CVE 2016-2109 fix am: 56abb3ed72 am: e0becbcb23 am: 5cfdab8c9d am: 61c19b30c3  -s ours am: 05b44fa879  -s ours am: 01ff070dc2  -s ours am: 3257cdbcc1  -s ours am: d732a2a9ad  -s ours
am: aa047e05e6  -s ours

Change-Id: I6aa8b341e177ce4d171ad0c7d1edd9f4659e61e9
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..65f95f0
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,232 @@
+// Note that some host libraries have the same module name as the target
+// libraries. This is currently needed to build, for example, adb. But it's
+// probably something that should be changed.
+
+// Pull in the autogenerated sources modules
+build = ["sources.bp"]
+
+// Used by libcrypto, libssl, bssl tool, and native tests
+cc_defaults {
+    name: "boringssl_flags",
+    vendor_available: true,
+
+    cflags: [
+        "-fvisibility=hidden",
+        "-DBORINGSSL_SHARED_LIBRARY",
+        "-DBORINGSSL_IMPLEMENTATION",
+        "-DOPENSSL_SMALL",
+        "-D_XOPEN_SOURCE=700",
+        "-Wno-unused-parameter",
+    ],
+
+    cppflags: [
+        "-Wall",
+        "-Werror",
+    ],
+
+    conlyflags: ["-std=c99"],
+}
+
+// Used by libcrypto + libssl
+cc_defaults {
+    name: "boringssl_defaults",
+
+    local_include_dirs: ["src/include"],
+    export_include_dirs: ["src/include"],
+    stl: "libc++_static",
+    sdk_version: "9",
+
+    cflags: ["-DBORINGSSL_ANDROID_SYSTEM"],
+}
+
+//// libcrypto
+
+// This should be removed when clang can compile everything.
+libcrypto_sources_no_clang = [
+    "linux-arm/crypto/aes/aes-armv4.S",
+    "linux-arm/crypto/aes/bsaes-armv7.S",
+]
+
+cc_defaults {
+    name: "libcrypto_defaults",
+    host_supported: true,
+
+    // Windows and Macs both have problems with assembly files
+    target: {
+        windows: {
+            enabled: true,
+            cflags: ["-DOPENSSL_NO_ASM"],
+            host_ldlibs: ["-lws2_32"],
+        },
+        darwin: {
+            cflags: ["-DOPENSSL_NO_ASM"],
+        },
+        host: {
+            host_ldlibs: ["-lpthread"],
+        },
+    },
+
+    local_include_dirs: ["src/crypto"],
+
+    arch: {
+        arm64: {
+            clang_asflags: ["-march=armv8-a+crypto"],
+        },
+    },
+
+    // This should be removed when clang can compile everything.
+    exclude_srcs: libcrypto_sources_no_clang,
+    whole_static_libs: ["libcrypto_no_clang"],
+}
+
+// Target and host library
+cc_library {
+    name: "libcrypto",
+    defaults: ["libcrypto_sources", "libcrypto_defaults", "boringssl_defaults", "boringssl_flags"],
+    unique_host_soname: true,
+}
+
+// Target and host library: files that don't compile with clang. This should
+// go away when clang can compile everything with integrated assembler.
+cc_library_static {
+    name: "libcrypto_no_clang",
+    defaults: ["boringssl_defaults", "boringssl_flags"],
+    host_supported: true,
+
+    target: {
+        windows: {
+            enabled: true,
+        },
+    },
+
+    local_include_dirs: ["src/crypto"],
+
+    arch: {
+        arm: {
+            clang_asflags: ["-no-integrated-as"],
+            srcs: libcrypto_sources_no_clang,
+        },
+    },
+}
+
+// Static library
+// This should only be used for host modules that will be in a JVM, all other
+// modules should use the static variant of libcrypto.
+cc_library_static {
+    name: "libcrypto_static",
+    defaults: ["libcrypto_sources", "libcrypto_defaults", "boringssl_defaults", "boringssl_flags"],
+
+    target: {
+        host: {
+            // TODO: b/26160319. ASAN breaks use of this library in JVM.
+            // Re-enable sanitization when the issue with making clients of this library
+            // preload ASAN runtime is resolved. Without that, clients are getting runtime
+            // errors due to unresolved ASAN symbols, such as
+            // __asan_option_detect_stack_use_after_return.
+            sanitize: {
+                never: true,
+            },
+        },
+    },
+}
+
+//// libssl
+
+// Target static library
+// Deprecated: all users should move to libssl
+cc_library_static {
+    name: "libssl_static",
+    defaults: ["libssl_sources", "boringssl_defaults", "boringssl_flags"],
+}
+
+// Static and Shared library
+cc_library {
+    name: "libssl",
+    host_supported: true,
+    defaults: ["libssl_sources", "boringssl_defaults", "boringssl_flags"],
+    unique_host_soname: true,
+
+    shared_libs: ["libcrypto"],
+}
+
+// Host static library
+cc_library_host_static {
+    name: "libssl_static-host",
+    defaults: ["libssl_sources", "boringssl_defaults", "boringssl_flags"],
+
+    // TODO: b/26160319. ASAN breaks use of this library in JVM.
+    // Re-enable sanitization when the issue with making clients of this library
+    // preload ASAN runtime is resolved. Without that, clients are getting runtime
+    // errors due to unresolved ASAN symbols, such as
+    // __asan_option_detect_stack_use_after_return.
+    sanitize: {
+        never: true,
+    },
+}
+
+// Tool
+cc_binary {
+    name: "bssl",
+    host_supported: true,
+    defaults: ["bssl_sources", "boringssl_flags"],
+
+    shared_libs: [
+        "libcrypto",
+        "libssl",
+    ],
+    target: {
+        host: {
+            // Needed for clock_gettime.
+            host_ldlibs: ["-lrt"],
+        },
+        darwin: {
+            enabled: false,
+        },
+    },
+}
+
+// Test support library
+cc_library_static {
+    name: "boringssl_test_support",
+    host_supported: true,
+    defaults: ["boringssl_test_support_sources", "boringssl_flags"],
+
+    shared_libs: [
+        "libcrypto",
+        "libssl",
+    ],
+}
+
+// Tests
+cc_test {
+    name: "boringssl_tests",
+    host_supported: true,
+    test_per_src: true,
+    defaults: ["boringssl_tests_sources", "boringssl_flags"],
+    whole_static_libs: ["boringssl_test_support"],
+
+    shared_libs: [
+        "libcrypto",
+        "libssl",
+    ],
+}
+
+cc_test {
+  name: "boringssl_crypto_test",
+  host_supported: true,
+  defaults: ["boringssl_crypto_test_sources", "boringssl_flags"],
+  whole_static_libs: ["boringssl_test_support"],
+
+  cflags: ["-DBORINGSSL_ANDROID_SYSTEM"],
+  shared_libs: ["libcrypto"],
+}
+
+cc_test {
+  name: "boringssl_ssl_test",
+  host_supported: true,
+  defaults: ["boringssl_ssl_test_sources", "boringssl_flags"],
+  whole_static_libs: ["boringssl_test_support"],
+
+  cflags: ["-DBORINGSSL_ANDROID_SYSTEM"],
+  shared_libs: ["libcrypto", "libssl"],
+}
diff --git a/Android.mk b/Android.mk
deleted file mode 100644
index 3e3ef2a..0000000
--- a/Android.mk
+++ /dev/null
@@ -1,159 +0,0 @@
-# Note that some host libraries have the same module name as the target
-# libraries. This is currently needed to build, for example, adb. But it's
-# probably something that should be changed.
-
-LOCAL_PATH := $(call my-dir)
-
-## libcrypto
-
-# Target static library
-include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE := libcrypto_static
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/src/include
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/crypto-sources.mk
-LOCAL_SDK_VERSION := 9
-LOCAL_CFLAGS += -fvisibility=hidden -DBORINGSSL_SHARED_LIBRARY -DBORINGSSL_IMPLEMENTATION -DOPENSSL_SMALL -Wno-unused-parameter
-# sha256-armv4.S does not compile with clang.
-LOCAL_CLANG_ASFLAGS_arm += -no-integrated-as
-LOCAL_CLANG_ASFLAGS_arm64 += -march=armv8-a+crypto
-include $(LOCAL_PATH)/crypto-sources.mk
-include $(BUILD_STATIC_LIBRARY)
-
-# Target shared library
-include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE := libcrypto
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/src/include
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/crypto-sources.mk
-LOCAL_CFLAGS += -fvisibility=hidden -DBORINGSSL_SHARED_LIBRARY -DBORINGSSL_IMPLEMENTATION -DOPENSSL_SMALL -Wno-unused-parameter
-LOCAL_SDK_VERSION := 9
-# sha256-armv4.S does not compile with clang.
-LOCAL_CLANG_ASFLAGS_arm += -no-integrated-as
-LOCAL_CLANG_ASFLAGS_arm64 += -march=armv8-a+crypto
-include $(LOCAL_PATH)/crypto-sources.mk
-include $(BUILD_SHARED_LIBRARY)
-
-# Target static tool
-include $(CLEAR_VARS)
-LOCAL_CFLAGS += -Wall -Werror -std=c++0x
-LOCAL_CPP_EXTENSION := cc
-LOCAL_MODULE := bssl
-LOCAL_MODULE_TAGS := optional
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/sources.mk
-LOCAL_CFLAGS += -fvisibility=hidden -DBORINGSSL_SHARED_LIBRARY -DBORINGSSL_IMPLEMENTATION -DOPENSSL_SMALL -Wno-unused-parameter
-LOCAL_SHARED_LIBRARIES=libcrypto libssl
-include $(LOCAL_PATH)/sources.mk
-LOCAL_SRC_FILES = $(tool_sources)
-include $(BUILD_EXECUTABLE)
-
-# Host static library
-include $(CLEAR_VARS)
-LOCAL_IS_HOST_MODULE := true
-LOCAL_MODULE := libcrypto_static
-LOCAL_MODULE_HOST_OS := darwin linux windows
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/src/include
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/crypto-sources.mk
-LOCAL_CFLAGS += -fvisibility=hidden -DBORINGSSL_SHARED_LIBRARY -DBORINGSSL_IMPLEMENTATION -DOPENSSL_SMALL -Wno-unused-parameter
-LOCAL_CXX_STL := none
-# Windows and Macs both have problems with assembly files
-LOCAL_CFLAGS_darwin += -DOPENSSL_NO_ASM
-LOCAL_CFLAGS_windows += -DOPENSSL_NO_ASM
-# TODO: b/26097626. ASAN breaks use of this library in JVM.
-# Re-enable sanitization when the issue with making clients of this library
-# preload ASAN runtime is resolved. Without that, clients are getting runtime
-# errors due to unresoled ASAN symbols, such as
-# __asan_option_detect_stack_use_after_return.
-LOCAL_SANITIZE := never
-include $(LOCAL_PATH)/crypto-sources.mk
-include $(BUILD_HOST_STATIC_LIBRARY)
-
-# Host shared library
-include $(CLEAR_VARS)
-LOCAL_IS_HOST_MODULE := true
-LOCAL_MODULE := libcrypto-host
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_MULTILIB := both
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/crypto-sources.mk
-LOCAL_CFLAGS += -fvisibility=hidden -DBORINGSSL_SHARED_LIBRARY -DBORINGSSL_IMPLEMENTATION -DOPENSSL_SMALL -Wno-unused-parameter
-# Windows and Macs both have problems with assembly files
-LOCAL_CFLAGS_darwin += -DOPENSSL_NO_ASM
-LOCAL_CFLAGS_windows += -DOPENSSL_NO_ASM
-LOCAL_LDLIBS_darwin := -lpthread
-LOCAL_LDLIBS_linux := -lpthread
-LOCAL_CXX_STL := none
-include $(LOCAL_PATH)/crypto-sources.mk
-include $(BUILD_HOST_SHARED_LIBRARY)
-
-
-## libssl
-
-# Target static library
-include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE := libssl_static
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/src/include
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/ssl-sources.mk
-LOCAL_SDK_VERSION := 9
-LOCAL_CFLAGS += -fvisibility=hidden -DBORINGSSL_SHARED_LIBRARY -DBORINGSSL_IMPLEMENTATION -DOPENSSL_SMALL -Wno-unused-parameter
-include $(LOCAL_PATH)/ssl-sources.mk
-include $(BUILD_STATIC_LIBRARY)
-
-# Target shared library
-include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE := libssl
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/src/include
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/ssl-sources.mk
-LOCAL_CFLAGS += -fvisibility=hidden -DBORINGSSL_SHARED_LIBRARY -DBORINGSSL_IMPLEMENTATION -DOPENSSL_SMALL -Wno-unused-parameter
-LOCAL_SHARED_LIBRARIES=libcrypto
-LOCAL_SDK_VERSION := 9
-include $(LOCAL_PATH)/ssl-sources.mk
-include $(BUILD_SHARED_LIBRARY)
-
-# Host static library
-include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE := libssl_static-host
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/src/include
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/ssl-sources.mk
-LOCAL_CFLAGS += -fvisibility=hidden -DBORINGSSL_SHARED_LIBRARY -DBORINGSSL_IMPLEMENTATION -DOPENSSL_SMALL -Wno-unused-parameter
-LOCAL_CXX_STL := none
-# TODO: b/26097626. ASAN breaks use of this library in JVM.
-# Re-enable sanitization when the issue with making clients of this library
-# preload ASAN runtime is resolved. Without that, clients are getting runtime
-# errors due to unresoled ASAN symbols, such as
-# __asan_option_detect_stack_use_after_return.
-LOCAL_SANITIZE := never
-include $(LOCAL_PATH)/ssl-sources.mk
-include $(BUILD_HOST_STATIC_LIBRARY)
-
-# Host static tool (for linux only).
-ifeq ($(HOST_OS), linux)
-include $(CLEAR_VARS)
-LOCAL_CFLAGS += -Wall -Werror -std=c++0x
-LOCAL_CPP_EXTENSION := cc
-LOCAL_MODULE := bssl
-LOCAL_MODULE_TAGS := optional
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/sources.mk
-LOCAL_CFLAGS += -fvisibility=hidden -DBORINGSSL_SHARED_LIBRARY -DBORINGSSL_IMPLEMENTATION -DOPENSSL_SMALL -Wno-unused-parameter
-LOCAL_SHARED_LIBRARIES=libcrypto-host libssl-host
-# Needed for clock_gettime.
-LOCAL_LDFLAGS := -lrt
-include $(LOCAL_PATH)/sources.mk
-LOCAL_SRC_FILES = $(tool_sources)
-include $(BUILD_HOST_EXECUTABLE)
-endif  # HOST_OS == linux
-
-# Host shared library
-include $(CLEAR_VARS)
-LOCAL_MODULE_TAGS := optional
-LOCAL_MODULE := libssl-host
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/src/include
-LOCAL_MULTILIB := both
-LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/ssl-sources.mk
-LOCAL_CFLAGS += -fvisibility=hidden -DBORINGSSL_SHARED_LIBRARY -DBORINGSSL_IMPLEMENTATION -DOPENSSL_SMALL -Wno-unused-parameter
-LOCAL_CXX_STL := none
-LOCAL_SHARED_LIBRARIES += libcrypto-host
-include $(LOCAL_PATH)/ssl-sources.mk
-include $(BUILD_HOST_SHARED_LIBRARY)
diff --git a/BORINGSSL_REVISION b/BORINGSSL_REVISION
index 6e9fe82..4d70d6c 100644
--- a/BORINGSSL_REVISION
+++ b/BORINGSSL_REVISION
@@ -1 +1 @@
-7b8b9c17db93ea5287575b437c77fb36eeb81b31
+bbfe603519bc54fbc4c8dd87efe1ed385df550b4
diff --git a/UPDATING b/UPDATING
old mode 100644
new mode 100755
index c7019e4..9703932
--- a/UPDATING
+++ b/UPDATING
@@ -1,9 +1,25 @@
+#!/bin/sh
+
+set -xe
+
+old_revision=$(cat BORINGSSL_REVISION)
 rm -Rf src
 git clone https://boringssl.googlesource.com/boringssl src
 cd src
-git show -s --pretty=%H > ../BORINGSSL_REVISION
+new_revision=$(git show -s --pretty=%H)
 cd ..
+echo ${new_revision} > BORINGSSL_REVISION
+
 rm -Rf src/.git
 rm -Rf src/fuzz
+rm -Rf src/third_party/googletest
 rm -Rf linux-aarch64/ linux-arm/ linux-x86/ linux-x86_64/ mac-x86/ mac-x86_64/ win-x86_64/ win-x86/
 python src/util/generate_build_files.py android
+
+git add .
+git commit -m "external/boringssl: Sync to ${new_revision}.
+
+This includes the following changes:
+
+https://boringssl.googlesource.com/boringssl/+log/${old_revision}..${new_revision}
+"
diff --git a/android_compat_hacks.c b/android_compat_hacks.c
deleted file mode 100644
index cf4863d..0000000
--- a/android_compat_hacks.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/* Copyright (c) 2014, Google Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
-
-/* This file contains odd functions that are needed, temporarily, on Android
- * because wpa_supplicant will take a little while to sync with upstream.
- *
- * The declarations for these functions are in the main BoringSSL headers but
- * the only definitions are here, in Android land. */
-
-#include <openssl/base.h>
-
-#include <assert.h>
-
-#include <openssl/bn.h>
-#include <openssl/cipher.h>
-#include <openssl/err.h>
-#include <openssl/ssl.h>
-
-
-BIGNUM *get_rfc3526_prime_1536(BIGNUM *bn) {
-  assert(bn == NULL);
-
-  static const uint8_t data[] = {
-      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
-      0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
-      0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
-      0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
-      0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
-      0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
-      0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
-      0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
-      0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
-      0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
-      0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
-      0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
-      0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
-      0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
-      0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
-      0xCA, 0x23, 0x73, 0x27, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-  };
-
-  return BN_bin2bn(data, sizeof(data), NULL);
-}
-
-int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len) {
-  return 0;
-}
-
-int SSL_set_session_ticket_ext_cb(SSL *s, void *cb, void *arg) {
-  return 0;
-}
-
-int SSL_set_session_secret_cb(SSL *s, void *cb, void *arg) {
-  return 0;
-}
-
-int SSL_set_ssl_method(SSL *s, const SSL_METHOD *method) {
-  /* This is only called when EAP-FAST is being used, which is not supported. */
-  abort();
-}
diff --git a/android_compat_keywrap.c b/android_compat_keywrap.c
deleted file mode 100644
index 9ffe17d..0000000
--- a/android_compat_keywrap.c
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project.
- */
-/* ====================================================================
- * Copyright (c) 2008 The OpenSSL Project.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- *    software must display the following acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- *    endorse or promote products derived from this software without
- *    prior written permission. For written permission, please contact
- *    licensing@OpenSSL.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- *    nor may "OpenSSL" appear in their names without prior written
- *    permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- *    acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- */
-
-#include <openssl/aes.h>
-#include <openssl/mem.h>
-
-#include <string.h>
-#include <stdlib.h>
-
-static const uint8_t default_iv[] = {
-    0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6,
-};
-
-int AES_wrap_key(AES_KEY *key, const uint8_t *iv, uint8_t *out,
-                 const uint8_t *in, unsigned int inlen) {
-  uint8_t *A, B[16], *R;
-  unsigned int i, j, t;
-  if ((inlen & 0x7) || (inlen < 8)) return -1;
-  A = B;
-  t = 1;
-  memcpy(out + 8, in, inlen);
-  if (!iv) iv = default_iv;
-
-  memcpy(A, iv, 8);
-
-  for (j = 0; j < 6; j++) {
-    R = out + 8;
-    for (i = 0; i < inlen; i += 8, t++, R += 8) {
-      memcpy(B + 8, R, 8);
-      AES_encrypt(B, B, key);
-      A[7] ^= (uint8_t)(t & 0xff);
-      if (t > 0xff) {
-        A[6] ^= (uint8_t)((t >> 8) & 0xff);
-        A[5] ^= (uint8_t)((t >> 16) & 0xff);
-        A[4] ^= (uint8_t)((t >> 24) & 0xff);
-      }
-      memcpy(R, B + 8, 8);
-    }
-  }
-  memcpy(out, A, 8);
-  return inlen + 8;
-}
-
-int AES_unwrap_key(AES_KEY *key, const uint8_t *iv, uint8_t *out,
-                   const uint8_t *in, unsigned int inlen) {
-  uint8_t *A, B[16], *R;
-  unsigned int i, j, t;
-  inlen -= 8;
-  if (inlen & 0x7) return -1;
-  if (inlen < 8) return -1;
-  A = B;
-  t = 6 * (inlen >> 3);
-  memcpy(A, in, 8);
-  memcpy(out, in + 8, inlen);
-  for (j = 0; j < 6; j++) {
-    R = out + inlen - 8;
-    for (i = 0; i < inlen; i += 8, t--, R -= 8) {
-      A[7] ^= (uint8_t)(t & 0xff);
-      if (t > 0xff) {
-        A[6] ^= (uint8_t)((t >> 8) & 0xff);
-        A[5] ^= (uint8_t)((t >> 16) & 0xff);
-        A[4] ^= (uint8_t)((t >> 24) & 0xff);
-      }
-      memcpy(B + 8, R, 8);
-      AES_decrypt(B, B, key);
-      memcpy(R, B + 8, 8);
-    }
-  }
-  if (!iv) iv = default_iv;
-  if (memcmp(A, iv, 8)) {
-    OPENSSL_cleanse(out, inlen);
-    return 0;
-  }
-  return inlen;
-}
diff --git a/arm_arch.h b/arm_arch.h
deleted file mode 120000
index 3958887..0000000
--- a/arm_arch.h
+++ /dev/null
@@ -1 +0,0 @@
-src/crypto/arm_arch.h
\ No newline at end of file
diff --git a/crypto-sources.mk b/crypto-sources.mk
index a5b8ba3..31c163f 100644
--- a/crypto-sources.mk
+++ b/crypto-sources.mk
@@ -1,16 +1,12 @@
+# Now used only by Trusty
 LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/sources.mk
 include $(LOCAL_PATH)/sources.mk
 
 LOCAL_CFLAGS += -I$(LOCAL_PATH)/src/include -I$(LOCAL_PATH)/src/crypto -Wno-unused-parameter -DBORINGSSL_ANDROID_SYSTEM
 LOCAL_ASFLAGS += -I$(LOCAL_PATH)/src/include -I$(LOCAL_PATH)/src/crypto -Wno-unused-parameter
 # Do not add in the architecture-specific files if we don't want to build assembly
-ifeq ($(LOCAL_IS_HOST_MODULE),true)
-LOCAL_SRC_FILES_linux_x86 := $(linux_x86_sources)
-LOCAL_SRC_FILES_linux_x86_64 := $(linux_x86_64_sources)
-else
 LOCAL_SRC_FILES_x86 := $(linux_x86_sources)
 LOCAL_SRC_FILES_x86_64 := $(linux_x86_64_sources)
 LOCAL_SRC_FILES_arm := $(linux_arm_sources)
 LOCAL_SRC_FILES_arm64 := $(linux_aarch64_sources)
-endif
 LOCAL_SRC_FILES += $(crypto_sources)
diff --git a/err_data.c b/err_data.c
index fe7979b..ea6dd73 100644
--- a/err_data.c
+++ b/err_data.c
@@ -54,178 +54,166 @@
 OPENSSL_COMPILE_ASSERT(ERR_NUM_LIBS == 33, library_values_changed_num);
 
 const uint32_t kOpenSSLReasonValues[] = {
-    0xc3207ab,
-    0xc3287c5,
-    0xc3307d4,
-    0xc3387e4,
-    0xc3407f3,
-    0xc34880c,
-    0xc350818,
-    0xc358835,
-    0xc360847,
-    0xc368855,
-    0xc370865,
-    0xc378872,
-    0xc380882,
-    0xc38888d,
-    0xc3908a3,
-    0xc3988b2,
-    0xc3a08c6,
-    0xc3a87b8,
-    0xc3b00b0,
-    0x10321469,
-    0x10329475,
-    0x1033148e,
-    0x103394a1,
-    0x10340dd2,
-    0x103494c0,
-    0x103514d5,
-    0x10359507,
-    0x10361520,
-    0x10369535,
-    0x10371553,
-    0x10379562,
-    0x1038157e,
-    0x10389599,
-    0x103915a8,
-    0x103995c4,
-    0x103a15df,
-    0x103a95f6,
-    0x103b1607,
-    0x103b961b,
-    0x103c163a,
-    0x103c9649,
-    0x103d1660,
-    0x103d9673,
-    0x103e0b5d,
-    0x103e96a4,
-    0x103f16b7,
-    0x103f96d1,
-    0x104016e1,
-    0x104096f5,
-    0x1041170b,
-    0x10419723,
-    0x10421738,
-    0x1042974c,
-    0x1043175e,
-    0x104385c1,
-    0x104408b2,
-    0x10449773,
-    0x1045178a,
-    0x1045979f,
-    0x104617ad,
-    0x10469686,
-    0x104714e8,
-    0x104787b8,
-    0x104800b0,
-    0x104894b4,
-    0x14320b40,
-    0x14328b4e,
-    0x14330b5d,
-    0x14338b6f,
+    0xc320838,
+    0xc328852,
+    0xc330861,
+    0xc338871,
+    0xc340880,
+    0xc348899,
+    0xc3508a5,
+    0xc3588c2,
+    0xc3608d4,
+    0xc3688e2,
+    0xc3708f2,
+    0xc3788ff,
+    0xc38090f,
+    0xc38891a,
+    0xc390930,
+    0xc39893f,
+    0xc3a0953,
+    0xc3a8845,
+    0xc3b00ea,
+    0x10320845,
+    0x1032943b,
+    0x10331447,
+    0x10339460,
+    0x10341473,
+    0x10348eb4,
+    0x10350c42,
+    0x10359486,
+    0x1036149b,
+    0x103694ae,
+    0x103714cd,
+    0x103794e6,
+    0x103814fb,
+    0x10389519,
+    0x10391528,
+    0x10399544,
+    0x103a155f,
+    0x103a956e,
+    0x103b158a,
+    0x103b95a5,
+    0x103c15bc,
+    0x103c80ea,
+    0x103d15cd,
+    0x103d95e1,
+    0x103e1600,
+    0x103e960f,
+    0x103f1626,
+    0x103f9639,
+    0x10400c06,
+    0x1040964c,
+    0x1041166a,
+    0x1041967d,
+    0x10421697,
+    0x104296a7,
+    0x104316bb,
+    0x104396d1,
+    0x104416e9,
+    0x104496fe,
+    0x10451712,
+    0x10459724,
+    0x104605fb,
+    0x1046893f,
+    0x10471739,
+    0x10479750,
+    0x10481765,
+    0x10489773,
+    0x14320be9,
+    0x14328bf7,
+    0x14330c06,
+    0x14338c18,
+    0x143400ac,
+    0x143480ea,
     0x18320083,
-    0x18328e38,
-    0x18340e66,
-    0x18348e7a,
-    0x18358eb1,
-    0x18368ede,
-    0x18370ef1,
-    0x18378f05,
-    0x18380f29,
-    0x18388f37,
-    0x18390f4d,
-    0x18398f61,
-    0x183a0f71,
-    0x183b0f81,
-    0x183b8f96,
-    0x183c8fc1,
-    0x183d0fd5,
-    0x183d8fe5,
-    0x183e0b8c,
-    0x183e8ff2,
-    0x183f1004,
-    0x183f900f,
-    0x1840101f,
-    0x18409030,
-    0x18411041,
-    0x18419053,
-    0x1842107c,
-    0x184290ae,
-    0x184310bd,
-    0x18451126,
-    0x1845913c,
-    0x18461157,
-    0x18468ec9,
-    0x184709ca,
-    0x18478094,
-    0x18480fad,
-    0x184890f2,
-    0x18490e4e,
-    0x18498e8f,
-    0x184a118d,
-    0x184a910a,
-    0x184b10d1,
-    0x184b8e28,
-    0x184c1095,
-    0x184c865c,
-    0x184d1172,
-    0x203211b4,
-    0x243211c0,
-    0x243288f8,
-    0x243311d2,
-    0x243391df,
-    0x243411ec,
-    0x243491fe,
-    0x2435120d,
-    0x2435922a,
-    0x24361237,
-    0x24369245,
-    0x24371253,
-    0x24379261,
-    0x2438126a,
-    0x24389277,
-    0x2439128a,
-    0x28320b80,
-    0x28328b8c,
-    0x28330b5d,
-    0x28338b9f,
-    0x2c32280e,
-    0x2c32a81c,
-    0x2c33282e,
-    0x2c33a840,
-    0x2c342854,
-    0x2c34a866,
-    0x2c352881,
-    0x2c35a893,
-    0x2c3628a6,
-    0x2c3682f3,
-    0x2c3728b3,
-    0x2c37a8c5,
-    0x2c3828d8,
-    0x2c38a8e6,
-    0x2c3928f6,
-    0x2c39a908,
-    0x2c3a291c,
-    0x2c3aa92d,
-    0x2c3b134a,
-    0x2c3ba93e,
-    0x2c3c2952,
-    0x2c3ca968,
-    0x2c3d2981,
-    0x2c3da9af,
-    0x2c3e29bd,
-    0x2c3ea9d5,
-    0x2c3f29ed,
-    0x2c3fa9fa,
-    0x2c402a1d,
-    0x2c40aa3c,
-    0x2c4111b4,
-    0x2c41aa4d,
-    0x2c422a60,
-    0x2c429126,
-    0x2c432a71,
-    0x2c438693,
-    0x2c44299e,
+    0x18328f0a,
+    0x183300ac,
+    0x18338f20,
+    0x18340f34,
+    0x183480ea,
+    0x18350f49,
+    0x18358f61,
+    0x18360f76,
+    0x18368f8a,
+    0x18370fae,
+    0x18378fc4,
+    0x18380fd8,
+    0x18388fe8,
+    0x18390a57,
+    0x18398ff8,
+    0x183a100d,
+    0x183a9021,
+    0x183b0c4e,
+    0x183b902e,
+    0x183c1040,
+    0x183c904b,
+    0x183d105b,
+    0x183d906c,
+    0x183e107d,
+    0x183e908f,
+    0x183f10b8,
+    0x183f90d1,
+    0x184010e9,
+    0x184086d3,
+    0x20321110,
+    0x2432111c,
+    0x24328985,
+    0x2433112e,
+    0x2433913b,
+    0x24341148,
+    0x2434915a,
+    0x24351169,
+    0x24359186,
+    0x24361193,
+    0x243691a1,
+    0x243711af,
+    0x243791bd,
+    0x243811c6,
+    0x243891d3,
+    0x243911e6,
+    0x28320c36,
+    0x28328c4e,
+    0x28330c06,
+    0x28338c61,
+    0x28340c42,
+    0x283480ac,
+    0x283500ea,
+    0x2c322af1,
+    0x2c32aaff,
+    0x2c332b11,
+    0x2c33ab23,
+    0x2c342b37,
+    0x2c34ab49,
+    0x2c352b64,
+    0x2c35ab76,
+    0x2c362b89,
+    0x2c36832d,
+    0x2c372b96,
+    0x2c37aba8,
+    0x2c382bbb,
+    0x2c38abd2,
+    0x2c392be0,
+    0x2c39abf0,
+    0x2c3a2c02,
+    0x2c3aac16,
+    0x2c3b2c27,
+    0x2c3bac46,
+    0x2c3c2c5a,
+    0x2c3cac70,
+    0x2c3d2c89,
+    0x2c3daca6,
+    0x2c3e2cb7,
+    0x2c3eacc5,
+    0x2c3f2cdd,
+    0x2c3facf5,
+    0x2c402d02,
+    0x2c409110,
+    0x2c412d13,
+    0x2c41ad26,
+    0x2c4210e9,
+    0x2c42ad37,
+    0x2c430720,
+    0x2c43ac38,
     0x30320000,
     0x30328015,
     0x3033001f,
@@ -235,440 +223,489 @@
     0x3035006b,
     0x30358083,
     0x30360094,
-    0x303680a1,
-    0x303700b0,
-    0x303780bd,
-    0x303800d0,
-    0x303880eb,
-    0x30390100,
-    0x30398114,
-    0x303a0128,
-    0x303a8139,
-    0x303b0152,
-    0x303b816f,
-    0x303c017d,
-    0x303c8191,
-    0x303d01a1,
-    0x303d81ba,
-    0x303e01ca,
-    0x303e81dd,
-    0x303f01ec,
-    0x303f81f8,
-    0x3040020d,
-    0x3040821d,
-    0x30410234,
-    0x30418241,
-    0x30420254,
-    0x30428263,
-    0x30430278,
-    0x30438299,
-    0x304402ac,
-    0x304482bf,
-    0x304502d8,
-    0x304582f3,
-    0x30460310,
-    0x30468329,
-    0x30470337,
-    0x30478348,
-    0x30480357,
-    0x3048836f,
-    0x30490381,
-    0x30498395,
-    0x304a03b4,
-    0x304a83c7,
-    0x304b03d2,
-    0x304b83e3,
-    0x304c03ef,
-    0x304c8405,
-    0x304d0413,
-    0x304d8429,
-    0x304e043b,
-    0x304e844d,
-    0x304f0460,
-    0x304f8473,
-    0x30500484,
-    0x30508494,
-    0x305104ac,
-    0x305184c1,
-    0x305204d9,
-    0x305284ed,
-    0x30530505,
-    0x3053851e,
-    0x30540537,
-    0x30548554,
-    0x3055055f,
-    0x30558577,
-    0x30560587,
-    0x30568598,
-    0x305705ab,
-    0x305785c1,
-    0x305805ca,
-    0x305885df,
-    0x305905f2,
-    0x30598601,
-    0x305a0621,
-    0x305a8630,
-    0x305b063c,
-    0x305b865c,
-    0x305c0678,
-    0x305c8689,
-    0x305d0693,
-    0x34320aba,
-    0x34328ace,
-    0x34330aeb,
-    0x34338afe,
-    0x34340b0d,
-    0x34348b2a,
+    0x303680ac,
+    0x303700b9,
+    0x303780c8,
+    0x303800ea,
+    0x303880f7,
+    0x3039010a,
+    0x30398125,
+    0x303a013a,
+    0x303a814e,
+    0x303b0162,
+    0x303b8173,
+    0x303c018c,
+    0x303c81a9,
+    0x303d01b7,
+    0x303d81cb,
+    0x303e01db,
+    0x303e81f4,
+    0x303f0204,
+    0x303f8217,
+    0x30400226,
+    0x30408232,
+    0x30410247,
+    0x30418257,
+    0x3042026e,
+    0x3042827b,
+    0x3043028e,
+    0x3043829d,
+    0x304402b2,
+    0x304482d3,
+    0x304502e6,
+    0x304582f9,
+    0x30460312,
+    0x3046832d,
+    0x3047034a,
+    0x30478363,
+    0x30480371,
+    0x30488382,
+    0x30490391,
+    0x304983a9,
+    0x304a03bb,
+    0x304a83cf,
+    0x304b03ee,
+    0x304b8401,
+    0x304c040c,
+    0x304c841d,
+    0x304d0429,
+    0x304d843f,
+    0x304e044d,
+    0x304e8463,
+    0x304f0475,
+    0x304f8487,
+    0x3050049a,
+    0x305084ad,
+    0x305104be,
+    0x305184ce,
+    0x305204e6,
+    0x305284fb,
+    0x30530513,
+    0x30538527,
+    0x3054053f,
+    0x30548558,
+    0x30550571,
+    0x3055858e,
+    0x30560599,
+    0x305685b1,
+    0x305705c1,
+    0x305785d2,
+    0x305805e5,
+    0x305885fb,
+    0x30590604,
+    0x30598619,
+    0x305a062c,
+    0x305a863b,
+    0x305b065b,
+    0x305b866a,
+    0x305c068b,
+    0x305c86a7,
+    0x305d06b3,
+    0x305d86d3,
+    0x305e06ef,
+    0x305e8700,
+    0x305f0716,
+    0x305f8720,
+    0x34320b47,
+    0x34328b5b,
+    0x34330b78,
+    0x34338b8b,
+    0x34340b9a,
+    0x34348bd3,
+    0x34350bb7,
     0x3c320083,
-    0x3c328bc9,
-    0x3c330be2,
-    0x3c338bfd,
-    0x3c340c1a,
-    0x3c348c35,
-    0x3c350c50,
-    0x3c358c65,
-    0x3c360c7e,
-    0x3c368c96,
-    0x3c370ca7,
-    0x3c378cb5,
-    0x3c380cc2,
-    0x3c388cd6,
-    0x3c390b8c,
-    0x3c398cea,
-    0x3c3a0cfe,
-    0x3c3a8872,
-    0x3c3b0d0e,
-    0x3c3b8d29,
-    0x3c3c0d3b,
-    0x3c3c8d51,
-    0x3c3d0d5b,
-    0x3c3d8d6f,
-    0x3c3e0d7d,
-    0x3c3e8da2,
-    0x3c3f0bb5,
-    0x3c3f8d8b,
-    0x403217c4,
-    0x403297da,
-    0x40331808,
-    0x40339812,
-    0x40341829,
-    0x40349847,
-    0x40351857,
-    0x40359869,
-    0x40361876,
-    0x40369882,
-    0x40371897,
-    0x403798a9,
-    0x403818b4,
-    0x403898c6,
-    0x40390dd2,
-    0x403998d6,
-    0x403a18e9,
-    0x403a990a,
-    0x403b191b,
-    0x403b992b,
+    0x3c328c8b,
+    0x3c330ca4,
+    0x3c338cbf,
+    0x3c340cdc,
+    0x3c348d06,
+    0x3c350d21,
+    0x3c358d47,
+    0x3c360d60,
+    0x3c368d78,
+    0x3c370d89,
+    0x3c378d97,
+    0x3c380da4,
+    0x3c388db8,
+    0x3c390c4e,
+    0x3c398dcc,
+    0x3c3a0de0,
+    0x3c3a88ff,
+    0x3c3b0df0,
+    0x3c3b8e0b,
+    0x3c3c0e1d,
+    0x3c3c8e33,
+    0x3c3d0e3d,
+    0x3c3d8e51,
+    0x3c3e0e5f,
+    0x3c3e8e84,
+    0x3c3f0c77,
+    0x3c3f8e6d,
+    0x3c4000ac,
+    0x3c4080ea,
+    0x3c410cf7,
+    0x3c418d36,
+    0x403217a6,
+    0x403297bc,
+    0x403317ea,
+    0x403397f4,
+    0x4034180b,
+    0x40349829,
+    0x40351839,
+    0x4035984b,
+    0x40361858,
+    0x40369864,
+    0x40371879,
+    0x4037988b,
+    0x40381896,
+    0x403898a8,
+    0x40390eb4,
+    0x403998b8,
+    0x403a18cb,
+    0x403a98ec,
+    0x403b18fd,
+    0x403b990d,
     0x403c0064,
     0x403c8083,
-    0x403d1937,
-    0x403d994d,
-    0x403e195c,
-    0x403e996f,
-    0x403f1989,
-    0x403f9997,
-    0x404019ac,
-    0x404099c0,
-    0x404119dd,
-    0x404199f8,
-    0x40421a11,
-    0x40429a24,
-    0x40431a38,
-    0x40439a50,
-    0x40441a67,
-    0x40448094,
-    0x40451a7c,
-    0x40459a8e,
-    0x40461ab2,
-    0x40469ad2,
-    0x40471ae0,
-    0x40479af4,
-    0x40481b09,
-    0x40489b22,
-    0x40491b39,
-    0x40499b53,
-    0x404a1b6a,
-    0x404a9b88,
-    0x404b1ba0,
-    0x404b9bb7,
-    0x404c1bcd,
-    0x404c9bdf,
-    0x404d1c00,
-    0x404d9c22,
-    0x404e1c36,
-    0x404e9c43,
-    0x404f1c5a,
-    0x404f9c6a,
-    0x40501c7a,
-    0x40509c8e,
-    0x40511ca9,
-    0x40519cb9,
-    0x40521cd0,
-    0x40529ce2,
-    0x40531cfa,
-    0x40539d0d,
-    0x40541d22,
-    0x40549d45,
-    0x40551d53,
-    0x40559d70,
-    0x40561d7d,
-    0x40569d96,
-    0x40571dae,
-    0x40579dc1,
-    0x40581dd6,
-    0x40589de8,
-    0x40591df8,
-    0x40599e11,
-    0x405a1e25,
-    0x405a9e35,
-    0x405b1e4d,
-    0x405b9e5e,
-    0x405c1e71,
-    0x405c9e82,
-    0x405d1e8f,
-    0x405d9ea6,
-    0x405e1ec6,
-    0x405e8a08,
-    0x405f1ee7,
-    0x405f9ef4,
-    0x40601f02,
-    0x40609f24,
-    0x40611f4c,
-    0x40619f61,
-    0x40621f78,
-    0x40629f89,
-    0x40631f9a,
-    0x40639faf,
-    0x40641fc6,
-    0x40649fd7,
-    0x40651ff2,
-    0x4065a009,
-    0x40662021,
-    0x4066a04b,
-    0x40672076,
-    0x4067a097,
-    0x406820aa,
-    0x4068a0cb,
-    0x406920e6,
-    0x4069a114,
-    0x406a2135,
-    0x406aa155,
-    0x406b22dd,
-    0x406ba300,
-    0x406c2316,
-    0x406ca542,
-    0x406d2571,
-    0x406da599,
-    0x406e25b2,
-    0x406ea5ca,
-    0x406f25e9,
-    0x406fa5fe,
-    0x40702611,
-    0x4070a62e,
-    0x40710773,
-    0x4071a640,
-    0x40722653,
-    0x4072a66c,
-    0x40732684,
-    0x407390ae,
-    0x40742698,
-    0x4074a6b2,
-    0x407526c3,
-    0x4075a6d7,
-    0x407626e5,
-    0x40769277,
-    0x4077270a,
-    0x4077a72c,
-    0x40782747,
-    0x4078a75c,
-    0x40792773,
-    0x4079a789,
-    0x407a2795,
-    0x407aa7a8,
-    0x407b27bd,
-    0x407ba7cf,
-    0x407c27e4,
-    0x407ca7ed,
-    0x41f42208,
-    0x41f9229a,
-    0x41fe218d,
-    0x41fea369,
-    0x41ff245a,
-    0x42032221,
-    0x42082243,
-    0x4208a27f,
-    0x42092171,
-    0x4209a2b9,
-    0x420a21c8,
-    0x420aa1a8,
-    0x420b21e8,
-    0x420ba261,
-    0x420c2476,
-    0x420ca336,
-    0x420d2350,
-    0x420da387,
-    0x421223a1,
-    0x4217243d,
-    0x4217a3e3,
-    0x421c2405,
-    0x421f23c0,
-    0x4221248d,
-    0x42262420,
-    0x422b2526,
-    0x422ba4ef,
-    0x422c250e,
-    0x422ca4c9,
-    0x422d24a8,
-    0x4432069e,
-    0x443286ad,
-    0x443306b9,
-    0x443386c7,
-    0x443406da,
-    0x443486eb,
-    0x443506f2,
-    0x443586fc,
-    0x4436070f,
-    0x44368725,
-    0x44370737,
-    0x44378744,
-    0x44380753,
-    0x4438875b,
-    0x44390773,
-    0x44398781,
-    0x443a0794,
-    0x4c3212a1,
-    0x4c3292b1,
-    0x4c3312c4,
-    0x4c3392e4,
-    0x4c340094,
-    0x4c3480b0,
-    0x4c3512f0,
-    0x4c3592fe,
-    0x4c36131a,
-    0x4c36932d,
-    0x4c37133c,
-    0x4c37934a,
-    0x4c38135f,
-    0x4c38936b,
-    0x4c39138b,
-    0x4c3993b5,
-    0x4c3a13ce,
-    0x4c3a93e7,
-    0x4c3b05c1,
-    0x4c3b9400,
-    0x4c3c1412,
-    0x4c3c9421,
-    0x4c3d10ae,
-    0x4c3d943a,
-    0x4c3e1447,
-    0x50322a83,
-    0x5032aa92,
-    0x50332a9d,
-    0x5033aaad,
-    0x50342ac6,
-    0x5034aae0,
-    0x50352aee,
-    0x5035ab04,
-    0x50362b16,
-    0x5036ab2c,
-    0x50372b45,
-    0x5037ab58,
-    0x50382b70,
-    0x5038ab81,
-    0x50392b96,
-    0x5039abaa,
-    0x503a2bca,
-    0x503aabe0,
-    0x503b2bf8,
-    0x503bac0a,
-    0x503c2c26,
-    0x503cac3d,
-    0x503d2c56,
-    0x503dac6c,
-    0x503e2c79,
-    0x503eac8f,
-    0x503f2ca1,
-    0x503f8348,
-    0x50402cb4,
-    0x5040acc4,
-    0x50412cde,
-    0x5041aced,
-    0x50422d07,
-    0x5042ad24,
-    0x50432d34,
-    0x5043ad44,
-    0x50442d53,
-    0x50448405,
-    0x50452d67,
-    0x5045ad85,
-    0x50462d98,
-    0x5046adae,
-    0x50472dc0,
-    0x5047add5,
-    0x50482dfb,
-    0x5048ae09,
-    0x50492e1c,
-    0x5049ae31,
-    0x504a2e47,
-    0x504aae57,
-    0x504b2e77,
-    0x504bae8a,
-    0x504c2ead,
-    0x504caedb,
-    0x504d2eed,
-    0x504daf0a,
-    0x504e2f25,
-    0x504eaf41,
-    0x504f2f53,
-    0x504faf6a,
-    0x50502f79,
-    0x50508678,
-    0x50512f8c,
-    0x58320e10,
-    0x68320dd2,
-    0x68328b8c,
-    0x68330b9f,
-    0x68338de0,
-    0x68340df0,
-    0x683480b0,
-    0x6c320dae,
-    0x6c328b6f,
-    0x6c330db9,
-    0x7432097e,
-    0x783208e3,
-    0x783288f8,
-    0x78330904,
+    0x403d1991,
+    0x403d99a7,
+    0x403e19b6,
+    0x403e99ee,
+    0x403f1a08,
+    0x403f9a16,
+    0x40401a2b,
+    0x40409a58,
+    0x40411a75,
+    0x40419a90,
+    0x40421aa9,
+    0x40429abc,
+    0x40431ad0,
+    0x40439ae8,
+    0x40441aff,
+    0x404480ac,
+    0x40451b14,
+    0x40459b26,
+    0x40461b4a,
+    0x40469b6a,
+    0x40471b78,
+    0x40479b9f,
+    0x40481bdc,
+    0x40489bf5,
+    0x40491c0c,
+    0x40499c26,
+    0x404a1c3d,
+    0x404a9c5b,
+    0x404b1c73,
+    0x404b9c8a,
+    0x404c1ca0,
+    0x404c9cb2,
+    0x404d1cd3,
+    0x404d9cf5,
+    0x404e1d09,
+    0x404e9d16,
+    0x404f1d43,
+    0x404f9d6c,
+    0x40501da7,
+    0x40509dbb,
+    0x40511dd6,
+    0x40521de6,
+    0x40529e0a,
+    0x40531e22,
+    0x40539e35,
+    0x40541e4a,
+    0x40549e6d,
+    0x40551e7b,
+    0x40559e98,
+    0x40561ea5,
+    0x40569ebe,
+    0x40571ed6,
+    0x40579ee9,
+    0x40581efe,
+    0x40589f25,
+    0x40591f54,
+    0x40599f81,
+    0x405a1f95,
+    0x405a9fa5,
+    0x405b1fbd,
+    0x405b9fce,
+    0x405c1fe1,
+    0x405ca002,
+    0x405d200f,
+    0x405da026,
+    0x405e2064,
+    0x405e8a95,
+    0x405f2085,
+    0x405fa092,
+    0x406020a0,
+    0x4060a0c2,
+    0x40612106,
+    0x4061a13e,
+    0x40622155,
+    0x4062a166,
+    0x40632177,
+    0x4063a18c,
+    0x406421a3,
+    0x4064a1cf,
+    0x406521ea,
+    0x4065a201,
+    0x40662219,
+    0x4066a243,
+    0x4067226e,
+    0x4067a28f,
+    0x406822b6,
+    0x4068a2d7,
+    0x40692309,
+    0x4069a337,
+    0x406a2358,
+    0x406aa378,
+    0x406b2500,
+    0x406ba523,
+    0x406c2539,
+    0x406ca7b4,
+    0x406d27e3,
+    0x406da80b,
+    0x406e2839,
+    0x406ea86d,
+    0x406f288c,
+    0x406fa8a1,
+    0x407028b4,
+    0x4070a8d1,
+    0x40710800,
+    0x4071a8e3,
+    0x407228f6,
+    0x4072a90f,
+    0x40732927,
+    0x407393aa,
+    0x4074293b,
+    0x4074a955,
+    0x40752966,
+    0x4075a97a,
+    0x40762988,
+    0x407691d3,
+    0x407729ad,
+    0x4077a9cf,
+    0x407829ea,
+    0x4078aa23,
+    0x40792a3a,
+    0x4079aa50,
+    0x407a2a5c,
+    0x407aaa6f,
+    0x407b2a84,
+    0x407baa96,
+    0x407c2ac7,
+    0x407caad0,
+    0x407d22f2,
+    0x407d9d7c,
+    0x407e29ff,
+    0x407e9f35,
+    0x407f1b8c,
+    0x407f9933,
+    0x40801d53,
+    0x40809bb4,
+    0x40811df8,
+    0x40819d2d,
+    0x40822824,
+    0x40829919,
+    0x40831f10,
+    0x4083a1b4,
+    0x40841bc8,
+    0x40849f6d,
+    0x40851ff2,
+    0x4085a0ea,
+    0x40862046,
+    0x40869d96,
+    0x40872851,
+    0x4087a11b,
+    0x4088197a,
+    0x4088a2a2,
+    0x408919c9,
+    0x40899956,
+    0x408a2559,
+    0x408a978a,
+    0x408b2aab,
+    0x408b9a3f,
+    0x41f4242b,
+    0x41f924bd,
+    0x41fe23b0,
+    0x41fea5a5,
+    0x41ff2696,
+    0x42032444,
+    0x42082466,
+    0x4208a4a2,
+    0x42092394,
+    0x4209a4dc,
+    0x420a23eb,
+    0x420aa3cb,
+    0x420b240b,
+    0x420ba484,
+    0x420c26b2,
+    0x420ca572,
+    0x420d258c,
+    0x420da5c3,
+    0x421225dd,
+    0x42172679,
+    0x4217a61f,
+    0x421c2641,
+    0x421f25fc,
+    0x422126c9,
+    0x4226265c,
+    0x422b2798,
+    0x422ba746,
+    0x422c2780,
+    0x422ca705,
+    0x422d26e4,
+    0x422da765,
+    0x422e272b,
+    0x4432072b,
+    0x4432873a,
+    0x44330746,
+    0x44338754,
+    0x44340767,
+    0x44348778,
+    0x4435077f,
+    0x44358789,
+    0x4436079c,
+    0x443687b2,
+    0x443707c4,
+    0x443787d1,
+    0x443807e0,
+    0x443887e8,
+    0x44390800,
+    0x4439880e,
+    0x443a0821,
+    0x4c321211,
+    0x4c329221,
+    0x4c331234,
+    0x4c339254,
+    0x4c3400ac,
+    0x4c3480ea,
+    0x4c351260,
+    0x4c35926e,
+    0x4c36128a,
+    0x4c36929d,
+    0x4c3712ac,
+    0x4c3792ba,
+    0x4c3812cf,
+    0x4c3892db,
+    0x4c3912fb,
+    0x4c399325,
+    0x4c3a133e,
+    0x4c3a9357,
+    0x4c3b05fb,
+    0x4c3b9370,
+    0x4c3c1382,
+    0x4c3c9391,
+    0x4c3d13aa,
+    0x4c3d8c29,
+    0x4c3e1403,
+    0x4c3e93b9,
+    0x4c3f1425,
+    0x4c3f91d3,
+    0x4c4013cf,
+    0x4c4091fd,
+    0x4c4113f3,
+    0x50322d49,
+    0x5032ad58,
+    0x50332d63,
+    0x5033ad73,
+    0x50342d8c,
+    0x5034ada6,
+    0x50352db4,
+    0x5035adca,
+    0x50362ddc,
+    0x5036adf2,
+    0x50372e0b,
+    0x5037ae1e,
+    0x50382e36,
+    0x5038ae47,
+    0x50392e5c,
+    0x5039ae70,
+    0x503a2e90,
+    0x503aaea6,
+    0x503b2ebe,
+    0x503baed0,
+    0x503c2eec,
+    0x503caf03,
+    0x503d2f1c,
+    0x503daf32,
+    0x503e2f3f,
+    0x503eaf55,
+    0x503f2f67,
+    0x503f8382,
+    0x50402f7a,
+    0x5040af8a,
+    0x50412fa4,
+    0x5041afb3,
+    0x50422fcd,
+    0x5042afea,
+    0x50432ffa,
+    0x5043b00a,
+    0x50443019,
+    0x5044843f,
+    0x5045302d,
+    0x5045b04b,
+    0x5046305e,
+    0x5046b074,
+    0x50473086,
+    0x5047b09b,
+    0x504830c1,
+    0x5048b0cf,
+    0x504930e2,
+    0x5049b0f7,
+    0x504a310d,
+    0x504ab11d,
+    0x504b313d,
+    0x504bb150,
+    0x504c3173,
+    0x504cb1a1,
+    0x504d31b3,
+    0x504db1d0,
+    0x504e31eb,
+    0x504eb207,
+    0x504f3219,
+    0x504fb230,
+    0x5050323f,
+    0x505086ef,
+    0x50513252,
+    0x58320ef2,
+    0x68320eb4,
+    0x68328c4e,
+    0x68330c61,
+    0x68338ec2,
+    0x68340ed2,
+    0x683480ea,
+    0x6c320e90,
+    0x6c328c18,
+    0x6c330e9b,
+    0x74320a0b,
+    0x743280ac,
+    0x74330c29,
+    0x78320970,
+    0x78328985,
+    0x78330991,
     0x78338083,
-    0x78340913,
-    0x78348928,
-    0x78350947,
-    0x78358969,
-    0x7836097e,
-    0x78368994,
-    0x783709a4,
-    0x783789b7,
-    0x783809ca,
-    0x783889dc,
-    0x783909e9,
-    0x78398a08,
-    0x783a0a1d,
-    0x783a8a2b,
-    0x783b0a35,
-    0x783b8a49,
-    0x783c0a60,
-    0x783c8a75,
-    0x783d0a8c,
-    0x783d8aa1,
-    0x783e09f7,
-    0x7c3211a3,
+    0x783409a0,
+    0x783489b5,
+    0x783509d4,
+    0x783589f6,
+    0x78360a0b,
+    0x78368a21,
+    0x78370a31,
+    0x78378a44,
+    0x78380a57,
+    0x78388a69,
+    0x78390a76,
+    0x78398a95,
+    0x783a0aaa,
+    0x783a8ab8,
+    0x783b0ac2,
+    0x783b8ad6,
+    0x783c0aed,
+    0x783c8b02,
+    0x783d0b19,
+    0x783d8b2e,
+    0x783e0a84,
+    0x7c3210ff,
 };
 
 const size_t kOpenSSLReasonValuesLen = sizeof(kOpenSSLReasonValues) / sizeof(kOpenSSLReasonValues[0]);
@@ -682,8 +719,10 @@
     "BN_LIB\0"
     "BOOLEAN_IS_WRONG_LENGTH\0"
     "BUFFER_TOO_SMALL\0"
+    "CONTEXT_NOT_INITIALISED\0"
     "DECODE_ERROR\0"
     "DEPTH_EXCEEDED\0"
+    "DIGEST_AND_KEY_TYPE_NOT_SUPPORTED\0"
     "ENCODE_ERROR\0"
     "ERROR_GETTING_TIME\0"
     "EXPECTING_AN_ASN1_SEQUENCE\0"
@@ -755,10 +794,13 @@
     "UNEXPECTED_EOC\0"
     "UNIVERSALSTRING_IS_WRONG_LENGTH\0"
     "UNKNOWN_FORMAT\0"
+    "UNKNOWN_MESSAGE_DIGEST_ALGORITHM\0"
+    "UNKNOWN_SIGNATURE_ALGORITHM\0"
     "UNKNOWN_TAG\0"
     "UNSUPPORTED_ANY_DEFINED_BY_TYPE\0"
     "UNSUPPORTED_PUBLIC_KEY_TYPE\0"
     "UNSUPPORTED_TYPE\0"
+    "WRONG_PUBLIC_KEY_TYPE\0"
     "WRONG_TAG\0"
     "WRONG_TYPE\0"
     "BAD_FOPEN_MODE\0"
@@ -825,12 +867,15 @@
     "MISSING_EQUAL_SIGN\0"
     "NO_CLOSE_BRACE\0"
     "UNABLE_TO_CREATE_NEW_SECTION\0"
+    "VARIABLE_EXPANSION_TOO_LONG\0"
     "VARIABLE_HAS_NO_VALUE\0"
     "BAD_GENERATOR\0"
     "INVALID_PUBKEY\0"
     "MODULUS_TOO_LARGE\0"
     "NO_PRIVATE_VALUE\0"
+    "UNKNOWN_HASH\0"
     "BAD_Q_VALUE\0"
+    "BAD_VERSION\0"
     "MISSING_PARAMETERS\0"
     "NEED_NEW_SETUP_VALUES\0"
     "BIGNUM_OUT_OF_RANGE\0"
@@ -838,8 +883,10 @@
     "D2I_ECPKPARAMETERS_FAILURE\0"
     "EC_GROUP_NEW_BY_NAME_FAILURE\0"
     "GROUP2PKPARAMETERS_FAILURE\0"
+    "GROUP_MISMATCH\0"
     "I2D_ECPKPARAMETERS_FAILURE\0"
     "INCOMPATIBLE_OBJECTS\0"
+    "INVALID_COFACTOR\0"
     "INVALID_COMPRESSED_POINT\0"
     "INVALID_COMPRESSION_BIT\0"
     "INVALID_ENCODING\0"
@@ -864,27 +911,19 @@
     "NOT_IMPLEMENTED\0"
     "RANDOM_NUMBER_GENERATION_FAILED\0"
     "OPERATION_NOT_SUPPORTED\0"
-    "BN_DECODE_ERROR\0"
     "COMMAND_NOT_SUPPORTED\0"
-    "CONTEXT_NOT_INITIALISED\0"
     "DIFFERENT_KEY_TYPES\0"
     "DIFFERENT_PARAMETERS\0"
-    "DIGEST_AND_KEY_TYPE_NOT_SUPPORTED\0"
     "EXPECTING_AN_EC_KEY_KEY\0"
     "EXPECTING_AN_RSA_KEY\0"
-    "EXPECTING_A_DH_KEY\0"
     "EXPECTING_A_DSA_KEY\0"
     "ILLEGAL_OR_UNSUPPORTED_PADDING_MODE\0"
-    "INVALID_CURVE\0"
     "INVALID_DIGEST_LENGTH\0"
     "INVALID_DIGEST_TYPE\0"
     "INVALID_KEYBITS\0"
     "INVALID_MGF1_MD\0"
     "INVALID_PADDING_MODE\0"
-    "INVALID_PSS_PARAMETERS\0"
     "INVALID_PSS_SALTLEN\0"
-    "INVALID_SALT_LENGTH\0"
-    "INVALID_TRAILER\0"
     "KEYS_NOT_SET\0"
     "NO_DEFAULT_DIGEST\0"
     "NO_KEY_SET\0"
@@ -894,17 +933,8 @@
     "NO_PARAMETERS_SET\0"
     "OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE\0"
     "OPERATON_NOT_INITIALIZED\0"
-    "PARAMETER_ENCODING_ERROR\0"
-    "UNKNOWN_DIGEST\0"
-    "UNKNOWN_MASK_DIGEST\0"
-    "UNKNOWN_MESSAGE_DIGEST_ALGORITHM\0"
     "UNKNOWN_PUBLIC_KEY_TYPE\0"
-    "UNKNOWN_SIGNATURE_ALGORITHM\0"
     "UNSUPPORTED_ALGORITHM\0"
-    "UNSUPPORTED_MASK_ALGORITHM\0"
-    "UNSUPPORTED_MASK_PARAMETER\0"
-    "UNSUPPORTED_SIGNATURE_TYPE\0"
-    "WRONG_PUBLIC_KEY_TYPE\0"
     "OUTPUT_TOO_LARGE\0"
     "UNKNOWN_NID\0"
     "BAD_BASE64_DECODE\0"
@@ -921,6 +951,7 @@
     "SHORT_HEADER\0"
     "UNSUPPORTED_CIPHER\0"
     "UNSUPPORTED_ENCRYPTION\0"
+    "BAD_ITERATION_COUNT\0"
     "BAD_PKCS12_DATA\0"
     "BAD_PKCS12_VERSION\0"
     "CIPHER_HAS_NO_OBJECT_IDENTIFIER\0"
@@ -940,13 +971,16 @@
     "UNKNOWN_ALGORITHM\0"
     "UNKNOWN_CIPHER\0"
     "UNKNOWN_CIPHER_ALGORITHM\0"
-    "UNKNOWN_HASH\0"
+    "UNKNOWN_DIGEST\0"
+    "UNSUPPORTED_KEYLENGTH\0"
+    "UNSUPPORTED_KEY_DERIVATION_FUNCTION\0"
+    "UNSUPPORTED_PRF\0"
     "UNSUPPORTED_PRIVATE_KEY_ALGORITHM\0"
+    "UNSUPPORTED_SALT_TYPE\0"
     "BAD_E_VALUE\0"
     "BAD_FIXED_HEADER_DECRYPT\0"
     "BAD_PAD_BYTE_COUNT\0"
     "BAD_RSA_PARAMETERS\0"
-    "BAD_VERSION\0"
     "BLOCK_TYPE_IS_NOT_01\0"
     "BN_NOT_INITIALIZED\0"
     "CANNOT_RECOVER_MULTI_PRIME_KEY\0"
@@ -982,6 +1016,7 @@
     "UNKNOWN_PADDING_TYPE\0"
     "VALUE_MISSING\0"
     "WRONG_SIGNATURE_LENGTH\0"
+    "ALPN_MISMATCH_ON_EARLY_DATA\0"
     "APP_DATA_IN_HANDSHAKE\0"
     "ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT\0"
     "BAD_ALERT\0"
@@ -1001,13 +1036,19 @@
     "BAD_SSL_FILETYPE\0"
     "BAD_WRITE_RETRY\0"
     "BIO_NOT_SET\0"
+    "BLOCK_CIPHER_PAD_IS_WRONG\0"
+    "BUFFERED_MESSAGES_ON_CIPHER_CHANGE\0"
+    "CANNOT_HAVE_BOTH_PRIVKEY_AND_METHOD\0"
+    "CANNOT_PARSE_LEAF_CERT\0"
     "CA_DN_LENGTH_MISMATCH\0"
     "CA_DN_TOO_LONG\0"
     "CCS_RECEIVED_EARLY\0"
+    "CERTIFICATE_AND_PRIVATE_KEY_MISMATCH\0"
     "CERTIFICATE_VERIFY_FAILED\0"
     "CERT_CB_ERROR\0"
     "CERT_LENGTH_MISMATCH\0"
     "CHANNEL_ID_NOT_P256\0"
+    "CHANNEL_ID_ON_EARLY_DATA\0"
     "CHANNEL_ID_SIGNATURE_INVALID\0"
     "CIPHER_OR_HASH_UNAVAILABLE\0"
     "CLIENTHELLO_PARSE_FAILED\0"
@@ -1021,7 +1062,10 @@
     "DH_PUBLIC_VALUE_LENGTH_IS_WRONG\0"
     "DH_P_TOO_LONG\0"
     "DIGEST_CHECK_FAILED\0"
+    "DOWNGRADE_DETECTED\0"
     "DTLS_MESSAGE_TOO_BIG\0"
+    "DUPLICATE_EXTENSION\0"
+    "DUPLICATE_KEY_SHARE\0"
     "ECC_CERT_NOT_FOR_SIGNING\0"
     "EMS_STATE_INCONSISTENT\0"
     "ENCRYPTED_LENGTH_TOO_LONG\0"
@@ -1036,13 +1080,17 @@
     "HTTPS_PROXY_REQUEST\0"
     "HTTP_REQUEST\0"
     "INAPPROPRIATE_FALLBACK\0"
+    "INVALID_ALPN_PROTOCOL\0"
     "INVALID_COMMAND\0"
+    "INVALID_COMPRESSION_LIST\0"
     "INVALID_MESSAGE\0"
+    "INVALID_OUTER_RECORD_TYPE\0"
+    "INVALID_SCT_LIST\0"
     "INVALID_SSL_SESSION\0"
     "INVALID_TICKET_KEYS_LENGTH\0"
     "LENGTH_MISMATCH\0"
-    "LIBRARY_HAS_NO_CIPHERS\0"
     "MISSING_EXTENSION\0"
+    "MISSING_KEY_SHARE\0"
     "MISSING_RSA_CERTIFICATE\0"
     "MISSING_TMP_DH_KEY\0"
     "MISSING_TMP_ECDH_KEY\0"
@@ -1055,29 +1103,37 @@
     "NO_CERTIFICATE_SET\0"
     "NO_CIPHERS_AVAILABLE\0"
     "NO_CIPHERS_PASSED\0"
+    "NO_CIPHERS_SPECIFIED\0"
     "NO_CIPHER_MATCH\0"
+    "NO_COMMON_SIGNATURE_ALGORITHMS\0"
     "NO_COMPRESSION_SPECIFIED\0"
+    "NO_GROUPS_SPECIFIED\0"
     "NO_METHOD_SPECIFIED\0"
     "NO_P256_SUPPORT\0"
     "NO_PRIVATE_KEY_ASSIGNED\0"
     "NO_RENEGOTIATION\0"
     "NO_REQUIRED_DIGEST\0"
     "NO_SHARED_CIPHER\0"
+    "NO_SHARED_GROUP\0"
     "NULL_SSL_CTX\0"
     "NULL_SSL_METHOD_PASSED\0"
     "OLD_SESSION_CIPHER_NOT_RETURNED\0"
+    "OLD_SESSION_PRF_HASH_MISMATCH\0"
     "OLD_SESSION_VERSION_NOT_RETURNED\0"
     "PARSE_TLSEXT\0"
     "PATH_TOO_LONG\0"
     "PEER_DID_NOT_RETURN_A_CERTIFICATE\0"
     "PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE\0"
+    "PRE_SHARED_KEY_MUST_BE_LAST\0"
     "PROTOCOL_IS_SHUTDOWN\0"
+    "PSK_IDENTITY_BINDER_COUNT_MISMATCH\0"
     "PSK_IDENTITY_NOT_FOUND\0"
     "PSK_NO_CLIENT_CB\0"
     "PSK_NO_SERVER_CB\0"
     "READ_TIMEOUT_EXPIRED\0"
     "RECORD_LENGTH_MISMATCH\0"
     "RECORD_TOO_LARGE\0"
+    "RENEGOTIATION_EMS_MISMATCH\0"
     "RENEGOTIATION_ENCODING_ERR\0"
     "RENEGOTIATION_MISMATCH\0"
     "REQUIRED_CIPHER_MISSING\0"
@@ -1085,8 +1141,10 @@
     "RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION\0"
     "SCSV_RECEIVED_WHEN_RENEGOTIATING\0"
     "SERVERHELLO_TLSEXT\0"
+    "SERVER_CERT_CHANGED\0"
     "SESSION_ID_CONTEXT_UNINITIALIZED\0"
     "SESSION_MAY_NOT_BE_CREATED\0"
+    "SHUTDOWN_WHILE_IN_INIT\0"
     "SIGNATURE_ALGORITHMS_EXTENSION_SENT_BY_SERVER\0"
     "SRTP_COULD_NOT_ALLOCATE_PROFILES\0"
     "SRTP_UNKNOWN_PROTECTION_PROFILE\0"
@@ -1106,6 +1164,7 @@
     "SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION\0"
     "SSL_HANDSHAKE_FAILURE\0"
     "SSL_SESSION_ID_CONTEXT_TOO_LONG\0"
+    "TICKET_ENCRYPTION_FAILED\0"
     "TLSV1_ALERT_ACCESS_DENIED\0"
     "TLSV1_ALERT_DECODE_ERROR\0"
     "TLSV1_ALERT_DECRYPTION_FAILED\0"
@@ -1121,13 +1180,17 @@
     "TLSV1_ALERT_USER_CANCELLED\0"
     "TLSV1_BAD_CERTIFICATE_HASH_VALUE\0"
     "TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE\0"
+    "TLSV1_CERTIFICATE_REQUIRED\0"
     "TLSV1_CERTIFICATE_UNOBTAINABLE\0"
+    "TLSV1_UNKNOWN_PSK_IDENTITY\0"
     "TLSV1_UNRECOGNIZED_NAME\0"
     "TLSV1_UNSUPPORTED_EXTENSION\0"
     "TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST\0"
     "TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG\0"
     "TOO_MANY_EMPTY_FRAGMENTS\0"
+    "TOO_MANY_KEY_UPDATES\0"
     "TOO_MANY_WARNING_ALERTS\0"
+    "TOO_MUCH_SKIPPED_EARLY_DATA\0"
     "UNABLE_TO_FIND_ECDH_PARAMETERS\0"
     "UNEXPECTED_EXTENSION\0"
     "UNEXPECTED_MESSAGE\0"
@@ -1145,6 +1208,7 @@
     "UNSUPPORTED_COMPRESSION_ALGORITHM\0"
     "UNSUPPORTED_ELLIPTIC_CURVE\0"
     "UNSUPPORTED_PROTOCOL\0"
+    "UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY\0"
     "WRONG_CERTIFICATE_TYPE\0"
     "WRONG_CIPHER_RETURNED\0"
     "WRONG_CURVE\0"
@@ -1152,6 +1216,7 @@
     "WRONG_SIGNATURE_TYPE\0"
     "WRONG_SSL_VERSION\0"
     "WRONG_VERSION_NUMBER\0"
+    "WRONG_VERSION_ON_EARLY_DATA\0"
     "X509_LIB\0"
     "X509_VERIFICATION_SETUP_PROBLEMS\0"
     "AKID_MISMATCH\0"
@@ -1165,12 +1230,14 @@
     "IDP_MISMATCH\0"
     "INVALID_DIRECTORY\0"
     "INVALID_FIELD_NAME\0"
+    "INVALID_PSS_PARAMETERS\0"
     "INVALID_TRUST\0"
     "ISSUER_MISMATCH\0"
     "KEY_TYPE_MISMATCH\0"
     "KEY_VALUES_MISMATCH\0"
     "LOADING_CERT_DIR\0"
     "LOADING_DEFAULTS\0"
+    "NAME_TOO_LONG\0"
     "NEWER_CRL_NOT_NEWER\0"
     "NOT_PKCS7_SIGNED_DATA\0"
     "NO_CERTIFICATES_INCLUDED\0"
@@ -1180,8 +1247,6 @@
     "PUBLIC_KEY_DECODE_ERROR\0"
     "PUBLIC_KEY_ENCODE_ERROR\0"
     "SHOULD_RETRY\0"
-    "UNABLE_TO_FIND_PARAMETERS_IN_CHAIN\0"
-    "UNABLE_TO_GET_CERTS_PUBLIC_KEY\0"
     "UNKNOWN_KEY_TYPE\0"
     "UNKNOWN_PURPOSE_ID\0"
     "UNKNOWN_TRUST_ID\0"
diff --git a/flavor.mk b/flavor.mk
deleted file mode 100644
index 32c4fc5..0000000
--- a/flavor.mk
+++ /dev/null
@@ -1,4 +0,0 @@
-# This makefile exists to be included by makefiles in other directories so that
-# they can detect whether BoringSSL or OpenSSL is being used.
-
-OPENSSL_FLAVOR=BoringSSL
diff --git a/linux-aarch64/crypto/aes/aesv8-armx64.S b/linux-aarch64/crypto/aes/aesv8-armx64.S
index fa2abbc..51e2464 100644
--- a/linux-aarch64/crypto/aes/aesv8-armx64.S
+++ b/linux-aarch64/crypto/aes/aesv8-armx64.S
@@ -3,7 +3,7 @@
 
 #if __ARM_MAX_ARCH__>=7
 .text
-#if !defined(__clang__)
+#if !defined(__clang__) || defined(BORINGSSL_CLANG_SUPPORTS_DOT_ARCH)
 .arch	armv8-a+crypto
 #endif
 .align	5
@@ -12,10 +12,11 @@
 .long	0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d	// rotate-n-splat
 .long	0x1b,0x1b,0x1b,0x1b
 
-.globl	aes_v8_set_encrypt_key
-.type	aes_v8_set_encrypt_key,%function
+.globl	aes_hw_set_encrypt_key
+.hidden	aes_hw_set_encrypt_key
+.type	aes_hw_set_encrypt_key,%function
 .align	5
-aes_v8_set_encrypt_key:
+aes_hw_set_encrypt_key:
 .Lenc_key:
 	stp	x29,x30,[sp,#-16]!
 	add	x29,sp,#0
@@ -177,12 +178,13 @@
 	mov	x0,x3			// return value
 	ldr	x29,[sp],#16
 	ret
-.size	aes_v8_set_encrypt_key,.-aes_v8_set_encrypt_key
+.size	aes_hw_set_encrypt_key,.-aes_hw_set_encrypt_key
 
-.globl	aes_v8_set_decrypt_key
-.type	aes_v8_set_decrypt_key,%function
+.globl	aes_hw_set_decrypt_key
+.hidden	aes_hw_set_decrypt_key
+.type	aes_hw_set_decrypt_key,%function
 .align	5
-aes_v8_set_decrypt_key:
+aes_hw_set_decrypt_key:
 	stp	x29,x30,[sp,#-16]!
 	add	x29,sp,#0
 	bl	.Lenc_key
@@ -217,11 +219,12 @@
 .Ldec_key_abort:
 	ldp	x29,x30,[sp],#16
 	ret
-.size	aes_v8_set_decrypt_key,.-aes_v8_set_decrypt_key
-.globl	aes_v8_encrypt
-.type	aes_v8_encrypt,%function
+.size	aes_hw_set_decrypt_key,.-aes_hw_set_decrypt_key
+.globl	aes_hw_encrypt
+.hidden	aes_hw_encrypt
+.type	aes_hw_encrypt,%function
 .align	5
-aes_v8_encrypt:
+aes_hw_encrypt:
 	ldr	w3,[x2,#240]
 	ld1	{v0.4s},[x2],#16
 	ld1	{v2.16b},[x0]
@@ -246,11 +249,12 @@
 
 	st1	{v2.16b},[x1]
 	ret
-.size	aes_v8_encrypt,.-aes_v8_encrypt
-.globl	aes_v8_decrypt
-.type	aes_v8_decrypt,%function
+.size	aes_hw_encrypt,.-aes_hw_encrypt
+.globl	aes_hw_decrypt
+.hidden	aes_hw_decrypt
+.type	aes_hw_decrypt,%function
 .align	5
-aes_v8_decrypt:
+aes_hw_decrypt:
 	ldr	w3,[x2,#240]
 	ld1	{v0.4s},[x2],#16
 	ld1	{v2.16b},[x0]
@@ -275,11 +279,12 @@
 
 	st1	{v2.16b},[x1]
 	ret
-.size	aes_v8_decrypt,.-aes_v8_decrypt
-.globl	aes_v8_cbc_encrypt
-.type	aes_v8_cbc_encrypt,%function
+.size	aes_hw_decrypt,.-aes_hw_decrypt
+.globl	aes_hw_cbc_encrypt
+.hidden	aes_hw_cbc_encrypt
+.type	aes_hw_cbc_encrypt,%function
 .align	5
-aes_v8_cbc_encrypt:
+aes_hw_cbc_encrypt:
 	stp	x29,x30,[sp,#-16]!
 	add	x29,sp,#0
 	subs	x2,x2,#16
@@ -565,11 +570,12 @@
 .Lcbc_abort:
 	ldr	x29,[sp],#16
 	ret
-.size	aes_v8_cbc_encrypt,.-aes_v8_cbc_encrypt
-.globl	aes_v8_ctr32_encrypt_blocks
-.type	aes_v8_ctr32_encrypt_blocks,%function
+.size	aes_hw_cbc_encrypt,.-aes_hw_cbc_encrypt
+.globl	aes_hw_ctr32_encrypt_blocks
+.hidden	aes_hw_ctr32_encrypt_blocks
+.type	aes_hw_ctr32_encrypt_blocks,%function
 .align	5
-aes_v8_ctr32_encrypt_blocks:
+aes_hw_ctr32_encrypt_blocks:
 	stp	x29,x30,[sp,#-16]!
 	add	x29,sp,#0
 	ldr	w5,[x3,#240]
@@ -746,6 +752,6 @@
 .Lctr32_done:
 	ldr	x29,[sp],#16
 	ret
-.size	aes_v8_ctr32_encrypt_blocks,.-aes_v8_ctr32_encrypt_blocks
+.size	aes_hw_ctr32_encrypt_blocks,.-aes_hw_ctr32_encrypt_blocks
 #endif
-#endif
\ No newline at end of file
+#endif
diff --git a/linux-aarch64/crypto/bn/armv8-mont.S b/linux-aarch64/crypto/bn/armv8-mont.S
index 9355ce7..74702db 100644
--- a/linux-aarch64/crypto/bn/armv8-mont.S
+++ b/linux-aarch64/crypto/bn/armv8-mont.S
@@ -2,6 +2,7 @@
 .text
 
 .globl	bn_mul_mont
+.hidden	bn_mul_mont
 .type	bn_mul_mont,%function
 .align	5
 bn_mul_mont:
@@ -1403,4 +1404,4 @@
 .byte	77,111,110,116,103,111,109,101,114,121,32,77,117,108,116,105,112,108,105,99,97,116,105,111,110,32,102,111,114,32,65,82,77,118,56,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
 .align	2
 .align	4
-#endif
\ No newline at end of file
+#endif
diff --git a/linux-aarch64/crypto/chacha/chacha-armv8.S b/linux-aarch64/crypto/chacha/chacha-armv8.S
new file mode 100644
index 0000000..6ff6bff
--- /dev/null
+++ b/linux-aarch64/crypto/chacha/chacha-armv8.S
@@ -0,0 +1,1971 @@
+#if defined(__aarch64__)
+#include <openssl/arm_arch.h>
+
+.text
+
+
+
+.align	5
+.Lsigma:
+.quad	0x3320646e61707865,0x6b20657479622d32		// endian-neutral
+.Lone:
+.long	1,0,0,0
+.LOPENSSL_armcap_P:
+#ifdef	__ILP32__
+.long	OPENSSL_armcap_P-.
+#else
+.quad	OPENSSL_armcap_P-.
+#endif
+.byte	67,104,97,67,104,97,50,48,32,102,111,114,32,65,82,77,118,56,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.align	2
+
+.globl	ChaCha20_ctr32
+.hidden	ChaCha20_ctr32
+.type	ChaCha20_ctr32,%function
+.align	5
+ChaCha20_ctr32:
+	cbz	x2,.Labort
+	adr	x5,.LOPENSSL_armcap_P
+	cmp	x2,#192
+	b.lo	.Lshort
+#ifdef	__ILP32__
+	ldrsw	x6,[x5]
+#else
+	ldr	x6,[x5]
+#endif
+	ldr	w17,[x6,x5]
+	tst	w17,#ARMV7_NEON
+	b.ne	ChaCha20_neon
+
+.Lshort:
+	stp	x29,x30,[sp,#-96]!
+	add	x29,sp,#0
+
+	adr	x5,.Lsigma
+	stp	x19,x20,[sp,#16]
+	stp	x21,x22,[sp,#32]
+	stp	x23,x24,[sp,#48]
+	stp	x25,x26,[sp,#64]
+	stp	x27,x28,[sp,#80]
+	sub	sp,sp,#64
+
+	ldp	x22,x23,[x5]		// load sigma
+	ldp	x24,x25,[x3]		// load key
+	ldp	x26,x27,[x3,#16]
+	ldp	x28,x30,[x4]		// load counter
+#ifdef	__ARMEB__
+	ror	x24,x24,#32
+	ror	x25,x25,#32
+	ror	x26,x26,#32
+	ror	x27,x27,#32
+	ror	x28,x28,#32
+	ror	x30,x30,#32
+#endif
+
+.Loop_outer:
+	mov	w5,w22			// unpack key block
+	lsr	x6,x22,#32
+	mov	w7,w23
+	lsr	x8,x23,#32
+	mov	w9,w24
+	lsr	x10,x24,#32
+	mov	w11,w25
+	lsr	x12,x25,#32
+	mov	w13,w26
+	lsr	x14,x26,#32
+	mov	w15,w27
+	lsr	x16,x27,#32
+	mov	w17,w28
+	lsr	x19,x28,#32
+	mov	w20,w30
+	lsr	x21,x30,#32
+
+	mov	x4,#10
+	subs	x2,x2,#64
+.Loop:
+	sub	x4,x4,#1
+	add	w5,w5,w9
+	add	w6,w6,w10
+	add	w7,w7,w11
+	add	w8,w8,w12
+	eor	w17,w17,w5
+	eor	w19,w19,w6
+	eor	w20,w20,w7
+	eor	w21,w21,w8
+	ror	w17,w17,#16
+	ror	w19,w19,#16
+	ror	w20,w20,#16
+	ror	w21,w21,#16
+	add	w13,w13,w17
+	add	w14,w14,w19
+	add	w15,w15,w20
+	add	w16,w16,w21
+	eor	w9,w9,w13
+	eor	w10,w10,w14
+	eor	w11,w11,w15
+	eor	w12,w12,w16
+	ror	w9,w9,#20
+	ror	w10,w10,#20
+	ror	w11,w11,#20
+	ror	w12,w12,#20
+	add	w5,w5,w9
+	add	w6,w6,w10
+	add	w7,w7,w11
+	add	w8,w8,w12
+	eor	w17,w17,w5
+	eor	w19,w19,w6
+	eor	w20,w20,w7
+	eor	w21,w21,w8
+	ror	w17,w17,#24
+	ror	w19,w19,#24
+	ror	w20,w20,#24
+	ror	w21,w21,#24
+	add	w13,w13,w17
+	add	w14,w14,w19
+	add	w15,w15,w20
+	add	w16,w16,w21
+	eor	w9,w9,w13
+	eor	w10,w10,w14
+	eor	w11,w11,w15
+	eor	w12,w12,w16
+	ror	w9,w9,#25
+	ror	w10,w10,#25
+	ror	w11,w11,#25
+	ror	w12,w12,#25
+	add	w5,w5,w10
+	add	w6,w6,w11
+	add	w7,w7,w12
+	add	w8,w8,w9
+	eor	w21,w21,w5
+	eor	w17,w17,w6
+	eor	w19,w19,w7
+	eor	w20,w20,w8
+	ror	w21,w21,#16
+	ror	w17,w17,#16
+	ror	w19,w19,#16
+	ror	w20,w20,#16
+	add	w15,w15,w21
+	add	w16,w16,w17
+	add	w13,w13,w19
+	add	w14,w14,w20
+	eor	w10,w10,w15
+	eor	w11,w11,w16
+	eor	w12,w12,w13
+	eor	w9,w9,w14
+	ror	w10,w10,#20
+	ror	w11,w11,#20
+	ror	w12,w12,#20
+	ror	w9,w9,#20
+	add	w5,w5,w10
+	add	w6,w6,w11
+	add	w7,w7,w12
+	add	w8,w8,w9
+	eor	w21,w21,w5
+	eor	w17,w17,w6
+	eor	w19,w19,w7
+	eor	w20,w20,w8
+	ror	w21,w21,#24
+	ror	w17,w17,#24
+	ror	w19,w19,#24
+	ror	w20,w20,#24
+	add	w15,w15,w21
+	add	w16,w16,w17
+	add	w13,w13,w19
+	add	w14,w14,w20
+	eor	w10,w10,w15
+	eor	w11,w11,w16
+	eor	w12,w12,w13
+	eor	w9,w9,w14
+	ror	w10,w10,#25
+	ror	w11,w11,#25
+	ror	w12,w12,#25
+	ror	w9,w9,#25
+	cbnz	x4,.Loop
+
+	add	w5,w5,w22		// accumulate key block
+	add	x6,x6,x22,lsr#32
+	add	w7,w7,w23
+	add	x8,x8,x23,lsr#32
+	add	w9,w9,w24
+	add	x10,x10,x24,lsr#32
+	add	w11,w11,w25
+	add	x12,x12,x25,lsr#32
+	add	w13,w13,w26
+	add	x14,x14,x26,lsr#32
+	add	w15,w15,w27
+	add	x16,x16,x27,lsr#32
+	add	w17,w17,w28
+	add	x19,x19,x28,lsr#32
+	add	w20,w20,w30
+	add	x21,x21,x30,lsr#32
+
+	b.lo	.Ltail
+
+	add	x5,x5,x6,lsl#32	// pack
+	add	x7,x7,x8,lsl#32
+	ldp	x6,x8,[x1,#0]		// load input
+	add	x9,x9,x10,lsl#32
+	add	x11,x11,x12,lsl#32
+	ldp	x10,x12,[x1,#16]
+	add	x13,x13,x14,lsl#32
+	add	x15,x15,x16,lsl#32
+	ldp	x14,x16,[x1,#32]
+	add	x17,x17,x19,lsl#32
+	add	x20,x20,x21,lsl#32
+	ldp	x19,x21,[x1,#48]
+	add	x1,x1,#64
+#ifdef	__ARMEB__
+	rev	x5,x5
+	rev	x7,x7
+	rev	x9,x9
+	rev	x11,x11
+	rev	x13,x13
+	rev	x15,x15
+	rev	x17,x17
+	rev	x20,x20
+#endif
+	eor	x5,x5,x6
+	eor	x7,x7,x8
+	eor	x9,x9,x10
+	eor	x11,x11,x12
+	eor	x13,x13,x14
+	eor	x15,x15,x16
+	eor	x17,x17,x19
+	eor	x20,x20,x21
+
+	stp	x5,x7,[x0,#0]		// store output
+	add	x28,x28,#1			// increment counter
+	stp	x9,x11,[x0,#16]
+	stp	x13,x15,[x0,#32]
+	stp	x17,x20,[x0,#48]
+	add	x0,x0,#64
+
+	b.hi	.Loop_outer
+
+	ldp	x19,x20,[x29,#16]
+	add	sp,sp,#64
+	ldp	x21,x22,[x29,#32]
+	ldp	x23,x24,[x29,#48]
+	ldp	x25,x26,[x29,#64]
+	ldp	x27,x28,[x29,#80]
+	ldp	x29,x30,[sp],#96
+.Labort:
+	ret
+
+.align	4
+.Ltail:
+	add	x2,x2,#64
+.Less_than_64:
+	sub	x0,x0,#1
+	add	x1,x1,x2
+	add	x0,x0,x2
+	add	x4,sp,x2
+	neg	x2,x2
+
+	add	x5,x5,x6,lsl#32	// pack
+	add	x7,x7,x8,lsl#32
+	add	x9,x9,x10,lsl#32
+	add	x11,x11,x12,lsl#32
+	add	x13,x13,x14,lsl#32
+	add	x15,x15,x16,lsl#32
+	add	x17,x17,x19,lsl#32
+	add	x20,x20,x21,lsl#32
+#ifdef	__ARMEB__
+	rev	x5,x5
+	rev	x7,x7
+	rev	x9,x9
+	rev	x11,x11
+	rev	x13,x13
+	rev	x15,x15
+	rev	x17,x17
+	rev	x20,x20
+#endif
+	stp	x5,x7,[sp,#0]
+	stp	x9,x11,[sp,#16]
+	stp	x13,x15,[sp,#32]
+	stp	x17,x20,[sp,#48]
+
+.Loop_tail:
+	ldrb	w10,[x1,x2]
+	ldrb	w11,[x4,x2]
+	add	x2,x2,#1
+	eor	w10,w10,w11
+	strb	w10,[x0,x2]
+	cbnz	x2,.Loop_tail
+
+	stp	xzr,xzr,[sp,#0]
+	stp	xzr,xzr,[sp,#16]
+	stp	xzr,xzr,[sp,#32]
+	stp	xzr,xzr,[sp,#48]
+
+	ldp	x19,x20,[x29,#16]
+	add	sp,sp,#64
+	ldp	x21,x22,[x29,#32]
+	ldp	x23,x24,[x29,#48]
+	ldp	x25,x26,[x29,#64]
+	ldp	x27,x28,[x29,#80]
+	ldp	x29,x30,[sp],#96
+	ret
+.size	ChaCha20_ctr32,.-ChaCha20_ctr32
+
+.type	ChaCha20_neon,%function
+.align	5
+ChaCha20_neon:
+	stp	x29,x30,[sp,#-96]!
+	add	x29,sp,#0
+
+	adr	x5,.Lsigma
+	stp	x19,x20,[sp,#16]
+	stp	x21,x22,[sp,#32]
+	stp	x23,x24,[sp,#48]
+	stp	x25,x26,[sp,#64]
+	stp	x27,x28,[sp,#80]
+	cmp	x2,#512
+	b.hs	.L512_or_more_neon
+
+	sub	sp,sp,#64
+
+	ldp	x22,x23,[x5]		// load sigma
+	ld1	{v24.4s},[x5],#16
+	ldp	x24,x25,[x3]		// load key
+	ldp	x26,x27,[x3,#16]
+	ld1	{v25.4s,v26.4s},[x3]
+	ldp	x28,x30,[x4]		// load counter
+	ld1	{v27.4s},[x4]
+	ld1	{v31.4s},[x5]
+#ifdef	__ARMEB__
+	rev64	v24.4s,v24.4s
+	ror	x24,x24,#32
+	ror	x25,x25,#32
+	ror	x26,x26,#32
+	ror	x27,x27,#32
+	ror	x28,x28,#32
+	ror	x30,x30,#32
+#endif
+	add	v27.4s,v27.4s,v31.4s		// += 1
+	add	v28.4s,v27.4s,v31.4s
+	add	v29.4s,v28.4s,v31.4s
+	shl	v31.4s,v31.4s,#2			// 1 -> 4
+
+.Loop_outer_neon:
+	mov	w5,w22			// unpack key block
+	lsr	x6,x22,#32
+	mov	v0.16b,v24.16b
+	mov	w7,w23
+	lsr	x8,x23,#32
+	mov	v4.16b,v24.16b
+	mov	w9,w24
+	lsr	x10,x24,#32
+	mov	v16.16b,v24.16b
+	mov	w11,w25
+	mov	v1.16b,v25.16b
+	lsr	x12,x25,#32
+	mov	v5.16b,v25.16b
+	mov	w13,w26
+	mov	v17.16b,v25.16b
+	lsr	x14,x26,#32
+	mov	v3.16b,v27.16b
+	mov	w15,w27
+	mov	v7.16b,v28.16b
+	lsr	x16,x27,#32
+	mov	v19.16b,v29.16b
+	mov	w17,w28
+	mov	v2.16b,v26.16b
+	lsr	x19,x28,#32
+	mov	v6.16b,v26.16b
+	mov	w20,w30
+	mov	v18.16b,v26.16b
+	lsr	x21,x30,#32
+
+	mov	x4,#10
+	subs	x2,x2,#256
+.Loop_neon:
+	sub	x4,x4,#1
+	add	v0.4s,v0.4s,v1.4s
+	add	w5,w5,w9
+	add	v4.4s,v4.4s,v5.4s
+	add	w6,w6,w10
+	add	v16.4s,v16.4s,v17.4s
+	add	w7,w7,w11
+	eor	v3.16b,v3.16b,v0.16b
+	add	w8,w8,w12
+	eor	v7.16b,v7.16b,v4.16b
+	eor	w17,w17,w5
+	eor	v19.16b,v19.16b,v16.16b
+	eor	w19,w19,w6
+	rev32	v3.8h,v3.8h
+	eor	w20,w20,w7
+	rev32	v7.8h,v7.8h
+	eor	w21,w21,w8
+	rev32	v19.8h,v19.8h
+	ror	w17,w17,#16
+	add	v2.4s,v2.4s,v3.4s
+	ror	w19,w19,#16
+	add	v6.4s,v6.4s,v7.4s
+	ror	w20,w20,#16
+	add	v18.4s,v18.4s,v19.4s
+	ror	w21,w21,#16
+	eor	v20.16b,v1.16b,v2.16b
+	add	w13,w13,w17
+	eor	v21.16b,v5.16b,v6.16b
+	add	w14,w14,w19
+	eor	v22.16b,v17.16b,v18.16b
+	add	w15,w15,w20
+	ushr	v1.4s,v20.4s,#20
+	add	w16,w16,w21
+	ushr	v5.4s,v21.4s,#20
+	eor	w9,w9,w13
+	ushr	v17.4s,v22.4s,#20
+	eor	w10,w10,w14
+	sli	v1.4s,v20.4s,#12
+	eor	w11,w11,w15
+	sli	v5.4s,v21.4s,#12
+	eor	w12,w12,w16
+	sli	v17.4s,v22.4s,#12
+	ror	w9,w9,#20
+	add	v0.4s,v0.4s,v1.4s
+	ror	w10,w10,#20
+	add	v4.4s,v4.4s,v5.4s
+	ror	w11,w11,#20
+	add	v16.4s,v16.4s,v17.4s
+	ror	w12,w12,#20
+	eor	v20.16b,v3.16b,v0.16b
+	add	w5,w5,w9
+	eor	v21.16b,v7.16b,v4.16b
+	add	w6,w6,w10
+	eor	v22.16b,v19.16b,v16.16b
+	add	w7,w7,w11
+	ushr	v3.4s,v20.4s,#24
+	add	w8,w8,w12
+	ushr	v7.4s,v21.4s,#24
+	eor	w17,w17,w5
+	ushr	v19.4s,v22.4s,#24
+	eor	w19,w19,w6
+	sli	v3.4s,v20.4s,#8
+	eor	w20,w20,w7
+	sli	v7.4s,v21.4s,#8
+	eor	w21,w21,w8
+	sli	v19.4s,v22.4s,#8
+	ror	w17,w17,#24
+	add	v2.4s,v2.4s,v3.4s
+	ror	w19,w19,#24
+	add	v6.4s,v6.4s,v7.4s
+	ror	w20,w20,#24
+	add	v18.4s,v18.4s,v19.4s
+	ror	w21,w21,#24
+	eor	v20.16b,v1.16b,v2.16b
+	add	w13,w13,w17
+	eor	v21.16b,v5.16b,v6.16b
+	add	w14,w14,w19
+	eor	v22.16b,v17.16b,v18.16b
+	add	w15,w15,w20
+	ushr	v1.4s,v20.4s,#25
+	add	w16,w16,w21
+	ushr	v5.4s,v21.4s,#25
+	eor	w9,w9,w13
+	ushr	v17.4s,v22.4s,#25
+	eor	w10,w10,w14
+	sli	v1.4s,v20.4s,#7
+	eor	w11,w11,w15
+	sli	v5.4s,v21.4s,#7
+	eor	w12,w12,w16
+	sli	v17.4s,v22.4s,#7
+	ror	w9,w9,#25
+	ext	v2.16b,v2.16b,v2.16b,#8
+	ror	w10,w10,#25
+	ext	v6.16b,v6.16b,v6.16b,#8
+	ror	w11,w11,#25
+	ext	v18.16b,v18.16b,v18.16b,#8
+	ror	w12,w12,#25
+	ext	v3.16b,v3.16b,v3.16b,#12
+	ext	v7.16b,v7.16b,v7.16b,#12
+	ext	v19.16b,v19.16b,v19.16b,#12
+	ext	v1.16b,v1.16b,v1.16b,#4
+	ext	v5.16b,v5.16b,v5.16b,#4
+	ext	v17.16b,v17.16b,v17.16b,#4
+	add	v0.4s,v0.4s,v1.4s
+	add	w5,w5,w10
+	add	v4.4s,v4.4s,v5.4s
+	add	w6,w6,w11
+	add	v16.4s,v16.4s,v17.4s
+	add	w7,w7,w12
+	eor	v3.16b,v3.16b,v0.16b
+	add	w8,w8,w9
+	eor	v7.16b,v7.16b,v4.16b
+	eor	w21,w21,w5
+	eor	v19.16b,v19.16b,v16.16b
+	eor	w17,w17,w6
+	rev32	v3.8h,v3.8h
+	eor	w19,w19,w7
+	rev32	v7.8h,v7.8h
+	eor	w20,w20,w8
+	rev32	v19.8h,v19.8h
+	ror	w21,w21,#16
+	add	v2.4s,v2.4s,v3.4s
+	ror	w17,w17,#16
+	add	v6.4s,v6.4s,v7.4s
+	ror	w19,w19,#16
+	add	v18.4s,v18.4s,v19.4s
+	ror	w20,w20,#16
+	eor	v20.16b,v1.16b,v2.16b
+	add	w15,w15,w21
+	eor	v21.16b,v5.16b,v6.16b
+	add	w16,w16,w17
+	eor	v22.16b,v17.16b,v18.16b
+	add	w13,w13,w19
+	ushr	v1.4s,v20.4s,#20
+	add	w14,w14,w20
+	ushr	v5.4s,v21.4s,#20
+	eor	w10,w10,w15
+	ushr	v17.4s,v22.4s,#20
+	eor	w11,w11,w16
+	sli	v1.4s,v20.4s,#12
+	eor	w12,w12,w13
+	sli	v5.4s,v21.4s,#12
+	eor	w9,w9,w14
+	sli	v17.4s,v22.4s,#12
+	ror	w10,w10,#20
+	add	v0.4s,v0.4s,v1.4s
+	ror	w11,w11,#20
+	add	v4.4s,v4.4s,v5.4s
+	ror	w12,w12,#20
+	add	v16.4s,v16.4s,v17.4s
+	ror	w9,w9,#20
+	eor	v20.16b,v3.16b,v0.16b
+	add	w5,w5,w10
+	eor	v21.16b,v7.16b,v4.16b
+	add	w6,w6,w11
+	eor	v22.16b,v19.16b,v16.16b
+	add	w7,w7,w12
+	ushr	v3.4s,v20.4s,#24
+	add	w8,w8,w9
+	ushr	v7.4s,v21.4s,#24
+	eor	w21,w21,w5
+	ushr	v19.4s,v22.4s,#24
+	eor	w17,w17,w6
+	sli	v3.4s,v20.4s,#8
+	eor	w19,w19,w7
+	sli	v7.4s,v21.4s,#8
+	eor	w20,w20,w8
+	sli	v19.4s,v22.4s,#8
+	ror	w21,w21,#24
+	add	v2.4s,v2.4s,v3.4s
+	ror	w17,w17,#24
+	add	v6.4s,v6.4s,v7.4s
+	ror	w19,w19,#24
+	add	v18.4s,v18.4s,v19.4s
+	ror	w20,w20,#24
+	eor	v20.16b,v1.16b,v2.16b
+	add	w15,w15,w21
+	eor	v21.16b,v5.16b,v6.16b
+	add	w16,w16,w17
+	eor	v22.16b,v17.16b,v18.16b
+	add	w13,w13,w19
+	ushr	v1.4s,v20.4s,#25
+	add	w14,w14,w20
+	ushr	v5.4s,v21.4s,#25
+	eor	w10,w10,w15
+	ushr	v17.4s,v22.4s,#25
+	eor	w11,w11,w16
+	sli	v1.4s,v20.4s,#7
+	eor	w12,w12,w13
+	sli	v5.4s,v21.4s,#7
+	eor	w9,w9,w14
+	sli	v17.4s,v22.4s,#7
+	ror	w10,w10,#25
+	ext	v2.16b,v2.16b,v2.16b,#8
+	ror	w11,w11,#25
+	ext	v6.16b,v6.16b,v6.16b,#8
+	ror	w12,w12,#25
+	ext	v18.16b,v18.16b,v18.16b,#8
+	ror	w9,w9,#25
+	ext	v3.16b,v3.16b,v3.16b,#4
+	ext	v7.16b,v7.16b,v7.16b,#4
+	ext	v19.16b,v19.16b,v19.16b,#4
+	ext	v1.16b,v1.16b,v1.16b,#12
+	ext	v5.16b,v5.16b,v5.16b,#12
+	ext	v17.16b,v17.16b,v17.16b,#12
+	cbnz	x4,.Loop_neon
+
+	add	w5,w5,w22		// accumulate key block
+	add	v0.4s,v0.4s,v24.4s
+	add	x6,x6,x22,lsr#32
+	add	v4.4s,v4.4s,v24.4s
+	add	w7,w7,w23
+	add	v16.4s,v16.4s,v24.4s
+	add	x8,x8,x23,lsr#32
+	add	v2.4s,v2.4s,v26.4s
+	add	w9,w9,w24
+	add	v6.4s,v6.4s,v26.4s
+	add	x10,x10,x24,lsr#32
+	add	v18.4s,v18.4s,v26.4s
+	add	w11,w11,w25
+	add	v3.4s,v3.4s,v27.4s
+	add	x12,x12,x25,lsr#32
+	add	w13,w13,w26
+	add	v7.4s,v7.4s,v28.4s
+	add	x14,x14,x26,lsr#32
+	add	w15,w15,w27
+	add	v19.4s,v19.4s,v29.4s
+	add	x16,x16,x27,lsr#32
+	add	w17,w17,w28
+	add	v1.4s,v1.4s,v25.4s
+	add	x19,x19,x28,lsr#32
+	add	w20,w20,w30
+	add	v5.4s,v5.4s,v25.4s
+	add	x21,x21,x30,lsr#32
+	add	v17.4s,v17.4s,v25.4s
+
+	b.lo	.Ltail_neon
+
+	add	x5,x5,x6,lsl#32	// pack
+	add	x7,x7,x8,lsl#32
+	ldp	x6,x8,[x1,#0]		// load input
+	add	x9,x9,x10,lsl#32
+	add	x11,x11,x12,lsl#32
+	ldp	x10,x12,[x1,#16]
+	add	x13,x13,x14,lsl#32
+	add	x15,x15,x16,lsl#32
+	ldp	x14,x16,[x1,#32]
+	add	x17,x17,x19,lsl#32
+	add	x20,x20,x21,lsl#32
+	ldp	x19,x21,[x1,#48]
+	add	x1,x1,#64
+#ifdef	__ARMEB__
+	rev	x5,x5
+	rev	x7,x7
+	rev	x9,x9
+	rev	x11,x11
+	rev	x13,x13
+	rev	x15,x15
+	rev	x17,x17
+	rev	x20,x20
+#endif
+	ld1	{v20.16b,v21.16b,v22.16b,v23.16b},[x1],#64
+	eor	x5,x5,x6
+	eor	x7,x7,x8
+	eor	x9,x9,x10
+	eor	x11,x11,x12
+	eor	x13,x13,x14
+	eor	v0.16b,v0.16b,v20.16b
+	eor	x15,x15,x16
+	eor	v1.16b,v1.16b,v21.16b
+	eor	x17,x17,x19
+	eor	v2.16b,v2.16b,v22.16b
+	eor	x20,x20,x21
+	eor	v3.16b,v3.16b,v23.16b
+	ld1	{v20.16b,v21.16b,v22.16b,v23.16b},[x1],#64
+
+	stp	x5,x7,[x0,#0]		// store output
+	add	x28,x28,#4			// increment counter
+	stp	x9,x11,[x0,#16]
+	add	v27.4s,v27.4s,v31.4s		// += 4
+	stp	x13,x15,[x0,#32]
+	add	v28.4s,v28.4s,v31.4s
+	stp	x17,x20,[x0,#48]
+	add	v29.4s,v29.4s,v31.4s
+	add	x0,x0,#64
+
+	st1	{v0.16b,v1.16b,v2.16b,v3.16b},[x0],#64
+	ld1	{v0.16b,v1.16b,v2.16b,v3.16b},[x1],#64
+
+	eor	v4.16b,v4.16b,v20.16b
+	eor	v5.16b,v5.16b,v21.16b
+	eor	v6.16b,v6.16b,v22.16b
+	eor	v7.16b,v7.16b,v23.16b
+	st1	{v4.16b,v5.16b,v6.16b,v7.16b},[x0],#64
+
+	eor	v16.16b,v16.16b,v0.16b
+	eor	v17.16b,v17.16b,v1.16b
+	eor	v18.16b,v18.16b,v2.16b
+	eor	v19.16b,v19.16b,v3.16b
+	st1	{v16.16b,v17.16b,v18.16b,v19.16b},[x0],#64
+
+	b.hi	.Loop_outer_neon
+
+	ldp	x19,x20,[x29,#16]
+	add	sp,sp,#64
+	ldp	x21,x22,[x29,#32]
+	ldp	x23,x24,[x29,#48]
+	ldp	x25,x26,[x29,#64]
+	ldp	x27,x28,[x29,#80]
+	ldp	x29,x30,[sp],#96
+	ret
+
+.Ltail_neon:
+	add	x2,x2,#256
+	cmp	x2,#64
+	b.lo	.Less_than_64
+
+	add	x5,x5,x6,lsl#32	// pack
+	add	x7,x7,x8,lsl#32
+	ldp	x6,x8,[x1,#0]		// load input
+	add	x9,x9,x10,lsl#32
+	add	x11,x11,x12,lsl#32
+	ldp	x10,x12,[x1,#16]
+	add	x13,x13,x14,lsl#32
+	add	x15,x15,x16,lsl#32
+	ldp	x14,x16,[x1,#32]
+	add	x17,x17,x19,lsl#32
+	add	x20,x20,x21,lsl#32
+	ldp	x19,x21,[x1,#48]
+	add	x1,x1,#64
+#ifdef	__ARMEB__
+	rev	x5,x5
+	rev	x7,x7
+	rev	x9,x9
+	rev	x11,x11
+	rev	x13,x13
+	rev	x15,x15
+	rev	x17,x17
+	rev	x20,x20
+#endif
+	eor	x5,x5,x6
+	eor	x7,x7,x8
+	eor	x9,x9,x10
+	eor	x11,x11,x12
+	eor	x13,x13,x14
+	eor	x15,x15,x16
+	eor	x17,x17,x19
+	eor	x20,x20,x21
+
+	stp	x5,x7,[x0,#0]		// store output
+	add	x28,x28,#4			// increment counter
+	stp	x9,x11,[x0,#16]
+	stp	x13,x15,[x0,#32]
+	stp	x17,x20,[x0,#48]
+	add	x0,x0,#64
+	b.eq	.Ldone_neon
+	sub	x2,x2,#64
+	cmp	x2,#64
+	b.lo	.Less_than_128
+
+	ld1	{v20.16b,v21.16b,v22.16b,v23.16b},[x1],#64
+	eor	v0.16b,v0.16b,v20.16b
+	eor	v1.16b,v1.16b,v21.16b
+	eor	v2.16b,v2.16b,v22.16b
+	eor	v3.16b,v3.16b,v23.16b
+	st1	{v0.16b,v1.16b,v2.16b,v3.16b},[x0],#64
+	b.eq	.Ldone_neon
+	sub	x2,x2,#64
+	cmp	x2,#64
+	b.lo	.Less_than_192
+
+	ld1	{v20.16b,v21.16b,v22.16b,v23.16b},[x1],#64
+	eor	v4.16b,v4.16b,v20.16b
+	eor	v5.16b,v5.16b,v21.16b
+	eor	v6.16b,v6.16b,v22.16b
+	eor	v7.16b,v7.16b,v23.16b
+	st1	{v4.16b,v5.16b,v6.16b,v7.16b},[x0],#64
+	b.eq	.Ldone_neon
+	sub	x2,x2,#64
+
+	st1	{v16.16b,v17.16b,v18.16b,v19.16b},[sp]
+	b	.Last_neon
+
+.Less_than_128:
+	st1	{v0.16b,v1.16b,v2.16b,v3.16b},[sp]
+	b	.Last_neon
+.Less_than_192:
+	st1	{v4.16b,v5.16b,v6.16b,v7.16b},[sp]
+	b	.Last_neon
+
+.align	4
+.Last_neon:
+	sub	x0,x0,#1
+	add	x1,x1,x2
+	add	x0,x0,x2
+	add	x4,sp,x2
+	neg	x2,x2
+
+.Loop_tail_neon:
+	ldrb	w10,[x1,x2]
+	ldrb	w11,[x4,x2]
+	add	x2,x2,#1
+	eor	w10,w10,w11
+	strb	w10,[x0,x2]
+	cbnz	x2,.Loop_tail_neon
+
+	stp	xzr,xzr,[sp,#0]
+	stp	xzr,xzr,[sp,#16]
+	stp	xzr,xzr,[sp,#32]
+	stp	xzr,xzr,[sp,#48]
+
+.Ldone_neon:
+	ldp	x19,x20,[x29,#16]
+	add	sp,sp,#64
+	ldp	x21,x22,[x29,#32]
+	ldp	x23,x24,[x29,#48]
+	ldp	x25,x26,[x29,#64]
+	ldp	x27,x28,[x29,#80]
+	ldp	x29,x30,[sp],#96
+	ret
+.size	ChaCha20_neon,.-ChaCha20_neon
+.type	ChaCha20_512_neon,%function
+.align	5
+ChaCha20_512_neon:
+	stp	x29,x30,[sp,#-96]!
+	add	x29,sp,#0
+
+	adr	x5,.Lsigma
+	stp	x19,x20,[sp,#16]
+	stp	x21,x22,[sp,#32]
+	stp	x23,x24,[sp,#48]
+	stp	x25,x26,[sp,#64]
+	stp	x27,x28,[sp,#80]
+
+.L512_or_more_neon:
+	sub	sp,sp,#128+64
+
+	ldp	x22,x23,[x5]		// load sigma
+	ld1	{v24.4s},[x5],#16
+	ldp	x24,x25,[x3]		// load key
+	ldp	x26,x27,[x3,#16]
+	ld1	{v25.4s,v26.4s},[x3]
+	ldp	x28,x30,[x4]		// load counter
+	ld1	{v27.4s},[x4]
+	ld1	{v31.4s},[x5]
+#ifdef	__ARMEB__
+	rev64	v24.4s,v24.4s
+	ror	x24,x24,#32
+	ror	x25,x25,#32
+	ror	x26,x26,#32
+	ror	x27,x27,#32
+	ror	x28,x28,#32
+	ror	x30,x30,#32
+#endif
+	add	v27.4s,v27.4s,v31.4s		// += 1
+	stp	q24,q25,[sp,#0]		// off-load key block, invariant part
+	add	v27.4s,v27.4s,v31.4s		// not typo
+	str	q26,[sp,#32]
+	add	v28.4s,v27.4s,v31.4s
+	add	v29.4s,v28.4s,v31.4s
+	add	v30.4s,v29.4s,v31.4s
+	shl	v31.4s,v31.4s,#2			// 1 -> 4
+
+	stp	d8,d9,[sp,#128+0]		// meet ABI requirements
+	stp	d10,d11,[sp,#128+16]
+	stp	d12,d13,[sp,#128+32]
+	stp	d14,d15,[sp,#128+48]
+
+	sub	x2,x2,#512			// not typo
+
+.Loop_outer_512_neon:
+	mov	v0.16b,v24.16b
+	mov	v4.16b,v24.16b
+	mov	v8.16b,v24.16b
+	mov	v12.16b,v24.16b
+	mov	v16.16b,v24.16b
+	mov	v20.16b,v24.16b
+	mov	v1.16b,v25.16b
+	mov	w5,w22			// unpack key block
+	mov	v5.16b,v25.16b
+	lsr	x6,x22,#32
+	mov	v9.16b,v25.16b
+	mov	w7,w23
+	mov	v13.16b,v25.16b
+	lsr	x8,x23,#32
+	mov	v17.16b,v25.16b
+	mov	w9,w24
+	mov	v21.16b,v25.16b
+	lsr	x10,x24,#32
+	mov	v3.16b,v27.16b
+	mov	w11,w25
+	mov	v7.16b,v28.16b
+	lsr	x12,x25,#32
+	mov	v11.16b,v29.16b
+	mov	w13,w26
+	mov	v15.16b,v30.16b
+	lsr	x14,x26,#32
+	mov	v2.16b,v26.16b
+	mov	w15,w27
+	mov	v6.16b,v26.16b
+	lsr	x16,x27,#32
+	add	v19.4s,v3.4s,v31.4s			// +4
+	mov	w17,w28
+	add	v23.4s,v7.4s,v31.4s			// +4
+	lsr	x19,x28,#32
+	mov	v10.16b,v26.16b
+	mov	w20,w30
+	mov	v14.16b,v26.16b
+	lsr	x21,x30,#32
+	mov	v18.16b,v26.16b
+	stp	q27,q28,[sp,#48]		// off-load key block, variable part
+	mov	v22.16b,v26.16b
+	str	q29,[sp,#80]
+
+	mov	x4,#5
+	subs	x2,x2,#512
+.Loop_upper_neon:
+	sub	x4,x4,#1
+	add	v0.4s,v0.4s,v1.4s
+	add	w5,w5,w9
+	add	v4.4s,v4.4s,v5.4s
+	add	w6,w6,w10
+	add	v8.4s,v8.4s,v9.4s
+	add	w7,w7,w11
+	add	v12.4s,v12.4s,v13.4s
+	add	w8,w8,w12
+	add	v16.4s,v16.4s,v17.4s
+	eor	w17,w17,w5
+	add	v20.4s,v20.4s,v21.4s
+	eor	w19,w19,w6
+	eor	v3.16b,v3.16b,v0.16b
+	eor	w20,w20,w7
+	eor	v7.16b,v7.16b,v4.16b
+	eor	w21,w21,w8
+	eor	v11.16b,v11.16b,v8.16b
+	ror	w17,w17,#16
+	eor	v15.16b,v15.16b,v12.16b
+	ror	w19,w19,#16
+	eor	v19.16b,v19.16b,v16.16b
+	ror	w20,w20,#16
+	eor	v23.16b,v23.16b,v20.16b
+	ror	w21,w21,#16
+	rev32	v3.8h,v3.8h
+	add	w13,w13,w17
+	rev32	v7.8h,v7.8h
+	add	w14,w14,w19
+	rev32	v11.8h,v11.8h
+	add	w15,w15,w20
+	rev32	v15.8h,v15.8h
+	add	w16,w16,w21
+	rev32	v19.8h,v19.8h
+	eor	w9,w9,w13
+	rev32	v23.8h,v23.8h
+	eor	w10,w10,w14
+	add	v2.4s,v2.4s,v3.4s
+	eor	w11,w11,w15
+	add	v6.4s,v6.4s,v7.4s
+	eor	w12,w12,w16
+	add	v10.4s,v10.4s,v11.4s
+	ror	w9,w9,#20
+	add	v14.4s,v14.4s,v15.4s
+	ror	w10,w10,#20
+	add	v18.4s,v18.4s,v19.4s
+	ror	w11,w11,#20
+	add	v22.4s,v22.4s,v23.4s
+	ror	w12,w12,#20
+	eor	v24.16b,v1.16b,v2.16b
+	add	w5,w5,w9
+	eor	v25.16b,v5.16b,v6.16b
+	add	w6,w6,w10
+	eor	v26.16b,v9.16b,v10.16b
+	add	w7,w7,w11
+	eor	v27.16b,v13.16b,v14.16b
+	add	w8,w8,w12
+	eor	v28.16b,v17.16b,v18.16b
+	eor	w17,w17,w5
+	eor	v29.16b,v21.16b,v22.16b
+	eor	w19,w19,w6
+	ushr	v1.4s,v24.4s,#20
+	eor	w20,w20,w7
+	ushr	v5.4s,v25.4s,#20
+	eor	w21,w21,w8
+	ushr	v9.4s,v26.4s,#20
+	ror	w17,w17,#24
+	ushr	v13.4s,v27.4s,#20
+	ror	w19,w19,#24
+	ushr	v17.4s,v28.4s,#20
+	ror	w20,w20,#24
+	ushr	v21.4s,v29.4s,#20
+	ror	w21,w21,#24
+	sli	v1.4s,v24.4s,#12
+	add	w13,w13,w17
+	sli	v5.4s,v25.4s,#12
+	add	w14,w14,w19
+	sli	v9.4s,v26.4s,#12
+	add	w15,w15,w20
+	sli	v13.4s,v27.4s,#12
+	add	w16,w16,w21
+	sli	v17.4s,v28.4s,#12
+	eor	w9,w9,w13
+	sli	v21.4s,v29.4s,#12
+	eor	w10,w10,w14
+	add	v0.4s,v0.4s,v1.4s
+	eor	w11,w11,w15
+	add	v4.4s,v4.4s,v5.4s
+	eor	w12,w12,w16
+	add	v8.4s,v8.4s,v9.4s
+	ror	w9,w9,#25
+	add	v12.4s,v12.4s,v13.4s
+	ror	w10,w10,#25
+	add	v16.4s,v16.4s,v17.4s
+	ror	w11,w11,#25
+	add	v20.4s,v20.4s,v21.4s
+	ror	w12,w12,#25
+	eor	v24.16b,v3.16b,v0.16b
+	add	w5,w5,w10
+	eor	v25.16b,v7.16b,v4.16b
+	add	w6,w6,w11
+	eor	v26.16b,v11.16b,v8.16b
+	add	w7,w7,w12
+	eor	v27.16b,v15.16b,v12.16b
+	add	w8,w8,w9
+	eor	v28.16b,v19.16b,v16.16b
+	eor	w21,w21,w5
+	eor	v29.16b,v23.16b,v20.16b
+	eor	w17,w17,w6
+	ushr	v3.4s,v24.4s,#24
+	eor	w19,w19,w7
+	ushr	v7.4s,v25.4s,#24
+	eor	w20,w20,w8
+	ushr	v11.4s,v26.4s,#24
+	ror	w21,w21,#16
+	ushr	v15.4s,v27.4s,#24
+	ror	w17,w17,#16
+	ushr	v19.4s,v28.4s,#24
+	ror	w19,w19,#16
+	ushr	v23.4s,v29.4s,#24
+	ror	w20,w20,#16
+	sli	v3.4s,v24.4s,#8
+	add	w15,w15,w21
+	sli	v7.4s,v25.4s,#8
+	add	w16,w16,w17
+	sli	v11.4s,v26.4s,#8
+	add	w13,w13,w19
+	sli	v15.4s,v27.4s,#8
+	add	w14,w14,w20
+	sli	v19.4s,v28.4s,#8
+	eor	w10,w10,w15
+	sli	v23.4s,v29.4s,#8
+	eor	w11,w11,w16
+	add	v2.4s,v2.4s,v3.4s
+	eor	w12,w12,w13
+	add	v6.4s,v6.4s,v7.4s
+	eor	w9,w9,w14
+	add	v10.4s,v10.4s,v11.4s
+	ror	w10,w10,#20
+	add	v14.4s,v14.4s,v15.4s
+	ror	w11,w11,#20
+	add	v18.4s,v18.4s,v19.4s
+	ror	w12,w12,#20
+	add	v22.4s,v22.4s,v23.4s
+	ror	w9,w9,#20
+	eor	v24.16b,v1.16b,v2.16b
+	add	w5,w5,w10
+	eor	v25.16b,v5.16b,v6.16b
+	add	w6,w6,w11
+	eor	v26.16b,v9.16b,v10.16b
+	add	w7,w7,w12
+	eor	v27.16b,v13.16b,v14.16b
+	add	w8,w8,w9
+	eor	v28.16b,v17.16b,v18.16b
+	eor	w21,w21,w5
+	eor	v29.16b,v21.16b,v22.16b
+	eor	w17,w17,w6
+	ushr	v1.4s,v24.4s,#25
+	eor	w19,w19,w7
+	ushr	v5.4s,v25.4s,#25
+	eor	w20,w20,w8
+	ushr	v9.4s,v26.4s,#25
+	ror	w21,w21,#24
+	ushr	v13.4s,v27.4s,#25
+	ror	w17,w17,#24
+	ushr	v17.4s,v28.4s,#25
+	ror	w19,w19,#24
+	ushr	v21.4s,v29.4s,#25
+	ror	w20,w20,#24
+	sli	v1.4s,v24.4s,#7
+	add	w15,w15,w21
+	sli	v5.4s,v25.4s,#7
+	add	w16,w16,w17
+	sli	v9.4s,v26.4s,#7
+	add	w13,w13,w19
+	sli	v13.4s,v27.4s,#7
+	add	w14,w14,w20
+	sli	v17.4s,v28.4s,#7
+	eor	w10,w10,w15
+	sli	v21.4s,v29.4s,#7
+	eor	w11,w11,w16
+	ext	v2.16b,v2.16b,v2.16b,#8
+	eor	w12,w12,w13
+	ext	v6.16b,v6.16b,v6.16b,#8
+	eor	w9,w9,w14
+	ext	v10.16b,v10.16b,v10.16b,#8
+	ror	w10,w10,#25
+	ext	v14.16b,v14.16b,v14.16b,#8
+	ror	w11,w11,#25
+	ext	v18.16b,v18.16b,v18.16b,#8
+	ror	w12,w12,#25
+	ext	v22.16b,v22.16b,v22.16b,#8
+	ror	w9,w9,#25
+	ext	v3.16b,v3.16b,v3.16b,#12
+	ext	v7.16b,v7.16b,v7.16b,#12
+	ext	v11.16b,v11.16b,v11.16b,#12
+	ext	v15.16b,v15.16b,v15.16b,#12
+	ext	v19.16b,v19.16b,v19.16b,#12
+	ext	v23.16b,v23.16b,v23.16b,#12
+	ext	v1.16b,v1.16b,v1.16b,#4
+	ext	v5.16b,v5.16b,v5.16b,#4
+	ext	v9.16b,v9.16b,v9.16b,#4
+	ext	v13.16b,v13.16b,v13.16b,#4
+	ext	v17.16b,v17.16b,v17.16b,#4
+	ext	v21.16b,v21.16b,v21.16b,#4
+	add	v0.4s,v0.4s,v1.4s
+	add	w5,w5,w9
+	add	v4.4s,v4.4s,v5.4s
+	add	w6,w6,w10
+	add	v8.4s,v8.4s,v9.4s
+	add	w7,w7,w11
+	add	v12.4s,v12.4s,v13.4s
+	add	w8,w8,w12
+	add	v16.4s,v16.4s,v17.4s
+	eor	w17,w17,w5
+	add	v20.4s,v20.4s,v21.4s
+	eor	w19,w19,w6
+	eor	v3.16b,v3.16b,v0.16b
+	eor	w20,w20,w7
+	eor	v7.16b,v7.16b,v4.16b
+	eor	w21,w21,w8
+	eor	v11.16b,v11.16b,v8.16b
+	ror	w17,w17,#16
+	eor	v15.16b,v15.16b,v12.16b
+	ror	w19,w19,#16
+	eor	v19.16b,v19.16b,v16.16b
+	ror	w20,w20,#16
+	eor	v23.16b,v23.16b,v20.16b
+	ror	w21,w21,#16
+	rev32	v3.8h,v3.8h
+	add	w13,w13,w17
+	rev32	v7.8h,v7.8h
+	add	w14,w14,w19
+	rev32	v11.8h,v11.8h
+	add	w15,w15,w20
+	rev32	v15.8h,v15.8h
+	add	w16,w16,w21
+	rev32	v19.8h,v19.8h
+	eor	w9,w9,w13
+	rev32	v23.8h,v23.8h
+	eor	w10,w10,w14
+	add	v2.4s,v2.4s,v3.4s
+	eor	w11,w11,w15
+	add	v6.4s,v6.4s,v7.4s
+	eor	w12,w12,w16
+	add	v10.4s,v10.4s,v11.4s
+	ror	w9,w9,#20
+	add	v14.4s,v14.4s,v15.4s
+	ror	w10,w10,#20
+	add	v18.4s,v18.4s,v19.4s
+	ror	w11,w11,#20
+	add	v22.4s,v22.4s,v23.4s
+	ror	w12,w12,#20
+	eor	v24.16b,v1.16b,v2.16b
+	add	w5,w5,w9
+	eor	v25.16b,v5.16b,v6.16b
+	add	w6,w6,w10
+	eor	v26.16b,v9.16b,v10.16b
+	add	w7,w7,w11
+	eor	v27.16b,v13.16b,v14.16b
+	add	w8,w8,w12
+	eor	v28.16b,v17.16b,v18.16b
+	eor	w17,w17,w5
+	eor	v29.16b,v21.16b,v22.16b
+	eor	w19,w19,w6
+	ushr	v1.4s,v24.4s,#20
+	eor	w20,w20,w7
+	ushr	v5.4s,v25.4s,#20
+	eor	w21,w21,w8
+	ushr	v9.4s,v26.4s,#20
+	ror	w17,w17,#24
+	ushr	v13.4s,v27.4s,#20
+	ror	w19,w19,#24
+	ushr	v17.4s,v28.4s,#20
+	ror	w20,w20,#24
+	ushr	v21.4s,v29.4s,#20
+	ror	w21,w21,#24
+	sli	v1.4s,v24.4s,#12
+	add	w13,w13,w17
+	sli	v5.4s,v25.4s,#12
+	add	w14,w14,w19
+	sli	v9.4s,v26.4s,#12
+	add	w15,w15,w20
+	sli	v13.4s,v27.4s,#12
+	add	w16,w16,w21
+	sli	v17.4s,v28.4s,#12
+	eor	w9,w9,w13
+	sli	v21.4s,v29.4s,#12
+	eor	w10,w10,w14
+	add	v0.4s,v0.4s,v1.4s
+	eor	w11,w11,w15
+	add	v4.4s,v4.4s,v5.4s
+	eor	w12,w12,w16
+	add	v8.4s,v8.4s,v9.4s
+	ror	w9,w9,#25
+	add	v12.4s,v12.4s,v13.4s
+	ror	w10,w10,#25
+	add	v16.4s,v16.4s,v17.4s
+	ror	w11,w11,#25
+	add	v20.4s,v20.4s,v21.4s
+	ror	w12,w12,#25
+	eor	v24.16b,v3.16b,v0.16b
+	add	w5,w5,w10
+	eor	v25.16b,v7.16b,v4.16b
+	add	w6,w6,w11
+	eor	v26.16b,v11.16b,v8.16b
+	add	w7,w7,w12
+	eor	v27.16b,v15.16b,v12.16b
+	add	w8,w8,w9
+	eor	v28.16b,v19.16b,v16.16b
+	eor	w21,w21,w5
+	eor	v29.16b,v23.16b,v20.16b
+	eor	w17,w17,w6
+	ushr	v3.4s,v24.4s,#24
+	eor	w19,w19,w7
+	ushr	v7.4s,v25.4s,#24
+	eor	w20,w20,w8
+	ushr	v11.4s,v26.4s,#24
+	ror	w21,w21,#16
+	ushr	v15.4s,v27.4s,#24
+	ror	w17,w17,#16
+	ushr	v19.4s,v28.4s,#24
+	ror	w19,w19,#16
+	ushr	v23.4s,v29.4s,#24
+	ror	w20,w20,#16
+	sli	v3.4s,v24.4s,#8
+	add	w15,w15,w21
+	sli	v7.4s,v25.4s,#8
+	add	w16,w16,w17
+	sli	v11.4s,v26.4s,#8
+	add	w13,w13,w19
+	sli	v15.4s,v27.4s,#8
+	add	w14,w14,w20
+	sli	v19.4s,v28.4s,#8
+	eor	w10,w10,w15
+	sli	v23.4s,v29.4s,#8
+	eor	w11,w11,w16
+	add	v2.4s,v2.4s,v3.4s
+	eor	w12,w12,w13
+	add	v6.4s,v6.4s,v7.4s
+	eor	w9,w9,w14
+	add	v10.4s,v10.4s,v11.4s
+	ror	w10,w10,#20
+	add	v14.4s,v14.4s,v15.4s
+	ror	w11,w11,#20
+	add	v18.4s,v18.4s,v19.4s
+	ror	w12,w12,#20
+	add	v22.4s,v22.4s,v23.4s
+	ror	w9,w9,#20
+	eor	v24.16b,v1.16b,v2.16b
+	add	w5,w5,w10
+	eor	v25.16b,v5.16b,v6.16b
+	add	w6,w6,w11
+	eor	v26.16b,v9.16b,v10.16b
+	add	w7,w7,w12
+	eor	v27.16b,v13.16b,v14.16b
+	add	w8,w8,w9
+	eor	v28.16b,v17.16b,v18.16b
+	eor	w21,w21,w5
+	eor	v29.16b,v21.16b,v22.16b
+	eor	w17,w17,w6
+	ushr	v1.4s,v24.4s,#25
+	eor	w19,w19,w7
+	ushr	v5.4s,v25.4s,#25
+	eor	w20,w20,w8
+	ushr	v9.4s,v26.4s,#25
+	ror	w21,w21,#24
+	ushr	v13.4s,v27.4s,#25
+	ror	w17,w17,#24
+	ushr	v17.4s,v28.4s,#25
+	ror	w19,w19,#24
+	ushr	v21.4s,v29.4s,#25
+	ror	w20,w20,#24
+	sli	v1.4s,v24.4s,#7
+	add	w15,w15,w21
+	sli	v5.4s,v25.4s,#7
+	add	w16,w16,w17
+	sli	v9.4s,v26.4s,#7
+	add	w13,w13,w19
+	sli	v13.4s,v27.4s,#7
+	add	w14,w14,w20
+	sli	v17.4s,v28.4s,#7
+	eor	w10,w10,w15
+	sli	v21.4s,v29.4s,#7
+	eor	w11,w11,w16
+	ext	v2.16b,v2.16b,v2.16b,#8
+	eor	w12,w12,w13
+	ext	v6.16b,v6.16b,v6.16b,#8
+	eor	w9,w9,w14
+	ext	v10.16b,v10.16b,v10.16b,#8
+	ror	w10,w10,#25
+	ext	v14.16b,v14.16b,v14.16b,#8
+	ror	w11,w11,#25
+	ext	v18.16b,v18.16b,v18.16b,#8
+	ror	w12,w12,#25
+	ext	v22.16b,v22.16b,v22.16b,#8
+	ror	w9,w9,#25
+	ext	v3.16b,v3.16b,v3.16b,#4
+	ext	v7.16b,v7.16b,v7.16b,#4
+	ext	v11.16b,v11.16b,v11.16b,#4
+	ext	v15.16b,v15.16b,v15.16b,#4
+	ext	v19.16b,v19.16b,v19.16b,#4
+	ext	v23.16b,v23.16b,v23.16b,#4
+	ext	v1.16b,v1.16b,v1.16b,#12
+	ext	v5.16b,v5.16b,v5.16b,#12
+	ext	v9.16b,v9.16b,v9.16b,#12
+	ext	v13.16b,v13.16b,v13.16b,#12
+	ext	v17.16b,v17.16b,v17.16b,#12
+	ext	v21.16b,v21.16b,v21.16b,#12
+	cbnz	x4,.Loop_upper_neon
+
+	add	w5,w5,w22		// accumulate key block
+	add	x6,x6,x22,lsr#32
+	add	w7,w7,w23
+	add	x8,x8,x23,lsr#32
+	add	w9,w9,w24
+	add	x10,x10,x24,lsr#32
+	add	w11,w11,w25
+	add	x12,x12,x25,lsr#32
+	add	w13,w13,w26
+	add	x14,x14,x26,lsr#32
+	add	w15,w15,w27
+	add	x16,x16,x27,lsr#32
+	add	w17,w17,w28
+	add	x19,x19,x28,lsr#32
+	add	w20,w20,w30
+	add	x21,x21,x30,lsr#32
+
+	add	x5,x5,x6,lsl#32	// pack
+	add	x7,x7,x8,lsl#32
+	ldp	x6,x8,[x1,#0]		// load input
+	add	x9,x9,x10,lsl#32
+	add	x11,x11,x12,lsl#32
+	ldp	x10,x12,[x1,#16]
+	add	x13,x13,x14,lsl#32
+	add	x15,x15,x16,lsl#32
+	ldp	x14,x16,[x1,#32]
+	add	x17,x17,x19,lsl#32
+	add	x20,x20,x21,lsl#32
+	ldp	x19,x21,[x1,#48]
+	add	x1,x1,#64
+#ifdef	__ARMEB__
+	rev	x5,x5
+	rev	x7,x7
+	rev	x9,x9
+	rev	x11,x11
+	rev	x13,x13
+	rev	x15,x15
+	rev	x17,x17
+	rev	x20,x20
+#endif
+	eor	x5,x5,x6
+	eor	x7,x7,x8
+	eor	x9,x9,x10
+	eor	x11,x11,x12
+	eor	x13,x13,x14
+	eor	x15,x15,x16
+	eor	x17,x17,x19
+	eor	x20,x20,x21
+
+	stp	x5,x7,[x0,#0]		// store output
+	add	x28,x28,#1			// increment counter
+	mov	w5,w22			// unpack key block
+	lsr	x6,x22,#32
+	stp	x9,x11,[x0,#16]
+	mov	w7,w23
+	lsr	x8,x23,#32
+	stp	x13,x15,[x0,#32]
+	mov	w9,w24
+	lsr	x10,x24,#32
+	stp	x17,x20,[x0,#48]
+	add	x0,x0,#64
+	mov	w11,w25
+	lsr	x12,x25,#32
+	mov	w13,w26
+	lsr	x14,x26,#32
+	mov	w15,w27
+	lsr	x16,x27,#32
+	mov	w17,w28
+	lsr	x19,x28,#32
+	mov	w20,w30
+	lsr	x21,x30,#32
+
+	mov	x4,#5
+.Loop_lower_neon:
+	sub	x4,x4,#1
+	add	v0.4s,v0.4s,v1.4s
+	add	w5,w5,w9
+	add	v4.4s,v4.4s,v5.4s
+	add	w6,w6,w10
+	add	v8.4s,v8.4s,v9.4s
+	add	w7,w7,w11
+	add	v12.4s,v12.4s,v13.4s
+	add	w8,w8,w12
+	add	v16.4s,v16.4s,v17.4s
+	eor	w17,w17,w5
+	add	v20.4s,v20.4s,v21.4s
+	eor	w19,w19,w6
+	eor	v3.16b,v3.16b,v0.16b
+	eor	w20,w20,w7
+	eor	v7.16b,v7.16b,v4.16b
+	eor	w21,w21,w8
+	eor	v11.16b,v11.16b,v8.16b
+	ror	w17,w17,#16
+	eor	v15.16b,v15.16b,v12.16b
+	ror	w19,w19,#16
+	eor	v19.16b,v19.16b,v16.16b
+	ror	w20,w20,#16
+	eor	v23.16b,v23.16b,v20.16b
+	ror	w21,w21,#16
+	rev32	v3.8h,v3.8h
+	add	w13,w13,w17
+	rev32	v7.8h,v7.8h
+	add	w14,w14,w19
+	rev32	v11.8h,v11.8h
+	add	w15,w15,w20
+	rev32	v15.8h,v15.8h
+	add	w16,w16,w21
+	rev32	v19.8h,v19.8h
+	eor	w9,w9,w13
+	rev32	v23.8h,v23.8h
+	eor	w10,w10,w14
+	add	v2.4s,v2.4s,v3.4s
+	eor	w11,w11,w15
+	add	v6.4s,v6.4s,v7.4s
+	eor	w12,w12,w16
+	add	v10.4s,v10.4s,v11.4s
+	ror	w9,w9,#20
+	add	v14.4s,v14.4s,v15.4s
+	ror	w10,w10,#20
+	add	v18.4s,v18.4s,v19.4s
+	ror	w11,w11,#20
+	add	v22.4s,v22.4s,v23.4s
+	ror	w12,w12,#20
+	eor	v24.16b,v1.16b,v2.16b
+	add	w5,w5,w9
+	eor	v25.16b,v5.16b,v6.16b
+	add	w6,w6,w10
+	eor	v26.16b,v9.16b,v10.16b
+	add	w7,w7,w11
+	eor	v27.16b,v13.16b,v14.16b
+	add	w8,w8,w12
+	eor	v28.16b,v17.16b,v18.16b
+	eor	w17,w17,w5
+	eor	v29.16b,v21.16b,v22.16b
+	eor	w19,w19,w6
+	ushr	v1.4s,v24.4s,#20
+	eor	w20,w20,w7
+	ushr	v5.4s,v25.4s,#20
+	eor	w21,w21,w8
+	ushr	v9.4s,v26.4s,#20
+	ror	w17,w17,#24
+	ushr	v13.4s,v27.4s,#20
+	ror	w19,w19,#24
+	ushr	v17.4s,v28.4s,#20
+	ror	w20,w20,#24
+	ushr	v21.4s,v29.4s,#20
+	ror	w21,w21,#24
+	sli	v1.4s,v24.4s,#12
+	add	w13,w13,w17
+	sli	v5.4s,v25.4s,#12
+	add	w14,w14,w19
+	sli	v9.4s,v26.4s,#12
+	add	w15,w15,w20
+	sli	v13.4s,v27.4s,#12
+	add	w16,w16,w21
+	sli	v17.4s,v28.4s,#12
+	eor	w9,w9,w13
+	sli	v21.4s,v29.4s,#12
+	eor	w10,w10,w14
+	add	v0.4s,v0.4s,v1.4s
+	eor	w11,w11,w15
+	add	v4.4s,v4.4s,v5.4s
+	eor	w12,w12,w16
+	add	v8.4s,v8.4s,v9.4s
+	ror	w9,w9,#25
+	add	v12.4s,v12.4s,v13.4s
+	ror	w10,w10,#25
+	add	v16.4s,v16.4s,v17.4s
+	ror	w11,w11,#25
+	add	v20.4s,v20.4s,v21.4s
+	ror	w12,w12,#25
+	eor	v24.16b,v3.16b,v0.16b
+	add	w5,w5,w10
+	eor	v25.16b,v7.16b,v4.16b
+	add	w6,w6,w11
+	eor	v26.16b,v11.16b,v8.16b
+	add	w7,w7,w12
+	eor	v27.16b,v15.16b,v12.16b
+	add	w8,w8,w9
+	eor	v28.16b,v19.16b,v16.16b
+	eor	w21,w21,w5
+	eor	v29.16b,v23.16b,v20.16b
+	eor	w17,w17,w6
+	ushr	v3.4s,v24.4s,#24
+	eor	w19,w19,w7
+	ushr	v7.4s,v25.4s,#24
+	eor	w20,w20,w8
+	ushr	v11.4s,v26.4s,#24
+	ror	w21,w21,#16
+	ushr	v15.4s,v27.4s,#24
+	ror	w17,w17,#16
+	ushr	v19.4s,v28.4s,#24
+	ror	w19,w19,#16
+	ushr	v23.4s,v29.4s,#24
+	ror	w20,w20,#16
+	sli	v3.4s,v24.4s,#8
+	add	w15,w15,w21
+	sli	v7.4s,v25.4s,#8
+	add	w16,w16,w17
+	sli	v11.4s,v26.4s,#8
+	add	w13,w13,w19
+	sli	v15.4s,v27.4s,#8
+	add	w14,w14,w20
+	sli	v19.4s,v28.4s,#8
+	eor	w10,w10,w15
+	sli	v23.4s,v29.4s,#8
+	eor	w11,w11,w16
+	add	v2.4s,v2.4s,v3.4s
+	eor	w12,w12,w13
+	add	v6.4s,v6.4s,v7.4s
+	eor	w9,w9,w14
+	add	v10.4s,v10.4s,v11.4s
+	ror	w10,w10,#20
+	add	v14.4s,v14.4s,v15.4s
+	ror	w11,w11,#20
+	add	v18.4s,v18.4s,v19.4s
+	ror	w12,w12,#20
+	add	v22.4s,v22.4s,v23.4s
+	ror	w9,w9,#20
+	eor	v24.16b,v1.16b,v2.16b
+	add	w5,w5,w10
+	eor	v25.16b,v5.16b,v6.16b
+	add	w6,w6,w11
+	eor	v26.16b,v9.16b,v10.16b
+	add	w7,w7,w12
+	eor	v27.16b,v13.16b,v14.16b
+	add	w8,w8,w9
+	eor	v28.16b,v17.16b,v18.16b
+	eor	w21,w21,w5
+	eor	v29.16b,v21.16b,v22.16b
+	eor	w17,w17,w6
+	ushr	v1.4s,v24.4s,#25
+	eor	w19,w19,w7
+	ushr	v5.4s,v25.4s,#25
+	eor	w20,w20,w8
+	ushr	v9.4s,v26.4s,#25
+	ror	w21,w21,#24
+	ushr	v13.4s,v27.4s,#25
+	ror	w17,w17,#24
+	ushr	v17.4s,v28.4s,#25
+	ror	w19,w19,#24
+	ushr	v21.4s,v29.4s,#25
+	ror	w20,w20,#24
+	sli	v1.4s,v24.4s,#7
+	add	w15,w15,w21
+	sli	v5.4s,v25.4s,#7
+	add	w16,w16,w17
+	sli	v9.4s,v26.4s,#7
+	add	w13,w13,w19
+	sli	v13.4s,v27.4s,#7
+	add	w14,w14,w20
+	sli	v17.4s,v28.4s,#7
+	eor	w10,w10,w15
+	sli	v21.4s,v29.4s,#7
+	eor	w11,w11,w16
+	ext	v2.16b,v2.16b,v2.16b,#8
+	eor	w12,w12,w13
+	ext	v6.16b,v6.16b,v6.16b,#8
+	eor	w9,w9,w14
+	ext	v10.16b,v10.16b,v10.16b,#8
+	ror	w10,w10,#25
+	ext	v14.16b,v14.16b,v14.16b,#8
+	ror	w11,w11,#25
+	ext	v18.16b,v18.16b,v18.16b,#8
+	ror	w12,w12,#25
+	ext	v22.16b,v22.16b,v22.16b,#8
+	ror	w9,w9,#25
+	ext	v3.16b,v3.16b,v3.16b,#12
+	ext	v7.16b,v7.16b,v7.16b,#12
+	ext	v11.16b,v11.16b,v11.16b,#12
+	ext	v15.16b,v15.16b,v15.16b,#12
+	ext	v19.16b,v19.16b,v19.16b,#12
+	ext	v23.16b,v23.16b,v23.16b,#12
+	ext	v1.16b,v1.16b,v1.16b,#4
+	ext	v5.16b,v5.16b,v5.16b,#4
+	ext	v9.16b,v9.16b,v9.16b,#4
+	ext	v13.16b,v13.16b,v13.16b,#4
+	ext	v17.16b,v17.16b,v17.16b,#4
+	ext	v21.16b,v21.16b,v21.16b,#4
+	add	v0.4s,v0.4s,v1.4s
+	add	w5,w5,w9
+	add	v4.4s,v4.4s,v5.4s
+	add	w6,w6,w10
+	add	v8.4s,v8.4s,v9.4s
+	add	w7,w7,w11
+	add	v12.4s,v12.4s,v13.4s
+	add	w8,w8,w12
+	add	v16.4s,v16.4s,v17.4s
+	eor	w17,w17,w5
+	add	v20.4s,v20.4s,v21.4s
+	eor	w19,w19,w6
+	eor	v3.16b,v3.16b,v0.16b
+	eor	w20,w20,w7
+	eor	v7.16b,v7.16b,v4.16b
+	eor	w21,w21,w8
+	eor	v11.16b,v11.16b,v8.16b
+	ror	w17,w17,#16
+	eor	v15.16b,v15.16b,v12.16b
+	ror	w19,w19,#16
+	eor	v19.16b,v19.16b,v16.16b
+	ror	w20,w20,#16
+	eor	v23.16b,v23.16b,v20.16b
+	ror	w21,w21,#16
+	rev32	v3.8h,v3.8h
+	add	w13,w13,w17
+	rev32	v7.8h,v7.8h
+	add	w14,w14,w19
+	rev32	v11.8h,v11.8h
+	add	w15,w15,w20
+	rev32	v15.8h,v15.8h
+	add	w16,w16,w21
+	rev32	v19.8h,v19.8h
+	eor	w9,w9,w13
+	rev32	v23.8h,v23.8h
+	eor	w10,w10,w14
+	add	v2.4s,v2.4s,v3.4s
+	eor	w11,w11,w15
+	add	v6.4s,v6.4s,v7.4s
+	eor	w12,w12,w16
+	add	v10.4s,v10.4s,v11.4s
+	ror	w9,w9,#20
+	add	v14.4s,v14.4s,v15.4s
+	ror	w10,w10,#20
+	add	v18.4s,v18.4s,v19.4s
+	ror	w11,w11,#20
+	add	v22.4s,v22.4s,v23.4s
+	ror	w12,w12,#20
+	eor	v24.16b,v1.16b,v2.16b
+	add	w5,w5,w9
+	eor	v25.16b,v5.16b,v6.16b
+	add	w6,w6,w10
+	eor	v26.16b,v9.16b,v10.16b
+	add	w7,w7,w11
+	eor	v27.16b,v13.16b,v14.16b
+	add	w8,w8,w12
+	eor	v28.16b,v17.16b,v18.16b
+	eor	w17,w17,w5
+	eor	v29.16b,v21.16b,v22.16b
+	eor	w19,w19,w6
+	ushr	v1.4s,v24.4s,#20
+	eor	w20,w20,w7
+	ushr	v5.4s,v25.4s,#20
+	eor	w21,w21,w8
+	ushr	v9.4s,v26.4s,#20
+	ror	w17,w17,#24
+	ushr	v13.4s,v27.4s,#20
+	ror	w19,w19,#24
+	ushr	v17.4s,v28.4s,#20
+	ror	w20,w20,#24
+	ushr	v21.4s,v29.4s,#20
+	ror	w21,w21,#24
+	sli	v1.4s,v24.4s,#12
+	add	w13,w13,w17
+	sli	v5.4s,v25.4s,#12
+	add	w14,w14,w19
+	sli	v9.4s,v26.4s,#12
+	add	w15,w15,w20
+	sli	v13.4s,v27.4s,#12
+	add	w16,w16,w21
+	sli	v17.4s,v28.4s,#12
+	eor	w9,w9,w13
+	sli	v21.4s,v29.4s,#12
+	eor	w10,w10,w14
+	add	v0.4s,v0.4s,v1.4s
+	eor	w11,w11,w15
+	add	v4.4s,v4.4s,v5.4s
+	eor	w12,w12,w16
+	add	v8.4s,v8.4s,v9.4s
+	ror	w9,w9,#25
+	add	v12.4s,v12.4s,v13.4s
+	ror	w10,w10,#25
+	add	v16.4s,v16.4s,v17.4s
+	ror	w11,w11,#25
+	add	v20.4s,v20.4s,v21.4s
+	ror	w12,w12,#25
+	eor	v24.16b,v3.16b,v0.16b
+	add	w5,w5,w10
+	eor	v25.16b,v7.16b,v4.16b
+	add	w6,w6,w11
+	eor	v26.16b,v11.16b,v8.16b
+	add	w7,w7,w12
+	eor	v27.16b,v15.16b,v12.16b
+	add	w8,w8,w9
+	eor	v28.16b,v19.16b,v16.16b
+	eor	w21,w21,w5
+	eor	v29.16b,v23.16b,v20.16b
+	eor	w17,w17,w6
+	ushr	v3.4s,v24.4s,#24
+	eor	w19,w19,w7
+	ushr	v7.4s,v25.4s,#24
+	eor	w20,w20,w8
+	ushr	v11.4s,v26.4s,#24
+	ror	w21,w21,#16
+	ushr	v15.4s,v27.4s,#24
+	ror	w17,w17,#16
+	ushr	v19.4s,v28.4s,#24
+	ror	w19,w19,#16
+	ushr	v23.4s,v29.4s,#24
+	ror	w20,w20,#16
+	sli	v3.4s,v24.4s,#8
+	add	w15,w15,w21
+	sli	v7.4s,v25.4s,#8
+	add	w16,w16,w17
+	sli	v11.4s,v26.4s,#8
+	add	w13,w13,w19
+	sli	v15.4s,v27.4s,#8
+	add	w14,w14,w20
+	sli	v19.4s,v28.4s,#8
+	eor	w10,w10,w15
+	sli	v23.4s,v29.4s,#8
+	eor	w11,w11,w16
+	add	v2.4s,v2.4s,v3.4s
+	eor	w12,w12,w13
+	add	v6.4s,v6.4s,v7.4s
+	eor	w9,w9,w14
+	add	v10.4s,v10.4s,v11.4s
+	ror	w10,w10,#20
+	add	v14.4s,v14.4s,v15.4s
+	ror	w11,w11,#20
+	add	v18.4s,v18.4s,v19.4s
+	ror	w12,w12,#20
+	add	v22.4s,v22.4s,v23.4s
+	ror	w9,w9,#20
+	eor	v24.16b,v1.16b,v2.16b
+	add	w5,w5,w10
+	eor	v25.16b,v5.16b,v6.16b
+	add	w6,w6,w11
+	eor	v26.16b,v9.16b,v10.16b
+	add	w7,w7,w12
+	eor	v27.16b,v13.16b,v14.16b
+	add	w8,w8,w9
+	eor	v28.16b,v17.16b,v18.16b
+	eor	w21,w21,w5
+	eor	v29.16b,v21.16b,v22.16b
+	eor	w17,w17,w6
+	ushr	v1.4s,v24.4s,#25
+	eor	w19,w19,w7
+	ushr	v5.4s,v25.4s,#25
+	eor	w20,w20,w8
+	ushr	v9.4s,v26.4s,#25
+	ror	w21,w21,#24
+	ushr	v13.4s,v27.4s,#25
+	ror	w17,w17,#24
+	ushr	v17.4s,v28.4s,#25
+	ror	w19,w19,#24
+	ushr	v21.4s,v29.4s,#25
+	ror	w20,w20,#24
+	sli	v1.4s,v24.4s,#7
+	add	w15,w15,w21
+	sli	v5.4s,v25.4s,#7
+	add	w16,w16,w17
+	sli	v9.4s,v26.4s,#7
+	add	w13,w13,w19
+	sli	v13.4s,v27.4s,#7
+	add	w14,w14,w20
+	sli	v17.4s,v28.4s,#7
+	eor	w10,w10,w15
+	sli	v21.4s,v29.4s,#7
+	eor	w11,w11,w16
+	ext	v2.16b,v2.16b,v2.16b,#8
+	eor	w12,w12,w13
+	ext	v6.16b,v6.16b,v6.16b,#8
+	eor	w9,w9,w14
+	ext	v10.16b,v10.16b,v10.16b,#8
+	ror	w10,w10,#25
+	ext	v14.16b,v14.16b,v14.16b,#8
+	ror	w11,w11,#25
+	ext	v18.16b,v18.16b,v18.16b,#8
+	ror	w12,w12,#25
+	ext	v22.16b,v22.16b,v22.16b,#8
+	ror	w9,w9,#25
+	ext	v3.16b,v3.16b,v3.16b,#4
+	ext	v7.16b,v7.16b,v7.16b,#4
+	ext	v11.16b,v11.16b,v11.16b,#4
+	ext	v15.16b,v15.16b,v15.16b,#4
+	ext	v19.16b,v19.16b,v19.16b,#4
+	ext	v23.16b,v23.16b,v23.16b,#4
+	ext	v1.16b,v1.16b,v1.16b,#12
+	ext	v5.16b,v5.16b,v5.16b,#12
+	ext	v9.16b,v9.16b,v9.16b,#12
+	ext	v13.16b,v13.16b,v13.16b,#12
+	ext	v17.16b,v17.16b,v17.16b,#12
+	ext	v21.16b,v21.16b,v21.16b,#12
+	cbnz	x4,.Loop_lower_neon
+
+	add	w5,w5,w22		// accumulate key block
+	ldp	q24,q25,[sp,#0]
+	add	x6,x6,x22,lsr#32
+	ldp	q26,q27,[sp,#32]
+	add	w7,w7,w23
+	ldp	q28,q29,[sp,#64]
+	add	x8,x8,x23,lsr#32
+	add	v0.4s,v0.4s,v24.4s
+	add	w9,w9,w24
+	add	v4.4s,v4.4s,v24.4s
+	add	x10,x10,x24,lsr#32
+	add	v8.4s,v8.4s,v24.4s
+	add	w11,w11,w25
+	add	v12.4s,v12.4s,v24.4s
+	add	x12,x12,x25,lsr#32
+	add	v16.4s,v16.4s,v24.4s
+	add	w13,w13,w26
+	add	v20.4s,v20.4s,v24.4s
+	add	x14,x14,x26,lsr#32
+	add	v2.4s,v2.4s,v26.4s
+	add	w15,w15,w27
+	add	v6.4s,v6.4s,v26.4s
+	add	x16,x16,x27,lsr#32
+	add	v10.4s,v10.4s,v26.4s
+	add	w17,w17,w28
+	add	v14.4s,v14.4s,v26.4s
+	add	x19,x19,x28,lsr#32
+	add	v18.4s,v18.4s,v26.4s
+	add	w20,w20,w30
+	add	v22.4s,v22.4s,v26.4s
+	add	x21,x21,x30,lsr#32
+	add	v19.4s,v19.4s,v31.4s			// +4
+	add	x5,x5,x6,lsl#32	// pack
+	add	v23.4s,v23.4s,v31.4s			// +4
+	add	x7,x7,x8,lsl#32
+	add	v3.4s,v3.4s,v27.4s
+	ldp	x6,x8,[x1,#0]		// load input
+	add	v7.4s,v7.4s,v28.4s
+	add	x9,x9,x10,lsl#32
+	add	v11.4s,v11.4s,v29.4s
+	add	x11,x11,x12,lsl#32
+	add	v15.4s,v15.4s,v30.4s
+	ldp	x10,x12,[x1,#16]
+	add	v19.4s,v19.4s,v27.4s
+	add	x13,x13,x14,lsl#32
+	add	v23.4s,v23.4s,v28.4s
+	add	x15,x15,x16,lsl#32
+	add	v1.4s,v1.4s,v25.4s
+	ldp	x14,x16,[x1,#32]
+	add	v5.4s,v5.4s,v25.4s
+	add	x17,x17,x19,lsl#32
+	add	v9.4s,v9.4s,v25.4s
+	add	x20,x20,x21,lsl#32
+	add	v13.4s,v13.4s,v25.4s
+	ldp	x19,x21,[x1,#48]
+	add	v17.4s,v17.4s,v25.4s
+	add	x1,x1,#64
+	add	v21.4s,v21.4s,v25.4s
+
+#ifdef	__ARMEB__
+	rev	x5,x5
+	rev	x7,x7
+	rev	x9,x9
+	rev	x11,x11
+	rev	x13,x13
+	rev	x15,x15
+	rev	x17,x17
+	rev	x20,x20
+#endif
+	ld1	{v24.16b,v25.16b,v26.16b,v27.16b},[x1],#64
+	eor	x5,x5,x6
+	eor	x7,x7,x8
+	eor	x9,x9,x10
+	eor	x11,x11,x12
+	eor	x13,x13,x14
+	eor	v0.16b,v0.16b,v24.16b
+	eor	x15,x15,x16
+	eor	v1.16b,v1.16b,v25.16b
+	eor	x17,x17,x19
+	eor	v2.16b,v2.16b,v26.16b
+	eor	x20,x20,x21
+	eor	v3.16b,v3.16b,v27.16b
+	ld1	{v24.16b,v25.16b,v26.16b,v27.16b},[x1],#64
+
+	stp	x5,x7,[x0,#0]		// store output
+	add	x28,x28,#7			// increment counter
+	stp	x9,x11,[x0,#16]
+	stp	x13,x15,[x0,#32]
+	stp	x17,x20,[x0,#48]
+	add	x0,x0,#64
+	st1	{v0.16b,v1.16b,v2.16b,v3.16b},[x0],#64
+
+	ld1	{v0.16b,v1.16b,v2.16b,v3.16b},[x1],#64
+	eor	v4.16b,v4.16b,v24.16b
+	eor	v5.16b,v5.16b,v25.16b
+	eor	v6.16b,v6.16b,v26.16b
+	eor	v7.16b,v7.16b,v27.16b
+	st1	{v4.16b,v5.16b,v6.16b,v7.16b},[x0],#64
+
+	ld1	{v4.16b,v5.16b,v6.16b,v7.16b},[x1],#64
+	eor	v8.16b,v8.16b,v0.16b
+	ldp	q24,q25,[sp,#0]
+	eor	v9.16b,v9.16b,v1.16b
+	ldp	q26,q27,[sp,#32]
+	eor	v10.16b,v10.16b,v2.16b
+	eor	v11.16b,v11.16b,v3.16b
+	st1	{v8.16b,v9.16b,v10.16b,v11.16b},[x0],#64
+
+	ld1	{v8.16b,v9.16b,v10.16b,v11.16b},[x1],#64
+	eor	v12.16b,v12.16b,v4.16b
+	eor	v13.16b,v13.16b,v5.16b
+	eor	v14.16b,v14.16b,v6.16b
+	eor	v15.16b,v15.16b,v7.16b
+	st1	{v12.16b,v13.16b,v14.16b,v15.16b},[x0],#64
+
+	ld1	{v12.16b,v13.16b,v14.16b,v15.16b},[x1],#64
+	eor	v16.16b,v16.16b,v8.16b
+	eor	v17.16b,v17.16b,v9.16b
+	eor	v18.16b,v18.16b,v10.16b
+	eor	v19.16b,v19.16b,v11.16b
+	st1	{v16.16b,v17.16b,v18.16b,v19.16b},[x0],#64
+
+	shl	v0.4s,v31.4s,#1			// 4 -> 8
+	eor	v20.16b,v20.16b,v12.16b
+	eor	v21.16b,v21.16b,v13.16b
+	eor	v22.16b,v22.16b,v14.16b
+	eor	v23.16b,v23.16b,v15.16b
+	st1	{v20.16b,v21.16b,v22.16b,v23.16b},[x0],#64
+
+	add	v27.4s,v27.4s,v0.4s			// += 8
+	add	v28.4s,v28.4s,v0.4s
+	add	v29.4s,v29.4s,v0.4s
+	add	v30.4s,v30.4s,v0.4s
+
+	b.hs	.Loop_outer_512_neon
+
+	adds	x2,x2,#512
+	ushr	v0.4s,v31.4s,#2			// 4 -> 1
+
+	ldp	d8,d9,[sp,#128+0]		// meet ABI requirements
+	ldp	d10,d11,[sp,#128+16]
+	ldp	d12,d13,[sp,#128+32]
+	ldp	d14,d15,[sp,#128+48]
+
+	stp	q24,q31,[sp,#0]		// wipe off-load area
+	stp	q24,q31,[sp,#32]
+	stp	q24,q31,[sp,#64]
+
+	b.eq	.Ldone_512_neon
+
+	cmp	x2,#192
+	sub	v27.4s,v27.4s,v0.4s			// -= 1
+	sub	v28.4s,v28.4s,v0.4s
+	sub	v29.4s,v29.4s,v0.4s
+	add	sp,sp,#128
+	b.hs	.Loop_outer_neon
+
+	eor	v25.16b,v25.16b,v25.16b
+	eor	v26.16b,v26.16b,v26.16b
+	eor	v27.16b,v27.16b,v27.16b
+	eor	v28.16b,v28.16b,v28.16b
+	eor	v29.16b,v29.16b,v29.16b
+	eor	v30.16b,v30.16b,v30.16b
+	b	.Loop_outer
+
+.Ldone_512_neon:
+	ldp	x19,x20,[x29,#16]
+	add	sp,sp,#128+64
+	ldp	x21,x22,[x29,#32]
+	ldp	x23,x24,[x29,#48]
+	ldp	x25,x26,[x29,#64]
+	ldp	x27,x28,[x29,#80]
+	ldp	x29,x30,[sp],#96
+	ret
+.size	ChaCha20_512_neon,.-ChaCha20_512_neon
+#endif
diff --git a/linux-aarch64/crypto/modes/ghashv8-armx64.S b/linux-aarch64/crypto/modes/ghashv8-armx64.S
index 8d44667..89d780f 100644
--- a/linux-aarch64/crypto/modes/ghashv8-armx64.S
+++ b/linux-aarch64/crypto/modes/ghashv8-armx64.S
@@ -2,10 +2,11 @@
 #include <openssl/arm_arch.h>
 
 .text
-#if !defined(__clang__)
+#if !defined(__clang__) || defined(BORINGSSL_CLANG_SUPPORTS_DOT_ARCH)
 .arch	armv8-a+crypto
 #endif
 .globl	gcm_init_v8
+.hidden	gcm_init_v8
 .type	gcm_init_v8,%function
 .align	4
 gcm_init_v8:
@@ -56,6 +57,7 @@
 	ret
 .size	gcm_init_v8,.-gcm_init_v8
 .globl	gcm_gmult_v8
+.hidden	gcm_gmult_v8
 .type	gcm_gmult_v8,%function
 .align	4
 gcm_gmult_v8:
@@ -97,6 +99,7 @@
 	ret
 .size	gcm_gmult_v8,.-gcm_gmult_v8
 .globl	gcm_ghash_v8
+.hidden	gcm_ghash_v8
 .type	gcm_ghash_v8,%function
 .align	4
 gcm_ghash_v8:
@@ -229,4 +232,4 @@
 .byte	71,72,65,83,72,32,102,111,114,32,65,82,77,118,56,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
 .align	2
 .align	2
-#endif
\ No newline at end of file
+#endif
diff --git a/linux-aarch64/crypto/sha/sha1-armv8.S b/linux-aarch64/crypto/sha/sha1-armv8.S
index 6cf9877..cfb4aa0 100644
--- a/linux-aarch64/crypto/sha/sha1-armv8.S
+++ b/linux-aarch64/crypto/sha/sha1-armv8.S
@@ -5,6 +5,7 @@
 
 
 .globl	sha1_block_data_order
+.hidden	sha1_block_data_order
 .type	sha1_block_data_order,%function
 .align	6
 sha1_block_data_order:
@@ -1212,4 +1213,4 @@
 .align	2
 .align	2
 .comm	OPENSSL_armcap_P,4,4
-#endif
\ No newline at end of file
+#endif
diff --git a/linux-aarch64/crypto/sha/sha256-armv8.S b/linux-aarch64/crypto/sha/sha256-armv8.S
index 0fad009..bfc552c 100644
--- a/linux-aarch64/crypto/sha/sha256-armv8.S
+++ b/linux-aarch64/crypto/sha/sha256-armv8.S
@@ -5,6 +5,7 @@
 
 
 .globl	sha256_block_data_order
+.hidden	sha256_block_data_order
 .type	sha256_block_data_order,%function
 .align	6
 sha256_block_data_order:
@@ -1142,4 +1143,4 @@
 	ret
 .size	sha256_block_armv8,.-sha256_block_armv8
 .comm	OPENSSL_armcap_P,4,4
-#endif
\ No newline at end of file
+#endif
diff --git a/linux-aarch64/crypto/sha/sha512-armv8.S b/linux-aarch64/crypto/sha/sha512-armv8.S
index 517c033..4645722 100644
--- a/linux-aarch64/crypto/sha/sha512-armv8.S
+++ b/linux-aarch64/crypto/sha/sha512-armv8.S
@@ -5,6 +5,7 @@
 
 
 .globl	sha512_block_data_order
+.hidden	sha512_block_data_order
 .type	sha512_block_data_order,%function
 .align	6
 sha512_block_data_order:
@@ -1022,4 +1023,4 @@
 .align	2
 .align	2
 .comm	OPENSSL_armcap_P,4,4
-#endif
\ No newline at end of file
+#endif
diff --git a/linux-arm/crypto/aes/aes-armv4.S b/linux-arm/crypto/aes/aes-armv4.S
index c4d7065..bc11e3f 100644
--- a/linux-arm/crypto/aes/aes-armv4.S
+++ b/linux-arm/crypto/aes/aes-armv4.S
@@ -1197,4 +1197,4 @@
 .align	2
 
 #endif
-#endif
\ No newline at end of file
+#endif
diff --git a/linux-arm/crypto/aes/aesv8-armx32.S b/linux-arm/crypto/aes/aesv8-armx32.S
index 6012b0c..c2f6b68 100644
--- a/linux-arm/crypto/aes/aesv8-armx32.S
+++ b/linux-arm/crypto/aes/aesv8-armx32.S
@@ -12,10 +12,11 @@
 .long	0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d,0x0c0f0e0d	@ rotate-n-splat
 .long	0x1b,0x1b,0x1b,0x1b
 
-.globl	aes_v8_set_encrypt_key
-.type	aes_v8_set_encrypt_key,%function
+.globl	aes_hw_set_encrypt_key
+.hidden	aes_hw_set_encrypt_key
+.type	aes_hw_set_encrypt_key,%function
 .align	5
-aes_v8_set_encrypt_key:
+aes_hw_set_encrypt_key:
 .Lenc_key:
 	mov	r3,#-1
 	cmp	r0,#0
@@ -180,12 +181,13 @@
 	mov	r0,r3			@ return value
 
 	bx	lr
-.size	aes_v8_set_encrypt_key,.-aes_v8_set_encrypt_key
+.size	aes_hw_set_encrypt_key,.-aes_hw_set_encrypt_key
 
-.globl	aes_v8_set_decrypt_key
-.type	aes_v8_set_decrypt_key,%function
+.globl	aes_hw_set_decrypt_key
+.hidden	aes_hw_set_decrypt_key
+.type	aes_hw_set_decrypt_key,%function
 .align	5
-aes_v8_set_decrypt_key:
+aes_hw_set_decrypt_key:
 	stmdb	sp!,{r4,lr}
 	bl	.Lenc_key
 
@@ -218,11 +220,12 @@
 	eor	r0,r0,r0		@ return value
 .Ldec_key_abort:
 	ldmia	sp!,{r4,pc}
-.size	aes_v8_set_decrypt_key,.-aes_v8_set_decrypt_key
-.globl	aes_v8_encrypt
-.type	aes_v8_encrypt,%function
+.size	aes_hw_set_decrypt_key,.-aes_hw_set_decrypt_key
+.globl	aes_hw_encrypt
+.hidden	aes_hw_encrypt
+.type	aes_hw_encrypt,%function
 .align	5
-aes_v8_encrypt:
+aes_hw_encrypt:
 	ldr	r3,[r2,#240]
 	vld1.32	{q0},[r2]!
 	vld1.8	{q2},[r0]
@@ -247,11 +250,12 @@
 
 	vst1.8	{q2},[r1]
 	bx	lr
-.size	aes_v8_encrypt,.-aes_v8_encrypt
-.globl	aes_v8_decrypt
-.type	aes_v8_decrypt,%function
+.size	aes_hw_encrypt,.-aes_hw_encrypt
+.globl	aes_hw_decrypt
+.hidden	aes_hw_decrypt
+.type	aes_hw_decrypt,%function
 .align	5
-aes_v8_decrypt:
+aes_hw_decrypt:
 	ldr	r3,[r2,#240]
 	vld1.32	{q0},[r2]!
 	vld1.8	{q2},[r0]
@@ -276,11 +280,12 @@
 
 	vst1.8	{q2},[r1]
 	bx	lr
-.size	aes_v8_decrypt,.-aes_v8_decrypt
-.globl	aes_v8_cbc_encrypt
-.type	aes_v8_cbc_encrypt,%function
+.size	aes_hw_decrypt,.-aes_hw_decrypt
+.globl	aes_hw_cbc_encrypt
+.hidden	aes_hw_cbc_encrypt
+.type	aes_hw_cbc_encrypt,%function
 .align	5
-aes_v8_cbc_encrypt:
+aes_hw_cbc_encrypt:
 	mov	ip,sp
 	stmdb	sp!,{r4,r5,r6,r7,r8,lr}
 	vstmdb	sp!,{d8,d9,d10,d11,d12,d13,d14,d15}            @ ABI specification says so
@@ -568,11 +573,12 @@
 .Lcbc_abort:
 	vldmia	sp!,{d8,d9,d10,d11,d12,d13,d14,d15}
 	ldmia	sp!,{r4,r5,r6,r7,r8,pc}
-.size	aes_v8_cbc_encrypt,.-aes_v8_cbc_encrypt
-.globl	aes_v8_ctr32_encrypt_blocks
-.type	aes_v8_ctr32_encrypt_blocks,%function
+.size	aes_hw_cbc_encrypt,.-aes_hw_cbc_encrypt
+.globl	aes_hw_ctr32_encrypt_blocks
+.hidden	aes_hw_ctr32_encrypt_blocks
+.type	aes_hw_ctr32_encrypt_blocks,%function
 .align	5
-aes_v8_ctr32_encrypt_blocks:
+aes_hw_ctr32_encrypt_blocks:
 	mov	ip,sp
 	stmdb	sp!,{r4,r5,r6,r7,r8,r9,r10,lr}
 	vstmdb	sp!,{d8,d9,d10,d11,d12,d13,d14,d15}            @ ABI specification says so
@@ -751,6 +757,6 @@
 .Lctr32_done:
 	vldmia	sp!,{d8,d9,d10,d11,d12,d13,d14,d15}
 	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,pc}
-.size	aes_v8_ctr32_encrypt_blocks,.-aes_v8_ctr32_encrypt_blocks
+.size	aes_hw_ctr32_encrypt_blocks,.-aes_hw_ctr32_encrypt_blocks
 #endif
-#endif
\ No newline at end of file
+#endif
diff --git a/linux-arm/crypto/aes/bsaes-armv7.S b/linux-arm/crypto/aes/bsaes-armv7.S
index a3ebec8..1db7bbe 100644
--- a/linux-arm/crypto/aes/bsaes-armv7.S
+++ b/linux-arm/crypto/aes/bsaes-armv7.S
@@ -1843,8 +1843,6 @@
 	b	.Lxts_enc_done
 .align	4
 .Lxts_enc_6:
-	vst1.64	{q14}, [r0,:128]		@ next round tweak
-
 	veor	q4, q4, q12
 #ifndef	BSAES_ASM_EXTENDED_KEY
 	add	r4, sp, #0x90			@ pass key schedule
@@ -1880,8 +1878,6 @@
 
 .align	5
 .Lxts_enc_5:
-	vst1.64	{q13}, [r0,:128]		@ next round tweak
-
 	veor	q3, q3, q11
 #ifndef	BSAES_ASM_EXTENDED_KEY
 	add	r4, sp, #0x90			@ pass key schedule
@@ -1910,8 +1906,6 @@
 	b	.Lxts_enc_done
 .align	4
 .Lxts_enc_4:
-	vst1.64	{q12}, [r0,:128]		@ next round tweak
-
 	veor	q2, q2, q10
 #ifndef	BSAES_ASM_EXTENDED_KEY
 	add	r4, sp, #0x90			@ pass key schedule
@@ -1937,8 +1931,6 @@
 	b	.Lxts_enc_done
 .align	4
 .Lxts_enc_3:
-	vst1.64	{q11}, [r0,:128]		@ next round tweak
-
 	veor	q1, q1, q9
 #ifndef	BSAES_ASM_EXTENDED_KEY
 	add	r4, sp, #0x90			@ pass key schedule
@@ -1963,8 +1955,6 @@
 	b	.Lxts_enc_done
 .align	4
 .Lxts_enc_2:
-	vst1.64	{q10}, [r0,:128]		@ next round tweak
-
 	veor	q0, q0, q8
 #ifndef	BSAES_ASM_EXTENDED_KEY
 	add	r4, sp, #0x90			@ pass key schedule
@@ -1987,7 +1977,7 @@
 .align	4
 .Lxts_enc_1:
 	mov	r0, sp
-	veor	q0, q8
+	veor	q0, q0, q8
 	mov	r1, sp
 	vst1.8	{q0}, [sp,:128]
 	mov	r2, r10
@@ -2376,8 +2366,6 @@
 	b	.Lxts_dec_done
 .align	4
 .Lxts_dec_5:
-	vst1.64	{q13}, [r0,:128]		@ next round tweak
-
 	veor	q3, q3, q11
 #ifndef	BSAES_ASM_EXTENDED_KEY
 	add	r4, sp, #0x90			@ pass key schedule
@@ -2406,8 +2394,6 @@
 	b	.Lxts_dec_done
 .align	4
 .Lxts_dec_4:
-	vst1.64	{q12}, [r0,:128]		@ next round tweak
-
 	veor	q2, q2, q10
 #ifndef	BSAES_ASM_EXTENDED_KEY
 	add	r4, sp, #0x90			@ pass key schedule
@@ -2433,8 +2419,6 @@
 	b	.Lxts_dec_done
 .align	4
 .Lxts_dec_3:
-	vst1.64	{q11}, [r0,:128]		@ next round tweak
-
 	veor	q1, q1, q9
 #ifndef	BSAES_ASM_EXTENDED_KEY
 	add	r4, sp, #0x90			@ pass key schedule
@@ -2459,8 +2443,6 @@
 	b	.Lxts_dec_done
 .align	4
 .Lxts_dec_2:
-	vst1.64	{q10}, [r0,:128]		@ next round tweak
-
 	veor	q0, q0, q8
 #ifndef	BSAES_ASM_EXTENDED_KEY
 	add	r4, sp, #0x90			@ pass key schedule
@@ -2483,12 +2465,12 @@
 .align	4
 .Lxts_dec_1:
 	mov	r0, sp
-	veor	q0, q8
+	veor	q0, q0, q8
 	mov	r1, sp
 	vst1.8	{q0}, [sp,:128]
+	mov	r5, r2			@ preserve magic
 	mov	r2, r10
 	mov	r4, r3				@ preserve fp
-	mov	r5, r2			@ preserve magic
 
 	bl	AES_decrypt
 
@@ -2574,4 +2556,4 @@
 
 .size	bsaes_xts_decrypt,.-bsaes_xts_decrypt
 #endif
-#endif
\ No newline at end of file
+#endif
diff --git a/linux-arm/crypto/bn/armv4-mont.S b/linux-arm/crypto/bn/armv4-mont.S
index fc671e8..e59599f 100644
--- a/linux-arm/crypto/bn/armv4-mont.S
+++ b/linux-arm/crypto/bn/armv4-mont.S
@@ -28,7 +28,7 @@
 #ifdef	__APPLE__
 	ldr	r0,[r0]
 #endif
-	tst	r0,#1			@ NEON available?
+	tst	r0,#ARMV7_NEON		@ NEON available?
 	ldmia	sp, {r0,r2}
 	beq	.Lialu
 	add	sp,sp,#8
@@ -586,4 +586,4 @@
 .comm	OPENSSL_armcap_P,4,4
 .hidden	OPENSSL_armcap_P
 #endif
-#endif
\ No newline at end of file
+#endif
diff --git a/linux-arm/crypto/chacha/chacha-armv4.S b/linux-arm/crypto/chacha/chacha-armv4.S
new file mode 100644
index 0000000..0784fc7
--- /dev/null
+++ b/linux-arm/crypto/chacha/chacha-armv4.S
@@ -0,0 +1,1471 @@
+#if defined(__arm__)
+#include <openssl/arm_arch.h>
+
+.text
+#if defined(__thumb2__)
+.syntax	unified
+.thumb
+#else
+.code	32
+#endif
+
+#if defined(__thumb2__) || defined(__clang__)
+#define ldrhsb	ldrbhs
+#endif
+
+.align	5
+.Lsigma:
+.long	0x61707865,0x3320646e,0x79622d32,0x6b206574	@ endian-neutral
+.Lone:
+.long	1,0,0,0
+#if __ARM_MAX_ARCH__>=7
+.LOPENSSL_armcap:
+.word	OPENSSL_armcap_P-.LChaCha20_ctr32
+#else
+.word	-1
+#endif
+
+.globl	ChaCha20_ctr32
+.hidden	ChaCha20_ctr32
+.type	ChaCha20_ctr32,%function
+.align	5
+ChaCha20_ctr32:
+.LChaCha20_ctr32:
+	ldr	r12,[sp,#0]		@ pull pointer to counter and nonce
+	stmdb	sp!,{r0,r1,r2,r4-r11,lr}
+#if __ARM_ARCH__<7 && !defined(__thumb2__)
+	sub	r14,pc,#16		@ ChaCha20_ctr32
+#else
+	adr	r14,.LChaCha20_ctr32
+#endif
+	cmp	r2,#0			@ len==0?
+#ifdef	__thumb2__
+	itt	eq
+#endif
+	addeq	sp,sp,#4*3
+	beq	.Lno_data
+#if __ARM_MAX_ARCH__>=7
+	cmp	r2,#192			@ test len
+	bls	.Lshort
+	ldr	r4,[r14,#-32]
+	ldr	r4,[r14,r4]
+# ifdef	__APPLE__
+	ldr	r4,[r4]
+# endif
+	tst	r4,#ARMV7_NEON
+	bne	.LChaCha20_neon
+.Lshort:
+#endif
+	ldmia	r12,{r4,r5,r6,r7}		@ load counter and nonce
+	sub	sp,sp,#4*(16)		@ off-load area
+	sub	r14,r14,#64		@ .Lsigma
+	stmdb	sp!,{r4,r5,r6,r7}		@ copy counter and nonce
+	ldmia	r3,{r4,r5,r6,r7,r8,r9,r10,r11}		@ load key
+	ldmia	r14,{r0,r1,r2,r3}		@ load sigma
+	stmdb	sp!,{r4,r5,r6,r7,r8,r9,r10,r11}		@ copy key
+	stmdb	sp!,{r0,r1,r2,r3}		@ copy sigma
+	str	r10,[sp,#4*(16+10)]	@ off-load "rx"
+	str	r11,[sp,#4*(16+11)]	@ off-load "rx"
+	b	.Loop_outer_enter
+
+.align	4
+.Loop_outer:
+	ldmia	sp,{r0,r1,r2,r3,r4,r5,r6,r7,r8,r9}		@ load key material
+	str	r11,[sp,#4*(32+2)]	@ save len
+	str	r12,  [sp,#4*(32+1)]	@ save inp
+	str	r14,  [sp,#4*(32+0)]	@ save out
+.Loop_outer_enter:
+	ldr	r11, [sp,#4*(15)]
+	ldr	r12,[sp,#4*(12)]	@ modulo-scheduled load
+	ldr	r10, [sp,#4*(13)]
+	ldr	r14,[sp,#4*(14)]
+	str	r11, [sp,#4*(16+15)]
+	mov	r11,#10
+	b	.Loop
+
+.align	4
+.Loop:
+	subs	r11,r11,#1
+	add	r0,r0,r4
+	mov	r12,r12,ror#16
+	add	r1,r1,r5
+	mov	r10,r10,ror#16
+	eor	r12,r12,r0,ror#16
+	eor	r10,r10,r1,ror#16
+	add	r8,r8,r12
+	mov	r4,r4,ror#20
+	add	r9,r9,r10
+	mov	r5,r5,ror#20
+	eor	r4,r4,r8,ror#20
+	eor	r5,r5,r9,ror#20
+	add	r0,r0,r4
+	mov	r12,r12,ror#24
+	add	r1,r1,r5
+	mov	r10,r10,ror#24
+	eor	r12,r12,r0,ror#24
+	eor	r10,r10,r1,ror#24
+	add	r8,r8,r12
+	mov	r4,r4,ror#25
+	add	r9,r9,r10
+	mov	r5,r5,ror#25
+	str	r10,[sp,#4*(16+13)]
+	ldr	r10,[sp,#4*(16+15)]
+	eor	r4,r4,r8,ror#25
+	eor	r5,r5,r9,ror#25
+	str	r8,[sp,#4*(16+8)]
+	ldr	r8,[sp,#4*(16+10)]
+	add	r2,r2,r6
+	mov	r14,r14,ror#16
+	str	r9,[sp,#4*(16+9)]
+	ldr	r9,[sp,#4*(16+11)]
+	add	r3,r3,r7
+	mov	r10,r10,ror#16
+	eor	r14,r14,r2,ror#16
+	eor	r10,r10,r3,ror#16
+	add	r8,r8,r14
+	mov	r6,r6,ror#20
+	add	r9,r9,r10
+	mov	r7,r7,ror#20
+	eor	r6,r6,r8,ror#20
+	eor	r7,r7,r9,ror#20
+	add	r2,r2,r6
+	mov	r14,r14,ror#24
+	add	r3,r3,r7
+	mov	r10,r10,ror#24
+	eor	r14,r14,r2,ror#24
+	eor	r10,r10,r3,ror#24
+	add	r8,r8,r14
+	mov	r6,r6,ror#25
+	add	r9,r9,r10
+	mov	r7,r7,ror#25
+	eor	r6,r6,r8,ror#25
+	eor	r7,r7,r9,ror#25
+	add	r0,r0,r5
+	mov	r10,r10,ror#16
+	add	r1,r1,r6
+	mov	r12,r12,ror#16
+	eor	r10,r10,r0,ror#16
+	eor	r12,r12,r1,ror#16
+	add	r8,r8,r10
+	mov	r5,r5,ror#20
+	add	r9,r9,r12
+	mov	r6,r6,ror#20
+	eor	r5,r5,r8,ror#20
+	eor	r6,r6,r9,ror#20
+	add	r0,r0,r5
+	mov	r10,r10,ror#24
+	add	r1,r1,r6
+	mov	r12,r12,ror#24
+	eor	r10,r10,r0,ror#24
+	eor	r12,r12,r1,ror#24
+	add	r8,r8,r10
+	mov	r5,r5,ror#25
+	str	r10,[sp,#4*(16+15)]
+	ldr	r10,[sp,#4*(16+13)]
+	add	r9,r9,r12
+	mov	r6,r6,ror#25
+	eor	r5,r5,r8,ror#25
+	eor	r6,r6,r9,ror#25
+	str	r8,[sp,#4*(16+10)]
+	ldr	r8,[sp,#4*(16+8)]
+	add	r2,r2,r7
+	mov	r10,r10,ror#16
+	str	r9,[sp,#4*(16+11)]
+	ldr	r9,[sp,#4*(16+9)]
+	add	r3,r3,r4
+	mov	r14,r14,ror#16
+	eor	r10,r10,r2,ror#16
+	eor	r14,r14,r3,ror#16
+	add	r8,r8,r10
+	mov	r7,r7,ror#20
+	add	r9,r9,r14
+	mov	r4,r4,ror#20
+	eor	r7,r7,r8,ror#20
+	eor	r4,r4,r9,ror#20
+	add	r2,r2,r7
+	mov	r10,r10,ror#24
+	add	r3,r3,r4
+	mov	r14,r14,ror#24
+	eor	r10,r10,r2,ror#24
+	eor	r14,r14,r3,ror#24
+	add	r8,r8,r10
+	mov	r7,r7,ror#25
+	add	r9,r9,r14
+	mov	r4,r4,ror#25
+	eor	r7,r7,r8,ror#25
+	eor	r4,r4,r9,ror#25
+	bne	.Loop
+
+	ldr	r11,[sp,#4*(32+2)]	@ load len
+
+	str	r8, [sp,#4*(16+8)]	@ modulo-scheduled store
+	str	r9, [sp,#4*(16+9)]
+	str	r12,[sp,#4*(16+12)]
+	str	r10, [sp,#4*(16+13)]
+	str	r14,[sp,#4*(16+14)]
+
+	@ at this point we have first half of 512-bit result in
+	@ rx and second half at sp+4*(16+8)
+
+	cmp	r11,#64		@ done yet?
+#ifdef	__thumb2__
+	itete	lo
+#endif
+	addlo	r12,sp,#4*(0)		@ shortcut or ...
+	ldrhs	r12,[sp,#4*(32+1)]	@ ... load inp
+	addlo	r14,sp,#4*(0)		@ shortcut or ...
+	ldrhs	r14,[sp,#4*(32+0)]	@ ... load out
+
+	ldr	r8,[sp,#4*(0)]	@ load key material
+	ldr	r9,[sp,#4*(1)]
+
+#if __ARM_ARCH__>=6 || !defined(__ARMEB__)
+# if __ARM_ARCH__<7
+	orr	r10,r12,r14
+	tst	r10,#3		@ are input and output aligned?
+	ldr	r10,[sp,#4*(2)]
+	bne	.Lunaligned
+	cmp	r11,#64		@ restore flags
+# else
+	ldr	r10,[sp,#4*(2)]
+# endif
+	ldr	r11,[sp,#4*(3)]
+
+	add	r0,r0,r8	@ accumulate key material
+	add	r1,r1,r9
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhs	r8,[r12],#16		@ load input
+	ldrhs	r9,[r12,#-12]
+
+	add	r2,r2,r10
+	add	r3,r3,r11
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhs	r10,[r12,#-8]
+	ldrhs	r11,[r12,#-4]
+# if __ARM_ARCH__>=6 && defined(__ARMEB__)
+	rev	r0,r0
+	rev	r1,r1
+	rev	r2,r2
+	rev	r3,r3
+# endif
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	eorhs	r0,r0,r8	@ xor with input
+	eorhs	r1,r1,r9
+	add	r8,sp,#4*(4)
+	str	r0,[r14],#16		@ store output
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	eorhs	r2,r2,r10
+	eorhs	r3,r3,r11
+	ldmia	r8,{r8,r9,r10,r11}	@ load key material
+	str	r1,[r14,#-12]
+	str	r2,[r14,#-8]
+	str	r3,[r14,#-4]
+
+	add	r4,r4,r8	@ accumulate key material
+	add	r5,r5,r9
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhs	r8,[r12],#16		@ load input
+	ldrhs	r9,[r12,#-12]
+	add	r6,r6,r10
+	add	r7,r7,r11
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhs	r10,[r12,#-8]
+	ldrhs	r11,[r12,#-4]
+# if __ARM_ARCH__>=6 && defined(__ARMEB__)
+	rev	r4,r4
+	rev	r5,r5
+	rev	r6,r6
+	rev	r7,r7
+# endif
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	eorhs	r4,r4,r8
+	eorhs	r5,r5,r9
+	add	r8,sp,#4*(8)
+	str	r4,[r14],#16		@ store output
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	eorhs	r6,r6,r10
+	eorhs	r7,r7,r11
+	str	r5,[r14,#-12]
+	ldmia	r8,{r8,r9,r10,r11}	@ load key material
+	str	r6,[r14,#-8]
+	add	r0,sp,#4*(16+8)
+	str	r7,[r14,#-4]
+
+	ldmia	r0,{r0,r1,r2,r3,r4,r5,r6,r7}	@ load second half
+
+	add	r0,r0,r8	@ accumulate key material
+	add	r1,r1,r9
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhs	r8,[r12],#16		@ load input
+	ldrhs	r9,[r12,#-12]
+# ifdef	__thumb2__
+	itt	hi
+# endif
+	strhi	r10,[sp,#4*(16+10)]	@ copy "rx" while at it
+	strhi	r11,[sp,#4*(16+11)]	@ copy "rx" while at it
+	add	r2,r2,r10
+	add	r3,r3,r11
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhs	r10,[r12,#-8]
+	ldrhs	r11,[r12,#-4]
+# if __ARM_ARCH__>=6 && defined(__ARMEB__)
+	rev	r0,r0
+	rev	r1,r1
+	rev	r2,r2
+	rev	r3,r3
+# endif
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	eorhs	r0,r0,r8
+	eorhs	r1,r1,r9
+	add	r8,sp,#4*(12)
+	str	r0,[r14],#16		@ store output
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	eorhs	r2,r2,r10
+	eorhs	r3,r3,r11
+	str	r1,[r14,#-12]
+	ldmia	r8,{r8,r9,r10,r11}	@ load key material
+	str	r2,[r14,#-8]
+	str	r3,[r14,#-4]
+
+	add	r4,r4,r8	@ accumulate key material
+	add	r5,r5,r9
+# ifdef	__thumb2__
+	itt	hi
+# endif
+	addhi	r8,r8,#1		@ next counter value
+	strhi	r8,[sp,#4*(12)]	@ save next counter value
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhs	r8,[r12],#16		@ load input
+	ldrhs	r9,[r12,#-12]
+	add	r6,r6,r10
+	add	r7,r7,r11
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhs	r10,[r12,#-8]
+	ldrhs	r11,[r12,#-4]
+# if __ARM_ARCH__>=6 && defined(__ARMEB__)
+	rev	r4,r4
+	rev	r5,r5
+	rev	r6,r6
+	rev	r7,r7
+# endif
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	eorhs	r4,r4,r8
+	eorhs	r5,r5,r9
+# ifdef	__thumb2__
+	it	ne
+# endif
+	ldrne	r8,[sp,#4*(32+2)]	@ re-load len
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	eorhs	r6,r6,r10
+	eorhs	r7,r7,r11
+	str	r4,[r14],#16		@ store output
+	str	r5,[r14,#-12]
+# ifdef	__thumb2__
+	it	hs
+# endif
+	subhs	r11,r8,#64		@ len-=64
+	str	r6,[r14,#-8]
+	str	r7,[r14,#-4]
+	bhi	.Loop_outer
+
+	beq	.Ldone
+# if __ARM_ARCH__<7
+	b	.Ltail
+
+.align	4
+.Lunaligned:@ unaligned endian-neutral path
+	cmp	r11,#64		@ restore flags
+# endif
+#endif
+#if __ARM_ARCH__<7
+	ldr	r11,[sp,#4*(3)]
+	add	r0,r0,r8		@ accumulate key material
+	add	r1,r1,r9
+	add	r2,r2,r10
+# ifdef	__thumb2__
+	itete	lo
+# endif
+	eorlo	r8,r8,r8		@ zero or ...
+	ldrhsb	r8,[r12],#16			@ ... load input
+	eorlo	r9,r9,r9
+	ldrhsb	r9,[r12,#-12]
+
+	add	r3,r3,r11
+# ifdef	__thumb2__
+	itete	lo
+# endif
+	eorlo	r10,r10,r10
+	ldrhsb	r10,[r12,#-8]
+	eorlo	r11,r11,r11
+	ldrhsb	r11,[r12,#-4]
+
+	eor	r0,r8,r0		@ xor with input (or zero)
+	eor	r1,r9,r1
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r8,[r12,#-15]		@ load more input
+	ldrhsb	r9,[r12,#-11]
+	eor	r2,r10,r2
+	strb	r0,[r14],#16		@ store output
+	eor	r3,r11,r3
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r10,[r12,#-7]
+	ldrhsb	r11,[r12,#-3]
+	strb	r1,[r14,#-12]
+	eor	r0,r8,r0,lsr#8
+	strb	r2,[r14,#-8]
+	eor	r1,r9,r1,lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r8,[r12,#-14]		@ load more input
+	ldrhsb	r9,[r12,#-10]
+	strb	r3,[r14,#-4]
+	eor	r2,r10,r2,lsr#8
+	strb	r0,[r14,#-15]
+	eor	r3,r11,r3,lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r10,[r12,#-6]
+	ldrhsb	r11,[r12,#-2]
+	strb	r1,[r14,#-11]
+	eor	r0,r8,r0,lsr#8
+	strb	r2,[r14,#-7]
+	eor	r1,r9,r1,lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r8,[r12,#-13]		@ load more input
+	ldrhsb	r9,[r12,#-9]
+	strb	r3,[r14,#-3]
+	eor	r2,r10,r2,lsr#8
+	strb	r0,[r14,#-14]
+	eor	r3,r11,r3,lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r10,[r12,#-5]
+	ldrhsb	r11,[r12,#-1]
+	strb	r1,[r14,#-10]
+	strb	r2,[r14,#-6]
+	eor	r0,r8,r0,lsr#8
+	strb	r3,[r14,#-2]
+	eor	r1,r9,r1,lsr#8
+	strb	r0,[r14,#-13]
+	eor	r2,r10,r2,lsr#8
+	strb	r1,[r14,#-9]
+	eor	r3,r11,r3,lsr#8
+	strb	r2,[r14,#-5]
+	strb	r3,[r14,#-1]
+	add	r8,sp,#4*(4+0)
+	ldmia	r8,{r8,r9,r10,r11}		@ load key material
+	add	r0,sp,#4*(16+8)
+	add	r4,r4,r8		@ accumulate key material
+	add	r5,r5,r9
+	add	r6,r6,r10
+# ifdef	__thumb2__
+	itete	lo
+# endif
+	eorlo	r8,r8,r8		@ zero or ...
+	ldrhsb	r8,[r12],#16			@ ... load input
+	eorlo	r9,r9,r9
+	ldrhsb	r9,[r12,#-12]
+
+	add	r7,r7,r11
+# ifdef	__thumb2__
+	itete	lo
+# endif
+	eorlo	r10,r10,r10
+	ldrhsb	r10,[r12,#-8]
+	eorlo	r11,r11,r11
+	ldrhsb	r11,[r12,#-4]
+
+	eor	r4,r8,r4		@ xor with input (or zero)
+	eor	r5,r9,r5
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r8,[r12,#-15]		@ load more input
+	ldrhsb	r9,[r12,#-11]
+	eor	r6,r10,r6
+	strb	r4,[r14],#16		@ store output
+	eor	r7,r11,r7
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r10,[r12,#-7]
+	ldrhsb	r11,[r12,#-3]
+	strb	r5,[r14,#-12]
+	eor	r4,r8,r4,lsr#8
+	strb	r6,[r14,#-8]
+	eor	r5,r9,r5,lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r8,[r12,#-14]		@ load more input
+	ldrhsb	r9,[r12,#-10]
+	strb	r7,[r14,#-4]
+	eor	r6,r10,r6,lsr#8
+	strb	r4,[r14,#-15]
+	eor	r7,r11,r7,lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r10,[r12,#-6]
+	ldrhsb	r11,[r12,#-2]
+	strb	r5,[r14,#-11]
+	eor	r4,r8,r4,lsr#8
+	strb	r6,[r14,#-7]
+	eor	r5,r9,r5,lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r8,[r12,#-13]		@ load more input
+	ldrhsb	r9,[r12,#-9]
+	strb	r7,[r14,#-3]
+	eor	r6,r10,r6,lsr#8
+	strb	r4,[r14,#-14]
+	eor	r7,r11,r7,lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r10,[r12,#-5]
+	ldrhsb	r11,[r12,#-1]
+	strb	r5,[r14,#-10]
+	strb	r6,[r14,#-6]
+	eor	r4,r8,r4,lsr#8
+	strb	r7,[r14,#-2]
+	eor	r5,r9,r5,lsr#8
+	strb	r4,[r14,#-13]
+	eor	r6,r10,r6,lsr#8
+	strb	r5,[r14,#-9]
+	eor	r7,r11,r7,lsr#8
+	strb	r6,[r14,#-5]
+	strb	r7,[r14,#-1]
+	add	r8,sp,#4*(4+4)
+	ldmia	r8,{r8,r9,r10,r11}		@ load key material
+	ldmia	r0,{r0,r1,r2,r3,r4,r5,r6,r7}		@ load second half
+# ifdef	__thumb2__
+	itt	hi
+# endif
+	strhi	r10,[sp,#4*(16+10)]		@ copy "rx"
+	strhi	r11,[sp,#4*(16+11)]		@ copy "rx"
+	add	r0,r0,r8		@ accumulate key material
+	add	r1,r1,r9
+	add	r2,r2,r10
+# ifdef	__thumb2__
+	itete	lo
+# endif
+	eorlo	r8,r8,r8		@ zero or ...
+	ldrhsb	r8,[r12],#16			@ ... load input
+	eorlo	r9,r9,r9
+	ldrhsb	r9,[r12,#-12]
+
+	add	r3,r3,r11
+# ifdef	__thumb2__
+	itete	lo
+# endif
+	eorlo	r10,r10,r10
+	ldrhsb	r10,[r12,#-8]
+	eorlo	r11,r11,r11
+	ldrhsb	r11,[r12,#-4]
+
+	eor	r0,r8,r0		@ xor with input (or zero)
+	eor	r1,r9,r1
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r8,[r12,#-15]		@ load more input
+	ldrhsb	r9,[r12,#-11]
+	eor	r2,r10,r2
+	strb	r0,[r14],#16		@ store output
+	eor	r3,r11,r3
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r10,[r12,#-7]
+	ldrhsb	r11,[r12,#-3]
+	strb	r1,[r14,#-12]
+	eor	r0,r8,r0,lsr#8
+	strb	r2,[r14,#-8]
+	eor	r1,r9,r1,lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r8,[r12,#-14]		@ load more input
+	ldrhsb	r9,[r12,#-10]
+	strb	r3,[r14,#-4]
+	eor	r2,r10,r2,lsr#8
+	strb	r0,[r14,#-15]
+	eor	r3,r11,r3,lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r10,[r12,#-6]
+	ldrhsb	r11,[r12,#-2]
+	strb	r1,[r14,#-11]
+	eor	r0,r8,r0,lsr#8
+	strb	r2,[r14,#-7]
+	eor	r1,r9,r1,lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r8,[r12,#-13]		@ load more input
+	ldrhsb	r9,[r12,#-9]
+	strb	r3,[r14,#-3]
+	eor	r2,r10,r2,lsr#8
+	strb	r0,[r14,#-14]
+	eor	r3,r11,r3,lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r10,[r12,#-5]
+	ldrhsb	r11,[r12,#-1]
+	strb	r1,[r14,#-10]
+	strb	r2,[r14,#-6]
+	eor	r0,r8,r0,lsr#8
+	strb	r3,[r14,#-2]
+	eor	r1,r9,r1,lsr#8
+	strb	r0,[r14,#-13]
+	eor	r2,r10,r2,lsr#8
+	strb	r1,[r14,#-9]
+	eor	r3,r11,r3,lsr#8
+	strb	r2,[r14,#-5]
+	strb	r3,[r14,#-1]
+	add	r8,sp,#4*(4+8)
+	ldmia	r8,{r8,r9,r10,r11}		@ load key material
+	add	r4,r4,r8		@ accumulate key material
+# ifdef	__thumb2__
+	itt	hi
+# endif
+	addhi	r8,r8,#1			@ next counter value
+	strhi	r8,[sp,#4*(12)]		@ save next counter value
+	add	r5,r5,r9
+	add	r6,r6,r10
+# ifdef	__thumb2__
+	itete	lo
+# endif
+	eorlo	r8,r8,r8		@ zero or ...
+	ldrhsb	r8,[r12],#16			@ ... load input
+	eorlo	r9,r9,r9
+	ldrhsb	r9,[r12,#-12]
+
+	add	r7,r7,r11
+# ifdef	__thumb2__
+	itete	lo
+# endif
+	eorlo	r10,r10,r10
+	ldrhsb	r10,[r12,#-8]
+	eorlo	r11,r11,r11
+	ldrhsb	r11,[r12,#-4]
+
+	eor	r4,r8,r4		@ xor with input (or zero)
+	eor	r5,r9,r5
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r8,[r12,#-15]		@ load more input
+	ldrhsb	r9,[r12,#-11]
+	eor	r6,r10,r6
+	strb	r4,[r14],#16		@ store output
+	eor	r7,r11,r7
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r10,[r12,#-7]
+	ldrhsb	r11,[r12,#-3]
+	strb	r5,[r14,#-12]
+	eor	r4,r8,r4,lsr#8
+	strb	r6,[r14,#-8]
+	eor	r5,r9,r5,lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r8,[r12,#-14]		@ load more input
+	ldrhsb	r9,[r12,#-10]
+	strb	r7,[r14,#-4]
+	eor	r6,r10,r6,lsr#8
+	strb	r4,[r14,#-15]
+	eor	r7,r11,r7,lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r10,[r12,#-6]
+	ldrhsb	r11,[r12,#-2]
+	strb	r5,[r14,#-11]
+	eor	r4,r8,r4,lsr#8
+	strb	r6,[r14,#-7]
+	eor	r5,r9,r5,lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r8,[r12,#-13]		@ load more input
+	ldrhsb	r9,[r12,#-9]
+	strb	r7,[r14,#-3]
+	eor	r6,r10,r6,lsr#8
+	strb	r4,[r14,#-14]
+	eor	r7,r11,r7,lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	r10,[r12,#-5]
+	ldrhsb	r11,[r12,#-1]
+	strb	r5,[r14,#-10]
+	strb	r6,[r14,#-6]
+	eor	r4,r8,r4,lsr#8
+	strb	r7,[r14,#-2]
+	eor	r5,r9,r5,lsr#8
+	strb	r4,[r14,#-13]
+	eor	r6,r10,r6,lsr#8
+	strb	r5,[r14,#-9]
+	eor	r7,r11,r7,lsr#8
+	strb	r6,[r14,#-5]
+	strb	r7,[r14,#-1]
+# ifdef	__thumb2__
+	it	ne
+# endif
+	ldrne	r8,[sp,#4*(32+2)]		@ re-load len
+# ifdef	__thumb2__
+	it	hs
+# endif
+	subhs	r11,r8,#64			@ len-=64
+	bhi	.Loop_outer
+
+	beq	.Ldone
+#endif
+
+.Ltail:
+	ldr	r12,[sp,#4*(32+1)]	@ load inp
+	add	r9,sp,#4*(0)
+	ldr	r14,[sp,#4*(32+0)]	@ load out
+
+.Loop_tail:
+	ldrb	r10,[r9],#1	@ read buffer on stack
+	ldrb	r11,[r12],#1		@ read input
+	subs	r8,r8,#1
+	eor	r11,r11,r10
+	strb	r11,[r14],#1		@ store output
+	bne	.Loop_tail
+
+.Ldone:
+	add	sp,sp,#4*(32+3)
+.Lno_data:
+	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,pc}
+.size	ChaCha20_ctr32,.-ChaCha20_ctr32
+#if __ARM_MAX_ARCH__>=7
+.arch	armv7-a
+.fpu	neon
+
+.type	ChaCha20_neon,%function
+.align	5
+ChaCha20_neon:
+	ldr	r12,[sp,#0]		@ pull pointer to counter and nonce
+	stmdb	sp!,{r0,r1,r2,r4-r11,lr}
+.LChaCha20_neon:
+	adr	r14,.Lsigma
+	vstmdb	sp!,{d8,d9,d10,d11,d12,d13,d14,d15}		@ ABI spec says so
+	stmdb	sp!,{r0,r1,r2,r3}
+
+	vld1.32	{q1,q2},[r3]		@ load key
+	ldmia	r3,{r4,r5,r6,r7,r8,r9,r10,r11}		@ load key
+
+	sub	sp,sp,#4*(16+16)
+	vld1.32	{q3},[r12]		@ load counter and nonce
+	add	r12,sp,#4*8
+	ldmia	r14,{r0,r1,r2,r3}		@ load sigma
+	vld1.32	{q0},[r14]!		@ load sigma
+	vld1.32	{q12},[r14]		@ one
+	vst1.32	{q2,q3},[r12]		@ copy 1/2key|counter|nonce
+	vst1.32	{q0,q1},[sp]		@ copy sigma|1/2key
+
+	str	r10,[sp,#4*(16+10)]	@ off-load "rx"
+	str	r11,[sp,#4*(16+11)]	@ off-load "rx"
+	vshl.i32	d26,d24,#1	@ two
+	vstr	d24,[sp,#4*(16+0)]
+	vshl.i32	d28,d24,#2	@ four
+	vstr	d26,[sp,#4*(16+2)]
+	vmov	q4,q0
+	vstr	d28,[sp,#4*(16+4)]
+	vmov	q8,q0
+	vmov	q5,q1
+	vmov	q9,q1
+	b	.Loop_neon_enter
+
+.align	4
+.Loop_neon_outer:
+	ldmia	sp,{r0,r1,r2,r3,r4,r5,r6,r7,r8,r9}		@ load key material
+	cmp	r11,#64*2		@ if len<=64*2
+	bls	.Lbreak_neon		@ switch to integer-only
+	vmov	q4,q0
+	str	r11,[sp,#4*(32+2)]	@ save len
+	vmov	q8,q0
+	str	r12,  [sp,#4*(32+1)]	@ save inp
+	vmov	q5,q1
+	str	r14,  [sp,#4*(32+0)]	@ save out
+	vmov	q9,q1
+.Loop_neon_enter:
+	ldr	r11, [sp,#4*(15)]
+	vadd.i32	q7,q3,q12		@ counter+1
+	ldr	r12,[sp,#4*(12)]	@ modulo-scheduled load
+	vmov	q6,q2
+	ldr	r10, [sp,#4*(13)]
+	vmov	q10,q2
+	ldr	r14,[sp,#4*(14)]
+	vadd.i32	q11,q7,q12		@ counter+2
+	str	r11, [sp,#4*(16+15)]
+	mov	r11,#10
+	add	r12,r12,#3	@ counter+3
+	b	.Loop_neon
+
+.align	4
+.Loop_neon:
+	subs	r11,r11,#1
+	vadd.i32	q0,q0,q1
+	add	r0,r0,r4
+	vadd.i32	q4,q4,q5
+	mov	r12,r12,ror#16
+	vadd.i32	q8,q8,q9
+	add	r1,r1,r5
+	veor	q3,q3,q0
+	mov	r10,r10,ror#16
+	veor	q7,q7,q4
+	eor	r12,r12,r0,ror#16
+	veor	q11,q11,q8
+	eor	r10,r10,r1,ror#16
+	vrev32.16	q3,q3
+	add	r8,r8,r12
+	vrev32.16	q7,q7
+	mov	r4,r4,ror#20
+	vrev32.16	q11,q11
+	add	r9,r9,r10
+	vadd.i32	q2,q2,q3
+	mov	r5,r5,ror#20
+	vadd.i32	q6,q6,q7
+	eor	r4,r4,r8,ror#20
+	vadd.i32	q10,q10,q11
+	eor	r5,r5,r9,ror#20
+	veor	q12,q1,q2
+	add	r0,r0,r4
+	veor	q13,q5,q6
+	mov	r12,r12,ror#24
+	veor	q14,q9,q10
+	add	r1,r1,r5
+	vshr.u32	q1,q12,#20
+	mov	r10,r10,ror#24
+	vshr.u32	q5,q13,#20
+	eor	r12,r12,r0,ror#24
+	vshr.u32	q9,q14,#20
+	eor	r10,r10,r1,ror#24
+	vsli.32	q1,q12,#12
+	add	r8,r8,r12
+	vsli.32	q5,q13,#12
+	mov	r4,r4,ror#25
+	vsli.32	q9,q14,#12
+	add	r9,r9,r10
+	vadd.i32	q0,q0,q1
+	mov	r5,r5,ror#25
+	vadd.i32	q4,q4,q5
+	str	r10,[sp,#4*(16+13)]
+	vadd.i32	q8,q8,q9
+	ldr	r10,[sp,#4*(16+15)]
+	veor	q12,q3,q0
+	eor	r4,r4,r8,ror#25
+	veor	q13,q7,q4
+	eor	r5,r5,r9,ror#25
+	veor	q14,q11,q8
+	str	r8,[sp,#4*(16+8)]
+	vshr.u32	q3,q12,#24
+	ldr	r8,[sp,#4*(16+10)]
+	vshr.u32	q7,q13,#24
+	add	r2,r2,r6
+	vshr.u32	q11,q14,#24
+	mov	r14,r14,ror#16
+	vsli.32	q3,q12,#8
+	str	r9,[sp,#4*(16+9)]
+	vsli.32	q7,q13,#8
+	ldr	r9,[sp,#4*(16+11)]
+	vsli.32	q11,q14,#8
+	add	r3,r3,r7
+	vadd.i32	q2,q2,q3
+	mov	r10,r10,ror#16
+	vadd.i32	q6,q6,q7
+	eor	r14,r14,r2,ror#16
+	vadd.i32	q10,q10,q11
+	eor	r10,r10,r3,ror#16
+	veor	q12,q1,q2
+	add	r8,r8,r14
+	veor	q13,q5,q6
+	mov	r6,r6,ror#20
+	veor	q14,q9,q10
+	add	r9,r9,r10
+	vshr.u32	q1,q12,#25
+	mov	r7,r7,ror#20
+	vshr.u32	q5,q13,#25
+	eor	r6,r6,r8,ror#20
+	vshr.u32	q9,q14,#25
+	eor	r7,r7,r9,ror#20
+	vsli.32	q1,q12,#7
+	add	r2,r2,r6
+	vsli.32	q5,q13,#7
+	mov	r14,r14,ror#24
+	vsli.32	q9,q14,#7
+	add	r3,r3,r7
+	vext.8	q2,q2,q2,#8
+	mov	r10,r10,ror#24
+	vext.8	q6,q6,q6,#8
+	eor	r14,r14,r2,ror#24
+	vext.8	q10,q10,q10,#8
+	eor	r10,r10,r3,ror#24
+	vext.8	q1,q1,q1,#4
+	add	r8,r8,r14
+	vext.8	q5,q5,q5,#4
+	mov	r6,r6,ror#25
+	vext.8	q9,q9,q9,#4
+	add	r9,r9,r10
+	vext.8	q3,q3,q3,#12
+	mov	r7,r7,ror#25
+	vext.8	q7,q7,q7,#12
+	eor	r6,r6,r8,ror#25
+	vext.8	q11,q11,q11,#12
+	eor	r7,r7,r9,ror#25
+	vadd.i32	q0,q0,q1
+	add	r0,r0,r5
+	vadd.i32	q4,q4,q5
+	mov	r10,r10,ror#16
+	vadd.i32	q8,q8,q9
+	add	r1,r1,r6
+	veor	q3,q3,q0
+	mov	r12,r12,ror#16
+	veor	q7,q7,q4
+	eor	r10,r10,r0,ror#16
+	veor	q11,q11,q8
+	eor	r12,r12,r1,ror#16
+	vrev32.16	q3,q3
+	add	r8,r8,r10
+	vrev32.16	q7,q7
+	mov	r5,r5,ror#20
+	vrev32.16	q11,q11
+	add	r9,r9,r12
+	vadd.i32	q2,q2,q3
+	mov	r6,r6,ror#20
+	vadd.i32	q6,q6,q7
+	eor	r5,r5,r8,ror#20
+	vadd.i32	q10,q10,q11
+	eor	r6,r6,r9,ror#20
+	veor	q12,q1,q2
+	add	r0,r0,r5
+	veor	q13,q5,q6
+	mov	r10,r10,ror#24
+	veor	q14,q9,q10
+	add	r1,r1,r6
+	vshr.u32	q1,q12,#20
+	mov	r12,r12,ror#24
+	vshr.u32	q5,q13,#20
+	eor	r10,r10,r0,ror#24
+	vshr.u32	q9,q14,#20
+	eor	r12,r12,r1,ror#24
+	vsli.32	q1,q12,#12
+	add	r8,r8,r10
+	vsli.32	q5,q13,#12
+	mov	r5,r5,ror#25
+	vsli.32	q9,q14,#12
+	str	r10,[sp,#4*(16+15)]
+	vadd.i32	q0,q0,q1
+	ldr	r10,[sp,#4*(16+13)]
+	vadd.i32	q4,q4,q5
+	add	r9,r9,r12
+	vadd.i32	q8,q8,q9
+	mov	r6,r6,ror#25
+	veor	q12,q3,q0
+	eor	r5,r5,r8,ror#25
+	veor	q13,q7,q4
+	eor	r6,r6,r9,ror#25
+	veor	q14,q11,q8
+	str	r8,[sp,#4*(16+10)]
+	vshr.u32	q3,q12,#24
+	ldr	r8,[sp,#4*(16+8)]
+	vshr.u32	q7,q13,#24
+	add	r2,r2,r7
+	vshr.u32	q11,q14,#24
+	mov	r10,r10,ror#16
+	vsli.32	q3,q12,#8
+	str	r9,[sp,#4*(16+11)]
+	vsli.32	q7,q13,#8
+	ldr	r9,[sp,#4*(16+9)]
+	vsli.32	q11,q14,#8
+	add	r3,r3,r4
+	vadd.i32	q2,q2,q3
+	mov	r14,r14,ror#16
+	vadd.i32	q6,q6,q7
+	eor	r10,r10,r2,ror#16
+	vadd.i32	q10,q10,q11
+	eor	r14,r14,r3,ror#16
+	veor	q12,q1,q2
+	add	r8,r8,r10
+	veor	q13,q5,q6
+	mov	r7,r7,ror#20
+	veor	q14,q9,q10
+	add	r9,r9,r14
+	vshr.u32	q1,q12,#25
+	mov	r4,r4,ror#20
+	vshr.u32	q5,q13,#25
+	eor	r7,r7,r8,ror#20
+	vshr.u32	q9,q14,#25
+	eor	r4,r4,r9,ror#20
+	vsli.32	q1,q12,#7
+	add	r2,r2,r7
+	vsli.32	q5,q13,#7
+	mov	r10,r10,ror#24
+	vsli.32	q9,q14,#7
+	add	r3,r3,r4
+	vext.8	q2,q2,q2,#8
+	mov	r14,r14,ror#24
+	vext.8	q6,q6,q6,#8
+	eor	r10,r10,r2,ror#24
+	vext.8	q10,q10,q10,#8
+	eor	r14,r14,r3,ror#24
+	vext.8	q1,q1,q1,#12
+	add	r8,r8,r10
+	vext.8	q5,q5,q5,#12
+	mov	r7,r7,ror#25
+	vext.8	q9,q9,q9,#12
+	add	r9,r9,r14
+	vext.8	q3,q3,q3,#4
+	mov	r4,r4,ror#25
+	vext.8	q7,q7,q7,#4
+	eor	r7,r7,r8,ror#25
+	vext.8	q11,q11,q11,#4
+	eor	r4,r4,r9,ror#25
+	bne	.Loop_neon
+
+	add	r11,sp,#32
+	vld1.32	{q12,q13},[sp]		@ load key material
+	vld1.32	{q14,q15},[r11]
+
+	ldr	r11,[sp,#4*(32+2)]	@ load len
+
+	str	r8, [sp,#4*(16+8)]	@ modulo-scheduled store
+	str	r9, [sp,#4*(16+9)]
+	str	r12,[sp,#4*(16+12)]
+	str	r10, [sp,#4*(16+13)]
+	str	r14,[sp,#4*(16+14)]
+
+	@ at this point we have first half of 512-bit result in
+	@ rx and second half at sp+4*(16+8)
+
+	ldr	r12,[sp,#4*(32+1)]	@ load inp
+	ldr	r14,[sp,#4*(32+0)]	@ load out
+
+	vadd.i32	q0,q0,q12		@ accumulate key material
+	vadd.i32	q4,q4,q12
+	vadd.i32	q8,q8,q12
+	vldr	d24,[sp,#4*(16+0)]	@ one
+
+	vadd.i32	q1,q1,q13
+	vadd.i32	q5,q5,q13
+	vadd.i32	q9,q9,q13
+	vldr	d26,[sp,#4*(16+2)]	@ two
+
+	vadd.i32	q2,q2,q14
+	vadd.i32	q6,q6,q14
+	vadd.i32	q10,q10,q14
+	vadd.i32	d14,d14,d24	@ counter+1
+	vadd.i32	d22,d22,d26	@ counter+2
+
+	vadd.i32	q3,q3,q15
+	vadd.i32	q7,q7,q15
+	vadd.i32	q11,q11,q15
+
+	cmp	r11,#64*4
+	blo	.Ltail_neon
+
+	vld1.8	{q12,q13},[r12]!	@ load input
+	mov	r11,sp
+	vld1.8	{q14,q15},[r12]!
+	veor	q0,q0,q12		@ xor with input
+	veor	q1,q1,q13
+	vld1.8	{q12,q13},[r12]!
+	veor	q2,q2,q14
+	veor	q3,q3,q15
+	vld1.8	{q14,q15},[r12]!
+
+	veor	q4,q4,q12
+	vst1.8	{q0,q1},[r14]!	@ store output
+	veor	q5,q5,q13
+	vld1.8	{q12,q13},[r12]!
+	veor	q6,q6,q14
+	vst1.8	{q2,q3},[r14]!
+	veor	q7,q7,q15
+	vld1.8	{q14,q15},[r12]!
+
+	veor	q8,q8,q12
+	vld1.32	{q0,q1},[r11]!	@ load for next iteration
+	veor	d25,d25,d25
+	vldr	d24,[sp,#4*(16+4)]	@ four
+	veor	q9,q9,q13
+	vld1.32	{q2,q3},[r11]
+	veor	q10,q10,q14
+	vst1.8	{q4,q5},[r14]!
+	veor	q11,q11,q15
+	vst1.8	{q6,q7},[r14]!
+
+	vadd.i32	d6,d6,d24	@ next counter value
+	vldr	d24,[sp,#4*(16+0)]	@ one
+
+	ldmia	sp,{r8,r9,r10,r11}	@ load key material
+	add	r0,r0,r8	@ accumulate key material
+	ldr	r8,[r12],#16		@ load input
+	vst1.8	{q8,q9},[r14]!
+	add	r1,r1,r9
+	ldr	r9,[r12,#-12]
+	vst1.8	{q10,q11},[r14]!
+	add	r2,r2,r10
+	ldr	r10,[r12,#-8]
+	add	r3,r3,r11
+	ldr	r11,[r12,#-4]
+# ifdef	__ARMEB__
+	rev	r0,r0
+	rev	r1,r1
+	rev	r2,r2
+	rev	r3,r3
+# endif
+	eor	r0,r0,r8	@ xor with input
+	add	r8,sp,#4*(4)
+	eor	r1,r1,r9
+	str	r0,[r14],#16		@ store output
+	eor	r2,r2,r10
+	str	r1,[r14,#-12]
+	eor	r3,r3,r11
+	ldmia	r8,{r8,r9,r10,r11}	@ load key material
+	str	r2,[r14,#-8]
+	str	r3,[r14,#-4]
+
+	add	r4,r4,r8	@ accumulate key material
+	ldr	r8,[r12],#16		@ load input
+	add	r5,r5,r9
+	ldr	r9,[r12,#-12]
+	add	r6,r6,r10
+	ldr	r10,[r12,#-8]
+	add	r7,r7,r11
+	ldr	r11,[r12,#-4]
+# ifdef	__ARMEB__
+	rev	r4,r4
+	rev	r5,r5
+	rev	r6,r6
+	rev	r7,r7
+# endif
+	eor	r4,r4,r8
+	add	r8,sp,#4*(8)
+	eor	r5,r5,r9
+	str	r4,[r14],#16		@ store output
+	eor	r6,r6,r10
+	str	r5,[r14,#-12]
+	eor	r7,r7,r11
+	ldmia	r8,{r8,r9,r10,r11}	@ load key material
+	str	r6,[r14,#-8]
+	add	r0,sp,#4*(16+8)
+	str	r7,[r14,#-4]
+
+	ldmia	r0,{r0,r1,r2,r3,r4,r5,r6,r7}	@ load second half
+
+	add	r0,r0,r8	@ accumulate key material
+	ldr	r8,[r12],#16		@ load input
+	add	r1,r1,r9
+	ldr	r9,[r12,#-12]
+# ifdef	__thumb2__
+	it	hi
+# endif
+	strhi	r10,[sp,#4*(16+10)]	@ copy "rx" while at it
+	add	r2,r2,r10
+	ldr	r10,[r12,#-8]
+# ifdef	__thumb2__
+	it	hi
+# endif
+	strhi	r11,[sp,#4*(16+11)]	@ copy "rx" while at it
+	add	r3,r3,r11
+	ldr	r11,[r12,#-4]
+# ifdef	__ARMEB__
+	rev	r0,r0
+	rev	r1,r1
+	rev	r2,r2
+	rev	r3,r3
+# endif
+	eor	r0,r0,r8
+	add	r8,sp,#4*(12)
+	eor	r1,r1,r9
+	str	r0,[r14],#16		@ store output
+	eor	r2,r2,r10
+	str	r1,[r14,#-12]
+	eor	r3,r3,r11
+	ldmia	r8,{r8,r9,r10,r11}	@ load key material
+	str	r2,[r14,#-8]
+	str	r3,[r14,#-4]
+
+	add	r4,r4,r8	@ accumulate key material
+	add	r8,r8,#4		@ next counter value
+	add	r5,r5,r9
+	str	r8,[sp,#4*(12)]	@ save next counter value
+	ldr	r8,[r12],#16		@ load input
+	add	r6,r6,r10
+	add	r4,r4,#3		@ counter+3
+	ldr	r9,[r12,#-12]
+	add	r7,r7,r11
+	ldr	r10,[r12,#-8]
+	ldr	r11,[r12,#-4]
+# ifdef	__ARMEB__
+	rev	r4,r4
+	rev	r5,r5
+	rev	r6,r6
+	rev	r7,r7
+# endif
+	eor	r4,r4,r8
+# ifdef	__thumb2__
+	it	hi
+# endif
+	ldrhi	r8,[sp,#4*(32+2)]	@ re-load len
+	eor	r5,r5,r9
+	eor	r6,r6,r10
+	str	r4,[r14],#16		@ store output
+	eor	r7,r7,r11
+	str	r5,[r14,#-12]
+	sub	r11,r8,#64*4	@ len-=64*4
+	str	r6,[r14,#-8]
+	str	r7,[r14,#-4]
+	bhi	.Loop_neon_outer
+
+	b	.Ldone_neon
+
+.align	4
+.Lbreak_neon:
+	@ harmonize NEON and integer-only stack frames: load data
+	@ from NEON frame, but save to integer-only one; distance
+	@ between the two is 4*(32+4+16-32)=4*(20).
+
+	str	r11, [sp,#4*(20+32+2)]	@ save len
+	add	r11,sp,#4*(32+4)
+	str	r12,   [sp,#4*(20+32+1)]	@ save inp
+	str	r14,   [sp,#4*(20+32+0)]	@ save out
+
+	ldr	r12,[sp,#4*(16+10)]
+	ldr	r14,[sp,#4*(16+11)]
+	vldmia	r11,{d8,d9,d10,d11,d12,d13,d14,d15}			@ fulfill ABI requirement
+	str	r12,[sp,#4*(20+16+10)]	@ copy "rx"
+	str	r14,[sp,#4*(20+16+11)]	@ copy "rx"
+
+	ldr	r11, [sp,#4*(15)]
+	ldr	r12,[sp,#4*(12)]		@ modulo-scheduled load
+	ldr	r10, [sp,#4*(13)]
+	ldr	r14,[sp,#4*(14)]
+	str	r11, [sp,#4*(20+16+15)]
+	add	r11,sp,#4*(20)
+	vst1.32	{q0,q1},[r11]!		@ copy key
+	add	sp,sp,#4*(20)			@ switch frame
+	vst1.32	{q2,q3},[r11]
+	mov	r11,#10
+	b	.Loop				@ go integer-only
+
+.align	4
+.Ltail_neon:
+	cmp	r11,#64*3
+	bhs	.L192_or_more_neon
+	cmp	r11,#64*2
+	bhs	.L128_or_more_neon
+	cmp	r11,#64*1
+	bhs	.L64_or_more_neon
+
+	add	r8,sp,#4*(8)
+	vst1.8	{q0,q1},[sp]
+	add	r10,sp,#4*(0)
+	vst1.8	{q2,q3},[r8]
+	b	.Loop_tail_neon
+
+.align	4
+.L64_or_more_neon:
+	vld1.8	{q12,q13},[r12]!
+	vld1.8	{q14,q15},[r12]!
+	veor	q0,q0,q12
+	veor	q1,q1,q13
+	veor	q2,q2,q14
+	veor	q3,q3,q15
+	vst1.8	{q0,q1},[r14]!
+	vst1.8	{q2,q3},[r14]!
+
+	beq	.Ldone_neon
+
+	add	r8,sp,#4*(8)
+	vst1.8	{q4,q5},[sp]
+	add	r10,sp,#4*(0)
+	vst1.8	{q6,q7},[r8]
+	sub	r11,r11,#64*1	@ len-=64*1
+	b	.Loop_tail_neon
+
+.align	4
+.L128_or_more_neon:
+	vld1.8	{q12,q13},[r12]!
+	vld1.8	{q14,q15},[r12]!
+	veor	q0,q0,q12
+	veor	q1,q1,q13
+	vld1.8	{q12,q13},[r12]!
+	veor	q2,q2,q14
+	veor	q3,q3,q15
+	vld1.8	{q14,q15},[r12]!
+
+	veor	q4,q4,q12
+	veor	q5,q5,q13
+	vst1.8	{q0,q1},[r14]!
+	veor	q6,q6,q14
+	vst1.8	{q2,q3},[r14]!
+	veor	q7,q7,q15
+	vst1.8	{q4,q5},[r14]!
+	vst1.8	{q6,q7},[r14]!
+
+	beq	.Ldone_neon
+
+	add	r8,sp,#4*(8)
+	vst1.8	{q8,q9},[sp]
+	add	r10,sp,#4*(0)
+	vst1.8	{q10,q11},[r8]
+	sub	r11,r11,#64*2	@ len-=64*2
+	b	.Loop_tail_neon
+
+.align	4
+.L192_or_more_neon:
+	vld1.8	{q12,q13},[r12]!
+	vld1.8	{q14,q15},[r12]!
+	veor	q0,q0,q12
+	veor	q1,q1,q13
+	vld1.8	{q12,q13},[r12]!
+	veor	q2,q2,q14
+	veor	q3,q3,q15
+	vld1.8	{q14,q15},[r12]!
+
+	veor	q4,q4,q12
+	veor	q5,q5,q13
+	vld1.8	{q12,q13},[r12]!
+	veor	q6,q6,q14
+	vst1.8	{q0,q1},[r14]!
+	veor	q7,q7,q15
+	vld1.8	{q14,q15},[r12]!
+
+	veor	q8,q8,q12
+	vst1.8	{q2,q3},[r14]!
+	veor	q9,q9,q13
+	vst1.8	{q4,q5},[r14]!
+	veor	q10,q10,q14
+	vst1.8	{q6,q7},[r14]!
+	veor	q11,q11,q15
+	vst1.8	{q8,q9},[r14]!
+	vst1.8	{q10,q11},[r14]!
+
+	beq	.Ldone_neon
+
+	ldmia	sp,{r8,r9,r10,r11}	@ load key material
+	add	r0,r0,r8	@ accumulate key material
+	add	r8,sp,#4*(4)
+	add	r1,r1,r9
+	add	r2,r2,r10
+	add	r3,r3,r11
+	ldmia	r8,{r8,r9,r10,r11}	@ load key material
+
+	add	r4,r4,r8	@ accumulate key material
+	add	r8,sp,#4*(8)
+	add	r5,r5,r9
+	add	r6,r6,r10
+	add	r7,r7,r11
+	ldmia	r8,{r8,r9,r10,r11}	@ load key material
+# ifdef	__ARMEB__
+	rev	r0,r0
+	rev	r1,r1
+	rev	r2,r2
+	rev	r3,r3
+	rev	r4,r4
+	rev	r5,r5
+	rev	r6,r6
+	rev	r7,r7
+# endif
+	stmia	sp,{r0,r1,r2,r3,r4,r5,r6,r7}
+	add	r0,sp,#4*(16+8)
+
+	ldmia	r0,{r0,r1,r2,r3,r4,r5,r6,r7}	@ load second half
+
+	add	r0,r0,r8	@ accumulate key material
+	add	r8,sp,#4*(12)
+	add	r1,r1,r9
+	add	r2,r2,r10
+	add	r3,r3,r11
+	ldmia	r8,{r8,r9,r10,r11}	@ load key material
+
+	add	r4,r4,r8	@ accumulate key material
+	add	r8,sp,#4*(8)
+	add	r5,r5,r9
+	add	r4,r4,#3		@ counter+3
+	add	r6,r6,r10
+	add	r7,r7,r11
+	ldr	r11,[sp,#4*(32+2)]	@ re-load len
+# ifdef	__ARMEB__
+	rev	r0,r0
+	rev	r1,r1
+	rev	r2,r2
+	rev	r3,r3
+	rev	r4,r4
+	rev	r5,r5
+	rev	r6,r6
+	rev	r7,r7
+# endif
+	stmia	r8,{r0,r1,r2,r3,r4,r5,r6,r7}
+	add	r10,sp,#4*(0)
+	sub	r11,r11,#64*3	@ len-=64*3
+
+.Loop_tail_neon:
+	ldrb	r8,[r10],#1	@ read buffer on stack
+	ldrb	r9,[r12],#1		@ read input
+	subs	r11,r11,#1
+	eor	r8,r8,r9
+	strb	r8,[r14],#1		@ store output
+	bne	.Loop_tail_neon
+
+.Ldone_neon:
+	add	sp,sp,#4*(32+4)
+	vldmia	sp,{d8,d9,d10,d11,d12,d13,d14,d15}
+	add	sp,sp,#4*(16+3)
+	ldmia	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,pc}
+.size	ChaCha20_neon,.-ChaCha20_neon
+.comm	OPENSSL_armcap_P,4,4
+#endif
+#endif
diff --git a/linux-arm/crypto/modes/ghash-armv4.S b/linux-arm/crypto/modes/ghash-armv4.S
index d955d82..791b289 100644
--- a/linux-arm/crypto/modes/ghash-armv4.S
+++ b/linux-arm/crypto/modes/ghash-armv4.S
@@ -535,4 +535,4 @@
 .byte	71,72,65,83,72,32,102,111,114,32,65,82,77,118,52,47,78,69,79,78,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
 .align	2
 .align	2
-#endif
\ No newline at end of file
+#endif
diff --git a/linux-arm/crypto/modes/ghashv8-armx32.S b/linux-arm/crypto/modes/ghashv8-armx32.S
index 9a38ded..0e1e631 100644
--- a/linux-arm/crypto/modes/ghashv8-armx32.S
+++ b/linux-arm/crypto/modes/ghashv8-armx32.S
@@ -5,6 +5,7 @@
 .fpu	neon
 .code	32
 .globl	gcm_init_v8
+.hidden	gcm_init_v8
 .type	gcm_init_v8,%function
 .align	4
 gcm_init_v8:
@@ -55,6 +56,7 @@
 	bx	lr
 .size	gcm_init_v8,.-gcm_init_v8
 .globl	gcm_gmult_v8
+.hidden	gcm_gmult_v8
 .type	gcm_gmult_v8,%function
 .align	4
 gcm_gmult_v8:
@@ -96,6 +98,7 @@
 	bx	lr
 .size	gcm_gmult_v8,.-gcm_gmult_v8
 .globl	gcm_ghash_v8
+.hidden	gcm_ghash_v8
 .type	gcm_ghash_v8,%function
 .align	4
 gcm_ghash_v8:
@@ -230,4 +233,4 @@
 .byte	71,72,65,83,72,32,102,111,114,32,65,82,77,118,56,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
 .align	2
 .align	2
-#endif
\ No newline at end of file
+#endif
diff --git a/linux-arm/crypto/sha/sha1-armv4-large.S b/linux-arm/crypto/sha/sha1-armv4-large.S
index 66d0ef3..36955fa 100644
--- a/linux-arm/crypto/sha/sha1-armv4-large.S
+++ b/linux-arm/crypto/sha/sha1-armv4-large.S
@@ -5,6 +5,7 @@
 .code	32
 
 .globl	sha1_block_data_order
+.hidden	sha1_block_data_order
 .type	sha1_block_data_order,%function
 
 .align	5
@@ -1459,4 +1460,4 @@
 .comm	OPENSSL_armcap_P,4,4
 .hidden	OPENSSL_armcap_P
 #endif
-#endif
\ No newline at end of file
+#endif
diff --git a/linux-arm/crypto/sha/sha256-armv4.S b/linux-arm/crypto/sha/sha256-armv4.S
index 9fc3e0b..f37fd7c 100644
--- a/linux-arm/crypto/sha/sha256-armv4.S
+++ b/linux-arm/crypto/sha/sha256-armv4.S
@@ -1,4 +1,11 @@
 #if defined(__arm__)
+@ Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved.
+@
+@ Licensed under the OpenSSL license (the "License").  You may not use
+@ this file except in compliance with the License.  You can obtain a copy
+@ in the file LICENSE in the source distribution or at
+@ https://www.openssl.org/source/license.html
+
 
 @ ====================================================================
 @ Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
@@ -45,16 +52,11 @@
 #endif
 
 .text
-#if __ARM_ARCH__<7
-.code	32
-#else
+#if defined(__thumb2__)
 .syntax	unified
-# if defined(__thumb2__) && !defined(__APPLE__)
-#  define adrl adr
 .thumb
-# else
+#else
 .code	32
-# endif
 #endif
 
 .type	K256,%object
@@ -85,13 +87,14 @@
 .align	5
 
 .globl	sha256_block_data_order
+.hidden	sha256_block_data_order
 .type	sha256_block_data_order,%function
 sha256_block_data_order:
 .Lsha256_block_data_order:
-#if __ARM_ARCH__<7
+#if __ARM_ARCH__<7 && !defined(__thumb2__)
 	sub	r3,pc,#8		@ sha256_block_data_order
 #else
-	adr	r3,sha256_block_data_order
+	adr	r3,.Lsha256_block_data_order
 #endif
 #if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
 	ldr	r12,.LOPENSSL_armcap
@@ -1875,14 +1878,16 @@
 .fpu	neon
 
 .globl	sha256_block_data_order_neon
+.hidden	sha256_block_data_order_neon
 .type	sha256_block_data_order_neon,%function
-.align	4
+.align	5
+.skip	16
 sha256_block_data_order_neon:
 .LNEON:
 	stmdb	sp!,{r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}
 
 	sub	r11,sp,#16*4+16
-	adrl	r14,K256
+	adr	r14,K256
 	bic	r11,r11,#15		@ align for 128-bit stores
 	mov	r12,sp
 	mov	sp,r11			@ alloca
@@ -2658,7 +2663,7 @@
 #endif
 #if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
 
-# if defined(__thumb2__) && !defined(__APPLE__)
+# if defined(__thumb2__)
 #  define INST(a,b,c,d)	.byte	c,d|0xc,a,b
 # else
 #  define INST(a,b,c,d)	.byte	a,b,c,d
@@ -2669,16 +2674,11 @@
 sha256_block_data_order_armv8:
 .LARMv8:
 	vld1.32	{q0,q1},[r0]
-# ifdef	__APPLE__
 	sub	r3,r3,#256+32
-# elif	defined(__thumb2__)
-	adr	r3,.LARMv8
-	sub	r3,r3,#.LARMv8-K256
-# else
-	adrl	r3,K256
-# endif
 	add	r2,r1,r2,lsl#6	@ len to point at the end of inp
+	b	.Loop_v8
 
+.align	4
 .Loop_v8:
 	vld1.8	{q8,q9},[r1]!
 	vld1.8	{q10,q11},[r1]!
@@ -2815,4 +2815,4 @@
 .comm	OPENSSL_armcap_P,4,4
 .hidden	OPENSSL_armcap_P
 #endif
-#endif
\ No newline at end of file
+#endif
diff --git a/linux-arm/crypto/sha/sha512-armv4.S b/linux-arm/crypto/sha/sha512-armv4.S
index 834ede9..93a7bf8 100644
--- a/linux-arm/crypto/sha/sha512-armv4.S
+++ b/linux-arm/crypto/sha/sha512-armv4.S
@@ -133,6 +133,7 @@
 #endif
 
 .globl	sha512_block_data_order
+.hidden	sha512_block_data_order
 .type	sha512_block_data_order,%function
 sha512_block_data_order:
 .Lsha512_block_data_order:
@@ -147,7 +148,7 @@
 #ifdef	__APPLE__
 	ldr	r12,[r12]
 #endif
-	tst	r12,#1
+	tst	r12,#ARMV7_NEON
 	bne	.LNEON
 #endif
 	add	r2,r1,r2,lsl#7	@ len to point at the end of inp
@@ -533,6 +534,7 @@
 .fpu	neon
 
 .globl	sha512_block_data_order_neon
+.hidden	sha512_block_data_order_neon
 .type	sha512_block_data_order_neon,%function
 .align	4
 sha512_block_data_order_neon:
@@ -1866,4 +1868,4 @@
 .comm	OPENSSL_armcap_P,4,4
 .hidden	OPENSSL_armcap_P
 #endif
-#endif
\ No newline at end of file
+#endif
diff --git a/linux-ppc64le/crypto/aes/aesp8-ppc.S b/linux-ppc64le/crypto/aes/aesp8-ppc.S
new file mode 100644
index 0000000..3424ea6
--- /dev/null
+++ b/linux-ppc64le/crypto/aes/aesp8-ppc.S
@@ -0,0 +1,3633 @@
+.machine	"any"
+
+.text
+
+.align	7
+rcon:
+.byte	0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01
+.byte	0x00,0x00,0x00,0x1b,0x00,0x00,0x00,0x1b,0x00,0x00,0x00,0x1b,0x00,0x00,0x00,0x1b
+.byte	0x0c,0x0f,0x0e,0x0d,0x0c,0x0f,0x0e,0x0d,0x0c,0x0f,0x0e,0x0d,0x0c,0x0f,0x0e,0x0d
+.byte	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+Lconsts:
+	mflr	0
+	bcl	20,31,$+4
+	mflr	6
+	addi	6,6,-0x48
+	mtlr	0
+	blr	
+.long	0
+.byte	0,12,0x14,0,0,0,0,0
+.byte	65,69,83,32,102,111,114,32,80,111,119,101,114,73,83,65,32,50,46,48,55,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.align	2
+
+.globl	aes_hw_set_encrypt_key
+.align	5
+aes_hw_set_encrypt_key:
+Lset_encrypt_key:
+	mflr	11
+	std	11,16(1)
+
+	li	6,-1
+	cmpldi	3,0
+	beq-	Lenc_key_abort
+	cmpldi	5,0
+	beq-	Lenc_key_abort
+	li	6,-2
+	cmpwi	4,128
+	blt-	Lenc_key_abort
+	cmpwi	4,256
+	bgt-	Lenc_key_abort
+	andi.	0,4,0x3f
+	bne-	Lenc_key_abort
+
+	lis	0,0xfff0
+	mfspr	12,256
+	mtspr	256,0
+
+	bl	Lconsts
+	mtlr	11
+
+	neg	9,3
+	lvx	1,0,3
+	addi	3,3,15
+	lvsr	3,0,9
+	li	8,0x20
+	cmpwi	4,192
+	lvx	2,0,3
+	vspltisb	5,0x0f
+	lvx	4,0,6
+	vxor	3,3,5
+	lvx	5,8,6
+	addi	6,6,0x10
+	vperm	1,1,2,3
+	li	7,8
+	vxor	0,0,0
+	mtctr	7
+
+	lvsl	8,0,5
+	vspltisb	9,-1
+	lvx	10,0,5
+	vperm	9,9,0,8
+
+	blt	Loop128
+	addi	3,3,8
+	beq	L192
+	addi	3,3,8
+	b	L256
+
+.align	4
+Loop128:
+	vperm	3,1,1,5
+	vsldoi	6,0,1,12
+	vperm	11,1,1,8
+	vsel	7,10,11,9
+	vor	10,11,11
+	.long	0x10632509
+	stvx	7,0,5
+	addi	5,5,16
+
+	vxor	1,1,6
+	vsldoi	6,0,6,12
+	vxor	1,1,6
+	vsldoi	6,0,6,12
+	vxor	1,1,6
+	vadduwm	4,4,4
+	vxor	1,1,3
+	bc	16,0,Loop128
+
+	lvx	4,0,6
+
+	vperm	3,1,1,5
+	vsldoi	6,0,1,12
+	vperm	11,1,1,8
+	vsel	7,10,11,9
+	vor	10,11,11
+	.long	0x10632509
+	stvx	7,0,5
+	addi	5,5,16
+
+	vxor	1,1,6
+	vsldoi	6,0,6,12
+	vxor	1,1,6
+	vsldoi	6,0,6,12
+	vxor	1,1,6
+	vadduwm	4,4,4
+	vxor	1,1,3
+
+	vperm	3,1,1,5
+	vsldoi	6,0,1,12
+	vperm	11,1,1,8
+	vsel	7,10,11,9
+	vor	10,11,11
+	.long	0x10632509
+	stvx	7,0,5
+	addi	5,5,16
+
+	vxor	1,1,6
+	vsldoi	6,0,6,12
+	vxor	1,1,6
+	vsldoi	6,0,6,12
+	vxor	1,1,6
+	vxor	1,1,3
+	vperm	11,1,1,8
+	vsel	7,10,11,9
+	vor	10,11,11
+	stvx	7,0,5
+
+	addi	3,5,15
+	addi	5,5,0x50
+
+	li	8,10
+	b	Ldone
+
+.align	4
+L192:
+	lvx	6,0,3
+	li	7,4
+	vperm	11,1,1,8
+	vsel	7,10,11,9
+	vor	10,11,11
+	stvx	7,0,5
+	addi	5,5,16
+	vperm	2,2,6,3
+	vspltisb	3,8
+	mtctr	7
+	vsububm	5,5,3
+
+Loop192:
+	vperm	3,2,2,5
+	vsldoi	6,0,1,12
+	.long	0x10632509
+
+	vxor	1,1,6
+	vsldoi	6,0,6,12
+	vxor	1,1,6
+	vsldoi	6,0,6,12
+	vxor	1,1,6
+
+	vsldoi	7,0,2,8
+	vspltw	6,1,3
+	vxor	6,6,2
+	vsldoi	2,0,2,12
+	vadduwm	4,4,4
+	vxor	2,2,6
+	vxor	1,1,3
+	vxor	2,2,3
+	vsldoi	7,7,1,8
+
+	vperm	3,2,2,5
+	vsldoi	6,0,1,12
+	vperm	11,7,7,8
+	vsel	7,10,11,9
+	vor	10,11,11
+	.long	0x10632509
+	stvx	7,0,5
+	addi	5,5,16
+
+	vsldoi	7,1,2,8
+	vxor	1,1,6
+	vsldoi	6,0,6,12
+	vperm	11,7,7,8
+	vsel	7,10,11,9
+	vor	10,11,11
+	vxor	1,1,6
+	vsldoi	6,0,6,12
+	vxor	1,1,6
+	stvx	7,0,5
+	addi	5,5,16
+
+	vspltw	6,1,3
+	vxor	6,6,2
+	vsldoi	2,0,2,12
+	vadduwm	4,4,4
+	vxor	2,2,6
+	vxor	1,1,3
+	vxor	2,2,3
+	vperm	11,1,1,8
+	vsel	7,10,11,9
+	vor	10,11,11
+	stvx	7,0,5
+	addi	3,5,15
+	addi	5,5,16
+	bc	16,0,Loop192
+
+	li	8,12
+	addi	5,5,0x20
+	b	Ldone
+
+.align	4
+L256:
+	lvx	6,0,3
+	li	7,7
+	li	8,14
+	vperm	11,1,1,8
+	vsel	7,10,11,9
+	vor	10,11,11
+	stvx	7,0,5
+	addi	5,5,16
+	vperm	2,2,6,3
+	mtctr	7
+
+Loop256:
+	vperm	3,2,2,5
+	vsldoi	6,0,1,12
+	vperm	11,2,2,8
+	vsel	7,10,11,9
+	vor	10,11,11
+	.long	0x10632509
+	stvx	7,0,5
+	addi	5,5,16
+
+	vxor	1,1,6
+	vsldoi	6,0,6,12
+	vxor	1,1,6
+	vsldoi	6,0,6,12
+	vxor	1,1,6
+	vadduwm	4,4,4
+	vxor	1,1,3
+	vperm	11,1,1,8
+	vsel	7,10,11,9
+	vor	10,11,11
+	stvx	7,0,5
+	addi	3,5,15
+	addi	5,5,16
+	bdz	Ldone
+
+	vspltw	3,1,3
+	vsldoi	6,0,2,12
+	.long	0x106305C8
+
+	vxor	2,2,6
+	vsldoi	6,0,6,12
+	vxor	2,2,6
+	vsldoi	6,0,6,12
+	vxor	2,2,6
+
+	vxor	2,2,3
+	b	Loop256
+
+.align	4
+Ldone:
+	lvx	2,0,3
+	vsel	2,10,2,9
+	stvx	2,0,3
+	li	6,0
+	mtspr	256,12
+	stw	8,0(5)
+
+Lenc_key_abort:
+	mr	3,6
+	blr	
+.long	0
+.byte	0,12,0x14,1,0,0,3,0
+.long	0
+
+
+.globl	aes_hw_set_decrypt_key
+.align	5
+aes_hw_set_decrypt_key:
+	stdu	1,-64(1)
+	mflr	10
+	std	10,64+16(1)
+	bl	Lset_encrypt_key
+	mtlr	10
+
+	cmpwi	3,0
+	bne-	Ldec_key_abort
+
+	slwi	7,8,4
+	subi	3,5,240
+	srwi	8,8,1
+	add	5,3,7
+	mtctr	8
+
+Ldeckey:
+	lwz	0, 0(3)
+	lwz	6, 4(3)
+	lwz	7, 8(3)
+	lwz	8, 12(3)
+	addi	3,3,16
+	lwz	9, 0(5)
+	lwz	10,4(5)
+	lwz	11,8(5)
+	lwz	12,12(5)
+	stw	0, 0(5)
+	stw	6, 4(5)
+	stw	7, 8(5)
+	stw	8, 12(5)
+	subi	5,5,16
+	stw	9, -16(3)
+	stw	10,-12(3)
+	stw	11,-8(3)
+	stw	12,-4(3)
+	bc	16,0,Ldeckey
+
+	xor	3,3,3
+Ldec_key_abort:
+	addi	1,1,64
+	blr	
+.long	0
+.byte	0,12,4,1,0x80,0,3,0
+.long	0
+
+.globl	aes_hw_encrypt
+.align	5
+aes_hw_encrypt:
+	lwz	6,240(5)
+	lis	0,0xfc00
+	mfspr	12,256
+	li	7,15
+	mtspr	256,0
+
+	lvx	0,0,3
+	neg	11,4
+	lvx	1,7,3
+	lvsl	2,0,3
+	vspltisb	4,0x0f
+	lvsr	3,0,11
+	vxor	2,2,4
+	li	7,16
+	vperm	0,0,1,2
+	lvx	1,0,5
+	lvsr	5,0,5
+	srwi	6,6,1
+	lvx	2,7,5
+	addi	7,7,16
+	subi	6,6,1
+	vperm	1,2,1,5
+
+	vxor	0,0,1
+	lvx	1,7,5
+	addi	7,7,16
+	mtctr	6
+
+Loop_enc:
+	vperm	2,1,2,5
+	.long	0x10001508
+	lvx	2,7,5
+	addi	7,7,16
+	vperm	1,2,1,5
+	.long	0x10000D08
+	lvx	1,7,5
+	addi	7,7,16
+	bc	16,0,Loop_enc
+
+	vperm	2,1,2,5
+	.long	0x10001508
+	lvx	2,7,5
+	vperm	1,2,1,5
+	.long	0x10000D09
+
+	vspltisb	2,-1
+	vxor	1,1,1
+	li	7,15
+	vperm	2,2,1,3
+	vxor	3,3,4
+	lvx	1,0,4
+	vperm	0,0,0,3
+	vsel	1,1,0,2
+	lvx	4,7,4
+	stvx	1,0,4
+	vsel	0,0,4,2
+	stvx	0,7,4
+
+	mtspr	256,12
+	blr	
+.long	0
+.byte	0,12,0x14,0,0,0,3,0
+.long	0
+
+.globl	aes_hw_decrypt
+.align	5
+aes_hw_decrypt:
+	lwz	6,240(5)
+	lis	0,0xfc00
+	mfspr	12,256
+	li	7,15
+	mtspr	256,0
+
+	lvx	0,0,3
+	neg	11,4
+	lvx	1,7,3
+	lvsl	2,0,3
+	vspltisb	4,0x0f
+	lvsr	3,0,11
+	vxor	2,2,4
+	li	7,16
+	vperm	0,0,1,2
+	lvx	1,0,5
+	lvsr	5,0,5
+	srwi	6,6,1
+	lvx	2,7,5
+	addi	7,7,16
+	subi	6,6,1
+	vperm	1,2,1,5
+
+	vxor	0,0,1
+	lvx	1,7,5
+	addi	7,7,16
+	mtctr	6
+
+Loop_dec:
+	vperm	2,1,2,5
+	.long	0x10001548
+	lvx	2,7,5
+	addi	7,7,16
+	vperm	1,2,1,5
+	.long	0x10000D48
+	lvx	1,7,5
+	addi	7,7,16
+	bc	16,0,Loop_dec
+
+	vperm	2,1,2,5
+	.long	0x10001548
+	lvx	2,7,5
+	vperm	1,2,1,5
+	.long	0x10000D49
+
+	vspltisb	2,-1
+	vxor	1,1,1
+	li	7,15
+	vperm	2,2,1,3
+	vxor	3,3,4
+	lvx	1,0,4
+	vperm	0,0,0,3
+	vsel	1,1,0,2
+	lvx	4,7,4
+	stvx	1,0,4
+	vsel	0,0,4,2
+	stvx	0,7,4
+
+	mtspr	256,12
+	blr	
+.long	0
+.byte	0,12,0x14,0,0,0,3,0
+.long	0
+
+.globl	aes_hw_cbc_encrypt
+.align	5
+aes_hw_cbc_encrypt:
+	cmpldi	5,16
+	bclr	14,0
+
+	cmpwi	8,0
+	lis	0,0xffe0
+	mfspr	12,256
+	mtspr	256,0
+
+	li	10,15
+	vxor	0,0,0
+	vspltisb	3,0x0f
+
+	lvx	4,0,7
+	lvsl	6,0,7
+	lvx	5,10,7
+	vxor	6,6,3
+	vperm	4,4,5,6
+
+	neg	11,3
+	lvsr	10,0,6
+	lwz	9,240(6)
+
+	lvsr	6,0,11
+	lvx	5,0,3
+	addi	3,3,15
+	vxor	6,6,3
+
+	lvsl	8,0,4
+	vspltisb	9,-1
+	lvx	7,0,4
+	vperm	9,9,0,8
+	vxor	8,8,3
+
+	srwi	9,9,1
+	li	10,16
+	subi	9,9,1
+	beq	Lcbc_dec
+
+Lcbc_enc:
+	vor	2,5,5
+	lvx	5,0,3
+	addi	3,3,16
+	mtctr	9
+	subi	5,5,16
+
+	lvx	0,0,6
+	vperm	2,2,5,6
+	lvx	1,10,6
+	addi	10,10,16
+	vperm	0,1,0,10
+	vxor	2,2,0
+	lvx	0,10,6
+	addi	10,10,16
+	vxor	2,2,4
+
+Loop_cbc_enc:
+	vperm	1,0,1,10
+	.long	0x10420D08
+	lvx	1,10,6
+	addi	10,10,16
+	vperm	0,1,0,10
+	.long	0x10420508
+	lvx	0,10,6
+	addi	10,10,16
+	bc	16,0,Loop_cbc_enc
+
+	vperm	1,0,1,10
+	.long	0x10420D08
+	lvx	1,10,6
+	li	10,16
+	vperm	0,1,0,10
+	.long	0x10820509
+	cmpldi	5,16
+
+	vperm	3,4,4,8
+	vsel	2,7,3,9
+	vor	7,3,3
+	stvx	2,0,4
+	addi	4,4,16
+	bge	Lcbc_enc
+
+	b	Lcbc_done
+
+.align	4
+Lcbc_dec:
+	cmpldi	5,128
+	bge	_aesp8_cbc_decrypt8x
+	vor	3,5,5
+	lvx	5,0,3
+	addi	3,3,16
+	mtctr	9
+	subi	5,5,16
+
+	lvx	0,0,6
+	vperm	3,3,5,6
+	lvx	1,10,6
+	addi	10,10,16
+	vperm	0,1,0,10
+	vxor	2,3,0
+	lvx	0,10,6
+	addi	10,10,16
+
+Loop_cbc_dec:
+	vperm	1,0,1,10
+	.long	0x10420D48
+	lvx	1,10,6
+	addi	10,10,16
+	vperm	0,1,0,10
+	.long	0x10420548
+	lvx	0,10,6
+	addi	10,10,16
+	bc	16,0,Loop_cbc_dec
+
+	vperm	1,0,1,10
+	.long	0x10420D48
+	lvx	1,10,6
+	li	10,16
+	vperm	0,1,0,10
+	.long	0x10420549
+	cmpldi	5,16
+
+	vxor	2,2,4
+	vor	4,3,3
+	vperm	3,2,2,8
+	vsel	2,7,3,9
+	vor	7,3,3
+	stvx	2,0,4
+	addi	4,4,16
+	bge	Lcbc_dec
+
+Lcbc_done:
+	addi	4,4,-1
+	lvx	2,0,4
+	vsel	2,7,2,9
+	stvx	2,0,4
+
+	neg	8,7
+	li	10,15
+	vxor	0,0,0
+	vspltisb	9,-1
+	vspltisb	3,0x0f
+	lvsr	8,0,8
+	vperm	9,9,0,8
+	vxor	8,8,3
+	lvx	7,0,7
+	vperm	4,4,4,8
+	vsel	2,7,4,9
+	lvx	5,10,7
+	stvx	2,0,7
+	vsel	2,4,5,9
+	stvx	2,10,7
+
+	mtspr	256,12
+	blr	
+.long	0
+.byte	0,12,0x14,0,0,0,6,0
+.long	0
+.align	5
+_aesp8_cbc_decrypt8x:
+	stdu	1,-448(1)
+	li	10,207
+	li	11,223
+	stvx	20,10,1
+	addi	10,10,32
+	stvx	21,11,1
+	addi	11,11,32
+	stvx	22,10,1
+	addi	10,10,32
+	stvx	23,11,1
+	addi	11,11,32
+	stvx	24,10,1
+	addi	10,10,32
+	stvx	25,11,1
+	addi	11,11,32
+	stvx	26,10,1
+	addi	10,10,32
+	stvx	27,11,1
+	addi	11,11,32
+	stvx	28,10,1
+	addi	10,10,32
+	stvx	29,11,1
+	addi	11,11,32
+	stvx	30,10,1
+	stvx	31,11,1
+	li	0,-1
+	stw	12,396(1)
+	li	8,0x10
+	std	26,400(1)
+	li	26,0x20
+	std	27,408(1)
+	li	27,0x30
+	std	28,416(1)
+	li	28,0x40
+	std	29,424(1)
+	li	29,0x50
+	std	30,432(1)
+	li	30,0x60
+	std	31,440(1)
+	li	31,0x70
+	mtspr	256,0
+
+	subi	9,9,3
+	subi	5,5,128
+
+	lvx	23,0,6
+	lvx	30,8,6
+	addi	6,6,0x20
+	lvx	31,0,6
+	vperm	23,30,23,10
+	addi	11,1,64+15
+	mtctr	9
+
+Load_cbc_dec_key:
+	vperm	24,31,30,10
+	lvx	30,8,6
+	addi	6,6,0x20
+	stvx	24,0,11
+	vperm	25,30,31,10
+	lvx	31,0,6
+	stvx	25,8,11
+	addi	11,11,0x20
+	bc	16,0,Load_cbc_dec_key
+
+	lvx	26,8,6
+	vperm	24,31,30,10
+	lvx	27,26,6
+	stvx	24,0,11
+	vperm	25,26,31,10
+	lvx	28,27,6
+	stvx	25,8,11
+	addi	11,1,64+15
+	vperm	26,27,26,10
+	lvx	29,28,6
+	vperm	27,28,27,10
+	lvx	30,29,6
+	vperm	28,29,28,10
+	lvx	31,30,6
+	vperm	29,30,29,10
+	lvx	14,31,6
+	vperm	30,31,30,10
+	lvx	24,0,11
+	vperm	31,14,31,10
+	lvx	25,8,11
+
+
+
+	subi	3,3,15
+
+	li	10,8
+	.long	0x7C001E99
+	lvsl	6,0,10
+	vspltisb	3,0x0f
+	.long	0x7C281E99
+	vxor	6,6,3
+	.long	0x7C5A1E99
+	vperm	0,0,0,6
+	.long	0x7C7B1E99
+	vperm	1,1,1,6
+	.long	0x7D5C1E99
+	vperm	2,2,2,6
+	vxor	14,0,23
+	.long	0x7D7D1E99
+	vperm	3,3,3,6
+	vxor	15,1,23
+	.long	0x7D9E1E99
+	vperm	10,10,10,6
+	vxor	16,2,23
+	.long	0x7DBF1E99
+	addi	3,3,0x80
+	vperm	11,11,11,6
+	vxor	17,3,23
+	vperm	12,12,12,6
+	vxor	18,10,23
+	vperm	13,13,13,6
+	vxor	19,11,23
+	vxor	20,12,23
+	vxor	21,13,23
+
+	mtctr	9
+	b	Loop_cbc_dec8x
+.align	5
+Loop_cbc_dec8x:
+	.long	0x11CEC548
+	.long	0x11EFC548
+	.long	0x1210C548
+	.long	0x1231C548
+	.long	0x1252C548
+	.long	0x1273C548
+	.long	0x1294C548
+	.long	0x12B5C548
+	lvx	24,26,11
+	addi	11,11,0x20
+
+	.long	0x11CECD48
+	.long	0x11EFCD48
+	.long	0x1210CD48
+	.long	0x1231CD48
+	.long	0x1252CD48
+	.long	0x1273CD48
+	.long	0x1294CD48
+	.long	0x12B5CD48
+	lvx	25,8,11
+	bc	16,0,Loop_cbc_dec8x
+
+	subic	5,5,128
+	.long	0x11CEC548
+	.long	0x11EFC548
+	.long	0x1210C548
+	.long	0x1231C548
+	.long	0x1252C548
+	.long	0x1273C548
+	.long	0x1294C548
+	.long	0x12B5C548
+
+	subfe.	0,0,0
+	.long	0x11CECD48
+	.long	0x11EFCD48
+	.long	0x1210CD48
+	.long	0x1231CD48
+	.long	0x1252CD48
+	.long	0x1273CD48
+	.long	0x1294CD48
+	.long	0x12B5CD48
+
+	and	0,0,5
+	.long	0x11CED548
+	.long	0x11EFD548
+	.long	0x1210D548
+	.long	0x1231D548
+	.long	0x1252D548
+	.long	0x1273D548
+	.long	0x1294D548
+	.long	0x12B5D548
+
+	add	3,3,0
+
+
+
+	.long	0x11CEDD48
+	.long	0x11EFDD48
+	.long	0x1210DD48
+	.long	0x1231DD48
+	.long	0x1252DD48
+	.long	0x1273DD48
+	.long	0x1294DD48
+	.long	0x12B5DD48
+
+	addi	11,1,64+15
+	.long	0x11CEE548
+	.long	0x11EFE548
+	.long	0x1210E548
+	.long	0x1231E548
+	.long	0x1252E548
+	.long	0x1273E548
+	.long	0x1294E548
+	.long	0x12B5E548
+	lvx	24,0,11
+
+	.long	0x11CEED48
+	.long	0x11EFED48
+	.long	0x1210ED48
+	.long	0x1231ED48
+	.long	0x1252ED48
+	.long	0x1273ED48
+	.long	0x1294ED48
+	.long	0x12B5ED48
+	lvx	25,8,11
+
+	.long	0x11CEF548
+	vxor	4,4,31
+	.long	0x11EFF548
+	vxor	0,0,31
+	.long	0x1210F548
+	vxor	1,1,31
+	.long	0x1231F548
+	vxor	2,2,31
+	.long	0x1252F548
+	vxor	3,3,31
+	.long	0x1273F548
+	vxor	10,10,31
+	.long	0x1294F548
+	vxor	11,11,31
+	.long	0x12B5F548
+	vxor	12,12,31
+
+	.long	0x11CE2549
+	.long	0x11EF0549
+	.long	0x7C001E99
+	.long	0x12100D49
+	.long	0x7C281E99
+	.long	0x12311549
+	vperm	0,0,0,6
+	.long	0x7C5A1E99
+	.long	0x12521D49
+	vperm	1,1,1,6
+	.long	0x7C7B1E99
+	.long	0x12735549
+	vperm	2,2,2,6
+	.long	0x7D5C1E99
+	.long	0x12945D49
+	vperm	3,3,3,6
+	.long	0x7D7D1E99
+	.long	0x12B56549
+	vperm	10,10,10,6
+	.long	0x7D9E1E99
+	vor	4,13,13
+	vperm	11,11,11,6
+	.long	0x7DBF1E99
+	addi	3,3,0x80
+
+	vperm	14,14,14,6
+	vperm	15,15,15,6
+	.long	0x7DC02799
+	vperm	12,12,12,6
+	vxor	14,0,23
+	vperm	16,16,16,6
+	.long	0x7DE82799
+	vperm	13,13,13,6
+	vxor	15,1,23
+	vperm	17,17,17,6
+	.long	0x7E1A2799
+	vxor	16,2,23
+	vperm	18,18,18,6
+	.long	0x7E3B2799
+	vxor	17,3,23
+	vperm	19,19,19,6
+	.long	0x7E5C2799
+	vxor	18,10,23
+	vperm	20,20,20,6
+	.long	0x7E7D2799
+	vxor	19,11,23
+	vperm	21,21,21,6
+	.long	0x7E9E2799
+	vxor	20,12,23
+	.long	0x7EBF2799
+	addi	4,4,0x80
+	vxor	21,13,23
+
+	mtctr	9
+	beq	Loop_cbc_dec8x
+
+	addic.	5,5,128
+	beq	Lcbc_dec8x_done
+	nop	
+	nop	
+
+Loop_cbc_dec8x_tail:
+	.long	0x11EFC548
+	.long	0x1210C548
+	.long	0x1231C548
+	.long	0x1252C548
+	.long	0x1273C548
+	.long	0x1294C548
+	.long	0x12B5C548
+	lvx	24,26,11
+	addi	11,11,0x20
+
+	.long	0x11EFCD48
+	.long	0x1210CD48
+	.long	0x1231CD48
+	.long	0x1252CD48
+	.long	0x1273CD48
+	.long	0x1294CD48
+	.long	0x12B5CD48
+	lvx	25,8,11
+	bc	16,0,Loop_cbc_dec8x_tail
+
+	.long	0x11EFC548
+	.long	0x1210C548
+	.long	0x1231C548
+	.long	0x1252C548
+	.long	0x1273C548
+	.long	0x1294C548
+	.long	0x12B5C548
+
+	.long	0x11EFCD48
+	.long	0x1210CD48
+	.long	0x1231CD48
+	.long	0x1252CD48
+	.long	0x1273CD48
+	.long	0x1294CD48
+	.long	0x12B5CD48
+
+	.long	0x11EFD548
+	.long	0x1210D548
+	.long	0x1231D548
+	.long	0x1252D548
+	.long	0x1273D548
+	.long	0x1294D548
+	.long	0x12B5D548
+
+	.long	0x11EFDD48
+	.long	0x1210DD48
+	.long	0x1231DD48
+	.long	0x1252DD48
+	.long	0x1273DD48
+	.long	0x1294DD48
+	.long	0x12B5DD48
+
+	.long	0x11EFE548
+	.long	0x1210E548
+	.long	0x1231E548
+	.long	0x1252E548
+	.long	0x1273E548
+	.long	0x1294E548
+	.long	0x12B5E548
+
+	.long	0x11EFED48
+	.long	0x1210ED48
+	.long	0x1231ED48
+	.long	0x1252ED48
+	.long	0x1273ED48
+	.long	0x1294ED48
+	.long	0x12B5ED48
+
+	.long	0x11EFF548
+	vxor	4,4,31
+	.long	0x1210F548
+	vxor	1,1,31
+	.long	0x1231F548
+	vxor	2,2,31
+	.long	0x1252F548
+	vxor	3,3,31
+	.long	0x1273F548
+	vxor	10,10,31
+	.long	0x1294F548
+	vxor	11,11,31
+	.long	0x12B5F548
+	vxor	12,12,31
+
+	cmplwi	5,32
+	blt	Lcbc_dec8x_one
+	nop	
+	beq	Lcbc_dec8x_two
+	cmplwi	5,64
+	blt	Lcbc_dec8x_three
+	nop	
+	beq	Lcbc_dec8x_four
+	cmplwi	5,96
+	blt	Lcbc_dec8x_five
+	nop	
+	beq	Lcbc_dec8x_six
+
+Lcbc_dec8x_seven:
+	.long	0x11EF2549
+	.long	0x12100D49
+	.long	0x12311549
+	.long	0x12521D49
+	.long	0x12735549
+	.long	0x12945D49
+	.long	0x12B56549
+	vor	4,13,13
+
+	vperm	15,15,15,6
+	vperm	16,16,16,6
+	.long	0x7DE02799
+	vperm	17,17,17,6
+	.long	0x7E082799
+	vperm	18,18,18,6
+	.long	0x7E3A2799
+	vperm	19,19,19,6
+	.long	0x7E5B2799
+	vperm	20,20,20,6
+	.long	0x7E7C2799
+	vperm	21,21,21,6
+	.long	0x7E9D2799
+	.long	0x7EBE2799
+	addi	4,4,0x70
+	b	Lcbc_dec8x_done
+
+.align	5
+Lcbc_dec8x_six:
+	.long	0x12102549
+	.long	0x12311549
+	.long	0x12521D49
+	.long	0x12735549
+	.long	0x12945D49
+	.long	0x12B56549
+	vor	4,13,13
+
+	vperm	16,16,16,6
+	vperm	17,17,17,6
+	.long	0x7E002799
+	vperm	18,18,18,6
+	.long	0x7E282799
+	vperm	19,19,19,6
+	.long	0x7E5A2799
+	vperm	20,20,20,6
+	.long	0x7E7B2799
+	vperm	21,21,21,6
+	.long	0x7E9C2799
+	.long	0x7EBD2799
+	addi	4,4,0x60
+	b	Lcbc_dec8x_done
+
+.align	5
+Lcbc_dec8x_five:
+	.long	0x12312549
+	.long	0x12521D49
+	.long	0x12735549
+	.long	0x12945D49
+	.long	0x12B56549
+	vor	4,13,13
+
+	vperm	17,17,17,6
+	vperm	18,18,18,6
+	.long	0x7E202799
+	vperm	19,19,19,6
+	.long	0x7E482799
+	vperm	20,20,20,6
+	.long	0x7E7A2799
+	vperm	21,21,21,6
+	.long	0x7E9B2799
+	.long	0x7EBC2799
+	addi	4,4,0x50
+	b	Lcbc_dec8x_done
+
+.align	5
+Lcbc_dec8x_four:
+	.long	0x12522549
+	.long	0x12735549
+	.long	0x12945D49
+	.long	0x12B56549
+	vor	4,13,13
+
+	vperm	18,18,18,6
+	vperm	19,19,19,6
+	.long	0x7E402799
+	vperm	20,20,20,6
+	.long	0x7E682799
+	vperm	21,21,21,6
+	.long	0x7E9A2799
+	.long	0x7EBB2799
+	addi	4,4,0x40
+	b	Lcbc_dec8x_done
+
+.align	5
+Lcbc_dec8x_three:
+	.long	0x12732549
+	.long	0x12945D49
+	.long	0x12B56549
+	vor	4,13,13
+
+	vperm	19,19,19,6
+	vperm	20,20,20,6
+	.long	0x7E602799
+	vperm	21,21,21,6
+	.long	0x7E882799
+	.long	0x7EBA2799
+	addi	4,4,0x30
+	b	Lcbc_dec8x_done
+
+.align	5
+Lcbc_dec8x_two:
+	.long	0x12942549
+	.long	0x12B56549
+	vor	4,13,13
+
+	vperm	20,20,20,6
+	vperm	21,21,21,6
+	.long	0x7E802799
+	.long	0x7EA82799
+	addi	4,4,0x20
+	b	Lcbc_dec8x_done
+
+.align	5
+Lcbc_dec8x_one:
+	.long	0x12B52549
+	vor	4,13,13
+
+	vperm	21,21,21,6
+	.long	0x7EA02799
+	addi	4,4,0x10
+
+Lcbc_dec8x_done:
+	vperm	4,4,4,6
+	.long	0x7C803F99
+
+	li	10,79
+	li	11,95
+	stvx	6,10,1
+	addi	10,10,32
+	stvx	6,11,1
+	addi	11,11,32
+	stvx	6,10,1
+	addi	10,10,32
+	stvx	6,11,1
+	addi	11,11,32
+	stvx	6,10,1
+	addi	10,10,32
+	stvx	6,11,1
+	addi	11,11,32
+	stvx	6,10,1
+	addi	10,10,32
+	stvx	6,11,1
+	addi	11,11,32
+
+	mtspr	256,12
+	lvx	20,10,1
+	addi	10,10,32
+	lvx	21,11,1
+	addi	11,11,32
+	lvx	22,10,1
+	addi	10,10,32
+	lvx	23,11,1
+	addi	11,11,32
+	lvx	24,10,1
+	addi	10,10,32
+	lvx	25,11,1
+	addi	11,11,32
+	lvx	26,10,1
+	addi	10,10,32
+	lvx	27,11,1
+	addi	11,11,32
+	lvx	28,10,1
+	addi	10,10,32
+	lvx	29,11,1
+	addi	11,11,32
+	lvx	30,10,1
+	lvx	31,11,1
+	ld	26,400(1)
+	ld	27,408(1)
+	ld	28,416(1)
+	ld	29,424(1)
+	ld	30,432(1)
+	ld	31,440(1)
+	addi	1,1,448
+	blr	
+.long	0
+.byte	0,12,0x04,0,0x80,6,6,0
+.long	0
+
+.globl	aes_hw_ctr32_encrypt_blocks
+.align	5
+aes_hw_ctr32_encrypt_blocks:
+	cmpldi	5,1
+	bclr	14,0
+
+	lis	0,0xfff0
+	mfspr	12,256
+	mtspr	256,0
+
+	li	10,15
+	vxor	0,0,0
+	vspltisb	3,0x0f
+
+	lvx	4,0,7
+	lvsl	6,0,7
+	lvx	5,10,7
+	vspltisb	11,1
+	vxor	6,6,3
+	vperm	4,4,5,6
+	vsldoi	11,0,11,1
+
+	neg	11,3
+	lvsr	10,0,6
+	lwz	9,240(6)
+
+	lvsr	6,0,11
+	lvx	5,0,3
+	addi	3,3,15
+	vxor	6,6,3
+
+	srwi	9,9,1
+	li	10,16
+	subi	9,9,1
+
+	cmpldi	5,8
+	bge	_aesp8_ctr32_encrypt8x
+
+	lvsl	8,0,4
+	vspltisb	9,-1
+	lvx	7,0,4
+	vperm	9,9,0,8
+	vxor	8,8,3
+
+	lvx	0,0,6
+	mtctr	9
+	lvx	1,10,6
+	addi	10,10,16
+	vperm	0,1,0,10
+	vxor	2,4,0
+	lvx	0,10,6
+	addi	10,10,16
+	b	Loop_ctr32_enc
+
+.align	5
+Loop_ctr32_enc:
+	vperm	1,0,1,10
+	.long	0x10420D08
+	lvx	1,10,6
+	addi	10,10,16
+	vperm	0,1,0,10
+	.long	0x10420508
+	lvx	0,10,6
+	addi	10,10,16
+	bc	16,0,Loop_ctr32_enc
+
+	vadduwm	4,4,11
+	vor	3,5,5
+	lvx	5,0,3
+	addi	3,3,16
+	subic.	5,5,1
+
+	vperm	1,0,1,10
+	.long	0x10420D08
+	lvx	1,10,6
+	vperm	3,3,5,6
+	li	10,16
+	vperm	1,1,0,10
+	lvx	0,0,6
+	vxor	3,3,1
+	.long	0x10421D09
+
+	lvx	1,10,6
+	addi	10,10,16
+	vperm	2,2,2,8
+	vsel	3,7,2,9
+	mtctr	9
+	vperm	0,1,0,10
+	vor	7,2,2
+	vxor	2,4,0
+	lvx	0,10,6
+	addi	10,10,16
+	stvx	3,0,4
+	addi	4,4,16
+	bne	Loop_ctr32_enc
+
+	addi	4,4,-1
+	lvx	2,0,4
+	vsel	2,7,2,9
+	stvx	2,0,4
+
+	mtspr	256,12
+	blr	
+.long	0
+.byte	0,12,0x14,0,0,0,6,0
+.long	0
+.align	5
+_aesp8_ctr32_encrypt8x:
+	stdu	1,-448(1)
+	li	10,207
+	li	11,223
+	stvx	20,10,1
+	addi	10,10,32
+	stvx	21,11,1
+	addi	11,11,32
+	stvx	22,10,1
+	addi	10,10,32
+	stvx	23,11,1
+	addi	11,11,32
+	stvx	24,10,1
+	addi	10,10,32
+	stvx	25,11,1
+	addi	11,11,32
+	stvx	26,10,1
+	addi	10,10,32
+	stvx	27,11,1
+	addi	11,11,32
+	stvx	28,10,1
+	addi	10,10,32
+	stvx	29,11,1
+	addi	11,11,32
+	stvx	30,10,1
+	stvx	31,11,1
+	li	0,-1
+	stw	12,396(1)
+	li	8,0x10
+	std	26,400(1)
+	li	26,0x20
+	std	27,408(1)
+	li	27,0x30
+	std	28,416(1)
+	li	28,0x40
+	std	29,424(1)
+	li	29,0x50
+	std	30,432(1)
+	li	30,0x60
+	std	31,440(1)
+	li	31,0x70
+	mtspr	256,0
+
+	subi	9,9,3
+
+	lvx	23,0,6
+	lvx	30,8,6
+	addi	6,6,0x20
+	lvx	31,0,6
+	vperm	23,30,23,10
+	addi	11,1,64+15
+	mtctr	9
+
+Load_ctr32_enc_key:
+	vperm	24,31,30,10
+	lvx	30,8,6
+	addi	6,6,0x20
+	stvx	24,0,11
+	vperm	25,30,31,10
+	lvx	31,0,6
+	stvx	25,8,11
+	addi	11,11,0x20
+	bc	16,0,Load_ctr32_enc_key
+
+	lvx	26,8,6
+	vperm	24,31,30,10
+	lvx	27,26,6
+	stvx	24,0,11
+	vperm	25,26,31,10
+	lvx	28,27,6
+	stvx	25,8,11
+	addi	11,1,64+15
+	vperm	26,27,26,10
+	lvx	29,28,6
+	vperm	27,28,27,10
+	lvx	30,29,6
+	vperm	28,29,28,10
+	lvx	31,30,6
+	vperm	29,30,29,10
+	lvx	15,31,6
+	vperm	30,31,30,10
+	lvx	24,0,11
+	vperm	31,15,31,10
+	lvx	25,8,11
+
+	vadduwm	7,11,11
+	subi	3,3,15
+	sldi	5,5,4
+
+	vadduwm	16,4,11
+	vadduwm	17,4,7
+	vxor	15,4,23
+	li	10,8
+	vadduwm	18,16,7
+	vxor	16,16,23
+	lvsl	6,0,10
+	vadduwm	19,17,7
+	vxor	17,17,23
+	vspltisb	3,0x0f
+	vadduwm	20,18,7
+	vxor	18,18,23
+	vxor	6,6,3
+	vadduwm	21,19,7
+	vxor	19,19,23
+	vadduwm	22,20,7
+	vxor	20,20,23
+	vadduwm	4,21,7
+	vxor	21,21,23
+	vxor	22,22,23
+
+	mtctr	9
+	b	Loop_ctr32_enc8x
+.align	5
+Loop_ctr32_enc8x:
+	.long	0x11EFC508
+	.long	0x1210C508
+	.long	0x1231C508
+	.long	0x1252C508
+	.long	0x1273C508
+	.long	0x1294C508
+	.long	0x12B5C508
+	.long	0x12D6C508
+Loop_ctr32_enc8x_middle:
+	lvx	24,26,11
+	addi	11,11,0x20
+
+	.long	0x11EFCD08
+	.long	0x1210CD08
+	.long	0x1231CD08
+	.long	0x1252CD08
+	.long	0x1273CD08
+	.long	0x1294CD08
+	.long	0x12B5CD08
+	.long	0x12D6CD08
+	lvx	25,8,11
+	bc	16,0,Loop_ctr32_enc8x
+
+	subic	11,5,256
+	.long	0x11EFC508
+	.long	0x1210C508
+	.long	0x1231C508
+	.long	0x1252C508
+	.long	0x1273C508
+	.long	0x1294C508
+	.long	0x12B5C508
+	.long	0x12D6C508
+
+	subfe	0,0,0
+	.long	0x11EFCD08
+	.long	0x1210CD08
+	.long	0x1231CD08
+	.long	0x1252CD08
+	.long	0x1273CD08
+	.long	0x1294CD08
+	.long	0x12B5CD08
+	.long	0x12D6CD08
+
+	and	0,0,11
+	addi	11,1,64+15
+	.long	0x11EFD508
+	.long	0x1210D508
+	.long	0x1231D508
+	.long	0x1252D508
+	.long	0x1273D508
+	.long	0x1294D508
+	.long	0x12B5D508
+	.long	0x12D6D508
+	lvx	24,0,11
+
+	subic	5,5,129
+	.long	0x11EFDD08
+	addi	5,5,1
+	.long	0x1210DD08
+	.long	0x1231DD08
+	.long	0x1252DD08
+	.long	0x1273DD08
+	.long	0x1294DD08
+	.long	0x12B5DD08
+	.long	0x12D6DD08
+	lvx	25,8,11
+
+	.long	0x11EFE508
+	.long	0x7C001E99
+	.long	0x1210E508
+	.long	0x7C281E99
+	.long	0x1231E508
+	.long	0x7C5A1E99
+	.long	0x1252E508
+	.long	0x7C7B1E99
+	.long	0x1273E508
+	.long	0x7D5C1E99
+	.long	0x1294E508
+	.long	0x7D9D1E99
+	.long	0x12B5E508
+	.long	0x7DBE1E99
+	.long	0x12D6E508
+	.long	0x7DDF1E99
+	addi	3,3,0x80
+
+	.long	0x11EFED08
+	vperm	0,0,0,6
+	.long	0x1210ED08
+	vperm	1,1,1,6
+	.long	0x1231ED08
+	vperm	2,2,2,6
+	.long	0x1252ED08
+	vperm	3,3,3,6
+	.long	0x1273ED08
+	vperm	10,10,10,6
+	.long	0x1294ED08
+	vperm	12,12,12,6
+	.long	0x12B5ED08
+	vperm	13,13,13,6
+	.long	0x12D6ED08
+	vperm	14,14,14,6
+
+	add	3,3,0
+
+
+
+	subfe.	0,0,0
+	.long	0x11EFF508
+	vxor	0,0,31
+	.long	0x1210F508
+	vxor	1,1,31
+	.long	0x1231F508
+	vxor	2,2,31
+	.long	0x1252F508
+	vxor	3,3,31
+	.long	0x1273F508
+	vxor	10,10,31
+	.long	0x1294F508
+	vxor	12,12,31
+	.long	0x12B5F508
+	vxor	13,13,31
+	.long	0x12D6F508
+	vxor	14,14,31
+
+	bne	Lctr32_enc8x_break
+
+	.long	0x100F0509
+	.long	0x10300D09
+	vadduwm	16,4,11
+	.long	0x10511509
+	vadduwm	17,4,7
+	vxor	15,4,23
+	.long	0x10721D09
+	vadduwm	18,16,7
+	vxor	16,16,23
+	.long	0x11535509
+	vadduwm	19,17,7
+	vxor	17,17,23
+	.long	0x11946509
+	vadduwm	20,18,7
+	vxor	18,18,23
+	.long	0x11B56D09
+	vadduwm	21,19,7
+	vxor	19,19,23
+	.long	0x11D67509
+	vadduwm	22,20,7
+	vxor	20,20,23
+	vperm	0,0,0,6
+	vadduwm	4,21,7
+	vxor	21,21,23
+	vperm	1,1,1,6
+	vxor	22,22,23
+	mtctr	9
+
+	.long	0x11EFC508
+	.long	0x7C002799
+	vperm	2,2,2,6
+	.long	0x1210C508
+	.long	0x7C282799
+	vperm	3,3,3,6
+	.long	0x1231C508
+	.long	0x7C5A2799
+	vperm	10,10,10,6
+	.long	0x1252C508
+	.long	0x7C7B2799
+	vperm	12,12,12,6
+	.long	0x1273C508
+	.long	0x7D5C2799
+	vperm	13,13,13,6
+	.long	0x1294C508
+	.long	0x7D9D2799
+	vperm	14,14,14,6
+	.long	0x12B5C508
+	.long	0x7DBE2799
+	.long	0x12D6C508
+	.long	0x7DDF2799
+	addi	4,4,0x80
+
+	b	Loop_ctr32_enc8x_middle
+
+.align	5
+Lctr32_enc8x_break:
+	cmpwi	5,-0x60
+	blt	Lctr32_enc8x_one
+	nop	
+	beq	Lctr32_enc8x_two
+	cmpwi	5,-0x40
+	blt	Lctr32_enc8x_three
+	nop	
+	beq	Lctr32_enc8x_four
+	cmpwi	5,-0x20
+	blt	Lctr32_enc8x_five
+	nop	
+	beq	Lctr32_enc8x_six
+	cmpwi	5,0x00
+	blt	Lctr32_enc8x_seven
+
+Lctr32_enc8x_eight:
+	.long	0x11EF0509
+	.long	0x12100D09
+	.long	0x12311509
+	.long	0x12521D09
+	.long	0x12735509
+	.long	0x12946509
+	.long	0x12B56D09
+	.long	0x12D67509
+
+	vperm	15,15,15,6
+	vperm	16,16,16,6
+	.long	0x7DE02799
+	vperm	17,17,17,6
+	.long	0x7E082799
+	vperm	18,18,18,6
+	.long	0x7E3A2799
+	vperm	19,19,19,6
+	.long	0x7E5B2799
+	vperm	20,20,20,6
+	.long	0x7E7C2799
+	vperm	21,21,21,6
+	.long	0x7E9D2799
+	vperm	22,22,22,6
+	.long	0x7EBE2799
+	.long	0x7EDF2799
+	addi	4,4,0x80
+	b	Lctr32_enc8x_done
+
+.align	5
+Lctr32_enc8x_seven:
+	.long	0x11EF0D09
+	.long	0x12101509
+	.long	0x12311D09
+	.long	0x12525509
+	.long	0x12736509
+	.long	0x12946D09
+	.long	0x12B57509
+
+	vperm	15,15,15,6
+	vperm	16,16,16,6
+	.long	0x7DE02799
+	vperm	17,17,17,6
+	.long	0x7E082799
+	vperm	18,18,18,6
+	.long	0x7E3A2799
+	vperm	19,19,19,6
+	.long	0x7E5B2799
+	vperm	20,20,20,6
+	.long	0x7E7C2799
+	vperm	21,21,21,6
+	.long	0x7E9D2799
+	.long	0x7EBE2799
+	addi	4,4,0x70
+	b	Lctr32_enc8x_done
+
+.align	5
+Lctr32_enc8x_six:
+	.long	0x11EF1509
+	.long	0x12101D09
+	.long	0x12315509
+	.long	0x12526509
+	.long	0x12736D09
+	.long	0x12947509
+
+	vperm	15,15,15,6
+	vperm	16,16,16,6
+	.long	0x7DE02799
+	vperm	17,17,17,6
+	.long	0x7E082799
+	vperm	18,18,18,6
+	.long	0x7E3A2799
+	vperm	19,19,19,6
+	.long	0x7E5B2799
+	vperm	20,20,20,6
+	.long	0x7E7C2799
+	.long	0x7E9D2799
+	addi	4,4,0x60
+	b	Lctr32_enc8x_done
+
+.align	5
+Lctr32_enc8x_five:
+	.long	0x11EF1D09
+	.long	0x12105509
+	.long	0x12316509
+	.long	0x12526D09
+	.long	0x12737509
+
+	vperm	15,15,15,6
+	vperm	16,16,16,6
+	.long	0x7DE02799
+	vperm	17,17,17,6
+	.long	0x7E082799
+	vperm	18,18,18,6
+	.long	0x7E3A2799
+	vperm	19,19,19,6
+	.long	0x7E5B2799
+	.long	0x7E7C2799
+	addi	4,4,0x50
+	b	Lctr32_enc8x_done
+
+.align	5
+Lctr32_enc8x_four:
+	.long	0x11EF5509
+	.long	0x12106509
+	.long	0x12316D09
+	.long	0x12527509
+
+	vperm	15,15,15,6
+	vperm	16,16,16,6
+	.long	0x7DE02799
+	vperm	17,17,17,6
+	.long	0x7E082799
+	vperm	18,18,18,6
+	.long	0x7E3A2799
+	.long	0x7E5B2799
+	addi	4,4,0x40
+	b	Lctr32_enc8x_done
+
+.align	5
+Lctr32_enc8x_three:
+	.long	0x11EF6509
+	.long	0x12106D09
+	.long	0x12317509
+
+	vperm	15,15,15,6
+	vperm	16,16,16,6
+	.long	0x7DE02799
+	vperm	17,17,17,6
+	.long	0x7E082799
+	.long	0x7E3A2799
+	addi	4,4,0x30
+	b	Lcbc_dec8x_done
+
+.align	5
+Lctr32_enc8x_two:
+	.long	0x11EF6D09
+	.long	0x12107509
+
+	vperm	15,15,15,6
+	vperm	16,16,16,6
+	.long	0x7DE02799
+	.long	0x7E082799
+	addi	4,4,0x20
+	b	Lcbc_dec8x_done
+
+.align	5
+Lctr32_enc8x_one:
+	.long	0x11EF7509
+
+	vperm	15,15,15,6
+	.long	0x7DE02799
+	addi	4,4,0x10
+
+Lctr32_enc8x_done:
+	li	10,79
+	li	11,95
+	stvx	6,10,1
+	addi	10,10,32
+	stvx	6,11,1
+	addi	11,11,32
+	stvx	6,10,1
+	addi	10,10,32
+	stvx	6,11,1
+	addi	11,11,32
+	stvx	6,10,1
+	addi	10,10,32
+	stvx	6,11,1
+	addi	11,11,32
+	stvx	6,10,1
+	addi	10,10,32
+	stvx	6,11,1
+	addi	11,11,32
+
+	mtspr	256,12
+	lvx	20,10,1
+	addi	10,10,32
+	lvx	21,11,1
+	addi	11,11,32
+	lvx	22,10,1
+	addi	10,10,32
+	lvx	23,11,1
+	addi	11,11,32
+	lvx	24,10,1
+	addi	10,10,32
+	lvx	25,11,1
+	addi	11,11,32
+	lvx	26,10,1
+	addi	10,10,32
+	lvx	27,11,1
+	addi	11,11,32
+	lvx	28,10,1
+	addi	10,10,32
+	lvx	29,11,1
+	addi	11,11,32
+	lvx	30,10,1
+	lvx	31,11,1
+	ld	26,400(1)
+	ld	27,408(1)
+	ld	28,416(1)
+	ld	29,424(1)
+	ld	30,432(1)
+	ld	31,440(1)
+	addi	1,1,448
+	blr	
+.long	0
+.byte	0,12,0x04,0,0x80,6,6,0
+.long	0
+
+.globl	aes_hw_xts_encrypt
+.align	5
+aes_hw_xts_encrypt:
+	mr	10,3
+	li	3,-1
+	cmpldi	5,16
+	bclr	14,0
+
+	lis	0,0xfff0
+	mfspr	12,256
+	li	11,0
+	mtspr	256,0
+
+	vspltisb	9,0x07
+	lvsl	6,11,11
+	vspltisb	11,0x0f
+	vxor	6,6,9
+
+	li	3,15
+	lvx	8,0,8
+	lvsl	5,0,8
+	lvx	4,3,8
+	vxor	5,5,11
+	vperm	8,8,4,5
+
+	neg	11,10
+	lvsr	5,0,11
+	lvx	2,0,10
+	addi	10,10,15
+	vxor	5,5,11
+
+	cmpldi	7,0
+	beq	Lxts_enc_no_key2
+
+	lvsr	7,0,7
+	lwz	9,240(7)
+	srwi	9,9,1
+	subi	9,9,1
+	li	3,16
+
+	lvx	0,0,7
+	lvx	1,3,7
+	addi	3,3,16
+	vperm	0,1,0,7
+	vxor	8,8,0
+	lvx	0,3,7
+	addi	3,3,16
+	mtctr	9
+
+Ltweak_xts_enc:
+	vperm	1,0,1,7
+	.long	0x11080D08
+	lvx	1,3,7
+	addi	3,3,16
+	vperm	0,1,0,7
+	.long	0x11080508
+	lvx	0,3,7
+	addi	3,3,16
+	bc	16,0,Ltweak_xts_enc
+
+	vperm	1,0,1,7
+	.long	0x11080D08
+	lvx	1,3,7
+	vperm	0,1,0,7
+	.long	0x11080509
+
+	li	8,0
+	b	Lxts_enc
+
+Lxts_enc_no_key2:
+	li	3,-16
+	and	5,5,3
+
+
+Lxts_enc:
+	lvx	4,0,10
+	addi	10,10,16
+
+	lvsr	7,0,6
+	lwz	9,240(6)
+	srwi	9,9,1
+	subi	9,9,1
+	li	3,16
+
+	vslb	10,9,9
+	vor	10,10,9
+	vspltisb	11,1
+	vsldoi	10,10,11,15
+
+	cmpldi	5,96
+	bge	_aesp8_xts_encrypt6x
+
+	andi.	7,5,15
+	subic	0,5,32
+	subi	7,7,16
+	subfe	0,0,0
+	and	0,0,7
+	add	10,10,0
+
+	lvx	0,0,6
+	lvx	1,3,6
+	addi	3,3,16
+	vperm	2,2,4,5
+	vperm	0,1,0,7
+	vxor	2,2,8
+	vxor	2,2,0
+	lvx	0,3,6
+	addi	3,3,16
+	mtctr	9
+	b	Loop_xts_enc
+
+.align	5
+Loop_xts_enc:
+	vperm	1,0,1,7
+	.long	0x10420D08
+	lvx	1,3,6
+	addi	3,3,16
+	vperm	0,1,0,7
+	.long	0x10420508
+	lvx	0,3,6
+	addi	3,3,16
+	bc	16,0,Loop_xts_enc
+
+	vperm	1,0,1,7
+	.long	0x10420D08
+	lvx	1,3,6
+	li	3,16
+	vperm	0,1,0,7
+	vxor	0,0,8
+	.long	0x10620509
+
+	vperm	11,3,3,6
+
+	.long	0x7D602799
+
+	addi	4,4,16
+
+	subic.	5,5,16
+	beq	Lxts_enc_done
+
+	vor	2,4,4
+	lvx	4,0,10
+	addi	10,10,16
+	lvx	0,0,6
+	lvx	1,3,6
+	addi	3,3,16
+
+	subic	0,5,32
+	subfe	0,0,0
+	and	0,0,7
+	add	10,10,0
+
+	vsrab	11,8,9
+	vaddubm	8,8,8
+	vsldoi	11,11,11,15
+	vand	11,11,10
+	vxor	8,8,11
+
+	vperm	2,2,4,5
+	vperm	0,1,0,7
+	vxor	2,2,8
+	vxor	3,3,0
+	vxor	2,2,0
+	lvx	0,3,6
+	addi	3,3,16
+
+	mtctr	9
+	cmpldi	5,16
+	bge	Loop_xts_enc
+
+	vxor	3,3,8
+	lvsr	5,0,5
+	vxor	4,4,4
+	vspltisb	11,-1
+	vperm	4,4,11,5
+	vsel	2,2,3,4
+
+	subi	11,4,17
+	subi	4,4,16
+	mtctr	5
+	li	5,16
+Loop_xts_enc_steal:
+	lbzu	0,1(11)
+	stb	0,16(11)
+	bc	16,0,Loop_xts_enc_steal
+
+	mtctr	9
+	b	Loop_xts_enc
+
+Lxts_enc_done:
+	cmpldi	8,0
+	beq	Lxts_enc_ret
+
+	vsrab	11,8,9
+	vaddubm	8,8,8
+	vsldoi	11,11,11,15
+	vand	11,11,10
+	vxor	8,8,11
+
+	vperm	8,8,8,6
+	.long	0x7D004799
+
+Lxts_enc_ret:
+	mtspr	256,12
+	li	3,0
+	blr	
+.long	0
+.byte	0,12,0x04,0,0x80,6,6,0
+.long	0
+
+
+.globl	aes_hw_xts_decrypt
+.align	5
+aes_hw_xts_decrypt:
+	mr	10,3
+	li	3,-1
+	cmpldi	5,16
+	bclr	14,0
+
+	lis	0,0xfff8
+	mfspr	12,256
+	li	11,0
+	mtspr	256,0
+
+	andi.	0,5,15
+	neg	0,0
+	andi.	0,0,16
+	sub	5,5,0
+
+	vspltisb	9,0x07
+	lvsl	6,11,11
+	vspltisb	11,0x0f
+	vxor	6,6,9
+
+	li	3,15
+	lvx	8,0,8
+	lvsl	5,0,8
+	lvx	4,3,8
+	vxor	5,5,11
+	vperm	8,8,4,5
+
+	neg	11,10
+	lvsr	5,0,11
+	lvx	2,0,10
+	addi	10,10,15
+	vxor	5,5,11
+
+	cmpldi	7,0
+	beq	Lxts_dec_no_key2
+
+	lvsr	7,0,7
+	lwz	9,240(7)
+	srwi	9,9,1
+	subi	9,9,1
+	li	3,16
+
+	lvx	0,0,7
+	lvx	1,3,7
+	addi	3,3,16
+	vperm	0,1,0,7
+	vxor	8,8,0
+	lvx	0,3,7
+	addi	3,3,16
+	mtctr	9
+
+Ltweak_xts_dec:
+	vperm	1,0,1,7
+	.long	0x11080D08
+	lvx	1,3,7
+	addi	3,3,16
+	vperm	0,1,0,7
+	.long	0x11080508
+	lvx	0,3,7
+	addi	3,3,16
+	bc	16,0,Ltweak_xts_dec
+
+	vperm	1,0,1,7
+	.long	0x11080D08
+	lvx	1,3,7
+	vperm	0,1,0,7
+	.long	0x11080509
+
+	li	8,0
+	b	Lxts_dec
+
+Lxts_dec_no_key2:
+	neg	3,5
+	andi.	3,3,15
+	add	5,5,3
+
+
+Lxts_dec:
+	lvx	4,0,10
+	addi	10,10,16
+
+	lvsr	7,0,6
+	lwz	9,240(6)
+	srwi	9,9,1
+	subi	9,9,1
+	li	3,16
+
+	vslb	10,9,9
+	vor	10,10,9
+	vspltisb	11,1
+	vsldoi	10,10,11,15
+
+	cmpldi	5,96
+	bge	_aesp8_xts_decrypt6x
+
+	lvx	0,0,6
+	lvx	1,3,6
+	addi	3,3,16
+	vperm	2,2,4,5
+	vperm	0,1,0,7
+	vxor	2,2,8
+	vxor	2,2,0
+	lvx	0,3,6
+	addi	3,3,16
+	mtctr	9
+
+	cmpldi	5,16
+	blt	Ltail_xts_dec
+
+
+.align	5
+Loop_xts_dec:
+	vperm	1,0,1,7
+	.long	0x10420D48
+	lvx	1,3,6
+	addi	3,3,16
+	vperm	0,1,0,7
+	.long	0x10420548
+	lvx	0,3,6
+	addi	3,3,16
+	bc	16,0,Loop_xts_dec
+
+	vperm	1,0,1,7
+	.long	0x10420D48
+	lvx	1,3,6
+	li	3,16
+	vperm	0,1,0,7
+	vxor	0,0,8
+	.long	0x10620549
+
+	vperm	11,3,3,6
+
+	.long	0x7D602799
+
+	addi	4,4,16
+
+	subic.	5,5,16
+	beq	Lxts_dec_done
+
+	vor	2,4,4
+	lvx	4,0,10
+	addi	10,10,16
+	lvx	0,0,6
+	lvx	1,3,6
+	addi	3,3,16
+
+	vsrab	11,8,9
+	vaddubm	8,8,8
+	vsldoi	11,11,11,15
+	vand	11,11,10
+	vxor	8,8,11
+
+	vperm	2,2,4,5
+	vperm	0,1,0,7
+	vxor	2,2,8
+	vxor	2,2,0
+	lvx	0,3,6
+	addi	3,3,16
+
+	mtctr	9
+	cmpldi	5,16
+	bge	Loop_xts_dec
+
+Ltail_xts_dec:
+	vsrab	11,8,9
+	vaddubm	12,8,8
+	vsldoi	11,11,11,15
+	vand	11,11,10
+	vxor	12,12,11
+
+	subi	10,10,16
+	add	10,10,5
+
+	vxor	2,2,8
+	vxor	2,2,12
+
+Loop_xts_dec_short:
+	vperm	1,0,1,7
+	.long	0x10420D48
+	lvx	1,3,6
+	addi	3,3,16
+	vperm	0,1,0,7
+	.long	0x10420548
+	lvx	0,3,6
+	addi	3,3,16
+	bc	16,0,Loop_xts_dec_short
+
+	vperm	1,0,1,7
+	.long	0x10420D48
+	lvx	1,3,6
+	li	3,16
+	vperm	0,1,0,7
+	vxor	0,0,12
+	.long	0x10620549
+
+	vperm	11,3,3,6
+
+	.long	0x7D602799
+
+
+	vor	2,4,4
+	lvx	4,0,10
+
+	lvx	0,0,6
+	lvx	1,3,6
+	addi	3,3,16
+	vperm	2,2,4,5
+	vperm	0,1,0,7
+
+	lvsr	5,0,5
+	vxor	4,4,4
+	vspltisb	11,-1
+	vperm	4,4,11,5
+	vsel	2,2,3,4
+
+	vxor	0,0,8
+	vxor	2,2,0
+	lvx	0,3,6
+	addi	3,3,16
+
+	subi	11,4,1
+	mtctr	5
+	li	5,16
+Loop_xts_dec_steal:
+	lbzu	0,1(11)
+	stb	0,16(11)
+	bc	16,0,Loop_xts_dec_steal
+
+	mtctr	9
+	b	Loop_xts_dec
+
+Lxts_dec_done:
+	cmpldi	8,0
+	beq	Lxts_dec_ret
+
+	vsrab	11,8,9
+	vaddubm	8,8,8
+	vsldoi	11,11,11,15
+	vand	11,11,10
+	vxor	8,8,11
+
+	vperm	8,8,8,6
+	.long	0x7D004799
+
+Lxts_dec_ret:
+	mtspr	256,12
+	li	3,0
+	blr	
+.long	0
+.byte	0,12,0x04,0,0x80,6,6,0
+.long	0
+
+.align	5
+_aesp8_xts_encrypt6x:
+	stdu	1,-448(1)
+	mflr	11
+	li	7,207
+	li	3,223
+	std	11,464(1)
+	stvx	20,7,1
+	addi	7,7,32
+	stvx	21,3,1
+	addi	3,3,32
+	stvx	22,7,1
+	addi	7,7,32
+	stvx	23,3,1
+	addi	3,3,32
+	stvx	24,7,1
+	addi	7,7,32
+	stvx	25,3,1
+	addi	3,3,32
+	stvx	26,7,1
+	addi	7,7,32
+	stvx	27,3,1
+	addi	3,3,32
+	stvx	28,7,1
+	addi	7,7,32
+	stvx	29,3,1
+	addi	3,3,32
+	stvx	30,7,1
+	stvx	31,3,1
+	li	0,-1
+	stw	12,396(1)
+	li	3,0x10
+	std	26,400(1)
+	li	26,0x20
+	std	27,408(1)
+	li	27,0x30
+	std	28,416(1)
+	li	28,0x40
+	std	29,424(1)
+	li	29,0x50
+	std	30,432(1)
+	li	30,0x60
+	std	31,440(1)
+	li	31,0x70
+	mtspr	256,0
+
+	subi	9,9,3
+
+	lvx	23,0,6
+	lvx	30,3,6
+	addi	6,6,0x20
+	lvx	31,0,6
+	vperm	23,30,23,7
+	addi	7,1,64+15
+	mtctr	9
+
+Load_xts_enc_key:
+	vperm	24,31,30,7
+	lvx	30,3,6
+	addi	6,6,0x20
+	stvx	24,0,7
+	vperm	25,30,31,7
+	lvx	31,0,6
+	stvx	25,3,7
+	addi	7,7,0x20
+	bc	16,0,Load_xts_enc_key
+
+	lvx	26,3,6
+	vperm	24,31,30,7
+	lvx	27,26,6
+	stvx	24,0,7
+	vperm	25,26,31,7
+	lvx	28,27,6
+	stvx	25,3,7
+	addi	7,1,64+15
+	vperm	26,27,26,7
+	lvx	29,28,6
+	vperm	27,28,27,7
+	lvx	30,29,6
+	vperm	28,29,28,7
+	lvx	31,30,6
+	vperm	29,30,29,7
+	lvx	22,31,6
+	vperm	30,31,30,7
+	lvx	24,0,7
+	vperm	31,22,31,7
+	lvx	25,3,7
+
+	vperm	0,2,4,5
+	subi	10,10,31
+	vxor	17,8,23
+	vsrab	11,8,9
+	vaddubm	8,8,8
+	vsldoi	11,11,11,15
+	vand	11,11,10
+	vxor	7,0,17
+	vxor	8,8,11
+
+	.long	0x7C235699
+	vxor	18,8,23
+	vsrab	11,8,9
+	vaddubm	8,8,8
+	vsldoi	11,11,11,15
+	vperm	1,1,1,6
+	vand	11,11,10
+	vxor	12,1,18
+	vxor	8,8,11
+
+	.long	0x7C5A5699
+	andi.	31,5,15
+	vxor	19,8,23
+	vsrab	11,8,9
+	vaddubm	8,8,8
+	vsldoi	11,11,11,15
+	vperm	2,2,2,6
+	vand	11,11,10
+	vxor	13,2,19
+	vxor	8,8,11
+
+	.long	0x7C7B5699
+	sub	5,5,31
+	vxor	20,8,23
+	vsrab	11,8,9
+	vaddubm	8,8,8
+	vsldoi	11,11,11,15
+	vperm	3,3,3,6
+	vand	11,11,10
+	vxor	14,3,20
+	vxor	8,8,11
+
+	.long	0x7C9C5699
+	subi	5,5,0x60
+	vxor	21,8,23
+	vsrab	11,8,9
+	vaddubm	8,8,8
+	vsldoi	11,11,11,15
+	vperm	4,4,4,6
+	vand	11,11,10
+	vxor	15,4,21
+	vxor	8,8,11
+
+	.long	0x7CBD5699
+	addi	10,10,0x60
+	vxor	22,8,23
+	vsrab	11,8,9
+	vaddubm	8,8,8
+	vsldoi	11,11,11,15
+	vperm	5,5,5,6
+	vand	11,11,10
+	vxor	16,5,22
+	vxor	8,8,11
+
+	vxor	31,31,23
+	mtctr	9
+	b	Loop_xts_enc6x
+
+.align	5
+Loop_xts_enc6x:
+	.long	0x10E7C508
+	.long	0x118CC508
+	.long	0x11ADC508
+	.long	0x11CEC508
+	.long	0x11EFC508
+	.long	0x1210C508
+	lvx	24,26,7
+	addi	7,7,0x20
+
+	.long	0x10E7CD08
+	.long	0x118CCD08
+	.long	0x11ADCD08
+	.long	0x11CECD08
+	.long	0x11EFCD08
+	.long	0x1210CD08
+	lvx	25,3,7
+	bc	16,0,Loop_xts_enc6x
+
+	subic	5,5,96
+	vxor	0,17,31
+	.long	0x10E7C508
+	.long	0x118CC508
+	vsrab	11,8,9
+	vxor	17,8,23
+	vaddubm	8,8,8
+	.long	0x11ADC508
+	.long	0x11CEC508
+	vsldoi	11,11,11,15
+	.long	0x11EFC508
+	.long	0x1210C508
+
+	subfe.	0,0,0
+	vand	11,11,10
+	.long	0x10E7CD08
+	.long	0x118CCD08
+	vxor	8,8,11
+	.long	0x11ADCD08
+	.long	0x11CECD08
+	vxor	1,18,31
+	vsrab	11,8,9
+	vxor	18,8,23
+	.long	0x11EFCD08
+	.long	0x1210CD08
+
+	and	0,0,5
+	vaddubm	8,8,8
+	vsldoi	11,11,11,15
+	.long	0x10E7D508
+	.long	0x118CD508
+	vand	11,11,10
+	.long	0x11ADD508
+	.long	0x11CED508
+	vxor	8,8,11
+	.long	0x11EFD508
+	.long	0x1210D508
+
+	add	10,10,0
+
+
+
+	vxor	2,19,31
+	vsrab	11,8,9
+	vxor	19,8,23
+	vaddubm	8,8,8
+	.long	0x10E7DD08
+	.long	0x118CDD08
+	vsldoi	11,11,11,15
+	.long	0x11ADDD08
+	.long	0x11CEDD08
+	vand	11,11,10
+	.long	0x11EFDD08
+	.long	0x1210DD08
+
+	addi	7,1,64+15
+	vxor	8,8,11
+	.long	0x10E7E508
+	.long	0x118CE508
+	vxor	3,20,31
+	vsrab	11,8,9
+	vxor	20,8,23
+	.long	0x11ADE508
+	.long	0x11CEE508
+	vaddubm	8,8,8
+	vsldoi	11,11,11,15
+	.long	0x11EFE508
+	.long	0x1210E508
+	lvx	24,0,7
+	vand	11,11,10
+
+	.long	0x10E7ED08
+	.long	0x118CED08
+	vxor	8,8,11
+	.long	0x11ADED08
+	.long	0x11CEED08
+	vxor	4,21,31
+	vsrab	11,8,9
+	vxor	21,8,23
+	.long	0x11EFED08
+	.long	0x1210ED08
+	lvx	25,3,7
+	vaddubm	8,8,8
+	vsldoi	11,11,11,15
+
+	.long	0x10E7F508
+	.long	0x118CF508
+	vand	11,11,10
+	.long	0x11ADF508
+	.long	0x11CEF508
+	vxor	8,8,11
+	.long	0x11EFF508
+	.long	0x1210F508
+	vxor	5,22,31
+	vsrab	11,8,9
+	vxor	22,8,23
+
+	.long	0x10E70509
+	.long	0x7C005699
+	vaddubm	8,8,8
+	vsldoi	11,11,11,15
+	.long	0x118C0D09
+	.long	0x7C235699
+	.long	0x11AD1509
+	vperm	0,0,0,6
+	.long	0x7C5A5699
+	vand	11,11,10
+	.long	0x11CE1D09
+	vperm	1,1,1,6
+	.long	0x7C7B5699
+	.long	0x11EF2509
+	vperm	2,2,2,6
+	.long	0x7C9C5699
+	vxor	8,8,11
+	.long	0x11702D09
+
+	vperm	3,3,3,6
+	.long	0x7CBD5699
+	addi	10,10,0x60
+	vperm	4,4,4,6
+	vperm	5,5,5,6
+
+	vperm	7,7,7,6
+	vperm	12,12,12,6
+	.long	0x7CE02799
+	vxor	7,0,17
+	vperm	13,13,13,6
+	.long	0x7D832799
+	vxor	12,1,18
+	vperm	14,14,14,6
+	.long	0x7DBA2799
+	vxor	13,2,19
+	vperm	15,15,15,6
+	.long	0x7DDB2799
+	vxor	14,3,20
+	vperm	16,11,11,6
+	.long	0x7DFC2799
+	vxor	15,4,21
+	.long	0x7E1D2799
+
+	vxor	16,5,22
+	addi	4,4,0x60
+
+	mtctr	9
+	beq	Loop_xts_enc6x
+
+	addic.	5,5,0x60
+	beq	Lxts_enc6x_zero
+	cmpwi	5,0x20
+	blt	Lxts_enc6x_one
+	nop	
+	beq	Lxts_enc6x_two
+	cmpwi	5,0x40
+	blt	Lxts_enc6x_three
+	nop	
+	beq	Lxts_enc6x_four
+
+Lxts_enc6x_five:
+	vxor	7,1,17
+	vxor	12,2,18
+	vxor	13,3,19
+	vxor	14,4,20
+	vxor	15,5,21
+
+	bl	_aesp8_xts_enc5x
+
+	vperm	7,7,7,6
+	vor	17,22,22
+	vperm	12,12,12,6
+	.long	0x7CE02799
+	vperm	13,13,13,6
+	.long	0x7D832799
+	vperm	14,14,14,6
+	.long	0x7DBA2799
+	vxor	11,15,22
+	vperm	15,15,15,6
+	.long	0x7DDB2799
+	.long	0x7DFC2799
+	addi	4,4,0x50
+	bne	Lxts_enc6x_steal
+	b	Lxts_enc6x_done
+
+.align	4
+Lxts_enc6x_four:
+	vxor	7,2,17
+	vxor	12,3,18
+	vxor	13,4,19
+	vxor	14,5,20
+	vxor	15,15,15
+
+	bl	_aesp8_xts_enc5x
+
+	vperm	7,7,7,6
+	vor	17,21,21
+	vperm	12,12,12,6
+	.long	0x7CE02799
+	vperm	13,13,13,6
+	.long	0x7D832799
+	vxor	11,14,21
+	vperm	14,14,14,6
+	.long	0x7DBA2799
+	.long	0x7DDB2799
+	addi	4,4,0x40
+	bne	Lxts_enc6x_steal
+	b	Lxts_enc6x_done
+
+.align	4
+Lxts_enc6x_three:
+	vxor	7,3,17
+	vxor	12,4,18
+	vxor	13,5,19
+	vxor	14,14,14
+	vxor	15,15,15
+
+	bl	_aesp8_xts_enc5x
+
+	vperm	7,7,7,6
+	vor	17,20,20
+	vperm	12,12,12,6
+	.long	0x7CE02799
+	vxor	11,13,20
+	vperm	13,13,13,6
+	.long	0x7D832799
+	.long	0x7DBA2799
+	addi	4,4,0x30
+	bne	Lxts_enc6x_steal
+	b	Lxts_enc6x_done
+
+.align	4
+Lxts_enc6x_two:
+	vxor	7,4,17
+	vxor	12,5,18
+	vxor	13,13,13
+	vxor	14,14,14
+	vxor	15,15,15
+
+	bl	_aesp8_xts_enc5x
+
+	vperm	7,7,7,6
+	vor	17,19,19
+	vxor	11,12,19
+	vperm	12,12,12,6
+	.long	0x7CE02799
+	.long	0x7D832799
+	addi	4,4,0x20
+	bne	Lxts_enc6x_steal
+	b	Lxts_enc6x_done
+
+.align	4
+Lxts_enc6x_one:
+	vxor	7,5,17
+	nop	
+Loop_xts_enc1x:
+	.long	0x10E7C508
+	lvx	24,26,7
+	addi	7,7,0x20
+
+	.long	0x10E7CD08
+	lvx	25,3,7
+	bc	16,0,Loop_xts_enc1x
+
+	add	10,10,31
+	cmpwi	31,0
+	.long	0x10E7C508
+
+	subi	10,10,16
+	.long	0x10E7CD08
+
+	lvsr	5,0,31
+	.long	0x10E7D508
+
+	.long	0x7C005699
+	.long	0x10E7DD08
+
+	addi	7,1,64+15
+	.long	0x10E7E508
+	lvx	24,0,7
+
+	.long	0x10E7ED08
+	lvx	25,3,7
+	vxor	17,17,31
+
+	vperm	0,0,0,6
+	.long	0x10E7F508
+
+	vperm	0,0,0,5
+	.long	0x10E78D09
+
+	vor	17,18,18
+	vxor	11,7,18
+	vperm	7,7,7,6
+	.long	0x7CE02799
+	addi	4,4,0x10
+	bne	Lxts_enc6x_steal
+	b	Lxts_enc6x_done
+
+.align	4
+Lxts_enc6x_zero:
+	cmpwi	31,0
+	beq	Lxts_enc6x_done
+
+	add	10,10,31
+	subi	10,10,16
+	.long	0x7C005699
+	lvsr	5,0,31
+	vperm	0,0,0,6
+	vperm	0,0,0,5
+	vxor	11,11,17
+Lxts_enc6x_steal:
+	vxor	0,0,17
+	vxor	7,7,7
+	vspltisb	12,-1
+	vperm	7,7,12,5
+	vsel	7,0,11,7
+
+	subi	30,4,17
+	subi	4,4,16
+	mtctr	31
+Loop_xts_enc6x_steal:
+	lbzu	0,1(30)
+	stb	0,16(30)
+	bc	16,0,Loop_xts_enc6x_steal
+
+	li	31,0
+	mtctr	9
+	b	Loop_xts_enc1x
+
+.align	4
+Lxts_enc6x_done:
+	cmpldi	8,0
+	beq	Lxts_enc6x_ret
+
+	vxor	8,17,23
+	vperm	8,8,8,6
+	.long	0x7D004799
+
+Lxts_enc6x_ret:
+	mtlr	11
+	li	10,79
+	li	11,95
+	stvx	9,10,1
+	addi	10,10,32
+	stvx	9,11,1
+	addi	11,11,32
+	stvx	9,10,1
+	addi	10,10,32
+	stvx	9,11,1
+	addi	11,11,32
+	stvx	9,10,1
+	addi	10,10,32
+	stvx	9,11,1
+	addi	11,11,32
+	stvx	9,10,1
+	addi	10,10,32
+	stvx	9,11,1
+	addi	11,11,32
+
+	mtspr	256,12
+	lvx	20,10,1
+	addi	10,10,32
+	lvx	21,11,1
+	addi	11,11,32
+	lvx	22,10,1
+	addi	10,10,32
+	lvx	23,11,1
+	addi	11,11,32
+	lvx	24,10,1
+	addi	10,10,32
+	lvx	25,11,1
+	addi	11,11,32
+	lvx	26,10,1
+	addi	10,10,32
+	lvx	27,11,1
+	addi	11,11,32
+	lvx	28,10,1
+	addi	10,10,32
+	lvx	29,11,1
+	addi	11,11,32
+	lvx	30,10,1
+	lvx	31,11,1
+	ld	26,400(1)
+	ld	27,408(1)
+	ld	28,416(1)
+	ld	29,424(1)
+	ld	30,432(1)
+	ld	31,440(1)
+	addi	1,1,448
+	blr	
+.long	0
+.byte	0,12,0x04,1,0x80,6,6,0
+.long	0
+
+.align	5
+_aesp8_xts_enc5x:
+	.long	0x10E7C508
+	.long	0x118CC508
+	.long	0x11ADC508
+	.long	0x11CEC508
+	.long	0x11EFC508
+	lvx	24,26,7
+	addi	7,7,0x20
+
+	.long	0x10E7CD08
+	.long	0x118CCD08
+	.long	0x11ADCD08
+	.long	0x11CECD08
+	.long	0x11EFCD08
+	lvx	25,3,7
+	bc	16,0,_aesp8_xts_enc5x
+
+	add	10,10,31
+	cmpwi	31,0
+	.long	0x10E7C508
+	.long	0x118CC508
+	.long	0x11ADC508
+	.long	0x11CEC508
+	.long	0x11EFC508
+
+	subi	10,10,16
+	.long	0x10E7CD08
+	.long	0x118CCD08
+	.long	0x11ADCD08
+	.long	0x11CECD08
+	.long	0x11EFCD08
+	vxor	17,17,31
+
+	.long	0x10E7D508
+	lvsr	5,0,31
+	.long	0x118CD508
+	.long	0x11ADD508
+	.long	0x11CED508
+	.long	0x11EFD508
+	vxor	1,18,31
+
+	.long	0x10E7DD08
+	.long	0x7C005699
+	.long	0x118CDD08
+	.long	0x11ADDD08
+	.long	0x11CEDD08
+	.long	0x11EFDD08
+	vxor	2,19,31
+
+	addi	7,1,64+15
+	.long	0x10E7E508
+	.long	0x118CE508
+	.long	0x11ADE508
+	.long	0x11CEE508
+	.long	0x11EFE508
+	lvx	24,0,7
+	vxor	3,20,31
+
+	.long	0x10E7ED08
+	vperm	0,0,0,6
+	.long	0x118CED08
+	.long	0x11ADED08
+	.long	0x11CEED08
+	.long	0x11EFED08
+	lvx	25,3,7
+	vxor	4,21,31
+
+	.long	0x10E7F508
+	vperm	0,0,0,5
+	.long	0x118CF508
+	.long	0x11ADF508
+	.long	0x11CEF508
+	.long	0x11EFF508
+
+	.long	0x10E78D09
+	.long	0x118C0D09
+	.long	0x11AD1509
+	.long	0x11CE1D09
+	.long	0x11EF2509
+	blr	
+.long	0
+.byte	0,12,0x14,0,0,0,0,0
+
+.align	5
+_aesp8_xts_decrypt6x:
+	stdu	1,-448(1)
+	mflr	11
+	li	7,207
+	li	3,223
+	std	11,464(1)
+	stvx	20,7,1
+	addi	7,7,32
+	stvx	21,3,1
+	addi	3,3,32
+	stvx	22,7,1
+	addi	7,7,32
+	stvx	23,3,1
+	addi	3,3,32
+	stvx	24,7,1
+	addi	7,7,32
+	stvx	25,3,1
+	addi	3,3,32
+	stvx	26,7,1
+	addi	7,7,32
+	stvx	27,3,1
+	addi	3,3,32
+	stvx	28,7,1
+	addi	7,7,32
+	stvx	29,3,1
+	addi	3,3,32
+	stvx	30,7,1
+	stvx	31,3,1
+	li	0,-1
+	stw	12,396(1)
+	li	3,0x10
+	std	26,400(1)
+	li	26,0x20
+	std	27,408(1)
+	li	27,0x30
+	std	28,416(1)
+	li	28,0x40
+	std	29,424(1)
+	li	29,0x50
+	std	30,432(1)
+	li	30,0x60
+	std	31,440(1)
+	li	31,0x70
+	mtspr	256,0
+
+	subi	9,9,3
+
+	lvx	23,0,6
+	lvx	30,3,6
+	addi	6,6,0x20
+	lvx	31,0,6
+	vperm	23,30,23,7
+	addi	7,1,64+15
+	mtctr	9
+
+Load_xts_dec_key:
+	vperm	24,31,30,7
+	lvx	30,3,6
+	addi	6,6,0x20
+	stvx	24,0,7
+	vperm	25,30,31,7
+	lvx	31,0,6
+	stvx	25,3,7
+	addi	7,7,0x20
+	bc	16,0,Load_xts_dec_key
+
+	lvx	26,3,6
+	vperm	24,31,30,7
+	lvx	27,26,6
+	stvx	24,0,7
+	vperm	25,26,31,7
+	lvx	28,27,6
+	stvx	25,3,7
+	addi	7,1,64+15
+	vperm	26,27,26,7
+	lvx	29,28,6
+	vperm	27,28,27,7
+	lvx	30,29,6
+	vperm	28,29,28,7
+	lvx	31,30,6
+	vperm	29,30,29,7
+	lvx	22,31,6
+	vperm	30,31,30,7
+	lvx	24,0,7
+	vperm	31,22,31,7
+	lvx	25,3,7
+
+	vperm	0,2,4,5
+	subi	10,10,31
+	vxor	17,8,23
+	vsrab	11,8,9
+	vaddubm	8,8,8
+	vsldoi	11,11,11,15
+	vand	11,11,10
+	vxor	7,0,17
+	vxor	8,8,11
+
+	.long	0x7C235699
+	vxor	18,8,23
+	vsrab	11,8,9
+	vaddubm	8,8,8
+	vsldoi	11,11,11,15
+	vperm	1,1,1,6
+	vand	11,11,10
+	vxor	12,1,18
+	vxor	8,8,11
+
+	.long	0x7C5A5699
+	andi.	31,5,15
+	vxor	19,8,23
+	vsrab	11,8,9
+	vaddubm	8,8,8
+	vsldoi	11,11,11,15
+	vperm	2,2,2,6
+	vand	11,11,10
+	vxor	13,2,19
+	vxor	8,8,11
+
+	.long	0x7C7B5699
+	sub	5,5,31
+	vxor	20,8,23
+	vsrab	11,8,9
+	vaddubm	8,8,8
+	vsldoi	11,11,11,15
+	vperm	3,3,3,6
+	vand	11,11,10
+	vxor	14,3,20
+	vxor	8,8,11
+
+	.long	0x7C9C5699
+	subi	5,5,0x60
+	vxor	21,8,23
+	vsrab	11,8,9
+	vaddubm	8,8,8
+	vsldoi	11,11,11,15
+	vperm	4,4,4,6
+	vand	11,11,10
+	vxor	15,4,21
+	vxor	8,8,11
+
+	.long	0x7CBD5699
+	addi	10,10,0x60
+	vxor	22,8,23
+	vsrab	11,8,9
+	vaddubm	8,8,8
+	vsldoi	11,11,11,15
+	vperm	5,5,5,6
+	vand	11,11,10
+	vxor	16,5,22
+	vxor	8,8,11
+
+	vxor	31,31,23
+	mtctr	9
+	b	Loop_xts_dec6x
+
+.align	5
+Loop_xts_dec6x:
+	.long	0x10E7C548
+	.long	0x118CC548
+	.long	0x11ADC548
+	.long	0x11CEC548
+	.long	0x11EFC548
+	.long	0x1210C548
+	lvx	24,26,7
+	addi	7,7,0x20
+
+	.long	0x10E7CD48
+	.long	0x118CCD48
+	.long	0x11ADCD48
+	.long	0x11CECD48
+	.long	0x11EFCD48
+	.long	0x1210CD48
+	lvx	25,3,7
+	bc	16,0,Loop_xts_dec6x
+
+	subic	5,5,96
+	vxor	0,17,31
+	.long	0x10E7C548
+	.long	0x118CC548
+	vsrab	11,8,9
+	vxor	17,8,23
+	vaddubm	8,8,8
+	.long	0x11ADC548
+	.long	0x11CEC548
+	vsldoi	11,11,11,15
+	.long	0x11EFC548
+	.long	0x1210C548
+
+	subfe.	0,0,0
+	vand	11,11,10
+	.long	0x10E7CD48
+	.long	0x118CCD48
+	vxor	8,8,11
+	.long	0x11ADCD48
+	.long	0x11CECD48
+	vxor	1,18,31
+	vsrab	11,8,9
+	vxor	18,8,23
+	.long	0x11EFCD48
+	.long	0x1210CD48
+
+	and	0,0,5
+	vaddubm	8,8,8
+	vsldoi	11,11,11,15
+	.long	0x10E7D548
+	.long	0x118CD548
+	vand	11,11,10
+	.long	0x11ADD548
+	.long	0x11CED548
+	vxor	8,8,11
+	.long	0x11EFD548
+	.long	0x1210D548
+
+	add	10,10,0
+
+
+
+	vxor	2,19,31
+	vsrab	11,8,9
+	vxor	19,8,23
+	vaddubm	8,8,8
+	.long	0x10E7DD48
+	.long	0x118CDD48
+	vsldoi	11,11,11,15
+	.long	0x11ADDD48
+	.long	0x11CEDD48
+	vand	11,11,10
+	.long	0x11EFDD48
+	.long	0x1210DD48
+
+	addi	7,1,64+15
+	vxor	8,8,11
+	.long	0x10E7E548
+	.long	0x118CE548
+	vxor	3,20,31
+	vsrab	11,8,9
+	vxor	20,8,23
+	.long	0x11ADE548
+	.long	0x11CEE548
+	vaddubm	8,8,8
+	vsldoi	11,11,11,15
+	.long	0x11EFE548
+	.long	0x1210E548
+	lvx	24,0,7
+	vand	11,11,10
+
+	.long	0x10E7ED48
+	.long	0x118CED48
+	vxor	8,8,11
+	.long	0x11ADED48
+	.long	0x11CEED48
+	vxor	4,21,31
+	vsrab	11,8,9
+	vxor	21,8,23
+	.long	0x11EFED48
+	.long	0x1210ED48
+	lvx	25,3,7
+	vaddubm	8,8,8
+	vsldoi	11,11,11,15
+
+	.long	0x10E7F548
+	.long	0x118CF548
+	vand	11,11,10
+	.long	0x11ADF548
+	.long	0x11CEF548
+	vxor	8,8,11
+	.long	0x11EFF548
+	.long	0x1210F548
+	vxor	5,22,31
+	vsrab	11,8,9
+	vxor	22,8,23
+
+	.long	0x10E70549
+	.long	0x7C005699
+	vaddubm	8,8,8
+	vsldoi	11,11,11,15
+	.long	0x118C0D49
+	.long	0x7C235699
+	.long	0x11AD1549
+	vperm	0,0,0,6
+	.long	0x7C5A5699
+	vand	11,11,10
+	.long	0x11CE1D49
+	vperm	1,1,1,6
+	.long	0x7C7B5699
+	.long	0x11EF2549
+	vperm	2,2,2,6
+	.long	0x7C9C5699
+	vxor	8,8,11
+	.long	0x12102D49
+	vperm	3,3,3,6
+	.long	0x7CBD5699
+	addi	10,10,0x60
+	vperm	4,4,4,6
+	vperm	5,5,5,6
+
+	vperm	7,7,7,6
+	vperm	12,12,12,6
+	.long	0x7CE02799
+	vxor	7,0,17
+	vperm	13,13,13,6
+	.long	0x7D832799
+	vxor	12,1,18
+	vperm	14,14,14,6
+	.long	0x7DBA2799
+	vxor	13,2,19
+	vperm	15,15,15,6
+	.long	0x7DDB2799
+	vxor	14,3,20
+	vperm	16,16,16,6
+	.long	0x7DFC2799
+	vxor	15,4,21
+	.long	0x7E1D2799
+	vxor	16,5,22
+	addi	4,4,0x60
+
+	mtctr	9
+	beq	Loop_xts_dec6x
+
+	addic.	5,5,0x60
+	beq	Lxts_dec6x_zero
+	cmpwi	5,0x20
+	blt	Lxts_dec6x_one
+	nop	
+	beq	Lxts_dec6x_two
+	cmpwi	5,0x40
+	blt	Lxts_dec6x_three
+	nop	
+	beq	Lxts_dec6x_four
+
+Lxts_dec6x_five:
+	vxor	7,1,17
+	vxor	12,2,18
+	vxor	13,3,19
+	vxor	14,4,20
+	vxor	15,5,21
+
+	bl	_aesp8_xts_dec5x
+
+	vperm	7,7,7,6
+	vor	17,22,22
+	vxor	18,8,23
+	vperm	12,12,12,6
+	.long	0x7CE02799
+	vxor	7,0,18
+	vperm	13,13,13,6
+	.long	0x7D832799
+	vperm	14,14,14,6
+	.long	0x7DBA2799
+	vperm	15,15,15,6
+	.long	0x7DDB2799
+	.long	0x7DFC2799
+	addi	4,4,0x50
+	bne	Lxts_dec6x_steal
+	b	Lxts_dec6x_done
+
+.align	4
+Lxts_dec6x_four:
+	vxor	7,2,17
+	vxor	12,3,18
+	vxor	13,4,19
+	vxor	14,5,20
+	vxor	15,15,15
+
+	bl	_aesp8_xts_dec5x
+
+	vperm	7,7,7,6
+	vor	17,21,21
+	vor	18,22,22
+	vperm	12,12,12,6
+	.long	0x7CE02799
+	vxor	7,0,22
+	vperm	13,13,13,6
+	.long	0x7D832799
+	vperm	14,14,14,6
+	.long	0x7DBA2799
+	.long	0x7DDB2799
+	addi	4,4,0x40
+	bne	Lxts_dec6x_steal
+	b	Lxts_dec6x_done
+
+.align	4
+Lxts_dec6x_three:
+	vxor	7,3,17
+	vxor	12,4,18
+	vxor	13,5,19
+	vxor	14,14,14
+	vxor	15,15,15
+
+	bl	_aesp8_xts_dec5x
+
+	vperm	7,7,7,6
+	vor	17,20,20
+	vor	18,21,21
+	vperm	12,12,12,6
+	.long	0x7CE02799
+	vxor	7,0,21
+	vperm	13,13,13,6
+	.long	0x7D832799
+	.long	0x7DBA2799
+	addi	4,4,0x30
+	bne	Lxts_dec6x_steal
+	b	Lxts_dec6x_done
+
+.align	4
+Lxts_dec6x_two:
+	vxor	7,4,17
+	vxor	12,5,18
+	vxor	13,13,13
+	vxor	14,14,14
+	vxor	15,15,15
+
+	bl	_aesp8_xts_dec5x
+
+	vperm	7,7,7,6
+	vor	17,19,19
+	vor	18,20,20
+	vperm	12,12,12,6
+	.long	0x7CE02799
+	vxor	7,0,20
+	.long	0x7D832799
+	addi	4,4,0x20
+	bne	Lxts_dec6x_steal
+	b	Lxts_dec6x_done
+
+.align	4
+Lxts_dec6x_one:
+	vxor	7,5,17
+	nop	
+Loop_xts_dec1x:
+	.long	0x10E7C548
+	lvx	24,26,7
+	addi	7,7,0x20
+
+	.long	0x10E7CD48
+	lvx	25,3,7
+	bc	16,0,Loop_xts_dec1x
+
+	subi	0,31,1
+	.long	0x10E7C548
+
+	andi.	0,0,16
+	cmpwi	31,0
+	.long	0x10E7CD48
+
+	sub	10,10,0
+	.long	0x10E7D548
+
+	.long	0x7C005699
+	.long	0x10E7DD48
+
+	addi	7,1,64+15
+	.long	0x10E7E548
+	lvx	24,0,7
+
+	.long	0x10E7ED48
+	lvx	25,3,7
+	vxor	17,17,31
+
+	vperm	0,0,0,6
+	.long	0x10E7F548
+
+	mtctr	9
+	.long	0x10E78D49
+
+	vor	17,18,18
+	vor	18,19,19
+	vperm	7,7,7,6
+	.long	0x7CE02799
+	addi	4,4,0x10
+	vxor	7,0,19
+	bne	Lxts_dec6x_steal
+	b	Lxts_dec6x_done
+
+.align	4
+Lxts_dec6x_zero:
+	cmpwi	31,0
+	beq	Lxts_dec6x_done
+
+	.long	0x7C005699
+	vperm	0,0,0,6
+	vxor	7,0,18
+Lxts_dec6x_steal:
+	.long	0x10E7C548
+	lvx	24,26,7
+	addi	7,7,0x20
+
+	.long	0x10E7CD48
+	lvx	25,3,7
+	bc	16,0,Lxts_dec6x_steal
+
+	add	10,10,31
+	.long	0x10E7C548
+
+	cmpwi	31,0
+	.long	0x10E7CD48
+
+	.long	0x7C005699
+	.long	0x10E7D548
+
+	lvsr	5,0,31
+	.long	0x10E7DD48
+
+	addi	7,1,64+15
+	.long	0x10E7E548
+	lvx	24,0,7
+
+	.long	0x10E7ED48
+	lvx	25,3,7
+	vxor	18,18,31
+
+	vperm	0,0,0,6
+	.long	0x10E7F548
+
+	vperm	0,0,0,5
+	.long	0x11679549
+
+	vperm	7,11,11,6
+	.long	0x7CE02799
+
+
+	vxor	7,7,7
+	vspltisb	12,-1
+	vperm	7,7,12,5
+	vsel	7,0,11,7
+	vxor	7,7,17
+
+	subi	30,4,1
+	mtctr	31
+Loop_xts_dec6x_steal:
+	lbzu	0,1(30)
+	stb	0,16(30)
+	bc	16,0,Loop_xts_dec6x_steal
+
+	li	31,0
+	mtctr	9
+	b	Loop_xts_dec1x
+
+.align	4
+Lxts_dec6x_done:
+	cmpldi	8,0
+	beq	Lxts_dec6x_ret
+
+	vxor	8,17,23
+	vperm	8,8,8,6
+	.long	0x7D004799
+
+Lxts_dec6x_ret:
+	mtlr	11
+	li	10,79
+	li	11,95
+	stvx	9,10,1
+	addi	10,10,32
+	stvx	9,11,1
+	addi	11,11,32
+	stvx	9,10,1
+	addi	10,10,32
+	stvx	9,11,1
+	addi	11,11,32
+	stvx	9,10,1
+	addi	10,10,32
+	stvx	9,11,1
+	addi	11,11,32
+	stvx	9,10,1
+	addi	10,10,32
+	stvx	9,11,1
+	addi	11,11,32
+
+	mtspr	256,12
+	lvx	20,10,1
+	addi	10,10,32
+	lvx	21,11,1
+	addi	11,11,32
+	lvx	22,10,1
+	addi	10,10,32
+	lvx	23,11,1
+	addi	11,11,32
+	lvx	24,10,1
+	addi	10,10,32
+	lvx	25,11,1
+	addi	11,11,32
+	lvx	26,10,1
+	addi	10,10,32
+	lvx	27,11,1
+	addi	11,11,32
+	lvx	28,10,1
+	addi	10,10,32
+	lvx	29,11,1
+	addi	11,11,32
+	lvx	30,10,1
+	lvx	31,11,1
+	ld	26,400(1)
+	ld	27,408(1)
+	ld	28,416(1)
+	ld	29,424(1)
+	ld	30,432(1)
+	ld	31,440(1)
+	addi	1,1,448
+	blr	
+.long	0
+.byte	0,12,0x04,1,0x80,6,6,0
+.long	0
+
+.align	5
+_aesp8_xts_dec5x:
+	.long	0x10E7C548
+	.long	0x118CC548
+	.long	0x11ADC548
+	.long	0x11CEC548
+	.long	0x11EFC548
+	lvx	24,26,7
+	addi	7,7,0x20
+
+	.long	0x10E7CD48
+	.long	0x118CCD48
+	.long	0x11ADCD48
+	.long	0x11CECD48
+	.long	0x11EFCD48
+	lvx	25,3,7
+	bc	16,0,_aesp8_xts_dec5x
+
+	subi	0,31,1
+	.long	0x10E7C548
+	.long	0x118CC548
+	.long	0x11ADC548
+	.long	0x11CEC548
+	.long	0x11EFC548
+
+	andi.	0,0,16
+	cmpwi	31,0
+	.long	0x10E7CD48
+	.long	0x118CCD48
+	.long	0x11ADCD48
+	.long	0x11CECD48
+	.long	0x11EFCD48
+	vxor	17,17,31
+
+	sub	10,10,0
+	.long	0x10E7D548
+	.long	0x118CD548
+	.long	0x11ADD548
+	.long	0x11CED548
+	.long	0x11EFD548
+	vxor	1,18,31
+
+	.long	0x10E7DD48
+	.long	0x7C005699
+	.long	0x118CDD48
+	.long	0x11ADDD48
+	.long	0x11CEDD48
+	.long	0x11EFDD48
+	vxor	2,19,31
+
+	addi	7,1,64+15
+	.long	0x10E7E548
+	.long	0x118CE548
+	.long	0x11ADE548
+	.long	0x11CEE548
+	.long	0x11EFE548
+	lvx	24,0,7
+	vxor	3,20,31
+
+	.long	0x10E7ED48
+	vperm	0,0,0,6
+	.long	0x118CED48
+	.long	0x11ADED48
+	.long	0x11CEED48
+	.long	0x11EFED48
+	lvx	25,3,7
+	vxor	4,21,31
+
+	.long	0x10E7F548
+	.long	0x118CF548
+	.long	0x11ADF548
+	.long	0x11CEF548
+	.long	0x11EFF548
+
+	.long	0x10E78D49
+	.long	0x118C0D49
+	.long	0x11AD1549
+	.long	0x11CE1D49
+	.long	0x11EF2549
+	mtctr	9
+	blr	
+.long	0
+.byte	0,12,0x14,0,0,0,0,0
diff --git a/linux-ppc64le/crypto/modes/ghashp8-ppc.S b/linux-ppc64le/crypto/modes/ghashp8-ppc.S
new file mode 100644
index 0000000..69ae1a5
--- /dev/null
+++ b/linux-ppc64le/crypto/modes/ghashp8-ppc.S
@@ -0,0 +1,565 @@
+.machine	"any"
+
+.text
+
+.globl	gcm_init_p8
+.align	5
+gcm_init_p8:
+	li	0,-4096
+	li	8,0x10
+	mfspr	12,256
+	li	9,0x20
+	mtspr	256,0
+	li	10,0x30
+	.long	0x7D202699
+
+	vspltisb	8,-16
+	vspltisb	5,1
+	vaddubm	8,8,8
+	vxor	4,4,4
+	vor	8,8,5
+	vsldoi	8,8,4,15
+	vsldoi	6,4,5,1
+	vaddubm	8,8,8
+	vspltisb	7,7
+	vor	8,8,6
+	vspltb	6,9,0
+	vsl	9,9,5
+	vsrab	6,6,7
+	vand	6,6,8
+	vxor	3,9,6
+
+	vsldoi	9,3,3,8
+	vsldoi	8,4,8,8
+	vsldoi	11,4,9,8
+	vsldoi	10,9,4,8
+
+	.long	0x7D001F99
+	.long	0x7D681F99
+	li	8,0x40
+	.long	0x7D291F99
+	li	9,0x50
+	.long	0x7D4A1F99
+	li	10,0x60
+
+	.long	0x10035CC8
+	.long	0x10234CC8
+	.long	0x104354C8
+
+	.long	0x10E044C8
+
+	vsldoi	5,1,4,8
+	vsldoi	6,4,1,8
+	vxor	0,0,5
+	vxor	2,2,6
+
+	vsldoi	0,0,0,8
+	vxor	0,0,7
+
+	vsldoi	6,0,0,8
+	.long	0x100044C8
+	vxor	6,6,2
+	vxor	16,0,6
+
+	vsldoi	17,16,16,8
+	vsldoi	19,4,17,8
+	vsldoi	18,17,4,8
+
+	.long	0x7E681F99
+	li	8,0x70
+	.long	0x7E291F99
+	li	9,0x80
+	.long	0x7E4A1F99
+	li	10,0x90
+	.long	0x10039CC8
+	.long	0x11B09CC8
+	.long	0x10238CC8
+	.long	0x11D08CC8
+	.long	0x104394C8
+	.long	0x11F094C8
+
+	.long	0x10E044C8
+	.long	0x114D44C8
+
+	vsldoi	5,1,4,8
+	vsldoi	6,4,1,8
+	vsldoi	11,14,4,8
+	vsldoi	9,4,14,8
+	vxor	0,0,5
+	vxor	2,2,6
+	vxor	13,13,11
+	vxor	15,15,9
+
+	vsldoi	0,0,0,8
+	vsldoi	13,13,13,8
+	vxor	0,0,7
+	vxor	13,13,10
+
+	vsldoi	6,0,0,8
+	vsldoi	9,13,13,8
+	.long	0x100044C8
+	.long	0x11AD44C8
+	vxor	6,6,2
+	vxor	9,9,15
+	vxor	0,0,6
+	vxor	13,13,9
+
+	vsldoi	9,0,0,8
+	vsldoi	17,13,13,8
+	vsldoi	11,4,9,8
+	vsldoi	10,9,4,8
+	vsldoi	19,4,17,8
+	vsldoi	18,17,4,8
+
+	.long	0x7D681F99
+	li	8,0xa0
+	.long	0x7D291F99
+	li	9,0xb0
+	.long	0x7D4A1F99
+	li	10,0xc0
+	.long	0x7E681F99
+	.long	0x7E291F99
+	.long	0x7E4A1F99
+
+	mtspr	256,12
+	blr	
+.long	0
+.byte	0,12,0x14,0,0,0,2,0
+.long	0
+
+.globl	gcm_gmult_p8
+.align	5
+gcm_gmult_p8:
+	lis	0,0xfff8
+	li	8,0x10
+	mfspr	12,256
+	li	9,0x20
+	mtspr	256,0
+	li	10,0x30
+	.long	0x7C601E99
+
+	.long	0x7D682699
+	lvsl	12,0,0
+	.long	0x7D292699
+	vspltisb	5,0x07
+	.long	0x7D4A2699
+	vxor	12,12,5
+	.long	0x7D002699
+	vperm	3,3,3,12
+	vxor	4,4,4
+
+	.long	0x10035CC8
+	.long	0x10234CC8
+	.long	0x104354C8
+
+	.long	0x10E044C8
+
+	vsldoi	5,1,4,8
+	vsldoi	6,4,1,8
+	vxor	0,0,5
+	vxor	2,2,6
+
+	vsldoi	0,0,0,8
+	vxor	0,0,7
+
+	vsldoi	6,0,0,8
+	.long	0x100044C8
+	vxor	6,6,2
+	vxor	0,0,6
+
+	vperm	0,0,0,12
+	.long	0x7C001F99
+
+	mtspr	256,12
+	blr	
+.long	0
+.byte	0,12,0x14,0,0,0,2,0
+.long	0
+
+
+.globl	gcm_ghash_p8
+.align	5
+gcm_ghash_p8:
+	li	0,-4096
+	li	8,0x10
+	mfspr	12,256
+	li	9,0x20
+	mtspr	256,0
+	li	10,0x30
+	.long	0x7C001E99
+
+	.long	0x7D682699
+	li	8,0x40
+	lvsl	12,0,0
+	.long	0x7D292699
+	li	9,0x50
+	vspltisb	5,0x07
+	.long	0x7D4A2699
+	li	10,0x60
+	vxor	12,12,5
+	.long	0x7D002699
+	vperm	0,0,0,12
+	vxor	4,4,4
+
+	cmpldi	6,64
+	bge	Lgcm_ghash_p8_4x
+
+	.long	0x7C602E99
+	addi	5,5,16
+	subic.	6,6,16
+	vperm	3,3,3,12
+	vxor	3,3,0
+	beq	Lshort
+
+	.long	0x7E682699
+	li	8,16
+	.long	0x7E292699
+	add	9,5,6
+	.long	0x7E4A2699
+
+
+.align	5
+Loop_2x:
+	.long	0x7E002E99
+	vperm	16,16,16,12
+
+	subic	6,6,32
+	.long	0x10039CC8
+	.long	0x11B05CC8
+	subfe	0,0,0
+	.long	0x10238CC8
+	.long	0x11D04CC8
+	and	0,0,6
+	.long	0x104394C8
+	.long	0x11F054C8
+	add	5,5,0
+
+	vxor	0,0,13
+	vxor	1,1,14
+
+	.long	0x10E044C8
+
+	vsldoi	5,1,4,8
+	vsldoi	6,4,1,8
+	vxor	2,2,15
+	vxor	0,0,5
+	vxor	2,2,6
+
+	vsldoi	0,0,0,8
+	vxor	0,0,7
+	.long	0x7C682E99
+	addi	5,5,32
+
+	vsldoi	6,0,0,8
+	.long	0x100044C8
+	vperm	3,3,3,12
+	vxor	6,6,2
+	vxor	3,3,6
+	vxor	3,3,0
+	cmpld	9,5
+	bgt	Loop_2x
+
+	cmplwi	6,0
+	bne	Leven
+
+Lshort:
+	.long	0x10035CC8
+	.long	0x10234CC8
+	.long	0x104354C8
+
+	.long	0x10E044C8
+
+	vsldoi	5,1,4,8
+	vsldoi	6,4,1,8
+	vxor	0,0,5
+	vxor	2,2,6
+
+	vsldoi	0,0,0,8
+	vxor	0,0,7
+
+	vsldoi	6,0,0,8
+	.long	0x100044C8
+	vxor	6,6,2
+
+Leven:
+	vxor	0,0,6
+	vperm	0,0,0,12
+	.long	0x7C001F99
+
+	mtspr	256,12
+	blr	
+.long	0
+.byte	0,12,0x14,0,0,0,4,0
+.long	0
+.align	5
+.gcm_ghash_p8_4x:
+Lgcm_ghash_p8_4x:
+	stdu	1,-256(1)
+	li	10,63
+	li	11,79
+	stvx	20,10,1
+	addi	10,10,32
+	stvx	21,11,1
+	addi	11,11,32
+	stvx	22,10,1
+	addi	10,10,32
+	stvx	23,11,1
+	addi	11,11,32
+	stvx	24,10,1
+	addi	10,10,32
+	stvx	25,11,1
+	addi	11,11,32
+	stvx	26,10,1
+	addi	10,10,32
+	stvx	27,11,1
+	addi	11,11,32
+	stvx	28,10,1
+	addi	10,10,32
+	stvx	29,11,1
+	addi	11,11,32
+	stvx	30,10,1
+	li	10,0x60
+	stvx	31,11,1
+	li	0,-1
+	stw	12,252(1)
+	mtspr	256,0
+
+	lvsl	5,0,8
+
+	li	8,0x70
+	.long	0x7E292699
+	li	9,0x80
+	vspltisb	6,8
+
+	li	10,0x90
+	.long	0x7EE82699
+	li	8,0xa0
+	.long	0x7F092699
+	li	9,0xb0
+	.long	0x7F2A2699
+	li	10,0xc0
+	.long	0x7FA82699
+	li	8,0x10
+	.long	0x7FC92699
+	li	9,0x20
+	.long	0x7FEA2699
+	li	10,0x30
+
+	vsldoi	7,4,6,8
+	vaddubm	18,5,7
+	vaddubm	19,6,18
+
+	srdi	6,6,4
+
+	.long	0x7C602E99
+	.long	0x7E082E99
+	subic.	6,6,8
+	.long	0x7EC92E99
+	.long	0x7F8A2E99
+	addi	5,5,0x40
+	vperm	3,3,3,12
+	vperm	16,16,16,12
+	vperm	22,22,22,12
+	vperm	28,28,28,12
+
+	vxor	2,3,0
+
+	.long	0x11B0BCC8
+	.long	0x11D0C4C8
+	.long	0x11F0CCC8
+
+	vperm	11,17,9,18
+	vperm	5,22,28,19
+	vperm	10,17,9,19
+	vperm	6,22,28,18
+	.long	0x12B68CC8
+	.long	0x12855CC8
+	.long	0x137C4CC8
+	.long	0x134654C8
+
+	vxor	21,21,14
+	vxor	20,20,13
+	vxor	27,27,21
+	vxor	26,26,15
+
+	blt	Ltail_4x
+
+Loop_4x:
+	.long	0x7C602E99
+	.long	0x7E082E99
+	subic.	6,6,4
+	.long	0x7EC92E99
+	.long	0x7F8A2E99
+	addi	5,5,0x40
+	vperm	16,16,16,12
+	vperm	22,22,22,12
+	vperm	28,28,28,12
+	vperm	3,3,3,12
+
+	.long	0x1002ECC8
+	.long	0x1022F4C8
+	.long	0x1042FCC8
+	.long	0x11B0BCC8
+	.long	0x11D0C4C8
+	.long	0x11F0CCC8
+
+	vxor	0,0,20
+	vxor	1,1,27
+	vxor	2,2,26
+	vperm	5,22,28,19
+	vperm	6,22,28,18
+
+	.long	0x10E044C8
+	.long	0x12855CC8
+	.long	0x134654C8
+
+	vsldoi	5,1,4,8
+	vsldoi	6,4,1,8
+	vxor	0,0,5
+	vxor	2,2,6
+
+	vsldoi	0,0,0,8
+	vxor	0,0,7
+
+	vsldoi	6,0,0,8
+	.long	0x12B68CC8
+	.long	0x137C4CC8
+	.long	0x100044C8
+
+	vxor	20,20,13
+	vxor	26,26,15
+	vxor	2,2,3
+	vxor	21,21,14
+	vxor	2,2,6
+	vxor	27,27,21
+	vxor	2,2,0
+	bge	Loop_4x
+
+Ltail_4x:
+	.long	0x1002ECC8
+	.long	0x1022F4C8
+	.long	0x1042FCC8
+
+	vxor	0,0,20
+	vxor	1,1,27
+
+	.long	0x10E044C8
+
+	vsldoi	5,1,4,8
+	vsldoi	6,4,1,8
+	vxor	2,2,26
+	vxor	0,0,5
+	vxor	2,2,6
+
+	vsldoi	0,0,0,8
+	vxor	0,0,7
+
+	vsldoi	6,0,0,8
+	.long	0x100044C8
+	vxor	6,6,2
+	vxor	0,0,6
+
+	addic.	6,6,4
+	beq	Ldone_4x
+
+	.long	0x7C602E99
+	cmpldi	6,2
+	li	6,-4
+	blt	Lone
+	.long	0x7E082E99
+	beq	Ltwo
+
+Lthree:
+	.long	0x7EC92E99
+	vperm	3,3,3,12
+	vperm	16,16,16,12
+	vperm	22,22,22,12
+
+	vxor	2,3,0
+	vor	29,23,23
+	vor	30, 24, 24
+	vor	31,25,25
+
+	vperm	5,16,22,19
+	vperm	6,16,22,18
+	.long	0x12B08CC8
+	.long	0x13764CC8
+	.long	0x12855CC8
+	.long	0x134654C8
+
+	vxor	27,27,21
+	b	Ltail_4x
+
+.align	4
+Ltwo:
+	vperm	3,3,3,12
+	vperm	16,16,16,12
+
+	vxor	2,3,0
+	vperm	5,4,16,19
+	vperm	6,4,16,18
+
+	vsldoi	29,4,17,8
+	vor	30, 17, 17
+	vsldoi	31,17,4,8
+
+	.long	0x12855CC8
+	.long	0x13704CC8
+	.long	0x134654C8
+
+	b	Ltail_4x
+
+.align	4
+Lone:
+	vperm	3,3,3,12
+
+	vsldoi	29,4,9,8
+	vor	30, 9, 9
+	vsldoi	31,9,4,8
+
+	vxor	2,3,0
+	vxor	20,20,20
+	vxor	27,27,27
+	vxor	26,26,26
+
+	b	Ltail_4x
+
+Ldone_4x:
+	vperm	0,0,0,12
+	.long	0x7C001F99
+
+	li	10,63
+	li	11,79
+	mtspr	256,12
+	lvx	20,10,1
+	addi	10,10,32
+	lvx	21,11,1
+	addi	11,11,32
+	lvx	22,10,1
+	addi	10,10,32
+	lvx	23,11,1
+	addi	11,11,32
+	lvx	24,10,1
+	addi	10,10,32
+	lvx	25,11,1
+	addi	11,11,32
+	lvx	26,10,1
+	addi	10,10,32
+	lvx	27,11,1
+	addi	11,11,32
+	lvx	28,10,1
+	addi	10,10,32
+	lvx	29,11,1
+	addi	11,11,32
+	lvx	30,10,1
+	lvx	31,11,1
+	addi	1,1,256
+	blr	
+.long	0
+.byte	0,12,0x04,0,0x80,0,4,0
+.long	0
+
+
+.byte	71,72,65,83,72,32,102,111,114,32,80,111,119,101,114,73,83,65,32,50,46,48,55,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.align	2
+.align	2
diff --git a/linux-x86/crypto/bn/x86-mont.S b/linux-x86/crypto/bn/x86-mont.S
index 1569b2c..e291a88 100644
--- a/linux-x86/crypto/bn/x86-mont.S
+++ b/linux-x86/crypto/bn/x86-mont.S
@@ -17,39 +17,54 @@
 	jl	.L000just_leave
 	leal	20(%esp),%esi
 	leal	24(%esp),%edx
-	movl	%esp,%ebp
 	addl	$2,%edi
 	negl	%edi
-	leal	-32(%esp,%edi,4),%esp
+	leal	-32(%esp,%edi,4),%ebp
 	negl	%edi
-	movl	%esp,%eax
+	movl	%ebp,%eax
 	subl	%edx,%eax
 	andl	$2047,%eax
-	subl	%eax,%esp
-	xorl	%esp,%edx
+	subl	%eax,%ebp
+	xorl	%ebp,%edx
 	andl	$2048,%edx
 	xorl	$2048,%edx
-	subl	%edx,%esp
-	andl	$-64,%esp
+	subl	%edx,%ebp
+	andl	$-64,%ebp
+	movl	%esp,%eax
+	subl	%ebp,%eax
+	andl	$-4096,%eax
+	movl	%esp,%edx
+	leal	(%ebp,%eax,1),%esp
+	movl	(%esp),%eax
+	cmpl	%ebp,%esp
+	ja	.L001page_walk
+	jmp	.L002page_walk_done
+.align	16
+.L001page_walk:
+	leal	-4096(%esp),%esp
+	movl	(%esp),%eax
+	cmpl	%ebp,%esp
+	ja	.L001page_walk
+.L002page_walk_done:
 	movl	(%esi),%eax
 	movl	4(%esi),%ebx
 	movl	8(%esi),%ecx
-	movl	12(%esi),%edx
+	movl	12(%esi),%ebp
 	movl	16(%esi),%esi
 	movl	(%esi),%esi
 	movl	%eax,4(%esp)
 	movl	%ebx,8(%esp)
 	movl	%ecx,12(%esp)
-	movl	%edx,16(%esp)
+	movl	%ebp,16(%esp)
 	movl	%esi,20(%esp)
 	leal	-3(%edi),%ebx
-	movl	%ebp,24(%esp)
-	call	.L001PIC_me_up
-.L001PIC_me_up:
+	movl	%edx,24(%esp)
+	call	.L003PIC_me_up
+.L003PIC_me_up:
 	popl	%eax
-	leal	OPENSSL_ia32cap_P-.L001PIC_me_up(%eax),%eax
+	leal	OPENSSL_ia32cap_P-.L003PIC_me_up(%eax),%eax
 	btl	$26,(%eax)
-	jnc	.L002non_sse2
+	jnc	.L004non_sse2
 	movl	$-1,%eax
 	movd	%eax,%mm7
 	movl	8(%esp),%esi
@@ -73,7 +88,7 @@
 	psrlq	$32,%mm3
 	incl	%ecx
 .align	16
-.L0031st:
+.L0051st:
 	pmuludq	%mm4,%mm0
 	pmuludq	%mm5,%mm1
 	paddq	%mm0,%mm2
@@ -88,7 +103,7 @@
 	psrlq	$32,%mm3
 	leal	1(%ecx),%ecx
 	cmpl	%ebx,%ecx
-	jl	.L0031st
+	jl	.L0051st
 	pmuludq	%mm4,%mm0
 	pmuludq	%mm5,%mm1
 	paddq	%mm0,%mm2
@@ -102,7 +117,7 @@
 	paddq	%mm2,%mm3
 	movq	%mm3,32(%esp,%ebx,4)
 	incl	%edx
-.L004outer:
+.L006outer:
 	xorl	%ecx,%ecx
 	movd	(%edi,%edx,4),%mm4
 	movd	(%esi),%mm5
@@ -124,7 +139,7 @@
 	paddq	%mm6,%mm2
 	incl	%ecx
 	decl	%ebx
-.L005inner:
+.L007inner:
 	pmuludq	%mm4,%mm0
 	pmuludq	%mm5,%mm1
 	paddq	%mm0,%mm2
@@ -141,7 +156,7 @@
 	paddq	%mm6,%mm2
 	decl	%ebx
 	leal	1(%ecx),%ecx
-	jnz	.L005inner
+	jnz	.L007inner
 	movl	%ecx,%ebx
 	pmuludq	%mm4,%mm0
 	pmuludq	%mm5,%mm1
@@ -159,11 +174,11 @@
 	movq	%mm3,32(%esp,%ebx,4)
 	leal	1(%edx),%edx
 	cmpl	%ebx,%edx
-	jle	.L004outer
+	jle	.L006outer
 	emms
-	jmp	.L006common_tail
+	jmp	.L008common_tail
 .align	16
-.L002non_sse2:
+.L004non_sse2:
 	movl	8(%esp),%esi
 	leal	1(%ebx),%ebp
 	movl	12(%esp),%edi
@@ -174,12 +189,12 @@
 	leal	4(%edi,%ebx,4),%eax
 	orl	%edx,%ebp
 	movl	(%edi),%edi
-	jz	.L007bn_sqr_mont
+	jz	.L009bn_sqr_mont
 	movl	%eax,28(%esp)
 	movl	(%esi),%eax
 	xorl	%edx,%edx
 .align	16
-.L008mull:
+.L010mull:
 	movl	%edx,%ebp
 	mull	%edi
 	addl	%eax,%ebp
@@ -188,7 +203,7 @@
 	movl	(%esi,%ecx,4),%eax
 	cmpl	%ebx,%ecx
 	movl	%ebp,28(%esp,%ecx,4)
-	jl	.L008mull
+	jl	.L010mull
 	movl	%edx,%ebp
 	mull	%edi
 	movl	20(%esp),%edi
@@ -206,9 +221,9 @@
 	movl	4(%esi),%eax
 	adcl	$0,%edx
 	incl	%ecx
-	jmp	.L0092ndmadd
+	jmp	.L0112ndmadd
 .align	16
-.L0101stmadd:
+.L0121stmadd:
 	movl	%edx,%ebp
 	mull	%edi
 	addl	32(%esp,%ecx,4),%ebp
@@ -219,7 +234,7 @@
 	adcl	$0,%edx
 	cmpl	%ebx,%ecx
 	movl	%ebp,28(%esp,%ecx,4)
-	jl	.L0101stmadd
+	jl	.L0121stmadd
 	movl	%edx,%ebp
 	mull	%edi
 	addl	32(%esp,%ebx,4),%eax
@@ -242,7 +257,7 @@
 	adcl	$0,%edx
 	movl	$1,%ecx
 .align	16
-.L0092ndmadd:
+.L0112ndmadd:
 	movl	%edx,%ebp
 	mull	%edi
 	addl	32(%esp,%ecx,4),%ebp
@@ -253,7 +268,7 @@
 	adcl	$0,%edx
 	cmpl	%ebx,%ecx
 	movl	%ebp,24(%esp,%ecx,4)
-	jl	.L0092ndmadd
+	jl	.L0112ndmadd
 	movl	%edx,%ebp
 	mull	%edi
 	addl	32(%esp,%ebx,4),%ebp
@@ -269,16 +284,16 @@
 	movl	%edx,32(%esp,%ebx,4)
 	cmpl	28(%esp),%ecx
 	movl	%eax,36(%esp,%ebx,4)
-	je	.L006common_tail
+	je	.L008common_tail
 	movl	(%ecx),%edi
 	movl	8(%esp),%esi
 	movl	%ecx,12(%esp)
 	xorl	%ecx,%ecx
 	xorl	%edx,%edx
 	movl	(%esi),%eax
-	jmp	.L0101stmadd
+	jmp	.L0121stmadd
 .align	16
-.L007bn_sqr_mont:
+.L009bn_sqr_mont:
 	movl	%ebx,(%esp)
 	movl	%ecx,12(%esp)
 	movl	%edi,%eax
@@ -289,7 +304,7 @@
 	andl	$1,%ebx
 	incl	%ecx
 .align	16
-.L011sqr:
+.L013sqr:
 	movl	(%esi,%ecx,4),%eax
 	movl	%edx,%ebp
 	mull	%edi
@@ -301,7 +316,7 @@
 	cmpl	(%esp),%ecx
 	movl	%eax,%ebx
 	movl	%ebp,28(%esp,%ecx,4)
-	jl	.L011sqr
+	jl	.L013sqr
 	movl	(%esi,%ecx,4),%eax
 	movl	%edx,%ebp
 	mull	%edi
@@ -325,7 +340,7 @@
 	movl	4(%esi),%eax
 	movl	$1,%ecx
 .align	16
-.L0123rdmadd:
+.L0143rdmadd:
 	movl	%edx,%ebp
 	mull	%edi
 	addl	32(%esp,%ecx,4),%ebp
@@ -344,7 +359,7 @@
 	adcl	$0,%edx
 	cmpl	%ebx,%ecx
 	movl	%ebp,24(%esp,%ecx,4)
-	jl	.L0123rdmadd
+	jl	.L0143rdmadd
 	movl	%edx,%ebp
 	mull	%edi
 	addl	32(%esp,%ebx,4),%ebp
@@ -360,7 +375,7 @@
 	movl	%edx,32(%esp,%ebx,4)
 	cmpl	%ebx,%ecx
 	movl	%eax,36(%esp,%ebx,4)
-	je	.L006common_tail
+	je	.L008common_tail
 	movl	4(%esi,%ecx,4),%edi
 	leal	1(%ecx),%ecx
 	movl	%edi,%eax
@@ -372,12 +387,12 @@
 	xorl	%ebp,%ebp
 	cmpl	%ebx,%ecx
 	leal	1(%ecx),%ecx
-	je	.L013sqrlast
+	je	.L015sqrlast
 	movl	%edx,%ebx
 	shrl	$1,%edx
 	andl	$1,%ebx
 .align	16
-.L014sqradd:
+.L016sqradd:
 	movl	(%esi,%ecx,4),%eax
 	movl	%edx,%ebp
 	mull	%edi
@@ -393,13 +408,13 @@
 	cmpl	(%esp),%ecx
 	movl	%ebp,28(%esp,%ecx,4)
 	movl	%eax,%ebx
-	jle	.L014sqradd
+	jle	.L016sqradd
 	movl	%edx,%ebp
 	addl	%edx,%edx
 	shrl	$31,%ebp
 	addl	%ebx,%edx
 	adcl	$0,%ebp
-.L013sqrlast:
+.L015sqrlast:
 	movl	20(%esp),%edi
 	movl	16(%esp),%esi
 	imull	32(%esp),%edi
@@ -414,9 +429,9 @@
 	adcl	$0,%edx
 	movl	$1,%ecx
 	movl	4(%esi),%eax
-	jmp	.L0123rdmadd
+	jmp	.L0143rdmadd
 .align	16
-.L006common_tail:
+.L008common_tail:
 	movl	16(%esp),%ebp
 	movl	4(%esp),%edi
 	leal	32(%esp),%esi
@@ -424,25 +439,26 @@
 	movl	%ebx,%ecx
 	xorl	%edx,%edx
 .align	16
-.L015sub:
+.L017sub:
 	sbbl	(%ebp,%edx,4),%eax
 	movl	%eax,(%edi,%edx,4)
 	decl	%ecx
 	movl	4(%esi,%edx,4),%eax
 	leal	1(%edx),%edx
-	jge	.L015sub
+	jge	.L017sub
 	sbbl	$0,%eax
+	andl	%eax,%esi
+	notl	%eax
+	movl	%edi,%ebp
+	andl	%eax,%ebp
+	orl	%ebp,%esi
 .align	16
-.L016copy:
-	movl	(%esi,%ebx,4),%edx
-	movl	(%edi,%ebx,4),%ebp
-	xorl	%ebp,%edx
-	andl	%eax,%edx
-	xorl	%ebp,%edx
-	movl	%ecx,(%esi,%ebx,4)
-	movl	%edx,(%edi,%ebx,4)
+.L018copy:
+	movl	(%esi,%ebx,4),%eax
+	movl	%eax,(%edi,%ebx,4)
+	movl	%ecx,32(%esp,%ebx,4)
 	decl	%ebx
-	jge	.L016copy
+	jge	.L018copy
 	movl	24(%esp),%esp
 	movl	$1,%eax
 .L000just_leave:
diff --git a/linux-x86/crypto/chacha/chacha-x86.S b/linux-x86/crypto/chacha/chacha-x86.S
new file mode 100644
index 0000000..d3c39ac
--- /dev/null
+++ b/linux-x86/crypto/chacha/chacha-x86.S
@@ -0,0 +1,969 @@
+#if defined(__i386__)
+.file	"chacha-x86.S"
+.text
+.globl	ChaCha20_ctr32
+.hidden	ChaCha20_ctr32
+.type	ChaCha20_ctr32,@function
+.align	16
+ChaCha20_ctr32:
+.L_ChaCha20_ctr32_begin:
+	pushl	%ebp
+	pushl	%ebx
+	pushl	%esi
+	pushl	%edi
+	xorl	%eax,%eax
+	cmpl	28(%esp),%eax
+	je	.L000no_data
+	call	.Lpic_point
+.Lpic_point:
+	popl	%eax
+	leal	OPENSSL_ia32cap_P-.Lpic_point(%eax),%ebp
+	testl	$16777216,(%ebp)
+	jz	.L001x86
+	testl	$512,4(%ebp)
+	jz	.L001x86
+	jmp	.Lssse3_shortcut
+.L001x86:
+	movl	32(%esp),%esi
+	movl	36(%esp),%edi
+	subl	$132,%esp
+	movl	(%esi),%eax
+	movl	4(%esi),%ebx
+	movl	8(%esi),%ecx
+	movl	12(%esi),%edx
+	movl	%eax,80(%esp)
+	movl	%ebx,84(%esp)
+	movl	%ecx,88(%esp)
+	movl	%edx,92(%esp)
+	movl	16(%esi),%eax
+	movl	20(%esi),%ebx
+	movl	24(%esi),%ecx
+	movl	28(%esi),%edx
+	movl	%eax,96(%esp)
+	movl	%ebx,100(%esp)
+	movl	%ecx,104(%esp)
+	movl	%edx,108(%esp)
+	movl	(%edi),%eax
+	movl	4(%edi),%ebx
+	movl	8(%edi),%ecx
+	movl	12(%edi),%edx
+	subl	$1,%eax
+	movl	%eax,112(%esp)
+	movl	%ebx,116(%esp)
+	movl	%ecx,120(%esp)
+	movl	%edx,124(%esp)
+	jmp	.L002entry
+.align	16
+.L003outer_loop:
+	movl	%ebx,156(%esp)
+	movl	%eax,152(%esp)
+	movl	%ecx,160(%esp)
+.L002entry:
+	movl	$1634760805,%eax
+	movl	$857760878,4(%esp)
+	movl	$2036477234,8(%esp)
+	movl	$1797285236,12(%esp)
+	movl	84(%esp),%ebx
+	movl	88(%esp),%ebp
+	movl	104(%esp),%ecx
+	movl	108(%esp),%esi
+	movl	116(%esp),%edx
+	movl	120(%esp),%edi
+	movl	%ebx,20(%esp)
+	movl	%ebp,24(%esp)
+	movl	%ecx,40(%esp)
+	movl	%esi,44(%esp)
+	movl	%edx,52(%esp)
+	movl	%edi,56(%esp)
+	movl	92(%esp),%ebx
+	movl	124(%esp),%edi
+	movl	112(%esp),%edx
+	movl	80(%esp),%ebp
+	movl	96(%esp),%ecx
+	movl	100(%esp),%esi
+	addl	$1,%edx
+	movl	%ebx,28(%esp)
+	movl	%edi,60(%esp)
+	movl	%edx,112(%esp)
+	movl	$10,%ebx
+	jmp	.L004loop
+.align	16
+.L004loop:
+	addl	%ebp,%eax
+	movl	%ebx,128(%esp)
+	movl	%ebp,%ebx
+	xorl	%eax,%edx
+	roll	$16,%edx
+	addl	%edx,%ecx
+	xorl	%ecx,%ebx
+	movl	52(%esp),%edi
+	roll	$12,%ebx
+	movl	20(%esp),%ebp
+	addl	%ebx,%eax
+	xorl	%eax,%edx
+	movl	%eax,(%esp)
+	roll	$8,%edx
+	movl	4(%esp),%eax
+	addl	%edx,%ecx
+	movl	%edx,48(%esp)
+	xorl	%ecx,%ebx
+	addl	%ebp,%eax
+	roll	$7,%ebx
+	xorl	%eax,%edi
+	movl	%ecx,32(%esp)
+	roll	$16,%edi
+	movl	%ebx,16(%esp)
+	addl	%edi,%esi
+	movl	40(%esp),%ecx
+	xorl	%esi,%ebp
+	movl	56(%esp),%edx
+	roll	$12,%ebp
+	movl	24(%esp),%ebx
+	addl	%ebp,%eax
+	xorl	%eax,%edi
+	movl	%eax,4(%esp)
+	roll	$8,%edi
+	movl	8(%esp),%eax
+	addl	%edi,%esi
+	movl	%edi,52(%esp)
+	xorl	%esi,%ebp
+	addl	%ebx,%eax
+	roll	$7,%ebp
+	xorl	%eax,%edx
+	movl	%esi,36(%esp)
+	roll	$16,%edx
+	movl	%ebp,20(%esp)
+	addl	%edx,%ecx
+	movl	44(%esp),%esi
+	xorl	%ecx,%ebx
+	movl	60(%esp),%edi
+	roll	$12,%ebx
+	movl	28(%esp),%ebp
+	addl	%ebx,%eax
+	xorl	%eax,%edx
+	movl	%eax,8(%esp)
+	roll	$8,%edx
+	movl	12(%esp),%eax
+	addl	%edx,%ecx
+	movl	%edx,56(%esp)
+	xorl	%ecx,%ebx
+	addl	%ebp,%eax
+	roll	$7,%ebx
+	xorl	%eax,%edi
+	roll	$16,%edi
+	movl	%ebx,24(%esp)
+	addl	%edi,%esi
+	xorl	%esi,%ebp
+	roll	$12,%ebp
+	movl	20(%esp),%ebx
+	addl	%ebp,%eax
+	xorl	%eax,%edi
+	movl	%eax,12(%esp)
+	roll	$8,%edi
+	movl	(%esp),%eax
+	addl	%edi,%esi
+	movl	%edi,%edx
+	xorl	%esi,%ebp
+	addl	%ebx,%eax
+	roll	$7,%ebp
+	xorl	%eax,%edx
+	roll	$16,%edx
+	movl	%ebp,28(%esp)
+	addl	%edx,%ecx
+	xorl	%ecx,%ebx
+	movl	48(%esp),%edi
+	roll	$12,%ebx
+	movl	24(%esp),%ebp
+	addl	%ebx,%eax
+	xorl	%eax,%edx
+	movl	%eax,(%esp)
+	roll	$8,%edx
+	movl	4(%esp),%eax
+	addl	%edx,%ecx
+	movl	%edx,60(%esp)
+	xorl	%ecx,%ebx
+	addl	%ebp,%eax
+	roll	$7,%ebx
+	xorl	%eax,%edi
+	movl	%ecx,40(%esp)
+	roll	$16,%edi
+	movl	%ebx,20(%esp)
+	addl	%edi,%esi
+	movl	32(%esp),%ecx
+	xorl	%esi,%ebp
+	movl	52(%esp),%edx
+	roll	$12,%ebp
+	movl	28(%esp),%ebx
+	addl	%ebp,%eax
+	xorl	%eax,%edi
+	movl	%eax,4(%esp)
+	roll	$8,%edi
+	movl	8(%esp),%eax
+	addl	%edi,%esi
+	movl	%edi,48(%esp)
+	xorl	%esi,%ebp
+	addl	%ebx,%eax
+	roll	$7,%ebp
+	xorl	%eax,%edx
+	movl	%esi,44(%esp)
+	roll	$16,%edx
+	movl	%ebp,24(%esp)
+	addl	%edx,%ecx
+	movl	36(%esp),%esi
+	xorl	%ecx,%ebx
+	movl	56(%esp),%edi
+	roll	$12,%ebx
+	movl	16(%esp),%ebp
+	addl	%ebx,%eax
+	xorl	%eax,%edx
+	movl	%eax,8(%esp)
+	roll	$8,%edx
+	movl	12(%esp),%eax
+	addl	%edx,%ecx
+	movl	%edx,52(%esp)
+	xorl	%ecx,%ebx
+	addl	%ebp,%eax
+	roll	$7,%ebx
+	xorl	%eax,%edi
+	roll	$16,%edi
+	movl	%ebx,28(%esp)
+	addl	%edi,%esi
+	xorl	%esi,%ebp
+	movl	48(%esp),%edx
+	roll	$12,%ebp
+	movl	128(%esp),%ebx
+	addl	%ebp,%eax
+	xorl	%eax,%edi
+	movl	%eax,12(%esp)
+	roll	$8,%edi
+	movl	(%esp),%eax
+	addl	%edi,%esi
+	movl	%edi,56(%esp)
+	xorl	%esi,%ebp
+	roll	$7,%ebp
+	decl	%ebx
+	jnz	.L004loop
+	movl	160(%esp),%ebx
+	addl	$1634760805,%eax
+	addl	80(%esp),%ebp
+	addl	96(%esp),%ecx
+	addl	100(%esp),%esi
+	cmpl	$64,%ebx
+	jb	.L005tail
+	movl	156(%esp),%ebx
+	addl	112(%esp),%edx
+	addl	120(%esp),%edi
+	xorl	(%ebx),%eax
+	xorl	16(%ebx),%ebp
+	movl	%eax,(%esp)
+	movl	152(%esp),%eax
+	xorl	32(%ebx),%ecx
+	xorl	36(%ebx),%esi
+	xorl	48(%ebx),%edx
+	xorl	56(%ebx),%edi
+	movl	%ebp,16(%eax)
+	movl	%ecx,32(%eax)
+	movl	%esi,36(%eax)
+	movl	%edx,48(%eax)
+	movl	%edi,56(%eax)
+	movl	4(%esp),%ebp
+	movl	8(%esp),%ecx
+	movl	12(%esp),%esi
+	movl	20(%esp),%edx
+	movl	24(%esp),%edi
+	addl	$857760878,%ebp
+	addl	$2036477234,%ecx
+	addl	$1797285236,%esi
+	addl	84(%esp),%edx
+	addl	88(%esp),%edi
+	xorl	4(%ebx),%ebp
+	xorl	8(%ebx),%ecx
+	xorl	12(%ebx),%esi
+	xorl	20(%ebx),%edx
+	xorl	24(%ebx),%edi
+	movl	%ebp,4(%eax)
+	movl	%ecx,8(%eax)
+	movl	%esi,12(%eax)
+	movl	%edx,20(%eax)
+	movl	%edi,24(%eax)
+	movl	28(%esp),%ebp
+	movl	40(%esp),%ecx
+	movl	44(%esp),%esi
+	movl	52(%esp),%edx
+	movl	60(%esp),%edi
+	addl	92(%esp),%ebp
+	addl	104(%esp),%ecx
+	addl	108(%esp),%esi
+	addl	116(%esp),%edx
+	addl	124(%esp),%edi
+	xorl	28(%ebx),%ebp
+	xorl	40(%ebx),%ecx
+	xorl	44(%ebx),%esi
+	xorl	52(%ebx),%edx
+	xorl	60(%ebx),%edi
+	leal	64(%ebx),%ebx
+	movl	%ebp,28(%eax)
+	movl	(%esp),%ebp
+	movl	%ecx,40(%eax)
+	movl	160(%esp),%ecx
+	movl	%esi,44(%eax)
+	movl	%edx,52(%eax)
+	movl	%edi,60(%eax)
+	movl	%ebp,(%eax)
+	leal	64(%eax),%eax
+	subl	$64,%ecx
+	jnz	.L003outer_loop
+	jmp	.L006done
+.L005tail:
+	addl	112(%esp),%edx
+	addl	120(%esp),%edi
+	movl	%eax,(%esp)
+	movl	%ebp,16(%esp)
+	movl	%ecx,32(%esp)
+	movl	%esi,36(%esp)
+	movl	%edx,48(%esp)
+	movl	%edi,56(%esp)
+	movl	4(%esp),%ebp
+	movl	8(%esp),%ecx
+	movl	12(%esp),%esi
+	movl	20(%esp),%edx
+	movl	24(%esp),%edi
+	addl	$857760878,%ebp
+	addl	$2036477234,%ecx
+	addl	$1797285236,%esi
+	addl	84(%esp),%edx
+	addl	88(%esp),%edi
+	movl	%ebp,4(%esp)
+	movl	%ecx,8(%esp)
+	movl	%esi,12(%esp)
+	movl	%edx,20(%esp)
+	movl	%edi,24(%esp)
+	movl	28(%esp),%ebp
+	movl	40(%esp),%ecx
+	movl	44(%esp),%esi
+	movl	52(%esp),%edx
+	movl	60(%esp),%edi
+	addl	92(%esp),%ebp
+	addl	104(%esp),%ecx
+	addl	108(%esp),%esi
+	addl	116(%esp),%edx
+	addl	124(%esp),%edi
+	movl	%ebp,28(%esp)
+	movl	156(%esp),%ebp
+	movl	%ecx,40(%esp)
+	movl	152(%esp),%ecx
+	movl	%esi,44(%esp)
+	xorl	%esi,%esi
+	movl	%edx,52(%esp)
+	movl	%edi,60(%esp)
+	xorl	%eax,%eax
+	xorl	%edx,%edx
+.L007tail_loop:
+	movb	(%esi,%ebp,1),%al
+	movb	(%esp,%esi,1),%dl
+	leal	1(%esi),%esi
+	xorb	%dl,%al
+	movb	%al,-1(%ecx,%esi,1)
+	decl	%ebx
+	jnz	.L007tail_loop
+.L006done:
+	addl	$132,%esp
+.L000no_data:
+	popl	%edi
+	popl	%esi
+	popl	%ebx
+	popl	%ebp
+	ret
+.size	ChaCha20_ctr32,.-.L_ChaCha20_ctr32_begin
+.globl	ChaCha20_ssse3
+.hidden	ChaCha20_ssse3
+.type	ChaCha20_ssse3,@function
+.align	16
+ChaCha20_ssse3:
+.L_ChaCha20_ssse3_begin:
+	pushl	%ebp
+	pushl	%ebx
+	pushl	%esi
+	pushl	%edi
+.Lssse3_shortcut:
+	movl	20(%esp),%edi
+	movl	24(%esp),%esi
+	movl	28(%esp),%ecx
+	movl	32(%esp),%edx
+	movl	36(%esp),%ebx
+	movl	%esp,%ebp
+	subl	$524,%esp
+	andl	$-64,%esp
+	movl	%ebp,512(%esp)
+	leal	.Lssse3_data-.Lpic_point(%eax),%eax
+	movdqu	(%ebx),%xmm3
+	cmpl	$256,%ecx
+	jb	.L0081x
+	movl	%edx,516(%esp)
+	movl	%ebx,520(%esp)
+	subl	$256,%ecx
+	leal	384(%esp),%ebp
+	movdqu	(%edx),%xmm7
+	pshufd	$0,%xmm3,%xmm0
+	pshufd	$85,%xmm3,%xmm1
+	pshufd	$170,%xmm3,%xmm2
+	pshufd	$255,%xmm3,%xmm3
+	paddd	48(%eax),%xmm0
+	pshufd	$0,%xmm7,%xmm4
+	pshufd	$85,%xmm7,%xmm5
+	psubd	64(%eax),%xmm0
+	pshufd	$170,%xmm7,%xmm6
+	pshufd	$255,%xmm7,%xmm7
+	movdqa	%xmm0,64(%ebp)
+	movdqa	%xmm1,80(%ebp)
+	movdqa	%xmm2,96(%ebp)
+	movdqa	%xmm3,112(%ebp)
+	movdqu	16(%edx),%xmm3
+	movdqa	%xmm4,-64(%ebp)
+	movdqa	%xmm5,-48(%ebp)
+	movdqa	%xmm6,-32(%ebp)
+	movdqa	%xmm7,-16(%ebp)
+	movdqa	32(%eax),%xmm7
+	leal	128(%esp),%ebx
+	pshufd	$0,%xmm3,%xmm0
+	pshufd	$85,%xmm3,%xmm1
+	pshufd	$170,%xmm3,%xmm2
+	pshufd	$255,%xmm3,%xmm3
+	pshufd	$0,%xmm7,%xmm4
+	pshufd	$85,%xmm7,%xmm5
+	pshufd	$170,%xmm7,%xmm6
+	pshufd	$255,%xmm7,%xmm7
+	movdqa	%xmm0,(%ebp)
+	movdqa	%xmm1,16(%ebp)
+	movdqa	%xmm2,32(%ebp)
+	movdqa	%xmm3,48(%ebp)
+	movdqa	%xmm4,-128(%ebp)
+	movdqa	%xmm5,-112(%ebp)
+	movdqa	%xmm6,-96(%ebp)
+	movdqa	%xmm7,-80(%ebp)
+	leal	128(%esi),%esi
+	leal	128(%edi),%edi
+	jmp	.L009outer_loop
+.align	16
+.L009outer_loop:
+	movdqa	-112(%ebp),%xmm1
+	movdqa	-96(%ebp),%xmm2
+	movdqa	-80(%ebp),%xmm3
+	movdqa	-48(%ebp),%xmm5
+	movdqa	-32(%ebp),%xmm6
+	movdqa	-16(%ebp),%xmm7
+	movdqa	%xmm1,-112(%ebx)
+	movdqa	%xmm2,-96(%ebx)
+	movdqa	%xmm3,-80(%ebx)
+	movdqa	%xmm5,-48(%ebx)
+	movdqa	%xmm6,-32(%ebx)
+	movdqa	%xmm7,-16(%ebx)
+	movdqa	32(%ebp),%xmm2
+	movdqa	48(%ebp),%xmm3
+	movdqa	64(%ebp),%xmm4
+	movdqa	80(%ebp),%xmm5
+	movdqa	96(%ebp),%xmm6
+	movdqa	112(%ebp),%xmm7
+	paddd	64(%eax),%xmm4
+	movdqa	%xmm2,32(%ebx)
+	movdqa	%xmm3,48(%ebx)
+	movdqa	%xmm4,64(%ebx)
+	movdqa	%xmm5,80(%ebx)
+	movdqa	%xmm6,96(%ebx)
+	movdqa	%xmm7,112(%ebx)
+	movdqa	%xmm4,64(%ebp)
+	movdqa	-128(%ebp),%xmm0
+	movdqa	%xmm4,%xmm6
+	movdqa	-64(%ebp),%xmm3
+	movdqa	(%ebp),%xmm4
+	movdqa	16(%ebp),%xmm5
+	movl	$10,%edx
+	nop
+.align	16
+.L010loop:
+	paddd	%xmm3,%xmm0
+	movdqa	%xmm3,%xmm2
+	pxor	%xmm0,%xmm6
+	pshufb	(%eax),%xmm6
+	paddd	%xmm6,%xmm4
+	pxor	%xmm4,%xmm2
+	movdqa	-48(%ebx),%xmm3
+	movdqa	%xmm2,%xmm1
+	pslld	$12,%xmm2
+	psrld	$20,%xmm1
+	por	%xmm1,%xmm2
+	movdqa	-112(%ebx),%xmm1
+	paddd	%xmm2,%xmm0
+	movdqa	80(%ebx),%xmm7
+	pxor	%xmm0,%xmm6
+	movdqa	%xmm0,-128(%ebx)
+	pshufb	16(%eax),%xmm6
+	paddd	%xmm6,%xmm4
+	movdqa	%xmm6,64(%ebx)
+	pxor	%xmm4,%xmm2
+	paddd	%xmm3,%xmm1
+	movdqa	%xmm2,%xmm0
+	pslld	$7,%xmm2
+	psrld	$25,%xmm0
+	pxor	%xmm1,%xmm7
+	por	%xmm0,%xmm2
+	movdqa	%xmm4,(%ebx)
+	pshufb	(%eax),%xmm7
+	movdqa	%xmm2,-64(%ebx)
+	paddd	%xmm7,%xmm5
+	movdqa	32(%ebx),%xmm4
+	pxor	%xmm5,%xmm3
+	movdqa	-32(%ebx),%xmm2
+	movdqa	%xmm3,%xmm0
+	pslld	$12,%xmm3
+	psrld	$20,%xmm0
+	por	%xmm0,%xmm3
+	movdqa	-96(%ebx),%xmm0
+	paddd	%xmm3,%xmm1
+	movdqa	96(%ebx),%xmm6
+	pxor	%xmm1,%xmm7
+	movdqa	%xmm1,-112(%ebx)
+	pshufb	16(%eax),%xmm7
+	paddd	%xmm7,%xmm5
+	movdqa	%xmm7,80(%ebx)
+	pxor	%xmm5,%xmm3
+	paddd	%xmm2,%xmm0
+	movdqa	%xmm3,%xmm1
+	pslld	$7,%xmm3
+	psrld	$25,%xmm1
+	pxor	%xmm0,%xmm6
+	por	%xmm1,%xmm3
+	movdqa	%xmm5,16(%ebx)
+	pshufb	(%eax),%xmm6
+	movdqa	%xmm3,-48(%ebx)
+	paddd	%xmm6,%xmm4
+	movdqa	48(%ebx),%xmm5
+	pxor	%xmm4,%xmm2
+	movdqa	-16(%ebx),%xmm3
+	movdqa	%xmm2,%xmm1
+	pslld	$12,%xmm2
+	psrld	$20,%xmm1
+	por	%xmm1,%xmm2
+	movdqa	-80(%ebx),%xmm1
+	paddd	%xmm2,%xmm0
+	movdqa	112(%ebx),%xmm7
+	pxor	%xmm0,%xmm6
+	movdqa	%xmm0,-96(%ebx)
+	pshufb	16(%eax),%xmm6
+	paddd	%xmm6,%xmm4
+	movdqa	%xmm6,96(%ebx)
+	pxor	%xmm4,%xmm2
+	paddd	%xmm3,%xmm1
+	movdqa	%xmm2,%xmm0
+	pslld	$7,%xmm2
+	psrld	$25,%xmm0
+	pxor	%xmm1,%xmm7
+	por	%xmm0,%xmm2
+	pshufb	(%eax),%xmm7
+	movdqa	%xmm2,-32(%ebx)
+	paddd	%xmm7,%xmm5
+	pxor	%xmm5,%xmm3
+	movdqa	-48(%ebx),%xmm2
+	movdqa	%xmm3,%xmm0
+	pslld	$12,%xmm3
+	psrld	$20,%xmm0
+	por	%xmm0,%xmm3
+	movdqa	-128(%ebx),%xmm0
+	paddd	%xmm3,%xmm1
+	pxor	%xmm1,%xmm7
+	movdqa	%xmm1,-80(%ebx)
+	pshufb	16(%eax),%xmm7
+	paddd	%xmm7,%xmm5
+	movdqa	%xmm7,%xmm6
+	pxor	%xmm5,%xmm3
+	paddd	%xmm2,%xmm0
+	movdqa	%xmm3,%xmm1
+	pslld	$7,%xmm3
+	psrld	$25,%xmm1
+	pxor	%xmm0,%xmm6
+	por	%xmm1,%xmm3
+	pshufb	(%eax),%xmm6
+	movdqa	%xmm3,-16(%ebx)
+	paddd	%xmm6,%xmm4
+	pxor	%xmm4,%xmm2
+	movdqa	-32(%ebx),%xmm3
+	movdqa	%xmm2,%xmm1
+	pslld	$12,%xmm2
+	psrld	$20,%xmm1
+	por	%xmm1,%xmm2
+	movdqa	-112(%ebx),%xmm1
+	paddd	%xmm2,%xmm0
+	movdqa	64(%ebx),%xmm7
+	pxor	%xmm0,%xmm6
+	movdqa	%xmm0,-128(%ebx)
+	pshufb	16(%eax),%xmm6
+	paddd	%xmm6,%xmm4
+	movdqa	%xmm6,112(%ebx)
+	pxor	%xmm4,%xmm2
+	paddd	%xmm3,%xmm1
+	movdqa	%xmm2,%xmm0
+	pslld	$7,%xmm2
+	psrld	$25,%xmm0
+	pxor	%xmm1,%xmm7
+	por	%xmm0,%xmm2
+	movdqa	%xmm4,32(%ebx)
+	pshufb	(%eax),%xmm7
+	movdqa	%xmm2,-48(%ebx)
+	paddd	%xmm7,%xmm5
+	movdqa	(%ebx),%xmm4
+	pxor	%xmm5,%xmm3
+	movdqa	-16(%ebx),%xmm2
+	movdqa	%xmm3,%xmm0
+	pslld	$12,%xmm3
+	psrld	$20,%xmm0
+	por	%xmm0,%xmm3
+	movdqa	-96(%ebx),%xmm0
+	paddd	%xmm3,%xmm1
+	movdqa	80(%ebx),%xmm6
+	pxor	%xmm1,%xmm7
+	movdqa	%xmm1,-112(%ebx)
+	pshufb	16(%eax),%xmm7
+	paddd	%xmm7,%xmm5
+	movdqa	%xmm7,64(%ebx)
+	pxor	%xmm5,%xmm3
+	paddd	%xmm2,%xmm0
+	movdqa	%xmm3,%xmm1
+	pslld	$7,%xmm3
+	psrld	$25,%xmm1
+	pxor	%xmm0,%xmm6
+	por	%xmm1,%xmm3
+	movdqa	%xmm5,48(%ebx)
+	pshufb	(%eax),%xmm6
+	movdqa	%xmm3,-32(%ebx)
+	paddd	%xmm6,%xmm4
+	movdqa	16(%ebx),%xmm5
+	pxor	%xmm4,%xmm2
+	movdqa	-64(%ebx),%xmm3
+	movdqa	%xmm2,%xmm1
+	pslld	$12,%xmm2
+	psrld	$20,%xmm1
+	por	%xmm1,%xmm2
+	movdqa	-80(%ebx),%xmm1
+	paddd	%xmm2,%xmm0
+	movdqa	96(%ebx),%xmm7
+	pxor	%xmm0,%xmm6
+	movdqa	%xmm0,-96(%ebx)
+	pshufb	16(%eax),%xmm6
+	paddd	%xmm6,%xmm4
+	movdqa	%xmm6,80(%ebx)
+	pxor	%xmm4,%xmm2
+	paddd	%xmm3,%xmm1
+	movdqa	%xmm2,%xmm0
+	pslld	$7,%xmm2
+	psrld	$25,%xmm0
+	pxor	%xmm1,%xmm7
+	por	%xmm0,%xmm2
+	pshufb	(%eax),%xmm7
+	movdqa	%xmm2,-16(%ebx)
+	paddd	%xmm7,%xmm5
+	pxor	%xmm5,%xmm3
+	movdqa	%xmm3,%xmm0
+	pslld	$12,%xmm3
+	psrld	$20,%xmm0
+	por	%xmm0,%xmm3
+	movdqa	-128(%ebx),%xmm0
+	paddd	%xmm3,%xmm1
+	movdqa	64(%ebx),%xmm6
+	pxor	%xmm1,%xmm7
+	movdqa	%xmm1,-80(%ebx)
+	pshufb	16(%eax),%xmm7
+	paddd	%xmm7,%xmm5
+	movdqa	%xmm7,96(%ebx)
+	pxor	%xmm5,%xmm3
+	movdqa	%xmm3,%xmm1
+	pslld	$7,%xmm3
+	psrld	$25,%xmm1
+	por	%xmm1,%xmm3
+	decl	%edx
+	jnz	.L010loop
+	movdqa	%xmm3,-64(%ebx)
+	movdqa	%xmm4,(%ebx)
+	movdqa	%xmm5,16(%ebx)
+	movdqa	%xmm6,64(%ebx)
+	movdqa	%xmm7,96(%ebx)
+	movdqa	-112(%ebx),%xmm1
+	movdqa	-96(%ebx),%xmm2
+	movdqa	-80(%ebx),%xmm3
+	paddd	-128(%ebp),%xmm0
+	paddd	-112(%ebp),%xmm1
+	paddd	-96(%ebp),%xmm2
+	paddd	-80(%ebp),%xmm3
+	movdqa	%xmm0,%xmm6
+	punpckldq	%xmm1,%xmm0
+	movdqa	%xmm2,%xmm7
+	punpckldq	%xmm3,%xmm2
+	punpckhdq	%xmm1,%xmm6
+	punpckhdq	%xmm3,%xmm7
+	movdqa	%xmm0,%xmm1
+	punpcklqdq	%xmm2,%xmm0
+	movdqa	%xmm6,%xmm3
+	punpcklqdq	%xmm7,%xmm6
+	punpckhqdq	%xmm2,%xmm1
+	punpckhqdq	%xmm7,%xmm3
+	movdqu	-128(%esi),%xmm4
+	movdqu	-64(%esi),%xmm5
+	movdqu	(%esi),%xmm2
+	movdqu	64(%esi),%xmm7
+	leal	16(%esi),%esi
+	pxor	%xmm0,%xmm4
+	movdqa	-64(%ebx),%xmm0
+	pxor	%xmm1,%xmm5
+	movdqa	-48(%ebx),%xmm1
+	pxor	%xmm2,%xmm6
+	movdqa	-32(%ebx),%xmm2
+	pxor	%xmm3,%xmm7
+	movdqa	-16(%ebx),%xmm3
+	movdqu	%xmm4,-128(%edi)
+	movdqu	%xmm5,-64(%edi)
+	movdqu	%xmm6,(%edi)
+	movdqu	%xmm7,64(%edi)
+	leal	16(%edi),%edi
+	paddd	-64(%ebp),%xmm0
+	paddd	-48(%ebp),%xmm1
+	paddd	-32(%ebp),%xmm2
+	paddd	-16(%ebp),%xmm3
+	movdqa	%xmm0,%xmm6
+	punpckldq	%xmm1,%xmm0
+	movdqa	%xmm2,%xmm7
+	punpckldq	%xmm3,%xmm2
+	punpckhdq	%xmm1,%xmm6
+	punpckhdq	%xmm3,%xmm7
+	movdqa	%xmm0,%xmm1
+	punpcklqdq	%xmm2,%xmm0
+	movdqa	%xmm6,%xmm3
+	punpcklqdq	%xmm7,%xmm6
+	punpckhqdq	%xmm2,%xmm1
+	punpckhqdq	%xmm7,%xmm3
+	movdqu	-128(%esi),%xmm4
+	movdqu	-64(%esi),%xmm5
+	movdqu	(%esi),%xmm2
+	movdqu	64(%esi),%xmm7
+	leal	16(%esi),%esi
+	pxor	%xmm0,%xmm4
+	movdqa	(%ebx),%xmm0
+	pxor	%xmm1,%xmm5
+	movdqa	16(%ebx),%xmm1
+	pxor	%xmm2,%xmm6
+	movdqa	32(%ebx),%xmm2
+	pxor	%xmm3,%xmm7
+	movdqa	48(%ebx),%xmm3
+	movdqu	%xmm4,-128(%edi)
+	movdqu	%xmm5,-64(%edi)
+	movdqu	%xmm6,(%edi)
+	movdqu	%xmm7,64(%edi)
+	leal	16(%edi),%edi
+	paddd	(%ebp),%xmm0
+	paddd	16(%ebp),%xmm1
+	paddd	32(%ebp),%xmm2
+	paddd	48(%ebp),%xmm3
+	movdqa	%xmm0,%xmm6
+	punpckldq	%xmm1,%xmm0
+	movdqa	%xmm2,%xmm7
+	punpckldq	%xmm3,%xmm2
+	punpckhdq	%xmm1,%xmm6
+	punpckhdq	%xmm3,%xmm7
+	movdqa	%xmm0,%xmm1
+	punpcklqdq	%xmm2,%xmm0
+	movdqa	%xmm6,%xmm3
+	punpcklqdq	%xmm7,%xmm6
+	punpckhqdq	%xmm2,%xmm1
+	punpckhqdq	%xmm7,%xmm3
+	movdqu	-128(%esi),%xmm4
+	movdqu	-64(%esi),%xmm5
+	movdqu	(%esi),%xmm2
+	movdqu	64(%esi),%xmm7
+	leal	16(%esi),%esi
+	pxor	%xmm0,%xmm4
+	movdqa	64(%ebx),%xmm0
+	pxor	%xmm1,%xmm5
+	movdqa	80(%ebx),%xmm1
+	pxor	%xmm2,%xmm6
+	movdqa	96(%ebx),%xmm2
+	pxor	%xmm3,%xmm7
+	movdqa	112(%ebx),%xmm3
+	movdqu	%xmm4,-128(%edi)
+	movdqu	%xmm5,-64(%edi)
+	movdqu	%xmm6,(%edi)
+	movdqu	%xmm7,64(%edi)
+	leal	16(%edi),%edi
+	paddd	64(%ebp),%xmm0
+	paddd	80(%ebp),%xmm1
+	paddd	96(%ebp),%xmm2
+	paddd	112(%ebp),%xmm3
+	movdqa	%xmm0,%xmm6
+	punpckldq	%xmm1,%xmm0
+	movdqa	%xmm2,%xmm7
+	punpckldq	%xmm3,%xmm2
+	punpckhdq	%xmm1,%xmm6
+	punpckhdq	%xmm3,%xmm7
+	movdqa	%xmm0,%xmm1
+	punpcklqdq	%xmm2,%xmm0
+	movdqa	%xmm6,%xmm3
+	punpcklqdq	%xmm7,%xmm6
+	punpckhqdq	%xmm2,%xmm1
+	punpckhqdq	%xmm7,%xmm3
+	movdqu	-128(%esi),%xmm4
+	movdqu	-64(%esi),%xmm5
+	movdqu	(%esi),%xmm2
+	movdqu	64(%esi),%xmm7
+	leal	208(%esi),%esi
+	pxor	%xmm0,%xmm4
+	pxor	%xmm1,%xmm5
+	pxor	%xmm2,%xmm6
+	pxor	%xmm3,%xmm7
+	movdqu	%xmm4,-128(%edi)
+	movdqu	%xmm5,-64(%edi)
+	movdqu	%xmm6,(%edi)
+	movdqu	%xmm7,64(%edi)
+	leal	208(%edi),%edi
+	subl	$256,%ecx
+	jnc	.L009outer_loop
+	addl	$256,%ecx
+	jz	.L011done
+	movl	520(%esp),%ebx
+	leal	-128(%esi),%esi
+	movl	516(%esp),%edx
+	leal	-128(%edi),%edi
+	movd	64(%ebp),%xmm2
+	movdqu	(%ebx),%xmm3
+	paddd	96(%eax),%xmm2
+	pand	112(%eax),%xmm3
+	por	%xmm2,%xmm3
+.L0081x:
+	movdqa	32(%eax),%xmm0
+	movdqu	(%edx),%xmm1
+	movdqu	16(%edx),%xmm2
+	movdqa	(%eax),%xmm6
+	movdqa	16(%eax),%xmm7
+	movl	%ebp,48(%esp)
+	movdqa	%xmm0,(%esp)
+	movdqa	%xmm1,16(%esp)
+	movdqa	%xmm2,32(%esp)
+	movdqa	%xmm3,48(%esp)
+	movl	$10,%edx
+	jmp	.L012loop1x
+.align	16
+.L013outer1x:
+	movdqa	80(%eax),%xmm3
+	movdqa	(%esp),%xmm0
+	movdqa	16(%esp),%xmm1
+	movdqa	32(%esp),%xmm2
+	paddd	48(%esp),%xmm3
+	movl	$10,%edx
+	movdqa	%xmm3,48(%esp)
+	jmp	.L012loop1x
+.align	16
+.L012loop1x:
+	paddd	%xmm1,%xmm0
+	pxor	%xmm0,%xmm3
+.byte	102,15,56,0,222
+	paddd	%xmm3,%xmm2
+	pxor	%xmm2,%xmm1
+	movdqa	%xmm1,%xmm4
+	psrld	$20,%xmm1
+	pslld	$12,%xmm4
+	por	%xmm4,%xmm1
+	paddd	%xmm1,%xmm0
+	pxor	%xmm0,%xmm3
+.byte	102,15,56,0,223
+	paddd	%xmm3,%xmm2
+	pxor	%xmm2,%xmm1
+	movdqa	%xmm1,%xmm4
+	psrld	$25,%xmm1
+	pslld	$7,%xmm4
+	por	%xmm4,%xmm1
+	pshufd	$78,%xmm2,%xmm2
+	pshufd	$57,%xmm1,%xmm1
+	pshufd	$147,%xmm3,%xmm3
+	nop
+	paddd	%xmm1,%xmm0
+	pxor	%xmm0,%xmm3
+.byte	102,15,56,0,222
+	paddd	%xmm3,%xmm2
+	pxor	%xmm2,%xmm1
+	movdqa	%xmm1,%xmm4
+	psrld	$20,%xmm1
+	pslld	$12,%xmm4
+	por	%xmm4,%xmm1
+	paddd	%xmm1,%xmm0
+	pxor	%xmm0,%xmm3
+.byte	102,15,56,0,223
+	paddd	%xmm3,%xmm2
+	pxor	%xmm2,%xmm1
+	movdqa	%xmm1,%xmm4
+	psrld	$25,%xmm1
+	pslld	$7,%xmm4
+	por	%xmm4,%xmm1
+	pshufd	$78,%xmm2,%xmm2
+	pshufd	$147,%xmm1,%xmm1
+	pshufd	$57,%xmm3,%xmm3
+	decl	%edx
+	jnz	.L012loop1x
+	paddd	(%esp),%xmm0
+	paddd	16(%esp),%xmm1
+	paddd	32(%esp),%xmm2
+	paddd	48(%esp),%xmm3
+	cmpl	$64,%ecx
+	jb	.L014tail
+	movdqu	(%esi),%xmm4
+	movdqu	16(%esi),%xmm5
+	pxor	%xmm4,%xmm0
+	movdqu	32(%esi),%xmm4
+	pxor	%xmm5,%xmm1
+	movdqu	48(%esi),%xmm5
+	pxor	%xmm4,%xmm2
+	pxor	%xmm5,%xmm3
+	leal	64(%esi),%esi
+	movdqu	%xmm0,(%edi)
+	movdqu	%xmm1,16(%edi)
+	movdqu	%xmm2,32(%edi)
+	movdqu	%xmm3,48(%edi)
+	leal	64(%edi),%edi
+	subl	$64,%ecx
+	jnz	.L013outer1x
+	jmp	.L011done
+.L014tail:
+	movdqa	%xmm0,(%esp)
+	movdqa	%xmm1,16(%esp)
+	movdqa	%xmm2,32(%esp)
+	movdqa	%xmm3,48(%esp)
+	xorl	%eax,%eax
+	xorl	%edx,%edx
+	xorl	%ebp,%ebp
+.L015tail_loop:
+	movb	(%esp,%ebp,1),%al
+	movb	(%esi,%ebp,1),%dl
+	leal	1(%ebp),%ebp
+	xorb	%dl,%al
+	movb	%al,-1(%edi,%ebp,1)
+	decl	%ecx
+	jnz	.L015tail_loop
+.L011done:
+	movl	512(%esp),%esp
+	popl	%edi
+	popl	%esi
+	popl	%ebx
+	popl	%ebp
+	ret
+.size	ChaCha20_ssse3,.-.L_ChaCha20_ssse3_begin
+.align	64
+.Lssse3_data:
+.byte	2,3,0,1,6,7,4,5,10,11,8,9,14,15,12,13
+.byte	3,0,1,2,7,4,5,6,11,8,9,10,15,12,13,14
+.long	1634760805,857760878,2036477234,1797285236
+.long	0,1,2,3
+.long	4,4,4,4
+.long	1,0,0,0
+.long	4,0,0,0
+.long	0,-1,-1,-1
+.align	64
+.byte	67,104,97,67,104,97,50,48,32,102,111,114,32,120,56,54
+.byte	44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32
+.byte	60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111
+.byte	114,103,62,0
+#endif
diff --git a/linux-x86/crypto/modes/ghash-x86.S b/linux-x86/crypto/modes/ghash-x86.S
index 2872088..84ff2f4 100644
--- a/linux-x86/crypto/modes/ghash-x86.S
+++ b/linux-x86/crypto/modes/ghash-x86.S
@@ -1,211 +1,6 @@
 #if defined(__i386__)
 .file	"ghash-x86.S"
 .text
-.globl	gcm_gmult_4bit_x86
-.hidden	gcm_gmult_4bit_x86
-.type	gcm_gmult_4bit_x86,@function
-.align	16
-gcm_gmult_4bit_x86:
-.L_gcm_gmult_4bit_x86_begin:
-	pushl	%ebp
-	pushl	%ebx
-	pushl	%esi
-	pushl	%edi
-	subl	$84,%esp
-	movl	104(%esp),%edi
-	movl	108(%esp),%esi
-	movl	(%edi),%ebp
-	movl	4(%edi),%edx
-	movl	8(%edi),%ecx
-	movl	12(%edi),%ebx
-	movl	$0,16(%esp)
-	movl	$471859200,20(%esp)
-	movl	$943718400,24(%esp)
-	movl	$610271232,28(%esp)
-	movl	$1887436800,32(%esp)
-	movl	$1822425088,36(%esp)
-	movl	$1220542464,40(%esp)
-	movl	$1423966208,44(%esp)
-	movl	$3774873600,48(%esp)
-	movl	$4246732800,52(%esp)
-	movl	$3644850176,56(%esp)
-	movl	$3311403008,60(%esp)
-	movl	$2441084928,64(%esp)
-	movl	$2376073216,68(%esp)
-	movl	$2847932416,72(%esp)
-	movl	$3051356160,76(%esp)
-	movl	%ebp,(%esp)
-	movl	%edx,4(%esp)
-	movl	%ecx,8(%esp)
-	movl	%ebx,12(%esp)
-	shrl	$20,%ebx
-	andl	$240,%ebx
-	movl	4(%esi,%ebx,1),%ebp
-	movl	(%esi,%ebx,1),%edx
-	movl	12(%esi,%ebx,1),%ecx
-	movl	8(%esi,%ebx,1),%ebx
-	xorl	%eax,%eax
-	movl	$15,%edi
-	jmp	.L000x86_loop
-.align	16
-.L000x86_loop:
-	movb	%bl,%al
-	shrdl	$4,%ecx,%ebx
-	andb	$15,%al
-	shrdl	$4,%edx,%ecx
-	shrdl	$4,%ebp,%edx
-	shrl	$4,%ebp
-	xorl	16(%esp,%eax,4),%ebp
-	movb	(%esp,%edi,1),%al
-	andb	$240,%al
-	xorl	8(%esi,%eax,1),%ebx
-	xorl	12(%esi,%eax,1),%ecx
-	xorl	(%esi,%eax,1),%edx
-	xorl	4(%esi,%eax,1),%ebp
-	decl	%edi
-	js	.L001x86_break
-	movb	%bl,%al
-	shrdl	$4,%ecx,%ebx
-	andb	$15,%al
-	shrdl	$4,%edx,%ecx
-	shrdl	$4,%ebp,%edx
-	shrl	$4,%ebp
-	xorl	16(%esp,%eax,4),%ebp
-	movb	(%esp,%edi,1),%al
-	shlb	$4,%al
-	xorl	8(%esi,%eax,1),%ebx
-	xorl	12(%esi,%eax,1),%ecx
-	xorl	(%esi,%eax,1),%edx
-	xorl	4(%esi,%eax,1),%ebp
-	jmp	.L000x86_loop
-.align	16
-.L001x86_break:
-	bswap	%ebx
-	bswap	%ecx
-	bswap	%edx
-	bswap	%ebp
-	movl	104(%esp),%edi
-	movl	%ebx,12(%edi)
-	movl	%ecx,8(%edi)
-	movl	%edx,4(%edi)
-	movl	%ebp,(%edi)
-	addl	$84,%esp
-	popl	%edi
-	popl	%esi
-	popl	%ebx
-	popl	%ebp
-	ret
-.size	gcm_gmult_4bit_x86,.-.L_gcm_gmult_4bit_x86_begin
-.globl	gcm_ghash_4bit_x86
-.hidden	gcm_ghash_4bit_x86
-.type	gcm_ghash_4bit_x86,@function
-.align	16
-gcm_ghash_4bit_x86:
-.L_gcm_ghash_4bit_x86_begin:
-	pushl	%ebp
-	pushl	%ebx
-	pushl	%esi
-	pushl	%edi
-	subl	$84,%esp
-	movl	104(%esp),%ebx
-	movl	108(%esp),%esi
-	movl	112(%esp),%edi
-	movl	116(%esp),%ecx
-	addl	%edi,%ecx
-	movl	%ecx,116(%esp)
-	movl	(%ebx),%ebp
-	movl	4(%ebx),%edx
-	movl	8(%ebx),%ecx
-	movl	12(%ebx),%ebx
-	movl	$0,16(%esp)
-	movl	$471859200,20(%esp)
-	movl	$943718400,24(%esp)
-	movl	$610271232,28(%esp)
-	movl	$1887436800,32(%esp)
-	movl	$1822425088,36(%esp)
-	movl	$1220542464,40(%esp)
-	movl	$1423966208,44(%esp)
-	movl	$3774873600,48(%esp)
-	movl	$4246732800,52(%esp)
-	movl	$3644850176,56(%esp)
-	movl	$3311403008,60(%esp)
-	movl	$2441084928,64(%esp)
-	movl	$2376073216,68(%esp)
-	movl	$2847932416,72(%esp)
-	movl	$3051356160,76(%esp)
-.align	16
-.L002x86_outer_loop:
-	xorl	12(%edi),%ebx
-	xorl	8(%edi),%ecx
-	xorl	4(%edi),%edx
-	xorl	(%edi),%ebp
-	movl	%ebx,12(%esp)
-	movl	%ecx,8(%esp)
-	movl	%edx,4(%esp)
-	movl	%ebp,(%esp)
-	shrl	$20,%ebx
-	andl	$240,%ebx
-	movl	4(%esi,%ebx,1),%ebp
-	movl	(%esi,%ebx,1),%edx
-	movl	12(%esi,%ebx,1),%ecx
-	movl	8(%esi,%ebx,1),%ebx
-	xorl	%eax,%eax
-	movl	$15,%edi
-	jmp	.L003x86_loop
-.align	16
-.L003x86_loop:
-	movb	%bl,%al
-	shrdl	$4,%ecx,%ebx
-	andb	$15,%al
-	shrdl	$4,%edx,%ecx
-	shrdl	$4,%ebp,%edx
-	shrl	$4,%ebp
-	xorl	16(%esp,%eax,4),%ebp
-	movb	(%esp,%edi,1),%al
-	andb	$240,%al
-	xorl	8(%esi,%eax,1),%ebx
-	xorl	12(%esi,%eax,1),%ecx
-	xorl	(%esi,%eax,1),%edx
-	xorl	4(%esi,%eax,1),%ebp
-	decl	%edi
-	js	.L004x86_break
-	movb	%bl,%al
-	shrdl	$4,%ecx,%ebx
-	andb	$15,%al
-	shrdl	$4,%edx,%ecx
-	shrdl	$4,%ebp,%edx
-	shrl	$4,%ebp
-	xorl	16(%esp,%eax,4),%ebp
-	movb	(%esp,%edi,1),%al
-	shlb	$4,%al
-	xorl	8(%esi,%eax,1),%ebx
-	xorl	12(%esi,%eax,1),%ecx
-	xorl	(%esi,%eax,1),%edx
-	xorl	4(%esi,%eax,1),%ebp
-	jmp	.L003x86_loop
-.align	16
-.L004x86_break:
-	bswap	%ebx
-	bswap	%ecx
-	bswap	%edx
-	bswap	%ebp
-	movl	112(%esp),%edi
-	leal	16(%edi),%edi
-	cmpl	116(%esp),%edi
-	movl	%edi,112(%esp)
-	jb	.L002x86_outer_loop
-	movl	104(%esp),%edi
-	movl	%ebx,12(%edi)
-	movl	%ecx,8(%edi)
-	movl	%edx,4(%edi)
-	movl	%ebp,(%edi)
-	addl	$84,%esp
-	popl	%edi
-	popl	%esi
-	popl	%ebx
-	popl	%ebp
-	ret
-.size	gcm_ghash_4bit_x86,.-.L_gcm_ghash_4bit_x86_begin
 .globl	gcm_gmult_4bit_mmx
 .hidden	gcm_gmult_4bit_mmx
 .type	gcm_gmult_4bit_mmx,@function
@@ -218,10 +13,10 @@
 	pushl	%edi
 	movl	20(%esp),%edi
 	movl	24(%esp),%esi
-	call	.L005pic_point
-.L005pic_point:
+	call	.L000pic_point
+.L000pic_point:
 	popl	%eax
-	leal	.Lrem_4bit-.L005pic_point(%eax),%eax
+	leal	.Lrem_4bit-.L000pic_point(%eax),%eax
 	movzbl	15(%edi),%ebx
 	xorl	%ecx,%ecx
 	movl	%ebx,%edx
@@ -232,9 +27,9 @@
 	movq	8(%esi,%ecx,1),%mm0
 	movq	(%esi,%ecx,1),%mm1
 	movd	%mm0,%ebx
-	jmp	.L006mmx_loop
+	jmp	.L001mmx_loop
 .align	16
-.L006mmx_loop:
+.L001mmx_loop:
 	psrlq	$4,%mm0
 	andl	$15,%ebx
 	movq	%mm1,%mm2
@@ -248,7 +43,7 @@
 	pxor	(%esi,%edx,1),%mm1
 	movl	%ecx,%edx
 	pxor	%mm2,%mm0
-	js	.L007mmx_break
+	js	.L002mmx_break
 	shlb	$4,%cl
 	andl	$15,%ebx
 	psrlq	$4,%mm0
@@ -261,9 +56,9 @@
 	movd	%mm0,%ebx
 	pxor	(%esi,%ecx,1),%mm1
 	pxor	%mm2,%mm0
-	jmp	.L006mmx_loop
+	jmp	.L001mmx_loop
 .align	16
-.L007mmx_break:
+.L002mmx_break:
 	shlb	$4,%cl
 	andl	$15,%ebx
 	psrlq	$4,%mm0
@@ -321,10 +116,10 @@
 	movl	28(%esp),%ecx
 	movl	32(%esp),%edx
 	movl	%esp,%ebp
-	call	.L008pic_point
-.L008pic_point:
+	call	.L003pic_point
+.L003pic_point:
 	popl	%esi
-	leal	.Lrem_8bit-.L008pic_point(%esi),%esi
+	leal	.Lrem_8bit-.L003pic_point(%esi),%esi
 	subl	$544,%esp
 	andl	$-64,%esp
 	subl	$16,%esp
@@ -563,7 +358,7 @@
 	movl	8(%eax),%ebx
 	movl	12(%eax),%edx
 .align	16
-.L009outer:
+.L004outer:
 	xorl	12(%ecx),%edx
 	xorl	8(%ecx),%ebx
 	pxor	(%ecx),%mm6
@@ -898,7 +693,7 @@
 	pshufw	$27,%mm6,%mm6
 	bswap	%ebx
 	cmpl	552(%esp),%ecx
-	jne	.L009outer
+	jne	.L004outer
 	movl	544(%esp),%eax
 	movl	%edx,12(%eax)
 	movl	%ebx,8(%eax)
@@ -919,10 +714,10 @@
 .L_gcm_init_clmul_begin:
 	movl	4(%esp),%edx
 	movl	8(%esp),%eax
-	call	.L010pic
-.L010pic:
+	call	.L005pic
+.L005pic:
 	popl	%ecx
-	leal	.Lbswap-.L010pic(%ecx),%ecx
+	leal	.Lbswap-.L005pic(%ecx),%ecx
 	movdqu	(%eax),%xmm2
 	pshufd	$78,%xmm2,%xmm2
 	pshufd	$255,%xmm2,%xmm4
@@ -989,10 +784,10 @@
 .L_gcm_gmult_clmul_begin:
 	movl	4(%esp),%eax
 	movl	8(%esp),%edx
-	call	.L011pic
-.L011pic:
+	call	.L006pic
+.L006pic:
 	popl	%ecx
-	leal	.Lbswap-.L011pic(%ecx),%ecx
+	leal	.Lbswap-.L006pic(%ecx),%ecx
 	movdqu	(%eax),%xmm0
 	movdqa	(%ecx),%xmm5
 	movups	(%edx),%xmm2
@@ -1049,16 +844,16 @@
 	movl	24(%esp),%edx
 	movl	28(%esp),%esi
 	movl	32(%esp),%ebx
-	call	.L012pic
-.L012pic:
+	call	.L007pic
+.L007pic:
 	popl	%ecx
-	leal	.Lbswap-.L012pic(%ecx),%ecx
+	leal	.Lbswap-.L007pic(%ecx),%ecx
 	movdqu	(%eax),%xmm0
 	movdqa	(%ecx),%xmm5
 	movdqu	(%edx),%xmm2
 .byte	102,15,56,0,197
 	subl	$16,%ebx
-	jz	.L013odd_tail
+	jz	.L008odd_tail
 	movdqu	(%esi),%xmm3
 	movdqu	16(%esi),%xmm6
 .byte	102,15,56,0,221
@@ -1075,10 +870,10 @@
 	movups	16(%edx),%xmm2
 	nop
 	subl	$32,%ebx
-	jbe	.L014even_tail
-	jmp	.L015mod_loop
+	jbe	.L009even_tail
+	jmp	.L010mod_loop
 .align	32
-.L015mod_loop:
+.L010mod_loop:
 	pshufd	$78,%xmm0,%xmm4
 	movdqa	%xmm0,%xmm1
 	pxor	%xmm0,%xmm4
@@ -1133,8 +928,8 @@
 .byte	102,15,58,68,221,0
 	leal	32(%esi),%esi
 	subl	$32,%ebx
-	ja	.L015mod_loop
-.L014even_tail:
+	ja	.L010mod_loop
+.L009even_tail:
 	pshufd	$78,%xmm0,%xmm4
 	movdqa	%xmm0,%xmm1
 	pxor	%xmm0,%xmm4
@@ -1173,9 +968,9 @@
 	psrlq	$1,%xmm0
 	pxor	%xmm1,%xmm0
 	testl	%ebx,%ebx
-	jnz	.L016done
+	jnz	.L011done
 	movups	(%edx),%xmm2
-.L013odd_tail:
+.L008odd_tail:
 	movdqu	(%esi),%xmm3
 .byte	102,15,56,0,221
 	pxor	%xmm3,%xmm0
@@ -1214,7 +1009,7 @@
 	pxor	%xmm4,%xmm0
 	psrlq	$1,%xmm0
 	pxor	%xmm1,%xmm0
-.L016done:
+.L011done:
 .byte	102,15,56,0,197
 	movdqu	%xmm0,(%eax)
 	popl	%edi
diff --git a/linux-x86/crypto/rc4/rc4-586.S b/linux-x86/crypto/rc4/rc4-586.S
deleted file mode 100644
index a5cce47..0000000
--- a/linux-x86/crypto/rc4/rc4-586.S
+++ /dev/null
@@ -1,385 +0,0 @@
-#if defined(__i386__)
-.file	"rc4-586.S"
-.text
-.globl	asm_RC4
-.hidden	asm_RC4
-.type	asm_RC4,@function
-.align	16
-asm_RC4:
-.L_asm_RC4_begin:
-	pushl	%ebp
-	pushl	%ebx
-	pushl	%esi
-	pushl	%edi
-	movl	20(%esp),%edi
-	movl	24(%esp),%edx
-	movl	28(%esp),%esi
-	movl	32(%esp),%ebp
-	xorl	%eax,%eax
-	xorl	%ebx,%ebx
-	cmpl	$0,%edx
-	je	.L000abort
-	movb	(%edi),%al
-	movb	4(%edi),%bl
-	addl	$8,%edi
-	leal	(%esi,%edx,1),%ecx
-	subl	%esi,%ebp
-	movl	%ecx,24(%esp)
-	incb	%al
-	cmpl	$-1,256(%edi)
-	je	.L001RC4_CHAR
-	movl	(%edi,%eax,4),%ecx
-	andl	$-4,%edx
-	jz	.L002loop1
-	movl	%ebp,32(%esp)
-	testl	$-8,%edx
-	jz	.L003go4loop4
-	call	.L004PIC_me_up
-.L004PIC_me_up:
-	popl	%ebp
-	leal	OPENSSL_ia32cap_P-.L004PIC_me_up(%ebp),%ebp
-	btl	$26,(%ebp)
-	jnc	.L003go4loop4
-	movl	32(%esp),%ebp
-	andl	$-8,%edx
-	leal	-8(%esi,%edx,1),%edx
-	movl	%edx,-4(%edi)
-	addb	%cl,%bl
-	movl	(%edi,%ebx,4),%edx
-	movl	%ecx,(%edi,%ebx,4)
-	movl	%edx,(%edi,%eax,4)
-	incl	%eax
-	addl	%ecx,%edx
-	movzbl	%al,%eax
-	movzbl	%dl,%edx
-	movq	(%esi),%mm0
-	movl	(%edi,%eax,4),%ecx
-	movd	(%edi,%edx,4),%mm2
-	jmp	.L005loop_mmx_enter
-.align	16
-.L006loop_mmx:
-	addb	%cl,%bl
-	psllq	$56,%mm1
-	movl	(%edi,%ebx,4),%edx
-	movl	%ecx,(%edi,%ebx,4)
-	movl	%edx,(%edi,%eax,4)
-	incl	%eax
-	addl	%ecx,%edx
-	movzbl	%al,%eax
-	movzbl	%dl,%edx
-	pxor	%mm1,%mm2
-	movq	(%esi),%mm0
-	movq	%mm2,-8(%ebp,%esi,1)
-	movl	(%edi,%eax,4),%ecx
-	movd	(%edi,%edx,4),%mm2
-.L005loop_mmx_enter:
-	addb	%cl,%bl
-	movl	(%edi,%ebx,4),%edx
-	movl	%ecx,(%edi,%ebx,4)
-	movl	%edx,(%edi,%eax,4)
-	incl	%eax
-	addl	%ecx,%edx
-	movzbl	%al,%eax
-	movzbl	%dl,%edx
-	pxor	%mm0,%mm2
-	movl	(%edi,%eax,4),%ecx
-	movd	(%edi,%edx,4),%mm1
-	addb	%cl,%bl
-	psllq	$8,%mm1
-	movl	(%edi,%ebx,4),%edx
-	movl	%ecx,(%edi,%ebx,4)
-	movl	%edx,(%edi,%eax,4)
-	incl	%eax
-	addl	%ecx,%edx
-	movzbl	%al,%eax
-	movzbl	%dl,%edx
-	pxor	%mm1,%mm2
-	movl	(%edi,%eax,4),%ecx
-	movd	(%edi,%edx,4),%mm1
-	addb	%cl,%bl
-	psllq	$16,%mm1
-	movl	(%edi,%ebx,4),%edx
-	movl	%ecx,(%edi,%ebx,4)
-	movl	%edx,(%edi,%eax,4)
-	incl	%eax
-	addl	%ecx,%edx
-	movzbl	%al,%eax
-	movzbl	%dl,%edx
-	pxor	%mm1,%mm2
-	movl	(%edi,%eax,4),%ecx
-	movd	(%edi,%edx,4),%mm1
-	addb	%cl,%bl
-	psllq	$24,%mm1
-	movl	(%edi,%ebx,4),%edx
-	movl	%ecx,(%edi,%ebx,4)
-	movl	%edx,(%edi,%eax,4)
-	incl	%eax
-	addl	%ecx,%edx
-	movzbl	%al,%eax
-	movzbl	%dl,%edx
-	pxor	%mm1,%mm2
-	movl	(%edi,%eax,4),%ecx
-	movd	(%edi,%edx,4),%mm1
-	addb	%cl,%bl
-	psllq	$32,%mm1
-	movl	(%edi,%ebx,4),%edx
-	movl	%ecx,(%edi,%ebx,4)
-	movl	%edx,(%edi,%eax,4)
-	incl	%eax
-	addl	%ecx,%edx
-	movzbl	%al,%eax
-	movzbl	%dl,%edx
-	pxor	%mm1,%mm2
-	movl	(%edi,%eax,4),%ecx
-	movd	(%edi,%edx,4),%mm1
-	addb	%cl,%bl
-	psllq	$40,%mm1
-	movl	(%edi,%ebx,4),%edx
-	movl	%ecx,(%edi,%ebx,4)
-	movl	%edx,(%edi,%eax,4)
-	incl	%eax
-	addl	%ecx,%edx
-	movzbl	%al,%eax
-	movzbl	%dl,%edx
-	pxor	%mm1,%mm2
-	movl	(%edi,%eax,4),%ecx
-	movd	(%edi,%edx,4),%mm1
-	addb	%cl,%bl
-	psllq	$48,%mm1
-	movl	(%edi,%ebx,4),%edx
-	movl	%ecx,(%edi,%ebx,4)
-	movl	%edx,(%edi,%eax,4)
-	incl	%eax
-	addl	%ecx,%edx
-	movzbl	%al,%eax
-	movzbl	%dl,%edx
-	pxor	%mm1,%mm2
-	movl	(%edi,%eax,4),%ecx
-	movd	(%edi,%edx,4),%mm1
-	movl	%ebx,%edx
-	xorl	%ebx,%ebx
-	movb	%dl,%bl
-	cmpl	-4(%edi),%esi
-	leal	8(%esi),%esi
-	jb	.L006loop_mmx
-	psllq	$56,%mm1
-	pxor	%mm1,%mm2
-	movq	%mm2,-8(%ebp,%esi,1)
-	emms
-	cmpl	24(%esp),%esi
-	je	.L007done
-	jmp	.L002loop1
-.align	16
-.L003go4loop4:
-	leal	-4(%esi,%edx,1),%edx
-	movl	%edx,28(%esp)
-.L008loop4:
-	addb	%cl,%bl
-	movl	(%edi,%ebx,4),%edx
-	movl	%ecx,(%edi,%ebx,4)
-	movl	%edx,(%edi,%eax,4)
-	addl	%ecx,%edx
-	incb	%al
-	andl	$255,%edx
-	movl	(%edi,%eax,4),%ecx
-	movl	(%edi,%edx,4),%ebp
-	addb	%cl,%bl
-	movl	(%edi,%ebx,4),%edx
-	movl	%ecx,(%edi,%ebx,4)
-	movl	%edx,(%edi,%eax,4)
-	addl	%ecx,%edx
-	incb	%al
-	andl	$255,%edx
-	rorl	$8,%ebp
-	movl	(%edi,%eax,4),%ecx
-	orl	(%edi,%edx,4),%ebp
-	addb	%cl,%bl
-	movl	(%edi,%ebx,4),%edx
-	movl	%ecx,(%edi,%ebx,4)
-	movl	%edx,(%edi,%eax,4)
-	addl	%ecx,%edx
-	incb	%al
-	andl	$255,%edx
-	rorl	$8,%ebp
-	movl	(%edi,%eax,4),%ecx
-	orl	(%edi,%edx,4),%ebp
-	addb	%cl,%bl
-	movl	(%edi,%ebx,4),%edx
-	movl	%ecx,(%edi,%ebx,4)
-	movl	%edx,(%edi,%eax,4)
-	addl	%ecx,%edx
-	incb	%al
-	andl	$255,%edx
-	rorl	$8,%ebp
-	movl	32(%esp),%ecx
-	orl	(%edi,%edx,4),%ebp
-	rorl	$8,%ebp
-	xorl	(%esi),%ebp
-	cmpl	28(%esp),%esi
-	movl	%ebp,(%ecx,%esi,1)
-	leal	4(%esi),%esi
-	movl	(%edi,%eax,4),%ecx
-	jb	.L008loop4
-	cmpl	24(%esp),%esi
-	je	.L007done
-	movl	32(%esp),%ebp
-.align	16
-.L002loop1:
-	addb	%cl,%bl
-	movl	(%edi,%ebx,4),%edx
-	movl	%ecx,(%edi,%ebx,4)
-	movl	%edx,(%edi,%eax,4)
-	addl	%ecx,%edx
-	incb	%al
-	andl	$255,%edx
-	movl	(%edi,%edx,4),%edx
-	xorb	(%esi),%dl
-	leal	1(%esi),%esi
-	movl	(%edi,%eax,4),%ecx
-	cmpl	24(%esp),%esi
-	movb	%dl,-1(%ebp,%esi,1)
-	jb	.L002loop1
-	jmp	.L007done
-.align	16
-.L001RC4_CHAR:
-	movzbl	(%edi,%eax,1),%ecx
-.L009cloop1:
-	addb	%cl,%bl
-	movzbl	(%edi,%ebx,1),%edx
-	movb	%cl,(%edi,%ebx,1)
-	movb	%dl,(%edi,%eax,1)
-	addb	%cl,%dl
-	movzbl	(%edi,%edx,1),%edx
-	addb	$1,%al
-	xorb	(%esi),%dl
-	leal	1(%esi),%esi
-	movzbl	(%edi,%eax,1),%ecx
-	cmpl	24(%esp),%esi
-	movb	%dl,-1(%ebp,%esi,1)
-	jb	.L009cloop1
-.L007done:
-	decb	%al
-	movl	%ebx,-4(%edi)
-	movb	%al,-8(%edi)
-.L000abort:
-	popl	%edi
-	popl	%esi
-	popl	%ebx
-	popl	%ebp
-	ret
-.size	asm_RC4,.-.L_asm_RC4_begin
-.globl	asm_RC4_set_key
-.hidden	asm_RC4_set_key
-.type	asm_RC4_set_key,@function
-.align	16
-asm_RC4_set_key:
-.L_asm_RC4_set_key_begin:
-	pushl	%ebp
-	pushl	%ebx
-	pushl	%esi
-	pushl	%edi
-	movl	20(%esp),%edi
-	movl	24(%esp),%ebp
-	movl	28(%esp),%esi
-	call	.L010PIC_me_up
-.L010PIC_me_up:
-	popl	%edx
-	leal	OPENSSL_ia32cap_P-.L010PIC_me_up(%edx),%edx
-	leal	8(%edi),%edi
-	leal	(%esi,%ebp,1),%esi
-	negl	%ebp
-	xorl	%eax,%eax
-	movl	%ebp,-4(%edi)
-	btl	$20,(%edx)
-	jc	.L011c1stloop
-.align	16
-.L012w1stloop:
-	movl	%eax,(%edi,%eax,4)
-	addb	$1,%al
-	jnc	.L012w1stloop
-	xorl	%ecx,%ecx
-	xorl	%edx,%edx
-.align	16
-.L013w2ndloop:
-	movl	(%edi,%ecx,4),%eax
-	addb	(%esi,%ebp,1),%dl
-	addb	%al,%dl
-	addl	$1,%ebp
-	movl	(%edi,%edx,4),%ebx
-	jnz	.L014wnowrap
-	movl	-4(%edi),%ebp
-.L014wnowrap:
-	movl	%eax,(%edi,%edx,4)
-	movl	%ebx,(%edi,%ecx,4)
-	addb	$1,%cl
-	jnc	.L013w2ndloop
-	jmp	.L015exit
-.align	16
-.L011c1stloop:
-	movb	%al,(%edi,%eax,1)
-	addb	$1,%al
-	jnc	.L011c1stloop
-	xorl	%ecx,%ecx
-	xorl	%edx,%edx
-	xorl	%ebx,%ebx
-.align	16
-.L016c2ndloop:
-	movb	(%edi,%ecx,1),%al
-	addb	(%esi,%ebp,1),%dl
-	addb	%al,%dl
-	addl	$1,%ebp
-	movb	(%edi,%edx,1),%bl
-	jnz	.L017cnowrap
-	movl	-4(%edi),%ebp
-.L017cnowrap:
-	movb	%al,(%edi,%edx,1)
-	movb	%bl,(%edi,%ecx,1)
-	addb	$1,%cl
-	jnc	.L016c2ndloop
-	movl	$-1,256(%edi)
-.L015exit:
-	xorl	%eax,%eax
-	movl	%eax,-8(%edi)
-	movl	%eax,-4(%edi)
-	popl	%edi
-	popl	%esi
-	popl	%ebx
-	popl	%ebp
-	ret
-.size	asm_RC4_set_key,.-.L_asm_RC4_set_key_begin
-.globl	RC4_options
-.hidden	RC4_options
-.type	RC4_options,@function
-.align	16
-RC4_options:
-.L_RC4_options_begin:
-	call	.L018pic_point
-.L018pic_point:
-	popl	%eax
-	leal	.L019opts-.L018pic_point(%eax),%eax
-	call	.L020PIC_me_up
-.L020PIC_me_up:
-	popl	%edx
-	leal	OPENSSL_ia32cap_P-.L020PIC_me_up(%edx),%edx
-	movl	(%edx),%edx
-	btl	$20,%edx
-	jc	.L0211xchar
-	btl	$26,%edx
-	jnc	.L022ret
-	addl	$25,%eax
-	ret
-.L0211xchar:
-	addl	$12,%eax
-.L022ret:
-	ret
-.align	64
-.L019opts:
-.byte	114,99,52,40,52,120,44,105,110,116,41,0
-.byte	114,99,52,40,49,120,44,99,104,97,114,41,0
-.byte	114,99,52,40,56,120,44,109,109,120,41,0
-.byte	82,67,52,32,102,111,114,32,120,56,54,44,32,67,82,89
-.byte	80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114
-.byte	111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
-.align	64
-.size	RC4_options,.-.L_RC4_options_begin
-#endif
diff --git a/linux-x86_64/crypto/aes/aes-x86_64.S b/linux-x86_64/crypto/aes/aes-x86_64.S
index 5f4b057..ab1168e 100644
--- a/linux-x86_64/crypto/aes/aes-x86_64.S
+++ b/linux-x86_64/crypto/aes/aes-x86_64.S
@@ -82,8 +82,8 @@
 	movl	0(%r14,%rdi,8),%edi
 	movl	0(%r14,%rbp,8),%ebp
 
-	andl	$65280,%edi
-	andl	$65280,%ebp
+	andl	$0x0000ff00,%edi
+	andl	$0x0000ff00,%ebp
 
 	xorl	%edi,%r10d
 	xorl	%ebp,%r11d
@@ -95,8 +95,8 @@
 	movl	0(%r14,%rsi,8),%esi
 	movl	0(%r14,%rdi,8),%edi
 
-	andl	$65280,%esi
-	andl	$65280,%edi
+	andl	$0x0000ff00,%esi
+	andl	$0x0000ff00,%edi
 	shrl	$16,%ebx
 	xorl	%esi,%r12d
 	xorl	%edi,%r8d
@@ -109,9 +109,9 @@
 	movl	0(%r14,%rdi,8),%edi
 	movl	0(%r14,%rbp,8),%ebp
 
-	andl	$16711680,%esi
-	andl	$16711680,%edi
-	andl	$16711680,%ebp
+	andl	$0x00ff0000,%esi
+	andl	$0x00ff0000,%edi
+	andl	$0x00ff0000,%ebp
 
 	xorl	%esi,%r10d
 	xorl	%edi,%r11d
@@ -124,9 +124,9 @@
 	movl	2(%r14,%rdi,8),%edi
 	movl	2(%r14,%rbp,8),%ebp
 
-	andl	$16711680,%esi
-	andl	$4278190080,%edi
-	andl	$4278190080,%ebp
+	andl	$0x00ff0000,%esi
+	andl	$0xff000000,%edi
+	andl	$0xff000000,%ebp
 
 	xorl	%esi,%r8d
 	xorl	%edi,%r10d
@@ -139,8 +139,8 @@
 	movl	2(%r14,%rdi,8),%edi
 	movl	16+0(%r15),%eax
 
-	andl	$4278190080,%esi
-	andl	$4278190080,%edi
+	andl	$0xff000000,%esi
+	andl	$0xff000000,%edi
 
 	xorl	%esi,%r12d
 	xorl	%edi,%r8d
@@ -242,8 +242,8 @@
 	xorl	%r8d,%edx
 	cmpq	16(%rsp),%r15
 	je	.Lenc_compact_done
-	movl	$2155905152,%r10d
-	movl	$2155905152,%r11d
+	movl	$0x80808080,%r10d
+	movl	$0x80808080,%r11d
 	andl	%eax,%r10d
 	andl	%ebx,%r11d
 	movl	%r10d,%esi
@@ -254,10 +254,10 @@
 	leal	(%rbx,%rbx,1),%r9d
 	subl	%r10d,%esi
 	subl	%r11d,%edi
-	andl	$4278124286,%r8d
-	andl	$4278124286,%r9d
-	andl	$454761243,%esi
-	andl	$454761243,%edi
+	andl	$0xfefefefe,%r8d
+	andl	$0xfefefefe,%r9d
+	andl	$0x1b1b1b1b,%esi
+	andl	$0x1b1b1b1b,%edi
 	movl	%eax,%r10d
 	movl	%ebx,%r11d
 	xorl	%esi,%r8d
@@ -265,9 +265,9 @@
 
 	xorl	%r8d,%eax
 	xorl	%r9d,%ebx
-	movl	$2155905152,%r12d
+	movl	$0x80808080,%r12d
 	roll	$24,%eax
-	movl	$2155905152,%ebp
+	movl	$0x80808080,%ebp
 	roll	$24,%ebx
 	andl	%ecx,%r12d
 	andl	%edx,%ebp
@@ -290,10 +290,10 @@
 	xorl	%r10d,%eax
 	xorl	%r11d,%ebx
 
-	andl	$4278124286,%r8d
-	andl	$4278124286,%r9d
-	andl	$454761243,%esi
-	andl	$454761243,%edi
+	andl	$0xfefefefe,%r8d
+	andl	$0xfefefefe,%r9d
+	andl	$0x1b1b1b1b,%esi
+	andl	$0x1b1b1b1b,%edi
 	movl	%ecx,%r12d
 	movl	%edx,%ebp
 	xorl	%esi,%r8d
@@ -332,6 +332,7 @@
 .type	asm_AES_encrypt,@function
 .hidden	asm_AES_encrypt
 asm_AES_encrypt:
+	movq	%rsp,%rax
 	pushq	%rbx
 	pushq	%rbp
 	pushq	%r12
@@ -340,17 +341,16 @@
 	pushq	%r15
 
 
-	movq	%rsp,%r10
 	leaq	-63(%rdx),%rcx
 	andq	$-64,%rsp
 	subq	%rsp,%rcx
 	negq	%rcx
-	andq	$960,%rcx
+	andq	$0x3c0,%rcx
 	subq	%rcx,%rsp
 	subq	$32,%rsp
 
 	movq	%rsi,16(%rsp)
-	movq	%r10,24(%rsp)
+	movq	%rax,24(%rsp)
 .Lenc_prologue:
 
 	movq	%rdx,%r15
@@ -370,7 +370,7 @@
 	leaq	.LAES_Te+2048(%rip),%r14
 	leaq	768(%rsp),%rbp
 	subq	%r14,%rbp
-	andq	$768,%rbp
+	andq	$0x300,%rbp
 	leaq	(%r14,%rbp,1),%r14
 
 	call	_x86_64_AES_encrypt_compact
@@ -382,13 +382,13 @@
 	movl	%ecx,8(%r9)
 	movl	%edx,12(%r9)
 
-	movq	(%rsi),%r15
-	movq	8(%rsi),%r14
-	movq	16(%rsi),%r13
-	movq	24(%rsi),%r12
-	movq	32(%rsi),%rbp
-	movq	40(%rsi),%rbx
-	leaq	48(%rsi),%rsp
+	movq	-48(%rsi),%r15
+	movq	-40(%rsi),%r14
+	movq	-32(%rsi),%r13
+	movq	-24(%rsi),%r12
+	movq	-16(%rsi),%rbp
+	movq	-8(%rsi),%rbx
+	leaq	(%rsi),%rsp
 .Lenc_epilogue:
 	.byte	0xf3,0xc3
 .size	asm_AES_encrypt,.-asm_AES_encrypt
@@ -778,6 +778,7 @@
 .type	asm_AES_decrypt,@function
 .hidden	asm_AES_decrypt
 asm_AES_decrypt:
+	movq	%rsp,%rax
 	pushq	%rbx
 	pushq	%rbp
 	pushq	%r12
@@ -786,17 +787,16 @@
 	pushq	%r15
 
 
-	movq	%rsp,%r10
 	leaq	-63(%rdx),%rcx
 	andq	$-64,%rsp
 	subq	%rsp,%rcx
 	negq	%rcx
-	andq	$960,%rcx
+	andq	$0x3c0,%rcx
 	subq	%rcx,%rsp
 	subq	$32,%rsp
 
 	movq	%rsi,16(%rsp)
-	movq	%r10,24(%rsp)
+	movq	%rax,24(%rsp)
 .Ldec_prologue:
 
 	movq	%rdx,%r15
@@ -816,7 +816,7 @@
 	leaq	.LAES_Td+2048(%rip),%r14
 	leaq	768(%rsp),%rbp
 	subq	%r14,%rbp
-	andq	$768,%rbp
+	andq	$0x300,%rbp
 	leaq	(%r14,%rbp,1),%r14
 	shrq	$3,%rbp
 	addq	%rbp,%r14
@@ -830,13 +830,13 @@
 	movl	%ecx,8(%r9)
 	movl	%edx,12(%r9)
 
-	movq	(%rsi),%r15
-	movq	8(%rsi),%r14
-	movq	16(%rsi),%r13
-	movq	24(%rsi),%r12
-	movq	32(%rsi),%rbp
-	movq	40(%rsi),%rbx
-	leaq	48(%rsi),%rsp
+	movq	-48(%rsi),%r15
+	movq	-40(%rsi),%r14
+	movq	-32(%rsi),%r13
+	movq	-24(%rsi),%r12
+	movq	-16(%rsi),%rbp
+	movq	-8(%rsi),%rbx
+	leaq	(%rsi),%rsp
 .Ldec_epilogue:
 	.byte	0xf3,0xc3
 .size	asm_AES_decrypt,.-asm_AES_decrypt
@@ -1313,10 +1313,9 @@
 	movl	%r9d,%r9d
 
 	leaq	.LAES_Te(%rip),%r14
+	leaq	.LAES_Td(%rip),%r10
 	cmpq	$0,%r9
-	jne	.Lcbc_picked_te
-	leaq	.LAES_Td(%rip),%r14
-.Lcbc_picked_te:
+	cmoveq	%r10,%r14
 
 	movl	OPENSSL_ia32cap_P(%rip),%r10d
 	cmpq	$512,%rdx
@@ -1334,9 +1333,9 @@
 	movq	%r14,%r10
 	leaq	2304(%r14),%r11
 	movq	%r15,%r12
-	andq	$4095,%r10
-	andq	$4095,%r11
-	andq	$4095,%r12
+	andq	$0xFFF,%r10
+	andq	$0xFFF,%r11
+	andq	$0xFFF,%r12
 
 	cmpq	%r11,%r12
 	jb	.Lcbc_te_break_out
@@ -1345,7 +1344,7 @@
 	jmp	.Lcbc_te_ok
 .Lcbc_te_break_out:
 	subq	%r10,%r12
-	andq	$4095,%r12
+	andq	$0xFFF,%r12
 	addq	$320,%r12
 	subq	%r12,%r15
 .align	4
@@ -1371,7 +1370,7 @@
 
 	movq	%r15,%r10
 	subq	%r14,%r10
-	andq	$4095,%r10
+	andq	$0xfff,%r10
 	cmpq	$2304,%r10
 	jb	.Lcbc_do_ecopy
 	cmpq	$4096-248,%r10
@@ -1558,7 +1557,7 @@
 	leaq	-88-63(%rcx),%r10
 	subq	%rbp,%r10
 	negq	%r10
-	andq	$960,%r10
+	andq	$0x3c0,%r10
 	subq	%r10,%rbp
 
 	xchgq	%rsp,%rbp
@@ -1587,7 +1586,7 @@
 	leaq	2048(%r14),%r14
 	leaq	768-8(%rsp),%rax
 	subq	%r14,%rax
-	andq	$768,%rax
+	andq	$0x300,%rax
 	leaq	(%r14,%rax,1),%r14
 
 	cmpq	$0,%rbx
diff --git a/linux-x86_64/crypto/aes/aesni-x86_64.S b/linux-x86_64/crypto/aes/aesni-x86_64.S
index 1d51d5b..a90e935 100644
--- a/linux-x86_64/crypto/aes/aesni-x86_64.S
+++ b/linux-x86_64/crypto/aes/aesni-x86_64.S
@@ -508,7 +508,7 @@
 	testl	%r8d,%r8d
 	jz	.Lecb_decrypt
 
-	cmpq	$128,%rdx
+	cmpq	$0x80,%rdx
 	jb	.Lecb_enc_tail
 
 	movdqu	(%rdi),%xmm2
@@ -520,7 +520,7 @@
 	movdqu	96(%rdi),%xmm8
 	movdqu	112(%rdi),%xmm9
 	leaq	128(%rdi),%rdi
-	subq	$128,%rdx
+	subq	$0x80,%rdx
 	jmp	.Lecb_enc_loop8_enter
 .align	16
 .Lecb_enc_loop8:
@@ -548,7 +548,7 @@
 
 	call	_aesni_encrypt8
 
-	subq	$128,%rdx
+	subq	$0x80,%rdx
 	jnc	.Lecb_enc_loop8
 
 	movups	%xmm2,(%rsi)
@@ -562,22 +562,22 @@
 	movups	%xmm8,96(%rsi)
 	movups	%xmm9,112(%rsi)
 	leaq	128(%rsi),%rsi
-	addq	$128,%rdx
+	addq	$0x80,%rdx
 	jz	.Lecb_ret
 
 .Lecb_enc_tail:
 	movups	(%rdi),%xmm2
-	cmpq	$32,%rdx
+	cmpq	$0x20,%rdx
 	jb	.Lecb_enc_one
 	movups	16(%rdi),%xmm3
 	je	.Lecb_enc_two
 	movups	32(%rdi),%xmm4
-	cmpq	$64,%rdx
+	cmpq	$0x40,%rdx
 	jb	.Lecb_enc_three
 	movups	48(%rdi),%xmm5
 	je	.Lecb_enc_four
 	movups	64(%rdi),%xmm6
-	cmpq	$96,%rdx
+	cmpq	$0x60,%rdx
 	jb	.Lecb_enc_five
 	movups	80(%rdi),%xmm7
 	je	.Lecb_enc_six
@@ -651,7 +651,7 @@
 
 .align	16
 .Lecb_decrypt:
-	cmpq	$128,%rdx
+	cmpq	$0x80,%rdx
 	jb	.Lecb_dec_tail
 
 	movdqu	(%rdi),%xmm2
@@ -663,7 +663,7 @@
 	movdqu	96(%rdi),%xmm8
 	movdqu	112(%rdi),%xmm9
 	leaq	128(%rdi),%rdi
-	subq	$128,%rdx
+	subq	$0x80,%rdx
 	jmp	.Lecb_dec_loop8_enter
 .align	16
 .Lecb_dec_loop8:
@@ -692,7 +692,7 @@
 	call	_aesni_decrypt8
 
 	movups	(%r11),%xmm0
-	subq	$128,%rdx
+	subq	$0x80,%rdx
 	jnc	.Lecb_dec_loop8
 
 	movups	%xmm2,(%rsi)
@@ -714,22 +714,22 @@
 	movups	%xmm9,112(%rsi)
 	pxor	%xmm9,%xmm9
 	leaq	128(%rsi),%rsi
-	addq	$128,%rdx
+	addq	$0x80,%rdx
 	jz	.Lecb_ret
 
 .Lecb_dec_tail:
 	movups	(%rdi),%xmm2
-	cmpq	$32,%rdx
+	cmpq	$0x20,%rdx
 	jb	.Lecb_dec_one
 	movups	16(%rdi),%xmm3
 	je	.Lecb_dec_two
 	movups	32(%rdi),%xmm4
-	cmpq	$64,%rdx
+	cmpq	$0x40,%rdx
 	jb	.Lecb_dec_three
 	movups	48(%rdi),%xmm5
 	je	.Lecb_dec_four
 	movups	64(%rdi),%xmm6
-	cmpq	$96,%rdx
+	cmpq	$0x60,%rdx
 	jb	.Lecb_dec_five
 	movups	80(%rdi),%xmm7
 	je	.Lecb_dec_six
@@ -1032,11 +1032,10 @@
 
 .align	16
 .Lctr32_bulk:
-	leaq	(%rsp),%rax
+	leaq	(%rsp),%r11
 	pushq	%rbp
 	subq	$128,%rsp
 	andq	$-16,%rsp
-	leaq	-8(%rax),%rbp
 
 
 
@@ -1045,7 +1044,7 @@
 	movdqu	(%rcx),%xmm0
 	movl	12(%r8),%r8d
 	pxor	%xmm0,%xmm2
-	movl	12(%rcx),%r11d
+	movl	12(%rcx),%ebp
 	movdqa	%xmm2,0(%rsp)
 	bswapl	%r8d
 	movdqa	%xmm2,%xmm3
@@ -1061,8 +1060,8 @@
 	leaq	2(%r8),%rdx
 	bswapl	%eax
 	bswapl	%edx
-	xorl	%r11d,%eax
-	xorl	%r11d,%edx
+	xorl	%ebp,%eax
+	xorl	%ebp,%edx
 .byte	102,15,58,34,216,3
 	leaq	3(%r8),%rax
 	movdqa	%xmm3,16(%rsp)
@@ -1071,25 +1070,25 @@
 	movq	%r10,%rdx
 	leaq	4(%r8),%r10
 	movdqa	%xmm4,32(%rsp)
-	xorl	%r11d,%eax
+	xorl	%ebp,%eax
 	bswapl	%r10d
 .byte	102,15,58,34,232,3
-	xorl	%r11d,%r10d
+	xorl	%ebp,%r10d
 	movdqa	%xmm5,48(%rsp)
 	leaq	5(%r8),%r9
 	movl	%r10d,64+12(%rsp)
 	bswapl	%r9d
 	leaq	6(%r8),%r10
 	movl	240(%rcx),%eax
-	xorl	%r11d,%r9d
+	xorl	%ebp,%r9d
 	bswapl	%r10d
 	movl	%r9d,80+12(%rsp)
-	xorl	%r11d,%r10d
+	xorl	%ebp,%r10d
 	leaq	7(%r8),%r9
 	movl	%r10d,96+12(%rsp)
 	bswapl	%r9d
 	movl	OPENSSL_ia32cap_P+4(%rip),%r10d
-	xorl	%r11d,%r9d
+	xorl	%ebp,%r9d
 	andl	$71303168,%r10d
 	movl	%r9d,112+12(%rsp)
 
@@ -1113,7 +1112,7 @@
 .Lctr32_6x:
 	shll	$4,%eax
 	movl	$48,%r10d
-	bswapl	%r11d
+	bswapl	%ebp
 	leaq	32(%rcx,%rax,1),%rcx
 	subq	%rax,%r10
 	jmp	.Lctr32_loop6
@@ -1124,32 +1123,32 @@
 	movups	-48(%rcx,%r10,1),%xmm0
 .byte	102,15,56,220,209
 	movl	%r8d,%eax
-	xorl	%r11d,%eax
+	xorl	%ebp,%eax
 .byte	102,15,56,220,217
 .byte	0x0f,0x38,0xf1,0x44,0x24,12
 	leal	1(%r8),%eax
 .byte	102,15,56,220,225
-	xorl	%r11d,%eax
+	xorl	%ebp,%eax
 .byte	0x0f,0x38,0xf1,0x44,0x24,28
 .byte	102,15,56,220,233
 	leal	2(%r8),%eax
-	xorl	%r11d,%eax
+	xorl	%ebp,%eax
 .byte	102,15,56,220,241
 .byte	0x0f,0x38,0xf1,0x44,0x24,44
 	leal	3(%r8),%eax
 .byte	102,15,56,220,249
 	movups	-32(%rcx,%r10,1),%xmm1
-	xorl	%r11d,%eax
+	xorl	%ebp,%eax
 
 .byte	102,15,56,220,208
 .byte	0x0f,0x38,0xf1,0x44,0x24,60
 	leal	4(%r8),%eax
 .byte	102,15,56,220,216
-	xorl	%r11d,%eax
+	xorl	%ebp,%eax
 .byte	0x0f,0x38,0xf1,0x44,0x24,76
 .byte	102,15,56,220,224
 	leal	5(%r8),%eax
-	xorl	%r11d,%eax
+	xorl	%ebp,%eax
 .byte	102,15,56,220,232
 .byte	0x0f,0x38,0xf1,0x44,0x24,92
 	movq	%r10,%rax
@@ -1210,7 +1209,7 @@
 	bswapl	%r9d
 	movups	32-128(%rcx),%xmm0
 .byte	102,15,56,220,225
-	xorl	%r11d,%r9d
+	xorl	%ebp,%r9d
 	nop
 .byte	102,15,56,220,233
 	movl	%r9d,0+12(%rsp)
@@ -1223,7 +1222,7 @@
 	bswapl	%r9d
 .byte	102,15,56,220,208
 .byte	102,15,56,220,216
-	xorl	%r11d,%r9d
+	xorl	%ebp,%r9d
 .byte	0x66,0x90
 .byte	102,15,56,220,224
 .byte	102,15,56,220,232
@@ -1237,7 +1236,7 @@
 	bswapl	%r9d
 .byte	102,15,56,220,209
 .byte	102,15,56,220,217
-	xorl	%r11d,%r9d
+	xorl	%ebp,%r9d
 .byte	0x66,0x90
 .byte	102,15,56,220,225
 .byte	102,15,56,220,233
@@ -1251,7 +1250,7 @@
 	bswapl	%r9d
 .byte	102,15,56,220,208
 .byte	102,15,56,220,216
-	xorl	%r11d,%r9d
+	xorl	%ebp,%r9d
 .byte	0x66,0x90
 .byte	102,15,56,220,224
 .byte	102,15,56,220,232
@@ -1265,7 +1264,7 @@
 	bswapl	%r9d
 .byte	102,15,56,220,209
 .byte	102,15,56,220,217
-	xorl	%r11d,%r9d
+	xorl	%ebp,%r9d
 .byte	0x66,0x90
 .byte	102,15,56,220,225
 .byte	102,15,56,220,233
@@ -1279,7 +1278,7 @@
 	bswapl	%r9d
 .byte	102,15,56,220,208
 .byte	102,15,56,220,216
-	xorl	%r11d,%r9d
+	xorl	%ebp,%r9d
 .byte	0x66,0x90
 .byte	102,15,56,220,224
 .byte	102,15,56,220,232
@@ -1293,7 +1292,7 @@
 	bswapl	%r9d
 .byte	102,15,56,220,209
 .byte	102,15,56,220,217
-	xorl	%r11d,%r9d
+	xorl	%ebp,%r9d
 .byte	0x66,0x90
 .byte	102,15,56,220,225
 .byte	102,15,56,220,233
@@ -1308,7 +1307,7 @@
 .byte	102,15,56,220,208
 .byte	102,15,56,220,216
 .byte	102,15,56,220,224
-	xorl	%r11d,%r9d
+	xorl	%ebp,%r9d
 	movdqu	0(%rdi),%xmm10
 .byte	102,15,56,220,232
 	movl	%r9d,112+12(%rsp)
@@ -1543,7 +1542,7 @@
 
 .Lctr32_done:
 	xorps	%xmm0,%xmm0
-	xorl	%r11d,%r11d
+	xorl	%ebp,%ebp
 	pxor	%xmm1,%xmm1
 	pxor	%xmm2,%xmm2
 	pxor	%xmm3,%xmm3
@@ -1567,8 +1566,8 @@
 	pxor	%xmm14,%xmm14
 	movaps	%xmm0,112(%rsp)
 	pxor	%xmm15,%xmm15
-	leaq	(%rbp),%rsp
-	popq	%rbp
+	movq	-8(%r11),%rbp
+	leaq	(%r11),%rsp
 .Lctr32_epilogue:
 	.byte	0xf3,0xc3
 .size	aesni_ctr32_encrypt_blocks,.-aesni_ctr32_encrypt_blocks
@@ -1577,11 +1576,10 @@
 .type	aesni_xts_encrypt,@function
 .align	16
 aesni_xts_encrypt:
-	leaq	(%rsp),%rax
+	leaq	(%rsp),%r11
 	pushq	%rbp
 	subq	$112,%rsp
 	andq	$-16,%rsp
-	leaq	-8(%rax),%rbp
 	movups	(%r9),%xmm2
 	movl	240(%r8),%eax
 	movl	240(%rcx),%r10d
@@ -1597,7 +1595,7 @@
 	jnz	.Loop_enc1_8
 .byte	102,15,56,221,209
 	movups	(%rcx),%xmm0
-	movq	%rcx,%r11
+	movq	%rcx,%rbp
 	movl	%r10d,%eax
 	shll	$4,%r10d
 	movq	%rdx,%r9
@@ -1607,7 +1605,7 @@
 
 	movdqa	.Lxts_magic(%rip),%xmm8
 	movdqa	%xmm2,%xmm15
-	pshufd	$95,%xmm2,%xmm9
+	pshufd	$0x5f,%xmm2,%xmm9
 	pxor	%xmm0,%xmm1
 	movdqa	%xmm9,%xmm14
 	paddd	%xmm9,%xmm9
@@ -1653,9 +1651,9 @@
 	jc	.Lxts_enc_short
 
 	movl	$16+96,%eax
-	leaq	32(%r11,%r10,1),%rcx
+	leaq	32(%rbp,%r10,1),%rcx
 	subq	%r10,%rax
-	movups	16(%r11),%xmm1
+	movups	16(%rbp),%xmm1
 	movq	%rax,%r10
 	leaq	.Lxts_magic(%rip),%r8
 	jmp	.Lxts_enc_grandloop
@@ -1680,7 +1678,7 @@
 	movdqa	96(%rsp),%xmm9
 	pxor	%xmm14,%xmm6
 .byte	102,15,56,220,233
-	movups	32(%r11),%xmm0
+	movups	32(%rbp),%xmm0
 	leaq	96(%rdi),%rdi
 	pxor	%xmm8,%xmm7
 
@@ -1689,7 +1687,7 @@
 	pxor	%xmm9,%xmm11
 	movdqa	%xmm10,0(%rsp)
 .byte	102,15,56,220,249
-	movups	48(%r11),%xmm1
+	movups	48(%rbp),%xmm1
 	pxor	%xmm9,%xmm12
 
 .byte	102,15,56,220,208
@@ -1704,9 +1702,9 @@
 	movdqa	%xmm14,64(%rsp)
 .byte	102,15,56,220,240
 .byte	102,15,56,220,248
-	movups	64(%r11),%xmm0
+	movups	64(%rbp),%xmm0
 	movdqa	%xmm8,80(%rsp)
-	pshufd	$95,%xmm15,%xmm9
+	pshufd	$0x5f,%xmm15,%xmm9
 	jmp	.Lxts_enc_loop6
 .align	32
 .Lxts_enc_loop6:
@@ -1736,7 +1734,7 @@
 	psrad	$31,%xmm14
 .byte	102,15,56,220,217
 	pand	%xmm8,%xmm14
-	movups	(%r11),%xmm10
+	movups	(%rbp),%xmm10
 .byte	102,15,56,220,225
 .byte	102,15,56,220,233
 .byte	102,15,56,220,241
@@ -1804,10 +1802,10 @@
 .byte	102,15,56,220,225
 .byte	102,15,56,220,233
 	pxor	%xmm0,%xmm15
-	movups	(%r11),%xmm0
+	movups	(%rbp),%xmm0
 .byte	102,15,56,220,241
 .byte	102,15,56,220,249
-	movups	16(%r11),%xmm1
+	movups	16(%rbp),%xmm1
 
 	pxor	%xmm15,%xmm14
 .byte	102,15,56,221,84,36,0
@@ -1834,7 +1832,7 @@
 
 	movl	$16+96,%eax
 	subl	%r10d,%eax
-	movq	%r11,%rcx
+	movq	%rbp,%rcx
 	shrl	$4,%eax
 
 .Lxts_enc_short:
@@ -1845,13 +1843,13 @@
 	jz	.Lxts_enc_done
 
 	pxor	%xmm0,%xmm11
-	cmpq	$32,%rdx
+	cmpq	$0x20,%rdx
 	jb	.Lxts_enc_one
 	pxor	%xmm0,%xmm12
 	je	.Lxts_enc_two
 
 	pxor	%xmm0,%xmm13
-	cmpq	$64,%rdx
+	cmpq	$0x40,%rdx
 	jb	.Lxts_enc_three
 	pxor	%xmm0,%xmm14
 	je	.Lxts_enc_four
@@ -1990,7 +1988,7 @@
 	jnz	.Lxts_enc_steal
 
 	subq	%r9,%rsi
-	movq	%r11,%rcx
+	movq	%rbp,%rcx
 	movl	%r10d,%eax
 
 	movups	-16(%rsi),%xmm2
@@ -2033,8 +2031,8 @@
 	movaps	%xmm0,96(%rsp)
 	pxor	%xmm14,%xmm14
 	pxor	%xmm15,%xmm15
-	leaq	(%rbp),%rsp
-	popq	%rbp
+	movq	-8(%r11),%rbp
+	leaq	(%r11),%rsp
 .Lxts_enc_epilogue:
 	.byte	0xf3,0xc3
 .size	aesni_xts_encrypt,.-aesni_xts_encrypt
@@ -2043,11 +2041,10 @@
 .type	aesni_xts_decrypt,@function
 .align	16
 aesni_xts_decrypt:
-	leaq	(%rsp),%rax
+	leaq	(%rsp),%r11
 	pushq	%rbp
 	subq	$112,%rsp
 	andq	$-16,%rsp
-	leaq	-8(%rax),%rbp
 	movups	(%r9),%xmm2
 	movl	240(%r8),%eax
 	movl	240(%rcx),%r10d
@@ -2069,7 +2066,7 @@
 	subq	%rax,%rdx
 
 	movups	(%rcx),%xmm0
-	movq	%rcx,%r11
+	movq	%rcx,%rbp
 	movl	%r10d,%eax
 	shll	$4,%r10d
 	movq	%rdx,%r9
@@ -2079,7 +2076,7 @@
 
 	movdqa	.Lxts_magic(%rip),%xmm8
 	movdqa	%xmm2,%xmm15
-	pshufd	$95,%xmm2,%xmm9
+	pshufd	$0x5f,%xmm2,%xmm9
 	pxor	%xmm0,%xmm1
 	movdqa	%xmm9,%xmm14
 	paddd	%xmm9,%xmm9
@@ -2125,9 +2122,9 @@
 	jc	.Lxts_dec_short
 
 	movl	$16+96,%eax
-	leaq	32(%r11,%r10,1),%rcx
+	leaq	32(%rbp,%r10,1),%rcx
 	subq	%r10,%rax
-	movups	16(%r11),%xmm1
+	movups	16(%rbp),%xmm1
 	movq	%rax,%r10
 	leaq	.Lxts_magic(%rip),%r8
 	jmp	.Lxts_dec_grandloop
@@ -2152,7 +2149,7 @@
 	movdqa	96(%rsp),%xmm9
 	pxor	%xmm14,%xmm6
 .byte	102,15,56,222,233
-	movups	32(%r11),%xmm0
+	movups	32(%rbp),%xmm0
 	leaq	96(%rdi),%rdi
 	pxor	%xmm8,%xmm7
 
@@ -2161,7 +2158,7 @@
 	pxor	%xmm9,%xmm11
 	movdqa	%xmm10,0(%rsp)
 .byte	102,15,56,222,249
-	movups	48(%r11),%xmm1
+	movups	48(%rbp),%xmm1
 	pxor	%xmm9,%xmm12
 
 .byte	102,15,56,222,208
@@ -2176,9 +2173,9 @@
 	movdqa	%xmm14,64(%rsp)
 .byte	102,15,56,222,240
 .byte	102,15,56,222,248
-	movups	64(%r11),%xmm0
+	movups	64(%rbp),%xmm0
 	movdqa	%xmm8,80(%rsp)
-	pshufd	$95,%xmm15,%xmm9
+	pshufd	$0x5f,%xmm15,%xmm9
 	jmp	.Lxts_dec_loop6
 .align	32
 .Lxts_dec_loop6:
@@ -2208,7 +2205,7 @@
 	psrad	$31,%xmm14
 .byte	102,15,56,222,217
 	pand	%xmm8,%xmm14
-	movups	(%r11),%xmm10
+	movups	(%rbp),%xmm10
 .byte	102,15,56,222,225
 .byte	102,15,56,222,233
 .byte	102,15,56,222,241
@@ -2276,10 +2273,10 @@
 .byte	102,15,56,222,225
 .byte	102,15,56,222,233
 	pxor	%xmm0,%xmm15
-	movups	(%r11),%xmm0
+	movups	(%rbp),%xmm0
 .byte	102,15,56,222,241
 .byte	102,15,56,222,249
-	movups	16(%r11),%xmm1
+	movups	16(%rbp),%xmm1
 
 	pxor	%xmm15,%xmm14
 .byte	102,15,56,223,84,36,0
@@ -2306,7 +2303,7 @@
 
 	movl	$16+96,%eax
 	subl	%r10d,%eax
-	movq	%r11,%rcx
+	movq	%rbp,%rcx
 	shrl	$4,%eax
 
 .Lxts_dec_short:
@@ -2318,13 +2315,13 @@
 	jz	.Lxts_dec_done
 
 	pxor	%xmm0,%xmm12
-	cmpq	$32,%rdx
+	cmpq	$0x20,%rdx
 	jb	.Lxts_dec_one
 	pxor	%xmm0,%xmm13
 	je	.Lxts_dec_two
 
 	pxor	%xmm0,%xmm14
-	cmpq	$64,%rdx
+	cmpq	$0x40,%rdx
 	jb	.Lxts_dec_three
 	je	.Lxts_dec_four
 
@@ -2355,7 +2352,7 @@
 	pcmpgtd	%xmm15,%xmm14
 	movdqu	%xmm6,64(%rsi)
 	leaq	80(%rsi),%rsi
-	pshufd	$19,%xmm14,%xmm11
+	pshufd	$0x13,%xmm14,%xmm11
 	andq	$15,%r9
 	jz	.Lxts_dec_ret
 
@@ -2463,7 +2460,7 @@
 	jz	.Lxts_dec_ret
 .Lxts_dec_done2:
 	movq	%r9,%rdx
-	movq	%r11,%rcx
+	movq	%rbp,%rcx
 	movl	%r10d,%eax
 
 	movups	(%rdi),%xmm2
@@ -2493,7 +2490,7 @@
 	jnz	.Lxts_dec_steal
 
 	subq	%r9,%rsi
-	movq	%r11,%rcx
+	movq	%rbp,%rcx
 	movl	%r10d,%eax
 
 	movups	(%rsi),%xmm2
@@ -2536,11 +2533,827 @@
 	movaps	%xmm0,96(%rsp)
 	pxor	%xmm14,%xmm14
 	pxor	%xmm15,%xmm15
-	leaq	(%rbp),%rsp
-	popq	%rbp
+	movq	-8(%r11),%rbp
+	leaq	(%r11),%rsp
 .Lxts_dec_epilogue:
 	.byte	0xf3,0xc3
 .size	aesni_xts_decrypt,.-aesni_xts_decrypt
+.globl	aesni_ocb_encrypt
+.hidden aesni_ocb_encrypt
+.type	aesni_ocb_encrypt,@function
+.align	32
+aesni_ocb_encrypt:
+	leaq	(%rsp),%rax
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	movq	8(%rax),%rbx
+	movq	8+8(%rax),%rbp
+
+	movl	240(%rcx),%r10d
+	movq	%rcx,%r11
+	shll	$4,%r10d
+	movups	(%rcx),%xmm9
+	movups	16(%rcx,%r10,1),%xmm1
+
+	movdqu	(%r9),%xmm15
+	pxor	%xmm1,%xmm9
+	pxor	%xmm1,%xmm15
+
+	movl	$16+32,%eax
+	leaq	32(%r11,%r10,1),%rcx
+	movups	16(%r11),%xmm1
+	subq	%r10,%rax
+	movq	%rax,%r10
+
+	movdqu	(%rbx),%xmm10
+	movdqu	(%rbp),%xmm8
+
+	testq	$1,%r8
+	jnz	.Locb_enc_odd
+
+	bsfq	%r8,%r12
+	addq	$1,%r8
+	shlq	$4,%r12
+	movdqu	(%rbx,%r12,1),%xmm7
+	movdqu	(%rdi),%xmm2
+	leaq	16(%rdi),%rdi
+
+	call	__ocb_encrypt1
+
+	movdqa	%xmm7,%xmm15
+	movups	%xmm2,(%rsi)
+	leaq	16(%rsi),%rsi
+	subq	$1,%rdx
+	jz	.Locb_enc_done
+
+.Locb_enc_odd:
+	leaq	1(%r8),%r12
+	leaq	3(%r8),%r13
+	leaq	5(%r8),%r14
+	leaq	6(%r8),%r8
+	bsfq	%r12,%r12
+	bsfq	%r13,%r13
+	bsfq	%r14,%r14
+	shlq	$4,%r12
+	shlq	$4,%r13
+	shlq	$4,%r14
+
+	subq	$6,%rdx
+	jc	.Locb_enc_short
+	jmp	.Locb_enc_grandloop
+
+.align	32
+.Locb_enc_grandloop:
+	movdqu	0(%rdi),%xmm2
+	movdqu	16(%rdi),%xmm3
+	movdqu	32(%rdi),%xmm4
+	movdqu	48(%rdi),%xmm5
+	movdqu	64(%rdi),%xmm6
+	movdqu	80(%rdi),%xmm7
+	leaq	96(%rdi),%rdi
+
+	call	__ocb_encrypt6
+
+	movups	%xmm2,0(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+	movups	%xmm7,80(%rsi)
+	leaq	96(%rsi),%rsi
+	subq	$6,%rdx
+	jnc	.Locb_enc_grandloop
+
+.Locb_enc_short:
+	addq	$6,%rdx
+	jz	.Locb_enc_done
+
+	movdqu	0(%rdi),%xmm2
+	cmpq	$2,%rdx
+	jb	.Locb_enc_one
+	movdqu	16(%rdi),%xmm3
+	je	.Locb_enc_two
+
+	movdqu	32(%rdi),%xmm4
+	cmpq	$4,%rdx
+	jb	.Locb_enc_three
+	movdqu	48(%rdi),%xmm5
+	je	.Locb_enc_four
+
+	movdqu	64(%rdi),%xmm6
+	pxor	%xmm7,%xmm7
+
+	call	__ocb_encrypt6
+
+	movdqa	%xmm14,%xmm15
+	movups	%xmm2,0(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+
+	jmp	.Locb_enc_done
+
+.align	16
+.Locb_enc_one:
+	movdqa	%xmm10,%xmm7
+
+	call	__ocb_encrypt1
+
+	movdqa	%xmm7,%xmm15
+	movups	%xmm2,0(%rsi)
+	jmp	.Locb_enc_done
+
+.align	16
+.Locb_enc_two:
+	pxor	%xmm4,%xmm4
+	pxor	%xmm5,%xmm5
+
+	call	__ocb_encrypt4
+
+	movdqa	%xmm11,%xmm15
+	movups	%xmm2,0(%rsi)
+	movups	%xmm3,16(%rsi)
+
+	jmp	.Locb_enc_done
+
+.align	16
+.Locb_enc_three:
+	pxor	%xmm5,%xmm5
+
+	call	__ocb_encrypt4
+
+	movdqa	%xmm12,%xmm15
+	movups	%xmm2,0(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+
+	jmp	.Locb_enc_done
+
+.align	16
+.Locb_enc_four:
+	call	__ocb_encrypt4
+
+	movdqa	%xmm13,%xmm15
+	movups	%xmm2,0(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+
+.Locb_enc_done:
+	pxor	%xmm0,%xmm15
+	movdqu	%xmm8,(%rbp)
+	movdqu	%xmm15,(%r9)
+
+	xorps	%xmm0,%xmm0
+	pxor	%xmm1,%xmm1
+	pxor	%xmm2,%xmm2
+	pxor	%xmm3,%xmm3
+	pxor	%xmm4,%xmm4
+	pxor	%xmm5,%xmm5
+	pxor	%xmm6,%xmm6
+	pxor	%xmm7,%xmm7
+	pxor	%xmm8,%xmm8
+	pxor	%xmm9,%xmm9
+	pxor	%xmm10,%xmm10
+	pxor	%xmm11,%xmm11
+	pxor	%xmm12,%xmm12
+	pxor	%xmm13,%xmm13
+	pxor	%xmm14,%xmm14
+	pxor	%xmm15,%xmm15
+	leaq	40(%rsp),%rax
+	movq	-40(%rax),%r14
+	movq	-32(%rax),%r13
+	movq	-24(%rax),%r12
+	movq	-16(%rax),%rbp
+	movq	-8(%rax),%rbx
+	leaq	(%rax),%rsp
+.Locb_enc_epilogue:
+	.byte	0xf3,0xc3
+.size	aesni_ocb_encrypt,.-aesni_ocb_encrypt
+
+.type	__ocb_encrypt6,@function
+.align	32
+__ocb_encrypt6:
+	pxor	%xmm9,%xmm15
+	movdqu	(%rbx,%r12,1),%xmm11
+	movdqa	%xmm10,%xmm12
+	movdqu	(%rbx,%r13,1),%xmm13
+	movdqa	%xmm10,%xmm14
+	pxor	%xmm15,%xmm10
+	movdqu	(%rbx,%r14,1),%xmm15
+	pxor	%xmm10,%xmm11
+	pxor	%xmm2,%xmm8
+	pxor	%xmm10,%xmm2
+	pxor	%xmm11,%xmm12
+	pxor	%xmm3,%xmm8
+	pxor	%xmm11,%xmm3
+	pxor	%xmm12,%xmm13
+	pxor	%xmm4,%xmm8
+	pxor	%xmm12,%xmm4
+	pxor	%xmm13,%xmm14
+	pxor	%xmm5,%xmm8
+	pxor	%xmm13,%xmm5
+	pxor	%xmm14,%xmm15
+	pxor	%xmm6,%xmm8
+	pxor	%xmm14,%xmm6
+	pxor	%xmm7,%xmm8
+	pxor	%xmm15,%xmm7
+	movups	32(%r11),%xmm0
+
+	leaq	1(%r8),%r12
+	leaq	3(%r8),%r13
+	leaq	5(%r8),%r14
+	addq	$6,%r8
+	pxor	%xmm9,%xmm10
+	bsfq	%r12,%r12
+	bsfq	%r13,%r13
+	bsfq	%r14,%r14
+
+.byte	102,15,56,220,209
+.byte	102,15,56,220,217
+.byte	102,15,56,220,225
+.byte	102,15,56,220,233
+	pxor	%xmm9,%xmm11
+	pxor	%xmm9,%xmm12
+.byte	102,15,56,220,241
+	pxor	%xmm9,%xmm13
+	pxor	%xmm9,%xmm14
+.byte	102,15,56,220,249
+	movups	48(%r11),%xmm1
+	pxor	%xmm9,%xmm15
+
+.byte	102,15,56,220,208
+.byte	102,15,56,220,216
+.byte	102,15,56,220,224
+.byte	102,15,56,220,232
+.byte	102,15,56,220,240
+.byte	102,15,56,220,248
+	movups	64(%r11),%xmm0
+	shlq	$4,%r12
+	shlq	$4,%r13
+	jmp	.Locb_enc_loop6
+
+.align	32
+.Locb_enc_loop6:
+.byte	102,15,56,220,209
+.byte	102,15,56,220,217
+.byte	102,15,56,220,225
+.byte	102,15,56,220,233
+.byte	102,15,56,220,241
+.byte	102,15,56,220,249
+	movups	(%rcx,%rax,1),%xmm1
+	addq	$32,%rax
+
+.byte	102,15,56,220,208
+.byte	102,15,56,220,216
+.byte	102,15,56,220,224
+.byte	102,15,56,220,232
+.byte	102,15,56,220,240
+.byte	102,15,56,220,248
+	movups	-16(%rcx,%rax,1),%xmm0
+	jnz	.Locb_enc_loop6
+
+.byte	102,15,56,220,209
+.byte	102,15,56,220,217
+.byte	102,15,56,220,225
+.byte	102,15,56,220,233
+.byte	102,15,56,220,241
+.byte	102,15,56,220,249
+	movups	16(%r11),%xmm1
+	shlq	$4,%r14
+
+.byte	102,65,15,56,221,210
+	movdqu	(%rbx),%xmm10
+	movq	%r10,%rax
+.byte	102,65,15,56,221,219
+.byte	102,65,15,56,221,228
+.byte	102,65,15,56,221,237
+.byte	102,65,15,56,221,246
+.byte	102,65,15,56,221,255
+	.byte	0xf3,0xc3
+.size	__ocb_encrypt6,.-__ocb_encrypt6
+
+.type	__ocb_encrypt4,@function
+.align	32
+__ocb_encrypt4:
+	pxor	%xmm9,%xmm15
+	movdqu	(%rbx,%r12,1),%xmm11
+	movdqa	%xmm10,%xmm12
+	movdqu	(%rbx,%r13,1),%xmm13
+	pxor	%xmm15,%xmm10
+	pxor	%xmm10,%xmm11
+	pxor	%xmm2,%xmm8
+	pxor	%xmm10,%xmm2
+	pxor	%xmm11,%xmm12
+	pxor	%xmm3,%xmm8
+	pxor	%xmm11,%xmm3
+	pxor	%xmm12,%xmm13
+	pxor	%xmm4,%xmm8
+	pxor	%xmm12,%xmm4
+	pxor	%xmm5,%xmm8
+	pxor	%xmm13,%xmm5
+	movups	32(%r11),%xmm0
+
+	pxor	%xmm9,%xmm10
+	pxor	%xmm9,%xmm11
+	pxor	%xmm9,%xmm12
+	pxor	%xmm9,%xmm13
+
+.byte	102,15,56,220,209
+.byte	102,15,56,220,217
+.byte	102,15,56,220,225
+.byte	102,15,56,220,233
+	movups	48(%r11),%xmm1
+
+.byte	102,15,56,220,208
+.byte	102,15,56,220,216
+.byte	102,15,56,220,224
+.byte	102,15,56,220,232
+	movups	64(%r11),%xmm0
+	jmp	.Locb_enc_loop4
+
+.align	32
+.Locb_enc_loop4:
+.byte	102,15,56,220,209
+.byte	102,15,56,220,217
+.byte	102,15,56,220,225
+.byte	102,15,56,220,233
+	movups	(%rcx,%rax,1),%xmm1
+	addq	$32,%rax
+
+.byte	102,15,56,220,208
+.byte	102,15,56,220,216
+.byte	102,15,56,220,224
+.byte	102,15,56,220,232
+	movups	-16(%rcx,%rax,1),%xmm0
+	jnz	.Locb_enc_loop4
+
+.byte	102,15,56,220,209
+.byte	102,15,56,220,217
+.byte	102,15,56,220,225
+.byte	102,15,56,220,233
+	movups	16(%r11),%xmm1
+	movq	%r10,%rax
+
+.byte	102,65,15,56,221,210
+.byte	102,65,15,56,221,219
+.byte	102,65,15,56,221,228
+.byte	102,65,15,56,221,237
+	.byte	0xf3,0xc3
+.size	__ocb_encrypt4,.-__ocb_encrypt4
+
+.type	__ocb_encrypt1,@function
+.align	32
+__ocb_encrypt1:
+	pxor	%xmm15,%xmm7
+	pxor	%xmm9,%xmm7
+	pxor	%xmm2,%xmm8
+	pxor	%xmm7,%xmm2
+	movups	32(%r11),%xmm0
+
+.byte	102,15,56,220,209
+	movups	48(%r11),%xmm1
+	pxor	%xmm9,%xmm7
+
+.byte	102,15,56,220,208
+	movups	64(%r11),%xmm0
+	jmp	.Locb_enc_loop1
+
+.align	32
+.Locb_enc_loop1:
+.byte	102,15,56,220,209
+	movups	(%rcx,%rax,1),%xmm1
+	addq	$32,%rax
+
+.byte	102,15,56,220,208
+	movups	-16(%rcx,%rax,1),%xmm0
+	jnz	.Locb_enc_loop1
+
+.byte	102,15,56,220,209
+	movups	16(%r11),%xmm1
+	movq	%r10,%rax
+
+.byte	102,15,56,221,215
+	.byte	0xf3,0xc3
+.size	__ocb_encrypt1,.-__ocb_encrypt1
+
+.globl	aesni_ocb_decrypt
+.hidden aesni_ocb_decrypt
+.type	aesni_ocb_decrypt,@function
+.align	32
+aesni_ocb_decrypt:
+	leaq	(%rsp),%rax
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	movq	8(%rax),%rbx
+	movq	8+8(%rax),%rbp
+
+	movl	240(%rcx),%r10d
+	movq	%rcx,%r11
+	shll	$4,%r10d
+	movups	(%rcx),%xmm9
+	movups	16(%rcx,%r10,1),%xmm1
+
+	movdqu	(%r9),%xmm15
+	pxor	%xmm1,%xmm9
+	pxor	%xmm1,%xmm15
+
+	movl	$16+32,%eax
+	leaq	32(%r11,%r10,1),%rcx
+	movups	16(%r11),%xmm1
+	subq	%r10,%rax
+	movq	%rax,%r10
+
+	movdqu	(%rbx),%xmm10
+	movdqu	(%rbp),%xmm8
+
+	testq	$1,%r8
+	jnz	.Locb_dec_odd
+
+	bsfq	%r8,%r12
+	addq	$1,%r8
+	shlq	$4,%r12
+	movdqu	(%rbx,%r12,1),%xmm7
+	movdqu	(%rdi),%xmm2
+	leaq	16(%rdi),%rdi
+
+	call	__ocb_decrypt1
+
+	movdqa	%xmm7,%xmm15
+	movups	%xmm2,(%rsi)
+	xorps	%xmm2,%xmm8
+	leaq	16(%rsi),%rsi
+	subq	$1,%rdx
+	jz	.Locb_dec_done
+
+.Locb_dec_odd:
+	leaq	1(%r8),%r12
+	leaq	3(%r8),%r13
+	leaq	5(%r8),%r14
+	leaq	6(%r8),%r8
+	bsfq	%r12,%r12
+	bsfq	%r13,%r13
+	bsfq	%r14,%r14
+	shlq	$4,%r12
+	shlq	$4,%r13
+	shlq	$4,%r14
+
+	subq	$6,%rdx
+	jc	.Locb_dec_short
+	jmp	.Locb_dec_grandloop
+
+.align	32
+.Locb_dec_grandloop:
+	movdqu	0(%rdi),%xmm2
+	movdqu	16(%rdi),%xmm3
+	movdqu	32(%rdi),%xmm4
+	movdqu	48(%rdi),%xmm5
+	movdqu	64(%rdi),%xmm6
+	movdqu	80(%rdi),%xmm7
+	leaq	96(%rdi),%rdi
+
+	call	__ocb_decrypt6
+
+	movups	%xmm2,0(%rsi)
+	pxor	%xmm2,%xmm8
+	movups	%xmm3,16(%rsi)
+	pxor	%xmm3,%xmm8
+	movups	%xmm4,32(%rsi)
+	pxor	%xmm4,%xmm8
+	movups	%xmm5,48(%rsi)
+	pxor	%xmm5,%xmm8
+	movups	%xmm6,64(%rsi)
+	pxor	%xmm6,%xmm8
+	movups	%xmm7,80(%rsi)
+	pxor	%xmm7,%xmm8
+	leaq	96(%rsi),%rsi
+	subq	$6,%rdx
+	jnc	.Locb_dec_grandloop
+
+.Locb_dec_short:
+	addq	$6,%rdx
+	jz	.Locb_dec_done
+
+	movdqu	0(%rdi),%xmm2
+	cmpq	$2,%rdx
+	jb	.Locb_dec_one
+	movdqu	16(%rdi),%xmm3
+	je	.Locb_dec_two
+
+	movdqu	32(%rdi),%xmm4
+	cmpq	$4,%rdx
+	jb	.Locb_dec_three
+	movdqu	48(%rdi),%xmm5
+	je	.Locb_dec_four
+
+	movdqu	64(%rdi),%xmm6
+	pxor	%xmm7,%xmm7
+
+	call	__ocb_decrypt6
+
+	movdqa	%xmm14,%xmm15
+	movups	%xmm2,0(%rsi)
+	pxor	%xmm2,%xmm8
+	movups	%xmm3,16(%rsi)
+	pxor	%xmm3,%xmm8
+	movups	%xmm4,32(%rsi)
+	pxor	%xmm4,%xmm8
+	movups	%xmm5,48(%rsi)
+	pxor	%xmm5,%xmm8
+	movups	%xmm6,64(%rsi)
+	pxor	%xmm6,%xmm8
+
+	jmp	.Locb_dec_done
+
+.align	16
+.Locb_dec_one:
+	movdqa	%xmm10,%xmm7
+
+	call	__ocb_decrypt1
+
+	movdqa	%xmm7,%xmm15
+	movups	%xmm2,0(%rsi)
+	xorps	%xmm2,%xmm8
+	jmp	.Locb_dec_done
+
+.align	16
+.Locb_dec_two:
+	pxor	%xmm4,%xmm4
+	pxor	%xmm5,%xmm5
+
+	call	__ocb_decrypt4
+
+	movdqa	%xmm11,%xmm15
+	movups	%xmm2,0(%rsi)
+	xorps	%xmm2,%xmm8
+	movups	%xmm3,16(%rsi)
+	xorps	%xmm3,%xmm8
+
+	jmp	.Locb_dec_done
+
+.align	16
+.Locb_dec_three:
+	pxor	%xmm5,%xmm5
+
+	call	__ocb_decrypt4
+
+	movdqa	%xmm12,%xmm15
+	movups	%xmm2,0(%rsi)
+	xorps	%xmm2,%xmm8
+	movups	%xmm3,16(%rsi)
+	xorps	%xmm3,%xmm8
+	movups	%xmm4,32(%rsi)
+	xorps	%xmm4,%xmm8
+
+	jmp	.Locb_dec_done
+
+.align	16
+.Locb_dec_four:
+	call	__ocb_decrypt4
+
+	movdqa	%xmm13,%xmm15
+	movups	%xmm2,0(%rsi)
+	pxor	%xmm2,%xmm8
+	movups	%xmm3,16(%rsi)
+	pxor	%xmm3,%xmm8
+	movups	%xmm4,32(%rsi)
+	pxor	%xmm4,%xmm8
+	movups	%xmm5,48(%rsi)
+	pxor	%xmm5,%xmm8
+
+.Locb_dec_done:
+	pxor	%xmm0,%xmm15
+	movdqu	%xmm8,(%rbp)
+	movdqu	%xmm15,(%r9)
+
+	xorps	%xmm0,%xmm0
+	pxor	%xmm1,%xmm1
+	pxor	%xmm2,%xmm2
+	pxor	%xmm3,%xmm3
+	pxor	%xmm4,%xmm4
+	pxor	%xmm5,%xmm5
+	pxor	%xmm6,%xmm6
+	pxor	%xmm7,%xmm7
+	pxor	%xmm8,%xmm8
+	pxor	%xmm9,%xmm9
+	pxor	%xmm10,%xmm10
+	pxor	%xmm11,%xmm11
+	pxor	%xmm12,%xmm12
+	pxor	%xmm13,%xmm13
+	pxor	%xmm14,%xmm14
+	pxor	%xmm15,%xmm15
+	leaq	40(%rsp),%rax
+	movq	-40(%rax),%r14
+	movq	-32(%rax),%r13
+	movq	-24(%rax),%r12
+	movq	-16(%rax),%rbp
+	movq	-8(%rax),%rbx
+	leaq	(%rax),%rsp
+.Locb_dec_epilogue:
+	.byte	0xf3,0xc3
+.size	aesni_ocb_decrypt,.-aesni_ocb_decrypt
+
+.type	__ocb_decrypt6,@function
+.align	32
+__ocb_decrypt6:
+	pxor	%xmm9,%xmm15
+	movdqu	(%rbx,%r12,1),%xmm11
+	movdqa	%xmm10,%xmm12
+	movdqu	(%rbx,%r13,1),%xmm13
+	movdqa	%xmm10,%xmm14
+	pxor	%xmm15,%xmm10
+	movdqu	(%rbx,%r14,1),%xmm15
+	pxor	%xmm10,%xmm11
+	pxor	%xmm10,%xmm2
+	pxor	%xmm11,%xmm12
+	pxor	%xmm11,%xmm3
+	pxor	%xmm12,%xmm13
+	pxor	%xmm12,%xmm4
+	pxor	%xmm13,%xmm14
+	pxor	%xmm13,%xmm5
+	pxor	%xmm14,%xmm15
+	pxor	%xmm14,%xmm6
+	pxor	%xmm15,%xmm7
+	movups	32(%r11),%xmm0
+
+	leaq	1(%r8),%r12
+	leaq	3(%r8),%r13
+	leaq	5(%r8),%r14
+	addq	$6,%r8
+	pxor	%xmm9,%xmm10
+	bsfq	%r12,%r12
+	bsfq	%r13,%r13
+	bsfq	%r14,%r14
+
+.byte	102,15,56,222,209
+.byte	102,15,56,222,217
+.byte	102,15,56,222,225
+.byte	102,15,56,222,233
+	pxor	%xmm9,%xmm11
+	pxor	%xmm9,%xmm12
+.byte	102,15,56,222,241
+	pxor	%xmm9,%xmm13
+	pxor	%xmm9,%xmm14
+.byte	102,15,56,222,249
+	movups	48(%r11),%xmm1
+	pxor	%xmm9,%xmm15
+
+.byte	102,15,56,222,208
+.byte	102,15,56,222,216
+.byte	102,15,56,222,224
+.byte	102,15,56,222,232
+.byte	102,15,56,222,240
+.byte	102,15,56,222,248
+	movups	64(%r11),%xmm0
+	shlq	$4,%r12
+	shlq	$4,%r13
+	jmp	.Locb_dec_loop6
+
+.align	32
+.Locb_dec_loop6:
+.byte	102,15,56,222,209
+.byte	102,15,56,222,217
+.byte	102,15,56,222,225
+.byte	102,15,56,222,233
+.byte	102,15,56,222,241
+.byte	102,15,56,222,249
+	movups	(%rcx,%rax,1),%xmm1
+	addq	$32,%rax
+
+.byte	102,15,56,222,208
+.byte	102,15,56,222,216
+.byte	102,15,56,222,224
+.byte	102,15,56,222,232
+.byte	102,15,56,222,240
+.byte	102,15,56,222,248
+	movups	-16(%rcx,%rax,1),%xmm0
+	jnz	.Locb_dec_loop6
+
+.byte	102,15,56,222,209
+.byte	102,15,56,222,217
+.byte	102,15,56,222,225
+.byte	102,15,56,222,233
+.byte	102,15,56,222,241
+.byte	102,15,56,222,249
+	movups	16(%r11),%xmm1
+	shlq	$4,%r14
+
+.byte	102,65,15,56,223,210
+	movdqu	(%rbx),%xmm10
+	movq	%r10,%rax
+.byte	102,65,15,56,223,219
+.byte	102,65,15,56,223,228
+.byte	102,65,15,56,223,237
+.byte	102,65,15,56,223,246
+.byte	102,65,15,56,223,255
+	.byte	0xf3,0xc3
+.size	__ocb_decrypt6,.-__ocb_decrypt6
+
+.type	__ocb_decrypt4,@function
+.align	32
+__ocb_decrypt4:
+	pxor	%xmm9,%xmm15
+	movdqu	(%rbx,%r12,1),%xmm11
+	movdqa	%xmm10,%xmm12
+	movdqu	(%rbx,%r13,1),%xmm13
+	pxor	%xmm15,%xmm10
+	pxor	%xmm10,%xmm11
+	pxor	%xmm10,%xmm2
+	pxor	%xmm11,%xmm12
+	pxor	%xmm11,%xmm3
+	pxor	%xmm12,%xmm13
+	pxor	%xmm12,%xmm4
+	pxor	%xmm13,%xmm5
+	movups	32(%r11),%xmm0
+
+	pxor	%xmm9,%xmm10
+	pxor	%xmm9,%xmm11
+	pxor	%xmm9,%xmm12
+	pxor	%xmm9,%xmm13
+
+.byte	102,15,56,222,209
+.byte	102,15,56,222,217
+.byte	102,15,56,222,225
+.byte	102,15,56,222,233
+	movups	48(%r11),%xmm1
+
+.byte	102,15,56,222,208
+.byte	102,15,56,222,216
+.byte	102,15,56,222,224
+.byte	102,15,56,222,232
+	movups	64(%r11),%xmm0
+	jmp	.Locb_dec_loop4
+
+.align	32
+.Locb_dec_loop4:
+.byte	102,15,56,222,209
+.byte	102,15,56,222,217
+.byte	102,15,56,222,225
+.byte	102,15,56,222,233
+	movups	(%rcx,%rax,1),%xmm1
+	addq	$32,%rax
+
+.byte	102,15,56,222,208
+.byte	102,15,56,222,216
+.byte	102,15,56,222,224
+.byte	102,15,56,222,232
+	movups	-16(%rcx,%rax,1),%xmm0
+	jnz	.Locb_dec_loop4
+
+.byte	102,15,56,222,209
+.byte	102,15,56,222,217
+.byte	102,15,56,222,225
+.byte	102,15,56,222,233
+	movups	16(%r11),%xmm1
+	movq	%r10,%rax
+
+.byte	102,65,15,56,223,210
+.byte	102,65,15,56,223,219
+.byte	102,65,15,56,223,228
+.byte	102,65,15,56,223,237
+	.byte	0xf3,0xc3
+.size	__ocb_decrypt4,.-__ocb_decrypt4
+
+.type	__ocb_decrypt1,@function
+.align	32
+__ocb_decrypt1:
+	pxor	%xmm15,%xmm7
+	pxor	%xmm9,%xmm7
+	pxor	%xmm7,%xmm2
+	movups	32(%r11),%xmm0
+
+.byte	102,15,56,222,209
+	movups	48(%r11),%xmm1
+	pxor	%xmm9,%xmm7
+
+.byte	102,15,56,222,208
+	movups	64(%r11),%xmm0
+	jmp	.Locb_dec_loop1
+
+.align	32
+.Locb_dec_loop1:
+.byte	102,15,56,222,209
+	movups	(%rcx,%rax,1),%xmm1
+	addq	$32,%rax
+
+.byte	102,15,56,222,208
+	movups	-16(%rcx,%rax,1),%xmm0
+	jnz	.Locb_dec_loop1
+
+.byte	102,15,56,222,209
+	movups	16(%r11),%xmm1
+	movq	%r10,%rax
+
+.byte	102,15,56,223,215
+	.byte	0xf3,0xc3
+.size	__ocb_decrypt1,.-__ocb_decrypt1
 .globl	aesni_cbc_encrypt
 .hidden aesni_cbc_encrypt
 .type	aesni_cbc_encrypt,@function
@@ -2638,14 +3451,14 @@
 	jmp	.Lcbc_ret
 .align	16
 .Lcbc_decrypt_bulk:
-	leaq	(%rsp),%rax
+	leaq	(%rsp),%r11
 	pushq	%rbp
 	subq	$16,%rsp
 	andq	$-16,%rsp
-	leaq	-8(%rax),%rbp
+	movq	%rcx,%rbp
 	movups	(%r8),%xmm10
 	movl	%r10d,%eax
-	cmpq	$80,%rdx
+	cmpq	$0x50,%rdx
 	jbe	.Lcbc_dec_tail
 
 	movups	(%rcx),%xmm0
@@ -2661,14 +3474,14 @@
 	movdqu	80(%rdi),%xmm7
 	movdqa	%xmm6,%xmm15
 	movl	OPENSSL_ia32cap_P+4(%rip),%r9d
-	cmpq	$112,%rdx
+	cmpq	$0x70,%rdx
 	jbe	.Lcbc_dec_six_or_seven
 
 	andl	$71303168,%r9d
-	subq	$80,%rdx
+	subq	$0x50,%rdx
 	cmpl	$4194304,%r9d
 	je	.Lcbc_dec_loop6_enter
-	subq	$32,%rdx
+	subq	$0x20,%rdx
 	leaq	112(%rcx),%rcx
 	jmp	.Lcbc_dec_loop8_enter
 .align	16
@@ -2682,8 +3495,8 @@
 	pxor	%xmm0,%xmm3
 	movups	16-112(%rcx),%xmm1
 	pxor	%xmm0,%xmm4
-	xorq	%r11,%r11
-	cmpq	$112,%rdx
+	movq	$-1,%rbp
+	cmpq	$0x70,%rdx
 	pxor	%xmm0,%xmm5
 	pxor	%xmm0,%xmm6
 	pxor	%xmm0,%xmm7
@@ -2698,10 +3511,10 @@
 .byte	102,15,56,222,241
 .byte	102,15,56,222,249
 .byte	102,68,15,56,222,193
-	setnc	%r11b
-	shlq	$7,%r11
+	adcq	$0,%rbp
+	andq	$128,%rbp
 .byte	102,68,15,56,222,201
-	addq	%rdi,%r11
+	addq	%rdi,%rbp
 	movups	48-112(%rcx),%xmm1
 .byte	102,15,56,222,208
 .byte	102,15,56,222,216
@@ -2839,18 +3652,18 @@
 	movdqu	112(%rdi),%xmm0
 .byte	102,65,15,56,223,228
 	leaq	128(%rdi),%rdi
-	movdqu	0(%r11),%xmm11
+	movdqu	0(%rbp),%xmm11
 .byte	102,65,15,56,223,237
 .byte	102,65,15,56,223,246
-	movdqu	16(%r11),%xmm12
-	movdqu	32(%r11),%xmm13
+	movdqu	16(%rbp),%xmm12
+	movdqu	32(%rbp),%xmm13
 .byte	102,65,15,56,223,255
 .byte	102,68,15,56,223,193
-	movdqu	48(%r11),%xmm14
-	movdqu	64(%r11),%xmm15
+	movdqu	48(%rbp),%xmm14
+	movdqu	64(%rbp),%xmm15
 .byte	102,69,15,56,223,202
 	movdqa	%xmm0,%xmm10
-	movdqu	80(%r11),%xmm1
+	movdqu	80(%rbp),%xmm1
 	movups	-112(%rcx),%xmm0
 
 	movups	%xmm2,(%rsi)
@@ -2868,21 +3681,21 @@
 	movups	%xmm8,96(%rsi)
 	leaq	112(%rsi),%rsi
 
-	subq	$128,%rdx
+	subq	$0x80,%rdx
 	ja	.Lcbc_dec_loop8
 
 	movaps	%xmm9,%xmm2
 	leaq	-112(%rcx),%rcx
-	addq	$112,%rdx
+	addq	$0x70,%rdx
 	jle	.Lcbc_dec_clear_tail_collected
 	movups	%xmm9,(%rsi)
 	leaq	16(%rsi),%rsi
-	cmpq	$80,%rdx
+	cmpq	$0x50,%rdx
 	jbe	.Lcbc_dec_tail
 
 	movaps	%xmm11,%xmm2
 .Lcbc_dec_six_or_seven:
-	cmpq	$96,%rdx
+	cmpq	$0x60,%rdx
 	ja	.Lcbc_dec_seven
 
 	movaps	%xmm7,%xmm8
@@ -2969,39 +3782,39 @@
 	pxor	%xmm13,%xmm5
 	movdqu	%xmm4,32(%rsi)
 	pxor	%xmm14,%xmm6
-	movq	%r11,%rcx
+	movq	%rbp,%rcx
 	movdqu	%xmm5,48(%rsi)
 	pxor	%xmm15,%xmm7
 	movl	%r10d,%eax
 	movdqu	%xmm6,64(%rsi)
 	leaq	80(%rsi),%rsi
-	subq	$96,%rdx
+	subq	$0x60,%rdx
 	ja	.Lcbc_dec_loop6
 
 	movdqa	%xmm7,%xmm2
-	addq	$80,%rdx
+	addq	$0x50,%rdx
 	jle	.Lcbc_dec_clear_tail_collected
 	movups	%xmm7,(%rsi)
 	leaq	16(%rsi),%rsi
 
 .Lcbc_dec_tail:
 	movups	(%rdi),%xmm2
-	subq	$16,%rdx
+	subq	$0x10,%rdx
 	jbe	.Lcbc_dec_one
 
 	movups	16(%rdi),%xmm3
 	movaps	%xmm2,%xmm11
-	subq	$16,%rdx
+	subq	$0x10,%rdx
 	jbe	.Lcbc_dec_two
 
 	movups	32(%rdi),%xmm4
 	movaps	%xmm3,%xmm12
-	subq	$16,%rdx
+	subq	$0x10,%rdx
 	jbe	.Lcbc_dec_three
 
 	movups	48(%rdi),%xmm5
 	movaps	%xmm4,%xmm13
-	subq	$16,%rdx
+	subq	$0x10,%rdx
 	jbe	.Lcbc_dec_four
 
 	movups	64(%rdi),%xmm6
@@ -3026,7 +3839,7 @@
 	movdqa	%xmm6,%xmm2
 	pxor	%xmm6,%xmm6
 	pxor	%xmm7,%xmm7
-	subq	$16,%rdx
+	subq	$0x10,%rdx
 	jmp	.Lcbc_dec_tail_collected
 
 .align	16
@@ -3122,8 +3935,8 @@
 .Lcbc_dec_ret:
 	xorps	%xmm0,%xmm0
 	pxor	%xmm1,%xmm1
-	leaq	(%rbp),%rsp
-	popq	%rbp
+	movq	-8(%r11),%rbp
+	leaq	(%r11),%rsp
 .Lcbc_ret:
 	.byte	0xf3,0xc3
 .size	aesni_cbc_encrypt,.-aesni_cbc_encrypt
@@ -3345,7 +4158,7 @@
 	pslldq	$4,%xmm0
 	pxor	%xmm3,%xmm0
 
-	pshufd	$255,%xmm0,%xmm3
+	pshufd	$0xff,%xmm0,%xmm3
 	pxor	%xmm1,%xmm3
 	pslldq	$4,%xmm1
 	pxor	%xmm1,%xmm3
@@ -3432,7 +4245,7 @@
 	decl	%r10d
 	jz	.Ldone_key256
 
-	pshufd	$255,%xmm0,%xmm2
+	pshufd	$0xff,%xmm0,%xmm2
 	pxor	%xmm3,%xmm3
 .byte	102,15,56,221,211
 
diff --git a/linux-x86_64/crypto/aes/bsaes-x86_64.S b/linux-x86_64/crypto/aes/bsaes-x86_64.S
index 8cfa4df..3f3c73b 100644
--- a/linux-x86_64/crypto/aes/bsaes-x86_64.S
+++ b/linux-x86_64/crypto/aes/bsaes-x86_64.S
@@ -327,45 +327,45 @@
 	pxor	%xmm2,%xmm5
 	decl	%r10d
 	jl	.Lenc_done
-	pshufd	$147,%xmm15,%xmm7
-	pshufd	$147,%xmm0,%xmm8
+	pshufd	$0x93,%xmm15,%xmm7
+	pshufd	$0x93,%xmm0,%xmm8
 	pxor	%xmm7,%xmm15
-	pshufd	$147,%xmm3,%xmm9
+	pshufd	$0x93,%xmm3,%xmm9
 	pxor	%xmm8,%xmm0
-	pshufd	$147,%xmm5,%xmm10
+	pshufd	$0x93,%xmm5,%xmm10
 	pxor	%xmm9,%xmm3
-	pshufd	$147,%xmm2,%xmm11
+	pshufd	$0x93,%xmm2,%xmm11
 	pxor	%xmm10,%xmm5
-	pshufd	$147,%xmm6,%xmm12
+	pshufd	$0x93,%xmm6,%xmm12
 	pxor	%xmm11,%xmm2
-	pshufd	$147,%xmm1,%xmm13
+	pshufd	$0x93,%xmm1,%xmm13
 	pxor	%xmm12,%xmm6
-	pshufd	$147,%xmm4,%xmm14
+	pshufd	$0x93,%xmm4,%xmm14
 	pxor	%xmm13,%xmm1
 	pxor	%xmm14,%xmm4
 
 	pxor	%xmm15,%xmm8
 	pxor	%xmm4,%xmm7
 	pxor	%xmm4,%xmm8
-	pshufd	$78,%xmm15,%xmm15
+	pshufd	$0x4E,%xmm15,%xmm15
 	pxor	%xmm0,%xmm9
-	pshufd	$78,%xmm0,%xmm0
+	pshufd	$0x4E,%xmm0,%xmm0
 	pxor	%xmm2,%xmm12
 	pxor	%xmm7,%xmm15
 	pxor	%xmm6,%xmm13
 	pxor	%xmm8,%xmm0
 	pxor	%xmm5,%xmm11
-	pshufd	$78,%xmm2,%xmm7
+	pshufd	$0x4E,%xmm2,%xmm7
 	pxor	%xmm1,%xmm14
-	pshufd	$78,%xmm6,%xmm8
+	pshufd	$0x4E,%xmm6,%xmm8
 	pxor	%xmm3,%xmm10
-	pshufd	$78,%xmm5,%xmm2
+	pshufd	$0x4E,%xmm5,%xmm2
 	pxor	%xmm4,%xmm10
-	pshufd	$78,%xmm4,%xmm6
+	pshufd	$0x4E,%xmm4,%xmm6
 	pxor	%xmm4,%xmm11
-	pshufd	$78,%xmm1,%xmm5
+	pshufd	$0x4E,%xmm1,%xmm5
 	pxor	%xmm11,%xmm7
-	pshufd	$78,%xmm3,%xmm1
+	pshufd	$0x4E,%xmm3,%xmm1
 	pxor	%xmm12,%xmm8
 	pxor	%xmm10,%xmm2
 	pxor	%xmm14,%xmm6
@@ -799,24 +799,24 @@
 	decl	%r10d
 	jl	.Ldec_done
 
-	pshufd	$78,%xmm15,%xmm7
-	pshufd	$78,%xmm2,%xmm13
+	pshufd	$0x4E,%xmm15,%xmm7
+	pshufd	$0x4E,%xmm2,%xmm13
 	pxor	%xmm15,%xmm7
-	pshufd	$78,%xmm4,%xmm14
+	pshufd	$0x4E,%xmm4,%xmm14
 	pxor	%xmm2,%xmm13
-	pshufd	$78,%xmm0,%xmm8
+	pshufd	$0x4E,%xmm0,%xmm8
 	pxor	%xmm4,%xmm14
-	pshufd	$78,%xmm5,%xmm9
+	pshufd	$0x4E,%xmm5,%xmm9
 	pxor	%xmm0,%xmm8
-	pshufd	$78,%xmm3,%xmm10
+	pshufd	$0x4E,%xmm3,%xmm10
 	pxor	%xmm5,%xmm9
 	pxor	%xmm13,%xmm15
 	pxor	%xmm13,%xmm0
-	pshufd	$78,%xmm1,%xmm11
+	pshufd	$0x4E,%xmm1,%xmm11
 	pxor	%xmm3,%xmm10
 	pxor	%xmm7,%xmm5
 	pxor	%xmm8,%xmm3
-	pshufd	$78,%xmm6,%xmm12
+	pshufd	$0x4E,%xmm6,%xmm12
 	pxor	%xmm1,%xmm11
 	pxor	%xmm14,%xmm0
 	pxor	%xmm9,%xmm1
@@ -830,45 +830,45 @@
 	pxor	%xmm14,%xmm1
 	pxor	%xmm14,%xmm6
 	pxor	%xmm12,%xmm4
-	pshufd	$147,%xmm15,%xmm7
-	pshufd	$147,%xmm0,%xmm8
+	pshufd	$0x93,%xmm15,%xmm7
+	pshufd	$0x93,%xmm0,%xmm8
 	pxor	%xmm7,%xmm15
-	pshufd	$147,%xmm5,%xmm9
+	pshufd	$0x93,%xmm5,%xmm9
 	pxor	%xmm8,%xmm0
-	pshufd	$147,%xmm3,%xmm10
+	pshufd	$0x93,%xmm3,%xmm10
 	pxor	%xmm9,%xmm5
-	pshufd	$147,%xmm1,%xmm11
+	pshufd	$0x93,%xmm1,%xmm11
 	pxor	%xmm10,%xmm3
-	pshufd	$147,%xmm6,%xmm12
+	pshufd	$0x93,%xmm6,%xmm12
 	pxor	%xmm11,%xmm1
-	pshufd	$147,%xmm2,%xmm13
+	pshufd	$0x93,%xmm2,%xmm13
 	pxor	%xmm12,%xmm6
-	pshufd	$147,%xmm4,%xmm14
+	pshufd	$0x93,%xmm4,%xmm14
 	pxor	%xmm13,%xmm2
 	pxor	%xmm14,%xmm4
 
 	pxor	%xmm15,%xmm8
 	pxor	%xmm4,%xmm7
 	pxor	%xmm4,%xmm8
-	pshufd	$78,%xmm15,%xmm15
+	pshufd	$0x4E,%xmm15,%xmm15
 	pxor	%xmm0,%xmm9
-	pshufd	$78,%xmm0,%xmm0
+	pshufd	$0x4E,%xmm0,%xmm0
 	pxor	%xmm1,%xmm12
 	pxor	%xmm7,%xmm15
 	pxor	%xmm6,%xmm13
 	pxor	%xmm8,%xmm0
 	pxor	%xmm3,%xmm11
-	pshufd	$78,%xmm1,%xmm7
+	pshufd	$0x4E,%xmm1,%xmm7
 	pxor	%xmm2,%xmm14
-	pshufd	$78,%xmm6,%xmm8
+	pshufd	$0x4E,%xmm6,%xmm8
 	pxor	%xmm5,%xmm10
-	pshufd	$78,%xmm3,%xmm1
+	pshufd	$0x4E,%xmm3,%xmm1
 	pxor	%xmm4,%xmm10
-	pshufd	$78,%xmm4,%xmm6
+	pshufd	$0x4E,%xmm4,%xmm6
 	pxor	%xmm4,%xmm11
-	pshufd	$78,%xmm2,%xmm3
+	pshufd	$0x4E,%xmm2,%xmm3
 	pxor	%xmm11,%xmm7
-	pshufd	$78,%xmm5,%xmm2
+	pshufd	$0x4E,%xmm5,%xmm2
 	pxor	%xmm12,%xmm8
 	pxor	%xmm1,%xmm10
 	pxor	%xmm14,%xmm6
@@ -1305,15 +1305,14 @@
 	cmpq	%rax,%rbp
 	ja	.Lcbc_dec_bzero
 
-	leaq	(%rbp),%rsp
-	movq	72(%rsp),%r15
-	movq	80(%rsp),%r14
-	movq	88(%rsp),%r13
-	movq	96(%rsp),%r12
-	movq	104(%rsp),%rbx
-	movq	112(%rsp),%rax
-	leaq	120(%rsp),%rsp
-	movq	%rax,%rbp
+	leaq	120(%rbp),%rax
+	movq	-48(%rax),%r15
+	movq	-40(%rax),%r14
+	movq	-32(%rax),%r13
+	movq	-24(%rax),%r12
+	movq	-16(%rax),%rbx
+	movq	-8(%rax),%rbp
+	leaq	(%rax),%rsp
 .Lcbc_dec_epilogue:
 	.byte	0xf3,0xc3
 .size	bsaes_cbc_encrypt,.-bsaes_cbc_encrypt
@@ -1506,15 +1505,14 @@
 	cmpq	%rax,%rbp
 	ja	.Lctr_enc_bzero
 
-	leaq	(%rbp),%rsp
-	movq	72(%rsp),%r15
-	movq	80(%rsp),%r14
-	movq	88(%rsp),%r13
-	movq	96(%rsp),%r12
-	movq	104(%rsp),%rbx
-	movq	112(%rsp),%rax
-	leaq	120(%rsp),%rsp
-	movq	%rax,%rbp
+	leaq	120(%rbp),%rax
+	movq	-48(%rax),%r15
+	movq	-40(%rax),%r14
+	movq	-32(%rax),%r13
+	movq	-24(%rax),%r12
+	movq	-16(%rax),%rbx
+	movq	-8(%rax),%rbp
+	leaq	(%rax),%rsp
 .Lctr_enc_epilogue:
 	.byte	0xf3,0xc3
 .size	bsaes_ctr32_encrypt_blocks,.-bsaes_ctr32_encrypt_blocks
@@ -1559,20 +1557,20 @@
 	movdqa	%xmm7,(%rax)
 
 	andq	$-16,%r14
-	subq	$128,%rsp
+	subq	$0x80,%rsp
 	movdqa	32(%rbp),%xmm6
 
 	pxor	%xmm14,%xmm14
 	movdqa	.Lxts_magic(%rip),%xmm12
 	pcmpgtd	%xmm6,%xmm14
 
-	subq	$128,%r14
+	subq	$0x80,%r14
 	jc	.Lxts_enc_short
 	jmp	.Lxts_enc_loop
 
 .align	16
 .Lxts_enc_loop:
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm15
 	movdqa	%xmm6,0(%rsp)
@@ -1580,7 +1578,7 @@
 	pand	%xmm12,%xmm13
 	pcmpgtd	%xmm6,%xmm14
 	pxor	%xmm13,%xmm6
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm0
 	movdqa	%xmm6,16(%rsp)
@@ -1589,7 +1587,7 @@
 	pcmpgtd	%xmm6,%xmm14
 	pxor	%xmm13,%xmm6
 	movdqu	0(%r12),%xmm7
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm1
 	movdqa	%xmm6,32(%rsp)
@@ -1599,7 +1597,7 @@
 	pxor	%xmm13,%xmm6
 	movdqu	16(%r12),%xmm8
 	pxor	%xmm7,%xmm15
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm2
 	movdqa	%xmm6,48(%rsp)
@@ -1609,7 +1607,7 @@
 	pxor	%xmm13,%xmm6
 	movdqu	32(%r12),%xmm9
 	pxor	%xmm8,%xmm0
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm3
 	movdqa	%xmm6,64(%rsp)
@@ -1619,7 +1617,7 @@
 	pxor	%xmm13,%xmm6
 	movdqu	48(%r12),%xmm10
 	pxor	%xmm9,%xmm1
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm4
 	movdqa	%xmm6,80(%rsp)
@@ -1629,7 +1627,7 @@
 	pxor	%xmm13,%xmm6
 	movdqu	64(%r12),%xmm11
 	pxor	%xmm10,%xmm2
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm5
 	movdqa	%xmm6,96(%rsp)
@@ -1673,20 +1671,20 @@
 	pxor	%xmm14,%xmm14
 	movdqa	.Lxts_magic(%rip),%xmm12
 	pcmpgtd	%xmm6,%xmm14
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	paddq	%xmm6,%xmm6
 	pand	%xmm12,%xmm13
 	pcmpgtd	%xmm6,%xmm14
 	pxor	%xmm13,%xmm6
 
-	subq	$128,%r14
+	subq	$0x80,%r14
 	jnc	.Lxts_enc_loop
 
 .Lxts_enc_short:
-	addq	$128,%r14
+	addq	$0x80,%r14
 	jz	.Lxts_enc_done
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm15
 	movdqa	%xmm6,0(%rsp)
@@ -1694,7 +1692,7 @@
 	pand	%xmm12,%xmm13
 	pcmpgtd	%xmm6,%xmm14
 	pxor	%xmm13,%xmm6
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm0
 	movdqa	%xmm6,16(%rsp)
@@ -1705,7 +1703,7 @@
 	movdqu	0(%r12),%xmm7
 	cmpq	$16,%r14
 	je	.Lxts_enc_1
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm1
 	movdqa	%xmm6,32(%rsp)
@@ -1717,7 +1715,7 @@
 	cmpq	$32,%r14
 	je	.Lxts_enc_2
 	pxor	%xmm7,%xmm15
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm2
 	movdqa	%xmm6,48(%rsp)
@@ -1729,7 +1727,7 @@
 	cmpq	$48,%r14
 	je	.Lxts_enc_3
 	pxor	%xmm8,%xmm0
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm3
 	movdqa	%xmm6,64(%rsp)
@@ -1741,7 +1739,7 @@
 	cmpq	$64,%r14
 	je	.Lxts_enc_4
 	pxor	%xmm9,%xmm1
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm4
 	movdqa	%xmm6,80(%rsp)
@@ -1753,7 +1751,7 @@
 	cmpq	$80,%r14
 	je	.Lxts_enc_5
 	pxor	%xmm10,%xmm2
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm5
 	movdqa	%xmm6,96(%rsp)
@@ -1958,15 +1956,14 @@
 	cmpq	%rax,%rbp
 	ja	.Lxts_enc_bzero
 
-	leaq	(%rbp),%rsp
-	movq	72(%rsp),%r15
-	movq	80(%rsp),%r14
-	movq	88(%rsp),%r13
-	movq	96(%rsp),%r12
-	movq	104(%rsp),%rbx
-	movq	112(%rsp),%rax
-	leaq	120(%rsp),%rsp
-	movq	%rax,%rbp
+	leaq	120(%rbp),%rax
+	movq	-48(%rax),%r15
+	movq	-40(%rax),%r14
+	movq	-32(%rax),%r13
+	movq	-24(%rax),%r12
+	movq	-16(%rax),%rbx
+	movq	-8(%rax),%rbp
+	leaq	(%rax),%rsp
 .Lxts_enc_epilogue:
 	.byte	0xf3,0xc3
 .size	bsaes_xts_encrypt,.-bsaes_xts_encrypt
@@ -2019,20 +2016,20 @@
 	shlq	$4,%rax
 	subq	%rax,%r14
 
-	subq	$128,%rsp
+	subq	$0x80,%rsp
 	movdqa	32(%rbp),%xmm6
 
 	pxor	%xmm14,%xmm14
 	movdqa	.Lxts_magic(%rip),%xmm12
 	pcmpgtd	%xmm6,%xmm14
 
-	subq	$128,%r14
+	subq	$0x80,%r14
 	jc	.Lxts_dec_short
 	jmp	.Lxts_dec_loop
 
 .align	16
 .Lxts_dec_loop:
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm15
 	movdqa	%xmm6,0(%rsp)
@@ -2040,7 +2037,7 @@
 	pand	%xmm12,%xmm13
 	pcmpgtd	%xmm6,%xmm14
 	pxor	%xmm13,%xmm6
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm0
 	movdqa	%xmm6,16(%rsp)
@@ -2049,7 +2046,7 @@
 	pcmpgtd	%xmm6,%xmm14
 	pxor	%xmm13,%xmm6
 	movdqu	0(%r12),%xmm7
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm1
 	movdqa	%xmm6,32(%rsp)
@@ -2059,7 +2056,7 @@
 	pxor	%xmm13,%xmm6
 	movdqu	16(%r12),%xmm8
 	pxor	%xmm7,%xmm15
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm2
 	movdqa	%xmm6,48(%rsp)
@@ -2069,7 +2066,7 @@
 	pxor	%xmm13,%xmm6
 	movdqu	32(%r12),%xmm9
 	pxor	%xmm8,%xmm0
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm3
 	movdqa	%xmm6,64(%rsp)
@@ -2079,7 +2076,7 @@
 	pxor	%xmm13,%xmm6
 	movdqu	48(%r12),%xmm10
 	pxor	%xmm9,%xmm1
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm4
 	movdqa	%xmm6,80(%rsp)
@@ -2089,7 +2086,7 @@
 	pxor	%xmm13,%xmm6
 	movdqu	64(%r12),%xmm11
 	pxor	%xmm10,%xmm2
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm5
 	movdqa	%xmm6,96(%rsp)
@@ -2133,20 +2130,20 @@
 	pxor	%xmm14,%xmm14
 	movdqa	.Lxts_magic(%rip),%xmm12
 	pcmpgtd	%xmm6,%xmm14
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	paddq	%xmm6,%xmm6
 	pand	%xmm12,%xmm13
 	pcmpgtd	%xmm6,%xmm14
 	pxor	%xmm13,%xmm6
 
-	subq	$128,%r14
+	subq	$0x80,%r14
 	jnc	.Lxts_dec_loop
 
 .Lxts_dec_short:
-	addq	$128,%r14
+	addq	$0x80,%r14
 	jz	.Lxts_dec_done
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm15
 	movdqa	%xmm6,0(%rsp)
@@ -2154,7 +2151,7 @@
 	pand	%xmm12,%xmm13
 	pcmpgtd	%xmm6,%xmm14
 	pxor	%xmm13,%xmm6
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm0
 	movdqa	%xmm6,16(%rsp)
@@ -2165,7 +2162,7 @@
 	movdqu	0(%r12),%xmm7
 	cmpq	$16,%r14
 	je	.Lxts_dec_1
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm1
 	movdqa	%xmm6,32(%rsp)
@@ -2177,7 +2174,7 @@
 	cmpq	$32,%r14
 	je	.Lxts_dec_2
 	pxor	%xmm7,%xmm15
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm2
 	movdqa	%xmm6,48(%rsp)
@@ -2189,7 +2186,7 @@
 	cmpq	$48,%r14
 	je	.Lxts_dec_3
 	pxor	%xmm8,%xmm0
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm3
 	movdqa	%xmm6,64(%rsp)
@@ -2201,7 +2198,7 @@
 	cmpq	$64,%r14
 	je	.Lxts_dec_4
 	pxor	%xmm9,%xmm1
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm4
 	movdqa	%xmm6,80(%rsp)
@@ -2213,7 +2210,7 @@
 	cmpq	$80,%r14
 	je	.Lxts_dec_5
 	pxor	%xmm10,%xmm2
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm5
 	movdqa	%xmm6,96(%rsp)
@@ -2390,7 +2387,7 @@
 	pxor	%xmm14,%xmm14
 	movdqa	.Lxts_magic(%rip),%xmm12
 	pcmpgtd	%xmm6,%xmm14
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	movdqa	%xmm6,%xmm5
 	paddq	%xmm6,%xmm6
 	pand	%xmm12,%xmm13
@@ -2437,15 +2434,14 @@
 	cmpq	%rax,%rbp
 	ja	.Lxts_dec_bzero
 
-	leaq	(%rbp),%rsp
-	movq	72(%rsp),%r15
-	movq	80(%rsp),%r14
-	movq	88(%rsp),%r13
-	movq	96(%rsp),%r12
-	movq	104(%rsp),%rbx
-	movq	112(%rsp),%rax
-	leaq	120(%rsp),%rsp
-	movq	%rax,%rbp
+	leaq	120(%rbp),%rax
+	movq	-48(%rax),%r15
+	movq	-40(%rax),%r14
+	movq	-32(%rax),%r13
+	movq	-24(%rax),%r12
+	movq	-16(%rax),%rbx
+	movq	-8(%rax),%rbp
+	leaq	(%rax),%rsp
 .Lxts_dec_epilogue:
 	.byte	0xf3,0xc3
 .size	bsaes_xts_decrypt,.-bsaes_xts_decrypt
diff --git a/linux-x86_64/crypto/aes/vpaes-x86_64.S b/linux-x86_64/crypto/aes/vpaes-x86_64.S
index 1d12424..4dfafa9 100644
--- a/linux-x86_64/crypto/aes/vpaes-x86_64.S
+++ b/linux-x86_64/crypto/aes/vpaes-x86_64.S
@@ -61,7 +61,7 @@
 	addq	$16,%r11
 	pxor	%xmm0,%xmm3
 .byte	102,15,56,0,193
-	andq	$48,%r11
+	andq	$0x30,%r11
 	subq	$1,%rax
 	pxor	%xmm3,%xmm0
 
@@ -121,10 +121,10 @@
 	pand	%xmm9,%xmm0
 .byte	102,15,56,0,208
 	movdqa	.Lk_dipt+16(%rip),%xmm0
-	xorq	$48,%r11
+	xorq	$0x30,%r11
 	leaq	.Lk_dsbd(%rip),%r10
 .byte	102,15,56,0,193
-	andq	$48,%r11
+	andq	$0x30,%r11
 	pxor	%xmm5,%xmm2
 	movdqa	.Lk_mc_forward+48(%rip),%xmm5
 	pxor	%xmm2,%xmm0
@@ -243,7 +243,7 @@
 	movdqa	(%r8,%r10,1),%xmm1
 .byte	102,15,56,0,217
 	movdqu	%xmm3,(%rdx)
-	xorq	$48,%r8
+	xorq	$0x30,%r8
 
 .Lschedule_go:
 	cmpl	$192,%esi
@@ -333,7 +333,7 @@
 	call	_vpaes_schedule_mangle
 
 
-	pshufd	$255,%xmm0,%xmm0
+	pshufd	$0xFF,%xmm0,%xmm0
 	movdqa	%xmm7,%xmm5
 	movdqa	%xmm6,%xmm7
 	call	_vpaes_schedule_low_round
@@ -400,8 +400,8 @@
 .type	_vpaes_schedule_192_smear,@function
 .align	16
 _vpaes_schedule_192_smear:
-	pshufd	$128,%xmm6,%xmm1
-	pshufd	$254,%xmm7,%xmm0
+	pshufd	$0x80,%xmm6,%xmm1
+	pshufd	$0xFE,%xmm7,%xmm0
 	pxor	%xmm1,%xmm6
 	pxor	%xmm1,%xmm1
 	pxor	%xmm0,%xmm6
@@ -438,7 +438,7 @@
 	pxor	%xmm1,%xmm7
 
 
-	pshufd	$255,%xmm0,%xmm0
+	pshufd	$0xFF,%xmm0,%xmm0
 .byte	102,15,58,15,192,1
 
 
@@ -597,7 +597,7 @@
 	movdqa	(%r8,%r10,1),%xmm1
 .byte	102,15,56,0,217
 	addq	$-16,%r8
-	andq	$48,%r8
+	andq	$0x30,%r8
 	movdqu	%xmm3,(%rdx)
 	.byte	0xf3,0xc3
 .size	_vpaes_schedule_mangle,.-_vpaes_schedule_mangle
@@ -616,7 +616,7 @@
 	movl	%eax,240(%rdx)
 
 	movl	$0,%ecx
-	movl	$48,%r8d
+	movl	$0x30,%r8d
 	call	_vpaes_schedule_core
 	xorl	%eax,%eax
 	.byte	0xf3,0xc3
diff --git a/linux-x86_64/crypto/bn/rsaz-avx2.S b/linux-x86_64/crypto/bn/rsaz-avx2.S
index cd334d9..db078a9 100644
--- a/linux-x86_64/crypto/bn/rsaz-avx2.S
+++ b/linux-x86_64/crypto/bn/rsaz-avx2.S
@@ -1,34 +1,1747 @@
 #if defined(__x86_64__)
 .text	
 
+.globl	rsaz_1024_sqr_avx2
+.hidden rsaz_1024_sqr_avx2
+.type	rsaz_1024_sqr_avx2,@function
+.align	64
+rsaz_1024_sqr_avx2:
+.cfi_startproc	
+	leaq	(%rsp),%rax
+.cfi_def_cfa_register	%rax
+	pushq	%rbx
+.cfi_offset	%rbx,-16
+	pushq	%rbp
+.cfi_offset	%rbp,-24
+	pushq	%r12
+.cfi_offset	%r12,-32
+	pushq	%r13
+.cfi_offset	%r13,-40
+	pushq	%r14
+.cfi_offset	%r14,-48
+	pushq	%r15
+.cfi_offset	%r15,-56
+	vzeroupper
+	movq	%rax,%rbp
+.cfi_def_cfa_register	%rbp
+	movq	%rdx,%r13
+	subq	$832,%rsp
+	movq	%r13,%r15
+	subq	$-128,%rdi
+	subq	$-128,%rsi
+	subq	$-128,%r13
+
+	andq	$4095,%r15
+	addq	$320,%r15
+	shrq	$12,%r15
+	vpxor	%ymm9,%ymm9,%ymm9
+	jz	.Lsqr_1024_no_n_copy
+
+
+
+
+
+	subq	$320,%rsp
+	vmovdqu	0-128(%r13),%ymm0
+	andq	$-2048,%rsp
+	vmovdqu	32-128(%r13),%ymm1
+	vmovdqu	64-128(%r13),%ymm2
+	vmovdqu	96-128(%r13),%ymm3
+	vmovdqu	128-128(%r13),%ymm4
+	vmovdqu	160-128(%r13),%ymm5
+	vmovdqu	192-128(%r13),%ymm6
+	vmovdqu	224-128(%r13),%ymm7
+	vmovdqu	256-128(%r13),%ymm8
+	leaq	832+128(%rsp),%r13
+	vmovdqu	%ymm0,0-128(%r13)
+	vmovdqu	%ymm1,32-128(%r13)
+	vmovdqu	%ymm2,64-128(%r13)
+	vmovdqu	%ymm3,96-128(%r13)
+	vmovdqu	%ymm4,128-128(%r13)
+	vmovdqu	%ymm5,160-128(%r13)
+	vmovdqu	%ymm6,192-128(%r13)
+	vmovdqu	%ymm7,224-128(%r13)
+	vmovdqu	%ymm8,256-128(%r13)
+	vmovdqu	%ymm9,288-128(%r13)
+
+.Lsqr_1024_no_n_copy:
+	andq	$-1024,%rsp
+
+	vmovdqu	32-128(%rsi),%ymm1
+	vmovdqu	64-128(%rsi),%ymm2
+	vmovdqu	96-128(%rsi),%ymm3
+	vmovdqu	128-128(%rsi),%ymm4
+	vmovdqu	160-128(%rsi),%ymm5
+	vmovdqu	192-128(%rsi),%ymm6
+	vmovdqu	224-128(%rsi),%ymm7
+	vmovdqu	256-128(%rsi),%ymm8
+
+	leaq	192(%rsp),%rbx
+	vpbroadcastq	.Land_mask(%rip),%ymm15
+	jmp	.LOOP_GRANDE_SQR_1024
+
+.align	32
+.LOOP_GRANDE_SQR_1024:
+	leaq	576+128(%rsp),%r9
+	leaq	448(%rsp),%r12
+
+
+
+
+	vpaddq	%ymm1,%ymm1,%ymm1
+	vpbroadcastq	0-128(%rsi),%ymm10
+	vpaddq	%ymm2,%ymm2,%ymm2
+	vmovdqa	%ymm1,0-128(%r9)
+	vpaddq	%ymm3,%ymm3,%ymm3
+	vmovdqa	%ymm2,32-128(%r9)
+	vpaddq	%ymm4,%ymm4,%ymm4
+	vmovdqa	%ymm3,64-128(%r9)
+	vpaddq	%ymm5,%ymm5,%ymm5
+	vmovdqa	%ymm4,96-128(%r9)
+	vpaddq	%ymm6,%ymm6,%ymm6
+	vmovdqa	%ymm5,128-128(%r9)
+	vpaddq	%ymm7,%ymm7,%ymm7
+	vmovdqa	%ymm6,160-128(%r9)
+	vpaddq	%ymm8,%ymm8,%ymm8
+	vmovdqa	%ymm7,192-128(%r9)
+	vpxor	%ymm9,%ymm9,%ymm9
+	vmovdqa	%ymm8,224-128(%r9)
+
+	vpmuludq	0-128(%rsi),%ymm10,%ymm0
+	vpbroadcastq	32-128(%rsi),%ymm11
+	vmovdqu	%ymm9,288-192(%rbx)
+	vpmuludq	%ymm10,%ymm1,%ymm1
+	vmovdqu	%ymm9,320-448(%r12)
+	vpmuludq	%ymm10,%ymm2,%ymm2
+	vmovdqu	%ymm9,352-448(%r12)
+	vpmuludq	%ymm10,%ymm3,%ymm3
+	vmovdqu	%ymm9,384-448(%r12)
+	vpmuludq	%ymm10,%ymm4,%ymm4
+	vmovdqu	%ymm9,416-448(%r12)
+	vpmuludq	%ymm10,%ymm5,%ymm5
+	vmovdqu	%ymm9,448-448(%r12)
+	vpmuludq	%ymm10,%ymm6,%ymm6
+	vmovdqu	%ymm9,480-448(%r12)
+	vpmuludq	%ymm10,%ymm7,%ymm7
+	vmovdqu	%ymm9,512-448(%r12)
+	vpmuludq	%ymm10,%ymm8,%ymm8
+	vpbroadcastq	64-128(%rsi),%ymm10
+	vmovdqu	%ymm9,544-448(%r12)
+
+	movq	%rsi,%r15
+	movl	$4,%r14d
+	jmp	.Lsqr_entry_1024
+.align	32
+.LOOP_SQR_1024:
+	vpbroadcastq	32-128(%r15),%ymm11
+	vpmuludq	0-128(%rsi),%ymm10,%ymm0
+	vpaddq	0-192(%rbx),%ymm0,%ymm0
+	vpmuludq	0-128(%r9),%ymm10,%ymm1
+	vpaddq	32-192(%rbx),%ymm1,%ymm1
+	vpmuludq	32-128(%r9),%ymm10,%ymm2
+	vpaddq	64-192(%rbx),%ymm2,%ymm2
+	vpmuludq	64-128(%r9),%ymm10,%ymm3
+	vpaddq	96-192(%rbx),%ymm3,%ymm3
+	vpmuludq	96-128(%r9),%ymm10,%ymm4
+	vpaddq	128-192(%rbx),%ymm4,%ymm4
+	vpmuludq	128-128(%r9),%ymm10,%ymm5
+	vpaddq	160-192(%rbx),%ymm5,%ymm5
+	vpmuludq	160-128(%r9),%ymm10,%ymm6
+	vpaddq	192-192(%rbx),%ymm6,%ymm6
+	vpmuludq	192-128(%r9),%ymm10,%ymm7
+	vpaddq	224-192(%rbx),%ymm7,%ymm7
+	vpmuludq	224-128(%r9),%ymm10,%ymm8
+	vpbroadcastq	64-128(%r15),%ymm10
+	vpaddq	256-192(%rbx),%ymm8,%ymm8
+.Lsqr_entry_1024:
+	vmovdqu	%ymm0,0-192(%rbx)
+	vmovdqu	%ymm1,32-192(%rbx)
+
+	vpmuludq	32-128(%rsi),%ymm11,%ymm12
+	vpaddq	%ymm12,%ymm2,%ymm2
+	vpmuludq	32-128(%r9),%ymm11,%ymm14
+	vpaddq	%ymm14,%ymm3,%ymm3
+	vpmuludq	64-128(%r9),%ymm11,%ymm13
+	vpaddq	%ymm13,%ymm4,%ymm4
+	vpmuludq	96-128(%r9),%ymm11,%ymm12
+	vpaddq	%ymm12,%ymm5,%ymm5
+	vpmuludq	128-128(%r9),%ymm11,%ymm14
+	vpaddq	%ymm14,%ymm6,%ymm6
+	vpmuludq	160-128(%r9),%ymm11,%ymm13
+	vpaddq	%ymm13,%ymm7,%ymm7
+	vpmuludq	192-128(%r9),%ymm11,%ymm12
+	vpaddq	%ymm12,%ymm8,%ymm8
+	vpmuludq	224-128(%r9),%ymm11,%ymm0
+	vpbroadcastq	96-128(%r15),%ymm11
+	vpaddq	288-192(%rbx),%ymm0,%ymm0
+
+	vmovdqu	%ymm2,64-192(%rbx)
+	vmovdqu	%ymm3,96-192(%rbx)
+
+	vpmuludq	64-128(%rsi),%ymm10,%ymm13
+	vpaddq	%ymm13,%ymm4,%ymm4
+	vpmuludq	64-128(%r9),%ymm10,%ymm12
+	vpaddq	%ymm12,%ymm5,%ymm5
+	vpmuludq	96-128(%r9),%ymm10,%ymm14
+	vpaddq	%ymm14,%ymm6,%ymm6
+	vpmuludq	128-128(%r9),%ymm10,%ymm13
+	vpaddq	%ymm13,%ymm7,%ymm7
+	vpmuludq	160-128(%r9),%ymm10,%ymm12
+	vpaddq	%ymm12,%ymm8,%ymm8
+	vpmuludq	192-128(%r9),%ymm10,%ymm14
+	vpaddq	%ymm14,%ymm0,%ymm0
+	vpmuludq	224-128(%r9),%ymm10,%ymm1
+	vpbroadcastq	128-128(%r15),%ymm10
+	vpaddq	320-448(%r12),%ymm1,%ymm1
+
+	vmovdqu	%ymm4,128-192(%rbx)
+	vmovdqu	%ymm5,160-192(%rbx)
+
+	vpmuludq	96-128(%rsi),%ymm11,%ymm12
+	vpaddq	%ymm12,%ymm6,%ymm6
+	vpmuludq	96-128(%r9),%ymm11,%ymm14
+	vpaddq	%ymm14,%ymm7,%ymm7
+	vpmuludq	128-128(%r9),%ymm11,%ymm13
+	vpaddq	%ymm13,%ymm8,%ymm8
+	vpmuludq	160-128(%r9),%ymm11,%ymm12
+	vpaddq	%ymm12,%ymm0,%ymm0
+	vpmuludq	192-128(%r9),%ymm11,%ymm14
+	vpaddq	%ymm14,%ymm1,%ymm1
+	vpmuludq	224-128(%r9),%ymm11,%ymm2
+	vpbroadcastq	160-128(%r15),%ymm11
+	vpaddq	352-448(%r12),%ymm2,%ymm2
+
+	vmovdqu	%ymm6,192-192(%rbx)
+	vmovdqu	%ymm7,224-192(%rbx)
+
+	vpmuludq	128-128(%rsi),%ymm10,%ymm12
+	vpaddq	%ymm12,%ymm8,%ymm8
+	vpmuludq	128-128(%r9),%ymm10,%ymm14
+	vpaddq	%ymm14,%ymm0,%ymm0
+	vpmuludq	160-128(%r9),%ymm10,%ymm13
+	vpaddq	%ymm13,%ymm1,%ymm1
+	vpmuludq	192-128(%r9),%ymm10,%ymm12
+	vpaddq	%ymm12,%ymm2,%ymm2
+	vpmuludq	224-128(%r9),%ymm10,%ymm3
+	vpbroadcastq	192-128(%r15),%ymm10
+	vpaddq	384-448(%r12),%ymm3,%ymm3
+
+	vmovdqu	%ymm8,256-192(%rbx)
+	vmovdqu	%ymm0,288-192(%rbx)
+	leaq	8(%rbx),%rbx
+
+	vpmuludq	160-128(%rsi),%ymm11,%ymm13
+	vpaddq	%ymm13,%ymm1,%ymm1
+	vpmuludq	160-128(%r9),%ymm11,%ymm12
+	vpaddq	%ymm12,%ymm2,%ymm2
+	vpmuludq	192-128(%r9),%ymm11,%ymm14
+	vpaddq	%ymm14,%ymm3,%ymm3
+	vpmuludq	224-128(%r9),%ymm11,%ymm4
+	vpbroadcastq	224-128(%r15),%ymm11
+	vpaddq	416-448(%r12),%ymm4,%ymm4
+
+	vmovdqu	%ymm1,320-448(%r12)
+	vmovdqu	%ymm2,352-448(%r12)
+
+	vpmuludq	192-128(%rsi),%ymm10,%ymm12
+	vpaddq	%ymm12,%ymm3,%ymm3
+	vpmuludq	192-128(%r9),%ymm10,%ymm14
+	vpbroadcastq	256-128(%r15),%ymm0
+	vpaddq	%ymm14,%ymm4,%ymm4
+	vpmuludq	224-128(%r9),%ymm10,%ymm5
+	vpbroadcastq	0+8-128(%r15),%ymm10
+	vpaddq	448-448(%r12),%ymm5,%ymm5
+
+	vmovdqu	%ymm3,384-448(%r12)
+	vmovdqu	%ymm4,416-448(%r12)
+	leaq	8(%r15),%r15
+
+	vpmuludq	224-128(%rsi),%ymm11,%ymm12
+	vpaddq	%ymm12,%ymm5,%ymm5
+	vpmuludq	224-128(%r9),%ymm11,%ymm6
+	vpaddq	480-448(%r12),%ymm6,%ymm6
+
+	vpmuludq	256-128(%rsi),%ymm0,%ymm7
+	vmovdqu	%ymm5,448-448(%r12)
+	vpaddq	512-448(%r12),%ymm7,%ymm7
+	vmovdqu	%ymm6,480-448(%r12)
+	vmovdqu	%ymm7,512-448(%r12)
+	leaq	8(%r12),%r12
+
+	decl	%r14d
+	jnz	.LOOP_SQR_1024
+
+	vmovdqu	256(%rsp),%ymm8
+	vmovdqu	288(%rsp),%ymm1
+	vmovdqu	320(%rsp),%ymm2
+	leaq	192(%rsp),%rbx
+
+	vpsrlq	$29,%ymm8,%ymm14
+	vpand	%ymm15,%ymm8,%ymm8
+	vpsrlq	$29,%ymm1,%ymm11
+	vpand	%ymm15,%ymm1,%ymm1
+
+	vpermq	$0x93,%ymm14,%ymm14
+	vpxor	%ymm9,%ymm9,%ymm9
+	vpermq	$0x93,%ymm11,%ymm11
+
+	vpblendd	$3,%ymm9,%ymm14,%ymm10
+	vpblendd	$3,%ymm14,%ymm11,%ymm14
+	vpaddq	%ymm10,%ymm8,%ymm8
+	vpblendd	$3,%ymm11,%ymm9,%ymm11
+	vpaddq	%ymm14,%ymm1,%ymm1
+	vpaddq	%ymm11,%ymm2,%ymm2
+	vmovdqu	%ymm1,288-192(%rbx)
+	vmovdqu	%ymm2,320-192(%rbx)
+
+	movq	(%rsp),%rax
+	movq	8(%rsp),%r10
+	movq	16(%rsp),%r11
+	movq	24(%rsp),%r12
+	vmovdqu	32(%rsp),%ymm1
+	vmovdqu	64-192(%rbx),%ymm2
+	vmovdqu	96-192(%rbx),%ymm3
+	vmovdqu	128-192(%rbx),%ymm4
+	vmovdqu	160-192(%rbx),%ymm5
+	vmovdqu	192-192(%rbx),%ymm6
+	vmovdqu	224-192(%rbx),%ymm7
+
+	movq	%rax,%r9
+	imull	%ecx,%eax
+	andl	$0x1fffffff,%eax
+	vmovd	%eax,%xmm12
+
+	movq	%rax,%rdx
+	imulq	-128(%r13),%rax
+	vpbroadcastq	%xmm12,%ymm12
+	addq	%rax,%r9
+	movq	%rdx,%rax
+	imulq	8-128(%r13),%rax
+	shrq	$29,%r9
+	addq	%rax,%r10
+	movq	%rdx,%rax
+	imulq	16-128(%r13),%rax
+	addq	%r9,%r10
+	addq	%rax,%r11
+	imulq	24-128(%r13),%rdx
+	addq	%rdx,%r12
+
+	movq	%r10,%rax
+	imull	%ecx,%eax
+	andl	$0x1fffffff,%eax
+
+	movl	$9,%r14d
+	jmp	.LOOP_REDUCE_1024
+
+.align	32
+.LOOP_REDUCE_1024:
+	vmovd	%eax,%xmm13
+	vpbroadcastq	%xmm13,%ymm13
+
+	vpmuludq	32-128(%r13),%ymm12,%ymm10
+	movq	%rax,%rdx
+	imulq	-128(%r13),%rax
+	vpaddq	%ymm10,%ymm1,%ymm1
+	addq	%rax,%r10
+	vpmuludq	64-128(%r13),%ymm12,%ymm14
+	movq	%rdx,%rax
+	imulq	8-128(%r13),%rax
+	vpaddq	%ymm14,%ymm2,%ymm2
+	vpmuludq	96-128(%r13),%ymm12,%ymm11
+.byte	0x67
+	addq	%rax,%r11
+.byte	0x67
+	movq	%rdx,%rax
+	imulq	16-128(%r13),%rax
+	shrq	$29,%r10
+	vpaddq	%ymm11,%ymm3,%ymm3
+	vpmuludq	128-128(%r13),%ymm12,%ymm10
+	addq	%rax,%r12
+	addq	%r10,%r11
+	vpaddq	%ymm10,%ymm4,%ymm4
+	vpmuludq	160-128(%r13),%ymm12,%ymm14
+	movq	%r11,%rax
+	imull	%ecx,%eax
+	vpaddq	%ymm14,%ymm5,%ymm5
+	vpmuludq	192-128(%r13),%ymm12,%ymm11
+	andl	$0x1fffffff,%eax
+	vpaddq	%ymm11,%ymm6,%ymm6
+	vpmuludq	224-128(%r13),%ymm12,%ymm10
+	vpaddq	%ymm10,%ymm7,%ymm7
+	vpmuludq	256-128(%r13),%ymm12,%ymm14
+	vmovd	%eax,%xmm12
+
+	vpaddq	%ymm14,%ymm8,%ymm8
+
+	vpbroadcastq	%xmm12,%ymm12
+
+	vpmuludq	32-8-128(%r13),%ymm13,%ymm11
+	vmovdqu	96-8-128(%r13),%ymm14
+	movq	%rax,%rdx
+	imulq	-128(%r13),%rax
+	vpaddq	%ymm11,%ymm1,%ymm1
+	vpmuludq	64-8-128(%r13),%ymm13,%ymm10
+	vmovdqu	128-8-128(%r13),%ymm11
+	addq	%rax,%r11
+	movq	%rdx,%rax
+	imulq	8-128(%r13),%rax
+	vpaddq	%ymm10,%ymm2,%ymm2
+	addq	%r12,%rax
+	shrq	$29,%r11
+	vpmuludq	%ymm13,%ymm14,%ymm14
+	vmovdqu	160-8-128(%r13),%ymm10
+	addq	%r11,%rax
+	vpaddq	%ymm14,%ymm3,%ymm3
+	vpmuludq	%ymm13,%ymm11,%ymm11
+	vmovdqu	192-8-128(%r13),%ymm14
+.byte	0x67
+	movq	%rax,%r12
+	imull	%ecx,%eax
+	vpaddq	%ymm11,%ymm4,%ymm4
+	vpmuludq	%ymm13,%ymm10,%ymm10
+.byte	0xc4,0x41,0x7e,0x6f,0x9d,0x58,0x00,0x00,0x00
+	andl	$0x1fffffff,%eax
+	vpaddq	%ymm10,%ymm5,%ymm5
+	vpmuludq	%ymm13,%ymm14,%ymm14
+	vmovdqu	256-8-128(%r13),%ymm10
+	vpaddq	%ymm14,%ymm6,%ymm6
+	vpmuludq	%ymm13,%ymm11,%ymm11
+	vmovdqu	288-8-128(%r13),%ymm9
+	vmovd	%eax,%xmm0
+	imulq	-128(%r13),%rax
+	vpaddq	%ymm11,%ymm7,%ymm7
+	vpmuludq	%ymm13,%ymm10,%ymm10
+	vmovdqu	32-16-128(%r13),%ymm14
+	vpbroadcastq	%xmm0,%ymm0
+	vpaddq	%ymm10,%ymm8,%ymm8
+	vpmuludq	%ymm13,%ymm9,%ymm9
+	vmovdqu	64-16-128(%r13),%ymm11
+	addq	%rax,%r12
+
+	vmovdqu	32-24-128(%r13),%ymm13
+	vpmuludq	%ymm12,%ymm14,%ymm14
+	vmovdqu	96-16-128(%r13),%ymm10
+	vpaddq	%ymm14,%ymm1,%ymm1
+	vpmuludq	%ymm0,%ymm13,%ymm13
+	vpmuludq	%ymm12,%ymm11,%ymm11
+.byte	0xc4,0x41,0x7e,0x6f,0xb5,0xf0,0xff,0xff,0xff
+	vpaddq	%ymm1,%ymm13,%ymm13
+	vpaddq	%ymm11,%ymm2,%ymm2
+	vpmuludq	%ymm12,%ymm10,%ymm10
+	vmovdqu	160-16-128(%r13),%ymm11
+.byte	0x67
+	vmovq	%xmm13,%rax
+	vmovdqu	%ymm13,(%rsp)
+	vpaddq	%ymm10,%ymm3,%ymm3
+	vpmuludq	%ymm12,%ymm14,%ymm14
+	vmovdqu	192-16-128(%r13),%ymm10
+	vpaddq	%ymm14,%ymm4,%ymm4
+	vpmuludq	%ymm12,%ymm11,%ymm11
+	vmovdqu	224-16-128(%r13),%ymm14
+	vpaddq	%ymm11,%ymm5,%ymm5
+	vpmuludq	%ymm12,%ymm10,%ymm10
+	vmovdqu	256-16-128(%r13),%ymm11
+	vpaddq	%ymm10,%ymm6,%ymm6
+	vpmuludq	%ymm12,%ymm14,%ymm14
+	shrq	$29,%r12
+	vmovdqu	288-16-128(%r13),%ymm10
+	addq	%r12,%rax
+	vpaddq	%ymm14,%ymm7,%ymm7
+	vpmuludq	%ymm12,%ymm11,%ymm11
+
+	movq	%rax,%r9
+	imull	%ecx,%eax
+	vpaddq	%ymm11,%ymm8,%ymm8
+	vpmuludq	%ymm12,%ymm10,%ymm10
+	andl	$0x1fffffff,%eax
+	vmovd	%eax,%xmm12
+	vmovdqu	96-24-128(%r13),%ymm11
+.byte	0x67
+	vpaddq	%ymm10,%ymm9,%ymm9
+	vpbroadcastq	%xmm12,%ymm12
+
+	vpmuludq	64-24-128(%r13),%ymm0,%ymm14
+	vmovdqu	128-24-128(%r13),%ymm10
+	movq	%rax,%rdx
+	imulq	-128(%r13),%rax
+	movq	8(%rsp),%r10
+	vpaddq	%ymm14,%ymm2,%ymm1
+	vpmuludq	%ymm0,%ymm11,%ymm11
+	vmovdqu	160-24-128(%r13),%ymm14
+	addq	%rax,%r9
+	movq	%rdx,%rax
+	imulq	8-128(%r13),%rax
+.byte	0x67
+	shrq	$29,%r9
+	movq	16(%rsp),%r11
+	vpaddq	%ymm11,%ymm3,%ymm2
+	vpmuludq	%ymm0,%ymm10,%ymm10
+	vmovdqu	192-24-128(%r13),%ymm11
+	addq	%rax,%r10
+	movq	%rdx,%rax
+	imulq	16-128(%r13),%rax
+	vpaddq	%ymm10,%ymm4,%ymm3
+	vpmuludq	%ymm0,%ymm14,%ymm14
+	vmovdqu	224-24-128(%r13),%ymm10
+	imulq	24-128(%r13),%rdx
+	addq	%rax,%r11
+	leaq	(%r9,%r10,1),%rax
+	vpaddq	%ymm14,%ymm5,%ymm4
+	vpmuludq	%ymm0,%ymm11,%ymm11
+	vmovdqu	256-24-128(%r13),%ymm14
+	movq	%rax,%r10
+	imull	%ecx,%eax
+	vpmuludq	%ymm0,%ymm10,%ymm10
+	vpaddq	%ymm11,%ymm6,%ymm5
+	vmovdqu	288-24-128(%r13),%ymm11
+	andl	$0x1fffffff,%eax
+	vpaddq	%ymm10,%ymm7,%ymm6
+	vpmuludq	%ymm0,%ymm14,%ymm14
+	addq	24(%rsp),%rdx
+	vpaddq	%ymm14,%ymm8,%ymm7
+	vpmuludq	%ymm0,%ymm11,%ymm11
+	vpaddq	%ymm11,%ymm9,%ymm8
+	vmovq	%r12,%xmm9
+	movq	%rdx,%r12
+
+	decl	%r14d
+	jnz	.LOOP_REDUCE_1024
+	leaq	448(%rsp),%r12
+	vpaddq	%ymm9,%ymm13,%ymm0
+	vpxor	%ymm9,%ymm9,%ymm9
+
+	vpaddq	288-192(%rbx),%ymm0,%ymm0
+	vpaddq	320-448(%r12),%ymm1,%ymm1
+	vpaddq	352-448(%r12),%ymm2,%ymm2
+	vpaddq	384-448(%r12),%ymm3,%ymm3
+	vpaddq	416-448(%r12),%ymm4,%ymm4
+	vpaddq	448-448(%r12),%ymm5,%ymm5
+	vpaddq	480-448(%r12),%ymm6,%ymm6
+	vpaddq	512-448(%r12),%ymm7,%ymm7
+	vpaddq	544-448(%r12),%ymm8,%ymm8
+
+	vpsrlq	$29,%ymm0,%ymm14
+	vpand	%ymm15,%ymm0,%ymm0
+	vpsrlq	$29,%ymm1,%ymm11
+	vpand	%ymm15,%ymm1,%ymm1
+	vpsrlq	$29,%ymm2,%ymm12
+	vpermq	$0x93,%ymm14,%ymm14
+	vpand	%ymm15,%ymm2,%ymm2
+	vpsrlq	$29,%ymm3,%ymm13
+	vpermq	$0x93,%ymm11,%ymm11
+	vpand	%ymm15,%ymm3,%ymm3
+	vpermq	$0x93,%ymm12,%ymm12
+
+	vpblendd	$3,%ymm9,%ymm14,%ymm10
+	vpermq	$0x93,%ymm13,%ymm13
+	vpblendd	$3,%ymm14,%ymm11,%ymm14
+	vpaddq	%ymm10,%ymm0,%ymm0
+	vpblendd	$3,%ymm11,%ymm12,%ymm11
+	vpaddq	%ymm14,%ymm1,%ymm1
+	vpblendd	$3,%ymm12,%ymm13,%ymm12
+	vpaddq	%ymm11,%ymm2,%ymm2
+	vpblendd	$3,%ymm13,%ymm9,%ymm13
+	vpaddq	%ymm12,%ymm3,%ymm3
+	vpaddq	%ymm13,%ymm4,%ymm4
+
+	vpsrlq	$29,%ymm0,%ymm14
+	vpand	%ymm15,%ymm0,%ymm0
+	vpsrlq	$29,%ymm1,%ymm11
+	vpand	%ymm15,%ymm1,%ymm1
+	vpsrlq	$29,%ymm2,%ymm12
+	vpermq	$0x93,%ymm14,%ymm14
+	vpand	%ymm15,%ymm2,%ymm2
+	vpsrlq	$29,%ymm3,%ymm13
+	vpermq	$0x93,%ymm11,%ymm11
+	vpand	%ymm15,%ymm3,%ymm3
+	vpermq	$0x93,%ymm12,%ymm12
+
+	vpblendd	$3,%ymm9,%ymm14,%ymm10
+	vpermq	$0x93,%ymm13,%ymm13
+	vpblendd	$3,%ymm14,%ymm11,%ymm14
+	vpaddq	%ymm10,%ymm0,%ymm0
+	vpblendd	$3,%ymm11,%ymm12,%ymm11
+	vpaddq	%ymm14,%ymm1,%ymm1
+	vmovdqu	%ymm0,0-128(%rdi)
+	vpblendd	$3,%ymm12,%ymm13,%ymm12
+	vpaddq	%ymm11,%ymm2,%ymm2
+	vmovdqu	%ymm1,32-128(%rdi)
+	vpblendd	$3,%ymm13,%ymm9,%ymm13
+	vpaddq	%ymm12,%ymm3,%ymm3
+	vmovdqu	%ymm2,64-128(%rdi)
+	vpaddq	%ymm13,%ymm4,%ymm4
+	vmovdqu	%ymm3,96-128(%rdi)
+	vpsrlq	$29,%ymm4,%ymm14
+	vpand	%ymm15,%ymm4,%ymm4
+	vpsrlq	$29,%ymm5,%ymm11
+	vpand	%ymm15,%ymm5,%ymm5
+	vpsrlq	$29,%ymm6,%ymm12
+	vpermq	$0x93,%ymm14,%ymm14
+	vpand	%ymm15,%ymm6,%ymm6
+	vpsrlq	$29,%ymm7,%ymm13
+	vpermq	$0x93,%ymm11,%ymm11
+	vpand	%ymm15,%ymm7,%ymm7
+	vpsrlq	$29,%ymm8,%ymm0
+	vpermq	$0x93,%ymm12,%ymm12
+	vpand	%ymm15,%ymm8,%ymm8
+	vpermq	$0x93,%ymm13,%ymm13
+
+	vpblendd	$3,%ymm9,%ymm14,%ymm10
+	vpermq	$0x93,%ymm0,%ymm0
+	vpblendd	$3,%ymm14,%ymm11,%ymm14
+	vpaddq	%ymm10,%ymm4,%ymm4
+	vpblendd	$3,%ymm11,%ymm12,%ymm11
+	vpaddq	%ymm14,%ymm5,%ymm5
+	vpblendd	$3,%ymm12,%ymm13,%ymm12
+	vpaddq	%ymm11,%ymm6,%ymm6
+	vpblendd	$3,%ymm13,%ymm0,%ymm13
+	vpaddq	%ymm12,%ymm7,%ymm7
+	vpaddq	%ymm13,%ymm8,%ymm8
+
+	vpsrlq	$29,%ymm4,%ymm14
+	vpand	%ymm15,%ymm4,%ymm4
+	vpsrlq	$29,%ymm5,%ymm11
+	vpand	%ymm15,%ymm5,%ymm5
+	vpsrlq	$29,%ymm6,%ymm12
+	vpermq	$0x93,%ymm14,%ymm14
+	vpand	%ymm15,%ymm6,%ymm6
+	vpsrlq	$29,%ymm7,%ymm13
+	vpermq	$0x93,%ymm11,%ymm11
+	vpand	%ymm15,%ymm7,%ymm7
+	vpsrlq	$29,%ymm8,%ymm0
+	vpermq	$0x93,%ymm12,%ymm12
+	vpand	%ymm15,%ymm8,%ymm8
+	vpermq	$0x93,%ymm13,%ymm13
+
+	vpblendd	$3,%ymm9,%ymm14,%ymm10
+	vpermq	$0x93,%ymm0,%ymm0
+	vpblendd	$3,%ymm14,%ymm11,%ymm14
+	vpaddq	%ymm10,%ymm4,%ymm4
+	vpblendd	$3,%ymm11,%ymm12,%ymm11
+	vpaddq	%ymm14,%ymm5,%ymm5
+	vmovdqu	%ymm4,128-128(%rdi)
+	vpblendd	$3,%ymm12,%ymm13,%ymm12
+	vpaddq	%ymm11,%ymm6,%ymm6
+	vmovdqu	%ymm5,160-128(%rdi)
+	vpblendd	$3,%ymm13,%ymm0,%ymm13
+	vpaddq	%ymm12,%ymm7,%ymm7
+	vmovdqu	%ymm6,192-128(%rdi)
+	vpaddq	%ymm13,%ymm8,%ymm8
+	vmovdqu	%ymm7,224-128(%rdi)
+	vmovdqu	%ymm8,256-128(%rdi)
+
+	movq	%rdi,%rsi
+	decl	%r8d
+	jne	.LOOP_GRANDE_SQR_1024
+
+	vzeroall
+	movq	%rbp,%rax
+.cfi_def_cfa_register	%rax
+	movq	-48(%rax),%r15
+.cfi_restore	%r15
+	movq	-40(%rax),%r14
+.cfi_restore	%r14
+	movq	-32(%rax),%r13
+.cfi_restore	%r13
+	movq	-24(%rax),%r12
+.cfi_restore	%r12
+	movq	-16(%rax),%rbp
+.cfi_restore	%rbp
+	movq	-8(%rax),%rbx
+.cfi_restore	%rbx
+	leaq	(%rax),%rsp
+.cfi_def_cfa_register	%rsp
+.Lsqr_1024_epilogue:
+	.byte	0xf3,0xc3
+.cfi_endproc	
+.size	rsaz_1024_sqr_avx2,.-rsaz_1024_sqr_avx2
+.globl	rsaz_1024_mul_avx2
+.hidden rsaz_1024_mul_avx2
+.type	rsaz_1024_mul_avx2,@function
+.align	64
+rsaz_1024_mul_avx2:
+.cfi_startproc	
+	leaq	(%rsp),%rax
+.cfi_def_cfa_register	%rax
+	pushq	%rbx
+.cfi_offset	%rbx,-16
+	pushq	%rbp
+.cfi_offset	%rbp,-24
+	pushq	%r12
+.cfi_offset	%r12,-32
+	pushq	%r13
+.cfi_offset	%r13,-40
+	pushq	%r14
+.cfi_offset	%r14,-48
+	pushq	%r15
+.cfi_offset	%r15,-56
+	movq	%rax,%rbp
+.cfi_def_cfa_register	%rbp
+	vzeroall
+	movq	%rdx,%r13
+	subq	$64,%rsp
+
+
+
+
+
+
+.byte	0x67,0x67
+	movq	%rsi,%r15
+	andq	$4095,%r15
+	addq	$320,%r15
+	shrq	$12,%r15
+	movq	%rsi,%r15
+	cmovnzq	%r13,%rsi
+	cmovnzq	%r15,%r13
+
+	movq	%rcx,%r15
+	subq	$-128,%rsi
+	subq	$-128,%rcx
+	subq	$-128,%rdi
+
+	andq	$4095,%r15
+	addq	$320,%r15
+.byte	0x67,0x67
+	shrq	$12,%r15
+	jz	.Lmul_1024_no_n_copy
+
+
+
+
+
+	subq	$320,%rsp
+	vmovdqu	0-128(%rcx),%ymm0
+	andq	$-512,%rsp
+	vmovdqu	32-128(%rcx),%ymm1
+	vmovdqu	64-128(%rcx),%ymm2
+	vmovdqu	96-128(%rcx),%ymm3
+	vmovdqu	128-128(%rcx),%ymm4
+	vmovdqu	160-128(%rcx),%ymm5
+	vmovdqu	192-128(%rcx),%ymm6
+	vmovdqu	224-128(%rcx),%ymm7
+	vmovdqu	256-128(%rcx),%ymm8
+	leaq	64+128(%rsp),%rcx
+	vmovdqu	%ymm0,0-128(%rcx)
+	vpxor	%ymm0,%ymm0,%ymm0
+	vmovdqu	%ymm1,32-128(%rcx)
+	vpxor	%ymm1,%ymm1,%ymm1
+	vmovdqu	%ymm2,64-128(%rcx)
+	vpxor	%ymm2,%ymm2,%ymm2
+	vmovdqu	%ymm3,96-128(%rcx)
+	vpxor	%ymm3,%ymm3,%ymm3
+	vmovdqu	%ymm4,128-128(%rcx)
+	vpxor	%ymm4,%ymm4,%ymm4
+	vmovdqu	%ymm5,160-128(%rcx)
+	vpxor	%ymm5,%ymm5,%ymm5
+	vmovdqu	%ymm6,192-128(%rcx)
+	vpxor	%ymm6,%ymm6,%ymm6
+	vmovdqu	%ymm7,224-128(%rcx)
+	vpxor	%ymm7,%ymm7,%ymm7
+	vmovdqu	%ymm8,256-128(%rcx)
+	vmovdqa	%ymm0,%ymm8
+	vmovdqu	%ymm9,288-128(%rcx)
+.Lmul_1024_no_n_copy:
+	andq	$-64,%rsp
+
+	movq	(%r13),%rbx
+	vpbroadcastq	(%r13),%ymm10
+	vmovdqu	%ymm0,(%rsp)
+	xorq	%r9,%r9
+.byte	0x67
+	xorq	%r10,%r10
+	xorq	%r11,%r11
+	xorq	%r12,%r12
+
+	vmovdqu	.Land_mask(%rip),%ymm15
+	movl	$9,%r14d
+	vmovdqu	%ymm9,288-128(%rdi)
+	jmp	.Loop_mul_1024
+
+.align	32
+.Loop_mul_1024:
+	vpsrlq	$29,%ymm3,%ymm9
+	movq	%rbx,%rax
+	imulq	-128(%rsi),%rax
+	addq	%r9,%rax
+	movq	%rbx,%r10
+	imulq	8-128(%rsi),%r10
+	addq	8(%rsp),%r10
+
+	movq	%rax,%r9
+	imull	%r8d,%eax
+	andl	$0x1fffffff,%eax
+
+	movq	%rbx,%r11
+	imulq	16-128(%rsi),%r11
+	addq	16(%rsp),%r11
+
+	movq	%rbx,%r12
+	imulq	24-128(%rsi),%r12
+	addq	24(%rsp),%r12
+	vpmuludq	32-128(%rsi),%ymm10,%ymm0
+	vmovd	%eax,%xmm11
+	vpaddq	%ymm0,%ymm1,%ymm1
+	vpmuludq	64-128(%rsi),%ymm10,%ymm12
+	vpbroadcastq	%xmm11,%ymm11
+	vpaddq	%ymm12,%ymm2,%ymm2
+	vpmuludq	96-128(%rsi),%ymm10,%ymm13
+	vpand	%ymm15,%ymm3,%ymm3
+	vpaddq	%ymm13,%ymm3,%ymm3
+	vpmuludq	128-128(%rsi),%ymm10,%ymm0
+	vpaddq	%ymm0,%ymm4,%ymm4
+	vpmuludq	160-128(%rsi),%ymm10,%ymm12
+	vpaddq	%ymm12,%ymm5,%ymm5
+	vpmuludq	192-128(%rsi),%ymm10,%ymm13
+	vpaddq	%ymm13,%ymm6,%ymm6
+	vpmuludq	224-128(%rsi),%ymm10,%ymm0
+	vpermq	$0x93,%ymm9,%ymm9
+	vpaddq	%ymm0,%ymm7,%ymm7
+	vpmuludq	256-128(%rsi),%ymm10,%ymm12
+	vpbroadcastq	8(%r13),%ymm10
+	vpaddq	%ymm12,%ymm8,%ymm8
+
+	movq	%rax,%rdx
+	imulq	-128(%rcx),%rax
+	addq	%rax,%r9
+	movq	%rdx,%rax
+	imulq	8-128(%rcx),%rax
+	addq	%rax,%r10
+	movq	%rdx,%rax
+	imulq	16-128(%rcx),%rax
+	addq	%rax,%r11
+	shrq	$29,%r9
+	imulq	24-128(%rcx),%rdx
+	addq	%rdx,%r12
+	addq	%r9,%r10
+
+	vpmuludq	32-128(%rcx),%ymm11,%ymm13
+	vmovq	%xmm10,%rbx
+	vpaddq	%ymm13,%ymm1,%ymm1
+	vpmuludq	64-128(%rcx),%ymm11,%ymm0
+	vpaddq	%ymm0,%ymm2,%ymm2
+	vpmuludq	96-128(%rcx),%ymm11,%ymm12
+	vpaddq	%ymm12,%ymm3,%ymm3
+	vpmuludq	128-128(%rcx),%ymm11,%ymm13
+	vpaddq	%ymm13,%ymm4,%ymm4
+	vpmuludq	160-128(%rcx),%ymm11,%ymm0
+	vpaddq	%ymm0,%ymm5,%ymm5
+	vpmuludq	192-128(%rcx),%ymm11,%ymm12
+	vpaddq	%ymm12,%ymm6,%ymm6
+	vpmuludq	224-128(%rcx),%ymm11,%ymm13
+	vpblendd	$3,%ymm14,%ymm9,%ymm9
+	vpaddq	%ymm13,%ymm7,%ymm7
+	vpmuludq	256-128(%rcx),%ymm11,%ymm0
+	vpaddq	%ymm9,%ymm3,%ymm3
+	vpaddq	%ymm0,%ymm8,%ymm8
+
+	movq	%rbx,%rax
+	imulq	-128(%rsi),%rax
+	addq	%rax,%r10
+	vmovdqu	-8+32-128(%rsi),%ymm12
+	movq	%rbx,%rax
+	imulq	8-128(%rsi),%rax
+	addq	%rax,%r11
+	vmovdqu	-8+64-128(%rsi),%ymm13
+
+	movq	%r10,%rax
+	imull	%r8d,%eax
+	andl	$0x1fffffff,%eax
+
+	imulq	16-128(%rsi),%rbx
+	addq	%rbx,%r12
+	vpmuludq	%ymm10,%ymm12,%ymm12
+	vmovd	%eax,%xmm11
+	vmovdqu	-8+96-128(%rsi),%ymm0
+	vpaddq	%ymm12,%ymm1,%ymm1
+	vpmuludq	%ymm10,%ymm13,%ymm13
+	vpbroadcastq	%xmm11,%ymm11
+	vmovdqu	-8+128-128(%rsi),%ymm12
+	vpaddq	%ymm13,%ymm2,%ymm2
+	vpmuludq	%ymm10,%ymm0,%ymm0
+	vmovdqu	-8+160-128(%rsi),%ymm13
+	vpaddq	%ymm0,%ymm3,%ymm3
+	vpmuludq	%ymm10,%ymm12,%ymm12
+	vmovdqu	-8+192-128(%rsi),%ymm0
+	vpaddq	%ymm12,%ymm4,%ymm4
+	vpmuludq	%ymm10,%ymm13,%ymm13
+	vmovdqu	-8+224-128(%rsi),%ymm12
+	vpaddq	%ymm13,%ymm5,%ymm5
+	vpmuludq	%ymm10,%ymm0,%ymm0
+	vmovdqu	-8+256-128(%rsi),%ymm13
+	vpaddq	%ymm0,%ymm6,%ymm6
+	vpmuludq	%ymm10,%ymm12,%ymm12
+	vmovdqu	-8+288-128(%rsi),%ymm9
+	vpaddq	%ymm12,%ymm7,%ymm7
+	vpmuludq	%ymm10,%ymm13,%ymm13
+	vpaddq	%ymm13,%ymm8,%ymm8
+	vpmuludq	%ymm10,%ymm9,%ymm9
+	vpbroadcastq	16(%r13),%ymm10
+
+	movq	%rax,%rdx
+	imulq	-128(%rcx),%rax
+	addq	%rax,%r10
+	vmovdqu	-8+32-128(%rcx),%ymm0
+	movq	%rdx,%rax
+	imulq	8-128(%rcx),%rax
+	addq	%rax,%r11
+	vmovdqu	-8+64-128(%rcx),%ymm12
+	shrq	$29,%r10
+	imulq	16-128(%rcx),%rdx
+	addq	%rdx,%r12
+	addq	%r10,%r11
+
+	vpmuludq	%ymm11,%ymm0,%ymm0
+	vmovq	%xmm10,%rbx
+	vmovdqu	-8+96-128(%rcx),%ymm13
+	vpaddq	%ymm0,%ymm1,%ymm1
+	vpmuludq	%ymm11,%ymm12,%ymm12
+	vmovdqu	-8+128-128(%rcx),%ymm0
+	vpaddq	%ymm12,%ymm2,%ymm2
+	vpmuludq	%ymm11,%ymm13,%ymm13
+	vmovdqu	-8+160-128(%rcx),%ymm12
+	vpaddq	%ymm13,%ymm3,%ymm3
+	vpmuludq	%ymm11,%ymm0,%ymm0
+	vmovdqu	-8+192-128(%rcx),%ymm13
+	vpaddq	%ymm0,%ymm4,%ymm4
+	vpmuludq	%ymm11,%ymm12,%ymm12
+	vmovdqu	-8+224-128(%rcx),%ymm0
+	vpaddq	%ymm12,%ymm5,%ymm5
+	vpmuludq	%ymm11,%ymm13,%ymm13
+	vmovdqu	-8+256-128(%rcx),%ymm12
+	vpaddq	%ymm13,%ymm6,%ymm6
+	vpmuludq	%ymm11,%ymm0,%ymm0
+	vmovdqu	-8+288-128(%rcx),%ymm13
+	vpaddq	%ymm0,%ymm7,%ymm7
+	vpmuludq	%ymm11,%ymm12,%ymm12
+	vpaddq	%ymm12,%ymm8,%ymm8
+	vpmuludq	%ymm11,%ymm13,%ymm13
+	vpaddq	%ymm13,%ymm9,%ymm9
+
+	vmovdqu	-16+32-128(%rsi),%ymm0
+	movq	%rbx,%rax
+	imulq	-128(%rsi),%rax
+	addq	%r11,%rax
+
+	vmovdqu	-16+64-128(%rsi),%ymm12
+	movq	%rax,%r11
+	imull	%r8d,%eax
+	andl	$0x1fffffff,%eax
+
+	imulq	8-128(%rsi),%rbx
+	addq	%rbx,%r12
+	vpmuludq	%ymm10,%ymm0,%ymm0
+	vmovd	%eax,%xmm11
+	vmovdqu	-16+96-128(%rsi),%ymm13
+	vpaddq	%ymm0,%ymm1,%ymm1
+	vpmuludq	%ymm10,%ymm12,%ymm12
+	vpbroadcastq	%xmm11,%ymm11
+	vmovdqu	-16+128-128(%rsi),%ymm0
+	vpaddq	%ymm12,%ymm2,%ymm2
+	vpmuludq	%ymm10,%ymm13,%ymm13
+	vmovdqu	-16+160-128(%rsi),%ymm12
+	vpaddq	%ymm13,%ymm3,%ymm3
+	vpmuludq	%ymm10,%ymm0,%ymm0
+	vmovdqu	-16+192-128(%rsi),%ymm13
+	vpaddq	%ymm0,%ymm4,%ymm4
+	vpmuludq	%ymm10,%ymm12,%ymm12
+	vmovdqu	-16+224-128(%rsi),%ymm0
+	vpaddq	%ymm12,%ymm5,%ymm5
+	vpmuludq	%ymm10,%ymm13,%ymm13
+	vmovdqu	-16+256-128(%rsi),%ymm12
+	vpaddq	%ymm13,%ymm6,%ymm6
+	vpmuludq	%ymm10,%ymm0,%ymm0
+	vmovdqu	-16+288-128(%rsi),%ymm13
+	vpaddq	%ymm0,%ymm7,%ymm7
+	vpmuludq	%ymm10,%ymm12,%ymm12
+	vpaddq	%ymm12,%ymm8,%ymm8
+	vpmuludq	%ymm10,%ymm13,%ymm13
+	vpbroadcastq	24(%r13),%ymm10
+	vpaddq	%ymm13,%ymm9,%ymm9
+
+	vmovdqu	-16+32-128(%rcx),%ymm0
+	movq	%rax,%rdx
+	imulq	-128(%rcx),%rax
+	addq	%rax,%r11
+	vmovdqu	-16+64-128(%rcx),%ymm12
+	imulq	8-128(%rcx),%rdx
+	addq	%rdx,%r12
+	shrq	$29,%r11
+
+	vpmuludq	%ymm11,%ymm0,%ymm0
+	vmovq	%xmm10,%rbx
+	vmovdqu	-16+96-128(%rcx),%ymm13
+	vpaddq	%ymm0,%ymm1,%ymm1
+	vpmuludq	%ymm11,%ymm12,%ymm12
+	vmovdqu	-16+128-128(%rcx),%ymm0
+	vpaddq	%ymm12,%ymm2,%ymm2
+	vpmuludq	%ymm11,%ymm13,%ymm13
+	vmovdqu	-16+160-128(%rcx),%ymm12
+	vpaddq	%ymm13,%ymm3,%ymm3
+	vpmuludq	%ymm11,%ymm0,%ymm0
+	vmovdqu	-16+192-128(%rcx),%ymm13
+	vpaddq	%ymm0,%ymm4,%ymm4
+	vpmuludq	%ymm11,%ymm12,%ymm12
+	vmovdqu	-16+224-128(%rcx),%ymm0
+	vpaddq	%ymm12,%ymm5,%ymm5
+	vpmuludq	%ymm11,%ymm13,%ymm13
+	vmovdqu	-16+256-128(%rcx),%ymm12
+	vpaddq	%ymm13,%ymm6,%ymm6
+	vpmuludq	%ymm11,%ymm0,%ymm0
+	vmovdqu	-16+288-128(%rcx),%ymm13
+	vpaddq	%ymm0,%ymm7,%ymm7
+	vpmuludq	%ymm11,%ymm12,%ymm12
+	vmovdqu	-24+32-128(%rsi),%ymm0
+	vpaddq	%ymm12,%ymm8,%ymm8
+	vpmuludq	%ymm11,%ymm13,%ymm13
+	vmovdqu	-24+64-128(%rsi),%ymm12
+	vpaddq	%ymm13,%ymm9,%ymm9
+
+	addq	%r11,%r12
+	imulq	-128(%rsi),%rbx
+	addq	%rbx,%r12
+
+	movq	%r12,%rax
+	imull	%r8d,%eax
+	andl	$0x1fffffff,%eax
+
+	vpmuludq	%ymm10,%ymm0,%ymm0
+	vmovd	%eax,%xmm11
+	vmovdqu	-24+96-128(%rsi),%ymm13
+	vpaddq	%ymm0,%ymm1,%ymm1
+	vpmuludq	%ymm10,%ymm12,%ymm12
+	vpbroadcastq	%xmm11,%ymm11
+	vmovdqu	-24+128-128(%rsi),%ymm0
+	vpaddq	%ymm12,%ymm2,%ymm2
+	vpmuludq	%ymm10,%ymm13,%ymm13
+	vmovdqu	-24+160-128(%rsi),%ymm12
+	vpaddq	%ymm13,%ymm3,%ymm3
+	vpmuludq	%ymm10,%ymm0,%ymm0
+	vmovdqu	-24+192-128(%rsi),%ymm13
+	vpaddq	%ymm0,%ymm4,%ymm4
+	vpmuludq	%ymm10,%ymm12,%ymm12
+	vmovdqu	-24+224-128(%rsi),%ymm0
+	vpaddq	%ymm12,%ymm5,%ymm5
+	vpmuludq	%ymm10,%ymm13,%ymm13
+	vmovdqu	-24+256-128(%rsi),%ymm12
+	vpaddq	%ymm13,%ymm6,%ymm6
+	vpmuludq	%ymm10,%ymm0,%ymm0
+	vmovdqu	-24+288-128(%rsi),%ymm13
+	vpaddq	%ymm0,%ymm7,%ymm7
+	vpmuludq	%ymm10,%ymm12,%ymm12
+	vpaddq	%ymm12,%ymm8,%ymm8
+	vpmuludq	%ymm10,%ymm13,%ymm13
+	vpbroadcastq	32(%r13),%ymm10
+	vpaddq	%ymm13,%ymm9,%ymm9
+	addq	$32,%r13
+
+	vmovdqu	-24+32-128(%rcx),%ymm0
+	imulq	-128(%rcx),%rax
+	addq	%rax,%r12
+	shrq	$29,%r12
+
+	vmovdqu	-24+64-128(%rcx),%ymm12
+	vpmuludq	%ymm11,%ymm0,%ymm0
+	vmovq	%xmm10,%rbx
+	vmovdqu	-24+96-128(%rcx),%ymm13
+	vpaddq	%ymm0,%ymm1,%ymm0
+	vpmuludq	%ymm11,%ymm12,%ymm12
+	vmovdqu	%ymm0,(%rsp)
+	vpaddq	%ymm12,%ymm2,%ymm1
+	vmovdqu	-24+128-128(%rcx),%ymm0
+	vpmuludq	%ymm11,%ymm13,%ymm13
+	vmovdqu	-24+160-128(%rcx),%ymm12
+	vpaddq	%ymm13,%ymm3,%ymm2
+	vpmuludq	%ymm11,%ymm0,%ymm0
+	vmovdqu	-24+192-128(%rcx),%ymm13
+	vpaddq	%ymm0,%ymm4,%ymm3
+	vpmuludq	%ymm11,%ymm12,%ymm12
+	vmovdqu	-24+224-128(%rcx),%ymm0
+	vpaddq	%ymm12,%ymm5,%ymm4
+	vpmuludq	%ymm11,%ymm13,%ymm13
+	vmovdqu	-24+256-128(%rcx),%ymm12
+	vpaddq	%ymm13,%ymm6,%ymm5
+	vpmuludq	%ymm11,%ymm0,%ymm0
+	vmovdqu	-24+288-128(%rcx),%ymm13
+	movq	%r12,%r9
+	vpaddq	%ymm0,%ymm7,%ymm6
+	vpmuludq	%ymm11,%ymm12,%ymm12
+	addq	(%rsp),%r9
+	vpaddq	%ymm12,%ymm8,%ymm7
+	vpmuludq	%ymm11,%ymm13,%ymm13
+	vmovq	%r12,%xmm12
+	vpaddq	%ymm13,%ymm9,%ymm8
+
+	decl	%r14d
+	jnz	.Loop_mul_1024
+	vpermq	$0,%ymm15,%ymm15
+	vpaddq	(%rsp),%ymm12,%ymm0
+
+	vpsrlq	$29,%ymm0,%ymm12
+	vpand	%ymm15,%ymm0,%ymm0
+	vpsrlq	$29,%ymm1,%ymm13
+	vpand	%ymm15,%ymm1,%ymm1
+	vpsrlq	$29,%ymm2,%ymm10
+	vpermq	$0x93,%ymm12,%ymm12
+	vpand	%ymm15,%ymm2,%ymm2
+	vpsrlq	$29,%ymm3,%ymm11
+	vpermq	$0x93,%ymm13,%ymm13
+	vpand	%ymm15,%ymm3,%ymm3
+
+	vpblendd	$3,%ymm14,%ymm12,%ymm9
+	vpermq	$0x93,%ymm10,%ymm10
+	vpblendd	$3,%ymm12,%ymm13,%ymm12
+	vpermq	$0x93,%ymm11,%ymm11
+	vpaddq	%ymm9,%ymm0,%ymm0
+	vpblendd	$3,%ymm13,%ymm10,%ymm13
+	vpaddq	%ymm12,%ymm1,%ymm1
+	vpblendd	$3,%ymm10,%ymm11,%ymm10
+	vpaddq	%ymm13,%ymm2,%ymm2
+	vpblendd	$3,%ymm11,%ymm14,%ymm11
+	vpaddq	%ymm10,%ymm3,%ymm3
+	vpaddq	%ymm11,%ymm4,%ymm4
+
+	vpsrlq	$29,%ymm0,%ymm12
+	vpand	%ymm15,%ymm0,%ymm0
+	vpsrlq	$29,%ymm1,%ymm13
+	vpand	%ymm15,%ymm1,%ymm1
+	vpsrlq	$29,%ymm2,%ymm10
+	vpermq	$0x93,%ymm12,%ymm12
+	vpand	%ymm15,%ymm2,%ymm2
+	vpsrlq	$29,%ymm3,%ymm11
+	vpermq	$0x93,%ymm13,%ymm13
+	vpand	%ymm15,%ymm3,%ymm3
+	vpermq	$0x93,%ymm10,%ymm10
+
+	vpblendd	$3,%ymm14,%ymm12,%ymm9
+	vpermq	$0x93,%ymm11,%ymm11
+	vpblendd	$3,%ymm12,%ymm13,%ymm12
+	vpaddq	%ymm9,%ymm0,%ymm0
+	vpblendd	$3,%ymm13,%ymm10,%ymm13
+	vpaddq	%ymm12,%ymm1,%ymm1
+	vpblendd	$3,%ymm10,%ymm11,%ymm10
+	vpaddq	%ymm13,%ymm2,%ymm2
+	vpblendd	$3,%ymm11,%ymm14,%ymm11
+	vpaddq	%ymm10,%ymm3,%ymm3
+	vpaddq	%ymm11,%ymm4,%ymm4
+
+	vmovdqu	%ymm0,0-128(%rdi)
+	vmovdqu	%ymm1,32-128(%rdi)
+	vmovdqu	%ymm2,64-128(%rdi)
+	vmovdqu	%ymm3,96-128(%rdi)
+	vpsrlq	$29,%ymm4,%ymm12
+	vpand	%ymm15,%ymm4,%ymm4
+	vpsrlq	$29,%ymm5,%ymm13
+	vpand	%ymm15,%ymm5,%ymm5
+	vpsrlq	$29,%ymm6,%ymm10
+	vpermq	$0x93,%ymm12,%ymm12
+	vpand	%ymm15,%ymm6,%ymm6
+	vpsrlq	$29,%ymm7,%ymm11
+	vpermq	$0x93,%ymm13,%ymm13
+	vpand	%ymm15,%ymm7,%ymm7
+	vpsrlq	$29,%ymm8,%ymm0
+	vpermq	$0x93,%ymm10,%ymm10
+	vpand	%ymm15,%ymm8,%ymm8
+	vpermq	$0x93,%ymm11,%ymm11
+
+	vpblendd	$3,%ymm14,%ymm12,%ymm9
+	vpermq	$0x93,%ymm0,%ymm0
+	vpblendd	$3,%ymm12,%ymm13,%ymm12
+	vpaddq	%ymm9,%ymm4,%ymm4
+	vpblendd	$3,%ymm13,%ymm10,%ymm13
+	vpaddq	%ymm12,%ymm5,%ymm5
+	vpblendd	$3,%ymm10,%ymm11,%ymm10
+	vpaddq	%ymm13,%ymm6,%ymm6
+	vpblendd	$3,%ymm11,%ymm0,%ymm11
+	vpaddq	%ymm10,%ymm7,%ymm7
+	vpaddq	%ymm11,%ymm8,%ymm8
+
+	vpsrlq	$29,%ymm4,%ymm12
+	vpand	%ymm15,%ymm4,%ymm4
+	vpsrlq	$29,%ymm5,%ymm13
+	vpand	%ymm15,%ymm5,%ymm5
+	vpsrlq	$29,%ymm6,%ymm10
+	vpermq	$0x93,%ymm12,%ymm12
+	vpand	%ymm15,%ymm6,%ymm6
+	vpsrlq	$29,%ymm7,%ymm11
+	vpermq	$0x93,%ymm13,%ymm13
+	vpand	%ymm15,%ymm7,%ymm7
+	vpsrlq	$29,%ymm8,%ymm0
+	vpermq	$0x93,%ymm10,%ymm10
+	vpand	%ymm15,%ymm8,%ymm8
+	vpermq	$0x93,%ymm11,%ymm11
+
+	vpblendd	$3,%ymm14,%ymm12,%ymm9
+	vpermq	$0x93,%ymm0,%ymm0
+	vpblendd	$3,%ymm12,%ymm13,%ymm12
+	vpaddq	%ymm9,%ymm4,%ymm4
+	vpblendd	$3,%ymm13,%ymm10,%ymm13
+	vpaddq	%ymm12,%ymm5,%ymm5
+	vpblendd	$3,%ymm10,%ymm11,%ymm10
+	vpaddq	%ymm13,%ymm6,%ymm6
+	vpblendd	$3,%ymm11,%ymm0,%ymm11
+	vpaddq	%ymm10,%ymm7,%ymm7
+	vpaddq	%ymm11,%ymm8,%ymm8
+
+	vmovdqu	%ymm4,128-128(%rdi)
+	vmovdqu	%ymm5,160-128(%rdi)
+	vmovdqu	%ymm6,192-128(%rdi)
+	vmovdqu	%ymm7,224-128(%rdi)
+	vmovdqu	%ymm8,256-128(%rdi)
+	vzeroupper
+
+	movq	%rbp,%rax
+.cfi_def_cfa_register	%rax
+	movq	-48(%rax),%r15
+.cfi_restore	%r15
+	movq	-40(%rax),%r14
+.cfi_restore	%r14
+	movq	-32(%rax),%r13
+.cfi_restore	%r13
+	movq	-24(%rax),%r12
+.cfi_restore	%r12
+	movq	-16(%rax),%rbp
+.cfi_restore	%rbp
+	movq	-8(%rax),%rbx
+.cfi_restore	%rbx
+	leaq	(%rax),%rsp
+.cfi_def_cfa_register	%rsp
+.Lmul_1024_epilogue:
+	.byte	0xf3,0xc3
+.cfi_endproc	
+.size	rsaz_1024_mul_avx2,.-rsaz_1024_mul_avx2
+.globl	rsaz_1024_red2norm_avx2
+.hidden rsaz_1024_red2norm_avx2
+.type	rsaz_1024_red2norm_avx2,@function
+.align	32
+rsaz_1024_red2norm_avx2:
+	subq	$-128,%rsi
+	xorq	%rax,%rax
+	movq	-128(%rsi),%r8
+	movq	-120(%rsi),%r9
+	movq	-112(%rsi),%r10
+	shlq	$0,%r8
+	shlq	$29,%r9
+	movq	%r10,%r11
+	shlq	$58,%r10
+	shrq	$6,%r11
+	addq	%r8,%rax
+	addq	%r9,%rax
+	addq	%r10,%rax
+	adcq	$0,%r11
+	movq	%rax,0(%rdi)
+	movq	%r11,%rax
+	movq	-104(%rsi),%r8
+	movq	-96(%rsi),%r9
+	shlq	$23,%r8
+	movq	%r9,%r10
+	shlq	$52,%r9
+	shrq	$12,%r10
+	addq	%r8,%rax
+	addq	%r9,%rax
+	adcq	$0,%r10
+	movq	%rax,8(%rdi)
+	movq	%r10,%rax
+	movq	-88(%rsi),%r11
+	movq	-80(%rsi),%r8
+	shlq	$17,%r11
+	movq	%r8,%r9
+	shlq	$46,%r8
+	shrq	$18,%r9
+	addq	%r11,%rax
+	addq	%r8,%rax
+	adcq	$0,%r9
+	movq	%rax,16(%rdi)
+	movq	%r9,%rax
+	movq	-72(%rsi),%r10
+	movq	-64(%rsi),%r11
+	shlq	$11,%r10
+	movq	%r11,%r8
+	shlq	$40,%r11
+	shrq	$24,%r8
+	addq	%r10,%rax
+	addq	%r11,%rax
+	adcq	$0,%r8
+	movq	%rax,24(%rdi)
+	movq	%r8,%rax
+	movq	-56(%rsi),%r9
+	movq	-48(%rsi),%r10
+	movq	-40(%rsi),%r11
+	shlq	$5,%r9
+	shlq	$34,%r10
+	movq	%r11,%r8
+	shlq	$63,%r11
+	shrq	$1,%r8
+	addq	%r9,%rax
+	addq	%r10,%rax
+	addq	%r11,%rax
+	adcq	$0,%r8
+	movq	%rax,32(%rdi)
+	movq	%r8,%rax
+	movq	-32(%rsi),%r9
+	movq	-24(%rsi),%r10
+	shlq	$28,%r9
+	movq	%r10,%r11
+	shlq	$57,%r10
+	shrq	$7,%r11
+	addq	%r9,%rax
+	addq	%r10,%rax
+	adcq	$0,%r11
+	movq	%rax,40(%rdi)
+	movq	%r11,%rax
+	movq	-16(%rsi),%r8
+	movq	-8(%rsi),%r9
+	shlq	$22,%r8
+	movq	%r9,%r10
+	shlq	$51,%r9
+	shrq	$13,%r10
+	addq	%r8,%rax
+	addq	%r9,%rax
+	adcq	$0,%r10
+	movq	%rax,48(%rdi)
+	movq	%r10,%rax
+	movq	0(%rsi),%r11
+	movq	8(%rsi),%r8
+	shlq	$16,%r11
+	movq	%r8,%r9
+	shlq	$45,%r8
+	shrq	$19,%r9
+	addq	%r11,%rax
+	addq	%r8,%rax
+	adcq	$0,%r9
+	movq	%rax,56(%rdi)
+	movq	%r9,%rax
+	movq	16(%rsi),%r10
+	movq	24(%rsi),%r11
+	shlq	$10,%r10
+	movq	%r11,%r8
+	shlq	$39,%r11
+	shrq	$25,%r8
+	addq	%r10,%rax
+	addq	%r11,%rax
+	adcq	$0,%r8
+	movq	%rax,64(%rdi)
+	movq	%r8,%rax
+	movq	32(%rsi),%r9
+	movq	40(%rsi),%r10
+	movq	48(%rsi),%r11
+	shlq	$4,%r9
+	shlq	$33,%r10
+	movq	%r11,%r8
+	shlq	$62,%r11
+	shrq	$2,%r8
+	addq	%r9,%rax
+	addq	%r10,%rax
+	addq	%r11,%rax
+	adcq	$0,%r8
+	movq	%rax,72(%rdi)
+	movq	%r8,%rax
+	movq	56(%rsi),%r9
+	movq	64(%rsi),%r10
+	shlq	$27,%r9
+	movq	%r10,%r11
+	shlq	$56,%r10
+	shrq	$8,%r11
+	addq	%r9,%rax
+	addq	%r10,%rax
+	adcq	$0,%r11
+	movq	%rax,80(%rdi)
+	movq	%r11,%rax
+	movq	72(%rsi),%r8
+	movq	80(%rsi),%r9
+	shlq	$21,%r8
+	movq	%r9,%r10
+	shlq	$50,%r9
+	shrq	$14,%r10
+	addq	%r8,%rax
+	addq	%r9,%rax
+	adcq	$0,%r10
+	movq	%rax,88(%rdi)
+	movq	%r10,%rax
+	movq	88(%rsi),%r11
+	movq	96(%rsi),%r8
+	shlq	$15,%r11
+	movq	%r8,%r9
+	shlq	$44,%r8
+	shrq	$20,%r9
+	addq	%r11,%rax
+	addq	%r8,%rax
+	adcq	$0,%r9
+	movq	%rax,96(%rdi)
+	movq	%r9,%rax
+	movq	104(%rsi),%r10
+	movq	112(%rsi),%r11
+	shlq	$9,%r10
+	movq	%r11,%r8
+	shlq	$38,%r11
+	shrq	$26,%r8
+	addq	%r10,%rax
+	addq	%r11,%rax
+	adcq	$0,%r8
+	movq	%rax,104(%rdi)
+	movq	%r8,%rax
+	movq	120(%rsi),%r9
+	movq	128(%rsi),%r10
+	movq	136(%rsi),%r11
+	shlq	$3,%r9
+	shlq	$32,%r10
+	movq	%r11,%r8
+	shlq	$61,%r11
+	shrq	$3,%r8
+	addq	%r9,%rax
+	addq	%r10,%rax
+	addq	%r11,%rax
+	adcq	$0,%r8
+	movq	%rax,112(%rdi)
+	movq	%r8,%rax
+	movq	144(%rsi),%r9
+	movq	152(%rsi),%r10
+	shlq	$26,%r9
+	movq	%r10,%r11
+	shlq	$55,%r10
+	shrq	$9,%r11
+	addq	%r9,%rax
+	addq	%r10,%rax
+	adcq	$0,%r11
+	movq	%rax,120(%rdi)
+	movq	%r11,%rax
+	.byte	0xf3,0xc3
+.size	rsaz_1024_red2norm_avx2,.-rsaz_1024_red2norm_avx2
+
+.globl	rsaz_1024_norm2red_avx2
+.hidden rsaz_1024_norm2red_avx2
+.type	rsaz_1024_norm2red_avx2,@function
+.align	32
+rsaz_1024_norm2red_avx2:
+	subq	$-128,%rdi
+	movq	(%rsi),%r8
+	movl	$0x1fffffff,%eax
+	movq	8(%rsi),%r9
+	movq	%r8,%r11
+	shrq	$0,%r11
+	andq	%rax,%r11
+	movq	%r11,-128(%rdi)
+	movq	%r8,%r10
+	shrq	$29,%r10
+	andq	%rax,%r10
+	movq	%r10,-120(%rdi)
+	shrdq	$58,%r9,%r8
+	andq	%rax,%r8
+	movq	%r8,-112(%rdi)
+	movq	16(%rsi),%r10
+	movq	%r9,%r8
+	shrq	$23,%r8
+	andq	%rax,%r8
+	movq	%r8,-104(%rdi)
+	shrdq	$52,%r10,%r9
+	andq	%rax,%r9
+	movq	%r9,-96(%rdi)
+	movq	24(%rsi),%r11
+	movq	%r10,%r9
+	shrq	$17,%r9
+	andq	%rax,%r9
+	movq	%r9,-88(%rdi)
+	shrdq	$46,%r11,%r10
+	andq	%rax,%r10
+	movq	%r10,-80(%rdi)
+	movq	32(%rsi),%r8
+	movq	%r11,%r10
+	shrq	$11,%r10
+	andq	%rax,%r10
+	movq	%r10,-72(%rdi)
+	shrdq	$40,%r8,%r11
+	andq	%rax,%r11
+	movq	%r11,-64(%rdi)
+	movq	40(%rsi),%r9
+	movq	%r8,%r11
+	shrq	$5,%r11
+	andq	%rax,%r11
+	movq	%r11,-56(%rdi)
+	movq	%r8,%r10
+	shrq	$34,%r10
+	andq	%rax,%r10
+	movq	%r10,-48(%rdi)
+	shrdq	$63,%r9,%r8
+	andq	%rax,%r8
+	movq	%r8,-40(%rdi)
+	movq	48(%rsi),%r10
+	movq	%r9,%r8
+	shrq	$28,%r8
+	andq	%rax,%r8
+	movq	%r8,-32(%rdi)
+	shrdq	$57,%r10,%r9
+	andq	%rax,%r9
+	movq	%r9,-24(%rdi)
+	movq	56(%rsi),%r11
+	movq	%r10,%r9
+	shrq	$22,%r9
+	andq	%rax,%r9
+	movq	%r9,-16(%rdi)
+	shrdq	$51,%r11,%r10
+	andq	%rax,%r10
+	movq	%r10,-8(%rdi)
+	movq	64(%rsi),%r8
+	movq	%r11,%r10
+	shrq	$16,%r10
+	andq	%rax,%r10
+	movq	%r10,0(%rdi)
+	shrdq	$45,%r8,%r11
+	andq	%rax,%r11
+	movq	%r11,8(%rdi)
+	movq	72(%rsi),%r9
+	movq	%r8,%r11
+	shrq	$10,%r11
+	andq	%rax,%r11
+	movq	%r11,16(%rdi)
+	shrdq	$39,%r9,%r8
+	andq	%rax,%r8
+	movq	%r8,24(%rdi)
+	movq	80(%rsi),%r10
+	movq	%r9,%r8
+	shrq	$4,%r8
+	andq	%rax,%r8
+	movq	%r8,32(%rdi)
+	movq	%r9,%r11
+	shrq	$33,%r11
+	andq	%rax,%r11
+	movq	%r11,40(%rdi)
+	shrdq	$62,%r10,%r9
+	andq	%rax,%r9
+	movq	%r9,48(%rdi)
+	movq	88(%rsi),%r11
+	movq	%r10,%r9
+	shrq	$27,%r9
+	andq	%rax,%r9
+	movq	%r9,56(%rdi)
+	shrdq	$56,%r11,%r10
+	andq	%rax,%r10
+	movq	%r10,64(%rdi)
+	movq	96(%rsi),%r8
+	movq	%r11,%r10
+	shrq	$21,%r10
+	andq	%rax,%r10
+	movq	%r10,72(%rdi)
+	shrdq	$50,%r8,%r11
+	andq	%rax,%r11
+	movq	%r11,80(%rdi)
+	movq	104(%rsi),%r9
+	movq	%r8,%r11
+	shrq	$15,%r11
+	andq	%rax,%r11
+	movq	%r11,88(%rdi)
+	shrdq	$44,%r9,%r8
+	andq	%rax,%r8
+	movq	%r8,96(%rdi)
+	movq	112(%rsi),%r10
+	movq	%r9,%r8
+	shrq	$9,%r8
+	andq	%rax,%r8
+	movq	%r8,104(%rdi)
+	shrdq	$38,%r10,%r9
+	andq	%rax,%r9
+	movq	%r9,112(%rdi)
+	movq	120(%rsi),%r11
+	movq	%r10,%r9
+	shrq	$3,%r9
+	andq	%rax,%r9
+	movq	%r9,120(%rdi)
+	movq	%r10,%r8
+	shrq	$32,%r8
+	andq	%rax,%r8
+	movq	%r8,128(%rdi)
+	shrdq	$61,%r11,%r10
+	andq	%rax,%r10
+	movq	%r10,136(%rdi)
+	xorq	%r8,%r8
+	movq	%r11,%r10
+	shrq	$26,%r10
+	andq	%rax,%r10
+	movq	%r10,144(%rdi)
+	shrdq	$55,%r8,%r11
+	andq	%rax,%r11
+	movq	%r11,152(%rdi)
+	movq	%r8,160(%rdi)
+	movq	%r8,168(%rdi)
+	movq	%r8,176(%rdi)
+	movq	%r8,184(%rdi)
+	.byte	0xf3,0xc3
+.size	rsaz_1024_norm2red_avx2,.-rsaz_1024_norm2red_avx2
+.globl	rsaz_1024_scatter5_avx2
+.hidden rsaz_1024_scatter5_avx2
+.type	rsaz_1024_scatter5_avx2,@function
+.align	32
+rsaz_1024_scatter5_avx2:
+	vzeroupper
+	vmovdqu	.Lscatter_permd(%rip),%ymm5
+	shll	$4,%edx
+	leaq	(%rdi,%rdx,1),%rdi
+	movl	$9,%eax
+	jmp	.Loop_scatter_1024
+
+.align	32
+.Loop_scatter_1024:
+	vmovdqu	(%rsi),%ymm0
+	leaq	32(%rsi),%rsi
+	vpermd	%ymm0,%ymm5,%ymm0
+	vmovdqu	%xmm0,(%rdi)
+	leaq	512(%rdi),%rdi
+	decl	%eax
+	jnz	.Loop_scatter_1024
+
+	vzeroupper
+	.byte	0xf3,0xc3
+.size	rsaz_1024_scatter5_avx2,.-rsaz_1024_scatter5_avx2
+
+.globl	rsaz_1024_gather5_avx2
+.hidden rsaz_1024_gather5_avx2
+.type	rsaz_1024_gather5_avx2,@function
+.align	32
+rsaz_1024_gather5_avx2:
+.cfi_startproc	
+	vzeroupper
+	movq	%rsp,%r11
+.cfi_def_cfa_register	%r11
+	leaq	-256(%rsp),%rsp
+	andq	$-32,%rsp
+	leaq	.Linc(%rip),%r10
+	leaq	-128(%rsp),%rax
+
+	vmovd	%edx,%xmm4
+	vmovdqa	(%r10),%ymm0
+	vmovdqa	32(%r10),%ymm1
+	vmovdqa	64(%r10),%ymm5
+	vpbroadcastd	%xmm4,%ymm4
+
+	vpaddd	%ymm5,%ymm0,%ymm2
+	vpcmpeqd	%ymm4,%ymm0,%ymm0
+	vpaddd	%ymm5,%ymm1,%ymm3
+	vpcmpeqd	%ymm4,%ymm1,%ymm1
+	vmovdqa	%ymm0,0+128(%rax)
+	vpaddd	%ymm5,%ymm2,%ymm0
+	vpcmpeqd	%ymm4,%ymm2,%ymm2
+	vmovdqa	%ymm1,32+128(%rax)
+	vpaddd	%ymm5,%ymm3,%ymm1
+	vpcmpeqd	%ymm4,%ymm3,%ymm3
+	vmovdqa	%ymm2,64+128(%rax)
+	vpaddd	%ymm5,%ymm0,%ymm2
+	vpcmpeqd	%ymm4,%ymm0,%ymm0
+	vmovdqa	%ymm3,96+128(%rax)
+	vpaddd	%ymm5,%ymm1,%ymm3
+	vpcmpeqd	%ymm4,%ymm1,%ymm1
+	vmovdqa	%ymm0,128+128(%rax)
+	vpaddd	%ymm5,%ymm2,%ymm8
+	vpcmpeqd	%ymm4,%ymm2,%ymm2
+	vmovdqa	%ymm1,160+128(%rax)
+	vpaddd	%ymm5,%ymm3,%ymm9
+	vpcmpeqd	%ymm4,%ymm3,%ymm3
+	vmovdqa	%ymm2,192+128(%rax)
+	vpaddd	%ymm5,%ymm8,%ymm10
+	vpcmpeqd	%ymm4,%ymm8,%ymm8
+	vmovdqa	%ymm3,224+128(%rax)
+	vpaddd	%ymm5,%ymm9,%ymm11
+	vpcmpeqd	%ymm4,%ymm9,%ymm9
+	vpaddd	%ymm5,%ymm10,%ymm12
+	vpcmpeqd	%ymm4,%ymm10,%ymm10
+	vpaddd	%ymm5,%ymm11,%ymm13
+	vpcmpeqd	%ymm4,%ymm11,%ymm11
+	vpaddd	%ymm5,%ymm12,%ymm14
+	vpcmpeqd	%ymm4,%ymm12,%ymm12
+	vpaddd	%ymm5,%ymm13,%ymm15
+	vpcmpeqd	%ymm4,%ymm13,%ymm13
+	vpcmpeqd	%ymm4,%ymm14,%ymm14
+	vpcmpeqd	%ymm4,%ymm15,%ymm15
+
+	vmovdqa	-32(%r10),%ymm7
+	leaq	128(%rsi),%rsi
+	movl	$9,%edx
+
+.Loop_gather_1024:
+	vmovdqa	0-128(%rsi),%ymm0
+	vmovdqa	32-128(%rsi),%ymm1
+	vmovdqa	64-128(%rsi),%ymm2
+	vmovdqa	96-128(%rsi),%ymm3
+	vpand	0+128(%rax),%ymm0,%ymm0
+	vpand	32+128(%rax),%ymm1,%ymm1
+	vpand	64+128(%rax),%ymm2,%ymm2
+	vpor	%ymm0,%ymm1,%ymm4
+	vpand	96+128(%rax),%ymm3,%ymm3
+	vmovdqa	128-128(%rsi),%ymm0
+	vmovdqa	160-128(%rsi),%ymm1
+	vpor	%ymm2,%ymm3,%ymm5
+	vmovdqa	192-128(%rsi),%ymm2
+	vmovdqa	224-128(%rsi),%ymm3
+	vpand	128+128(%rax),%ymm0,%ymm0
+	vpand	160+128(%rax),%ymm1,%ymm1
+	vpand	192+128(%rax),%ymm2,%ymm2
+	vpor	%ymm0,%ymm4,%ymm4
+	vpand	224+128(%rax),%ymm3,%ymm3
+	vpand	256-128(%rsi),%ymm8,%ymm0
+	vpor	%ymm1,%ymm5,%ymm5
+	vpand	288-128(%rsi),%ymm9,%ymm1
+	vpor	%ymm2,%ymm4,%ymm4
+	vpand	320-128(%rsi),%ymm10,%ymm2
+	vpor	%ymm3,%ymm5,%ymm5
+	vpand	352-128(%rsi),%ymm11,%ymm3
+	vpor	%ymm0,%ymm4,%ymm4
+	vpand	384-128(%rsi),%ymm12,%ymm0
+	vpor	%ymm1,%ymm5,%ymm5
+	vpand	416-128(%rsi),%ymm13,%ymm1
+	vpor	%ymm2,%ymm4,%ymm4
+	vpand	448-128(%rsi),%ymm14,%ymm2
+	vpor	%ymm3,%ymm5,%ymm5
+	vpand	480-128(%rsi),%ymm15,%ymm3
+	leaq	512(%rsi),%rsi
+	vpor	%ymm0,%ymm4,%ymm4
+	vpor	%ymm1,%ymm5,%ymm5
+	vpor	%ymm2,%ymm4,%ymm4
+	vpor	%ymm3,%ymm5,%ymm5
+
+	vpor	%ymm5,%ymm4,%ymm4
+	vextracti128	$1,%ymm4,%xmm5
+	vpor	%xmm4,%xmm5,%xmm5
+	vpermd	%ymm5,%ymm7,%ymm5
+	vmovdqu	%ymm5,(%rdi)
+	leaq	32(%rdi),%rdi
+	decl	%edx
+	jnz	.Loop_gather_1024
+
+	vpxor	%ymm0,%ymm0,%ymm0
+	vmovdqu	%ymm0,(%rdi)
+	vzeroupper
+	leaq	(%r11),%rsp
+.cfi_def_cfa_register	%rsp
+	.byte	0xf3,0xc3
+.cfi_endproc	
+.LSEH_end_rsaz_1024_gather5:
+.size	rsaz_1024_gather5_avx2,.-rsaz_1024_gather5_avx2
+.extern	OPENSSL_ia32cap_P
+.hidden OPENSSL_ia32cap_P
 .globl	rsaz_avx2_eligible
 .hidden rsaz_avx2_eligible
 .type	rsaz_avx2_eligible,@function
+.align	32
 rsaz_avx2_eligible:
-	xorl	%eax,%eax
+	movl	OPENSSL_ia32cap_P+8(%rip),%eax
+	movl	$524544,%ecx
+	movl	$0,%edx
+	andl	%eax,%ecx
+	cmpl	$524544,%ecx
+	cmovel	%edx,%eax
+	andl	$32,%eax
+	shrl	$5,%eax
 	.byte	0xf3,0xc3
 .size	rsaz_avx2_eligible,.-rsaz_avx2_eligible
 
-.globl	rsaz_1024_sqr_avx2
-.hidden rsaz_1024_sqr_avx2
-.globl	rsaz_1024_mul_avx2
-.hidden rsaz_1024_mul_avx2
-.globl	rsaz_1024_norm2red_avx2
-.hidden rsaz_1024_norm2red_avx2
-.globl	rsaz_1024_red2norm_avx2
-.hidden rsaz_1024_red2norm_avx2
-.globl	rsaz_1024_scatter5_avx2
-.hidden rsaz_1024_scatter5_avx2
-.globl	rsaz_1024_gather5_avx2
-.hidden rsaz_1024_gather5_avx2
-.type	rsaz_1024_sqr_avx2,@function
-rsaz_1024_sqr_avx2:
-rsaz_1024_mul_avx2:
-rsaz_1024_norm2red_avx2:
-rsaz_1024_red2norm_avx2:
-rsaz_1024_scatter5_avx2:
-rsaz_1024_gather5_avx2:
-.byte	0x0f,0x0b
-	.byte	0xf3,0xc3
-.size	rsaz_1024_sqr_avx2,.-rsaz_1024_sqr_avx2
+.align	64
+.Land_mask:
+.quad	0x1fffffff,0x1fffffff,0x1fffffff,-1
+.Lscatter_permd:
+.long	0,2,4,6,7,7,7,7
+.Lgather_permd:
+.long	0,7,1,7,2,7,3,7
+.Linc:
+.long	0,0,0,0, 1,1,1,1
+.long	2,2,2,2, 3,3,3,3
+.long	4,4,4,4, 4,4,4,4
+.align	64
 #endif
diff --git a/linux-x86_64/crypto/bn/rsaz-x86_64.S b/linux-x86_64/crypto/bn/rsaz-x86_64.S
deleted file mode 100644
index dd3d310..0000000
--- a/linux-x86_64/crypto/bn/rsaz-x86_64.S
+++ /dev/null
@@ -1,1127 +0,0 @@
-#if defined(__x86_64__)
-.text	
-
-.extern	OPENSSL_ia32cap_P
-.hidden OPENSSL_ia32cap_P
-
-.globl	rsaz_512_sqr
-.hidden rsaz_512_sqr
-.type	rsaz_512_sqr,@function
-.align	32
-rsaz_512_sqr:
-	pushq	%rbx
-	pushq	%rbp
-	pushq	%r12
-	pushq	%r13
-	pushq	%r14
-	pushq	%r15
-
-	subq	$128+24,%rsp
-.Lsqr_body:
-	movq	%rdx,%rbp
-	movq	(%rsi),%rdx
-	movq	8(%rsi),%rax
-	movq	%rcx,128(%rsp)
-	jmp	.Loop_sqr
-
-.align	32
-.Loop_sqr:
-	movl	%r8d,128+8(%rsp)
-
-	movq	%rdx,%rbx
-	mulq	%rdx
-	movq	%rax,%r8
-	movq	16(%rsi),%rax
-	movq	%rdx,%r9
-
-	mulq	%rbx
-	addq	%rax,%r9
-	movq	24(%rsi),%rax
-	movq	%rdx,%r10
-	adcq	$0,%r10
-
-	mulq	%rbx
-	addq	%rax,%r10
-	movq	32(%rsi),%rax
-	movq	%rdx,%r11
-	adcq	$0,%r11
-
-	mulq	%rbx
-	addq	%rax,%r11
-	movq	40(%rsi),%rax
-	movq	%rdx,%r12
-	adcq	$0,%r12
-
-	mulq	%rbx
-	addq	%rax,%r12
-	movq	48(%rsi),%rax
-	movq	%rdx,%r13
-	adcq	$0,%r13
-
-	mulq	%rbx
-	addq	%rax,%r13
-	movq	56(%rsi),%rax
-	movq	%rdx,%r14
-	adcq	$0,%r14
-
-	mulq	%rbx
-	addq	%rax,%r14
-	movq	%rbx,%rax
-	movq	%rdx,%r15
-	adcq	$0,%r15
-
-	addq	%r8,%r8
-	movq	%r9,%rcx
-	adcq	%r9,%r9
-
-	mulq	%rax
-	movq	%rax,(%rsp)
-	addq	%rdx,%r8
-	adcq	$0,%r9
-
-	movq	%r8,8(%rsp)
-	shrq	$63,%rcx
-
-
-	movq	8(%rsi),%r8
-	movq	16(%rsi),%rax
-	mulq	%r8
-	addq	%rax,%r10
-	movq	24(%rsi),%rax
-	movq	%rdx,%rbx
-	adcq	$0,%rbx
-
-	mulq	%r8
-	addq	%rax,%r11
-	movq	32(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%rbx,%r11
-	movq	%rdx,%rbx
-	adcq	$0,%rbx
-
-	mulq	%r8
-	addq	%rax,%r12
-	movq	40(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%rbx,%r12
-	movq	%rdx,%rbx
-	adcq	$0,%rbx
-
-	mulq	%r8
-	addq	%rax,%r13
-	movq	48(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%rbx,%r13
-	movq	%rdx,%rbx
-	adcq	$0,%rbx
-
-	mulq	%r8
-	addq	%rax,%r14
-	movq	56(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%rbx,%r14
-	movq	%rdx,%rbx
-	adcq	$0,%rbx
-
-	mulq	%r8
-	addq	%rax,%r15
-	movq	%r8,%rax
-	adcq	$0,%rdx
-	addq	%rbx,%r15
-	movq	%rdx,%r8
-	movq	%r10,%rdx
-	adcq	$0,%r8
-
-	addq	%rdx,%rdx
-	leaq	(%rcx,%r10,2),%r10
-	movq	%r11,%rbx
-	adcq	%r11,%r11
-
-	mulq	%rax
-	addq	%rax,%r9
-	adcq	%rdx,%r10
-	adcq	$0,%r11
-
-	movq	%r9,16(%rsp)
-	movq	%r10,24(%rsp)
-	shrq	$63,%rbx
-
-
-	movq	16(%rsi),%r9
-	movq	24(%rsi),%rax
-	mulq	%r9
-	addq	%rax,%r12
-	movq	32(%rsi),%rax
-	movq	%rdx,%rcx
-	adcq	$0,%rcx
-
-	mulq	%r9
-	addq	%rax,%r13
-	movq	40(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%rcx,%r13
-	movq	%rdx,%rcx
-	adcq	$0,%rcx
-
-	mulq	%r9
-	addq	%rax,%r14
-	movq	48(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%rcx,%r14
-	movq	%rdx,%rcx
-	adcq	$0,%rcx
-
-	mulq	%r9
-	movq	%r12,%r10
-	leaq	(%rbx,%r12,2),%r12
-	addq	%rax,%r15
-	movq	56(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%rcx,%r15
-	movq	%rdx,%rcx
-	adcq	$0,%rcx
-
-	mulq	%r9
-	shrq	$63,%r10
-	addq	%rax,%r8
-	movq	%r9,%rax
-	adcq	$0,%rdx
-	addq	%rcx,%r8
-	movq	%rdx,%r9
-	adcq	$0,%r9
-
-	movq	%r13,%rcx
-	leaq	(%r10,%r13,2),%r13
-
-	mulq	%rax
-	addq	%rax,%r11
-	adcq	%rdx,%r12
-	adcq	$0,%r13
-
-	movq	%r11,32(%rsp)
-	movq	%r12,40(%rsp)
-	shrq	$63,%rcx
-
-
-	movq	24(%rsi),%r10
-	movq	32(%rsi),%rax
-	mulq	%r10
-	addq	%rax,%r14
-	movq	40(%rsi),%rax
-	movq	%rdx,%rbx
-	adcq	$0,%rbx
-
-	mulq	%r10
-	addq	%rax,%r15
-	movq	48(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%rbx,%r15
-	movq	%rdx,%rbx
-	adcq	$0,%rbx
-
-	mulq	%r10
-	movq	%r14,%r12
-	leaq	(%rcx,%r14,2),%r14
-	addq	%rax,%r8
-	movq	56(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%rbx,%r8
-	movq	%rdx,%rbx
-	adcq	$0,%rbx
-
-	mulq	%r10
-	shrq	$63,%r12
-	addq	%rax,%r9
-	movq	%r10,%rax
-	adcq	$0,%rdx
-	addq	%rbx,%r9
-	movq	%rdx,%r10
-	adcq	$0,%r10
-
-	movq	%r15,%rbx
-	leaq	(%r12,%r15,2),%r15
-
-	mulq	%rax
-	addq	%rax,%r13
-	adcq	%rdx,%r14
-	adcq	$0,%r15
-
-	movq	%r13,48(%rsp)
-	movq	%r14,56(%rsp)
-	shrq	$63,%rbx
-
-
-	movq	32(%rsi),%r11
-	movq	40(%rsi),%rax
-	mulq	%r11
-	addq	%rax,%r8
-	movq	48(%rsi),%rax
-	movq	%rdx,%rcx
-	adcq	$0,%rcx
-
-	mulq	%r11
-	addq	%rax,%r9
-	movq	56(%rsi),%rax
-	adcq	$0,%rdx
-	movq	%r8,%r12
-	leaq	(%rbx,%r8,2),%r8
-	addq	%rcx,%r9
-	movq	%rdx,%rcx
-	adcq	$0,%rcx
-
-	mulq	%r11
-	shrq	$63,%r12
-	addq	%rax,%r10
-	movq	%r11,%rax
-	adcq	$0,%rdx
-	addq	%rcx,%r10
-	movq	%rdx,%r11
-	adcq	$0,%r11
-
-	movq	%r9,%rcx
-	leaq	(%r12,%r9,2),%r9
-
-	mulq	%rax
-	addq	%rax,%r15
-	adcq	%rdx,%r8
-	adcq	$0,%r9
-
-	movq	%r15,64(%rsp)
-	movq	%r8,72(%rsp)
-	shrq	$63,%rcx
-
-
-	movq	40(%rsi),%r12
-	movq	48(%rsi),%rax
-	mulq	%r12
-	addq	%rax,%r10
-	movq	56(%rsi),%rax
-	movq	%rdx,%rbx
-	adcq	$0,%rbx
-
-	mulq	%r12
-	addq	%rax,%r11
-	movq	%r12,%rax
-	movq	%r10,%r15
-	leaq	(%rcx,%r10,2),%r10
-	adcq	$0,%rdx
-	shrq	$63,%r15
-	addq	%rbx,%r11
-	movq	%rdx,%r12
-	adcq	$0,%r12
-
-	movq	%r11,%rbx
-	leaq	(%r15,%r11,2),%r11
-
-	mulq	%rax
-	addq	%rax,%r9
-	adcq	%rdx,%r10
-	adcq	$0,%r11
-
-	movq	%r9,80(%rsp)
-	movq	%r10,88(%rsp)
-
-
-	movq	48(%rsi),%r13
-	movq	56(%rsi),%rax
-	mulq	%r13
-	addq	%rax,%r12
-	movq	%r13,%rax
-	movq	%rdx,%r13
-	adcq	$0,%r13
-
-	xorq	%r14,%r14
-	shlq	$1,%rbx
-	adcq	%r12,%r12
-	adcq	%r13,%r13
-	adcq	%r14,%r14
-
-	mulq	%rax
-	addq	%rax,%r11
-	adcq	%rdx,%r12
-	adcq	$0,%r13
-
-	movq	%r11,96(%rsp)
-	movq	%r12,104(%rsp)
-
-
-	movq	56(%rsi),%rax
-	mulq	%rax
-	addq	%rax,%r13
-	adcq	$0,%rdx
-
-	addq	%rdx,%r14
-
-	movq	%r13,112(%rsp)
-	movq	%r14,120(%rsp)
-
-	movq	(%rsp),%r8
-	movq	8(%rsp),%r9
-	movq	16(%rsp),%r10
-	movq	24(%rsp),%r11
-	movq	32(%rsp),%r12
-	movq	40(%rsp),%r13
-	movq	48(%rsp),%r14
-	movq	56(%rsp),%r15
-
-	call	__rsaz_512_reduce
-
-	addq	64(%rsp),%r8
-	adcq	72(%rsp),%r9
-	adcq	80(%rsp),%r10
-	adcq	88(%rsp),%r11
-	adcq	96(%rsp),%r12
-	adcq	104(%rsp),%r13
-	adcq	112(%rsp),%r14
-	adcq	120(%rsp),%r15
-	sbbq	%rcx,%rcx
-
-	call	__rsaz_512_subtract
-
-	movq	%r8,%rdx
-	movq	%r9,%rax
-	movl	128+8(%rsp),%r8d
-	movq	%rdi,%rsi
-
-	decl	%r8d
-	jnz	.Loop_sqr
-
-	leaq	128+24+48(%rsp),%rax
-	movq	-48(%rax),%r15
-	movq	-40(%rax),%r14
-	movq	-32(%rax),%r13
-	movq	-24(%rax),%r12
-	movq	-16(%rax),%rbp
-	movq	-8(%rax),%rbx
-	leaq	(%rax),%rsp
-.Lsqr_epilogue:
-	.byte	0xf3,0xc3
-.size	rsaz_512_sqr,.-rsaz_512_sqr
-.globl	rsaz_512_mul
-.hidden rsaz_512_mul
-.type	rsaz_512_mul,@function
-.align	32
-rsaz_512_mul:
-	pushq	%rbx
-	pushq	%rbp
-	pushq	%r12
-	pushq	%r13
-	pushq	%r14
-	pushq	%r15
-
-	subq	$128+24,%rsp
-.Lmul_body:
-.byte	102,72,15,110,199
-.byte	102,72,15,110,201
-	movq	%r8,128(%rsp)
-	movq	(%rdx),%rbx
-	movq	%rdx,%rbp
-	call	__rsaz_512_mul
-
-.byte	102,72,15,126,199
-.byte	102,72,15,126,205
-
-	movq	(%rsp),%r8
-	movq	8(%rsp),%r9
-	movq	16(%rsp),%r10
-	movq	24(%rsp),%r11
-	movq	32(%rsp),%r12
-	movq	40(%rsp),%r13
-	movq	48(%rsp),%r14
-	movq	56(%rsp),%r15
-
-	call	__rsaz_512_reduce
-	addq	64(%rsp),%r8
-	adcq	72(%rsp),%r9
-	adcq	80(%rsp),%r10
-	adcq	88(%rsp),%r11
-	adcq	96(%rsp),%r12
-	adcq	104(%rsp),%r13
-	adcq	112(%rsp),%r14
-	adcq	120(%rsp),%r15
-	sbbq	%rcx,%rcx
-
-	call	__rsaz_512_subtract
-
-	leaq	128+24+48(%rsp),%rax
-	movq	-48(%rax),%r15
-	movq	-40(%rax),%r14
-	movq	-32(%rax),%r13
-	movq	-24(%rax),%r12
-	movq	-16(%rax),%rbp
-	movq	-8(%rax),%rbx
-	leaq	(%rax),%rsp
-.Lmul_epilogue:
-	.byte	0xf3,0xc3
-.size	rsaz_512_mul,.-rsaz_512_mul
-.globl	rsaz_512_mul_gather4
-.hidden rsaz_512_mul_gather4
-.type	rsaz_512_mul_gather4,@function
-.align	32
-rsaz_512_mul_gather4:
-	pushq	%rbx
-	pushq	%rbp
-	pushq	%r12
-	pushq	%r13
-	pushq	%r14
-	pushq	%r15
-
-	movl	%r9d,%r9d
-	subq	$128+24,%rsp
-.Lmul_gather4_body:
-	movl	64(%rdx,%r9,4),%eax
-.byte	102,72,15,110,199
-	movl	(%rdx,%r9,4),%ebx
-.byte	102,72,15,110,201
-	movq	%r8,128(%rsp)
-
-	shlq	$32,%rax
-	orq	%rax,%rbx
-	movq	(%rsi),%rax
-	movq	8(%rsi),%rcx
-	leaq	128(%rdx,%r9,4),%rbp
-	mulq	%rbx
-	movq	%rax,(%rsp)
-	movq	%rcx,%rax
-	movq	%rdx,%r8
-
-	mulq	%rbx
-	movd	(%rbp),%xmm4
-	addq	%rax,%r8
-	movq	16(%rsi),%rax
-	movq	%rdx,%r9
-	adcq	$0,%r9
-
-	mulq	%rbx
-	movd	64(%rbp),%xmm5
-	addq	%rax,%r9
-	movq	24(%rsi),%rax
-	movq	%rdx,%r10
-	adcq	$0,%r10
-
-	mulq	%rbx
-	pslldq	$4,%xmm5
-	addq	%rax,%r10
-	movq	32(%rsi),%rax
-	movq	%rdx,%r11
-	adcq	$0,%r11
-
-	mulq	%rbx
-	por	%xmm5,%xmm4
-	addq	%rax,%r11
-	movq	40(%rsi),%rax
-	movq	%rdx,%r12
-	adcq	$0,%r12
-
-	mulq	%rbx
-	addq	%rax,%r12
-	movq	48(%rsi),%rax
-	movq	%rdx,%r13
-	adcq	$0,%r13
-
-	mulq	%rbx
-	leaq	128(%rbp),%rbp
-	addq	%rax,%r13
-	movq	56(%rsi),%rax
-	movq	%rdx,%r14
-	adcq	$0,%r14
-
-	mulq	%rbx
-.byte	102,72,15,126,227
-	addq	%rax,%r14
-	movq	(%rsi),%rax
-	movq	%rdx,%r15
-	adcq	$0,%r15
-
-	leaq	8(%rsp),%rdi
-	movl	$7,%ecx
-	jmp	.Loop_mul_gather
-
-.align	32
-.Loop_mul_gather:
-	mulq	%rbx
-	addq	%rax,%r8
-	movq	8(%rsi),%rax
-	movq	%r8,(%rdi)
-	movq	%rdx,%r8
-	adcq	$0,%r8
-
-	mulq	%rbx
-	movd	(%rbp),%xmm4
-	addq	%rax,%r9
-	movq	16(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%r9,%r8
-	movq	%rdx,%r9
-	adcq	$0,%r9
-
-	mulq	%rbx
-	movd	64(%rbp),%xmm5
-	addq	%rax,%r10
-	movq	24(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%r10,%r9
-	movq	%rdx,%r10
-	adcq	$0,%r10
-
-	mulq	%rbx
-	pslldq	$4,%xmm5
-	addq	%rax,%r11
-	movq	32(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%r11,%r10
-	movq	%rdx,%r11
-	adcq	$0,%r11
-
-	mulq	%rbx
-	por	%xmm5,%xmm4
-	addq	%rax,%r12
-	movq	40(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%r12,%r11
-	movq	%rdx,%r12
-	adcq	$0,%r12
-
-	mulq	%rbx
-	addq	%rax,%r13
-	movq	48(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%r13,%r12
-	movq	%rdx,%r13
-	adcq	$0,%r13
-
-	mulq	%rbx
-	addq	%rax,%r14
-	movq	56(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%r14,%r13
-	movq	%rdx,%r14
-	adcq	$0,%r14
-
-	mulq	%rbx
-.byte	102,72,15,126,227
-	addq	%rax,%r15
-	movq	(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%r15,%r14
-	movq	%rdx,%r15
-	adcq	$0,%r15
-
-	leaq	128(%rbp),%rbp
-	leaq	8(%rdi),%rdi
-
-	decl	%ecx
-	jnz	.Loop_mul_gather
-
-	movq	%r8,(%rdi)
-	movq	%r9,8(%rdi)
-	movq	%r10,16(%rdi)
-	movq	%r11,24(%rdi)
-	movq	%r12,32(%rdi)
-	movq	%r13,40(%rdi)
-	movq	%r14,48(%rdi)
-	movq	%r15,56(%rdi)
-
-.byte	102,72,15,126,199
-.byte	102,72,15,126,205
-
-	movq	(%rsp),%r8
-	movq	8(%rsp),%r9
-	movq	16(%rsp),%r10
-	movq	24(%rsp),%r11
-	movq	32(%rsp),%r12
-	movq	40(%rsp),%r13
-	movq	48(%rsp),%r14
-	movq	56(%rsp),%r15
-
-	call	__rsaz_512_reduce
-	addq	64(%rsp),%r8
-	adcq	72(%rsp),%r9
-	adcq	80(%rsp),%r10
-	adcq	88(%rsp),%r11
-	adcq	96(%rsp),%r12
-	adcq	104(%rsp),%r13
-	adcq	112(%rsp),%r14
-	adcq	120(%rsp),%r15
-	sbbq	%rcx,%rcx
-
-	call	__rsaz_512_subtract
-
-	leaq	128+24+48(%rsp),%rax
-	movq	-48(%rax),%r15
-	movq	-40(%rax),%r14
-	movq	-32(%rax),%r13
-	movq	-24(%rax),%r12
-	movq	-16(%rax),%rbp
-	movq	-8(%rax),%rbx
-	leaq	(%rax),%rsp
-.Lmul_gather4_epilogue:
-	.byte	0xf3,0xc3
-.size	rsaz_512_mul_gather4,.-rsaz_512_mul_gather4
-.globl	rsaz_512_mul_scatter4
-.hidden rsaz_512_mul_scatter4
-.type	rsaz_512_mul_scatter4,@function
-.align	32
-rsaz_512_mul_scatter4:
-	pushq	%rbx
-	pushq	%rbp
-	pushq	%r12
-	pushq	%r13
-	pushq	%r14
-	pushq	%r15
-
-	movl	%r9d,%r9d
-	subq	$128+24,%rsp
-.Lmul_scatter4_body:
-	leaq	(%r8,%r9,4),%r8
-.byte	102,72,15,110,199
-.byte	102,72,15,110,202
-.byte	102,73,15,110,208
-	movq	%rcx,128(%rsp)
-
-	movq	%rdi,%rbp
-	movq	(%rdi),%rbx
-	call	__rsaz_512_mul
-
-.byte	102,72,15,126,199
-.byte	102,72,15,126,205
-
-	movq	(%rsp),%r8
-	movq	8(%rsp),%r9
-	movq	16(%rsp),%r10
-	movq	24(%rsp),%r11
-	movq	32(%rsp),%r12
-	movq	40(%rsp),%r13
-	movq	48(%rsp),%r14
-	movq	56(%rsp),%r15
-
-	call	__rsaz_512_reduce
-	addq	64(%rsp),%r8
-	adcq	72(%rsp),%r9
-	adcq	80(%rsp),%r10
-	adcq	88(%rsp),%r11
-	adcq	96(%rsp),%r12
-	adcq	104(%rsp),%r13
-	adcq	112(%rsp),%r14
-	adcq	120(%rsp),%r15
-.byte	102,72,15,126,214
-	sbbq	%rcx,%rcx
-
-	call	__rsaz_512_subtract
-
-	movl	%r8d,0(%rsi)
-	shrq	$32,%r8
-	movl	%r9d,128(%rsi)
-	shrq	$32,%r9
-	movl	%r10d,256(%rsi)
-	shrq	$32,%r10
-	movl	%r11d,384(%rsi)
-	shrq	$32,%r11
-	movl	%r12d,512(%rsi)
-	shrq	$32,%r12
-	movl	%r13d,640(%rsi)
-	shrq	$32,%r13
-	movl	%r14d,768(%rsi)
-	shrq	$32,%r14
-	movl	%r15d,896(%rsi)
-	shrq	$32,%r15
-	movl	%r8d,64(%rsi)
-	movl	%r9d,192(%rsi)
-	movl	%r10d,320(%rsi)
-	movl	%r11d,448(%rsi)
-	movl	%r12d,576(%rsi)
-	movl	%r13d,704(%rsi)
-	movl	%r14d,832(%rsi)
-	movl	%r15d,960(%rsi)
-
-	leaq	128+24+48(%rsp),%rax
-	movq	-48(%rax),%r15
-	movq	-40(%rax),%r14
-	movq	-32(%rax),%r13
-	movq	-24(%rax),%r12
-	movq	-16(%rax),%rbp
-	movq	-8(%rax),%rbx
-	leaq	(%rax),%rsp
-.Lmul_scatter4_epilogue:
-	.byte	0xf3,0xc3
-.size	rsaz_512_mul_scatter4,.-rsaz_512_mul_scatter4
-.globl	rsaz_512_mul_by_one
-.hidden rsaz_512_mul_by_one
-.type	rsaz_512_mul_by_one,@function
-.align	32
-rsaz_512_mul_by_one:
-	pushq	%rbx
-	pushq	%rbp
-	pushq	%r12
-	pushq	%r13
-	pushq	%r14
-	pushq	%r15
-
-	subq	$128+24,%rsp
-.Lmul_by_one_body:
-	movq	%rdx,%rbp
-	movq	%rcx,128(%rsp)
-
-	movq	(%rsi),%r8
-	pxor	%xmm0,%xmm0
-	movq	8(%rsi),%r9
-	movq	16(%rsi),%r10
-	movq	24(%rsi),%r11
-	movq	32(%rsi),%r12
-	movq	40(%rsi),%r13
-	movq	48(%rsi),%r14
-	movq	56(%rsi),%r15
-
-	movdqa	%xmm0,(%rsp)
-	movdqa	%xmm0,16(%rsp)
-	movdqa	%xmm0,32(%rsp)
-	movdqa	%xmm0,48(%rsp)
-	movdqa	%xmm0,64(%rsp)
-	movdqa	%xmm0,80(%rsp)
-	movdqa	%xmm0,96(%rsp)
-	call	__rsaz_512_reduce
-	movq	%r8,(%rdi)
-	movq	%r9,8(%rdi)
-	movq	%r10,16(%rdi)
-	movq	%r11,24(%rdi)
-	movq	%r12,32(%rdi)
-	movq	%r13,40(%rdi)
-	movq	%r14,48(%rdi)
-	movq	%r15,56(%rdi)
-
-	leaq	128+24+48(%rsp),%rax
-	movq	-48(%rax),%r15
-	movq	-40(%rax),%r14
-	movq	-32(%rax),%r13
-	movq	-24(%rax),%r12
-	movq	-16(%rax),%rbp
-	movq	-8(%rax),%rbx
-	leaq	(%rax),%rsp
-.Lmul_by_one_epilogue:
-	.byte	0xf3,0xc3
-.size	rsaz_512_mul_by_one,.-rsaz_512_mul_by_one
-.type	__rsaz_512_reduce,@function
-.align	32
-__rsaz_512_reduce:
-	movq	%r8,%rbx
-	imulq	128+8(%rsp),%rbx
-	movq	0(%rbp),%rax
-	movl	$8,%ecx
-	jmp	.Lreduction_loop
-
-.align	32
-.Lreduction_loop:
-	mulq	%rbx
-	movq	8(%rbp),%rax
-	negq	%r8
-	movq	%rdx,%r8
-	adcq	$0,%r8
-
-	mulq	%rbx
-	addq	%rax,%r9
-	movq	16(%rbp),%rax
-	adcq	$0,%rdx
-	addq	%r9,%r8
-	movq	%rdx,%r9
-	adcq	$0,%r9
-
-	mulq	%rbx
-	addq	%rax,%r10
-	movq	24(%rbp),%rax
-	adcq	$0,%rdx
-	addq	%r10,%r9
-	movq	%rdx,%r10
-	adcq	$0,%r10
-
-	mulq	%rbx
-	addq	%rax,%r11
-	movq	32(%rbp),%rax
-	adcq	$0,%rdx
-	addq	%r11,%r10
-	movq	128+8(%rsp),%rsi
-
-
-	adcq	$0,%rdx
-	movq	%rdx,%r11
-
-	mulq	%rbx
-	addq	%rax,%r12
-	movq	40(%rbp),%rax
-	adcq	$0,%rdx
-	imulq	%r8,%rsi
-	addq	%r12,%r11
-	movq	%rdx,%r12
-	adcq	$0,%r12
-
-	mulq	%rbx
-	addq	%rax,%r13
-	movq	48(%rbp),%rax
-	adcq	$0,%rdx
-	addq	%r13,%r12
-	movq	%rdx,%r13
-	adcq	$0,%r13
-
-	mulq	%rbx
-	addq	%rax,%r14
-	movq	56(%rbp),%rax
-	adcq	$0,%rdx
-	addq	%r14,%r13
-	movq	%rdx,%r14
-	adcq	$0,%r14
-
-	mulq	%rbx
-	movq	%rsi,%rbx
-	addq	%rax,%r15
-	movq	0(%rbp),%rax
-	adcq	$0,%rdx
-	addq	%r15,%r14
-	movq	%rdx,%r15
-	adcq	$0,%r15
-
-	decl	%ecx
-	jne	.Lreduction_loop
-
-	.byte	0xf3,0xc3
-.size	__rsaz_512_reduce,.-__rsaz_512_reduce
-.type	__rsaz_512_subtract,@function
-.align	32
-__rsaz_512_subtract:
-	movq	%r8,(%rdi)
-	movq	%r9,8(%rdi)
-	movq	%r10,16(%rdi)
-	movq	%r11,24(%rdi)
-	movq	%r12,32(%rdi)
-	movq	%r13,40(%rdi)
-	movq	%r14,48(%rdi)
-	movq	%r15,56(%rdi)
-
-	movq	0(%rbp),%r8
-	movq	8(%rbp),%r9
-	negq	%r8
-	notq	%r9
-	andq	%rcx,%r8
-	movq	16(%rbp),%r10
-	andq	%rcx,%r9
-	notq	%r10
-	movq	24(%rbp),%r11
-	andq	%rcx,%r10
-	notq	%r11
-	movq	32(%rbp),%r12
-	andq	%rcx,%r11
-	notq	%r12
-	movq	40(%rbp),%r13
-	andq	%rcx,%r12
-	notq	%r13
-	movq	48(%rbp),%r14
-	andq	%rcx,%r13
-	notq	%r14
-	movq	56(%rbp),%r15
-	andq	%rcx,%r14
-	notq	%r15
-	andq	%rcx,%r15
-
-	addq	(%rdi),%r8
-	adcq	8(%rdi),%r9
-	adcq	16(%rdi),%r10
-	adcq	24(%rdi),%r11
-	adcq	32(%rdi),%r12
-	adcq	40(%rdi),%r13
-	adcq	48(%rdi),%r14
-	adcq	56(%rdi),%r15
-
-	movq	%r8,(%rdi)
-	movq	%r9,8(%rdi)
-	movq	%r10,16(%rdi)
-	movq	%r11,24(%rdi)
-	movq	%r12,32(%rdi)
-	movq	%r13,40(%rdi)
-	movq	%r14,48(%rdi)
-	movq	%r15,56(%rdi)
-
-	.byte	0xf3,0xc3
-.size	__rsaz_512_subtract,.-__rsaz_512_subtract
-.type	__rsaz_512_mul,@function
-.align	32
-__rsaz_512_mul:
-	leaq	8(%rsp),%rdi
-
-	movq	(%rsi),%rax
-	mulq	%rbx
-	movq	%rax,(%rdi)
-	movq	8(%rsi),%rax
-	movq	%rdx,%r8
-
-	mulq	%rbx
-	addq	%rax,%r8
-	movq	16(%rsi),%rax
-	movq	%rdx,%r9
-	adcq	$0,%r9
-
-	mulq	%rbx
-	addq	%rax,%r9
-	movq	24(%rsi),%rax
-	movq	%rdx,%r10
-	adcq	$0,%r10
-
-	mulq	%rbx
-	addq	%rax,%r10
-	movq	32(%rsi),%rax
-	movq	%rdx,%r11
-	adcq	$0,%r11
-
-	mulq	%rbx
-	addq	%rax,%r11
-	movq	40(%rsi),%rax
-	movq	%rdx,%r12
-	adcq	$0,%r12
-
-	mulq	%rbx
-	addq	%rax,%r12
-	movq	48(%rsi),%rax
-	movq	%rdx,%r13
-	adcq	$0,%r13
-
-	mulq	%rbx
-	addq	%rax,%r13
-	movq	56(%rsi),%rax
-	movq	%rdx,%r14
-	adcq	$0,%r14
-
-	mulq	%rbx
-	addq	%rax,%r14
-	movq	(%rsi),%rax
-	movq	%rdx,%r15
-	adcq	$0,%r15
-
-	leaq	8(%rbp),%rbp
-	leaq	8(%rdi),%rdi
-
-	movl	$7,%ecx
-	jmp	.Loop_mul
-
-.align	32
-.Loop_mul:
-	movq	(%rbp),%rbx
-	mulq	%rbx
-	addq	%rax,%r8
-	movq	8(%rsi),%rax
-	movq	%r8,(%rdi)
-	movq	%rdx,%r8
-	adcq	$0,%r8
-
-	mulq	%rbx
-	addq	%rax,%r9
-	movq	16(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%r9,%r8
-	movq	%rdx,%r9
-	adcq	$0,%r9
-
-	mulq	%rbx
-	addq	%rax,%r10
-	movq	24(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%r10,%r9
-	movq	%rdx,%r10
-	adcq	$0,%r10
-
-	mulq	%rbx
-	addq	%rax,%r11
-	movq	32(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%r11,%r10
-	movq	%rdx,%r11
-	adcq	$0,%r11
-
-	mulq	%rbx
-	addq	%rax,%r12
-	movq	40(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%r12,%r11
-	movq	%rdx,%r12
-	adcq	$0,%r12
-
-	mulq	%rbx
-	addq	%rax,%r13
-	movq	48(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%r13,%r12
-	movq	%rdx,%r13
-	adcq	$0,%r13
-
-	mulq	%rbx
-	addq	%rax,%r14
-	movq	56(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%r14,%r13
-	movq	%rdx,%r14
-	leaq	8(%rbp),%rbp
-	adcq	$0,%r14
-
-	mulq	%rbx
-	addq	%rax,%r15
-	movq	(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%r15,%r14
-	movq	%rdx,%r15
-	adcq	$0,%r15
-
-	leaq	8(%rdi),%rdi
-
-	decl	%ecx
-	jnz	.Loop_mul
-
-	movq	%r8,(%rdi)
-	movq	%r9,8(%rdi)
-	movq	%r10,16(%rdi)
-	movq	%r11,24(%rdi)
-	movq	%r12,32(%rdi)
-	movq	%r13,40(%rdi)
-	movq	%r14,48(%rdi)
-	movq	%r15,56(%rdi)
-
-	.byte	0xf3,0xc3
-.size	__rsaz_512_mul,.-__rsaz_512_mul
-.globl	rsaz_512_scatter4
-.hidden rsaz_512_scatter4
-.type	rsaz_512_scatter4,@function
-.align	16
-rsaz_512_scatter4:
-	leaq	(%rdi,%rdx,4),%rdi
-	movl	$8,%r9d
-	jmp	.Loop_scatter
-.align	16
-.Loop_scatter:
-	movq	(%rsi),%rax
-	leaq	8(%rsi),%rsi
-	movl	%eax,(%rdi)
-	shrq	$32,%rax
-	movl	%eax,64(%rdi)
-	leaq	128(%rdi),%rdi
-	decl	%r9d
-	jnz	.Loop_scatter
-	.byte	0xf3,0xc3
-.size	rsaz_512_scatter4,.-rsaz_512_scatter4
-
-.globl	rsaz_512_gather4
-.hidden rsaz_512_gather4
-.type	rsaz_512_gather4,@function
-.align	16
-rsaz_512_gather4:
-	leaq	(%rsi,%rdx,4),%rsi
-	movl	$8,%r9d
-	jmp	.Loop_gather
-.align	16
-.Loop_gather:
-	movl	(%rsi),%eax
-	movl	64(%rsi),%r8d
-	leaq	128(%rsi),%rsi
-	shlq	$32,%r8
-	orq	%r8,%rax
-	movq	%rax,(%rdi)
-	leaq	8(%rdi),%rdi
-	decl	%r9d
-	jnz	.Loop_gather
-	.byte	0xf3,0xc3
-.size	rsaz_512_gather4,.-rsaz_512_gather4
-#endif
diff --git a/linux-x86_64/crypto/bn/x86_64-mont.S b/linux-x86_64/crypto/bn/x86_64-mont.S
index 4d401c6..0d2cea2 100644
--- a/linux-x86_64/crypto/bn/x86_64-mont.S
+++ b/linux-x86_64/crypto/bn/x86_64-mont.S
@@ -9,6 +9,10 @@
 .type	bn_mul_mont,@function
 .align	16
 bn_mul_mont:
+.cfi_startproc	
+	movl	%r9d,%r9d
+	movq	%rsp,%rax
+.cfi_def_cfa_register	%rax
 	testl	$3,%r9d
 	jnz	.Lmul_enter
 	cmpl	$8,%r9d
@@ -22,20 +26,50 @@
 .align	16
 .Lmul_enter:
 	pushq	%rbx
+.cfi_offset	%rbx,-16
 	pushq	%rbp
+.cfi_offset	%rbp,-24
 	pushq	%r12
+.cfi_offset	%r12,-32
 	pushq	%r13
+.cfi_offset	%r13,-40
 	pushq	%r14
+.cfi_offset	%r14,-48
 	pushq	%r15
+.cfi_offset	%r15,-56
 
-	movl	%r9d,%r9d
-	leaq	2(%r9),%r10
+	negq	%r9
 	movq	%rsp,%r11
-	negq	%r10
-	leaq	(%rsp,%r10,8),%rsp
-	andq	$-1024,%rsp
+	leaq	-16(%rsp,%r9,8),%r10
+	negq	%r9
+	andq	$-1024,%r10
 
-	movq	%r11,8(%rsp,%r9,8)
+
+
+
+
+
+
+
+
+	subq	%r10,%r11
+	andq	$-4096,%r11
+	leaq	(%r10,%r11,1),%rsp
+	movq	(%rsp),%r11
+	cmpq	%r10,%rsp
+	ja	.Lmul_page_walk
+	jmp	.Lmul_page_walk_done
+
+.align	16
+.Lmul_page_walk:
+	leaq	-4096(%rsp),%rsp
+	movq	(%rsp),%r11
+	cmpq	%r10,%rsp
+	ja	.Lmul_page_walk
+.Lmul_page_walk_done:
+
+	movq	%rax,8(%rsp,%r9,8)
+.cfi_escape	0x0f,0x0a,0x77,0x08,0x79,0x00,0x38,0x1e,0x22,0x06,0x23,0x08
 .Lmul_body:
 	movq	%rdx,%r12
 	movq	(%r8),%r8
@@ -187,51 +221,86 @@
 
 	sbbq	$0,%rax
 	xorq	%r14,%r14
+	andq	%rax,%rsi
+	notq	%rax
+	movq	%rdi,%rcx
+	andq	%rax,%rcx
 	movq	%r9,%r15
+	orq	%rcx,%rsi
 .align	16
 .Lcopy:
-	movq	(%rsp,%r14,8),%rsi
-	movq	(%rdi,%r14,8),%rcx
-	xorq	%rcx,%rsi
-	andq	%rax,%rsi
-	xorq	%rcx,%rsi
+	movq	(%rsi,%r14,8),%rax
 	movq	%r14,(%rsp,%r14,8)
-	movq	%rsi,(%rdi,%r14,8)
+	movq	%rax,(%rdi,%r14,8)
 	leaq	1(%r14),%r14
 	subq	$1,%r15
 	jnz	.Lcopy
 
 	movq	8(%rsp,%r9,8),%rsi
+.cfi_def_cfa	%rsi,8
 	movq	$1,%rax
-	movq	(%rsi),%r15
-	movq	8(%rsi),%r14
-	movq	16(%rsi),%r13
-	movq	24(%rsi),%r12
-	movq	32(%rsi),%rbp
-	movq	40(%rsi),%rbx
-	leaq	48(%rsi),%rsp
+	movq	-48(%rsi),%r15
+.cfi_restore	%r15
+	movq	-40(%rsi),%r14
+.cfi_restore	%r14
+	movq	-32(%rsi),%r13
+.cfi_restore	%r13
+	movq	-24(%rsi),%r12
+.cfi_restore	%r12
+	movq	-16(%rsi),%rbp
+.cfi_restore	%rbp
+	movq	-8(%rsi),%rbx
+.cfi_restore	%rbx
+	leaq	(%rsi),%rsp
+.cfi_def_cfa_register	%rsp
 .Lmul_epilogue:
 	.byte	0xf3,0xc3
+.cfi_endproc	
 .size	bn_mul_mont,.-bn_mul_mont
 .type	bn_mul4x_mont,@function
 .align	16
 bn_mul4x_mont:
+.cfi_startproc	
+	movl	%r9d,%r9d
+	movq	%rsp,%rax
+.cfi_def_cfa_register	%rax
 .Lmul4x_enter:
 	pushq	%rbx
+.cfi_offset	%rbx,-16
 	pushq	%rbp
+.cfi_offset	%rbp,-24
 	pushq	%r12
+.cfi_offset	%r12,-32
 	pushq	%r13
+.cfi_offset	%r13,-40
 	pushq	%r14
+.cfi_offset	%r14,-48
 	pushq	%r15
+.cfi_offset	%r15,-56
 
-	movl	%r9d,%r9d
-	leaq	4(%r9),%r10
+	negq	%r9
 	movq	%rsp,%r11
-	negq	%r10
-	leaq	(%rsp,%r10,8),%rsp
-	andq	$-1024,%rsp
+	leaq	-32(%rsp,%r9,8),%r10
+	negq	%r9
+	andq	$-1024,%r10
 
-	movq	%r11,8(%rsp,%r9,8)
+	subq	%r10,%r11
+	andq	$-4096,%r11
+	leaq	(%r10,%r11,1),%rsp
+	movq	(%rsp),%r11
+	cmpq	%r10,%rsp
+	ja	.Lmul4x_page_walk
+	jmp	.Lmul4x_page_walk_done
+
+.Lmul4x_page_walk:
+	leaq	-4096(%rsp),%rsp
+	movq	(%rsp),%r11
+	cmpq	%r10,%rsp
+	ja	.Lmul4x_page_walk
+.Lmul4x_page_walk_done:
+
+	movq	%rax,8(%rsp,%r9,8)
+.cfi_escape	0x0f,0x0a,0x77,0x08,0x79,0x00,0x38,0x1e,0x22,0x06,0x23,0x08
 .Lmul4x_body:
 	movq	%rdi,16(%rsp,%r9,8)
 	movq	%rdx,%r12
@@ -531,9 +600,11 @@
 	cmpq	%r9,%r14
 	jb	.Louter4x
 	movq	16(%rsp,%r9,8),%rdi
+	leaq	-4(%r9),%r15
 	movq	0(%rsp),%rax
+	pxor	%xmm0,%xmm0
 	movq	8(%rsp),%rdx
-	shrq	$2,%r9
+	shrq	$2,%r15
 	leaq	(%rsp),%rsi
 	xorq	%r14,%r14
 
@@ -541,7 +612,6 @@
 	movq	16(%rsi),%rbx
 	movq	24(%rsi),%rbp
 	sbbq	8(%rcx),%rdx
-	leaq	-1(%r9),%r15
 	jmp	.Lsub4x
 .align	16
 .Lsub4x:
@@ -569,47 +639,55 @@
 	movq	%rbx,16(%rdi,%r14,8)
 
 	sbbq	$0,%rax
-	movq	%rax,%xmm0
-	punpcklqdq	%xmm0,%xmm0
 	movq	%rbp,24(%rdi,%r14,8)
 	xorq	%r14,%r14
+	andq	%rax,%rsi
+	notq	%rax
+	movq	%rdi,%rcx
+	andq	%rax,%rcx
+	leaq	-4(%r9),%r15
+	orq	%rcx,%rsi
+	shrq	$2,%r15
 
-	movq	%r9,%r15
-	pxor	%xmm5,%xmm5
+	movdqu	(%rsi),%xmm1
+	movdqa	%xmm0,(%rsp)
+	movdqu	%xmm1,(%rdi)
 	jmp	.Lcopy4x
 .align	16
 .Lcopy4x:
-	movdqu	(%rsp,%r14,1),%xmm2
-	movdqu	16(%rsp,%r14,1),%xmm4
-	movdqu	(%rdi,%r14,1),%xmm1
-	movdqu	16(%rdi,%r14,1),%xmm3
-	pxor	%xmm1,%xmm2
-	pxor	%xmm3,%xmm4
-	pand	%xmm0,%xmm2
-	pand	%xmm0,%xmm4
-	pxor	%xmm1,%xmm2
-	pxor	%xmm3,%xmm4
-	movdqu	%xmm2,(%rdi,%r14,1)
-	movdqu	%xmm4,16(%rdi,%r14,1)
-	movdqa	%xmm5,(%rsp,%r14,1)
-	movdqa	%xmm5,16(%rsp,%r14,1)
-
+	movdqu	16(%rsi,%r14,1),%xmm2
+	movdqu	32(%rsi,%r14,1),%xmm1
+	movdqa	%xmm0,16(%rsp,%r14,1)
+	movdqu	%xmm2,16(%rdi,%r14,1)
+	movdqa	%xmm0,32(%rsp,%r14,1)
+	movdqu	%xmm1,32(%rdi,%r14,1)
 	leaq	32(%r14),%r14
 	decq	%r15
 	jnz	.Lcopy4x
 
-	shlq	$2,%r9
+	movdqu	16(%rsi,%r14,1),%xmm2
+	movdqa	%xmm0,16(%rsp,%r14,1)
+	movdqu	%xmm2,16(%rdi,%r14,1)
 	movq	8(%rsp,%r9,8),%rsi
+.cfi_def_cfa	%rsi, 8
 	movq	$1,%rax
-	movq	(%rsi),%r15
-	movq	8(%rsi),%r14
-	movq	16(%rsi),%r13
-	movq	24(%rsi),%r12
-	movq	32(%rsi),%rbp
-	movq	40(%rsi),%rbx
-	leaq	48(%rsi),%rsp
+	movq	-48(%rsi),%r15
+.cfi_restore	%r15
+	movq	-40(%rsi),%r14
+.cfi_restore	%r14
+	movq	-32(%rsi),%r13
+.cfi_restore	%r13
+	movq	-24(%rsi),%r12
+.cfi_restore	%r12
+	movq	-16(%rsi),%rbp
+.cfi_restore	%rbp
+	movq	-8(%rsi),%rbx
+.cfi_restore	%rbx
+	leaq	(%rsi),%rsp
+.cfi_def_cfa_register	%rsp
 .Lmul4x_epilogue:
 	.byte	0xf3,0xc3
+.cfi_endproc	
 .size	bn_mul4x_mont,.-bn_mul4x_mont
 .extern	bn_sqr8x_internal
 .hidden bn_sqr8x_internal
@@ -617,14 +695,23 @@
 .type	bn_sqr8x_mont,@function
 .align	32
 bn_sqr8x_mont:
-.Lsqr8x_enter:
+.cfi_startproc	
 	movq	%rsp,%rax
+.cfi_def_cfa_register	%rax
+.Lsqr8x_enter:
 	pushq	%rbx
+.cfi_offset	%rbx,-16
 	pushq	%rbp
+.cfi_offset	%rbp,-24
 	pushq	%r12
+.cfi_offset	%r12,-32
 	pushq	%r13
+.cfi_offset	%r13,-40
 	pushq	%r14
+.cfi_offset	%r14,-48
 	pushq	%r15
+.cfi_offset	%r15,-56
+.Lsqr8x_prologue:
 
 	movl	%r9d,%r10d
 	shll	$3,%r9d
@@ -636,92 +723,142 @@
 
 
 
-	leaq	-64(%rsp,%r9,4),%r11
+	leaq	-64(%rsp,%r9,2),%r11
+	movq	%rsp,%rbp
 	movq	(%r8),%r8
 	subq	%rsi,%r11
 	andq	$4095,%r11
 	cmpq	%r11,%r10
 	jb	.Lsqr8x_sp_alt
-	subq	%r11,%rsp
-	leaq	-64(%rsp,%r9,4),%rsp
+	subq	%r11,%rbp
+	leaq	-64(%rbp,%r9,2),%rbp
 	jmp	.Lsqr8x_sp_done
 
 .align	32
 .Lsqr8x_sp_alt:
-	leaq	4096-64(,%r9,4),%r10
-	leaq	-64(%rsp,%r9,4),%rsp
+	leaq	4096-64(,%r9,2),%r10
+	leaq	-64(%rbp,%r9,2),%rbp
 	subq	%r10,%r11
 	movq	$0,%r10
 	cmovcq	%r10,%r11
-	subq	%r11,%rsp
+	subq	%r11,%rbp
 .Lsqr8x_sp_done:
-	andq	$-64,%rsp
+	andq	$-64,%rbp
+	movq	%rsp,%r11
+	subq	%rbp,%r11
+	andq	$-4096,%r11
+	leaq	(%r11,%rbp,1),%rsp
+	movq	(%rsp),%r10
+	cmpq	%rbp,%rsp
+	ja	.Lsqr8x_page_walk
+	jmp	.Lsqr8x_page_walk_done
+
+.align	16
+.Lsqr8x_page_walk:
+	leaq	-4096(%rsp),%rsp
+	movq	(%rsp),%r10
+	cmpq	%rbp,%rsp
+	ja	.Lsqr8x_page_walk
+.Lsqr8x_page_walk_done:
+
 	movq	%r9,%r10
 	negq	%r9
 
-	leaq	64(%rsp,%r9,2),%r11
 	movq	%r8,32(%rsp)
 	movq	%rax,40(%rsp)
+.cfi_escape	0x0f,0x05,0x77,0x28,0x06,0x23,0x08
 .Lsqr8x_body:
 
-	movq	%r9,%rbp
-.byte	102,73,15,110,211
-	shrq	$3+2,%rbp
-	movl	OPENSSL_ia32cap_P+8(%rip),%eax
-	jmp	.Lsqr8x_copy_n
-
-.align	32
-.Lsqr8x_copy_n:
-	movq	0(%rcx),%xmm0
-	movq	8(%rcx),%xmm1
-	movq	16(%rcx),%xmm3
-	movq	24(%rcx),%xmm4
-	leaq	32(%rcx),%rcx
-	movdqa	%xmm0,0(%r11)
-	movdqa	%xmm1,16(%r11)
-	movdqa	%xmm3,32(%r11)
-	movdqa	%xmm4,48(%r11)
-	leaq	64(%r11),%r11
-	decq	%rbp
-	jnz	.Lsqr8x_copy_n
-
+.byte	102,72,15,110,209
 	pxor	%xmm0,%xmm0
 .byte	102,72,15,110,207
 .byte	102,73,15,110,218
 	call	bn_sqr8x_internal
 
-	pxor	%xmm0,%xmm0
-	leaq	48(%rsp),%rax
-	leaq	64(%rsp,%r9,2),%rdx
-	shrq	$3+2,%r9
-	movq	40(%rsp),%rsi
-	jmp	.Lsqr8x_zero
+
+
+
+	leaq	(%rdi,%r9,1),%rbx
+	movq	%r9,%rcx
+	movq	%r9,%rdx
+.byte	102,72,15,126,207
+	sarq	$3+2,%rcx
+	jmp	.Lsqr8x_sub
 
 .align	32
-.Lsqr8x_zero:
-	movdqa	%xmm0,0(%rax)
-	movdqa	%xmm0,16(%rax)
-	movdqa	%xmm0,32(%rax)
-	movdqa	%xmm0,48(%rax)
-	leaq	64(%rax),%rax
-	movdqa	%xmm0,0(%rdx)
-	movdqa	%xmm0,16(%rdx)
-	movdqa	%xmm0,32(%rdx)
-	movdqa	%xmm0,48(%rdx)
-	leaq	64(%rdx),%rdx
-	decq	%r9
-	jnz	.Lsqr8x_zero
+.Lsqr8x_sub:
+	movq	0(%rbx),%r12
+	movq	8(%rbx),%r13
+	movq	16(%rbx),%r14
+	movq	24(%rbx),%r15
+	leaq	32(%rbx),%rbx
+	sbbq	0(%rbp),%r12
+	sbbq	8(%rbp),%r13
+	sbbq	16(%rbp),%r14
+	sbbq	24(%rbp),%r15
+	leaq	32(%rbp),%rbp
+	movq	%r12,0(%rdi)
+	movq	%r13,8(%rdi)
+	movq	%r14,16(%rdi)
+	movq	%r15,24(%rdi)
+	leaq	32(%rdi),%rdi
+	incq	%rcx
+	jnz	.Lsqr8x_sub
+
+	sbbq	$0,%rax
+	leaq	(%rbx,%r9,1),%rbx
+	leaq	(%rdi,%r9,1),%rdi
+
+.byte	102,72,15,110,200
+	pxor	%xmm0,%xmm0
+	pshufd	$0,%xmm1,%xmm1
+	movq	40(%rsp),%rsi
+.cfi_def_cfa	%rsi,8
+	jmp	.Lsqr8x_cond_copy
+
+.align	32
+.Lsqr8x_cond_copy:
+	movdqa	0(%rbx),%xmm2
+	movdqa	16(%rbx),%xmm3
+	leaq	32(%rbx),%rbx
+	movdqu	0(%rdi),%xmm4
+	movdqu	16(%rdi),%xmm5
+	leaq	32(%rdi),%rdi
+	movdqa	%xmm0,-32(%rbx)
+	movdqa	%xmm0,-16(%rbx)
+	movdqa	%xmm0,-32(%rbx,%rdx,1)
+	movdqa	%xmm0,-16(%rbx,%rdx,1)
+	pcmpeqd	%xmm1,%xmm0
+	pand	%xmm1,%xmm2
+	pand	%xmm1,%xmm3
+	pand	%xmm0,%xmm4
+	pand	%xmm0,%xmm5
+	pxor	%xmm0,%xmm0
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqu	%xmm4,-32(%rdi)
+	movdqu	%xmm5,-16(%rdi)
+	addq	$32,%r9
+	jnz	.Lsqr8x_cond_copy
 
 	movq	$1,%rax
 	movq	-48(%rsi),%r15
+.cfi_restore	%r15
 	movq	-40(%rsi),%r14
+.cfi_restore	%r14
 	movq	-32(%rsi),%r13
+.cfi_restore	%r13
 	movq	-24(%rsi),%r12
+.cfi_restore	%r12
 	movq	-16(%rsi),%rbp
+.cfi_restore	%rbp
 	movq	-8(%rsi),%rbx
+.cfi_restore	%rbx
 	leaq	(%rsi),%rsp
+.cfi_def_cfa_register	%rsp
 .Lsqr8x_epilogue:
 	.byte	0xf3,0xc3
+.cfi_endproc	
 .size	bn_sqr8x_mont,.-bn_sqr8x_mont
 .byte	77,111,110,116,103,111,109,101,114,121,32,77,117,108,116,105,112,108,105,99,97,116,105,111,110,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
 .align	16
diff --git a/linux-x86_64/crypto/bn/x86_64-mont5.S b/linux-x86_64/crypto/bn/x86_64-mont5.S
index 214064e..33ca3c4 100644
--- a/linux-x86_64/crypto/bn/x86_64-mont5.S
+++ b/linux-x86_64/crypto/bn/x86_64-mont5.S
@@ -9,54 +9,193 @@
 .type	bn_mul_mont_gather5,@function
 .align	64
 bn_mul_mont_gather5:
+.cfi_startproc	
+	movl	%r9d,%r9d
+	movq	%rsp,%rax
+.cfi_def_cfa_register	%rax
 	testl	$7,%r9d
 	jnz	.Lmul_enter
 	jmp	.Lmul4x_enter
 
 .align	16
 .Lmul_enter:
-	movl	%r9d,%r9d
-	movq	%rsp,%rax
-	movl	8(%rsp),%r10d
+	movd	8(%rsp),%xmm5
 	pushq	%rbx
+.cfi_offset	%rbx,-16
 	pushq	%rbp
+.cfi_offset	%rbp,-24
 	pushq	%r12
+.cfi_offset	%r12,-32
 	pushq	%r13
+.cfi_offset	%r13,-40
 	pushq	%r14
+.cfi_offset	%r14,-48
 	pushq	%r15
-	leaq	2(%r9),%r11
-	negq	%r11
-	leaq	(%rsp,%r11,8),%rsp
-	andq	$-1024,%rsp
+.cfi_offset	%r15,-56
 
+	negq	%r9
+	movq	%rsp,%r11
+	leaq	-280(%rsp,%r9,8),%r10
+	negq	%r9
+	andq	$-1024,%r10
+
+
+
+
+
+
+
+
+
+	subq	%r10,%r11
+	andq	$-4096,%r11
+	leaq	(%r10,%r11,1),%rsp
+	movq	(%rsp),%r11
+	cmpq	%r10,%rsp
+	ja	.Lmul_page_walk
+	jmp	.Lmul_page_walk_done
+
+.Lmul_page_walk:
+	leaq	-4096(%rsp),%rsp
+	movq	(%rsp),%r11
+	cmpq	%r10,%rsp
+	ja	.Lmul_page_walk
+.Lmul_page_walk_done:
+
+	leaq	.Linc(%rip),%r10
 	movq	%rax,8(%rsp,%r9,8)
+.cfi_escape	0x0f,0x0a,0x77,0x08,0x79,0x00,0x38,0x1e,0x22,0x06,0x23,0x08
 .Lmul_body:
-	movq	%rdx,%r12
-	movq	%r10,%r11
-	shrq	$3,%r10
-	andq	$7,%r11
-	notq	%r10
-	leaq	.Lmagic_masks(%rip),%rax
-	andq	$3,%r10
-	leaq	96(%r12,%r11,8),%r12
-	movq	0(%rax,%r10,8),%xmm4
-	movq	8(%rax,%r10,8),%xmm5
-	movq	16(%rax,%r10,8),%xmm6
-	movq	24(%rax,%r10,8),%xmm7
 
-	movq	-96(%r12),%xmm0
-	movq	-32(%r12),%xmm1
-	pand	%xmm4,%xmm0
-	movq	32(%r12),%xmm2
-	pand	%xmm5,%xmm1
-	movq	96(%r12),%xmm3
-	pand	%xmm6,%xmm2
-	por	%xmm1,%xmm0
-	pand	%xmm7,%xmm3
+	leaq	128(%rdx),%r12
+	movdqa	0(%r10),%xmm0
+	movdqa	16(%r10),%xmm1
+	leaq	24-112(%rsp,%r9,8),%r10
+	andq	$-16,%r10
+
+	pshufd	$0,%xmm5,%xmm5
+	movdqa	%xmm1,%xmm4
+	movdqa	%xmm1,%xmm2
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+.byte	0x67
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,112(%r10)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,128(%r10)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,144(%r10)
+	movdqa	%xmm4,%xmm2
+
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,160(%r10)
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,176(%r10)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,192(%r10)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,208(%r10)
+	movdqa	%xmm4,%xmm2
+
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,224(%r10)
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,240(%r10)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,256(%r10)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,272(%r10)
+	movdqa	%xmm4,%xmm2
+
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,288(%r10)
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,304(%r10)
+
+	paddd	%xmm2,%xmm3
+.byte	0x67
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,320(%r10)
+
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,336(%r10)
+	pand	64(%r12),%xmm0
+
+	pand	80(%r12),%xmm1
+	pand	96(%r12),%xmm2
+	movdqa	%xmm3,352(%r10)
+	pand	112(%r12),%xmm3
 	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	movdqa	-128(%r12),%xmm4
+	movdqa	-112(%r12),%xmm5
+	movdqa	-96(%r12),%xmm2
+	pand	112(%r10),%xmm4
+	movdqa	-80(%r12),%xmm3
+	pand	128(%r10),%xmm5
+	por	%xmm4,%xmm0
+	pand	144(%r10),%xmm2
+	por	%xmm5,%xmm1
+	pand	160(%r10),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	movdqa	-64(%r12),%xmm4
+	movdqa	-48(%r12),%xmm5
+	movdqa	-32(%r12),%xmm2
+	pand	176(%r10),%xmm4
+	movdqa	-16(%r12),%xmm3
+	pand	192(%r10),%xmm5
+	por	%xmm4,%xmm0
+	pand	208(%r10),%xmm2
+	por	%xmm5,%xmm1
+	pand	224(%r10),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	movdqa	0(%r12),%xmm4
+	movdqa	16(%r12),%xmm5
+	movdqa	32(%r12),%xmm2
+	pand	240(%r10),%xmm4
+	movdqa	48(%r12),%xmm3
+	pand	256(%r10),%xmm5
+	por	%xmm4,%xmm0
+	pand	272(%r10),%xmm2
+	por	%xmm5,%xmm1
+	pand	288(%r10),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	por	%xmm1,%xmm0
+	pshufd	$0x4e,%xmm0,%xmm1
+	por	%xmm1,%xmm0
 	leaq	256(%r12),%r12
-	por	%xmm3,%xmm0
-
 .byte	102,72,15,126,195
 
 	movq	(%r8),%r8
@@ -65,29 +204,14 @@
 	xorq	%r14,%r14
 	xorq	%r15,%r15
 
-	movq	-96(%r12),%xmm0
-	movq	-32(%r12),%xmm1
-	pand	%xmm4,%xmm0
-	movq	32(%r12),%xmm2
-	pand	%xmm5,%xmm1
-
 	movq	%r8,%rbp
 	mulq	%rbx
 	movq	%rax,%r10
 	movq	(%rcx),%rax
 
-	movq	96(%r12),%xmm3
-	pand	%xmm6,%xmm2
-	por	%xmm1,%xmm0
-	pand	%xmm7,%xmm3
-
 	imulq	%r10,%rbp
 	movq	%rdx,%r11
 
-	por	%xmm2,%xmm0
-	leaq	256(%r12),%r12
-	por	%xmm3,%xmm0
-
 	mulq	%rbp
 	addq	%rax,%r10
 	movq	8(%rsi),%rax
@@ -120,14 +244,12 @@
 	cmpq	%r9,%r15
 	jne	.L1st
 
-.byte	102,72,15,126,195
 
 	addq	%rax,%r13
-	movq	(%rsi),%rax
 	adcq	$0,%rdx
 	addq	%r11,%r13
 	adcq	$0,%rdx
-	movq	%r13,-16(%rsp,%r15,8)
+	movq	%r13,-16(%rsp,%r9,8)
 	movq	%rdx,%r13
 	movq	%r10,%r11
 
@@ -141,33 +263,78 @@
 	jmp	.Louter
 .align	16
 .Louter:
+	leaq	24+128(%rsp,%r9,8),%rdx
+	andq	$-16,%rdx
+	pxor	%xmm4,%xmm4
+	pxor	%xmm5,%xmm5
+	movdqa	-128(%r12),%xmm0
+	movdqa	-112(%r12),%xmm1
+	movdqa	-96(%r12),%xmm2
+	movdqa	-80(%r12),%xmm3
+	pand	-128(%rdx),%xmm0
+	pand	-112(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	-96(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	-80(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	-64(%r12),%xmm0
+	movdqa	-48(%r12),%xmm1
+	movdqa	-32(%r12),%xmm2
+	movdqa	-16(%r12),%xmm3
+	pand	-64(%rdx),%xmm0
+	pand	-48(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	-32(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	-16(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	0(%r12),%xmm0
+	movdqa	16(%r12),%xmm1
+	movdqa	32(%r12),%xmm2
+	movdqa	48(%r12),%xmm3
+	pand	0(%rdx),%xmm0
+	pand	16(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	32(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	48(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	64(%r12),%xmm0
+	movdqa	80(%r12),%xmm1
+	movdqa	96(%r12),%xmm2
+	movdqa	112(%r12),%xmm3
+	pand	64(%rdx),%xmm0
+	pand	80(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	96(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	112(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	por	%xmm5,%xmm4
+	pshufd	$0x4e,%xmm4,%xmm0
+	por	%xmm4,%xmm0
+	leaq	256(%r12),%r12
+
+	movq	(%rsi),%rax
+.byte	102,72,15,126,195
+
 	xorq	%r15,%r15
 	movq	%r8,%rbp
 	movq	(%rsp),%r10
 
-	movq	-96(%r12),%xmm0
-	movq	-32(%r12),%xmm1
-	pand	%xmm4,%xmm0
-	movq	32(%r12),%xmm2
-	pand	%xmm5,%xmm1
-
 	mulq	%rbx
 	addq	%rax,%r10
 	movq	(%rcx),%rax
 	adcq	$0,%rdx
 
-	movq	96(%r12),%xmm3
-	pand	%xmm6,%xmm2
-	por	%xmm1,%xmm0
-	pand	%xmm7,%xmm3
-
 	imulq	%r10,%rbp
 	movq	%rdx,%r11
 
-	por	%xmm2,%xmm0
-	leaq	256(%r12),%r12
-	por	%xmm3,%xmm0
-
 	mulq	%rbp
 	addq	%rax,%r10
 	movq	8(%rsi),%rax
@@ -203,15 +370,12 @@
 	cmpq	%r9,%r15
 	jne	.Linner
 
-.byte	102,72,15,126,195
-
 	addq	%rax,%r13
-	movq	(%rsi),%rax
 	adcq	$0,%rdx
 	addq	%r10,%r13
-	movq	(%rsp,%r15,8),%r10
+	movq	(%rsp,%r9,8),%r10
 	adcq	$0,%rdx
-	movq	%r13,-16(%rsp,%r15,8)
+	movq	%r13,-16(%rsp,%r9,8)
 	movq	%rdx,%r13
 
 	xorq	%rdx,%rdx
@@ -241,48 +405,68 @@
 
 	sbbq	$0,%rax
 	xorq	%r14,%r14
+	andq	%rax,%rsi
+	notq	%rax
+	movq	%rdi,%rcx
+	andq	%rax,%rcx
 	movq	%r9,%r15
+	orq	%rcx,%rsi
 .align	16
 .Lcopy:
-	movq	(%rsp,%r14,8),%rsi
-	movq	(%rdi,%r14,8),%rcx
-	xorq	%rcx,%rsi
-	andq	%rax,%rsi
-	xorq	%rcx,%rsi
+	movq	(%rsi,%r14,8),%rax
 	movq	%r14,(%rsp,%r14,8)
-	movq	%rsi,(%rdi,%r14,8)
+	movq	%rax,(%rdi,%r14,8)
 	leaq	1(%r14),%r14
 	subq	$1,%r15
 	jnz	.Lcopy
 
 	movq	8(%rsp,%r9,8),%rsi
+.cfi_def_cfa	%rsi,8
 	movq	$1,%rax
+
 	movq	-48(%rsi),%r15
+.cfi_restore	%r15
 	movq	-40(%rsi),%r14
+.cfi_restore	%r14
 	movq	-32(%rsi),%r13
+.cfi_restore	%r13
 	movq	-24(%rsi),%r12
+.cfi_restore	%r12
 	movq	-16(%rsi),%rbp
+.cfi_restore	%rbp
 	movq	-8(%rsi),%rbx
+.cfi_restore	%rbx
 	leaq	(%rsi),%rsp
+.cfi_def_cfa_register	%rsp
 .Lmul_epilogue:
 	.byte	0xf3,0xc3
+.cfi_endproc	
 .size	bn_mul_mont_gather5,.-bn_mul_mont_gather5
 .type	bn_mul4x_mont_gather5,@function
 .align	32
 bn_mul4x_mont_gather5:
-.Lmul4x_enter:
+.cfi_startproc	
 .byte	0x67
 	movq	%rsp,%rax
+.cfi_def_cfa_register	%rax
+.Lmul4x_enter:
 	pushq	%rbx
+.cfi_offset	%rbx,-16
 	pushq	%rbp
+.cfi_offset	%rbp,-24
 	pushq	%r12
+.cfi_offset	%r12,-32
 	pushq	%r13
+.cfi_offset	%r13,-40
 	pushq	%r14
+.cfi_offset	%r14,-48
 	pushq	%r15
+.cfi_offset	%r15,-56
+.Lmul4x_prologue:
+
 .byte	0x67
-	movl	%r9d,%r10d
 	shll	$3,%r9d
-	shll	$3+2,%r10d
+	leaq	(%r9,%r9,2),%r10
 	negq	%r9
 
 
@@ -292,90 +476,214 @@
 
 
 
-	leaq	-64(%rsp,%r9,2),%r11
-	subq	%rsi,%r11
+
+
+	leaq	-320(%rsp,%r9,2),%r11
+	movq	%rsp,%rbp
+	subq	%rdi,%r11
 	andq	$4095,%r11
 	cmpq	%r11,%r10
 	jb	.Lmul4xsp_alt
-	subq	%r11,%rsp
-	leaq	-64(%rsp,%r9,2),%rsp
+	subq	%r11,%rbp
+	leaq	-320(%rbp,%r9,2),%rbp
 	jmp	.Lmul4xsp_done
 
 .align	32
 .Lmul4xsp_alt:
-	leaq	4096-64(,%r9,2),%r10
-	leaq	-64(%rsp,%r9,2),%rsp
+	leaq	4096-320(,%r9,2),%r10
+	leaq	-320(%rbp,%r9,2),%rbp
 	subq	%r10,%r11
 	movq	$0,%r10
 	cmovcq	%r10,%r11
-	subq	%r11,%rsp
+	subq	%r11,%rbp
 .Lmul4xsp_done:
-	andq	$-64,%rsp
+	andq	$-64,%rbp
+	movq	%rsp,%r11
+	subq	%rbp,%r11
+	andq	$-4096,%r11
+	leaq	(%r11,%rbp,1),%rsp
+	movq	(%rsp),%r10
+	cmpq	%rbp,%rsp
+	ja	.Lmul4x_page_walk
+	jmp	.Lmul4x_page_walk_done
+
+.Lmul4x_page_walk:
+	leaq	-4096(%rsp),%rsp
+	movq	(%rsp),%r10
+	cmpq	%rbp,%rsp
+	ja	.Lmul4x_page_walk
+.Lmul4x_page_walk_done:
+
 	negq	%r9
 
 	movq	%rax,40(%rsp)
+.cfi_escape	0x0f,0x05,0x77,0x28,0x06,0x23,0x08
 .Lmul4x_body:
 
 	call	mul4x_internal
 
 	movq	40(%rsp),%rsi
+.cfi_def_cfa	%rsi,8
 	movq	$1,%rax
+
 	movq	-48(%rsi),%r15
+.cfi_restore	%r15
 	movq	-40(%rsi),%r14
+.cfi_restore	%r14
 	movq	-32(%rsi),%r13
+.cfi_restore	%r13
 	movq	-24(%rsi),%r12
+.cfi_restore	%r12
 	movq	-16(%rsi),%rbp
+.cfi_restore	%rbp
 	movq	-8(%rsi),%rbx
+.cfi_restore	%rbx
 	leaq	(%rsi),%rsp
+.cfi_def_cfa_register	%rsp
 .Lmul4x_epilogue:
 	.byte	0xf3,0xc3
+.cfi_endproc	
 .size	bn_mul4x_mont_gather5,.-bn_mul4x_mont_gather5
 
 .type	mul4x_internal,@function
 .align	32
 mul4x_internal:
 	shlq	$5,%r9
-	movl	8(%rax),%r10d
-	leaq	256(%rdx,%r9,1),%r13
+	movd	8(%rax),%xmm5
+	leaq	.Linc(%rip),%rax
+	leaq	128(%rdx,%r9,1),%r13
 	shrq	$5,%r9
-	movq	%r10,%r11
-	shrq	$3,%r10
-	andq	$7,%r11
-	notq	%r10
-	leaq	.Lmagic_masks(%rip),%rax
-	andq	$3,%r10
-	leaq	96(%rdx,%r11,8),%r12
-	movq	0(%rax,%r10,8),%xmm4
-	movq	8(%rax,%r10,8),%xmm5
-	addq	$7,%r11
-	movq	16(%rax,%r10,8),%xmm6
-	movq	24(%rax,%r10,8),%xmm7
-	andq	$7,%r11
+	movdqa	0(%rax),%xmm0
+	movdqa	16(%rax),%xmm1
+	leaq	88-112(%rsp,%r9,1),%r10
+	leaq	128(%rdx),%r12
 
-	movq	-96(%r12),%xmm0
-	leaq	256(%r12),%r14
-	movq	-32(%r12),%xmm1
-	pand	%xmm4,%xmm0
-	movq	32(%r12),%xmm2
-	pand	%xmm5,%xmm1
-	movq	96(%r12),%xmm3
-	pand	%xmm6,%xmm2
+	pshufd	$0,%xmm5,%xmm5
+	movdqa	%xmm1,%xmm4
+.byte	0x67,0x67
+	movdqa	%xmm1,%xmm2
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
 .byte	0x67
-	por	%xmm1,%xmm0
-	movq	-96(%r14),%xmm1
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,112(%r10)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,128(%r10)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,144(%r10)
+	movdqa	%xmm4,%xmm2
+
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,160(%r10)
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,176(%r10)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,192(%r10)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,208(%r10)
+	movdqa	%xmm4,%xmm2
+
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,224(%r10)
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,240(%r10)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,256(%r10)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,272(%r10)
+	movdqa	%xmm4,%xmm2
+
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,288(%r10)
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,304(%r10)
+
+	paddd	%xmm2,%xmm3
 .byte	0x67
-	pand	%xmm7,%xmm3
-.byte	0x67
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,320(%r10)
+
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,336(%r10)
+	pand	64(%r12),%xmm0
+
+	pand	80(%r12),%xmm1
+	pand	96(%r12),%xmm2
+	movdqa	%xmm3,352(%r10)
+	pand	112(%r12),%xmm3
 	por	%xmm2,%xmm0
-	movq	-32(%r14),%xmm2
-.byte	0x67
-	pand	%xmm4,%xmm1
-.byte	0x67
-	por	%xmm3,%xmm0
-	movq	32(%r14),%xmm3
-
+	por	%xmm3,%xmm1
+	movdqa	-128(%r12),%xmm4
+	movdqa	-112(%r12),%xmm5
+	movdqa	-96(%r12),%xmm2
+	pand	112(%r10),%xmm4
+	movdqa	-80(%r12),%xmm3
+	pand	128(%r10),%xmm5
+	por	%xmm4,%xmm0
+	pand	144(%r10),%xmm2
+	por	%xmm5,%xmm1
+	pand	160(%r10),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	movdqa	-64(%r12),%xmm4
+	movdqa	-48(%r12),%xmm5
+	movdqa	-32(%r12),%xmm2
+	pand	176(%r10),%xmm4
+	movdqa	-16(%r12),%xmm3
+	pand	192(%r10),%xmm5
+	por	%xmm4,%xmm0
+	pand	208(%r10),%xmm2
+	por	%xmm5,%xmm1
+	pand	224(%r10),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	movdqa	0(%r12),%xmm4
+	movdqa	16(%r12),%xmm5
+	movdqa	32(%r12),%xmm2
+	pand	240(%r10),%xmm4
+	movdqa	48(%r12),%xmm3
+	pand	256(%r10),%xmm5
+	por	%xmm4,%xmm0
+	pand	272(%r10),%xmm2
+	por	%xmm5,%xmm1
+	pand	288(%r10),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	por	%xmm1,%xmm0
+	pshufd	$0x4e,%xmm0,%xmm1
+	por	%xmm1,%xmm0
+	leaq	256(%r12),%r12
 .byte	102,72,15,126,195
-	movq	96(%r14),%xmm0
+
 	movq	%r13,16+8(%rsp)
 	movq	%rdi,56+8(%rsp)
 
@@ -389,26 +697,10 @@
 	movq	%rax,%r10
 	movq	(%rcx),%rax
 
-	pand	%xmm5,%xmm2
-	pand	%xmm6,%xmm3
-	por	%xmm2,%xmm1
-
 	imulq	%r10,%rbp
-
-
-
-
-
-
-
-	leaq	64+8(%rsp,%r11,8),%r14
+	leaq	64+8(%rsp),%r14
 	movq	%rdx,%r11
 
-	pand	%xmm7,%xmm0
-	por	%xmm3,%xmm1
-	leaq	512(%r12),%r12
-	por	%xmm1,%xmm0
-
 	mulq	%rbp
 	addq	%rax,%r10
 	movq	8(%rsi,%r9,1),%rax
@@ -417,7 +709,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r11
-	movq	16(%rcx),%rax
+	movq	8(%rcx),%rax
 	adcq	$0,%rdx
 	movq	%rdx,%r10
 
@@ -427,7 +719,7 @@
 	adcq	$0,%rdx
 	addq	%r11,%rdi
 	leaq	32(%r9),%r15
-	leaq	64(%rcx),%rcx
+	leaq	32(%rcx),%rcx
 	adcq	$0,%rdx
 	movq	%rdi,(%r14)
 	movq	%rdx,%r13
@@ -437,7 +729,7 @@
 .L1st4x:
 	mulq	%rbx
 	addq	%rax,%r10
-	movq	-32(%rcx),%rax
+	movq	-16(%rcx),%rax
 	leaq	32(%r14),%r14
 	adcq	$0,%rdx
 	movq	%rdx,%r11
@@ -453,7 +745,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r11
-	movq	-16(%rcx),%rax
+	movq	-8(%rcx),%rax
 	adcq	$0,%rdx
 	movq	%rdx,%r10
 
@@ -483,7 +775,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r11
-	movq	16(%rcx),%rax
+	movq	8(%rcx),%rax
 	adcq	$0,%rdx
 	movq	%rdx,%r10
 
@@ -492,7 +784,7 @@
 	movq	16(%rsi,%r15,1),%rax
 	adcq	$0,%rdx
 	addq	%r11,%rdi
-	leaq	64(%rcx),%rcx
+	leaq	32(%rcx),%rcx
 	adcq	$0,%rdx
 	movq	%rdi,(%r14)
 	movq	%rdx,%r13
@@ -502,7 +794,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r10
-	movq	-32(%rcx),%rax
+	movq	-16(%rcx),%rax
 	leaq	32(%r14),%r14
 	adcq	$0,%rdx
 	movq	%rdx,%r11
@@ -518,7 +810,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r11
-	movq	-16(%rcx),%rax
+	movq	-8(%rcx),%rax
 	adcq	$0,%rdx
 	movq	%rdx,%r10
 
@@ -531,8 +823,7 @@
 	movq	%rdi,-16(%r14)
 	movq	%rdx,%r13
 
-.byte	102,72,15,126,195
-	leaq	(%rcx,%r9,2),%rcx
+	leaq	(%rcx,%r9,1),%rcx
 
 	xorq	%rdi,%rdi
 	addq	%r10,%r13
@@ -543,6 +834,63 @@
 
 .align	32
 .Louter4x:
+	leaq	16+128(%r14),%rdx
+	pxor	%xmm4,%xmm4
+	pxor	%xmm5,%xmm5
+	movdqa	-128(%r12),%xmm0
+	movdqa	-112(%r12),%xmm1
+	movdqa	-96(%r12),%xmm2
+	movdqa	-80(%r12),%xmm3
+	pand	-128(%rdx),%xmm0
+	pand	-112(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	-96(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	-80(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	-64(%r12),%xmm0
+	movdqa	-48(%r12),%xmm1
+	movdqa	-32(%r12),%xmm2
+	movdqa	-16(%r12),%xmm3
+	pand	-64(%rdx),%xmm0
+	pand	-48(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	-32(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	-16(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	0(%r12),%xmm0
+	movdqa	16(%r12),%xmm1
+	movdqa	32(%r12),%xmm2
+	movdqa	48(%r12),%xmm3
+	pand	0(%rdx),%xmm0
+	pand	16(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	32(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	48(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	64(%r12),%xmm0
+	movdqa	80(%r12),%xmm1
+	movdqa	96(%r12),%xmm2
+	movdqa	112(%r12),%xmm3
+	pand	64(%rdx),%xmm0
+	pand	80(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	96(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	112(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	por	%xmm5,%xmm4
+	pshufd	$0x4e,%xmm4,%xmm0
+	por	%xmm4,%xmm0
+	leaq	256(%r12),%r12
+.byte	102,72,15,126,195
+
 	movq	(%r14,%r9,1),%r10
 	movq	%r8,%rbp
 	mulq	%rbx
@@ -550,25 +898,11 @@
 	movq	(%rcx),%rax
 	adcq	$0,%rdx
 
-	movq	-96(%r12),%xmm0
-	movq	-32(%r12),%xmm1
-	pand	%xmm4,%xmm0
-	movq	32(%r12),%xmm2
-	pand	%xmm5,%xmm1
-	movq	96(%r12),%xmm3
-
 	imulq	%r10,%rbp
-.byte	0x67
 	movq	%rdx,%r11
 	movq	%rdi,(%r14)
 
-	pand	%xmm6,%xmm2
-	por	%xmm1,%xmm0
-	pand	%xmm7,%xmm3
-	por	%xmm2,%xmm0
 	leaq	(%r14,%r9,1),%r14
-	leaq	256(%r12),%r12
-	por	%xmm3,%xmm0
 
 	mulq	%rbp
 	addq	%rax,%r10
@@ -578,7 +912,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r11
-	movq	16(%rcx),%rax
+	movq	8(%rcx),%rax
 	adcq	$0,%rdx
 	addq	8(%r14),%r11
 	adcq	$0,%rdx
@@ -590,7 +924,7 @@
 	adcq	$0,%rdx
 	addq	%r11,%rdi
 	leaq	32(%r9),%r15
-	leaq	64(%rcx),%rcx
+	leaq	32(%rcx),%rcx
 	adcq	$0,%rdx
 	movq	%rdx,%r13
 	jmp	.Linner4x
@@ -599,7 +933,7 @@
 .Linner4x:
 	mulq	%rbx
 	addq	%rax,%r10
-	movq	-32(%rcx),%rax
+	movq	-16(%rcx),%rax
 	adcq	$0,%rdx
 	addq	16(%r14),%r10
 	leaq	32(%r14),%r14
@@ -617,7 +951,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r11
-	movq	-16(%rcx),%rax
+	movq	-8(%rcx),%rax
 	adcq	$0,%rdx
 	addq	-8(%r14),%r11
 	adcq	$0,%rdx
@@ -651,7 +985,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r11
-	movq	16(%rcx),%rax
+	movq	8(%rcx),%rax
 	adcq	$0,%rdx
 	addq	8(%r14),%r11
 	adcq	$0,%rdx
@@ -662,7 +996,7 @@
 	movq	16(%rsi,%r15,1),%rax
 	adcq	$0,%rdx
 	addq	%r11,%rdi
-	leaq	64(%rcx),%rcx
+	leaq	32(%rcx),%rcx
 	adcq	$0,%rdx
 	movq	%r13,-8(%r14)
 	movq	%rdx,%r13
@@ -672,7 +1006,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r10
-	movq	-32(%rcx),%rax
+	movq	-16(%rcx),%rax
 	adcq	$0,%rdx
 	addq	16(%r14),%r10
 	leaq	32(%r14),%r14
@@ -691,7 +1025,7 @@
 	mulq	%rbx
 	addq	%rax,%r11
 	movq	%rbp,%rax
-	movq	-16(%rcx),%rbp
+	movq	-8(%rcx),%rbp
 	adcq	$0,%rdx
 	addq	-8(%r14),%r11
 	adcq	$0,%rdx
@@ -706,9 +1040,8 @@
 	movq	%r13,-24(%r14)
 	movq	%rdx,%r13
 
-.byte	102,72,15,126,195
 	movq	%rdi,-16(%r14)
-	leaq	(%rcx,%r9,2),%rcx
+	leaq	(%rcx,%r9,1),%rcx
 
 	xorq	%rdi,%rdi
 	addq	%r10,%r13
@@ -719,32 +1052,48 @@
 
 	cmpq	16+8(%rsp),%r12
 	jb	.Louter4x
+	xorq	%rax,%rax
 	subq	%r13,%rbp
 	adcq	%r15,%r15
 	orq	%r15,%rdi
-	xorq	$1,%rdi
+	subq	%rdi,%rax
 	leaq	(%r14,%r9,1),%rbx
-	leaq	(%rcx,%rdi,8),%rbp
+	movq	(%rcx),%r12
+	leaq	(%rcx),%rbp
 	movq	%r9,%rcx
 	sarq	$3+2,%rcx
 	movq	56+8(%rsp),%rdi
-	jmp	.Lsqr4x_sub
+	decq	%r12
+	xorq	%r10,%r10
+	movq	8(%rbp),%r13
+	movq	16(%rbp),%r14
+	movq	24(%rbp),%r15
+	jmp	.Lsqr4x_sub_entry
 .size	mul4x_internal,.-mul4x_internal
 .globl	bn_power5
 .hidden bn_power5
 .type	bn_power5,@function
 .align	32
 bn_power5:
+.cfi_startproc	
 	movq	%rsp,%rax
+.cfi_def_cfa_register	%rax
 	pushq	%rbx
+.cfi_offset	%rbx,-16
 	pushq	%rbp
+.cfi_offset	%rbp,-24
 	pushq	%r12
+.cfi_offset	%r12,-32
 	pushq	%r13
+.cfi_offset	%r13,-40
 	pushq	%r14
+.cfi_offset	%r14,-48
 	pushq	%r15
-	movl	%r9d,%r10d
+.cfi_offset	%r15,-56
+.Lpower5_prologue:
+
 	shll	$3,%r9d
-	shll	$3+2,%r10d
+	leal	(%r9,%r9,2),%r10d
 	negq	%r9
 	movq	(%r8),%r8
 
@@ -754,25 +1103,43 @@
 
 
 
-	leaq	-64(%rsp,%r9,2),%r11
-	subq	%rsi,%r11
+
+	leaq	-320(%rsp,%r9,2),%r11
+	movq	%rsp,%rbp
+	subq	%rdi,%r11
 	andq	$4095,%r11
 	cmpq	%r11,%r10
 	jb	.Lpwr_sp_alt
-	subq	%r11,%rsp
-	leaq	-64(%rsp,%r9,2),%rsp
+	subq	%r11,%rbp
+	leaq	-320(%rbp,%r9,2),%rbp
 	jmp	.Lpwr_sp_done
 
 .align	32
 .Lpwr_sp_alt:
-	leaq	4096-64(,%r9,2),%r10
-	leaq	-64(%rsp,%r9,2),%rsp
+	leaq	4096-320(,%r9,2),%r10
+	leaq	-320(%rbp,%r9,2),%rbp
 	subq	%r10,%r11
 	movq	$0,%r10
 	cmovcq	%r10,%r11
-	subq	%r11,%rsp
+	subq	%r11,%rbp
 .Lpwr_sp_done:
-	andq	$-64,%rsp
+	andq	$-64,%rbp
+	movq	%rsp,%r11
+	subq	%rbp,%r11
+	andq	$-4096,%r11
+	leaq	(%r11,%rbp,1),%rsp
+	movq	(%rsp),%r10
+	cmpq	%rbp,%rsp
+	ja	.Lpwr_page_walk
+	jmp	.Lpwr_page_walk_done
+
+.Lpwr_page_walk:
+	leaq	-4096(%rsp),%rsp
+	movq	(%rsp),%r10
+	cmpq	%rbp,%rsp
+	ja	.Lpwr_page_walk
+.Lpwr_page_walk_done:
+
 	movq	%r9,%r10
 	negq	%r9
 
@@ -787,6 +1154,7 @@
 
 	movq	%r8,32(%rsp)
 	movq	%rax,40(%rsp)
+.cfi_escape	0x0f,0x05,0x77,0x28,0x06,0x23,0x08
 .Lpower5_body:
 .byte	102,72,15,110,207
 .byte	102,72,15,110,209
@@ -794,10 +1162,15 @@
 .byte	102,72,15,110,226
 
 	call	__bn_sqr8x_internal
+	call	__bn_post4x_internal
 	call	__bn_sqr8x_internal
+	call	__bn_post4x_internal
 	call	__bn_sqr8x_internal
+	call	__bn_post4x_internal
 	call	__bn_sqr8x_internal
+	call	__bn_post4x_internal
 	call	__bn_sqr8x_internal
+	call	__bn_post4x_internal
 
 .byte	102,72,15,126,209
 .byte	102,72,15,126,226
@@ -808,16 +1181,25 @@
 	call	mul4x_internal
 
 	movq	40(%rsp),%rsi
+.cfi_def_cfa	%rsi,8
 	movq	$1,%rax
 	movq	-48(%rsi),%r15
+.cfi_restore	%r15
 	movq	-40(%rsi),%r14
+.cfi_restore	%r14
 	movq	-32(%rsi),%r13
+.cfi_restore	%r13
 	movq	-24(%rsi),%r12
+.cfi_restore	%r12
 	movq	-16(%rsi),%rbp
+.cfi_restore	%rbp
 	movq	-8(%rsi),%rbx
+.cfi_restore	%rbx
 	leaq	(%rsi),%rsp
+.cfi_def_cfa_register	%rsp
 .Lpower5_epilogue:
 	.byte	0xf3,0xc3
+.cfi_endproc	
 .size	bn_power5,.-bn_power5
 
 .globl	bn_sqr8x_internal
@@ -1342,9 +1724,9 @@
 	movq	%rbx,-16(%rdi)
 	movq	%r8,-8(%rdi)
 .byte	102,72,15,126,213
-sqr8x_reduction:
+__bn_sqr8x_reduction:
 	xorq	%rax,%rax
-	leaq	(%rbp,%r9,2),%rcx
+	leaq	(%r9,%rbp,1),%rcx
 	leaq	48+8(%rsp,%r9,2),%rdx
 	movq	%rcx,0+8(%rsp)
 	leaq	48+8(%rsp,%r9,1),%rdi
@@ -1377,14 +1759,14 @@
 .align	32
 .L8x_reduce:
 	mulq	%rbx
-	movq	16(%rbp),%rax
+	movq	8(%rbp),%rax
 	negq	%r8
 	movq	%rdx,%r8
 	adcq	$0,%r8
 
 	mulq	%rbx
 	addq	%rax,%r9
-	movq	32(%rbp),%rax
+	movq	16(%rbp),%rax
 	adcq	$0,%rdx
 	addq	%r9,%r8
 	movq	%rbx,48-8+8(%rsp,%rcx,8)
@@ -1393,7 +1775,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r10
-	movq	48(%rbp),%rax
+	movq	24(%rbp),%rax
 	adcq	$0,%rdx
 	addq	%r10,%r9
 	movq	32+8(%rsp),%rsi
@@ -1402,7 +1784,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r11
-	movq	64(%rbp),%rax
+	movq	32(%rbp),%rax
 	adcq	$0,%rdx
 	imulq	%r8,%rsi
 	addq	%r11,%r10
@@ -1411,7 +1793,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r12
-	movq	80(%rbp),%rax
+	movq	40(%rbp),%rax
 	adcq	$0,%rdx
 	addq	%r12,%r11
 	movq	%rdx,%r12
@@ -1419,7 +1801,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r13
-	movq	96(%rbp),%rax
+	movq	48(%rbp),%rax
 	adcq	$0,%rdx
 	addq	%r13,%r12
 	movq	%rdx,%r13
@@ -1427,7 +1809,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r14
-	movq	112(%rbp),%rax
+	movq	56(%rbp),%rax
 	adcq	$0,%rdx
 	addq	%r14,%r13
 	movq	%rdx,%r14
@@ -1445,7 +1827,7 @@
 	decl	%ecx
 	jnz	.L8x_reduce
 
-	leaq	128(%rbp),%rbp
+	leaq	64(%rbp),%rbp
 	xorq	%rax,%rax
 	movq	8+8(%rsp),%rdx
 	cmpq	0+8(%rsp),%rbp
@@ -1471,14 +1853,14 @@
 .L8x_tail:
 	mulq	%rbx
 	addq	%rax,%r8
-	movq	16(%rbp),%rax
+	movq	8(%rbp),%rax
 	movq	%r8,(%rdi)
 	movq	%rdx,%r8
 	adcq	$0,%r8
 
 	mulq	%rbx
 	addq	%rax,%r9
-	movq	32(%rbp),%rax
+	movq	16(%rbp),%rax
 	adcq	$0,%rdx
 	addq	%r9,%r8
 	leaq	8(%rdi),%rdi
@@ -1487,7 +1869,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r10
-	movq	48(%rbp),%rax
+	movq	24(%rbp),%rax
 	adcq	$0,%rdx
 	addq	%r10,%r9
 	movq	%rdx,%r10
@@ -1495,7 +1877,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r11
-	movq	64(%rbp),%rax
+	movq	32(%rbp),%rax
 	adcq	$0,%rdx
 	addq	%r11,%r10
 	movq	%rdx,%r11
@@ -1503,7 +1885,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r12
-	movq	80(%rbp),%rax
+	movq	40(%rbp),%rax
 	adcq	$0,%rdx
 	addq	%r12,%r11
 	movq	%rdx,%r12
@@ -1511,7 +1893,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r13
-	movq	96(%rbp),%rax
+	movq	48(%rbp),%rax
 	adcq	$0,%rdx
 	addq	%r13,%r12
 	movq	%rdx,%r13
@@ -1519,7 +1901,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r14
-	movq	112(%rbp),%rax
+	movq	56(%rbp),%rax
 	adcq	$0,%rdx
 	addq	%r14,%r13
 	movq	%rdx,%r14
@@ -1537,7 +1919,7 @@
 	decl	%ecx
 	jnz	.L8x_tail
 
-	leaq	128(%rbp),%rbp
+	leaq	64(%rbp),%rbp
 	movq	8+8(%rsp),%rdx
 	cmpq	0+8(%rsp),%rbp
 	jae	.L8x_tail_done
@@ -1560,6 +1942,7 @@
 
 .align	32
 .L8x_tail_done:
+	xorq	%rax,%rax
 	addq	(%rdx),%r8
 	adcq	$0,%r9
 	adcq	$0,%r10
@@ -1568,9 +1951,7 @@
 	adcq	$0,%r13
 	adcq	$0,%r14
 	adcq	$0,%r15
-
-
-	xorq	%rax,%rax
+	adcq	$0,%rax
 
 	negq	%rsi
 .L8x_no_tail:
@@ -1583,7 +1964,7 @@
 	adcq	48(%rdi),%r14
 	adcq	56(%rdi),%r15
 	adcq	$0,%rax
-	movq	-16(%rbp),%rcx
+	movq	-8(%rbp),%rcx
 	xorq	%rsi,%rsi
 
 .byte	102,72,15,126,213
@@ -1601,44 +1982,62 @@
 
 	cmpq	%rdx,%rdi
 	jb	.L8x_reduction_loop
-
-	subq	%r15,%rcx
-	leaq	(%rdi,%r9,1),%rbx
-	adcq	%rsi,%rsi
-	movq	%r9,%rcx
-	orq	%rsi,%rax
-.byte	102,72,15,126,207
-	xorq	$1,%rax
-.byte	102,72,15,126,206
-	leaq	(%rbp,%rax,8),%rbp
-	sarq	$3+2,%rcx
-	jmp	.Lsqr4x_sub
-
+	.byte	0xf3,0xc3
+.size	bn_sqr8x_internal,.-bn_sqr8x_internal
+.type	__bn_post4x_internal,@function
 .align	32
+__bn_post4x_internal:
+	movq	0(%rbp),%r12
+	leaq	(%rdi,%r9,1),%rbx
+	movq	%r9,%rcx
+.byte	102,72,15,126,207
+	negq	%rax
+.byte	102,72,15,126,206
+	sarq	$3+2,%rcx
+	decq	%r12
+	xorq	%r10,%r10
+	movq	8(%rbp),%r13
+	movq	16(%rbp),%r14
+	movq	24(%rbp),%r15
+	jmp	.Lsqr4x_sub_entry
+
+.align	16
 .Lsqr4x_sub:
-.byte	0x66
-	movq	0(%rbx),%r12
-	movq	8(%rbx),%r13
-	sbbq	0(%rbp),%r12
-	movq	16(%rbx),%r14
-	sbbq	16(%rbp),%r13
-	movq	24(%rbx),%r15
-	leaq	32(%rbx),%rbx
-	sbbq	32(%rbp),%r14
+	movq	0(%rbp),%r12
+	movq	8(%rbp),%r13
+	movq	16(%rbp),%r14
+	movq	24(%rbp),%r15
+.Lsqr4x_sub_entry:
+	leaq	32(%rbp),%rbp
+	notq	%r12
+	notq	%r13
+	notq	%r14
+	notq	%r15
+	andq	%rax,%r12
+	andq	%rax,%r13
+	andq	%rax,%r14
+	andq	%rax,%r15
+
+	negq	%r10
+	adcq	0(%rbx),%r12
+	adcq	8(%rbx),%r13
+	adcq	16(%rbx),%r14
+	adcq	24(%rbx),%r15
 	movq	%r12,0(%rdi)
-	sbbq	48(%rbp),%r15
-	leaq	64(%rbp),%rbp
+	leaq	32(%rbx),%rbx
 	movq	%r13,8(%rdi)
+	sbbq	%r10,%r10
 	movq	%r14,16(%rdi)
 	movq	%r15,24(%rdi)
 	leaq	32(%rdi),%rdi
 
 	incq	%rcx
 	jnz	.Lsqr4x_sub
+
 	movq	%r9,%r10
 	negq	%r9
 	.byte	0xf3,0xc3
-.size	bn_sqr8x_internal,.-bn_sqr8x_internal
+.size	__bn_post4x_internal,.-__bn_post4x_internal
 .globl	bn_from_montgomery
 .hidden bn_from_montgomery
 .type	bn_from_montgomery,@function
@@ -1653,18 +2052,26 @@
 .type	bn_from_mont8x,@function
 .align	32
 bn_from_mont8x:
+.cfi_startproc	
 .byte	0x67
 	movq	%rsp,%rax
+.cfi_def_cfa_register	%rax
 	pushq	%rbx
+.cfi_offset	%rbx,-16
 	pushq	%rbp
+.cfi_offset	%rbp,-24
 	pushq	%r12
+.cfi_offset	%r12,-32
 	pushq	%r13
+.cfi_offset	%r13,-40
 	pushq	%r14
+.cfi_offset	%r14,-48
 	pushq	%r15
-.byte	0x67
-	movl	%r9d,%r10d
+.cfi_offset	%r15,-56
+.Lfrom_prologue:
+
 	shll	$3,%r9d
-	shll	$3+2,%r10d
+	leaq	(%r9,%r9,2),%r10
 	negq	%r9
 	movq	(%r8),%r8
 
@@ -1674,25 +2081,43 @@
 
 
 
-	leaq	-64(%rsp,%r9,2),%r11
-	subq	%rsi,%r11
+
+	leaq	-320(%rsp,%r9,2),%r11
+	movq	%rsp,%rbp
+	subq	%rdi,%r11
 	andq	$4095,%r11
 	cmpq	%r11,%r10
 	jb	.Lfrom_sp_alt
-	subq	%r11,%rsp
-	leaq	-64(%rsp,%r9,2),%rsp
+	subq	%r11,%rbp
+	leaq	-320(%rbp,%r9,2),%rbp
 	jmp	.Lfrom_sp_done
 
 .align	32
 .Lfrom_sp_alt:
-	leaq	4096-64(,%r9,2),%r10
-	leaq	-64(%rsp,%r9,2),%rsp
+	leaq	4096-320(,%r9,2),%r10
+	leaq	-320(%rbp,%r9,2),%rbp
 	subq	%r10,%r11
 	movq	$0,%r10
 	cmovcq	%r10,%r11
-	subq	%r11,%rsp
+	subq	%r11,%rbp
 .Lfrom_sp_done:
-	andq	$-64,%rsp
+	andq	$-64,%rbp
+	movq	%rsp,%r11
+	subq	%rbp,%r11
+	andq	$-4096,%r11
+	leaq	(%r11,%rbp,1),%rsp
+	movq	(%rsp),%r10
+	cmpq	%rbp,%rsp
+	ja	.Lfrom_page_walk
+	jmp	.Lfrom_page_walk_done
+
+.Lfrom_page_walk:
+	leaq	-4096(%rsp),%rsp
+	movq	(%rsp),%r10
+	cmpq	%rbp,%rsp
+	ja	.Lfrom_page_walk
+.Lfrom_page_walk_done:
+
 	movq	%r9,%r10
 	negq	%r9
 
@@ -1707,6 +2132,7 @@
 
 	movq	%r8,32(%rsp)
 	movq	%rax,40(%rsp)
+.cfi_escape	0x0f,0x05,0x77,0x28,0x06,0x23,0x08
 .Lfrom_body:
 	movq	%r9,%r11
 	leaq	48(%rsp),%rax
@@ -1737,15 +2163,17 @@
 .byte	0x67
 	movq	%rcx,%rbp
 .byte	102,73,15,110,218
-	call	sqr8x_reduction
+	call	__bn_sqr8x_reduction
+	call	__bn_post4x_internal
 
 	pxor	%xmm0,%xmm0
 	leaq	48(%rsp),%rax
-	movq	40(%rsp),%rsi
 	jmp	.Lfrom_mont_zero
 
 .align	32
 .Lfrom_mont_zero:
+	movq	40(%rsp),%rsi
+.cfi_def_cfa	%rsi,8
 	movdqa	%xmm0,0(%rax)
 	movdqa	%xmm0,16(%rax)
 	movdqa	%xmm0,32(%rax)
@@ -1756,14 +2184,22 @@
 
 	movq	$1,%rax
 	movq	-48(%rsi),%r15
+.cfi_restore	%r15
 	movq	-40(%rsi),%r14
+.cfi_restore	%r14
 	movq	-32(%rsi),%r13
+.cfi_restore	%r13
 	movq	-24(%rsi),%r12
+.cfi_restore	%r12
 	movq	-16(%rsi),%rbp
+.cfi_restore	%rbp
 	movq	-8(%rsi),%rbx
+.cfi_restore	%rbx
 	leaq	(%rsi),%rsp
+.cfi_def_cfa_register	%rsp
 .Lfrom_epilogue:
 	.byte	0xf3,0xc3
+.cfi_endproc	
 .size	bn_from_mont8x,.-bn_from_mont8x
 .globl	bn_scatter5
 .hidden bn_scatter5
@@ -1787,46 +2223,170 @@
 .globl	bn_gather5
 .hidden bn_gather5
 .type	bn_gather5,@function
-.align	16
+.align	32
 bn_gather5:
-	movl	%ecx,%r11d
-	shrl	$3,%ecx
-	andq	$7,%r11
-	notl	%ecx
-	leaq	.Lmagic_masks(%rip),%rax
-	andl	$3,%ecx
-	leaq	128(%rdx,%r11,8),%rdx
-	movq	0(%rax,%rcx,8),%xmm4
-	movq	8(%rax,%rcx,8),%xmm5
-	movq	16(%rax,%rcx,8),%xmm6
-	movq	24(%rax,%rcx,8),%xmm7
-	jmp	.Lgather
-.align	16
-.Lgather:
-	movq	-128(%rdx),%xmm0
-	movq	-64(%rdx),%xmm1
-	pand	%xmm4,%xmm0
-	movq	0(%rdx),%xmm2
-	pand	%xmm5,%xmm1
-	movq	64(%rdx),%xmm3
-	pand	%xmm6,%xmm2
-	por	%xmm1,%xmm0
-	pand	%xmm7,%xmm3
-.byte	0x67,0x67
-	por	%xmm2,%xmm0
-	leaq	256(%rdx),%rdx
-	por	%xmm3,%xmm0
+.LSEH_begin_bn_gather5:
 
+.byte	0x4c,0x8d,0x14,0x24
+.byte	0x48,0x81,0xec,0x08,0x01,0x00,0x00
+	leaq	.Linc(%rip),%rax
+	andq	$-16,%rsp
+
+	movd	%ecx,%xmm5
+	movdqa	0(%rax),%xmm0
+	movdqa	16(%rax),%xmm1
+	leaq	128(%rdx),%r11
+	leaq	128(%rsp),%rax
+
+	pshufd	$0,%xmm5,%xmm5
+	movdqa	%xmm1,%xmm4
+	movdqa	%xmm1,%xmm2
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm4,%xmm3
+
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,-128(%rax)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,-112(%rax)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,-96(%rax)
+	movdqa	%xmm4,%xmm2
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,-80(%rax)
+	movdqa	%xmm4,%xmm3
+
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,-64(%rax)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,-48(%rax)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,-32(%rax)
+	movdqa	%xmm4,%xmm2
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,-16(%rax)
+	movdqa	%xmm4,%xmm3
+
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,0(%rax)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,16(%rax)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,32(%rax)
+	movdqa	%xmm4,%xmm2
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,48(%rax)
+	movdqa	%xmm4,%xmm3
+
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,64(%rax)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,80(%rax)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,96(%rax)
+	movdqa	%xmm4,%xmm2
+	movdqa	%xmm3,112(%rax)
+	jmp	.Lgather
+
+.align	32
+.Lgather:
+	pxor	%xmm4,%xmm4
+	pxor	%xmm5,%xmm5
+	movdqa	-128(%r11),%xmm0
+	movdqa	-112(%r11),%xmm1
+	movdqa	-96(%r11),%xmm2
+	pand	-128(%rax),%xmm0
+	movdqa	-80(%r11),%xmm3
+	pand	-112(%rax),%xmm1
+	por	%xmm0,%xmm4
+	pand	-96(%rax),%xmm2
+	por	%xmm1,%xmm5
+	pand	-80(%rax),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	-64(%r11),%xmm0
+	movdqa	-48(%r11),%xmm1
+	movdqa	-32(%r11),%xmm2
+	pand	-64(%rax),%xmm0
+	movdqa	-16(%r11),%xmm3
+	pand	-48(%rax),%xmm1
+	por	%xmm0,%xmm4
+	pand	-32(%rax),%xmm2
+	por	%xmm1,%xmm5
+	pand	-16(%rax),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	0(%r11),%xmm0
+	movdqa	16(%r11),%xmm1
+	movdqa	32(%r11),%xmm2
+	pand	0(%rax),%xmm0
+	movdqa	48(%r11),%xmm3
+	pand	16(%rax),%xmm1
+	por	%xmm0,%xmm4
+	pand	32(%rax),%xmm2
+	por	%xmm1,%xmm5
+	pand	48(%rax),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	64(%r11),%xmm0
+	movdqa	80(%r11),%xmm1
+	movdqa	96(%r11),%xmm2
+	pand	64(%rax),%xmm0
+	movdqa	112(%r11),%xmm3
+	pand	80(%rax),%xmm1
+	por	%xmm0,%xmm4
+	pand	96(%rax),%xmm2
+	por	%xmm1,%xmm5
+	pand	112(%rax),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	por	%xmm5,%xmm4
+	leaq	256(%r11),%r11
+	pshufd	$0x4e,%xmm4,%xmm0
+	por	%xmm4,%xmm0
 	movq	%xmm0,(%rdi)
 	leaq	8(%rdi),%rdi
 	subl	$1,%esi
 	jnz	.Lgather
+
+	leaq	(%r10),%rsp
 	.byte	0xf3,0xc3
 .LSEH_end_bn_gather5:
 .size	bn_gather5,.-bn_gather5
 .align	64
-.Lmagic_masks:
-.long	0,0, 0,0, 0,0, -1,-1
-.long	0,0, 0,0, 0,0,  0,0
+.Linc:
+.long	0,0, 1,1
+.long	2,2, 2,2
 .byte	77,111,110,116,103,111,109,101,114,121,32,77,117,108,116,105,112,108,105,99,97,116,105,111,110,32,119,105,116,104,32,115,99,97,116,116,101,114,47,103,97,116,104,101,114,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
 #endif
diff --git a/linux-x86_64/crypto/chacha/chacha-x86_64.S b/linux-x86_64/crypto/chacha/chacha-x86_64.S
new file mode 100644
index 0000000..25ec715
--- /dev/null
+++ b/linux-x86_64/crypto/chacha/chacha-x86_64.S
@@ -0,0 +1,1586 @@
+#if defined(__x86_64__)
+.text	
+
+.extern	OPENSSL_ia32cap_P
+.hidden OPENSSL_ia32cap_P
+
+.align	64
+.Lzero:
+.long	0,0,0,0
+.Lone:
+.long	1,0,0,0
+.Linc:
+.long	0,1,2,3
+.Lfour:
+.long	4,4,4,4
+.Lincy:
+.long	0,2,4,6,1,3,5,7
+.Leight:
+.long	8,8,8,8,8,8,8,8
+.Lrot16:
+.byte	0x2,0x3,0x0,0x1, 0x6,0x7,0x4,0x5, 0xa,0xb,0x8,0x9, 0xe,0xf,0xc,0xd
+.Lrot24:
+.byte	0x3,0x0,0x1,0x2, 0x7,0x4,0x5,0x6, 0xb,0x8,0x9,0xa, 0xf,0xc,0xd,0xe
+.Lsigma:
+.byte	101,120,112,97,110,100,32,51,50,45,98,121,116,101,32,107,0
+.align	64
+.Lzeroz:
+.long	0,0,0,0, 1,0,0,0, 2,0,0,0, 3,0,0,0
+.Lfourz:
+.long	4,0,0,0, 4,0,0,0, 4,0,0,0, 4,0,0,0
+.Lincz:
+.long	0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+.Lsixteen:
+.long	16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16
+.byte	67,104,97,67,104,97,50,48,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.globl	ChaCha20_ctr32
+.hidden ChaCha20_ctr32
+.type	ChaCha20_ctr32,@function
+.align	64
+ChaCha20_ctr32:
+	cmpq	$0,%rdx
+	je	.Lno_data
+	movq	OPENSSL_ia32cap_P+4(%rip),%r10
+	testl	$512,%r10d
+	jnz	.LChaCha20_ssse3
+
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	subq	$64+24,%rsp
+.Lctr32_body:
+
+
+	movdqu	(%rcx),%xmm1
+	movdqu	16(%rcx),%xmm2
+	movdqu	(%r8),%xmm3
+	movdqa	.Lone(%rip),%xmm4
+
+
+	movdqa	%xmm1,16(%rsp)
+	movdqa	%xmm2,32(%rsp)
+	movdqa	%xmm3,48(%rsp)
+	movq	%rdx,%rbp
+	jmp	.Loop_outer
+
+.align	32
+.Loop_outer:
+	movl	$0x61707865,%eax
+	movl	$0x3320646e,%ebx
+	movl	$0x79622d32,%ecx
+	movl	$0x6b206574,%edx
+	movl	16(%rsp),%r8d
+	movl	20(%rsp),%r9d
+	movl	24(%rsp),%r10d
+	movl	28(%rsp),%r11d
+	movd	%xmm3,%r12d
+	movl	52(%rsp),%r13d
+	movl	56(%rsp),%r14d
+	movl	60(%rsp),%r15d
+
+	movq	%rbp,64+0(%rsp)
+	movl	$10,%ebp
+	movq	%rsi,64+8(%rsp)
+.byte	102,72,15,126,214
+	movq	%rdi,64+16(%rsp)
+	movq	%rsi,%rdi
+	shrq	$32,%rdi
+	jmp	.Loop
+
+.align	32
+.Loop:
+	addl	%r8d,%eax
+	xorl	%eax,%r12d
+	roll	$16,%r12d
+	addl	%r9d,%ebx
+	xorl	%ebx,%r13d
+	roll	$16,%r13d
+	addl	%r12d,%esi
+	xorl	%esi,%r8d
+	roll	$12,%r8d
+	addl	%r13d,%edi
+	xorl	%edi,%r9d
+	roll	$12,%r9d
+	addl	%r8d,%eax
+	xorl	%eax,%r12d
+	roll	$8,%r12d
+	addl	%r9d,%ebx
+	xorl	%ebx,%r13d
+	roll	$8,%r13d
+	addl	%r12d,%esi
+	xorl	%esi,%r8d
+	roll	$7,%r8d
+	addl	%r13d,%edi
+	xorl	%edi,%r9d
+	roll	$7,%r9d
+	movl	%esi,32(%rsp)
+	movl	%edi,36(%rsp)
+	movl	40(%rsp),%esi
+	movl	44(%rsp),%edi
+	addl	%r10d,%ecx
+	xorl	%ecx,%r14d
+	roll	$16,%r14d
+	addl	%r11d,%edx
+	xorl	%edx,%r15d
+	roll	$16,%r15d
+	addl	%r14d,%esi
+	xorl	%esi,%r10d
+	roll	$12,%r10d
+	addl	%r15d,%edi
+	xorl	%edi,%r11d
+	roll	$12,%r11d
+	addl	%r10d,%ecx
+	xorl	%ecx,%r14d
+	roll	$8,%r14d
+	addl	%r11d,%edx
+	xorl	%edx,%r15d
+	roll	$8,%r15d
+	addl	%r14d,%esi
+	xorl	%esi,%r10d
+	roll	$7,%r10d
+	addl	%r15d,%edi
+	xorl	%edi,%r11d
+	roll	$7,%r11d
+	addl	%r9d,%eax
+	xorl	%eax,%r15d
+	roll	$16,%r15d
+	addl	%r10d,%ebx
+	xorl	%ebx,%r12d
+	roll	$16,%r12d
+	addl	%r15d,%esi
+	xorl	%esi,%r9d
+	roll	$12,%r9d
+	addl	%r12d,%edi
+	xorl	%edi,%r10d
+	roll	$12,%r10d
+	addl	%r9d,%eax
+	xorl	%eax,%r15d
+	roll	$8,%r15d
+	addl	%r10d,%ebx
+	xorl	%ebx,%r12d
+	roll	$8,%r12d
+	addl	%r15d,%esi
+	xorl	%esi,%r9d
+	roll	$7,%r9d
+	addl	%r12d,%edi
+	xorl	%edi,%r10d
+	roll	$7,%r10d
+	movl	%esi,40(%rsp)
+	movl	%edi,44(%rsp)
+	movl	32(%rsp),%esi
+	movl	36(%rsp),%edi
+	addl	%r11d,%ecx
+	xorl	%ecx,%r13d
+	roll	$16,%r13d
+	addl	%r8d,%edx
+	xorl	%edx,%r14d
+	roll	$16,%r14d
+	addl	%r13d,%esi
+	xorl	%esi,%r11d
+	roll	$12,%r11d
+	addl	%r14d,%edi
+	xorl	%edi,%r8d
+	roll	$12,%r8d
+	addl	%r11d,%ecx
+	xorl	%ecx,%r13d
+	roll	$8,%r13d
+	addl	%r8d,%edx
+	xorl	%edx,%r14d
+	roll	$8,%r14d
+	addl	%r13d,%esi
+	xorl	%esi,%r11d
+	roll	$7,%r11d
+	addl	%r14d,%edi
+	xorl	%edi,%r8d
+	roll	$7,%r8d
+	decl	%ebp
+	jnz	.Loop
+	movl	%edi,36(%rsp)
+	movl	%esi,32(%rsp)
+	movq	64(%rsp),%rbp
+	movdqa	%xmm2,%xmm1
+	movq	64+8(%rsp),%rsi
+	paddd	%xmm4,%xmm3
+	movq	64+16(%rsp),%rdi
+
+	addl	$0x61707865,%eax
+	addl	$0x3320646e,%ebx
+	addl	$0x79622d32,%ecx
+	addl	$0x6b206574,%edx
+	addl	16(%rsp),%r8d
+	addl	20(%rsp),%r9d
+	addl	24(%rsp),%r10d
+	addl	28(%rsp),%r11d
+	addl	48(%rsp),%r12d
+	addl	52(%rsp),%r13d
+	addl	56(%rsp),%r14d
+	addl	60(%rsp),%r15d
+	paddd	32(%rsp),%xmm1
+
+	cmpq	$64,%rbp
+	jb	.Ltail
+
+	xorl	0(%rsi),%eax
+	xorl	4(%rsi),%ebx
+	xorl	8(%rsi),%ecx
+	xorl	12(%rsi),%edx
+	xorl	16(%rsi),%r8d
+	xorl	20(%rsi),%r9d
+	xorl	24(%rsi),%r10d
+	xorl	28(%rsi),%r11d
+	movdqu	32(%rsi),%xmm0
+	xorl	48(%rsi),%r12d
+	xorl	52(%rsi),%r13d
+	xorl	56(%rsi),%r14d
+	xorl	60(%rsi),%r15d
+	leaq	64(%rsi),%rsi
+	pxor	%xmm1,%xmm0
+
+	movdqa	%xmm2,32(%rsp)
+	movd	%xmm3,48(%rsp)
+
+	movl	%eax,0(%rdi)
+	movl	%ebx,4(%rdi)
+	movl	%ecx,8(%rdi)
+	movl	%edx,12(%rdi)
+	movl	%r8d,16(%rdi)
+	movl	%r9d,20(%rdi)
+	movl	%r10d,24(%rdi)
+	movl	%r11d,28(%rdi)
+	movdqu	%xmm0,32(%rdi)
+	movl	%r12d,48(%rdi)
+	movl	%r13d,52(%rdi)
+	movl	%r14d,56(%rdi)
+	movl	%r15d,60(%rdi)
+	leaq	64(%rdi),%rdi
+
+	subq	$64,%rbp
+	jnz	.Loop_outer
+
+	jmp	.Ldone
+
+.align	16
+.Ltail:
+	movl	%eax,0(%rsp)
+	movl	%ebx,4(%rsp)
+	xorq	%rbx,%rbx
+	movl	%ecx,8(%rsp)
+	movl	%edx,12(%rsp)
+	movl	%r8d,16(%rsp)
+	movl	%r9d,20(%rsp)
+	movl	%r10d,24(%rsp)
+	movl	%r11d,28(%rsp)
+	movdqa	%xmm1,32(%rsp)
+	movl	%r12d,48(%rsp)
+	movl	%r13d,52(%rsp)
+	movl	%r14d,56(%rsp)
+	movl	%r15d,60(%rsp)
+
+.Loop_tail:
+	movzbl	(%rsi,%rbx,1),%eax
+	movzbl	(%rsp,%rbx,1),%edx
+	leaq	1(%rbx),%rbx
+	xorl	%edx,%eax
+	movb	%al,-1(%rdi,%rbx,1)
+	decq	%rbp
+	jnz	.Loop_tail
+
+.Ldone:
+	leaq	64+24+48(%rsp),%rsi
+	movq	-48(%rsi),%r15
+	movq	-40(%rsi),%r14
+	movq	-32(%rsi),%r13
+	movq	-24(%rsi),%r12
+	movq	-16(%rsi),%rbp
+	movq	-8(%rsi),%rbx
+	leaq	(%rsi),%rsp
+.Lno_data:
+	.byte	0xf3,0xc3
+.size	ChaCha20_ctr32,.-ChaCha20_ctr32
+.type	ChaCha20_ssse3,@function
+.align	32
+ChaCha20_ssse3:
+.LChaCha20_ssse3:
+	movq	%rsp,%r9
+	cmpq	$128,%rdx
+	ja	.LChaCha20_4x
+
+.Ldo_sse3_after_all:
+	subq	$64+8,%rsp
+	movdqa	.Lsigma(%rip),%xmm0
+	movdqu	(%rcx),%xmm1
+	movdqu	16(%rcx),%xmm2
+	movdqu	(%r8),%xmm3
+	movdqa	.Lrot16(%rip),%xmm6
+	movdqa	.Lrot24(%rip),%xmm7
+
+	movdqa	%xmm0,0(%rsp)
+	movdqa	%xmm1,16(%rsp)
+	movdqa	%xmm2,32(%rsp)
+	movdqa	%xmm3,48(%rsp)
+	movq	$10,%r8
+	jmp	.Loop_ssse3
+
+.align	32
+.Loop_outer_ssse3:
+	movdqa	.Lone(%rip),%xmm3
+	movdqa	0(%rsp),%xmm0
+	movdqa	16(%rsp),%xmm1
+	movdqa	32(%rsp),%xmm2
+	paddd	48(%rsp),%xmm3
+	movq	$10,%r8
+	movdqa	%xmm3,48(%rsp)
+	jmp	.Loop_ssse3
+
+.align	32
+.Loop_ssse3:
+	paddd	%xmm1,%xmm0
+	pxor	%xmm0,%xmm3
+.byte	102,15,56,0,222
+	paddd	%xmm3,%xmm2
+	pxor	%xmm2,%xmm1
+	movdqa	%xmm1,%xmm4
+	psrld	$20,%xmm1
+	pslld	$12,%xmm4
+	por	%xmm4,%xmm1
+	paddd	%xmm1,%xmm0
+	pxor	%xmm0,%xmm3
+.byte	102,15,56,0,223
+	paddd	%xmm3,%xmm2
+	pxor	%xmm2,%xmm1
+	movdqa	%xmm1,%xmm4
+	psrld	$25,%xmm1
+	pslld	$7,%xmm4
+	por	%xmm4,%xmm1
+	pshufd	$78,%xmm2,%xmm2
+	pshufd	$57,%xmm1,%xmm1
+	pshufd	$147,%xmm3,%xmm3
+	nop
+	paddd	%xmm1,%xmm0
+	pxor	%xmm0,%xmm3
+.byte	102,15,56,0,222
+	paddd	%xmm3,%xmm2
+	pxor	%xmm2,%xmm1
+	movdqa	%xmm1,%xmm4
+	psrld	$20,%xmm1
+	pslld	$12,%xmm4
+	por	%xmm4,%xmm1
+	paddd	%xmm1,%xmm0
+	pxor	%xmm0,%xmm3
+.byte	102,15,56,0,223
+	paddd	%xmm3,%xmm2
+	pxor	%xmm2,%xmm1
+	movdqa	%xmm1,%xmm4
+	psrld	$25,%xmm1
+	pslld	$7,%xmm4
+	por	%xmm4,%xmm1
+	pshufd	$78,%xmm2,%xmm2
+	pshufd	$147,%xmm1,%xmm1
+	pshufd	$57,%xmm3,%xmm3
+	decq	%r8
+	jnz	.Loop_ssse3
+	paddd	0(%rsp),%xmm0
+	paddd	16(%rsp),%xmm1
+	paddd	32(%rsp),%xmm2
+	paddd	48(%rsp),%xmm3
+
+	cmpq	$64,%rdx
+	jb	.Ltail_ssse3
+
+	movdqu	0(%rsi),%xmm4
+	movdqu	16(%rsi),%xmm5
+	pxor	%xmm4,%xmm0
+	movdqu	32(%rsi),%xmm4
+	pxor	%xmm5,%xmm1
+	movdqu	48(%rsi),%xmm5
+	leaq	64(%rsi),%rsi
+	pxor	%xmm4,%xmm2
+	pxor	%xmm5,%xmm3
+
+	movdqu	%xmm0,0(%rdi)
+	movdqu	%xmm1,16(%rdi)
+	movdqu	%xmm2,32(%rdi)
+	movdqu	%xmm3,48(%rdi)
+	leaq	64(%rdi),%rdi
+
+	subq	$64,%rdx
+	jnz	.Loop_outer_ssse3
+
+	jmp	.Ldone_ssse3
+
+.align	16
+.Ltail_ssse3:
+	movdqa	%xmm0,0(%rsp)
+	movdqa	%xmm1,16(%rsp)
+	movdqa	%xmm2,32(%rsp)
+	movdqa	%xmm3,48(%rsp)
+	xorq	%r8,%r8
+
+.Loop_tail_ssse3:
+	movzbl	(%rsi,%r8,1),%eax
+	movzbl	(%rsp,%r8,1),%ecx
+	leaq	1(%r8),%r8
+	xorl	%ecx,%eax
+	movb	%al,-1(%rdi,%r8,1)
+	decq	%rdx
+	jnz	.Loop_tail_ssse3
+
+.Ldone_ssse3:
+	leaq	(%r9),%rsp
+.Lssse3_epilogue:
+	.byte	0xf3,0xc3
+.size	ChaCha20_ssse3,.-ChaCha20_ssse3
+.type	ChaCha20_4x,@function
+.align	32
+ChaCha20_4x:
+.LChaCha20_4x:
+	movq	%rsp,%r9
+	movq	%r10,%r11
+	shrq	$32,%r10
+	testq	$32,%r10
+	jnz	.LChaCha20_8x
+	cmpq	$192,%rdx
+	ja	.Lproceed4x
+
+	andq	$71303168,%r11
+	cmpq	$4194304,%r11
+	je	.Ldo_sse3_after_all
+
+.Lproceed4x:
+	subq	$0x140+8,%rsp
+	movdqa	.Lsigma(%rip),%xmm11
+	movdqu	(%rcx),%xmm15
+	movdqu	16(%rcx),%xmm7
+	movdqu	(%r8),%xmm3
+	leaq	256(%rsp),%rcx
+	leaq	.Lrot16(%rip),%r10
+	leaq	.Lrot24(%rip),%r11
+
+	pshufd	$0x00,%xmm11,%xmm8
+	pshufd	$0x55,%xmm11,%xmm9
+	movdqa	%xmm8,64(%rsp)
+	pshufd	$0xaa,%xmm11,%xmm10
+	movdqa	%xmm9,80(%rsp)
+	pshufd	$0xff,%xmm11,%xmm11
+	movdqa	%xmm10,96(%rsp)
+	movdqa	%xmm11,112(%rsp)
+
+	pshufd	$0x00,%xmm15,%xmm12
+	pshufd	$0x55,%xmm15,%xmm13
+	movdqa	%xmm12,128-256(%rcx)
+	pshufd	$0xaa,%xmm15,%xmm14
+	movdqa	%xmm13,144-256(%rcx)
+	pshufd	$0xff,%xmm15,%xmm15
+	movdqa	%xmm14,160-256(%rcx)
+	movdqa	%xmm15,176-256(%rcx)
+
+	pshufd	$0x00,%xmm7,%xmm4
+	pshufd	$0x55,%xmm7,%xmm5
+	movdqa	%xmm4,192-256(%rcx)
+	pshufd	$0xaa,%xmm7,%xmm6
+	movdqa	%xmm5,208-256(%rcx)
+	pshufd	$0xff,%xmm7,%xmm7
+	movdqa	%xmm6,224-256(%rcx)
+	movdqa	%xmm7,240-256(%rcx)
+
+	pshufd	$0x00,%xmm3,%xmm0
+	pshufd	$0x55,%xmm3,%xmm1
+	paddd	.Linc(%rip),%xmm0
+	pshufd	$0xaa,%xmm3,%xmm2
+	movdqa	%xmm1,272-256(%rcx)
+	pshufd	$0xff,%xmm3,%xmm3
+	movdqa	%xmm2,288-256(%rcx)
+	movdqa	%xmm3,304-256(%rcx)
+
+	jmp	.Loop_enter4x
+
+.align	32
+.Loop_outer4x:
+	movdqa	64(%rsp),%xmm8
+	movdqa	80(%rsp),%xmm9
+	movdqa	96(%rsp),%xmm10
+	movdqa	112(%rsp),%xmm11
+	movdqa	128-256(%rcx),%xmm12
+	movdqa	144-256(%rcx),%xmm13
+	movdqa	160-256(%rcx),%xmm14
+	movdqa	176-256(%rcx),%xmm15
+	movdqa	192-256(%rcx),%xmm4
+	movdqa	208-256(%rcx),%xmm5
+	movdqa	224-256(%rcx),%xmm6
+	movdqa	240-256(%rcx),%xmm7
+	movdqa	256-256(%rcx),%xmm0
+	movdqa	272-256(%rcx),%xmm1
+	movdqa	288-256(%rcx),%xmm2
+	movdqa	304-256(%rcx),%xmm3
+	paddd	.Lfour(%rip),%xmm0
+
+.Loop_enter4x:
+	movdqa	%xmm6,32(%rsp)
+	movdqa	%xmm7,48(%rsp)
+	movdqa	(%r10),%xmm7
+	movl	$10,%eax
+	movdqa	%xmm0,256-256(%rcx)
+	jmp	.Loop4x
+
+.align	32
+.Loop4x:
+	paddd	%xmm12,%xmm8
+	paddd	%xmm13,%xmm9
+	pxor	%xmm8,%xmm0
+	pxor	%xmm9,%xmm1
+.byte	102,15,56,0,199
+.byte	102,15,56,0,207
+	paddd	%xmm0,%xmm4
+	paddd	%xmm1,%xmm5
+	pxor	%xmm4,%xmm12
+	pxor	%xmm5,%xmm13
+	movdqa	%xmm12,%xmm6
+	pslld	$12,%xmm12
+	psrld	$20,%xmm6
+	movdqa	%xmm13,%xmm7
+	pslld	$12,%xmm13
+	por	%xmm6,%xmm12
+	psrld	$20,%xmm7
+	movdqa	(%r11),%xmm6
+	por	%xmm7,%xmm13
+	paddd	%xmm12,%xmm8
+	paddd	%xmm13,%xmm9
+	pxor	%xmm8,%xmm0
+	pxor	%xmm9,%xmm1
+.byte	102,15,56,0,198
+.byte	102,15,56,0,206
+	paddd	%xmm0,%xmm4
+	paddd	%xmm1,%xmm5
+	pxor	%xmm4,%xmm12
+	pxor	%xmm5,%xmm13
+	movdqa	%xmm12,%xmm7
+	pslld	$7,%xmm12
+	psrld	$25,%xmm7
+	movdqa	%xmm13,%xmm6
+	pslld	$7,%xmm13
+	por	%xmm7,%xmm12
+	psrld	$25,%xmm6
+	movdqa	(%r10),%xmm7
+	por	%xmm6,%xmm13
+	movdqa	%xmm4,0(%rsp)
+	movdqa	%xmm5,16(%rsp)
+	movdqa	32(%rsp),%xmm4
+	movdqa	48(%rsp),%xmm5
+	paddd	%xmm14,%xmm10
+	paddd	%xmm15,%xmm11
+	pxor	%xmm10,%xmm2
+	pxor	%xmm11,%xmm3
+.byte	102,15,56,0,215
+.byte	102,15,56,0,223
+	paddd	%xmm2,%xmm4
+	paddd	%xmm3,%xmm5
+	pxor	%xmm4,%xmm14
+	pxor	%xmm5,%xmm15
+	movdqa	%xmm14,%xmm6
+	pslld	$12,%xmm14
+	psrld	$20,%xmm6
+	movdqa	%xmm15,%xmm7
+	pslld	$12,%xmm15
+	por	%xmm6,%xmm14
+	psrld	$20,%xmm7
+	movdqa	(%r11),%xmm6
+	por	%xmm7,%xmm15
+	paddd	%xmm14,%xmm10
+	paddd	%xmm15,%xmm11
+	pxor	%xmm10,%xmm2
+	pxor	%xmm11,%xmm3
+.byte	102,15,56,0,214
+.byte	102,15,56,0,222
+	paddd	%xmm2,%xmm4
+	paddd	%xmm3,%xmm5
+	pxor	%xmm4,%xmm14
+	pxor	%xmm5,%xmm15
+	movdqa	%xmm14,%xmm7
+	pslld	$7,%xmm14
+	psrld	$25,%xmm7
+	movdqa	%xmm15,%xmm6
+	pslld	$7,%xmm15
+	por	%xmm7,%xmm14
+	psrld	$25,%xmm6
+	movdqa	(%r10),%xmm7
+	por	%xmm6,%xmm15
+	paddd	%xmm13,%xmm8
+	paddd	%xmm14,%xmm9
+	pxor	%xmm8,%xmm3
+	pxor	%xmm9,%xmm0
+.byte	102,15,56,0,223
+.byte	102,15,56,0,199
+	paddd	%xmm3,%xmm4
+	paddd	%xmm0,%xmm5
+	pxor	%xmm4,%xmm13
+	pxor	%xmm5,%xmm14
+	movdqa	%xmm13,%xmm6
+	pslld	$12,%xmm13
+	psrld	$20,%xmm6
+	movdqa	%xmm14,%xmm7
+	pslld	$12,%xmm14
+	por	%xmm6,%xmm13
+	psrld	$20,%xmm7
+	movdqa	(%r11),%xmm6
+	por	%xmm7,%xmm14
+	paddd	%xmm13,%xmm8
+	paddd	%xmm14,%xmm9
+	pxor	%xmm8,%xmm3
+	pxor	%xmm9,%xmm0
+.byte	102,15,56,0,222
+.byte	102,15,56,0,198
+	paddd	%xmm3,%xmm4
+	paddd	%xmm0,%xmm5
+	pxor	%xmm4,%xmm13
+	pxor	%xmm5,%xmm14
+	movdqa	%xmm13,%xmm7
+	pslld	$7,%xmm13
+	psrld	$25,%xmm7
+	movdqa	%xmm14,%xmm6
+	pslld	$7,%xmm14
+	por	%xmm7,%xmm13
+	psrld	$25,%xmm6
+	movdqa	(%r10),%xmm7
+	por	%xmm6,%xmm14
+	movdqa	%xmm4,32(%rsp)
+	movdqa	%xmm5,48(%rsp)
+	movdqa	0(%rsp),%xmm4
+	movdqa	16(%rsp),%xmm5
+	paddd	%xmm15,%xmm10
+	paddd	%xmm12,%xmm11
+	pxor	%xmm10,%xmm1
+	pxor	%xmm11,%xmm2
+.byte	102,15,56,0,207
+.byte	102,15,56,0,215
+	paddd	%xmm1,%xmm4
+	paddd	%xmm2,%xmm5
+	pxor	%xmm4,%xmm15
+	pxor	%xmm5,%xmm12
+	movdqa	%xmm15,%xmm6
+	pslld	$12,%xmm15
+	psrld	$20,%xmm6
+	movdqa	%xmm12,%xmm7
+	pslld	$12,%xmm12
+	por	%xmm6,%xmm15
+	psrld	$20,%xmm7
+	movdqa	(%r11),%xmm6
+	por	%xmm7,%xmm12
+	paddd	%xmm15,%xmm10
+	paddd	%xmm12,%xmm11
+	pxor	%xmm10,%xmm1
+	pxor	%xmm11,%xmm2
+.byte	102,15,56,0,206
+.byte	102,15,56,0,214
+	paddd	%xmm1,%xmm4
+	paddd	%xmm2,%xmm5
+	pxor	%xmm4,%xmm15
+	pxor	%xmm5,%xmm12
+	movdqa	%xmm15,%xmm7
+	pslld	$7,%xmm15
+	psrld	$25,%xmm7
+	movdqa	%xmm12,%xmm6
+	pslld	$7,%xmm12
+	por	%xmm7,%xmm15
+	psrld	$25,%xmm6
+	movdqa	(%r10),%xmm7
+	por	%xmm6,%xmm12
+	decl	%eax
+	jnz	.Loop4x
+
+	paddd	64(%rsp),%xmm8
+	paddd	80(%rsp),%xmm9
+	paddd	96(%rsp),%xmm10
+	paddd	112(%rsp),%xmm11
+
+	movdqa	%xmm8,%xmm6
+	punpckldq	%xmm9,%xmm8
+	movdqa	%xmm10,%xmm7
+	punpckldq	%xmm11,%xmm10
+	punpckhdq	%xmm9,%xmm6
+	punpckhdq	%xmm11,%xmm7
+	movdqa	%xmm8,%xmm9
+	punpcklqdq	%xmm10,%xmm8
+	movdqa	%xmm6,%xmm11
+	punpcklqdq	%xmm7,%xmm6
+	punpckhqdq	%xmm10,%xmm9
+	punpckhqdq	%xmm7,%xmm11
+	paddd	128-256(%rcx),%xmm12
+	paddd	144-256(%rcx),%xmm13
+	paddd	160-256(%rcx),%xmm14
+	paddd	176-256(%rcx),%xmm15
+
+	movdqa	%xmm8,0(%rsp)
+	movdqa	%xmm9,16(%rsp)
+	movdqa	32(%rsp),%xmm8
+	movdqa	48(%rsp),%xmm9
+
+	movdqa	%xmm12,%xmm10
+	punpckldq	%xmm13,%xmm12
+	movdqa	%xmm14,%xmm7
+	punpckldq	%xmm15,%xmm14
+	punpckhdq	%xmm13,%xmm10
+	punpckhdq	%xmm15,%xmm7
+	movdqa	%xmm12,%xmm13
+	punpcklqdq	%xmm14,%xmm12
+	movdqa	%xmm10,%xmm15
+	punpcklqdq	%xmm7,%xmm10
+	punpckhqdq	%xmm14,%xmm13
+	punpckhqdq	%xmm7,%xmm15
+	paddd	192-256(%rcx),%xmm4
+	paddd	208-256(%rcx),%xmm5
+	paddd	224-256(%rcx),%xmm8
+	paddd	240-256(%rcx),%xmm9
+
+	movdqa	%xmm6,32(%rsp)
+	movdqa	%xmm11,48(%rsp)
+
+	movdqa	%xmm4,%xmm14
+	punpckldq	%xmm5,%xmm4
+	movdqa	%xmm8,%xmm7
+	punpckldq	%xmm9,%xmm8
+	punpckhdq	%xmm5,%xmm14
+	punpckhdq	%xmm9,%xmm7
+	movdqa	%xmm4,%xmm5
+	punpcklqdq	%xmm8,%xmm4
+	movdqa	%xmm14,%xmm9
+	punpcklqdq	%xmm7,%xmm14
+	punpckhqdq	%xmm8,%xmm5
+	punpckhqdq	%xmm7,%xmm9
+	paddd	256-256(%rcx),%xmm0
+	paddd	272-256(%rcx),%xmm1
+	paddd	288-256(%rcx),%xmm2
+	paddd	304-256(%rcx),%xmm3
+
+	movdqa	%xmm0,%xmm8
+	punpckldq	%xmm1,%xmm0
+	movdqa	%xmm2,%xmm7
+	punpckldq	%xmm3,%xmm2
+	punpckhdq	%xmm1,%xmm8
+	punpckhdq	%xmm3,%xmm7
+	movdqa	%xmm0,%xmm1
+	punpcklqdq	%xmm2,%xmm0
+	movdqa	%xmm8,%xmm3
+	punpcklqdq	%xmm7,%xmm8
+	punpckhqdq	%xmm2,%xmm1
+	punpckhqdq	%xmm7,%xmm3
+	cmpq	$256,%rdx
+	jb	.Ltail4x
+
+	movdqu	0(%rsi),%xmm6
+	movdqu	16(%rsi),%xmm11
+	movdqu	32(%rsi),%xmm2
+	movdqu	48(%rsi),%xmm7
+	pxor	0(%rsp),%xmm6
+	pxor	%xmm12,%xmm11
+	pxor	%xmm4,%xmm2
+	pxor	%xmm0,%xmm7
+
+	movdqu	%xmm6,0(%rdi)
+	movdqu	64(%rsi),%xmm6
+	movdqu	%xmm11,16(%rdi)
+	movdqu	80(%rsi),%xmm11
+	movdqu	%xmm2,32(%rdi)
+	movdqu	96(%rsi),%xmm2
+	movdqu	%xmm7,48(%rdi)
+	movdqu	112(%rsi),%xmm7
+	leaq	128(%rsi),%rsi
+	pxor	16(%rsp),%xmm6
+	pxor	%xmm13,%xmm11
+	pxor	%xmm5,%xmm2
+	pxor	%xmm1,%xmm7
+
+	movdqu	%xmm6,64(%rdi)
+	movdqu	0(%rsi),%xmm6
+	movdqu	%xmm11,80(%rdi)
+	movdqu	16(%rsi),%xmm11
+	movdqu	%xmm2,96(%rdi)
+	movdqu	32(%rsi),%xmm2
+	movdqu	%xmm7,112(%rdi)
+	leaq	128(%rdi),%rdi
+	movdqu	48(%rsi),%xmm7
+	pxor	32(%rsp),%xmm6
+	pxor	%xmm10,%xmm11
+	pxor	%xmm14,%xmm2
+	pxor	%xmm8,%xmm7
+
+	movdqu	%xmm6,0(%rdi)
+	movdqu	64(%rsi),%xmm6
+	movdqu	%xmm11,16(%rdi)
+	movdqu	80(%rsi),%xmm11
+	movdqu	%xmm2,32(%rdi)
+	movdqu	96(%rsi),%xmm2
+	movdqu	%xmm7,48(%rdi)
+	movdqu	112(%rsi),%xmm7
+	leaq	128(%rsi),%rsi
+	pxor	48(%rsp),%xmm6
+	pxor	%xmm15,%xmm11
+	pxor	%xmm9,%xmm2
+	pxor	%xmm3,%xmm7
+	movdqu	%xmm6,64(%rdi)
+	movdqu	%xmm11,80(%rdi)
+	movdqu	%xmm2,96(%rdi)
+	movdqu	%xmm7,112(%rdi)
+	leaq	128(%rdi),%rdi
+
+	subq	$256,%rdx
+	jnz	.Loop_outer4x
+
+	jmp	.Ldone4x
+
+.Ltail4x:
+	cmpq	$192,%rdx
+	jae	.L192_or_more4x
+	cmpq	$128,%rdx
+	jae	.L128_or_more4x
+	cmpq	$64,%rdx
+	jae	.L64_or_more4x
+
+
+	xorq	%r10,%r10
+
+	movdqa	%xmm12,16(%rsp)
+	movdqa	%xmm4,32(%rsp)
+	movdqa	%xmm0,48(%rsp)
+	jmp	.Loop_tail4x
+
+.align	32
+.L64_or_more4x:
+	movdqu	0(%rsi),%xmm6
+	movdqu	16(%rsi),%xmm11
+	movdqu	32(%rsi),%xmm2
+	movdqu	48(%rsi),%xmm7
+	pxor	0(%rsp),%xmm6
+	pxor	%xmm12,%xmm11
+	pxor	%xmm4,%xmm2
+	pxor	%xmm0,%xmm7
+	movdqu	%xmm6,0(%rdi)
+	movdqu	%xmm11,16(%rdi)
+	movdqu	%xmm2,32(%rdi)
+	movdqu	%xmm7,48(%rdi)
+	je	.Ldone4x
+
+	movdqa	16(%rsp),%xmm6
+	leaq	64(%rsi),%rsi
+	xorq	%r10,%r10
+	movdqa	%xmm6,0(%rsp)
+	movdqa	%xmm13,16(%rsp)
+	leaq	64(%rdi),%rdi
+	movdqa	%xmm5,32(%rsp)
+	subq	$64,%rdx
+	movdqa	%xmm1,48(%rsp)
+	jmp	.Loop_tail4x
+
+.align	32
+.L128_or_more4x:
+	movdqu	0(%rsi),%xmm6
+	movdqu	16(%rsi),%xmm11
+	movdqu	32(%rsi),%xmm2
+	movdqu	48(%rsi),%xmm7
+	pxor	0(%rsp),%xmm6
+	pxor	%xmm12,%xmm11
+	pxor	%xmm4,%xmm2
+	pxor	%xmm0,%xmm7
+
+	movdqu	%xmm6,0(%rdi)
+	movdqu	64(%rsi),%xmm6
+	movdqu	%xmm11,16(%rdi)
+	movdqu	80(%rsi),%xmm11
+	movdqu	%xmm2,32(%rdi)
+	movdqu	96(%rsi),%xmm2
+	movdqu	%xmm7,48(%rdi)
+	movdqu	112(%rsi),%xmm7
+	pxor	16(%rsp),%xmm6
+	pxor	%xmm13,%xmm11
+	pxor	%xmm5,%xmm2
+	pxor	%xmm1,%xmm7
+	movdqu	%xmm6,64(%rdi)
+	movdqu	%xmm11,80(%rdi)
+	movdqu	%xmm2,96(%rdi)
+	movdqu	%xmm7,112(%rdi)
+	je	.Ldone4x
+
+	movdqa	32(%rsp),%xmm6
+	leaq	128(%rsi),%rsi
+	xorq	%r10,%r10
+	movdqa	%xmm6,0(%rsp)
+	movdqa	%xmm10,16(%rsp)
+	leaq	128(%rdi),%rdi
+	movdqa	%xmm14,32(%rsp)
+	subq	$128,%rdx
+	movdqa	%xmm8,48(%rsp)
+	jmp	.Loop_tail4x
+
+.align	32
+.L192_or_more4x:
+	movdqu	0(%rsi),%xmm6
+	movdqu	16(%rsi),%xmm11
+	movdqu	32(%rsi),%xmm2
+	movdqu	48(%rsi),%xmm7
+	pxor	0(%rsp),%xmm6
+	pxor	%xmm12,%xmm11
+	pxor	%xmm4,%xmm2
+	pxor	%xmm0,%xmm7
+
+	movdqu	%xmm6,0(%rdi)
+	movdqu	64(%rsi),%xmm6
+	movdqu	%xmm11,16(%rdi)
+	movdqu	80(%rsi),%xmm11
+	movdqu	%xmm2,32(%rdi)
+	movdqu	96(%rsi),%xmm2
+	movdqu	%xmm7,48(%rdi)
+	movdqu	112(%rsi),%xmm7
+	leaq	128(%rsi),%rsi
+	pxor	16(%rsp),%xmm6
+	pxor	%xmm13,%xmm11
+	pxor	%xmm5,%xmm2
+	pxor	%xmm1,%xmm7
+
+	movdqu	%xmm6,64(%rdi)
+	movdqu	0(%rsi),%xmm6
+	movdqu	%xmm11,80(%rdi)
+	movdqu	16(%rsi),%xmm11
+	movdqu	%xmm2,96(%rdi)
+	movdqu	32(%rsi),%xmm2
+	movdqu	%xmm7,112(%rdi)
+	leaq	128(%rdi),%rdi
+	movdqu	48(%rsi),%xmm7
+	pxor	32(%rsp),%xmm6
+	pxor	%xmm10,%xmm11
+	pxor	%xmm14,%xmm2
+	pxor	%xmm8,%xmm7
+	movdqu	%xmm6,0(%rdi)
+	movdqu	%xmm11,16(%rdi)
+	movdqu	%xmm2,32(%rdi)
+	movdqu	%xmm7,48(%rdi)
+	je	.Ldone4x
+
+	movdqa	48(%rsp),%xmm6
+	leaq	64(%rsi),%rsi
+	xorq	%r10,%r10
+	movdqa	%xmm6,0(%rsp)
+	movdqa	%xmm15,16(%rsp)
+	leaq	64(%rdi),%rdi
+	movdqa	%xmm9,32(%rsp)
+	subq	$192,%rdx
+	movdqa	%xmm3,48(%rsp)
+
+.Loop_tail4x:
+	movzbl	(%rsi,%r10,1),%eax
+	movzbl	(%rsp,%r10,1),%ecx
+	leaq	1(%r10),%r10
+	xorl	%ecx,%eax
+	movb	%al,-1(%rdi,%r10,1)
+	decq	%rdx
+	jnz	.Loop_tail4x
+
+.Ldone4x:
+	leaq	(%r9),%rsp
+.L4x_epilogue:
+	.byte	0xf3,0xc3
+.size	ChaCha20_4x,.-ChaCha20_4x
+.type	ChaCha20_8x,@function
+.align	32
+ChaCha20_8x:
+.LChaCha20_8x:
+	movq	%rsp,%r9
+	subq	$0x280+8,%rsp
+	andq	$-32,%rsp
+	vzeroupper
+
+
+
+
+
+
+
+
+
+
+	vbroadcasti128	.Lsigma(%rip),%ymm11
+	vbroadcasti128	(%rcx),%ymm3
+	vbroadcasti128	16(%rcx),%ymm15
+	vbroadcasti128	(%r8),%ymm7
+	leaq	256(%rsp),%rcx
+	leaq	512(%rsp),%rax
+	leaq	.Lrot16(%rip),%r10
+	leaq	.Lrot24(%rip),%r11
+
+	vpshufd	$0x00,%ymm11,%ymm8
+	vpshufd	$0x55,%ymm11,%ymm9
+	vmovdqa	%ymm8,128-256(%rcx)
+	vpshufd	$0xaa,%ymm11,%ymm10
+	vmovdqa	%ymm9,160-256(%rcx)
+	vpshufd	$0xff,%ymm11,%ymm11
+	vmovdqa	%ymm10,192-256(%rcx)
+	vmovdqa	%ymm11,224-256(%rcx)
+
+	vpshufd	$0x00,%ymm3,%ymm0
+	vpshufd	$0x55,%ymm3,%ymm1
+	vmovdqa	%ymm0,256-256(%rcx)
+	vpshufd	$0xaa,%ymm3,%ymm2
+	vmovdqa	%ymm1,288-256(%rcx)
+	vpshufd	$0xff,%ymm3,%ymm3
+	vmovdqa	%ymm2,320-256(%rcx)
+	vmovdqa	%ymm3,352-256(%rcx)
+
+	vpshufd	$0x00,%ymm15,%ymm12
+	vpshufd	$0x55,%ymm15,%ymm13
+	vmovdqa	%ymm12,384-512(%rax)
+	vpshufd	$0xaa,%ymm15,%ymm14
+	vmovdqa	%ymm13,416-512(%rax)
+	vpshufd	$0xff,%ymm15,%ymm15
+	vmovdqa	%ymm14,448-512(%rax)
+	vmovdqa	%ymm15,480-512(%rax)
+
+	vpshufd	$0x00,%ymm7,%ymm4
+	vpshufd	$0x55,%ymm7,%ymm5
+	vpaddd	.Lincy(%rip),%ymm4,%ymm4
+	vpshufd	$0xaa,%ymm7,%ymm6
+	vmovdqa	%ymm5,544-512(%rax)
+	vpshufd	$0xff,%ymm7,%ymm7
+	vmovdqa	%ymm6,576-512(%rax)
+	vmovdqa	%ymm7,608-512(%rax)
+
+	jmp	.Loop_enter8x
+
+.align	32
+.Loop_outer8x:
+	vmovdqa	128-256(%rcx),%ymm8
+	vmovdqa	160-256(%rcx),%ymm9
+	vmovdqa	192-256(%rcx),%ymm10
+	vmovdqa	224-256(%rcx),%ymm11
+	vmovdqa	256-256(%rcx),%ymm0
+	vmovdqa	288-256(%rcx),%ymm1
+	vmovdqa	320-256(%rcx),%ymm2
+	vmovdqa	352-256(%rcx),%ymm3
+	vmovdqa	384-512(%rax),%ymm12
+	vmovdqa	416-512(%rax),%ymm13
+	vmovdqa	448-512(%rax),%ymm14
+	vmovdqa	480-512(%rax),%ymm15
+	vmovdqa	512-512(%rax),%ymm4
+	vmovdqa	544-512(%rax),%ymm5
+	vmovdqa	576-512(%rax),%ymm6
+	vmovdqa	608-512(%rax),%ymm7
+	vpaddd	.Leight(%rip),%ymm4,%ymm4
+
+.Loop_enter8x:
+	vmovdqa	%ymm14,64(%rsp)
+	vmovdqa	%ymm15,96(%rsp)
+	vbroadcasti128	(%r10),%ymm15
+	vmovdqa	%ymm4,512-512(%rax)
+	movl	$10,%eax
+	jmp	.Loop8x
+
+.align	32
+.Loop8x:
+	vpaddd	%ymm0,%ymm8,%ymm8
+	vpxor	%ymm4,%ymm8,%ymm4
+	vpshufb	%ymm15,%ymm4,%ymm4
+	vpaddd	%ymm1,%ymm9,%ymm9
+	vpxor	%ymm5,%ymm9,%ymm5
+	vpshufb	%ymm15,%ymm5,%ymm5
+	vpaddd	%ymm4,%ymm12,%ymm12
+	vpxor	%ymm0,%ymm12,%ymm0
+	vpslld	$12,%ymm0,%ymm14
+	vpsrld	$20,%ymm0,%ymm0
+	vpor	%ymm0,%ymm14,%ymm0
+	vbroadcasti128	(%r11),%ymm14
+	vpaddd	%ymm5,%ymm13,%ymm13
+	vpxor	%ymm1,%ymm13,%ymm1
+	vpslld	$12,%ymm1,%ymm15
+	vpsrld	$20,%ymm1,%ymm1
+	vpor	%ymm1,%ymm15,%ymm1
+	vpaddd	%ymm0,%ymm8,%ymm8
+	vpxor	%ymm4,%ymm8,%ymm4
+	vpshufb	%ymm14,%ymm4,%ymm4
+	vpaddd	%ymm1,%ymm9,%ymm9
+	vpxor	%ymm5,%ymm9,%ymm5
+	vpshufb	%ymm14,%ymm5,%ymm5
+	vpaddd	%ymm4,%ymm12,%ymm12
+	vpxor	%ymm0,%ymm12,%ymm0
+	vpslld	$7,%ymm0,%ymm15
+	vpsrld	$25,%ymm0,%ymm0
+	vpor	%ymm0,%ymm15,%ymm0
+	vbroadcasti128	(%r10),%ymm15
+	vpaddd	%ymm5,%ymm13,%ymm13
+	vpxor	%ymm1,%ymm13,%ymm1
+	vpslld	$7,%ymm1,%ymm14
+	vpsrld	$25,%ymm1,%ymm1
+	vpor	%ymm1,%ymm14,%ymm1
+	vmovdqa	%ymm12,0(%rsp)
+	vmovdqa	%ymm13,32(%rsp)
+	vmovdqa	64(%rsp),%ymm12
+	vmovdqa	96(%rsp),%ymm13
+	vpaddd	%ymm2,%ymm10,%ymm10
+	vpxor	%ymm6,%ymm10,%ymm6
+	vpshufb	%ymm15,%ymm6,%ymm6
+	vpaddd	%ymm3,%ymm11,%ymm11
+	vpxor	%ymm7,%ymm11,%ymm7
+	vpshufb	%ymm15,%ymm7,%ymm7
+	vpaddd	%ymm6,%ymm12,%ymm12
+	vpxor	%ymm2,%ymm12,%ymm2
+	vpslld	$12,%ymm2,%ymm14
+	vpsrld	$20,%ymm2,%ymm2
+	vpor	%ymm2,%ymm14,%ymm2
+	vbroadcasti128	(%r11),%ymm14
+	vpaddd	%ymm7,%ymm13,%ymm13
+	vpxor	%ymm3,%ymm13,%ymm3
+	vpslld	$12,%ymm3,%ymm15
+	vpsrld	$20,%ymm3,%ymm3
+	vpor	%ymm3,%ymm15,%ymm3
+	vpaddd	%ymm2,%ymm10,%ymm10
+	vpxor	%ymm6,%ymm10,%ymm6
+	vpshufb	%ymm14,%ymm6,%ymm6
+	vpaddd	%ymm3,%ymm11,%ymm11
+	vpxor	%ymm7,%ymm11,%ymm7
+	vpshufb	%ymm14,%ymm7,%ymm7
+	vpaddd	%ymm6,%ymm12,%ymm12
+	vpxor	%ymm2,%ymm12,%ymm2
+	vpslld	$7,%ymm2,%ymm15
+	vpsrld	$25,%ymm2,%ymm2
+	vpor	%ymm2,%ymm15,%ymm2
+	vbroadcasti128	(%r10),%ymm15
+	vpaddd	%ymm7,%ymm13,%ymm13
+	vpxor	%ymm3,%ymm13,%ymm3
+	vpslld	$7,%ymm3,%ymm14
+	vpsrld	$25,%ymm3,%ymm3
+	vpor	%ymm3,%ymm14,%ymm3
+	vpaddd	%ymm1,%ymm8,%ymm8
+	vpxor	%ymm7,%ymm8,%ymm7
+	vpshufb	%ymm15,%ymm7,%ymm7
+	vpaddd	%ymm2,%ymm9,%ymm9
+	vpxor	%ymm4,%ymm9,%ymm4
+	vpshufb	%ymm15,%ymm4,%ymm4
+	vpaddd	%ymm7,%ymm12,%ymm12
+	vpxor	%ymm1,%ymm12,%ymm1
+	vpslld	$12,%ymm1,%ymm14
+	vpsrld	$20,%ymm1,%ymm1
+	vpor	%ymm1,%ymm14,%ymm1
+	vbroadcasti128	(%r11),%ymm14
+	vpaddd	%ymm4,%ymm13,%ymm13
+	vpxor	%ymm2,%ymm13,%ymm2
+	vpslld	$12,%ymm2,%ymm15
+	vpsrld	$20,%ymm2,%ymm2
+	vpor	%ymm2,%ymm15,%ymm2
+	vpaddd	%ymm1,%ymm8,%ymm8
+	vpxor	%ymm7,%ymm8,%ymm7
+	vpshufb	%ymm14,%ymm7,%ymm7
+	vpaddd	%ymm2,%ymm9,%ymm9
+	vpxor	%ymm4,%ymm9,%ymm4
+	vpshufb	%ymm14,%ymm4,%ymm4
+	vpaddd	%ymm7,%ymm12,%ymm12
+	vpxor	%ymm1,%ymm12,%ymm1
+	vpslld	$7,%ymm1,%ymm15
+	vpsrld	$25,%ymm1,%ymm1
+	vpor	%ymm1,%ymm15,%ymm1
+	vbroadcasti128	(%r10),%ymm15
+	vpaddd	%ymm4,%ymm13,%ymm13
+	vpxor	%ymm2,%ymm13,%ymm2
+	vpslld	$7,%ymm2,%ymm14
+	vpsrld	$25,%ymm2,%ymm2
+	vpor	%ymm2,%ymm14,%ymm2
+	vmovdqa	%ymm12,64(%rsp)
+	vmovdqa	%ymm13,96(%rsp)
+	vmovdqa	0(%rsp),%ymm12
+	vmovdqa	32(%rsp),%ymm13
+	vpaddd	%ymm3,%ymm10,%ymm10
+	vpxor	%ymm5,%ymm10,%ymm5
+	vpshufb	%ymm15,%ymm5,%ymm5
+	vpaddd	%ymm0,%ymm11,%ymm11
+	vpxor	%ymm6,%ymm11,%ymm6
+	vpshufb	%ymm15,%ymm6,%ymm6
+	vpaddd	%ymm5,%ymm12,%ymm12
+	vpxor	%ymm3,%ymm12,%ymm3
+	vpslld	$12,%ymm3,%ymm14
+	vpsrld	$20,%ymm3,%ymm3
+	vpor	%ymm3,%ymm14,%ymm3
+	vbroadcasti128	(%r11),%ymm14
+	vpaddd	%ymm6,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm13,%ymm0
+	vpslld	$12,%ymm0,%ymm15
+	vpsrld	$20,%ymm0,%ymm0
+	vpor	%ymm0,%ymm15,%ymm0
+	vpaddd	%ymm3,%ymm10,%ymm10
+	vpxor	%ymm5,%ymm10,%ymm5
+	vpshufb	%ymm14,%ymm5,%ymm5
+	vpaddd	%ymm0,%ymm11,%ymm11
+	vpxor	%ymm6,%ymm11,%ymm6
+	vpshufb	%ymm14,%ymm6,%ymm6
+	vpaddd	%ymm5,%ymm12,%ymm12
+	vpxor	%ymm3,%ymm12,%ymm3
+	vpslld	$7,%ymm3,%ymm15
+	vpsrld	$25,%ymm3,%ymm3
+	vpor	%ymm3,%ymm15,%ymm3
+	vbroadcasti128	(%r10),%ymm15
+	vpaddd	%ymm6,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm13,%ymm0
+	vpslld	$7,%ymm0,%ymm14
+	vpsrld	$25,%ymm0,%ymm0
+	vpor	%ymm0,%ymm14,%ymm0
+	decl	%eax
+	jnz	.Loop8x
+
+	leaq	512(%rsp),%rax
+	vpaddd	128-256(%rcx),%ymm8,%ymm8
+	vpaddd	160-256(%rcx),%ymm9,%ymm9
+	vpaddd	192-256(%rcx),%ymm10,%ymm10
+	vpaddd	224-256(%rcx),%ymm11,%ymm11
+
+	vpunpckldq	%ymm9,%ymm8,%ymm14
+	vpunpckldq	%ymm11,%ymm10,%ymm15
+	vpunpckhdq	%ymm9,%ymm8,%ymm8
+	vpunpckhdq	%ymm11,%ymm10,%ymm10
+	vpunpcklqdq	%ymm15,%ymm14,%ymm9
+	vpunpckhqdq	%ymm15,%ymm14,%ymm14
+	vpunpcklqdq	%ymm10,%ymm8,%ymm11
+	vpunpckhqdq	%ymm10,%ymm8,%ymm8
+	vpaddd	256-256(%rcx),%ymm0,%ymm0
+	vpaddd	288-256(%rcx),%ymm1,%ymm1
+	vpaddd	320-256(%rcx),%ymm2,%ymm2
+	vpaddd	352-256(%rcx),%ymm3,%ymm3
+
+	vpunpckldq	%ymm1,%ymm0,%ymm10
+	vpunpckldq	%ymm3,%ymm2,%ymm15
+	vpunpckhdq	%ymm1,%ymm0,%ymm0
+	vpunpckhdq	%ymm3,%ymm2,%ymm2
+	vpunpcklqdq	%ymm15,%ymm10,%ymm1
+	vpunpckhqdq	%ymm15,%ymm10,%ymm10
+	vpunpcklqdq	%ymm2,%ymm0,%ymm3
+	vpunpckhqdq	%ymm2,%ymm0,%ymm0
+	vperm2i128	$0x20,%ymm1,%ymm9,%ymm15
+	vperm2i128	$0x31,%ymm1,%ymm9,%ymm1
+	vperm2i128	$0x20,%ymm10,%ymm14,%ymm9
+	vperm2i128	$0x31,%ymm10,%ymm14,%ymm10
+	vperm2i128	$0x20,%ymm3,%ymm11,%ymm14
+	vperm2i128	$0x31,%ymm3,%ymm11,%ymm3
+	vperm2i128	$0x20,%ymm0,%ymm8,%ymm11
+	vperm2i128	$0x31,%ymm0,%ymm8,%ymm0
+	vmovdqa	%ymm15,0(%rsp)
+	vmovdqa	%ymm9,32(%rsp)
+	vmovdqa	64(%rsp),%ymm15
+	vmovdqa	96(%rsp),%ymm9
+
+	vpaddd	384-512(%rax),%ymm12,%ymm12
+	vpaddd	416-512(%rax),%ymm13,%ymm13
+	vpaddd	448-512(%rax),%ymm15,%ymm15
+	vpaddd	480-512(%rax),%ymm9,%ymm9
+
+	vpunpckldq	%ymm13,%ymm12,%ymm2
+	vpunpckldq	%ymm9,%ymm15,%ymm8
+	vpunpckhdq	%ymm13,%ymm12,%ymm12
+	vpunpckhdq	%ymm9,%ymm15,%ymm15
+	vpunpcklqdq	%ymm8,%ymm2,%ymm13
+	vpunpckhqdq	%ymm8,%ymm2,%ymm2
+	vpunpcklqdq	%ymm15,%ymm12,%ymm9
+	vpunpckhqdq	%ymm15,%ymm12,%ymm12
+	vpaddd	512-512(%rax),%ymm4,%ymm4
+	vpaddd	544-512(%rax),%ymm5,%ymm5
+	vpaddd	576-512(%rax),%ymm6,%ymm6
+	vpaddd	608-512(%rax),%ymm7,%ymm7
+
+	vpunpckldq	%ymm5,%ymm4,%ymm15
+	vpunpckldq	%ymm7,%ymm6,%ymm8
+	vpunpckhdq	%ymm5,%ymm4,%ymm4
+	vpunpckhdq	%ymm7,%ymm6,%ymm6
+	vpunpcklqdq	%ymm8,%ymm15,%ymm5
+	vpunpckhqdq	%ymm8,%ymm15,%ymm15
+	vpunpcklqdq	%ymm6,%ymm4,%ymm7
+	vpunpckhqdq	%ymm6,%ymm4,%ymm4
+	vperm2i128	$0x20,%ymm5,%ymm13,%ymm8
+	vperm2i128	$0x31,%ymm5,%ymm13,%ymm5
+	vperm2i128	$0x20,%ymm15,%ymm2,%ymm13
+	vperm2i128	$0x31,%ymm15,%ymm2,%ymm15
+	vperm2i128	$0x20,%ymm7,%ymm9,%ymm2
+	vperm2i128	$0x31,%ymm7,%ymm9,%ymm7
+	vperm2i128	$0x20,%ymm4,%ymm12,%ymm9
+	vperm2i128	$0x31,%ymm4,%ymm12,%ymm4
+	vmovdqa	0(%rsp),%ymm6
+	vmovdqa	32(%rsp),%ymm12
+
+	cmpq	$512,%rdx
+	jb	.Ltail8x
+
+	vpxor	0(%rsi),%ymm6,%ymm6
+	vpxor	32(%rsi),%ymm8,%ymm8
+	vpxor	64(%rsi),%ymm1,%ymm1
+	vpxor	96(%rsi),%ymm5,%ymm5
+	leaq	128(%rsi),%rsi
+	vmovdqu	%ymm6,0(%rdi)
+	vmovdqu	%ymm8,32(%rdi)
+	vmovdqu	%ymm1,64(%rdi)
+	vmovdqu	%ymm5,96(%rdi)
+	leaq	128(%rdi),%rdi
+
+	vpxor	0(%rsi),%ymm12,%ymm12
+	vpxor	32(%rsi),%ymm13,%ymm13
+	vpxor	64(%rsi),%ymm10,%ymm10
+	vpxor	96(%rsi),%ymm15,%ymm15
+	leaq	128(%rsi),%rsi
+	vmovdqu	%ymm12,0(%rdi)
+	vmovdqu	%ymm13,32(%rdi)
+	vmovdqu	%ymm10,64(%rdi)
+	vmovdqu	%ymm15,96(%rdi)
+	leaq	128(%rdi),%rdi
+
+	vpxor	0(%rsi),%ymm14,%ymm14
+	vpxor	32(%rsi),%ymm2,%ymm2
+	vpxor	64(%rsi),%ymm3,%ymm3
+	vpxor	96(%rsi),%ymm7,%ymm7
+	leaq	128(%rsi),%rsi
+	vmovdqu	%ymm14,0(%rdi)
+	vmovdqu	%ymm2,32(%rdi)
+	vmovdqu	%ymm3,64(%rdi)
+	vmovdqu	%ymm7,96(%rdi)
+	leaq	128(%rdi),%rdi
+
+	vpxor	0(%rsi),%ymm11,%ymm11
+	vpxor	32(%rsi),%ymm9,%ymm9
+	vpxor	64(%rsi),%ymm0,%ymm0
+	vpxor	96(%rsi),%ymm4,%ymm4
+	leaq	128(%rsi),%rsi
+	vmovdqu	%ymm11,0(%rdi)
+	vmovdqu	%ymm9,32(%rdi)
+	vmovdqu	%ymm0,64(%rdi)
+	vmovdqu	%ymm4,96(%rdi)
+	leaq	128(%rdi),%rdi
+
+	subq	$512,%rdx
+	jnz	.Loop_outer8x
+
+	jmp	.Ldone8x
+
+.Ltail8x:
+	cmpq	$448,%rdx
+	jae	.L448_or_more8x
+	cmpq	$384,%rdx
+	jae	.L384_or_more8x
+	cmpq	$320,%rdx
+	jae	.L320_or_more8x
+	cmpq	$256,%rdx
+	jae	.L256_or_more8x
+	cmpq	$192,%rdx
+	jae	.L192_or_more8x
+	cmpq	$128,%rdx
+	jae	.L128_or_more8x
+	cmpq	$64,%rdx
+	jae	.L64_or_more8x
+
+	xorq	%r10,%r10
+	vmovdqa	%ymm6,0(%rsp)
+	vmovdqa	%ymm8,32(%rsp)
+	jmp	.Loop_tail8x
+
+.align	32
+.L64_or_more8x:
+	vpxor	0(%rsi),%ymm6,%ymm6
+	vpxor	32(%rsi),%ymm8,%ymm8
+	vmovdqu	%ymm6,0(%rdi)
+	vmovdqu	%ymm8,32(%rdi)
+	je	.Ldone8x
+
+	leaq	64(%rsi),%rsi
+	xorq	%r10,%r10
+	vmovdqa	%ymm1,0(%rsp)
+	leaq	64(%rdi),%rdi
+	subq	$64,%rdx
+	vmovdqa	%ymm5,32(%rsp)
+	jmp	.Loop_tail8x
+
+.align	32
+.L128_or_more8x:
+	vpxor	0(%rsi),%ymm6,%ymm6
+	vpxor	32(%rsi),%ymm8,%ymm8
+	vpxor	64(%rsi),%ymm1,%ymm1
+	vpxor	96(%rsi),%ymm5,%ymm5
+	vmovdqu	%ymm6,0(%rdi)
+	vmovdqu	%ymm8,32(%rdi)
+	vmovdqu	%ymm1,64(%rdi)
+	vmovdqu	%ymm5,96(%rdi)
+	je	.Ldone8x
+
+	leaq	128(%rsi),%rsi
+	xorq	%r10,%r10
+	vmovdqa	%ymm12,0(%rsp)
+	leaq	128(%rdi),%rdi
+	subq	$128,%rdx
+	vmovdqa	%ymm13,32(%rsp)
+	jmp	.Loop_tail8x
+
+.align	32
+.L192_or_more8x:
+	vpxor	0(%rsi),%ymm6,%ymm6
+	vpxor	32(%rsi),%ymm8,%ymm8
+	vpxor	64(%rsi),%ymm1,%ymm1
+	vpxor	96(%rsi),%ymm5,%ymm5
+	vpxor	128(%rsi),%ymm12,%ymm12
+	vpxor	160(%rsi),%ymm13,%ymm13
+	vmovdqu	%ymm6,0(%rdi)
+	vmovdqu	%ymm8,32(%rdi)
+	vmovdqu	%ymm1,64(%rdi)
+	vmovdqu	%ymm5,96(%rdi)
+	vmovdqu	%ymm12,128(%rdi)
+	vmovdqu	%ymm13,160(%rdi)
+	je	.Ldone8x
+
+	leaq	192(%rsi),%rsi
+	xorq	%r10,%r10
+	vmovdqa	%ymm10,0(%rsp)
+	leaq	192(%rdi),%rdi
+	subq	$192,%rdx
+	vmovdqa	%ymm15,32(%rsp)
+	jmp	.Loop_tail8x
+
+.align	32
+.L256_or_more8x:
+	vpxor	0(%rsi),%ymm6,%ymm6
+	vpxor	32(%rsi),%ymm8,%ymm8
+	vpxor	64(%rsi),%ymm1,%ymm1
+	vpxor	96(%rsi),%ymm5,%ymm5
+	vpxor	128(%rsi),%ymm12,%ymm12
+	vpxor	160(%rsi),%ymm13,%ymm13
+	vpxor	192(%rsi),%ymm10,%ymm10
+	vpxor	224(%rsi),%ymm15,%ymm15
+	vmovdqu	%ymm6,0(%rdi)
+	vmovdqu	%ymm8,32(%rdi)
+	vmovdqu	%ymm1,64(%rdi)
+	vmovdqu	%ymm5,96(%rdi)
+	vmovdqu	%ymm12,128(%rdi)
+	vmovdqu	%ymm13,160(%rdi)
+	vmovdqu	%ymm10,192(%rdi)
+	vmovdqu	%ymm15,224(%rdi)
+	je	.Ldone8x
+
+	leaq	256(%rsi),%rsi
+	xorq	%r10,%r10
+	vmovdqa	%ymm14,0(%rsp)
+	leaq	256(%rdi),%rdi
+	subq	$256,%rdx
+	vmovdqa	%ymm2,32(%rsp)
+	jmp	.Loop_tail8x
+
+.align	32
+.L320_or_more8x:
+	vpxor	0(%rsi),%ymm6,%ymm6
+	vpxor	32(%rsi),%ymm8,%ymm8
+	vpxor	64(%rsi),%ymm1,%ymm1
+	vpxor	96(%rsi),%ymm5,%ymm5
+	vpxor	128(%rsi),%ymm12,%ymm12
+	vpxor	160(%rsi),%ymm13,%ymm13
+	vpxor	192(%rsi),%ymm10,%ymm10
+	vpxor	224(%rsi),%ymm15,%ymm15
+	vpxor	256(%rsi),%ymm14,%ymm14
+	vpxor	288(%rsi),%ymm2,%ymm2
+	vmovdqu	%ymm6,0(%rdi)
+	vmovdqu	%ymm8,32(%rdi)
+	vmovdqu	%ymm1,64(%rdi)
+	vmovdqu	%ymm5,96(%rdi)
+	vmovdqu	%ymm12,128(%rdi)
+	vmovdqu	%ymm13,160(%rdi)
+	vmovdqu	%ymm10,192(%rdi)
+	vmovdqu	%ymm15,224(%rdi)
+	vmovdqu	%ymm14,256(%rdi)
+	vmovdqu	%ymm2,288(%rdi)
+	je	.Ldone8x
+
+	leaq	320(%rsi),%rsi
+	xorq	%r10,%r10
+	vmovdqa	%ymm3,0(%rsp)
+	leaq	320(%rdi),%rdi
+	subq	$320,%rdx
+	vmovdqa	%ymm7,32(%rsp)
+	jmp	.Loop_tail8x
+
+.align	32
+.L384_or_more8x:
+	vpxor	0(%rsi),%ymm6,%ymm6
+	vpxor	32(%rsi),%ymm8,%ymm8
+	vpxor	64(%rsi),%ymm1,%ymm1
+	vpxor	96(%rsi),%ymm5,%ymm5
+	vpxor	128(%rsi),%ymm12,%ymm12
+	vpxor	160(%rsi),%ymm13,%ymm13
+	vpxor	192(%rsi),%ymm10,%ymm10
+	vpxor	224(%rsi),%ymm15,%ymm15
+	vpxor	256(%rsi),%ymm14,%ymm14
+	vpxor	288(%rsi),%ymm2,%ymm2
+	vpxor	320(%rsi),%ymm3,%ymm3
+	vpxor	352(%rsi),%ymm7,%ymm7
+	vmovdqu	%ymm6,0(%rdi)
+	vmovdqu	%ymm8,32(%rdi)
+	vmovdqu	%ymm1,64(%rdi)
+	vmovdqu	%ymm5,96(%rdi)
+	vmovdqu	%ymm12,128(%rdi)
+	vmovdqu	%ymm13,160(%rdi)
+	vmovdqu	%ymm10,192(%rdi)
+	vmovdqu	%ymm15,224(%rdi)
+	vmovdqu	%ymm14,256(%rdi)
+	vmovdqu	%ymm2,288(%rdi)
+	vmovdqu	%ymm3,320(%rdi)
+	vmovdqu	%ymm7,352(%rdi)
+	je	.Ldone8x
+
+	leaq	384(%rsi),%rsi
+	xorq	%r10,%r10
+	vmovdqa	%ymm11,0(%rsp)
+	leaq	384(%rdi),%rdi
+	subq	$384,%rdx
+	vmovdqa	%ymm9,32(%rsp)
+	jmp	.Loop_tail8x
+
+.align	32
+.L448_or_more8x:
+	vpxor	0(%rsi),%ymm6,%ymm6
+	vpxor	32(%rsi),%ymm8,%ymm8
+	vpxor	64(%rsi),%ymm1,%ymm1
+	vpxor	96(%rsi),%ymm5,%ymm5
+	vpxor	128(%rsi),%ymm12,%ymm12
+	vpxor	160(%rsi),%ymm13,%ymm13
+	vpxor	192(%rsi),%ymm10,%ymm10
+	vpxor	224(%rsi),%ymm15,%ymm15
+	vpxor	256(%rsi),%ymm14,%ymm14
+	vpxor	288(%rsi),%ymm2,%ymm2
+	vpxor	320(%rsi),%ymm3,%ymm3
+	vpxor	352(%rsi),%ymm7,%ymm7
+	vpxor	384(%rsi),%ymm11,%ymm11
+	vpxor	416(%rsi),%ymm9,%ymm9
+	vmovdqu	%ymm6,0(%rdi)
+	vmovdqu	%ymm8,32(%rdi)
+	vmovdqu	%ymm1,64(%rdi)
+	vmovdqu	%ymm5,96(%rdi)
+	vmovdqu	%ymm12,128(%rdi)
+	vmovdqu	%ymm13,160(%rdi)
+	vmovdqu	%ymm10,192(%rdi)
+	vmovdqu	%ymm15,224(%rdi)
+	vmovdqu	%ymm14,256(%rdi)
+	vmovdqu	%ymm2,288(%rdi)
+	vmovdqu	%ymm3,320(%rdi)
+	vmovdqu	%ymm7,352(%rdi)
+	vmovdqu	%ymm11,384(%rdi)
+	vmovdqu	%ymm9,416(%rdi)
+	je	.Ldone8x
+
+	leaq	448(%rsi),%rsi
+	xorq	%r10,%r10
+	vmovdqa	%ymm0,0(%rsp)
+	leaq	448(%rdi),%rdi
+	subq	$448,%rdx
+	vmovdqa	%ymm4,32(%rsp)
+
+.Loop_tail8x:
+	movzbl	(%rsi,%r10,1),%eax
+	movzbl	(%rsp,%r10,1),%ecx
+	leaq	1(%r10),%r10
+	xorl	%ecx,%eax
+	movb	%al,-1(%rdi,%r10,1)
+	decq	%rdx
+	jnz	.Loop_tail8x
+
+.Ldone8x:
+	vzeroall
+	leaq	(%r9),%rsp
+.L8x_epilogue:
+	.byte	0xf3,0xc3
+.size	ChaCha20_8x,.-ChaCha20_8x
+#endif
diff --git a/linux-x86_64/crypto/cipher/chacha20_poly1305_x86_64.S b/linux-x86_64/crypto/cipher/chacha20_poly1305_x86_64.S
new file mode 100644
index 0000000..c7e673f
--- /dev/null
+++ b/linux-x86_64/crypto/cipher/chacha20_poly1305_x86_64.S
@@ -0,0 +1,8788 @@
+#if defined(__x86_64__)
+.text	
+.extern	OPENSSL_ia32cap_P
+.hidden OPENSSL_ia32cap_P
+
+chacha20_poly1305_constants:
+
+.align	64
+.chacha20_consts:
+.byte	'e','x','p','a','n','d',' ','3','2','-','b','y','t','e',' ','k'
+.byte	'e','x','p','a','n','d',' ','3','2','-','b','y','t','e',' ','k'
+.rol8:
+.byte	3,0,1,2, 7,4,5,6, 11,8,9,10, 15,12,13,14
+.byte	3,0,1,2, 7,4,5,6, 11,8,9,10, 15,12,13,14
+.rol16:
+.byte	2,3,0,1, 6,7,4,5, 10,11,8,9, 14,15,12,13
+.byte	2,3,0,1, 6,7,4,5, 10,11,8,9, 14,15,12,13
+.avx2_init:
+.long	0,0,0,0
+.sse_inc:
+.long	1,0,0,0
+.avx2_inc:
+.long	2,0,0,0,2,0,0,0
+.clamp:
+.quad	0x0FFFFFFC0FFFFFFF, 0x0FFFFFFC0FFFFFFC
+.quad	0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF
+.align	16
+.and_masks:
+.byte	0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+.byte	0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+.byte	0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+.byte	0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+.byte	0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+.byte	0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+.byte	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+.byte	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+.byte	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+.byte	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00
+.byte	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00
+.byte	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00
+.byte	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00
+.byte	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00
+.byte	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00
+
+.type	poly_hash_ad_internal,@function
+.align	64
+poly_hash_ad_internal:
+.cfi_startproc	
+	xorq	%r10,%r10
+	xorq	%r11,%r11
+	xorq	%r12,%r12
+	cmpq	$13,%r8
+	jne	hash_ad_loop
+poly_fast_tls_ad:
+
+	movq	(%rcx),%r10
+	movq	5(%rcx),%r11
+	shrq	$24,%r11
+	movq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	.byte	0xf3,0xc3
+hash_ad_loop:
+
+	cmpq	$16,%r8
+	jb	hash_ad_tail
+	addq	0(%rcx),%r10
+	adcq	8+0(%rcx),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%rcx),%rcx
+	subq	$16,%r8
+	jmp	hash_ad_loop
+hash_ad_tail:
+	cmpq	$0,%r8
+	je	1f
+
+	xorq	%r13,%r13
+	xorq	%r14,%r14
+	xorq	%r15,%r15
+	addq	%r8,%rcx
+hash_ad_tail_loop:
+	shldq	$8,%r13,%r14
+	shlq	$8,%r13
+	movzbq	-1(%rcx),%r15
+	xorq	%r15,%r13
+	decq	%rcx
+	decq	%r8
+	jne	hash_ad_tail_loop
+
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+
+1:
+	.byte	0xf3,0xc3
+.cfi_endproc	
+.size	poly_hash_ad_internal, .-poly_hash_ad_internal
+
+.globl	chacha20_poly1305_open
+.hidden chacha20_poly1305_open
+.type	chacha20_poly1305_open,@function
+.align	64
+chacha20_poly1305_open:
+.cfi_startproc	
+	pushq	%rbp
+.cfi_adjust_cfa_offset	8
+	pushq	%rbx
+.cfi_adjust_cfa_offset	8
+	pushq	%r12
+.cfi_adjust_cfa_offset	8
+	pushq	%r13
+.cfi_adjust_cfa_offset	8
+	pushq	%r14
+.cfi_adjust_cfa_offset	8
+	pushq	%r15
+.cfi_adjust_cfa_offset	8
+
+
+	pushq	%r9
+.cfi_adjust_cfa_offset	8
+	subq	$288 + 32,%rsp
+.cfi_adjust_cfa_offset	288 + 32
+.cfi_offset	rbp, -16
+.cfi_offset	rbx, -24
+.cfi_offset	r12, -32
+.cfi_offset	r13, -40
+.cfi_offset	r14, -48
+.cfi_offset	r15, -56
+	leaq	32(%rsp),%rbp
+	andq	$-32,%rbp
+	movq	%rdx,8+32(%rbp)
+	movq	%r8,0+32(%rbp)
+	movq	%rdx,%rbx
+
+	movl	OPENSSL_ia32cap_P+8(%rip),%eax
+	andl	$288,%eax
+	xorl	$288,%eax
+	jz	chacha20_poly1305_open_avx2
+
+1:
+	cmpq	$128,%rbx
+	jbe	open_sse_128
+
+	movdqa	.chacha20_consts(%rip),%xmm0
+	movdqu	0(%r9),%xmm4
+	movdqu	16(%r9),%xmm8
+	movdqu	32(%r9),%xmm12
+	movdqa	%xmm12,%xmm7
+
+	movdqa	%xmm4,48(%rbp)
+	movdqa	%xmm8,64(%rbp)
+	movdqa	%xmm12,96(%rbp)
+	movq	$10,%r10
+1:
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,4
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,12
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,12
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,4
+
+	decq	%r10
+	jne	1b
+
+	paddd	.chacha20_consts(%rip),%xmm0
+	paddd	48(%rbp),%xmm4
+
+	pand	.clamp(%rip),%xmm0
+	movdqa	%xmm0,0(%rbp)
+	movdqa	%xmm4,16(%rbp)
+
+	movq	%r8,%r8
+	call	poly_hash_ad_internal
+open_sse_main_loop:
+	cmpq	$256,%rbx
+	jb	2f
+
+	movdqa	.chacha20_consts(%rip),%xmm0
+	movdqa	48(%rbp),%xmm4
+	movdqa	64(%rbp),%xmm8
+	movdqa	%xmm0,%xmm1
+	movdqa	%xmm4,%xmm5
+	movdqa	%xmm8,%xmm9
+	movdqa	%xmm0,%xmm2
+	movdqa	%xmm4,%xmm6
+	movdqa	%xmm8,%xmm10
+	movdqa	%xmm0,%xmm3
+	movdqa	%xmm4,%xmm7
+	movdqa	%xmm8,%xmm11
+	movdqa	96(%rbp),%xmm15
+	paddd	.sse_inc(%rip),%xmm15
+	movdqa	%xmm15,%xmm14
+	paddd	.sse_inc(%rip),%xmm14
+	movdqa	%xmm14,%xmm13
+	paddd	.sse_inc(%rip),%xmm13
+	movdqa	%xmm13,%xmm12
+	paddd	.sse_inc(%rip),%xmm12
+	movdqa	%xmm12,96(%rbp)
+	movdqa	%xmm13,112(%rbp)
+	movdqa	%xmm14,128(%rbp)
+	movdqa	%xmm15,144(%rbp)
+
+
+
+	movq	$4,%rcx
+	movq	%rsi,%r8
+1:
+	movdqa	%xmm8,80(%rbp)
+	movdqa	.rol16(%rip),%xmm8
+	paddd	%xmm7,%xmm3
+	paddd	%xmm6,%xmm2
+	paddd	%xmm5,%xmm1
+	paddd	%xmm4,%xmm0
+	pxor	%xmm3,%xmm15
+	pxor	%xmm2,%xmm14
+	pxor	%xmm1,%xmm13
+	pxor	%xmm0,%xmm12
+.byte	102,69,15,56,0,248
+.byte	102,69,15,56,0,240
+.byte	102,69,15,56,0,232
+.byte	102,69,15,56,0,224
+	movdqa	80(%rbp),%xmm8
+	paddd	%xmm15,%xmm11
+	paddd	%xmm14,%xmm10
+	paddd	%xmm13,%xmm9
+	paddd	%xmm12,%xmm8
+	pxor	%xmm11,%xmm7
+	addq	0(%r8),%r10
+	adcq	8+0(%r8),%r11
+	adcq	$1,%r12
+
+	leaq	16(%r8),%r8
+	pxor	%xmm10,%xmm6
+	pxor	%xmm9,%xmm5
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm8,80(%rbp)
+	movdqa	%xmm7,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm7
+	pxor	%xmm8,%xmm7
+	movdqa	%xmm6,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm6
+	pxor	%xmm8,%xmm6
+	movdqa	%xmm5,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm5
+	pxor	%xmm8,%xmm5
+	movdqa	%xmm4,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm4
+	pxor	%xmm8,%xmm4
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movdqa	.rol8(%rip),%xmm8
+	paddd	%xmm7,%xmm3
+	paddd	%xmm6,%xmm2
+	paddd	%xmm5,%xmm1
+	paddd	%xmm4,%xmm0
+	pxor	%xmm3,%xmm15
+	pxor	%xmm2,%xmm14
+	pxor	%xmm1,%xmm13
+	pxor	%xmm0,%xmm12
+.byte	102,69,15,56,0,248
+.byte	102,69,15,56,0,240
+.byte	102,69,15,56,0,232
+.byte	102,69,15,56,0,224
+	movdqa	80(%rbp),%xmm8
+	paddd	%xmm15,%xmm11
+	paddd	%xmm14,%xmm10
+	paddd	%xmm13,%xmm9
+	paddd	%xmm12,%xmm8
+	pxor	%xmm11,%xmm7
+	pxor	%xmm10,%xmm6
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	pxor	%xmm9,%xmm5
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm8,80(%rbp)
+	movdqa	%xmm7,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm7
+	pxor	%xmm8,%xmm7
+	movdqa	%xmm6,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm6
+	pxor	%xmm8,%xmm6
+	movdqa	%xmm5,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm5
+	pxor	%xmm8,%xmm5
+	movdqa	%xmm4,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm4
+	pxor	%xmm8,%xmm4
+	movdqa	80(%rbp),%xmm8
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+.byte	102,15,58,15,255,4
+.byte	102,69,15,58,15,219,8
+.byte	102,69,15,58,15,255,12
+.byte	102,15,58,15,246,4
+.byte	102,69,15,58,15,210,8
+.byte	102,69,15,58,15,246,12
+.byte	102,15,58,15,237,4
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,12
+.byte	102,15,58,15,228,4
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,12
+	movdqa	%xmm8,80(%rbp)
+	movdqa	.rol16(%rip),%xmm8
+	paddd	%xmm7,%xmm3
+	paddd	%xmm6,%xmm2
+	paddd	%xmm5,%xmm1
+	paddd	%xmm4,%xmm0
+	pxor	%xmm3,%xmm15
+	pxor	%xmm2,%xmm14
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	pxor	%xmm1,%xmm13
+	pxor	%xmm0,%xmm12
+.byte	102,69,15,56,0,248
+.byte	102,69,15,56,0,240
+.byte	102,69,15,56,0,232
+.byte	102,69,15,56,0,224
+	movdqa	80(%rbp),%xmm8
+	paddd	%xmm15,%xmm11
+	paddd	%xmm14,%xmm10
+	paddd	%xmm13,%xmm9
+	paddd	%xmm12,%xmm8
+	pxor	%xmm11,%xmm7
+	pxor	%xmm10,%xmm6
+	pxor	%xmm9,%xmm5
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm8,80(%rbp)
+	movdqa	%xmm7,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm7
+	pxor	%xmm8,%xmm7
+	movdqa	%xmm6,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm6
+	pxor	%xmm8,%xmm6
+	movdqa	%xmm5,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm5
+	pxor	%xmm8,%xmm5
+	movdqa	%xmm4,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm4
+	pxor	%xmm8,%xmm4
+	movdqa	.rol8(%rip),%xmm8
+	paddd	%xmm7,%xmm3
+	paddd	%xmm6,%xmm2
+	paddd	%xmm5,%xmm1
+	paddd	%xmm4,%xmm0
+	pxor	%xmm3,%xmm15
+	pxor	%xmm2,%xmm14
+	pxor	%xmm1,%xmm13
+	pxor	%xmm0,%xmm12
+.byte	102,69,15,56,0,248
+.byte	102,69,15,56,0,240
+.byte	102,69,15,56,0,232
+.byte	102,69,15,56,0,224
+	movdqa	80(%rbp),%xmm8
+	paddd	%xmm15,%xmm11
+	paddd	%xmm14,%xmm10
+	paddd	%xmm13,%xmm9
+	paddd	%xmm12,%xmm8
+	pxor	%xmm11,%xmm7
+	pxor	%xmm10,%xmm6
+	pxor	%xmm9,%xmm5
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm8,80(%rbp)
+	movdqa	%xmm7,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm7
+	pxor	%xmm8,%xmm7
+	movdqa	%xmm6,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm6
+	pxor	%xmm8,%xmm6
+	movdqa	%xmm5,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm5
+	pxor	%xmm8,%xmm5
+	movdqa	%xmm4,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm4
+	pxor	%xmm8,%xmm4
+	movdqa	80(%rbp),%xmm8
+.byte	102,15,58,15,255,12
+.byte	102,69,15,58,15,219,8
+.byte	102,69,15,58,15,255,4
+.byte	102,15,58,15,246,12
+.byte	102,69,15,58,15,210,8
+.byte	102,69,15,58,15,246,4
+.byte	102,15,58,15,237,12
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,4
+.byte	102,15,58,15,228,12
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,4
+
+	decq	%rcx
+	jge	1b
+	addq	0(%r8),%r10
+	adcq	8+0(%r8),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%r8),%r8
+	cmpq	$-6,%rcx
+	jg	1b
+	paddd	.chacha20_consts(%rip),%xmm3
+	paddd	48(%rbp),%xmm7
+	paddd	64(%rbp),%xmm11
+	paddd	144(%rbp),%xmm15
+	paddd	.chacha20_consts(%rip),%xmm2
+	paddd	48(%rbp),%xmm6
+	paddd	64(%rbp),%xmm10
+	paddd	128(%rbp),%xmm14
+	paddd	.chacha20_consts(%rip),%xmm1
+	paddd	48(%rbp),%xmm5
+	paddd	64(%rbp),%xmm9
+	paddd	112(%rbp),%xmm13
+	paddd	.chacha20_consts(%rip),%xmm0
+	paddd	48(%rbp),%xmm4
+	paddd	64(%rbp),%xmm8
+	paddd	96(%rbp),%xmm12
+	movdqa	%xmm12,80(%rbp)
+	movdqu	0 + 0(%rsi),%xmm12
+	pxor	%xmm3,%xmm12
+	movdqu	%xmm12,0 + 0(%rdi)
+	movdqu	16 + 0(%rsi),%xmm12
+	pxor	%xmm7,%xmm12
+	movdqu	%xmm12,16 + 0(%rdi)
+	movdqu	32 + 0(%rsi),%xmm12
+	pxor	%xmm11,%xmm12
+	movdqu	%xmm12,32 + 0(%rdi)
+	movdqu	48 + 0(%rsi),%xmm12
+	pxor	%xmm15,%xmm12
+	movdqu	%xmm12,48 + 0(%rdi)
+	movdqu	0 + 64(%rsi),%xmm3
+	movdqu	16 + 64(%rsi),%xmm7
+	movdqu	32 + 64(%rsi),%xmm11
+	movdqu	48 + 64(%rsi),%xmm15
+	pxor	%xmm3,%xmm2
+	pxor	%xmm7,%xmm6
+	pxor	%xmm11,%xmm10
+	pxor	%xmm14,%xmm15
+	movdqu	%xmm2,0 + 64(%rdi)
+	movdqu	%xmm6,16 + 64(%rdi)
+	movdqu	%xmm10,32 + 64(%rdi)
+	movdqu	%xmm15,48 + 64(%rdi)
+	movdqu	0 + 128(%rsi),%xmm3
+	movdqu	16 + 128(%rsi),%xmm7
+	movdqu	32 + 128(%rsi),%xmm11
+	movdqu	48 + 128(%rsi),%xmm15
+	pxor	%xmm3,%xmm1
+	pxor	%xmm7,%xmm5
+	pxor	%xmm11,%xmm9
+	pxor	%xmm13,%xmm15
+	movdqu	%xmm1,0 + 128(%rdi)
+	movdqu	%xmm5,16 + 128(%rdi)
+	movdqu	%xmm9,32 + 128(%rdi)
+	movdqu	%xmm15,48 + 128(%rdi)
+	movdqu	0 + 192(%rsi),%xmm3
+	movdqu	16 + 192(%rsi),%xmm7
+	movdqu	32 + 192(%rsi),%xmm11
+	movdqu	48 + 192(%rsi),%xmm15
+	pxor	%xmm3,%xmm0
+	pxor	%xmm7,%xmm4
+	pxor	%xmm11,%xmm8
+	pxor	80(%rbp),%xmm15
+	movdqu	%xmm0,0 + 192(%rdi)
+	movdqu	%xmm4,16 + 192(%rdi)
+	movdqu	%xmm8,32 + 192(%rdi)
+	movdqu	%xmm15,48 + 192(%rdi)
+
+	leaq	256(%rsi),%rsi
+	leaq	256(%rdi),%rdi
+	subq	$256,%rbx
+	jmp	open_sse_main_loop
+2:
+
+	testq	%rbx,%rbx
+	jz	open_sse_finalize
+	cmpq	$64,%rbx
+	ja	3f
+	movdqa	.chacha20_consts(%rip),%xmm0
+	movdqa	48(%rbp),%xmm4
+	movdqa	64(%rbp),%xmm8
+	movdqa	96(%rbp),%xmm12
+	paddd	.sse_inc(%rip),%xmm12
+	movdqa	%xmm12,96(%rbp)
+
+	xorq	%r8,%r8
+	movq	%rbx,%rcx
+	cmpq	$16,%rcx
+	jb	2f
+1:
+	addq	0(%rsi,%r8), %r10
+	adcq	8+0(%rsi,%r8), %r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	subq	$16,%rcx
+2:
+	addq	$16,%r8
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,4
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,12
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,12
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,4
+
+	cmpq	$16,%rcx
+	jae	1b
+	cmpq	$160,%r8
+	jne	2b
+	paddd	.chacha20_consts(%rip),%xmm0
+	paddd	48(%rbp),%xmm4
+	paddd	64(%rbp),%xmm8
+	paddd	96(%rbp),%xmm12
+
+	jmp	open_sse_tail_64_dec_loop
+3:
+	cmpq	$128,%rbx
+	ja	3f
+	movdqa	.chacha20_consts(%rip),%xmm0
+	movdqa	48(%rbp),%xmm4
+	movdqa	64(%rbp),%xmm8
+	movdqa	%xmm0,%xmm1
+	movdqa	%xmm4,%xmm5
+	movdqa	%xmm8,%xmm9
+	movdqa	96(%rbp),%xmm13
+	paddd	.sse_inc(%rip),%xmm13
+	movdqa	%xmm13,%xmm12
+	paddd	.sse_inc(%rip),%xmm12
+	movdqa	%xmm12,96(%rbp)
+	movdqa	%xmm13,112(%rbp)
+
+	movq	%rbx,%rcx
+	andq	$-16,%rcx
+	xorq	%r8,%r8
+1:
+	addq	0(%rsi,%r8), %r10
+	adcq	8+0(%rsi,%r8), %r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+2:
+	addq	$16,%r8
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,4
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,12
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol16(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm5
+	pxor	%xmm3,%xmm5
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol8(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm5
+	pxor	%xmm3,%xmm5
+.byte	102,15,58,15,237,4
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,12
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,12
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,4
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol16(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm5
+	pxor	%xmm3,%xmm5
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol8(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm5
+	pxor	%xmm3,%xmm5
+.byte	102,15,58,15,237,12
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,4
+
+	cmpq	%rcx,%r8
+	jb	1b
+	cmpq	$160,%r8
+	jne	2b
+	paddd	.chacha20_consts(%rip),%xmm1
+	paddd	48(%rbp),%xmm5
+	paddd	64(%rbp),%xmm9
+	paddd	112(%rbp),%xmm13
+	paddd	.chacha20_consts(%rip),%xmm0
+	paddd	48(%rbp),%xmm4
+	paddd	64(%rbp),%xmm8
+	paddd	96(%rbp),%xmm12
+	movdqu	0 + 0(%rsi),%xmm3
+	movdqu	16 + 0(%rsi),%xmm7
+	movdqu	32 + 0(%rsi),%xmm11
+	movdqu	48 + 0(%rsi),%xmm15
+	pxor	%xmm3,%xmm1
+	pxor	%xmm7,%xmm5
+	pxor	%xmm11,%xmm9
+	pxor	%xmm13,%xmm15
+	movdqu	%xmm1,0 + 0(%rdi)
+	movdqu	%xmm5,16 + 0(%rdi)
+	movdqu	%xmm9,32 + 0(%rdi)
+	movdqu	%xmm15,48 + 0(%rdi)
+
+	subq	$64,%rbx
+	leaq	64(%rsi),%rsi
+	leaq	64(%rdi),%rdi
+	jmp	open_sse_tail_64_dec_loop
+3:
+	cmpq	$192,%rbx
+	ja	3f
+	movdqa	.chacha20_consts(%rip),%xmm0
+	movdqa	48(%rbp),%xmm4
+	movdqa	64(%rbp),%xmm8
+	movdqa	%xmm0,%xmm1
+	movdqa	%xmm4,%xmm5
+	movdqa	%xmm8,%xmm9
+	movdqa	%xmm0,%xmm2
+	movdqa	%xmm4,%xmm6
+	movdqa	%xmm8,%xmm10
+	movdqa	96(%rbp),%xmm14
+	paddd	.sse_inc(%rip),%xmm14
+	movdqa	%xmm14,%xmm13
+	paddd	.sse_inc(%rip),%xmm13
+	movdqa	%xmm13,%xmm12
+	paddd	.sse_inc(%rip),%xmm12
+	movdqa	%xmm12,96(%rbp)
+	movdqa	%xmm13,112(%rbp)
+	movdqa	%xmm14,128(%rbp)
+
+	movq	%rbx,%rcx
+	movq	$160,%r8
+	cmpq	$160,%rcx
+	cmovgq	%r8,%rcx
+	andq	$-16,%rcx
+	xorq	%r8,%r8
+1:
+	addq	0(%rsi,%r8), %r10
+	adcq	8+0(%rsi,%r8), %r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+2:
+	addq	$16,%r8
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,4
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,12
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol16(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm5
+	pxor	%xmm3,%xmm5
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol8(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm5
+	pxor	%xmm3,%xmm5
+.byte	102,15,58,15,237,4
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,12
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol16(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm6
+	pxor	%xmm3,%xmm6
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol8(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm6
+	pxor	%xmm3,%xmm6
+.byte	102,15,58,15,246,4
+.byte	102,69,15,58,15,210,8
+.byte	102,69,15,58,15,246,12
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,12
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,4
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol16(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm5
+	pxor	%xmm3,%xmm5
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol8(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm5
+	pxor	%xmm3,%xmm5
+.byte	102,15,58,15,237,12
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,4
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol16(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm6
+	pxor	%xmm3,%xmm6
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol8(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm6
+	pxor	%xmm3,%xmm6
+.byte	102,15,58,15,246,12
+.byte	102,69,15,58,15,210,8
+.byte	102,69,15,58,15,246,4
+
+	cmpq	%rcx,%r8
+	jb	1b
+	cmpq	$160,%r8
+	jne	2b
+	cmpq	$176,%rbx
+	jb	1f
+	addq	160(%rsi),%r10
+	adcq	8+160(%rsi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	cmpq	$192,%rbx
+	jb	1f
+	addq	176(%rsi),%r10
+	adcq	8+176(%rsi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+1:
+	paddd	.chacha20_consts(%rip),%xmm2
+	paddd	48(%rbp),%xmm6
+	paddd	64(%rbp),%xmm10
+	paddd	128(%rbp),%xmm14
+	paddd	.chacha20_consts(%rip),%xmm1
+	paddd	48(%rbp),%xmm5
+	paddd	64(%rbp),%xmm9
+	paddd	112(%rbp),%xmm13
+	paddd	.chacha20_consts(%rip),%xmm0
+	paddd	48(%rbp),%xmm4
+	paddd	64(%rbp),%xmm8
+	paddd	96(%rbp),%xmm12
+	movdqu	0 + 0(%rsi),%xmm3
+	movdqu	16 + 0(%rsi),%xmm7
+	movdqu	32 + 0(%rsi),%xmm11
+	movdqu	48 + 0(%rsi),%xmm15
+	pxor	%xmm3,%xmm2
+	pxor	%xmm7,%xmm6
+	pxor	%xmm11,%xmm10
+	pxor	%xmm14,%xmm15
+	movdqu	%xmm2,0 + 0(%rdi)
+	movdqu	%xmm6,16 + 0(%rdi)
+	movdqu	%xmm10,32 + 0(%rdi)
+	movdqu	%xmm15,48 + 0(%rdi)
+	movdqu	0 + 64(%rsi),%xmm3
+	movdqu	16 + 64(%rsi),%xmm7
+	movdqu	32 + 64(%rsi),%xmm11
+	movdqu	48 + 64(%rsi),%xmm15
+	pxor	%xmm3,%xmm1
+	pxor	%xmm7,%xmm5
+	pxor	%xmm11,%xmm9
+	pxor	%xmm13,%xmm15
+	movdqu	%xmm1,0 + 64(%rdi)
+	movdqu	%xmm5,16 + 64(%rdi)
+	movdqu	%xmm9,32 + 64(%rdi)
+	movdqu	%xmm15,48 + 64(%rdi)
+
+	subq	$128,%rbx
+	leaq	128(%rsi),%rsi
+	leaq	128(%rdi),%rdi
+	jmp	open_sse_tail_64_dec_loop
+3:
+
+	movdqa	.chacha20_consts(%rip),%xmm0
+	movdqa	48(%rbp),%xmm4
+	movdqa	64(%rbp),%xmm8
+	movdqa	%xmm0,%xmm1
+	movdqa	%xmm4,%xmm5
+	movdqa	%xmm8,%xmm9
+	movdqa	%xmm0,%xmm2
+	movdqa	%xmm4,%xmm6
+	movdqa	%xmm8,%xmm10
+	movdqa	%xmm0,%xmm3
+	movdqa	%xmm4,%xmm7
+	movdqa	%xmm8,%xmm11
+	movdqa	96(%rbp),%xmm15
+	paddd	.sse_inc(%rip),%xmm15
+	movdqa	%xmm15,%xmm14
+	paddd	.sse_inc(%rip),%xmm14
+	movdqa	%xmm14,%xmm13
+	paddd	.sse_inc(%rip),%xmm13
+	movdqa	%xmm13,%xmm12
+	paddd	.sse_inc(%rip),%xmm12
+	movdqa	%xmm12,96(%rbp)
+	movdqa	%xmm13,112(%rbp)
+	movdqa	%xmm14,128(%rbp)
+	movdqa	%xmm15,144(%rbp)
+
+	xorq	%r8,%r8
+1:
+	addq	0(%rsi,%r8), %r10
+	adcq	8+0(%rsi,%r8), %r11
+	adcq	$1,%r12
+	movdqa	%xmm11,80(%rbp)
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm11
+	pslld	$12,%xmm11
+	psrld	$20,%xmm4
+	pxor	%xmm11,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm11
+	pslld	$7,%xmm11
+	psrld	$25,%xmm4
+	pxor	%xmm11,%xmm4
+.byte	102,15,58,15,228,4
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,12
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol16(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm11
+	pslld	$12,%xmm11
+	psrld	$20,%xmm5
+	pxor	%xmm11,%xmm5
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol8(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm11
+	pslld	$7,%xmm11
+	psrld	$25,%xmm5
+	pxor	%xmm11,%xmm5
+.byte	102,15,58,15,237,4
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,12
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol16(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm11
+	pslld	$12,%xmm11
+	psrld	$20,%xmm6
+	pxor	%xmm11,%xmm6
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol8(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm11
+	pslld	$7,%xmm11
+	psrld	$25,%xmm6
+	pxor	%xmm11,%xmm6
+.byte	102,15,58,15,246,4
+.byte	102,69,15,58,15,210,8
+.byte	102,69,15,58,15,246,12
+	movdqa	80(%rbp),%xmm11
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movdqa	%xmm9,80(%rbp)
+	paddd	%xmm7,%xmm3
+	pxor	%xmm3,%xmm15
+	pshufb	.rol16(%rip),%xmm15
+	paddd	%xmm15,%xmm11
+	pxor	%xmm11,%xmm7
+	movdqa	%xmm7,%xmm9
+	pslld	$12,%xmm9
+	psrld	$20,%xmm7
+	pxor	%xmm9,%xmm7
+	paddd	%xmm7,%xmm3
+	pxor	%xmm3,%xmm15
+	pshufb	.rol8(%rip),%xmm15
+	paddd	%xmm15,%xmm11
+	pxor	%xmm11,%xmm7
+	movdqa	%xmm7,%xmm9
+	pslld	$7,%xmm9
+	psrld	$25,%xmm7
+	pxor	%xmm9,%xmm7
+.byte	102,15,58,15,255,4
+.byte	102,69,15,58,15,219,8
+.byte	102,69,15,58,15,255,12
+	movdqa	80(%rbp),%xmm9
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	movdqa	%xmm11,80(%rbp)
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm11
+	pslld	$12,%xmm11
+	psrld	$20,%xmm4
+	pxor	%xmm11,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm11
+	pslld	$7,%xmm11
+	psrld	$25,%xmm4
+	pxor	%xmm11,%xmm4
+.byte	102,15,58,15,228,12
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,4
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol16(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm11
+	pslld	$12,%xmm11
+	psrld	$20,%xmm5
+	pxor	%xmm11,%xmm5
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol8(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm11
+	pslld	$7,%xmm11
+	psrld	$25,%xmm5
+	pxor	%xmm11,%xmm5
+.byte	102,15,58,15,237,12
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,4
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol16(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm11
+	pslld	$12,%xmm11
+	psrld	$20,%xmm6
+	pxor	%xmm11,%xmm6
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol8(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm11
+	pslld	$7,%xmm11
+	psrld	$25,%xmm6
+	pxor	%xmm11,%xmm6
+.byte	102,15,58,15,246,12
+.byte	102,69,15,58,15,210,8
+.byte	102,69,15,58,15,246,4
+	movdqa	80(%rbp),%xmm11
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	movdqa	%xmm9,80(%rbp)
+	paddd	%xmm7,%xmm3
+	pxor	%xmm3,%xmm15
+	pshufb	.rol16(%rip),%xmm15
+	paddd	%xmm15,%xmm11
+	pxor	%xmm11,%xmm7
+	movdqa	%xmm7,%xmm9
+	pslld	$12,%xmm9
+	psrld	$20,%xmm7
+	pxor	%xmm9,%xmm7
+	paddd	%xmm7,%xmm3
+	pxor	%xmm3,%xmm15
+	pshufb	.rol8(%rip),%xmm15
+	paddd	%xmm15,%xmm11
+	pxor	%xmm11,%xmm7
+	movdqa	%xmm7,%xmm9
+	pslld	$7,%xmm9
+	psrld	$25,%xmm7
+	pxor	%xmm9,%xmm7
+.byte	102,15,58,15,255,12
+.byte	102,69,15,58,15,219,8
+.byte	102,69,15,58,15,255,4
+	movdqa	80(%rbp),%xmm9
+
+	addq	$16,%r8
+	cmpq	$160,%r8
+	jb	1b
+	movq	%rbx,%rcx
+	andq	$-16,%rcx
+1:
+	addq	0(%rsi,%r8), %r10
+	adcq	8+0(%rsi,%r8), %r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	addq	$16,%r8
+	cmpq	%rcx,%r8
+	jb	1b
+	paddd	.chacha20_consts(%rip),%xmm3
+	paddd	48(%rbp),%xmm7
+	paddd	64(%rbp),%xmm11
+	paddd	144(%rbp),%xmm15
+	paddd	.chacha20_consts(%rip),%xmm2
+	paddd	48(%rbp),%xmm6
+	paddd	64(%rbp),%xmm10
+	paddd	128(%rbp),%xmm14
+	paddd	.chacha20_consts(%rip),%xmm1
+	paddd	48(%rbp),%xmm5
+	paddd	64(%rbp),%xmm9
+	paddd	112(%rbp),%xmm13
+	paddd	.chacha20_consts(%rip),%xmm0
+	paddd	48(%rbp),%xmm4
+	paddd	64(%rbp),%xmm8
+	paddd	96(%rbp),%xmm12
+	movdqa	%xmm12,80(%rbp)
+	movdqu	0 + 0(%rsi),%xmm12
+	pxor	%xmm3,%xmm12
+	movdqu	%xmm12,0 + 0(%rdi)
+	movdqu	16 + 0(%rsi),%xmm12
+	pxor	%xmm7,%xmm12
+	movdqu	%xmm12,16 + 0(%rdi)
+	movdqu	32 + 0(%rsi),%xmm12
+	pxor	%xmm11,%xmm12
+	movdqu	%xmm12,32 + 0(%rdi)
+	movdqu	48 + 0(%rsi),%xmm12
+	pxor	%xmm15,%xmm12
+	movdqu	%xmm12,48 + 0(%rdi)
+	movdqu	0 + 64(%rsi),%xmm3
+	movdqu	16 + 64(%rsi),%xmm7
+	movdqu	32 + 64(%rsi),%xmm11
+	movdqu	48 + 64(%rsi),%xmm15
+	pxor	%xmm3,%xmm2
+	pxor	%xmm7,%xmm6
+	pxor	%xmm11,%xmm10
+	pxor	%xmm14,%xmm15
+	movdqu	%xmm2,0 + 64(%rdi)
+	movdqu	%xmm6,16 + 64(%rdi)
+	movdqu	%xmm10,32 + 64(%rdi)
+	movdqu	%xmm15,48 + 64(%rdi)
+	movdqu	0 + 128(%rsi),%xmm3
+	movdqu	16 + 128(%rsi),%xmm7
+	movdqu	32 + 128(%rsi),%xmm11
+	movdqu	48 + 128(%rsi),%xmm15
+	pxor	%xmm3,%xmm1
+	pxor	%xmm7,%xmm5
+	pxor	%xmm11,%xmm9
+	pxor	%xmm13,%xmm15
+	movdqu	%xmm1,0 + 128(%rdi)
+	movdqu	%xmm5,16 + 128(%rdi)
+	movdqu	%xmm9,32 + 128(%rdi)
+	movdqu	%xmm15,48 + 128(%rdi)
+
+	movdqa	80(%rbp),%xmm12
+	subq	$192,%rbx
+	leaq	192(%rsi),%rsi
+	leaq	192(%rdi),%rdi
+
+
+open_sse_tail_64_dec_loop:
+	cmpq	$16,%rbx
+	jb	1f
+	subq	$16,%rbx
+	movdqu	(%rsi),%xmm3
+	pxor	%xmm3,%xmm0
+	movdqu	%xmm0,(%rdi)
+	leaq	16(%rsi),%rsi
+	leaq	16(%rdi),%rdi
+	movdqa	%xmm4,%xmm0
+	movdqa	%xmm8,%xmm4
+	movdqa	%xmm12,%xmm8
+	jmp	open_sse_tail_64_dec_loop
+1:
+	movdqa	%xmm0,%xmm1
+
+
+open_sse_tail_16:
+	testq	%rbx,%rbx
+	jz	open_sse_finalize
+
+
+
+	pxor	%xmm3,%xmm3
+	leaq	-1(%rsi,%rbx), %rsi
+	movq	%rbx,%r8
+2:
+	pslldq	$1,%xmm3
+	pinsrb	$0,(%rsi),%xmm3
+	subq	$1,%rsi
+	subq	$1,%r8
+	jnz	2b
+
+3:
+.byte	102,73,15,126,221
+	pextrq	$1,%xmm3,%r14
+
+	pxor	%xmm1,%xmm3
+
+
+2:
+	pextrb	$0,%xmm3,(%rdi)
+	psrldq	$1,%xmm3
+	addq	$1,%rdi
+	subq	$1,%rbx
+	jne	2b
+
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+
+open_sse_finalize:
+	addq	32(%rbp),%r10
+	adcq	8+32(%rbp),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+
+	movq	%r10,%r13
+	movq	%r11,%r14
+	movq	%r12,%r15
+	subq	$-5,%r10
+	sbbq	$-1,%r11
+	sbbq	$3,%r12
+	cmovcq	%r13,%r10
+	cmovcq	%r14,%r11
+	cmovcq	%r15,%r12
+
+	addq	0+16(%rbp),%r10
+	adcq	8+16(%rbp),%r11
+
+	addq	$288 + 32,%rsp
+.cfi_adjust_cfa_offset	-(288 + 32)
+	popq	%r9
+.cfi_adjust_cfa_offset	-8
+	movq	%r10,(%r9)
+	movq	%r11,8(%r9)
+
+	popq	%r15
+.cfi_adjust_cfa_offset	-8
+	popq	%r14
+.cfi_adjust_cfa_offset	-8
+	popq	%r13
+.cfi_adjust_cfa_offset	-8
+	popq	%r12
+.cfi_adjust_cfa_offset	-8
+	popq	%rbx
+.cfi_adjust_cfa_offset	-8
+	popq	%rbp
+.cfi_adjust_cfa_offset	-8
+	.byte	0xf3,0xc3
+.cfi_adjust_cfa_offset	(8 * 6) + 288 + 32
+
+open_sse_128:
+	movdqu	.chacha20_consts(%rip),%xmm0
+	movdqa	%xmm0,%xmm1
+	movdqa	%xmm0,%xmm2
+	movdqu	0(%r9),%xmm4
+	movdqa	%xmm4,%xmm5
+	movdqa	%xmm4,%xmm6
+	movdqu	16(%r9),%xmm8
+	movdqa	%xmm8,%xmm9
+	movdqa	%xmm8,%xmm10
+	movdqu	32(%r9),%xmm12
+	movdqa	%xmm12,%xmm13
+	paddd	.sse_inc(%rip),%xmm13
+	movdqa	%xmm13,%xmm14
+	paddd	.sse_inc(%rip),%xmm14
+	movdqa	%xmm4,%xmm7
+	movdqa	%xmm8,%xmm11
+	movdqa	%xmm13,%xmm15
+	movq	$10,%r10
+1:
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,4
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,12
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol16(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm5
+	pxor	%xmm3,%xmm5
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol8(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm5
+	pxor	%xmm3,%xmm5
+.byte	102,15,58,15,237,4
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,12
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol16(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm6
+	pxor	%xmm3,%xmm6
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol8(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm6
+	pxor	%xmm3,%xmm6
+.byte	102,15,58,15,246,4
+.byte	102,69,15,58,15,210,8
+.byte	102,69,15,58,15,246,12
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,12
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,4
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol16(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm5
+	pxor	%xmm3,%xmm5
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol8(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm5
+	pxor	%xmm3,%xmm5
+.byte	102,15,58,15,237,12
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,4
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol16(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm6
+	pxor	%xmm3,%xmm6
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol8(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm6
+	pxor	%xmm3,%xmm6
+.byte	102,15,58,15,246,12
+.byte	102,69,15,58,15,210,8
+.byte	102,69,15,58,15,246,4
+
+	decq	%r10
+	jnz	1b
+	paddd	.chacha20_consts(%rip),%xmm0
+	paddd	.chacha20_consts(%rip),%xmm1
+	paddd	.chacha20_consts(%rip),%xmm2
+	paddd	%xmm7,%xmm4
+	paddd	%xmm7,%xmm5
+	paddd	%xmm7,%xmm6
+	paddd	%xmm11,%xmm9
+	paddd	%xmm11,%xmm10
+	paddd	%xmm15,%xmm13
+	paddd	.sse_inc(%rip),%xmm15
+	paddd	%xmm15,%xmm14
+
+	pand	.clamp(%rip),%xmm0
+	movdqa	%xmm0,0(%rbp)
+	movdqa	%xmm4,16(%rbp)
+
+	movq	%r8,%r8
+	call	poly_hash_ad_internal
+1:
+	cmpq	$16,%rbx
+	jb	open_sse_tail_16
+	subq	$16,%rbx
+	addq	0(%rsi),%r10
+	adcq	8+0(%rsi),%r11
+	adcq	$1,%r12
+
+
+	movdqu	0(%rsi),%xmm3
+	pxor	%xmm3,%xmm1
+	movdqu	%xmm1,0(%rdi)
+	leaq	16(%rsi),%rsi
+	leaq	16(%rdi),%rdi
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+
+	movdqa	%xmm5,%xmm1
+	movdqa	%xmm9,%xmm5
+	movdqa	%xmm13,%xmm9
+	movdqa	%xmm2,%xmm13
+	movdqa	%xmm6,%xmm2
+	movdqa	%xmm10,%xmm6
+	movdqa	%xmm14,%xmm10
+	jmp	1b
+	jmp	open_sse_tail_16
+.size	chacha20_poly1305_open, .-chacha20_poly1305_open
+.cfi_endproc	
+
+
+
+
+.globl	chacha20_poly1305_seal
+.hidden chacha20_poly1305_seal
+.type	chacha20_poly1305_seal,@function
+.align	64
+chacha20_poly1305_seal:
+.cfi_startproc	
+	pushq	%rbp
+.cfi_adjust_cfa_offset	8
+	pushq	%rbx
+.cfi_adjust_cfa_offset	8
+	pushq	%r12
+.cfi_adjust_cfa_offset	8
+	pushq	%r13
+.cfi_adjust_cfa_offset	8
+	pushq	%r14
+.cfi_adjust_cfa_offset	8
+	pushq	%r15
+.cfi_adjust_cfa_offset	8
+
+
+	pushq	%r9
+.cfi_adjust_cfa_offset	8
+	subq	$288 + 32,%rsp
+.cfi_adjust_cfa_offset	288 + 32
+.cfi_offset	rbp, -16
+.cfi_offset	rbx, -24
+.cfi_offset	r12, -32
+.cfi_offset	r13, -40
+.cfi_offset	r14, -48
+.cfi_offset	r15, -56
+	leaq	32(%rsp),%rbp
+	andq	$-32,%rbp
+	movq	%rdx,8+32(%rbp)
+	movq	%r8,0+32(%rbp)
+	movq	%rdx,%rbx
+
+	movl	OPENSSL_ia32cap_P+8(%rip),%eax
+	andl	$288,%eax
+	xorl	$288,%eax
+	jz	chacha20_poly1305_seal_avx2
+
+	cmpq	$128,%rbx
+	jbe	seal_sse_128
+
+	movdqa	.chacha20_consts(%rip),%xmm0
+	movdqu	0(%r9),%xmm4
+	movdqu	16(%r9),%xmm8
+	movdqu	32(%r9),%xmm12
+	movdqa	%xmm0,%xmm1
+	movdqa	%xmm0,%xmm2
+	movdqa	%xmm0,%xmm3
+	movdqa	%xmm4,%xmm5
+	movdqa	%xmm4,%xmm6
+	movdqa	%xmm4,%xmm7
+	movdqa	%xmm8,%xmm9
+	movdqa	%xmm8,%xmm10
+	movdqa	%xmm8,%xmm11
+	movdqa	%xmm12,%xmm15
+	paddd	.sse_inc(%rip),%xmm12
+	movdqa	%xmm12,%xmm14
+	paddd	.sse_inc(%rip),%xmm12
+	movdqa	%xmm12,%xmm13
+	paddd	.sse_inc(%rip),%xmm12
+
+	movdqa	%xmm4,48(%rbp)
+	movdqa	%xmm8,64(%rbp)
+	movdqa	%xmm12,96(%rbp)
+	movdqa	%xmm13,112(%rbp)
+	movdqa	%xmm14,128(%rbp)
+	movdqa	%xmm15,144(%rbp)
+	movq	$10,%r10
+1:
+	movdqa	%xmm8,80(%rbp)
+	movdqa	.rol16(%rip),%xmm8
+	paddd	%xmm7,%xmm3
+	paddd	%xmm6,%xmm2
+	paddd	%xmm5,%xmm1
+	paddd	%xmm4,%xmm0
+	pxor	%xmm3,%xmm15
+	pxor	%xmm2,%xmm14
+	pxor	%xmm1,%xmm13
+	pxor	%xmm0,%xmm12
+.byte	102,69,15,56,0,248
+.byte	102,69,15,56,0,240
+.byte	102,69,15,56,0,232
+.byte	102,69,15,56,0,224
+	movdqa	80(%rbp),%xmm8
+	paddd	%xmm15,%xmm11
+	paddd	%xmm14,%xmm10
+	paddd	%xmm13,%xmm9
+	paddd	%xmm12,%xmm8
+	pxor	%xmm11,%xmm7
+	pxor	%xmm10,%xmm6
+	pxor	%xmm9,%xmm5
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm8,80(%rbp)
+	movdqa	%xmm7,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm7
+	pxor	%xmm8,%xmm7
+	movdqa	%xmm6,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm6
+	pxor	%xmm8,%xmm6
+	movdqa	%xmm5,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm5
+	pxor	%xmm8,%xmm5
+	movdqa	%xmm4,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm4
+	pxor	%xmm8,%xmm4
+	movdqa	.rol8(%rip),%xmm8
+	paddd	%xmm7,%xmm3
+	paddd	%xmm6,%xmm2
+	paddd	%xmm5,%xmm1
+	paddd	%xmm4,%xmm0
+	pxor	%xmm3,%xmm15
+	pxor	%xmm2,%xmm14
+	pxor	%xmm1,%xmm13
+	pxor	%xmm0,%xmm12
+.byte	102,69,15,56,0,248
+.byte	102,69,15,56,0,240
+.byte	102,69,15,56,0,232
+.byte	102,69,15,56,0,224
+	movdqa	80(%rbp),%xmm8
+	paddd	%xmm15,%xmm11
+	paddd	%xmm14,%xmm10
+	paddd	%xmm13,%xmm9
+	paddd	%xmm12,%xmm8
+	pxor	%xmm11,%xmm7
+	pxor	%xmm10,%xmm6
+	pxor	%xmm9,%xmm5
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm8,80(%rbp)
+	movdqa	%xmm7,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm7
+	pxor	%xmm8,%xmm7
+	movdqa	%xmm6,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm6
+	pxor	%xmm8,%xmm6
+	movdqa	%xmm5,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm5
+	pxor	%xmm8,%xmm5
+	movdqa	%xmm4,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm4
+	pxor	%xmm8,%xmm4
+	movdqa	80(%rbp),%xmm8
+.byte	102,15,58,15,255,4
+.byte	102,69,15,58,15,219,8
+.byte	102,69,15,58,15,255,12
+.byte	102,15,58,15,246,4
+.byte	102,69,15,58,15,210,8
+.byte	102,69,15,58,15,246,12
+.byte	102,15,58,15,237,4
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,12
+.byte	102,15,58,15,228,4
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,12
+	movdqa	%xmm8,80(%rbp)
+	movdqa	.rol16(%rip),%xmm8
+	paddd	%xmm7,%xmm3
+	paddd	%xmm6,%xmm2
+	paddd	%xmm5,%xmm1
+	paddd	%xmm4,%xmm0
+	pxor	%xmm3,%xmm15
+	pxor	%xmm2,%xmm14
+	pxor	%xmm1,%xmm13
+	pxor	%xmm0,%xmm12
+.byte	102,69,15,56,0,248
+.byte	102,69,15,56,0,240
+.byte	102,69,15,56,0,232
+.byte	102,69,15,56,0,224
+	movdqa	80(%rbp),%xmm8
+	paddd	%xmm15,%xmm11
+	paddd	%xmm14,%xmm10
+	paddd	%xmm13,%xmm9
+	paddd	%xmm12,%xmm8
+	pxor	%xmm11,%xmm7
+	pxor	%xmm10,%xmm6
+	pxor	%xmm9,%xmm5
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm8,80(%rbp)
+	movdqa	%xmm7,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm7
+	pxor	%xmm8,%xmm7
+	movdqa	%xmm6,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm6
+	pxor	%xmm8,%xmm6
+	movdqa	%xmm5,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm5
+	pxor	%xmm8,%xmm5
+	movdqa	%xmm4,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm4
+	pxor	%xmm8,%xmm4
+	movdqa	.rol8(%rip),%xmm8
+	paddd	%xmm7,%xmm3
+	paddd	%xmm6,%xmm2
+	paddd	%xmm5,%xmm1
+	paddd	%xmm4,%xmm0
+	pxor	%xmm3,%xmm15
+	pxor	%xmm2,%xmm14
+	pxor	%xmm1,%xmm13
+	pxor	%xmm0,%xmm12
+.byte	102,69,15,56,0,248
+.byte	102,69,15,56,0,240
+.byte	102,69,15,56,0,232
+.byte	102,69,15,56,0,224
+	movdqa	80(%rbp),%xmm8
+	paddd	%xmm15,%xmm11
+	paddd	%xmm14,%xmm10
+	paddd	%xmm13,%xmm9
+	paddd	%xmm12,%xmm8
+	pxor	%xmm11,%xmm7
+	pxor	%xmm10,%xmm6
+	pxor	%xmm9,%xmm5
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm8,80(%rbp)
+	movdqa	%xmm7,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm7
+	pxor	%xmm8,%xmm7
+	movdqa	%xmm6,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm6
+	pxor	%xmm8,%xmm6
+	movdqa	%xmm5,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm5
+	pxor	%xmm8,%xmm5
+	movdqa	%xmm4,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm4
+	pxor	%xmm8,%xmm4
+	movdqa	80(%rbp),%xmm8
+.byte	102,15,58,15,255,12
+.byte	102,69,15,58,15,219,8
+.byte	102,69,15,58,15,255,4
+.byte	102,15,58,15,246,12
+.byte	102,69,15,58,15,210,8
+.byte	102,69,15,58,15,246,4
+.byte	102,15,58,15,237,12
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,4
+.byte	102,15,58,15,228,12
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,4
+
+	decq	%r10
+	jnz	1b
+	paddd	.chacha20_consts(%rip),%xmm3
+	paddd	48(%rbp),%xmm7
+	paddd	64(%rbp),%xmm11
+	paddd	144(%rbp),%xmm15
+	paddd	.chacha20_consts(%rip),%xmm2
+	paddd	48(%rbp),%xmm6
+	paddd	64(%rbp),%xmm10
+	paddd	128(%rbp),%xmm14
+	paddd	.chacha20_consts(%rip),%xmm1
+	paddd	48(%rbp),%xmm5
+	paddd	64(%rbp),%xmm9
+	paddd	112(%rbp),%xmm13
+	paddd	.chacha20_consts(%rip),%xmm0
+	paddd	48(%rbp),%xmm4
+	paddd	64(%rbp),%xmm8
+	paddd	96(%rbp),%xmm12
+
+
+	pand	.clamp(%rip),%xmm3
+	movdqa	%xmm3,0(%rbp)
+	movdqa	%xmm7,16(%rbp)
+
+	movq	%r8,%r8
+	call	poly_hash_ad_internal
+	movdqu	0 + 0(%rsi),%xmm3
+	movdqu	16 + 0(%rsi),%xmm7
+	movdqu	32 + 0(%rsi),%xmm11
+	movdqu	48 + 0(%rsi),%xmm15
+	pxor	%xmm3,%xmm2
+	pxor	%xmm7,%xmm6
+	pxor	%xmm11,%xmm10
+	pxor	%xmm14,%xmm15
+	movdqu	%xmm2,0 + 0(%rdi)
+	movdqu	%xmm6,16 + 0(%rdi)
+	movdqu	%xmm10,32 + 0(%rdi)
+	movdqu	%xmm15,48 + 0(%rdi)
+	movdqu	0 + 64(%rsi),%xmm3
+	movdqu	16 + 64(%rsi),%xmm7
+	movdqu	32 + 64(%rsi),%xmm11
+	movdqu	48 + 64(%rsi),%xmm15
+	pxor	%xmm3,%xmm1
+	pxor	%xmm7,%xmm5
+	pxor	%xmm11,%xmm9
+	pxor	%xmm13,%xmm15
+	movdqu	%xmm1,0 + 64(%rdi)
+	movdqu	%xmm5,16 + 64(%rdi)
+	movdqu	%xmm9,32 + 64(%rdi)
+	movdqu	%xmm15,48 + 64(%rdi)
+
+	cmpq	$192,%rbx
+	ja	1f
+	movq	$128,%rcx
+	subq	$128,%rbx
+	leaq	128(%rsi),%rsi
+	jmp	seal_sse_128_seal_hash
+1:
+	movdqu	0 + 128(%rsi),%xmm3
+	movdqu	16 + 128(%rsi),%xmm7
+	movdqu	32 + 128(%rsi),%xmm11
+	movdqu	48 + 128(%rsi),%xmm15
+	pxor	%xmm3,%xmm0
+	pxor	%xmm7,%xmm4
+	pxor	%xmm11,%xmm8
+	pxor	%xmm12,%xmm15
+	movdqu	%xmm0,0 + 128(%rdi)
+	movdqu	%xmm4,16 + 128(%rdi)
+	movdqu	%xmm8,32 + 128(%rdi)
+	movdqu	%xmm15,48 + 128(%rdi)
+
+	movq	$192,%rcx
+	subq	$192,%rbx
+	leaq	192(%rsi),%rsi
+	movq	$2,%rcx
+	movq	$8,%r8
+	cmpq	$64,%rbx
+	jbe	seal_sse_tail_64
+	cmpq	$128,%rbx
+	jbe	seal_sse_tail_128
+	cmpq	$192,%rbx
+	jbe	seal_sse_tail_192
+
+1:
+	movdqa	.chacha20_consts(%rip),%xmm0
+	movdqa	48(%rbp),%xmm4
+	movdqa	64(%rbp),%xmm8
+	movdqa	%xmm0,%xmm1
+	movdqa	%xmm4,%xmm5
+	movdqa	%xmm8,%xmm9
+	movdqa	%xmm0,%xmm2
+	movdqa	%xmm4,%xmm6
+	movdqa	%xmm8,%xmm10
+	movdqa	%xmm0,%xmm3
+	movdqa	%xmm4,%xmm7
+	movdqa	%xmm8,%xmm11
+	movdqa	96(%rbp),%xmm15
+	paddd	.sse_inc(%rip),%xmm15
+	movdqa	%xmm15,%xmm14
+	paddd	.sse_inc(%rip),%xmm14
+	movdqa	%xmm14,%xmm13
+	paddd	.sse_inc(%rip),%xmm13
+	movdqa	%xmm13,%xmm12
+	paddd	.sse_inc(%rip),%xmm12
+	movdqa	%xmm12,96(%rbp)
+	movdqa	%xmm13,112(%rbp)
+	movdqa	%xmm14,128(%rbp)
+	movdqa	%xmm15,144(%rbp)
+
+2:
+	movdqa	%xmm8,80(%rbp)
+	movdqa	.rol16(%rip),%xmm8
+	paddd	%xmm7,%xmm3
+	paddd	%xmm6,%xmm2
+	paddd	%xmm5,%xmm1
+	paddd	%xmm4,%xmm0
+	pxor	%xmm3,%xmm15
+	pxor	%xmm2,%xmm14
+	pxor	%xmm1,%xmm13
+	pxor	%xmm0,%xmm12
+.byte	102,69,15,56,0,248
+.byte	102,69,15,56,0,240
+.byte	102,69,15,56,0,232
+.byte	102,69,15,56,0,224
+	movdqa	80(%rbp),%xmm8
+	paddd	%xmm15,%xmm11
+	paddd	%xmm14,%xmm10
+	paddd	%xmm13,%xmm9
+	paddd	%xmm12,%xmm8
+	pxor	%xmm11,%xmm7
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	pxor	%xmm10,%xmm6
+	pxor	%xmm9,%xmm5
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm8,80(%rbp)
+	movdqa	%xmm7,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm7
+	pxor	%xmm8,%xmm7
+	movdqa	%xmm6,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm6
+	pxor	%xmm8,%xmm6
+	movdqa	%xmm5,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm5
+	pxor	%xmm8,%xmm5
+	movdqa	%xmm4,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm4
+	pxor	%xmm8,%xmm4
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movdqa	.rol8(%rip),%xmm8
+	paddd	%xmm7,%xmm3
+	paddd	%xmm6,%xmm2
+	paddd	%xmm5,%xmm1
+	paddd	%xmm4,%xmm0
+	pxor	%xmm3,%xmm15
+	pxor	%xmm2,%xmm14
+	pxor	%xmm1,%xmm13
+	pxor	%xmm0,%xmm12
+.byte	102,69,15,56,0,248
+.byte	102,69,15,56,0,240
+.byte	102,69,15,56,0,232
+.byte	102,69,15,56,0,224
+	movdqa	80(%rbp),%xmm8
+	paddd	%xmm15,%xmm11
+	paddd	%xmm14,%xmm10
+	paddd	%xmm13,%xmm9
+	paddd	%xmm12,%xmm8
+	pxor	%xmm11,%xmm7
+	pxor	%xmm10,%xmm6
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	pxor	%xmm9,%xmm5
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm8,80(%rbp)
+	movdqa	%xmm7,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm7
+	pxor	%xmm8,%xmm7
+	movdqa	%xmm6,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm6
+	pxor	%xmm8,%xmm6
+	movdqa	%xmm5,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm5
+	pxor	%xmm8,%xmm5
+	movdqa	%xmm4,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm4
+	pxor	%xmm8,%xmm4
+	movdqa	80(%rbp),%xmm8
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+.byte	102,15,58,15,255,4
+.byte	102,69,15,58,15,219,8
+.byte	102,69,15,58,15,255,12
+.byte	102,15,58,15,246,4
+.byte	102,69,15,58,15,210,8
+.byte	102,69,15,58,15,246,12
+.byte	102,15,58,15,237,4
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,12
+.byte	102,15,58,15,228,4
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,12
+	movdqa	%xmm8,80(%rbp)
+	movdqa	.rol16(%rip),%xmm8
+	paddd	%xmm7,%xmm3
+	paddd	%xmm6,%xmm2
+	paddd	%xmm5,%xmm1
+	paddd	%xmm4,%xmm0
+	pxor	%xmm3,%xmm15
+	pxor	%xmm2,%xmm14
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	pxor	%xmm1,%xmm13
+	pxor	%xmm0,%xmm12
+.byte	102,69,15,56,0,248
+.byte	102,69,15,56,0,240
+.byte	102,69,15,56,0,232
+.byte	102,69,15,56,0,224
+	movdqa	80(%rbp),%xmm8
+	paddd	%xmm15,%xmm11
+	paddd	%xmm14,%xmm10
+	paddd	%xmm13,%xmm9
+	paddd	%xmm12,%xmm8
+	pxor	%xmm11,%xmm7
+	pxor	%xmm10,%xmm6
+	pxor	%xmm9,%xmm5
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm8,80(%rbp)
+	movdqa	%xmm7,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm7
+	pxor	%xmm8,%xmm7
+	movdqa	%xmm6,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm6
+	pxor	%xmm8,%xmm6
+	movdqa	%xmm5,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm5
+	pxor	%xmm8,%xmm5
+	movdqa	%xmm4,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm4
+	pxor	%xmm8,%xmm4
+	movdqa	.rol8(%rip),%xmm8
+	paddd	%xmm7,%xmm3
+	paddd	%xmm6,%xmm2
+	paddd	%xmm5,%xmm1
+	paddd	%xmm4,%xmm0
+	pxor	%xmm3,%xmm15
+	pxor	%xmm2,%xmm14
+	pxor	%xmm1,%xmm13
+	pxor	%xmm0,%xmm12
+.byte	102,69,15,56,0,248
+.byte	102,69,15,56,0,240
+.byte	102,69,15,56,0,232
+.byte	102,69,15,56,0,224
+	movdqa	80(%rbp),%xmm8
+	paddd	%xmm15,%xmm11
+	paddd	%xmm14,%xmm10
+	paddd	%xmm13,%xmm9
+	paddd	%xmm12,%xmm8
+	pxor	%xmm11,%xmm7
+	pxor	%xmm10,%xmm6
+	pxor	%xmm9,%xmm5
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm8,80(%rbp)
+	movdqa	%xmm7,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm7
+	pxor	%xmm8,%xmm7
+	movdqa	%xmm6,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm6
+	pxor	%xmm8,%xmm6
+	movdqa	%xmm5,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm5
+	pxor	%xmm8,%xmm5
+	movdqa	%xmm4,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm4
+	pxor	%xmm8,%xmm4
+	movdqa	80(%rbp),%xmm8
+.byte	102,15,58,15,255,12
+.byte	102,69,15,58,15,219,8
+.byte	102,69,15,58,15,255,4
+.byte	102,15,58,15,246,12
+.byte	102,69,15,58,15,210,8
+.byte	102,69,15,58,15,246,4
+.byte	102,15,58,15,237,12
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,4
+.byte	102,15,58,15,228,12
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,4
+
+	leaq	16(%rdi),%rdi
+	decq	%r8
+	jge	2b
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%rdi),%rdi
+	decq	%rcx
+	jg	2b
+	paddd	.chacha20_consts(%rip),%xmm3
+	paddd	48(%rbp),%xmm7
+	paddd	64(%rbp),%xmm11
+	paddd	144(%rbp),%xmm15
+	paddd	.chacha20_consts(%rip),%xmm2
+	paddd	48(%rbp),%xmm6
+	paddd	64(%rbp),%xmm10
+	paddd	128(%rbp),%xmm14
+	paddd	.chacha20_consts(%rip),%xmm1
+	paddd	48(%rbp),%xmm5
+	paddd	64(%rbp),%xmm9
+	paddd	112(%rbp),%xmm13
+	paddd	.chacha20_consts(%rip),%xmm0
+	paddd	48(%rbp),%xmm4
+	paddd	64(%rbp),%xmm8
+	paddd	96(%rbp),%xmm12
+
+	movdqa	%xmm14,80(%rbp)
+	movdqa	%xmm14,80(%rbp)
+	movdqu	0 + 0(%rsi),%xmm14
+	pxor	%xmm3,%xmm14
+	movdqu	%xmm14,0 + 0(%rdi)
+	movdqu	16 + 0(%rsi),%xmm14
+	pxor	%xmm7,%xmm14
+	movdqu	%xmm14,16 + 0(%rdi)
+	movdqu	32 + 0(%rsi),%xmm14
+	pxor	%xmm11,%xmm14
+	movdqu	%xmm14,32 + 0(%rdi)
+	movdqu	48 + 0(%rsi),%xmm14
+	pxor	%xmm15,%xmm14
+	movdqu	%xmm14,48 + 0(%rdi)
+
+	movdqa	80(%rbp),%xmm14
+	movdqu	0 + 64(%rsi),%xmm3
+	movdqu	16 + 64(%rsi),%xmm7
+	movdqu	32 + 64(%rsi),%xmm11
+	movdqu	48 + 64(%rsi),%xmm15
+	pxor	%xmm3,%xmm2
+	pxor	%xmm7,%xmm6
+	pxor	%xmm11,%xmm10
+	pxor	%xmm14,%xmm15
+	movdqu	%xmm2,0 + 64(%rdi)
+	movdqu	%xmm6,16 + 64(%rdi)
+	movdqu	%xmm10,32 + 64(%rdi)
+	movdqu	%xmm15,48 + 64(%rdi)
+	movdqu	0 + 128(%rsi),%xmm3
+	movdqu	16 + 128(%rsi),%xmm7
+	movdqu	32 + 128(%rsi),%xmm11
+	movdqu	48 + 128(%rsi),%xmm15
+	pxor	%xmm3,%xmm1
+	pxor	%xmm7,%xmm5
+	pxor	%xmm11,%xmm9
+	pxor	%xmm13,%xmm15
+	movdqu	%xmm1,0 + 128(%rdi)
+	movdqu	%xmm5,16 + 128(%rdi)
+	movdqu	%xmm9,32 + 128(%rdi)
+	movdqu	%xmm15,48 + 128(%rdi)
+
+	cmpq	$256,%rbx
+	ja	3f
+
+	movq	$192,%rcx
+	subq	$192,%rbx
+	leaq	192(%rsi),%rsi
+	jmp	seal_sse_128_seal_hash
+3:
+	movdqu	0 + 192(%rsi),%xmm3
+	movdqu	16 + 192(%rsi),%xmm7
+	movdqu	32 + 192(%rsi),%xmm11
+	movdqu	48 + 192(%rsi),%xmm15
+	pxor	%xmm3,%xmm0
+	pxor	%xmm7,%xmm4
+	pxor	%xmm11,%xmm8
+	pxor	%xmm12,%xmm15
+	movdqu	%xmm0,0 + 192(%rdi)
+	movdqu	%xmm4,16 + 192(%rdi)
+	movdqu	%xmm8,32 + 192(%rdi)
+	movdqu	%xmm15,48 + 192(%rdi)
+
+	leaq	256(%rsi),%rsi
+	subq	$256,%rbx
+	movq	$6,%rcx
+	movq	$4,%r8
+	cmpq	$192,%rbx
+	jg	1b
+	movq	%rbx,%rcx
+	testq	%rbx,%rbx
+	je	seal_sse_128_seal_hash
+	movq	$6,%rcx
+	cmpq	$64,%rbx
+	jg	3f
+
+seal_sse_tail_64:
+	movdqa	.chacha20_consts(%rip),%xmm0
+	movdqa	48(%rbp),%xmm4
+	movdqa	64(%rbp),%xmm8
+	movdqa	96(%rbp),%xmm12
+	paddd	.sse_inc(%rip),%xmm12
+	movdqa	%xmm12,96(%rbp)
+
+1:
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%rdi),%rdi
+2:
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,4
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,12
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,12
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,4
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%rdi),%rdi
+	decq	%rcx
+	jg	1b
+	decq	%r8
+	jge	2b
+	paddd	.chacha20_consts(%rip),%xmm0
+	paddd	48(%rbp),%xmm4
+	paddd	64(%rbp),%xmm8
+	paddd	96(%rbp),%xmm12
+
+	jmp	seal_sse_128_seal
+3:
+	cmpq	$128,%rbx
+	jg	3f
+
+seal_sse_tail_128:
+	movdqa	.chacha20_consts(%rip),%xmm0
+	movdqa	48(%rbp),%xmm4
+	movdqa	64(%rbp),%xmm8
+	movdqa	%xmm0,%xmm1
+	movdqa	%xmm4,%xmm5
+	movdqa	%xmm8,%xmm9
+	movdqa	96(%rbp),%xmm13
+	paddd	.sse_inc(%rip),%xmm13
+	movdqa	%xmm13,%xmm12
+	paddd	.sse_inc(%rip),%xmm12
+	movdqa	%xmm12,96(%rbp)
+	movdqa	%xmm13,112(%rbp)
+
+1:
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%rdi),%rdi
+2:
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,4
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,12
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol16(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm5
+	pxor	%xmm3,%xmm5
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol8(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm5
+	pxor	%xmm3,%xmm5
+.byte	102,15,58,15,237,4
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,12
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,12
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,4
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol16(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm5
+	pxor	%xmm3,%xmm5
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol8(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm5
+	pxor	%xmm3,%xmm5
+.byte	102,15,58,15,237,12
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,4
+
+	leaq	16(%rdi),%rdi
+	decq	%rcx
+	jg	1b
+	decq	%r8
+	jge	2b
+	paddd	.chacha20_consts(%rip),%xmm1
+	paddd	48(%rbp),%xmm5
+	paddd	64(%rbp),%xmm9
+	paddd	112(%rbp),%xmm13
+	paddd	.chacha20_consts(%rip),%xmm0
+	paddd	48(%rbp),%xmm4
+	paddd	64(%rbp),%xmm8
+	paddd	96(%rbp),%xmm12
+	movdqu	0 + 0(%rsi),%xmm3
+	movdqu	16 + 0(%rsi),%xmm7
+	movdqu	32 + 0(%rsi),%xmm11
+	movdqu	48 + 0(%rsi),%xmm15
+	pxor	%xmm3,%xmm1
+	pxor	%xmm7,%xmm5
+	pxor	%xmm11,%xmm9
+	pxor	%xmm13,%xmm15
+	movdqu	%xmm1,0 + 0(%rdi)
+	movdqu	%xmm5,16 + 0(%rdi)
+	movdqu	%xmm9,32 + 0(%rdi)
+	movdqu	%xmm15,48 + 0(%rdi)
+
+	movq	$64,%rcx
+	subq	$64,%rbx
+	leaq	64(%rsi),%rsi
+	jmp	seal_sse_128_seal_hash
+3:
+
+seal_sse_tail_192:
+	movdqa	.chacha20_consts(%rip),%xmm0
+	movdqa	48(%rbp),%xmm4
+	movdqa	64(%rbp),%xmm8
+	movdqa	%xmm0,%xmm1
+	movdqa	%xmm4,%xmm5
+	movdqa	%xmm8,%xmm9
+	movdqa	%xmm0,%xmm2
+	movdqa	%xmm4,%xmm6
+	movdqa	%xmm8,%xmm10
+	movdqa	96(%rbp),%xmm14
+	paddd	.sse_inc(%rip),%xmm14
+	movdqa	%xmm14,%xmm13
+	paddd	.sse_inc(%rip),%xmm13
+	movdqa	%xmm13,%xmm12
+	paddd	.sse_inc(%rip),%xmm12
+	movdqa	%xmm12,96(%rbp)
+	movdqa	%xmm13,112(%rbp)
+	movdqa	%xmm14,128(%rbp)
+
+1:
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%rdi),%rdi
+2:
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,4
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,12
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol16(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm5
+	pxor	%xmm3,%xmm5
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol8(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm5
+	pxor	%xmm3,%xmm5
+.byte	102,15,58,15,237,4
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,12
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol16(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm6
+	pxor	%xmm3,%xmm6
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol8(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm6
+	pxor	%xmm3,%xmm6
+.byte	102,15,58,15,246,4
+.byte	102,69,15,58,15,210,8
+.byte	102,69,15,58,15,246,12
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,12
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,4
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol16(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm5
+	pxor	%xmm3,%xmm5
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol8(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm5
+	pxor	%xmm3,%xmm5
+.byte	102,15,58,15,237,12
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,4
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol16(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm6
+	pxor	%xmm3,%xmm6
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol8(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm6
+	pxor	%xmm3,%xmm6
+.byte	102,15,58,15,246,12
+.byte	102,69,15,58,15,210,8
+.byte	102,69,15,58,15,246,4
+
+	leaq	16(%rdi),%rdi
+	decq	%rcx
+	jg	1b
+	decq	%r8
+	jge	2b
+	paddd	.chacha20_consts(%rip),%xmm2
+	paddd	48(%rbp),%xmm6
+	paddd	64(%rbp),%xmm10
+	paddd	128(%rbp),%xmm14
+	paddd	.chacha20_consts(%rip),%xmm1
+	paddd	48(%rbp),%xmm5
+	paddd	64(%rbp),%xmm9
+	paddd	112(%rbp),%xmm13
+	paddd	.chacha20_consts(%rip),%xmm0
+	paddd	48(%rbp),%xmm4
+	paddd	64(%rbp),%xmm8
+	paddd	96(%rbp),%xmm12
+	movdqu	0 + 0(%rsi),%xmm3
+	movdqu	16 + 0(%rsi),%xmm7
+	movdqu	32 + 0(%rsi),%xmm11
+	movdqu	48 + 0(%rsi),%xmm15
+	pxor	%xmm3,%xmm2
+	pxor	%xmm7,%xmm6
+	pxor	%xmm11,%xmm10
+	pxor	%xmm14,%xmm15
+	movdqu	%xmm2,0 + 0(%rdi)
+	movdqu	%xmm6,16 + 0(%rdi)
+	movdqu	%xmm10,32 + 0(%rdi)
+	movdqu	%xmm15,48 + 0(%rdi)
+	movdqu	0 + 64(%rsi),%xmm3
+	movdqu	16 + 64(%rsi),%xmm7
+	movdqu	32 + 64(%rsi),%xmm11
+	movdqu	48 + 64(%rsi),%xmm15
+	pxor	%xmm3,%xmm1
+	pxor	%xmm7,%xmm5
+	pxor	%xmm11,%xmm9
+	pxor	%xmm13,%xmm15
+	movdqu	%xmm1,0 + 64(%rdi)
+	movdqu	%xmm5,16 + 64(%rdi)
+	movdqu	%xmm9,32 + 64(%rdi)
+	movdqu	%xmm15,48 + 64(%rdi)
+
+	movq	$128,%rcx
+	subq	$128,%rbx
+	leaq	128(%rsi),%rsi
+
+seal_sse_128_seal_hash:
+	cmpq	$16,%rcx
+	jb	seal_sse_128_seal
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	subq	$16,%rcx
+	leaq	16(%rdi),%rdi
+	jmp	seal_sse_128_seal_hash
+
+seal_sse_128_seal:
+	cmpq	$16,%rbx
+	jb	seal_sse_tail_16
+	subq	$16,%rbx
+
+	movdqu	0(%rsi),%xmm3
+	pxor	%xmm3,%xmm0
+	movdqu	%xmm0,0(%rdi)
+
+	addq	0(%rdi),%r10
+	adcq	8(%rdi),%r11
+	adcq	$1,%r12
+	leaq	16(%rsi),%rsi
+	leaq	16(%rdi),%rdi
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+
+	movdqa	%xmm4,%xmm0
+	movdqa	%xmm8,%xmm4
+	movdqa	%xmm12,%xmm8
+	movdqa	%xmm1,%xmm12
+	movdqa	%xmm5,%xmm1
+	movdqa	%xmm9,%xmm5
+	movdqa	%xmm13,%xmm9
+	jmp	seal_sse_128_seal
+
+seal_sse_tail_16:
+	testq	%rbx,%rbx
+	jz	seal_sse_finalize
+
+	movq	%rbx,%r8
+	shlq	$4,%r8
+	leaq	.and_masks(%rip),%r13
+	movq	%rbx,%rcx
+	leaq	-1(%rsi,%rbx), %rsi
+	pxor	%xmm15,%xmm15
+1:
+	pslldq	$1,%xmm15
+	pinsrb	$0,(%rsi),%xmm15
+	leaq	-1(%rsi),%rsi
+	decq	%rcx
+	jne	1b
+
+
+	pxor	%xmm0,%xmm15
+
+
+	movq	%rbx,%rcx
+	movdqu	%xmm15,%xmm0
+2:
+	pextrb	$0,%xmm0,(%rdi)
+	psrldq	$1,%xmm0
+	addq	$1,%rdi
+	subq	$1,%rcx
+	jnz	2b
+
+	pand	-16(%r13,%r8), %xmm15
+.byte	102,77,15,126,253
+	pextrq	$1,%xmm15,%r14
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+seal_sse_finalize:
+	addq	32(%rbp),%r10
+	adcq	8+32(%rbp),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+
+	movq	%r10,%r13
+	movq	%r11,%r14
+	movq	%r12,%r15
+	subq	$-5,%r10
+	sbbq	$-1,%r11
+	sbbq	$3,%r12
+	cmovcq	%r13,%r10
+	cmovcq	%r14,%r11
+	cmovcq	%r15,%r12
+
+	addq	0+16(%rbp),%r10
+	adcq	8+16(%rbp),%r11
+
+	addq	$288 + 32,%rsp
+.cfi_adjust_cfa_offset	-(288 + 32)
+	popq	%r9
+.cfi_adjust_cfa_offset	-8
+	movq	%r10,0(%r9)
+	movq	%r11,8(%r9)
+
+	popq	%r15
+.cfi_adjust_cfa_offset	-8
+	popq	%r14
+.cfi_adjust_cfa_offset	-8
+	popq	%r13
+.cfi_adjust_cfa_offset	-8
+	popq	%r12
+.cfi_adjust_cfa_offset	-8
+	popq	%rbx
+.cfi_adjust_cfa_offset	-8
+	popq	%rbp
+.cfi_adjust_cfa_offset	-8
+	.byte	0xf3,0xc3
+.cfi_adjust_cfa_offset	(8 * 6) + 288 + 32
+
+seal_sse_128:
+	movdqu	.chacha20_consts(%rip),%xmm0
+	movdqa	%xmm0,%xmm1
+	movdqa	%xmm0,%xmm2
+	movdqu	0(%r9),%xmm4
+	movdqa	%xmm4,%xmm5
+	movdqa	%xmm4,%xmm6
+	movdqu	16(%r9),%xmm8
+	movdqa	%xmm8,%xmm9
+	movdqa	%xmm8,%xmm10
+	movdqu	32(%r9),%xmm14
+	movdqa	%xmm14,%xmm12
+	paddd	.sse_inc(%rip),%xmm12
+	movdqa	%xmm12,%xmm13
+	paddd	.sse_inc(%rip),%xmm13
+	movdqa	%xmm4,%xmm7
+	movdqa	%xmm8,%xmm11
+	movdqa	%xmm12,%xmm15
+	movq	$10,%r10
+1:
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,4
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,12
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol16(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm5
+	pxor	%xmm3,%xmm5
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol8(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm5
+	pxor	%xmm3,%xmm5
+.byte	102,15,58,15,237,4
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,12
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol16(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm6
+	pxor	%xmm3,%xmm6
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol8(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm6
+	pxor	%xmm3,%xmm6
+.byte	102,15,58,15,246,4
+.byte	102,69,15,58,15,210,8
+.byte	102,69,15,58,15,246,12
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,12
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,4
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol16(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm5
+	pxor	%xmm3,%xmm5
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol8(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm5
+	pxor	%xmm3,%xmm5
+.byte	102,15,58,15,237,12
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,4
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol16(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm6
+	pxor	%xmm3,%xmm6
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol8(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm6
+	pxor	%xmm3,%xmm6
+.byte	102,15,58,15,246,12
+.byte	102,69,15,58,15,210,8
+.byte	102,69,15,58,15,246,4
+
+	decq	%r10
+	jnz	1b
+	paddd	.chacha20_consts(%rip),%xmm0
+	paddd	.chacha20_consts(%rip),%xmm1
+	paddd	.chacha20_consts(%rip),%xmm2
+	paddd	%xmm7,%xmm4
+	paddd	%xmm7,%xmm5
+	paddd	%xmm7,%xmm6
+	paddd	%xmm11,%xmm8
+	paddd	%xmm11,%xmm9
+	paddd	%xmm15,%xmm12
+	paddd	.sse_inc(%rip),%xmm15
+	paddd	%xmm15,%xmm13
+
+	pand	.clamp(%rip),%xmm2
+	movdqa	%xmm2,0(%rbp)
+	movdqa	%xmm6,16(%rbp)
+
+	movq	%r8,%r8
+	call	poly_hash_ad_internal
+	jmp	seal_sse_128_seal
+.size	chacha20_poly1305_seal, .-chacha20_poly1305_seal
+
+
+.type	chacha20_poly1305_open_avx2,@function
+.align	64
+chacha20_poly1305_open_avx2:
+	vzeroupper
+	vmovdqa	.chacha20_consts(%rip),%ymm0
+	vbroadcasti128	0(%r9),%ymm4
+	vbroadcasti128	16(%r9),%ymm8
+	vbroadcasti128	32(%r9),%ymm12
+	vpaddd	.avx2_init(%rip),%ymm12,%ymm12
+	cmpq	$192,%rbx
+	jbe	open_avx2_192
+	cmpq	$320,%rbx
+	jbe	open_avx2_320
+
+	vmovdqa	%ymm4,64(%rbp)
+	vmovdqa	%ymm8,96(%rbp)
+	vmovdqa	%ymm12,160(%rbp)
+	movq	$10,%r10
+1:
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+
+	decq	%r10
+	jne	1b
+	vpaddd	.chacha20_consts(%rip),%ymm0,%ymm0
+	vpaddd	64(%rbp),%ymm4,%ymm4
+	vpaddd	96(%rbp),%ymm8,%ymm8
+	vpaddd	160(%rbp),%ymm12,%ymm12
+
+	vperm2i128	$0x02,%ymm0,%ymm4,%ymm3
+
+	vpand	.clamp(%rip),%ymm3,%ymm3
+	vmovdqa	%ymm3,0(%rbp)
+
+	vperm2i128	$0x13,%ymm0,%ymm4,%ymm0
+	vperm2i128	$0x13,%ymm8,%ymm12,%ymm4
+
+	movq	%r8,%r8
+	call	poly_hash_ad_internal
+	xorq	%rcx,%rcx
+
+1:
+	addq	0(%rsi,%rcx), %r10
+	adcq	8+0(%rsi,%rcx), %r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	addq	$16,%rcx
+	cmpq	$64,%rcx
+	jne	1b
+
+	vpxor	0(%rsi),%ymm0,%ymm0
+	vpxor	32(%rsi),%ymm4,%ymm4
+	vmovdqu	%ymm0,0(%rdi)
+	vmovdqu	%ymm4,32(%rdi)
+	leaq	64(%rsi),%rsi
+	leaq	64(%rdi),%rdi
+	subq	$64,%rbx
+1:
+
+	cmpq	$512,%rbx
+	jb	3f
+	vmovdqa	.chacha20_consts(%rip),%ymm0
+	vmovdqa	64(%rbp),%ymm4
+	vmovdqa	96(%rbp),%ymm8
+	vmovdqa	%ymm0,%ymm1
+	vmovdqa	%ymm4,%ymm5
+	vmovdqa	%ymm8,%ymm9
+	vmovdqa	%ymm0,%ymm2
+	vmovdqa	%ymm4,%ymm6
+	vmovdqa	%ymm8,%ymm10
+	vmovdqa	%ymm0,%ymm3
+	vmovdqa	%ymm4,%ymm7
+	vmovdqa	%ymm8,%ymm11
+	vmovdqa	.avx2_inc(%rip),%ymm12
+	vpaddd	160(%rbp),%ymm12,%ymm15
+	vpaddd	%ymm15,%ymm12,%ymm14
+	vpaddd	%ymm14,%ymm12,%ymm13
+	vpaddd	%ymm13,%ymm12,%ymm12
+	vmovdqa	%ymm15,256(%rbp)
+	vmovdqa	%ymm14,224(%rbp)
+	vmovdqa	%ymm13,192(%rbp)
+	vmovdqa	%ymm12,160(%rbp)
+
+	xorq	%rcx,%rcx
+2:
+	addq	0*8(%rsi,%rcx), %r10
+	adcq	8+0*8(%rsi,%rcx), %r11
+	adcq	$1,%r12
+	vmovdqa	%ymm8,128(%rbp)
+	vmovdqa	.rol16(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	movq	0+0(%rbp),%rdx
+	movq	%rdx,%r15
+	mulxq	%r10,%r13,%r14
+	mulxq	%r11,%rax,%rdx
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	movq	8+0(%rbp),%rdx
+	mulxq	%r10,%r10,%rax
+	addq	%r10,%r14
+	mulxq	%r11,%r11,%r9
+	adcq	%r11,%r15
+	adcq	$0,%r9
+	imulq	%r12,%rdx
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$20,%ymm7,%ymm8
+	vpslld	$32-20,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$20,%ymm6,%ymm8
+	vpslld	$32-20,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$20,%ymm5,%ymm8
+	addq	%rax,%r15
+	adcq	%rdx,%r9
+	vpslld	$32-20,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$20,%ymm4,%ymm8
+	vpslld	$32-20,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	.rol8(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	addq	2*8(%rsi,%rcx), %r10
+	adcq	8+2*8(%rsi,%rcx), %r11
+	adcq	$1,%r12
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	movq	0+0(%rbp),%rdx
+	movq	%rdx,%r15
+	mulxq	%r10,%r13,%r14
+	mulxq	%r11,%rax,%rdx
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$25,%ymm7,%ymm8
+	vpslld	$32-25,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$25,%ymm6,%ymm8
+	vpslld	$32-25,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$25,%ymm5,%ymm8
+	vpslld	$32-25,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$25,%ymm4,%ymm8
+	vpslld	$32-25,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	128(%rbp),%ymm8
+	vpalignr	$4,%ymm7,%ymm7,%ymm7
+	vpalignr	$8,%ymm11,%ymm11,%ymm11
+	vpalignr	$12,%ymm15,%ymm15,%ymm15
+	vpalignr	$4,%ymm6,%ymm6,%ymm6
+	movq	8+0(%rbp),%rdx
+	mulxq	%r10,%r10,%rax
+	addq	%r10,%r14
+	mulxq	%r11,%r11,%r9
+	adcq	%r11,%r15
+	adcq	$0,%r9
+	imulq	%r12,%rdx
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$12,%ymm14,%ymm14,%ymm14
+	vpalignr	$4,%ymm5,%ymm5,%ymm5
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$12,%ymm13,%ymm13,%ymm13
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vmovdqa	%ymm8,128(%rbp)
+	vmovdqa	.rol16(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	addq	%rax,%r15
+	adcq	%rdx,%r9
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$20,%ymm7,%ymm8
+	vpslld	$32-20,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	addq	4*8(%rsi,%rcx), %r10
+	adcq	8+4*8(%rsi,%rcx), %r11
+	adcq	$1,%r12
+
+	leaq	48(%rcx),%rcx
+	vpsrld	$20,%ymm6,%ymm8
+	vpslld	$32-20,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$20,%ymm5,%ymm8
+	vpslld	$32-20,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$20,%ymm4,%ymm8
+	vpslld	$32-20,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	.rol8(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	movq	0+0(%rbp),%rdx
+	movq	%rdx,%r15
+	mulxq	%r10,%r13,%r14
+	mulxq	%r11,%rax,%rdx
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	movq	8+0(%rbp),%rdx
+	mulxq	%r10,%r10,%rax
+	addq	%r10,%r14
+	mulxq	%r11,%r11,%r9
+	adcq	%r11,%r15
+	adcq	$0,%r9
+	imulq	%r12,%rdx
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$25,%ymm7,%ymm8
+	vpslld	$32-25,%ymm7,%ymm7
+	addq	%rax,%r15
+	adcq	%rdx,%r9
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$25,%ymm6,%ymm8
+	vpslld	$32-25,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$25,%ymm5,%ymm8
+	vpslld	$32-25,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$25,%ymm4,%ymm8
+	vpslld	$32-25,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	128(%rbp),%ymm8
+	vpalignr	$12,%ymm7,%ymm7,%ymm7
+	vpalignr	$8,%ymm11,%ymm11,%ymm11
+	vpalignr	$4,%ymm15,%ymm15,%ymm15
+	vpalignr	$12,%ymm6,%ymm6,%ymm6
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$4,%ymm14,%ymm14,%ymm14
+	vpalignr	$12,%ymm5,%ymm5,%ymm5
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$4,%ymm13,%ymm13,%ymm13
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+
+	cmpq	$60*8,%rcx
+	jne	2b
+	vpaddd	.chacha20_consts(%rip),%ymm3,%ymm3
+	vpaddd	64(%rbp),%ymm7,%ymm7
+	vpaddd	96(%rbp),%ymm11,%ymm11
+	vpaddd	256(%rbp),%ymm15,%ymm15
+	vpaddd	.chacha20_consts(%rip),%ymm2,%ymm2
+	vpaddd	64(%rbp),%ymm6,%ymm6
+	vpaddd	96(%rbp),%ymm10,%ymm10
+	vpaddd	224(%rbp),%ymm14,%ymm14
+	vpaddd	.chacha20_consts(%rip),%ymm1,%ymm1
+	vpaddd	64(%rbp),%ymm5,%ymm5
+	vpaddd	96(%rbp),%ymm9,%ymm9
+	vpaddd	192(%rbp),%ymm13,%ymm13
+	vpaddd	.chacha20_consts(%rip),%ymm0,%ymm0
+	vpaddd	64(%rbp),%ymm4,%ymm4
+	vpaddd	96(%rbp),%ymm8,%ymm8
+	vpaddd	160(%rbp),%ymm12,%ymm12
+
+	vmovdqa	%ymm0,128(%rbp)
+	addq	60*8(%rsi),%r10
+	adcq	8+60*8(%rsi),%r11
+	adcq	$1,%r12
+	vperm2i128	$0x02,%ymm3,%ymm7,%ymm0
+	vperm2i128	$0x13,%ymm3,%ymm7,%ymm7
+	vperm2i128	$0x02,%ymm11,%ymm15,%ymm3
+	vperm2i128	$0x13,%ymm11,%ymm15,%ymm11
+	vpxor	0+0(%rsi),%ymm0,%ymm0
+	vpxor	32+0(%rsi),%ymm3,%ymm3
+	vpxor	64+0(%rsi),%ymm7,%ymm7
+	vpxor	96+0(%rsi),%ymm11,%ymm11
+	vmovdqu	%ymm0,0+0(%rdi)
+	vmovdqu	%ymm3,32+0(%rdi)
+	vmovdqu	%ymm7,64+0(%rdi)
+	vmovdqu	%ymm11,96+0(%rdi)
+
+	vmovdqa	128(%rbp),%ymm0
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	vperm2i128	$0x02,%ymm2,%ymm6,%ymm3
+	vperm2i128	$0x13,%ymm2,%ymm6,%ymm6
+	vperm2i128	$0x02,%ymm10,%ymm14,%ymm2
+	vperm2i128	$0x13,%ymm10,%ymm14,%ymm10
+	vpxor	0+128(%rsi),%ymm3,%ymm3
+	vpxor	32+128(%rsi),%ymm2,%ymm2
+	vpxor	64+128(%rsi),%ymm6,%ymm6
+	vpxor	96+128(%rsi),%ymm10,%ymm10
+	vmovdqu	%ymm3,0+128(%rdi)
+	vmovdqu	%ymm2,32+128(%rdi)
+	vmovdqu	%ymm6,64+128(%rdi)
+	vmovdqu	%ymm10,96+128(%rdi)
+	addq	60*8+16(%rsi),%r10
+	adcq	8+60*8+16(%rsi),%r11
+	adcq	$1,%r12
+	vperm2i128	$0x02,%ymm1,%ymm5,%ymm3
+	vperm2i128	$0x13,%ymm1,%ymm5,%ymm5
+	vperm2i128	$0x02,%ymm9,%ymm13,%ymm1
+	vperm2i128	$0x13,%ymm9,%ymm13,%ymm9
+	vpxor	0+256(%rsi),%ymm3,%ymm3
+	vpxor	32+256(%rsi),%ymm1,%ymm1
+	vpxor	64+256(%rsi),%ymm5,%ymm5
+	vpxor	96+256(%rsi),%ymm9,%ymm9
+	vmovdqu	%ymm3,0+256(%rdi)
+	vmovdqu	%ymm1,32+256(%rdi)
+	vmovdqu	%ymm5,64+256(%rdi)
+	vmovdqu	%ymm9,96+256(%rdi)
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	vperm2i128	$0x02,%ymm0,%ymm4,%ymm3
+	vperm2i128	$0x13,%ymm0,%ymm4,%ymm4
+	vperm2i128	$0x02,%ymm8,%ymm12,%ymm0
+	vperm2i128	$0x13,%ymm8,%ymm12,%ymm8
+	vpxor	0+384(%rsi),%ymm3,%ymm3
+	vpxor	32+384(%rsi),%ymm0,%ymm0
+	vpxor	64+384(%rsi),%ymm4,%ymm4
+	vpxor	96+384(%rsi),%ymm8,%ymm8
+	vmovdqu	%ymm3,0+384(%rdi)
+	vmovdqu	%ymm0,32+384(%rdi)
+	vmovdqu	%ymm4,64+384(%rdi)
+	vmovdqu	%ymm8,96+384(%rdi)
+
+	leaq	512(%rsi),%rsi
+	leaq	512(%rdi),%rdi
+	subq	$512,%rbx
+	jmp	1b
+3:
+	testq	%rbx,%rbx
+	vzeroupper
+	je	open_sse_finalize
+3:
+	cmpq	$128,%rbx
+	ja	3f
+	vmovdqa	.chacha20_consts(%rip),%ymm0
+	vmovdqa	64(%rbp),%ymm4
+	vmovdqa	96(%rbp),%ymm8
+	vmovdqa	.avx2_inc(%rip),%ymm12
+	vpaddd	160(%rbp),%ymm12,%ymm12
+	vmovdqa	%ymm12,160(%rbp)
+
+	xorq	%r8,%r8
+	movq	%rbx,%rcx
+	andq	$-16,%rcx
+	testq	%rcx,%rcx
+	je	2f
+1:
+	addq	0*8(%rsi,%r8), %r10
+	adcq	8+0*8(%rsi,%r8), %r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+2:
+	addq	$16,%r8
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+
+	cmpq	%rcx,%r8
+	jb	1b
+	cmpq	$160,%r8
+	jne	2b
+	vpaddd	.chacha20_consts(%rip),%ymm0,%ymm0
+	vpaddd	64(%rbp),%ymm4,%ymm4
+	vpaddd	96(%rbp),%ymm8,%ymm8
+	vpaddd	160(%rbp),%ymm12,%ymm12
+	vperm2i128	$0x13,%ymm0,%ymm4,%ymm3
+	vperm2i128	$0x02,%ymm0,%ymm4,%ymm0
+	vperm2i128	$0x02,%ymm8,%ymm12,%ymm4
+	vperm2i128	$0x13,%ymm8,%ymm12,%ymm12
+	vmovdqa	%ymm3,%ymm8
+
+	jmp	open_avx2_tail_loop
+3:
+	cmpq	$256,%rbx
+	ja	3f
+	vmovdqa	.chacha20_consts(%rip),%ymm0
+	vmovdqa	64(%rbp),%ymm4
+	vmovdqa	96(%rbp),%ymm8
+	vmovdqa	%ymm0,%ymm1
+	vmovdqa	%ymm4,%ymm5
+	vmovdqa	%ymm8,%ymm9
+	vmovdqa	.avx2_inc(%rip),%ymm12
+	vpaddd	160(%rbp),%ymm12,%ymm13
+	vpaddd	%ymm13,%ymm12,%ymm12
+	vmovdqa	%ymm12,160(%rbp)
+	vmovdqa	%ymm13,192(%rbp)
+
+	movq	%rbx,128(%rbp)
+	movq	%rbx,%rcx
+	subq	$128,%rcx
+	shrq	$4,%rcx
+	movq	$10,%r8
+	cmpq	$10,%rcx
+	cmovgq	%r8,%rcx
+	movq	%rsi,%rbx
+	xorq	%r8,%r8
+1:
+	addq	0(%rbx),%r10
+	adcq	8+0(%rbx),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rdx
+	movq	%rdx,%r15
+	mulxq	%r10,%r13,%r14
+	mulxq	%r11,%rax,%rdx
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rdx
+	mulxq	%r10,%r10,%rax
+	addq	%r10,%r14
+	mulxq	%r11,%r11,%r9
+	adcq	%r11,%r15
+	adcq	$0,%r9
+	imulq	%r12,%rdx
+	addq	%rax,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%rbx),%rbx
+2:
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol16(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpsrld	$20,%ymm5,%ymm3
+	vpslld	$12,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol8(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpslld	$7,%ymm5,%ymm3
+	vpsrld	$25,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpalignr	$12,%ymm13,%ymm13,%ymm13
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$4,%ymm5,%ymm5,%ymm5
+
+	incq	%r8
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol16(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpsrld	$20,%ymm5,%ymm3
+	vpslld	$12,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol8(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpslld	$7,%ymm5,%ymm3
+	vpsrld	$25,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpalignr	$4,%ymm13,%ymm13,%ymm13
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$12,%ymm5,%ymm5,%ymm5
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol16(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpsrld	$20,%ymm6,%ymm3
+	vpslld	$12,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol8(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpslld	$7,%ymm6,%ymm3
+	vpsrld	$25,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpalignr	$4,%ymm14,%ymm14,%ymm14
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$12,%ymm6,%ymm6,%ymm6
+
+	cmpq	%rcx,%r8
+	jb	1b
+	cmpq	$10,%r8
+	jne	2b
+	movq	%rbx,%r8
+	subq	%rsi,%rbx
+	movq	%rbx,%rcx
+	movq	128(%rbp),%rbx
+1:
+	addq	$16,%rcx
+	cmpq	%rbx,%rcx
+	jg	1f
+	addq	0(%r8),%r10
+	adcq	8+0(%r8),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rdx
+	movq	%rdx,%r15
+	mulxq	%r10,%r13,%r14
+	mulxq	%r11,%rax,%rdx
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rdx
+	mulxq	%r10,%r10,%rax
+	addq	%r10,%r14
+	mulxq	%r11,%r11,%r9
+	adcq	%r11,%r15
+	adcq	$0,%r9
+	imulq	%r12,%rdx
+	addq	%rax,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%r8),%r8
+	jmp	1b
+1:
+	vpaddd	.chacha20_consts(%rip),%ymm1,%ymm1
+	vpaddd	64(%rbp),%ymm5,%ymm5
+	vpaddd	96(%rbp),%ymm9,%ymm9
+	vpaddd	192(%rbp),%ymm13,%ymm13
+	vpaddd	.chacha20_consts(%rip),%ymm0,%ymm0
+	vpaddd	64(%rbp),%ymm4,%ymm4
+	vpaddd	96(%rbp),%ymm8,%ymm8
+	vpaddd	160(%rbp),%ymm12,%ymm12
+	vperm2i128	$0x02,%ymm1,%ymm5,%ymm3
+	vperm2i128	$0x13,%ymm1,%ymm5,%ymm5
+	vperm2i128	$0x02,%ymm9,%ymm13,%ymm1
+	vperm2i128	$0x13,%ymm9,%ymm13,%ymm9
+	vpxor	0+0(%rsi),%ymm3,%ymm3
+	vpxor	32+0(%rsi),%ymm1,%ymm1
+	vpxor	64+0(%rsi),%ymm5,%ymm5
+	vpxor	96+0(%rsi),%ymm9,%ymm9
+	vmovdqu	%ymm3,0+0(%rdi)
+	vmovdqu	%ymm1,32+0(%rdi)
+	vmovdqu	%ymm5,64+0(%rdi)
+	vmovdqu	%ymm9,96+0(%rdi)
+	vperm2i128	$0x13,%ymm0,%ymm4,%ymm3
+	vperm2i128	$0x02,%ymm0,%ymm4,%ymm0
+	vperm2i128	$0x02,%ymm8,%ymm12,%ymm4
+	vperm2i128	$0x13,%ymm8,%ymm12,%ymm12
+	vmovdqa	%ymm3,%ymm8
+
+	leaq	128(%rsi),%rsi
+	leaq	128(%rdi),%rdi
+	subq	$128,%rbx
+	jmp	open_avx2_tail_loop
+3:
+	cmpq	$384,%rbx
+	ja	3f
+	vmovdqa	.chacha20_consts(%rip),%ymm0
+	vmovdqa	64(%rbp),%ymm4
+	vmovdqa	96(%rbp),%ymm8
+	vmovdqa	%ymm0,%ymm1
+	vmovdqa	%ymm4,%ymm5
+	vmovdqa	%ymm8,%ymm9
+	vmovdqa	%ymm0,%ymm2
+	vmovdqa	%ymm4,%ymm6
+	vmovdqa	%ymm8,%ymm10
+	vmovdqa	.avx2_inc(%rip),%ymm12
+	vpaddd	160(%rbp),%ymm12,%ymm14
+	vpaddd	%ymm14,%ymm12,%ymm13
+	vpaddd	%ymm13,%ymm12,%ymm12
+	vmovdqa	%ymm12,160(%rbp)
+	vmovdqa	%ymm13,192(%rbp)
+	vmovdqa	%ymm14,224(%rbp)
+
+	movq	%rbx,128(%rbp)
+	movq	%rbx,%rcx
+	subq	$256,%rcx
+	shrq	$4,%rcx
+	addq	$6,%rcx
+	movq	$10,%r8
+	cmpq	$10,%rcx
+	cmovgq	%r8,%rcx
+	movq	%rsi,%rbx
+	xorq	%r8,%r8
+1:
+	addq	0(%rbx),%r10
+	adcq	8+0(%rbx),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rdx
+	movq	%rdx,%r15
+	mulxq	%r10,%r13,%r14
+	mulxq	%r11,%rax,%rdx
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rdx
+	mulxq	%r10,%r10,%rax
+	addq	%r10,%r14
+	mulxq	%r11,%r11,%r9
+	adcq	%r11,%r15
+	adcq	$0,%r9
+	imulq	%r12,%rdx
+	addq	%rax,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%rbx),%rbx
+2:
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol16(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpsrld	$20,%ymm6,%ymm3
+	vpslld	$12,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol8(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpslld	$7,%ymm6,%ymm3
+	vpsrld	$25,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpalignr	$12,%ymm14,%ymm14,%ymm14
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$4,%ymm6,%ymm6,%ymm6
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol16(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpsrld	$20,%ymm5,%ymm3
+	vpslld	$12,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol8(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpslld	$7,%ymm5,%ymm3
+	vpsrld	$25,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpalignr	$12,%ymm13,%ymm13,%ymm13
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$4,%ymm5,%ymm5,%ymm5
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	addq	0(%rbx),%r10
+	adcq	8+0(%rbx),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%rbx),%rbx
+	incq	%r8
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol16(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpsrld	$20,%ymm6,%ymm3
+	vpslld	$12,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol8(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpslld	$7,%ymm6,%ymm3
+	vpsrld	$25,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpalignr	$4,%ymm14,%ymm14,%ymm14
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$12,%ymm6,%ymm6,%ymm6
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol16(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpsrld	$20,%ymm5,%ymm3
+	vpslld	$12,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol8(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpslld	$7,%ymm5,%ymm3
+	vpsrld	$25,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpalignr	$4,%ymm13,%ymm13,%ymm13
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$12,%ymm5,%ymm5,%ymm5
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+
+	cmpq	%rcx,%r8
+	jb	1b
+	cmpq	$10,%r8
+	jne	2b
+	movq	%rbx,%r8
+	subq	%rsi,%rbx
+	movq	%rbx,%rcx
+	movq	128(%rbp),%rbx
+1:
+	addq	$16,%rcx
+	cmpq	%rbx,%rcx
+	jg	1f
+	addq	0(%r8),%r10
+	adcq	8+0(%r8),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rdx
+	movq	%rdx,%r15
+	mulxq	%r10,%r13,%r14
+	mulxq	%r11,%rax,%rdx
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rdx
+	mulxq	%r10,%r10,%rax
+	addq	%r10,%r14
+	mulxq	%r11,%r11,%r9
+	adcq	%r11,%r15
+	adcq	$0,%r9
+	imulq	%r12,%rdx
+	addq	%rax,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%r8),%r8
+	jmp	1b
+1:
+	vpaddd	.chacha20_consts(%rip),%ymm2,%ymm2
+	vpaddd	64(%rbp),%ymm6,%ymm6
+	vpaddd	96(%rbp),%ymm10,%ymm10
+	vpaddd	224(%rbp),%ymm14,%ymm14
+	vpaddd	.chacha20_consts(%rip),%ymm1,%ymm1
+	vpaddd	64(%rbp),%ymm5,%ymm5
+	vpaddd	96(%rbp),%ymm9,%ymm9
+	vpaddd	192(%rbp),%ymm13,%ymm13
+	vpaddd	.chacha20_consts(%rip),%ymm0,%ymm0
+	vpaddd	64(%rbp),%ymm4,%ymm4
+	vpaddd	96(%rbp),%ymm8,%ymm8
+	vpaddd	160(%rbp),%ymm12,%ymm12
+	vperm2i128	$0x02,%ymm2,%ymm6,%ymm3
+	vperm2i128	$0x13,%ymm2,%ymm6,%ymm6
+	vperm2i128	$0x02,%ymm10,%ymm14,%ymm2
+	vperm2i128	$0x13,%ymm10,%ymm14,%ymm10
+	vpxor	0+0(%rsi),%ymm3,%ymm3
+	vpxor	32+0(%rsi),%ymm2,%ymm2
+	vpxor	64+0(%rsi),%ymm6,%ymm6
+	vpxor	96+0(%rsi),%ymm10,%ymm10
+	vmovdqu	%ymm3,0+0(%rdi)
+	vmovdqu	%ymm2,32+0(%rdi)
+	vmovdqu	%ymm6,64+0(%rdi)
+	vmovdqu	%ymm10,96+0(%rdi)
+	vperm2i128	$0x02,%ymm1,%ymm5,%ymm3
+	vperm2i128	$0x13,%ymm1,%ymm5,%ymm5
+	vperm2i128	$0x02,%ymm9,%ymm13,%ymm1
+	vperm2i128	$0x13,%ymm9,%ymm13,%ymm9
+	vpxor	0+128(%rsi),%ymm3,%ymm3
+	vpxor	32+128(%rsi),%ymm1,%ymm1
+	vpxor	64+128(%rsi),%ymm5,%ymm5
+	vpxor	96+128(%rsi),%ymm9,%ymm9
+	vmovdqu	%ymm3,0+128(%rdi)
+	vmovdqu	%ymm1,32+128(%rdi)
+	vmovdqu	%ymm5,64+128(%rdi)
+	vmovdqu	%ymm9,96+128(%rdi)
+	vperm2i128	$0x13,%ymm0,%ymm4,%ymm3
+	vperm2i128	$0x02,%ymm0,%ymm4,%ymm0
+	vperm2i128	$0x02,%ymm8,%ymm12,%ymm4
+	vperm2i128	$0x13,%ymm8,%ymm12,%ymm12
+	vmovdqa	%ymm3,%ymm8
+
+	leaq	256(%rsi),%rsi
+	leaq	256(%rdi),%rdi
+	subq	$256,%rbx
+	jmp	open_avx2_tail_loop
+3:
+	vmovdqa	.chacha20_consts(%rip),%ymm0
+	vmovdqa	64(%rbp),%ymm4
+	vmovdqa	96(%rbp),%ymm8
+	vmovdqa	%ymm0,%ymm1
+	vmovdqa	%ymm4,%ymm5
+	vmovdqa	%ymm8,%ymm9
+	vmovdqa	%ymm0,%ymm2
+	vmovdqa	%ymm4,%ymm6
+	vmovdqa	%ymm8,%ymm10
+	vmovdqa	%ymm0,%ymm3
+	vmovdqa	%ymm4,%ymm7
+	vmovdqa	%ymm8,%ymm11
+	vmovdqa	.avx2_inc(%rip),%ymm12
+	vpaddd	160(%rbp),%ymm12,%ymm15
+	vpaddd	%ymm15,%ymm12,%ymm14
+	vpaddd	%ymm14,%ymm12,%ymm13
+	vpaddd	%ymm13,%ymm12,%ymm12
+	vmovdqa	%ymm15,256(%rbp)
+	vmovdqa	%ymm14,224(%rbp)
+	vmovdqa	%ymm13,192(%rbp)
+	vmovdqa	%ymm12,160(%rbp)
+
+	xorq	%rcx,%rcx
+	movq	%rsi,%r8
+1:
+	addq	0(%r8),%r10
+	adcq	8+0(%r8),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%r8),%r8
+2:
+	vmovdqa	%ymm8,128(%rbp)
+	vmovdqa	.rol16(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$20,%ymm7,%ymm8
+	vpslld	$32-20,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$20,%ymm6,%ymm8
+	vpslld	$32-20,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$20,%ymm5,%ymm8
+	vpslld	$32-20,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$20,%ymm4,%ymm8
+	vpslld	$32-20,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	.rol8(%rip),%ymm8
+	addq	0(%r8),%r10
+	adcq	8+0(%r8),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rdx
+	movq	%rdx,%r15
+	mulxq	%r10,%r13,%r14
+	mulxq	%r11,%rax,%rdx
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rdx
+	mulxq	%r10,%r10,%rax
+	addq	%r10,%r14
+	mulxq	%r11,%r11,%r9
+	adcq	%r11,%r15
+	adcq	$0,%r9
+	imulq	%r12,%rdx
+	addq	%rax,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$25,%ymm7,%ymm8
+	vpslld	$32-25,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$25,%ymm6,%ymm8
+	vpslld	$32-25,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$25,%ymm5,%ymm8
+	vpslld	$32-25,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$25,%ymm4,%ymm8
+	vpslld	$32-25,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	128(%rbp),%ymm8
+	vpalignr	$4,%ymm7,%ymm7,%ymm7
+	vpalignr	$8,%ymm11,%ymm11,%ymm11
+	vpalignr	$12,%ymm15,%ymm15,%ymm15
+	vpalignr	$4,%ymm6,%ymm6,%ymm6
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$12,%ymm14,%ymm14,%ymm14
+	vpalignr	$4,%ymm5,%ymm5,%ymm5
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$12,%ymm13,%ymm13,%ymm13
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vmovdqa	%ymm8,128(%rbp)
+	addq	16(%r8),%r10
+	adcq	8+16(%r8),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rdx
+	movq	%rdx,%r15
+	mulxq	%r10,%r13,%r14
+	mulxq	%r11,%rax,%rdx
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rdx
+	mulxq	%r10,%r10,%rax
+	addq	%r10,%r14
+	mulxq	%r11,%r11,%r9
+	adcq	%r11,%r15
+	adcq	$0,%r9
+	imulq	%r12,%rdx
+	addq	%rax,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	32(%r8),%r8
+	vmovdqa	.rol16(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$20,%ymm7,%ymm8
+	vpslld	$32-20,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$20,%ymm6,%ymm8
+	vpslld	$32-20,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$20,%ymm5,%ymm8
+	vpslld	$32-20,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$20,%ymm4,%ymm8
+	vpslld	$32-20,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	.rol8(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$25,%ymm7,%ymm8
+	vpslld	$32-25,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$25,%ymm6,%ymm8
+	vpslld	$32-25,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$25,%ymm5,%ymm8
+	vpslld	$32-25,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$25,%ymm4,%ymm8
+	vpslld	$32-25,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	128(%rbp),%ymm8
+	vpalignr	$12,%ymm7,%ymm7,%ymm7
+	vpalignr	$8,%ymm11,%ymm11,%ymm11
+	vpalignr	$4,%ymm15,%ymm15,%ymm15
+	vpalignr	$12,%ymm6,%ymm6,%ymm6
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$4,%ymm14,%ymm14,%ymm14
+	vpalignr	$12,%ymm5,%ymm5,%ymm5
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$4,%ymm13,%ymm13,%ymm13
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+
+	incq	%rcx
+	cmpq	$4,%rcx
+	jl	1b
+	cmpq	$10,%rcx
+	jne	2b
+	movq	%rbx,%rcx
+	subq	$384,%rcx
+	andq	$-16,%rcx
+1:
+	testq	%rcx,%rcx
+	je	1f
+	addq	0(%r8),%r10
+	adcq	8+0(%r8),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rdx
+	movq	%rdx,%r15
+	mulxq	%r10,%r13,%r14
+	mulxq	%r11,%rax,%rdx
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rdx
+	mulxq	%r10,%r10,%rax
+	addq	%r10,%r14
+	mulxq	%r11,%r11,%r9
+	adcq	%r11,%r15
+	adcq	$0,%r9
+	imulq	%r12,%rdx
+	addq	%rax,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%r8),%r8
+	subq	$16,%rcx
+	jmp	1b
+1:
+	vpaddd	.chacha20_consts(%rip),%ymm3,%ymm3
+	vpaddd	64(%rbp),%ymm7,%ymm7
+	vpaddd	96(%rbp),%ymm11,%ymm11
+	vpaddd	256(%rbp),%ymm15,%ymm15
+	vpaddd	.chacha20_consts(%rip),%ymm2,%ymm2
+	vpaddd	64(%rbp),%ymm6,%ymm6
+	vpaddd	96(%rbp),%ymm10,%ymm10
+	vpaddd	224(%rbp),%ymm14,%ymm14
+	vpaddd	.chacha20_consts(%rip),%ymm1,%ymm1
+	vpaddd	64(%rbp),%ymm5,%ymm5
+	vpaddd	96(%rbp),%ymm9,%ymm9
+	vpaddd	192(%rbp),%ymm13,%ymm13
+	vpaddd	.chacha20_consts(%rip),%ymm0,%ymm0
+	vpaddd	64(%rbp),%ymm4,%ymm4
+	vpaddd	96(%rbp),%ymm8,%ymm8
+	vpaddd	160(%rbp),%ymm12,%ymm12
+
+	vmovdqa	%ymm0,128(%rbp)
+	vperm2i128	$0x02,%ymm3,%ymm7,%ymm0
+	vperm2i128	$0x13,%ymm3,%ymm7,%ymm7
+	vperm2i128	$0x02,%ymm11,%ymm15,%ymm3
+	vperm2i128	$0x13,%ymm11,%ymm15,%ymm11
+	vpxor	0+0(%rsi),%ymm0,%ymm0
+	vpxor	32+0(%rsi),%ymm3,%ymm3
+	vpxor	64+0(%rsi),%ymm7,%ymm7
+	vpxor	96+0(%rsi),%ymm11,%ymm11
+	vmovdqu	%ymm0,0+0(%rdi)
+	vmovdqu	%ymm3,32+0(%rdi)
+	vmovdqu	%ymm7,64+0(%rdi)
+	vmovdqu	%ymm11,96+0(%rdi)
+
+	vmovdqa	128(%rbp),%ymm0
+	vperm2i128	$0x02,%ymm2,%ymm6,%ymm3
+	vperm2i128	$0x13,%ymm2,%ymm6,%ymm6
+	vperm2i128	$0x02,%ymm10,%ymm14,%ymm2
+	vperm2i128	$0x13,%ymm10,%ymm14,%ymm10
+	vpxor	0+128(%rsi),%ymm3,%ymm3
+	vpxor	32+128(%rsi),%ymm2,%ymm2
+	vpxor	64+128(%rsi),%ymm6,%ymm6
+	vpxor	96+128(%rsi),%ymm10,%ymm10
+	vmovdqu	%ymm3,0+128(%rdi)
+	vmovdqu	%ymm2,32+128(%rdi)
+	vmovdqu	%ymm6,64+128(%rdi)
+	vmovdqu	%ymm10,96+128(%rdi)
+	vperm2i128	$0x02,%ymm1,%ymm5,%ymm3
+	vperm2i128	$0x13,%ymm1,%ymm5,%ymm5
+	vperm2i128	$0x02,%ymm9,%ymm13,%ymm1
+	vperm2i128	$0x13,%ymm9,%ymm13,%ymm9
+	vpxor	0+256(%rsi),%ymm3,%ymm3
+	vpxor	32+256(%rsi),%ymm1,%ymm1
+	vpxor	64+256(%rsi),%ymm5,%ymm5
+	vpxor	96+256(%rsi),%ymm9,%ymm9
+	vmovdqu	%ymm3,0+256(%rdi)
+	vmovdqu	%ymm1,32+256(%rdi)
+	vmovdqu	%ymm5,64+256(%rdi)
+	vmovdqu	%ymm9,96+256(%rdi)
+	vperm2i128	$0x13,%ymm0,%ymm4,%ymm3
+	vperm2i128	$0x02,%ymm0,%ymm4,%ymm0
+	vperm2i128	$0x02,%ymm8,%ymm12,%ymm4
+	vperm2i128	$0x13,%ymm8,%ymm12,%ymm12
+	vmovdqa	%ymm3,%ymm8
+
+	leaq	384(%rsi),%rsi
+	leaq	384(%rdi),%rdi
+	subq	$384,%rbx
+open_avx2_tail_loop:
+	cmpq	$32,%rbx
+	jb	open_avx2_tail
+	subq	$32,%rbx
+	vpxor	(%rsi),%ymm0,%ymm0
+	vmovdqu	%ymm0,(%rdi)
+	leaq	32(%rsi),%rsi
+	leaq	32(%rdi),%rdi
+	vmovdqa	%ymm4,%ymm0
+	vmovdqa	%ymm8,%ymm4
+	vmovdqa	%ymm12,%ymm8
+	jmp	open_avx2_tail_loop
+open_avx2_tail:
+	cmpq	$16,%rbx
+	vmovdqa	%xmm0,%xmm1
+	jb	1f
+	subq	$16,%rbx
+
+	vpxor	(%rsi),%xmm0,%xmm1
+	vmovdqu	%xmm1,(%rdi)
+	leaq	16(%rsi),%rsi
+	leaq	16(%rdi),%rdi
+	vperm2i128	$0x11,%ymm0,%ymm0,%ymm0
+	vmovdqa	%xmm0,%xmm1
+1:
+	vzeroupper
+	jmp	open_sse_tail_16
+
+open_avx2_192:
+	vmovdqa	%ymm0,%ymm1
+	vmovdqa	%ymm0,%ymm2
+	vmovdqa	%ymm4,%ymm5
+	vmovdqa	%ymm4,%ymm6
+	vmovdqa	%ymm8,%ymm9
+	vmovdqa	%ymm8,%ymm10
+	vpaddd	.avx2_inc(%rip),%ymm12,%ymm13
+	vmovdqa	%ymm12,%ymm11
+	vmovdqa	%ymm13,%ymm15
+	movq	$10,%r10
+1:
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol16(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpsrld	$20,%ymm5,%ymm3
+	vpslld	$12,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol8(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpslld	$7,%ymm5,%ymm3
+	vpsrld	$25,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpalignr	$12,%ymm13,%ymm13,%ymm13
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$4,%ymm5,%ymm5,%ymm5
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol16(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpsrld	$20,%ymm5,%ymm3
+	vpslld	$12,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol8(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpslld	$7,%ymm5,%ymm3
+	vpsrld	$25,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpalignr	$4,%ymm13,%ymm13,%ymm13
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$12,%ymm5,%ymm5,%ymm5
+
+	decq	%r10
+	jne	1b
+	vpaddd	%ymm2,%ymm0,%ymm0
+	vpaddd	%ymm2,%ymm1,%ymm1
+	vpaddd	%ymm6,%ymm4,%ymm4
+	vpaddd	%ymm6,%ymm5,%ymm5
+	vpaddd	%ymm10,%ymm8,%ymm8
+	vpaddd	%ymm10,%ymm9,%ymm9
+	vpaddd	%ymm11,%ymm12,%ymm12
+	vpaddd	%ymm15,%ymm13,%ymm13
+	vperm2i128	$0x02,%ymm0,%ymm4,%ymm3
+
+	vpand	.clamp(%rip),%ymm3,%ymm3
+	vmovdqa	%ymm3,0(%rbp)
+
+	vperm2i128	$0x13,%ymm0,%ymm4,%ymm0
+	vperm2i128	$0x13,%ymm8,%ymm12,%ymm4
+	vperm2i128	$0x02,%ymm1,%ymm5,%ymm8
+	vperm2i128	$0x02,%ymm9,%ymm13,%ymm12
+	vperm2i128	$0x13,%ymm1,%ymm5,%ymm1
+	vperm2i128	$0x13,%ymm9,%ymm13,%ymm5
+open_avx2_short:
+	movq	%r8,%r8
+	call	poly_hash_ad_internal
+open_avx2_hash_and_xor_loop:
+	cmpq	$32,%rbx
+	jb	open_avx2_short_tail_32
+	subq	$32,%rbx
+	addq	0(%rsi),%r10
+	adcq	8+0(%rsi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	addq	16(%rsi),%r10
+	adcq	8+16(%rsi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+
+	vpxor	(%rsi),%ymm0,%ymm0
+	vmovdqu	%ymm0,(%rdi)
+	leaq	32(%rsi),%rsi
+	leaq	32(%rdi),%rdi
+
+	vmovdqa	%ymm4,%ymm0
+	vmovdqa	%ymm8,%ymm4
+	vmovdqa	%ymm12,%ymm8
+	vmovdqa	%ymm1,%ymm12
+	vmovdqa	%ymm5,%ymm1
+	vmovdqa	%ymm9,%ymm5
+	vmovdqa	%ymm13,%ymm9
+	vmovdqa	%ymm2,%ymm13
+	vmovdqa	%ymm6,%ymm2
+	jmp	open_avx2_hash_and_xor_loop
+open_avx2_short_tail_32:
+	cmpq	$16,%rbx
+	vmovdqa	%xmm0,%xmm1
+	jb	1f
+	subq	$16,%rbx
+	addq	0(%rsi),%r10
+	adcq	8+0(%rsi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	vpxor	(%rsi),%xmm0,%xmm3
+	vmovdqu	%xmm3,(%rdi)
+	leaq	16(%rsi),%rsi
+	leaq	16(%rdi),%rdi
+	vextracti128	$1,%ymm0,%xmm1
+1:
+	vzeroupper
+	jmp	open_sse_tail_16
+
+open_avx2_320:
+	vmovdqa	%ymm0,%ymm1
+	vmovdqa	%ymm0,%ymm2
+	vmovdqa	%ymm4,%ymm5
+	vmovdqa	%ymm4,%ymm6
+	vmovdqa	%ymm8,%ymm9
+	vmovdqa	%ymm8,%ymm10
+	vpaddd	.avx2_inc(%rip),%ymm12,%ymm13
+	vpaddd	.avx2_inc(%rip),%ymm13,%ymm14
+	vmovdqa	%ymm4,%ymm7
+	vmovdqa	%ymm8,%ymm11
+	vmovdqa	%ymm12,160(%rbp)
+	vmovdqa	%ymm13,192(%rbp)
+	vmovdqa	%ymm14,224(%rbp)
+	movq	$10,%r10
+1:
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol16(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpsrld	$20,%ymm5,%ymm3
+	vpslld	$12,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol8(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpslld	$7,%ymm5,%ymm3
+	vpsrld	$25,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpalignr	$12,%ymm13,%ymm13,%ymm13
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$4,%ymm5,%ymm5,%ymm5
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol16(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpsrld	$20,%ymm6,%ymm3
+	vpslld	$12,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol8(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpslld	$7,%ymm6,%ymm3
+	vpsrld	$25,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpalignr	$12,%ymm14,%ymm14,%ymm14
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$4,%ymm6,%ymm6,%ymm6
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol16(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpsrld	$20,%ymm5,%ymm3
+	vpslld	$12,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol8(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpslld	$7,%ymm5,%ymm3
+	vpsrld	$25,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpalignr	$4,%ymm13,%ymm13,%ymm13
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$12,%ymm5,%ymm5,%ymm5
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol16(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpsrld	$20,%ymm6,%ymm3
+	vpslld	$12,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol8(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpslld	$7,%ymm6,%ymm3
+	vpsrld	$25,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpalignr	$4,%ymm14,%ymm14,%ymm14
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$12,%ymm6,%ymm6,%ymm6
+
+	decq	%r10
+	jne	1b
+	vpaddd	.chacha20_consts(%rip),%ymm0,%ymm0
+	vpaddd	.chacha20_consts(%rip),%ymm1,%ymm1
+	vpaddd	.chacha20_consts(%rip),%ymm2,%ymm2
+	vpaddd	%ymm7,%ymm4,%ymm4
+	vpaddd	%ymm7,%ymm5,%ymm5
+	vpaddd	%ymm7,%ymm6,%ymm6
+	vpaddd	%ymm11,%ymm8,%ymm8
+	vpaddd	%ymm11,%ymm9,%ymm9
+	vpaddd	%ymm11,%ymm10,%ymm10
+	vpaddd	160(%rbp),%ymm12,%ymm12
+	vpaddd	192(%rbp),%ymm13,%ymm13
+	vpaddd	224(%rbp),%ymm14,%ymm14
+	vperm2i128	$0x02,%ymm0,%ymm4,%ymm3
+
+	vpand	.clamp(%rip),%ymm3,%ymm3
+	vmovdqa	%ymm3,0(%rbp)
+
+	vperm2i128	$0x13,%ymm0,%ymm4,%ymm0
+	vperm2i128	$0x13,%ymm8,%ymm12,%ymm4
+	vperm2i128	$0x02,%ymm1,%ymm5,%ymm8
+	vperm2i128	$0x02,%ymm9,%ymm13,%ymm12
+	vperm2i128	$0x13,%ymm1,%ymm5,%ymm1
+	vperm2i128	$0x13,%ymm9,%ymm13,%ymm5
+	vperm2i128	$0x02,%ymm2,%ymm6,%ymm9
+	vperm2i128	$0x02,%ymm10,%ymm14,%ymm13
+	vperm2i128	$0x13,%ymm2,%ymm6,%ymm2
+	vperm2i128	$0x13,%ymm10,%ymm14,%ymm6
+	jmp	open_avx2_short
+.size	chacha20_poly1305_open_avx2, .-chacha20_poly1305_open_avx2
+
+
+.type	chacha20_poly1305_seal_avx2,@function
+.align	64
+chacha20_poly1305_seal_avx2:
+	vzeroupper
+	vmovdqa	.chacha20_consts(%rip),%ymm0
+	vbroadcasti128	0(%r9),%ymm4
+	vbroadcasti128	16(%r9),%ymm8
+	vbroadcasti128	32(%r9),%ymm12
+	vpaddd	.avx2_init(%rip),%ymm12,%ymm12
+	cmpq	$192,%rbx
+	jbe	seal_avx2_192
+	cmpq	$320,%rbx
+	jbe	seal_avx2_320
+	vmovdqa	%ymm0,%ymm1
+	vmovdqa	%ymm0,%ymm2
+	vmovdqa	%ymm0,%ymm3
+	vmovdqa	%ymm4,%ymm5
+	vmovdqa	%ymm4,%ymm6
+	vmovdqa	%ymm4,%ymm7
+	vmovdqa	%ymm4,64(%rbp)
+	vmovdqa	%ymm8,%ymm9
+	vmovdqa	%ymm8,%ymm10
+	vmovdqa	%ymm8,%ymm11
+	vmovdqa	%ymm8,96(%rbp)
+	vmovdqa	%ymm12,%ymm15
+	vpaddd	.avx2_inc(%rip),%ymm15,%ymm14
+	vpaddd	.avx2_inc(%rip),%ymm14,%ymm13
+	vpaddd	.avx2_inc(%rip),%ymm13,%ymm12
+	vmovdqa	%ymm12,160(%rbp)
+	vmovdqa	%ymm13,192(%rbp)
+	vmovdqa	%ymm14,224(%rbp)
+	vmovdqa	%ymm15,256(%rbp)
+	movq	$10,%r10
+1:
+	vmovdqa	%ymm8,128(%rbp)
+	vmovdqa	.rol16(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$20,%ymm7,%ymm8
+	vpslld	$32-20,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$20,%ymm6,%ymm8
+	vpslld	$32-20,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$20,%ymm5,%ymm8
+	vpslld	$32-20,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$20,%ymm4,%ymm8
+	vpslld	$32-20,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	.rol8(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$25,%ymm7,%ymm8
+	vpslld	$32-25,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$25,%ymm6,%ymm8
+	vpslld	$32-25,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$25,%ymm5,%ymm8
+	vpslld	$32-25,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$25,%ymm4,%ymm8
+	vpslld	$32-25,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	128(%rbp),%ymm8
+	vpalignr	$4,%ymm7,%ymm7,%ymm7
+	vpalignr	$8,%ymm11,%ymm11,%ymm11
+	vpalignr	$12,%ymm15,%ymm15,%ymm15
+	vpalignr	$4,%ymm6,%ymm6,%ymm6
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$12,%ymm14,%ymm14,%ymm14
+	vpalignr	$4,%ymm5,%ymm5,%ymm5
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$12,%ymm13,%ymm13,%ymm13
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vmovdqa	%ymm8,128(%rbp)
+	vmovdqa	.rol16(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$20,%ymm7,%ymm8
+	vpslld	$32-20,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$20,%ymm6,%ymm8
+	vpslld	$32-20,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$20,%ymm5,%ymm8
+	vpslld	$32-20,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$20,%ymm4,%ymm8
+	vpslld	$32-20,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	.rol8(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$25,%ymm7,%ymm8
+	vpslld	$32-25,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$25,%ymm6,%ymm8
+	vpslld	$32-25,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$25,%ymm5,%ymm8
+	vpslld	$32-25,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$25,%ymm4,%ymm8
+	vpslld	$32-25,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	128(%rbp),%ymm8
+	vpalignr	$12,%ymm7,%ymm7,%ymm7
+	vpalignr	$8,%ymm11,%ymm11,%ymm11
+	vpalignr	$4,%ymm15,%ymm15,%ymm15
+	vpalignr	$12,%ymm6,%ymm6,%ymm6
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$4,%ymm14,%ymm14,%ymm14
+	vpalignr	$12,%ymm5,%ymm5,%ymm5
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$4,%ymm13,%ymm13,%ymm13
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+
+	decq	%r10
+	jnz	1b
+	vpaddd	.chacha20_consts(%rip),%ymm3,%ymm3
+	vpaddd	64(%rbp),%ymm7,%ymm7
+	vpaddd	96(%rbp),%ymm11,%ymm11
+	vpaddd	256(%rbp),%ymm15,%ymm15
+	vpaddd	.chacha20_consts(%rip),%ymm2,%ymm2
+	vpaddd	64(%rbp),%ymm6,%ymm6
+	vpaddd	96(%rbp),%ymm10,%ymm10
+	vpaddd	224(%rbp),%ymm14,%ymm14
+	vpaddd	.chacha20_consts(%rip),%ymm1,%ymm1
+	vpaddd	64(%rbp),%ymm5,%ymm5
+	vpaddd	96(%rbp),%ymm9,%ymm9
+	vpaddd	192(%rbp),%ymm13,%ymm13
+	vpaddd	.chacha20_consts(%rip),%ymm0,%ymm0
+	vpaddd	64(%rbp),%ymm4,%ymm4
+	vpaddd	96(%rbp),%ymm8,%ymm8
+	vpaddd	160(%rbp),%ymm12,%ymm12
+
+	vperm2i128	$0x13,%ymm11,%ymm15,%ymm11
+	vperm2i128	$0x02,%ymm3,%ymm7,%ymm15
+	vperm2i128	$0x13,%ymm3,%ymm7,%ymm3
+	vpand	.clamp(%rip),%ymm15,%ymm15
+	vmovdqa	%ymm15,0(%rbp)
+	movq	%r8,%r8
+	call	poly_hash_ad_internal
+
+	vpxor	0(%rsi),%ymm3,%ymm3
+	vpxor	32(%rsi),%ymm11,%ymm11
+	vmovdqu	%ymm3,0(%rdi)
+	vmovdqu	%ymm11,32(%rdi)
+	vperm2i128	$0x02,%ymm2,%ymm6,%ymm15
+	vperm2i128	$0x13,%ymm2,%ymm6,%ymm6
+	vperm2i128	$0x02,%ymm10,%ymm14,%ymm2
+	vperm2i128	$0x13,%ymm10,%ymm14,%ymm10
+	vpxor	0+64(%rsi),%ymm15,%ymm15
+	vpxor	32+64(%rsi),%ymm2,%ymm2
+	vpxor	64+64(%rsi),%ymm6,%ymm6
+	vpxor	96+64(%rsi),%ymm10,%ymm10
+	vmovdqu	%ymm15,0+64(%rdi)
+	vmovdqu	%ymm2,32+64(%rdi)
+	vmovdqu	%ymm6,64+64(%rdi)
+	vmovdqu	%ymm10,96+64(%rdi)
+	vperm2i128	$0x02,%ymm1,%ymm5,%ymm15
+	vperm2i128	$0x13,%ymm1,%ymm5,%ymm5
+	vperm2i128	$0x02,%ymm9,%ymm13,%ymm1
+	vperm2i128	$0x13,%ymm9,%ymm13,%ymm9
+	vpxor	0+192(%rsi),%ymm15,%ymm15
+	vpxor	32+192(%rsi),%ymm1,%ymm1
+	vpxor	64+192(%rsi),%ymm5,%ymm5
+	vpxor	96+192(%rsi),%ymm9,%ymm9
+	vmovdqu	%ymm15,0+192(%rdi)
+	vmovdqu	%ymm1,32+192(%rdi)
+	vmovdqu	%ymm5,64+192(%rdi)
+	vmovdqu	%ymm9,96+192(%rdi)
+	vperm2i128	$0x13,%ymm0,%ymm4,%ymm15
+	vperm2i128	$0x02,%ymm0,%ymm4,%ymm0
+	vperm2i128	$0x02,%ymm8,%ymm12,%ymm4
+	vperm2i128	$0x13,%ymm8,%ymm12,%ymm12
+	vmovdqa	%ymm15,%ymm8
+
+	leaq	320(%rsi),%rsi
+	subq	$320,%rbx
+	movq	$320,%rcx
+	cmpq	$128,%rbx
+	jbe	seal_avx2_hash
+	vpxor	0(%rsi),%ymm0,%ymm0
+	vpxor	32(%rsi),%ymm4,%ymm4
+	vpxor	64(%rsi),%ymm8,%ymm8
+	vpxor	96(%rsi),%ymm12,%ymm12
+	vmovdqu	%ymm0,320(%rdi)
+	vmovdqu	%ymm4,352(%rdi)
+	vmovdqu	%ymm8,384(%rdi)
+	vmovdqu	%ymm12,416(%rdi)
+	leaq	128(%rsi),%rsi
+	subq	$128,%rbx
+	movq	$8,%rcx
+	movq	$2,%r8
+	cmpq	$128,%rbx
+	jbe	seal_avx2_tail_128
+	cmpq	$256,%rbx
+	jbe	seal_avx2_tail_256
+	cmpq	$384,%rbx
+	jbe	seal_avx2_tail_384
+	cmpq	$512,%rbx
+	jbe	seal_avx2_tail_512
+	vmovdqa	.chacha20_consts(%rip),%ymm0
+	vmovdqa	64(%rbp),%ymm4
+	vmovdqa	96(%rbp),%ymm8
+	vmovdqa	%ymm0,%ymm1
+	vmovdqa	%ymm4,%ymm5
+	vmovdqa	%ymm8,%ymm9
+	vmovdqa	%ymm0,%ymm2
+	vmovdqa	%ymm4,%ymm6
+	vmovdqa	%ymm8,%ymm10
+	vmovdqa	%ymm0,%ymm3
+	vmovdqa	%ymm4,%ymm7
+	vmovdqa	%ymm8,%ymm11
+	vmovdqa	.avx2_inc(%rip),%ymm12
+	vpaddd	160(%rbp),%ymm12,%ymm15
+	vpaddd	%ymm15,%ymm12,%ymm14
+	vpaddd	%ymm14,%ymm12,%ymm13
+	vpaddd	%ymm13,%ymm12,%ymm12
+	vmovdqa	%ymm15,256(%rbp)
+	vmovdqa	%ymm14,224(%rbp)
+	vmovdqa	%ymm13,192(%rbp)
+	vmovdqa	%ymm12,160(%rbp)
+	vmovdqa	%ymm8,128(%rbp)
+	vmovdqa	.rol16(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$20,%ymm7,%ymm8
+	vpslld	$32-20,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$20,%ymm6,%ymm8
+	vpslld	$32-20,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$20,%ymm5,%ymm8
+	vpslld	$32-20,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$20,%ymm4,%ymm8
+	vpslld	$32-20,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	.rol8(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$25,%ymm7,%ymm8
+	vpslld	$32-25,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$25,%ymm6,%ymm8
+	vpslld	$32-25,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$25,%ymm5,%ymm8
+	vpslld	$32-25,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$25,%ymm4,%ymm8
+	vpslld	$32-25,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	128(%rbp),%ymm8
+	vpalignr	$4,%ymm7,%ymm7,%ymm7
+	vpalignr	$8,%ymm11,%ymm11,%ymm11
+	vpalignr	$12,%ymm15,%ymm15,%ymm15
+	vpalignr	$4,%ymm6,%ymm6,%ymm6
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$12,%ymm14,%ymm14,%ymm14
+	vpalignr	$4,%ymm5,%ymm5,%ymm5
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$12,%ymm13,%ymm13,%ymm13
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vmovdqa	%ymm8,128(%rbp)
+	vmovdqa	.rol16(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$20,%ymm7,%ymm8
+	vpslld	$32-20,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$20,%ymm6,%ymm8
+	vpslld	$32-20,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$20,%ymm5,%ymm8
+	vpslld	$32-20,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$20,%ymm4,%ymm8
+	vpslld	$32-20,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	.rol8(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$25,%ymm7,%ymm8
+	vpslld	$32-25,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$25,%ymm6,%ymm8
+	vpslld	$32-25,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$25,%ymm5,%ymm8
+	vpslld	$32-25,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$25,%ymm4,%ymm8
+	vpslld	$32-25,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	128(%rbp),%ymm8
+	vpalignr	$12,%ymm7,%ymm7,%ymm7
+	vpalignr	$8,%ymm11,%ymm11,%ymm11
+	vpalignr	$4,%ymm15,%ymm15,%ymm15
+	vpalignr	$12,%ymm6,%ymm6,%ymm6
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$4,%ymm14,%ymm14,%ymm14
+	vpalignr	$12,%ymm5,%ymm5,%ymm5
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$4,%ymm13,%ymm13,%ymm13
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+	vmovdqa	%ymm8,128(%rbp)
+	vmovdqa	.rol16(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$20,%ymm7,%ymm8
+	vpslld	$32-20,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$20,%ymm6,%ymm8
+	vpslld	$32-20,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$20,%ymm5,%ymm8
+	vpslld	$32-20,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$20,%ymm4,%ymm8
+	vpslld	$32-20,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	.rol8(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+
+	subq	$16,%rdi
+	movq	$9,%rcx
+	jmp	4f
+1:
+	vmovdqa	.chacha20_consts(%rip),%ymm0
+	vmovdqa	64(%rbp),%ymm4
+	vmovdqa	96(%rbp),%ymm8
+	vmovdqa	%ymm0,%ymm1
+	vmovdqa	%ymm4,%ymm5
+	vmovdqa	%ymm8,%ymm9
+	vmovdqa	%ymm0,%ymm2
+	vmovdqa	%ymm4,%ymm6
+	vmovdqa	%ymm8,%ymm10
+	vmovdqa	%ymm0,%ymm3
+	vmovdqa	%ymm4,%ymm7
+	vmovdqa	%ymm8,%ymm11
+	vmovdqa	.avx2_inc(%rip),%ymm12
+	vpaddd	160(%rbp),%ymm12,%ymm15
+	vpaddd	%ymm15,%ymm12,%ymm14
+	vpaddd	%ymm14,%ymm12,%ymm13
+	vpaddd	%ymm13,%ymm12,%ymm12
+	vmovdqa	%ymm15,256(%rbp)
+	vmovdqa	%ymm14,224(%rbp)
+	vmovdqa	%ymm13,192(%rbp)
+	vmovdqa	%ymm12,160(%rbp)
+
+	movq	$10,%rcx
+2:
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	vmovdqa	%ymm8,128(%rbp)
+	vmovdqa	.rol16(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	movq	0+0(%rbp),%rdx
+	movq	%rdx,%r15
+	mulxq	%r10,%r13,%r14
+	mulxq	%r11,%rax,%rdx
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	movq	8+0(%rbp),%rdx
+	mulxq	%r10,%r10,%rax
+	addq	%r10,%r14
+	mulxq	%r11,%r11,%r9
+	adcq	%r11,%r15
+	adcq	$0,%r9
+	imulq	%r12,%rdx
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$20,%ymm7,%ymm8
+	vpslld	$32-20,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$20,%ymm6,%ymm8
+	vpslld	$32-20,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$20,%ymm5,%ymm8
+	addq	%rax,%r15
+	adcq	%rdx,%r9
+	vpslld	$32-20,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$20,%ymm4,%ymm8
+	vpslld	$32-20,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	.rol8(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+4:
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	addq	16(%rdi),%r10
+	adcq	8+16(%rdi),%r11
+	adcq	$1,%r12
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	movq	0+0(%rbp),%rdx
+	movq	%rdx,%r15
+	mulxq	%r10,%r13,%r14
+	mulxq	%r11,%rax,%rdx
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$25,%ymm7,%ymm8
+	vpslld	$32-25,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$25,%ymm6,%ymm8
+	vpslld	$32-25,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$25,%ymm5,%ymm8
+	vpslld	$32-25,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$25,%ymm4,%ymm8
+	vpslld	$32-25,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	128(%rbp),%ymm8
+	vpalignr	$4,%ymm7,%ymm7,%ymm7
+	vpalignr	$8,%ymm11,%ymm11,%ymm11
+	vpalignr	$12,%ymm15,%ymm15,%ymm15
+	vpalignr	$4,%ymm6,%ymm6,%ymm6
+	movq	8+0(%rbp),%rdx
+	mulxq	%r10,%r10,%rax
+	addq	%r10,%r14
+	mulxq	%r11,%r11,%r9
+	adcq	%r11,%r15
+	adcq	$0,%r9
+	imulq	%r12,%rdx
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$12,%ymm14,%ymm14,%ymm14
+	vpalignr	$4,%ymm5,%ymm5,%ymm5
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$12,%ymm13,%ymm13,%ymm13
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vmovdqa	%ymm8,128(%rbp)
+	vmovdqa	.rol16(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	addq	%rax,%r15
+	adcq	%rdx,%r9
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$20,%ymm7,%ymm8
+	vpslld	$32-20,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	addq	32(%rdi),%r10
+	adcq	8+32(%rdi),%r11
+	adcq	$1,%r12
+
+	leaq	48(%rdi),%rdi
+	vpsrld	$20,%ymm6,%ymm8
+	vpslld	$32-20,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$20,%ymm5,%ymm8
+	vpslld	$32-20,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$20,%ymm4,%ymm8
+	vpslld	$32-20,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	.rol8(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	movq	0+0(%rbp),%rdx
+	movq	%rdx,%r15
+	mulxq	%r10,%r13,%r14
+	mulxq	%r11,%rax,%rdx
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	movq	8+0(%rbp),%rdx
+	mulxq	%r10,%r10,%rax
+	addq	%r10,%r14
+	mulxq	%r11,%r11,%r9
+	adcq	%r11,%r15
+	adcq	$0,%r9
+	imulq	%r12,%rdx
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$25,%ymm7,%ymm8
+	vpslld	$32-25,%ymm7,%ymm7
+	addq	%rax,%r15
+	adcq	%rdx,%r9
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$25,%ymm6,%ymm8
+	vpslld	$32-25,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$25,%ymm5,%ymm8
+	vpslld	$32-25,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$25,%ymm4,%ymm8
+	vpslld	$32-25,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	128(%rbp),%ymm8
+	vpalignr	$12,%ymm7,%ymm7,%ymm7
+	vpalignr	$8,%ymm11,%ymm11,%ymm11
+	vpalignr	$4,%ymm15,%ymm15,%ymm15
+	vpalignr	$12,%ymm6,%ymm6,%ymm6
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$4,%ymm14,%ymm14,%ymm14
+	vpalignr	$12,%ymm5,%ymm5,%ymm5
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$4,%ymm13,%ymm13,%ymm13
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+
+	decq	%rcx
+	jne	2b
+	vpaddd	.chacha20_consts(%rip),%ymm3,%ymm3
+	vpaddd	64(%rbp),%ymm7,%ymm7
+	vpaddd	96(%rbp),%ymm11,%ymm11
+	vpaddd	256(%rbp),%ymm15,%ymm15
+	vpaddd	.chacha20_consts(%rip),%ymm2,%ymm2
+	vpaddd	64(%rbp),%ymm6,%ymm6
+	vpaddd	96(%rbp),%ymm10,%ymm10
+	vpaddd	224(%rbp),%ymm14,%ymm14
+	vpaddd	.chacha20_consts(%rip),%ymm1,%ymm1
+	vpaddd	64(%rbp),%ymm5,%ymm5
+	vpaddd	96(%rbp),%ymm9,%ymm9
+	vpaddd	192(%rbp),%ymm13,%ymm13
+	vpaddd	.chacha20_consts(%rip),%ymm0,%ymm0
+	vpaddd	64(%rbp),%ymm4,%ymm4
+	vpaddd	96(%rbp),%ymm8,%ymm8
+	vpaddd	160(%rbp),%ymm12,%ymm12
+
+	leaq	32(%rdi),%rdi
+	vmovdqa	%ymm0,128(%rbp)
+	addq	-32(%rdi),%r10
+	adcq	8+-32(%rdi),%r11
+	adcq	$1,%r12
+	vperm2i128	$0x02,%ymm3,%ymm7,%ymm0
+	vperm2i128	$0x13,%ymm3,%ymm7,%ymm7
+	vperm2i128	$0x02,%ymm11,%ymm15,%ymm3
+	vperm2i128	$0x13,%ymm11,%ymm15,%ymm11
+	vpxor	0+0(%rsi),%ymm0,%ymm0
+	vpxor	32+0(%rsi),%ymm3,%ymm3
+	vpxor	64+0(%rsi),%ymm7,%ymm7
+	vpxor	96+0(%rsi),%ymm11,%ymm11
+	vmovdqu	%ymm0,0+0(%rdi)
+	vmovdqu	%ymm3,32+0(%rdi)
+	vmovdqu	%ymm7,64+0(%rdi)
+	vmovdqu	%ymm11,96+0(%rdi)
+
+	vmovdqa	128(%rbp),%ymm0
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	vperm2i128	$0x02,%ymm2,%ymm6,%ymm3
+	vperm2i128	$0x13,%ymm2,%ymm6,%ymm6
+	vperm2i128	$0x02,%ymm10,%ymm14,%ymm2
+	vperm2i128	$0x13,%ymm10,%ymm14,%ymm10
+	vpxor	0+128(%rsi),%ymm3,%ymm3
+	vpxor	32+128(%rsi),%ymm2,%ymm2
+	vpxor	64+128(%rsi),%ymm6,%ymm6
+	vpxor	96+128(%rsi),%ymm10,%ymm10
+	vmovdqu	%ymm3,0+128(%rdi)
+	vmovdqu	%ymm2,32+128(%rdi)
+	vmovdqu	%ymm6,64+128(%rdi)
+	vmovdqu	%ymm10,96+128(%rdi)
+	addq	-16(%rdi),%r10
+	adcq	8+-16(%rdi),%r11
+	adcq	$1,%r12
+	vperm2i128	$0x02,%ymm1,%ymm5,%ymm3
+	vperm2i128	$0x13,%ymm1,%ymm5,%ymm5
+	vperm2i128	$0x02,%ymm9,%ymm13,%ymm1
+	vperm2i128	$0x13,%ymm9,%ymm13,%ymm9
+	vpxor	0+256(%rsi),%ymm3,%ymm3
+	vpxor	32+256(%rsi),%ymm1,%ymm1
+	vpxor	64+256(%rsi),%ymm5,%ymm5
+	vpxor	96+256(%rsi),%ymm9,%ymm9
+	vmovdqu	%ymm3,0+256(%rdi)
+	vmovdqu	%ymm1,32+256(%rdi)
+	vmovdqu	%ymm5,64+256(%rdi)
+	vmovdqu	%ymm9,96+256(%rdi)
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	vperm2i128	$0x02,%ymm0,%ymm4,%ymm3
+	vperm2i128	$0x13,%ymm0,%ymm4,%ymm4
+	vperm2i128	$0x02,%ymm8,%ymm12,%ymm0
+	vperm2i128	$0x13,%ymm8,%ymm12,%ymm8
+	vpxor	0+384(%rsi),%ymm3,%ymm3
+	vpxor	32+384(%rsi),%ymm0,%ymm0
+	vpxor	64+384(%rsi),%ymm4,%ymm4
+	vpxor	96+384(%rsi),%ymm8,%ymm8
+	vmovdqu	%ymm3,0+384(%rdi)
+	vmovdqu	%ymm0,32+384(%rdi)
+	vmovdqu	%ymm4,64+384(%rdi)
+	vmovdqu	%ymm8,96+384(%rdi)
+
+	leaq	512(%rsi),%rsi
+	subq	$512,%rbx
+	cmpq	$512,%rbx
+	jg	1b
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	addq	16(%rdi),%r10
+	adcq	8+16(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	32(%rdi),%rdi
+	movq	$10,%rcx
+	xorq	%r8,%r8
+	cmpq	$128,%rbx
+	ja	3f
+
+seal_avx2_tail_128:
+	vmovdqa	.chacha20_consts(%rip),%ymm0
+	vmovdqa	64(%rbp),%ymm4
+	vmovdqa	96(%rbp),%ymm8
+	vmovdqa	.avx2_inc(%rip),%ymm12
+	vpaddd	160(%rbp),%ymm12,%ymm12
+	vmovdqa	%ymm12,160(%rbp)
+
+1:
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%rdi),%rdi
+2:
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+	addq	16(%rdi),%r10
+	adcq	8+16(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	32(%rdi),%rdi
+	decq	%rcx
+	jg	1b
+	decq	%r8
+	jge	2b
+	vpaddd	.chacha20_consts(%rip),%ymm0,%ymm0
+	vpaddd	64(%rbp),%ymm4,%ymm4
+	vpaddd	96(%rbp),%ymm8,%ymm8
+	vpaddd	160(%rbp),%ymm12,%ymm12
+	vperm2i128	$0x13,%ymm0,%ymm4,%ymm3
+	vperm2i128	$0x02,%ymm0,%ymm4,%ymm0
+	vperm2i128	$0x02,%ymm8,%ymm12,%ymm4
+	vperm2i128	$0x13,%ymm8,%ymm12,%ymm12
+	vmovdqa	%ymm3,%ymm8
+
+	jmp	seal_avx2_short_loop
+3:
+	cmpq	$256,%rbx
+	ja	3f
+
+seal_avx2_tail_256:
+	vmovdqa	.chacha20_consts(%rip),%ymm0
+	vmovdqa	64(%rbp),%ymm4
+	vmovdqa	96(%rbp),%ymm8
+	vmovdqa	%ymm0,%ymm1
+	vmovdqa	%ymm4,%ymm5
+	vmovdqa	%ymm8,%ymm9
+	vmovdqa	.avx2_inc(%rip),%ymm12
+	vpaddd	160(%rbp),%ymm12,%ymm13
+	vpaddd	%ymm13,%ymm12,%ymm12
+	vmovdqa	%ymm12,160(%rbp)
+	vmovdqa	%ymm13,192(%rbp)
+
+1:
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%rdi),%rdi
+2:
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol16(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpsrld	$20,%ymm5,%ymm3
+	vpslld	$12,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol8(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpslld	$7,%ymm5,%ymm3
+	vpsrld	$25,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpalignr	$12,%ymm13,%ymm13,%ymm13
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$4,%ymm5,%ymm5,%ymm5
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol16(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpsrld	$20,%ymm5,%ymm3
+	vpslld	$12,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol8(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpslld	$7,%ymm5,%ymm3
+	vpsrld	$25,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpalignr	$4,%ymm13,%ymm13,%ymm13
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$12,%ymm5,%ymm5,%ymm5
+	addq	16(%rdi),%r10
+	adcq	8+16(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	32(%rdi),%rdi
+	decq	%rcx
+	jg	1b
+	decq	%r8
+	jge	2b
+	vpaddd	.chacha20_consts(%rip),%ymm1,%ymm1
+	vpaddd	64(%rbp),%ymm5,%ymm5
+	vpaddd	96(%rbp),%ymm9,%ymm9
+	vpaddd	192(%rbp),%ymm13,%ymm13
+	vpaddd	.chacha20_consts(%rip),%ymm0,%ymm0
+	vpaddd	64(%rbp),%ymm4,%ymm4
+	vpaddd	96(%rbp),%ymm8,%ymm8
+	vpaddd	160(%rbp),%ymm12,%ymm12
+	vperm2i128	$0x02,%ymm1,%ymm5,%ymm3
+	vperm2i128	$0x13,%ymm1,%ymm5,%ymm5
+	vperm2i128	$0x02,%ymm9,%ymm13,%ymm1
+	vperm2i128	$0x13,%ymm9,%ymm13,%ymm9
+	vpxor	0+0(%rsi),%ymm3,%ymm3
+	vpxor	32+0(%rsi),%ymm1,%ymm1
+	vpxor	64+0(%rsi),%ymm5,%ymm5
+	vpxor	96+0(%rsi),%ymm9,%ymm9
+	vmovdqu	%ymm3,0+0(%rdi)
+	vmovdqu	%ymm1,32+0(%rdi)
+	vmovdqu	%ymm5,64+0(%rdi)
+	vmovdqu	%ymm9,96+0(%rdi)
+	vperm2i128	$0x13,%ymm0,%ymm4,%ymm3
+	vperm2i128	$0x02,%ymm0,%ymm4,%ymm0
+	vperm2i128	$0x02,%ymm8,%ymm12,%ymm4
+	vperm2i128	$0x13,%ymm8,%ymm12,%ymm12
+	vmovdqa	%ymm3,%ymm8
+
+	movq	$128,%rcx
+	leaq	128(%rsi),%rsi
+	subq	$128,%rbx
+	jmp	seal_avx2_hash
+3:
+	cmpq	$384,%rbx
+	ja	seal_avx2_tail_512
+
+seal_avx2_tail_384:
+	vmovdqa	.chacha20_consts(%rip),%ymm0
+	vmovdqa	64(%rbp),%ymm4
+	vmovdqa	96(%rbp),%ymm8
+	vmovdqa	%ymm0,%ymm1
+	vmovdqa	%ymm4,%ymm5
+	vmovdqa	%ymm8,%ymm9
+	vmovdqa	%ymm0,%ymm2
+	vmovdqa	%ymm4,%ymm6
+	vmovdqa	%ymm8,%ymm10
+	vmovdqa	.avx2_inc(%rip),%ymm12
+	vpaddd	160(%rbp),%ymm12,%ymm14
+	vpaddd	%ymm14,%ymm12,%ymm13
+	vpaddd	%ymm13,%ymm12,%ymm12
+	vmovdqa	%ymm12,160(%rbp)
+	vmovdqa	%ymm13,192(%rbp)
+	vmovdqa	%ymm14,224(%rbp)
+
+1:
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%rdi),%rdi
+2:
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol16(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpsrld	$20,%ymm5,%ymm3
+	vpslld	$12,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol8(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpslld	$7,%ymm5,%ymm3
+	vpsrld	$25,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpalignr	$12,%ymm13,%ymm13,%ymm13
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$4,%ymm5,%ymm5,%ymm5
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol16(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpsrld	$20,%ymm6,%ymm3
+	vpslld	$12,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol8(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpslld	$7,%ymm6,%ymm3
+	vpsrld	$25,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpalignr	$12,%ymm14,%ymm14,%ymm14
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$4,%ymm6,%ymm6,%ymm6
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+	addq	16(%rdi),%r10
+	adcq	8+16(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol16(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpsrld	$20,%ymm5,%ymm3
+	vpslld	$12,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol8(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpslld	$7,%ymm5,%ymm3
+	vpsrld	$25,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpalignr	$4,%ymm13,%ymm13,%ymm13
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$12,%ymm5,%ymm5,%ymm5
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol16(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpsrld	$20,%ymm6,%ymm3
+	vpslld	$12,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol8(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpslld	$7,%ymm6,%ymm3
+	vpsrld	$25,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpalignr	$4,%ymm14,%ymm14,%ymm14
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$12,%ymm6,%ymm6,%ymm6
+
+	leaq	32(%rdi),%rdi
+	decq	%rcx
+	jg	1b
+	decq	%r8
+	jge	2b
+	vpaddd	.chacha20_consts(%rip),%ymm2,%ymm2
+	vpaddd	64(%rbp),%ymm6,%ymm6
+	vpaddd	96(%rbp),%ymm10,%ymm10
+	vpaddd	224(%rbp),%ymm14,%ymm14
+	vpaddd	.chacha20_consts(%rip),%ymm1,%ymm1
+	vpaddd	64(%rbp),%ymm5,%ymm5
+	vpaddd	96(%rbp),%ymm9,%ymm9
+	vpaddd	192(%rbp),%ymm13,%ymm13
+	vpaddd	.chacha20_consts(%rip),%ymm0,%ymm0
+	vpaddd	64(%rbp),%ymm4,%ymm4
+	vpaddd	96(%rbp),%ymm8,%ymm8
+	vpaddd	160(%rbp),%ymm12,%ymm12
+	vperm2i128	$0x02,%ymm2,%ymm6,%ymm3
+	vperm2i128	$0x13,%ymm2,%ymm6,%ymm6
+	vperm2i128	$0x02,%ymm10,%ymm14,%ymm2
+	vperm2i128	$0x13,%ymm10,%ymm14,%ymm10
+	vpxor	0+0(%rsi),%ymm3,%ymm3
+	vpxor	32+0(%rsi),%ymm2,%ymm2
+	vpxor	64+0(%rsi),%ymm6,%ymm6
+	vpxor	96+0(%rsi),%ymm10,%ymm10
+	vmovdqu	%ymm3,0+0(%rdi)
+	vmovdqu	%ymm2,32+0(%rdi)
+	vmovdqu	%ymm6,64+0(%rdi)
+	vmovdqu	%ymm10,96+0(%rdi)
+	vperm2i128	$0x02,%ymm1,%ymm5,%ymm3
+	vperm2i128	$0x13,%ymm1,%ymm5,%ymm5
+	vperm2i128	$0x02,%ymm9,%ymm13,%ymm1
+	vperm2i128	$0x13,%ymm9,%ymm13,%ymm9
+	vpxor	0+128(%rsi),%ymm3,%ymm3
+	vpxor	32+128(%rsi),%ymm1,%ymm1
+	vpxor	64+128(%rsi),%ymm5,%ymm5
+	vpxor	96+128(%rsi),%ymm9,%ymm9
+	vmovdqu	%ymm3,0+128(%rdi)
+	vmovdqu	%ymm1,32+128(%rdi)
+	vmovdqu	%ymm5,64+128(%rdi)
+	vmovdqu	%ymm9,96+128(%rdi)
+	vperm2i128	$0x13,%ymm0,%ymm4,%ymm3
+	vperm2i128	$0x02,%ymm0,%ymm4,%ymm0
+	vperm2i128	$0x02,%ymm8,%ymm12,%ymm4
+	vperm2i128	$0x13,%ymm8,%ymm12,%ymm12
+	vmovdqa	%ymm3,%ymm8
+
+	movq	$256,%rcx
+	leaq	256(%rsi),%rsi
+	subq	$256,%rbx
+	jmp	seal_avx2_hash
+
+seal_avx2_tail_512:
+	vmovdqa	.chacha20_consts(%rip),%ymm0
+	vmovdqa	64(%rbp),%ymm4
+	vmovdqa	96(%rbp),%ymm8
+	vmovdqa	%ymm0,%ymm1
+	vmovdqa	%ymm4,%ymm5
+	vmovdqa	%ymm8,%ymm9
+	vmovdqa	%ymm0,%ymm2
+	vmovdqa	%ymm4,%ymm6
+	vmovdqa	%ymm8,%ymm10
+	vmovdqa	%ymm0,%ymm3
+	vmovdqa	%ymm4,%ymm7
+	vmovdqa	%ymm8,%ymm11
+	vmovdqa	.avx2_inc(%rip),%ymm12
+	vpaddd	160(%rbp),%ymm12,%ymm15
+	vpaddd	%ymm15,%ymm12,%ymm14
+	vpaddd	%ymm14,%ymm12,%ymm13
+	vpaddd	%ymm13,%ymm12,%ymm12
+	vmovdqa	%ymm15,256(%rbp)
+	vmovdqa	%ymm14,224(%rbp)
+	vmovdqa	%ymm13,192(%rbp)
+	vmovdqa	%ymm12,160(%rbp)
+
+1:
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rdx
+	movq	%rdx,%r15
+	mulxq	%r10,%r13,%r14
+	mulxq	%r11,%rax,%rdx
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rdx
+	mulxq	%r10,%r10,%rax
+	addq	%r10,%r14
+	mulxq	%r11,%r11,%r9
+	adcq	%r11,%r15
+	adcq	$0,%r9
+	imulq	%r12,%rdx
+	addq	%rax,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%rdi),%rdi
+2:
+	vmovdqa	%ymm8,128(%rbp)
+	vmovdqa	.rol16(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$20,%ymm7,%ymm8
+	vpslld	$32-20,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$20,%ymm6,%ymm8
+	vpslld	$32-20,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$20,%ymm5,%ymm8
+	vpslld	$32-20,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$20,%ymm4,%ymm8
+	vpslld	$32-20,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	.rol8(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	movq	0+0(%rbp),%rdx
+	movq	%rdx,%r15
+	mulxq	%r10,%r13,%r14
+	mulxq	%r11,%rax,%rdx
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$25,%ymm7,%ymm8
+	movq	8+0(%rbp),%rdx
+	mulxq	%r10,%r10,%rax
+	addq	%r10,%r14
+	mulxq	%r11,%r11,%r9
+	adcq	%r11,%r15
+	adcq	$0,%r9
+	imulq	%r12,%rdx
+	vpslld	$32-25,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$25,%ymm6,%ymm8
+	vpslld	$32-25,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$25,%ymm5,%ymm8
+	vpslld	$32-25,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$25,%ymm4,%ymm8
+	vpslld	$32-25,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	128(%rbp),%ymm8
+	vpalignr	$4,%ymm7,%ymm7,%ymm7
+	vpalignr	$8,%ymm11,%ymm11,%ymm11
+	vpalignr	$12,%ymm15,%ymm15,%ymm15
+	vpalignr	$4,%ymm6,%ymm6,%ymm6
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$12,%ymm14,%ymm14,%ymm14
+	vpalignr	$4,%ymm5,%ymm5,%ymm5
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	addq	%rax,%r15
+	adcq	%rdx,%r9
+	vpalignr	$12,%ymm13,%ymm13,%ymm13
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vmovdqa	%ymm8,128(%rbp)
+	vmovdqa	.rol16(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$20,%ymm7,%ymm8
+	vpslld	$32-20,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$20,%ymm6,%ymm8
+	vpslld	$32-20,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$20,%ymm5,%ymm8
+	vpslld	$32-20,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$20,%ymm4,%ymm8
+	vpslld	$32-20,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	addq	16(%rdi),%r10
+	adcq	8+16(%rdi),%r11
+	adcq	$1,%r12
+	vmovdqa	.rol8(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	movq	0+0(%rbp),%rdx
+	movq	%rdx,%r15
+	mulxq	%r10,%r13,%r14
+	mulxq	%r11,%rax,%rdx
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$25,%ymm7,%ymm8
+	vpslld	$32-25,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$25,%ymm6,%ymm8
+	vpslld	$32-25,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$25,%ymm5,%ymm8
+	vpslld	$32-25,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$25,%ymm4,%ymm8
+	vpslld	$32-25,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	128(%rbp),%ymm8
+	vpalignr	$12,%ymm7,%ymm7,%ymm7
+	vpalignr	$8,%ymm11,%ymm11,%ymm11
+	vpalignr	$4,%ymm15,%ymm15,%ymm15
+	vpalignr	$12,%ymm6,%ymm6,%ymm6
+	movq	8+0(%rbp),%rdx
+	mulxq	%r10,%r10,%rax
+	addq	%r10,%r14
+	mulxq	%r11,%r11,%r9
+	adcq	%r11,%r15
+	adcq	$0,%r9
+	imulq	%r12,%rdx
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$4,%ymm14,%ymm14,%ymm14
+	vpalignr	$12,%ymm5,%ymm5,%ymm5
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$4,%ymm13,%ymm13,%ymm13
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+
+
+
+
+
+
+
+
+
+
+
+
+	addq	%rax,%r15
+	adcq	%rdx,%r9
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	32(%rdi),%rdi
+	decq	%rcx
+	jg	1b
+	decq	%r8
+	jge	2b
+	vpaddd	.chacha20_consts(%rip),%ymm3,%ymm3
+	vpaddd	64(%rbp),%ymm7,%ymm7
+	vpaddd	96(%rbp),%ymm11,%ymm11
+	vpaddd	256(%rbp),%ymm15,%ymm15
+	vpaddd	.chacha20_consts(%rip),%ymm2,%ymm2
+	vpaddd	64(%rbp),%ymm6,%ymm6
+	vpaddd	96(%rbp),%ymm10,%ymm10
+	vpaddd	224(%rbp),%ymm14,%ymm14
+	vpaddd	.chacha20_consts(%rip),%ymm1,%ymm1
+	vpaddd	64(%rbp),%ymm5,%ymm5
+	vpaddd	96(%rbp),%ymm9,%ymm9
+	vpaddd	192(%rbp),%ymm13,%ymm13
+	vpaddd	.chacha20_consts(%rip),%ymm0,%ymm0
+	vpaddd	64(%rbp),%ymm4,%ymm4
+	vpaddd	96(%rbp),%ymm8,%ymm8
+	vpaddd	160(%rbp),%ymm12,%ymm12
+
+	vmovdqa	%ymm0,128(%rbp)
+	vperm2i128	$0x02,%ymm3,%ymm7,%ymm0
+	vperm2i128	$0x13,%ymm3,%ymm7,%ymm7
+	vperm2i128	$0x02,%ymm11,%ymm15,%ymm3
+	vperm2i128	$0x13,%ymm11,%ymm15,%ymm11
+	vpxor	0+0(%rsi),%ymm0,%ymm0
+	vpxor	32+0(%rsi),%ymm3,%ymm3
+	vpxor	64+0(%rsi),%ymm7,%ymm7
+	vpxor	96+0(%rsi),%ymm11,%ymm11
+	vmovdqu	%ymm0,0+0(%rdi)
+	vmovdqu	%ymm3,32+0(%rdi)
+	vmovdqu	%ymm7,64+0(%rdi)
+	vmovdqu	%ymm11,96+0(%rdi)
+
+	vmovdqa	128(%rbp),%ymm0
+	vperm2i128	$0x02,%ymm2,%ymm6,%ymm3
+	vperm2i128	$0x13,%ymm2,%ymm6,%ymm6
+	vperm2i128	$0x02,%ymm10,%ymm14,%ymm2
+	vperm2i128	$0x13,%ymm10,%ymm14,%ymm10
+	vpxor	0+128(%rsi),%ymm3,%ymm3
+	vpxor	32+128(%rsi),%ymm2,%ymm2
+	vpxor	64+128(%rsi),%ymm6,%ymm6
+	vpxor	96+128(%rsi),%ymm10,%ymm10
+	vmovdqu	%ymm3,0+128(%rdi)
+	vmovdqu	%ymm2,32+128(%rdi)
+	vmovdqu	%ymm6,64+128(%rdi)
+	vmovdqu	%ymm10,96+128(%rdi)
+	vperm2i128	$0x02,%ymm1,%ymm5,%ymm3
+	vperm2i128	$0x13,%ymm1,%ymm5,%ymm5
+	vperm2i128	$0x02,%ymm9,%ymm13,%ymm1
+	vperm2i128	$0x13,%ymm9,%ymm13,%ymm9
+	vpxor	0+256(%rsi),%ymm3,%ymm3
+	vpxor	32+256(%rsi),%ymm1,%ymm1
+	vpxor	64+256(%rsi),%ymm5,%ymm5
+	vpxor	96+256(%rsi),%ymm9,%ymm9
+	vmovdqu	%ymm3,0+256(%rdi)
+	vmovdqu	%ymm1,32+256(%rdi)
+	vmovdqu	%ymm5,64+256(%rdi)
+	vmovdqu	%ymm9,96+256(%rdi)
+	vperm2i128	$0x13,%ymm0,%ymm4,%ymm3
+	vperm2i128	$0x02,%ymm0,%ymm4,%ymm0
+	vperm2i128	$0x02,%ymm8,%ymm12,%ymm4
+	vperm2i128	$0x13,%ymm8,%ymm12,%ymm12
+	vmovdqa	%ymm3,%ymm8
+
+	movq	$384,%rcx
+	leaq	384(%rsi),%rsi
+	subq	$384,%rbx
+	jmp	seal_avx2_hash
+
+seal_avx2_320:
+	vmovdqa	%ymm0,%ymm1
+	vmovdqa	%ymm0,%ymm2
+	vmovdqa	%ymm4,%ymm5
+	vmovdqa	%ymm4,%ymm6
+	vmovdqa	%ymm8,%ymm9
+	vmovdqa	%ymm8,%ymm10
+	vpaddd	.avx2_inc(%rip),%ymm12,%ymm13
+	vpaddd	.avx2_inc(%rip),%ymm13,%ymm14
+	vmovdqa	%ymm4,%ymm7
+	vmovdqa	%ymm8,%ymm11
+	vmovdqa	%ymm12,160(%rbp)
+	vmovdqa	%ymm13,192(%rbp)
+	vmovdqa	%ymm14,224(%rbp)
+	movq	$10,%r10
+1:
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol16(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpsrld	$20,%ymm5,%ymm3
+	vpslld	$12,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol8(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpslld	$7,%ymm5,%ymm3
+	vpsrld	$25,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpalignr	$12,%ymm13,%ymm13,%ymm13
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$4,%ymm5,%ymm5,%ymm5
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol16(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpsrld	$20,%ymm6,%ymm3
+	vpslld	$12,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol8(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpslld	$7,%ymm6,%ymm3
+	vpsrld	$25,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpalignr	$12,%ymm14,%ymm14,%ymm14
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$4,%ymm6,%ymm6,%ymm6
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol16(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpsrld	$20,%ymm5,%ymm3
+	vpslld	$12,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol8(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpslld	$7,%ymm5,%ymm3
+	vpsrld	$25,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpalignr	$4,%ymm13,%ymm13,%ymm13
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$12,%ymm5,%ymm5,%ymm5
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol16(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpsrld	$20,%ymm6,%ymm3
+	vpslld	$12,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol8(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpslld	$7,%ymm6,%ymm3
+	vpsrld	$25,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpalignr	$4,%ymm14,%ymm14,%ymm14
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$12,%ymm6,%ymm6,%ymm6
+
+	decq	%r10
+	jne	1b
+	vpaddd	.chacha20_consts(%rip),%ymm0,%ymm0
+	vpaddd	.chacha20_consts(%rip),%ymm1,%ymm1
+	vpaddd	.chacha20_consts(%rip),%ymm2,%ymm2
+	vpaddd	%ymm7,%ymm4,%ymm4
+	vpaddd	%ymm7,%ymm5,%ymm5
+	vpaddd	%ymm7,%ymm6,%ymm6
+	vpaddd	%ymm11,%ymm8,%ymm8
+	vpaddd	%ymm11,%ymm9,%ymm9
+	vpaddd	%ymm11,%ymm10,%ymm10
+	vpaddd	160(%rbp),%ymm12,%ymm12
+	vpaddd	192(%rbp),%ymm13,%ymm13
+	vpaddd	224(%rbp),%ymm14,%ymm14
+	vperm2i128	$0x02,%ymm0,%ymm4,%ymm3
+
+	vpand	.clamp(%rip),%ymm3,%ymm3
+	vmovdqa	%ymm3,0(%rbp)
+
+	vperm2i128	$0x13,%ymm0,%ymm4,%ymm0
+	vperm2i128	$0x13,%ymm8,%ymm12,%ymm4
+	vperm2i128	$0x02,%ymm1,%ymm5,%ymm8
+	vperm2i128	$0x02,%ymm9,%ymm13,%ymm12
+	vperm2i128	$0x13,%ymm1,%ymm5,%ymm1
+	vperm2i128	$0x13,%ymm9,%ymm13,%ymm5
+	vperm2i128	$0x02,%ymm2,%ymm6,%ymm9
+	vperm2i128	$0x02,%ymm10,%ymm14,%ymm13
+	vperm2i128	$0x13,%ymm2,%ymm6,%ymm2
+	vperm2i128	$0x13,%ymm10,%ymm14,%ymm6
+	jmp	seal_avx2_short
+
+seal_avx2_192:
+	vmovdqa	%ymm0,%ymm1
+	vmovdqa	%ymm0,%ymm2
+	vmovdqa	%ymm4,%ymm5
+	vmovdqa	%ymm4,%ymm6
+	vmovdqa	%ymm8,%ymm9
+	vmovdqa	%ymm8,%ymm10
+	vpaddd	.avx2_inc(%rip),%ymm12,%ymm13
+	vmovdqa	%ymm12,%ymm11
+	vmovdqa	%ymm13,%ymm15
+	movq	$10,%r10
+1:
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol16(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpsrld	$20,%ymm5,%ymm3
+	vpslld	$12,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol8(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpslld	$7,%ymm5,%ymm3
+	vpsrld	$25,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpalignr	$12,%ymm13,%ymm13,%ymm13
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$4,%ymm5,%ymm5,%ymm5
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol16(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpsrld	$20,%ymm5,%ymm3
+	vpslld	$12,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol8(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpslld	$7,%ymm5,%ymm3
+	vpsrld	$25,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpalignr	$4,%ymm13,%ymm13,%ymm13
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$12,%ymm5,%ymm5,%ymm5
+
+	decq	%r10
+	jne	1b
+	vpaddd	%ymm2,%ymm0,%ymm0
+	vpaddd	%ymm2,%ymm1,%ymm1
+	vpaddd	%ymm6,%ymm4,%ymm4
+	vpaddd	%ymm6,%ymm5,%ymm5
+	vpaddd	%ymm10,%ymm8,%ymm8
+	vpaddd	%ymm10,%ymm9,%ymm9
+	vpaddd	%ymm11,%ymm12,%ymm12
+	vpaddd	%ymm15,%ymm13,%ymm13
+	vperm2i128	$0x02,%ymm0,%ymm4,%ymm3
+
+	vpand	.clamp(%rip),%ymm3,%ymm3
+	vmovdqa	%ymm3,0(%rbp)
+
+	vperm2i128	$0x13,%ymm0,%ymm4,%ymm0
+	vperm2i128	$0x13,%ymm8,%ymm12,%ymm4
+	vperm2i128	$0x02,%ymm1,%ymm5,%ymm8
+	vperm2i128	$0x02,%ymm9,%ymm13,%ymm12
+	vperm2i128	$0x13,%ymm1,%ymm5,%ymm1
+	vperm2i128	$0x13,%ymm9,%ymm13,%ymm5
+seal_avx2_short:
+	movq	%r8,%r8
+	call	poly_hash_ad_internal
+	xorq	%rcx,%rcx
+seal_avx2_hash:
+	cmpq	$16,%rcx
+	jb	seal_avx2_short_loop
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	subq	$16,%rcx
+	addq	$16,%rdi
+	jmp	seal_avx2_hash
+seal_avx2_short_loop:
+	cmpq	$32,%rbx
+	jb	seal_avx2_short_tail
+	subq	$32,%rbx
+
+	vpxor	(%rsi),%ymm0,%ymm0
+	vmovdqu	%ymm0,(%rdi)
+	leaq	32(%rsi),%rsi
+
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	addq	16(%rdi),%r10
+	adcq	8+16(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	32(%rdi),%rdi
+
+	vmovdqa	%ymm4,%ymm0
+	vmovdqa	%ymm8,%ymm4
+	vmovdqa	%ymm12,%ymm8
+	vmovdqa	%ymm1,%ymm12
+	vmovdqa	%ymm5,%ymm1
+	vmovdqa	%ymm9,%ymm5
+	vmovdqa	%ymm13,%ymm9
+	vmovdqa	%ymm2,%ymm13
+	vmovdqa	%ymm6,%ymm2
+	jmp	seal_avx2_short_loop
+seal_avx2_short_tail:
+	cmpq	$16,%rbx
+	jb	1f
+	subq	$16,%rbx
+	vpxor	(%rsi),%xmm0,%xmm3
+	vmovdqu	%xmm3,(%rdi)
+	leaq	16(%rsi),%rsi
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%rdi),%rdi
+	vextracti128	$1,%ymm0,%xmm0
+1:
+	vzeroupper
+	jmp	seal_sse_tail_16
+.cfi_endproc	
+#endif
diff --git a/linux-x86_64/crypto/ec/p256-x86_64-asm.S b/linux-x86_64/crypto/ec/p256-x86_64-asm.S
index 2884c69..785f269 100644
--- a/linux-x86_64/crypto/ec/p256-x86_64-asm.S
+++ b/linux-x86_64/crypto/ec/p256-x86_64-asm.S
@@ -17,47 +17,6 @@
 .LONE_mont:
 .quad	0x0000000000000001, 0xffffffff00000000, 0xffffffffffffffff, 0x00000000fffffffe
 
-.type	ecp_nistz256_mul_by_2,@function
-.align	64
-ecp_nistz256_mul_by_2:
-	pushq	%r12
-	pushq	%r13
-
-	movq	0(%rsi),%r8
-	movq	8(%rsi),%r9
-	addq	%r8,%r8
-	movq	16(%rsi),%r10
-	adcq	%r9,%r9
-	movq	24(%rsi),%r11
-	leaq	.Lpoly(%rip),%rsi
-	movq	%r8,%rax
-	adcq	%r10,%r10
-	adcq	%r11,%r11
-	movq	%r9,%rdx
-	sbbq	%r13,%r13
-
-	subq	0(%rsi),%r8
-	movq	%r10,%rcx
-	sbbq	8(%rsi),%r9
-	sbbq	16(%rsi),%r10
-	movq	%r11,%r12
-	sbbq	24(%rsi),%r11
-	testq	%r13,%r13
-
-	cmovzq	%rax,%r8
-	cmovzq	%rdx,%r9
-	movq	%r8,0(%rdi)
-	cmovzq	%rcx,%r10
-	movq	%r9,8(%rdi)
-	cmovzq	%r12,%r11
-	movq	%r10,16(%rdi)
-	movq	%r11,24(%rdi)
-
-	popq	%r13
-	popq	%r12
-	.byte	0xf3,0xc3
-.size	ecp_nistz256_mul_by_2,.-ecp_nistz256_mul_by_2
-
 
 
 .globl	ecp_nistz256_neg
@@ -553,101 +512,6 @@
 .size	__ecp_nistz256_sqr_montq,.-__ecp_nistz256_sqr_montq
 
 
-
-
-
-
-.globl	ecp_nistz256_from_mont
-.hidden ecp_nistz256_from_mont
-.type	ecp_nistz256_from_mont,@function
-.align	32
-ecp_nistz256_from_mont:
-	pushq	%r12
-	pushq	%r13
-
-	movq	0(%rsi),%rax
-	movq	.Lpoly+24(%rip),%r13
-	movq	8(%rsi),%r9
-	movq	16(%rsi),%r10
-	movq	24(%rsi),%r11
-	movq	%rax,%r8
-	movq	.Lpoly+8(%rip),%r12
-
-
-
-	movq	%rax,%rcx
-	shlq	$32,%r8
-	mulq	%r13
-	shrq	$32,%rcx
-	addq	%r8,%r9
-	adcq	%rcx,%r10
-	adcq	%rax,%r11
-	movq	%r9,%rax
-	adcq	$0,%rdx
-
-
-
-	movq	%r9,%rcx
-	shlq	$32,%r9
-	movq	%rdx,%r8
-	mulq	%r13
-	shrq	$32,%rcx
-	addq	%r9,%r10
-	adcq	%rcx,%r11
-	adcq	%rax,%r8
-	movq	%r10,%rax
-	adcq	$0,%rdx
-
-
-
-	movq	%r10,%rcx
-	shlq	$32,%r10
-	movq	%rdx,%r9
-	mulq	%r13
-	shrq	$32,%rcx
-	addq	%r10,%r11
-	adcq	%rcx,%r8
-	adcq	%rax,%r9
-	movq	%r11,%rax
-	adcq	$0,%rdx
-
-
-
-	movq	%r11,%rcx
-	shlq	$32,%r11
-	movq	%rdx,%r10
-	mulq	%r13
-	shrq	$32,%rcx
-	addq	%r11,%r8
-	adcq	%rcx,%r9
-	movq	%r8,%rcx
-	adcq	%rax,%r10
-	movq	%r9,%rsi
-	adcq	$0,%rdx
-
-	subq	$-1,%r8
-	movq	%r10,%rax
-	sbbq	%r12,%r9
-	sbbq	$0,%r10
-	movq	%rdx,%r11
-	sbbq	%r13,%rdx
-	sbbq	%r13,%r13
-
-	cmovnzq	%rcx,%r8
-	cmovnzq	%rsi,%r9
-	movq	%r8,0(%rdi)
-	cmovnzq	%rax,%r10
-	movq	%r9,8(%rdi)
-	cmovzq	%rdx,%r11
-	movq	%r10,16(%rdi)
-	movq	%r11,24(%rdi)
-
-	popq	%r13
-	popq	%r12
-	.byte	0xf3,0xc3
-.size	ecp_nistz256_from_mont,.-ecp_nistz256_from_mont
-
-
 .globl	ecp_nistz256_select_w5
 .hidden ecp_nistz256_select_w5
 .type	ecp_nistz256_select_w5,@function
@@ -765,13 +629,14 @@
 .type	__ecp_nistz256_add_toq,@function
 .align	32
 __ecp_nistz256_add_toq:
+	xorq	%r11,%r11
 	addq	0(%rbx),%r12
 	adcq	8(%rbx),%r13
 	movq	%r12,%rax
 	adcq	16(%rbx),%r8
 	adcq	24(%rbx),%r9
 	movq	%r13,%rbp
-	sbbq	%r11,%r11
+	adcq	$0,%r11
 
 	subq	$-1,%r12
 	movq	%r8,%rcx
@@ -779,14 +644,14 @@
 	sbbq	$0,%r8
 	movq	%r9,%r10
 	sbbq	%r15,%r9
-	testq	%r11,%r11
+	sbbq	$0,%r11
 
-	cmovzq	%rax,%r12
-	cmovzq	%rbp,%r13
+	cmovcq	%rax,%r12
+	cmovcq	%rbp,%r13
 	movq	%r12,0(%rdi)
-	cmovzq	%rcx,%r8
+	cmovcq	%rcx,%r8
 	movq	%r13,8(%rdi)
-	cmovzq	%r10,%r9
+	cmovcq	%r10,%r9
 	movq	%r8,16(%rdi)
 	movq	%r9,24(%rdi)
 
@@ -854,13 +719,14 @@
 .type	__ecp_nistz256_mul_by_2q,@function
 .align	32
 __ecp_nistz256_mul_by_2q:
+	xorq	%r11,%r11
 	addq	%r12,%r12
 	adcq	%r13,%r13
 	movq	%r12,%rax
 	adcq	%r8,%r8
 	adcq	%r9,%r9
 	movq	%r13,%rbp
-	sbbq	%r11,%r11
+	adcq	$0,%r11
 
 	subq	$-1,%r12
 	movq	%r8,%rcx
@@ -868,14 +734,14 @@
 	sbbq	$0,%r8
 	movq	%r9,%r10
 	sbbq	%r15,%r9
-	testq	%r11,%r11
+	sbbq	$0,%r11
 
-	cmovzq	%rax,%r12
-	cmovzq	%rbp,%r13
+	cmovcq	%rax,%r12
+	cmovcq	%rbp,%r13
 	movq	%r12,0(%rdi)
-	cmovzq	%rcx,%r8
+	cmovcq	%rcx,%r8
 	movq	%r13,8(%rdi)
-	cmovzq	%r10,%r9
+	cmovcq	%r10,%r9
 	movq	%r8,16(%rdi)
 	movq	%r9,24(%rdi)
 
@@ -894,6 +760,7 @@
 	pushq	%r15
 	subq	$160+8,%rsp
 
+.Lpoint_double_shortcutq:
 	movdqu	0(%rsi),%xmm0
 	movq	%rsi,%rbx
 	movdqu	16(%rsi),%xmm1
@@ -1106,16 +973,14 @@
 	movq	%rdx,%rsi
 	movdqa	%xmm0,384(%rsp)
 	movdqa	%xmm1,384+16(%rsp)
-	por	%xmm0,%xmm1
 	movdqa	%xmm2,416(%rsp)
 	movdqa	%xmm3,416+16(%rsp)
-	por	%xmm2,%xmm3
 	movdqa	%xmm4,448(%rsp)
 	movdqa	%xmm5,448+16(%rsp)
-	por	%xmm1,%xmm3
+	por	%xmm4,%xmm5
 
 	movdqu	0(%rsi),%xmm0
-	pshufd	$177,%xmm3,%xmm5
+	pshufd	$0xb1,%xmm5,%xmm3
 	movdqu	16(%rsi),%xmm1
 	movdqu	32(%rsi),%xmm2
 	por	%xmm3,%xmm5
@@ -1125,16 +990,16 @@
 	movq	64+16(%rsi),%r15
 	movq	64+24(%rsi),%r8
 	movdqa	%xmm0,480(%rsp)
-	pshufd	$30,%xmm5,%xmm4
+	pshufd	$0x1e,%xmm5,%xmm4
 	movdqa	%xmm1,480+16(%rsp)
-	por	%xmm0,%xmm1
-.byte	102,72,15,110,199
+	movdqu	64(%rsi),%xmm0
+	movdqu	80(%rsi),%xmm1
 	movdqa	%xmm2,512(%rsp)
 	movdqa	%xmm3,512+16(%rsp)
-	por	%xmm2,%xmm3
 	por	%xmm4,%xmm5
 	pxor	%xmm4,%xmm4
-	por	%xmm1,%xmm3
+	por	%xmm0,%xmm1
+.byte	102,72,15,110,199
 
 	leaq	64-0(%rsi),%rsi
 	movq	%rax,544+0(%rsp)
@@ -1145,10 +1010,10 @@
 	call	__ecp_nistz256_sqr_montq
 
 	pcmpeqd	%xmm4,%xmm5
-	pshufd	$177,%xmm3,%xmm4
-	por	%xmm3,%xmm4
+	pshufd	$0xb1,%xmm1,%xmm4
+	por	%xmm1,%xmm4
 	pshufd	$0,%xmm5,%xmm5
-	pshufd	$30,%xmm4,%xmm3
+	pshufd	$0x1e,%xmm4,%xmm3
 	por	%xmm3,%xmm4
 	pxor	%xmm3,%xmm3
 	pcmpeqd	%xmm3,%xmm4
@@ -1157,6 +1022,7 @@
 	movq	64+8(%rbx),%r14
 	movq	64+16(%rbx),%r15
 	movq	64+24(%rbx),%r8
+.byte	102,72,15,110,203
 
 	leaq	64-0(%rbx),%rsi
 	leaq	32(%rsp),%rdi
@@ -1248,7 +1114,7 @@
 	testq	%r8,%r8
 	jnz	.Ladd_proceedq
 	testq	%r9,%r9
-	jz	.Ladd_proceedq
+	jz	.Ladd_doubleq
 
 .byte	102,72,15,126,199
 	pxor	%xmm0,%xmm0
@@ -1261,6 +1127,13 @@
 	jmp	.Ladd_doneq
 
 .align	32
+.Ladd_doubleq:
+.byte	102,72,15,126,206
+.byte	102,72,15,126,199
+	addq	$416,%rsp
+	jmp	.Lpoint_double_shortcutq
+
+.align	32
 .Ladd_proceedq:
 	movq	0+64(%rsp),%rax
 	movq	8+64(%rsp),%r14
@@ -1321,6 +1194,7 @@
 
 
 
+	xorq	%r11,%r11
 	addq	%r12,%r12
 	leaq	96(%rsp),%rsi
 	adcq	%r13,%r13
@@ -1328,7 +1202,7 @@
 	adcq	%r8,%r8
 	adcq	%r9,%r9
 	movq	%r13,%rbp
-	sbbq	%r11,%r11
+	adcq	$0,%r11
 
 	subq	$-1,%r12
 	movq	%r8,%rcx
@@ -1336,15 +1210,15 @@
 	sbbq	$0,%r8
 	movq	%r9,%r10
 	sbbq	%r15,%r9
-	testq	%r11,%r11
+	sbbq	$0,%r11
 
-	cmovzq	%rax,%r12
+	cmovcq	%rax,%r12
 	movq	0(%rsi),%rax
-	cmovzq	%rbp,%r13
+	cmovcq	%rbp,%r13
 	movq	8(%rsi),%rbp
-	cmovzq	%rcx,%r8
+	cmovcq	%rcx,%r8
 	movq	16(%rsi),%rcx
-	cmovzq	%r10,%r9
+	cmovcq	%r10,%r9
 	movq	24(%rsi),%r10
 
 	call	__ecp_nistz256_subq
@@ -1499,22 +1373,20 @@
 	movq	64+24(%rsi),%r8
 	movdqa	%xmm0,320(%rsp)
 	movdqa	%xmm1,320+16(%rsp)
-	por	%xmm0,%xmm1
 	movdqa	%xmm2,352(%rsp)
 	movdqa	%xmm3,352+16(%rsp)
-	por	%xmm2,%xmm3
 	movdqa	%xmm4,384(%rsp)
 	movdqa	%xmm5,384+16(%rsp)
-	por	%xmm1,%xmm3
+	por	%xmm4,%xmm5
 
 	movdqu	0(%rbx),%xmm0
-	pshufd	$177,%xmm3,%xmm5
+	pshufd	$0xb1,%xmm5,%xmm3
 	movdqu	16(%rbx),%xmm1
 	movdqu	32(%rbx),%xmm2
 	por	%xmm3,%xmm5
 	movdqu	48(%rbx),%xmm3
 	movdqa	%xmm0,416(%rsp)
-	pshufd	$30,%xmm5,%xmm4
+	pshufd	$0x1e,%xmm5,%xmm4
 	movdqa	%xmm1,416+16(%rsp)
 	por	%xmm0,%xmm1
 .byte	102,72,15,110,199
@@ -1530,13 +1402,13 @@
 	call	__ecp_nistz256_sqr_montq
 
 	pcmpeqd	%xmm4,%xmm5
-	pshufd	$177,%xmm3,%xmm4
+	pshufd	$0xb1,%xmm3,%xmm4
 	movq	0(%rbx),%rax
 
 	movq	%r12,%r9
 	por	%xmm3,%xmm4
 	pshufd	$0,%xmm5,%xmm5
-	pshufd	$30,%xmm4,%xmm3
+	pshufd	$0x1e,%xmm4,%xmm3
 	movq	%r13,%r10
 	por	%xmm3,%xmm4
 	pxor	%xmm3,%xmm3
@@ -1626,6 +1498,7 @@
 
 
 
+	xorq	%r11,%r11
 	addq	%r12,%r12
 	leaq	192(%rsp),%rsi
 	adcq	%r13,%r13
@@ -1633,7 +1506,7 @@
 	adcq	%r8,%r8
 	adcq	%r9,%r9
 	movq	%r13,%rbp
-	sbbq	%r11,%r11
+	adcq	$0,%r11
 
 	subq	$-1,%r12
 	movq	%r8,%rcx
@@ -1641,15 +1514,15 @@
 	sbbq	$0,%r8
 	movq	%r9,%r10
 	sbbq	%r15,%r9
-	testq	%r11,%r11
+	sbbq	$0,%r11
 
-	cmovzq	%rax,%r12
+	cmovcq	%rax,%r12
 	movq	0(%rsi),%rax
-	cmovzq	%rbp,%r13
+	cmovcq	%rbp,%r13
 	movq	8(%rsi),%rbp
-	cmovzq	%rcx,%r8
+	cmovcq	%rcx,%r8
 	movq	16(%rsi),%rcx
-	cmovzq	%r10,%r9
+	cmovcq	%r10,%r9
 	movq	24(%rsi),%r10
 
 	call	__ecp_nistz256_subq
diff --git a/linux-x86_64/crypto/md5/md5-x86_64.S b/linux-x86_64/crypto/md5/md5-x86_64.S
index 7644689..05369e2 100644
--- a/linux-x86_64/crypto/md5/md5-x86_64.S
+++ b/linux-x86_64/crypto/md5/md5-x86_64.S
@@ -495,14 +495,14 @@
 	movl	%ecx,%r11d
 	addl	%ecx,%ebx
 	movl	0(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	xorl	%edx,%r11d
 	leal	-198630844(%rax,%r10,1),%eax
 	orl	%ebx,%r11d
 	xorl	%ecx,%r11d
 	addl	%r11d,%eax
 	movl	28(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	roll	$6,%eax
 	xorl	%ecx,%r11d
 	addl	%ebx,%eax
@@ -511,7 +511,7 @@
 	xorl	%ebx,%r11d
 	addl	%r11d,%edx
 	movl	56(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	roll	$10,%edx
 	xorl	%ebx,%r11d
 	addl	%eax,%edx
@@ -520,7 +520,7 @@
 	xorl	%eax,%r11d
 	addl	%r11d,%ecx
 	movl	20(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	roll	$15,%ecx
 	xorl	%eax,%r11d
 	addl	%edx,%ecx
@@ -529,7 +529,7 @@
 	xorl	%edx,%r11d
 	addl	%r11d,%ebx
 	movl	48(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	roll	$21,%ebx
 	xorl	%edx,%r11d
 	addl	%ecx,%ebx
@@ -538,7 +538,7 @@
 	xorl	%ecx,%r11d
 	addl	%r11d,%eax
 	movl	12(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	roll	$6,%eax
 	xorl	%ecx,%r11d
 	addl	%ebx,%eax
@@ -547,7 +547,7 @@
 	xorl	%ebx,%r11d
 	addl	%r11d,%edx
 	movl	40(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	roll	$10,%edx
 	xorl	%ebx,%r11d
 	addl	%eax,%edx
@@ -556,7 +556,7 @@
 	xorl	%eax,%r11d
 	addl	%r11d,%ecx
 	movl	4(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	roll	$15,%ecx
 	xorl	%eax,%r11d
 	addl	%edx,%ecx
@@ -565,7 +565,7 @@
 	xorl	%edx,%r11d
 	addl	%r11d,%ebx
 	movl	32(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	roll	$21,%ebx
 	xorl	%edx,%r11d
 	addl	%ecx,%ebx
@@ -574,7 +574,7 @@
 	xorl	%ecx,%r11d
 	addl	%r11d,%eax
 	movl	60(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	roll	$6,%eax
 	xorl	%ecx,%r11d
 	addl	%ebx,%eax
@@ -583,7 +583,7 @@
 	xorl	%ebx,%r11d
 	addl	%r11d,%edx
 	movl	24(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	roll	$10,%edx
 	xorl	%ebx,%r11d
 	addl	%eax,%edx
@@ -592,7 +592,7 @@
 	xorl	%eax,%r11d
 	addl	%r11d,%ecx
 	movl	52(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	roll	$15,%ecx
 	xorl	%eax,%r11d
 	addl	%edx,%ecx
@@ -601,7 +601,7 @@
 	xorl	%edx,%r11d
 	addl	%r11d,%ebx
 	movl	16(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	roll	$21,%ebx
 	xorl	%edx,%r11d
 	addl	%ecx,%ebx
@@ -610,7 +610,7 @@
 	xorl	%ecx,%r11d
 	addl	%r11d,%eax
 	movl	44(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	roll	$6,%eax
 	xorl	%ecx,%r11d
 	addl	%ebx,%eax
@@ -619,7 +619,7 @@
 	xorl	%ebx,%r11d
 	addl	%r11d,%edx
 	movl	8(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	roll	$10,%edx
 	xorl	%ebx,%r11d
 	addl	%eax,%edx
@@ -628,7 +628,7 @@
 	xorl	%eax,%r11d
 	addl	%r11d,%ecx
 	movl	36(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	roll	$15,%ecx
 	xorl	%eax,%r11d
 	addl	%edx,%ecx
@@ -637,7 +637,7 @@
 	xorl	%edx,%r11d
 	addl	%r11d,%ebx
 	movl	0(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	roll	$21,%ebx
 	xorl	%edx,%r11d
 	addl	%ecx,%ebx
diff --git a/linux-x86_64/crypto/modes/aesni-gcm-x86_64.S b/linux-x86_64/crypto/modes/aesni-gcm-x86_64.S
index f01692e..9953e4c 100644
--- a/linux-x86_64/crypto/modes/aesni-gcm-x86_64.S
+++ b/linux-x86_64/crypto/modes/aesni-gcm-x86_64.S
@@ -1,19 +1,798 @@
 #if defined(__x86_64__)
 .text	
 
-.globl	aesni_gcm_encrypt
-.hidden aesni_gcm_encrypt
-.type	aesni_gcm_encrypt,@function
-aesni_gcm_encrypt:
-	xorl	%eax,%eax
-	.byte	0xf3,0xc3
-.size	aesni_gcm_encrypt,.-aesni_gcm_encrypt
+.type	_aesni_ctr32_ghash_6x,@function
+.align	32
+_aesni_ctr32_ghash_6x:
+	vmovdqu	32(%r11),%xmm2
+	subq	$6,%rdx
+	vpxor	%xmm4,%xmm4,%xmm4
+	vmovdqu	0-128(%rcx),%xmm15
+	vpaddb	%xmm2,%xmm1,%xmm10
+	vpaddb	%xmm2,%xmm10,%xmm11
+	vpaddb	%xmm2,%xmm11,%xmm12
+	vpaddb	%xmm2,%xmm12,%xmm13
+	vpaddb	%xmm2,%xmm13,%xmm14
+	vpxor	%xmm15,%xmm1,%xmm9
+	vmovdqu	%xmm4,16+8(%rsp)
+	jmp	.Loop6x
 
+.align	32
+.Loop6x:
+	addl	$100663296,%ebx
+	jc	.Lhandle_ctr32
+	vmovdqu	0-32(%r9),%xmm3
+	vpaddb	%xmm2,%xmm14,%xmm1
+	vpxor	%xmm15,%xmm10,%xmm10
+	vpxor	%xmm15,%xmm11,%xmm11
+
+.Lresume_ctr32:
+	vmovdqu	%xmm1,(%r8)
+	vpclmulqdq	$0x10,%xmm3,%xmm7,%xmm5
+	vpxor	%xmm15,%xmm12,%xmm12
+	vmovups	16-128(%rcx),%xmm2
+	vpclmulqdq	$0x01,%xmm3,%xmm7,%xmm6
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+	xorq	%r12,%r12
+	cmpq	%r14,%r15
+
+	vaesenc	%xmm2,%xmm9,%xmm9
+	vmovdqu	48+8(%rsp),%xmm0
+	vpxor	%xmm15,%xmm13,%xmm13
+	vpclmulqdq	$0x00,%xmm3,%xmm7,%xmm1
+	vaesenc	%xmm2,%xmm10,%xmm10
+	vpxor	%xmm15,%xmm14,%xmm14
+	setnc	%r12b
+	vpclmulqdq	$0x11,%xmm3,%xmm7,%xmm7
+	vaesenc	%xmm2,%xmm11,%xmm11
+	vmovdqu	16-32(%r9),%xmm3
+	negq	%r12
+	vaesenc	%xmm2,%xmm12,%xmm12
+	vpxor	%xmm5,%xmm6,%xmm6
+	vpclmulqdq	$0x00,%xmm3,%xmm0,%xmm5
+	vpxor	%xmm4,%xmm8,%xmm8
+	vaesenc	%xmm2,%xmm13,%xmm13
+	vpxor	%xmm5,%xmm1,%xmm4
+	andq	$0x60,%r12
+	vmovups	32-128(%rcx),%xmm15
+	vpclmulqdq	$0x10,%xmm3,%xmm0,%xmm1
+	vaesenc	%xmm2,%xmm14,%xmm14
+
+	vpclmulqdq	$0x01,%xmm3,%xmm0,%xmm2
+	leaq	(%r14,%r12,1),%r14
+	vaesenc	%xmm15,%xmm9,%xmm9
+	vpxor	16+8(%rsp),%xmm8,%xmm8
+	vpclmulqdq	$0x11,%xmm3,%xmm0,%xmm3
+	vmovdqu	64+8(%rsp),%xmm0
+	vaesenc	%xmm15,%xmm10,%xmm10
+	movbeq	88(%r14),%r13
+	vaesenc	%xmm15,%xmm11,%xmm11
+	movbeq	80(%r14),%r12
+	vaesenc	%xmm15,%xmm12,%xmm12
+	movq	%r13,32+8(%rsp)
+	vaesenc	%xmm15,%xmm13,%xmm13
+	movq	%r12,40+8(%rsp)
+	vmovdqu	48-32(%r9),%xmm5
+	vaesenc	%xmm15,%xmm14,%xmm14
+
+	vmovups	48-128(%rcx),%xmm15
+	vpxor	%xmm1,%xmm6,%xmm6
+	vpclmulqdq	$0x00,%xmm5,%xmm0,%xmm1
+	vaesenc	%xmm15,%xmm9,%xmm9
+	vpxor	%xmm2,%xmm6,%xmm6
+	vpclmulqdq	$0x10,%xmm5,%xmm0,%xmm2
+	vaesenc	%xmm15,%xmm10,%xmm10
+	vpxor	%xmm3,%xmm7,%xmm7
+	vpclmulqdq	$0x01,%xmm5,%xmm0,%xmm3
+	vaesenc	%xmm15,%xmm11,%xmm11
+	vpclmulqdq	$0x11,%xmm5,%xmm0,%xmm5
+	vmovdqu	80+8(%rsp),%xmm0
+	vaesenc	%xmm15,%xmm12,%xmm12
+	vaesenc	%xmm15,%xmm13,%xmm13
+	vpxor	%xmm1,%xmm4,%xmm4
+	vmovdqu	64-32(%r9),%xmm1
+	vaesenc	%xmm15,%xmm14,%xmm14
+
+	vmovups	64-128(%rcx),%xmm15
+	vpxor	%xmm2,%xmm6,%xmm6
+	vpclmulqdq	$0x00,%xmm1,%xmm0,%xmm2
+	vaesenc	%xmm15,%xmm9,%xmm9
+	vpxor	%xmm3,%xmm6,%xmm6
+	vpclmulqdq	$0x10,%xmm1,%xmm0,%xmm3
+	vaesenc	%xmm15,%xmm10,%xmm10
+	movbeq	72(%r14),%r13
+	vpxor	%xmm5,%xmm7,%xmm7
+	vpclmulqdq	$0x01,%xmm1,%xmm0,%xmm5
+	vaesenc	%xmm15,%xmm11,%xmm11
+	movbeq	64(%r14),%r12
+	vpclmulqdq	$0x11,%xmm1,%xmm0,%xmm1
+	vmovdqu	96+8(%rsp),%xmm0
+	vaesenc	%xmm15,%xmm12,%xmm12
+	movq	%r13,48+8(%rsp)
+	vaesenc	%xmm15,%xmm13,%xmm13
+	movq	%r12,56+8(%rsp)
+	vpxor	%xmm2,%xmm4,%xmm4
+	vmovdqu	96-32(%r9),%xmm2
+	vaesenc	%xmm15,%xmm14,%xmm14
+
+	vmovups	80-128(%rcx),%xmm15
+	vpxor	%xmm3,%xmm6,%xmm6
+	vpclmulqdq	$0x00,%xmm2,%xmm0,%xmm3
+	vaesenc	%xmm15,%xmm9,%xmm9
+	vpxor	%xmm5,%xmm6,%xmm6
+	vpclmulqdq	$0x10,%xmm2,%xmm0,%xmm5
+	vaesenc	%xmm15,%xmm10,%xmm10
+	movbeq	56(%r14),%r13
+	vpxor	%xmm1,%xmm7,%xmm7
+	vpclmulqdq	$0x01,%xmm2,%xmm0,%xmm1
+	vpxor	112+8(%rsp),%xmm8,%xmm8
+	vaesenc	%xmm15,%xmm11,%xmm11
+	movbeq	48(%r14),%r12
+	vpclmulqdq	$0x11,%xmm2,%xmm0,%xmm2
+	vaesenc	%xmm15,%xmm12,%xmm12
+	movq	%r13,64+8(%rsp)
+	vaesenc	%xmm15,%xmm13,%xmm13
+	movq	%r12,72+8(%rsp)
+	vpxor	%xmm3,%xmm4,%xmm4
+	vmovdqu	112-32(%r9),%xmm3
+	vaesenc	%xmm15,%xmm14,%xmm14
+
+	vmovups	96-128(%rcx),%xmm15
+	vpxor	%xmm5,%xmm6,%xmm6
+	vpclmulqdq	$0x10,%xmm3,%xmm8,%xmm5
+	vaesenc	%xmm15,%xmm9,%xmm9
+	vpxor	%xmm1,%xmm6,%xmm6
+	vpclmulqdq	$0x01,%xmm3,%xmm8,%xmm1
+	vaesenc	%xmm15,%xmm10,%xmm10
+	movbeq	40(%r14),%r13
+	vpxor	%xmm2,%xmm7,%xmm7
+	vpclmulqdq	$0x00,%xmm3,%xmm8,%xmm2
+	vaesenc	%xmm15,%xmm11,%xmm11
+	movbeq	32(%r14),%r12
+	vpclmulqdq	$0x11,%xmm3,%xmm8,%xmm8
+	vaesenc	%xmm15,%xmm12,%xmm12
+	movq	%r13,80+8(%rsp)
+	vaesenc	%xmm15,%xmm13,%xmm13
+	movq	%r12,88+8(%rsp)
+	vpxor	%xmm5,%xmm6,%xmm6
+	vaesenc	%xmm15,%xmm14,%xmm14
+	vpxor	%xmm1,%xmm6,%xmm6
+
+	vmovups	112-128(%rcx),%xmm15
+	vpslldq	$8,%xmm6,%xmm5
+	vpxor	%xmm2,%xmm4,%xmm4
+	vmovdqu	16(%r11),%xmm3
+
+	vaesenc	%xmm15,%xmm9,%xmm9
+	vpxor	%xmm8,%xmm7,%xmm7
+	vaesenc	%xmm15,%xmm10,%xmm10
+	vpxor	%xmm5,%xmm4,%xmm4
+	movbeq	24(%r14),%r13
+	vaesenc	%xmm15,%xmm11,%xmm11
+	movbeq	16(%r14),%r12
+	vpalignr	$8,%xmm4,%xmm4,%xmm0
+	vpclmulqdq	$0x10,%xmm3,%xmm4,%xmm4
+	movq	%r13,96+8(%rsp)
+	vaesenc	%xmm15,%xmm12,%xmm12
+	movq	%r12,104+8(%rsp)
+	vaesenc	%xmm15,%xmm13,%xmm13
+	vmovups	128-128(%rcx),%xmm1
+	vaesenc	%xmm15,%xmm14,%xmm14
+
+	vaesenc	%xmm1,%xmm9,%xmm9
+	vmovups	144-128(%rcx),%xmm15
+	vaesenc	%xmm1,%xmm10,%xmm10
+	vpsrldq	$8,%xmm6,%xmm6
+	vaesenc	%xmm1,%xmm11,%xmm11
+	vpxor	%xmm6,%xmm7,%xmm7
+	vaesenc	%xmm1,%xmm12,%xmm12
+	vpxor	%xmm0,%xmm4,%xmm4
+	movbeq	8(%r14),%r13
+	vaesenc	%xmm1,%xmm13,%xmm13
+	movbeq	0(%r14),%r12
+	vaesenc	%xmm1,%xmm14,%xmm14
+	vmovups	160-128(%rcx),%xmm1
+	cmpl	$11,%ebp
+	jb	.Lenc_tail
+
+	vaesenc	%xmm15,%xmm9,%xmm9
+	vaesenc	%xmm15,%xmm10,%xmm10
+	vaesenc	%xmm15,%xmm11,%xmm11
+	vaesenc	%xmm15,%xmm12,%xmm12
+	vaesenc	%xmm15,%xmm13,%xmm13
+	vaesenc	%xmm15,%xmm14,%xmm14
+
+	vaesenc	%xmm1,%xmm9,%xmm9
+	vaesenc	%xmm1,%xmm10,%xmm10
+	vaesenc	%xmm1,%xmm11,%xmm11
+	vaesenc	%xmm1,%xmm12,%xmm12
+	vaesenc	%xmm1,%xmm13,%xmm13
+	vmovups	176-128(%rcx),%xmm15
+	vaesenc	%xmm1,%xmm14,%xmm14
+	vmovups	192-128(%rcx),%xmm1
+	je	.Lenc_tail
+
+	vaesenc	%xmm15,%xmm9,%xmm9
+	vaesenc	%xmm15,%xmm10,%xmm10
+	vaesenc	%xmm15,%xmm11,%xmm11
+	vaesenc	%xmm15,%xmm12,%xmm12
+	vaesenc	%xmm15,%xmm13,%xmm13
+	vaesenc	%xmm15,%xmm14,%xmm14
+
+	vaesenc	%xmm1,%xmm9,%xmm9
+	vaesenc	%xmm1,%xmm10,%xmm10
+	vaesenc	%xmm1,%xmm11,%xmm11
+	vaesenc	%xmm1,%xmm12,%xmm12
+	vaesenc	%xmm1,%xmm13,%xmm13
+	vmovups	208-128(%rcx),%xmm15
+	vaesenc	%xmm1,%xmm14,%xmm14
+	vmovups	224-128(%rcx),%xmm1
+	jmp	.Lenc_tail
+
+.align	32
+.Lhandle_ctr32:
+	vmovdqu	(%r11),%xmm0
+	vpshufb	%xmm0,%xmm1,%xmm6
+	vmovdqu	48(%r11),%xmm5
+	vpaddd	64(%r11),%xmm6,%xmm10
+	vpaddd	%xmm5,%xmm6,%xmm11
+	vmovdqu	0-32(%r9),%xmm3
+	vpaddd	%xmm5,%xmm10,%xmm12
+	vpshufb	%xmm0,%xmm10,%xmm10
+	vpaddd	%xmm5,%xmm11,%xmm13
+	vpshufb	%xmm0,%xmm11,%xmm11
+	vpxor	%xmm15,%xmm10,%xmm10
+	vpaddd	%xmm5,%xmm12,%xmm14
+	vpshufb	%xmm0,%xmm12,%xmm12
+	vpxor	%xmm15,%xmm11,%xmm11
+	vpaddd	%xmm5,%xmm13,%xmm1
+	vpshufb	%xmm0,%xmm13,%xmm13
+	vpshufb	%xmm0,%xmm14,%xmm14
+	vpshufb	%xmm0,%xmm1,%xmm1
+	jmp	.Lresume_ctr32
+
+.align	32
+.Lenc_tail:
+	vaesenc	%xmm15,%xmm9,%xmm9
+	vmovdqu	%xmm7,16+8(%rsp)
+	vpalignr	$8,%xmm4,%xmm4,%xmm8
+	vaesenc	%xmm15,%xmm10,%xmm10
+	vpclmulqdq	$0x10,%xmm3,%xmm4,%xmm4
+	vpxor	0(%rdi),%xmm1,%xmm2
+	vaesenc	%xmm15,%xmm11,%xmm11
+	vpxor	16(%rdi),%xmm1,%xmm0
+	vaesenc	%xmm15,%xmm12,%xmm12
+	vpxor	32(%rdi),%xmm1,%xmm5
+	vaesenc	%xmm15,%xmm13,%xmm13
+	vpxor	48(%rdi),%xmm1,%xmm6
+	vaesenc	%xmm15,%xmm14,%xmm14
+	vpxor	64(%rdi),%xmm1,%xmm7
+	vpxor	80(%rdi),%xmm1,%xmm3
+	vmovdqu	(%r8),%xmm1
+
+	vaesenclast	%xmm2,%xmm9,%xmm9
+	vmovdqu	32(%r11),%xmm2
+	vaesenclast	%xmm0,%xmm10,%xmm10
+	vpaddb	%xmm2,%xmm1,%xmm0
+	movq	%r13,112+8(%rsp)
+	leaq	96(%rdi),%rdi
+	vaesenclast	%xmm5,%xmm11,%xmm11
+	vpaddb	%xmm2,%xmm0,%xmm5
+	movq	%r12,120+8(%rsp)
+	leaq	96(%rsi),%rsi
+	vmovdqu	0-128(%rcx),%xmm15
+	vaesenclast	%xmm6,%xmm12,%xmm12
+	vpaddb	%xmm2,%xmm5,%xmm6
+	vaesenclast	%xmm7,%xmm13,%xmm13
+	vpaddb	%xmm2,%xmm6,%xmm7
+	vaesenclast	%xmm3,%xmm14,%xmm14
+	vpaddb	%xmm2,%xmm7,%xmm3
+
+	addq	$0x60,%r10
+	subq	$0x6,%rdx
+	jc	.L6x_done
+
+	vmovups	%xmm9,-96(%rsi)
+	vpxor	%xmm15,%xmm1,%xmm9
+	vmovups	%xmm10,-80(%rsi)
+	vmovdqa	%xmm0,%xmm10
+	vmovups	%xmm11,-64(%rsi)
+	vmovdqa	%xmm5,%xmm11
+	vmovups	%xmm12,-48(%rsi)
+	vmovdqa	%xmm6,%xmm12
+	vmovups	%xmm13,-32(%rsi)
+	vmovdqa	%xmm7,%xmm13
+	vmovups	%xmm14,-16(%rsi)
+	vmovdqa	%xmm3,%xmm14
+	vmovdqu	32+8(%rsp),%xmm7
+	jmp	.Loop6x
+
+.L6x_done:
+	vpxor	16+8(%rsp),%xmm8,%xmm8
+	vpxor	%xmm4,%xmm8,%xmm8
+
+	.byte	0xf3,0xc3
+.size	_aesni_ctr32_ghash_6x,.-_aesni_ctr32_ghash_6x
 .globl	aesni_gcm_decrypt
 .hidden aesni_gcm_decrypt
 .type	aesni_gcm_decrypt,@function
+.align	32
 aesni_gcm_decrypt:
-	xorl	%eax,%eax
+	xorq	%r10,%r10
+
+
+
+	cmpq	$0x60,%rdx
+	jb	.Lgcm_dec_abort
+
+	leaq	(%rsp),%rax
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	vzeroupper
+
+	vmovdqu	(%r8),%xmm1
+	addq	$-128,%rsp
+	movl	12(%r8),%ebx
+	leaq	.Lbswap_mask(%rip),%r11
+	leaq	-128(%rcx),%r14
+	movq	$0xf80,%r15
+	vmovdqu	(%r9),%xmm8
+	andq	$-128,%rsp
+	vmovdqu	(%r11),%xmm0
+	leaq	128(%rcx),%rcx
+	leaq	32+32(%r9),%r9
+	movl	240-128(%rcx),%ebp
+	vpshufb	%xmm0,%xmm8,%xmm8
+
+	andq	%r15,%r14
+	andq	%rsp,%r15
+	subq	%r14,%r15
+	jc	.Ldec_no_key_aliasing
+	cmpq	$768,%r15
+	jnc	.Ldec_no_key_aliasing
+	subq	%r15,%rsp
+.Ldec_no_key_aliasing:
+
+	vmovdqu	80(%rdi),%xmm7
+	leaq	(%rdi),%r14
+	vmovdqu	64(%rdi),%xmm4
+
+
+
+
+
+
+
+	leaq	-192(%rdi,%rdx,1),%r15
+
+	vmovdqu	48(%rdi),%xmm5
+	shrq	$4,%rdx
+	xorq	%r10,%r10
+	vmovdqu	32(%rdi),%xmm6
+	vpshufb	%xmm0,%xmm7,%xmm7
+	vmovdqu	16(%rdi),%xmm2
+	vpshufb	%xmm0,%xmm4,%xmm4
+	vmovdqu	(%rdi),%xmm3
+	vpshufb	%xmm0,%xmm5,%xmm5
+	vmovdqu	%xmm4,48(%rsp)
+	vpshufb	%xmm0,%xmm6,%xmm6
+	vmovdqu	%xmm5,64(%rsp)
+	vpshufb	%xmm0,%xmm2,%xmm2
+	vmovdqu	%xmm6,80(%rsp)
+	vpshufb	%xmm0,%xmm3,%xmm3
+	vmovdqu	%xmm2,96(%rsp)
+	vmovdqu	%xmm3,112(%rsp)
+
+	call	_aesni_ctr32_ghash_6x
+
+	vmovups	%xmm9,-96(%rsi)
+	vmovups	%xmm10,-80(%rsi)
+	vmovups	%xmm11,-64(%rsi)
+	vmovups	%xmm12,-48(%rsi)
+	vmovups	%xmm13,-32(%rsi)
+	vmovups	%xmm14,-16(%rsi)
+
+	vpshufb	(%r11),%xmm8,%xmm8
+	vmovdqu	%xmm8,-64(%r9)
+
+	vzeroupper
+	movq	-48(%rax),%r15
+	movq	-40(%rax),%r14
+	movq	-32(%rax),%r13
+	movq	-24(%rax),%r12
+	movq	-16(%rax),%rbp
+	movq	-8(%rax),%rbx
+	leaq	(%rax),%rsp
+.Lgcm_dec_abort:
+	movq	%r10,%rax
 	.byte	0xf3,0xc3
 .size	aesni_gcm_decrypt,.-aesni_gcm_decrypt
+.type	_aesni_ctr32_6x,@function
+.align	32
+_aesni_ctr32_6x:
+	vmovdqu	0-128(%rcx),%xmm4
+	vmovdqu	32(%r11),%xmm2
+	leaq	-1(%rbp),%r13
+	vmovups	16-128(%rcx),%xmm15
+	leaq	32-128(%rcx),%r12
+	vpxor	%xmm4,%xmm1,%xmm9
+	addl	$100663296,%ebx
+	jc	.Lhandle_ctr32_2
+	vpaddb	%xmm2,%xmm1,%xmm10
+	vpaddb	%xmm2,%xmm10,%xmm11
+	vpxor	%xmm4,%xmm10,%xmm10
+	vpaddb	%xmm2,%xmm11,%xmm12
+	vpxor	%xmm4,%xmm11,%xmm11
+	vpaddb	%xmm2,%xmm12,%xmm13
+	vpxor	%xmm4,%xmm12,%xmm12
+	vpaddb	%xmm2,%xmm13,%xmm14
+	vpxor	%xmm4,%xmm13,%xmm13
+	vpaddb	%xmm2,%xmm14,%xmm1
+	vpxor	%xmm4,%xmm14,%xmm14
+	jmp	.Loop_ctr32
+
+.align	16
+.Loop_ctr32:
+	vaesenc	%xmm15,%xmm9,%xmm9
+	vaesenc	%xmm15,%xmm10,%xmm10
+	vaesenc	%xmm15,%xmm11,%xmm11
+	vaesenc	%xmm15,%xmm12,%xmm12
+	vaesenc	%xmm15,%xmm13,%xmm13
+	vaesenc	%xmm15,%xmm14,%xmm14
+	vmovups	(%r12),%xmm15
+	leaq	16(%r12),%r12
+	decl	%r13d
+	jnz	.Loop_ctr32
+
+	vmovdqu	(%r12),%xmm3
+	vaesenc	%xmm15,%xmm9,%xmm9
+	vpxor	0(%rdi),%xmm3,%xmm4
+	vaesenc	%xmm15,%xmm10,%xmm10
+	vpxor	16(%rdi),%xmm3,%xmm5
+	vaesenc	%xmm15,%xmm11,%xmm11
+	vpxor	32(%rdi),%xmm3,%xmm6
+	vaesenc	%xmm15,%xmm12,%xmm12
+	vpxor	48(%rdi),%xmm3,%xmm8
+	vaesenc	%xmm15,%xmm13,%xmm13
+	vpxor	64(%rdi),%xmm3,%xmm2
+	vaesenc	%xmm15,%xmm14,%xmm14
+	vpxor	80(%rdi),%xmm3,%xmm3
+	leaq	96(%rdi),%rdi
+
+	vaesenclast	%xmm4,%xmm9,%xmm9
+	vaesenclast	%xmm5,%xmm10,%xmm10
+	vaesenclast	%xmm6,%xmm11,%xmm11
+	vaesenclast	%xmm8,%xmm12,%xmm12
+	vaesenclast	%xmm2,%xmm13,%xmm13
+	vaesenclast	%xmm3,%xmm14,%xmm14
+	vmovups	%xmm9,0(%rsi)
+	vmovups	%xmm10,16(%rsi)
+	vmovups	%xmm11,32(%rsi)
+	vmovups	%xmm12,48(%rsi)
+	vmovups	%xmm13,64(%rsi)
+	vmovups	%xmm14,80(%rsi)
+	leaq	96(%rsi),%rsi
+
+	.byte	0xf3,0xc3
+.align	32
+.Lhandle_ctr32_2:
+	vpshufb	%xmm0,%xmm1,%xmm6
+	vmovdqu	48(%r11),%xmm5
+	vpaddd	64(%r11),%xmm6,%xmm10
+	vpaddd	%xmm5,%xmm6,%xmm11
+	vpaddd	%xmm5,%xmm10,%xmm12
+	vpshufb	%xmm0,%xmm10,%xmm10
+	vpaddd	%xmm5,%xmm11,%xmm13
+	vpshufb	%xmm0,%xmm11,%xmm11
+	vpxor	%xmm4,%xmm10,%xmm10
+	vpaddd	%xmm5,%xmm12,%xmm14
+	vpshufb	%xmm0,%xmm12,%xmm12
+	vpxor	%xmm4,%xmm11,%xmm11
+	vpaddd	%xmm5,%xmm13,%xmm1
+	vpshufb	%xmm0,%xmm13,%xmm13
+	vpxor	%xmm4,%xmm12,%xmm12
+	vpshufb	%xmm0,%xmm14,%xmm14
+	vpxor	%xmm4,%xmm13,%xmm13
+	vpshufb	%xmm0,%xmm1,%xmm1
+	vpxor	%xmm4,%xmm14,%xmm14
+	jmp	.Loop_ctr32
+.size	_aesni_ctr32_6x,.-_aesni_ctr32_6x
+
+.globl	aesni_gcm_encrypt
+.hidden aesni_gcm_encrypt
+.type	aesni_gcm_encrypt,@function
+.align	32
+aesni_gcm_encrypt:
+	xorq	%r10,%r10
+
+
+
+
+	cmpq	$288,%rdx
+	jb	.Lgcm_enc_abort
+
+	leaq	(%rsp),%rax
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	vzeroupper
+
+	vmovdqu	(%r8),%xmm1
+	addq	$-128,%rsp
+	movl	12(%r8),%ebx
+	leaq	.Lbswap_mask(%rip),%r11
+	leaq	-128(%rcx),%r14
+	movq	$0xf80,%r15
+	leaq	128(%rcx),%rcx
+	vmovdqu	(%r11),%xmm0
+	andq	$-128,%rsp
+	movl	240-128(%rcx),%ebp
+
+	andq	%r15,%r14
+	andq	%rsp,%r15
+	subq	%r14,%r15
+	jc	.Lenc_no_key_aliasing
+	cmpq	$768,%r15
+	jnc	.Lenc_no_key_aliasing
+	subq	%r15,%rsp
+.Lenc_no_key_aliasing:
+
+	leaq	(%rsi),%r14
+
+
+
+
+
+
+
+
+	leaq	-192(%rsi,%rdx,1),%r15
+
+	shrq	$4,%rdx
+
+	call	_aesni_ctr32_6x
+	vpshufb	%xmm0,%xmm9,%xmm8
+	vpshufb	%xmm0,%xmm10,%xmm2
+	vmovdqu	%xmm8,112(%rsp)
+	vpshufb	%xmm0,%xmm11,%xmm4
+	vmovdqu	%xmm2,96(%rsp)
+	vpshufb	%xmm0,%xmm12,%xmm5
+	vmovdqu	%xmm4,80(%rsp)
+	vpshufb	%xmm0,%xmm13,%xmm6
+	vmovdqu	%xmm5,64(%rsp)
+	vpshufb	%xmm0,%xmm14,%xmm7
+	vmovdqu	%xmm6,48(%rsp)
+
+	call	_aesni_ctr32_6x
+
+	vmovdqu	(%r9),%xmm8
+	leaq	32+32(%r9),%r9
+	subq	$12,%rdx
+	movq	$192,%r10
+	vpshufb	%xmm0,%xmm8,%xmm8
+
+	call	_aesni_ctr32_ghash_6x
+	vmovdqu	32(%rsp),%xmm7
+	vmovdqu	(%r11),%xmm0
+	vmovdqu	0-32(%r9),%xmm3
+	vpunpckhqdq	%xmm7,%xmm7,%xmm1
+	vmovdqu	32-32(%r9),%xmm15
+	vmovups	%xmm9,-96(%rsi)
+	vpshufb	%xmm0,%xmm9,%xmm9
+	vpxor	%xmm7,%xmm1,%xmm1
+	vmovups	%xmm10,-80(%rsi)
+	vpshufb	%xmm0,%xmm10,%xmm10
+	vmovups	%xmm11,-64(%rsi)
+	vpshufb	%xmm0,%xmm11,%xmm11
+	vmovups	%xmm12,-48(%rsi)
+	vpshufb	%xmm0,%xmm12,%xmm12
+	vmovups	%xmm13,-32(%rsi)
+	vpshufb	%xmm0,%xmm13,%xmm13
+	vmovups	%xmm14,-16(%rsi)
+	vpshufb	%xmm0,%xmm14,%xmm14
+	vmovdqu	%xmm9,16(%rsp)
+	vmovdqu	48(%rsp),%xmm6
+	vmovdqu	16-32(%r9),%xmm0
+	vpunpckhqdq	%xmm6,%xmm6,%xmm2
+	vpclmulqdq	$0x00,%xmm3,%xmm7,%xmm5
+	vpxor	%xmm6,%xmm2,%xmm2
+	vpclmulqdq	$0x11,%xmm3,%xmm7,%xmm7
+	vpclmulqdq	$0x00,%xmm15,%xmm1,%xmm1
+
+	vmovdqu	64(%rsp),%xmm9
+	vpclmulqdq	$0x00,%xmm0,%xmm6,%xmm4
+	vmovdqu	48-32(%r9),%xmm3
+	vpxor	%xmm5,%xmm4,%xmm4
+	vpunpckhqdq	%xmm9,%xmm9,%xmm5
+	vpclmulqdq	$0x11,%xmm0,%xmm6,%xmm6
+	vpxor	%xmm9,%xmm5,%xmm5
+	vpxor	%xmm7,%xmm6,%xmm6
+	vpclmulqdq	$0x10,%xmm15,%xmm2,%xmm2
+	vmovdqu	80-32(%r9),%xmm15
+	vpxor	%xmm1,%xmm2,%xmm2
+
+	vmovdqu	80(%rsp),%xmm1
+	vpclmulqdq	$0x00,%xmm3,%xmm9,%xmm7
+	vmovdqu	64-32(%r9),%xmm0
+	vpxor	%xmm4,%xmm7,%xmm7
+	vpunpckhqdq	%xmm1,%xmm1,%xmm4
+	vpclmulqdq	$0x11,%xmm3,%xmm9,%xmm9
+	vpxor	%xmm1,%xmm4,%xmm4
+	vpxor	%xmm6,%xmm9,%xmm9
+	vpclmulqdq	$0x00,%xmm15,%xmm5,%xmm5
+	vpxor	%xmm2,%xmm5,%xmm5
+
+	vmovdqu	96(%rsp),%xmm2
+	vpclmulqdq	$0x00,%xmm0,%xmm1,%xmm6
+	vmovdqu	96-32(%r9),%xmm3
+	vpxor	%xmm7,%xmm6,%xmm6
+	vpunpckhqdq	%xmm2,%xmm2,%xmm7
+	vpclmulqdq	$0x11,%xmm0,%xmm1,%xmm1
+	vpxor	%xmm2,%xmm7,%xmm7
+	vpxor	%xmm9,%xmm1,%xmm1
+	vpclmulqdq	$0x10,%xmm15,%xmm4,%xmm4
+	vmovdqu	128-32(%r9),%xmm15
+	vpxor	%xmm5,%xmm4,%xmm4
+
+	vpxor	112(%rsp),%xmm8,%xmm8
+	vpclmulqdq	$0x00,%xmm3,%xmm2,%xmm5
+	vmovdqu	112-32(%r9),%xmm0
+	vpunpckhqdq	%xmm8,%xmm8,%xmm9
+	vpxor	%xmm6,%xmm5,%xmm5
+	vpclmulqdq	$0x11,%xmm3,%xmm2,%xmm2
+	vpxor	%xmm8,%xmm9,%xmm9
+	vpxor	%xmm1,%xmm2,%xmm2
+	vpclmulqdq	$0x00,%xmm15,%xmm7,%xmm7
+	vpxor	%xmm4,%xmm7,%xmm4
+
+	vpclmulqdq	$0x00,%xmm0,%xmm8,%xmm6
+	vmovdqu	0-32(%r9),%xmm3
+	vpunpckhqdq	%xmm14,%xmm14,%xmm1
+	vpclmulqdq	$0x11,%xmm0,%xmm8,%xmm8
+	vpxor	%xmm14,%xmm1,%xmm1
+	vpxor	%xmm5,%xmm6,%xmm5
+	vpclmulqdq	$0x10,%xmm15,%xmm9,%xmm9
+	vmovdqu	32-32(%r9),%xmm15
+	vpxor	%xmm2,%xmm8,%xmm7
+	vpxor	%xmm4,%xmm9,%xmm6
+
+	vmovdqu	16-32(%r9),%xmm0
+	vpxor	%xmm5,%xmm7,%xmm9
+	vpclmulqdq	$0x00,%xmm3,%xmm14,%xmm4
+	vpxor	%xmm9,%xmm6,%xmm6
+	vpunpckhqdq	%xmm13,%xmm13,%xmm2
+	vpclmulqdq	$0x11,%xmm3,%xmm14,%xmm14
+	vpxor	%xmm13,%xmm2,%xmm2
+	vpslldq	$8,%xmm6,%xmm9
+	vpclmulqdq	$0x00,%xmm15,%xmm1,%xmm1
+	vpxor	%xmm9,%xmm5,%xmm8
+	vpsrldq	$8,%xmm6,%xmm6
+	vpxor	%xmm6,%xmm7,%xmm7
+
+	vpclmulqdq	$0x00,%xmm0,%xmm13,%xmm5
+	vmovdqu	48-32(%r9),%xmm3
+	vpxor	%xmm4,%xmm5,%xmm5
+	vpunpckhqdq	%xmm12,%xmm12,%xmm9
+	vpclmulqdq	$0x11,%xmm0,%xmm13,%xmm13
+	vpxor	%xmm12,%xmm9,%xmm9
+	vpxor	%xmm14,%xmm13,%xmm13
+	vpalignr	$8,%xmm8,%xmm8,%xmm14
+	vpclmulqdq	$0x10,%xmm15,%xmm2,%xmm2
+	vmovdqu	80-32(%r9),%xmm15
+	vpxor	%xmm1,%xmm2,%xmm2
+
+	vpclmulqdq	$0x00,%xmm3,%xmm12,%xmm4
+	vmovdqu	64-32(%r9),%xmm0
+	vpxor	%xmm5,%xmm4,%xmm4
+	vpunpckhqdq	%xmm11,%xmm11,%xmm1
+	vpclmulqdq	$0x11,%xmm3,%xmm12,%xmm12
+	vpxor	%xmm11,%xmm1,%xmm1
+	vpxor	%xmm13,%xmm12,%xmm12
+	vxorps	16(%rsp),%xmm7,%xmm7
+	vpclmulqdq	$0x00,%xmm15,%xmm9,%xmm9
+	vpxor	%xmm2,%xmm9,%xmm9
+
+	vpclmulqdq	$0x10,16(%r11),%xmm8,%xmm8
+	vxorps	%xmm14,%xmm8,%xmm8
+
+	vpclmulqdq	$0x00,%xmm0,%xmm11,%xmm5
+	vmovdqu	96-32(%r9),%xmm3
+	vpxor	%xmm4,%xmm5,%xmm5
+	vpunpckhqdq	%xmm10,%xmm10,%xmm2
+	vpclmulqdq	$0x11,%xmm0,%xmm11,%xmm11
+	vpxor	%xmm10,%xmm2,%xmm2
+	vpalignr	$8,%xmm8,%xmm8,%xmm14
+	vpxor	%xmm12,%xmm11,%xmm11
+	vpclmulqdq	$0x10,%xmm15,%xmm1,%xmm1
+	vmovdqu	128-32(%r9),%xmm15
+	vpxor	%xmm9,%xmm1,%xmm1
+
+	vxorps	%xmm7,%xmm14,%xmm14
+	vpclmulqdq	$0x10,16(%r11),%xmm8,%xmm8
+	vxorps	%xmm14,%xmm8,%xmm8
+
+	vpclmulqdq	$0x00,%xmm3,%xmm10,%xmm4
+	vmovdqu	112-32(%r9),%xmm0
+	vpxor	%xmm5,%xmm4,%xmm4
+	vpunpckhqdq	%xmm8,%xmm8,%xmm9
+	vpclmulqdq	$0x11,%xmm3,%xmm10,%xmm10
+	vpxor	%xmm8,%xmm9,%xmm9
+	vpxor	%xmm11,%xmm10,%xmm10
+	vpclmulqdq	$0x00,%xmm15,%xmm2,%xmm2
+	vpxor	%xmm1,%xmm2,%xmm2
+
+	vpclmulqdq	$0x00,%xmm0,%xmm8,%xmm5
+	vpclmulqdq	$0x11,%xmm0,%xmm8,%xmm7
+	vpxor	%xmm4,%xmm5,%xmm5
+	vpclmulqdq	$0x10,%xmm15,%xmm9,%xmm6
+	vpxor	%xmm10,%xmm7,%xmm7
+	vpxor	%xmm2,%xmm6,%xmm6
+
+	vpxor	%xmm5,%xmm7,%xmm4
+	vpxor	%xmm4,%xmm6,%xmm6
+	vpslldq	$8,%xmm6,%xmm1
+	vmovdqu	16(%r11),%xmm3
+	vpsrldq	$8,%xmm6,%xmm6
+	vpxor	%xmm1,%xmm5,%xmm8
+	vpxor	%xmm6,%xmm7,%xmm7
+
+	vpalignr	$8,%xmm8,%xmm8,%xmm2
+	vpclmulqdq	$0x10,%xmm3,%xmm8,%xmm8
+	vpxor	%xmm2,%xmm8,%xmm8
+
+	vpalignr	$8,%xmm8,%xmm8,%xmm2
+	vpclmulqdq	$0x10,%xmm3,%xmm8,%xmm8
+	vpxor	%xmm7,%xmm2,%xmm2
+	vpxor	%xmm2,%xmm8,%xmm8
+	vpshufb	(%r11),%xmm8,%xmm8
+	vmovdqu	%xmm8,-64(%r9)
+
+	vzeroupper
+	movq	-48(%rax),%r15
+	movq	-40(%rax),%r14
+	movq	-32(%rax),%r13
+	movq	-24(%rax),%r12
+	movq	-16(%rax),%rbp
+	movq	-8(%rax),%rbx
+	leaq	(%rax),%rsp
+.Lgcm_enc_abort:
+	movq	%r10,%rax
+	.byte	0xf3,0xc3
+.size	aesni_gcm_encrypt,.-aesni_gcm_encrypt
+.align	64
+.Lbswap_mask:
+.byte	15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
+.Lpoly:
+.byte	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xc2
+.Lone_msb:
+.byte	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
+.Ltwo_lsb:
+.byte	2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+.Lone_lsb:
+.byte	1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+.byte	65,69,83,45,78,73,32,71,67,77,32,109,111,100,117,108,101,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.align	64
 #endif
diff --git a/linux-x86_64/crypto/modes/ghash-x86_64.S b/linux-x86_64/crypto/modes/ghash-x86_64.S
index 1db7d69..8842c27 100644
--- a/linux-x86_64/crypto/modes/ghash-x86_64.S
+++ b/linux-x86_64/crypto/modes/ghash-x86_64.S
@@ -11,6 +11,10 @@
 	pushq	%rbx
 	pushq	%rbp
 	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	subq	$280,%rsp
 .Lgmult_prologue:
 
 	movzbq	15(%rdi),%r8
@@ -23,14 +27,14 @@
 	movq	$14,%rcx
 	movq	8(%rsi,%rax,1),%r8
 	movq	(%rsi,%rax,1),%r9
-	andb	$240,%bl
+	andb	$0xf0,%bl
 	movq	%r8,%rdx
 	jmp	.Loop1
 
 .align	16
 .Loop1:
 	shrq	$4,%r8
-	andq	$15,%rdx
+	andq	$0xf,%rdx
 	movq	%r9,%r10
 	movb	(%rdi,%rcx,1),%al
 	shrq	$4,%r9
@@ -46,13 +50,13 @@
 	js	.Lbreak1
 
 	shrq	$4,%r8
-	andq	$15,%rdx
+	andq	$0xf,%rdx
 	movq	%r9,%r10
 	shrq	$4,%r9
 	xorq	8(%rsi,%rax,1),%r8
 	shlq	$60,%r10
 	xorq	(%rsi,%rax,1),%r9
-	andb	$240,%bl
+	andb	$0xf0,%bl
 	xorq	(%r11,%rdx,8),%r9
 	movq	%r8,%rdx
 	xorq	%r10,%r8
@@ -61,19 +65,19 @@
 .align	16
 .Lbreak1:
 	shrq	$4,%r8
-	andq	$15,%rdx
+	andq	$0xf,%rdx
 	movq	%r9,%r10
 	shrq	$4,%r9
 	xorq	8(%rsi,%rax,1),%r8
 	shlq	$60,%r10
 	xorq	(%rsi,%rax,1),%r9
-	andb	$240,%bl
+	andb	$0xf0,%bl
 	xorq	(%r11,%rdx,8),%r9
 	movq	%r8,%rdx
 	xorq	%r10,%r8
 
 	shrq	$4,%r8
-	andq	$15,%rdx
+	andq	$0xf,%rdx
 	movq	%r9,%r10
 	shrq	$4,%r9
 	xorq	8(%rsi,%rbx,1),%r8
@@ -87,8 +91,9 @@
 	movq	%r8,8(%rdi)
 	movq	%r9,(%rdi)
 
-	movq	16(%rsp),%rbx
-	leaq	24(%rsp),%rsp
+	leaq	280+48(%rsp),%rsi
+	movq	-8(%rsi),%rbx
+	leaq	(%rsi),%rsp
 .Lgmult_epilogue:
 	.byte	0xf3,0xc3
 .size	gcm_gmult_4bit,.-gcm_gmult_4bit
@@ -648,14 +653,14 @@
 	movq	%r8,8(%rdi)
 	movq	%r9,(%rdi)
 
-	leaq	280(%rsp),%rsi
-	movq	0(%rsi),%r15
-	movq	8(%rsi),%r14
-	movq	16(%rsi),%r13
-	movq	24(%rsi),%r12
-	movq	32(%rsi),%rbp
-	movq	40(%rsi),%rbx
-	leaq	48(%rsi),%rsp
+	leaq	280+48(%rsp),%rsi
+	movq	-48(%rsi),%r15
+	movq	-40(%rsi),%r14
+	movq	-32(%rsi),%r13
+	movq	-24(%rsi),%r12
+	movq	-16(%rsi),%rbp
+	movq	-8(%rsi),%rbx
+	leaq	0(%rsi),%rsp
 .Lghash_epilogue:
 	.byte	0xf3,0xc3
 .size	gcm_ghash_4bit,.-gcm_ghash_4bit
@@ -881,20 +886,20 @@
 	movdqu	32(%rsi),%xmm7
 .byte	102,65,15,56,0,194
 
-	subq	$16,%rcx
+	subq	$0x10,%rcx
 	jz	.Lodd_tail
 
 	movdqu	16(%rsi),%xmm6
 	movl	OPENSSL_ia32cap_P+4(%rip),%eax
-	cmpq	$48,%rcx
+	cmpq	$0x30,%rcx
 	jb	.Lskip4x
 
 	andl	$71303168,%eax
 	cmpl	$4194304,%eax
 	je	.Lskip4x
 
-	subq	$48,%rcx
-	movq	$11547335547999543296,%rax
+	subq	$0x30,%rcx
+	movq	$0xA040608020C0E000,%rax
 	movdqu	48(%rsi),%xmm14
 	movdqu	64(%rsi),%xmm15
 
@@ -941,7 +946,7 @@
 	xorps	%xmm13,%xmm5
 
 	leaq	64(%rdx),%rdx
-	subq	$64,%rcx
+	subq	$0x40,%rcx
 	jc	.Ltail4x
 
 	jmp	.Lmod4_loop
@@ -1024,7 +1029,7 @@
 	xorps	%xmm13,%xmm5
 
 	leaq	64(%rdx),%rdx
-	subq	$64,%rcx
+	subq	$0x40,%rcx
 	jnc	.Lmod4_loop
 
 .Ltail4x:
@@ -1068,10 +1073,10 @@
 	pxor	%xmm4,%xmm0
 	psrlq	$1,%xmm0
 	pxor	%xmm1,%xmm0
-	addq	$64,%rcx
+	addq	$0x40,%rcx
 	jz	.Ldone
 	movdqu	32(%rsi),%xmm7
-	subq	$16,%rcx
+	subq	$0x10,%rcx
 	jz	.Lodd_tail
 .Lskip4x:
 
@@ -1094,7 +1099,7 @@
 
 	leaq	32(%rdx),%rdx
 	nop
-	subq	$32,%rcx
+	subq	$0x20,%rcx
 	jbe	.Leven_tail
 	nop
 	jmp	.Lmod_loop
@@ -1157,7 +1162,7 @@
 .byte	102,15,58,68,231,0
 	pxor	%xmm1,%xmm0
 
-	subq	$32,%rcx
+	subq	$0x20,%rcx
 	ja	.Lmod_loop
 
 .Leven_tail:
@@ -1257,7 +1262,108 @@
 .type	gcm_init_avx,@function
 .align	32
 gcm_init_avx:
-	jmp	.L_init_clmul
+	vzeroupper
+
+	vmovdqu	(%rsi),%xmm2
+	vpshufd	$78,%xmm2,%xmm2
+
+
+	vpshufd	$255,%xmm2,%xmm4
+	vpsrlq	$63,%xmm2,%xmm3
+	vpsllq	$1,%xmm2,%xmm2
+	vpxor	%xmm5,%xmm5,%xmm5
+	vpcmpgtd	%xmm4,%xmm5,%xmm5
+	vpslldq	$8,%xmm3,%xmm3
+	vpor	%xmm3,%xmm2,%xmm2
+
+
+	vpand	.L0x1c2_polynomial(%rip),%xmm5,%xmm5
+	vpxor	%xmm5,%xmm2,%xmm2
+
+	vpunpckhqdq	%xmm2,%xmm2,%xmm6
+	vmovdqa	%xmm2,%xmm0
+	vpxor	%xmm2,%xmm6,%xmm6
+	movq	$4,%r10
+	jmp	.Linit_start_avx
+.align	32
+.Linit_loop_avx:
+	vpalignr	$8,%xmm3,%xmm4,%xmm5
+	vmovdqu	%xmm5,-16(%rdi)
+	vpunpckhqdq	%xmm0,%xmm0,%xmm3
+	vpxor	%xmm0,%xmm3,%xmm3
+	vpclmulqdq	$0x11,%xmm2,%xmm0,%xmm1
+	vpclmulqdq	$0x00,%xmm2,%xmm0,%xmm0
+	vpclmulqdq	$0x00,%xmm6,%xmm3,%xmm3
+	vpxor	%xmm0,%xmm1,%xmm4
+	vpxor	%xmm4,%xmm3,%xmm3
+
+	vpslldq	$8,%xmm3,%xmm4
+	vpsrldq	$8,%xmm3,%xmm3
+	vpxor	%xmm4,%xmm0,%xmm0
+	vpxor	%xmm3,%xmm1,%xmm1
+	vpsllq	$57,%xmm0,%xmm3
+	vpsllq	$62,%xmm0,%xmm4
+	vpxor	%xmm3,%xmm4,%xmm4
+	vpsllq	$63,%xmm0,%xmm3
+	vpxor	%xmm3,%xmm4,%xmm4
+	vpslldq	$8,%xmm4,%xmm3
+	vpsrldq	$8,%xmm4,%xmm4
+	vpxor	%xmm3,%xmm0,%xmm0
+	vpxor	%xmm4,%xmm1,%xmm1
+
+	vpsrlq	$1,%xmm0,%xmm4
+	vpxor	%xmm0,%xmm1,%xmm1
+	vpxor	%xmm4,%xmm0,%xmm0
+	vpsrlq	$5,%xmm4,%xmm4
+	vpxor	%xmm4,%xmm0,%xmm0
+	vpsrlq	$1,%xmm0,%xmm0
+	vpxor	%xmm1,%xmm0,%xmm0
+.Linit_start_avx:
+	vmovdqa	%xmm0,%xmm5
+	vpunpckhqdq	%xmm0,%xmm0,%xmm3
+	vpxor	%xmm0,%xmm3,%xmm3
+	vpclmulqdq	$0x11,%xmm2,%xmm0,%xmm1
+	vpclmulqdq	$0x00,%xmm2,%xmm0,%xmm0
+	vpclmulqdq	$0x00,%xmm6,%xmm3,%xmm3
+	vpxor	%xmm0,%xmm1,%xmm4
+	vpxor	%xmm4,%xmm3,%xmm3
+
+	vpslldq	$8,%xmm3,%xmm4
+	vpsrldq	$8,%xmm3,%xmm3
+	vpxor	%xmm4,%xmm0,%xmm0
+	vpxor	%xmm3,%xmm1,%xmm1
+	vpsllq	$57,%xmm0,%xmm3
+	vpsllq	$62,%xmm0,%xmm4
+	vpxor	%xmm3,%xmm4,%xmm4
+	vpsllq	$63,%xmm0,%xmm3
+	vpxor	%xmm3,%xmm4,%xmm4
+	vpslldq	$8,%xmm4,%xmm3
+	vpsrldq	$8,%xmm4,%xmm4
+	vpxor	%xmm3,%xmm0,%xmm0
+	vpxor	%xmm4,%xmm1,%xmm1
+
+	vpsrlq	$1,%xmm0,%xmm4
+	vpxor	%xmm0,%xmm1,%xmm1
+	vpxor	%xmm4,%xmm0,%xmm0
+	vpsrlq	$5,%xmm4,%xmm4
+	vpxor	%xmm4,%xmm0,%xmm0
+	vpsrlq	$1,%xmm0,%xmm0
+	vpxor	%xmm1,%xmm0,%xmm0
+	vpshufd	$78,%xmm5,%xmm3
+	vpshufd	$78,%xmm0,%xmm4
+	vpxor	%xmm5,%xmm3,%xmm3
+	vmovdqu	%xmm5,0(%rdi)
+	vpxor	%xmm0,%xmm4,%xmm4
+	vmovdqu	%xmm0,16(%rdi)
+	leaq	48(%rdi),%rdi
+	subq	$1,%r10
+	jnz	.Linit_loop_avx
+
+	vpalignr	$8,%xmm4,%xmm3,%xmm5
+	vmovdqu	%xmm5,-16(%rdi)
+
+	vzeroupper
+	.byte	0xf3,0xc3
 .size	gcm_init_avx,.-gcm_init_avx
 .globl	gcm_gmult_avx
 .hidden gcm_gmult_avx
@@ -1271,7 +1377,377 @@
 .type	gcm_ghash_avx,@function
 .align	32
 gcm_ghash_avx:
-	jmp	.L_ghash_clmul
+	vzeroupper
+
+	vmovdqu	(%rdi),%xmm10
+	leaq	.L0x1c2_polynomial(%rip),%r10
+	leaq	64(%rsi),%rsi
+	vmovdqu	.Lbswap_mask(%rip),%xmm13
+	vpshufb	%xmm13,%xmm10,%xmm10
+	cmpq	$0x80,%rcx
+	jb	.Lshort_avx
+	subq	$0x80,%rcx
+
+	vmovdqu	112(%rdx),%xmm14
+	vmovdqu	0-64(%rsi),%xmm6
+	vpshufb	%xmm13,%xmm14,%xmm14
+	vmovdqu	32-64(%rsi),%xmm7
+
+	vpunpckhqdq	%xmm14,%xmm14,%xmm9
+	vmovdqu	96(%rdx),%xmm15
+	vpclmulqdq	$0x00,%xmm6,%xmm14,%xmm0
+	vpxor	%xmm14,%xmm9,%xmm9
+	vpshufb	%xmm13,%xmm15,%xmm15
+	vpclmulqdq	$0x11,%xmm6,%xmm14,%xmm1
+	vmovdqu	16-64(%rsi),%xmm6
+	vpunpckhqdq	%xmm15,%xmm15,%xmm8
+	vmovdqu	80(%rdx),%xmm14
+	vpclmulqdq	$0x00,%xmm7,%xmm9,%xmm2
+	vpxor	%xmm15,%xmm8,%xmm8
+
+	vpshufb	%xmm13,%xmm14,%xmm14
+	vpclmulqdq	$0x00,%xmm6,%xmm15,%xmm3
+	vpunpckhqdq	%xmm14,%xmm14,%xmm9
+	vpclmulqdq	$0x11,%xmm6,%xmm15,%xmm4
+	vmovdqu	48-64(%rsi),%xmm6
+	vpxor	%xmm14,%xmm9,%xmm9
+	vmovdqu	64(%rdx),%xmm15
+	vpclmulqdq	$0x10,%xmm7,%xmm8,%xmm5
+	vmovdqu	80-64(%rsi),%xmm7
+
+	vpshufb	%xmm13,%xmm15,%xmm15
+	vpxor	%xmm0,%xmm3,%xmm3
+	vpclmulqdq	$0x00,%xmm6,%xmm14,%xmm0
+	vpxor	%xmm1,%xmm4,%xmm4
+	vpunpckhqdq	%xmm15,%xmm15,%xmm8
+	vpclmulqdq	$0x11,%xmm6,%xmm14,%xmm1
+	vmovdqu	64-64(%rsi),%xmm6
+	vpxor	%xmm2,%xmm5,%xmm5
+	vpclmulqdq	$0x00,%xmm7,%xmm9,%xmm2
+	vpxor	%xmm15,%xmm8,%xmm8
+
+	vmovdqu	48(%rdx),%xmm14
+	vpxor	%xmm3,%xmm0,%xmm0
+	vpclmulqdq	$0x00,%xmm6,%xmm15,%xmm3
+	vpxor	%xmm4,%xmm1,%xmm1
+	vpshufb	%xmm13,%xmm14,%xmm14
+	vpclmulqdq	$0x11,%xmm6,%xmm15,%xmm4
+	vmovdqu	96-64(%rsi),%xmm6
+	vpxor	%xmm5,%xmm2,%xmm2
+	vpunpckhqdq	%xmm14,%xmm14,%xmm9
+	vpclmulqdq	$0x10,%xmm7,%xmm8,%xmm5
+	vmovdqu	128-64(%rsi),%xmm7
+	vpxor	%xmm14,%xmm9,%xmm9
+
+	vmovdqu	32(%rdx),%xmm15
+	vpxor	%xmm0,%xmm3,%xmm3
+	vpclmulqdq	$0x00,%xmm6,%xmm14,%xmm0
+	vpxor	%xmm1,%xmm4,%xmm4
+	vpshufb	%xmm13,%xmm15,%xmm15
+	vpclmulqdq	$0x11,%xmm6,%xmm14,%xmm1
+	vmovdqu	112-64(%rsi),%xmm6
+	vpxor	%xmm2,%xmm5,%xmm5
+	vpunpckhqdq	%xmm15,%xmm15,%xmm8
+	vpclmulqdq	$0x00,%xmm7,%xmm9,%xmm2
+	vpxor	%xmm15,%xmm8,%xmm8
+
+	vmovdqu	16(%rdx),%xmm14
+	vpxor	%xmm3,%xmm0,%xmm0
+	vpclmulqdq	$0x00,%xmm6,%xmm15,%xmm3
+	vpxor	%xmm4,%xmm1,%xmm1
+	vpshufb	%xmm13,%xmm14,%xmm14
+	vpclmulqdq	$0x11,%xmm6,%xmm15,%xmm4
+	vmovdqu	144-64(%rsi),%xmm6
+	vpxor	%xmm5,%xmm2,%xmm2
+	vpunpckhqdq	%xmm14,%xmm14,%xmm9
+	vpclmulqdq	$0x10,%xmm7,%xmm8,%xmm5
+	vmovdqu	176-64(%rsi),%xmm7
+	vpxor	%xmm14,%xmm9,%xmm9
+
+	vmovdqu	(%rdx),%xmm15
+	vpxor	%xmm0,%xmm3,%xmm3
+	vpclmulqdq	$0x00,%xmm6,%xmm14,%xmm0
+	vpxor	%xmm1,%xmm4,%xmm4
+	vpshufb	%xmm13,%xmm15,%xmm15
+	vpclmulqdq	$0x11,%xmm6,%xmm14,%xmm1
+	vmovdqu	160-64(%rsi),%xmm6
+	vpxor	%xmm2,%xmm5,%xmm5
+	vpclmulqdq	$0x10,%xmm7,%xmm9,%xmm2
+
+	leaq	128(%rdx),%rdx
+	cmpq	$0x80,%rcx
+	jb	.Ltail_avx
+
+	vpxor	%xmm10,%xmm15,%xmm15
+	subq	$0x80,%rcx
+	jmp	.Loop8x_avx
+
+.align	32
+.Loop8x_avx:
+	vpunpckhqdq	%xmm15,%xmm15,%xmm8
+	vmovdqu	112(%rdx),%xmm14
+	vpxor	%xmm0,%xmm3,%xmm3
+	vpxor	%xmm15,%xmm8,%xmm8
+	vpclmulqdq	$0x00,%xmm6,%xmm15,%xmm10
+	vpshufb	%xmm13,%xmm14,%xmm14
+	vpxor	%xmm1,%xmm4,%xmm4
+	vpclmulqdq	$0x11,%xmm6,%xmm15,%xmm11
+	vmovdqu	0-64(%rsi),%xmm6
+	vpunpckhqdq	%xmm14,%xmm14,%xmm9
+	vpxor	%xmm2,%xmm5,%xmm5
+	vpclmulqdq	$0x00,%xmm7,%xmm8,%xmm12
+	vmovdqu	32-64(%rsi),%xmm7
+	vpxor	%xmm14,%xmm9,%xmm9
+
+	vmovdqu	96(%rdx),%xmm15
+	vpclmulqdq	$0x00,%xmm6,%xmm14,%xmm0
+	vpxor	%xmm3,%xmm10,%xmm10
+	vpshufb	%xmm13,%xmm15,%xmm15
+	vpclmulqdq	$0x11,%xmm6,%xmm14,%xmm1
+	vxorps	%xmm4,%xmm11,%xmm11
+	vmovdqu	16-64(%rsi),%xmm6
+	vpunpckhqdq	%xmm15,%xmm15,%xmm8
+	vpclmulqdq	$0x00,%xmm7,%xmm9,%xmm2
+	vpxor	%xmm5,%xmm12,%xmm12
+	vxorps	%xmm15,%xmm8,%xmm8
+
+	vmovdqu	80(%rdx),%xmm14
+	vpxor	%xmm10,%xmm12,%xmm12
+	vpclmulqdq	$0x00,%xmm6,%xmm15,%xmm3
+	vpxor	%xmm11,%xmm12,%xmm12
+	vpslldq	$8,%xmm12,%xmm9
+	vpxor	%xmm0,%xmm3,%xmm3
+	vpclmulqdq	$0x11,%xmm6,%xmm15,%xmm4
+	vpsrldq	$8,%xmm12,%xmm12
+	vpxor	%xmm9,%xmm10,%xmm10
+	vmovdqu	48-64(%rsi),%xmm6
+	vpshufb	%xmm13,%xmm14,%xmm14
+	vxorps	%xmm12,%xmm11,%xmm11
+	vpxor	%xmm1,%xmm4,%xmm4
+	vpunpckhqdq	%xmm14,%xmm14,%xmm9
+	vpclmulqdq	$0x10,%xmm7,%xmm8,%xmm5
+	vmovdqu	80-64(%rsi),%xmm7
+	vpxor	%xmm14,%xmm9,%xmm9
+	vpxor	%xmm2,%xmm5,%xmm5
+
+	vmovdqu	64(%rdx),%xmm15
+	vpalignr	$8,%xmm10,%xmm10,%xmm12
+	vpclmulqdq	$0x00,%xmm6,%xmm14,%xmm0
+	vpshufb	%xmm13,%xmm15,%xmm15
+	vpxor	%xmm3,%xmm0,%xmm0
+	vpclmulqdq	$0x11,%xmm6,%xmm14,%xmm1
+	vmovdqu	64-64(%rsi),%xmm6
+	vpunpckhqdq	%xmm15,%xmm15,%xmm8
+	vpxor	%xmm4,%xmm1,%xmm1
+	vpclmulqdq	$0x00,%xmm7,%xmm9,%xmm2
+	vxorps	%xmm15,%xmm8,%xmm8
+	vpxor	%xmm5,%xmm2,%xmm2
+
+	vmovdqu	48(%rdx),%xmm14
+	vpclmulqdq	$0x10,(%r10),%xmm10,%xmm10
+	vpclmulqdq	$0x00,%xmm6,%xmm15,%xmm3
+	vpshufb	%xmm13,%xmm14,%xmm14
+	vpxor	%xmm0,%xmm3,%xmm3
+	vpclmulqdq	$0x11,%xmm6,%xmm15,%xmm4
+	vmovdqu	96-64(%rsi),%xmm6
+	vpunpckhqdq	%xmm14,%xmm14,%xmm9
+	vpxor	%xmm1,%xmm4,%xmm4
+	vpclmulqdq	$0x10,%xmm7,%xmm8,%xmm5
+	vmovdqu	128-64(%rsi),%xmm7
+	vpxor	%xmm14,%xmm9,%xmm9
+	vpxor	%xmm2,%xmm5,%xmm5
+
+	vmovdqu	32(%rdx),%xmm15
+	vpclmulqdq	$0x00,%xmm6,%xmm14,%xmm0
+	vpshufb	%xmm13,%xmm15,%xmm15
+	vpxor	%xmm3,%xmm0,%xmm0
+	vpclmulqdq	$0x11,%xmm6,%xmm14,%xmm1
+	vmovdqu	112-64(%rsi),%xmm6
+	vpunpckhqdq	%xmm15,%xmm15,%xmm8
+	vpxor	%xmm4,%xmm1,%xmm1
+	vpclmulqdq	$0x00,%xmm7,%xmm9,%xmm2
+	vpxor	%xmm15,%xmm8,%xmm8
+	vpxor	%xmm5,%xmm2,%xmm2
+	vxorps	%xmm12,%xmm10,%xmm10
+
+	vmovdqu	16(%rdx),%xmm14
+	vpalignr	$8,%xmm10,%xmm10,%xmm12
+	vpclmulqdq	$0x00,%xmm6,%xmm15,%xmm3
+	vpshufb	%xmm13,%xmm14,%xmm14
+	vpxor	%xmm0,%xmm3,%xmm3
+	vpclmulqdq	$0x11,%xmm6,%xmm15,%xmm4
+	vmovdqu	144-64(%rsi),%xmm6
+	vpclmulqdq	$0x10,(%r10),%xmm10,%xmm10
+	vxorps	%xmm11,%xmm12,%xmm12
+	vpunpckhqdq	%xmm14,%xmm14,%xmm9
+	vpxor	%xmm1,%xmm4,%xmm4
+	vpclmulqdq	$0x10,%xmm7,%xmm8,%xmm5
+	vmovdqu	176-64(%rsi),%xmm7
+	vpxor	%xmm14,%xmm9,%xmm9
+	vpxor	%xmm2,%xmm5,%xmm5
+
+	vmovdqu	(%rdx),%xmm15
+	vpclmulqdq	$0x00,%xmm6,%xmm14,%xmm0
+	vpshufb	%xmm13,%xmm15,%xmm15
+	vpclmulqdq	$0x11,%xmm6,%xmm14,%xmm1
+	vmovdqu	160-64(%rsi),%xmm6
+	vpxor	%xmm12,%xmm15,%xmm15
+	vpclmulqdq	$0x10,%xmm7,%xmm9,%xmm2
+	vpxor	%xmm10,%xmm15,%xmm15
+
+	leaq	128(%rdx),%rdx
+	subq	$0x80,%rcx
+	jnc	.Loop8x_avx
+
+	addq	$0x80,%rcx
+	jmp	.Ltail_no_xor_avx
+
+.align	32
+.Lshort_avx:
+	vmovdqu	-16(%rdx,%rcx,1),%xmm14
+	leaq	(%rdx,%rcx,1),%rdx
+	vmovdqu	0-64(%rsi),%xmm6
+	vmovdqu	32-64(%rsi),%xmm7
+	vpshufb	%xmm13,%xmm14,%xmm15
+
+	vmovdqa	%xmm0,%xmm3
+	vmovdqa	%xmm1,%xmm4
+	vmovdqa	%xmm2,%xmm5
+	subq	$0x10,%rcx
+	jz	.Ltail_avx
+
+	vpunpckhqdq	%xmm15,%xmm15,%xmm8
+	vpxor	%xmm0,%xmm3,%xmm3
+	vpclmulqdq	$0x00,%xmm6,%xmm15,%xmm0
+	vpxor	%xmm15,%xmm8,%xmm8
+	vmovdqu	-32(%rdx),%xmm14
+	vpxor	%xmm1,%xmm4,%xmm4
+	vpclmulqdq	$0x11,%xmm6,%xmm15,%xmm1
+	vmovdqu	16-64(%rsi),%xmm6
+	vpshufb	%xmm13,%xmm14,%xmm15
+	vpxor	%xmm2,%xmm5,%xmm5
+	vpclmulqdq	$0x00,%xmm7,%xmm8,%xmm2
+	vpsrldq	$8,%xmm7,%xmm7
+	subq	$0x10,%rcx
+	jz	.Ltail_avx
+
+	vpunpckhqdq	%xmm15,%xmm15,%xmm8
+	vpxor	%xmm0,%xmm3,%xmm3
+	vpclmulqdq	$0x00,%xmm6,%xmm15,%xmm0
+	vpxor	%xmm15,%xmm8,%xmm8
+	vmovdqu	-48(%rdx),%xmm14
+	vpxor	%xmm1,%xmm4,%xmm4
+	vpclmulqdq	$0x11,%xmm6,%xmm15,%xmm1
+	vmovdqu	48-64(%rsi),%xmm6
+	vpshufb	%xmm13,%xmm14,%xmm15
+	vpxor	%xmm2,%xmm5,%xmm5
+	vpclmulqdq	$0x00,%xmm7,%xmm8,%xmm2
+	vmovdqu	80-64(%rsi),%xmm7
+	subq	$0x10,%rcx
+	jz	.Ltail_avx
+
+	vpunpckhqdq	%xmm15,%xmm15,%xmm8
+	vpxor	%xmm0,%xmm3,%xmm3
+	vpclmulqdq	$0x00,%xmm6,%xmm15,%xmm0
+	vpxor	%xmm15,%xmm8,%xmm8
+	vmovdqu	-64(%rdx),%xmm14
+	vpxor	%xmm1,%xmm4,%xmm4
+	vpclmulqdq	$0x11,%xmm6,%xmm15,%xmm1
+	vmovdqu	64-64(%rsi),%xmm6
+	vpshufb	%xmm13,%xmm14,%xmm15
+	vpxor	%xmm2,%xmm5,%xmm5
+	vpclmulqdq	$0x00,%xmm7,%xmm8,%xmm2
+	vpsrldq	$8,%xmm7,%xmm7
+	subq	$0x10,%rcx
+	jz	.Ltail_avx
+
+	vpunpckhqdq	%xmm15,%xmm15,%xmm8
+	vpxor	%xmm0,%xmm3,%xmm3
+	vpclmulqdq	$0x00,%xmm6,%xmm15,%xmm0
+	vpxor	%xmm15,%xmm8,%xmm8
+	vmovdqu	-80(%rdx),%xmm14
+	vpxor	%xmm1,%xmm4,%xmm4
+	vpclmulqdq	$0x11,%xmm6,%xmm15,%xmm1
+	vmovdqu	96-64(%rsi),%xmm6
+	vpshufb	%xmm13,%xmm14,%xmm15
+	vpxor	%xmm2,%xmm5,%xmm5
+	vpclmulqdq	$0x00,%xmm7,%xmm8,%xmm2
+	vmovdqu	128-64(%rsi),%xmm7
+	subq	$0x10,%rcx
+	jz	.Ltail_avx
+
+	vpunpckhqdq	%xmm15,%xmm15,%xmm8
+	vpxor	%xmm0,%xmm3,%xmm3
+	vpclmulqdq	$0x00,%xmm6,%xmm15,%xmm0
+	vpxor	%xmm15,%xmm8,%xmm8
+	vmovdqu	-96(%rdx),%xmm14
+	vpxor	%xmm1,%xmm4,%xmm4
+	vpclmulqdq	$0x11,%xmm6,%xmm15,%xmm1
+	vmovdqu	112-64(%rsi),%xmm6
+	vpshufb	%xmm13,%xmm14,%xmm15
+	vpxor	%xmm2,%xmm5,%xmm5
+	vpclmulqdq	$0x00,%xmm7,%xmm8,%xmm2
+	vpsrldq	$8,%xmm7,%xmm7
+	subq	$0x10,%rcx
+	jz	.Ltail_avx
+
+	vpunpckhqdq	%xmm15,%xmm15,%xmm8
+	vpxor	%xmm0,%xmm3,%xmm3
+	vpclmulqdq	$0x00,%xmm6,%xmm15,%xmm0
+	vpxor	%xmm15,%xmm8,%xmm8
+	vmovdqu	-112(%rdx),%xmm14
+	vpxor	%xmm1,%xmm4,%xmm4
+	vpclmulqdq	$0x11,%xmm6,%xmm15,%xmm1
+	vmovdqu	144-64(%rsi),%xmm6
+	vpshufb	%xmm13,%xmm14,%xmm15
+	vpxor	%xmm2,%xmm5,%xmm5
+	vpclmulqdq	$0x00,%xmm7,%xmm8,%xmm2
+	vmovq	184-64(%rsi),%xmm7
+	subq	$0x10,%rcx
+	jmp	.Ltail_avx
+
+.align	32
+.Ltail_avx:
+	vpxor	%xmm10,%xmm15,%xmm15
+.Ltail_no_xor_avx:
+	vpunpckhqdq	%xmm15,%xmm15,%xmm8
+	vpxor	%xmm0,%xmm3,%xmm3
+	vpclmulqdq	$0x00,%xmm6,%xmm15,%xmm0
+	vpxor	%xmm15,%xmm8,%xmm8
+	vpxor	%xmm1,%xmm4,%xmm4
+	vpclmulqdq	$0x11,%xmm6,%xmm15,%xmm1
+	vpxor	%xmm2,%xmm5,%xmm5
+	vpclmulqdq	$0x00,%xmm7,%xmm8,%xmm2
+
+	vmovdqu	(%r10),%xmm12
+
+	vpxor	%xmm0,%xmm3,%xmm10
+	vpxor	%xmm1,%xmm4,%xmm11
+	vpxor	%xmm2,%xmm5,%xmm5
+
+	vpxor	%xmm10,%xmm5,%xmm5
+	vpxor	%xmm11,%xmm5,%xmm5
+	vpslldq	$8,%xmm5,%xmm9
+	vpsrldq	$8,%xmm5,%xmm5
+	vpxor	%xmm9,%xmm10,%xmm10
+	vpxor	%xmm5,%xmm11,%xmm11
+
+	vpclmulqdq	$0x10,%xmm12,%xmm10,%xmm9
+	vpalignr	$8,%xmm10,%xmm10,%xmm10
+	vpxor	%xmm9,%xmm10,%xmm10
+
+	vpclmulqdq	$0x10,%xmm12,%xmm10,%xmm9
+	vpalignr	$8,%xmm10,%xmm10,%xmm10
+	vpxor	%xmm11,%xmm10,%xmm10
+	vpxor	%xmm9,%xmm10,%xmm10
+
+	cmpq	$0,%rcx
+	jne	.Lshort_avx
+
+	vpshufb	%xmm13,%xmm10,%xmm10
+	vmovdqu	%xmm10,(%rdi)
+	vzeroupper
+	.byte	0xf3,0xc3
 .size	gcm_ghash_avx,.-gcm_ghash_avx
 .align	64
 .Lbswap_mask:
diff --git a/linux-x86_64/crypto/rc4/rc4-x86_64.S b/linux-x86_64/crypto/rc4/rc4-x86_64.S
deleted file mode 100644
index c4d1002..0000000
--- a/linux-x86_64/crypto/rc4/rc4-x86_64.S
+++ /dev/null
@@ -1,596 +0,0 @@
-#if defined(__x86_64__)
-.text	
-.extern	OPENSSL_ia32cap_P
-.hidden OPENSSL_ia32cap_P
-
-.globl	asm_RC4
-.hidden asm_RC4
-.type	asm_RC4,@function
-.align	16
-asm_RC4:
-	orq	%rsi,%rsi
-	jne	.Lentry
-	.byte	0xf3,0xc3
-.Lentry:
-	pushq	%rbx
-	pushq	%r12
-	pushq	%r13
-.Lprologue:
-	movq	%rsi,%r11
-	movq	%rdx,%r12
-	movq	%rcx,%r13
-	xorq	%r10,%r10
-	xorq	%rcx,%rcx
-
-	leaq	8(%rdi),%rdi
-	movb	-8(%rdi),%r10b
-	movb	-4(%rdi),%cl
-	cmpl	$-1,256(%rdi)
-	je	.LRC4_CHAR
-	movl	OPENSSL_ia32cap_P(%rip),%r8d
-	xorq	%rbx,%rbx
-	incb	%r10b
-	subq	%r10,%rbx
-	subq	%r12,%r13
-	movl	(%rdi,%r10,4),%eax
-	testq	$-16,%r11
-	jz	.Lloop1
-	btl	$30,%r8d
-	jc	.Lintel
-	andq	$7,%rbx
-	leaq	1(%r10),%rsi
-	jz	.Loop8
-	subq	%rbx,%r11
-.Loop8_warmup:
-	addb	%al,%cl
-	movl	(%rdi,%rcx,4),%edx
-	movl	%eax,(%rdi,%rcx,4)
-	movl	%edx,(%rdi,%r10,4)
-	addb	%dl,%al
-	incb	%r10b
-	movl	(%rdi,%rax,4),%edx
-	movl	(%rdi,%r10,4),%eax
-	xorb	(%r12),%dl
-	movb	%dl,(%r12,%r13,1)
-	leaq	1(%r12),%r12
-	decq	%rbx
-	jnz	.Loop8_warmup
-
-	leaq	1(%r10),%rsi
-	jmp	.Loop8
-.align	16
-.Loop8:
-	addb	%al,%cl
-	movl	(%rdi,%rcx,4),%edx
-	movl	%eax,(%rdi,%rcx,4)
-	movl	0(%rdi,%rsi,4),%ebx
-	rorq	$8,%r8
-	movl	%edx,0(%rdi,%r10,4)
-	addb	%al,%dl
-	movb	(%rdi,%rdx,4),%r8b
-	addb	%bl,%cl
-	movl	(%rdi,%rcx,4),%edx
-	movl	%ebx,(%rdi,%rcx,4)
-	movl	4(%rdi,%rsi,4),%eax
-	rorq	$8,%r8
-	movl	%edx,4(%rdi,%r10,4)
-	addb	%bl,%dl
-	movb	(%rdi,%rdx,4),%r8b
-	addb	%al,%cl
-	movl	(%rdi,%rcx,4),%edx
-	movl	%eax,(%rdi,%rcx,4)
-	movl	8(%rdi,%rsi,4),%ebx
-	rorq	$8,%r8
-	movl	%edx,8(%rdi,%r10,4)
-	addb	%al,%dl
-	movb	(%rdi,%rdx,4),%r8b
-	addb	%bl,%cl
-	movl	(%rdi,%rcx,4),%edx
-	movl	%ebx,(%rdi,%rcx,4)
-	movl	12(%rdi,%rsi,4),%eax
-	rorq	$8,%r8
-	movl	%edx,12(%rdi,%r10,4)
-	addb	%bl,%dl
-	movb	(%rdi,%rdx,4),%r8b
-	addb	%al,%cl
-	movl	(%rdi,%rcx,4),%edx
-	movl	%eax,(%rdi,%rcx,4)
-	movl	16(%rdi,%rsi,4),%ebx
-	rorq	$8,%r8
-	movl	%edx,16(%rdi,%r10,4)
-	addb	%al,%dl
-	movb	(%rdi,%rdx,4),%r8b
-	addb	%bl,%cl
-	movl	(%rdi,%rcx,4),%edx
-	movl	%ebx,(%rdi,%rcx,4)
-	movl	20(%rdi,%rsi,4),%eax
-	rorq	$8,%r8
-	movl	%edx,20(%rdi,%r10,4)
-	addb	%bl,%dl
-	movb	(%rdi,%rdx,4),%r8b
-	addb	%al,%cl
-	movl	(%rdi,%rcx,4),%edx
-	movl	%eax,(%rdi,%rcx,4)
-	movl	24(%rdi,%rsi,4),%ebx
-	rorq	$8,%r8
-	movl	%edx,24(%rdi,%r10,4)
-	addb	%al,%dl
-	movb	(%rdi,%rdx,4),%r8b
-	addb	$8,%sil
-	addb	%bl,%cl
-	movl	(%rdi,%rcx,4),%edx
-	movl	%ebx,(%rdi,%rcx,4)
-	movl	-4(%rdi,%rsi,4),%eax
-	rorq	$8,%r8
-	movl	%edx,28(%rdi,%r10,4)
-	addb	%bl,%dl
-	movb	(%rdi,%rdx,4),%r8b
-	addb	$8,%r10b
-	rorq	$8,%r8
-	subq	$8,%r11
-
-	xorq	(%r12),%r8
-	movq	%r8,(%r12,%r13,1)
-	leaq	8(%r12),%r12
-
-	testq	$-8,%r11
-	jnz	.Loop8
-	cmpq	$0,%r11
-	jne	.Lloop1
-	jmp	.Lexit
-
-.align	16
-.Lintel:
-	testq	$-32,%r11
-	jz	.Lloop1
-	andq	$15,%rbx
-	jz	.Loop16_is_hot
-	subq	%rbx,%r11
-.Loop16_warmup:
-	addb	%al,%cl
-	movl	(%rdi,%rcx,4),%edx
-	movl	%eax,(%rdi,%rcx,4)
-	movl	%edx,(%rdi,%r10,4)
-	addb	%dl,%al
-	incb	%r10b
-	movl	(%rdi,%rax,4),%edx
-	movl	(%rdi,%r10,4),%eax
-	xorb	(%r12),%dl
-	movb	%dl,(%r12,%r13,1)
-	leaq	1(%r12),%r12
-	decq	%rbx
-	jnz	.Loop16_warmup
-
-	movq	%rcx,%rbx
-	xorq	%rcx,%rcx
-	movb	%bl,%cl
-
-.Loop16_is_hot:
-	leaq	(%rdi,%r10,4),%rsi
-	addb	%al,%cl
-	movl	(%rdi,%rcx,4),%edx
-	pxor	%xmm0,%xmm0
-	movl	%eax,(%rdi,%rcx,4)
-	addb	%dl,%al
-	movl	4(%rsi),%ebx
-	movzbl	%al,%eax
-	movl	%edx,0(%rsi)
-	addb	%bl,%cl
-	pinsrw	$0,(%rdi,%rax,4),%xmm0
-	jmp	.Loop16_enter
-.align	16
-.Loop16:
-	addb	%al,%cl
-	movl	(%rdi,%rcx,4),%edx
-	pxor	%xmm0,%xmm2
-	psllq	$8,%xmm1
-	pxor	%xmm0,%xmm0
-	movl	%eax,(%rdi,%rcx,4)
-	addb	%dl,%al
-	movl	4(%rsi),%ebx
-	movzbl	%al,%eax
-	movl	%edx,0(%rsi)
-	pxor	%xmm1,%xmm2
-	addb	%bl,%cl
-	pinsrw	$0,(%rdi,%rax,4),%xmm0
-	movdqu	%xmm2,(%r12,%r13,1)
-	leaq	16(%r12),%r12
-.Loop16_enter:
-	movl	(%rdi,%rcx,4),%edx
-	pxor	%xmm1,%xmm1
-	movl	%ebx,(%rdi,%rcx,4)
-	addb	%dl,%bl
-	movl	8(%rsi),%eax
-	movzbl	%bl,%ebx
-	movl	%edx,4(%rsi)
-	addb	%al,%cl
-	pinsrw	$0,(%rdi,%rbx,4),%xmm1
-	movl	(%rdi,%rcx,4),%edx
-	movl	%eax,(%rdi,%rcx,4)
-	addb	%dl,%al
-	movl	12(%rsi),%ebx
-	movzbl	%al,%eax
-	movl	%edx,8(%rsi)
-	addb	%bl,%cl
-	pinsrw	$1,(%rdi,%rax,4),%xmm0
-	movl	(%rdi,%rcx,4),%edx
-	movl	%ebx,(%rdi,%rcx,4)
-	addb	%dl,%bl
-	movl	16(%rsi),%eax
-	movzbl	%bl,%ebx
-	movl	%edx,12(%rsi)
-	addb	%al,%cl
-	pinsrw	$1,(%rdi,%rbx,4),%xmm1
-	movl	(%rdi,%rcx,4),%edx
-	movl	%eax,(%rdi,%rcx,4)
-	addb	%dl,%al
-	movl	20(%rsi),%ebx
-	movzbl	%al,%eax
-	movl	%edx,16(%rsi)
-	addb	%bl,%cl
-	pinsrw	$2,(%rdi,%rax,4),%xmm0
-	movl	(%rdi,%rcx,4),%edx
-	movl	%ebx,(%rdi,%rcx,4)
-	addb	%dl,%bl
-	movl	24(%rsi),%eax
-	movzbl	%bl,%ebx
-	movl	%edx,20(%rsi)
-	addb	%al,%cl
-	pinsrw	$2,(%rdi,%rbx,4),%xmm1
-	movl	(%rdi,%rcx,4),%edx
-	movl	%eax,(%rdi,%rcx,4)
-	addb	%dl,%al
-	movl	28(%rsi),%ebx
-	movzbl	%al,%eax
-	movl	%edx,24(%rsi)
-	addb	%bl,%cl
-	pinsrw	$3,(%rdi,%rax,4),%xmm0
-	movl	(%rdi,%rcx,4),%edx
-	movl	%ebx,(%rdi,%rcx,4)
-	addb	%dl,%bl
-	movl	32(%rsi),%eax
-	movzbl	%bl,%ebx
-	movl	%edx,28(%rsi)
-	addb	%al,%cl
-	pinsrw	$3,(%rdi,%rbx,4),%xmm1
-	movl	(%rdi,%rcx,4),%edx
-	movl	%eax,(%rdi,%rcx,4)
-	addb	%dl,%al
-	movl	36(%rsi),%ebx
-	movzbl	%al,%eax
-	movl	%edx,32(%rsi)
-	addb	%bl,%cl
-	pinsrw	$4,(%rdi,%rax,4),%xmm0
-	movl	(%rdi,%rcx,4),%edx
-	movl	%ebx,(%rdi,%rcx,4)
-	addb	%dl,%bl
-	movl	40(%rsi),%eax
-	movzbl	%bl,%ebx
-	movl	%edx,36(%rsi)
-	addb	%al,%cl
-	pinsrw	$4,(%rdi,%rbx,4),%xmm1
-	movl	(%rdi,%rcx,4),%edx
-	movl	%eax,(%rdi,%rcx,4)
-	addb	%dl,%al
-	movl	44(%rsi),%ebx
-	movzbl	%al,%eax
-	movl	%edx,40(%rsi)
-	addb	%bl,%cl
-	pinsrw	$5,(%rdi,%rax,4),%xmm0
-	movl	(%rdi,%rcx,4),%edx
-	movl	%ebx,(%rdi,%rcx,4)
-	addb	%dl,%bl
-	movl	48(%rsi),%eax
-	movzbl	%bl,%ebx
-	movl	%edx,44(%rsi)
-	addb	%al,%cl
-	pinsrw	$5,(%rdi,%rbx,4),%xmm1
-	movl	(%rdi,%rcx,4),%edx
-	movl	%eax,(%rdi,%rcx,4)
-	addb	%dl,%al
-	movl	52(%rsi),%ebx
-	movzbl	%al,%eax
-	movl	%edx,48(%rsi)
-	addb	%bl,%cl
-	pinsrw	$6,(%rdi,%rax,4),%xmm0
-	movl	(%rdi,%rcx,4),%edx
-	movl	%ebx,(%rdi,%rcx,4)
-	addb	%dl,%bl
-	movl	56(%rsi),%eax
-	movzbl	%bl,%ebx
-	movl	%edx,52(%rsi)
-	addb	%al,%cl
-	pinsrw	$6,(%rdi,%rbx,4),%xmm1
-	movl	(%rdi,%rcx,4),%edx
-	movl	%eax,(%rdi,%rcx,4)
-	addb	%dl,%al
-	movl	60(%rsi),%ebx
-	movzbl	%al,%eax
-	movl	%edx,56(%rsi)
-	addb	%bl,%cl
-	pinsrw	$7,(%rdi,%rax,4),%xmm0
-	addb	$16,%r10b
-	movdqu	(%r12),%xmm2
-	movl	(%rdi,%rcx,4),%edx
-	movl	%ebx,(%rdi,%rcx,4)
-	addb	%dl,%bl
-	movzbl	%bl,%ebx
-	movl	%edx,60(%rsi)
-	leaq	(%rdi,%r10,4),%rsi
-	pinsrw	$7,(%rdi,%rbx,4),%xmm1
-	movl	(%rsi),%eax
-	movq	%rcx,%rbx
-	xorq	%rcx,%rcx
-	subq	$16,%r11
-	movb	%bl,%cl
-	testq	$-16,%r11
-	jnz	.Loop16
-
-	psllq	$8,%xmm1
-	pxor	%xmm0,%xmm2
-	pxor	%xmm1,%xmm2
-	movdqu	%xmm2,(%r12,%r13,1)
-	leaq	16(%r12),%r12
-
-	cmpq	$0,%r11
-	jne	.Lloop1
-	jmp	.Lexit
-
-.align	16
-.Lloop1:
-	addb	%al,%cl
-	movl	(%rdi,%rcx,4),%edx
-	movl	%eax,(%rdi,%rcx,4)
-	movl	%edx,(%rdi,%r10,4)
-	addb	%dl,%al
-	incb	%r10b
-	movl	(%rdi,%rax,4),%edx
-	movl	(%rdi,%r10,4),%eax
-	xorb	(%r12),%dl
-	movb	%dl,(%r12,%r13,1)
-	leaq	1(%r12),%r12
-	decq	%r11
-	jnz	.Lloop1
-	jmp	.Lexit
-
-.align	16
-.LRC4_CHAR:
-	addb	$1,%r10b
-	movzbl	(%rdi,%r10,1),%eax
-	testq	$-8,%r11
-	jz	.Lcloop1
-	jmp	.Lcloop8
-.align	16
-.Lcloop8:
-	movl	(%r12),%r8d
-	movl	4(%r12),%r9d
-	addb	%al,%cl
-	leaq	1(%r10),%rsi
-	movzbl	(%rdi,%rcx,1),%edx
-	movzbl	%sil,%esi
-	movzbl	(%rdi,%rsi,1),%ebx
-	movb	%al,(%rdi,%rcx,1)
-	cmpq	%rsi,%rcx
-	movb	%dl,(%rdi,%r10,1)
-	jne	.Lcmov0
-	movq	%rax,%rbx
-.Lcmov0:
-	addb	%al,%dl
-	xorb	(%rdi,%rdx,1),%r8b
-	rorl	$8,%r8d
-	addb	%bl,%cl
-	leaq	1(%rsi),%r10
-	movzbl	(%rdi,%rcx,1),%edx
-	movzbl	%r10b,%r10d
-	movzbl	(%rdi,%r10,1),%eax
-	movb	%bl,(%rdi,%rcx,1)
-	cmpq	%r10,%rcx
-	movb	%dl,(%rdi,%rsi,1)
-	jne	.Lcmov1
-	movq	%rbx,%rax
-.Lcmov1:
-	addb	%bl,%dl
-	xorb	(%rdi,%rdx,1),%r8b
-	rorl	$8,%r8d
-	addb	%al,%cl
-	leaq	1(%r10),%rsi
-	movzbl	(%rdi,%rcx,1),%edx
-	movzbl	%sil,%esi
-	movzbl	(%rdi,%rsi,1),%ebx
-	movb	%al,(%rdi,%rcx,1)
-	cmpq	%rsi,%rcx
-	movb	%dl,(%rdi,%r10,1)
-	jne	.Lcmov2
-	movq	%rax,%rbx
-.Lcmov2:
-	addb	%al,%dl
-	xorb	(%rdi,%rdx,1),%r8b
-	rorl	$8,%r8d
-	addb	%bl,%cl
-	leaq	1(%rsi),%r10
-	movzbl	(%rdi,%rcx,1),%edx
-	movzbl	%r10b,%r10d
-	movzbl	(%rdi,%r10,1),%eax
-	movb	%bl,(%rdi,%rcx,1)
-	cmpq	%r10,%rcx
-	movb	%dl,(%rdi,%rsi,1)
-	jne	.Lcmov3
-	movq	%rbx,%rax
-.Lcmov3:
-	addb	%bl,%dl
-	xorb	(%rdi,%rdx,1),%r8b
-	rorl	$8,%r8d
-	addb	%al,%cl
-	leaq	1(%r10),%rsi
-	movzbl	(%rdi,%rcx,1),%edx
-	movzbl	%sil,%esi
-	movzbl	(%rdi,%rsi,1),%ebx
-	movb	%al,(%rdi,%rcx,1)
-	cmpq	%rsi,%rcx
-	movb	%dl,(%rdi,%r10,1)
-	jne	.Lcmov4
-	movq	%rax,%rbx
-.Lcmov4:
-	addb	%al,%dl
-	xorb	(%rdi,%rdx,1),%r9b
-	rorl	$8,%r9d
-	addb	%bl,%cl
-	leaq	1(%rsi),%r10
-	movzbl	(%rdi,%rcx,1),%edx
-	movzbl	%r10b,%r10d
-	movzbl	(%rdi,%r10,1),%eax
-	movb	%bl,(%rdi,%rcx,1)
-	cmpq	%r10,%rcx
-	movb	%dl,(%rdi,%rsi,1)
-	jne	.Lcmov5
-	movq	%rbx,%rax
-.Lcmov5:
-	addb	%bl,%dl
-	xorb	(%rdi,%rdx,1),%r9b
-	rorl	$8,%r9d
-	addb	%al,%cl
-	leaq	1(%r10),%rsi
-	movzbl	(%rdi,%rcx,1),%edx
-	movzbl	%sil,%esi
-	movzbl	(%rdi,%rsi,1),%ebx
-	movb	%al,(%rdi,%rcx,1)
-	cmpq	%rsi,%rcx
-	movb	%dl,(%rdi,%r10,1)
-	jne	.Lcmov6
-	movq	%rax,%rbx
-.Lcmov6:
-	addb	%al,%dl
-	xorb	(%rdi,%rdx,1),%r9b
-	rorl	$8,%r9d
-	addb	%bl,%cl
-	leaq	1(%rsi),%r10
-	movzbl	(%rdi,%rcx,1),%edx
-	movzbl	%r10b,%r10d
-	movzbl	(%rdi,%r10,1),%eax
-	movb	%bl,(%rdi,%rcx,1)
-	cmpq	%r10,%rcx
-	movb	%dl,(%rdi,%rsi,1)
-	jne	.Lcmov7
-	movq	%rbx,%rax
-.Lcmov7:
-	addb	%bl,%dl
-	xorb	(%rdi,%rdx,1),%r9b
-	rorl	$8,%r9d
-	leaq	-8(%r11),%r11
-	movl	%r8d,(%r13)
-	leaq	8(%r12),%r12
-	movl	%r9d,4(%r13)
-	leaq	8(%r13),%r13
-
-	testq	$-8,%r11
-	jnz	.Lcloop8
-	cmpq	$0,%r11
-	jne	.Lcloop1
-	jmp	.Lexit
-.align	16
-.Lcloop1:
-	addb	%al,%cl
-	movzbl	%cl,%ecx
-	movzbl	(%rdi,%rcx,1),%edx
-	movb	%al,(%rdi,%rcx,1)
-	movb	%dl,(%rdi,%r10,1)
-	addb	%al,%dl
-	addb	$1,%r10b
-	movzbl	%dl,%edx
-	movzbl	%r10b,%r10d
-	movzbl	(%rdi,%rdx,1),%edx
-	movzbl	(%rdi,%r10,1),%eax
-	xorb	(%r12),%dl
-	leaq	1(%r12),%r12
-	movb	%dl,(%r13)
-	leaq	1(%r13),%r13
-	subq	$1,%r11
-	jnz	.Lcloop1
-	jmp	.Lexit
-
-.align	16
-.Lexit:
-	subb	$1,%r10b
-	movl	%r10d,-8(%rdi)
-	movl	%ecx,-4(%rdi)
-
-	movq	(%rsp),%r13
-	movq	8(%rsp),%r12
-	movq	16(%rsp),%rbx
-	addq	$24,%rsp
-.Lepilogue:
-	.byte	0xf3,0xc3
-.size	asm_RC4,.-asm_RC4
-.globl	asm_RC4_set_key
-.hidden asm_RC4_set_key
-.type	asm_RC4_set_key,@function
-.align	16
-asm_RC4_set_key:
-	leaq	8(%rdi),%rdi
-	leaq	(%rdx,%rsi,1),%rdx
-	negq	%rsi
-	movq	%rsi,%rcx
-	xorl	%eax,%eax
-	xorq	%r9,%r9
-	xorq	%r10,%r10
-	xorq	%r11,%r11
-
-	movl	OPENSSL_ia32cap_P(%rip),%r8d
-	btl	$20,%r8d
-	jc	.Lc1stloop
-	jmp	.Lw1stloop
-
-.align	16
-.Lw1stloop:
-	movl	%eax,(%rdi,%rax,4)
-	addb	$1,%al
-	jnc	.Lw1stloop
-
-	xorq	%r9,%r9
-	xorq	%r8,%r8
-.align	16
-.Lw2ndloop:
-	movl	(%rdi,%r9,4),%r10d
-	addb	(%rdx,%rsi,1),%r8b
-	addb	%r10b,%r8b
-	addq	$1,%rsi
-	movl	(%rdi,%r8,4),%r11d
-	cmovzq	%rcx,%rsi
-	movl	%r10d,(%rdi,%r8,4)
-	movl	%r11d,(%rdi,%r9,4)
-	addb	$1,%r9b
-	jnc	.Lw2ndloop
-	jmp	.Lexit_key
-
-.align	16
-.Lc1stloop:
-	movb	%al,(%rdi,%rax,1)
-	addb	$1,%al
-	jnc	.Lc1stloop
-
-	xorq	%r9,%r9
-	xorq	%r8,%r8
-.align	16
-.Lc2ndloop:
-	movb	(%rdi,%r9,1),%r10b
-	addb	(%rdx,%rsi,1),%r8b
-	addb	%r10b,%r8b
-	addq	$1,%rsi
-	movb	(%rdi,%r8,1),%r11b
-	jnz	.Lcnowrap
-	movq	%rcx,%rsi
-.Lcnowrap:
-	movb	%r10b,(%rdi,%r8,1)
-	movb	%r11b,(%rdi,%r9,1)
-	addb	$1,%r9b
-	jnc	.Lc2ndloop
-	movl	$-1,256(%rdi)
-
-.align	16
-.Lexit_key:
-	xorl	%eax,%eax
-	movl	%eax,-8(%rdi)
-	movl	%eax,-4(%rdi)
-	.byte	0xf3,0xc3
-.size	asm_RC4_set_key,.-asm_RC4_set_key
-#endif
diff --git a/linux-x86_64/crypto/sha/sha1-x86_64.S b/linux-x86_64/crypto/sha/sha1-x86_64.S
index d830b53..567bdfd 100644
--- a/linux-x86_64/crypto/sha/sha1-x86_64.S
+++ b/linux-x86_64/crypto/sha/sha1-x86_64.S
@@ -1241,14 +1241,13 @@
 .align	16
 sha1_block_data_order_ssse3:
 _ssse3_shortcut:
-	movq	%rsp,%rax
+	movq	%rsp,%r11
 	pushq	%rbx
 	pushq	%rbp
 	pushq	%r12
 	pushq	%r13
 	pushq	%r14
 	leaq	-64(%rsp),%rsp
-	movq	%rax,%r14
 	andq	$-64,%rsp
 	movq	%rdi,%r8
 	movq	%rsi,%r9
@@ -1256,7 +1255,7 @@
 
 	shlq	$6,%r10
 	addq	%r9,%r10
-	leaq	K_XX_XX+64(%rip),%r11
+	leaq	K_XX_XX+64(%rip),%r14
 
 	movl	0(%r8),%eax
 	movl	4(%r8),%ebx
@@ -1268,8 +1267,8 @@
 	xorl	%edx,%edi
 	andl	%edi,%esi
 
-	movdqa	64(%r11),%xmm6
-	movdqa	-64(%r11),%xmm9
+	movdqa	64(%r14),%xmm6
+	movdqa	-64(%r14),%xmm9
 	movdqu	0(%r9),%xmm0
 	movdqu	16(%r9),%xmm1
 	movdqu	32(%r9),%xmm2
@@ -1345,7 +1344,7 @@
 	pslld	$2,%xmm9
 	pxor	%xmm10,%xmm4
 	xorl	%ebp,%edx
-	movdqa	-64(%r11),%xmm10
+	movdqa	-64(%r14),%xmm10
 	roll	$5,%ecx
 	addl	%edi,%ebx
 	andl	%edx,%esi
@@ -1406,7 +1405,7 @@
 	pslld	$2,%xmm10
 	pxor	%xmm8,%xmm5
 	xorl	%eax,%ebp
-	movdqa	-32(%r11),%xmm8
+	movdqa	-32(%r14),%xmm8
 	roll	$5,%edx
 	addl	%edi,%ecx
 	andl	%ebp,%esi
@@ -1467,7 +1466,7 @@
 	pslld	$2,%xmm8
 	pxor	%xmm9,%xmm6
 	xorl	%ebx,%eax
-	movdqa	-32(%r11),%xmm9
+	movdqa	-32(%r14),%xmm9
 	roll	$5,%ebp
 	addl	%edi,%edx
 	andl	%eax,%esi
@@ -1528,7 +1527,7 @@
 	pslld	$2,%xmm9
 	pxor	%xmm10,%xmm7
 	xorl	%ecx,%ebx
-	movdqa	-32(%r11),%xmm10
+	movdqa	-32(%r14),%xmm10
 	roll	$5,%eax
 	addl	%edi,%ebp
 	andl	%ebx,%esi
@@ -1639,7 +1638,7 @@
 	pxor	%xmm3,%xmm2
 	addl	%esi,%eax
 	xorl	%edx,%edi
-	movdqa	0(%r11),%xmm10
+	movdqa	0(%r14),%xmm10
 	rorl	$7,%ecx
 	paddd	%xmm1,%xmm9
 	addl	%ebx,%eax
@@ -1874,7 +1873,7 @@
 	pxor	%xmm0,%xmm7
 	roll	$5,%ebx
 	addl	%esi,%eax
-	movdqa	32(%r11),%xmm9
+	movdqa	32(%r14),%xmm9
 	xorl	%ecx,%edi
 	paddd	%xmm6,%xmm8
 	xorl	%edx,%ecx
@@ -2165,8 +2164,8 @@
 	addl	%edx,%ecx
 	cmpq	%r10,%r9
 	je	.Ldone_ssse3
-	movdqa	64(%r11),%xmm6
-	movdqa	-64(%r11),%xmm9
+	movdqa	64(%r14),%xmm6
+	movdqa	-64(%r14),%xmm9
 	movdqu	0(%r9),%xmm0
 	movdqu	16(%r9),%xmm1
 	movdqu	32(%r9),%xmm2
@@ -2403,13 +2402,12 @@
 	movl	%ecx,8(%r8)
 	movl	%edx,12(%r8)
 	movl	%ebp,16(%r8)
-	leaq	(%r14),%rsi
-	movq	-40(%rsi),%r14
-	movq	-32(%rsi),%r13
-	movq	-24(%rsi),%r12
-	movq	-16(%rsi),%rbp
-	movq	-8(%rsi),%rbx
-	leaq	(%rsi),%rsp
+	movq	-40(%r11),%r14
+	movq	-32(%r11),%r13
+	movq	-24(%r11),%r12
+	movq	-16(%r11),%rbp
+	movq	-8(%r11),%rbx
+	leaq	(%r11),%rsp
 .Lepilogue_ssse3:
 	.byte	0xf3,0xc3
 .size	sha1_block_data_order_ssse3,.-sha1_block_data_order_ssse3
@@ -2417,7 +2415,7 @@
 .align	16
 sha1_block_data_order_avx:
 _avx_shortcut:
-	movq	%rsp,%rax
+	movq	%rsp,%r11
 	pushq	%rbx
 	pushq	%rbp
 	pushq	%r12
@@ -2425,7 +2423,6 @@
 	pushq	%r14
 	leaq	-64(%rsp),%rsp
 	vzeroupper
-	movq	%rax,%r14
 	andq	$-64,%rsp
 	movq	%rdi,%r8
 	movq	%rsi,%r9
@@ -2433,7 +2430,7 @@
 
 	shlq	$6,%r10
 	addq	%r9,%r10
-	leaq	K_XX_XX+64(%rip),%r11
+	leaq	K_XX_XX+64(%rip),%r14
 
 	movl	0(%r8),%eax
 	movl	4(%r8),%ebx
@@ -2445,8 +2442,8 @@
 	xorl	%edx,%edi
 	andl	%edi,%esi
 
-	vmovdqa	64(%r11),%xmm6
-	vmovdqa	-64(%r11),%xmm11
+	vmovdqa	64(%r14),%xmm6
+	vmovdqa	-64(%r14),%xmm11
 	vmovdqu	0(%r9),%xmm0
 	vmovdqu	16(%r9),%xmm1
 	vmovdqu	32(%r9),%xmm2
@@ -2571,7 +2568,7 @@
 	vpxor	%xmm10,%xmm5,%xmm5
 	xorl	%eax,%ebp
 	shldl	$5,%edx,%edx
-	vmovdqa	-32(%r11),%xmm11
+	vmovdqa	-32(%r14),%xmm11
 	addl	%edi,%ecx
 	andl	%ebp,%esi
 	xorl	%eax,%ebp
@@ -2784,7 +2781,7 @@
 	addl	%esi,%eax
 	xorl	%edx,%edi
 	vpaddd	%xmm1,%xmm11,%xmm9
-	vmovdqa	0(%r11),%xmm11
+	vmovdqa	0(%r14),%xmm11
 	shrdl	$7,%ecx,%ecx
 	addl	%ebx,%eax
 	vpxor	%xmm8,%xmm2,%xmm2
@@ -3003,7 +3000,7 @@
 	movl	%ebx,%edi
 	xorl	%edx,%esi
 	vpaddd	%xmm6,%xmm11,%xmm9
-	vmovdqa	32(%r11),%xmm11
+	vmovdqa	32(%r14),%xmm11
 	shldl	$5,%ebx,%ebx
 	addl	%esi,%eax
 	vpxor	%xmm8,%xmm7,%xmm7
@@ -3282,8 +3279,8 @@
 	addl	%edx,%ecx
 	cmpq	%r10,%r9
 	je	.Ldone_avx
-	vmovdqa	64(%r11),%xmm6
-	vmovdqa	-64(%r11),%xmm11
+	vmovdqa	64(%r14),%xmm6
+	vmovdqa	-64(%r14),%xmm11
 	vmovdqu	0(%r9),%xmm0
 	vmovdqu	16(%r9),%xmm1
 	vmovdqu	32(%r9),%xmm2
@@ -3519,13 +3516,12 @@
 	movl	%ecx,8(%r8)
 	movl	%edx,12(%r8)
 	movl	%ebp,16(%r8)
-	leaq	(%r14),%rsi
-	movq	-40(%rsi),%r14
-	movq	-32(%rsi),%r13
-	movq	-24(%rsi),%r12
-	movq	-16(%rsi),%rbp
-	movq	-8(%rsi),%rbx
-	leaq	(%rsi),%rsp
+	movq	-40(%r11),%r14
+	movq	-32(%r11),%r13
+	movq	-24(%r11),%r12
+	movq	-16(%r11),%rbp
+	movq	-8(%r11),%rbx
+	leaq	(%r11),%rsp
 .Lepilogue_avx:
 	.byte	0xf3,0xc3
 .size	sha1_block_data_order_avx,.-sha1_block_data_order_avx
diff --git a/linux-x86_64/crypto/sha/sha256-x86_64.S b/linux-x86_64/crypto/sha/sha256-x86_64.S
index 445b497..273b7a5 100644
--- a/linux-x86_64/crypto/sha/sha256-x86_64.S
+++ b/linux-x86_64/crypto/sha/sha256-x86_64.S
@@ -19,13 +19,13 @@
 	je	.Lavx_shortcut
 	testl	$512,%r10d
 	jnz	.Lssse3_shortcut
+	movq	%rsp,%rax
 	pushq	%rbx
 	pushq	%rbp
 	pushq	%r12
 	pushq	%r13
 	pushq	%r14
 	pushq	%r15
-	movq	%rsp,%r11
 	shlq	$4,%rdx
 	subq	$64+32,%rsp
 	leaq	(%rsi,%rdx,4),%rdx
@@ -33,7 +33,7 @@
 	movq	%rdi,64+0(%rsp)
 	movq	%rsi,64+8(%rsp)
 	movq	%rdx,64+16(%rsp)
-	movq	%r11,64+24(%rsp)
+	movq	%rax,64+24(%rsp)
 .Lprologue:
 
 	movl	0(%rdi),%eax
@@ -1698,13 +1698,13 @@
 	jb	.Lloop
 
 	movq	64+24(%rsp),%rsi
-	movq	(%rsi),%r15
-	movq	8(%rsi),%r14
-	movq	16(%rsi),%r13
-	movq	24(%rsi),%r12
-	movq	32(%rsi),%rbp
-	movq	40(%rsi),%rbx
-	leaq	48(%rsi),%rsp
+	movq	-48(%rsi),%r15
+	movq	-40(%rsi),%r14
+	movq	-32(%rsi),%r13
+	movq	-24(%rsi),%r12
+	movq	-16(%rsi),%rbp
+	movq	-8(%rsi),%rbx
+	leaq	(%rsi),%rsp
 .Lepilogue:
 	.byte	0xf3,0xc3
 .size	sha256_block_data_order,.-sha256_block_data_order
@@ -1755,13 +1755,13 @@
 .align	64
 sha256_block_data_order_ssse3:
 .Lssse3_shortcut:
+	movq	%rsp,%rax
 	pushq	%rbx
 	pushq	%rbp
 	pushq	%r12
 	pushq	%r13
 	pushq	%r14
 	pushq	%r15
-	movq	%rsp,%r11
 	shlq	$4,%rdx
 	subq	$96,%rsp
 	leaq	(%rsi,%rdx,4),%rdx
@@ -1769,7 +1769,7 @@
 	movq	%rdi,64+0(%rsp)
 	movq	%rsi,64+8(%rsp)
 	movq	%rdx,64+16(%rsp)
-	movq	%r11,64+24(%rsp)
+	movq	%rax,64+24(%rsp)
 .Lprologue_ssse3:
 
 	movl	0(%rdi),%eax
@@ -2836,13 +2836,13 @@
 	jb	.Lloop_ssse3
 
 	movq	64+24(%rsp),%rsi
-	movq	(%rsi),%r15
-	movq	8(%rsi),%r14
-	movq	16(%rsi),%r13
-	movq	24(%rsi),%r12
-	movq	32(%rsi),%rbp
-	movq	40(%rsi),%rbx
-	leaq	48(%rsi),%rsp
+	movq	-48(%rsi),%r15
+	movq	-40(%rsi),%r14
+	movq	-32(%rsi),%r13
+	movq	-24(%rsi),%r12
+	movq	-16(%rsi),%rbp
+	movq	-8(%rsi),%rbx
+	leaq	(%rsi),%rsp
 .Lepilogue_ssse3:
 	.byte	0xf3,0xc3
 .size	sha256_block_data_order_ssse3,.-sha256_block_data_order_ssse3
@@ -2850,13 +2850,13 @@
 .align	64
 sha256_block_data_order_avx:
 .Lavx_shortcut:
+	movq	%rsp,%rax
 	pushq	%rbx
 	pushq	%rbp
 	pushq	%r12
 	pushq	%r13
 	pushq	%r14
 	pushq	%r15
-	movq	%rsp,%r11
 	shlq	$4,%rdx
 	subq	$96,%rsp
 	leaq	(%rsi,%rdx,4),%rdx
@@ -2864,7 +2864,7 @@
 	movq	%rdi,64+0(%rsp)
 	movq	%rsi,64+8(%rsp)
 	movq	%rdx,64+16(%rsp)
-	movq	%r11,64+24(%rsp)
+	movq	%rax,64+24(%rsp)
 .Lprologue_avx:
 
 	vzeroupper
@@ -3893,13 +3893,13 @@
 
 	movq	64+24(%rsp),%rsi
 	vzeroupper
-	movq	(%rsi),%r15
-	movq	8(%rsi),%r14
-	movq	16(%rsi),%r13
-	movq	24(%rsi),%r12
-	movq	32(%rsi),%rbp
-	movq	40(%rsi),%rbx
-	leaq	48(%rsi),%rsp
+	movq	-48(%rsi),%r15
+	movq	-40(%rsi),%r14
+	movq	-32(%rsi),%r13
+	movq	-24(%rsi),%r12
+	movq	-16(%rsi),%rbp
+	movq	-8(%rsi),%rbx
+	leaq	(%rsi),%rsp
 .Lepilogue_avx:
 	.byte	0xf3,0xc3
 .size	sha256_block_data_order_avx,.-sha256_block_data_order_avx
diff --git a/linux-x86_64/crypto/sha/sha512-x86_64.S b/linux-x86_64/crypto/sha/sha512-x86_64.S
index d65743f..f272b64 100644
--- a/linux-x86_64/crypto/sha/sha512-x86_64.S
+++ b/linux-x86_64/crypto/sha/sha512-x86_64.S
@@ -19,13 +19,13 @@
 	orl	%r9d,%r10d
 	cmpl	$1342177792,%r10d
 	je	.Lavx_shortcut
+	movq	%rsp,%rax
 	pushq	%rbx
 	pushq	%rbp
 	pushq	%r12
 	pushq	%r13
 	pushq	%r14
 	pushq	%r15
-	movq	%rsp,%r11
 	shlq	$4,%rdx
 	subq	$128+32,%rsp
 	leaq	(%rsi,%rdx,8),%rdx
@@ -33,7 +33,7 @@
 	movq	%rdi,128+0(%rsp)
 	movq	%rsi,128+8(%rsp)
 	movq	%rdx,128+16(%rsp)
-	movq	%r11,128+24(%rsp)
+	movq	%rax,128+24(%rsp)
 .Lprologue:
 
 	movq	0(%rdi),%rax
@@ -1698,13 +1698,13 @@
 	jb	.Lloop
 
 	movq	128+24(%rsp),%rsi
-	movq	(%rsi),%r15
-	movq	8(%rsi),%r14
-	movq	16(%rsi),%r13
-	movq	24(%rsi),%r12
-	movq	32(%rsi),%rbp
-	movq	40(%rsi),%rbx
-	leaq	48(%rsi),%rsp
+	movq	-48(%rsi),%r15
+	movq	-40(%rsi),%r14
+	movq	-32(%rsi),%r13
+	movq	-24(%rsi),%r12
+	movq	-16(%rsi),%rbp
+	movq	-8(%rsi),%rbx
+	leaq	(%rsi),%rsp
 .Lepilogue:
 	.byte	0xf3,0xc3
 .size	sha512_block_data_order,.-sha512_block_data_order
@@ -1799,13 +1799,13 @@
 .align	64
 sha512_block_data_order_xop:
 .Lxop_shortcut:
+	movq	%rsp,%rax
 	pushq	%rbx
 	pushq	%rbp
 	pushq	%r12
 	pushq	%r13
 	pushq	%r14
 	pushq	%r15
-	movq	%rsp,%r11
 	shlq	$4,%rdx
 	subq	$160,%rsp
 	leaq	(%rsi,%rdx,8),%rdx
@@ -1813,7 +1813,7 @@
 	movq	%rdi,128+0(%rsp)
 	movq	%rsi,128+8(%rsp)
 	movq	%rdx,128+16(%rsp)
-	movq	%r11,128+24(%rsp)
+	movq	%rax,128+24(%rsp)
 .Lprologue_xop:
 
 	vzeroupper
@@ -2868,13 +2868,13 @@
 
 	movq	128+24(%rsp),%rsi
 	vzeroupper
-	movq	(%rsi),%r15
-	movq	8(%rsi),%r14
-	movq	16(%rsi),%r13
-	movq	24(%rsi),%r12
-	movq	32(%rsi),%rbp
-	movq	40(%rsi),%rbx
-	leaq	48(%rsi),%rsp
+	movq	-48(%rsi),%r15
+	movq	-40(%rsi),%r14
+	movq	-32(%rsi),%r13
+	movq	-24(%rsi),%r12
+	movq	-16(%rsi),%rbp
+	movq	-8(%rsi),%rbx
+	leaq	(%rsi),%rsp
 .Lepilogue_xop:
 	.byte	0xf3,0xc3
 .size	sha512_block_data_order_xop,.-sha512_block_data_order_xop
@@ -2882,13 +2882,13 @@
 .align	64
 sha512_block_data_order_avx:
 .Lavx_shortcut:
+	movq	%rsp,%rax
 	pushq	%rbx
 	pushq	%rbp
 	pushq	%r12
 	pushq	%r13
 	pushq	%r14
 	pushq	%r15
-	movq	%rsp,%r11
 	shlq	$4,%rdx
 	subq	$160,%rsp
 	leaq	(%rsi,%rdx,8),%rdx
@@ -2896,7 +2896,7 @@
 	movq	%rdi,128+0(%rsp)
 	movq	%rsi,128+8(%rsp)
 	movq	%rdx,128+16(%rsp)
-	movq	%r11,128+24(%rsp)
+	movq	%rax,128+24(%rsp)
 .Lprologue_avx:
 
 	vzeroupper
@@ -4015,13 +4015,13 @@
 
 	movq	128+24(%rsp),%rsi
 	vzeroupper
-	movq	(%rsi),%r15
-	movq	8(%rsi),%r14
-	movq	16(%rsi),%r13
-	movq	24(%rsi),%r12
-	movq	32(%rsi),%rbp
-	movq	40(%rsi),%rbx
-	leaq	48(%rsi),%rsp
+	movq	-48(%rsi),%r15
+	movq	-40(%rsi),%r14
+	movq	-32(%rsi),%r13
+	movq	-24(%rsi),%r12
+	movq	-16(%rsi),%rbp
+	movq	-8(%rsi),%rbx
+	leaq	(%rsi),%rsp
 .Lepilogue_avx:
 	.byte	0xf3,0xc3
 .size	sha512_block_data_order_avx,.-sha512_block_data_order_avx
diff --git a/mac-x86/crypto/bn/x86-mont.S b/mac-x86/crypto/bn/x86-mont.S
index 234034b..5c13ca4 100644
--- a/mac-x86/crypto/bn/x86-mont.S
+++ b/mac-x86/crypto/bn/x86-mont.S
@@ -16,39 +16,54 @@
 	jl	L000just_leave
 	leal	20(%esp),%esi
 	leal	24(%esp),%edx
-	movl	%esp,%ebp
 	addl	$2,%edi
 	negl	%edi
-	leal	-32(%esp,%edi,4),%esp
+	leal	-32(%esp,%edi,4),%ebp
 	negl	%edi
-	movl	%esp,%eax
+	movl	%ebp,%eax
 	subl	%edx,%eax
 	andl	$2047,%eax
-	subl	%eax,%esp
-	xorl	%esp,%edx
+	subl	%eax,%ebp
+	xorl	%ebp,%edx
 	andl	$2048,%edx
 	xorl	$2048,%edx
-	subl	%edx,%esp
-	andl	$-64,%esp
+	subl	%edx,%ebp
+	andl	$-64,%ebp
+	movl	%esp,%eax
+	subl	%ebp,%eax
+	andl	$-4096,%eax
+	movl	%esp,%edx
+	leal	(%ebp,%eax,1),%esp
+	movl	(%esp),%eax
+	cmpl	%ebp,%esp
+	ja	L001page_walk
+	jmp	L002page_walk_done
+.align	4,0x90
+L001page_walk:
+	leal	-4096(%esp),%esp
+	movl	(%esp),%eax
+	cmpl	%ebp,%esp
+	ja	L001page_walk
+L002page_walk_done:
 	movl	(%esi),%eax
 	movl	4(%esi),%ebx
 	movl	8(%esi),%ecx
-	movl	12(%esi),%edx
+	movl	12(%esi),%ebp
 	movl	16(%esi),%esi
 	movl	(%esi),%esi
 	movl	%eax,4(%esp)
 	movl	%ebx,8(%esp)
 	movl	%ecx,12(%esp)
-	movl	%edx,16(%esp)
+	movl	%ebp,16(%esp)
 	movl	%esi,20(%esp)
 	leal	-3(%edi),%ebx
-	movl	%ebp,24(%esp)
-	call	L001PIC_me_up
-L001PIC_me_up:
+	movl	%edx,24(%esp)
+	call	L003PIC_me_up
+L003PIC_me_up:
 	popl	%eax
-	movl	L_OPENSSL_ia32cap_P$non_lazy_ptr-L001PIC_me_up(%eax),%eax
+	movl	L_OPENSSL_ia32cap_P$non_lazy_ptr-L003PIC_me_up(%eax),%eax
 	btl	$26,(%eax)
-	jnc	L002non_sse2
+	jnc	L004non_sse2
 	movl	$-1,%eax
 	movd	%eax,%mm7
 	movl	8(%esp),%esi
@@ -72,7 +87,7 @@
 	psrlq	$32,%mm3
 	incl	%ecx
 .align	4,0x90
-L0031st:
+L0051st:
 	pmuludq	%mm4,%mm0
 	pmuludq	%mm5,%mm1
 	paddq	%mm0,%mm2
@@ -87,7 +102,7 @@
 	psrlq	$32,%mm3
 	leal	1(%ecx),%ecx
 	cmpl	%ebx,%ecx
-	jl	L0031st
+	jl	L0051st
 	pmuludq	%mm4,%mm0
 	pmuludq	%mm5,%mm1
 	paddq	%mm0,%mm2
@@ -101,7 +116,7 @@
 	paddq	%mm2,%mm3
 	movq	%mm3,32(%esp,%ebx,4)
 	incl	%edx
-L004outer:
+L006outer:
 	xorl	%ecx,%ecx
 	movd	(%edi,%edx,4),%mm4
 	movd	(%esi),%mm5
@@ -123,7 +138,7 @@
 	paddq	%mm6,%mm2
 	incl	%ecx
 	decl	%ebx
-L005inner:
+L007inner:
 	pmuludq	%mm4,%mm0
 	pmuludq	%mm5,%mm1
 	paddq	%mm0,%mm2
@@ -140,7 +155,7 @@
 	paddq	%mm6,%mm2
 	decl	%ebx
 	leal	1(%ecx),%ecx
-	jnz	L005inner
+	jnz	L007inner
 	movl	%ecx,%ebx
 	pmuludq	%mm4,%mm0
 	pmuludq	%mm5,%mm1
@@ -158,11 +173,11 @@
 	movq	%mm3,32(%esp,%ebx,4)
 	leal	1(%edx),%edx
 	cmpl	%ebx,%edx
-	jle	L004outer
+	jle	L006outer
 	emms
-	jmp	L006common_tail
+	jmp	L008common_tail
 .align	4,0x90
-L002non_sse2:
+L004non_sse2:
 	movl	8(%esp),%esi
 	leal	1(%ebx),%ebp
 	movl	12(%esp),%edi
@@ -173,12 +188,12 @@
 	leal	4(%edi,%ebx,4),%eax
 	orl	%edx,%ebp
 	movl	(%edi),%edi
-	jz	L007bn_sqr_mont
+	jz	L009bn_sqr_mont
 	movl	%eax,28(%esp)
 	movl	(%esi),%eax
 	xorl	%edx,%edx
 .align	4,0x90
-L008mull:
+L010mull:
 	movl	%edx,%ebp
 	mull	%edi
 	addl	%eax,%ebp
@@ -187,7 +202,7 @@
 	movl	(%esi,%ecx,4),%eax
 	cmpl	%ebx,%ecx
 	movl	%ebp,28(%esp,%ecx,4)
-	jl	L008mull
+	jl	L010mull
 	movl	%edx,%ebp
 	mull	%edi
 	movl	20(%esp),%edi
@@ -205,9 +220,9 @@
 	movl	4(%esi),%eax
 	adcl	$0,%edx
 	incl	%ecx
-	jmp	L0092ndmadd
+	jmp	L0112ndmadd
 .align	4,0x90
-L0101stmadd:
+L0121stmadd:
 	movl	%edx,%ebp
 	mull	%edi
 	addl	32(%esp,%ecx,4),%ebp
@@ -218,7 +233,7 @@
 	adcl	$0,%edx
 	cmpl	%ebx,%ecx
 	movl	%ebp,28(%esp,%ecx,4)
-	jl	L0101stmadd
+	jl	L0121stmadd
 	movl	%edx,%ebp
 	mull	%edi
 	addl	32(%esp,%ebx,4),%eax
@@ -241,7 +256,7 @@
 	adcl	$0,%edx
 	movl	$1,%ecx
 .align	4,0x90
-L0092ndmadd:
+L0112ndmadd:
 	movl	%edx,%ebp
 	mull	%edi
 	addl	32(%esp,%ecx,4),%ebp
@@ -252,7 +267,7 @@
 	adcl	$0,%edx
 	cmpl	%ebx,%ecx
 	movl	%ebp,24(%esp,%ecx,4)
-	jl	L0092ndmadd
+	jl	L0112ndmadd
 	movl	%edx,%ebp
 	mull	%edi
 	addl	32(%esp,%ebx,4),%ebp
@@ -268,16 +283,16 @@
 	movl	%edx,32(%esp,%ebx,4)
 	cmpl	28(%esp),%ecx
 	movl	%eax,36(%esp,%ebx,4)
-	je	L006common_tail
+	je	L008common_tail
 	movl	(%ecx),%edi
 	movl	8(%esp),%esi
 	movl	%ecx,12(%esp)
 	xorl	%ecx,%ecx
 	xorl	%edx,%edx
 	movl	(%esi),%eax
-	jmp	L0101stmadd
+	jmp	L0121stmadd
 .align	4,0x90
-L007bn_sqr_mont:
+L009bn_sqr_mont:
 	movl	%ebx,(%esp)
 	movl	%ecx,12(%esp)
 	movl	%edi,%eax
@@ -288,7 +303,7 @@
 	andl	$1,%ebx
 	incl	%ecx
 .align	4,0x90
-L011sqr:
+L013sqr:
 	movl	(%esi,%ecx,4),%eax
 	movl	%edx,%ebp
 	mull	%edi
@@ -300,7 +315,7 @@
 	cmpl	(%esp),%ecx
 	movl	%eax,%ebx
 	movl	%ebp,28(%esp,%ecx,4)
-	jl	L011sqr
+	jl	L013sqr
 	movl	(%esi,%ecx,4),%eax
 	movl	%edx,%ebp
 	mull	%edi
@@ -324,7 +339,7 @@
 	movl	4(%esi),%eax
 	movl	$1,%ecx
 .align	4,0x90
-L0123rdmadd:
+L0143rdmadd:
 	movl	%edx,%ebp
 	mull	%edi
 	addl	32(%esp,%ecx,4),%ebp
@@ -343,7 +358,7 @@
 	adcl	$0,%edx
 	cmpl	%ebx,%ecx
 	movl	%ebp,24(%esp,%ecx,4)
-	jl	L0123rdmadd
+	jl	L0143rdmadd
 	movl	%edx,%ebp
 	mull	%edi
 	addl	32(%esp,%ebx,4),%ebp
@@ -359,7 +374,7 @@
 	movl	%edx,32(%esp,%ebx,4)
 	cmpl	%ebx,%ecx
 	movl	%eax,36(%esp,%ebx,4)
-	je	L006common_tail
+	je	L008common_tail
 	movl	4(%esi,%ecx,4),%edi
 	leal	1(%ecx),%ecx
 	movl	%edi,%eax
@@ -371,12 +386,12 @@
 	xorl	%ebp,%ebp
 	cmpl	%ebx,%ecx
 	leal	1(%ecx),%ecx
-	je	L013sqrlast
+	je	L015sqrlast
 	movl	%edx,%ebx
 	shrl	$1,%edx
 	andl	$1,%ebx
 .align	4,0x90
-L014sqradd:
+L016sqradd:
 	movl	(%esi,%ecx,4),%eax
 	movl	%edx,%ebp
 	mull	%edi
@@ -392,13 +407,13 @@
 	cmpl	(%esp),%ecx
 	movl	%ebp,28(%esp,%ecx,4)
 	movl	%eax,%ebx
-	jle	L014sqradd
+	jle	L016sqradd
 	movl	%edx,%ebp
 	addl	%edx,%edx
 	shrl	$31,%ebp
 	addl	%ebx,%edx
 	adcl	$0,%ebp
-L013sqrlast:
+L015sqrlast:
 	movl	20(%esp),%edi
 	movl	16(%esp),%esi
 	imull	32(%esp),%edi
@@ -413,9 +428,9 @@
 	adcl	$0,%edx
 	movl	$1,%ecx
 	movl	4(%esi),%eax
-	jmp	L0123rdmadd
+	jmp	L0143rdmadd
 .align	4,0x90
-L006common_tail:
+L008common_tail:
 	movl	16(%esp),%ebp
 	movl	4(%esp),%edi
 	leal	32(%esp),%esi
@@ -423,25 +438,26 @@
 	movl	%ebx,%ecx
 	xorl	%edx,%edx
 .align	4,0x90
-L015sub:
+L017sub:
 	sbbl	(%ebp,%edx,4),%eax
 	movl	%eax,(%edi,%edx,4)
 	decl	%ecx
 	movl	4(%esi,%edx,4),%eax
 	leal	1(%edx),%edx
-	jge	L015sub
+	jge	L017sub
 	sbbl	$0,%eax
+	andl	%eax,%esi
+	notl	%eax
+	movl	%edi,%ebp
+	andl	%eax,%ebp
+	orl	%ebp,%esi
 .align	4,0x90
-L016copy:
-	movl	(%esi,%ebx,4),%edx
-	movl	(%edi,%ebx,4),%ebp
-	xorl	%ebp,%edx
-	andl	%eax,%edx
-	xorl	%ebp,%edx
-	movl	%ecx,(%esi,%ebx,4)
-	movl	%edx,(%edi,%ebx,4)
+L018copy:
+	movl	(%esi,%ebx,4),%eax
+	movl	%eax,(%edi,%ebx,4)
+	movl	%ecx,32(%esp,%ebx,4)
 	decl	%ebx
-	jge	L016copy
+	jge	L018copy
 	movl	24(%esp),%esp
 	movl	$1,%eax
 L000just_leave:
diff --git a/mac-x86/crypto/chacha/chacha-x86.S b/mac-x86/crypto/chacha/chacha-x86.S
new file mode 100644
index 0000000..5de98a3
--- /dev/null
+++ b/mac-x86/crypto/chacha/chacha-x86.S
@@ -0,0 +1,969 @@
+#if defined(__i386__)
+.file	"chacha-x86.S"
+.text
+.globl	_ChaCha20_ctr32
+.private_extern	_ChaCha20_ctr32
+.align	4
+_ChaCha20_ctr32:
+L_ChaCha20_ctr32_begin:
+	pushl	%ebp
+	pushl	%ebx
+	pushl	%esi
+	pushl	%edi
+	xorl	%eax,%eax
+	cmpl	28(%esp),%eax
+	je	L000no_data
+	call	Lpic_point
+Lpic_point:
+	popl	%eax
+	movl	L_OPENSSL_ia32cap_P$non_lazy_ptr-Lpic_point(%eax),%ebp
+	testl	$16777216,(%ebp)
+	jz	L001x86
+	testl	$512,4(%ebp)
+	jz	L001x86
+	jmp	Lssse3_shortcut
+L001x86:
+	movl	32(%esp),%esi
+	movl	36(%esp),%edi
+	subl	$132,%esp
+	movl	(%esi),%eax
+	movl	4(%esi),%ebx
+	movl	8(%esi),%ecx
+	movl	12(%esi),%edx
+	movl	%eax,80(%esp)
+	movl	%ebx,84(%esp)
+	movl	%ecx,88(%esp)
+	movl	%edx,92(%esp)
+	movl	16(%esi),%eax
+	movl	20(%esi),%ebx
+	movl	24(%esi),%ecx
+	movl	28(%esi),%edx
+	movl	%eax,96(%esp)
+	movl	%ebx,100(%esp)
+	movl	%ecx,104(%esp)
+	movl	%edx,108(%esp)
+	movl	(%edi),%eax
+	movl	4(%edi),%ebx
+	movl	8(%edi),%ecx
+	movl	12(%edi),%edx
+	subl	$1,%eax
+	movl	%eax,112(%esp)
+	movl	%ebx,116(%esp)
+	movl	%ecx,120(%esp)
+	movl	%edx,124(%esp)
+	jmp	L002entry
+.align	4,0x90
+L003outer_loop:
+	movl	%ebx,156(%esp)
+	movl	%eax,152(%esp)
+	movl	%ecx,160(%esp)
+L002entry:
+	movl	$1634760805,%eax
+	movl	$857760878,4(%esp)
+	movl	$2036477234,8(%esp)
+	movl	$1797285236,12(%esp)
+	movl	84(%esp),%ebx
+	movl	88(%esp),%ebp
+	movl	104(%esp),%ecx
+	movl	108(%esp),%esi
+	movl	116(%esp),%edx
+	movl	120(%esp),%edi
+	movl	%ebx,20(%esp)
+	movl	%ebp,24(%esp)
+	movl	%ecx,40(%esp)
+	movl	%esi,44(%esp)
+	movl	%edx,52(%esp)
+	movl	%edi,56(%esp)
+	movl	92(%esp),%ebx
+	movl	124(%esp),%edi
+	movl	112(%esp),%edx
+	movl	80(%esp),%ebp
+	movl	96(%esp),%ecx
+	movl	100(%esp),%esi
+	addl	$1,%edx
+	movl	%ebx,28(%esp)
+	movl	%edi,60(%esp)
+	movl	%edx,112(%esp)
+	movl	$10,%ebx
+	jmp	L004loop
+.align	4,0x90
+L004loop:
+	addl	%ebp,%eax
+	movl	%ebx,128(%esp)
+	movl	%ebp,%ebx
+	xorl	%eax,%edx
+	roll	$16,%edx
+	addl	%edx,%ecx
+	xorl	%ecx,%ebx
+	movl	52(%esp),%edi
+	roll	$12,%ebx
+	movl	20(%esp),%ebp
+	addl	%ebx,%eax
+	xorl	%eax,%edx
+	movl	%eax,(%esp)
+	roll	$8,%edx
+	movl	4(%esp),%eax
+	addl	%edx,%ecx
+	movl	%edx,48(%esp)
+	xorl	%ecx,%ebx
+	addl	%ebp,%eax
+	roll	$7,%ebx
+	xorl	%eax,%edi
+	movl	%ecx,32(%esp)
+	roll	$16,%edi
+	movl	%ebx,16(%esp)
+	addl	%edi,%esi
+	movl	40(%esp),%ecx
+	xorl	%esi,%ebp
+	movl	56(%esp),%edx
+	roll	$12,%ebp
+	movl	24(%esp),%ebx
+	addl	%ebp,%eax
+	xorl	%eax,%edi
+	movl	%eax,4(%esp)
+	roll	$8,%edi
+	movl	8(%esp),%eax
+	addl	%edi,%esi
+	movl	%edi,52(%esp)
+	xorl	%esi,%ebp
+	addl	%ebx,%eax
+	roll	$7,%ebp
+	xorl	%eax,%edx
+	movl	%esi,36(%esp)
+	roll	$16,%edx
+	movl	%ebp,20(%esp)
+	addl	%edx,%ecx
+	movl	44(%esp),%esi
+	xorl	%ecx,%ebx
+	movl	60(%esp),%edi
+	roll	$12,%ebx
+	movl	28(%esp),%ebp
+	addl	%ebx,%eax
+	xorl	%eax,%edx
+	movl	%eax,8(%esp)
+	roll	$8,%edx
+	movl	12(%esp),%eax
+	addl	%edx,%ecx
+	movl	%edx,56(%esp)
+	xorl	%ecx,%ebx
+	addl	%ebp,%eax
+	roll	$7,%ebx
+	xorl	%eax,%edi
+	roll	$16,%edi
+	movl	%ebx,24(%esp)
+	addl	%edi,%esi
+	xorl	%esi,%ebp
+	roll	$12,%ebp
+	movl	20(%esp),%ebx
+	addl	%ebp,%eax
+	xorl	%eax,%edi
+	movl	%eax,12(%esp)
+	roll	$8,%edi
+	movl	(%esp),%eax
+	addl	%edi,%esi
+	movl	%edi,%edx
+	xorl	%esi,%ebp
+	addl	%ebx,%eax
+	roll	$7,%ebp
+	xorl	%eax,%edx
+	roll	$16,%edx
+	movl	%ebp,28(%esp)
+	addl	%edx,%ecx
+	xorl	%ecx,%ebx
+	movl	48(%esp),%edi
+	roll	$12,%ebx
+	movl	24(%esp),%ebp
+	addl	%ebx,%eax
+	xorl	%eax,%edx
+	movl	%eax,(%esp)
+	roll	$8,%edx
+	movl	4(%esp),%eax
+	addl	%edx,%ecx
+	movl	%edx,60(%esp)
+	xorl	%ecx,%ebx
+	addl	%ebp,%eax
+	roll	$7,%ebx
+	xorl	%eax,%edi
+	movl	%ecx,40(%esp)
+	roll	$16,%edi
+	movl	%ebx,20(%esp)
+	addl	%edi,%esi
+	movl	32(%esp),%ecx
+	xorl	%esi,%ebp
+	movl	52(%esp),%edx
+	roll	$12,%ebp
+	movl	28(%esp),%ebx
+	addl	%ebp,%eax
+	xorl	%eax,%edi
+	movl	%eax,4(%esp)
+	roll	$8,%edi
+	movl	8(%esp),%eax
+	addl	%edi,%esi
+	movl	%edi,48(%esp)
+	xorl	%esi,%ebp
+	addl	%ebx,%eax
+	roll	$7,%ebp
+	xorl	%eax,%edx
+	movl	%esi,44(%esp)
+	roll	$16,%edx
+	movl	%ebp,24(%esp)
+	addl	%edx,%ecx
+	movl	36(%esp),%esi
+	xorl	%ecx,%ebx
+	movl	56(%esp),%edi
+	roll	$12,%ebx
+	movl	16(%esp),%ebp
+	addl	%ebx,%eax
+	xorl	%eax,%edx
+	movl	%eax,8(%esp)
+	roll	$8,%edx
+	movl	12(%esp),%eax
+	addl	%edx,%ecx
+	movl	%edx,52(%esp)
+	xorl	%ecx,%ebx
+	addl	%ebp,%eax
+	roll	$7,%ebx
+	xorl	%eax,%edi
+	roll	$16,%edi
+	movl	%ebx,28(%esp)
+	addl	%edi,%esi
+	xorl	%esi,%ebp
+	movl	48(%esp),%edx
+	roll	$12,%ebp
+	movl	128(%esp),%ebx
+	addl	%ebp,%eax
+	xorl	%eax,%edi
+	movl	%eax,12(%esp)
+	roll	$8,%edi
+	movl	(%esp),%eax
+	addl	%edi,%esi
+	movl	%edi,56(%esp)
+	xorl	%esi,%ebp
+	roll	$7,%ebp
+	decl	%ebx
+	jnz	L004loop
+	movl	160(%esp),%ebx
+	addl	$1634760805,%eax
+	addl	80(%esp),%ebp
+	addl	96(%esp),%ecx
+	addl	100(%esp),%esi
+	cmpl	$64,%ebx
+	jb	L005tail
+	movl	156(%esp),%ebx
+	addl	112(%esp),%edx
+	addl	120(%esp),%edi
+	xorl	(%ebx),%eax
+	xorl	16(%ebx),%ebp
+	movl	%eax,(%esp)
+	movl	152(%esp),%eax
+	xorl	32(%ebx),%ecx
+	xorl	36(%ebx),%esi
+	xorl	48(%ebx),%edx
+	xorl	56(%ebx),%edi
+	movl	%ebp,16(%eax)
+	movl	%ecx,32(%eax)
+	movl	%esi,36(%eax)
+	movl	%edx,48(%eax)
+	movl	%edi,56(%eax)
+	movl	4(%esp),%ebp
+	movl	8(%esp),%ecx
+	movl	12(%esp),%esi
+	movl	20(%esp),%edx
+	movl	24(%esp),%edi
+	addl	$857760878,%ebp
+	addl	$2036477234,%ecx
+	addl	$1797285236,%esi
+	addl	84(%esp),%edx
+	addl	88(%esp),%edi
+	xorl	4(%ebx),%ebp
+	xorl	8(%ebx),%ecx
+	xorl	12(%ebx),%esi
+	xorl	20(%ebx),%edx
+	xorl	24(%ebx),%edi
+	movl	%ebp,4(%eax)
+	movl	%ecx,8(%eax)
+	movl	%esi,12(%eax)
+	movl	%edx,20(%eax)
+	movl	%edi,24(%eax)
+	movl	28(%esp),%ebp
+	movl	40(%esp),%ecx
+	movl	44(%esp),%esi
+	movl	52(%esp),%edx
+	movl	60(%esp),%edi
+	addl	92(%esp),%ebp
+	addl	104(%esp),%ecx
+	addl	108(%esp),%esi
+	addl	116(%esp),%edx
+	addl	124(%esp),%edi
+	xorl	28(%ebx),%ebp
+	xorl	40(%ebx),%ecx
+	xorl	44(%ebx),%esi
+	xorl	52(%ebx),%edx
+	xorl	60(%ebx),%edi
+	leal	64(%ebx),%ebx
+	movl	%ebp,28(%eax)
+	movl	(%esp),%ebp
+	movl	%ecx,40(%eax)
+	movl	160(%esp),%ecx
+	movl	%esi,44(%eax)
+	movl	%edx,52(%eax)
+	movl	%edi,60(%eax)
+	movl	%ebp,(%eax)
+	leal	64(%eax),%eax
+	subl	$64,%ecx
+	jnz	L003outer_loop
+	jmp	L006done
+L005tail:
+	addl	112(%esp),%edx
+	addl	120(%esp),%edi
+	movl	%eax,(%esp)
+	movl	%ebp,16(%esp)
+	movl	%ecx,32(%esp)
+	movl	%esi,36(%esp)
+	movl	%edx,48(%esp)
+	movl	%edi,56(%esp)
+	movl	4(%esp),%ebp
+	movl	8(%esp),%ecx
+	movl	12(%esp),%esi
+	movl	20(%esp),%edx
+	movl	24(%esp),%edi
+	addl	$857760878,%ebp
+	addl	$2036477234,%ecx
+	addl	$1797285236,%esi
+	addl	84(%esp),%edx
+	addl	88(%esp),%edi
+	movl	%ebp,4(%esp)
+	movl	%ecx,8(%esp)
+	movl	%esi,12(%esp)
+	movl	%edx,20(%esp)
+	movl	%edi,24(%esp)
+	movl	28(%esp),%ebp
+	movl	40(%esp),%ecx
+	movl	44(%esp),%esi
+	movl	52(%esp),%edx
+	movl	60(%esp),%edi
+	addl	92(%esp),%ebp
+	addl	104(%esp),%ecx
+	addl	108(%esp),%esi
+	addl	116(%esp),%edx
+	addl	124(%esp),%edi
+	movl	%ebp,28(%esp)
+	movl	156(%esp),%ebp
+	movl	%ecx,40(%esp)
+	movl	152(%esp),%ecx
+	movl	%esi,44(%esp)
+	xorl	%esi,%esi
+	movl	%edx,52(%esp)
+	movl	%edi,60(%esp)
+	xorl	%eax,%eax
+	xorl	%edx,%edx
+L007tail_loop:
+	movb	(%esi,%ebp,1),%al
+	movb	(%esp,%esi,1),%dl
+	leal	1(%esi),%esi
+	xorb	%dl,%al
+	movb	%al,-1(%ecx,%esi,1)
+	decl	%ebx
+	jnz	L007tail_loop
+L006done:
+	addl	$132,%esp
+L000no_data:
+	popl	%edi
+	popl	%esi
+	popl	%ebx
+	popl	%ebp
+	ret
+.globl	_ChaCha20_ssse3
+.private_extern	_ChaCha20_ssse3
+.align	4
+_ChaCha20_ssse3:
+L_ChaCha20_ssse3_begin:
+	pushl	%ebp
+	pushl	%ebx
+	pushl	%esi
+	pushl	%edi
+Lssse3_shortcut:
+	movl	20(%esp),%edi
+	movl	24(%esp),%esi
+	movl	28(%esp),%ecx
+	movl	32(%esp),%edx
+	movl	36(%esp),%ebx
+	movl	%esp,%ebp
+	subl	$524,%esp
+	andl	$-64,%esp
+	movl	%ebp,512(%esp)
+	leal	Lssse3_data-Lpic_point(%eax),%eax
+	movdqu	(%ebx),%xmm3
+	cmpl	$256,%ecx
+	jb	L0081x
+	movl	%edx,516(%esp)
+	movl	%ebx,520(%esp)
+	subl	$256,%ecx
+	leal	384(%esp),%ebp
+	movdqu	(%edx),%xmm7
+	pshufd	$0,%xmm3,%xmm0
+	pshufd	$85,%xmm3,%xmm1
+	pshufd	$170,%xmm3,%xmm2
+	pshufd	$255,%xmm3,%xmm3
+	paddd	48(%eax),%xmm0
+	pshufd	$0,%xmm7,%xmm4
+	pshufd	$85,%xmm7,%xmm5
+	psubd	64(%eax),%xmm0
+	pshufd	$170,%xmm7,%xmm6
+	pshufd	$255,%xmm7,%xmm7
+	movdqa	%xmm0,64(%ebp)
+	movdqa	%xmm1,80(%ebp)
+	movdqa	%xmm2,96(%ebp)
+	movdqa	%xmm3,112(%ebp)
+	movdqu	16(%edx),%xmm3
+	movdqa	%xmm4,-64(%ebp)
+	movdqa	%xmm5,-48(%ebp)
+	movdqa	%xmm6,-32(%ebp)
+	movdqa	%xmm7,-16(%ebp)
+	movdqa	32(%eax),%xmm7
+	leal	128(%esp),%ebx
+	pshufd	$0,%xmm3,%xmm0
+	pshufd	$85,%xmm3,%xmm1
+	pshufd	$170,%xmm3,%xmm2
+	pshufd	$255,%xmm3,%xmm3
+	pshufd	$0,%xmm7,%xmm4
+	pshufd	$85,%xmm7,%xmm5
+	pshufd	$170,%xmm7,%xmm6
+	pshufd	$255,%xmm7,%xmm7
+	movdqa	%xmm0,(%ebp)
+	movdqa	%xmm1,16(%ebp)
+	movdqa	%xmm2,32(%ebp)
+	movdqa	%xmm3,48(%ebp)
+	movdqa	%xmm4,-128(%ebp)
+	movdqa	%xmm5,-112(%ebp)
+	movdqa	%xmm6,-96(%ebp)
+	movdqa	%xmm7,-80(%ebp)
+	leal	128(%esi),%esi
+	leal	128(%edi),%edi
+	jmp	L009outer_loop
+.align	4,0x90
+L009outer_loop:
+	movdqa	-112(%ebp),%xmm1
+	movdqa	-96(%ebp),%xmm2
+	movdqa	-80(%ebp),%xmm3
+	movdqa	-48(%ebp),%xmm5
+	movdqa	-32(%ebp),%xmm6
+	movdqa	-16(%ebp),%xmm7
+	movdqa	%xmm1,-112(%ebx)
+	movdqa	%xmm2,-96(%ebx)
+	movdqa	%xmm3,-80(%ebx)
+	movdqa	%xmm5,-48(%ebx)
+	movdqa	%xmm6,-32(%ebx)
+	movdqa	%xmm7,-16(%ebx)
+	movdqa	32(%ebp),%xmm2
+	movdqa	48(%ebp),%xmm3
+	movdqa	64(%ebp),%xmm4
+	movdqa	80(%ebp),%xmm5
+	movdqa	96(%ebp),%xmm6
+	movdqa	112(%ebp),%xmm7
+	paddd	64(%eax),%xmm4
+	movdqa	%xmm2,32(%ebx)
+	movdqa	%xmm3,48(%ebx)
+	movdqa	%xmm4,64(%ebx)
+	movdqa	%xmm5,80(%ebx)
+	movdqa	%xmm6,96(%ebx)
+	movdqa	%xmm7,112(%ebx)
+	movdqa	%xmm4,64(%ebp)
+	movdqa	-128(%ebp),%xmm0
+	movdqa	%xmm4,%xmm6
+	movdqa	-64(%ebp),%xmm3
+	movdqa	(%ebp),%xmm4
+	movdqa	16(%ebp),%xmm5
+	movl	$10,%edx
+	nop
+.align	4,0x90
+L010loop:
+	paddd	%xmm3,%xmm0
+	movdqa	%xmm3,%xmm2
+	pxor	%xmm0,%xmm6
+	pshufb	(%eax),%xmm6
+	paddd	%xmm6,%xmm4
+	pxor	%xmm4,%xmm2
+	movdqa	-48(%ebx),%xmm3
+	movdqa	%xmm2,%xmm1
+	pslld	$12,%xmm2
+	psrld	$20,%xmm1
+	por	%xmm1,%xmm2
+	movdqa	-112(%ebx),%xmm1
+	paddd	%xmm2,%xmm0
+	movdqa	80(%ebx),%xmm7
+	pxor	%xmm0,%xmm6
+	movdqa	%xmm0,-128(%ebx)
+	pshufb	16(%eax),%xmm6
+	paddd	%xmm6,%xmm4
+	movdqa	%xmm6,64(%ebx)
+	pxor	%xmm4,%xmm2
+	paddd	%xmm3,%xmm1
+	movdqa	%xmm2,%xmm0
+	pslld	$7,%xmm2
+	psrld	$25,%xmm0
+	pxor	%xmm1,%xmm7
+	por	%xmm0,%xmm2
+	movdqa	%xmm4,(%ebx)
+	pshufb	(%eax),%xmm7
+	movdqa	%xmm2,-64(%ebx)
+	paddd	%xmm7,%xmm5
+	movdqa	32(%ebx),%xmm4
+	pxor	%xmm5,%xmm3
+	movdqa	-32(%ebx),%xmm2
+	movdqa	%xmm3,%xmm0
+	pslld	$12,%xmm3
+	psrld	$20,%xmm0
+	por	%xmm0,%xmm3
+	movdqa	-96(%ebx),%xmm0
+	paddd	%xmm3,%xmm1
+	movdqa	96(%ebx),%xmm6
+	pxor	%xmm1,%xmm7
+	movdqa	%xmm1,-112(%ebx)
+	pshufb	16(%eax),%xmm7
+	paddd	%xmm7,%xmm5
+	movdqa	%xmm7,80(%ebx)
+	pxor	%xmm5,%xmm3
+	paddd	%xmm2,%xmm0
+	movdqa	%xmm3,%xmm1
+	pslld	$7,%xmm3
+	psrld	$25,%xmm1
+	pxor	%xmm0,%xmm6
+	por	%xmm1,%xmm3
+	movdqa	%xmm5,16(%ebx)
+	pshufb	(%eax),%xmm6
+	movdqa	%xmm3,-48(%ebx)
+	paddd	%xmm6,%xmm4
+	movdqa	48(%ebx),%xmm5
+	pxor	%xmm4,%xmm2
+	movdqa	-16(%ebx),%xmm3
+	movdqa	%xmm2,%xmm1
+	pslld	$12,%xmm2
+	psrld	$20,%xmm1
+	por	%xmm1,%xmm2
+	movdqa	-80(%ebx),%xmm1
+	paddd	%xmm2,%xmm0
+	movdqa	112(%ebx),%xmm7
+	pxor	%xmm0,%xmm6
+	movdqa	%xmm0,-96(%ebx)
+	pshufb	16(%eax),%xmm6
+	paddd	%xmm6,%xmm4
+	movdqa	%xmm6,96(%ebx)
+	pxor	%xmm4,%xmm2
+	paddd	%xmm3,%xmm1
+	movdqa	%xmm2,%xmm0
+	pslld	$7,%xmm2
+	psrld	$25,%xmm0
+	pxor	%xmm1,%xmm7
+	por	%xmm0,%xmm2
+	pshufb	(%eax),%xmm7
+	movdqa	%xmm2,-32(%ebx)
+	paddd	%xmm7,%xmm5
+	pxor	%xmm5,%xmm3
+	movdqa	-48(%ebx),%xmm2
+	movdqa	%xmm3,%xmm0
+	pslld	$12,%xmm3
+	psrld	$20,%xmm0
+	por	%xmm0,%xmm3
+	movdqa	-128(%ebx),%xmm0
+	paddd	%xmm3,%xmm1
+	pxor	%xmm1,%xmm7
+	movdqa	%xmm1,-80(%ebx)
+	pshufb	16(%eax),%xmm7
+	paddd	%xmm7,%xmm5
+	movdqa	%xmm7,%xmm6
+	pxor	%xmm5,%xmm3
+	paddd	%xmm2,%xmm0
+	movdqa	%xmm3,%xmm1
+	pslld	$7,%xmm3
+	psrld	$25,%xmm1
+	pxor	%xmm0,%xmm6
+	por	%xmm1,%xmm3
+	pshufb	(%eax),%xmm6
+	movdqa	%xmm3,-16(%ebx)
+	paddd	%xmm6,%xmm4
+	pxor	%xmm4,%xmm2
+	movdqa	-32(%ebx),%xmm3
+	movdqa	%xmm2,%xmm1
+	pslld	$12,%xmm2
+	psrld	$20,%xmm1
+	por	%xmm1,%xmm2
+	movdqa	-112(%ebx),%xmm1
+	paddd	%xmm2,%xmm0
+	movdqa	64(%ebx),%xmm7
+	pxor	%xmm0,%xmm6
+	movdqa	%xmm0,-128(%ebx)
+	pshufb	16(%eax),%xmm6
+	paddd	%xmm6,%xmm4
+	movdqa	%xmm6,112(%ebx)
+	pxor	%xmm4,%xmm2
+	paddd	%xmm3,%xmm1
+	movdqa	%xmm2,%xmm0
+	pslld	$7,%xmm2
+	psrld	$25,%xmm0
+	pxor	%xmm1,%xmm7
+	por	%xmm0,%xmm2
+	movdqa	%xmm4,32(%ebx)
+	pshufb	(%eax),%xmm7
+	movdqa	%xmm2,-48(%ebx)
+	paddd	%xmm7,%xmm5
+	movdqa	(%ebx),%xmm4
+	pxor	%xmm5,%xmm3
+	movdqa	-16(%ebx),%xmm2
+	movdqa	%xmm3,%xmm0
+	pslld	$12,%xmm3
+	psrld	$20,%xmm0
+	por	%xmm0,%xmm3
+	movdqa	-96(%ebx),%xmm0
+	paddd	%xmm3,%xmm1
+	movdqa	80(%ebx),%xmm6
+	pxor	%xmm1,%xmm7
+	movdqa	%xmm1,-112(%ebx)
+	pshufb	16(%eax),%xmm7
+	paddd	%xmm7,%xmm5
+	movdqa	%xmm7,64(%ebx)
+	pxor	%xmm5,%xmm3
+	paddd	%xmm2,%xmm0
+	movdqa	%xmm3,%xmm1
+	pslld	$7,%xmm3
+	psrld	$25,%xmm1
+	pxor	%xmm0,%xmm6
+	por	%xmm1,%xmm3
+	movdqa	%xmm5,48(%ebx)
+	pshufb	(%eax),%xmm6
+	movdqa	%xmm3,-32(%ebx)
+	paddd	%xmm6,%xmm4
+	movdqa	16(%ebx),%xmm5
+	pxor	%xmm4,%xmm2
+	movdqa	-64(%ebx),%xmm3
+	movdqa	%xmm2,%xmm1
+	pslld	$12,%xmm2
+	psrld	$20,%xmm1
+	por	%xmm1,%xmm2
+	movdqa	-80(%ebx),%xmm1
+	paddd	%xmm2,%xmm0
+	movdqa	96(%ebx),%xmm7
+	pxor	%xmm0,%xmm6
+	movdqa	%xmm0,-96(%ebx)
+	pshufb	16(%eax),%xmm6
+	paddd	%xmm6,%xmm4
+	movdqa	%xmm6,80(%ebx)
+	pxor	%xmm4,%xmm2
+	paddd	%xmm3,%xmm1
+	movdqa	%xmm2,%xmm0
+	pslld	$7,%xmm2
+	psrld	$25,%xmm0
+	pxor	%xmm1,%xmm7
+	por	%xmm0,%xmm2
+	pshufb	(%eax),%xmm7
+	movdqa	%xmm2,-16(%ebx)
+	paddd	%xmm7,%xmm5
+	pxor	%xmm5,%xmm3
+	movdqa	%xmm3,%xmm0
+	pslld	$12,%xmm3
+	psrld	$20,%xmm0
+	por	%xmm0,%xmm3
+	movdqa	-128(%ebx),%xmm0
+	paddd	%xmm3,%xmm1
+	movdqa	64(%ebx),%xmm6
+	pxor	%xmm1,%xmm7
+	movdqa	%xmm1,-80(%ebx)
+	pshufb	16(%eax),%xmm7
+	paddd	%xmm7,%xmm5
+	movdqa	%xmm7,96(%ebx)
+	pxor	%xmm5,%xmm3
+	movdqa	%xmm3,%xmm1
+	pslld	$7,%xmm3
+	psrld	$25,%xmm1
+	por	%xmm1,%xmm3
+	decl	%edx
+	jnz	L010loop
+	movdqa	%xmm3,-64(%ebx)
+	movdqa	%xmm4,(%ebx)
+	movdqa	%xmm5,16(%ebx)
+	movdqa	%xmm6,64(%ebx)
+	movdqa	%xmm7,96(%ebx)
+	movdqa	-112(%ebx),%xmm1
+	movdqa	-96(%ebx),%xmm2
+	movdqa	-80(%ebx),%xmm3
+	paddd	-128(%ebp),%xmm0
+	paddd	-112(%ebp),%xmm1
+	paddd	-96(%ebp),%xmm2
+	paddd	-80(%ebp),%xmm3
+	movdqa	%xmm0,%xmm6
+	punpckldq	%xmm1,%xmm0
+	movdqa	%xmm2,%xmm7
+	punpckldq	%xmm3,%xmm2
+	punpckhdq	%xmm1,%xmm6
+	punpckhdq	%xmm3,%xmm7
+	movdqa	%xmm0,%xmm1
+	punpcklqdq	%xmm2,%xmm0
+	movdqa	%xmm6,%xmm3
+	punpcklqdq	%xmm7,%xmm6
+	punpckhqdq	%xmm2,%xmm1
+	punpckhqdq	%xmm7,%xmm3
+	movdqu	-128(%esi),%xmm4
+	movdqu	-64(%esi),%xmm5
+	movdqu	(%esi),%xmm2
+	movdqu	64(%esi),%xmm7
+	leal	16(%esi),%esi
+	pxor	%xmm0,%xmm4
+	movdqa	-64(%ebx),%xmm0
+	pxor	%xmm1,%xmm5
+	movdqa	-48(%ebx),%xmm1
+	pxor	%xmm2,%xmm6
+	movdqa	-32(%ebx),%xmm2
+	pxor	%xmm3,%xmm7
+	movdqa	-16(%ebx),%xmm3
+	movdqu	%xmm4,-128(%edi)
+	movdqu	%xmm5,-64(%edi)
+	movdqu	%xmm6,(%edi)
+	movdqu	%xmm7,64(%edi)
+	leal	16(%edi),%edi
+	paddd	-64(%ebp),%xmm0
+	paddd	-48(%ebp),%xmm1
+	paddd	-32(%ebp),%xmm2
+	paddd	-16(%ebp),%xmm3
+	movdqa	%xmm0,%xmm6
+	punpckldq	%xmm1,%xmm0
+	movdqa	%xmm2,%xmm7
+	punpckldq	%xmm3,%xmm2
+	punpckhdq	%xmm1,%xmm6
+	punpckhdq	%xmm3,%xmm7
+	movdqa	%xmm0,%xmm1
+	punpcklqdq	%xmm2,%xmm0
+	movdqa	%xmm6,%xmm3
+	punpcklqdq	%xmm7,%xmm6
+	punpckhqdq	%xmm2,%xmm1
+	punpckhqdq	%xmm7,%xmm3
+	movdqu	-128(%esi),%xmm4
+	movdqu	-64(%esi),%xmm5
+	movdqu	(%esi),%xmm2
+	movdqu	64(%esi),%xmm7
+	leal	16(%esi),%esi
+	pxor	%xmm0,%xmm4
+	movdqa	(%ebx),%xmm0
+	pxor	%xmm1,%xmm5
+	movdqa	16(%ebx),%xmm1
+	pxor	%xmm2,%xmm6
+	movdqa	32(%ebx),%xmm2
+	pxor	%xmm3,%xmm7
+	movdqa	48(%ebx),%xmm3
+	movdqu	%xmm4,-128(%edi)
+	movdqu	%xmm5,-64(%edi)
+	movdqu	%xmm6,(%edi)
+	movdqu	%xmm7,64(%edi)
+	leal	16(%edi),%edi
+	paddd	(%ebp),%xmm0
+	paddd	16(%ebp),%xmm1
+	paddd	32(%ebp),%xmm2
+	paddd	48(%ebp),%xmm3
+	movdqa	%xmm0,%xmm6
+	punpckldq	%xmm1,%xmm0
+	movdqa	%xmm2,%xmm7
+	punpckldq	%xmm3,%xmm2
+	punpckhdq	%xmm1,%xmm6
+	punpckhdq	%xmm3,%xmm7
+	movdqa	%xmm0,%xmm1
+	punpcklqdq	%xmm2,%xmm0
+	movdqa	%xmm6,%xmm3
+	punpcklqdq	%xmm7,%xmm6
+	punpckhqdq	%xmm2,%xmm1
+	punpckhqdq	%xmm7,%xmm3
+	movdqu	-128(%esi),%xmm4
+	movdqu	-64(%esi),%xmm5
+	movdqu	(%esi),%xmm2
+	movdqu	64(%esi),%xmm7
+	leal	16(%esi),%esi
+	pxor	%xmm0,%xmm4
+	movdqa	64(%ebx),%xmm0
+	pxor	%xmm1,%xmm5
+	movdqa	80(%ebx),%xmm1
+	pxor	%xmm2,%xmm6
+	movdqa	96(%ebx),%xmm2
+	pxor	%xmm3,%xmm7
+	movdqa	112(%ebx),%xmm3
+	movdqu	%xmm4,-128(%edi)
+	movdqu	%xmm5,-64(%edi)
+	movdqu	%xmm6,(%edi)
+	movdqu	%xmm7,64(%edi)
+	leal	16(%edi),%edi
+	paddd	64(%ebp),%xmm0
+	paddd	80(%ebp),%xmm1
+	paddd	96(%ebp),%xmm2
+	paddd	112(%ebp),%xmm3
+	movdqa	%xmm0,%xmm6
+	punpckldq	%xmm1,%xmm0
+	movdqa	%xmm2,%xmm7
+	punpckldq	%xmm3,%xmm2
+	punpckhdq	%xmm1,%xmm6
+	punpckhdq	%xmm3,%xmm7
+	movdqa	%xmm0,%xmm1
+	punpcklqdq	%xmm2,%xmm0
+	movdqa	%xmm6,%xmm3
+	punpcklqdq	%xmm7,%xmm6
+	punpckhqdq	%xmm2,%xmm1
+	punpckhqdq	%xmm7,%xmm3
+	movdqu	-128(%esi),%xmm4
+	movdqu	-64(%esi),%xmm5
+	movdqu	(%esi),%xmm2
+	movdqu	64(%esi),%xmm7
+	leal	208(%esi),%esi
+	pxor	%xmm0,%xmm4
+	pxor	%xmm1,%xmm5
+	pxor	%xmm2,%xmm6
+	pxor	%xmm3,%xmm7
+	movdqu	%xmm4,-128(%edi)
+	movdqu	%xmm5,-64(%edi)
+	movdqu	%xmm6,(%edi)
+	movdqu	%xmm7,64(%edi)
+	leal	208(%edi),%edi
+	subl	$256,%ecx
+	jnc	L009outer_loop
+	addl	$256,%ecx
+	jz	L011done
+	movl	520(%esp),%ebx
+	leal	-128(%esi),%esi
+	movl	516(%esp),%edx
+	leal	-128(%edi),%edi
+	movd	64(%ebp),%xmm2
+	movdqu	(%ebx),%xmm3
+	paddd	96(%eax),%xmm2
+	pand	112(%eax),%xmm3
+	por	%xmm2,%xmm3
+L0081x:
+	movdqa	32(%eax),%xmm0
+	movdqu	(%edx),%xmm1
+	movdqu	16(%edx),%xmm2
+	movdqa	(%eax),%xmm6
+	movdqa	16(%eax),%xmm7
+	movl	%ebp,48(%esp)
+	movdqa	%xmm0,(%esp)
+	movdqa	%xmm1,16(%esp)
+	movdqa	%xmm2,32(%esp)
+	movdqa	%xmm3,48(%esp)
+	movl	$10,%edx
+	jmp	L012loop1x
+.align	4,0x90
+L013outer1x:
+	movdqa	80(%eax),%xmm3
+	movdqa	(%esp),%xmm0
+	movdqa	16(%esp),%xmm1
+	movdqa	32(%esp),%xmm2
+	paddd	48(%esp),%xmm3
+	movl	$10,%edx
+	movdqa	%xmm3,48(%esp)
+	jmp	L012loop1x
+.align	4,0x90
+L012loop1x:
+	paddd	%xmm1,%xmm0
+	pxor	%xmm0,%xmm3
+.byte	102,15,56,0,222
+	paddd	%xmm3,%xmm2
+	pxor	%xmm2,%xmm1
+	movdqa	%xmm1,%xmm4
+	psrld	$20,%xmm1
+	pslld	$12,%xmm4
+	por	%xmm4,%xmm1
+	paddd	%xmm1,%xmm0
+	pxor	%xmm0,%xmm3
+.byte	102,15,56,0,223
+	paddd	%xmm3,%xmm2
+	pxor	%xmm2,%xmm1
+	movdqa	%xmm1,%xmm4
+	psrld	$25,%xmm1
+	pslld	$7,%xmm4
+	por	%xmm4,%xmm1
+	pshufd	$78,%xmm2,%xmm2
+	pshufd	$57,%xmm1,%xmm1
+	pshufd	$147,%xmm3,%xmm3
+	nop
+	paddd	%xmm1,%xmm0
+	pxor	%xmm0,%xmm3
+.byte	102,15,56,0,222
+	paddd	%xmm3,%xmm2
+	pxor	%xmm2,%xmm1
+	movdqa	%xmm1,%xmm4
+	psrld	$20,%xmm1
+	pslld	$12,%xmm4
+	por	%xmm4,%xmm1
+	paddd	%xmm1,%xmm0
+	pxor	%xmm0,%xmm3
+.byte	102,15,56,0,223
+	paddd	%xmm3,%xmm2
+	pxor	%xmm2,%xmm1
+	movdqa	%xmm1,%xmm4
+	psrld	$25,%xmm1
+	pslld	$7,%xmm4
+	por	%xmm4,%xmm1
+	pshufd	$78,%xmm2,%xmm2
+	pshufd	$147,%xmm1,%xmm1
+	pshufd	$57,%xmm3,%xmm3
+	decl	%edx
+	jnz	L012loop1x
+	paddd	(%esp),%xmm0
+	paddd	16(%esp),%xmm1
+	paddd	32(%esp),%xmm2
+	paddd	48(%esp),%xmm3
+	cmpl	$64,%ecx
+	jb	L014tail
+	movdqu	(%esi),%xmm4
+	movdqu	16(%esi),%xmm5
+	pxor	%xmm4,%xmm0
+	movdqu	32(%esi),%xmm4
+	pxor	%xmm5,%xmm1
+	movdqu	48(%esi),%xmm5
+	pxor	%xmm4,%xmm2
+	pxor	%xmm5,%xmm3
+	leal	64(%esi),%esi
+	movdqu	%xmm0,(%edi)
+	movdqu	%xmm1,16(%edi)
+	movdqu	%xmm2,32(%edi)
+	movdqu	%xmm3,48(%edi)
+	leal	64(%edi),%edi
+	subl	$64,%ecx
+	jnz	L013outer1x
+	jmp	L011done
+L014tail:
+	movdqa	%xmm0,(%esp)
+	movdqa	%xmm1,16(%esp)
+	movdqa	%xmm2,32(%esp)
+	movdqa	%xmm3,48(%esp)
+	xorl	%eax,%eax
+	xorl	%edx,%edx
+	xorl	%ebp,%ebp
+L015tail_loop:
+	movb	(%esp,%ebp,1),%al
+	movb	(%esi,%ebp,1),%dl
+	leal	1(%ebp),%ebp
+	xorb	%dl,%al
+	movb	%al,-1(%edi,%ebp,1)
+	decl	%ecx
+	jnz	L015tail_loop
+L011done:
+	movl	512(%esp),%esp
+	popl	%edi
+	popl	%esi
+	popl	%ebx
+	popl	%ebp
+	ret
+.align	6,0x90
+Lssse3_data:
+.byte	2,3,0,1,6,7,4,5,10,11,8,9,14,15,12,13
+.byte	3,0,1,2,7,4,5,6,11,8,9,10,15,12,13,14
+.long	1634760805,857760878,2036477234,1797285236
+.long	0,1,2,3
+.long	4,4,4,4
+.long	1,0,0,0
+.long	4,0,0,0
+.long	0,-1,-1,-1
+.align	6,0x90
+.byte	67,104,97,67,104,97,50,48,32,102,111,114,32,120,56,54
+.byte	44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32
+.byte	60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111
+.byte	114,103,62,0
+.section __IMPORT,__pointers,non_lazy_symbol_pointers
+L_OPENSSL_ia32cap_P$non_lazy_ptr:
+.indirect_symbol	_OPENSSL_ia32cap_P
+.long	0
+#endif
diff --git a/mac-x86/crypto/modes/ghash-x86.S b/mac-x86/crypto/modes/ghash-x86.S
index 8693b82..8ae2183 100644
--- a/mac-x86/crypto/modes/ghash-x86.S
+++ b/mac-x86/crypto/modes/ghash-x86.S
@@ -1,207 +1,6 @@
 #if defined(__i386__)
 .file	"ghash-x86.S"
 .text
-.globl	_gcm_gmult_4bit_x86
-.private_extern	_gcm_gmult_4bit_x86
-.align	4
-_gcm_gmult_4bit_x86:
-L_gcm_gmult_4bit_x86_begin:
-	pushl	%ebp
-	pushl	%ebx
-	pushl	%esi
-	pushl	%edi
-	subl	$84,%esp
-	movl	104(%esp),%edi
-	movl	108(%esp),%esi
-	movl	(%edi),%ebp
-	movl	4(%edi),%edx
-	movl	8(%edi),%ecx
-	movl	12(%edi),%ebx
-	movl	$0,16(%esp)
-	movl	$471859200,20(%esp)
-	movl	$943718400,24(%esp)
-	movl	$610271232,28(%esp)
-	movl	$1887436800,32(%esp)
-	movl	$1822425088,36(%esp)
-	movl	$1220542464,40(%esp)
-	movl	$1423966208,44(%esp)
-	movl	$3774873600,48(%esp)
-	movl	$4246732800,52(%esp)
-	movl	$3644850176,56(%esp)
-	movl	$3311403008,60(%esp)
-	movl	$2441084928,64(%esp)
-	movl	$2376073216,68(%esp)
-	movl	$2847932416,72(%esp)
-	movl	$3051356160,76(%esp)
-	movl	%ebp,(%esp)
-	movl	%edx,4(%esp)
-	movl	%ecx,8(%esp)
-	movl	%ebx,12(%esp)
-	shrl	$20,%ebx
-	andl	$240,%ebx
-	movl	4(%esi,%ebx,1),%ebp
-	movl	(%esi,%ebx,1),%edx
-	movl	12(%esi,%ebx,1),%ecx
-	movl	8(%esi,%ebx,1),%ebx
-	xorl	%eax,%eax
-	movl	$15,%edi
-	jmp	L000x86_loop
-.align	4,0x90
-L000x86_loop:
-	movb	%bl,%al
-	shrdl	$4,%ecx,%ebx
-	andb	$15,%al
-	shrdl	$4,%edx,%ecx
-	shrdl	$4,%ebp,%edx
-	shrl	$4,%ebp
-	xorl	16(%esp,%eax,4),%ebp
-	movb	(%esp,%edi,1),%al
-	andb	$240,%al
-	xorl	8(%esi,%eax,1),%ebx
-	xorl	12(%esi,%eax,1),%ecx
-	xorl	(%esi,%eax,1),%edx
-	xorl	4(%esi,%eax,1),%ebp
-	decl	%edi
-	js	L001x86_break
-	movb	%bl,%al
-	shrdl	$4,%ecx,%ebx
-	andb	$15,%al
-	shrdl	$4,%edx,%ecx
-	shrdl	$4,%ebp,%edx
-	shrl	$4,%ebp
-	xorl	16(%esp,%eax,4),%ebp
-	movb	(%esp,%edi,1),%al
-	shlb	$4,%al
-	xorl	8(%esi,%eax,1),%ebx
-	xorl	12(%esi,%eax,1),%ecx
-	xorl	(%esi,%eax,1),%edx
-	xorl	4(%esi,%eax,1),%ebp
-	jmp	L000x86_loop
-.align	4,0x90
-L001x86_break:
-	bswap	%ebx
-	bswap	%ecx
-	bswap	%edx
-	bswap	%ebp
-	movl	104(%esp),%edi
-	movl	%ebx,12(%edi)
-	movl	%ecx,8(%edi)
-	movl	%edx,4(%edi)
-	movl	%ebp,(%edi)
-	addl	$84,%esp
-	popl	%edi
-	popl	%esi
-	popl	%ebx
-	popl	%ebp
-	ret
-.globl	_gcm_ghash_4bit_x86
-.private_extern	_gcm_ghash_4bit_x86
-.align	4
-_gcm_ghash_4bit_x86:
-L_gcm_ghash_4bit_x86_begin:
-	pushl	%ebp
-	pushl	%ebx
-	pushl	%esi
-	pushl	%edi
-	subl	$84,%esp
-	movl	104(%esp),%ebx
-	movl	108(%esp),%esi
-	movl	112(%esp),%edi
-	movl	116(%esp),%ecx
-	addl	%edi,%ecx
-	movl	%ecx,116(%esp)
-	movl	(%ebx),%ebp
-	movl	4(%ebx),%edx
-	movl	8(%ebx),%ecx
-	movl	12(%ebx),%ebx
-	movl	$0,16(%esp)
-	movl	$471859200,20(%esp)
-	movl	$943718400,24(%esp)
-	movl	$610271232,28(%esp)
-	movl	$1887436800,32(%esp)
-	movl	$1822425088,36(%esp)
-	movl	$1220542464,40(%esp)
-	movl	$1423966208,44(%esp)
-	movl	$3774873600,48(%esp)
-	movl	$4246732800,52(%esp)
-	movl	$3644850176,56(%esp)
-	movl	$3311403008,60(%esp)
-	movl	$2441084928,64(%esp)
-	movl	$2376073216,68(%esp)
-	movl	$2847932416,72(%esp)
-	movl	$3051356160,76(%esp)
-.align	4,0x90
-L002x86_outer_loop:
-	xorl	12(%edi),%ebx
-	xorl	8(%edi),%ecx
-	xorl	4(%edi),%edx
-	xorl	(%edi),%ebp
-	movl	%ebx,12(%esp)
-	movl	%ecx,8(%esp)
-	movl	%edx,4(%esp)
-	movl	%ebp,(%esp)
-	shrl	$20,%ebx
-	andl	$240,%ebx
-	movl	4(%esi,%ebx,1),%ebp
-	movl	(%esi,%ebx,1),%edx
-	movl	12(%esi,%ebx,1),%ecx
-	movl	8(%esi,%ebx,1),%ebx
-	xorl	%eax,%eax
-	movl	$15,%edi
-	jmp	L003x86_loop
-.align	4,0x90
-L003x86_loop:
-	movb	%bl,%al
-	shrdl	$4,%ecx,%ebx
-	andb	$15,%al
-	shrdl	$4,%edx,%ecx
-	shrdl	$4,%ebp,%edx
-	shrl	$4,%ebp
-	xorl	16(%esp,%eax,4),%ebp
-	movb	(%esp,%edi,1),%al
-	andb	$240,%al
-	xorl	8(%esi,%eax,1),%ebx
-	xorl	12(%esi,%eax,1),%ecx
-	xorl	(%esi,%eax,1),%edx
-	xorl	4(%esi,%eax,1),%ebp
-	decl	%edi
-	js	L004x86_break
-	movb	%bl,%al
-	shrdl	$4,%ecx,%ebx
-	andb	$15,%al
-	shrdl	$4,%edx,%ecx
-	shrdl	$4,%ebp,%edx
-	shrl	$4,%ebp
-	xorl	16(%esp,%eax,4),%ebp
-	movb	(%esp,%edi,1),%al
-	shlb	$4,%al
-	xorl	8(%esi,%eax,1),%ebx
-	xorl	12(%esi,%eax,1),%ecx
-	xorl	(%esi,%eax,1),%edx
-	xorl	4(%esi,%eax,1),%ebp
-	jmp	L003x86_loop
-.align	4,0x90
-L004x86_break:
-	bswap	%ebx
-	bswap	%ecx
-	bswap	%edx
-	bswap	%ebp
-	movl	112(%esp),%edi
-	leal	16(%edi),%edi
-	cmpl	116(%esp),%edi
-	movl	%edi,112(%esp)
-	jb	L002x86_outer_loop
-	movl	104(%esp),%edi
-	movl	%ebx,12(%edi)
-	movl	%ecx,8(%edi)
-	movl	%edx,4(%edi)
-	movl	%ebp,(%edi)
-	addl	$84,%esp
-	popl	%edi
-	popl	%esi
-	popl	%ebx
-	popl	%ebp
-	ret
 .globl	_gcm_gmult_4bit_mmx
 .private_extern	_gcm_gmult_4bit_mmx
 .align	4
@@ -213,10 +12,10 @@
 	pushl	%edi
 	movl	20(%esp),%edi
 	movl	24(%esp),%esi
-	call	L005pic_point
-L005pic_point:
+	call	L000pic_point
+L000pic_point:
 	popl	%eax
-	leal	Lrem_4bit-L005pic_point(%eax),%eax
+	leal	Lrem_4bit-L000pic_point(%eax),%eax
 	movzbl	15(%edi),%ebx
 	xorl	%ecx,%ecx
 	movl	%ebx,%edx
@@ -227,9 +26,9 @@
 	movq	8(%esi,%ecx,1),%mm0
 	movq	(%esi,%ecx,1),%mm1
 	movd	%mm0,%ebx
-	jmp	L006mmx_loop
+	jmp	L001mmx_loop
 .align	4,0x90
-L006mmx_loop:
+L001mmx_loop:
 	psrlq	$4,%mm0
 	andl	$15,%ebx
 	movq	%mm1,%mm2
@@ -243,7 +42,7 @@
 	pxor	(%esi,%edx,1),%mm1
 	movl	%ecx,%edx
 	pxor	%mm2,%mm0
-	js	L007mmx_break
+	js	L002mmx_break
 	shlb	$4,%cl
 	andl	$15,%ebx
 	psrlq	$4,%mm0
@@ -256,9 +55,9 @@
 	movd	%mm0,%ebx
 	pxor	(%esi,%ecx,1),%mm1
 	pxor	%mm2,%mm0
-	jmp	L006mmx_loop
+	jmp	L001mmx_loop
 .align	4,0x90
-L007mmx_break:
+L002mmx_break:
 	shlb	$4,%cl
 	andl	$15,%ebx
 	psrlq	$4,%mm0
@@ -314,10 +113,10 @@
 	movl	28(%esp),%ecx
 	movl	32(%esp),%edx
 	movl	%esp,%ebp
-	call	L008pic_point
-L008pic_point:
+	call	L003pic_point
+L003pic_point:
 	popl	%esi
-	leal	Lrem_8bit-L008pic_point(%esi),%esi
+	leal	Lrem_8bit-L003pic_point(%esi),%esi
 	subl	$544,%esp
 	andl	$-64,%esp
 	subl	$16,%esp
@@ -556,7 +355,7 @@
 	movl	8(%eax),%ebx
 	movl	12(%eax),%edx
 .align	4,0x90
-L009outer:
+L004outer:
 	xorl	12(%ecx),%edx
 	xorl	8(%ecx),%ebx
 	pxor	(%ecx),%mm6
@@ -891,7 +690,7 @@
 	pshufw	$27,%mm6,%mm6
 	bswap	%ebx
 	cmpl	552(%esp),%ecx
-	jne	L009outer
+	jne	L004outer
 	movl	544(%esp),%eax
 	movl	%edx,12(%eax)
 	movl	%ebx,8(%eax)
@@ -910,10 +709,10 @@
 L_gcm_init_clmul_begin:
 	movl	4(%esp),%edx
 	movl	8(%esp),%eax
-	call	L010pic
-L010pic:
+	call	L005pic
+L005pic:
 	popl	%ecx
-	leal	Lbswap-L010pic(%ecx),%ecx
+	leal	Lbswap-L005pic(%ecx),%ecx
 	movdqu	(%eax),%xmm2
 	pshufd	$78,%xmm2,%xmm2
 	pshufd	$255,%xmm2,%xmm4
@@ -978,10 +777,10 @@
 L_gcm_gmult_clmul_begin:
 	movl	4(%esp),%eax
 	movl	8(%esp),%edx
-	call	L011pic
-L011pic:
+	call	L006pic
+L006pic:
 	popl	%ecx
-	leal	Lbswap-L011pic(%ecx),%ecx
+	leal	Lbswap-L006pic(%ecx),%ecx
 	movdqu	(%eax),%xmm0
 	movdqa	(%ecx),%xmm5
 	movups	(%edx),%xmm2
@@ -1036,16 +835,16 @@
 	movl	24(%esp),%edx
 	movl	28(%esp),%esi
 	movl	32(%esp),%ebx
-	call	L012pic
-L012pic:
+	call	L007pic
+L007pic:
 	popl	%ecx
-	leal	Lbswap-L012pic(%ecx),%ecx
+	leal	Lbswap-L007pic(%ecx),%ecx
 	movdqu	(%eax),%xmm0
 	movdqa	(%ecx),%xmm5
 	movdqu	(%edx),%xmm2
 .byte	102,15,56,0,197
 	subl	$16,%ebx
-	jz	L013odd_tail
+	jz	L008odd_tail
 	movdqu	(%esi),%xmm3
 	movdqu	16(%esi),%xmm6
 .byte	102,15,56,0,221
@@ -1062,10 +861,10 @@
 	movups	16(%edx),%xmm2
 	nop
 	subl	$32,%ebx
-	jbe	L014even_tail
-	jmp	L015mod_loop
+	jbe	L009even_tail
+	jmp	L010mod_loop
 .align	5,0x90
-L015mod_loop:
+L010mod_loop:
 	pshufd	$78,%xmm0,%xmm4
 	movdqa	%xmm0,%xmm1
 	pxor	%xmm0,%xmm4
@@ -1120,8 +919,8 @@
 .byte	102,15,58,68,221,0
 	leal	32(%esi),%esi
 	subl	$32,%ebx
-	ja	L015mod_loop
-L014even_tail:
+	ja	L010mod_loop
+L009even_tail:
 	pshufd	$78,%xmm0,%xmm4
 	movdqa	%xmm0,%xmm1
 	pxor	%xmm0,%xmm4
@@ -1160,9 +959,9 @@
 	psrlq	$1,%xmm0
 	pxor	%xmm1,%xmm0
 	testl	%ebx,%ebx
-	jnz	L016done
+	jnz	L011done
 	movups	(%edx),%xmm2
-L013odd_tail:
+L008odd_tail:
 	movdqu	(%esi),%xmm3
 .byte	102,15,56,0,221
 	pxor	%xmm3,%xmm0
@@ -1201,7 +1000,7 @@
 	pxor	%xmm4,%xmm0
 	psrlq	$1,%xmm0
 	pxor	%xmm1,%xmm0
-L016done:
+L011done:
 .byte	102,15,56,0,197
 	movdqu	%xmm0,(%eax)
 	popl	%edi
diff --git a/mac-x86/crypto/rc4/rc4-586.S b/mac-x86/crypto/rc4/rc4-586.S
deleted file mode 100644
index faecdfa..0000000
--- a/mac-x86/crypto/rc4/rc4-586.S
+++ /dev/null
@@ -1,383 +0,0 @@
-#if defined(__i386__)
-.file	"rc4-586.S"
-.text
-.globl	_asm_RC4
-.private_extern	_asm_RC4
-.align	4
-_asm_RC4:
-L_asm_RC4_begin:
-	pushl	%ebp
-	pushl	%ebx
-	pushl	%esi
-	pushl	%edi
-	movl	20(%esp),%edi
-	movl	24(%esp),%edx
-	movl	28(%esp),%esi
-	movl	32(%esp),%ebp
-	xorl	%eax,%eax
-	xorl	%ebx,%ebx
-	cmpl	$0,%edx
-	je	L000abort
-	movb	(%edi),%al
-	movb	4(%edi),%bl
-	addl	$8,%edi
-	leal	(%esi,%edx,1),%ecx
-	subl	%esi,%ebp
-	movl	%ecx,24(%esp)
-	incb	%al
-	cmpl	$-1,256(%edi)
-	je	L001RC4_CHAR
-	movl	(%edi,%eax,4),%ecx
-	andl	$-4,%edx
-	jz	L002loop1
-	movl	%ebp,32(%esp)
-	testl	$-8,%edx
-	jz	L003go4loop4
-	call	L004PIC_me_up
-L004PIC_me_up:
-	popl	%ebp
-	movl	L_OPENSSL_ia32cap_P$non_lazy_ptr-L004PIC_me_up(%ebp),%ebp
-	btl	$26,(%ebp)
-	jnc	L003go4loop4
-	movl	32(%esp),%ebp
-	andl	$-8,%edx
-	leal	-8(%esi,%edx,1),%edx
-	movl	%edx,-4(%edi)
-	addb	%cl,%bl
-	movl	(%edi,%ebx,4),%edx
-	movl	%ecx,(%edi,%ebx,4)
-	movl	%edx,(%edi,%eax,4)
-	incl	%eax
-	addl	%ecx,%edx
-	movzbl	%al,%eax
-	movzbl	%dl,%edx
-	movq	(%esi),%mm0
-	movl	(%edi,%eax,4),%ecx
-	movd	(%edi,%edx,4),%mm2
-	jmp	L005loop_mmx_enter
-.align	4,0x90
-L006loop_mmx:
-	addb	%cl,%bl
-	psllq	$56,%mm1
-	movl	(%edi,%ebx,4),%edx
-	movl	%ecx,(%edi,%ebx,4)
-	movl	%edx,(%edi,%eax,4)
-	incl	%eax
-	addl	%ecx,%edx
-	movzbl	%al,%eax
-	movzbl	%dl,%edx
-	pxor	%mm1,%mm2
-	movq	(%esi),%mm0
-	movq	%mm2,-8(%ebp,%esi,1)
-	movl	(%edi,%eax,4),%ecx
-	movd	(%edi,%edx,4),%mm2
-L005loop_mmx_enter:
-	addb	%cl,%bl
-	movl	(%edi,%ebx,4),%edx
-	movl	%ecx,(%edi,%ebx,4)
-	movl	%edx,(%edi,%eax,4)
-	incl	%eax
-	addl	%ecx,%edx
-	movzbl	%al,%eax
-	movzbl	%dl,%edx
-	pxor	%mm0,%mm2
-	movl	(%edi,%eax,4),%ecx
-	movd	(%edi,%edx,4),%mm1
-	addb	%cl,%bl
-	psllq	$8,%mm1
-	movl	(%edi,%ebx,4),%edx
-	movl	%ecx,(%edi,%ebx,4)
-	movl	%edx,(%edi,%eax,4)
-	incl	%eax
-	addl	%ecx,%edx
-	movzbl	%al,%eax
-	movzbl	%dl,%edx
-	pxor	%mm1,%mm2
-	movl	(%edi,%eax,4),%ecx
-	movd	(%edi,%edx,4),%mm1
-	addb	%cl,%bl
-	psllq	$16,%mm1
-	movl	(%edi,%ebx,4),%edx
-	movl	%ecx,(%edi,%ebx,4)
-	movl	%edx,(%edi,%eax,4)
-	incl	%eax
-	addl	%ecx,%edx
-	movzbl	%al,%eax
-	movzbl	%dl,%edx
-	pxor	%mm1,%mm2
-	movl	(%edi,%eax,4),%ecx
-	movd	(%edi,%edx,4),%mm1
-	addb	%cl,%bl
-	psllq	$24,%mm1
-	movl	(%edi,%ebx,4),%edx
-	movl	%ecx,(%edi,%ebx,4)
-	movl	%edx,(%edi,%eax,4)
-	incl	%eax
-	addl	%ecx,%edx
-	movzbl	%al,%eax
-	movzbl	%dl,%edx
-	pxor	%mm1,%mm2
-	movl	(%edi,%eax,4),%ecx
-	movd	(%edi,%edx,4),%mm1
-	addb	%cl,%bl
-	psllq	$32,%mm1
-	movl	(%edi,%ebx,4),%edx
-	movl	%ecx,(%edi,%ebx,4)
-	movl	%edx,(%edi,%eax,4)
-	incl	%eax
-	addl	%ecx,%edx
-	movzbl	%al,%eax
-	movzbl	%dl,%edx
-	pxor	%mm1,%mm2
-	movl	(%edi,%eax,4),%ecx
-	movd	(%edi,%edx,4),%mm1
-	addb	%cl,%bl
-	psllq	$40,%mm1
-	movl	(%edi,%ebx,4),%edx
-	movl	%ecx,(%edi,%ebx,4)
-	movl	%edx,(%edi,%eax,4)
-	incl	%eax
-	addl	%ecx,%edx
-	movzbl	%al,%eax
-	movzbl	%dl,%edx
-	pxor	%mm1,%mm2
-	movl	(%edi,%eax,4),%ecx
-	movd	(%edi,%edx,4),%mm1
-	addb	%cl,%bl
-	psllq	$48,%mm1
-	movl	(%edi,%ebx,4),%edx
-	movl	%ecx,(%edi,%ebx,4)
-	movl	%edx,(%edi,%eax,4)
-	incl	%eax
-	addl	%ecx,%edx
-	movzbl	%al,%eax
-	movzbl	%dl,%edx
-	pxor	%mm1,%mm2
-	movl	(%edi,%eax,4),%ecx
-	movd	(%edi,%edx,4),%mm1
-	movl	%ebx,%edx
-	xorl	%ebx,%ebx
-	movb	%dl,%bl
-	cmpl	-4(%edi),%esi
-	leal	8(%esi),%esi
-	jb	L006loop_mmx
-	psllq	$56,%mm1
-	pxor	%mm1,%mm2
-	movq	%mm2,-8(%ebp,%esi,1)
-	emms
-	cmpl	24(%esp),%esi
-	je	L007done
-	jmp	L002loop1
-.align	4,0x90
-L003go4loop4:
-	leal	-4(%esi,%edx,1),%edx
-	movl	%edx,28(%esp)
-L008loop4:
-	addb	%cl,%bl
-	movl	(%edi,%ebx,4),%edx
-	movl	%ecx,(%edi,%ebx,4)
-	movl	%edx,(%edi,%eax,4)
-	addl	%ecx,%edx
-	incb	%al
-	andl	$255,%edx
-	movl	(%edi,%eax,4),%ecx
-	movl	(%edi,%edx,4),%ebp
-	addb	%cl,%bl
-	movl	(%edi,%ebx,4),%edx
-	movl	%ecx,(%edi,%ebx,4)
-	movl	%edx,(%edi,%eax,4)
-	addl	%ecx,%edx
-	incb	%al
-	andl	$255,%edx
-	rorl	$8,%ebp
-	movl	(%edi,%eax,4),%ecx
-	orl	(%edi,%edx,4),%ebp
-	addb	%cl,%bl
-	movl	(%edi,%ebx,4),%edx
-	movl	%ecx,(%edi,%ebx,4)
-	movl	%edx,(%edi,%eax,4)
-	addl	%ecx,%edx
-	incb	%al
-	andl	$255,%edx
-	rorl	$8,%ebp
-	movl	(%edi,%eax,4),%ecx
-	orl	(%edi,%edx,4),%ebp
-	addb	%cl,%bl
-	movl	(%edi,%ebx,4),%edx
-	movl	%ecx,(%edi,%ebx,4)
-	movl	%edx,(%edi,%eax,4)
-	addl	%ecx,%edx
-	incb	%al
-	andl	$255,%edx
-	rorl	$8,%ebp
-	movl	32(%esp),%ecx
-	orl	(%edi,%edx,4),%ebp
-	rorl	$8,%ebp
-	xorl	(%esi),%ebp
-	cmpl	28(%esp),%esi
-	movl	%ebp,(%ecx,%esi,1)
-	leal	4(%esi),%esi
-	movl	(%edi,%eax,4),%ecx
-	jb	L008loop4
-	cmpl	24(%esp),%esi
-	je	L007done
-	movl	32(%esp),%ebp
-.align	4,0x90
-L002loop1:
-	addb	%cl,%bl
-	movl	(%edi,%ebx,4),%edx
-	movl	%ecx,(%edi,%ebx,4)
-	movl	%edx,(%edi,%eax,4)
-	addl	%ecx,%edx
-	incb	%al
-	andl	$255,%edx
-	movl	(%edi,%edx,4),%edx
-	xorb	(%esi),%dl
-	leal	1(%esi),%esi
-	movl	(%edi,%eax,4),%ecx
-	cmpl	24(%esp),%esi
-	movb	%dl,-1(%ebp,%esi,1)
-	jb	L002loop1
-	jmp	L007done
-.align	4,0x90
-L001RC4_CHAR:
-	movzbl	(%edi,%eax,1),%ecx
-L009cloop1:
-	addb	%cl,%bl
-	movzbl	(%edi,%ebx,1),%edx
-	movb	%cl,(%edi,%ebx,1)
-	movb	%dl,(%edi,%eax,1)
-	addb	%cl,%dl
-	movzbl	(%edi,%edx,1),%edx
-	addb	$1,%al
-	xorb	(%esi),%dl
-	leal	1(%esi),%esi
-	movzbl	(%edi,%eax,1),%ecx
-	cmpl	24(%esp),%esi
-	movb	%dl,-1(%ebp,%esi,1)
-	jb	L009cloop1
-L007done:
-	decb	%al
-	movl	%ebx,-4(%edi)
-	movb	%al,-8(%edi)
-L000abort:
-	popl	%edi
-	popl	%esi
-	popl	%ebx
-	popl	%ebp
-	ret
-.globl	_asm_RC4_set_key
-.private_extern	_asm_RC4_set_key
-.align	4
-_asm_RC4_set_key:
-L_asm_RC4_set_key_begin:
-	pushl	%ebp
-	pushl	%ebx
-	pushl	%esi
-	pushl	%edi
-	movl	20(%esp),%edi
-	movl	24(%esp),%ebp
-	movl	28(%esp),%esi
-	call	L010PIC_me_up
-L010PIC_me_up:
-	popl	%edx
-	movl	L_OPENSSL_ia32cap_P$non_lazy_ptr-L010PIC_me_up(%edx),%edx
-	leal	8(%edi),%edi
-	leal	(%esi,%ebp,1),%esi
-	negl	%ebp
-	xorl	%eax,%eax
-	movl	%ebp,-4(%edi)
-	btl	$20,(%edx)
-	jc	L011c1stloop
-.align	4,0x90
-L012w1stloop:
-	movl	%eax,(%edi,%eax,4)
-	addb	$1,%al
-	jnc	L012w1stloop
-	xorl	%ecx,%ecx
-	xorl	%edx,%edx
-.align	4,0x90
-L013w2ndloop:
-	movl	(%edi,%ecx,4),%eax
-	addb	(%esi,%ebp,1),%dl
-	addb	%al,%dl
-	addl	$1,%ebp
-	movl	(%edi,%edx,4),%ebx
-	jnz	L014wnowrap
-	movl	-4(%edi),%ebp
-L014wnowrap:
-	movl	%eax,(%edi,%edx,4)
-	movl	%ebx,(%edi,%ecx,4)
-	addb	$1,%cl
-	jnc	L013w2ndloop
-	jmp	L015exit
-.align	4,0x90
-L011c1stloop:
-	movb	%al,(%edi,%eax,1)
-	addb	$1,%al
-	jnc	L011c1stloop
-	xorl	%ecx,%ecx
-	xorl	%edx,%edx
-	xorl	%ebx,%ebx
-.align	4,0x90
-L016c2ndloop:
-	movb	(%edi,%ecx,1),%al
-	addb	(%esi,%ebp,1),%dl
-	addb	%al,%dl
-	addl	$1,%ebp
-	movb	(%edi,%edx,1),%bl
-	jnz	L017cnowrap
-	movl	-4(%edi),%ebp
-L017cnowrap:
-	movb	%al,(%edi,%edx,1)
-	movb	%bl,(%edi,%ecx,1)
-	addb	$1,%cl
-	jnc	L016c2ndloop
-	movl	$-1,256(%edi)
-L015exit:
-	xorl	%eax,%eax
-	movl	%eax,-8(%edi)
-	movl	%eax,-4(%edi)
-	popl	%edi
-	popl	%esi
-	popl	%ebx
-	popl	%ebp
-	ret
-.globl	_RC4_options
-.private_extern	_RC4_options
-.align	4
-_RC4_options:
-L_RC4_options_begin:
-	call	L018pic_point
-L018pic_point:
-	popl	%eax
-	leal	L019opts-L018pic_point(%eax),%eax
-	call	L020PIC_me_up
-L020PIC_me_up:
-	popl	%edx
-	movl	L_OPENSSL_ia32cap_P$non_lazy_ptr-L020PIC_me_up(%edx),%edx
-	movl	(%edx),%edx
-	btl	$20,%edx
-	jc	L0211xchar
-	btl	$26,%edx
-	jnc	L022ret
-	addl	$25,%eax
-	ret
-L0211xchar:
-	addl	$12,%eax
-L022ret:
-	ret
-.align	6,0x90
-L019opts:
-.byte	114,99,52,40,52,120,44,105,110,116,41,0
-.byte	114,99,52,40,49,120,44,99,104,97,114,41,0
-.byte	114,99,52,40,56,120,44,109,109,120,41,0
-.byte	82,67,52,32,102,111,114,32,120,56,54,44,32,67,82,89
-.byte	80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114
-.byte	111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
-.align	6,0x90
-.section __IMPORT,__pointers,non_lazy_symbol_pointers
-L_OPENSSL_ia32cap_P$non_lazy_ptr:
-.indirect_symbol	_OPENSSL_ia32cap_P
-.long	0
-#endif
diff --git a/mac-x86_64/crypto/aes/aes-x86_64.S b/mac-x86_64/crypto/aes/aes-x86_64.S
index 02f378b..52df2ae 100644
--- a/mac-x86_64/crypto/aes/aes-x86_64.S
+++ b/mac-x86_64/crypto/aes/aes-x86_64.S
@@ -82,8 +82,8 @@
 	movl	0(%r14,%rdi,8),%edi
 	movl	0(%r14,%rbp,8),%ebp
 
-	andl	$65280,%edi
-	andl	$65280,%ebp
+	andl	$0x0000ff00,%edi
+	andl	$0x0000ff00,%ebp
 
 	xorl	%edi,%r10d
 	xorl	%ebp,%r11d
@@ -95,8 +95,8 @@
 	movl	0(%r14,%rsi,8),%esi
 	movl	0(%r14,%rdi,8),%edi
 
-	andl	$65280,%esi
-	andl	$65280,%edi
+	andl	$0x0000ff00,%esi
+	andl	$0x0000ff00,%edi
 	shrl	$16,%ebx
 	xorl	%esi,%r12d
 	xorl	%edi,%r8d
@@ -109,9 +109,9 @@
 	movl	0(%r14,%rdi,8),%edi
 	movl	0(%r14,%rbp,8),%ebp
 
-	andl	$16711680,%esi
-	andl	$16711680,%edi
-	andl	$16711680,%ebp
+	andl	$0x00ff0000,%esi
+	andl	$0x00ff0000,%edi
+	andl	$0x00ff0000,%ebp
 
 	xorl	%esi,%r10d
 	xorl	%edi,%r11d
@@ -124,9 +124,9 @@
 	movl	2(%r14,%rdi,8),%edi
 	movl	2(%r14,%rbp,8),%ebp
 
-	andl	$16711680,%esi
-	andl	$4278190080,%edi
-	andl	$4278190080,%ebp
+	andl	$0x00ff0000,%esi
+	andl	$0xff000000,%edi
+	andl	$0xff000000,%ebp
 
 	xorl	%esi,%r8d
 	xorl	%edi,%r10d
@@ -139,8 +139,8 @@
 	movl	2(%r14,%rdi,8),%edi
 	movl	16+0(%r15),%eax
 
-	andl	$4278190080,%esi
-	andl	$4278190080,%edi
+	andl	$0xff000000,%esi
+	andl	$0xff000000,%edi
 
 	xorl	%esi,%r12d
 	xorl	%edi,%r8d
@@ -242,8 +242,8 @@
 	xorl	%r8d,%edx
 	cmpq	16(%rsp),%r15
 	je	L$enc_compact_done
-	movl	$2155905152,%r10d
-	movl	$2155905152,%r11d
+	movl	$0x80808080,%r10d
+	movl	$0x80808080,%r11d
 	andl	%eax,%r10d
 	andl	%ebx,%r11d
 	movl	%r10d,%esi
@@ -254,10 +254,10 @@
 	leal	(%rbx,%rbx,1),%r9d
 	subl	%r10d,%esi
 	subl	%r11d,%edi
-	andl	$4278124286,%r8d
-	andl	$4278124286,%r9d
-	andl	$454761243,%esi
-	andl	$454761243,%edi
+	andl	$0xfefefefe,%r8d
+	andl	$0xfefefefe,%r9d
+	andl	$0x1b1b1b1b,%esi
+	andl	$0x1b1b1b1b,%edi
 	movl	%eax,%r10d
 	movl	%ebx,%r11d
 	xorl	%esi,%r8d
@@ -265,9 +265,9 @@
 
 	xorl	%r8d,%eax
 	xorl	%r9d,%ebx
-	movl	$2155905152,%r12d
+	movl	$0x80808080,%r12d
 	roll	$24,%eax
-	movl	$2155905152,%ebp
+	movl	$0x80808080,%ebp
 	roll	$24,%ebx
 	andl	%ecx,%r12d
 	andl	%edx,%ebp
@@ -290,10 +290,10 @@
 	xorl	%r10d,%eax
 	xorl	%r11d,%ebx
 
-	andl	$4278124286,%r8d
-	andl	$4278124286,%r9d
-	andl	$454761243,%esi
-	andl	$454761243,%edi
+	andl	$0xfefefefe,%r8d
+	andl	$0xfefefefe,%r9d
+	andl	$0x1b1b1b1b,%esi
+	andl	$0x1b1b1b1b,%edi
 	movl	%ecx,%r12d
 	movl	%edx,%ebp
 	xorl	%esi,%r8d
@@ -332,6 +332,7 @@
 
 .private_extern	_asm_AES_encrypt
 _asm_AES_encrypt:
+	movq	%rsp,%rax
 	pushq	%rbx
 	pushq	%rbp
 	pushq	%r12
@@ -340,17 +341,16 @@
 	pushq	%r15
 
 
-	movq	%rsp,%r10
 	leaq	-63(%rdx),%rcx
 	andq	$-64,%rsp
 	subq	%rsp,%rcx
 	negq	%rcx
-	andq	$960,%rcx
+	andq	$0x3c0,%rcx
 	subq	%rcx,%rsp
 	subq	$32,%rsp
 
 	movq	%rsi,16(%rsp)
-	movq	%r10,24(%rsp)
+	movq	%rax,24(%rsp)
 L$enc_prologue:
 
 	movq	%rdx,%r15
@@ -370,7 +370,7 @@
 	leaq	L$AES_Te+2048(%rip),%r14
 	leaq	768(%rsp),%rbp
 	subq	%r14,%rbp
-	andq	$768,%rbp
+	andq	$0x300,%rbp
 	leaq	(%r14,%rbp,1),%r14
 
 	call	_x86_64_AES_encrypt_compact
@@ -382,13 +382,13 @@
 	movl	%ecx,8(%r9)
 	movl	%edx,12(%r9)
 
-	movq	(%rsi),%r15
-	movq	8(%rsi),%r14
-	movq	16(%rsi),%r13
-	movq	24(%rsi),%r12
-	movq	32(%rsi),%rbp
-	movq	40(%rsi),%rbx
-	leaq	48(%rsi),%rsp
+	movq	-48(%rsi),%r15
+	movq	-40(%rsi),%r14
+	movq	-32(%rsi),%r13
+	movq	-24(%rsi),%r12
+	movq	-16(%rsi),%rbp
+	movq	-8(%rsi),%rbx
+	leaq	(%rsi),%rsp
 L$enc_epilogue:
 	.byte	0xf3,0xc3
 
@@ -778,6 +778,7 @@
 
 .private_extern	_asm_AES_decrypt
 _asm_AES_decrypt:
+	movq	%rsp,%rax
 	pushq	%rbx
 	pushq	%rbp
 	pushq	%r12
@@ -786,17 +787,16 @@
 	pushq	%r15
 
 
-	movq	%rsp,%r10
 	leaq	-63(%rdx),%rcx
 	andq	$-64,%rsp
 	subq	%rsp,%rcx
 	negq	%rcx
-	andq	$960,%rcx
+	andq	$0x3c0,%rcx
 	subq	%rcx,%rsp
 	subq	$32,%rsp
 
 	movq	%rsi,16(%rsp)
-	movq	%r10,24(%rsp)
+	movq	%rax,24(%rsp)
 L$dec_prologue:
 
 	movq	%rdx,%r15
@@ -816,7 +816,7 @@
 	leaq	L$AES_Td+2048(%rip),%r14
 	leaq	768(%rsp),%rbp
 	subq	%r14,%rbp
-	andq	$768,%rbp
+	andq	$0x300,%rbp
 	leaq	(%r14,%rbp,1),%r14
 	shrq	$3,%rbp
 	addq	%rbp,%r14
@@ -830,13 +830,13 @@
 	movl	%ecx,8(%r9)
 	movl	%edx,12(%r9)
 
-	movq	(%rsi),%r15
-	movq	8(%rsi),%r14
-	movq	16(%rsi),%r13
-	movq	24(%rsi),%r12
-	movq	32(%rsi),%rbp
-	movq	40(%rsi),%rbx
-	leaq	48(%rsi),%rsp
+	movq	-48(%rsi),%r15
+	movq	-40(%rsi),%r14
+	movq	-32(%rsi),%r13
+	movq	-24(%rsi),%r12
+	movq	-16(%rsi),%rbp
+	movq	-8(%rsi),%rbx
+	leaq	(%rsi),%rsp
 L$dec_epilogue:
 	.byte	0xf3,0xc3
 
@@ -1312,10 +1312,9 @@
 	movl	%r9d,%r9d
 
 	leaq	L$AES_Te(%rip),%r14
+	leaq	L$AES_Td(%rip),%r10
 	cmpq	$0,%r9
-	jne	L$cbc_picked_te
-	leaq	L$AES_Td(%rip),%r14
-L$cbc_picked_te:
+	cmoveq	%r10,%r14
 
 	movl	_OPENSSL_ia32cap_P(%rip),%r10d
 	cmpq	$512,%rdx
@@ -1333,9 +1332,9 @@
 	movq	%r14,%r10
 	leaq	2304(%r14),%r11
 	movq	%r15,%r12
-	andq	$4095,%r10
-	andq	$4095,%r11
-	andq	$4095,%r12
+	andq	$0xFFF,%r10
+	andq	$0xFFF,%r11
+	andq	$0xFFF,%r12
 
 	cmpq	%r11,%r12
 	jb	L$cbc_te_break_out
@@ -1344,7 +1343,7 @@
 	jmp	L$cbc_te_ok
 L$cbc_te_break_out:
 	subq	%r10,%r12
-	andq	$4095,%r12
+	andq	$0xFFF,%r12
 	addq	$320,%r12
 	subq	%r12,%r15
 .p2align	2
@@ -1370,7 +1369,7 @@
 
 	movq	%r15,%r10
 	subq	%r14,%r10
-	andq	$4095,%r10
+	andq	$0xfff,%r10
 	cmpq	$2304,%r10
 	jb	L$cbc_do_ecopy
 	cmpq	$4096-248,%r10
@@ -1557,7 +1556,7 @@
 	leaq	-88-63(%rcx),%r10
 	subq	%rbp,%r10
 	negq	%r10
-	andq	$960,%r10
+	andq	$0x3c0,%r10
 	subq	%r10,%rbp
 
 	xchgq	%rsp,%rbp
@@ -1586,7 +1585,7 @@
 	leaq	2048(%r14),%r14
 	leaq	768-8(%rsp),%rax
 	subq	%r14,%rax
-	andq	$768,%rax
+	andq	$0x300,%rax
 	leaq	(%r14,%rax,1),%r14
 
 	cmpq	$0,%rbx
diff --git a/mac-x86_64/crypto/aes/aesni-x86_64.S b/mac-x86_64/crypto/aes/aesni-x86_64.S
index 69b22c2..4e3b7d0 100644
--- a/mac-x86_64/crypto/aes/aesni-x86_64.S
+++ b/mac-x86_64/crypto/aes/aesni-x86_64.S
@@ -507,7 +507,7 @@
 	testl	%r8d,%r8d
 	jz	L$ecb_decrypt
 
-	cmpq	$128,%rdx
+	cmpq	$0x80,%rdx
 	jb	L$ecb_enc_tail
 
 	movdqu	(%rdi),%xmm2
@@ -519,7 +519,7 @@
 	movdqu	96(%rdi),%xmm8
 	movdqu	112(%rdi),%xmm9
 	leaq	128(%rdi),%rdi
-	subq	$128,%rdx
+	subq	$0x80,%rdx
 	jmp	L$ecb_enc_loop8_enter
 .p2align	4
 L$ecb_enc_loop8:
@@ -547,7 +547,7 @@
 
 	call	_aesni_encrypt8
 
-	subq	$128,%rdx
+	subq	$0x80,%rdx
 	jnc	L$ecb_enc_loop8
 
 	movups	%xmm2,(%rsi)
@@ -561,22 +561,22 @@
 	movups	%xmm8,96(%rsi)
 	movups	%xmm9,112(%rsi)
 	leaq	128(%rsi),%rsi
-	addq	$128,%rdx
+	addq	$0x80,%rdx
 	jz	L$ecb_ret
 
 L$ecb_enc_tail:
 	movups	(%rdi),%xmm2
-	cmpq	$32,%rdx
+	cmpq	$0x20,%rdx
 	jb	L$ecb_enc_one
 	movups	16(%rdi),%xmm3
 	je	L$ecb_enc_two
 	movups	32(%rdi),%xmm4
-	cmpq	$64,%rdx
+	cmpq	$0x40,%rdx
 	jb	L$ecb_enc_three
 	movups	48(%rdi),%xmm5
 	je	L$ecb_enc_four
 	movups	64(%rdi),%xmm6
-	cmpq	$96,%rdx
+	cmpq	$0x60,%rdx
 	jb	L$ecb_enc_five
 	movups	80(%rdi),%xmm7
 	je	L$ecb_enc_six
@@ -650,7 +650,7 @@
 
 .p2align	4
 L$ecb_decrypt:
-	cmpq	$128,%rdx
+	cmpq	$0x80,%rdx
 	jb	L$ecb_dec_tail
 
 	movdqu	(%rdi),%xmm2
@@ -662,7 +662,7 @@
 	movdqu	96(%rdi),%xmm8
 	movdqu	112(%rdi),%xmm9
 	leaq	128(%rdi),%rdi
-	subq	$128,%rdx
+	subq	$0x80,%rdx
 	jmp	L$ecb_dec_loop8_enter
 .p2align	4
 L$ecb_dec_loop8:
@@ -691,7 +691,7 @@
 	call	_aesni_decrypt8
 
 	movups	(%r11),%xmm0
-	subq	$128,%rdx
+	subq	$0x80,%rdx
 	jnc	L$ecb_dec_loop8
 
 	movups	%xmm2,(%rsi)
@@ -713,22 +713,22 @@
 	movups	%xmm9,112(%rsi)
 	pxor	%xmm9,%xmm9
 	leaq	128(%rsi),%rsi
-	addq	$128,%rdx
+	addq	$0x80,%rdx
 	jz	L$ecb_ret
 
 L$ecb_dec_tail:
 	movups	(%rdi),%xmm2
-	cmpq	$32,%rdx
+	cmpq	$0x20,%rdx
 	jb	L$ecb_dec_one
 	movups	16(%rdi),%xmm3
 	je	L$ecb_dec_two
 	movups	32(%rdi),%xmm4
-	cmpq	$64,%rdx
+	cmpq	$0x40,%rdx
 	jb	L$ecb_dec_three
 	movups	48(%rdi),%xmm5
 	je	L$ecb_dec_four
 	movups	64(%rdi),%xmm6
-	cmpq	$96,%rdx
+	cmpq	$0x60,%rdx
 	jb	L$ecb_dec_five
 	movups	80(%rdi),%xmm7
 	je	L$ecb_dec_six
@@ -1031,11 +1031,10 @@
 
 .p2align	4
 L$ctr32_bulk:
-	leaq	(%rsp),%rax
+	leaq	(%rsp),%r11
 	pushq	%rbp
 	subq	$128,%rsp
 	andq	$-16,%rsp
-	leaq	-8(%rax),%rbp
 
 
 
@@ -1044,7 +1043,7 @@
 	movdqu	(%rcx),%xmm0
 	movl	12(%r8),%r8d
 	pxor	%xmm0,%xmm2
-	movl	12(%rcx),%r11d
+	movl	12(%rcx),%ebp
 	movdqa	%xmm2,0(%rsp)
 	bswapl	%r8d
 	movdqa	%xmm2,%xmm3
@@ -1060,8 +1059,8 @@
 	leaq	2(%r8),%rdx
 	bswapl	%eax
 	bswapl	%edx
-	xorl	%r11d,%eax
-	xorl	%r11d,%edx
+	xorl	%ebp,%eax
+	xorl	%ebp,%edx
 .byte	102,15,58,34,216,3
 	leaq	3(%r8),%rax
 	movdqa	%xmm3,16(%rsp)
@@ -1070,25 +1069,25 @@
 	movq	%r10,%rdx
 	leaq	4(%r8),%r10
 	movdqa	%xmm4,32(%rsp)
-	xorl	%r11d,%eax
+	xorl	%ebp,%eax
 	bswapl	%r10d
 .byte	102,15,58,34,232,3
-	xorl	%r11d,%r10d
+	xorl	%ebp,%r10d
 	movdqa	%xmm5,48(%rsp)
 	leaq	5(%r8),%r9
 	movl	%r10d,64+12(%rsp)
 	bswapl	%r9d
 	leaq	6(%r8),%r10
 	movl	240(%rcx),%eax
-	xorl	%r11d,%r9d
+	xorl	%ebp,%r9d
 	bswapl	%r10d
 	movl	%r9d,80+12(%rsp)
-	xorl	%r11d,%r10d
+	xorl	%ebp,%r10d
 	leaq	7(%r8),%r9
 	movl	%r10d,96+12(%rsp)
 	bswapl	%r9d
 	movl	_OPENSSL_ia32cap_P+4(%rip),%r10d
-	xorl	%r11d,%r9d
+	xorl	%ebp,%r9d
 	andl	$71303168,%r10d
 	movl	%r9d,112+12(%rsp)
 
@@ -1112,7 +1111,7 @@
 L$ctr32_6x:
 	shll	$4,%eax
 	movl	$48,%r10d
-	bswapl	%r11d
+	bswapl	%ebp
 	leaq	32(%rcx,%rax,1),%rcx
 	subq	%rax,%r10
 	jmp	L$ctr32_loop6
@@ -1123,32 +1122,32 @@
 	movups	-48(%rcx,%r10,1),%xmm0
 .byte	102,15,56,220,209
 	movl	%r8d,%eax
-	xorl	%r11d,%eax
+	xorl	%ebp,%eax
 .byte	102,15,56,220,217
 .byte	0x0f,0x38,0xf1,0x44,0x24,12
 	leal	1(%r8),%eax
 .byte	102,15,56,220,225
-	xorl	%r11d,%eax
+	xorl	%ebp,%eax
 .byte	0x0f,0x38,0xf1,0x44,0x24,28
 .byte	102,15,56,220,233
 	leal	2(%r8),%eax
-	xorl	%r11d,%eax
+	xorl	%ebp,%eax
 .byte	102,15,56,220,241
 .byte	0x0f,0x38,0xf1,0x44,0x24,44
 	leal	3(%r8),%eax
 .byte	102,15,56,220,249
 	movups	-32(%rcx,%r10,1),%xmm1
-	xorl	%r11d,%eax
+	xorl	%ebp,%eax
 
 .byte	102,15,56,220,208
 .byte	0x0f,0x38,0xf1,0x44,0x24,60
 	leal	4(%r8),%eax
 .byte	102,15,56,220,216
-	xorl	%r11d,%eax
+	xorl	%ebp,%eax
 .byte	0x0f,0x38,0xf1,0x44,0x24,76
 .byte	102,15,56,220,224
 	leal	5(%r8),%eax
-	xorl	%r11d,%eax
+	xorl	%ebp,%eax
 .byte	102,15,56,220,232
 .byte	0x0f,0x38,0xf1,0x44,0x24,92
 	movq	%r10,%rax
@@ -1209,7 +1208,7 @@
 	bswapl	%r9d
 	movups	32-128(%rcx),%xmm0
 .byte	102,15,56,220,225
-	xorl	%r11d,%r9d
+	xorl	%ebp,%r9d
 	nop
 .byte	102,15,56,220,233
 	movl	%r9d,0+12(%rsp)
@@ -1222,7 +1221,7 @@
 	bswapl	%r9d
 .byte	102,15,56,220,208
 .byte	102,15,56,220,216
-	xorl	%r11d,%r9d
+	xorl	%ebp,%r9d
 .byte	0x66,0x90
 .byte	102,15,56,220,224
 .byte	102,15,56,220,232
@@ -1236,7 +1235,7 @@
 	bswapl	%r9d
 .byte	102,15,56,220,209
 .byte	102,15,56,220,217
-	xorl	%r11d,%r9d
+	xorl	%ebp,%r9d
 .byte	0x66,0x90
 .byte	102,15,56,220,225
 .byte	102,15,56,220,233
@@ -1250,7 +1249,7 @@
 	bswapl	%r9d
 .byte	102,15,56,220,208
 .byte	102,15,56,220,216
-	xorl	%r11d,%r9d
+	xorl	%ebp,%r9d
 .byte	0x66,0x90
 .byte	102,15,56,220,224
 .byte	102,15,56,220,232
@@ -1264,7 +1263,7 @@
 	bswapl	%r9d
 .byte	102,15,56,220,209
 .byte	102,15,56,220,217
-	xorl	%r11d,%r9d
+	xorl	%ebp,%r9d
 .byte	0x66,0x90
 .byte	102,15,56,220,225
 .byte	102,15,56,220,233
@@ -1278,7 +1277,7 @@
 	bswapl	%r9d
 .byte	102,15,56,220,208
 .byte	102,15,56,220,216
-	xorl	%r11d,%r9d
+	xorl	%ebp,%r9d
 .byte	0x66,0x90
 .byte	102,15,56,220,224
 .byte	102,15,56,220,232
@@ -1292,7 +1291,7 @@
 	bswapl	%r9d
 .byte	102,15,56,220,209
 .byte	102,15,56,220,217
-	xorl	%r11d,%r9d
+	xorl	%ebp,%r9d
 .byte	0x66,0x90
 .byte	102,15,56,220,225
 .byte	102,15,56,220,233
@@ -1307,7 +1306,7 @@
 .byte	102,15,56,220,208
 .byte	102,15,56,220,216
 .byte	102,15,56,220,224
-	xorl	%r11d,%r9d
+	xorl	%ebp,%r9d
 	movdqu	0(%rdi),%xmm10
 .byte	102,15,56,220,232
 	movl	%r9d,112+12(%rsp)
@@ -1542,7 +1541,7 @@
 
 L$ctr32_done:
 	xorps	%xmm0,%xmm0
-	xorl	%r11d,%r11d
+	xorl	%ebp,%ebp
 	pxor	%xmm1,%xmm1
 	pxor	%xmm2,%xmm2
 	pxor	%xmm3,%xmm3
@@ -1566,8 +1565,8 @@
 	pxor	%xmm14,%xmm14
 	movaps	%xmm0,112(%rsp)
 	pxor	%xmm15,%xmm15
-	leaq	(%rbp),%rsp
-	popq	%rbp
+	movq	-8(%r11),%rbp
+	leaq	(%r11),%rsp
 L$ctr32_epilogue:
 	.byte	0xf3,0xc3
 
@@ -1576,11 +1575,10 @@
 
 .p2align	4
 _aesni_xts_encrypt:
-	leaq	(%rsp),%rax
+	leaq	(%rsp),%r11
 	pushq	%rbp
 	subq	$112,%rsp
 	andq	$-16,%rsp
-	leaq	-8(%rax),%rbp
 	movups	(%r9),%xmm2
 	movl	240(%r8),%eax
 	movl	240(%rcx),%r10d
@@ -1596,7 +1594,7 @@
 	jnz	L$oop_enc1_8
 .byte	102,15,56,221,209
 	movups	(%rcx),%xmm0
-	movq	%rcx,%r11
+	movq	%rcx,%rbp
 	movl	%r10d,%eax
 	shll	$4,%r10d
 	movq	%rdx,%r9
@@ -1606,7 +1604,7 @@
 
 	movdqa	L$xts_magic(%rip),%xmm8
 	movdqa	%xmm2,%xmm15
-	pshufd	$95,%xmm2,%xmm9
+	pshufd	$0x5f,%xmm2,%xmm9
 	pxor	%xmm0,%xmm1
 	movdqa	%xmm9,%xmm14
 	paddd	%xmm9,%xmm9
@@ -1652,9 +1650,9 @@
 	jc	L$xts_enc_short
 
 	movl	$16+96,%eax
-	leaq	32(%r11,%r10,1),%rcx
+	leaq	32(%rbp,%r10,1),%rcx
 	subq	%r10,%rax
-	movups	16(%r11),%xmm1
+	movups	16(%rbp),%xmm1
 	movq	%rax,%r10
 	leaq	L$xts_magic(%rip),%r8
 	jmp	L$xts_enc_grandloop
@@ -1679,7 +1677,7 @@
 	movdqa	96(%rsp),%xmm9
 	pxor	%xmm14,%xmm6
 .byte	102,15,56,220,233
-	movups	32(%r11),%xmm0
+	movups	32(%rbp),%xmm0
 	leaq	96(%rdi),%rdi
 	pxor	%xmm8,%xmm7
 
@@ -1688,7 +1686,7 @@
 	pxor	%xmm9,%xmm11
 	movdqa	%xmm10,0(%rsp)
 .byte	102,15,56,220,249
-	movups	48(%r11),%xmm1
+	movups	48(%rbp),%xmm1
 	pxor	%xmm9,%xmm12
 
 .byte	102,15,56,220,208
@@ -1703,9 +1701,9 @@
 	movdqa	%xmm14,64(%rsp)
 .byte	102,15,56,220,240
 .byte	102,15,56,220,248
-	movups	64(%r11),%xmm0
+	movups	64(%rbp),%xmm0
 	movdqa	%xmm8,80(%rsp)
-	pshufd	$95,%xmm15,%xmm9
+	pshufd	$0x5f,%xmm15,%xmm9
 	jmp	L$xts_enc_loop6
 .p2align	5
 L$xts_enc_loop6:
@@ -1735,7 +1733,7 @@
 	psrad	$31,%xmm14
 .byte	102,15,56,220,217
 	pand	%xmm8,%xmm14
-	movups	(%r11),%xmm10
+	movups	(%rbp),%xmm10
 .byte	102,15,56,220,225
 .byte	102,15,56,220,233
 .byte	102,15,56,220,241
@@ -1803,10 +1801,10 @@
 .byte	102,15,56,220,225
 .byte	102,15,56,220,233
 	pxor	%xmm0,%xmm15
-	movups	(%r11),%xmm0
+	movups	(%rbp),%xmm0
 .byte	102,15,56,220,241
 .byte	102,15,56,220,249
-	movups	16(%r11),%xmm1
+	movups	16(%rbp),%xmm1
 
 	pxor	%xmm15,%xmm14
 .byte	102,15,56,221,84,36,0
@@ -1833,7 +1831,7 @@
 
 	movl	$16+96,%eax
 	subl	%r10d,%eax
-	movq	%r11,%rcx
+	movq	%rbp,%rcx
 	shrl	$4,%eax
 
 L$xts_enc_short:
@@ -1844,13 +1842,13 @@
 	jz	L$xts_enc_done
 
 	pxor	%xmm0,%xmm11
-	cmpq	$32,%rdx
+	cmpq	$0x20,%rdx
 	jb	L$xts_enc_one
 	pxor	%xmm0,%xmm12
 	je	L$xts_enc_two
 
 	pxor	%xmm0,%xmm13
-	cmpq	$64,%rdx
+	cmpq	$0x40,%rdx
 	jb	L$xts_enc_three
 	pxor	%xmm0,%xmm14
 	je	L$xts_enc_four
@@ -1989,7 +1987,7 @@
 	jnz	L$xts_enc_steal
 
 	subq	%r9,%rsi
-	movq	%r11,%rcx
+	movq	%rbp,%rcx
 	movl	%r10d,%eax
 
 	movups	-16(%rsi),%xmm2
@@ -2032,8 +2030,8 @@
 	movaps	%xmm0,96(%rsp)
 	pxor	%xmm14,%xmm14
 	pxor	%xmm15,%xmm15
-	leaq	(%rbp),%rsp
-	popq	%rbp
+	movq	-8(%r11),%rbp
+	leaq	(%r11),%rsp
 L$xts_enc_epilogue:
 	.byte	0xf3,0xc3
 
@@ -2042,11 +2040,10 @@
 
 .p2align	4
 _aesni_xts_decrypt:
-	leaq	(%rsp),%rax
+	leaq	(%rsp),%r11
 	pushq	%rbp
 	subq	$112,%rsp
 	andq	$-16,%rsp
-	leaq	-8(%rax),%rbp
 	movups	(%r9),%xmm2
 	movl	240(%r8),%eax
 	movl	240(%rcx),%r10d
@@ -2068,7 +2065,7 @@
 	subq	%rax,%rdx
 
 	movups	(%rcx),%xmm0
-	movq	%rcx,%r11
+	movq	%rcx,%rbp
 	movl	%r10d,%eax
 	shll	$4,%r10d
 	movq	%rdx,%r9
@@ -2078,7 +2075,7 @@
 
 	movdqa	L$xts_magic(%rip),%xmm8
 	movdqa	%xmm2,%xmm15
-	pshufd	$95,%xmm2,%xmm9
+	pshufd	$0x5f,%xmm2,%xmm9
 	pxor	%xmm0,%xmm1
 	movdqa	%xmm9,%xmm14
 	paddd	%xmm9,%xmm9
@@ -2124,9 +2121,9 @@
 	jc	L$xts_dec_short
 
 	movl	$16+96,%eax
-	leaq	32(%r11,%r10,1),%rcx
+	leaq	32(%rbp,%r10,1),%rcx
 	subq	%r10,%rax
-	movups	16(%r11),%xmm1
+	movups	16(%rbp),%xmm1
 	movq	%rax,%r10
 	leaq	L$xts_magic(%rip),%r8
 	jmp	L$xts_dec_grandloop
@@ -2151,7 +2148,7 @@
 	movdqa	96(%rsp),%xmm9
 	pxor	%xmm14,%xmm6
 .byte	102,15,56,222,233
-	movups	32(%r11),%xmm0
+	movups	32(%rbp),%xmm0
 	leaq	96(%rdi),%rdi
 	pxor	%xmm8,%xmm7
 
@@ -2160,7 +2157,7 @@
 	pxor	%xmm9,%xmm11
 	movdqa	%xmm10,0(%rsp)
 .byte	102,15,56,222,249
-	movups	48(%r11),%xmm1
+	movups	48(%rbp),%xmm1
 	pxor	%xmm9,%xmm12
 
 .byte	102,15,56,222,208
@@ -2175,9 +2172,9 @@
 	movdqa	%xmm14,64(%rsp)
 .byte	102,15,56,222,240
 .byte	102,15,56,222,248
-	movups	64(%r11),%xmm0
+	movups	64(%rbp),%xmm0
 	movdqa	%xmm8,80(%rsp)
-	pshufd	$95,%xmm15,%xmm9
+	pshufd	$0x5f,%xmm15,%xmm9
 	jmp	L$xts_dec_loop6
 .p2align	5
 L$xts_dec_loop6:
@@ -2207,7 +2204,7 @@
 	psrad	$31,%xmm14
 .byte	102,15,56,222,217
 	pand	%xmm8,%xmm14
-	movups	(%r11),%xmm10
+	movups	(%rbp),%xmm10
 .byte	102,15,56,222,225
 .byte	102,15,56,222,233
 .byte	102,15,56,222,241
@@ -2275,10 +2272,10 @@
 .byte	102,15,56,222,225
 .byte	102,15,56,222,233
 	pxor	%xmm0,%xmm15
-	movups	(%r11),%xmm0
+	movups	(%rbp),%xmm0
 .byte	102,15,56,222,241
 .byte	102,15,56,222,249
-	movups	16(%r11),%xmm1
+	movups	16(%rbp),%xmm1
 
 	pxor	%xmm15,%xmm14
 .byte	102,15,56,223,84,36,0
@@ -2305,7 +2302,7 @@
 
 	movl	$16+96,%eax
 	subl	%r10d,%eax
-	movq	%r11,%rcx
+	movq	%rbp,%rcx
 	shrl	$4,%eax
 
 L$xts_dec_short:
@@ -2317,13 +2314,13 @@
 	jz	L$xts_dec_done
 
 	pxor	%xmm0,%xmm12
-	cmpq	$32,%rdx
+	cmpq	$0x20,%rdx
 	jb	L$xts_dec_one
 	pxor	%xmm0,%xmm13
 	je	L$xts_dec_two
 
 	pxor	%xmm0,%xmm14
-	cmpq	$64,%rdx
+	cmpq	$0x40,%rdx
 	jb	L$xts_dec_three
 	je	L$xts_dec_four
 
@@ -2354,7 +2351,7 @@
 	pcmpgtd	%xmm15,%xmm14
 	movdqu	%xmm6,64(%rsi)
 	leaq	80(%rsi),%rsi
-	pshufd	$19,%xmm14,%xmm11
+	pshufd	$0x13,%xmm14,%xmm11
 	andq	$15,%r9
 	jz	L$xts_dec_ret
 
@@ -2462,7 +2459,7 @@
 	jz	L$xts_dec_ret
 L$xts_dec_done2:
 	movq	%r9,%rdx
-	movq	%r11,%rcx
+	movq	%rbp,%rcx
 	movl	%r10d,%eax
 
 	movups	(%rdi),%xmm2
@@ -2492,7 +2489,7 @@
 	jnz	L$xts_dec_steal
 
 	subq	%r9,%rsi
-	movq	%r11,%rcx
+	movq	%rbp,%rcx
 	movl	%r10d,%eax
 
 	movups	(%rsi),%xmm2
@@ -2535,11 +2532,827 @@
 	movaps	%xmm0,96(%rsp)
 	pxor	%xmm14,%xmm14
 	pxor	%xmm15,%xmm15
-	leaq	(%rbp),%rsp
-	popq	%rbp
+	movq	-8(%r11),%rbp
+	leaq	(%r11),%rsp
 L$xts_dec_epilogue:
 	.byte	0xf3,0xc3
 
+.globl	_aesni_ocb_encrypt
+.private_extern _aesni_ocb_encrypt
+
+.p2align	5
+_aesni_ocb_encrypt:
+	leaq	(%rsp),%rax
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	movq	8(%rax),%rbx
+	movq	8+8(%rax),%rbp
+
+	movl	240(%rcx),%r10d
+	movq	%rcx,%r11
+	shll	$4,%r10d
+	movups	(%rcx),%xmm9
+	movups	16(%rcx,%r10,1),%xmm1
+
+	movdqu	(%r9),%xmm15
+	pxor	%xmm1,%xmm9
+	pxor	%xmm1,%xmm15
+
+	movl	$16+32,%eax
+	leaq	32(%r11,%r10,1),%rcx
+	movups	16(%r11),%xmm1
+	subq	%r10,%rax
+	movq	%rax,%r10
+
+	movdqu	(%rbx),%xmm10
+	movdqu	(%rbp),%xmm8
+
+	testq	$1,%r8
+	jnz	L$ocb_enc_odd
+
+	bsfq	%r8,%r12
+	addq	$1,%r8
+	shlq	$4,%r12
+	movdqu	(%rbx,%r12,1),%xmm7
+	movdqu	(%rdi),%xmm2
+	leaq	16(%rdi),%rdi
+
+	call	__ocb_encrypt1
+
+	movdqa	%xmm7,%xmm15
+	movups	%xmm2,(%rsi)
+	leaq	16(%rsi),%rsi
+	subq	$1,%rdx
+	jz	L$ocb_enc_done
+
+L$ocb_enc_odd:
+	leaq	1(%r8),%r12
+	leaq	3(%r8),%r13
+	leaq	5(%r8),%r14
+	leaq	6(%r8),%r8
+	bsfq	%r12,%r12
+	bsfq	%r13,%r13
+	bsfq	%r14,%r14
+	shlq	$4,%r12
+	shlq	$4,%r13
+	shlq	$4,%r14
+
+	subq	$6,%rdx
+	jc	L$ocb_enc_short
+	jmp	L$ocb_enc_grandloop
+
+.p2align	5
+L$ocb_enc_grandloop:
+	movdqu	0(%rdi),%xmm2
+	movdqu	16(%rdi),%xmm3
+	movdqu	32(%rdi),%xmm4
+	movdqu	48(%rdi),%xmm5
+	movdqu	64(%rdi),%xmm6
+	movdqu	80(%rdi),%xmm7
+	leaq	96(%rdi),%rdi
+
+	call	__ocb_encrypt6
+
+	movups	%xmm2,0(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+	movups	%xmm7,80(%rsi)
+	leaq	96(%rsi),%rsi
+	subq	$6,%rdx
+	jnc	L$ocb_enc_grandloop
+
+L$ocb_enc_short:
+	addq	$6,%rdx
+	jz	L$ocb_enc_done
+
+	movdqu	0(%rdi),%xmm2
+	cmpq	$2,%rdx
+	jb	L$ocb_enc_one
+	movdqu	16(%rdi),%xmm3
+	je	L$ocb_enc_two
+
+	movdqu	32(%rdi),%xmm4
+	cmpq	$4,%rdx
+	jb	L$ocb_enc_three
+	movdqu	48(%rdi),%xmm5
+	je	L$ocb_enc_four
+
+	movdqu	64(%rdi),%xmm6
+	pxor	%xmm7,%xmm7
+
+	call	__ocb_encrypt6
+
+	movdqa	%xmm14,%xmm15
+	movups	%xmm2,0(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+	movups	%xmm6,64(%rsi)
+
+	jmp	L$ocb_enc_done
+
+.p2align	4
+L$ocb_enc_one:
+	movdqa	%xmm10,%xmm7
+
+	call	__ocb_encrypt1
+
+	movdqa	%xmm7,%xmm15
+	movups	%xmm2,0(%rsi)
+	jmp	L$ocb_enc_done
+
+.p2align	4
+L$ocb_enc_two:
+	pxor	%xmm4,%xmm4
+	pxor	%xmm5,%xmm5
+
+	call	__ocb_encrypt4
+
+	movdqa	%xmm11,%xmm15
+	movups	%xmm2,0(%rsi)
+	movups	%xmm3,16(%rsi)
+
+	jmp	L$ocb_enc_done
+
+.p2align	4
+L$ocb_enc_three:
+	pxor	%xmm5,%xmm5
+
+	call	__ocb_encrypt4
+
+	movdqa	%xmm12,%xmm15
+	movups	%xmm2,0(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+
+	jmp	L$ocb_enc_done
+
+.p2align	4
+L$ocb_enc_four:
+	call	__ocb_encrypt4
+
+	movdqa	%xmm13,%xmm15
+	movups	%xmm2,0(%rsi)
+	movups	%xmm3,16(%rsi)
+	movups	%xmm4,32(%rsi)
+	movups	%xmm5,48(%rsi)
+
+L$ocb_enc_done:
+	pxor	%xmm0,%xmm15
+	movdqu	%xmm8,(%rbp)
+	movdqu	%xmm15,(%r9)
+
+	xorps	%xmm0,%xmm0
+	pxor	%xmm1,%xmm1
+	pxor	%xmm2,%xmm2
+	pxor	%xmm3,%xmm3
+	pxor	%xmm4,%xmm4
+	pxor	%xmm5,%xmm5
+	pxor	%xmm6,%xmm6
+	pxor	%xmm7,%xmm7
+	pxor	%xmm8,%xmm8
+	pxor	%xmm9,%xmm9
+	pxor	%xmm10,%xmm10
+	pxor	%xmm11,%xmm11
+	pxor	%xmm12,%xmm12
+	pxor	%xmm13,%xmm13
+	pxor	%xmm14,%xmm14
+	pxor	%xmm15,%xmm15
+	leaq	40(%rsp),%rax
+	movq	-40(%rax),%r14
+	movq	-32(%rax),%r13
+	movq	-24(%rax),%r12
+	movq	-16(%rax),%rbp
+	movq	-8(%rax),%rbx
+	leaq	(%rax),%rsp
+L$ocb_enc_epilogue:
+	.byte	0xf3,0xc3
+
+
+
+.p2align	5
+__ocb_encrypt6:
+	pxor	%xmm9,%xmm15
+	movdqu	(%rbx,%r12,1),%xmm11
+	movdqa	%xmm10,%xmm12
+	movdqu	(%rbx,%r13,1),%xmm13
+	movdqa	%xmm10,%xmm14
+	pxor	%xmm15,%xmm10
+	movdqu	(%rbx,%r14,1),%xmm15
+	pxor	%xmm10,%xmm11
+	pxor	%xmm2,%xmm8
+	pxor	%xmm10,%xmm2
+	pxor	%xmm11,%xmm12
+	pxor	%xmm3,%xmm8
+	pxor	%xmm11,%xmm3
+	pxor	%xmm12,%xmm13
+	pxor	%xmm4,%xmm8
+	pxor	%xmm12,%xmm4
+	pxor	%xmm13,%xmm14
+	pxor	%xmm5,%xmm8
+	pxor	%xmm13,%xmm5
+	pxor	%xmm14,%xmm15
+	pxor	%xmm6,%xmm8
+	pxor	%xmm14,%xmm6
+	pxor	%xmm7,%xmm8
+	pxor	%xmm15,%xmm7
+	movups	32(%r11),%xmm0
+
+	leaq	1(%r8),%r12
+	leaq	3(%r8),%r13
+	leaq	5(%r8),%r14
+	addq	$6,%r8
+	pxor	%xmm9,%xmm10
+	bsfq	%r12,%r12
+	bsfq	%r13,%r13
+	bsfq	%r14,%r14
+
+.byte	102,15,56,220,209
+.byte	102,15,56,220,217
+.byte	102,15,56,220,225
+.byte	102,15,56,220,233
+	pxor	%xmm9,%xmm11
+	pxor	%xmm9,%xmm12
+.byte	102,15,56,220,241
+	pxor	%xmm9,%xmm13
+	pxor	%xmm9,%xmm14
+.byte	102,15,56,220,249
+	movups	48(%r11),%xmm1
+	pxor	%xmm9,%xmm15
+
+.byte	102,15,56,220,208
+.byte	102,15,56,220,216
+.byte	102,15,56,220,224
+.byte	102,15,56,220,232
+.byte	102,15,56,220,240
+.byte	102,15,56,220,248
+	movups	64(%r11),%xmm0
+	shlq	$4,%r12
+	shlq	$4,%r13
+	jmp	L$ocb_enc_loop6
+
+.p2align	5
+L$ocb_enc_loop6:
+.byte	102,15,56,220,209
+.byte	102,15,56,220,217
+.byte	102,15,56,220,225
+.byte	102,15,56,220,233
+.byte	102,15,56,220,241
+.byte	102,15,56,220,249
+	movups	(%rcx,%rax,1),%xmm1
+	addq	$32,%rax
+
+.byte	102,15,56,220,208
+.byte	102,15,56,220,216
+.byte	102,15,56,220,224
+.byte	102,15,56,220,232
+.byte	102,15,56,220,240
+.byte	102,15,56,220,248
+	movups	-16(%rcx,%rax,1),%xmm0
+	jnz	L$ocb_enc_loop6
+
+.byte	102,15,56,220,209
+.byte	102,15,56,220,217
+.byte	102,15,56,220,225
+.byte	102,15,56,220,233
+.byte	102,15,56,220,241
+.byte	102,15,56,220,249
+	movups	16(%r11),%xmm1
+	shlq	$4,%r14
+
+.byte	102,65,15,56,221,210
+	movdqu	(%rbx),%xmm10
+	movq	%r10,%rax
+.byte	102,65,15,56,221,219
+.byte	102,65,15,56,221,228
+.byte	102,65,15,56,221,237
+.byte	102,65,15,56,221,246
+.byte	102,65,15,56,221,255
+	.byte	0xf3,0xc3
+
+
+
+.p2align	5
+__ocb_encrypt4:
+	pxor	%xmm9,%xmm15
+	movdqu	(%rbx,%r12,1),%xmm11
+	movdqa	%xmm10,%xmm12
+	movdqu	(%rbx,%r13,1),%xmm13
+	pxor	%xmm15,%xmm10
+	pxor	%xmm10,%xmm11
+	pxor	%xmm2,%xmm8
+	pxor	%xmm10,%xmm2
+	pxor	%xmm11,%xmm12
+	pxor	%xmm3,%xmm8
+	pxor	%xmm11,%xmm3
+	pxor	%xmm12,%xmm13
+	pxor	%xmm4,%xmm8
+	pxor	%xmm12,%xmm4
+	pxor	%xmm5,%xmm8
+	pxor	%xmm13,%xmm5
+	movups	32(%r11),%xmm0
+
+	pxor	%xmm9,%xmm10
+	pxor	%xmm9,%xmm11
+	pxor	%xmm9,%xmm12
+	pxor	%xmm9,%xmm13
+
+.byte	102,15,56,220,209
+.byte	102,15,56,220,217
+.byte	102,15,56,220,225
+.byte	102,15,56,220,233
+	movups	48(%r11),%xmm1
+
+.byte	102,15,56,220,208
+.byte	102,15,56,220,216
+.byte	102,15,56,220,224
+.byte	102,15,56,220,232
+	movups	64(%r11),%xmm0
+	jmp	L$ocb_enc_loop4
+
+.p2align	5
+L$ocb_enc_loop4:
+.byte	102,15,56,220,209
+.byte	102,15,56,220,217
+.byte	102,15,56,220,225
+.byte	102,15,56,220,233
+	movups	(%rcx,%rax,1),%xmm1
+	addq	$32,%rax
+
+.byte	102,15,56,220,208
+.byte	102,15,56,220,216
+.byte	102,15,56,220,224
+.byte	102,15,56,220,232
+	movups	-16(%rcx,%rax,1),%xmm0
+	jnz	L$ocb_enc_loop4
+
+.byte	102,15,56,220,209
+.byte	102,15,56,220,217
+.byte	102,15,56,220,225
+.byte	102,15,56,220,233
+	movups	16(%r11),%xmm1
+	movq	%r10,%rax
+
+.byte	102,65,15,56,221,210
+.byte	102,65,15,56,221,219
+.byte	102,65,15,56,221,228
+.byte	102,65,15,56,221,237
+	.byte	0xf3,0xc3
+
+
+
+.p2align	5
+__ocb_encrypt1:
+	pxor	%xmm15,%xmm7
+	pxor	%xmm9,%xmm7
+	pxor	%xmm2,%xmm8
+	pxor	%xmm7,%xmm2
+	movups	32(%r11),%xmm0
+
+.byte	102,15,56,220,209
+	movups	48(%r11),%xmm1
+	pxor	%xmm9,%xmm7
+
+.byte	102,15,56,220,208
+	movups	64(%r11),%xmm0
+	jmp	L$ocb_enc_loop1
+
+.p2align	5
+L$ocb_enc_loop1:
+.byte	102,15,56,220,209
+	movups	(%rcx,%rax,1),%xmm1
+	addq	$32,%rax
+
+.byte	102,15,56,220,208
+	movups	-16(%rcx,%rax,1),%xmm0
+	jnz	L$ocb_enc_loop1
+
+.byte	102,15,56,220,209
+	movups	16(%r11),%xmm1
+	movq	%r10,%rax
+
+.byte	102,15,56,221,215
+	.byte	0xf3,0xc3
+
+
+.globl	_aesni_ocb_decrypt
+.private_extern _aesni_ocb_decrypt
+
+.p2align	5
+_aesni_ocb_decrypt:
+	leaq	(%rsp),%rax
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	movq	8(%rax),%rbx
+	movq	8+8(%rax),%rbp
+
+	movl	240(%rcx),%r10d
+	movq	%rcx,%r11
+	shll	$4,%r10d
+	movups	(%rcx),%xmm9
+	movups	16(%rcx,%r10,1),%xmm1
+
+	movdqu	(%r9),%xmm15
+	pxor	%xmm1,%xmm9
+	pxor	%xmm1,%xmm15
+
+	movl	$16+32,%eax
+	leaq	32(%r11,%r10,1),%rcx
+	movups	16(%r11),%xmm1
+	subq	%r10,%rax
+	movq	%rax,%r10
+
+	movdqu	(%rbx),%xmm10
+	movdqu	(%rbp),%xmm8
+
+	testq	$1,%r8
+	jnz	L$ocb_dec_odd
+
+	bsfq	%r8,%r12
+	addq	$1,%r8
+	shlq	$4,%r12
+	movdqu	(%rbx,%r12,1),%xmm7
+	movdqu	(%rdi),%xmm2
+	leaq	16(%rdi),%rdi
+
+	call	__ocb_decrypt1
+
+	movdqa	%xmm7,%xmm15
+	movups	%xmm2,(%rsi)
+	xorps	%xmm2,%xmm8
+	leaq	16(%rsi),%rsi
+	subq	$1,%rdx
+	jz	L$ocb_dec_done
+
+L$ocb_dec_odd:
+	leaq	1(%r8),%r12
+	leaq	3(%r8),%r13
+	leaq	5(%r8),%r14
+	leaq	6(%r8),%r8
+	bsfq	%r12,%r12
+	bsfq	%r13,%r13
+	bsfq	%r14,%r14
+	shlq	$4,%r12
+	shlq	$4,%r13
+	shlq	$4,%r14
+
+	subq	$6,%rdx
+	jc	L$ocb_dec_short
+	jmp	L$ocb_dec_grandloop
+
+.p2align	5
+L$ocb_dec_grandloop:
+	movdqu	0(%rdi),%xmm2
+	movdqu	16(%rdi),%xmm3
+	movdqu	32(%rdi),%xmm4
+	movdqu	48(%rdi),%xmm5
+	movdqu	64(%rdi),%xmm6
+	movdqu	80(%rdi),%xmm7
+	leaq	96(%rdi),%rdi
+
+	call	__ocb_decrypt6
+
+	movups	%xmm2,0(%rsi)
+	pxor	%xmm2,%xmm8
+	movups	%xmm3,16(%rsi)
+	pxor	%xmm3,%xmm8
+	movups	%xmm4,32(%rsi)
+	pxor	%xmm4,%xmm8
+	movups	%xmm5,48(%rsi)
+	pxor	%xmm5,%xmm8
+	movups	%xmm6,64(%rsi)
+	pxor	%xmm6,%xmm8
+	movups	%xmm7,80(%rsi)
+	pxor	%xmm7,%xmm8
+	leaq	96(%rsi),%rsi
+	subq	$6,%rdx
+	jnc	L$ocb_dec_grandloop
+
+L$ocb_dec_short:
+	addq	$6,%rdx
+	jz	L$ocb_dec_done
+
+	movdqu	0(%rdi),%xmm2
+	cmpq	$2,%rdx
+	jb	L$ocb_dec_one
+	movdqu	16(%rdi),%xmm3
+	je	L$ocb_dec_two
+
+	movdqu	32(%rdi),%xmm4
+	cmpq	$4,%rdx
+	jb	L$ocb_dec_three
+	movdqu	48(%rdi),%xmm5
+	je	L$ocb_dec_four
+
+	movdqu	64(%rdi),%xmm6
+	pxor	%xmm7,%xmm7
+
+	call	__ocb_decrypt6
+
+	movdqa	%xmm14,%xmm15
+	movups	%xmm2,0(%rsi)
+	pxor	%xmm2,%xmm8
+	movups	%xmm3,16(%rsi)
+	pxor	%xmm3,%xmm8
+	movups	%xmm4,32(%rsi)
+	pxor	%xmm4,%xmm8
+	movups	%xmm5,48(%rsi)
+	pxor	%xmm5,%xmm8
+	movups	%xmm6,64(%rsi)
+	pxor	%xmm6,%xmm8
+
+	jmp	L$ocb_dec_done
+
+.p2align	4
+L$ocb_dec_one:
+	movdqa	%xmm10,%xmm7
+
+	call	__ocb_decrypt1
+
+	movdqa	%xmm7,%xmm15
+	movups	%xmm2,0(%rsi)
+	xorps	%xmm2,%xmm8
+	jmp	L$ocb_dec_done
+
+.p2align	4
+L$ocb_dec_two:
+	pxor	%xmm4,%xmm4
+	pxor	%xmm5,%xmm5
+
+	call	__ocb_decrypt4
+
+	movdqa	%xmm11,%xmm15
+	movups	%xmm2,0(%rsi)
+	xorps	%xmm2,%xmm8
+	movups	%xmm3,16(%rsi)
+	xorps	%xmm3,%xmm8
+
+	jmp	L$ocb_dec_done
+
+.p2align	4
+L$ocb_dec_three:
+	pxor	%xmm5,%xmm5
+
+	call	__ocb_decrypt4
+
+	movdqa	%xmm12,%xmm15
+	movups	%xmm2,0(%rsi)
+	xorps	%xmm2,%xmm8
+	movups	%xmm3,16(%rsi)
+	xorps	%xmm3,%xmm8
+	movups	%xmm4,32(%rsi)
+	xorps	%xmm4,%xmm8
+
+	jmp	L$ocb_dec_done
+
+.p2align	4
+L$ocb_dec_four:
+	call	__ocb_decrypt4
+
+	movdqa	%xmm13,%xmm15
+	movups	%xmm2,0(%rsi)
+	pxor	%xmm2,%xmm8
+	movups	%xmm3,16(%rsi)
+	pxor	%xmm3,%xmm8
+	movups	%xmm4,32(%rsi)
+	pxor	%xmm4,%xmm8
+	movups	%xmm5,48(%rsi)
+	pxor	%xmm5,%xmm8
+
+L$ocb_dec_done:
+	pxor	%xmm0,%xmm15
+	movdqu	%xmm8,(%rbp)
+	movdqu	%xmm15,(%r9)
+
+	xorps	%xmm0,%xmm0
+	pxor	%xmm1,%xmm1
+	pxor	%xmm2,%xmm2
+	pxor	%xmm3,%xmm3
+	pxor	%xmm4,%xmm4
+	pxor	%xmm5,%xmm5
+	pxor	%xmm6,%xmm6
+	pxor	%xmm7,%xmm7
+	pxor	%xmm8,%xmm8
+	pxor	%xmm9,%xmm9
+	pxor	%xmm10,%xmm10
+	pxor	%xmm11,%xmm11
+	pxor	%xmm12,%xmm12
+	pxor	%xmm13,%xmm13
+	pxor	%xmm14,%xmm14
+	pxor	%xmm15,%xmm15
+	leaq	40(%rsp),%rax
+	movq	-40(%rax),%r14
+	movq	-32(%rax),%r13
+	movq	-24(%rax),%r12
+	movq	-16(%rax),%rbp
+	movq	-8(%rax),%rbx
+	leaq	(%rax),%rsp
+L$ocb_dec_epilogue:
+	.byte	0xf3,0xc3
+
+
+
+.p2align	5
+__ocb_decrypt6:
+	pxor	%xmm9,%xmm15
+	movdqu	(%rbx,%r12,1),%xmm11
+	movdqa	%xmm10,%xmm12
+	movdqu	(%rbx,%r13,1),%xmm13
+	movdqa	%xmm10,%xmm14
+	pxor	%xmm15,%xmm10
+	movdqu	(%rbx,%r14,1),%xmm15
+	pxor	%xmm10,%xmm11
+	pxor	%xmm10,%xmm2
+	pxor	%xmm11,%xmm12
+	pxor	%xmm11,%xmm3
+	pxor	%xmm12,%xmm13
+	pxor	%xmm12,%xmm4
+	pxor	%xmm13,%xmm14
+	pxor	%xmm13,%xmm5
+	pxor	%xmm14,%xmm15
+	pxor	%xmm14,%xmm6
+	pxor	%xmm15,%xmm7
+	movups	32(%r11),%xmm0
+
+	leaq	1(%r8),%r12
+	leaq	3(%r8),%r13
+	leaq	5(%r8),%r14
+	addq	$6,%r8
+	pxor	%xmm9,%xmm10
+	bsfq	%r12,%r12
+	bsfq	%r13,%r13
+	bsfq	%r14,%r14
+
+.byte	102,15,56,222,209
+.byte	102,15,56,222,217
+.byte	102,15,56,222,225
+.byte	102,15,56,222,233
+	pxor	%xmm9,%xmm11
+	pxor	%xmm9,%xmm12
+.byte	102,15,56,222,241
+	pxor	%xmm9,%xmm13
+	pxor	%xmm9,%xmm14
+.byte	102,15,56,222,249
+	movups	48(%r11),%xmm1
+	pxor	%xmm9,%xmm15
+
+.byte	102,15,56,222,208
+.byte	102,15,56,222,216
+.byte	102,15,56,222,224
+.byte	102,15,56,222,232
+.byte	102,15,56,222,240
+.byte	102,15,56,222,248
+	movups	64(%r11),%xmm0
+	shlq	$4,%r12
+	shlq	$4,%r13
+	jmp	L$ocb_dec_loop6
+
+.p2align	5
+L$ocb_dec_loop6:
+.byte	102,15,56,222,209
+.byte	102,15,56,222,217
+.byte	102,15,56,222,225
+.byte	102,15,56,222,233
+.byte	102,15,56,222,241
+.byte	102,15,56,222,249
+	movups	(%rcx,%rax,1),%xmm1
+	addq	$32,%rax
+
+.byte	102,15,56,222,208
+.byte	102,15,56,222,216
+.byte	102,15,56,222,224
+.byte	102,15,56,222,232
+.byte	102,15,56,222,240
+.byte	102,15,56,222,248
+	movups	-16(%rcx,%rax,1),%xmm0
+	jnz	L$ocb_dec_loop6
+
+.byte	102,15,56,222,209
+.byte	102,15,56,222,217
+.byte	102,15,56,222,225
+.byte	102,15,56,222,233
+.byte	102,15,56,222,241
+.byte	102,15,56,222,249
+	movups	16(%r11),%xmm1
+	shlq	$4,%r14
+
+.byte	102,65,15,56,223,210
+	movdqu	(%rbx),%xmm10
+	movq	%r10,%rax
+.byte	102,65,15,56,223,219
+.byte	102,65,15,56,223,228
+.byte	102,65,15,56,223,237
+.byte	102,65,15,56,223,246
+.byte	102,65,15,56,223,255
+	.byte	0xf3,0xc3
+
+
+
+.p2align	5
+__ocb_decrypt4:
+	pxor	%xmm9,%xmm15
+	movdqu	(%rbx,%r12,1),%xmm11
+	movdqa	%xmm10,%xmm12
+	movdqu	(%rbx,%r13,1),%xmm13
+	pxor	%xmm15,%xmm10
+	pxor	%xmm10,%xmm11
+	pxor	%xmm10,%xmm2
+	pxor	%xmm11,%xmm12
+	pxor	%xmm11,%xmm3
+	pxor	%xmm12,%xmm13
+	pxor	%xmm12,%xmm4
+	pxor	%xmm13,%xmm5
+	movups	32(%r11),%xmm0
+
+	pxor	%xmm9,%xmm10
+	pxor	%xmm9,%xmm11
+	pxor	%xmm9,%xmm12
+	pxor	%xmm9,%xmm13
+
+.byte	102,15,56,222,209
+.byte	102,15,56,222,217
+.byte	102,15,56,222,225
+.byte	102,15,56,222,233
+	movups	48(%r11),%xmm1
+
+.byte	102,15,56,222,208
+.byte	102,15,56,222,216
+.byte	102,15,56,222,224
+.byte	102,15,56,222,232
+	movups	64(%r11),%xmm0
+	jmp	L$ocb_dec_loop4
+
+.p2align	5
+L$ocb_dec_loop4:
+.byte	102,15,56,222,209
+.byte	102,15,56,222,217
+.byte	102,15,56,222,225
+.byte	102,15,56,222,233
+	movups	(%rcx,%rax,1),%xmm1
+	addq	$32,%rax
+
+.byte	102,15,56,222,208
+.byte	102,15,56,222,216
+.byte	102,15,56,222,224
+.byte	102,15,56,222,232
+	movups	-16(%rcx,%rax,1),%xmm0
+	jnz	L$ocb_dec_loop4
+
+.byte	102,15,56,222,209
+.byte	102,15,56,222,217
+.byte	102,15,56,222,225
+.byte	102,15,56,222,233
+	movups	16(%r11),%xmm1
+	movq	%r10,%rax
+
+.byte	102,65,15,56,223,210
+.byte	102,65,15,56,223,219
+.byte	102,65,15,56,223,228
+.byte	102,65,15,56,223,237
+	.byte	0xf3,0xc3
+
+
+
+.p2align	5
+__ocb_decrypt1:
+	pxor	%xmm15,%xmm7
+	pxor	%xmm9,%xmm7
+	pxor	%xmm7,%xmm2
+	movups	32(%r11),%xmm0
+
+.byte	102,15,56,222,209
+	movups	48(%r11),%xmm1
+	pxor	%xmm9,%xmm7
+
+.byte	102,15,56,222,208
+	movups	64(%r11),%xmm0
+	jmp	L$ocb_dec_loop1
+
+.p2align	5
+L$ocb_dec_loop1:
+.byte	102,15,56,222,209
+	movups	(%rcx,%rax,1),%xmm1
+	addq	$32,%rax
+
+.byte	102,15,56,222,208
+	movups	-16(%rcx,%rax,1),%xmm0
+	jnz	L$ocb_dec_loop1
+
+.byte	102,15,56,222,209
+	movups	16(%r11),%xmm1
+	movq	%r10,%rax
+
+.byte	102,15,56,223,215
+	.byte	0xf3,0xc3
+
 .globl	_aesni_cbc_encrypt
 .private_extern _aesni_cbc_encrypt
 
@@ -2637,14 +3450,14 @@
 	jmp	L$cbc_ret
 .p2align	4
 L$cbc_decrypt_bulk:
-	leaq	(%rsp),%rax
+	leaq	(%rsp),%r11
 	pushq	%rbp
 	subq	$16,%rsp
 	andq	$-16,%rsp
-	leaq	-8(%rax),%rbp
+	movq	%rcx,%rbp
 	movups	(%r8),%xmm10
 	movl	%r10d,%eax
-	cmpq	$80,%rdx
+	cmpq	$0x50,%rdx
 	jbe	L$cbc_dec_tail
 
 	movups	(%rcx),%xmm0
@@ -2660,14 +3473,14 @@
 	movdqu	80(%rdi),%xmm7
 	movdqa	%xmm6,%xmm15
 	movl	_OPENSSL_ia32cap_P+4(%rip),%r9d
-	cmpq	$112,%rdx
+	cmpq	$0x70,%rdx
 	jbe	L$cbc_dec_six_or_seven
 
 	andl	$71303168,%r9d
-	subq	$80,%rdx
+	subq	$0x50,%rdx
 	cmpl	$4194304,%r9d
 	je	L$cbc_dec_loop6_enter
-	subq	$32,%rdx
+	subq	$0x20,%rdx
 	leaq	112(%rcx),%rcx
 	jmp	L$cbc_dec_loop8_enter
 .p2align	4
@@ -2681,8 +3494,8 @@
 	pxor	%xmm0,%xmm3
 	movups	16-112(%rcx),%xmm1
 	pxor	%xmm0,%xmm4
-	xorq	%r11,%r11
-	cmpq	$112,%rdx
+	movq	$-1,%rbp
+	cmpq	$0x70,%rdx
 	pxor	%xmm0,%xmm5
 	pxor	%xmm0,%xmm6
 	pxor	%xmm0,%xmm7
@@ -2697,10 +3510,10 @@
 .byte	102,15,56,222,241
 .byte	102,15,56,222,249
 .byte	102,68,15,56,222,193
-	setnc	%r11b
-	shlq	$7,%r11
+	adcq	$0,%rbp
+	andq	$128,%rbp
 .byte	102,68,15,56,222,201
-	addq	%rdi,%r11
+	addq	%rdi,%rbp
 	movups	48-112(%rcx),%xmm1
 .byte	102,15,56,222,208
 .byte	102,15,56,222,216
@@ -2838,18 +3651,18 @@
 	movdqu	112(%rdi),%xmm0
 .byte	102,65,15,56,223,228
 	leaq	128(%rdi),%rdi
-	movdqu	0(%r11),%xmm11
+	movdqu	0(%rbp),%xmm11
 .byte	102,65,15,56,223,237
 .byte	102,65,15,56,223,246
-	movdqu	16(%r11),%xmm12
-	movdqu	32(%r11),%xmm13
+	movdqu	16(%rbp),%xmm12
+	movdqu	32(%rbp),%xmm13
 .byte	102,65,15,56,223,255
 .byte	102,68,15,56,223,193
-	movdqu	48(%r11),%xmm14
-	movdqu	64(%r11),%xmm15
+	movdqu	48(%rbp),%xmm14
+	movdqu	64(%rbp),%xmm15
 .byte	102,69,15,56,223,202
 	movdqa	%xmm0,%xmm10
-	movdqu	80(%r11),%xmm1
+	movdqu	80(%rbp),%xmm1
 	movups	-112(%rcx),%xmm0
 
 	movups	%xmm2,(%rsi)
@@ -2867,21 +3680,21 @@
 	movups	%xmm8,96(%rsi)
 	leaq	112(%rsi),%rsi
 
-	subq	$128,%rdx
+	subq	$0x80,%rdx
 	ja	L$cbc_dec_loop8
 
 	movaps	%xmm9,%xmm2
 	leaq	-112(%rcx),%rcx
-	addq	$112,%rdx
+	addq	$0x70,%rdx
 	jle	L$cbc_dec_clear_tail_collected
 	movups	%xmm9,(%rsi)
 	leaq	16(%rsi),%rsi
-	cmpq	$80,%rdx
+	cmpq	$0x50,%rdx
 	jbe	L$cbc_dec_tail
 
 	movaps	%xmm11,%xmm2
 L$cbc_dec_six_or_seven:
-	cmpq	$96,%rdx
+	cmpq	$0x60,%rdx
 	ja	L$cbc_dec_seven
 
 	movaps	%xmm7,%xmm8
@@ -2968,39 +3781,39 @@
 	pxor	%xmm13,%xmm5
 	movdqu	%xmm4,32(%rsi)
 	pxor	%xmm14,%xmm6
-	movq	%r11,%rcx
+	movq	%rbp,%rcx
 	movdqu	%xmm5,48(%rsi)
 	pxor	%xmm15,%xmm7
 	movl	%r10d,%eax
 	movdqu	%xmm6,64(%rsi)
 	leaq	80(%rsi),%rsi
-	subq	$96,%rdx
+	subq	$0x60,%rdx
 	ja	L$cbc_dec_loop6
 
 	movdqa	%xmm7,%xmm2
-	addq	$80,%rdx
+	addq	$0x50,%rdx
 	jle	L$cbc_dec_clear_tail_collected
 	movups	%xmm7,(%rsi)
 	leaq	16(%rsi),%rsi
 
 L$cbc_dec_tail:
 	movups	(%rdi),%xmm2
-	subq	$16,%rdx
+	subq	$0x10,%rdx
 	jbe	L$cbc_dec_one
 
 	movups	16(%rdi),%xmm3
 	movaps	%xmm2,%xmm11
-	subq	$16,%rdx
+	subq	$0x10,%rdx
 	jbe	L$cbc_dec_two
 
 	movups	32(%rdi),%xmm4
 	movaps	%xmm3,%xmm12
-	subq	$16,%rdx
+	subq	$0x10,%rdx
 	jbe	L$cbc_dec_three
 
 	movups	48(%rdi),%xmm5
 	movaps	%xmm4,%xmm13
-	subq	$16,%rdx
+	subq	$0x10,%rdx
 	jbe	L$cbc_dec_four
 
 	movups	64(%rdi),%xmm6
@@ -3025,7 +3838,7 @@
 	movdqa	%xmm6,%xmm2
 	pxor	%xmm6,%xmm6
 	pxor	%xmm7,%xmm7
-	subq	$16,%rdx
+	subq	$0x10,%rdx
 	jmp	L$cbc_dec_tail_collected
 
 .p2align	4
@@ -3121,8 +3934,8 @@
 L$cbc_dec_ret:
 	xorps	%xmm0,%xmm0
 	pxor	%xmm1,%xmm1
-	leaq	(%rbp),%rsp
-	popq	%rbp
+	movq	-8(%r11),%rbp
+	leaq	(%r11),%rsp
 L$cbc_ret:
 	.byte	0xf3,0xc3
 
@@ -3344,7 +4157,7 @@
 	pslldq	$4,%xmm0
 	pxor	%xmm3,%xmm0
 
-	pshufd	$255,%xmm0,%xmm3
+	pshufd	$0xff,%xmm0,%xmm3
 	pxor	%xmm1,%xmm3
 	pslldq	$4,%xmm1
 	pxor	%xmm1,%xmm3
@@ -3431,7 +4244,7 @@
 	decl	%r10d
 	jz	L$done_key256
 
-	pshufd	$255,%xmm0,%xmm2
+	pshufd	$0xff,%xmm0,%xmm2
 	pxor	%xmm3,%xmm3
 .byte	102,15,56,221,211
 
diff --git a/mac-x86_64/crypto/aes/bsaes-x86_64.S b/mac-x86_64/crypto/aes/bsaes-x86_64.S
index c2d0477..6e679c1 100644
--- a/mac-x86_64/crypto/aes/bsaes-x86_64.S
+++ b/mac-x86_64/crypto/aes/bsaes-x86_64.S
@@ -325,45 +325,45 @@
 	pxor	%xmm2,%xmm5
 	decl	%r10d
 	jl	L$enc_done
-	pshufd	$147,%xmm15,%xmm7
-	pshufd	$147,%xmm0,%xmm8
+	pshufd	$0x93,%xmm15,%xmm7
+	pshufd	$0x93,%xmm0,%xmm8
 	pxor	%xmm7,%xmm15
-	pshufd	$147,%xmm3,%xmm9
+	pshufd	$0x93,%xmm3,%xmm9
 	pxor	%xmm8,%xmm0
-	pshufd	$147,%xmm5,%xmm10
+	pshufd	$0x93,%xmm5,%xmm10
 	pxor	%xmm9,%xmm3
-	pshufd	$147,%xmm2,%xmm11
+	pshufd	$0x93,%xmm2,%xmm11
 	pxor	%xmm10,%xmm5
-	pshufd	$147,%xmm6,%xmm12
+	pshufd	$0x93,%xmm6,%xmm12
 	pxor	%xmm11,%xmm2
-	pshufd	$147,%xmm1,%xmm13
+	pshufd	$0x93,%xmm1,%xmm13
 	pxor	%xmm12,%xmm6
-	pshufd	$147,%xmm4,%xmm14
+	pshufd	$0x93,%xmm4,%xmm14
 	pxor	%xmm13,%xmm1
 	pxor	%xmm14,%xmm4
 
 	pxor	%xmm15,%xmm8
 	pxor	%xmm4,%xmm7
 	pxor	%xmm4,%xmm8
-	pshufd	$78,%xmm15,%xmm15
+	pshufd	$0x4E,%xmm15,%xmm15
 	pxor	%xmm0,%xmm9
-	pshufd	$78,%xmm0,%xmm0
+	pshufd	$0x4E,%xmm0,%xmm0
 	pxor	%xmm2,%xmm12
 	pxor	%xmm7,%xmm15
 	pxor	%xmm6,%xmm13
 	pxor	%xmm8,%xmm0
 	pxor	%xmm5,%xmm11
-	pshufd	$78,%xmm2,%xmm7
+	pshufd	$0x4E,%xmm2,%xmm7
 	pxor	%xmm1,%xmm14
-	pshufd	$78,%xmm6,%xmm8
+	pshufd	$0x4E,%xmm6,%xmm8
 	pxor	%xmm3,%xmm10
-	pshufd	$78,%xmm5,%xmm2
+	pshufd	$0x4E,%xmm5,%xmm2
 	pxor	%xmm4,%xmm10
-	pshufd	$78,%xmm4,%xmm6
+	pshufd	$0x4E,%xmm4,%xmm6
 	pxor	%xmm4,%xmm11
-	pshufd	$78,%xmm1,%xmm5
+	pshufd	$0x4E,%xmm1,%xmm5
 	pxor	%xmm11,%xmm7
-	pshufd	$78,%xmm3,%xmm1
+	pshufd	$0x4E,%xmm3,%xmm1
 	pxor	%xmm12,%xmm8
 	pxor	%xmm10,%xmm2
 	pxor	%xmm14,%xmm6
@@ -797,24 +797,24 @@
 	decl	%r10d
 	jl	L$dec_done
 
-	pshufd	$78,%xmm15,%xmm7
-	pshufd	$78,%xmm2,%xmm13
+	pshufd	$0x4E,%xmm15,%xmm7
+	pshufd	$0x4E,%xmm2,%xmm13
 	pxor	%xmm15,%xmm7
-	pshufd	$78,%xmm4,%xmm14
+	pshufd	$0x4E,%xmm4,%xmm14
 	pxor	%xmm2,%xmm13
-	pshufd	$78,%xmm0,%xmm8
+	pshufd	$0x4E,%xmm0,%xmm8
 	pxor	%xmm4,%xmm14
-	pshufd	$78,%xmm5,%xmm9
+	pshufd	$0x4E,%xmm5,%xmm9
 	pxor	%xmm0,%xmm8
-	pshufd	$78,%xmm3,%xmm10
+	pshufd	$0x4E,%xmm3,%xmm10
 	pxor	%xmm5,%xmm9
 	pxor	%xmm13,%xmm15
 	pxor	%xmm13,%xmm0
-	pshufd	$78,%xmm1,%xmm11
+	pshufd	$0x4E,%xmm1,%xmm11
 	pxor	%xmm3,%xmm10
 	pxor	%xmm7,%xmm5
 	pxor	%xmm8,%xmm3
-	pshufd	$78,%xmm6,%xmm12
+	pshufd	$0x4E,%xmm6,%xmm12
 	pxor	%xmm1,%xmm11
 	pxor	%xmm14,%xmm0
 	pxor	%xmm9,%xmm1
@@ -828,45 +828,45 @@
 	pxor	%xmm14,%xmm1
 	pxor	%xmm14,%xmm6
 	pxor	%xmm12,%xmm4
-	pshufd	$147,%xmm15,%xmm7
-	pshufd	$147,%xmm0,%xmm8
+	pshufd	$0x93,%xmm15,%xmm7
+	pshufd	$0x93,%xmm0,%xmm8
 	pxor	%xmm7,%xmm15
-	pshufd	$147,%xmm5,%xmm9
+	pshufd	$0x93,%xmm5,%xmm9
 	pxor	%xmm8,%xmm0
-	pshufd	$147,%xmm3,%xmm10
+	pshufd	$0x93,%xmm3,%xmm10
 	pxor	%xmm9,%xmm5
-	pshufd	$147,%xmm1,%xmm11
+	pshufd	$0x93,%xmm1,%xmm11
 	pxor	%xmm10,%xmm3
-	pshufd	$147,%xmm6,%xmm12
+	pshufd	$0x93,%xmm6,%xmm12
 	pxor	%xmm11,%xmm1
-	pshufd	$147,%xmm2,%xmm13
+	pshufd	$0x93,%xmm2,%xmm13
 	pxor	%xmm12,%xmm6
-	pshufd	$147,%xmm4,%xmm14
+	pshufd	$0x93,%xmm4,%xmm14
 	pxor	%xmm13,%xmm2
 	pxor	%xmm14,%xmm4
 
 	pxor	%xmm15,%xmm8
 	pxor	%xmm4,%xmm7
 	pxor	%xmm4,%xmm8
-	pshufd	$78,%xmm15,%xmm15
+	pshufd	$0x4E,%xmm15,%xmm15
 	pxor	%xmm0,%xmm9
-	pshufd	$78,%xmm0,%xmm0
+	pshufd	$0x4E,%xmm0,%xmm0
 	pxor	%xmm1,%xmm12
 	pxor	%xmm7,%xmm15
 	pxor	%xmm6,%xmm13
 	pxor	%xmm8,%xmm0
 	pxor	%xmm3,%xmm11
-	pshufd	$78,%xmm1,%xmm7
+	pshufd	$0x4E,%xmm1,%xmm7
 	pxor	%xmm2,%xmm14
-	pshufd	$78,%xmm6,%xmm8
+	pshufd	$0x4E,%xmm6,%xmm8
 	pxor	%xmm5,%xmm10
-	pshufd	$78,%xmm3,%xmm1
+	pshufd	$0x4E,%xmm3,%xmm1
 	pxor	%xmm4,%xmm10
-	pshufd	$78,%xmm4,%xmm6
+	pshufd	$0x4E,%xmm4,%xmm6
 	pxor	%xmm4,%xmm11
-	pshufd	$78,%xmm2,%xmm3
+	pshufd	$0x4E,%xmm2,%xmm3
 	pxor	%xmm11,%xmm7
-	pshufd	$78,%xmm5,%xmm2
+	pshufd	$0x4E,%xmm5,%xmm2
 	pxor	%xmm12,%xmm8
 	pxor	%xmm1,%xmm10
 	pxor	%xmm14,%xmm6
@@ -1302,15 +1302,14 @@
 	cmpq	%rax,%rbp
 	ja	L$cbc_dec_bzero
 
-	leaq	(%rbp),%rsp
-	movq	72(%rsp),%r15
-	movq	80(%rsp),%r14
-	movq	88(%rsp),%r13
-	movq	96(%rsp),%r12
-	movq	104(%rsp),%rbx
-	movq	112(%rsp),%rax
-	leaq	120(%rsp),%rsp
-	movq	%rax,%rbp
+	leaq	120(%rbp),%rax
+	movq	-48(%rax),%r15
+	movq	-40(%rax),%r14
+	movq	-32(%rax),%r13
+	movq	-24(%rax),%r12
+	movq	-16(%rax),%rbx
+	movq	-8(%rax),%rbp
+	leaq	(%rax),%rsp
 L$cbc_dec_epilogue:
 	.byte	0xf3,0xc3
 
@@ -1503,15 +1502,14 @@
 	cmpq	%rax,%rbp
 	ja	L$ctr_enc_bzero
 
-	leaq	(%rbp),%rsp
-	movq	72(%rsp),%r15
-	movq	80(%rsp),%r14
-	movq	88(%rsp),%r13
-	movq	96(%rsp),%r12
-	movq	104(%rsp),%rbx
-	movq	112(%rsp),%rax
-	leaq	120(%rsp),%rsp
-	movq	%rax,%rbp
+	leaq	120(%rbp),%rax
+	movq	-48(%rax),%r15
+	movq	-40(%rax),%r14
+	movq	-32(%rax),%r13
+	movq	-24(%rax),%r12
+	movq	-16(%rax),%rbx
+	movq	-8(%rax),%rbp
+	leaq	(%rax),%rsp
 L$ctr_enc_epilogue:
 	.byte	0xf3,0xc3
 
@@ -1556,20 +1554,20 @@
 	movdqa	%xmm7,(%rax)
 
 	andq	$-16,%r14
-	subq	$128,%rsp
+	subq	$0x80,%rsp
 	movdqa	32(%rbp),%xmm6
 
 	pxor	%xmm14,%xmm14
 	movdqa	L$xts_magic(%rip),%xmm12
 	pcmpgtd	%xmm6,%xmm14
 
-	subq	$128,%r14
+	subq	$0x80,%r14
 	jc	L$xts_enc_short
 	jmp	L$xts_enc_loop
 
 .p2align	4
 L$xts_enc_loop:
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm15
 	movdqa	%xmm6,0(%rsp)
@@ -1577,7 +1575,7 @@
 	pand	%xmm12,%xmm13
 	pcmpgtd	%xmm6,%xmm14
 	pxor	%xmm13,%xmm6
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm0
 	movdqa	%xmm6,16(%rsp)
@@ -1586,7 +1584,7 @@
 	pcmpgtd	%xmm6,%xmm14
 	pxor	%xmm13,%xmm6
 	movdqu	0(%r12),%xmm7
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm1
 	movdqa	%xmm6,32(%rsp)
@@ -1596,7 +1594,7 @@
 	pxor	%xmm13,%xmm6
 	movdqu	16(%r12),%xmm8
 	pxor	%xmm7,%xmm15
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm2
 	movdqa	%xmm6,48(%rsp)
@@ -1606,7 +1604,7 @@
 	pxor	%xmm13,%xmm6
 	movdqu	32(%r12),%xmm9
 	pxor	%xmm8,%xmm0
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm3
 	movdqa	%xmm6,64(%rsp)
@@ -1616,7 +1614,7 @@
 	pxor	%xmm13,%xmm6
 	movdqu	48(%r12),%xmm10
 	pxor	%xmm9,%xmm1
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm4
 	movdqa	%xmm6,80(%rsp)
@@ -1626,7 +1624,7 @@
 	pxor	%xmm13,%xmm6
 	movdqu	64(%r12),%xmm11
 	pxor	%xmm10,%xmm2
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm5
 	movdqa	%xmm6,96(%rsp)
@@ -1670,20 +1668,20 @@
 	pxor	%xmm14,%xmm14
 	movdqa	L$xts_magic(%rip),%xmm12
 	pcmpgtd	%xmm6,%xmm14
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	paddq	%xmm6,%xmm6
 	pand	%xmm12,%xmm13
 	pcmpgtd	%xmm6,%xmm14
 	pxor	%xmm13,%xmm6
 
-	subq	$128,%r14
+	subq	$0x80,%r14
 	jnc	L$xts_enc_loop
 
 L$xts_enc_short:
-	addq	$128,%r14
+	addq	$0x80,%r14
 	jz	L$xts_enc_done
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm15
 	movdqa	%xmm6,0(%rsp)
@@ -1691,7 +1689,7 @@
 	pand	%xmm12,%xmm13
 	pcmpgtd	%xmm6,%xmm14
 	pxor	%xmm13,%xmm6
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm0
 	movdqa	%xmm6,16(%rsp)
@@ -1702,7 +1700,7 @@
 	movdqu	0(%r12),%xmm7
 	cmpq	$16,%r14
 	je	L$xts_enc_1
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm1
 	movdqa	%xmm6,32(%rsp)
@@ -1714,7 +1712,7 @@
 	cmpq	$32,%r14
 	je	L$xts_enc_2
 	pxor	%xmm7,%xmm15
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm2
 	movdqa	%xmm6,48(%rsp)
@@ -1726,7 +1724,7 @@
 	cmpq	$48,%r14
 	je	L$xts_enc_3
 	pxor	%xmm8,%xmm0
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm3
 	movdqa	%xmm6,64(%rsp)
@@ -1738,7 +1736,7 @@
 	cmpq	$64,%r14
 	je	L$xts_enc_4
 	pxor	%xmm9,%xmm1
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm4
 	movdqa	%xmm6,80(%rsp)
@@ -1750,7 +1748,7 @@
 	cmpq	$80,%r14
 	je	L$xts_enc_5
 	pxor	%xmm10,%xmm2
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm5
 	movdqa	%xmm6,96(%rsp)
@@ -1955,15 +1953,14 @@
 	cmpq	%rax,%rbp
 	ja	L$xts_enc_bzero
 
-	leaq	(%rbp),%rsp
-	movq	72(%rsp),%r15
-	movq	80(%rsp),%r14
-	movq	88(%rsp),%r13
-	movq	96(%rsp),%r12
-	movq	104(%rsp),%rbx
-	movq	112(%rsp),%rax
-	leaq	120(%rsp),%rsp
-	movq	%rax,%rbp
+	leaq	120(%rbp),%rax
+	movq	-48(%rax),%r15
+	movq	-40(%rax),%r14
+	movq	-32(%rax),%r13
+	movq	-24(%rax),%r12
+	movq	-16(%rax),%rbx
+	movq	-8(%rax),%rbp
+	leaq	(%rax),%rsp
 L$xts_enc_epilogue:
 	.byte	0xf3,0xc3
 
@@ -2016,20 +2013,20 @@
 	shlq	$4,%rax
 	subq	%rax,%r14
 
-	subq	$128,%rsp
+	subq	$0x80,%rsp
 	movdqa	32(%rbp),%xmm6
 
 	pxor	%xmm14,%xmm14
 	movdqa	L$xts_magic(%rip),%xmm12
 	pcmpgtd	%xmm6,%xmm14
 
-	subq	$128,%r14
+	subq	$0x80,%r14
 	jc	L$xts_dec_short
 	jmp	L$xts_dec_loop
 
 .p2align	4
 L$xts_dec_loop:
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm15
 	movdqa	%xmm6,0(%rsp)
@@ -2037,7 +2034,7 @@
 	pand	%xmm12,%xmm13
 	pcmpgtd	%xmm6,%xmm14
 	pxor	%xmm13,%xmm6
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm0
 	movdqa	%xmm6,16(%rsp)
@@ -2046,7 +2043,7 @@
 	pcmpgtd	%xmm6,%xmm14
 	pxor	%xmm13,%xmm6
 	movdqu	0(%r12),%xmm7
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm1
 	movdqa	%xmm6,32(%rsp)
@@ -2056,7 +2053,7 @@
 	pxor	%xmm13,%xmm6
 	movdqu	16(%r12),%xmm8
 	pxor	%xmm7,%xmm15
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm2
 	movdqa	%xmm6,48(%rsp)
@@ -2066,7 +2063,7 @@
 	pxor	%xmm13,%xmm6
 	movdqu	32(%r12),%xmm9
 	pxor	%xmm8,%xmm0
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm3
 	movdqa	%xmm6,64(%rsp)
@@ -2076,7 +2073,7 @@
 	pxor	%xmm13,%xmm6
 	movdqu	48(%r12),%xmm10
 	pxor	%xmm9,%xmm1
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm4
 	movdqa	%xmm6,80(%rsp)
@@ -2086,7 +2083,7 @@
 	pxor	%xmm13,%xmm6
 	movdqu	64(%r12),%xmm11
 	pxor	%xmm10,%xmm2
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm5
 	movdqa	%xmm6,96(%rsp)
@@ -2130,20 +2127,20 @@
 	pxor	%xmm14,%xmm14
 	movdqa	L$xts_magic(%rip),%xmm12
 	pcmpgtd	%xmm6,%xmm14
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	paddq	%xmm6,%xmm6
 	pand	%xmm12,%xmm13
 	pcmpgtd	%xmm6,%xmm14
 	pxor	%xmm13,%xmm6
 
-	subq	$128,%r14
+	subq	$0x80,%r14
 	jnc	L$xts_dec_loop
 
 L$xts_dec_short:
-	addq	$128,%r14
+	addq	$0x80,%r14
 	jz	L$xts_dec_done
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm15
 	movdqa	%xmm6,0(%rsp)
@@ -2151,7 +2148,7 @@
 	pand	%xmm12,%xmm13
 	pcmpgtd	%xmm6,%xmm14
 	pxor	%xmm13,%xmm6
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm0
 	movdqa	%xmm6,16(%rsp)
@@ -2162,7 +2159,7 @@
 	movdqu	0(%r12),%xmm7
 	cmpq	$16,%r14
 	je	L$xts_dec_1
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm1
 	movdqa	%xmm6,32(%rsp)
@@ -2174,7 +2171,7 @@
 	cmpq	$32,%r14
 	je	L$xts_dec_2
 	pxor	%xmm7,%xmm15
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm2
 	movdqa	%xmm6,48(%rsp)
@@ -2186,7 +2183,7 @@
 	cmpq	$48,%r14
 	je	L$xts_dec_3
 	pxor	%xmm8,%xmm0
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm3
 	movdqa	%xmm6,64(%rsp)
@@ -2198,7 +2195,7 @@
 	cmpq	$64,%r14
 	je	L$xts_dec_4
 	pxor	%xmm9,%xmm1
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm4
 	movdqa	%xmm6,80(%rsp)
@@ -2210,7 +2207,7 @@
 	cmpq	$80,%r14
 	je	L$xts_dec_5
 	pxor	%xmm10,%xmm2
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	pxor	%xmm14,%xmm14
 	movdqa	%xmm6,%xmm5
 	movdqa	%xmm6,96(%rsp)
@@ -2387,7 +2384,7 @@
 	pxor	%xmm14,%xmm14
 	movdqa	L$xts_magic(%rip),%xmm12
 	pcmpgtd	%xmm6,%xmm14
-	pshufd	$19,%xmm14,%xmm13
+	pshufd	$0x13,%xmm14,%xmm13
 	movdqa	%xmm6,%xmm5
 	paddq	%xmm6,%xmm6
 	pand	%xmm12,%xmm13
@@ -2434,15 +2431,14 @@
 	cmpq	%rax,%rbp
 	ja	L$xts_dec_bzero
 
-	leaq	(%rbp),%rsp
-	movq	72(%rsp),%r15
-	movq	80(%rsp),%r14
-	movq	88(%rsp),%r13
-	movq	96(%rsp),%r12
-	movq	104(%rsp),%rbx
-	movq	112(%rsp),%rax
-	leaq	120(%rsp),%rsp
-	movq	%rax,%rbp
+	leaq	120(%rbp),%rax
+	movq	-48(%rax),%r15
+	movq	-40(%rax),%r14
+	movq	-32(%rax),%r13
+	movq	-24(%rax),%r12
+	movq	-16(%rax),%rbx
+	movq	-8(%rax),%rbp
+	leaq	(%rax),%rsp
 L$xts_dec_epilogue:
 	.byte	0xf3,0xc3
 
diff --git a/mac-x86_64/crypto/aes/vpaes-x86_64.S b/mac-x86_64/crypto/aes/vpaes-x86_64.S
index 711ea43..997cde8 100644
--- a/mac-x86_64/crypto/aes/vpaes-x86_64.S
+++ b/mac-x86_64/crypto/aes/vpaes-x86_64.S
@@ -61,7 +61,7 @@
 	addq	$16,%r11
 	pxor	%xmm0,%xmm3
 .byte	102,15,56,0,193
-	andq	$48,%r11
+	andq	$0x30,%r11
 	subq	$1,%rax
 	pxor	%xmm3,%xmm0
 
@@ -121,10 +121,10 @@
 	pand	%xmm9,%xmm0
 .byte	102,15,56,0,208
 	movdqa	L$k_dipt+16(%rip),%xmm0
-	xorq	$48,%r11
+	xorq	$0x30,%r11
 	leaq	L$k_dsbd(%rip),%r10
 .byte	102,15,56,0,193
-	andq	$48,%r11
+	andq	$0x30,%r11
 	pxor	%xmm5,%xmm2
 	movdqa	L$k_mc_forward+48(%rip),%xmm5
 	pxor	%xmm2,%xmm0
@@ -243,7 +243,7 @@
 	movdqa	(%r8,%r10,1),%xmm1
 .byte	102,15,56,0,217
 	movdqu	%xmm3,(%rdx)
-	xorq	$48,%r8
+	xorq	$0x30,%r8
 
 L$schedule_go:
 	cmpl	$192,%esi
@@ -333,7 +333,7 @@
 	call	_vpaes_schedule_mangle
 
 
-	pshufd	$255,%xmm0,%xmm0
+	pshufd	$0xFF,%xmm0,%xmm0
 	movdqa	%xmm7,%xmm5
 	movdqa	%xmm6,%xmm7
 	call	_vpaes_schedule_low_round
@@ -400,8 +400,8 @@
 
 .p2align	4
 _vpaes_schedule_192_smear:
-	pshufd	$128,%xmm6,%xmm1
-	pshufd	$254,%xmm7,%xmm0
+	pshufd	$0x80,%xmm6,%xmm1
+	pshufd	$0xFE,%xmm7,%xmm0
 	pxor	%xmm1,%xmm6
 	pxor	%xmm1,%xmm1
 	pxor	%xmm0,%xmm6
@@ -438,7 +438,7 @@
 	pxor	%xmm1,%xmm7
 
 
-	pshufd	$255,%xmm0,%xmm0
+	pshufd	$0xFF,%xmm0,%xmm0
 .byte	102,15,58,15,192,1
 
 
@@ -597,7 +597,7 @@
 	movdqa	(%r8,%r10,1),%xmm1
 .byte	102,15,56,0,217
 	addq	$-16,%r8
-	andq	$48,%r8
+	andq	$0x30,%r8
 	movdqu	%xmm3,(%rdx)
 	.byte	0xf3,0xc3
 
@@ -616,7 +616,7 @@
 	movl	%eax,240(%rdx)
 
 	movl	$0,%ecx
-	movl	$48,%r8d
+	movl	$0x30,%r8d
 	call	_vpaes_schedule_core
 	xorl	%eax,%eax
 	.byte	0xf3,0xc3
diff --git a/mac-x86_64/crypto/bn/rsaz-avx2.S b/mac-x86_64/crypto/bn/rsaz-avx2.S
index 8ba2019..a913507 100644
--- a/mac-x86_64/crypto/bn/rsaz-avx2.S
+++ b/mac-x86_64/crypto/bn/rsaz-avx2.S
@@ -1,34 +1,1746 @@
 #if defined(__x86_64__)
 .text	
 
-.globl	_rsaz_avx2_eligible
-.private_extern _rsaz_avx2_eligible
+.globl	_rsaz_1024_sqr_avx2
+.private_extern _rsaz_1024_sqr_avx2
 
-_rsaz_avx2_eligible:
-	xorl	%eax,%eax
+.p2align	6
+_rsaz_1024_sqr_avx2:
+
+	leaq	(%rsp),%rax
+
+	pushq	%rbx
+
+	pushq	%rbp
+
+	pushq	%r12
+
+	pushq	%r13
+
+	pushq	%r14
+
+	pushq	%r15
+
+	vzeroupper
+	movq	%rax,%rbp
+
+	movq	%rdx,%r13
+	subq	$832,%rsp
+	movq	%r13,%r15
+	subq	$-128,%rdi
+	subq	$-128,%rsi
+	subq	$-128,%r13
+
+	andq	$4095,%r15
+	addq	$320,%r15
+	shrq	$12,%r15
+	vpxor	%ymm9,%ymm9,%ymm9
+	jz	L$sqr_1024_no_n_copy
+
+
+
+
+
+	subq	$320,%rsp
+	vmovdqu	0-128(%r13),%ymm0
+	andq	$-2048,%rsp
+	vmovdqu	32-128(%r13),%ymm1
+	vmovdqu	64-128(%r13),%ymm2
+	vmovdqu	96-128(%r13),%ymm3
+	vmovdqu	128-128(%r13),%ymm4
+	vmovdqu	160-128(%r13),%ymm5
+	vmovdqu	192-128(%r13),%ymm6
+	vmovdqu	224-128(%r13),%ymm7
+	vmovdqu	256-128(%r13),%ymm8
+	leaq	832+128(%rsp),%r13
+	vmovdqu	%ymm0,0-128(%r13)
+	vmovdqu	%ymm1,32-128(%r13)
+	vmovdqu	%ymm2,64-128(%r13)
+	vmovdqu	%ymm3,96-128(%r13)
+	vmovdqu	%ymm4,128-128(%r13)
+	vmovdqu	%ymm5,160-128(%r13)
+	vmovdqu	%ymm6,192-128(%r13)
+	vmovdqu	%ymm7,224-128(%r13)
+	vmovdqu	%ymm8,256-128(%r13)
+	vmovdqu	%ymm9,288-128(%r13)
+
+L$sqr_1024_no_n_copy:
+	andq	$-1024,%rsp
+
+	vmovdqu	32-128(%rsi),%ymm1
+	vmovdqu	64-128(%rsi),%ymm2
+	vmovdqu	96-128(%rsi),%ymm3
+	vmovdqu	128-128(%rsi),%ymm4
+	vmovdqu	160-128(%rsi),%ymm5
+	vmovdqu	192-128(%rsi),%ymm6
+	vmovdqu	224-128(%rsi),%ymm7
+	vmovdqu	256-128(%rsi),%ymm8
+
+	leaq	192(%rsp),%rbx
+	vpbroadcastq	L$and_mask(%rip),%ymm15
+	jmp	L$OOP_GRANDE_SQR_1024
+
+.p2align	5
+L$OOP_GRANDE_SQR_1024:
+	leaq	576+128(%rsp),%r9
+	leaq	448(%rsp),%r12
+
+
+
+
+	vpaddq	%ymm1,%ymm1,%ymm1
+	vpbroadcastq	0-128(%rsi),%ymm10
+	vpaddq	%ymm2,%ymm2,%ymm2
+	vmovdqa	%ymm1,0-128(%r9)
+	vpaddq	%ymm3,%ymm3,%ymm3
+	vmovdqa	%ymm2,32-128(%r9)
+	vpaddq	%ymm4,%ymm4,%ymm4
+	vmovdqa	%ymm3,64-128(%r9)
+	vpaddq	%ymm5,%ymm5,%ymm5
+	vmovdqa	%ymm4,96-128(%r9)
+	vpaddq	%ymm6,%ymm6,%ymm6
+	vmovdqa	%ymm5,128-128(%r9)
+	vpaddq	%ymm7,%ymm7,%ymm7
+	vmovdqa	%ymm6,160-128(%r9)
+	vpaddq	%ymm8,%ymm8,%ymm8
+	vmovdqa	%ymm7,192-128(%r9)
+	vpxor	%ymm9,%ymm9,%ymm9
+	vmovdqa	%ymm8,224-128(%r9)
+
+	vpmuludq	0-128(%rsi),%ymm10,%ymm0
+	vpbroadcastq	32-128(%rsi),%ymm11
+	vmovdqu	%ymm9,288-192(%rbx)
+	vpmuludq	%ymm10,%ymm1,%ymm1
+	vmovdqu	%ymm9,320-448(%r12)
+	vpmuludq	%ymm10,%ymm2,%ymm2
+	vmovdqu	%ymm9,352-448(%r12)
+	vpmuludq	%ymm10,%ymm3,%ymm3
+	vmovdqu	%ymm9,384-448(%r12)
+	vpmuludq	%ymm10,%ymm4,%ymm4
+	vmovdqu	%ymm9,416-448(%r12)
+	vpmuludq	%ymm10,%ymm5,%ymm5
+	vmovdqu	%ymm9,448-448(%r12)
+	vpmuludq	%ymm10,%ymm6,%ymm6
+	vmovdqu	%ymm9,480-448(%r12)
+	vpmuludq	%ymm10,%ymm7,%ymm7
+	vmovdqu	%ymm9,512-448(%r12)
+	vpmuludq	%ymm10,%ymm8,%ymm8
+	vpbroadcastq	64-128(%rsi),%ymm10
+	vmovdqu	%ymm9,544-448(%r12)
+
+	movq	%rsi,%r15
+	movl	$4,%r14d
+	jmp	L$sqr_entry_1024
+.p2align	5
+L$OOP_SQR_1024:
+	vpbroadcastq	32-128(%r15),%ymm11
+	vpmuludq	0-128(%rsi),%ymm10,%ymm0
+	vpaddq	0-192(%rbx),%ymm0,%ymm0
+	vpmuludq	0-128(%r9),%ymm10,%ymm1
+	vpaddq	32-192(%rbx),%ymm1,%ymm1
+	vpmuludq	32-128(%r9),%ymm10,%ymm2
+	vpaddq	64-192(%rbx),%ymm2,%ymm2
+	vpmuludq	64-128(%r9),%ymm10,%ymm3
+	vpaddq	96-192(%rbx),%ymm3,%ymm3
+	vpmuludq	96-128(%r9),%ymm10,%ymm4
+	vpaddq	128-192(%rbx),%ymm4,%ymm4
+	vpmuludq	128-128(%r9),%ymm10,%ymm5
+	vpaddq	160-192(%rbx),%ymm5,%ymm5
+	vpmuludq	160-128(%r9),%ymm10,%ymm6
+	vpaddq	192-192(%rbx),%ymm6,%ymm6
+	vpmuludq	192-128(%r9),%ymm10,%ymm7
+	vpaddq	224-192(%rbx),%ymm7,%ymm7
+	vpmuludq	224-128(%r9),%ymm10,%ymm8
+	vpbroadcastq	64-128(%r15),%ymm10
+	vpaddq	256-192(%rbx),%ymm8,%ymm8
+L$sqr_entry_1024:
+	vmovdqu	%ymm0,0-192(%rbx)
+	vmovdqu	%ymm1,32-192(%rbx)
+
+	vpmuludq	32-128(%rsi),%ymm11,%ymm12
+	vpaddq	%ymm12,%ymm2,%ymm2
+	vpmuludq	32-128(%r9),%ymm11,%ymm14
+	vpaddq	%ymm14,%ymm3,%ymm3
+	vpmuludq	64-128(%r9),%ymm11,%ymm13
+	vpaddq	%ymm13,%ymm4,%ymm4
+	vpmuludq	96-128(%r9),%ymm11,%ymm12
+	vpaddq	%ymm12,%ymm5,%ymm5
+	vpmuludq	128-128(%r9),%ymm11,%ymm14
+	vpaddq	%ymm14,%ymm6,%ymm6
+	vpmuludq	160-128(%r9),%ymm11,%ymm13
+	vpaddq	%ymm13,%ymm7,%ymm7
+	vpmuludq	192-128(%r9),%ymm11,%ymm12
+	vpaddq	%ymm12,%ymm8,%ymm8
+	vpmuludq	224-128(%r9),%ymm11,%ymm0
+	vpbroadcastq	96-128(%r15),%ymm11
+	vpaddq	288-192(%rbx),%ymm0,%ymm0
+
+	vmovdqu	%ymm2,64-192(%rbx)
+	vmovdqu	%ymm3,96-192(%rbx)
+
+	vpmuludq	64-128(%rsi),%ymm10,%ymm13
+	vpaddq	%ymm13,%ymm4,%ymm4
+	vpmuludq	64-128(%r9),%ymm10,%ymm12
+	vpaddq	%ymm12,%ymm5,%ymm5
+	vpmuludq	96-128(%r9),%ymm10,%ymm14
+	vpaddq	%ymm14,%ymm6,%ymm6
+	vpmuludq	128-128(%r9),%ymm10,%ymm13
+	vpaddq	%ymm13,%ymm7,%ymm7
+	vpmuludq	160-128(%r9),%ymm10,%ymm12
+	vpaddq	%ymm12,%ymm8,%ymm8
+	vpmuludq	192-128(%r9),%ymm10,%ymm14
+	vpaddq	%ymm14,%ymm0,%ymm0
+	vpmuludq	224-128(%r9),%ymm10,%ymm1
+	vpbroadcastq	128-128(%r15),%ymm10
+	vpaddq	320-448(%r12),%ymm1,%ymm1
+
+	vmovdqu	%ymm4,128-192(%rbx)
+	vmovdqu	%ymm5,160-192(%rbx)
+
+	vpmuludq	96-128(%rsi),%ymm11,%ymm12
+	vpaddq	%ymm12,%ymm6,%ymm6
+	vpmuludq	96-128(%r9),%ymm11,%ymm14
+	vpaddq	%ymm14,%ymm7,%ymm7
+	vpmuludq	128-128(%r9),%ymm11,%ymm13
+	vpaddq	%ymm13,%ymm8,%ymm8
+	vpmuludq	160-128(%r9),%ymm11,%ymm12
+	vpaddq	%ymm12,%ymm0,%ymm0
+	vpmuludq	192-128(%r9),%ymm11,%ymm14
+	vpaddq	%ymm14,%ymm1,%ymm1
+	vpmuludq	224-128(%r9),%ymm11,%ymm2
+	vpbroadcastq	160-128(%r15),%ymm11
+	vpaddq	352-448(%r12),%ymm2,%ymm2
+
+	vmovdqu	%ymm6,192-192(%rbx)
+	vmovdqu	%ymm7,224-192(%rbx)
+
+	vpmuludq	128-128(%rsi),%ymm10,%ymm12
+	vpaddq	%ymm12,%ymm8,%ymm8
+	vpmuludq	128-128(%r9),%ymm10,%ymm14
+	vpaddq	%ymm14,%ymm0,%ymm0
+	vpmuludq	160-128(%r9),%ymm10,%ymm13
+	vpaddq	%ymm13,%ymm1,%ymm1
+	vpmuludq	192-128(%r9),%ymm10,%ymm12
+	vpaddq	%ymm12,%ymm2,%ymm2
+	vpmuludq	224-128(%r9),%ymm10,%ymm3
+	vpbroadcastq	192-128(%r15),%ymm10
+	vpaddq	384-448(%r12),%ymm3,%ymm3
+
+	vmovdqu	%ymm8,256-192(%rbx)
+	vmovdqu	%ymm0,288-192(%rbx)
+	leaq	8(%rbx),%rbx
+
+	vpmuludq	160-128(%rsi),%ymm11,%ymm13
+	vpaddq	%ymm13,%ymm1,%ymm1
+	vpmuludq	160-128(%r9),%ymm11,%ymm12
+	vpaddq	%ymm12,%ymm2,%ymm2
+	vpmuludq	192-128(%r9),%ymm11,%ymm14
+	vpaddq	%ymm14,%ymm3,%ymm3
+	vpmuludq	224-128(%r9),%ymm11,%ymm4
+	vpbroadcastq	224-128(%r15),%ymm11
+	vpaddq	416-448(%r12),%ymm4,%ymm4
+
+	vmovdqu	%ymm1,320-448(%r12)
+	vmovdqu	%ymm2,352-448(%r12)
+
+	vpmuludq	192-128(%rsi),%ymm10,%ymm12
+	vpaddq	%ymm12,%ymm3,%ymm3
+	vpmuludq	192-128(%r9),%ymm10,%ymm14
+	vpbroadcastq	256-128(%r15),%ymm0
+	vpaddq	%ymm14,%ymm4,%ymm4
+	vpmuludq	224-128(%r9),%ymm10,%ymm5
+	vpbroadcastq	0+8-128(%r15),%ymm10
+	vpaddq	448-448(%r12),%ymm5,%ymm5
+
+	vmovdqu	%ymm3,384-448(%r12)
+	vmovdqu	%ymm4,416-448(%r12)
+	leaq	8(%r15),%r15
+
+	vpmuludq	224-128(%rsi),%ymm11,%ymm12
+	vpaddq	%ymm12,%ymm5,%ymm5
+	vpmuludq	224-128(%r9),%ymm11,%ymm6
+	vpaddq	480-448(%r12),%ymm6,%ymm6
+
+	vpmuludq	256-128(%rsi),%ymm0,%ymm7
+	vmovdqu	%ymm5,448-448(%r12)
+	vpaddq	512-448(%r12),%ymm7,%ymm7
+	vmovdqu	%ymm6,480-448(%r12)
+	vmovdqu	%ymm7,512-448(%r12)
+	leaq	8(%r12),%r12
+
+	decl	%r14d
+	jnz	L$OOP_SQR_1024
+
+	vmovdqu	256(%rsp),%ymm8
+	vmovdqu	288(%rsp),%ymm1
+	vmovdqu	320(%rsp),%ymm2
+	leaq	192(%rsp),%rbx
+
+	vpsrlq	$29,%ymm8,%ymm14
+	vpand	%ymm15,%ymm8,%ymm8
+	vpsrlq	$29,%ymm1,%ymm11
+	vpand	%ymm15,%ymm1,%ymm1
+
+	vpermq	$0x93,%ymm14,%ymm14
+	vpxor	%ymm9,%ymm9,%ymm9
+	vpermq	$0x93,%ymm11,%ymm11
+
+	vpblendd	$3,%ymm9,%ymm14,%ymm10
+	vpblendd	$3,%ymm14,%ymm11,%ymm14
+	vpaddq	%ymm10,%ymm8,%ymm8
+	vpblendd	$3,%ymm11,%ymm9,%ymm11
+	vpaddq	%ymm14,%ymm1,%ymm1
+	vpaddq	%ymm11,%ymm2,%ymm2
+	vmovdqu	%ymm1,288-192(%rbx)
+	vmovdqu	%ymm2,320-192(%rbx)
+
+	movq	(%rsp),%rax
+	movq	8(%rsp),%r10
+	movq	16(%rsp),%r11
+	movq	24(%rsp),%r12
+	vmovdqu	32(%rsp),%ymm1
+	vmovdqu	64-192(%rbx),%ymm2
+	vmovdqu	96-192(%rbx),%ymm3
+	vmovdqu	128-192(%rbx),%ymm4
+	vmovdqu	160-192(%rbx),%ymm5
+	vmovdqu	192-192(%rbx),%ymm6
+	vmovdqu	224-192(%rbx),%ymm7
+
+	movq	%rax,%r9
+	imull	%ecx,%eax
+	andl	$0x1fffffff,%eax
+	vmovd	%eax,%xmm12
+
+	movq	%rax,%rdx
+	imulq	-128(%r13),%rax
+	vpbroadcastq	%xmm12,%ymm12
+	addq	%rax,%r9
+	movq	%rdx,%rax
+	imulq	8-128(%r13),%rax
+	shrq	$29,%r9
+	addq	%rax,%r10
+	movq	%rdx,%rax
+	imulq	16-128(%r13),%rax
+	addq	%r9,%r10
+	addq	%rax,%r11
+	imulq	24-128(%r13),%rdx
+	addq	%rdx,%r12
+
+	movq	%r10,%rax
+	imull	%ecx,%eax
+	andl	$0x1fffffff,%eax
+
+	movl	$9,%r14d
+	jmp	L$OOP_REDUCE_1024
+
+.p2align	5
+L$OOP_REDUCE_1024:
+	vmovd	%eax,%xmm13
+	vpbroadcastq	%xmm13,%ymm13
+
+	vpmuludq	32-128(%r13),%ymm12,%ymm10
+	movq	%rax,%rdx
+	imulq	-128(%r13),%rax
+	vpaddq	%ymm10,%ymm1,%ymm1
+	addq	%rax,%r10
+	vpmuludq	64-128(%r13),%ymm12,%ymm14
+	movq	%rdx,%rax
+	imulq	8-128(%r13),%rax
+	vpaddq	%ymm14,%ymm2,%ymm2
+	vpmuludq	96-128(%r13),%ymm12,%ymm11
+.byte	0x67
+	addq	%rax,%r11
+.byte	0x67
+	movq	%rdx,%rax
+	imulq	16-128(%r13),%rax
+	shrq	$29,%r10
+	vpaddq	%ymm11,%ymm3,%ymm3
+	vpmuludq	128-128(%r13),%ymm12,%ymm10
+	addq	%rax,%r12
+	addq	%r10,%r11
+	vpaddq	%ymm10,%ymm4,%ymm4
+	vpmuludq	160-128(%r13),%ymm12,%ymm14
+	movq	%r11,%rax
+	imull	%ecx,%eax
+	vpaddq	%ymm14,%ymm5,%ymm5
+	vpmuludq	192-128(%r13),%ymm12,%ymm11
+	andl	$0x1fffffff,%eax
+	vpaddq	%ymm11,%ymm6,%ymm6
+	vpmuludq	224-128(%r13),%ymm12,%ymm10
+	vpaddq	%ymm10,%ymm7,%ymm7
+	vpmuludq	256-128(%r13),%ymm12,%ymm14
+	vmovd	%eax,%xmm12
+
+	vpaddq	%ymm14,%ymm8,%ymm8
+
+	vpbroadcastq	%xmm12,%ymm12
+
+	vpmuludq	32-8-128(%r13),%ymm13,%ymm11
+	vmovdqu	96-8-128(%r13),%ymm14
+	movq	%rax,%rdx
+	imulq	-128(%r13),%rax
+	vpaddq	%ymm11,%ymm1,%ymm1
+	vpmuludq	64-8-128(%r13),%ymm13,%ymm10
+	vmovdqu	128-8-128(%r13),%ymm11
+	addq	%rax,%r11
+	movq	%rdx,%rax
+	imulq	8-128(%r13),%rax
+	vpaddq	%ymm10,%ymm2,%ymm2
+	addq	%r12,%rax
+	shrq	$29,%r11
+	vpmuludq	%ymm13,%ymm14,%ymm14
+	vmovdqu	160-8-128(%r13),%ymm10
+	addq	%r11,%rax
+	vpaddq	%ymm14,%ymm3,%ymm3
+	vpmuludq	%ymm13,%ymm11,%ymm11
+	vmovdqu	192-8-128(%r13),%ymm14
+.byte	0x67
+	movq	%rax,%r12
+	imull	%ecx,%eax
+	vpaddq	%ymm11,%ymm4,%ymm4
+	vpmuludq	%ymm13,%ymm10,%ymm10
+.byte	0xc4,0x41,0x7e,0x6f,0x9d,0x58,0x00,0x00,0x00
+	andl	$0x1fffffff,%eax
+	vpaddq	%ymm10,%ymm5,%ymm5
+	vpmuludq	%ymm13,%ymm14,%ymm14
+	vmovdqu	256-8-128(%r13),%ymm10
+	vpaddq	%ymm14,%ymm6,%ymm6
+	vpmuludq	%ymm13,%ymm11,%ymm11
+	vmovdqu	288-8-128(%r13),%ymm9
+	vmovd	%eax,%xmm0
+	imulq	-128(%r13),%rax
+	vpaddq	%ymm11,%ymm7,%ymm7
+	vpmuludq	%ymm13,%ymm10,%ymm10
+	vmovdqu	32-16-128(%r13),%ymm14
+	vpbroadcastq	%xmm0,%ymm0
+	vpaddq	%ymm10,%ymm8,%ymm8
+	vpmuludq	%ymm13,%ymm9,%ymm9
+	vmovdqu	64-16-128(%r13),%ymm11
+	addq	%rax,%r12
+
+	vmovdqu	32-24-128(%r13),%ymm13
+	vpmuludq	%ymm12,%ymm14,%ymm14
+	vmovdqu	96-16-128(%r13),%ymm10
+	vpaddq	%ymm14,%ymm1,%ymm1
+	vpmuludq	%ymm0,%ymm13,%ymm13
+	vpmuludq	%ymm12,%ymm11,%ymm11
+.byte	0xc4,0x41,0x7e,0x6f,0xb5,0xf0,0xff,0xff,0xff
+	vpaddq	%ymm1,%ymm13,%ymm13
+	vpaddq	%ymm11,%ymm2,%ymm2
+	vpmuludq	%ymm12,%ymm10,%ymm10
+	vmovdqu	160-16-128(%r13),%ymm11
+.byte	0x67
+	vmovq	%xmm13,%rax
+	vmovdqu	%ymm13,(%rsp)
+	vpaddq	%ymm10,%ymm3,%ymm3
+	vpmuludq	%ymm12,%ymm14,%ymm14
+	vmovdqu	192-16-128(%r13),%ymm10
+	vpaddq	%ymm14,%ymm4,%ymm4
+	vpmuludq	%ymm12,%ymm11,%ymm11
+	vmovdqu	224-16-128(%r13),%ymm14
+	vpaddq	%ymm11,%ymm5,%ymm5
+	vpmuludq	%ymm12,%ymm10,%ymm10
+	vmovdqu	256-16-128(%r13),%ymm11
+	vpaddq	%ymm10,%ymm6,%ymm6
+	vpmuludq	%ymm12,%ymm14,%ymm14
+	shrq	$29,%r12
+	vmovdqu	288-16-128(%r13),%ymm10
+	addq	%r12,%rax
+	vpaddq	%ymm14,%ymm7,%ymm7
+	vpmuludq	%ymm12,%ymm11,%ymm11
+
+	movq	%rax,%r9
+	imull	%ecx,%eax
+	vpaddq	%ymm11,%ymm8,%ymm8
+	vpmuludq	%ymm12,%ymm10,%ymm10
+	andl	$0x1fffffff,%eax
+	vmovd	%eax,%xmm12
+	vmovdqu	96-24-128(%r13),%ymm11
+.byte	0x67
+	vpaddq	%ymm10,%ymm9,%ymm9
+	vpbroadcastq	%xmm12,%ymm12
+
+	vpmuludq	64-24-128(%r13),%ymm0,%ymm14
+	vmovdqu	128-24-128(%r13),%ymm10
+	movq	%rax,%rdx
+	imulq	-128(%r13),%rax
+	movq	8(%rsp),%r10
+	vpaddq	%ymm14,%ymm2,%ymm1
+	vpmuludq	%ymm0,%ymm11,%ymm11
+	vmovdqu	160-24-128(%r13),%ymm14
+	addq	%rax,%r9
+	movq	%rdx,%rax
+	imulq	8-128(%r13),%rax
+.byte	0x67
+	shrq	$29,%r9
+	movq	16(%rsp),%r11
+	vpaddq	%ymm11,%ymm3,%ymm2
+	vpmuludq	%ymm0,%ymm10,%ymm10
+	vmovdqu	192-24-128(%r13),%ymm11
+	addq	%rax,%r10
+	movq	%rdx,%rax
+	imulq	16-128(%r13),%rax
+	vpaddq	%ymm10,%ymm4,%ymm3
+	vpmuludq	%ymm0,%ymm14,%ymm14
+	vmovdqu	224-24-128(%r13),%ymm10
+	imulq	24-128(%r13),%rdx
+	addq	%rax,%r11
+	leaq	(%r9,%r10,1),%rax
+	vpaddq	%ymm14,%ymm5,%ymm4
+	vpmuludq	%ymm0,%ymm11,%ymm11
+	vmovdqu	256-24-128(%r13),%ymm14
+	movq	%rax,%r10
+	imull	%ecx,%eax
+	vpmuludq	%ymm0,%ymm10,%ymm10
+	vpaddq	%ymm11,%ymm6,%ymm5
+	vmovdqu	288-24-128(%r13),%ymm11
+	andl	$0x1fffffff,%eax
+	vpaddq	%ymm10,%ymm7,%ymm6
+	vpmuludq	%ymm0,%ymm14,%ymm14
+	addq	24(%rsp),%rdx
+	vpaddq	%ymm14,%ymm8,%ymm7
+	vpmuludq	%ymm0,%ymm11,%ymm11
+	vpaddq	%ymm11,%ymm9,%ymm8
+	vmovq	%r12,%xmm9
+	movq	%rdx,%r12
+
+	decl	%r14d
+	jnz	L$OOP_REDUCE_1024
+	leaq	448(%rsp),%r12
+	vpaddq	%ymm9,%ymm13,%ymm0
+	vpxor	%ymm9,%ymm9,%ymm9
+
+	vpaddq	288-192(%rbx),%ymm0,%ymm0
+	vpaddq	320-448(%r12),%ymm1,%ymm1
+	vpaddq	352-448(%r12),%ymm2,%ymm2
+	vpaddq	384-448(%r12),%ymm3,%ymm3
+	vpaddq	416-448(%r12),%ymm4,%ymm4
+	vpaddq	448-448(%r12),%ymm5,%ymm5
+	vpaddq	480-448(%r12),%ymm6,%ymm6
+	vpaddq	512-448(%r12),%ymm7,%ymm7
+	vpaddq	544-448(%r12),%ymm8,%ymm8
+
+	vpsrlq	$29,%ymm0,%ymm14
+	vpand	%ymm15,%ymm0,%ymm0
+	vpsrlq	$29,%ymm1,%ymm11
+	vpand	%ymm15,%ymm1,%ymm1
+	vpsrlq	$29,%ymm2,%ymm12
+	vpermq	$0x93,%ymm14,%ymm14
+	vpand	%ymm15,%ymm2,%ymm2
+	vpsrlq	$29,%ymm3,%ymm13
+	vpermq	$0x93,%ymm11,%ymm11
+	vpand	%ymm15,%ymm3,%ymm3
+	vpermq	$0x93,%ymm12,%ymm12
+
+	vpblendd	$3,%ymm9,%ymm14,%ymm10
+	vpermq	$0x93,%ymm13,%ymm13
+	vpblendd	$3,%ymm14,%ymm11,%ymm14
+	vpaddq	%ymm10,%ymm0,%ymm0
+	vpblendd	$3,%ymm11,%ymm12,%ymm11
+	vpaddq	%ymm14,%ymm1,%ymm1
+	vpblendd	$3,%ymm12,%ymm13,%ymm12
+	vpaddq	%ymm11,%ymm2,%ymm2
+	vpblendd	$3,%ymm13,%ymm9,%ymm13
+	vpaddq	%ymm12,%ymm3,%ymm3
+	vpaddq	%ymm13,%ymm4,%ymm4
+
+	vpsrlq	$29,%ymm0,%ymm14
+	vpand	%ymm15,%ymm0,%ymm0
+	vpsrlq	$29,%ymm1,%ymm11
+	vpand	%ymm15,%ymm1,%ymm1
+	vpsrlq	$29,%ymm2,%ymm12
+	vpermq	$0x93,%ymm14,%ymm14
+	vpand	%ymm15,%ymm2,%ymm2
+	vpsrlq	$29,%ymm3,%ymm13
+	vpermq	$0x93,%ymm11,%ymm11
+	vpand	%ymm15,%ymm3,%ymm3
+	vpermq	$0x93,%ymm12,%ymm12
+
+	vpblendd	$3,%ymm9,%ymm14,%ymm10
+	vpermq	$0x93,%ymm13,%ymm13
+	vpblendd	$3,%ymm14,%ymm11,%ymm14
+	vpaddq	%ymm10,%ymm0,%ymm0
+	vpblendd	$3,%ymm11,%ymm12,%ymm11
+	vpaddq	%ymm14,%ymm1,%ymm1
+	vmovdqu	%ymm0,0-128(%rdi)
+	vpblendd	$3,%ymm12,%ymm13,%ymm12
+	vpaddq	%ymm11,%ymm2,%ymm2
+	vmovdqu	%ymm1,32-128(%rdi)
+	vpblendd	$3,%ymm13,%ymm9,%ymm13
+	vpaddq	%ymm12,%ymm3,%ymm3
+	vmovdqu	%ymm2,64-128(%rdi)
+	vpaddq	%ymm13,%ymm4,%ymm4
+	vmovdqu	%ymm3,96-128(%rdi)
+	vpsrlq	$29,%ymm4,%ymm14
+	vpand	%ymm15,%ymm4,%ymm4
+	vpsrlq	$29,%ymm5,%ymm11
+	vpand	%ymm15,%ymm5,%ymm5
+	vpsrlq	$29,%ymm6,%ymm12
+	vpermq	$0x93,%ymm14,%ymm14
+	vpand	%ymm15,%ymm6,%ymm6
+	vpsrlq	$29,%ymm7,%ymm13
+	vpermq	$0x93,%ymm11,%ymm11
+	vpand	%ymm15,%ymm7,%ymm7
+	vpsrlq	$29,%ymm8,%ymm0
+	vpermq	$0x93,%ymm12,%ymm12
+	vpand	%ymm15,%ymm8,%ymm8
+	vpermq	$0x93,%ymm13,%ymm13
+
+	vpblendd	$3,%ymm9,%ymm14,%ymm10
+	vpermq	$0x93,%ymm0,%ymm0
+	vpblendd	$3,%ymm14,%ymm11,%ymm14
+	vpaddq	%ymm10,%ymm4,%ymm4
+	vpblendd	$3,%ymm11,%ymm12,%ymm11
+	vpaddq	%ymm14,%ymm5,%ymm5
+	vpblendd	$3,%ymm12,%ymm13,%ymm12
+	vpaddq	%ymm11,%ymm6,%ymm6
+	vpblendd	$3,%ymm13,%ymm0,%ymm13
+	vpaddq	%ymm12,%ymm7,%ymm7
+	vpaddq	%ymm13,%ymm8,%ymm8
+
+	vpsrlq	$29,%ymm4,%ymm14
+	vpand	%ymm15,%ymm4,%ymm4
+	vpsrlq	$29,%ymm5,%ymm11
+	vpand	%ymm15,%ymm5,%ymm5
+	vpsrlq	$29,%ymm6,%ymm12
+	vpermq	$0x93,%ymm14,%ymm14
+	vpand	%ymm15,%ymm6,%ymm6
+	vpsrlq	$29,%ymm7,%ymm13
+	vpermq	$0x93,%ymm11,%ymm11
+	vpand	%ymm15,%ymm7,%ymm7
+	vpsrlq	$29,%ymm8,%ymm0
+	vpermq	$0x93,%ymm12,%ymm12
+	vpand	%ymm15,%ymm8,%ymm8
+	vpermq	$0x93,%ymm13,%ymm13
+
+	vpblendd	$3,%ymm9,%ymm14,%ymm10
+	vpermq	$0x93,%ymm0,%ymm0
+	vpblendd	$3,%ymm14,%ymm11,%ymm14
+	vpaddq	%ymm10,%ymm4,%ymm4
+	vpblendd	$3,%ymm11,%ymm12,%ymm11
+	vpaddq	%ymm14,%ymm5,%ymm5
+	vmovdqu	%ymm4,128-128(%rdi)
+	vpblendd	$3,%ymm12,%ymm13,%ymm12
+	vpaddq	%ymm11,%ymm6,%ymm6
+	vmovdqu	%ymm5,160-128(%rdi)
+	vpblendd	$3,%ymm13,%ymm0,%ymm13
+	vpaddq	%ymm12,%ymm7,%ymm7
+	vmovdqu	%ymm6,192-128(%rdi)
+	vpaddq	%ymm13,%ymm8,%ymm8
+	vmovdqu	%ymm7,224-128(%rdi)
+	vmovdqu	%ymm8,256-128(%rdi)
+
+	movq	%rdi,%rsi
+	decl	%r8d
+	jne	L$OOP_GRANDE_SQR_1024
+
+	vzeroall
+	movq	%rbp,%rax
+
+	movq	-48(%rax),%r15
+
+	movq	-40(%rax),%r14
+
+	movq	-32(%rax),%r13
+
+	movq	-24(%rax),%r12
+
+	movq	-16(%rax),%rbp
+
+	movq	-8(%rax),%rbx
+
+	leaq	(%rax),%rsp
+
+L$sqr_1024_epilogue:
 	.byte	0xf3,0xc3
 
 
-.globl	_rsaz_1024_sqr_avx2
-.private_extern _rsaz_1024_sqr_avx2
 .globl	_rsaz_1024_mul_avx2
 .private_extern _rsaz_1024_mul_avx2
-.globl	_rsaz_1024_norm2red_avx2
-.private_extern _rsaz_1024_norm2red_avx2
+
+.p2align	6
+_rsaz_1024_mul_avx2:
+
+	leaq	(%rsp),%rax
+
+	pushq	%rbx
+
+	pushq	%rbp
+
+	pushq	%r12
+
+	pushq	%r13
+
+	pushq	%r14
+
+	pushq	%r15
+
+	movq	%rax,%rbp
+
+	vzeroall
+	movq	%rdx,%r13
+	subq	$64,%rsp
+
+
+
+
+
+
+.byte	0x67,0x67
+	movq	%rsi,%r15
+	andq	$4095,%r15
+	addq	$320,%r15
+	shrq	$12,%r15
+	movq	%rsi,%r15
+	cmovnzq	%r13,%rsi
+	cmovnzq	%r15,%r13
+
+	movq	%rcx,%r15
+	subq	$-128,%rsi
+	subq	$-128,%rcx
+	subq	$-128,%rdi
+
+	andq	$4095,%r15
+	addq	$320,%r15
+.byte	0x67,0x67
+	shrq	$12,%r15
+	jz	L$mul_1024_no_n_copy
+
+
+
+
+
+	subq	$320,%rsp
+	vmovdqu	0-128(%rcx),%ymm0
+	andq	$-512,%rsp
+	vmovdqu	32-128(%rcx),%ymm1
+	vmovdqu	64-128(%rcx),%ymm2
+	vmovdqu	96-128(%rcx),%ymm3
+	vmovdqu	128-128(%rcx),%ymm4
+	vmovdqu	160-128(%rcx),%ymm5
+	vmovdqu	192-128(%rcx),%ymm6
+	vmovdqu	224-128(%rcx),%ymm7
+	vmovdqu	256-128(%rcx),%ymm8
+	leaq	64+128(%rsp),%rcx
+	vmovdqu	%ymm0,0-128(%rcx)
+	vpxor	%ymm0,%ymm0,%ymm0
+	vmovdqu	%ymm1,32-128(%rcx)
+	vpxor	%ymm1,%ymm1,%ymm1
+	vmovdqu	%ymm2,64-128(%rcx)
+	vpxor	%ymm2,%ymm2,%ymm2
+	vmovdqu	%ymm3,96-128(%rcx)
+	vpxor	%ymm3,%ymm3,%ymm3
+	vmovdqu	%ymm4,128-128(%rcx)
+	vpxor	%ymm4,%ymm4,%ymm4
+	vmovdqu	%ymm5,160-128(%rcx)
+	vpxor	%ymm5,%ymm5,%ymm5
+	vmovdqu	%ymm6,192-128(%rcx)
+	vpxor	%ymm6,%ymm6,%ymm6
+	vmovdqu	%ymm7,224-128(%rcx)
+	vpxor	%ymm7,%ymm7,%ymm7
+	vmovdqu	%ymm8,256-128(%rcx)
+	vmovdqa	%ymm0,%ymm8
+	vmovdqu	%ymm9,288-128(%rcx)
+L$mul_1024_no_n_copy:
+	andq	$-64,%rsp
+
+	movq	(%r13),%rbx
+	vpbroadcastq	(%r13),%ymm10
+	vmovdqu	%ymm0,(%rsp)
+	xorq	%r9,%r9
+.byte	0x67
+	xorq	%r10,%r10
+	xorq	%r11,%r11
+	xorq	%r12,%r12
+
+	vmovdqu	L$and_mask(%rip),%ymm15
+	movl	$9,%r14d
+	vmovdqu	%ymm9,288-128(%rdi)
+	jmp	L$oop_mul_1024
+
+.p2align	5
+L$oop_mul_1024:
+	vpsrlq	$29,%ymm3,%ymm9
+	movq	%rbx,%rax
+	imulq	-128(%rsi),%rax
+	addq	%r9,%rax
+	movq	%rbx,%r10
+	imulq	8-128(%rsi),%r10
+	addq	8(%rsp),%r10
+
+	movq	%rax,%r9
+	imull	%r8d,%eax
+	andl	$0x1fffffff,%eax
+
+	movq	%rbx,%r11
+	imulq	16-128(%rsi),%r11
+	addq	16(%rsp),%r11
+
+	movq	%rbx,%r12
+	imulq	24-128(%rsi),%r12
+	addq	24(%rsp),%r12
+	vpmuludq	32-128(%rsi),%ymm10,%ymm0
+	vmovd	%eax,%xmm11
+	vpaddq	%ymm0,%ymm1,%ymm1
+	vpmuludq	64-128(%rsi),%ymm10,%ymm12
+	vpbroadcastq	%xmm11,%ymm11
+	vpaddq	%ymm12,%ymm2,%ymm2
+	vpmuludq	96-128(%rsi),%ymm10,%ymm13
+	vpand	%ymm15,%ymm3,%ymm3
+	vpaddq	%ymm13,%ymm3,%ymm3
+	vpmuludq	128-128(%rsi),%ymm10,%ymm0
+	vpaddq	%ymm0,%ymm4,%ymm4
+	vpmuludq	160-128(%rsi),%ymm10,%ymm12
+	vpaddq	%ymm12,%ymm5,%ymm5
+	vpmuludq	192-128(%rsi),%ymm10,%ymm13
+	vpaddq	%ymm13,%ymm6,%ymm6
+	vpmuludq	224-128(%rsi),%ymm10,%ymm0
+	vpermq	$0x93,%ymm9,%ymm9
+	vpaddq	%ymm0,%ymm7,%ymm7
+	vpmuludq	256-128(%rsi),%ymm10,%ymm12
+	vpbroadcastq	8(%r13),%ymm10
+	vpaddq	%ymm12,%ymm8,%ymm8
+
+	movq	%rax,%rdx
+	imulq	-128(%rcx),%rax
+	addq	%rax,%r9
+	movq	%rdx,%rax
+	imulq	8-128(%rcx),%rax
+	addq	%rax,%r10
+	movq	%rdx,%rax
+	imulq	16-128(%rcx),%rax
+	addq	%rax,%r11
+	shrq	$29,%r9
+	imulq	24-128(%rcx),%rdx
+	addq	%rdx,%r12
+	addq	%r9,%r10
+
+	vpmuludq	32-128(%rcx),%ymm11,%ymm13
+	vmovq	%xmm10,%rbx
+	vpaddq	%ymm13,%ymm1,%ymm1
+	vpmuludq	64-128(%rcx),%ymm11,%ymm0
+	vpaddq	%ymm0,%ymm2,%ymm2
+	vpmuludq	96-128(%rcx),%ymm11,%ymm12
+	vpaddq	%ymm12,%ymm3,%ymm3
+	vpmuludq	128-128(%rcx),%ymm11,%ymm13
+	vpaddq	%ymm13,%ymm4,%ymm4
+	vpmuludq	160-128(%rcx),%ymm11,%ymm0
+	vpaddq	%ymm0,%ymm5,%ymm5
+	vpmuludq	192-128(%rcx),%ymm11,%ymm12
+	vpaddq	%ymm12,%ymm6,%ymm6
+	vpmuludq	224-128(%rcx),%ymm11,%ymm13
+	vpblendd	$3,%ymm14,%ymm9,%ymm9
+	vpaddq	%ymm13,%ymm7,%ymm7
+	vpmuludq	256-128(%rcx),%ymm11,%ymm0
+	vpaddq	%ymm9,%ymm3,%ymm3
+	vpaddq	%ymm0,%ymm8,%ymm8
+
+	movq	%rbx,%rax
+	imulq	-128(%rsi),%rax
+	addq	%rax,%r10
+	vmovdqu	-8+32-128(%rsi),%ymm12
+	movq	%rbx,%rax
+	imulq	8-128(%rsi),%rax
+	addq	%rax,%r11
+	vmovdqu	-8+64-128(%rsi),%ymm13
+
+	movq	%r10,%rax
+	imull	%r8d,%eax
+	andl	$0x1fffffff,%eax
+
+	imulq	16-128(%rsi),%rbx
+	addq	%rbx,%r12
+	vpmuludq	%ymm10,%ymm12,%ymm12
+	vmovd	%eax,%xmm11
+	vmovdqu	-8+96-128(%rsi),%ymm0
+	vpaddq	%ymm12,%ymm1,%ymm1
+	vpmuludq	%ymm10,%ymm13,%ymm13
+	vpbroadcastq	%xmm11,%ymm11
+	vmovdqu	-8+128-128(%rsi),%ymm12
+	vpaddq	%ymm13,%ymm2,%ymm2
+	vpmuludq	%ymm10,%ymm0,%ymm0
+	vmovdqu	-8+160-128(%rsi),%ymm13
+	vpaddq	%ymm0,%ymm3,%ymm3
+	vpmuludq	%ymm10,%ymm12,%ymm12
+	vmovdqu	-8+192-128(%rsi),%ymm0
+	vpaddq	%ymm12,%ymm4,%ymm4
+	vpmuludq	%ymm10,%ymm13,%ymm13
+	vmovdqu	-8+224-128(%rsi),%ymm12
+	vpaddq	%ymm13,%ymm5,%ymm5
+	vpmuludq	%ymm10,%ymm0,%ymm0
+	vmovdqu	-8+256-128(%rsi),%ymm13
+	vpaddq	%ymm0,%ymm6,%ymm6
+	vpmuludq	%ymm10,%ymm12,%ymm12
+	vmovdqu	-8+288-128(%rsi),%ymm9
+	vpaddq	%ymm12,%ymm7,%ymm7
+	vpmuludq	%ymm10,%ymm13,%ymm13
+	vpaddq	%ymm13,%ymm8,%ymm8
+	vpmuludq	%ymm10,%ymm9,%ymm9
+	vpbroadcastq	16(%r13),%ymm10
+
+	movq	%rax,%rdx
+	imulq	-128(%rcx),%rax
+	addq	%rax,%r10
+	vmovdqu	-8+32-128(%rcx),%ymm0
+	movq	%rdx,%rax
+	imulq	8-128(%rcx),%rax
+	addq	%rax,%r11
+	vmovdqu	-8+64-128(%rcx),%ymm12
+	shrq	$29,%r10
+	imulq	16-128(%rcx),%rdx
+	addq	%rdx,%r12
+	addq	%r10,%r11
+
+	vpmuludq	%ymm11,%ymm0,%ymm0
+	vmovq	%xmm10,%rbx
+	vmovdqu	-8+96-128(%rcx),%ymm13
+	vpaddq	%ymm0,%ymm1,%ymm1
+	vpmuludq	%ymm11,%ymm12,%ymm12
+	vmovdqu	-8+128-128(%rcx),%ymm0
+	vpaddq	%ymm12,%ymm2,%ymm2
+	vpmuludq	%ymm11,%ymm13,%ymm13
+	vmovdqu	-8+160-128(%rcx),%ymm12
+	vpaddq	%ymm13,%ymm3,%ymm3
+	vpmuludq	%ymm11,%ymm0,%ymm0
+	vmovdqu	-8+192-128(%rcx),%ymm13
+	vpaddq	%ymm0,%ymm4,%ymm4
+	vpmuludq	%ymm11,%ymm12,%ymm12
+	vmovdqu	-8+224-128(%rcx),%ymm0
+	vpaddq	%ymm12,%ymm5,%ymm5
+	vpmuludq	%ymm11,%ymm13,%ymm13
+	vmovdqu	-8+256-128(%rcx),%ymm12
+	vpaddq	%ymm13,%ymm6,%ymm6
+	vpmuludq	%ymm11,%ymm0,%ymm0
+	vmovdqu	-8+288-128(%rcx),%ymm13
+	vpaddq	%ymm0,%ymm7,%ymm7
+	vpmuludq	%ymm11,%ymm12,%ymm12
+	vpaddq	%ymm12,%ymm8,%ymm8
+	vpmuludq	%ymm11,%ymm13,%ymm13
+	vpaddq	%ymm13,%ymm9,%ymm9
+
+	vmovdqu	-16+32-128(%rsi),%ymm0
+	movq	%rbx,%rax
+	imulq	-128(%rsi),%rax
+	addq	%r11,%rax
+
+	vmovdqu	-16+64-128(%rsi),%ymm12
+	movq	%rax,%r11
+	imull	%r8d,%eax
+	andl	$0x1fffffff,%eax
+
+	imulq	8-128(%rsi),%rbx
+	addq	%rbx,%r12
+	vpmuludq	%ymm10,%ymm0,%ymm0
+	vmovd	%eax,%xmm11
+	vmovdqu	-16+96-128(%rsi),%ymm13
+	vpaddq	%ymm0,%ymm1,%ymm1
+	vpmuludq	%ymm10,%ymm12,%ymm12
+	vpbroadcastq	%xmm11,%ymm11
+	vmovdqu	-16+128-128(%rsi),%ymm0
+	vpaddq	%ymm12,%ymm2,%ymm2
+	vpmuludq	%ymm10,%ymm13,%ymm13
+	vmovdqu	-16+160-128(%rsi),%ymm12
+	vpaddq	%ymm13,%ymm3,%ymm3
+	vpmuludq	%ymm10,%ymm0,%ymm0
+	vmovdqu	-16+192-128(%rsi),%ymm13
+	vpaddq	%ymm0,%ymm4,%ymm4
+	vpmuludq	%ymm10,%ymm12,%ymm12
+	vmovdqu	-16+224-128(%rsi),%ymm0
+	vpaddq	%ymm12,%ymm5,%ymm5
+	vpmuludq	%ymm10,%ymm13,%ymm13
+	vmovdqu	-16+256-128(%rsi),%ymm12
+	vpaddq	%ymm13,%ymm6,%ymm6
+	vpmuludq	%ymm10,%ymm0,%ymm0
+	vmovdqu	-16+288-128(%rsi),%ymm13
+	vpaddq	%ymm0,%ymm7,%ymm7
+	vpmuludq	%ymm10,%ymm12,%ymm12
+	vpaddq	%ymm12,%ymm8,%ymm8
+	vpmuludq	%ymm10,%ymm13,%ymm13
+	vpbroadcastq	24(%r13),%ymm10
+	vpaddq	%ymm13,%ymm9,%ymm9
+
+	vmovdqu	-16+32-128(%rcx),%ymm0
+	movq	%rax,%rdx
+	imulq	-128(%rcx),%rax
+	addq	%rax,%r11
+	vmovdqu	-16+64-128(%rcx),%ymm12
+	imulq	8-128(%rcx),%rdx
+	addq	%rdx,%r12
+	shrq	$29,%r11
+
+	vpmuludq	%ymm11,%ymm0,%ymm0
+	vmovq	%xmm10,%rbx
+	vmovdqu	-16+96-128(%rcx),%ymm13
+	vpaddq	%ymm0,%ymm1,%ymm1
+	vpmuludq	%ymm11,%ymm12,%ymm12
+	vmovdqu	-16+128-128(%rcx),%ymm0
+	vpaddq	%ymm12,%ymm2,%ymm2
+	vpmuludq	%ymm11,%ymm13,%ymm13
+	vmovdqu	-16+160-128(%rcx),%ymm12
+	vpaddq	%ymm13,%ymm3,%ymm3
+	vpmuludq	%ymm11,%ymm0,%ymm0
+	vmovdqu	-16+192-128(%rcx),%ymm13
+	vpaddq	%ymm0,%ymm4,%ymm4
+	vpmuludq	%ymm11,%ymm12,%ymm12
+	vmovdqu	-16+224-128(%rcx),%ymm0
+	vpaddq	%ymm12,%ymm5,%ymm5
+	vpmuludq	%ymm11,%ymm13,%ymm13
+	vmovdqu	-16+256-128(%rcx),%ymm12
+	vpaddq	%ymm13,%ymm6,%ymm6
+	vpmuludq	%ymm11,%ymm0,%ymm0
+	vmovdqu	-16+288-128(%rcx),%ymm13
+	vpaddq	%ymm0,%ymm7,%ymm7
+	vpmuludq	%ymm11,%ymm12,%ymm12
+	vmovdqu	-24+32-128(%rsi),%ymm0
+	vpaddq	%ymm12,%ymm8,%ymm8
+	vpmuludq	%ymm11,%ymm13,%ymm13
+	vmovdqu	-24+64-128(%rsi),%ymm12
+	vpaddq	%ymm13,%ymm9,%ymm9
+
+	addq	%r11,%r12
+	imulq	-128(%rsi),%rbx
+	addq	%rbx,%r12
+
+	movq	%r12,%rax
+	imull	%r8d,%eax
+	andl	$0x1fffffff,%eax
+
+	vpmuludq	%ymm10,%ymm0,%ymm0
+	vmovd	%eax,%xmm11
+	vmovdqu	-24+96-128(%rsi),%ymm13
+	vpaddq	%ymm0,%ymm1,%ymm1
+	vpmuludq	%ymm10,%ymm12,%ymm12
+	vpbroadcastq	%xmm11,%ymm11
+	vmovdqu	-24+128-128(%rsi),%ymm0
+	vpaddq	%ymm12,%ymm2,%ymm2
+	vpmuludq	%ymm10,%ymm13,%ymm13
+	vmovdqu	-24+160-128(%rsi),%ymm12
+	vpaddq	%ymm13,%ymm3,%ymm3
+	vpmuludq	%ymm10,%ymm0,%ymm0
+	vmovdqu	-24+192-128(%rsi),%ymm13
+	vpaddq	%ymm0,%ymm4,%ymm4
+	vpmuludq	%ymm10,%ymm12,%ymm12
+	vmovdqu	-24+224-128(%rsi),%ymm0
+	vpaddq	%ymm12,%ymm5,%ymm5
+	vpmuludq	%ymm10,%ymm13,%ymm13
+	vmovdqu	-24+256-128(%rsi),%ymm12
+	vpaddq	%ymm13,%ymm6,%ymm6
+	vpmuludq	%ymm10,%ymm0,%ymm0
+	vmovdqu	-24+288-128(%rsi),%ymm13
+	vpaddq	%ymm0,%ymm7,%ymm7
+	vpmuludq	%ymm10,%ymm12,%ymm12
+	vpaddq	%ymm12,%ymm8,%ymm8
+	vpmuludq	%ymm10,%ymm13,%ymm13
+	vpbroadcastq	32(%r13),%ymm10
+	vpaddq	%ymm13,%ymm9,%ymm9
+	addq	$32,%r13
+
+	vmovdqu	-24+32-128(%rcx),%ymm0
+	imulq	-128(%rcx),%rax
+	addq	%rax,%r12
+	shrq	$29,%r12
+
+	vmovdqu	-24+64-128(%rcx),%ymm12
+	vpmuludq	%ymm11,%ymm0,%ymm0
+	vmovq	%xmm10,%rbx
+	vmovdqu	-24+96-128(%rcx),%ymm13
+	vpaddq	%ymm0,%ymm1,%ymm0
+	vpmuludq	%ymm11,%ymm12,%ymm12
+	vmovdqu	%ymm0,(%rsp)
+	vpaddq	%ymm12,%ymm2,%ymm1
+	vmovdqu	-24+128-128(%rcx),%ymm0
+	vpmuludq	%ymm11,%ymm13,%ymm13
+	vmovdqu	-24+160-128(%rcx),%ymm12
+	vpaddq	%ymm13,%ymm3,%ymm2
+	vpmuludq	%ymm11,%ymm0,%ymm0
+	vmovdqu	-24+192-128(%rcx),%ymm13
+	vpaddq	%ymm0,%ymm4,%ymm3
+	vpmuludq	%ymm11,%ymm12,%ymm12
+	vmovdqu	-24+224-128(%rcx),%ymm0
+	vpaddq	%ymm12,%ymm5,%ymm4
+	vpmuludq	%ymm11,%ymm13,%ymm13
+	vmovdqu	-24+256-128(%rcx),%ymm12
+	vpaddq	%ymm13,%ymm6,%ymm5
+	vpmuludq	%ymm11,%ymm0,%ymm0
+	vmovdqu	-24+288-128(%rcx),%ymm13
+	movq	%r12,%r9
+	vpaddq	%ymm0,%ymm7,%ymm6
+	vpmuludq	%ymm11,%ymm12,%ymm12
+	addq	(%rsp),%r9
+	vpaddq	%ymm12,%ymm8,%ymm7
+	vpmuludq	%ymm11,%ymm13,%ymm13
+	vmovq	%r12,%xmm12
+	vpaddq	%ymm13,%ymm9,%ymm8
+
+	decl	%r14d
+	jnz	L$oop_mul_1024
+	vpermq	$0,%ymm15,%ymm15
+	vpaddq	(%rsp),%ymm12,%ymm0
+
+	vpsrlq	$29,%ymm0,%ymm12
+	vpand	%ymm15,%ymm0,%ymm0
+	vpsrlq	$29,%ymm1,%ymm13
+	vpand	%ymm15,%ymm1,%ymm1
+	vpsrlq	$29,%ymm2,%ymm10
+	vpermq	$0x93,%ymm12,%ymm12
+	vpand	%ymm15,%ymm2,%ymm2
+	vpsrlq	$29,%ymm3,%ymm11
+	vpermq	$0x93,%ymm13,%ymm13
+	vpand	%ymm15,%ymm3,%ymm3
+
+	vpblendd	$3,%ymm14,%ymm12,%ymm9
+	vpermq	$0x93,%ymm10,%ymm10
+	vpblendd	$3,%ymm12,%ymm13,%ymm12
+	vpermq	$0x93,%ymm11,%ymm11
+	vpaddq	%ymm9,%ymm0,%ymm0
+	vpblendd	$3,%ymm13,%ymm10,%ymm13
+	vpaddq	%ymm12,%ymm1,%ymm1
+	vpblendd	$3,%ymm10,%ymm11,%ymm10
+	vpaddq	%ymm13,%ymm2,%ymm2
+	vpblendd	$3,%ymm11,%ymm14,%ymm11
+	vpaddq	%ymm10,%ymm3,%ymm3
+	vpaddq	%ymm11,%ymm4,%ymm4
+
+	vpsrlq	$29,%ymm0,%ymm12
+	vpand	%ymm15,%ymm0,%ymm0
+	vpsrlq	$29,%ymm1,%ymm13
+	vpand	%ymm15,%ymm1,%ymm1
+	vpsrlq	$29,%ymm2,%ymm10
+	vpermq	$0x93,%ymm12,%ymm12
+	vpand	%ymm15,%ymm2,%ymm2
+	vpsrlq	$29,%ymm3,%ymm11
+	vpermq	$0x93,%ymm13,%ymm13
+	vpand	%ymm15,%ymm3,%ymm3
+	vpermq	$0x93,%ymm10,%ymm10
+
+	vpblendd	$3,%ymm14,%ymm12,%ymm9
+	vpermq	$0x93,%ymm11,%ymm11
+	vpblendd	$3,%ymm12,%ymm13,%ymm12
+	vpaddq	%ymm9,%ymm0,%ymm0
+	vpblendd	$3,%ymm13,%ymm10,%ymm13
+	vpaddq	%ymm12,%ymm1,%ymm1
+	vpblendd	$3,%ymm10,%ymm11,%ymm10
+	vpaddq	%ymm13,%ymm2,%ymm2
+	vpblendd	$3,%ymm11,%ymm14,%ymm11
+	vpaddq	%ymm10,%ymm3,%ymm3
+	vpaddq	%ymm11,%ymm4,%ymm4
+
+	vmovdqu	%ymm0,0-128(%rdi)
+	vmovdqu	%ymm1,32-128(%rdi)
+	vmovdqu	%ymm2,64-128(%rdi)
+	vmovdqu	%ymm3,96-128(%rdi)
+	vpsrlq	$29,%ymm4,%ymm12
+	vpand	%ymm15,%ymm4,%ymm4
+	vpsrlq	$29,%ymm5,%ymm13
+	vpand	%ymm15,%ymm5,%ymm5
+	vpsrlq	$29,%ymm6,%ymm10
+	vpermq	$0x93,%ymm12,%ymm12
+	vpand	%ymm15,%ymm6,%ymm6
+	vpsrlq	$29,%ymm7,%ymm11
+	vpermq	$0x93,%ymm13,%ymm13
+	vpand	%ymm15,%ymm7,%ymm7
+	vpsrlq	$29,%ymm8,%ymm0
+	vpermq	$0x93,%ymm10,%ymm10
+	vpand	%ymm15,%ymm8,%ymm8
+	vpermq	$0x93,%ymm11,%ymm11
+
+	vpblendd	$3,%ymm14,%ymm12,%ymm9
+	vpermq	$0x93,%ymm0,%ymm0
+	vpblendd	$3,%ymm12,%ymm13,%ymm12
+	vpaddq	%ymm9,%ymm4,%ymm4
+	vpblendd	$3,%ymm13,%ymm10,%ymm13
+	vpaddq	%ymm12,%ymm5,%ymm5
+	vpblendd	$3,%ymm10,%ymm11,%ymm10
+	vpaddq	%ymm13,%ymm6,%ymm6
+	vpblendd	$3,%ymm11,%ymm0,%ymm11
+	vpaddq	%ymm10,%ymm7,%ymm7
+	vpaddq	%ymm11,%ymm8,%ymm8
+
+	vpsrlq	$29,%ymm4,%ymm12
+	vpand	%ymm15,%ymm4,%ymm4
+	vpsrlq	$29,%ymm5,%ymm13
+	vpand	%ymm15,%ymm5,%ymm5
+	vpsrlq	$29,%ymm6,%ymm10
+	vpermq	$0x93,%ymm12,%ymm12
+	vpand	%ymm15,%ymm6,%ymm6
+	vpsrlq	$29,%ymm7,%ymm11
+	vpermq	$0x93,%ymm13,%ymm13
+	vpand	%ymm15,%ymm7,%ymm7
+	vpsrlq	$29,%ymm8,%ymm0
+	vpermq	$0x93,%ymm10,%ymm10
+	vpand	%ymm15,%ymm8,%ymm8
+	vpermq	$0x93,%ymm11,%ymm11
+
+	vpblendd	$3,%ymm14,%ymm12,%ymm9
+	vpermq	$0x93,%ymm0,%ymm0
+	vpblendd	$3,%ymm12,%ymm13,%ymm12
+	vpaddq	%ymm9,%ymm4,%ymm4
+	vpblendd	$3,%ymm13,%ymm10,%ymm13
+	vpaddq	%ymm12,%ymm5,%ymm5
+	vpblendd	$3,%ymm10,%ymm11,%ymm10
+	vpaddq	%ymm13,%ymm6,%ymm6
+	vpblendd	$3,%ymm11,%ymm0,%ymm11
+	vpaddq	%ymm10,%ymm7,%ymm7
+	vpaddq	%ymm11,%ymm8,%ymm8
+
+	vmovdqu	%ymm4,128-128(%rdi)
+	vmovdqu	%ymm5,160-128(%rdi)
+	vmovdqu	%ymm6,192-128(%rdi)
+	vmovdqu	%ymm7,224-128(%rdi)
+	vmovdqu	%ymm8,256-128(%rdi)
+	vzeroupper
+
+	movq	%rbp,%rax
+
+	movq	-48(%rax),%r15
+
+	movq	-40(%rax),%r14
+
+	movq	-32(%rax),%r13
+
+	movq	-24(%rax),%r12
+
+	movq	-16(%rax),%rbp
+
+	movq	-8(%rax),%rbx
+
+	leaq	(%rax),%rsp
+
+L$mul_1024_epilogue:
+	.byte	0xf3,0xc3
+
+
 .globl	_rsaz_1024_red2norm_avx2
 .private_extern _rsaz_1024_red2norm_avx2
+
+.p2align	5
+_rsaz_1024_red2norm_avx2:
+	subq	$-128,%rsi
+	xorq	%rax,%rax
+	movq	-128(%rsi),%r8
+	movq	-120(%rsi),%r9
+	movq	-112(%rsi),%r10
+	shlq	$0,%r8
+	shlq	$29,%r9
+	movq	%r10,%r11
+	shlq	$58,%r10
+	shrq	$6,%r11
+	addq	%r8,%rax
+	addq	%r9,%rax
+	addq	%r10,%rax
+	adcq	$0,%r11
+	movq	%rax,0(%rdi)
+	movq	%r11,%rax
+	movq	-104(%rsi),%r8
+	movq	-96(%rsi),%r9
+	shlq	$23,%r8
+	movq	%r9,%r10
+	shlq	$52,%r9
+	shrq	$12,%r10
+	addq	%r8,%rax
+	addq	%r9,%rax
+	adcq	$0,%r10
+	movq	%rax,8(%rdi)
+	movq	%r10,%rax
+	movq	-88(%rsi),%r11
+	movq	-80(%rsi),%r8
+	shlq	$17,%r11
+	movq	%r8,%r9
+	shlq	$46,%r8
+	shrq	$18,%r9
+	addq	%r11,%rax
+	addq	%r8,%rax
+	adcq	$0,%r9
+	movq	%rax,16(%rdi)
+	movq	%r9,%rax
+	movq	-72(%rsi),%r10
+	movq	-64(%rsi),%r11
+	shlq	$11,%r10
+	movq	%r11,%r8
+	shlq	$40,%r11
+	shrq	$24,%r8
+	addq	%r10,%rax
+	addq	%r11,%rax
+	adcq	$0,%r8
+	movq	%rax,24(%rdi)
+	movq	%r8,%rax
+	movq	-56(%rsi),%r9
+	movq	-48(%rsi),%r10
+	movq	-40(%rsi),%r11
+	shlq	$5,%r9
+	shlq	$34,%r10
+	movq	%r11,%r8
+	shlq	$63,%r11
+	shrq	$1,%r8
+	addq	%r9,%rax
+	addq	%r10,%rax
+	addq	%r11,%rax
+	adcq	$0,%r8
+	movq	%rax,32(%rdi)
+	movq	%r8,%rax
+	movq	-32(%rsi),%r9
+	movq	-24(%rsi),%r10
+	shlq	$28,%r9
+	movq	%r10,%r11
+	shlq	$57,%r10
+	shrq	$7,%r11
+	addq	%r9,%rax
+	addq	%r10,%rax
+	adcq	$0,%r11
+	movq	%rax,40(%rdi)
+	movq	%r11,%rax
+	movq	-16(%rsi),%r8
+	movq	-8(%rsi),%r9
+	shlq	$22,%r8
+	movq	%r9,%r10
+	shlq	$51,%r9
+	shrq	$13,%r10
+	addq	%r8,%rax
+	addq	%r9,%rax
+	adcq	$0,%r10
+	movq	%rax,48(%rdi)
+	movq	%r10,%rax
+	movq	0(%rsi),%r11
+	movq	8(%rsi),%r8
+	shlq	$16,%r11
+	movq	%r8,%r9
+	shlq	$45,%r8
+	shrq	$19,%r9
+	addq	%r11,%rax
+	addq	%r8,%rax
+	adcq	$0,%r9
+	movq	%rax,56(%rdi)
+	movq	%r9,%rax
+	movq	16(%rsi),%r10
+	movq	24(%rsi),%r11
+	shlq	$10,%r10
+	movq	%r11,%r8
+	shlq	$39,%r11
+	shrq	$25,%r8
+	addq	%r10,%rax
+	addq	%r11,%rax
+	adcq	$0,%r8
+	movq	%rax,64(%rdi)
+	movq	%r8,%rax
+	movq	32(%rsi),%r9
+	movq	40(%rsi),%r10
+	movq	48(%rsi),%r11
+	shlq	$4,%r9
+	shlq	$33,%r10
+	movq	%r11,%r8
+	shlq	$62,%r11
+	shrq	$2,%r8
+	addq	%r9,%rax
+	addq	%r10,%rax
+	addq	%r11,%rax
+	adcq	$0,%r8
+	movq	%rax,72(%rdi)
+	movq	%r8,%rax
+	movq	56(%rsi),%r9
+	movq	64(%rsi),%r10
+	shlq	$27,%r9
+	movq	%r10,%r11
+	shlq	$56,%r10
+	shrq	$8,%r11
+	addq	%r9,%rax
+	addq	%r10,%rax
+	adcq	$0,%r11
+	movq	%rax,80(%rdi)
+	movq	%r11,%rax
+	movq	72(%rsi),%r8
+	movq	80(%rsi),%r9
+	shlq	$21,%r8
+	movq	%r9,%r10
+	shlq	$50,%r9
+	shrq	$14,%r10
+	addq	%r8,%rax
+	addq	%r9,%rax
+	adcq	$0,%r10
+	movq	%rax,88(%rdi)
+	movq	%r10,%rax
+	movq	88(%rsi),%r11
+	movq	96(%rsi),%r8
+	shlq	$15,%r11
+	movq	%r8,%r9
+	shlq	$44,%r8
+	shrq	$20,%r9
+	addq	%r11,%rax
+	addq	%r8,%rax
+	adcq	$0,%r9
+	movq	%rax,96(%rdi)
+	movq	%r9,%rax
+	movq	104(%rsi),%r10
+	movq	112(%rsi),%r11
+	shlq	$9,%r10
+	movq	%r11,%r8
+	shlq	$38,%r11
+	shrq	$26,%r8
+	addq	%r10,%rax
+	addq	%r11,%rax
+	adcq	$0,%r8
+	movq	%rax,104(%rdi)
+	movq	%r8,%rax
+	movq	120(%rsi),%r9
+	movq	128(%rsi),%r10
+	movq	136(%rsi),%r11
+	shlq	$3,%r9
+	shlq	$32,%r10
+	movq	%r11,%r8
+	shlq	$61,%r11
+	shrq	$3,%r8
+	addq	%r9,%rax
+	addq	%r10,%rax
+	addq	%r11,%rax
+	adcq	$0,%r8
+	movq	%rax,112(%rdi)
+	movq	%r8,%rax
+	movq	144(%rsi),%r9
+	movq	152(%rsi),%r10
+	shlq	$26,%r9
+	movq	%r10,%r11
+	shlq	$55,%r10
+	shrq	$9,%r11
+	addq	%r9,%rax
+	addq	%r10,%rax
+	adcq	$0,%r11
+	movq	%rax,120(%rdi)
+	movq	%r11,%rax
+	.byte	0xf3,0xc3
+
+
+.globl	_rsaz_1024_norm2red_avx2
+.private_extern _rsaz_1024_norm2red_avx2
+
+.p2align	5
+_rsaz_1024_norm2red_avx2:
+	subq	$-128,%rdi
+	movq	(%rsi),%r8
+	movl	$0x1fffffff,%eax
+	movq	8(%rsi),%r9
+	movq	%r8,%r11
+	shrq	$0,%r11
+	andq	%rax,%r11
+	movq	%r11,-128(%rdi)
+	movq	%r8,%r10
+	shrq	$29,%r10
+	andq	%rax,%r10
+	movq	%r10,-120(%rdi)
+	shrdq	$58,%r9,%r8
+	andq	%rax,%r8
+	movq	%r8,-112(%rdi)
+	movq	16(%rsi),%r10
+	movq	%r9,%r8
+	shrq	$23,%r8
+	andq	%rax,%r8
+	movq	%r8,-104(%rdi)
+	shrdq	$52,%r10,%r9
+	andq	%rax,%r9
+	movq	%r9,-96(%rdi)
+	movq	24(%rsi),%r11
+	movq	%r10,%r9
+	shrq	$17,%r9
+	andq	%rax,%r9
+	movq	%r9,-88(%rdi)
+	shrdq	$46,%r11,%r10
+	andq	%rax,%r10
+	movq	%r10,-80(%rdi)
+	movq	32(%rsi),%r8
+	movq	%r11,%r10
+	shrq	$11,%r10
+	andq	%rax,%r10
+	movq	%r10,-72(%rdi)
+	shrdq	$40,%r8,%r11
+	andq	%rax,%r11
+	movq	%r11,-64(%rdi)
+	movq	40(%rsi),%r9
+	movq	%r8,%r11
+	shrq	$5,%r11
+	andq	%rax,%r11
+	movq	%r11,-56(%rdi)
+	movq	%r8,%r10
+	shrq	$34,%r10
+	andq	%rax,%r10
+	movq	%r10,-48(%rdi)
+	shrdq	$63,%r9,%r8
+	andq	%rax,%r8
+	movq	%r8,-40(%rdi)
+	movq	48(%rsi),%r10
+	movq	%r9,%r8
+	shrq	$28,%r8
+	andq	%rax,%r8
+	movq	%r8,-32(%rdi)
+	shrdq	$57,%r10,%r9
+	andq	%rax,%r9
+	movq	%r9,-24(%rdi)
+	movq	56(%rsi),%r11
+	movq	%r10,%r9
+	shrq	$22,%r9
+	andq	%rax,%r9
+	movq	%r9,-16(%rdi)
+	shrdq	$51,%r11,%r10
+	andq	%rax,%r10
+	movq	%r10,-8(%rdi)
+	movq	64(%rsi),%r8
+	movq	%r11,%r10
+	shrq	$16,%r10
+	andq	%rax,%r10
+	movq	%r10,0(%rdi)
+	shrdq	$45,%r8,%r11
+	andq	%rax,%r11
+	movq	%r11,8(%rdi)
+	movq	72(%rsi),%r9
+	movq	%r8,%r11
+	shrq	$10,%r11
+	andq	%rax,%r11
+	movq	%r11,16(%rdi)
+	shrdq	$39,%r9,%r8
+	andq	%rax,%r8
+	movq	%r8,24(%rdi)
+	movq	80(%rsi),%r10
+	movq	%r9,%r8
+	shrq	$4,%r8
+	andq	%rax,%r8
+	movq	%r8,32(%rdi)
+	movq	%r9,%r11
+	shrq	$33,%r11
+	andq	%rax,%r11
+	movq	%r11,40(%rdi)
+	shrdq	$62,%r10,%r9
+	andq	%rax,%r9
+	movq	%r9,48(%rdi)
+	movq	88(%rsi),%r11
+	movq	%r10,%r9
+	shrq	$27,%r9
+	andq	%rax,%r9
+	movq	%r9,56(%rdi)
+	shrdq	$56,%r11,%r10
+	andq	%rax,%r10
+	movq	%r10,64(%rdi)
+	movq	96(%rsi),%r8
+	movq	%r11,%r10
+	shrq	$21,%r10
+	andq	%rax,%r10
+	movq	%r10,72(%rdi)
+	shrdq	$50,%r8,%r11
+	andq	%rax,%r11
+	movq	%r11,80(%rdi)
+	movq	104(%rsi),%r9
+	movq	%r8,%r11
+	shrq	$15,%r11
+	andq	%rax,%r11
+	movq	%r11,88(%rdi)
+	shrdq	$44,%r9,%r8
+	andq	%rax,%r8
+	movq	%r8,96(%rdi)
+	movq	112(%rsi),%r10
+	movq	%r9,%r8
+	shrq	$9,%r8
+	andq	%rax,%r8
+	movq	%r8,104(%rdi)
+	shrdq	$38,%r10,%r9
+	andq	%rax,%r9
+	movq	%r9,112(%rdi)
+	movq	120(%rsi),%r11
+	movq	%r10,%r9
+	shrq	$3,%r9
+	andq	%rax,%r9
+	movq	%r9,120(%rdi)
+	movq	%r10,%r8
+	shrq	$32,%r8
+	andq	%rax,%r8
+	movq	%r8,128(%rdi)
+	shrdq	$61,%r11,%r10
+	andq	%rax,%r10
+	movq	%r10,136(%rdi)
+	xorq	%r8,%r8
+	movq	%r11,%r10
+	shrq	$26,%r10
+	andq	%rax,%r10
+	movq	%r10,144(%rdi)
+	shrdq	$55,%r8,%r11
+	andq	%rax,%r11
+	movq	%r11,152(%rdi)
+	movq	%r8,160(%rdi)
+	movq	%r8,168(%rdi)
+	movq	%r8,176(%rdi)
+	movq	%r8,184(%rdi)
+	.byte	0xf3,0xc3
+
 .globl	_rsaz_1024_scatter5_avx2
 .private_extern _rsaz_1024_scatter5_avx2
+
+.p2align	5
+_rsaz_1024_scatter5_avx2:
+	vzeroupper
+	vmovdqu	L$scatter_permd(%rip),%ymm5
+	shll	$4,%edx
+	leaq	(%rdi,%rdx,1),%rdi
+	movl	$9,%eax
+	jmp	L$oop_scatter_1024
+
+.p2align	5
+L$oop_scatter_1024:
+	vmovdqu	(%rsi),%ymm0
+	leaq	32(%rsi),%rsi
+	vpermd	%ymm0,%ymm5,%ymm0
+	vmovdqu	%xmm0,(%rdi)
+	leaq	512(%rdi),%rdi
+	decl	%eax
+	jnz	L$oop_scatter_1024
+
+	vzeroupper
+	.byte	0xf3,0xc3
+
+
 .globl	_rsaz_1024_gather5_avx2
 .private_extern _rsaz_1024_gather5_avx2
 
-_rsaz_1024_sqr_avx2:
-_rsaz_1024_mul_avx2:
-_rsaz_1024_norm2red_avx2:
-_rsaz_1024_red2norm_avx2:
-_rsaz_1024_scatter5_avx2:
+.p2align	5
 _rsaz_1024_gather5_avx2:
-.byte	0x0f,0x0b
+
+	vzeroupper
+	movq	%rsp,%r11
+
+	leaq	-256(%rsp),%rsp
+	andq	$-32,%rsp
+	leaq	L$inc(%rip),%r10
+	leaq	-128(%rsp),%rax
+
+	vmovd	%edx,%xmm4
+	vmovdqa	(%r10),%ymm0
+	vmovdqa	32(%r10),%ymm1
+	vmovdqa	64(%r10),%ymm5
+	vpbroadcastd	%xmm4,%ymm4
+
+	vpaddd	%ymm5,%ymm0,%ymm2
+	vpcmpeqd	%ymm4,%ymm0,%ymm0
+	vpaddd	%ymm5,%ymm1,%ymm3
+	vpcmpeqd	%ymm4,%ymm1,%ymm1
+	vmovdqa	%ymm0,0+128(%rax)
+	vpaddd	%ymm5,%ymm2,%ymm0
+	vpcmpeqd	%ymm4,%ymm2,%ymm2
+	vmovdqa	%ymm1,32+128(%rax)
+	vpaddd	%ymm5,%ymm3,%ymm1
+	vpcmpeqd	%ymm4,%ymm3,%ymm3
+	vmovdqa	%ymm2,64+128(%rax)
+	vpaddd	%ymm5,%ymm0,%ymm2
+	vpcmpeqd	%ymm4,%ymm0,%ymm0
+	vmovdqa	%ymm3,96+128(%rax)
+	vpaddd	%ymm5,%ymm1,%ymm3
+	vpcmpeqd	%ymm4,%ymm1,%ymm1
+	vmovdqa	%ymm0,128+128(%rax)
+	vpaddd	%ymm5,%ymm2,%ymm8
+	vpcmpeqd	%ymm4,%ymm2,%ymm2
+	vmovdqa	%ymm1,160+128(%rax)
+	vpaddd	%ymm5,%ymm3,%ymm9
+	vpcmpeqd	%ymm4,%ymm3,%ymm3
+	vmovdqa	%ymm2,192+128(%rax)
+	vpaddd	%ymm5,%ymm8,%ymm10
+	vpcmpeqd	%ymm4,%ymm8,%ymm8
+	vmovdqa	%ymm3,224+128(%rax)
+	vpaddd	%ymm5,%ymm9,%ymm11
+	vpcmpeqd	%ymm4,%ymm9,%ymm9
+	vpaddd	%ymm5,%ymm10,%ymm12
+	vpcmpeqd	%ymm4,%ymm10,%ymm10
+	vpaddd	%ymm5,%ymm11,%ymm13
+	vpcmpeqd	%ymm4,%ymm11,%ymm11
+	vpaddd	%ymm5,%ymm12,%ymm14
+	vpcmpeqd	%ymm4,%ymm12,%ymm12
+	vpaddd	%ymm5,%ymm13,%ymm15
+	vpcmpeqd	%ymm4,%ymm13,%ymm13
+	vpcmpeqd	%ymm4,%ymm14,%ymm14
+	vpcmpeqd	%ymm4,%ymm15,%ymm15
+
+	vmovdqa	-32(%r10),%ymm7
+	leaq	128(%rsi),%rsi
+	movl	$9,%edx
+
+L$oop_gather_1024:
+	vmovdqa	0-128(%rsi),%ymm0
+	vmovdqa	32-128(%rsi),%ymm1
+	vmovdqa	64-128(%rsi),%ymm2
+	vmovdqa	96-128(%rsi),%ymm3
+	vpand	0+128(%rax),%ymm0,%ymm0
+	vpand	32+128(%rax),%ymm1,%ymm1
+	vpand	64+128(%rax),%ymm2,%ymm2
+	vpor	%ymm0,%ymm1,%ymm4
+	vpand	96+128(%rax),%ymm3,%ymm3
+	vmovdqa	128-128(%rsi),%ymm0
+	vmovdqa	160-128(%rsi),%ymm1
+	vpor	%ymm2,%ymm3,%ymm5
+	vmovdqa	192-128(%rsi),%ymm2
+	vmovdqa	224-128(%rsi),%ymm3
+	vpand	128+128(%rax),%ymm0,%ymm0
+	vpand	160+128(%rax),%ymm1,%ymm1
+	vpand	192+128(%rax),%ymm2,%ymm2
+	vpor	%ymm0,%ymm4,%ymm4
+	vpand	224+128(%rax),%ymm3,%ymm3
+	vpand	256-128(%rsi),%ymm8,%ymm0
+	vpor	%ymm1,%ymm5,%ymm5
+	vpand	288-128(%rsi),%ymm9,%ymm1
+	vpor	%ymm2,%ymm4,%ymm4
+	vpand	320-128(%rsi),%ymm10,%ymm2
+	vpor	%ymm3,%ymm5,%ymm5
+	vpand	352-128(%rsi),%ymm11,%ymm3
+	vpor	%ymm0,%ymm4,%ymm4
+	vpand	384-128(%rsi),%ymm12,%ymm0
+	vpor	%ymm1,%ymm5,%ymm5
+	vpand	416-128(%rsi),%ymm13,%ymm1
+	vpor	%ymm2,%ymm4,%ymm4
+	vpand	448-128(%rsi),%ymm14,%ymm2
+	vpor	%ymm3,%ymm5,%ymm5
+	vpand	480-128(%rsi),%ymm15,%ymm3
+	leaq	512(%rsi),%rsi
+	vpor	%ymm0,%ymm4,%ymm4
+	vpor	%ymm1,%ymm5,%ymm5
+	vpor	%ymm2,%ymm4,%ymm4
+	vpor	%ymm3,%ymm5,%ymm5
+
+	vpor	%ymm5,%ymm4,%ymm4
+	vextracti128	$1,%ymm4,%xmm5
+	vpor	%xmm4,%xmm5,%xmm5
+	vpermd	%ymm5,%ymm7,%ymm5
+	vmovdqu	%ymm5,(%rdi)
+	leaq	32(%rdi),%rdi
+	decl	%edx
+	jnz	L$oop_gather_1024
+
+	vpxor	%ymm0,%ymm0,%ymm0
+	vmovdqu	%ymm0,(%rdi)
+	vzeroupper
+	leaq	(%r11),%rsp
+
 	.byte	0xf3,0xc3
 
+L$SEH_end_rsaz_1024_gather5:
+
+
+.globl	_rsaz_avx2_eligible
+.private_extern _rsaz_avx2_eligible
+
+.p2align	5
+_rsaz_avx2_eligible:
+	movl	_OPENSSL_ia32cap_P+8(%rip),%eax
+	movl	$524544,%ecx
+	movl	$0,%edx
+	andl	%eax,%ecx
+	cmpl	$524544,%ecx
+	cmovel	%edx,%eax
+	andl	$32,%eax
+	shrl	$5,%eax
+	.byte	0xf3,0xc3
+
+
+.p2align	6
+L$and_mask:
+.quad	0x1fffffff,0x1fffffff,0x1fffffff,-1
+L$scatter_permd:
+.long	0,2,4,6,7,7,7,7
+L$gather_permd:
+.long	0,7,1,7,2,7,3,7
+L$inc:
+.long	0,0,0,0, 1,1,1,1
+.long	2,2,2,2, 3,3,3,3
+.long	4,4,4,4, 4,4,4,4
+.p2align	6
 #endif
diff --git a/mac-x86_64/crypto/bn/rsaz-x86_64.S b/mac-x86_64/crypto/bn/rsaz-x86_64.S
deleted file mode 100644
index 5e9e82f..0000000
--- a/mac-x86_64/crypto/bn/rsaz-x86_64.S
+++ /dev/null
@@ -1,1126 +0,0 @@
-#if defined(__x86_64__)
-.text	
-
-
-
-.globl	_rsaz_512_sqr
-.private_extern _rsaz_512_sqr
-
-.p2align	5
-_rsaz_512_sqr:
-	pushq	%rbx
-	pushq	%rbp
-	pushq	%r12
-	pushq	%r13
-	pushq	%r14
-	pushq	%r15
-
-	subq	$128+24,%rsp
-L$sqr_body:
-	movq	%rdx,%rbp
-	movq	(%rsi),%rdx
-	movq	8(%rsi),%rax
-	movq	%rcx,128(%rsp)
-	jmp	L$oop_sqr
-
-.p2align	5
-L$oop_sqr:
-	movl	%r8d,128+8(%rsp)
-
-	movq	%rdx,%rbx
-	mulq	%rdx
-	movq	%rax,%r8
-	movq	16(%rsi),%rax
-	movq	%rdx,%r9
-
-	mulq	%rbx
-	addq	%rax,%r9
-	movq	24(%rsi),%rax
-	movq	%rdx,%r10
-	adcq	$0,%r10
-
-	mulq	%rbx
-	addq	%rax,%r10
-	movq	32(%rsi),%rax
-	movq	%rdx,%r11
-	adcq	$0,%r11
-
-	mulq	%rbx
-	addq	%rax,%r11
-	movq	40(%rsi),%rax
-	movq	%rdx,%r12
-	adcq	$0,%r12
-
-	mulq	%rbx
-	addq	%rax,%r12
-	movq	48(%rsi),%rax
-	movq	%rdx,%r13
-	adcq	$0,%r13
-
-	mulq	%rbx
-	addq	%rax,%r13
-	movq	56(%rsi),%rax
-	movq	%rdx,%r14
-	adcq	$0,%r14
-
-	mulq	%rbx
-	addq	%rax,%r14
-	movq	%rbx,%rax
-	movq	%rdx,%r15
-	adcq	$0,%r15
-
-	addq	%r8,%r8
-	movq	%r9,%rcx
-	adcq	%r9,%r9
-
-	mulq	%rax
-	movq	%rax,(%rsp)
-	addq	%rdx,%r8
-	adcq	$0,%r9
-
-	movq	%r8,8(%rsp)
-	shrq	$63,%rcx
-
-
-	movq	8(%rsi),%r8
-	movq	16(%rsi),%rax
-	mulq	%r8
-	addq	%rax,%r10
-	movq	24(%rsi),%rax
-	movq	%rdx,%rbx
-	adcq	$0,%rbx
-
-	mulq	%r8
-	addq	%rax,%r11
-	movq	32(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%rbx,%r11
-	movq	%rdx,%rbx
-	adcq	$0,%rbx
-
-	mulq	%r8
-	addq	%rax,%r12
-	movq	40(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%rbx,%r12
-	movq	%rdx,%rbx
-	adcq	$0,%rbx
-
-	mulq	%r8
-	addq	%rax,%r13
-	movq	48(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%rbx,%r13
-	movq	%rdx,%rbx
-	adcq	$0,%rbx
-
-	mulq	%r8
-	addq	%rax,%r14
-	movq	56(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%rbx,%r14
-	movq	%rdx,%rbx
-	adcq	$0,%rbx
-
-	mulq	%r8
-	addq	%rax,%r15
-	movq	%r8,%rax
-	adcq	$0,%rdx
-	addq	%rbx,%r15
-	movq	%rdx,%r8
-	movq	%r10,%rdx
-	adcq	$0,%r8
-
-	addq	%rdx,%rdx
-	leaq	(%rcx,%r10,2),%r10
-	movq	%r11,%rbx
-	adcq	%r11,%r11
-
-	mulq	%rax
-	addq	%rax,%r9
-	adcq	%rdx,%r10
-	adcq	$0,%r11
-
-	movq	%r9,16(%rsp)
-	movq	%r10,24(%rsp)
-	shrq	$63,%rbx
-
-
-	movq	16(%rsi),%r9
-	movq	24(%rsi),%rax
-	mulq	%r9
-	addq	%rax,%r12
-	movq	32(%rsi),%rax
-	movq	%rdx,%rcx
-	adcq	$0,%rcx
-
-	mulq	%r9
-	addq	%rax,%r13
-	movq	40(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%rcx,%r13
-	movq	%rdx,%rcx
-	adcq	$0,%rcx
-
-	mulq	%r9
-	addq	%rax,%r14
-	movq	48(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%rcx,%r14
-	movq	%rdx,%rcx
-	adcq	$0,%rcx
-
-	mulq	%r9
-	movq	%r12,%r10
-	leaq	(%rbx,%r12,2),%r12
-	addq	%rax,%r15
-	movq	56(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%rcx,%r15
-	movq	%rdx,%rcx
-	adcq	$0,%rcx
-
-	mulq	%r9
-	shrq	$63,%r10
-	addq	%rax,%r8
-	movq	%r9,%rax
-	adcq	$0,%rdx
-	addq	%rcx,%r8
-	movq	%rdx,%r9
-	adcq	$0,%r9
-
-	movq	%r13,%rcx
-	leaq	(%r10,%r13,2),%r13
-
-	mulq	%rax
-	addq	%rax,%r11
-	adcq	%rdx,%r12
-	adcq	$0,%r13
-
-	movq	%r11,32(%rsp)
-	movq	%r12,40(%rsp)
-	shrq	$63,%rcx
-
-
-	movq	24(%rsi),%r10
-	movq	32(%rsi),%rax
-	mulq	%r10
-	addq	%rax,%r14
-	movq	40(%rsi),%rax
-	movq	%rdx,%rbx
-	adcq	$0,%rbx
-
-	mulq	%r10
-	addq	%rax,%r15
-	movq	48(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%rbx,%r15
-	movq	%rdx,%rbx
-	adcq	$0,%rbx
-
-	mulq	%r10
-	movq	%r14,%r12
-	leaq	(%rcx,%r14,2),%r14
-	addq	%rax,%r8
-	movq	56(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%rbx,%r8
-	movq	%rdx,%rbx
-	adcq	$0,%rbx
-
-	mulq	%r10
-	shrq	$63,%r12
-	addq	%rax,%r9
-	movq	%r10,%rax
-	adcq	$0,%rdx
-	addq	%rbx,%r9
-	movq	%rdx,%r10
-	adcq	$0,%r10
-
-	movq	%r15,%rbx
-	leaq	(%r12,%r15,2),%r15
-
-	mulq	%rax
-	addq	%rax,%r13
-	adcq	%rdx,%r14
-	adcq	$0,%r15
-
-	movq	%r13,48(%rsp)
-	movq	%r14,56(%rsp)
-	shrq	$63,%rbx
-
-
-	movq	32(%rsi),%r11
-	movq	40(%rsi),%rax
-	mulq	%r11
-	addq	%rax,%r8
-	movq	48(%rsi),%rax
-	movq	%rdx,%rcx
-	adcq	$0,%rcx
-
-	mulq	%r11
-	addq	%rax,%r9
-	movq	56(%rsi),%rax
-	adcq	$0,%rdx
-	movq	%r8,%r12
-	leaq	(%rbx,%r8,2),%r8
-	addq	%rcx,%r9
-	movq	%rdx,%rcx
-	adcq	$0,%rcx
-
-	mulq	%r11
-	shrq	$63,%r12
-	addq	%rax,%r10
-	movq	%r11,%rax
-	adcq	$0,%rdx
-	addq	%rcx,%r10
-	movq	%rdx,%r11
-	adcq	$0,%r11
-
-	movq	%r9,%rcx
-	leaq	(%r12,%r9,2),%r9
-
-	mulq	%rax
-	addq	%rax,%r15
-	adcq	%rdx,%r8
-	adcq	$0,%r9
-
-	movq	%r15,64(%rsp)
-	movq	%r8,72(%rsp)
-	shrq	$63,%rcx
-
-
-	movq	40(%rsi),%r12
-	movq	48(%rsi),%rax
-	mulq	%r12
-	addq	%rax,%r10
-	movq	56(%rsi),%rax
-	movq	%rdx,%rbx
-	adcq	$0,%rbx
-
-	mulq	%r12
-	addq	%rax,%r11
-	movq	%r12,%rax
-	movq	%r10,%r15
-	leaq	(%rcx,%r10,2),%r10
-	adcq	$0,%rdx
-	shrq	$63,%r15
-	addq	%rbx,%r11
-	movq	%rdx,%r12
-	adcq	$0,%r12
-
-	movq	%r11,%rbx
-	leaq	(%r15,%r11,2),%r11
-
-	mulq	%rax
-	addq	%rax,%r9
-	adcq	%rdx,%r10
-	adcq	$0,%r11
-
-	movq	%r9,80(%rsp)
-	movq	%r10,88(%rsp)
-
-
-	movq	48(%rsi),%r13
-	movq	56(%rsi),%rax
-	mulq	%r13
-	addq	%rax,%r12
-	movq	%r13,%rax
-	movq	%rdx,%r13
-	adcq	$0,%r13
-
-	xorq	%r14,%r14
-	shlq	$1,%rbx
-	adcq	%r12,%r12
-	adcq	%r13,%r13
-	adcq	%r14,%r14
-
-	mulq	%rax
-	addq	%rax,%r11
-	adcq	%rdx,%r12
-	adcq	$0,%r13
-
-	movq	%r11,96(%rsp)
-	movq	%r12,104(%rsp)
-
-
-	movq	56(%rsi),%rax
-	mulq	%rax
-	addq	%rax,%r13
-	adcq	$0,%rdx
-
-	addq	%rdx,%r14
-
-	movq	%r13,112(%rsp)
-	movq	%r14,120(%rsp)
-
-	movq	(%rsp),%r8
-	movq	8(%rsp),%r9
-	movq	16(%rsp),%r10
-	movq	24(%rsp),%r11
-	movq	32(%rsp),%r12
-	movq	40(%rsp),%r13
-	movq	48(%rsp),%r14
-	movq	56(%rsp),%r15
-
-	call	__rsaz_512_reduce
-
-	addq	64(%rsp),%r8
-	adcq	72(%rsp),%r9
-	adcq	80(%rsp),%r10
-	adcq	88(%rsp),%r11
-	adcq	96(%rsp),%r12
-	adcq	104(%rsp),%r13
-	adcq	112(%rsp),%r14
-	adcq	120(%rsp),%r15
-	sbbq	%rcx,%rcx
-
-	call	__rsaz_512_subtract
-
-	movq	%r8,%rdx
-	movq	%r9,%rax
-	movl	128+8(%rsp),%r8d
-	movq	%rdi,%rsi
-
-	decl	%r8d
-	jnz	L$oop_sqr
-
-	leaq	128+24+48(%rsp),%rax
-	movq	-48(%rax),%r15
-	movq	-40(%rax),%r14
-	movq	-32(%rax),%r13
-	movq	-24(%rax),%r12
-	movq	-16(%rax),%rbp
-	movq	-8(%rax),%rbx
-	leaq	(%rax),%rsp
-L$sqr_epilogue:
-	.byte	0xf3,0xc3
-
-.globl	_rsaz_512_mul
-.private_extern _rsaz_512_mul
-
-.p2align	5
-_rsaz_512_mul:
-	pushq	%rbx
-	pushq	%rbp
-	pushq	%r12
-	pushq	%r13
-	pushq	%r14
-	pushq	%r15
-
-	subq	$128+24,%rsp
-L$mul_body:
-.byte	102,72,15,110,199
-.byte	102,72,15,110,201
-	movq	%r8,128(%rsp)
-	movq	(%rdx),%rbx
-	movq	%rdx,%rbp
-	call	__rsaz_512_mul
-
-.byte	102,72,15,126,199
-.byte	102,72,15,126,205
-
-	movq	(%rsp),%r8
-	movq	8(%rsp),%r9
-	movq	16(%rsp),%r10
-	movq	24(%rsp),%r11
-	movq	32(%rsp),%r12
-	movq	40(%rsp),%r13
-	movq	48(%rsp),%r14
-	movq	56(%rsp),%r15
-
-	call	__rsaz_512_reduce
-	addq	64(%rsp),%r8
-	adcq	72(%rsp),%r9
-	adcq	80(%rsp),%r10
-	adcq	88(%rsp),%r11
-	adcq	96(%rsp),%r12
-	adcq	104(%rsp),%r13
-	adcq	112(%rsp),%r14
-	adcq	120(%rsp),%r15
-	sbbq	%rcx,%rcx
-
-	call	__rsaz_512_subtract
-
-	leaq	128+24+48(%rsp),%rax
-	movq	-48(%rax),%r15
-	movq	-40(%rax),%r14
-	movq	-32(%rax),%r13
-	movq	-24(%rax),%r12
-	movq	-16(%rax),%rbp
-	movq	-8(%rax),%rbx
-	leaq	(%rax),%rsp
-L$mul_epilogue:
-	.byte	0xf3,0xc3
-
-.globl	_rsaz_512_mul_gather4
-.private_extern _rsaz_512_mul_gather4
-
-.p2align	5
-_rsaz_512_mul_gather4:
-	pushq	%rbx
-	pushq	%rbp
-	pushq	%r12
-	pushq	%r13
-	pushq	%r14
-	pushq	%r15
-
-	movl	%r9d,%r9d
-	subq	$128+24,%rsp
-L$mul_gather4_body:
-	movl	64(%rdx,%r9,4),%eax
-.byte	102,72,15,110,199
-	movl	(%rdx,%r9,4),%ebx
-.byte	102,72,15,110,201
-	movq	%r8,128(%rsp)
-
-	shlq	$32,%rax
-	orq	%rax,%rbx
-	movq	(%rsi),%rax
-	movq	8(%rsi),%rcx
-	leaq	128(%rdx,%r9,4),%rbp
-	mulq	%rbx
-	movq	%rax,(%rsp)
-	movq	%rcx,%rax
-	movq	%rdx,%r8
-
-	mulq	%rbx
-	movd	(%rbp),%xmm4
-	addq	%rax,%r8
-	movq	16(%rsi),%rax
-	movq	%rdx,%r9
-	adcq	$0,%r9
-
-	mulq	%rbx
-	movd	64(%rbp),%xmm5
-	addq	%rax,%r9
-	movq	24(%rsi),%rax
-	movq	%rdx,%r10
-	adcq	$0,%r10
-
-	mulq	%rbx
-	pslldq	$4,%xmm5
-	addq	%rax,%r10
-	movq	32(%rsi),%rax
-	movq	%rdx,%r11
-	adcq	$0,%r11
-
-	mulq	%rbx
-	por	%xmm5,%xmm4
-	addq	%rax,%r11
-	movq	40(%rsi),%rax
-	movq	%rdx,%r12
-	adcq	$0,%r12
-
-	mulq	%rbx
-	addq	%rax,%r12
-	movq	48(%rsi),%rax
-	movq	%rdx,%r13
-	adcq	$0,%r13
-
-	mulq	%rbx
-	leaq	128(%rbp),%rbp
-	addq	%rax,%r13
-	movq	56(%rsi),%rax
-	movq	%rdx,%r14
-	adcq	$0,%r14
-
-	mulq	%rbx
-.byte	102,72,15,126,227
-	addq	%rax,%r14
-	movq	(%rsi),%rax
-	movq	%rdx,%r15
-	adcq	$0,%r15
-
-	leaq	8(%rsp),%rdi
-	movl	$7,%ecx
-	jmp	L$oop_mul_gather
-
-.p2align	5
-L$oop_mul_gather:
-	mulq	%rbx
-	addq	%rax,%r8
-	movq	8(%rsi),%rax
-	movq	%r8,(%rdi)
-	movq	%rdx,%r8
-	adcq	$0,%r8
-
-	mulq	%rbx
-	movd	(%rbp),%xmm4
-	addq	%rax,%r9
-	movq	16(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%r9,%r8
-	movq	%rdx,%r9
-	adcq	$0,%r9
-
-	mulq	%rbx
-	movd	64(%rbp),%xmm5
-	addq	%rax,%r10
-	movq	24(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%r10,%r9
-	movq	%rdx,%r10
-	adcq	$0,%r10
-
-	mulq	%rbx
-	pslldq	$4,%xmm5
-	addq	%rax,%r11
-	movq	32(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%r11,%r10
-	movq	%rdx,%r11
-	adcq	$0,%r11
-
-	mulq	%rbx
-	por	%xmm5,%xmm4
-	addq	%rax,%r12
-	movq	40(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%r12,%r11
-	movq	%rdx,%r12
-	adcq	$0,%r12
-
-	mulq	%rbx
-	addq	%rax,%r13
-	movq	48(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%r13,%r12
-	movq	%rdx,%r13
-	adcq	$0,%r13
-
-	mulq	%rbx
-	addq	%rax,%r14
-	movq	56(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%r14,%r13
-	movq	%rdx,%r14
-	adcq	$0,%r14
-
-	mulq	%rbx
-.byte	102,72,15,126,227
-	addq	%rax,%r15
-	movq	(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%r15,%r14
-	movq	%rdx,%r15
-	adcq	$0,%r15
-
-	leaq	128(%rbp),%rbp
-	leaq	8(%rdi),%rdi
-
-	decl	%ecx
-	jnz	L$oop_mul_gather
-
-	movq	%r8,(%rdi)
-	movq	%r9,8(%rdi)
-	movq	%r10,16(%rdi)
-	movq	%r11,24(%rdi)
-	movq	%r12,32(%rdi)
-	movq	%r13,40(%rdi)
-	movq	%r14,48(%rdi)
-	movq	%r15,56(%rdi)
-
-.byte	102,72,15,126,199
-.byte	102,72,15,126,205
-
-	movq	(%rsp),%r8
-	movq	8(%rsp),%r9
-	movq	16(%rsp),%r10
-	movq	24(%rsp),%r11
-	movq	32(%rsp),%r12
-	movq	40(%rsp),%r13
-	movq	48(%rsp),%r14
-	movq	56(%rsp),%r15
-
-	call	__rsaz_512_reduce
-	addq	64(%rsp),%r8
-	adcq	72(%rsp),%r9
-	adcq	80(%rsp),%r10
-	adcq	88(%rsp),%r11
-	adcq	96(%rsp),%r12
-	adcq	104(%rsp),%r13
-	adcq	112(%rsp),%r14
-	adcq	120(%rsp),%r15
-	sbbq	%rcx,%rcx
-
-	call	__rsaz_512_subtract
-
-	leaq	128+24+48(%rsp),%rax
-	movq	-48(%rax),%r15
-	movq	-40(%rax),%r14
-	movq	-32(%rax),%r13
-	movq	-24(%rax),%r12
-	movq	-16(%rax),%rbp
-	movq	-8(%rax),%rbx
-	leaq	(%rax),%rsp
-L$mul_gather4_epilogue:
-	.byte	0xf3,0xc3
-
-.globl	_rsaz_512_mul_scatter4
-.private_extern _rsaz_512_mul_scatter4
-
-.p2align	5
-_rsaz_512_mul_scatter4:
-	pushq	%rbx
-	pushq	%rbp
-	pushq	%r12
-	pushq	%r13
-	pushq	%r14
-	pushq	%r15
-
-	movl	%r9d,%r9d
-	subq	$128+24,%rsp
-L$mul_scatter4_body:
-	leaq	(%r8,%r9,4),%r8
-.byte	102,72,15,110,199
-.byte	102,72,15,110,202
-.byte	102,73,15,110,208
-	movq	%rcx,128(%rsp)
-
-	movq	%rdi,%rbp
-	movq	(%rdi),%rbx
-	call	__rsaz_512_mul
-
-.byte	102,72,15,126,199
-.byte	102,72,15,126,205
-
-	movq	(%rsp),%r8
-	movq	8(%rsp),%r9
-	movq	16(%rsp),%r10
-	movq	24(%rsp),%r11
-	movq	32(%rsp),%r12
-	movq	40(%rsp),%r13
-	movq	48(%rsp),%r14
-	movq	56(%rsp),%r15
-
-	call	__rsaz_512_reduce
-	addq	64(%rsp),%r8
-	adcq	72(%rsp),%r9
-	adcq	80(%rsp),%r10
-	adcq	88(%rsp),%r11
-	adcq	96(%rsp),%r12
-	adcq	104(%rsp),%r13
-	adcq	112(%rsp),%r14
-	adcq	120(%rsp),%r15
-.byte	102,72,15,126,214
-	sbbq	%rcx,%rcx
-
-	call	__rsaz_512_subtract
-
-	movl	%r8d,0(%rsi)
-	shrq	$32,%r8
-	movl	%r9d,128(%rsi)
-	shrq	$32,%r9
-	movl	%r10d,256(%rsi)
-	shrq	$32,%r10
-	movl	%r11d,384(%rsi)
-	shrq	$32,%r11
-	movl	%r12d,512(%rsi)
-	shrq	$32,%r12
-	movl	%r13d,640(%rsi)
-	shrq	$32,%r13
-	movl	%r14d,768(%rsi)
-	shrq	$32,%r14
-	movl	%r15d,896(%rsi)
-	shrq	$32,%r15
-	movl	%r8d,64(%rsi)
-	movl	%r9d,192(%rsi)
-	movl	%r10d,320(%rsi)
-	movl	%r11d,448(%rsi)
-	movl	%r12d,576(%rsi)
-	movl	%r13d,704(%rsi)
-	movl	%r14d,832(%rsi)
-	movl	%r15d,960(%rsi)
-
-	leaq	128+24+48(%rsp),%rax
-	movq	-48(%rax),%r15
-	movq	-40(%rax),%r14
-	movq	-32(%rax),%r13
-	movq	-24(%rax),%r12
-	movq	-16(%rax),%rbp
-	movq	-8(%rax),%rbx
-	leaq	(%rax),%rsp
-L$mul_scatter4_epilogue:
-	.byte	0xf3,0xc3
-
-.globl	_rsaz_512_mul_by_one
-.private_extern _rsaz_512_mul_by_one
-
-.p2align	5
-_rsaz_512_mul_by_one:
-	pushq	%rbx
-	pushq	%rbp
-	pushq	%r12
-	pushq	%r13
-	pushq	%r14
-	pushq	%r15
-
-	subq	$128+24,%rsp
-L$mul_by_one_body:
-	movq	%rdx,%rbp
-	movq	%rcx,128(%rsp)
-
-	movq	(%rsi),%r8
-	pxor	%xmm0,%xmm0
-	movq	8(%rsi),%r9
-	movq	16(%rsi),%r10
-	movq	24(%rsi),%r11
-	movq	32(%rsi),%r12
-	movq	40(%rsi),%r13
-	movq	48(%rsi),%r14
-	movq	56(%rsi),%r15
-
-	movdqa	%xmm0,(%rsp)
-	movdqa	%xmm0,16(%rsp)
-	movdqa	%xmm0,32(%rsp)
-	movdqa	%xmm0,48(%rsp)
-	movdqa	%xmm0,64(%rsp)
-	movdqa	%xmm0,80(%rsp)
-	movdqa	%xmm0,96(%rsp)
-	call	__rsaz_512_reduce
-	movq	%r8,(%rdi)
-	movq	%r9,8(%rdi)
-	movq	%r10,16(%rdi)
-	movq	%r11,24(%rdi)
-	movq	%r12,32(%rdi)
-	movq	%r13,40(%rdi)
-	movq	%r14,48(%rdi)
-	movq	%r15,56(%rdi)
-
-	leaq	128+24+48(%rsp),%rax
-	movq	-48(%rax),%r15
-	movq	-40(%rax),%r14
-	movq	-32(%rax),%r13
-	movq	-24(%rax),%r12
-	movq	-16(%rax),%rbp
-	movq	-8(%rax),%rbx
-	leaq	(%rax),%rsp
-L$mul_by_one_epilogue:
-	.byte	0xf3,0xc3
-
-
-.p2align	5
-__rsaz_512_reduce:
-	movq	%r8,%rbx
-	imulq	128+8(%rsp),%rbx
-	movq	0(%rbp),%rax
-	movl	$8,%ecx
-	jmp	L$reduction_loop
-
-.p2align	5
-L$reduction_loop:
-	mulq	%rbx
-	movq	8(%rbp),%rax
-	negq	%r8
-	movq	%rdx,%r8
-	adcq	$0,%r8
-
-	mulq	%rbx
-	addq	%rax,%r9
-	movq	16(%rbp),%rax
-	adcq	$0,%rdx
-	addq	%r9,%r8
-	movq	%rdx,%r9
-	adcq	$0,%r9
-
-	mulq	%rbx
-	addq	%rax,%r10
-	movq	24(%rbp),%rax
-	adcq	$0,%rdx
-	addq	%r10,%r9
-	movq	%rdx,%r10
-	adcq	$0,%r10
-
-	mulq	%rbx
-	addq	%rax,%r11
-	movq	32(%rbp),%rax
-	adcq	$0,%rdx
-	addq	%r11,%r10
-	movq	128+8(%rsp),%rsi
-
-
-	adcq	$0,%rdx
-	movq	%rdx,%r11
-
-	mulq	%rbx
-	addq	%rax,%r12
-	movq	40(%rbp),%rax
-	adcq	$0,%rdx
-	imulq	%r8,%rsi
-	addq	%r12,%r11
-	movq	%rdx,%r12
-	adcq	$0,%r12
-
-	mulq	%rbx
-	addq	%rax,%r13
-	movq	48(%rbp),%rax
-	adcq	$0,%rdx
-	addq	%r13,%r12
-	movq	%rdx,%r13
-	adcq	$0,%r13
-
-	mulq	%rbx
-	addq	%rax,%r14
-	movq	56(%rbp),%rax
-	adcq	$0,%rdx
-	addq	%r14,%r13
-	movq	%rdx,%r14
-	adcq	$0,%r14
-
-	mulq	%rbx
-	movq	%rsi,%rbx
-	addq	%rax,%r15
-	movq	0(%rbp),%rax
-	adcq	$0,%rdx
-	addq	%r15,%r14
-	movq	%rdx,%r15
-	adcq	$0,%r15
-
-	decl	%ecx
-	jne	L$reduction_loop
-
-	.byte	0xf3,0xc3
-
-
-.p2align	5
-__rsaz_512_subtract:
-	movq	%r8,(%rdi)
-	movq	%r9,8(%rdi)
-	movq	%r10,16(%rdi)
-	movq	%r11,24(%rdi)
-	movq	%r12,32(%rdi)
-	movq	%r13,40(%rdi)
-	movq	%r14,48(%rdi)
-	movq	%r15,56(%rdi)
-
-	movq	0(%rbp),%r8
-	movq	8(%rbp),%r9
-	negq	%r8
-	notq	%r9
-	andq	%rcx,%r8
-	movq	16(%rbp),%r10
-	andq	%rcx,%r9
-	notq	%r10
-	movq	24(%rbp),%r11
-	andq	%rcx,%r10
-	notq	%r11
-	movq	32(%rbp),%r12
-	andq	%rcx,%r11
-	notq	%r12
-	movq	40(%rbp),%r13
-	andq	%rcx,%r12
-	notq	%r13
-	movq	48(%rbp),%r14
-	andq	%rcx,%r13
-	notq	%r14
-	movq	56(%rbp),%r15
-	andq	%rcx,%r14
-	notq	%r15
-	andq	%rcx,%r15
-
-	addq	(%rdi),%r8
-	adcq	8(%rdi),%r9
-	adcq	16(%rdi),%r10
-	adcq	24(%rdi),%r11
-	adcq	32(%rdi),%r12
-	adcq	40(%rdi),%r13
-	adcq	48(%rdi),%r14
-	adcq	56(%rdi),%r15
-
-	movq	%r8,(%rdi)
-	movq	%r9,8(%rdi)
-	movq	%r10,16(%rdi)
-	movq	%r11,24(%rdi)
-	movq	%r12,32(%rdi)
-	movq	%r13,40(%rdi)
-	movq	%r14,48(%rdi)
-	movq	%r15,56(%rdi)
-
-	.byte	0xf3,0xc3
-
-
-.p2align	5
-__rsaz_512_mul:
-	leaq	8(%rsp),%rdi
-
-	movq	(%rsi),%rax
-	mulq	%rbx
-	movq	%rax,(%rdi)
-	movq	8(%rsi),%rax
-	movq	%rdx,%r8
-
-	mulq	%rbx
-	addq	%rax,%r8
-	movq	16(%rsi),%rax
-	movq	%rdx,%r9
-	adcq	$0,%r9
-
-	mulq	%rbx
-	addq	%rax,%r9
-	movq	24(%rsi),%rax
-	movq	%rdx,%r10
-	adcq	$0,%r10
-
-	mulq	%rbx
-	addq	%rax,%r10
-	movq	32(%rsi),%rax
-	movq	%rdx,%r11
-	adcq	$0,%r11
-
-	mulq	%rbx
-	addq	%rax,%r11
-	movq	40(%rsi),%rax
-	movq	%rdx,%r12
-	adcq	$0,%r12
-
-	mulq	%rbx
-	addq	%rax,%r12
-	movq	48(%rsi),%rax
-	movq	%rdx,%r13
-	adcq	$0,%r13
-
-	mulq	%rbx
-	addq	%rax,%r13
-	movq	56(%rsi),%rax
-	movq	%rdx,%r14
-	adcq	$0,%r14
-
-	mulq	%rbx
-	addq	%rax,%r14
-	movq	(%rsi),%rax
-	movq	%rdx,%r15
-	adcq	$0,%r15
-
-	leaq	8(%rbp),%rbp
-	leaq	8(%rdi),%rdi
-
-	movl	$7,%ecx
-	jmp	L$oop_mul
-
-.p2align	5
-L$oop_mul:
-	movq	(%rbp),%rbx
-	mulq	%rbx
-	addq	%rax,%r8
-	movq	8(%rsi),%rax
-	movq	%r8,(%rdi)
-	movq	%rdx,%r8
-	adcq	$0,%r8
-
-	mulq	%rbx
-	addq	%rax,%r9
-	movq	16(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%r9,%r8
-	movq	%rdx,%r9
-	adcq	$0,%r9
-
-	mulq	%rbx
-	addq	%rax,%r10
-	movq	24(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%r10,%r9
-	movq	%rdx,%r10
-	adcq	$0,%r10
-
-	mulq	%rbx
-	addq	%rax,%r11
-	movq	32(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%r11,%r10
-	movq	%rdx,%r11
-	adcq	$0,%r11
-
-	mulq	%rbx
-	addq	%rax,%r12
-	movq	40(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%r12,%r11
-	movq	%rdx,%r12
-	adcq	$0,%r12
-
-	mulq	%rbx
-	addq	%rax,%r13
-	movq	48(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%r13,%r12
-	movq	%rdx,%r13
-	adcq	$0,%r13
-
-	mulq	%rbx
-	addq	%rax,%r14
-	movq	56(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%r14,%r13
-	movq	%rdx,%r14
-	leaq	8(%rbp),%rbp
-	adcq	$0,%r14
-
-	mulq	%rbx
-	addq	%rax,%r15
-	movq	(%rsi),%rax
-	adcq	$0,%rdx
-	addq	%r15,%r14
-	movq	%rdx,%r15
-	adcq	$0,%r15
-
-	leaq	8(%rdi),%rdi
-
-	decl	%ecx
-	jnz	L$oop_mul
-
-	movq	%r8,(%rdi)
-	movq	%r9,8(%rdi)
-	movq	%r10,16(%rdi)
-	movq	%r11,24(%rdi)
-	movq	%r12,32(%rdi)
-	movq	%r13,40(%rdi)
-	movq	%r14,48(%rdi)
-	movq	%r15,56(%rdi)
-
-	.byte	0xf3,0xc3
-
-.globl	_rsaz_512_scatter4
-.private_extern _rsaz_512_scatter4
-
-.p2align	4
-_rsaz_512_scatter4:
-	leaq	(%rdi,%rdx,4),%rdi
-	movl	$8,%r9d
-	jmp	L$oop_scatter
-.p2align	4
-L$oop_scatter:
-	movq	(%rsi),%rax
-	leaq	8(%rsi),%rsi
-	movl	%eax,(%rdi)
-	shrq	$32,%rax
-	movl	%eax,64(%rdi)
-	leaq	128(%rdi),%rdi
-	decl	%r9d
-	jnz	L$oop_scatter
-	.byte	0xf3,0xc3
-
-
-.globl	_rsaz_512_gather4
-.private_extern _rsaz_512_gather4
-
-.p2align	4
-_rsaz_512_gather4:
-	leaq	(%rsi,%rdx,4),%rsi
-	movl	$8,%r9d
-	jmp	L$oop_gather
-.p2align	4
-L$oop_gather:
-	movl	(%rsi),%eax
-	movl	64(%rsi),%r8d
-	leaq	128(%rsi),%rsi
-	shlq	$32,%r8
-	orq	%r8,%rax
-	movq	%rax,(%rdi)
-	leaq	8(%rdi),%rdi
-	decl	%r9d
-	jnz	L$oop_gather
-	.byte	0xf3,0xc3
-
-#endif
diff --git a/mac-x86_64/crypto/bn/x86_64-mont.S b/mac-x86_64/crypto/bn/x86_64-mont.S
index 6b9bc05..41a0926 100644
--- a/mac-x86_64/crypto/bn/x86_64-mont.S
+++ b/mac-x86_64/crypto/bn/x86_64-mont.S
@@ -8,6 +8,10 @@
 
 .p2align	4
 _bn_mul_mont:
+
+	movl	%r9d,%r9d
+	movq	%rsp,%rax
+
 	testl	$3,%r9d
 	jnz	L$mul_enter
 	cmpl	$8,%r9d
@@ -21,20 +25,50 @@
 .p2align	4
 L$mul_enter:
 	pushq	%rbx
+
 	pushq	%rbp
+
 	pushq	%r12
+
 	pushq	%r13
+
 	pushq	%r14
+
 	pushq	%r15
 
-	movl	%r9d,%r9d
-	leaq	2(%r9),%r10
-	movq	%rsp,%r11
-	negq	%r10
-	leaq	(%rsp,%r10,8),%rsp
-	andq	$-1024,%rsp
 
-	movq	%r11,8(%rsp,%r9,8)
+	negq	%r9
+	movq	%rsp,%r11
+	leaq	-16(%rsp,%r9,8),%r10
+	negq	%r9
+	andq	$-1024,%r10
+
+
+
+
+
+
+
+
+
+	subq	%r10,%r11
+	andq	$-4096,%r11
+	leaq	(%r10,%r11,1),%rsp
+	movq	(%rsp),%r11
+	cmpq	%r10,%rsp
+	ja	L$mul_page_walk
+	jmp	L$mul_page_walk_done
+
+.p2align	4
+L$mul_page_walk:
+	leaq	-4096(%rsp),%rsp
+	movq	(%rsp),%r11
+	cmpq	%r10,%rsp
+	ja	L$mul_page_walk
+L$mul_page_walk_done:
+
+	movq	%rax,8(%rsp,%r9,8)
+
 L$mul_body:
 	movq	%rdx,%r12
 	movq	(%r8),%r8
@@ -186,51 +220,86 @@
 
 	sbbq	$0,%rax
 	xorq	%r14,%r14
+	andq	%rax,%rsi
+	notq	%rax
+	movq	%rdi,%rcx
+	andq	%rax,%rcx
 	movq	%r9,%r15
+	orq	%rcx,%rsi
 .p2align	4
 L$copy:
-	movq	(%rsp,%r14,8),%rsi
-	movq	(%rdi,%r14,8),%rcx
-	xorq	%rcx,%rsi
-	andq	%rax,%rsi
-	xorq	%rcx,%rsi
+	movq	(%rsi,%r14,8),%rax
 	movq	%r14,(%rsp,%r14,8)
-	movq	%rsi,(%rdi,%r14,8)
+	movq	%rax,(%rdi,%r14,8)
 	leaq	1(%r14),%r14
 	subq	$1,%r15
 	jnz	L$copy
 
 	movq	8(%rsp,%r9,8),%rsi
+
 	movq	$1,%rax
-	movq	(%rsi),%r15
-	movq	8(%rsi),%r14
-	movq	16(%rsi),%r13
-	movq	24(%rsi),%r12
-	movq	32(%rsi),%rbp
-	movq	40(%rsi),%rbx
-	leaq	48(%rsi),%rsp
+	movq	-48(%rsi),%r15
+
+	movq	-40(%rsi),%r14
+
+	movq	-32(%rsi),%r13
+
+	movq	-24(%rsi),%r12
+
+	movq	-16(%rsi),%rbp
+
+	movq	-8(%rsi),%rbx
+
+	leaq	(%rsi),%rsp
+
 L$mul_epilogue:
 	.byte	0xf3,0xc3
 
 
+
 .p2align	4
 bn_mul4x_mont:
-L$mul4x_enter:
-	pushq	%rbx
-	pushq	%rbp
-	pushq	%r12
-	pushq	%r13
-	pushq	%r14
-	pushq	%r15
 
 	movl	%r9d,%r9d
-	leaq	4(%r9),%r10
-	movq	%rsp,%r11
-	negq	%r10
-	leaq	(%rsp,%r10,8),%rsp
-	andq	$-1024,%rsp
+	movq	%rsp,%rax
 
-	movq	%r11,8(%rsp,%r9,8)
+L$mul4x_enter:
+	pushq	%rbx
+
+	pushq	%rbp
+
+	pushq	%r12
+
+	pushq	%r13
+
+	pushq	%r14
+
+	pushq	%r15
+
+
+	negq	%r9
+	movq	%rsp,%r11
+	leaq	-32(%rsp,%r9,8),%r10
+	negq	%r9
+	andq	$-1024,%r10
+
+	subq	%r10,%r11
+	andq	$-4096,%r11
+	leaq	(%r10,%r11,1),%rsp
+	movq	(%rsp),%r11
+	cmpq	%r10,%rsp
+	ja	L$mul4x_page_walk
+	jmp	L$mul4x_page_walk_done
+
+L$mul4x_page_walk:
+	leaq	-4096(%rsp),%rsp
+	movq	(%rsp),%r11
+	cmpq	%r10,%rsp
+	ja	L$mul4x_page_walk
+L$mul4x_page_walk_done:
+
+	movq	%rax,8(%rsp,%r9,8)
+
 L$mul4x_body:
 	movq	%rdi,16(%rsp,%r9,8)
 	movq	%rdx,%r12
@@ -530,9 +599,11 @@
 	cmpq	%r9,%r14
 	jb	L$outer4x
 	movq	16(%rsp,%r9,8),%rdi
+	leaq	-4(%r9),%r15
 	movq	0(%rsp),%rax
+	pxor	%xmm0,%xmm0
 	movq	8(%rsp),%rdx
-	shrq	$2,%r9
+	shrq	$2,%r15
 	leaq	(%rsp),%rsi
 	xorq	%r14,%r14
 
@@ -540,7 +611,6 @@
 	movq	16(%rsi),%rbx
 	movq	24(%rsi),%rbp
 	sbbq	8(%rcx),%rdx
-	leaq	-1(%r9),%r15
 	jmp	L$sub4x
 .p2align	4
 L$sub4x:
@@ -568,62 +638,79 @@
 	movq	%rbx,16(%rdi,%r14,8)
 
 	sbbq	$0,%rax
-	movq	%rax,%xmm0
-	punpcklqdq	%xmm0,%xmm0
 	movq	%rbp,24(%rdi,%r14,8)
 	xorq	%r14,%r14
+	andq	%rax,%rsi
+	notq	%rax
+	movq	%rdi,%rcx
+	andq	%rax,%rcx
+	leaq	-4(%r9),%r15
+	orq	%rcx,%rsi
+	shrq	$2,%r15
 
-	movq	%r9,%r15
-	pxor	%xmm5,%xmm5
+	movdqu	(%rsi),%xmm1
+	movdqa	%xmm0,(%rsp)
+	movdqu	%xmm1,(%rdi)
 	jmp	L$copy4x
 .p2align	4
 L$copy4x:
-	movdqu	(%rsp,%r14,1),%xmm2
-	movdqu	16(%rsp,%r14,1),%xmm4
-	movdqu	(%rdi,%r14,1),%xmm1
-	movdqu	16(%rdi,%r14,1),%xmm3
-	pxor	%xmm1,%xmm2
-	pxor	%xmm3,%xmm4
-	pand	%xmm0,%xmm2
-	pand	%xmm0,%xmm4
-	pxor	%xmm1,%xmm2
-	pxor	%xmm3,%xmm4
-	movdqu	%xmm2,(%rdi,%r14,1)
-	movdqu	%xmm4,16(%rdi,%r14,1)
-	movdqa	%xmm5,(%rsp,%r14,1)
-	movdqa	%xmm5,16(%rsp,%r14,1)
-
+	movdqu	16(%rsi,%r14,1),%xmm2
+	movdqu	32(%rsi,%r14,1),%xmm1
+	movdqa	%xmm0,16(%rsp,%r14,1)
+	movdqu	%xmm2,16(%rdi,%r14,1)
+	movdqa	%xmm0,32(%rsp,%r14,1)
+	movdqu	%xmm1,32(%rdi,%r14,1)
 	leaq	32(%r14),%r14
 	decq	%r15
 	jnz	L$copy4x
 
-	shlq	$2,%r9
+	movdqu	16(%rsi,%r14,1),%xmm2
+	movdqa	%xmm0,16(%rsp,%r14,1)
+	movdqu	%xmm2,16(%rdi,%r14,1)
 	movq	8(%rsp,%r9,8),%rsi
+
 	movq	$1,%rax
-	movq	(%rsi),%r15
-	movq	8(%rsi),%r14
-	movq	16(%rsi),%r13
-	movq	24(%rsi),%r12
-	movq	32(%rsi),%rbp
-	movq	40(%rsi),%rbx
-	leaq	48(%rsi),%rsp
+	movq	-48(%rsi),%r15
+
+	movq	-40(%rsi),%r14
+
+	movq	-32(%rsi),%r13
+
+	movq	-24(%rsi),%r12
+
+	movq	-16(%rsi),%rbp
+
+	movq	-8(%rsi),%rbx
+
+	leaq	(%rsi),%rsp
+
 L$mul4x_epilogue:
 	.byte	0xf3,0xc3
 
 
 
 
+
 .p2align	5
 bn_sqr8x_mont:
-L$sqr8x_enter:
+
 	movq	%rsp,%rax
+
+L$sqr8x_enter:
 	pushq	%rbx
+
 	pushq	%rbp
+
 	pushq	%r12
+
 	pushq	%r13
+
 	pushq	%r14
+
 	pushq	%r15
 
+L$sqr8x_prologue:
+
 	movl	%r9d,%r10d
 	shll	$3,%r9d
 	shlq	$3+2,%r10
@@ -634,93 +721,143 @@
 
 
 
-	leaq	-64(%rsp,%r9,4),%r11
+	leaq	-64(%rsp,%r9,2),%r11
+	movq	%rsp,%rbp
 	movq	(%r8),%r8
 	subq	%rsi,%r11
 	andq	$4095,%r11
 	cmpq	%r11,%r10
 	jb	L$sqr8x_sp_alt
-	subq	%r11,%rsp
-	leaq	-64(%rsp,%r9,4),%rsp
+	subq	%r11,%rbp
+	leaq	-64(%rbp,%r9,2),%rbp
 	jmp	L$sqr8x_sp_done
 
 .p2align	5
 L$sqr8x_sp_alt:
-	leaq	4096-64(,%r9,4),%r10
-	leaq	-64(%rsp,%r9,4),%rsp
+	leaq	4096-64(,%r9,2),%r10
+	leaq	-64(%rbp,%r9,2),%rbp
 	subq	%r10,%r11
 	movq	$0,%r10
 	cmovcq	%r10,%r11
-	subq	%r11,%rsp
+	subq	%r11,%rbp
 L$sqr8x_sp_done:
-	andq	$-64,%rsp
+	andq	$-64,%rbp
+	movq	%rsp,%r11
+	subq	%rbp,%r11
+	andq	$-4096,%r11
+	leaq	(%r11,%rbp,1),%rsp
+	movq	(%rsp),%r10
+	cmpq	%rbp,%rsp
+	ja	L$sqr8x_page_walk
+	jmp	L$sqr8x_page_walk_done
+
+.p2align	4
+L$sqr8x_page_walk:
+	leaq	-4096(%rsp),%rsp
+	movq	(%rsp),%r10
+	cmpq	%rbp,%rsp
+	ja	L$sqr8x_page_walk
+L$sqr8x_page_walk_done:
+
 	movq	%r9,%r10
 	negq	%r9
 
-	leaq	64(%rsp,%r9,2),%r11
 	movq	%r8,32(%rsp)
 	movq	%rax,40(%rsp)
+
 L$sqr8x_body:
 
-	movq	%r9,%rbp
-.byte	102,73,15,110,211
-	shrq	$3+2,%rbp
-	movl	_OPENSSL_ia32cap_P+8(%rip),%eax
-	jmp	L$sqr8x_copy_n
-
-.p2align	5
-L$sqr8x_copy_n:
-	movq	0(%rcx),%xmm0
-	movq	8(%rcx),%xmm1
-	movq	16(%rcx),%xmm3
-	movq	24(%rcx),%xmm4
-	leaq	32(%rcx),%rcx
-	movdqa	%xmm0,0(%r11)
-	movdqa	%xmm1,16(%r11)
-	movdqa	%xmm3,32(%r11)
-	movdqa	%xmm4,48(%r11)
-	leaq	64(%r11),%r11
-	decq	%rbp
-	jnz	L$sqr8x_copy_n
-
+.byte	102,72,15,110,209
 	pxor	%xmm0,%xmm0
 .byte	102,72,15,110,207
 .byte	102,73,15,110,218
 	call	_bn_sqr8x_internal
 
-	pxor	%xmm0,%xmm0
-	leaq	48(%rsp),%rax
-	leaq	64(%rsp,%r9,2),%rdx
-	shrq	$3+2,%r9
-	movq	40(%rsp),%rsi
-	jmp	L$sqr8x_zero
+
+
+
+	leaq	(%rdi,%r9,1),%rbx
+	movq	%r9,%rcx
+	movq	%r9,%rdx
+.byte	102,72,15,126,207
+	sarq	$3+2,%rcx
+	jmp	L$sqr8x_sub
 
 .p2align	5
-L$sqr8x_zero:
-	movdqa	%xmm0,0(%rax)
-	movdqa	%xmm0,16(%rax)
-	movdqa	%xmm0,32(%rax)
-	movdqa	%xmm0,48(%rax)
-	leaq	64(%rax),%rax
-	movdqa	%xmm0,0(%rdx)
-	movdqa	%xmm0,16(%rdx)
-	movdqa	%xmm0,32(%rdx)
-	movdqa	%xmm0,48(%rdx)
-	leaq	64(%rdx),%rdx
-	decq	%r9
-	jnz	L$sqr8x_zero
+L$sqr8x_sub:
+	movq	0(%rbx),%r12
+	movq	8(%rbx),%r13
+	movq	16(%rbx),%r14
+	movq	24(%rbx),%r15
+	leaq	32(%rbx),%rbx
+	sbbq	0(%rbp),%r12
+	sbbq	8(%rbp),%r13
+	sbbq	16(%rbp),%r14
+	sbbq	24(%rbp),%r15
+	leaq	32(%rbp),%rbp
+	movq	%r12,0(%rdi)
+	movq	%r13,8(%rdi)
+	movq	%r14,16(%rdi)
+	movq	%r15,24(%rdi)
+	leaq	32(%rdi),%rdi
+	incq	%rcx
+	jnz	L$sqr8x_sub
+
+	sbbq	$0,%rax
+	leaq	(%rbx,%r9,1),%rbx
+	leaq	(%rdi,%r9,1),%rdi
+
+.byte	102,72,15,110,200
+	pxor	%xmm0,%xmm0
+	pshufd	$0,%xmm1,%xmm1
+	movq	40(%rsp),%rsi
+
+	jmp	L$sqr8x_cond_copy
+
+.p2align	5
+L$sqr8x_cond_copy:
+	movdqa	0(%rbx),%xmm2
+	movdqa	16(%rbx),%xmm3
+	leaq	32(%rbx),%rbx
+	movdqu	0(%rdi),%xmm4
+	movdqu	16(%rdi),%xmm5
+	leaq	32(%rdi),%rdi
+	movdqa	%xmm0,-32(%rbx)
+	movdqa	%xmm0,-16(%rbx)
+	movdqa	%xmm0,-32(%rbx,%rdx,1)
+	movdqa	%xmm0,-16(%rbx,%rdx,1)
+	pcmpeqd	%xmm1,%xmm0
+	pand	%xmm1,%xmm2
+	pand	%xmm1,%xmm3
+	pand	%xmm0,%xmm4
+	pand	%xmm0,%xmm5
+	pxor	%xmm0,%xmm0
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqu	%xmm4,-32(%rdi)
+	movdqu	%xmm5,-16(%rdi)
+	addq	$32,%r9
+	jnz	L$sqr8x_cond_copy
 
 	movq	$1,%rax
 	movq	-48(%rsi),%r15
+
 	movq	-40(%rsi),%r14
+
 	movq	-32(%rsi),%r13
+
 	movq	-24(%rsi),%r12
+
 	movq	-16(%rsi),%rbp
+
 	movq	-8(%rsi),%rbx
+
 	leaq	(%rsi),%rsp
+
 L$sqr8x_epilogue:
 	.byte	0xf3,0xc3
 
+
 .byte	77,111,110,116,103,111,109,101,114,121,32,77,117,108,116,105,112,108,105,99,97,116,105,111,110,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
 .p2align	4
 #endif
diff --git a/mac-x86_64/crypto/bn/x86_64-mont5.S b/mac-x86_64/crypto/bn/x86_64-mont5.S
index 461bfb2..24b56de 100644
--- a/mac-x86_64/crypto/bn/x86_64-mont5.S
+++ b/mac-x86_64/crypto/bn/x86_64-mont5.S
@@ -8,54 +8,193 @@
 
 .p2align	6
 _bn_mul_mont_gather5:
+
+	movl	%r9d,%r9d
+	movq	%rsp,%rax
+
 	testl	$7,%r9d
 	jnz	L$mul_enter
 	jmp	L$mul4x_enter
 
 .p2align	4
 L$mul_enter:
-	movl	%r9d,%r9d
-	movq	%rsp,%rax
-	movl	8(%rsp),%r10d
+	movd	8(%rsp),%xmm5
 	pushq	%rbx
+
 	pushq	%rbp
+
 	pushq	%r12
+
 	pushq	%r13
+
 	pushq	%r14
+
 	pushq	%r15
-	leaq	2(%r9),%r11
-	negq	%r11
-	leaq	(%rsp,%r11,8),%rsp
-	andq	$-1024,%rsp
 
+
+	negq	%r9
+	movq	%rsp,%r11
+	leaq	-280(%rsp,%r9,8),%r10
+	negq	%r9
+	andq	$-1024,%r10
+
+
+
+
+
+
+
+
+
+	subq	%r10,%r11
+	andq	$-4096,%r11
+	leaq	(%r10,%r11,1),%rsp
+	movq	(%rsp),%r11
+	cmpq	%r10,%rsp
+	ja	L$mul_page_walk
+	jmp	L$mul_page_walk_done
+
+L$mul_page_walk:
+	leaq	-4096(%rsp),%rsp
+	movq	(%rsp),%r11
+	cmpq	%r10,%rsp
+	ja	L$mul_page_walk
+L$mul_page_walk_done:
+
+	leaq	L$inc(%rip),%r10
 	movq	%rax,8(%rsp,%r9,8)
+
 L$mul_body:
-	movq	%rdx,%r12
-	movq	%r10,%r11
-	shrq	$3,%r10
-	andq	$7,%r11
-	notq	%r10
-	leaq	L$magic_masks(%rip),%rax
-	andq	$3,%r10
-	leaq	96(%r12,%r11,8),%r12
-	movq	0(%rax,%r10,8),%xmm4
-	movq	8(%rax,%r10,8),%xmm5
-	movq	16(%rax,%r10,8),%xmm6
-	movq	24(%rax,%r10,8),%xmm7
 
-	movq	-96(%r12),%xmm0
-	movq	-32(%r12),%xmm1
-	pand	%xmm4,%xmm0
-	movq	32(%r12),%xmm2
-	pand	%xmm5,%xmm1
-	movq	96(%r12),%xmm3
-	pand	%xmm6,%xmm2
-	por	%xmm1,%xmm0
-	pand	%xmm7,%xmm3
+	leaq	128(%rdx),%r12
+	movdqa	0(%r10),%xmm0
+	movdqa	16(%r10),%xmm1
+	leaq	24-112(%rsp,%r9,8),%r10
+	andq	$-16,%r10
+
+	pshufd	$0,%xmm5,%xmm5
+	movdqa	%xmm1,%xmm4
+	movdqa	%xmm1,%xmm2
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+.byte	0x67
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,112(%r10)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,128(%r10)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,144(%r10)
+	movdqa	%xmm4,%xmm2
+
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,160(%r10)
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,176(%r10)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,192(%r10)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,208(%r10)
+	movdqa	%xmm4,%xmm2
+
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,224(%r10)
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,240(%r10)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,256(%r10)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,272(%r10)
+	movdqa	%xmm4,%xmm2
+
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,288(%r10)
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,304(%r10)
+
+	paddd	%xmm2,%xmm3
+.byte	0x67
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,320(%r10)
+
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,336(%r10)
+	pand	64(%r12),%xmm0
+
+	pand	80(%r12),%xmm1
+	pand	96(%r12),%xmm2
+	movdqa	%xmm3,352(%r10)
+	pand	112(%r12),%xmm3
 	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	movdqa	-128(%r12),%xmm4
+	movdqa	-112(%r12),%xmm5
+	movdqa	-96(%r12),%xmm2
+	pand	112(%r10),%xmm4
+	movdqa	-80(%r12),%xmm3
+	pand	128(%r10),%xmm5
+	por	%xmm4,%xmm0
+	pand	144(%r10),%xmm2
+	por	%xmm5,%xmm1
+	pand	160(%r10),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	movdqa	-64(%r12),%xmm4
+	movdqa	-48(%r12),%xmm5
+	movdqa	-32(%r12),%xmm2
+	pand	176(%r10),%xmm4
+	movdqa	-16(%r12),%xmm3
+	pand	192(%r10),%xmm5
+	por	%xmm4,%xmm0
+	pand	208(%r10),%xmm2
+	por	%xmm5,%xmm1
+	pand	224(%r10),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	movdqa	0(%r12),%xmm4
+	movdqa	16(%r12),%xmm5
+	movdqa	32(%r12),%xmm2
+	pand	240(%r10),%xmm4
+	movdqa	48(%r12),%xmm3
+	pand	256(%r10),%xmm5
+	por	%xmm4,%xmm0
+	pand	272(%r10),%xmm2
+	por	%xmm5,%xmm1
+	pand	288(%r10),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	por	%xmm1,%xmm0
+	pshufd	$0x4e,%xmm0,%xmm1
+	por	%xmm1,%xmm0
 	leaq	256(%r12),%r12
-	por	%xmm3,%xmm0
-
 .byte	102,72,15,126,195
 
 	movq	(%r8),%r8
@@ -64,29 +203,14 @@
 	xorq	%r14,%r14
 	xorq	%r15,%r15
 
-	movq	-96(%r12),%xmm0
-	movq	-32(%r12),%xmm1
-	pand	%xmm4,%xmm0
-	movq	32(%r12),%xmm2
-	pand	%xmm5,%xmm1
-
 	movq	%r8,%rbp
 	mulq	%rbx
 	movq	%rax,%r10
 	movq	(%rcx),%rax
 
-	movq	96(%r12),%xmm3
-	pand	%xmm6,%xmm2
-	por	%xmm1,%xmm0
-	pand	%xmm7,%xmm3
-
 	imulq	%r10,%rbp
 	movq	%rdx,%r11
 
-	por	%xmm2,%xmm0
-	leaq	256(%r12),%r12
-	por	%xmm3,%xmm0
-
 	mulq	%rbp
 	addq	%rax,%r10
 	movq	8(%rsi),%rax
@@ -119,14 +243,12 @@
 	cmpq	%r9,%r15
 	jne	L$1st
 
-.byte	102,72,15,126,195
 
 	addq	%rax,%r13
-	movq	(%rsi),%rax
 	adcq	$0,%rdx
 	addq	%r11,%r13
 	adcq	$0,%rdx
-	movq	%r13,-16(%rsp,%r15,8)
+	movq	%r13,-16(%rsp,%r9,8)
 	movq	%rdx,%r13
 	movq	%r10,%r11
 
@@ -140,33 +262,78 @@
 	jmp	L$outer
 .p2align	4
 L$outer:
+	leaq	24+128(%rsp,%r9,8),%rdx
+	andq	$-16,%rdx
+	pxor	%xmm4,%xmm4
+	pxor	%xmm5,%xmm5
+	movdqa	-128(%r12),%xmm0
+	movdqa	-112(%r12),%xmm1
+	movdqa	-96(%r12),%xmm2
+	movdqa	-80(%r12),%xmm3
+	pand	-128(%rdx),%xmm0
+	pand	-112(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	-96(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	-80(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	-64(%r12),%xmm0
+	movdqa	-48(%r12),%xmm1
+	movdqa	-32(%r12),%xmm2
+	movdqa	-16(%r12),%xmm3
+	pand	-64(%rdx),%xmm0
+	pand	-48(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	-32(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	-16(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	0(%r12),%xmm0
+	movdqa	16(%r12),%xmm1
+	movdqa	32(%r12),%xmm2
+	movdqa	48(%r12),%xmm3
+	pand	0(%rdx),%xmm0
+	pand	16(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	32(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	48(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	64(%r12),%xmm0
+	movdqa	80(%r12),%xmm1
+	movdqa	96(%r12),%xmm2
+	movdqa	112(%r12),%xmm3
+	pand	64(%rdx),%xmm0
+	pand	80(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	96(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	112(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	por	%xmm5,%xmm4
+	pshufd	$0x4e,%xmm4,%xmm0
+	por	%xmm4,%xmm0
+	leaq	256(%r12),%r12
+
+	movq	(%rsi),%rax
+.byte	102,72,15,126,195
+
 	xorq	%r15,%r15
 	movq	%r8,%rbp
 	movq	(%rsp),%r10
 
-	movq	-96(%r12),%xmm0
-	movq	-32(%r12),%xmm1
-	pand	%xmm4,%xmm0
-	movq	32(%r12),%xmm2
-	pand	%xmm5,%xmm1
-
 	mulq	%rbx
 	addq	%rax,%r10
 	movq	(%rcx),%rax
 	adcq	$0,%rdx
 
-	movq	96(%r12),%xmm3
-	pand	%xmm6,%xmm2
-	por	%xmm1,%xmm0
-	pand	%xmm7,%xmm3
-
 	imulq	%r10,%rbp
 	movq	%rdx,%r11
 
-	por	%xmm2,%xmm0
-	leaq	256(%r12),%r12
-	por	%xmm3,%xmm0
-
 	mulq	%rbp
 	addq	%rax,%r10
 	movq	8(%rsi),%rax
@@ -202,15 +369,12 @@
 	cmpq	%r9,%r15
 	jne	L$inner
 
-.byte	102,72,15,126,195
-
 	addq	%rax,%r13
-	movq	(%rsi),%rax
 	adcq	$0,%rdx
 	addq	%r10,%r13
-	movq	(%rsp,%r15,8),%r10
+	movq	(%rsp,%r9,8),%r10
 	adcq	$0,%rdx
-	movq	%r13,-16(%rsp,%r15,8)
+	movq	%r13,-16(%rsp,%r9,8)
 	movq	%rdx,%r13
 
 	xorq	%rdx,%rdx
@@ -240,48 +404,68 @@
 
 	sbbq	$0,%rax
 	xorq	%r14,%r14
+	andq	%rax,%rsi
+	notq	%rax
+	movq	%rdi,%rcx
+	andq	%rax,%rcx
 	movq	%r9,%r15
+	orq	%rcx,%rsi
 .p2align	4
 L$copy:
-	movq	(%rsp,%r14,8),%rsi
-	movq	(%rdi,%r14,8),%rcx
-	xorq	%rcx,%rsi
-	andq	%rax,%rsi
-	xorq	%rcx,%rsi
+	movq	(%rsi,%r14,8),%rax
 	movq	%r14,(%rsp,%r14,8)
-	movq	%rsi,(%rdi,%r14,8)
+	movq	%rax,(%rdi,%r14,8)
 	leaq	1(%r14),%r14
 	subq	$1,%r15
 	jnz	L$copy
 
 	movq	8(%rsp,%r9,8),%rsi
+
 	movq	$1,%rax
+
 	movq	-48(%rsi),%r15
+
 	movq	-40(%rsi),%r14
+
 	movq	-32(%rsi),%r13
+
 	movq	-24(%rsi),%r12
+
 	movq	-16(%rsi),%rbp
+
 	movq	-8(%rsi),%rbx
+
 	leaq	(%rsi),%rsp
+
 L$mul_epilogue:
 	.byte	0xf3,0xc3
 
 
+
 .p2align	5
 bn_mul4x_mont_gather5:
-L$mul4x_enter:
+
 .byte	0x67
 	movq	%rsp,%rax
+
+L$mul4x_enter:
 	pushq	%rbx
+
 	pushq	%rbp
+
 	pushq	%r12
+
 	pushq	%r13
+
 	pushq	%r14
+
 	pushq	%r15
+
+L$mul4x_prologue:
+
 .byte	0x67
-	movl	%r9d,%r10d
 	shll	$3,%r9d
-	shll	$3+2,%r10d
+	leaq	(%r9,%r9,2),%r10
 	negq	%r9
 
 
@@ -291,90 +475,214 @@
 
 
 
-	leaq	-64(%rsp,%r9,2),%r11
-	subq	%rsi,%r11
+
+
+	leaq	-320(%rsp,%r9,2),%r11
+	movq	%rsp,%rbp
+	subq	%rdi,%r11
 	andq	$4095,%r11
 	cmpq	%r11,%r10
 	jb	L$mul4xsp_alt
-	subq	%r11,%rsp
-	leaq	-64(%rsp,%r9,2),%rsp
+	subq	%r11,%rbp
+	leaq	-320(%rbp,%r9,2),%rbp
 	jmp	L$mul4xsp_done
 
 .p2align	5
 L$mul4xsp_alt:
-	leaq	4096-64(,%r9,2),%r10
-	leaq	-64(%rsp,%r9,2),%rsp
+	leaq	4096-320(,%r9,2),%r10
+	leaq	-320(%rbp,%r9,2),%rbp
 	subq	%r10,%r11
 	movq	$0,%r10
 	cmovcq	%r10,%r11
-	subq	%r11,%rsp
+	subq	%r11,%rbp
 L$mul4xsp_done:
-	andq	$-64,%rsp
+	andq	$-64,%rbp
+	movq	%rsp,%r11
+	subq	%rbp,%r11
+	andq	$-4096,%r11
+	leaq	(%r11,%rbp,1),%rsp
+	movq	(%rsp),%r10
+	cmpq	%rbp,%rsp
+	ja	L$mul4x_page_walk
+	jmp	L$mul4x_page_walk_done
+
+L$mul4x_page_walk:
+	leaq	-4096(%rsp),%rsp
+	movq	(%rsp),%r10
+	cmpq	%rbp,%rsp
+	ja	L$mul4x_page_walk
+L$mul4x_page_walk_done:
+
 	negq	%r9
 
 	movq	%rax,40(%rsp)
+
 L$mul4x_body:
 
 	call	mul4x_internal
 
 	movq	40(%rsp),%rsi
+
 	movq	$1,%rax
+
 	movq	-48(%rsi),%r15
+
 	movq	-40(%rsi),%r14
+
 	movq	-32(%rsi),%r13
+
 	movq	-24(%rsi),%r12
+
 	movq	-16(%rsi),%rbp
+
 	movq	-8(%rsi),%rbx
+
 	leaq	(%rsi),%rsp
+
 L$mul4x_epilogue:
 	.byte	0xf3,0xc3
 
 
 
+
 .p2align	5
 mul4x_internal:
 	shlq	$5,%r9
-	movl	8(%rax),%r10d
-	leaq	256(%rdx,%r9,1),%r13
+	movd	8(%rax),%xmm5
+	leaq	L$inc(%rip),%rax
+	leaq	128(%rdx,%r9,1),%r13
 	shrq	$5,%r9
-	movq	%r10,%r11
-	shrq	$3,%r10
-	andq	$7,%r11
-	notq	%r10
-	leaq	L$magic_masks(%rip),%rax
-	andq	$3,%r10
-	leaq	96(%rdx,%r11,8),%r12
-	movq	0(%rax,%r10,8),%xmm4
-	movq	8(%rax,%r10,8),%xmm5
-	addq	$7,%r11
-	movq	16(%rax,%r10,8),%xmm6
-	movq	24(%rax,%r10,8),%xmm7
-	andq	$7,%r11
+	movdqa	0(%rax),%xmm0
+	movdqa	16(%rax),%xmm1
+	leaq	88-112(%rsp,%r9,1),%r10
+	leaq	128(%rdx),%r12
 
-	movq	-96(%r12),%xmm0
-	leaq	256(%r12),%r14
-	movq	-32(%r12),%xmm1
-	pand	%xmm4,%xmm0
-	movq	32(%r12),%xmm2
-	pand	%xmm5,%xmm1
-	movq	96(%r12),%xmm3
-	pand	%xmm6,%xmm2
+	pshufd	$0,%xmm5,%xmm5
+	movdqa	%xmm1,%xmm4
+.byte	0x67,0x67
+	movdqa	%xmm1,%xmm2
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
 .byte	0x67
-	por	%xmm1,%xmm0
-	movq	-96(%r14),%xmm1
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,112(%r10)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,128(%r10)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,144(%r10)
+	movdqa	%xmm4,%xmm2
+
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,160(%r10)
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,176(%r10)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,192(%r10)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,208(%r10)
+	movdqa	%xmm4,%xmm2
+
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,224(%r10)
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,240(%r10)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,256(%r10)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,272(%r10)
+	movdqa	%xmm4,%xmm2
+
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,288(%r10)
+	movdqa	%xmm4,%xmm3
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,304(%r10)
+
+	paddd	%xmm2,%xmm3
 .byte	0x67
-	pand	%xmm7,%xmm3
-.byte	0x67
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,320(%r10)
+
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,336(%r10)
+	pand	64(%r12),%xmm0
+
+	pand	80(%r12),%xmm1
+	pand	96(%r12),%xmm2
+	movdqa	%xmm3,352(%r10)
+	pand	112(%r12),%xmm3
 	por	%xmm2,%xmm0
-	movq	-32(%r14),%xmm2
-.byte	0x67
-	pand	%xmm4,%xmm1
-.byte	0x67
-	por	%xmm3,%xmm0
-	movq	32(%r14),%xmm3
-
+	por	%xmm3,%xmm1
+	movdqa	-128(%r12),%xmm4
+	movdqa	-112(%r12),%xmm5
+	movdqa	-96(%r12),%xmm2
+	pand	112(%r10),%xmm4
+	movdqa	-80(%r12),%xmm3
+	pand	128(%r10),%xmm5
+	por	%xmm4,%xmm0
+	pand	144(%r10),%xmm2
+	por	%xmm5,%xmm1
+	pand	160(%r10),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	movdqa	-64(%r12),%xmm4
+	movdqa	-48(%r12),%xmm5
+	movdqa	-32(%r12),%xmm2
+	pand	176(%r10),%xmm4
+	movdqa	-16(%r12),%xmm3
+	pand	192(%r10),%xmm5
+	por	%xmm4,%xmm0
+	pand	208(%r10),%xmm2
+	por	%xmm5,%xmm1
+	pand	224(%r10),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	movdqa	0(%r12),%xmm4
+	movdqa	16(%r12),%xmm5
+	movdqa	32(%r12),%xmm2
+	pand	240(%r10),%xmm4
+	movdqa	48(%r12),%xmm3
+	pand	256(%r10),%xmm5
+	por	%xmm4,%xmm0
+	pand	272(%r10),%xmm2
+	por	%xmm5,%xmm1
+	pand	288(%r10),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+	por	%xmm1,%xmm0
+	pshufd	$0x4e,%xmm0,%xmm1
+	por	%xmm1,%xmm0
+	leaq	256(%r12),%r12
 .byte	102,72,15,126,195
-	movq	96(%r14),%xmm0
+
 	movq	%r13,16+8(%rsp)
 	movq	%rdi,56+8(%rsp)
 
@@ -388,26 +696,10 @@
 	movq	%rax,%r10
 	movq	(%rcx),%rax
 
-	pand	%xmm5,%xmm2
-	pand	%xmm6,%xmm3
-	por	%xmm2,%xmm1
-
 	imulq	%r10,%rbp
-
-
-
-
-
-
-
-	leaq	64+8(%rsp,%r11,8),%r14
+	leaq	64+8(%rsp),%r14
 	movq	%rdx,%r11
 
-	pand	%xmm7,%xmm0
-	por	%xmm3,%xmm1
-	leaq	512(%r12),%r12
-	por	%xmm1,%xmm0
-
 	mulq	%rbp
 	addq	%rax,%r10
 	movq	8(%rsi,%r9,1),%rax
@@ -416,7 +708,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r11
-	movq	16(%rcx),%rax
+	movq	8(%rcx),%rax
 	adcq	$0,%rdx
 	movq	%rdx,%r10
 
@@ -426,7 +718,7 @@
 	adcq	$0,%rdx
 	addq	%r11,%rdi
 	leaq	32(%r9),%r15
-	leaq	64(%rcx),%rcx
+	leaq	32(%rcx),%rcx
 	adcq	$0,%rdx
 	movq	%rdi,(%r14)
 	movq	%rdx,%r13
@@ -436,7 +728,7 @@
 L$1st4x:
 	mulq	%rbx
 	addq	%rax,%r10
-	movq	-32(%rcx),%rax
+	movq	-16(%rcx),%rax
 	leaq	32(%r14),%r14
 	adcq	$0,%rdx
 	movq	%rdx,%r11
@@ -452,7 +744,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r11
-	movq	-16(%rcx),%rax
+	movq	-8(%rcx),%rax
 	adcq	$0,%rdx
 	movq	%rdx,%r10
 
@@ -482,7 +774,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r11
-	movq	16(%rcx),%rax
+	movq	8(%rcx),%rax
 	adcq	$0,%rdx
 	movq	%rdx,%r10
 
@@ -491,7 +783,7 @@
 	movq	16(%rsi,%r15,1),%rax
 	adcq	$0,%rdx
 	addq	%r11,%rdi
-	leaq	64(%rcx),%rcx
+	leaq	32(%rcx),%rcx
 	adcq	$0,%rdx
 	movq	%rdi,(%r14)
 	movq	%rdx,%r13
@@ -501,7 +793,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r10
-	movq	-32(%rcx),%rax
+	movq	-16(%rcx),%rax
 	leaq	32(%r14),%r14
 	adcq	$0,%rdx
 	movq	%rdx,%r11
@@ -517,7 +809,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r11
-	movq	-16(%rcx),%rax
+	movq	-8(%rcx),%rax
 	adcq	$0,%rdx
 	movq	%rdx,%r10
 
@@ -530,8 +822,7 @@
 	movq	%rdi,-16(%r14)
 	movq	%rdx,%r13
 
-.byte	102,72,15,126,195
-	leaq	(%rcx,%r9,2),%rcx
+	leaq	(%rcx,%r9,1),%rcx
 
 	xorq	%rdi,%rdi
 	addq	%r10,%r13
@@ -542,6 +833,63 @@
 
 .p2align	5
 L$outer4x:
+	leaq	16+128(%r14),%rdx
+	pxor	%xmm4,%xmm4
+	pxor	%xmm5,%xmm5
+	movdqa	-128(%r12),%xmm0
+	movdqa	-112(%r12),%xmm1
+	movdqa	-96(%r12),%xmm2
+	movdqa	-80(%r12),%xmm3
+	pand	-128(%rdx),%xmm0
+	pand	-112(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	-96(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	-80(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	-64(%r12),%xmm0
+	movdqa	-48(%r12),%xmm1
+	movdqa	-32(%r12),%xmm2
+	movdqa	-16(%r12),%xmm3
+	pand	-64(%rdx),%xmm0
+	pand	-48(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	-32(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	-16(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	0(%r12),%xmm0
+	movdqa	16(%r12),%xmm1
+	movdqa	32(%r12),%xmm2
+	movdqa	48(%r12),%xmm3
+	pand	0(%rdx),%xmm0
+	pand	16(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	32(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	48(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	64(%r12),%xmm0
+	movdqa	80(%r12),%xmm1
+	movdqa	96(%r12),%xmm2
+	movdqa	112(%r12),%xmm3
+	pand	64(%rdx),%xmm0
+	pand	80(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	96(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	112(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	por	%xmm5,%xmm4
+	pshufd	$0x4e,%xmm4,%xmm0
+	por	%xmm4,%xmm0
+	leaq	256(%r12),%r12
+.byte	102,72,15,126,195
+
 	movq	(%r14,%r9,1),%r10
 	movq	%r8,%rbp
 	mulq	%rbx
@@ -549,25 +897,11 @@
 	movq	(%rcx),%rax
 	adcq	$0,%rdx
 
-	movq	-96(%r12),%xmm0
-	movq	-32(%r12),%xmm1
-	pand	%xmm4,%xmm0
-	movq	32(%r12),%xmm2
-	pand	%xmm5,%xmm1
-	movq	96(%r12),%xmm3
-
 	imulq	%r10,%rbp
-.byte	0x67
 	movq	%rdx,%r11
 	movq	%rdi,(%r14)
 
-	pand	%xmm6,%xmm2
-	por	%xmm1,%xmm0
-	pand	%xmm7,%xmm3
-	por	%xmm2,%xmm0
 	leaq	(%r14,%r9,1),%r14
-	leaq	256(%r12),%r12
-	por	%xmm3,%xmm0
 
 	mulq	%rbp
 	addq	%rax,%r10
@@ -577,7 +911,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r11
-	movq	16(%rcx),%rax
+	movq	8(%rcx),%rax
 	adcq	$0,%rdx
 	addq	8(%r14),%r11
 	adcq	$0,%rdx
@@ -589,7 +923,7 @@
 	adcq	$0,%rdx
 	addq	%r11,%rdi
 	leaq	32(%r9),%r15
-	leaq	64(%rcx),%rcx
+	leaq	32(%rcx),%rcx
 	adcq	$0,%rdx
 	movq	%rdx,%r13
 	jmp	L$inner4x
@@ -598,7 +932,7 @@
 L$inner4x:
 	mulq	%rbx
 	addq	%rax,%r10
-	movq	-32(%rcx),%rax
+	movq	-16(%rcx),%rax
 	adcq	$0,%rdx
 	addq	16(%r14),%r10
 	leaq	32(%r14),%r14
@@ -616,7 +950,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r11
-	movq	-16(%rcx),%rax
+	movq	-8(%rcx),%rax
 	adcq	$0,%rdx
 	addq	-8(%r14),%r11
 	adcq	$0,%rdx
@@ -650,7 +984,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r11
-	movq	16(%rcx),%rax
+	movq	8(%rcx),%rax
 	adcq	$0,%rdx
 	addq	8(%r14),%r11
 	adcq	$0,%rdx
@@ -661,7 +995,7 @@
 	movq	16(%rsi,%r15,1),%rax
 	adcq	$0,%rdx
 	addq	%r11,%rdi
-	leaq	64(%rcx),%rcx
+	leaq	32(%rcx),%rcx
 	adcq	$0,%rdx
 	movq	%r13,-8(%r14)
 	movq	%rdx,%r13
@@ -671,7 +1005,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r10
-	movq	-32(%rcx),%rax
+	movq	-16(%rcx),%rax
 	adcq	$0,%rdx
 	addq	16(%r14),%r10
 	leaq	32(%r14),%r14
@@ -690,7 +1024,7 @@
 	mulq	%rbx
 	addq	%rax,%r11
 	movq	%rbp,%rax
-	movq	-16(%rcx),%rbp
+	movq	-8(%rcx),%rbp
 	adcq	$0,%rdx
 	addq	-8(%r14),%r11
 	adcq	$0,%rdx
@@ -705,9 +1039,8 @@
 	movq	%r13,-24(%r14)
 	movq	%rdx,%r13
 
-.byte	102,72,15,126,195
 	movq	%rdi,-16(%r14)
-	leaq	(%rcx,%r9,2),%rcx
+	leaq	(%rcx,%r9,1),%rcx
 
 	xorq	%rdi,%rdi
 	addq	%r10,%r13
@@ -718,32 +1051,48 @@
 
 	cmpq	16+8(%rsp),%r12
 	jb	L$outer4x
+	xorq	%rax,%rax
 	subq	%r13,%rbp
 	adcq	%r15,%r15
 	orq	%r15,%rdi
-	xorq	$1,%rdi
+	subq	%rdi,%rax
 	leaq	(%r14,%r9,1),%rbx
-	leaq	(%rcx,%rdi,8),%rbp
+	movq	(%rcx),%r12
+	leaq	(%rcx),%rbp
 	movq	%r9,%rcx
 	sarq	$3+2,%rcx
 	movq	56+8(%rsp),%rdi
-	jmp	L$sqr4x_sub
+	decq	%r12
+	xorq	%r10,%r10
+	movq	8(%rbp),%r13
+	movq	16(%rbp),%r14
+	movq	24(%rbp),%r15
+	jmp	L$sqr4x_sub_entry
 
 .globl	_bn_power5
 .private_extern _bn_power5
 
 .p2align	5
 _bn_power5:
+
 	movq	%rsp,%rax
+
 	pushq	%rbx
+
 	pushq	%rbp
+
 	pushq	%r12
+
 	pushq	%r13
+
 	pushq	%r14
+
 	pushq	%r15
-	movl	%r9d,%r10d
+
+L$power5_prologue:
+
 	shll	$3,%r9d
-	shll	$3+2,%r10d
+	leal	(%r9,%r9,2),%r10d
 	negq	%r9
 	movq	(%r8),%r8
 
@@ -753,25 +1102,43 @@
 
 
 
-	leaq	-64(%rsp,%r9,2),%r11
-	subq	%rsi,%r11
+
+	leaq	-320(%rsp,%r9,2),%r11
+	movq	%rsp,%rbp
+	subq	%rdi,%r11
 	andq	$4095,%r11
 	cmpq	%r11,%r10
 	jb	L$pwr_sp_alt
-	subq	%r11,%rsp
-	leaq	-64(%rsp,%r9,2),%rsp
+	subq	%r11,%rbp
+	leaq	-320(%rbp,%r9,2),%rbp
 	jmp	L$pwr_sp_done
 
 .p2align	5
 L$pwr_sp_alt:
-	leaq	4096-64(,%r9,2),%r10
-	leaq	-64(%rsp,%r9,2),%rsp
+	leaq	4096-320(,%r9,2),%r10
+	leaq	-320(%rbp,%r9,2),%rbp
 	subq	%r10,%r11
 	movq	$0,%r10
 	cmovcq	%r10,%r11
-	subq	%r11,%rsp
+	subq	%r11,%rbp
 L$pwr_sp_done:
-	andq	$-64,%rsp
+	andq	$-64,%rbp
+	movq	%rsp,%r11
+	subq	%rbp,%r11
+	andq	$-4096,%r11
+	leaq	(%r11,%rbp,1),%rsp
+	movq	(%rsp),%r10
+	cmpq	%rbp,%rsp
+	ja	L$pwr_page_walk
+	jmp	L$pwr_page_walk_done
+
+L$pwr_page_walk:
+	leaq	-4096(%rsp),%rsp
+	movq	(%rsp),%r10
+	cmpq	%rbp,%rsp
+	ja	L$pwr_page_walk
+L$pwr_page_walk_done:
+
 	movq	%r9,%r10
 	negq	%r9
 
@@ -786,6 +1153,7 @@
 
 	movq	%r8,32(%rsp)
 	movq	%rax,40(%rsp)
+
 L$power5_body:
 .byte	102,72,15,110,207
 .byte	102,72,15,110,209
@@ -793,10 +1161,15 @@
 .byte	102,72,15,110,226
 
 	call	__bn_sqr8x_internal
+	call	__bn_post4x_internal
 	call	__bn_sqr8x_internal
+	call	__bn_post4x_internal
 	call	__bn_sqr8x_internal
+	call	__bn_post4x_internal
 	call	__bn_sqr8x_internal
+	call	__bn_post4x_internal
 	call	__bn_sqr8x_internal
+	call	__bn_post4x_internal
 
 .byte	102,72,15,126,209
 .byte	102,72,15,126,226
@@ -807,18 +1180,27 @@
 	call	mul4x_internal
 
 	movq	40(%rsp),%rsi
+
 	movq	$1,%rax
 	movq	-48(%rsi),%r15
+
 	movq	-40(%rsi),%r14
+
 	movq	-32(%rsi),%r13
+
 	movq	-24(%rsi),%r12
+
 	movq	-16(%rsi),%rbp
+
 	movq	-8(%rsi),%rbx
+
 	leaq	(%rsi),%rsp
+
 L$power5_epilogue:
 	.byte	0xf3,0xc3
 
 
+
 .globl	_bn_sqr8x_internal
 .private_extern _bn_sqr8x_internal
 .private_extern	_bn_sqr8x_internal
@@ -1341,9 +1723,9 @@
 	movq	%rbx,-16(%rdi)
 	movq	%r8,-8(%rdi)
 .byte	102,72,15,126,213
-sqr8x_reduction:
+__bn_sqr8x_reduction:
 	xorq	%rax,%rax
-	leaq	(%rbp,%r9,2),%rcx
+	leaq	(%r9,%rbp,1),%rcx
 	leaq	48+8(%rsp,%r9,2),%rdx
 	movq	%rcx,0+8(%rsp)
 	leaq	48+8(%rsp,%r9,1),%rdi
@@ -1376,14 +1758,14 @@
 .p2align	5
 L$8x_reduce:
 	mulq	%rbx
-	movq	16(%rbp),%rax
+	movq	8(%rbp),%rax
 	negq	%r8
 	movq	%rdx,%r8
 	adcq	$0,%r8
 
 	mulq	%rbx
 	addq	%rax,%r9
-	movq	32(%rbp),%rax
+	movq	16(%rbp),%rax
 	adcq	$0,%rdx
 	addq	%r9,%r8
 	movq	%rbx,48-8+8(%rsp,%rcx,8)
@@ -1392,7 +1774,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r10
-	movq	48(%rbp),%rax
+	movq	24(%rbp),%rax
 	adcq	$0,%rdx
 	addq	%r10,%r9
 	movq	32+8(%rsp),%rsi
@@ -1401,7 +1783,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r11
-	movq	64(%rbp),%rax
+	movq	32(%rbp),%rax
 	adcq	$0,%rdx
 	imulq	%r8,%rsi
 	addq	%r11,%r10
@@ -1410,7 +1792,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r12
-	movq	80(%rbp),%rax
+	movq	40(%rbp),%rax
 	adcq	$0,%rdx
 	addq	%r12,%r11
 	movq	%rdx,%r12
@@ -1418,7 +1800,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r13
-	movq	96(%rbp),%rax
+	movq	48(%rbp),%rax
 	adcq	$0,%rdx
 	addq	%r13,%r12
 	movq	%rdx,%r13
@@ -1426,7 +1808,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r14
-	movq	112(%rbp),%rax
+	movq	56(%rbp),%rax
 	adcq	$0,%rdx
 	addq	%r14,%r13
 	movq	%rdx,%r14
@@ -1444,7 +1826,7 @@
 	decl	%ecx
 	jnz	L$8x_reduce
 
-	leaq	128(%rbp),%rbp
+	leaq	64(%rbp),%rbp
 	xorq	%rax,%rax
 	movq	8+8(%rsp),%rdx
 	cmpq	0+8(%rsp),%rbp
@@ -1470,14 +1852,14 @@
 L$8x_tail:
 	mulq	%rbx
 	addq	%rax,%r8
-	movq	16(%rbp),%rax
+	movq	8(%rbp),%rax
 	movq	%r8,(%rdi)
 	movq	%rdx,%r8
 	adcq	$0,%r8
 
 	mulq	%rbx
 	addq	%rax,%r9
-	movq	32(%rbp),%rax
+	movq	16(%rbp),%rax
 	adcq	$0,%rdx
 	addq	%r9,%r8
 	leaq	8(%rdi),%rdi
@@ -1486,7 +1868,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r10
-	movq	48(%rbp),%rax
+	movq	24(%rbp),%rax
 	adcq	$0,%rdx
 	addq	%r10,%r9
 	movq	%rdx,%r10
@@ -1494,7 +1876,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r11
-	movq	64(%rbp),%rax
+	movq	32(%rbp),%rax
 	adcq	$0,%rdx
 	addq	%r11,%r10
 	movq	%rdx,%r11
@@ -1502,7 +1884,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r12
-	movq	80(%rbp),%rax
+	movq	40(%rbp),%rax
 	adcq	$0,%rdx
 	addq	%r12,%r11
 	movq	%rdx,%r12
@@ -1510,7 +1892,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r13
-	movq	96(%rbp),%rax
+	movq	48(%rbp),%rax
 	adcq	$0,%rdx
 	addq	%r13,%r12
 	movq	%rdx,%r13
@@ -1518,7 +1900,7 @@
 
 	mulq	%rbx
 	addq	%rax,%r14
-	movq	112(%rbp),%rax
+	movq	56(%rbp),%rax
 	adcq	$0,%rdx
 	addq	%r14,%r13
 	movq	%rdx,%r14
@@ -1536,7 +1918,7 @@
 	decl	%ecx
 	jnz	L$8x_tail
 
-	leaq	128(%rbp),%rbp
+	leaq	64(%rbp),%rbp
 	movq	8+8(%rsp),%rdx
 	cmpq	0+8(%rsp),%rbp
 	jae	L$8x_tail_done
@@ -1559,6 +1941,7 @@
 
 .p2align	5
 L$8x_tail_done:
+	xorq	%rax,%rax
 	addq	(%rdx),%r8
 	adcq	$0,%r9
 	adcq	$0,%r10
@@ -1567,9 +1950,7 @@
 	adcq	$0,%r13
 	adcq	$0,%r14
 	adcq	$0,%r15
-
-
-	xorq	%rax,%rax
+	adcq	$0,%rax
 
 	negq	%rsi
 L$8x_no_tail:
@@ -1582,7 +1963,7 @@
 	adcq	48(%rdi),%r14
 	adcq	56(%rdi),%r15
 	adcq	$0,%rax
-	movq	-16(%rbp),%rcx
+	movq	-8(%rbp),%rcx
 	xorq	%rsi,%rsi
 
 .byte	102,72,15,126,213
@@ -1600,40 +1981,58 @@
 
 	cmpq	%rdx,%rdi
 	jb	L$8x_reduction_loop
+	.byte	0xf3,0xc3
 
-	subq	%r15,%rcx
-	leaq	(%rdi,%r9,1),%rbx
-	adcq	%rsi,%rsi
-	movq	%r9,%rcx
-	orq	%rsi,%rax
-.byte	102,72,15,126,207
-	xorq	$1,%rax
-.byte	102,72,15,126,206
-	leaq	(%rbp,%rax,8),%rbp
-	sarq	$3+2,%rcx
-	jmp	L$sqr4x_sub
 
 .p2align	5
+__bn_post4x_internal:
+	movq	0(%rbp),%r12
+	leaq	(%rdi,%r9,1),%rbx
+	movq	%r9,%rcx
+.byte	102,72,15,126,207
+	negq	%rax
+.byte	102,72,15,126,206
+	sarq	$3+2,%rcx
+	decq	%r12
+	xorq	%r10,%r10
+	movq	8(%rbp),%r13
+	movq	16(%rbp),%r14
+	movq	24(%rbp),%r15
+	jmp	L$sqr4x_sub_entry
+
+.p2align	4
 L$sqr4x_sub:
-.byte	0x66
-	movq	0(%rbx),%r12
-	movq	8(%rbx),%r13
-	sbbq	0(%rbp),%r12
-	movq	16(%rbx),%r14
-	sbbq	16(%rbp),%r13
-	movq	24(%rbx),%r15
-	leaq	32(%rbx),%rbx
-	sbbq	32(%rbp),%r14
+	movq	0(%rbp),%r12
+	movq	8(%rbp),%r13
+	movq	16(%rbp),%r14
+	movq	24(%rbp),%r15
+L$sqr4x_sub_entry:
+	leaq	32(%rbp),%rbp
+	notq	%r12
+	notq	%r13
+	notq	%r14
+	notq	%r15
+	andq	%rax,%r12
+	andq	%rax,%r13
+	andq	%rax,%r14
+	andq	%rax,%r15
+
+	negq	%r10
+	adcq	0(%rbx),%r12
+	adcq	8(%rbx),%r13
+	adcq	16(%rbx),%r14
+	adcq	24(%rbx),%r15
 	movq	%r12,0(%rdi)
-	sbbq	48(%rbp),%r15
-	leaq	64(%rbp),%rbp
+	leaq	32(%rbx),%rbx
 	movq	%r13,8(%rdi)
+	sbbq	%r10,%r10
 	movq	%r14,16(%rdi)
 	movq	%r15,24(%rdi)
 	leaq	32(%rdi),%rdi
 
 	incq	%rcx
 	jnz	L$sqr4x_sub
+
 	movq	%r9,%r10
 	negq	%r9
 	.byte	0xf3,0xc3
@@ -1652,18 +2051,26 @@
 
 .p2align	5
 bn_from_mont8x:
+
 .byte	0x67
 	movq	%rsp,%rax
+
 	pushq	%rbx
+
 	pushq	%rbp
+
 	pushq	%r12
+
 	pushq	%r13
+
 	pushq	%r14
+
 	pushq	%r15
-.byte	0x67
-	movl	%r9d,%r10d
+
+L$from_prologue:
+
 	shll	$3,%r9d
-	shll	$3+2,%r10d
+	leaq	(%r9,%r9,2),%r10
 	negq	%r9
 	movq	(%r8),%r8
 
@@ -1673,25 +2080,43 @@
 
 
 
-	leaq	-64(%rsp,%r9,2),%r11
-	subq	%rsi,%r11
+
+	leaq	-320(%rsp,%r9,2),%r11
+	movq	%rsp,%rbp
+	subq	%rdi,%r11
 	andq	$4095,%r11
 	cmpq	%r11,%r10
 	jb	L$from_sp_alt
-	subq	%r11,%rsp
-	leaq	-64(%rsp,%r9,2),%rsp
+	subq	%r11,%rbp
+	leaq	-320(%rbp,%r9,2),%rbp
 	jmp	L$from_sp_done
 
 .p2align	5
 L$from_sp_alt:
-	leaq	4096-64(,%r9,2),%r10
-	leaq	-64(%rsp,%r9,2),%rsp
+	leaq	4096-320(,%r9,2),%r10
+	leaq	-320(%rbp,%r9,2),%rbp
 	subq	%r10,%r11
 	movq	$0,%r10
 	cmovcq	%r10,%r11
-	subq	%r11,%rsp
+	subq	%r11,%rbp
 L$from_sp_done:
-	andq	$-64,%rsp
+	andq	$-64,%rbp
+	movq	%rsp,%r11
+	subq	%rbp,%r11
+	andq	$-4096,%r11
+	leaq	(%r11,%rbp,1),%rsp
+	movq	(%rsp),%r10
+	cmpq	%rbp,%rsp
+	ja	L$from_page_walk
+	jmp	L$from_page_walk_done
+
+L$from_page_walk:
+	leaq	-4096(%rsp),%rsp
+	movq	(%rsp),%r10
+	cmpq	%rbp,%rsp
+	ja	L$from_page_walk
+L$from_page_walk_done:
+
 	movq	%r9,%r10
 	negq	%r9
 
@@ -1706,6 +2131,7 @@
 
 	movq	%r8,32(%rsp)
 	movq	%rax,40(%rsp)
+
 L$from_body:
 	movq	%r9,%r11
 	leaq	48(%rsp),%rax
@@ -1736,15 +2162,17 @@
 .byte	0x67
 	movq	%rcx,%rbp
 .byte	102,73,15,110,218
-	call	sqr8x_reduction
+	call	__bn_sqr8x_reduction
+	call	__bn_post4x_internal
 
 	pxor	%xmm0,%xmm0
 	leaq	48(%rsp),%rax
-	movq	40(%rsp),%rsi
 	jmp	L$from_mont_zero
 
 .p2align	5
 L$from_mont_zero:
+	movq	40(%rsp),%rsi
+
 	movdqa	%xmm0,0(%rax)
 	movdqa	%xmm0,16(%rax)
 	movdqa	%xmm0,32(%rax)
@@ -1755,15 +2183,23 @@
 
 	movq	$1,%rax
 	movq	-48(%rsi),%r15
+
 	movq	-40(%rsi),%r14
+
 	movq	-32(%rsi),%r13
+
 	movq	-24(%rsi),%r12
+
 	movq	-16(%rsi),%rbp
+
 	movq	-8(%rsi),%rbx
+
 	leaq	(%rsi),%rsp
+
 L$from_epilogue:
 	.byte	0xf3,0xc3
 
+
 .globl	_bn_scatter5
 .private_extern _bn_scatter5
 
@@ -1786,46 +2222,170 @@
 .globl	_bn_gather5
 .private_extern _bn_gather5
 
-.p2align	4
+.p2align	5
 _bn_gather5:
-	movl	%ecx,%r11d
-	shrl	$3,%ecx
-	andq	$7,%r11
-	notl	%ecx
-	leaq	L$magic_masks(%rip),%rax
-	andl	$3,%ecx
-	leaq	128(%rdx,%r11,8),%rdx
-	movq	0(%rax,%rcx,8),%xmm4
-	movq	8(%rax,%rcx,8),%xmm5
-	movq	16(%rax,%rcx,8),%xmm6
-	movq	24(%rax,%rcx,8),%xmm7
-	jmp	L$gather
-.p2align	4
-L$gather:
-	movq	-128(%rdx),%xmm0
-	movq	-64(%rdx),%xmm1
-	pand	%xmm4,%xmm0
-	movq	0(%rdx),%xmm2
-	pand	%xmm5,%xmm1
-	movq	64(%rdx),%xmm3
-	pand	%xmm6,%xmm2
-	por	%xmm1,%xmm0
-	pand	%xmm7,%xmm3
-.byte	0x67,0x67
-	por	%xmm2,%xmm0
-	leaq	256(%rdx),%rdx
-	por	%xmm3,%xmm0
+L$SEH_begin_bn_gather5:
 
+.byte	0x4c,0x8d,0x14,0x24
+.byte	0x48,0x81,0xec,0x08,0x01,0x00,0x00
+	leaq	L$inc(%rip),%rax
+	andq	$-16,%rsp
+
+	movd	%ecx,%xmm5
+	movdqa	0(%rax),%xmm0
+	movdqa	16(%rax),%xmm1
+	leaq	128(%rdx),%r11
+	leaq	128(%rsp),%rax
+
+	pshufd	$0,%xmm5,%xmm5
+	movdqa	%xmm1,%xmm4
+	movdqa	%xmm1,%xmm2
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm4,%xmm3
+
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,-128(%rax)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,-112(%rax)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,-96(%rax)
+	movdqa	%xmm4,%xmm2
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,-80(%rax)
+	movdqa	%xmm4,%xmm3
+
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,-64(%rax)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,-48(%rax)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,-32(%rax)
+	movdqa	%xmm4,%xmm2
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,-16(%rax)
+	movdqa	%xmm4,%xmm3
+
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,0(%rax)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,16(%rax)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,32(%rax)
+	movdqa	%xmm4,%xmm2
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,48(%rax)
+	movdqa	%xmm4,%xmm3
+
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,64(%rax)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,80(%rax)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,96(%rax)
+	movdqa	%xmm4,%xmm2
+	movdqa	%xmm3,112(%rax)
+	jmp	L$gather
+
+.p2align	5
+L$gather:
+	pxor	%xmm4,%xmm4
+	pxor	%xmm5,%xmm5
+	movdqa	-128(%r11),%xmm0
+	movdqa	-112(%r11),%xmm1
+	movdqa	-96(%r11),%xmm2
+	pand	-128(%rax),%xmm0
+	movdqa	-80(%r11),%xmm3
+	pand	-112(%rax),%xmm1
+	por	%xmm0,%xmm4
+	pand	-96(%rax),%xmm2
+	por	%xmm1,%xmm5
+	pand	-80(%rax),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	-64(%r11),%xmm0
+	movdqa	-48(%r11),%xmm1
+	movdqa	-32(%r11),%xmm2
+	pand	-64(%rax),%xmm0
+	movdqa	-16(%r11),%xmm3
+	pand	-48(%rax),%xmm1
+	por	%xmm0,%xmm4
+	pand	-32(%rax),%xmm2
+	por	%xmm1,%xmm5
+	pand	-16(%rax),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	0(%r11),%xmm0
+	movdqa	16(%r11),%xmm1
+	movdqa	32(%r11),%xmm2
+	pand	0(%rax),%xmm0
+	movdqa	48(%r11),%xmm3
+	pand	16(%rax),%xmm1
+	por	%xmm0,%xmm4
+	pand	32(%rax),%xmm2
+	por	%xmm1,%xmm5
+	pand	48(%rax),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqa	64(%r11),%xmm0
+	movdqa	80(%r11),%xmm1
+	movdqa	96(%r11),%xmm2
+	pand	64(%rax),%xmm0
+	movdqa	112(%r11),%xmm3
+	pand	80(%rax),%xmm1
+	por	%xmm0,%xmm4
+	pand	96(%rax),%xmm2
+	por	%xmm1,%xmm5
+	pand	112(%rax),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	por	%xmm5,%xmm4
+	leaq	256(%r11),%r11
+	pshufd	$0x4e,%xmm4,%xmm0
+	por	%xmm4,%xmm0
 	movq	%xmm0,(%rdi)
 	leaq	8(%rdi),%rdi
 	subl	$1,%esi
 	jnz	L$gather
+
+	leaq	(%r10),%rsp
 	.byte	0xf3,0xc3
 L$SEH_end_bn_gather5:
 
 .p2align	6
-L$magic_masks:
-.long	0,0, 0,0, 0,0, -1,-1
-.long	0,0, 0,0, 0,0,  0,0
+L$inc:
+.long	0,0, 1,1
+.long	2,2, 2,2
 .byte	77,111,110,116,103,111,109,101,114,121,32,77,117,108,116,105,112,108,105,99,97,116,105,111,110,32,119,105,116,104,32,115,99,97,116,116,101,114,47,103,97,116,104,101,114,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
 #endif
diff --git a/mac-x86_64/crypto/chacha/chacha-x86_64.S b/mac-x86_64/crypto/chacha/chacha-x86_64.S
new file mode 100644
index 0000000..51c0caa
--- /dev/null
+++ b/mac-x86_64/crypto/chacha/chacha-x86_64.S
@@ -0,0 +1,1585 @@
+#if defined(__x86_64__)
+.text	
+
+
+
+.p2align	6
+L$zero:
+.long	0,0,0,0
+L$one:
+.long	1,0,0,0
+L$inc:
+.long	0,1,2,3
+L$four:
+.long	4,4,4,4
+L$incy:
+.long	0,2,4,6,1,3,5,7
+L$eight:
+.long	8,8,8,8,8,8,8,8
+L$rot16:
+.byte	0x2,0x3,0x0,0x1, 0x6,0x7,0x4,0x5, 0xa,0xb,0x8,0x9, 0xe,0xf,0xc,0xd
+L$rot24:
+.byte	0x3,0x0,0x1,0x2, 0x7,0x4,0x5,0x6, 0xb,0x8,0x9,0xa, 0xf,0xc,0xd,0xe
+L$sigma:
+.byte	101,120,112,97,110,100,32,51,50,45,98,121,116,101,32,107,0
+.p2align	6
+L$zeroz:
+.long	0,0,0,0, 1,0,0,0, 2,0,0,0, 3,0,0,0
+L$fourz:
+.long	4,0,0,0, 4,0,0,0, 4,0,0,0, 4,0,0,0
+L$incz:
+.long	0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+L$sixteen:
+.long	16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16
+.byte	67,104,97,67,104,97,50,48,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.globl	_ChaCha20_ctr32
+.private_extern _ChaCha20_ctr32
+
+.p2align	6
+_ChaCha20_ctr32:
+	cmpq	$0,%rdx
+	je	L$no_data
+	movq	_OPENSSL_ia32cap_P+4(%rip),%r10
+	testl	$512,%r10d
+	jnz	L$ChaCha20_ssse3
+
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	subq	$64+24,%rsp
+L$ctr32_body:
+
+
+	movdqu	(%rcx),%xmm1
+	movdqu	16(%rcx),%xmm2
+	movdqu	(%r8),%xmm3
+	movdqa	L$one(%rip),%xmm4
+
+
+	movdqa	%xmm1,16(%rsp)
+	movdqa	%xmm2,32(%rsp)
+	movdqa	%xmm3,48(%rsp)
+	movq	%rdx,%rbp
+	jmp	L$oop_outer
+
+.p2align	5
+L$oop_outer:
+	movl	$0x61707865,%eax
+	movl	$0x3320646e,%ebx
+	movl	$0x79622d32,%ecx
+	movl	$0x6b206574,%edx
+	movl	16(%rsp),%r8d
+	movl	20(%rsp),%r9d
+	movl	24(%rsp),%r10d
+	movl	28(%rsp),%r11d
+	movd	%xmm3,%r12d
+	movl	52(%rsp),%r13d
+	movl	56(%rsp),%r14d
+	movl	60(%rsp),%r15d
+
+	movq	%rbp,64+0(%rsp)
+	movl	$10,%ebp
+	movq	%rsi,64+8(%rsp)
+.byte	102,72,15,126,214
+	movq	%rdi,64+16(%rsp)
+	movq	%rsi,%rdi
+	shrq	$32,%rdi
+	jmp	L$oop
+
+.p2align	5
+L$oop:
+	addl	%r8d,%eax
+	xorl	%eax,%r12d
+	roll	$16,%r12d
+	addl	%r9d,%ebx
+	xorl	%ebx,%r13d
+	roll	$16,%r13d
+	addl	%r12d,%esi
+	xorl	%esi,%r8d
+	roll	$12,%r8d
+	addl	%r13d,%edi
+	xorl	%edi,%r9d
+	roll	$12,%r9d
+	addl	%r8d,%eax
+	xorl	%eax,%r12d
+	roll	$8,%r12d
+	addl	%r9d,%ebx
+	xorl	%ebx,%r13d
+	roll	$8,%r13d
+	addl	%r12d,%esi
+	xorl	%esi,%r8d
+	roll	$7,%r8d
+	addl	%r13d,%edi
+	xorl	%edi,%r9d
+	roll	$7,%r9d
+	movl	%esi,32(%rsp)
+	movl	%edi,36(%rsp)
+	movl	40(%rsp),%esi
+	movl	44(%rsp),%edi
+	addl	%r10d,%ecx
+	xorl	%ecx,%r14d
+	roll	$16,%r14d
+	addl	%r11d,%edx
+	xorl	%edx,%r15d
+	roll	$16,%r15d
+	addl	%r14d,%esi
+	xorl	%esi,%r10d
+	roll	$12,%r10d
+	addl	%r15d,%edi
+	xorl	%edi,%r11d
+	roll	$12,%r11d
+	addl	%r10d,%ecx
+	xorl	%ecx,%r14d
+	roll	$8,%r14d
+	addl	%r11d,%edx
+	xorl	%edx,%r15d
+	roll	$8,%r15d
+	addl	%r14d,%esi
+	xorl	%esi,%r10d
+	roll	$7,%r10d
+	addl	%r15d,%edi
+	xorl	%edi,%r11d
+	roll	$7,%r11d
+	addl	%r9d,%eax
+	xorl	%eax,%r15d
+	roll	$16,%r15d
+	addl	%r10d,%ebx
+	xorl	%ebx,%r12d
+	roll	$16,%r12d
+	addl	%r15d,%esi
+	xorl	%esi,%r9d
+	roll	$12,%r9d
+	addl	%r12d,%edi
+	xorl	%edi,%r10d
+	roll	$12,%r10d
+	addl	%r9d,%eax
+	xorl	%eax,%r15d
+	roll	$8,%r15d
+	addl	%r10d,%ebx
+	xorl	%ebx,%r12d
+	roll	$8,%r12d
+	addl	%r15d,%esi
+	xorl	%esi,%r9d
+	roll	$7,%r9d
+	addl	%r12d,%edi
+	xorl	%edi,%r10d
+	roll	$7,%r10d
+	movl	%esi,40(%rsp)
+	movl	%edi,44(%rsp)
+	movl	32(%rsp),%esi
+	movl	36(%rsp),%edi
+	addl	%r11d,%ecx
+	xorl	%ecx,%r13d
+	roll	$16,%r13d
+	addl	%r8d,%edx
+	xorl	%edx,%r14d
+	roll	$16,%r14d
+	addl	%r13d,%esi
+	xorl	%esi,%r11d
+	roll	$12,%r11d
+	addl	%r14d,%edi
+	xorl	%edi,%r8d
+	roll	$12,%r8d
+	addl	%r11d,%ecx
+	xorl	%ecx,%r13d
+	roll	$8,%r13d
+	addl	%r8d,%edx
+	xorl	%edx,%r14d
+	roll	$8,%r14d
+	addl	%r13d,%esi
+	xorl	%esi,%r11d
+	roll	$7,%r11d
+	addl	%r14d,%edi
+	xorl	%edi,%r8d
+	roll	$7,%r8d
+	decl	%ebp
+	jnz	L$oop
+	movl	%edi,36(%rsp)
+	movl	%esi,32(%rsp)
+	movq	64(%rsp),%rbp
+	movdqa	%xmm2,%xmm1
+	movq	64+8(%rsp),%rsi
+	paddd	%xmm4,%xmm3
+	movq	64+16(%rsp),%rdi
+
+	addl	$0x61707865,%eax
+	addl	$0x3320646e,%ebx
+	addl	$0x79622d32,%ecx
+	addl	$0x6b206574,%edx
+	addl	16(%rsp),%r8d
+	addl	20(%rsp),%r9d
+	addl	24(%rsp),%r10d
+	addl	28(%rsp),%r11d
+	addl	48(%rsp),%r12d
+	addl	52(%rsp),%r13d
+	addl	56(%rsp),%r14d
+	addl	60(%rsp),%r15d
+	paddd	32(%rsp),%xmm1
+
+	cmpq	$64,%rbp
+	jb	L$tail
+
+	xorl	0(%rsi),%eax
+	xorl	4(%rsi),%ebx
+	xorl	8(%rsi),%ecx
+	xorl	12(%rsi),%edx
+	xorl	16(%rsi),%r8d
+	xorl	20(%rsi),%r9d
+	xorl	24(%rsi),%r10d
+	xorl	28(%rsi),%r11d
+	movdqu	32(%rsi),%xmm0
+	xorl	48(%rsi),%r12d
+	xorl	52(%rsi),%r13d
+	xorl	56(%rsi),%r14d
+	xorl	60(%rsi),%r15d
+	leaq	64(%rsi),%rsi
+	pxor	%xmm1,%xmm0
+
+	movdqa	%xmm2,32(%rsp)
+	movd	%xmm3,48(%rsp)
+
+	movl	%eax,0(%rdi)
+	movl	%ebx,4(%rdi)
+	movl	%ecx,8(%rdi)
+	movl	%edx,12(%rdi)
+	movl	%r8d,16(%rdi)
+	movl	%r9d,20(%rdi)
+	movl	%r10d,24(%rdi)
+	movl	%r11d,28(%rdi)
+	movdqu	%xmm0,32(%rdi)
+	movl	%r12d,48(%rdi)
+	movl	%r13d,52(%rdi)
+	movl	%r14d,56(%rdi)
+	movl	%r15d,60(%rdi)
+	leaq	64(%rdi),%rdi
+
+	subq	$64,%rbp
+	jnz	L$oop_outer
+
+	jmp	L$done
+
+.p2align	4
+L$tail:
+	movl	%eax,0(%rsp)
+	movl	%ebx,4(%rsp)
+	xorq	%rbx,%rbx
+	movl	%ecx,8(%rsp)
+	movl	%edx,12(%rsp)
+	movl	%r8d,16(%rsp)
+	movl	%r9d,20(%rsp)
+	movl	%r10d,24(%rsp)
+	movl	%r11d,28(%rsp)
+	movdqa	%xmm1,32(%rsp)
+	movl	%r12d,48(%rsp)
+	movl	%r13d,52(%rsp)
+	movl	%r14d,56(%rsp)
+	movl	%r15d,60(%rsp)
+
+L$oop_tail:
+	movzbl	(%rsi,%rbx,1),%eax
+	movzbl	(%rsp,%rbx,1),%edx
+	leaq	1(%rbx),%rbx
+	xorl	%edx,%eax
+	movb	%al,-1(%rdi,%rbx,1)
+	decq	%rbp
+	jnz	L$oop_tail
+
+L$done:
+	leaq	64+24+48(%rsp),%rsi
+	movq	-48(%rsi),%r15
+	movq	-40(%rsi),%r14
+	movq	-32(%rsi),%r13
+	movq	-24(%rsi),%r12
+	movq	-16(%rsi),%rbp
+	movq	-8(%rsi),%rbx
+	leaq	(%rsi),%rsp
+L$no_data:
+	.byte	0xf3,0xc3
+
+
+.p2align	5
+ChaCha20_ssse3:
+L$ChaCha20_ssse3:
+	movq	%rsp,%r9
+	cmpq	$128,%rdx
+	ja	L$ChaCha20_4x
+
+L$do_sse3_after_all:
+	subq	$64+8,%rsp
+	movdqa	L$sigma(%rip),%xmm0
+	movdqu	(%rcx),%xmm1
+	movdqu	16(%rcx),%xmm2
+	movdqu	(%r8),%xmm3
+	movdqa	L$rot16(%rip),%xmm6
+	movdqa	L$rot24(%rip),%xmm7
+
+	movdqa	%xmm0,0(%rsp)
+	movdqa	%xmm1,16(%rsp)
+	movdqa	%xmm2,32(%rsp)
+	movdqa	%xmm3,48(%rsp)
+	movq	$10,%r8
+	jmp	L$oop_ssse3
+
+.p2align	5
+L$oop_outer_ssse3:
+	movdqa	L$one(%rip),%xmm3
+	movdqa	0(%rsp),%xmm0
+	movdqa	16(%rsp),%xmm1
+	movdqa	32(%rsp),%xmm2
+	paddd	48(%rsp),%xmm3
+	movq	$10,%r8
+	movdqa	%xmm3,48(%rsp)
+	jmp	L$oop_ssse3
+
+.p2align	5
+L$oop_ssse3:
+	paddd	%xmm1,%xmm0
+	pxor	%xmm0,%xmm3
+.byte	102,15,56,0,222
+	paddd	%xmm3,%xmm2
+	pxor	%xmm2,%xmm1
+	movdqa	%xmm1,%xmm4
+	psrld	$20,%xmm1
+	pslld	$12,%xmm4
+	por	%xmm4,%xmm1
+	paddd	%xmm1,%xmm0
+	pxor	%xmm0,%xmm3
+.byte	102,15,56,0,223
+	paddd	%xmm3,%xmm2
+	pxor	%xmm2,%xmm1
+	movdqa	%xmm1,%xmm4
+	psrld	$25,%xmm1
+	pslld	$7,%xmm4
+	por	%xmm4,%xmm1
+	pshufd	$78,%xmm2,%xmm2
+	pshufd	$57,%xmm1,%xmm1
+	pshufd	$147,%xmm3,%xmm3
+	nop
+	paddd	%xmm1,%xmm0
+	pxor	%xmm0,%xmm3
+.byte	102,15,56,0,222
+	paddd	%xmm3,%xmm2
+	pxor	%xmm2,%xmm1
+	movdqa	%xmm1,%xmm4
+	psrld	$20,%xmm1
+	pslld	$12,%xmm4
+	por	%xmm4,%xmm1
+	paddd	%xmm1,%xmm0
+	pxor	%xmm0,%xmm3
+.byte	102,15,56,0,223
+	paddd	%xmm3,%xmm2
+	pxor	%xmm2,%xmm1
+	movdqa	%xmm1,%xmm4
+	psrld	$25,%xmm1
+	pslld	$7,%xmm4
+	por	%xmm4,%xmm1
+	pshufd	$78,%xmm2,%xmm2
+	pshufd	$147,%xmm1,%xmm1
+	pshufd	$57,%xmm3,%xmm3
+	decq	%r8
+	jnz	L$oop_ssse3
+	paddd	0(%rsp),%xmm0
+	paddd	16(%rsp),%xmm1
+	paddd	32(%rsp),%xmm2
+	paddd	48(%rsp),%xmm3
+
+	cmpq	$64,%rdx
+	jb	L$tail_ssse3
+
+	movdqu	0(%rsi),%xmm4
+	movdqu	16(%rsi),%xmm5
+	pxor	%xmm4,%xmm0
+	movdqu	32(%rsi),%xmm4
+	pxor	%xmm5,%xmm1
+	movdqu	48(%rsi),%xmm5
+	leaq	64(%rsi),%rsi
+	pxor	%xmm4,%xmm2
+	pxor	%xmm5,%xmm3
+
+	movdqu	%xmm0,0(%rdi)
+	movdqu	%xmm1,16(%rdi)
+	movdqu	%xmm2,32(%rdi)
+	movdqu	%xmm3,48(%rdi)
+	leaq	64(%rdi),%rdi
+
+	subq	$64,%rdx
+	jnz	L$oop_outer_ssse3
+
+	jmp	L$done_ssse3
+
+.p2align	4
+L$tail_ssse3:
+	movdqa	%xmm0,0(%rsp)
+	movdqa	%xmm1,16(%rsp)
+	movdqa	%xmm2,32(%rsp)
+	movdqa	%xmm3,48(%rsp)
+	xorq	%r8,%r8
+
+L$oop_tail_ssse3:
+	movzbl	(%rsi,%r8,1),%eax
+	movzbl	(%rsp,%r8,1),%ecx
+	leaq	1(%r8),%r8
+	xorl	%ecx,%eax
+	movb	%al,-1(%rdi,%r8,1)
+	decq	%rdx
+	jnz	L$oop_tail_ssse3
+
+L$done_ssse3:
+	leaq	(%r9),%rsp
+L$ssse3_epilogue:
+	.byte	0xf3,0xc3
+
+
+.p2align	5
+ChaCha20_4x:
+L$ChaCha20_4x:
+	movq	%rsp,%r9
+	movq	%r10,%r11
+	shrq	$32,%r10
+	testq	$32,%r10
+	jnz	L$ChaCha20_8x
+	cmpq	$192,%rdx
+	ja	L$proceed4x
+
+	andq	$71303168,%r11
+	cmpq	$4194304,%r11
+	je	L$do_sse3_after_all
+
+L$proceed4x:
+	subq	$0x140+8,%rsp
+	movdqa	L$sigma(%rip),%xmm11
+	movdqu	(%rcx),%xmm15
+	movdqu	16(%rcx),%xmm7
+	movdqu	(%r8),%xmm3
+	leaq	256(%rsp),%rcx
+	leaq	L$rot16(%rip),%r10
+	leaq	L$rot24(%rip),%r11
+
+	pshufd	$0x00,%xmm11,%xmm8
+	pshufd	$0x55,%xmm11,%xmm9
+	movdqa	%xmm8,64(%rsp)
+	pshufd	$0xaa,%xmm11,%xmm10
+	movdqa	%xmm9,80(%rsp)
+	pshufd	$0xff,%xmm11,%xmm11
+	movdqa	%xmm10,96(%rsp)
+	movdqa	%xmm11,112(%rsp)
+
+	pshufd	$0x00,%xmm15,%xmm12
+	pshufd	$0x55,%xmm15,%xmm13
+	movdqa	%xmm12,128-256(%rcx)
+	pshufd	$0xaa,%xmm15,%xmm14
+	movdqa	%xmm13,144-256(%rcx)
+	pshufd	$0xff,%xmm15,%xmm15
+	movdqa	%xmm14,160-256(%rcx)
+	movdqa	%xmm15,176-256(%rcx)
+
+	pshufd	$0x00,%xmm7,%xmm4
+	pshufd	$0x55,%xmm7,%xmm5
+	movdqa	%xmm4,192-256(%rcx)
+	pshufd	$0xaa,%xmm7,%xmm6
+	movdqa	%xmm5,208-256(%rcx)
+	pshufd	$0xff,%xmm7,%xmm7
+	movdqa	%xmm6,224-256(%rcx)
+	movdqa	%xmm7,240-256(%rcx)
+
+	pshufd	$0x00,%xmm3,%xmm0
+	pshufd	$0x55,%xmm3,%xmm1
+	paddd	L$inc(%rip),%xmm0
+	pshufd	$0xaa,%xmm3,%xmm2
+	movdqa	%xmm1,272-256(%rcx)
+	pshufd	$0xff,%xmm3,%xmm3
+	movdqa	%xmm2,288-256(%rcx)
+	movdqa	%xmm3,304-256(%rcx)
+
+	jmp	L$oop_enter4x
+
+.p2align	5
+L$oop_outer4x:
+	movdqa	64(%rsp),%xmm8
+	movdqa	80(%rsp),%xmm9
+	movdqa	96(%rsp),%xmm10
+	movdqa	112(%rsp),%xmm11
+	movdqa	128-256(%rcx),%xmm12
+	movdqa	144-256(%rcx),%xmm13
+	movdqa	160-256(%rcx),%xmm14
+	movdqa	176-256(%rcx),%xmm15
+	movdqa	192-256(%rcx),%xmm4
+	movdqa	208-256(%rcx),%xmm5
+	movdqa	224-256(%rcx),%xmm6
+	movdqa	240-256(%rcx),%xmm7
+	movdqa	256-256(%rcx),%xmm0
+	movdqa	272-256(%rcx),%xmm1
+	movdqa	288-256(%rcx),%xmm2
+	movdqa	304-256(%rcx),%xmm3
+	paddd	L$four(%rip),%xmm0
+
+L$oop_enter4x:
+	movdqa	%xmm6,32(%rsp)
+	movdqa	%xmm7,48(%rsp)
+	movdqa	(%r10),%xmm7
+	movl	$10,%eax
+	movdqa	%xmm0,256-256(%rcx)
+	jmp	L$oop4x
+
+.p2align	5
+L$oop4x:
+	paddd	%xmm12,%xmm8
+	paddd	%xmm13,%xmm9
+	pxor	%xmm8,%xmm0
+	pxor	%xmm9,%xmm1
+.byte	102,15,56,0,199
+.byte	102,15,56,0,207
+	paddd	%xmm0,%xmm4
+	paddd	%xmm1,%xmm5
+	pxor	%xmm4,%xmm12
+	pxor	%xmm5,%xmm13
+	movdqa	%xmm12,%xmm6
+	pslld	$12,%xmm12
+	psrld	$20,%xmm6
+	movdqa	%xmm13,%xmm7
+	pslld	$12,%xmm13
+	por	%xmm6,%xmm12
+	psrld	$20,%xmm7
+	movdqa	(%r11),%xmm6
+	por	%xmm7,%xmm13
+	paddd	%xmm12,%xmm8
+	paddd	%xmm13,%xmm9
+	pxor	%xmm8,%xmm0
+	pxor	%xmm9,%xmm1
+.byte	102,15,56,0,198
+.byte	102,15,56,0,206
+	paddd	%xmm0,%xmm4
+	paddd	%xmm1,%xmm5
+	pxor	%xmm4,%xmm12
+	pxor	%xmm5,%xmm13
+	movdqa	%xmm12,%xmm7
+	pslld	$7,%xmm12
+	psrld	$25,%xmm7
+	movdqa	%xmm13,%xmm6
+	pslld	$7,%xmm13
+	por	%xmm7,%xmm12
+	psrld	$25,%xmm6
+	movdqa	(%r10),%xmm7
+	por	%xmm6,%xmm13
+	movdqa	%xmm4,0(%rsp)
+	movdqa	%xmm5,16(%rsp)
+	movdqa	32(%rsp),%xmm4
+	movdqa	48(%rsp),%xmm5
+	paddd	%xmm14,%xmm10
+	paddd	%xmm15,%xmm11
+	pxor	%xmm10,%xmm2
+	pxor	%xmm11,%xmm3
+.byte	102,15,56,0,215
+.byte	102,15,56,0,223
+	paddd	%xmm2,%xmm4
+	paddd	%xmm3,%xmm5
+	pxor	%xmm4,%xmm14
+	pxor	%xmm5,%xmm15
+	movdqa	%xmm14,%xmm6
+	pslld	$12,%xmm14
+	psrld	$20,%xmm6
+	movdqa	%xmm15,%xmm7
+	pslld	$12,%xmm15
+	por	%xmm6,%xmm14
+	psrld	$20,%xmm7
+	movdqa	(%r11),%xmm6
+	por	%xmm7,%xmm15
+	paddd	%xmm14,%xmm10
+	paddd	%xmm15,%xmm11
+	pxor	%xmm10,%xmm2
+	pxor	%xmm11,%xmm3
+.byte	102,15,56,0,214
+.byte	102,15,56,0,222
+	paddd	%xmm2,%xmm4
+	paddd	%xmm3,%xmm5
+	pxor	%xmm4,%xmm14
+	pxor	%xmm5,%xmm15
+	movdqa	%xmm14,%xmm7
+	pslld	$7,%xmm14
+	psrld	$25,%xmm7
+	movdqa	%xmm15,%xmm6
+	pslld	$7,%xmm15
+	por	%xmm7,%xmm14
+	psrld	$25,%xmm6
+	movdqa	(%r10),%xmm7
+	por	%xmm6,%xmm15
+	paddd	%xmm13,%xmm8
+	paddd	%xmm14,%xmm9
+	pxor	%xmm8,%xmm3
+	pxor	%xmm9,%xmm0
+.byte	102,15,56,0,223
+.byte	102,15,56,0,199
+	paddd	%xmm3,%xmm4
+	paddd	%xmm0,%xmm5
+	pxor	%xmm4,%xmm13
+	pxor	%xmm5,%xmm14
+	movdqa	%xmm13,%xmm6
+	pslld	$12,%xmm13
+	psrld	$20,%xmm6
+	movdqa	%xmm14,%xmm7
+	pslld	$12,%xmm14
+	por	%xmm6,%xmm13
+	psrld	$20,%xmm7
+	movdqa	(%r11),%xmm6
+	por	%xmm7,%xmm14
+	paddd	%xmm13,%xmm8
+	paddd	%xmm14,%xmm9
+	pxor	%xmm8,%xmm3
+	pxor	%xmm9,%xmm0
+.byte	102,15,56,0,222
+.byte	102,15,56,0,198
+	paddd	%xmm3,%xmm4
+	paddd	%xmm0,%xmm5
+	pxor	%xmm4,%xmm13
+	pxor	%xmm5,%xmm14
+	movdqa	%xmm13,%xmm7
+	pslld	$7,%xmm13
+	psrld	$25,%xmm7
+	movdqa	%xmm14,%xmm6
+	pslld	$7,%xmm14
+	por	%xmm7,%xmm13
+	psrld	$25,%xmm6
+	movdqa	(%r10),%xmm7
+	por	%xmm6,%xmm14
+	movdqa	%xmm4,32(%rsp)
+	movdqa	%xmm5,48(%rsp)
+	movdqa	0(%rsp),%xmm4
+	movdqa	16(%rsp),%xmm5
+	paddd	%xmm15,%xmm10
+	paddd	%xmm12,%xmm11
+	pxor	%xmm10,%xmm1
+	pxor	%xmm11,%xmm2
+.byte	102,15,56,0,207
+.byte	102,15,56,0,215
+	paddd	%xmm1,%xmm4
+	paddd	%xmm2,%xmm5
+	pxor	%xmm4,%xmm15
+	pxor	%xmm5,%xmm12
+	movdqa	%xmm15,%xmm6
+	pslld	$12,%xmm15
+	psrld	$20,%xmm6
+	movdqa	%xmm12,%xmm7
+	pslld	$12,%xmm12
+	por	%xmm6,%xmm15
+	psrld	$20,%xmm7
+	movdqa	(%r11),%xmm6
+	por	%xmm7,%xmm12
+	paddd	%xmm15,%xmm10
+	paddd	%xmm12,%xmm11
+	pxor	%xmm10,%xmm1
+	pxor	%xmm11,%xmm2
+.byte	102,15,56,0,206
+.byte	102,15,56,0,214
+	paddd	%xmm1,%xmm4
+	paddd	%xmm2,%xmm5
+	pxor	%xmm4,%xmm15
+	pxor	%xmm5,%xmm12
+	movdqa	%xmm15,%xmm7
+	pslld	$7,%xmm15
+	psrld	$25,%xmm7
+	movdqa	%xmm12,%xmm6
+	pslld	$7,%xmm12
+	por	%xmm7,%xmm15
+	psrld	$25,%xmm6
+	movdqa	(%r10),%xmm7
+	por	%xmm6,%xmm12
+	decl	%eax
+	jnz	L$oop4x
+
+	paddd	64(%rsp),%xmm8
+	paddd	80(%rsp),%xmm9
+	paddd	96(%rsp),%xmm10
+	paddd	112(%rsp),%xmm11
+
+	movdqa	%xmm8,%xmm6
+	punpckldq	%xmm9,%xmm8
+	movdqa	%xmm10,%xmm7
+	punpckldq	%xmm11,%xmm10
+	punpckhdq	%xmm9,%xmm6
+	punpckhdq	%xmm11,%xmm7
+	movdqa	%xmm8,%xmm9
+	punpcklqdq	%xmm10,%xmm8
+	movdqa	%xmm6,%xmm11
+	punpcklqdq	%xmm7,%xmm6
+	punpckhqdq	%xmm10,%xmm9
+	punpckhqdq	%xmm7,%xmm11
+	paddd	128-256(%rcx),%xmm12
+	paddd	144-256(%rcx),%xmm13
+	paddd	160-256(%rcx),%xmm14
+	paddd	176-256(%rcx),%xmm15
+
+	movdqa	%xmm8,0(%rsp)
+	movdqa	%xmm9,16(%rsp)
+	movdqa	32(%rsp),%xmm8
+	movdqa	48(%rsp),%xmm9
+
+	movdqa	%xmm12,%xmm10
+	punpckldq	%xmm13,%xmm12
+	movdqa	%xmm14,%xmm7
+	punpckldq	%xmm15,%xmm14
+	punpckhdq	%xmm13,%xmm10
+	punpckhdq	%xmm15,%xmm7
+	movdqa	%xmm12,%xmm13
+	punpcklqdq	%xmm14,%xmm12
+	movdqa	%xmm10,%xmm15
+	punpcklqdq	%xmm7,%xmm10
+	punpckhqdq	%xmm14,%xmm13
+	punpckhqdq	%xmm7,%xmm15
+	paddd	192-256(%rcx),%xmm4
+	paddd	208-256(%rcx),%xmm5
+	paddd	224-256(%rcx),%xmm8
+	paddd	240-256(%rcx),%xmm9
+
+	movdqa	%xmm6,32(%rsp)
+	movdqa	%xmm11,48(%rsp)
+
+	movdqa	%xmm4,%xmm14
+	punpckldq	%xmm5,%xmm4
+	movdqa	%xmm8,%xmm7
+	punpckldq	%xmm9,%xmm8
+	punpckhdq	%xmm5,%xmm14
+	punpckhdq	%xmm9,%xmm7
+	movdqa	%xmm4,%xmm5
+	punpcklqdq	%xmm8,%xmm4
+	movdqa	%xmm14,%xmm9
+	punpcklqdq	%xmm7,%xmm14
+	punpckhqdq	%xmm8,%xmm5
+	punpckhqdq	%xmm7,%xmm9
+	paddd	256-256(%rcx),%xmm0
+	paddd	272-256(%rcx),%xmm1
+	paddd	288-256(%rcx),%xmm2
+	paddd	304-256(%rcx),%xmm3
+
+	movdqa	%xmm0,%xmm8
+	punpckldq	%xmm1,%xmm0
+	movdqa	%xmm2,%xmm7
+	punpckldq	%xmm3,%xmm2
+	punpckhdq	%xmm1,%xmm8
+	punpckhdq	%xmm3,%xmm7
+	movdqa	%xmm0,%xmm1
+	punpcklqdq	%xmm2,%xmm0
+	movdqa	%xmm8,%xmm3
+	punpcklqdq	%xmm7,%xmm8
+	punpckhqdq	%xmm2,%xmm1
+	punpckhqdq	%xmm7,%xmm3
+	cmpq	$256,%rdx
+	jb	L$tail4x
+
+	movdqu	0(%rsi),%xmm6
+	movdqu	16(%rsi),%xmm11
+	movdqu	32(%rsi),%xmm2
+	movdqu	48(%rsi),%xmm7
+	pxor	0(%rsp),%xmm6
+	pxor	%xmm12,%xmm11
+	pxor	%xmm4,%xmm2
+	pxor	%xmm0,%xmm7
+
+	movdqu	%xmm6,0(%rdi)
+	movdqu	64(%rsi),%xmm6
+	movdqu	%xmm11,16(%rdi)
+	movdqu	80(%rsi),%xmm11
+	movdqu	%xmm2,32(%rdi)
+	movdqu	96(%rsi),%xmm2
+	movdqu	%xmm7,48(%rdi)
+	movdqu	112(%rsi),%xmm7
+	leaq	128(%rsi),%rsi
+	pxor	16(%rsp),%xmm6
+	pxor	%xmm13,%xmm11
+	pxor	%xmm5,%xmm2
+	pxor	%xmm1,%xmm7
+
+	movdqu	%xmm6,64(%rdi)
+	movdqu	0(%rsi),%xmm6
+	movdqu	%xmm11,80(%rdi)
+	movdqu	16(%rsi),%xmm11
+	movdqu	%xmm2,96(%rdi)
+	movdqu	32(%rsi),%xmm2
+	movdqu	%xmm7,112(%rdi)
+	leaq	128(%rdi),%rdi
+	movdqu	48(%rsi),%xmm7
+	pxor	32(%rsp),%xmm6
+	pxor	%xmm10,%xmm11
+	pxor	%xmm14,%xmm2
+	pxor	%xmm8,%xmm7
+
+	movdqu	%xmm6,0(%rdi)
+	movdqu	64(%rsi),%xmm6
+	movdqu	%xmm11,16(%rdi)
+	movdqu	80(%rsi),%xmm11
+	movdqu	%xmm2,32(%rdi)
+	movdqu	96(%rsi),%xmm2
+	movdqu	%xmm7,48(%rdi)
+	movdqu	112(%rsi),%xmm7
+	leaq	128(%rsi),%rsi
+	pxor	48(%rsp),%xmm6
+	pxor	%xmm15,%xmm11
+	pxor	%xmm9,%xmm2
+	pxor	%xmm3,%xmm7
+	movdqu	%xmm6,64(%rdi)
+	movdqu	%xmm11,80(%rdi)
+	movdqu	%xmm2,96(%rdi)
+	movdqu	%xmm7,112(%rdi)
+	leaq	128(%rdi),%rdi
+
+	subq	$256,%rdx
+	jnz	L$oop_outer4x
+
+	jmp	L$done4x
+
+L$tail4x:
+	cmpq	$192,%rdx
+	jae	L$192_or_more4x
+	cmpq	$128,%rdx
+	jae	L$128_or_more4x
+	cmpq	$64,%rdx
+	jae	L$64_or_more4x
+
+
+	xorq	%r10,%r10
+
+	movdqa	%xmm12,16(%rsp)
+	movdqa	%xmm4,32(%rsp)
+	movdqa	%xmm0,48(%rsp)
+	jmp	L$oop_tail4x
+
+.p2align	5
+L$64_or_more4x:
+	movdqu	0(%rsi),%xmm6
+	movdqu	16(%rsi),%xmm11
+	movdqu	32(%rsi),%xmm2
+	movdqu	48(%rsi),%xmm7
+	pxor	0(%rsp),%xmm6
+	pxor	%xmm12,%xmm11
+	pxor	%xmm4,%xmm2
+	pxor	%xmm0,%xmm7
+	movdqu	%xmm6,0(%rdi)
+	movdqu	%xmm11,16(%rdi)
+	movdqu	%xmm2,32(%rdi)
+	movdqu	%xmm7,48(%rdi)
+	je	L$done4x
+
+	movdqa	16(%rsp),%xmm6
+	leaq	64(%rsi),%rsi
+	xorq	%r10,%r10
+	movdqa	%xmm6,0(%rsp)
+	movdqa	%xmm13,16(%rsp)
+	leaq	64(%rdi),%rdi
+	movdqa	%xmm5,32(%rsp)
+	subq	$64,%rdx
+	movdqa	%xmm1,48(%rsp)
+	jmp	L$oop_tail4x
+
+.p2align	5
+L$128_or_more4x:
+	movdqu	0(%rsi),%xmm6
+	movdqu	16(%rsi),%xmm11
+	movdqu	32(%rsi),%xmm2
+	movdqu	48(%rsi),%xmm7
+	pxor	0(%rsp),%xmm6
+	pxor	%xmm12,%xmm11
+	pxor	%xmm4,%xmm2
+	pxor	%xmm0,%xmm7
+
+	movdqu	%xmm6,0(%rdi)
+	movdqu	64(%rsi),%xmm6
+	movdqu	%xmm11,16(%rdi)
+	movdqu	80(%rsi),%xmm11
+	movdqu	%xmm2,32(%rdi)
+	movdqu	96(%rsi),%xmm2
+	movdqu	%xmm7,48(%rdi)
+	movdqu	112(%rsi),%xmm7
+	pxor	16(%rsp),%xmm6
+	pxor	%xmm13,%xmm11
+	pxor	%xmm5,%xmm2
+	pxor	%xmm1,%xmm7
+	movdqu	%xmm6,64(%rdi)
+	movdqu	%xmm11,80(%rdi)
+	movdqu	%xmm2,96(%rdi)
+	movdqu	%xmm7,112(%rdi)
+	je	L$done4x
+
+	movdqa	32(%rsp),%xmm6
+	leaq	128(%rsi),%rsi
+	xorq	%r10,%r10
+	movdqa	%xmm6,0(%rsp)
+	movdqa	%xmm10,16(%rsp)
+	leaq	128(%rdi),%rdi
+	movdqa	%xmm14,32(%rsp)
+	subq	$128,%rdx
+	movdqa	%xmm8,48(%rsp)
+	jmp	L$oop_tail4x
+
+.p2align	5
+L$192_or_more4x:
+	movdqu	0(%rsi),%xmm6
+	movdqu	16(%rsi),%xmm11
+	movdqu	32(%rsi),%xmm2
+	movdqu	48(%rsi),%xmm7
+	pxor	0(%rsp),%xmm6
+	pxor	%xmm12,%xmm11
+	pxor	%xmm4,%xmm2
+	pxor	%xmm0,%xmm7
+
+	movdqu	%xmm6,0(%rdi)
+	movdqu	64(%rsi),%xmm6
+	movdqu	%xmm11,16(%rdi)
+	movdqu	80(%rsi),%xmm11
+	movdqu	%xmm2,32(%rdi)
+	movdqu	96(%rsi),%xmm2
+	movdqu	%xmm7,48(%rdi)
+	movdqu	112(%rsi),%xmm7
+	leaq	128(%rsi),%rsi
+	pxor	16(%rsp),%xmm6
+	pxor	%xmm13,%xmm11
+	pxor	%xmm5,%xmm2
+	pxor	%xmm1,%xmm7
+
+	movdqu	%xmm6,64(%rdi)
+	movdqu	0(%rsi),%xmm6
+	movdqu	%xmm11,80(%rdi)
+	movdqu	16(%rsi),%xmm11
+	movdqu	%xmm2,96(%rdi)
+	movdqu	32(%rsi),%xmm2
+	movdqu	%xmm7,112(%rdi)
+	leaq	128(%rdi),%rdi
+	movdqu	48(%rsi),%xmm7
+	pxor	32(%rsp),%xmm6
+	pxor	%xmm10,%xmm11
+	pxor	%xmm14,%xmm2
+	pxor	%xmm8,%xmm7
+	movdqu	%xmm6,0(%rdi)
+	movdqu	%xmm11,16(%rdi)
+	movdqu	%xmm2,32(%rdi)
+	movdqu	%xmm7,48(%rdi)
+	je	L$done4x
+
+	movdqa	48(%rsp),%xmm6
+	leaq	64(%rsi),%rsi
+	xorq	%r10,%r10
+	movdqa	%xmm6,0(%rsp)
+	movdqa	%xmm15,16(%rsp)
+	leaq	64(%rdi),%rdi
+	movdqa	%xmm9,32(%rsp)
+	subq	$192,%rdx
+	movdqa	%xmm3,48(%rsp)
+
+L$oop_tail4x:
+	movzbl	(%rsi,%r10,1),%eax
+	movzbl	(%rsp,%r10,1),%ecx
+	leaq	1(%r10),%r10
+	xorl	%ecx,%eax
+	movb	%al,-1(%rdi,%r10,1)
+	decq	%rdx
+	jnz	L$oop_tail4x
+
+L$done4x:
+	leaq	(%r9),%rsp
+L$4x_epilogue:
+	.byte	0xf3,0xc3
+
+
+.p2align	5
+ChaCha20_8x:
+L$ChaCha20_8x:
+	movq	%rsp,%r9
+	subq	$0x280+8,%rsp
+	andq	$-32,%rsp
+	vzeroupper
+
+
+
+
+
+
+
+
+
+
+	vbroadcasti128	L$sigma(%rip),%ymm11
+	vbroadcasti128	(%rcx),%ymm3
+	vbroadcasti128	16(%rcx),%ymm15
+	vbroadcasti128	(%r8),%ymm7
+	leaq	256(%rsp),%rcx
+	leaq	512(%rsp),%rax
+	leaq	L$rot16(%rip),%r10
+	leaq	L$rot24(%rip),%r11
+
+	vpshufd	$0x00,%ymm11,%ymm8
+	vpshufd	$0x55,%ymm11,%ymm9
+	vmovdqa	%ymm8,128-256(%rcx)
+	vpshufd	$0xaa,%ymm11,%ymm10
+	vmovdqa	%ymm9,160-256(%rcx)
+	vpshufd	$0xff,%ymm11,%ymm11
+	vmovdqa	%ymm10,192-256(%rcx)
+	vmovdqa	%ymm11,224-256(%rcx)
+
+	vpshufd	$0x00,%ymm3,%ymm0
+	vpshufd	$0x55,%ymm3,%ymm1
+	vmovdqa	%ymm0,256-256(%rcx)
+	vpshufd	$0xaa,%ymm3,%ymm2
+	vmovdqa	%ymm1,288-256(%rcx)
+	vpshufd	$0xff,%ymm3,%ymm3
+	vmovdqa	%ymm2,320-256(%rcx)
+	vmovdqa	%ymm3,352-256(%rcx)
+
+	vpshufd	$0x00,%ymm15,%ymm12
+	vpshufd	$0x55,%ymm15,%ymm13
+	vmovdqa	%ymm12,384-512(%rax)
+	vpshufd	$0xaa,%ymm15,%ymm14
+	vmovdqa	%ymm13,416-512(%rax)
+	vpshufd	$0xff,%ymm15,%ymm15
+	vmovdqa	%ymm14,448-512(%rax)
+	vmovdqa	%ymm15,480-512(%rax)
+
+	vpshufd	$0x00,%ymm7,%ymm4
+	vpshufd	$0x55,%ymm7,%ymm5
+	vpaddd	L$incy(%rip),%ymm4,%ymm4
+	vpshufd	$0xaa,%ymm7,%ymm6
+	vmovdqa	%ymm5,544-512(%rax)
+	vpshufd	$0xff,%ymm7,%ymm7
+	vmovdqa	%ymm6,576-512(%rax)
+	vmovdqa	%ymm7,608-512(%rax)
+
+	jmp	L$oop_enter8x
+
+.p2align	5
+L$oop_outer8x:
+	vmovdqa	128-256(%rcx),%ymm8
+	vmovdqa	160-256(%rcx),%ymm9
+	vmovdqa	192-256(%rcx),%ymm10
+	vmovdqa	224-256(%rcx),%ymm11
+	vmovdqa	256-256(%rcx),%ymm0
+	vmovdqa	288-256(%rcx),%ymm1
+	vmovdqa	320-256(%rcx),%ymm2
+	vmovdqa	352-256(%rcx),%ymm3
+	vmovdqa	384-512(%rax),%ymm12
+	vmovdqa	416-512(%rax),%ymm13
+	vmovdqa	448-512(%rax),%ymm14
+	vmovdqa	480-512(%rax),%ymm15
+	vmovdqa	512-512(%rax),%ymm4
+	vmovdqa	544-512(%rax),%ymm5
+	vmovdqa	576-512(%rax),%ymm6
+	vmovdqa	608-512(%rax),%ymm7
+	vpaddd	L$eight(%rip),%ymm4,%ymm4
+
+L$oop_enter8x:
+	vmovdqa	%ymm14,64(%rsp)
+	vmovdqa	%ymm15,96(%rsp)
+	vbroadcasti128	(%r10),%ymm15
+	vmovdqa	%ymm4,512-512(%rax)
+	movl	$10,%eax
+	jmp	L$oop8x
+
+.p2align	5
+L$oop8x:
+	vpaddd	%ymm0,%ymm8,%ymm8
+	vpxor	%ymm4,%ymm8,%ymm4
+	vpshufb	%ymm15,%ymm4,%ymm4
+	vpaddd	%ymm1,%ymm9,%ymm9
+	vpxor	%ymm5,%ymm9,%ymm5
+	vpshufb	%ymm15,%ymm5,%ymm5
+	vpaddd	%ymm4,%ymm12,%ymm12
+	vpxor	%ymm0,%ymm12,%ymm0
+	vpslld	$12,%ymm0,%ymm14
+	vpsrld	$20,%ymm0,%ymm0
+	vpor	%ymm0,%ymm14,%ymm0
+	vbroadcasti128	(%r11),%ymm14
+	vpaddd	%ymm5,%ymm13,%ymm13
+	vpxor	%ymm1,%ymm13,%ymm1
+	vpslld	$12,%ymm1,%ymm15
+	vpsrld	$20,%ymm1,%ymm1
+	vpor	%ymm1,%ymm15,%ymm1
+	vpaddd	%ymm0,%ymm8,%ymm8
+	vpxor	%ymm4,%ymm8,%ymm4
+	vpshufb	%ymm14,%ymm4,%ymm4
+	vpaddd	%ymm1,%ymm9,%ymm9
+	vpxor	%ymm5,%ymm9,%ymm5
+	vpshufb	%ymm14,%ymm5,%ymm5
+	vpaddd	%ymm4,%ymm12,%ymm12
+	vpxor	%ymm0,%ymm12,%ymm0
+	vpslld	$7,%ymm0,%ymm15
+	vpsrld	$25,%ymm0,%ymm0
+	vpor	%ymm0,%ymm15,%ymm0
+	vbroadcasti128	(%r10),%ymm15
+	vpaddd	%ymm5,%ymm13,%ymm13
+	vpxor	%ymm1,%ymm13,%ymm1
+	vpslld	$7,%ymm1,%ymm14
+	vpsrld	$25,%ymm1,%ymm1
+	vpor	%ymm1,%ymm14,%ymm1
+	vmovdqa	%ymm12,0(%rsp)
+	vmovdqa	%ymm13,32(%rsp)
+	vmovdqa	64(%rsp),%ymm12
+	vmovdqa	96(%rsp),%ymm13
+	vpaddd	%ymm2,%ymm10,%ymm10
+	vpxor	%ymm6,%ymm10,%ymm6
+	vpshufb	%ymm15,%ymm6,%ymm6
+	vpaddd	%ymm3,%ymm11,%ymm11
+	vpxor	%ymm7,%ymm11,%ymm7
+	vpshufb	%ymm15,%ymm7,%ymm7
+	vpaddd	%ymm6,%ymm12,%ymm12
+	vpxor	%ymm2,%ymm12,%ymm2
+	vpslld	$12,%ymm2,%ymm14
+	vpsrld	$20,%ymm2,%ymm2
+	vpor	%ymm2,%ymm14,%ymm2
+	vbroadcasti128	(%r11),%ymm14
+	vpaddd	%ymm7,%ymm13,%ymm13
+	vpxor	%ymm3,%ymm13,%ymm3
+	vpslld	$12,%ymm3,%ymm15
+	vpsrld	$20,%ymm3,%ymm3
+	vpor	%ymm3,%ymm15,%ymm3
+	vpaddd	%ymm2,%ymm10,%ymm10
+	vpxor	%ymm6,%ymm10,%ymm6
+	vpshufb	%ymm14,%ymm6,%ymm6
+	vpaddd	%ymm3,%ymm11,%ymm11
+	vpxor	%ymm7,%ymm11,%ymm7
+	vpshufb	%ymm14,%ymm7,%ymm7
+	vpaddd	%ymm6,%ymm12,%ymm12
+	vpxor	%ymm2,%ymm12,%ymm2
+	vpslld	$7,%ymm2,%ymm15
+	vpsrld	$25,%ymm2,%ymm2
+	vpor	%ymm2,%ymm15,%ymm2
+	vbroadcasti128	(%r10),%ymm15
+	vpaddd	%ymm7,%ymm13,%ymm13
+	vpxor	%ymm3,%ymm13,%ymm3
+	vpslld	$7,%ymm3,%ymm14
+	vpsrld	$25,%ymm3,%ymm3
+	vpor	%ymm3,%ymm14,%ymm3
+	vpaddd	%ymm1,%ymm8,%ymm8
+	vpxor	%ymm7,%ymm8,%ymm7
+	vpshufb	%ymm15,%ymm7,%ymm7
+	vpaddd	%ymm2,%ymm9,%ymm9
+	vpxor	%ymm4,%ymm9,%ymm4
+	vpshufb	%ymm15,%ymm4,%ymm4
+	vpaddd	%ymm7,%ymm12,%ymm12
+	vpxor	%ymm1,%ymm12,%ymm1
+	vpslld	$12,%ymm1,%ymm14
+	vpsrld	$20,%ymm1,%ymm1
+	vpor	%ymm1,%ymm14,%ymm1
+	vbroadcasti128	(%r11),%ymm14
+	vpaddd	%ymm4,%ymm13,%ymm13
+	vpxor	%ymm2,%ymm13,%ymm2
+	vpslld	$12,%ymm2,%ymm15
+	vpsrld	$20,%ymm2,%ymm2
+	vpor	%ymm2,%ymm15,%ymm2
+	vpaddd	%ymm1,%ymm8,%ymm8
+	vpxor	%ymm7,%ymm8,%ymm7
+	vpshufb	%ymm14,%ymm7,%ymm7
+	vpaddd	%ymm2,%ymm9,%ymm9
+	vpxor	%ymm4,%ymm9,%ymm4
+	vpshufb	%ymm14,%ymm4,%ymm4
+	vpaddd	%ymm7,%ymm12,%ymm12
+	vpxor	%ymm1,%ymm12,%ymm1
+	vpslld	$7,%ymm1,%ymm15
+	vpsrld	$25,%ymm1,%ymm1
+	vpor	%ymm1,%ymm15,%ymm1
+	vbroadcasti128	(%r10),%ymm15
+	vpaddd	%ymm4,%ymm13,%ymm13
+	vpxor	%ymm2,%ymm13,%ymm2
+	vpslld	$7,%ymm2,%ymm14
+	vpsrld	$25,%ymm2,%ymm2
+	vpor	%ymm2,%ymm14,%ymm2
+	vmovdqa	%ymm12,64(%rsp)
+	vmovdqa	%ymm13,96(%rsp)
+	vmovdqa	0(%rsp),%ymm12
+	vmovdqa	32(%rsp),%ymm13
+	vpaddd	%ymm3,%ymm10,%ymm10
+	vpxor	%ymm5,%ymm10,%ymm5
+	vpshufb	%ymm15,%ymm5,%ymm5
+	vpaddd	%ymm0,%ymm11,%ymm11
+	vpxor	%ymm6,%ymm11,%ymm6
+	vpshufb	%ymm15,%ymm6,%ymm6
+	vpaddd	%ymm5,%ymm12,%ymm12
+	vpxor	%ymm3,%ymm12,%ymm3
+	vpslld	$12,%ymm3,%ymm14
+	vpsrld	$20,%ymm3,%ymm3
+	vpor	%ymm3,%ymm14,%ymm3
+	vbroadcasti128	(%r11),%ymm14
+	vpaddd	%ymm6,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm13,%ymm0
+	vpslld	$12,%ymm0,%ymm15
+	vpsrld	$20,%ymm0,%ymm0
+	vpor	%ymm0,%ymm15,%ymm0
+	vpaddd	%ymm3,%ymm10,%ymm10
+	vpxor	%ymm5,%ymm10,%ymm5
+	vpshufb	%ymm14,%ymm5,%ymm5
+	vpaddd	%ymm0,%ymm11,%ymm11
+	vpxor	%ymm6,%ymm11,%ymm6
+	vpshufb	%ymm14,%ymm6,%ymm6
+	vpaddd	%ymm5,%ymm12,%ymm12
+	vpxor	%ymm3,%ymm12,%ymm3
+	vpslld	$7,%ymm3,%ymm15
+	vpsrld	$25,%ymm3,%ymm3
+	vpor	%ymm3,%ymm15,%ymm3
+	vbroadcasti128	(%r10),%ymm15
+	vpaddd	%ymm6,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm13,%ymm0
+	vpslld	$7,%ymm0,%ymm14
+	vpsrld	$25,%ymm0,%ymm0
+	vpor	%ymm0,%ymm14,%ymm0
+	decl	%eax
+	jnz	L$oop8x
+
+	leaq	512(%rsp),%rax
+	vpaddd	128-256(%rcx),%ymm8,%ymm8
+	vpaddd	160-256(%rcx),%ymm9,%ymm9
+	vpaddd	192-256(%rcx),%ymm10,%ymm10
+	vpaddd	224-256(%rcx),%ymm11,%ymm11
+
+	vpunpckldq	%ymm9,%ymm8,%ymm14
+	vpunpckldq	%ymm11,%ymm10,%ymm15
+	vpunpckhdq	%ymm9,%ymm8,%ymm8
+	vpunpckhdq	%ymm11,%ymm10,%ymm10
+	vpunpcklqdq	%ymm15,%ymm14,%ymm9
+	vpunpckhqdq	%ymm15,%ymm14,%ymm14
+	vpunpcklqdq	%ymm10,%ymm8,%ymm11
+	vpunpckhqdq	%ymm10,%ymm8,%ymm8
+	vpaddd	256-256(%rcx),%ymm0,%ymm0
+	vpaddd	288-256(%rcx),%ymm1,%ymm1
+	vpaddd	320-256(%rcx),%ymm2,%ymm2
+	vpaddd	352-256(%rcx),%ymm3,%ymm3
+
+	vpunpckldq	%ymm1,%ymm0,%ymm10
+	vpunpckldq	%ymm3,%ymm2,%ymm15
+	vpunpckhdq	%ymm1,%ymm0,%ymm0
+	vpunpckhdq	%ymm3,%ymm2,%ymm2
+	vpunpcklqdq	%ymm15,%ymm10,%ymm1
+	vpunpckhqdq	%ymm15,%ymm10,%ymm10
+	vpunpcklqdq	%ymm2,%ymm0,%ymm3
+	vpunpckhqdq	%ymm2,%ymm0,%ymm0
+	vperm2i128	$0x20,%ymm1,%ymm9,%ymm15
+	vperm2i128	$0x31,%ymm1,%ymm9,%ymm1
+	vperm2i128	$0x20,%ymm10,%ymm14,%ymm9
+	vperm2i128	$0x31,%ymm10,%ymm14,%ymm10
+	vperm2i128	$0x20,%ymm3,%ymm11,%ymm14
+	vperm2i128	$0x31,%ymm3,%ymm11,%ymm3
+	vperm2i128	$0x20,%ymm0,%ymm8,%ymm11
+	vperm2i128	$0x31,%ymm0,%ymm8,%ymm0
+	vmovdqa	%ymm15,0(%rsp)
+	vmovdqa	%ymm9,32(%rsp)
+	vmovdqa	64(%rsp),%ymm15
+	vmovdqa	96(%rsp),%ymm9
+
+	vpaddd	384-512(%rax),%ymm12,%ymm12
+	vpaddd	416-512(%rax),%ymm13,%ymm13
+	vpaddd	448-512(%rax),%ymm15,%ymm15
+	vpaddd	480-512(%rax),%ymm9,%ymm9
+
+	vpunpckldq	%ymm13,%ymm12,%ymm2
+	vpunpckldq	%ymm9,%ymm15,%ymm8
+	vpunpckhdq	%ymm13,%ymm12,%ymm12
+	vpunpckhdq	%ymm9,%ymm15,%ymm15
+	vpunpcklqdq	%ymm8,%ymm2,%ymm13
+	vpunpckhqdq	%ymm8,%ymm2,%ymm2
+	vpunpcklqdq	%ymm15,%ymm12,%ymm9
+	vpunpckhqdq	%ymm15,%ymm12,%ymm12
+	vpaddd	512-512(%rax),%ymm4,%ymm4
+	vpaddd	544-512(%rax),%ymm5,%ymm5
+	vpaddd	576-512(%rax),%ymm6,%ymm6
+	vpaddd	608-512(%rax),%ymm7,%ymm7
+
+	vpunpckldq	%ymm5,%ymm4,%ymm15
+	vpunpckldq	%ymm7,%ymm6,%ymm8
+	vpunpckhdq	%ymm5,%ymm4,%ymm4
+	vpunpckhdq	%ymm7,%ymm6,%ymm6
+	vpunpcklqdq	%ymm8,%ymm15,%ymm5
+	vpunpckhqdq	%ymm8,%ymm15,%ymm15
+	vpunpcklqdq	%ymm6,%ymm4,%ymm7
+	vpunpckhqdq	%ymm6,%ymm4,%ymm4
+	vperm2i128	$0x20,%ymm5,%ymm13,%ymm8
+	vperm2i128	$0x31,%ymm5,%ymm13,%ymm5
+	vperm2i128	$0x20,%ymm15,%ymm2,%ymm13
+	vperm2i128	$0x31,%ymm15,%ymm2,%ymm15
+	vperm2i128	$0x20,%ymm7,%ymm9,%ymm2
+	vperm2i128	$0x31,%ymm7,%ymm9,%ymm7
+	vperm2i128	$0x20,%ymm4,%ymm12,%ymm9
+	vperm2i128	$0x31,%ymm4,%ymm12,%ymm4
+	vmovdqa	0(%rsp),%ymm6
+	vmovdqa	32(%rsp),%ymm12
+
+	cmpq	$512,%rdx
+	jb	L$tail8x
+
+	vpxor	0(%rsi),%ymm6,%ymm6
+	vpxor	32(%rsi),%ymm8,%ymm8
+	vpxor	64(%rsi),%ymm1,%ymm1
+	vpxor	96(%rsi),%ymm5,%ymm5
+	leaq	128(%rsi),%rsi
+	vmovdqu	%ymm6,0(%rdi)
+	vmovdqu	%ymm8,32(%rdi)
+	vmovdqu	%ymm1,64(%rdi)
+	vmovdqu	%ymm5,96(%rdi)
+	leaq	128(%rdi),%rdi
+
+	vpxor	0(%rsi),%ymm12,%ymm12
+	vpxor	32(%rsi),%ymm13,%ymm13
+	vpxor	64(%rsi),%ymm10,%ymm10
+	vpxor	96(%rsi),%ymm15,%ymm15
+	leaq	128(%rsi),%rsi
+	vmovdqu	%ymm12,0(%rdi)
+	vmovdqu	%ymm13,32(%rdi)
+	vmovdqu	%ymm10,64(%rdi)
+	vmovdqu	%ymm15,96(%rdi)
+	leaq	128(%rdi),%rdi
+
+	vpxor	0(%rsi),%ymm14,%ymm14
+	vpxor	32(%rsi),%ymm2,%ymm2
+	vpxor	64(%rsi),%ymm3,%ymm3
+	vpxor	96(%rsi),%ymm7,%ymm7
+	leaq	128(%rsi),%rsi
+	vmovdqu	%ymm14,0(%rdi)
+	vmovdqu	%ymm2,32(%rdi)
+	vmovdqu	%ymm3,64(%rdi)
+	vmovdqu	%ymm7,96(%rdi)
+	leaq	128(%rdi),%rdi
+
+	vpxor	0(%rsi),%ymm11,%ymm11
+	vpxor	32(%rsi),%ymm9,%ymm9
+	vpxor	64(%rsi),%ymm0,%ymm0
+	vpxor	96(%rsi),%ymm4,%ymm4
+	leaq	128(%rsi),%rsi
+	vmovdqu	%ymm11,0(%rdi)
+	vmovdqu	%ymm9,32(%rdi)
+	vmovdqu	%ymm0,64(%rdi)
+	vmovdqu	%ymm4,96(%rdi)
+	leaq	128(%rdi),%rdi
+
+	subq	$512,%rdx
+	jnz	L$oop_outer8x
+
+	jmp	L$done8x
+
+L$tail8x:
+	cmpq	$448,%rdx
+	jae	L$448_or_more8x
+	cmpq	$384,%rdx
+	jae	L$384_or_more8x
+	cmpq	$320,%rdx
+	jae	L$320_or_more8x
+	cmpq	$256,%rdx
+	jae	L$256_or_more8x
+	cmpq	$192,%rdx
+	jae	L$192_or_more8x
+	cmpq	$128,%rdx
+	jae	L$128_or_more8x
+	cmpq	$64,%rdx
+	jae	L$64_or_more8x
+
+	xorq	%r10,%r10
+	vmovdqa	%ymm6,0(%rsp)
+	vmovdqa	%ymm8,32(%rsp)
+	jmp	L$oop_tail8x
+
+.p2align	5
+L$64_or_more8x:
+	vpxor	0(%rsi),%ymm6,%ymm6
+	vpxor	32(%rsi),%ymm8,%ymm8
+	vmovdqu	%ymm6,0(%rdi)
+	vmovdqu	%ymm8,32(%rdi)
+	je	L$done8x
+
+	leaq	64(%rsi),%rsi
+	xorq	%r10,%r10
+	vmovdqa	%ymm1,0(%rsp)
+	leaq	64(%rdi),%rdi
+	subq	$64,%rdx
+	vmovdqa	%ymm5,32(%rsp)
+	jmp	L$oop_tail8x
+
+.p2align	5
+L$128_or_more8x:
+	vpxor	0(%rsi),%ymm6,%ymm6
+	vpxor	32(%rsi),%ymm8,%ymm8
+	vpxor	64(%rsi),%ymm1,%ymm1
+	vpxor	96(%rsi),%ymm5,%ymm5
+	vmovdqu	%ymm6,0(%rdi)
+	vmovdqu	%ymm8,32(%rdi)
+	vmovdqu	%ymm1,64(%rdi)
+	vmovdqu	%ymm5,96(%rdi)
+	je	L$done8x
+
+	leaq	128(%rsi),%rsi
+	xorq	%r10,%r10
+	vmovdqa	%ymm12,0(%rsp)
+	leaq	128(%rdi),%rdi
+	subq	$128,%rdx
+	vmovdqa	%ymm13,32(%rsp)
+	jmp	L$oop_tail8x
+
+.p2align	5
+L$192_or_more8x:
+	vpxor	0(%rsi),%ymm6,%ymm6
+	vpxor	32(%rsi),%ymm8,%ymm8
+	vpxor	64(%rsi),%ymm1,%ymm1
+	vpxor	96(%rsi),%ymm5,%ymm5
+	vpxor	128(%rsi),%ymm12,%ymm12
+	vpxor	160(%rsi),%ymm13,%ymm13
+	vmovdqu	%ymm6,0(%rdi)
+	vmovdqu	%ymm8,32(%rdi)
+	vmovdqu	%ymm1,64(%rdi)
+	vmovdqu	%ymm5,96(%rdi)
+	vmovdqu	%ymm12,128(%rdi)
+	vmovdqu	%ymm13,160(%rdi)
+	je	L$done8x
+
+	leaq	192(%rsi),%rsi
+	xorq	%r10,%r10
+	vmovdqa	%ymm10,0(%rsp)
+	leaq	192(%rdi),%rdi
+	subq	$192,%rdx
+	vmovdqa	%ymm15,32(%rsp)
+	jmp	L$oop_tail8x
+
+.p2align	5
+L$256_or_more8x:
+	vpxor	0(%rsi),%ymm6,%ymm6
+	vpxor	32(%rsi),%ymm8,%ymm8
+	vpxor	64(%rsi),%ymm1,%ymm1
+	vpxor	96(%rsi),%ymm5,%ymm5
+	vpxor	128(%rsi),%ymm12,%ymm12
+	vpxor	160(%rsi),%ymm13,%ymm13
+	vpxor	192(%rsi),%ymm10,%ymm10
+	vpxor	224(%rsi),%ymm15,%ymm15
+	vmovdqu	%ymm6,0(%rdi)
+	vmovdqu	%ymm8,32(%rdi)
+	vmovdqu	%ymm1,64(%rdi)
+	vmovdqu	%ymm5,96(%rdi)
+	vmovdqu	%ymm12,128(%rdi)
+	vmovdqu	%ymm13,160(%rdi)
+	vmovdqu	%ymm10,192(%rdi)
+	vmovdqu	%ymm15,224(%rdi)
+	je	L$done8x
+
+	leaq	256(%rsi),%rsi
+	xorq	%r10,%r10
+	vmovdqa	%ymm14,0(%rsp)
+	leaq	256(%rdi),%rdi
+	subq	$256,%rdx
+	vmovdqa	%ymm2,32(%rsp)
+	jmp	L$oop_tail8x
+
+.p2align	5
+L$320_or_more8x:
+	vpxor	0(%rsi),%ymm6,%ymm6
+	vpxor	32(%rsi),%ymm8,%ymm8
+	vpxor	64(%rsi),%ymm1,%ymm1
+	vpxor	96(%rsi),%ymm5,%ymm5
+	vpxor	128(%rsi),%ymm12,%ymm12
+	vpxor	160(%rsi),%ymm13,%ymm13
+	vpxor	192(%rsi),%ymm10,%ymm10
+	vpxor	224(%rsi),%ymm15,%ymm15
+	vpxor	256(%rsi),%ymm14,%ymm14
+	vpxor	288(%rsi),%ymm2,%ymm2
+	vmovdqu	%ymm6,0(%rdi)
+	vmovdqu	%ymm8,32(%rdi)
+	vmovdqu	%ymm1,64(%rdi)
+	vmovdqu	%ymm5,96(%rdi)
+	vmovdqu	%ymm12,128(%rdi)
+	vmovdqu	%ymm13,160(%rdi)
+	vmovdqu	%ymm10,192(%rdi)
+	vmovdqu	%ymm15,224(%rdi)
+	vmovdqu	%ymm14,256(%rdi)
+	vmovdqu	%ymm2,288(%rdi)
+	je	L$done8x
+
+	leaq	320(%rsi),%rsi
+	xorq	%r10,%r10
+	vmovdqa	%ymm3,0(%rsp)
+	leaq	320(%rdi),%rdi
+	subq	$320,%rdx
+	vmovdqa	%ymm7,32(%rsp)
+	jmp	L$oop_tail8x
+
+.p2align	5
+L$384_or_more8x:
+	vpxor	0(%rsi),%ymm6,%ymm6
+	vpxor	32(%rsi),%ymm8,%ymm8
+	vpxor	64(%rsi),%ymm1,%ymm1
+	vpxor	96(%rsi),%ymm5,%ymm5
+	vpxor	128(%rsi),%ymm12,%ymm12
+	vpxor	160(%rsi),%ymm13,%ymm13
+	vpxor	192(%rsi),%ymm10,%ymm10
+	vpxor	224(%rsi),%ymm15,%ymm15
+	vpxor	256(%rsi),%ymm14,%ymm14
+	vpxor	288(%rsi),%ymm2,%ymm2
+	vpxor	320(%rsi),%ymm3,%ymm3
+	vpxor	352(%rsi),%ymm7,%ymm7
+	vmovdqu	%ymm6,0(%rdi)
+	vmovdqu	%ymm8,32(%rdi)
+	vmovdqu	%ymm1,64(%rdi)
+	vmovdqu	%ymm5,96(%rdi)
+	vmovdqu	%ymm12,128(%rdi)
+	vmovdqu	%ymm13,160(%rdi)
+	vmovdqu	%ymm10,192(%rdi)
+	vmovdqu	%ymm15,224(%rdi)
+	vmovdqu	%ymm14,256(%rdi)
+	vmovdqu	%ymm2,288(%rdi)
+	vmovdqu	%ymm3,320(%rdi)
+	vmovdqu	%ymm7,352(%rdi)
+	je	L$done8x
+
+	leaq	384(%rsi),%rsi
+	xorq	%r10,%r10
+	vmovdqa	%ymm11,0(%rsp)
+	leaq	384(%rdi),%rdi
+	subq	$384,%rdx
+	vmovdqa	%ymm9,32(%rsp)
+	jmp	L$oop_tail8x
+
+.p2align	5
+L$448_or_more8x:
+	vpxor	0(%rsi),%ymm6,%ymm6
+	vpxor	32(%rsi),%ymm8,%ymm8
+	vpxor	64(%rsi),%ymm1,%ymm1
+	vpxor	96(%rsi),%ymm5,%ymm5
+	vpxor	128(%rsi),%ymm12,%ymm12
+	vpxor	160(%rsi),%ymm13,%ymm13
+	vpxor	192(%rsi),%ymm10,%ymm10
+	vpxor	224(%rsi),%ymm15,%ymm15
+	vpxor	256(%rsi),%ymm14,%ymm14
+	vpxor	288(%rsi),%ymm2,%ymm2
+	vpxor	320(%rsi),%ymm3,%ymm3
+	vpxor	352(%rsi),%ymm7,%ymm7
+	vpxor	384(%rsi),%ymm11,%ymm11
+	vpxor	416(%rsi),%ymm9,%ymm9
+	vmovdqu	%ymm6,0(%rdi)
+	vmovdqu	%ymm8,32(%rdi)
+	vmovdqu	%ymm1,64(%rdi)
+	vmovdqu	%ymm5,96(%rdi)
+	vmovdqu	%ymm12,128(%rdi)
+	vmovdqu	%ymm13,160(%rdi)
+	vmovdqu	%ymm10,192(%rdi)
+	vmovdqu	%ymm15,224(%rdi)
+	vmovdqu	%ymm14,256(%rdi)
+	vmovdqu	%ymm2,288(%rdi)
+	vmovdqu	%ymm3,320(%rdi)
+	vmovdqu	%ymm7,352(%rdi)
+	vmovdqu	%ymm11,384(%rdi)
+	vmovdqu	%ymm9,416(%rdi)
+	je	L$done8x
+
+	leaq	448(%rsi),%rsi
+	xorq	%r10,%r10
+	vmovdqa	%ymm0,0(%rsp)
+	leaq	448(%rdi),%rdi
+	subq	$448,%rdx
+	vmovdqa	%ymm4,32(%rsp)
+
+L$oop_tail8x:
+	movzbl	(%rsi,%r10,1),%eax
+	movzbl	(%rsp,%r10,1),%ecx
+	leaq	1(%r10),%r10
+	xorl	%ecx,%eax
+	movb	%al,-1(%rdi,%r10,1)
+	decq	%rdx
+	jnz	L$oop_tail8x
+
+L$done8x:
+	vzeroall
+	leaq	(%r9),%rsp
+L$8x_epilogue:
+	.byte	0xf3,0xc3
+
+#endif
diff --git a/mac-x86_64/crypto/cipher/chacha20_poly1305_x86_64.S b/mac-x86_64/crypto/cipher/chacha20_poly1305_x86_64.S
new file mode 100644
index 0000000..62d114d
--- /dev/null
+++ b/mac-x86_64/crypto/cipher/chacha20_poly1305_x86_64.S
@@ -0,0 +1,8787 @@
+#if defined(__x86_64__)
+.text	
+
+
+chacha20_poly1305_constants:
+
+.p2align	6
+.chacha20_consts:
+.byte	'e','x','p','a','n','d',' ','3','2','-','b','y','t','e',' ','k'
+.byte	'e','x','p','a','n','d',' ','3','2','-','b','y','t','e',' ','k'
+.rol8:
+.byte	3,0,1,2, 7,4,5,6, 11,8,9,10, 15,12,13,14
+.byte	3,0,1,2, 7,4,5,6, 11,8,9,10, 15,12,13,14
+.rol16:
+.byte	2,3,0,1, 6,7,4,5, 10,11,8,9, 14,15,12,13
+.byte	2,3,0,1, 6,7,4,5, 10,11,8,9, 14,15,12,13
+.avx2_init:
+.long	0,0,0,0
+.sse_inc:
+.long	1,0,0,0
+.avx2_inc:
+.long	2,0,0,0,2,0,0,0
+.clamp:
+.quad	0x0FFFFFFC0FFFFFFF, 0x0FFFFFFC0FFFFFFC
+.quad	0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF
+.p2align	4
+.and_masks:
+.byte	0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+.byte	0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+.byte	0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+.byte	0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+.byte	0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+.byte	0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+.byte	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+.byte	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+.byte	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+.byte	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00
+.byte	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00
+.byte	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00
+.byte	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00
+.byte	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00
+.byte	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00
+
+
+.p2align	6
+poly_hash_ad_internal:
+
+	xorq	%r10,%r10
+	xorq	%r11,%r11
+	xorq	%r12,%r12
+	cmpq	$13,%r8
+	jne	hash_ad_loop
+poly_fast_tls_ad:
+
+	movq	(%rcx),%r10
+	movq	5(%rcx),%r11
+	shrq	$24,%r11
+	movq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	.byte	0xf3,0xc3
+hash_ad_loop:
+
+	cmpq	$16,%r8
+	jb	hash_ad_tail
+	addq	0(%rcx),%r10
+	adcq	8+0(%rcx),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%rcx),%rcx
+	subq	$16,%r8
+	jmp	hash_ad_loop
+hash_ad_tail:
+	cmpq	$0,%r8
+	je	1f
+
+	xorq	%r13,%r13
+	xorq	%r14,%r14
+	xorq	%r15,%r15
+	addq	%r8,%rcx
+hash_ad_tail_loop:
+	shldq	$8,%r13,%r14
+	shlq	$8,%r13
+	movzbq	-1(%rcx),%r15
+	xorq	%r15,%r13
+	decq	%rcx
+	decq	%r8
+	jne	hash_ad_tail_loop
+
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+
+1:
+	.byte	0xf3,0xc3
+
+
+
+.globl	_chacha20_poly1305_open
+.private_extern _chacha20_poly1305_open
+
+.p2align	6
+_chacha20_poly1305_open:
+
+	pushq	%rbp
+
+	pushq	%rbx
+
+	pushq	%r12
+
+	pushq	%r13
+
+	pushq	%r14
+
+	pushq	%r15
+
+
+
+	pushq	%r9
+
+	subq	$288 + 32,%rsp
+
+
+
+
+
+
+
+	leaq	32(%rsp),%rbp
+	andq	$-32,%rbp
+	movq	%rdx,8+32(%rbp)
+	movq	%r8,0+32(%rbp)
+	movq	%rdx,%rbx
+
+	movl	_OPENSSL_ia32cap_P+8(%rip),%eax
+	andl	$288,%eax
+	xorl	$288,%eax
+	jz	chacha20_poly1305_open_avx2
+
+1:
+	cmpq	$128,%rbx
+	jbe	open_sse_128
+
+	movdqa	.chacha20_consts(%rip),%xmm0
+	movdqu	0(%r9),%xmm4
+	movdqu	16(%r9),%xmm8
+	movdqu	32(%r9),%xmm12
+	movdqa	%xmm12,%xmm7
+
+	movdqa	%xmm4,48(%rbp)
+	movdqa	%xmm8,64(%rbp)
+	movdqa	%xmm12,96(%rbp)
+	movq	$10,%r10
+1:
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,4
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,12
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,12
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,4
+
+	decq	%r10
+	jne	1b
+
+	paddd	.chacha20_consts(%rip),%xmm0
+	paddd	48(%rbp),%xmm4
+
+	pand	.clamp(%rip),%xmm0
+	movdqa	%xmm0,0(%rbp)
+	movdqa	%xmm4,16(%rbp)
+
+	movq	%r8,%r8
+	call	poly_hash_ad_internal
+open_sse_main_loop:
+	cmpq	$256,%rbx
+	jb	2f
+
+	movdqa	.chacha20_consts(%rip),%xmm0
+	movdqa	48(%rbp),%xmm4
+	movdqa	64(%rbp),%xmm8
+	movdqa	%xmm0,%xmm1
+	movdqa	%xmm4,%xmm5
+	movdqa	%xmm8,%xmm9
+	movdqa	%xmm0,%xmm2
+	movdqa	%xmm4,%xmm6
+	movdqa	%xmm8,%xmm10
+	movdqa	%xmm0,%xmm3
+	movdqa	%xmm4,%xmm7
+	movdqa	%xmm8,%xmm11
+	movdqa	96(%rbp),%xmm15
+	paddd	.sse_inc(%rip),%xmm15
+	movdqa	%xmm15,%xmm14
+	paddd	.sse_inc(%rip),%xmm14
+	movdqa	%xmm14,%xmm13
+	paddd	.sse_inc(%rip),%xmm13
+	movdqa	%xmm13,%xmm12
+	paddd	.sse_inc(%rip),%xmm12
+	movdqa	%xmm12,96(%rbp)
+	movdqa	%xmm13,112(%rbp)
+	movdqa	%xmm14,128(%rbp)
+	movdqa	%xmm15,144(%rbp)
+
+
+
+	movq	$4,%rcx
+	movq	%rsi,%r8
+1:
+	movdqa	%xmm8,80(%rbp)
+	movdqa	.rol16(%rip),%xmm8
+	paddd	%xmm7,%xmm3
+	paddd	%xmm6,%xmm2
+	paddd	%xmm5,%xmm1
+	paddd	%xmm4,%xmm0
+	pxor	%xmm3,%xmm15
+	pxor	%xmm2,%xmm14
+	pxor	%xmm1,%xmm13
+	pxor	%xmm0,%xmm12
+.byte	102,69,15,56,0,248
+.byte	102,69,15,56,0,240
+.byte	102,69,15,56,0,232
+.byte	102,69,15,56,0,224
+	movdqa	80(%rbp),%xmm8
+	paddd	%xmm15,%xmm11
+	paddd	%xmm14,%xmm10
+	paddd	%xmm13,%xmm9
+	paddd	%xmm12,%xmm8
+	pxor	%xmm11,%xmm7
+	addq	0(%r8),%r10
+	adcq	8+0(%r8),%r11
+	adcq	$1,%r12
+
+	leaq	16(%r8),%r8
+	pxor	%xmm10,%xmm6
+	pxor	%xmm9,%xmm5
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm8,80(%rbp)
+	movdqa	%xmm7,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm7
+	pxor	%xmm8,%xmm7
+	movdqa	%xmm6,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm6
+	pxor	%xmm8,%xmm6
+	movdqa	%xmm5,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm5
+	pxor	%xmm8,%xmm5
+	movdqa	%xmm4,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm4
+	pxor	%xmm8,%xmm4
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movdqa	.rol8(%rip),%xmm8
+	paddd	%xmm7,%xmm3
+	paddd	%xmm6,%xmm2
+	paddd	%xmm5,%xmm1
+	paddd	%xmm4,%xmm0
+	pxor	%xmm3,%xmm15
+	pxor	%xmm2,%xmm14
+	pxor	%xmm1,%xmm13
+	pxor	%xmm0,%xmm12
+.byte	102,69,15,56,0,248
+.byte	102,69,15,56,0,240
+.byte	102,69,15,56,0,232
+.byte	102,69,15,56,0,224
+	movdqa	80(%rbp),%xmm8
+	paddd	%xmm15,%xmm11
+	paddd	%xmm14,%xmm10
+	paddd	%xmm13,%xmm9
+	paddd	%xmm12,%xmm8
+	pxor	%xmm11,%xmm7
+	pxor	%xmm10,%xmm6
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	pxor	%xmm9,%xmm5
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm8,80(%rbp)
+	movdqa	%xmm7,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm7
+	pxor	%xmm8,%xmm7
+	movdqa	%xmm6,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm6
+	pxor	%xmm8,%xmm6
+	movdqa	%xmm5,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm5
+	pxor	%xmm8,%xmm5
+	movdqa	%xmm4,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm4
+	pxor	%xmm8,%xmm4
+	movdqa	80(%rbp),%xmm8
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+.byte	102,15,58,15,255,4
+.byte	102,69,15,58,15,219,8
+.byte	102,69,15,58,15,255,12
+.byte	102,15,58,15,246,4
+.byte	102,69,15,58,15,210,8
+.byte	102,69,15,58,15,246,12
+.byte	102,15,58,15,237,4
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,12
+.byte	102,15,58,15,228,4
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,12
+	movdqa	%xmm8,80(%rbp)
+	movdqa	.rol16(%rip),%xmm8
+	paddd	%xmm7,%xmm3
+	paddd	%xmm6,%xmm2
+	paddd	%xmm5,%xmm1
+	paddd	%xmm4,%xmm0
+	pxor	%xmm3,%xmm15
+	pxor	%xmm2,%xmm14
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	pxor	%xmm1,%xmm13
+	pxor	%xmm0,%xmm12
+.byte	102,69,15,56,0,248
+.byte	102,69,15,56,0,240
+.byte	102,69,15,56,0,232
+.byte	102,69,15,56,0,224
+	movdqa	80(%rbp),%xmm8
+	paddd	%xmm15,%xmm11
+	paddd	%xmm14,%xmm10
+	paddd	%xmm13,%xmm9
+	paddd	%xmm12,%xmm8
+	pxor	%xmm11,%xmm7
+	pxor	%xmm10,%xmm6
+	pxor	%xmm9,%xmm5
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm8,80(%rbp)
+	movdqa	%xmm7,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm7
+	pxor	%xmm8,%xmm7
+	movdqa	%xmm6,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm6
+	pxor	%xmm8,%xmm6
+	movdqa	%xmm5,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm5
+	pxor	%xmm8,%xmm5
+	movdqa	%xmm4,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm4
+	pxor	%xmm8,%xmm4
+	movdqa	.rol8(%rip),%xmm8
+	paddd	%xmm7,%xmm3
+	paddd	%xmm6,%xmm2
+	paddd	%xmm5,%xmm1
+	paddd	%xmm4,%xmm0
+	pxor	%xmm3,%xmm15
+	pxor	%xmm2,%xmm14
+	pxor	%xmm1,%xmm13
+	pxor	%xmm0,%xmm12
+.byte	102,69,15,56,0,248
+.byte	102,69,15,56,0,240
+.byte	102,69,15,56,0,232
+.byte	102,69,15,56,0,224
+	movdqa	80(%rbp),%xmm8
+	paddd	%xmm15,%xmm11
+	paddd	%xmm14,%xmm10
+	paddd	%xmm13,%xmm9
+	paddd	%xmm12,%xmm8
+	pxor	%xmm11,%xmm7
+	pxor	%xmm10,%xmm6
+	pxor	%xmm9,%xmm5
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm8,80(%rbp)
+	movdqa	%xmm7,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm7
+	pxor	%xmm8,%xmm7
+	movdqa	%xmm6,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm6
+	pxor	%xmm8,%xmm6
+	movdqa	%xmm5,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm5
+	pxor	%xmm8,%xmm5
+	movdqa	%xmm4,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm4
+	pxor	%xmm8,%xmm4
+	movdqa	80(%rbp),%xmm8
+.byte	102,15,58,15,255,12
+.byte	102,69,15,58,15,219,8
+.byte	102,69,15,58,15,255,4
+.byte	102,15,58,15,246,12
+.byte	102,69,15,58,15,210,8
+.byte	102,69,15,58,15,246,4
+.byte	102,15,58,15,237,12
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,4
+.byte	102,15,58,15,228,12
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,4
+
+	decq	%rcx
+	jge	1b
+	addq	0(%r8),%r10
+	adcq	8+0(%r8),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%r8),%r8
+	cmpq	$-6,%rcx
+	jg	1b
+	paddd	.chacha20_consts(%rip),%xmm3
+	paddd	48(%rbp),%xmm7
+	paddd	64(%rbp),%xmm11
+	paddd	144(%rbp),%xmm15
+	paddd	.chacha20_consts(%rip),%xmm2
+	paddd	48(%rbp),%xmm6
+	paddd	64(%rbp),%xmm10
+	paddd	128(%rbp),%xmm14
+	paddd	.chacha20_consts(%rip),%xmm1
+	paddd	48(%rbp),%xmm5
+	paddd	64(%rbp),%xmm9
+	paddd	112(%rbp),%xmm13
+	paddd	.chacha20_consts(%rip),%xmm0
+	paddd	48(%rbp),%xmm4
+	paddd	64(%rbp),%xmm8
+	paddd	96(%rbp),%xmm12
+	movdqa	%xmm12,80(%rbp)
+	movdqu	0 + 0(%rsi),%xmm12
+	pxor	%xmm3,%xmm12
+	movdqu	%xmm12,0 + 0(%rdi)
+	movdqu	16 + 0(%rsi),%xmm12
+	pxor	%xmm7,%xmm12
+	movdqu	%xmm12,16 + 0(%rdi)
+	movdqu	32 + 0(%rsi),%xmm12
+	pxor	%xmm11,%xmm12
+	movdqu	%xmm12,32 + 0(%rdi)
+	movdqu	48 + 0(%rsi),%xmm12
+	pxor	%xmm15,%xmm12
+	movdqu	%xmm12,48 + 0(%rdi)
+	movdqu	0 + 64(%rsi),%xmm3
+	movdqu	16 + 64(%rsi),%xmm7
+	movdqu	32 + 64(%rsi),%xmm11
+	movdqu	48 + 64(%rsi),%xmm15
+	pxor	%xmm3,%xmm2
+	pxor	%xmm7,%xmm6
+	pxor	%xmm11,%xmm10
+	pxor	%xmm14,%xmm15
+	movdqu	%xmm2,0 + 64(%rdi)
+	movdqu	%xmm6,16 + 64(%rdi)
+	movdqu	%xmm10,32 + 64(%rdi)
+	movdqu	%xmm15,48 + 64(%rdi)
+	movdqu	0 + 128(%rsi),%xmm3
+	movdqu	16 + 128(%rsi),%xmm7
+	movdqu	32 + 128(%rsi),%xmm11
+	movdqu	48 + 128(%rsi),%xmm15
+	pxor	%xmm3,%xmm1
+	pxor	%xmm7,%xmm5
+	pxor	%xmm11,%xmm9
+	pxor	%xmm13,%xmm15
+	movdqu	%xmm1,0 + 128(%rdi)
+	movdqu	%xmm5,16 + 128(%rdi)
+	movdqu	%xmm9,32 + 128(%rdi)
+	movdqu	%xmm15,48 + 128(%rdi)
+	movdqu	0 + 192(%rsi),%xmm3
+	movdqu	16 + 192(%rsi),%xmm7
+	movdqu	32 + 192(%rsi),%xmm11
+	movdqu	48 + 192(%rsi),%xmm15
+	pxor	%xmm3,%xmm0
+	pxor	%xmm7,%xmm4
+	pxor	%xmm11,%xmm8
+	pxor	80(%rbp),%xmm15
+	movdqu	%xmm0,0 + 192(%rdi)
+	movdqu	%xmm4,16 + 192(%rdi)
+	movdqu	%xmm8,32 + 192(%rdi)
+	movdqu	%xmm15,48 + 192(%rdi)
+
+	leaq	256(%rsi),%rsi
+	leaq	256(%rdi),%rdi
+	subq	$256,%rbx
+	jmp	open_sse_main_loop
+2:
+
+	testq	%rbx,%rbx
+	jz	open_sse_finalize
+	cmpq	$64,%rbx
+	ja	3f
+	movdqa	.chacha20_consts(%rip),%xmm0
+	movdqa	48(%rbp),%xmm4
+	movdqa	64(%rbp),%xmm8
+	movdqa	96(%rbp),%xmm12
+	paddd	.sse_inc(%rip),%xmm12
+	movdqa	%xmm12,96(%rbp)
+
+	xorq	%r8,%r8
+	movq	%rbx,%rcx
+	cmpq	$16,%rcx
+	jb	2f
+1:
+	addq	0(%rsi,%r8), %r10
+	adcq	8+0(%rsi,%r8), %r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	subq	$16,%rcx
+2:
+	addq	$16,%r8
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,4
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,12
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,12
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,4
+
+	cmpq	$16,%rcx
+	jae	1b
+	cmpq	$160,%r8
+	jne	2b
+	paddd	.chacha20_consts(%rip),%xmm0
+	paddd	48(%rbp),%xmm4
+	paddd	64(%rbp),%xmm8
+	paddd	96(%rbp),%xmm12
+
+	jmp	open_sse_tail_64_dec_loop
+3:
+	cmpq	$128,%rbx
+	ja	3f
+	movdqa	.chacha20_consts(%rip),%xmm0
+	movdqa	48(%rbp),%xmm4
+	movdqa	64(%rbp),%xmm8
+	movdqa	%xmm0,%xmm1
+	movdqa	%xmm4,%xmm5
+	movdqa	%xmm8,%xmm9
+	movdqa	96(%rbp),%xmm13
+	paddd	.sse_inc(%rip),%xmm13
+	movdqa	%xmm13,%xmm12
+	paddd	.sse_inc(%rip),%xmm12
+	movdqa	%xmm12,96(%rbp)
+	movdqa	%xmm13,112(%rbp)
+
+	movq	%rbx,%rcx
+	andq	$-16,%rcx
+	xorq	%r8,%r8
+1:
+	addq	0(%rsi,%r8), %r10
+	adcq	8+0(%rsi,%r8), %r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+2:
+	addq	$16,%r8
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,4
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,12
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol16(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm5
+	pxor	%xmm3,%xmm5
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol8(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm5
+	pxor	%xmm3,%xmm5
+.byte	102,15,58,15,237,4
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,12
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,12
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,4
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol16(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm5
+	pxor	%xmm3,%xmm5
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol8(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm5
+	pxor	%xmm3,%xmm5
+.byte	102,15,58,15,237,12
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,4
+
+	cmpq	%rcx,%r8
+	jb	1b
+	cmpq	$160,%r8
+	jne	2b
+	paddd	.chacha20_consts(%rip),%xmm1
+	paddd	48(%rbp),%xmm5
+	paddd	64(%rbp),%xmm9
+	paddd	112(%rbp),%xmm13
+	paddd	.chacha20_consts(%rip),%xmm0
+	paddd	48(%rbp),%xmm4
+	paddd	64(%rbp),%xmm8
+	paddd	96(%rbp),%xmm12
+	movdqu	0 + 0(%rsi),%xmm3
+	movdqu	16 + 0(%rsi),%xmm7
+	movdqu	32 + 0(%rsi),%xmm11
+	movdqu	48 + 0(%rsi),%xmm15
+	pxor	%xmm3,%xmm1
+	pxor	%xmm7,%xmm5
+	pxor	%xmm11,%xmm9
+	pxor	%xmm13,%xmm15
+	movdqu	%xmm1,0 + 0(%rdi)
+	movdqu	%xmm5,16 + 0(%rdi)
+	movdqu	%xmm9,32 + 0(%rdi)
+	movdqu	%xmm15,48 + 0(%rdi)
+
+	subq	$64,%rbx
+	leaq	64(%rsi),%rsi
+	leaq	64(%rdi),%rdi
+	jmp	open_sse_tail_64_dec_loop
+3:
+	cmpq	$192,%rbx
+	ja	3f
+	movdqa	.chacha20_consts(%rip),%xmm0
+	movdqa	48(%rbp),%xmm4
+	movdqa	64(%rbp),%xmm8
+	movdqa	%xmm0,%xmm1
+	movdqa	%xmm4,%xmm5
+	movdqa	%xmm8,%xmm9
+	movdqa	%xmm0,%xmm2
+	movdqa	%xmm4,%xmm6
+	movdqa	%xmm8,%xmm10
+	movdqa	96(%rbp),%xmm14
+	paddd	.sse_inc(%rip),%xmm14
+	movdqa	%xmm14,%xmm13
+	paddd	.sse_inc(%rip),%xmm13
+	movdqa	%xmm13,%xmm12
+	paddd	.sse_inc(%rip),%xmm12
+	movdqa	%xmm12,96(%rbp)
+	movdqa	%xmm13,112(%rbp)
+	movdqa	%xmm14,128(%rbp)
+
+	movq	%rbx,%rcx
+	movq	$160,%r8
+	cmpq	$160,%rcx
+	cmovgq	%r8,%rcx
+	andq	$-16,%rcx
+	xorq	%r8,%r8
+1:
+	addq	0(%rsi,%r8), %r10
+	adcq	8+0(%rsi,%r8), %r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+2:
+	addq	$16,%r8
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,4
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,12
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol16(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm5
+	pxor	%xmm3,%xmm5
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol8(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm5
+	pxor	%xmm3,%xmm5
+.byte	102,15,58,15,237,4
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,12
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol16(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm6
+	pxor	%xmm3,%xmm6
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol8(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm6
+	pxor	%xmm3,%xmm6
+.byte	102,15,58,15,246,4
+.byte	102,69,15,58,15,210,8
+.byte	102,69,15,58,15,246,12
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,12
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,4
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol16(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm5
+	pxor	%xmm3,%xmm5
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol8(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm5
+	pxor	%xmm3,%xmm5
+.byte	102,15,58,15,237,12
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,4
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol16(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm6
+	pxor	%xmm3,%xmm6
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol8(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm6
+	pxor	%xmm3,%xmm6
+.byte	102,15,58,15,246,12
+.byte	102,69,15,58,15,210,8
+.byte	102,69,15,58,15,246,4
+
+	cmpq	%rcx,%r8
+	jb	1b
+	cmpq	$160,%r8
+	jne	2b
+	cmpq	$176,%rbx
+	jb	1f
+	addq	160(%rsi),%r10
+	adcq	8+160(%rsi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	cmpq	$192,%rbx
+	jb	1f
+	addq	176(%rsi),%r10
+	adcq	8+176(%rsi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+1:
+	paddd	.chacha20_consts(%rip),%xmm2
+	paddd	48(%rbp),%xmm6
+	paddd	64(%rbp),%xmm10
+	paddd	128(%rbp),%xmm14
+	paddd	.chacha20_consts(%rip),%xmm1
+	paddd	48(%rbp),%xmm5
+	paddd	64(%rbp),%xmm9
+	paddd	112(%rbp),%xmm13
+	paddd	.chacha20_consts(%rip),%xmm0
+	paddd	48(%rbp),%xmm4
+	paddd	64(%rbp),%xmm8
+	paddd	96(%rbp),%xmm12
+	movdqu	0 + 0(%rsi),%xmm3
+	movdqu	16 + 0(%rsi),%xmm7
+	movdqu	32 + 0(%rsi),%xmm11
+	movdqu	48 + 0(%rsi),%xmm15
+	pxor	%xmm3,%xmm2
+	pxor	%xmm7,%xmm6
+	pxor	%xmm11,%xmm10
+	pxor	%xmm14,%xmm15
+	movdqu	%xmm2,0 + 0(%rdi)
+	movdqu	%xmm6,16 + 0(%rdi)
+	movdqu	%xmm10,32 + 0(%rdi)
+	movdqu	%xmm15,48 + 0(%rdi)
+	movdqu	0 + 64(%rsi),%xmm3
+	movdqu	16 + 64(%rsi),%xmm7
+	movdqu	32 + 64(%rsi),%xmm11
+	movdqu	48 + 64(%rsi),%xmm15
+	pxor	%xmm3,%xmm1
+	pxor	%xmm7,%xmm5
+	pxor	%xmm11,%xmm9
+	pxor	%xmm13,%xmm15
+	movdqu	%xmm1,0 + 64(%rdi)
+	movdqu	%xmm5,16 + 64(%rdi)
+	movdqu	%xmm9,32 + 64(%rdi)
+	movdqu	%xmm15,48 + 64(%rdi)
+
+	subq	$128,%rbx
+	leaq	128(%rsi),%rsi
+	leaq	128(%rdi),%rdi
+	jmp	open_sse_tail_64_dec_loop
+3:
+
+	movdqa	.chacha20_consts(%rip),%xmm0
+	movdqa	48(%rbp),%xmm4
+	movdqa	64(%rbp),%xmm8
+	movdqa	%xmm0,%xmm1
+	movdqa	%xmm4,%xmm5
+	movdqa	%xmm8,%xmm9
+	movdqa	%xmm0,%xmm2
+	movdqa	%xmm4,%xmm6
+	movdqa	%xmm8,%xmm10
+	movdqa	%xmm0,%xmm3
+	movdqa	%xmm4,%xmm7
+	movdqa	%xmm8,%xmm11
+	movdqa	96(%rbp),%xmm15
+	paddd	.sse_inc(%rip),%xmm15
+	movdqa	%xmm15,%xmm14
+	paddd	.sse_inc(%rip),%xmm14
+	movdqa	%xmm14,%xmm13
+	paddd	.sse_inc(%rip),%xmm13
+	movdqa	%xmm13,%xmm12
+	paddd	.sse_inc(%rip),%xmm12
+	movdqa	%xmm12,96(%rbp)
+	movdqa	%xmm13,112(%rbp)
+	movdqa	%xmm14,128(%rbp)
+	movdqa	%xmm15,144(%rbp)
+
+	xorq	%r8,%r8
+1:
+	addq	0(%rsi,%r8), %r10
+	adcq	8+0(%rsi,%r8), %r11
+	adcq	$1,%r12
+	movdqa	%xmm11,80(%rbp)
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm11
+	pslld	$12,%xmm11
+	psrld	$20,%xmm4
+	pxor	%xmm11,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm11
+	pslld	$7,%xmm11
+	psrld	$25,%xmm4
+	pxor	%xmm11,%xmm4
+.byte	102,15,58,15,228,4
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,12
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol16(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm11
+	pslld	$12,%xmm11
+	psrld	$20,%xmm5
+	pxor	%xmm11,%xmm5
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol8(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm11
+	pslld	$7,%xmm11
+	psrld	$25,%xmm5
+	pxor	%xmm11,%xmm5
+.byte	102,15,58,15,237,4
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,12
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol16(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm11
+	pslld	$12,%xmm11
+	psrld	$20,%xmm6
+	pxor	%xmm11,%xmm6
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol8(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm11
+	pslld	$7,%xmm11
+	psrld	$25,%xmm6
+	pxor	%xmm11,%xmm6
+.byte	102,15,58,15,246,4
+.byte	102,69,15,58,15,210,8
+.byte	102,69,15,58,15,246,12
+	movdqa	80(%rbp),%xmm11
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movdqa	%xmm9,80(%rbp)
+	paddd	%xmm7,%xmm3
+	pxor	%xmm3,%xmm15
+	pshufb	.rol16(%rip),%xmm15
+	paddd	%xmm15,%xmm11
+	pxor	%xmm11,%xmm7
+	movdqa	%xmm7,%xmm9
+	pslld	$12,%xmm9
+	psrld	$20,%xmm7
+	pxor	%xmm9,%xmm7
+	paddd	%xmm7,%xmm3
+	pxor	%xmm3,%xmm15
+	pshufb	.rol8(%rip),%xmm15
+	paddd	%xmm15,%xmm11
+	pxor	%xmm11,%xmm7
+	movdqa	%xmm7,%xmm9
+	pslld	$7,%xmm9
+	psrld	$25,%xmm7
+	pxor	%xmm9,%xmm7
+.byte	102,15,58,15,255,4
+.byte	102,69,15,58,15,219,8
+.byte	102,69,15,58,15,255,12
+	movdqa	80(%rbp),%xmm9
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	movdqa	%xmm11,80(%rbp)
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm11
+	pslld	$12,%xmm11
+	psrld	$20,%xmm4
+	pxor	%xmm11,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm11
+	pslld	$7,%xmm11
+	psrld	$25,%xmm4
+	pxor	%xmm11,%xmm4
+.byte	102,15,58,15,228,12
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,4
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol16(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm11
+	pslld	$12,%xmm11
+	psrld	$20,%xmm5
+	pxor	%xmm11,%xmm5
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol8(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm11
+	pslld	$7,%xmm11
+	psrld	$25,%xmm5
+	pxor	%xmm11,%xmm5
+.byte	102,15,58,15,237,12
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,4
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol16(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm11
+	pslld	$12,%xmm11
+	psrld	$20,%xmm6
+	pxor	%xmm11,%xmm6
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol8(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm11
+	pslld	$7,%xmm11
+	psrld	$25,%xmm6
+	pxor	%xmm11,%xmm6
+.byte	102,15,58,15,246,12
+.byte	102,69,15,58,15,210,8
+.byte	102,69,15,58,15,246,4
+	movdqa	80(%rbp),%xmm11
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	movdqa	%xmm9,80(%rbp)
+	paddd	%xmm7,%xmm3
+	pxor	%xmm3,%xmm15
+	pshufb	.rol16(%rip),%xmm15
+	paddd	%xmm15,%xmm11
+	pxor	%xmm11,%xmm7
+	movdqa	%xmm7,%xmm9
+	pslld	$12,%xmm9
+	psrld	$20,%xmm7
+	pxor	%xmm9,%xmm7
+	paddd	%xmm7,%xmm3
+	pxor	%xmm3,%xmm15
+	pshufb	.rol8(%rip),%xmm15
+	paddd	%xmm15,%xmm11
+	pxor	%xmm11,%xmm7
+	movdqa	%xmm7,%xmm9
+	pslld	$7,%xmm9
+	psrld	$25,%xmm7
+	pxor	%xmm9,%xmm7
+.byte	102,15,58,15,255,12
+.byte	102,69,15,58,15,219,8
+.byte	102,69,15,58,15,255,4
+	movdqa	80(%rbp),%xmm9
+
+	addq	$16,%r8
+	cmpq	$160,%r8
+	jb	1b
+	movq	%rbx,%rcx
+	andq	$-16,%rcx
+1:
+	addq	0(%rsi,%r8), %r10
+	adcq	8+0(%rsi,%r8), %r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	addq	$16,%r8
+	cmpq	%rcx,%r8
+	jb	1b
+	paddd	.chacha20_consts(%rip),%xmm3
+	paddd	48(%rbp),%xmm7
+	paddd	64(%rbp),%xmm11
+	paddd	144(%rbp),%xmm15
+	paddd	.chacha20_consts(%rip),%xmm2
+	paddd	48(%rbp),%xmm6
+	paddd	64(%rbp),%xmm10
+	paddd	128(%rbp),%xmm14
+	paddd	.chacha20_consts(%rip),%xmm1
+	paddd	48(%rbp),%xmm5
+	paddd	64(%rbp),%xmm9
+	paddd	112(%rbp),%xmm13
+	paddd	.chacha20_consts(%rip),%xmm0
+	paddd	48(%rbp),%xmm4
+	paddd	64(%rbp),%xmm8
+	paddd	96(%rbp),%xmm12
+	movdqa	%xmm12,80(%rbp)
+	movdqu	0 + 0(%rsi),%xmm12
+	pxor	%xmm3,%xmm12
+	movdqu	%xmm12,0 + 0(%rdi)
+	movdqu	16 + 0(%rsi),%xmm12
+	pxor	%xmm7,%xmm12
+	movdqu	%xmm12,16 + 0(%rdi)
+	movdqu	32 + 0(%rsi),%xmm12
+	pxor	%xmm11,%xmm12
+	movdqu	%xmm12,32 + 0(%rdi)
+	movdqu	48 + 0(%rsi),%xmm12
+	pxor	%xmm15,%xmm12
+	movdqu	%xmm12,48 + 0(%rdi)
+	movdqu	0 + 64(%rsi),%xmm3
+	movdqu	16 + 64(%rsi),%xmm7
+	movdqu	32 + 64(%rsi),%xmm11
+	movdqu	48 + 64(%rsi),%xmm15
+	pxor	%xmm3,%xmm2
+	pxor	%xmm7,%xmm6
+	pxor	%xmm11,%xmm10
+	pxor	%xmm14,%xmm15
+	movdqu	%xmm2,0 + 64(%rdi)
+	movdqu	%xmm6,16 + 64(%rdi)
+	movdqu	%xmm10,32 + 64(%rdi)
+	movdqu	%xmm15,48 + 64(%rdi)
+	movdqu	0 + 128(%rsi),%xmm3
+	movdqu	16 + 128(%rsi),%xmm7
+	movdqu	32 + 128(%rsi),%xmm11
+	movdqu	48 + 128(%rsi),%xmm15
+	pxor	%xmm3,%xmm1
+	pxor	%xmm7,%xmm5
+	pxor	%xmm11,%xmm9
+	pxor	%xmm13,%xmm15
+	movdqu	%xmm1,0 + 128(%rdi)
+	movdqu	%xmm5,16 + 128(%rdi)
+	movdqu	%xmm9,32 + 128(%rdi)
+	movdqu	%xmm15,48 + 128(%rdi)
+
+	movdqa	80(%rbp),%xmm12
+	subq	$192,%rbx
+	leaq	192(%rsi),%rsi
+	leaq	192(%rdi),%rdi
+
+
+open_sse_tail_64_dec_loop:
+	cmpq	$16,%rbx
+	jb	1f
+	subq	$16,%rbx
+	movdqu	(%rsi),%xmm3
+	pxor	%xmm3,%xmm0
+	movdqu	%xmm0,(%rdi)
+	leaq	16(%rsi),%rsi
+	leaq	16(%rdi),%rdi
+	movdqa	%xmm4,%xmm0
+	movdqa	%xmm8,%xmm4
+	movdqa	%xmm12,%xmm8
+	jmp	open_sse_tail_64_dec_loop
+1:
+	movdqa	%xmm0,%xmm1
+
+
+open_sse_tail_16:
+	testq	%rbx,%rbx
+	jz	open_sse_finalize
+
+
+
+	pxor	%xmm3,%xmm3
+	leaq	-1(%rsi,%rbx), %rsi
+	movq	%rbx,%r8
+2:
+	pslldq	$1,%xmm3
+	pinsrb	$0,(%rsi),%xmm3
+	subq	$1,%rsi
+	subq	$1,%r8
+	jnz	2b
+
+3:
+.byte	102,73,15,126,221
+	pextrq	$1,%xmm3,%r14
+
+	pxor	%xmm1,%xmm3
+
+
+2:
+	pextrb	$0,%xmm3,(%rdi)
+	psrldq	$1,%xmm3
+	addq	$1,%rdi
+	subq	$1,%rbx
+	jne	2b
+
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+
+open_sse_finalize:
+	addq	32(%rbp),%r10
+	adcq	8+32(%rbp),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+
+	movq	%r10,%r13
+	movq	%r11,%r14
+	movq	%r12,%r15
+	subq	$-5,%r10
+	sbbq	$-1,%r11
+	sbbq	$3,%r12
+	cmovcq	%r13,%r10
+	cmovcq	%r14,%r11
+	cmovcq	%r15,%r12
+
+	addq	0+16(%rbp),%r10
+	adcq	8+16(%rbp),%r11
+
+	addq	$288 + 32,%rsp
+
+	popq	%r9
+
+	movq	%r10,(%r9)
+	movq	%r11,8(%r9)
+
+	popq	%r15
+
+	popq	%r14
+
+	popq	%r13
+
+	popq	%r12
+
+	popq	%rbx
+
+	popq	%rbp
+
+	.byte	0xf3,0xc3
+
+
+open_sse_128:
+	movdqu	.chacha20_consts(%rip),%xmm0
+	movdqa	%xmm0,%xmm1
+	movdqa	%xmm0,%xmm2
+	movdqu	0(%r9),%xmm4
+	movdqa	%xmm4,%xmm5
+	movdqa	%xmm4,%xmm6
+	movdqu	16(%r9),%xmm8
+	movdqa	%xmm8,%xmm9
+	movdqa	%xmm8,%xmm10
+	movdqu	32(%r9),%xmm12
+	movdqa	%xmm12,%xmm13
+	paddd	.sse_inc(%rip),%xmm13
+	movdqa	%xmm13,%xmm14
+	paddd	.sse_inc(%rip),%xmm14
+	movdqa	%xmm4,%xmm7
+	movdqa	%xmm8,%xmm11
+	movdqa	%xmm13,%xmm15
+	movq	$10,%r10
+1:
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,4
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,12
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol16(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm5
+	pxor	%xmm3,%xmm5
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol8(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm5
+	pxor	%xmm3,%xmm5
+.byte	102,15,58,15,237,4
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,12
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol16(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm6
+	pxor	%xmm3,%xmm6
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol8(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm6
+	pxor	%xmm3,%xmm6
+.byte	102,15,58,15,246,4
+.byte	102,69,15,58,15,210,8
+.byte	102,69,15,58,15,246,12
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,12
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,4
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol16(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm5
+	pxor	%xmm3,%xmm5
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol8(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm5
+	pxor	%xmm3,%xmm5
+.byte	102,15,58,15,237,12
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,4
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol16(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm6
+	pxor	%xmm3,%xmm6
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol8(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm6
+	pxor	%xmm3,%xmm6
+.byte	102,15,58,15,246,12
+.byte	102,69,15,58,15,210,8
+.byte	102,69,15,58,15,246,4
+
+	decq	%r10
+	jnz	1b
+	paddd	.chacha20_consts(%rip),%xmm0
+	paddd	.chacha20_consts(%rip),%xmm1
+	paddd	.chacha20_consts(%rip),%xmm2
+	paddd	%xmm7,%xmm4
+	paddd	%xmm7,%xmm5
+	paddd	%xmm7,%xmm6
+	paddd	%xmm11,%xmm9
+	paddd	%xmm11,%xmm10
+	paddd	%xmm15,%xmm13
+	paddd	.sse_inc(%rip),%xmm15
+	paddd	%xmm15,%xmm14
+
+	pand	.clamp(%rip),%xmm0
+	movdqa	%xmm0,0(%rbp)
+	movdqa	%xmm4,16(%rbp)
+
+	movq	%r8,%r8
+	call	poly_hash_ad_internal
+1:
+	cmpq	$16,%rbx
+	jb	open_sse_tail_16
+	subq	$16,%rbx
+	addq	0(%rsi),%r10
+	adcq	8+0(%rsi),%r11
+	adcq	$1,%r12
+
+
+	movdqu	0(%rsi),%xmm3
+	pxor	%xmm3,%xmm1
+	movdqu	%xmm1,0(%rdi)
+	leaq	16(%rsi),%rsi
+	leaq	16(%rdi),%rdi
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+
+	movdqa	%xmm5,%xmm1
+	movdqa	%xmm9,%xmm5
+	movdqa	%xmm13,%xmm9
+	movdqa	%xmm2,%xmm13
+	movdqa	%xmm6,%xmm2
+	movdqa	%xmm10,%xmm6
+	movdqa	%xmm14,%xmm10
+	jmp	1b
+	jmp	open_sse_tail_16
+
+
+
+
+
+
+.globl	_chacha20_poly1305_seal
+.private_extern _chacha20_poly1305_seal
+
+.p2align	6
+_chacha20_poly1305_seal:
+
+	pushq	%rbp
+
+	pushq	%rbx
+
+	pushq	%r12
+
+	pushq	%r13
+
+	pushq	%r14
+
+	pushq	%r15
+
+
+
+	pushq	%r9
+
+	subq	$288 + 32,%rsp
+
+
+
+
+
+
+
+	leaq	32(%rsp),%rbp
+	andq	$-32,%rbp
+	movq	%rdx,8+32(%rbp)
+	movq	%r8,0+32(%rbp)
+	movq	%rdx,%rbx
+
+	movl	_OPENSSL_ia32cap_P+8(%rip),%eax
+	andl	$288,%eax
+	xorl	$288,%eax
+	jz	chacha20_poly1305_seal_avx2
+
+	cmpq	$128,%rbx
+	jbe	seal_sse_128
+
+	movdqa	.chacha20_consts(%rip),%xmm0
+	movdqu	0(%r9),%xmm4
+	movdqu	16(%r9),%xmm8
+	movdqu	32(%r9),%xmm12
+	movdqa	%xmm0,%xmm1
+	movdqa	%xmm0,%xmm2
+	movdqa	%xmm0,%xmm3
+	movdqa	%xmm4,%xmm5
+	movdqa	%xmm4,%xmm6
+	movdqa	%xmm4,%xmm7
+	movdqa	%xmm8,%xmm9
+	movdqa	%xmm8,%xmm10
+	movdqa	%xmm8,%xmm11
+	movdqa	%xmm12,%xmm15
+	paddd	.sse_inc(%rip),%xmm12
+	movdqa	%xmm12,%xmm14
+	paddd	.sse_inc(%rip),%xmm12
+	movdqa	%xmm12,%xmm13
+	paddd	.sse_inc(%rip),%xmm12
+
+	movdqa	%xmm4,48(%rbp)
+	movdqa	%xmm8,64(%rbp)
+	movdqa	%xmm12,96(%rbp)
+	movdqa	%xmm13,112(%rbp)
+	movdqa	%xmm14,128(%rbp)
+	movdqa	%xmm15,144(%rbp)
+	movq	$10,%r10
+1:
+	movdqa	%xmm8,80(%rbp)
+	movdqa	.rol16(%rip),%xmm8
+	paddd	%xmm7,%xmm3
+	paddd	%xmm6,%xmm2
+	paddd	%xmm5,%xmm1
+	paddd	%xmm4,%xmm0
+	pxor	%xmm3,%xmm15
+	pxor	%xmm2,%xmm14
+	pxor	%xmm1,%xmm13
+	pxor	%xmm0,%xmm12
+.byte	102,69,15,56,0,248
+.byte	102,69,15,56,0,240
+.byte	102,69,15,56,0,232
+.byte	102,69,15,56,0,224
+	movdqa	80(%rbp),%xmm8
+	paddd	%xmm15,%xmm11
+	paddd	%xmm14,%xmm10
+	paddd	%xmm13,%xmm9
+	paddd	%xmm12,%xmm8
+	pxor	%xmm11,%xmm7
+	pxor	%xmm10,%xmm6
+	pxor	%xmm9,%xmm5
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm8,80(%rbp)
+	movdqa	%xmm7,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm7
+	pxor	%xmm8,%xmm7
+	movdqa	%xmm6,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm6
+	pxor	%xmm8,%xmm6
+	movdqa	%xmm5,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm5
+	pxor	%xmm8,%xmm5
+	movdqa	%xmm4,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm4
+	pxor	%xmm8,%xmm4
+	movdqa	.rol8(%rip),%xmm8
+	paddd	%xmm7,%xmm3
+	paddd	%xmm6,%xmm2
+	paddd	%xmm5,%xmm1
+	paddd	%xmm4,%xmm0
+	pxor	%xmm3,%xmm15
+	pxor	%xmm2,%xmm14
+	pxor	%xmm1,%xmm13
+	pxor	%xmm0,%xmm12
+.byte	102,69,15,56,0,248
+.byte	102,69,15,56,0,240
+.byte	102,69,15,56,0,232
+.byte	102,69,15,56,0,224
+	movdqa	80(%rbp),%xmm8
+	paddd	%xmm15,%xmm11
+	paddd	%xmm14,%xmm10
+	paddd	%xmm13,%xmm9
+	paddd	%xmm12,%xmm8
+	pxor	%xmm11,%xmm7
+	pxor	%xmm10,%xmm6
+	pxor	%xmm9,%xmm5
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm8,80(%rbp)
+	movdqa	%xmm7,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm7
+	pxor	%xmm8,%xmm7
+	movdqa	%xmm6,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm6
+	pxor	%xmm8,%xmm6
+	movdqa	%xmm5,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm5
+	pxor	%xmm8,%xmm5
+	movdqa	%xmm4,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm4
+	pxor	%xmm8,%xmm4
+	movdqa	80(%rbp),%xmm8
+.byte	102,15,58,15,255,4
+.byte	102,69,15,58,15,219,8
+.byte	102,69,15,58,15,255,12
+.byte	102,15,58,15,246,4
+.byte	102,69,15,58,15,210,8
+.byte	102,69,15,58,15,246,12
+.byte	102,15,58,15,237,4
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,12
+.byte	102,15,58,15,228,4
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,12
+	movdqa	%xmm8,80(%rbp)
+	movdqa	.rol16(%rip),%xmm8
+	paddd	%xmm7,%xmm3
+	paddd	%xmm6,%xmm2
+	paddd	%xmm5,%xmm1
+	paddd	%xmm4,%xmm0
+	pxor	%xmm3,%xmm15
+	pxor	%xmm2,%xmm14
+	pxor	%xmm1,%xmm13
+	pxor	%xmm0,%xmm12
+.byte	102,69,15,56,0,248
+.byte	102,69,15,56,0,240
+.byte	102,69,15,56,0,232
+.byte	102,69,15,56,0,224
+	movdqa	80(%rbp),%xmm8
+	paddd	%xmm15,%xmm11
+	paddd	%xmm14,%xmm10
+	paddd	%xmm13,%xmm9
+	paddd	%xmm12,%xmm8
+	pxor	%xmm11,%xmm7
+	pxor	%xmm10,%xmm6
+	pxor	%xmm9,%xmm5
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm8,80(%rbp)
+	movdqa	%xmm7,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm7
+	pxor	%xmm8,%xmm7
+	movdqa	%xmm6,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm6
+	pxor	%xmm8,%xmm6
+	movdqa	%xmm5,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm5
+	pxor	%xmm8,%xmm5
+	movdqa	%xmm4,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm4
+	pxor	%xmm8,%xmm4
+	movdqa	.rol8(%rip),%xmm8
+	paddd	%xmm7,%xmm3
+	paddd	%xmm6,%xmm2
+	paddd	%xmm5,%xmm1
+	paddd	%xmm4,%xmm0
+	pxor	%xmm3,%xmm15
+	pxor	%xmm2,%xmm14
+	pxor	%xmm1,%xmm13
+	pxor	%xmm0,%xmm12
+.byte	102,69,15,56,0,248
+.byte	102,69,15,56,0,240
+.byte	102,69,15,56,0,232
+.byte	102,69,15,56,0,224
+	movdqa	80(%rbp),%xmm8
+	paddd	%xmm15,%xmm11
+	paddd	%xmm14,%xmm10
+	paddd	%xmm13,%xmm9
+	paddd	%xmm12,%xmm8
+	pxor	%xmm11,%xmm7
+	pxor	%xmm10,%xmm6
+	pxor	%xmm9,%xmm5
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm8,80(%rbp)
+	movdqa	%xmm7,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm7
+	pxor	%xmm8,%xmm7
+	movdqa	%xmm6,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm6
+	pxor	%xmm8,%xmm6
+	movdqa	%xmm5,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm5
+	pxor	%xmm8,%xmm5
+	movdqa	%xmm4,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm4
+	pxor	%xmm8,%xmm4
+	movdqa	80(%rbp),%xmm8
+.byte	102,15,58,15,255,12
+.byte	102,69,15,58,15,219,8
+.byte	102,69,15,58,15,255,4
+.byte	102,15,58,15,246,12
+.byte	102,69,15,58,15,210,8
+.byte	102,69,15,58,15,246,4
+.byte	102,15,58,15,237,12
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,4
+.byte	102,15,58,15,228,12
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,4
+
+	decq	%r10
+	jnz	1b
+	paddd	.chacha20_consts(%rip),%xmm3
+	paddd	48(%rbp),%xmm7
+	paddd	64(%rbp),%xmm11
+	paddd	144(%rbp),%xmm15
+	paddd	.chacha20_consts(%rip),%xmm2
+	paddd	48(%rbp),%xmm6
+	paddd	64(%rbp),%xmm10
+	paddd	128(%rbp),%xmm14
+	paddd	.chacha20_consts(%rip),%xmm1
+	paddd	48(%rbp),%xmm5
+	paddd	64(%rbp),%xmm9
+	paddd	112(%rbp),%xmm13
+	paddd	.chacha20_consts(%rip),%xmm0
+	paddd	48(%rbp),%xmm4
+	paddd	64(%rbp),%xmm8
+	paddd	96(%rbp),%xmm12
+
+
+	pand	.clamp(%rip),%xmm3
+	movdqa	%xmm3,0(%rbp)
+	movdqa	%xmm7,16(%rbp)
+
+	movq	%r8,%r8
+	call	poly_hash_ad_internal
+	movdqu	0 + 0(%rsi),%xmm3
+	movdqu	16 + 0(%rsi),%xmm7
+	movdqu	32 + 0(%rsi),%xmm11
+	movdqu	48 + 0(%rsi),%xmm15
+	pxor	%xmm3,%xmm2
+	pxor	%xmm7,%xmm6
+	pxor	%xmm11,%xmm10
+	pxor	%xmm14,%xmm15
+	movdqu	%xmm2,0 + 0(%rdi)
+	movdqu	%xmm6,16 + 0(%rdi)
+	movdqu	%xmm10,32 + 0(%rdi)
+	movdqu	%xmm15,48 + 0(%rdi)
+	movdqu	0 + 64(%rsi),%xmm3
+	movdqu	16 + 64(%rsi),%xmm7
+	movdqu	32 + 64(%rsi),%xmm11
+	movdqu	48 + 64(%rsi),%xmm15
+	pxor	%xmm3,%xmm1
+	pxor	%xmm7,%xmm5
+	pxor	%xmm11,%xmm9
+	pxor	%xmm13,%xmm15
+	movdqu	%xmm1,0 + 64(%rdi)
+	movdqu	%xmm5,16 + 64(%rdi)
+	movdqu	%xmm9,32 + 64(%rdi)
+	movdqu	%xmm15,48 + 64(%rdi)
+
+	cmpq	$192,%rbx
+	ja	1f
+	movq	$128,%rcx
+	subq	$128,%rbx
+	leaq	128(%rsi),%rsi
+	jmp	seal_sse_128_seal_hash
+1:
+	movdqu	0 + 128(%rsi),%xmm3
+	movdqu	16 + 128(%rsi),%xmm7
+	movdqu	32 + 128(%rsi),%xmm11
+	movdqu	48 + 128(%rsi),%xmm15
+	pxor	%xmm3,%xmm0
+	pxor	%xmm7,%xmm4
+	pxor	%xmm11,%xmm8
+	pxor	%xmm12,%xmm15
+	movdqu	%xmm0,0 + 128(%rdi)
+	movdqu	%xmm4,16 + 128(%rdi)
+	movdqu	%xmm8,32 + 128(%rdi)
+	movdqu	%xmm15,48 + 128(%rdi)
+
+	movq	$192,%rcx
+	subq	$192,%rbx
+	leaq	192(%rsi),%rsi
+	movq	$2,%rcx
+	movq	$8,%r8
+	cmpq	$64,%rbx
+	jbe	seal_sse_tail_64
+	cmpq	$128,%rbx
+	jbe	seal_sse_tail_128
+	cmpq	$192,%rbx
+	jbe	seal_sse_tail_192
+
+1:
+	movdqa	.chacha20_consts(%rip),%xmm0
+	movdqa	48(%rbp),%xmm4
+	movdqa	64(%rbp),%xmm8
+	movdqa	%xmm0,%xmm1
+	movdqa	%xmm4,%xmm5
+	movdqa	%xmm8,%xmm9
+	movdqa	%xmm0,%xmm2
+	movdqa	%xmm4,%xmm6
+	movdqa	%xmm8,%xmm10
+	movdqa	%xmm0,%xmm3
+	movdqa	%xmm4,%xmm7
+	movdqa	%xmm8,%xmm11
+	movdqa	96(%rbp),%xmm15
+	paddd	.sse_inc(%rip),%xmm15
+	movdqa	%xmm15,%xmm14
+	paddd	.sse_inc(%rip),%xmm14
+	movdqa	%xmm14,%xmm13
+	paddd	.sse_inc(%rip),%xmm13
+	movdqa	%xmm13,%xmm12
+	paddd	.sse_inc(%rip),%xmm12
+	movdqa	%xmm12,96(%rbp)
+	movdqa	%xmm13,112(%rbp)
+	movdqa	%xmm14,128(%rbp)
+	movdqa	%xmm15,144(%rbp)
+
+2:
+	movdqa	%xmm8,80(%rbp)
+	movdqa	.rol16(%rip),%xmm8
+	paddd	%xmm7,%xmm3
+	paddd	%xmm6,%xmm2
+	paddd	%xmm5,%xmm1
+	paddd	%xmm4,%xmm0
+	pxor	%xmm3,%xmm15
+	pxor	%xmm2,%xmm14
+	pxor	%xmm1,%xmm13
+	pxor	%xmm0,%xmm12
+.byte	102,69,15,56,0,248
+.byte	102,69,15,56,0,240
+.byte	102,69,15,56,0,232
+.byte	102,69,15,56,0,224
+	movdqa	80(%rbp),%xmm8
+	paddd	%xmm15,%xmm11
+	paddd	%xmm14,%xmm10
+	paddd	%xmm13,%xmm9
+	paddd	%xmm12,%xmm8
+	pxor	%xmm11,%xmm7
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	pxor	%xmm10,%xmm6
+	pxor	%xmm9,%xmm5
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm8,80(%rbp)
+	movdqa	%xmm7,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm7
+	pxor	%xmm8,%xmm7
+	movdqa	%xmm6,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm6
+	pxor	%xmm8,%xmm6
+	movdqa	%xmm5,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm5
+	pxor	%xmm8,%xmm5
+	movdqa	%xmm4,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm4
+	pxor	%xmm8,%xmm4
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movdqa	.rol8(%rip),%xmm8
+	paddd	%xmm7,%xmm3
+	paddd	%xmm6,%xmm2
+	paddd	%xmm5,%xmm1
+	paddd	%xmm4,%xmm0
+	pxor	%xmm3,%xmm15
+	pxor	%xmm2,%xmm14
+	pxor	%xmm1,%xmm13
+	pxor	%xmm0,%xmm12
+.byte	102,69,15,56,0,248
+.byte	102,69,15,56,0,240
+.byte	102,69,15,56,0,232
+.byte	102,69,15,56,0,224
+	movdqa	80(%rbp),%xmm8
+	paddd	%xmm15,%xmm11
+	paddd	%xmm14,%xmm10
+	paddd	%xmm13,%xmm9
+	paddd	%xmm12,%xmm8
+	pxor	%xmm11,%xmm7
+	pxor	%xmm10,%xmm6
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	pxor	%xmm9,%xmm5
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm8,80(%rbp)
+	movdqa	%xmm7,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm7
+	pxor	%xmm8,%xmm7
+	movdqa	%xmm6,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm6
+	pxor	%xmm8,%xmm6
+	movdqa	%xmm5,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm5
+	pxor	%xmm8,%xmm5
+	movdqa	%xmm4,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm4
+	pxor	%xmm8,%xmm4
+	movdqa	80(%rbp),%xmm8
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+.byte	102,15,58,15,255,4
+.byte	102,69,15,58,15,219,8
+.byte	102,69,15,58,15,255,12
+.byte	102,15,58,15,246,4
+.byte	102,69,15,58,15,210,8
+.byte	102,69,15,58,15,246,12
+.byte	102,15,58,15,237,4
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,12
+.byte	102,15,58,15,228,4
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,12
+	movdqa	%xmm8,80(%rbp)
+	movdqa	.rol16(%rip),%xmm8
+	paddd	%xmm7,%xmm3
+	paddd	%xmm6,%xmm2
+	paddd	%xmm5,%xmm1
+	paddd	%xmm4,%xmm0
+	pxor	%xmm3,%xmm15
+	pxor	%xmm2,%xmm14
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	pxor	%xmm1,%xmm13
+	pxor	%xmm0,%xmm12
+.byte	102,69,15,56,0,248
+.byte	102,69,15,56,0,240
+.byte	102,69,15,56,0,232
+.byte	102,69,15,56,0,224
+	movdqa	80(%rbp),%xmm8
+	paddd	%xmm15,%xmm11
+	paddd	%xmm14,%xmm10
+	paddd	%xmm13,%xmm9
+	paddd	%xmm12,%xmm8
+	pxor	%xmm11,%xmm7
+	pxor	%xmm10,%xmm6
+	pxor	%xmm9,%xmm5
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm8,80(%rbp)
+	movdqa	%xmm7,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm7
+	pxor	%xmm8,%xmm7
+	movdqa	%xmm6,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm6
+	pxor	%xmm8,%xmm6
+	movdqa	%xmm5,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm5
+	pxor	%xmm8,%xmm5
+	movdqa	%xmm4,%xmm8
+	psrld	$20,%xmm8
+	pslld	$32-20,%xmm4
+	pxor	%xmm8,%xmm4
+	movdqa	.rol8(%rip),%xmm8
+	paddd	%xmm7,%xmm3
+	paddd	%xmm6,%xmm2
+	paddd	%xmm5,%xmm1
+	paddd	%xmm4,%xmm0
+	pxor	%xmm3,%xmm15
+	pxor	%xmm2,%xmm14
+	pxor	%xmm1,%xmm13
+	pxor	%xmm0,%xmm12
+.byte	102,69,15,56,0,248
+.byte	102,69,15,56,0,240
+.byte	102,69,15,56,0,232
+.byte	102,69,15,56,0,224
+	movdqa	80(%rbp),%xmm8
+	paddd	%xmm15,%xmm11
+	paddd	%xmm14,%xmm10
+	paddd	%xmm13,%xmm9
+	paddd	%xmm12,%xmm8
+	pxor	%xmm11,%xmm7
+	pxor	%xmm10,%xmm6
+	pxor	%xmm9,%xmm5
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm8,80(%rbp)
+	movdqa	%xmm7,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm7
+	pxor	%xmm8,%xmm7
+	movdqa	%xmm6,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm6
+	pxor	%xmm8,%xmm6
+	movdqa	%xmm5,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm5
+	pxor	%xmm8,%xmm5
+	movdqa	%xmm4,%xmm8
+	psrld	$25,%xmm8
+	pslld	$32-25,%xmm4
+	pxor	%xmm8,%xmm4
+	movdqa	80(%rbp),%xmm8
+.byte	102,15,58,15,255,12
+.byte	102,69,15,58,15,219,8
+.byte	102,69,15,58,15,255,4
+.byte	102,15,58,15,246,12
+.byte	102,69,15,58,15,210,8
+.byte	102,69,15,58,15,246,4
+.byte	102,15,58,15,237,12
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,4
+.byte	102,15,58,15,228,12
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,4
+
+	leaq	16(%rdi),%rdi
+	decq	%r8
+	jge	2b
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%rdi),%rdi
+	decq	%rcx
+	jg	2b
+	paddd	.chacha20_consts(%rip),%xmm3
+	paddd	48(%rbp),%xmm7
+	paddd	64(%rbp),%xmm11
+	paddd	144(%rbp),%xmm15
+	paddd	.chacha20_consts(%rip),%xmm2
+	paddd	48(%rbp),%xmm6
+	paddd	64(%rbp),%xmm10
+	paddd	128(%rbp),%xmm14
+	paddd	.chacha20_consts(%rip),%xmm1
+	paddd	48(%rbp),%xmm5
+	paddd	64(%rbp),%xmm9
+	paddd	112(%rbp),%xmm13
+	paddd	.chacha20_consts(%rip),%xmm0
+	paddd	48(%rbp),%xmm4
+	paddd	64(%rbp),%xmm8
+	paddd	96(%rbp),%xmm12
+
+	movdqa	%xmm14,80(%rbp)
+	movdqa	%xmm14,80(%rbp)
+	movdqu	0 + 0(%rsi),%xmm14
+	pxor	%xmm3,%xmm14
+	movdqu	%xmm14,0 + 0(%rdi)
+	movdqu	16 + 0(%rsi),%xmm14
+	pxor	%xmm7,%xmm14
+	movdqu	%xmm14,16 + 0(%rdi)
+	movdqu	32 + 0(%rsi),%xmm14
+	pxor	%xmm11,%xmm14
+	movdqu	%xmm14,32 + 0(%rdi)
+	movdqu	48 + 0(%rsi),%xmm14
+	pxor	%xmm15,%xmm14
+	movdqu	%xmm14,48 + 0(%rdi)
+
+	movdqa	80(%rbp),%xmm14
+	movdqu	0 + 64(%rsi),%xmm3
+	movdqu	16 + 64(%rsi),%xmm7
+	movdqu	32 + 64(%rsi),%xmm11
+	movdqu	48 + 64(%rsi),%xmm15
+	pxor	%xmm3,%xmm2
+	pxor	%xmm7,%xmm6
+	pxor	%xmm11,%xmm10
+	pxor	%xmm14,%xmm15
+	movdqu	%xmm2,0 + 64(%rdi)
+	movdqu	%xmm6,16 + 64(%rdi)
+	movdqu	%xmm10,32 + 64(%rdi)
+	movdqu	%xmm15,48 + 64(%rdi)
+	movdqu	0 + 128(%rsi),%xmm3
+	movdqu	16 + 128(%rsi),%xmm7
+	movdqu	32 + 128(%rsi),%xmm11
+	movdqu	48 + 128(%rsi),%xmm15
+	pxor	%xmm3,%xmm1
+	pxor	%xmm7,%xmm5
+	pxor	%xmm11,%xmm9
+	pxor	%xmm13,%xmm15
+	movdqu	%xmm1,0 + 128(%rdi)
+	movdqu	%xmm5,16 + 128(%rdi)
+	movdqu	%xmm9,32 + 128(%rdi)
+	movdqu	%xmm15,48 + 128(%rdi)
+
+	cmpq	$256,%rbx
+	ja	3f
+
+	movq	$192,%rcx
+	subq	$192,%rbx
+	leaq	192(%rsi),%rsi
+	jmp	seal_sse_128_seal_hash
+3:
+	movdqu	0 + 192(%rsi),%xmm3
+	movdqu	16 + 192(%rsi),%xmm7
+	movdqu	32 + 192(%rsi),%xmm11
+	movdqu	48 + 192(%rsi),%xmm15
+	pxor	%xmm3,%xmm0
+	pxor	%xmm7,%xmm4
+	pxor	%xmm11,%xmm8
+	pxor	%xmm12,%xmm15
+	movdqu	%xmm0,0 + 192(%rdi)
+	movdqu	%xmm4,16 + 192(%rdi)
+	movdqu	%xmm8,32 + 192(%rdi)
+	movdqu	%xmm15,48 + 192(%rdi)
+
+	leaq	256(%rsi),%rsi
+	subq	$256,%rbx
+	movq	$6,%rcx
+	movq	$4,%r8
+	cmpq	$192,%rbx
+	jg	1b
+	movq	%rbx,%rcx
+	testq	%rbx,%rbx
+	je	seal_sse_128_seal_hash
+	movq	$6,%rcx
+	cmpq	$64,%rbx
+	jg	3f
+
+seal_sse_tail_64:
+	movdqa	.chacha20_consts(%rip),%xmm0
+	movdqa	48(%rbp),%xmm4
+	movdqa	64(%rbp),%xmm8
+	movdqa	96(%rbp),%xmm12
+	paddd	.sse_inc(%rip),%xmm12
+	movdqa	%xmm12,96(%rbp)
+
+1:
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%rdi),%rdi
+2:
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,4
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,12
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,12
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,4
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%rdi),%rdi
+	decq	%rcx
+	jg	1b
+	decq	%r8
+	jge	2b
+	paddd	.chacha20_consts(%rip),%xmm0
+	paddd	48(%rbp),%xmm4
+	paddd	64(%rbp),%xmm8
+	paddd	96(%rbp),%xmm12
+
+	jmp	seal_sse_128_seal
+3:
+	cmpq	$128,%rbx
+	jg	3f
+
+seal_sse_tail_128:
+	movdqa	.chacha20_consts(%rip),%xmm0
+	movdqa	48(%rbp),%xmm4
+	movdqa	64(%rbp),%xmm8
+	movdqa	%xmm0,%xmm1
+	movdqa	%xmm4,%xmm5
+	movdqa	%xmm8,%xmm9
+	movdqa	96(%rbp),%xmm13
+	paddd	.sse_inc(%rip),%xmm13
+	movdqa	%xmm13,%xmm12
+	paddd	.sse_inc(%rip),%xmm12
+	movdqa	%xmm12,96(%rbp)
+	movdqa	%xmm13,112(%rbp)
+
+1:
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%rdi),%rdi
+2:
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,4
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,12
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol16(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm5
+	pxor	%xmm3,%xmm5
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol8(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm5
+	pxor	%xmm3,%xmm5
+.byte	102,15,58,15,237,4
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,12
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,12
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,4
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol16(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm5
+	pxor	%xmm3,%xmm5
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol8(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm5
+	pxor	%xmm3,%xmm5
+.byte	102,15,58,15,237,12
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,4
+
+	leaq	16(%rdi),%rdi
+	decq	%rcx
+	jg	1b
+	decq	%r8
+	jge	2b
+	paddd	.chacha20_consts(%rip),%xmm1
+	paddd	48(%rbp),%xmm5
+	paddd	64(%rbp),%xmm9
+	paddd	112(%rbp),%xmm13
+	paddd	.chacha20_consts(%rip),%xmm0
+	paddd	48(%rbp),%xmm4
+	paddd	64(%rbp),%xmm8
+	paddd	96(%rbp),%xmm12
+	movdqu	0 + 0(%rsi),%xmm3
+	movdqu	16 + 0(%rsi),%xmm7
+	movdqu	32 + 0(%rsi),%xmm11
+	movdqu	48 + 0(%rsi),%xmm15
+	pxor	%xmm3,%xmm1
+	pxor	%xmm7,%xmm5
+	pxor	%xmm11,%xmm9
+	pxor	%xmm13,%xmm15
+	movdqu	%xmm1,0 + 0(%rdi)
+	movdqu	%xmm5,16 + 0(%rdi)
+	movdqu	%xmm9,32 + 0(%rdi)
+	movdqu	%xmm15,48 + 0(%rdi)
+
+	movq	$64,%rcx
+	subq	$64,%rbx
+	leaq	64(%rsi),%rsi
+	jmp	seal_sse_128_seal_hash
+3:
+
+seal_sse_tail_192:
+	movdqa	.chacha20_consts(%rip),%xmm0
+	movdqa	48(%rbp),%xmm4
+	movdqa	64(%rbp),%xmm8
+	movdqa	%xmm0,%xmm1
+	movdqa	%xmm4,%xmm5
+	movdqa	%xmm8,%xmm9
+	movdqa	%xmm0,%xmm2
+	movdqa	%xmm4,%xmm6
+	movdqa	%xmm8,%xmm10
+	movdqa	96(%rbp),%xmm14
+	paddd	.sse_inc(%rip),%xmm14
+	movdqa	%xmm14,%xmm13
+	paddd	.sse_inc(%rip),%xmm13
+	movdqa	%xmm13,%xmm12
+	paddd	.sse_inc(%rip),%xmm12
+	movdqa	%xmm12,96(%rbp)
+	movdqa	%xmm13,112(%rbp)
+	movdqa	%xmm14,128(%rbp)
+
+1:
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%rdi),%rdi
+2:
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,4
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,12
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol16(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm5
+	pxor	%xmm3,%xmm5
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol8(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm5
+	pxor	%xmm3,%xmm5
+.byte	102,15,58,15,237,4
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,12
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol16(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm6
+	pxor	%xmm3,%xmm6
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol8(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm6
+	pxor	%xmm3,%xmm6
+.byte	102,15,58,15,246,4
+.byte	102,69,15,58,15,210,8
+.byte	102,69,15,58,15,246,12
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,12
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,4
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol16(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm5
+	pxor	%xmm3,%xmm5
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol8(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm5
+	pxor	%xmm3,%xmm5
+.byte	102,15,58,15,237,12
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,4
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol16(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm6
+	pxor	%xmm3,%xmm6
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol8(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm6
+	pxor	%xmm3,%xmm6
+.byte	102,15,58,15,246,12
+.byte	102,69,15,58,15,210,8
+.byte	102,69,15,58,15,246,4
+
+	leaq	16(%rdi),%rdi
+	decq	%rcx
+	jg	1b
+	decq	%r8
+	jge	2b
+	paddd	.chacha20_consts(%rip),%xmm2
+	paddd	48(%rbp),%xmm6
+	paddd	64(%rbp),%xmm10
+	paddd	128(%rbp),%xmm14
+	paddd	.chacha20_consts(%rip),%xmm1
+	paddd	48(%rbp),%xmm5
+	paddd	64(%rbp),%xmm9
+	paddd	112(%rbp),%xmm13
+	paddd	.chacha20_consts(%rip),%xmm0
+	paddd	48(%rbp),%xmm4
+	paddd	64(%rbp),%xmm8
+	paddd	96(%rbp),%xmm12
+	movdqu	0 + 0(%rsi),%xmm3
+	movdqu	16 + 0(%rsi),%xmm7
+	movdqu	32 + 0(%rsi),%xmm11
+	movdqu	48 + 0(%rsi),%xmm15
+	pxor	%xmm3,%xmm2
+	pxor	%xmm7,%xmm6
+	pxor	%xmm11,%xmm10
+	pxor	%xmm14,%xmm15
+	movdqu	%xmm2,0 + 0(%rdi)
+	movdqu	%xmm6,16 + 0(%rdi)
+	movdqu	%xmm10,32 + 0(%rdi)
+	movdqu	%xmm15,48 + 0(%rdi)
+	movdqu	0 + 64(%rsi),%xmm3
+	movdqu	16 + 64(%rsi),%xmm7
+	movdqu	32 + 64(%rsi),%xmm11
+	movdqu	48 + 64(%rsi),%xmm15
+	pxor	%xmm3,%xmm1
+	pxor	%xmm7,%xmm5
+	pxor	%xmm11,%xmm9
+	pxor	%xmm13,%xmm15
+	movdqu	%xmm1,0 + 64(%rdi)
+	movdqu	%xmm5,16 + 64(%rdi)
+	movdqu	%xmm9,32 + 64(%rdi)
+	movdqu	%xmm15,48 + 64(%rdi)
+
+	movq	$128,%rcx
+	subq	$128,%rbx
+	leaq	128(%rsi),%rsi
+
+seal_sse_128_seal_hash:
+	cmpq	$16,%rcx
+	jb	seal_sse_128_seal
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	subq	$16,%rcx
+	leaq	16(%rdi),%rdi
+	jmp	seal_sse_128_seal_hash
+
+seal_sse_128_seal:
+	cmpq	$16,%rbx
+	jb	seal_sse_tail_16
+	subq	$16,%rbx
+
+	movdqu	0(%rsi),%xmm3
+	pxor	%xmm3,%xmm0
+	movdqu	%xmm0,0(%rdi)
+
+	addq	0(%rdi),%r10
+	adcq	8(%rdi),%r11
+	adcq	$1,%r12
+	leaq	16(%rsi),%rsi
+	leaq	16(%rdi),%rdi
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+
+	movdqa	%xmm4,%xmm0
+	movdqa	%xmm8,%xmm4
+	movdqa	%xmm12,%xmm8
+	movdqa	%xmm1,%xmm12
+	movdqa	%xmm5,%xmm1
+	movdqa	%xmm9,%xmm5
+	movdqa	%xmm13,%xmm9
+	jmp	seal_sse_128_seal
+
+seal_sse_tail_16:
+	testq	%rbx,%rbx
+	jz	seal_sse_finalize
+
+	movq	%rbx,%r8
+	shlq	$4,%r8
+	leaq	.and_masks(%rip),%r13
+	movq	%rbx,%rcx
+	leaq	-1(%rsi,%rbx), %rsi
+	pxor	%xmm15,%xmm15
+1:
+	pslldq	$1,%xmm15
+	pinsrb	$0,(%rsi),%xmm15
+	leaq	-1(%rsi),%rsi
+	decq	%rcx
+	jne	1b
+
+
+	pxor	%xmm0,%xmm15
+
+
+	movq	%rbx,%rcx
+	movdqu	%xmm15,%xmm0
+2:
+	pextrb	$0,%xmm0,(%rdi)
+	psrldq	$1,%xmm0
+	addq	$1,%rdi
+	subq	$1,%rcx
+	jnz	2b
+
+	pand	-16(%r13,%r8), %xmm15
+.byte	102,77,15,126,253
+	pextrq	$1,%xmm15,%r14
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+seal_sse_finalize:
+	addq	32(%rbp),%r10
+	adcq	8+32(%rbp),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+
+	movq	%r10,%r13
+	movq	%r11,%r14
+	movq	%r12,%r15
+	subq	$-5,%r10
+	sbbq	$-1,%r11
+	sbbq	$3,%r12
+	cmovcq	%r13,%r10
+	cmovcq	%r14,%r11
+	cmovcq	%r15,%r12
+
+	addq	0+16(%rbp),%r10
+	adcq	8+16(%rbp),%r11
+
+	addq	$288 + 32,%rsp
+
+	popq	%r9
+
+	movq	%r10,0(%r9)
+	movq	%r11,8(%r9)
+
+	popq	%r15
+
+	popq	%r14
+
+	popq	%r13
+
+	popq	%r12
+
+	popq	%rbx
+
+	popq	%rbp
+
+	.byte	0xf3,0xc3
+
+
+seal_sse_128:
+	movdqu	.chacha20_consts(%rip),%xmm0
+	movdqa	%xmm0,%xmm1
+	movdqa	%xmm0,%xmm2
+	movdqu	0(%r9),%xmm4
+	movdqa	%xmm4,%xmm5
+	movdqa	%xmm4,%xmm6
+	movdqu	16(%r9),%xmm8
+	movdqa	%xmm8,%xmm9
+	movdqa	%xmm8,%xmm10
+	movdqu	32(%r9),%xmm14
+	movdqa	%xmm14,%xmm12
+	paddd	.sse_inc(%rip),%xmm12
+	movdqa	%xmm12,%xmm13
+	paddd	.sse_inc(%rip),%xmm13
+	movdqa	%xmm4,%xmm7
+	movdqa	%xmm8,%xmm11
+	movdqa	%xmm12,%xmm15
+	movq	$10,%r10
+1:
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,4
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,12
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol16(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm5
+	pxor	%xmm3,%xmm5
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol8(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm5
+	pxor	%xmm3,%xmm5
+.byte	102,15,58,15,237,4
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,12
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol16(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm6
+	pxor	%xmm3,%xmm6
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol8(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm6
+	pxor	%xmm3,%xmm6
+.byte	102,15,58,15,246,4
+.byte	102,69,15,58,15,210,8
+.byte	102,69,15,58,15,246,12
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol16(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm4
+	pxor	%xmm3,%xmm4
+	paddd	%xmm4,%xmm0
+	pxor	%xmm0,%xmm12
+	pshufb	.rol8(%rip),%xmm12
+	paddd	%xmm12,%xmm8
+	pxor	%xmm8,%xmm4
+	movdqa	%xmm4,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm4
+	pxor	%xmm3,%xmm4
+.byte	102,15,58,15,228,12
+.byte	102,69,15,58,15,192,8
+.byte	102,69,15,58,15,228,4
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol16(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm5
+	pxor	%xmm3,%xmm5
+	paddd	%xmm5,%xmm1
+	pxor	%xmm1,%xmm13
+	pshufb	.rol8(%rip),%xmm13
+	paddd	%xmm13,%xmm9
+	pxor	%xmm9,%xmm5
+	movdqa	%xmm5,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm5
+	pxor	%xmm3,%xmm5
+.byte	102,15,58,15,237,12
+.byte	102,69,15,58,15,201,8
+.byte	102,69,15,58,15,237,4
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol16(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm3
+	pslld	$12,%xmm3
+	psrld	$20,%xmm6
+	pxor	%xmm3,%xmm6
+	paddd	%xmm6,%xmm2
+	pxor	%xmm2,%xmm14
+	pshufb	.rol8(%rip),%xmm14
+	paddd	%xmm14,%xmm10
+	pxor	%xmm10,%xmm6
+	movdqa	%xmm6,%xmm3
+	pslld	$7,%xmm3
+	psrld	$25,%xmm6
+	pxor	%xmm3,%xmm6
+.byte	102,15,58,15,246,12
+.byte	102,69,15,58,15,210,8
+.byte	102,69,15,58,15,246,4
+
+	decq	%r10
+	jnz	1b
+	paddd	.chacha20_consts(%rip),%xmm0
+	paddd	.chacha20_consts(%rip),%xmm1
+	paddd	.chacha20_consts(%rip),%xmm2
+	paddd	%xmm7,%xmm4
+	paddd	%xmm7,%xmm5
+	paddd	%xmm7,%xmm6
+	paddd	%xmm11,%xmm8
+	paddd	%xmm11,%xmm9
+	paddd	%xmm15,%xmm12
+	paddd	.sse_inc(%rip),%xmm15
+	paddd	%xmm15,%xmm13
+
+	pand	.clamp(%rip),%xmm2
+	movdqa	%xmm2,0(%rbp)
+	movdqa	%xmm6,16(%rbp)
+
+	movq	%r8,%r8
+	call	poly_hash_ad_internal
+	jmp	seal_sse_128_seal
+
+
+
+
+.p2align	6
+chacha20_poly1305_open_avx2:
+	vzeroupper
+	vmovdqa	.chacha20_consts(%rip),%ymm0
+	vbroadcasti128	0(%r9),%ymm4
+	vbroadcasti128	16(%r9),%ymm8
+	vbroadcasti128	32(%r9),%ymm12
+	vpaddd	.avx2_init(%rip),%ymm12,%ymm12
+	cmpq	$192,%rbx
+	jbe	open_avx2_192
+	cmpq	$320,%rbx
+	jbe	open_avx2_320
+
+	vmovdqa	%ymm4,64(%rbp)
+	vmovdqa	%ymm8,96(%rbp)
+	vmovdqa	%ymm12,160(%rbp)
+	movq	$10,%r10
+1:
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+
+	decq	%r10
+	jne	1b
+	vpaddd	.chacha20_consts(%rip),%ymm0,%ymm0
+	vpaddd	64(%rbp),%ymm4,%ymm4
+	vpaddd	96(%rbp),%ymm8,%ymm8
+	vpaddd	160(%rbp),%ymm12,%ymm12
+
+	vperm2i128	$0x02,%ymm0,%ymm4,%ymm3
+
+	vpand	.clamp(%rip),%ymm3,%ymm3
+	vmovdqa	%ymm3,0(%rbp)
+
+	vperm2i128	$0x13,%ymm0,%ymm4,%ymm0
+	vperm2i128	$0x13,%ymm8,%ymm12,%ymm4
+
+	movq	%r8,%r8
+	call	poly_hash_ad_internal
+	xorq	%rcx,%rcx
+
+1:
+	addq	0(%rsi,%rcx), %r10
+	adcq	8+0(%rsi,%rcx), %r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	addq	$16,%rcx
+	cmpq	$64,%rcx
+	jne	1b
+
+	vpxor	0(%rsi),%ymm0,%ymm0
+	vpxor	32(%rsi),%ymm4,%ymm4
+	vmovdqu	%ymm0,0(%rdi)
+	vmovdqu	%ymm4,32(%rdi)
+	leaq	64(%rsi),%rsi
+	leaq	64(%rdi),%rdi
+	subq	$64,%rbx
+1:
+
+	cmpq	$512,%rbx
+	jb	3f
+	vmovdqa	.chacha20_consts(%rip),%ymm0
+	vmovdqa	64(%rbp),%ymm4
+	vmovdqa	96(%rbp),%ymm8
+	vmovdqa	%ymm0,%ymm1
+	vmovdqa	%ymm4,%ymm5
+	vmovdqa	%ymm8,%ymm9
+	vmovdqa	%ymm0,%ymm2
+	vmovdqa	%ymm4,%ymm6
+	vmovdqa	%ymm8,%ymm10
+	vmovdqa	%ymm0,%ymm3
+	vmovdqa	%ymm4,%ymm7
+	vmovdqa	%ymm8,%ymm11
+	vmovdqa	.avx2_inc(%rip),%ymm12
+	vpaddd	160(%rbp),%ymm12,%ymm15
+	vpaddd	%ymm15,%ymm12,%ymm14
+	vpaddd	%ymm14,%ymm12,%ymm13
+	vpaddd	%ymm13,%ymm12,%ymm12
+	vmovdqa	%ymm15,256(%rbp)
+	vmovdqa	%ymm14,224(%rbp)
+	vmovdqa	%ymm13,192(%rbp)
+	vmovdqa	%ymm12,160(%rbp)
+
+	xorq	%rcx,%rcx
+2:
+	addq	0*8(%rsi,%rcx), %r10
+	adcq	8+0*8(%rsi,%rcx), %r11
+	adcq	$1,%r12
+	vmovdqa	%ymm8,128(%rbp)
+	vmovdqa	.rol16(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	movq	0+0(%rbp),%rdx
+	movq	%rdx,%r15
+	mulxq	%r10,%r13,%r14
+	mulxq	%r11,%rax,%rdx
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	movq	8+0(%rbp),%rdx
+	mulxq	%r10,%r10,%rax
+	addq	%r10,%r14
+	mulxq	%r11,%r11,%r9
+	adcq	%r11,%r15
+	adcq	$0,%r9
+	imulq	%r12,%rdx
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$20,%ymm7,%ymm8
+	vpslld	$32-20,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$20,%ymm6,%ymm8
+	vpslld	$32-20,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$20,%ymm5,%ymm8
+	addq	%rax,%r15
+	adcq	%rdx,%r9
+	vpslld	$32-20,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$20,%ymm4,%ymm8
+	vpslld	$32-20,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	.rol8(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	addq	2*8(%rsi,%rcx), %r10
+	adcq	8+2*8(%rsi,%rcx), %r11
+	adcq	$1,%r12
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	movq	0+0(%rbp),%rdx
+	movq	%rdx,%r15
+	mulxq	%r10,%r13,%r14
+	mulxq	%r11,%rax,%rdx
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$25,%ymm7,%ymm8
+	vpslld	$32-25,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$25,%ymm6,%ymm8
+	vpslld	$32-25,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$25,%ymm5,%ymm8
+	vpslld	$32-25,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$25,%ymm4,%ymm8
+	vpslld	$32-25,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	128(%rbp),%ymm8
+	vpalignr	$4,%ymm7,%ymm7,%ymm7
+	vpalignr	$8,%ymm11,%ymm11,%ymm11
+	vpalignr	$12,%ymm15,%ymm15,%ymm15
+	vpalignr	$4,%ymm6,%ymm6,%ymm6
+	movq	8+0(%rbp),%rdx
+	mulxq	%r10,%r10,%rax
+	addq	%r10,%r14
+	mulxq	%r11,%r11,%r9
+	adcq	%r11,%r15
+	adcq	$0,%r9
+	imulq	%r12,%rdx
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$12,%ymm14,%ymm14,%ymm14
+	vpalignr	$4,%ymm5,%ymm5,%ymm5
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$12,%ymm13,%ymm13,%ymm13
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vmovdqa	%ymm8,128(%rbp)
+	vmovdqa	.rol16(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	addq	%rax,%r15
+	adcq	%rdx,%r9
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$20,%ymm7,%ymm8
+	vpslld	$32-20,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	addq	4*8(%rsi,%rcx), %r10
+	adcq	8+4*8(%rsi,%rcx), %r11
+	adcq	$1,%r12
+
+	leaq	48(%rcx),%rcx
+	vpsrld	$20,%ymm6,%ymm8
+	vpslld	$32-20,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$20,%ymm5,%ymm8
+	vpslld	$32-20,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$20,%ymm4,%ymm8
+	vpslld	$32-20,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	.rol8(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	movq	0+0(%rbp),%rdx
+	movq	%rdx,%r15
+	mulxq	%r10,%r13,%r14
+	mulxq	%r11,%rax,%rdx
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	movq	8+0(%rbp),%rdx
+	mulxq	%r10,%r10,%rax
+	addq	%r10,%r14
+	mulxq	%r11,%r11,%r9
+	adcq	%r11,%r15
+	adcq	$0,%r9
+	imulq	%r12,%rdx
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$25,%ymm7,%ymm8
+	vpslld	$32-25,%ymm7,%ymm7
+	addq	%rax,%r15
+	adcq	%rdx,%r9
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$25,%ymm6,%ymm8
+	vpslld	$32-25,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$25,%ymm5,%ymm8
+	vpslld	$32-25,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$25,%ymm4,%ymm8
+	vpslld	$32-25,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	128(%rbp),%ymm8
+	vpalignr	$12,%ymm7,%ymm7,%ymm7
+	vpalignr	$8,%ymm11,%ymm11,%ymm11
+	vpalignr	$4,%ymm15,%ymm15,%ymm15
+	vpalignr	$12,%ymm6,%ymm6,%ymm6
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$4,%ymm14,%ymm14,%ymm14
+	vpalignr	$12,%ymm5,%ymm5,%ymm5
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$4,%ymm13,%ymm13,%ymm13
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+
+	cmpq	$60*8,%rcx
+	jne	2b
+	vpaddd	.chacha20_consts(%rip),%ymm3,%ymm3
+	vpaddd	64(%rbp),%ymm7,%ymm7
+	vpaddd	96(%rbp),%ymm11,%ymm11
+	vpaddd	256(%rbp),%ymm15,%ymm15
+	vpaddd	.chacha20_consts(%rip),%ymm2,%ymm2
+	vpaddd	64(%rbp),%ymm6,%ymm6
+	vpaddd	96(%rbp),%ymm10,%ymm10
+	vpaddd	224(%rbp),%ymm14,%ymm14
+	vpaddd	.chacha20_consts(%rip),%ymm1,%ymm1
+	vpaddd	64(%rbp),%ymm5,%ymm5
+	vpaddd	96(%rbp),%ymm9,%ymm9
+	vpaddd	192(%rbp),%ymm13,%ymm13
+	vpaddd	.chacha20_consts(%rip),%ymm0,%ymm0
+	vpaddd	64(%rbp),%ymm4,%ymm4
+	vpaddd	96(%rbp),%ymm8,%ymm8
+	vpaddd	160(%rbp),%ymm12,%ymm12
+
+	vmovdqa	%ymm0,128(%rbp)
+	addq	60*8(%rsi),%r10
+	adcq	8+60*8(%rsi),%r11
+	adcq	$1,%r12
+	vperm2i128	$0x02,%ymm3,%ymm7,%ymm0
+	vperm2i128	$0x13,%ymm3,%ymm7,%ymm7
+	vperm2i128	$0x02,%ymm11,%ymm15,%ymm3
+	vperm2i128	$0x13,%ymm11,%ymm15,%ymm11
+	vpxor	0+0(%rsi),%ymm0,%ymm0
+	vpxor	32+0(%rsi),%ymm3,%ymm3
+	vpxor	64+0(%rsi),%ymm7,%ymm7
+	vpxor	96+0(%rsi),%ymm11,%ymm11
+	vmovdqu	%ymm0,0+0(%rdi)
+	vmovdqu	%ymm3,32+0(%rdi)
+	vmovdqu	%ymm7,64+0(%rdi)
+	vmovdqu	%ymm11,96+0(%rdi)
+
+	vmovdqa	128(%rbp),%ymm0
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	vperm2i128	$0x02,%ymm2,%ymm6,%ymm3
+	vperm2i128	$0x13,%ymm2,%ymm6,%ymm6
+	vperm2i128	$0x02,%ymm10,%ymm14,%ymm2
+	vperm2i128	$0x13,%ymm10,%ymm14,%ymm10
+	vpxor	0+128(%rsi),%ymm3,%ymm3
+	vpxor	32+128(%rsi),%ymm2,%ymm2
+	vpxor	64+128(%rsi),%ymm6,%ymm6
+	vpxor	96+128(%rsi),%ymm10,%ymm10
+	vmovdqu	%ymm3,0+128(%rdi)
+	vmovdqu	%ymm2,32+128(%rdi)
+	vmovdqu	%ymm6,64+128(%rdi)
+	vmovdqu	%ymm10,96+128(%rdi)
+	addq	60*8+16(%rsi),%r10
+	adcq	8+60*8+16(%rsi),%r11
+	adcq	$1,%r12
+	vperm2i128	$0x02,%ymm1,%ymm5,%ymm3
+	vperm2i128	$0x13,%ymm1,%ymm5,%ymm5
+	vperm2i128	$0x02,%ymm9,%ymm13,%ymm1
+	vperm2i128	$0x13,%ymm9,%ymm13,%ymm9
+	vpxor	0+256(%rsi),%ymm3,%ymm3
+	vpxor	32+256(%rsi),%ymm1,%ymm1
+	vpxor	64+256(%rsi),%ymm5,%ymm5
+	vpxor	96+256(%rsi),%ymm9,%ymm9
+	vmovdqu	%ymm3,0+256(%rdi)
+	vmovdqu	%ymm1,32+256(%rdi)
+	vmovdqu	%ymm5,64+256(%rdi)
+	vmovdqu	%ymm9,96+256(%rdi)
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	vperm2i128	$0x02,%ymm0,%ymm4,%ymm3
+	vperm2i128	$0x13,%ymm0,%ymm4,%ymm4
+	vperm2i128	$0x02,%ymm8,%ymm12,%ymm0
+	vperm2i128	$0x13,%ymm8,%ymm12,%ymm8
+	vpxor	0+384(%rsi),%ymm3,%ymm3
+	vpxor	32+384(%rsi),%ymm0,%ymm0
+	vpxor	64+384(%rsi),%ymm4,%ymm4
+	vpxor	96+384(%rsi),%ymm8,%ymm8
+	vmovdqu	%ymm3,0+384(%rdi)
+	vmovdqu	%ymm0,32+384(%rdi)
+	vmovdqu	%ymm4,64+384(%rdi)
+	vmovdqu	%ymm8,96+384(%rdi)
+
+	leaq	512(%rsi),%rsi
+	leaq	512(%rdi),%rdi
+	subq	$512,%rbx
+	jmp	1b
+3:
+	testq	%rbx,%rbx
+	vzeroupper
+	je	open_sse_finalize
+3:
+	cmpq	$128,%rbx
+	ja	3f
+	vmovdqa	.chacha20_consts(%rip),%ymm0
+	vmovdqa	64(%rbp),%ymm4
+	vmovdqa	96(%rbp),%ymm8
+	vmovdqa	.avx2_inc(%rip),%ymm12
+	vpaddd	160(%rbp),%ymm12,%ymm12
+	vmovdqa	%ymm12,160(%rbp)
+
+	xorq	%r8,%r8
+	movq	%rbx,%rcx
+	andq	$-16,%rcx
+	testq	%rcx,%rcx
+	je	2f
+1:
+	addq	0*8(%rsi,%r8), %r10
+	adcq	8+0*8(%rsi,%r8), %r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+2:
+	addq	$16,%r8
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+
+	cmpq	%rcx,%r8
+	jb	1b
+	cmpq	$160,%r8
+	jne	2b
+	vpaddd	.chacha20_consts(%rip),%ymm0,%ymm0
+	vpaddd	64(%rbp),%ymm4,%ymm4
+	vpaddd	96(%rbp),%ymm8,%ymm8
+	vpaddd	160(%rbp),%ymm12,%ymm12
+	vperm2i128	$0x13,%ymm0,%ymm4,%ymm3
+	vperm2i128	$0x02,%ymm0,%ymm4,%ymm0
+	vperm2i128	$0x02,%ymm8,%ymm12,%ymm4
+	vperm2i128	$0x13,%ymm8,%ymm12,%ymm12
+	vmovdqa	%ymm3,%ymm8
+
+	jmp	open_avx2_tail_loop
+3:
+	cmpq	$256,%rbx
+	ja	3f
+	vmovdqa	.chacha20_consts(%rip),%ymm0
+	vmovdqa	64(%rbp),%ymm4
+	vmovdqa	96(%rbp),%ymm8
+	vmovdqa	%ymm0,%ymm1
+	vmovdqa	%ymm4,%ymm5
+	vmovdqa	%ymm8,%ymm9
+	vmovdqa	.avx2_inc(%rip),%ymm12
+	vpaddd	160(%rbp),%ymm12,%ymm13
+	vpaddd	%ymm13,%ymm12,%ymm12
+	vmovdqa	%ymm12,160(%rbp)
+	vmovdqa	%ymm13,192(%rbp)
+
+	movq	%rbx,128(%rbp)
+	movq	%rbx,%rcx
+	subq	$128,%rcx
+	shrq	$4,%rcx
+	movq	$10,%r8
+	cmpq	$10,%rcx
+	cmovgq	%r8,%rcx
+	movq	%rsi,%rbx
+	xorq	%r8,%r8
+1:
+	addq	0(%rbx),%r10
+	adcq	8+0(%rbx),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rdx
+	movq	%rdx,%r15
+	mulxq	%r10,%r13,%r14
+	mulxq	%r11,%rax,%rdx
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rdx
+	mulxq	%r10,%r10,%rax
+	addq	%r10,%r14
+	mulxq	%r11,%r11,%r9
+	adcq	%r11,%r15
+	adcq	$0,%r9
+	imulq	%r12,%rdx
+	addq	%rax,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%rbx),%rbx
+2:
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol16(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpsrld	$20,%ymm5,%ymm3
+	vpslld	$12,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol8(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpslld	$7,%ymm5,%ymm3
+	vpsrld	$25,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpalignr	$12,%ymm13,%ymm13,%ymm13
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$4,%ymm5,%ymm5,%ymm5
+
+	incq	%r8
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol16(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpsrld	$20,%ymm5,%ymm3
+	vpslld	$12,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol8(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpslld	$7,%ymm5,%ymm3
+	vpsrld	$25,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpalignr	$4,%ymm13,%ymm13,%ymm13
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$12,%ymm5,%ymm5,%ymm5
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol16(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpsrld	$20,%ymm6,%ymm3
+	vpslld	$12,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol8(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpslld	$7,%ymm6,%ymm3
+	vpsrld	$25,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpalignr	$4,%ymm14,%ymm14,%ymm14
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$12,%ymm6,%ymm6,%ymm6
+
+	cmpq	%rcx,%r8
+	jb	1b
+	cmpq	$10,%r8
+	jne	2b
+	movq	%rbx,%r8
+	subq	%rsi,%rbx
+	movq	%rbx,%rcx
+	movq	128(%rbp),%rbx
+1:
+	addq	$16,%rcx
+	cmpq	%rbx,%rcx
+	jg	1f
+	addq	0(%r8),%r10
+	adcq	8+0(%r8),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rdx
+	movq	%rdx,%r15
+	mulxq	%r10,%r13,%r14
+	mulxq	%r11,%rax,%rdx
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rdx
+	mulxq	%r10,%r10,%rax
+	addq	%r10,%r14
+	mulxq	%r11,%r11,%r9
+	adcq	%r11,%r15
+	adcq	$0,%r9
+	imulq	%r12,%rdx
+	addq	%rax,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%r8),%r8
+	jmp	1b
+1:
+	vpaddd	.chacha20_consts(%rip),%ymm1,%ymm1
+	vpaddd	64(%rbp),%ymm5,%ymm5
+	vpaddd	96(%rbp),%ymm9,%ymm9
+	vpaddd	192(%rbp),%ymm13,%ymm13
+	vpaddd	.chacha20_consts(%rip),%ymm0,%ymm0
+	vpaddd	64(%rbp),%ymm4,%ymm4
+	vpaddd	96(%rbp),%ymm8,%ymm8
+	vpaddd	160(%rbp),%ymm12,%ymm12
+	vperm2i128	$0x02,%ymm1,%ymm5,%ymm3
+	vperm2i128	$0x13,%ymm1,%ymm5,%ymm5
+	vperm2i128	$0x02,%ymm9,%ymm13,%ymm1
+	vperm2i128	$0x13,%ymm9,%ymm13,%ymm9
+	vpxor	0+0(%rsi),%ymm3,%ymm3
+	vpxor	32+0(%rsi),%ymm1,%ymm1
+	vpxor	64+0(%rsi),%ymm5,%ymm5
+	vpxor	96+0(%rsi),%ymm9,%ymm9
+	vmovdqu	%ymm3,0+0(%rdi)
+	vmovdqu	%ymm1,32+0(%rdi)
+	vmovdqu	%ymm5,64+0(%rdi)
+	vmovdqu	%ymm9,96+0(%rdi)
+	vperm2i128	$0x13,%ymm0,%ymm4,%ymm3
+	vperm2i128	$0x02,%ymm0,%ymm4,%ymm0
+	vperm2i128	$0x02,%ymm8,%ymm12,%ymm4
+	vperm2i128	$0x13,%ymm8,%ymm12,%ymm12
+	vmovdqa	%ymm3,%ymm8
+
+	leaq	128(%rsi),%rsi
+	leaq	128(%rdi),%rdi
+	subq	$128,%rbx
+	jmp	open_avx2_tail_loop
+3:
+	cmpq	$384,%rbx
+	ja	3f
+	vmovdqa	.chacha20_consts(%rip),%ymm0
+	vmovdqa	64(%rbp),%ymm4
+	vmovdqa	96(%rbp),%ymm8
+	vmovdqa	%ymm0,%ymm1
+	vmovdqa	%ymm4,%ymm5
+	vmovdqa	%ymm8,%ymm9
+	vmovdqa	%ymm0,%ymm2
+	vmovdqa	%ymm4,%ymm6
+	vmovdqa	%ymm8,%ymm10
+	vmovdqa	.avx2_inc(%rip),%ymm12
+	vpaddd	160(%rbp),%ymm12,%ymm14
+	vpaddd	%ymm14,%ymm12,%ymm13
+	vpaddd	%ymm13,%ymm12,%ymm12
+	vmovdqa	%ymm12,160(%rbp)
+	vmovdqa	%ymm13,192(%rbp)
+	vmovdqa	%ymm14,224(%rbp)
+
+	movq	%rbx,128(%rbp)
+	movq	%rbx,%rcx
+	subq	$256,%rcx
+	shrq	$4,%rcx
+	addq	$6,%rcx
+	movq	$10,%r8
+	cmpq	$10,%rcx
+	cmovgq	%r8,%rcx
+	movq	%rsi,%rbx
+	xorq	%r8,%r8
+1:
+	addq	0(%rbx),%r10
+	adcq	8+0(%rbx),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rdx
+	movq	%rdx,%r15
+	mulxq	%r10,%r13,%r14
+	mulxq	%r11,%rax,%rdx
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rdx
+	mulxq	%r10,%r10,%rax
+	addq	%r10,%r14
+	mulxq	%r11,%r11,%r9
+	adcq	%r11,%r15
+	adcq	$0,%r9
+	imulq	%r12,%rdx
+	addq	%rax,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%rbx),%rbx
+2:
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol16(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpsrld	$20,%ymm6,%ymm3
+	vpslld	$12,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol8(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpslld	$7,%ymm6,%ymm3
+	vpsrld	$25,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpalignr	$12,%ymm14,%ymm14,%ymm14
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$4,%ymm6,%ymm6,%ymm6
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol16(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpsrld	$20,%ymm5,%ymm3
+	vpslld	$12,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol8(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpslld	$7,%ymm5,%ymm3
+	vpsrld	$25,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpalignr	$12,%ymm13,%ymm13,%ymm13
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$4,%ymm5,%ymm5,%ymm5
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	addq	0(%rbx),%r10
+	adcq	8+0(%rbx),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%rbx),%rbx
+	incq	%r8
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol16(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpsrld	$20,%ymm6,%ymm3
+	vpslld	$12,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol8(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpslld	$7,%ymm6,%ymm3
+	vpsrld	$25,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpalignr	$4,%ymm14,%ymm14,%ymm14
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$12,%ymm6,%ymm6,%ymm6
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol16(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpsrld	$20,%ymm5,%ymm3
+	vpslld	$12,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol8(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpslld	$7,%ymm5,%ymm3
+	vpsrld	$25,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpalignr	$4,%ymm13,%ymm13,%ymm13
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$12,%ymm5,%ymm5,%ymm5
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+
+	cmpq	%rcx,%r8
+	jb	1b
+	cmpq	$10,%r8
+	jne	2b
+	movq	%rbx,%r8
+	subq	%rsi,%rbx
+	movq	%rbx,%rcx
+	movq	128(%rbp),%rbx
+1:
+	addq	$16,%rcx
+	cmpq	%rbx,%rcx
+	jg	1f
+	addq	0(%r8),%r10
+	adcq	8+0(%r8),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rdx
+	movq	%rdx,%r15
+	mulxq	%r10,%r13,%r14
+	mulxq	%r11,%rax,%rdx
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rdx
+	mulxq	%r10,%r10,%rax
+	addq	%r10,%r14
+	mulxq	%r11,%r11,%r9
+	adcq	%r11,%r15
+	adcq	$0,%r9
+	imulq	%r12,%rdx
+	addq	%rax,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%r8),%r8
+	jmp	1b
+1:
+	vpaddd	.chacha20_consts(%rip),%ymm2,%ymm2
+	vpaddd	64(%rbp),%ymm6,%ymm6
+	vpaddd	96(%rbp),%ymm10,%ymm10
+	vpaddd	224(%rbp),%ymm14,%ymm14
+	vpaddd	.chacha20_consts(%rip),%ymm1,%ymm1
+	vpaddd	64(%rbp),%ymm5,%ymm5
+	vpaddd	96(%rbp),%ymm9,%ymm9
+	vpaddd	192(%rbp),%ymm13,%ymm13
+	vpaddd	.chacha20_consts(%rip),%ymm0,%ymm0
+	vpaddd	64(%rbp),%ymm4,%ymm4
+	vpaddd	96(%rbp),%ymm8,%ymm8
+	vpaddd	160(%rbp),%ymm12,%ymm12
+	vperm2i128	$0x02,%ymm2,%ymm6,%ymm3
+	vperm2i128	$0x13,%ymm2,%ymm6,%ymm6
+	vperm2i128	$0x02,%ymm10,%ymm14,%ymm2
+	vperm2i128	$0x13,%ymm10,%ymm14,%ymm10
+	vpxor	0+0(%rsi),%ymm3,%ymm3
+	vpxor	32+0(%rsi),%ymm2,%ymm2
+	vpxor	64+0(%rsi),%ymm6,%ymm6
+	vpxor	96+0(%rsi),%ymm10,%ymm10
+	vmovdqu	%ymm3,0+0(%rdi)
+	vmovdqu	%ymm2,32+0(%rdi)
+	vmovdqu	%ymm6,64+0(%rdi)
+	vmovdqu	%ymm10,96+0(%rdi)
+	vperm2i128	$0x02,%ymm1,%ymm5,%ymm3
+	vperm2i128	$0x13,%ymm1,%ymm5,%ymm5
+	vperm2i128	$0x02,%ymm9,%ymm13,%ymm1
+	vperm2i128	$0x13,%ymm9,%ymm13,%ymm9
+	vpxor	0+128(%rsi),%ymm3,%ymm3
+	vpxor	32+128(%rsi),%ymm1,%ymm1
+	vpxor	64+128(%rsi),%ymm5,%ymm5
+	vpxor	96+128(%rsi),%ymm9,%ymm9
+	vmovdqu	%ymm3,0+128(%rdi)
+	vmovdqu	%ymm1,32+128(%rdi)
+	vmovdqu	%ymm5,64+128(%rdi)
+	vmovdqu	%ymm9,96+128(%rdi)
+	vperm2i128	$0x13,%ymm0,%ymm4,%ymm3
+	vperm2i128	$0x02,%ymm0,%ymm4,%ymm0
+	vperm2i128	$0x02,%ymm8,%ymm12,%ymm4
+	vperm2i128	$0x13,%ymm8,%ymm12,%ymm12
+	vmovdqa	%ymm3,%ymm8
+
+	leaq	256(%rsi),%rsi
+	leaq	256(%rdi),%rdi
+	subq	$256,%rbx
+	jmp	open_avx2_tail_loop
+3:
+	vmovdqa	.chacha20_consts(%rip),%ymm0
+	vmovdqa	64(%rbp),%ymm4
+	vmovdqa	96(%rbp),%ymm8
+	vmovdqa	%ymm0,%ymm1
+	vmovdqa	%ymm4,%ymm5
+	vmovdqa	%ymm8,%ymm9
+	vmovdqa	%ymm0,%ymm2
+	vmovdqa	%ymm4,%ymm6
+	vmovdqa	%ymm8,%ymm10
+	vmovdqa	%ymm0,%ymm3
+	vmovdqa	%ymm4,%ymm7
+	vmovdqa	%ymm8,%ymm11
+	vmovdqa	.avx2_inc(%rip),%ymm12
+	vpaddd	160(%rbp),%ymm12,%ymm15
+	vpaddd	%ymm15,%ymm12,%ymm14
+	vpaddd	%ymm14,%ymm12,%ymm13
+	vpaddd	%ymm13,%ymm12,%ymm12
+	vmovdqa	%ymm15,256(%rbp)
+	vmovdqa	%ymm14,224(%rbp)
+	vmovdqa	%ymm13,192(%rbp)
+	vmovdqa	%ymm12,160(%rbp)
+
+	xorq	%rcx,%rcx
+	movq	%rsi,%r8
+1:
+	addq	0(%r8),%r10
+	adcq	8+0(%r8),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%r8),%r8
+2:
+	vmovdqa	%ymm8,128(%rbp)
+	vmovdqa	.rol16(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$20,%ymm7,%ymm8
+	vpslld	$32-20,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$20,%ymm6,%ymm8
+	vpslld	$32-20,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$20,%ymm5,%ymm8
+	vpslld	$32-20,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$20,%ymm4,%ymm8
+	vpslld	$32-20,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	.rol8(%rip),%ymm8
+	addq	0(%r8),%r10
+	adcq	8+0(%r8),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rdx
+	movq	%rdx,%r15
+	mulxq	%r10,%r13,%r14
+	mulxq	%r11,%rax,%rdx
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rdx
+	mulxq	%r10,%r10,%rax
+	addq	%r10,%r14
+	mulxq	%r11,%r11,%r9
+	adcq	%r11,%r15
+	adcq	$0,%r9
+	imulq	%r12,%rdx
+	addq	%rax,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$25,%ymm7,%ymm8
+	vpslld	$32-25,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$25,%ymm6,%ymm8
+	vpslld	$32-25,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$25,%ymm5,%ymm8
+	vpslld	$32-25,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$25,%ymm4,%ymm8
+	vpslld	$32-25,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	128(%rbp),%ymm8
+	vpalignr	$4,%ymm7,%ymm7,%ymm7
+	vpalignr	$8,%ymm11,%ymm11,%ymm11
+	vpalignr	$12,%ymm15,%ymm15,%ymm15
+	vpalignr	$4,%ymm6,%ymm6,%ymm6
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$12,%ymm14,%ymm14,%ymm14
+	vpalignr	$4,%ymm5,%ymm5,%ymm5
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$12,%ymm13,%ymm13,%ymm13
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vmovdqa	%ymm8,128(%rbp)
+	addq	16(%r8),%r10
+	adcq	8+16(%r8),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rdx
+	movq	%rdx,%r15
+	mulxq	%r10,%r13,%r14
+	mulxq	%r11,%rax,%rdx
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rdx
+	mulxq	%r10,%r10,%rax
+	addq	%r10,%r14
+	mulxq	%r11,%r11,%r9
+	adcq	%r11,%r15
+	adcq	$0,%r9
+	imulq	%r12,%rdx
+	addq	%rax,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	32(%r8),%r8
+	vmovdqa	.rol16(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$20,%ymm7,%ymm8
+	vpslld	$32-20,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$20,%ymm6,%ymm8
+	vpslld	$32-20,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$20,%ymm5,%ymm8
+	vpslld	$32-20,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$20,%ymm4,%ymm8
+	vpslld	$32-20,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	.rol8(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$25,%ymm7,%ymm8
+	vpslld	$32-25,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$25,%ymm6,%ymm8
+	vpslld	$32-25,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$25,%ymm5,%ymm8
+	vpslld	$32-25,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$25,%ymm4,%ymm8
+	vpslld	$32-25,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	128(%rbp),%ymm8
+	vpalignr	$12,%ymm7,%ymm7,%ymm7
+	vpalignr	$8,%ymm11,%ymm11,%ymm11
+	vpalignr	$4,%ymm15,%ymm15,%ymm15
+	vpalignr	$12,%ymm6,%ymm6,%ymm6
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$4,%ymm14,%ymm14,%ymm14
+	vpalignr	$12,%ymm5,%ymm5,%ymm5
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$4,%ymm13,%ymm13,%ymm13
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+
+	incq	%rcx
+	cmpq	$4,%rcx
+	jl	1b
+	cmpq	$10,%rcx
+	jne	2b
+	movq	%rbx,%rcx
+	subq	$384,%rcx
+	andq	$-16,%rcx
+1:
+	testq	%rcx,%rcx
+	je	1f
+	addq	0(%r8),%r10
+	adcq	8+0(%r8),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rdx
+	movq	%rdx,%r15
+	mulxq	%r10,%r13,%r14
+	mulxq	%r11,%rax,%rdx
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rdx
+	mulxq	%r10,%r10,%rax
+	addq	%r10,%r14
+	mulxq	%r11,%r11,%r9
+	adcq	%r11,%r15
+	adcq	$0,%r9
+	imulq	%r12,%rdx
+	addq	%rax,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%r8),%r8
+	subq	$16,%rcx
+	jmp	1b
+1:
+	vpaddd	.chacha20_consts(%rip),%ymm3,%ymm3
+	vpaddd	64(%rbp),%ymm7,%ymm7
+	vpaddd	96(%rbp),%ymm11,%ymm11
+	vpaddd	256(%rbp),%ymm15,%ymm15
+	vpaddd	.chacha20_consts(%rip),%ymm2,%ymm2
+	vpaddd	64(%rbp),%ymm6,%ymm6
+	vpaddd	96(%rbp),%ymm10,%ymm10
+	vpaddd	224(%rbp),%ymm14,%ymm14
+	vpaddd	.chacha20_consts(%rip),%ymm1,%ymm1
+	vpaddd	64(%rbp),%ymm5,%ymm5
+	vpaddd	96(%rbp),%ymm9,%ymm9
+	vpaddd	192(%rbp),%ymm13,%ymm13
+	vpaddd	.chacha20_consts(%rip),%ymm0,%ymm0
+	vpaddd	64(%rbp),%ymm4,%ymm4
+	vpaddd	96(%rbp),%ymm8,%ymm8
+	vpaddd	160(%rbp),%ymm12,%ymm12
+
+	vmovdqa	%ymm0,128(%rbp)
+	vperm2i128	$0x02,%ymm3,%ymm7,%ymm0
+	vperm2i128	$0x13,%ymm3,%ymm7,%ymm7
+	vperm2i128	$0x02,%ymm11,%ymm15,%ymm3
+	vperm2i128	$0x13,%ymm11,%ymm15,%ymm11
+	vpxor	0+0(%rsi),%ymm0,%ymm0
+	vpxor	32+0(%rsi),%ymm3,%ymm3
+	vpxor	64+0(%rsi),%ymm7,%ymm7
+	vpxor	96+0(%rsi),%ymm11,%ymm11
+	vmovdqu	%ymm0,0+0(%rdi)
+	vmovdqu	%ymm3,32+0(%rdi)
+	vmovdqu	%ymm7,64+0(%rdi)
+	vmovdqu	%ymm11,96+0(%rdi)
+
+	vmovdqa	128(%rbp),%ymm0
+	vperm2i128	$0x02,%ymm2,%ymm6,%ymm3
+	vperm2i128	$0x13,%ymm2,%ymm6,%ymm6
+	vperm2i128	$0x02,%ymm10,%ymm14,%ymm2
+	vperm2i128	$0x13,%ymm10,%ymm14,%ymm10
+	vpxor	0+128(%rsi),%ymm3,%ymm3
+	vpxor	32+128(%rsi),%ymm2,%ymm2
+	vpxor	64+128(%rsi),%ymm6,%ymm6
+	vpxor	96+128(%rsi),%ymm10,%ymm10
+	vmovdqu	%ymm3,0+128(%rdi)
+	vmovdqu	%ymm2,32+128(%rdi)
+	vmovdqu	%ymm6,64+128(%rdi)
+	vmovdqu	%ymm10,96+128(%rdi)
+	vperm2i128	$0x02,%ymm1,%ymm5,%ymm3
+	vperm2i128	$0x13,%ymm1,%ymm5,%ymm5
+	vperm2i128	$0x02,%ymm9,%ymm13,%ymm1
+	vperm2i128	$0x13,%ymm9,%ymm13,%ymm9
+	vpxor	0+256(%rsi),%ymm3,%ymm3
+	vpxor	32+256(%rsi),%ymm1,%ymm1
+	vpxor	64+256(%rsi),%ymm5,%ymm5
+	vpxor	96+256(%rsi),%ymm9,%ymm9
+	vmovdqu	%ymm3,0+256(%rdi)
+	vmovdqu	%ymm1,32+256(%rdi)
+	vmovdqu	%ymm5,64+256(%rdi)
+	vmovdqu	%ymm9,96+256(%rdi)
+	vperm2i128	$0x13,%ymm0,%ymm4,%ymm3
+	vperm2i128	$0x02,%ymm0,%ymm4,%ymm0
+	vperm2i128	$0x02,%ymm8,%ymm12,%ymm4
+	vperm2i128	$0x13,%ymm8,%ymm12,%ymm12
+	vmovdqa	%ymm3,%ymm8
+
+	leaq	384(%rsi),%rsi
+	leaq	384(%rdi),%rdi
+	subq	$384,%rbx
+open_avx2_tail_loop:
+	cmpq	$32,%rbx
+	jb	open_avx2_tail
+	subq	$32,%rbx
+	vpxor	(%rsi),%ymm0,%ymm0
+	vmovdqu	%ymm0,(%rdi)
+	leaq	32(%rsi),%rsi
+	leaq	32(%rdi),%rdi
+	vmovdqa	%ymm4,%ymm0
+	vmovdqa	%ymm8,%ymm4
+	vmovdqa	%ymm12,%ymm8
+	jmp	open_avx2_tail_loop
+open_avx2_tail:
+	cmpq	$16,%rbx
+	vmovdqa	%xmm0,%xmm1
+	jb	1f
+	subq	$16,%rbx
+
+	vpxor	(%rsi),%xmm0,%xmm1
+	vmovdqu	%xmm1,(%rdi)
+	leaq	16(%rsi),%rsi
+	leaq	16(%rdi),%rdi
+	vperm2i128	$0x11,%ymm0,%ymm0,%ymm0
+	vmovdqa	%xmm0,%xmm1
+1:
+	vzeroupper
+	jmp	open_sse_tail_16
+
+open_avx2_192:
+	vmovdqa	%ymm0,%ymm1
+	vmovdqa	%ymm0,%ymm2
+	vmovdqa	%ymm4,%ymm5
+	vmovdqa	%ymm4,%ymm6
+	vmovdqa	%ymm8,%ymm9
+	vmovdqa	%ymm8,%ymm10
+	vpaddd	.avx2_inc(%rip),%ymm12,%ymm13
+	vmovdqa	%ymm12,%ymm11
+	vmovdqa	%ymm13,%ymm15
+	movq	$10,%r10
+1:
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol16(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpsrld	$20,%ymm5,%ymm3
+	vpslld	$12,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol8(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpslld	$7,%ymm5,%ymm3
+	vpsrld	$25,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpalignr	$12,%ymm13,%ymm13,%ymm13
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$4,%ymm5,%ymm5,%ymm5
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol16(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpsrld	$20,%ymm5,%ymm3
+	vpslld	$12,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol8(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpslld	$7,%ymm5,%ymm3
+	vpsrld	$25,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpalignr	$4,%ymm13,%ymm13,%ymm13
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$12,%ymm5,%ymm5,%ymm5
+
+	decq	%r10
+	jne	1b
+	vpaddd	%ymm2,%ymm0,%ymm0
+	vpaddd	%ymm2,%ymm1,%ymm1
+	vpaddd	%ymm6,%ymm4,%ymm4
+	vpaddd	%ymm6,%ymm5,%ymm5
+	vpaddd	%ymm10,%ymm8,%ymm8
+	vpaddd	%ymm10,%ymm9,%ymm9
+	vpaddd	%ymm11,%ymm12,%ymm12
+	vpaddd	%ymm15,%ymm13,%ymm13
+	vperm2i128	$0x02,%ymm0,%ymm4,%ymm3
+
+	vpand	.clamp(%rip),%ymm3,%ymm3
+	vmovdqa	%ymm3,0(%rbp)
+
+	vperm2i128	$0x13,%ymm0,%ymm4,%ymm0
+	vperm2i128	$0x13,%ymm8,%ymm12,%ymm4
+	vperm2i128	$0x02,%ymm1,%ymm5,%ymm8
+	vperm2i128	$0x02,%ymm9,%ymm13,%ymm12
+	vperm2i128	$0x13,%ymm1,%ymm5,%ymm1
+	vperm2i128	$0x13,%ymm9,%ymm13,%ymm5
+open_avx2_short:
+	movq	%r8,%r8
+	call	poly_hash_ad_internal
+open_avx2_hash_and_xor_loop:
+	cmpq	$32,%rbx
+	jb	open_avx2_short_tail_32
+	subq	$32,%rbx
+	addq	0(%rsi),%r10
+	adcq	8+0(%rsi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	addq	16(%rsi),%r10
+	adcq	8+16(%rsi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+
+	vpxor	(%rsi),%ymm0,%ymm0
+	vmovdqu	%ymm0,(%rdi)
+	leaq	32(%rsi),%rsi
+	leaq	32(%rdi),%rdi
+
+	vmovdqa	%ymm4,%ymm0
+	vmovdqa	%ymm8,%ymm4
+	vmovdqa	%ymm12,%ymm8
+	vmovdqa	%ymm1,%ymm12
+	vmovdqa	%ymm5,%ymm1
+	vmovdqa	%ymm9,%ymm5
+	vmovdqa	%ymm13,%ymm9
+	vmovdqa	%ymm2,%ymm13
+	vmovdqa	%ymm6,%ymm2
+	jmp	open_avx2_hash_and_xor_loop
+open_avx2_short_tail_32:
+	cmpq	$16,%rbx
+	vmovdqa	%xmm0,%xmm1
+	jb	1f
+	subq	$16,%rbx
+	addq	0(%rsi),%r10
+	adcq	8+0(%rsi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	vpxor	(%rsi),%xmm0,%xmm3
+	vmovdqu	%xmm3,(%rdi)
+	leaq	16(%rsi),%rsi
+	leaq	16(%rdi),%rdi
+	vextracti128	$1,%ymm0,%xmm1
+1:
+	vzeroupper
+	jmp	open_sse_tail_16
+
+open_avx2_320:
+	vmovdqa	%ymm0,%ymm1
+	vmovdqa	%ymm0,%ymm2
+	vmovdqa	%ymm4,%ymm5
+	vmovdqa	%ymm4,%ymm6
+	vmovdqa	%ymm8,%ymm9
+	vmovdqa	%ymm8,%ymm10
+	vpaddd	.avx2_inc(%rip),%ymm12,%ymm13
+	vpaddd	.avx2_inc(%rip),%ymm13,%ymm14
+	vmovdqa	%ymm4,%ymm7
+	vmovdqa	%ymm8,%ymm11
+	vmovdqa	%ymm12,160(%rbp)
+	vmovdqa	%ymm13,192(%rbp)
+	vmovdqa	%ymm14,224(%rbp)
+	movq	$10,%r10
+1:
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol16(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpsrld	$20,%ymm5,%ymm3
+	vpslld	$12,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol8(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpslld	$7,%ymm5,%ymm3
+	vpsrld	$25,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpalignr	$12,%ymm13,%ymm13,%ymm13
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$4,%ymm5,%ymm5,%ymm5
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol16(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpsrld	$20,%ymm6,%ymm3
+	vpslld	$12,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol8(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpslld	$7,%ymm6,%ymm3
+	vpsrld	$25,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpalignr	$12,%ymm14,%ymm14,%ymm14
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$4,%ymm6,%ymm6,%ymm6
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol16(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpsrld	$20,%ymm5,%ymm3
+	vpslld	$12,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol8(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpslld	$7,%ymm5,%ymm3
+	vpsrld	$25,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpalignr	$4,%ymm13,%ymm13,%ymm13
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$12,%ymm5,%ymm5,%ymm5
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol16(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpsrld	$20,%ymm6,%ymm3
+	vpslld	$12,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol8(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpslld	$7,%ymm6,%ymm3
+	vpsrld	$25,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpalignr	$4,%ymm14,%ymm14,%ymm14
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$12,%ymm6,%ymm6,%ymm6
+
+	decq	%r10
+	jne	1b
+	vpaddd	.chacha20_consts(%rip),%ymm0,%ymm0
+	vpaddd	.chacha20_consts(%rip),%ymm1,%ymm1
+	vpaddd	.chacha20_consts(%rip),%ymm2,%ymm2
+	vpaddd	%ymm7,%ymm4,%ymm4
+	vpaddd	%ymm7,%ymm5,%ymm5
+	vpaddd	%ymm7,%ymm6,%ymm6
+	vpaddd	%ymm11,%ymm8,%ymm8
+	vpaddd	%ymm11,%ymm9,%ymm9
+	vpaddd	%ymm11,%ymm10,%ymm10
+	vpaddd	160(%rbp),%ymm12,%ymm12
+	vpaddd	192(%rbp),%ymm13,%ymm13
+	vpaddd	224(%rbp),%ymm14,%ymm14
+	vperm2i128	$0x02,%ymm0,%ymm4,%ymm3
+
+	vpand	.clamp(%rip),%ymm3,%ymm3
+	vmovdqa	%ymm3,0(%rbp)
+
+	vperm2i128	$0x13,%ymm0,%ymm4,%ymm0
+	vperm2i128	$0x13,%ymm8,%ymm12,%ymm4
+	vperm2i128	$0x02,%ymm1,%ymm5,%ymm8
+	vperm2i128	$0x02,%ymm9,%ymm13,%ymm12
+	vperm2i128	$0x13,%ymm1,%ymm5,%ymm1
+	vperm2i128	$0x13,%ymm9,%ymm13,%ymm5
+	vperm2i128	$0x02,%ymm2,%ymm6,%ymm9
+	vperm2i128	$0x02,%ymm10,%ymm14,%ymm13
+	vperm2i128	$0x13,%ymm2,%ymm6,%ymm2
+	vperm2i128	$0x13,%ymm10,%ymm14,%ymm6
+	jmp	open_avx2_short
+
+
+
+
+.p2align	6
+chacha20_poly1305_seal_avx2:
+	vzeroupper
+	vmovdqa	.chacha20_consts(%rip),%ymm0
+	vbroadcasti128	0(%r9),%ymm4
+	vbroadcasti128	16(%r9),%ymm8
+	vbroadcasti128	32(%r9),%ymm12
+	vpaddd	.avx2_init(%rip),%ymm12,%ymm12
+	cmpq	$192,%rbx
+	jbe	seal_avx2_192
+	cmpq	$320,%rbx
+	jbe	seal_avx2_320
+	vmovdqa	%ymm0,%ymm1
+	vmovdqa	%ymm0,%ymm2
+	vmovdqa	%ymm0,%ymm3
+	vmovdqa	%ymm4,%ymm5
+	vmovdqa	%ymm4,%ymm6
+	vmovdqa	%ymm4,%ymm7
+	vmovdqa	%ymm4,64(%rbp)
+	vmovdqa	%ymm8,%ymm9
+	vmovdqa	%ymm8,%ymm10
+	vmovdqa	%ymm8,%ymm11
+	vmovdqa	%ymm8,96(%rbp)
+	vmovdqa	%ymm12,%ymm15
+	vpaddd	.avx2_inc(%rip),%ymm15,%ymm14
+	vpaddd	.avx2_inc(%rip),%ymm14,%ymm13
+	vpaddd	.avx2_inc(%rip),%ymm13,%ymm12
+	vmovdqa	%ymm12,160(%rbp)
+	vmovdqa	%ymm13,192(%rbp)
+	vmovdqa	%ymm14,224(%rbp)
+	vmovdqa	%ymm15,256(%rbp)
+	movq	$10,%r10
+1:
+	vmovdqa	%ymm8,128(%rbp)
+	vmovdqa	.rol16(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$20,%ymm7,%ymm8
+	vpslld	$32-20,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$20,%ymm6,%ymm8
+	vpslld	$32-20,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$20,%ymm5,%ymm8
+	vpslld	$32-20,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$20,%ymm4,%ymm8
+	vpslld	$32-20,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	.rol8(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$25,%ymm7,%ymm8
+	vpslld	$32-25,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$25,%ymm6,%ymm8
+	vpslld	$32-25,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$25,%ymm5,%ymm8
+	vpslld	$32-25,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$25,%ymm4,%ymm8
+	vpslld	$32-25,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	128(%rbp),%ymm8
+	vpalignr	$4,%ymm7,%ymm7,%ymm7
+	vpalignr	$8,%ymm11,%ymm11,%ymm11
+	vpalignr	$12,%ymm15,%ymm15,%ymm15
+	vpalignr	$4,%ymm6,%ymm6,%ymm6
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$12,%ymm14,%ymm14,%ymm14
+	vpalignr	$4,%ymm5,%ymm5,%ymm5
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$12,%ymm13,%ymm13,%ymm13
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vmovdqa	%ymm8,128(%rbp)
+	vmovdqa	.rol16(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$20,%ymm7,%ymm8
+	vpslld	$32-20,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$20,%ymm6,%ymm8
+	vpslld	$32-20,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$20,%ymm5,%ymm8
+	vpslld	$32-20,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$20,%ymm4,%ymm8
+	vpslld	$32-20,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	.rol8(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$25,%ymm7,%ymm8
+	vpslld	$32-25,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$25,%ymm6,%ymm8
+	vpslld	$32-25,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$25,%ymm5,%ymm8
+	vpslld	$32-25,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$25,%ymm4,%ymm8
+	vpslld	$32-25,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	128(%rbp),%ymm8
+	vpalignr	$12,%ymm7,%ymm7,%ymm7
+	vpalignr	$8,%ymm11,%ymm11,%ymm11
+	vpalignr	$4,%ymm15,%ymm15,%ymm15
+	vpalignr	$12,%ymm6,%ymm6,%ymm6
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$4,%ymm14,%ymm14,%ymm14
+	vpalignr	$12,%ymm5,%ymm5,%ymm5
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$4,%ymm13,%ymm13,%ymm13
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+
+	decq	%r10
+	jnz	1b
+	vpaddd	.chacha20_consts(%rip),%ymm3,%ymm3
+	vpaddd	64(%rbp),%ymm7,%ymm7
+	vpaddd	96(%rbp),%ymm11,%ymm11
+	vpaddd	256(%rbp),%ymm15,%ymm15
+	vpaddd	.chacha20_consts(%rip),%ymm2,%ymm2
+	vpaddd	64(%rbp),%ymm6,%ymm6
+	vpaddd	96(%rbp),%ymm10,%ymm10
+	vpaddd	224(%rbp),%ymm14,%ymm14
+	vpaddd	.chacha20_consts(%rip),%ymm1,%ymm1
+	vpaddd	64(%rbp),%ymm5,%ymm5
+	vpaddd	96(%rbp),%ymm9,%ymm9
+	vpaddd	192(%rbp),%ymm13,%ymm13
+	vpaddd	.chacha20_consts(%rip),%ymm0,%ymm0
+	vpaddd	64(%rbp),%ymm4,%ymm4
+	vpaddd	96(%rbp),%ymm8,%ymm8
+	vpaddd	160(%rbp),%ymm12,%ymm12
+
+	vperm2i128	$0x13,%ymm11,%ymm15,%ymm11
+	vperm2i128	$0x02,%ymm3,%ymm7,%ymm15
+	vperm2i128	$0x13,%ymm3,%ymm7,%ymm3
+	vpand	.clamp(%rip),%ymm15,%ymm15
+	vmovdqa	%ymm15,0(%rbp)
+	movq	%r8,%r8
+	call	poly_hash_ad_internal
+
+	vpxor	0(%rsi),%ymm3,%ymm3
+	vpxor	32(%rsi),%ymm11,%ymm11
+	vmovdqu	%ymm3,0(%rdi)
+	vmovdqu	%ymm11,32(%rdi)
+	vperm2i128	$0x02,%ymm2,%ymm6,%ymm15
+	vperm2i128	$0x13,%ymm2,%ymm6,%ymm6
+	vperm2i128	$0x02,%ymm10,%ymm14,%ymm2
+	vperm2i128	$0x13,%ymm10,%ymm14,%ymm10
+	vpxor	0+64(%rsi),%ymm15,%ymm15
+	vpxor	32+64(%rsi),%ymm2,%ymm2
+	vpxor	64+64(%rsi),%ymm6,%ymm6
+	vpxor	96+64(%rsi),%ymm10,%ymm10
+	vmovdqu	%ymm15,0+64(%rdi)
+	vmovdqu	%ymm2,32+64(%rdi)
+	vmovdqu	%ymm6,64+64(%rdi)
+	vmovdqu	%ymm10,96+64(%rdi)
+	vperm2i128	$0x02,%ymm1,%ymm5,%ymm15
+	vperm2i128	$0x13,%ymm1,%ymm5,%ymm5
+	vperm2i128	$0x02,%ymm9,%ymm13,%ymm1
+	vperm2i128	$0x13,%ymm9,%ymm13,%ymm9
+	vpxor	0+192(%rsi),%ymm15,%ymm15
+	vpxor	32+192(%rsi),%ymm1,%ymm1
+	vpxor	64+192(%rsi),%ymm5,%ymm5
+	vpxor	96+192(%rsi),%ymm9,%ymm9
+	vmovdqu	%ymm15,0+192(%rdi)
+	vmovdqu	%ymm1,32+192(%rdi)
+	vmovdqu	%ymm5,64+192(%rdi)
+	vmovdqu	%ymm9,96+192(%rdi)
+	vperm2i128	$0x13,%ymm0,%ymm4,%ymm15
+	vperm2i128	$0x02,%ymm0,%ymm4,%ymm0
+	vperm2i128	$0x02,%ymm8,%ymm12,%ymm4
+	vperm2i128	$0x13,%ymm8,%ymm12,%ymm12
+	vmovdqa	%ymm15,%ymm8
+
+	leaq	320(%rsi),%rsi
+	subq	$320,%rbx
+	movq	$320,%rcx
+	cmpq	$128,%rbx
+	jbe	seal_avx2_hash
+	vpxor	0(%rsi),%ymm0,%ymm0
+	vpxor	32(%rsi),%ymm4,%ymm4
+	vpxor	64(%rsi),%ymm8,%ymm8
+	vpxor	96(%rsi),%ymm12,%ymm12
+	vmovdqu	%ymm0,320(%rdi)
+	vmovdqu	%ymm4,352(%rdi)
+	vmovdqu	%ymm8,384(%rdi)
+	vmovdqu	%ymm12,416(%rdi)
+	leaq	128(%rsi),%rsi
+	subq	$128,%rbx
+	movq	$8,%rcx
+	movq	$2,%r8
+	cmpq	$128,%rbx
+	jbe	seal_avx2_tail_128
+	cmpq	$256,%rbx
+	jbe	seal_avx2_tail_256
+	cmpq	$384,%rbx
+	jbe	seal_avx2_tail_384
+	cmpq	$512,%rbx
+	jbe	seal_avx2_tail_512
+	vmovdqa	.chacha20_consts(%rip),%ymm0
+	vmovdqa	64(%rbp),%ymm4
+	vmovdqa	96(%rbp),%ymm8
+	vmovdqa	%ymm0,%ymm1
+	vmovdqa	%ymm4,%ymm5
+	vmovdqa	%ymm8,%ymm9
+	vmovdqa	%ymm0,%ymm2
+	vmovdqa	%ymm4,%ymm6
+	vmovdqa	%ymm8,%ymm10
+	vmovdqa	%ymm0,%ymm3
+	vmovdqa	%ymm4,%ymm7
+	vmovdqa	%ymm8,%ymm11
+	vmovdqa	.avx2_inc(%rip),%ymm12
+	vpaddd	160(%rbp),%ymm12,%ymm15
+	vpaddd	%ymm15,%ymm12,%ymm14
+	vpaddd	%ymm14,%ymm12,%ymm13
+	vpaddd	%ymm13,%ymm12,%ymm12
+	vmovdqa	%ymm15,256(%rbp)
+	vmovdqa	%ymm14,224(%rbp)
+	vmovdqa	%ymm13,192(%rbp)
+	vmovdqa	%ymm12,160(%rbp)
+	vmovdqa	%ymm8,128(%rbp)
+	vmovdqa	.rol16(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$20,%ymm7,%ymm8
+	vpslld	$32-20,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$20,%ymm6,%ymm8
+	vpslld	$32-20,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$20,%ymm5,%ymm8
+	vpslld	$32-20,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$20,%ymm4,%ymm8
+	vpslld	$32-20,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	.rol8(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$25,%ymm7,%ymm8
+	vpslld	$32-25,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$25,%ymm6,%ymm8
+	vpslld	$32-25,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$25,%ymm5,%ymm8
+	vpslld	$32-25,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$25,%ymm4,%ymm8
+	vpslld	$32-25,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	128(%rbp),%ymm8
+	vpalignr	$4,%ymm7,%ymm7,%ymm7
+	vpalignr	$8,%ymm11,%ymm11,%ymm11
+	vpalignr	$12,%ymm15,%ymm15,%ymm15
+	vpalignr	$4,%ymm6,%ymm6,%ymm6
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$12,%ymm14,%ymm14,%ymm14
+	vpalignr	$4,%ymm5,%ymm5,%ymm5
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$12,%ymm13,%ymm13,%ymm13
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vmovdqa	%ymm8,128(%rbp)
+	vmovdqa	.rol16(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$20,%ymm7,%ymm8
+	vpslld	$32-20,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$20,%ymm6,%ymm8
+	vpslld	$32-20,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$20,%ymm5,%ymm8
+	vpslld	$32-20,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$20,%ymm4,%ymm8
+	vpslld	$32-20,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	.rol8(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$25,%ymm7,%ymm8
+	vpslld	$32-25,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$25,%ymm6,%ymm8
+	vpslld	$32-25,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$25,%ymm5,%ymm8
+	vpslld	$32-25,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$25,%ymm4,%ymm8
+	vpslld	$32-25,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	128(%rbp),%ymm8
+	vpalignr	$12,%ymm7,%ymm7,%ymm7
+	vpalignr	$8,%ymm11,%ymm11,%ymm11
+	vpalignr	$4,%ymm15,%ymm15,%ymm15
+	vpalignr	$12,%ymm6,%ymm6,%ymm6
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$4,%ymm14,%ymm14,%ymm14
+	vpalignr	$12,%ymm5,%ymm5,%ymm5
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$4,%ymm13,%ymm13,%ymm13
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+	vmovdqa	%ymm8,128(%rbp)
+	vmovdqa	.rol16(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$20,%ymm7,%ymm8
+	vpslld	$32-20,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$20,%ymm6,%ymm8
+	vpslld	$32-20,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$20,%ymm5,%ymm8
+	vpslld	$32-20,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$20,%ymm4,%ymm8
+	vpslld	$32-20,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	.rol8(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+
+	subq	$16,%rdi
+	movq	$9,%rcx
+	jmp	4f
+1:
+	vmovdqa	.chacha20_consts(%rip),%ymm0
+	vmovdqa	64(%rbp),%ymm4
+	vmovdqa	96(%rbp),%ymm8
+	vmovdqa	%ymm0,%ymm1
+	vmovdqa	%ymm4,%ymm5
+	vmovdqa	%ymm8,%ymm9
+	vmovdqa	%ymm0,%ymm2
+	vmovdqa	%ymm4,%ymm6
+	vmovdqa	%ymm8,%ymm10
+	vmovdqa	%ymm0,%ymm3
+	vmovdqa	%ymm4,%ymm7
+	vmovdqa	%ymm8,%ymm11
+	vmovdqa	.avx2_inc(%rip),%ymm12
+	vpaddd	160(%rbp),%ymm12,%ymm15
+	vpaddd	%ymm15,%ymm12,%ymm14
+	vpaddd	%ymm14,%ymm12,%ymm13
+	vpaddd	%ymm13,%ymm12,%ymm12
+	vmovdqa	%ymm15,256(%rbp)
+	vmovdqa	%ymm14,224(%rbp)
+	vmovdqa	%ymm13,192(%rbp)
+	vmovdqa	%ymm12,160(%rbp)
+
+	movq	$10,%rcx
+2:
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	vmovdqa	%ymm8,128(%rbp)
+	vmovdqa	.rol16(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	movq	0+0(%rbp),%rdx
+	movq	%rdx,%r15
+	mulxq	%r10,%r13,%r14
+	mulxq	%r11,%rax,%rdx
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	movq	8+0(%rbp),%rdx
+	mulxq	%r10,%r10,%rax
+	addq	%r10,%r14
+	mulxq	%r11,%r11,%r9
+	adcq	%r11,%r15
+	adcq	$0,%r9
+	imulq	%r12,%rdx
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$20,%ymm7,%ymm8
+	vpslld	$32-20,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$20,%ymm6,%ymm8
+	vpslld	$32-20,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$20,%ymm5,%ymm8
+	addq	%rax,%r15
+	adcq	%rdx,%r9
+	vpslld	$32-20,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$20,%ymm4,%ymm8
+	vpslld	$32-20,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	.rol8(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+4:
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	addq	16(%rdi),%r10
+	adcq	8+16(%rdi),%r11
+	adcq	$1,%r12
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	movq	0+0(%rbp),%rdx
+	movq	%rdx,%r15
+	mulxq	%r10,%r13,%r14
+	mulxq	%r11,%rax,%rdx
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$25,%ymm7,%ymm8
+	vpslld	$32-25,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$25,%ymm6,%ymm8
+	vpslld	$32-25,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$25,%ymm5,%ymm8
+	vpslld	$32-25,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$25,%ymm4,%ymm8
+	vpslld	$32-25,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	128(%rbp),%ymm8
+	vpalignr	$4,%ymm7,%ymm7,%ymm7
+	vpalignr	$8,%ymm11,%ymm11,%ymm11
+	vpalignr	$12,%ymm15,%ymm15,%ymm15
+	vpalignr	$4,%ymm6,%ymm6,%ymm6
+	movq	8+0(%rbp),%rdx
+	mulxq	%r10,%r10,%rax
+	addq	%r10,%r14
+	mulxq	%r11,%r11,%r9
+	adcq	%r11,%r15
+	adcq	$0,%r9
+	imulq	%r12,%rdx
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$12,%ymm14,%ymm14,%ymm14
+	vpalignr	$4,%ymm5,%ymm5,%ymm5
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$12,%ymm13,%ymm13,%ymm13
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vmovdqa	%ymm8,128(%rbp)
+	vmovdqa	.rol16(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	addq	%rax,%r15
+	adcq	%rdx,%r9
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$20,%ymm7,%ymm8
+	vpslld	$32-20,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	addq	32(%rdi),%r10
+	adcq	8+32(%rdi),%r11
+	adcq	$1,%r12
+
+	leaq	48(%rdi),%rdi
+	vpsrld	$20,%ymm6,%ymm8
+	vpslld	$32-20,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$20,%ymm5,%ymm8
+	vpslld	$32-20,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$20,%ymm4,%ymm8
+	vpslld	$32-20,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	.rol8(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	movq	0+0(%rbp),%rdx
+	movq	%rdx,%r15
+	mulxq	%r10,%r13,%r14
+	mulxq	%r11,%rax,%rdx
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	movq	8+0(%rbp),%rdx
+	mulxq	%r10,%r10,%rax
+	addq	%r10,%r14
+	mulxq	%r11,%r11,%r9
+	adcq	%r11,%r15
+	adcq	$0,%r9
+	imulq	%r12,%rdx
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$25,%ymm7,%ymm8
+	vpslld	$32-25,%ymm7,%ymm7
+	addq	%rax,%r15
+	adcq	%rdx,%r9
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$25,%ymm6,%ymm8
+	vpslld	$32-25,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$25,%ymm5,%ymm8
+	vpslld	$32-25,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$25,%ymm4,%ymm8
+	vpslld	$32-25,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	128(%rbp),%ymm8
+	vpalignr	$12,%ymm7,%ymm7,%ymm7
+	vpalignr	$8,%ymm11,%ymm11,%ymm11
+	vpalignr	$4,%ymm15,%ymm15,%ymm15
+	vpalignr	$12,%ymm6,%ymm6,%ymm6
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$4,%ymm14,%ymm14,%ymm14
+	vpalignr	$12,%ymm5,%ymm5,%ymm5
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$4,%ymm13,%ymm13,%ymm13
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+
+	decq	%rcx
+	jne	2b
+	vpaddd	.chacha20_consts(%rip),%ymm3,%ymm3
+	vpaddd	64(%rbp),%ymm7,%ymm7
+	vpaddd	96(%rbp),%ymm11,%ymm11
+	vpaddd	256(%rbp),%ymm15,%ymm15
+	vpaddd	.chacha20_consts(%rip),%ymm2,%ymm2
+	vpaddd	64(%rbp),%ymm6,%ymm6
+	vpaddd	96(%rbp),%ymm10,%ymm10
+	vpaddd	224(%rbp),%ymm14,%ymm14
+	vpaddd	.chacha20_consts(%rip),%ymm1,%ymm1
+	vpaddd	64(%rbp),%ymm5,%ymm5
+	vpaddd	96(%rbp),%ymm9,%ymm9
+	vpaddd	192(%rbp),%ymm13,%ymm13
+	vpaddd	.chacha20_consts(%rip),%ymm0,%ymm0
+	vpaddd	64(%rbp),%ymm4,%ymm4
+	vpaddd	96(%rbp),%ymm8,%ymm8
+	vpaddd	160(%rbp),%ymm12,%ymm12
+
+	leaq	32(%rdi),%rdi
+	vmovdqa	%ymm0,128(%rbp)
+	addq	-32(%rdi),%r10
+	adcq	8+-32(%rdi),%r11
+	adcq	$1,%r12
+	vperm2i128	$0x02,%ymm3,%ymm7,%ymm0
+	vperm2i128	$0x13,%ymm3,%ymm7,%ymm7
+	vperm2i128	$0x02,%ymm11,%ymm15,%ymm3
+	vperm2i128	$0x13,%ymm11,%ymm15,%ymm11
+	vpxor	0+0(%rsi),%ymm0,%ymm0
+	vpxor	32+0(%rsi),%ymm3,%ymm3
+	vpxor	64+0(%rsi),%ymm7,%ymm7
+	vpxor	96+0(%rsi),%ymm11,%ymm11
+	vmovdqu	%ymm0,0+0(%rdi)
+	vmovdqu	%ymm3,32+0(%rdi)
+	vmovdqu	%ymm7,64+0(%rdi)
+	vmovdqu	%ymm11,96+0(%rdi)
+
+	vmovdqa	128(%rbp),%ymm0
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	vperm2i128	$0x02,%ymm2,%ymm6,%ymm3
+	vperm2i128	$0x13,%ymm2,%ymm6,%ymm6
+	vperm2i128	$0x02,%ymm10,%ymm14,%ymm2
+	vperm2i128	$0x13,%ymm10,%ymm14,%ymm10
+	vpxor	0+128(%rsi),%ymm3,%ymm3
+	vpxor	32+128(%rsi),%ymm2,%ymm2
+	vpxor	64+128(%rsi),%ymm6,%ymm6
+	vpxor	96+128(%rsi),%ymm10,%ymm10
+	vmovdqu	%ymm3,0+128(%rdi)
+	vmovdqu	%ymm2,32+128(%rdi)
+	vmovdqu	%ymm6,64+128(%rdi)
+	vmovdqu	%ymm10,96+128(%rdi)
+	addq	-16(%rdi),%r10
+	adcq	8+-16(%rdi),%r11
+	adcq	$1,%r12
+	vperm2i128	$0x02,%ymm1,%ymm5,%ymm3
+	vperm2i128	$0x13,%ymm1,%ymm5,%ymm5
+	vperm2i128	$0x02,%ymm9,%ymm13,%ymm1
+	vperm2i128	$0x13,%ymm9,%ymm13,%ymm9
+	vpxor	0+256(%rsi),%ymm3,%ymm3
+	vpxor	32+256(%rsi),%ymm1,%ymm1
+	vpxor	64+256(%rsi),%ymm5,%ymm5
+	vpxor	96+256(%rsi),%ymm9,%ymm9
+	vmovdqu	%ymm3,0+256(%rdi)
+	vmovdqu	%ymm1,32+256(%rdi)
+	vmovdqu	%ymm5,64+256(%rdi)
+	vmovdqu	%ymm9,96+256(%rdi)
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	vperm2i128	$0x02,%ymm0,%ymm4,%ymm3
+	vperm2i128	$0x13,%ymm0,%ymm4,%ymm4
+	vperm2i128	$0x02,%ymm8,%ymm12,%ymm0
+	vperm2i128	$0x13,%ymm8,%ymm12,%ymm8
+	vpxor	0+384(%rsi),%ymm3,%ymm3
+	vpxor	32+384(%rsi),%ymm0,%ymm0
+	vpxor	64+384(%rsi),%ymm4,%ymm4
+	vpxor	96+384(%rsi),%ymm8,%ymm8
+	vmovdqu	%ymm3,0+384(%rdi)
+	vmovdqu	%ymm0,32+384(%rdi)
+	vmovdqu	%ymm4,64+384(%rdi)
+	vmovdqu	%ymm8,96+384(%rdi)
+
+	leaq	512(%rsi),%rsi
+	subq	$512,%rbx
+	cmpq	$512,%rbx
+	jg	1b
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	addq	16(%rdi),%r10
+	adcq	8+16(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	32(%rdi),%rdi
+	movq	$10,%rcx
+	xorq	%r8,%r8
+	cmpq	$128,%rbx
+	ja	3f
+
+seal_avx2_tail_128:
+	vmovdqa	.chacha20_consts(%rip),%ymm0
+	vmovdqa	64(%rbp),%ymm4
+	vmovdqa	96(%rbp),%ymm8
+	vmovdqa	.avx2_inc(%rip),%ymm12
+	vpaddd	160(%rbp),%ymm12,%ymm12
+	vmovdqa	%ymm12,160(%rbp)
+
+1:
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%rdi),%rdi
+2:
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+	addq	16(%rdi),%r10
+	adcq	8+16(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	32(%rdi),%rdi
+	decq	%rcx
+	jg	1b
+	decq	%r8
+	jge	2b
+	vpaddd	.chacha20_consts(%rip),%ymm0,%ymm0
+	vpaddd	64(%rbp),%ymm4,%ymm4
+	vpaddd	96(%rbp),%ymm8,%ymm8
+	vpaddd	160(%rbp),%ymm12,%ymm12
+	vperm2i128	$0x13,%ymm0,%ymm4,%ymm3
+	vperm2i128	$0x02,%ymm0,%ymm4,%ymm0
+	vperm2i128	$0x02,%ymm8,%ymm12,%ymm4
+	vperm2i128	$0x13,%ymm8,%ymm12,%ymm12
+	vmovdqa	%ymm3,%ymm8
+
+	jmp	seal_avx2_short_loop
+3:
+	cmpq	$256,%rbx
+	ja	3f
+
+seal_avx2_tail_256:
+	vmovdqa	.chacha20_consts(%rip),%ymm0
+	vmovdqa	64(%rbp),%ymm4
+	vmovdqa	96(%rbp),%ymm8
+	vmovdqa	%ymm0,%ymm1
+	vmovdqa	%ymm4,%ymm5
+	vmovdqa	%ymm8,%ymm9
+	vmovdqa	.avx2_inc(%rip),%ymm12
+	vpaddd	160(%rbp),%ymm12,%ymm13
+	vpaddd	%ymm13,%ymm12,%ymm12
+	vmovdqa	%ymm12,160(%rbp)
+	vmovdqa	%ymm13,192(%rbp)
+
+1:
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%rdi),%rdi
+2:
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol16(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpsrld	$20,%ymm5,%ymm3
+	vpslld	$12,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol8(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpslld	$7,%ymm5,%ymm3
+	vpsrld	$25,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpalignr	$12,%ymm13,%ymm13,%ymm13
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$4,%ymm5,%ymm5,%ymm5
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol16(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpsrld	$20,%ymm5,%ymm3
+	vpslld	$12,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol8(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpslld	$7,%ymm5,%ymm3
+	vpsrld	$25,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpalignr	$4,%ymm13,%ymm13,%ymm13
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$12,%ymm5,%ymm5,%ymm5
+	addq	16(%rdi),%r10
+	adcq	8+16(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	32(%rdi),%rdi
+	decq	%rcx
+	jg	1b
+	decq	%r8
+	jge	2b
+	vpaddd	.chacha20_consts(%rip),%ymm1,%ymm1
+	vpaddd	64(%rbp),%ymm5,%ymm5
+	vpaddd	96(%rbp),%ymm9,%ymm9
+	vpaddd	192(%rbp),%ymm13,%ymm13
+	vpaddd	.chacha20_consts(%rip),%ymm0,%ymm0
+	vpaddd	64(%rbp),%ymm4,%ymm4
+	vpaddd	96(%rbp),%ymm8,%ymm8
+	vpaddd	160(%rbp),%ymm12,%ymm12
+	vperm2i128	$0x02,%ymm1,%ymm5,%ymm3
+	vperm2i128	$0x13,%ymm1,%ymm5,%ymm5
+	vperm2i128	$0x02,%ymm9,%ymm13,%ymm1
+	vperm2i128	$0x13,%ymm9,%ymm13,%ymm9
+	vpxor	0+0(%rsi),%ymm3,%ymm3
+	vpxor	32+0(%rsi),%ymm1,%ymm1
+	vpxor	64+0(%rsi),%ymm5,%ymm5
+	vpxor	96+0(%rsi),%ymm9,%ymm9
+	vmovdqu	%ymm3,0+0(%rdi)
+	vmovdqu	%ymm1,32+0(%rdi)
+	vmovdqu	%ymm5,64+0(%rdi)
+	vmovdqu	%ymm9,96+0(%rdi)
+	vperm2i128	$0x13,%ymm0,%ymm4,%ymm3
+	vperm2i128	$0x02,%ymm0,%ymm4,%ymm0
+	vperm2i128	$0x02,%ymm8,%ymm12,%ymm4
+	vperm2i128	$0x13,%ymm8,%ymm12,%ymm12
+	vmovdqa	%ymm3,%ymm8
+
+	movq	$128,%rcx
+	leaq	128(%rsi),%rsi
+	subq	$128,%rbx
+	jmp	seal_avx2_hash
+3:
+	cmpq	$384,%rbx
+	ja	seal_avx2_tail_512
+
+seal_avx2_tail_384:
+	vmovdqa	.chacha20_consts(%rip),%ymm0
+	vmovdqa	64(%rbp),%ymm4
+	vmovdqa	96(%rbp),%ymm8
+	vmovdqa	%ymm0,%ymm1
+	vmovdqa	%ymm4,%ymm5
+	vmovdqa	%ymm8,%ymm9
+	vmovdqa	%ymm0,%ymm2
+	vmovdqa	%ymm4,%ymm6
+	vmovdqa	%ymm8,%ymm10
+	vmovdqa	.avx2_inc(%rip),%ymm12
+	vpaddd	160(%rbp),%ymm12,%ymm14
+	vpaddd	%ymm14,%ymm12,%ymm13
+	vpaddd	%ymm13,%ymm12,%ymm12
+	vmovdqa	%ymm12,160(%rbp)
+	vmovdqa	%ymm13,192(%rbp)
+	vmovdqa	%ymm14,224(%rbp)
+
+1:
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%rdi),%rdi
+2:
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol16(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpsrld	$20,%ymm5,%ymm3
+	vpslld	$12,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol8(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpslld	$7,%ymm5,%ymm3
+	vpsrld	$25,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpalignr	$12,%ymm13,%ymm13,%ymm13
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$4,%ymm5,%ymm5,%ymm5
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol16(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpsrld	$20,%ymm6,%ymm3
+	vpslld	$12,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol8(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpslld	$7,%ymm6,%ymm3
+	vpsrld	$25,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpalignr	$12,%ymm14,%ymm14,%ymm14
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$4,%ymm6,%ymm6,%ymm6
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+	addq	16(%rdi),%r10
+	adcq	8+16(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol16(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpsrld	$20,%ymm5,%ymm3
+	vpslld	$12,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol8(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpslld	$7,%ymm5,%ymm3
+	vpsrld	$25,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpalignr	$4,%ymm13,%ymm13,%ymm13
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$12,%ymm5,%ymm5,%ymm5
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol16(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpsrld	$20,%ymm6,%ymm3
+	vpslld	$12,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol8(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpslld	$7,%ymm6,%ymm3
+	vpsrld	$25,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpalignr	$4,%ymm14,%ymm14,%ymm14
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$12,%ymm6,%ymm6,%ymm6
+
+	leaq	32(%rdi),%rdi
+	decq	%rcx
+	jg	1b
+	decq	%r8
+	jge	2b
+	vpaddd	.chacha20_consts(%rip),%ymm2,%ymm2
+	vpaddd	64(%rbp),%ymm6,%ymm6
+	vpaddd	96(%rbp),%ymm10,%ymm10
+	vpaddd	224(%rbp),%ymm14,%ymm14
+	vpaddd	.chacha20_consts(%rip),%ymm1,%ymm1
+	vpaddd	64(%rbp),%ymm5,%ymm5
+	vpaddd	96(%rbp),%ymm9,%ymm9
+	vpaddd	192(%rbp),%ymm13,%ymm13
+	vpaddd	.chacha20_consts(%rip),%ymm0,%ymm0
+	vpaddd	64(%rbp),%ymm4,%ymm4
+	vpaddd	96(%rbp),%ymm8,%ymm8
+	vpaddd	160(%rbp),%ymm12,%ymm12
+	vperm2i128	$0x02,%ymm2,%ymm6,%ymm3
+	vperm2i128	$0x13,%ymm2,%ymm6,%ymm6
+	vperm2i128	$0x02,%ymm10,%ymm14,%ymm2
+	vperm2i128	$0x13,%ymm10,%ymm14,%ymm10
+	vpxor	0+0(%rsi),%ymm3,%ymm3
+	vpxor	32+0(%rsi),%ymm2,%ymm2
+	vpxor	64+0(%rsi),%ymm6,%ymm6
+	vpxor	96+0(%rsi),%ymm10,%ymm10
+	vmovdqu	%ymm3,0+0(%rdi)
+	vmovdqu	%ymm2,32+0(%rdi)
+	vmovdqu	%ymm6,64+0(%rdi)
+	vmovdqu	%ymm10,96+0(%rdi)
+	vperm2i128	$0x02,%ymm1,%ymm5,%ymm3
+	vperm2i128	$0x13,%ymm1,%ymm5,%ymm5
+	vperm2i128	$0x02,%ymm9,%ymm13,%ymm1
+	vperm2i128	$0x13,%ymm9,%ymm13,%ymm9
+	vpxor	0+128(%rsi),%ymm3,%ymm3
+	vpxor	32+128(%rsi),%ymm1,%ymm1
+	vpxor	64+128(%rsi),%ymm5,%ymm5
+	vpxor	96+128(%rsi),%ymm9,%ymm9
+	vmovdqu	%ymm3,0+128(%rdi)
+	vmovdqu	%ymm1,32+128(%rdi)
+	vmovdqu	%ymm5,64+128(%rdi)
+	vmovdqu	%ymm9,96+128(%rdi)
+	vperm2i128	$0x13,%ymm0,%ymm4,%ymm3
+	vperm2i128	$0x02,%ymm0,%ymm4,%ymm0
+	vperm2i128	$0x02,%ymm8,%ymm12,%ymm4
+	vperm2i128	$0x13,%ymm8,%ymm12,%ymm12
+	vmovdqa	%ymm3,%ymm8
+
+	movq	$256,%rcx
+	leaq	256(%rsi),%rsi
+	subq	$256,%rbx
+	jmp	seal_avx2_hash
+
+seal_avx2_tail_512:
+	vmovdqa	.chacha20_consts(%rip),%ymm0
+	vmovdqa	64(%rbp),%ymm4
+	vmovdqa	96(%rbp),%ymm8
+	vmovdqa	%ymm0,%ymm1
+	vmovdqa	%ymm4,%ymm5
+	vmovdqa	%ymm8,%ymm9
+	vmovdqa	%ymm0,%ymm2
+	vmovdqa	%ymm4,%ymm6
+	vmovdqa	%ymm8,%ymm10
+	vmovdqa	%ymm0,%ymm3
+	vmovdqa	%ymm4,%ymm7
+	vmovdqa	%ymm8,%ymm11
+	vmovdqa	.avx2_inc(%rip),%ymm12
+	vpaddd	160(%rbp),%ymm12,%ymm15
+	vpaddd	%ymm15,%ymm12,%ymm14
+	vpaddd	%ymm14,%ymm12,%ymm13
+	vpaddd	%ymm13,%ymm12,%ymm12
+	vmovdqa	%ymm15,256(%rbp)
+	vmovdqa	%ymm14,224(%rbp)
+	vmovdqa	%ymm13,192(%rbp)
+	vmovdqa	%ymm12,160(%rbp)
+
+1:
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rdx
+	movq	%rdx,%r15
+	mulxq	%r10,%r13,%r14
+	mulxq	%r11,%rax,%rdx
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rdx
+	mulxq	%r10,%r10,%rax
+	addq	%r10,%r14
+	mulxq	%r11,%r11,%r9
+	adcq	%r11,%r15
+	adcq	$0,%r9
+	imulq	%r12,%rdx
+	addq	%rax,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%rdi),%rdi
+2:
+	vmovdqa	%ymm8,128(%rbp)
+	vmovdqa	.rol16(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$20,%ymm7,%ymm8
+	vpslld	$32-20,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$20,%ymm6,%ymm8
+	vpslld	$32-20,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$20,%ymm5,%ymm8
+	vpslld	$32-20,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$20,%ymm4,%ymm8
+	vpslld	$32-20,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	.rol8(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	movq	0+0(%rbp),%rdx
+	movq	%rdx,%r15
+	mulxq	%r10,%r13,%r14
+	mulxq	%r11,%rax,%rdx
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$25,%ymm7,%ymm8
+	movq	8+0(%rbp),%rdx
+	mulxq	%r10,%r10,%rax
+	addq	%r10,%r14
+	mulxq	%r11,%r11,%r9
+	adcq	%r11,%r15
+	adcq	$0,%r9
+	imulq	%r12,%rdx
+	vpslld	$32-25,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$25,%ymm6,%ymm8
+	vpslld	$32-25,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$25,%ymm5,%ymm8
+	vpslld	$32-25,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$25,%ymm4,%ymm8
+	vpslld	$32-25,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	128(%rbp),%ymm8
+	vpalignr	$4,%ymm7,%ymm7,%ymm7
+	vpalignr	$8,%ymm11,%ymm11,%ymm11
+	vpalignr	$12,%ymm15,%ymm15,%ymm15
+	vpalignr	$4,%ymm6,%ymm6,%ymm6
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$12,%ymm14,%ymm14,%ymm14
+	vpalignr	$4,%ymm5,%ymm5,%ymm5
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	addq	%rax,%r15
+	adcq	%rdx,%r9
+	vpalignr	$12,%ymm13,%ymm13,%ymm13
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vmovdqa	%ymm8,128(%rbp)
+	vmovdqa	.rol16(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$20,%ymm7,%ymm8
+	vpslld	$32-20,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$20,%ymm6,%ymm8
+	vpslld	$32-20,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$20,%ymm5,%ymm8
+	vpslld	$32-20,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$20,%ymm4,%ymm8
+	vpslld	$32-20,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	addq	16(%rdi),%r10
+	adcq	8+16(%rdi),%r11
+	adcq	$1,%r12
+	vmovdqa	.rol8(%rip),%ymm8
+	vpaddd	%ymm7,%ymm3,%ymm3
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm3,%ymm15,%ymm15
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	%ymm8,%ymm15,%ymm15
+	vpshufb	%ymm8,%ymm14,%ymm14
+	vpshufb	%ymm8,%ymm13,%ymm13
+	vpshufb	%ymm8,%ymm12,%ymm12
+	vmovdqa	128(%rbp),%ymm8
+	vpaddd	%ymm15,%ymm11,%ymm11
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm11,%ymm7,%ymm7
+	vpxor	%ymm10,%ymm6,%ymm6
+	movq	0+0(%rbp),%rdx
+	movq	%rdx,%r15
+	mulxq	%r10,%r13,%r14
+	mulxq	%r11,%rax,%rdx
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	%ymm8,128(%rbp)
+	vpsrld	$25,%ymm7,%ymm8
+	vpslld	$32-25,%ymm7,%ymm7
+	vpxor	%ymm8,%ymm7,%ymm7
+	vpsrld	$25,%ymm6,%ymm8
+	vpslld	$32-25,%ymm6,%ymm6
+	vpxor	%ymm8,%ymm6,%ymm6
+	vpsrld	$25,%ymm5,%ymm8
+	vpslld	$32-25,%ymm5,%ymm5
+	vpxor	%ymm8,%ymm5,%ymm5
+	vpsrld	$25,%ymm4,%ymm8
+	vpslld	$32-25,%ymm4,%ymm4
+	vpxor	%ymm8,%ymm4,%ymm4
+	vmovdqa	128(%rbp),%ymm8
+	vpalignr	$12,%ymm7,%ymm7,%ymm7
+	vpalignr	$8,%ymm11,%ymm11,%ymm11
+	vpalignr	$4,%ymm15,%ymm15,%ymm15
+	vpalignr	$12,%ymm6,%ymm6,%ymm6
+	movq	8+0(%rbp),%rdx
+	mulxq	%r10,%r10,%rax
+	addq	%r10,%r14
+	mulxq	%r11,%r11,%r9
+	adcq	%r11,%r15
+	adcq	$0,%r9
+	imulq	%r12,%rdx
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$4,%ymm14,%ymm14,%ymm14
+	vpalignr	$12,%ymm5,%ymm5,%ymm5
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$4,%ymm13,%ymm13,%ymm13
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+
+
+
+
+
+
+
+
+
+
+
+
+	addq	%rax,%r15
+	adcq	%rdx,%r9
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	32(%rdi),%rdi
+	decq	%rcx
+	jg	1b
+	decq	%r8
+	jge	2b
+	vpaddd	.chacha20_consts(%rip),%ymm3,%ymm3
+	vpaddd	64(%rbp),%ymm7,%ymm7
+	vpaddd	96(%rbp),%ymm11,%ymm11
+	vpaddd	256(%rbp),%ymm15,%ymm15
+	vpaddd	.chacha20_consts(%rip),%ymm2,%ymm2
+	vpaddd	64(%rbp),%ymm6,%ymm6
+	vpaddd	96(%rbp),%ymm10,%ymm10
+	vpaddd	224(%rbp),%ymm14,%ymm14
+	vpaddd	.chacha20_consts(%rip),%ymm1,%ymm1
+	vpaddd	64(%rbp),%ymm5,%ymm5
+	vpaddd	96(%rbp),%ymm9,%ymm9
+	vpaddd	192(%rbp),%ymm13,%ymm13
+	vpaddd	.chacha20_consts(%rip),%ymm0,%ymm0
+	vpaddd	64(%rbp),%ymm4,%ymm4
+	vpaddd	96(%rbp),%ymm8,%ymm8
+	vpaddd	160(%rbp),%ymm12,%ymm12
+
+	vmovdqa	%ymm0,128(%rbp)
+	vperm2i128	$0x02,%ymm3,%ymm7,%ymm0
+	vperm2i128	$0x13,%ymm3,%ymm7,%ymm7
+	vperm2i128	$0x02,%ymm11,%ymm15,%ymm3
+	vperm2i128	$0x13,%ymm11,%ymm15,%ymm11
+	vpxor	0+0(%rsi),%ymm0,%ymm0
+	vpxor	32+0(%rsi),%ymm3,%ymm3
+	vpxor	64+0(%rsi),%ymm7,%ymm7
+	vpxor	96+0(%rsi),%ymm11,%ymm11
+	vmovdqu	%ymm0,0+0(%rdi)
+	vmovdqu	%ymm3,32+0(%rdi)
+	vmovdqu	%ymm7,64+0(%rdi)
+	vmovdqu	%ymm11,96+0(%rdi)
+
+	vmovdqa	128(%rbp),%ymm0
+	vperm2i128	$0x02,%ymm2,%ymm6,%ymm3
+	vperm2i128	$0x13,%ymm2,%ymm6,%ymm6
+	vperm2i128	$0x02,%ymm10,%ymm14,%ymm2
+	vperm2i128	$0x13,%ymm10,%ymm14,%ymm10
+	vpxor	0+128(%rsi),%ymm3,%ymm3
+	vpxor	32+128(%rsi),%ymm2,%ymm2
+	vpxor	64+128(%rsi),%ymm6,%ymm6
+	vpxor	96+128(%rsi),%ymm10,%ymm10
+	vmovdqu	%ymm3,0+128(%rdi)
+	vmovdqu	%ymm2,32+128(%rdi)
+	vmovdqu	%ymm6,64+128(%rdi)
+	vmovdqu	%ymm10,96+128(%rdi)
+	vperm2i128	$0x02,%ymm1,%ymm5,%ymm3
+	vperm2i128	$0x13,%ymm1,%ymm5,%ymm5
+	vperm2i128	$0x02,%ymm9,%ymm13,%ymm1
+	vperm2i128	$0x13,%ymm9,%ymm13,%ymm9
+	vpxor	0+256(%rsi),%ymm3,%ymm3
+	vpxor	32+256(%rsi),%ymm1,%ymm1
+	vpxor	64+256(%rsi),%ymm5,%ymm5
+	vpxor	96+256(%rsi),%ymm9,%ymm9
+	vmovdqu	%ymm3,0+256(%rdi)
+	vmovdqu	%ymm1,32+256(%rdi)
+	vmovdqu	%ymm5,64+256(%rdi)
+	vmovdqu	%ymm9,96+256(%rdi)
+	vperm2i128	$0x13,%ymm0,%ymm4,%ymm3
+	vperm2i128	$0x02,%ymm0,%ymm4,%ymm0
+	vperm2i128	$0x02,%ymm8,%ymm12,%ymm4
+	vperm2i128	$0x13,%ymm8,%ymm12,%ymm12
+	vmovdqa	%ymm3,%ymm8
+
+	movq	$384,%rcx
+	leaq	384(%rsi),%rsi
+	subq	$384,%rbx
+	jmp	seal_avx2_hash
+
+seal_avx2_320:
+	vmovdqa	%ymm0,%ymm1
+	vmovdqa	%ymm0,%ymm2
+	vmovdqa	%ymm4,%ymm5
+	vmovdqa	%ymm4,%ymm6
+	vmovdqa	%ymm8,%ymm9
+	vmovdqa	%ymm8,%ymm10
+	vpaddd	.avx2_inc(%rip),%ymm12,%ymm13
+	vpaddd	.avx2_inc(%rip),%ymm13,%ymm14
+	vmovdqa	%ymm4,%ymm7
+	vmovdqa	%ymm8,%ymm11
+	vmovdqa	%ymm12,160(%rbp)
+	vmovdqa	%ymm13,192(%rbp)
+	vmovdqa	%ymm14,224(%rbp)
+	movq	$10,%r10
+1:
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol16(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpsrld	$20,%ymm5,%ymm3
+	vpslld	$12,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol8(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpslld	$7,%ymm5,%ymm3
+	vpsrld	$25,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpalignr	$12,%ymm13,%ymm13,%ymm13
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$4,%ymm5,%ymm5,%ymm5
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol16(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpsrld	$20,%ymm6,%ymm3
+	vpslld	$12,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol8(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpslld	$7,%ymm6,%ymm3
+	vpsrld	$25,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpalignr	$12,%ymm14,%ymm14,%ymm14
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$4,%ymm6,%ymm6,%ymm6
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol16(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpsrld	$20,%ymm5,%ymm3
+	vpslld	$12,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol8(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpslld	$7,%ymm5,%ymm3
+	vpsrld	$25,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpalignr	$4,%ymm13,%ymm13,%ymm13
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$12,%ymm5,%ymm5,%ymm5
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol16(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpsrld	$20,%ymm6,%ymm3
+	vpslld	$12,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpaddd	%ymm6,%ymm2,%ymm2
+	vpxor	%ymm2,%ymm14,%ymm14
+	vpshufb	.rol8(%rip),%ymm14,%ymm14
+	vpaddd	%ymm14,%ymm10,%ymm10
+	vpxor	%ymm10,%ymm6,%ymm6
+	vpslld	$7,%ymm6,%ymm3
+	vpsrld	$25,%ymm6,%ymm6
+	vpxor	%ymm3,%ymm6,%ymm6
+	vpalignr	$4,%ymm14,%ymm14,%ymm14
+	vpalignr	$8,%ymm10,%ymm10,%ymm10
+	vpalignr	$12,%ymm6,%ymm6,%ymm6
+
+	decq	%r10
+	jne	1b
+	vpaddd	.chacha20_consts(%rip),%ymm0,%ymm0
+	vpaddd	.chacha20_consts(%rip),%ymm1,%ymm1
+	vpaddd	.chacha20_consts(%rip),%ymm2,%ymm2
+	vpaddd	%ymm7,%ymm4,%ymm4
+	vpaddd	%ymm7,%ymm5,%ymm5
+	vpaddd	%ymm7,%ymm6,%ymm6
+	vpaddd	%ymm11,%ymm8,%ymm8
+	vpaddd	%ymm11,%ymm9,%ymm9
+	vpaddd	%ymm11,%ymm10,%ymm10
+	vpaddd	160(%rbp),%ymm12,%ymm12
+	vpaddd	192(%rbp),%ymm13,%ymm13
+	vpaddd	224(%rbp),%ymm14,%ymm14
+	vperm2i128	$0x02,%ymm0,%ymm4,%ymm3
+
+	vpand	.clamp(%rip),%ymm3,%ymm3
+	vmovdqa	%ymm3,0(%rbp)
+
+	vperm2i128	$0x13,%ymm0,%ymm4,%ymm0
+	vperm2i128	$0x13,%ymm8,%ymm12,%ymm4
+	vperm2i128	$0x02,%ymm1,%ymm5,%ymm8
+	vperm2i128	$0x02,%ymm9,%ymm13,%ymm12
+	vperm2i128	$0x13,%ymm1,%ymm5,%ymm1
+	vperm2i128	$0x13,%ymm9,%ymm13,%ymm5
+	vperm2i128	$0x02,%ymm2,%ymm6,%ymm9
+	vperm2i128	$0x02,%ymm10,%ymm14,%ymm13
+	vperm2i128	$0x13,%ymm2,%ymm6,%ymm2
+	vperm2i128	$0x13,%ymm10,%ymm14,%ymm6
+	jmp	seal_avx2_short
+
+seal_avx2_192:
+	vmovdqa	%ymm0,%ymm1
+	vmovdqa	%ymm0,%ymm2
+	vmovdqa	%ymm4,%ymm5
+	vmovdqa	%ymm4,%ymm6
+	vmovdqa	%ymm8,%ymm9
+	vmovdqa	%ymm8,%ymm10
+	vpaddd	.avx2_inc(%rip),%ymm12,%ymm13
+	vmovdqa	%ymm12,%ymm11
+	vmovdqa	%ymm13,%ymm15
+	movq	$10,%r10
+1:
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$12,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$4,%ymm4,%ymm4,%ymm4
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol16(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpsrld	$20,%ymm5,%ymm3
+	vpslld	$12,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol8(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpslld	$7,%ymm5,%ymm3
+	vpsrld	$25,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpalignr	$12,%ymm13,%ymm13,%ymm13
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$4,%ymm5,%ymm5,%ymm5
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol16(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpsrld	$20,%ymm4,%ymm3
+	vpslld	$12,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpaddd	%ymm4,%ymm0,%ymm0
+	vpxor	%ymm0,%ymm12,%ymm12
+	vpshufb	.rol8(%rip),%ymm12,%ymm12
+	vpaddd	%ymm12,%ymm8,%ymm8
+	vpxor	%ymm8,%ymm4,%ymm4
+	vpslld	$7,%ymm4,%ymm3
+	vpsrld	$25,%ymm4,%ymm4
+	vpxor	%ymm3,%ymm4,%ymm4
+	vpalignr	$4,%ymm12,%ymm12,%ymm12
+	vpalignr	$8,%ymm8,%ymm8,%ymm8
+	vpalignr	$12,%ymm4,%ymm4,%ymm4
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol16(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpsrld	$20,%ymm5,%ymm3
+	vpslld	$12,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpaddd	%ymm5,%ymm1,%ymm1
+	vpxor	%ymm1,%ymm13,%ymm13
+	vpshufb	.rol8(%rip),%ymm13,%ymm13
+	vpaddd	%ymm13,%ymm9,%ymm9
+	vpxor	%ymm9,%ymm5,%ymm5
+	vpslld	$7,%ymm5,%ymm3
+	vpsrld	$25,%ymm5,%ymm5
+	vpxor	%ymm3,%ymm5,%ymm5
+	vpalignr	$4,%ymm13,%ymm13,%ymm13
+	vpalignr	$8,%ymm9,%ymm9,%ymm9
+	vpalignr	$12,%ymm5,%ymm5,%ymm5
+
+	decq	%r10
+	jne	1b
+	vpaddd	%ymm2,%ymm0,%ymm0
+	vpaddd	%ymm2,%ymm1,%ymm1
+	vpaddd	%ymm6,%ymm4,%ymm4
+	vpaddd	%ymm6,%ymm5,%ymm5
+	vpaddd	%ymm10,%ymm8,%ymm8
+	vpaddd	%ymm10,%ymm9,%ymm9
+	vpaddd	%ymm11,%ymm12,%ymm12
+	vpaddd	%ymm15,%ymm13,%ymm13
+	vperm2i128	$0x02,%ymm0,%ymm4,%ymm3
+
+	vpand	.clamp(%rip),%ymm3,%ymm3
+	vmovdqa	%ymm3,0(%rbp)
+
+	vperm2i128	$0x13,%ymm0,%ymm4,%ymm0
+	vperm2i128	$0x13,%ymm8,%ymm12,%ymm4
+	vperm2i128	$0x02,%ymm1,%ymm5,%ymm8
+	vperm2i128	$0x02,%ymm9,%ymm13,%ymm12
+	vperm2i128	$0x13,%ymm1,%ymm5,%ymm1
+	vperm2i128	$0x13,%ymm9,%ymm13,%ymm5
+seal_avx2_short:
+	movq	%r8,%r8
+	call	poly_hash_ad_internal
+	xorq	%rcx,%rcx
+seal_avx2_hash:
+	cmpq	$16,%rcx
+	jb	seal_avx2_short_loop
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	subq	$16,%rcx
+	addq	$16,%rdi
+	jmp	seal_avx2_hash
+seal_avx2_short_loop:
+	cmpq	$32,%rbx
+	jb	seal_avx2_short_tail
+	subq	$32,%rbx
+
+	vpxor	(%rsi),%ymm0,%ymm0
+	vmovdqu	%ymm0,(%rdi)
+	leaq	32(%rsi),%rsi
+
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+	addq	16(%rdi),%r10
+	adcq	8+16(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	32(%rdi),%rdi
+
+	vmovdqa	%ymm4,%ymm0
+	vmovdqa	%ymm8,%ymm4
+	vmovdqa	%ymm12,%ymm8
+	vmovdqa	%ymm1,%ymm12
+	vmovdqa	%ymm5,%ymm1
+	vmovdqa	%ymm9,%ymm5
+	vmovdqa	%ymm13,%ymm9
+	vmovdqa	%ymm2,%ymm13
+	vmovdqa	%ymm6,%ymm2
+	jmp	seal_avx2_short_loop
+seal_avx2_short_tail:
+	cmpq	$16,%rbx
+	jb	1f
+	subq	$16,%rbx
+	vpxor	(%rsi),%xmm0,%xmm3
+	vmovdqu	%xmm3,(%rdi)
+	leaq	16(%rsi),%rsi
+	addq	0(%rdi),%r10
+	adcq	8+0(%rdi),%r11
+	adcq	$1,%r12
+	movq	0+0(%rbp),%rax
+	movq	%rax,%r15
+	mulq	%r10
+	movq	%rax,%r13
+	movq	%rdx,%r14
+	movq	0+0(%rbp),%rax
+	mulq	%r11
+	imulq	%r12,%r15
+	addq	%rax,%r14
+	adcq	%rdx,%r15
+	movq	8+0(%rbp),%rax
+	movq	%rax,%r9
+	mulq	%r10
+	addq	%rax,%r14
+	adcq	$0,%rdx
+	movq	%rdx,%r10
+	movq	8+0(%rbp),%rax
+	mulq	%r11
+	addq	%rax,%r15
+	adcq	$0,%rdx
+	imulq	%r12,%r9
+	addq	%r10,%r15
+	adcq	%rdx,%r9
+	movq	%r13,%r10
+	movq	%r14,%r11
+	movq	%r15,%r12
+	andq	$3,%r12
+	movq	%r15,%r13
+	andq	$-4,%r13
+	movq	%r9,%r14
+	shrdq	$2,%r9,%r15
+	shrq	$2,%r9
+	addq	%r13,%r10
+	adcq	%r14,%r11
+	adcq	$0,%r12
+	addq	%r15,%r10
+	adcq	%r9,%r11
+	adcq	$0,%r12
+
+	leaq	16(%rdi),%rdi
+	vextracti128	$1,%ymm0,%xmm0
+1:
+	vzeroupper
+	jmp	seal_sse_tail_16
+
+#endif
diff --git a/mac-x86_64/crypto/ec/p256-x86_64-asm.S b/mac-x86_64/crypto/ec/p256-x86_64-asm.S
index bed1130..aa434bf 100644
--- a/mac-x86_64/crypto/ec/p256-x86_64-asm.S
+++ b/mac-x86_64/crypto/ec/p256-x86_64-asm.S
@@ -17,47 +17,6 @@
 .quad	0x0000000000000001, 0xffffffff00000000, 0xffffffffffffffff, 0x00000000fffffffe
 
 
-.p2align	6
-ecp_nistz256_mul_by_2:
-	pushq	%r12
-	pushq	%r13
-
-	movq	0(%rsi),%r8
-	movq	8(%rsi),%r9
-	addq	%r8,%r8
-	movq	16(%rsi),%r10
-	adcq	%r9,%r9
-	movq	24(%rsi),%r11
-	leaq	L$poly(%rip),%rsi
-	movq	%r8,%rax
-	adcq	%r10,%r10
-	adcq	%r11,%r11
-	movq	%r9,%rdx
-	sbbq	%r13,%r13
-
-	subq	0(%rsi),%r8
-	movq	%r10,%rcx
-	sbbq	8(%rsi),%r9
-	sbbq	16(%rsi),%r10
-	movq	%r11,%r12
-	sbbq	24(%rsi),%r11
-	testq	%r13,%r13
-
-	cmovzq	%rax,%r8
-	cmovzq	%rdx,%r9
-	movq	%r8,0(%rdi)
-	cmovzq	%rcx,%r10
-	movq	%r9,8(%rdi)
-	cmovzq	%r12,%r11
-	movq	%r10,16(%rdi)
-	movq	%r11,24(%rdi)
-
-	popq	%r13
-	popq	%r12
-	.byte	0xf3,0xc3
-
-
-
 
 .globl	_ecp_nistz256_neg
 .private_extern _ecp_nistz256_neg
@@ -552,101 +511,6 @@
 
 
 
-
-
-
-
-.globl	_ecp_nistz256_from_mont
-.private_extern _ecp_nistz256_from_mont
-
-.p2align	5
-_ecp_nistz256_from_mont:
-	pushq	%r12
-	pushq	%r13
-
-	movq	0(%rsi),%rax
-	movq	L$poly+24(%rip),%r13
-	movq	8(%rsi),%r9
-	movq	16(%rsi),%r10
-	movq	24(%rsi),%r11
-	movq	%rax,%r8
-	movq	L$poly+8(%rip),%r12
-
-
-
-	movq	%rax,%rcx
-	shlq	$32,%r8
-	mulq	%r13
-	shrq	$32,%rcx
-	addq	%r8,%r9
-	adcq	%rcx,%r10
-	adcq	%rax,%r11
-	movq	%r9,%rax
-	adcq	$0,%rdx
-
-
-
-	movq	%r9,%rcx
-	shlq	$32,%r9
-	movq	%rdx,%r8
-	mulq	%r13
-	shrq	$32,%rcx
-	addq	%r9,%r10
-	adcq	%rcx,%r11
-	adcq	%rax,%r8
-	movq	%r10,%rax
-	adcq	$0,%rdx
-
-
-
-	movq	%r10,%rcx
-	shlq	$32,%r10
-	movq	%rdx,%r9
-	mulq	%r13
-	shrq	$32,%rcx
-	addq	%r10,%r11
-	adcq	%rcx,%r8
-	adcq	%rax,%r9
-	movq	%r11,%rax
-	adcq	$0,%rdx
-
-
-
-	movq	%r11,%rcx
-	shlq	$32,%r11
-	movq	%rdx,%r10
-	mulq	%r13
-	shrq	$32,%rcx
-	addq	%r11,%r8
-	adcq	%rcx,%r9
-	movq	%r8,%rcx
-	adcq	%rax,%r10
-	movq	%r9,%rsi
-	adcq	$0,%rdx
-
-	subq	$-1,%r8
-	movq	%r10,%rax
-	sbbq	%r12,%r9
-	sbbq	$0,%r10
-	movq	%rdx,%r11
-	sbbq	%r13,%rdx
-	sbbq	%r13,%r13
-
-	cmovnzq	%rcx,%r8
-	cmovnzq	%rsi,%r9
-	movq	%r8,0(%rdi)
-	cmovnzq	%rax,%r10
-	movq	%r9,8(%rdi)
-	cmovzq	%rdx,%r11
-	movq	%r10,16(%rdi)
-	movq	%r11,24(%rdi)
-
-	popq	%r13
-	popq	%r12
-	.byte	0xf3,0xc3
-
-
-
 .globl	_ecp_nistz256_select_w5
 .private_extern _ecp_nistz256_select_w5
 
@@ -764,13 +628,14 @@
 
 .p2align	5
 __ecp_nistz256_add_toq:
+	xorq	%r11,%r11
 	addq	0(%rbx),%r12
 	adcq	8(%rbx),%r13
 	movq	%r12,%rax
 	adcq	16(%rbx),%r8
 	adcq	24(%rbx),%r9
 	movq	%r13,%rbp
-	sbbq	%r11,%r11
+	adcq	$0,%r11
 
 	subq	$-1,%r12
 	movq	%r8,%rcx
@@ -778,14 +643,14 @@
 	sbbq	$0,%r8
 	movq	%r9,%r10
 	sbbq	%r15,%r9
-	testq	%r11,%r11
+	sbbq	$0,%r11
 
-	cmovzq	%rax,%r12
-	cmovzq	%rbp,%r13
+	cmovcq	%rax,%r12
+	cmovcq	%rbp,%r13
 	movq	%r12,0(%rdi)
-	cmovzq	%rcx,%r8
+	cmovcq	%rcx,%r8
 	movq	%r13,8(%rdi)
-	cmovzq	%r10,%r9
+	cmovcq	%r10,%r9
 	movq	%r8,16(%rdi)
 	movq	%r9,24(%rdi)
 
@@ -853,13 +718,14 @@
 
 .p2align	5
 __ecp_nistz256_mul_by_2q:
+	xorq	%r11,%r11
 	addq	%r12,%r12
 	adcq	%r13,%r13
 	movq	%r12,%rax
 	adcq	%r8,%r8
 	adcq	%r9,%r9
 	movq	%r13,%rbp
-	sbbq	%r11,%r11
+	adcq	$0,%r11
 
 	subq	$-1,%r12
 	movq	%r8,%rcx
@@ -867,14 +733,14 @@
 	sbbq	$0,%r8
 	movq	%r9,%r10
 	sbbq	%r15,%r9
-	testq	%r11,%r11
+	sbbq	$0,%r11
 
-	cmovzq	%rax,%r12
-	cmovzq	%rbp,%r13
+	cmovcq	%rax,%r12
+	cmovcq	%rbp,%r13
 	movq	%r12,0(%rdi)
-	cmovzq	%rcx,%r8
+	cmovcq	%rcx,%r8
 	movq	%r13,8(%rdi)
-	cmovzq	%r10,%r9
+	cmovcq	%r10,%r9
 	movq	%r8,16(%rdi)
 	movq	%r9,24(%rdi)
 
@@ -893,6 +759,7 @@
 	pushq	%r15
 	subq	$160+8,%rsp
 
+L$point_double_shortcutq:
 	movdqu	0(%rsi),%xmm0
 	movq	%rsi,%rbx
 	movdqu	16(%rsi),%xmm1
@@ -1105,16 +972,14 @@
 	movq	%rdx,%rsi
 	movdqa	%xmm0,384(%rsp)
 	movdqa	%xmm1,384+16(%rsp)
-	por	%xmm0,%xmm1
 	movdqa	%xmm2,416(%rsp)
 	movdqa	%xmm3,416+16(%rsp)
-	por	%xmm2,%xmm3
 	movdqa	%xmm4,448(%rsp)
 	movdqa	%xmm5,448+16(%rsp)
-	por	%xmm1,%xmm3
+	por	%xmm4,%xmm5
 
 	movdqu	0(%rsi),%xmm0
-	pshufd	$177,%xmm3,%xmm5
+	pshufd	$0xb1,%xmm5,%xmm3
 	movdqu	16(%rsi),%xmm1
 	movdqu	32(%rsi),%xmm2
 	por	%xmm3,%xmm5
@@ -1124,16 +989,16 @@
 	movq	64+16(%rsi),%r15
 	movq	64+24(%rsi),%r8
 	movdqa	%xmm0,480(%rsp)
-	pshufd	$30,%xmm5,%xmm4
+	pshufd	$0x1e,%xmm5,%xmm4
 	movdqa	%xmm1,480+16(%rsp)
-	por	%xmm0,%xmm1
-.byte	102,72,15,110,199
+	movdqu	64(%rsi),%xmm0
+	movdqu	80(%rsi),%xmm1
 	movdqa	%xmm2,512(%rsp)
 	movdqa	%xmm3,512+16(%rsp)
-	por	%xmm2,%xmm3
 	por	%xmm4,%xmm5
 	pxor	%xmm4,%xmm4
-	por	%xmm1,%xmm3
+	por	%xmm0,%xmm1
+.byte	102,72,15,110,199
 
 	leaq	64-0(%rsi),%rsi
 	movq	%rax,544+0(%rsp)
@@ -1144,10 +1009,10 @@
 	call	__ecp_nistz256_sqr_montq
 
 	pcmpeqd	%xmm4,%xmm5
-	pshufd	$177,%xmm3,%xmm4
-	por	%xmm3,%xmm4
+	pshufd	$0xb1,%xmm1,%xmm4
+	por	%xmm1,%xmm4
 	pshufd	$0,%xmm5,%xmm5
-	pshufd	$30,%xmm4,%xmm3
+	pshufd	$0x1e,%xmm4,%xmm3
 	por	%xmm3,%xmm4
 	pxor	%xmm3,%xmm3
 	pcmpeqd	%xmm3,%xmm4
@@ -1156,6 +1021,7 @@
 	movq	64+8(%rbx),%r14
 	movq	64+16(%rbx),%r15
 	movq	64+24(%rbx),%r8
+.byte	102,72,15,110,203
 
 	leaq	64-0(%rbx),%rsi
 	leaq	32(%rsp),%rdi
@@ -1247,7 +1113,7 @@
 	testq	%r8,%r8
 	jnz	L$add_proceedq
 	testq	%r9,%r9
-	jz	L$add_proceedq
+	jz	L$add_doubleq
 
 .byte	102,72,15,126,199
 	pxor	%xmm0,%xmm0
@@ -1260,6 +1126,13 @@
 	jmp	L$add_doneq
 
 .p2align	5
+L$add_doubleq:
+.byte	102,72,15,126,206
+.byte	102,72,15,126,199
+	addq	$416,%rsp
+	jmp	L$point_double_shortcutq
+
+.p2align	5
 L$add_proceedq:
 	movq	0+64(%rsp),%rax
 	movq	8+64(%rsp),%r14
@@ -1320,6 +1193,7 @@
 
 
 
+	xorq	%r11,%r11
 	addq	%r12,%r12
 	leaq	96(%rsp),%rsi
 	adcq	%r13,%r13
@@ -1327,7 +1201,7 @@
 	adcq	%r8,%r8
 	adcq	%r9,%r9
 	movq	%r13,%rbp
-	sbbq	%r11,%r11
+	adcq	$0,%r11
 
 	subq	$-1,%r12
 	movq	%r8,%rcx
@@ -1335,15 +1209,15 @@
 	sbbq	$0,%r8
 	movq	%r9,%r10
 	sbbq	%r15,%r9
-	testq	%r11,%r11
+	sbbq	$0,%r11
 
-	cmovzq	%rax,%r12
+	cmovcq	%rax,%r12
 	movq	0(%rsi),%rax
-	cmovzq	%rbp,%r13
+	cmovcq	%rbp,%r13
 	movq	8(%rsi),%rbp
-	cmovzq	%rcx,%r8
+	cmovcq	%rcx,%r8
 	movq	16(%rsi),%rcx
-	cmovzq	%r10,%r9
+	cmovcq	%r10,%r9
 	movq	24(%rsi),%r10
 
 	call	__ecp_nistz256_subq
@@ -1498,22 +1372,20 @@
 	movq	64+24(%rsi),%r8
 	movdqa	%xmm0,320(%rsp)
 	movdqa	%xmm1,320+16(%rsp)
-	por	%xmm0,%xmm1
 	movdqa	%xmm2,352(%rsp)
 	movdqa	%xmm3,352+16(%rsp)
-	por	%xmm2,%xmm3
 	movdqa	%xmm4,384(%rsp)
 	movdqa	%xmm5,384+16(%rsp)
-	por	%xmm1,%xmm3
+	por	%xmm4,%xmm5
 
 	movdqu	0(%rbx),%xmm0
-	pshufd	$177,%xmm3,%xmm5
+	pshufd	$0xb1,%xmm5,%xmm3
 	movdqu	16(%rbx),%xmm1
 	movdqu	32(%rbx),%xmm2
 	por	%xmm3,%xmm5
 	movdqu	48(%rbx),%xmm3
 	movdqa	%xmm0,416(%rsp)
-	pshufd	$30,%xmm5,%xmm4
+	pshufd	$0x1e,%xmm5,%xmm4
 	movdqa	%xmm1,416+16(%rsp)
 	por	%xmm0,%xmm1
 .byte	102,72,15,110,199
@@ -1529,13 +1401,13 @@
 	call	__ecp_nistz256_sqr_montq
 
 	pcmpeqd	%xmm4,%xmm5
-	pshufd	$177,%xmm3,%xmm4
+	pshufd	$0xb1,%xmm3,%xmm4
 	movq	0(%rbx),%rax
 
 	movq	%r12,%r9
 	por	%xmm3,%xmm4
 	pshufd	$0,%xmm5,%xmm5
-	pshufd	$30,%xmm4,%xmm3
+	pshufd	$0x1e,%xmm4,%xmm3
 	movq	%r13,%r10
 	por	%xmm3,%xmm4
 	pxor	%xmm3,%xmm3
@@ -1625,6 +1497,7 @@
 
 
 
+	xorq	%r11,%r11
 	addq	%r12,%r12
 	leaq	192(%rsp),%rsi
 	adcq	%r13,%r13
@@ -1632,7 +1505,7 @@
 	adcq	%r8,%r8
 	adcq	%r9,%r9
 	movq	%r13,%rbp
-	sbbq	%r11,%r11
+	adcq	$0,%r11
 
 	subq	$-1,%r12
 	movq	%r8,%rcx
@@ -1640,15 +1513,15 @@
 	sbbq	$0,%r8
 	movq	%r9,%r10
 	sbbq	%r15,%r9
-	testq	%r11,%r11
+	sbbq	$0,%r11
 
-	cmovzq	%rax,%r12
+	cmovcq	%rax,%r12
 	movq	0(%rsi),%rax
-	cmovzq	%rbp,%r13
+	cmovcq	%rbp,%r13
 	movq	8(%rsi),%rbp
-	cmovzq	%rcx,%r8
+	cmovcq	%rcx,%r8
 	movq	16(%rsi),%rcx
-	cmovzq	%r10,%r9
+	cmovcq	%r10,%r9
 	movq	24(%rsi),%r10
 
 	call	__ecp_nistz256_subq
diff --git a/mac-x86_64/crypto/md5/md5-x86_64.S b/mac-x86_64/crypto/md5/md5-x86_64.S
index 1e61479..16fd2cc 100644
--- a/mac-x86_64/crypto/md5/md5-x86_64.S
+++ b/mac-x86_64/crypto/md5/md5-x86_64.S
@@ -495,14 +495,14 @@
 	movl	%ecx,%r11d
 	addl	%ecx,%ebx
 	movl	0(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	xorl	%edx,%r11d
 	leal	-198630844(%rax,%r10,1),%eax
 	orl	%ebx,%r11d
 	xorl	%ecx,%r11d
 	addl	%r11d,%eax
 	movl	28(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	roll	$6,%eax
 	xorl	%ecx,%r11d
 	addl	%ebx,%eax
@@ -511,7 +511,7 @@
 	xorl	%ebx,%r11d
 	addl	%r11d,%edx
 	movl	56(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	roll	$10,%edx
 	xorl	%ebx,%r11d
 	addl	%eax,%edx
@@ -520,7 +520,7 @@
 	xorl	%eax,%r11d
 	addl	%r11d,%ecx
 	movl	20(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	roll	$15,%ecx
 	xorl	%eax,%r11d
 	addl	%edx,%ecx
@@ -529,7 +529,7 @@
 	xorl	%edx,%r11d
 	addl	%r11d,%ebx
 	movl	48(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	roll	$21,%ebx
 	xorl	%edx,%r11d
 	addl	%ecx,%ebx
@@ -538,7 +538,7 @@
 	xorl	%ecx,%r11d
 	addl	%r11d,%eax
 	movl	12(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	roll	$6,%eax
 	xorl	%ecx,%r11d
 	addl	%ebx,%eax
@@ -547,7 +547,7 @@
 	xorl	%ebx,%r11d
 	addl	%r11d,%edx
 	movl	40(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	roll	$10,%edx
 	xorl	%ebx,%r11d
 	addl	%eax,%edx
@@ -556,7 +556,7 @@
 	xorl	%eax,%r11d
 	addl	%r11d,%ecx
 	movl	4(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	roll	$15,%ecx
 	xorl	%eax,%r11d
 	addl	%edx,%ecx
@@ -565,7 +565,7 @@
 	xorl	%edx,%r11d
 	addl	%r11d,%ebx
 	movl	32(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	roll	$21,%ebx
 	xorl	%edx,%r11d
 	addl	%ecx,%ebx
@@ -574,7 +574,7 @@
 	xorl	%ecx,%r11d
 	addl	%r11d,%eax
 	movl	60(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	roll	$6,%eax
 	xorl	%ecx,%r11d
 	addl	%ebx,%eax
@@ -583,7 +583,7 @@
 	xorl	%ebx,%r11d
 	addl	%r11d,%edx
 	movl	24(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	roll	$10,%edx
 	xorl	%ebx,%r11d
 	addl	%eax,%edx
@@ -592,7 +592,7 @@
 	xorl	%eax,%r11d
 	addl	%r11d,%ecx
 	movl	52(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	roll	$15,%ecx
 	xorl	%eax,%r11d
 	addl	%edx,%ecx
@@ -601,7 +601,7 @@
 	xorl	%edx,%r11d
 	addl	%r11d,%ebx
 	movl	16(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	roll	$21,%ebx
 	xorl	%edx,%r11d
 	addl	%ecx,%ebx
@@ -610,7 +610,7 @@
 	xorl	%ecx,%r11d
 	addl	%r11d,%eax
 	movl	44(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	roll	$6,%eax
 	xorl	%ecx,%r11d
 	addl	%ebx,%eax
@@ -619,7 +619,7 @@
 	xorl	%ebx,%r11d
 	addl	%r11d,%edx
 	movl	8(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	roll	$10,%edx
 	xorl	%ebx,%r11d
 	addl	%eax,%edx
@@ -628,7 +628,7 @@
 	xorl	%eax,%r11d
 	addl	%r11d,%ecx
 	movl	36(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	roll	$15,%ecx
 	xorl	%eax,%r11d
 	addl	%edx,%ecx
@@ -637,7 +637,7 @@
 	xorl	%edx,%r11d
 	addl	%r11d,%ebx
 	movl	0(%rsi),%r10d
-	movl	$4294967295,%r11d
+	movl	$0xffffffff,%r11d
 	roll	$21,%ebx
 	xorl	%edx,%r11d
 	addl	%ecx,%ebx
diff --git a/mac-x86_64/crypto/modes/aesni-gcm-x86_64.S b/mac-x86_64/crypto/modes/aesni-gcm-x86_64.S
index 21d5ad6..901bb96 100644
--- a/mac-x86_64/crypto/modes/aesni-gcm-x86_64.S
+++ b/mac-x86_64/crypto/modes/aesni-gcm-x86_64.S
@@ -1,19 +1,798 @@
 #if defined(__x86_64__)
 .text	
 
-.globl	_aesni_gcm_encrypt
-.private_extern _aesni_gcm_encrypt
 
-_aesni_gcm_encrypt:
-	xorl	%eax,%eax
+.p2align	5
+_aesni_ctr32_ghash_6x:
+	vmovdqu	32(%r11),%xmm2
+	subq	$6,%rdx
+	vpxor	%xmm4,%xmm4,%xmm4
+	vmovdqu	0-128(%rcx),%xmm15
+	vpaddb	%xmm2,%xmm1,%xmm10
+	vpaddb	%xmm2,%xmm10,%xmm11
+	vpaddb	%xmm2,%xmm11,%xmm12
+	vpaddb	%xmm2,%xmm12,%xmm13
+	vpaddb	%xmm2,%xmm13,%xmm14
+	vpxor	%xmm15,%xmm1,%xmm9
+	vmovdqu	%xmm4,16+8(%rsp)
+	jmp	L$oop6x
+
+.p2align	5
+L$oop6x:
+	addl	$100663296,%ebx
+	jc	L$handle_ctr32
+	vmovdqu	0-32(%r9),%xmm3
+	vpaddb	%xmm2,%xmm14,%xmm1
+	vpxor	%xmm15,%xmm10,%xmm10
+	vpxor	%xmm15,%xmm11,%xmm11
+
+L$resume_ctr32:
+	vmovdqu	%xmm1,(%r8)
+	vpclmulqdq	$0x10,%xmm3,%xmm7,%xmm5
+	vpxor	%xmm15,%xmm12,%xmm12
+	vmovups	16-128(%rcx),%xmm2
+	vpclmulqdq	$0x01,%xmm3,%xmm7,%xmm6
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+	xorq	%r12,%r12
+	cmpq	%r14,%r15
+
+	vaesenc	%xmm2,%xmm9,%xmm9
+	vmovdqu	48+8(%rsp),%xmm0
+	vpxor	%xmm15,%xmm13,%xmm13
+	vpclmulqdq	$0x00,%xmm3,%xmm7,%xmm1
+	vaesenc	%xmm2,%xmm10,%xmm10
+	vpxor	%xmm15,%xmm14,%xmm14
+	setnc	%r12b
+	vpclmulqdq	$0x11,%xmm3,%xmm7,%xmm7
+	vaesenc	%xmm2,%xmm11,%xmm11
+	vmovdqu	16-32(%r9),%xmm3
+	negq	%r12
+	vaesenc	%xmm2,%xmm12,%xmm12
+	vpxor	%xmm5,%xmm6,%xmm6
+	vpclmulqdq	$0x00,%xmm3,%xmm0,%xmm5
+	vpxor	%xmm4,%xmm8,%xmm8
+	vaesenc	%xmm2,%xmm13,%xmm13
+	vpxor	%xmm5,%xmm1,%xmm4
+	andq	$0x60,%r12
+	vmovups	32-128(%rcx),%xmm15
+	vpclmulqdq	$0x10,%xmm3,%xmm0,%xmm1
+	vaesenc	%xmm2,%xmm14,%xmm14
+
+	vpclmulqdq	$0x01,%xmm3,%xmm0,%xmm2
+	leaq	(%r14,%r12,1),%r14
+	vaesenc	%xmm15,%xmm9,%xmm9
+	vpxor	16+8(%rsp),%xmm8,%xmm8
+	vpclmulqdq	$0x11,%xmm3,%xmm0,%xmm3
+	vmovdqu	64+8(%rsp),%xmm0
+	vaesenc	%xmm15,%xmm10,%xmm10
+	movbeq	88(%r14),%r13
+	vaesenc	%xmm15,%xmm11,%xmm11
+	movbeq	80(%r14),%r12
+	vaesenc	%xmm15,%xmm12,%xmm12
+	movq	%r13,32+8(%rsp)
+	vaesenc	%xmm15,%xmm13,%xmm13
+	movq	%r12,40+8(%rsp)
+	vmovdqu	48-32(%r9),%xmm5
+	vaesenc	%xmm15,%xmm14,%xmm14
+
+	vmovups	48-128(%rcx),%xmm15
+	vpxor	%xmm1,%xmm6,%xmm6
+	vpclmulqdq	$0x00,%xmm5,%xmm0,%xmm1
+	vaesenc	%xmm15,%xmm9,%xmm9
+	vpxor	%xmm2,%xmm6,%xmm6
+	vpclmulqdq	$0x10,%xmm5,%xmm0,%xmm2
+	vaesenc	%xmm15,%xmm10,%xmm10
+	vpxor	%xmm3,%xmm7,%xmm7
+	vpclmulqdq	$0x01,%xmm5,%xmm0,%xmm3
+	vaesenc	%xmm15,%xmm11,%xmm11
+	vpclmulqdq	$0x11,%xmm5,%xmm0,%xmm5
+	vmovdqu	80+8(%rsp),%xmm0
+	vaesenc	%xmm15,%xmm12,%xmm12
+	vaesenc	%xmm15,%xmm13,%xmm13
+	vpxor	%xmm1,%xmm4,%xmm4
+	vmovdqu	64-32(%r9),%xmm1
+	vaesenc	%xmm15,%xmm14,%xmm14
+
+	vmovups	64-128(%rcx),%xmm15
+	vpxor	%xmm2,%xmm6,%xmm6
+	vpclmulqdq	$0x00,%xmm1,%xmm0,%xmm2
+	vaesenc	%xmm15,%xmm9,%xmm9
+	vpxor	%xmm3,%xmm6,%xmm6
+	vpclmulqdq	$0x10,%xmm1,%xmm0,%xmm3
+	vaesenc	%xmm15,%xmm10,%xmm10
+	movbeq	72(%r14),%r13
+	vpxor	%xmm5,%xmm7,%xmm7
+	vpclmulqdq	$0x01,%xmm1,%xmm0,%xmm5
+	vaesenc	%xmm15,%xmm11,%xmm11
+	movbeq	64(%r14),%r12
+	vpclmulqdq	$0x11,%xmm1,%xmm0,%xmm1
+	vmovdqu	96+8(%rsp),%xmm0
+	vaesenc	%xmm15,%xmm12,%xmm12
+	movq	%r13,48+8(%rsp)
+	vaesenc	%xmm15,%xmm13,%xmm13
+	movq	%r12,56+8(%rsp)
+	vpxor	%xmm2,%xmm4,%xmm4
+	vmovdqu	96-32(%r9),%xmm2
+	vaesenc	%xmm15,%xmm14,%xmm14
+
+	vmovups	80-128(%rcx),%xmm15
+	vpxor	%xmm3,%xmm6,%xmm6
+	vpclmulqdq	$0x00,%xmm2,%xmm0,%xmm3
+	vaesenc	%xmm15,%xmm9,%xmm9
+	vpxor	%xmm5,%xmm6,%xmm6
+	vpclmulqdq	$0x10,%xmm2,%xmm0,%xmm5
+	vaesenc	%xmm15,%xmm10,%xmm10
+	movbeq	56(%r14),%r13
+	vpxor	%xmm1,%xmm7,%xmm7
+	vpclmulqdq	$0x01,%xmm2,%xmm0,%xmm1
+	vpxor	112+8(%rsp),%xmm8,%xmm8
+	vaesenc	%xmm15,%xmm11,%xmm11
+	movbeq	48(%r14),%r12
+	vpclmulqdq	$0x11,%xmm2,%xmm0,%xmm2
+	vaesenc	%xmm15,%xmm12,%xmm12
+	movq	%r13,64+8(%rsp)
+	vaesenc	%xmm15,%xmm13,%xmm13
+	movq	%r12,72+8(%rsp)
+	vpxor	%xmm3,%xmm4,%xmm4
+	vmovdqu	112-32(%r9),%xmm3
+	vaesenc	%xmm15,%xmm14,%xmm14
+
+	vmovups	96-128(%rcx),%xmm15
+	vpxor	%xmm5,%xmm6,%xmm6
+	vpclmulqdq	$0x10,%xmm3,%xmm8,%xmm5
+	vaesenc	%xmm15,%xmm9,%xmm9
+	vpxor	%xmm1,%xmm6,%xmm6
+	vpclmulqdq	$0x01,%xmm3,%xmm8,%xmm1
+	vaesenc	%xmm15,%xmm10,%xmm10
+	movbeq	40(%r14),%r13
+	vpxor	%xmm2,%xmm7,%xmm7
+	vpclmulqdq	$0x00,%xmm3,%xmm8,%xmm2
+	vaesenc	%xmm15,%xmm11,%xmm11
+	movbeq	32(%r14),%r12
+	vpclmulqdq	$0x11,%xmm3,%xmm8,%xmm8
+	vaesenc	%xmm15,%xmm12,%xmm12
+	movq	%r13,80+8(%rsp)
+	vaesenc	%xmm15,%xmm13,%xmm13
+	movq	%r12,88+8(%rsp)
+	vpxor	%xmm5,%xmm6,%xmm6
+	vaesenc	%xmm15,%xmm14,%xmm14
+	vpxor	%xmm1,%xmm6,%xmm6
+
+	vmovups	112-128(%rcx),%xmm15
+	vpslldq	$8,%xmm6,%xmm5
+	vpxor	%xmm2,%xmm4,%xmm4
+	vmovdqu	16(%r11),%xmm3
+
+	vaesenc	%xmm15,%xmm9,%xmm9
+	vpxor	%xmm8,%xmm7,%xmm7
+	vaesenc	%xmm15,%xmm10,%xmm10
+	vpxor	%xmm5,%xmm4,%xmm4
+	movbeq	24(%r14),%r13
+	vaesenc	%xmm15,%xmm11,%xmm11
+	movbeq	16(%r14),%r12
+	vpalignr	$8,%xmm4,%xmm4,%xmm0
+	vpclmulqdq	$0x10,%xmm3,%xmm4,%xmm4
+	movq	%r13,96+8(%rsp)
+	vaesenc	%xmm15,%xmm12,%xmm12
+	movq	%r12,104+8(%rsp)
+	vaesenc	%xmm15,%xmm13,%xmm13
+	vmovups	128-128(%rcx),%xmm1
+	vaesenc	%xmm15,%xmm14,%xmm14
+
+	vaesenc	%xmm1,%xmm9,%xmm9
+	vmovups	144-128(%rcx),%xmm15
+	vaesenc	%xmm1,%xmm10,%xmm10
+	vpsrldq	$8,%xmm6,%xmm6
+	vaesenc	%xmm1,%xmm11,%xmm11
+	vpxor	%xmm6,%xmm7,%xmm7
+	vaesenc	%xmm1,%xmm12,%xmm12
+	vpxor	%xmm0,%xmm4,%xmm4
+	movbeq	8(%r14),%r13
+	vaesenc	%xmm1,%xmm13,%xmm13
+	movbeq	0(%r14),%r12
+	vaesenc	%xmm1,%xmm14,%xmm14
+	vmovups	160-128(%rcx),%xmm1
+	cmpl	$11,%ebp
+	jb	L$enc_tail
+
+	vaesenc	%xmm15,%xmm9,%xmm9
+	vaesenc	%xmm15,%xmm10,%xmm10
+	vaesenc	%xmm15,%xmm11,%xmm11
+	vaesenc	%xmm15,%xmm12,%xmm12
+	vaesenc	%xmm15,%xmm13,%xmm13
+	vaesenc	%xmm15,%xmm14,%xmm14
+
+	vaesenc	%xmm1,%xmm9,%xmm9
+	vaesenc	%xmm1,%xmm10,%xmm10
+	vaesenc	%xmm1,%xmm11,%xmm11
+	vaesenc	%xmm1,%xmm12,%xmm12
+	vaesenc	%xmm1,%xmm13,%xmm13
+	vmovups	176-128(%rcx),%xmm15
+	vaesenc	%xmm1,%xmm14,%xmm14
+	vmovups	192-128(%rcx),%xmm1
+	je	L$enc_tail
+
+	vaesenc	%xmm15,%xmm9,%xmm9
+	vaesenc	%xmm15,%xmm10,%xmm10
+	vaesenc	%xmm15,%xmm11,%xmm11
+	vaesenc	%xmm15,%xmm12,%xmm12
+	vaesenc	%xmm15,%xmm13,%xmm13
+	vaesenc	%xmm15,%xmm14,%xmm14
+
+	vaesenc	%xmm1,%xmm9,%xmm9
+	vaesenc	%xmm1,%xmm10,%xmm10
+	vaesenc	%xmm1,%xmm11,%xmm11
+	vaesenc	%xmm1,%xmm12,%xmm12
+	vaesenc	%xmm1,%xmm13,%xmm13
+	vmovups	208-128(%rcx),%xmm15
+	vaesenc	%xmm1,%xmm14,%xmm14
+	vmovups	224-128(%rcx),%xmm1
+	jmp	L$enc_tail
+
+.p2align	5
+L$handle_ctr32:
+	vmovdqu	(%r11),%xmm0
+	vpshufb	%xmm0,%xmm1,%xmm6
+	vmovdqu	48(%r11),%xmm5
+	vpaddd	64(%r11),%xmm6,%xmm10
+	vpaddd	%xmm5,%xmm6,%xmm11
+	vmovdqu	0-32(%r9),%xmm3
+	vpaddd	%xmm5,%xmm10,%xmm12
+	vpshufb	%xmm0,%xmm10,%xmm10
+	vpaddd	%xmm5,%xmm11,%xmm13
+	vpshufb	%xmm0,%xmm11,%xmm11
+	vpxor	%xmm15,%xmm10,%xmm10
+	vpaddd	%xmm5,%xmm12,%xmm14
+	vpshufb	%xmm0,%xmm12,%xmm12
+	vpxor	%xmm15,%xmm11,%xmm11
+	vpaddd	%xmm5,%xmm13,%xmm1
+	vpshufb	%xmm0,%xmm13,%xmm13
+	vpshufb	%xmm0,%xmm14,%xmm14
+	vpshufb	%xmm0,%xmm1,%xmm1
+	jmp	L$resume_ctr32
+
+.p2align	5
+L$enc_tail:
+	vaesenc	%xmm15,%xmm9,%xmm9
+	vmovdqu	%xmm7,16+8(%rsp)
+	vpalignr	$8,%xmm4,%xmm4,%xmm8
+	vaesenc	%xmm15,%xmm10,%xmm10
+	vpclmulqdq	$0x10,%xmm3,%xmm4,%xmm4
+	vpxor	0(%rdi),%xmm1,%xmm2
+	vaesenc	%xmm15,%xmm11,%xmm11
+	vpxor	16(%rdi),%xmm1,%xmm0
+	vaesenc	%xmm15,%xmm12,%xmm12
+	vpxor	32(%rdi),%xmm1,%xmm5
+	vaesenc	%xmm15,%xmm13,%xmm13
+	vpxor	48(%rdi),%xmm1,%xmm6
+	vaesenc	%xmm15,%xmm14,%xmm14
+	vpxor	64(%rdi),%xmm1,%xmm7
+	vpxor	80(%rdi),%xmm1,%xmm3
+	vmovdqu	(%r8),%xmm1
+
+	vaesenclast	%xmm2,%xmm9,%xmm9
+	vmovdqu	32(%r11),%xmm2
+	vaesenclast	%xmm0,%xmm10,%xmm10
+	vpaddb	%xmm2,%xmm1,%xmm0
+	movq	%r13,112+8(%rsp)
+	leaq	96(%rdi),%rdi
+	vaesenclast	%xmm5,%xmm11,%xmm11
+	vpaddb	%xmm2,%xmm0,%xmm5
+	movq	%r12,120+8(%rsp)
+	leaq	96(%rsi),%rsi
+	vmovdqu	0-128(%rcx),%xmm15
+	vaesenclast	%xmm6,%xmm12,%xmm12
+	vpaddb	%xmm2,%xmm5,%xmm6
+	vaesenclast	%xmm7,%xmm13,%xmm13
+	vpaddb	%xmm2,%xmm6,%xmm7
+	vaesenclast	%xmm3,%xmm14,%xmm14
+	vpaddb	%xmm2,%xmm7,%xmm3
+
+	addq	$0x60,%r10
+	subq	$0x6,%rdx
+	jc	L$6x_done
+
+	vmovups	%xmm9,-96(%rsi)
+	vpxor	%xmm15,%xmm1,%xmm9
+	vmovups	%xmm10,-80(%rsi)
+	vmovdqa	%xmm0,%xmm10
+	vmovups	%xmm11,-64(%rsi)
+	vmovdqa	%xmm5,%xmm11
+	vmovups	%xmm12,-48(%rsi)
+	vmovdqa	%xmm6,%xmm12
+	vmovups	%xmm13,-32(%rsi)
+	vmovdqa	%xmm7,%xmm13
+	vmovups	%xmm14,-16(%rsi)
+	vmovdqa	%xmm3,%xmm14
+	vmovdqu	32+8(%rsp),%xmm7
+	jmp	L$oop6x
+
+L$6x_done:
+	vpxor	16+8(%rsp),%xmm8,%xmm8
+	vpxor	%xmm4,%xmm8,%xmm8
+
 	.byte	0xf3,0xc3
 
-
 .globl	_aesni_gcm_decrypt
 .private_extern _aesni_gcm_decrypt
 
+.p2align	5
 _aesni_gcm_decrypt:
-	xorl	%eax,%eax
+	xorq	%r10,%r10
+
+
+
+	cmpq	$0x60,%rdx
+	jb	L$gcm_dec_abort
+
+	leaq	(%rsp),%rax
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	vzeroupper
+
+	vmovdqu	(%r8),%xmm1
+	addq	$-128,%rsp
+	movl	12(%r8),%ebx
+	leaq	L$bswap_mask(%rip),%r11
+	leaq	-128(%rcx),%r14
+	movq	$0xf80,%r15
+	vmovdqu	(%r9),%xmm8
+	andq	$-128,%rsp
+	vmovdqu	(%r11),%xmm0
+	leaq	128(%rcx),%rcx
+	leaq	32+32(%r9),%r9
+	movl	240-128(%rcx),%ebp
+	vpshufb	%xmm0,%xmm8,%xmm8
+
+	andq	%r15,%r14
+	andq	%rsp,%r15
+	subq	%r14,%r15
+	jc	L$dec_no_key_aliasing
+	cmpq	$768,%r15
+	jnc	L$dec_no_key_aliasing
+	subq	%r15,%rsp
+L$dec_no_key_aliasing:
+
+	vmovdqu	80(%rdi),%xmm7
+	leaq	(%rdi),%r14
+	vmovdqu	64(%rdi),%xmm4
+
+
+
+
+
+
+
+	leaq	-192(%rdi,%rdx,1),%r15
+
+	vmovdqu	48(%rdi),%xmm5
+	shrq	$4,%rdx
+	xorq	%r10,%r10
+	vmovdqu	32(%rdi),%xmm6
+	vpshufb	%xmm0,%xmm7,%xmm7
+	vmovdqu	16(%rdi),%xmm2
+	vpshufb	%xmm0,%xmm4,%xmm4
+	vmovdqu	(%rdi),%xmm3
+	vpshufb	%xmm0,%xmm5,%xmm5
+	vmovdqu	%xmm4,48(%rsp)
+	vpshufb	%xmm0,%xmm6,%xmm6
+	vmovdqu	%xmm5,64(%rsp)
+	vpshufb	%xmm0,%xmm2,%xmm2
+	vmovdqu	%xmm6,80(%rsp)
+	vpshufb	%xmm0,%xmm3,%xmm3
+	vmovdqu	%xmm2,96(%rsp)
+	vmovdqu	%xmm3,112(%rsp)
+
+	call	_aesni_ctr32_ghash_6x
+
+	vmovups	%xmm9,-96(%rsi)
+	vmovups	%xmm10,-80(%rsi)
+	vmovups	%xmm11,-64(%rsi)
+	vmovups	%xmm12,-48(%rsi)
+	vmovups	%xmm13,-32(%rsi)
+	vmovups	%xmm14,-16(%rsi)
+
+	vpshufb	(%r11),%xmm8,%xmm8
+	vmovdqu	%xmm8,-64(%r9)
+
+	vzeroupper
+	movq	-48(%rax),%r15
+	movq	-40(%rax),%r14
+	movq	-32(%rax),%r13
+	movq	-24(%rax),%r12
+	movq	-16(%rax),%rbp
+	movq	-8(%rax),%rbx
+	leaq	(%rax),%rsp
+L$gcm_dec_abort:
+	movq	%r10,%rax
 	.byte	0xf3,0xc3
 
+
+.p2align	5
+_aesni_ctr32_6x:
+	vmovdqu	0-128(%rcx),%xmm4
+	vmovdqu	32(%r11),%xmm2
+	leaq	-1(%rbp),%r13
+	vmovups	16-128(%rcx),%xmm15
+	leaq	32-128(%rcx),%r12
+	vpxor	%xmm4,%xmm1,%xmm9
+	addl	$100663296,%ebx
+	jc	L$handle_ctr32_2
+	vpaddb	%xmm2,%xmm1,%xmm10
+	vpaddb	%xmm2,%xmm10,%xmm11
+	vpxor	%xmm4,%xmm10,%xmm10
+	vpaddb	%xmm2,%xmm11,%xmm12
+	vpxor	%xmm4,%xmm11,%xmm11
+	vpaddb	%xmm2,%xmm12,%xmm13
+	vpxor	%xmm4,%xmm12,%xmm12
+	vpaddb	%xmm2,%xmm13,%xmm14
+	vpxor	%xmm4,%xmm13,%xmm13
+	vpaddb	%xmm2,%xmm14,%xmm1
+	vpxor	%xmm4,%xmm14,%xmm14
+	jmp	L$oop_ctr32
+
+.p2align	4
+L$oop_ctr32:
+	vaesenc	%xmm15,%xmm9,%xmm9
+	vaesenc	%xmm15,%xmm10,%xmm10
+	vaesenc	%xmm15,%xmm11,%xmm11
+	vaesenc	%xmm15,%xmm12,%xmm12
+	vaesenc	%xmm15,%xmm13,%xmm13
+	vaesenc	%xmm15,%xmm14,%xmm14
+	vmovups	(%r12),%xmm15
+	leaq	16(%r12),%r12
+	decl	%r13d
+	jnz	L$oop_ctr32
+
+	vmovdqu	(%r12),%xmm3
+	vaesenc	%xmm15,%xmm9,%xmm9
+	vpxor	0(%rdi),%xmm3,%xmm4
+	vaesenc	%xmm15,%xmm10,%xmm10
+	vpxor	16(%rdi),%xmm3,%xmm5
+	vaesenc	%xmm15,%xmm11,%xmm11
+	vpxor	32(%rdi),%xmm3,%xmm6
+	vaesenc	%xmm15,%xmm12,%xmm12
+	vpxor	48(%rdi),%xmm3,%xmm8
+	vaesenc	%xmm15,%xmm13,%xmm13
+	vpxor	64(%rdi),%xmm3,%xmm2
+	vaesenc	%xmm15,%xmm14,%xmm14
+	vpxor	80(%rdi),%xmm3,%xmm3
+	leaq	96(%rdi),%rdi
+
+	vaesenclast	%xmm4,%xmm9,%xmm9
+	vaesenclast	%xmm5,%xmm10,%xmm10
+	vaesenclast	%xmm6,%xmm11,%xmm11
+	vaesenclast	%xmm8,%xmm12,%xmm12
+	vaesenclast	%xmm2,%xmm13,%xmm13
+	vaesenclast	%xmm3,%xmm14,%xmm14
+	vmovups	%xmm9,0(%rsi)
+	vmovups	%xmm10,16(%rsi)
+	vmovups	%xmm11,32(%rsi)
+	vmovups	%xmm12,48(%rsi)
+	vmovups	%xmm13,64(%rsi)
+	vmovups	%xmm14,80(%rsi)
+	leaq	96(%rsi),%rsi
+
+	.byte	0xf3,0xc3
+.p2align	5
+L$handle_ctr32_2:
+	vpshufb	%xmm0,%xmm1,%xmm6
+	vmovdqu	48(%r11),%xmm5
+	vpaddd	64(%r11),%xmm6,%xmm10
+	vpaddd	%xmm5,%xmm6,%xmm11
+	vpaddd	%xmm5,%xmm10,%xmm12
+	vpshufb	%xmm0,%xmm10,%xmm10
+	vpaddd	%xmm5,%xmm11,%xmm13
+	vpshufb	%xmm0,%xmm11,%xmm11
+	vpxor	%xmm4,%xmm10,%xmm10
+	vpaddd	%xmm5,%xmm12,%xmm14
+	vpshufb	%xmm0,%xmm12,%xmm12
+	vpxor	%xmm4,%xmm11,%xmm11
+	vpaddd	%xmm5,%xmm13,%xmm1
+	vpshufb	%xmm0,%xmm13,%xmm13
+	vpxor	%xmm4,%xmm12,%xmm12
+	vpshufb	%xmm0,%xmm14,%xmm14
+	vpxor	%xmm4,%xmm13,%xmm13
+	vpshufb	%xmm0,%xmm1,%xmm1
+	vpxor	%xmm4,%xmm14,%xmm14
+	jmp	L$oop_ctr32
+
+
+.globl	_aesni_gcm_encrypt
+.private_extern _aesni_gcm_encrypt
+
+.p2align	5
+_aesni_gcm_encrypt:
+	xorq	%r10,%r10
+
+
+
+
+	cmpq	$288,%rdx
+	jb	L$gcm_enc_abort
+
+	leaq	(%rsp),%rax
+	pushq	%rbx
+	pushq	%rbp
+	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	vzeroupper
+
+	vmovdqu	(%r8),%xmm1
+	addq	$-128,%rsp
+	movl	12(%r8),%ebx
+	leaq	L$bswap_mask(%rip),%r11
+	leaq	-128(%rcx),%r14
+	movq	$0xf80,%r15
+	leaq	128(%rcx),%rcx
+	vmovdqu	(%r11),%xmm0
+	andq	$-128,%rsp
+	movl	240-128(%rcx),%ebp
+
+	andq	%r15,%r14
+	andq	%rsp,%r15
+	subq	%r14,%r15
+	jc	L$enc_no_key_aliasing
+	cmpq	$768,%r15
+	jnc	L$enc_no_key_aliasing
+	subq	%r15,%rsp
+L$enc_no_key_aliasing:
+
+	leaq	(%rsi),%r14
+
+
+
+
+
+
+
+
+	leaq	-192(%rsi,%rdx,1),%r15
+
+	shrq	$4,%rdx
+
+	call	_aesni_ctr32_6x
+	vpshufb	%xmm0,%xmm9,%xmm8
+	vpshufb	%xmm0,%xmm10,%xmm2
+	vmovdqu	%xmm8,112(%rsp)
+	vpshufb	%xmm0,%xmm11,%xmm4
+	vmovdqu	%xmm2,96(%rsp)
+	vpshufb	%xmm0,%xmm12,%xmm5
+	vmovdqu	%xmm4,80(%rsp)
+	vpshufb	%xmm0,%xmm13,%xmm6
+	vmovdqu	%xmm5,64(%rsp)
+	vpshufb	%xmm0,%xmm14,%xmm7
+	vmovdqu	%xmm6,48(%rsp)
+
+	call	_aesni_ctr32_6x
+
+	vmovdqu	(%r9),%xmm8
+	leaq	32+32(%r9),%r9
+	subq	$12,%rdx
+	movq	$192,%r10
+	vpshufb	%xmm0,%xmm8,%xmm8
+
+	call	_aesni_ctr32_ghash_6x
+	vmovdqu	32(%rsp),%xmm7
+	vmovdqu	(%r11),%xmm0
+	vmovdqu	0-32(%r9),%xmm3
+	vpunpckhqdq	%xmm7,%xmm7,%xmm1
+	vmovdqu	32-32(%r9),%xmm15
+	vmovups	%xmm9,-96(%rsi)
+	vpshufb	%xmm0,%xmm9,%xmm9
+	vpxor	%xmm7,%xmm1,%xmm1
+	vmovups	%xmm10,-80(%rsi)
+	vpshufb	%xmm0,%xmm10,%xmm10
+	vmovups	%xmm11,-64(%rsi)
+	vpshufb	%xmm0,%xmm11,%xmm11
+	vmovups	%xmm12,-48(%rsi)
+	vpshufb	%xmm0,%xmm12,%xmm12
+	vmovups	%xmm13,-32(%rsi)
+	vpshufb	%xmm0,%xmm13,%xmm13
+	vmovups	%xmm14,-16(%rsi)
+	vpshufb	%xmm0,%xmm14,%xmm14
+	vmovdqu	%xmm9,16(%rsp)
+	vmovdqu	48(%rsp),%xmm6
+	vmovdqu	16-32(%r9),%xmm0
+	vpunpckhqdq	%xmm6,%xmm6,%xmm2
+	vpclmulqdq	$0x00,%xmm3,%xmm7,%xmm5
+	vpxor	%xmm6,%xmm2,%xmm2
+	vpclmulqdq	$0x11,%xmm3,%xmm7,%xmm7
+	vpclmulqdq	$0x00,%xmm15,%xmm1,%xmm1
+
+	vmovdqu	64(%rsp),%xmm9
+	vpclmulqdq	$0x00,%xmm0,%xmm6,%xmm4
+	vmovdqu	48-32(%r9),%xmm3
+	vpxor	%xmm5,%xmm4,%xmm4
+	vpunpckhqdq	%xmm9,%xmm9,%xmm5
+	vpclmulqdq	$0x11,%xmm0,%xmm6,%xmm6
+	vpxor	%xmm9,%xmm5,%xmm5
+	vpxor	%xmm7,%xmm6,%xmm6
+	vpclmulqdq	$0x10,%xmm15,%xmm2,%xmm2
+	vmovdqu	80-32(%r9),%xmm15
+	vpxor	%xmm1,%xmm2,%xmm2
+
+	vmovdqu	80(%rsp),%xmm1
+	vpclmulqdq	$0x00,%xmm3,%xmm9,%xmm7
+	vmovdqu	64-32(%r9),%xmm0
+	vpxor	%xmm4,%xmm7,%xmm7
+	vpunpckhqdq	%xmm1,%xmm1,%xmm4
+	vpclmulqdq	$0x11,%xmm3,%xmm9,%xmm9
+	vpxor	%xmm1,%xmm4,%xmm4
+	vpxor	%xmm6,%xmm9,%xmm9
+	vpclmulqdq	$0x00,%xmm15,%xmm5,%xmm5
+	vpxor	%xmm2,%xmm5,%xmm5
+
+	vmovdqu	96(%rsp),%xmm2
+	vpclmulqdq	$0x00,%xmm0,%xmm1,%xmm6
+	vmovdqu	96-32(%r9),%xmm3
+	vpxor	%xmm7,%xmm6,%xmm6
+	vpunpckhqdq	%xmm2,%xmm2,%xmm7
+	vpclmulqdq	$0x11,%xmm0,%xmm1,%xmm1
+	vpxor	%xmm2,%xmm7,%xmm7
+	vpxor	%xmm9,%xmm1,%xmm1
+	vpclmulqdq	$0x10,%xmm15,%xmm4,%xmm4
+	vmovdqu	128-32(%r9),%xmm15
+	vpxor	%xmm5,%xmm4,%xmm4
+
+	vpxor	112(%rsp),%xmm8,%xmm8
+	vpclmulqdq	$0x00,%xmm3,%xmm2,%xmm5
+	vmovdqu	112-32(%r9),%xmm0
+	vpunpckhqdq	%xmm8,%xmm8,%xmm9
+	vpxor	%xmm6,%xmm5,%xmm5
+	vpclmulqdq	$0x11,%xmm3,%xmm2,%xmm2
+	vpxor	%xmm8,%xmm9,%xmm9
+	vpxor	%xmm1,%xmm2,%xmm2
+	vpclmulqdq	$0x00,%xmm15,%xmm7,%xmm7
+	vpxor	%xmm4,%xmm7,%xmm4
+
+	vpclmulqdq	$0x00,%xmm0,%xmm8,%xmm6
+	vmovdqu	0-32(%r9),%xmm3
+	vpunpckhqdq	%xmm14,%xmm14,%xmm1
+	vpclmulqdq	$0x11,%xmm0,%xmm8,%xmm8
+	vpxor	%xmm14,%xmm1,%xmm1
+	vpxor	%xmm5,%xmm6,%xmm5
+	vpclmulqdq	$0x10,%xmm15,%xmm9,%xmm9
+	vmovdqu	32-32(%r9),%xmm15
+	vpxor	%xmm2,%xmm8,%xmm7
+	vpxor	%xmm4,%xmm9,%xmm6
+
+	vmovdqu	16-32(%r9),%xmm0
+	vpxor	%xmm5,%xmm7,%xmm9
+	vpclmulqdq	$0x00,%xmm3,%xmm14,%xmm4
+	vpxor	%xmm9,%xmm6,%xmm6
+	vpunpckhqdq	%xmm13,%xmm13,%xmm2
+	vpclmulqdq	$0x11,%xmm3,%xmm14,%xmm14
+	vpxor	%xmm13,%xmm2,%xmm2
+	vpslldq	$8,%xmm6,%xmm9
+	vpclmulqdq	$0x00,%xmm15,%xmm1,%xmm1
+	vpxor	%xmm9,%xmm5,%xmm8
+	vpsrldq	$8,%xmm6,%xmm6
+	vpxor	%xmm6,%xmm7,%xmm7
+
+	vpclmulqdq	$0x00,%xmm0,%xmm13,%xmm5
+	vmovdqu	48-32(%r9),%xmm3
+	vpxor	%xmm4,%xmm5,%xmm5
+	vpunpckhqdq	%xmm12,%xmm12,%xmm9
+	vpclmulqdq	$0x11,%xmm0,%xmm13,%xmm13
+	vpxor	%xmm12,%xmm9,%xmm9
+	vpxor	%xmm14,%xmm13,%xmm13
+	vpalignr	$8,%xmm8,%xmm8,%xmm14
+	vpclmulqdq	$0x10,%xmm15,%xmm2,%xmm2
+	vmovdqu	80-32(%r9),%xmm15
+	vpxor	%xmm1,%xmm2,%xmm2
+
+	vpclmulqdq	$0x00,%xmm3,%xmm12,%xmm4
+	vmovdqu	64-32(%r9),%xmm0
+	vpxor	%xmm5,%xmm4,%xmm4
+	vpunpckhqdq	%xmm11,%xmm11,%xmm1
+	vpclmulqdq	$0x11,%xmm3,%xmm12,%xmm12
+	vpxor	%xmm11,%xmm1,%xmm1
+	vpxor	%xmm13,%xmm12,%xmm12
+	vxorps	16(%rsp),%xmm7,%xmm7
+	vpclmulqdq	$0x00,%xmm15,%xmm9,%xmm9
+	vpxor	%xmm2,%xmm9,%xmm9
+
+	vpclmulqdq	$0x10,16(%r11),%xmm8,%xmm8
+	vxorps	%xmm14,%xmm8,%xmm8
+
+	vpclmulqdq	$0x00,%xmm0,%xmm11,%xmm5
+	vmovdqu	96-32(%r9),%xmm3
+	vpxor	%xmm4,%xmm5,%xmm5
+	vpunpckhqdq	%xmm10,%xmm10,%xmm2
+	vpclmulqdq	$0x11,%xmm0,%xmm11,%xmm11
+	vpxor	%xmm10,%xmm2,%xmm2
+	vpalignr	$8,%xmm8,%xmm8,%xmm14
+	vpxor	%xmm12,%xmm11,%xmm11
+	vpclmulqdq	$0x10,%xmm15,%xmm1,%xmm1
+	vmovdqu	128-32(%r9),%xmm15
+	vpxor	%xmm9,%xmm1,%xmm1
+
+	vxorps	%xmm7,%xmm14,%xmm14
+	vpclmulqdq	$0x10,16(%r11),%xmm8,%xmm8
+	vxorps	%xmm14,%xmm8,%xmm8
+
+	vpclmulqdq	$0x00,%xmm3,%xmm10,%xmm4
+	vmovdqu	112-32(%r9),%xmm0
+	vpxor	%xmm5,%xmm4,%xmm4
+	vpunpckhqdq	%xmm8,%xmm8,%xmm9
+	vpclmulqdq	$0x11,%xmm3,%xmm10,%xmm10
+	vpxor	%xmm8,%xmm9,%xmm9
+	vpxor	%xmm11,%xmm10,%xmm10
+	vpclmulqdq	$0x00,%xmm15,%xmm2,%xmm2
+	vpxor	%xmm1,%xmm2,%xmm2
+
+	vpclmulqdq	$0x00,%xmm0,%xmm8,%xmm5
+	vpclmulqdq	$0x11,%xmm0,%xmm8,%xmm7
+	vpxor	%xmm4,%xmm5,%xmm5
+	vpclmulqdq	$0x10,%xmm15,%xmm9,%xmm6
+	vpxor	%xmm10,%xmm7,%xmm7
+	vpxor	%xmm2,%xmm6,%xmm6
+
+	vpxor	%xmm5,%xmm7,%xmm4
+	vpxor	%xmm4,%xmm6,%xmm6
+	vpslldq	$8,%xmm6,%xmm1
+	vmovdqu	16(%r11),%xmm3
+	vpsrldq	$8,%xmm6,%xmm6
+	vpxor	%xmm1,%xmm5,%xmm8
+	vpxor	%xmm6,%xmm7,%xmm7
+
+	vpalignr	$8,%xmm8,%xmm8,%xmm2
+	vpclmulqdq	$0x10,%xmm3,%xmm8,%xmm8
+	vpxor	%xmm2,%xmm8,%xmm8
+
+	vpalignr	$8,%xmm8,%xmm8,%xmm2
+	vpclmulqdq	$0x10,%xmm3,%xmm8,%xmm8
+	vpxor	%xmm7,%xmm2,%xmm2
+	vpxor	%xmm2,%xmm8,%xmm8
+	vpshufb	(%r11),%xmm8,%xmm8
+	vmovdqu	%xmm8,-64(%r9)
+
+	vzeroupper
+	movq	-48(%rax),%r15
+	movq	-40(%rax),%r14
+	movq	-32(%rax),%r13
+	movq	-24(%rax),%r12
+	movq	-16(%rax),%rbp
+	movq	-8(%rax),%rbx
+	leaq	(%rax),%rsp
+L$gcm_enc_abort:
+	movq	%r10,%rax
+	.byte	0xf3,0xc3
+
+.p2align	6
+L$bswap_mask:
+.byte	15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
+L$poly:
+.byte	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xc2
+L$one_msb:
+.byte	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
+L$two_lsb:
+.byte	2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+L$one_lsb:
+.byte	1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+.byte	65,69,83,45,78,73,32,71,67,77,32,109,111,100,117,108,101,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+.p2align	6
 #endif
diff --git a/mac-x86_64/crypto/modes/ghash-x86_64.S b/mac-x86_64/crypto/modes/ghash-x86_64.S
index 305a91c..814d796 100644
--- a/mac-x86_64/crypto/modes/ghash-x86_64.S
+++ b/mac-x86_64/crypto/modes/ghash-x86_64.S
@@ -10,6 +10,10 @@
 	pushq	%rbx
 	pushq	%rbp
 	pushq	%r12
+	pushq	%r13
+	pushq	%r14
+	pushq	%r15
+	subq	$280,%rsp
 L$gmult_prologue:
 
 	movzbq	15(%rdi),%r8
@@ -22,14 +26,14 @@
 	movq	$14,%rcx
 	movq	8(%rsi,%rax,1),%r8
 	movq	(%rsi,%rax,1),%r9
-	andb	$240,%bl
+	andb	$0xf0,%bl
 	movq	%r8,%rdx
 	jmp	L$oop1
 
 .p2align	4
 L$oop1:
 	shrq	$4,%r8
-	andq	$15,%rdx
+	andq	$0xf,%rdx
 	movq	%r9,%r10
 	movb	(%rdi,%rcx,1),%al
 	shrq	$4,%r9
@@ -45,13 +49,13 @@
 	js	L$break1
 
 	shrq	$4,%r8
-	andq	$15,%rdx
+	andq	$0xf,%rdx
 	movq	%r9,%r10
 	shrq	$4,%r9
 	xorq	8(%rsi,%rax,1),%r8
 	shlq	$60,%r10
 	xorq	(%rsi,%rax,1),%r9
-	andb	$240,%bl
+	andb	$0xf0,%bl
 	xorq	(%r11,%rdx,8),%r9
 	movq	%r8,%rdx
 	xorq	%r10,%r8
@@ -60,19 +64,19 @@
 .p2align	4
 L$break1:
 	shrq	$4,%r8
-	andq	$15,%rdx
+	andq	$0xf,%rdx
 	movq	%r9,%r10
 	shrq	$4,%r9
 	xorq	8(%rsi,%rax,1),%r8
 	shlq	$60,%r10
 	xorq	(%rsi,%rax,1),%r9
-	andb	$240,%bl
+	andb	$0xf0,%bl
 	xorq	(%r11,%rdx,8),%r9
 	movq	%r8,%rdx
 	xorq	%r10,%r8
 
 	shrq	$4,%r8
-	andq	$15,%rdx
+	andq	$0xf,%rdx
 	movq	%r9,%r10
 	shrq	$4,%r9
 	xorq	8(%rsi,%rbx,1),%r8
@@ -86,8 +90,9 @@
 	movq	%r8,8(%rdi)
 	movq	%r9,(%rdi)
 
-	movq	16(%rsp),%rbx
-	leaq	24(%rsp),%rsp
+	leaq	280+48(%rsp),%rsi
+	movq	-8(%rsi),%rbx
+	leaq	(%rsi),%rsp
 L$gmult_epilogue:
 	.byte	0xf3,0xc3
 
@@ -647,14 +652,14 @@
 	movq	%r8,8(%rdi)
 	movq	%r9,(%rdi)
 
-	leaq	280(%rsp),%rsi
-	movq	0(%rsi),%r15
-	movq	8(%rsi),%r14
-	movq	16(%rsi),%r13
-	movq	24(%rsi),%r12
-	movq	32(%rsi),%rbp
-	movq	40(%rsi),%rbx
-	leaq	48(%rsi),%rsp
+	leaq	280+48(%rsp),%rsi
+	movq	-48(%rsi),%r15
+	movq	-40(%rsi),%r14
+	movq	-32(%rsi),%r13
+	movq	-24(%rsi),%r12
+	movq	-16(%rsi),%rbp
+	movq	-8(%rsi),%rbx
+	leaq	0(%rsi),%rsp
 L$ghash_epilogue:
 	.byte	0xf3,0xc3
 
@@ -880,20 +885,20 @@
 	movdqu	32(%rsi),%xmm7
 .byte	102,65,15,56,0,194
 
-	subq	$16,%rcx
+	subq	$0x10,%rcx
 	jz	L$odd_tail
 
 	movdqu	16(%rsi),%xmm6
 	movl	_OPENSSL_ia32cap_P+4(%rip),%eax
-	cmpq	$48,%rcx
+	cmpq	$0x30,%rcx
 	jb	L$skip4x
 
 	andl	$71303168,%eax
 	cmpl	$4194304,%eax
 	je	L$skip4x
 
-	subq	$48,%rcx
-	movq	$11547335547999543296,%rax
+	subq	$0x30,%rcx
+	movq	$0xA040608020C0E000,%rax
 	movdqu	48(%rsi),%xmm14
 	movdqu	64(%rsi),%xmm15
 
@@ -940,7 +945,7 @@
 	xorps	%xmm13,%xmm5
 
 	leaq	64(%rdx),%rdx
-	subq	$64,%rcx
+	subq	$0x40,%rcx
 	jc	L$tail4x
 
 	jmp	L$mod4_loop
@@ -1023,7 +1028,7 @@
 	xorps	%xmm13,%xmm5
 
 	leaq	64(%rdx),%rdx
-	subq	$64,%rcx
+	subq	$0x40,%rcx
 	jnc	L$mod4_loop
 
 L$tail4x:
@@ -1067,10 +1072,10 @@
 	pxor	%xmm4,%xmm0
 	psrlq	$1,%xmm0
 	pxor	%xmm1,%xmm0
-	addq	$64,%rcx
+	addq	$0x40,%rcx
 	jz	L$done
 	movdqu	32(%rsi),%xmm7
-	subq	$16,%rcx
+	subq	$0x10,%rcx
 	jz	L$odd_tail
 L$skip4x:
 
@@ -1093,7 +1098,7 @@
 
 	leaq	32(%rdx),%rdx
 	nop
-	subq	$32,%rcx
+	subq	$0x20,%rcx
 	jbe	L$even_tail
 	nop
 	jmp	L$mod_loop
@@ -1156,7 +1161,7 @@
 .byte	102,15,58,68,231,0
 	pxor	%xmm1,%xmm0
 
-	subq	$32,%rcx
+	subq	$0x20,%rcx
 	ja	L$mod_loop
 
 L$even_tail:
@@ -1256,7 +1261,108 @@
 
 .p2align	5
 _gcm_init_avx:
-	jmp	L$_init_clmul
+	vzeroupper
+
+	vmovdqu	(%rsi),%xmm2
+	vpshufd	$78,%xmm2,%xmm2
+
+
+	vpshufd	$255,%xmm2,%xmm4
+	vpsrlq	$63,%xmm2,%xmm3
+	vpsllq	$1,%xmm2,%xmm2
+	vpxor	%xmm5,%xmm5,%xmm5
+	vpcmpgtd	%xmm4,%xmm5,%xmm5
+	vpslldq	$8,%xmm3,%xmm3
+	vpor	%xmm3,%xmm2,%xmm2
+
+
+	vpand	L$0x1c2_polynomial(%rip),%xmm5,%xmm5
+	vpxor	%xmm5,%xmm2,%xmm2
+
+	vpunpckhqdq	%xmm2,%xmm2,%xmm6
+	vmovdqa	%xmm2,%xmm0
+	vpxor	%xmm2,%xmm6,%xmm6
+	movq	$4,%r10
+	jmp	L$init_start_avx
+.p2align	5
+L$init_loop_avx:
+	vpalignr	$8,%xmm3,%xmm4,%xmm5
+	vmovdqu	%xmm5,-16(%rdi)
+	vpunpckhqdq	%xmm0,%xmm0,%xmm3
+	vpxor	%xmm0,%xmm3,%xmm3
+	vpclmulqdq	$0x11,%xmm2,%xmm0,%xmm1
+	vpclmulqdq	$0x00,%xmm2,%xmm0,%xmm0
+	vpclmulqdq	$0x00,%xmm6,%xmm3,%xmm3
+	vpxor	%xmm0,%xmm1,%xmm4
+	vpxor	%xmm4,%xmm3,%xmm3
+
+	vpslldq	$8,%xmm3,%xmm4
+	vpsrldq	$8,%xmm3,%xmm3
+	vpxor	%xmm4,%xmm0,%xmm0
+	vpxor	%xmm3,%xmm1,%xmm1
+	vpsllq	$57,%xmm0,%xmm3
+	vpsllq	$62,%xmm0,%xmm4
+	vpxor	%xmm3,%xmm4,%xmm4
+	vpsllq	$63,%xmm0,%xmm3
+	vpxor	%xmm3,%xmm4,%xmm4
+	vpslldq	$8,%xmm4,%xmm3
+	vpsrldq	$8,%xmm4,%xmm4
+	vpxor	%xmm3,%xmm0,%xmm0
+	vpxor	%xmm4,%xmm1,%xmm1
+
+	vpsrlq	$1,%xmm0,%xmm4
+	vpxor	%xmm0,%xmm1,%xmm1
+	vpxor	%xmm4,%xmm0,%xmm0
+	vpsrlq	$5,%xmm4,%xmm4
+	vpxor	%xmm4,%xmm0,%xmm0
+	vpsrlq	$1,%xmm0,%xmm0
+	vpxor	%xmm1,%xmm0,%xmm0
+L$init_start_avx:
+	vmovdqa	%xmm0,%xmm5
+	vpunpckhqdq	%xmm0,%xmm0,%xmm3
+	vpxor	%xmm0,%xmm3,%xmm3
+	vpclmulqdq	$0x11,%xmm2,%xmm0,%xmm1
+	vpclmulqdq	$0x00,%xmm2,%xmm0,%xmm0
+	vpclmulqdq	$0x00,%xmm6,%xmm3,%xmm3
+	vpxor	%xmm0,%xmm1,%xmm4
+	vpxor	%xmm4,%xmm3,%xmm3
+
+	vpslldq	$8,%xmm3,%xmm4
+	vpsrldq	$8,%xmm3,%xmm3
+	vpxor	%xmm4,%xmm0,%xmm0
+	vpxor	%xmm3,%xmm1,%xmm1
+	vpsllq	$57,%xmm0,%xmm3
+	vpsllq	$62,%xmm0,%xmm4
+	vpxor	%xmm3,%xmm4,%xmm4
+	vpsllq	$63,%xmm0,%xmm3
+	vpxor	%xmm3,%xmm4,%xmm4
+	vpslldq	$8,%xmm4,%xmm3
+	vpsrldq	$8,%xmm4,%xmm4
+	vpxor	%xmm3,%xmm0,%xmm0
+	vpxor	%xmm4,%xmm1,%xmm1
+
+	vpsrlq	$1,%xmm0,%xmm4
+	vpxor	%xmm0,%xmm1,%xmm1
+	vpxor	%xmm4,%xmm0,%xmm0
+	vpsrlq	$5,%xmm4,%xmm4
+	vpxor	%xmm4,%xmm0,%xmm0
+	vpsrlq	$1,%xmm0,%xmm0
+	vpxor	%xmm1,%xmm0,%xmm0
+	vpshufd	$78,%xmm5,%xmm3
+	vpshufd	$78,%xmm0,%xmm4
+	vpxor	%xmm5,%xmm3,%xmm3
+	vmovdqu	%xmm5,0(%rdi)
+	vpxor	%xmm0,%xmm4,%xmm4
+	vmovdqu	%xmm0,16(%rdi)
+	leaq	48(%rdi),%rdi
+	subq	$1,%r10
+	jnz	L$init_loop_avx
+
+	vpalignr	$8,%xmm4,%xmm3,%xmm5
+	vmovdqu	%xmm5,-16(%rdi)
+
+	vzeroupper
+	.byte	0xf3,0xc3
 
 .globl	_gcm_gmult_avx
 .private_extern _gcm_gmult_avx
@@ -1270,7 +1376,377 @@
 
 .p2align	5
 _gcm_ghash_avx:
-	jmp	L$_ghash_clmul
+	vzeroupper
+
+	vmovdqu	(%rdi),%xmm10
+	leaq	L$0x1c2_polynomial(%rip),%r10
+	leaq	64(%rsi),%rsi
+	vmovdqu	L$bswap_mask(%rip),%xmm13
+	vpshufb	%xmm13,%xmm10,%xmm10
+	cmpq	$0x80,%rcx
+	jb	L$short_avx
+	subq	$0x80,%rcx
+
+	vmovdqu	112(%rdx),%xmm14
+	vmovdqu	0-64(%rsi),%xmm6
+	vpshufb	%xmm13,%xmm14,%xmm14
+	vmovdqu	32-64(%rsi),%xmm7
+
+	vpunpckhqdq	%xmm14,%xmm14,%xmm9
+	vmovdqu	96(%rdx),%xmm15
+	vpclmulqdq	$0x00,%xmm6,%xmm14,%xmm0
+	vpxor	%xmm14,%xmm9,%xmm9
+	vpshufb	%xmm13,%xmm15,%xmm15
+	vpclmulqdq	$0x11,%xmm6,%xmm14,%xmm1
+	vmovdqu	16-64(%rsi),%xmm6
+	vpunpckhqdq	%xmm15,%xmm15,%xmm8
+	vmovdqu	80(%rdx),%xmm14
+	vpclmulqdq	$0x00,%xmm7,%xmm9,%xmm2
+	vpxor	%xmm15,%xmm8,%xmm8
+
+	vpshufb	%xmm13,%xmm14,%xmm14
+	vpclmulqdq	$0x00,%xmm6,%xmm15,%xmm3
+	vpunpckhqdq	%xmm14,%xmm14,%xmm9
+	vpclmulqdq	$0x11,%xmm6,%xmm15,%xmm4
+	vmovdqu	48-64(%rsi),%xmm6
+	vpxor	%xmm14,%xmm9,%xmm9
+	vmovdqu	64(%rdx),%xmm15
+	vpclmulqdq	$0x10,%xmm7,%xmm8,%xmm5
+	vmovdqu	80-64(%rsi),%xmm7
+
+	vpshufb	%xmm13,%xmm15,%xmm15
+	vpxor	%xmm0,%xmm3,%xmm3
+	vpclmulqdq	$0x00,%xmm6,%xmm14,%xmm0
+	vpxor	%xmm1,%xmm4,%xmm4
+	vpunpckhqdq	%xmm15,%xmm15,%xmm8
+	vpclmulqdq	$0x11,%xmm6,%xmm14,%xmm1
+	vmovdqu	64-64(%rsi),%xmm6
+	vpxor	%xmm2,%xmm5,%xmm5
+	vpclmulqdq	$0x00,%xmm7,%xmm9,%xmm2
+	vpxor	%xmm15,%xmm8,%xmm8
+
+	vmovdqu	48(%rdx),%xmm14
+	vpxor	%xmm3,%xmm0,%xmm0
+	vpclmulqdq	$0x00,%xmm6,%xmm15,%xmm3
+	vpxor	%xmm4,%xmm1,%xmm1
+	vpshufb	%xmm13,%xmm14,%xmm14
+	vpclmulqdq	$0x11,%xmm6,%xmm15,%xmm4
+	vmovdqu	96-64(%rsi),%xmm6
+	vpxor	%xmm5,%xmm2,%xmm2
+	vpunpckhqdq	%xmm14,%xmm14,%xmm9
+	vpclmulqdq	$0x10,%xmm7,%xmm8,%xmm5
+	vmovdqu	128-64(%rsi),%xmm7
+	vpxor	%xmm14,%xmm9,%xmm9
+
+	vmovdqu	32(%rdx),%xmm15
+	vpxor	%xmm0,%xmm3,%xmm3
+	vpclmulqdq	$0x00,%xmm6,%xmm14,%xmm0
+	vpxor	%xmm1,%xmm4,%xmm4
+	vpshufb	%xmm13,%xmm15,%xmm15
+	vpclmulqdq	$0x11,%xmm6,%xmm14,%xmm1
+	vmovdqu	112-64(%rsi),%xmm6
+	vpxor	%xmm2,%xmm5,%xmm5
+	vpunpckhqdq	%xmm15,%xmm15,%xmm8
+	vpclmulqdq	$0x00,%xmm7,%xmm9,%xmm2
+	vpxor	%xmm15,%xmm8,%xmm8
+
+	vmovdqu	16(%rdx),%xmm14
+	vpxor	%xmm3,%xmm0,%xmm0
+	vpclmulqdq	$0x00,%xmm6,%xmm15,%xmm3
+	vpxor	%xmm4,%xmm1,%xmm1
+	vpshufb	%xmm13,%xmm14,%xmm14
+	vpclmulqdq	$0x11,%xmm6,%xmm15,%xmm4
+	vmovdqu	144-64(%rsi),%xmm6
+	vpxor	%xmm5,%xmm2,%xmm2
+	vpunpckhqdq	%xmm14,%xmm14,%xmm9
+	vpclmulqdq	$0x10,%xmm7,%xmm8,%xmm5
+	vmovdqu	176-64(%rsi),%xmm7
+	vpxor	%xmm14,%xmm9,%xmm9
+
+	vmovdqu	(%rdx),%xmm15
+	vpxor	%xmm0,%xmm3,%xmm3
+	vpclmulqdq	$0x00,%xmm6,%xmm14,%xmm0
+	vpxor	%xmm1,%xmm4,%xmm4
+	vpshufb	%xmm13,%xmm15,%xmm15
+	vpclmulqdq	$0x11,%xmm6,%xmm14,%xmm1
+	vmovdqu	160-64(%rsi),%xmm6
+	vpxor	%xmm2,%xmm5,%xmm5
+	vpclmulqdq	$0x10,%xmm7,%xmm9,%xmm2
+
+	leaq	128(%rdx),%rdx
+	cmpq	$0x80,%rcx
+	jb	L$tail_avx
+
+	vpxor	%xmm10,%xmm15,%xmm15
+	subq	$0x80,%rcx
+	jmp	L$oop8x_avx
+
+.p2align	5
+L$oop8x_avx:
+	vpunpckhqdq	%xmm15,%xmm15,%xmm8
+	vmovdqu	112(%rdx),%xmm14
+	vpxor	%xmm0,%xmm3,%xmm3
+	vpxor	%xmm15,%xmm8,%xmm8
+	vpclmulqdq	$0x00,%xmm6,%xmm15,%xmm10
+	vpshufb	%xmm13,%xmm14,%xmm14
+	vpxor	%xmm1,%xmm4,%xmm4
+	vpclmulqdq	$0x11,%xmm6,%xmm15,%xmm11
+	vmovdqu	0-64(%rsi),%xmm6
+	vpunpckhqdq	%xmm14,%xmm14,%xmm9
+	vpxor	%xmm2,%xmm5,%xmm5
+	vpclmulqdq	$0x00,%xmm7,%xmm8,%xmm12
+	vmovdqu	32-64(%rsi),%xmm7
+	vpxor	%xmm14,%xmm9,%xmm9
+
+	vmovdqu	96(%rdx),%xmm15
+	vpclmulqdq	$0x00,%xmm6,%xmm14,%xmm0
+	vpxor	%xmm3,%xmm10,%xmm10
+	vpshufb	%xmm13,%xmm15,%xmm15
+	vpclmulqdq	$0x11,%xmm6,%xmm14,%xmm1
+	vxorps	%xmm4,%xmm11,%xmm11
+	vmovdqu	16-64(%rsi),%xmm6
+	vpunpckhqdq	%xmm15,%xmm15,%xmm8
+	vpclmulqdq	$0x00,%xmm7,%xmm9,%xmm2
+	vpxor	%xmm5,%xmm12,%xmm12
+	vxorps	%xmm15,%xmm8,%xmm8
+
+	vmovdqu	80(%rdx),%xmm14
+	vpxor	%xmm10,%xmm12,%xmm12
+	vpclmulqdq	$0x00,%xmm6,%xmm15,%xmm3
+	vpxor	%xmm11,%xmm12,%xmm12
+	vpslldq	$8,%xmm12,%xmm9
+	vpxor	%xmm0,%xmm3,%xmm3
+	vpclmulqdq	$0x11,%xmm6,%xmm15,%xmm4
+	vpsrldq	$8,%xmm12,%xmm12
+	vpxor	%xmm9,%xmm10,%xmm10
+	vmovdqu	48-64(%rsi),%xmm6
+	vpshufb	%xmm13,%xmm14,%xmm14
+	vxorps	%xmm12,%xmm11,%xmm11
+	vpxor	%xmm1,%xmm4,%xmm4
+	vpunpckhqdq	%xmm14,%xmm14,%xmm9
+	vpclmulqdq	$0x10,%xmm7,%xmm8,%xmm5
+	vmovdqu	80-64(%rsi),%xmm7
+	vpxor	%xmm14,%xmm9,%xmm9
+	vpxor	%xmm2,%xmm5,%xmm5
+
+	vmovdqu	64(%rdx),%xmm15
+	vpalignr	$8,%xmm10,%xmm10,%xmm12
+	vpclmulqdq	$0x00,%xmm6,%xmm14,%xmm0
+	vpshufb	%xmm13,%xmm15,%xmm15
+	vpxor	%xmm3,%xmm0,%xmm0
+	vpclmulqdq	$0x11,%xmm6,%xmm14,%xmm1
+	vmovdqu	64-64(%rsi),%xmm6
+	vpunpckhqdq	%xmm15,%xmm15,%xmm8
+	vpxor	%xmm4,%xmm1,%xmm1
+	vpclmulqdq	$0x00,%xmm7,%xmm9,%xmm2
+	vxorps	%xmm15,%xmm8,%xmm8
+	vpxor	%xmm5,%xmm2,%xmm2
+
+	vmovdqu	48(%rdx),%xmm14
+	vpclmulqdq	$0x10,(%r10),%xmm10,%xmm10
+	vpclmulqdq	$0x00,%xmm6,%xmm15,%xmm3
+	vpshufb	%xmm13,%xmm14,%xmm14
+	vpxor	%xmm0,%xmm3,%xmm3
+	vpclmulqdq	$0x11,%xmm6,%xmm15,%xmm4
+	vmovdqu	96-64(%rsi),%xmm6
+	vpunpckhqdq	%xmm14,%xmm14,%xmm9
+	vpxor	%xmm1,%xmm4,%xmm4
+	vpclmulqdq	$0x10,%xmm7,%xmm8,%xmm5
+	vmovdqu	128-64(%rsi),%xmm7
+	vpxor	%xmm14,%xmm9,%xmm9
+	vpxor	%xmm2,%xmm5,%xmm5
+
+	vmovdqu	32(%rdx),%xmm15
+	vpclmulqdq	$0x00,%xmm6,%xmm14,%xmm0
+	vpshufb	%xmm13,%xmm15,%xmm15
+	vpxor	%xmm3,%xmm0,%xmm0
+	vpclmulqdq	$0x11,%xmm6,%xmm14,%xmm1
+	vmovdqu	112-64(%rsi),%xmm6
+	vpunpckhqdq	%xmm15,%xmm15,%xmm8
+	vpxor	%xmm4,%xmm1,%xmm1
+	vpclmulqdq	$0x00,%xmm7,%xmm9,%xmm2
+	vpxor	%xmm15,%xmm8,%xmm8
+	vpxor	%xmm5,%xmm2,%xmm2
+	vxorps	%xmm12,%xmm10,%xmm10
+
+	vmovdqu	16(%rdx),%xmm14
+	vpalignr	$8,%xmm10,%xmm10,%xmm12
+	vpclmulqdq	$0x00,%xmm6,%xmm15,%xmm3
+	vpshufb	%xmm13,%xmm14,%xmm14
+	vpxor	%xmm0,%xmm3,%xmm3
+	vpclmulqdq	$0x11,%xmm6,%xmm15,%xmm4
+	vmovdqu	144-64(%rsi),%xmm6
+	vpclmulqdq	$0x10,(%r10),%xmm10,%xmm10
+	vxorps	%xmm11,%xmm12,%xmm12
+	vpunpckhqdq	%xmm14,%xmm14,%xmm9
+	vpxor	%xmm1,%xmm4,%xmm4
+	vpclmulqdq	$0x10,%xmm7,%xmm8,%xmm5
+	vmovdqu	176-64(%rsi),%xmm7
+	vpxor	%xmm14,%xmm9,%xmm9
+	vpxor	%xmm2,%xmm5,%xmm5
+
+	vmovdqu	(%rdx),%xmm15
+	vpclmulqdq	$0x00,%xmm6,%xmm14,%xmm0
+	vpshufb	%xmm13,%xmm15,%xmm15
+	vpclmulqdq	$0x11,%xmm6,%xmm14,%xmm1
+	vmovdqu	160-64(%rsi),%xmm6
+	vpxor	%xmm12,%xmm15,%xmm15
+	vpclmulqdq	$0x10,%xmm7,%xmm9,%xmm2
+	vpxor	%xmm10,%xmm15,%xmm15
+
+	leaq	128(%rdx),%rdx
+	subq	$0x80,%rcx
+	jnc	L$oop8x_avx
+
+	addq	$0x80,%rcx
+	jmp	L$tail_no_xor_avx
+
+.p2align	5
+L$short_avx:
+	vmovdqu	-16(%rdx,%rcx,1),%xmm14
+	leaq	(%rdx,%rcx,1),%rdx
+	vmovdqu	0-64(%rsi),%xmm6
+	vmovdqu	32-64(%rsi),%xmm7
+	vpshufb	%xmm13,%xmm14,%xmm15
+
+	vmovdqa	%xmm0,%xmm3
+	vmovdqa	%xmm1,%xmm4
+	vmovdqa	%xmm2,%xmm5
+	subq	$0x10,%rcx
+	jz	L$tail_avx
+
+	vpunpckhqdq	%xmm15,%xmm15,%xmm8
+	vpxor	%xmm0,%xmm3,%xmm3
+	vpclmulqdq	$0x00,%xmm6,%xmm15,%xmm0
+	vpxor	%xmm15,%xmm8,%xmm8
+	vmovdqu	-32(%rdx),%xmm14
+	vpxor	%xmm1,%xmm4,%xmm4
+	vpclmulqdq	$0x11,%xmm6,%xmm15,%xmm1
+	vmovdqu	16-64(%rsi),%xmm6
+	vpshufb	%xmm13,%xmm14,%xmm15
+	vpxor	%xmm2,%xmm5,%xmm5
+	vpclmulqdq	$0x00,%xmm7,%xmm8,%xmm2
+	vpsrldq	$8,%xmm7,%xmm7
+	subq	$0x10,%rcx
+	jz	L$tail_avx
+
+	vpunpckhqdq	%xmm15,%xmm15,%xmm8
+	vpxor	%xmm0,%xmm3,%xmm3
+	vpclmulqdq	$0x00,%xmm6,%xmm15,%xmm0
+	vpxor	%xmm15,%xmm8,%xmm8
+	vmovdqu	-48(%rdx),%xmm14
+	vpxor	%xmm1,%xmm4,%xmm4
+	vpclmulqdq	$0x11,%xmm6,%xmm15,%xmm1
+	vmovdqu	48-64(%rsi),%xmm6
+	vpshufb	%xmm13,%xmm14,%xmm15
+	vpxor	%xmm2,%xmm5,%xmm5
+	vpclmulqdq	$0x00,%xmm7,%xmm8,%xmm2
+	vmovdqu	80-64(%rsi),%xmm7
+	subq	$0x10,%rcx
+	jz	L$tail_avx
+
+	vpunpckhqdq	%xmm15,%xmm15,%xmm8
+	vpxor	%xmm0,%xmm3,%xmm3
+	vpclmulqdq	$0x00,%xmm6,%xmm15,%xmm0
+	vpxor	%xmm15,%xmm8,%xmm8
+	vmovdqu	-64(%rdx),%xmm14
+	vpxor	%xmm1,%xmm4,%xmm4
+	vpclmulqdq	$0x11,%xmm6,%xmm15,%xmm1
+	vmovdqu	64-64(%rsi),%xmm6
+	vpshufb	%xmm13,%xmm14,%xmm15
+	vpxor	%xmm2,%xmm5,%xmm5
+	vpclmulqdq	$0x00,%xmm7,%xmm8,%xmm2
+	vpsrldq	$8,%xmm7,%xmm7
+	subq	$0x10,%rcx
+	jz	L$tail_avx
+
+	vpunpckhqdq	%xmm15,%xmm15,%xmm8
+	vpxor	%xmm0,%xmm3,%xmm3
+	vpclmulqdq	$0x00,%xmm6,%xmm15,%xmm0
+	vpxor	%xmm15,%xmm8,%xmm8
+	vmovdqu	-80(%rdx),%xmm14
+	vpxor	%xmm1,%xmm4,%xmm4
+	vpclmulqdq	$0x11,%xmm6,%xmm15,%xmm1
+	vmovdqu	96-64(%rsi),%xmm6
+	vpshufb	%xmm13,%xmm14,%xmm15
+	vpxor	%xmm2,%xmm5,%xmm5
+	vpclmulqdq	$0x00,%xmm7,%xmm8,%xmm2
+	vmovdqu	128-64(%rsi),%xmm7
+	subq	$0x10,%rcx
+	jz	L$tail_avx
+
+	vpunpckhqdq	%xmm15,%xmm15,%xmm8
+	vpxor	%xmm0,%xmm3,%xmm3
+	vpclmulqdq	$0x00,%xmm6,%xmm15,%xmm0
+	vpxor	%xmm15,%xmm8,%xmm8
+	vmovdqu	-96(%rdx),%xmm14
+	vpxor	%xmm1,%xmm4,%xmm4
+	vpclmulqdq	$0x11,%xmm6,%xmm15,%xmm1
+	vmovdqu	112-64(%rsi),%xmm6
+	vpshufb	%xmm13,%xmm14,%xmm15
+	vpxor	%xmm2,%xmm5,%xmm5
+	vpclmulqdq	$0x00,%xmm7,%xmm8,%xmm2
+	vpsrldq	$8,%xmm7,%xmm7
+	subq	$0x10,%rcx
+	jz	L$tail_avx
+
+	vpunpckhqdq	%xmm15,%xmm15,%xmm8
+	vpxor	%xmm0,%xmm3,%xmm3
+	vpclmulqdq	$0x00,%xmm6,%xmm15,%xmm0
+	vpxor	%xmm15,%xmm8,%xmm8
+	vmovdqu	-112(%rdx),%xmm14
+	vpxor	%xmm1,%xmm4,%xmm4
+	vpclmulqdq	$0x11,%xmm6,%xmm15,%xmm1
+	vmovdqu	144-64(%rsi),%xmm6
+	vpshufb	%xmm13,%xmm14,%xmm15
+	vpxor	%xmm2,%xmm5,%xmm5
+	vpclmulqdq	$0x00,%xmm7,%xmm8,%xmm2
+	vmovq	184-64(%rsi),%xmm7
+	subq	$0x10,%rcx
+	jmp	L$tail_avx
+
+.p2align	5
+L$tail_avx:
+	vpxor	%xmm10,%xmm15,%xmm15
+L$tail_no_xor_avx:
+	vpunpckhqdq	%xmm15,%xmm15,%xmm8
+	vpxor	%xmm0,%xmm3,%xmm3
+	vpclmulqdq	$0x00,%xmm6,%xmm15,%xmm0
+	vpxor	%xmm15,%xmm8,%xmm8
+	vpxor	%xmm1,%xmm4,%xmm4
+	vpclmulqdq	$0x11,%xmm6,%xmm15,%xmm1
+	vpxor	%xmm2,%xmm5,%xmm5
+	vpclmulqdq	$0x00,%xmm7,%xmm8,%xmm2
+
+	vmovdqu	(%r10),%xmm12
+
+	vpxor	%xmm0,%xmm3,%xmm10
+	vpxor	%xmm1,%xmm4,%xmm11
+	vpxor	%xmm2,%xmm5,%xmm5
+
+	vpxor	%xmm10,%xmm5,%xmm5
+	vpxor	%xmm11,%xmm5,%xmm5
+	vpslldq	$8,%xmm5,%xmm9
+	vpsrldq	$8,%xmm5,%xmm5
+	vpxor	%xmm9,%xmm10,%xmm10
+	vpxor	%xmm5,%xmm11,%xmm11
+
+	vpclmulqdq	$0x10,%xmm12,%xmm10,%xmm9
+	vpalignr	$8,%xmm10,%xmm10,%xmm10
+	vpxor	%xmm9,%xmm10,%xmm10
+
+	vpclmulqdq	$0x10,%xmm12,%xmm10,%xmm9
+	vpalignr	$8,%xmm10,%xmm10,%xmm10
+	vpxor	%xmm11,%xmm10,%xmm10
+	vpxor	%xmm9,%xmm10,%xmm10
+
+	cmpq	$0,%rcx
+	jne	L$short_avx
+
+	vpshufb	%xmm13,%xmm10,%xmm10
+	vmovdqu	%xmm10,(%rdi)
+	vzeroupper
+	.byte	0xf3,0xc3
 
 .p2align	6
 L$bswap_mask:
diff --git a/mac-x86_64/crypto/rc4/rc4-x86_64.S b/mac-x86_64/crypto/rc4/rc4-x86_64.S
deleted file mode 100644
index 7808184..0000000
--- a/mac-x86_64/crypto/rc4/rc4-x86_64.S
+++ /dev/null
@@ -1,595 +0,0 @@
-#if defined(__x86_64__)
-.text	
-
-
-.globl	_asm_RC4
-.private_extern _asm_RC4
-
-.p2align	4
-_asm_RC4:
-	orq	%rsi,%rsi
-	jne	L$entry
-	.byte	0xf3,0xc3
-L$entry:
-	pushq	%rbx
-	pushq	%r12
-	pushq	%r13
-L$prologue:
-	movq	%rsi,%r11
-	movq	%rdx,%r12
-	movq	%rcx,%r13
-	xorq	%r10,%r10
-	xorq	%rcx,%rcx
-
-	leaq	8(%rdi),%rdi
-	movb	-8(%rdi),%r10b
-	movb	-4(%rdi),%cl
-	cmpl	$-1,256(%rdi)
-	je	L$RC4_CHAR
-	movl	_OPENSSL_ia32cap_P(%rip),%r8d
-	xorq	%rbx,%rbx
-	incb	%r10b
-	subq	%r10,%rbx
-	subq	%r12,%r13
-	movl	(%rdi,%r10,4),%eax
-	testq	$-16,%r11
-	jz	L$loop1
-	btl	$30,%r8d
-	jc	L$intel
-	andq	$7,%rbx
-	leaq	1(%r10),%rsi
-	jz	L$oop8
-	subq	%rbx,%r11
-L$oop8_warmup:
-	addb	%al,%cl
-	movl	(%rdi,%rcx,4),%edx
-	movl	%eax,(%rdi,%rcx,4)
-	movl	%edx,(%rdi,%r10,4)
-	addb	%dl,%al
-	incb	%r10b
-	movl	(%rdi,%rax,4),%edx
-	movl	(%rdi,%r10,4),%eax
-	xorb	(%r12),%dl
-	movb	%dl,(%r12,%r13,1)
-	leaq	1(%r12),%r12
-	decq	%rbx
-	jnz	L$oop8_warmup
-
-	leaq	1(%r10),%rsi
-	jmp	L$oop8
-.p2align	4
-L$oop8:
-	addb	%al,%cl
-	movl	(%rdi,%rcx,4),%edx
-	movl	%eax,(%rdi,%rcx,4)
-	movl	0(%rdi,%rsi,4),%ebx
-	rorq	$8,%r8
-	movl	%edx,0(%rdi,%r10,4)
-	addb	%al,%dl
-	movb	(%rdi,%rdx,4),%r8b
-	addb	%bl,%cl
-	movl	(%rdi,%rcx,4),%edx
-	movl	%ebx,(%rdi,%rcx,4)
-	movl	4(%rdi,%rsi,4),%eax
-	rorq	$8,%r8
-	movl	%edx,4(%rdi,%r10,4)
-	addb	%bl,%dl
-	movb	(%rdi,%rdx,4),%r8b
-	addb	%al,%cl
-	movl	(%rdi,%rcx,4),%edx
-	movl	%eax,(%rdi,%rcx,4)
-	movl	8(%rdi,%rsi,4),%ebx
-	rorq	$8,%r8
-	movl	%edx,8(%rdi,%r10,4)
-	addb	%al,%dl
-	movb	(%rdi,%rdx,4),%r8b
-	addb	%bl,%cl
-	movl	(%rdi,%rcx,4),%edx
-	movl	%ebx,(%rdi,%rcx,4)
-	movl	12(%rdi,%rsi,4),%eax
-	rorq	$8,%r8
-	movl	%edx,12(%rdi,%r10,4)
-	addb	%bl,%dl
-	movb	(%rdi,%rdx,4),%r8b
-	addb	%al,%cl
-	movl	(%rdi,%rcx,4),%edx
-	movl	%eax,(%rdi,%rcx,4)
-	movl	16(%rdi,%rsi,4),%ebx
-	rorq	$8,%r8
-	movl	%edx,16(%rdi,%r10,4)
-	addb	%al,%dl
-	movb	(%rdi,%rdx,4),%r8b
-	addb	%bl,%cl
-	movl	(%rdi,%rcx,4),%edx
-	movl	%ebx,(%rdi,%rcx,4)
-	movl	20(%rdi,%rsi,4),%eax
-	rorq	$8,%r8
-	movl	%edx,20(%rdi,%r10,4)
-	addb	%bl,%dl
-	movb	(%rdi,%rdx,4),%r8b
-	addb	%al,%cl
-	movl	(%rdi,%rcx,4),%edx
-	movl	%eax,(%rdi,%rcx,4)
-	movl	24(%rdi,%rsi,4),%ebx
-	rorq	$8,%r8
-	movl	%edx,24(%rdi,%r10,4)
-	addb	%al,%dl
-	movb	(%rdi,%rdx,4),%r8b
-	addb	$8,%sil
-	addb	%bl,%cl
-	movl	(%rdi,%rcx,4),%edx
-	movl	%ebx,(%rdi,%rcx,4)
-	movl	-4(%rdi,%rsi,4),%eax
-	rorq	$8,%r8
-	movl	%edx,28(%rdi,%r10,4)
-	addb	%bl,%dl
-	movb	(%rdi,%rdx,4),%r8b
-	addb	$8,%r10b
-	rorq	$8,%r8
-	subq	$8,%r11
-
-	xorq	(%r12),%r8
-	movq	%r8,(%r12,%r13,1)
-	leaq	8(%r12),%r12
-
-	testq	$-8,%r11
-	jnz	L$oop8
-	cmpq	$0,%r11
-	jne	L$loop1
-	jmp	L$exit
-
-.p2align	4
-L$intel:
-	testq	$-32,%r11
-	jz	L$loop1
-	andq	$15,%rbx
-	jz	L$oop16_is_hot
-	subq	%rbx,%r11
-L$oop16_warmup:
-	addb	%al,%cl
-	movl	(%rdi,%rcx,4),%edx
-	movl	%eax,(%rdi,%rcx,4)
-	movl	%edx,(%rdi,%r10,4)
-	addb	%dl,%al
-	incb	%r10b
-	movl	(%rdi,%rax,4),%edx
-	movl	(%rdi,%r10,4),%eax
-	xorb	(%r12),%dl
-	movb	%dl,(%r12,%r13,1)
-	leaq	1(%r12),%r12
-	decq	%rbx
-	jnz	L$oop16_warmup
-
-	movq	%rcx,%rbx
-	xorq	%rcx,%rcx
-	movb	%bl,%cl
-
-L$oop16_is_hot:
-	leaq	(%rdi,%r10,4),%rsi
-	addb	%al,%cl
-	movl	(%rdi,%rcx,4),%edx
-	pxor	%xmm0,%xmm0
-	movl	%eax,(%rdi,%rcx,4)
-	addb	%dl,%al
-	movl	4(%rsi),%ebx
-	movzbl	%al,%eax
-	movl	%edx,0(%rsi)
-	addb	%bl,%cl
-	pinsrw	$0,(%rdi,%rax,4),%xmm0
-	jmp	L$oop16_enter
-.p2align	4
-L$oop16:
-	addb	%al,%cl
-	movl	(%rdi,%rcx,4),%edx
-	pxor	%xmm0,%xmm2
-	psllq	$8,%xmm1
-	pxor	%xmm0,%xmm0
-	movl	%eax,(%rdi,%rcx,4)
-	addb	%dl,%al
-	movl	4(%rsi),%ebx
-	movzbl	%al,%eax
-	movl	%edx,0(%rsi)
-	pxor	%xmm1,%xmm2
-	addb	%bl,%cl
-	pinsrw	$0,(%rdi,%rax,4),%xmm0
-	movdqu	%xmm2,(%r12,%r13,1)
-	leaq	16(%r12),%r12
-L$oop16_enter:
-	movl	(%rdi,%rcx,4),%edx
-	pxor	%xmm1,%xmm1
-	movl	%ebx,(%rdi,%rcx,4)
-	addb	%dl,%bl
-	movl	8(%rsi),%eax
-	movzbl	%bl,%ebx
-	movl	%edx,4(%rsi)
-	addb	%al,%cl
-	pinsrw	$0,(%rdi,%rbx,4),%xmm1
-	movl	(%rdi,%rcx,4),%edx
-	movl	%eax,(%rdi,%rcx,4)
-	addb	%dl,%al
-	movl	12(%rsi),%ebx
-	movzbl	%al,%eax
-	movl	%edx,8(%rsi)
-	addb	%bl,%cl
-	pinsrw	$1,(%rdi,%rax,4),%xmm0
-	movl	(%rdi,%rcx,4),%edx
-	movl	%ebx,(%rdi,%rcx,4)
-	addb	%dl,%bl
-	movl	16(%rsi),%eax
-	movzbl	%bl,%ebx
-	movl	%edx,12(%rsi)
-	addb	%al,%cl
-	pinsrw	$1,(%rdi,%rbx,4),%xmm1
-	movl	(%rdi,%rcx,4),%edx
-	movl	%eax,(%rdi,%rcx,4)
-	addb	%dl,%al
-	movl	20(%rsi),%ebx
-	movzbl	%al,%eax
-	movl	%edx,16(%rsi)
-	addb	%bl,%cl
-	pinsrw	$2,(%rdi,%rax,4),%xmm0
-	movl	(%rdi,%rcx,4),%edx
-	movl	%ebx,(%rdi,%rcx,4)
-	addb	%dl,%bl
-	movl	24(%rsi),%eax
-	movzbl	%bl,%ebx
-	movl	%edx,20(%rsi)
-	addb	%al,%cl
-	pinsrw	$2,(%rdi,%rbx,4),%xmm1
-	movl	(%rdi,%rcx,4),%edx
-	movl	%eax,(%rdi,%rcx,4)
-	addb	%dl,%al
-	movl	28(%rsi),%ebx
-	movzbl	%al,%eax
-	movl	%edx,24(%rsi)
-	addb	%bl,%cl
-	pinsrw	$3,(%rdi,%rax,4),%xmm0
-	movl	(%rdi,%rcx,4),%edx
-	movl	%ebx,(%rdi,%rcx,4)
-	addb	%dl,%bl
-	movl	32(%rsi),%eax
-	movzbl	%bl,%ebx
-	movl	%edx,28(%rsi)
-	addb	%al,%cl
-	pinsrw	$3,(%rdi,%rbx,4),%xmm1
-	movl	(%rdi,%rcx,4),%edx
-	movl	%eax,(%rdi,%rcx,4)
-	addb	%dl,%al
-	movl	36(%rsi),%ebx
-	movzbl	%al,%eax
-	movl	%edx,32(%rsi)
-	addb	%bl,%cl
-	pinsrw	$4,(%rdi,%rax,4),%xmm0
-	movl	(%rdi,%rcx,4),%edx
-	movl	%ebx,(%rdi,%rcx,4)
-	addb	%dl,%bl
-	movl	40(%rsi),%eax
-	movzbl	%bl,%ebx
-	movl	%edx,36(%rsi)
-	addb	%al,%cl
-	pinsrw	$4,(%rdi,%rbx,4),%xmm1
-	movl	(%rdi,%rcx,4),%edx
-	movl	%eax,(%rdi,%rcx,4)
-	addb	%dl,%al
-	movl	44(%rsi),%ebx
-	movzbl	%al,%eax
-	movl	%edx,40(%rsi)
-	addb	%bl,%cl
-	pinsrw	$5,(%rdi,%rax,4),%xmm0
-	movl	(%rdi,%rcx,4),%edx
-	movl	%ebx,(%rdi,%rcx,4)
-	addb	%dl,%bl
-	movl	48(%rsi),%eax
-	movzbl	%bl,%ebx
-	movl	%edx,44(%rsi)
-	addb	%al,%cl
-	pinsrw	$5,(%rdi,%rbx,4),%xmm1
-	movl	(%rdi,%rcx,4),%edx
-	movl	%eax,(%rdi,%rcx,4)
-	addb	%dl,%al
-	movl	52(%rsi),%ebx
-	movzbl	%al,%eax
-	movl	%edx,48(%rsi)
-	addb	%bl,%cl
-	pinsrw	$6,(%rdi,%rax,4),%xmm0
-	movl	(%rdi,%rcx,4),%edx
-	movl	%ebx,(%rdi,%rcx,4)
-	addb	%dl,%bl
-	movl	56(%rsi),%eax
-	movzbl	%bl,%ebx
-	movl	%edx,52(%rsi)
-	addb	%al,%cl
-	pinsrw	$6,(%rdi,%rbx,4),%xmm1
-	movl	(%rdi,%rcx,4),%edx
-	movl	%eax,(%rdi,%rcx,4)
-	addb	%dl,%al
-	movl	60(%rsi),%ebx
-	movzbl	%al,%eax
-	movl	%edx,56(%rsi)
-	addb	%bl,%cl
-	pinsrw	$7,(%rdi,%rax,4),%xmm0
-	addb	$16,%r10b
-	movdqu	(%r12),%xmm2
-	movl	(%rdi,%rcx,4),%edx
-	movl	%ebx,(%rdi,%rcx,4)
-	addb	%dl,%bl
-	movzbl	%bl,%ebx
-	movl	%edx,60(%rsi)
-	leaq	(%rdi,%r10,4),%rsi
-	pinsrw	$7,(%rdi,%rbx,4),%xmm1
-	movl	(%rsi),%eax
-	movq	%rcx,%rbx
-	xorq	%rcx,%rcx
-	subq	$16,%r11
-	movb	%bl,%cl
-	testq	$-16,%r11
-	jnz	L$oop16
-
-	psllq	$8,%xmm1
-	pxor	%xmm0,%xmm2
-	pxor	%xmm1,%xmm2
-	movdqu	%xmm2,(%r12,%r13,1)
-	leaq	16(%r12),%r12
-
-	cmpq	$0,%r11
-	jne	L$loop1
-	jmp	L$exit
-
-.p2align	4
-L$loop1:
-	addb	%al,%cl
-	movl	(%rdi,%rcx,4),%edx
-	movl	%eax,(%rdi,%rcx,4)
-	movl	%edx,(%rdi,%r10,4)
-	addb	%dl,%al
-	incb	%r10b
-	movl	(%rdi,%rax,4),%edx
-	movl	(%rdi,%r10,4),%eax
-	xorb	(%r12),%dl
-	movb	%dl,(%r12,%r13,1)
-	leaq	1(%r12),%r12
-	decq	%r11
-	jnz	L$loop1
-	jmp	L$exit
-
-.p2align	4
-L$RC4_CHAR:
-	addb	$1,%r10b
-	movzbl	(%rdi,%r10,1),%eax
-	testq	$-8,%r11
-	jz	L$cloop1
-	jmp	L$cloop8
-.p2align	4
-L$cloop8:
-	movl	(%r12),%r8d
-	movl	4(%r12),%r9d
-	addb	%al,%cl
-	leaq	1(%r10),%rsi
-	movzbl	(%rdi,%rcx,1),%edx
-	movzbl	%sil,%esi
-	movzbl	(%rdi,%rsi,1),%ebx
-	movb	%al,(%rdi,%rcx,1)
-	cmpq	%rsi,%rcx
-	movb	%dl,(%rdi,%r10,1)
-	jne	L$cmov0
-	movq	%rax,%rbx
-L$cmov0:
-	addb	%al,%dl
-	xorb	(%rdi,%rdx,1),%r8b
-	rorl	$8,%r8d
-	addb	%bl,%cl
-	leaq	1(%rsi),%r10
-	movzbl	(%rdi,%rcx,1),%edx
-	movzbl	%r10b,%r10d
-	movzbl	(%rdi,%r10,1),%eax
-	movb	%bl,(%rdi,%rcx,1)
-	cmpq	%r10,%rcx
-	movb	%dl,(%rdi,%rsi,1)
-	jne	L$cmov1
-	movq	%rbx,%rax
-L$cmov1:
-	addb	%bl,%dl
-	xorb	(%rdi,%rdx,1),%r8b
-	rorl	$8,%r8d
-	addb	%al,%cl
-	leaq	1(%r10),%rsi
-	movzbl	(%rdi,%rcx,1),%edx
-	movzbl	%sil,%esi
-	movzbl	(%rdi,%rsi,1),%ebx
-	movb	%al,(%rdi,%rcx,1)
-	cmpq	%rsi,%rcx
-	movb	%dl,(%rdi,%r10,1)
-	jne	L$cmov2
-	movq	%rax,%rbx
-L$cmov2:
-	addb	%al,%dl
-	xorb	(%rdi,%rdx,1),%r8b
-	rorl	$8,%r8d
-	addb	%bl,%cl
-	leaq	1(%rsi),%r10
-	movzbl	(%rdi,%rcx,1),%edx
-	movzbl	%r10b,%r10d
-	movzbl	(%rdi,%r10,1),%eax
-	movb	%bl,(%rdi,%rcx,1)
-	cmpq	%r10,%rcx
-	movb	%dl,(%rdi,%rsi,1)
-	jne	L$cmov3
-	movq	%rbx,%rax
-L$cmov3:
-	addb	%bl,%dl
-	xorb	(%rdi,%rdx,1),%r8b
-	rorl	$8,%r8d
-	addb	%al,%cl
-	leaq	1(%r10),%rsi
-	movzbl	(%rdi,%rcx,1),%edx
-	movzbl	%sil,%esi
-	movzbl	(%rdi,%rsi,1),%ebx
-	movb	%al,(%rdi,%rcx,1)
-	cmpq	%rsi,%rcx
-	movb	%dl,(%rdi,%r10,1)
-	jne	L$cmov4
-	movq	%rax,%rbx
-L$cmov4:
-	addb	%al,%dl
-	xorb	(%rdi,%rdx,1),%r9b
-	rorl	$8,%r9d
-	addb	%bl,%cl
-	leaq	1(%rsi),%r10
-	movzbl	(%rdi,%rcx,1),%edx
-	movzbl	%r10b,%r10d
-	movzbl	(%rdi,%r10,1),%eax
-	movb	%bl,(%rdi,%rcx,1)
-	cmpq	%r10,%rcx
-	movb	%dl,(%rdi,%rsi,1)
-	jne	L$cmov5
-	movq	%rbx,%rax
-L$cmov5:
-	addb	%bl,%dl
-	xorb	(%rdi,%rdx,1),%r9b
-	rorl	$8,%r9d
-	addb	%al,%cl
-	leaq	1(%r10),%rsi
-	movzbl	(%rdi,%rcx,1),%edx
-	movzbl	%sil,%esi
-	movzbl	(%rdi,%rsi,1),%ebx
-	movb	%al,(%rdi,%rcx,1)
-	cmpq	%rsi,%rcx
-	movb	%dl,(%rdi,%r10,1)
-	jne	L$cmov6
-	movq	%rax,%rbx
-L$cmov6:
-	addb	%al,%dl
-	xorb	(%rdi,%rdx,1),%r9b
-	rorl	$8,%r9d
-	addb	%bl,%cl
-	leaq	1(%rsi),%r10
-	movzbl	(%rdi,%rcx,1),%edx
-	movzbl	%r10b,%r10d
-	movzbl	(%rdi,%r10,1),%eax
-	movb	%bl,(%rdi,%rcx,1)
-	cmpq	%r10,%rcx
-	movb	%dl,(%rdi,%rsi,1)
-	jne	L$cmov7
-	movq	%rbx,%rax
-L$cmov7:
-	addb	%bl,%dl
-	xorb	(%rdi,%rdx,1),%r9b
-	rorl	$8,%r9d
-	leaq	-8(%r11),%r11
-	movl	%r8d,(%r13)
-	leaq	8(%r12),%r12
-	movl	%r9d,4(%r13)
-	leaq	8(%r13),%r13
-
-	testq	$-8,%r11
-	jnz	L$cloop8
-	cmpq	$0,%r11
-	jne	L$cloop1
-	jmp	L$exit
-.p2align	4
-L$cloop1:
-	addb	%al,%cl
-	movzbl	%cl,%ecx
-	movzbl	(%rdi,%rcx,1),%edx
-	movb	%al,(%rdi,%rcx,1)
-	movb	%dl,(%rdi,%r10,1)
-	addb	%al,%dl
-	addb	$1,%r10b
-	movzbl	%dl,%edx
-	movzbl	%r10b,%r10d
-	movzbl	(%rdi,%rdx,1),%edx
-	movzbl	(%rdi,%r10,1),%eax
-	xorb	(%r12),%dl
-	leaq	1(%r12),%r12
-	movb	%dl,(%r13)
-	leaq	1(%r13),%r13
-	subq	$1,%r11
-	jnz	L$cloop1
-	jmp	L$exit
-
-.p2align	4
-L$exit:
-	subb	$1,%r10b
-	movl	%r10d,-8(%rdi)
-	movl	%ecx,-4(%rdi)
-
-	movq	(%rsp),%r13
-	movq	8(%rsp),%r12
-	movq	16(%rsp),%rbx
-	addq	$24,%rsp
-L$epilogue:
-	.byte	0xf3,0xc3
-
-.globl	_asm_RC4_set_key
-.private_extern _asm_RC4_set_key
-
-.p2align	4
-_asm_RC4_set_key:
-	leaq	8(%rdi),%rdi
-	leaq	(%rdx,%rsi,1),%rdx
-	negq	%rsi
-	movq	%rsi,%rcx
-	xorl	%eax,%eax
-	xorq	%r9,%r9
-	xorq	%r10,%r10
-	xorq	%r11,%r11
-
-	movl	_OPENSSL_ia32cap_P(%rip),%r8d
-	btl	$20,%r8d
-	jc	L$c1stloop
-	jmp	L$w1stloop
-
-.p2align	4
-L$w1stloop:
-	movl	%eax,(%rdi,%rax,4)
-	addb	$1,%al
-	jnc	L$w1stloop
-
-	xorq	%r9,%r9
-	xorq	%r8,%r8
-.p2align	4
-L$w2ndloop:
-	movl	(%rdi,%r9,4),%r10d
-	addb	(%rdx,%rsi,1),%r8b
-	addb	%r10b,%r8b
-	addq	$1,%rsi
-	movl	(%rdi,%r8,4),%r11d
-	cmovzq	%rcx,%rsi
-	movl	%r10d,(%rdi,%r8,4)
-	movl	%r11d,(%rdi,%r9,4)
-	addb	$1,%r9b
-	jnc	L$w2ndloop
-	jmp	L$exit_key
-
-.p2align	4
-L$c1stloop:
-	movb	%al,(%rdi,%rax,1)
-	addb	$1,%al
-	jnc	L$c1stloop
-
-	xorq	%r9,%r9
-	xorq	%r8,%r8
-.p2align	4
-L$c2ndloop:
-	movb	(%rdi,%r9,1),%r10b
-	addb	(%rdx,%rsi,1),%r8b
-	addb	%r10b,%r8b
-	addq	$1,%rsi
-	movb	(%rdi,%r8,1),%r11b
-	jnz	L$cnowrap
-	movq	%rcx,%rsi
-L$cnowrap:
-	movb	%r10b,(%rdi,%r8,1)
-	movb	%r11b,(%rdi,%r9,1)
-	addb	$1,%r9b
-	jnc	L$c2ndloop
-	movl	$-1,256(%rdi)
-
-.p2align	4
-L$exit_key:
-	xorl	%eax,%eax
-	movl	%eax,-8(%rdi)
-	movl	%eax,-4(%rdi)
-	.byte	0xf3,0xc3
-
-#endif
diff --git a/mac-x86_64/crypto/sha/sha1-x86_64.S b/mac-x86_64/crypto/sha/sha1-x86_64.S
index 0509d45..cf45d8a 100644
--- a/mac-x86_64/crypto/sha/sha1-x86_64.S
+++ b/mac-x86_64/crypto/sha/sha1-x86_64.S
@@ -1240,14 +1240,13 @@
 .p2align	4
 sha1_block_data_order_ssse3:
 _ssse3_shortcut:
-	movq	%rsp,%rax
+	movq	%rsp,%r11
 	pushq	%rbx
 	pushq	%rbp
 	pushq	%r12
 	pushq	%r13
 	pushq	%r14
 	leaq	-64(%rsp),%rsp
-	movq	%rax,%r14
 	andq	$-64,%rsp
 	movq	%rdi,%r8
 	movq	%rsi,%r9
@@ -1255,7 +1254,7 @@
 
 	shlq	$6,%r10
 	addq	%r9,%r10
-	leaq	K_XX_XX+64(%rip),%r11
+	leaq	K_XX_XX+64(%rip),%r14
 
 	movl	0(%r8),%eax
 	movl	4(%r8),%ebx
@@ -1267,8 +1266,8 @@
 	xorl	%edx,%edi
 	andl	%edi,%esi
 
-	movdqa	64(%r11),%xmm6
-	movdqa	-64(%r11),%xmm9
+	movdqa	64(%r14),%xmm6
+	movdqa	-64(%r14),%xmm9
 	movdqu	0(%r9),%xmm0
 	movdqu	16(%r9),%xmm1
 	movdqu	32(%r9),%xmm2
@@ -1344,7 +1343,7 @@
 	pslld	$2,%xmm9
 	pxor	%xmm10,%xmm4
 	xorl	%ebp,%edx
-	movdqa	-64(%r11),%xmm10
+	movdqa	-64(%r14),%xmm10
 	roll	$5,%ecx
 	addl	%edi,%ebx
 	andl	%edx,%esi
@@ -1405,7 +1404,7 @@
 	pslld	$2,%xmm10
 	pxor	%xmm8,%xmm5
 	xorl	%eax,%ebp
-	movdqa	-32(%r11),%xmm8
+	movdqa	-32(%r14),%xmm8
 	roll	$5,%edx
 	addl	%edi,%ecx
 	andl	%ebp,%esi
@@ -1466,7 +1465,7 @@
 	pslld	$2,%xmm8
 	pxor	%xmm9,%xmm6
 	xorl	%ebx,%eax
-	movdqa	-32(%r11),%xmm9
+	movdqa	-32(%r14),%xmm9
 	roll	$5,%ebp
 	addl	%edi,%edx
 	andl	%eax,%esi
@@ -1527,7 +1526,7 @@
 	pslld	$2,%xmm9
 	pxor	%xmm10,%xmm7
 	xorl	%ecx,%ebx
-	movdqa	-32(%r11),%xmm10
+	movdqa	-32(%r14),%xmm10
 	roll	$5,%eax
 	addl	%edi,%ebp
 	andl	%ebx,%esi
@@ -1638,7 +1637,7 @@
 	pxor	%xmm3,%xmm2
 	addl	%esi,%eax
 	xorl	%edx,%edi
-	movdqa	0(%r11),%xmm10
+	movdqa	0(%r14),%xmm10
 	rorl	$7,%ecx
 	paddd	%xmm1,%xmm9
 	addl	%ebx,%eax
@@ -1873,7 +1872,7 @@
 	pxor	%xmm0,%xmm7
 	roll	$5,%ebx
 	addl	%esi,%eax
-	movdqa	32(%r11),%xmm9
+	movdqa	32(%r14),%xmm9
 	xorl	%ecx,%edi
 	paddd	%xmm6,%xmm8
 	xorl	%edx,%ecx
@@ -2164,8 +2163,8 @@
 	addl	%edx,%ecx
 	cmpq	%r10,%r9
 	je	L$done_ssse3
-	movdqa	64(%r11),%xmm6
-	movdqa	-64(%r11),%xmm9
+	movdqa	64(%r14),%xmm6
+	movdqa	-64(%r14),%xmm9
 	movdqu	0(%r9),%xmm0
 	movdqu	16(%r9),%xmm1
 	movdqu	32(%r9),%xmm2
@@ -2402,13 +2401,12 @@
 	movl	%ecx,8(%r8)
 	movl	%edx,12(%r8)
 	movl	%ebp,16(%r8)
-	leaq	(%r14),%rsi
-	movq	-40(%rsi),%r14
-	movq	-32(%rsi),%r13
-	movq	-24(%rsi),%r12
-	movq	-16(%rsi),%rbp
-	movq	-8(%rsi),%rbx
-	leaq	(%rsi),%rsp
+	movq	-40(%r11),%r14
+	movq	-32(%r11),%r13
+	movq	-24(%r11),%r12
+	movq	-16(%r11),%rbp
+	movq	-8(%r11),%rbx
+	leaq	(%r11),%rsp
 L$epilogue_ssse3:
 	.byte	0xf3,0xc3
 
@@ -2416,7 +2414,7 @@
 .p2align	4
 sha1_block_data_order_avx:
 _avx_shortcut:
-	movq	%rsp,%rax
+	movq	%rsp,%r11
 	pushq	%rbx
 	pushq	%rbp
 	pushq	%r12
@@ -2424,7 +2422,6 @@
 	pushq	%r14
 	leaq	-64(%rsp),%rsp
 	vzeroupper
-	movq	%rax,%r14
 	andq	$-64,%rsp
 	movq	%rdi,%r8
 	movq	%rsi,%r9
@@ -2432,7 +2429,7 @@
 
 	shlq	$6,%r10
 	addq	%r9,%r10
-	leaq	K_XX_XX+64(%rip),%r11
+	leaq	K_XX_XX+64(%rip),%r14
 
 	movl	0(%r8),%eax
 	movl	4(%r8),%ebx
@@ -2444,8 +2441,8 @@
 	xorl	%edx,%edi
 	andl	%edi,%esi
 
-	vmovdqa	64(%r11),%xmm6
-	vmovdqa	-64(%r11),%xmm11
+	vmovdqa	64(%r14),%xmm6
+	vmovdqa	-64(%r14),%xmm11
 	vmovdqu	0(%r9),%xmm0
 	vmovdqu	16(%r9),%xmm1
 	vmovdqu	32(%r9),%xmm2
@@ -2570,7 +2567,7 @@
 	vpxor	%xmm10,%xmm5,%xmm5
 	xorl	%eax,%ebp
 	shldl	$5,%edx,%edx
-	vmovdqa	-32(%r11),%xmm11
+	vmovdqa	-32(%r14),%xmm11
 	addl	%edi,%ecx
 	andl	%ebp,%esi
 	xorl	%eax,%ebp
@@ -2783,7 +2780,7 @@
 	addl	%esi,%eax
 	xorl	%edx,%edi
 	vpaddd	%xmm1,%xmm11,%xmm9
-	vmovdqa	0(%r11),%xmm11
+	vmovdqa	0(%r14),%xmm11
 	shrdl	$7,%ecx,%ecx
 	addl	%ebx,%eax
 	vpxor	%xmm8,%xmm2,%xmm2
@@ -3002,7 +2999,7 @@
 	movl	%ebx,%edi
 	xorl	%edx,%esi
 	vpaddd	%xmm6,%xmm11,%xmm9
-	vmovdqa	32(%r11),%xmm11
+	vmovdqa	32(%r14),%xmm11
 	shldl	$5,%ebx,%ebx
 	addl	%esi,%eax
 	vpxor	%xmm8,%xmm7,%xmm7
@@ -3281,8 +3278,8 @@
 	addl	%edx,%ecx
 	cmpq	%r10,%r9
 	je	L$done_avx
-	vmovdqa	64(%r11),%xmm6
-	vmovdqa	-64(%r11),%xmm11
+	vmovdqa	64(%r14),%xmm6
+	vmovdqa	-64(%r14),%xmm11
 	vmovdqu	0(%r9),%xmm0
 	vmovdqu	16(%r9),%xmm1
 	vmovdqu	32(%r9),%xmm2
@@ -3518,13 +3515,12 @@
 	movl	%ecx,8(%r8)
 	movl	%edx,12(%r8)
 	movl	%ebp,16(%r8)
-	leaq	(%r14),%rsi
-	movq	-40(%rsi),%r14
-	movq	-32(%rsi),%r13
-	movq	-24(%rsi),%r12
-	movq	-16(%rsi),%rbp
-	movq	-8(%rsi),%rbx
-	leaq	(%rsi),%rsp
+	movq	-40(%r11),%r14
+	movq	-32(%r11),%r13
+	movq	-24(%r11),%r12
+	movq	-16(%r11),%rbp
+	movq	-8(%r11),%rbx
+	leaq	(%r11),%rsp
 L$epilogue_avx:
 	.byte	0xf3,0xc3
 
diff --git a/mac-x86_64/crypto/sha/sha256-x86_64.S b/mac-x86_64/crypto/sha/sha256-x86_64.S
index 0146ff5..f00ef6d 100644
--- a/mac-x86_64/crypto/sha/sha256-x86_64.S
+++ b/mac-x86_64/crypto/sha/sha256-x86_64.S
@@ -18,13 +18,13 @@
 	je	L$avx_shortcut
 	testl	$512,%r10d
 	jnz	L$ssse3_shortcut
+	movq	%rsp,%rax
 	pushq	%rbx
 	pushq	%rbp
 	pushq	%r12
 	pushq	%r13
 	pushq	%r14
 	pushq	%r15
-	movq	%rsp,%r11
 	shlq	$4,%rdx
 	subq	$64+32,%rsp
 	leaq	(%rsi,%rdx,4),%rdx
@@ -32,7 +32,7 @@
 	movq	%rdi,64+0(%rsp)
 	movq	%rsi,64+8(%rsp)
 	movq	%rdx,64+16(%rsp)
-	movq	%r11,64+24(%rsp)
+	movq	%rax,64+24(%rsp)
 L$prologue:
 
 	movl	0(%rdi),%eax
@@ -1697,13 +1697,13 @@
 	jb	L$loop
 
 	movq	64+24(%rsp),%rsi
-	movq	(%rsi),%r15
-	movq	8(%rsi),%r14
-	movq	16(%rsi),%r13
-	movq	24(%rsi),%r12
-	movq	32(%rsi),%rbp
-	movq	40(%rsi),%rbx
-	leaq	48(%rsi),%rsp
+	movq	-48(%rsi),%r15
+	movq	-40(%rsi),%r14
+	movq	-32(%rsi),%r13
+	movq	-24(%rsi),%r12
+	movq	-16(%rsi),%rbp
+	movq	-8(%rsi),%rbx
+	leaq	(%rsi),%rsp
 L$epilogue:
 	.byte	0xf3,0xc3
 
@@ -1754,13 +1754,13 @@
 .p2align	6
 sha256_block_data_order_ssse3:
 L$ssse3_shortcut:
+	movq	%rsp,%rax
 	pushq	%rbx
 	pushq	%rbp
 	pushq	%r12
 	pushq	%r13
 	pushq	%r14
 	pushq	%r15
-	movq	%rsp,%r11
 	shlq	$4,%rdx
 	subq	$96,%rsp
 	leaq	(%rsi,%rdx,4),%rdx
@@ -1768,7 +1768,7 @@
 	movq	%rdi,64+0(%rsp)
 	movq	%rsi,64+8(%rsp)
 	movq	%rdx,64+16(%rsp)
-	movq	%r11,64+24(%rsp)
+	movq	%rax,64+24(%rsp)
 L$prologue_ssse3:
 
 	movl	0(%rdi),%eax
@@ -2835,13 +2835,13 @@
 	jb	L$loop_ssse3
 
 	movq	64+24(%rsp),%rsi
-	movq	(%rsi),%r15
-	movq	8(%rsi),%r14
-	movq	16(%rsi),%r13
-	movq	24(%rsi),%r12
-	movq	32(%rsi),%rbp
-	movq	40(%rsi),%rbx
-	leaq	48(%rsi),%rsp
+	movq	-48(%rsi),%r15
+	movq	-40(%rsi),%r14
+	movq	-32(%rsi),%r13
+	movq	-24(%rsi),%r12
+	movq	-16(%rsi),%rbp
+	movq	-8(%rsi),%rbx
+	leaq	(%rsi),%rsp
 L$epilogue_ssse3:
 	.byte	0xf3,0xc3
 
@@ -2849,13 +2849,13 @@
 .p2align	6
 sha256_block_data_order_avx:
 L$avx_shortcut:
+	movq	%rsp,%rax
 	pushq	%rbx
 	pushq	%rbp
 	pushq	%r12
 	pushq	%r13
 	pushq	%r14
 	pushq	%r15
-	movq	%rsp,%r11
 	shlq	$4,%rdx
 	subq	$96,%rsp
 	leaq	(%rsi,%rdx,4),%rdx
@@ -2863,7 +2863,7 @@
 	movq	%rdi,64+0(%rsp)
 	movq	%rsi,64+8(%rsp)
 	movq	%rdx,64+16(%rsp)
-	movq	%r11,64+24(%rsp)
+	movq	%rax,64+24(%rsp)
 L$prologue_avx:
 
 	vzeroupper
@@ -3892,13 +3892,13 @@
 
 	movq	64+24(%rsp),%rsi
 	vzeroupper
-	movq	(%rsi),%r15
-	movq	8(%rsi),%r14
-	movq	16(%rsi),%r13
-	movq	24(%rsi),%r12
-	movq	32(%rsi),%rbp
-	movq	40(%rsi),%rbx
-	leaq	48(%rsi),%rsp
+	movq	-48(%rsi),%r15
+	movq	-40(%rsi),%r14
+	movq	-32(%rsi),%r13
+	movq	-24(%rsi),%r12
+	movq	-16(%rsi),%rbp
+	movq	-8(%rsi),%rbx
+	leaq	(%rsi),%rsp
 L$epilogue_avx:
 	.byte	0xf3,0xc3
 
diff --git a/mac-x86_64/crypto/sha/sha512-x86_64.S b/mac-x86_64/crypto/sha/sha512-x86_64.S
index aeabd3f..eabcb3a 100644
--- a/mac-x86_64/crypto/sha/sha512-x86_64.S
+++ b/mac-x86_64/crypto/sha/sha512-x86_64.S
@@ -18,13 +18,13 @@
 	orl	%r9d,%r10d
 	cmpl	$1342177792,%r10d
 	je	L$avx_shortcut
+	movq	%rsp,%rax
 	pushq	%rbx
 	pushq	%rbp
 	pushq	%r12
 	pushq	%r13
 	pushq	%r14
 	pushq	%r15
-	movq	%rsp,%r11
 	shlq	$4,%rdx
 	subq	$128+32,%rsp
 	leaq	(%rsi,%rdx,8),%rdx
@@ -32,7 +32,7 @@
 	movq	%rdi,128+0(%rsp)
 	movq	%rsi,128+8(%rsp)
 	movq	%rdx,128+16(%rsp)
-	movq	%r11,128+24(%rsp)
+	movq	%rax,128+24(%rsp)
 L$prologue:
 
 	movq	0(%rdi),%rax
@@ -1697,13 +1697,13 @@
 	jb	L$loop
 
 	movq	128+24(%rsp),%rsi
-	movq	(%rsi),%r15
-	movq	8(%rsi),%r14
-	movq	16(%rsi),%r13
-	movq	24(%rsi),%r12
-	movq	32(%rsi),%rbp
-	movq	40(%rsi),%rbx
-	leaq	48(%rsi),%rsp
+	movq	-48(%rsi),%r15
+	movq	-40(%rsi),%r14
+	movq	-32(%rsi),%r13
+	movq	-24(%rsi),%r12
+	movq	-16(%rsi),%rbp
+	movq	-8(%rsi),%rbx
+	leaq	(%rsi),%rsp
 L$epilogue:
 	.byte	0xf3,0xc3
 
@@ -1798,13 +1798,13 @@
 .p2align	6
 sha512_block_data_order_xop:
 L$xop_shortcut:
+	movq	%rsp,%rax
 	pushq	%rbx
 	pushq	%rbp
 	pushq	%r12
 	pushq	%r13
 	pushq	%r14
 	pushq	%r15
-	movq	%rsp,%r11
 	shlq	$4,%rdx
 	subq	$160,%rsp
 	leaq	(%rsi,%rdx,8),%rdx
@@ -1812,7 +1812,7 @@
 	movq	%rdi,128+0(%rsp)
 	movq	%rsi,128+8(%rsp)
 	movq	%rdx,128+16(%rsp)
-	movq	%r11,128+24(%rsp)
+	movq	%rax,128+24(%rsp)
 L$prologue_xop:
 
 	vzeroupper
@@ -2867,13 +2867,13 @@
 
 	movq	128+24(%rsp),%rsi
 	vzeroupper
-	movq	(%rsi),%r15
-	movq	8(%rsi),%r14
-	movq	16(%rsi),%r13
-	movq	24(%rsi),%r12
-	movq	32(%rsi),%rbp
-	movq	40(%rsi),%rbx
-	leaq	48(%rsi),%rsp
+	movq	-48(%rsi),%r15
+	movq	-40(%rsi),%r14
+	movq	-32(%rsi),%r13
+	movq	-24(%rsi),%r12
+	movq	-16(%rsi),%rbp
+	movq	-8(%rsi),%rbx
+	leaq	(%rsi),%rsp
 L$epilogue_xop:
 	.byte	0xf3,0xc3
 
@@ -2881,13 +2881,13 @@
 .p2align	6
 sha512_block_data_order_avx:
 L$avx_shortcut:
+	movq	%rsp,%rax
 	pushq	%rbx
 	pushq	%rbp
 	pushq	%r12
 	pushq	%r13
 	pushq	%r14
 	pushq	%r15
-	movq	%rsp,%r11
 	shlq	$4,%rdx
 	subq	$160,%rsp
 	leaq	(%rsi,%rdx,8),%rdx
@@ -2895,7 +2895,7 @@
 	movq	%rdi,128+0(%rsp)
 	movq	%rsi,128+8(%rsp)
 	movq	%rdx,128+16(%rsp)
-	movq	%r11,128+24(%rsp)
+	movq	%rax,128+24(%rsp)
 L$prologue_avx:
 
 	vzeroupper
@@ -4014,13 +4014,13 @@
 
 	movq	128+24(%rsp),%rsi
 	vzeroupper
-	movq	(%rsi),%r15
-	movq	8(%rsi),%r14
-	movq	16(%rsi),%r13
-	movq	24(%rsi),%r12
-	movq	32(%rsi),%rbp
-	movq	40(%rsi),%rbx
-	leaq	48(%rsi),%rsp
+	movq	-48(%rsi),%r15
+	movq	-40(%rsi),%r14
+	movq	-32(%rsi),%r13
+	movq	-24(%rsi),%r12
+	movq	-16(%rsi),%rbp
+	movq	-8(%rsi),%rbx
+	leaq	(%rsi),%rsp
 L$epilogue_avx:
 	.byte	0xf3,0xc3
 
diff --git a/rules.mk b/rules.mk
index e2d5ae3..1a388c4 100644
--- a/rules.mk
+++ b/rules.mk
@@ -44,7 +44,6 @@
 # the functions defined in these files exists, the linker will be happy. If
 # such a path is created, it'll be a link-time error and something more complex
 # may need to be considered.
-LOCAL_SRC_FILES := $(filter-out android_compat_hacks.c,$(LOCAL_SRC_FILES))
 LOCAL_SRC_FILES := $(filter-out src/crypto/bio/connect.c,$(LOCAL_SRC_FILES))
 LOCAL_SRC_FILES := $(filter-out src/crypto/bio/fd.c,$(LOCAL_SRC_FILES))
 LOCAL_SRC_FILES := $(filter-out src/crypto/bio/file.c,$(LOCAL_SRC_FILES))
@@ -52,9 +51,8 @@
 LOCAL_SRC_FILES := $(filter-out src/crypto/bio/socket_helper.c,$(LOCAL_SRC_FILES))
 LOCAL_SRC_FILES := $(filter-out src/crypto/directory_posix.c,$(LOCAL_SRC_FILES))
 LOCAL_SRC_FILES := $(filter-out src/crypto/rand/urandom.c,$(LOCAL_SRC_FILES))
-LOCAL_SRC_FILES := $(filter-out src/crypto/time_support.c,$(LOCAL_SRC_FILES))
+LOCAL_SRC_FILES := $(filter-out src/crypto/asn1/time_support.c,$(LOCAL_SRC_FILES))
 LOCAL_SRC_FILES := $(filter-out src/crypto/x509/by_dir.c,$(LOCAL_SRC_FILES))
-LOCAL_SRC_FILES := $(filter-out src/crypto/x509v3/v3_utl.c,$(LOCAL_SRC_FILES))
 
 # BoringSSL detects Trusty based on this define and does things like switch to
 # no-op threading functions.
@@ -77,6 +75,10 @@
 
 GLOBAL_INCLUDES += $(addprefix $(LOCAL_DIR)/,$(LOCAL_C_INCLUDES))
 
+# BoringSSL expects an STL to be available when building for C++11 to provide
+# scopers. Suppress those APIs.
+GLOBAL_CPPFLAGS += -DBORINGSSL_NO_CXX
+
 MODULE_DEPS := \
 	lib/openssl-stubs \
 
diff --git a/sources.bp b/sources.bp
new file mode 100644
index 0000000..cad184c
--- /dev/null
+++ b/sources.bp
@@ -0,0 +1,527 @@
+// Copyright (C) 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// This file is created by generate_build_files.py. Do not edit manually.
+
+cc_defaults {
+    name: "libcrypto_sources",
+    srcs: [
+        "err_data.c",
+        "src/crypto/aes/aes.c",
+        "src/crypto/aes/key_wrap.c",
+        "src/crypto/aes/mode_wrappers.c",
+        "src/crypto/asn1/a_bitstr.c",
+        "src/crypto/asn1/a_bool.c",
+        "src/crypto/asn1/a_d2i_fp.c",
+        "src/crypto/asn1/a_dup.c",
+        "src/crypto/asn1/a_enum.c",
+        "src/crypto/asn1/a_gentm.c",
+        "src/crypto/asn1/a_i2d_fp.c",
+        "src/crypto/asn1/a_int.c",
+        "src/crypto/asn1/a_mbstr.c",
+        "src/crypto/asn1/a_object.c",
+        "src/crypto/asn1/a_octet.c",
+        "src/crypto/asn1/a_print.c",
+        "src/crypto/asn1/a_strnid.c",
+        "src/crypto/asn1/a_time.c",
+        "src/crypto/asn1/a_type.c",
+        "src/crypto/asn1/a_utctm.c",
+        "src/crypto/asn1/a_utf8.c",
+        "src/crypto/asn1/asn1_lib.c",
+        "src/crypto/asn1/asn1_par.c",
+        "src/crypto/asn1/asn_pack.c",
+        "src/crypto/asn1/f_enum.c",
+        "src/crypto/asn1/f_int.c",
+        "src/crypto/asn1/f_string.c",
+        "src/crypto/asn1/t_bitst.c",
+        "src/crypto/asn1/tasn_dec.c",
+        "src/crypto/asn1/tasn_enc.c",
+        "src/crypto/asn1/tasn_fre.c",
+        "src/crypto/asn1/tasn_new.c",
+        "src/crypto/asn1/tasn_typ.c",
+        "src/crypto/asn1/tasn_utl.c",
+        "src/crypto/asn1/time_support.c",
+        "src/crypto/base64/base64.c",
+        "src/crypto/bio/bio.c",
+        "src/crypto/bio/bio_mem.c",
+        "src/crypto/bio/connect.c",
+        "src/crypto/bio/fd.c",
+        "src/crypto/bio/file.c",
+        "src/crypto/bio/hexdump.c",
+        "src/crypto/bio/pair.c",
+        "src/crypto/bio/printf.c",
+        "src/crypto/bio/socket.c",
+        "src/crypto/bio/socket_helper.c",
+        "src/crypto/bn/add.c",
+        "src/crypto/bn/asm/x86_64-gcc.c",
+        "src/crypto/bn/bn.c",
+        "src/crypto/bn/bn_asn1.c",
+        "src/crypto/bn/cmp.c",
+        "src/crypto/bn/convert.c",
+        "src/crypto/bn/ctx.c",
+        "src/crypto/bn/div.c",
+        "src/crypto/bn/exponentiation.c",
+        "src/crypto/bn/gcd.c",
+        "src/crypto/bn/generic.c",
+        "src/crypto/bn/kronecker.c",
+        "src/crypto/bn/montgomery.c",
+        "src/crypto/bn/montgomery_inv.c",
+        "src/crypto/bn/mul.c",
+        "src/crypto/bn/prime.c",
+        "src/crypto/bn/random.c",
+        "src/crypto/bn/rsaz_exp.c",
+        "src/crypto/bn/shift.c",
+        "src/crypto/bn/sqrt.c",
+        "src/crypto/buf/buf.c",
+        "src/crypto/bytestring/asn1_compat.c",
+        "src/crypto/bytestring/ber.c",
+        "src/crypto/bytestring/cbb.c",
+        "src/crypto/bytestring/cbs.c",
+        "src/crypto/chacha/chacha.c",
+        "src/crypto/cipher/aead.c",
+        "src/crypto/cipher/cipher.c",
+        "src/crypto/cipher/derive_key.c",
+        "src/crypto/cipher/e_aes.c",
+        "src/crypto/cipher/e_chacha20poly1305.c",
+        "src/crypto/cipher/e_des.c",
+        "src/crypto/cipher/e_null.c",
+        "src/crypto/cipher/e_rc2.c",
+        "src/crypto/cipher/e_rc4.c",
+        "src/crypto/cipher/e_ssl3.c",
+        "src/crypto/cipher/e_tls.c",
+        "src/crypto/cipher/tls_cbc.c",
+        "src/crypto/cmac/cmac.c",
+        "src/crypto/conf/conf.c",
+        "src/crypto/cpu-aarch64-linux.c",
+        "src/crypto/cpu-arm-linux.c",
+        "src/crypto/cpu-arm.c",
+        "src/crypto/cpu-intel.c",
+        "src/crypto/cpu-ppc64le.c",
+        "src/crypto/crypto.c",
+        "src/crypto/curve25519/curve25519.c",
+        "src/crypto/curve25519/spake25519.c",
+        "src/crypto/curve25519/x25519-x86_64.c",
+        "src/crypto/des/des.c",
+        "src/crypto/dh/check.c",
+        "src/crypto/dh/dh.c",
+        "src/crypto/dh/dh_asn1.c",
+        "src/crypto/dh/params.c",
+        "src/crypto/digest/digest.c",
+        "src/crypto/digest/digests.c",
+        "src/crypto/dsa/dsa.c",
+        "src/crypto/dsa/dsa_asn1.c",
+        "src/crypto/ec/ec.c",
+        "src/crypto/ec/ec_asn1.c",
+        "src/crypto/ec/ec_key.c",
+        "src/crypto/ec/ec_montgomery.c",
+        "src/crypto/ec/oct.c",
+        "src/crypto/ec/p224-64.c",
+        "src/crypto/ec/p256-64.c",
+        "src/crypto/ec/p256-x86_64.c",
+        "src/crypto/ec/simple.c",
+        "src/crypto/ec/util-64.c",
+        "src/crypto/ec/wnaf.c",
+        "src/crypto/ecdh/ecdh.c",
+        "src/crypto/ecdsa/ecdsa.c",
+        "src/crypto/ecdsa/ecdsa_asn1.c",
+        "src/crypto/engine/engine.c",
+        "src/crypto/err/err.c",
+        "src/crypto/evp/digestsign.c",
+        "src/crypto/evp/evp.c",
+        "src/crypto/evp/evp_asn1.c",
+        "src/crypto/evp/evp_ctx.c",
+        "src/crypto/evp/p_dsa_asn1.c",
+        "src/crypto/evp/p_ec.c",
+        "src/crypto/evp/p_ec_asn1.c",
+        "src/crypto/evp/p_rsa.c",
+        "src/crypto/evp/p_rsa_asn1.c",
+        "src/crypto/evp/pbkdf.c",
+        "src/crypto/evp/print.c",
+        "src/crypto/evp/sign.c",
+        "src/crypto/ex_data.c",
+        "src/crypto/hkdf/hkdf.c",
+        "src/crypto/hmac/hmac.c",
+        "src/crypto/lhash/lhash.c",
+        "src/crypto/md4/md4.c",
+        "src/crypto/md5/md5.c",
+        "src/crypto/mem.c",
+        "src/crypto/modes/cbc.c",
+        "src/crypto/modes/cfb.c",
+        "src/crypto/modes/ctr.c",
+        "src/crypto/modes/gcm.c",
+        "src/crypto/modes/ofb.c",
+        "src/crypto/modes/polyval.c",
+        "src/crypto/obj/obj.c",
+        "src/crypto/obj/obj_xref.c",
+        "src/crypto/pem/pem_all.c",
+        "src/crypto/pem/pem_info.c",
+        "src/crypto/pem/pem_lib.c",
+        "src/crypto/pem/pem_oth.c",
+        "src/crypto/pem/pem_pk8.c",
+        "src/crypto/pem/pem_pkey.c",
+        "src/crypto/pem/pem_x509.c",
+        "src/crypto/pem/pem_xaux.c",
+        "src/crypto/pkcs8/p5_pbev2.c",
+        "src/crypto/pkcs8/pkcs8.c",
+        "src/crypto/pkcs8/pkcs8_x509.c",
+        "src/crypto/poly1305/poly1305.c",
+        "src/crypto/poly1305/poly1305_arm.c",
+        "src/crypto/poly1305/poly1305_vec.c",
+        "src/crypto/pool/pool.c",
+        "src/crypto/rand/deterministic.c",
+        "src/crypto/rand/fuchsia.c",
+        "src/crypto/rand/rand.c",
+        "src/crypto/rand/urandom.c",
+        "src/crypto/rand/windows.c",
+        "src/crypto/rc4/rc4.c",
+        "src/crypto/refcount_c11.c",
+        "src/crypto/refcount_lock.c",
+        "src/crypto/rsa/blinding.c",
+        "src/crypto/rsa/padding.c",
+        "src/crypto/rsa/rsa.c",
+        "src/crypto/rsa/rsa_asn1.c",
+        "src/crypto/rsa/rsa_impl.c",
+        "src/crypto/sha/sha1-altivec.c",
+        "src/crypto/sha/sha1.c",
+        "src/crypto/sha/sha256.c",
+        "src/crypto/sha/sha512.c",
+        "src/crypto/stack/stack.c",
+        "src/crypto/thread.c",
+        "src/crypto/thread_none.c",
+        "src/crypto/thread_pthread.c",
+        "src/crypto/thread_win.c",
+        "src/crypto/x509/a_digest.c",
+        "src/crypto/x509/a_sign.c",
+        "src/crypto/x509/a_strex.c",
+        "src/crypto/x509/a_verify.c",
+        "src/crypto/x509/algorithm.c",
+        "src/crypto/x509/asn1_gen.c",
+        "src/crypto/x509/by_dir.c",
+        "src/crypto/x509/by_file.c",
+        "src/crypto/x509/i2d_pr.c",
+        "src/crypto/x509/pkcs7.c",
+        "src/crypto/x509/rsa_pss.c",
+        "src/crypto/x509/t_crl.c",
+        "src/crypto/x509/t_req.c",
+        "src/crypto/x509/t_x509.c",
+        "src/crypto/x509/t_x509a.c",
+        "src/crypto/x509/x509.c",
+        "src/crypto/x509/x509_att.c",
+        "src/crypto/x509/x509_cmp.c",
+        "src/crypto/x509/x509_d2.c",
+        "src/crypto/x509/x509_def.c",
+        "src/crypto/x509/x509_ext.c",
+        "src/crypto/x509/x509_lu.c",
+        "src/crypto/x509/x509_obj.c",
+        "src/crypto/x509/x509_r2x.c",
+        "src/crypto/x509/x509_req.c",
+        "src/crypto/x509/x509_set.c",
+        "src/crypto/x509/x509_trs.c",
+        "src/crypto/x509/x509_txt.c",
+        "src/crypto/x509/x509_v3.c",
+        "src/crypto/x509/x509_vfy.c",
+        "src/crypto/x509/x509_vpm.c",
+        "src/crypto/x509/x509cset.c",
+        "src/crypto/x509/x509name.c",
+        "src/crypto/x509/x509rset.c",
+        "src/crypto/x509/x509spki.c",
+        "src/crypto/x509/x509type.c",
+        "src/crypto/x509/x_algor.c",
+        "src/crypto/x509/x_all.c",
+        "src/crypto/x509/x_attrib.c",
+        "src/crypto/x509/x_crl.c",
+        "src/crypto/x509/x_exten.c",
+        "src/crypto/x509/x_info.c",
+        "src/crypto/x509/x_name.c",
+        "src/crypto/x509/x_pkey.c",
+        "src/crypto/x509/x_pubkey.c",
+        "src/crypto/x509/x_req.c",
+        "src/crypto/x509/x_sig.c",
+        "src/crypto/x509/x_spki.c",
+        "src/crypto/x509/x_val.c",
+        "src/crypto/x509/x_x509.c",
+        "src/crypto/x509/x_x509a.c",
+        "src/crypto/x509v3/pcy_cache.c",
+        "src/crypto/x509v3/pcy_data.c",
+        "src/crypto/x509v3/pcy_lib.c",
+        "src/crypto/x509v3/pcy_map.c",
+        "src/crypto/x509v3/pcy_node.c",
+        "src/crypto/x509v3/pcy_tree.c",
+        "src/crypto/x509v3/v3_akey.c",
+        "src/crypto/x509v3/v3_akeya.c",
+        "src/crypto/x509v3/v3_alt.c",
+        "src/crypto/x509v3/v3_bcons.c",
+        "src/crypto/x509v3/v3_bitst.c",
+        "src/crypto/x509v3/v3_conf.c",
+        "src/crypto/x509v3/v3_cpols.c",
+        "src/crypto/x509v3/v3_crld.c",
+        "src/crypto/x509v3/v3_enum.c",
+        "src/crypto/x509v3/v3_extku.c",
+        "src/crypto/x509v3/v3_genn.c",
+        "src/crypto/x509v3/v3_ia5.c",
+        "src/crypto/x509v3/v3_info.c",
+        "src/crypto/x509v3/v3_int.c",
+        "src/crypto/x509v3/v3_lib.c",
+        "src/crypto/x509v3/v3_ncons.c",
+        "src/crypto/x509v3/v3_pci.c",
+        "src/crypto/x509v3/v3_pcia.c",
+        "src/crypto/x509v3/v3_pcons.c",
+        "src/crypto/x509v3/v3_pku.c",
+        "src/crypto/x509v3/v3_pmaps.c",
+        "src/crypto/x509v3/v3_prn.c",
+        "src/crypto/x509v3/v3_purp.c",
+        "src/crypto/x509v3/v3_skey.c",
+        "src/crypto/x509v3/v3_sxnet.c",
+        "src/crypto/x509v3/v3_utl.c",
+    ],
+    target: {
+        android_arm64: {
+            srcs: [
+                "linux-aarch64/crypto/aes/aesv8-armx64.S",
+                "linux-aarch64/crypto/bn/armv8-mont.S",
+                "linux-aarch64/crypto/chacha/chacha-armv8.S",
+                "linux-aarch64/crypto/modes/ghashv8-armx64.S",
+                "linux-aarch64/crypto/sha/sha1-armv8.S",
+                "linux-aarch64/crypto/sha/sha256-armv8.S",
+                "linux-aarch64/crypto/sha/sha512-armv8.S",
+            ],
+        },
+        android_arm: {
+            srcs: [
+                "linux-arm/crypto/aes/aes-armv4.S",
+                "linux-arm/crypto/aes/aesv8-armx32.S",
+                "linux-arm/crypto/aes/bsaes-armv7.S",
+                "linux-arm/crypto/bn/armv4-mont.S",
+                "linux-arm/crypto/chacha/chacha-armv4.S",
+                "linux-arm/crypto/modes/ghash-armv4.S",
+                "linux-arm/crypto/modes/ghashv8-armx32.S",
+                "linux-arm/crypto/sha/sha1-armv4-large.S",
+                "linux-arm/crypto/sha/sha256-armv4.S",
+                "linux-arm/crypto/sha/sha512-armv4.S",
+                "src/crypto/curve25519/asm/x25519-asm-arm.S",
+                "src/crypto/poly1305/poly1305_arm_asm.S",
+            ],
+        },
+        android_x86: {
+            srcs: [
+                "linux-x86/crypto/aes/aes-586.S",
+                "linux-x86/crypto/aes/aesni-x86.S",
+                "linux-x86/crypto/aes/vpaes-x86.S",
+                "linux-x86/crypto/bn/bn-586.S",
+                "linux-x86/crypto/bn/co-586.S",
+                "linux-x86/crypto/bn/x86-mont.S",
+                "linux-x86/crypto/chacha/chacha-x86.S",
+                "linux-x86/crypto/md5/md5-586.S",
+                "linux-x86/crypto/modes/ghash-x86.S",
+                "linux-x86/crypto/sha/sha1-586.S",
+                "linux-x86/crypto/sha/sha256-586.S",
+                "linux-x86/crypto/sha/sha512-586.S",
+            ],
+        },
+        linux_x86: {
+            srcs: [
+                "linux-x86/crypto/aes/aes-586.S",
+                "linux-x86/crypto/aes/aesni-x86.S",
+                "linux-x86/crypto/aes/vpaes-x86.S",
+                "linux-x86/crypto/bn/bn-586.S",
+                "linux-x86/crypto/bn/co-586.S",
+                "linux-x86/crypto/bn/x86-mont.S",
+                "linux-x86/crypto/chacha/chacha-x86.S",
+                "linux-x86/crypto/md5/md5-586.S",
+                "linux-x86/crypto/modes/ghash-x86.S",
+                "linux-x86/crypto/sha/sha1-586.S",
+                "linux-x86/crypto/sha/sha256-586.S",
+                "linux-x86/crypto/sha/sha512-586.S",
+            ],
+        },
+        android_x86_64: {
+            srcs: [
+                "linux-x86_64/crypto/aes/aes-x86_64.S",
+                "linux-x86_64/crypto/aes/aesni-x86_64.S",
+                "linux-x86_64/crypto/aes/bsaes-x86_64.S",
+                "linux-x86_64/crypto/aes/vpaes-x86_64.S",
+                "linux-x86_64/crypto/bn/rsaz-avx2.S",
+                "linux-x86_64/crypto/bn/x86_64-mont.S",
+                "linux-x86_64/crypto/bn/x86_64-mont5.S",
+                "linux-x86_64/crypto/chacha/chacha-x86_64.S",
+                "linux-x86_64/crypto/cipher/chacha20_poly1305_x86_64.S",
+                "linux-x86_64/crypto/ec/p256-x86_64-asm.S",
+                "linux-x86_64/crypto/md5/md5-x86_64.S",
+                "linux-x86_64/crypto/modes/aesni-gcm-x86_64.S",
+                "linux-x86_64/crypto/modes/ghash-x86_64.S",
+                "linux-x86_64/crypto/rand/rdrand-x86_64.S",
+                "linux-x86_64/crypto/sha/sha1-x86_64.S",
+                "linux-x86_64/crypto/sha/sha256-x86_64.S",
+                "linux-x86_64/crypto/sha/sha512-x86_64.S",
+                "src/crypto/curve25519/asm/x25519-asm-x86_64.S",
+            ],
+        },
+        linux_x86_64: {
+            srcs: [
+                "linux-x86_64/crypto/aes/aes-x86_64.S",
+                "linux-x86_64/crypto/aes/aesni-x86_64.S",
+                "linux-x86_64/crypto/aes/bsaes-x86_64.S",
+                "linux-x86_64/crypto/aes/vpaes-x86_64.S",
+                "linux-x86_64/crypto/bn/rsaz-avx2.S",
+                "linux-x86_64/crypto/bn/x86_64-mont.S",
+                "linux-x86_64/crypto/bn/x86_64-mont5.S",
+                "linux-x86_64/crypto/chacha/chacha-x86_64.S",
+                "linux-x86_64/crypto/cipher/chacha20_poly1305_x86_64.S",
+                "linux-x86_64/crypto/ec/p256-x86_64-asm.S",
+                "linux-x86_64/crypto/md5/md5-x86_64.S",
+                "linux-x86_64/crypto/modes/aesni-gcm-x86_64.S",
+                "linux-x86_64/crypto/modes/ghash-x86_64.S",
+                "linux-x86_64/crypto/rand/rdrand-x86_64.S",
+                "linux-x86_64/crypto/sha/sha1-x86_64.S",
+                "linux-x86_64/crypto/sha/sha256-x86_64.S",
+                "linux-x86_64/crypto/sha/sha512-x86_64.S",
+                "src/crypto/curve25519/asm/x25519-asm-x86_64.S",
+            ],
+        },
+    },
+}
+
+cc_defaults {
+    name: "libssl_sources",
+    srcs: [
+        "src/ssl/bio_ssl.c",
+        "src/ssl/custom_extensions.c",
+        "src/ssl/d1_both.c",
+        "src/ssl/d1_lib.c",
+        "src/ssl/d1_pkt.c",
+        "src/ssl/d1_srtp.c",
+        "src/ssl/dtls_method.c",
+        "src/ssl/dtls_record.c",
+        "src/ssl/handshake_client.c",
+        "src/ssl/handshake_server.c",
+        "src/ssl/s3_both.c",
+        "src/ssl/s3_lib.c",
+        "src/ssl/s3_pkt.c",
+        "src/ssl/ssl_aead_ctx.c",
+        "src/ssl/ssl_asn1.c",
+        "src/ssl/ssl_buffer.c",
+        "src/ssl/ssl_cert.c",
+        "src/ssl/ssl_cipher.c",
+        "src/ssl/ssl_ecdh.c",
+        "src/ssl/ssl_file.c",
+        "src/ssl/ssl_lib.c",
+        "src/ssl/ssl_privkey.c",
+        "src/ssl/ssl_privkey_cc.cc",
+        "src/ssl/ssl_session.c",
+        "src/ssl/ssl_stat.c",
+        "src/ssl/ssl_transcript.c",
+        "src/ssl/ssl_x509.c",
+        "src/ssl/t1_enc.c",
+        "src/ssl/t1_lib.c",
+        "src/ssl/tls13_both.c",
+        "src/ssl/tls13_client.c",
+        "src/ssl/tls13_enc.c",
+        "src/ssl/tls13_server.c",
+        "src/ssl/tls_method.c",
+        "src/ssl/tls_record.c",
+    ],
+}
+
+cc_defaults {
+    name: "bssl_sources",
+    srcs: [
+        "src/tool/args.cc",
+        "src/tool/ciphers.cc",
+        "src/tool/client.cc",
+        "src/tool/const.cc",
+        "src/tool/digest.cc",
+        "src/tool/generate_ed25519.cc",
+        "src/tool/genrsa.cc",
+        "src/tool/pkcs12.cc",
+        "src/tool/rand.cc",
+        "src/tool/server.cc",
+        "src/tool/speed.cc",
+        "src/tool/tool.cc",
+        "src/tool/transport_common.cc",
+    ],
+}
+
+cc_defaults {
+    name: "boringssl_test_support_sources",
+    srcs: [
+        "src/crypto/test/file_test.cc",
+        "src/crypto/test/malloc.cc",
+        "src/crypto/test/test_util.cc",
+    ],
+}
+
+cc_defaults {
+    name: "boringssl_crypto_test_sources",
+    srcs: [
+        "src/crypto/asn1/asn1_test.cc",
+        "src/crypto/bio/bio_test.cc",
+        "src/crypto/chacha/chacha_test.cc",
+        "src/crypto/constant_time_test.cc",
+        "src/crypto/curve25519/x25519_test.cc",
+        "src/crypto/dh/dh_test.cc",
+        "src/crypto/dsa/dsa_test.cc",
+        "src/crypto/ec/ec_test.cc",
+        "src/crypto/err/err_test.cc",
+        "src/crypto/evp/evp_extra_test.cc",
+        "src/crypto/rsa/rsa_test.cc",
+        "src/crypto/test/gtest_main.cc",
+    ],
+}
+
+cc_defaults {
+    name: "boringssl_ssl_test_sources",
+    srcs: [
+        "src/crypto/test/gtest_main.cc",
+        "src/ssl/ssl_test.cc",
+    ],
+}
+
+cc_defaults {
+    name: "boringssl_tests_sources",
+    srcs: [
+        "src/crypto/aes/aes_test.cc",
+        "src/crypto/base64/base64_test.cc",
+        "src/crypto/bn/bn_test.cc",
+        "src/crypto/bytestring/bytestring_test.cc",
+        "src/crypto/cipher/aead_test.cc",
+        "src/crypto/cipher/cipher_test.cc",
+        "src/crypto/cmac/cmac_test.cc",
+        "src/crypto/curve25519/ed25519_test.cc",
+        "src/crypto/curve25519/spake25519_test.cc",
+        "src/crypto/digest/digest_test.cc",
+        "src/crypto/ec/example_mul.c",
+        "src/crypto/ec/p256-x86_64_test.cc",
+        "src/crypto/ecdh/ecdh_test.cc",
+        "src/crypto/ecdsa/ecdsa_sign_test.cc",
+        "src/crypto/ecdsa/ecdsa_test.cc",
+        "src/crypto/ecdsa/ecdsa_verify_test.cc",
+        "src/crypto/evp/evp_test.cc",
+        "src/crypto/evp/pbkdf_test.cc",
+        "src/crypto/hkdf/hkdf_test.cc",
+        "src/crypto/hmac/hmac_test.cc",
+        "src/crypto/lhash/lhash_test.cc",
+        "src/crypto/modes/gcm_test.cc",
+        "src/crypto/obj/obj_test.cc",
+        "src/crypto/pkcs8/pkcs12_test.cc",
+        "src/crypto/pkcs8/pkcs8_test.cc",
+        "src/crypto/poly1305/poly1305_test.cc",
+        "src/crypto/pool/pool_test.cc",
+        "src/crypto/refcount_test.cc",
+        "src/crypto/thread_test.c",
+        "src/crypto/x509/pkcs7_test.c",
+        "src/crypto/x509/x509_test.cc",
+        "src/crypto/x509v3/tab_test.c",
+        "src/crypto/x509v3/v3name_test.c",
+    ],
+}
diff --git a/sources.mk b/sources.mk
index e82f3d5..d3d689d 100644
--- a/sources.mk
+++ b/sources.mk
@@ -12,15 +12,15 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# This file is created by generate_build_files.py. Do not edit manually.
+
 crypto_sources := \
-  android_compat_hacks.c\
-  android_compat_keywrap.c\
   err_data.c\
   src/crypto/aes/aes.c\
+  src/crypto/aes/key_wrap.c\
   src/crypto/aes/mode_wrappers.c\
   src/crypto/asn1/a_bitstr.c\
   src/crypto/asn1/a_bool.c\
-  src/crypto/asn1/a_bytes.c\
   src/crypto/asn1/a_d2i_fp.c\
   src/crypto/asn1/a_dup.c\
   src/crypto/asn1/a_enum.c\
@@ -39,26 +39,20 @@
   src/crypto/asn1/asn1_lib.c\
   src/crypto/asn1/asn1_par.c\
   src/crypto/asn1/asn_pack.c\
-  src/crypto/asn1/bio_asn1.c\
-  src/crypto/asn1/bio_ndef.c\
   src/crypto/asn1/f_enum.c\
   src/crypto/asn1/f_int.c\
   src/crypto/asn1/f_string.c\
   src/crypto/asn1/t_bitst.c\
-  src/crypto/asn1/t_pkey.c\
   src/crypto/asn1/tasn_dec.c\
   src/crypto/asn1/tasn_enc.c\
   src/crypto/asn1/tasn_fre.c\
   src/crypto/asn1/tasn_new.c\
-  src/crypto/asn1/tasn_prn.c\
   src/crypto/asn1/tasn_typ.c\
   src/crypto/asn1/tasn_utl.c\
-  src/crypto/asn1/x_bignum.c\
-  src/crypto/asn1/x_long.c\
+  src/crypto/asn1/time_support.c\
   src/crypto/base64/base64.c\
   src/crypto/bio/bio.c\
   src/crypto/bio/bio_mem.c\
-  src/crypto/bio/buffer.c\
   src/crypto/bio/connect.c\
   src/crypto/bio/fd.c\
   src/crypto/bio/file.c\
@@ -80,6 +74,7 @@
   src/crypto/bn/generic.c\
   src/crypto/bn/kronecker.c\
   src/crypto/bn/montgomery.c\
+  src/crypto/bn/montgomery_inv.c\
   src/crypto/bn/mul.c\
   src/crypto/bn/prime.c\
   src/crypto/bn/random.c\
@@ -87,11 +82,11 @@
   src/crypto/bn/shift.c\
   src/crypto/bn/sqrt.c\
   src/crypto/buf/buf.c\
+  src/crypto/bytestring/asn1_compat.c\
   src/crypto/bytestring/ber.c\
   src/crypto/bytestring/cbb.c\
   src/crypto/bytestring/cbs.c\
-  src/crypto/chacha/chacha_generic.c\
-  src/crypto/chacha/chacha_vec.c\
+  src/crypto/chacha/chacha.c\
   src/crypto/cipher/aead.c\
   src/crypto/cipher/cipher.c\
   src/crypto/cipher/derive_key.c\
@@ -106,10 +101,14 @@
   src/crypto/cipher/tls_cbc.c\
   src/crypto/cmac/cmac.c\
   src/crypto/conf/conf.c\
+  src/crypto/cpu-aarch64-linux.c\
+  src/crypto/cpu-arm-linux.c\
   src/crypto/cpu-arm.c\
   src/crypto/cpu-intel.c\
+  src/crypto/cpu-ppc64le.c\
   src/crypto/crypto.c\
   src/crypto/curve25519/curve25519.c\
+  src/crypto/curve25519/spake25519.c\
   src/crypto/curve25519/x25519-x86_64.c\
   src/crypto/des/des.c\
   src/crypto/dh/check.c\
@@ -118,8 +117,6 @@
   src/crypto/dh/params.c\
   src/crypto/digest/digest.c\
   src/crypto/digest/digests.c\
-  src/crypto/directory_posix.c\
-  src/crypto/directory_win.c\
   src/crypto/dsa/dsa.c\
   src/crypto/dsa/dsa_asn1.c\
   src/crypto/ec/ec.c\
@@ -138,7 +135,6 @@
   src/crypto/ecdsa/ecdsa_asn1.c\
   src/crypto/engine/engine.c\
   src/crypto/err/err.c\
-  src/crypto/evp/algorithm.c\
   src/crypto/evp/digestsign.c\
   src/crypto/evp/evp.c\
   src/crypto/evp/evp_asn1.c\
@@ -149,6 +145,7 @@
   src/crypto/evp/p_rsa.c\
   src/crypto/evp/p_rsa_asn1.c\
   src/crypto/evp/pbkdf.c\
+  src/crypto/evp/print.c\
   src/crypto/evp/sign.c\
   src/crypto/ex_data.c\
   src/crypto/hkdf/hkdf.c\
@@ -162,6 +159,7 @@
   src/crypto/modes/ctr.c\
   src/crypto/modes/gcm.c\
   src/crypto/modes/ofb.c\
+  src/crypto/modes/polyval.c\
   src/crypto/obj/obj.c\
   src/crypto/obj/obj_xref.c\
   src/crypto/pem/pem_all.c\
@@ -172,13 +170,15 @@
   src/crypto/pem/pem_pkey.c\
   src/crypto/pem/pem_x509.c\
   src/crypto/pem/pem_xaux.c\
-  src/crypto/pkcs8/p5_pbe.c\
   src/crypto/pkcs8/p5_pbev2.c\
-  src/crypto/pkcs8/p8_pkey.c\
   src/crypto/pkcs8/pkcs8.c\
+  src/crypto/pkcs8/pkcs8_x509.c\
   src/crypto/poly1305/poly1305.c\
   src/crypto/poly1305/poly1305_arm.c\
   src/crypto/poly1305/poly1305_vec.c\
+  src/crypto/pool/pool.c\
+  src/crypto/rand/deterministic.c\
+  src/crypto/rand/fuchsia.c\
   src/crypto/rand/rand.c\
   src/crypto/rand/urandom.c\
   src/crypto/rand/windows.c\
@@ -190,6 +190,7 @@
   src/crypto/rsa/rsa.c\
   src/crypto/rsa/rsa_asn1.c\
   src/crypto/rsa/rsa_impl.c\
+  src/crypto/sha/sha1-altivec.c\
   src/crypto/sha/sha1.c\
   src/crypto/sha/sha256.c\
   src/crypto/sha/sha512.c\
@@ -198,16 +199,17 @@
   src/crypto/thread_none.c\
   src/crypto/thread_pthread.c\
   src/crypto/thread_win.c\
-  src/crypto/time_support.c\
   src/crypto/x509/a_digest.c\
   src/crypto/x509/a_sign.c\
   src/crypto/x509/a_strex.c\
   src/crypto/x509/a_verify.c\
+  src/crypto/x509/algorithm.c\
   src/crypto/x509/asn1_gen.c\
   src/crypto/x509/by_dir.c\
   src/crypto/x509/by_file.c\
   src/crypto/x509/i2d_pr.c\
   src/crypto/x509/pkcs7.c\
+  src/crypto/x509/rsa_pss.c\
   src/crypto/x509/t_crl.c\
   src/crypto/x509/t_req.c\
   src/crypto/x509/t_x509.c\
@@ -281,57 +283,10 @@
   src/crypto/x509v3/v3_sxnet.c\
   src/crypto/x509v3/v3_utl.c\
 
-ssl_sources := \
-  src/ssl/custom_extensions.c\
-  src/ssl/d1_both.c\
-  src/ssl/d1_clnt.c\
-  src/ssl/d1_lib.c\
-  src/ssl/d1_meth.c\
-  src/ssl/d1_pkt.c\
-  src/ssl/d1_srtp.c\
-  src/ssl/d1_srvr.c\
-  src/ssl/dtls_record.c\
-  src/ssl/pqueue/pqueue.c\
-  src/ssl/s3_both.c\
-  src/ssl/s3_clnt.c\
-  src/ssl/s3_enc.c\
-  src/ssl/s3_lib.c\
-  src/ssl/s3_meth.c\
-  src/ssl/s3_pkt.c\
-  src/ssl/s3_srvr.c\
-  src/ssl/ssl_aead_ctx.c\
-  src/ssl/ssl_asn1.c\
-  src/ssl/ssl_buffer.c\
-  src/ssl/ssl_cert.c\
-  src/ssl/ssl_cipher.c\
-  src/ssl/ssl_ecdh.c\
-  src/ssl/ssl_file.c\
-  src/ssl/ssl_lib.c\
-  src/ssl/ssl_rsa.c\
-  src/ssl/ssl_session.c\
-  src/ssl/ssl_stat.c\
-  src/ssl/t1_enc.c\
-  src/ssl/t1_lib.c\
-  src/ssl/tls_record.c\
-
-tool_sources := \
-  src/tool/args.cc\
-  src/tool/ciphers.cc\
-  src/tool/client.cc\
-  src/tool/const.cc\
-  src/tool/digest.cc\
-  src/tool/generate_ed25519.cc\
-  src/tool/genrsa.cc\
-  src/tool/pkcs12.cc\
-  src/tool/rand.cc\
-  src/tool/server.cc\
-  src/tool/speed.cc\
-  src/tool/tool.cc\
-  src/tool/transport_common.cc\
-
 linux_aarch64_sources := \
   linux-aarch64/crypto/aes/aesv8-armx64.S\
   linux-aarch64/crypto/bn/armv8-mont.S\
+  linux-aarch64/crypto/chacha/chacha-armv8.S\
   linux-aarch64/crypto/modes/ghashv8-armx64.S\
   linux-aarch64/crypto/sha/sha1-armv8.S\
   linux-aarch64/crypto/sha/sha256-armv8.S\
@@ -342,16 +297,19 @@
   linux-arm/crypto/aes/aesv8-armx32.S\
   linux-arm/crypto/aes/bsaes-armv7.S\
   linux-arm/crypto/bn/armv4-mont.S\
+  linux-arm/crypto/chacha/chacha-armv4.S\
   linux-arm/crypto/modes/ghash-armv4.S\
   linux-arm/crypto/modes/ghashv8-armx32.S\
   linux-arm/crypto/sha/sha1-armv4-large.S\
   linux-arm/crypto/sha/sha256-armv4.S\
   linux-arm/crypto/sha/sha512-armv4.S\
-  src/crypto/chacha/chacha_vec_arm.S\
-  src/crypto/cpu-arm-asm.S\
   src/crypto/curve25519/asm/x25519-asm-arm.S\
   src/crypto/poly1305/poly1305_arm_asm.S\
 
+linux_ppc64le_sources := \
+  linux-ppc64le/crypto/aes/aesp8-ppc.S\
+  linux-ppc64le/crypto/modes/ghashp8-ppc.S\
+
 linux_x86_sources := \
   linux-x86/crypto/aes/aes-586.S\
   linux-x86/crypto/aes/aesni-x86.S\
@@ -359,9 +317,9 @@
   linux-x86/crypto/bn/bn-586.S\
   linux-x86/crypto/bn/co-586.S\
   linux-x86/crypto/bn/x86-mont.S\
+  linux-x86/crypto/chacha/chacha-x86.S\
   linux-x86/crypto/md5/md5-586.S\
   linux-x86/crypto/modes/ghash-x86.S\
-  linux-x86/crypto/rc4/rc4-586.S\
   linux-x86/crypto/sha/sha1-586.S\
   linux-x86/crypto/sha/sha256-586.S\
   linux-x86/crypto/sha/sha512-586.S\
@@ -372,82 +330,17 @@
   linux-x86_64/crypto/aes/bsaes-x86_64.S\
   linux-x86_64/crypto/aes/vpaes-x86_64.S\
   linux-x86_64/crypto/bn/rsaz-avx2.S\
-  linux-x86_64/crypto/bn/rsaz-x86_64.S\
   linux-x86_64/crypto/bn/x86_64-mont.S\
   linux-x86_64/crypto/bn/x86_64-mont5.S\
+  linux-x86_64/crypto/chacha/chacha-x86_64.S\
+  linux-x86_64/crypto/cipher/chacha20_poly1305_x86_64.S\
   linux-x86_64/crypto/ec/p256-x86_64-asm.S\
   linux-x86_64/crypto/md5/md5-x86_64.S\
   linux-x86_64/crypto/modes/aesni-gcm-x86_64.S\
   linux-x86_64/crypto/modes/ghash-x86_64.S\
   linux-x86_64/crypto/rand/rdrand-x86_64.S\
-  linux-x86_64/crypto/rc4/rc4-x86_64.S\
   linux-x86_64/crypto/sha/sha1-x86_64.S\
   linux-x86_64/crypto/sha/sha256-x86_64.S\
   linux-x86_64/crypto/sha/sha512-x86_64.S\
-
-mac_x86_sources := \
-  mac-x86/crypto/aes/aes-586.S\
-  mac-x86/crypto/aes/aesni-x86.S\
-  mac-x86/crypto/aes/vpaes-x86.S\
-  mac-x86/crypto/bn/bn-586.S\
-  mac-x86/crypto/bn/co-586.S\
-  mac-x86/crypto/bn/x86-mont.S\
-  mac-x86/crypto/md5/md5-586.S\
-  mac-x86/crypto/modes/ghash-x86.S\
-  mac-x86/crypto/rc4/rc4-586.S\
-  mac-x86/crypto/sha/sha1-586.S\
-  mac-x86/crypto/sha/sha256-586.S\
-  mac-x86/crypto/sha/sha512-586.S\
-
-mac_x86_64_sources := \
-  mac-x86_64/crypto/aes/aes-x86_64.S\
-  mac-x86_64/crypto/aes/aesni-x86_64.S\
-  mac-x86_64/crypto/aes/bsaes-x86_64.S\
-  mac-x86_64/crypto/aes/vpaes-x86_64.S\
-  mac-x86_64/crypto/bn/rsaz-avx2.S\
-  mac-x86_64/crypto/bn/rsaz-x86_64.S\
-  mac-x86_64/crypto/bn/x86_64-mont.S\
-  mac-x86_64/crypto/bn/x86_64-mont5.S\
-  mac-x86_64/crypto/ec/p256-x86_64-asm.S\
-  mac-x86_64/crypto/md5/md5-x86_64.S\
-  mac-x86_64/crypto/modes/aesni-gcm-x86_64.S\
-  mac-x86_64/crypto/modes/ghash-x86_64.S\
-  mac-x86_64/crypto/rand/rdrand-x86_64.S\
-  mac-x86_64/crypto/rc4/rc4-x86_64.S\
-  mac-x86_64/crypto/sha/sha1-x86_64.S\
-  mac-x86_64/crypto/sha/sha256-x86_64.S\
-  mac-x86_64/crypto/sha/sha512-x86_64.S\
-
-win_x86_sources := \
-  win-x86/crypto/aes/aes-586.asm\
-  win-x86/crypto/aes/aesni-x86.asm\
-  win-x86/crypto/aes/vpaes-x86.asm\
-  win-x86/crypto/bn/bn-586.asm\
-  win-x86/crypto/bn/co-586.asm\
-  win-x86/crypto/bn/x86-mont.asm\
-  win-x86/crypto/md5/md5-586.asm\
-  win-x86/crypto/modes/ghash-x86.asm\
-  win-x86/crypto/rc4/rc4-586.asm\
-  win-x86/crypto/sha/sha1-586.asm\
-  win-x86/crypto/sha/sha256-586.asm\
-  win-x86/crypto/sha/sha512-586.asm\
-
-win_x86_64_sources := \
-  win-x86_64/crypto/aes/aes-x86_64.asm\
-  win-x86_64/crypto/aes/aesni-x86_64.asm\
-  win-x86_64/crypto/aes/bsaes-x86_64.asm\
-  win-x86_64/crypto/aes/vpaes-x86_64.asm\
-  win-x86_64/crypto/bn/rsaz-avx2.asm\
-  win-x86_64/crypto/bn/rsaz-x86_64.asm\
-  win-x86_64/crypto/bn/x86_64-mont.asm\
-  win-x86_64/crypto/bn/x86_64-mont5.asm\
-  win-x86_64/crypto/ec/p256-x86_64-asm.asm\
-  win-x86_64/crypto/md5/md5-x86_64.asm\
-  win-x86_64/crypto/modes/aesni-gcm-x86_64.asm\
-  win-x86_64/crypto/modes/ghash-x86_64.asm\
-  win-x86_64/crypto/rand/rdrand-x86_64.asm\
-  win-x86_64/crypto/rc4/rc4-x86_64.asm\
-  win-x86_64/crypto/sha/sha1-x86_64.asm\
-  win-x86_64/crypto/sha/sha256-x86_64.asm\
-  win-x86_64/crypto/sha/sha512-x86_64.asm\
+  src/crypto/curve25519/asm/x25519-asm-x86_64.S\
 
diff --git a/src/.clang-format b/src/.clang-format
index 43032d4..5865a70 100644
--- a/src/.clang-format
+++ b/src/.clang-format
@@ -2,3 +2,6 @@
 MaxEmptyLinesToKeep: 3
 AllowShortIfStatementsOnASingleLine: false
 AllowShortLoopsOnASingleLine: false
+DerivePointerAlignment: false
+PointerAlignment: Right
+
diff --git a/src/.github/PULL_REQUEST_TEMPLATE b/src/.github/PULL_REQUEST_TEMPLATE
new file mode 100644
index 0000000..6c101ea
--- /dev/null
+++ b/src/.github/PULL_REQUEST_TEMPLATE
@@ -0,0 +1,7 @@
+Please do not send pull requests to the BoringSSL repository.
+
+We do, however, take contributions gladly.
+
+See https://boringssl.googlesource.com/boringssl/+/master/CONTRIBUTING.md
+
+Thanks!
diff --git a/src/.gitignore b/src/.gitignore
index a2e3ed2..9f396f6 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -4,3 +4,18 @@
 *.swo
 doc/*.html
 doc/doc.css
+
+util/bot/android_tools
+util/bot/cmake-linux64
+util/bot/cmake-linux64.tar.gz
+util/bot/cmake-mac
+util/bot/cmake-mac.tar.gz
+util/bot/cmake-win32
+util/bot/cmake-win32.zip
+util/bot/golang
+util/bot/gyp
+util/bot/llvm-build
+util/bot/perl-win32
+util/bot/perl-win32.zip
+util/bot/win_toolchain.json
+util/bot/yasm-win32.exe
diff --git a/src/API-CONVENTIONS.md b/src/API-CONVENTIONS.md
new file mode 100644
index 0000000..7b33797
--- /dev/null
+++ b/src/API-CONVENTIONS.md
@@ -0,0 +1,184 @@
+# BoringSSL API Conventions
+
+This document describes conventions for BoringSSL APIs. The [style
+guide](/STYLE.md) also includes guidelines, but this document is targeted at
+both API consumers and developers.
+
+
+## Documentation
+
+All supported public APIs are documented in the public header files, found in
+`include/openssl`. The API documentation is also available
+[online](https://commondatastorage.googleapis.com/chromium-boringssl-docs/headers.html).
+
+Some headers lack documention comments. These are functions and structures from
+OpenSSL's legacy ASN.1, X.509, and PEM implementation. If possible, avoid using
+them. These are left largely unmodified from upstream and are retained only for
+compatibility with existing OpenSSL consumers.
+
+
+## Forward declarations
+
+Do not write `typedef struct foo_st FOO` or try otherwise to define BoringSSL's
+types. Including `openssl/base.h` (or `openssl/ossl_typ.h` for consumers who
+wish to be OpenSSL-compatible) will forward-declare each type without importing
+the rest of the library or invasive macros.
+
+
+## Error-handling
+
+Most functions in BoringSSL may fail, either due to allocation failures or input
+errors. Functions which return an `int` typically return one on success and zero
+on failure. Functions which return a pointer typically return `NULL` on failure.
+However, due to legacy constraints, some functions are more complex. Consult the
+API documentation before using a function.
+
+On error, most functions also push errors on the error queue, an `errno`-like
+mechanism. See the documentation for
+[err.h](https://commondatastorage.googleapis.com/chromium-boringssl-docs/err.h.html)
+for more details.
+
+As with `errno`, callers must test the function's return value, not the error
+queue to determine whether an operation failed. Some codepaths may not interact
+with the error queue, and the error queue may have state from a previous failed
+operation.
+
+When ignoring a failed operation, it is recommended to call `ERR_clear_error` to
+avoid the state interacting with future operations. Failing to do so should not
+affect the actual behavior of any functions, but may result in errors from both
+operations being mixed in error logging. We hope to
+[improve](https://bugs.chromium.org/p/boringssl/issues/detail?id=38) this
+situation in the future.
+
+Where possible, avoid conditioning on specific reason codes and limit usage to
+logging. The reason codes are very specific and may change over time.
+
+
+## Memory allocation
+
+BoringSSL allocates memory via `OPENSSL_malloc`, found in `mem.h`. Use
+`OPENSSL_free`, found in the same header file, to release it. BoringSSL
+functions will fail gracefully on allocation error, but it is recommended to use
+a `malloc` implementation that `abort`s on failure.
+
+
+## Object initialization and cleanup
+
+BoringSSL defines a number of structs for use in its APIs. It is a C library,
+so the caller is responsible for ensuring these structs are properly
+initialized and released. Consult the documentation for a module for the
+proper use of its types. Some general conventions are listed below.
+
+
+### Heap-allocated types
+
+Some types, such as `RSA`, are heap-allocated. All instances will be allocated
+and returned from BoringSSL's APIs. It is an error to instantiate a heap-
+allocated type on the stack or embedded within another object.
+
+Heap-allocated types may have functioned named like `RSA_new` which allocates a
+fresh blank `RSA`. Other functions may also return newly-allocated instances.
+For example, `RSA_parse_public_key` is documented to return a newly-allocated
+`RSA` object.
+
+Heap-allocated objects must be released by the corresponding free function,
+named like `RSA_free`. Like C's `free` and C++'s `delete`, all free functions
+internally check for `NULL`. Consumers are not required to check for `NULL`
+before calling.
+
+A heap-allocated type may be reference-counted. In this case, a function named
+like `RSA_up_ref` will be available to take an additional reference count. The
+free function must be called to decrement the reference count. It will only
+release resources when the final reference is released. For OpenSSL
+compatibility, these functions return `int`, but callers may assume they always
+successfully return one because reference counts use saturating arithmetic.
+
+C++ consumers are recommended to use `bssl::UniquePtr` to manage heap-allocated
+objects. `bssl::UniquePtr<T>`, like other types, is forward-declared in
+`openssl/base.h`. Code that needs access to the free functions, such as code
+which destroys a `bssl::UniquePtr`, must include the corresponding module's
+header. (This matches `std::unique_ptr`'s relationship with forward
+declarations.)
+
+
+### Stack-allocated types
+
+Other types in BoringSSL are stack-allocated, such as `EVP_MD_CTX`. These
+types may be allocated on the stack or embedded within another object.
+However, they must still be initialized before use.
+
+Every stack-allocated object in BoringSSL has a *zero state*, analogous to
+initializing a pointer to `NULL`. In this state, the object may not be
+completely initialized, but it is safe to call cleanup functions. Entering the
+zero state cannot fail. (It is usually `memset(0)`.)
+
+The function to enter the zero state is named like `EVP_MD_CTX_init` or
+`CBB_zero` and will always return `void`. To release resources associated with
+the type, call the cleanup function, named like `EVP_MD_CTX_cleanup`. The
+cleanup function must be called on all codepaths, regardless of success or
+failure. For example:
+
+    uint8_t md[EVP_MAX_MD_SIZE];
+    unsigned md_len;
+    EVP_MD_CTX ctx;
+    EVP_MD_CTX_init(&ctx);  /* Enter the zero state. */
+    int ok = EVP_DigestInit_ex(&ctx, EVP_sha256(), NULL) &&
+             EVP_DigestUpdate(&ctx, "hello ", 6) &&
+             EVP_DigestUpdate(&ctx, "world", 5) &&
+             EVP_DigestFinal_ex(&ctx, md, &md_len);
+    EVP_MD_CTX_cleanup(&ctx);  /* Release |ctx|. */
+
+Note that `EVP_MD_CTX_cleanup` is called whether or not the `EVP_Digest*`
+operations succeeded. More complex C functions may use the `goto err` pattern:
+
+      int ret = 0;
+      EVP_MD_CTX ctx;
+      EVP_MD_CTX_init(&ctx);
+
+      if (!some_other_operation()) {
+        goto err;
+      }
+
+      uint8_t md[EVP_MAX_MD_SIZE];
+      unsigned md_len;
+      if (!EVP_DigestInit_ex(&ctx, EVP_sha256(), NULL) ||
+          !EVP_DigestUpdate(&ctx, "hello ", 6) ||
+          !EVP_DigestUpdate(&ctx, "world", 5) ||
+          !EVP_DigestFinal_ex(&ctx, md, &md_len) {
+        goto err;
+      }
+
+      ret = 1;
+
+    err:
+      EVP_MD_CTX_cleanup(&ctx);
+      return ret;
+
+Note that, because `ctx` is set to the zero state before any failures,
+`EVP_MD_CTX_cleanup` is safe to call even if the first operation fails before
+`EVP_DigestInit_ex`. However, it would be illegal to move the `EVP_MD_CTX_init`
+below the `some_other_operation` call.
+
+As a rule of thumb, enter the zero state of stack-allocated structs in the
+same place they are declared.
+
+C++ consumers are recommended to use the wrappers named like
+`bssl::ScopedEVP_MD_CTX`, defined in the corresponding module's header. These
+wrappers are automatically initialized to the zero state and are automatically
+cleaned up.
+
+
+### Data-only types
+
+A few types, such as `SHA_CTX`, are data-only types and do not require cleanup.
+These are usually for low-level cryptographic operations. These types may be
+used freely without special cleanup conventions.
+
+
+## Thread safety
+
+BoringSSL is internally aware of the platform threading library and calls into
+it as needed. Consult the API documentation for the threading guarantees of
+particular objects. In general, stateless reference-counted objects like `RSA`
+or `EVP_PKEY` which represent keys may typically be used from multiple threads
+simultaneously, provided no thread mutates the key.
diff --git a/src/BUILDING.md b/src/BUILDING.md
index 02f8f11..e691afd 100644
--- a/src/BUILDING.md
+++ b/src/BUILDING.md
@@ -2,14 +2,18 @@
 
 ## Build Prerequisites
 
-  * [CMake](http://www.cmake.org/download/) 2.8.8 or later is required.
+  * [CMake](https://cmake.org/download/) 2.8.11 or later is required.
 
   * Perl 5.6.1 or later is required. On Windows,
-    [Strawberry Perl](http://strawberryperl.com/) and MSYS Perl have both been
-    reported to work. If not found by CMake, it may be configured explicitly by
-    setting `PERL_EXECUTABLE`.
+    [Active State Perl](http://www.activestate.com/activeperl/) has been
+    reported to work, as has MSYS Perl.
+    [Strawberry Perl](http://strawberryperl.com/) also works but it adds GCC
+    to `PATH`, which can confuse some build tools when identifying the compiler
+    (removing `C:\Strawberry\c\bin` from `PATH` should resolve any problems).
+    If Perl is not found by CMake, it may be configured explicitly by setting
+    `PERL_EXECUTABLE`.
 
-  * On Windows you currently must use [Ninja](https://martine.github.io/ninja/)
+  * On Windows you currently must use [Ninja](https://ninja-build.org/)
     to build; on other platforms, it is not required, but recommended, because
     it makes builds faster.
 
@@ -20,22 +24,16 @@
     by CMake, it may be configured explicitly by setting
     `CMAKE_ASM_NASM_COMPILER`.
 
-  * A C compiler is required. On Windows, MSVC 12 (Visual Studio 2013) or later
-    with Platform SDK 8.1 or later are supported. Recent versions of GCC and
-    Clang should work on non-Windows platforms, and maybe on Windows too.
+  * A C compiler is required. On Windows, MSVC 14 (Visual Studio 2015) or later
+    with Platform SDK 8.1 or later are supported. Recent versions of GCC (4.8+)
+    and Clang should work on non-Windows platforms, and maybe on Windows too.
+    To build the tests, you also need a C++ compiler with C++11 support.
 
   * [Go](https://golang.org/dl/) is required. If not found by CMake, the go
     executable may be configured explicitly by setting `GO_EXECUTABLE`.
 
-  * If you change crypto/chacha/chacha\_vec.c, you will need the
-    arm-linux-gnueabihf-gcc compiler:
-
-    ```
-    wget https://releases.linaro.org/14.11/components/toolchain/binaries/arm-linux-gnueabihf/gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf.tar.xz && \
-    echo bc4ca2ced084d2dc12424815a4442e19cb1422db87068830305d90075feb1a3b  gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf.tar.xz | sha256sum -c && \
-    tar xf gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf.tar.xz && \
-    sudo mv gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf /opt/
-    ```
+  * To build the x86 and x86\_64 assembly, your assembler must support AVX2
+    instructions and MOVBE. If using GNU binutils, you must have 2.22 or later.
 
 ## Building
 
@@ -58,7 +56,8 @@
 themselves automatically.
 
 Note that the default build flags in the top-level `CMakeLists.txt` are for
-debugging—optimisation isn't enabled.
+debugging—optimisation isn't enabled. Pass `-DCMAKE_BUILD_TYPE=Release` to
+`cmake` to configure a release build.
 
 If you want to cross-compile then there is an example toolchain file for 32-bit
 Intel in `util/`. Wipe out the build directory, recreate it and run `cmake` like
@@ -75,24 +74,27 @@
 where performance is the overriding concern, `OPENSSL_SMALL` can be defined to
 remove some code that is especially large.
 
+See [CMake's documentation](https://cmake.org/cmake/help/v3.4/manual/cmake-variables.7.html)
+for other variables which may be used to configure the build.
+
 ### Building for Android
 
 It's possible to build BoringSSL with the Android NDK using CMake. This has
 been tested with version 10d of the NDK.
 
 Unpack the Android NDK somewhere and export `ANDROID_NDK` to point to the
-directory. Clone https://github.com/taka-no-me/android-cmake into `util/`.  Then
-make a build directory as above and run CMake *twice* like this:
+directory. Then make a build directory as above and run CMake like this:
 
-    cmake -DANDROID_NATIVE_API_LEVEL=android-9 \
-          -DANDROID_ABI=armeabi-v7a \
-          -DCMAKE_TOOLCHAIN_FILE=../util/android-cmake/android.toolchain.cmake \
+    cmake -DANDROID_ABI=armeabi-v7a \
+          -DCMAKE_TOOLCHAIN_FILE=../third_party/android-cmake/android.toolchain.cmake \
           -DANDROID_NATIVE_API_LEVEL=16 \
           -GNinja ..
 
-Once you've run that twice, Ninja should produce Android-compatible binaries.
-You can replace `armeabi-v7a` in the above with `arm64-v8a` to build aarch64
-binaries.
+Once you've run that, Ninja should produce Android-compatible binaries.  You
+can replace `armeabi-v7a` in the above with `arm64-v8a` and use API level 21 or
+higher to build aarch64 binaries.
+
+For other options, see [android-cmake's documentation](./third_party/android-cmake/README.md).
 
 ## Known Limitations on Windows
 
@@ -132,6 +134,18 @@
 Note that if a feature is enabled in this way, but not actually supported at
 run-time, BoringSSL will likely crash.
 
+## Assembling ARMv8 with Clang
+
+In order to support the ARMv8 crypto instructions, Clang requires that the
+architecture be `armv8-a+crypto`. However, setting that as a general build flag
+would allow the compiler to assume that crypto instructions are *always*
+supported, even without testing for them.
+
+It's possible to set the architecture in an assembly file using the `.arch`
+directive, but only very recent versions of Clang support this. If
+`BORINGSSL_CLANG_SUPPORTS_DOT_ARCH` is defined then `.arch` directives will be
+used with Clang, otherwise you may need to craft acceptable assembler flags.
+
 # Running tests
 
 There are two sets of tests: the C/C++ tests and the blackbox tests. For former
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index e07be54..844a140 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,12 +1,26 @@
-cmake_minimum_required (VERSION 2.8.10)
+cmake_minimum_required (VERSION 2.8.11)
 
-project (BoringSSL)
+# Defer enabling C and CXX languages.
+project (BoringSSL NONE)
+
+if(WIN32)
+  # On Windows, prefer cl over gcc if both are available. By default most of
+  # the CMake generators prefer gcc, even on Windows.
+  set(CMAKE_GENERATOR_CC cl)
+endif()
+
+enable_language(C)
+enable_language(CXX)
 
 if(ANDROID)
   # Android-NDK CMake files reconfigure the path and so Go and Perl won't be
   # found. However, ninja will still find them in $PATH if we just name them.
-  set(PERL_EXECUTABLE "perl")
-  set(GO_EXECUTABLE "go")
+  if(NOT PERL_EXECUTABLE)
+    set(PERL_EXECUTABLE "perl")
+  endif()
+  if(NOT GO_EXECUTABLE)
+    set(GO_EXECUTABLE "go")
+  endif()
 else()
   find_package(Perl REQUIRED)
   find_program(GO_EXECUTABLE go)
@@ -17,14 +31,28 @@
 endif()
 
 if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
-  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -Wsign-compare -Wmissing-field-initializers -ggdb -fvisibility=hidden")
-  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror -Wsign-compare -Wmissing-field-initializers -ggdb -std=c++0x -fvisibility=hidden")
+  set(C_CXX_FLAGS "-Wall -Werror -Wformat=2 -Wsign-compare -Wmissing-field-initializers -Wwrite-strings -ggdb -fvisibility=hidden -fno-common")
+  if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+    set(C_CXX_FLAGS "${C_CXX_FLAGS} -Wnewline-eof")
+  endif()
+  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_CXX_FLAGS} -Wmissing-prototypes -Wold-style-definition -Wstrict-prototypes")
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ${C_CXX_FLAGS} -Wmissing-declarations")
+  # Clang's integerated assembler does not support debug symbols.
+  if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+    set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -Wa,-g")
+  endif()
 elseif(MSVC)
   set(MSVC_DISABLED_WARNINGS_LIST
+      "C4061" # enumerator 'identifier' in switch of enum 'enumeration' is not
+              # explicitly handled by a case label
+              # Disable this because it flags even when there is a default.
       "C4100" # 'exarg' : unreferenced formal parameter
       "C4127" # conditional expression is constant
       "C4200" # nonstandard extension used : zero-sized array in
               # struct/union.
+      "C4204" # nonstandard extension used: non-constant aggregate initializer
+      "C4221" # nonstandard extension used : 'identifier' : cannot be
+              # initialized using address of automatic variable
       "C4242" # 'function' : conversion from 'int' to 'uint8_t',
               # possible loss of data
       "C4244" # 'function' : conversion from 'int' to 'uint8_t',
@@ -40,6 +68,7 @@
       "C4365" # '=' : conversion from 'size_t' to 'int',
               # signed/unsigned mismatch
       "C4389" # '!=' : signed/unsigned mismatch
+      "C4464" # relative include path contains '..'
       "C4510" # 'argument' : default constructor could not be generated
       "C4512" # 'argument' : assignment operator could not be generated
       "C4514" # 'function': unreferenced inline function has been removed
@@ -47,26 +76,38 @@
               # side-effect" caused by FD_* macros.
       "C4610" # struct 'argument' can never be instantiated - user defined
               # constructor required.
+      "C4623" # default constructor was implicitly defined as deleted
       "C4625" # copy constructor could not be generated because a base class
               # copy constructor is inaccessible or deleted
       "C4626" # assignment operator could not be generated because a base class
               # assignment operator is inaccessible or deleted
+      "C4668" # 'symbol' is not defined as a preprocessor macro, replacing with
+              # '0' for 'directives'
+              # Disable this because GTest uses it everywhere.
       "C4706" # assignment within conditional expression
       "C4710" # 'function': function not inlined
       "C4711" # function 'function' selected for inline expansion
       "C4800" # 'int' : forcing value to bool 'true' or 'false'
               # (performance warning)
       "C4820" # 'bytes' bytes padding added after construct 'member_name'
-      "C4996" # 'read': The POSIX name for this item is deprecated. Instead,
-              # use the ISO C++ conformant name: _read.
-     )
+      "C5026" # move constructor was implicitly defined as deleted
+      "C5027" # move assignment operator was implicitly defined as deleted
+      )
+  set(MSVC_LEVEL4_WARNINGS_LIST
+      # See https://connect.microsoft.com/VisualStudio/feedback/details/1217660/warning-c4265-when-using-functional-header
+      "C4265" # class has virtual functions, but destructor is not virtual
+      )
   string(REPLACE "C" " -wd" MSVC_DISABLED_WARNINGS_STR
                             ${MSVC_DISABLED_WARNINGS_LIST})
-  set(CMAKE_C_FLAGS   "-Wall -WX ${MSVC_DISABLED_WARNINGS_STR}")
-  set(CMAKE_CXX_FLAGS "-Wall -WX ${MSVC_DISABLED_WARNINGS_STR}")
+  string(REPLACE "C" " -w4" MSVC_LEVEL4_WARNINGS_STR
+                            ${MSVC_LEVEL4_WARNINGS_LIST})
+  set(CMAKE_C_FLAGS   "-Wall -WX ${MSVC_DISABLED_WARNINGS_STR} ${MSVC_LEVEL4_WARNINGS_STR}")
+  set(CMAKE_CXX_FLAGS "-Wall -WX ${MSVC_DISABLED_WARNINGS_STR} ${MSVC_LEVEL4_WARNINGS_STR}")
+  set(CMAKE_ASM_NASM_FLAGS "-g cv8")
   add_definitions(-D_HAS_EXCEPTIONS=0)
   add_definitions(-DWIN32_LEAN_AND_MEAN)
   add_definitions(-DNOMINMAX)
+  add_definitions(-D_CRT_SECURE_NO_WARNINGS) # Allow use of fopen
 endif()
 
 if((CMAKE_COMPILER_IS_GNUCXX AND CMAKE_C_COMPILER_VERSION VERSION_GREATER "4.7.99") OR
@@ -75,18 +116,35 @@
   set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wshadow")
 endif()
 
-if((CMAKE_COMPILER_IS_GNUCXX AND CMAKE_C_COMPILER_VERSION VERSION_GREATER "4.8.99") OR
-   CMAKE_CXX_COMPILER_ID MATCHES "Clang")
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -D_XOPEN_SOURCE=700")
+if(CMAKE_COMPILER_IS_GNUCXX)
+  if ((CMAKE_C_COMPILER_VERSION VERSION_GREATER "4.8.99") OR
+      CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11")
+  else()
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")
+  endif()
+endif()
+
+# pthread_rwlock_t requires a feature flag.
+if(NOT WIN32)
+  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_XOPEN_SOURCE=700")
 endif()
 
 if(FUZZ)
-  if(!CMAKE_CXX_COMPILER_ID MATCHES "Clang")
-    message("You need to build with Clang for fuzzing to work")
+  if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+    message(FATAL_ERROR "You need to build with Clang for fuzzing to work")
   endif()
 
-  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize-coverage=edge,indirect-calls")
-  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize-coverage=edge,indirect-calls")
+  add_definitions(-DBORINGSSL_UNSAFE_DETERMINISTIC_MODE)
+  set(RUNNER_ARGS "-deterministic")
+
+  if(NOT NO_FUZZER_MODE)
+    add_definitions(-DBORINGSSL_UNSAFE_FUZZER_MODE)
+    set(RUNNER_ARGS ${RUNNER_ARGS} "-fuzzer" "-shim-config" "fuzzer_mode.json")
+  endif()
+
+  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize-coverage=edge,indirect-calls,8bit-counters")
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize-coverage=edge,indirect-calls,8bit-counters")
   set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")
   link_directories(.)
 endif()
@@ -117,14 +175,15 @@
   set(ARCH "x86")
 elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "i686")
   set(ARCH "x86")
-elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "arm")
-  set(ARCH "arm")
-elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "armv6")
-  set(ARCH "arm")
-elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "armv7-a")
+elseif (${CMAKE_SYSTEM_PROCESSOR} MATCHES "^arm*")
   set(ARCH "arm")
 elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64")
   set(ARCH "aarch64")
+elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "mips")
+  # Just to avoid the “unknown processor” error.
+  set(ARCH "generic")
+elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "ppc64le")
+  set(ARCH "ppc64le")
 else()
   message(FATAL_ERROR "Unknown processor:" ${CMAKE_SYSTEM_PROCESSOR})
 endif()
@@ -143,11 +202,47 @@
   set(ARCH "x86_64")
 endif()
 
+if (MSAN)
+  if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+    message(FATAL_ERROR "Cannot enable MSAN unless using Clang")
+  endif()
+
+  if (ASAN)
+    message(FATAL_ERROR "ASAN and MSAN are mutually exclusive")
+  endif()
+
+  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer")
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer")
+  set(OPENSSL_NO_ASM "1")
+endif()
+
+if (ASAN)
+  if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang")
+    message(FATAL_ERROR "Cannot enable ASAN unless using Clang")
+  endif()
+
+  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope -fno-omit-frame-pointer")
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope -fno-omit-frame-pointer")
+  set(OPENSSL_NO_ASM "1")
+endif()
+
+if (GCOV)
+  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage")
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
+endif()
+
 if (OPENSSL_NO_ASM)
   add_definitions(-DOPENSSL_NO_ASM)
   set(ARCH "generic")
 endif()
 
+# Add minimal googletest targets. The provided one has many side-effects, and
+# googletest has a very straightforward build.
+add_library(gtest third_party/googletest/src/gtest-all.cc)
+target_include_directories(gtest PRIVATE third_party/googletest)
+
+include_directories(third_party/googletest/include)
+
 # Declare a dummy target to build all unit tests. Test targets should inject
 # themselves as dependencies next to the target definition.
 add_custom_target(all_tests)
@@ -171,8 +266,9 @@
     run_tests
     COMMAND ${GO_EXECUTABLE} run util/all_tests.go -build-dir
             ${CMAKE_BINARY_DIR}
-    COMMAND cd ssl/test/runner
-    COMMAND ${GO_EXECUTABLE} test -shim-path $<TARGET_FILE:bssl_shim>
+    COMMAND cd ssl/test/runner &&
+            ${GO_EXECUTABLE} test -shim-path $<TARGET_FILE:bssl_shim>
+              ${RUNNER_ARGS}
     WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
     DEPENDS all_tests bssl_shim
     ${MAYBE_USES_TERMINAL})
diff --git a/src/CONTRIBUTING.md b/src/CONTRIBUTING.md
new file mode 100644
index 0000000..8907cc9
--- /dev/null
+++ b/src/CONTRIBUTING.md
@@ -0,0 +1,49 @@
+Want to contribute? Great! First, read this page (including the small print at the end).
+
+### Before you contribute
+Before we can use your code, you must sign the
+[Google Individual Contributor License Agreement](https://cla.developers.google.com/about/google-individual)
+(CLA), which you can do online. The CLA is necessary mainly because you own the
+copyright to your changes, even after your contribution becomes part of our
+codebase, so we need your permission to use and distribute your code. We also
+need to be sure of various other things—for instance that you'll tell us if you
+know that your code infringes on other people's patents. You don't have to sign
+the CLA until after you've submitted your code for review and a member has
+approved it, but you must do it before we can put your code into our codebase.
+Before you start working on a larger contribution, you should get in touch with
+us first via email with your idea so that we can help out and possibly guide
+you. Coordinating up front makes it much easier to avoid frustration later on.
+
+### Code reviews
+All submissions, including submissions by project members, require review. We
+use [Gerrit](https://boringssl-review.googlesource.com) for this purpose.
+
+#### Setup
+If you have not done so on this machine, you will need to set up a password for
+Gerrit. Sign in with a Google account, visit
+[this link](https://boringssl.googlesource.com/), and click the "Generate
+Password" link in the top right. You will also need to prepare your checkout to
+[add Change-Ids](https://gerrit-review.googlesource.com/Documentation/cmd-hook-commit-msg.html)
+on commit. Run:
+
+    curl -Lo .git/hooks/commit-msg https://boringssl-review.googlesource.com/tools/hooks/commit-msg
+    chmod u+x .git/hooks/commit-msg
+
+#### Uploading changes
+To upload a change, push it to the special `refs/for/master` target:
+
+    git push origin HEAD:refs/for/master
+
+The output will then give you a link to the change. Add `agl@google.com` and
+`davidben@google.com` as reviewers.
+
+Pushing a commit with the same Change-Id as an existing change will upload a new
+version of it. (Use the `git rebase` or `git commit --amend` commands.)
+
+For more detailed instructions, see the
+[Gerrit User Guide](https://gerrit-review.googlesource.com/Documentation/intro-user.html).
+
+### The small print
+Contributions made by corporations are covered by a different agreement than
+the one above, the
+[Software Grant and Corporate Contributor License Agreement](https://cla.developers.google.com/about/google-corporate).
diff --git a/src/FUZZING.md b/src/FUZZING.md
index 4bd15a3..70660ab 100644
--- a/src/FUZZING.md
+++ b/src/FUZZING.md
@@ -13,9 +13,9 @@
 In order for the fuzz tests to link, the linker needs to find libFuzzer. This is not commonly provided and you may need to download the [Clang source code](http://llvm.org/releases/download.html) and do the following:
 
 ```
-cd llvm-3.7.0.src/lib
-clang -c -g -O2 -std=c++11 Fuzzer/*.cpp -IFuzzer
-ar q libFuzzer.a *.o
+svn co http://llvm.org/svn/llvm-project/llvm/trunk/lib/Fuzzer
+clang++ -c -g -O2 -std=c++11 Fuzzer/*.cpp -IFuzzer
+ar ruv libFuzzer.a Fuzzer*.o
 ```
 
 Then copy `libFuzzer.a` to the top-level of your BoringSSL source directory.
@@ -23,18 +23,62 @@
 From the `build/` directory, you can then run the fuzzers. For example:
 
 ```
-./fuzz/cert -max_len=4000 -jobs=32 -workers=32 ../fuzz/cert_corpus/
+./fuzz/cert -max_len=10000 -jobs=32 -workers=32 ../fuzz/cert_corpus/
 ```
 
-The `max_len` argument is often important because, without it, libFuzzer defaults to limiting all test cases to 64 bytes, which is often insufficient for the formats that we wish to fuzz. The arguments to `jobs` and `workers` should be the number of cores that you wish to dedicate to fuzzing.
+The arguments to `jobs` and `workers` should be the number of cores that you wish to dedicate to fuzzing. By default, libFuzzer uses the largest test in the corpus (or 64 if empty) as the maximum test case length. The `max_len` argument overrides this.
+
+The recommended values of `max_len` for each test are:
+
+| Test          | `max_len` value |
+|---------------|-----------------|
+| `cert`        | 10000           |
+| `client`      | 20000           |
+| `pkcs8`       | 2048            |
+| `privkey`     | 2048            |
+| `server`      | 4096            |
+| `session`     | 8192            |
+| `spki`        | 1024            |
+| `read_pem`    | 512             |
+| `ssl_ctx_api` | 256             |
+
+These were determined by rounding up the length of the largest case in the corpus.
 
 There are directories in `fuzz/` for each of the fuzzing tests which contain seed files for fuzzing. Some of the seed files were generated manually but many of them are “interesting” results generated by the fuzzing itself. (Where “interesting” means that it triggered a previously unknown path in the code.)
 
-Here are the recommended values of `max_len` for each test.
+## Minimising the corpuses
 
-| Test      | `max_len` value |
-|-----------|-----------------|
-| `privkey` | 2048            |
-| `cert`    | 3072            |
-| `server`  | 1024            |
-| `client`  | 4096            |
+When a large number of new seeds are available, it's a good idea to minimise the corpus so that different seeds that trigger the same code paths can be deduplicated.
+
+In order to minimise all the corpuses, build for fuzzing and run `./fuzz/minimise_corpuses.sh`. Note that minimisation is, oddly, often not idempotent for unknown reasons.
+
+## Fuzzer mode
+
+When `-DFUZZ=1` is passed into CMake, BoringSSL builds with `BORINGSSL_UNSAFE_FUZZER_MODE` and `BORINGSSL_UNSAFE_DETERMINISTIC_MODE` defined. This modifies the library to be more friendly to fuzzers. If `BORINGSSL_UNSAFE_DETERMINISTIC_MODE` is set, BoringSSL will:
+
+* Replace `RAND_bytes` with a deterministic PRNG. Call `RAND_reset_for_fuzzing()` at the start of fuzzers which use `RAND_bytes` to reset the PRNG state.
+
+* Use a hard-coded time instead of the actual time.
+
+Additionally, if `BORINGSSL_UNSAFE_FUZZER_MODE` is set, BoringSSL will:
+
+* Modify the TLS stack to perform all signature checks (CertificateVerify and ServerKeyExchange) and the Finished check, but always act as if the check succeeded.
+
+* Treat every cipher as the NULL cipher.
+
+* Tickets are unencrypted and the MAC check is performed but ignored.
+
+This is to prevent the fuzzer from getting stuck at a cryptographic invariant in the protocol.
+
+## TLS transcripts
+
+The `client` and `server` corpora are seeded from the test suite. The test suite has a `-fuzzer` flag which mirrors the fuzzer mode changes above and a `-deterministic` flag which removes all non-determinism on the Go side. Not all tests pass, so `ssl/test/runner/fuzzer_mode.json` contains the necessary suppressions. The `run_tests` target will pass appropriate command-line flags.
+
+There are separate corpora, `client_corpus_no_fuzzer_mode` and `server_corpus_no_fuzzer_mode`. These are transcripts for fuzzers with only `BORINGSSL_UNSAFE_DETERMINISTIC_MODE` defined. To build in this mode, pass `-DNO_FUZZER_MODE=1` into CMake. This configuration is run in the same way but without `-fuzzer` and `-shim-path` flags.
+
+If both sets of tests pass, refresh the fuzzer corpora with `refresh_ssl_corpora.sh`:
+
+```
+cd fuzz
+./refresh_fuzzer_corpora.sh /path/to/fuzzer/mode/build /path/to/non/fuzzer/mode/build
+```
diff --git a/src/INCORPORATING.md b/src/INCORPORATING.md
new file mode 100644
index 0000000..6dc7fa9
--- /dev/null
+++ b/src/INCORPORATING.md
@@ -0,0 +1,108 @@
+# Incorporating BoringSSL into a project
+
+**Note**: if your target project is not a Google project then first read the
+[main README](/README.md) about the purpose of BoringSSL.
+
+## Bazel
+
+If you are using [Bazel](https://bazel.build) then you can incorporate
+BoringSSL as an external repository by using a commit from the
+`master-with-bazel` branch. That branch is maintained by a bot from `master`
+and includes the needed generated files and a top-level BUILD file.
+
+For example:
+
+    git_repository(
+        name = "boringssl",
+        commit = "_some commit_",
+        remote = "https://boringssl.googlesource.com/boringssl",
+    )
+
+You would still need to keep the referenced commit up to date if a specific
+commit is referred to.
+
+## Directory layout
+
+Typically projects create a `third_party/boringssl` directory to put
+BoringSSL-specific files into. The source code of BoringSSL itself goes into
+`third_party/boringssl/src`, either by copying or as a
+[submodule](https://git-scm.com/docs/git-submodule).
+
+It's generally a mistake to put BoringSSL's source code into
+`third_party/boringssl` directly because pre-built files and custom build files
+need to go somewhere and merging these with the BoringSSL source code makes
+updating things more complex.
+
+## Build support
+
+BoringSSL is designed to work with many different build systems. Currently,
+different projects use [GYP](https://gyp.gsrc.io/),
+[GN](https://chromium.googlesource.com/chromium/src/+/master/tools/gn/docs/quick_start.md),
+[Bazel](https://bazel.build/) and [Make](https://www.gnu.org/software/make/)  to
+build BoringSSL, without too much pain.
+
+The development build system is CMake and the CMake build knows how to
+automatically generate the intermediate files that BoringSSL needs. However,
+outside of the CMake environment, these intermediates are generated once and
+checked into the incorporating project's source repository. This avoids
+incorporating projects needing to support Perl and Go in their build systems.
+
+The script [`util/generate_build_files.py`](/util/generate_build_files.py)
+expects to be run from the `third_party/boringssl` directory and to find the
+BoringSSL source code in `src/`. You should pass it a single argument: the name
+of the build system that you're using. If you don't use any of the supported
+build systems then you should augment `generate_build_files.py` with support
+for it.
+
+The script will pregenerate the intermediate files (see
+[BUILDING.md](/BUILDING.md) for details about which tools will need to be
+installed) and output helper files for that build system. It doesn't generate a
+complete build script, just file and test lists, which change often. For
+example, see the
+[file](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/boringssl/BUILD.generated.gni)
+and
+[test](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/boringssl/BUILD.generated_tests.gni)
+lists generated for GN in Chromium.
+
+Generally one checks in these generated files alongside the hand-written build
+files. Periodically an engineer updates the BoringSSL revision, regenerates
+these files and checks in the updated result. As an example, see how this is
+done [in Chromium](https://code.google.com/p/chromium/codesearch#chromium/src/third_party/boringssl/).
+
+## Defines
+
+BoringSSL does not present a lot of configurability in order to reduce the
+number of configurations that need to be tested. But there are a couple of
+\#defines that you may wish to set:
+
+`OPENSSL_NO_ASM` prevents the use of assembly code (although it's up to you to
+ensure that the build system doesn't link it in if you wish to reduce binary
+size). This will have a significant performance impact but can be useful if you
+wish to use tools like
+[AddressSanitizer](http://clang.llvm.org/docs/AddressSanitizer.html) that
+interact poorly with assembly code.
+
+`OPENSSL_SMALL` removes some code that is especially large at some performance
+cost.
+
+## Symbols
+
+You cannot link multiple versions of BoringSSL or OpenSSL into a single binary
+without dealing with symbol conflicts. If you are statically linking multiple
+versions together, there's not a lot that can be done because C doesn't have a
+module system.
+
+If you are using multiple versions in a single binary, in different shared
+objects, ensure you build BoringSSL with `-fvisibility=hidden` and do not
+export any of BoringSSL's symbols. This will prevent any collisions with other
+verisons that may be included in other shared objects. Note that this requires
+that all callers of BoringSSL APIs live in the same shared object as BoringSSL.
+
+If you require that BoringSSL APIs be used across shared object boundaries,
+continue to build with `-fvisibility=hidden` but define
+`BORINGSSL_SHARED_LIBRARY` in both BoringSSL and consumers. BoringSSL's own
+source files (but *not* consumers' source files) must also build with
+`BORINGSSL_IMPLEMENTATION` defined. This will export BoringSSL's public symbols
+in the resulting shared object while hiding private symbols. However note that,
+as with a static link, this precludes dynamically linking with another version
+of BoringSSL or OpenSSL.
diff --git a/src/LICENSE b/src/LICENSE
index b242dcb..a25996f 100644
--- a/src/LICENSE
+++ b/src/LICENSE
@@ -14,6 +14,13 @@
 licenses. In case of any license issues related to OpenSSL please contact
 openssl-core@openssl.org.
 
+The following are Google-internal bug numbers where explicit permission from
+some authors is recorded for use of their work. (This is purely for our own
+record keeping.)
+  27287199
+  27287880
+  27287883
+
   OpenSSL License
   ---------------
 
diff --git a/src/PORTING.md b/src/PORTING.md
index b3e50d7..b9d6752 100644
--- a/src/PORTING.md
+++ b/src/PORTING.md
@@ -10,6 +10,9 @@
 `OPENSSL_IS_BORINGSSL` preprocessor macro may be used in `#ifdef`s. This macro
 should also be used in lieu of the presence of any particular function to detect
 OpenSSL vs BoringSSL in configure scripts, etc., where those are necessary.
+Before using the preprocessor, however, contact the BoringSSL maintainers about
+the missing APIs. If not an intentionally removed feature, BoringSSL will
+typically add compatibility functions for convenience.
 
 For convenience, BoringSSL defines upstream's `OPENSSL_NO_*` feature macros
 corresponding to removed features. These may also be used to disable code which
@@ -79,7 +82,8 @@
 
 Switch any `*_ctrl` callers to the macro/function versions. This works in both
 OpenSSL and BoringSSL. Note that BoringSSL's function versions will be
-type-checked and may require more care with types.
+type-checked and may require more care with types. See the end of this
+document for a table of functions to use.
 
 ### HMAC `EVP_PKEY`s
 
@@ -130,6 +134,23 @@
 uppercase. Some code may require changes to avoid being sensitive to this
 difference.
 
+### Legacy ASN.1 functions
+
+OpenSSL's ASN.1 stack uses `d2i` functions for parsing. They have the form:
+
+    RSA *d2i_RSAPrivateKey(RSA **out, const uint8_t **inp, long len);
+
+In addition to returning the result, OpenSSL places it in `*out` if `out` is
+not `NULL`. On input, if `*out` is not `NULL`, OpenSSL will usually (but not
+always) reuse that object rather than allocating a new one. In BoringSSL, these
+functions are compatibility wrappers over a newer ASN.1 stack. Even if `*out`
+is not `NULL`, these wrappers will always allocate a new object and free the
+previous one.
+
+Ensure that callers do not rely on this object reuse behavior. It is
+recommended to avoid the `out` parameter completely and always pass in `NULL`.
+Note that less error-prone APIs are available for BoringSSL-specific code (see
+below).
 
 ## Optional BoringSSL-specific simplifications
 
@@ -162,3 +183,67 @@
 these does nothing in BoringSSL. Instead, BoringSSL calls pthreads and the
 corresponding Windows APIs internally and is always thread-safe where the API
 guarantees it.
+
+### ASN.1
+
+BoringSSL is in the process of deprecating OpenSSL's `d2i` and `i2d` in favor of
+new functions using the much less error-prone `CBS` and `CBB` types.
+BoringSSL-only code should use those functions where available.
+
+
+## Replacements for `CTRL` values
+
+When porting code which uses `SSL_CTX_ctrl` or `SSL_ctrl`, use the replacement
+functions below. If a function has both `SSL_CTX` and `SSL` variants, only the
+`SSL_CTX` version is listed.
+
+Note some values correspond to multiple functions depending on the `larg`
+parameter.
+
+`CTRL` value | Replacement function(s)
+-------------|-------------------------
+`DTLS_CTRL_GET_TIMEOUT` | `DTLSv1_get_timeout`
+`DTLS_CTRL_HANDLE_TIMEOUT` | `DTLSv1_handle_timeout`
+`SSL_CTRL_CHAIN` | `SSL_CTX_set0_chain` or `SSL_CTX_set1_chain`
+`SSL_CTRL_CHAIN_CERT` | `SSL_add0_chain_cert` or `SSL_add1_chain_cert`
+`SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS` | `SSL_CTX_clear_extra_chain_certs`
+`SSL_CTRL_CLEAR_MODE` | `SSL_CTX_clear_mode`
+`SSL_CTRL_CLEAR_OPTIONS` | `SSL_CTX_clear_options`
+`SSL_CTRL_EXTRA_CHAIN_CERT` | `SSL_CTX_add_extra_chain_cert`
+`SSL_CTRL_GET_CHAIN_CERTS` | `SSL_CTX_get0_chain_certs`
+`SSL_CTRL_GET_CLIENT_CERT_TYPES` | `SSL_get0_certificate_types`
+`SSL_CTRL_GET_EXTRA_CHAIN_CERTS` | `SSL_CTX_get_extra_chain_certs` or `SSL_CTX_get_extra_chain_certs_only`
+`SSL_CTRL_GET_MAX_CERT_LIST` | `SSL_CTX_get_max_cert_list`
+`SSL_CTRL_GET_NUM_RENEGOTIATIONS` | `SSL_num_renegotiations`
+`SSL_CTRL_GET_READ_AHEAD` | `SSL_CTX_get_read_ahead`
+`SSL_CTRL_GET_RI_SUPPORT` | `SSL_get_secure_renegotiation_support`
+`SSL_CTRL_GET_SESSION_REUSED` | `SSL_session_reused`
+`SSL_CTRL_GET_SESS_CACHE_MODE` | `SSL_CTX_get_session_cache_mode`
+`SSL_CTRL_GET_SESS_CACHE_SIZE` | `SSL_CTX_sess_get_cache_size`
+`SSL_CTRL_GET_TLSEXT_TICKET_KEYS` | `SSL_CTX_get_tlsext_ticket_keys`
+`SSL_CTRL_GET_TOTAL_RENEGOTIATIONS` | `SSL_total_renegotiations`
+`SSL_CTRL_MODE` | `SSL_CTX_get_mode` or `SSL_CTX_set_mode`
+`SSL_CTRL_NEED_TMP_RSA` | `SSL_CTX_need_tmp_RSA` is equivalent, but [*do not use this function*](https://freakattack.com/). (It is a no-op in BoringSSL.)
+`SSL_CTRL_OPTIONS` | `SSL_CTX_get_options` or `SSL_CTX_set_options`
+`SSL_CTRL_SESS_NUMBER` | `SSL_CTX_sess_number`
+`SSL_CTRL_SET_CURVES` | `SSL_CTX_set1_curves`
+`SSL_CTRL_SET_ECDH_AUTO` | `SSL_CTX_set_ecdh_auto`
+`SSL_CTRL_SET_MAX_CERT_LIST` | `SSL_CTX_set_max_cert_list`
+`SSL_CTRL_SET_MAX_SEND_FRAGMENT` | `SSL_CTX_set_max_send_fragment`
+`SSL_CTRL_SET_MSG_CALLBACK` | `SSL_set_msg_callback`
+`SSL_CTRL_SET_MSG_CALLBACK_ARG` | `SSL_set_msg_callback_arg`
+`SSL_CTRL_SET_MTU` | `SSL_set_mtu`
+`SSL_CTRL_SET_READ_AHEAD` | `SSL_CTX_set_read_ahead`
+`SSL_CTRL_SET_SESS_CACHE_MODE` | `SSL_CTX_set_session_cache_mode`
+`SSL_CTRL_SET_SESS_CACHE_SIZE` | `SSL_CTX_sess_set_cache_size`
+`SSL_CTRL_SET_TLSEXT_HOSTNAME` | `SSL_set_tlsext_host_name`
+`SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG` | `SSL_CTX_set_tlsext_servername_arg`
+`SSL_CTRL_SET_TLSEXT_SERVERNAME_CB` | `SSL_CTX_set_tlsext_servername_callback`
+`SSL_CTRL_SET_TLSEXT_TICKET_KEYS` | `SSL_CTX_set_tlsext_ticket_keys`
+`SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB` | `SSL_CTX_set_tlsext_ticket_key_cb`
+`SSL_CTRL_SET_TMP_DH` | `SSL_CTX_set_tmp_dh`
+`SSL_CTRL_SET_TMP_DH_CB` | `SSL_CTX_set_tmp_dh_callback`
+`SSL_CTRL_SET_TMP_ECDH` | `SSL_CTX_set_tmp_ecdh`
+`SSL_CTRL_SET_TMP_ECDH_CB` | `SSL_CTX_set_tmp_ecdh_callback`
+`SSL_CTRL_SET_TMP_RSA` | `SSL_CTX_set_tmp_rsa` is equivalent, but [*do not use this function*](https://freakattack.com/). (It is a no-op in BoringSSL.)
+`SSL_CTRL_SET_TMP_RSA_CB` | `SSL_CTX_set_tmp_rsa_callback` is equivalent, but [*do not use this function*](https://freakattack.com/). (It is a no-op in BoringSSL.)
diff --git a/src/README.md b/src/README.md
index d8a65c2..b28e721 100644
--- a/src/README.md
+++ b/src/README.md
@@ -25,6 +25,9 @@
 
   * [PORTING.md](/PORTING.md): how to port OpenSSL-using code to BoringSSL.
   * [BUILDING.md](/BUILDING.md): how to build BoringSSL
+  * [INCORPORATING.md](/INCORPORATING.md): how to incorporate BoringSSL into a project.
+  * [API-CONVENTIONS.md](/API-CONVENTIONS.md): general API conventions for BoringSSL consumers and developers.
   * [STYLE.md](/STYLE.md): rules and guidelines for coding style.
   * include/openssl: public headers with API documentation in comments. Also [available online](https://commondatastorage.googleapis.com/chromium-boringssl-docs/headers.html).
   * [FUZZING.md](/FUZZING.md): information about fuzzing BoringSSL.
+  * [CONTRIBUTING.md](/CONTRIBUTING.md): how to contribute to BoringSSL.
diff --git a/src/STYLE.md b/src/STYLE.md
index 4d2c5de..4b377e7 100644
--- a/src/STYLE.md
+++ b/src/STYLE.md
@@ -14,10 +14,10 @@
 given rule. Module-wide deviations on naming should be respected while
 integer and return value conventions take precedence over consistency.
 
-Some modules have seen few changes, so they still retain the original
-indentation style for now. When editing these, try to retain the
-original style. For Emacs, `doc/c-indentation.el` from OpenSSL may be
-helpful in this.
+Modules from OpenSSL's legacy ASN.1 and X.509 stack are retained for
+compatibility and left largely unmodified. To ease importing patches from
+upstream, they match OpenSSL's new indentation style. For Emacs,
+`doc/openssl-c-indent.el` from OpenSSL may be helpful in this.
 
 
 ## Language
@@ -27,7 +27,9 @@
 our target platforms. Typically, Chromium's target MSVC is the most
 restrictive.
 
-Variable declarations in the middle of a function are allowed.
+Variable declarations in the middle of a function or inside a `for` loop are
+allowed and preferred where possible. Note that the common `goto err` cleanup
+pattern requires lifting some variable declarations.
 
 Comments should be `/* C-style */` for consistency.
 
@@ -43,6 +45,16 @@
 Rather than `malloc()` and `free()`, use the wrappers `OPENSSL_malloc()`
 and `OPENSSL_free()`. Use the standard C `assert()` function freely.
 
+Use the following wrappers, found in `crypto/internal.h` instead of the
+corresponding C standard library functions. They behave the same but avoid
+confusing undefined behavior.
+
+* `OPENSSL_memchr`
+* `OPENSSL_memcmp`
+* `OPENSSL_memcpy`
+* `OPENSSL_memmove`
+* `OPENSSL_memset`
+
 For new constants, prefer enums when the values are sequential and typed
 constants for flags. If adding values to an existing set of `#define`s,
 continue with `#define`.
@@ -157,7 +169,7 @@
     /* CBB_add_asn sets |*out_contents| to a |CBB| into which the contents of an
      * ASN.1 object can be written. The |tag| argument will be used as the tag for
      * the object. It returns one on success or zero on error. */
-    OPENSSL_EXPORT int CBB_add_asn1(CBB *cbb, CBB *out_contents, uint8_t tag);
+    OPENSSL_EXPORT int CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned tag);
 
 
 ## Documentation
diff --git a/src/codereview.settings b/src/codereview.settings
index 1e123a1..3620348 100644
--- a/src/codereview.settings
+++ b/src/codereview.settings
@@ -1,4 +1,4 @@
-# This file is used by gcl to get repository specific information.
+# This file is used by gcl to get repository specific information. 
 GERRIT_HOST: True
 GERRIT_PORT: True
 CODE_REVIEW_SERVER: https://boringssl-review.googlesource.com
diff --git a/src/crypto/CMakeLists.txt b/src/crypto/CMakeLists.txt
index 6651f29..3728e6f 100644
--- a/src/crypto/CMakeLists.txt
+++ b/src/crypto/CMakeLists.txt
@@ -17,11 +17,14 @@
   elseif (${ARCH} STREQUAL "x86")
     set(PERLASM_FLAGS "-fPIC -DOPENSSL_IA32_SSE2")
     set(PERLASM_STYLE elf)
+  elseif (${ARCH} STREQUAL "ppc64le")
+    set(PERLASM_STYLE ppc64le)
   else()
     set(PERLASM_STYLE elf)
   endif()
   set(ASM_EXT S)
   enable_language(ASM)
+  set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -Wa,--noexecstack")
 else()
   if (CMAKE_CL_64)
     message("Using nasm")
@@ -40,10 +43,11 @@
 function(perlasm dest src)
   add_custom_command(
     OUTPUT ${dest}
-    COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${src} ${PERLASM_STYLE} ${PERLASM_FLAGS} ${ARGN} > ${dest}
+    COMMAND ${PERL_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${src} ${PERLASM_STYLE} ${PERLASM_FLAGS} ${ARGN} ${dest}
     DEPENDS
     ${src}
     ${PROJECT_SOURCE_DIR}/crypto/perlasm/arm-xlate.pl
+    ${PROJECT_SOURCE_DIR}/crypto/perlasm/ppc-xlate.pl
     ${PROJECT_SOURCE_DIR}/crypto/perlasm/x86_64-xlate.pl
     ${PROJECT_SOURCE_DIR}/crypto/perlasm/x86asm.pl
     ${PROJECT_SOURCE_DIR}/crypto/perlasm/x86gas.pl
@@ -53,39 +57,6 @@
   )
 endfunction()
 
-if (${ARCH} STREQUAL "x86_64")
-  set(
-    CRYPTO_ARCH_SOURCES
-
-    cpu-intel.c
-  )
-endif()
-
-if (${ARCH} STREQUAL "x86")
-  set(
-    CRYPTO_ARCH_SOURCES
-
-    cpu-intel.c
-  )
-endif()
-
-if (${ARCH} STREQUAL "arm")
-  set(
-    CRYPTO_ARCH_SOURCES
-
-    cpu-arm.c
-    cpu-arm-asm.S
-  )
-endif()
-
-if (${ARCH} STREQUAL "aarch64")
-  set(
-    CRYPTO_ARCH_SOURCES
-
-    cpu-arm.c
-  )
-endif()
-
 # Level 0.1 - depends on nothing outside this set.
 add_subdirectory(stack)
 add_subdirectory(lhash)
@@ -93,6 +64,7 @@
 add_subdirectory(buf)
 add_subdirectory(base64)
 add_subdirectory(bytestring)
+add_subdirectory(pool)
 
 # Level 0.2 - depends on nothing but itself
 add_subdirectory(sha)
@@ -143,9 +115,12 @@
 add_library(
   crypto
 
+  cpu-aarch64-linux.c
+  cpu-arm.c
+  cpu-arm-linux.c
+  cpu-intel.c
+  cpu-ppc64le.c
   crypto.c
-  directory_posix.c
-  directory_win.c
   ex_data.c
   mem.c
   refcount_c11.c
@@ -154,15 +129,13 @@
   thread_none.c
   thread_pthread.c
   thread_win.c
-  time_support.c
-
-  ${CRYPTO_ARCH_SOURCES}
 
   $<TARGET_OBJECTS:stack>
   $<TARGET_OBJECTS:lhash>
   $<TARGET_OBJECTS:err>
   $<TARGET_OBJECTS:base64>
   $<TARGET_OBJECTS:bytestring>
+  $<TARGET_OBJECTS:pool>
   $<TARGET_OBJECTS:sha>
   $<TARGET_OBJECTS:md4>
   $<TARGET_OBJECTS:md5>
@@ -196,7 +169,7 @@
   $<TARGET_OBJECTS:pem>
   $<TARGET_OBJECTS:x509>
   $<TARGET_OBJECTS:x509v3>
-  $<TARGET_OBJECTS:pkcs8>
+  $<TARGET_OBJECTS:pkcs8_lib>
 )
 
 if(NOT MSVC AND NOT ANDROID)
@@ -204,17 +177,6 @@
 endif()
 
 add_executable(
-  constant_time_test
-
-  constant_time_test.c
-
-  $<TARGET_OBJECTS:test_support>
-)
-
-target_link_libraries(constant_time_test crypto)
-add_dependencies(all_tests constant_time_test)
-
-add_executable(
   thread_test
 
   thread_test.c
@@ -228,8 +190,34 @@
 add_executable(
   refcount_test
 
-  refcount_test.c
+  refcount_test.cc
 )
 
 target_link_libraries(refcount_test crypto)
 add_dependencies(all_tests refcount_test)
+
+# TODO(davidben): Convert the remaining tests to GTest.
+add_executable(
+  crypto_test
+
+  asn1/asn1_test.cc
+  bio/bio_test.cc
+  chacha/chacha_test.cc
+  constant_time_test.cc
+  curve25519/x25519_test.cc
+  dh/dh_test.cc
+  dsa/dsa_test.cc
+  ec/ec_test.cc
+  err/err_test.cc
+  evp/evp_extra_test.cc
+  rsa/rsa_test.cc
+
+  $<TARGET_OBJECTS:gtest_main>
+  $<TARGET_OBJECTS:test_support>
+)
+
+target_link_libraries(crypto_test crypto gtest)
+if (WIN32)
+  target_link_libraries(crypto_test ws2_32)
+endif()
+add_dependencies(all_tests crypto_test)
diff --git a/src/crypto/aes/CMakeLists.txt b/src/crypto/aes/CMakeLists.txt
index 0566e39..33eebf5 100644
--- a/src/crypto/aes/CMakeLists.txt
+++ b/src/crypto/aes/CMakeLists.txt
@@ -39,12 +39,21 @@
   )
 endif()
 
+if (${ARCH} STREQUAL "ppc64le")
+  set(
+    AES_ARCH_SOURCES
+
+    aesp8-ppc.${ASM_EXT}
+  )
+endif()
+
 add_library(
   aes
 
   OBJECT
 
   aes.c
+  key_wrap.c
   mode_wrappers.c
 
   ${AES_ARCH_SOURCES}
@@ -60,6 +69,7 @@
 perlasm(aes-armv4.${ASM_EXT} asm/aes-armv4.pl)
 perlasm(bsaes-armv7.${ASM_EXT} asm/bsaes-armv7.pl)
 perlasm(aesv8-armx.${ASM_EXT} asm/aesv8-armx.pl)
+perlasm(aesp8-ppc.${ASM_EXT} asm/aesp8-ppc.pl)
 
 add_executable(
   aes_test
diff --git a/src/crypto/aes/aes.c b/src/crypto/aes/aes.c
index 8823919..1aed63e 100644
--- a/src/crypto/aes/aes.c
+++ b/src/crypto/aes/aes.c
@@ -1066,12 +1066,12 @@
   return CRYPTO_is_ARMv8_AES_capable();
 }
 
-int aes_v8_set_encrypt_key(const uint8_t *user_key, const int bits,
+int aes_hw_set_encrypt_key(const uint8_t *user_key, const int bits,
                            AES_KEY *key);
-int aes_v8_set_decrypt_key(const uint8_t *user_key, const int bits,
+int aes_hw_set_decrypt_key(const uint8_t *user_key, const int bits,
                            AES_KEY *key);
-void aes_v8_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
-void aes_v8_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
+void aes_hw_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
+void aes_hw_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
 
 #else
 
@@ -1079,19 +1079,19 @@
   return 0;
 }
 
-static int aes_v8_set_encrypt_key(const uint8_t *user_key, int bits, AES_KEY *key) {
+static int aes_hw_set_encrypt_key(const uint8_t *user_key, int bits, AES_KEY *key) {
   abort();
 }
 
-static int aes_v8_set_decrypt_key(const uint8_t *user_key, int bits, AES_KEY *key) {
+static int aes_hw_set_decrypt_key(const uint8_t *user_key, int bits, AES_KEY *key) {
   abort();
 }
 
-static void aes_v8_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
+static void aes_hw_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
   abort();
 }
 
-static void aes_v8_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
+static void aes_hw_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
   abort();
 }
 
@@ -1106,7 +1106,7 @@
 void asm_AES_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
 void AES_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
   if (hwaes_capable()) {
-    aes_v8_encrypt(in, out, key);
+    aes_hw_encrypt(in, out, key);
   } else {
     asm_AES_encrypt(in, out, key);
   }
@@ -1115,7 +1115,7 @@
 void asm_AES_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
 void AES_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
   if (hwaes_capable()) {
-    aes_v8_decrypt(in, out, key);
+    aes_hw_decrypt(in, out, key);
   } else {
     asm_AES_decrypt(in, out, key);
   }
@@ -1124,7 +1124,7 @@
 int asm_AES_set_encrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey);
 int AES_set_encrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey) {
   if (hwaes_capable()) {
-    return aes_v8_set_encrypt_key(key, bits, aeskey);
+    return aes_hw_set_encrypt_key(key, bits, aeskey);
   } else {
     return asm_AES_set_encrypt_key(key, bits, aeskey);
   }
@@ -1133,7 +1133,7 @@
 int asm_AES_set_decrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey);
 int AES_set_decrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey) {
   if (hwaes_capable()) {
-    return aes_v8_set_decrypt_key(key, bits, aeskey);
+    return aes_hw_set_decrypt_key(key, bits, aeskey);
   } else {
     return asm_AES_set_decrypt_key(key, bits, aeskey);
   }
diff --git a/src/crypto/aes/aes_test.cc b/src/crypto/aes/aes_test.cc
index e488d81..cdf03d3 100644
--- a/src/crypto/aes/aes_test.cc
+++ b/src/crypto/aes/aes_test.cc
@@ -15,88 +15,176 @@
 #include <stdio.h>
 #include <string.h>
 
+#include <memory>
+#include <vector>
+
 #include <openssl/aes.h>
 #include <openssl/crypto.h>
 
+#include "../internal.h"
+#include "../test/file_test.h"
 
-static bool TestAES(const uint8_t *key, size_t key_len,
-                    const uint8_t plaintext[AES_BLOCK_SIZE],
-                    const uint8_t ciphertext[AES_BLOCK_SIZE]) {
+
+static bool TestRaw(FileTest *t) {
+  std::vector<uint8_t> key, plaintext, ciphertext;
+  if (!t->GetBytes(&key, "Key") ||
+      !t->GetBytes(&plaintext, "Plaintext") ||
+      !t->GetBytes(&ciphertext, "Ciphertext")) {
+    return false;
+  }
+
+  if (plaintext.size() != AES_BLOCK_SIZE ||
+      ciphertext.size() != AES_BLOCK_SIZE) {
+    t->PrintLine("Plaintext or Ciphertext not a block size.");
+    return false;
+  }
+
   AES_KEY aes_key;
-  if (AES_set_encrypt_key(key, key_len * 8, &aes_key) != 0) {
-    fprintf(stderr, "AES_set_encrypt_key failed\n");
+  if (AES_set_encrypt_key(key.data(), 8 * key.size(), &aes_key) != 0) {
+    t->PrintLine("AES_set_encrypt_key failed.");
     return false;
   }
 
   // Test encryption.
   uint8_t block[AES_BLOCK_SIZE];
-  AES_encrypt(plaintext, block, &aes_key);
-  if (memcmp(block, ciphertext, AES_BLOCK_SIZE) != 0) {
-    fprintf(stderr, "AES_encrypt gave the wrong output\n");
+  AES_encrypt(plaintext.data(), block, &aes_key);
+  if (!t->ExpectBytesEqual(block, AES_BLOCK_SIZE, ciphertext.data(),
+                           ciphertext.size())) {
+    t->PrintLine("AES_encrypt gave the wrong output.");
     return false;
   }
 
   // Test in-place encryption.
-  memcpy(block, plaintext, AES_BLOCK_SIZE);
+  OPENSSL_memcpy(block, plaintext.data(), AES_BLOCK_SIZE);
   AES_encrypt(block, block, &aes_key);
-  if (memcmp(block, ciphertext, AES_BLOCK_SIZE) != 0) {
-    fprintf(stderr, "AES_encrypt gave the wrong output\n");
+  if (!t->ExpectBytesEqual(block, AES_BLOCK_SIZE, ciphertext.data(),
+                           ciphertext.size())) {
+    t->PrintLine("In-place AES_encrypt gave the wrong output.");
     return false;
   }
 
-  if (AES_set_decrypt_key(key, key_len * 8, &aes_key) != 0) {
-    fprintf(stderr, "AES_set_decrypt_key failed\n");
+  if (AES_set_decrypt_key(key.data(), 8 * key.size(), &aes_key) != 0) {
+    t->PrintLine("AES_set_decrypt_key failed.");
     return false;
   }
 
   // Test decryption.
-  AES_decrypt(ciphertext, block, &aes_key);
-  if (memcmp(block, plaintext, AES_BLOCK_SIZE) != 0) {
-    fprintf(stderr, "AES_decrypt gave the wrong output\n");
+  AES_decrypt(ciphertext.data(), block, &aes_key);
+  if (!t->ExpectBytesEqual(block, AES_BLOCK_SIZE, plaintext.data(),
+                           plaintext.size())) {
+    t->PrintLine("AES_decrypt gave the wrong output.");
     return false;
   }
 
   // Test in-place decryption.
-  memcpy(block, ciphertext, AES_BLOCK_SIZE);
+  OPENSSL_memcpy(block, ciphertext.data(), AES_BLOCK_SIZE);
   AES_decrypt(block, block, &aes_key);
-  if (memcmp(block, plaintext, AES_BLOCK_SIZE) != 0) {
-    fprintf(stderr, "AES_decrypt gave the wrong output\n");
+  if (!t->ExpectBytesEqual(block, AES_BLOCK_SIZE, plaintext.data(),
+                           plaintext.size())) {
+    t->PrintLine("In-place AES_decrypt gave the wrong output.");
     return false;
   }
+
   return true;
 }
 
-int main() {
-  CRYPTO_library_init();
+static bool TestKeyWrap(FileTest *t) {
+  // All test vectors use the default IV, so test both with implicit and
+  // explicit IV.
+  //
+  // TODO(davidben): Find test vectors that use a different IV.
+  static const uint8_t kDefaultIV[] = {
+      0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
+  };
 
-  // Test vectors from FIPS-197, Appendix C.
-  if (!TestAES((const uint8_t *)"\x00\x01\x02\x03\x04\x05\x06\x07"
-                                "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
-               128 / 8,
-               (const uint8_t *)"\x00\x11\x22\x33\x44\x55\x66\x77"
-                                "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
-               (const uint8_t *)"\x69\xc4\xe0\xd8\x6a\x7b\x04\x30"
-                                "\xd8\xcd\xb7\x80\x70\xb4\xc5\x5a") ||
-      !TestAES((const uint8_t *)"\x00\x01\x02\x03\x04\x05\x06\x07"
-                                "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
-                                "\x10\x11\x12\x13\x14\x15\x16\x17",
-               192 / 8,
-               (const uint8_t *)"\x00\x11\x22\x33\x44\x55\x66\x77"
-                                "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
-               (const uint8_t *)"\xdd\xa9\x7c\xa4\x86\x4c\xdf\xe0"
-                                "\x6e\xaf\x70\xa0\xec\x0d\x71\x91") ||
-      !TestAES((const uint8_t *)"\x00\x01\x02\x03\x04\x05\x06\x07"
-                                "\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"
-                                "\x10\x11\x12\x13\x14\x15\x16\x17"
-                                "\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f",
-               256 / 8,
-               (const uint8_t *)"\x00\x11\x22\x33\x44\x55\x66\x77"
-                                "\x88\x99\xaa\xbb\xcc\xdd\xee\xff",
-               (const uint8_t *)"\x8e\xa2\xb7\xca\x51\x67\x45\xbf"
-                                "\xea\xfc\x49\x90\x4b\x49\x60\x89")) {
+  std::vector<uint8_t> key, plaintext, ciphertext;
+  if (!t->GetBytes(&key, "Key") ||
+      !t->GetBytes(&plaintext, "Plaintext") ||
+      !t->GetBytes(&ciphertext, "Ciphertext")) {
     return false;
   }
 
-  printf("PASS\n");
-  return 0;
+  if (plaintext.size() + 8 != ciphertext.size()) {
+    t->PrintLine("Invalid Plaintext and Ciphertext lengths.");
+    return false;
+  }
+
+  AES_KEY aes_key;
+  if (AES_set_encrypt_key(key.data(), 8 * key.size(), &aes_key) != 0) {
+    t->PrintLine("AES_set_encrypt_key failed.");
+    return false;
+  }
+
+  std::unique_ptr<uint8_t[]> buf(new uint8_t[ciphertext.size()]);
+  if (AES_wrap_key(&aes_key, nullptr /* iv */, buf.get(), plaintext.data(),
+                   plaintext.size()) != static_cast<int>(ciphertext.size()) ||
+      !t->ExpectBytesEqual(buf.get(), ciphertext.size(), ciphertext.data(),
+                           ciphertext.size())) {
+    t->PrintLine("AES_wrap_key with implicit IV failed.");
+    return false;
+  }
+
+  OPENSSL_memset(buf.get(), 0, ciphertext.size());
+  if (AES_wrap_key(&aes_key, kDefaultIV, buf.get(), plaintext.data(),
+                   plaintext.size()) != static_cast<int>(ciphertext.size()) ||
+      !t->ExpectBytesEqual(buf.get(), ciphertext.size(), ciphertext.data(),
+                           ciphertext.size())) {
+    t->PrintLine("AES_wrap_key with explicit IV failed.");
+    return false;
+  }
+
+  if (AES_set_decrypt_key(key.data(), 8 * key.size(), &aes_key) != 0) {
+    t->PrintLine("AES_set_decrypt_key failed.");
+    return false;
+  }
+
+  buf.reset(new uint8_t[plaintext.size()]);
+  if (AES_unwrap_key(&aes_key, nullptr /* iv */, buf.get(), ciphertext.data(),
+                     ciphertext.size()) != static_cast<int>(plaintext.size()) ||
+      !t->ExpectBytesEqual(buf.get(), plaintext.size(), plaintext.data(),
+                           plaintext.size())) {
+    t->PrintLine("AES_unwrap_key with implicit IV failed.");
+    return false;
+  }
+
+  OPENSSL_memset(buf.get(), 0, plaintext.size());
+  if (AES_unwrap_key(&aes_key, kDefaultIV, buf.get(), ciphertext.data(),
+                     ciphertext.size()) != static_cast<int>(plaintext.size()) ||
+      !t->ExpectBytesEqual(buf.get(), plaintext.size(), plaintext.data(),
+                           plaintext.size())) {
+    t->PrintLine("AES_unwrap_key with explicit IV failed.");
+    return false;
+  }
+
+  ciphertext[0] ^= 1;
+  if (AES_unwrap_key(&aes_key, nullptr /* iv */, buf.get(), ciphertext.data(),
+                     ciphertext.size()) != -1) {
+    t->PrintLine("AES_unwrap_key with bad input unexpectedly succeeded.");
+    return false;
+  }
+
+  return true;
+}
+
+static bool TestAES(FileTest *t, void *arg) {
+  if (t->GetParameter() == "Raw") {
+    return TestRaw(t);
+  }
+  if (t->GetParameter() == "KeyWrap") {
+    return TestKeyWrap(t);
+  }
+
+  t->PrintLine("Unknown mode '%s'.", t->GetParameter().c_str());
+  return false;
+}
+
+int main(int argc, char **argv) {
+  CRYPTO_library_init();
+
+  if (argc != 2) {
+    fprintf(stderr, "%s <test file.txt>\n", argv[0]);
+    return 1;
+  }
+
+  return FileTestMain(TestAES, nullptr, argv[1]);
 }
diff --git a/src/crypto/aes/aes_tests.txt b/src/crypto/aes/aes_tests.txt
new file mode 100644
index 0000000..d4e4c61
--- /dev/null
+++ b/src/crypto/aes/aes_tests.txt
@@ -0,0 +1,50 @@
+# Test vectors from FIPS-197, Appendix C.
+
+Mode = Raw
+Key = 000102030405060708090a0b0c0d0e0f
+Plaintext = 00112233445566778899aabbccddeeff
+Ciphertext = 69c4e0d86a7b0430d8cdb78070b4c55a
+
+Mode = Raw
+Key = 000102030405060708090a0b0c0d0e0f1011121314151617
+Plaintext = 00112233445566778899aabbccddeeff
+Ciphertext = dda97ca4864cdfe06eaf70a0ec0d7191
+
+Mode = Raw
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Plaintext = 00112233445566778899aabbccddeeff
+Ciphertext = 8ea2b7ca516745bfeafc49904b496089
+
+
+# Test vectors from
+# http://csrc.nist.gov/groups/ST/toolkit/documents/kms/key-wrap.pdf
+
+Mode = KeyWrap
+Key = 000102030405060708090a0b0c0d0e0f
+Plaintext = 00112233445566778899aabbccddeeff
+Ciphertext = 1fa68b0a8112b447aef34bd8fb5a7b829d3e862371d2cfe5
+
+Mode = KeyWrap
+Key = 000102030405060708090a0b0c0d0e0f1011121314151617
+Plaintext = 00112233445566778899aabbccddeeff
+Ciphertext = 96778b25ae6ca435f92b5b97c050aed2468ab8a17ad84e5d
+
+Mode = KeyWrap
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Plaintext = 00112233445566778899aabbccddeeff
+Ciphertext = 64e8c3f9ce0f5ba263e9777905818a2a93c8191e7d6e8ae7
+
+Mode = KeyWrap
+Key = 000102030405060708090a0b0c0d0e0f1011121314151617
+Plaintext = 00112233445566778899aabbccddeeff0001020304050607
+Ciphertext = 031d33264e15d33268f24ec260743edce1c6c7ddee725a936ba814915c6762d2
+
+Mode = KeyWrap
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Plaintext = 00112233445566778899aabbccddeeff0001020304050607
+Ciphertext = a8f9bc1612c68b3ff6e6f4fbe30e71e4769c8b80a32cb8958cd5d17d6b254da1
+
+Mode = KeyWrap
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Plaintext = 00112233445566778899aabbccddeeff000102030405060708090a0b0c0d0e0f
+Ciphertext = 28c9f404c4b810f4cbccb35cfb87f8263f5786e2d80ed326cbc7f0e71a99f43bfb988b9b7a02dd21
diff --git a/src/crypto/aes/asm/aes-586.pl b/src/crypto/aes/asm/aes-586.pl
index 6e8a6a8..45c19fb 100755
--- a/src/crypto/aes/asm/aes-586.pl
+++ b/src/crypto/aes/asm/aes-586.pl
@@ -116,7 +116,7 @@
 # words every cache-line is *guaranteed* to be accessed within ~50
 # cycles window. Why just SSE? Because it's needed on hyper-threading
 # CPU! Which is also why it's prefetched with 64 byte stride. Best
-# part is that it has no negative effect on performance:-)  
+# part is that it has no negative effect on performance:-)
 #
 # Version 4.3 implements switch between compact and non-compact block
 # functions in AES_cbc_encrypt depending on how much data was asked
@@ -191,6 +191,10 @@
 push(@INC,"${dir}","${dir}../../perlasm");
 require "x86asm.pl";
 
+$output = pop;
+open OUT,">$output";
+*STDOUT=*OUT;
+
 &asm_init($ARGV[0],"aes-586.pl",$x86only = $ARGV[$#ARGV] eq "386");
 &static_label("AES_Te");
 &static_label("AES_Td");
@@ -574,7 +578,7 @@
 # +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 # |          mm4          |          mm0          |
 # +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
-# |     s3    |     s2    |     s1    |     s0    |    
+# |     s3    |     s2    |     s1    |     s0    |
 # +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
 # |15|14|13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| 0|
 # +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
@@ -794,7 +798,7 @@
 
 	if ($i==3)  {	$tmp=$s[3]; &mov ($s[2],$__s1);		}##%ecx
 	elsif($i==2){	&movz	($tmp,&HB($s[3]));		}#%ebx[2]
-	else        {	&mov	($tmp,$s[3]); 
+	else        {	&mov	($tmp,$s[3]);
 			&shr	($tmp,24)			}
 			&xor	($out,&DWP(1,$te,$tmp,8));
 	if ($i<2)   {	&mov	(&DWP(4+4*$i,"esp"),$out);	}
@@ -1547,7 +1551,7 @@
 		&pxor	("mm1","mm3");		&pxor	("mm5","mm7");	# tp4
 		&pshufw	("mm3","mm1",0xb1);	&pshufw	("mm7","mm5",0xb1);
 		&pxor	("mm0","mm1");		&pxor	("mm4","mm5");	# ^= tp4
-		&pxor	("mm0","mm3");		&pxor	("mm4","mm7");	# ^= ROTATE(tp4,16)	
+		&pxor	("mm0","mm3");		&pxor	("mm4","mm7");	# ^= ROTATE(tp4,16)
 
 		&pxor	("mm3","mm3");		&pxor	("mm7","mm7");
 		&pcmpgtb("mm3","mm1");		&pcmpgtb("mm7","mm5");
@@ -2017,7 +2021,7 @@
 {
 # stack frame layout
 #             -4(%esp)		# return address	 0(%esp)
-#              0(%esp)		# s0 backing store	 4(%esp)	
+#              0(%esp)		# s0 backing store	 4(%esp)
 #              4(%esp)		# s1 backing store	 8(%esp)
 #              8(%esp)		# s2 backing store	12(%esp)
 #             12(%esp)		# s3 backing store	16(%esp)
@@ -2727,7 +2731,7 @@
 	&mov	(&DWP(80,"edi"),10);		# setup number of rounds
 	&xor	("eax","eax");
 	&jmp	(&label("exit"));
-		
+
     &set_label("12rounds");
 	&mov	("eax",&DWP(0,"esi"));		# copy first 6 dwords
 	&mov	("ebx",&DWP(4,"esi"));
@@ -2985,3 +2989,5 @@
 &asciz("AES for x86, CRYPTOGAMS by <appro\@openssl.org>");
 
 &asm_finish();
+
+close STDOUT;
diff --git a/src/crypto/aes/asm/aes-armv4.pl b/src/crypto/aes/asm/aes-armv4.pl
index 882017a..5e1e117 100644
--- a/src/crypto/aes/asm/aes-armv4.pl
+++ b/src/crypto/aes/asm/aes-armv4.pl
@@ -33,8 +33,8 @@
 # improvement on Cortex A8 core and ~21.5 cycles per byte.
 
 $flavour = shift;
-if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
-else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} }
+if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
+else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} }
 
 if ($flavour && $flavour ne "void") {
     $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
@@ -191,7 +191,6 @@
 @ void asm_AES_encrypt(const unsigned char *in, unsigned char *out,
 @ 		       const AES_KEY *key) {
 .global asm_AES_encrypt
-.hidden asm_AES_encrypt
 .type   asm_AES_encrypt,%function
 .align	5
 asm_AES_encrypt:
@@ -441,7 +440,6 @@
 .size	_armv4_AES_encrypt,.-_armv4_AES_encrypt
 
 .global asm_AES_set_encrypt_key
-.hidden asm_AES_set_encrypt_key
 .type   asm_AES_set_encrypt_key,%function
 .align	5
 asm_AES_set_encrypt_key:
@@ -748,7 +746,6 @@
 .size	asm_AES_set_encrypt_key,.-asm_AES_set_encrypt_key
 
 .global asm_AES_set_decrypt_key
-.hidden asm_AES_set_decrypt_key
 .type   asm_AES_set_decrypt_key,%function
 .align	5
 asm_AES_set_decrypt_key:
@@ -765,7 +762,6 @@
 
 @ void AES_set_enc2dec_key(const AES_KEY *inp,AES_KEY *out)
 .global	AES_set_enc2dec_key
-.hidden	AES_set_enc2dec_key
 .type	AES_set_enc2dec_key,%function
 .align	5
 AES_set_enc2dec_key:
@@ -971,7 +967,6 @@
 @ void asm_AES_decrypt(const unsigned char *in, unsigned char *out,
 @ 		       const AES_KEY *key) {
 .global asm_AES_decrypt
-.hidden asm_AES_decrypt
 .type   asm_AES_decrypt,%function
 .align	5
 asm_AES_decrypt:
diff --git a/src/crypto/aes/asm/aes-x86_64.pl b/src/crypto/aes/asm/aes-x86_64.pl
old mode 100644
new mode 100755
index 4b6e1b4..abf957c
--- a/src/crypto/aes/asm/aes-x86_64.pl
+++ b/src/crypto/aes/asm/aes-x86_64.pl
@@ -37,7 +37,7 @@
 ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
 die "can't locate x86_64-xlate.pl";
 
-open OUT,"| \"$^X\" $xlate $flavour $output";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
 *STDOUT=*OUT;
 
 $verticalspin=1;	# unlike 32-bit version $verticalspin performs
@@ -590,6 +590,7 @@
 .type	asm_AES_encrypt,\@function,3
 .hidden	asm_AES_encrypt
 asm_AES_encrypt:
+	mov	%rsp,%rax
 	push	%rbx
 	push	%rbp
 	push	%r12
@@ -598,7 +599,6 @@
 	push	%r15
 
 	# allocate frame "above" key schedule
-	mov	%rsp,%r10
 	lea	-63(%rdx),%rcx	# %rdx is key argument
 	and	\$-64,%rsp
 	sub	%rsp,%rcx
@@ -608,7 +608,7 @@
 	sub	\$32,%rsp
 
 	mov	%rsi,16(%rsp)	# save out
-	mov	%r10,24(%rsp)	# save real stack pointer
+	mov	%rax,24(%rsp)	# save original stack pointer
 .Lenc_prologue:
 
 	mov	%rdx,$key
@@ -640,13 +640,13 @@
 	mov	$s2,8($out)
 	mov	$s3,12($out)
 
-	mov	(%rsi),%r15
-	mov	8(%rsi),%r14
-	mov	16(%rsi),%r13
-	mov	24(%rsi),%r12
-	mov	32(%rsi),%rbp
-	mov	40(%rsi),%rbx
-	lea	48(%rsi),%rsp
+	mov	-48(%rsi),%r15
+	mov	-40(%rsi),%r14
+	mov	-32(%rsi),%r13
+	mov	-24(%rsi),%r12
+	mov	-16(%rsi),%rbp
+	mov	-8(%rsi),%rbx
+	lea	(%rsi),%rsp
 .Lenc_epilogue:
 	ret
 .size	asm_AES_encrypt,.-asm_AES_encrypt
@@ -1186,6 +1186,7 @@
 .type	asm_AES_decrypt,\@function,3
 .hidden	asm_AES_decrypt
 asm_AES_decrypt:
+	mov	%rsp,%rax
 	push	%rbx
 	push	%rbp
 	push	%r12
@@ -1194,7 +1195,6 @@
 	push	%r15
 
 	# allocate frame "above" key schedule
-	mov	%rsp,%r10
 	lea	-63(%rdx),%rcx	# %rdx is key argument
 	and	\$-64,%rsp
 	sub	%rsp,%rcx
@@ -1204,7 +1204,7 @@
 	sub	\$32,%rsp
 
 	mov	%rsi,16(%rsp)	# save out
-	mov	%r10,24(%rsp)	# save real stack pointer
+	mov	%rax,24(%rsp)	# save original stack pointer
 .Ldec_prologue:
 
 	mov	%rdx,$key
@@ -1238,13 +1238,13 @@
 	mov	$s2,8($out)
 	mov	$s3,12($out)
 
-	mov	(%rsi),%r15
-	mov	8(%rsi),%r14
-	mov	16(%rsi),%r13
-	mov	24(%rsi),%r12
-	mov	32(%rsi),%rbp
-	mov	40(%rsi),%rbx
-	lea	48(%rsi),%rsp
+	mov	-48(%rsi),%r15
+	mov	-40(%rsi),%r14
+	mov	-32(%rsi),%r13
+	mov	-24(%rsi),%r12
+	mov	-16(%rsi),%rbp
+	mov	-8(%rsi),%rbx
+	lea	(%rsi),%rsp
 .Ldec_epilogue:
 	ret
 .size	asm_AES_decrypt,.-asm_AES_decrypt
@@ -1286,7 +1286,7 @@
 asm_AES_set_encrypt_key:
 	push	%rbx
 	push	%rbp
-	push	%r12			# redundant, but allows to share 
+	push	%r12			# redundant, but allows to share
 	push	%r13			# exception handler...
 	push	%r14
 	push	%r15
@@ -1412,7 +1412,7 @@
 	xor	%rax,%rax
 	jmp	.Lexit
 
-.L14rounds:		
+.L14rounds:
 	mov	0(%rsi),%rax			# copy first 8 dwords
 	mov	8(%rsi),%rbx
 	mov	16(%rsi),%rcx
@@ -1660,10 +1660,9 @@
 	mov	%r9d,%r9d	# clear upper half of enc
 
 	lea	.LAES_Te(%rip),$sbox
+	lea	.LAES_Td(%rip),%r10
 	cmp	\$0,%r9
-	jne	.Lcbc_picked_te
-	lea	.LAES_Td(%rip),$sbox
-.Lcbc_picked_te:
+	cmoveq	%r10,$sbox
 
 	mov	OPENSSL_ia32cap_P(%rip),%r10d
 	cmp	\$$speed_limit,%rdx
@@ -2565,7 +2564,6 @@
 	jae	.Lin_block_prologue
 
 	mov	24(%rax),%rax		# pull saved real stack pointer
-	lea	48(%rax),%rax		# adjust...
 
 	mov	-8(%rax),%rbx
 	mov	-16(%rax),%rbp
diff --git a/src/crypto/aes/asm/aesni-x86.pl b/src/crypto/aes/asm/aesni-x86.pl
index 9b2e37a..e494dd1 100644
--- a/src/crypto/aes/asm/aesni-x86.pl
+++ b/src/crypto/aes/asm/aesni-x86.pl
@@ -51,7 +51,9 @@
 # Westmere	3.77/1.37	1.37	1.52	1.27
 # * Bridge	5.07/0.98	0.99	1.09	0.91
 # Haswell	4.44/0.80	0.97	1.03	0.72
+# Skylake	2.68/0.65	0.65	0.66	0.64
 # Silvermont	5.77/3.56	3.67	4.03	3.46
+# Goldmont	3.84/1.39	1.39	1.63	1.31
 # Bulldozer	5.80/0.98	1.05	1.24	0.93
 
 $PREFIX="aesni";	# if $PREFIX is set to "AES", the script
@@ -63,6 +65,10 @@
 push(@INC,"${dir}","${dir}../../perlasm");
 require "x86asm.pl";
 
+$output = pop;
+open OUT,">$output";
+*STDOUT=*OUT;
+
 &asm_init($ARGV[0],$0);
 
 &external_label("OPENSSL_ia32cap_P");
@@ -1036,7 +1042,7 @@
 &set_label("ctr32_one_shortcut",16);
 	&movups	($inout0,&QWP(0,$rounds_));	# load ivec
 	&mov	($rounds,&DWP(240,$key));
-	
+
 &set_label("ctr32_one");
 	if ($inline)
 	{   &aesni_inline_generate1("enc");	}
@@ -2523,3 +2529,5 @@
 &asciz("AES for Intel AES-NI, CRYPTOGAMS by <appro\@openssl.org>");
 
 &asm_finish();
+
+close STDOUT;
diff --git a/src/crypto/aes/asm/aesni-x86_64.pl b/src/crypto/aes/asm/aesni-x86_64.pl
index 25ca574..8ae6dbf 100644
--- a/src/crypto/aes/asm/aesni-x86_64.pl
+++ b/src/crypto/aes/asm/aesni-x86_64.pl
@@ -1,4 +1,11 @@
-#!/usr/bin/env perl
+#! /usr/bin/env perl
+# Copyright 2009-2016 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the OpenSSL license (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
 #
 # ====================================================================
 # Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
@@ -27,7 +34,7 @@
 # ECB	4.25/4.25   1.38/1.38   1.28/1.28   1.26/1.26	1.26/1.26
 # CTR	5.42/5.42   1.92/1.92   1.44/1.44   1.28/1.28   1.26/1.26
 # CBC	4.38/4.43   4.15/1.43   4.07/1.32   4.07/1.29   4.06/1.28
-# CCM	5.66/9.42   4.42/5.41   4.16/4.40   4.09/4.15   4.06/4.07   
+# CCM	5.66/9.42   4.42/5.41   4.16/4.40   4.09/4.15   4.06/4.07
 # OFB	5.42/5.42   4.64/4.64   4.44/4.44   4.39/4.39   4.38/4.38
 # CFB	5.73/5.85   5.56/5.62   5.48/5.56   5.47/5.55   5.47/5.55
 #
@@ -111,7 +118,7 @@
 # performance is achieved by interleaving instructions working on
 # independent blocks. In which case asymptotic limit for such modes
 # can be obtained by dividing above mentioned numbers by AES
-# instructions' interleave factor. Westmere can execute at most 3 
+# instructions' interleave factor. Westmere can execute at most 3
 # instructions at a time, meaning that optimal interleave factor is 3,
 # and that's where the "magic" number of 1.25 come from. "Optimal
 # interleave factor" means that increase of interleave factor does
@@ -157,16 +164,23 @@
 # one byte out of 8KB with 128-bit key, Sandy Bridge - 0.90. Just like
 # in CTR mode AES instruction interleave factor was chosen to be 6x.
 
+# November 2015
+#
+# Add aesni_ocb_[en|de]crypt. AES instruction interleave factor was
+# chosen to be 6x.
+
 ######################################################################
 # Current large-block performance in cycles per byte processed with
 # 128-bit key (less is better).
 #
-#		CBC en-/decrypt	CTR	XTS	ECB
+#		CBC en-/decrypt	CTR	XTS	ECB	OCB
 # Westmere	3.77/1.25	1.25	1.25	1.26
-# * Bridge	5.07/0.74	0.75	0.90	0.85
-# Haswell	4.44/0.63	0.63	0.73	0.63
-# Silvermont	5.75/3.54	3.56	4.12	3.87(*)
-# Bulldozer	5.77/0.70	0.72	0.90	0.70
+# * Bridge	5.07/0.74	0.75	0.90	0.85	0.98
+# Haswell	4.44/0.63	0.63	0.73	0.63	0.70
+# Skylake	2.62/0.63	0.63	0.63	0.63
+# Silvermont	5.75/3.54	3.56	4.12	3.87(*)	4.11
+# Goldmont	3.82/1.26	1.26	1.29	1.29	1.50
+# Bulldozer	5.77/0.70	0.72	0.90	0.70	0.95
 #
 # (*)	Atom Silvermont ECB result is suboptimal because of penalties
 #	incurred by operations on %xmm8-15. As ECB is not considered
@@ -187,7 +201,7 @@
 ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
 die "can't locate x86_64-xlate.pl";
 
-open OUT,"| \"$^X\" $xlate $flavour $output";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
 *STDOUT=*OUT;
 
 $movkey = $PREFIX eq "aesni" ? "movups" : "movups";
@@ -299,7 +313,7 @@
 # on 2x subroutine on Atom Silvermont account. For processors that
 # can schedule aes[enc|dec] every cycle optimal interleave factor
 # equals to corresponding instructions latency. 8x is optimal for
-# * Bridge and "super-optimal" for other Intel CPUs... 
+# * Bridge and "super-optimal" for other Intel CPUs...
 
 sub aesni_generate2 {
 my $dir=shift;
@@ -1158,7 +1172,7 @@
 # with zero-round key xor.
 {
 my ($in0,$in1,$in2,$in3,$in4,$in5)=map("%xmm$_",(10..15));
-my ($key0,$ctr)=("${key_}d","${ivp}d");
+my ($key0,$ctr)=("%ebp","${ivp}d");
 my $frame_size = 0x80 + ($win64?160:0);
 
 $code.=<<___;
@@ -1187,26 +1201,25 @@
 
 .align	16
 .Lctr32_bulk:
-	lea	(%rsp),%rax
+	lea	(%rsp),$key_			# use $key_ as frame pointer
 	push	%rbp
 	sub	\$$frame_size,%rsp
 	and	\$-16,%rsp	# Linux kernel stack can be incorrectly seeded
 ___
 $code.=<<___ if ($win64);
-	movaps	%xmm6,-0xa8(%rax)		# offload everything
-	movaps	%xmm7,-0x98(%rax)
-	movaps	%xmm8,-0x88(%rax)
-	movaps	%xmm9,-0x78(%rax)
-	movaps	%xmm10,-0x68(%rax)
-	movaps	%xmm11,-0x58(%rax)
-	movaps	%xmm12,-0x48(%rax)
-	movaps	%xmm13,-0x38(%rax)
-	movaps	%xmm14,-0x28(%rax)
-	movaps	%xmm15,-0x18(%rax)
+	movaps	%xmm6,-0xa8($key_)		# offload everything
+	movaps	%xmm7,-0x98($key_)
+	movaps	%xmm8,-0x88($key_)
+	movaps	%xmm9,-0x78($key_)
+	movaps	%xmm10,-0x68($key_)
+	movaps	%xmm11,-0x58($key_)
+	movaps	%xmm12,-0x48($key_)
+	movaps	%xmm13,-0x38($key_)
+	movaps	%xmm14,-0x28($key_)
+	movaps	%xmm15,-0x18($key_)
 .Lctr32_body:
 ___
 $code.=<<___;
-	lea	-8(%rax),%rbp
 
 	# 8 16-byte words on top of stack are counter values
 	# xor-ed with zero-round key
@@ -1258,7 +1271,7 @@
 	lea	7($ctr),%r9
 	 mov	%r10d,0x60+12(%rsp)
 	bswap	%r9d
-	 mov	OPENSSL_ia32cap_P+4(%rip),%r10d 
+	 mov	OPENSSL_ia32cap_P+4(%rip),%r10d
 	xor	$key0,%r9d
 	 and	\$`1<<26|1<<22`,%r10d		# isolate XSAVE+MOVBE
 	mov	%r9d,0x70+12(%rsp)
@@ -1538,7 +1551,7 @@
 
 .Lctr32_tail:
 	# note that at this point $inout0..5 are populated with
-	# counter values xor-ed with 0-round key 
+	# counter values xor-ed with 0-round key
 	lea	16($key),$key
 	cmp	\$4,$len
 	jb	.Lctr32_loop3
@@ -1678,26 +1691,26 @@
 	pxor	%xmm15,%xmm15
 ___
 $code.=<<___ if ($win64);
-	movaps	-0xa0(%rbp),%xmm6
-	movaps	%xmm0,-0xa0(%rbp)		# clear stack
-	movaps	-0x90(%rbp),%xmm7
-	movaps	%xmm0,-0x90(%rbp)
-	movaps	-0x80(%rbp),%xmm8
-	movaps	%xmm0,-0x80(%rbp)
-	movaps	-0x70(%rbp),%xmm9
-	movaps	%xmm0,-0x70(%rbp)
-	movaps	-0x60(%rbp),%xmm10
-	movaps	%xmm0,-0x60(%rbp)
-	movaps	-0x50(%rbp),%xmm11
-	movaps	%xmm0,-0x50(%rbp)
-	movaps	-0x40(%rbp),%xmm12
-	movaps	%xmm0,-0x40(%rbp)
-	movaps	-0x30(%rbp),%xmm13
-	movaps	%xmm0,-0x30(%rbp)
-	movaps	-0x20(%rbp),%xmm14
-	movaps	%xmm0,-0x20(%rbp)
-	movaps	-0x10(%rbp),%xmm15
-	movaps	%xmm0,-0x10(%rbp)
+	movaps	-0xa8($key_),%xmm6
+	movaps	%xmm0,-0xa8($key_)		# clear stack
+	movaps	-0x98($key_),%xmm7
+	movaps	%xmm0,-0x98($key_)
+	movaps	-0x88($key_),%xmm8
+	movaps	%xmm0,-0x88($key_)
+	movaps	-0x78($key_),%xmm9
+	movaps	%xmm0,-0x78($key_)
+	movaps	-0x68($key_),%xmm10
+	movaps	%xmm0,-0x68($key_)
+	movaps	-0x58($key_),%xmm11
+	movaps	%xmm0,-0x58($key_)
+	movaps	-0x48($key_),%xmm12
+	movaps	%xmm0,-0x48($key_)
+	movaps	-0x38($key_),%xmm13
+	movaps	%xmm0,-0x38($key_)
+	movaps	-0x28($key_),%xmm14
+	movaps	%xmm0,-0x28($key_)
+	movaps	-0x18($key_),%xmm15
+	movaps	%xmm0,-0x18($key_)
 	movaps	%xmm0,0x00(%rsp)
 	movaps	%xmm0,0x10(%rsp)
 	movaps	%xmm0,0x20(%rsp)
@@ -1708,8 +1721,8 @@
 	movaps	%xmm0,0x70(%rsp)
 ___
 $code.=<<___;
-	lea	(%rbp),%rsp
-	pop	%rbp
+	mov	-8($key_),%rbp
+	lea	($key_),%rsp
 .Lctr32_epilogue:
 	ret
 .size	aesni_ctr32_encrypt_blocks,.-aesni_ctr32_encrypt_blocks
@@ -1726,32 +1739,32 @@
 my ($twmask,$twres,$twtmp)=("%xmm8","%xmm9",@tweak[4]);
 my ($key2,$ivp,$len_)=("%r8","%r9","%r9");
 my $frame_size = 0x70 + ($win64?160:0);
+my $key_ = "%rbp";	# override so that we can use %r11 as FP
 
 $code.=<<___;
 .globl	aesni_xts_encrypt
 .type	aesni_xts_encrypt,\@function,6
 .align	16
 aesni_xts_encrypt:
-	lea	(%rsp),%rax
+	lea	(%rsp),%r11			# frame pointer
 	push	%rbp
 	sub	\$$frame_size,%rsp
 	and	\$-16,%rsp	# Linux kernel stack can be incorrectly seeded
 ___
 $code.=<<___ if ($win64);
-	movaps	%xmm6,-0xa8(%rax)		# offload everything
-	movaps	%xmm7,-0x98(%rax)
-	movaps	%xmm8,-0x88(%rax)
-	movaps	%xmm9,-0x78(%rax)
-	movaps	%xmm10,-0x68(%rax)
-	movaps	%xmm11,-0x58(%rax)
-	movaps	%xmm12,-0x48(%rax)
-	movaps	%xmm13,-0x38(%rax)
-	movaps	%xmm14,-0x28(%rax)
-	movaps	%xmm15,-0x18(%rax)
+	movaps	%xmm6,-0xa8(%r11)		# offload everything
+	movaps	%xmm7,-0x98(%r11)
+	movaps	%xmm8,-0x88(%r11)
+	movaps	%xmm9,-0x78(%r11)
+	movaps	%xmm10,-0x68(%r11)
+	movaps	%xmm11,-0x58(%r11)
+	movaps	%xmm12,-0x48(%r11)
+	movaps	%xmm13,-0x38(%r11)
+	movaps	%xmm14,-0x28(%r11)
+	movaps	%xmm15,-0x18(%r11)
 .Lxts_enc_body:
 ___
 $code.=<<___;
-	lea	-8(%rax),%rbp
 	movups	($ivp),$inout0			# load clear-text tweak
 	mov	240(%r8),$rounds		# key2->rounds
 	mov	240($key),$rnds_		# key1->rounds
@@ -2169,26 +2182,26 @@
 	pxor	%xmm15,%xmm15
 ___
 $code.=<<___ if ($win64);
-	movaps	-0xa0(%rbp),%xmm6
-	movaps	%xmm0,-0xa0(%rbp)		# clear stack
-	movaps	-0x90(%rbp),%xmm7
-	movaps	%xmm0,-0x90(%rbp)
-	movaps	-0x80(%rbp),%xmm8
-	movaps	%xmm0,-0x80(%rbp)
-	movaps	-0x70(%rbp),%xmm9
-	movaps	%xmm0,-0x70(%rbp)
-	movaps	-0x60(%rbp),%xmm10
-	movaps	%xmm0,-0x60(%rbp)
-	movaps	-0x50(%rbp),%xmm11
-	movaps	%xmm0,-0x50(%rbp)
-	movaps	-0x40(%rbp),%xmm12
-	movaps	%xmm0,-0x40(%rbp)
-	movaps	-0x30(%rbp),%xmm13
-	movaps	%xmm0,-0x30(%rbp)
-	movaps	-0x20(%rbp),%xmm14
-	movaps	%xmm0,-0x20(%rbp)
-	movaps	-0x10(%rbp),%xmm15
-	movaps	%xmm0,-0x10(%rbp)
+	movaps	-0xa8(%r11),%xmm6
+	movaps	%xmm0,-0xa8(%r11)		# clear stack
+	movaps	-0x98(%r11),%xmm7
+	movaps	%xmm0,-0x98(%r11)
+	movaps	-0x88(%r11),%xmm8
+	movaps	%xmm0,-0x88(%r11)
+	movaps	-0x78(%r11),%xmm9
+	movaps	%xmm0,-0x78(%r11)
+	movaps	-0x68(%r11),%xmm10
+	movaps	%xmm0,-0x68(%r11)
+	movaps	-0x58(%r11),%xmm11
+	movaps	%xmm0,-0x58(%r11)
+	movaps	-0x48(%r11),%xmm12
+	movaps	%xmm0,-0x48(%r11)
+	movaps	-0x38(%r11),%xmm13
+	movaps	%xmm0,-0x38(%r11)
+	movaps	-0x28(%r11),%xmm14
+	movaps	%xmm0,-0x28(%r11)
+	movaps	-0x18(%r11),%xmm15
+	movaps	%xmm0,-0x18(%r11)
 	movaps	%xmm0,0x00(%rsp)
 	movaps	%xmm0,0x10(%rsp)
 	movaps	%xmm0,0x20(%rsp)
@@ -2198,8 +2211,8 @@
 	movaps	%xmm0,0x60(%rsp)
 ___
 $code.=<<___;
-	lea	(%rbp),%rsp
-	pop	%rbp
+	mov	-8(%r11),%rbp
+	lea	(%r11),%rsp
 .Lxts_enc_epilogue:
 	ret
 .size	aesni_xts_encrypt,.-aesni_xts_encrypt
@@ -2210,26 +2223,25 @@
 .type	aesni_xts_decrypt,\@function,6
 .align	16
 aesni_xts_decrypt:
-	lea	(%rsp),%rax
+	lea	(%rsp),%r11			# frame pointer
 	push	%rbp
 	sub	\$$frame_size,%rsp
 	and	\$-16,%rsp	# Linux kernel stack can be incorrectly seeded
 ___
 $code.=<<___ if ($win64);
-	movaps	%xmm6,-0xa8(%rax)		# offload everything
-	movaps	%xmm7,-0x98(%rax)
-	movaps	%xmm8,-0x88(%rax)
-	movaps	%xmm9,-0x78(%rax)
-	movaps	%xmm10,-0x68(%rax)
-	movaps	%xmm11,-0x58(%rax)
-	movaps	%xmm12,-0x48(%rax)
-	movaps	%xmm13,-0x38(%rax)
-	movaps	%xmm14,-0x28(%rax)
-	movaps	%xmm15,-0x18(%rax)
+	movaps	%xmm6,-0xa8(%r11)		# offload everything
+	movaps	%xmm7,-0x98(%r11)
+	movaps	%xmm8,-0x88(%r11)
+	movaps	%xmm9,-0x78(%r11)
+	movaps	%xmm10,-0x68(%r11)
+	movaps	%xmm11,-0x58(%r11)
+	movaps	%xmm12,-0x48(%r11)
+	movaps	%xmm13,-0x38(%r11)
+	movaps	%xmm14,-0x28(%r11)
+	movaps	%xmm15,-0x18(%r11)
 .Lxts_dec_body:
 ___
 $code.=<<___;
-	lea	-8(%rax),%rbp
 	movups	($ivp),$inout0			# load clear-text tweak
 	mov	240($key2),$rounds		# key2->rounds
 	mov	240($key),$rnds_		# key1->rounds
@@ -2673,26 +2685,26 @@
 	pxor	%xmm15,%xmm15
 ___
 $code.=<<___ if ($win64);
-	movaps	-0xa0(%rbp),%xmm6
-	movaps	%xmm0,-0xa0(%rbp)		# clear stack
-	movaps	-0x90(%rbp),%xmm7
-	movaps	%xmm0,-0x90(%rbp)
-	movaps	-0x80(%rbp),%xmm8
-	movaps	%xmm0,-0x80(%rbp)
-	movaps	-0x70(%rbp),%xmm9
-	movaps	%xmm0,-0x70(%rbp)
-	movaps	-0x60(%rbp),%xmm10
-	movaps	%xmm0,-0x60(%rbp)
-	movaps	-0x50(%rbp),%xmm11
-	movaps	%xmm0,-0x50(%rbp)
-	movaps	-0x40(%rbp),%xmm12
-	movaps	%xmm0,-0x40(%rbp)
-	movaps	-0x30(%rbp),%xmm13
-	movaps	%xmm0,-0x30(%rbp)
-	movaps	-0x20(%rbp),%xmm14
-	movaps	%xmm0,-0x20(%rbp)
-	movaps	-0x10(%rbp),%xmm15
-	movaps	%xmm0,-0x10(%rbp)
+	movaps	-0xa8(%r11),%xmm6
+	movaps	%xmm0,-0xa8(%r11)		# clear stack
+	movaps	-0x98(%r11),%xmm7
+	movaps	%xmm0,-0x98(%r11)
+	movaps	-0x88(%r11),%xmm8
+	movaps	%xmm0,-0x88(%r11)
+	movaps	-0x78(%r11),%xmm9
+	movaps	%xmm0,-0x78(%r11)
+	movaps	-0x68(%r11),%xmm10
+	movaps	%xmm0,-0x68(%r11)
+	movaps	-0x58(%r11),%xmm11
+	movaps	%xmm0,-0x58(%r11)
+	movaps	-0x48(%r11),%xmm12
+	movaps	%xmm0,-0x48(%r11)
+	movaps	-0x38(%r11),%xmm13
+	movaps	%xmm0,-0x38(%r11)
+	movaps	-0x28(%r11),%xmm14
+	movaps	%xmm0,-0x28(%r11)
+	movaps	-0x18(%r11),%xmm15
+	movaps	%xmm0,-0x18(%r11)
 	movaps	%xmm0,0x00(%rsp)
 	movaps	%xmm0,0x10(%rsp)
 	movaps	%xmm0,0x20(%rsp)
@@ -2702,12 +2714,933 @@
 	movaps	%xmm0,0x60(%rsp)
 ___
 $code.=<<___;
-	lea	(%rbp),%rsp
-	pop	%rbp
+	mov	-8(%r11),%rbp
+	lea	(%r11),%rsp
 .Lxts_dec_epilogue:
 	ret
 .size	aesni_xts_decrypt,.-aesni_xts_decrypt
 ___
+}
+
+######################################################################
+# void aesni_ocb_[en|de]crypt(const char *inp, char *out, size_t blocks,
+#	const AES_KEY *key, unsigned int start_block_num,
+#	unsigned char offset_i[16], const unsigned char L_[][16],
+#	unsigned char checksum[16]);
+#
+{
+my @offset=map("%xmm$_",(10..15));
+my ($checksum,$rndkey0l)=("%xmm8","%xmm9");
+my ($block_num,$offset_p)=("%r8","%r9");		# 5th and 6th arguments
+my ($L_p,$checksum_p) = ("%rbx","%rbp");
+my ($i1,$i3,$i5) = ("%r12","%r13","%r14");
+my $seventh_arg = $win64 ? 56 : 8;
+my $blocks = $len;
+
+$code.=<<___;
+.globl	aesni_ocb_encrypt
+.type	aesni_ocb_encrypt,\@function,6
+.align	32
+aesni_ocb_encrypt:
+	lea	(%rsp),%rax
+	push	%rbx
+	push	%rbp
+	push	%r12
+	push	%r13
+	push	%r14
+___
+$code.=<<___ if ($win64);
+	lea	-0xa0(%rsp),%rsp
+	movaps	%xmm6,0x00(%rsp)		# offload everything
+	movaps	%xmm7,0x10(%rsp)
+	movaps	%xmm8,0x20(%rsp)
+	movaps	%xmm9,0x30(%rsp)
+	movaps	%xmm10,0x40(%rsp)
+	movaps	%xmm11,0x50(%rsp)
+	movaps	%xmm12,0x60(%rsp)
+	movaps	%xmm13,0x70(%rsp)
+	movaps	%xmm14,0x80(%rsp)
+	movaps	%xmm15,0x90(%rsp)
+.Locb_enc_body:
+___
+$code.=<<___;
+	mov	$seventh_arg(%rax),$L_p		# 7th argument
+	mov	$seventh_arg+8(%rax),$checksum_p# 8th argument
+
+	mov	240($key),$rnds_
+	mov	$key,$key_
+	shl	\$4,$rnds_
+	$movkey	($key),$rndkey0l		# round[0]
+	$movkey	16($key,$rnds_),$rndkey1	# round[last]
+
+	movdqu	($offset_p),@offset[5]		# load last offset_i
+	pxor	$rndkey1,$rndkey0l		# round[0] ^ round[last]
+	pxor	$rndkey1,@offset[5]		# offset_i ^ round[last]
+
+	mov	\$16+32,$rounds
+	lea	32($key_,$rnds_),$key
+	$movkey	16($key_),$rndkey1		# round[1]
+	sub	%r10,%rax			# twisted $rounds
+	mov	%rax,%r10			# backup twisted $rounds
+
+	movdqu	($L_p),@offset[0]		# L_0 for all odd-numbered blocks
+	movdqu	($checksum_p),$checksum		# load checksum
+
+	test	\$1,$block_num			# is first block number odd?
+	jnz	.Locb_enc_odd
+
+	bsf	$block_num,$i1
+	add	\$1,$block_num
+	shl	\$4,$i1
+	movdqu	($L_p,$i1),$inout5		# borrow
+	movdqu	($inp),$inout0
+	lea	16($inp),$inp
+
+	call	__ocb_encrypt1
+
+	movdqa	$inout5,@offset[5]
+	movups	$inout0,($out)
+	lea	16($out),$out
+	sub	\$1,$blocks
+	jz	.Locb_enc_done
+
+.Locb_enc_odd:
+	lea	1($block_num),$i1		# even-numbered blocks
+	lea	3($block_num),$i3
+	lea	5($block_num),$i5
+	lea	6($block_num),$block_num
+	bsf	$i1,$i1				# ntz(block)
+	bsf	$i3,$i3
+	bsf	$i5,$i5
+	shl	\$4,$i1				# ntz(block) -> table offset
+	shl	\$4,$i3
+	shl	\$4,$i5
+
+	sub	\$6,$blocks
+	jc	.Locb_enc_short
+	jmp	.Locb_enc_grandloop
+
+.align	32
+.Locb_enc_grandloop:
+	movdqu	`16*0`($inp),$inout0		# load input
+	movdqu	`16*1`($inp),$inout1
+	movdqu	`16*2`($inp),$inout2
+	movdqu	`16*3`($inp),$inout3
+	movdqu	`16*4`($inp),$inout4
+	movdqu	`16*5`($inp),$inout5
+	lea	`16*6`($inp),$inp
+
+	call	__ocb_encrypt6
+
+	movups	$inout0,`16*0`($out)		# store output
+	movups	$inout1,`16*1`($out)
+	movups	$inout2,`16*2`($out)
+	movups	$inout3,`16*3`($out)
+	movups	$inout4,`16*4`($out)
+	movups	$inout5,`16*5`($out)
+	lea	`16*6`($out),$out
+	sub	\$6,$blocks
+	jnc	.Locb_enc_grandloop
+
+.Locb_enc_short:
+	add	\$6,$blocks
+	jz	.Locb_enc_done
+
+	movdqu	`16*0`($inp),$inout0
+	cmp	\$2,$blocks
+	jb	.Locb_enc_one
+	movdqu	`16*1`($inp),$inout1
+	je	.Locb_enc_two
+
+	movdqu	`16*2`($inp),$inout2
+	cmp	\$4,$blocks
+	jb	.Locb_enc_three
+	movdqu	`16*3`($inp),$inout3
+	je	.Locb_enc_four
+
+	movdqu	`16*4`($inp),$inout4
+	pxor	$inout5,$inout5
+
+	call	__ocb_encrypt6
+
+	movdqa	@offset[4],@offset[5]
+	movups	$inout0,`16*0`($out)
+	movups	$inout1,`16*1`($out)
+	movups	$inout2,`16*2`($out)
+	movups	$inout3,`16*3`($out)
+	movups	$inout4,`16*4`($out)
+
+	jmp	.Locb_enc_done
+
+.align	16
+.Locb_enc_one:
+	movdqa	@offset[0],$inout5		# borrow
+
+	call	__ocb_encrypt1
+
+	movdqa	$inout5,@offset[5]
+	movups	$inout0,`16*0`($out)
+	jmp	.Locb_enc_done
+
+.align	16
+.Locb_enc_two:
+	pxor	$inout2,$inout2
+	pxor	$inout3,$inout3
+
+	call	__ocb_encrypt4
+
+	movdqa	@offset[1],@offset[5]
+	movups	$inout0,`16*0`($out)
+	movups	$inout1,`16*1`($out)
+
+	jmp	.Locb_enc_done
+
+.align	16
+.Locb_enc_three:
+	pxor	$inout3,$inout3
+
+	call	__ocb_encrypt4
+
+	movdqa	@offset[2],@offset[5]
+	movups	$inout0,`16*0`($out)
+	movups	$inout1,`16*1`($out)
+	movups	$inout2,`16*2`($out)
+
+	jmp	.Locb_enc_done
+
+.align	16
+.Locb_enc_four:
+	call	__ocb_encrypt4
+
+	movdqa	@offset[3],@offset[5]
+	movups	$inout0,`16*0`($out)
+	movups	$inout1,`16*1`($out)
+	movups	$inout2,`16*2`($out)
+	movups	$inout3,`16*3`($out)
+
+.Locb_enc_done:
+	pxor	$rndkey0,@offset[5]		# "remove" round[last]
+	movdqu	$checksum,($checksum_p)		# store checksum
+	movdqu	@offset[5],($offset_p)		# store last offset_i
+
+	xorps	%xmm0,%xmm0			# clear register bank
+	pxor	%xmm1,%xmm1
+	pxor	%xmm2,%xmm2
+	pxor	%xmm3,%xmm3
+	pxor	%xmm4,%xmm4
+	pxor	%xmm5,%xmm5
+___
+$code.=<<___ if (!$win64);
+	pxor	%xmm6,%xmm6
+	pxor	%xmm7,%xmm7
+	pxor	%xmm8,%xmm8
+	pxor	%xmm9,%xmm9
+	pxor	%xmm10,%xmm10
+	pxor	%xmm11,%xmm11
+	pxor	%xmm12,%xmm12
+	pxor	%xmm13,%xmm13
+	pxor	%xmm14,%xmm14
+	pxor	%xmm15,%xmm15
+	lea	0x28(%rsp),%rax
+___
+$code.=<<___ if ($win64);
+	movaps	0x00(%rsp),%xmm6
+	movaps	%xmm0,0x00(%rsp)		# clear stack
+	movaps	0x10(%rsp),%xmm7
+	movaps	%xmm0,0x10(%rsp)
+	movaps	0x20(%rsp),%xmm8
+	movaps	%xmm0,0x20(%rsp)
+	movaps	0x30(%rsp),%xmm9
+	movaps	%xmm0,0x30(%rsp)
+	movaps	0x40(%rsp),%xmm10
+	movaps	%xmm0,0x40(%rsp)
+	movaps	0x50(%rsp),%xmm11
+	movaps	%xmm0,0x50(%rsp)
+	movaps	0x60(%rsp),%xmm12
+	movaps	%xmm0,0x60(%rsp)
+	movaps	0x70(%rsp),%xmm13
+	movaps	%xmm0,0x70(%rsp)
+	movaps	0x80(%rsp),%xmm14
+	movaps	%xmm0,0x80(%rsp)
+	movaps	0x90(%rsp),%xmm15
+	movaps	%xmm0,0x90(%rsp)
+	lea	0xa0+0x28(%rsp),%rax
+.Locb_enc_pop:
+___
+$code.=<<___;
+	mov	-40(%rax),%r14
+	mov	-32(%rax),%r13
+	mov	-24(%rax),%r12
+	mov	-16(%rax),%rbp
+	mov	-8(%rax),%rbx
+	lea	(%rax),%rsp
+.Locb_enc_epilogue:
+	ret
+.size	aesni_ocb_encrypt,.-aesni_ocb_encrypt
+
+.type	__ocb_encrypt6,\@abi-omnipotent
+.align	32
+__ocb_encrypt6:
+	 pxor		$rndkey0l,@offset[5]	# offset_i ^ round[0]
+	 movdqu		($L_p,$i1),@offset[1]
+	 movdqa		@offset[0],@offset[2]
+	 movdqu		($L_p,$i3),@offset[3]
+	 movdqa		@offset[0],@offset[4]
+	 pxor		@offset[5],@offset[0]
+	 movdqu		($L_p,$i5),@offset[5]
+	 pxor		@offset[0],@offset[1]
+	pxor		$inout0,$checksum	# accumulate checksum
+	pxor		@offset[0],$inout0	# input ^ round[0] ^ offset_i
+	 pxor		@offset[1],@offset[2]
+	pxor		$inout1,$checksum
+	pxor		@offset[1],$inout1
+	 pxor		@offset[2],@offset[3]
+	pxor		$inout2,$checksum
+	pxor		@offset[2],$inout2
+	 pxor		@offset[3],@offset[4]
+	pxor		$inout3,$checksum
+	pxor		@offset[3],$inout3
+	 pxor		@offset[4],@offset[5]
+	pxor		$inout4,$checksum
+	pxor		@offset[4],$inout4
+	pxor		$inout5,$checksum
+	pxor		@offset[5],$inout5
+	$movkey		32($key_),$rndkey0
+
+	lea		1($block_num),$i1	# even-numbered blocks
+	lea		3($block_num),$i3
+	lea		5($block_num),$i5
+	add		\$6,$block_num
+	 pxor		$rndkey0l,@offset[0]	# offset_i ^ round[last]
+	bsf		$i1,$i1			# ntz(block)
+	bsf		$i3,$i3
+	bsf		$i5,$i5
+
+	aesenc		$rndkey1,$inout0
+	aesenc		$rndkey1,$inout1
+	aesenc		$rndkey1,$inout2
+	aesenc		$rndkey1,$inout3
+	 pxor		$rndkey0l,@offset[1]
+	 pxor		$rndkey0l,@offset[2]
+	aesenc		$rndkey1,$inout4
+	 pxor		$rndkey0l,@offset[3]
+	 pxor		$rndkey0l,@offset[4]
+	aesenc		$rndkey1,$inout5
+	$movkey		48($key_),$rndkey1
+	 pxor		$rndkey0l,@offset[5]
+
+	aesenc		$rndkey0,$inout0
+	aesenc		$rndkey0,$inout1
+	aesenc		$rndkey0,$inout2
+	aesenc		$rndkey0,$inout3
+	aesenc		$rndkey0,$inout4
+	aesenc		$rndkey0,$inout5
+	$movkey		64($key_),$rndkey0
+	shl		\$4,$i1			# ntz(block) -> table offset
+	shl		\$4,$i3
+	jmp		.Locb_enc_loop6
+
+.align	32
+.Locb_enc_loop6:
+	aesenc		$rndkey1,$inout0
+	aesenc		$rndkey1,$inout1
+	aesenc		$rndkey1,$inout2
+	aesenc		$rndkey1,$inout3
+	aesenc		$rndkey1,$inout4
+	aesenc		$rndkey1,$inout5
+	$movkey		($key,%rax),$rndkey1
+	add		\$32,%rax
+
+	aesenc		$rndkey0,$inout0
+	aesenc		$rndkey0,$inout1
+	aesenc		$rndkey0,$inout2
+	aesenc		$rndkey0,$inout3
+	aesenc		$rndkey0,$inout4
+	aesenc		$rndkey0,$inout5
+	$movkey		-16($key,%rax),$rndkey0
+	jnz		.Locb_enc_loop6
+
+	aesenc		$rndkey1,$inout0
+	aesenc		$rndkey1,$inout1
+	aesenc		$rndkey1,$inout2
+	aesenc		$rndkey1,$inout3
+	aesenc		$rndkey1,$inout4
+	aesenc		$rndkey1,$inout5
+	$movkey		16($key_),$rndkey1
+	shl		\$4,$i5
+
+	aesenclast	@offset[0],$inout0
+	movdqu		($L_p),@offset[0]	# L_0 for all odd-numbered blocks
+	mov		%r10,%rax		# restore twisted rounds
+	aesenclast	@offset[1],$inout1
+	aesenclast	@offset[2],$inout2
+	aesenclast	@offset[3],$inout3
+	aesenclast	@offset[4],$inout4
+	aesenclast	@offset[5],$inout5
+	ret
+.size	__ocb_encrypt6,.-__ocb_encrypt6
+
+.type	__ocb_encrypt4,\@abi-omnipotent
+.align	32
+__ocb_encrypt4:
+	 pxor		$rndkey0l,@offset[5]	# offset_i ^ round[0]
+	 movdqu		($L_p,$i1),@offset[1]
+	 movdqa		@offset[0],@offset[2]
+	 movdqu		($L_p,$i3),@offset[3]
+	 pxor		@offset[5],@offset[0]
+	 pxor		@offset[0],@offset[1]
+	pxor		$inout0,$checksum	# accumulate checksum
+	pxor		@offset[0],$inout0	# input ^ round[0] ^ offset_i
+	 pxor		@offset[1],@offset[2]
+	pxor		$inout1,$checksum
+	pxor		@offset[1],$inout1
+	 pxor		@offset[2],@offset[3]
+	pxor		$inout2,$checksum
+	pxor		@offset[2],$inout2
+	pxor		$inout3,$checksum
+	pxor		@offset[3],$inout3
+	$movkey		32($key_),$rndkey0
+
+	 pxor		$rndkey0l,@offset[0]	# offset_i ^ round[last]
+	 pxor		$rndkey0l,@offset[1]
+	 pxor		$rndkey0l,@offset[2]
+	 pxor		$rndkey0l,@offset[3]
+
+	aesenc		$rndkey1,$inout0
+	aesenc		$rndkey1,$inout1
+	aesenc		$rndkey1,$inout2
+	aesenc		$rndkey1,$inout3
+	$movkey		48($key_),$rndkey1
+
+	aesenc		$rndkey0,$inout0
+	aesenc		$rndkey0,$inout1
+	aesenc		$rndkey0,$inout2
+	aesenc		$rndkey0,$inout3
+	$movkey		64($key_),$rndkey0
+	jmp		.Locb_enc_loop4
+
+.align	32
+.Locb_enc_loop4:
+	aesenc		$rndkey1,$inout0
+	aesenc		$rndkey1,$inout1
+	aesenc		$rndkey1,$inout2
+	aesenc		$rndkey1,$inout3
+	$movkey		($key,%rax),$rndkey1
+	add		\$32,%rax
+
+	aesenc		$rndkey0,$inout0
+	aesenc		$rndkey0,$inout1
+	aesenc		$rndkey0,$inout2
+	aesenc		$rndkey0,$inout3
+	$movkey		-16($key,%rax),$rndkey0
+	jnz		.Locb_enc_loop4
+
+	aesenc		$rndkey1,$inout0
+	aesenc		$rndkey1,$inout1
+	aesenc		$rndkey1,$inout2
+	aesenc		$rndkey1,$inout3
+	$movkey		16($key_),$rndkey1
+	mov		%r10,%rax		# restore twisted rounds
+
+	aesenclast	@offset[0],$inout0
+	aesenclast	@offset[1],$inout1
+	aesenclast	@offset[2],$inout2
+	aesenclast	@offset[3],$inout3
+	ret
+.size	__ocb_encrypt4,.-__ocb_encrypt4
+
+.type	__ocb_encrypt1,\@abi-omnipotent
+.align	32
+__ocb_encrypt1:
+	 pxor		@offset[5],$inout5	# offset_i
+	 pxor		$rndkey0l,$inout5	# offset_i ^ round[0]
+	pxor		$inout0,$checksum	# accumulate checksum
+	pxor		$inout5,$inout0		# input ^ round[0] ^ offset_i
+	$movkey		32($key_),$rndkey0
+
+	aesenc		$rndkey1,$inout0
+	$movkey		48($key_),$rndkey1
+	pxor		$rndkey0l,$inout5	# offset_i ^ round[last]
+
+	aesenc		$rndkey0,$inout0
+	$movkey		64($key_),$rndkey0
+	jmp		.Locb_enc_loop1
+
+.align	32
+.Locb_enc_loop1:
+	aesenc		$rndkey1,$inout0
+	$movkey		($key,%rax),$rndkey1
+	add		\$32,%rax
+
+	aesenc		$rndkey0,$inout0
+	$movkey		-16($key,%rax),$rndkey0
+	jnz		.Locb_enc_loop1
+
+	aesenc		$rndkey1,$inout0
+	$movkey		16($key_),$rndkey1	# redundant in tail
+	mov		%r10,%rax		# restore twisted rounds
+
+	aesenclast	$inout5,$inout0
+	ret
+.size	__ocb_encrypt1,.-__ocb_encrypt1
+
+.globl	aesni_ocb_decrypt
+.type	aesni_ocb_decrypt,\@function,6
+.align	32
+aesni_ocb_decrypt:
+	lea	(%rsp),%rax
+	push	%rbx
+	push	%rbp
+	push	%r12
+	push	%r13
+	push	%r14
+___
+$code.=<<___ if ($win64);
+	lea	-0xa0(%rsp),%rsp
+	movaps	%xmm6,0x00(%rsp)		# offload everything
+	movaps	%xmm7,0x10(%rsp)
+	movaps	%xmm8,0x20(%rsp)
+	movaps	%xmm9,0x30(%rsp)
+	movaps	%xmm10,0x40(%rsp)
+	movaps	%xmm11,0x50(%rsp)
+	movaps	%xmm12,0x60(%rsp)
+	movaps	%xmm13,0x70(%rsp)
+	movaps	%xmm14,0x80(%rsp)
+	movaps	%xmm15,0x90(%rsp)
+.Locb_dec_body:
+___
+$code.=<<___;
+	mov	$seventh_arg(%rax),$L_p		# 7th argument
+	mov	$seventh_arg+8(%rax),$checksum_p# 8th argument
+
+	mov	240($key),$rnds_
+	mov	$key,$key_
+	shl	\$4,$rnds_
+	$movkey	($key),$rndkey0l		# round[0]
+	$movkey	16($key,$rnds_),$rndkey1	# round[last]
+
+	movdqu	($offset_p),@offset[5]		# load last offset_i
+	pxor	$rndkey1,$rndkey0l		# round[0] ^ round[last]
+	pxor	$rndkey1,@offset[5]		# offset_i ^ round[last]
+
+	mov	\$16+32,$rounds
+	lea	32($key_,$rnds_),$key
+	$movkey	16($key_),$rndkey1		# round[1]
+	sub	%r10,%rax			# twisted $rounds
+	mov	%rax,%r10			# backup twisted $rounds
+
+	movdqu	($L_p),@offset[0]		# L_0 for all odd-numbered blocks
+	movdqu	($checksum_p),$checksum		# load checksum
+
+	test	\$1,$block_num			# is first block number odd?
+	jnz	.Locb_dec_odd
+
+	bsf	$block_num,$i1
+	add	\$1,$block_num
+	shl	\$4,$i1
+	movdqu	($L_p,$i1),$inout5		# borrow
+	movdqu	($inp),$inout0
+	lea	16($inp),$inp
+
+	call	__ocb_decrypt1
+
+	movdqa	$inout5,@offset[5]
+	movups	$inout0,($out)
+	xorps	$inout0,$checksum		# accumulate checksum
+	lea	16($out),$out
+	sub	\$1,$blocks
+	jz	.Locb_dec_done
+
+.Locb_dec_odd:
+	lea	1($block_num),$i1		# even-numbered blocks
+	lea	3($block_num),$i3
+	lea	5($block_num),$i5
+	lea	6($block_num),$block_num
+	bsf	$i1,$i1				# ntz(block)
+	bsf	$i3,$i3
+	bsf	$i5,$i5
+	shl	\$4,$i1				# ntz(block) -> table offset
+	shl	\$4,$i3
+	shl	\$4,$i5
+
+	sub	\$6,$blocks
+	jc	.Locb_dec_short
+	jmp	.Locb_dec_grandloop
+
+.align	32
+.Locb_dec_grandloop:
+	movdqu	`16*0`($inp),$inout0		# load input
+	movdqu	`16*1`($inp),$inout1
+	movdqu	`16*2`($inp),$inout2
+	movdqu	`16*3`($inp),$inout3
+	movdqu	`16*4`($inp),$inout4
+	movdqu	`16*5`($inp),$inout5
+	lea	`16*6`($inp),$inp
+
+	call	__ocb_decrypt6
+
+	movups	$inout0,`16*0`($out)		# store output
+	pxor	$inout0,$checksum		# accumulate checksum
+	movups	$inout1,`16*1`($out)
+	pxor	$inout1,$checksum
+	movups	$inout2,`16*2`($out)
+	pxor	$inout2,$checksum
+	movups	$inout3,`16*3`($out)
+	pxor	$inout3,$checksum
+	movups	$inout4,`16*4`($out)
+	pxor	$inout4,$checksum
+	movups	$inout5,`16*5`($out)
+	pxor	$inout5,$checksum
+	lea	`16*6`($out),$out
+	sub	\$6,$blocks
+	jnc	.Locb_dec_grandloop
+
+.Locb_dec_short:
+	add	\$6,$blocks
+	jz	.Locb_dec_done
+
+	movdqu	`16*0`($inp),$inout0
+	cmp	\$2,$blocks
+	jb	.Locb_dec_one
+	movdqu	`16*1`($inp),$inout1
+	je	.Locb_dec_two
+
+	movdqu	`16*2`($inp),$inout2
+	cmp	\$4,$blocks
+	jb	.Locb_dec_three
+	movdqu	`16*3`($inp),$inout3
+	je	.Locb_dec_four
+
+	movdqu	`16*4`($inp),$inout4
+	pxor	$inout5,$inout5
+
+	call	__ocb_decrypt6
+
+	movdqa	@offset[4],@offset[5]
+	movups	$inout0,`16*0`($out)		# store output
+	pxor	$inout0,$checksum		# accumulate checksum
+	movups	$inout1,`16*1`($out)
+	pxor	$inout1,$checksum
+	movups	$inout2,`16*2`($out)
+	pxor	$inout2,$checksum
+	movups	$inout3,`16*3`($out)
+	pxor	$inout3,$checksum
+	movups	$inout4,`16*4`($out)
+	pxor	$inout4,$checksum
+
+	jmp	.Locb_dec_done
+
+.align	16
+.Locb_dec_one:
+	movdqa	@offset[0],$inout5		# borrow
+
+	call	__ocb_decrypt1
+
+	movdqa	$inout5,@offset[5]
+	movups	$inout0,`16*0`($out)		# store output
+	xorps	$inout0,$checksum		# accumulate checksum
+	jmp	.Locb_dec_done
+
+.align	16
+.Locb_dec_two:
+	pxor	$inout2,$inout2
+	pxor	$inout3,$inout3
+
+	call	__ocb_decrypt4
+
+	movdqa	@offset[1],@offset[5]
+	movups	$inout0,`16*0`($out)		# store output
+	xorps	$inout0,$checksum		# accumulate checksum
+	movups	$inout1,`16*1`($out)
+	xorps	$inout1,$checksum
+
+	jmp	.Locb_dec_done
+
+.align	16
+.Locb_dec_three:
+	pxor	$inout3,$inout3
+
+	call	__ocb_decrypt4
+
+	movdqa	@offset[2],@offset[5]
+	movups	$inout0,`16*0`($out)		# store output
+	xorps	$inout0,$checksum		# accumulate checksum
+	movups	$inout1,`16*1`($out)
+	xorps	$inout1,$checksum
+	movups	$inout2,`16*2`($out)
+	xorps	$inout2,$checksum
+
+	jmp	.Locb_dec_done
+
+.align	16
+.Locb_dec_four:
+	call	__ocb_decrypt4
+
+	movdqa	@offset[3],@offset[5]
+	movups	$inout0,`16*0`($out)		# store output
+	pxor	$inout0,$checksum		# accumulate checksum
+	movups	$inout1,`16*1`($out)
+	pxor	$inout1,$checksum
+	movups	$inout2,`16*2`($out)
+	pxor	$inout2,$checksum
+	movups	$inout3,`16*3`($out)
+	pxor	$inout3,$checksum
+
+.Locb_dec_done:
+	pxor	$rndkey0,@offset[5]		# "remove" round[last]
+	movdqu	$checksum,($checksum_p)		# store checksum
+	movdqu	@offset[5],($offset_p)		# store last offset_i
+
+	xorps	%xmm0,%xmm0			# clear register bank
+	pxor	%xmm1,%xmm1
+	pxor	%xmm2,%xmm2
+	pxor	%xmm3,%xmm3
+	pxor	%xmm4,%xmm4
+	pxor	%xmm5,%xmm5
+___
+$code.=<<___ if (!$win64);
+	pxor	%xmm6,%xmm6
+	pxor	%xmm7,%xmm7
+	pxor	%xmm8,%xmm8
+	pxor	%xmm9,%xmm9
+	pxor	%xmm10,%xmm10
+	pxor	%xmm11,%xmm11
+	pxor	%xmm12,%xmm12
+	pxor	%xmm13,%xmm13
+	pxor	%xmm14,%xmm14
+	pxor	%xmm15,%xmm15
+	lea	0x28(%rsp),%rax
+___
+$code.=<<___ if ($win64);
+	movaps	0x00(%rsp),%xmm6
+	movaps	%xmm0,0x00(%rsp)		# clear stack
+	movaps	0x10(%rsp),%xmm7
+	movaps	%xmm0,0x10(%rsp)
+	movaps	0x20(%rsp),%xmm8
+	movaps	%xmm0,0x20(%rsp)
+	movaps	0x30(%rsp),%xmm9
+	movaps	%xmm0,0x30(%rsp)
+	movaps	0x40(%rsp),%xmm10
+	movaps	%xmm0,0x40(%rsp)
+	movaps	0x50(%rsp),%xmm11
+	movaps	%xmm0,0x50(%rsp)
+	movaps	0x60(%rsp),%xmm12
+	movaps	%xmm0,0x60(%rsp)
+	movaps	0x70(%rsp),%xmm13
+	movaps	%xmm0,0x70(%rsp)
+	movaps	0x80(%rsp),%xmm14
+	movaps	%xmm0,0x80(%rsp)
+	movaps	0x90(%rsp),%xmm15
+	movaps	%xmm0,0x90(%rsp)
+	lea	0xa0+0x28(%rsp),%rax
+.Locb_dec_pop:
+___
+$code.=<<___;
+	mov	-40(%rax),%r14
+	mov	-32(%rax),%r13
+	mov	-24(%rax),%r12
+	mov	-16(%rax),%rbp
+	mov	-8(%rax),%rbx
+	lea	(%rax),%rsp
+.Locb_dec_epilogue:
+	ret
+.size	aesni_ocb_decrypt,.-aesni_ocb_decrypt
+
+.type	__ocb_decrypt6,\@abi-omnipotent
+.align	32
+__ocb_decrypt6:
+	 pxor		$rndkey0l,@offset[5]	# offset_i ^ round[0]
+	 movdqu		($L_p,$i1),@offset[1]
+	 movdqa		@offset[0],@offset[2]
+	 movdqu		($L_p,$i3),@offset[3]
+	 movdqa		@offset[0],@offset[4]
+	 pxor		@offset[5],@offset[0]
+	 movdqu		($L_p,$i5),@offset[5]
+	 pxor		@offset[0],@offset[1]
+	pxor		@offset[0],$inout0	# input ^ round[0] ^ offset_i
+	 pxor		@offset[1],@offset[2]
+	pxor		@offset[1],$inout1
+	 pxor		@offset[2],@offset[3]
+	pxor		@offset[2],$inout2
+	 pxor		@offset[3],@offset[4]
+	pxor		@offset[3],$inout3
+	 pxor		@offset[4],@offset[5]
+	pxor		@offset[4],$inout4
+	pxor		@offset[5],$inout5
+	$movkey		32($key_),$rndkey0
+
+	lea		1($block_num),$i1	# even-numbered blocks
+	lea		3($block_num),$i3
+	lea		5($block_num),$i5
+	add		\$6,$block_num
+	 pxor		$rndkey0l,@offset[0]	# offset_i ^ round[last]
+	bsf		$i1,$i1			# ntz(block)
+	bsf		$i3,$i3
+	bsf		$i5,$i5
+
+	aesdec		$rndkey1,$inout0
+	aesdec		$rndkey1,$inout1
+	aesdec		$rndkey1,$inout2
+	aesdec		$rndkey1,$inout3
+	 pxor		$rndkey0l,@offset[1]
+	 pxor		$rndkey0l,@offset[2]
+	aesdec		$rndkey1,$inout4
+	 pxor		$rndkey0l,@offset[3]
+	 pxor		$rndkey0l,@offset[4]
+	aesdec		$rndkey1,$inout5
+	$movkey		48($key_),$rndkey1
+	 pxor		$rndkey0l,@offset[5]
+
+	aesdec		$rndkey0,$inout0
+	aesdec		$rndkey0,$inout1
+	aesdec		$rndkey0,$inout2
+	aesdec		$rndkey0,$inout3
+	aesdec		$rndkey0,$inout4
+	aesdec		$rndkey0,$inout5
+	$movkey		64($key_),$rndkey0
+	shl		\$4,$i1			# ntz(block) -> table offset
+	shl		\$4,$i3
+	jmp		.Locb_dec_loop6
+
+.align	32
+.Locb_dec_loop6:
+	aesdec		$rndkey1,$inout0
+	aesdec		$rndkey1,$inout1
+	aesdec		$rndkey1,$inout2
+	aesdec		$rndkey1,$inout3
+	aesdec		$rndkey1,$inout4
+	aesdec		$rndkey1,$inout5
+	$movkey		($key,%rax),$rndkey1
+	add		\$32,%rax
+
+	aesdec		$rndkey0,$inout0
+	aesdec		$rndkey0,$inout1
+	aesdec		$rndkey0,$inout2
+	aesdec		$rndkey0,$inout3
+	aesdec		$rndkey0,$inout4
+	aesdec		$rndkey0,$inout5
+	$movkey		-16($key,%rax),$rndkey0
+	jnz		.Locb_dec_loop6
+
+	aesdec		$rndkey1,$inout0
+	aesdec		$rndkey1,$inout1
+	aesdec		$rndkey1,$inout2
+	aesdec		$rndkey1,$inout3
+	aesdec		$rndkey1,$inout4
+	aesdec		$rndkey1,$inout5
+	$movkey		16($key_),$rndkey1
+	shl		\$4,$i5
+
+	aesdeclast	@offset[0],$inout0
+	movdqu		($L_p),@offset[0]	# L_0 for all odd-numbered blocks
+	mov		%r10,%rax		# restore twisted rounds
+	aesdeclast	@offset[1],$inout1
+	aesdeclast	@offset[2],$inout2
+	aesdeclast	@offset[3],$inout3
+	aesdeclast	@offset[4],$inout4
+	aesdeclast	@offset[5],$inout5
+	ret
+.size	__ocb_decrypt6,.-__ocb_decrypt6
+
+.type	__ocb_decrypt4,\@abi-omnipotent
+.align	32
+__ocb_decrypt4:
+	 pxor		$rndkey0l,@offset[5]	# offset_i ^ round[0]
+	 movdqu		($L_p,$i1),@offset[1]
+	 movdqa		@offset[0],@offset[2]
+	 movdqu		($L_p,$i3),@offset[3]
+	 pxor		@offset[5],@offset[0]
+	 pxor		@offset[0],@offset[1]
+	pxor		@offset[0],$inout0	# input ^ round[0] ^ offset_i
+	 pxor		@offset[1],@offset[2]
+	pxor		@offset[1],$inout1
+	 pxor		@offset[2],@offset[3]
+	pxor		@offset[2],$inout2
+	pxor		@offset[3],$inout3
+	$movkey		32($key_),$rndkey0
+
+	 pxor		$rndkey0l,@offset[0]	# offset_i ^ round[last]
+	 pxor		$rndkey0l,@offset[1]
+	 pxor		$rndkey0l,@offset[2]
+	 pxor		$rndkey0l,@offset[3]
+
+	aesdec		$rndkey1,$inout0
+	aesdec		$rndkey1,$inout1
+	aesdec		$rndkey1,$inout2
+	aesdec		$rndkey1,$inout3
+	$movkey		48($key_),$rndkey1
+
+	aesdec		$rndkey0,$inout0
+	aesdec		$rndkey0,$inout1
+	aesdec		$rndkey0,$inout2
+	aesdec		$rndkey0,$inout3
+	$movkey		64($key_),$rndkey0
+	jmp		.Locb_dec_loop4
+
+.align	32
+.Locb_dec_loop4:
+	aesdec		$rndkey1,$inout0
+	aesdec		$rndkey1,$inout1
+	aesdec		$rndkey1,$inout2
+	aesdec		$rndkey1,$inout3
+	$movkey		($key,%rax),$rndkey1
+	add		\$32,%rax
+
+	aesdec		$rndkey0,$inout0
+	aesdec		$rndkey0,$inout1
+	aesdec		$rndkey0,$inout2
+	aesdec		$rndkey0,$inout3
+	$movkey		-16($key,%rax),$rndkey0
+	jnz		.Locb_dec_loop4
+
+	aesdec		$rndkey1,$inout0
+	aesdec		$rndkey1,$inout1
+	aesdec		$rndkey1,$inout2
+	aesdec		$rndkey1,$inout3
+	$movkey		16($key_),$rndkey1
+	mov		%r10,%rax		# restore twisted rounds
+
+	aesdeclast	@offset[0],$inout0
+	aesdeclast	@offset[1],$inout1
+	aesdeclast	@offset[2],$inout2
+	aesdeclast	@offset[3],$inout3
+	ret
+.size	__ocb_decrypt4,.-__ocb_decrypt4
+
+.type	__ocb_decrypt1,\@abi-omnipotent
+.align	32
+__ocb_decrypt1:
+	 pxor		@offset[5],$inout5	# offset_i
+	 pxor		$rndkey0l,$inout5	# offset_i ^ round[0]
+	pxor		$inout5,$inout0		# input ^ round[0] ^ offset_i
+	$movkey		32($key_),$rndkey0
+
+	aesdec		$rndkey1,$inout0
+	$movkey		48($key_),$rndkey1
+	pxor		$rndkey0l,$inout5	# offset_i ^ round[last]
+
+	aesdec		$rndkey0,$inout0
+	$movkey		64($key_),$rndkey0
+	jmp		.Locb_dec_loop1
+
+.align	32
+.Locb_dec_loop1:
+	aesdec		$rndkey1,$inout0
+	$movkey		($key,%rax),$rndkey1
+	add		\$32,%rax
+
+	aesdec		$rndkey0,$inout0
+	$movkey		-16($key,%rax),$rndkey0
+	jnz		.Locb_dec_loop1
+
+	aesdec		$rndkey1,$inout0
+	$movkey		16($key_),$rndkey1	# redundant in tail
+	mov		%r10,%rax		# restore twisted rounds
+
+	aesdeclast	$inout5,$inout0
+	ret
+.size	__ocb_decrypt1,.-__ocb_decrypt1
+___
 } }}
 
 ########################################################################
@@ -2717,7 +3650,6 @@
 {
 my $frame_size = 0x10 + ($win64?0xa0:0);	# used in decrypt
 my ($iv,$in0,$in1,$in2,$in3,$in4)=map("%xmm$_",(10..15));
-my $inp_=$key_;
 
 $code.=<<___;
 .globl	${PREFIX}_cbc_encrypt
@@ -2799,7 +3731,7 @@
 	jmp	.Lcbc_ret
 .align	16
 .Lcbc_decrypt_bulk:
-	lea	(%rsp),%rax
+	lea	(%rsp),%r11		# frame pointer
 	push	%rbp
 	sub	\$$frame_size,%rsp
 	and	\$-16,%rsp	# Linux kernel stack can be incorrectly seeded
@@ -2817,8 +3749,11 @@
 	movaps	%xmm15,0xa0(%rsp)
 .Lcbc_decrypt_body:
 ___
+
+my $inp_=$key_="%rbp";			# reassign $key_
+
 $code.=<<___;
-	lea	-8(%rax),%rbp
+	mov	$key,$key_		# [re-]backup $key [after reassignment]
 	movups	($ivp),$iv
 	mov	$rnds_,$rounds
 	cmp	\$0x50,$len
@@ -2858,7 +3793,7 @@
 	pxor		$rndkey0,$inout1
 	$movkey		0x10-0x70($key),$rndkey1
 	pxor		$rndkey0,$inout2
-	xor		$inp_,$inp_
+	mov		\$-1,$inp_
 	cmp		\$0x70,$len	# is there at least 0x60 bytes ahead?
 	pxor		$rndkey0,$inout3
 	pxor		$rndkey0,$inout4
@@ -2874,8 +3809,8 @@
 	aesdec		$rndkey1,$inout4
 	aesdec		$rndkey1,$inout5
 	aesdec		$rndkey1,$inout6
-	setnc		${inp_}b
-	shl		\$7,$inp_
+	adc		\$0,$inp_
+	and		\$128,$inp_
 	aesdec		$rndkey1,$inout7
 	add		$inp,$inp_
 	$movkey		0x30-0x70($key),$rndkey1
@@ -3239,8 +4174,8 @@
 	movaps	%xmm0,0xa0(%rsp)
 ___
 $code.=<<___;
-	lea	(%rbp),%rsp
-	pop	%rbp
+	mov	-8(%r11),%rbp
+	lea	(%r11),%rsp
 .Lcbc_ret:
 	ret
 .size	${PREFIX}_cbc_encrypt,.-${PREFIX}_cbc_encrypt
@@ -3307,7 +4242,7 @@
 #	Vinodh Gopal <vinodh.gopal@intel.com>
 #	Kahraman Akdemir
 #
-# Agressively optimized in respect to aeskeygenassist's critical path
+# Aggressively optimized in respect to aeskeygenassist's critical path
 # and is contained in %xmm0-5 to meet Win64 ABI requirement.
 #
 # int ${PREFIX}_set_encrypt_key(const unsigned char *inp,
@@ -3811,14 +4746,76 @@
 	cmp	%r10,%rbx		# context->Rip>=epilogue label
 	jae	.Lcommon_seh_tail
 
-	mov	160($context),%rax	# pull context->Rbp
-	lea	-0xa0(%rax),%rsi	# %xmm save area
+	mov	208($context),%rax	# pull context->R11
+
+	lea	-0xa8(%rax),%rsi	# %xmm save area
 	lea	512($context),%rdi	# & context.Xmm6
 	mov	\$20,%ecx		# 10*sizeof(%xmm0)/sizeof(%rax)
 	.long	0xa548f3fc		# cld; rep movsq
 
-	jmp	.Lcommon_rbp_tail
+	mov	-8(%rax),%rbp		# restore saved %rbp
+	mov	%rbp,160($context)	# restore context->Rbp
+	jmp	.Lcommon_seh_tail
 .size	ctr_xts_se_handler,.-ctr_xts_se_handler
+
+.type	ocb_se_handler,\@abi-omnipotent
+.align	16
+ocb_se_handler:
+	push	%rsi
+	push	%rdi
+	push	%rbx
+	push	%rbp
+	push	%r12
+	push	%r13
+	push	%r14
+	push	%r15
+	pushfq
+	sub	\$64,%rsp
+
+	mov	120($context),%rax	# pull context->Rax
+	mov	248($context),%rbx	# pull context->Rip
+
+	mov	8($disp),%rsi		# disp->ImageBase
+	mov	56($disp),%r11		# disp->HandlerData
+
+	mov	0(%r11),%r10d		# HandlerData[0]
+	lea	(%rsi,%r10),%r10	# prologue lable
+	cmp	%r10,%rbx		# context->Rip<prologue label
+	jb	.Lcommon_seh_tail
+
+	mov	4(%r11),%r10d		# HandlerData[1]
+	lea	(%rsi,%r10),%r10	# epilogue label
+	cmp	%r10,%rbx		# context->Rip>=epilogue label
+	jae	.Lcommon_seh_tail
+
+	mov	8(%r11),%r10d		# HandlerData[2]
+	lea	(%rsi,%r10),%r10
+	cmp	%r10,%rbx		# context->Rip>=pop label
+	jae	.Locb_no_xmm
+
+	mov	152($context),%rax	# pull context->Rsp
+
+	lea	(%rax),%rsi		# %xmm save area
+	lea	512($context),%rdi	# & context.Xmm6
+	mov	\$20,%ecx		# 10*sizeof(%xmm0)/sizeof(%rax)
+	.long	0xa548f3fc		# cld; rep movsq
+	lea	0xa0+0x28(%rax),%rax
+
+.Locb_no_xmm:
+	mov	-8(%rax),%rbx
+	mov	-16(%rax),%rbp
+	mov	-24(%rax),%r12
+	mov	-32(%rax),%r13
+	mov	-40(%rax),%r14
+
+	mov	%rbx,144($context)	# restore context->Rbx
+	mov	%rbp,160($context)	# restore context->Rbp
+	mov	%r12,216($context)	# restore context->R12
+	mov	%r13,224($context)	# restore context->R13
+	mov	%r14,232($context)	# restore context->R14
+
+	jmp	.Lcommon_seh_tail
+.size	ocb_se_handler,.-ocb_se_handler
 ___
 $code.=<<___;
 .type	cbc_se_handler,\@abi-omnipotent
@@ -3842,9 +4839,13 @@
 	cmp	%r10,%rbx		# context->Rip<"prologue" label
 	jb	.Lcommon_seh_tail
 
+	mov	120($context),%rax	# pull context->Rax
+
 	lea	.Lcbc_decrypt_body(%rip),%r10
 	cmp	%r10,%rbx		# context->Rip<cbc_decrypt_body
-	jb	.Lrestore_cbc_rax
+	jb	.Lcommon_seh_tail
+
+	mov	152($context),%rax	# pull context->Rsp
 
 	lea	.Lcbc_ret(%rip),%r10
 	cmp	%r10,%rbx		# context->Rip>="epilogue" label
@@ -3855,15 +4856,10 @@
 	mov	\$20,%ecx		# 10*sizeof(%xmm0)/sizeof(%rax)
 	.long	0xa548f3fc		# cld; rep movsq
 
-.Lcommon_rbp_tail:
-	mov	160($context),%rax	# pull context->Rbp
-	mov	(%rax),%rbp		# restore saved %rbp
-	lea	8(%rax),%rax		# adjust stack pointer
-	mov	%rbp,160($context)	# restore context->Rbp
-	jmp	.Lcommon_seh_tail
+	mov	208($context),%rax	# pull context->R11
 
-.Lrestore_cbc_rax:
-	mov	120($context),%rax
+	mov	-8(%rax),%rbp		# restore saved %rbp
+	mov	%rbp,160($context)	# restore context->Rbp
 
 .Lcommon_seh_tail:
 	mov	8(%rax),%rdi
@@ -3932,6 +4928,14 @@
 	.rva	.LSEH_begin_aesni_xts_decrypt
 	.rva	.LSEH_end_aesni_xts_decrypt
 	.rva	.LSEH_info_xts_dec
+
+	.rva	.LSEH_begin_aesni_ocb_encrypt
+	.rva	.LSEH_end_aesni_ocb_encrypt
+	.rva	.LSEH_info_ocb_enc
+
+	.rva	.LSEH_begin_aesni_ocb_decrypt
+	.rva	.LSEH_end_aesni_ocb_decrypt
+	.rva	.LSEH_info_ocb_dec
 ___
 $code.=<<___;
 	.rva	.LSEH_begin_${PREFIX}_cbc_encrypt
@@ -3973,6 +4977,18 @@
 	.byte	9,0,0,0
 	.rva	ctr_xts_se_handler
 	.rva	.Lxts_dec_body,.Lxts_dec_epilogue	# HandlerData[]
+.LSEH_info_ocb_enc:
+	.byte	9,0,0,0
+	.rva	ocb_se_handler
+	.rva	.Locb_enc_body,.Locb_enc_epilogue	# HandlerData[]
+	.rva	.Locb_enc_pop
+	.long	0
+.LSEH_info_ocb_dec:
+	.byte	9,0,0,0
+	.rva	ocb_se_handler
+	.rva	.Locb_dec_body,.Locb_dec_epilogue	# HandlerData[]
+	.rva	.Locb_dec_pop
+	.long	0
 ___
 $code.=<<___;
 .LSEH_info_cbc:
diff --git a/src/crypto/aes/asm/aesp8-ppc.pl b/src/crypto/aes/asm/aesp8-ppc.pl
new file mode 100644
index 0000000..ca3a150
--- /dev/null
+++ b/src/crypto/aes/asm/aesp8-ppc.pl
@@ -0,0 +1,3805 @@
+#! /usr/bin/env perl
+# Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the OpenSSL license (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# This module implements support for AES instructions as per PowerISA
+# specification version 2.07, first implemented by POWER8 processor.
+# The module is endian-agnostic in sense that it supports both big-
+# and little-endian cases. Data alignment in parallelizable modes is
+# handled with VSX loads and stores, which implies MSR.VSX flag being
+# set. It should also be noted that ISA specification doesn't prohibit
+# alignment exceptions for these instructions on page boundaries.
+# Initially alignment was handled in pure AltiVec/VMX way [when data
+# is aligned programmatically, which in turn guarantees exception-
+# free execution], but it turned to hamper performance when vcipher
+# instructions are interleaved. It's reckoned that eventual
+# misalignment penalties at page boundaries are in average lower
+# than additional overhead in pure AltiVec approach.
+#
+# May 2016
+#
+# Add XTS subroutine, 9x on little- and 12x improvement on big-endian
+# systems were measured.
+#
+######################################################################
+# Current large-block performance in cycles per byte processed with
+# 128-bit key (less is better).
+#
+#		CBC en-/decrypt	CTR	XTS
+# POWER8[le]	3.96/0.72	0.74	1.1
+# POWER8[be]	3.75/0.65	0.66	1.0
+
+$flavour = shift;
+
+if ($flavour =~ /64/) {
+	$SIZE_T	=8;
+	$LRSAVE	=2*$SIZE_T;
+	$STU	="stdu";
+	$POP	="ld";
+	$PUSH	="std";
+	$UCMP	="cmpld";
+	$SHL	="sldi";
+} elsif ($flavour =~ /32/) {
+	$SIZE_T	=4;
+	$LRSAVE	=$SIZE_T;
+	$STU	="stwu";
+	$POP	="lwz";
+	$PUSH	="stw";
+	$UCMP	="cmplw";
+	$SHL	="slwi";
+} else { die "nonsense $flavour"; }
+
+$LITTLE_ENDIAN = ($flavour=~/le$/) ? $SIZE_T : 0;
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
+die "can't locate ppc-xlate.pl";
+
+open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!";
+
+$FRAME=8*$SIZE_T;
+$prefix="aes_hw";
+
+$sp="r1";
+$vrsave="r12";
+
+#########################################################################
+{{{	# Key setup procedures						#
+my ($inp,$bits,$out,$ptr,$cnt,$rounds)=map("r$_",(3..8));
+my ($zero,$in0,$in1,$key,$rcon,$mask,$tmp)=map("v$_",(0..6));
+my ($stage,$outperm,$outmask,$outhead,$outtail)=map("v$_",(7..11));
+
+$code.=<<___;
+.machine	"any"
+
+.text
+
+.align	7
+rcon:
+.long	0x01000000, 0x01000000, 0x01000000, 0x01000000	?rev
+.long	0x1b000000, 0x1b000000, 0x1b000000, 0x1b000000	?rev
+.long	0x0d0e0f0c, 0x0d0e0f0c, 0x0d0e0f0c, 0x0d0e0f0c	?rev
+.long	0,0,0,0						?asis
+Lconsts:
+	mflr	r0
+	bcl	20,31,\$+4
+	mflr	$ptr	 #vvvvv "distance between . and rcon
+	addi	$ptr,$ptr,-0x48
+	mtlr	r0
+	blr
+	.long	0
+	.byte	0,12,0x14,0,0,0,0,0
+.asciz	"AES for PowerISA 2.07, CRYPTOGAMS by <appro\@openssl.org>"
+
+.globl	.${prefix}_set_encrypt_key
+.align	5
+.${prefix}_set_encrypt_key:
+Lset_encrypt_key:
+	mflr		r11
+	$PUSH		r11,$LRSAVE($sp)
+
+	li		$ptr,-1
+	${UCMP}i	$inp,0
+	beq-		Lenc_key_abort		# if ($inp==0) return -1;
+	${UCMP}i	$out,0
+	beq-		Lenc_key_abort		# if ($out==0) return -1;
+	li		$ptr,-2
+	cmpwi		$bits,128
+	blt-		Lenc_key_abort
+	cmpwi		$bits,256
+	bgt-		Lenc_key_abort
+	andi.		r0,$bits,0x3f
+	bne-		Lenc_key_abort
+
+	lis		r0,0xfff0
+	mfspr		$vrsave,256
+	mtspr		256,r0
+
+	bl		Lconsts
+	mtlr		r11
+
+	neg		r9,$inp
+	lvx		$in0,0,$inp
+	addi		$inp,$inp,15		# 15 is not typo
+	lvsr		$key,0,r9		# borrow $key
+	li		r8,0x20
+	cmpwi		$bits,192
+	lvx		$in1,0,$inp
+	le?vspltisb	$mask,0x0f		# borrow $mask
+	lvx		$rcon,0,$ptr
+	le?vxor		$key,$key,$mask		# adjust for byte swap
+	lvx		$mask,r8,$ptr
+	addi		$ptr,$ptr,0x10
+	vperm		$in0,$in0,$in1,$key	# align [and byte swap in LE]
+	li		$cnt,8
+	vxor		$zero,$zero,$zero
+	mtctr		$cnt
+
+	?lvsr		$outperm,0,$out
+	vspltisb	$outmask,-1
+	lvx		$outhead,0,$out
+	?vperm		$outmask,$zero,$outmask,$outperm
+
+	blt		Loop128
+	addi		$inp,$inp,8
+	beq		L192
+	addi		$inp,$inp,8
+	b		L256
+
+.align	4
+Loop128:
+	vperm		$key,$in0,$in0,$mask	# rotate-n-splat
+	vsldoi		$tmp,$zero,$in0,12	# >>32
+	 vperm		$outtail,$in0,$in0,$outperm	# rotate
+	 vsel		$stage,$outhead,$outtail,$outmask
+	 vmr		$outhead,$outtail
+	vcipherlast	$key,$key,$rcon
+	 stvx		$stage,0,$out
+	 addi		$out,$out,16
+
+	vxor		$in0,$in0,$tmp
+	vsldoi		$tmp,$zero,$tmp,12	# >>32
+	vxor		$in0,$in0,$tmp
+	vsldoi		$tmp,$zero,$tmp,12	# >>32
+	vxor		$in0,$in0,$tmp
+	 vadduwm	$rcon,$rcon,$rcon
+	vxor		$in0,$in0,$key
+	bdnz		Loop128
+
+	lvx		$rcon,0,$ptr		# last two round keys
+
+	vperm		$key,$in0,$in0,$mask	# rotate-n-splat
+	vsldoi		$tmp,$zero,$in0,12	# >>32
+	 vperm		$outtail,$in0,$in0,$outperm	# rotate
+	 vsel		$stage,$outhead,$outtail,$outmask
+	 vmr		$outhead,$outtail
+	vcipherlast	$key,$key,$rcon
+	 stvx		$stage,0,$out
+	 addi		$out,$out,16
+
+	vxor		$in0,$in0,$tmp
+	vsldoi		$tmp,$zero,$tmp,12	# >>32
+	vxor		$in0,$in0,$tmp
+	vsldoi		$tmp,$zero,$tmp,12	# >>32
+	vxor		$in0,$in0,$tmp
+	 vadduwm	$rcon,$rcon,$rcon
+	vxor		$in0,$in0,$key
+
+	vperm		$key,$in0,$in0,$mask	# rotate-n-splat
+	vsldoi		$tmp,$zero,$in0,12	# >>32
+	 vperm		$outtail,$in0,$in0,$outperm	# rotate
+	 vsel		$stage,$outhead,$outtail,$outmask
+	 vmr		$outhead,$outtail
+	vcipherlast	$key,$key,$rcon
+	 stvx		$stage,0,$out
+	 addi		$out,$out,16
+
+	vxor		$in0,$in0,$tmp
+	vsldoi		$tmp,$zero,$tmp,12	# >>32
+	vxor		$in0,$in0,$tmp
+	vsldoi		$tmp,$zero,$tmp,12	# >>32
+	vxor		$in0,$in0,$tmp
+	vxor		$in0,$in0,$key
+	 vperm		$outtail,$in0,$in0,$outperm	# rotate
+	 vsel		$stage,$outhead,$outtail,$outmask
+	 vmr		$outhead,$outtail
+	 stvx		$stage,0,$out
+
+	addi		$inp,$out,15		# 15 is not typo
+	addi		$out,$out,0x50
+
+	li		$rounds,10
+	b		Ldone
+
+.align	4
+L192:
+	lvx		$tmp,0,$inp
+	li		$cnt,4
+	 vperm		$outtail,$in0,$in0,$outperm	# rotate
+	 vsel		$stage,$outhead,$outtail,$outmask
+	 vmr		$outhead,$outtail
+	 stvx		$stage,0,$out
+	 addi		$out,$out,16
+	vperm		$in1,$in1,$tmp,$key	# align [and byte swap in LE]
+	vspltisb	$key,8			# borrow $key
+	mtctr		$cnt
+	vsububm		$mask,$mask,$key	# adjust the mask
+
+Loop192:
+	vperm		$key,$in1,$in1,$mask	# roate-n-splat
+	vsldoi		$tmp,$zero,$in0,12	# >>32
+	vcipherlast	$key,$key,$rcon
+
+	vxor		$in0,$in0,$tmp
+	vsldoi		$tmp,$zero,$tmp,12	# >>32
+	vxor		$in0,$in0,$tmp
+	vsldoi		$tmp,$zero,$tmp,12	# >>32
+	vxor		$in0,$in0,$tmp
+
+	 vsldoi		$stage,$zero,$in1,8
+	vspltw		$tmp,$in0,3
+	vxor		$tmp,$tmp,$in1
+	vsldoi		$in1,$zero,$in1,12	# >>32
+	 vadduwm	$rcon,$rcon,$rcon
+	vxor		$in1,$in1,$tmp
+	vxor		$in0,$in0,$key
+	vxor		$in1,$in1,$key
+	 vsldoi		$stage,$stage,$in0,8
+
+	vperm		$key,$in1,$in1,$mask	# rotate-n-splat
+	vsldoi		$tmp,$zero,$in0,12	# >>32
+	 vperm		$outtail,$stage,$stage,$outperm	# rotate
+	 vsel		$stage,$outhead,$outtail,$outmask
+	 vmr		$outhead,$outtail
+	vcipherlast	$key,$key,$rcon
+	 stvx		$stage,0,$out
+	 addi		$out,$out,16
+
+	 vsldoi		$stage,$in0,$in1,8
+	vxor		$in0,$in0,$tmp
+	vsldoi		$tmp,$zero,$tmp,12	# >>32
+	 vperm		$outtail,$stage,$stage,$outperm	# rotate
+	 vsel		$stage,$outhead,$outtail,$outmask
+	 vmr		$outhead,$outtail
+	vxor		$in0,$in0,$tmp
+	vsldoi		$tmp,$zero,$tmp,12	# >>32
+	vxor		$in0,$in0,$tmp
+	 stvx		$stage,0,$out
+	 addi		$out,$out,16
+
+	vspltw		$tmp,$in0,3
+	vxor		$tmp,$tmp,$in1
+	vsldoi		$in1,$zero,$in1,12	# >>32
+	 vadduwm	$rcon,$rcon,$rcon
+	vxor		$in1,$in1,$tmp
+	vxor		$in0,$in0,$key
+	vxor		$in1,$in1,$key
+	 vperm		$outtail,$in0,$in0,$outperm	# rotate
+	 vsel		$stage,$outhead,$outtail,$outmask
+	 vmr		$outhead,$outtail
+	 stvx		$stage,0,$out
+	 addi		$inp,$out,15		# 15 is not typo
+	 addi		$out,$out,16
+	bdnz		Loop192
+
+	li		$rounds,12
+	addi		$out,$out,0x20
+	b		Ldone
+
+.align	4
+L256:
+	lvx		$tmp,0,$inp
+	li		$cnt,7
+	li		$rounds,14
+	 vperm		$outtail,$in0,$in0,$outperm	# rotate
+	 vsel		$stage,$outhead,$outtail,$outmask
+	 vmr		$outhead,$outtail
+	 stvx		$stage,0,$out
+	 addi		$out,$out,16
+	vperm		$in1,$in1,$tmp,$key	# align [and byte swap in LE]
+	mtctr		$cnt
+
+Loop256:
+	vperm		$key,$in1,$in1,$mask	# rotate-n-splat
+	vsldoi		$tmp,$zero,$in0,12	# >>32
+	 vperm		$outtail,$in1,$in1,$outperm	# rotate
+	 vsel		$stage,$outhead,$outtail,$outmask
+	 vmr		$outhead,$outtail
+	vcipherlast	$key,$key,$rcon
+	 stvx		$stage,0,$out
+	 addi		$out,$out,16
+
+	vxor		$in0,$in0,$tmp
+	vsldoi		$tmp,$zero,$tmp,12	# >>32
+	vxor		$in0,$in0,$tmp
+	vsldoi		$tmp,$zero,$tmp,12	# >>32
+	vxor		$in0,$in0,$tmp
+	 vadduwm	$rcon,$rcon,$rcon
+	vxor		$in0,$in0,$key
+	 vperm		$outtail,$in0,$in0,$outperm	# rotate
+	 vsel		$stage,$outhead,$outtail,$outmask
+	 vmr		$outhead,$outtail
+	 stvx		$stage,0,$out
+	 addi		$inp,$out,15		# 15 is not typo
+	 addi		$out,$out,16
+	bdz		Ldone
+
+	vspltw		$key,$in0,3		# just splat
+	vsldoi		$tmp,$zero,$in1,12	# >>32
+	vsbox		$key,$key
+
+	vxor		$in1,$in1,$tmp
+	vsldoi		$tmp,$zero,$tmp,12	# >>32
+	vxor		$in1,$in1,$tmp
+	vsldoi		$tmp,$zero,$tmp,12	# >>32
+	vxor		$in1,$in1,$tmp
+
+	vxor		$in1,$in1,$key
+	b		Loop256
+
+.align	4
+Ldone:
+	lvx		$in1,0,$inp		# redundant in aligned case
+	vsel		$in1,$outhead,$in1,$outmask
+	stvx		$in1,0,$inp
+	li		$ptr,0
+	mtspr		256,$vrsave
+	stw		$rounds,0($out)
+
+Lenc_key_abort:
+	mr		r3,$ptr
+	blr
+	.long		0
+	.byte		0,12,0x14,1,0,0,3,0
+	.long		0
+.size	.${prefix}_set_encrypt_key,.-.${prefix}_set_encrypt_key
+
+.globl	.${prefix}_set_decrypt_key
+.align	5
+.${prefix}_set_decrypt_key:
+	$STU		$sp,-$FRAME($sp)
+	mflr		r10
+	$PUSH		r10,$FRAME+$LRSAVE($sp)
+	bl		Lset_encrypt_key
+	mtlr		r10
+
+	cmpwi		r3,0
+	bne-		Ldec_key_abort
+
+	slwi		$cnt,$rounds,4
+	subi		$inp,$out,240		# first round key
+	srwi		$rounds,$rounds,1
+	add		$out,$inp,$cnt		# last round key
+	mtctr		$rounds
+
+Ldeckey:
+	lwz		r0, 0($inp)
+	lwz		r6, 4($inp)
+	lwz		r7, 8($inp)
+	lwz		r8, 12($inp)
+	addi		$inp,$inp,16
+	lwz		r9, 0($out)
+	lwz		r10,4($out)
+	lwz		r11,8($out)
+	lwz		r12,12($out)
+	stw		r0, 0($out)
+	stw		r6, 4($out)
+	stw		r7, 8($out)
+	stw		r8, 12($out)
+	subi		$out,$out,16
+	stw		r9, -16($inp)
+	stw		r10,-12($inp)
+	stw		r11,-8($inp)
+	stw		r12,-4($inp)
+	bdnz		Ldeckey
+
+	xor		r3,r3,r3		# return value
+Ldec_key_abort:
+	addi		$sp,$sp,$FRAME
+	blr
+	.long		0
+	.byte		0,12,4,1,0x80,0,3,0
+	.long		0
+.size	.${prefix}_set_decrypt_key,.-.${prefix}_set_decrypt_key
+___
+}}}
+#########################################################################
+{{{	# Single block en- and decrypt procedures			#
+sub gen_block () {
+my $dir = shift;
+my $n   = $dir eq "de" ? "n" : "";
+my ($inp,$out,$key,$rounds,$idx)=map("r$_",(3..7));
+
+$code.=<<___;
+.globl	.${prefix}_${dir}crypt
+.align	5
+.${prefix}_${dir}crypt:
+	lwz		$rounds,240($key)
+	lis		r0,0xfc00
+	mfspr		$vrsave,256
+	li		$idx,15			# 15 is not typo
+	mtspr		256,r0
+
+	lvx		v0,0,$inp
+	neg		r11,$out
+	lvx		v1,$idx,$inp
+	lvsl		v2,0,$inp		# inpperm
+	le?vspltisb	v4,0x0f
+	?lvsl		v3,0,r11		# outperm
+	le?vxor		v2,v2,v4
+	li		$idx,16
+	vperm		v0,v0,v1,v2		# align [and byte swap in LE]
+	lvx		v1,0,$key
+	?lvsl		v5,0,$key		# keyperm
+	srwi		$rounds,$rounds,1
+	lvx		v2,$idx,$key
+	addi		$idx,$idx,16
+	subi		$rounds,$rounds,1
+	?vperm		v1,v1,v2,v5		# align round key
+
+	vxor		v0,v0,v1
+	lvx		v1,$idx,$key
+	addi		$idx,$idx,16
+	mtctr		$rounds
+
+Loop_${dir}c:
+	?vperm		v2,v2,v1,v5
+	v${n}cipher	v0,v0,v2
+	lvx		v2,$idx,$key
+	addi		$idx,$idx,16
+	?vperm		v1,v1,v2,v5
+	v${n}cipher	v0,v0,v1
+	lvx		v1,$idx,$key
+	addi		$idx,$idx,16
+	bdnz		Loop_${dir}c
+
+	?vperm		v2,v2,v1,v5
+	v${n}cipher	v0,v0,v2
+	lvx		v2,$idx,$key
+	?vperm		v1,v1,v2,v5
+	v${n}cipherlast	v0,v0,v1
+
+	vspltisb	v2,-1
+	vxor		v1,v1,v1
+	li		$idx,15			# 15 is not typo
+	?vperm		v2,v1,v2,v3		# outmask
+	le?vxor		v3,v3,v4
+	lvx		v1,0,$out		# outhead
+	vperm		v0,v0,v0,v3		# rotate [and byte swap in LE]
+	vsel		v1,v1,v0,v2
+	lvx		v4,$idx,$out
+	stvx		v1,0,$out
+	vsel		v0,v0,v4,v2
+	stvx		v0,$idx,$out
+
+	mtspr		256,$vrsave
+	blr
+	.long		0
+	.byte		0,12,0x14,0,0,0,3,0
+	.long		0
+.size	.${prefix}_${dir}crypt,.-.${prefix}_${dir}crypt
+___
+}
+&gen_block("en");
+&gen_block("de");
+}}}
+#########################################################################
+{{{	# CBC en- and decrypt procedures				#
+my ($inp,$out,$len,$key,$ivp,$enc,$rounds,$idx)=map("r$_",(3..10));
+my ($rndkey0,$rndkey1,$inout,$tmp)=		map("v$_",(0..3));
+my ($ivec,$inptail,$inpperm,$outhead,$outperm,$outmask,$keyperm)=
+						map("v$_",(4..10));
+$code.=<<___;
+.globl	.${prefix}_cbc_encrypt
+.align	5
+.${prefix}_cbc_encrypt:
+	${UCMP}i	$len,16
+	bltlr-
+
+	cmpwi		$enc,0			# test direction
+	lis		r0,0xffe0
+	mfspr		$vrsave,256
+	mtspr		256,r0
+
+	li		$idx,15
+	vxor		$rndkey0,$rndkey0,$rndkey0
+	le?vspltisb	$tmp,0x0f
+
+	lvx		$ivec,0,$ivp		# load [unaligned] iv
+	lvsl		$inpperm,0,$ivp
+	lvx		$inptail,$idx,$ivp
+	le?vxor		$inpperm,$inpperm,$tmp
+	vperm		$ivec,$ivec,$inptail,$inpperm
+
+	neg		r11,$inp
+	?lvsl		$keyperm,0,$key		# prepare for unaligned key
+	lwz		$rounds,240($key)
+
+	lvsr		$inpperm,0,r11		# prepare for unaligned load
+	lvx		$inptail,0,$inp
+	addi		$inp,$inp,15		# 15 is not typo
+	le?vxor		$inpperm,$inpperm,$tmp
+
+	?lvsr		$outperm,0,$out		# prepare for unaligned store
+	vspltisb	$outmask,-1
+	lvx		$outhead,0,$out
+	?vperm		$outmask,$rndkey0,$outmask,$outperm
+	le?vxor		$outperm,$outperm,$tmp
+
+	srwi		$rounds,$rounds,1
+	li		$idx,16
+	subi		$rounds,$rounds,1
+	beq		Lcbc_dec
+
+Lcbc_enc:
+	vmr		$inout,$inptail
+	lvx		$inptail,0,$inp
+	addi		$inp,$inp,16
+	mtctr		$rounds
+	subi		$len,$len,16		# len-=16
+
+	lvx		$rndkey0,0,$key
+	 vperm		$inout,$inout,$inptail,$inpperm
+	lvx		$rndkey1,$idx,$key
+	addi		$idx,$idx,16
+	?vperm		$rndkey0,$rndkey0,$rndkey1,$keyperm
+	vxor		$inout,$inout,$rndkey0
+	lvx		$rndkey0,$idx,$key
+	addi		$idx,$idx,16
+	vxor		$inout,$inout,$ivec
+
+Loop_cbc_enc:
+	?vperm		$rndkey1,$rndkey1,$rndkey0,$keyperm
+	vcipher		$inout,$inout,$rndkey1
+	lvx		$rndkey1,$idx,$key
+	addi		$idx,$idx,16
+	?vperm		$rndkey0,$rndkey0,$rndkey1,$keyperm
+	vcipher		$inout,$inout,$rndkey0
+	lvx		$rndkey0,$idx,$key
+	addi		$idx,$idx,16
+	bdnz		Loop_cbc_enc
+
+	?vperm		$rndkey1,$rndkey1,$rndkey0,$keyperm
+	vcipher		$inout,$inout,$rndkey1
+	lvx		$rndkey1,$idx,$key
+	li		$idx,16
+	?vperm		$rndkey0,$rndkey0,$rndkey1,$keyperm
+	vcipherlast	$ivec,$inout,$rndkey0
+	${UCMP}i	$len,16
+
+	vperm		$tmp,$ivec,$ivec,$outperm
+	vsel		$inout,$outhead,$tmp,$outmask
+	vmr		$outhead,$tmp
+	stvx		$inout,0,$out
+	addi		$out,$out,16
+	bge		Lcbc_enc
+
+	b		Lcbc_done
+
+.align	4
+Lcbc_dec:
+	${UCMP}i	$len,128
+	bge		_aesp8_cbc_decrypt8x
+	vmr		$tmp,$inptail
+	lvx		$inptail,0,$inp
+	addi		$inp,$inp,16
+	mtctr		$rounds
+	subi		$len,$len,16		# len-=16
+
+	lvx		$rndkey0,0,$key
+	 vperm		$tmp,$tmp,$inptail,$inpperm
+	lvx		$rndkey1,$idx,$key
+	addi		$idx,$idx,16
+	?vperm		$rndkey0,$rndkey0,$rndkey1,$keyperm
+	vxor		$inout,$tmp,$rndkey0
+	lvx		$rndkey0,$idx,$key
+	addi		$idx,$idx,16
+
+Loop_cbc_dec:
+	?vperm		$rndkey1,$rndkey1,$rndkey0,$keyperm
+	vncipher	$inout,$inout,$rndkey1
+	lvx		$rndkey1,$idx,$key
+	addi		$idx,$idx,16
+	?vperm		$rndkey0,$rndkey0,$rndkey1,$keyperm
+	vncipher	$inout,$inout,$rndkey0
+	lvx		$rndkey0,$idx,$key
+	addi		$idx,$idx,16
+	bdnz		Loop_cbc_dec
+
+	?vperm		$rndkey1,$rndkey1,$rndkey0,$keyperm
+	vncipher	$inout,$inout,$rndkey1
+	lvx		$rndkey1,$idx,$key
+	li		$idx,16
+	?vperm		$rndkey0,$rndkey0,$rndkey1,$keyperm
+	vncipherlast	$inout,$inout,$rndkey0
+	${UCMP}i	$len,16
+
+	vxor		$inout,$inout,$ivec
+	vmr		$ivec,$tmp
+	vperm		$tmp,$inout,$inout,$outperm
+	vsel		$inout,$outhead,$tmp,$outmask
+	vmr		$outhead,$tmp
+	stvx		$inout,0,$out
+	addi		$out,$out,16
+	bge		Lcbc_dec
+
+Lcbc_done:
+	addi		$out,$out,-1
+	lvx		$inout,0,$out		# redundant in aligned case
+	vsel		$inout,$outhead,$inout,$outmask
+	stvx		$inout,0,$out
+
+	neg		$enc,$ivp		# write [unaligned] iv
+	li		$idx,15			# 15 is not typo
+	vxor		$rndkey0,$rndkey0,$rndkey0
+	vspltisb	$outmask,-1
+	le?vspltisb	$tmp,0x0f
+	?lvsl		$outperm,0,$enc
+	?vperm		$outmask,$rndkey0,$outmask,$outperm
+	le?vxor		$outperm,$outperm,$tmp
+	lvx		$outhead,0,$ivp
+	vperm		$ivec,$ivec,$ivec,$outperm
+	vsel		$inout,$outhead,$ivec,$outmask
+	lvx		$inptail,$idx,$ivp
+	stvx		$inout,0,$ivp
+	vsel		$inout,$ivec,$inptail,$outmask
+	stvx		$inout,$idx,$ivp
+
+	mtspr		256,$vrsave
+	blr
+	.long		0
+	.byte		0,12,0x14,0,0,0,6,0
+	.long		0
+___
+#########################################################################
+{{	# Optimized CBC decrypt procedure				#
+my $key_="r11";
+my ($x00,$x10,$x20,$x30,$x40,$x50,$x60,$x70)=map("r$_",(0,8,26..31));
+    $x00=0 if ($flavour =~ /osx/);
+my ($in0, $in1, $in2, $in3, $in4, $in5, $in6, $in7 )=map("v$_",(0..3,10..13));
+my ($out0,$out1,$out2,$out3,$out4,$out5,$out6,$out7)=map("v$_",(14..21));
+my $rndkey0="v23";	# v24-v25 rotating buffer for first found keys
+			# v26-v31 last 6 round keys
+my ($tmp,$keyperm)=($in3,$in4);	# aliases with "caller", redundant assignment
+
+$code.=<<___;
+.align	5
+_aesp8_cbc_decrypt8x:
+	$STU		$sp,-`($FRAME+21*16+6*$SIZE_T)`($sp)
+	li		r10,`$FRAME+8*16+15`
+	li		r11,`$FRAME+8*16+31`
+	stvx		v20,r10,$sp		# ABI says so
+	addi		r10,r10,32
+	stvx		v21,r11,$sp
+	addi		r11,r11,32
+	stvx		v22,r10,$sp
+	addi		r10,r10,32
+	stvx		v23,r11,$sp
+	addi		r11,r11,32
+	stvx		v24,r10,$sp
+	addi		r10,r10,32
+	stvx		v25,r11,$sp
+	addi		r11,r11,32
+	stvx		v26,r10,$sp
+	addi		r10,r10,32
+	stvx		v27,r11,$sp
+	addi		r11,r11,32
+	stvx		v28,r10,$sp
+	addi		r10,r10,32
+	stvx		v29,r11,$sp
+	addi		r11,r11,32
+	stvx		v30,r10,$sp
+	stvx		v31,r11,$sp
+	li		r0,-1
+	stw		$vrsave,`$FRAME+21*16-4`($sp)	# save vrsave
+	li		$x10,0x10
+	$PUSH		r26,`$FRAME+21*16+0*$SIZE_T`($sp)
+	li		$x20,0x20
+	$PUSH		r27,`$FRAME+21*16+1*$SIZE_T`($sp)
+	li		$x30,0x30
+	$PUSH		r28,`$FRAME+21*16+2*$SIZE_T`($sp)
+	li		$x40,0x40
+	$PUSH		r29,`$FRAME+21*16+3*$SIZE_T`($sp)
+	li		$x50,0x50
+	$PUSH		r30,`$FRAME+21*16+4*$SIZE_T`($sp)
+	li		$x60,0x60
+	$PUSH		r31,`$FRAME+21*16+5*$SIZE_T`($sp)
+	li		$x70,0x70
+	mtspr		256,r0
+
+	subi		$rounds,$rounds,3	# -4 in total
+	subi		$len,$len,128		# bias
+
+	lvx		$rndkey0,$x00,$key	# load key schedule
+	lvx		v30,$x10,$key
+	addi		$key,$key,0x20
+	lvx		v31,$x00,$key
+	?vperm		$rndkey0,$rndkey0,v30,$keyperm
+	addi		$key_,$sp,$FRAME+15
+	mtctr		$rounds
+
+Load_cbc_dec_key:
+	?vperm		v24,v30,v31,$keyperm
+	lvx		v30,$x10,$key
+	addi		$key,$key,0x20
+	stvx		v24,$x00,$key_		# off-load round[1]
+	?vperm		v25,v31,v30,$keyperm
+	lvx		v31,$x00,$key
+	stvx		v25,$x10,$key_		# off-load round[2]
+	addi		$key_,$key_,0x20
+	bdnz		Load_cbc_dec_key
+
+	lvx		v26,$x10,$key
+	?vperm		v24,v30,v31,$keyperm
+	lvx		v27,$x20,$key
+	stvx		v24,$x00,$key_		# off-load round[3]
+	?vperm		v25,v31,v26,$keyperm
+	lvx		v28,$x30,$key
+	stvx		v25,$x10,$key_		# off-load round[4]
+	addi		$key_,$sp,$FRAME+15	# rewind $key_
+	?vperm		v26,v26,v27,$keyperm
+	lvx		v29,$x40,$key
+	?vperm		v27,v27,v28,$keyperm
+	lvx		v30,$x50,$key
+	?vperm		v28,v28,v29,$keyperm
+	lvx		v31,$x60,$key
+	?vperm		v29,v29,v30,$keyperm
+	lvx		$out0,$x70,$key		# borrow $out0
+	?vperm		v30,v30,v31,$keyperm
+	lvx		v24,$x00,$key_		# pre-load round[1]
+	?vperm		v31,v31,$out0,$keyperm
+	lvx		v25,$x10,$key_		# pre-load round[2]
+
+	#lvx		$inptail,0,$inp		# "caller" already did this
+	#addi		$inp,$inp,15		# 15 is not typo
+	subi		$inp,$inp,15		# undo "caller"
+
+	 le?li		$idx,8
+	lvx_u		$in0,$x00,$inp		# load first 8 "words"
+	 le?lvsl	$inpperm,0,$idx
+	 le?vspltisb	$tmp,0x0f
+	lvx_u		$in1,$x10,$inp
+	 le?vxor	$inpperm,$inpperm,$tmp	# transform for lvx_u/stvx_u
+	lvx_u		$in2,$x20,$inp
+	 le?vperm	$in0,$in0,$in0,$inpperm
+	lvx_u		$in3,$x30,$inp
+	 le?vperm	$in1,$in1,$in1,$inpperm
+	lvx_u		$in4,$x40,$inp
+	 le?vperm	$in2,$in2,$in2,$inpperm
+	vxor		$out0,$in0,$rndkey0
+	lvx_u		$in5,$x50,$inp
+	 le?vperm	$in3,$in3,$in3,$inpperm
+	vxor		$out1,$in1,$rndkey0
+	lvx_u		$in6,$x60,$inp
+	 le?vperm	$in4,$in4,$in4,$inpperm
+	vxor		$out2,$in2,$rndkey0
+	lvx_u		$in7,$x70,$inp
+	addi		$inp,$inp,0x80
+	 le?vperm	$in5,$in5,$in5,$inpperm
+	vxor		$out3,$in3,$rndkey0
+	 le?vperm	$in6,$in6,$in6,$inpperm
+	vxor		$out4,$in4,$rndkey0
+	 le?vperm	$in7,$in7,$in7,$inpperm
+	vxor		$out5,$in5,$rndkey0
+	vxor		$out6,$in6,$rndkey0
+	vxor		$out7,$in7,$rndkey0
+
+	mtctr		$rounds
+	b		Loop_cbc_dec8x
+.align	5
+Loop_cbc_dec8x:
+	vncipher	$out0,$out0,v24
+	vncipher	$out1,$out1,v24
+	vncipher	$out2,$out2,v24
+	vncipher	$out3,$out3,v24
+	vncipher	$out4,$out4,v24
+	vncipher	$out5,$out5,v24
+	vncipher	$out6,$out6,v24
+	vncipher	$out7,$out7,v24
+	lvx		v24,$x20,$key_		# round[3]
+	addi		$key_,$key_,0x20
+
+	vncipher	$out0,$out0,v25
+	vncipher	$out1,$out1,v25
+	vncipher	$out2,$out2,v25
+	vncipher	$out3,$out3,v25
+	vncipher	$out4,$out4,v25
+	vncipher	$out5,$out5,v25
+	vncipher	$out6,$out6,v25
+	vncipher	$out7,$out7,v25
+	lvx		v25,$x10,$key_		# round[4]
+	bdnz		Loop_cbc_dec8x
+
+	subic		$len,$len,128		# $len-=128
+	vncipher	$out0,$out0,v24
+	vncipher	$out1,$out1,v24
+	vncipher	$out2,$out2,v24
+	vncipher	$out3,$out3,v24
+	vncipher	$out4,$out4,v24
+	vncipher	$out5,$out5,v24
+	vncipher	$out6,$out6,v24
+	vncipher	$out7,$out7,v24
+
+	subfe.		r0,r0,r0		# borrow?-1:0
+	vncipher	$out0,$out0,v25
+	vncipher	$out1,$out1,v25
+	vncipher	$out2,$out2,v25
+	vncipher	$out3,$out3,v25
+	vncipher	$out4,$out4,v25
+	vncipher	$out5,$out5,v25
+	vncipher	$out6,$out6,v25
+	vncipher	$out7,$out7,v25
+
+	and		r0,r0,$len
+	vncipher	$out0,$out0,v26
+	vncipher	$out1,$out1,v26
+	vncipher	$out2,$out2,v26
+	vncipher	$out3,$out3,v26
+	vncipher	$out4,$out4,v26
+	vncipher	$out5,$out5,v26
+	vncipher	$out6,$out6,v26
+	vncipher	$out7,$out7,v26
+
+	add		$inp,$inp,r0		# $inp is adjusted in such
+						# way that at exit from the
+						# loop inX-in7 are loaded
+						# with last "words"
+	vncipher	$out0,$out0,v27
+	vncipher	$out1,$out1,v27
+	vncipher	$out2,$out2,v27
+	vncipher	$out3,$out3,v27
+	vncipher	$out4,$out4,v27
+	vncipher	$out5,$out5,v27
+	vncipher	$out6,$out6,v27
+	vncipher	$out7,$out7,v27
+
+	addi		$key_,$sp,$FRAME+15	# rewind $key_
+	vncipher	$out0,$out0,v28
+	vncipher	$out1,$out1,v28
+	vncipher	$out2,$out2,v28
+	vncipher	$out3,$out3,v28
+	vncipher	$out4,$out4,v28
+	vncipher	$out5,$out5,v28
+	vncipher	$out6,$out6,v28
+	vncipher	$out7,$out7,v28
+	lvx		v24,$x00,$key_		# re-pre-load round[1]
+
+	vncipher	$out0,$out0,v29
+	vncipher	$out1,$out1,v29
+	vncipher	$out2,$out2,v29
+	vncipher	$out3,$out3,v29
+	vncipher	$out4,$out4,v29
+	vncipher	$out5,$out5,v29
+	vncipher	$out6,$out6,v29
+	vncipher	$out7,$out7,v29
+	lvx		v25,$x10,$key_		# re-pre-load round[2]
+
+	vncipher	$out0,$out0,v30
+	 vxor		$ivec,$ivec,v31		# xor with last round key
+	vncipher	$out1,$out1,v30
+	 vxor		$in0,$in0,v31
+	vncipher	$out2,$out2,v30
+	 vxor		$in1,$in1,v31
+	vncipher	$out3,$out3,v30
+	 vxor		$in2,$in2,v31
+	vncipher	$out4,$out4,v30
+	 vxor		$in3,$in3,v31
+	vncipher	$out5,$out5,v30
+	 vxor		$in4,$in4,v31
+	vncipher	$out6,$out6,v30
+	 vxor		$in5,$in5,v31
+	vncipher	$out7,$out7,v30
+	 vxor		$in6,$in6,v31
+
+	vncipherlast	$out0,$out0,$ivec
+	vncipherlast	$out1,$out1,$in0
+	 lvx_u		$in0,$x00,$inp		# load next input block
+	vncipherlast	$out2,$out2,$in1
+	 lvx_u		$in1,$x10,$inp
+	vncipherlast	$out3,$out3,$in2
+	 le?vperm	$in0,$in0,$in0,$inpperm
+	 lvx_u		$in2,$x20,$inp
+	vncipherlast	$out4,$out4,$in3
+	 le?vperm	$in1,$in1,$in1,$inpperm
+	 lvx_u		$in3,$x30,$inp
+	vncipherlast	$out5,$out5,$in4
+	 le?vperm	$in2,$in2,$in2,$inpperm
+	 lvx_u		$in4,$x40,$inp
+	vncipherlast	$out6,$out6,$in5
+	 le?vperm	$in3,$in3,$in3,$inpperm
+	 lvx_u		$in5,$x50,$inp
+	vncipherlast	$out7,$out7,$in6
+	 le?vperm	$in4,$in4,$in4,$inpperm
+	 lvx_u		$in6,$x60,$inp
+	vmr		$ivec,$in7
+	 le?vperm	$in5,$in5,$in5,$inpperm
+	 lvx_u		$in7,$x70,$inp
+	 addi		$inp,$inp,0x80
+
+	le?vperm	$out0,$out0,$out0,$inpperm
+	le?vperm	$out1,$out1,$out1,$inpperm
+	stvx_u		$out0,$x00,$out
+	 le?vperm	$in6,$in6,$in6,$inpperm
+	 vxor		$out0,$in0,$rndkey0
+	le?vperm	$out2,$out2,$out2,$inpperm
+	stvx_u		$out1,$x10,$out
+	 le?vperm	$in7,$in7,$in7,$inpperm
+	 vxor		$out1,$in1,$rndkey0
+	le?vperm	$out3,$out3,$out3,$inpperm
+	stvx_u		$out2,$x20,$out
+	 vxor		$out2,$in2,$rndkey0
+	le?vperm	$out4,$out4,$out4,$inpperm
+	stvx_u		$out3,$x30,$out
+	 vxor		$out3,$in3,$rndkey0
+	le?vperm	$out5,$out5,$out5,$inpperm
+	stvx_u		$out4,$x40,$out
+	 vxor		$out4,$in4,$rndkey0
+	le?vperm	$out6,$out6,$out6,$inpperm
+	stvx_u		$out5,$x50,$out
+	 vxor		$out5,$in5,$rndkey0
+	le?vperm	$out7,$out7,$out7,$inpperm
+	stvx_u		$out6,$x60,$out
+	 vxor		$out6,$in6,$rndkey0
+	stvx_u		$out7,$x70,$out
+	addi		$out,$out,0x80
+	 vxor		$out7,$in7,$rndkey0
+
+	mtctr		$rounds
+	beq		Loop_cbc_dec8x		# did $len-=128 borrow?
+
+	addic.		$len,$len,128
+	beq		Lcbc_dec8x_done
+	nop
+	nop
+
+Loop_cbc_dec8x_tail:				# up to 7 "words" tail...
+	vncipher	$out1,$out1,v24
+	vncipher	$out2,$out2,v24
+	vncipher	$out3,$out3,v24
+	vncipher	$out4,$out4,v24
+	vncipher	$out5,$out5,v24
+	vncipher	$out6,$out6,v24
+	vncipher	$out7,$out7,v24
+	lvx		v24,$x20,$key_		# round[3]
+	addi		$key_,$key_,0x20
+
+	vncipher	$out1,$out1,v25
+	vncipher	$out2,$out2,v25
+	vncipher	$out3,$out3,v25
+	vncipher	$out4,$out4,v25
+	vncipher	$out5,$out5,v25
+	vncipher	$out6,$out6,v25
+	vncipher	$out7,$out7,v25
+	lvx		v25,$x10,$key_		# round[4]
+	bdnz		Loop_cbc_dec8x_tail
+
+	vncipher	$out1,$out1,v24
+	vncipher	$out2,$out2,v24
+	vncipher	$out3,$out3,v24
+	vncipher	$out4,$out4,v24
+	vncipher	$out5,$out5,v24
+	vncipher	$out6,$out6,v24
+	vncipher	$out7,$out7,v24
+
+	vncipher	$out1,$out1,v25
+	vncipher	$out2,$out2,v25
+	vncipher	$out3,$out3,v25
+	vncipher	$out4,$out4,v25
+	vncipher	$out5,$out5,v25
+	vncipher	$out6,$out6,v25
+	vncipher	$out7,$out7,v25
+
+	vncipher	$out1,$out1,v26
+	vncipher	$out2,$out2,v26
+	vncipher	$out3,$out3,v26
+	vncipher	$out4,$out4,v26
+	vncipher	$out5,$out5,v26
+	vncipher	$out6,$out6,v26
+	vncipher	$out7,$out7,v26
+
+	vncipher	$out1,$out1,v27
+	vncipher	$out2,$out2,v27
+	vncipher	$out3,$out3,v27
+	vncipher	$out4,$out4,v27
+	vncipher	$out5,$out5,v27
+	vncipher	$out6,$out6,v27
+	vncipher	$out7,$out7,v27
+
+	vncipher	$out1,$out1,v28
+	vncipher	$out2,$out2,v28
+	vncipher	$out3,$out3,v28
+	vncipher	$out4,$out4,v28
+	vncipher	$out5,$out5,v28
+	vncipher	$out6,$out6,v28
+	vncipher	$out7,$out7,v28
+
+	vncipher	$out1,$out1,v29
+	vncipher	$out2,$out2,v29
+	vncipher	$out3,$out3,v29
+	vncipher	$out4,$out4,v29
+	vncipher	$out5,$out5,v29
+	vncipher	$out6,$out6,v29
+	vncipher	$out7,$out7,v29
+
+	vncipher	$out1,$out1,v30
+	 vxor		$ivec,$ivec,v31		# last round key
+	vncipher	$out2,$out2,v30
+	 vxor		$in1,$in1,v31
+	vncipher	$out3,$out3,v30
+	 vxor		$in2,$in2,v31
+	vncipher	$out4,$out4,v30
+	 vxor		$in3,$in3,v31
+	vncipher	$out5,$out5,v30
+	 vxor		$in4,$in4,v31
+	vncipher	$out6,$out6,v30
+	 vxor		$in5,$in5,v31
+	vncipher	$out7,$out7,v30
+	 vxor		$in6,$in6,v31
+
+	cmplwi		$len,32			# switch($len)
+	blt		Lcbc_dec8x_one
+	nop
+	beq		Lcbc_dec8x_two
+	cmplwi		$len,64
+	blt		Lcbc_dec8x_three
+	nop
+	beq		Lcbc_dec8x_four
+	cmplwi		$len,96
+	blt		Lcbc_dec8x_five
+	nop
+	beq		Lcbc_dec8x_six
+
+Lcbc_dec8x_seven:
+	vncipherlast	$out1,$out1,$ivec
+	vncipherlast	$out2,$out2,$in1
+	vncipherlast	$out3,$out3,$in2
+	vncipherlast	$out4,$out4,$in3
+	vncipherlast	$out5,$out5,$in4
+	vncipherlast	$out6,$out6,$in5
+	vncipherlast	$out7,$out7,$in6
+	vmr		$ivec,$in7
+
+	le?vperm	$out1,$out1,$out1,$inpperm
+	le?vperm	$out2,$out2,$out2,$inpperm
+	stvx_u		$out1,$x00,$out
+	le?vperm	$out3,$out3,$out3,$inpperm
+	stvx_u		$out2,$x10,$out
+	le?vperm	$out4,$out4,$out4,$inpperm
+	stvx_u		$out3,$x20,$out
+	le?vperm	$out5,$out5,$out5,$inpperm
+	stvx_u		$out4,$x30,$out
+	le?vperm	$out6,$out6,$out6,$inpperm
+	stvx_u		$out5,$x40,$out
+	le?vperm	$out7,$out7,$out7,$inpperm
+	stvx_u		$out6,$x50,$out
+	stvx_u		$out7,$x60,$out
+	addi		$out,$out,0x70
+	b		Lcbc_dec8x_done
+
+.align	5
+Lcbc_dec8x_six:
+	vncipherlast	$out2,$out2,$ivec
+	vncipherlast	$out3,$out3,$in2
+	vncipherlast	$out4,$out4,$in3
+	vncipherlast	$out5,$out5,$in4
+	vncipherlast	$out6,$out6,$in5
+	vncipherlast	$out7,$out7,$in6
+	vmr		$ivec,$in7
+
+	le?vperm	$out2,$out2,$out2,$inpperm
+	le?vperm	$out3,$out3,$out3,$inpperm
+	stvx_u		$out2,$x00,$out
+	le?vperm	$out4,$out4,$out4,$inpperm
+	stvx_u		$out3,$x10,$out
+	le?vperm	$out5,$out5,$out5,$inpperm
+	stvx_u		$out4,$x20,$out
+	le?vperm	$out6,$out6,$out6,$inpperm
+	stvx_u		$out5,$x30,$out
+	le?vperm	$out7,$out7,$out7,$inpperm
+	stvx_u		$out6,$x40,$out
+	stvx_u		$out7,$x50,$out
+	addi		$out,$out,0x60
+	b		Lcbc_dec8x_done
+
+.align	5
+Lcbc_dec8x_five:
+	vncipherlast	$out3,$out3,$ivec
+	vncipherlast	$out4,$out4,$in3
+	vncipherlast	$out5,$out5,$in4
+	vncipherlast	$out6,$out6,$in5
+	vncipherlast	$out7,$out7,$in6
+	vmr		$ivec,$in7
+
+	le?vperm	$out3,$out3,$out3,$inpperm
+	le?vperm	$out4,$out4,$out4,$inpperm
+	stvx_u		$out3,$x00,$out
+	le?vperm	$out5,$out5,$out5,$inpperm
+	stvx_u		$out4,$x10,$out
+	le?vperm	$out6,$out6,$out6,$inpperm
+	stvx_u		$out5,$x20,$out
+	le?vperm	$out7,$out7,$out7,$inpperm
+	stvx_u		$out6,$x30,$out
+	stvx_u		$out7,$x40,$out
+	addi		$out,$out,0x50
+	b		Lcbc_dec8x_done
+
+.align	5
+Lcbc_dec8x_four:
+	vncipherlast	$out4,$out4,$ivec
+	vncipherlast	$out5,$out5,$in4
+	vncipherlast	$out6,$out6,$in5
+	vncipherlast	$out7,$out7,$in6
+	vmr		$ivec,$in7
+
+	le?vperm	$out4,$out4,$out4,$inpperm
+	le?vperm	$out5,$out5,$out5,$inpperm
+	stvx_u		$out4,$x00,$out
+	le?vperm	$out6,$out6,$out6,$inpperm
+	stvx_u		$out5,$x10,$out
+	le?vperm	$out7,$out7,$out7,$inpperm
+	stvx_u		$out6,$x20,$out
+	stvx_u		$out7,$x30,$out
+	addi		$out,$out,0x40
+	b		Lcbc_dec8x_done
+
+.align	5
+Lcbc_dec8x_three:
+	vncipherlast	$out5,$out5,$ivec
+	vncipherlast	$out6,$out6,$in5
+	vncipherlast	$out7,$out7,$in6
+	vmr		$ivec,$in7
+
+	le?vperm	$out5,$out5,$out5,$inpperm
+	le?vperm	$out6,$out6,$out6,$inpperm
+	stvx_u		$out5,$x00,$out
+	le?vperm	$out7,$out7,$out7,$inpperm
+	stvx_u		$out6,$x10,$out
+	stvx_u		$out7,$x20,$out
+	addi		$out,$out,0x30
+	b		Lcbc_dec8x_done
+
+.align	5
+Lcbc_dec8x_two:
+	vncipherlast	$out6,$out6,$ivec
+	vncipherlast	$out7,$out7,$in6
+	vmr		$ivec,$in7
+
+	le?vperm	$out6,$out6,$out6,$inpperm
+	le?vperm	$out7,$out7,$out7,$inpperm
+	stvx_u		$out6,$x00,$out
+	stvx_u		$out7,$x10,$out
+	addi		$out,$out,0x20
+	b		Lcbc_dec8x_done
+
+.align	5
+Lcbc_dec8x_one:
+	vncipherlast	$out7,$out7,$ivec
+	vmr		$ivec,$in7
+
+	le?vperm	$out7,$out7,$out7,$inpperm
+	stvx_u		$out7,0,$out
+	addi		$out,$out,0x10
+
+Lcbc_dec8x_done:
+	le?vperm	$ivec,$ivec,$ivec,$inpperm
+	stvx_u		$ivec,0,$ivp		# write [unaligned] iv
+
+	li		r10,`$FRAME+15`
+	li		r11,`$FRAME+31`
+	stvx		$inpperm,r10,$sp	# wipe copies of round keys
+	addi		r10,r10,32
+	stvx		$inpperm,r11,$sp
+	addi		r11,r11,32
+	stvx		$inpperm,r10,$sp
+	addi		r10,r10,32
+	stvx		$inpperm,r11,$sp
+	addi		r11,r11,32
+	stvx		$inpperm,r10,$sp
+	addi		r10,r10,32
+	stvx		$inpperm,r11,$sp
+	addi		r11,r11,32
+	stvx		$inpperm,r10,$sp
+	addi		r10,r10,32
+	stvx		$inpperm,r11,$sp
+	addi		r11,r11,32
+
+	mtspr		256,$vrsave
+	lvx		v20,r10,$sp		# ABI says so
+	addi		r10,r10,32
+	lvx		v21,r11,$sp
+	addi		r11,r11,32
+	lvx		v22,r10,$sp
+	addi		r10,r10,32
+	lvx		v23,r11,$sp
+	addi		r11,r11,32
+	lvx		v24,r10,$sp
+	addi		r10,r10,32
+	lvx		v25,r11,$sp
+	addi		r11,r11,32
+	lvx		v26,r10,$sp
+	addi		r10,r10,32
+	lvx		v27,r11,$sp
+	addi		r11,r11,32
+	lvx		v28,r10,$sp
+	addi		r10,r10,32
+	lvx		v29,r11,$sp
+	addi		r11,r11,32
+	lvx		v30,r10,$sp
+	lvx		v31,r11,$sp
+	$POP		r26,`$FRAME+21*16+0*$SIZE_T`($sp)
+	$POP		r27,`$FRAME+21*16+1*$SIZE_T`($sp)
+	$POP		r28,`$FRAME+21*16+2*$SIZE_T`($sp)
+	$POP		r29,`$FRAME+21*16+3*$SIZE_T`($sp)
+	$POP		r30,`$FRAME+21*16+4*$SIZE_T`($sp)
+	$POP		r31,`$FRAME+21*16+5*$SIZE_T`($sp)
+	addi		$sp,$sp,`$FRAME+21*16+6*$SIZE_T`
+	blr
+	.long		0
+	.byte		0,12,0x04,0,0x80,6,6,0
+	.long		0
+.size	.${prefix}_cbc_encrypt,.-.${prefix}_cbc_encrypt
+___
+}}	}}}
+
+#########################################################################
+{{{	# CTR procedure[s]						#
+my ($inp,$out,$len,$key,$ivp,$x10,$rounds,$idx)=map("r$_",(3..10));
+my ($rndkey0,$rndkey1,$inout,$tmp)=		map("v$_",(0..3));
+my ($ivec,$inptail,$inpperm,$outhead,$outperm,$outmask,$keyperm,$one)=
+						map("v$_",(4..11));
+my $dat=$tmp;
+
+$code.=<<___;
+.globl	.${prefix}_ctr32_encrypt_blocks
+.align	5
+.${prefix}_ctr32_encrypt_blocks:
+	${UCMP}i	$len,1
+	bltlr-
+
+	lis		r0,0xfff0
+	mfspr		$vrsave,256
+	mtspr		256,r0
+
+	li		$idx,15
+	vxor		$rndkey0,$rndkey0,$rndkey0
+	le?vspltisb	$tmp,0x0f
+
+	lvx		$ivec,0,$ivp		# load [unaligned] iv
+	lvsl		$inpperm,0,$ivp
+	lvx		$inptail,$idx,$ivp
+	 vspltisb	$one,1
+	le?vxor		$inpperm,$inpperm,$tmp
+	vperm		$ivec,$ivec,$inptail,$inpperm
+	 vsldoi		$one,$rndkey0,$one,1
+
+	neg		r11,$inp
+	?lvsl		$keyperm,0,$key		# prepare for unaligned key
+	lwz		$rounds,240($key)
+
+	lvsr		$inpperm,0,r11		# prepare for unaligned load
+	lvx		$inptail,0,$inp
+	addi		$inp,$inp,15		# 15 is not typo
+	le?vxor		$inpperm,$inpperm,$tmp
+
+	srwi		$rounds,$rounds,1
+	li		$idx,16
+	subi		$rounds,$rounds,1
+
+	${UCMP}i	$len,8
+	bge		_aesp8_ctr32_encrypt8x
+
+	?lvsr		$outperm,0,$out		# prepare for unaligned store
+	vspltisb	$outmask,-1
+	lvx		$outhead,0,$out
+	?vperm		$outmask,$rndkey0,$outmask,$outperm
+	le?vxor		$outperm,$outperm,$tmp
+
+	lvx		$rndkey0,0,$key
+	mtctr		$rounds
+	lvx		$rndkey1,$idx,$key
+	addi		$idx,$idx,16
+	?vperm		$rndkey0,$rndkey0,$rndkey1,$keyperm
+	vxor		$inout,$ivec,$rndkey0
+	lvx		$rndkey0,$idx,$key
+	addi		$idx,$idx,16
+	b		Loop_ctr32_enc
+
+.align	5
+Loop_ctr32_enc:
+	?vperm		$rndkey1,$rndkey1,$rndkey0,$keyperm
+	vcipher		$inout,$inout,$rndkey1
+	lvx		$rndkey1,$idx,$key
+	addi		$idx,$idx,16
+	?vperm		$rndkey0,$rndkey0,$rndkey1,$keyperm
+	vcipher		$inout,$inout,$rndkey0
+	lvx		$rndkey0,$idx,$key
+	addi		$idx,$idx,16
+	bdnz		Loop_ctr32_enc
+
+	vadduwm		$ivec,$ivec,$one
+	 vmr		$dat,$inptail
+	 lvx		$inptail,0,$inp
+	 addi		$inp,$inp,16
+	 subic.		$len,$len,1		# blocks--
+
+	?vperm		$rndkey1,$rndkey1,$rndkey0,$keyperm
+	vcipher		$inout,$inout,$rndkey1
+	lvx		$rndkey1,$idx,$key
+	 vperm		$dat,$dat,$inptail,$inpperm
+	 li		$idx,16
+	?vperm		$rndkey1,$rndkey0,$rndkey1,$keyperm
+	 lvx		$rndkey0,0,$key
+	vxor		$dat,$dat,$rndkey1	# last round key
+	vcipherlast	$inout,$inout,$dat
+
+	 lvx		$rndkey1,$idx,$key
+	 addi		$idx,$idx,16
+	vperm		$inout,$inout,$inout,$outperm
+	vsel		$dat,$outhead,$inout,$outmask
+	 mtctr		$rounds
+	 ?vperm		$rndkey0,$rndkey0,$rndkey1,$keyperm
+	vmr		$outhead,$inout
+	 vxor		$inout,$ivec,$rndkey0
+	 lvx		$rndkey0,$idx,$key
+	 addi		$idx,$idx,16
+	stvx		$dat,0,$out
+	addi		$out,$out,16
+	bne		Loop_ctr32_enc
+
+	addi		$out,$out,-1
+	lvx		$inout,0,$out		# redundant in aligned case
+	vsel		$inout,$outhead,$inout,$outmask
+	stvx		$inout,0,$out
+
+	mtspr		256,$vrsave
+	blr
+	.long		0
+	.byte		0,12,0x14,0,0,0,6,0
+	.long		0
+___
+#########################################################################
+{{	# Optimized CTR procedure					#
+my $key_="r11";
+my ($x00,$x10,$x20,$x30,$x40,$x50,$x60,$x70)=map("r$_",(0,8,26..31));
+    $x00=0 if ($flavour =~ /osx/);
+my ($in0, $in1, $in2, $in3, $in4, $in5, $in6, $in7 )=map("v$_",(0..3,10,12..14));
+my ($out0,$out1,$out2,$out3,$out4,$out5,$out6,$out7)=map("v$_",(15..22));
+my $rndkey0="v23";	# v24-v25 rotating buffer for first found keys
+			# v26-v31 last 6 round keys
+my ($tmp,$keyperm)=($in3,$in4);	# aliases with "caller", redundant assignment
+my ($two,$three,$four)=($outhead,$outperm,$outmask);
+
+$code.=<<___;
+.align	5
+_aesp8_ctr32_encrypt8x:
+	$STU		$sp,-`($FRAME+21*16+6*$SIZE_T)`($sp)
+	li		r10,`$FRAME+8*16+15`
+	li		r11,`$FRAME+8*16+31`
+	stvx		v20,r10,$sp		# ABI says so
+	addi		r10,r10,32
+	stvx		v21,r11,$sp
+	addi		r11,r11,32
+	stvx		v22,r10,$sp
+	addi		r10,r10,32
+	stvx		v23,r11,$sp
+	addi		r11,r11,32
+	stvx		v24,r10,$sp
+	addi		r10,r10,32
+	stvx		v25,r11,$sp
+	addi		r11,r11,32
+	stvx		v26,r10,$sp
+	addi		r10,r10,32
+	stvx		v27,r11,$sp
+	addi		r11,r11,32
+	stvx		v28,r10,$sp
+	addi		r10,r10,32
+	stvx		v29,r11,$sp
+	addi		r11,r11,32
+	stvx		v30,r10,$sp
+	stvx		v31,r11,$sp
+	li		r0,-1
+	stw		$vrsave,`$FRAME+21*16-4`($sp)	# save vrsave
+	li		$x10,0x10
+	$PUSH		r26,`$FRAME+21*16+0*$SIZE_T`($sp)
+	li		$x20,0x20
+	$PUSH		r27,`$FRAME+21*16+1*$SIZE_T`($sp)
+	li		$x30,0x30
+	$PUSH		r28,`$FRAME+21*16+2*$SIZE_T`($sp)
+	li		$x40,0x40
+	$PUSH		r29,`$FRAME+21*16+3*$SIZE_T`($sp)
+	li		$x50,0x50
+	$PUSH		r30,`$FRAME+21*16+4*$SIZE_T`($sp)
+	li		$x60,0x60
+	$PUSH		r31,`$FRAME+21*16+5*$SIZE_T`($sp)
+	li		$x70,0x70
+	mtspr		256,r0
+
+	subi		$rounds,$rounds,3	# -4 in total
+
+	lvx		$rndkey0,$x00,$key	# load key schedule
+	lvx		v30,$x10,$key
+	addi		$key,$key,0x20
+	lvx		v31,$x00,$key
+	?vperm		$rndkey0,$rndkey0,v30,$keyperm
+	addi		$key_,$sp,$FRAME+15
+	mtctr		$rounds
+
+Load_ctr32_enc_key:
+	?vperm		v24,v30,v31,$keyperm
+	lvx		v30,$x10,$key
+	addi		$key,$key,0x20
+	stvx		v24,$x00,$key_		# off-load round[1]
+	?vperm		v25,v31,v30,$keyperm
+	lvx		v31,$x00,$key
+	stvx		v25,$x10,$key_		# off-load round[2]
+	addi		$key_,$key_,0x20
+	bdnz		Load_ctr32_enc_key
+
+	lvx		v26,$x10,$key
+	?vperm		v24,v30,v31,$keyperm
+	lvx		v27,$x20,$key
+	stvx		v24,$x00,$key_		# off-load round[3]
+	?vperm		v25,v31,v26,$keyperm
+	lvx		v28,$x30,$key
+	stvx		v25,$x10,$key_		# off-load round[4]
+	addi		$key_,$sp,$FRAME+15	# rewind $key_
+	?vperm		v26,v26,v27,$keyperm
+	lvx		v29,$x40,$key
+	?vperm		v27,v27,v28,$keyperm
+	lvx		v30,$x50,$key
+	?vperm		v28,v28,v29,$keyperm
+	lvx		v31,$x60,$key
+	?vperm		v29,v29,v30,$keyperm
+	lvx		$out0,$x70,$key		# borrow $out0
+	?vperm		v30,v30,v31,$keyperm
+	lvx		v24,$x00,$key_		# pre-load round[1]
+	?vperm		v31,v31,$out0,$keyperm
+	lvx		v25,$x10,$key_		# pre-load round[2]
+
+	vadduwm		$two,$one,$one
+	subi		$inp,$inp,15		# undo "caller"
+	$SHL		$len,$len,4
+
+	vadduwm		$out1,$ivec,$one	# counter values ...
+	vadduwm		$out2,$ivec,$two
+	vxor		$out0,$ivec,$rndkey0	# ... xored with rndkey[0]
+	 le?li		$idx,8
+	vadduwm		$out3,$out1,$two
+	vxor		$out1,$out1,$rndkey0
+	 le?lvsl	$inpperm,0,$idx
+	vadduwm		$out4,$out2,$two
+	vxor		$out2,$out2,$rndkey0
+	 le?vspltisb	$tmp,0x0f
+	vadduwm		$out5,$out3,$two
+	vxor		$out3,$out3,$rndkey0
+	 le?vxor	$inpperm,$inpperm,$tmp	# transform for lvx_u/stvx_u
+	vadduwm		$out6,$out4,$two
+	vxor		$out4,$out4,$rndkey0
+	vadduwm		$out7,$out5,$two
+	vxor		$out5,$out5,$rndkey0
+	vadduwm		$ivec,$out6,$two	# next counter value
+	vxor		$out6,$out6,$rndkey0
+	vxor		$out7,$out7,$rndkey0
+
+	mtctr		$rounds
+	b		Loop_ctr32_enc8x
+.align	5
+Loop_ctr32_enc8x:
+	vcipher 	$out0,$out0,v24
+	vcipher 	$out1,$out1,v24
+	vcipher 	$out2,$out2,v24
+	vcipher 	$out3,$out3,v24
+	vcipher 	$out4,$out4,v24
+	vcipher 	$out5,$out5,v24
+	vcipher 	$out6,$out6,v24
+	vcipher 	$out7,$out7,v24
+Loop_ctr32_enc8x_middle:
+	lvx		v24,$x20,$key_		# round[3]
+	addi		$key_,$key_,0x20
+
+	vcipher 	$out0,$out0,v25
+	vcipher 	$out1,$out1,v25
+	vcipher 	$out2,$out2,v25
+	vcipher 	$out3,$out3,v25
+	vcipher 	$out4,$out4,v25
+	vcipher 	$out5,$out5,v25
+	vcipher 	$out6,$out6,v25
+	vcipher 	$out7,$out7,v25
+	lvx		v25,$x10,$key_		# round[4]
+	bdnz		Loop_ctr32_enc8x
+
+	subic		r11,$len,256		# $len-256, borrow $key_
+	vcipher 	$out0,$out0,v24
+	vcipher 	$out1,$out1,v24
+	vcipher 	$out2,$out2,v24
+	vcipher 	$out3,$out3,v24
+	vcipher 	$out4,$out4,v24
+	vcipher 	$out5,$out5,v24
+	vcipher 	$out6,$out6,v24
+	vcipher 	$out7,$out7,v24
+
+	subfe		r0,r0,r0		# borrow?-1:0
+	vcipher 	$out0,$out0,v25
+	vcipher 	$out1,$out1,v25
+	vcipher 	$out2,$out2,v25
+	vcipher 	$out3,$out3,v25
+	vcipher 	$out4,$out4,v25
+	vcipher		$out5,$out5,v25
+	vcipher		$out6,$out6,v25
+	vcipher		$out7,$out7,v25
+
+	and		r0,r0,r11
+	addi		$key_,$sp,$FRAME+15	# rewind $key_
+	vcipher		$out0,$out0,v26
+	vcipher		$out1,$out1,v26
+	vcipher		$out2,$out2,v26
+	vcipher		$out3,$out3,v26
+	vcipher		$out4,$out4,v26
+	vcipher		$out5,$out5,v26
+	vcipher		$out6,$out6,v26
+	vcipher		$out7,$out7,v26
+	lvx		v24,$x00,$key_		# re-pre-load round[1]
+
+	subic		$len,$len,129		# $len-=129
+	vcipher		$out0,$out0,v27
+	addi		$len,$len,1		# $len-=128 really
+	vcipher		$out1,$out1,v27
+	vcipher		$out2,$out2,v27
+	vcipher		$out3,$out3,v27
+	vcipher		$out4,$out4,v27
+	vcipher		$out5,$out5,v27
+	vcipher		$out6,$out6,v27
+	vcipher		$out7,$out7,v27
+	lvx		v25,$x10,$key_		# re-pre-load round[2]
+
+	vcipher		$out0,$out0,v28
+	 lvx_u		$in0,$x00,$inp		# load input
+	vcipher		$out1,$out1,v28
+	 lvx_u		$in1,$x10,$inp
+	vcipher		$out2,$out2,v28
+	 lvx_u		$in2,$x20,$inp
+	vcipher		$out3,$out3,v28
+	 lvx_u		$in3,$x30,$inp
+	vcipher		$out4,$out4,v28
+	 lvx_u		$in4,$x40,$inp
+	vcipher		$out5,$out5,v28
+	 lvx_u		$in5,$x50,$inp
+	vcipher		$out6,$out6,v28
+	 lvx_u		$in6,$x60,$inp
+	vcipher		$out7,$out7,v28
+	 lvx_u		$in7,$x70,$inp
+	 addi		$inp,$inp,0x80
+
+	vcipher		$out0,$out0,v29
+	 le?vperm	$in0,$in0,$in0,$inpperm
+	vcipher		$out1,$out1,v29
+	 le?vperm	$in1,$in1,$in1,$inpperm
+	vcipher		$out2,$out2,v29
+	 le?vperm	$in2,$in2,$in2,$inpperm
+	vcipher		$out3,$out3,v29
+	 le?vperm	$in3,$in3,$in3,$inpperm
+	vcipher		$out4,$out4,v29
+	 le?vperm	$in4,$in4,$in4,$inpperm
+	vcipher		$out5,$out5,v29
+	 le?vperm	$in5,$in5,$in5,$inpperm
+	vcipher		$out6,$out6,v29
+	 le?vperm	$in6,$in6,$in6,$inpperm
+	vcipher		$out7,$out7,v29
+	 le?vperm	$in7,$in7,$in7,$inpperm
+
+	add		$inp,$inp,r0		# $inp is adjusted in such
+						# way that at exit from the
+						# loop inX-in7 are loaded
+						# with last "words"
+	subfe.		r0,r0,r0		# borrow?-1:0
+	vcipher		$out0,$out0,v30
+	 vxor		$in0,$in0,v31		# xor with last round key
+	vcipher		$out1,$out1,v30
+	 vxor		$in1,$in1,v31
+	vcipher		$out2,$out2,v30
+	 vxor		$in2,$in2,v31
+	vcipher		$out3,$out3,v30
+	 vxor		$in3,$in3,v31
+	vcipher		$out4,$out4,v30
+	 vxor		$in4,$in4,v31
+	vcipher		$out5,$out5,v30
+	 vxor		$in5,$in5,v31
+	vcipher		$out6,$out6,v30
+	 vxor		$in6,$in6,v31
+	vcipher		$out7,$out7,v30
+	 vxor		$in7,$in7,v31
+
+	bne		Lctr32_enc8x_break	# did $len-129 borrow?
+
+	vcipherlast	$in0,$out0,$in0
+	vcipherlast	$in1,$out1,$in1
+	 vadduwm	$out1,$ivec,$one	# counter values ...
+	vcipherlast	$in2,$out2,$in2
+	 vadduwm	$out2,$ivec,$two
+	 vxor		$out0,$ivec,$rndkey0	# ... xored with rndkey[0]
+	vcipherlast	$in3,$out3,$in3
+	 vadduwm	$out3,$out1,$two
+	 vxor		$out1,$out1,$rndkey0
+	vcipherlast	$in4,$out4,$in4
+	 vadduwm	$out4,$out2,$two
+	 vxor		$out2,$out2,$rndkey0
+	vcipherlast	$in5,$out5,$in5
+	 vadduwm	$out5,$out3,$two
+	 vxor		$out3,$out3,$rndkey0
+	vcipherlast	$in6,$out6,$in6
+	 vadduwm	$out6,$out4,$two
+	 vxor		$out4,$out4,$rndkey0
+	vcipherlast	$in7,$out7,$in7
+	 vadduwm	$out7,$out5,$two
+	 vxor		$out5,$out5,$rndkey0
+	le?vperm	$in0,$in0,$in0,$inpperm
+	 vadduwm	$ivec,$out6,$two	# next counter value
+	 vxor		$out6,$out6,$rndkey0
+	le?vperm	$in1,$in1,$in1,$inpperm
+	 vxor		$out7,$out7,$rndkey0
+	mtctr		$rounds
+
+	 vcipher	$out0,$out0,v24
+	stvx_u		$in0,$x00,$out
+	le?vperm	$in2,$in2,$in2,$inpperm
+	 vcipher	$out1,$out1,v24
+	stvx_u		$in1,$x10,$out
+	le?vperm	$in3,$in3,$in3,$inpperm
+	 vcipher	$out2,$out2,v24
+	stvx_u		$in2,$x20,$out
+	le?vperm	$in4,$in4,$in4,$inpperm
+	 vcipher	$out3,$out3,v24
+	stvx_u		$in3,$x30,$out
+	le?vperm	$in5,$in5,$in5,$inpperm
+	 vcipher	$out4,$out4,v24
+	stvx_u		$in4,$x40,$out
+	le?vperm	$in6,$in6,$in6,$inpperm
+	 vcipher	$out5,$out5,v24
+	stvx_u		$in5,$x50,$out
+	le?vperm	$in7,$in7,$in7,$inpperm
+	 vcipher	$out6,$out6,v24
+	stvx_u		$in6,$x60,$out
+	 vcipher	$out7,$out7,v24
+	stvx_u		$in7,$x70,$out
+	addi		$out,$out,0x80
+
+	b		Loop_ctr32_enc8x_middle
+
+.align	5
+Lctr32_enc8x_break:
+	cmpwi		$len,-0x60
+	blt		Lctr32_enc8x_one
+	nop
+	beq		Lctr32_enc8x_two
+	cmpwi		$len,-0x40
+	blt		Lctr32_enc8x_three
+	nop
+	beq		Lctr32_enc8x_four
+	cmpwi		$len,-0x20
+	blt		Lctr32_enc8x_five
+	nop
+	beq		Lctr32_enc8x_six
+	cmpwi		$len,0x00
+	blt		Lctr32_enc8x_seven
+
+Lctr32_enc8x_eight:
+	vcipherlast	$out0,$out0,$in0
+	vcipherlast	$out1,$out1,$in1
+	vcipherlast	$out2,$out2,$in2
+	vcipherlast	$out3,$out3,$in3
+	vcipherlast	$out4,$out4,$in4
+	vcipherlast	$out5,$out5,$in5
+	vcipherlast	$out6,$out6,$in6
+	vcipherlast	$out7,$out7,$in7
+
+	le?vperm	$out0,$out0,$out0,$inpperm
+	le?vperm	$out1,$out1,$out1,$inpperm
+	stvx_u		$out0,$x00,$out
+	le?vperm	$out2,$out2,$out2,$inpperm
+	stvx_u		$out1,$x10,$out
+	le?vperm	$out3,$out3,$out3,$inpperm
+	stvx_u		$out2,$x20,$out
+	le?vperm	$out4,$out4,$out4,$inpperm
+	stvx_u		$out3,$x30,$out
+	le?vperm	$out5,$out5,$out5,$inpperm
+	stvx_u		$out4,$x40,$out
+	le?vperm	$out6,$out6,$out6,$inpperm
+	stvx_u		$out5,$x50,$out
+	le?vperm	$out7,$out7,$out7,$inpperm
+	stvx_u		$out6,$x60,$out
+	stvx_u		$out7,$x70,$out
+	addi		$out,$out,0x80
+	b		Lctr32_enc8x_done
+
+.align	5
+Lctr32_enc8x_seven:
+	vcipherlast	$out0,$out0,$in1
+	vcipherlast	$out1,$out1,$in2
+	vcipherlast	$out2,$out2,$in3
+	vcipherlast	$out3,$out3,$in4
+	vcipherlast	$out4,$out4,$in5
+	vcipherlast	$out5,$out5,$in6
+	vcipherlast	$out6,$out6,$in7
+
+	le?vperm	$out0,$out0,$out0,$inpperm
+	le?vperm	$out1,$out1,$out1,$inpperm
+	stvx_u		$out0,$x00,$out
+	le?vperm	$out2,$out2,$out2,$inpperm
+	stvx_u		$out1,$x10,$out
+	le?vperm	$out3,$out3,$out3,$inpperm
+	stvx_u		$out2,$x20,$out
+	le?vperm	$out4,$out4,$out4,$inpperm
+	stvx_u		$out3,$x30,$out
+	le?vperm	$out5,$out5,$out5,$inpperm
+	stvx_u		$out4,$x40,$out
+	le?vperm	$out6,$out6,$out6,$inpperm
+	stvx_u		$out5,$x50,$out
+	stvx_u		$out6,$x60,$out
+	addi		$out,$out,0x70
+	b		Lctr32_enc8x_done
+
+.align	5
+Lctr32_enc8x_six:
+	vcipherlast	$out0,$out0,$in2
+	vcipherlast	$out1,$out1,$in3
+	vcipherlast	$out2,$out2,$in4
+	vcipherlast	$out3,$out3,$in5
+	vcipherlast	$out4,$out4,$in6
+	vcipherlast	$out5,$out5,$in7
+
+	le?vperm	$out0,$out0,$out0,$inpperm
+	le?vperm	$out1,$out1,$out1,$inpperm
+	stvx_u		$out0,$x00,$out
+	le?vperm	$out2,$out2,$out2,$inpperm
+	stvx_u		$out1,$x10,$out
+	le?vperm	$out3,$out3,$out3,$inpperm
+	stvx_u		$out2,$x20,$out
+	le?vperm	$out4,$out4,$out4,$inpperm
+	stvx_u		$out3,$x30,$out
+	le?vperm	$out5,$out5,$out5,$inpperm
+	stvx_u		$out4,$x40,$out
+	stvx_u		$out5,$x50,$out
+	addi		$out,$out,0x60
+	b		Lctr32_enc8x_done
+
+.align	5
+Lctr32_enc8x_five:
+	vcipherlast	$out0,$out0,$in3
+	vcipherlast	$out1,$out1,$in4
+	vcipherlast	$out2,$out2,$in5
+	vcipherlast	$out3,$out3,$in6
+	vcipherlast	$out4,$out4,$in7
+
+	le?vperm	$out0,$out0,$out0,$inpperm
+	le?vperm	$out1,$out1,$out1,$inpperm
+	stvx_u		$out0,$x00,$out
+	le?vperm	$out2,$out2,$out2,$inpperm
+	stvx_u		$out1,$x10,$out
+	le?vperm	$out3,$out3,$out3,$inpperm
+	stvx_u		$out2,$x20,$out
+	le?vperm	$out4,$out4,$out4,$inpperm
+	stvx_u		$out3,$x30,$out
+	stvx_u		$out4,$x40,$out
+	addi		$out,$out,0x50
+	b		Lctr32_enc8x_done
+
+.align	5
+Lctr32_enc8x_four:
+	vcipherlast	$out0,$out0,$in4
+	vcipherlast	$out1,$out1,$in5
+	vcipherlast	$out2,$out2,$in6
+	vcipherlast	$out3,$out3,$in7
+
+	le?vperm	$out0,$out0,$out0,$inpperm
+	le?vperm	$out1,$out1,$out1,$inpperm
+	stvx_u		$out0,$x00,$out
+	le?vperm	$out2,$out2,$out2,$inpperm
+	stvx_u		$out1,$x10,$out
+	le?vperm	$out3,$out3,$out3,$inpperm
+	stvx_u		$out2,$x20,$out
+	stvx_u		$out3,$x30,$out
+	addi		$out,$out,0x40
+	b		Lctr32_enc8x_done
+
+.align	5
+Lctr32_enc8x_three:
+	vcipherlast	$out0,$out0,$in5
+	vcipherlast	$out1,$out1,$in6
+	vcipherlast	$out2,$out2,$in7
+
+	le?vperm	$out0,$out0,$out0,$inpperm
+	le?vperm	$out1,$out1,$out1,$inpperm
+	stvx_u		$out0,$x00,$out
+	le?vperm	$out2,$out2,$out2,$inpperm
+	stvx_u		$out1,$x10,$out
+	stvx_u		$out2,$x20,$out
+	addi		$out,$out,0x30
+	b		Lcbc_dec8x_done
+
+.align	5
+Lctr32_enc8x_two:
+	vcipherlast	$out0,$out0,$in6
+	vcipherlast	$out1,$out1,$in7
+
+	le?vperm	$out0,$out0,$out0,$inpperm
+	le?vperm	$out1,$out1,$out1,$inpperm
+	stvx_u		$out0,$x00,$out
+	stvx_u		$out1,$x10,$out
+	addi		$out,$out,0x20
+	b		Lcbc_dec8x_done
+
+.align	5
+Lctr32_enc8x_one:
+	vcipherlast	$out0,$out0,$in7
+
+	le?vperm	$out0,$out0,$out0,$inpperm
+	stvx_u		$out0,0,$out
+	addi		$out,$out,0x10
+
+Lctr32_enc8x_done:
+	li		r10,`$FRAME+15`
+	li		r11,`$FRAME+31`
+	stvx		$inpperm,r10,$sp	# wipe copies of round keys
+	addi		r10,r10,32
+	stvx		$inpperm,r11,$sp
+	addi		r11,r11,32
+	stvx		$inpperm,r10,$sp
+	addi		r10,r10,32
+	stvx		$inpperm,r11,$sp
+	addi		r11,r11,32
+	stvx		$inpperm,r10,$sp
+	addi		r10,r10,32
+	stvx		$inpperm,r11,$sp
+	addi		r11,r11,32
+	stvx		$inpperm,r10,$sp
+	addi		r10,r10,32
+	stvx		$inpperm,r11,$sp
+	addi		r11,r11,32
+
+	mtspr		256,$vrsave
+	lvx		v20,r10,$sp		# ABI says so
+	addi		r10,r10,32
+	lvx		v21,r11,$sp
+	addi		r11,r11,32
+	lvx		v22,r10,$sp
+	addi		r10,r10,32
+	lvx		v23,r11,$sp
+	addi		r11,r11,32
+	lvx		v24,r10,$sp
+	addi		r10,r10,32
+	lvx		v25,r11,$sp
+	addi		r11,r11,32
+	lvx		v26,r10,$sp
+	addi		r10,r10,32
+	lvx		v27,r11,$sp
+	addi		r11,r11,32
+	lvx		v28,r10,$sp
+	addi		r10,r10,32
+	lvx		v29,r11,$sp
+	addi		r11,r11,32
+	lvx		v30,r10,$sp
+	lvx		v31,r11,$sp
+	$POP		r26,`$FRAME+21*16+0*$SIZE_T`($sp)
+	$POP		r27,`$FRAME+21*16+1*$SIZE_T`($sp)
+	$POP		r28,`$FRAME+21*16+2*$SIZE_T`($sp)
+	$POP		r29,`$FRAME+21*16+3*$SIZE_T`($sp)
+	$POP		r30,`$FRAME+21*16+4*$SIZE_T`($sp)
+	$POP		r31,`$FRAME+21*16+5*$SIZE_T`($sp)
+	addi		$sp,$sp,`$FRAME+21*16+6*$SIZE_T`
+	blr
+	.long		0
+	.byte		0,12,0x04,0,0x80,6,6,0
+	.long		0
+.size	.${prefix}_ctr32_encrypt_blocks,.-.${prefix}_ctr32_encrypt_blocks
+___
+}}	}}}
+
+#########################################################################
+{{{	# XTS procedures						#
+# int aes_p8_xts_[en|de]crypt(const char *inp, char *out, size_t len,	#
+#                             const AES_KEY *key1, const AES_KEY *key2,	#
+#                             [const] unsigned char iv[16]);		#
+# If $key2 is NULL, then a "tweak chaining" mode is engaged, in which	#
+# input tweak value is assumed to be encrypted already, and last tweak	#
+# value, one suitable for consecutive call on same chunk of data, is	#
+# written back to original buffer. In addition, in "tweak chaining"	#
+# mode only complete input blocks are processed.			#
+
+my ($inp,$out,$len,$key1,$key2,$ivp,$rounds,$idx) =	map("r$_",(3..10));
+my ($rndkey0,$rndkey1,$inout) =				map("v$_",(0..2));
+my ($output,$inptail,$inpperm,$leperm,$keyperm) =	map("v$_",(3..7));
+my ($tweak,$seven,$eighty7,$tmp,$tweak1) =		map("v$_",(8..12));
+my $taillen = $key2;
+
+   ($inp,$idx) = ($idx,$inp);				# reassign
+
+$code.=<<___;
+.globl	.${prefix}_xts_encrypt
+.align	5
+.${prefix}_xts_encrypt:
+	mr		$inp,r3				# reassign
+	li		r3,-1
+	${UCMP}i	$len,16
+	bltlr-
+
+	lis		r0,0xfff0
+	mfspr		r12,256				# save vrsave
+	li		r11,0
+	mtspr		256,r0
+
+	vspltisb	$seven,0x07			# 0x070707..07
+	le?lvsl		$leperm,r11,r11
+	le?vspltisb	$tmp,0x0f
+	le?vxor		$leperm,$leperm,$seven
+
+	li		$idx,15
+	lvx		$tweak,0,$ivp			# load [unaligned] iv
+	lvsl		$inpperm,0,$ivp
+	lvx		$inptail,$idx,$ivp
+	le?vxor		$inpperm,$inpperm,$tmp
+	vperm		$tweak,$tweak,$inptail,$inpperm
+
+	neg		r11,$inp
+	lvsr		$inpperm,0,r11			# prepare for unaligned load
+	lvx		$inout,0,$inp
+	addi		$inp,$inp,15			# 15 is not typo
+	le?vxor		$inpperm,$inpperm,$tmp
+
+	${UCMP}i	$key2,0				# key2==NULL?
+	beq		Lxts_enc_no_key2
+
+	?lvsl		$keyperm,0,$key2		# prepare for unaligned key
+	lwz		$rounds,240($key2)
+	srwi		$rounds,$rounds,1
+	subi		$rounds,$rounds,1
+	li		$idx,16
+
+	lvx		$rndkey0,0,$key2
+	lvx		$rndkey1,$idx,$key2
+	addi		$idx,$idx,16
+	?vperm		$rndkey0,$rndkey0,$rndkey1,$keyperm
+	vxor		$tweak,$tweak,$rndkey0
+	lvx		$rndkey0,$idx,$key2
+	addi		$idx,$idx,16
+	mtctr		$rounds
+
+Ltweak_xts_enc:
+	?vperm		$rndkey1,$rndkey1,$rndkey0,$keyperm
+	vcipher		$tweak,$tweak,$rndkey1
+	lvx		$rndkey1,$idx,$key2
+	addi		$idx,$idx,16
+	?vperm		$rndkey0,$rndkey0,$rndkey1,$keyperm
+	vcipher		$tweak,$tweak,$rndkey0
+	lvx		$rndkey0,$idx,$key2
+	addi		$idx,$idx,16
+	bdnz		Ltweak_xts_enc
+
+	?vperm		$rndkey1,$rndkey1,$rndkey0,$keyperm
+	vcipher		$tweak,$tweak,$rndkey1
+	lvx		$rndkey1,$idx,$key2
+	?vperm		$rndkey0,$rndkey0,$rndkey1,$keyperm
+	vcipherlast	$tweak,$tweak,$rndkey0
+
+	li		$ivp,0				# don't chain the tweak
+	b		Lxts_enc
+
+Lxts_enc_no_key2:
+	li		$idx,-16
+	and		$len,$len,$idx			# in "tweak chaining"
+							# mode only complete
+							# blocks are processed
+Lxts_enc:
+	lvx		$inptail,0,$inp
+	addi		$inp,$inp,16
+
+	?lvsl		$keyperm,0,$key1		# prepare for unaligned key
+	lwz		$rounds,240($key1)
+	srwi		$rounds,$rounds,1
+	subi		$rounds,$rounds,1
+	li		$idx,16
+
+	vslb		$eighty7,$seven,$seven		# 0x808080..80
+	vor		$eighty7,$eighty7,$seven	# 0x878787..87
+	vspltisb	$tmp,1				# 0x010101..01
+	vsldoi		$eighty7,$eighty7,$tmp,15	# 0x870101..01
+
+	${UCMP}i	$len,96
+	bge		_aesp8_xts_encrypt6x
+
+	andi.		$taillen,$len,15
+	subic		r0,$len,32
+	subi		$taillen,$taillen,16
+	subfe		r0,r0,r0
+	and		r0,r0,$taillen
+	add		$inp,$inp,r0
+
+	lvx		$rndkey0,0,$key1
+	lvx		$rndkey1,$idx,$key1
+	addi		$idx,$idx,16
+	vperm		$inout,$inout,$inptail,$inpperm
+	?vperm		$rndkey0,$rndkey0,$rndkey1,$keyperm
+	vxor		$inout,$inout,$tweak
+	vxor		$inout,$inout,$rndkey0
+	lvx		$rndkey0,$idx,$key1
+	addi		$idx,$idx,16
+	mtctr		$rounds
+	b		Loop_xts_enc
+
+.align	5
+Loop_xts_enc:
+	?vperm		$rndkey1,$rndkey1,$rndkey0,$keyperm
+	vcipher		$inout,$inout,$rndkey1
+	lvx		$rndkey1,$idx,$key1
+	addi		$idx,$idx,16
+	?vperm		$rndkey0,$rndkey0,$rndkey1,$keyperm
+	vcipher		$inout,$inout,$rndkey0
+	lvx		$rndkey0,$idx,$key1
+	addi		$idx,$idx,16
+	bdnz		Loop_xts_enc
+
+	?vperm		$rndkey1,$rndkey1,$rndkey0,$keyperm
+	vcipher		$inout,$inout,$rndkey1
+	lvx		$rndkey1,$idx,$key1
+	li		$idx,16
+	?vperm		$rndkey0,$rndkey0,$rndkey1,$keyperm
+	vxor		$rndkey0,$rndkey0,$tweak
+	vcipherlast	$output,$inout,$rndkey0
+
+	le?vperm	$tmp,$output,$output,$leperm
+	be?nop
+	le?stvx_u	$tmp,0,$out
+	be?stvx_u	$output,0,$out
+	addi		$out,$out,16
+
+	subic.		$len,$len,16
+	beq		Lxts_enc_done
+
+	vmr		$inout,$inptail
+	lvx		$inptail,0,$inp
+	addi		$inp,$inp,16
+	lvx		$rndkey0,0,$key1
+	lvx		$rndkey1,$idx,$key1
+	addi		$idx,$idx,16
+
+	subic		r0,$len,32
+	subfe		r0,r0,r0
+	and		r0,r0,$taillen
+	add		$inp,$inp,r0
+
+	vsrab		$tmp,$tweak,$seven		# next tweak value
+	vaddubm		$tweak,$tweak,$tweak
+	vsldoi		$tmp,$tmp,$tmp,15
+	vand		$tmp,$tmp,$eighty7
+	vxor		$tweak,$tweak,$tmp
+
+	vperm		$inout,$inout,$inptail,$inpperm
+	?vperm		$rndkey0,$rndkey0,$rndkey1,$keyperm
+	vxor		$inout,$inout,$tweak
+	vxor		$output,$output,$rndkey0	# just in case $len<16
+	vxor		$inout,$inout,$rndkey0
+	lvx		$rndkey0,$idx,$key1
+	addi		$idx,$idx,16
+
+	mtctr		$rounds
+	${UCMP}i	$len,16
+	bge		Loop_xts_enc
+
+	vxor		$output,$output,$tweak
+	lvsr		$inpperm,0,$len			# $inpperm is no longer needed
+	vxor		$inptail,$inptail,$inptail	# $inptail is no longer needed
+	vspltisb	$tmp,-1
+	vperm		$inptail,$inptail,$tmp,$inpperm
+	vsel		$inout,$inout,$output,$inptail
+
+	subi		r11,$out,17
+	subi		$out,$out,16
+	mtctr		$len
+	li		$len,16
+Loop_xts_enc_steal:
+	lbzu		r0,1(r11)
+	stb		r0,16(r11)
+	bdnz		Loop_xts_enc_steal
+
+	mtctr		$rounds
+	b		Loop_xts_enc			# one more time...
+
+Lxts_enc_done:
+	${UCMP}i	$ivp,0
+	beq		Lxts_enc_ret
+
+	vsrab		$tmp,$tweak,$seven		# next tweak value
+	vaddubm		$tweak,$tweak,$tweak
+	vsldoi		$tmp,$tmp,$tmp,15
+	vand		$tmp,$tmp,$eighty7
+	vxor		$tweak,$tweak,$tmp
+
+	le?vperm	$tweak,$tweak,$tweak,$leperm
+	stvx_u		$tweak,0,$ivp
+
+Lxts_enc_ret:
+	mtspr		256,r12				# restore vrsave
+	li		r3,0
+	blr
+	.long		0
+	.byte		0,12,0x04,0,0x80,6,6,0
+	.long		0
+.size	.${prefix}_xts_encrypt,.-.${prefix}_xts_encrypt
+
+.globl	.${prefix}_xts_decrypt
+.align	5
+.${prefix}_xts_decrypt:
+	mr		$inp,r3				# reassign
+	li		r3,-1
+	${UCMP}i	$len,16
+	bltlr-
+
+	lis		r0,0xfff8
+	mfspr		r12,256				# save vrsave
+	li		r11,0
+	mtspr		256,r0
+
+	andi.		r0,$len,15
+	neg		r0,r0
+	andi.		r0,r0,16
+	sub		$len,$len,r0
+
+	vspltisb	$seven,0x07			# 0x070707..07
+	le?lvsl		$leperm,r11,r11
+	le?vspltisb	$tmp,0x0f
+	le?vxor		$leperm,$leperm,$seven
+
+	li		$idx,15
+	lvx		$tweak,0,$ivp			# load [unaligned] iv
+	lvsl		$inpperm,0,$ivp
+	lvx		$inptail,$idx,$ivp
+	le?vxor		$inpperm,$inpperm,$tmp
+	vperm		$tweak,$tweak,$inptail,$inpperm
+
+	neg		r11,$inp
+	lvsr		$inpperm,0,r11			# prepare for unaligned load
+	lvx		$inout,0,$inp
+	addi		$inp,$inp,15			# 15 is not typo
+	le?vxor		$inpperm,$inpperm,$tmp
+
+	${UCMP}i	$key2,0				# key2==NULL?
+	beq		Lxts_dec_no_key2
+
+	?lvsl		$keyperm,0,$key2		# prepare for unaligned key
+	lwz		$rounds,240($key2)
+	srwi		$rounds,$rounds,1
+	subi		$rounds,$rounds,1
+	li		$idx,16
+
+	lvx		$rndkey0,0,$key2
+	lvx		$rndkey1,$idx,$key2
+	addi		$idx,$idx,16
+	?vperm		$rndkey0,$rndkey0,$rndkey1,$keyperm
+	vxor		$tweak,$tweak,$rndkey0
+	lvx		$rndkey0,$idx,$key2
+	addi		$idx,$idx,16
+	mtctr		$rounds
+
+Ltweak_xts_dec:
+	?vperm		$rndkey1,$rndkey1,$rndkey0,$keyperm
+	vcipher		$tweak,$tweak,$rndkey1
+	lvx		$rndkey1,$idx,$key2
+	addi		$idx,$idx,16
+	?vperm		$rndkey0,$rndkey0,$rndkey1,$keyperm
+	vcipher		$tweak,$tweak,$rndkey0
+	lvx		$rndkey0,$idx,$key2
+	addi		$idx,$idx,16
+	bdnz		Ltweak_xts_dec
+
+	?vperm		$rndkey1,$rndkey1,$rndkey0,$keyperm
+	vcipher		$tweak,$tweak,$rndkey1
+	lvx		$rndkey1,$idx,$key2
+	?vperm		$rndkey0,$rndkey0,$rndkey1,$keyperm
+	vcipherlast	$tweak,$tweak,$rndkey0
+
+	li		$ivp,0				# don't chain the tweak
+	b		Lxts_dec
+
+Lxts_dec_no_key2:
+	neg		$idx,$len
+	andi.		$idx,$idx,15
+	add		$len,$len,$idx			# in "tweak chaining"
+							# mode only complete
+							# blocks are processed
+Lxts_dec:
+	lvx		$inptail,0,$inp
+	addi		$inp,$inp,16
+
+	?lvsl		$keyperm,0,$key1		# prepare for unaligned key
+	lwz		$rounds,240($key1)
+	srwi		$rounds,$rounds,1
+	subi		$rounds,$rounds,1
+	li		$idx,16
+
+	vslb		$eighty7,$seven,$seven		# 0x808080..80
+	vor		$eighty7,$eighty7,$seven	# 0x878787..87
+	vspltisb	$tmp,1				# 0x010101..01
+	vsldoi		$eighty7,$eighty7,$tmp,15	# 0x870101..01
+
+	${UCMP}i	$len,96
+	bge		_aesp8_xts_decrypt6x
+
+	lvx		$rndkey0,0,$key1
+	lvx		$rndkey1,$idx,$key1
+	addi		$idx,$idx,16
+	vperm		$inout,$inout,$inptail,$inpperm
+	?vperm		$rndkey0,$rndkey0,$rndkey1,$keyperm
+	vxor		$inout,$inout,$tweak
+	vxor		$inout,$inout,$rndkey0
+	lvx		$rndkey0,$idx,$key1
+	addi		$idx,$idx,16
+	mtctr		$rounds
+
+	${UCMP}i	$len,16
+	blt		Ltail_xts_dec
+	be?b		Loop_xts_dec
+
+.align	5
+Loop_xts_dec:
+	?vperm		$rndkey1,$rndkey1,$rndkey0,$keyperm
+	vncipher	$inout,$inout,$rndkey1
+	lvx		$rndkey1,$idx,$key1
+	addi		$idx,$idx,16
+	?vperm		$rndkey0,$rndkey0,$rndkey1,$keyperm
+	vncipher	$inout,$inout,$rndkey0
+	lvx		$rndkey0,$idx,$key1
+	addi		$idx,$idx,16
+	bdnz		Loop_xts_dec
+
+	?vperm		$rndkey1,$rndkey1,$rndkey0,$keyperm
+	vncipher	$inout,$inout,$rndkey1
+	lvx		$rndkey1,$idx,$key1
+	li		$idx,16
+	?vperm		$rndkey0,$rndkey0,$rndkey1,$keyperm
+	vxor		$rndkey0,$rndkey0,$tweak
+	vncipherlast	$output,$inout,$rndkey0
+
+	le?vperm	$tmp,$output,$output,$leperm
+	be?nop
+	le?stvx_u	$tmp,0,$out
+	be?stvx_u	$output,0,$out
+	addi		$out,$out,16
+
+	subic.		$len,$len,16
+	beq		Lxts_dec_done
+
+	vmr		$inout,$inptail
+	lvx		$inptail,0,$inp
+	addi		$inp,$inp,16
+	lvx		$rndkey0,0,$key1
+	lvx		$rndkey1,$idx,$key1
+	addi		$idx,$idx,16
+
+	vsrab		$tmp,$tweak,$seven		# next tweak value
+	vaddubm		$tweak,$tweak,$tweak
+	vsldoi		$tmp,$tmp,$tmp,15
+	vand		$tmp,$tmp,$eighty7
+	vxor		$tweak,$tweak,$tmp
+
+	vperm		$inout,$inout,$inptail,$inpperm
+	?vperm		$rndkey0,$rndkey0,$rndkey1,$keyperm
+	vxor		$inout,$inout,$tweak
+	vxor		$inout,$inout,$rndkey0
+	lvx		$rndkey0,$idx,$key1
+	addi		$idx,$idx,16
+
+	mtctr		$rounds
+	${UCMP}i	$len,16
+	bge		Loop_xts_dec
+
+Ltail_xts_dec:
+	vsrab		$tmp,$tweak,$seven		# next tweak value
+	vaddubm		$tweak1,$tweak,$tweak
+	vsldoi		$tmp,$tmp,$tmp,15
+	vand		$tmp,$tmp,$eighty7
+	vxor		$tweak1,$tweak1,$tmp
+
+	subi		$inp,$inp,16
+	add		$inp,$inp,$len
+
+	vxor		$inout,$inout,$tweak		# :-(
+	vxor		$inout,$inout,$tweak1		# :-)
+
+Loop_xts_dec_short:
+	?vperm		$rndkey1,$rndkey1,$rndkey0,$keyperm
+	vncipher	$inout,$inout,$rndkey1
+	lvx		$rndkey1,$idx,$key1
+	addi		$idx,$idx,16
+	?vperm		$rndkey0,$rndkey0,$rndkey1,$keyperm
+	vncipher	$inout,$inout,$rndkey0
+	lvx		$rndkey0,$idx,$key1
+	addi		$idx,$idx,16
+	bdnz		Loop_xts_dec_short
+
+	?vperm		$rndkey1,$rndkey1,$rndkey0,$keyperm
+	vncipher	$inout,$inout,$rndkey1
+	lvx		$rndkey1,$idx,$key1
+	li		$idx,16
+	?vperm		$rndkey0,$rndkey0,$rndkey1,$keyperm
+	vxor		$rndkey0,$rndkey0,$tweak1
+	vncipherlast	$output,$inout,$rndkey0
+
+	le?vperm	$tmp,$output,$output,$leperm
+	be?nop
+	le?stvx_u	$tmp,0,$out
+	be?stvx_u	$output,0,$out
+
+	vmr		$inout,$inptail
+	lvx		$inptail,0,$inp
+	#addi		$inp,$inp,16
+	lvx		$rndkey0,0,$key1
+	lvx		$rndkey1,$idx,$key1
+	addi		$idx,$idx,16
+	vperm		$inout,$inout,$inptail,$inpperm
+	?vperm		$rndkey0,$rndkey0,$rndkey1,$keyperm
+
+	lvsr		$inpperm,0,$len			# $inpperm is no longer needed
+	vxor		$inptail,$inptail,$inptail	# $inptail is no longer needed
+	vspltisb	$tmp,-1
+	vperm		$inptail,$inptail,$tmp,$inpperm
+	vsel		$inout,$inout,$output,$inptail
+
+	vxor		$rndkey0,$rndkey0,$tweak
+	vxor		$inout,$inout,$rndkey0
+	lvx		$rndkey0,$idx,$key1
+	addi		$idx,$idx,16
+
+	subi		r11,$out,1
+	mtctr		$len
+	li		$len,16
+Loop_xts_dec_steal:
+	lbzu		r0,1(r11)
+	stb		r0,16(r11)
+	bdnz		Loop_xts_dec_steal
+
+	mtctr		$rounds
+	b		Loop_xts_dec			# one more time...
+
+Lxts_dec_done:
+	${UCMP}i	$ivp,0
+	beq		Lxts_dec_ret
+
+	vsrab		$tmp,$tweak,$seven		# next tweak value
+	vaddubm		$tweak,$tweak,$tweak
+	vsldoi		$tmp,$tmp,$tmp,15
+	vand		$tmp,$tmp,$eighty7
+	vxor		$tweak,$tweak,$tmp
+
+	le?vperm	$tweak,$tweak,$tweak,$leperm
+	stvx_u		$tweak,0,$ivp
+
+Lxts_dec_ret:
+	mtspr		256,r12				# restore vrsave
+	li		r3,0
+	blr
+	.long		0
+	.byte		0,12,0x04,0,0x80,6,6,0
+	.long		0
+.size	.${prefix}_xts_decrypt,.-.${prefix}_xts_decrypt
+___
+#########################################################################
+{{	# Optimized XTS procedures					#
+my $key_=$key2;
+my ($x00,$x10,$x20,$x30,$x40,$x50,$x60,$x70)=map("r$_",(0,3,26..31));
+    $x00=0 if ($flavour =~ /osx/);
+my ($in0,  $in1,  $in2,  $in3,  $in4,  $in5 )=map("v$_",(0..5));
+my ($out0, $out1, $out2, $out3, $out4, $out5)=map("v$_",(7,12..16));
+my ($twk0, $twk1, $twk2, $twk3, $twk4, $twk5)=map("v$_",(17..22));
+my $rndkey0="v23";	# v24-v25 rotating buffer for first found keys
+			# v26-v31 last 6 round keys
+my ($keyperm)=($out0);	# aliases with "caller", redundant assignment
+my $taillen=$x70;
+
+$code.=<<___;
+.align	5
+_aesp8_xts_encrypt6x:
+	$STU		$sp,-`($FRAME+21*16+6*$SIZE_T)`($sp)
+	mflr		r11
+	li		r7,`$FRAME+8*16+15`
+	li		r3,`$FRAME+8*16+31`
+	$PUSH		r11,`$FRAME+21*16+6*$SIZE_T+$LRSAVE`($sp)
+	stvx		v20,r7,$sp		# ABI says so
+	addi		r7,r7,32
+	stvx		v21,r3,$sp
+	addi		r3,r3,32
+	stvx		v22,r7,$sp
+	addi		r7,r7,32
+	stvx		v23,r3,$sp
+	addi		r3,r3,32
+	stvx		v24,r7,$sp
+	addi		r7,r7,32
+	stvx		v25,r3,$sp
+	addi		r3,r3,32
+	stvx		v26,r7,$sp
+	addi		r7,r7,32
+	stvx		v27,r3,$sp
+	addi		r3,r3,32
+	stvx		v28,r7,$sp
+	addi		r7,r7,32
+	stvx		v29,r3,$sp
+	addi		r3,r3,32
+	stvx		v30,r7,$sp
+	stvx		v31,r3,$sp
+	li		r0,-1
+	stw		$vrsave,`$FRAME+21*16-4`($sp)	# save vrsave
+	li		$x10,0x10
+	$PUSH		r26,`$FRAME+21*16+0*$SIZE_T`($sp)
+	li		$x20,0x20
+	$PUSH		r27,`$FRAME+21*16+1*$SIZE_T`($sp)
+	li		$x30,0x30
+	$PUSH		r28,`$FRAME+21*16+2*$SIZE_T`($sp)
+	li		$x40,0x40
+	$PUSH		r29,`$FRAME+21*16+3*$SIZE_T`($sp)
+	li		$x50,0x50
+	$PUSH		r30,`$FRAME+21*16+4*$SIZE_T`($sp)
+	li		$x60,0x60
+	$PUSH		r31,`$FRAME+21*16+5*$SIZE_T`($sp)
+	li		$x70,0x70
+	mtspr		256,r0
+
+	subi		$rounds,$rounds,3	# -4 in total
+
+	lvx		$rndkey0,$x00,$key1	# load key schedule
+	lvx		v30,$x10,$key1
+	addi		$key1,$key1,0x20
+	lvx		v31,$x00,$key1
+	?vperm		$rndkey0,$rndkey0,v30,$keyperm
+	addi		$key_,$sp,$FRAME+15
+	mtctr		$rounds
+
+Load_xts_enc_key:
+	?vperm		v24,v30,v31,$keyperm
+	lvx		v30,$x10,$key1
+	addi		$key1,$key1,0x20
+	stvx		v24,$x00,$key_		# off-load round[1]
+	?vperm		v25,v31,v30,$keyperm
+	lvx		v31,$x00,$key1
+	stvx		v25,$x10,$key_		# off-load round[2]
+	addi		$key_,$key_,0x20
+	bdnz		Load_xts_enc_key
+
+	lvx		v26,$x10,$key1
+	?vperm		v24,v30,v31,$keyperm
+	lvx		v27,$x20,$key1
+	stvx		v24,$x00,$key_		# off-load round[3]
+	?vperm		v25,v31,v26,$keyperm
+	lvx		v28,$x30,$key1
+	stvx		v25,$x10,$key_		# off-load round[4]
+	addi		$key_,$sp,$FRAME+15	# rewind $key_
+	?vperm		v26,v26,v27,$keyperm
+	lvx		v29,$x40,$key1
+	?vperm		v27,v27,v28,$keyperm
+	lvx		v30,$x50,$key1
+	?vperm		v28,v28,v29,$keyperm
+	lvx		v31,$x60,$key1
+	?vperm		v29,v29,v30,$keyperm
+	lvx		$twk5,$x70,$key1	# borrow $twk5
+	?vperm		v30,v30,v31,$keyperm
+	lvx		v24,$x00,$key_		# pre-load round[1]
+	?vperm		v31,v31,$twk5,$keyperm
+	lvx		v25,$x10,$key_		# pre-load round[2]
+
+	 vperm		$in0,$inout,$inptail,$inpperm
+	 subi		$inp,$inp,31		# undo "caller"
+	vxor		$twk0,$tweak,$rndkey0
+	vsrab		$tmp,$tweak,$seven	# next tweak value
+	vaddubm		$tweak,$tweak,$tweak
+	vsldoi		$tmp,$tmp,$tmp,15
+	vand		$tmp,$tmp,$eighty7
+	 vxor		$out0,$in0,$twk0
+	vxor		$tweak,$tweak,$tmp
+
+	 lvx_u		$in1,$x10,$inp
+	vxor		$twk1,$tweak,$rndkey0
+	vsrab		$tmp,$tweak,$seven	# next tweak value
+	vaddubm		$tweak,$tweak,$tweak
+	vsldoi		$tmp,$tmp,$tmp,15
+	 le?vperm	$in1,$in1,$in1,$leperm
+	vand		$tmp,$tmp,$eighty7
+	 vxor		$out1,$in1,$twk1
+	vxor		$tweak,$tweak,$tmp
+
+	 lvx_u		$in2,$x20,$inp
+	 andi.		$taillen,$len,15
+	vxor		$twk2,$tweak,$rndkey0
+	vsrab		$tmp,$tweak,$seven	# next tweak value
+	vaddubm		$tweak,$tweak,$tweak
+	vsldoi		$tmp,$tmp,$tmp,15
+	 le?vperm	$in2,$in2,$in2,$leperm
+	vand		$tmp,$tmp,$eighty7
+	 vxor		$out2,$in2,$twk2
+	vxor		$tweak,$tweak,$tmp
+
+	 lvx_u		$in3,$x30,$inp
+	 sub		$len,$len,$taillen
+	vxor		$twk3,$tweak,$rndkey0
+	vsrab		$tmp,$tweak,$seven	# next tweak value
+	vaddubm		$tweak,$tweak,$tweak
+	vsldoi		$tmp,$tmp,$tmp,15
+	 le?vperm	$in3,$in3,$in3,$leperm
+	vand		$tmp,$tmp,$eighty7
+	 vxor		$out3,$in3,$twk3
+	vxor		$tweak,$tweak,$tmp
+
+	 lvx_u		$in4,$x40,$inp
+	 subi		$len,$len,0x60
+	vxor		$twk4,$tweak,$rndkey0
+	vsrab		$tmp,$tweak,$seven	# next tweak value
+	vaddubm		$tweak,$tweak,$tweak
+	vsldoi		$tmp,$tmp,$tmp,15
+	 le?vperm	$in4,$in4,$in4,$leperm
+	vand		$tmp,$tmp,$eighty7
+	 vxor		$out4,$in4,$twk4
+	vxor		$tweak,$tweak,$tmp
+
+	 lvx_u		$in5,$x50,$inp
+	 addi		$inp,$inp,0x60
+	vxor		$twk5,$tweak,$rndkey0
+	vsrab		$tmp,$tweak,$seven	# next tweak value
+	vaddubm		$tweak,$tweak,$tweak
+	vsldoi		$tmp,$tmp,$tmp,15
+	 le?vperm	$in5,$in5,$in5,$leperm
+	vand		$tmp,$tmp,$eighty7
+	 vxor		$out5,$in5,$twk5
+	vxor		$tweak,$tweak,$tmp
+
+	vxor		v31,v31,$rndkey0
+	mtctr		$rounds
+	b		Loop_xts_enc6x
+
+.align	5
+Loop_xts_enc6x:
+	vcipher		$out0,$out0,v24
+	vcipher		$out1,$out1,v24
+	vcipher		$out2,$out2,v24
+	vcipher		$out3,$out3,v24
+	vcipher		$out4,$out4,v24
+	vcipher		$out5,$out5,v24
+	lvx		v24,$x20,$key_		# round[3]
+	addi		$key_,$key_,0x20
+
+	vcipher		$out0,$out0,v25
+	vcipher		$out1,$out1,v25
+	vcipher		$out2,$out2,v25
+	vcipher		$out3,$out3,v25
+	vcipher		$out4,$out4,v25
+	vcipher		$out5,$out5,v25
+	lvx		v25,$x10,$key_		# round[4]
+	bdnz		Loop_xts_enc6x
+
+	subic		$len,$len,96		# $len-=96
+	 vxor		$in0,$twk0,v31		# xor with last round key
+	vcipher		$out0,$out0,v24
+	vcipher		$out1,$out1,v24
+	 vsrab		$tmp,$tweak,$seven	# next tweak value
+	 vxor		$twk0,$tweak,$rndkey0
+	 vaddubm	$tweak,$tweak,$tweak
+	vcipher		$out2,$out2,v24
+	vcipher		$out3,$out3,v24
+	 vsldoi		$tmp,$tmp,$tmp,15
+	vcipher		$out4,$out4,v24
+	vcipher		$out5,$out5,v24
+
+	subfe.		r0,r0,r0		# borrow?-1:0
+	 vand		$tmp,$tmp,$eighty7
+	vcipher		$out0,$out0,v25
+	vcipher		$out1,$out1,v25
+	 vxor		$tweak,$tweak,$tmp
+	vcipher		$out2,$out2,v25
+	vcipher		$out3,$out3,v25
+	 vxor		$in1,$twk1,v31
+	 vsrab		$tmp,$tweak,$seven	# next tweak value
+	 vxor		$twk1,$tweak,$rndkey0
+	vcipher		$out4,$out4,v25
+	vcipher		$out5,$out5,v25
+
+	and		r0,r0,$len
+	 vaddubm	$tweak,$tweak,$tweak
+	 vsldoi		$tmp,$tmp,$tmp,15
+	vcipher		$out0,$out0,v26
+	vcipher		$out1,$out1,v26
+	 vand		$tmp,$tmp,$eighty7
+	vcipher		$out2,$out2,v26
+	vcipher		$out3,$out3,v26
+	 vxor		$tweak,$tweak,$tmp
+	vcipher		$out4,$out4,v26
+	vcipher		$out5,$out5,v26
+
+	add		$inp,$inp,r0		# $inp is adjusted in such
+						# way that at exit from the
+						# loop inX-in5 are loaded
+						# with last "words"
+	 vxor		$in2,$twk2,v31
+	 vsrab		$tmp,$tweak,$seven	# next tweak value
+	 vxor		$twk2,$tweak,$rndkey0
+	 vaddubm	$tweak,$tweak,$tweak
+	vcipher		$out0,$out0,v27
+	vcipher		$out1,$out1,v27
+	 vsldoi		$tmp,$tmp,$tmp,15
+	vcipher		$out2,$out2,v27
+	vcipher		$out3,$out3,v27
+	 vand		$tmp,$tmp,$eighty7
+	vcipher		$out4,$out4,v27
+	vcipher		$out5,$out5,v27
+
+	addi		$key_,$sp,$FRAME+15	# rewind $key_
+	 vxor		$tweak,$tweak,$tmp
+	vcipher		$out0,$out0,v28
+	vcipher		$out1,$out1,v28
+	 vxor		$in3,$twk3,v31
+	 vsrab		$tmp,$tweak,$seven	# next tweak value
+	 vxor		$twk3,$tweak,$rndkey0
+	vcipher		$out2,$out2,v28
+	vcipher		$out3,$out3,v28
+	 vaddubm	$tweak,$tweak,$tweak
+	 vsldoi		$tmp,$tmp,$tmp,15
+	vcipher		$out4,$out4,v28
+	vcipher		$out5,$out5,v28
+	lvx		v24,$x00,$key_		# re-pre-load round[1]
+	 vand		$tmp,$tmp,$eighty7
+
+	vcipher		$out0,$out0,v29
+	vcipher		$out1,$out1,v29
+	 vxor		$tweak,$tweak,$tmp
+	vcipher		$out2,$out2,v29
+	vcipher		$out3,$out3,v29
+	 vxor		$in4,$twk4,v31
+	 vsrab		$tmp,$tweak,$seven	# next tweak value
+	 vxor		$twk4,$tweak,$rndkey0
+	vcipher		$out4,$out4,v29
+	vcipher		$out5,$out5,v29
+	lvx		v25,$x10,$key_		# re-pre-load round[2]
+	 vaddubm	$tweak,$tweak,$tweak
+	 vsldoi		$tmp,$tmp,$tmp,15
+
+	vcipher		$out0,$out0,v30
+	vcipher		$out1,$out1,v30
+	 vand		$tmp,$tmp,$eighty7
+	vcipher		$out2,$out2,v30
+	vcipher		$out3,$out3,v30
+	 vxor		$tweak,$tweak,$tmp
+	vcipher		$out4,$out4,v30
+	vcipher		$out5,$out5,v30
+	 vxor		$in5,$twk5,v31
+	 vsrab		$tmp,$tweak,$seven	# next tweak value
+	 vxor		$twk5,$tweak,$rndkey0
+
+	vcipherlast	$out0,$out0,$in0
+	 lvx_u		$in0,$x00,$inp		# load next input block
+	 vaddubm	$tweak,$tweak,$tweak
+	 vsldoi		$tmp,$tmp,$tmp,15
+	vcipherlast	$out1,$out1,$in1
+	 lvx_u		$in1,$x10,$inp
+	vcipherlast	$out2,$out2,$in2
+	 le?vperm	$in0,$in0,$in0,$leperm
+	 lvx_u		$in2,$x20,$inp
+	 vand		$tmp,$tmp,$eighty7
+	vcipherlast	$out3,$out3,$in3
+	 le?vperm	$in1,$in1,$in1,$leperm
+	 lvx_u		$in3,$x30,$inp
+	vcipherlast	$out4,$out4,$in4
+	 le?vperm	$in2,$in2,$in2,$leperm
+	 lvx_u		$in4,$x40,$inp
+	 vxor		$tweak,$tweak,$tmp
+	vcipherlast	$tmp,$out5,$in5		# last block might be needed
+						# in stealing mode
+	 le?vperm	$in3,$in3,$in3,$leperm
+	 lvx_u		$in5,$x50,$inp
+	 addi		$inp,$inp,0x60
+	 le?vperm	$in4,$in4,$in4,$leperm
+	 le?vperm	$in5,$in5,$in5,$leperm
+
+	le?vperm	$out0,$out0,$out0,$leperm
+	le?vperm	$out1,$out1,$out1,$leperm
+	stvx_u		$out0,$x00,$out		# store output
+	 vxor		$out0,$in0,$twk0
+	le?vperm	$out2,$out2,$out2,$leperm
+	stvx_u		$out1,$x10,$out
+	 vxor		$out1,$in1,$twk1
+	le?vperm	$out3,$out3,$out3,$leperm
+	stvx_u		$out2,$x20,$out
+	 vxor		$out2,$in2,$twk2
+	le?vperm	$out4,$out4,$out4,$leperm
+	stvx_u		$out3,$x30,$out
+	 vxor		$out3,$in3,$twk3
+	le?vperm	$out5,$tmp,$tmp,$leperm
+	stvx_u		$out4,$x40,$out
+	 vxor		$out4,$in4,$twk4
+	le?stvx_u	$out5,$x50,$out
+	be?stvx_u	$tmp, $x50,$out
+	 vxor		$out5,$in5,$twk5
+	addi		$out,$out,0x60
+
+	mtctr		$rounds
+	beq		Loop_xts_enc6x		# did $len-=96 borrow?
+
+	addic.		$len,$len,0x60
+	beq		Lxts_enc6x_zero
+	cmpwi		$len,0x20
+	blt		Lxts_enc6x_one
+	nop
+	beq		Lxts_enc6x_two
+	cmpwi		$len,0x40
+	blt		Lxts_enc6x_three
+	nop
+	beq		Lxts_enc6x_four
+
+Lxts_enc6x_five:
+	vxor		$out0,$in1,$twk0
+	vxor		$out1,$in2,$twk1
+	vxor		$out2,$in3,$twk2
+	vxor		$out3,$in4,$twk3
+	vxor		$out4,$in5,$twk4
+
+	bl		_aesp8_xts_enc5x
+
+	le?vperm	$out0,$out0,$out0,$leperm
+	vmr		$twk0,$twk5		# unused tweak
+	le?vperm	$out1,$out1,$out1,$leperm
+	stvx_u		$out0,$x00,$out		# store output
+	le?vperm	$out2,$out2,$out2,$leperm
+	stvx_u		$out1,$x10,$out
+	le?vperm	$out3,$out3,$out3,$leperm
+	stvx_u		$out2,$x20,$out
+	vxor		$tmp,$out4,$twk5	# last block prep for stealing
+	le?vperm	$out4,$out4,$out4,$leperm
+	stvx_u		$out3,$x30,$out
+	stvx_u		$out4,$x40,$out
+	addi		$out,$out,0x50
+	bne		Lxts_enc6x_steal
+	b		Lxts_enc6x_done
+
+.align	4
+Lxts_enc6x_four:
+	vxor		$out0,$in2,$twk0
+	vxor		$out1,$in3,$twk1
+	vxor		$out2,$in4,$twk2
+	vxor		$out3,$in5,$twk3
+	vxor		$out4,$out4,$out4
+
+	bl		_aesp8_xts_enc5x
+
+	le?vperm	$out0,$out0,$out0,$leperm
+	vmr		$twk0,$twk4		# unused tweak
+	le?vperm	$out1,$out1,$out1,$leperm
+	stvx_u		$out0,$x00,$out		# store output
+	le?vperm	$out2,$out2,$out2,$leperm
+	stvx_u		$out1,$x10,$out
+	vxor		$tmp,$out3,$twk4	# last block prep for stealing
+	le?vperm	$out3,$out3,$out3,$leperm
+	stvx_u		$out2,$x20,$out
+	stvx_u		$out3,$x30,$out
+	addi		$out,$out,0x40
+	bne		Lxts_enc6x_steal
+	b		Lxts_enc6x_done
+
+.align	4
+Lxts_enc6x_three:
+	vxor		$out0,$in3,$twk0
+	vxor		$out1,$in4,$twk1
+	vxor		$out2,$in5,$twk2
+	vxor		$out3,$out3,$out3
+	vxor		$out4,$out4,$out4
+
+	bl		_aesp8_xts_enc5x
+
+	le?vperm	$out0,$out0,$out0,$leperm
+	vmr		$twk0,$twk3		# unused tweak
+	le?vperm	$out1,$out1,$out1,$leperm
+	stvx_u		$out0,$x00,$out		# store output
+	vxor		$tmp,$out2,$twk3	# last block prep for stealing
+	le?vperm	$out2,$out2,$out2,$leperm
+	stvx_u		$out1,$x10,$out
+	stvx_u		$out2,$x20,$out
+	addi		$out,$out,0x30
+	bne		Lxts_enc6x_steal
+	b		Lxts_enc6x_done
+
+.align	4
+Lxts_enc6x_two:
+	vxor		$out0,$in4,$twk0
+	vxor		$out1,$in5,$twk1
+	vxor		$out2,$out2,$out2
+	vxor		$out3,$out3,$out3
+	vxor		$out4,$out4,$out4
+
+	bl		_aesp8_xts_enc5x
+
+	le?vperm	$out0,$out0,$out0,$leperm
+	vmr		$twk0,$twk2		# unused tweak
+	vxor		$tmp,$out1,$twk2	# last block prep for stealing
+	le?vperm	$out1,$out1,$out1,$leperm
+	stvx_u		$out0,$x00,$out		# store output
+	stvx_u		$out1,$x10,$out
+	addi		$out,$out,0x20
+	bne		Lxts_enc6x_steal
+	b		Lxts_enc6x_done
+
+.align	4
+Lxts_enc6x_one:
+	vxor		$out0,$in5,$twk0
+	nop
+Loop_xts_enc1x:
+	vcipher		$out0,$out0,v24
+	lvx		v24,$x20,$key_		# round[3]
+	addi		$key_,$key_,0x20
+
+	vcipher		$out0,$out0,v25
+	lvx		v25,$x10,$key_		# round[4]
+	bdnz		Loop_xts_enc1x
+
+	add		$inp,$inp,$taillen
+	cmpwi		$taillen,0
+	vcipher		$out0,$out0,v24
+
+	subi		$inp,$inp,16
+	vcipher		$out0,$out0,v25
+
+	lvsr		$inpperm,0,$taillen
+	vcipher		$out0,$out0,v26
+
+	lvx_u		$in0,0,$inp
+	vcipher		$out0,$out0,v27
+
+	addi		$key_,$sp,$FRAME+15	# rewind $key_
+	vcipher		$out0,$out0,v28
+	lvx		v24,$x00,$key_		# re-pre-load round[1]
+
+	vcipher		$out0,$out0,v29
+	lvx		v25,$x10,$key_		# re-pre-load round[2]
+	 vxor		$twk0,$twk0,v31
+
+	le?vperm	$in0,$in0,$in0,$leperm
+	vcipher		$out0,$out0,v30
+
+	vperm		$in0,$in0,$in0,$inpperm
+	vcipherlast	$out0,$out0,$twk0
+
+	vmr		$twk0,$twk1		# unused tweak
+	vxor		$tmp,$out0,$twk1	# last block prep for stealing
+	le?vperm	$out0,$out0,$out0,$leperm
+	stvx_u		$out0,$x00,$out		# store output
+	addi		$out,$out,0x10
+	bne		Lxts_enc6x_steal
+	b		Lxts_enc6x_done
+
+.align	4
+Lxts_enc6x_zero:
+	cmpwi		$taillen,0
+	beq		Lxts_enc6x_done
+
+	add		$inp,$inp,$taillen
+	subi		$inp,$inp,16
+	lvx_u		$in0,0,$inp
+	lvsr		$inpperm,0,$taillen	# $in5 is no more
+	le?vperm	$in0,$in0,$in0,$leperm
+	vperm		$in0,$in0,$in0,$inpperm
+	vxor		$tmp,$tmp,$twk0
+Lxts_enc6x_steal:
+	vxor		$in0,$in0,$twk0
+	vxor		$out0,$out0,$out0
+	vspltisb	$out1,-1
+	vperm		$out0,$out0,$out1,$inpperm
+	vsel		$out0,$in0,$tmp,$out0	# $tmp is last block, remember?
+
+	subi		r30,$out,17
+	subi		$out,$out,16
+	mtctr		$taillen
+Loop_xts_enc6x_steal:
+	lbzu		r0,1(r30)
+	stb		r0,16(r30)
+	bdnz		Loop_xts_enc6x_steal
+
+	li		$taillen,0
+	mtctr		$rounds
+	b		Loop_xts_enc1x		# one more time...
+
+.align	4
+Lxts_enc6x_done:
+	${UCMP}i	$ivp,0
+	beq		Lxts_enc6x_ret
+
+	vxor		$tweak,$twk0,$rndkey0
+	le?vperm	$tweak,$tweak,$tweak,$leperm
+	stvx_u		$tweak,0,$ivp
+
+Lxts_enc6x_ret:
+	mtlr		r11
+	li		r10,`$FRAME+15`
+	li		r11,`$FRAME+31`
+	stvx		$seven,r10,$sp		# wipe copies of round keys
+	addi		r10,r10,32
+	stvx		$seven,r11,$sp
+	addi		r11,r11,32
+	stvx		$seven,r10,$sp
+	addi		r10,r10,32
+	stvx		$seven,r11,$sp
+	addi		r11,r11,32
+	stvx		$seven,r10,$sp
+	addi		r10,r10,32
+	stvx		$seven,r11,$sp
+	addi		r11,r11,32
+	stvx		$seven,r10,$sp
+	addi		r10,r10,32
+	stvx		$seven,r11,$sp
+	addi		r11,r11,32
+
+	mtspr		256,$vrsave
+	lvx		v20,r10,$sp		# ABI says so
+	addi		r10,r10,32
+	lvx		v21,r11,$sp
+	addi		r11,r11,32
+	lvx		v22,r10,$sp
+	addi		r10,r10,32
+	lvx		v23,r11,$sp
+	addi		r11,r11,32
+	lvx		v24,r10,$sp
+	addi		r10,r10,32
+	lvx		v25,r11,$sp
+	addi		r11,r11,32
+	lvx		v26,r10,$sp
+	addi		r10,r10,32
+	lvx		v27,r11,$sp
+	addi		r11,r11,32
+	lvx		v28,r10,$sp
+	addi		r10,r10,32
+	lvx		v29,r11,$sp
+	addi		r11,r11,32
+	lvx		v30,r10,$sp
+	lvx		v31,r11,$sp
+	$POP		r26,`$FRAME+21*16+0*$SIZE_T`($sp)
+	$POP		r27,`$FRAME+21*16+1*$SIZE_T`($sp)
+	$POP		r28,`$FRAME+21*16+2*$SIZE_T`($sp)
+	$POP		r29,`$FRAME+21*16+3*$SIZE_T`($sp)
+	$POP		r30,`$FRAME+21*16+4*$SIZE_T`($sp)
+	$POP		r31,`$FRAME+21*16+5*$SIZE_T`($sp)
+	addi		$sp,$sp,`$FRAME+21*16+6*$SIZE_T`
+	blr
+	.long		0
+	.byte		0,12,0x04,1,0x80,6,6,0
+	.long		0
+
+.align	5
+_aesp8_xts_enc5x:
+	vcipher		$out0,$out0,v24
+	vcipher		$out1,$out1,v24
+	vcipher		$out2,$out2,v24
+	vcipher		$out3,$out3,v24
+	vcipher		$out4,$out4,v24
+	lvx		v24,$x20,$key_		# round[3]
+	addi		$key_,$key_,0x20
+
+	vcipher		$out0,$out0,v25
+	vcipher		$out1,$out1,v25
+	vcipher		$out2,$out2,v25
+	vcipher		$out3,$out3,v25
+	vcipher		$out4,$out4,v25
+	lvx		v25,$x10,$key_		# round[4]
+	bdnz		_aesp8_xts_enc5x
+
+	add		$inp,$inp,$taillen
+	cmpwi		$taillen,0
+	vcipher		$out0,$out0,v24
+	vcipher		$out1,$out1,v24
+	vcipher		$out2,$out2,v24
+	vcipher		$out3,$out3,v24
+	vcipher		$out4,$out4,v24
+
+	subi		$inp,$inp,16
+	vcipher		$out0,$out0,v25
+	vcipher		$out1,$out1,v25
+	vcipher		$out2,$out2,v25
+	vcipher		$out3,$out3,v25
+	vcipher		$out4,$out4,v25
+	 vxor		$twk0,$twk0,v31
+
+	vcipher		$out0,$out0,v26
+	lvsr		$inpperm,0,$taillen	# $in5 is no more
+	vcipher		$out1,$out1,v26
+	vcipher		$out2,$out2,v26
+	vcipher		$out3,$out3,v26
+	vcipher		$out4,$out4,v26
+	 vxor		$in1,$twk1,v31
+
+	vcipher		$out0,$out0,v27
+	lvx_u		$in0,0,$inp
+	vcipher		$out1,$out1,v27
+	vcipher		$out2,$out2,v27
+	vcipher		$out3,$out3,v27
+	vcipher		$out4,$out4,v27
+	 vxor		$in2,$twk2,v31
+
+	addi		$key_,$sp,$FRAME+15	# rewind $key_
+	vcipher		$out0,$out0,v28
+	vcipher		$out1,$out1,v28
+	vcipher		$out2,$out2,v28
+	vcipher		$out3,$out3,v28
+	vcipher		$out4,$out4,v28
+	lvx		v24,$x00,$key_		# re-pre-load round[1]
+	 vxor		$in3,$twk3,v31
+
+	vcipher		$out0,$out0,v29
+	le?vperm	$in0,$in0,$in0,$leperm
+	vcipher		$out1,$out1,v29
+	vcipher		$out2,$out2,v29
+	vcipher		$out3,$out3,v29
+	vcipher		$out4,$out4,v29
+	lvx		v25,$x10,$key_		# re-pre-load round[2]
+	 vxor		$in4,$twk4,v31
+
+	vcipher		$out0,$out0,v30
+	vperm		$in0,$in0,$in0,$inpperm
+	vcipher		$out1,$out1,v30
+	vcipher		$out2,$out2,v30
+	vcipher		$out3,$out3,v30
+	vcipher		$out4,$out4,v30
+
+	vcipherlast	$out0,$out0,$twk0
+	vcipherlast	$out1,$out1,$in1
+	vcipherlast	$out2,$out2,$in2
+	vcipherlast	$out3,$out3,$in3
+	vcipherlast	$out4,$out4,$in4
+	blr
+        .long   	0
+        .byte   	0,12,0x14,0,0,0,0,0
+
+.align	5
+_aesp8_xts_decrypt6x:
+	$STU		$sp,-`($FRAME+21*16+6*$SIZE_T)`($sp)
+	mflr		r11
+	li		r7,`$FRAME+8*16+15`
+	li		r3,`$FRAME+8*16+31`
+	$PUSH		r11,`$FRAME+21*16+6*$SIZE_T+$LRSAVE`($sp)
+	stvx		v20,r7,$sp		# ABI says so
+	addi		r7,r7,32
+	stvx		v21,r3,$sp
+	addi		r3,r3,32
+	stvx		v22,r7,$sp
+	addi		r7,r7,32
+	stvx		v23,r3,$sp
+	addi		r3,r3,32
+	stvx		v24,r7,$sp
+	addi		r7,r7,32
+	stvx		v25,r3,$sp
+	addi		r3,r3,32
+	stvx		v26,r7,$sp
+	addi		r7,r7,32
+	stvx		v27,r3,$sp
+	addi		r3,r3,32
+	stvx		v28,r7,$sp
+	addi		r7,r7,32
+	stvx		v29,r3,$sp
+	addi		r3,r3,32
+	stvx		v30,r7,$sp
+	stvx		v31,r3,$sp
+	li		r0,-1
+	stw		$vrsave,`$FRAME+21*16-4`($sp)	# save vrsave
+	li		$x10,0x10
+	$PUSH		r26,`$FRAME+21*16+0*$SIZE_T`($sp)
+	li		$x20,0x20
+	$PUSH		r27,`$FRAME+21*16+1*$SIZE_T`($sp)
+	li		$x30,0x30
+	$PUSH		r28,`$FRAME+21*16+2*$SIZE_T`($sp)
+	li		$x40,0x40
+	$PUSH		r29,`$FRAME+21*16+3*$SIZE_T`($sp)
+	li		$x50,0x50
+	$PUSH		r30,`$FRAME+21*16+4*$SIZE_T`($sp)
+	li		$x60,0x60
+	$PUSH		r31,`$FRAME+21*16+5*$SIZE_T`($sp)
+	li		$x70,0x70
+	mtspr		256,r0
+
+	subi		$rounds,$rounds,3	# -4 in total
+
+	lvx		$rndkey0,$x00,$key1	# load key schedule
+	lvx		v30,$x10,$key1
+	addi		$key1,$key1,0x20
+	lvx		v31,$x00,$key1
+	?vperm		$rndkey0,$rndkey0,v30,$keyperm
+	addi		$key_,$sp,$FRAME+15
+	mtctr		$rounds
+
+Load_xts_dec_key:
+	?vperm		v24,v30,v31,$keyperm
+	lvx		v30,$x10,$key1
+	addi		$key1,$key1,0x20
+	stvx		v24,$x00,$key_		# off-load round[1]
+	?vperm		v25,v31,v30,$keyperm
+	lvx		v31,$x00,$key1
+	stvx		v25,$x10,$key_		# off-load round[2]
+	addi		$key_,$key_,0x20
+	bdnz		Load_xts_dec_key
+
+	lvx		v26,$x10,$key1
+	?vperm		v24,v30,v31,$keyperm
+	lvx		v27,$x20,$key1
+	stvx		v24,$x00,$key_		# off-load round[3]
+	?vperm		v25,v31,v26,$keyperm
+	lvx		v28,$x30,$key1
+	stvx		v25,$x10,$key_		# off-load round[4]
+	addi		$key_,$sp,$FRAME+15	# rewind $key_
+	?vperm		v26,v26,v27,$keyperm
+	lvx		v29,$x40,$key1
+	?vperm		v27,v27,v28,$keyperm
+	lvx		v30,$x50,$key1
+	?vperm		v28,v28,v29,$keyperm
+	lvx		v31,$x60,$key1
+	?vperm		v29,v29,v30,$keyperm
+	lvx		$twk5,$x70,$key1	# borrow $twk5
+	?vperm		v30,v30,v31,$keyperm
+	lvx		v24,$x00,$key_		# pre-load round[1]
+	?vperm		v31,v31,$twk5,$keyperm
+	lvx		v25,$x10,$key_		# pre-load round[2]
+
+	 vperm		$in0,$inout,$inptail,$inpperm
+	 subi		$inp,$inp,31		# undo "caller"
+	vxor		$twk0,$tweak,$rndkey0
+	vsrab		$tmp,$tweak,$seven	# next tweak value
+	vaddubm		$tweak,$tweak,$tweak
+	vsldoi		$tmp,$tmp,$tmp,15
+	vand		$tmp,$tmp,$eighty7
+	 vxor		$out0,$in0,$twk0
+	vxor		$tweak,$tweak,$tmp
+
+	 lvx_u		$in1,$x10,$inp
+	vxor		$twk1,$tweak,$rndkey0
+	vsrab		$tmp,$tweak,$seven	# next tweak value
+	vaddubm		$tweak,$tweak,$tweak
+	vsldoi		$tmp,$tmp,$tmp,15
+	 le?vperm	$in1,$in1,$in1,$leperm
+	vand		$tmp,$tmp,$eighty7
+	 vxor		$out1,$in1,$twk1
+	vxor		$tweak,$tweak,$tmp
+
+	 lvx_u		$in2,$x20,$inp
+	 andi.		$taillen,$len,15
+	vxor		$twk2,$tweak,$rndkey0
+	vsrab		$tmp,$tweak,$seven	# next tweak value
+	vaddubm		$tweak,$tweak,$tweak
+	vsldoi		$tmp,$tmp,$tmp,15
+	 le?vperm	$in2,$in2,$in2,$leperm
+	vand		$tmp,$tmp,$eighty7
+	 vxor		$out2,$in2,$twk2
+	vxor		$tweak,$tweak,$tmp
+
+	 lvx_u		$in3,$x30,$inp
+	 sub		$len,$len,$taillen
+	vxor		$twk3,$tweak,$rndkey0
+	vsrab		$tmp,$tweak,$seven	# next tweak value
+	vaddubm		$tweak,$tweak,$tweak
+	vsldoi		$tmp,$tmp,$tmp,15
+	 le?vperm	$in3,$in3,$in3,$leperm
+	vand		$tmp,$tmp,$eighty7
+	 vxor		$out3,$in3,$twk3
+	vxor		$tweak,$tweak,$tmp
+
+	 lvx_u		$in4,$x40,$inp
+	 subi		$len,$len,0x60
+	vxor		$twk4,$tweak,$rndkey0
+	vsrab		$tmp,$tweak,$seven	# next tweak value
+	vaddubm		$tweak,$tweak,$tweak
+	vsldoi		$tmp,$tmp,$tmp,15
+	 le?vperm	$in4,$in4,$in4,$leperm
+	vand		$tmp,$tmp,$eighty7
+	 vxor		$out4,$in4,$twk4
+	vxor		$tweak,$tweak,$tmp
+
+	 lvx_u		$in5,$x50,$inp
+	 addi		$inp,$inp,0x60
+	vxor		$twk5,$tweak,$rndkey0
+	vsrab		$tmp,$tweak,$seven	# next tweak value
+	vaddubm		$tweak,$tweak,$tweak
+	vsldoi		$tmp,$tmp,$tmp,15
+	 le?vperm	$in5,$in5,$in5,$leperm
+	vand		$tmp,$tmp,$eighty7
+	 vxor		$out5,$in5,$twk5
+	vxor		$tweak,$tweak,$tmp
+
+	vxor		v31,v31,$rndkey0
+	mtctr		$rounds
+	b		Loop_xts_dec6x
+
+.align	5
+Loop_xts_dec6x:
+	vncipher	$out0,$out0,v24
+	vncipher	$out1,$out1,v24
+	vncipher	$out2,$out2,v24
+	vncipher	$out3,$out3,v24
+	vncipher	$out4,$out4,v24
+	vncipher	$out5,$out5,v24
+	lvx		v24,$x20,$key_		# round[3]
+	addi		$key_,$key_,0x20
+
+	vncipher	$out0,$out0,v25
+	vncipher	$out1,$out1,v25
+	vncipher	$out2,$out2,v25
+	vncipher	$out3,$out3,v25
+	vncipher	$out4,$out4,v25
+	vncipher	$out5,$out5,v25
+	lvx		v25,$x10,$key_		# round[4]
+	bdnz		Loop_xts_dec6x
+
+	subic		$len,$len,96		# $len-=96
+	 vxor		$in0,$twk0,v31		# xor with last round key
+	vncipher	$out0,$out0,v24
+	vncipher	$out1,$out1,v24
+	 vsrab		$tmp,$tweak,$seven	# next tweak value
+	 vxor		$twk0,$tweak,$rndkey0
+	 vaddubm	$tweak,$tweak,$tweak
+	vncipher	$out2,$out2,v24
+	vncipher	$out3,$out3,v24
+	 vsldoi		$tmp,$tmp,$tmp,15
+	vncipher	$out4,$out4,v24
+	vncipher	$out5,$out5,v24
+
+	subfe.		r0,r0,r0		# borrow?-1:0
+	 vand		$tmp,$tmp,$eighty7
+	vncipher	$out0,$out0,v25
+	vncipher	$out1,$out1,v25
+	 vxor		$tweak,$tweak,$tmp
+	vncipher	$out2,$out2,v25
+	vncipher	$out3,$out3,v25
+	 vxor		$in1,$twk1,v31
+	 vsrab		$tmp,$tweak,$seven	# next tweak value
+	 vxor		$twk1,$tweak,$rndkey0
+	vncipher	$out4,$out4,v25
+	vncipher	$out5,$out5,v25
+
+	and		r0,r0,$len
+	 vaddubm	$tweak,$tweak,$tweak
+	 vsldoi		$tmp,$tmp,$tmp,15
+	vncipher	$out0,$out0,v26
+	vncipher	$out1,$out1,v26
+	 vand		$tmp,$tmp,$eighty7
+	vncipher	$out2,$out2,v26
+	vncipher	$out3,$out3,v26
+	 vxor		$tweak,$tweak,$tmp
+	vncipher	$out4,$out4,v26
+	vncipher	$out5,$out5,v26
+
+	add		$inp,$inp,r0		# $inp is adjusted in such
+						# way that at exit from the
+						# loop inX-in5 are loaded
+						# with last "words"
+	 vxor		$in2,$twk2,v31
+	 vsrab		$tmp,$tweak,$seven	# next tweak value
+	 vxor		$twk2,$tweak,$rndkey0
+	 vaddubm	$tweak,$tweak,$tweak
+	vncipher	$out0,$out0,v27
+	vncipher	$out1,$out1,v27
+	 vsldoi		$tmp,$tmp,$tmp,15
+	vncipher	$out2,$out2,v27
+	vncipher	$out3,$out3,v27
+	 vand		$tmp,$tmp,$eighty7
+	vncipher	$out4,$out4,v27
+	vncipher	$out5,$out5,v27
+
+	addi		$key_,$sp,$FRAME+15	# rewind $key_
+	 vxor		$tweak,$tweak,$tmp
+	vncipher	$out0,$out0,v28
+	vncipher	$out1,$out1,v28
+	 vxor		$in3,$twk3,v31
+	 vsrab		$tmp,$tweak,$seven	# next tweak value
+	 vxor		$twk3,$tweak,$rndkey0
+	vncipher	$out2,$out2,v28
+	vncipher	$out3,$out3,v28
+	 vaddubm	$tweak,$tweak,$tweak
+	 vsldoi		$tmp,$tmp,$tmp,15
+	vncipher	$out4,$out4,v28
+	vncipher	$out5,$out5,v28
+	lvx		v24,$x00,$key_		# re-pre-load round[1]
+	 vand		$tmp,$tmp,$eighty7
+
+	vncipher	$out0,$out0,v29
+	vncipher	$out1,$out1,v29
+	 vxor		$tweak,$tweak,$tmp
+	vncipher	$out2,$out2,v29
+	vncipher	$out3,$out3,v29
+	 vxor		$in4,$twk4,v31
+	 vsrab		$tmp,$tweak,$seven	# next tweak value
+	 vxor		$twk4,$tweak,$rndkey0
+	vncipher	$out4,$out4,v29
+	vncipher	$out5,$out5,v29
+	lvx		v25,$x10,$key_		# re-pre-load round[2]
+	 vaddubm	$tweak,$tweak,$tweak
+	 vsldoi		$tmp,$tmp,$tmp,15
+
+	vncipher	$out0,$out0,v30
+	vncipher	$out1,$out1,v30
+	 vand		$tmp,$tmp,$eighty7
+	vncipher	$out2,$out2,v30
+	vncipher	$out3,$out3,v30
+	 vxor		$tweak,$tweak,$tmp
+	vncipher	$out4,$out4,v30
+	vncipher	$out5,$out5,v30
+	 vxor		$in5,$twk5,v31
+	 vsrab		$tmp,$tweak,$seven	# next tweak value
+	 vxor		$twk5,$tweak,$rndkey0
+
+	vncipherlast	$out0,$out0,$in0
+	 lvx_u		$in0,$x00,$inp		# load next input block
+	 vaddubm	$tweak,$tweak,$tweak
+	 vsldoi		$tmp,$tmp,$tmp,15
+	vncipherlast	$out1,$out1,$in1
+	 lvx_u		$in1,$x10,$inp
+	vncipherlast	$out2,$out2,$in2
+	 le?vperm	$in0,$in0,$in0,$leperm
+	 lvx_u		$in2,$x20,$inp
+	 vand		$tmp,$tmp,$eighty7
+	vncipherlast	$out3,$out3,$in3
+	 le?vperm	$in1,$in1,$in1,$leperm
+	 lvx_u		$in3,$x30,$inp
+	vncipherlast	$out4,$out4,$in4
+	 le?vperm	$in2,$in2,$in2,$leperm
+	 lvx_u		$in4,$x40,$inp
+	 vxor		$tweak,$tweak,$tmp
+	vncipherlast	$out5,$out5,$in5
+	 le?vperm	$in3,$in3,$in3,$leperm
+	 lvx_u		$in5,$x50,$inp
+	 addi		$inp,$inp,0x60
+	 le?vperm	$in4,$in4,$in4,$leperm
+	 le?vperm	$in5,$in5,$in5,$leperm
+
+	le?vperm	$out0,$out0,$out0,$leperm
+	le?vperm	$out1,$out1,$out1,$leperm
+	stvx_u		$out0,$x00,$out		# store output
+	 vxor		$out0,$in0,$twk0
+	le?vperm	$out2,$out2,$out2,$leperm
+	stvx_u		$out1,$x10,$out
+	 vxor		$out1,$in1,$twk1
+	le?vperm	$out3,$out3,$out3,$leperm
+	stvx_u		$out2,$x20,$out
+	 vxor		$out2,$in2,$twk2
+	le?vperm	$out4,$out4,$out4,$leperm
+	stvx_u		$out3,$x30,$out
+	 vxor		$out3,$in3,$twk3
+	le?vperm	$out5,$out5,$out5,$leperm
+	stvx_u		$out4,$x40,$out
+	 vxor		$out4,$in4,$twk4
+	stvx_u		$out5,$x50,$out
+	 vxor		$out5,$in5,$twk5
+	addi		$out,$out,0x60
+
+	mtctr		$rounds
+	beq		Loop_xts_dec6x		# did $len-=96 borrow?
+
+	addic.		$len,$len,0x60
+	beq		Lxts_dec6x_zero
+	cmpwi		$len,0x20
+	blt		Lxts_dec6x_one
+	nop
+	beq		Lxts_dec6x_two
+	cmpwi		$len,0x40
+	blt		Lxts_dec6x_three
+	nop
+	beq		Lxts_dec6x_four
+
+Lxts_dec6x_five:
+	vxor		$out0,$in1,$twk0
+	vxor		$out1,$in2,$twk1
+	vxor		$out2,$in3,$twk2
+	vxor		$out3,$in4,$twk3
+	vxor		$out4,$in5,$twk4
+
+	bl		_aesp8_xts_dec5x
+
+	le?vperm	$out0,$out0,$out0,$leperm
+	vmr		$twk0,$twk5		# unused tweak
+	vxor		$twk1,$tweak,$rndkey0
+	le?vperm	$out1,$out1,$out1,$leperm
+	stvx_u		$out0,$x00,$out		# store output
+	vxor		$out0,$in0,$twk1
+	le?vperm	$out2,$out2,$out2,$leperm
+	stvx_u		$out1,$x10,$out
+	le?vperm	$out3,$out3,$out3,$leperm
+	stvx_u		$out2,$x20,$out
+	le?vperm	$out4,$out4,$out4,$leperm
+	stvx_u		$out3,$x30,$out
+	stvx_u		$out4,$x40,$out
+	addi		$out,$out,0x50
+	bne		Lxts_dec6x_steal
+	b		Lxts_dec6x_done
+
+.align	4
+Lxts_dec6x_four:
+	vxor		$out0,$in2,$twk0
+	vxor		$out1,$in3,$twk1
+	vxor		$out2,$in4,$twk2
+	vxor		$out3,$in5,$twk3
+	vxor		$out4,$out4,$out4
+
+	bl		_aesp8_xts_dec5x
+
+	le?vperm	$out0,$out0,$out0,$leperm
+	vmr		$twk0,$twk4		# unused tweak
+	vmr		$twk1,$twk5
+	le?vperm	$out1,$out1,$out1,$leperm
+	stvx_u		$out0,$x00,$out		# store output
+	vxor		$out0,$in0,$twk5
+	le?vperm	$out2,$out2,$out2,$leperm
+	stvx_u		$out1,$x10,$out
+	le?vperm	$out3,$out3,$out3,$leperm
+	stvx_u		$out2,$x20,$out
+	stvx_u		$out3,$x30,$out
+	addi		$out,$out,0x40
+	bne		Lxts_dec6x_steal
+	b		Lxts_dec6x_done
+
+.align	4
+Lxts_dec6x_three:
+	vxor		$out0,$in3,$twk0
+	vxor		$out1,$in4,$twk1
+	vxor		$out2,$in5,$twk2
+	vxor		$out3,$out3,$out3
+	vxor		$out4,$out4,$out4
+
+	bl		_aesp8_xts_dec5x
+
+	le?vperm	$out0,$out0,$out0,$leperm
+	vmr		$twk0,$twk3		# unused tweak
+	vmr		$twk1,$twk4
+	le?vperm	$out1,$out1,$out1,$leperm
+	stvx_u		$out0,$x00,$out		# store output
+	vxor		$out0,$in0,$twk4
+	le?vperm	$out2,$out2,$out2,$leperm
+	stvx_u		$out1,$x10,$out
+	stvx_u		$out2,$x20,$out
+	addi		$out,$out,0x30
+	bne		Lxts_dec6x_steal
+	b		Lxts_dec6x_done
+
+.align	4
+Lxts_dec6x_two:
+	vxor		$out0,$in4,$twk0
+	vxor		$out1,$in5,$twk1
+	vxor		$out2,$out2,$out2
+	vxor		$out3,$out3,$out3
+	vxor		$out4,$out4,$out4
+
+	bl		_aesp8_xts_dec5x
+
+	le?vperm	$out0,$out0,$out0,$leperm
+	vmr		$twk0,$twk2		# unused tweak
+	vmr		$twk1,$twk3
+	le?vperm	$out1,$out1,$out1,$leperm
+	stvx_u		$out0,$x00,$out		# store output
+	vxor		$out0,$in0,$twk3
+	stvx_u		$out1,$x10,$out
+	addi		$out,$out,0x20
+	bne		Lxts_dec6x_steal
+	b		Lxts_dec6x_done
+
+.align	4
+Lxts_dec6x_one:
+	vxor		$out0,$in5,$twk0
+	nop
+Loop_xts_dec1x:
+	vncipher	$out0,$out0,v24
+	lvx		v24,$x20,$key_		# round[3]
+	addi		$key_,$key_,0x20
+
+	vncipher	$out0,$out0,v25
+	lvx		v25,$x10,$key_		# round[4]
+	bdnz		Loop_xts_dec1x
+
+	subi		r0,$taillen,1
+	vncipher	$out0,$out0,v24
+
+	andi.		r0,r0,16
+	cmpwi		$taillen,0
+	vncipher	$out0,$out0,v25
+
+	sub		$inp,$inp,r0
+	vncipher	$out0,$out0,v26
+
+	lvx_u		$in0,0,$inp
+	vncipher	$out0,$out0,v27
+
+	addi		$key_,$sp,$FRAME+15	# rewind $key_
+	vncipher	$out0,$out0,v28
+	lvx		v24,$x00,$key_		# re-pre-load round[1]
+
+	vncipher	$out0,$out0,v29
+	lvx		v25,$x10,$key_		# re-pre-load round[2]
+	 vxor		$twk0,$twk0,v31
+
+	le?vperm	$in0,$in0,$in0,$leperm
+	vncipher	$out0,$out0,v30
+
+	mtctr		$rounds
+	vncipherlast	$out0,$out0,$twk0
+
+	vmr		$twk0,$twk1		# unused tweak
+	vmr		$twk1,$twk2
+	le?vperm	$out0,$out0,$out0,$leperm
+	stvx_u		$out0,$x00,$out		# store output
+	addi		$out,$out,0x10
+	vxor		$out0,$in0,$twk2
+	bne		Lxts_dec6x_steal
+	b		Lxts_dec6x_done
+
+.align	4
+Lxts_dec6x_zero:
+	cmpwi		$taillen,0
+	beq		Lxts_dec6x_done
+
+	lvx_u		$in0,0,$inp
+	le?vperm	$in0,$in0,$in0,$leperm
+	vxor		$out0,$in0,$twk1
+Lxts_dec6x_steal:
+	vncipher	$out0,$out0,v24
+	lvx		v24,$x20,$key_		# round[3]
+	addi		$key_,$key_,0x20
+
+	vncipher	$out0,$out0,v25
+	lvx		v25,$x10,$key_		# round[4]
+	bdnz		Lxts_dec6x_steal
+
+	add		$inp,$inp,$taillen
+	vncipher	$out0,$out0,v24
+
+	cmpwi		$taillen,0
+	vncipher	$out0,$out0,v25
+
+	lvx_u		$in0,0,$inp
+	vncipher	$out0,$out0,v26
+
+	lvsr		$inpperm,0,$taillen	# $in5 is no more
+	vncipher	$out0,$out0,v27
+
+	addi		$key_,$sp,$FRAME+15	# rewind $key_
+	vncipher	$out0,$out0,v28
+	lvx		v24,$x00,$key_		# re-pre-load round[1]
+
+	vncipher	$out0,$out0,v29
+	lvx		v25,$x10,$key_		# re-pre-load round[2]
+	 vxor		$twk1,$twk1,v31
+
+	le?vperm	$in0,$in0,$in0,$leperm
+	vncipher	$out0,$out0,v30
+
+	vperm		$in0,$in0,$in0,$inpperm
+	vncipherlast	$tmp,$out0,$twk1
+
+	le?vperm	$out0,$tmp,$tmp,$leperm
+	le?stvx_u	$out0,0,$out
+	be?stvx_u	$tmp,0,$out
+
+	vxor		$out0,$out0,$out0
+	vspltisb	$out1,-1
+	vperm		$out0,$out0,$out1,$inpperm
+	vsel		$out0,$in0,$tmp,$out0
+	vxor		$out0,$out0,$twk0
+
+	subi		r30,$out,1
+	mtctr		$taillen
+Loop_xts_dec6x_steal:
+	lbzu		r0,1(r30)
+	stb		r0,16(r30)
+	bdnz		Loop_xts_dec6x_steal
+
+	li		$taillen,0
+	mtctr		$rounds
+	b		Loop_xts_dec1x		# one more time...
+
+.align	4
+Lxts_dec6x_done:
+	${UCMP}i	$ivp,0
+	beq		Lxts_dec6x_ret
+
+	vxor		$tweak,$twk0,$rndkey0
+	le?vperm	$tweak,$tweak,$tweak,$leperm
+	stvx_u		$tweak,0,$ivp
+
+Lxts_dec6x_ret:
+	mtlr		r11
+	li		r10,`$FRAME+15`
+	li		r11,`$FRAME+31`
+	stvx		$seven,r10,$sp		# wipe copies of round keys
+	addi		r10,r10,32
+	stvx		$seven,r11,$sp
+	addi		r11,r11,32
+	stvx		$seven,r10,$sp
+	addi		r10,r10,32
+	stvx		$seven,r11,$sp
+	addi		r11,r11,32
+	stvx		$seven,r10,$sp
+	addi		r10,r10,32
+	stvx		$seven,r11,$sp
+	addi		r11,r11,32
+	stvx		$seven,r10,$sp
+	addi		r10,r10,32
+	stvx		$seven,r11,$sp
+	addi		r11,r11,32
+
+	mtspr		256,$vrsave
+	lvx		v20,r10,$sp		# ABI says so
+	addi		r10,r10,32
+	lvx		v21,r11,$sp
+	addi		r11,r11,32
+	lvx		v22,r10,$sp
+	addi		r10,r10,32
+	lvx		v23,r11,$sp
+	addi		r11,r11,32
+	lvx		v24,r10,$sp
+	addi		r10,r10,32
+	lvx		v25,r11,$sp
+	addi		r11,r11,32
+	lvx		v26,r10,$sp
+	addi		r10,r10,32
+	lvx		v27,r11,$sp
+	addi		r11,r11,32
+	lvx		v28,r10,$sp
+	addi		r10,r10,32
+	lvx		v29,r11,$sp
+	addi		r11,r11,32
+	lvx		v30,r10,$sp
+	lvx		v31,r11,$sp
+	$POP		r26,`$FRAME+21*16+0*$SIZE_T`($sp)
+	$POP		r27,`$FRAME+21*16+1*$SIZE_T`($sp)
+	$POP		r28,`$FRAME+21*16+2*$SIZE_T`($sp)
+	$POP		r29,`$FRAME+21*16+3*$SIZE_T`($sp)
+	$POP		r30,`$FRAME+21*16+4*$SIZE_T`($sp)
+	$POP		r31,`$FRAME+21*16+5*$SIZE_T`($sp)
+	addi		$sp,$sp,`$FRAME+21*16+6*$SIZE_T`
+	blr
+	.long		0
+	.byte		0,12,0x04,1,0x80,6,6,0
+	.long		0
+
+.align	5
+_aesp8_xts_dec5x:
+	vncipher	$out0,$out0,v24
+	vncipher	$out1,$out1,v24
+	vncipher	$out2,$out2,v24
+	vncipher	$out3,$out3,v24
+	vncipher	$out4,$out4,v24
+	lvx		v24,$x20,$key_		# round[3]
+	addi		$key_,$key_,0x20
+
+	vncipher	$out0,$out0,v25
+	vncipher	$out1,$out1,v25
+	vncipher	$out2,$out2,v25
+	vncipher	$out3,$out3,v25
+	vncipher	$out4,$out4,v25
+	lvx		v25,$x10,$key_		# round[4]
+	bdnz		_aesp8_xts_dec5x
+
+	subi		r0,$taillen,1
+	vncipher	$out0,$out0,v24
+	vncipher	$out1,$out1,v24
+	vncipher	$out2,$out2,v24
+	vncipher	$out3,$out3,v24
+	vncipher	$out4,$out4,v24
+
+	andi.		r0,r0,16
+	cmpwi		$taillen,0
+	vncipher	$out0,$out0,v25
+	vncipher	$out1,$out1,v25
+	vncipher	$out2,$out2,v25
+	vncipher	$out3,$out3,v25
+	vncipher	$out4,$out4,v25
+	 vxor		$twk0,$twk0,v31
+
+	sub		$inp,$inp,r0
+	vncipher	$out0,$out0,v26
+	vncipher	$out1,$out1,v26
+	vncipher	$out2,$out2,v26
+	vncipher	$out3,$out3,v26
+	vncipher	$out4,$out4,v26
+	 vxor		$in1,$twk1,v31
+
+	vncipher	$out0,$out0,v27
+	lvx_u		$in0,0,$inp
+	vncipher	$out1,$out1,v27
+	vncipher	$out2,$out2,v27
+	vncipher	$out3,$out3,v27
+	vncipher	$out4,$out4,v27
+	 vxor		$in2,$twk2,v31
+
+	addi		$key_,$sp,$FRAME+15	# rewind $key_
+	vncipher	$out0,$out0,v28
+	vncipher	$out1,$out1,v28
+	vncipher	$out2,$out2,v28
+	vncipher	$out3,$out3,v28
+	vncipher	$out4,$out4,v28
+	lvx		v24,$x00,$key_		# re-pre-load round[1]
+	 vxor		$in3,$twk3,v31
+
+	vncipher	$out0,$out0,v29
+	le?vperm	$in0,$in0,$in0,$leperm
+	vncipher	$out1,$out1,v29
+	vncipher	$out2,$out2,v29
+	vncipher	$out3,$out3,v29
+	vncipher	$out4,$out4,v29
+	lvx		v25,$x10,$key_		# re-pre-load round[2]
+	 vxor		$in4,$twk4,v31
+
+	vncipher	$out0,$out0,v30
+	vncipher	$out1,$out1,v30
+	vncipher	$out2,$out2,v30
+	vncipher	$out3,$out3,v30
+	vncipher	$out4,$out4,v30
+
+	vncipherlast	$out0,$out0,$twk0
+	vncipherlast	$out1,$out1,$in1
+	vncipherlast	$out2,$out2,$in2
+	vncipherlast	$out3,$out3,$in3
+	vncipherlast	$out4,$out4,$in4
+	mtctr		$rounds
+	blr
+        .long   	0
+        .byte   	0,12,0x14,0,0,0,0,0
+___
+}}	}}}
+
+my $consts=1;
+foreach(split("\n",$code)) {
+        s/\`([^\`]*)\`/eval($1)/geo;
+
+	# constants table endian-specific conversion
+	if ($consts && m/\.(long|byte)\s+(.+)\s+(\?[a-z]*)$/o) {
+	    my $conv=$3;
+	    my @bytes=();
+
+	    # convert to endian-agnostic format
+	    if ($1 eq "long") {
+	      foreach (split(/,\s*/,$2)) {
+		my $l = /^0/?oct:int;
+		push @bytes,($l>>24)&0xff,($l>>16)&0xff,($l>>8)&0xff,$l&0xff;
+	      }
+	    } else {
+		@bytes = map(/^0/?oct:int,split(/,\s*/,$2));
+	    }
+
+	    # little-endian conversion
+	    if ($flavour =~ /le$/o) {
+		SWITCH: for($conv)  {
+		    /\?inv/ && do   { @bytes=map($_^0xf,@bytes); last; };
+		    /\?rev/ && do   { @bytes=reverse(@bytes);    last; };
+		}
+	    }
+
+	    #emit
+	    print ".byte\t",join(',',map (sprintf("0x%02x",$_),@bytes)),"\n";
+	    next;
+	}
+	$consts=0 if (m/Lconsts:/o);	# end of table
+
+	# instructions prefixed with '?' are endian-specific and need
+	# to be adjusted accordingly...
+	if ($flavour =~ /le$/o) {	# little-endian
+	    s/le\?//o		or
+	    s/be\?/#be#/o	or
+	    s/\?lvsr/lvsl/o	or
+	    s/\?lvsl/lvsr/o	or
+	    s/\?(vperm\s+v[0-9]+,\s*)(v[0-9]+,\s*)(v[0-9]+,\s*)(v[0-9]+)/$1$3$2$4/o or
+	    s/\?(vsldoi\s+v[0-9]+,\s*)(v[0-9]+,)\s*(v[0-9]+,\s*)([0-9]+)/$1$3$2 16-$4/o or
+	    s/\?(vspltw\s+v[0-9]+,\s*)(v[0-9]+,)\s*([0-9])/$1$2 3-$3/o;
+	} else {			# big-endian
+	    s/le\?/#le#/o	or
+	    s/be\?//o		or
+	    s/\?([a-z]+)/$1/o;
+	}
+
+        print $_,"\n";
+}
+
+close STDOUT;
diff --git a/src/crypto/aes/asm/aesv8-armx.pl b/src/crypto/aes/asm/aesv8-armx.pl
index 121154a..23ed77c 100644
--- a/src/crypto/aes/asm/aesv8-armx.pl
+++ b/src/crypto/aes/asm/aesv8-armx.pl
@@ -42,7 +42,7 @@
 open OUT,"| \"$^X\" $xlate $flavour $output";
 *STDOUT=*OUT;
 
-$prefix="aes_v8";
+$prefix="aes_hw";
 
 $code=<<___;
 #include <openssl/arm_arch.h>
@@ -51,7 +51,7 @@
 .text
 ___
 $code.=<<___ if ($flavour =~ /64/);
-#if !defined(__clang__)
+#if !defined(__clang__) || defined(BORINGSSL_CLANG_SUPPORTS_DOT_ARCH)
 .arch  armv8-a+crypto
 #endif
 ___
@@ -957,21 +957,21 @@
 
 	$arg =~ m/q([0-9]+),\s*\{q([0-9]+)\},\s*q([0-9]+)/o &&
 	sprintf	"vtbl.8	d%d,{q%d},d%d\n\t".
-		"vtbl.8	d%d,{q%d},d%d", 2*$1,$2,2*$3, 2*$1+1,$2,2*$3+1;	
+		"vtbl.8	d%d,{q%d},d%d", 2*$1,$2,2*$3, 2*$1+1,$2,2*$3+1;
     }
 
     sub unvdup32 {
 	my $arg=shift;
 
 	$arg =~ m/q([0-9]+),\s*q([0-9]+)\[([0-3])\]/o &&
-	sprintf	"vdup.32	q%d,d%d[%d]",$1,2*$2+($3>>1),$3&1;	
+	sprintf	"vdup.32	q%d,d%d[%d]",$1,2*$2+($3>>1),$3&1;
     }
 
     sub unvmov32 {
 	my $arg=shift;
 
 	$arg =~ m/q([0-9]+)\[([0-3])\],(.*)/o &&
-	sprintf	"vmov.32	d%d[%d],%s",2*$1+($2>>1),$2&1,$3;	
+	sprintf	"vmov.32	d%d[%d],%s",2*$1+($2>>1),$2&1,$3;
     }
 
     foreach(split("\n",$code)) {
diff --git a/src/crypto/aes/asm/bsaes-armv7.pl b/src/crypto/aes/asm/bsaes-armv7.pl
index 2617fef..d645de4 100644
--- a/src/crypto/aes/asm/bsaes-armv7.pl
+++ b/src/crypto/aes/asm/bsaes-armv7.pl
@@ -48,8 +48,8 @@
 #					<ard.biesheuvel@linaro.org>
 
 $flavour = shift;
-if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
-else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} }
+if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
+else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} }
 
 if ($flavour && $flavour ne "void") {
     $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
@@ -84,7 +84,7 @@
 
 sub InBasisChange {
 # input in  lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
-# output in lsb > [b6, b5, b0, b3, b7, b1, b4, b2] < msb 
+# output in lsb > [b6, b5, b0, b3, b7, b1, b4, b2] < msb
 my @b=@_[0..7];
 $code.=<<___;
 	veor	@b[2], @b[2], @b[1]
@@ -1006,7 +1006,6 @@
 			# used for benchmarking...
 $code.=<<___;
 .globl	bsaes_enc_key_convert
-.hidden	bsaes_enc_key_convert
 .type	bsaes_enc_key_convert,%function
 .align	4
 bsaes_enc_key_convert:
@@ -1025,7 +1024,6 @@
 .size	bsaes_enc_key_convert,.-bsaes_enc_key_convert
 
 .globl	bsaes_encrypt_128
-.hidden	bsaes_encrypt_128
 .type	bsaes_encrypt_128,%function
 .align	4
 bsaes_encrypt_128:
@@ -1056,7 +1054,6 @@
 .size	bsaes_encrypt_128,.-bsaes_encrypt_128
 
 .globl	bsaes_dec_key_convert
-.hidden	bsaes_dec_key_convert
 .type	bsaes_dec_key_convert,%function
 .align	4
 bsaes_dec_key_convert:
@@ -1077,7 +1074,6 @@
 .size	bsaes_dec_key_convert,.-bsaes_dec_key_convert
 
 .globl	bsaes_decrypt_128
-.hidden	bsaes_decrypt_128
 .type	bsaes_decrypt_128,%function
 .align	4
 bsaes_decrypt_128:
@@ -1117,7 +1113,6 @@
 .extern AES_decrypt
 
 .global	bsaes_cbc_encrypt
-.hidden	bsaes_cbc_encrypt
 .type	bsaes_cbc_encrypt,%function
 .align	5
 bsaes_cbc_encrypt:
@@ -1393,7 +1388,6 @@
 $code.=<<___;
 .extern	AES_encrypt
 .global	bsaes_ctr32_encrypt_blocks
-.hidden	bsaes_ctr32_encrypt_blocks
 .type	bsaes_ctr32_encrypt_blocks,%function
 .align	5
 bsaes_ctr32_encrypt_blocks:
@@ -1635,7 +1629,6 @@
 
 $code.=<<___;
 .globl	bsaes_xts_encrypt
-.hidden	bsaes_xts_encrypt
 .type	bsaes_xts_encrypt,%function
 .align	4
 bsaes_xts_encrypt:
@@ -1838,8 +1831,6 @@
 	b		.Lxts_enc_done
 .align	4
 .Lxts_enc_6:
-	vst1.64		{@XMM[14]}, [r0,:128]		@ next round tweak
-
 	veor		@XMM[4], @XMM[4], @XMM[12]
 #ifndef	BSAES_ASM_EXTENDED_KEY
 	add		r4, sp, #0x90			@ pass key schedule
@@ -1875,8 +1866,6 @@
 
 .align	5
 .Lxts_enc_5:
-	vst1.64		{@XMM[13]}, [r0,:128]		@ next round tweak
-
 	veor		@XMM[3], @XMM[3], @XMM[11]
 #ifndef	BSAES_ASM_EXTENDED_KEY
 	add		r4, sp, #0x90			@ pass key schedule
@@ -1905,8 +1894,6 @@
 	b		.Lxts_enc_done
 .align	4
 .Lxts_enc_4:
-	vst1.64		{@XMM[12]}, [r0,:128]		@ next round tweak
-
 	veor		@XMM[2], @XMM[2], @XMM[10]
 #ifndef	BSAES_ASM_EXTENDED_KEY
 	add		r4, sp, #0x90			@ pass key schedule
@@ -1932,8 +1919,6 @@
 	b		.Lxts_enc_done
 .align	4
 .Lxts_enc_3:
-	vst1.64		{@XMM[11]}, [r0,:128]		@ next round tweak
-
 	veor		@XMM[1], @XMM[1], @XMM[9]
 #ifndef	BSAES_ASM_EXTENDED_KEY
 	add		r4, sp, #0x90			@ pass key schedule
@@ -1958,8 +1943,6 @@
 	b		.Lxts_enc_done
 .align	4
 .Lxts_enc_2:
-	vst1.64		{@XMM[10]}, [r0,:128]		@ next round tweak
-
 	veor		@XMM[0], @XMM[0], @XMM[8]
 #ifndef	BSAES_ASM_EXTENDED_KEY
 	add		r4, sp, #0x90			@ pass key schedule
@@ -1982,7 +1965,7 @@
 .align	4
 .Lxts_enc_1:
 	mov		r0, sp
-	veor		@XMM[0], @XMM[8]
+	veor		@XMM[0], @XMM[0], @XMM[8]
 	mov		r1, sp
 	vst1.8		{@XMM[0]}, [sp,:128]
 	mov		r2, $key
@@ -2050,7 +2033,6 @@
 .size	bsaes_xts_encrypt,.-bsaes_xts_encrypt
 
 .globl	bsaes_xts_decrypt
-.hidden	bsaes_xts_decrypt
 .type	bsaes_xts_decrypt,%function
 .align	4
 bsaes_xts_decrypt:
@@ -2295,8 +2277,6 @@
 	b		.Lxts_dec_done
 .align	4
 .Lxts_dec_5:
-	vst1.64		{@XMM[13]}, [r0,:128]		@ next round tweak
-
 	veor		@XMM[3], @XMM[3], @XMM[11]
 #ifndef	BSAES_ASM_EXTENDED_KEY
 	add		r4, sp, #0x90			@ pass key schedule
@@ -2325,8 +2305,6 @@
 	b		.Lxts_dec_done
 .align	4
 .Lxts_dec_4:
-	vst1.64		{@XMM[12]}, [r0,:128]		@ next round tweak
-
 	veor		@XMM[2], @XMM[2], @XMM[10]
 #ifndef	BSAES_ASM_EXTENDED_KEY
 	add		r4, sp, #0x90			@ pass key schedule
@@ -2352,8 +2330,6 @@
 	b		.Lxts_dec_done
 .align	4
 .Lxts_dec_3:
-	vst1.64		{@XMM[11]}, [r0,:128]		@ next round tweak
-
 	veor		@XMM[1], @XMM[1], @XMM[9]
 #ifndef	BSAES_ASM_EXTENDED_KEY
 	add		r4, sp, #0x90			@ pass key schedule
@@ -2378,8 +2354,6 @@
 	b		.Lxts_dec_done
 .align	4
 .Lxts_dec_2:
-	vst1.64		{@XMM[10]}, [r0,:128]		@ next round tweak
-
 	veor		@XMM[0], @XMM[0], @XMM[8]
 #ifndef	BSAES_ASM_EXTENDED_KEY
 	add		r4, sp, #0x90			@ pass key schedule
@@ -2402,12 +2376,12 @@
 .align	4
 .Lxts_dec_1:
 	mov		r0, sp
-	veor		@XMM[0], @XMM[8]
+	veor		@XMM[0], @XMM[0], @XMM[8]
 	mov		r1, sp
 	vst1.8		{@XMM[0]}, [sp,:128]
+	mov		r5, $magic			@ preserve magic
 	mov		r2, $key
 	mov		r4, $fp				@ preserve fp
-	mov		r5, $magic			@ preserve magic
 
 	bl		AES_decrypt
 
diff --git a/src/crypto/aes/asm/bsaes-x86_64.pl b/src/crypto/aes/asm/bsaes-x86_64.pl
index 3f7d33c..9a8055e 100644
--- a/src/crypto/aes/asm/bsaes-x86_64.pl
+++ b/src/crypto/aes/asm/bsaes-x86_64.pl
@@ -41,6 +41,7 @@
 # Nehalem(**) 	7.63		6.88		+11%
 # Atom	    	17.1		16.4		+4%
 # Silvermont	-		12.9
+# Goldmont	-		8.85
 #
 # (*)	Comparison is not completely fair, because "this" is ECB,
 #	i.e. no extra processing such as counter values calculation
@@ -80,6 +81,7 @@
 # Nehalem	7.80
 # Atom		17.9
 # Silvermont	14.0
+# Goldmont	10.2
 #
 # November 2011.
 #
@@ -99,7 +101,7 @@
 ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
 die "can't locate x86_64-xlate.pl";
 
-open OUT,"| \"$^X\" $xlate $flavour $output";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
 *STDOUT=*OUT;
 
 my ($inp,$out,$len,$key,$ivp)=("%rdi","%rsi","%rdx","%rcx");
@@ -122,7 +124,7 @@
 
 sub InBasisChange {
 # input in  lsb > [b0, b1, b2, b3, b4, b5, b6, b7] < msb
-# output in lsb > [b6, b5, b0, b3, b7, b1, b4, b2] < msb 
+# output in lsb > [b6, b5, b0, b3, b7, b1, b4, b2] < msb
 my @b=@_[0..7];
 $code.=<<___;
 	pxor	@b[6], @b[5]
@@ -372,7 +374,7 @@
 	pxor	@s[0], @t[3]
 	pxor	@s[1], @t[2]
 	pxor	@s[2], @t[1]
-	pxor	@s[3], @t[0] 
+	pxor	@s[3], @t[0]
 
 	#Inv_GF16 \t0, \t1, \t2, \t3, \s0, \s1, \s2, \s3
 
@@ -1325,7 +1327,7 @@
 	cmp	%rax, %rbp
 	jb	.Lecb_enc_bzero
 
-	lea	(%rbp),%rsp		# restore %rsp
+	lea	0x78(%rbp),%rax
 ___
 $code.=<<___ if ($win64);
 	movaps	0x40(%rbp), %xmm6
@@ -1338,17 +1340,17 @@
 	movaps	0xb0(%rbp), %xmm13
 	movaps	0xc0(%rbp), %xmm14
 	movaps	0xd0(%rbp), %xmm15
-	lea	0xa0(%rbp), %rsp
+	lea	0xa0(%rax), %rax
+.Lecb_enc_tail:
 ___
 $code.=<<___;
-	mov	0x48(%rsp), %r15
-	mov	0x50(%rsp), %r14
-	mov	0x58(%rsp), %r13
-	mov	0x60(%rsp), %r12
-	mov	0x68(%rsp), %rbx
-	mov	0x70(%rsp), %rax
-	lea	0x78(%rsp), %rsp
-	mov	%rax, %rbp
+	mov	-48(%rax), %r15
+	mov	-40(%rax), %r14
+	mov	-32(%rax), %r13
+	mov	-24(%rax), %r12
+	mov	-16(%rax), %rbx
+	mov	-8(%rax), %rbp
+	lea	(%rax), %rsp		# restore %rsp
 .Lecb_enc_epilogue:
 	ret
 .size	bsaes_ecb_encrypt_blocks,.-bsaes_ecb_encrypt_blocks
@@ -1527,7 +1529,7 @@
 	cmp	%rax, %rbp
 	jb	.Lecb_dec_bzero
 
-	lea	(%rbp),%rsp		# restore %rsp
+	lea	0x78(%rbp),%rax
 ___
 $code.=<<___ if ($win64);
 	movaps	0x40(%rbp), %xmm6
@@ -1540,17 +1542,17 @@
 	movaps	0xb0(%rbp), %xmm13
 	movaps	0xc0(%rbp), %xmm14
 	movaps	0xd0(%rbp), %xmm15
-	lea	0xa0(%rbp), %rsp
+	lea	0xa0(%rax), %rax
+.Lecb_dec_tail:
 ___
 $code.=<<___;
-	mov	0x48(%rsp), %r15
-	mov	0x50(%rsp), %r14
-	mov	0x58(%rsp), %r13
-	mov	0x60(%rsp), %r12
-	mov	0x68(%rsp), %rbx
-	mov	0x70(%rsp), %rax
-	lea	0x78(%rsp), %rsp
-	mov	%rax, %rbp
+	mov	-48(%rax), %r15
+	mov	-40(%rax), %r14
+	mov	-32(%rax), %r13
+	mov	-24(%rax), %r12
+	mov	-16(%rax), %rbx
+	mov	-8(%rax), %rbp
+	lea	(%rax), %rsp		# restore %rsp
 .Lecb_dec_epilogue:
 	ret
 .size	bsaes_ecb_decrypt_blocks,.-bsaes_ecb_decrypt_blocks
@@ -1817,7 +1819,7 @@
 	cmp	%rax, %rbp
 	ja	.Lcbc_dec_bzero
 
-	lea	(%rbp),%rsp		# restore %rsp
+	lea	0x78(%rbp),%rax
 ___
 $code.=<<___ if ($win64);
 	movaps	0x40(%rbp), %xmm6
@@ -1830,17 +1832,17 @@
 	movaps	0xb0(%rbp), %xmm13
 	movaps	0xc0(%rbp), %xmm14
 	movaps	0xd0(%rbp), %xmm15
-	lea	0xa0(%rbp), %rsp
+	lea	0xa0(%rax), %rax
+.Lcbc_dec_tail:
 ___
 $code.=<<___;
-	mov	0x48(%rsp), %r15
-	mov	0x50(%rsp), %r14
-	mov	0x58(%rsp), %r13
-	mov	0x60(%rsp), %r12
-	mov	0x68(%rsp), %rbx
-	mov	0x70(%rsp), %rax
-	lea	0x78(%rsp), %rsp
-	mov	%rax, %rbp
+	mov	-48(%rax), %r15
+	mov	-40(%rax), %r14
+	mov	-32(%rax), %r13
+	mov	-24(%rax), %r12
+	mov	-16(%rax), %rbx
+	mov	-8(%rax), %rbp
+	lea	(%rax), %rsp		# restore %rsp
 .Lcbc_dec_epilogue:
 	ret
 .size	bsaes_cbc_encrypt,.-bsaes_cbc_encrypt
@@ -2049,7 +2051,7 @@
 	cmp	%rax, %rbp
 	ja	.Lctr_enc_bzero
 
-	lea	(%rbp),%rsp		# restore %rsp
+	lea	0x78(%rbp),%rax
 ___
 $code.=<<___ if ($win64);
 	movaps	0x40(%rbp), %xmm6
@@ -2062,17 +2064,17 @@
 	movaps	0xb0(%rbp), %xmm13
 	movaps	0xc0(%rbp), %xmm14
 	movaps	0xd0(%rbp), %xmm15
-	lea	0xa0(%rbp), %rsp
+	lea	0xa0(%rax), %rax
+.Lctr_enc_tail:
 ___
 $code.=<<___;
-	mov	0x48(%rsp), %r15
-	mov	0x50(%rsp), %r14
-	mov	0x58(%rsp), %r13
-	mov	0x60(%rsp), %r12
-	mov	0x68(%rsp), %rbx
-	mov	0x70(%rsp), %rax
-	lea	0x78(%rsp), %rsp
-	mov	%rax, %rbp
+	mov	-48(%rax), %r15
+	mov	-40(%rax), %r14
+	mov	-32(%rax), %r13
+	mov	-24(%rax), %r12
+	mov	-16(%rax), %rbx
+	mov	-8(%rax), %rbp
+	lea	(%rax), %rsp		# restore %rsp
 .Lctr_enc_epilogue:
 	ret
 .size	bsaes_ctr32_encrypt_blocks,.-bsaes_ctr32_encrypt_blocks
@@ -2439,7 +2441,7 @@
 	cmp	%rax, %rbp
 	ja	.Lxts_enc_bzero
 
-	lea	(%rbp),%rsp		# restore %rsp
+	lea	0x78(%rbp),%rax
 ___
 $code.=<<___ if ($win64);
 	movaps	0x40(%rbp), %xmm6
@@ -2452,17 +2454,17 @@
 	movaps	0xb0(%rbp), %xmm13
 	movaps	0xc0(%rbp), %xmm14
 	movaps	0xd0(%rbp), %xmm15
-	lea	0xa0(%rbp), %rsp
+	lea	0xa0(%rax), %rax
+.Lxts_enc_tail:
 ___
 $code.=<<___;
-	mov	0x48(%rsp), %r15
-	mov	0x50(%rsp), %r14
-	mov	0x58(%rsp), %r13
-	mov	0x60(%rsp), %r12
-	mov	0x68(%rsp), %rbx
-	mov	0x70(%rsp), %rax
-	lea	0x78(%rsp), %rsp
-	mov	%rax, %rbp
+	mov	-48(%rax), %r15
+	mov	-40(%rax), %r14
+	mov	-32(%rax), %r13
+	mov	-24(%rax), %r12
+	mov	-16(%rax), %rbx
+	mov	-8(%rax), %rbp
+	lea	(%rax), %rsp		# restore %rsp
 .Lxts_enc_epilogue:
 	ret
 .size	bsaes_xts_encrypt,.-bsaes_xts_encrypt
@@ -2846,7 +2848,7 @@
 	cmp	%rax, %rbp
 	ja	.Lxts_dec_bzero
 
-	lea	(%rbp),%rsp		# restore %rsp
+	lea	0x78(%rbp),%rax
 ___
 $code.=<<___ if ($win64);
 	movaps	0x40(%rbp), %xmm6
@@ -2859,17 +2861,17 @@
 	movaps	0xb0(%rbp), %xmm13
 	movaps	0xc0(%rbp), %xmm14
 	movaps	0xd0(%rbp), %xmm15
-	lea	0xa0(%rbp), %rsp
+	lea	0xa0(%rax), %rax
+.Lxts_dec_tail:
 ___
 $code.=<<___;
-	mov	0x48(%rsp), %r15
-	mov	0x50(%rsp), %r14
-	mov	0x58(%rsp), %r13
-	mov	0x60(%rsp), %r12
-	mov	0x68(%rsp), %rbx
-	mov	0x70(%rsp), %rax
-	lea	0x78(%rsp), %rsp
-	mov	%rax, %rbp
+	mov	-48(%rax), %r15
+	mov	-40(%rax), %r14
+	mov	-32(%rax), %r13
+	mov	-24(%rax), %r12
+	mov	-16(%rax), %rbx
+	mov	-8(%rax), %rbp
+	lea	(%rax), %rsp		# restore %rsp
 .Lxts_dec_epilogue:
 	ret
 .size	bsaes_xts_decrypt,.-bsaes_xts_decrypt
@@ -2965,31 +2967,34 @@
 
 	mov	0(%r11),%r10d		# HandlerData[0]
 	lea	(%rsi,%r10),%r10	# prologue label
-	cmp	%r10,%rbx		# context->Rip<prologue label
-	jb	.Lin_prologue
-
-	mov	152($context),%rax	# pull context->Rsp
+	cmp	%r10,%rbx		# context->Rip<=prologue label
+	jbe	.Lin_prologue
 
 	mov	4(%r11),%r10d		# HandlerData[1]
 	lea	(%rsi,%r10),%r10	# epilogue label
 	cmp	%r10,%rbx		# context->Rip>=epilogue label
 	jae	.Lin_prologue
 
+	mov	8(%r11),%r10d		# HandlerData[2]
+	lea	(%rsi,%r10),%r10	# epilogue label
+	cmp	%r10,%rbx		# context->Rip>=tail label
+	jae	.Lin_tail
+
 	mov	160($context),%rax	# pull context->Rbp
 
 	lea	0x40(%rax),%rsi		# %xmm save area
 	lea	512($context),%rdi	# &context.Xmm6
 	mov	\$20,%ecx		# 10*sizeof(%xmm0)/sizeof(%rax)
 	.long	0xa548f3fc		# cld; rep movsq
-	lea	0xa0(%rax),%rax		# adjust stack pointer
+	lea	0xa0+0x78(%rax),%rax	# adjust stack pointer
 
-	mov	0x70(%rax),%rbp
-	mov	0x68(%rax),%rbx
-	mov	0x60(%rax),%r12
-	mov	0x58(%rax),%r13
-	mov	0x50(%rax),%r14
-	mov	0x48(%rax),%r15
-	lea	0x78(%rax),%rax		# adjust stack pointer
+.Lin_tail:
+	mov	-48(%rax),%rbp
+	mov	-40(%rax),%rbx
+	mov	-32(%rax),%r12
+	mov	-24(%rax),%r13
+	mov	-16(%rax),%r14
+	mov	-8(%rax),%r15
 	mov	%rbx,144($context)	# restore context->Rbx
 	mov	%rbp,160($context)	# restore context->Rbp
 	mov	%r12,216($context)	# restore context->R12
@@ -3070,28 +3075,40 @@
 	.byte	9,0,0,0
 	.rva	se_handler
 	.rva	.Lecb_enc_body,.Lecb_enc_epilogue	# HandlerData[]
+	.rva	.Lecb_enc_tail
+	.long	0
 .Lecb_dec_info:
 	.byte	9,0,0,0
 	.rva	se_handler
 	.rva	.Lecb_dec_body,.Lecb_dec_epilogue	# HandlerData[]
+	.rva	.Lecb_dec_tail
+	.long	0
 ___
 $code.=<<___;
 .Lcbc_dec_info:
 	.byte	9,0,0,0
 	.rva	se_handler
 	.rva	.Lcbc_dec_body,.Lcbc_dec_epilogue	# HandlerData[]
+	.rva	.Lcbc_dec_tail
+	.long	0
 .Lctr_enc_info:
 	.byte	9,0,0,0
 	.rva	se_handler
 	.rva	.Lctr_enc_body,.Lctr_enc_epilogue	# HandlerData[]
+	.rva	.Lctr_enc_tail
+	.long	0
 .Lxts_enc_info:
 	.byte	9,0,0,0
 	.rva	se_handler
 	.rva	.Lxts_enc_body,.Lxts_enc_epilogue	# HandlerData[]
+	.rva	.Lxts_enc_tail
+	.long	0
 .Lxts_dec_info:
 	.byte	9,0,0,0
 	.rva	se_handler
 	.rva	.Lxts_dec_body,.Lxts_dec_epilogue	# HandlerData[]
+	.rva	.Lxts_dec_tail
+	.long	0
 ___
 }
 
diff --git a/src/crypto/aes/asm/vpaes-x86.pl b/src/crypto/aes/asm/vpaes-x86.pl
index 2ba149c..ebf90e7 100644
--- a/src/crypto/aes/asm/vpaes-x86.pl
+++ b/src/crypto/aes/asm/vpaes-x86.pl
@@ -51,6 +51,10 @@
 push(@INC,"${dir}","${dir}../../perlasm");
 require "x86asm.pl";
 
+$output = pop;
+open OUT,">$output";
+*STDOUT=*OUT;
+
 &asm_init($ARGV[0],"vpaes-x86.pl",$x86only = $ARGV[$#ARGV] eq "386");
 
 $PREFIX="vpaes";
@@ -434,7 +438,7 @@
 ##
 &set_label("schedule_192",16);
 	&movdqu	("xmm0",&QWP(8,$inp));		# load key part 2 (very unaligned)
-	&call	("_vpaes_schedule_transform");	# input transform	
+	&call	("_vpaes_schedule_transform");	# input transform
 	&movdqa	("xmm6","xmm0");		# save short part
 	&pxor	("xmm4","xmm4");		# clear 4
 	&movhlps("xmm6","xmm4");		# clobber low side with zeros
@@ -465,7 +469,7 @@
 ##
 &set_label("schedule_256",16);
 	&movdqu	("xmm0",&QWP(16,$inp));		# load key part 2 (unaligned)
-	&call	("_vpaes_schedule_transform");	# input transform	
+	&call	("_vpaes_schedule_transform");	# input transform
 	&mov	($round,7);
 
 &set_label("loop_schedule_256");
@@ -476,7 +480,7 @@
 	&call	("_vpaes_schedule_round");
 	&dec	($round);
 	&jz	(&label("schedule_mangle_last"));
-	&call	("_vpaes_schedule_mangle");	
+	&call	("_vpaes_schedule_mangle");
 
 	# low round. swap xmm7 and xmm6
 	&pshufd	("xmm0","xmm0",0xFF);
@@ -599,7 +603,7 @@
 	# subbyte
 	&movdqa	("xmm4",&QWP($k_s0F,$const));
 	&movdqa	("xmm5",&QWP($k_inv,$const));	# 4 : 1/j
-	&movdqa	("xmm1","xmm4");	
+	&movdqa	("xmm1","xmm4");
 	&pandn	("xmm1","xmm0");
 	&psrld	("xmm1",4);			# 1 = i
 	&pand	("xmm0","xmm4");		# 0 = k
@@ -901,3 +905,5 @@
 &function_end("${PREFIX}_cbc_encrypt");
 
 &asm_finish();
+
+close STDOUT;
diff --git a/src/crypto/aes/asm/vpaes-x86_64.pl b/src/crypto/aes/asm/vpaes-x86_64.pl
index f2ef318..7a24e0d 100644
--- a/src/crypto/aes/asm/vpaes-x86_64.pl
+++ b/src/crypto/aes/asm/vpaes-x86_64.pl
@@ -31,6 +31,7 @@
 # Nehalem	29.6/40.3/14.6		10.0/11.8
 # Atom		57.3/74.2/32.1		60.9/77.2(***)
 # Silvermont	52.7/64.0/19.5		48.8/60.8(***)
+# Goldmont	38.9/49.0/17.8		10.6/12.6
 #
 # (*)	"Hyper-threading" in the context refers rather to cache shared
 #	among multiple cores, than to specifically Intel HTT. As vast
@@ -57,7 +58,7 @@
 ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
 die "can't locate x86_64-xlate.pl";
 
-open OUT,"| \"$^X\" $xlate $flavour $output";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
 *STDOUT=*OUT;
 
 $PREFIX="vpaes";
@@ -164,7 +165,7 @@
 	pshufb	%xmm1,	%xmm0
 	ret
 .size	_vpaes_encrypt_core,.-_vpaes_encrypt_core
-	
+
 ##
 ##  Decryption core
 ##
@@ -325,7 +326,7 @@
 ##
 .Lschedule_128:
 	mov	\$10, %esi
-	
+
 .Loop_schedule_128:
 	call 	_vpaes_schedule_round
 	dec	%rsi
@@ -359,7 +360,7 @@
 
 .Loop_schedule_192:
 	call	_vpaes_schedule_round
-	palignr	\$8,%xmm6,%xmm0	
+	palignr	\$8,%xmm6,%xmm0
 	call	_vpaes_schedule_mangle	# save key n
 	call	_vpaes_schedule_192_smear
 	call	_vpaes_schedule_mangle	# save key n+1
@@ -385,7 +386,7 @@
 	movdqu	16(%rdi),%xmm0		# load key part 2 (unaligned)
 	call	_vpaes_schedule_transform	# input transform
 	mov	\$7, %esi
-	
+
 .Loop_schedule_256:
 	call	_vpaes_schedule_mangle	# output low result
 	movdqa	%xmm0,	%xmm6		# save cur_lo in xmm6
@@ -394,7 +395,7 @@
 	call	_vpaes_schedule_round
 	dec	%rsi
 	jz 	.Lschedule_mangle_last
-	call	_vpaes_schedule_mangle	
+	call	_vpaes_schedule_mangle
 
 	# low round. swap xmm7 and xmm6
 	pshufd	\$0xFF,	%xmm0,	%xmm0
@@ -402,10 +403,10 @@
 	movdqa	%xmm6,	%xmm7
 	call	_vpaes_schedule_low_round
 	movdqa	%xmm5,	%xmm7
-	
+
 	jmp	.Loop_schedule_256
 
-	
+
 ##
 ##  .aes_schedule_mangle_last
 ##
@@ -504,9 +505,9 @@
 	# rotate
 	pshufd	\$0xFF,	%xmm0,	%xmm0
 	palignr	\$1,	%xmm0,	%xmm0
-	
+
 	# fall through...
-	
+
 	# low round: same as high round, but no rotation and no rcon.
 _vpaes_schedule_low_round:
 	# smear xmm7
@@ -545,7 +546,7 @@
 	pxor	%xmm4, 	%xmm0		# 0 = sbox output
 
 	# add in smeared stuff
-	pxor	%xmm7,	%xmm0	
+	pxor	%xmm7,	%xmm0
 	movdqa	%xmm0,	%xmm7
 	ret
 .size	_vpaes_schedule_round,.-_vpaes_schedule_round
diff --git a/src/crypto/aes/key_wrap.c b/src/crypto/aes/key_wrap.c
new file mode 100644
index 0000000..23553b7
--- /dev/null
+++ b/src/crypto/aes/key_wrap.c
@@ -0,0 +1,138 @@
+/* ====================================================================
+ * Copyright (c) 2001-2011 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ==================================================================== */
+
+#include <openssl/aes.h>
+
+#include <limits.h>
+#include <string.h>
+
+#include <openssl/mem.h>
+
+#include "../internal.h"
+
+
+/* kDefaultIV is the default IV value given in RFC 3394, 2.2.3.1. */
+static const uint8_t kDefaultIV[] = {
+    0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
+};
+
+static const unsigned kBound = 6;
+
+int AES_wrap_key(const AES_KEY *key, const uint8_t *iv, uint8_t *out,
+                 const uint8_t *in, size_t in_len) {
+  /* See RFC 3394, section 2.2.1. */
+
+  if (in_len > INT_MAX - 8 || in_len < 8 || in_len % 8 != 0) {
+    return -1;
+  }
+
+  if (iv == NULL) {
+    iv = kDefaultIV;
+  }
+
+  OPENSSL_memmove(out + 8, in, in_len);
+  uint8_t A[AES_BLOCK_SIZE];
+  OPENSSL_memcpy(A, iv, 8);
+
+  size_t n = in_len / 8;
+
+  for (unsigned j = 0; j < kBound; j++) {
+    for (size_t i = 1; i <= n; i++) {
+      OPENSSL_memcpy(A + 8, out + 8 * i, 8);
+      AES_encrypt(A, A, key);
+
+      uint32_t t = (uint32_t)(n * j + i);
+      A[7] ^= t & 0xff;
+      A[6] ^= (t >> 8) & 0xff;
+      A[5] ^= (t >> 16) & 0xff;
+      A[4] ^= (t >> 24) & 0xff;
+      OPENSSL_memcpy(out + 8 * i, A + 8, 8);
+    }
+  }
+
+  OPENSSL_memcpy(out, A, 8);
+  return (int)in_len + 8;
+}
+
+int AES_unwrap_key(const AES_KEY *key, const uint8_t *iv, uint8_t *out,
+                   const uint8_t *in, size_t in_len) {
+  /* See RFC 3394, section 2.2.2. */
+
+  if (in_len > INT_MAX || in_len < 16 || in_len % 8 != 0) {
+    return -1;
+  }
+
+  if (iv == NULL) {
+    iv = kDefaultIV;
+  }
+
+  uint8_t A[AES_BLOCK_SIZE];
+  OPENSSL_memcpy(A, in, 8);
+  OPENSSL_memmove(out, in + 8, in_len - 8);
+
+  size_t n = (in_len / 8) - 1;
+
+  for (unsigned j = kBound - 1; j < kBound; j--) {
+    for (size_t i = n; i > 0; i--) {
+      uint32_t t = (uint32_t)(n * j + i);
+      A[7] ^= t & 0xff;
+      A[6] ^= (t >> 8) & 0xff;
+      A[5] ^= (t >> 16) & 0xff;
+      A[4] ^= (t >> 24) & 0xff;
+      OPENSSL_memcpy(A + 8, out + 8 * (i - 1), 8);
+      AES_decrypt(A, A, key);
+      OPENSSL_memcpy(out + 8 * (i - 1), A + 8, 8);
+    }
+  }
+
+  if (CRYPTO_memcmp(A, iv, 8) != 0) {
+    return -1;
+  }
+
+  return (int)in_len - 8;
+}
diff --git a/src/crypto/aes/mode_wrappers.c b/src/crypto/aes/mode_wrappers.c
index dc657dc..4929920 100644
--- a/src/crypto/aes/mode_wrappers.c
+++ b/src/crypto/aes/mode_wrappers.c
@@ -96,13 +96,17 @@
 
 void AES_ofb128_encrypt(const uint8_t *in, uint8_t *out, size_t length,
                         const AES_KEY *key, uint8_t *ivec, int *num) {
-  CRYPTO_ofb128_encrypt(in, out, length, key, ivec, num,
+  unsigned num_u = (unsigned)(*num);
+  CRYPTO_ofb128_encrypt(in, out, length, key, ivec, &num_u,
                         (block128_f)AES_encrypt);
+  *num = (int)num_u;
 }
 
 void AES_cfb128_encrypt(const uint8_t *in, uint8_t *out, size_t length,
                         const AES_KEY *key, uint8_t *ivec, int *num,
                         int enc) {
-  CRYPTO_cfb128_encrypt(in, out, length, key, ivec, num, enc,
+  unsigned num_u = (unsigned)(*num);
+  CRYPTO_cfb128_encrypt(in, out, length, key, ivec, &num_u, enc,
                         (block128_f)AES_encrypt);
+  *num = (int)num_u;
 }
diff --git a/src/crypto/asn1/CMakeLists.txt b/src/crypto/asn1/CMakeLists.txt
index 41e3122..9a5c651 100644
--- a/src/crypto/asn1/CMakeLists.txt
+++ b/src/crypto/asn1/CMakeLists.txt
@@ -7,7 +7,6 @@
 
   a_bitstr.c
   a_bool.c
-  a_bytes.c
   a_d2i_fp.c
   a_dup.c
   a_enum.c
@@ -26,20 +25,15 @@
   asn1_lib.c
   asn1_par.c
   asn_pack.c
-  bio_asn1.c
-  bio_ndef.c
   f_enum.c
   f_int.c
   f_string.c
   t_bitst.c
-  t_pkey.c
   tasn_dec.c
   tasn_enc.c
   tasn_fre.c
   tasn_new.c
-  tasn_prn.c
   tasn_typ.c
   tasn_utl.c
-  x_bignum.c
-  x_long.c
+  time_support.c
 )
diff --git a/src/crypto/asn1/a_bitstr.c b/src/crypto/asn1/a_bitstr.c
index 8bad339..ea9da24 100644
--- a/src/crypto/asn1/a_bitstr.c
+++ b/src/crypto/asn1/a_bitstr.c
@@ -33,7 +33,7 @@
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from 
+ * 4. If you include any Windows specific code (or a derivative thereof) from
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  *
@@ -61,195 +61,206 @@
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
+#include "../internal.h"
+
 
 int ASN1_BIT_STRING_set(ASN1_BIT_STRING *x, unsigned char *d, int len)
-{ return M_ASN1_BIT_STRING_set(x, d, len); }
+{
+    return M_ASN1_BIT_STRING_set(x, d, len);
+}
 
 int i2c_ASN1_BIT_STRING(ASN1_BIT_STRING *a, unsigned char **pp)
-	{
-	int ret,j,bits,len;
-	unsigned char *p,*d;
+{
+    int ret, j, bits, len;
+    unsigned char *p, *d;
 
-	if (a == NULL) return(0);
+    if (a == NULL)
+        return (0);
 
-	len=a->length;
+    len = a->length;
 
-	if (len > 0)
-		{
-		if (a->flags & ASN1_STRING_FLAG_BITS_LEFT)
-			{
-			bits=(int)a->flags&0x07;
-			}
-		else
-			{
-			for ( ; len > 0; len--)
-				{
-				if (a->data[len-1]) break;
-				}
-			j=a->data[len-1];
-			if      (j & 0x01) bits=0;
-			else if (j & 0x02) bits=1;
-			else if (j & 0x04) bits=2;
-			else if (j & 0x08) bits=3;
-			else if (j & 0x10) bits=4;
-			else if (j & 0x20) bits=5;
-			else if (j & 0x40) bits=6;
-			else if (j & 0x80) bits=7;
-			else bits=0; /* should not happen */
-			}
-		}
-	else
-		bits=0;
+    if (len > 0) {
+        if (a->flags & ASN1_STRING_FLAG_BITS_LEFT) {
+            bits = (int)a->flags & 0x07;
+        } else {
+            for (; len > 0; len--) {
+                if (a->data[len - 1])
+                    break;
+            }
+            j = a->data[len - 1];
+            if (j & 0x01)
+                bits = 0;
+            else if (j & 0x02)
+                bits = 1;
+            else if (j & 0x04)
+                bits = 2;
+            else if (j & 0x08)
+                bits = 3;
+            else if (j & 0x10)
+                bits = 4;
+            else if (j & 0x20)
+                bits = 5;
+            else if (j & 0x40)
+                bits = 6;
+            else if (j & 0x80)
+                bits = 7;
+            else
+                bits = 0;       /* should not happen */
+        }
+    } else
+        bits = 0;
 
-	ret=1+len;
-	if (pp == NULL) return(ret);
+    ret = 1 + len;
+    if (pp == NULL)
+        return (ret);
 
-	p= *pp;
+    p = *pp;
 
-	*(p++)=(unsigned char)bits;
-	d=a->data;
-	memcpy(p,d,len);
-	p+=len;
-	if (len > 0) p[-1]&=(0xff<<bits);
-	*pp=p;
-	return(ret);
-	}
+    *(p++) = (unsigned char)bits;
+    d = a->data;
+    OPENSSL_memcpy(p, d, len);
+    p += len;
+    if (len > 0)
+        p[-1] &= (0xff << bits);
+    *pp = p;
+    return (ret);
+}
 
 ASN1_BIT_STRING *c2i_ASN1_BIT_STRING(ASN1_BIT_STRING **a,
-	const unsigned char **pp, long len)
-	{
-	ASN1_BIT_STRING *ret=NULL;
-	const unsigned char *p;
-	unsigned char *s;
-	int padding;
+                                     const unsigned char **pp, long len)
+{
+    ASN1_BIT_STRING *ret = NULL;
+    const unsigned char *p;
+    unsigned char *s;
+    int padding;
 
-	if (len < 1)
-		{
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT);
-		goto err;
-		}
+    if (len < 1) {
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT);
+        goto err;
+    }
 
-	if ((a == NULL) || ((*a) == NULL))
-		{
-		if ((ret=M_ASN1_BIT_STRING_new()) == NULL) return(NULL);
-		}
-	else
-		ret=(*a);
+    if ((a == NULL) || ((*a) == NULL)) {
+        if ((ret = M_ASN1_BIT_STRING_new()) == NULL)
+            return (NULL);
+    } else
+        ret = (*a);
 
-	p= *pp;
-	padding = *(p++);
-	if (padding > 7)
-		{
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
-		goto err;
-		}
+    p = *pp;
+    padding = *(p++);
+    if (padding > 7) {
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BIT_STRING_BITS_LEFT);
+        goto err;
+    }
 
-	/* We do this to preserve the settings.  If we modify
-	 * the settings, via the _set_bit function, we will recalculate
-	 * on output */
-	ret->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear */
-	ret->flags|=(ASN1_STRING_FLAG_BITS_LEFT|padding); /* set */
+    /*
+     * We do this to preserve the settings.  If we modify the settings, via
+     * the _set_bit function, we will recalculate on output
+     */
+    ret->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear */
+    ret->flags |= (ASN1_STRING_FLAG_BITS_LEFT | padding); /* set */
 
-	if (len-- > 1) /* using one because of the bits left byte */
-		{
-		s=(unsigned char *)OPENSSL_malloc((int)len);
-		if (s == NULL)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-			goto err;
-			}
-		memcpy(s,p,(int)len);
-		s[len-1]&=(0xff<<padding);
-		p+=len;
-		}
-	else
-		s=NULL;
+    if (len-- > 1) {            /* using one because of the bits left byte */
+        s = (unsigned char *)OPENSSL_malloc((int)len);
+        if (s == NULL) {
+            OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+            goto err;
+        }
+        OPENSSL_memcpy(s, p, (int)len);
+        s[len - 1] &= (0xff << padding);
+        p += len;
+    } else
+        s = NULL;
 
-	ret->length=(int)len;
-	if (ret->data != NULL) OPENSSL_free(ret->data);
-	ret->data=s;
-	ret->type=V_ASN1_BIT_STRING;
-	if (a != NULL) (*a)=ret;
-	*pp=p;
-	return(ret);
-err:
-	if ((ret != NULL) && ((a == NULL) || (*a != ret)))
-		M_ASN1_BIT_STRING_free(ret);
-	return(NULL);
-	}
-
-/* These next 2 functions from Goetz Babin-Ebell <babinebell@trustcenter.de>
- */
-int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value)
-	{
-	int w,v,iv;
-	unsigned char *c;
-
-	w=n/8;
-	v=1<<(7-(n&0x07));
-	iv= ~v;
-	if (!value) v=0;
-
-	if (a == NULL)
-		return 0;
-
-	a->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); /* clear, set on write */
-
-	if ((a->length < (w+1)) || (a->data == NULL))
-		{
-		if (!value) return(1); /* Don't need to set */
-		if (a->data == NULL)
-			c=(unsigned char *)OPENSSL_malloc(w+1);
-		else
-			c=(unsigned char *)OPENSSL_realloc_clean(a->data,
-								 a->length,
-								 w+1);
-		if (c == NULL)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-			return 0;
-			}
-  		if (w+1-a->length > 0) memset(c+a->length, 0, w+1-a->length);
-		a->data=c;
-		a->length=w+1;
-	}
-	a->data[w]=((a->data[w])&iv)|v;
-	while ((a->length > 0) && (a->data[a->length-1] == 0))
-		a->length--;
-	return(1);
-	}
-
-int ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *a, int n)
-	{
-	int w,v;
-
-	w=n/8;
-	v=1<<(7-(n&0x07));
-	if ((a == NULL) || (a->length < (w+1)) || (a->data == NULL))
-		return(0);
-	return((a->data[w]&v) != 0);
-	}
+    ret->length = (int)len;
+    if (ret->data != NULL)
+        OPENSSL_free(ret->data);
+    ret->data = s;
+    ret->type = V_ASN1_BIT_STRING;
+    if (a != NULL)
+        (*a) = ret;
+    *pp = p;
+    return (ret);
+ err:
+    if ((ret != NULL) && ((a == NULL) || (*a != ret)))
+        M_ASN1_BIT_STRING_free(ret);
+    return (NULL);
+}
 
 /*
- * Checks if the given bit string contains only bits specified by 
+ * These next 2 functions from Goetz Babin-Ebell <babinebell@trustcenter.de>
+ */
+int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *a, int n, int value)
+{
+    int w, v, iv;
+    unsigned char *c;
+
+    w = n / 8;
+    v = 1 << (7 - (n & 0x07));
+    iv = ~v;
+    if (!value)
+        v = 0;
+
+    if (a == NULL)
+        return 0;
+
+    a->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); /* clear, set on write */
+
+    if ((a->length < (w + 1)) || (a->data == NULL)) {
+        if (!value)
+            return (1);         /* Don't need to set */
+        if (a->data == NULL)
+            c = (unsigned char *)OPENSSL_malloc(w + 1);
+        else
+            c = (unsigned char *)OPENSSL_realloc_clean(a->data,
+                                                       a->length, w + 1);
+        if (c == NULL) {
+            OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+            return 0;
+        }
+        if (w + 1 - a->length > 0)
+            OPENSSL_memset(c + a->length, 0, w + 1 - a->length);
+        a->data = c;
+        a->length = w + 1;
+    }
+    a->data[w] = ((a->data[w]) & iv) | v;
+    while ((a->length > 0) && (a->data[a->length - 1] == 0))
+        a->length--;
+    return (1);
+}
+
+int ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *a, int n)
+{
+    int w, v;
+
+    w = n / 8;
+    v = 1 << (7 - (n & 0x07));
+    if ((a == NULL) || (a->length < (w + 1)) || (a->data == NULL))
+        return (0);
+    return ((a->data[w] & v) != 0);
+}
+
+/*
+ * Checks if the given bit string contains only bits specified by
  * the flags vector. Returns 0 if there is at least one bit set in 'a'
  * which is not specified in 'flags', 1 otherwise.
  * 'len' is the length of 'flags'.
  */
 int ASN1_BIT_STRING_check(ASN1_BIT_STRING *a,
-			  unsigned char *flags, int flags_len)
-	{
-	int i, ok;
-	/* Check if there is one bit set at all. */
-	if (!a || !a->data) return 1;
+                          unsigned char *flags, int flags_len)
+{
+    int i, ok;
+    /* Check if there is one bit set at all. */
+    if (!a || !a->data)
+        return 1;
 
-	/* Check each byte of the internal representation of the bit string. */
-	ok = 1;
-	for (i = 0; i < a->length && ok; ++i)
-		{
-		unsigned char mask = i < flags_len ? ~flags[i] : 0xff;
-		/* We are done if there is an unneeded bit set. */
-		ok = (a->data[i] & mask) == 0;
-		}
-	return ok;
-	}
+    /*
+     * Check each byte of the internal representation of the bit string.
+     */
+    ok = 1;
+    for (i = 0; i < a->length && ok; ++i) {
+        unsigned char mask = i < flags_len ? ~flags[i] : 0xff;
+        /* We are done if there is an unneeded bit set. */
+        ok = (a->data[i] & mask) == 0;
+    }
+    return ok;
+}
diff --git a/src/crypto/asn1/a_bool.c b/src/crypto/asn1/a_bool.c
index 826bcf4..64a079e 100644
--- a/src/crypto/asn1/a_bool.c
+++ b/src/crypto/asn1/a_bool.c
@@ -33,7 +33,7 @@
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from 
+ * 4. If you include any Windows specific code (or a derivative thereof) from
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
  *
@@ -59,54 +59,52 @@
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
-
 int i2d_ASN1_BOOLEAN(int a, unsigned char **pp)
-	{
-	int r;
-	unsigned char *p;
+{
+    int r;
+    unsigned char *p;
 
-	r=ASN1_object_size(0,1,V_ASN1_BOOLEAN);
-	if (pp == NULL) return(r);
-	p= *pp;
+    r = ASN1_object_size(0, 1, V_ASN1_BOOLEAN);
+    if (pp == NULL)
+        return (r);
+    p = *pp;
 
-	ASN1_put_object(&p,0,1,V_ASN1_BOOLEAN,V_ASN1_UNIVERSAL);
-	*(p++)= (unsigned char)a;
-	*pp=p;
-	return(r);
-	}
+    ASN1_put_object(&p, 0, 1, V_ASN1_BOOLEAN, V_ASN1_UNIVERSAL);
+    *(p++) = (unsigned char)a;
+    *pp = p;
+    return (r);
+}
 
 int d2i_ASN1_BOOLEAN(int *a, const unsigned char **pp, long length)
-	{
-	int ret= -1;
-	const unsigned char *p;
-	long len;
-	int inf,tag,xclass;
-	int i=0;
+{
+    int ret = -1;
+    const unsigned char *p;
+    long len;
+    int inf, tag, xclass;
+    int i = 0;
 
-	p= *pp;
-	inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
-	if (inf & 0x80)
-		{
-		i=ASN1_R_BAD_OBJECT_HEADER;
-		goto err;
-		}
+    p = *pp;
+    inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
+    if (inf & 0x80) {
+        i = ASN1_R_BAD_OBJECT_HEADER;
+        goto err;
+    }
 
-	if (tag != V_ASN1_BOOLEAN)
-		{
-		i=ASN1_R_EXPECTING_A_BOOLEAN;
-		goto err;
-		}
+    if (tag != V_ASN1_BOOLEAN) {
+        i = ASN1_R_EXPECTING_A_BOOLEAN;
+        goto err;
+    }
 
-	if (len != 1)
-		{
-		i=ASN1_R_BOOLEAN_IS_WRONG_LENGTH;
-		goto err;
-		}
-	ret= (int)*(p++);
-	if (a != NULL) (*a)=ret;
-	*pp=p;
-	return(ret);
-err:
-	OPENSSL_PUT_ERROR(ASN1, i);
-	return(ret);
-	}
+    if (len != 1) {
+        i = ASN1_R_BOOLEAN_IS_WRONG_LENGTH;
+        goto err;
+    }
+    ret = (int)*(p++);
+    if (a != NULL)
+        (*a) = ret;
+    *pp = p;
+    return (ret);
+ err:
+    OPENSSL_PUT_ERROR(ASN1, i);
+    return (ret);
+}
diff --git a/src/crypto/asn1/a_bytes.c b/src/crypto/asn1/a_bytes.c
deleted file mode 100644
index 1904375..0000000
--- a/src/crypto/asn1/a_bytes.c
+++ /dev/null
@@ -1,317 +0,0 @@
-/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to.  The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *    "This product includes cryptographic software written by
- *     Eric Young (eay@cryptsoft.com)"
- *    The word 'cryptographic' can be left out if the rouines from the library
- *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- *    the apps directory (application code) you must include an acknowledgement:
- *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed.  i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.] */
-
-#include <openssl/asn1.h>
-
-#include <string.h>
-
-#include <openssl/buf.h>
-#include <openssl/err.h>
-#include <openssl/mem.h>
-
-
-static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c);
-/* type is a 'bitmap' of acceptable string types.
- */
-ASN1_STRING *d2i_ASN1_type_bytes(ASN1_STRING **a, const unsigned char **pp,
-	     long length, int type)
-	{
-	ASN1_STRING *ret=NULL;
-	const unsigned char *p;
-	unsigned char *s;
-	long len;
-	int inf,tag,xclass;
-	int i=0;
-
-	p= *pp;
-	inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
-	if (inf & 0x80) goto err;
-
-	if (tag >= 32)
-		{
-		i=ASN1_R_TAG_VALUE_TOO_HIGH;
-		goto err;
-		}
-	if (!(ASN1_tag2bit(tag) & type))
-		{
-		i=ASN1_R_WRONG_TYPE;
-		goto err;
-		}
-
-	/* If a bit-string, exit early */
-	if (tag == V_ASN1_BIT_STRING)
-		return(d2i_ASN1_BIT_STRING(a,pp,length));
-
-	if ((a == NULL) || ((*a) == NULL))
-		{
-		if ((ret=ASN1_STRING_new()) == NULL) return(NULL);
-		}
-	else
-		ret=(*a);
-
-	if (len != 0)
-		{
-		s=(unsigned char *)OPENSSL_malloc((int)len+1);
-		if (s == NULL)
-			{
-			i=ERR_R_MALLOC_FAILURE;
-			goto err;
-			}
-		memcpy(s,p,(int)len);
-		s[len]='\0';
-		p+=len;
-		}
-	else
-		s=NULL;
-
-	if (ret->data != NULL) OPENSSL_free(ret->data);
-	ret->length=(int)len;
-	ret->data=s;
-	ret->type=tag;
-	if (a != NULL) (*a)=ret;
-	*pp=p;
-	return(ret);
-err:
-	OPENSSL_PUT_ERROR(ASN1, i);
-	if ((ret != NULL) && ((a == NULL) || (*a != ret)))
-		ASN1_STRING_free(ret);
-	return(NULL);
-	}
-
-int i2d_ASN1_bytes(ASN1_STRING *a, unsigned char **pp, int tag, int xclass)
-	{
-	int ret,r,constructed;
-	unsigned char *p;
-
-	if (a == NULL)  return(0);
-
-	if (tag == V_ASN1_BIT_STRING)
-		return(i2d_ASN1_BIT_STRING(a,pp));
-		
-	ret=a->length;
-	r=ASN1_object_size(0,ret,tag);
-	if (pp == NULL) return(r);
-	p= *pp;
-
-	if ((tag == V_ASN1_SEQUENCE) || (tag == V_ASN1_SET))
-		constructed=1;
-	else
-		constructed=0;
-	ASN1_put_object(&p,constructed,ret,tag,xclass);
-	memcpy(p,a->data,a->length);
-	p+=a->length;
-	*pp= p;
-	return(r);
-	}
-
-ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp,
-	     long length, int Ptag, int Pclass)
-	{
-	ASN1_STRING *ret=NULL;
-	const unsigned char *p;
-	unsigned char *s;
-	long len;
-	int inf,tag,xclass;
-	int i=0;
-
-	if ((a == NULL) || ((*a) == NULL))
-		{
-		if ((ret=ASN1_STRING_new()) == NULL) return(NULL);
-		}
-	else
-		ret=(*a);
-
-	p= *pp;
-	inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
-	if (inf & 0x80)
-		{
-		i=ASN1_R_BAD_OBJECT_HEADER;
-		goto err;
-		}
-
-	if (tag != Ptag)
-		{
-		i=ASN1_R_WRONG_TAG;
-		goto err;
-		}
-
-	if (inf & V_ASN1_CONSTRUCTED)
-		{
-		ASN1_const_CTX c;
-
-		c.pp=pp;
-		c.p=p;
-		c.inf=inf;
-		c.slen=len;
-		c.tag=Ptag;
-		c.xclass=Pclass;
-		c.max=(length == 0)?0:(p+length);
-		if (!asn1_collate_primitive(ret,&c)) 
-			goto err; 
-		else
-			{
-			p=c.p;
-			}
-		}
-	else
-		{
-		if (len != 0)
-			{
-			if ((ret->length < len) || (ret->data == NULL))
-				{
-				if (ret->data != NULL) OPENSSL_free(ret->data);
-				s=(unsigned char *)OPENSSL_malloc((int)len + 1);
-				if (s == NULL)
-					{
-					i=ERR_R_MALLOC_FAILURE;
-					goto err;
-					}
-				}
-			else
-				s=ret->data;
-			memcpy(s,p,(int)len);
-			s[len] = '\0';
-			p+=len;
-			}
-		else
-			{
-			s=NULL;
-			if (ret->data != NULL) OPENSSL_free(ret->data);
-			}
-
-		ret->length=(int)len;
-		ret->data=s;
-		ret->type=Ptag;
-		}
-
-	if (a != NULL) (*a)=ret;
-	*pp=p;
-	return(ret);
-err:
-	if ((ret != NULL) && ((a == NULL) || (*a != ret)))
-		ASN1_STRING_free(ret);
-	OPENSSL_PUT_ERROR(ASN1, i);
-	return(NULL);
-	}
-
-
-/* We are about to parse 0..n d2i_ASN1_bytes objects, we are to collapse
- * them into the one structure that is then returned */
-/* There have been a few bug fixes for this function from
- * Paul Keogh <paul.keogh@sse.ie>, many thanks to him */
-static int asn1_collate_primitive(ASN1_STRING *a, ASN1_const_CTX *c)
-	{
-	ASN1_STRING *os=NULL;
-	BUF_MEM b;
-	int num;
-
-	b.length=0;
-	b.max=0;
-	b.data=NULL;
-
-	if (a == NULL)
-		{
-		c->error=ERR_R_PASSED_NULL_PARAMETER;
-		goto err;
-		}
-
-	num=0;
-	for (;;)
-		{
-		if (c->inf & 1)
-			{
-			c->eos=ASN1_const_check_infinite_end(&c->p,
-				(long)(c->max-c->p));
-			if (c->eos) break;
-			}
-		else
-			{
-			if (c->slen <= 0) break;
-			}
-
-		c->q=c->p;
-		if (d2i_ASN1_bytes(&os,&c->p,c->max-c->p,c->tag,c->xclass)
-			== NULL)
-			{
-			c->error=ERR_R_ASN1_LIB;
-			goto err;
-			}
-
-		if (!BUF_MEM_grow_clean(&b,num+os->length))
-			{
-			c->error=ERR_R_BUF_LIB;
-			goto err;
-			}
-		memcpy(&(b.data[num]),os->data,os->length);
-		if (!(c->inf & 1))
-			c->slen-=(c->p-c->q);
-		num+=os->length;
-		}
-
-	if (!asn1_const_Finish(c)) goto err;
-
-	a->length=num;
-	if (a->data != NULL) OPENSSL_free(a->data);
-	a->data=(unsigned char *)b.data;
-	if (os != NULL) ASN1_STRING_free(os);
-	return(1);
-err:
-	OPENSSL_PUT_ERROR(ASN1, c->error);
-	if (os != NULL) ASN1_STRING_free(os);
-	if (b.data != NULL) OPENSSL_free(b.data);
-	return(0);
-	}
-
diff --git a/src/crypto/asn1/a_d2i_fp.c b/src/crypto/asn1/a_d2i_fp.c
index af03bc0..b544971 100644
--- a/src/crypto/asn1/a_d2i_fp.c
+++ b/src/crypto/asn1/a_d2i_fp.c
@@ -62,241 +62,221 @@
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
-
 static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb);
 
 #ifndef NO_OLD_ASN1
-#ifndef OPENSSL_NO_FP_API
+# ifndef OPENSSL_NO_FP_API
 
-void *ASN1_d2i_fp(void *(*xnew)(void), d2i_of_void *d2i, FILE *in, void **x)
-        {
-        BIO *b;
-        void *ret;
+void *ASN1_d2i_fp(void *(*xnew) (void), d2i_of_void *d2i, FILE *in, void **x)
+{
+    BIO *b;
+    void *ret;
 
-        if ((b=BIO_new(BIO_s_file())) == NULL)
-		{
-		OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
-                return(NULL);
-		}
-        BIO_set_fp(b,in,BIO_NOCLOSE);
-        ret=ASN1_d2i_bio(xnew,d2i,b,x);
-        BIO_free(b);
-        return(ret);
-        }
-#endif
+    if ((b = BIO_new(BIO_s_file())) == NULL) {
+        OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
+        return (NULL);
+    }
+    BIO_set_fp(b, in, BIO_NOCLOSE);
+    ret = ASN1_d2i_bio(xnew, d2i, b, x);
+    BIO_free(b);
+    return (ret);
+}
+# endif
 
-void *ASN1_d2i_bio(void *(*xnew)(void), d2i_of_void *d2i, BIO *in, void **x)
-	{
-	BUF_MEM *b = NULL;
-	const unsigned char *p;
-	void *ret=NULL;
-	int len;
+void *ASN1_d2i_bio(void *(*xnew) (void), d2i_of_void *d2i, BIO *in, void **x)
+{
+    BUF_MEM *b = NULL;
+    const unsigned char *p;
+    void *ret = NULL;
+    int len;
 
-	len = asn1_d2i_read_bio(in, &b);
-	if(len < 0) goto err;
+    len = asn1_d2i_read_bio(in, &b);
+    if (len < 0)
+        goto err;
 
-	p=(unsigned char *)b->data;
-	ret=d2i(x,&p,len);
-err:
-	if (b != NULL) BUF_MEM_free(b);
-	return(ret);
-	}
+    p = (unsigned char *)b->data;
+    ret = d2i(x, &p, len);
+ err:
+    if (b != NULL)
+        BUF_MEM_free(b);
+    return (ret);
+}
 
 #endif
 
 void *ASN1_item_d2i_bio(const ASN1_ITEM *it, BIO *in, void *x)
-	{
-	BUF_MEM *b = NULL;
-	const unsigned char *p;
-	void *ret=NULL;
-	int len;
+{
+    BUF_MEM *b = NULL;
+    const unsigned char *p;
+    void *ret = NULL;
+    int len;
 
-	len = asn1_d2i_read_bio(in, &b);
-	if(len < 0) goto err;
+    len = asn1_d2i_read_bio(in, &b);
+    if (len < 0)
+        goto err;
 
-	p=(const unsigned char *)b->data;
-	ret=ASN1_item_d2i(x,&p,len, it);
-err:
-	if (b != NULL) BUF_MEM_free(b);
-	return(ret);
-	}
+    p = (const unsigned char *)b->data;
+    ret = ASN1_item_d2i(x, &p, len, it);
+ err:
+    if (b != NULL)
+        BUF_MEM_free(b);
+    return (ret);
+}
 
 #ifndef OPENSSL_NO_FP_API
 void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x)
-        {
-        BIO *b;
-        char *ret;
+{
+    BIO *b;
+    char *ret;
 
-        if ((b=BIO_new(BIO_s_file())) == NULL)
-		{
-		OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
-                return(NULL);
-		}
-        BIO_set_fp(b,in,BIO_NOCLOSE);
-        ret=ASN1_item_d2i_bio(it,b,x);
-        BIO_free(b);
-        return(ret);
-        }
+    if ((b = BIO_new(BIO_s_file())) == NULL) {
+        OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
+        return (NULL);
+    }
+    BIO_set_fp(b, in, BIO_NOCLOSE);
+    ret = ASN1_item_d2i_bio(it, b, x);
+    BIO_free(b);
+    return (ret);
+}
 #endif
 
 #define HEADER_SIZE   8
 #define ASN1_CHUNK_INITIAL_SIZE (16 * 1024)
 static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
-	{
-	BUF_MEM *b;
-	unsigned char *p;
-	int i;
-	ASN1_const_CTX c;
-	size_t want=HEADER_SIZE;
-	int eos=0;
-	size_t off=0;
-	size_t len=0;
+{
+    BUF_MEM *b;
+    unsigned char *p;
+    int i;
+    ASN1_const_CTX c;
+    size_t want = HEADER_SIZE;
+    int eos = 0;
+    size_t off = 0;
+    size_t len = 0;
 
-	b=BUF_MEM_new();
-	if (b == NULL)
-		{
-		OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-		return -1;
-		}
+    b = BUF_MEM_new();
+    if (b == NULL) {
+        OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+        return -1;
+    }
 
-	ERR_clear_error();
-	for (;;)
-		{
-		if (want >= (len-off))
-			{
-			want-=(len-off);
+    ERR_clear_error();
+    for (;;) {
+        if (want >= (len - off)) {
+            want -= (len - off);
 
-			if (len + want < len || !BUF_MEM_grow_clean(b,len+want))
-				{
-				OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-				goto err;
-				}
-			i=BIO_read(in,&(b->data[len]),want);
-			if ((i < 0) && ((len-off) == 0))
-				{
-				OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA);
-				goto err;
-				}
-			if (i > 0)
-				{
-				if (len+i < len)
-					{
-					OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
-					goto err;
-					}
-				len+=i;
-				}
-			}
-		/* else data already loaded */
+            if (len + want < len || !BUF_MEM_grow_clean(b, len + want)) {
+                OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+                goto err;
+            }
+            i = BIO_read(in, &(b->data[len]), want);
+            if ((i < 0) && ((len - off) == 0)) {
+                OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA);
+                goto err;
+            }
+            if (i > 0) {
+                if (len + i < len) {
+                    OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
+                    goto err;
+                }
+                len += i;
+            }
+        }
+        /* else data already loaded */
 
-		p=(unsigned char *)&(b->data[off]);
-		c.p=p;
-		c.inf=ASN1_get_object(&(c.p),&(c.slen),&(c.tag),&(c.xclass),
-			len-off);
-		if (c.inf & 0x80)
-			{
-			uint32_t e;
+        p = (unsigned char *)&(b->data[off]);
+        c.p = p;
+        c.inf = ASN1_get_object(&(c.p), &(c.slen), &(c.tag), &(c.xclass),
+                                len - off);
+        if (c.inf & 0x80) {
+            uint32_t e;
 
-			e=ERR_GET_REASON(ERR_peek_error());
-			if (e != ASN1_R_TOO_LONG)
-				goto err;
-			else
-				ERR_clear_error(); /* clear error */
-			}
-		i=c.p-p;/* header length */
-		off+=i;	/* end of data */
+            e = ERR_GET_REASON(ERR_peek_error());
+            if (e != ASN1_R_TOO_LONG)
+                goto err;
+            else
+                ERR_clear_error(); /* clear error */
+        }
+        i = c.p - p;            /* header length */
+        off += i;               /* end of data */
 
-		if (c.inf & 1)
-			{
-			/* no data body so go round again */
-			eos++;
-			if (eos < 0)
-				{
-				OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG);
-				goto err;
-				}
-			want=HEADER_SIZE;
-			}
-		else if (eos && (c.slen == 0) && (c.tag == V_ASN1_EOC))
-			{
-			/* eos value, so go back and read another header */
-			eos--;
-			if (eos <= 0)
-				break;
-			else
-				want=HEADER_SIZE;
-			}
-		else 
-			{
-			/* suck in c.slen bytes of data */
-			want=c.slen;
-			if (want > (len-off))
-				{
-                                size_t chunk_max = ASN1_CHUNK_INITIAL_SIZE;
-				want-=(len-off);
-				if (want > INT_MAX /* BIO_read takes an int length */ ||
-					len+want < len)
-						{
-						OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
-						goto err;
-						}
-				while (want > 0)
-					{
+        if (c.inf & 1) {
+            /* no data body so go round again */
+            eos++;
+            if (eos < 0) {
+                OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG);
+                goto err;
+            }
+            want = HEADER_SIZE;
+        } else if (eos && (c.slen == 0) && (c.tag == V_ASN1_EOC)) {
+            /* eos value, so go back and read another header */
+            eos--;
+            if (eos <= 0)
+                break;
+            else
+                want = HEADER_SIZE;
+        } else {
+            /* suck in c.slen bytes of data */
+            want = c.slen;
+            if (want > (len - off)) {
+                size_t chunk_max = ASN1_CHUNK_INITIAL_SIZE;
+                want -= (len - off);
+                if (want > INT_MAX /* BIO_read takes an int length */  ||
+                    len + want < len) {
+                    OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
+                    goto err;
+                }
+                while (want > 0) {
+                    /*
+                     * Read content in chunks of increasing size
+                     * so we can return an error for EOF without
+                     * having to allocate the entire content length
+                     * in one go.
+                     */
+                    size_t chunk = want > chunk_max ? chunk_max : want;
 
-                                        /*
-                                         * Read content in chunks of increasing size
-                                         * so we can return an error for EOF without
-                                         * having to allocate the entire content length
-                                         * in one go.
-                                         */
-                                        size_t chunk = want > chunk_max ? chunk_max : want;
+                    if (!BUF_MEM_grow_clean(b, len + chunk)) {
+                        OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+                        goto err;
+                    }
+                    want -= chunk;
+                    while (chunk > 0) {
+                        i = BIO_read(in, &(b->data[len]), chunk);
+                        if (i <= 0) {
+                            OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA);
+                            goto err;
+                        }
+                        /*
+                         * This can't overflow because |len+want| didn't
+                         * overflow.
+                         */
+                        len += i;
+                        chunk -= i;
+                    }
+                    if (chunk_max < INT_MAX/2)
+                        chunk_max *= 2;
+                }
+            }
+            if (off + c.slen < off) {
+                OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
+                goto err;
+            }
+            off += c.slen;
+            if (eos <= 0) {
+                break;
+            } else
+                want = HEADER_SIZE;
+        }
+    }
 
-                                        if (!BUF_MEM_grow_clean(b, len + chunk)) {
-                                          OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-                                          goto err;
-                                        }
-                                        want -= chunk;
-                                        while (chunk > 0) {
-                                          i = BIO_read(in, &(b->data[len]), chunk);
-                                          if (i <= 0) {
-                                            OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ENOUGH_DATA);
-                                            goto err;
-                                          }
-                                          /*
-                                           * This can't overflow because |len+want| didn't
-                                           * overflow.
-                                           */
-                                          len += i;
-                                          chunk -= i;
-                                        }
-                                        if (chunk_max < INT_MAX/2)
-                                          chunk_max *= 2;
-					}
-				}
-			if (off + c.slen < off)
-				{
-				OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
-				goto err;
-				}
-			off+=c.slen;
-			if (eos <= 0)
-				{
-				break;
-				}
-			else
-				want=HEADER_SIZE;
-			}
-		}
+    if (off > INT_MAX) {
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
+        goto err;
+    }
 
-	if (off > INT_MAX)
-		{
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
-		goto err;
-		}
-
-	*pb = b;
-	return off;
-err:
-	if (b != NULL) BUF_MEM_free(b);
-	return -1;
-	}
+    *pb = b;
+    return off;
+ err:
+    if (b != NULL)
+        BUF_MEM_free(b);
+    return -1;
+}
diff --git a/src/crypto/asn1/a_dup.c b/src/crypto/asn1/a_dup.c
index 5e87457..57394f5 100644
--- a/src/crypto/asn1/a_dup.c
+++ b/src/crypto/asn1/a_dup.c
@@ -59,45 +59,53 @@
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
-
 void *ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, void *x)
-	{
-	unsigned char *b,*p;
-	const unsigned char *p2;
-	int i;
-	char *ret;
+{
+    unsigned char *b, *p;
+    const unsigned char *p2;
+    int i;
+    char *ret;
 
-	if (x == NULL) return(NULL);
+    if (x == NULL)
+        return (NULL);
 
-	i=i2d(x,NULL);
-	b=OPENSSL_malloc(i+10);
-	if (b == NULL)
-		{ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); return(NULL); }
-	p= b;
-	i=i2d(x,&p);
-	p2= b;
-	ret=d2i(NULL,&p2,i);
-	OPENSSL_free(b);
-	return(ret);
-	}
+    i = i2d(x, NULL);
+    b = OPENSSL_malloc(i + 10);
+    if (b == NULL) {
+        OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+        return (NULL);
+    }
+    p = b;
+    i = i2d(x, &p);
+    p2 = b;
+    ret = d2i(NULL, &p2, i);
+    OPENSSL_free(b);
+    return (ret);
+}
 
-/* ASN1_ITEM version of dup: this follows the model above except we don't need
- * to allocate the buffer. At some point this could be rewritten to directly dup
- * the underlying structure instead of doing and encode and decode. */
+/*
+ * ASN1_ITEM version of dup: this follows the model above except we don't
+ * need to allocate the buffer. At some point this could be rewritten to
+ * directly dup the underlying structure instead of doing and encode and
+ * decode.
+ */
 void *ASN1_item_dup(const ASN1_ITEM *it, void *x)
-	{
-	unsigned char *b = NULL;
-	const unsigned char *p;
-	long i;
-	void *ret;
+{
+    unsigned char *b = NULL;
+    const unsigned char *p;
+    long i;
+    void *ret;
 
-	if (x == NULL) return(NULL);
+    if (x == NULL)
+        return (NULL);
 
-	i=ASN1_item_i2d(x,&b,it);
-	if (b == NULL)
-		{ OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); return(NULL); }
-	p= b;
-	ret=ASN1_item_d2i(NULL,&p,i, it);
-	OPENSSL_free(b);
-	return(ret);
-	}
+    i = ASN1_item_i2d(x, &b, it);
+    if (b == NULL) {
+        OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+        return (NULL);
+    }
+    p = b;
+    ret = ASN1_item_d2i(NULL, &p, i, it);
+    OPENSSL_free(b);
+    return (ret);
+}
diff --git a/src/crypto/asn1/a_enum.c b/src/crypto/asn1/a_enum.c
index 579dafd..cc46905 100644
--- a/src/crypto/asn1/a_enum.c
+++ b/src/crypto/asn1/a_enum.c
@@ -61,123 +61,124 @@
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
+#include "../internal.h"
 
-/* 
+
+/*
  * Code for ENUMERATED type: identical to INTEGER apart from a different tag.
  * for comments on encoding see a_int.c
  */
 
 int ASN1_ENUMERATED_set(ASN1_ENUMERATED *a, long v)
-	{
-	int j,k;
-	unsigned int i;
-	unsigned char buf[sizeof(long)+1];
-	long d;
+{
+    int j, k;
+    unsigned int i;
+    unsigned char buf[sizeof(long) + 1];
+    long d;
 
-	a->type=V_ASN1_ENUMERATED;
-	if (a->length < (int)(sizeof(long)+1))
-		{
-		if (a->data != NULL)
-			OPENSSL_free(a->data);
-		if ((a->data=(unsigned char *)OPENSSL_malloc(sizeof(long)+1)) != NULL)
-			memset((char *)a->data,0,sizeof(long)+1);
-		}
-	if (a->data == NULL)
-		{
-		OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-		return(0);
-		}
-	d=v;
-	if (d < 0)
-		{
-		d= -d;
-		a->type=V_ASN1_NEG_ENUMERATED;
-		}
+    a->type = V_ASN1_ENUMERATED;
+    if (a->length < (int)(sizeof(long) + 1)) {
+        if (a->data != NULL)
+            OPENSSL_free(a->data);
+        if ((a->data =
+             (unsigned char *)OPENSSL_malloc(sizeof(long) + 1)) != NULL)
+            OPENSSL_memset((char *)a->data, 0, sizeof(long) + 1);
+    }
+    if (a->data == NULL) {
+        OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+        return (0);
+    }
+    d = v;
+    if (d < 0) {
+        d = -d;
+        a->type = V_ASN1_NEG_ENUMERATED;
+    }
 
-	for (i=0; i<sizeof(long); i++)
-		{
-		if (d == 0) break;
-		buf[i]=(int)d&0xff;
-		d>>=8;
-		}
-	j=0;
-	for (k=i-1; k >=0; k--)
-		a->data[j++]=buf[k];
-	a->length=j;
-	return(1);
-	}
+    for (i = 0; i < sizeof(long); i++) {
+        if (d == 0)
+            break;
+        buf[i] = (int)d & 0xff;
+        d >>= 8;
+    }
+    j = 0;
+    for (k = i - 1; k >= 0; k--)
+        a->data[j++] = buf[k];
+    a->length = j;
+    return (1);
+}
 
 long ASN1_ENUMERATED_get(ASN1_ENUMERATED *a)
-	{
-	int neg=0,i;
-	long r=0;
+{
+    int neg = 0, i;
+    long r = 0;
 
-	if (a == NULL) return(0L);
-	i=a->type;
-	if (i == V_ASN1_NEG_ENUMERATED)
-		neg=1;
-	else if (i != V_ASN1_ENUMERATED)
-		return -1;
-	
-	if (a->length > (int)sizeof(long))
-		{
-		/* hmm... a bit ugly */
-		return(0xffffffffL);
-		}
-	if (a->data == NULL)
-		return 0;
+    if (a == NULL)
+        return (0L);
+    i = a->type;
+    if (i == V_ASN1_NEG_ENUMERATED)
+        neg = 1;
+    else if (i != V_ASN1_ENUMERATED)
+        return -1;
 
-	for (i=0; i<a->length; i++)
-		{
-		r<<=8;
-		r|=(unsigned char)a->data[i];
-		}
-	if (neg) r= -r;
-	return(r);
-	}
+    if (a->length > (int)sizeof(long)) {
+        /* hmm... a bit ugly */
+        return (0xffffffffL);
+    }
+    if (a->data == NULL)
+        return 0;
+
+    for (i = 0; i < a->length; i++) {
+        r <<= 8;
+        r |= (unsigned char)a->data[i];
+    }
+    if (neg)
+        r = -r;
+    return (r);
+}
 
 ASN1_ENUMERATED *BN_to_ASN1_ENUMERATED(BIGNUM *bn, ASN1_ENUMERATED *ai)
-	{
-	ASN1_ENUMERATED *ret;
-	int len,j;
+{
+    ASN1_ENUMERATED *ret;
+    int len, j;
 
-	if (ai == NULL)
-		ret=M_ASN1_ENUMERATED_new();
-	else
-		ret=ai;
-	if (ret == NULL)
-		{
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
-		goto err;
-		}
-	if(BN_is_negative(bn)) ret->type = V_ASN1_NEG_ENUMERATED;
-	else ret->type=V_ASN1_ENUMERATED;
-	j=BN_num_bits(bn);
-	len=((j == 0)?0:((j/8)+1));
-	if (ret->length < len+4)
-		{
-		unsigned char *new_data=OPENSSL_realloc(ret->data, len+4);
-		if (!new_data)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-			goto err;
-			}
-		ret->data=new_data;
-		}
+    if (ai == NULL)
+        ret = M_ASN1_ENUMERATED_new();
+    else
+        ret = ai;
+    if (ret == NULL) {
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+        goto err;
+    }
+    if (BN_is_negative(bn))
+        ret->type = V_ASN1_NEG_ENUMERATED;
+    else
+        ret->type = V_ASN1_ENUMERATED;
+    j = BN_num_bits(bn);
+    len = ((j == 0) ? 0 : ((j / 8) + 1));
+    if (ret->length < len + 4) {
+        unsigned char *new_data = OPENSSL_realloc(ret->data, len + 4);
+        if (!new_data) {
+            OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+            goto err;
+        }
+        ret->data = new_data;
+    }
 
-	ret->length=BN_bn2bin(bn,ret->data);
-	return(ret);
-err:
-	if (ret != ai) M_ASN1_ENUMERATED_free(ret);
-	return(NULL);
-	}
+    ret->length = BN_bn2bin(bn, ret->data);
+    return (ret);
+ err:
+    if (ret != ai)
+        M_ASN1_ENUMERATED_free(ret);
+    return (NULL);
+}
 
 BIGNUM *ASN1_ENUMERATED_to_BN(ASN1_ENUMERATED *ai, BIGNUM *bn)
-	{
-	BIGNUM *ret;
+{
+    BIGNUM *ret;
 
-	if ((ret=BN_bin2bn(ai->data,ai->length,bn)) == NULL)
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_BN_LIB);
-	else if(ai->type == V_ASN1_NEG_ENUMERATED) BN_set_negative(ret,1);
-	return(ret);
-	}
+    if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL)
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_BN_LIB);
+    else if (ai->type == V_ASN1_NEG_ENUMERATED)
+        BN_set_negative(ret, 1);
+    return (ret);
+}
diff --git a/src/crypto/asn1/a_gentm.c b/src/crypto/asn1/a_gentm.c
index 7cb18a9..d130cdf 100644
--- a/src/crypto/asn1/a_gentm.c
+++ b/src/crypto/asn1/a_gentm.c
@@ -61,195 +61,201 @@
 
 #include <openssl/err.h>
 #include <openssl/mem.h>
-#include <openssl/time_support.h>
 
+#include "asn1_locl.h"
 
 int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d)
-	{
-	static const int min[9]={ 0, 0, 1, 1, 0, 0, 0, 0, 0};
-	static const int max[9]={99, 99,12,31,23,59,59,12,59};
-	char *a;
-	int n,i,l,o;
+{
+    static const int min[9] = { 0, 0, 1, 1, 0, 0, 0, 0, 0 };
+    static const int max[9] = { 99, 99, 12, 31, 23, 59, 59, 12, 59 };
+    char *a;
+    int n, i, l, o;
 
-	if (d->type != V_ASN1_GENERALIZEDTIME) return(0);
-	l=d->length;
-	a=(char *)d->data;
-	o=0;
-	/* GENERALIZEDTIME is similar to UTCTIME except the year is
-         * represented as YYYY. This stuff treats everything as a two digit
-         * field so make first two fields 00 to 99
-         */
-	if (l < 13) goto err;
-	for (i=0; i<7; i++)
-		{
-		if ((i == 6) && ((a[o] == 'Z') ||
-			(a[o] == '+') || (a[o] == '-')))
-			{
-			i++;
-			if (tm)
-				tm->tm_sec = 0;
-			break;
-			}
-		if ((a[o] < '0') || (a[o] > '9')) goto err;
-		n= a[o]-'0';
-		if (++o > l) goto err;
+    if (d->type != V_ASN1_GENERALIZEDTIME)
+        return (0);
+    l = d->length;
+    a = (char *)d->data;
+    o = 0;
+    /*
+     * GENERALIZEDTIME is similar to UTCTIME except the year is represented
+     * as YYYY. This stuff treats everything as a two digit field so make
+     * first two fields 00 to 99
+     */
+    if (l < 13)
+        goto err;
+    for (i = 0; i < 7; i++) {
+        if ((i == 6) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) {
+            i++;
+            if (tm)
+                tm->tm_sec = 0;
+            break;
+        }
+        if ((a[o] < '0') || (a[o] > '9'))
+            goto err;
+        n = a[o] - '0';
+        if (++o > l)
+            goto err;
 
-		if ((a[o] < '0') || (a[o] > '9')) goto err;
-		n=(n*10)+ a[o]-'0';
-		if (++o > l) goto err;
+        if ((a[o] < '0') || (a[o] > '9'))
+            goto err;
+        n = (n * 10) + a[o] - '0';
+        if (++o > l)
+            goto err;
 
-		if ((n < min[i]) || (n > max[i])) goto err;
-		if (tm)
-			{
-			switch(i)
-				{
-			case 0:
-				tm->tm_year = n * 100 - 1900;
-				break;
-			case 1:
-				tm->tm_year += n;
-				break;
-			case 2:
-				tm->tm_mon = n - 1;
-				break;
-			case 3:
-				tm->tm_mday = n;
-				break;
-			case 4:
-				tm->tm_hour = n;
-				break;
-			case 5:
-				tm->tm_min = n;
-				break;
-			case 6:
-				tm->tm_sec = n;
-				break;
-				}
-			}
-		}
-	/* Optional fractional seconds: decimal point followed by one
-	 * or more digits.
-	 */
-	if (a[o] == '.')
-		{
-		if (++o > l) goto err;
-		i = o;
-		while ((a[o] >= '0') && (a[o] <= '9') && (o <= l))
-			o++;
-		/* Must have at least one digit after decimal point */
-		if (i == o) goto err;
-		}
+        if ((n < min[i]) || (n > max[i]))
+            goto err;
+        if (tm) {
+            switch (i) {
+            case 0:
+                tm->tm_year = n * 100 - 1900;
+                break;
+            case 1:
+                tm->tm_year += n;
+                break;
+            case 2:
+                tm->tm_mon = n - 1;
+                break;
+            case 3:
+                tm->tm_mday = n;
+                break;
+            case 4:
+                tm->tm_hour = n;
+                break;
+            case 5:
+                tm->tm_min = n;
+                break;
+            case 6:
+                tm->tm_sec = n;
+                break;
+            }
+        }
+    }
+    /*
+     * Optional fractional seconds: decimal point followed by one or more
+     * digits.
+     */
+    if (a[o] == '.') {
+        if (++o > l)
+            goto err;
+        i = o;
+        while ((a[o] >= '0') && (a[o] <= '9') && (o <= l))
+            o++;
+        /* Must have at least one digit after decimal point */
+        if (i == o)
+            goto err;
+    }
 
-	if (a[o] == 'Z')
-		o++;
-	else if ((a[o] == '+') || (a[o] == '-'))
-		{
-		int offsign = a[o] == '-' ? -1 : 1, offset = 0;
-		o++;
-		if (o+4 > l) goto err;
-		for (i=7; i<9; i++)
-			{
-			if ((a[o] < '0') || (a[o] > '9')) goto err;
-			n= a[o]-'0';
-			o++;
-			if ((a[o] < '0') || (a[o] > '9')) goto err;
-			n=(n*10)+ a[o]-'0';
-			if ((n < min[i]) || (n > max[i])) goto err;
-			if (tm)
-				{
-				if (i == 7)
-					offset = n * 3600;
-				else if (i == 8)
-					offset += n * 60;
-				}
-			o++;
-			}
-		if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign))
-			return 0;
-		}
-	else if (a[o])
-		{
-		/* Missing time zone information. */
-		goto err;
-		}
-	return(o == l);
-err:
-	return(0);
-	}
+    if (a[o] == 'Z')
+        o++;
+    else if ((a[o] == '+') || (a[o] == '-')) {
+        int offsign = a[o] == '-' ? -1 : 1, offset = 0;
+        o++;
+        if (o + 4 > l)
+            goto err;
+        for (i = 7; i < 9; i++) {
+            if ((a[o] < '0') || (a[o] > '9'))
+                goto err;
+            n = a[o] - '0';
+            o++;
+            if ((a[o] < '0') || (a[o] > '9'))
+                goto err;
+            n = (n * 10) + a[o] - '0';
+            if ((n < min[i]) || (n > max[i]))
+                goto err;
+            if (tm) {
+                if (i == 7)
+                    offset = n * 3600;
+                else if (i == 8)
+                    offset += n * 60;
+            }
+            o++;
+        }
+        if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign))
+            return 0;
+    } else if (a[o]) {
+        /* Missing time zone information. */
+        goto err;
+    }
+    return (o == l);
+ err:
+    return (0);
+}
 
 int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *d)
-	{
-	return asn1_generalizedtime_to_tm(NULL, d);
-	}
+{
+    return asn1_generalizedtime_to_tm(NULL, d);
+}
 
 int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s, const char *str)
-	{
-	ASN1_GENERALIZEDTIME t;
+{
+    ASN1_GENERALIZEDTIME t;
 
-	t.type=V_ASN1_GENERALIZEDTIME;
-	t.length=strlen(str);
-	t.data=(unsigned char *)str;
-	if (ASN1_GENERALIZEDTIME_check(&t))
-		{
-		if (s != NULL)
-			{
-			if (!ASN1_STRING_set((ASN1_STRING *)s,
-				(unsigned char *)str,t.length))
-				return 0;
-			s->type=V_ASN1_GENERALIZEDTIME;
-			}
-		return(1);
-		}
-	else
-		return(0);
-	}
+    t.type = V_ASN1_GENERALIZEDTIME;
+    t.length = strlen(str);
+    t.data = (unsigned char *)str;
+    if (ASN1_GENERALIZEDTIME_check(&t)) {
+        if (s != NULL) {
+            if (!ASN1_STRING_set((ASN1_STRING *)s,
+                                 (unsigned char *)str, t.length))
+                return 0;
+            s->type = V_ASN1_GENERALIZEDTIME;
+        }
+        return (1);
+    } else
+        return (0);
+}
 
 ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s,
-	     time_t t)
-	{
-		return ASN1_GENERALIZEDTIME_adj(s, t, 0, 0);
-	}
+                                               time_t t)
+{
+    return ASN1_GENERALIZEDTIME_adj(s, t, 0, 0);
+}
 
 ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s,
-	     time_t t, int offset_day, long offset_sec)
-	{
-	char *p;
-	struct tm *ts;
-	struct tm data;
-	size_t len = 20; 
+                                               time_t t, int offset_day,
+                                               long offset_sec)
+{
+    char *p;
+    struct tm *ts;
+    struct tm data;
+    size_t len = 20;
+    ASN1_GENERALIZEDTIME *tmps = NULL;
 
-	if (s == NULL)
-		s=M_ASN1_GENERALIZEDTIME_new();
-	if (s == NULL)
-		return(NULL);
+    if (s == NULL)
+        tmps = ASN1_GENERALIZEDTIME_new();
+    else
+        tmps = s;
+    if (tmps == NULL)
+        return NULL;
 
-	ts=OPENSSL_gmtime(&t, &data);
-	if (ts == NULL)
-		return(NULL);
+    ts = OPENSSL_gmtime(&t, &data);
+    if (ts == NULL)
+        goto err;
 
-	if (offset_day || offset_sec)
-		{ 
-		if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
-			return NULL;
-		}
+    if (offset_day || offset_sec) {
+        if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
+            goto err;
+    }
 
-	p=(char *)s->data;
-	if ((p == NULL) || ((size_t)s->length < len))
-		{
-		p=OPENSSL_malloc(len);
-		if (p == NULL)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-			return(NULL);
-			}
-		if (s->data != NULL)
-			OPENSSL_free(s->data);
-		s->data=(unsigned char *)p;
-		}
+    p = (char *)tmps->data;
+    if ((p == NULL) || ((size_t)tmps->length < len)) {
+        p = OPENSSL_malloc(len);
+        if (p == NULL) {
+            OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+            goto err;
+        }
+        OPENSSL_free(tmps->data);
+        tmps->data = (unsigned char *)p;
+    }
 
-	BIO_snprintf(p,len,"%04d%02d%02d%02d%02d%02dZ",ts->tm_year + 1900,
-		     ts->tm_mon+1,ts->tm_mday,ts->tm_hour,ts->tm_min,ts->tm_sec);
-	s->length=strlen(p);
-	s->type=V_ASN1_GENERALIZEDTIME;
-	return(s);
-	}
+    BIO_snprintf(p, len, "%04d%02d%02d%02d%02d%02dZ", ts->tm_year + 1900,
+                 ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min,
+                 ts->tm_sec);
+    tmps->length = strlen(p);
+    tmps->type = V_ASN1_GENERALIZEDTIME;
+    return tmps;
+ err:
+    if (s == NULL)
+        ASN1_GENERALIZEDTIME_free(tmps);
+    return NULL;
+}
diff --git a/src/crypto/asn1/a_i2d_fp.c b/src/crypto/asn1/a_i2d_fp.c
index 74ded78..486207e 100644
--- a/src/crypto/asn1/a_i2d_fp.c
+++ b/src/crypto/asn1/a_i2d_fp.c
@@ -59,96 +59,89 @@
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
-
 int ASN1_i2d_fp(i2d_of_void *i2d, FILE *out, void *x)
-        {
-        BIO *b;
-        int ret;
+{
+    BIO *b;
+    int ret;
 
-        if ((b=BIO_new(BIO_s_file())) == NULL)
-		{
-		OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
-                return(0);
-		}
-        BIO_set_fp(b,out,BIO_NOCLOSE);
-        ret=ASN1_i2d_bio(i2d,b,x);
-        BIO_free(b);
-        return(ret);
-        }
+    if ((b = BIO_new(BIO_s_file())) == NULL) {
+        OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
+        return (0);
+    }
+    BIO_set_fp(b, out, BIO_NOCLOSE);
+    ret = ASN1_i2d_bio(i2d, b, x);
+    BIO_free(b);
+    return (ret);
+}
 
 int ASN1_i2d_bio(i2d_of_void *i2d, BIO *out, void *x)
-	{
-	char *b;
-	unsigned char *p;
-	int i,j=0,n,ret=1;
+{
+    char *b;
+    unsigned char *p;
+    int i, j = 0, n, ret = 1;
 
-	n=i2d(x,NULL);
-	b=(char *)OPENSSL_malloc(n);
-	if (b == NULL)
-		{
-		OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-		return(0);
-		}
+    n = i2d(x, NULL);
+    b = (char *)OPENSSL_malloc(n);
+    if (b == NULL) {
+        OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+        return (0);
+    }
 
-	p=(unsigned char *)b;
-	i2d(x,&p);
-	
-	for (;;)
-		{
-		i=BIO_write(out,&(b[j]),n);
-		if (i == n) break;
-		if (i <= 0)
-			{
-			ret=0;
-			break;
-			}
-		j+=i;
-		n-=i;
-		}
-	OPENSSL_free(b);
-	return(ret);
-	}
+    p = (unsigned char *)b;
+    i2d(x, &p);
+
+    for (;;) {
+        i = BIO_write(out, &(b[j]), n);
+        if (i == n)
+            break;
+        if (i <= 0) {
+            ret = 0;
+            break;
+        }
+        j += i;
+        n -= i;
+    }
+    OPENSSL_free(b);
+    return (ret);
+}
 
 int ASN1_item_i2d_fp(const ASN1_ITEM *it, FILE *out, void *x)
-        {
-        BIO *b;
-        int ret;
+{
+    BIO *b;
+    int ret;
 
-        if ((b=BIO_new(BIO_s_file())) == NULL)
-		{
-		OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
-                return(0);
-		}
-        BIO_set_fp(b,out,BIO_NOCLOSE);
-        ret=ASN1_item_i2d_bio(it,b,x);
-        BIO_free(b);
-        return(ret);
-        }
+    if ((b = BIO_new(BIO_s_file())) == NULL) {
+        OPENSSL_PUT_ERROR(ASN1, ERR_R_BUF_LIB);
+        return (0);
+    }
+    BIO_set_fp(b, out, BIO_NOCLOSE);
+    ret = ASN1_item_i2d_bio(it, b, x);
+    BIO_free(b);
+    return (ret);
+}
 
 int ASN1_item_i2d_bio(const ASN1_ITEM *it, BIO *out, void *x)
-	{
-	unsigned char *b = NULL;
-	int i,j=0,n,ret=1;
+{
+    unsigned char *b = NULL;
+    int i, j = 0, n, ret = 1;
 
-	n = ASN1_item_i2d(x, &b, it);
-	if (b == NULL)
-		{
-		OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-		return(0);
-		}
+    n = ASN1_item_i2d(x, &b, it);
+    if (b == NULL) {
+        OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+        return (0);
+    }
 
-	for (;;)
-		{
-		i=BIO_write(out,&(b[j]),n);
-		if (i == n) break;
-		if (i <= 0)
-			{
-			ret=0;
-			break;
-			}
-		j+=i;
-		n-=i;
-		}
-	OPENSSL_free(b);
-	return(ret);
-	}
+    for (;;) {
+        i = BIO_write(out, &(b[j]), n);
+        if (i == n)
+            break;
+        if (i <= 0) {
+            ret = 0;
+            break;
+        }
+        j += i;
+        n -= i;
+    }
+    OPENSSL_free(b);
+    return (ret);
+}
diff --git a/src/crypto/asn1/a_int.c b/src/crypto/asn1/a_int.c
index 46855d9..617ba96 100644
--- a/src/crypto/asn1/a_int.c
+++ b/src/crypto/asn1/a_int.c
@@ -61,47 +61,49 @@
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
+#include "../internal.h"
+
 
 ASN1_INTEGER *ASN1_INTEGER_dup(const ASN1_INTEGER *x)
-{ return M_ASN1_INTEGER_dup(x);}
+{
+    return M_ASN1_INTEGER_dup(x);
+}
 
 int ASN1_INTEGER_cmp(const ASN1_INTEGER *x, const ASN1_INTEGER *y)
-	{ 
-	int neg, ret;
-	/* Compare signs */
-	neg = x->type & V_ASN1_NEG;
-	if (neg != (y->type & V_ASN1_NEG))
-		{
-		if (neg)
-			return -1;
-		else
-			return 1;
-		}
+{
+    int neg, ret;
+    /* Compare signs */
+    neg = x->type & V_ASN1_NEG;
+    if (neg != (y->type & V_ASN1_NEG)) {
+        if (neg)
+            return -1;
+        else
+            return 1;
+    }
 
-	ret = ASN1_STRING_cmp(x, y);
+    ret = ASN1_STRING_cmp(x, y);
 
-	if (neg)
-		return -ret;
-	else
-		return ret;
-	}
-	
+    if (neg)
+        return -ret;
+    else
+        return ret;
+}
 
-/* 
+/*
  * This converts an ASN1 INTEGER into its content encoding.
  * The internal representation is an ASN1_STRING whose data is a big endian
  * representation of the value, ignoring the sign. The sign is determined by
- * the type: V_ASN1_INTEGER for positive and V_ASN1_NEG_INTEGER for negative. 
+ * the type: V_ASN1_INTEGER for positive and V_ASN1_NEG_INTEGER for negative.
  *
  * Positive integers are no problem: they are almost the same as the DER
  * encoding, except if the first byte is >= 0x80 we need to add a zero pad.
  *
  * Negative integers are a bit trickier...
  * The DER representation of negative integers is in 2s complement form.
- * The internal form is converted by complementing each octet and finally 
+ * The internal form is converted by complementing each octet and finally
  * adding one to the result. This can be done less messily with a little trick.
  * If the internal form has trailing zeroes then they will become FF by the
- * complement and 0 by the add one (due to carry) so just copy as many trailing 
+ * complement and 0 by the add one (due to carry) so just copy as many trailing
  * zeros to the destination as there are in the source. The carry will add one
  * to the last none zero octet: so complement this octet and add one and finally
  * complement any left over until you get to the start of the string.
@@ -113,346 +115,349 @@
  */
 
 int i2c_ASN1_INTEGER(ASN1_INTEGER *a, unsigned char **pp)
-	{
-	int pad=0,ret,i,neg;
-	unsigned char *p,*n,pb=0;
+{
+    int pad = 0, ret, i, neg;
+    unsigned char *p, *n, pb = 0;
 
-	if (a == NULL) return(0);
-	neg=a->type & V_ASN1_NEG;
-	if (a->length == 0)
-		ret=1;
-	else
-		{
-		ret=a->length;
-		i=a->data[0];
-		if (ret == 1 && i == 0)
-			neg=0;
-		if (!neg && (i > 127)) {
-			pad=1;
-			pb=0;
-		} else if(neg) {
-			if(i>128) {
-				pad=1;
-				pb=0xFF;
-			} else if(i == 128) {
-			/*
-			 * Special case: if any other bytes non zero we pad:
-			 * otherwise we don't.
-			 */
-				for(i = 1; i < a->length; i++) if(a->data[i]) {
-						pad=1;
-						pb=0xFF;
-						break;
-				}
-			}
-		}
-		ret+=pad;
-		}
-	if (pp == NULL) return(ret);
-	p= *pp;
+    if (a == NULL)
+        return (0);
+    neg = a->type & V_ASN1_NEG;
+    if (a->length == 0)
+        ret = 1;
+    else {
+        ret = a->length;
+        i = a->data[0];
+        if (ret == 1 && i == 0)
+            neg = 0;
+        if (!neg && (i > 127)) {
+            pad = 1;
+            pb = 0;
+        } else if (neg) {
+            if (i > 128) {
+                pad = 1;
+                pb = 0xFF;
+            } else if (i == 128) {
+                /*
+                 * Special case: if any other bytes non zero we pad:
+                 * otherwise we don't.
+                 */
+                for (i = 1; i < a->length; i++)
+                    if (a->data[i]) {
+                        pad = 1;
+                        pb = 0xFF;
+                        break;
+                    }
+            }
+        }
+        ret += pad;
+    }
+    if (pp == NULL)
+        return (ret);
+    p = *pp;
 
-	if (pad) *(p++)=pb;
-	if (a->length == 0) *(p++)=0;
-	else if (!neg) memcpy(p,a->data,(unsigned int)a->length);
-	else {
-		/* Begin at the end of the encoding */
-		n=a->data + a->length - 1;
-		p += a->length - 1;
-		i = a->length;
-		/* Copy zeros to destination as long as source is zero */
-		while(!*n && i > 1) {
-			*(p--) = 0;
-			n--;
-			i--;
-		}
-		/* Complement and increment next octet */
-		*(p--) = ((*(n--)) ^ 0xff) + 1;
-		i--;
-		/* Complement any octets left */
-		for(;i > 0; i--) *(p--) = *(n--) ^ 0xff;
-	}
+    if (pad)
+        *(p++) = pb;
+    if (a->length == 0)
+        *(p++) = 0;
+    else if (!neg)
+        OPENSSL_memcpy(p, a->data, (unsigned int)a->length);
+    else {
+        /* Begin at the end of the encoding */
+        n = a->data + a->length - 1;
+        p += a->length - 1;
+        i = a->length;
+        /* Copy zeros to destination as long as source is zero */
+        while (!*n && i > 1) {
+            *(p--) = 0;
+            n--;
+            i--;
+        }
+        /* Complement and increment next octet */
+        *(p--) = ((*(n--)) ^ 0xff) + 1;
+        i--;
+        /* Complement any octets left */
+        for (; i > 0; i--)
+            *(p--) = *(n--) ^ 0xff;
+    }
 
-	*pp+=ret;
-	return(ret);
-	}
+    *pp += ret;
+    return (ret);
+}
 
 /* Convert just ASN1 INTEGER content octets to ASN1_INTEGER structure */
 
 ASN1_INTEGER *c2i_ASN1_INTEGER(ASN1_INTEGER **a, const unsigned char **pp,
-	     long len)
-	{
-	ASN1_INTEGER *ret=NULL;
-	const unsigned char *p, *pend;
-	unsigned char *to,*s;
-	int i;
+                               long len)
+{
+    ASN1_INTEGER *ret = NULL;
+    const unsigned char *p, *pend;
+    unsigned char *to, *s;
+    int i;
 
-	if ((a == NULL) || ((*a) == NULL))
-		{
-		if ((ret=M_ASN1_INTEGER_new()) == NULL) return(NULL);
-		ret->type=V_ASN1_INTEGER;
-		}
-	else
-		ret=(*a);
+    if ((a == NULL) || ((*a) == NULL)) {
+        if ((ret = M_ASN1_INTEGER_new()) == NULL)
+            return (NULL);
+        ret->type = V_ASN1_INTEGER;
+    } else
+        ret = (*a);
 
-	p= *pp;
-	pend = p + len;
+    p = *pp;
+    pend = p + len;
 
-	/* We must OPENSSL_malloc stuff, even for 0 bytes otherwise it
-	 * signifies a missing NULL parameter. */
-	s=(unsigned char *)OPENSSL_malloc((int)len+1);
-	if (s == NULL)
-		{
-		i=ERR_R_MALLOC_FAILURE;
-		goto err;
-		}
-	to=s;
-	if(!len) {
-		/* Strictly speaking this is an illegal INTEGER but we
-		 * tolerate it.
-		 */
-		ret->type=V_ASN1_INTEGER;
-	} else if (*p & 0x80) /* a negative number */
-		{
-		ret->type=V_ASN1_NEG_INTEGER;
-		if ((*p == 0xff) && (len != 1)) {
-			p++;
-			len--;
-		}
-		i = len;
-		p += i - 1;
-		to += i - 1;
-		while((!*p) && i) {
-			*(to--) = 0;
-			i--;
-			p--;
-		}
-		/* Special case: if all zeros then the number will be of
-		 * the form FF followed by n zero bytes: this corresponds to
-		 * 1 followed by n zero bytes. We've already written n zeros
-		 * so we just append an extra one and set the first byte to
-		 * a 1. This is treated separately because it is the only case
-		 * where the number of bytes is larger than len.
-		 */
-		if(!i) {
-			*s = 1;
-			s[len] = 0;
-			len++;
-		} else {
-			*(to--) = (*(p--) ^ 0xff) + 1;
-			i--;
-			for(;i > 0; i--) *(to--) = *(p--) ^ 0xff;
-		}
-	} else {
-		ret->type=V_ASN1_INTEGER;
-		if ((*p == 0) && (len != 1))
-			{
-			p++;
-			len--;
-			}
-		memcpy(s,p,(int)len);
-	}
+    /*
+     * We must OPENSSL_malloc stuff, even for 0 bytes otherwise it signifies
+     * a missing NULL parameter.
+     */
+    s = (unsigned char *)OPENSSL_malloc((int)len + 1);
+    if (s == NULL) {
+        i = ERR_R_MALLOC_FAILURE;
+        goto err;
+    }
+    to = s;
+    if (!len) {
+        /*
+         * Strictly speaking this is an illegal INTEGER but we tolerate it.
+         */
+        ret->type = V_ASN1_INTEGER;
+    } else if (*p & 0x80) {     /* a negative number */
+        ret->type = V_ASN1_NEG_INTEGER;
+        if ((*p == 0xff) && (len != 1)) {
+            p++;
+            len--;
+        }
+        i = len;
+        p += i - 1;
+        to += i - 1;
+        while ((!*p) && i) {
+            *(to--) = 0;
+            i--;
+            p--;
+        }
+        /*
+         * Special case: if all zeros then the number will be of the form FF
+         * followed by n zero bytes: this corresponds to 1 followed by n zero
+         * bytes. We've already written n zeros so we just append an extra
+         * one and set the first byte to a 1. This is treated separately
+         * because it is the only case where the number of bytes is larger
+         * than len.
+         */
+        if (!i) {
+            *s = 1;
+            s[len] = 0;
+            len++;
+        } else {
+            *(to--) = (*(p--) ^ 0xff) + 1;
+            i--;
+            for (; i > 0; i--)
+                *(to--) = *(p--) ^ 0xff;
+        }
+    } else {
+        ret->type = V_ASN1_INTEGER;
+        if ((*p == 0) && (len != 1)) {
+            p++;
+            len--;
+        }
+        OPENSSL_memcpy(s, p, (int)len);
+    }
 
-	if (ret->data != NULL) OPENSSL_free(ret->data);
-	ret->data=s;
-	ret->length=(int)len;
-	if (a != NULL) (*a)=ret;
-	*pp=pend;
-	return(ret);
-err:
-	OPENSSL_PUT_ERROR(ASN1, i);
-	if ((ret != NULL) && ((a == NULL) || (*a != ret)))
-		M_ASN1_INTEGER_free(ret);
-	return(NULL);
-	}
+    if (ret->data != NULL)
+        OPENSSL_free(ret->data);
+    ret->data = s;
+    ret->length = (int)len;
+    if (a != NULL)
+        (*a) = ret;
+    *pp = pend;
+    return (ret);
+ err:
+    OPENSSL_PUT_ERROR(ASN1, i);
+    if ((ret != NULL) && ((a == NULL) || (*a != ret)))
+        M_ASN1_INTEGER_free(ret);
+    return (NULL);
+}
 
-
-/* This is a version of d2i_ASN1_INTEGER that ignores the sign bit of
- * ASN1 integers: some broken software can encode a positive INTEGER
- * with its MSB set as negative (it doesn't add a padding zero).
+/*
+ * This is a version of d2i_ASN1_INTEGER that ignores the sign bit of ASN1
+ * integers: some broken software can encode a positive INTEGER with its MSB
+ * set as negative (it doesn't add a padding zero).
  */
 
 ASN1_INTEGER *d2i_ASN1_UINTEGER(ASN1_INTEGER **a, const unsigned char **pp,
-	     long length)
-	{
-	ASN1_INTEGER *ret=NULL;
-	const unsigned char *p;
-	unsigned char *s;
-	long len;
-	int inf,tag,xclass;
-	int i;
+                                long length)
+{
+    ASN1_INTEGER *ret = NULL;
+    const unsigned char *p;
+    unsigned char *s;
+    long len;
+    int inf, tag, xclass;
+    int i;
 
-	if ((a == NULL) || ((*a) == NULL))
-		{
-		if ((ret=M_ASN1_INTEGER_new()) == NULL) return(NULL);
-		ret->type=V_ASN1_INTEGER;
-		}
-	else
-		ret=(*a);
+    if ((a == NULL) || ((*a) == NULL)) {
+        if ((ret = M_ASN1_INTEGER_new()) == NULL)
+            return (NULL);
+        ret->type = V_ASN1_INTEGER;
+    } else
+        ret = (*a);
 
-	p= *pp;
-	inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
-	if (inf & 0x80)
-		{
-		i=ASN1_R_BAD_OBJECT_HEADER;
-		goto err;
-		}
+    p = *pp;
+    inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
+    if (inf & 0x80) {
+        i = ASN1_R_BAD_OBJECT_HEADER;
+        goto err;
+    }
 
-	if (tag != V_ASN1_INTEGER)
-		{
-		i=ASN1_R_EXPECTING_AN_INTEGER;
-		goto err;
-		}
+    if (tag != V_ASN1_INTEGER) {
+        i = ASN1_R_EXPECTING_AN_INTEGER;
+        goto err;
+    }
 
-	/* We must OPENSSL_malloc stuff, even for 0 bytes otherwise it
-	 * signifies a missing NULL parameter. */
-	s=(unsigned char *)OPENSSL_malloc((int)len+1);
-	if (s == NULL)
-		{
-		i=ERR_R_MALLOC_FAILURE;
-		goto err;
-		}
-	ret->type=V_ASN1_INTEGER;
-	if(len) {
-		if ((*p == 0) && (len != 1))
-			{
-			p++;
-			len--;
-			}
-		memcpy(s,p,(int)len);
-		p+=len;
-	}
+    /*
+     * We must OPENSSL_malloc stuff, even for 0 bytes otherwise it signifies
+     * a missing NULL parameter.
+     */
+    s = (unsigned char *)OPENSSL_malloc((int)len + 1);
+    if (s == NULL) {
+        i = ERR_R_MALLOC_FAILURE;
+        goto err;
+    }
+    ret->type = V_ASN1_INTEGER;
+    if (len) {
+        if ((*p == 0) && (len != 1)) {
+            p++;
+            len--;
+        }
+        OPENSSL_memcpy(s, p, (int)len);
+        p += len;
+    }
 
-	if (ret->data != NULL) OPENSSL_free(ret->data);
-	ret->data=s;
-	ret->length=(int)len;
-	if (a != NULL) (*a)=ret;
-	*pp=p;
-	return(ret);
-err:
-	OPENSSL_PUT_ERROR(ASN1, i);
-	if ((ret != NULL) && ((a == NULL) || (*a != ret)))
-		M_ASN1_INTEGER_free(ret);
-	return(NULL);
-	}
+    if (ret->data != NULL)
+        OPENSSL_free(ret->data);
+    ret->data = s;
+    ret->length = (int)len;
+    if (a != NULL)
+        (*a) = ret;
+    *pp = p;
+    return (ret);
+ err:
+    OPENSSL_PUT_ERROR(ASN1, i);
+    if ((ret != NULL) && ((a == NULL) || (*a != ret)))
+        M_ASN1_INTEGER_free(ret);
+    return (NULL);
+}
 
 int ASN1_INTEGER_set(ASN1_INTEGER *a, long v)
-	{
-	int j,k;
-	unsigned int i;
-	unsigned char buf[sizeof(long)+1];
-	long d;
+{
+    int j, k;
+    unsigned int i;
+    unsigned char buf[sizeof(long) + 1];
+    long d;
 
-	a->type=V_ASN1_INTEGER;
-	if (a->length < (int)(sizeof(long)+1))
-		{
-		if (a->data != NULL)
-			OPENSSL_free(a->data);
-		if ((a->data=(unsigned char *)OPENSSL_malloc(sizeof(long)+1)) != NULL)
-			memset((char *)a->data,0,sizeof(long)+1);
-		}
-	if (a->data == NULL)
-		{
-		OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-		return(0);
-		}
-	d=v;
-	if (d < 0)
-		{
-		d= -d;
-		a->type=V_ASN1_NEG_INTEGER;
-		}
+    a->type = V_ASN1_INTEGER;
+    if (a->length < (int)(sizeof(long) + 1)) {
+        if (a->data != NULL)
+            OPENSSL_free(a->data);
+        if ((a->data =
+             (unsigned char *)OPENSSL_malloc(sizeof(long) + 1)) != NULL)
+            OPENSSL_memset((char *)a->data, 0, sizeof(long) + 1);
+    }
+    if (a->data == NULL) {
+        OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+        return (0);
+    }
+    d = v;
+    if (d < 0) {
+        d = -d;
+        a->type = V_ASN1_NEG_INTEGER;
+    }
 
-	for (i=0; i<sizeof(long); i++)
-		{
-		if (d == 0) break;
-		buf[i]=(int)d&0xff;
-		d>>=8;
-		}
-	j=0;
-	for (k=i-1; k >=0; k--)
-		a->data[j++]=buf[k];
-	a->length=j;
-	return(1);
-	}
+    for (i = 0; i < sizeof(long); i++) {
+        if (d == 0)
+            break;
+        buf[i] = (int)d & 0xff;
+        d >>= 8;
+    }
+    j = 0;
+    for (k = i - 1; k >= 0; k--)
+        a->data[j++] = buf[k];
+    a->length = j;
+    return (1);
+}
 
 long ASN1_INTEGER_get(const ASN1_INTEGER *a)
-	{
-	int neg=0,i;
-	long r=0;
+{
+    int neg = 0, i;
+    long r = 0;
 
-	if (a == NULL) return(0L);
-	i=a->type;
-	if (i == V_ASN1_NEG_INTEGER)
-		neg=1;
-	else if (i != V_ASN1_INTEGER)
-		return -1;
-	
-	if (a->length > (int)sizeof(long))
-		{
-		/* hmm... a bit ugly, return all ones */
-		return -1;
-		}
-	if (a->data == NULL)
-		return 0;
+    if (a == NULL)
+        return (0L);
+    i = a->type;
+    if (i == V_ASN1_NEG_INTEGER)
+        neg = 1;
+    else if (i != V_ASN1_INTEGER)
+        return -1;
 
-	for (i=0; i<a->length; i++)
-		{
-		r<<=8;
-		r|=(unsigned char)a->data[i];
-		}
-	if (neg) r= -r;
-	return(r);
-	}
+    if (a->length > (int)sizeof(long)) {
+        /* hmm... a bit ugly, return all ones */
+        return -1;
+    }
+    if (a->data == NULL)
+        return 0;
+
+    for (i = 0; i < a->length; i++) {
+        r <<= 8;
+        r |= (unsigned char)a->data[i];
+    }
+    if (neg)
+        r = -r;
+    return (r);
+}
 
 ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai)
-	{
-	ASN1_INTEGER *ret;
-	int len,j;
+{
+    ASN1_INTEGER *ret;
+    int len, j;
 
-	if (ai == NULL)
-		ret=M_ASN1_INTEGER_new();
-	else
-		ret=ai;
-	if (ret == NULL)
-		{
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
-		goto err;
-		}
-	if (BN_is_negative(bn) && !BN_is_zero(bn))
-		ret->type = V_ASN1_NEG_INTEGER;
-	else ret->type=V_ASN1_INTEGER;
-	j=BN_num_bits(bn);
-	len=((j == 0)?0:((j/8)+1));
-	if (ret->length < len+4)
-		{
-		unsigned char *new_data=OPENSSL_realloc(ret->data, len+4);
-		if (!new_data)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-			goto err;
-			}
-		ret->data=new_data;
-		}
-	ret->length=BN_bn2bin(bn,ret->data);
-	/* Correct zero case */
-	if(!ret->length)
-		{
-		ret->data[0] = 0;
-		ret->length = 1;
-		}
-	return(ret);
-err:
-	if (ret != ai) M_ASN1_INTEGER_free(ret);
-	return(NULL);
-	}
+    if (ai == NULL)
+        ret = M_ASN1_INTEGER_new();
+    else
+        ret = ai;
+    if (ret == NULL) {
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+        goto err;
+    }
+    if (BN_is_negative(bn) && !BN_is_zero(bn))
+        ret->type = V_ASN1_NEG_INTEGER;
+    else
+        ret->type = V_ASN1_INTEGER;
+    j = BN_num_bits(bn);
+    len = ((j == 0) ? 0 : ((j / 8) + 1));
+    if (ret->length < len + 4) {
+        unsigned char *new_data = OPENSSL_realloc(ret->data, len + 4);
+        if (!new_data) {
+            OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+            goto err;
+        }
+        ret->data = new_data;
+    }
+    ret->length = BN_bn2bin(bn, ret->data);
+    /* Correct zero case */
+    if (!ret->length) {
+        ret->data[0] = 0;
+        ret->length = 1;
+    }
+    return (ret);
+ err:
+    if (ret != ai)
+        M_ASN1_INTEGER_free(ret);
+    return (NULL);
+}
 
 BIGNUM *ASN1_INTEGER_to_BN(const ASN1_INTEGER *ai, BIGNUM *bn)
-	{
-	BIGNUM *ret;
+{
+    BIGNUM *ret;
 
-	if ((ret=BN_bin2bn(ai->data,ai->length,bn)) == NULL)
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_BN_LIB);
-	else if(ai->type == V_ASN1_NEG_INTEGER)
-		BN_set_negative(ret, 1);
-	return(ret);
-	}
+    if ((ret = BN_bin2bn(ai->data, ai->length, bn)) == NULL)
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_BN_LIB);
+    else if (ai->type == V_ASN1_NEG_INTEGER)
+        BN_set_negative(ret, 1);
+    return (ret);
+}
diff --git a/src/crypto/asn1/a_mbstr.c b/src/crypto/asn1/a_mbstr.c
index 42806d1..30fff82 100644
--- a/src/crypto/asn1/a_mbstr.c
+++ b/src/crypto/asn1/a_mbstr.c
@@ -61,9 +61,9 @@
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
-
 static int traverse_string(const unsigned char *p, int len, int inform,
-		 int (*rfunc)(unsigned long value, void *in), void *arg);
+                           int (*rfunc) (unsigned long value, void *in),
+                           void *arg);
 static int in_utf8(unsigned long value, void *arg);
 static int out_utf8(unsigned long value, void *arg);
 static int type_str(unsigned long value, void *arg);
@@ -73,208 +73,219 @@
 static int cpy_utf8(unsigned long value, void *arg);
 static int is_printable(unsigned long value);
 
-/* These functions take a string in UTF8, ASCII or multibyte form and
- * a mask of permissible ASN1 string types. It then works out the minimal
- * type (using the order Printable < IA5 < T61 < BMP < Universal < UTF8)
- * and creates a string of the correct type with the supplied data.
- * Yes this is horrible: it has to be :-(
- * The 'ncopy' form checks minimum and maximum size limits too.
+/*
+ * These functions take a string in UTF8, ASCII or multibyte form and a mask
+ * of permissible ASN1 string types. It then works out the minimal type
+ * (using the order Printable < IA5 < T61 < BMP < Universal < UTF8) and
+ * creates a string of the correct type with the supplied data. Yes this is
+ * horrible: it has to be :-( The 'ncopy' form checks minimum and maximum
+ * size limits too.
  */
 
 int ASN1_mbstring_copy(ASN1_STRING **out, const unsigned char *in, int len,
-					int inform, unsigned long mask)
+                       int inform, unsigned long mask)
 {
-	return ASN1_mbstring_ncopy(out, in, len, inform, mask, 0, 0);
+    return ASN1_mbstring_ncopy(out, in, len, inform, mask, 0, 0);
 }
 
 int ASN1_mbstring_ncopy(ASN1_STRING **out, const unsigned char *in, int len,
-					int inform, unsigned long mask, 
-					long minsize, long maxsize)
+                        int inform, unsigned long mask,
+                        long minsize, long maxsize)
 {
-	int str_type;
-	int ret;
-	char free_out;
-	int outform, outlen = 0;
-	ASN1_STRING *dest;
-	unsigned char *p;
-	int nchar;
-	char strbuf[32];
-	int (*cpyfunc)(unsigned long,void *) = NULL;
-	if(len == -1) len = strlen((const char *)in);
-	if(!mask) mask = DIRSTRING_TYPE;
+    int str_type;
+    int ret;
+    char free_out;
+    int outform, outlen = 0;
+    ASN1_STRING *dest;
+    unsigned char *p;
+    int nchar;
+    char strbuf[32];
+    int (*cpyfunc) (unsigned long, void *) = NULL;
+    if (len == -1)
+        len = strlen((const char *)in);
+    if (!mask)
+        mask = DIRSTRING_TYPE;
 
-	/* First do a string check and work out the number of characters */
-	switch(inform) {
+    /* First do a string check and work out the number of characters */
+    switch (inform) {
 
-		case MBSTRING_BMP:
-		if(len & 1) {
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BMPSTRING_LENGTH);
-			return -1;
-		}
-		nchar = len >> 1;
-		break;
+    case MBSTRING_BMP:
+        if (len & 1) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_BMPSTRING_LENGTH);
+            return -1;
+        }
+        nchar = len >> 1;
+        break;
 
-		case MBSTRING_UNIV:
-		if(len & 3) {
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
-			return -1;
-		}
-		nchar = len >> 2;
-		break;
+    case MBSTRING_UNIV:
+        if (len & 3) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_UNIVERSALSTRING_LENGTH);
+            return -1;
+        }
+        nchar = len >> 2;
+        break;
 
-		case MBSTRING_UTF8:
-		nchar = 0;
-		/* This counts the characters and does utf8 syntax checking */
-		ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar);
-		if(ret < 0) {
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_UTF8STRING);
-			return -1;
-		}
-		break;
+    case MBSTRING_UTF8:
+        nchar = 0;
+        /* This counts the characters and does utf8 syntax checking */
+        ret = traverse_string(in, len, MBSTRING_UTF8, in_utf8, &nchar);
+        if (ret < 0) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_UTF8STRING);
+            return -1;
+        }
+        break;
 
-		case MBSTRING_ASC:
-		nchar = len;
-		break;
+    case MBSTRING_ASC:
+        nchar = len;
+        break;
 
-		default:
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT);
-		return -1;
-	}
+    default:
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT);
+        return -1;
+    }
 
-	if((minsize > 0) && (nchar < minsize)) {
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT);
-		BIO_snprintf(strbuf, sizeof strbuf, "%ld", minsize);
-		ERR_add_error_data(2, "minsize=", strbuf);
-		return -1;
-	}
+    if ((minsize > 0) && (nchar < minsize)) {
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_SHORT);
+        BIO_snprintf(strbuf, sizeof strbuf, "%ld", minsize);
+        ERR_add_error_data(2, "minsize=", strbuf);
+        return -1;
+    }
 
-	if((maxsize > 0) && (nchar > maxsize)) {
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG);
-		BIO_snprintf(strbuf, sizeof strbuf, "%ld", maxsize);
-		ERR_add_error_data(2, "maxsize=", strbuf);
-		return -1;
-	}
+    if ((maxsize > 0) && (nchar > maxsize)) {
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG);
+        BIO_snprintf(strbuf, sizeof strbuf, "%ld", maxsize);
+        ERR_add_error_data(2, "maxsize=", strbuf);
+        return -1;
+    }
 
-	/* Now work out minimal type (if any) */
-	if(traverse_string(in, len, inform, type_str, &mask) < 0) {
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS);
-		return -1;
-	}
+    /* Now work out minimal type (if any) */
+    if (traverse_string(in, len, inform, type_str, &mask) < 0) {
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_CHARACTERS);
+        return -1;
+    }
 
+    /* Now work out output format and string type */
+    outform = MBSTRING_ASC;
+    if (mask & B_ASN1_PRINTABLESTRING)
+        str_type = V_ASN1_PRINTABLESTRING;
+    else if (mask & B_ASN1_IA5STRING)
+        str_type = V_ASN1_IA5STRING;
+    else if (mask & B_ASN1_T61STRING)
+        str_type = V_ASN1_T61STRING;
+    else if (mask & B_ASN1_BMPSTRING) {
+        str_type = V_ASN1_BMPSTRING;
+        outform = MBSTRING_BMP;
+    } else if (mask & B_ASN1_UNIVERSALSTRING) {
+        str_type = V_ASN1_UNIVERSALSTRING;
+        outform = MBSTRING_UNIV;
+    } else {
+        str_type = V_ASN1_UTF8STRING;
+        outform = MBSTRING_UTF8;
+    }
+    if (!out)
+        return str_type;
+    if (*out) {
+        free_out = 0;
+        dest = *out;
+        if (dest->data) {
+            dest->length = 0;
+            OPENSSL_free(dest->data);
+            dest->data = NULL;
+        }
+        dest->type = str_type;
+    } else {
+        free_out = 1;
+        dest = ASN1_STRING_type_new(str_type);
+        if (!dest) {
+            OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+            return -1;
+        }
+        *out = dest;
+    }
+    /* If both the same type just copy across */
+    if (inform == outform) {
+        if (!ASN1_STRING_set(dest, in, len)) {
+            OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+            return -1;
+        }
+        return str_type;
+    }
 
-	/* Now work out output format and string type */
-	outform = MBSTRING_ASC;
-	if(mask & B_ASN1_PRINTABLESTRING) str_type = V_ASN1_PRINTABLESTRING;
-	else if(mask & B_ASN1_IA5STRING) str_type = V_ASN1_IA5STRING;
-	else if(mask & B_ASN1_T61STRING) str_type = V_ASN1_T61STRING;
-	else if(mask & B_ASN1_BMPSTRING) {
-		str_type = V_ASN1_BMPSTRING;
-		outform = MBSTRING_BMP;
-	} else if(mask & B_ASN1_UNIVERSALSTRING) {
-		str_type = V_ASN1_UNIVERSALSTRING;
-		outform = MBSTRING_UNIV;
-	} else {
-		str_type = V_ASN1_UTF8STRING;
-		outform = MBSTRING_UTF8;
-	}
-	if(!out) return str_type;
-	if(*out) {
-		free_out = 0;
-		dest = *out;
-		if(dest->data) {
-			dest->length = 0;
-			OPENSSL_free(dest->data);
-			dest->data = NULL;
-		}
-		dest->type = str_type;
-	} else {
-		free_out = 1;
-		dest = ASN1_STRING_type_new(str_type);
-		if(!dest) {
-			OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-			return -1;
-		}
-		*out = dest;
-	}
-	/* If both the same type just copy across */
-	if(inform == outform) {
-		if(!ASN1_STRING_set(dest, in, len)) {
-			OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-			return -1;
-		}
-		return str_type;
-	} 
+    /* Work out how much space the destination will need */
+    switch (outform) {
+    case MBSTRING_ASC:
+        outlen = nchar;
+        cpyfunc = cpy_asc;
+        break;
 
-	/* Work out how much space the destination will need */
-	switch(outform) {
-		case MBSTRING_ASC:
-		outlen = nchar;
-		cpyfunc = cpy_asc;
-		break;
+    case MBSTRING_BMP:
+        outlen = nchar << 1;
+        cpyfunc = cpy_bmp;
+        break;
 
-		case MBSTRING_BMP:
-		outlen = nchar << 1;
-		cpyfunc = cpy_bmp;
-		break;
+    case MBSTRING_UNIV:
+        outlen = nchar << 2;
+        cpyfunc = cpy_univ;
+        break;
 
-		case MBSTRING_UNIV:
-		outlen = nchar << 2;
-		cpyfunc = cpy_univ;
-		break;
-
-		case MBSTRING_UTF8:
-		outlen = 0;
-		traverse_string(in, len, inform, out_utf8, &outlen);
-		cpyfunc = cpy_utf8;
-		break;
-	}
-	if(!(p = OPENSSL_malloc(outlen + 1))) {
-		if(free_out) ASN1_STRING_free(dest);
-		OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-		return -1;
-	}
-	dest->length = outlen;
-	dest->data = p;
-	p[outlen] = 0;
-	traverse_string(in, len, inform, cpyfunc, &p);
-	return str_type;	
+    case MBSTRING_UTF8:
+        outlen = 0;
+        traverse_string(in, len, inform, out_utf8, &outlen);
+        cpyfunc = cpy_utf8;
+        break;
+    }
+    if (!(p = OPENSSL_malloc(outlen + 1))) {
+        if (free_out)
+            ASN1_STRING_free(dest);
+        OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+        return -1;
+    }
+    dest->length = outlen;
+    dest->data = p;
+    p[outlen] = 0;
+    traverse_string(in, len, inform, cpyfunc, &p);
+    return str_type;
 }
 
-/* This function traverses a string and passes the value of each character
- * to an optional function along with a void * argument.
+/*
+ * This function traverses a string and passes the value of each character to
+ * an optional function along with a void * argument.
  */
 
 static int traverse_string(const unsigned char *p, int len, int inform,
-		 int (*rfunc)(unsigned long value, void *in), void *arg)
+                           int (*rfunc) (unsigned long value, void *in),
+                           void *arg)
 {
-	unsigned long value;
-	int ret;
-	while(len) {
-		if(inform == MBSTRING_ASC) {
-			value = *p++;
-			len--;
-		} else if(inform == MBSTRING_BMP) {
-			value = *p++ << 8;
-			value |= *p++;
-			len -= 2;
-		} else if(inform == MBSTRING_UNIV) {
-			value = ((unsigned long)*p++) << 24;
-			value |= ((unsigned long)*p++) << 16;
-			value |= *p++ << 8;
-			value |= *p++;
-			len -= 4;
-		} else {
-			ret = UTF8_getc(p, len, &value);
-			if(ret < 0) return -1;
-			len -= ret;
-			p += ret;
-		}
-		if(rfunc) {
-			ret = rfunc(value, arg);
-			if(ret <= 0) return ret;
-		}
-	}
-	return 1;
+    unsigned long value;
+    int ret;
+    while (len) {
+        if (inform == MBSTRING_ASC) {
+            value = *p++;
+            len--;
+        } else if (inform == MBSTRING_BMP) {
+            value = *p++ << 8;
+            value |= *p++;
+            len -= 2;
+        } else if (inform == MBSTRING_UNIV) {
+            value = ((unsigned long)*p++) << 24;
+            value |= ((unsigned long)*p++) << 16;
+            value |= *p++ << 8;
+            value |= *p++;
+            len -= 4;
+        } else {
+            ret = UTF8_getc(p, len, &value);
+            if (ret < 0)
+                return -1;
+            len -= ret;
+            p += ret;
+        }
+        if (rfunc) {
+            ret = rfunc(value, arg);
+            if (ret <= 0)
+                return ret;
+        }
+    }
+    return 1;
 }
 
 /* Various utility functions for traverse_string */
@@ -283,108 +294,116 @@
 
 static int in_utf8(unsigned long value, void *arg)
 {
-	int *nchar;
-	nchar = arg;
-	(*nchar)++;
-	return 1;
+    int *nchar;
+    nchar = arg;
+    (*nchar)++;
+    return 1;
 }
 
 /* Determine size of output as a UTF8 String */
 
 static int out_utf8(unsigned long value, void *arg)
 {
-	int *outlen;
-	outlen = arg;
-	*outlen += UTF8_putc(NULL, -1, value);
-	return 1;
+    int *outlen;
+    outlen = arg;
+    *outlen += UTF8_putc(NULL, -1, value);
+    return 1;
 }
 
-/* Determine the "type" of a string: check each character against a
- * supplied "mask".
+/*
+ * Determine the "type" of a string: check each character against a supplied
+ * "mask".
  */
 
 static int type_str(unsigned long value, void *arg)
 {
-	unsigned long types;
-	types = *((unsigned long *)arg);
-	if((types & B_ASN1_PRINTABLESTRING) && !is_printable(value))
-					types &= ~B_ASN1_PRINTABLESTRING;
-	if((types & B_ASN1_IA5STRING) && (value > 127))
-					types &= ~B_ASN1_IA5STRING;
-	if((types & B_ASN1_T61STRING) && (value > 0xff))
-					types &= ~B_ASN1_T61STRING;
-	if((types & B_ASN1_BMPSTRING) && (value > 0xffff))
-					types &= ~B_ASN1_BMPSTRING;
-	if(!types) return -1;
-	*((unsigned long *)arg) = types;
-	return 1;
+    unsigned long types;
+    types = *((unsigned long *)arg);
+    if ((types & B_ASN1_PRINTABLESTRING) && !is_printable(value))
+        types &= ~B_ASN1_PRINTABLESTRING;
+    if ((types & B_ASN1_IA5STRING) && (value > 127))
+        types &= ~B_ASN1_IA5STRING;
+    if ((types & B_ASN1_T61STRING) && (value > 0xff))
+        types &= ~B_ASN1_T61STRING;
+    if ((types & B_ASN1_BMPSTRING) && (value > 0xffff))
+        types &= ~B_ASN1_BMPSTRING;
+    if (!types)
+        return -1;
+    *((unsigned long *)arg) = types;
+    return 1;
 }
 
 /* Copy one byte per character ASCII like strings */
 
 static int cpy_asc(unsigned long value, void *arg)
 {
-	unsigned char **p, *q;
-	p = arg;
-	q = *p;
-	*q = (unsigned char) value;
-	(*p)++;
-	return 1;
+    unsigned char **p, *q;
+    p = arg;
+    q = *p;
+    *q = (unsigned char)value;
+    (*p)++;
+    return 1;
 }
 
 /* Copy two byte per character BMPStrings */
 
 static int cpy_bmp(unsigned long value, void *arg)
 {
-	unsigned char **p, *q;
-	p = arg;
-	q = *p;
-	*q++ = (unsigned char) ((value >> 8) & 0xff);
-	*q = (unsigned char) (value & 0xff);
-	*p += 2;
-	return 1;
+    unsigned char **p, *q;
+    p = arg;
+    q = *p;
+    *q++ = (unsigned char)((value >> 8) & 0xff);
+    *q = (unsigned char)(value & 0xff);
+    *p += 2;
+    return 1;
 }
 
 /* Copy four byte per character UniversalStrings */
 
 static int cpy_univ(unsigned long value, void *arg)
 {
-	unsigned char **p, *q;
-	p = arg;
-	q = *p;
-	*q++ = (unsigned char) ((value >> 24) & 0xff);
-	*q++ = (unsigned char) ((value >> 16) & 0xff);
-	*q++ = (unsigned char) ((value >> 8) & 0xff);
-	*q = (unsigned char) (value & 0xff);
-	*p += 4;
-	return 1;
+    unsigned char **p, *q;
+    p = arg;
+    q = *p;
+    *q++ = (unsigned char)((value >> 24) & 0xff);
+    *q++ = (unsigned char)((value >> 16) & 0xff);
+    *q++ = (unsigned char)((value >> 8) & 0xff);
+    *q = (unsigned char)(value & 0xff);
+    *p += 4;
+    return 1;
 }
 
 /* Copy to a UTF8String */
 
 static int cpy_utf8(unsigned long value, void *arg)
 {
-	unsigned char **p;
-	int ret;
-	p = arg;
-	/* We already know there is enough room so pass 0xff as the length */
-	ret = UTF8_putc(*p, 0xff, value);
-	*p += ret;
-	return 1;
+    unsigned char **p;
+    int ret;
+    p = arg;
+    /* We already know there is enough room so pass 0xff as the length */
+    ret = UTF8_putc(*p, 0xff, value);
+    *p += ret;
+    return 1;
 }
 
 /* Return 1 if the character is permitted in a PrintableString */
 static int is_printable(unsigned long value)
 {
-	int ch;
-	if(value > 0x7f) return 0;
-	ch = (int) value;
-	/* Note: we can't use 'isalnum' because certain accented 
-	 * characters may count as alphanumeric in some environments.
-	 */
-	if((ch >= 'a') && (ch <= 'z')) return 1;
-	if((ch >= 'A') && (ch <= 'Z')) return 1;
-	if((ch >= '0') && (ch <= '9')) return 1;
-	if ((ch == ' ') || strchr("'()+,-./:=?", ch)) return 1;
-	return 0;
+    int ch;
+    if (value > 0x7f)
+        return 0;
+    ch = (int)value;
+    /*
+     * Note: we can't use 'isalnum' because certain accented characters may
+     * count as alphanumeric in some environments.
+     */
+    if ((ch >= 'a') && (ch <= 'z'))
+        return 1;
+    if ((ch >= 'A') && (ch <= 'Z'))
+        return 1;
+    if ((ch >= '0') && (ch <= '9'))
+        return 1;
+    if ((ch == ' ') || strchr("'()+,-./:=?", ch))
+        return 1;
+    return 0;
 }
diff --git a/src/crypto/asn1/a_object.c b/src/crypto/asn1/a_object.c
index 6ddfca9..a710add 100644
--- a/src/crypto/asn1/a_object.c
+++ b/src/crypto/asn1/a_object.c
@@ -63,350 +63,341 @@
 #include <openssl/mem.h>
 #include <openssl/obj.h>
 
+#include "../internal.h"
+
 
 int i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp)
-	{
-	unsigned char *p;
-	int objsize;
+{
+    unsigned char *p;
+    int objsize;
 
-	if ((a == NULL) || (a->data == NULL)) return(0);
+    if ((a == NULL) || (a->data == NULL))
+        return (0);
 
-	objsize = ASN1_object_size(0,a->length,V_ASN1_OBJECT);
-	if (pp == NULL) return objsize;
+    objsize = ASN1_object_size(0, a->length, V_ASN1_OBJECT);
+    if (pp == NULL || objsize == -1)
+        return objsize;
 
-	p= *pp;
-	ASN1_put_object(&p,0,a->length,V_ASN1_OBJECT,V_ASN1_UNIVERSAL);
-	memcpy(p,a->data,a->length);
-	p+=a->length;
+    p = *pp;
+    ASN1_put_object(&p, 0, a->length, V_ASN1_OBJECT, V_ASN1_UNIVERSAL);
+    OPENSSL_memcpy(p, a->data, a->length);
+    p += a->length;
 
-	*pp=p;
-	return(objsize);
-	}
+    *pp = p;
+    return (objsize);
+}
 
 int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num)
-	{
-	int i,first,len=0,c, use_bn;
-	char ftmp[24], *tmp = ftmp;
-	int tmpsize = sizeof ftmp;
-	const char *p;
-	unsigned long l;
-	BIGNUM *bl = NULL;
+{
+    int i, first, len = 0, c, use_bn;
+    char ftmp[24], *tmp = ftmp;
+    int tmpsize = sizeof ftmp;
+    const char *p;
+    unsigned long l;
+    BIGNUM *bl = NULL;
 
-	if (num == 0)
-		return(0);
-	else if (num == -1)
-		num=strlen(buf);
+    if (num == 0)
+        return (0);
+    else if (num == -1)
+        num = strlen(buf);
 
-	p=buf;
-	c= *(p++);
-	num--;
-	if ((c >= '0') && (c <= '2'))
-		{
-		first= c-'0';
-		}
-	else
-		{
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_FIRST_NUM_TOO_LARGE);
-		goto err;
-		}
+    p = buf;
+    c = *(p++);
+    num--;
+    if ((c >= '0') && (c <= '2')) {
+        first = c - '0';
+    } else {
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_FIRST_NUM_TOO_LARGE);
+        goto err;
+    }
 
-	if (num <= 0)
-		{
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_SECOND_NUMBER);
-		goto err;
-		}
-	c= *(p++);
-	num--;
-	for (;;)
-		{
-		if (num <= 0) break;
-		if ((c != '.') && (c != ' '))
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_SEPARATOR);
-			goto err;
-			}
-		l=0;
-		use_bn = 0;
-		for (;;)
-			{
-			if (num <= 0) break;
-			num--;
-			c= *(p++);
-			if ((c == ' ') || (c == '.'))
-				break;
-			if ((c < '0') || (c > '9'))
-				{
-				OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_DIGIT);
-				goto err;
-				}
-			if (!use_bn && l >= ((ULONG_MAX - 80) / 10L))
-				{
-				use_bn = 1;
-				if (!bl)
-					bl = BN_new();
-				if (!bl || !BN_set_word(bl, l))
-					goto err;
-				}
-			if (use_bn)
-				{
-				if (!BN_mul_word(bl, 10L)
-					|| !BN_add_word(bl, c-'0'))
-					goto err;
-				}
-			else
-				l=l*10L+(long)(c-'0');
-			}
-		if (len == 0)
-			{
-			if ((first < 2) && (l >= 40))
-				{
-				OPENSSL_PUT_ERROR(ASN1, ASN1_R_SECOND_NUMBER_TOO_LARGE);
-				goto err;
-				}
-			if (use_bn)
-				{
-				if (!BN_add_word(bl, first * 40))
-					goto err;
-				}
-			else
-				l+=(long)first*40;
-			}
-		i=0;
-		if (use_bn)
-			{
-			int blsize;
-			blsize = BN_num_bits(bl);
-			blsize = (blsize + 6)/7;
-			if (blsize > tmpsize)
-				{
-				if (tmp != ftmp)
-					OPENSSL_free(tmp);
-				tmpsize = blsize + 32;
-				tmp = OPENSSL_malloc(tmpsize);
-				if (!tmp)
-					goto err;
-				}
-			while(blsize--)
-				tmp[i++] = (unsigned char)BN_div_word(bl, 0x80L);
-			}
-		else
-			{
-					
-			for (;;)
-				{
-				tmp[i++]=(unsigned char)l&0x7f;
-				l>>=7L;
-				if (l == 0L) break;
-				}
+    if (num <= 0) {
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_SECOND_NUMBER);
+        goto err;
+    }
+    c = *(p++);
+    num--;
+    for (;;) {
+        if (num <= 0)
+            break;
+        if ((c != '.') && (c != ' ')) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_SEPARATOR);
+            goto err;
+        }
+        l = 0;
+        use_bn = 0;
+        for (;;) {
+            if (num <= 0)
+                break;
+            num--;
+            c = *(p++);
+            if ((c == ' ') || (c == '.'))
+                break;
+            if ((c < '0') || (c > '9')) {
+                OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_DIGIT);
+                goto err;
+            }
+            if (!use_bn && l >= ((ULONG_MAX - 80) / 10L)) {
+                use_bn = 1;
+                if (!bl)
+                    bl = BN_new();
+                if (!bl || !BN_set_word(bl, l))
+                    goto err;
+            }
+            if (use_bn) {
+                if (!BN_mul_word(bl, 10L)
+                    || !BN_add_word(bl, c - '0'))
+                    goto err;
+            } else
+                l = l * 10L + (long)(c - '0');
+        }
+        if (len == 0) {
+            if ((first < 2) && (l >= 40)) {
+                OPENSSL_PUT_ERROR(ASN1, ASN1_R_SECOND_NUMBER_TOO_LARGE);
+                goto err;
+            }
+            if (use_bn) {
+                if (!BN_add_word(bl, first * 40))
+                    goto err;
+            } else
+                l += (long)first *40;
+        }
+        i = 0;
+        if (use_bn) {
+            int blsize;
+            blsize = BN_num_bits(bl);
+            blsize = (blsize + 6) / 7;
+            if (blsize > tmpsize) {
+                if (tmp != ftmp)
+                    OPENSSL_free(tmp);
+                tmpsize = blsize + 32;
+                tmp = OPENSSL_malloc(tmpsize);
+                if (!tmp)
+                    goto err;
+            }
+            while (blsize--) {
+                BN_ULONG t = BN_div_word(bl, 0x80L);
+                if (t == (BN_ULONG)-1)
+                    goto err;
+                tmp[i++] = (unsigned char)t;
+            }
+        } else {
 
-			}
-		if (out != NULL)
-			{
-			if (len+i > olen)
-				{
-				OPENSSL_PUT_ERROR(ASN1, ASN1_R_BUFFER_TOO_SMALL);
-				goto err;
-				}
-			while (--i > 0)
-				out[len++]=tmp[i]|0x80;
-			out[len++]=tmp[0];
-			}
-		else
-			len+=i;
-		}
-	if (tmp != ftmp)
-		OPENSSL_free(tmp);
-	if (bl)
-		BN_free(bl);
-	return(len);
-err:
-	if (tmp != ftmp)
-		OPENSSL_free(tmp);
-	if (bl)
-		BN_free(bl);
-	return(0);
-	}
+            for (;;) {
+                tmp[i++] = (unsigned char)l & 0x7f;
+                l >>= 7L;
+                if (l == 0L)
+                    break;
+            }
+
+        }
+        if (out != NULL) {
+            if (len + i > olen) {
+                OPENSSL_PUT_ERROR(ASN1, ASN1_R_BUFFER_TOO_SMALL);
+                goto err;
+            }
+            while (--i > 0)
+                out[len++] = tmp[i] | 0x80;
+            out[len++] = tmp[0];
+        } else
+            len += i;
+    }
+    if (tmp != ftmp)
+        OPENSSL_free(tmp);
+    if (bl)
+        BN_free(bl);
+    return (len);
+ err:
+    if (tmp != ftmp)
+        OPENSSL_free(tmp);
+    if (bl)
+        BN_free(bl);
+    return (0);
+}
 
 int i2t_ASN1_OBJECT(char *buf, int buf_len, ASN1_OBJECT *a)
 {
-	return OBJ_obj2txt(buf, buf_len, a, 0);
+    return OBJ_obj2txt(buf, buf_len, a, 0);
 }
 
 int i2a_ASN1_OBJECT(BIO *bp, ASN1_OBJECT *a)
-	{
-	char buf[80], *p = buf;
-	int i;
+{
+    char buf[80], *p = buf;
+    int i;
 
-	if ((a == NULL) || (a->data == NULL))
-		return(BIO_write(bp,"NULL",4));
-	i=i2t_ASN1_OBJECT(buf,sizeof buf,a);
-	if (i > (int)(sizeof(buf) - 1))
-		{
-		p = OPENSSL_malloc(i + 1);
-		if (!p)
-			return -1;
-		i2t_ASN1_OBJECT(p,i + 1,a);
-		}
-	if (i <= 0)
-		return BIO_write(bp, "<INVALID>", 9);
-	BIO_write(bp,p,i);
-	if (p != buf)
-		OPENSSL_free(p);
-	return(i);
-	}
+    if ((a == NULL) || (a->data == NULL))
+        return (BIO_write(bp, "NULL", 4));
+    i = i2t_ASN1_OBJECT(buf, sizeof buf, a);
+    if (i > (int)(sizeof(buf) - 1)) {
+        p = OPENSSL_malloc(i + 1);
+        if (!p)
+            return -1;
+        i2t_ASN1_OBJECT(p, i + 1, a);
+    }
+    if (i <= 0)
+        return BIO_write(bp, "<INVALID>", 9);
+    BIO_write(bp, p, i);
+    if (p != buf)
+        OPENSSL_free(p);
+    return (i);
+}
 
 ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
-	     long length)
+                             long length)
 {
-	const unsigned char *p;
-	long len;
-	int tag,xclass;
-	int inf,i;
-	ASN1_OBJECT *ret = NULL;
-	p= *pp;
-	inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
-	if (inf & 0x80)
-		{
-		i=ASN1_R_BAD_OBJECT_HEADER;
-		goto err;
-		}
+    const unsigned char *p;
+    long len;
+    int tag, xclass;
+    int inf, i;
+    ASN1_OBJECT *ret = NULL;
+    p = *pp;
+    inf = ASN1_get_object(&p, &len, &tag, &xclass, length);
+    if (inf & 0x80) {
+        i = ASN1_R_BAD_OBJECT_HEADER;
+        goto err;
+    }
 
-	if (tag != V_ASN1_OBJECT)
-		{
-		i=ASN1_R_EXPECTING_AN_OBJECT;
-		goto err;
-		}
-	ret = c2i_ASN1_OBJECT(a, &p, len);
-	if(ret) *pp = p;
-	return ret;
-err:
-	OPENSSL_PUT_ERROR(ASN1, i);
-	return(NULL);
+    if (tag != V_ASN1_OBJECT) {
+        i = ASN1_R_EXPECTING_AN_OBJECT;
+        goto err;
+    }
+    ret = c2i_ASN1_OBJECT(a, &p, len);
+    if (ret)
+        *pp = p;
+    return ret;
+ err:
+    OPENSSL_PUT_ERROR(ASN1, i);
+    return (NULL);
 }
 
 ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
-	     long len)
-	{
-	ASN1_OBJECT *ret=NULL;
-	const unsigned char *p;
-	unsigned char *data;
-	int i, length;
+                             long len)
+{
+    ASN1_OBJECT *ret = NULL;
+    const unsigned char *p;
+    unsigned char *data;
+    int i, length;
 
-	/* Sanity check OID encoding.
-	 * Need at least one content octet.
-	 * MSB must be clear in the last octet.
-	 * can't have leading 0x80 in subidentifiers, see: X.690 8.19.2
-	 */
-	if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL ||
-	    p[len - 1] & 0x80)
-		{
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING);
-		return NULL;
-		}
-	/* Now 0 < len <= INT_MAX, so the cast is safe. */
-	length = (int)len;
-	for (i = 0; i < length; i++, p++)
-		{
-		if (*p == 0x80 && (!i || !(p[-1] & 0x80)))
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING);
-			return NULL;
-			}
-		}
+    /*
+     * Sanity check OID encoding. Need at least one content octet. MSB must
+     * be clear in the last octet. can't have leading 0x80 in subidentifiers,
+     * see: X.690 8.19.2
+     */
+    if (len <= 0 || len > INT_MAX || pp == NULL || (p = *pp) == NULL ||
+        p[len - 1] & 0x80) {
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING);
+        return NULL;
+    }
+    /* Now 0 < len <= INT_MAX, so the cast is safe. */
+    length = (int)len;
+    for (i = 0; i < length; i++, p++) {
+        if (*p == 0x80 && (!i || !(p[-1] & 0x80))) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING);
+            return NULL;
+        }
+    }
 
-	/* only the ASN1_OBJECTs from the 'table' will have values
-	 * for ->sn or ->ln */
-	if ((a == NULL) || ((*a) == NULL) ||
-		!((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC))
-		{
-		if ((ret=ASN1_OBJECT_new()) == NULL) return(NULL);
-		}
-	else	ret=(*a);
+    /*
+     * only the ASN1_OBJECTs from the 'table' will have values for ->sn or
+     * ->ln
+     */
+    if ((a == NULL) || ((*a) == NULL) ||
+        !((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC)) {
+        if ((ret = ASN1_OBJECT_new()) == NULL)
+            return (NULL);
+    } else
+        ret = (*a);
 
-	p= *pp;
-	/* detach data from object */
-	data = (unsigned char *)ret->data;
-	ret->data = NULL;
-	/* once detached we can change it */
-	if ((data == NULL) || (ret->length < length))
-		{
-		ret->length=0;
-		if (data != NULL) OPENSSL_free(data);
-		data=(unsigned char *)OPENSSL_malloc(length);
-		if (data == NULL)
-			{ i=ERR_R_MALLOC_FAILURE; goto err; }
-		ret->flags|=ASN1_OBJECT_FLAG_DYNAMIC_DATA;
-		}
-	memcpy(data,p,length);
-	/* reattach data to object, after which it remains const */
-	ret->data  =data;
-	ret->length=length;
-	ret->sn=NULL;
-	ret->ln=NULL;
-	/* ret->flags=ASN1_OBJECT_FLAG_DYNAMIC; we know it is dynamic */
-	p+=length;
+    p = *pp;
+    /* detach data from object */
+    data = (unsigned char *)ret->data;
+    ret->data = NULL;
+    /* once detached we can change it */
+    if ((data == NULL) || (ret->length < length)) {
+        ret->length = 0;
+        if (data != NULL)
+            OPENSSL_free(data);
+        data = (unsigned char *)OPENSSL_malloc(length);
+        if (data == NULL) {
+            i = ERR_R_MALLOC_FAILURE;
+            goto err;
+        }
+        ret->flags |= ASN1_OBJECT_FLAG_DYNAMIC_DATA;
+    }
+    OPENSSL_memcpy(data, p, length);
+    /* reattach data to object, after which it remains const */
+    ret->data = data;
+    ret->length = length;
+    ret->sn = NULL;
+    ret->ln = NULL;
+    /* ret->flags=ASN1_OBJECT_FLAG_DYNAMIC; we know it is dynamic */
+    p += length;
 
-	if (a != NULL) (*a)=ret;
-	*pp=p;
-	return(ret);
-err:
-	OPENSSL_PUT_ERROR(ASN1, i);
-	if ((ret != NULL) && ((a == NULL) || (*a != ret)))
-		ASN1_OBJECT_free(ret);
-	return(NULL);
-	}
+    if (a != NULL)
+        (*a) = ret;
+    *pp = p;
+    return (ret);
+ err:
+    OPENSSL_PUT_ERROR(ASN1, i);
+    if ((ret != NULL) && ((a == NULL) || (*a != ret)))
+        ASN1_OBJECT_free(ret);
+    return (NULL);
+}
 
 ASN1_OBJECT *ASN1_OBJECT_new(void)
-	{
-	ASN1_OBJECT *ret;
+{
+    ASN1_OBJECT *ret;
 
-	ret=(ASN1_OBJECT *)OPENSSL_malloc(sizeof(ASN1_OBJECT));
-	if (ret == NULL)
-		{
-		OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-		return(NULL);
-		}
-	ret->length=0;
-	ret->data=NULL;
-	ret->nid=0;
-	ret->sn=NULL;
-	ret->ln=NULL;
-	ret->flags=ASN1_OBJECT_FLAG_DYNAMIC;
-	return(ret);
-	}
+    ret = (ASN1_OBJECT *)OPENSSL_malloc(sizeof(ASN1_OBJECT));
+    if (ret == NULL) {
+        OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+        return (NULL);
+    }
+    ret->length = 0;
+    ret->data = NULL;
+    ret->nid = 0;
+    ret->sn = NULL;
+    ret->ln = NULL;
+    ret->flags = ASN1_OBJECT_FLAG_DYNAMIC;
+    return (ret);
+}
 
 void ASN1_OBJECT_free(ASN1_OBJECT *a)
-	{
-	if (a == NULL) return;
-	if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS)
-		{
-#ifndef CONST_STRICT /* disable purely for compile-time strict const checking. Doing this on a "real" compile will cause memory leaks */
-		if (a->sn != NULL) OPENSSL_free((void *)a->sn);
-		if (a->ln != NULL) OPENSSL_free((void *)a->ln);
+{
+    if (a == NULL)
+        return;
+    if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) {
+#ifndef CONST_STRICT            /* disable purely for compile-time strict
+                                 * const checking. Doing this on a "real"
+                                 * compile will cause memory leaks */
+        if (a->sn != NULL)
+            OPENSSL_free((void *)a->sn);
+        if (a->ln != NULL)
+            OPENSSL_free((void *)a->ln);
 #endif
-		a->sn=a->ln=NULL;
-		}
-	if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA)
-		{
-		if (a->data != NULL) OPENSSL_free((void *)a->data);
-		a->data=NULL;
-		a->length=0;
-		}
-	if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC)
-		OPENSSL_free(a);
-	}
+        a->sn = a->ln = NULL;
+    }
+    if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA) {
+        if (a->data != NULL)
+            OPENSSL_free((void *)a->data);
+        a->data = NULL;
+        a->length = 0;
+    }
+    if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC)
+        OPENSSL_free(a);
+}
 
 ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data, int len,
-	     const char *sn, const char *ln)
-	{
-	ASN1_OBJECT o;
+                                const char *sn, const char *ln)
+{
+    ASN1_OBJECT o;
 
-	o.sn=sn;
-	o.ln=ln;
-	o.data=data;
-	o.nid=nid;
-	o.length=len;
-	o.flags=ASN1_OBJECT_FLAG_DYNAMIC|ASN1_OBJECT_FLAG_DYNAMIC_STRINGS|
-		ASN1_OBJECT_FLAG_DYNAMIC_DATA;
-	return(OBJ_dup(&o));
-	}
+    o.sn = sn;
+    o.ln = ln;
+    o.data = data;
+    o.nid = nid;
+    o.length = len;
+    o.flags = ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
+        ASN1_OBJECT_FLAG_DYNAMIC_DATA;
+    return (OBJ_dup(&o));
+}
diff --git a/src/crypto/asn1/a_octet.c b/src/crypto/asn1/a_octet.c
index 583c9e9..2e74d6b 100644
--- a/src/crypto/asn1/a_octet.c
+++ b/src/crypto/asn1/a_octet.c
@@ -59,12 +59,19 @@
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
-
 ASN1_OCTET_STRING *ASN1_OCTET_STRING_dup(const ASN1_OCTET_STRING *x)
-{ return M_ASN1_OCTET_STRING_dup(x); }
+{
+    return M_ASN1_OCTET_STRING_dup(x);
+}
 
-int ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a, const ASN1_OCTET_STRING *b)
-{ return M_ASN1_OCTET_STRING_cmp(a, b); }
+int ASN1_OCTET_STRING_cmp(const ASN1_OCTET_STRING *a,
+                          const ASN1_OCTET_STRING *b)
+{
+    return M_ASN1_OCTET_STRING_cmp(a, b);
+}
 
-int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *x, const unsigned char *d, int len)
-{ return M_ASN1_OCTET_STRING_set(x, d, len); }
+int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *x, const unsigned char *d,
+                          int len)
+{
+    return M_ASN1_OCTET_STRING_set(x, d, len);
+}
diff --git a/src/crypto/asn1/a_print.c b/src/crypto/asn1/a_print.c
index 3b6be10..aee54fa 100644
--- a/src/crypto/asn1/a_print.c
+++ b/src/crypto/asn1/a_print.c
@@ -59,61 +59,63 @@
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
-
 int ASN1_PRINTABLE_type(const unsigned char *s, int len)
-	{
-	int c;
-	int ia5=0;
-	int t61=0;
+{
+    int c;
+    int ia5 = 0;
+    int t61 = 0;
 
-	if (len <= 0) len= -1;
-	if (s == NULL) return(V_ASN1_PRINTABLESTRING);
+    if (len <= 0)
+        len = -1;
+    if (s == NULL)
+        return (V_ASN1_PRINTABLESTRING);
 
-	while ((*s) && (len-- != 0))
-		{
-		c= *(s++);
-		if (!(	((c >= 'a') && (c <= 'z')) ||
-			((c >= 'A') && (c <= 'Z')) ||
-			(c == ' ') ||
-			((c >= '0') && (c <= '9')) ||
-			(c == ' ') || (c == '\'') ||
-			(c == '(') || (c == ')') ||
-			(c == '+') || (c == ',') ||
-			(c == '-') || (c == '.') ||
-			(c == '/') || (c == ':') ||
-			(c == '=') || (c == '?')))
-			ia5=1;
-		if (c&0x80)
-			t61=1;
-		}
-	if (t61) return(V_ASN1_T61STRING);
-	if (ia5) return(V_ASN1_IA5STRING);
-	return(V_ASN1_PRINTABLESTRING);
-	}
+    while ((*s) && (len-- != 0)) {
+        c = *(s++);
+        if (!(((c >= 'a') && (c <= 'z')) ||
+              ((c >= 'A') && (c <= 'Z')) ||
+              (c == ' ') ||
+              ((c >= '0') && (c <= '9')) ||
+              (c == ' ') || (c == '\'') ||
+              (c == '(') || (c == ')') ||
+              (c == '+') || (c == ',') ||
+              (c == '-') || (c == '.') ||
+              (c == '/') || (c == ':') || (c == '=') || (c == '?')))
+            ia5 = 1;
+        if (c & 0x80)
+            t61 = 1;
+    }
+    if (t61)
+        return (V_ASN1_T61STRING);
+    if (ia5)
+        return (V_ASN1_IA5STRING);
+    return (V_ASN1_PRINTABLESTRING);
+}
 
 int ASN1_UNIVERSALSTRING_to_string(ASN1_UNIVERSALSTRING *s)
-	{
-	int i;
-	unsigned char *p;
+{
+    int i;
+    unsigned char *p;
 
-	if (s->type != V_ASN1_UNIVERSALSTRING) return(0);
-	if ((s->length%4) != 0) return(0);
-	p=s->data;
-	for (i=0; i<s->length; i+=4)
-		{
-		if ((p[0] != '\0') || (p[1] != '\0') || (p[2] != '\0'))
-			break;
-		else
-			p+=4;
-		}
-	if (i < s->length) return(0);
-	p=s->data;
-	for (i=3; i<s->length; i+=4)
-		{
-		*(p++)=s->data[i];
-		}
-	*(p)='\0';
-	s->length/=4;
-	s->type=ASN1_PRINTABLE_type(s->data,s->length);
-	return(1);
-	}
+    if (s->type != V_ASN1_UNIVERSALSTRING)
+        return (0);
+    if ((s->length % 4) != 0)
+        return (0);
+    p = s->data;
+    for (i = 0; i < s->length; i += 4) {
+        if ((p[0] != '\0') || (p[1] != '\0') || (p[2] != '\0'))
+            break;
+        else
+            p += 4;
+    }
+    if (i < s->length)
+        return (0);
+    p = s->data;
+    for (i = 3; i < s->length; i += 4) {
+        *(p++) = s->data[i];
+    }
+    *(p) = '\0';
+    s->length /= 4;
+    s->type = ASN1_PRINTABLE_type(s->data, s->length);
+    return (1);
+}
diff --git a/src/crypto/asn1/a_strnid.c b/src/crypto/asn1/a_strnid.c
index d4316f7..c558bce 100644
--- a/src/crypto/asn1/a_strnid.c
+++ b/src/crypto/asn1/a_strnid.c
@@ -56,231 +56,254 @@
 
 #include <openssl/asn1.h>
 
-#include <stdlib.h>  /* For bsearch */
+#include <stdlib.h>             /* For bsearch */
 #include <string.h>
 
 #include <openssl/err.h>
 #include <openssl/mem.h>
 #include <openssl/obj.h>
 
-
 static STACK_OF(ASN1_STRING_TABLE) *stable = NULL;
 static void st_free(ASN1_STRING_TABLE *tbl);
 
-/* This is the global mask for the mbstring functions: this is use to
- * mask out certain types (such as BMPString and UTF8String) because
- * certain software (e.g. Netscape) has problems with them.
+/*
+ * This is the global mask for the mbstring functions: this is use to mask
+ * out certain types (such as BMPString and UTF8String) because certain
+ * software (e.g. Netscape) has problems with them.
  */
 
 static unsigned long global_mask = B_ASN1_UTF8STRING;
 
 void ASN1_STRING_set_default_mask(unsigned long mask)
 {
-	global_mask = mask;
+    global_mask = mask;
 }
 
 unsigned long ASN1_STRING_get_default_mask(void)
 {
-	return global_mask;
+    return global_mask;
 }
 
-/* This function sets the default to various "flavours" of configuration.
- * based on an ASCII string. Currently this is:
- * MASK:XXXX : a numerical mask value.
- * nobmp : Don't use BMPStrings (just Printable, T61).
- * pkix : PKIX recommendation in RFC2459.
- * utf8only : only use UTF8Strings (RFC2459 recommendation for 2004).
- * default:   the default value, Printable, T61, BMP.
+/*
+ * This function sets the default to various "flavours" of configuration.
+ * based on an ASCII string. Currently this is: MASK:XXXX : a numerical mask
+ * value. nobmp : Don't use BMPStrings (just Printable, T61). pkix : PKIX
+ * recommendation in RFC2459. utf8only : only use UTF8Strings (RFC2459
+ * recommendation for 2004). default: the default value, Printable, T61, BMP.
  */
 
 int ASN1_STRING_set_default_mask_asc(const char *p)
 {
-	unsigned long mask;
-	char *end;
-	if(!strncmp(p, "MASK:", 5)) {
-		if(!p[5]) return 0;
-		mask = strtoul(p + 5, &end, 0);
-		if(*end) return 0;
-	} else if(!strcmp(p, "nombstr"))
-			 mask = ~((unsigned long)(B_ASN1_BMPSTRING|B_ASN1_UTF8STRING));
-	else if(!strcmp(p, "pkix"))
-			mask = ~((unsigned long)B_ASN1_T61STRING);
-	else if(!strcmp(p, "utf8only")) mask = B_ASN1_UTF8STRING;
-	else if(!strcmp(p, "default"))
-	    mask = 0xFFFFFFFFL;
-	else return 0;
-	ASN1_STRING_set_default_mask(mask);
-	return 1;
+    unsigned long mask;
+    char *end;
+    if (!strncmp(p, "MASK:", 5)) {
+        if (!p[5])
+            return 0;
+        mask = strtoul(p + 5, &end, 0);
+        if (*end)
+            return 0;
+    } else if (!strcmp(p, "nombstr"))
+        mask = ~((unsigned long)(B_ASN1_BMPSTRING | B_ASN1_UTF8STRING));
+    else if (!strcmp(p, "pkix"))
+        mask = ~((unsigned long)B_ASN1_T61STRING);
+    else if (!strcmp(p, "utf8only"))
+        mask = B_ASN1_UTF8STRING;
+    else if (!strcmp(p, "default"))
+        mask = 0xFFFFFFFFL;
+    else
+        return 0;
+    ASN1_STRING_set_default_mask(mask);
+    return 1;
 }
 
-/* The following function generates an ASN1_STRING based on limits in a table.
- * Frequently the types and length of an ASN1_STRING are restricted by a 
- * corresponding OID. For example certificates and certificate requests.
+/*
+ * The following function generates an ASN1_STRING based on limits in a
+ * table. Frequently the types and length of an ASN1_STRING are restricted by
+ * a corresponding OID. For example certificates and certificate requests.
  */
 
-ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out, const unsigned char *in,
-					int inlen, int inform, int nid)
+ASN1_STRING *ASN1_STRING_set_by_NID(ASN1_STRING **out,
+                                    const unsigned char *in, int inlen,
+                                    int inform, int nid)
 {
-	ASN1_STRING_TABLE *tbl;
-	ASN1_STRING *str = NULL;
-	unsigned long mask;
-	int ret;
-	if(!out) out = &str;
-	tbl = ASN1_STRING_TABLE_get(nid);
-	if(tbl) {
-		mask = tbl->mask;
-		if(!(tbl->flags & STABLE_NO_MASK)) mask &= global_mask;
-		ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask,
-					tbl->minsize, tbl->maxsize);
-	} else ret = ASN1_mbstring_copy(out, in, inlen, inform, DIRSTRING_TYPE & global_mask);
-	if(ret <= 0) return NULL;
-	return *out;
+    ASN1_STRING_TABLE *tbl;
+    ASN1_STRING *str = NULL;
+    unsigned long mask;
+    int ret;
+    if (!out)
+        out = &str;
+    tbl = ASN1_STRING_TABLE_get(nid);
+    if (tbl) {
+        mask = tbl->mask;
+        if (!(tbl->flags & STABLE_NO_MASK))
+            mask &= global_mask;
+        ret = ASN1_mbstring_ncopy(out, in, inlen, inform, mask,
+                                  tbl->minsize, tbl->maxsize);
+    } else
+        ret =
+            ASN1_mbstring_copy(out, in, inlen, inform,
+                               DIRSTRING_TYPE & global_mask);
+    if (ret <= 0)
+        return NULL;
+    return *out;
 }
 
-/* Now the tables and helper functions for the string table:
+/*
+ * Now the tables and helper functions for the string table:
  */
 
 /* size limits: this stuff is taken straight from RFC3280 */
 
-#define ub_name				32768
-#define ub_common_name			64
-#define ub_locality_name		128
-#define ub_state_name			128
-#define ub_organization_name		64
-#define ub_organization_unit_name	64
-#define ub_title			64
-#define ub_email_address		128
-#define ub_serial_number		64
-
+#define ub_name                         32768
+#define ub_common_name                  64
+#define ub_locality_name                128
+#define ub_state_name                   128
+#define ub_organization_name            64
+#define ub_organization_unit_name       64
+#define ub_title                        64
+#define ub_email_address                128
+#define ub_serial_number                64
 
 /* This table must be kept in NID order */
 
 static const ASN1_STRING_TABLE tbl_standard[] = {
-{NID_commonName,		1, ub_common_name, DIRSTRING_TYPE, 0},
-{NID_countryName,		2, 2, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
-{NID_localityName,		1, ub_locality_name, DIRSTRING_TYPE, 0},
-{NID_stateOrProvinceName,	1, ub_state_name, DIRSTRING_TYPE, 0},
-{NID_organizationName,		1, ub_organization_name, DIRSTRING_TYPE, 0},
-{NID_organizationalUnitName,	1, ub_organization_unit_name, DIRSTRING_TYPE, 0},
-{NID_pkcs9_emailAddress,	1, ub_email_address, B_ASN1_IA5STRING, STABLE_NO_MASK},
-{NID_pkcs9_unstructuredName,	1, -1, PKCS9STRING_TYPE, 0},
-{NID_pkcs9_challengePassword,	1, -1, PKCS9STRING_TYPE, 0},
-{NID_pkcs9_unstructuredAddress,	1, -1, DIRSTRING_TYPE, 0},
-{NID_givenName,			1, ub_name, DIRSTRING_TYPE, 0},
-{NID_surname,			1, ub_name, DIRSTRING_TYPE, 0},
-{NID_initials,			1, ub_name, DIRSTRING_TYPE, 0},
-{NID_serialNumber,		1, ub_serial_number, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
-{NID_friendlyName,		-1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK},
-{NID_name,			1, ub_name, DIRSTRING_TYPE, 0},
-{NID_dnQualifier,		-1, -1, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
-{NID_domainComponent,		1, -1, B_ASN1_IA5STRING, STABLE_NO_MASK},
-{NID_ms_csp_name,		-1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK}
+    {NID_commonName, 1, ub_common_name, DIRSTRING_TYPE, 0},
+    {NID_countryName, 2, 2, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
+    {NID_localityName, 1, ub_locality_name, DIRSTRING_TYPE, 0},
+    {NID_stateOrProvinceName, 1, ub_state_name, DIRSTRING_TYPE, 0},
+    {NID_organizationName, 1, ub_organization_name, DIRSTRING_TYPE, 0},
+    {NID_organizationalUnitName, 1, ub_organization_unit_name, DIRSTRING_TYPE,
+     0},
+    {NID_pkcs9_emailAddress, 1, ub_email_address, B_ASN1_IA5STRING,
+     STABLE_NO_MASK},
+    {NID_pkcs9_unstructuredName, 1, -1, PKCS9STRING_TYPE, 0},
+    {NID_pkcs9_challengePassword, 1, -1, PKCS9STRING_TYPE, 0},
+    {NID_pkcs9_unstructuredAddress, 1, -1, DIRSTRING_TYPE, 0},
+    {NID_givenName, 1, ub_name, DIRSTRING_TYPE, 0},
+    {NID_surname, 1, ub_name, DIRSTRING_TYPE, 0},
+    {NID_initials, 1, ub_name, DIRSTRING_TYPE, 0},
+    {NID_serialNumber, 1, ub_serial_number, B_ASN1_PRINTABLESTRING,
+     STABLE_NO_MASK},
+    {NID_friendlyName, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK},
+    {NID_name, 1, ub_name, DIRSTRING_TYPE, 0},
+    {NID_dnQualifier, -1, -1, B_ASN1_PRINTABLESTRING, STABLE_NO_MASK},
+    {NID_domainComponent, 1, -1, B_ASN1_IA5STRING, STABLE_NO_MASK},
+    {NID_ms_csp_name, -1, -1, B_ASN1_BMPSTRING, STABLE_NO_MASK}
 };
 
 static int sk_table_cmp(const ASN1_STRING_TABLE **a,
-			const ASN1_STRING_TABLE **b)
+                        const ASN1_STRING_TABLE **b)
 {
-	return (*a)->nid - (*b)->nid;
+    return (*a)->nid - (*b)->nid;
 }
 
 static int table_cmp(const void *in_a, const void *in_b)
 {
-	const ASN1_STRING_TABLE *a = in_a;
-	const ASN1_STRING_TABLE *b = in_b;
-	return a->nid - b->nid;
+    const ASN1_STRING_TABLE *a = in_a;
+    const ASN1_STRING_TABLE *b = in_b;
+    return a->nid - b->nid;
 }
 
 ASN1_STRING_TABLE *ASN1_STRING_TABLE_get(int nid)
 {
-	int found;
-	size_t idx;
-	ASN1_STRING_TABLE *ttmp;
-	ASN1_STRING_TABLE fnd;
-	fnd.nid = nid;
+    int found;
+    size_t idx;
+    ASN1_STRING_TABLE *ttmp;
+    ASN1_STRING_TABLE fnd;
+    fnd.nid = nid;
 
-	ttmp = bsearch(&fnd, tbl_standard, sizeof(tbl_standard)/sizeof(ASN1_STRING_TABLE), sizeof(ASN1_STRING_TABLE), table_cmp);
-	if(ttmp) return ttmp;
-	if(!stable) return NULL;
-	found = sk_ASN1_STRING_TABLE_find(stable, &idx, &fnd);
-	if (!found) return NULL;
-	return sk_ASN1_STRING_TABLE_value(stable, idx);
+    ttmp =
+        bsearch(&fnd, tbl_standard,
+                sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE),
+                sizeof(ASN1_STRING_TABLE), table_cmp);
+    if (ttmp)
+        return ttmp;
+    if (!stable)
+        return NULL;
+    found = sk_ASN1_STRING_TABLE_find(stable, &idx, &fnd);
+    if (!found)
+        return NULL;
+    return sk_ASN1_STRING_TABLE_value(stable, idx);
 }
-	
+
 int ASN1_STRING_TABLE_add(int nid,
-		 long minsize, long maxsize, unsigned long mask,
-				unsigned long flags)
+                          long minsize, long maxsize, unsigned long mask,
+                          unsigned long flags)
 {
-	ASN1_STRING_TABLE *tmp;
-	char new_nid = 0;
-	flags &= ~STABLE_FLAGS_MALLOC;
-	if(!stable) stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp);
-	if(!stable) {
-		OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-		return 0;
-	}
-	if(!(tmp = ASN1_STRING_TABLE_get(nid))) {
-		tmp = OPENSSL_malloc(sizeof(ASN1_STRING_TABLE));
-		if(!tmp) {
-			OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-			return 0;
-		}
-		tmp->flags = flags | STABLE_FLAGS_MALLOC;
-		tmp->nid = nid;
-		new_nid = 1;
-	} else tmp->flags = (tmp->flags & STABLE_FLAGS_MALLOC) | flags;
-	if(minsize != -1) tmp->minsize = minsize;
-	if(maxsize != -1) tmp->maxsize = maxsize;
-	tmp->mask = mask;
-	if(new_nid) sk_ASN1_STRING_TABLE_push(stable, tmp);
-	return 1;
+    ASN1_STRING_TABLE *tmp;
+    char new_nid = 0;
+    flags &= ~STABLE_FLAGS_MALLOC;
+    if (!stable)
+        stable = sk_ASN1_STRING_TABLE_new(sk_table_cmp);
+    if (!stable) {
+        OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
+    if (!(tmp = ASN1_STRING_TABLE_get(nid))) {
+        tmp = OPENSSL_malloc(sizeof(ASN1_STRING_TABLE));
+        if (!tmp) {
+            OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+            return 0;
+        }
+        tmp->flags = flags | STABLE_FLAGS_MALLOC;
+        tmp->nid = nid;
+        tmp->minsize = tmp->maxsize = -1;
+        new_nid = 1;
+    } else
+        tmp->flags = (tmp->flags & STABLE_FLAGS_MALLOC) | flags;
+    if (minsize != -1)
+        tmp->minsize = minsize;
+    if (maxsize != -1)
+        tmp->maxsize = maxsize;
+    tmp->mask = mask;
+    if (new_nid)
+        sk_ASN1_STRING_TABLE_push(stable, tmp);
+    return 1;
 }
 
 void ASN1_STRING_TABLE_cleanup(void)
 {
-	STACK_OF(ASN1_STRING_TABLE) *tmp;
-	tmp = stable;
-	if(!tmp) return;
-	stable = NULL;
-	sk_ASN1_STRING_TABLE_pop_free(tmp, st_free);
+    STACK_OF(ASN1_STRING_TABLE) *tmp;
+    tmp = stable;
+    if (!tmp)
+        return;
+    stable = NULL;
+    sk_ASN1_STRING_TABLE_pop_free(tmp, st_free);
 }
 
 static void st_free(ASN1_STRING_TABLE *tbl)
 {
-	if(tbl->flags & STABLE_FLAGS_MALLOC) OPENSSL_free(tbl);
+    if (tbl->flags & STABLE_FLAGS_MALLOC)
+        OPENSSL_free(tbl);
 }
 
-
 #ifdef STRING_TABLE_TEST
 
-int
-main(void)
+int main(void)
 {
-	ASN1_STRING_TABLE *tmp;
-	int i, last_nid = -1;
+    ASN1_STRING_TABLE *tmp;
+    int i, last_nid = -1;
 
-	for (tmp = tbl_standard, i = 0;
-		i < sizeof(tbl_standard)/sizeof(ASN1_STRING_TABLE); i++, tmp++)
-		{
-			if (tmp->nid < last_nid)
-				{
-				last_nid = 0;
-				break;
-				}
-			last_nid = tmp->nid;
-		}
+    for (tmp = tbl_standard, i = 0;
+         i < sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE); i++, tmp++) {
+        if (tmp->nid < last_nid) {
+            last_nid = 0;
+            break;
+        }
+        last_nid = tmp->nid;
+    }
 
-	if (last_nid != 0)
-		{
-		printf("Table order OK\n");
-		exit(0);
-		}
+    if (last_nid != 0) {
+        printf("Table order OK\n");
+        exit(0);
+    }
 
-	for (tmp = tbl_standard, i = 0;
-		i < sizeof(tbl_standard)/sizeof(ASN1_STRING_TABLE); i++, tmp++)
-			printf("Index %d, NID %d, Name=%s\n", i, tmp->nid,
-							OBJ_nid2ln(tmp->nid));
+    for (tmp = tbl_standard, i = 0;
+         i < sizeof(tbl_standard) / sizeof(ASN1_STRING_TABLE); i++, tmp++)
+        printf("Index %d, NID %d, Name=%s\n", i, tmp->nid,
+               OBJ_nid2ln(tmp->nid));
 
-	return 0;
+    return 0;
 }
 
 #endif
diff --git a/src/crypto/asn1/a_time.c b/src/crypto/asn1/a_time.c
index ac2cb48..c962c0b 100644
--- a/src/crypto/asn1/a_time.c
+++ b/src/crypto/asn1/a_time.c
@@ -63,159 +63,151 @@
 #include <openssl/buf.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
-#include <openssl/time_support.h>
 
 #include "asn1_locl.h"
 
-
-/* This is an implementation of the ASN1 Time structure which is:
- *    Time ::= CHOICE {
- *      utcTime        UTCTime,
- *      generalTime    GeneralizedTime }
- * written by Steve Henson.
+/*
+ * This is an implementation of the ASN1 Time structure which is: Time ::=
+ * CHOICE { utcTime UTCTime, generalTime GeneralizedTime } written by Steve
+ * Henson.
  */
 
 IMPLEMENT_ASN1_MSTRING(ASN1_TIME, B_ASN1_TIME)
 
 IMPLEMENT_ASN1_FUNCTIONS(ASN1_TIME)
 
-#if 0
-int i2d_ASN1_TIME(ASN1_TIME *a, unsigned char **pp)
-	{
-	if(a->type == V_ASN1_UTCTIME || a->type == V_ASN1_GENERALIZEDTIME)
-				return(i2d_ASN1_bytes((ASN1_STRING *)a,pp,
-				     a->type ,V_ASN1_UNIVERSAL));
-	OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPECTING_A_TIME);
-	return -1;
-	}
-#endif
-
-
 ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t)
-	{
-	return ASN1_TIME_adj(s, t, 0, 0);
-	}
+{
+    return ASN1_TIME_adj(s, t, 0, 0);
+}
 
 ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t,
-				int offset_day, long offset_sec)
-	{
-	struct tm *ts;
-	struct tm data;
+                         int offset_day, long offset_sec)
+{
+    struct tm *ts;
+    struct tm data;
 
-	ts=OPENSSL_gmtime(&t,&data);
-	if (ts == NULL)
-		{
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_ERROR_GETTING_TIME);
-		return NULL;
-		}
-	if (offset_day || offset_sec)
-		{ 
-		if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
-			return NULL;
-		}
-	if((ts->tm_year >= 50) && (ts->tm_year < 150))
-			return ASN1_UTCTIME_adj(s, t, offset_day, offset_sec);
-	return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec);
-	}
+    ts = OPENSSL_gmtime(&t, &data);
+    if (ts == NULL) {
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_ERROR_GETTING_TIME);
+        return NULL;
+    }
+    if (offset_day || offset_sec) {
+        if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
+            return NULL;
+    }
+    if ((ts->tm_year >= 50) && (ts->tm_year < 150))
+        return ASN1_UTCTIME_adj(s, t, offset_day, offset_sec);
+    return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec);
+}
 
 int ASN1_TIME_check(ASN1_TIME *t)
-	{
-	if (t->type == V_ASN1_GENERALIZEDTIME)
-		return ASN1_GENERALIZEDTIME_check(t);
-	else if (t->type == V_ASN1_UTCTIME)
-		return ASN1_UTCTIME_check(t);
-	return 0;
-	}
+{
+    if (t->type == V_ASN1_GENERALIZEDTIME)
+        return ASN1_GENERALIZEDTIME_check(t);
+    else if (t->type == V_ASN1_UTCTIME)
+        return ASN1_UTCTIME_check(t);
+    return 0;
+}
 
 /* Convert an ASN1_TIME structure to GeneralizedTime */
-ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t, ASN1_GENERALIZEDTIME **out)
-	{
-	ASN1_GENERALIZEDTIME *ret;
-	char *str;
-	int newlen;
+ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t,
+                                                   ASN1_GENERALIZEDTIME **out)
+{
+    ASN1_GENERALIZEDTIME *ret = NULL;
+    char *str;
+    int newlen;
 
-	if (!ASN1_TIME_check(t)) return NULL;
+    if (!ASN1_TIME_check(t))
+        return NULL;
 
-	if (!out || !*out)
-		{
-		if (!(ret = ASN1_GENERALIZEDTIME_new ()))
-			return NULL;
-		if (out) *out = ret;
-		}
-	else ret = *out;
+    if (!out || !*out) {
+        if (!(ret = ASN1_GENERALIZEDTIME_new()))
+            goto err;
+    } else {
+        ret = *out;
+    }
 
-	/* If already GeneralizedTime just copy across */
-	if (t->type == V_ASN1_GENERALIZEDTIME)
-		{
-		if(!ASN1_STRING_set(ret, t->data, t->length))
-			return NULL;
-		return ret;
-		}
+    /* If already GeneralizedTime just copy across */
+    if (t->type == V_ASN1_GENERALIZEDTIME) {
+        if (!ASN1_STRING_set(ret, t->data, t->length))
+            goto err;
+        goto done;
+    }
 
-	/* grow the string */
-	if (!ASN1_STRING_set(ret, NULL, t->length + 2))
-		return NULL;
-	/* ASN1_STRING_set() allocated 'len + 1' bytes. */
-	newlen = t->length + 2 + 1;
-	str = (char *)ret->data;
-	/* Work out the century and prepend */
-	if (t->data[0] >= '5') BUF_strlcpy(str, "19", newlen);
-	else BUF_strlcpy(str, "20", newlen);
+    /* grow the string */
+    if (!ASN1_STRING_set(ret, NULL, t->length + 2))
+        goto err;
+    /* ASN1_STRING_set() allocated 'len + 1' bytes. */
+    newlen = t->length + 2 + 1;
+    str = (char *)ret->data;
+    /* Work out the century and prepend */
+    if (t->data[0] >= '5')
+        BUF_strlcpy(str, "19", newlen);
+    else
+        BUF_strlcpy(str, "20", newlen);
 
-	BUF_strlcat(str, (char *)t->data, newlen);
+    BUF_strlcat(str, (char *)t->data, newlen);
 
-	return ret;
-	}
+ done:
+   if (out != NULL && *out == NULL)
+       *out = ret;
+   return ret;
+
+ err:
+    if (out == NULL || *out != ret)
+        ASN1_GENERALIZEDTIME_free(ret);
+    return NULL;
+}
+
 
 int ASN1_TIME_set_string(ASN1_TIME *s, const char *str)
-	{
-	ASN1_TIME t;
+{
+    ASN1_TIME t;
 
-	t.length = strlen(str);
-	t.data = (unsigned char *)str;
-	t.flags = 0;
-	
-	t.type = V_ASN1_UTCTIME;
+    t.length = strlen(str);
+    t.data = (unsigned char *)str;
+    t.flags = 0;
 
-	if (!ASN1_TIME_check(&t))
-		{
-		t.type = V_ASN1_GENERALIZEDTIME;
-		if (!ASN1_TIME_check(&t))
-			return 0;
-		}
-	
-	if (s && !ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t))
-			return 0;
+    t.type = V_ASN1_UTCTIME;
 
-	return 1;
-	}
+    if (!ASN1_TIME_check(&t)) {
+        t.type = V_ASN1_GENERALIZEDTIME;
+        if (!ASN1_TIME_check(&t))
+            return 0;
+    }
+
+    if (s && !ASN1_STRING_copy((ASN1_STRING *)s, (ASN1_STRING *)&t))
+        return 0;
+
+    return 1;
+}
 
 static int asn1_time_to_tm(struct tm *tm, const ASN1_TIME *t)
-	{
-	if (t == NULL)
-		{
-		time_t now_t;
-		time(&now_t);
-		if (OPENSSL_gmtime(&now_t, tm))
-			return 1;
-		return 0;
-		}
-		
-	if (t->type == V_ASN1_UTCTIME)
-		return asn1_utctime_to_tm(tm, t);
-	else if (t->type == V_ASN1_GENERALIZEDTIME)
-		return asn1_generalizedtime_to_tm(tm, t);
+{
+    if (t == NULL) {
+        time_t now_t;
+        time(&now_t);
+        if (OPENSSL_gmtime(&now_t, tm))
+            return 1;
+        return 0;
+    }
 
-	return 0;
-	}
+    if (t->type == V_ASN1_UTCTIME)
+        return asn1_utctime_to_tm(tm, t);
+    else if (t->type == V_ASN1_GENERALIZEDTIME)
+        return asn1_generalizedtime_to_tm(tm, t);
+
+    return 0;
+}
 
 int ASN1_TIME_diff(int *pday, int *psec,
-			const ASN1_TIME *from, const ASN1_TIME *to)
-	{
-	struct tm tm_from, tm_to;
-	if (!asn1_time_to_tm(&tm_from, from))
-		return 0;
-	if (!asn1_time_to_tm(&tm_to, to))
-		return 0;
-	return OPENSSL_gmtime_diff(pday, psec, &tm_from, &tm_to);
-	}	
+                   const ASN1_TIME *from, const ASN1_TIME *to)
+{
+    struct tm tm_from, tm_to;
+    if (!asn1_time_to_tm(&tm_from, from))
+        return 0;
+    if (!asn1_time_to_tm(&tm_to, to))
+        return 0;
+    return OPENSSL_gmtime_diff(pday, psec, &tm_from, &tm_to);
+}
diff --git a/src/crypto/asn1/a_type.c b/src/crypto/asn1/a_type.c
index fd3d5b1..734ff8b 100644
--- a/src/crypto/asn1/a_type.c
+++ b/src/crypto/asn1/a_type.c
@@ -61,100 +61,91 @@
 #include <openssl/mem.h>
 #include <openssl/obj.h>
 
-
 int ASN1_TYPE_get(ASN1_TYPE *a)
-	{
-	if ((a->value.ptr != NULL) || (a->type == V_ASN1_NULL))
-		return(a->type);
-	else
-		return(0);
-	}
+{
+    if ((a->value.ptr != NULL) || (a->type == V_ASN1_NULL))
+        return (a->type);
+    else
+        return (0);
+}
 
 void ASN1_TYPE_set(ASN1_TYPE *a, int type, void *value)
-	{
-	if (a->value.ptr != NULL)
-		{
-		ASN1_TYPE **tmp_a = &a;
-		ASN1_primitive_free((ASN1_VALUE **)tmp_a, NULL);
-		}
-	a->type=type;
-	if (type == V_ASN1_BOOLEAN)
-		a->value.boolean = value ? 0xff : 0;
-	else
-		a->value.ptr=value;
-	}
+{
+    if (a->value.ptr != NULL) {
+        ASN1_TYPE **tmp_a = &a;
+        ASN1_primitive_free((ASN1_VALUE **)tmp_a, NULL);
+    }
+    a->type = type;
+    if (type == V_ASN1_BOOLEAN)
+        a->value.boolean = value ? 0xff : 0;
+    else
+        a->value.ptr = value;
+}
 
 int ASN1_TYPE_set1(ASN1_TYPE *a, int type, const void *value)
-	{
-	if (!value || (type == V_ASN1_BOOLEAN))
-		{
-		void *p = (void *)value;
-		ASN1_TYPE_set(a, type, p);
-		}
-	else if (type == V_ASN1_OBJECT)
-		{
-		ASN1_OBJECT *odup;
-		odup = OBJ_dup(value);
-		if (!odup)
-			return 0;
-		ASN1_TYPE_set(a, type, odup);
-		}
-	else
-		{
-		ASN1_STRING *sdup;
-		sdup = ASN1_STRING_dup(value);
-		if (!sdup)
-			return 0;
-		ASN1_TYPE_set(a, type, sdup);
-		}
-	return 1;
-	}
+{
+    if (!value || (type == V_ASN1_BOOLEAN)) {
+        void *p = (void *)value;
+        ASN1_TYPE_set(a, type, p);
+    } else if (type == V_ASN1_OBJECT) {
+        ASN1_OBJECT *odup;
+        odup = OBJ_dup(value);
+        if (!odup)
+            return 0;
+        ASN1_TYPE_set(a, type, odup);
+    } else {
+        ASN1_STRING *sdup;
+        sdup = ASN1_STRING_dup(value);
+        if (!sdup)
+            return 0;
+        ASN1_TYPE_set(a, type, sdup);
+    }
+    return 1;
+}
 
 /* Returns 0 if they are equal, != 0 otherwise. */
 int ASN1_TYPE_cmp(const ASN1_TYPE *a, const ASN1_TYPE *b)
-	{
-	int result = -1;
+{
+    int result = -1;
 
-	if (!a || !b || a->type != b->type) return -1;
+    if (!a || !b || a->type != b->type)
+        return -1;
 
-	switch (a->type)
-		{
-	case V_ASN1_OBJECT:
-		result = OBJ_cmp(a->value.object, b->value.object);
-		break;
-	case V_ASN1_NULL:
-		result = 0;	/* They do not have content. */
-		break;
-	case V_ASN1_BOOLEAN:
-		result = a->value.boolean - b->value.boolean;
-		break;
-	case V_ASN1_INTEGER:
-	case V_ASN1_NEG_INTEGER:
-	case V_ASN1_ENUMERATED:
-	case V_ASN1_NEG_ENUMERATED:
-	case V_ASN1_BIT_STRING:
-	case V_ASN1_OCTET_STRING:
-	case V_ASN1_SEQUENCE:
-	case V_ASN1_SET:
-	case V_ASN1_NUMERICSTRING:
-	case V_ASN1_PRINTABLESTRING:
-	case V_ASN1_T61STRING:
-	case V_ASN1_VIDEOTEXSTRING:
-	case V_ASN1_IA5STRING:
-	case V_ASN1_UTCTIME:
-	case V_ASN1_GENERALIZEDTIME:
-	case V_ASN1_GRAPHICSTRING:
-	case V_ASN1_VISIBLESTRING:
-	case V_ASN1_GENERALSTRING:
-	case V_ASN1_UNIVERSALSTRING:
-	case V_ASN1_BMPSTRING:
-	case V_ASN1_UTF8STRING:
-	case V_ASN1_OTHER:
-	default:
-		result = ASN1_STRING_cmp((ASN1_STRING *) a->value.ptr,
-					 (ASN1_STRING *) b->value.ptr);
-		break;
-		}
+    switch (a->type) {
+    case V_ASN1_OBJECT:
+        result = OBJ_cmp(a->value.object, b->value.object);
+        break;
+    case V_ASN1_NULL:
+        result = 0;             /* They do not have content. */
+        break;
+    case V_ASN1_BOOLEAN:
+        result = a->value.boolean - b->value.boolean;
+        break;
+    case V_ASN1_INTEGER:
+    case V_ASN1_ENUMERATED:
+    case V_ASN1_BIT_STRING:
+    case V_ASN1_OCTET_STRING:
+    case V_ASN1_SEQUENCE:
+    case V_ASN1_SET:
+    case V_ASN1_NUMERICSTRING:
+    case V_ASN1_PRINTABLESTRING:
+    case V_ASN1_T61STRING:
+    case V_ASN1_VIDEOTEXSTRING:
+    case V_ASN1_IA5STRING:
+    case V_ASN1_UTCTIME:
+    case V_ASN1_GENERALIZEDTIME:
+    case V_ASN1_GRAPHICSTRING:
+    case V_ASN1_VISIBLESTRING:
+    case V_ASN1_GENERALSTRING:
+    case V_ASN1_UNIVERSALSTRING:
+    case V_ASN1_BMPSTRING:
+    case V_ASN1_UTF8STRING:
+    case V_ASN1_OTHER:
+    default:
+        result = ASN1_STRING_cmp((ASN1_STRING *)a->value.ptr,
+                                 (ASN1_STRING *)b->value.ptr);
+        break;
+    }
 
-	return result;
-	}
+    return result;
+}
diff --git a/src/crypto/asn1/a_utctm.c b/src/crypto/asn1/a_utctm.c
index dbbbecb..193b83f 100644
--- a/src/crypto/asn1/a_utctm.c
+++ b/src/crypto/asn1/a_utctm.c
@@ -61,282 +61,243 @@
 
 #include <openssl/err.h>
 #include <openssl/mem.h>
-#include <openssl/time_support.h>
 
+#include "asn1_locl.h"
 
-#if 0
-int i2d_ASN1_UTCTIME(ASN1_UTCTIME *a, unsigned char **pp)
-	{
-	return(i2d_ASN1_bytes((ASN1_STRING *)a,pp,
-		V_ASN1_UTCTIME,V_ASN1_UNIVERSAL));
-	}
-
-
-ASN1_UTCTIME *d2i_ASN1_UTCTIME(ASN1_UTCTIME **a, unsigned char **pp,
-	     long length)
-	{
-	ASN1_UTCTIME *ret=NULL;
-
-	ret=(ASN1_UTCTIME *)d2i_ASN1_bytes((ASN1_STRING **)a,pp,length,
-		V_ASN1_UTCTIME,V_ASN1_UNIVERSAL);
-	if (ret == NULL)
-		{
-		OPENSSL_PUT_ERROR(ASN1, ERR_R_NESTED_ASN1_ERROR);
-		return(NULL);
-		}
-	if (!ASN1_UTCTIME_check(ret))
-		{
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_TIME_FORMAT);
-		goto err;
-		}
-
-	return(ret);
-err:
-	if ((ret != NULL) && ((a == NULL) || (*a != ret)))
-		M_ASN1_UTCTIME_free(ret);
-	return(NULL);
-	}
-
-#endif
 
 int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d)
-	{
-	static const int min[8]={ 0, 1, 1, 0, 0, 0, 0, 0};
-	static const int max[8]={99,12,31,23,59,59,12,59};
-	char *a;
-	int n,i,l,o;
+{
+    static const int min[8] = { 0, 1, 1, 0, 0, 0, 0, 0 };
+    static const int max[8] = { 99, 12, 31, 23, 59, 59, 12, 59 };
+    char *a;
+    int n, i, l, o;
 
-	if (d->type != V_ASN1_UTCTIME) return(0);
-	l=d->length;
-	a=(char *)d->data;
-	o=0;
+    if (d->type != V_ASN1_UTCTIME)
+        return (0);
+    l = d->length;
+    a = (char *)d->data;
+    o = 0;
 
-	if (l < 11) goto err;
-	for (i=0; i<6; i++)
-		{
-		if ((i == 5) && ((a[o] == 'Z') ||
-			(a[o] == '+') || (a[o] == '-')))
-			{
-			i++;
-			if (tm)
-				tm->tm_sec = 0;
-			break;
-			}
-		if ((a[o] < '0') || (a[o] > '9')) goto err;
-		n= a[o]-'0';
-		if (++o > l) goto err;
+    if (l < 11)
+        goto err;
+    for (i = 0; i < 6; i++) {
+        if ((i == 5) && ((a[o] == 'Z') || (a[o] == '+') || (a[o] == '-'))) {
+            i++;
+            if (tm)
+                tm->tm_sec = 0;
+            break;
+        }
+        if ((a[o] < '0') || (a[o] > '9'))
+            goto err;
+        n = a[o] - '0';
+        if (++o > l)
+            goto err;
 
-		if ((a[o] < '0') || (a[o] > '9')) goto err;
-		n=(n*10)+ a[o]-'0';
-		if (++o > l) goto err;
+        if ((a[o] < '0') || (a[o] > '9'))
+            goto err;
+        n = (n * 10) + a[o] - '0';
+        if (++o > l)
+            goto err;
 
-		if ((n < min[i]) || (n > max[i])) goto err;
-		if (tm)
-			{
-			switch(i)
-				{
-			case 0:
-				tm->tm_year = n < 50 ? n + 100 : n;
-				break;
-			case 1:
-				tm->tm_mon = n - 1;
-				break;
-			case 2:
-				tm->tm_mday = n;
-				break;
-			case 3:
-				tm->tm_hour = n;
-				break;
-			case 4:
-				tm->tm_min = n;
-				break;
-			case 5:
-				tm->tm_sec = n;
-				break;
-				}
-			}
-		}
-	if (a[o] == 'Z')
-		o++;
-	else if ((a[o] == '+') || (a[o] == '-'))
-		{
-		int offsign = a[o] == '-' ? -1 : 1, offset = 0;
-		o++;
-		if (o+4 > l) goto err;
-		for (i=6; i<8; i++)
-			{
-			if ((a[o] < '0') || (a[o] > '9')) goto err;
-			n= a[o]-'0';
-			o++;
-			if ((a[o] < '0') || (a[o] > '9')) goto err;
-			n=(n*10)+ a[o]-'0';
-			if ((n < min[i]) || (n > max[i])) goto err;
-			if (tm)
-				{
-				if (i == 6)
-					offset = n * 3600;
-				else if (i == 7)
-					offset += n * 60;
-				}
-			o++;
-			}
-		if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign))
-			return 0;
-		}
-	return o == l;
-err:
-	return 0;
-	}
+        if ((n < min[i]) || (n > max[i]))
+            goto err;
+        if (tm) {
+            switch (i) {
+            case 0:
+                tm->tm_year = n < 50 ? n + 100 : n;
+                break;
+            case 1:
+                tm->tm_mon = n - 1;
+                break;
+            case 2:
+                tm->tm_mday = n;
+                break;
+            case 3:
+                tm->tm_hour = n;
+                break;
+            case 4:
+                tm->tm_min = n;
+                break;
+            case 5:
+                tm->tm_sec = n;
+                break;
+            }
+        }
+    }
+    if (a[o] == 'Z')
+        o++;
+    else if ((a[o] == '+') || (a[o] == '-')) {
+        int offsign = a[o] == '-' ? -1 : 1, offset = 0;
+        o++;
+        if (o + 4 > l)
+            goto err;
+        for (i = 6; i < 8; i++) {
+            if ((a[o] < '0') || (a[o] > '9'))
+                goto err;
+            n = a[o] - '0';
+            o++;
+            if ((a[o] < '0') || (a[o] > '9'))
+                goto err;
+            n = (n * 10) + a[o] - '0';
+            if ((n < min[i]) || (n > max[i]))
+                goto err;
+            if (tm) {
+                if (i == 6)
+                    offset = n * 3600;
+                else if (i == 7)
+                    offset += n * 60;
+            }
+            o++;
+        }
+        if (offset && !OPENSSL_gmtime_adj(tm, 0, offset * offsign))
+            return 0;
+    }
+    return o == l;
+ err:
+    return 0;
+}
 
 int ASN1_UTCTIME_check(const ASN1_UTCTIME *d)
-	{
-	return asn1_utctime_to_tm(NULL, d);
-	}
+{
+    return asn1_utctime_to_tm(NULL, d);
+}
 
 int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str)
-	{
-	ASN1_UTCTIME t;
+{
+    ASN1_UTCTIME t;
 
-	t.type=V_ASN1_UTCTIME;
-	t.length=strlen(str);
-	t.data=(unsigned char *)str;
-	if (ASN1_UTCTIME_check(&t))
-		{
-		if (s != NULL)
-			{
-			if (!ASN1_STRING_set((ASN1_STRING *)s,
-				(unsigned char *)str,t.length))
-				return 0;
-			s->type = V_ASN1_UTCTIME;
-			}
-		return(1);
-		}
-	else
-		return(0);
-	}
+    t.type = V_ASN1_UTCTIME;
+    t.length = strlen(str);
+    t.data = (unsigned char *)str;
+    if (ASN1_UTCTIME_check(&t)) {
+        if (s != NULL) {
+            if (!ASN1_STRING_set((ASN1_STRING *)s,
+                                 (unsigned char *)str, t.length))
+                return 0;
+            s->type = V_ASN1_UTCTIME;
+        }
+        return (1);
+    } else
+        return (0);
+}
 
 ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t)
-	{
-	return ASN1_UTCTIME_adj(s, t, 0, 0);
-	}
+{
+    return ASN1_UTCTIME_adj(s, t, 0, 0);
+}
 
 ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t,
-				int offset_day, long offset_sec)
-	{
-	char *p;
-	struct tm *ts;
-	struct tm data;
-	size_t len = 20;
-	int free_s = 0;
+                               int offset_day, long offset_sec)
+{
+    char *p;
+    struct tm *ts;
+    struct tm data;
+    size_t len = 20;
+    int free_s = 0;
 
-	if (s == NULL)
-		{
-		free_s = 1;
-		s=M_ASN1_UTCTIME_new();
-		}
-	if (s == NULL)
-		goto err;
+    if (s == NULL) {
+        free_s = 1;
+        s = M_ASN1_UTCTIME_new();
+    }
+    if (s == NULL)
+        goto err;
 
+    ts = OPENSSL_gmtime(&t, &data);
+    if (ts == NULL)
+        goto err;
 
-	ts=OPENSSL_gmtime(&t, &data);
-	if (ts == NULL)
-		goto err;
+    if (offset_day || offset_sec) {
+        if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
+            goto err;
+    }
 
-	if (offset_day || offset_sec)
-		{ 
-		if (!OPENSSL_gmtime_adj(ts, offset_day, offset_sec))
-			goto err;
-		}
+    if ((ts->tm_year < 50) || (ts->tm_year >= 150))
+        goto err;
 
-	if((ts->tm_year < 50) || (ts->tm_year >= 150))
-		goto err;
+    p = (char *)s->data;
+    if ((p == NULL) || ((size_t)s->length < len)) {
+        p = OPENSSL_malloc(len);
+        if (p == NULL) {
+            OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+            goto err;
+        }
+        if (s->data != NULL)
+            OPENSSL_free(s->data);
+        s->data = (unsigned char *)p;
+    }
 
-	p=(char *)s->data;
-	if ((p == NULL) || ((size_t)s->length < len))
-		{
-		p=OPENSSL_malloc(len);
-		if (p == NULL)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-			goto err;
-			}
-		if (s->data != NULL)
-			OPENSSL_free(s->data);
-		s->data=(unsigned char *)p;
-		}
-
-	BIO_snprintf(p,len,"%02d%02d%02d%02d%02d%02dZ",ts->tm_year%100,
-		     ts->tm_mon+1,ts->tm_mday,ts->tm_hour,ts->tm_min,ts->tm_sec);
-	s->length=strlen(p);
-	s->type=V_ASN1_UTCTIME;
-	return(s);
-	err:
-	if (free_s && s)
-		M_ASN1_UTCTIME_free(s);
-	return NULL;
-	}
-
+    BIO_snprintf(p, len, "%02d%02d%02d%02d%02d%02dZ", ts->tm_year % 100,
+                 ts->tm_mon + 1, ts->tm_mday, ts->tm_hour, ts->tm_min,
+                 ts->tm_sec);
+    s->length = strlen(p);
+    s->type = V_ASN1_UTCTIME;
+    return (s);
+ err:
+    if (free_s && s)
+        M_ASN1_UTCTIME_free(s);
+    return NULL;
+}
 
 int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t)
-	{
-	struct tm stm, ttm;
-	int day, sec;
+{
+    struct tm stm, ttm;
+    int day, sec;
 
-	if (!asn1_utctime_to_tm(&stm, s))
-		return -2;
+    if (!asn1_utctime_to_tm(&stm, s))
+        return -2;
 
-	if (!OPENSSL_gmtime(&t, &ttm))
-		return -2;
+    if (!OPENSSL_gmtime(&t, &ttm))
+        return -2;
 
-	if (!OPENSSL_gmtime_diff(&day, &sec, &ttm, &stm))
-		return -2;
+    if (!OPENSSL_gmtime_diff(&day, &sec, &ttm, &stm))
+        return -2;
 
-	if (day > 0)
-		return 1;
-	if (day < 0)
-		return -1;
-	if (sec > 0)
-		return 1;
-	if (sec < 0)
-		return -1;
-	return 0;
-	}
-
+    if (day > 0)
+        return 1;
+    if (day < 0)
+        return -1;
+    if (sec > 0)
+        return 1;
+    if (sec < 0)
+        return -1;
+    return 0;
+}
 
 #if 0
 time_t ASN1_UTCTIME_get(const ASN1_UTCTIME *s)
-	{
-	struct tm tm;
-	int offset;
+{
+    struct tm tm;
+    int offset;
 
-	memset(&tm,'\0',sizeof tm);
+    OPENSSL_memset(&tm, '\0', sizeof tm);
 
-#define g2(p) (((p)[0]-'0')*10+(p)[1]-'0')
-	tm.tm_year=g2(s->data);
-	if(tm.tm_year < 50)
-		tm.tm_year+=100;
-	tm.tm_mon=g2(s->data+2)-1;
-	tm.tm_mday=g2(s->data+4);
-	tm.tm_hour=g2(s->data+6);
-	tm.tm_min=g2(s->data+8);
-	tm.tm_sec=g2(s->data+10);
-	if(s->data[12] == 'Z')
-		offset=0;
-	else
-		{
-		offset=g2(s->data+13)*60+g2(s->data+15);
-		if(s->data[12] == '-')
-			offset= -offset;
-		}
-#undef g2
+# define g2(p) (((p)[0]-'0')*10+(p)[1]-'0')
+    tm.tm_year = g2(s->data);
+    if (tm.tm_year < 50)
+        tm.tm_year += 100;
+    tm.tm_mon = g2(s->data + 2) - 1;
+    tm.tm_mday = g2(s->data + 4);
+    tm.tm_hour = g2(s->data + 6);
+    tm.tm_min = g2(s->data + 8);
+    tm.tm_sec = g2(s->data + 10);
+    if (s->data[12] == 'Z')
+        offset = 0;
+    else {
+        offset = g2(s->data + 13) * 60 + g2(s->data + 15);
+        if (s->data[12] == '-')
+            offset = -offset;
+    }
+# undef g2
 
-	return mktime(&tm)-offset*60; /* FIXME: mktime assumes the current timezone
-	                               * instead of UTC, and unless we rewrite OpenSSL
-				       * in Lisp we cannot locally change the timezone
-				       * without possibly interfering with other parts
-	                               * of the program. timegm, which uses UTC, is
-				       * non-standard.
-	                               * Also time_t is inappropriate for general
-	                               * UTC times because it may a 32 bit type. */
-	}
+    return mktime(&tm) - offset * 60; /* FIXME: mktime assumes the current
+                                       * timezone instead of UTC, and unless
+                                       * we rewrite OpenSSL in Lisp we cannot
+                                       * locally change the timezone without
+                                       * possibly interfering with other
+                                       * parts of the program. timegm, which
+                                       * uses UTC, is non-standard. Also
+                                       * time_t is inappropriate for general
+                                       * UTC times because it may a 32 bit
+                                       * type. */
+}
 #endif
diff --git a/src/crypto/asn1/a_utf8.c b/src/crypto/asn1/a_utf8.c
index ed6e98d..1702768 100644
--- a/src/crypto/asn1/a_utf8.c
+++ b/src/crypto/asn1/a_utf8.c
@@ -59,152 +59,176 @@
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
-
 /* UTF8 utilities */
 
-/* This parses a UTF8 string one character at a time. It is passed a pointer
- * to the string and the length of the string. It sets 'value' to the value of
- * the current character. It returns the number of characters read or a
- * negative error code:
- * -1 = string too short
- * -2 = illegal character
- * -3 = subsequent characters not of the form 10xxxxxx
- * -4 = character encoded incorrectly (not minimal length).
+/*
+ * This parses a UTF8 string one character at a time. It is passed a pointer
+ * to the string and the length of the string. It sets 'value' to the value
+ * of the current character. It returns the number of characters read or a
+ * negative error code: -1 = string too short -2 = illegal character -3 =
+ * subsequent characters not of the form 10xxxxxx -4 = character encoded
+ * incorrectly (not minimal length).
  */
 
 int UTF8_getc(const unsigned char *str, int len, unsigned long *val)
 {
-	const unsigned char *p;
-	unsigned long value;
-	int ret;
-	if(len <= 0) return 0;
-	p = str;
+    const unsigned char *p;
+    unsigned long value;
+    int ret;
+    if (len <= 0)
+        return 0;
+    p = str;
 
-	/* Check syntax and work out the encoded value (if correct) */
-	if((*p & 0x80) == 0) {
-		value = *p++ & 0x7f;
-		ret = 1;
-	} else if((*p & 0xe0) == 0xc0) {
-		if(len < 2) return -1;
-		if((p[1] & 0xc0) != 0x80) return -3;
-		value = (*p++ & 0x1f) << 6;
-		value |= *p++ & 0x3f;
-		if(value < 0x80) return -4;
-		ret = 2;
-	} else if((*p & 0xf0) == 0xe0) {
-		if(len < 3) return -1;
-		if( ((p[1] & 0xc0) != 0x80)
-		   || ((p[2] & 0xc0) != 0x80) ) return -3;
-		value = (*p++ & 0xf) << 12;
-		value |= (*p++ & 0x3f) << 6;
-		value |= *p++ & 0x3f;
-		if(value < 0x800) return -4;
-		ret = 3;
-	} else if((*p & 0xf8) == 0xf0) {
-		if(len < 4) return -1;
-		if( ((p[1] & 0xc0) != 0x80)
-		   || ((p[2] & 0xc0) != 0x80) 
-		   || ((p[3] & 0xc0) != 0x80) ) return -3;
-		value = ((unsigned long)(*p++ & 0x7)) << 18;
-		value |= (*p++ & 0x3f) << 12;
-		value |= (*p++ & 0x3f) << 6;
-		value |= *p++ & 0x3f;
-		if(value < 0x10000) return -4;
-		ret = 4;
-	} else if((*p & 0xfc) == 0xf8) {
-		if(len < 5) return -1;
-		if( ((p[1] & 0xc0) != 0x80)
-		   || ((p[2] & 0xc0) != 0x80) 
-		   || ((p[3] & 0xc0) != 0x80) 
-		   || ((p[4] & 0xc0) != 0x80) ) return -3;
-		value = ((unsigned long)(*p++ & 0x3)) << 24;
-		value |= ((unsigned long)(*p++ & 0x3f)) << 18;
-		value |= ((unsigned long)(*p++ & 0x3f)) << 12;
-		value |= (*p++ & 0x3f) << 6;
-		value |= *p++ & 0x3f;
-		if(value < 0x200000) return -4;
-		ret = 5;
-	} else if((*p & 0xfe) == 0xfc) {
-		if(len < 6) return -1;
-		if( ((p[1] & 0xc0) != 0x80)
-		   || ((p[2] & 0xc0) != 0x80) 
-		   || ((p[3] & 0xc0) != 0x80) 
-		   || ((p[4] & 0xc0) != 0x80) 
-		   || ((p[5] & 0xc0) != 0x80) ) return -3;
-		value = ((unsigned long)(*p++ & 0x1)) << 30;
-		value |= ((unsigned long)(*p++ & 0x3f)) << 24;
-		value |= ((unsigned long)(*p++ & 0x3f)) << 18;
-		value |= ((unsigned long)(*p++ & 0x3f)) << 12;
-		value |= (*p++ & 0x3f) << 6;
-		value |= *p++ & 0x3f;
-		if(value < 0x4000000) return -4;
-		ret = 6;
-	} else return -2;
-	*val = value;
-	return ret;
+    /* Check syntax and work out the encoded value (if correct) */
+    if ((*p & 0x80) == 0) {
+        value = *p++ & 0x7f;
+        ret = 1;
+    } else if ((*p & 0xe0) == 0xc0) {
+        if (len < 2)
+            return -1;
+        if ((p[1] & 0xc0) != 0x80)
+            return -3;
+        value = (*p++ & 0x1f) << 6;
+        value |= *p++ & 0x3f;
+        if (value < 0x80)
+            return -4;
+        ret = 2;
+    } else if ((*p & 0xf0) == 0xe0) {
+        if (len < 3)
+            return -1;
+        if (((p[1] & 0xc0) != 0x80)
+            || ((p[2] & 0xc0) != 0x80))
+            return -3;
+        value = (*p++ & 0xf) << 12;
+        value |= (*p++ & 0x3f) << 6;
+        value |= *p++ & 0x3f;
+        if (value < 0x800)
+            return -4;
+        ret = 3;
+    } else if ((*p & 0xf8) == 0xf0) {
+        if (len < 4)
+            return -1;
+        if (((p[1] & 0xc0) != 0x80)
+            || ((p[2] & 0xc0) != 0x80)
+            || ((p[3] & 0xc0) != 0x80))
+            return -3;
+        value = ((unsigned long)(*p++ & 0x7)) << 18;
+        value |= (*p++ & 0x3f) << 12;
+        value |= (*p++ & 0x3f) << 6;
+        value |= *p++ & 0x3f;
+        if (value < 0x10000)
+            return -4;
+        ret = 4;
+    } else if ((*p & 0xfc) == 0xf8) {
+        if (len < 5)
+            return -1;
+        if (((p[1] & 0xc0) != 0x80)
+            || ((p[2] & 0xc0) != 0x80)
+            || ((p[3] & 0xc0) != 0x80)
+            || ((p[4] & 0xc0) != 0x80))
+            return -3;
+        value = ((unsigned long)(*p++ & 0x3)) << 24;
+        value |= ((unsigned long)(*p++ & 0x3f)) << 18;
+        value |= ((unsigned long)(*p++ & 0x3f)) << 12;
+        value |= (*p++ & 0x3f) << 6;
+        value |= *p++ & 0x3f;
+        if (value < 0x200000)
+            return -4;
+        ret = 5;
+    } else if ((*p & 0xfe) == 0xfc) {
+        if (len < 6)
+            return -1;
+        if (((p[1] & 0xc0) != 0x80)
+            || ((p[2] & 0xc0) != 0x80)
+            || ((p[3] & 0xc0) != 0x80)
+            || ((p[4] & 0xc0) != 0x80)
+            || ((p[5] & 0xc0) != 0x80))
+            return -3;
+        value = ((unsigned long)(*p++ & 0x1)) << 30;
+        value |= ((unsigned long)(*p++ & 0x3f)) << 24;
+        value |= ((unsigned long)(*p++ & 0x3f)) << 18;
+        value |= ((unsigned long)(*p++ & 0x3f)) << 12;
+        value |= (*p++ & 0x3f) << 6;
+        value |= *p++ & 0x3f;
+        if (value < 0x4000000)
+            return -4;
+        ret = 6;
+    } else
+        return -2;
+    *val = value;
+    return ret;
 }
 
-/* This takes a character 'value' and writes the UTF8 encoded value in
- * 'str' where 'str' is a buffer containing 'len' characters. Returns
- * the number of characters written or -1 if 'len' is too small. 'str' can
- * be set to NULL in which case it just returns the number of characters.
- * It will need at most 6 characters.
+/*
+ * This takes a character 'value' and writes the UTF8 encoded value in 'str'
+ * where 'str' is a buffer containing 'len' characters. Returns the number of
+ * characters written or -1 if 'len' is too small. 'str' can be set to NULL
+ * in which case it just returns the number of characters. It will need at
+ * most 6 characters.
  */
 
 int UTF8_putc(unsigned char *str, int len, unsigned long value)
 {
-	if(!str) len = 6;	/* Maximum we will need */
-	else if(len <= 0) return -1;
-	if(value < 0x80) {
-		if(str) *str = (unsigned char)value;
-		return 1;
-	}
-	if(value < 0x800) {
-		if(len < 2) return -1;
-		if(str) {
-			*str++ = (unsigned char)(((value >> 6) & 0x1f) | 0xc0);
-			*str = (unsigned char)((value & 0x3f) | 0x80);
-		}
-		return 2;
-	}
-	if(value < 0x10000) {
-		if(len < 3) return -1;
-		if(str) {
-			*str++ = (unsigned char)(((value >> 12) & 0xf) | 0xe0);
-			*str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
-			*str = (unsigned char)((value & 0x3f) | 0x80);
-		}
-		return 3;
-	}
-	if(value < 0x200000) {
-		if(len < 4) return -1;
-		if(str) {
-			*str++ = (unsigned char)(((value >> 18) & 0x7) | 0xf0);
-			*str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
-			*str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
-			*str = (unsigned char)((value & 0x3f) | 0x80);
-		}
-		return 4;
-	}
-	if(value < 0x4000000) {
-		if(len < 5) return -1;
-		if(str) {
-			*str++ = (unsigned char)(((value >> 24) & 0x3) | 0xf8);
-			*str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80);
-			*str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
-			*str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
-			*str = (unsigned char)((value & 0x3f) | 0x80);
-		}
-		return 5;
-	}
-	if(len < 6) return -1;
-	if(str) {
-		*str++ = (unsigned char)(((value >> 30) & 0x1) | 0xfc);
-		*str++ = (unsigned char)(((value >> 24) & 0x3f) | 0x80);
-		*str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80);
-		*str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
-		*str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
-		*str = (unsigned char)((value & 0x3f) | 0x80);
-	}
-	return 6;
+    if (!str)
+        len = 6;                /* Maximum we will need */
+    else if (len <= 0)
+        return -1;
+    if (value < 0x80) {
+        if (str)
+            *str = (unsigned char)value;
+        return 1;
+    }
+    if (value < 0x800) {
+        if (len < 2)
+            return -1;
+        if (str) {
+            *str++ = (unsigned char)(((value >> 6) & 0x1f) | 0xc0);
+            *str = (unsigned char)((value & 0x3f) | 0x80);
+        }
+        return 2;
+    }
+    if (value < 0x10000) {
+        if (len < 3)
+            return -1;
+        if (str) {
+            *str++ = (unsigned char)(((value >> 12) & 0xf) | 0xe0);
+            *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
+            *str = (unsigned char)((value & 0x3f) | 0x80);
+        }
+        return 3;
+    }
+    if (value < 0x200000) {
+        if (len < 4)
+            return -1;
+        if (str) {
+            *str++ = (unsigned char)(((value >> 18) & 0x7) | 0xf0);
+            *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
+            *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
+            *str = (unsigned char)((value & 0x3f) | 0x80);
+        }
+        return 4;
+    }
+    if (value < 0x4000000) {
+        if (len < 5)
+            return -1;
+        if (str) {
+            *str++ = (unsigned char)(((value >> 24) & 0x3) | 0xf8);
+            *str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80);
+            *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
+            *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
+            *str = (unsigned char)((value & 0x3f) | 0x80);
+        }
+        return 5;
+    }
+    if (len < 6)
+        return -1;
+    if (str) {
+        *str++ = (unsigned char)(((value >> 30) & 0x1) | 0xfc);
+        *str++ = (unsigned char)(((value >> 24) & 0x3f) | 0x80);
+        *str++ = (unsigned char)(((value >> 18) & 0x3f) | 0x80);
+        *str++ = (unsigned char)(((value >> 12) & 0x3f) | 0x80);
+        *str++ = (unsigned char)(((value >> 6) & 0x3f) | 0x80);
+        *str = (unsigned char)((value & 0x3f) | 0x80);
+    }
+    return 6;
 }
diff --git a/src/crypto/asn1/asn1_lib.c b/src/crypto/asn1/asn1_lib.c
index 0f2ce50..774f151 100644
--- a/src/crypto/asn1/asn1_lib.c
+++ b/src/crypto/asn1/asn1_lib.c
@@ -63,444 +63,424 @@
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
+#include "../internal.h"
 
-/* Cross-module errors from crypto/x509/i2d_pr.c */
-OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_PUBLIC_KEY_TYPE);
 
-/* Cross-module errors from crypto/x509/asn1_gen.c.
- * TODO(davidben): Remove these once asn1_gen.c is gone. */
-OPENSSL_DECLARE_ERROR_REASON(ASN1, DEPTH_EXCEEDED);
-OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BITSTRING_FORMAT);
-OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BOOLEAN);
-OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_FORMAT);
-OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_HEX);
-OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_IMPLICIT_TAG);
-OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_INTEGER);
-OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_NESTED_TAGGING);
-OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_NULL_VALUE);
-OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_OBJECT);
-OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_TIME_VALUE);
-OPENSSL_DECLARE_ERROR_REASON(ASN1, INTEGER_NOT_ASCII_FORMAT);
-OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_MODIFIER);
-OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_NUMBER);
-OPENSSL_DECLARE_ERROR_REASON(ASN1, LIST_ERROR);
-OPENSSL_DECLARE_ERROR_REASON(ASN1, MISSING_VALUE);
-OPENSSL_DECLARE_ERROR_REASON(ASN1, NOT_ASCII_FORMAT);
-OPENSSL_DECLARE_ERROR_REASON(ASN1, OBJECT_NOT_ASCII_FORMAT);
-OPENSSL_DECLARE_ERROR_REASON(ASN1, SEQUENCE_OR_SET_NEEDS_CONFIG);
-OPENSSL_DECLARE_ERROR_REASON(ASN1, TIME_NOT_ASCII_FORMAT);
-OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_FORMAT);
-OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_TAG);
-OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_TYPE);
+/* Cross-module errors from crypto/x509/i2d_pr.c. */
+OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_PUBLIC_KEY_TYPE)
 
-static int asn1_get_length(const unsigned char **pp,int *inf,long *rl,int max);
+/* Cross-module errors from crypto/x509/algorithm.c. */
+OPENSSL_DECLARE_ERROR_REASON(ASN1, CONTEXT_NOT_INITIALISED)
+OPENSSL_DECLARE_ERROR_REASON(ASN1, DIGEST_AND_KEY_TYPE_NOT_SUPPORTED)
+OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_MESSAGE_DIGEST_ALGORITHM)
+OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_SIGNATURE_ALGORITHM)
+OPENSSL_DECLARE_ERROR_REASON(ASN1, WRONG_PUBLIC_KEY_TYPE)
+/*
+ * Cross-module errors from crypto/x509/asn1_gen.c. TODO(davidben): Remove
+ * these once asn1_gen.c is gone.
+ */
+OPENSSL_DECLARE_ERROR_REASON(ASN1, DEPTH_EXCEEDED)
+OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BITSTRING_FORMAT)
+OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BOOLEAN)
+OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_FORMAT)
+OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_HEX)
+OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_IMPLICIT_TAG)
+OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_INTEGER)
+OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_NESTED_TAGGING)
+OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_NULL_VALUE)
+OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_OBJECT)
+OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_TIME_VALUE)
+OPENSSL_DECLARE_ERROR_REASON(ASN1, INTEGER_NOT_ASCII_FORMAT)
+OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_MODIFIER)
+OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_NUMBER)
+OPENSSL_DECLARE_ERROR_REASON(ASN1, LIST_ERROR)
+OPENSSL_DECLARE_ERROR_REASON(ASN1, MISSING_VALUE)
+OPENSSL_DECLARE_ERROR_REASON(ASN1, NOT_ASCII_FORMAT)
+OPENSSL_DECLARE_ERROR_REASON(ASN1, OBJECT_NOT_ASCII_FORMAT)
+OPENSSL_DECLARE_ERROR_REASON(ASN1, SEQUENCE_OR_SET_NEEDS_CONFIG)
+OPENSSL_DECLARE_ERROR_REASON(ASN1, TIME_NOT_ASCII_FORMAT)
+OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_FORMAT)
+OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_TAG)
+OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_TYPE)
+
+static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
+                           long max);
 static void asn1_put_length(unsigned char **pp, int length);
 
 static int _asn1_check_infinite_end(const unsigned char **p, long len)
-	{
-	/* If there is 0 or 1 byte left, the length check should pick
-	 * things up */
-	if (len <= 0)
-		return(1);
-	else if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0))
-		{
-		(*p)+=2;
-		return(1);
-		}
-	return(0);
-	}
+{
+    /*
+     * If there is 0 or 1 byte left, the length check should pick things up
+     */
+    if (len <= 0)
+        return (1);
+    else if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0)) {
+        (*p) += 2;
+        return (1);
+    }
+    return (0);
+}
 
 int ASN1_check_infinite_end(unsigned char **p, long len)
-	{
-	return _asn1_check_infinite_end((const unsigned char **)p, len);
-	}
+{
+    return _asn1_check_infinite_end((const unsigned char **)p, len);
+}
 
 int ASN1_const_check_infinite_end(const unsigned char **p, long len)
-	{
-	return _asn1_check_infinite_end(p, len);
-	}
-
+{
+    return _asn1_check_infinite_end(p, len);
+}
 
 int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
-	int *pclass, long omax)
-	{
-	int i,ret;
-	long l;
-	const unsigned char *p= *pp;
-	int tag,xclass,inf;
-	long max=omax;
+                    int *pclass, long omax)
+{
+    int i, ret;
+    long l;
+    const unsigned char *p = *pp;
+    int tag, xclass, inf;
+    long max = omax;
 
-	if (!max) goto err;
-	ret=(*p&V_ASN1_CONSTRUCTED);
-	xclass=(*p&V_ASN1_PRIVATE);
-	i= *p&V_ASN1_PRIMITIVE_TAG;
-	if (i == V_ASN1_PRIMITIVE_TAG)
-		{		/* high-tag */
-		p++;
-		if (--max == 0) goto err;
-		l=0;
-		while (*p&0x80)
-			{
-			l<<=7L;
-			l|= *(p++)&0x7f;
-			if (--max == 0) goto err;
-			if (l > (INT_MAX >> 7L)) goto err;
-			}
-		l<<=7L;
-		l|= *(p++)&0x7f;
-		tag=(int)l;
-		if (--max == 0) goto err;
-		}
-	else
-		{ 
-		tag=i;
-		p++;
-		if (--max == 0) goto err;
-		}
-	*ptag=tag;
-	*pclass=xclass;
-	if (!asn1_get_length(&p,&inf,plength,(int)max)) goto err;
+    if (!max)
+        goto err;
+    ret = (*p & V_ASN1_CONSTRUCTED);
+    xclass = (*p & V_ASN1_PRIVATE);
+    i = *p & V_ASN1_PRIMITIVE_TAG;
+    if (i == V_ASN1_PRIMITIVE_TAG) { /* high-tag */
+        p++;
+        if (--max == 0)
+            goto err;
+        l = 0;
+        while (*p & 0x80) {
+            l <<= 7L;
+            l |= *(p++) & 0x7f;
+            if (--max == 0)
+                goto err;
+            if (l > (INT_MAX >> 7L))
+                goto err;
+        }
+        l <<= 7L;
+        l |= *(p++) & 0x7f;
+        tag = (int)l;
+        if (--max == 0)
+            goto err;
+    } else {
+        tag = i;
+        p++;
+        if (--max == 0)
+            goto err;
+    }
 
-	if (inf && !(ret & V_ASN1_CONSTRUCTED))
-		goto err;
+    /* To avoid ambiguity with V_ASN1_NEG, impose a limit on universal tags. */
+    if (xclass == V_ASN1_UNIVERSAL && tag > V_ASN1_MAX_UNIVERSAL)
+        goto err;
+
+    *ptag = tag;
+    *pclass = xclass;
+    if (!asn1_get_length(&p, &inf, plength, max))
+        goto err;
+
+    if (inf && !(ret & V_ASN1_CONSTRUCTED))
+        goto err;
 
 #if 0
-	fprintf(stderr,"p=%d + *plength=%ld > omax=%ld + *pp=%d  (%d > %d)\n", 
-		(int)p,*plength,omax,(int)*pp,(int)(p+ *plength),
-		(int)(omax+ *pp));
+    fprintf(stderr, "p=%d + *plength=%ld > omax=%ld + *pp=%d  (%d > %d)\n",
+            (int)p, *plength, omax, (int)*pp, (int)(p + *plength),
+            (int)(omax + *pp));
 
 #endif
-	if (*plength > (omax - (p - *pp)))
-		{
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
-		/* Set this so that even if things are not long enough
-		 * the values are set correctly */
-		ret|=0x80;
-		}
-	*pp=p;
-	return(ret|inf);
-err:
-	OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG);
-	return(0x80);
-	}
+    if (*plength > (omax - (p - *pp))) {
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
+        /*
+         * Set this so that even if things are not long enough the values are
+         * set correctly
+         */
+        ret |= 0x80;
+    }
+    *pp = p;
+    return (ret | inf);
+ err:
+    OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG);
+    return (0x80);
+}
 
-static int asn1_get_length(const unsigned char **pp, int *inf, long *rl, int max)
-	{
-	const unsigned char *p= *pp;
-	unsigned long ret=0;
-	unsigned int i;
+static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
+                           long max)
+{
+    const unsigned char *p = *pp;
+    unsigned long ret = 0;
+    unsigned long i;
 
-	if (max-- < 1) return(0);
-	if (*p == 0x80)
-		{
-		*inf=1;
-		ret=0;
-		p++;
-		}
-	else
-		{
-		*inf=0;
-		i= *p&0x7f;
-		if (*(p++) & 0x80)
-			{
-			if (i > sizeof(long))
-				return 0;
-			if (max-- == 0) return(0);
-			while (i-- > 0)
-				{
-				ret<<=8L;
-				ret|= *(p++);
-				if (max-- == 0) return(0);
-				}
-			}
-		else
-			ret=i;
-		}
-	if (ret > LONG_MAX)
-		return 0;
-	*pp=p;
-	*rl=(long)ret;
-	return(1);
-	}
+    if (max-- < 1)
+        return 0;
+    if (*p == 0x80) {
+        *inf = 1;
+        ret = 0;
+        p++;
+    } else {
+        *inf = 0;
+        i = *p & 0x7f;
+        if (*(p++) & 0x80) {
+            if (i > sizeof(ret) || max < (long)i)
+                return 0;
+            while (i-- > 0) {
+                ret <<= 8L;
+                ret |= *(p++);
+            }
+        } else
+            ret = i;
+    }
+    if (ret > LONG_MAX)
+        return 0;
+    *pp = p;
+    *rl = (long)ret;
+    return 1;
+}
 
-/* class 0 is constructed
- * constructed == 2 for indefinite length constructed */
+/*
+ * class 0 is constructed constructed == 2 for indefinite length constructed
+ */
 void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag,
-	     int xclass)
-	{
-	unsigned char *p= *pp;
-	int i, ttag;
+                     int xclass)
+{
+    unsigned char *p = *pp;
+    int i, ttag;
 
-	i=(constructed)?V_ASN1_CONSTRUCTED:0;
-	i|=(xclass&V_ASN1_PRIVATE);
-	if (tag < 31)
-		*(p++)=i|(tag&V_ASN1_PRIMITIVE_TAG);
-	else
-		{
-		*(p++)=i|V_ASN1_PRIMITIVE_TAG;
-		for(i = 0, ttag = tag; ttag > 0; i++) ttag >>=7;
-		ttag = i;
-		while(i-- > 0)
-			{
-			p[i] = tag & 0x7f;
-			if(i != (ttag - 1)) p[i] |= 0x80;
-			tag >>= 7;
-			}
-		p += ttag;
-		}
-	if (constructed == 2)
-		*(p++)=0x80;
-	else
-		asn1_put_length(&p,length);
-	*pp=p;
-	}
+    i = (constructed) ? V_ASN1_CONSTRUCTED : 0;
+    i |= (xclass & V_ASN1_PRIVATE);
+    if (tag < 31)
+        *(p++) = i | (tag & V_ASN1_PRIMITIVE_TAG);
+    else {
+        *(p++) = i | V_ASN1_PRIMITIVE_TAG;
+        for (i = 0, ttag = tag; ttag > 0; i++)
+            ttag >>= 7;
+        ttag = i;
+        while (i-- > 0) {
+            p[i] = tag & 0x7f;
+            if (i != (ttag - 1))
+                p[i] |= 0x80;
+            tag >>= 7;
+        }
+        p += ttag;
+    }
+    if (constructed == 2)
+        *(p++) = 0x80;
+    else
+        asn1_put_length(&p, length);
+    *pp = p;
+}
 
 int ASN1_put_eoc(unsigned char **pp)
-	{
-	unsigned char *p = *pp;
-	*p++ = 0;
-	*p++ = 0;
-	*pp = p;
-	return 2;
-	}
+{
+    unsigned char *p = *pp;
+    *p++ = 0;
+    *p++ = 0;
+    *pp = p;
+    return 2;
+}
 
 static void asn1_put_length(unsigned char **pp, int length)
-	{
-	unsigned char *p= *pp;
-	int i,l;
-	if (length <= 127)
-		*(p++)=(unsigned char)length;
-	else
-		{
-		l=length;
-		for (i=0; l > 0; i++)
-			l>>=8;
-		*(p++)=i|0x80;
-		l=i;
-		while (i-- > 0)
-			{
-			p[i]=length&0xff;
-			length>>=8;
-			}
-		p+=l;
-		}
-	*pp=p;
-	}
+{
+    unsigned char *p = *pp;
+    int i, l;
+    if (length <= 127)
+        *(p++) = (unsigned char)length;
+    else {
+        l = length;
+        for (i = 0; l > 0; i++)
+            l >>= 8;
+        *(p++) = i | 0x80;
+        l = i;
+        while (i-- > 0) {
+            p[i] = length & 0xff;
+            length >>= 8;
+        }
+        p += l;
+    }
+    *pp = p;
+}
 
 int ASN1_object_size(int constructed, int length, int tag)
-	{
-	int ret;
-
-	ret=length;
-	ret++;
-	if (tag >= 31)
-		{
-		while (tag > 0)
-			{
-			tag>>=7;
-			ret++;
-			}
-		}
-	if (constructed == 2)
-		return ret + 3;
-	ret++;
-	if (length > 127)
-		{
-		while (length > 0)
-			{
-			length>>=8;
-			ret++;
-			}
-		}
-	return(ret);
-	}
+{
+    int ret = 1;
+    if (length < 0)
+        return -1;
+    if (tag >= 31) {
+        while (tag > 0) {
+            tag >>= 7;
+            ret++;
+        }
+    }
+    if (constructed == 2) {
+        ret += 3;
+    } else {
+        ret++;
+        if (length > 127) {
+            int tmplen = length;
+            while (tmplen > 0) {
+                tmplen >>= 8;
+                ret++;
+            }
+        }
+    }
+    if (ret >= INT_MAX - length)
+        return -1;
+    return ret + length;
+}
 
 static int _asn1_Finish(ASN1_const_CTX *c)
-	{
-	if ((c->inf == (1|V_ASN1_CONSTRUCTED)) && (!c->eos))
-		{
-		if (!ASN1_const_check_infinite_end(&c->p,c->slen))
-			{
-			c->error=ASN1_R_MISSING_ASN1_EOS;
-			return(0);
-			}
-		}
-	if (	((c->slen != 0) && !(c->inf & 1)) ||
-		((c->slen < 0) && (c->inf & 1)))
-		{
-		c->error=ASN1_R_ASN1_LENGTH_MISMATCH;
-		return(0);
-		}
-	return(1);
-	}
+{
+    if ((c->inf == (1 | V_ASN1_CONSTRUCTED)) && (!c->eos)) {
+        if (!ASN1_const_check_infinite_end(&c->p, c->slen)) {
+            c->error = ASN1_R_MISSING_ASN1_EOS;
+            return (0);
+        }
+    }
+    if (((c->slen != 0) && !(c->inf & 1)) || ((c->slen < 0) && (c->inf & 1))) {
+        c->error = ASN1_R_ASN1_LENGTH_MISMATCH;
+        return (0);
+    }
+    return (1);
+}
 
 int asn1_Finish(ASN1_CTX *c)
-	{
-	return _asn1_Finish((ASN1_const_CTX *)c);
-	}
+{
+    return _asn1_Finish((ASN1_const_CTX *)c);
+}
 
 int asn1_const_Finish(ASN1_const_CTX *c)
-	{
-	return _asn1_Finish(c);
-	}
-
-int asn1_GetSequence(ASN1_const_CTX *c, long *length)
-	{
-	const unsigned char *q;
-
-	q=c->p;
-	c->inf=ASN1_get_object(&(c->p),&(c->slen),&(c->tag),&(c->xclass),
-		*length);
-	if (c->inf & 0x80)
-		{
-		c->error=ASN1_R_BAD_GET_ASN1_OBJECT_CALL;
-		return(0);
-		}
-	if (c->tag != V_ASN1_SEQUENCE)
-		{
-		c->error=ASN1_R_EXPECTING_AN_ASN1_SEQUENCE;
-		return(0);
-		}
-	(*length)-=(c->p-q);
-	if (c->max && (*length < 0))
-		{
-		c->error=ASN1_R_ASN1_LENGTH_MISMATCH;
-		return(0);
-		}
-	if (c->inf == (1|V_ASN1_CONSTRUCTED))
-		c->slen= *length+ *(c->pp)-c->p;
-	c->eos=0;
-	return(1);
-	}
+{
+    return _asn1_Finish(c);
+}
 
 int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str)
-	{
-	if (str == NULL)
-		return 0;
-	dst->type = str->type;
-	if (!ASN1_STRING_set(dst,str->data,str->length))
-		return 0;
-	dst->flags = str->flags;
-	return 1;
-	}
+{
+    if (str == NULL)
+        return 0;
+    dst->type = str->type;
+    if (!ASN1_STRING_set(dst, str->data, str->length))
+        return 0;
+    dst->flags = str->flags;
+    return 1;
+}
 
 ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str)
-	{
-	ASN1_STRING *ret;
-	if (!str)
-		 return NULL;
-	ret=ASN1_STRING_new();
-	if (!ret)
-		return NULL;
-	if (!ASN1_STRING_copy(ret,str))
-		{
-		ASN1_STRING_free(ret);
-		return NULL;
-		}
-	return ret;
-	}
+{
+    ASN1_STRING *ret;
+    if (!str)
+        return NULL;
+    ret = ASN1_STRING_new();
+    if (!ret)
+        return NULL;
+    if (!ASN1_STRING_copy(ret, str)) {
+        ASN1_STRING_free(ret);
+        return NULL;
+    }
+    return ret;
+}
 
 int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len)
-	{
-	unsigned char *c;
-	const char *data=_data;
+{
+    unsigned char *c;
+    const char *data = _data;
 
-	if (len < 0)
-		{
-		if (data == NULL)
-			return(0);
-		else
-			len=strlen(data);
-		}
-	if ((str->length < len) || (str->data == NULL))
-		{
-		c=str->data;
-		if (c == NULL)
-			str->data=OPENSSL_malloc(len+1);
-		else
-			str->data=OPENSSL_realloc(c,len+1);
+    if (len < 0) {
+        if (data == NULL)
+            return (0);
+        else
+            len = strlen(data);
+    }
+    if ((str->length <= len) || (str->data == NULL)) {
+        c = str->data;
+        if (c == NULL)
+            str->data = OPENSSL_malloc(len + 1);
+        else
+            str->data = OPENSSL_realloc(c, len + 1);
 
-		if (str->data == NULL)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-			str->data=c;
-			return(0);
-			}
-		}
-	str->length=len;
-	if (data != NULL)
-		{
-		memcpy(str->data,data,len);
-		/* an allowance for strings :-) */
-		str->data[len]='\0';
-		}
-	return(1);
-	}
+        if (str->data == NULL) {
+            OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+            str->data = c;
+            return (0);
+        }
+    }
+    str->length = len;
+    if (data != NULL) {
+        OPENSSL_memcpy(str->data, data, len);
+        /* an allowance for strings :-) */
+        str->data[len] = '\0';
+    }
+    return (1);
+}
 
 void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len)
-	{
-	if (str->data)
-		OPENSSL_free(str->data);
-	str->data = data;
-	str->length = len;
-	}
+{
+    if (str->data)
+        OPENSSL_free(str->data);
+    str->data = data;
+    str->length = len;
+}
 
 ASN1_STRING *ASN1_STRING_new(void)
-	{
-	return(ASN1_STRING_type_new(V_ASN1_OCTET_STRING));
-	}
-
+{
+    return (ASN1_STRING_type_new(V_ASN1_OCTET_STRING));
+}
 
 ASN1_STRING *ASN1_STRING_type_new(int type)
-	{
-	ASN1_STRING *ret;
+{
+    ASN1_STRING *ret;
 
-	ret=(ASN1_STRING *)OPENSSL_malloc(sizeof(ASN1_STRING));
-	if (ret == NULL)
-		{
-		OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-		return(NULL);
-		}
-	ret->length=0;
-	ret->type=type;
-	ret->data=NULL;
-	ret->flags=0;
-	return(ret);
-	}
+    ret = (ASN1_STRING *)OPENSSL_malloc(sizeof(ASN1_STRING));
+    if (ret == NULL) {
+        OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+        return (NULL);
+    }
+    ret->length = 0;
+    ret->type = type;
+    ret->data = NULL;
+    ret->flags = 0;
+    return (ret);
+}
 
 void ASN1_STRING_free(ASN1_STRING *a)
-	{
-	if (a == NULL) return;
-	if (a->data && !(a->flags & ASN1_STRING_FLAG_NDEF))
-		OPENSSL_free(a->data);
-	OPENSSL_free(a);
-	}
+{
+    if (a == NULL)
+        return;
+    if (a->data && !(a->flags & ASN1_STRING_FLAG_NDEF))
+        OPENSSL_free(a->data);
+    OPENSSL_free(a);
+}
 
 int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b)
-	{
-	int i;
+{
+    int i;
 
-	i=(a->length-b->length);
-	if (i == 0)
-		{
-		i=memcmp(a->data,b->data,a->length);
-		if (i == 0)
-			return(a->type-b->type);
-		else
-			return(i);
-		}
-	else
-		return(i);
-	}
+    i = (a->length - b->length);
+    if (i == 0) {
+        i = OPENSSL_memcmp(a->data, b->data, a->length);
+        if (i == 0)
+            return (a->type - b->type);
+        else
+            return (i);
+    } else
+        return (i);
+}
 
 int ASN1_STRING_length(const ASN1_STRING *x)
-{ return M_ASN1_STRING_length(x); }
+{
+    return M_ASN1_STRING_length(x);
+}
 
 void ASN1_STRING_length_set(ASN1_STRING *x, int len)
-{ M_ASN1_STRING_length_set(x, len); return; }
+{
+    M_ASN1_STRING_length_set(x, len);
+    return;
+}
 
 int ASN1_STRING_type(ASN1_STRING *x)
-{ return M_ASN1_STRING_type(x); }
+{
+    return M_ASN1_STRING_type(x);
+}
 
-unsigned char * ASN1_STRING_data(ASN1_STRING *x)
-{ return M_ASN1_STRING_data(x); }
+unsigned char *ASN1_STRING_data(ASN1_STRING *x)
+{
+    return M_ASN1_STRING_data(x);
+}
diff --git a/src/crypto/asn1/asn1_locl.h b/src/crypto/asn1/asn1_locl.h
index ca5f612..ce8146b 100644
--- a/src/crypto/asn1/asn1_locl.h
+++ b/src/crypto/asn1/asn1_locl.h
@@ -1,6 +1,7 @@
 /* asn1t.h */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 2006.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 2006.
  */
 /* ====================================================================
  * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
@@ -10,7 +11,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -56,18 +57,42 @@
  *
  */
 
+#ifndef OPENSSL_HEADER_ASN1_ASN1_LOCL_H
+#define OPENSSL_HEADER_ASN1_ASN1_LOCL_H
+
+#include <time.h>
+
+#include <openssl/asn1.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* Wrapper functions for time functions. */
+
+/* OPENSSL_gmtime wraps |gmtime_r|. See the manual page for that function. */
+struct tm *OPENSSL_gmtime(const time_t *timer, struct tm *result);
+
+/* OPENSSL_gmtime_adj updates |tm| by adding |offset_day| days and |offset_sec|
+ * seconds. */
+int OPENSSL_gmtime_adj(struct tm *tm, int offset_day, long offset_sec);
+
+/* OPENSSL_gmtime_diff calculates the difference between |from| and |to| and
+ * outputs the difference as a number of days and seconds in |*out_days| and
+ * |*out_secs|. */
+int OPENSSL_gmtime_diff(int *out_days, int *out_secs, const struct tm *from,
+                        const struct tm *to);
+
+
 /* Internal ASN1 structures and functions: not for application use */
 
 int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d);
 int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d);
 
-/* ASN1 print context structure */
 
-struct asn1_pctx_st
-	{
-	unsigned long flags;
-	unsigned long nm_flags;
-	unsigned long cert_flags;
-	unsigned long oid_flags;
-	unsigned long str_flags;
-	} /* ASN1_PCTX */;
+#if defined(__cplusplus)
+}  /* extern C */
+#endif
+
+#endif  /* OPENSSL_HEADER_ASN1_ASN1_LOCL_H */
diff --git a/src/crypto/asn1/asn1_par.c b/src/crypto/asn1/asn1_par.c
index e04aa1e..b1a01ed 100644
--- a/src/crypto/asn1/asn1_par.c
+++ b/src/crypto/asn1/asn1_par.c
@@ -56,389 +56,25 @@
 
 #include <openssl/asn1.h>
 
-#include <openssl/bio.h>
-#include <openssl/err.h>
-#include <openssl/mem.h>
-
-
-#define ASN1_PARSE_MAXDEPTH 128
-
-static int asn1_print_info(BIO *bp, int tag, int xclass,int constructed,
-	int indent);
-static int asn1_parse2(BIO *bp, const unsigned char **pp, long length,
-	int offset, int depth, int indent, int dump);
-static int asn1_print_info(BIO *bp, int tag, int xclass, int constructed,
-	     int indent)
-	{
-	static const char fmt[]="%-18s";
-	char str[128];
-	const char *p;
-
-	if (constructed & V_ASN1_CONSTRUCTED)
-		p="cons: ";
-	else
-		p="prim: ";
-	if (BIO_write(bp,p,6) < 6) goto err;
-	BIO_indent(bp,indent,128);
-
-	p=str;
-	if ((xclass & V_ASN1_PRIVATE) == V_ASN1_PRIVATE)
-		BIO_snprintf(str,sizeof str,"priv [ %d ] ",tag);
-	else if ((xclass & V_ASN1_CONTEXT_SPECIFIC) == V_ASN1_CONTEXT_SPECIFIC)
-		BIO_snprintf(str,sizeof str,"cont [ %d ]",tag);
-	else if ((xclass & V_ASN1_APPLICATION) == V_ASN1_APPLICATION)
-		BIO_snprintf(str,sizeof str,"appl [ %d ]",tag);
-	else if (tag > 30)
-		BIO_snprintf(str,sizeof str,"<ASN1 %d>",tag);
-	else
-		p = ASN1_tag2str(tag);
-
-	if (BIO_printf(bp,fmt,p) <= 0)
-		goto err;
-	return(1);
-err:
-	return(0);
-	}
-
-int ASN1_parse(BIO *bp, const unsigned char *pp, long len, int indent)
-	{
-	return(asn1_parse2(bp,&pp,len,0,0,indent,0));
-	}
-
-int ASN1_parse_dump(BIO *bp, const unsigned char *pp, long len, int indent, int dump)
-	{
-	return(asn1_parse2(bp,&pp,len,0,0,indent,dump));
-	}
-
-static int asn1_parse2(BIO *bp, const unsigned char **pp, long length, int offset,
-	     int depth, int indent, int dump)
-	{
-	const unsigned char *p,*ep,*tot,*op,*opp;
-	long len;
-	int tag,xclass,ret=0;
-	int nl,hl,j,r;
-	ASN1_OBJECT *o=NULL;
-	ASN1_OCTET_STRING *os=NULL;
-	/* ASN1_BMPSTRING *bmp=NULL;*/
-	int dump_indent;
-
-#if 0
-	dump_indent = indent;
-#else
-	dump_indent = 6;	/* Because we know BIO_dump_indent() */
-#endif
-
-	if (depth > ASN1_PARSE_MAXDEPTH)
-		{
-		BIO_puts(bp, "BAD RECURSION DEPTH\n");
-		return 0;
-		}
-
-	p= *pp;
-	tot=p+length;
-	op=p-1;
-	while ((p < tot) && (op < p))
-		{
-		op=p;
-		j=ASN1_get_object(&p,&len,&tag,&xclass,length);
-#ifdef LINT
-		j=j;
-#endif
-		if (j & 0x80)
-			{
-			if (BIO_puts(bp, "Error in encoding\n") <= 0)
-				goto end;
-			ret=0;
-			goto end;
-			}
-		hl=(p-op);
-		length-=hl;
-		/* if j == 0x21 it is a constructed indefinite length object */
-		if (BIO_printf(bp,"%5ld:",(long)offset+(long)(op- *pp))
-			<= 0) goto end;
-
-		if (j != (V_ASN1_CONSTRUCTED | 1))
-			{
-			if (BIO_printf(bp,"d=%-2d hl=%ld l=%4ld ",
-				depth,(long)hl,len) <= 0)
-				goto end;
-			}
-		else
-			{
-			if (BIO_printf(bp,"d=%-2d hl=%ld l=inf  ",
-				depth,(long)hl) <= 0)
-				goto end;
-			}
-		if (!asn1_print_info(bp,tag,xclass,j,(indent)?depth:0))
-			goto end;
-		if (j & V_ASN1_CONSTRUCTED)
-			{
-			ep=p+len;
-			if (BIO_puts(bp, "\n") <= 0) goto end;
-			if (len > length)
-				{
-				BIO_printf(bp,
-					"length is greater than %ld\n",length);
-				ret=0;
-				goto end;
-				}
-			if ((j == 0x21) && (len == 0))
-				{
-				for (;;)
-					{
-					r=asn1_parse2(bp,&p,(long)(tot-p),
-						offset+(p - *pp),depth+1,
-						indent,dump);
-					if (r == 0) { ret=0; goto end; }
-					if ((r == 2) || (p >= tot)) break;
-					}
-				}
-			else
-				while (p < ep)
-					{
-					r=asn1_parse2(bp,&p,(long)len,
-						offset+(p - *pp),depth+1,
-						indent,dump);
-					if (r == 0) { ret=0; goto end; }
-					}
-			}
-		else if (xclass != 0)
-			{
-			p+=len;
-			if (BIO_puts(bp, "\n") <= 0) goto end;
-			}
-		else
-			{
-			nl=0;
-			if (	(tag == V_ASN1_PRINTABLESTRING) ||
-				(tag == V_ASN1_T61STRING) ||
-				(tag == V_ASN1_IA5STRING) ||
-				(tag == V_ASN1_VISIBLESTRING) ||
-				(tag == V_ASN1_NUMERICSTRING) ||
-				(tag == V_ASN1_UTF8STRING) ||
-				(tag == V_ASN1_UTCTIME) ||
-				(tag == V_ASN1_GENERALIZEDTIME))
-				{
-				if (BIO_puts(bp, ":") <= 0) goto end;
-				if ((len > 0) &&
-					BIO_write(bp,(const char *)p,(int)len)
-					!= (int)len)
-					goto end;
-				}
-			else if (tag == V_ASN1_OBJECT)
-				{
-				opp=op;
-				if (d2i_ASN1_OBJECT(&o,&opp,len+hl) != NULL)
-					{
-					if (BIO_puts(bp, ":") <= 0) goto end;
-					i2a_ASN1_OBJECT(bp,o);
-					}
-				else
-					{
-					if (BIO_puts(bp, ":BAD OBJECT") <= 0)
-						goto end;
-					}
-				}
-			else if (tag == V_ASN1_BOOLEAN)
-				{
-				int ii;
-
-				opp=op;
-				ii=d2i_ASN1_BOOLEAN(NULL,&opp,len+hl);
-				if (ii < 0)
-					{
-					if (BIO_puts(bp, "Bad boolean\n") <= 0)
-						goto end;
-					}
-				BIO_printf(bp,":%d",ii);
-				}
-			else if (tag == V_ASN1_BMPSTRING)
-				{
-				/* do the BMP thang */
-				}
-			else if (tag == V_ASN1_OCTET_STRING)
-				{
-				int i,printable=1;
-
-				opp=op;
-				os=d2i_ASN1_OCTET_STRING(NULL,&opp,len+hl);
-				if (os != NULL && os->length > 0)
-					{
-					opp = os->data;
-					/* testing whether the octet string is
-					 * printable */
-					for (i=0; i<os->length; i++)
-						{
-						if ((	(opp[i] < ' ') &&
-							(opp[i] != '\n') &&
-							(opp[i] != '\r') &&
-							(opp[i] != '\t')) ||
-							(opp[i] > '~'))
-							{
-							printable=0;
-							break;
-							}
-						}
-					if (printable)
-					/* printable string */
-						{
-						if (BIO_puts(bp, ":") <= 0)
-							goto end;
-						if (BIO_write(bp,(const char *)opp,
-							os->length) <= 0)
-							goto end;
-						}
-					else if (!dump)
-					/* not printable => print octet string
-					 * as hex dump */
-						{
-						if (BIO_puts(bp, "[HEX DUMP]:") <= 0)
-							goto end;
-						for (i=0; i<os->length; i++)
-							{
-							if (BIO_printf(bp,"%02X"
-								, opp[i]) <= 0)
-								goto end;
-							}
-						}
-					else
-					/* print the normal dump */
-						{
-						if (!nl) 
-							{
-							if (BIO_puts(bp, "\n") <= 0)
-								goto end;
-							}
-						if (!BIO_hexdump(bp, opp,
-							((dump == -1 || dump > 
-							os->length)?os->length:dump),
-							dump_indent))
-							goto end;
-						nl=1;
-						}
-					}
-				if (os != NULL)
-					{
-					M_ASN1_OCTET_STRING_free(os);
-					os=NULL;
-					}
-				}
-			else if (tag == V_ASN1_INTEGER)
-				{
-				ASN1_INTEGER *bs;
-				int i;
-
-				opp=op;
-				bs=d2i_ASN1_INTEGER(NULL,&opp,len+hl);
-				if (bs != NULL)
-					{
-					if (BIO_puts(bp, ":") <= 0) goto end;
-					if (bs->type == V_ASN1_NEG_INTEGER)
-						if (BIO_puts(bp, "-") <= 0)
-							goto end;
-					for (i=0; i<bs->length; i++)
-						{
-						if (BIO_printf(bp,"%02X",
-							bs->data[i]) <= 0)
-							goto end;
-						}
-					if (bs->length == 0)
-						{
-						if (BIO_puts(bp, "00") <= 0)
-							goto end;
-						}
-					}
-				else
-					{
-					if (BIO_puts(bp, "BAD INTEGER") <= 0)
-						goto end;
-					}
-				M_ASN1_INTEGER_free(bs);
-				}
-			else if (tag == V_ASN1_ENUMERATED)
-				{
-				ASN1_ENUMERATED *bs;
-				int i;
-
-				opp=op;
-				bs=d2i_ASN1_ENUMERATED(NULL,&opp,len+hl);
-				if (bs != NULL)
-					{
-					if (BIO_puts(bp, ":") <= 0) goto end;
-					if (bs->type == V_ASN1_NEG_ENUMERATED)
-						if (BIO_puts(bp, "-") <= 0)
-							goto end;
-					for (i=0; i<bs->length; i++)
-						{
-						if (BIO_printf(bp,"%02X",
-							bs->data[i]) <= 0)
-							goto end;
-						}
-					if (bs->length == 0)
-						{
-						if (BIO_puts(bp, "00") <= 0)
-							goto end;
-						}
-					}
-				else
-					{
-					if (BIO_puts(bp, "BAD ENUMERATED") <= 0)
-						goto end;
-					}
-				M_ASN1_ENUMERATED_free(bs);
-				}
-			else if (len > 0 && dump)
-				{
-				if (!nl) 
-					{
-					if (BIO_puts(bp, "\n") <= 0)
-						goto end;
-					}
-				if (!BIO_hexdump(bp,p,
-					((dump == -1 || dump > len)?len:dump),
-					dump_indent))
-					goto end;
-				nl=1;
-				}
-
-			if (!nl) 
-				{
-				if (BIO_puts(bp, "\n") <= 0) goto end;
-				}
-			p+=len;
-			if ((tag == V_ASN1_EOC) && (xclass == 0))
-				{
-				ret=2; /* End of sequence */
-				goto end;
-				}
-			}
-		length-=len;
-		}
-	ret=1;
-end:
-	if (o != NULL) ASN1_OBJECT_free(o);
-	if (os != NULL) M_ASN1_OCTET_STRING_free(os);
-	*pp=p;
-	return(ret);
-	}
 
 const char *ASN1_tag2str(int tag)
 {
-	static const char * const tag2str[] = {
-	 "EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", /* 0-4 */
-	 "NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", /* 5-9 */
-	 "ENUMERATED", "<ASN1 11>", "UTF8STRING", "<ASN1 13>", 	    /* 10-13 */
-	"<ASN1 14>", "<ASN1 15>", "SEQUENCE", "SET", 		    /* 15-17 */
-	"NUMERICSTRING", "PRINTABLESTRING", "T61STRING",	    /* 18-20 */
-	"VIDEOTEXSTRING", "IA5STRING", "UTCTIME","GENERALIZEDTIME", /* 21-24 */
-	"GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING",	    /* 25-27 */
-	"UNIVERSALSTRING", "<ASN1 29>", "BMPSTRING"		    /* 28-30 */
-	};
+    static const char *const tag2str[] = {
+        "EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", /* 0-4 */
+        "NULL", "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", /* 5-9 */
+        "ENUMERATED", "<ASN1 11>", "UTF8STRING", "<ASN1 13>", /* 10-13 */
+        "<ASN1 14>", "<ASN1 15>", "SEQUENCE", "SET", /* 15-17 */
+        "NUMERICSTRING", "PRINTABLESTRING", "T61STRING", /* 18-20 */
+        "VIDEOTEXSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME", /* 21-24
+                                                                      */
+        "GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", /* 25-27 */
+        "UNIVERSALSTRING", "<ASN1 29>", "BMPSTRING" /* 28-30 */
+    };
 
-	if((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED))
-							tag &= ~0x100;
+    if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED))
+        tag &= ~0x100;
 
-	if(tag < 0 || tag > 30) return "(unknown)";
-	return tag2str[tag];
+    if (tag < 0 || tag > 30)
+        return "(unknown)";
+    return tag2str[tag];
 }
-
diff --git a/src/crypto/asn1/asn1_test.cc b/src/crypto/asn1/asn1_test.cc
new file mode 100644
index 0000000..accf3ba
--- /dev/null
+++ b/src/crypto/asn1/asn1_test.cc
@@ -0,0 +1,62 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <stdio.h>
+
+#include <gtest/gtest.h>
+
+#include <openssl/asn1.h>
+#include <openssl/err.h>
+
+#include "../test/test_util.h"
+
+
+// kTag128 is an ASN.1 structure with a universal tag with number 128.
+static const uint8_t kTag128[] = {
+    0x1f, 0x81, 0x00, 0x01, 0x00,
+};
+
+// kTag258 is an ASN.1 structure with a universal tag with number 258.
+static const uint8_t kTag258[] = {
+    0x1f, 0x82, 0x02, 0x01, 0x00,
+};
+
+static_assert(V_ASN1_NEG_INTEGER == 258,
+              "V_ASN1_NEG_INTEGER changed. Update kTag258 to collide with it.");
+
+// kTagOverflow is an ASN.1 structure with a universal tag with number 2^35-1,
+// which will not fit in an int.
+static const uint8_t kTagOverflow[] = {
+    0x1f, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x01, 0x00,
+};
+
+TEST(ASN1Test, LargeTags) {
+  const uint8_t *p = kTag258;
+  bssl::UniquePtr<ASN1_TYPE> obj(d2i_ASN1_TYPE(NULL, &p, sizeof(kTag258)));
+  EXPECT_FALSE(obj) << "Parsed value with illegal tag" << obj->type;
+  ERR_clear_error();
+
+  p = kTagOverflow;
+  obj.reset(d2i_ASN1_TYPE(NULL, &p, sizeof(kTagOverflow)));
+  EXPECT_FALSE(obj) << "Parsed value with tag overflow" << obj->type;
+  ERR_clear_error();
+
+  p = kTag128;
+  obj.reset(d2i_ASN1_TYPE(NULL, &p, sizeof(kTag128)));
+  ASSERT_TRUE(obj);
+  EXPECT_EQ(128, obj->type);
+  const uint8_t kZero = 0;
+  EXPECT_EQ(Bytes(&kZero, 1), Bytes(obj->value.asn1_string->data,
+                                    obj->value.asn1_string->length));
+}
diff --git a/src/crypto/asn1/asn_pack.c b/src/crypto/asn1/asn_pack.c
index e842a10..eff54e5 100644
--- a/src/crypto/asn1/asn_pack.c
+++ b/src/crypto/asn1/asn_pack.c
@@ -59,46 +59,47 @@
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
-
 /* ASN1_ITEM versions of the above */
 
 ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct)
 {
-	ASN1_STRING *octmp;
+    ASN1_STRING *octmp;
 
-	if (!oct || !*oct) {
-		if (!(octmp = ASN1_STRING_new ())) {
-			OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-			return NULL;
-		}
-		if (oct) *oct = octmp;
-	} else octmp = *oct;
+    if (!oct || !*oct) {
+        if (!(octmp = ASN1_STRING_new())) {
+            OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+            return NULL;
+        }
+        if (oct)
+            *oct = octmp;
+    } else
+        octmp = *oct;
 
-	if(octmp->data) {
-		OPENSSL_free(octmp->data);
-		octmp->data = NULL;
-	}
-		
-	if (!(octmp->length = ASN1_item_i2d(obj, &octmp->data, it))) {
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_ENCODE_ERROR);
-		return NULL;
-	}
-	if (!octmp->data) {
-		OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-		return NULL;
-	}
-	return octmp;
+    if (octmp->data) {
+        OPENSSL_free(octmp->data);
+        octmp->data = NULL;
+    }
+
+    if (!(octmp->length = ASN1_item_i2d(obj, &octmp->data, it))) {
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_ENCODE_ERROR);
+        return NULL;
+    }
+    if (!octmp->data) {
+        OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+    return octmp;
 }
 
 /* Extract an ASN1 object from an ASN1_STRING */
 
 void *ASN1_item_unpack(ASN1_STRING *oct, const ASN1_ITEM *it)
 {
-	const unsigned char *p;
-	void *ret;
+    const unsigned char *p;
+    void *ret;
 
-	p = oct->data;
-	if(!(ret = ASN1_item_d2i(NULL, &p, oct->length, it)))
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
-	return ret;
+    p = oct->data;
+    if (!(ret = ASN1_item_d2i(NULL, &p, oct->length, it)))
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
+    return ret;
 }
diff --git a/src/crypto/asn1/bio_asn1.c b/src/crypto/asn1/bio_asn1.c
deleted file mode 100644
index 15f233b..0000000
--- a/src/crypto/asn1/bio_asn1.c
+++ /dev/null
@@ -1,496 +0,0 @@
-/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to.  The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *    "This product includes cryptographic software written by
- *     Eric Young (eay@cryptsoft.com)"
- *    The word 'cryptographic' can be left out if the rouines from the library
- *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- *    the apps directory (application code) you must include an acknowledgement:
- *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed.  i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.] */
-
-#include <openssl/asn1.h>
-
-#include <assert.h>
-#include <string.h>
-
-#include <openssl/bio.h>
-#include <openssl/mem.h>
-
-
-/* Must be large enough for biggest tag+length */
-#define DEFAULT_ASN1_BUF_SIZE 20
-
-typedef enum 
-	{
-	ASN1_STATE_START,
-	ASN1_STATE_PRE_COPY,
-	ASN1_STATE_HEADER,
-	ASN1_STATE_HEADER_COPY,
-	ASN1_STATE_DATA_COPY,
-	ASN1_STATE_POST_COPY,
-	ASN1_STATE_DONE
-	} asn1_bio_state_t;
-
-typedef struct BIO_ASN1_EX_FUNCS_st
-	{
-	asn1_ps_func	*ex_func;
-	asn1_ps_func	*ex_free_func;
-	} BIO_ASN1_EX_FUNCS;
-
-typedef struct BIO_ASN1_BUF_CTX_t
-	{
-	/* Internal state */
-	asn1_bio_state_t state;
-	/* Internal buffer */
-	unsigned char *buf;
-	/* Size of buffer */
-	int bufsize;
-	/* Current position in buffer */
-	int bufpos;
-	/* Current buffer length */
-	int buflen;
-	/* Amount of data to copy */
-	int copylen;
-	/* Class and tag to use */
-	int asn1_class, asn1_tag;
-	asn1_ps_func *prefix, *prefix_free, *suffix, *suffix_free;
-	/* Extra buffer for prefix and suffix data */
-	unsigned char *ex_buf;
-	int ex_len;
-	int ex_pos;
-	void *ex_arg;
-	} BIO_ASN1_BUF_CTX;
-
-
-static int asn1_bio_write(BIO *h, const char *buf,int num);
-static int asn1_bio_read(BIO *h, char *buf, int size);
-static int asn1_bio_puts(BIO *h, const char *str);
-static int asn1_bio_gets(BIO *h, char *str, int size);
-static long asn1_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2);
-static int asn1_bio_new(BIO *h);
-static int asn1_bio_free(BIO *data);
-static long asn1_bio_callback_ctrl(BIO *h, int cmd, bio_info_cb fp);
-
-static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size);
-static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
-				asn1_ps_func *cleanup, asn1_bio_state_t next);
-static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
-				asn1_ps_func *setup, 
-				asn1_bio_state_t ex_state,
-				asn1_bio_state_t other_state);
-
-static const BIO_METHOD methods_asn1=
-	{
-	BIO_TYPE_ASN1,
-	"asn1",
-	asn1_bio_write,
-	asn1_bio_read,
-	asn1_bio_puts,
-	asn1_bio_gets,
-	asn1_bio_ctrl,
-	asn1_bio_new,
-	asn1_bio_free,
-	asn1_bio_callback_ctrl,
-	};
-
-const BIO_METHOD *BIO_f_asn1(void)
-	{
-	return(&methods_asn1);
-	}
-
-
-static int asn1_bio_new(BIO *b)
-	{
-	BIO_ASN1_BUF_CTX *ctx;
-	ctx = OPENSSL_malloc(sizeof(BIO_ASN1_BUF_CTX));
-	if (!ctx)
-		return 0;
-	if (!asn1_bio_init(ctx, DEFAULT_ASN1_BUF_SIZE))
-		{
-		OPENSSL_free(ctx);
-		return 0;
-		}
-	b->init = 1;
-	b->ptr = (char *)ctx;
-	b->flags = 0;
-	return 1;
-	}
-
-static int asn1_bio_init(BIO_ASN1_BUF_CTX *ctx, int size)
-	{
-	ctx->buf = OPENSSL_malloc(size);
-	if (!ctx->buf)
-		return 0;
-	ctx->bufsize = size;
-	ctx->bufpos = 0;
-	ctx->buflen = 0;
-	ctx->copylen = 0;
-	ctx->asn1_class = V_ASN1_UNIVERSAL;
-	ctx->asn1_tag = V_ASN1_OCTET_STRING;
-	ctx->ex_buf = 0;
-	ctx->ex_pos = 0;
-	ctx->ex_len = 0;
-	ctx->state = ASN1_STATE_START;
-	return 1;
-	}
-
-static int asn1_bio_free(BIO *b)
-	{
-	BIO_ASN1_BUF_CTX *ctx;
-	ctx = (BIO_ASN1_BUF_CTX *) b->ptr;
-	if (ctx == NULL)
-		return 0;
-	if (ctx->buf)
-		OPENSSL_free(ctx->buf);
-	OPENSSL_free(ctx);
-	b->init = 0;
-	b->ptr = NULL;
-	b->flags = 0;
-	return 1;
-	}
-
-static int asn1_bio_write(BIO *b, const char *in , int inl)
-	{
-	BIO_ASN1_BUF_CTX *ctx;
-	int wrmax, wrlen, ret;
-	unsigned char *p;
-	if (!in || (inl < 0) || (b->next_bio == NULL))
-		return 0;
-	ctx = (BIO_ASN1_BUF_CTX *) b->ptr;
-	if (ctx == NULL)
-		return 0;
-
-	wrlen = 0;
-	ret = -1;
-
-	for(;;)
-		{
-		switch (ctx->state)
-			{
-
-			/* Setup prefix data, call it */
-			case ASN1_STATE_START:
-			if (!asn1_bio_setup_ex(b, ctx, ctx->prefix,
-				ASN1_STATE_PRE_COPY, ASN1_STATE_HEADER))
-				return 0;
-			break;
-
-			/* Copy any pre data first */
-			case ASN1_STATE_PRE_COPY:
-
-			ret = asn1_bio_flush_ex(b, ctx, ctx->prefix_free,
-							ASN1_STATE_HEADER);
-
-			if (ret <= 0)
-				goto done;
-
-			break;
-
-			case ASN1_STATE_HEADER:
-			ctx->buflen =
-				ASN1_object_size(0, inl, ctx->asn1_tag) - inl;
-			assert(ctx->buflen <= ctx->bufsize);
-			p = ctx->buf;
-			ASN1_put_object(&p, 0, inl,
-					ctx->asn1_tag, ctx->asn1_class);
-			ctx->copylen = inl;
-			ctx->state = ASN1_STATE_HEADER_COPY;
-
-			break;
-
-			case ASN1_STATE_HEADER_COPY:	
-			ret = BIO_write(b->next_bio,
-					ctx->buf + ctx->bufpos, ctx->buflen);
-			if (ret <= 0)
-				goto done;
-
-			ctx->buflen -= ret;
-			if (ctx->buflen)
-				ctx->bufpos += ret;
-			else
-				{
-				ctx->bufpos = 0;
-				ctx->state = ASN1_STATE_DATA_COPY;
-				}
-
-			break;
-
-			case ASN1_STATE_DATA_COPY:
-
-			if (inl > ctx->copylen)
-				wrmax = ctx->copylen;
-			else
-				wrmax = inl;
-			ret = BIO_write(b->next_bio, in, wrmax);
-			if (ret <= 0)
-				break;
-			wrlen += ret;
-			ctx->copylen -= ret;
-			in += ret;
-			inl -= ret;
-
-			if (ctx->copylen == 0)
-				ctx->state = ASN1_STATE_HEADER;
-
-			if (inl == 0)
-				goto done;
-
-			break;
-
-			default:
-			BIO_clear_retry_flags(b);
-			return 0;
-
-			}
-
-		}
-
-	done:
-	BIO_clear_retry_flags(b);
-	BIO_copy_next_retry(b);
-
-	return (wrlen > 0) ? wrlen : ret;
-
-	}
-
-static int asn1_bio_flush_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
-				asn1_ps_func *cleanup, asn1_bio_state_t next)
-	{
-	int ret;
-	if (ctx->ex_len <= 0)
-		return 1;
-	for(;;)
-		{
-		ret = BIO_write(b->next_bio, ctx->ex_buf + ctx->ex_pos,
-								ctx->ex_len);
-		if (ret <= 0)
-			break;
-		ctx->ex_len -= ret;
-		if (ctx->ex_len > 0)
-			ctx->ex_pos += ret;
-		else
-			{
-			if(cleanup)
-				cleanup(b, &ctx->ex_buf, &ctx->ex_len,
-								&ctx->ex_arg);
-			ctx->state = next;
-			ctx->ex_pos = 0;
-			break;
-			}
-		}
-	return ret;
-	}
-
-static int asn1_bio_setup_ex(BIO *b, BIO_ASN1_BUF_CTX *ctx,
-				asn1_ps_func *setup, 
-				asn1_bio_state_t ex_state,
-				asn1_bio_state_t other_state)
-	{
-	if (setup && !setup(b, &ctx->ex_buf, &ctx->ex_len, &ctx->ex_arg))
-		{
-		BIO_clear_retry_flags(b);
-		return 0;
-		}
-	if (ctx->ex_len > 0)
-		ctx->state = ex_state;
-	else
-		ctx->state = other_state;
-	return 1;
-	}
-
-static int asn1_bio_read(BIO *b, char *in , int inl)
-	{
-	if (!b->next_bio)
-		return 0;
-	return BIO_read(b->next_bio, in , inl);
-	}
-
-static int asn1_bio_puts(BIO *b, const char *str)
-	{
-	return asn1_bio_write(b, str, strlen(str));
-	}
-
-static int asn1_bio_gets(BIO *b, char *str, int size)
-	{
-	if (!b->next_bio)
-		return 0;
-	return BIO_gets(b->next_bio, str , size);
-	}
-
-static long asn1_bio_callback_ctrl(BIO *b, int cmd, bio_info_cb fp)
-	{
-	if (b->next_bio == NULL) return(0);
-	return BIO_callback_ctrl(b->next_bio,cmd,fp);
-	}
-
-static long asn1_bio_ctrl(BIO *b, int cmd, long arg1, void *arg2)
-	{
-	BIO_ASN1_BUF_CTX *ctx;
-	BIO_ASN1_EX_FUNCS *ex_func;
-	long ret = 1;
-	ctx = (BIO_ASN1_BUF_CTX *) b->ptr;
-	if (ctx == NULL)
-		return 0;
-	switch(cmd)
-		{
-
-		case BIO_C_SET_PREFIX:
-		ex_func = arg2;
-		ctx->prefix  = ex_func->ex_func;
-		ctx->prefix_free  = ex_func->ex_free_func;
-		break;
-
-		case BIO_C_GET_PREFIX:
-		ex_func = arg2;
-		ex_func->ex_func = ctx->prefix;
-		ex_func->ex_free_func = ctx->prefix_free;
-		break;
-
-		case BIO_C_SET_SUFFIX:
-		ex_func = arg2;
-		ctx->suffix  = ex_func->ex_func;
-		ctx->suffix_free  = ex_func->ex_free_func;
-		break;
-
-		case BIO_C_GET_SUFFIX:
-		ex_func = arg2;
-		ex_func->ex_func = ctx->suffix;
-		ex_func->ex_free_func = ctx->suffix_free;
-		break;
-
-		case BIO_C_SET_EX_ARG:
-		ctx->ex_arg = arg2;
-		break;
-
-		case BIO_C_GET_EX_ARG:
-		*(void **)arg2 = ctx->ex_arg;
-		break;
-
-		case BIO_CTRL_FLUSH:
-		if (!b->next_bio)
-			return 0;
-
-		/* Call post function if possible */
-		if (ctx->state == ASN1_STATE_HEADER)
-			{
-			if (!asn1_bio_setup_ex(b, ctx, ctx->suffix,
-				ASN1_STATE_POST_COPY, ASN1_STATE_DONE))
-				return 0;
-			}
-
-		if (ctx->state == ASN1_STATE_POST_COPY)
-			{
-			ret = asn1_bio_flush_ex(b, ctx, ctx->suffix_free,
-							ASN1_STATE_DONE);
-			if (ret <= 0)
-				return ret;
-			}
-
-		if (ctx->state == ASN1_STATE_DONE)
-			return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
-		else
-			{
-			BIO_clear_retry_flags(b);
-			return 0;
-			}
-		break;
-
-
-		default:
-		if (!b->next_bio)
-			return 0;
-		return BIO_ctrl(b->next_bio, cmd, arg1, arg2);
-
-		}
-
-	return ret;
-	}
-
-static int asn1_bio_set_ex(BIO *b, int cmd,
-		asn1_ps_func *ex_func, asn1_ps_func *ex_free_func)
-	{
-	BIO_ASN1_EX_FUNCS extmp;
-	extmp.ex_func = ex_func;
-	extmp.ex_free_func = ex_free_func;
-	return BIO_ctrl(b, cmd, 0, &extmp);
-	}
-
-static int asn1_bio_get_ex(BIO *b, int cmd,
-		asn1_ps_func **ex_func, asn1_ps_func **ex_free_func)
-	{
-	BIO_ASN1_EX_FUNCS extmp;
-	int ret;
-	ret = BIO_ctrl(b, cmd, 0, &extmp);
-	if (ret > 0)
-		{
-		*ex_func = extmp.ex_func;
-		*ex_free_func = extmp.ex_free_func;
-		}
-	return ret;
-	}
-
-int BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix, asn1_ps_func *prefix_free)
-	{
-	return asn1_bio_set_ex(b, BIO_C_SET_PREFIX, prefix, prefix_free);
-	}
-
-int BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix, asn1_ps_func **pprefix_free)
-	{
-	return asn1_bio_get_ex(b, BIO_C_GET_PREFIX, pprefix, pprefix_free);
-	}
-
-int BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix, asn1_ps_func *suffix_free)
-	{
-	return asn1_bio_set_ex(b, BIO_C_SET_SUFFIX, suffix, suffix_free);
-	}
-
-int BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix, asn1_ps_func **psuffix_free)
-	{
-	return asn1_bio_get_ex(b, BIO_C_GET_SUFFIX, psuffix, psuffix_free);
-	}
diff --git a/src/crypto/asn1/bio_ndef.c b/src/crypto/asn1/bio_ndef.c
deleted file mode 100644
index f07d3de..0000000
--- a/src/crypto/asn1/bio_ndef.c
+++ /dev/null
@@ -1,254 +0,0 @@
-/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to.  The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *    "This product includes cryptographic software written by
- *     Eric Young (eay@cryptsoft.com)"
- *    The word 'cryptographic' can be left out if the rouines from the library
- *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- *    the apps directory (application code) you must include an acknowledgement:
- *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed.  i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.] */
-
-#include <openssl/asn1.h>
-
-#include <assert.h>
-
-#include <openssl/asn1t.h>
-#include <openssl/bio.h>
-#include <openssl/err.h>
-#include <openssl/mem.h>
-
-
-/* Experimental NDEF ASN1 BIO support routines */
-
-/* The usage is quite simple, initialize an ASN1 structure,
- * get a BIO from it then any data written through the BIO
- * will end up translated to approptiate format on the fly.
- * The data is streamed out and does *not* need to be
- * all held in memory at once.
- *
- * When the BIO is flushed the output is finalized and any
- * signatures etc written out.
- *
- * The BIO is a 'proper' BIO and can handle non blocking I/O
- * correctly.
- *
- * The usage is simple. The implementation is *not*...
- */
-
-/* BIO support data stored in the ASN1 BIO ex_arg */
-
-typedef struct ndef_aux_st
-	{
-	/* ASN1 structure this BIO refers to */
-	ASN1_VALUE *val;
-	const ASN1_ITEM *it;
-	/* Top of the BIO chain */
-	BIO *ndef_bio;
-	/* Output BIO */
-	BIO *out;
-	/* Boundary where content is inserted */
-	unsigned char **boundary;
-	/* DER buffer start */
-	unsigned char *derbuf;
-	} NDEF_SUPPORT;
-
-static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
-static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg);
-static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg);
-static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg);
-
-BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it)
-	{
-	NDEF_SUPPORT *ndef_aux = NULL;
-	BIO *asn_bio = NULL;
-	const ASN1_AUX *aux = it->funcs;
-	ASN1_STREAM_ARG sarg;
-
-	if (!aux || !aux->asn1_cb)
-		{
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_STREAMING_NOT_SUPPORTED);
-		return NULL;
-		}
-	ndef_aux = OPENSSL_malloc(sizeof(NDEF_SUPPORT));
-	asn_bio = BIO_new(BIO_f_asn1());
-
-	/* ASN1 bio needs to be next to output BIO */
-
-	out = BIO_push(asn_bio, out);
-
-	if (!ndef_aux || !asn_bio || !out)
-		goto err;
-
-	BIO_asn1_set_prefix(asn_bio, ndef_prefix, ndef_prefix_free);
-	BIO_asn1_set_suffix(asn_bio, ndef_suffix, ndef_suffix_free);
-
-	/* Now let callback prepend any digest, cipher etc BIOs
-	 * ASN1 structure needs.
-	 */
-
-	sarg.out = out;
-	sarg.ndef_bio = NULL;
-	sarg.boundary = NULL;
-
-	if (aux->asn1_cb(ASN1_OP_STREAM_PRE, &val, it, &sarg) <= 0)
-		goto err;
-
-	ndef_aux->val = val;
-	ndef_aux->it = it;
-	ndef_aux->ndef_bio = sarg.ndef_bio;
-	ndef_aux->boundary = sarg.boundary;
-	ndef_aux->out = out;
-
-	BIO_ctrl(asn_bio, BIO_C_SET_EX_ARG, 0, ndef_aux);
-
-	return sarg.ndef_bio;
-
-	err:
-	if (asn_bio)
-		BIO_free(asn_bio);
-	if (ndef_aux)
-		OPENSSL_free(ndef_aux);
-	return NULL;
-	}
-
-static int ndef_prefix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
-	{
-	NDEF_SUPPORT *ndef_aux;
-	unsigned char *p;
-	int derlen;
-
-	if (!parg)
-		return 0;
-
-	ndef_aux = *(NDEF_SUPPORT **)parg;
-
-	derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
-	p = OPENSSL_malloc(derlen);
-	if (p == NULL)
-		return 0;
-
-	ndef_aux->derbuf = p;
-	*pbuf = p;
-	derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
-
-	if (!*ndef_aux->boundary)
-		return 0;
-
-	*plen = *ndef_aux->boundary - *pbuf;
-
-	return 1;
-	}
-
-static int ndef_prefix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg)
-	{
-	NDEF_SUPPORT *ndef_aux;
-
-	if (!parg)
-		return 0;
-
-	ndef_aux = *(NDEF_SUPPORT **)parg;
-
-	if (ndef_aux->derbuf)
-		OPENSSL_free(ndef_aux->derbuf);
-
-	ndef_aux->derbuf = NULL;
-	*pbuf = NULL;
-	*plen = 0;
-	return 1;
-	}
-
-static int ndef_suffix_free(BIO *b, unsigned char **pbuf, int *plen, void *parg)
-	{
-	NDEF_SUPPORT **pndef_aux = (NDEF_SUPPORT **)parg;
-	if (!ndef_prefix_free(b, pbuf, plen, parg))
-		return 0;
-	OPENSSL_free(*pndef_aux);
-	*pndef_aux = NULL;
-	return 1;
-	}
-
-static int ndef_suffix(BIO *b, unsigned char **pbuf, int *plen, void *parg)
-	{
-	NDEF_SUPPORT *ndef_aux;
-	unsigned char *p;
-	int derlen;
-	const ASN1_AUX *aux;
-	ASN1_STREAM_ARG sarg;
-
-	if (!parg)
-		return 0;
-
-	ndef_aux = *(NDEF_SUPPORT **)parg;
-
-	aux = ndef_aux->it->funcs;
-
-	/* Finalize structures */
-	sarg.ndef_bio = ndef_aux->ndef_bio;
-	sarg.out = ndef_aux->out;
-	sarg.boundary = ndef_aux->boundary;
-	if (aux->asn1_cb(ASN1_OP_STREAM_POST,
-				&ndef_aux->val, ndef_aux->it, &sarg) <= 0)
-		return 0;
-
-	derlen = ASN1_item_ndef_i2d(ndef_aux->val, NULL, ndef_aux->it);
-	p = OPENSSL_malloc(derlen);
-	if (p == NULL)
-		return 0;
-
-	ndef_aux->derbuf = p;
-	*pbuf = p;
-	derlen = ASN1_item_ndef_i2d(ndef_aux->val, &p, ndef_aux->it);
-
-	if (!*ndef_aux->boundary)
-		return 0;
-	*pbuf = *ndef_aux->boundary;
-	*plen = derlen - (*ndef_aux->boundary - ndef_aux->derbuf);
-
-	return 1;
-	}
diff --git a/src/crypto/asn1/f_enum.c b/src/crypto/asn1/f_enum.c
index bcdb773..7ce479d 100644
--- a/src/crypto/asn1/f_enum.c
+++ b/src/crypto/asn1/f_enum.c
@@ -56,151 +56,38 @@
 
 #include <openssl/asn1.h>
 
-#include <openssl/err.h>
-#include <openssl/mem.h>
+#include <openssl/bio.h>
 
 /* Based on a_int.c: equivalent ENUMERATED functions */
 
 int i2a_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *a)
-	{
-	int i,n=0;
-	static const char *h="0123456789ABCDEF";
-	char buf[2];
+{
+    int i, n = 0;
+    static const char *h = "0123456789ABCDEF";
+    char buf[2];
 
-	if (a == NULL) return(0);
+    if (a == NULL)
+        return (0);
 
-	if (a->length == 0)
-		{
-		if (BIO_write(bp,"00",2) != 2) goto err;
-		n=2;
-		}
-	else
-		{
-		for (i=0; i<a->length; i++)
-			{
-			if ((i != 0) && (i%35 == 0))
-				{
-				if (BIO_write(bp,"\\\n",2) != 2) goto err;
-				n+=2;
-				}
-			buf[0]=h[((unsigned char)a->data[i]>>4)&0x0f];
-			buf[1]=h[((unsigned char)a->data[i]   )&0x0f];
-			if (BIO_write(bp,buf,2) != 2) goto err;
-			n+=2;
-			}
-		}
-	return(n);
-err:
-	return(-1);
-	}
-
-int a2i_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *bs, char *buf, int size)
-	{
-	int ret=0;
-	int i,j,k,m,n,again,bufsize;
-	unsigned char *s=NULL,*sp;
-	unsigned char *bufp;
-	int num=0,slen=0,first=1;
-
-	bs->type=V_ASN1_ENUMERATED;
-
-	bufsize=BIO_gets(bp,buf,size);
-	for (;;)
-		{
-		if (bufsize < 1) goto err_sl;
-		i=bufsize;
-		if (buf[i-1] == '\n') buf[--i]='\0';
-		if (i == 0) goto err_sl;
-		if (buf[i-1] == '\r') buf[--i]='\0';
-		if (i == 0) goto err_sl;
-		again=(buf[i-1] == '\\');
-
-		for (j=0; j<i; j++)
-			{
-			if (!(	((buf[j] >= '0') && (buf[j] <= '9')) ||
-				((buf[j] >= 'a') && (buf[j] <= 'f')) ||
-				((buf[j] >= 'A') && (buf[j] <= 'F'))))
-				{
-				i=j;
-				break;
-				}
-			}
-		buf[i]='\0';
-		/* We have now cleared all the crap off the end of the
-		 * line */
-		if (i < 2) goto err_sl;
-
-		bufp=(unsigned char *)buf;
-		if (first)
-			{
-			first=0;
-			if ((bufp[0] == '0') && (buf[1] == '0'))
-				{
-				bufp+=2;
-				i-=2;
-				}
-			}
-		k=0;
-		i-=again;
-		if (i%2 != 0)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_ODD_NUMBER_OF_CHARS);
-			goto err;
-			}
-		i/=2;
-		if (num+i > slen)
-			{
-			if (s == NULL)
-				sp=(unsigned char *)OPENSSL_malloc(
-					(unsigned int)num+i*2);
-			else
-				sp=(unsigned char *)OPENSSL_realloc(s,
-					(unsigned int)num+i*2);
-			if (sp == NULL)
-				{
-				OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-				goto err;
-				}
-			s=sp;
-			slen=num+i*2;
-			}
-		for (j=0; j<i; j++,k+=2)
-			{
-			for (n=0; n<2; n++)
-				{
-				m=bufp[k+n];
-				if ((m >= '0') && (m <= '9'))
-					m-='0';
-				else if ((m >= 'a') && (m <= 'f'))
-					m=m-'a'+10;
-				else if ((m >= 'A') && (m <= 'F'))
-					m=m-'A'+10;
-				else
-					{
-					OPENSSL_PUT_ERROR(ASN1, ASN1_R_NON_HEX_CHARACTERS);
-					goto err;
-					}
-				s[num+j]<<=4;
-				s[num+j]|=m;
-				}
-			}
-		num+=i;
-		if (again)
-			bufsize=BIO_gets(bp,buf,size);
-		else
-			break;
-		}
-	bs->length=num;
-	bs->data=s;
-	ret=1;
-err:
-	if (0)
-		{
-err_sl:
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_SHORT_LINE);
-		}
-	if (s != NULL)
-		OPENSSL_free(s);
-	return(ret);
-	}
-
+    if (a->length == 0) {
+        if (BIO_write(bp, "00", 2) != 2)
+            goto err;
+        n = 2;
+    } else {
+        for (i = 0; i < a->length; i++) {
+            if ((i != 0) && (i % 35 == 0)) {
+                if (BIO_write(bp, "\\\n", 2) != 2)
+                    goto err;
+                n += 2;
+            }
+            buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f];
+            buf[1] = h[((unsigned char)a->data[i]) & 0x0f];
+            if (BIO_write(bp, buf, 2) != 2)
+                goto err;
+            n += 2;
+        }
+    }
+    return (n);
+ err:
+    return (-1);
+}
diff --git a/src/crypto/asn1/f_int.c b/src/crypto/asn1/f_int.c
index 5186304..79ea152 100644
--- a/src/crypto/asn1/f_int.c
+++ b/src/crypto/asn1/f_int.c
@@ -56,155 +56,42 @@
 
 #include <openssl/asn1.h>
 
-#include <openssl/err.h>
-#include <openssl/mem.h>
-
+#include <openssl/bio.h>
 
 int i2a_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *a)
-	{
-	int i,n=0;
-	static const char *h="0123456789ABCDEF";
-	char buf[2];
+{
+    int i, n = 0;
+    static const char *h = "0123456789ABCDEF";
+    char buf[2];
 
-	if (a == NULL) return(0);
+    if (a == NULL)
+        return (0);
 
-	if (a->type & V_ASN1_NEG)
-		{
-		if (BIO_write(bp, "-", 1) != 1) goto err;
-		n = 1;
-		}
+    if (a->type & V_ASN1_NEG) {
+        if (BIO_write(bp, "-", 1) != 1)
+            goto err;
+        n = 1;
+    }
 
-	if (a->length == 0)
-		{
-		if (BIO_write(bp,"00",2) != 2) goto err;
-		n += 2;
-		}
-	else
-		{
-		for (i=0; i<a->length; i++)
-			{
-			if ((i != 0) && (i%35 == 0))
-				{
-				if (BIO_write(bp,"\\\n",2) != 2) goto err;
-				n+=2;
-				}
-			buf[0]=h[((unsigned char)a->data[i]>>4)&0x0f];
-			buf[1]=h[((unsigned char)a->data[i]   )&0x0f];
-			if (BIO_write(bp,buf,2) != 2) goto err;
-			n+=2;
-			}
-		}
-	return(n);
-err:
-	return(-1);
-	}
-
-int a2i_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *bs, char *buf, int size)
-	{
-	int ret=0;
-	int i,j,k,m,n,again,bufsize;
-	unsigned char *s=NULL,*sp;
-	unsigned char *bufp;
-	int num=0,slen=0,first=1;
-
-	bs->type=V_ASN1_INTEGER;
-
-	bufsize=BIO_gets(bp,buf,size);
-	for (;;)
-		{
-		if (bufsize < 1) goto err_sl;
-		i=bufsize;
-		if (buf[i-1] == '\n') buf[--i]='\0';
-		if (i == 0) goto err_sl;
-		if (buf[i-1] == '\r') buf[--i]='\0';
-		if (i == 0) goto err_sl;
-		again=(buf[i-1] == '\\');
-
-		for (j=0; j<i; j++)
-			{
-			if (!(	((buf[j] >= '0') && (buf[j] <= '9')) ||
-				((buf[j] >= 'a') && (buf[j] <= 'f')) ||
-				((buf[j] >= 'A') && (buf[j] <= 'F'))))
-				{
-				i=j;
-				break;
-				}
-			}
-		buf[i]='\0';
-		/* We have now cleared all the crap off the end of the
-		 * line */
-		if (i < 2) goto err_sl;
-
-		bufp=(unsigned char *)buf;
-		if (first)
-			{
-			first=0;
-			if ((bufp[0] == '0') && (buf[1] == '0'))
-				{
-				bufp+=2;
-				i-=2;
-				}
-			}
-		k=0;
-		i-=again;
-		if (i%2 != 0)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_ODD_NUMBER_OF_CHARS);
-			goto err;
-			}
-		i/=2;
-		if (num+i > slen)
-			{
-			if (s == NULL)
-				sp=(unsigned char *)OPENSSL_malloc(
-					(unsigned int)num+i*2);
-			else
-				sp=OPENSSL_realloc_clean(s,slen,num+i*2);
-			if (sp == NULL)
-				{
-				OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-				goto err;
-				}
-			s=sp;
-			slen=num+i*2;
-			}
-		for (j=0; j<i; j++,k+=2)
-			{
-			for (n=0; n<2; n++)
-				{
-				m=bufp[k+n];
-				if ((m >= '0') && (m <= '9'))
-					m-='0';
-				else if ((m >= 'a') && (m <= 'f'))
-					m=m-'a'+10;
-				else if ((m >= 'A') && (m <= 'F'))
-					m=m-'A'+10;
-				else
-					{
-					OPENSSL_PUT_ERROR(ASN1, ASN1_R_NON_HEX_CHARACTERS);
-					goto err;
-					}
-				s[num+j]<<=4;
-				s[num+j]|=m;
-				}
-			}
-		num+=i;
-		if (again)
-			bufsize=BIO_gets(bp,buf,size);
-		else
-			break;
-		}
-	bs->length=num;
-	bs->data=s;
-	ret=1;
-err:
-	if (0)
-		{
-err_sl:
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_SHORT_LINE);
-		}
-	if (s != NULL)
-		OPENSSL_free(s);
-	return(ret);
-	}
-
+    if (a->length == 0) {
+        if (BIO_write(bp, "00", 2) != 2)
+            goto err;
+        n += 2;
+    } else {
+        for (i = 0; i < a->length; i++) {
+            if ((i != 0) && (i % 35 == 0)) {
+                if (BIO_write(bp, "\\\n", 2) != 2)
+                    goto err;
+                n += 2;
+            }
+            buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f];
+            buf[1] = h[((unsigned char)a->data[i]) & 0x0f];
+            if (BIO_write(bp, buf, 2) != 2)
+                goto err;
+            n += 2;
+        }
+    }
+    return (n);
+ err:
+    return (-1);
+}
diff --git a/src/crypto/asn1/f_string.c b/src/crypto/asn1/f_string.c
index 5a7fe36..97c6ae7 100644
--- a/src/crypto/asn1/f_string.c
+++ b/src/crypto/asn1/f_string.c
@@ -56,149 +56,36 @@
 
 #include <openssl/asn1.h>
 
-#include <openssl/err.h>
-#include <openssl/mem.h>
-
-
+#include <openssl/bio.h>
 
 int i2a_ASN1_STRING(BIO *bp, ASN1_STRING *a, int type)
-	{
-	int i,n=0;
-	static const char *h="0123456789ABCDEF";
-	char buf[2];
+{
+    int i, n = 0;
+    static const char *h = "0123456789ABCDEF";
+    char buf[2];
 
-	if (a == NULL) return(0);
+    if (a == NULL)
+        return (0);
 
-	if (a->length == 0)
-		{
-		if (BIO_write(bp,"0",1) != 1) goto err;
-		n=1;
-		}
-	else
-		{
-		for (i=0; i<a->length; i++)
-			{
-			if ((i != 0) && (i%35 == 0))
-				{
-				if (BIO_write(bp,"\\\n",2) != 2) goto err;
-				n+=2;
-				}
-			buf[0]=h[((unsigned char)a->data[i]>>4)&0x0f];
-			buf[1]=h[((unsigned char)a->data[i]   )&0x0f];
-			if (BIO_write(bp,buf,2) != 2) goto err;
-			n+=2;
-			}
-		}
-	return(n);
-err:
-	return(-1);
-	}
-
-int a2i_ASN1_STRING(BIO *bp, ASN1_STRING *bs, char *buf, int size)
-	{
-	int ret=0;
-	int i,j,k,m,n,again,bufsize;
-	unsigned char *s=NULL,*sp;
-	unsigned char *bufp;
-	int num=0,slen=0,first=1;
-
-	bufsize=BIO_gets(bp,buf,size);
-	for (;;)
-		{
-		if (bufsize < 1)
-			{
-			if (first)
-				break;
-			else
-				goto err_sl;
-			}
-		first=0;
-
-		i=bufsize;
-		if (buf[i-1] == '\n') buf[--i]='\0';
-		if (i == 0) goto err_sl;
-		if (buf[i-1] == '\r') buf[--i]='\0';
-		if (i == 0) goto err_sl;
-		again=(buf[i-1] == '\\');
-
-		for (j=i-1; j>0; j--)
-			{
-			if (!(	((buf[j] >= '0') && (buf[j] <= '9')) ||
-				((buf[j] >= 'a') && (buf[j] <= 'f')) ||
-				((buf[j] >= 'A') && (buf[j] <= 'F'))))
-				{
-				i=j;
-				break;
-				}
-			}
-		buf[i]='\0';
-		/* We have now cleared all the crap off the end of the
-		 * line */
-		if (i < 2) goto err_sl;
-
-		bufp=(unsigned char *)buf;
-
-		k=0;
-		i-=again;
-		if (i%2 != 0)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_ODD_NUMBER_OF_CHARS);
-			goto err;
-			}
-		i/=2;
-		if (num+i > slen)
-			{
-			if (s == NULL)
-				sp=(unsigned char *)OPENSSL_malloc(
-					(unsigned int)num+i*2);
-			else
-				sp=(unsigned char *)OPENSSL_realloc(s,
-					(unsigned int)num+i*2);
-			if (sp == NULL)
-				{
-				OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-				goto err;
-				}
-			s=sp;
-			slen=num+i*2;
-			}
-		for (j=0; j<i; j++,k+=2)
-			{
-			for (n=0; n<2; n++)
-				{
-				m=bufp[k+n];
-				if ((m >= '0') && (m <= '9'))
-					m-='0';
-				else if ((m >= 'a') && (m <= 'f'))
-					m=m-'a'+10;
-				else if ((m >= 'A') && (m <= 'F'))
-					m=m-'A'+10;
-				else
-					{
-					OPENSSL_PUT_ERROR(ASN1, ASN1_R_NON_HEX_CHARACTERS);
-					goto err;
-					}
-				s[num+j]<<=4;
-				s[num+j]|=m;
-				}
-			}
-		num+=i;
-		if (again)
-			bufsize=BIO_gets(bp,buf,size);
-		else
-			break;
-		}
-	bs->length=num;
-	bs->data=s;
-	ret=1;
-err:
-	if (0)
-		{
-err_sl:
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_SHORT_LINE);
-		}
-	if (s != NULL)
-		OPENSSL_free(s);
-	return(ret);
-	}
-
+    if (a->length == 0) {
+        if (BIO_write(bp, "0", 1) != 1)
+            goto err;
+        n = 1;
+    } else {
+        for (i = 0; i < a->length; i++) {
+            if ((i != 0) && (i % 35 == 0)) {
+                if (BIO_write(bp, "\\\n", 2) != 2)
+                    goto err;
+                n += 2;
+            }
+            buf[0] = h[((unsigned char)a->data[i] >> 4) & 0x0f];
+            buf[1] = h[((unsigned char)a->data[i]) & 0x0f];
+            if (BIO_write(bp, buf, 2) != 2)
+                goto err;
+            n += 2;
+        }
+    }
+    return (n);
+ err:
+    return (-1);
+}
diff --git a/src/crypto/asn1/t_bitst.c b/src/crypto/asn1/t_bitst.c
index 1ca6e08..e754ca7 100644
--- a/src/crypto/asn1/t_bitst.c
+++ b/src/crypto/asn1/t_bitst.c
@@ -60,43 +60,44 @@
 
 #include <openssl/mem.h>
 
-
 int ASN1_BIT_STRING_name_print(BIO *out, ASN1_BIT_STRING *bs,
-				BIT_STRING_BITNAME *tbl, int indent)
+                               BIT_STRING_BITNAME *tbl, int indent)
 {
-	BIT_STRING_BITNAME *bnam;
-	char first = 1;
-	BIO_printf(out, "%*s", indent, "");
-	for(bnam = tbl; bnam->lname; bnam++) {
-		if(ASN1_BIT_STRING_get_bit(bs, bnam->bitnum)) {
-			if(!first) BIO_puts(out, ", ");
-			BIO_puts(out, bnam->lname);
-			first = 0;
-		}
-	}
-	BIO_puts(out, "\n");
-	return 1;
+    BIT_STRING_BITNAME *bnam;
+    char first = 1;
+    BIO_printf(out, "%*s", indent, "");
+    for (bnam = tbl; bnam->lname; bnam++) {
+        if (ASN1_BIT_STRING_get_bit(bs, bnam->bitnum)) {
+            if (!first)
+                BIO_puts(out, ", ");
+            BIO_puts(out, bnam->lname);
+            first = 0;
+        }
+    }
+    BIO_puts(out, "\n");
+    return 1;
 }
 
 int ASN1_BIT_STRING_set_asc(ASN1_BIT_STRING *bs, char *name, int value,
-				BIT_STRING_BITNAME *tbl)
+                            BIT_STRING_BITNAME *tbl)
 {
-	int bitnum;
-	bitnum = ASN1_BIT_STRING_num_asc(name, tbl);
-	if(bitnum < 0) return 0;
-	if(bs) {
-		if(!ASN1_BIT_STRING_set_bit(bs, bitnum, value))
-			return 0;
-	}
-	return 1;
+    int bitnum;
+    bitnum = ASN1_BIT_STRING_num_asc(name, tbl);
+    if (bitnum < 0)
+        return 0;
+    if (bs) {
+        if (!ASN1_BIT_STRING_set_bit(bs, bitnum, value))
+            return 0;
+    }
+    return 1;
 }
 
 int ASN1_BIT_STRING_num_asc(char *name, BIT_STRING_BITNAME *tbl)
 {
-	BIT_STRING_BITNAME *bnam;
-	for(bnam = tbl; bnam->lname; bnam++) {
-		if(!strcmp(bnam->sname, name) ||
-			!strcmp(bnam->lname, name) ) return bnam->bitnum;
-	}
-	return -1;
+    BIT_STRING_BITNAME *bnam;
+    for (bnam = tbl; bnam->lname; bnam++) {
+        if (!strcmp(bnam->sname, name) || !strcmp(bnam->lname, name))
+            return bnam->bitnum;
+    }
+    return -1;
 }
diff --git a/src/crypto/asn1/t_pkey.c b/src/crypto/asn1/t_pkey.c
deleted file mode 100644
index 6ac9b3d..0000000
--- a/src/crypto/asn1/t_pkey.c
+++ /dev/null
@@ -1,112 +0,0 @@
-/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to.  The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *    "This product includes cryptographic software written by
- *     Eric Young (eay@cryptsoft.com)"
- *    The word 'cryptographic' can be left out if the rouines from the library
- *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- *    the apps directory (application code) you must include an acknowledgement:
- *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed.  i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.] */
-
-#include <openssl/asn1.h>
-
-#include <openssl/bio.h>
-#include <openssl/mem.h>
-
-
-int ASN1_bn_print(BIO *bp, const char *number, const BIGNUM *num,
-			unsigned char *buf, int off)
-	{
-	int n,i;
-	const char *neg;
-
-	if (num == NULL) return(1);
-	neg = (BN_is_negative(num))?"-":"";
-	if(!BIO_indent(bp,off,128))
-		return 0;
-	if (BN_is_zero(num))
-		{
-		if (BIO_printf(bp, "%s 0\n", number) <= 0)
-			return 0;
-		return 1;
-		}
-
-	if (BN_num_bytes(num) <= sizeof(long))
-		{
-		if (BIO_printf(bp,"%s %s%lu (%s0x%lx)\n",number,neg,
-			(unsigned long)num->d[0],neg,(unsigned long)num->d[0])
-			<= 0) return(0);
-		}
-	else
-		{
-		buf[0]=0;
-		if (BIO_printf(bp,"%s%s",number,
-			(neg[0] == '-')?" (Negative)":"") <= 0)
-			return(0);
-		n=BN_bn2bin(num,&buf[1]);
-	
-		if (buf[1] & 0x80)
-			n++;
-		else	buf++;
-
-		for (i=0; i<n; i++)
-			{
-			if ((i%15) == 0)
-				{
-				if(BIO_puts(bp,"\n") <= 0
-				   || !BIO_indent(bp,off+4,128))
-				    return 0;
-				}
-			if (BIO_printf(bp,"%02x%s",buf[i],((i+1) == n)?"":":")
-				<= 0) return(0);
-			}
-		if (BIO_write(bp,"\n",1) <= 0) return(0);
-		}
-	return(1);
-	}
diff --git a/src/crypto/asn1/tasn_dec.c b/src/crypto/asn1/tasn_dec.c
index 7c81753..bf008af 100644
--- a/src/crypto/asn1/tasn_dec.c
+++ b/src/crypto/asn1/tasn_dec.c
@@ -65,1278 +65,1159 @@
 
 #include "../internal.h"
 
-
 static int asn1_check_eoc(const unsigned char **in, long len);
 static int asn1_find_end(const unsigned char **in, long len, char inf);
 
 static int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len,
-			char inf, int tag, int aclass, int depth);
+                        char inf, int tag, int aclass, int depth);
 
 static int collect_data(BUF_MEM *buf, const unsigned char **p, long plen);
 
 static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass,
-				char *inf, char *cst,
-				const unsigned char **in, long len,
-				int exptag, int expclass, char opt,
-				ASN1_TLC *ctx);
+                           char *inf, char *cst,
+                           const unsigned char **in, long len,
+                           int exptag, int expclass, char opt, ASN1_TLC *ctx);
 
 static int asn1_template_ex_d2i(ASN1_VALUE **pval,
-				const unsigned char **in, long len,
-				const ASN1_TEMPLATE *tt, char opt,
-				ASN1_TLC *ctx);
+                                const unsigned char **in, long len,
+                                const ASN1_TEMPLATE *tt, char opt,
+                                ASN1_TLC *ctx);
 static int asn1_template_noexp_d2i(ASN1_VALUE **val,
-				const unsigned char **in, long len,
-				const ASN1_TEMPLATE *tt, char opt,
-				ASN1_TLC *ctx);
+                                   const unsigned char **in, long len,
+                                   const ASN1_TEMPLATE *tt, char opt,
+                                   ASN1_TLC *ctx);
 static int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
-				const unsigned char **in, long len,
-				const ASN1_ITEM *it,
-				int tag, int aclass, char opt, ASN1_TLC *ctx);
+                                 const unsigned char **in, long len,
+                                 const ASN1_ITEM *it,
+                                 int tag, int aclass, char opt,
+                                 ASN1_TLC *ctx);
 
 /* Table to convert tags to bit values, used for MSTRING type */
 static const unsigned long tag2bit[32] = {
-0,	0,	0,	B_ASN1_BIT_STRING,	/* tags  0 -  3 */
-B_ASN1_OCTET_STRING,	0,	0,		B_ASN1_UNKNOWN,/* tags  4- 7 */
-B_ASN1_UNKNOWN,	B_ASN1_UNKNOWN,	B_ASN1_UNKNOWN,	B_ASN1_UNKNOWN,/* tags  8-11 */
-B_ASN1_UTF8STRING,B_ASN1_UNKNOWN,B_ASN1_UNKNOWN,B_ASN1_UNKNOWN,/* tags 12-15 */
-B_ASN1_SEQUENCE,0,B_ASN1_NUMERICSTRING,B_ASN1_PRINTABLESTRING, /* tags 16-19 */
-B_ASN1_T61STRING,B_ASN1_VIDEOTEXSTRING,B_ASN1_IA5STRING,       /* tags 20-22 */
-B_ASN1_UTCTIME, B_ASN1_GENERALIZEDTIME,			       /* tags 23-24 */	
-B_ASN1_GRAPHICSTRING,B_ASN1_ISO64STRING,B_ASN1_GENERALSTRING,  /* tags 25-27 */
-B_ASN1_UNIVERSALSTRING,B_ASN1_UNKNOWN,B_ASN1_BMPSTRING,B_ASN1_UNKNOWN, /* tags 28-31 */
-	};
+    0, 0, 0, B_ASN1_BIT_STRING, /* tags 0 - 3 */
+    B_ASN1_OCTET_STRING, 0, 0, B_ASN1_UNKNOWN, /* tags 4- 7 */
+    B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, /* tags
+                                                                     * 8-11 */
+    B_ASN1_UTF8STRING, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, /* tags
+                                                                        * 12-15
+                                                                        */
+    B_ASN1_SEQUENCE, 0, B_ASN1_NUMERICSTRING, B_ASN1_PRINTABLESTRING, /* tags
+                                                                       * 16-19
+                                                                       */
+    B_ASN1_T61STRING, B_ASN1_VIDEOTEXSTRING, B_ASN1_IA5STRING, /* tags 20-22 */
+    B_ASN1_UTCTIME, B_ASN1_GENERALIZEDTIME, /* tags 23-24 */
+    B_ASN1_GRAPHICSTRING, B_ASN1_ISO64STRING, B_ASN1_GENERALSTRING, /* tags
+                                                                     * 25-27 */
+    B_ASN1_UNIVERSALSTRING, B_ASN1_UNKNOWN, B_ASN1_BMPSTRING, B_ASN1_UNKNOWN, /* tags
+                                                                               * 28-31
+                                                                               */
+};
 
 unsigned long ASN1_tag2bit(int tag)
-	{
-	if ((tag < 0) || (tag > 30)) return 0;
-	return tag2bit[tag];
-	}
+{
+    if ((tag < 0) || (tag > 30))
+        return 0;
+    return tag2bit[tag];
+}
 
 /* Macro to initialize and invalidate the cache */
 
-#define asn1_tlc_clear(c)	if (c) (c)->valid = 0
+#define asn1_tlc_clear(c)       if (c) (c)->valid = 0
 /* Version to avoid compiler warning about 'c' always non-NULL */
-#define asn1_tlc_clear_nc(c)	(c)->valid = 0
+#define asn1_tlc_clear_nc(c)    (c)->valid = 0
 
-/* Decode an ASN1 item, this currently behaves just 
- * like a standard 'd2i' function. 'in' points to 
- * a buffer to read the data from, in future we will
- * have more advanced versions that can input data
- * a piece at a time and this will simply be a special
- * case.
+/*
+ * Decode an ASN1 item, this currently behaves just like a standard 'd2i'
+ * function. 'in' points to a buffer to read the data from, in future we
+ * will have more advanced versions that can input data a piece at a time and
+ * this will simply be a special case.
  */
 
 ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **pval,
-		const unsigned char **in, long len, const ASN1_ITEM *it)
-	{
-	ASN1_TLC c;
-	ASN1_VALUE *ptmpval = NULL;
-	if (!pval)
-		pval = &ptmpval;
-	asn1_tlc_clear_nc(&c);
-	if (ASN1_item_ex_d2i(pval, in, len, it, -1, 0, 0, &c) > 0) 
-		return *pval;
-	return NULL;
-	}
+                          const unsigned char **in, long len,
+                          const ASN1_ITEM *it)
+{
+    ASN1_TLC c;
+    ASN1_VALUE *ptmpval = NULL;
+    if (!pval)
+        pval = &ptmpval;
+    asn1_tlc_clear_nc(&c);
+    if (ASN1_item_ex_d2i(pval, in, len, it, -1, 0, 0, &c) > 0)
+        return *pval;
+    return NULL;
+}
 
 int ASN1_template_d2i(ASN1_VALUE **pval,
-		const unsigned char **in, long len, const ASN1_TEMPLATE *tt)
-	{
-	ASN1_TLC c;
-	asn1_tlc_clear_nc(&c);
-	return asn1_template_ex_d2i(pval, in, len, tt, 0, &c);
-	}
+                      const unsigned char **in, long len,
+                      const ASN1_TEMPLATE *tt)
+{
+    ASN1_TLC c;
+    asn1_tlc_clear_nc(&c);
+    return asn1_template_ex_d2i(pval, in, len, tt, 0, &c);
+}
 
-
-/* Decode an item, taking care of IMPLICIT tagging, if any.
- * If 'opt' set and tag mismatch return -1 to handle OPTIONAL
+/*
+ * Decode an item, taking care of IMPLICIT tagging, if any. If 'opt' set and
+ * tag mismatch return -1 to handle OPTIONAL
  */
 
 int ASN1_item_ex_d2i(ASN1_VALUE **pval, const unsigned char **in, long len,
-			const ASN1_ITEM *it,
-			int tag, int aclass, char opt, ASN1_TLC *ctx)
-	{
-	const ASN1_TEMPLATE *tt, *errtt = NULL;
-	const ASN1_COMPAT_FUNCS *cf;
-	const ASN1_EXTERN_FUNCS *ef;
-	const ASN1_AUX *aux = it->funcs;
-	ASN1_aux_cb *asn1_cb;
-	const unsigned char *p = NULL, *q;
-	unsigned char *wp=NULL;	/* BIG FAT WARNING!  BREAKS CONST WHERE USED */
-	unsigned char imphack = 0, oclass;
-	char seq_eoc, seq_nolen, cst, isopt;
-	long tmplen;
-	int i;
-	int otag;
-	int ret = 0;
-	ASN1_VALUE **pchptr, *ptmpval;
-	int combine = aclass & ASN1_TFLG_COMBINE;
-	if (!pval)
-		return 0;
-	if (aux && aux->asn1_cb)
-		asn1_cb = aux->asn1_cb;
-	else asn1_cb = 0;
+                     const ASN1_ITEM *it,
+                     int tag, int aclass, char opt, ASN1_TLC *ctx)
+{
+    const ASN1_TEMPLATE *tt, *errtt = NULL;
+    const ASN1_COMPAT_FUNCS *cf;
+    const ASN1_EXTERN_FUNCS *ef;
+    const ASN1_AUX *aux = it->funcs;
+    ASN1_aux_cb *asn1_cb;
+    const unsigned char *p = NULL, *q;
+    unsigned char *wp = NULL;   /* BIG FAT WARNING! BREAKS CONST WHERE USED */
+    unsigned char imphack = 0, oclass;
+    char seq_eoc, seq_nolen, cst, isopt;
+    long tmplen;
+    int i;
+    int otag;
+    int ret = 0;
+    ASN1_VALUE **pchptr, *ptmpval;
+    int combine = aclass & ASN1_TFLG_COMBINE;
+    aclass &= ~ASN1_TFLG_COMBINE;
+    if (!pval)
+        return 0;
+    if (aux && aux->asn1_cb)
+        asn1_cb = aux->asn1_cb;
+    else
+        asn1_cb = 0;
 
-	switch(it->itype)
-		{
-		case ASN1_ITYPE_PRIMITIVE:
-		if (it->templates)
-			{
-			/* tagging or OPTIONAL is currently illegal on an item
-			 * template because the flags can't get passed down.
-			 * In practice this isn't a problem: we include the
-			 * relevant flags from the item template in the
-			 * template itself.
-			 */
-			if ((tag != -1) || opt)
-				{
-				OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE);
-				goto err;
-				}
-			return asn1_template_ex_d2i(pval, in, len,
-					it->templates, opt, ctx);
-		}
-		return asn1_d2i_ex_primitive(pval, in, len, it,
-						tag, aclass, opt, ctx);
-		break;
+    switch (it->itype) {
+    case ASN1_ITYPE_PRIMITIVE:
+        if (it->templates) {
+            /*
+             * tagging or OPTIONAL is currently illegal on an item template
+             * because the flags can't get passed down. In practice this
+             * isn't a problem: we include the relevant flags from the item
+             * template in the template itself.
+             */
+            if ((tag != -1) || opt) {
+                OPENSSL_PUT_ERROR(ASN1,
+                                  ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE);
+                goto err;
+            }
+            return asn1_template_ex_d2i(pval, in, len,
+                                        it->templates, opt, ctx);
+        }
+        return asn1_d2i_ex_primitive(pval, in, len, it,
+                                     tag, aclass, opt, ctx);
+        break;
 
-		case ASN1_ITYPE_MSTRING:
-		p = *in;
-		/* Just read in tag and class */
-		ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, NULL,
-						&p, len, -1, 0, 1, ctx);
-		if (!ret)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
-			goto err;
-			}
+    case ASN1_ITYPE_MSTRING:
+        p = *in;
+        /* Just read in tag and class */
+        ret = asn1_check_tlen(NULL, &otag, &oclass, NULL, NULL,
+                              &p, len, -1, 0, 1, ctx);
+        if (!ret) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+            goto err;
+        }
 
-		/* Must be UNIVERSAL class */
-		if (oclass != V_ASN1_UNIVERSAL)
-			{
-			/* If OPTIONAL, assume this is OK */
-			if (opt) return -1;
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_MSTRING_NOT_UNIVERSAL);
-			goto err;
-			}
-		/* Check tag matches bit map */
-		if (!(ASN1_tag2bit(otag) & it->utype))
-			{
-			/* If OPTIONAL, assume this is OK */
-			if (opt)
-				return -1;
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_MSTRING_WRONG_TAG);
-			goto err;
-			}
-		return asn1_d2i_ex_primitive(pval, in, len,
-						it, otag, 0, 0, ctx);
+        /* Must be UNIVERSAL class */
+        if (oclass != V_ASN1_UNIVERSAL) {
+            /* If OPTIONAL, assume this is OK */
+            if (opt)
+                return -1;
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_MSTRING_NOT_UNIVERSAL);
+            goto err;
+        }
+        /* Check tag matches bit map */
+        if (!(ASN1_tag2bit(otag) & it->utype)) {
+            /* If OPTIONAL, assume this is OK */
+            if (opt)
+                return -1;
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_MSTRING_WRONG_TAG);
+            goto err;
+        }
+        return asn1_d2i_ex_primitive(pval, in, len, it, otag, 0, 0, ctx);
 
-		case ASN1_ITYPE_EXTERN:
-		/* Use new style d2i */
-		ef = it->funcs;
-		return ef->asn1_ex_d2i(pval, in, len,
-						it, tag, aclass, opt, ctx);
+    case ASN1_ITYPE_EXTERN:
+        /* Use new style d2i */
+        ef = it->funcs;
+        return ef->asn1_ex_d2i(pval, in, len, it, tag, aclass, opt, ctx);
 
-		case ASN1_ITYPE_COMPAT:
-		/* we must resort to old style evil hackery */
-		cf = it->funcs;
+    case ASN1_ITYPE_COMPAT:
+        /* we must resort to old style evil hackery */
+        cf = it->funcs;
 
-		/* If OPTIONAL see if it is there */
-		if (opt)
-			{
-			int exptag;
-			p = *in;
-			if (tag == -1)
-				exptag = it->utype;
-			else exptag = tag;
-			/* Don't care about anything other than presence
-			 * of expected tag */
+        /* If OPTIONAL see if it is there */
+        if (opt) {
+            int exptag;
+            p = *in;
+            if (tag == -1)
+                exptag = it->utype;
+            else
+                exptag = tag;
+            /*
+             * Don't care about anything other than presence of expected tag
+             */
 
-			ret = asn1_check_tlen(NULL, NULL, NULL, NULL, NULL,
-					&p, len, exptag, aclass, 1, ctx);
-			if (!ret)
-				{
-				OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
-				goto err;
-				}
-			if (ret == -1)
-				return -1;
-			}
+            ret = asn1_check_tlen(NULL, NULL, NULL, NULL, NULL,
+                                  &p, len, exptag, aclass, 1, ctx);
+            if (!ret) {
+                OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+                goto err;
+            }
+            if (ret == -1)
+                return -1;
+        }
 
-		/* This is the old style evil hack IMPLICIT handling:
-		 * since the underlying code is expecting a tag and
-		 * class other than the one present we change the
-		 * buffer temporarily then change it back afterwards.
-		 * This doesn't and never did work for tags > 30.
-		 *
-		 * Yes this is *horrible* but it is only needed for
-		 * old style d2i which will hopefully not be around
-		 * for much longer.
-		 * FIXME: should copy the buffer then modify it so
-		 * the input buffer can be const: we should *always*
-		 * copy because the old style d2i might modify the
-		 * buffer.
-		 */
+        /*
+         * This is the old style evil hack IMPLICIT handling: since the
+         * underlying code is expecting a tag and class other than the one
+         * present we change the buffer temporarily then change it back
+         * afterwards. This doesn't and never did work for tags > 30. Yes
+         * this is *horrible* but it is only needed for old style d2i which
+         * will hopefully not be around for much longer. FIXME: should copy
+         * the buffer then modify it so the input buffer can be const: we
+         * should *always* copy because the old style d2i might modify the
+         * buffer.
+         */
 
-		if (tag != -1)
-			{
-			wp = *(unsigned char **)in;
-			imphack = *wp;
-			if (p == NULL)
-				{
-				OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
-				goto err;
-				}
-			*wp = (unsigned char)((*p & V_ASN1_CONSTRUCTED)
-								| it->utype);
-			}
+        if (tag != -1) {
+            wp = *(unsigned char **)in;
+            imphack = *wp;
+            if (p == NULL) {
+                OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+                goto err;
+            }
+            *wp = (unsigned char)((*p & V_ASN1_CONSTRUCTED)
+                                  | it->utype);
+        }
 
-		ptmpval = cf->asn1_d2i(pval, in, len);
+        ptmpval = cf->asn1_d2i(pval, in, len);
 
-		if (tag != -1)
-			*wp = imphack;
+        if (tag != -1)
+            *wp = imphack;
 
-		if (ptmpval)
-			return 1;
+        if (ptmpval)
+            return 1;
 
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
-		goto err;
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+        goto err;
 
+    case ASN1_ITYPE_CHOICE:
+        if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL))
+            goto auxerr;
 
-		case ASN1_ITYPE_CHOICE:
-		if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL))
-				goto auxerr;
+        if (*pval) {
+            /* Free up and zero CHOICE value if initialised */
+            i = asn1_get_choice_selector(pval, it);
+            if ((i >= 0) && (i < it->tcount)) {
+                tt = it->templates + i;
+                pchptr = asn1_get_field_ptr(pval, tt);
+                ASN1_template_free(pchptr, tt);
+                asn1_set_choice_selector(pval, -1, it);
+            }
+        } else if (!ASN1_item_ex_new(pval, it)) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+            goto err;
+        }
+        /* CHOICE type, try each possibility in turn */
+        p = *in;
+        for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) {
+            pchptr = asn1_get_field_ptr(pval, tt);
+            /*
+             * We mark field as OPTIONAL so its absence can be recognised.
+             */
+            ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx);
+            /* If field not present, try the next one */
+            if (ret == -1)
+                continue;
+            /* If positive return, read OK, break loop */
+            if (ret > 0)
+                break;
+            /* Otherwise must be an ASN1 parsing error */
+            errtt = tt;
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+            goto err;
+        }
 
-		if (*pval)
-			{
-			/* Free up and zero CHOICE value if initialised */
-			i = asn1_get_choice_selector(pval, it);
-			if ((i >= 0) && (i < it->tcount))
-				{
-				tt = it->templates + i;
-				pchptr = asn1_get_field_ptr(pval, tt);
-				ASN1_template_free(pchptr, tt);
-				asn1_set_choice_selector(pval, -1, it);
-				}
-			}
-		else if (!ASN1_item_ex_new(pval, it))
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
-			goto err;
-			}
-		/* CHOICE type, try each possibility in turn */
-		p = *in;
-		for (i = 0, tt=it->templates; i < it->tcount; i++, tt++)
-			{
-			pchptr = asn1_get_field_ptr(pval, tt);
-			/* We mark field as OPTIONAL so its absence
-			 * can be recognised.
-			 */
-			ret = asn1_template_ex_d2i(pchptr, &p, len, tt, 1, ctx);
-			/* If field not present, try the next one */
-			if (ret == -1)
-				continue;
-			/* If positive return, read OK, break loop */
-			if (ret > 0)
-				break;
-			/* Otherwise must be an ASN1 parsing error */
-			errtt = tt;
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
-			goto err;
-			}
+        /* Did we fall off the end without reading anything? */
+        if (i == it->tcount) {
+            /* If OPTIONAL, this is OK */
+            if (opt) {
+                /* Free and zero it */
+                ASN1_item_ex_free(pval, it);
+                return -1;
+            }
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_NO_MATCHING_CHOICE_TYPE);
+            goto err;
+        }
 
-		/* Did we fall off the end without reading anything? */
-		if (i == it->tcount)
-			{
-			/* If OPTIONAL, this is OK */
-			if (opt)
-				{
-				/* Free and zero it */
-				ASN1_item_ex_free(pval, it);
-				return -1;
-				}
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_NO_MATCHING_CHOICE_TYPE);
-			goto err;
-			}
+        asn1_set_choice_selector(pval, i, it);
+        if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL))
+            goto auxerr;
+        *in = p;
+        return 1;
 
-		asn1_set_choice_selector(pval, i, it);
-		if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL))
-				goto auxerr;
-		*in = p;
-		return 1;
+    case ASN1_ITYPE_NDEF_SEQUENCE:
+    case ASN1_ITYPE_SEQUENCE:
+        p = *in;
+        tmplen = len;
 
-		case ASN1_ITYPE_NDEF_SEQUENCE:
-		case ASN1_ITYPE_SEQUENCE:
-		p = *in;
-		tmplen = len;
+        /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
+        if (tag == -1) {
+            tag = V_ASN1_SEQUENCE;
+            aclass = V_ASN1_UNIVERSAL;
+        }
+        /* Get SEQUENCE length and update len, p */
+        ret = asn1_check_tlen(&len, NULL, NULL, &seq_eoc, &cst,
+                              &p, len, tag, aclass, opt, ctx);
+        if (!ret) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+            goto err;
+        } else if (ret == -1)
+            return -1;
+        if (aux && (aux->flags & ASN1_AFLG_BROKEN)) {
+            len = tmplen - (p - *in);
+            seq_nolen = 1;
+        }
+        /* If indefinite we don't do a length check */
+        else
+            seq_nolen = seq_eoc;
+        if (!cst) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_SEQUENCE_NOT_CONSTRUCTED);
+            goto err;
+        }
 
-		/* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
-		if (tag == -1)
-			{
-			tag = V_ASN1_SEQUENCE;
-			aclass = V_ASN1_UNIVERSAL;
-			}
-		/* Get SEQUENCE length and update len, p */
-		ret = asn1_check_tlen(&len, NULL, NULL, &seq_eoc, &cst,
-					&p, len, tag, aclass, opt, ctx);
-		if (!ret)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
-			goto err;
-			}
-		else if (ret == -1)
-			return -1;
-		if (aux && (aux->flags & ASN1_AFLG_BROKEN))
-			{
-			len = tmplen - (p - *in);
-			seq_nolen = 1;
-			}
-		/* If indefinite we don't do a length check */
-		else seq_nolen = seq_eoc;
-		if (!cst)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_SEQUENCE_NOT_CONSTRUCTED);
-			goto err;
-			}
+        if (!*pval && !ASN1_item_ex_new(pval, it)) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+            goto err;
+        }
 
-		if (!*pval && !ASN1_item_ex_new(pval, it))
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
-			goto err;
-			}
+        if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL))
+            goto auxerr;
 
-		if (asn1_cb && !asn1_cb(ASN1_OP_D2I_PRE, pval, it, NULL))
-				goto auxerr;
+        /* Free up and zero any ADB found */
+        for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) {
+            if (tt->flags & ASN1_TFLG_ADB_MASK) {
+                const ASN1_TEMPLATE *seqtt;
+                ASN1_VALUE **pseqval;
+                seqtt = asn1_do_adb(pval, tt, 0);
+                if (seqtt == NULL)
+                    continue;
+                pseqval = asn1_get_field_ptr(pval, seqtt);
+                ASN1_template_free(pseqval, seqtt);
+            }
+        }
 
-		/* Free up and zero any ADB found */
-		for (i = 0, tt = it->templates; i < it->tcount; i++, tt++)
-			{
-			if (tt->flags & ASN1_TFLG_ADB_MASK)
-				{
-				const ASN1_TEMPLATE *seqtt;
-				ASN1_VALUE **pseqval;
-				seqtt = asn1_do_adb(pval, tt, 1);
-				pseqval = asn1_get_field_ptr(pval, seqtt);
-				ASN1_template_free(pseqval, seqtt);
-				}
-			}
+        /* Get each field entry */
+        for (i = 0, tt = it->templates; i < it->tcount; i++, tt++) {
+            const ASN1_TEMPLATE *seqtt;
+            ASN1_VALUE **pseqval;
+            seqtt = asn1_do_adb(pval, tt, 1);
+            if (seqtt == NULL)
+                goto err;
+            pseqval = asn1_get_field_ptr(pval, seqtt);
+            /* Have we ran out of data? */
+            if (!len)
+                break;
+            q = p;
+            if (asn1_check_eoc(&p, len)) {
+                if (!seq_eoc) {
+                    OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNEXPECTED_EOC);
+                    goto err;
+                }
+                len -= p - q;
+                seq_eoc = 0;
+                q = p;
+                break;
+            }
+            /*
+             * This determines the OPTIONAL flag value. The field cannot be
+             * omitted if it is the last of a SEQUENCE and there is still
+             * data to be read. This isn't strictly necessary but it
+             * increases efficiency in some cases.
+             */
+            if (i == (it->tcount - 1))
+                isopt = 0;
+            else
+                isopt = (char)(seqtt->flags & ASN1_TFLG_OPTIONAL);
+            /*
+             * attempt to read in field, allowing each to be OPTIONAL
+             */
 
-		/* Get each field entry */
-		for (i = 0, tt = it->templates; i < it->tcount; i++, tt++)
-			{
-			const ASN1_TEMPLATE *seqtt;
-			ASN1_VALUE **pseqval;
-			seqtt = asn1_do_adb(pval, tt, 1);
-			if (!seqtt)
-				goto err;
-			pseqval = asn1_get_field_ptr(pval, seqtt);
-			/* Have we ran out of data? */
-			if (!len)
-				break;
-			q = p;
-			if (asn1_check_eoc(&p, len))
-				{
-				if (!seq_eoc)
-					{
-					OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNEXPECTED_EOC);
-					goto err;
-					}
-				len -= p - q;
-				seq_eoc = 0;
-				q = p;
-				break;
-				}
-			/* This determines the OPTIONAL flag value. The field
-			 * cannot be omitted if it is the last of a SEQUENCE
-			 * and there is still data to be read. This isn't
-			 * strictly necessary but it increases efficiency in
-			 * some cases.
-			 */
-			if (i == (it->tcount - 1))
-				isopt = 0;
-			else isopt = (char)(seqtt->flags & ASN1_TFLG_OPTIONAL);
-			/* attempt to read in field, allowing each to be
-			 * OPTIONAL */
+            ret = asn1_template_ex_d2i(pseqval, &p, len, seqtt, isopt, ctx);
+            if (!ret) {
+                errtt = seqtt;
+                goto err;
+            } else if (ret == -1) {
+                /*
+                 * OPTIONAL component absent. Free and zero the field.
+                 */
+                ASN1_template_free(pseqval, seqtt);
+                continue;
+            }
+            /* Update length */
+            len -= p - q;
+        }
 
-			ret = asn1_template_ex_d2i(pseqval, &p, len,
-							seqtt, isopt, ctx);
-			if (!ret)
-				{
-				errtt = seqtt;
-				goto err;
-				}
-			else if (ret == -1)
-				{
-				/* OPTIONAL component absent.
-				 * Free and zero the field.
-				 */
-				ASN1_template_free(pseqval, seqtt);
-				continue;
-				}
-			/* Update length */
-			len -= p - q;
-			}
+        /* Check for EOC if expecting one */
+        if (seq_eoc && !asn1_check_eoc(&p, len)) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_EOC);
+            goto err;
+        }
+        /* Check all data read */
+        if (!seq_nolen && len) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_SEQUENCE_LENGTH_MISMATCH);
+            goto err;
+        }
 
-		/* Check for EOC if expecting one */
-		if (seq_eoc && !asn1_check_eoc(&p, len))
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_EOC);
-			goto err;
-			}
-		/* Check all data read */
-		if (!seq_nolen && len)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_SEQUENCE_LENGTH_MISMATCH);
-			goto err;
-			}
+        /*
+         * If we get here we've got no more data in the SEQUENCE, however we
+         * may not have read all fields so check all remaining are OPTIONAL
+         * and clear any that are.
+         */
+        for (; i < it->tcount; tt++, i++) {
+            const ASN1_TEMPLATE *seqtt;
+            seqtt = asn1_do_adb(pval, tt, 1);
+            if (seqtt == NULL)
+                goto err;
+            if (seqtt->flags & ASN1_TFLG_OPTIONAL) {
+                ASN1_VALUE **pseqval;
+                pseqval = asn1_get_field_ptr(pval, seqtt);
+                ASN1_template_free(pseqval, seqtt);
+            } else {
+                errtt = seqtt;
+                OPENSSL_PUT_ERROR(ASN1, ASN1_R_FIELD_MISSING);
+                goto err;
+            }
+        }
+        /* Save encoding */
+        if (!asn1_enc_save(pval, *in, p - *in, it))
+            goto auxerr;
+        if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL))
+            goto auxerr;
+        *in = p;
+        return 1;
 
-		/* If we get here we've got no more data in the SEQUENCE,
-		 * however we may not have read all fields so check all
-		 * remaining are OPTIONAL and clear any that are.
-		 */
-		for (; i < it->tcount; tt++, i++)
-			{
-			const ASN1_TEMPLATE *seqtt;
-			seqtt = asn1_do_adb(pval, tt, 1);
-			if (!seqtt)
-				goto err;
-			if (seqtt->flags & ASN1_TFLG_OPTIONAL)
-				{
-				ASN1_VALUE **pseqval;
-				pseqval = asn1_get_field_ptr(pval, seqtt);
-				ASN1_template_free(pseqval, seqtt);
-				}
-			else
-				{
-				errtt = seqtt;
-				OPENSSL_PUT_ERROR(ASN1, ASN1_R_FIELD_MISSING);
-				goto err;
-				}
-			}
-		/* Save encoding */
-		if (!asn1_enc_save(pval, *in, p - *in, it))
-			goto auxerr;
-		if (asn1_cb && !asn1_cb(ASN1_OP_D2I_POST, pval, it, NULL))
-				goto auxerr;
-		*in = p;
-		return 1;
+    default:
+        return 0;
+    }
+ auxerr:
+    OPENSSL_PUT_ERROR(ASN1, ASN1_R_AUX_ERROR);
+ err:
+    if (combine == 0)
+        ASN1_item_ex_free(pval, it);
+    if (errtt)
+        ERR_add_error_data(4, "Field=", errtt->field_name,
+                           ", Type=", it->sname);
+    else
+        ERR_add_error_data(2, "Type=", it->sname);
+    return 0;
+}
 
-		default:
-		return 0;
-		}
-	auxerr:
-	OPENSSL_PUT_ERROR(ASN1, ASN1_R_AUX_ERROR);
-	err:
-	if (combine == 0)
-		ASN1_item_ex_free(pval, it);
-	if (errtt)
-		ERR_add_error_data(4, "Field=", errtt->field_name,
-					", Type=", it->sname);
-	else
-		ERR_add_error_data(2, "Type=", it->sname);
-	return 0;
-	}
-
-/* Templates are handled with two separate functions.
- * One handles any EXPLICIT tag and the other handles the rest.
+/*
+ * Templates are handled with two separate functions. One handles any
+ * EXPLICIT tag and the other handles the rest.
  */
 
 static int asn1_template_ex_d2i(ASN1_VALUE **val,
-				const unsigned char **in, long inlen,
-				const ASN1_TEMPLATE *tt, char opt,
-							ASN1_TLC *ctx)
-	{
-	int flags, aclass;
-	int ret;
-	long len;
-	const unsigned char *p, *q;
-	char exp_eoc;
-	if (!val)
-		return 0;
-	flags = tt->flags;
-	aclass = flags & ASN1_TFLG_TAG_CLASS;
+                                const unsigned char **in, long inlen,
+                                const ASN1_TEMPLATE *tt, char opt,
+                                ASN1_TLC *ctx)
+{
+    int flags, aclass;
+    int ret;
+    long len;
+    const unsigned char *p, *q;
+    char exp_eoc;
+    if (!val)
+        return 0;
+    flags = tt->flags;
+    aclass = flags & ASN1_TFLG_TAG_CLASS;
 
-	p = *in;
+    p = *in;
 
-	/* Check if EXPLICIT tag expected */
-	if (flags & ASN1_TFLG_EXPTAG)
-		{
-		char cst;
-		/* Need to work out amount of data available to the inner
-		 * content and where it starts: so read in EXPLICIT header to
-		 * get the info.
-		 */
-		ret = asn1_check_tlen(&len, NULL, NULL, &exp_eoc, &cst,
-					&p, inlen, tt->tag, aclass, opt, ctx);
-		q = p;
-		if (!ret)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
-			return 0;
-			}
-		else if (ret == -1)
-			return -1;
-		if (!cst)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED);
-			return 0;
-			}
-		/* We've found the field so it can't be OPTIONAL now */
-		ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx);
-		if (!ret)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
-			return 0;
-			}
-		/* We read the field in OK so update length */
-		len -= p - q;
-		if (exp_eoc)
-			{
-			/* If NDEF we must have an EOC here */
-			if (!asn1_check_eoc(&p, len))
-				{
-				OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_EOC);
-				goto err;
-				}
-			}
-		else
-			{
-			/* Otherwise we must hit the EXPLICIT tag end or its
-			 * an error */
-			if (len)
-				{
-				OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPLICIT_LENGTH_MISMATCH);
-				goto err;
-				}
-			}
-		}
-		else 
-			return asn1_template_noexp_d2i(val, in, inlen,
-								tt, opt, ctx);
+    /* Check if EXPLICIT tag expected */
+    if (flags & ASN1_TFLG_EXPTAG) {
+        char cst;
+        /*
+         * Need to work out amount of data available to the inner content and
+         * where it starts: so read in EXPLICIT header to get the info.
+         */
+        ret = asn1_check_tlen(&len, NULL, NULL, &exp_eoc, &cst,
+                              &p, inlen, tt->tag, aclass, opt, ctx);
+        q = p;
+        if (!ret) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+            return 0;
+        } else if (ret == -1)
+            return -1;
+        if (!cst) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED);
+            return 0;
+        }
+        /* We've found the field so it can't be OPTIONAL now */
+        ret = asn1_template_noexp_d2i(val, &p, len, tt, 0, ctx);
+        if (!ret) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+            return 0;
+        }
+        /* We read the field in OK so update length */
+        len -= p - q;
+        if (exp_eoc) {
+            /* If NDEF we must have an EOC here */
+            if (!asn1_check_eoc(&p, len)) {
+                OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_EOC);
+                goto err;
+            }
+        } else {
+            /*
+             * Otherwise we must hit the EXPLICIT tag end or its an error
+             */
+            if (len) {
+                OPENSSL_PUT_ERROR(ASN1, ASN1_R_EXPLICIT_LENGTH_MISMATCH);
+                goto err;
+            }
+        }
+    } else
+        return asn1_template_noexp_d2i(val, in, inlen, tt, opt, ctx);
 
-	*in = p;
-	return 1;
+    *in = p;
+    return 1;
 
-	err:
-	ASN1_template_free(val, tt);
-	return 0;
-	}
+ err:
+    ASN1_template_free(val, tt);
+    return 0;
+}
 
 static int asn1_template_noexp_d2i(ASN1_VALUE **val,
-				const unsigned char **in, long len,
-				const ASN1_TEMPLATE *tt, char opt,
-				ASN1_TLC *ctx)
-	{
-	int flags, aclass;
-	int ret;
-	const unsigned char *p;
-	if (!val)
-		return 0;
-	flags = tt->flags;
-	aclass = flags & ASN1_TFLG_TAG_CLASS;
+                                   const unsigned char **in, long len,
+                                   const ASN1_TEMPLATE *tt, char opt,
+                                   ASN1_TLC *ctx)
+{
+    int flags, aclass;
+    int ret;
+    const unsigned char *p;
+    if (!val)
+        return 0;
+    flags = tt->flags;
+    aclass = flags & ASN1_TFLG_TAG_CLASS;
 
-	p = *in;
+    p = *in;
 
-	if (flags & ASN1_TFLG_SK_MASK)
-		{
-		/* SET OF, SEQUENCE OF */
-		int sktag, skaclass;
-		char sk_eoc;
-		/* First work out expected inner tag value */
-		if (flags & ASN1_TFLG_IMPTAG)
-			{
-			sktag = tt->tag;
-			skaclass = aclass;
-			}
-		else
-			{
-			skaclass = V_ASN1_UNIVERSAL;
-			if (flags & ASN1_TFLG_SET_OF)
-				sktag = V_ASN1_SET;
-			else
-				sktag = V_ASN1_SEQUENCE;
-			}
-		/* Get the tag */
-		ret = asn1_check_tlen(&len, NULL, NULL, &sk_eoc, NULL,
-					&p, len, sktag, skaclass, opt, ctx);
-		if (!ret)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
-			return 0;
-			}
-		else if (ret == -1)
-			return -1;
-		if (!*val)
-			*val = (ASN1_VALUE *)sk_new_null();
-		else
-			{
-			/* We've got a valid STACK: free up any items present */
-			STACK_OF(ASN1_VALUE) *sktmp
-			    = (STACK_OF(ASN1_VALUE) *)*val;
-			ASN1_VALUE *vtmp;
-			while(sk_ASN1_VALUE_num(sktmp) > 0)
-				{
-				vtmp = sk_ASN1_VALUE_pop(sktmp);
-				ASN1_item_ex_free(&vtmp,
-						ASN1_ITEM_ptr(tt->item));
-				}
-			}
-				
-		if (!*val)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-			goto err;
-			}
+    if (flags & ASN1_TFLG_SK_MASK) {
+        /* SET OF, SEQUENCE OF */
+        int sktag, skaclass;
+        char sk_eoc;
+        /* First work out expected inner tag value */
+        if (flags & ASN1_TFLG_IMPTAG) {
+            sktag = tt->tag;
+            skaclass = aclass;
+        } else {
+            skaclass = V_ASN1_UNIVERSAL;
+            if (flags & ASN1_TFLG_SET_OF)
+                sktag = V_ASN1_SET;
+            else
+                sktag = V_ASN1_SEQUENCE;
+        }
+        /* Get the tag */
+        ret = asn1_check_tlen(&len, NULL, NULL, &sk_eoc, NULL,
+                              &p, len, sktag, skaclass, opt, ctx);
+        if (!ret) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+            return 0;
+        } else if (ret == -1)
+            return -1;
+        if (!*val)
+            *val = (ASN1_VALUE *)sk_new_null();
+        else {
+            /*
+             * We've got a valid STACK: free up any items present
+             */
+            STACK_OF(ASN1_VALUE) *sktmp = (STACK_OF(ASN1_VALUE) *)*val;
+            ASN1_VALUE *vtmp;
+            while (sk_ASN1_VALUE_num(sktmp) > 0) {
+                vtmp = sk_ASN1_VALUE_pop(sktmp);
+                ASN1_item_ex_free(&vtmp, ASN1_ITEM_ptr(tt->item));
+            }
+        }
 
-		/* Read as many items as we can */
-		while(len > 0)
-			{
-			ASN1_VALUE *skfield;
-			const unsigned char *q = p;
-			/* See if EOC found */
-			if (asn1_check_eoc(&p, len))
-				{
-				if (!sk_eoc)
-					{
-					OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNEXPECTED_EOC);
-					goto err;
-					}
-				len -= p - q;
-				sk_eoc = 0;
-				break;
-				}
-			skfield = NULL;
-			if (!ASN1_item_ex_d2i(&skfield, &p, len,
-						ASN1_ITEM_ptr(tt->item),
-						-1, 0, 0, ctx))
-				{
-				OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
-				goto err;
-				}
-			len -= p - q;
-			if (!sk_ASN1_VALUE_push((STACK_OF(ASN1_VALUE) *)*val,
-						skfield))
-				{
-				OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-				goto err;
-				}
-			}
-		if (sk_eoc)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_EOC);
-			goto err;
-			}
-		}
-	else if (flags & ASN1_TFLG_IMPTAG)
-		{
-		/* IMPLICIT tagging */
-		ret = ASN1_item_ex_d2i(val, &p, len,
-			ASN1_ITEM_ptr(tt->item), tt->tag, aclass, opt, ctx);
-		if (!ret)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
-			goto err;
-			}
-		else if (ret == -1)
-			return -1;
-		}
-	else
-		{
-		/* Nothing special */
-		ret = ASN1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item),
-							-1, tt->flags & ASN1_TFLG_COMBINE, opt, ctx);
-		if (!ret)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
-			goto err;
-			}
-		else if (ret == -1)
-			return -1;
-		}
+        if (!*val) {
+            OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+            goto err;
+        }
 
-	*in = p;
-	return 1;
+        /* Read as many items as we can */
+        while (len > 0) {
+            ASN1_VALUE *skfield;
+            const unsigned char *q = p;
+            /* See if EOC found */
+            if (asn1_check_eoc(&p, len)) {
+                if (!sk_eoc) {
+                    OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNEXPECTED_EOC);
+                    goto err;
+                }
+                len -= p - q;
+                sk_eoc = 0;
+                break;
+            }
+            skfield = NULL;
+            if (!ASN1_item_ex_d2i(&skfield, &p, len,
+                                  ASN1_ITEM_ptr(tt->item), -1, 0, 0, ctx)) {
+                OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+                goto err;
+            }
+            len -= p - q;
+            if (!sk_ASN1_VALUE_push((STACK_OF(ASN1_VALUE) *)*val, skfield)) {
+                ASN1_item_ex_free(&skfield, ASN1_ITEM_ptr(tt->item));
+                OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+                goto err;
+            }
+        }
+        if (sk_eoc) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_EOC);
+            goto err;
+        }
+    } else if (flags & ASN1_TFLG_IMPTAG) {
+        /* IMPLICIT tagging */
+        ret = ASN1_item_ex_d2i(val, &p, len,
+                               ASN1_ITEM_ptr(tt->item), tt->tag, aclass, opt,
+                               ctx);
+        if (!ret) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+            goto err;
+        } else if (ret == -1)
+            return -1;
+    } else {
+        /* Nothing special */
+        ret = ASN1_item_ex_d2i(val, &p, len, ASN1_ITEM_ptr(tt->item),
+                               -1, tt->flags & ASN1_TFLG_COMBINE, opt, ctx);
+        if (!ret) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+            goto err;
+        } else if (ret == -1)
+            return -1;
+    }
 
-	err:
-	ASN1_template_free(val, tt);
-	return 0;
-	}
+    *in = p;
+    return 1;
+
+ err:
+    ASN1_template_free(val, tt);
+    return 0;
+}
 
 static int asn1_d2i_ex_primitive(ASN1_VALUE **pval,
-				const unsigned char **in, long inlen, 
-				const ASN1_ITEM *it,
-				int tag, int aclass, char opt, ASN1_TLC *ctx)
-        OPENSSL_SUPPRESS_POTENTIALLY_UNINITIALIZED_WARNINGS
-	{
-	int ret = 0, utype;
-	long plen;
-	char cst, inf, free_cont = 0;
-	const unsigned char *p;
-	BUF_MEM buf;
-	const unsigned char *cont = NULL;
-	long len; 
-	if (!pval)
-		{
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_NULL);
-		return 0; /* Should never happen */
-		}
+                                 const unsigned char **in, long inlen,
+                                 const ASN1_ITEM *it,
+                                 int tag, int aclass, char opt, ASN1_TLC *ctx)
+{
+    int ret = 0, utype;
+    long plen;
+    char cst, inf, free_cont = 0;
+    const unsigned char *p;
+    BUF_MEM buf = {0, NULL, 0 };
+    const unsigned char *cont = NULL;
+    long len;
+    if (!pval) {
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_NULL);
+        return 0;               /* Should never happen */
+    }
 
-	if (it->itype == ASN1_ITYPE_MSTRING)
-		{
-		utype = tag;
-		tag = -1;
-		}
-	else
-		utype = it->utype;
+    if (it->itype == ASN1_ITYPE_MSTRING) {
+        utype = tag;
+        tag = -1;
+    } else
+        utype = it->utype;
 
-	if (utype == V_ASN1_ANY)
-		{
-		/* If type is ANY need to figure out type from tag */
-		unsigned char oclass;
-		if (tag >= 0)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_TAGGED_ANY);
-			return 0;
-			}
-		if (opt)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OPTIONAL_ANY);
-			return 0;
-			}
-		p = *in;
-		ret = asn1_check_tlen(NULL, &utype, &oclass, NULL, NULL,
-					&p, inlen, -1, 0, 0, ctx);
-		if (!ret)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
-			return 0;
-			}
-		if (oclass != V_ASN1_UNIVERSAL)
-			utype = V_ASN1_OTHER;
-		}
-	if (tag == -1)
-		{
-		tag = utype;
-		aclass = V_ASN1_UNIVERSAL;
-		}
-	p = *in;
-	/* Check header */
-	ret = asn1_check_tlen(&plen, NULL, NULL, &inf, &cst,
-				&p, inlen, tag, aclass, opt, ctx);
-	if (!ret)
-		{
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
-		return 0;
-		}
-	else if (ret == -1)
-		return -1;
-        ret = 0;
-	/* SEQUENCE, SET and "OTHER" are left in encoded form */
-	if ((utype == V_ASN1_SEQUENCE)
-		|| (utype == V_ASN1_SET) || (utype == V_ASN1_OTHER))
-		{
-		/* Clear context cache for type OTHER because the auto clear
-		 * when we have a exact match wont work
-		 */
-		if (utype == V_ASN1_OTHER)
-			{
-			asn1_tlc_clear(ctx);
-			}
-		/* SEQUENCE and SET must be constructed */
-		else if (!cst)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_CONSTRUCTED);
-			return 0;
-			}
+    if (utype == V_ASN1_ANY) {
+        /* If type is ANY need to figure out type from tag */
+        unsigned char oclass;
+        if (tag >= 0) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_TAGGED_ANY);
+            return 0;
+        }
+        if (opt) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OPTIONAL_ANY);
+            return 0;
+        }
+        p = *in;
+        ret = asn1_check_tlen(NULL, &utype, &oclass, NULL, NULL,
+                              &p, inlen, -1, 0, 0, ctx);
+        if (!ret) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+            return 0;
+        }
+        if (oclass != V_ASN1_UNIVERSAL)
+            utype = V_ASN1_OTHER;
+    }
+    if (tag == -1) {
+        tag = utype;
+        aclass = V_ASN1_UNIVERSAL;
+    }
+    p = *in;
+    /* Check header */
+    ret = asn1_check_tlen(&plen, NULL, NULL, &inf, &cst,
+                          &p, inlen, tag, aclass, opt, ctx);
+    if (!ret) {
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+        return 0;
+    } else if (ret == -1)
+        return -1;
+    ret = 0;
+    /* SEQUENCE, SET and "OTHER" are left in encoded form */
+    if ((utype == V_ASN1_SEQUENCE)
+        || (utype == V_ASN1_SET) || (utype == V_ASN1_OTHER)) {
+        /*
+         * Clear context cache for type OTHER because the auto clear when we
+         * have a exact match wont work
+         */
+        if (utype == V_ASN1_OTHER) {
+            asn1_tlc_clear(ctx);
+        }
+        /* SEQUENCE and SET must be constructed */
+        else if (!cst) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_CONSTRUCTED);
+            return 0;
+        }
 
-		cont = *in;
-		/* If indefinite length constructed find the real end */
-		if (inf)
-			{
-			if (!asn1_find_end(&p, plen, inf))
-				 goto err;
-			len = p - cont;
-			}
-		else
-			{
-			len = p - cont + plen;
-			p += plen;
-			buf.data = NULL;
-			}
-		}
-	else if (cst)
-		{
-		if (utype == V_ASN1_NULL || utype == V_ASN1_BOOLEAN
-			|| utype == V_ASN1_OBJECT || utype == V_ASN1_INTEGER
-			|| utype == V_ASN1_ENUMERATED)
-			{
-			/* These types only have primitive encodings. */
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_PRIMITIVE);
-			return 0;
-			}
+        cont = *in;
+        /* If indefinite length constructed find the real end */
+        if (inf) {
+            if (!asn1_find_end(&p, plen, inf))
+                goto err;
+            len = p - cont;
+        } else {
+            len = p - cont + plen;
+            p += plen;
+        }
+    } else if (cst) {
+        if (utype == V_ASN1_NULL || utype == V_ASN1_BOOLEAN
+            || utype == V_ASN1_OBJECT || utype == V_ASN1_INTEGER
+            || utype == V_ASN1_ENUMERATED) {
+            /* These types only have primitive encodings. */
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_TYPE_NOT_PRIMITIVE);
+            return 0;
+        }
 
-		buf.length = 0;
-		buf.max = 0;
-		buf.data = NULL;
-		/* Should really check the internal tags are correct but
-		 * some things may get this wrong. The relevant specs
-		 * say that constructed string types should be OCTET STRINGs
-		 * internally irrespective of the type. So instead just check
-		 * for UNIVERSAL class and ignore the tag.
-		 */
-		if (!asn1_collect(&buf, &p, plen, inf, -1, V_ASN1_UNIVERSAL, 0))
-			{
-			free_cont = 1;
-			goto err;
-			}
-		len = buf.length;
-		/* Append a final null to string */
-		if (!BUF_MEM_grow_clean(&buf, len + 1))
-			{
-			OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-			return 0;
-			}
-		buf.data[len] = 0;
-		cont = (const unsigned char *)buf.data;
-		free_cont = 1;
-		}
-	else
-		{
-		cont = p;
-		len = plen;
-		p += plen;
-		}
+        /* Free any returned 'buf' content */
+        free_cont = 1;
+        /*
+         * Should really check the internal tags are correct but some things
+         * may get this wrong. The relevant specs say that constructed string
+         * types should be OCTET STRINGs internally irrespective of the type.
+         * So instead just check for UNIVERSAL class and ignore the tag.
+         */
+        if (!asn1_collect(&buf, &p, plen, inf, -1, V_ASN1_UNIVERSAL, 0)) {
+            goto err;
+        }
+        len = buf.length;
+        /* Append a final null to string */
+        if (!BUF_MEM_grow_clean(&buf, len + 1)) {
+            OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+            goto err;
+        }
+        buf.data[len] = 0;
+        cont = (const unsigned char *)buf.data;
+    } else {
+        cont = p;
+        len = plen;
+        p += plen;
+    }
 
-	/* We now have content length and type: translate into a structure */
-	if (!asn1_ex_c2i(pval, cont, len, utype, &free_cont, it))
-		goto err;
+    /* We now have content length and type: translate into a structure */
+    /* asn1_ex_c2i may reuse allocated buffer, and so sets free_cont to 0 */
+    if (!asn1_ex_c2i(pval, cont, len, utype, &free_cont, it))
+        goto err;
 
-	*in = p;
-	ret = 1;
-	err:
-	if (free_cont && buf.data) OPENSSL_free(buf.data);
-	return ret;
-	}
+    *in = p;
+    ret = 1;
+ err:
+    if (free_cont && buf.data)
+        OPENSSL_free(buf.data);
+    return ret;
+}
 
 /* Translate ASN1 content octets into a structure */
 
 int asn1_ex_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
-			int utype, char *free_cont, const ASN1_ITEM *it)
-	{
-	ASN1_VALUE **opval = NULL;
-	ASN1_STRING *stmp;
-	ASN1_TYPE *typ = NULL;
-	int ret = 0;
-	const ASN1_PRIMITIVE_FUNCS *pf;
-	ASN1_INTEGER **tint;
-	pf = it->funcs;
+                int utype, char *free_cont, const ASN1_ITEM *it)
+{
+    ASN1_VALUE **opval = NULL;
+    ASN1_STRING *stmp;
+    ASN1_TYPE *typ = NULL;
+    int ret = 0;
+    const ASN1_PRIMITIVE_FUNCS *pf;
+    ASN1_INTEGER **tint;
+    pf = it->funcs;
 
-	if (pf && pf->prim_c2i)
-		return pf->prim_c2i(pval, cont, len, utype, free_cont, it);
-	/* If ANY type clear type and set pointer to internal value */
-	if (it->utype == V_ASN1_ANY)
-		{
-		if (!*pval)
-			{
-			typ = ASN1_TYPE_new();
-			if (typ == NULL)
-				goto err;
-			*pval = (ASN1_VALUE *)typ;
-			}
-		else
-			typ = (ASN1_TYPE *)*pval;
+    if (pf && pf->prim_c2i)
+        return pf->prim_c2i(pval, cont, len, utype, free_cont, it);
+    /* If ANY type clear type and set pointer to internal value */
+    if (it->utype == V_ASN1_ANY) {
+        if (!*pval) {
+            typ = ASN1_TYPE_new();
+            if (typ == NULL)
+                goto err;
+            *pval = (ASN1_VALUE *)typ;
+        } else
+            typ = (ASN1_TYPE *)*pval;
 
-		if (utype != typ->type)
-			ASN1_TYPE_set(typ, utype, NULL);
-		opval = pval;
-		pval = &typ->value.asn1_value;
-		}
-	switch(utype)
-		{
-		case V_ASN1_OBJECT:
-		if (!c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, len))
-			goto err;
-		break;
+        if (utype != typ->type)
+            ASN1_TYPE_set(typ, utype, NULL);
+        opval = pval;
+        pval = &typ->value.asn1_value;
+    }
+    switch (utype) {
+    case V_ASN1_OBJECT:
+        if (!c2i_ASN1_OBJECT((ASN1_OBJECT **)pval, &cont, len))
+            goto err;
+        break;
 
-		case V_ASN1_NULL:
-		if (len)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_NULL_IS_WRONG_LENGTH);
-			goto err;
-			}
-		*pval = (ASN1_VALUE *)1;
-		break;
+    case V_ASN1_NULL:
+        if (len) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_NULL_IS_WRONG_LENGTH);
+            goto err;
+        }
+        *pval = (ASN1_VALUE *)1;
+        break;
 
-		case V_ASN1_BOOLEAN:
-		if (len != 1)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_BOOLEAN_IS_WRONG_LENGTH);
-			goto err;
-			}
-		else
-			{
-			ASN1_BOOLEAN *tbool;
-			tbool = (ASN1_BOOLEAN *)pval;
-			*tbool = *cont;
-			}
-		break;
+    case V_ASN1_BOOLEAN:
+        if (len != 1) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_BOOLEAN_IS_WRONG_LENGTH);
+            goto err;
+        } else {
+            ASN1_BOOLEAN *tbool;
+            tbool = (ASN1_BOOLEAN *)pval;
+            *tbool = *cont;
+        }
+        break;
 
-		case V_ASN1_BIT_STRING:
-		if (!c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &cont, len))
-			goto err;
-		break;
+    case V_ASN1_BIT_STRING:
+        if (!c2i_ASN1_BIT_STRING((ASN1_BIT_STRING **)pval, &cont, len))
+            goto err;
+        break;
 
-		case V_ASN1_INTEGER:
-		case V_ASN1_NEG_INTEGER:
-		case V_ASN1_ENUMERATED:
-		case V_ASN1_NEG_ENUMERATED:
-		tint = (ASN1_INTEGER **)pval;
-		if (!c2i_ASN1_INTEGER(tint, &cont, len))
-			goto err;
-		/* Fixup type to match the expected form */
-		(*tint)->type = utype | ((*tint)->type & V_ASN1_NEG);
-		break;
+    case V_ASN1_INTEGER:
+    case V_ASN1_ENUMERATED:
+        tint = (ASN1_INTEGER **)pval;
+        if (!c2i_ASN1_INTEGER(tint, &cont, len))
+            goto err;
+        /* Fixup type to match the expected form */
+        (*tint)->type = utype | ((*tint)->type & V_ASN1_NEG);
+        break;
 
-		case V_ASN1_OCTET_STRING:
-		case V_ASN1_NUMERICSTRING:
-		case V_ASN1_PRINTABLESTRING:
-		case V_ASN1_T61STRING:
-		case V_ASN1_VIDEOTEXSTRING:
-		case V_ASN1_IA5STRING:
-		case V_ASN1_UTCTIME:
-		case V_ASN1_GENERALIZEDTIME:
-		case V_ASN1_GRAPHICSTRING:
-		case V_ASN1_VISIBLESTRING:
-		case V_ASN1_GENERALSTRING:
-		case V_ASN1_UNIVERSALSTRING:
-		case V_ASN1_BMPSTRING:
-		case V_ASN1_UTF8STRING:
-		case V_ASN1_OTHER:
-		case V_ASN1_SET:
-		case V_ASN1_SEQUENCE:
-		default:
-		if (utype == V_ASN1_BMPSTRING && (len & 1))
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_BMPSTRING_IS_WRONG_LENGTH);
-			goto err;
-			}
-		if (utype == V_ASN1_UNIVERSALSTRING && (len & 3))
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH);
-			goto err;
-			}
-		/* All based on ASN1_STRING and handled the same */
-		if (!*pval)
-			{
-			stmp = ASN1_STRING_type_new(utype);
-			if (!stmp)
-				{
-				OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-				goto err;
-				}
-			*pval = (ASN1_VALUE *)stmp;
-			}
-		else
-			{
-			stmp = (ASN1_STRING *)*pval;
-			stmp->type = utype;
-			}
-		/* If we've already allocated a buffer use it */
-		if (*free_cont)
-			{
-			if (stmp->data)
-				OPENSSL_free(stmp->data);
-			stmp->data = (unsigned char *)cont; /* UGLY CAST! RL */
-			stmp->length = len;
-			*free_cont = 0;
-			}
-		else
-			{
-			if (!ASN1_STRING_set(stmp, cont, len))
-				{
-				OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-				ASN1_STRING_free(stmp);	
-				*pval = NULL;
-				goto err;
-				}
-			}
-		break;
-		}
-	/* If ASN1_ANY and NULL type fix up value */
-	if (typ && (utype == V_ASN1_NULL))
-		 typ->value.ptr = NULL;
+    case V_ASN1_OCTET_STRING:
+    case V_ASN1_NUMERICSTRING:
+    case V_ASN1_PRINTABLESTRING:
+    case V_ASN1_T61STRING:
+    case V_ASN1_VIDEOTEXSTRING:
+    case V_ASN1_IA5STRING:
+    case V_ASN1_UTCTIME:
+    case V_ASN1_GENERALIZEDTIME:
+    case V_ASN1_GRAPHICSTRING:
+    case V_ASN1_VISIBLESTRING:
+    case V_ASN1_GENERALSTRING:
+    case V_ASN1_UNIVERSALSTRING:
+    case V_ASN1_BMPSTRING:
+    case V_ASN1_UTF8STRING:
+    case V_ASN1_OTHER:
+    case V_ASN1_SET:
+    case V_ASN1_SEQUENCE:
+    default:
+        if (utype == V_ASN1_BMPSTRING && (len & 1)) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_BMPSTRING_IS_WRONG_LENGTH);
+            goto err;
+        }
+        if (utype == V_ASN1_UNIVERSALSTRING && (len & 3)) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH);
+            goto err;
+        }
+        /* All based on ASN1_STRING and handled the same */
+        if (!*pval) {
+            stmp = ASN1_STRING_type_new(utype);
+            if (!stmp) {
+                OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+                goto err;
+            }
+            *pval = (ASN1_VALUE *)stmp;
+        } else {
+            stmp = (ASN1_STRING *)*pval;
+            stmp->type = utype;
+        }
+        /* If we've already allocated a buffer use it */
+        if (*free_cont) {
+            if (stmp->data)
+                OPENSSL_free(stmp->data);
+            stmp->data = (unsigned char *)cont; /* UGLY CAST! RL */
+            stmp->length = len;
+            *free_cont = 0;
+        } else {
+            if (!ASN1_STRING_set(stmp, cont, len)) {
+                OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+                ASN1_STRING_free(stmp);
+                *pval = NULL;
+                goto err;
+            }
+        }
+        break;
+    }
+    /* If ASN1_ANY and NULL type fix up value */
+    if (typ && (utype == V_ASN1_NULL))
+        typ->value.ptr = NULL;
 
-	ret = 1;
-	err:
-	if (!ret)
-		{
-		ASN1_TYPE_free(typ);
-		if (opval)
-			*opval = NULL;
-		}
-	return ret;
-	}
+    ret = 1;
+ err:
+    if (!ret) {
+        ASN1_TYPE_free(typ);
+        if (opval)
+            *opval = NULL;
+    }
+    return ret;
+}
 
-
-/* This function finds the end of an ASN1 structure when passed its maximum
- * length, whether it is indefinite length and a pointer to the content.
- * This is more efficient than calling asn1_collect because it does not
- * recurse on each indefinite length header.
+/*
+ * This function finds the end of an ASN1 structure when passed its maximum
+ * length, whether it is indefinite length and a pointer to the content. This
+ * is more efficient than calling asn1_collect because it does not recurse on
+ * each indefinite length header.
  */
 
 static int asn1_find_end(const unsigned char **in, long len, char inf)
-	{
-	int expected_eoc;
-	long plen;
-	const unsigned char *p = *in, *q;
-	/* If not indefinite length constructed just add length */
-	if (inf == 0)
-		{
-		*in += len;
-		return 1;
-		}
-	expected_eoc = 1;
-	/* Indefinite length constructed form. Find the end when enough EOCs
-	 * are found. If more indefinite length constructed headers
-	 * are encountered increment the expected eoc count otherwise just
-	 * skip to the end of the data.
-	 */
-	while (len > 0)
-		{
-		if(asn1_check_eoc(&p, len))
-			{
-			expected_eoc--;
-			if (expected_eoc == 0)
-				break;
-			len -= 2;
-			continue;
-			}
-		q = p;
-		/* Just read in a header: only care about the length */
-		if(!asn1_check_tlen(&plen, NULL, NULL, &inf, NULL, &p, len,
-				-1, 0, 0, NULL))
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
-			return 0;
-			}
-		if (inf)
-			expected_eoc++;
-		else
-			p += plen;
-		len -= p - q;
-		}
-	if (expected_eoc)
-		{
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_EOC);
-		return 0;
-		}
-	*in = p;
-	return 1;
-	}
-/* This function collects the asn1 data from a constructred string
- * type into a buffer. The values of 'in' and 'len' should refer
- * to the contents of the constructed type and 'inf' should be set
- * if it is indefinite length.
+{
+    int expected_eoc;
+    long plen;
+    const unsigned char *p = *in, *q;
+    /* If not indefinite length constructed just add length */
+    if (inf == 0) {
+        *in += len;
+        return 1;
+    }
+    expected_eoc = 1;
+    /*
+     * Indefinite length constructed form. Find the end when enough EOCs are
+     * found. If more indefinite length constructed headers are encountered
+     * increment the expected eoc count otherwise just skip to the end of the
+     * data.
+     */
+    while (len > 0) {
+        if (asn1_check_eoc(&p, len)) {
+            expected_eoc--;
+            if (expected_eoc == 0)
+                break;
+            len -= 2;
+            continue;
+        }
+        q = p;
+        /* Just read in a header: only care about the length */
+        if (!asn1_check_tlen(&plen, NULL, NULL, &inf, NULL, &p, len,
+                             -1, 0, 0, NULL)) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+            return 0;
+        }
+        if (inf)
+            expected_eoc++;
+        else
+            p += plen;
+        len -= p - q;
+    }
+    if (expected_eoc) {
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_EOC);
+        return 0;
+    }
+    *in = p;
+    return 1;
+}
+
+/*
+ * This function collects the asn1 data from a constructred string type into
+ * a buffer. The values of 'in' and 'len' should refer to the contents of the
+ * constructed type and 'inf' should be set if it is indefinite length.
  */
 
 #ifndef ASN1_MAX_STRING_NEST
-/* This determines how many levels of recursion are permitted in ASN1
- * string types. If it is not limited stack overflows can occur. If set
- * to zero no recursion is allowed at all. Although zero should be adequate
- * examples exist that require a value of 1. So 5 should be more than enough.
+/*
+ * This determines how many levels of recursion are permitted in ASN1 string
+ * types. If it is not limited stack overflows can occur. If set to zero no
+ * recursion is allowed at all. Although zero should be adequate examples
+ * exist that require a value of 1. So 5 should be more than enough.
  */
-#define ASN1_MAX_STRING_NEST 5
+# define ASN1_MAX_STRING_NEST 5
 #endif
 
-
 static int asn1_collect(BUF_MEM *buf, const unsigned char **in, long len,
-			char inf, int tag, int aclass, int depth)
-	{
-	const unsigned char *p, *q;
-	long plen;
-	char cst, ininf;
-	p = *in;
-	inf &= 1;
-	/* If no buffer and not indefinite length constructed just pass over
-	 * the encoded data */
-	if (!buf && !inf)
-		{
-		*in += len;
-		return 1;
-		}
-	while(len > 0)
-		{
-		q = p;
-		/* Check for EOC */
-		if (asn1_check_eoc(&p, len))
-			{
-			/* EOC is illegal outside indefinite length
-			 * constructed form */
-			if (!inf)
-				{
-				OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNEXPECTED_EOC);
-				return 0;
-				}
-			inf = 0;
-			break;
-			}
+                        char inf, int tag, int aclass, int depth)
+{
+    const unsigned char *p, *q;
+    long plen;
+    char cst, ininf;
+    p = *in;
+    inf &= 1;
+    /*
+     * If no buffer and not indefinite length constructed just pass over the
+     * encoded data
+     */
+    if (!buf && !inf) {
+        *in += len;
+        return 1;
+    }
+    while (len > 0) {
+        q = p;
+        /* Check for EOC */
+        if (asn1_check_eoc(&p, len)) {
+            /*
+             * EOC is illegal outside indefinite length constructed form
+             */
+            if (!inf) {
+                OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNEXPECTED_EOC);
+                return 0;
+            }
+            inf = 0;
+            break;
+        }
 
-		if (!asn1_check_tlen(&plen, NULL, NULL, &ininf, &cst, &p,
-					len, tag, aclass, 0, NULL))
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
-			return 0;
-			}
+        if (!asn1_check_tlen(&plen, NULL, NULL, &ininf, &cst, &p,
+                             len, tag, aclass, 0, NULL)) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_ERROR);
+            return 0;
+        }
 
-		/* If indefinite length constructed update max length */
-		if (cst)
-			{
-			if (depth >= ASN1_MAX_STRING_NEST)
-				{
-				OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_STRING);
-				return 0;
-				}
-			if (!asn1_collect(buf, &p, plen, ininf, tag, aclass,
-						depth + 1))
-				return 0;
-			}
-		else if (plen && !collect_data(buf, &p, plen))
-			return 0;
-		len -= p - q;
-		}
-	if (inf)
-		{
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_EOC);
-		return 0;
-		}
-	*in = p;
-	return 1;
-	}
+        /* If indefinite length constructed update max length */
+        if (cst) {
+            if (depth >= ASN1_MAX_STRING_NEST) {
+                OPENSSL_PUT_ERROR(ASN1, ASN1_R_NESTED_ASN1_STRING);
+                return 0;
+            }
+            if (!asn1_collect(buf, &p, plen, ininf, tag, aclass, depth + 1))
+                return 0;
+        } else if (plen && !collect_data(buf, &p, plen))
+            return 0;
+        len -= p - q;
+    }
+    if (inf) {
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_EOC);
+        return 0;
+    }
+    *in = p;
+    return 1;
+}
 
 static int collect_data(BUF_MEM *buf, const unsigned char **p, long plen)
-	{
-	int len;
-	if (buf)
-		{
-		len = buf->length;
-		if (!BUF_MEM_grow_clean(buf, len + plen))
-			{
-			OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-			return 0;
-			}
-		memcpy(buf->data + len, *p, plen);
-		}
-	*p += plen;
-	return 1;
-	}
+{
+    int len;
+    if (buf) {
+        len = buf->length;
+        if (!BUF_MEM_grow_clean(buf, len + plen)) {
+            OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+            return 0;
+        }
+        OPENSSL_memcpy(buf->data + len, *p, plen);
+    }
+    *p += plen;
+    return 1;
+}
 
 /* Check for ASN1 EOC and swallow it if found */
 
 static int asn1_check_eoc(const unsigned char **in, long len)
-	{
-	const unsigned char *p;
-	if (len < 2) return 0;
-	p = *in;
-	if (!p[0] && !p[1])
-		{
-		*in += 2;
-		return 1;
-		}
-	return 0;
-	}
+{
+    const unsigned char *p;
+    if (len < 2)
+        return 0;
+    p = *in;
+    if (!p[0] && !p[1]) {
+        *in += 2;
+        return 1;
+    }
+    return 0;
+}
 
-/* Check an ASN1 tag and length: a bit like ASN1_get_object
- * but it sets the length for indefinite length constructed
- * form, we don't know the exact length but we can set an
- * upper bound to the amount of data available minus the
- * header length just read.
+/*
+ * Check an ASN1 tag and length: a bit like ASN1_get_object but it sets the
+ * length for indefinite length constructed form, we don't know the exact
+ * length but we can set an upper bound to the amount of data available minus
+ * the header length just read.
  */
 
 static int asn1_check_tlen(long *olen, int *otag, unsigned char *oclass,
-				char *inf, char *cst,
-				const unsigned char **in, long len,
-				int exptag, int expclass, char opt,
-				ASN1_TLC *ctx)
-	{
-	int i;
-	int ptag, pclass;
-	long plen;
-	const unsigned char *p, *q;
-	p = *in;
-	q = p;
+                           char *inf, char *cst,
+                           const unsigned char **in, long len,
+                           int exptag, int expclass, char opt, ASN1_TLC *ctx)
+{
+    int i;
+    int ptag, pclass;
+    long plen;
+    const unsigned char *p, *q;
+    p = *in;
+    q = p;
 
-	if (ctx && ctx->valid)
-		{
-		i = ctx->ret;
-		plen = ctx->plen;
-		pclass = ctx->pclass;
-		ptag = ctx->ptag;
-		p += ctx->hdrlen;
-		}
-	else
-		{
-		i = ASN1_get_object(&p, &plen, &ptag, &pclass, len);
-		if (ctx)
-			{
-			ctx->ret = i;
-			ctx->plen = plen;
-			ctx->pclass = pclass;
-			ctx->ptag = ptag;
-			ctx->hdrlen = p - q;
-			ctx->valid = 1;
-			/* If definite length, and no error, length +
-			 * header can't exceed total amount of data available. 
-			 */
-			if (!(i & 0x81) && ((plen + ctx->hdrlen) > len))
-				{
-				OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
-				asn1_tlc_clear(ctx);
-				return 0;
-				}
-			}
-		}
+    if (ctx && ctx->valid) {
+        i = ctx->ret;
+        plen = ctx->plen;
+        pclass = ctx->pclass;
+        ptag = ctx->ptag;
+        p += ctx->hdrlen;
+    } else {
+        i = ASN1_get_object(&p, &plen, &ptag, &pclass, len);
+        if (ctx) {
+            ctx->ret = i;
+            ctx->plen = plen;
+            ctx->pclass = pclass;
+            ctx->ptag = ptag;
+            ctx->hdrlen = p - q;
+            ctx->valid = 1;
+            /*
+             * If definite length, and no error, length + header can't exceed
+             * total amount of data available.
+             */
+            if (!(i & 0x81) && ((plen + ctx->hdrlen) > len)) {
+                OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
+                asn1_tlc_clear(ctx);
+                return 0;
+            }
+        }
+    }
 
-	if (i & 0x80)
-		{
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_OBJECT_HEADER);
-		asn1_tlc_clear(ctx);
-		return 0;
-		}
-	if (exptag >= 0)
-		{
-		if ((exptag != ptag) || (expclass != pclass))
-			{
-			/* If type is OPTIONAL, not an error:
-			 * indicate missing type.
-			 */
-			if (opt) return -1;
-			asn1_tlc_clear(ctx);
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TAG);
-			return 0;
-			}
-		/* We have a tag and class match:
-		 * assume we are going to do something with it */
-		asn1_tlc_clear(ctx);
-		}
+    if (i & 0x80) {
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_BAD_OBJECT_HEADER);
+        asn1_tlc_clear(ctx);
+        return 0;
+    }
+    if (exptag >= 0) {
+        if ((exptag != ptag) || (expclass != pclass)) {
+            /*
+             * If type is OPTIONAL, not an error: indicate missing type.
+             */
+            if (opt)
+                return -1;
+            asn1_tlc_clear(ctx);
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TAG);
+            return 0;
+        }
+        /*
+         * We have a tag and class match: assume we are going to do something
+         * with it
+         */
+        asn1_tlc_clear(ctx);
+    }
 
-	if (i & 1)
-		plen = len - (p - q);
+    if (i & 1)
+        plen = len - (p - q);
 
-	if (inf)
-		*inf = i & 1;
+    if (inf)
+        *inf = i & 1;
 
-	if (cst)
-		*cst = i & V_ASN1_CONSTRUCTED;
+    if (cst)
+        *cst = i & V_ASN1_CONSTRUCTED;
 
-	if (olen)
-		*olen = plen;
+    if (olen)
+        *olen = plen;
 
-	if (oclass)
-		*oclass = pclass;
+    if (oclass)
+        *oclass = pclass;
 
-	if (otag)
-		*otag = ptag;
+    if (otag)
+        *otag = ptag;
 
-	*in = p;
-	return 1;
-	}
+    *in = p;
+    return 1;
+}
diff --git a/src/crypto/asn1/tasn_enc.c b/src/crypto/asn1/tasn_enc.c
index 38e14d2..9286ef6 100644
--- a/src/crypto/asn1/tasn_enc.c
+++ b/src/crypto/asn1/tasn_enc.c
@@ -56,640 +56,613 @@
 
 #include <openssl/asn1.h>
 
+#include <limits.h>
 #include <string.h>
 
 #include <openssl/asn1t.h>
 #include <openssl/mem.h>
 
+#include "../internal.h"
+
 
 static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
-					const ASN1_ITEM *it,
-					int tag, int aclass);
+                                 const ASN1_ITEM *it, int tag, int aclass);
 static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
-					int skcontlen, const ASN1_ITEM *item,
-					int do_sort, int iclass);
+                            int skcontlen, const ASN1_ITEM *item,
+                            int do_sort, int iclass);
 static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
-					const ASN1_TEMPLATE *tt,
-					int tag, int aclass);
+                                const ASN1_TEMPLATE *tt, int tag, int aclass);
 static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
-					const ASN1_ITEM *it, int flags);
+                               const ASN1_ITEM *it, int flags);
 
-/* Top level i2d equivalents: the 'ndef' variant instructs the encoder
- * to use indefinite length constructed encoding, where appropriate
+/*
+ * Top level i2d equivalents: the 'ndef' variant instructs the encoder to use
+ * indefinite length constructed encoding, where appropriate
  */
 
 int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out,
-						const ASN1_ITEM *it)
-	{
-	return asn1_item_flags_i2d(val, out, it, ASN1_TFLG_NDEF);
-	}
+                       const ASN1_ITEM *it)
+{
+    return asn1_item_flags_i2d(val, out, it, ASN1_TFLG_NDEF);
+}
 
 int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it)
-	{
-	return asn1_item_flags_i2d(val, out, it, 0);
-	}
+{
+    return asn1_item_flags_i2d(val, out, it, 0);
+}
 
-/* Encode an ASN1 item, this is use by the
- * standard 'i2d' function. 'out' points to 
- * a buffer to output the data to.
- *
- * The new i2d has one additional feature. If the output
- * buffer is NULL (i.e. *out == NULL) then a buffer is
+/*
+ * Encode an ASN1 item, this is use by the standard 'i2d' function. 'out'
+ * points to a buffer to output the data to. The new i2d has one additional
+ * feature. If the output buffer is NULL (i.e. *out == NULL) then a buffer is
  * allocated and populated with the encoding.
  */
 
 static int asn1_item_flags_i2d(ASN1_VALUE *val, unsigned char **out,
-					const ASN1_ITEM *it, int flags)
-	{
-	if (out && !*out)
-		{
-		unsigned char *p, *buf;
-		int len;
-		len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags);
-		if (len <= 0)
-			return len;
-		buf = OPENSSL_malloc(len);
-		if (!buf)
-			return -1;
-		p = buf;
-		ASN1_item_ex_i2d(&val, &p, it, -1, flags);
-		*out = buf;
-		return len;
-		}
+                               const ASN1_ITEM *it, int flags)
+{
+    if (out && !*out) {
+        unsigned char *p, *buf;
+        int len;
+        len = ASN1_item_ex_i2d(&val, NULL, it, -1, flags);
+        if (len <= 0)
+            return len;
+        buf = OPENSSL_malloc(len);
+        if (!buf)
+            return -1;
+        p = buf;
+        ASN1_item_ex_i2d(&val, &p, it, -1, flags);
+        *out = buf;
+        return len;
+    }
 
-	return ASN1_item_ex_i2d(&val, out, it, -1, flags);
-	}
+    return ASN1_item_ex_i2d(&val, out, it, -1, flags);
+}
 
-/* Encode an item, taking care of IMPLICIT tagging (if any).
- * This function performs the normal item handling: it can be
- * used in external types.
+/*
+ * Encode an item, taking care of IMPLICIT tagging (if any). This function
+ * performs the normal item handling: it can be used in external types.
  */
 
 int ASN1_item_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
-			const ASN1_ITEM *it, int tag, int aclass)
-	{
-	const ASN1_TEMPLATE *tt = NULL;
-	unsigned char *p = NULL;
-	int i, seqcontlen, seqlen, ndef = 1;
-	const ASN1_COMPAT_FUNCS *cf;
-	const ASN1_EXTERN_FUNCS *ef;
-	const ASN1_AUX *aux = it->funcs;
-	ASN1_aux_cb *asn1_cb = 0;
+                     const ASN1_ITEM *it, int tag, int aclass)
+{
+    const ASN1_TEMPLATE *tt = NULL;
+    unsigned char *p = NULL;
+    int i, seqcontlen, seqlen, ndef = 1;
+    const ASN1_COMPAT_FUNCS *cf;
+    const ASN1_EXTERN_FUNCS *ef;
+    const ASN1_AUX *aux = it->funcs;
+    ASN1_aux_cb *asn1_cb = 0;
 
-	if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
-		return 0;
+    if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
+        return 0;
 
-	if (aux && aux->asn1_cb)
-		 asn1_cb = aux->asn1_cb;
+    if (aux && aux->asn1_cb)
+        asn1_cb = aux->asn1_cb;
 
-	switch(it->itype)
-		{
+    switch (it->itype) {
 
-		case ASN1_ITYPE_PRIMITIVE:
-		if (it->templates)
-			return asn1_template_ex_i2d(pval, out, it->templates,
-								tag, aclass);
-		return asn1_i2d_ex_primitive(pval, out, it, tag, aclass);
-		break;
+    case ASN1_ITYPE_PRIMITIVE:
+        if (it->templates)
+            return asn1_template_ex_i2d(pval, out, it->templates,
+                                        tag, aclass);
+        return asn1_i2d_ex_primitive(pval, out, it, tag, aclass);
+        break;
 
-		case ASN1_ITYPE_MSTRING:
-		return asn1_i2d_ex_primitive(pval, out, it, -1, aclass);
+    case ASN1_ITYPE_MSTRING:
+        return asn1_i2d_ex_primitive(pval, out, it, -1, aclass);
 
-		case ASN1_ITYPE_CHOICE:
-		if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
-				return 0;
-		i = asn1_get_choice_selector(pval, it);
-		if ((i >= 0) && (i < it->tcount))
-			{
-			ASN1_VALUE **pchval;
-			const ASN1_TEMPLATE *chtt;
-			chtt = it->templates + i;
-			pchval = asn1_get_field_ptr(pval, chtt);
-			return asn1_template_ex_i2d(pchval, out, chtt,
-								-1, aclass);
-			}
-		/* Fixme: error condition if selector out of range */
-		if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
-				return 0;
-		break;
+    case ASN1_ITYPE_CHOICE:
+        if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
+            return 0;
+        i = asn1_get_choice_selector(pval, it);
+        if ((i >= 0) && (i < it->tcount)) {
+            ASN1_VALUE **pchval;
+            const ASN1_TEMPLATE *chtt;
+            chtt = it->templates + i;
+            pchval = asn1_get_field_ptr(pval, chtt);
+            return asn1_template_ex_i2d(pchval, out, chtt, -1, aclass);
+        }
+        /* Fixme: error condition if selector out of range */
+        if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
+            return 0;
+        break;
 
-		case ASN1_ITYPE_EXTERN:
-		/* If new style i2d it does all the work */
-		ef = it->funcs;
-		return ef->asn1_ex_i2d(pval, out, it, tag, aclass);
+    case ASN1_ITYPE_EXTERN:
+        /* If new style i2d it does all the work */
+        ef = it->funcs;
+        return ef->asn1_ex_i2d(pval, out, it, tag, aclass);
 
-		case ASN1_ITYPE_COMPAT:
-		/* old style hackery... */
-		cf = it->funcs;
-		if (out)
-			p = *out;
-		i = cf->asn1_i2d(*pval, out);
-		/* Fixup for IMPLICIT tag: note this messes up for tags > 30,
-		 * but so did the old code. Tags > 30 are very rare anyway.
-		 */
-		if (out && (tag != -1))
-			*p = aclass | tag | (*p & V_ASN1_CONSTRUCTED);
-		return i;
-		
-		case ASN1_ITYPE_NDEF_SEQUENCE:
-		/* Use indefinite length constructed if requested */
-		if (aclass & ASN1_TFLG_NDEF) ndef = 2;
-		/* fall through */
+    case ASN1_ITYPE_COMPAT:
+        /* old style hackery... */
+        cf = it->funcs;
+        if (out)
+            p = *out;
+        i = cf->asn1_i2d(*pval, out);
+        /*
+         * Fixup for IMPLICIT tag: note this messes up for tags > 30, but so
+         * did the old code. Tags > 30 are very rare anyway.
+         */
+        if (out && (tag != -1))
+            *p = aclass | tag | (*p & V_ASN1_CONSTRUCTED);
+        return i;
 
-		case ASN1_ITYPE_SEQUENCE:
-		i = asn1_enc_restore(&seqcontlen, out, pval, it);
-		/* An error occurred */
-		if (i < 0)
-			return 0;
-		/* We have a valid cached encoding... */
-		if (i > 0)
-			return seqcontlen;
-		/* Otherwise carry on */
-		seqcontlen = 0;
-		/* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
-		if (tag == -1)
-			{
-			tag = V_ASN1_SEQUENCE;
-			/* Retain any other flags in aclass */
-			aclass = (aclass & ~ASN1_TFLG_TAG_CLASS)
-					| V_ASN1_UNIVERSAL;
-			}
-		if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
-				return 0;
-		/* First work out sequence content length */
-		for (i = 0, tt = it->templates; i < it->tcount; tt++, i++)
-			{
-			const ASN1_TEMPLATE *seqtt;
-			ASN1_VALUE **pseqval;
-			seqtt = asn1_do_adb(pval, tt, 1);
-			if (!seqtt)
-				return 0;
-			pseqval = asn1_get_field_ptr(pval, seqtt);
-			/* FIXME: check for errors in enhanced version */
-			seqcontlen += asn1_template_ex_i2d(pseqval, NULL, seqtt,
-								-1, aclass);
-			}
+    case ASN1_ITYPE_NDEF_SEQUENCE:
+        /* Use indefinite length constructed if requested */
+        if (aclass & ASN1_TFLG_NDEF)
+            ndef = 2;
+        /* fall through */
 
-		seqlen = ASN1_object_size(ndef, seqcontlen, tag);
-		if (!out)
-			return seqlen;
-		/* Output SEQUENCE header */
-		ASN1_put_object(out, ndef, seqcontlen, tag, aclass);
-		for (i = 0, tt = it->templates; i < it->tcount; tt++, i++)
-			{
-			const ASN1_TEMPLATE *seqtt;
-			ASN1_VALUE **pseqval;
-			seqtt = asn1_do_adb(pval, tt, 1);
-			if (!seqtt)
-				return 0;
-			pseqval = asn1_get_field_ptr(pval, seqtt);
-			/* FIXME: check for errors in enhanced version */
-			asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass);
-			}
-		if (ndef == 2)
-			ASN1_put_eoc(out);
-		if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
-				return 0;
-		return seqlen;
+    case ASN1_ITYPE_SEQUENCE:
+        i = asn1_enc_restore(&seqcontlen, out, pval, it);
+        /* An error occurred */
+        if (i < 0)
+            return 0;
+        /* We have a valid cached encoding... */
+        if (i > 0)
+            return seqcontlen;
+        /* Otherwise carry on */
+        seqcontlen = 0;
+        /* If no IMPLICIT tagging set to SEQUENCE, UNIVERSAL */
+        if (tag == -1) {
+            tag = V_ASN1_SEQUENCE;
+            /* Retain any other flags in aclass */
+            aclass = (aclass & ~ASN1_TFLG_TAG_CLASS)
+                | V_ASN1_UNIVERSAL;
+        }
+        if (asn1_cb && !asn1_cb(ASN1_OP_I2D_PRE, pval, it, NULL))
+            return 0;
+        /* First work out sequence content length */
+        for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
+            const ASN1_TEMPLATE *seqtt;
+            ASN1_VALUE **pseqval;
+            int tmplen;
+            seqtt = asn1_do_adb(pval, tt, 1);
+            if (!seqtt)
+                return 0;
+            pseqval = asn1_get_field_ptr(pval, seqtt);
+            tmplen = asn1_template_ex_i2d(pseqval, NULL, seqtt, -1, aclass);
+            if (tmplen == -1 || (tmplen > INT_MAX - seqcontlen))
+                return -1;
+            seqcontlen += tmplen;
+        }
 
-		default:
-		return 0;
+        seqlen = ASN1_object_size(ndef, seqcontlen, tag);
+        if (!out || seqlen == -1)
+            return seqlen;
+        /* Output SEQUENCE header */
+        ASN1_put_object(out, ndef, seqcontlen, tag, aclass);
+        for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
+            const ASN1_TEMPLATE *seqtt;
+            ASN1_VALUE **pseqval;
+            seqtt = asn1_do_adb(pval, tt, 1);
+            if (!seqtt)
+                return 0;
+            pseqval = asn1_get_field_ptr(pval, seqtt);
+            /* FIXME: check for errors in enhanced version */
+            asn1_template_ex_i2d(pseqval, out, seqtt, -1, aclass);
+        }
+        if (ndef == 2)
+            ASN1_put_eoc(out);
+        if (asn1_cb && !asn1_cb(ASN1_OP_I2D_POST, pval, it, NULL))
+            return 0;
+        return seqlen;
 
-		}
-	return 0;
-	}
+    default:
+        return 0;
+
+    }
+    return 0;
+}
 
 int ASN1_template_i2d(ASN1_VALUE **pval, unsigned char **out,
-							const ASN1_TEMPLATE *tt)
-	{
-	return asn1_template_ex_i2d(pval, out, tt, -1, 0);
-	}
+                      const ASN1_TEMPLATE *tt)
+{
+    return asn1_template_ex_i2d(pval, out, tt, -1, 0);
+}
 
 static int asn1_template_ex_i2d(ASN1_VALUE **pval, unsigned char **out,
-				const ASN1_TEMPLATE *tt, int tag, int iclass)
-	{
-	int i, ret, flags, ttag, tclass, ndef;
-	size_t j;
-	flags = tt->flags;
-	/* Work out tag and class to use: tagging may come
-	 * either from the template or the arguments, not both
-	 * because this would create ambiguity. Additionally
-	 * the iclass argument may contain some additional flags
-	 * which should be noted and passed down to other levels.
-	 */
-	if (flags & ASN1_TFLG_TAG_MASK)
-		{
-		/* Error if argument and template tagging */
-		if (tag != -1)
-			/* FIXME: error code here */
-			return -1;
-		/* Get tagging from template */
-		ttag = tt->tag;
-		tclass = flags & ASN1_TFLG_TAG_CLASS;
-		}
-	else if (tag != -1)
-		{
-		/* No template tagging, get from arguments */
-		ttag = tag;
-		tclass = iclass & ASN1_TFLG_TAG_CLASS;
-		}
-	else
-		{
-		ttag = -1;
-		tclass = 0;
-		}
-	/* 
-	 * Remove any class mask from iflag.
-	 */
-	iclass &= ~ASN1_TFLG_TAG_CLASS;
+                                const ASN1_TEMPLATE *tt, int tag, int iclass)
+{
+    int i, ret, flags, ttag, tclass, ndef;
+    size_t j;
+    flags = tt->flags;
+    /*
+     * Work out tag and class to use: tagging may come either from the
+     * template or the arguments, not both because this would create
+     * ambiguity. Additionally the iclass argument may contain some
+     * additional flags which should be noted and passed down to other
+     * levels.
+     */
+    if (flags & ASN1_TFLG_TAG_MASK) {
+        /* Error if argument and template tagging */
+        if (tag != -1)
+            /* FIXME: error code here */
+            return -1;
+        /* Get tagging from template */
+        ttag = tt->tag;
+        tclass = flags & ASN1_TFLG_TAG_CLASS;
+    } else if (tag != -1) {
+        /* No template tagging, get from arguments */
+        ttag = tag;
+        tclass = iclass & ASN1_TFLG_TAG_CLASS;
+    } else {
+        ttag = -1;
+        tclass = 0;
+    }
+    /*
+     * Remove any class mask from iflag.
+     */
+    iclass &= ~ASN1_TFLG_TAG_CLASS;
 
-	/* At this point 'ttag' contains the outer tag to use,
-	 * 'tclass' is the class and iclass is any flags passed
-	 * to this function.
-	 */
+    /*
+     * At this point 'ttag' contains the outer tag to use, 'tclass' is the
+     * class and iclass is any flags passed to this function.
+     */
 
-	/* if template and arguments require ndef, use it */
-	if ((flags & ASN1_TFLG_NDEF) && (iclass & ASN1_TFLG_NDEF))
-		ndef = 2;
-	else ndef = 1;
+    /* if template and arguments require ndef, use it */
+    if ((flags & ASN1_TFLG_NDEF) && (iclass & ASN1_TFLG_NDEF))
+        ndef = 2;
+    else
+        ndef = 1;
 
-	if (flags & ASN1_TFLG_SK_MASK)
-		{
-		/* SET OF, SEQUENCE OF */
-		STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
-		int isset, sktag, skaclass;
-		int skcontlen, sklen;
-		ASN1_VALUE *skitem;
+    if (flags & ASN1_TFLG_SK_MASK) {
+        /* SET OF, SEQUENCE OF */
+        STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
+        int isset, sktag, skaclass;
+        int skcontlen, sklen;
+        ASN1_VALUE *skitem;
 
-		if (!*pval)
-			return 0;
+        if (!*pval)
+            return 0;
 
-		if (flags & ASN1_TFLG_SET_OF)
-			{
-			isset = 1;
-			/* 2 means we reorder */
-			if (flags & ASN1_TFLG_SEQUENCE_OF)
-				isset = 2;
-			}
-		else isset = 0;
+        if (flags & ASN1_TFLG_SET_OF) {
+            isset = 1;
+            /* 2 means we reorder */
+            if (flags & ASN1_TFLG_SEQUENCE_OF)
+                isset = 2;
+        } else
+            isset = 0;
 
-		/* Work out inner tag value: if EXPLICIT
-		 * or no tagging use underlying type.
-		 */
-		if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG))
-			{
-			sktag = ttag;
-			skaclass = tclass;
-			}
-		else
-			{
-			skaclass = V_ASN1_UNIVERSAL;
-			if (isset)
-				sktag = V_ASN1_SET;
-			else sktag = V_ASN1_SEQUENCE;
-			}
+        /*
+         * Work out inner tag value: if EXPLICIT or no tagging use underlying
+         * type.
+         */
+        if ((ttag != -1) && !(flags & ASN1_TFLG_EXPTAG)) {
+            sktag = ttag;
+            skaclass = tclass;
+        } else {
+            skaclass = V_ASN1_UNIVERSAL;
+            if (isset)
+                sktag = V_ASN1_SET;
+            else
+                sktag = V_ASN1_SEQUENCE;
+        }
 
-		/* Determine total length of items */
-		skcontlen = 0;
-		for (j = 0; j < sk_ASN1_VALUE_num(sk); j++)
-			{
-			skitem = sk_ASN1_VALUE_value(sk, j);
-			skcontlen += ASN1_item_ex_i2d(&skitem, NULL,
-						ASN1_ITEM_ptr(tt->item),
-							-1, iclass);
-			}
-		sklen = ASN1_object_size(ndef, skcontlen, sktag);
-		/* If EXPLICIT need length of surrounding tag */
-		if (flags & ASN1_TFLG_EXPTAG)
-			ret = ASN1_object_size(ndef, sklen, ttag);
-		else ret = sklen;
+        /* Determine total length of items */
+        skcontlen = 0;
+        for (j = 0; j < sk_ASN1_VALUE_num(sk); j++) {
+            int tmplen;
+            skitem = sk_ASN1_VALUE_value(sk, j);
+            tmplen = ASN1_item_ex_i2d(&skitem, NULL, ASN1_ITEM_ptr(tt->item),
+                                      -1, iclass);
+            if (tmplen == -1 || (skcontlen > INT_MAX - tmplen))
+                return -1;
+            skcontlen += tmplen;
+        }
+        sklen = ASN1_object_size(ndef, skcontlen, sktag);
+        if (sklen == -1)
+            return -1;
+        /* If EXPLICIT need length of surrounding tag */
+        if (flags & ASN1_TFLG_EXPTAG)
+            ret = ASN1_object_size(ndef, sklen, ttag);
+        else
+            ret = sklen;
 
-		if (!out)
-			return ret;
+        if (!out || ret == -1)
+            return ret;
 
-		/* Now encode this lot... */
-		/* EXPLICIT tag */
-		if (flags & ASN1_TFLG_EXPTAG)
-			ASN1_put_object(out, ndef, sklen, ttag, tclass);
-		/* SET or SEQUENCE and IMPLICIT tag */
-		ASN1_put_object(out, ndef, skcontlen, sktag, skaclass);
-		/* And the stuff itself */
-		asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item),
-								isset, iclass);
-		if (ndef == 2)
-			{
-			ASN1_put_eoc(out);
-			if (flags & ASN1_TFLG_EXPTAG)
-				ASN1_put_eoc(out);
-			}
+        /* Now encode this lot... */
+        /* EXPLICIT tag */
+        if (flags & ASN1_TFLG_EXPTAG)
+            ASN1_put_object(out, ndef, sklen, ttag, tclass);
+        /* SET or SEQUENCE and IMPLICIT tag */
+        ASN1_put_object(out, ndef, skcontlen, sktag, skaclass);
+        /* And the stuff itself */
+        asn1_set_seq_out(sk, out, skcontlen, ASN1_ITEM_ptr(tt->item),
+                         isset, iclass);
+        if (ndef == 2) {
+            ASN1_put_eoc(out);
+            if (flags & ASN1_TFLG_EXPTAG)
+                ASN1_put_eoc(out);
+        }
 
-		return ret;
-		}
+        return ret;
+    }
 
-	if (flags & ASN1_TFLG_EXPTAG)
-		{
-		/* EXPLICIT tagging */
-		/* Find length of tagged item */
-		i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item),
-								-1, iclass);
-		if (!i)
-			return 0;
-		/* Find length of EXPLICIT tag */
-		ret = ASN1_object_size(ndef, i, ttag);
-		if (out)
-			{
-			/* Output tag and item */
-			ASN1_put_object(out, ndef, i, ttag, tclass);
-			ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
-								-1, iclass);
-			if (ndef == 2)
-				ASN1_put_eoc(out);
-			}
-		return ret;
-		}
+    if (flags & ASN1_TFLG_EXPTAG) {
+        /* EXPLICIT tagging */
+        /* Find length of tagged item */
+        i = ASN1_item_ex_i2d(pval, NULL, ASN1_ITEM_ptr(tt->item), -1, iclass);
+        if (!i)
+            return 0;
+        /* Find length of EXPLICIT tag */
+        ret = ASN1_object_size(ndef, i, ttag);
+        if (out && ret != -1) {
+            /* Output tag and item */
+            ASN1_put_object(out, ndef, i, ttag, tclass);
+            ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item), -1, iclass);
+            if (ndef == 2)
+                ASN1_put_eoc(out);
+        }
+        return ret;
+    }
 
-	/* Either normal or IMPLICIT tagging: combine class and flags */
-	return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
-						ttag, tclass | iclass);
+    /* Either normal or IMPLICIT tagging: combine class and flags */
+    return ASN1_item_ex_i2d(pval, out, ASN1_ITEM_ptr(tt->item),
+                            ttag, tclass | iclass);
 
 }
 
 /* Temporary structure used to hold DER encoding of items for SET OF */
 
-typedef	struct {
-	unsigned char *data;
-	int length;
-	ASN1_VALUE *field;
+typedef struct {
+    unsigned char *data;
+    int length;
+    ASN1_VALUE *field;
 } DER_ENC;
 
 static int der_cmp(const void *a, const void *b)
-	{
-	const DER_ENC *d1 = a, *d2 = b;
-	int cmplen, i;
-	cmplen = (d1->length < d2->length) ? d1->length : d2->length;
-	i = memcmp(d1->data, d2->data, cmplen);
-	if (i)
-		return i;
-	return d1->length - d2->length;
-	}
+{
+    const DER_ENC *d1 = a, *d2 = b;
+    int cmplen, i;
+    cmplen = (d1->length < d2->length) ? d1->length : d2->length;
+    i = OPENSSL_memcmp(d1->data, d2->data, cmplen);
+    if (i)
+        return i;
+    return d1->length - d2->length;
+}
 
 /* Output the content octets of SET OF or SEQUENCE OF */
 
 static int asn1_set_seq_out(STACK_OF(ASN1_VALUE) *sk, unsigned char **out,
-					int skcontlen, const ASN1_ITEM *item,
-					int do_sort, int iclass)
-	{
-	size_t i;
-	ASN1_VALUE *skitem;
-	unsigned char *tmpdat = NULL, *p = NULL;
-	DER_ENC *derlst = NULL, *tder;
-	if (do_sort)
-		 {
-		/* Don't need to sort less than 2 items */
-		if (sk_ASN1_VALUE_num(sk) < 2)
-			do_sort = 0;
-		else
-			{
-			derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk)
-						* sizeof(*derlst));
-			if (!derlst)
-				return 0;
-			tmpdat = OPENSSL_malloc(skcontlen);
-			if (!tmpdat)
-				{
-				OPENSSL_free(derlst);
-				return 0;
-				}
-			}
-		}
-	/* If not sorting just output each item */
-	if (!do_sort)
-		{
-		for (i = 0; i < sk_ASN1_VALUE_num(sk); i++)
-			{
-			skitem = sk_ASN1_VALUE_value(sk, i);
-			ASN1_item_ex_i2d(&skitem, out, item, -1, iclass);
-			}
-		return 1;
-		}
-	p = tmpdat;
+                            int skcontlen, const ASN1_ITEM *item,
+                            int do_sort, int iclass)
+{
+    size_t i;
+    ASN1_VALUE *skitem;
+    unsigned char *tmpdat = NULL, *p = NULL;
+    DER_ENC *derlst = NULL, *tder;
+    if (do_sort) {
+        /* Don't need to sort less than 2 items */
+        if (sk_ASN1_VALUE_num(sk) < 2)
+            do_sort = 0;
+        else {
+            derlst = OPENSSL_malloc(sk_ASN1_VALUE_num(sk)
+                                    * sizeof(*derlst));
+            if (!derlst)
+                return 0;
+            tmpdat = OPENSSL_malloc(skcontlen);
+            if (!tmpdat) {
+                OPENSSL_free(derlst);
+                return 0;
+            }
+        }
+    }
+    /* If not sorting just output each item */
+    if (!do_sort) {
+        for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
+            skitem = sk_ASN1_VALUE_value(sk, i);
+            ASN1_item_ex_i2d(&skitem, out, item, -1, iclass);
+        }
+        return 1;
+    }
+    p = tmpdat;
 
-	/* Doing sort: build up a list of each member's DER encoding */
-	for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++)
-		{
-		skitem = sk_ASN1_VALUE_value(sk, i);
-		tder->data = p;
-		tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass);
-		tder->field = skitem;
-		}
+    /* Doing sort: build up a list of each member's DER encoding */
+    for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
+        skitem = sk_ASN1_VALUE_value(sk, i);
+        tder->data = p;
+        tder->length = ASN1_item_ex_i2d(&skitem, &p, item, -1, iclass);
+        tder->field = skitem;
+    }
 
-	/* Now sort them */
-	qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp);
-	/* Output sorted DER encoding */	
-	p = *out;
-	for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++)
-		{
-		memcpy(p, tder->data, tder->length);
-		p += tder->length;
-		}
-	*out = p;
-	/* If do_sort is 2 then reorder the STACK */
-	if (do_sort == 2)
-		{
-		for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk);
-							i++, tder++)
-			(void)sk_ASN1_VALUE_set(sk, i, tder->field);
-		}
-	OPENSSL_free(derlst);
-	OPENSSL_free(tmpdat);
-	return 1;
-	}
+    /* Now sort them */
+    qsort(derlst, sk_ASN1_VALUE_num(sk), sizeof(*derlst), der_cmp);
+    /* Output sorted DER encoding */
+    p = *out;
+    for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++) {
+        OPENSSL_memcpy(p, tder->data, tder->length);
+        p += tder->length;
+    }
+    *out = p;
+    /* If do_sort is 2 then reorder the STACK */
+    if (do_sort == 2) {
+        for (i = 0, tder = derlst; i < sk_ASN1_VALUE_num(sk); i++, tder++)
+            (void)sk_ASN1_VALUE_set(sk, i, tder->field);
+    }
+    OPENSSL_free(derlst);
+    OPENSSL_free(tmpdat);
+    return 1;
+}
 
 static int asn1_i2d_ex_primitive(ASN1_VALUE **pval, unsigned char **out,
-				const ASN1_ITEM *it, int tag, int aclass)
-	{
-	int len;
-	int utype;
-	int usetag;
-	int ndef = 0;
+                                 const ASN1_ITEM *it, int tag, int aclass)
+{
+    int len;
+    int utype;
+    int usetag;
+    int ndef = 0;
 
-	utype = it->utype;
+    utype = it->utype;
 
-	/* Get length of content octets and maybe find
-	 * out the underlying type.
-	 */
+    /*
+     * Get length of content octets and maybe find out the underlying type.
+     */
 
-	len = asn1_ex_i2c(pval, NULL, &utype, it);
+    len = asn1_ex_i2c(pval, NULL, &utype, it);
 
-	/* If SEQUENCE, SET or OTHER then header is
-	 * included in pseudo content octets so don't
-	 * include tag+length. We need to check here
-	 * because the call to asn1_ex_i2c() could change
-	 * utype.
-	 */
-	if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) ||
-	   (utype == V_ASN1_OTHER))
-		usetag = 0;
-	else usetag = 1;
+    /*
+     * If SEQUENCE, SET or OTHER then header is included in pseudo content
+     * octets so don't include tag+length. We need to check here because the
+     * call to asn1_ex_i2c() could change utype.
+     */
+    if ((utype == V_ASN1_SEQUENCE) || (utype == V_ASN1_SET) ||
+        (utype == V_ASN1_OTHER))
+        usetag = 0;
+    else
+        usetag = 1;
 
-	/* -1 means omit type */
+    /* -1 means omit type */
 
-	if (len == -1)
-		return 0;
+    if (len == -1)
+        return 0;
 
-	/* -2 return is special meaning use ndef */
-	if (len == -2)
-		{
-		ndef = 2;
-		len = 0;
-		}
+    /* -2 return is special meaning use ndef */
+    if (len == -2) {
+        ndef = 2;
+        len = 0;
+    }
 
-	/* If not implicitly tagged get tag from underlying type */
-	if (tag == -1) tag = utype;
+    /* If not implicitly tagged get tag from underlying type */
+    if (tag == -1)
+        tag = utype;
 
-	/* Output tag+length followed by content octets */
-	if (out)
-		{
-		if (usetag)
-			ASN1_put_object(out, ndef, len, tag, aclass);
-		asn1_ex_i2c(pval, *out, &utype, it);
-		if (ndef)
-			ASN1_put_eoc(out);
-		else
-			*out += len;
-		}
+    /* Output tag+length followed by content octets */
+    if (out) {
+        if (usetag)
+            ASN1_put_object(out, ndef, len, tag, aclass);
+        asn1_ex_i2c(pval, *out, &utype, it);
+        if (ndef)
+            ASN1_put_eoc(out);
+        else
+            *out += len;
+    }
 
-	if (usetag)
-		return ASN1_object_size(ndef, len, tag);
-	return len;
-	}
+    if (usetag)
+        return ASN1_object_size(ndef, len, tag);
+    return len;
+}
 
 /* Produce content octets from a structure */
 
 int asn1_ex_i2c(ASN1_VALUE **pval, unsigned char *cout, int *putype,
-				const ASN1_ITEM *it)
-	{
-	ASN1_BOOLEAN *tbool = NULL;
-	ASN1_STRING *strtmp;
-	ASN1_OBJECT *otmp;
-	int utype;
-	const unsigned char *cont;
-	unsigned char c;
-	int len;
-	const ASN1_PRIMITIVE_FUNCS *pf;
-	pf = it->funcs;
-	if (pf && pf->prim_i2c)
-		return pf->prim_i2c(pval, cout, putype, it);
+                const ASN1_ITEM *it)
+{
+    ASN1_BOOLEAN *tbool = NULL;
+    ASN1_STRING *strtmp;
+    ASN1_OBJECT *otmp;
+    int utype;
+    const unsigned char *cont;
+    unsigned char c;
+    int len;
+    const ASN1_PRIMITIVE_FUNCS *pf;
+    pf = it->funcs;
+    if (pf && pf->prim_i2c)
+        return pf->prim_i2c(pval, cout, putype, it);
 
-	/* Should type be omitted? */
-	if ((it->itype != ASN1_ITYPE_PRIMITIVE)
-		|| (it->utype != V_ASN1_BOOLEAN))
-		{
-		if (!*pval) return -1;
-		}
+    /* Should type be omitted? */
+    if ((it->itype != ASN1_ITYPE_PRIMITIVE)
+        || (it->utype != V_ASN1_BOOLEAN)) {
+        if (!*pval)
+            return -1;
+    }
 
-	if (it->itype == ASN1_ITYPE_MSTRING)
-		{
-		/* If MSTRING type set the underlying type */
-		strtmp = (ASN1_STRING *)*pval;
-		utype = strtmp->type;
-		*putype = utype;
-		}
-	else if (it->utype == V_ASN1_ANY)
-		{
-		/* If ANY set type and pointer to value */
-		ASN1_TYPE *typ;
-		typ = (ASN1_TYPE *)*pval;
-		utype = typ->type;
-		*putype = utype;
-		pval = &typ->value.asn1_value;
-		}
-	else utype = *putype;
+    if (it->itype == ASN1_ITYPE_MSTRING) {
+        /* If MSTRING type set the underlying type */
+        strtmp = (ASN1_STRING *)*pval;
+        utype = strtmp->type;
+        *putype = utype;
+    } else if (it->utype == V_ASN1_ANY) {
+        /* If ANY set type and pointer to value */
+        ASN1_TYPE *typ;
+        typ = (ASN1_TYPE *)*pval;
+        utype = typ->type;
+        *putype = utype;
+        pval = &typ->value.asn1_value;
+    } else
+        utype = *putype;
 
-	switch(utype)
-		{
-		case V_ASN1_OBJECT:
-		otmp = (ASN1_OBJECT *)*pval;
-		cont = otmp->data;
-		len = otmp->length;
-		break;
+    switch (utype) {
+    case V_ASN1_OBJECT:
+        otmp = (ASN1_OBJECT *)*pval;
+        cont = otmp->data;
+        len = otmp->length;
+        break;
 
-		case V_ASN1_NULL:
-		cont = NULL;
-		len = 0;
-		break;
+    case V_ASN1_NULL:
+        cont = NULL;
+        len = 0;
+        break;
 
-		case V_ASN1_BOOLEAN:
-		tbool = (ASN1_BOOLEAN *)pval;
-		if (*tbool == -1)
-			return -1;
-		if (it->utype != V_ASN1_ANY)
-			{
-			/* Default handling if value == size field then omit */
-			if (*tbool && (it->size > 0))
-				return -1;
-			if (!*tbool && !it->size)
-				return -1;
-			}
-		c = (unsigned char)*tbool;
-		cont = &c;
-		len = 1;
-		break;
+    case V_ASN1_BOOLEAN:
+        tbool = (ASN1_BOOLEAN *)pval;
+        if (*tbool == -1)
+            return -1;
+        if (it->utype != V_ASN1_ANY) {
+            /*
+             * Default handling if value == size field then omit
+             */
+            if (*tbool && (it->size > 0))
+                return -1;
+            if (!*tbool && !it->size)
+                return -1;
+        }
+        c = (unsigned char)*tbool;
+        cont = &c;
+        len = 1;
+        break;
 
-		case V_ASN1_BIT_STRING:
-		return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval,
-							cout ? &cout : NULL);
-		break;
+    case V_ASN1_BIT_STRING:
+        return i2c_ASN1_BIT_STRING((ASN1_BIT_STRING *)*pval,
+                                   cout ? &cout : NULL);
+        break;
 
-		case V_ASN1_INTEGER:
-		case V_ASN1_NEG_INTEGER:
-		case V_ASN1_ENUMERATED:
-		case V_ASN1_NEG_ENUMERATED:
-		/* These are all have the same content format
-		 * as ASN1_INTEGER
-		 */
-		return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval,
-							cout ? &cout : NULL);
-		break;
+    case V_ASN1_INTEGER:
+    case V_ASN1_ENUMERATED:
+        /*
+         * These are all have the same content format as ASN1_INTEGER
+         */
+        return i2c_ASN1_INTEGER((ASN1_INTEGER *)*pval, cout ? &cout : NULL);
+        break;
 
-		case V_ASN1_OCTET_STRING:
-		case V_ASN1_NUMERICSTRING:
-		case V_ASN1_PRINTABLESTRING:
-		case V_ASN1_T61STRING:
-		case V_ASN1_VIDEOTEXSTRING:
-		case V_ASN1_IA5STRING:
-		case V_ASN1_UTCTIME:
-		case V_ASN1_GENERALIZEDTIME:
-		case V_ASN1_GRAPHICSTRING:
-		case V_ASN1_VISIBLESTRING:
-		case V_ASN1_GENERALSTRING:
-		case V_ASN1_UNIVERSALSTRING:
-		case V_ASN1_BMPSTRING:
-		case V_ASN1_UTF8STRING:
-		case V_ASN1_SEQUENCE:
-		case V_ASN1_SET:
-		default:
-		/* All based on ASN1_STRING and handled the same */
-		strtmp = (ASN1_STRING *)*pval;
-		/* Special handling for NDEF */
-		if ((it->size == ASN1_TFLG_NDEF)
-			&& (strtmp->flags & ASN1_STRING_FLAG_NDEF))
-			{
-			if (cout)
-				{
-				strtmp->data = cout;
-				strtmp->length = 0;
-				}
-			/* Special return code */
-			return -2;
-			}
-		cont = strtmp->data;
-		len = strtmp->length;
+    case V_ASN1_OCTET_STRING:
+    case V_ASN1_NUMERICSTRING:
+    case V_ASN1_PRINTABLESTRING:
+    case V_ASN1_T61STRING:
+    case V_ASN1_VIDEOTEXSTRING:
+    case V_ASN1_IA5STRING:
+    case V_ASN1_UTCTIME:
+    case V_ASN1_GENERALIZEDTIME:
+    case V_ASN1_GRAPHICSTRING:
+    case V_ASN1_VISIBLESTRING:
+    case V_ASN1_GENERALSTRING:
+    case V_ASN1_UNIVERSALSTRING:
+    case V_ASN1_BMPSTRING:
+    case V_ASN1_UTF8STRING:
+    case V_ASN1_SEQUENCE:
+    case V_ASN1_SET:
+    default:
+        /* All based on ASN1_STRING and handled the same */
+        strtmp = (ASN1_STRING *)*pval;
+        /* Special handling for NDEF */
+        if ((it->size == ASN1_TFLG_NDEF)
+            && (strtmp->flags & ASN1_STRING_FLAG_NDEF)) {
+            if (cout) {
+                strtmp->data = cout;
+                strtmp->length = 0;
+            }
+            /* Special return code */
+            return -2;
+        }
+        cont = strtmp->data;
+        len = strtmp->length;
 
-		break;
+        break;
 
-		}
-	if (cout && len)
-		memcpy(cout, cont, len);
-	return len;
-	}
+    }
+    if (cout && len)
+        OPENSSL_memcpy(cout, cont, len);
+    return len;
+}
diff --git a/src/crypto/asn1/tasn_fre.c b/src/crypto/asn1/tasn_fre.c
index d1317ae..609cb9f 100644
--- a/src/crypto/asn1/tasn_fre.c
+++ b/src/crypto/asn1/tasn_fre.c
@@ -59,206 +59,188 @@
 #include <openssl/asn1t.h>
 #include <openssl/mem.h>
 
-
-static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine);
+static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it,
+                                   int combine);
 
 /* Free up an ASN1 structure */
 
 void ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it)
-	{
-	asn1_item_combine_free(&val, it, 0);
-	}
+{
+    asn1_item_combine_free(&val, it, 0);
+}
 
 void ASN1_item_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
-	{
-	asn1_item_combine_free(pval, it, 0);
-	}
+{
+    asn1_item_combine_free(pval, it, 0);
+}
 
-static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it, int combine)
-	{
-	const ASN1_TEMPLATE *tt = NULL, *seqtt;
-	const ASN1_EXTERN_FUNCS *ef;
-	const ASN1_COMPAT_FUNCS *cf;
-	const ASN1_AUX *aux = it->funcs;
-	ASN1_aux_cb *asn1_cb;
-	int i;
-	if (!pval)
-		return;
-	if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
-		return;
-	if (aux && aux->asn1_cb)
-		asn1_cb = aux->asn1_cb;
-	else
-		asn1_cb = 0;
+static void asn1_item_combine_free(ASN1_VALUE **pval, const ASN1_ITEM *it,
+                                   int combine)
+{
+    const ASN1_TEMPLATE *tt = NULL, *seqtt;
+    const ASN1_EXTERN_FUNCS *ef;
+    const ASN1_COMPAT_FUNCS *cf;
+    const ASN1_AUX *aux = it->funcs;
+    ASN1_aux_cb *asn1_cb;
+    int i;
+    if (!pval)
+        return;
+    if ((it->itype != ASN1_ITYPE_PRIMITIVE) && !*pval)
+        return;
+    if (aux && aux->asn1_cb)
+        asn1_cb = aux->asn1_cb;
+    else
+        asn1_cb = 0;
 
-	switch(it->itype)
-		{
+    switch (it->itype) {
 
-		case ASN1_ITYPE_PRIMITIVE:
-		if (it->templates)
-			ASN1_template_free(pval, it->templates);
-		else
-			ASN1_primitive_free(pval, it);
-		break;
+    case ASN1_ITYPE_PRIMITIVE:
+        if (it->templates)
+            ASN1_template_free(pval, it->templates);
+        else
+            ASN1_primitive_free(pval, it);
+        break;
 
-		case ASN1_ITYPE_MSTRING:
-		ASN1_primitive_free(pval, it);
-		break;
+    case ASN1_ITYPE_MSTRING:
+        ASN1_primitive_free(pval, it);
+        break;
 
-		case ASN1_ITYPE_CHOICE:
-		if (asn1_cb)
-			{
-			i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
-			if (i == 2)
-				return;
-			}
-		i = asn1_get_choice_selector(pval, it);
-		if ((i >= 0) && (i < it->tcount))
-			{
-			ASN1_VALUE **pchval;
-			tt = it->templates + i;
-			pchval = asn1_get_field_ptr(pval, tt);
-			ASN1_template_free(pchval, tt);
-			}
-		if (asn1_cb)
-			asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
-		if (!combine)
-			{
-			OPENSSL_free(*pval);
-			*pval = NULL;
-			}
-		break;
+    case ASN1_ITYPE_CHOICE:
+        if (asn1_cb) {
+            i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
+            if (i == 2)
+                return;
+        }
+        i = asn1_get_choice_selector(pval, it);
+        if ((i >= 0) && (i < it->tcount)) {
+            ASN1_VALUE **pchval;
+            tt = it->templates + i;
+            pchval = asn1_get_field_ptr(pval, tt);
+            ASN1_template_free(pchval, tt);
+        }
+        if (asn1_cb)
+            asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
+        if (!combine) {
+            OPENSSL_free(*pval);
+            *pval = NULL;
+        }
+        break;
 
-		case ASN1_ITYPE_COMPAT:
-		cf = it->funcs;
-		if (cf && cf->asn1_free)
-			cf->asn1_free(*pval);
-		break;
+    case ASN1_ITYPE_COMPAT:
+        cf = it->funcs;
+        if (cf && cf->asn1_free)
+            cf->asn1_free(*pval);
+        break;
 
-		case ASN1_ITYPE_EXTERN:
-		ef = it->funcs;
-		if (ef && ef->asn1_ex_free)
-			ef->asn1_ex_free(pval, it);
-		break;
+    case ASN1_ITYPE_EXTERN:
+        ef = it->funcs;
+        if (ef && ef->asn1_ex_free)
+            ef->asn1_ex_free(pval, it);
+        break;
 
-		case ASN1_ITYPE_NDEF_SEQUENCE:
-		case ASN1_ITYPE_SEQUENCE:
-		if (!asn1_refcount_dec_and_test_zero(pval, it))
-			return;
-		if (asn1_cb)
-			{
-			i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
-			if (i == 2)
-				return;
-			}		
-		asn1_enc_free(pval, it);
-		/* If we free up as normal we will invalidate any
-		 * ANY DEFINED BY field and we wont be able to 
-		 * determine the type of the field it defines. So
-		 * free up in reverse order.
-		 */
-		tt = it->templates + it->tcount - 1;
-		for (i = 0; i < it->tcount; tt--, i++)
-			{
-			ASN1_VALUE **pseqval;
-			seqtt = asn1_do_adb(pval, tt, 0);
-			if (!seqtt)
-				continue;
-			pseqval = asn1_get_field_ptr(pval, seqtt);
-			ASN1_template_free(pseqval, seqtt);
-			}
-		if (asn1_cb)
-			asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
-		if (!combine)
-			{
-			OPENSSL_free(*pval);
-			*pval = NULL;
-			}
-		break;
-		}
-	}
+    case ASN1_ITYPE_NDEF_SEQUENCE:
+    case ASN1_ITYPE_SEQUENCE:
+        if (!asn1_refcount_dec_and_test_zero(pval, it))
+            return;
+        if (asn1_cb) {
+            i = asn1_cb(ASN1_OP_FREE_PRE, pval, it, NULL);
+            if (i == 2)
+                return;
+        }
+        asn1_enc_free(pval, it);
+        /*
+         * If we free up as normal we will invalidate any ANY DEFINED BY
+         * field and we wont be able to determine the type of the field it
+         * defines. So free up in reverse order.
+         */
+        tt = it->templates + it->tcount - 1;
+        for (i = 0; i < it->tcount; tt--, i++) {
+            ASN1_VALUE **pseqval;
+            seqtt = asn1_do_adb(pval, tt, 0);
+            if (!seqtt)
+                continue;
+            pseqval = asn1_get_field_ptr(pval, seqtt);
+            ASN1_template_free(pseqval, seqtt);
+        }
+        if (asn1_cb)
+            asn1_cb(ASN1_OP_FREE_POST, pval, it, NULL);
+        if (!combine) {
+            OPENSSL_free(*pval);
+            *pval = NULL;
+        }
+        break;
+    }
+}
 
 void ASN1_template_free(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
-	{
-	size_t i;
-	if (tt->flags & ASN1_TFLG_SK_MASK)
-		{
-		STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
-		for (i = 0; i < sk_ASN1_VALUE_num(sk); i++)
-			{
-			ASN1_VALUE *vtmp;
-			vtmp = sk_ASN1_VALUE_value(sk, i);
-			asn1_item_combine_free(&vtmp, ASN1_ITEM_ptr(tt->item),
-									0);
-			}
-		sk_ASN1_VALUE_free(sk);
-		*pval = NULL;
-		}
-	else
-		asn1_item_combine_free(pval, ASN1_ITEM_ptr(tt->item),
-						tt->flags & ASN1_TFLG_COMBINE);
-	}
+{
+    size_t i;
+    if (tt->flags & ASN1_TFLG_SK_MASK) {
+        STACK_OF(ASN1_VALUE) *sk = (STACK_OF(ASN1_VALUE) *)*pval;
+        for (i = 0; i < sk_ASN1_VALUE_num(sk); i++) {
+            ASN1_VALUE *vtmp;
+            vtmp = sk_ASN1_VALUE_value(sk, i);
+            asn1_item_combine_free(&vtmp, ASN1_ITEM_ptr(tt->item), 0);
+        }
+        sk_ASN1_VALUE_free(sk);
+        *pval = NULL;
+    } else
+        asn1_item_combine_free(pval, ASN1_ITEM_ptr(tt->item),
+                               tt->flags & ASN1_TFLG_COMBINE);
+}
 
 void ASN1_primitive_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
-	{
-	int utype;
-	if (it)
-		{
-		const ASN1_PRIMITIVE_FUNCS *pf;
-		pf = it->funcs;
-		if (pf && pf->prim_free)
-			{
-			pf->prim_free(pval, it);
-			return;
-			}
-		}
-	/* Special case: if 'it' is NULL free contents of ASN1_TYPE */
-	if (!it)
-		{
-		ASN1_TYPE *typ = (ASN1_TYPE *)*pval;
-		utype = typ->type;
-		pval = &typ->value.asn1_value;
-		if (!*pval)
-			return;
-		}
-	else if (it->itype == ASN1_ITYPE_MSTRING)
-		{
-		utype = -1;
-		if (!*pval)
-			return;
-		}
-	else
-		{
-		utype = it->utype;
-		if ((utype != V_ASN1_BOOLEAN) && !*pval)
-			return;
-		}
+{
+    int utype;
+    if (it) {
+        const ASN1_PRIMITIVE_FUNCS *pf;
+        pf = it->funcs;
+        if (pf && pf->prim_free) {
+            pf->prim_free(pval, it);
+            return;
+        }
+    }
+    /* Special case: if 'it' is NULL free contents of ASN1_TYPE */
+    if (!it) {
+        ASN1_TYPE *typ = (ASN1_TYPE *)*pval;
+        utype = typ->type;
+        pval = &typ->value.asn1_value;
+        if (!*pval)
+            return;
+    } else if (it->itype == ASN1_ITYPE_MSTRING) {
+        utype = -1;
+        if (!*pval)
+            return;
+    } else {
+        utype = it->utype;
+        if ((utype != V_ASN1_BOOLEAN) && !*pval)
+            return;
+    }
 
-	switch(utype)
-		{
-		case V_ASN1_OBJECT:
-		ASN1_OBJECT_free((ASN1_OBJECT *)*pval);
-		break;
+    switch (utype) {
+    case V_ASN1_OBJECT:
+        ASN1_OBJECT_free((ASN1_OBJECT *)*pval);
+        break;
 
-		case V_ASN1_BOOLEAN:
-		if (it)
-			*(ASN1_BOOLEAN *)pval = it->size;
-		else
-			*(ASN1_BOOLEAN *)pval = -1;
-		return;
+    case V_ASN1_BOOLEAN:
+        if (it)
+            *(ASN1_BOOLEAN *)pval = it->size;
+        else
+            *(ASN1_BOOLEAN *)pval = -1;
+        return;
 
-		case V_ASN1_NULL:
-		break;
+    case V_ASN1_NULL:
+        break;
 
-		case V_ASN1_ANY:
-		ASN1_primitive_free(pval, NULL);
-		OPENSSL_free(*pval);
-		break;
+    case V_ASN1_ANY:
+        ASN1_primitive_free(pval, NULL);
+        OPENSSL_free(*pval);
+        break;
 
-		default:
-		ASN1_STRING_free((ASN1_STRING *)*pval);
-		*pval = NULL;
-		break;
-		}
-	*pval = NULL;
-	}
+    default:
+        ASN1_STRING_free((ASN1_STRING *)*pval);
+        *pval = NULL;
+        break;
+    }
+    *pval = NULL;
+}
diff --git a/src/crypto/asn1/tasn_new.c b/src/crypto/asn1/tasn_new.c
index c68fe06..10cf954 100644
--- a/src/crypto/asn1/tasn_new.c
+++ b/src/crypto/asn1/tasn_new.c
@@ -63,336 +63,324 @@
 #include <openssl/mem.h>
 #include <openssl/obj.h>
 
+#include "../internal.h"
+
 
 static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
-								int combine);
+                                    int combine);
 static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
 static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt);
 static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it);
 
 ASN1_VALUE *ASN1_item_new(const ASN1_ITEM *it)
-	{
-	ASN1_VALUE *ret = NULL;
-	if (ASN1_item_ex_new(&ret, it) > 0)
-		return ret;
-	return NULL;
-	}
+{
+    ASN1_VALUE *ret = NULL;
+    if (ASN1_item_ex_new(&ret, it) > 0)
+        return ret;
+    return NULL;
+}
 
 /* Allocate an ASN1 structure */
 
 int ASN1_item_ex_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
-	{
-	return asn1_item_ex_combine_new(pval, it, 0);
-	}
+{
+    return asn1_item_ex_combine_new(pval, it, 0);
+}
 
 static int asn1_item_ex_combine_new(ASN1_VALUE **pval, const ASN1_ITEM *it,
-								int combine)
-	{
-	const ASN1_TEMPLATE *tt = NULL;
-	const ASN1_COMPAT_FUNCS *cf;
-	const ASN1_EXTERN_FUNCS *ef;
-	const ASN1_AUX *aux = it->funcs;
-	ASN1_aux_cb *asn1_cb;
-	ASN1_VALUE **pseqval;
-	int i;
-	if (aux && aux->asn1_cb)
-		asn1_cb = aux->asn1_cb;
-	else
-		asn1_cb = 0;
+                                    int combine)
+{
+    const ASN1_TEMPLATE *tt = NULL;
+    const ASN1_COMPAT_FUNCS *cf;
+    const ASN1_EXTERN_FUNCS *ef;
+    const ASN1_AUX *aux = it->funcs;
+    ASN1_aux_cb *asn1_cb;
+    ASN1_VALUE **pseqval;
+    int i;
+    if (aux && aux->asn1_cb)
+        asn1_cb = aux->asn1_cb;
+    else
+        asn1_cb = 0;
 
 #ifdef CRYPTO_MDEBUG
-	if (it->sname)
-		CRYPTO_push_info(it->sname);
+    if (it->sname)
+        CRYPTO_push_info(it->sname);
 #endif
 
-	switch(it->itype)
-		{
+    switch (it->itype) {
 
-		case ASN1_ITYPE_EXTERN:
-		ef = it->funcs;
-		if (ef && ef->asn1_ex_new)
-			{
-			if (!ef->asn1_ex_new(pval, it))
-				goto memerr;
-			}
-		break;
+    case ASN1_ITYPE_EXTERN:
+        ef = it->funcs;
+        if (ef && ef->asn1_ex_new) {
+            if (!ef->asn1_ex_new(pval, it))
+                goto memerr;
+        }
+        break;
 
-		case ASN1_ITYPE_COMPAT:
-		cf = it->funcs;
-		if (cf && cf->asn1_new) {
-			*pval = cf->asn1_new();
-			if (!*pval)
-				goto memerr;
-		}
-		break;
+    case ASN1_ITYPE_COMPAT:
+        cf = it->funcs;
+        if (cf && cf->asn1_new) {
+            *pval = cf->asn1_new();
+            if (!*pval)
+                goto memerr;
+        }
+        break;
 
-		case ASN1_ITYPE_PRIMITIVE:
-		if (it->templates)
-			{
-			if (!ASN1_template_new(pval, it->templates))
-				goto memerr;
-			}
-		else if (!ASN1_primitive_new(pval, it))
-				goto memerr;
-		break;
+    case ASN1_ITYPE_PRIMITIVE:
+        if (it->templates) {
+            if (!ASN1_template_new(pval, it->templates))
+                goto memerr;
+        } else if (!ASN1_primitive_new(pval, it))
+            goto memerr;
+        break;
 
-		case ASN1_ITYPE_MSTRING:
-		if (!ASN1_primitive_new(pval, it))
-				goto memerr;
-		break;
+    case ASN1_ITYPE_MSTRING:
+        if (!ASN1_primitive_new(pval, it))
+            goto memerr;
+        break;
 
-		case ASN1_ITYPE_CHOICE:
-		if (asn1_cb)
-			{
-			i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
-			if (!i)
-				goto auxerr;
-			if (i==2)
-				{
+    case ASN1_ITYPE_CHOICE:
+        if (asn1_cb) {
+            i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
+            if (!i)
+                goto auxerr;
+            if (i == 2) {
 #ifdef CRYPTO_MDEBUG
-				if (it->sname)
-					CRYPTO_pop_info();
+                if (it->sname)
+                    CRYPTO_pop_info();
 #endif
-				return 1;
-				}
-			}
-		if (!combine)
-			{
-			*pval = OPENSSL_malloc(it->size);
-			if (!*pval)
-				goto memerr;
-			memset(*pval, 0, it->size);
-			}
-		asn1_set_choice_selector(pval, -1, it);
-		if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
-				goto auxerr;
-		break;
+                return 1;
+            }
+        }
+        if (!combine) {
+            *pval = OPENSSL_malloc(it->size);
+            if (!*pval)
+                goto memerr;
+            OPENSSL_memset(*pval, 0, it->size);
+        }
+        asn1_set_choice_selector(pval, -1, it);
+        if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
+            goto auxerr2;
+        break;
 
-		case ASN1_ITYPE_NDEF_SEQUENCE:
-		case ASN1_ITYPE_SEQUENCE:
-		if (asn1_cb)
-			{
-			i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
-			if (!i)
-				goto auxerr;
-			if (i==2)
-				{
+    case ASN1_ITYPE_NDEF_SEQUENCE:
+    case ASN1_ITYPE_SEQUENCE:
+        if (asn1_cb) {
+            i = asn1_cb(ASN1_OP_NEW_PRE, pval, it, NULL);
+            if (!i)
+                goto auxerr;
+            if (i == 2) {
 #ifdef CRYPTO_MDEBUG
-				if (it->sname)
-					CRYPTO_pop_info();
+                if (it->sname)
+                    CRYPTO_pop_info();
 #endif
-				return 1;
-				}
-			}
-		if (!combine)
-			{
-			*pval = OPENSSL_malloc(it->size);
-			if (!*pval)
-				goto memerr;
-			memset(*pval, 0, it->size);
-			asn1_refcount_set_one(pval, it);
-			asn1_enc_init(pval, it);
-			}
-		for (i = 0, tt = it->templates; i < it->tcount; tt++, i++)
-			{
-			pseqval = asn1_get_field_ptr(pval, tt);
-			if (!ASN1_template_new(pseqval, tt))
-				goto memerr;
-			}
-		if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
-				goto auxerr;
-		break;
-	}
+                return 1;
+            }
+        }
+        if (!combine) {
+            *pval = OPENSSL_malloc(it->size);
+            if (!*pval)
+                goto memerr;
+            OPENSSL_memset(*pval, 0, it->size);
+            asn1_refcount_set_one(pval, it);
+            asn1_enc_init(pval, it);
+        }
+        for (i = 0, tt = it->templates; i < it->tcount; tt++, i++) {
+            pseqval = asn1_get_field_ptr(pval, tt);
+            if (!ASN1_template_new(pseqval, tt))
+                goto memerr2;
+        }
+        if (asn1_cb && !asn1_cb(ASN1_OP_NEW_POST, pval, it, NULL))
+            goto auxerr2;
+        break;
+    }
 #ifdef CRYPTO_MDEBUG
-	if (it->sname) CRYPTO_pop_info();
+    if (it->sname)
+        CRYPTO_pop_info();
 #endif
-	return 1;
+    return 1;
 
-	memerr:
-	OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-	ASN1_item_ex_free(pval, it);
+ memerr2:
+    ASN1_item_ex_free(pval, it);
+ memerr:
+    OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
 #ifdef CRYPTO_MDEBUG
-	if (it->sname) CRYPTO_pop_info();
+    if (it->sname)
+        CRYPTO_pop_info();
 #endif
-	return 0;
+    return 0;
 
-	auxerr:
-	OPENSSL_PUT_ERROR(ASN1, ASN1_R_AUX_ERROR);
-	ASN1_item_ex_free(pval, it);
+ auxerr2:
+    ASN1_item_ex_free(pval, it);
+ auxerr:
+    OPENSSL_PUT_ERROR(ASN1, ASN1_R_AUX_ERROR);
 #ifdef CRYPTO_MDEBUG
-	if (it->sname) CRYPTO_pop_info();
+    if (it->sname)
+        CRYPTO_pop_info();
 #endif
-	return 0;
+    return 0;
 
-	}
+}
 
 static void asn1_item_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
-	{
-	const ASN1_EXTERN_FUNCS *ef;
+{
+    const ASN1_EXTERN_FUNCS *ef;
 
-	switch(it->itype)
-		{
+    switch (it->itype) {
 
-		case ASN1_ITYPE_EXTERN:
-		ef = it->funcs;
-		if (ef && ef->asn1_ex_clear) 
-			ef->asn1_ex_clear(pval, it);
-		else *pval = NULL;
-		break;
+    case ASN1_ITYPE_EXTERN:
+        ef = it->funcs;
+        if (ef && ef->asn1_ex_clear)
+            ef->asn1_ex_clear(pval, it);
+        else
+            *pval = NULL;
+        break;
 
+    case ASN1_ITYPE_PRIMITIVE:
+        if (it->templates)
+            asn1_template_clear(pval, it->templates);
+        else
+            asn1_primitive_clear(pval, it);
+        break;
 
-		case ASN1_ITYPE_PRIMITIVE:
-		if (it->templates) 
-			asn1_template_clear(pval, it->templates);
-		else
-			asn1_primitive_clear(pval, it);
-		break;
+    case ASN1_ITYPE_MSTRING:
+        asn1_primitive_clear(pval, it);
+        break;
 
-		case ASN1_ITYPE_MSTRING:
-		asn1_primitive_clear(pval, it);
-		break;
-
-		case ASN1_ITYPE_COMPAT:
-		case ASN1_ITYPE_CHOICE:
-		case ASN1_ITYPE_SEQUENCE:
-		case ASN1_ITYPE_NDEF_SEQUENCE:
-		*pval = NULL;
-		break;
-		}
-	}
-
+    case ASN1_ITYPE_COMPAT:
+    case ASN1_ITYPE_CHOICE:
+    case ASN1_ITYPE_SEQUENCE:
+    case ASN1_ITYPE_NDEF_SEQUENCE:
+        *pval = NULL;
+        break;
+    }
+}
 
 int ASN1_template_new(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
-	{
-	const ASN1_ITEM *it = ASN1_ITEM_ptr(tt->item);
-	int ret;
-	if (tt->flags & ASN1_TFLG_OPTIONAL)
-		{
-		asn1_template_clear(pval, tt);
-		return 1;
-		}
-	/* If ANY DEFINED BY nothing to do */
+{
+    const ASN1_ITEM *it = ASN1_ITEM_ptr(tt->item);
+    int ret;
+    if (tt->flags & ASN1_TFLG_OPTIONAL) {
+        asn1_template_clear(pval, tt);
+        return 1;
+    }
+    /* If ANY DEFINED BY nothing to do */
 
-	if (tt->flags & ASN1_TFLG_ADB_MASK)
-		{
-		*pval = NULL;
-		return 1;
-		}
+    if (tt->flags & ASN1_TFLG_ADB_MASK) {
+        *pval = NULL;
+        return 1;
+    }
 #ifdef CRYPTO_MDEBUG
-	if (tt->field_name)
-		CRYPTO_push_info(tt->field_name);
+    if (tt->field_name)
+        CRYPTO_push_info(tt->field_name);
 #endif
-	/* If SET OF or SEQUENCE OF, its a STACK */
-	if (tt->flags & ASN1_TFLG_SK_MASK)
-		{
-		STACK_OF(ASN1_VALUE) *skval;
-		skval = sk_ASN1_VALUE_new_null();
-		if (!skval)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-			ret = 0;
-			goto done;
-			}
-		*pval = (ASN1_VALUE *)skval;
-		ret = 1;
-		goto done;
-		}
-	/* Otherwise pass it back to the item routine */
-	ret = asn1_item_ex_combine_new(pval, it, tt->flags & ASN1_TFLG_COMBINE);
-	done:
+    /* If SET OF or SEQUENCE OF, its a STACK */
+    if (tt->flags & ASN1_TFLG_SK_MASK) {
+        STACK_OF(ASN1_VALUE) *skval;
+        skval = sk_ASN1_VALUE_new_null();
+        if (!skval) {
+            OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+            ret = 0;
+            goto done;
+        }
+        *pval = (ASN1_VALUE *)skval;
+        ret = 1;
+        goto done;
+    }
+    /* Otherwise pass it back to the item routine */
+    ret = asn1_item_ex_combine_new(pval, it, tt->flags & ASN1_TFLG_COMBINE);
+ done:
 #ifdef CRYPTO_MDEBUG
-	if (it->sname)
-		CRYPTO_pop_info();
+    if (it->sname)
+        CRYPTO_pop_info();
 #endif
-	return ret;
-	}
+    return ret;
+}
 
 static void asn1_template_clear(ASN1_VALUE **pval, const ASN1_TEMPLATE *tt)
-	{
-	/* If ADB or STACK just NULL the field */
-	if (tt->flags & (ASN1_TFLG_ADB_MASK|ASN1_TFLG_SK_MASK)) 
-		*pval = NULL;
-	else
-		asn1_item_clear(pval, ASN1_ITEM_ptr(tt->item));
-	}
+{
+    /* If ADB or STACK just NULL the field */
+    if (tt->flags & (ASN1_TFLG_ADB_MASK | ASN1_TFLG_SK_MASK))
+        *pval = NULL;
+    else
+        asn1_item_clear(pval, ASN1_ITEM_ptr(tt->item));
+}
 
-
-/* NB: could probably combine most of the real XXX_new() behaviour and junk
+/*
+ * NB: could probably combine most of the real XXX_new() behaviour and junk
  * all the old functions.
  */
 
 int ASN1_primitive_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
-	{
-	ASN1_TYPE *typ;
-	ASN1_STRING *str;
-	int utype;
+{
+    ASN1_TYPE *typ;
+    ASN1_STRING *str;
+    int utype;
 
-	if (!it)
-		return 0;
+    if (!it)
+        return 0;
 
-	if (it->funcs)
-		{
-		const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
-		if (pf->prim_new)
-			return pf->prim_new(pval, it);
-		}
+    if (it->funcs) {
+        const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
+        if (pf->prim_new)
+            return pf->prim_new(pval, it);
+    }
 
-	if (it->itype == ASN1_ITYPE_MSTRING)
-		utype = -1;
-	else
-		utype = it->utype;
-	switch(utype)
-		{
-		case V_ASN1_OBJECT:
-		*pval = (ASN1_VALUE *)OBJ_nid2obj(NID_undef);
-		return 1;
+    if (it->itype == ASN1_ITYPE_MSTRING)
+        utype = -1;
+    else
+        utype = it->utype;
+    switch (utype) {
+    case V_ASN1_OBJECT:
+        *pval = (ASN1_VALUE *)OBJ_nid2obj(NID_undef);
+        return 1;
 
-		case V_ASN1_BOOLEAN:
-		*(ASN1_BOOLEAN *)pval = it->size;
-		return 1;
+    case V_ASN1_BOOLEAN:
+        *(ASN1_BOOLEAN *)pval = it->size;
+        return 1;
 
-		case V_ASN1_NULL:
-		*pval = (ASN1_VALUE *)1;
-		return 1;
+    case V_ASN1_NULL:
+        *pval = (ASN1_VALUE *)1;
+        return 1;
 
-		case V_ASN1_ANY:
-		typ = OPENSSL_malloc(sizeof(ASN1_TYPE));
-		if (!typ)
-			return 0;
-		typ->value.ptr = NULL;
-		typ->type = -1;
-		*pval = (ASN1_VALUE *)typ;
-		break;
+    case V_ASN1_ANY:
+        typ = OPENSSL_malloc(sizeof(ASN1_TYPE));
+        if (!typ)
+            return 0;
+        typ->value.ptr = NULL;
+        typ->type = -1;
+        *pval = (ASN1_VALUE *)typ;
+        break;
 
-		default:
-		str = ASN1_STRING_type_new(utype);
-		if (it->itype == ASN1_ITYPE_MSTRING && str)
-			str->flags |= ASN1_STRING_FLAG_MSTRING;
-		*pval = (ASN1_VALUE *)str;
-		break;
-		}
-	if (*pval)
-		return 1;
-	return 0;
-	}
+    default:
+        str = ASN1_STRING_type_new(utype);
+        if (it->itype == ASN1_ITYPE_MSTRING && str)
+            str->flags |= ASN1_STRING_FLAG_MSTRING;
+        *pval = (ASN1_VALUE *)str;
+        break;
+    }
+    if (*pval)
+        return 1;
+    return 0;
+}
 
 static void asn1_primitive_clear(ASN1_VALUE **pval, const ASN1_ITEM *it)
-	{
-	int utype;
-	if (it && it->funcs)
-		{
-		const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
-		if (pf->prim_clear)
-			pf->prim_clear(pval, it);
-		else 
-			*pval = NULL;
-		return;
-		}
-	if (!it || (it->itype == ASN1_ITYPE_MSTRING))
-		utype = -1;
-	else
-		utype = it->utype;
-	if (utype == V_ASN1_BOOLEAN)
-		*(ASN1_BOOLEAN *)pval = it->size;
-	else *pval = NULL;
-	}
+{
+    int utype;
+    if (it && it->funcs) {
+        const ASN1_PRIMITIVE_FUNCS *pf = it->funcs;
+        if (pf->prim_clear)
+            pf->prim_clear(pval, it);
+        else
+            *pval = NULL;
+        return;
+    }
+    if (!it || (it->itype == ASN1_ITYPE_MSTRING))
+        utype = -1;
+    else
+        utype = it->utype;
+    if (utype == V_ASN1_BOOLEAN)
+        *(ASN1_BOOLEAN *)pval = it->size;
+    else
+        *pval = NULL;
+}
diff --git a/src/crypto/asn1/tasn_prn.c b/src/crypto/asn1/tasn_prn.c
deleted file mode 100644
index a574055..0000000
--- a/src/crypto/asn1/tasn_prn.c
+++ /dev/null
@@ -1,642 +0,0 @@
-/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to.  The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *    "This product includes cryptographic software written by
- *     Eric Young (eay@cryptsoft.com)"
- *    The word 'cryptographic' can be left out if the rouines from the library
- *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- *    the apps directory (application code) you must include an acknowledgement:
- *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed.  i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.] */
-
-#include <openssl/asn1.h>
-
-#include <time.h>
-
-#include <openssl/asn1t.h>
-#include <openssl/err.h>
-#include <openssl/obj.h>
-#include <openssl/mem.h>
-
-#include "asn1_locl.h"
-
-
-
-/* Print routines.
- */
-
-/* ASN1_PCTX routines */
-
-static ASN1_PCTX default_pctx = 
-	{
-	ASN1_PCTX_FLAGS_SHOW_ABSENT,	/* flags */
-	0,	/* nm_flags */
-	0,	/* cert_flags */
-	0,	/* oid_flags */
-	0	/* str_flags */
-	};
-	
-
-ASN1_PCTX *ASN1_PCTX_new(void)
-	{
-	ASN1_PCTX *ret;
-	ret = OPENSSL_malloc(sizeof(ASN1_PCTX));
-	if (ret == NULL)
-		{
-		OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-		return NULL;
-		}
-	ret->flags = 0;
-	ret->nm_flags = 0;
-	ret->cert_flags = 0;
-	ret->oid_flags = 0;
-	ret->str_flags = 0;
-	return ret;
-	}
-
-void ASN1_PCTX_free(ASN1_PCTX *p)
-	{
-	OPENSSL_free(p);
-	}
-
-unsigned long ASN1_PCTX_get_flags(ASN1_PCTX *p)
-	{
-	return p->flags;
-	}
-
-void ASN1_PCTX_set_flags(ASN1_PCTX *p, unsigned long flags)
-	{
-	p->flags = flags;
-	}
-
-unsigned long ASN1_PCTX_get_nm_flags(ASN1_PCTX *p)
-	{
-	return p->nm_flags;
-	}
-
-void ASN1_PCTX_set_nm_flags(ASN1_PCTX *p, unsigned long flags)
-	{
-	p->nm_flags = flags;
-	}
-
-unsigned long ASN1_PCTX_get_cert_flags(ASN1_PCTX *p)
-	{
-	return p->cert_flags;
-	}
-
-void ASN1_PCTX_set_cert_flags(ASN1_PCTX *p, unsigned long flags)
-	{
-	p->cert_flags = flags;
-	}
-
-unsigned long ASN1_PCTX_get_oid_flags(ASN1_PCTX *p)
-	{
-	return p->oid_flags;
-	}
-
-void ASN1_PCTX_set_oid_flags(ASN1_PCTX *p, unsigned long flags)
-	{
-	p->oid_flags = flags;
-	}
-
-unsigned long ASN1_PCTX_get_str_flags(ASN1_PCTX *p)
-	{
-	return p->str_flags;
-	}
-
-void ASN1_PCTX_set_str_flags(ASN1_PCTX *p, unsigned long flags)
-	{
-	p->str_flags = flags;
-	}
-
-/* Main print routines */
-
-static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
-				const ASN1_ITEM *it,
-				const char *fname, const char *sname,
-				int nohdr, const ASN1_PCTX *pctx);
-
-int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
-				const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx);
-
-static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld,
-				const ASN1_ITEM *it, int indent,
-				const char *fname, const char *sname,
-				const ASN1_PCTX *pctx);
-
-static int asn1_print_fsname(BIO *out, int indent,
-			const char *fname, const char *sname,
-			const ASN1_PCTX *pctx);
-
-int ASN1_item_print(BIO *out, ASN1_VALUE *ifld, int indent,
-				const ASN1_ITEM *it, const ASN1_PCTX *pctx)
-	{
-	const char *sname;
-	if (pctx == NULL)
-		pctx = &default_pctx;
-	if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME)
-		sname = NULL;
-	else
-		sname = it->sname;
-	return asn1_item_print_ctx(out, &ifld, indent, it,
-							NULL, sname, 0, pctx);
-	}
-
-static int asn1_item_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
-				const ASN1_ITEM *it,
-				const char *fname, const char *sname,
-				int nohdr, const ASN1_PCTX *pctx)
-	{
-	const ASN1_TEMPLATE *tt;
-	const ASN1_EXTERN_FUNCS *ef;
-	ASN1_VALUE **tmpfld;
-	const ASN1_AUX *aux = it->funcs;
-	ASN1_aux_cb *asn1_cb;
-	ASN1_PRINT_ARG parg;
-	int i;
-	if (aux && aux->asn1_cb)
-		{
-		parg.out = out;
-		parg.indent = indent;
-		parg.pctx = pctx;
-		asn1_cb = aux->asn1_cb;
-		}
-	else asn1_cb = 0;
-
-	if(*fld == NULL)
-		{
-		if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_ABSENT)
-			{
-			if (!nohdr && !asn1_print_fsname(out, indent,
-							fname, sname, pctx))
-				return 0;
-			if (BIO_puts(out, "<ABSENT>\n") <= 0)
-				return 0;
-			}
-		return 1;
-		}
-
-	switch(it->itype)
-		{
-		case ASN1_ITYPE_PRIMITIVE:
-		if(it->templates)
-			{
-			if (!asn1_template_print_ctx(out, fld, indent,
-							it->templates, pctx))
-				return 0;
-			break;
-			}
-		/* fall thru */
-		case ASN1_ITYPE_MSTRING:
-		if (!asn1_primitive_print(out, fld, it,
-				indent, fname, sname,pctx))
-			return 0;
-		break;
-
-		case ASN1_ITYPE_EXTERN:
-		if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx))
-			return 0;
-		/* Use new style print routine if possible */
-		ef = it->funcs;
-		if (ef && ef->asn1_ex_print)
-			{
-			i = ef->asn1_ex_print(out, fld, indent, "", pctx);
-			if (!i)
-				return 0;
-			if ((i == 2) && (BIO_puts(out, "\n") <= 0))
-				return 0;
-			return 1;
-			}
-		else if (sname && 
-			BIO_printf(out, ":EXTERNAL TYPE %s\n", sname) <= 0)
-			return 0;
-		break;
-
-		case ASN1_ITYPE_CHOICE:
-#if 0
-		if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx))
-			return 0;
-#endif
-		/* CHOICE type, get selector */
-		i = asn1_get_choice_selector(fld, it);
-		/* This should never happen... */
-		if((i < 0) || (i >= it->tcount))
-			{
-			if (BIO_printf(out,
-				"ERROR: selector [%d] invalid\n", i) <= 0)
-				return 0;
-			return 1;
-			}
-		tt = it->templates + i;
-		tmpfld = asn1_get_field_ptr(fld, tt);
-		if (!asn1_template_print_ctx(out, tmpfld, indent, tt, pctx))
-			return 0;
-		break;
-
-		case ASN1_ITYPE_SEQUENCE:
-		case ASN1_ITYPE_NDEF_SEQUENCE:
-		if (!nohdr && !asn1_print_fsname(out, indent, fname, sname, pctx))
-			return 0;
-		if (fname || sname)
-			{
-			if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE)
-				{
-				if (BIO_puts(out, " {\n") <= 0)
-					return 0;
-				}
-			else
-				{
-				if (BIO_puts(out, "\n") <= 0)
-					return 0;
-				}
-			}
-
-		if (asn1_cb)
-			{
-			i = asn1_cb(ASN1_OP_PRINT_PRE, fld, it, &parg);
-			if (i == 0)
-				return 0;
-			if (i == 2)
-				return 1;
-			}
-
-		/* Print each field entry */
-		for(i = 0, tt = it->templates; i < it->tcount; i++, tt++)
-			{
-			const ASN1_TEMPLATE *seqtt;
-			seqtt = asn1_do_adb(fld, tt, 1);
-			if (!seqtt)
-				return 0;
-			tmpfld = asn1_get_field_ptr(fld, seqtt);
-			if (!asn1_template_print_ctx(out, tmpfld,
-						indent + 2, seqtt, pctx))
-				return 0;
-			}
-		if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE)
-			{
-			if (BIO_printf(out, "%*s}\n", indent, "") < 0)
-				return 0;
-			}
-
-		if (asn1_cb)
-			{
-			i = asn1_cb(ASN1_OP_PRINT_POST, fld, it, &parg);
-			if (i == 0)
-				return 0;
-			}
-		break;
-
-		default:
-		BIO_printf(out, "Unprocessed type %d\n", it->itype);
-		return 0;
-		}
-
-	return 1;
-	}
-
-int asn1_template_print_ctx(BIO *out, ASN1_VALUE **fld, int indent,
-				const ASN1_TEMPLATE *tt, const ASN1_PCTX *pctx)
-	{
-	int flags;
-	size_t i;
-	const char *sname, *fname;
-	flags = tt->flags;
-	if(pctx->flags & ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME)
-		sname = ASN1_ITEM_ptr(tt->item)->sname;
-	else
-		sname = NULL;
-	if(pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME)
-		fname = NULL;
-	else
-		fname = tt->field_name;
-	if(flags & ASN1_TFLG_SK_MASK)
-		{
-		const char *tname;
-		ASN1_VALUE *skitem;
-		STACK_OF(ASN1_VALUE) *stack;
-
-		/* SET OF, SEQUENCE OF */
-		if (fname)
-			{
-			if(pctx->flags & ASN1_PCTX_FLAGS_SHOW_SSOF)
-				{
-				if(flags & ASN1_TFLG_SET_OF)
-					tname = "SET";
-				else
-					tname = "SEQUENCE";
-				if (BIO_printf(out, "%*s%s OF %s {\n",
-					indent, "", tname, tt->field_name) <= 0)
-					return 0;
-				}
-			else if (BIO_printf(out, "%*s%s:\n", indent, "",
-					fname) <= 0)
-				return 0;
-			}
-		stack = (STACK_OF(ASN1_VALUE) *)*fld;
-		for(i = 0; i < sk_ASN1_VALUE_num(stack); i++)
-			{
-			if ((i > 0) && (BIO_puts(out, "\n") <= 0))
-				return 0;
-
-			skitem = sk_ASN1_VALUE_value(stack, i);
-			if (!asn1_item_print_ctx(out, &skitem, indent + 2,
-				ASN1_ITEM_ptr(tt->item), NULL, NULL, 1, pctx))
-				return 0;
-			}
-		if (!i && BIO_printf(out, "%*s<EMPTY>\n", indent + 2, "") <= 0)
-				return 0;
-		if(pctx->flags & ASN1_PCTX_FLAGS_SHOW_SEQUENCE)
-			{
-			if (BIO_printf(out, "%*s}\n", indent, "") <= 0)
-				return 0;
-			}
-		return 1;
-		}
-	return asn1_item_print_ctx(out, fld, indent, ASN1_ITEM_ptr(tt->item),
-							fname, sname, 0, pctx);
-	}
-
-static int asn1_print_fsname(BIO *out, int indent,
-			const char *fname, const char *sname,
-			const ASN1_PCTX *pctx)
-	{
-	static char spaces[] = "                    ";
-	const int nspaces = sizeof(spaces) - 1;
-
-#if 0
-	if (!sname && !fname)
-		return 1;
-#endif
-
-	while (indent > nspaces)
-		{
-		if (BIO_write(out, spaces, nspaces) != nspaces)
-			return 0;
-		indent -= nspaces;
-		}
-	if (BIO_write(out, spaces, indent) != indent)
-		return 0;
-	if (pctx->flags & ASN1_PCTX_FLAGS_NO_STRUCT_NAME)
-		sname = NULL;
-	if (pctx->flags & ASN1_PCTX_FLAGS_NO_FIELD_NAME)
-		fname = NULL;
-	if (!sname && !fname)
-		return 1;
-	if (fname)
-		{
-		if (BIO_puts(out, fname) <= 0)
-			return 0;
-		}
-	if (sname)
-		{
-		if (fname)
-			{
-			if (BIO_printf(out, " (%s)", sname) <= 0)
-				return 0;
-			}
-		else
-			{
-			if (BIO_puts(out, sname) <= 0)
-				return 0;
-			}
-		}
-	if (BIO_write(out, ": ", 2) != 2)
-		return 0;
-	return 1;
-	}
-
-static int asn1_print_boolean_ctx(BIO *out, int boolval,
-							const ASN1_PCTX *pctx)
-	{
-	const char *str;
-	switch (boolval)
-		{
-		case -1:
-		str = "BOOL ABSENT";
-		break;
-
-		case 0:
-		str = "FALSE";
-		break;
-
-		default:
-		str = "TRUE";
-		break;
-
-		}
-
-	if (BIO_puts(out, str) <= 0)
-		return 0;
-	return 1;
-
-	}
-
-static int asn1_print_integer_ctx(BIO *out, ASN1_INTEGER *str,
-						const ASN1_PCTX *pctx)
-	{
-	BIGNUM *bn = NULL;
-	char *s = NULL;
-	int ret = 1;
-
-	bn = ASN1_INTEGER_to_BN(str, NULL);
-	if (bn == NULL) {
-		return 0;
-	}
-	s = BN_bn2dec(bn);
-	BN_free(bn);
-	if (s == NULL) {
-		return 0;
-	}
-
-	if (BIO_puts(out, s) <= 0) {
-		ret = 0;
-	}
-	OPENSSL_free(s);
-	return ret;
-	}
-
-static int asn1_print_oid_ctx(BIO *out, const ASN1_OBJECT *oid,
-						const ASN1_PCTX *pctx)
-	{
-	char objbuf[80];
-	const char *ln;
-	ln = OBJ_nid2ln(OBJ_obj2nid(oid));
-	if(!ln)
-		ln = "";
-	OBJ_obj2txt(objbuf, sizeof objbuf, oid, 1);
-	if (BIO_printf(out, "%s (%s)", ln, objbuf) <= 0)
-		return 0;
-	return 1;
-	}
-
-static int asn1_print_obstring_ctx(BIO *out, ASN1_STRING *str, int indent,
-						const ASN1_PCTX *pctx)
-	{
-	if (str->type == V_ASN1_BIT_STRING)
-		{
-		if (BIO_printf(out, " (%ld unused bits)\n",
-					str->flags & 0x7) <= 0)
-				return 0;
-		}
-	else if (BIO_puts(out, "\n") <= 0)
-		return 0;
-	if (str->length > 0 && !BIO_hexdump(out, str->data, str->length, indent + 2)) {
-		return 0;
-	}
-	return 1;
-	}
-
-static int asn1_primitive_print(BIO *out, ASN1_VALUE **fld,
-				const ASN1_ITEM *it, int indent,
-				const char *fname, const char *sname,
-				const ASN1_PCTX *pctx)
-	{
-	long utype;
-	ASN1_STRING *str;
-	int ret = 1, needlf = 1;
-	const char *pname;
-	const ASN1_PRIMITIVE_FUNCS *pf;
-	pf = it->funcs;
-	if (!asn1_print_fsname(out, indent, fname, sname, pctx))
-			return 0;
-	if (pf && pf->prim_print)
-		return pf->prim_print(out, fld, it, indent, pctx);
-	str = (ASN1_STRING *)*fld;
-	if (it->itype == ASN1_ITYPE_MSTRING)
-		utype = str->type & ~V_ASN1_NEG;
-	else
-		utype = it->utype;
-	if (utype == V_ASN1_ANY)
-		{
-		ASN1_TYPE *atype = (ASN1_TYPE *)*fld;
-		utype = atype->type;
-		fld = &atype->value.asn1_value;
-		str = (ASN1_STRING *)*fld;
-		if (pctx->flags & ASN1_PCTX_FLAGS_NO_ANY_TYPE)
-			pname = NULL;
-		else 
-			pname = ASN1_tag2str(utype);
-		}
-	else
-		{
-		if (pctx->flags & ASN1_PCTX_FLAGS_SHOW_TYPE)
-			pname = ASN1_tag2str(utype);
-		else 
-			pname = NULL;
-		}
-
-	if (utype == V_ASN1_NULL)
-		{
-		if (BIO_puts(out, "NULL\n") <= 0)
-			return 0;
-		return 1;
-		}
-
-	if (pname)
-		{
-		if (BIO_puts(out, pname) <= 0)
-			return 0;
-		if (BIO_puts(out, ":") <= 0)
-			return 0;
-		}
-
-	switch (utype)
-		{
-		case V_ASN1_BOOLEAN:
-			{
-			int boolval = *(int *)fld;
-			if (boolval == -1)
-				boolval = it->size;
-			ret = asn1_print_boolean_ctx(out, boolval, pctx);
-			}
-		break;
-
-		case V_ASN1_INTEGER:
-		case V_ASN1_ENUMERATED:
-		ret = asn1_print_integer_ctx(out, str, pctx);
-		break;
-
-		case V_ASN1_UTCTIME:
-		ret = ASN1_UTCTIME_print(out, str);
-		break;
-
-		case V_ASN1_GENERALIZEDTIME:
-		ret = ASN1_GENERALIZEDTIME_print(out, str);
-		break;
-
-		case V_ASN1_OBJECT:
-		ret = asn1_print_oid_ctx(out, (const ASN1_OBJECT *)*fld, pctx);
-		break;
-
-		case V_ASN1_OCTET_STRING:
-		case V_ASN1_BIT_STRING:
-		ret = asn1_print_obstring_ctx(out, str, indent, pctx);
-		needlf = 0;
-		break;
-
-		case V_ASN1_SEQUENCE:
-		case V_ASN1_SET:
-		case V_ASN1_OTHER:
-		if (BIO_puts(out, "\n") <= 0)
-			return 0;
-		if (ASN1_parse_dump(out, str->data, str->length,
-						indent, 0) <= 0)
-			ret = 0;
-		needlf = 0;
-		break;
-
-		default:
-		ret = ASN1_STRING_print_ex(out, str, pctx->str_flags);
-
-		}
-	if (!ret)
-		return 0;
-	if (needlf && BIO_puts(out, "\n") <= 0)
-		return 0;
-	return 1;
-	}
diff --git a/src/crypto/asn1/tasn_typ.c b/src/crypto/asn1/tasn_typ.c
index f004b0d..7c5bfd5 100644
--- a/src/crypto/asn1/tasn_typ.c
+++ b/src/crypto/asn1/tasn_typ.c
@@ -58,20 +58,19 @@
 
 #include <openssl/asn1t.h>
 
-
 /* Declarations for string types */
 
 #define IMPLEMENT_ASN1_STRING_FUNCTIONS(sname) \
-	IMPLEMENT_ASN1_TYPE(sname) \
-	IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(sname, sname, sname) \
-	sname *sname##_new(void) \
-	{ \
-		return ASN1_STRING_type_new(V_##sname); \
-	} \
-	void sname##_free(sname *x) \
-	{ \
-		ASN1_STRING_free(x); \
-	}
+        IMPLEMENT_ASN1_TYPE(sname) \
+        IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(sname, sname, sname) \
+        sname *sname##_new(void) \
+        { \
+                return ASN1_STRING_type_new(V_##sname); \
+        } \
+        void sname##_free(sname *x) \
+        { \
+                ASN1_STRING_free(x); \
+        }
 
 IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_OCTET_STRING)
 IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_INTEGER)
@@ -88,50 +87,45 @@
 IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_UNIVERSALSTRING)
 IMPLEMENT_ASN1_STRING_FUNCTIONS(ASN1_BMPSTRING)
 
-IMPLEMENT_ASN1_TYPE(ASN1_NULL);
-IMPLEMENT_ASN1_FUNCTIONS(ASN1_NULL);
+IMPLEMENT_ASN1_TYPE(ASN1_NULL)
+IMPLEMENT_ASN1_FUNCTIONS(ASN1_NULL)
 
-IMPLEMENT_ASN1_TYPE(ASN1_OBJECT);
+IMPLEMENT_ASN1_TYPE(ASN1_OBJECT)
 
-IMPLEMENT_ASN1_TYPE(ASN1_ANY);
+IMPLEMENT_ASN1_TYPE(ASN1_ANY)
 
-/* Just swallow an ASN1_SEQUENCE in an ASN1_STRING */;
-IMPLEMENT_ASN1_TYPE(ASN1_SEQUENCE);
+/* Just swallow an ASN1_SEQUENCE in an ASN1_STRING */
+IMPLEMENT_ASN1_TYPE(ASN1_SEQUENCE)
 
-IMPLEMENT_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE);
+IMPLEMENT_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE)
 
-/* Multistring types */;
+/* Multistring types */
 
-IMPLEMENT_ASN1_MSTRING(ASN1_PRINTABLE, B_ASN1_PRINTABLE);
-IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, ASN1_PRINTABLE);
+IMPLEMENT_ASN1_MSTRING(ASN1_PRINTABLE, B_ASN1_PRINTABLE)
+IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, ASN1_PRINTABLE)
 
-IMPLEMENT_ASN1_MSTRING(DISPLAYTEXT, B_ASN1_DISPLAYTEXT);
-IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, DISPLAYTEXT);
+IMPLEMENT_ASN1_MSTRING(DISPLAYTEXT, B_ASN1_DISPLAYTEXT)
+IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, DISPLAYTEXT)
 
-IMPLEMENT_ASN1_MSTRING(DIRECTORYSTRING, B_ASN1_DIRECTORYSTRING);
-IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, DIRECTORYSTRING);
+IMPLEMENT_ASN1_MSTRING(DIRECTORYSTRING, B_ASN1_DIRECTORYSTRING)
+IMPLEMENT_ASN1_FUNCTIONS_name(ASN1_STRING, DIRECTORYSTRING)
 
-/* Three separate BOOLEAN type: normal, DEFAULT TRUE and DEFAULT FALSE */;
-IMPLEMENT_ASN1_TYPE_ex(ASN1_BOOLEAN, ASN1_BOOLEAN, -1);
-IMPLEMENT_ASN1_TYPE_ex(ASN1_TBOOLEAN, ASN1_BOOLEAN, 1);
-IMPLEMENT_ASN1_TYPE_ex(ASN1_FBOOLEAN, ASN1_BOOLEAN, 0);
+/* Three separate BOOLEAN type: normal, DEFAULT TRUE and DEFAULT FALSE */
+IMPLEMENT_ASN1_TYPE_ex(ASN1_BOOLEAN, ASN1_BOOLEAN, -1)
+IMPLEMENT_ASN1_TYPE_ex(ASN1_TBOOLEAN, ASN1_BOOLEAN, 1)
+IMPLEMENT_ASN1_TYPE_ex(ASN1_FBOOLEAN, ASN1_BOOLEAN, 0)
 
-/* Special, OCTET STRING with indefinite length constructed support */;
+/* Special, OCTET STRING with indefinite length constructed support */
 
-IMPLEMENT_ASN1_TYPE_ex(ASN1_OCTET_STRING_NDEF, ASN1_OCTET_STRING,
-                       ASN1_TFLG_NDEF);
+IMPLEMENT_ASN1_TYPE_ex(ASN1_OCTET_STRING_NDEF, ASN1_OCTET_STRING, ASN1_TFLG_NDEF)
 
-ASN1_ITEM_TEMPLATE(ASN1_SEQUENCE_ANY) = ASN1_EX_TEMPLATE_TYPE(
-    ASN1_TFLG_SEQUENCE_OF, 0, ASN1_SEQUENCE_ANY, ASN1_ANY);
-ASN1_ITEM_TEMPLATE_END(ASN1_SEQUENCE_ANY);
+ASN1_ITEM_TEMPLATE(ASN1_SEQUENCE_ANY) =
+        ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, ASN1_SEQUENCE_ANY, ASN1_ANY)
+ASN1_ITEM_TEMPLATE_END(ASN1_SEQUENCE_ANY)
 
-ASN1_ITEM_TEMPLATE(ASN1_SET_ANY) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0,
-                                                         ASN1_SET_ANY,
-                                                         ASN1_ANY);
-ASN1_ITEM_TEMPLATE_END(ASN1_SET_ANY);
+ASN1_ITEM_TEMPLATE(ASN1_SET_ANY) =
+        ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0, ASN1_SET_ANY, ASN1_ANY)
+ASN1_ITEM_TEMPLATE_END(ASN1_SET_ANY)
 
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY,
-                                            ASN1_SEQUENCE_ANY,
-                                            ASN1_SEQUENCE_ANY);
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SET_ANY,
-                                            ASN1_SET_ANY);
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY, ASN1_SEQUENCE_ANY)
+IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(ASN1_SEQUENCE_ANY, ASN1_SET_ANY, ASN1_SET_ANY)
diff --git a/src/crypto/asn1/tasn_utl.c b/src/crypto/asn1/tasn_utl.c
index 960cdbb..a7516f6 100644
--- a/src/crypto/asn1/tasn_utl.c
+++ b/src/crypto/asn1/tasn_utl.c
@@ -56,6 +56,7 @@
 
 #include <openssl/asn1.h>
 
+#include <assert.h>
 #include <string.h>
 
 #include <openssl/asn1t.h>
@@ -70,7 +71,7 @@
 /* Utility functions for manipulating fields and offsets */
 
 /* Add 'offset' to 'addr' */
-#define offset2ptr(addr, offset) (void *)(((char *) addr) + offset)
+#define offset2ptr(addr, offset) (void *)(((char *)(addr)) + (offset))
 
 /* Given an ASN1_ITEM CHOICE type return the selector value */
 int asn1_get_choice_selector(ASN1_VALUE **pval, const ASN1_ITEM *it) {
@@ -134,6 +135,8 @@
   if (enc) {
     enc->enc = NULL;
     enc->len = 0;
+    enc->alias_only = 0;
+    enc->alias_only_on_next_parse = 0;
     enc->modified = 1;
   }
 }
@@ -142,11 +145,13 @@
   ASN1_ENCODING *enc;
   enc = asn1_get_enc_ptr(pval, it);
   if (enc) {
-    if (enc->enc) {
+    if (enc->enc && !enc->alias_only) {
       OPENSSL_free(enc->enc);
     }
     enc->enc = NULL;
     enc->len = 0;
+    enc->alias_only = 0;
+    enc->alias_only_on_next_parse = 0;
     enc->modified = 1;
   }
 }
@@ -159,14 +164,23 @@
     return 1;
   }
 
-  if (enc->enc) {
+  if (!enc->alias_only) {
     OPENSSL_free(enc->enc);
   }
-  enc->enc = OPENSSL_malloc(inlen);
-  if (!enc->enc) {
-    return 0;
+
+  enc->alias_only = enc->alias_only_on_next_parse;
+  enc->alias_only_on_next_parse = 0;
+
+  if (enc->alias_only) {
+    enc->enc = (uint8_t *) in;
+  } else {
+    enc->enc = OPENSSL_malloc(inlen);
+    if (!enc->enc) {
+      return 0;
+    }
+    OPENSSL_memcpy(enc->enc, in, inlen);
   }
-  memcpy(enc->enc, in, inlen);
+
   enc->len = inlen;
   enc->modified = 0;
 
@@ -181,7 +195,7 @@
     return 0;
   }
   if (out) {
-    memcpy(*out, enc->enc, enc->len);
+    OPENSSL_memcpy(*out, enc->enc, enc->len);
     *out += enc->len;
   }
   if (len) {
@@ -222,7 +236,7 @@
   sfld = offset2ptr(*pval, adb->offset);
 
   /* Check if NULL */
-  if (!sfld) {
+  if (*sfld == NULL) {
     if (!adb->null_tt) {
       goto err;
     }
diff --git a/src/crypto/time_support.c b/src/crypto/asn1/time_support.c
similarity index 99%
rename from src/crypto/time_support.c
rename to src/crypto/asn1/time_support.c
index ae0f496..194dc3a 100644
--- a/src/crypto/time_support.c
+++ b/src/crypto/asn1/time_support.c
@@ -59,7 +59,7 @@
 #define _POSIX_C_SOURCE 201410L  /* for gmtime_r */
 #endif
 
-#include <openssl/time_support.h>
+#include "asn1_locl.h"
 
 #include <time.h>
 
diff --git a/src/crypto/asn1/x_bignum.c b/src/crypto/asn1/x_bignum.c
deleted file mode 100644
index 5867c4f..0000000
--- a/src/crypto/asn1/x_bignum.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to.  The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *    "This product includes cryptographic software written by
- *     Eric Young (eay@cryptsoft.com)"
- *    The word 'cryptographic' can be left out if the rouines from the library
- *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- *    the apps directory (application code) you must include an acknowledgement:
- *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed.  i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.] */
-
-#include <openssl/asn1.h>
-
-#include <openssl/asn1t.h>
-#include <openssl/bn.h>
-
-
-/* Custom primitive type for BIGNUM handling. This reads in an ASN1_INTEGER as a
- * BIGNUM directly. Currently it ignores the sign which isn't a problem since all
- * BIGNUMs used are non negative and anything that looks negative is normally due
- * to an encoding error.
- */
-
-#define BN_SENSITIVE	1
-
-static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
-static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
-
-static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it);
-static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it);
-
-static const ASN1_PRIMITIVE_FUNCS bignum_pf = {
-	NULL, 0,
-	bn_new,
-	bn_free,
-	0,
-	bn_c2i,
-	bn_i2c,
-	NULL /* prim_print */,
-};
-
-ASN1_ITEM_start(BIGNUM)
-	ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, 0, "BIGNUM"
-ASN1_ITEM_end(BIGNUM)
-
-ASN1_ITEM_start(CBIGNUM)
-	ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, BN_SENSITIVE, "BIGNUM"
-ASN1_ITEM_end(CBIGNUM)
-
-static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
-{
-	*pval = (ASN1_VALUE *)BN_new();
-	if(*pval) return 1;
-	else return 0;
-}
-
-static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
-{
-	if(!*pval) return;
-	if(it->size & BN_SENSITIVE) BN_clear_free((BIGNUM *)*pval);
-	else BN_free((BIGNUM *)*pval);
-	*pval = NULL;
-}
-
-static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it)
-{
-	BIGNUM *bn;
-	int pad;
-	if(!*pval) return -1;
-	bn = (BIGNUM *)*pval;
-	/* If MSB set in an octet we need a padding byte */
-	if(BN_num_bits(bn) & 0x7) pad = 0;
-	else pad = 1;
-	if(cont) {
-		if(pad) *cont++ = 0;
-		BN_bn2bin(bn, cont);
-	}
-	return pad + BN_num_bytes(bn);
-}
-
-static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
-		  int utype, char *free_cont, const ASN1_ITEM *it)
-{
-	BIGNUM *bn;
-	if(!*pval)
-		{
-		if (!bn_new(pval, it))
-			{
-			return 0;
-			}
-		}
-	bn  = (BIGNUM *)*pval;
-	if(!BN_bin2bn(cont, len, bn)) {
-		bn_free(pval, it);
-		return 0;
-	}
-	return 1;
-}
diff --git a/src/crypto/asn1/x_long.c b/src/crypto/asn1/x_long.c
deleted file mode 100644
index 7b1a6fe..0000000
--- a/src/crypto/asn1/x_long.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to.  The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *    "This product includes cryptographic software written by
- *     Eric Young (eay@cryptsoft.com)"
- *    The word 'cryptographic' can be left out if the rouines from the library
- *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- *    the apps directory (application code) you must include an acknowledgement:
- *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed.  i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.] */
-
-#include <openssl/asn1.h>
-
-#include <string.h>
-
-#include <openssl/asn1t.h>
-#include <openssl/bn.h>
-#include <openssl/err.h>
-#include <openssl/mem.h>
-
-
-/* Custom primitive type for long handling. This converts between an ASN1_INTEGER
- * and a long directly.
- */
-
-
-static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
-static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
-
-static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it);
-static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it);
-static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it, int indent, const ASN1_PCTX *pctx);
-
-static const ASN1_PRIMITIVE_FUNCS long_pf = {
-	NULL, 0,
-	long_new,
-	long_free,
-	long_free,	/* Clear should set to initial value */
-	long_c2i,
-	long_i2c,
-	long_print
-};
-
-ASN1_ITEM_start(LONG)
-	ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, ASN1_LONG_UNDEF, "LONG"
-ASN1_ITEM_end(LONG)
-
-ASN1_ITEM_start(ZLONG)
-	ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, 0, "ZLONG"
-ASN1_ITEM_end(ZLONG)
-
-static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
-{
-	*(long *)pval = it->size;
-	return 1;
-}
-
-static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
-{
-	*(long *)pval = it->size;
-}
-
-static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it)
-{
-	long ltmp;
-	unsigned long utmp;
-	int clen, pad, i;
-	/* this exists to bypass broken gcc optimization */
-	char *cp = (char *)pval;
-
-	/* use memcpy, because we may not be long aligned */
-	memcpy(&ltmp, cp, sizeof(long));
-
-	if(ltmp == it->size) return -1;
-	/* Convert the long to positive: we subtract one if negative so
-	 * we can cleanly handle the padding if only the MSB of the leading
-	 * octet is set. 
-	 */
-	if(ltmp < 0) utmp = -ltmp - 1;
-	else utmp = ltmp;
-	clen = BN_num_bits_word(utmp);
-	/* If MSB of leading octet set we need to pad */
-	if(!(clen & 0x7)) pad = 1;
-	else pad = 0;
-
-	/* Convert number of bits to number of octets */
-	clen = (clen + 7) >> 3;
-
-	if(cont) {
-		if(pad) *cont++ = (ltmp < 0) ? 0xff : 0;
-		for(i = clen - 1; i >= 0; i--) {
-			cont[i] = (unsigned char)(utmp & 0xff);
-			if(ltmp < 0) cont[i] ^= 0xff;
-			utmp >>= 8;
-		}
-	}
-	return clen + pad;
-}
-
-static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
-		    int utype, char *free_cont, const ASN1_ITEM *it)
-{
-	int neg, i;
-	long ltmp;
-	unsigned long utmp = 0;
-	char *cp = (char *)pval;
-	if(len > (int)sizeof(long)) {
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
-		return 0;
-	}
-	/* Is it negative? */
-	if(len && (cont[0] & 0x80)) neg = 1;
-	else neg = 0;
-	utmp = 0;
-	for(i = 0; i < len; i++) {
-		utmp <<= 8;
-		if(neg) utmp |= cont[i] ^ 0xff;
-		else utmp |= cont[i];
-	}
-	ltmp = (long)utmp;
-	if(neg) {
-		ltmp++;
-		ltmp = -ltmp;
-	}
-	if(ltmp == it->size) {
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
-		return 0;
-	}
-	memcpy(cp, &ltmp, sizeof(long));
-	return 1;
-}
-
-static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
-			int indent, const ASN1_PCTX *pctx)
-	{
-	return BIO_printf(out, "%ld\n", *(long *)pval);
-	}
diff --git a/src/crypto/base64/base64.c b/src/crypto/base64/base64.c
index 4822fb8..7afadf7 100644
--- a/src/crypto/base64/base64.c
+++ b/src/crypto/base64/base64.c
@@ -60,118 +60,125 @@
 #include <limits.h>
 #include <string.h>
 
+#include <openssl/type_check.h>
+
+#include "../internal.h"
+
+
+/* Encoding. */
 
 static const unsigned char data_bin2ascii[65] =
     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
 #define conv_bin2ascii(a) (data_bin2ascii[(a) & 0x3f])
 
-/* 64 char lines
- * pad input with 0
- * left over chars are set to =
- * 1 byte  => xx==
- * 2 bytes => xxx=
- * 3 bytes => xxxx
- */
-#define BIN_PER_LINE    (64/4*3)
-#define CHUNKS_PER_LINE (64/4)
-#define CHAR_PER_LINE   (64+1)
+OPENSSL_COMPILE_ASSERT(sizeof(((EVP_ENCODE_CTX *)(NULL))->data) % 3 == 0,
+                       data_length_must_be_multiple_of_base64_chunk_size);
 
-/* 0xF0 is a EOLN
- * 0xF1 is ignore but next needs to be 0xF0 (for \r\n processing).
- * 0xF2 is EOF
- * 0xE0 is ignore at start of line.
- * 0xFF is error */
-
-#define B64_EOLN 0xF0
-#define B64_CR 0xF1
-#define B64_EOF 0xF2
-#define B64_WS 0xE0
-#define B64_ERROR 0xFF
-#define B64_NOT_BASE64(a) (((a) | 0x13) == 0xF3)
-
-static const uint8_t data_ascii2bin[128] = {
-    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xF0, 0xFF,
-    0xFF, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF,
-    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xF2, 0xFF, 0x3F,
-    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0xFF, 0xFF,
-    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
-    0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12,
-    0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-    0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24,
-    0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30,
-    0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-};
-
-static uint8_t conv_ascii2bin(uint8_t a) {
-  if (a >= 128) {
-    return 0xFF;
+int EVP_EncodedLength(size_t *out_len, size_t len) {
+  if (len + 2 < len) {
+    return 0;
   }
-  return data_ascii2bin[a];
+  len += 2;
+  len /= 3;
+
+  if (((len << 2) >> 2) != len) {
+    return 0;
+  }
+  len <<= 2;
+
+  if (len + 1 < len) {
+    return 0;
+  }
+  len++;
+
+  *out_len = len;
+  return 1;
 }
 
 void EVP_EncodeInit(EVP_ENCODE_CTX *ctx) {
-  ctx->length = 48;
-  ctx->num = 0;
-  ctx->line_num = 0;
+  OPENSSL_memset(ctx, 0, sizeof(EVP_ENCODE_CTX));
 }
 
 void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len,
                       const uint8_t *in, size_t in_len) {
-  unsigned i, j;
-  unsigned total = 0;
+  size_t total = 0;
 
   *out_len = 0;
   if (in_len == 0) {
     return;
   }
 
-  assert(ctx->length <= sizeof(ctx->enc_data));
+  assert(ctx->data_used < sizeof(ctx->data));
 
-  if (ctx->num + in_len < ctx->length) {
-    memcpy(&ctx->enc_data[ctx->num], in, in_len);
-    ctx->num += in_len;
+  if (sizeof(ctx->data) - ctx->data_used > in_len) {
+    OPENSSL_memcpy(&ctx->data[ctx->data_used], in, in_len);
+    ctx->data_used += (unsigned)in_len;
     return;
   }
-  if (ctx->num != 0) {
-    i = ctx->length - ctx->num;
-    memcpy(&ctx->enc_data[ctx->num], in, i);
-    in += i;
-    in_len -= i;
-    j = EVP_EncodeBlock(out, ctx->enc_data, ctx->length);
-    ctx->num = 0;
-    out += j;
+
+  if (ctx->data_used != 0) {
+    const size_t todo = sizeof(ctx->data) - ctx->data_used;
+    OPENSSL_memcpy(&ctx->data[ctx->data_used], in, todo);
+    in += todo;
+    in_len -= todo;
+
+    size_t encoded = EVP_EncodeBlock(out, ctx->data, sizeof(ctx->data));
+    ctx->data_used = 0;
+
+    out += encoded;
     *(out++) = '\n';
     *out = '\0';
-    total = j + 1;
+
+    total = encoded + 1;
   }
-  while (in_len >= ctx->length) {
-    j = EVP_EncodeBlock(out, in, ctx->length);
-    in += ctx->length;
-    in_len -= ctx->length;
-    out += j;
+
+  while (in_len >= sizeof(ctx->data)) {
+    size_t encoded = EVP_EncodeBlock(out, in, sizeof(ctx->data));
+    in += sizeof(ctx->data);
+    in_len -= sizeof(ctx->data);
+
+    out += encoded;
     *(out++) = '\n';
     *out = '\0';
-    total += j + 1;
+
+    if (total + encoded + 1 < total) {
+      *out_len = 0;
+      return;
+    }
+
+    total += encoded + 1;
   }
+
   if (in_len != 0) {
-    memcpy(&ctx->enc_data[0], in, in_len);
+    OPENSSL_memcpy(ctx->data, in, in_len);
   }
-  ctx->num = in_len;
-  *out_len = total;
+
+  ctx->data_used = (unsigned)in_len;
+
+  if (total > INT_MAX) {
+    /* We cannot signal an error, but we can at least avoid making *out_len
+     * negative. */
+    total = 0;
+  }
+  *out_len = (int)total;
 }
 
 void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len) {
-  unsigned ret = 0;
-
-  if (ctx->num != 0) {
-    ret = EVP_EncodeBlock(out, ctx->enc_data, ctx->num);
-    out[ret++] = '\n';
-    out[ret] = '\0';
-    ctx->num = 0;
+  if (ctx->data_used == 0) {
+    *out_len = 0;
+    return;
   }
-  *out_len = ret;
+
+  size_t encoded = EVP_EncodeBlock(out, ctx->data, ctx->data_used);
+  out[encoded++] = '\n';
+  out[encoded] = '\0';
+  ctx->data_used = 0;
+
+  /* ctx->data_used is bounded by sizeof(ctx->data), so this does not
+   * overflow. */
+  assert(encoded <= INT_MAX);
+  *out_len = (int)encoded;
 }
 
 size_t EVP_EncodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) {
@@ -206,246 +213,223 @@
   return ret;
 }
 
+
+/* Decoding. */
+
 int EVP_DecodedLength(size_t *out_len, size_t len) {
   if (len % 4 != 0) {
     return 0;
   }
+
   *out_len = (len / 4) * 3;
   return 1;
 }
 
+void EVP_DecodeInit(EVP_ENCODE_CTX *ctx) {
+  OPENSSL_memset(ctx, 0, sizeof(EVP_ENCODE_CTX));
+}
+
+/* kBase64ASCIIToBinData maps characters (c < 128) to their base64 value, or
+ * else 0xff if they are invalid. As a special case, the padding character
+ * ('=') is mapped to zero. */
+static const uint8_t kBase64ASCIIToBinData[128] = {
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
+    0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff,
+    0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+    0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
+    0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24,
+    0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
+    0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
+};
+
+static uint8_t base64_ascii_to_bin(uint8_t a) {
+  if (a >= 128) {
+    return 0xFF;
+  }
+
+  return kBase64ASCIIToBinData[a];
+}
+
+/* base64_decode_quad decodes a single “quad” (i.e. four characters) of base64
+ * data and writes up to three bytes to |out|. It sets |*out_num_bytes| to the
+ * number of bytes written, which will be less than three if the quad ended
+ * with padding.  It returns one on success or zero on error. */
+static int base64_decode_quad(uint8_t *out, size_t *out_num_bytes,
+                              const uint8_t *in) {
+  const uint8_t a = base64_ascii_to_bin(in[0]);
+  const uint8_t b = base64_ascii_to_bin(in[1]);
+  const uint8_t c = base64_ascii_to_bin(in[2]);
+  const uint8_t d = base64_ascii_to_bin(in[3]);
+  if (a == 0xff || b == 0xff || c == 0xff || d == 0xff) {
+    return 0;
+  }
+
+  const uint32_t v = ((uint32_t)a) << 18 | ((uint32_t)b) << 12 |
+                     ((uint32_t)c) << 6 | (uint32_t)d;
+
+  const unsigned padding_pattern = (in[0] == '=') << 3 |
+                                   (in[1] == '=') << 2 |
+                                   (in[2] == '=') << 1 |
+                                   (in[3] == '=');
+
+  switch (padding_pattern) {
+    case 0:
+      /* The common case of no padding. */
+      *out_num_bytes = 3;
+      out[0] = v >> 16;
+      out[1] = v >> 8;
+      out[2] = v;
+      break;
+
+    case 1: /* xxx= */
+      *out_num_bytes = 2;
+      out[0] = v >> 16;
+      out[1] = v >> 8;
+      break;
+
+    case 3: /* xx== */
+      *out_num_bytes = 1;
+      out[0] = v >> 16;
+      break;
+
+    default:
+      return 0;
+  }
+
+  return 1;
+}
+
+int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len,
+                     const uint8_t *in, size_t in_len) {
+  *out_len = 0;
+
+  if (ctx->error_encountered) {
+    return -1;
+  }
+
+  size_t bytes_out = 0, i;
+  for (i = 0; i < in_len; i++) {
+    const char c = in[i];
+    switch (c) {
+      case ' ':
+      case '\t':
+      case '\r':
+      case '\n':
+        continue;
+    }
+
+    if (base64_ascii_to_bin(c) == 0xff || ctx->eof_seen) {
+      ctx->error_encountered = 1;
+      return -1;
+    }
+
+    ctx->data[ctx->data_used++] = c;
+    if (ctx->data_used == 4) {
+      size_t num_bytes_resulting;
+      if (!base64_decode_quad(out, &num_bytes_resulting, ctx->data)) {
+        ctx->error_encountered = 1;
+        return -1;
+      }
+
+      ctx->data_used = 0;
+      bytes_out += num_bytes_resulting;
+      out += num_bytes_resulting;
+
+      if (num_bytes_resulting < 3) {
+        ctx->eof_seen = 1;
+      }
+    }
+  }
+
+  if (bytes_out > INT_MAX) {
+    ctx->error_encountered = 1;
+    *out_len = 0;
+    return -1;
+  }
+  *out_len = (int)bytes_out;
+
+  if (ctx->eof_seen) {
+    return 0;
+  }
+
+  return 1;
+}
+
+int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len) {
+  *out_len = 0;
+  if (ctx->error_encountered || ctx->data_used != 0) {
+    return -1;
+  }
+
+  return 1;
+}
+
 int EVP_DecodeBase64(uint8_t *out, size_t *out_len, size_t max_out,
                      const uint8_t *in, size_t in_len) {
-  uint8_t a, b, c, d;
-  size_t pad_len = 0, len = 0, max_len, i;
-  uint32_t l;
+  *out_len = 0;
 
-  if (!EVP_DecodedLength(&max_len, in_len) || max_out < max_len) {
+  if (in_len % 4 != 0) {
     return 0;
   }
 
+  size_t max_len;
+  if (!EVP_DecodedLength(&max_len, in_len) ||
+      max_out < max_len) {
+    return 0;
+  }
+
+  size_t i, bytes_out = 0;
   for (i = 0; i < in_len; i += 4) {
-    a = conv_ascii2bin(*(in++));
-    b = conv_ascii2bin(*(in++));
-    if (i + 4 == in_len && in[1] == '=') {
-        if (in[0] == '=') {
-          pad_len = 2;
-        } else {
-          pad_len = 1;
-        }
-    }
-    if (pad_len < 2) {
-      c = conv_ascii2bin(*(in++));
-    } else {
-      c = 0;
-    }
-    if (pad_len < 1) {
-      d = conv_ascii2bin(*(in++));
-    } else {
-      d = 0;
-    }
-    if ((a & 0x80) || (b & 0x80) || (c & 0x80) || (d & 0x80)) {
+    size_t num_bytes_resulting;
+
+    if (!base64_decode_quad(out, &num_bytes_resulting, &in[i])) {
       return 0;
     }
-    l = ((((uint32_t)a) << 18L) | (((uint32_t)b) << 12L) |
-         (((uint32_t)c) << 6L) | (((uint32_t)d)));
-    *(out++) = (uint8_t)(l >> 16L) & 0xff;
-    if (pad_len < 2) {
-      *(out++) = (uint8_t)(l >> 8L) & 0xff;
+
+    bytes_out += num_bytes_resulting;
+    out += num_bytes_resulting;
+    if (num_bytes_resulting != 3 && i != in_len - 4) {
+      return 0;
     }
-    if (pad_len < 1) {
-      *(out++) = (uint8_t)(l) & 0xff;
-    }
-    len += 3 - pad_len;
   }
-  *out_len = len;
+
+  *out_len = bytes_out;
   return 1;
 }
 
-void EVP_DecodeInit(EVP_ENCODE_CTX *ctx) {
-  ctx->length = 30;
-  ctx->num = 0;
-  ctx->line_num = 0;
-  ctx->expect_nl = 0;
-}
-
-int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len,
-                     const uint8_t *in, size_t in_len) {
-  int seof = -1, eof = 0, rv = -1, v, tmp, exp_nl;
-  uint8_t *d;
-  unsigned i, n, ln, ret = 0;
-
-  n = ctx->num;
-  d = ctx->enc_data;
-  ln = ctx->line_num;
-  exp_nl = ctx->expect_nl;
-
-  /* last line of input. */
-  if (in_len == 0 || (n == 0 && conv_ascii2bin(in[0]) == B64_EOF)) {
-    rv = 0;
-    goto end;
-  }
-
-  /* We parse the input data */
-  for (i = 0; i < in_len; i++) {
-    /* If the current line is > 80 characters, scream alot */
-    if (ln >= 80) {
-      rv = -1;
-      goto end;
-    }
-
-    /* Get char and put it into the buffer */
-    tmp = *(in++);
-    v = conv_ascii2bin(tmp);
-    /* only save the good data :-) */
-    if (!B64_NOT_BASE64(v)) {
-      assert(n < sizeof(ctx->enc_data));
-      d[n++] = tmp;
-      ln++;
-    } else if (v == B64_ERROR) {
-      rv = -1;
-      goto end;
-    }
-
-    /* have we seen a '=' which is 'definitly' the last
-     * input line.  seof will point to the character that
-     * holds it. and eof will hold how many characters to
-     * chop off. */
-    if (tmp == '=') {
-      if (seof == -1) {
-        seof = n;
-      }
-      eof++;
-      if (eof > 2) {
-        /* There are, at most, two equals signs at the end of base64 data. */
-        rv = -1;
-        goto end;
-      }
-    }
-
-    if (v == B64_CR) {
-      ln = 0;
-      if (exp_nl) {
-        continue;
-      }
-    }
-
-    /* eoln */
-    if (v == B64_EOLN) {
-      ln = 0;
-      if (exp_nl) {
-        exp_nl = 0;
-        continue;
-      }
-    }
-    exp_nl = 0;
-
-    /* If we are at the end of input and it looks like a
-     * line, process it. */
-    if ((i + 1) == in_len && (((n & 3) == 0) || eof)) {
-      v = B64_EOF;
-      /* In case things were given us in really small
-         records (so two '=' were given in separate
-         updates), eof may contain the incorrect number
-         of ending bytes to skip, so let's redo the count */
-      eof = 0;
-      if (d[n - 1] == '=') {
-        eof++;
-      }
-      if (d[n - 2] == '=') {
-        eof++;
-      }
-      /* There will never be more than two '=' */
-    }
-
-    if ((v == B64_EOF && (n & 3) == 0) || n >= 64) {
-      /* This is needed to work correctly on 64 byte input
-       * lines.  We process the line and then need to
-       * accept the '\n' */
-      if (v != B64_EOF && n >= 64) {
-        exp_nl = 1;
-      }
-      if (n > 0) {
-        /* TODO(davidben): Switch this to EVP_DecodeBase64. */
-        v = EVP_DecodeBlock(out, d, n);
-        n = 0;
-        if (v < 0) {
-          rv = 0;
-          goto end;
-        }
-        if (eof > v) {
-          rv = -1;
-          goto end;
-        }
-        ret += (v - eof);
-      } else {
-        eof = 1;
-        v = 0;
-      }
-
-      /* This is the case where we have had a short
-       * but valid input line */
-      if (v < (int)ctx->length && eof) {
-        rv = 0;
-        goto end;
-      } else {
-        ctx->length = v;
-      }
-
-      if (seof >= 0) {
-        rv = 0;
-        goto end;
-      }
-      out += v;
-    }
-  }
-  rv = 1;
-
-end:
-  *out_len = ret;
-  ctx->num = n;
-  ctx->line_num = ln;
-  ctx->expect_nl = exp_nl;
-  return rv;
-}
-
-int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *outl) {
-  int i;
-
-  *outl = 0;
-  if (ctx->num != 0) {
-    /* TODO(davidben): Switch this to EVP_DecodeBase64. */
-    i = EVP_DecodeBlock(out, ctx->enc_data, ctx->num);
-    if (i < 0) {
-      return -1;
-    }
-    ctx->num = 0;
-    *outl = i;
-    return 1;
-  } else {
-    return 1;
-  }
-}
-
 int EVP_DecodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) {
-  size_t dst_len;
+  /* Trim spaces and tabs from the beginning of the input. */
+  while (src_len > 0) {
+    if (src[0] != ' ' && src[0] != '\t') {
+      break;
+    }
 
-  /* trim white space from the start of the line. */
-  while (conv_ascii2bin(*src) == B64_WS && src_len > 0) {
     src++;
     src_len--;
   }
 
-  /* strip off stuff at the end of the line
-   * ascii2bin values B64_WS, B64_EOLN, B64_EOLN and B64_EOF */
-  while (src_len > 3 && B64_NOT_BASE64(conv_ascii2bin(src[src_len - 1]))) {
-    src_len--;
+  /* Trim newlines, spaces and tabs from the end of the line. */
+  while (src_len > 0) {
+    switch (src[src_len-1]) {
+      case ' ':
+      case '\t':
+      case '\r':
+      case '\n':
+        src_len--;
+        continue;
+    }
+
+    break;
   }
 
-  if (!EVP_DecodedLength(&dst_len, src_len) || dst_len > INT_MAX) {
-    return -1;
-  }
-  if (!EVP_DecodeBase64(dst, &dst_len, dst_len, src, src_len)) {
+  size_t dst_len;
+  if (!EVP_DecodedLength(&dst_len, src_len) ||
+      dst_len > INT_MAX ||
+      !EVP_DecodeBase64(dst, &dst_len, dst_len, src, src_len)) {
     return -1;
   }
 
@@ -456,23 +440,5 @@
   }
   assert(dst_len <= INT_MAX);
 
-  return dst_len;
-}
-
-int EVP_EncodedLength(size_t *out_len, size_t len) {
-  if (len + 2 < len) {
-    return 0;
-  }
-  len += 2;
-  len /= 3;
-  if (((len << 2) >> 2) != len) {
-    return 0;
-  }
-  len <<= 2;
-  if (len + 1 < len) {
-    return 0;
-  }
-  len++;
-  *out_len = len;
-  return 1;
+  return (int)dst_len;
 }
diff --git a/src/crypto/base64/base64_test.cc b/src/crypto/base64/base64_test.cc
index fde0b46..bdf3d9a 100644
--- a/src/crypto/base64/base64_test.cc
+++ b/src/crypto/base64/base64_test.cc
@@ -15,100 +15,366 @@
 #include <stdio.h>
 #include <string.h>
 
+#include <string>
+#include <vector>
+
 #include <openssl/base64.h>
 #include <openssl/crypto.h>
 #include <openssl/err.h>
 
+#include "../internal.h"
+
+
+enum encoding_relation {
+  // canonical indicates that the encoding is the expected encoding of the
+  // input.
+  canonical,
+  // valid indicates that the encoding is /a/ valid encoding of the input, but
+  // need not be the canonical one.
+  valid,
+  // invalid indicates that the encoded data is valid.
+  invalid,
+};
 
 struct TestVector {
+  enum encoding_relation relation;
   const char *decoded;
   const char *encoded;
 };
 
 // Test vectors from RFC 4648.
 static const TestVector kTestVectors[] = {
-  { "", "" },
-  { "f" , "Zg==" },
-  { "fo", "Zm8=" },
-  { "foo", "Zm9v" },
-  { "foob", "Zm9vYg==" },
-  { "fooba", "Zm9vYmE=" },
-  { "foobar", "Zm9vYmFy" },
+    {canonical, "", ""},
+    {canonical, "f", "Zg==\n"},
+    {canonical, "fo", "Zm8=\n"},
+    {canonical, "foo", "Zm9v\n"},
+    {canonical, "foob", "Zm9vYg==\n"},
+    {canonical, "fooba", "Zm9vYmE=\n"},
+    {canonical, "foobar", "Zm9vYmFy\n"},
+    {valid, "foobar", "Zm9vYmFy\n\n"},
+    {valid, "foobar", " Zm9vYmFy\n\n"},
+    {valid, "foobar", " Z m 9 v Y m F y\n\n"},
+    {invalid, "", "Zm9vYmFy=\n"},
+    {invalid, "", "Zm9vYmFy==\n"},
+    {invalid, "", "Zm9vYmFy===\n"},
+    {invalid, "", "Z"},
+    {invalid, "", "Z\n"},
+    {invalid, "", "ab!c"},
+    {invalid, "", "ab=c"},
+    {invalid, "", "abc"},
+
+    {canonical, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+     "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA==\n"},
+    {valid, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+     "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA\n==\n"},
+    {valid, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+     "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA=\n=\n"},
+    {invalid, "",
+     "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA=\n==\n"},
+    {canonical, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+     "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4\neHh4eHh"
+     "4eHh4eHh4\n"},
+    {canonical,
+     "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+     "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4\neHh4eHh"
+     "4eHh4eHh4eHh4eA==\n"},
+    {valid, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+     "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh\n4eHh4eHh"
+     "4eHh4eHh4eHh4eA==\n"},
+    {valid, "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
+     "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4e"
+     "Hh4eHh4eHh4eA==\n"},
+    {invalid, "",
+     "eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eA=="
+     "\neHh4eHh4eHh4eHh4eHh4eHh4\n"},
+
+    // A '-' has traditionally been treated as the end of the data by OpenSSL
+    // and anything following would be ignored. BoringSSL does not accept this
+    // non-standard extension.
+    {invalid, "", "Zm9vYmFy-anythinggoes"},
+    {invalid, "", "Zm9vYmFy\n-anythinggoes"},
+
+    // CVE-2015-0292
+    {invalid, "",
+     "ZW5jb2RlIG1lCg==========================================================="
+     "=======\n"},
 };
 
-static const size_t kNumTests = sizeof(kTestVectors) / sizeof(kTestVectors[0]);
+static const size_t kNumTests = OPENSSL_ARRAY_SIZE(kTestVectors);
 
-static bool TestEncode() {
-  for (size_t i = 0; i < kNumTests; i++) {
+// RemoveNewlines returns a copy of |in| with all '\n' characters removed.
+static std::string RemoveNewlines(const char *in) {
+  std::string ret;
+  const size_t in_len = strlen(in);
+
+  for (size_t i = 0; i < in_len; i++) {
+    if (in[i] != '\n') {
+      ret.push_back(in[i]);
+    }
+  }
+
+  return ret;
+}
+
+static bool TestEncodeBlock() {
+  for (unsigned i = 0; i < kNumTests; i++) {
     const TestVector *t = &kTestVectors[i];
-    uint8_t out[9];
-    size_t len = EVP_EncodeBlock(out, (const uint8_t*)t->decoded,
-                                 strlen(t->decoded));
-    if (len != strlen(t->encoded) ||
-        memcmp(out, t->encoded, len) != 0) {
+    if (t->relation != canonical) {
+      continue;
+    }
+
+    const size_t decoded_len = strlen(t->decoded);
+    size_t max_encoded_len;
+    if (!EVP_EncodedLength(&max_encoded_len, decoded_len)) {
+      fprintf(stderr, "#%u: EVP_EncodedLength failed\n", i);
+      return false;
+    }
+
+    std::vector<uint8_t> out_vec(max_encoded_len);
+    uint8_t *out = out_vec.data();
+    size_t len = EVP_EncodeBlock(out, (const uint8_t *)t->decoded, decoded_len);
+
+    std::string encoded(RemoveNewlines(t->encoded));
+    if (len != encoded.size() ||
+        OPENSSL_memcmp(out, encoded.data(), len) != 0) {
       fprintf(stderr, "encode(\"%s\") = \"%.*s\", want \"%s\"\n",
-              t->decoded, (int)len, (const char*)out, t->encoded);
+              t->decoded, (int)len, (const char*)out, encoded.c_str());
       return false;
     }
   }
+
   return true;
 }
 
-static bool TestDecode() {
-  uint8_t out[6];
+static bool TestDecodeBase64() {
   size_t len;
 
-  for (size_t i = 0; i < kNumTests; i++) {
-    // Test the normal API.
+  for (unsigned i = 0; i < kNumTests; i++) {
     const TestVector *t = &kTestVectors[i];
-    size_t expected_len = strlen(t->decoded);
-    if (!EVP_DecodeBase64(out, &len, sizeof(out),
-                          (const uint8_t*)t->encoded, strlen(t->encoded))) {
-      fprintf(stderr, "decode(\"%s\") failed\n", t->encoded);
-      return false;
-    }
-    if (len != strlen(t->decoded) ||
-        memcmp(out, t->decoded, len) != 0) {
-      fprintf(stderr, "decode(\"%s\") = \"%.*s\", want \"%s\"\n",
-              t->encoded, (int)len, (const char*)out, t->decoded);
-      return false;
+
+    if (t->relation == valid) {
+      // The non-canonical encodings will generally have odd whitespace etc
+      // that |EVP_DecodeBase64| will reject.
+      continue;
     }
 
+    const std::string encoded(RemoveNewlines(t->encoded));
+    std::vector<uint8_t> out_vec(encoded.size());
+    uint8_t *out = out_vec.data();
+
+    int ok = EVP_DecodeBase64(out, &len, out_vec.size(),
+                              (const uint8_t *)encoded.data(), encoded.size());
+
+    if (t->relation == invalid) {
+      if (ok) {
+        fprintf(stderr, "decode(\"%s\") didn't fail but should have\n",
+                encoded.c_str());
+        return false;
+      }
+    } else if (t->relation == canonical) {
+      if (!ok) {
+        fprintf(stderr, "decode(\"%s\") failed\n", encoded.c_str());
+        return false;
+      }
+
+      if (len != strlen(t->decoded) ||
+          OPENSSL_memcmp(out, t->decoded, len) != 0) {
+        fprintf(stderr, "decode(\"%s\") = \"%.*s\", want \"%s\"\n",
+                encoded.c_str(), (int)len, (const char*)out, t->decoded);
+        return false;
+      }
+    }
+  }
+
+  return true;
+}
+
+static bool TestDecodeBlock() {
+  for (unsigned i = 0; i < kNumTests; i++) {
+    const TestVector *t = &kTestVectors[i];
+    if (t->relation != canonical) {
+      continue;
+    }
+
+    std::string encoded(RemoveNewlines(t->encoded));
+
+    std::vector<uint8_t> out_vec(encoded.size());
+    uint8_t *out = out_vec.data();
+
     // Test that the padding behavior of the deprecated API is preserved.
-    int ret = EVP_DecodeBlock(out, (const uint8_t*)t->encoded,
-                              strlen(t->encoded));
+    int ret =
+        EVP_DecodeBlock(out, (const uint8_t *)encoded.data(), encoded.size());
     if (ret < 0) {
-      fprintf(stderr, "decode(\"%s\") failed\n", t->encoded);
+      fprintf(stderr, "EVP_DecodeBlock(\"%s\") failed\n", t->encoded);
       return false;
     }
     if (ret % 3 != 0) {
       fprintf(stderr, "EVP_DecodeBlock did not ignore padding\n");
       return false;
     }
+    size_t expected_len = strlen(t->decoded);
     if (expected_len % 3 != 0) {
       ret -= 3 - (expected_len % 3);
     }
     if (static_cast<size_t>(ret) != strlen(t->decoded) ||
-        memcmp(out, t->decoded, ret) != 0) {
+        OPENSSL_memcmp(out, t->decoded, ret) != 0) {
       fprintf(stderr, "decode(\"%s\") = \"%.*s\", want \"%s\"\n",
               t->encoded, ret, (const char*)out, t->decoded);
       return false;
     }
   }
 
-  if (EVP_DecodeBase64(out, &len, sizeof(out), (const uint8_t*)"a!bc", 4)) {
-    fprintf(stderr, "Failed to reject invalid characters in the middle.\n");
-    return false;
+  return true;
+}
+
+static bool TestEncodeDecode() {
+  for (unsigned test_num = 0; test_num < kNumTests; test_num++) {
+    const TestVector *t = &kTestVectors[test_num];
+
+    EVP_ENCODE_CTX ctx;
+    const size_t decoded_len = strlen(t->decoded);
+
+    if (t->relation == canonical) {
+      size_t max_encoded_len;
+      if (!EVP_EncodedLength(&max_encoded_len, decoded_len)) {
+        fprintf(stderr, "#%u: EVP_EncodedLength failed\n", test_num);
+        return false;
+      }
+
+      // EVP_EncodeUpdate will output new lines every 64 bytes of output so we
+      // need slightly more than |EVP_EncodedLength| returns. */
+      max_encoded_len += (max_encoded_len + 63) >> 6;
+      std::vector<uint8_t> out_vec(max_encoded_len);
+      uint8_t *out = out_vec.data();
+
+      EVP_EncodeInit(&ctx);
+
+      int out_len;
+      EVP_EncodeUpdate(&ctx, out, &out_len,
+                       reinterpret_cast<const uint8_t *>(t->decoded),
+                       decoded_len);
+      size_t total = out_len;
+
+      EVP_EncodeFinal(&ctx, out + total, &out_len);
+      total += out_len;
+
+      if (total != strlen(t->encoded) ||
+          OPENSSL_memcmp(out, t->encoded, total) != 0) {
+        fprintf(stderr, "#%u: EVP_EncodeUpdate produced different output: '%s' (%u)\n",
+                test_num, out, static_cast<unsigned>(total));
+        return false;
+      }
+    }
+
+    std::vector<uint8_t> out_vec(strlen(t->encoded));
+    uint8_t *out = out_vec.data();
+
+    EVP_DecodeInit(&ctx);
+    int out_len;
+    size_t total = 0;
+    int ret = EVP_DecodeUpdate(&ctx, out, &out_len,
+                               reinterpret_cast<const uint8_t *>(t->encoded),
+                               strlen(t->encoded));
+    if (ret != -1) {
+      total = out_len;
+      ret = EVP_DecodeFinal(&ctx, out + total, &out_len);
+      total += out_len;
+    }
+
+    switch (t->relation) {
+      case canonical:
+      case valid:
+        if (ret == -1) {
+          fprintf(stderr, "#%u: EVP_DecodeUpdate failed\n", test_num);
+          return false;
+        }
+        if (total != decoded_len ||
+            OPENSSL_memcmp(out, t->decoded, decoded_len)) {
+          fprintf(stderr, "#%u: EVP_DecodeUpdate produced incorrect output\n",
+                  test_num);
+          return false;
+        }
+        break;
+
+      case invalid:
+        if (ret != -1) {
+          fprintf(stderr, "#%u: EVP_DecodeUpdate was successful but shouldn't have been\n", test_num);
+          return false;
+        }
+        break;
+    }
   }
 
-  if (EVP_DecodeBase64(out, &len, sizeof(out), (const uint8_t*)"a=bc", 4)) {
-    fprintf(stderr, "Failed to reject invalid characters in the middle.\n");
-    return false;
-  }
+  return true;
+}
 
-  if (EVP_DecodeBase64(out, &len, sizeof(out), (const uint8_t*)"abc", 4)) {
-    fprintf(stderr, "Failed to reject invalid input length.\n");
-    return false;
+static bool TestDecodeUpdateStreaming() {
+  for (unsigned test_num = 0; test_num < kNumTests; test_num++) {
+    const TestVector *t = &kTestVectors[test_num];
+    if (t->relation == invalid) {
+      continue;
+    }
+
+    const size_t encoded_len = strlen(t->encoded);
+
+    std::vector<uint8_t> out(encoded_len);
+
+    for (size_t chunk_size = 1; chunk_size <= encoded_len; chunk_size++) {
+      size_t out_len = 0;
+      EVP_ENCODE_CTX ctx;
+      EVP_DecodeInit(&ctx);
+
+      for (size_t i = 0; i < encoded_len;) {
+        size_t todo = encoded_len - i;
+        if (todo > chunk_size) {
+          todo = chunk_size;
+        }
+
+        int bytes_written;
+        int ret = EVP_DecodeUpdate(
+            &ctx, out.data() + out_len, &bytes_written,
+            reinterpret_cast<const uint8_t *>(t->encoded + i), todo);
+        i += todo;
+
+        switch (ret) {
+          case -1:
+            fprintf(stderr, "#%u: EVP_DecodeUpdate returned error\n", test_num);
+            return 0;
+          case 0:
+            out_len += bytes_written;
+            if (i == encoded_len ||
+                (i + 1 == encoded_len && t->encoded[i] == '\n') ||
+                /* If there was an '-' in the input (which means “EOF”) then
+                 * this loop will continue to test that |EVP_DecodeUpdate| will
+                 * ignore the remainder of the input. */
+                strchr(t->encoded, '-') != nullptr) {
+              break;
+            }
+
+            fprintf(stderr,
+                    "#%u: EVP_DecodeUpdate returned zero before end of "
+                    "encoded data\n",
+                    test_num);
+            return 0;
+          default:
+            out_len += bytes_written;
+        }
+      }
+
+      int bytes_written;
+      int ret = EVP_DecodeFinal(&ctx, out.data() + out_len, &bytes_written);
+      if (ret == -1) {
+        fprintf(stderr, "#%u: EVP_DecodeFinal returned error\n", test_num);
+        return 0;
+      }
+      out_len += bytes_written;
+
+      if (out_len != strlen(t->decoded) ||
+          OPENSSL_memcmp(out.data(), t->decoded, out_len) != 0) {
+        fprintf(stderr, "#%u: incorrect output\n", test_num);
+        return 0;
+      }
+    }
   }
 
   return true;
@@ -116,10 +382,12 @@
 
 int main(void) {
   CRYPTO_library_init();
-  ERR_load_crypto_strings();
 
-  if (!TestEncode() ||
-      !TestDecode()) {
+  if (!TestEncodeBlock() ||
+      !TestDecodeBase64() ||
+      !TestDecodeBlock() ||
+      !TestDecodeUpdateStreaming() ||
+      !TestEncodeDecode()) {
     return 1;
   }
 
diff --git a/src/crypto/bio/CMakeLists.txt b/src/crypto/bio/CMakeLists.txt
index 7859b58..fccb152 100644
--- a/src/crypto/bio/CMakeLists.txt
+++ b/src/crypto/bio/CMakeLists.txt
@@ -7,7 +7,6 @@
 
   bio.c
   bio_mem.c
-  buffer.c
   connect.c
   fd.c
   file.c
@@ -17,17 +16,3 @@
   socket.c
   socket_helper.c
 )
-
-add_executable(
-  bio_test
-
-  bio_test.cc
-
-  $<TARGET_OBJECTS:test_support>
-)
-
-target_link_libraries(bio_test crypto)
-if (WIN32)
-  target_link_libraries(bio_test ws2_32)
-endif()
-add_dependencies(all_tests bio_test)
diff --git a/src/crypto/bio/bio.c b/src/crypto/bio/bio.c
index 7a1a9e3..5cab843 100644
--- a/src/crypto/bio/bio.c
+++ b/src/crypto/bio/bio.c
@@ -68,25 +68,6 @@
 #include "../internal.h"
 
 
-/* BIO_set initialises a BIO structure to have the given type and sets the
- * reference count to one. It returns one on success or zero on error. */
-static int bio_set(BIO *bio, const BIO_METHOD *method) {
-  /* This function can be called with a stack allocated |BIO| so we have to
-   * assume that the contents of |BIO| are arbitary. This also means that it'll
-   * leak memory if you call |BIO_set| twice on the same BIO. */
-  memset(bio, 0, sizeof(BIO));
-
-  bio->method = method;
-  bio->shutdown = 1;
-  bio->references = 1;
-
-  if (method->create != NULL && !method->create(bio)) {
-    return 0;
-  }
-
-  return 1;
-}
-
 BIO *BIO_new(const BIO_METHOD *method) {
   BIO *ret = OPENSSL_malloc(sizeof(BIO));
   if (ret == NULL) {
@@ -94,9 +75,14 @@
     return NULL;
   }
 
-  if (!bio_set(ret, method)) {
+  OPENSSL_memset(ret, 0, sizeof(BIO));
+  ret->method = method;
+  ret->shutdown = 1;
+  ret->references = 1;
+
+  if (method->create != NULL && !method->create(ret)) {
     OPENSSL_free(ret);
-    ret = NULL;
+    return NULL;
   }
 
   return ret;
@@ -128,9 +114,9 @@
   return 1;
 }
 
-BIO *BIO_up_ref(BIO *bio) {
+int BIO_up_ref(BIO *bio) {
   CRYPTO_refcount_inc(&bio->references);
-  return bio;
+  return 1;
 }
 
 void BIO_vfree(BIO *bio) {
@@ -257,6 +243,10 @@
   return BIO_ctrl(bio, BIO_CTRL_RESET, 0, NULL);
 }
 
+int BIO_eof(BIO *bio) {
+  return BIO_ctrl(bio, BIO_CTRL_EOF, 0, NULL);
+}
+
 void BIO_set_flags(BIO *bio, int flags) {
   bio->flags |= flags;
 }
@@ -346,7 +336,13 @@
 }
 
 size_t BIO_pending(const BIO *bio) {
-  return BIO_ctrl((BIO *) bio, BIO_CTRL_PENDING, 0, NULL);
+  const long r = BIO_ctrl((BIO *) bio, BIO_CTRL_PENDING, 0, NULL);
+  assert(r >= 0);
+
+  if (r < 0) {
+    return 0;
+  }
+  return r;
 }
 
 size_t BIO_ctrl_pending(const BIO *bio) {
@@ -354,7 +350,13 @@
 }
 
 size_t BIO_wpending(const BIO *bio) {
-  return BIO_ctrl((BIO *) bio, BIO_CTRL_WPENDING, 0, NULL);
+  const long r = BIO_ctrl((BIO *) bio, BIO_CTRL_WPENDING, 0, NULL);
+  assert(r >= 0);
+
+  if (r < 0) {
+    return 0;
+  }
+  return r;
 }
 
 int BIO_set_close(BIO *bio, int close_flag) {
@@ -458,12 +460,8 @@
   return BIO_write((BIO *)bio, str, len);
 }
 
-void BIO_print_errors(BIO *bio) {
-  ERR_print_errors_cb(print_bio, bio);
-}
-
 void ERR_print_errors(BIO *bio) {
-  BIO_print_errors(bio);
+  ERR_print_errors_cb(print_bio, bio);
 }
 
 /* bio_read_all reads everything from |bio| and prepends |prefix| to it. On
@@ -490,7 +488,7 @@
   if (*out == NULL) {
     return 0;
   }
-  memcpy(*out, prefix, prefix_len);
+  OPENSSL_memcpy(*out, prefix, prefix_len);
   size_t done = prefix_len;
 
   for (;;) {
@@ -597,7 +595,7 @@
   if (*out == NULL) {
     return 0;
   }
-  memcpy(*out, header, header_len);
+  OPENSSL_memcpy(*out, header, header_len);
   if (BIO_read(bio, (*out) + header_len, len - header_len) !=
       (int) (len - header_len)) {
     OPENSSL_free(*out);
@@ -606,3 +604,9 @@
 
   return 1;
 }
+
+void BIO_set_retry_special(BIO *bio) {
+  bio->flags |= BIO_FLAGS_READ | BIO_FLAGS_IO_SPECIAL;
+}
+
+int BIO_set_write_buffer_size(BIO *bio, int buffer_size) { return 0; }
diff --git a/src/crypto/bio/bio_mem.c b/src/crypto/bio/bio_mem.c
index 6864f6f..1cba8a8 100644
--- a/src/crypto/bio/bio_mem.c
+++ b/src/crypto/bio/bio_mem.c
@@ -63,8 +63,10 @@
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
+#include "../internal.h"
 
-BIO *BIO_new_mem_buf(void *buf, int len) {
+
+BIO *BIO_new_mem_buf(const void *buf, int len) {
   BIO *ret;
   BUF_MEM *b;
   const size_t size = len < 0 ? strlen((char *)buf) : (size_t)len;
@@ -80,7 +82,8 @@
   }
 
   b = (BUF_MEM *)ret->ptr;
-  b->data = buf;
+  /* BIO_FLAGS_MEM_RDONLY ensures |b->data| is not written to. */
+  b->data = (void *)buf;
   b->length = size;
   b->max = size;
 
@@ -143,12 +146,12 @@
   }
 
   if (ret > 0) {
-    memcpy(out, b->data, ret);
+    OPENSSL_memcpy(out, b->data, ret);
     b->length -= ret;
     if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
       b->data += ret;
     } else {
-      memmove(b->data, &b->data[ret], b->length);
+      OPENSSL_memmove(b->data, &b->data[ret], b->length);
     }
   } else if (b->length == 0) {
     ret = bio->num;
@@ -179,17 +182,13 @@
   if (BUF_MEM_grow_clean(b, blen + inl) != ((size_t) blen) + inl) {
     goto err;
   }
-  memcpy(&b->data[blen], in, inl);
+  OPENSSL_memcpy(&b->data[blen], in, inl);
   ret = inl;
 
 err:
   return ret;
 }
 
-static int mem_puts(BIO *bp, const char *str) {
-  return mem_write(bp, str, strlen(str));
-}
-
 static int mem_gets(BIO *bio, char *buf, int size) {
   int i, j;
   char *p;
@@ -239,7 +238,7 @@
           b->data -= b->max - b->length;
           b->length = b->max;
         } else {
-          memset(b->data, 0, b->max);
+          OPENSSL_memset(b->data, 0, b->max);
           b->length = 0;
         }
       }
@@ -292,8 +291,12 @@
 }
 
 static const BIO_METHOD mem_method = {
-    BIO_TYPE_MEM, "memory buffer", mem_write, mem_read, mem_puts,
-    mem_gets,     mem_ctrl,        mem_new,   mem_free, NULL, };
+    BIO_TYPE_MEM,    "memory buffer",
+    mem_write,       mem_read,
+    NULL /* puts */, mem_gets,
+    mem_ctrl,        mem_new,
+    mem_free,        NULL /* callback_ctrl */,
+};
 
 const BIO_METHOD *BIO_s_mem(void) { return &mem_method; }
 
diff --git a/src/crypto/bio/bio_test.cc b/src/crypto/bio/bio_test.cc
index 4d7dfe2..beb182b 100644
--- a/src/crypto/bio/bio_test.cc
+++ b/src/crypto/bio/bio_test.cc
@@ -16,7 +16,18 @@
 #define _POSIX_C_SOURCE 201410L
 #endif
 
-#include <openssl/base.h>
+#include <algorithm>
+#include <string>
+
+#include <gtest/gtest.h>
+
+#include <openssl/bio.h>
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+#include "../internal.h"
+#include "../test/test_util.h"
 
 #if !defined(OPENSSL_WINDOWS)
 #include <arpa/inet.h>
@@ -27,39 +38,27 @@
 #include <unistd.h>
 #else
 #include <io.h>
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <winsock2.h>
 #include <ws2tcpip.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
 #endif
 
-#include <openssl/bio.h>
-#include <openssl/crypto.h>
-#include <openssl/err.h>
-#include <openssl/mem.h>
-
-#include <algorithm>
-
-#include "../test/scoped_types.h"
-
 
 #if !defined(OPENSSL_WINDOWS)
-static int closesocket(int sock) {
-  return close(sock);
-}
-
-static void PrintSocketError(const char *func) {
-  perror(func);
-}
+static int closesocket(int sock) { return close(sock); }
+static std::string LastSocketError() { return strerror(errno); }
 #else
-static void PrintSocketError(const char *func) {
-  fprintf(stderr, "%s: %d\n", func, WSAGetLastError());
+static std::string LastSocketError() {
+  char buf[DECIMAL_SIZE(int) + 1];
+  BIO_snprintf(buf, sizeof(buf), "%d", WSAGetLastError());
+  return buf;
 }
 #endif
 
 class ScopedSocket {
  public:
-  ScopedSocket(int sock) : sock_(sock) {}
+  explicit ScopedSocket(int sock) : sock_(sock) {}
   ~ScopedSocket() {
     closesocket(sock_);
   }
@@ -68,374 +67,246 @@
   const int sock_;
 };
 
-static bool TestSocketConnect() {
+TEST(BIOTest, SocketConnect) {
   static const char kTestMessage[] = "test";
 
+  // Set up a listening socket on localhost.
   int listening_sock = socket(AF_INET, SOCK_STREAM, 0);
-  if (listening_sock == -1) {
-    PrintSocketError("socket");
-    return false;
-  }
+  ASSERT_NE(-1, listening_sock) << LastSocketError();
   ScopedSocket listening_sock_closer(listening_sock);
 
   struct sockaddr_in sin;
-  memset(&sin, 0, sizeof(sin));
+  OPENSSL_memset(&sin, 0, sizeof(sin));
   sin.sin_family = AF_INET;
-  if (!inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr)) {
-    PrintSocketError("inet_pton");
-    return false;
-  }
-  if (bind(listening_sock, (struct sockaddr *)&sin, sizeof(sin)) != 0) {
-    PrintSocketError("bind");
-    return false;
-  }
-  if (listen(listening_sock, 1)) {
-    PrintSocketError("listen");
-    return false;
-  }
+  ASSERT_EQ(1, inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr))
+      << LastSocketError();
+  ASSERT_EQ(0, bind(listening_sock, (struct sockaddr *)&sin, sizeof(sin)))
+      << LastSocketError();
+  ASSERT_EQ(0, listen(listening_sock, 1)) << LastSocketError();
   socklen_t sockaddr_len = sizeof(sin);
-  if (getsockname(listening_sock, (struct sockaddr *)&sin, &sockaddr_len) ||
-      sockaddr_len != sizeof(sin)) {
-    PrintSocketError("getsockname");
-    return false;
-  }
+  ASSERT_EQ(0,
+            getsockname(listening_sock, (struct sockaddr *)&sin, &sockaddr_len))
+      << LastSocketError();
+  // The Android NDK, contrary to POSIX, makes |socklen_t| signed.
+  ASSERT_EQ(sizeof(sin), static_cast<size_t>(sockaddr_len));
 
+  // Connect to it with a connect BIO.
   char hostname[80];
   BIO_snprintf(hostname, sizeof(hostname), "%s:%d", "127.0.0.1",
                ntohs(sin.sin_port));
-  ScopedBIO bio(BIO_new_connect(hostname));
-  if (!bio) {
-    fprintf(stderr, "BIO_new_connect failed.\n");
-    return false;
-  }
+  bssl::UniquePtr<BIO> bio(BIO_new_connect(hostname));
+  ASSERT_TRUE(bio);
 
-  if (BIO_write(bio.get(), kTestMessage, sizeof(kTestMessage)) !=
-      sizeof(kTestMessage)) {
-    fprintf(stderr, "BIO_write failed.\n");
-    ERR_print_errors_fp(stderr);
-    return false;
-  }
+  // Write a test message to the BIO.
+  ASSERT_EQ(static_cast<int>(sizeof(kTestMessage)),
+            BIO_write(bio.get(), kTestMessage, sizeof(kTestMessage)));
 
+  // Accept the socket.
   int sock = accept(listening_sock, (struct sockaddr *) &sin, &sockaddr_len);
-  if (sock == -1) {
-    PrintSocketError("accept");
-    return false;
-  }
+  ASSERT_NE(-1, sock) << LastSocketError();
   ScopedSocket sock_closer(sock);
 
-  char buf[5];
-  if (recv(sock, buf, sizeof(buf), 0) != sizeof(kTestMessage)) {
-    PrintSocketError("read");
-    return false;
-  }
-  if (memcmp(buf, kTestMessage, sizeof(kTestMessage))) {
-    return false;
-  }
-
-  return true;
+  // Check the same message is read back out.
+  char buf[sizeof(kTestMessage)];
+  ASSERT_EQ(static_cast<int>(sizeof(kTestMessage)),
+            recv(sock, buf, sizeof(buf), 0))
+      << LastSocketError();
+  EXPECT_EQ(Bytes(kTestMessage, sizeof(kTestMessage)), Bytes(buf, sizeof(buf)));
 }
 
-
-// BioReadZeroCopyWrapper is a wrapper around the zero-copy APIs to make
-// testing easier.
-static size_t BioReadZeroCopyWrapper(BIO *bio, uint8_t *data, size_t len) {
-  uint8_t *read_buf;
-  size_t read_buf_offset;
-  size_t available_bytes;
-  size_t len_read = 0;
-
-  do {
-    if (!BIO_zero_copy_get_read_buf(bio, &read_buf, &read_buf_offset,
-                                    &available_bytes)) {
-      return 0;
-    }
-
-    available_bytes = std::min(available_bytes, len - len_read);
-    memmove(data + len_read, read_buf + read_buf_offset, available_bytes);
-
-    BIO_zero_copy_get_read_buf_done(bio, available_bytes);
-
-    len_read += available_bytes;
-  } while (len - len_read > 0 && available_bytes > 0);
-
-  return len_read;
-}
-
-// BioWriteZeroCopyWrapper is a wrapper around the zero-copy APIs to make
-// testing easier.
-static size_t BioWriteZeroCopyWrapper(BIO *bio, const uint8_t *data,
-                                      size_t len) {
-  uint8_t *write_buf;
-  size_t write_buf_offset;
-  size_t available_bytes;
-  size_t len_written = 0;
-
-  do {
-    if (!BIO_zero_copy_get_write_buf(bio, &write_buf, &write_buf_offset,
-                                     &available_bytes)) {
-      return 0;
-    }
-
-    available_bytes = std::min(available_bytes, len - len_written);
-    memmove(write_buf + write_buf_offset, data + len_written, available_bytes);
-
-    BIO_zero_copy_get_write_buf_done(bio, available_bytes);
-
-    len_written += available_bytes;
-  } while (len - len_written > 0 && available_bytes > 0);
-
-  return len_written;
-}
-
-static bool TestZeroCopyBioPairs() {
-  // Test read and write, especially triggering the ring buffer wrap-around.
-  uint8_t bio1_application_send_buffer[1024];
-  uint8_t bio2_application_recv_buffer[1024];
-
-  const size_t kLengths[] = {254, 255, 256, 257, 510, 511, 512, 513};
-
-  // These trigger ring buffer wrap around.
-  const size_t kPartialLengths[] = {0, 1, 2, 3, 128, 255, 256, 257, 511, 512};
-
-  static const size_t kBufferSize = 512;
-
-  srand(1);
-  for (size_t i = 0; i < sizeof(bio1_application_send_buffer); i++) {
-    bio1_application_send_buffer[i] = rand() & 255;
-  }
-
-  // Transfer bytes from bio1_application_send_buffer to
-  // bio2_application_recv_buffer in various ways.
-  for (size_t i = 0; i < sizeof(kLengths) / sizeof(kLengths[0]); i++) {
-    for (size_t j = 0; j < sizeof(kPartialLengths) / sizeof(kPartialLengths[0]);
-         j++) {
-      size_t total_write = 0;
-      size_t total_read = 0;
-
-      BIO *bio1, *bio2;
-      if (!BIO_new_bio_pair(&bio1, kBufferSize, &bio2, kBufferSize)) {
-        return false;
-      }
-      ScopedBIO bio1_scoper(bio1);
-      ScopedBIO bio2_scoper(bio2);
-
-      total_write += BioWriteZeroCopyWrapper(
-          bio1, bio1_application_send_buffer, kLengths[i]);
-
-      // This tests interleaved read/write calls. Do a read between zero copy
-      // write calls.
-      uint8_t *write_buf;
-      size_t write_buf_offset;
-      size_t available_bytes;
-      if (!BIO_zero_copy_get_write_buf(bio1, &write_buf, &write_buf_offset,
-                                       &available_bytes)) {
-        return false;
-      }
-
-      // Free kPartialLengths[j] bytes in the beginning of bio1 write buffer.
-      // This enables ring buffer wrap around for the next write.
-      total_read += BIO_read(bio2, bio2_application_recv_buffer + total_read,
-                             kPartialLengths[j]);
-
-      size_t interleaved_write_len = std::min(kPartialLengths[j],
-                                              available_bytes);
-
-      // Write the data for the interleaved write call. If the buffer becomes
-      // empty after a read, the write offset is normally set to 0. Check that
-      // this does not happen for interleaved read/write and that
-      // |write_buf_offset| is still valid.
-      memcpy(write_buf + write_buf_offset,
-             bio1_application_send_buffer + total_write, interleaved_write_len);
-      if (BIO_zero_copy_get_write_buf_done(bio1, interleaved_write_len)) {
-        total_write += interleaved_write_len;
-      }
-
-      // Do another write in case |write_buf_offset| was wrapped.
-      total_write += BioWriteZeroCopyWrapper(
-          bio1, bio1_application_send_buffer + total_write,
-          kPartialLengths[j] - interleaved_write_len);
-
-      // Drain the rest.
-      size_t bytes_left = BIO_pending(bio2);
-      total_read += BioReadZeroCopyWrapper(
-          bio2, bio2_application_recv_buffer + total_read, bytes_left);
-
-      if (total_read != total_write) {
-        fprintf(stderr, "Lengths not equal in round (%u, %u)\n", (unsigned)i,
-                (unsigned)j);
-        return false;
-      }
-      if (total_read > kLengths[i] + kPartialLengths[j]) {
-        fprintf(stderr, "Bad lengths in round (%u, %u)\n", (unsigned)i,
-                (unsigned)j);
-        return false;
-      }
-      if (memcmp(bio1_application_send_buffer, bio2_application_recv_buffer,
-                 total_read) != 0) {
-        fprintf(stderr, "Buffers not equal in round (%u, %u)\n", (unsigned)i,
-                (unsigned)j);
-        return false;
-      }
-    }
-  }
-
-  return true;
-}
-
-static bool TestPrintf() {
+TEST(BIOTest, Printf) {
   // Test a short output, a very long one, and various sizes around
   // 256 (the size of the buffer) to ensure edge cases are correct.
-  static const size_t kLengths[] = { 5, 250, 251, 252, 253, 254, 1023 };
+  static const size_t kLengths[] = {5, 250, 251, 252, 253, 254, 1023};
 
-  ScopedBIO bio(BIO_new(BIO_s_mem()));
-  if (!bio) {
-    fprintf(stderr, "BIO_new failed\n");
-    return false;
-  }
+  bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_mem()));
+  ASSERT_TRUE(bio);
 
-  for (size_t i = 0; i < sizeof(kLengths) / sizeof(kLengths[0]); i++) {
-    char string[1024];
-    if (kLengths[i] >= sizeof(string)) {
-      fprintf(stderr, "Bad test string length\n");
-      return false;
-    }
-    memset(string, 'a', sizeof(string));
-    string[kLengths[i]] = '\0';
+  for (size_t length : kLengths) {
+    SCOPED_TRACE(length);
 
-    int ret = BIO_printf(bio.get(), "test %s", string);
-    if (ret < 0 || static_cast<size_t>(ret) != 5 + kLengths[i]) {
-      fprintf(stderr, "BIO_printf failed: %d\n", ret);
-      return false;
-    }
+    std::string in(length, 'a');
+
+    int ret = BIO_printf(bio.get(), "test %s", in.c_str());
+    ASSERT_GE(ret, 0);
+    EXPECT_EQ(5 + length, static_cast<size_t>(ret));
+
     const uint8_t *contents;
     size_t len;
-    if (!BIO_mem_contents(bio.get(), &contents, &len)) {
-      fprintf(stderr, "BIO_mem_contents failed\n");
-      return false;
-    }
-    if (len != 5 + kLengths[i] ||
-        strncmp((const char *)contents, "test ", 5) != 0 ||
-        strncmp((const char *)contents + 5, string, kLengths[i]) != 0) {
-      fprintf(stderr, "Contents did not match: %.*s\n", (int)len, contents);
-      return false;
-    }
+    ASSERT_TRUE(BIO_mem_contents(bio.get(), &contents, &len));
+    EXPECT_EQ("test " + in,
+              std::string(reinterpret_cast<const char *>(contents), len));
 
-    if (!BIO_reset(bio.get())) {
-      fprintf(stderr, "BIO_reset failed\n");
-      return false;
-    }
+    ASSERT_TRUE(BIO_reset(bio.get()));
   }
-
-  return true;
 }
 
-static bool ReadASN1(bool should_succeed, const uint8_t *data, size_t data_len,
-                     size_t expected_len, size_t max_len) {
-  ScopedBIO bio(BIO_new_mem_buf(const_cast<uint8_t*>(data), data_len));
+static const size_t kLargeASN1PayloadLen = 8000;
+
+struct ASN1TestParam {
+  bool should_succeed;
+  std::vector<uint8_t> input;
+  // suffix_len is the number of zeros to append to |input|.
+  size_t suffix_len;
+  // expected_len, if |should_succeed| is true, is the expected length of the
+  // ASN.1 element.
+  size_t expected_len;
+  size_t max_len;
+} kASN1TestParams[] = {
+    {true, {0x30, 2, 1, 2, 0, 0}, 0, 4, 100},
+    {false /* truncated */, {0x30, 3, 1, 2}, 0, 0, 100},
+    {false /* should be short len */, {0x30, 0x81, 1, 1}, 0, 0, 100},
+    {false /* zero padded */, {0x30, 0x82, 0, 1, 1}, 0, 0, 100},
+
+    // Test a large payload.
+    {true,
+     {0x30, 0x82, kLargeASN1PayloadLen >> 8, kLargeASN1PayloadLen & 0xff},
+     kLargeASN1PayloadLen,
+     4 + kLargeASN1PayloadLen,
+     kLargeASN1PayloadLen * 2},
+    {false /* max_len too short */,
+     {0x30, 0x82, kLargeASN1PayloadLen >> 8, kLargeASN1PayloadLen & 0xff},
+     kLargeASN1PayloadLen,
+     4 + kLargeASN1PayloadLen,
+     3 + kLargeASN1PayloadLen},
+
+    // Test an indefinite-length input.
+    {true,
+     {0x30, 0x80},
+     kLargeASN1PayloadLen + 2,
+     2 + kLargeASN1PayloadLen + 2,
+     kLargeASN1PayloadLen * 2},
+    {false /* max_len too short */,
+     {0x30, 0x80},
+     kLargeASN1PayloadLen + 2,
+     2 + kLargeASN1PayloadLen + 2,
+     2 + kLargeASN1PayloadLen + 1},
+};
+
+class BIOASN1Test : public testing::TestWithParam<ASN1TestParam> {};
+
+TEST_P(BIOASN1Test, ReadASN1) {
+  const ASN1TestParam& param = GetParam();
+  std::vector<uint8_t> input = param.input;
+  input.resize(input.size() + param.suffix_len, 0);
+
+  bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(input.data(), input.size()));
+  ASSERT_TRUE(bio);
 
   uint8_t *out;
   size_t out_len;
-  int ok = BIO_read_asn1(bio.get(), &out, &out_len, max_len);
+  int ok = BIO_read_asn1(bio.get(), &out, &out_len, param.max_len);
   if (!ok) {
     out = nullptr;
   }
-  ScopedOpenSSLBytes out_storage(out);
+  bssl::UniquePtr<uint8_t> out_storage(out);
 
-  if (should_succeed != (ok == 1)) {
-    return false;
+  ASSERT_EQ(param.should_succeed, (ok == 1));
+  if (param.should_succeed) {
+    EXPECT_EQ(Bytes(input.data(), param.expected_len), Bytes(out, out_len));
   }
-
-  if (should_succeed &&
-      (out_len != expected_len || memcmp(data, out, expected_len) != 0)) {
-    return false;
-  }
-
-  return true;
 }
 
-static bool TestASN1() {
-  static const uint8_t kData1[] = {0x30, 2, 1, 2, 0, 0};
-  static const uint8_t kData2[] = {0x30, 3, 1, 2};  /* truncated */
-  static const uint8_t kData3[] = {0x30, 0x81, 1, 1};  /* should be short len */
-  static const uint8_t kData4[] = {0x30, 0x82, 0, 1, 1};  /* zero padded. */
+INSTANTIATE_TEST_CASE_P(, BIOASN1Test, testing::ValuesIn(kASN1TestParams));
 
-  if (!ReadASN1(true, kData1, sizeof(kData1), 4, 100) ||
-      !ReadASN1(false, kData2, sizeof(kData2), 0, 100) ||
-      !ReadASN1(false, kData3, sizeof(kData3), 0, 100) ||
-      !ReadASN1(false, kData4, sizeof(kData4), 0, 100)) {
-    return false;
+// Run through the tests twice, swapping |bio1| and |bio2|, for symmetry.
+class BIOPairTest : public testing::TestWithParam<bool> {};
+
+TEST_P(BIOPairTest, TestPair) {
+  BIO *bio1, *bio2;
+  ASSERT_TRUE(BIO_new_bio_pair(&bio1, 10, &bio2, 10));
+  bssl::UniquePtr<BIO> free_bio1(bio1), free_bio2(bio2);
+
+  if (GetParam()) {
+    std::swap(bio1, bio2);
   }
 
-  static const size_t kLargePayloadLen = 8000;
-  static const uint8_t kLargePrefix[] = {0x30, 0x82, kLargePayloadLen >> 8,
-                                         kLargePayloadLen & 0xff};
-  ScopedOpenSSLBytes large(reinterpret_cast<uint8_t *>(
-      OPENSSL_malloc(sizeof(kLargePrefix) + kLargePayloadLen)));
-  if (!large) {
-    return false;
-  }
-  memset(large.get() + sizeof(kLargePrefix), 0, kLargePayloadLen);
-  memcpy(large.get(), kLargePrefix, sizeof(kLargePrefix));
+  // Check initial states.
+  EXPECT_EQ(10u, BIO_ctrl_get_write_guarantee(bio1));
+  EXPECT_EQ(0u, BIO_ctrl_get_read_request(bio1));
 
-  if (!ReadASN1(true, large.get(), sizeof(kLargePrefix) + kLargePayloadLen,
-                sizeof(kLargePrefix) + kLargePayloadLen,
-                kLargePayloadLen * 2)) {
-    fprintf(stderr, "Large payload test failed.\n");
-    return false;
-  }
+  // Data written in one end may be read out the other.
+  uint8_t buf[20];
+  EXPECT_EQ(5, BIO_write(bio1, "12345", 5));
+  EXPECT_EQ(5u, BIO_ctrl_get_write_guarantee(bio1));
+  ASSERT_EQ(5, BIO_read(bio2, buf, sizeof(buf)));
+  EXPECT_EQ(Bytes("12345"), Bytes(buf, 5));
+  EXPECT_EQ(10u, BIO_ctrl_get_write_guarantee(bio1));
 
-  if (!ReadASN1(false, large.get(), sizeof(kLargePrefix) + kLargePayloadLen,
-                sizeof(kLargePrefix) + kLargePayloadLen,
-                kLargePayloadLen - 1)) {
-    fprintf(stderr, "max_len test failed.\n");
-    return false;
-  }
+  // Attempting to write more than 10 bytes will write partially.
+  EXPECT_EQ(10, BIO_write(bio1, "1234567890___", 13));
+  EXPECT_EQ(0u, BIO_ctrl_get_write_guarantee(bio1));
+  EXPECT_EQ(-1, BIO_write(bio1, "z", 1));
+  EXPECT_TRUE(BIO_should_write(bio1));
+  ASSERT_EQ(10, BIO_read(bio2, buf, sizeof(buf)));
+  EXPECT_EQ(Bytes("1234567890"), Bytes(buf, 10));
+  EXPECT_EQ(10u, BIO_ctrl_get_write_guarantee(bio1));
 
-  static const uint8_t kIndefPrefix[] = {0x30, 0x80};
-  memcpy(large.get(), kIndefPrefix, sizeof(kIndefPrefix));
-  if (!ReadASN1(true, large.get(), sizeof(kLargePrefix) + kLargePayloadLen,
-                sizeof(kLargePrefix) + kLargePayloadLen,
-                kLargePayloadLen*2)) {
-    fprintf(stderr, "indefinite length test failed.\n");
-    return false;
-  }
+  // Unsuccessful reads update the read request.
+  EXPECT_EQ(-1, BIO_read(bio2, buf, 5));
+  EXPECT_TRUE(BIO_should_read(bio2));
+  EXPECT_EQ(5u, BIO_ctrl_get_read_request(bio1));
 
-  if (!ReadASN1(false, large.get(), sizeof(kLargePrefix) + kLargePayloadLen,
-                sizeof(kLargePrefix) + kLargePayloadLen,
-                kLargePayloadLen-1)) {
-    fprintf(stderr, "indefinite length, max_len test failed.\n");
-    return false;
-  }
+  // The read request is clamped to the size of the buffer.
+  EXPECT_EQ(-1, BIO_read(bio2, buf, 20));
+  EXPECT_TRUE(BIO_should_read(bio2));
+  EXPECT_EQ(10u, BIO_ctrl_get_read_request(bio1));
 
-  return true;
+  // Data may be written and read in chunks.
+  EXPECT_EQ(5, BIO_write(bio1, "12345", 5));
+  EXPECT_EQ(5u, BIO_ctrl_get_write_guarantee(bio1));
+  EXPECT_EQ(5, BIO_write(bio1, "67890___", 8));
+  EXPECT_EQ(0u, BIO_ctrl_get_write_guarantee(bio1));
+  ASSERT_EQ(3, BIO_read(bio2, buf, 3));
+  EXPECT_EQ(Bytes("123"), Bytes(buf, 3));
+  EXPECT_EQ(3u, BIO_ctrl_get_write_guarantee(bio1));
+  ASSERT_EQ(7, BIO_read(bio2, buf, sizeof(buf)));
+  EXPECT_EQ(Bytes("4567890"), Bytes(buf, 7));
+  EXPECT_EQ(10u, BIO_ctrl_get_write_guarantee(bio1));
+
+  // Successful reads reset the read request.
+  EXPECT_EQ(0u, BIO_ctrl_get_read_request(bio1));
+
+  // Test writes and reads starting in the middle of the ring buffer and
+  // wrapping to front.
+  EXPECT_EQ(8, BIO_write(bio1, "abcdefgh", 8));
+  EXPECT_EQ(2u, BIO_ctrl_get_write_guarantee(bio1));
+  ASSERT_EQ(3, BIO_read(bio2, buf, 3));
+  EXPECT_EQ(Bytes("abc"), Bytes(buf, 3));
+  EXPECT_EQ(5u, BIO_ctrl_get_write_guarantee(bio1));
+  EXPECT_EQ(5, BIO_write(bio1, "ijklm___", 8));
+  EXPECT_EQ(0u, BIO_ctrl_get_write_guarantee(bio1));
+  ASSERT_EQ(10, BIO_read(bio2, buf, sizeof(buf)));
+  EXPECT_EQ(Bytes("defghijklm"), Bytes(buf, 10));
+  EXPECT_EQ(10u, BIO_ctrl_get_write_guarantee(bio1));
+
+  // Data may flow from both ends in parallel.
+  EXPECT_EQ(5, BIO_write(bio1, "12345", 5));
+  EXPECT_EQ(5, BIO_write(bio2, "67890", 5));
+  ASSERT_EQ(5, BIO_read(bio2, buf, sizeof(buf)));
+  EXPECT_EQ(Bytes("12345"), Bytes(buf, 5));
+  ASSERT_EQ(5, BIO_read(bio1, buf, sizeof(buf)));
+  EXPECT_EQ(Bytes("67890"), Bytes(buf, 5));
+
+  // Closing the write end causes an EOF on the read half, after draining.
+  EXPECT_EQ(5, BIO_write(bio1, "12345", 5));
+  EXPECT_TRUE(BIO_shutdown_wr(bio1));
+  ASSERT_EQ(5, BIO_read(bio2, buf, sizeof(buf)));
+  EXPECT_EQ(Bytes("12345"), Bytes(buf, 5));
+  EXPECT_EQ(0, BIO_read(bio2, buf, sizeof(buf)));
+
+  // A closed write end may not be written to.
+  EXPECT_EQ(0u, BIO_ctrl_get_write_guarantee(bio1));
+  EXPECT_EQ(-1, BIO_write(bio1, "_____", 5));
+
+  uint32_t err = ERR_get_error();
+  EXPECT_EQ(ERR_LIB_BIO, ERR_GET_LIB(err));
+  EXPECT_EQ(BIO_R_BROKEN_PIPE, ERR_GET_REASON(err));
+
+  // The other end is still functional.
+  EXPECT_EQ(5, BIO_write(bio2, "12345", 5));
+  ASSERT_EQ(5, BIO_read(bio1, buf, sizeof(buf)));
+  EXPECT_EQ(Bytes("12345"), Bytes(buf, 5));
 }
 
-int main(void) {
-  CRYPTO_library_init();
-  ERR_load_crypto_strings();
-
-#if defined(OPENSSL_WINDOWS)
-  // Initialize Winsock.
-  WORD wsa_version = MAKEWORD(2, 2);
-  WSADATA wsa_data;
-  int wsa_err = WSAStartup(wsa_version, &wsa_data);
-  if (wsa_err != 0) {
-    fprintf(stderr, "WSAStartup failed: %d\n", wsa_err);
-    return 1;
-  }
-  if (wsa_data.wVersion != wsa_version) {
-    fprintf(stderr, "Didn't get expected version: %x\n", wsa_data.wVersion);
-    return 1;
-  }
-#endif
-
-  if (!TestSocketConnect() ||
-      !TestPrintf() ||
-      !TestZeroCopyBioPairs() ||
-      !TestASN1()) {
-    return 1;
-  }
-
-  printf("PASS\n");
-  return 0;
-}
+INSTANTIATE_TEST_CASE_P(, BIOPairTest, testing::Values(false, true));
diff --git a/src/crypto/bio/buffer.c b/src/crypto/bio/buffer.c
deleted file mode 100644
index 9d0cb3c..0000000
--- a/src/crypto/bio/buffer.c
+++ /dev/null
@@ -1,496 +0,0 @@
-/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- * 
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to.  The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- * 
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- * 
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *    "This product includes cryptographic software written by
- *     Eric Young (eay@cryptsoft.com)"
- *    The word 'cryptographic' can be left out if the rouines from the library
- *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from 
- *    the apps directory (application code) you must include an acknowledgement:
- *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- * 
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * 
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed.  i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.] */
-
-#include <openssl/bio.h>
-
-#include <string.h>
-
-#include <openssl/buf.h>
-#include <openssl/err.h>
-#include <openssl/mem.h>
-
-
-#define DEFAULT_BUFFER_SIZE 4096
-
-typedef struct bio_f_buffer_ctx_struct {
-  /* Buffers are setup like this:
-   *
-   * <---------------------- size ----------------------->
-   * +---------------------------------------------------+
-   * | consumed | remaining          | free space        |
-   * +---------------------------------------------------+
-   * <-- off --><------- len ------->
-   */
-
-  int ibuf_size;  /* how big is the input buffer */
-  int obuf_size;  /* how big is the output buffer */
-
-  char *ibuf;   /* the char array */
-  int ibuf_len; /* how many bytes are in it */
-  int ibuf_off; /* write/read offset */
-
-  char *obuf;   /* the char array */
-  int obuf_len; /* how many bytes are in it */
-  int obuf_off; /* write/read offset */
-} BIO_F_BUFFER_CTX;
-
-static int buffer_new(BIO *bio) {
-  BIO_F_BUFFER_CTX *ctx;
-
-  ctx = OPENSSL_malloc(sizeof(BIO_F_BUFFER_CTX));
-  if (ctx == NULL) {
-    return 0;
-  }
-  memset(ctx, 0, sizeof(BIO_F_BUFFER_CTX));
-
-  ctx->ibuf = OPENSSL_malloc(DEFAULT_BUFFER_SIZE);
-  if (ctx->ibuf == NULL) {
-    goto err1;
-  }
-  ctx->obuf = (char *)OPENSSL_malloc(DEFAULT_BUFFER_SIZE);
-  if (ctx->obuf == NULL) {
-    goto err2;
-  }
-  ctx->ibuf_size = DEFAULT_BUFFER_SIZE;
-  ctx->obuf_size = DEFAULT_BUFFER_SIZE;
-
-  bio->init = 1;
-  bio->ptr = (char *)ctx;
-  return 1;
-
-err2:
-  OPENSSL_free(ctx->ibuf);
-
-err1:
-  OPENSSL_free(ctx);
-  return 0;
-}
-
-static int buffer_free(BIO *bio) {
-  BIO_F_BUFFER_CTX *ctx;
-
-  if (bio == NULL || bio->ptr == NULL) {
-    return 0;
-  }
-
-  ctx = (BIO_F_BUFFER_CTX *)bio->ptr;
-  OPENSSL_free(ctx->ibuf);
-  OPENSSL_free(ctx->obuf);
-  OPENSSL_free(bio->ptr);
-
-  bio->ptr = NULL;
-  bio->init = 0;
-  bio->flags = 0;
-
-  return 1;
-}
-
-static int buffer_read(BIO *bio, char *out, int outl) {
-  int i, num = 0;
-  BIO_F_BUFFER_CTX *ctx;
-
-  ctx = (BIO_F_BUFFER_CTX *)bio->ptr;
-
-  if (ctx == NULL || bio->next_bio == NULL) {
-    return 0;
-  }
-
-  num = 0;
-  BIO_clear_retry_flags(bio);
-
-  for (;;) {
-    i = ctx->ibuf_len;
-    /* If there is stuff left over, grab it */
-    if (i != 0) {
-      if (i > outl) {
-        i = outl;
-      }
-      memcpy(out, &ctx->ibuf[ctx->ibuf_off], i);
-      ctx->ibuf_off += i;
-      ctx->ibuf_len -= i;
-      num += i;
-      if (outl == i) {
-        return num;
-      }
-      outl -= i;
-      out += i;
-    }
-
-    /* We may have done a partial read. Try to do more. We have nothing in the
-     * buffer. If we get an error and have read some data, just return it and
-     * let them retry to get the error again. Copy direct to parent address
-     * space */
-    if (outl > ctx->ibuf_size) {
-      for (;;) {
-        i = BIO_read(bio->next_bio, out, outl);
-        if (i <= 0) {
-          BIO_copy_next_retry(bio);
-          if (i < 0) {
-            return (num > 0) ? num : i;
-          }
-          return num;
-        }
-        num += i;
-        if (outl == i) {
-          return num;
-        }
-        out += i;
-        outl -= i;
-      }
-    }
-    /* else */
-
-    /* we are going to be doing some buffering */
-    i = BIO_read(bio->next_bio, ctx->ibuf, ctx->ibuf_size);
-    if (i <= 0) {
-      BIO_copy_next_retry(bio);
-      if (i < 0) {
-        return (num > 0) ? num : i;
-      }
-      return num;
-    }
-    ctx->ibuf_off = 0;
-    ctx->ibuf_len = i;
-  }
-}
-
-static int buffer_write(BIO *b, const char *in, int inl) {
-  int i, num = 0;
-  BIO_F_BUFFER_CTX *ctx;
-
-  ctx = (BIO_F_BUFFER_CTX *)b->ptr;
-  if (ctx == NULL || b->next_bio == NULL) {
-    return 0;
-  }
-
-  BIO_clear_retry_flags(b);
-
-  for (;;) {
-    i = ctx->obuf_size - (ctx->obuf_off + ctx->obuf_len);
-    /* add to buffer and return */
-    if (i >= inl) {
-      memcpy(&ctx->obuf[ctx->obuf_off + ctx->obuf_len], in, inl);
-      ctx->obuf_len += inl;
-      return num + inl;
-    }
-    /* else */
-    /* stuff already in buffer, so add to it first, then flush */
-    if (ctx->obuf_len != 0) {
-      if (i > 0) {
-        memcpy(&ctx->obuf[ctx->obuf_off + ctx->obuf_len], in, i);
-        in += i;
-        inl -= i;
-        num += i;
-        ctx->obuf_len += i;
-      }
-
-      /* we now have a full buffer needing flushing */
-      for (;;) {
-        i = BIO_write(b->next_bio, &ctx->obuf[ctx->obuf_off], ctx->obuf_len);
-        if (i <= 0) {
-          BIO_copy_next_retry(b);
-
-          if (i < 0) {
-            return (num > 0) ? num : i;
-          }
-          return num;
-        }
-        ctx->obuf_off += i;
-        ctx->obuf_len -= i;
-        if (ctx->obuf_len == 0) {
-          break;
-        }
-      }
-    }
-
-    /* we only get here if the buffer has been flushed and we
-     * still have stuff to write */
-    ctx->obuf_off = 0;
-
-    /* we now have inl bytes to write */
-    while (inl >= ctx->obuf_size) {
-      i = BIO_write(b->next_bio, in, inl);
-      if (i <= 0) {
-        BIO_copy_next_retry(b);
-        if (i < 0) {
-          return (num > 0) ? num : i;
-        }
-        return num;
-      }
-      num += i;
-      in += i;
-      inl -= i;
-      if (inl == 0) {
-        return num;
-      }
-    }
-
-    /* copy the rest into the buffer since we have only a small
-     * amount left */
-  }
-}
-
-static long buffer_ctrl(BIO *b, int cmd, long num, void *ptr) {
-  BIO_F_BUFFER_CTX *ctx;
-  long ret = 1;
-  char *p1, *p2;
-  int r, *ip;
-  int ibs, obs;
-
-  ctx = (BIO_F_BUFFER_CTX *)b->ptr;
-
-  switch (cmd) {
-    case BIO_CTRL_RESET:
-      ctx->ibuf_off = 0;
-      ctx->ibuf_len = 0;
-      ctx->obuf_off = 0;
-      ctx->obuf_len = 0;
-      if (b->next_bio == NULL) {
-        return 0;
-      }
-      ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
-      break;
-
-    case BIO_CTRL_INFO:
-      ret = ctx->obuf_len;
-      break;
-
-    case BIO_CTRL_WPENDING:
-      ret = (long)ctx->obuf_len;
-      if (ret == 0) {
-        if (b->next_bio == NULL) {
-          return 0;
-        }
-        ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
-      }
-      break;
-
-    case BIO_CTRL_PENDING:
-      ret = (long)ctx->ibuf_len;
-      if (ret == 0) {
-        if (b->next_bio == NULL) {
-          return 0;
-        }
-        ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
-      }
-      break;
-
-    case BIO_C_SET_BUFF_SIZE:
-      ip = (int *)ptr;
-      if (*ip == 0) {
-        ibs = (int)num;
-        obs = ctx->obuf_size;
-      } else /* if (*ip == 1) */ {
-        ibs = ctx->ibuf_size;
-        obs = (int)num;
-      }
-      p1 = ctx->ibuf;
-      p2 = ctx->obuf;
-      if (ibs > DEFAULT_BUFFER_SIZE && ibs != ctx->ibuf_size) {
-        p1 = (char *)OPENSSL_malloc(ibs);
-        if (p1 == NULL) {
-          goto malloc_error;
-        }
-      }
-      if (obs > DEFAULT_BUFFER_SIZE && obs != ctx->obuf_size) {
-        p2 = (char *)OPENSSL_malloc(obs);
-        if (p2 == NULL) {
-          if (p1 != ctx->ibuf) {
-            OPENSSL_free(p1);
-          }
-          goto malloc_error;
-        }
-      }
-
-      if (ctx->ibuf != p1) {
-        OPENSSL_free(ctx->ibuf);
-        ctx->ibuf = p1;
-        ctx->ibuf_size = ibs;
-      }
-      ctx->ibuf_off = 0;
-      ctx->ibuf_len = 0;
-
-      if (ctx->obuf != p2) {
-        OPENSSL_free(ctx->obuf);
-        ctx->obuf = p2;
-        ctx->obuf_size = obs;
-      }
-      ctx->obuf_off = 0;
-      ctx->obuf_len = 0;
-      break;
-
-    case BIO_CTRL_FLUSH:
-      if (b->next_bio == NULL) {
-        return 0;
-      }
-
-      while (ctx->obuf_len > 0) {
-        BIO_clear_retry_flags(b);
-        r = BIO_write(b->next_bio, &(ctx->obuf[ctx->obuf_off]),
-                      ctx->obuf_len);
-        BIO_copy_next_retry(b);
-        if (r <= 0) {
-          return r;
-        }
-        ctx->obuf_off += r;
-        ctx->obuf_len -= r;
-      }
-
-      ctx->obuf_len = 0;
-      ctx->obuf_off = 0;
-      ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
-      break;
-
-    default:
-      if (b->next_bio == NULL) {
-        return 0;
-      }
-      BIO_clear_retry_flags(b);
-      ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
-      BIO_copy_next_retry(b);
-      break;
-  }
-  return ret;
-
-malloc_error:
-  OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
-  return 0;
-}
-
-static long buffer_callback_ctrl(BIO *b, int cmd, bio_info_cb fp) {
-  long ret = 1;
-
-  if (b->next_bio == NULL) {
-    return 0;
-  }
-
-  switch (cmd) {
-    default:
-      ret = BIO_callback_ctrl(b->next_bio, cmd, fp);
-      break;
-  }
-  return ret;
-}
-
-static int buffer_gets(BIO *b, char *buf, int size) {
-  BIO_F_BUFFER_CTX *ctx;
-  int num = 0, i, flag;
-  char *p;
-
-  ctx = (BIO_F_BUFFER_CTX *)b->ptr;
-  if (buf == NULL || size <= 0) {
-    return 0;
-  }
-
-  size--; /* reserve space for a '\0' */
-  BIO_clear_retry_flags(b);
-
-  for (;;) {
-    if (ctx->ibuf_len > 0) {
-      p = &ctx->ibuf[ctx->ibuf_off];
-      flag = 0;
-      for (i = 0; (i < ctx->ibuf_len) && (i < size); i++) {
-        *(buf++) = p[i];
-        if (p[i] == '\n') {
-          flag = 1;
-          i++;
-          break;
-        }
-      }
-      num += i;
-      size -= i;
-      ctx->ibuf_len -= i;
-      ctx->ibuf_off += i;
-      if (flag || size == 0) {
-        *buf = '\0';
-        return num;
-      }
-    } else /* read another chunk */
-    {
-      i = BIO_read(b->next_bio, ctx->ibuf, ctx->ibuf_size);
-      if (i <= 0) {
-        BIO_copy_next_retry(b);
-        *buf = '\0';
-        if (i < 0) {
-          return (num > 0) ? num : i;
-        }
-        return num;
-      }
-      ctx->ibuf_len = i;
-      ctx->ibuf_off = 0;
-    }
-  }
-}
-
-static int buffer_puts(BIO *b, const char *str) {
-  return buffer_write(b, str, strlen(str));
-}
-
-static const BIO_METHOD methods_buffer = {
-    BIO_TYPE_BUFFER, "buffer",             buffer_write, buffer_read,
-    buffer_puts,     buffer_gets,          buffer_ctrl,  buffer_new,
-    buffer_free,     buffer_callback_ctrl,
-};
-
-const BIO_METHOD *BIO_f_buffer(void) { return &methods_buffer; }
-
-int BIO_set_read_buffer_size(BIO *bio, int buffer_size) {
-  return BIO_int_ctrl(bio, BIO_C_SET_BUFF_SIZE, buffer_size, 0);
-}
-
-int BIO_set_write_buffer_size(BIO *bio, int buffer_size) {
-  return BIO_int_ctrl(bio, BIO_C_SET_BUFF_SIZE, buffer_size, 1);
-}
diff --git a/src/crypto/bio/connect.c b/src/crypto/bio/connect.c
index 0b0bf13..d40dd53 100644
--- a/src/crypto/bio/connect.c
+++ b/src/crypto/bio/connect.c
@@ -58,7 +58,6 @@
 
 #include <assert.h>
 #include <errno.h>
-#include <stdio.h>
 #include <string.h>
 
 #if !defined(OPENSSL_WINDOWS)
@@ -67,10 +66,10 @@
 #include <arpa/inet.h>
 #include <unistd.h>
 #else
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <winsock2.h>
 #include <ws2tcpip.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
 #endif
 
 #include <openssl/buf.h>
@@ -78,6 +77,7 @@
 #include <openssl/mem.h>
 
 #include "internal.h"
+#include "../internal.h"
 
 
 enum {
@@ -299,7 +299,7 @@
   if (ret == NULL) {
     return NULL;
   }
-  memset(ret, 0, sizeof(BIO_CONNECT));
+  OPENSSL_memset(ret, 0, sizeof(BIO_CONNECT));
 
   ret->state = BIO_CONN_S_BEFORE;
   return ret;
@@ -468,14 +468,6 @@
       break;
     case BIO_CTRL_FLUSH:
       break;
-    case BIO_CTRL_SET_CALLBACK: {
-#if 0 /* FIXME: Should this be used?  -- Richard Levitte */
-		OPENSSL_PUT_ERROR(BIO, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
-		ret = -1;
-#else
-      ret = 0;
-#endif
-    } break;
     case BIO_CTRL_GET_CALLBACK: {
       int (**fptr)(const BIO *bio, int state, int xret);
       fptr = (int (**)(const BIO *bio, int state, int xret))ptr;
@@ -485,7 +477,7 @@
       ret = 0;
       break;
   }
-  return (ret);
+  return ret;
 }
 
 static long conn_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) {
@@ -495,9 +487,9 @@
   data = (BIO_CONNECT *)bio->ptr;
 
   switch (cmd) {
-    case BIO_CTRL_SET_CALLBACK: {
+    case BIO_CTRL_SET_CALLBACK:
       data->info_callback = (int (*)(const struct bio_st *, int, int))fp;
-    } break;
+      break;
     default:
       ret = 0;
       break;
@@ -505,10 +497,6 @@
   return ret;
 }
 
-static int conn_puts(BIO *bp, const char *str) {
-  return conn_write(bp, str, strlen(str));
-}
-
 BIO *BIO_new_connect(const char *hostname) {
   BIO *ret;
 
@@ -524,8 +512,8 @@
 }
 
 static const BIO_METHOD methods_connectp = {
-    BIO_TYPE_CONNECT, "socket connect",         conn_write, conn_read,
-    conn_puts,        NULL /* connect_gets, */, conn_ctrl,  conn_new,
+    BIO_TYPE_CONNECT, "socket connect",   conn_write, conn_read,
+    NULL /* puts */,  NULL /* gets */,    conn_ctrl,  conn_new,
     conn_free,        conn_callback_ctrl,
 };
 
@@ -539,6 +527,16 @@
   return BIO_ctrl(bio, BIO_C_SET_CONNECT, 1, (void*) port_str);
 }
 
+int BIO_set_conn_int_port(BIO *bio, const int *port) {
+  char buf[DECIMAL_SIZE(int) + 1];
+  BIO_snprintf(buf, sizeof(buf), "%d", *port);
+  return BIO_set_conn_port(bio, buf);
+}
+
 int BIO_set_nbio(BIO *bio, int on) {
   return BIO_ctrl(bio, BIO_C_SET_NBIO, on, NULL);
 }
+
+int BIO_do_connect(BIO *bio) {
+  return BIO_ctrl(bio, BIO_C_DO_STATE_MACHINE, 0, NULL);
+}
diff --git a/src/crypto/bio/fd.c b/src/crypto/bio/fd.c
index 0b3484c..4e9eeac 100644
--- a/src/crypto/bio/fd.c
+++ b/src/crypto/bio/fd.c
@@ -63,15 +63,17 @@
 #include <unistd.h>
 #else
 #include <io.h>
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <windows.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
 #endif
 
 #include <openssl/buf.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
+#include "internal.h"
+
 
 static int bio_fd_non_fatal_error(int err) {
   if (
@@ -106,20 +108,25 @@
 }
 
 #if defined(OPENSSL_WINDOWS)
-int bio_fd_should_retry(int i) {
-  if (i == -1) {
-    return bio_fd_non_fatal_error((int)GetLastError());
-  }
-  return 0;
-}
+  #define BORINGSSL_ERRNO (int)GetLastError()
+  #define BORINGSSL_CLOSE _close
+  #define BORINGSSL_LSEEK _lseek
+  #define BORINGSSL_READ _read
+  #define BORINGSSL_WRITE _write
 #else
+  #define BORINGSSL_ERRNO errno
+  #define BORINGSSL_CLOSE close
+  #define BORINGSSL_LSEEK lseek
+  #define BORINGSSL_READ read
+  #define BORINGSSL_WRITE write
+#endif
+
 int bio_fd_should_retry(int i) {
   if (i == -1) {
-    return bio_fd_non_fatal_error(errno);
+    return bio_fd_non_fatal_error(BORINGSSL_ERRNO);
   }
   return 0;
 }
-#endif
 
 BIO *BIO_new_fd(int fd, int close_flag) {
   BIO *ret = BIO_new(BIO_s_fd());
@@ -143,7 +150,7 @@
 
   if (bio->shutdown) {
     if (bio->init) {
-      close(bio->num);
+      BORINGSSL_CLOSE(bio->num);
     }
     bio->init = 0;
   }
@@ -153,7 +160,7 @@
 static int fd_read(BIO *b, char *out, int outl) {
   int ret = 0;
 
-  ret = read(b->num, out, outl);
+  ret = BORINGSSL_READ(b->num, out, outl);
   BIO_clear_retry_flags(b);
   if (ret <= 0) {
     if (bio_fd_should_retry(ret)) {
@@ -165,7 +172,7 @@
 }
 
 static int fd_write(BIO *b, const char *in, int inl) {
-  int ret = write(b->num, in, inl);
+  int ret = BORINGSSL_WRITE(b->num, in, inl);
   BIO_clear_retry_flags(b);
   if (ret <= 0) {
     if (bio_fd_should_retry(ret)) {
@@ -186,14 +193,14 @@
     case BIO_C_FILE_SEEK:
       ret = 0;
       if (b->init) {
-        ret = (long)lseek(b->num, num, SEEK_SET);
+        ret = (long)BORINGSSL_LSEEK(b->num, num, SEEK_SET);
       }
       break;
     case BIO_C_FILE_TELL:
     case BIO_CTRL_INFO:
       ret = 0;
       if (b->init) {
-        ret = (long)lseek(b->num, 0, SEEK_CUR);
+        ret = (long)BORINGSSL_LSEEK(b->num, 0, SEEK_CUR);
       }
       break;
     case BIO_C_SET_FD:
@@ -234,10 +241,6 @@
   return ret;
 }
 
-static int fd_puts(BIO *bp, const char *str) {
-  return fd_write(bp, str, strlen(str));
-}
-
 static int fd_gets(BIO *bp, char *buf, int size) {
   char *ptr = buf;
   char *end = buf + size - 1;
@@ -256,8 +259,9 @@
 }
 
 static const BIO_METHOD methods_fdp = {
-    BIO_TYPE_FD, "file descriptor", fd_write, fd_read, fd_puts,
-    fd_gets,     fd_ctrl,           fd_new,   fd_free, NULL, };
+    BIO_TYPE_FD, "file descriptor", fd_write, fd_read, NULL /* puts */,
+    fd_gets,     fd_ctrl,           fd_new,   fd_free, NULL /* callback_ctrl */,
+};
 
 const BIO_METHOD *BIO_s_fd(void) { return &methods_fdp; }
 
diff --git a/src/crypto/bio/file.c b/src/crypto/bio/file.c
index 9e29b43..3580cd1 100644
--- a/src/crypto/bio/file.c
+++ b/src/crypto/bio/file.c
@@ -87,47 +87,11 @@
 #define BIO_FP_WRITE 0x04
 #define BIO_FP_APPEND 0x08
 
-static FILE *open_file(const char *filename, const char *mode) {
-#if defined(OPENSSL_WINDOWS) && defined(CP_UTF8)
-  int sz, len_0 = (int)strlen(filename) + 1;
-  DWORD flags;
-
-  /* Basically there are three cases to cover: a) filename is pure ASCII
-   * string; b) actual UTF-8 encoded string and c) locale-ized string, i.e. one
-   * containing 8-bit characters that are meaningful in current system locale.
-   * If filename is pure ASCII or real UTF-8 encoded string,
-   * MultiByteToWideChar succeeds and _wfopen works. If filename is locale-ized
-   * string, chances are that MultiByteToWideChar fails reporting
-   * ERROR_NO_UNICODE_TRANSLATION, in which case we fall back to fopen... */
-  if ((sz = MultiByteToWideChar(CP_UTF8, (flags = MB_ERR_INVALID_CHARS),
-                                filename, len_0, NULL, 0)) > 0 ||
-      (GetLastError() == ERROR_INVALID_FLAGS &&
-       (sz = MultiByteToWideChar(CP_UTF8, (flags = 0), filename, len_0, NULL,
-                                 0)) > 0)) {
-    WCHAR wmode[8];
-    WCHAR *wfilename = _alloca(sz * sizeof(WCHAR));
-
-    if (MultiByteToWideChar(CP_UTF8, flags, filename, len_0, wfilename, sz) &&
-        MultiByteToWideChar(CP_UTF8, 0, mode, strlen(mode) + 1, wmode,
-                            sizeof(wmode) / sizeof(wmode[0])) &&
-        (file = _wfopen(wfilename, wmode)) == NULL &&
-        (errno == ENOENT ||
-         errno == EBADF)) /* UTF-8 decode succeeded, but no file, filename
-                           * could still have been locale-ized... */
-      return fopen(filename, mode);
-  } else if (GetLastError() == ERROR_NO_UNICODE_TRANSLATION) {
-    return fopen(filename, mode);
-  }
-#else
-  return fopen(filename, mode);
-#endif
-}
-
 BIO *BIO_new_file(const char *filename, const char *mode) {
   BIO *ret;
   FILE *file;
 
-  file = open_file(filename, mode);
+  file = fopen(filename, mode);
   if (file == NULL) {
     OPENSSL_PUT_SYSTEM_ERROR();
 
@@ -256,7 +220,7 @@
         ret = 0;
         break;
       }
-      fp = open_file(ptr, p);
+      fp = fopen(ptr, p);
       if (fp == NULL) {
         OPENSSL_PUT_SYSTEM_ERROR();
         ERR_add_error_data(5, "fopen('", ptr, "','", p, "')");
@@ -309,13 +273,13 @@
   return ret;
 }
 
-static int file_puts(BIO *bp, const char *str) {
-  return file_write(bp, str, strlen(str));
-}
-
 static const BIO_METHOD methods_filep = {
-    BIO_TYPE_FILE, "FILE pointer", file_write, file_read, file_puts,
-    file_gets,     file_ctrl,      file_new,   file_free, NULL, };
+    BIO_TYPE_FILE,   "FILE pointer",
+    file_write,      file_read,
+    NULL /* puts */, file_gets,
+    file_ctrl,       file_new,
+    file_free,       NULL /* callback_ctrl */,
+};
 
 const BIO_METHOD *BIO_s_file(void) { return &methods_filep; }
 
diff --git a/src/crypto/bio/hexdump.c b/src/crypto/bio/hexdump.c
index 17f5518..d55df62 100644
--- a/src/crypto/bio/hexdump.c
+++ b/src/crypto/bio/hexdump.c
@@ -59,6 +59,8 @@
 #include <limits.h>
 #include <string.h>
 
+#include "../internal.h"
+
 
 /* hexdump_ctx contains the state of a hexdump. */
 struct hexdump_ctx {
@@ -86,7 +88,6 @@
  * |ctx|. */
 static int hexdump_write(struct hexdump_ctx *ctx, const uint8_t *data,
                          size_t len) {
-  size_t i;
   char buf[10];
   unsigned l;
 
@@ -95,7 +96,7 @@
    * ^ offset                          ^ extra space           ^ ASCII of line
    */
 
-  for (i = 0; i < len; i++) {
+  for (size_t i = 0; i < len; i++) {
     if (ctx->used == 0) {
       /* The beginning of a line. */
       BIO_indent(ctx->bio, ctx->indent, UINT_MAX);
@@ -155,7 +156,7 @@
     return 1;
   }
 
-  memset(buf, ' ', 4);
+  OPENSSL_memset(buf, ' ', 4);
   buf[4] = '|';
 
   for (; ctx->used < 16; ctx->used++) {
@@ -180,7 +181,7 @@
 
 int BIO_hexdump(BIO *bio, const uint8_t *data, size_t len, unsigned indent) {
   struct hexdump_ctx ctx;
-  memset(&ctx, 0, sizeof(ctx));
+  OPENSSL_memset(&ctx, 0, sizeof(ctx));
   ctx.bio = bio;
   ctx.indent = indent;
 
diff --git a/src/crypto/bio/internal.h b/src/crypto/bio/internal.h
index d9a34f1..4ec77fa 100644
--- a/src/crypto/bio/internal.h
+++ b/src/crypto/bio/internal.h
@@ -67,6 +67,9 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 #else
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
+#include <winsock2.h>
+OPENSSL_MSVC_PRAGMA(warning(pop))
 typedef int socklen_t;
 #endif
 
diff --git a/src/crypto/bio/pair.c b/src/crypto/bio/pair.c
index fba4be2..8ba382d 100644
--- a/src/crypto/bio/pair.c
+++ b/src/crypto/bio/pair.c
@@ -59,6 +59,8 @@
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
+#include "../internal.h"
+
 
 struct bio_bio_st {
   BIO *peer; /* NULL if buf == NULL.
@@ -72,12 +74,6 @@
   size_t offset; /* valid iff buf != NULL; 0 if len == 0 */
   size_t size;
   uint8_t *buf; /* "size" elements (if != NULL) */
-  char buf_externally_allocated; /* true iff buf was externally allocated. */
-
-  char zero_copy_read_lock;  /* true iff a zero copy read operation
-                              * is in progress. */
-  char zero_copy_write_lock; /* true iff a zero copy write operation
-                              * is in progress. */
 
   size_t request; /* valid iff peer != NULL; 0 if len != 0,
                    * otherwise set by peer to number of bytes
@@ -92,7 +88,7 @@
   if (b == NULL) {
     return 0;
   }
-  memset(b, 0, sizeof(struct bio_bio_st));
+  OPENSSL_memset(b, 0, sizeof(struct bio_bio_st));
 
   b->size = 17 * 1024; /* enough for one TLS record (just a default) */
   bio->ptr = b;
@@ -145,263 +141,12 @@
     bio_destroy_pair(bio);
   }
 
-  if (!b->buf_externally_allocated) {
-    OPENSSL_free(b->buf);
-  }
-
+  OPENSSL_free(b->buf);
   OPENSSL_free(b);
 
   return 1;
 }
 
-static size_t bio_zero_copy_get_read_buf(struct bio_bio_st* peer_b,
-                                         uint8_t** out_read_buf,
-                                         size_t* out_buf_offset) {
-  size_t max_available;
-  if (peer_b->len > peer_b->size - peer_b->offset) {
-    /* Only the first half of the ring buffer can be read. */
-    max_available = peer_b->size - peer_b->offset;
-  } else {
-    max_available = peer_b->len;
-  }
-
-  *out_read_buf = peer_b->buf;
-  *out_buf_offset = peer_b->offset;
-  return max_available;
-}
-
-int BIO_zero_copy_get_read_buf(BIO* bio, uint8_t** out_read_buf,
-                               size_t* out_buf_offset,
-                               size_t* out_available_bytes) {
-  struct bio_bio_st* b;
-  struct bio_bio_st* peer_b;
-  size_t max_available;
-  *out_available_bytes = 0;
-
-  BIO_clear_retry_flags(bio);
-
-  if (!bio->init) {
-    OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
-    return 0;
-  }
-
-  b = bio->ptr;
-
-  if (!b || !b->peer) {
-    OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
-    return 0;
-  }
-
-  peer_b = b->peer->ptr;
-  if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
-    OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
-    return 0;
-  }
-
-  if (peer_b->zero_copy_read_lock) {
-    OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
-    return 0;
-  }
-
-  peer_b->request = 0;  /* Is not used by zero-copy API. */
-
-  max_available =
-      bio_zero_copy_get_read_buf(peer_b, out_read_buf, out_buf_offset);
-
-  assert(peer_b->buf != NULL);
-  if (max_available > 0) {
-    peer_b->zero_copy_read_lock = 1;
-  }
-
-  *out_available_bytes = max_available;
-  return 1;
-}
-
-int BIO_zero_copy_get_read_buf_done(BIO* bio, size_t bytes_read) {
-  struct bio_bio_st* b;
-  struct bio_bio_st* peer_b;
-  size_t max_available;
-  size_t dummy_read_offset;
-  uint8_t* dummy_read_buf;
-
-  assert(BIO_get_retry_flags(bio) == 0);
-
-  if (!bio->init) {
-    OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
-    return 0;
-  }
-
-  b = bio->ptr;
-
-  if (!b || !b->peer) {
-    OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
-    return 0;
-  }
-
-  peer_b = b->peer->ptr;
-  if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
-    OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
-    return 0;
-  }
-
-  if (!peer_b->zero_copy_read_lock) {
-    OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
-    return 0;
-  }
-
-  max_available =
-      bio_zero_copy_get_read_buf(peer_b, &dummy_read_buf, &dummy_read_offset);
-  if (bytes_read > max_available) {
-    OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
-    return 0;
-  }
-
-  assert(peer_b->len >= bytes_read);
-  peer_b->len -= bytes_read;
-  assert(peer_b->offset + bytes_read <= peer_b->size);
-
-  /* Move read offset. If zero_copy_write_lock == 1 we must advance the
-   * offset even if buffer becomes empty, to make sure
-   * write_offset = (offset + len) mod size does not change. */
-  if (peer_b->offset + bytes_read == peer_b->size ||
-      (!peer_b->zero_copy_write_lock && peer_b->len == 0)) {
-    peer_b->offset = 0;
-  } else {
-    peer_b->offset += bytes_read;
-  }
-
-  bio->num_read += bytes_read;
-  peer_b->zero_copy_read_lock = 0;
-  return 1;
-}
-
-static size_t bio_zero_copy_get_write_buf(struct bio_bio_st* b,
-                                          uint8_t** out_write_buf,
-                                          size_t* out_buf_offset) {
-  size_t write_offset;
-  size_t max_available;
-
-  assert(b->len <= b->size);
-
-  write_offset = b->offset + b->len;
-
-  if (write_offset >= b->size) {
-    /* Only the first half of the ring buffer can be written to. */
-    write_offset -= b->size;
-    /* write up to the start of the ring buffer. */
-    max_available = b->offset - write_offset;
-  } else {
-    /* write up to the end the buffer. */
-    max_available = b->size - write_offset;
-  }
-
-  *out_write_buf = b->buf;
-  *out_buf_offset = write_offset;
-  return max_available;
-}
-
-int BIO_zero_copy_get_write_buf(BIO* bio, uint8_t** out_write_buf,
-                                size_t* out_buf_offset,
-                                size_t* out_available_bytes) {
-  struct bio_bio_st* b;
-  struct bio_bio_st* peer_b;
-  size_t max_available;
-
-  *out_available_bytes = 0;
-  BIO_clear_retry_flags(bio);
-
-  if (!bio->init) {
-    OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
-    return 0;
-  }
-
-  b = bio->ptr;
-
-  if (!b || !b->buf || !b->peer) {
-    OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
-    return 0;
-  }
-  peer_b = b->peer->ptr;
-  if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
-    OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
-    return 0;
-  }
-
-  assert(b->buf != NULL);
-
-  if (b->zero_copy_write_lock) {
-    OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
-    return 0;
-  }
-
-  b->request = 0;
-  if (b->closed) {
-    /* Bio is already closed. */
-    OPENSSL_PUT_ERROR(BIO, BIO_R_BROKEN_PIPE);
-    return 0;
-  }
-
-  max_available = bio_zero_copy_get_write_buf(b, out_write_buf, out_buf_offset);
-
-  if (max_available > 0) {
-    b->zero_copy_write_lock = 1;
-  }
-
-  *out_available_bytes = max_available;
-  return 1;
-}
-
-int BIO_zero_copy_get_write_buf_done(BIO* bio, size_t bytes_written) {
-  struct bio_bio_st* b;
-  struct bio_bio_st* peer_b;
-
-  size_t rest;
-  size_t dummy_write_offset;
-  uint8_t* dummy_write_buf;
-
-  if (!bio->init) {
-    OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
-    return 0;
-  }
-
-  b = bio->ptr;
-
-  if (!b || !b->buf || !b->peer) {
-    OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
-    return 0;
-  }
-  peer_b = b->peer->ptr;
-  if (!peer_b || !peer_b->peer || peer_b->peer->ptr != b) {
-    OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
-    return 0;
-  }
-
-  b->request = 0;
-  if (b->closed) {
-    /* BIO is already closed. */
-    OPENSSL_PUT_ERROR(BIO, BIO_R_BROKEN_PIPE);
-    return 0;
-  }
-
-  if (!b->zero_copy_write_lock) {
-    OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
-    return 0;
-  }
-
-  rest = bio_zero_copy_get_write_buf(b, &dummy_write_buf, &dummy_write_offset);
-
-  if (bytes_written > rest) {
-    OPENSSL_PUT_ERROR(BIO, BIO_R_INVALID_ARGUMENT);
-    return 0;
-  }
-
-  bio->num_write += bytes_written;
-  /* Move write offset. */
-  b->len += bytes_written;
-  b->zero_copy_write_lock = 0;
-  return 1;
-}
-
 static int bio_read(BIO *bio, char *buf, int size_) {
   size_t size = size_;
   size_t rest;
@@ -422,7 +167,7 @@
 
   peer_b->request = 0; /* will be set in "retry_read" situation */
 
-  if (buf == NULL || size == 0 || peer_b->zero_copy_read_lock) {
+  if (buf == NULL || size == 0) {
     return 0;
   }
 
@@ -464,13 +209,10 @@
     }
     assert(peer_b->offset + chunk <= peer_b->size);
 
-    memcpy(buf, peer_b->buf + peer_b->offset, chunk);
+    OPENSSL_memcpy(buf, peer_b->buf + peer_b->offset, chunk);
 
     peer_b->len -= chunk;
-    /* If zero_copy_write_lock == 1 we must advance the offset even if buffer
-     * becomes empty, to make sure write_offset = (offset + len) % size
-     * does not change. */
-    if (peer_b->len || peer_b->zero_copy_write_lock) {
+    if (peer_b->len) {
       peer_b->offset += chunk;
       assert(peer_b->offset <= peer_b->size);
       if (peer_b->offset == peer_b->size) {
@@ -504,10 +246,6 @@
   assert(b->peer != NULL);
   assert(b->buf != NULL);
 
-  if (b->zero_copy_write_lock) {
-    return 0;
-  }
-
   b->request = 0;
   if (b->closed) {
     /* we already closed */
@@ -551,7 +289,7 @@
       chunk = b->size - write_offset;
     }
 
-    memcpy(b->buf + write_offset, buf, chunk);
+    OPENSSL_memcpy(b->buf + write_offset, buf, chunk);
 
     b->len += chunk;
 
@@ -564,9 +302,8 @@
   return num;
 }
 
-static int bio_make_pair(BIO* bio1, BIO* bio2,
-                         size_t writebuf1_len, uint8_t* ext_writebuf1,
-                         size_t writebuf2_len, uint8_t* ext_writebuf2) {
+static int bio_make_pair(BIO *bio1, BIO *bio2, size_t writebuf1_len,
+                         size_t writebuf2_len) {
   struct bio_bio_st *b1, *b2;
 
   assert(bio1 != NULL);
@@ -580,23 +317,14 @@
     return 0;
   }
 
-  assert(b1->buf_externally_allocated == 0);
-  assert(b2->buf_externally_allocated == 0);
-
   if (b1->buf == NULL) {
     if (writebuf1_len) {
       b1->size = writebuf1_len;
     }
-    if (!ext_writebuf1) {
-      b1->buf_externally_allocated = 0;
-      b1->buf = OPENSSL_malloc(b1->size);
-      if (b1->buf == NULL) {
-        OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
-        return 0;
-      }
-    } else {
-      b1->buf = ext_writebuf1;
-      b1->buf_externally_allocated = 1;
+    b1->buf = OPENSSL_malloc(b1->size);
+    if (b1->buf == NULL) {
+      OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
+      return 0;
     }
     b1->len = 0;
     b1->offset = 0;
@@ -606,16 +334,10 @@
     if (writebuf2_len) {
       b2->size = writebuf2_len;
     }
-    if (!ext_writebuf2) {
-      b2->buf_externally_allocated = 0;
-      b2->buf = OPENSSL_malloc(b2->size);
-      if (b2->buf == NULL) {
-        OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
-        return 0;
-      }
-    } else {
-      b2->buf = ext_writebuf2;
-      b2->buf_externally_allocated = 1;
+    b2->buf = OPENSSL_malloc(b2->size);
+    if (b2->buf == NULL) {
+      OPENSSL_PUT_ERROR(BIO, ERR_R_MALLOC_FAILURE);
+      return 0;
     }
     b2->len = 0;
     b2->offset = 0;
@@ -624,13 +346,9 @@
   b1->peer = bio2;
   b1->closed = 0;
   b1->request = 0;
-  b1->zero_copy_read_lock = 0;
-  b1->zero_copy_write_lock = 0;
   b2->peer = bio1;
   b2->closed = 0;
   b2->request = 0;
-  b2->zero_copy_read_lock = 0;
-  b2->zero_copy_write_lock = 0;
 
   bio1->init = 1;
   bio2->init = 1;
@@ -732,62 +450,30 @@
   return ret;
 }
 
-static int bio_puts(BIO *bio, const char *str) {
-  return bio_write(bio, str, strlen(str));
-}
 
 static const BIO_METHOD methods_biop = {
-    BIO_TYPE_BIO, "BIO pair",             bio_write, bio_read,
-    bio_puts,     NULL /* no bio_gets */, bio_ctrl,  bio_new,
-    bio_free,     NULL /* no bio_callback_ctrl */
+    BIO_TYPE_BIO,    "BIO pair", bio_write, bio_read, NULL /* puts */,
+    NULL /* gets */, bio_ctrl,   bio_new,   bio_free, NULL /* callback_ctrl */
 };
 
-const BIO_METHOD *bio_s_bio(void) { return &methods_biop; }
+static const BIO_METHOD *bio_s_bio(void) { return &methods_biop; }
 
-int BIO_new_bio_pair(BIO** bio1_p, size_t writebuf1,
-                     BIO** bio2_p, size_t writebuf2) {
-  return BIO_new_bio_pair_external_buf(bio1_p, writebuf1, NULL, bio2_p,
-                                       writebuf2, NULL);
-}
-
-int BIO_new_bio_pair_external_buf(BIO** bio1_p, size_t writebuf1_len,
-                                  uint8_t* ext_writebuf1,
-                                  BIO** bio2_p, size_t writebuf2_len,
-                                  uint8_t* ext_writebuf2) {
-  BIO *bio1 = NULL, *bio2 = NULL;
-  int ret = 0;
-
-  /* External buffers must have sizes greater than 0. */
-  if ((ext_writebuf1 && !writebuf1_len) || (ext_writebuf2 && !writebuf2_len)) {
-    goto err;
-  }
-
-  bio1 = BIO_new(bio_s_bio());
-  if (bio1 == NULL) {
-    goto err;
-  }
-  bio2 = BIO_new(bio_s_bio());
-  if (bio2 == NULL) {
-    goto err;
-  }
-
-  if (!bio_make_pair(bio1, bio2, writebuf1_len, ext_writebuf1, writebuf2_len,
-                     ext_writebuf2)) {
-    goto err;
-  }
-  ret = 1;
-
-err:
-  if (ret == 0) {
+int BIO_new_bio_pair(BIO** bio1_p, size_t writebuf1_len,
+                     BIO** bio2_p, size_t writebuf2_len) {
+  BIO *bio1 = BIO_new(bio_s_bio());
+  BIO *bio2 = BIO_new(bio_s_bio());
+  if (bio1 == NULL || bio2 == NULL ||
+      !bio_make_pair(bio1, bio2, writebuf1_len, writebuf2_len)) {
     BIO_free(bio1);
-    bio1 = NULL;
     BIO_free(bio2);
-    bio2 = NULL;
+    *bio1_p = NULL;
+    *bio2_p = NULL;
+    return 0;
   }
 
   *bio1_p = bio1;
   *bio2_p = bio2;
-  return ret;
+  return 1;
 }
 
 size_t BIO_ctrl_get_read_request(BIO *bio) {
diff --git a/src/crypto/bio/socket.c b/src/crypto/bio/socket.c
index 98f32a6..111761f 100644
--- a/src/crypto/bio/socket.c
+++ b/src/crypto/bio/socket.c
@@ -63,11 +63,11 @@
 #if !defined(OPENSSL_WINDOWS)
 #include <unistd.h>
 #else
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <winsock2.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
 
-#pragma comment(lib, "Ws2_32.lib")
+OPENSSL_MSVC_PRAGMA(comment(lib, "Ws2_32.lib"))
 #endif
 
 #include "internal.h"
@@ -110,7 +110,11 @@
   }
 
   bio_clear_socket_error();
+#if defined(OPENSSL_WINDOWS)
   ret = recv(b->num, out, outl, 0);
+#else
+  ret = read(b->num, out, outl);
+#endif
   BIO_clear_retry_flags(b);
   if (ret <= 0) {
     if (bio_fd_should_retry(ret)) {
@@ -124,7 +128,11 @@
   int ret;
 
   bio_clear_socket_error();
+#if defined(OPENSSL_WINDOWS)
   ret = send(b->num, in, inl, 0);
+#else
+  ret = write(b->num, in, inl);
+#endif
   BIO_clear_retry_flags(b);
   if (ret <= 0) {
     if (bio_fd_should_retry(ret)) {
@@ -134,10 +142,6 @@
   return ret;
 }
 
-static int sock_puts(BIO *bp, const char *str) {
-  return sock_write(bp, str, strlen(str));
-}
-
 static long sock_ctrl(BIO *b, int cmd, long num, void *ptr) {
   long ret = 1;
   int *ip;
@@ -177,8 +181,11 @@
 }
 
 static const BIO_METHOD methods_sockp = {
-    BIO_TYPE_SOCKET,  "socket",  sock_write, sock_read, sock_puts,
-    NULL /* gets, */, sock_ctrl, sock_new,   sock_free, NULL,
+    BIO_TYPE_SOCKET, "socket",
+    sock_write,      sock_read,
+    NULL /* puts */, NULL /* gets, */,
+    sock_ctrl,       sock_new,
+    sock_free,       NULL /* callback_ctrl */,
 };
 
 const BIO_METHOD *BIO_s_socket(void) { return &methods_sockp; }
diff --git a/src/crypto/bio/socket_helper.c b/src/crypto/bio/socket_helper.c
index 4ddc094..268405a 100644
--- a/src/crypto/bio/socket_helper.c
+++ b/src/crypto/bio/socket_helper.c
@@ -26,13 +26,14 @@
 #include <netdb.h>
 #include <unistd.h>
 #else
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <winsock2.h>
 #include <ws2tcpip.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
 #endif
 
 #include "internal.h"
+#include "../internal.h"
 
 
 int bio_ip_and_port_to_socket_and_addr(int *out_sock,
@@ -45,7 +46,7 @@
 
   *out_sock = -1;
 
-  memset(&hint, 0, sizeof(hint));
+  OPENSSL_memset(&hint, 0, sizeof(hint));
   hint.ai_family = AF_UNSPEC;
   hint.ai_socktype = SOCK_STREAM;
 
@@ -62,8 +63,8 @@
     if ((size_t) cur->ai_addrlen > sizeof(struct sockaddr_storage)) {
       continue;
     }
-    memset(out_addr, 0, sizeof(struct sockaddr_storage));
-    memcpy(out_addr, cur->ai_addr, cur->ai_addrlen);
+    OPENSSL_memset(out_addr, 0, sizeof(struct sockaddr_storage));
+    OPENSSL_memcpy(out_addr, cur->ai_addr, cur->ai_addrlen);
     *out_addr_length = cur->ai_addrlen;
 
     *out_sock = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol);
diff --git a/src/crypto/bn/CMakeLists.txt b/src/crypto/bn/CMakeLists.txt
index b9875d6..9dd24b4 100644
--- a/src/crypto/bn/CMakeLists.txt
+++ b/src/crypto/bn/CMakeLists.txt
@@ -6,7 +6,6 @@
 
     x86_64-mont.${ASM_EXT}
     x86_64-mont5.${ASM_EXT}
-    rsaz-x86_64.${ASM_EXT}
     rsaz-avx2.${ASM_EXT}
 
     rsaz_exp.c
@@ -57,6 +56,7 @@
   gcd.c
   kronecker.c
   montgomery.c
+  montgomery_inv.c
   mul.c
   prime.c
   random.c
@@ -68,7 +68,6 @@
 
 perlasm(x86_64-mont.${ASM_EXT} asm/x86_64-mont.pl)
 perlasm(x86_64-mont5.${ASM_EXT} asm/x86_64-mont5.pl)
-perlasm(rsaz-x86_64.${ASM_EXT} asm/rsaz-x86_64.pl)
 perlasm(rsaz-avx2.${ASM_EXT} asm/rsaz-avx2.pl)
 perlasm(bn-586.${ASM_EXT} asm/bn-586.pl)
 perlasm(co-586.${ASM_EXT} asm/co-586.pl)
diff --git a/src/crypto/bn/add.c b/src/crypto/bn/add.c
index 23f9f80..cfa3bbe 100644
--- a/src/crypto/bn/add.c
+++ b/src/crypto/bn/add.c
@@ -314,7 +314,7 @@
   }
 
   if (dif > 0 && rp != ap) {
-    memcpy(rp, ap, sizeof(*rp) * dif);
+    OPENSSL_memcpy(rp, ap, sizeof(*rp) * dif);
   }
 
   r->top = max;
diff --git a/src/crypto/bn/asm/armv4-mont.pl b/src/crypto/bn/asm/armv4-mont.pl
index 4206fd8..d7298d2 100644
--- a/src/crypto/bn/asm/armv4-mont.pl
+++ b/src/crypto/bn/asm/armv4-mont.pl
@@ -16,7 +16,7 @@
 # [depending on key length, less for longer keys] on ARM920T, and
 # +115-80% on Intel IXP425. This is compared to pre-bn_mul_mont code
 # base and compiler generated code with in-lined umull and even umlal
-# instructions. The latter means that this code didn't really have an 
+# instructions. The latter means that this code didn't really have an
 # "advantage" of utilizing some "secret" instruction.
 #
 # The code is interoperable with Thumb ISA and is rather compact, less
@@ -39,8 +39,8 @@
 # others outweighs the marginal loss on Cortex-A9.
 
 $flavour = shift;
-if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
-else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} }
+if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
+else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} }
 
 if ($flavour && $flavour ne "void") {
     $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
@@ -91,7 +91,6 @@
 #endif
 
 .global	bn_mul_mont
-.hidden	bn_mul_mont
 .type	bn_mul_mont,%function
 
 .align	5
@@ -108,7 +107,7 @@
 #ifdef	__APPLE__
 	ldr	r0,[r0]
 #endif
-	tst	r0,#1			@ NEON available?
+	tst	r0,#ARMV7_NEON		@ NEON available?
 	ldmia	sp, {r0,r2}
 	beq	.Lialu
 	add	sp,sp,#8
diff --git a/src/crypto/bn/asm/bn-586.pl b/src/crypto/bn/asm/bn-586.pl
index 26d9bcb..ccc9451 100644
--- a/src/crypto/bn/asm/bn-586.pl
+++ b/src/crypto/bn/asm/bn-586.pl
@@ -4,6 +4,9 @@
 push(@INC,"${dir}","${dir}../../perlasm");
 require "x86asm.pl";
 
+$output = pop;
+open STDOUT,">$output";
+
 &asm_init($ARGV[0],$0);
 
 $sse2=0;
@@ -21,6 +24,8 @@
 
 &asm_finish();
 
+close STDOUT;
+
 sub bn_mul_add_words
 	{
 	local($name)=@_;
@@ -42,7 +47,7 @@
 		&movd("mm0",&wparam(3));	# mm0 = w
 		&pxor("mm1","mm1");		# mm1 = carry_in
 		&jmp(&label("maw_sse2_entry"));
-		
+
 	&set_label("maw_sse2_unrolled",16);
 		&movd("mm3",&DWP(0,$r,"",0));	# mm3 = r[0]
 		&paddq("mm1","mm3");		# mm1 = carry_in + r[0]
@@ -663,20 +668,20 @@
 	    &adc($c,0);
 	    &mov(&DWP($i*4,$r,"",0),$tmp1); 	# *r
 	}
-	    
+
 	&comment("");
 	&add($b,32);
 	&add($r,32);
 	&sub($num,8);
 	&jnz(&label("pw_neg_loop"));
-	    
+
 	&set_label("pw_neg_finish",0);
 	&mov($tmp2,&wparam(4));	# get dl
 	&mov($num,0);
 	&sub($num,$tmp2);
 	&and($num,7);
 	&jz(&label("pw_end"));
-	    
+
 	for ($i=0; $i<7; $i++)
 	{
 	    &comment("dl<0 Tail Round $i");
@@ -693,9 +698,9 @@
 	}
 
 	&jmp(&label("pw_end"));
-	
+
 	&set_label("pw_pos",0);
-	
+
 	&and($num,0xfffffff8);	# num / 8
 	&jz(&label("pw_pos_finish"));
 
@@ -710,18 +715,18 @@
 	    &mov(&DWP($i*4,$r,"",0),$tmp1);	# *r
 	    &jnc(&label("pw_nc".$i));
 	}
-	    
+
 	&comment("");
 	&add($a,32);
 	&add($r,32);
 	&sub($num,8);
 	&jnz(&label("pw_pos_loop"));
-	    
+
 	&set_label("pw_pos_finish",0);
 	&mov($num,&wparam(4));	# get dl
 	&and($num,7);
 	&jz(&label("pw_end"));
-	    
+
 	for ($i=0; $i<7; $i++)
 	{
 	    &comment("dl>0 Tail Round $i");
@@ -742,17 +747,17 @@
 	    &mov(&DWP($i*4,$r,"",0),$tmp1);	# *r
 	    &set_label("pw_nc".$i,0);
 	}
-	    
+
 	&comment("");
 	&add($a,32);
 	&add($r,32);
 	&sub($num,8);
 	&jnz(&label("pw_nc_loop"));
-	    
+
 	&mov($num,&wparam(4));	# get dl
 	&and($num,7);
 	&jz(&label("pw_nc_end"));
-	    
+
 	for ($i=0; $i<7; $i++)
 	{
 	    &mov($tmp1,&DWP($i*4,$a,"",0));	# *a
@@ -771,4 +776,3 @@
 
 	&function_end($name);
 	}
-
diff --git a/src/crypto/bn/asm/co-586.pl b/src/crypto/bn/asm/co-586.pl
index 57101a6..c63e562 100644
--- a/src/crypto/bn/asm/co-586.pl
+++ b/src/crypto/bn/asm/co-586.pl
@@ -4,6 +4,9 @@
 push(@INC,"${dir}","${dir}../../perlasm");
 require "x86asm.pl";
 
+$output = pop;
+open STDOUT,">$output";
+
 &asm_init($ARGV[0],$0);
 
 &bn_mul_comba("bn_mul_comba8",8);
@@ -13,6 +16,8 @@
 
 &asm_finish();
 
+close STDOUT;
+
 sub mul_add_c
 	{
 	local($a,$ai,$b,$bi,$c0,$c1,$c2,$pos,$i,$na,$nb)=@_;
@@ -36,7 +41,7 @@
 	 &mov("edx",&DWP(($nb)*4,$b,"",0)) if $pos == 1;	# laod next b
 	 ###
 	&adc($c2,0);
-	 # is pos > 1, it means it is the last loop 
+	 # is pos > 1, it means it is the last loop
 	 &mov(&DWP($i*4,"eax","",0),$c0) if $pos > 0;		# save r[];
 	&mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 1;		# laod next a
 	}
@@ -65,7 +70,7 @@
 	 &mov("edx",&DWP(($nb)*4,$a,"",0)) if ($pos == 1) && ($na != $nb);
 	 ###
 	&adc($c2,0);
-	 # is pos > 1, it means it is the last loop 
+	 # is pos > 1, it means it is the last loop
 	 &mov(&DWP($i*4,$r,"",0),$c0) if $pos > 0;		# save r[];
 	&mov("eax",&DWP(($na)*4,$a,"",0)) if $pos == 1;		# load next b
 	}
@@ -116,7 +121,7 @@
 	$c2="ebp";
 	$a="esi";
 	$b="edi";
-	
+
 	$as=0;
 	$ae=0;
 	$bs=0;
@@ -131,9 +136,9 @@
 	 &push("ebx");
 
 	&xor($c0,$c0);
-	 &mov("eax",&DWP(0,$a,"",0));	# load the first word 
+	 &mov("eax",&DWP(0,$a,"",0));	# load the first word
 	&xor($c1,$c1);
-	 &mov("edx",&DWP(0,$b,"",0));	# load the first second 
+	 &mov("edx",&DWP(0,$b,"",0));	# load the first second
 
 	for ($i=0; $i<$tot; $i++)
 		{
@@ -141,7 +146,7 @@
 		$bi=$bs;
 		$end=$be+1;
 
-		&comment("################## Calculate word $i"); 
+		&comment("################## Calculate word $i");
 
 		for ($j=$bs; $j<$end; $j++)
 			{
diff --git a/src/crypto/bn/asm/rsaz-avx2.pl b/src/crypto/bn/asm/rsaz-avx2.pl
old mode 100644
new mode 100755
index bbceccb..60c4ca2
--- a/src/crypto/bn/asm/rsaz-avx2.pl
+++ b/src/crypto/bn/asm/rsaz-avx2.pl
@@ -84,10 +84,10 @@
 # output, so this isn't useful anyway.
 #
 # TODO(davidben): Enable these after testing. $avx goes up to 2 and $addx to 1.
-$avx = 0;
-$addx = 0;
+$avx = 2;
+$addx = 1;
 
-open OUT,"| \"$^X\" $xlate $flavour $output";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
 *STDOUT = *OUT;
 
 if ($avx>1) {{{
@@ -145,13 +145,21 @@
 .type	rsaz_1024_sqr_avx2,\@function,5
 .align	64
 rsaz_1024_sqr_avx2:		# 702 cycles, 14% faster than rsaz_1024_mul_avx2
+.cfi_startproc
 	lea	(%rsp), %rax
+.cfi_def_cfa_register	%rax
 	push	%rbx
+.cfi_push	%rbx
 	push	%rbp
+.cfi_push	%rbp
 	push	%r12
+.cfi_push	%r12
 	push	%r13
+.cfi_push	%r13
 	push	%r14
+.cfi_push	%r14
 	push	%r15
+.cfi_push	%r15
 	vzeroupper
 ___
 $code.=<<___ if ($win64);
@@ -170,6 +178,7 @@
 ___
 $code.=<<___;
 	mov	%rax,%rbp
+.cfi_def_cfa_register	%rbp
 	mov	%rdx, $np			# reassigned argument
 	sub	\$$FrameSize, %rsp
 	mov	$np, $tmp
@@ -359,7 +368,7 @@
 	vpaddq		$TEMP1, $ACC1, $ACC1
 	vpmuludq	32*7-128($aap), $B2, $ACC2
 	 vpbroadcastq	32*5-128($tpa), $B2
-	vpaddq		32*11-448($tp1), $ACC2, $ACC2	
+	vpaddq		32*11-448($tp1), $ACC2, $ACC2
 
 	vmovdqu		$ACC6, 32*6-192($tp0)
 	vmovdqu		$ACC7, 32*7-192($tp0)
@@ -418,7 +427,7 @@
 	vmovdqu		$ACC7, 32*16-448($tp1)
 	lea		8($tp1), $tp1
 
-	dec	$i        
+	dec	$i
 	jnz	.LOOP_SQR_1024
 ___
 $ZERO = $ACC9;
@@ -427,7 +436,7 @@
 $TEMP3 = $Y1;
 $TEMP4 = $Y2;
 $code.=<<___;
-	#we need to fix indexes 32-39 to avoid overflow
+	# we need to fix indices 32-39 to avoid overflow
 	vmovdqu		32*8(%rsp), $ACC8		# 32*8-192($tp0),
 	vmovdqu		32*9(%rsp), $ACC1		# 32*9-192($tp0)
 	vmovdqu		32*10(%rsp), $ACC2		# 32*10-192($tp0)
@@ -763,7 +772,7 @@
 	vpblendd	\$3, $TEMP4, $TEMP5, $TEMP4
 	vpaddq		$TEMP3, $ACC7, $ACC7
 	vpaddq		$TEMP4, $ACC8, $ACC8
-     
+
 	vpsrlq		\$29, $ACC4, $TEMP1
 	vpand		$AND_MASK, $ACC4, $ACC4
 	vpsrlq		\$29, $ACC5, $TEMP2
@@ -802,8 +811,10 @@
 
 	vzeroall
 	mov	%rbp, %rax
+.cfi_def_cfa_register	%rax
 ___
 $code.=<<___ if ($win64);
+.Lsqr_1024_in_tail:
 	movaps	-0xd8(%rax),%xmm6
 	movaps	-0xc8(%rax),%xmm7
 	movaps	-0xb8(%rax),%xmm8
@@ -817,14 +828,22 @@
 ___
 $code.=<<___;
 	mov	-48(%rax),%r15
+.cfi_restore	%r15
 	mov	-40(%rax),%r14
+.cfi_restore	%r14
 	mov	-32(%rax),%r13
+.cfi_restore	%r13
 	mov	-24(%rax),%r12
+.cfi_restore	%r12
 	mov	-16(%rax),%rbp
+.cfi_restore	%rbp
 	mov	-8(%rax),%rbx
+.cfi_restore	%rbx
 	lea	(%rax),%rsp		# restore %rsp
+.cfi_def_cfa_register	%rsp
 .Lsqr_1024_epilogue:
 	ret
+.cfi_endproc
 .size	rsaz_1024_sqr_avx2,.-rsaz_1024_sqr_avx2
 ___
 }
@@ -877,13 +896,21 @@
 .type	rsaz_1024_mul_avx2,\@function,5
 .align	64
 rsaz_1024_mul_avx2:
+.cfi_startproc
 	lea	(%rsp), %rax
+.cfi_def_cfa_register	%rax
 	push	%rbx
+.cfi_push	%rbx
 	push	%rbp
+.cfi_push	%rbp
 	push	%r12
+.cfi_push	%r12
 	push	%r13
+.cfi_push	%r13
 	push	%r14
+.cfi_push	%r14
 	push	%r15
+.cfi_push	%r15
 ___
 $code.=<<___ if ($win64);
 	vzeroupper
@@ -902,6 +929,7 @@
 ___
 $code.=<<___;
 	mov	%rax,%rbp
+.cfi_def_cfa_register	%rbp
 	vzeroall
 	mov	%rdx, $bp	# reassigned argument
 	sub	\$64,%rsp
@@ -1428,15 +1456,17 @@
 	vpaddq		$TEMP4, $ACC8, $ACC8
 
 	vmovdqu		$ACC4, 128-128($rp)
-	vmovdqu		$ACC5, 160-128($rp)    
+	vmovdqu		$ACC5, 160-128($rp)
 	vmovdqu		$ACC6, 192-128($rp)
 	vmovdqu		$ACC7, 224-128($rp)
 	vmovdqu		$ACC8, 256-128($rp)
 	vzeroupper
 
 	mov	%rbp, %rax
+.cfi_def_cfa_register	%rax
 ___
 $code.=<<___ if ($win64);
+.Lmul_1024_in_tail:
 	movaps	-0xd8(%rax),%xmm6
 	movaps	-0xc8(%rax),%xmm7
 	movaps	-0xb8(%rax),%xmm8
@@ -1450,14 +1480,22 @@
 ___
 $code.=<<___;
 	mov	-48(%rax),%r15
+.cfi_restore	%r15
 	mov	-40(%rax),%r14
+.cfi_restore	%r14
 	mov	-32(%rax),%r13
+.cfi_restore	%r13
 	mov	-24(%rax),%r12
+.cfi_restore	%r12
 	mov	-16(%rax),%rbp
+.cfi_restore	%rbp
 	mov	-8(%rax),%rbx
+.cfi_restore	%rbx
 	lea	(%rax),%rsp		# restore %rsp
+.cfi_def_cfa_register	%rsp
 .Lmul_1024_epilogue:
 	ret
+.cfi_endproc
 .size	rsaz_1024_mul_avx2,.-rsaz_1024_mul_avx2
 ___
 }
@@ -1576,68 +1614,130 @@
 .type	rsaz_1024_gather5_avx2,\@abi-omnipotent
 .align	32
 rsaz_1024_gather5_avx2:
+.cfi_startproc
+	vzeroupper
+	mov	%rsp,%r11
+.cfi_def_cfa_register	%r11
 ___
 $code.=<<___ if ($win64);
 	lea	-0x88(%rsp),%rax
-	vzeroupper
 .LSEH_begin_rsaz_1024_gather5:
 	# I can't trust assembler to use specific encoding:-(
-	.byte	0x48,0x8d,0x60,0xe0		#lea	-0x20(%rax),%rsp
-	.byte	0xc5,0xf8,0x29,0x70,0xe0	#vmovaps %xmm6,-0x20(%rax)
-	.byte	0xc5,0xf8,0x29,0x78,0xf0	#vmovaps %xmm7,-0x10(%rax)
-	.byte	0xc5,0x78,0x29,0x40,0x00	#vmovaps %xmm8,0(%rax)
-	.byte	0xc5,0x78,0x29,0x48,0x10	#vmovaps %xmm9,0x10(%rax)
-	.byte	0xc5,0x78,0x29,0x50,0x20	#vmovaps %xmm10,0x20(%rax)
-	.byte	0xc5,0x78,0x29,0x58,0x30	#vmovaps %xmm11,0x30(%rax)
-	.byte	0xc5,0x78,0x29,0x60,0x40	#vmovaps %xmm12,0x40(%rax)
-	.byte	0xc5,0x78,0x29,0x68,0x50	#vmovaps %xmm13,0x50(%rax)
-	.byte	0xc5,0x78,0x29,0x70,0x60	#vmovaps %xmm14,0x60(%rax)
-	.byte	0xc5,0x78,0x29,0x78,0x70	#vmovaps %xmm15,0x70(%rax)
+	.byte	0x48,0x8d,0x60,0xe0		# lea	-0x20(%rax),%rsp
+	.byte	0xc5,0xf8,0x29,0x70,0xe0	# vmovaps %xmm6,-0x20(%rax)
+	.byte	0xc5,0xf8,0x29,0x78,0xf0	# vmovaps %xmm7,-0x10(%rax)
+	.byte	0xc5,0x78,0x29,0x40,0x00	# vmovaps %xmm8,0(%rax)
+	.byte	0xc5,0x78,0x29,0x48,0x10	# vmovaps %xmm9,0x10(%rax)
+	.byte	0xc5,0x78,0x29,0x50,0x20	# vmovaps %xmm10,0x20(%rax)
+	.byte	0xc5,0x78,0x29,0x58,0x30	# vmovaps %xmm11,0x30(%rax)
+	.byte	0xc5,0x78,0x29,0x60,0x40	# vmovaps %xmm12,0x40(%rax)
+	.byte	0xc5,0x78,0x29,0x68,0x50	# vmovaps %xmm13,0x50(%rax)
+	.byte	0xc5,0x78,0x29,0x70,0x60	# vmovaps %xmm14,0x60(%rax)
+	.byte	0xc5,0x78,0x29,0x78,0x70	# vmovaps %xmm15,0x70(%rax)
 ___
 $code.=<<___;
-	lea	.Lgather_table(%rip),%r11
-	mov	$power,%eax
-	and	\$3,$power
-	shr	\$2,%eax			# cache line number
-	shl	\$4,$power			# offset within cache line
+	lea	-0x100(%rsp),%rsp
+	and	\$-32, %rsp
+	lea	.Linc(%rip), %r10
+	lea	-128(%rsp),%rax			# control u-op density
 
-	vmovdqu		-32(%r11),%ymm7		# .Lgather_permd
-	vpbroadcastb	8(%r11,%rax), %xmm8
-	vpbroadcastb	7(%r11,%rax), %xmm9
-	vpbroadcastb	6(%r11,%rax), %xmm10
-	vpbroadcastb	5(%r11,%rax), %xmm11
-	vpbroadcastb	4(%r11,%rax), %xmm12
-	vpbroadcastb	3(%r11,%rax), %xmm13
-	vpbroadcastb	2(%r11,%rax), %xmm14
-	vpbroadcastb	1(%r11,%rax), %xmm15
+	vmovd		$power, %xmm4
+	vmovdqa		(%r10),%ymm0
+	vmovdqa		32(%r10),%ymm1
+	vmovdqa		64(%r10),%ymm5
+	vpbroadcastd	%xmm4,%ymm4
 
-	lea	64($inp,$power),$inp
-	mov	\$64,%r11			# size optimization
-	mov	\$9,%eax
-	jmp	.Loop_gather_1024
+	vpaddd		%ymm5, %ymm0, %ymm2
+	vpcmpeqd	%ymm4, %ymm0, %ymm0
+	vpaddd		%ymm5, %ymm1, %ymm3
+	vpcmpeqd	%ymm4, %ymm1, %ymm1
+	vmovdqa		%ymm0, 32*0+128(%rax)
+	vpaddd		%ymm5, %ymm2, %ymm0
+	vpcmpeqd	%ymm4, %ymm2, %ymm2
+	vmovdqa		%ymm1, 32*1+128(%rax)
+	vpaddd		%ymm5, %ymm3, %ymm1
+	vpcmpeqd	%ymm4, %ymm3, %ymm3
+	vmovdqa		%ymm2, 32*2+128(%rax)
+	vpaddd		%ymm5, %ymm0, %ymm2
+	vpcmpeqd	%ymm4, %ymm0, %ymm0
+	vmovdqa		%ymm3, 32*3+128(%rax)
+	vpaddd		%ymm5, %ymm1, %ymm3
+	vpcmpeqd	%ymm4, %ymm1, %ymm1
+	vmovdqa		%ymm0, 32*4+128(%rax)
+	vpaddd		%ymm5, %ymm2, %ymm8
+	vpcmpeqd	%ymm4, %ymm2, %ymm2
+	vmovdqa		%ymm1, 32*5+128(%rax)
+	vpaddd		%ymm5, %ymm3, %ymm9
+	vpcmpeqd	%ymm4, %ymm3, %ymm3
+	vmovdqa		%ymm2, 32*6+128(%rax)
+	vpaddd		%ymm5, %ymm8, %ymm10
+	vpcmpeqd	%ymm4, %ymm8, %ymm8
+	vmovdqa		%ymm3, 32*7+128(%rax)
+	vpaddd		%ymm5, %ymm9, %ymm11
+	vpcmpeqd	%ymm4, %ymm9, %ymm9
+	vpaddd		%ymm5, %ymm10, %ymm12
+	vpcmpeqd	%ymm4, %ymm10, %ymm10
+	vpaddd		%ymm5, %ymm11, %ymm13
+	vpcmpeqd	%ymm4, %ymm11, %ymm11
+	vpaddd		%ymm5, %ymm12, %ymm14
+	vpcmpeqd	%ymm4, %ymm12, %ymm12
+	vpaddd		%ymm5, %ymm13, %ymm15
+	vpcmpeqd	%ymm4, %ymm13, %ymm13
+	vpcmpeqd	%ymm4, %ymm14, %ymm14
+	vpcmpeqd	%ymm4, %ymm15, %ymm15
 
-.align	32
+	vmovdqa	-32(%r10),%ymm7			# .Lgather_permd
+	lea	128($inp), $inp
+	mov	\$9,$power
+
 .Loop_gather_1024:
-	vpand		-64($inp),		%xmm8,%xmm0
-	vpand		($inp),			%xmm9,%xmm1
-	vpand		64($inp),		%xmm10,%xmm2
-	vpand		($inp,%r11,2),		%xmm11,%xmm3
-	 vpor					%xmm0,%xmm1,%xmm1
-	vpand		64($inp,%r11,2),	%xmm12,%xmm4
-	 vpor					%xmm2,%xmm3,%xmm3
-	vpand		($inp,%r11,4),		%xmm13,%xmm5
-	 vpor					%xmm1,%xmm3,%xmm3
-	vpand		64($inp,%r11,4),	%xmm14,%xmm6
-	 vpor					%xmm4,%xmm5,%xmm5
-	vpand		-128($inp,%r11,8),	%xmm15,%xmm2
-	lea		($inp,%r11,8),$inp
-	 vpor					%xmm3,%xmm5,%xmm5
-	 vpor					%xmm2,%xmm6,%xmm6
-	 vpor					%xmm5,%xmm6,%xmm6
-	vpermd		%ymm6,%ymm7,%ymm6
-	vmovdqu		%ymm6,($out)
+	vmovdqa		32*0-128($inp),	%ymm0
+	vmovdqa		32*1-128($inp),	%ymm1
+	vmovdqa		32*2-128($inp),	%ymm2
+	vmovdqa		32*3-128($inp),	%ymm3
+	vpand		32*0+128(%rax),	%ymm0,	%ymm0
+	vpand		32*1+128(%rax),	%ymm1,	%ymm1
+	vpand		32*2+128(%rax),	%ymm2,	%ymm2
+	vpor		%ymm0, %ymm1, %ymm4
+	vpand		32*3+128(%rax),	%ymm3,	%ymm3
+	vmovdqa		32*4-128($inp),	%ymm0
+	vmovdqa		32*5-128($inp),	%ymm1
+	vpor		%ymm2, %ymm3, %ymm5
+	vmovdqa		32*6-128($inp),	%ymm2
+	vmovdqa		32*7-128($inp),	%ymm3
+	vpand		32*4+128(%rax),	%ymm0,	%ymm0
+	vpand		32*5+128(%rax),	%ymm1,	%ymm1
+	vpand		32*6+128(%rax),	%ymm2,	%ymm2
+	vpor		%ymm0, %ymm4, %ymm4
+	vpand		32*7+128(%rax),	%ymm3,	%ymm3
+	vpand		32*8-128($inp),	%ymm8,	%ymm0
+	vpor		%ymm1, %ymm5, %ymm5
+	vpand		32*9-128($inp),	%ymm9,	%ymm1
+	vpor		%ymm2, %ymm4, %ymm4
+	vpand		32*10-128($inp),%ymm10,	%ymm2
+	vpor		%ymm3, %ymm5, %ymm5
+	vpand		32*11-128($inp),%ymm11,	%ymm3
+	vpor		%ymm0, %ymm4, %ymm4
+	vpand		32*12-128($inp),%ymm12,	%ymm0
+	vpor		%ymm1, %ymm5, %ymm5
+	vpand		32*13-128($inp),%ymm13,	%ymm1
+	vpor		%ymm2, %ymm4, %ymm4
+	vpand		32*14-128($inp),%ymm14,	%ymm2
+	vpor		%ymm3, %ymm5, %ymm5
+	vpand		32*15-128($inp),%ymm15,	%ymm3
+	lea		32*16($inp), $inp
+	vpor		%ymm0, %ymm4, %ymm4
+	vpor		%ymm1, %ymm5, %ymm5
+	vpor		%ymm2, %ymm4, %ymm4
+	vpor		%ymm3, %ymm5, %ymm5
+
+	vpor		%ymm5, %ymm4, %ymm4
+	vextracti128	\$1, %ymm4, %xmm5	# upper half is cleared
+	vpor		%xmm4, %xmm5, %xmm5
+	vpermd		%ymm5,%ymm7,%ymm5
+	vmovdqu		%ymm5,($out)
 	lea		32($out),$out
-	dec	%eax
+	dec	$power
 	jnz	.Loop_gather_1024
 
 	vpxor	%ymm0,%ymm0,%ymm0
@@ -1645,21 +1745,23 @@
 	vzeroupper
 ___
 $code.=<<___ if ($win64);
-	movaps	(%rsp),%xmm6
-	movaps	0x10(%rsp),%xmm7
-	movaps	0x20(%rsp),%xmm8
-	movaps	0x30(%rsp),%xmm9
-	movaps	0x40(%rsp),%xmm10
-	movaps	0x50(%rsp),%xmm11
-	movaps	0x60(%rsp),%xmm12
-	movaps	0x70(%rsp),%xmm13
-	movaps	0x80(%rsp),%xmm14
-	movaps	0x90(%rsp),%xmm15
-	lea	0xa8(%rsp),%rsp
-.LSEH_end_rsaz_1024_gather5:
+	movaps	-0xa8(%r11),%xmm6
+	movaps	-0x98(%r11),%xmm7
+	movaps	-0x88(%r11),%xmm8
+	movaps	-0x78(%r11),%xmm9
+	movaps	-0x68(%r11),%xmm10
+	movaps	-0x58(%r11),%xmm11
+	movaps	-0x48(%r11),%xmm12
+	movaps	-0x38(%r11),%xmm13
+	movaps	-0x28(%r11),%xmm14
+	movaps	-0x18(%r11),%xmm15
 ___
 $code.=<<___;
+	lea	(%r11),%rsp
+.cfi_def_cfa_register	%rsp
 	ret
+.cfi_endproc
+.LSEH_end_rsaz_1024_gather5:
 .size	rsaz_1024_gather5_avx2,.-rsaz_1024_gather5_avx2
 ___
 }
@@ -1692,8 +1794,10 @@
 	.long	0,2,4,6,7,7,7,7
 .Lgather_permd:
 	.long	0,7,1,7,2,7,3,7
-.Lgather_table:
-	.byte	0,0,0,0,0,0,0,0, 0xff,0,0,0,0,0,0,0
+.Linc:
+	.long	0,0,0,0, 1,1,1,1
+	.long	2,2,2,2, 3,3,3,3
+	.long	4,4,4,4, 4,4,4,4
 .align	64
 ___
 
@@ -1730,14 +1834,17 @@
 	cmp	%r10,%rbx		# context->Rip<prologue label
 	jb	.Lcommon_seh_tail
 
-	mov	152($context),%rax	# pull context->Rsp
-
 	mov	4(%r11),%r10d		# HandlerData[1]
 	lea	(%rsi,%r10),%r10	# epilogue label
 	cmp	%r10,%rbx		# context->Rip>=epilogue label
 	jae	.Lcommon_seh_tail
 
-	mov	160($context),%rax	# pull context->Rbp
+	mov	160($context),%rbp	# pull context->Rbp
+
+	mov	8(%r11),%r10d		# HandlerData[2]
+	lea	(%rsi,%r10),%r10	# "in tail" label
+	cmp	%r10,%rbx		# context->Rip>="in tail" label
+	cmovc	%rbp,%rax
 
 	mov	-48(%rax),%r15
 	mov	-40(%rax),%r14
@@ -1815,24 +1922,27 @@
 .LSEH_info_rsaz_1024_sqr_avx2:
 	.byte	9,0,0,0
 	.rva	rsaz_se_handler
-	.rva	.Lsqr_1024_body,.Lsqr_1024_epilogue
+	.rva	.Lsqr_1024_body,.Lsqr_1024_epilogue,.Lsqr_1024_in_tail
+	.long	0
 .LSEH_info_rsaz_1024_mul_avx2:
 	.byte	9,0,0,0
 	.rva	rsaz_se_handler
-	.rva	.Lmul_1024_body,.Lmul_1024_epilogue
+	.rva	.Lmul_1024_body,.Lmul_1024_epilogue,.Lmul_1024_in_tail
+	.long	0
 .LSEH_info_rsaz_1024_gather5:
-	.byte	0x01,0x33,0x16,0x00
-	.byte	0x36,0xf8,0x09,0x00	#vmovaps 0x90(rsp),xmm15
-	.byte	0x31,0xe8,0x08,0x00	#vmovaps 0x80(rsp),xmm14
-	.byte	0x2c,0xd8,0x07,0x00	#vmovaps 0x70(rsp),xmm13
-	.byte	0x27,0xc8,0x06,0x00	#vmovaps 0x60(rsp),xmm12
-	.byte	0x22,0xb8,0x05,0x00	#vmovaps 0x50(rsp),xmm11
-	.byte	0x1d,0xa8,0x04,0x00	#vmovaps 0x40(rsp),xmm10
-	.byte	0x18,0x98,0x03,0x00	#vmovaps 0x30(rsp),xmm9
-	.byte	0x13,0x88,0x02,0x00	#vmovaps 0x20(rsp),xmm8
-	.byte	0x0e,0x78,0x01,0x00	#vmovaps 0x10(rsp),xmm7
-	.byte	0x09,0x68,0x00,0x00	#vmovaps 0x00(rsp),xmm6
-	.byte	0x04,0x01,0x15,0x00	#sub	rsp,0xa8
+	.byte	0x01,0x36,0x17,0x0b
+	.byte	0x36,0xf8,0x09,0x00	# vmovaps 0x90(rsp),xmm15
+	.byte	0x31,0xe8,0x08,0x00	# vmovaps 0x80(rsp),xmm14
+	.byte	0x2c,0xd8,0x07,0x00	# vmovaps 0x70(rsp),xmm13
+	.byte	0x27,0xc8,0x06,0x00	# vmovaps 0x60(rsp),xmm12
+	.byte	0x22,0xb8,0x05,0x00	# vmovaps 0x50(rsp),xmm11
+	.byte	0x1d,0xa8,0x04,0x00	# vmovaps 0x40(rsp),xmm10
+	.byte	0x18,0x98,0x03,0x00	# vmovaps 0x30(rsp),xmm9
+	.byte	0x13,0x88,0x02,0x00	# vmovaps 0x20(rsp),xmm8
+	.byte	0x0e,0x78,0x01,0x00	# vmovaps 0x10(rsp),xmm7
+	.byte	0x09,0x68,0x00,0x00	# vmovaps 0x00(rsp),xmm6
+	.byte	0x04,0x01,0x15,0x00	# sub	  rsp,0xa8
+	.byte	0x00,0xb3,0x00,0x00	# set_frame r11
 ___
 }
 
diff --git a/src/crypto/bn/asm/rsaz-x86_64.pl b/src/crypto/bn/asm/rsaz-x86_64.pl
deleted file mode 100644
index 4113d53..0000000
--- a/src/crypto/bn/asm/rsaz-x86_64.pl
+++ /dev/null
@@ -1,2131 +0,0 @@
-#!/usr/bin/env perl
-
-##############################################################################
-#                                                                            #
-#  Copyright (c) 2012, Intel Corporation                                     #
-#                                                                            #
-#  All rights reserved.                                                      #
-#                                                                            #
-#  Redistribution and use in source and binary forms, with or without        #
-#  modification, are permitted provided that the following conditions are    #
-#  met:                                                                      #
-#                                                                            #
-#  *  Redistributions of source code must retain the above copyright         #
-#     notice, this list of conditions and the following disclaimer.          #
-#                                                                            #
-#  *  Redistributions in binary form must reproduce the above copyright      #
-#     notice, this list of conditions and the following disclaimer in the    #
-#     documentation and/or other materials provided with the                 #
-#     distribution.                                                          #
-#                                                                            #
-#  *  Neither the name of the Intel Corporation nor the names of its         #
-#     contributors may be used to endorse or promote products derived from   #
-#     this software without specific prior written permission.               #
-#                                                                            #
-#                                                                            #
-#  THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION ""AS IS"" AND ANY          #
-#  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE         #
-#  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR        #
-#  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR            #
-#  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,     #
-#  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,       #
-#  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR        #
-#  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    #
-#  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING      #
-#  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS        #
-#  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.              #
-#                                                                            #
-##############################################################################
-# Developers and authors:                                                    #
-# Shay Gueron (1, 2), and Vlad Krasnov (1)                                   #
-# (1) Intel Architecture Group, Microprocessor and Chipset Development,      #
-#     Israel Development Center, Haifa, Israel                               #
-# (2) University of Haifa                                                    #
-##############################################################################
-# Reference:                                                                 #
-# [1] S. Gueron, "Efficient Software Implementations of Modular              #
-#     Exponentiation", http://eprint.iacr.org/2011/239                       #
-# [2] S. Gueron, V. Krasnov. "Speeding up Big-Numbers Squaring".             #
-#     IEEE Proceedings of 9th International Conference on Information        #
-#     Technology: New Generations (ITNG 2012), 821-823 (2012).               #
-# [3] S. Gueron, Efficient Software Implementations of Modular Exponentiation#
-#     Journal of Cryptographic Engineering 2:31-43 (2012).                   #
-# [4] S. Gueron, V. Krasnov: "[PATCH] Efficient and side channel analysis    #
-#     resistant 512-bit and 1024-bit modular exponentiation for optimizing   #
-#     RSA1024 and RSA2048 on x86_64 platforms",                              #
-#     http://rt.openssl.org/Ticket/Display.html?id=2582&user=guest&pass=guest#
-##############################################################################
-
-# While original submission covers 512- and 1024-bit exponentiation,
-# this module is limited to 512-bit version only (and as such
-# accelerates RSA1024 sign). This is because improvement for longer
-# keys is not high enough to justify the effort, highest measured
-# was ~5% on Westmere. [This is relative to OpenSSL 1.0.2, upcoming
-# for the moment of this writing!] Nor does this module implement
-# "monolithic" complete exponentiation jumbo-subroutine, but adheres
-# to more modular mixture of C and assembly. And it's optimized even
-# for processors other than Intel Core family (see table below for
-# improvement coefficients).
-# 						<appro@openssl.org>
-#
-# RSA1024 sign/sec	this/original	|this/rsax(*)	this/fips(*)
-#			----------------+---------------------------
-# Opteron		+13%		|+5%		+20%
-# Bulldozer		-0%		|-1%		+10%
-# P4			+11%		|+7%		+8%
-# Westmere		+5%		|+14%		+17%
-# Sandy Bridge		+2%		|+12%		+29%
-# Ivy Bridge		+1%		|+11%		+35%
-# Haswell(**)		-0%		|+12%		+39%
-# Atom			+13%		|+11%		+4%
-# VIA Nano		+70%		|+9%		+25%
-#
-# (*)	rsax engine and fips numbers are presented for reference
-#	purposes;
-# (**)	MULX was attempted, but found to give only marginal improvement;
-
-$flavour = shift;
-$output  = shift;
-if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
-
-$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
-
-$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
-( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
-( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
-die "can't locate x86_64-xlate.pl";
-
-open OUT,"| \"$^X\" $xlate $flavour $output";
-*STDOUT=*OUT;
-
-# In upstream, this is controlled by shelling out to the compiler to check
-# versions, but BoringSSL is intended to be used with pre-generated perlasm
-# output, so this isn't useful anyway.
-#
-# TODO(davidben): Enable this after testing. $addx goes up to 1.
-$addx = 0;
-
-($out, $inp, $mod) = ("%rdi", "%rsi", "%rbp");	# common internal API
-{
-my ($out,$inp,$mod,$n0,$times) = ("%rdi","%rsi","%rdx","%rcx","%r8d");
-
-$code.=<<___;
-.text
-
-.extern	OPENSSL_ia32cap_P
-
-.globl	rsaz_512_sqr
-.type	rsaz_512_sqr,\@function,5
-.align	32
-rsaz_512_sqr:				# 25-29% faster than rsaz_512_mul
-	push	%rbx
-	push	%rbp
-	push	%r12
-	push	%r13
-	push	%r14
-	push	%r15
-
-	subq	\$128+24, %rsp
-.Lsqr_body:
-	movq	$mod, %rbp		# common argument
-	movq	($inp), %rdx
-	movq	8($inp), %rax
-	movq	$n0, 128(%rsp)
-___
-$code.=<<___ if ($addx);
-	movl	\$0x80100,%r11d
-	andl	OPENSSL_ia32cap_P+8(%rip),%r11d
-	cmpl	\$0x80100,%r11d		# check for MULX and ADO/CX
-	je	.Loop_sqrx
-___
-$code.=<<___;
-	jmp	.Loop_sqr
-
-.align	32
-.Loop_sqr:
-	movl	$times,128+8(%rsp)
-#first iteration
-	movq	%rdx, %rbx
-	mulq	%rdx
-	movq	%rax, %r8
-	movq	16($inp), %rax
-	movq	%rdx, %r9
-
-	mulq	%rbx
-	addq	%rax, %r9
-	movq	24($inp), %rax
-	movq	%rdx, %r10
-	adcq	\$0, %r10
-
-	mulq	%rbx
-	addq	%rax, %r10
-	movq	32($inp), %rax
-	movq	%rdx, %r11
-	adcq	\$0, %r11
-
-	mulq	%rbx
-	addq	%rax, %r11
-	movq	40($inp), %rax
-	movq	%rdx, %r12
-	adcq	\$0, %r12
-
-	mulq	%rbx
-	addq	%rax, %r12
-	movq	48($inp), %rax
-	movq	%rdx, %r13
-	adcq	\$0, %r13
-
-	mulq	%rbx
-	addq	%rax, %r13
-	movq	56($inp), %rax
-	movq	%rdx, %r14
-	adcq	\$0, %r14
-
-	mulq	%rbx
-	addq	%rax, %r14
-	movq	%rbx, %rax
-	movq	%rdx, %r15
-	adcq	\$0, %r15
-
-	addq	%r8, %r8		#shlq	\$1, %r8
-	movq	%r9, %rcx
-	adcq	%r9, %r9		#shld	\$1, %r8, %r9
-
-	mulq	%rax
-	movq	%rax, (%rsp)
-	addq	%rdx, %r8
-	adcq	\$0, %r9
-
-	movq	%r8, 8(%rsp)
-	shrq	\$63, %rcx
-
-#second iteration
-	movq	8($inp), %r8
-	movq	16($inp), %rax
-	mulq	%r8
-	addq	%rax, %r10
-	movq	24($inp), %rax
-	movq	%rdx, %rbx
-	adcq	\$0, %rbx
-
-	mulq	%r8
-	addq	%rax, %r11
-	movq	32($inp), %rax
-	adcq	\$0, %rdx
-	addq	%rbx, %r11
-	movq	%rdx, %rbx
-	adcq	\$0, %rbx
-
-	mulq	%r8
-	addq	%rax, %r12
-	movq	40($inp), %rax
-	adcq	\$0, %rdx
-	addq	%rbx, %r12
-	movq	%rdx, %rbx
-	adcq	\$0, %rbx
-
-	mulq	%r8
-	addq	%rax, %r13
-	movq	48($inp), %rax
-	adcq	\$0, %rdx
-	addq	%rbx, %r13
-	movq	%rdx, %rbx
-	adcq	\$0, %rbx
-
-	mulq	%r8
-	addq	%rax, %r14
-	movq	56($inp), %rax
-	adcq	\$0, %rdx
-	addq	%rbx, %r14
-	movq	%rdx, %rbx
-	adcq	\$0, %rbx
-
-	mulq	%r8
-	addq	%rax, %r15
-	movq	%r8, %rax
-	adcq	\$0, %rdx
-	addq	%rbx, %r15
-	movq	%rdx, %r8
-	movq	%r10, %rdx
-	adcq	\$0, %r8
-
-	add	%rdx, %rdx
-	lea	(%rcx,%r10,2), %r10	#shld	\$1, %rcx, %r10
-	movq	%r11, %rbx
-	adcq	%r11, %r11		#shld	\$1, %r10, %r11
-
-	mulq	%rax
-	addq	%rax, %r9
-	adcq	%rdx, %r10
-	adcq	\$0, %r11
-
-	movq	%r9, 16(%rsp)
-	movq	%r10, 24(%rsp)
-	shrq	\$63, %rbx
-	
-#third iteration
-	movq	16($inp), %r9	
-	movq	24($inp), %rax
-	mulq	%r9
-	addq	%rax, %r12
-	movq	32($inp), %rax
-	movq	%rdx, %rcx
-	adcq	\$0, %rcx
-
-	mulq	%r9
-	addq	%rax, %r13
-	movq	40($inp), %rax
-	adcq	\$0, %rdx
-	addq	%rcx, %r13
-	movq	%rdx, %rcx
-	adcq	\$0, %rcx
-
-	mulq	%r9
-	addq	%rax, %r14
-	movq	48($inp), %rax
-	adcq	\$0, %rdx
-	addq	%rcx, %r14
-	movq	%rdx, %rcx
-	adcq	\$0, %rcx
-
-	mulq	%r9
-	 movq	%r12, %r10
-	 lea	(%rbx,%r12,2), %r12	#shld	\$1, %rbx, %r12
-	addq	%rax, %r15
-	movq	56($inp), %rax
-	adcq	\$0, %rdx
-	addq	%rcx, %r15
-	movq	%rdx, %rcx
-	adcq	\$0, %rcx
-
-	mulq	%r9
-	 shrq	\$63, %r10
-	addq	%rax, %r8
-	movq	%r9, %rax
-	adcq	\$0, %rdx
-	addq	%rcx, %r8
-	movq	%rdx, %r9
-	adcq	\$0, %r9
-
-	movq	%r13, %rcx
-	leaq	(%r10,%r13,2), %r13	#shld	\$1, %r12, %r13
-
-	mulq	%rax
-	addq	%rax, %r11
-	adcq	%rdx, %r12
-	adcq	\$0, %r13
-
-	movq	%r11, 32(%rsp)
-	movq	%r12, 40(%rsp)
-	shrq	\$63, %rcx
-
-#fourth iteration
-	movq	24($inp), %r10
-	movq	32($inp), %rax
-	mulq	%r10
-	addq	%rax, %r14
-	movq	40($inp), %rax
-	movq	%rdx, %rbx
-	adcq	\$0, %rbx
-
-	mulq	%r10
-	addq	%rax, %r15
-	movq	48($inp), %rax
-	adcq	\$0, %rdx
-	addq	%rbx, %r15
-	movq	%rdx, %rbx
-	adcq	\$0, %rbx
-
-	mulq	%r10
-	 movq	%r14, %r12
-	 leaq	(%rcx,%r14,2), %r14	#shld	\$1, %rcx, %r14
-	addq	%rax, %r8
-	movq	56($inp), %rax
-	adcq	\$0, %rdx
-	addq	%rbx, %r8
-	movq	%rdx, %rbx
-	adcq	\$0, %rbx
-
-	mulq	%r10
-	 shrq	\$63, %r12
-	addq	%rax, %r9
-	movq	%r10, %rax
-	adcq	\$0, %rdx
-	addq	%rbx, %r9
-	movq	%rdx, %r10
-	adcq	\$0, %r10
-
-	movq	%r15, %rbx
-	leaq	(%r12,%r15,2),%r15	#shld	\$1, %r14, %r15
-
-	mulq	%rax
-	addq	%rax, %r13
-	adcq	%rdx, %r14
-	adcq	\$0, %r15
-
-	movq	%r13, 48(%rsp)
-	movq	%r14, 56(%rsp)
-	shrq	\$63, %rbx
-
-#fifth iteration
-	movq	32($inp), %r11
-	movq	40($inp), %rax
-	mulq	%r11
-	addq	%rax, %r8
-	movq	48($inp), %rax
-	movq	%rdx, %rcx
-	adcq	\$0, %rcx
-
-	mulq	%r11
-	addq	%rax, %r9
-	movq	56($inp), %rax
-	adcq	\$0, %rdx
-	 movq	%r8, %r12
-	 leaq	(%rbx,%r8,2), %r8	#shld	\$1, %rbx, %r8
-	addq	%rcx, %r9
-	movq	%rdx, %rcx
-	adcq	\$0, %rcx
-
-	mulq	%r11
-	 shrq	\$63, %r12
-	addq	%rax, %r10
-	movq	%r11, %rax
-	adcq	\$0, %rdx
-	addq	%rcx, %r10
-	movq	%rdx, %r11
-	adcq	\$0, %r11
-
-	movq	%r9, %rcx
-	leaq	(%r12,%r9,2), %r9	#shld	\$1, %r8, %r9
-
-	mulq	%rax
-	addq	%rax, %r15
-	adcq	%rdx, %r8
-	adcq	\$0, %r9
-
-	movq	%r15, 64(%rsp)
-	movq	%r8, 72(%rsp)
-	shrq	\$63, %rcx
-
-#sixth iteration
-	movq	40($inp), %r12
-	movq	48($inp), %rax
-	mulq	%r12
-	addq	%rax, %r10
-	movq	56($inp), %rax
-	movq	%rdx, %rbx
-	adcq	\$0, %rbx
-
-	mulq	%r12
-	addq	%rax, %r11
-	movq	%r12, %rax
-	 movq	%r10, %r15
-	 leaq	(%rcx,%r10,2), %r10	#shld	\$1, %rcx, %r10
-	adcq	\$0, %rdx
-	 shrq	\$63, %r15
-	addq	%rbx, %r11
-	movq	%rdx, %r12
-	adcq	\$0, %r12
-
-	movq	%r11, %rbx
-	leaq	(%r15,%r11,2), %r11	#shld	\$1, %r10, %r11
-
-	mulq	%rax
-	addq	%rax, %r9
-	adcq	%rdx, %r10
-	adcq	\$0, %r11
-
-	movq	%r9, 80(%rsp)
-	movq	%r10, 88(%rsp)
-
-#seventh iteration
-	movq	48($inp), %r13
-	movq	56($inp), %rax
-	mulq	%r13
-	addq	%rax, %r12
-	movq	%r13, %rax
-	movq	%rdx, %r13
-	adcq	\$0, %r13
-
-	xorq	%r14, %r14
-	shlq	\$1, %rbx
-	adcq	%r12, %r12		#shld	\$1, %rbx, %r12
-	adcq	%r13, %r13		#shld	\$1, %r12, %r13
-	adcq	%r14, %r14		#shld	\$1, %r13, %r14
-
-	mulq	%rax
-	addq	%rax, %r11
-	adcq	%rdx, %r12
-	adcq	\$0, %r13
-
-	movq	%r11, 96(%rsp)
-	movq	%r12, 104(%rsp)
-
-#eighth iteration
-	movq	56($inp), %rax
-	mulq	%rax
-	addq	%rax, %r13
-	adcq	\$0, %rdx
-
-	addq	%rdx, %r14
-
-	movq	%r13, 112(%rsp)
-	movq	%r14, 120(%rsp)
-
-	movq	(%rsp), %r8
-	movq	8(%rsp), %r9
-	movq	16(%rsp), %r10
-	movq	24(%rsp), %r11
-	movq	32(%rsp), %r12
-	movq	40(%rsp), %r13
-	movq	48(%rsp), %r14
-	movq	56(%rsp), %r15
-
-	call	__rsaz_512_reduce
-
-	addq	64(%rsp), %r8
-	adcq	72(%rsp), %r9
-	adcq	80(%rsp), %r10
-	adcq	88(%rsp), %r11
-	adcq	96(%rsp), %r12
-	adcq	104(%rsp), %r13
-	adcq	112(%rsp), %r14
-	adcq	120(%rsp), %r15
-	sbbq	%rcx, %rcx
-
-	call	__rsaz_512_subtract
-
-	movq	%r8, %rdx
-	movq	%r9, %rax
-	movl	128+8(%rsp), $times
-	movq	$out, $inp
-
-	decl	$times
-	jnz	.Loop_sqr
-___
-if ($addx) {
-$code.=<<___;
-	jmp	.Lsqr_tail
-
-.align	32
-.Loop_sqrx:
-	movl	$times,128+8(%rsp)
-	movq	$out, %xmm0		# off-load
-	movq	%rbp, %xmm1		# off-load
-#first iteration	
-	mulx	%rax, %r8, %r9
-
-	mulx	16($inp), %rcx, %r10
-	xor	%rbp, %rbp		# cf=0, of=0
-
-	mulx	24($inp), %rax, %r11
-	adcx	%rcx, %r9
-
-	mulx	32($inp), %rcx, %r12
-	adcx	%rax, %r10
-
-	mulx	40($inp), %rax, %r13
-	adcx	%rcx, %r11
-
-	.byte	0xc4,0x62,0xf3,0xf6,0xb6,0x30,0x00,0x00,0x00	# mulx	48($inp), %rcx, %r14
-	adcx	%rax, %r12
-	adcx	%rcx, %r13
-
-	.byte	0xc4,0x62,0xfb,0xf6,0xbe,0x38,0x00,0x00,0x00	# mulx	56($inp), %rax, %r15
-	adcx	%rax, %r14
-	adcx	%rbp, %r15		# %rbp is 0
-
-	mov	%r9, %rcx
-	shld	\$1, %r8, %r9
-	shl	\$1, %r8
-
-	xor	%ebp, %ebp
-	mulx	%rdx, %rax, %rdx
-	adcx	%rdx, %r8
-	 mov	8($inp), %rdx
-	adcx	%rbp, %r9
-
-	mov	%rax, (%rsp)
-	mov	%r8, 8(%rsp)
-
-#second iteration	
-	mulx	16($inp), %rax, %rbx
-	adox	%rax, %r10
-	adcx	%rbx, %r11
-
-	.byte	0xc4,0x62,0xc3,0xf6,0x86,0x18,0x00,0x00,0x00	# mulx	24($inp), $out, %r8
-	adox	$out, %r11
-	adcx	%r8, %r12
-
-	mulx	32($inp), %rax, %rbx
-	adox	%rax, %r12
-	adcx	%rbx, %r13
-
-	mulx	40($inp), $out, %r8
-	adox	$out, %r13
-	adcx	%r8, %r14
-
-	.byte	0xc4,0xe2,0xfb,0xf6,0x9e,0x30,0x00,0x00,0x00	# mulx	48($inp), %rax, %rbx
-	adox	%rax, %r14
-	adcx	%rbx, %r15
-
-	.byte	0xc4,0x62,0xc3,0xf6,0x86,0x38,0x00,0x00,0x00	# mulx	56($inp), $out, %r8
-	adox	$out, %r15
-	adcx	%rbp, %r8
-	adox	%rbp, %r8
-
-	mov	%r11, %rbx
-	shld	\$1, %r10, %r11
-	shld	\$1, %rcx, %r10
-
-	xor	%ebp,%ebp
-	mulx	%rdx, %rax, %rcx
-	 mov	16($inp), %rdx
-	adcx	%rax, %r9
-	adcx	%rcx, %r10
-	adcx	%rbp, %r11
-
-	mov	%r9, 16(%rsp)
-	.byte	0x4c,0x89,0x94,0x24,0x18,0x00,0x00,0x00		# mov	%r10, 24(%rsp)
-	
-#third iteration	
-	.byte	0xc4,0x62,0xc3,0xf6,0x8e,0x18,0x00,0x00,0x00	# mulx	24($inp), $out, %r9
-	adox	$out, %r12
-	adcx	%r9, %r13
-
-	mulx	32($inp), %rax, %rcx
-	adox	%rax, %r13
-	adcx	%rcx, %r14
-
-	mulx	40($inp), $out, %r9
-	adox	$out, %r14
-	adcx	%r9, %r15
-
-	.byte	0xc4,0xe2,0xfb,0xf6,0x8e,0x30,0x00,0x00,0x00	# mulx	48($inp), %rax, %rcx
-	adox	%rax, %r15
-	adcx	%rcx, %r8
-
-	.byte	0xc4,0x62,0xc3,0xf6,0x8e,0x38,0x00,0x00,0x00	# mulx	56($inp), $out, %r9
-	adox	$out, %r8
-	adcx	%rbp, %r9
-	adox	%rbp, %r9
-
-	mov	%r13, %rcx
-	shld	\$1, %r12, %r13
-	shld	\$1, %rbx, %r12
-
-	xor	%ebp, %ebp
-	mulx	%rdx, %rax, %rdx
-	adcx	%rax, %r11
-	adcx	%rdx, %r12
-	 mov	24($inp), %rdx
-	adcx	%rbp, %r13
-
-	mov	%r11, 32(%rsp)
-	.byte	0x4c,0x89,0xa4,0x24,0x28,0x00,0x00,0x00		# mov	%r12, 40(%rsp)
-	
-#fourth iteration	
-	.byte	0xc4,0xe2,0xfb,0xf6,0x9e,0x20,0x00,0x00,0x00	# mulx	32($inp), %rax, %rbx
-	adox	%rax, %r14
-	adcx	%rbx, %r15
-
-	mulx	40($inp), $out, %r10
-	adox	$out, %r15
-	adcx	%r10, %r8
-
-	mulx	48($inp), %rax, %rbx
-	adox	%rax, %r8
-	adcx	%rbx, %r9
-
-	mulx	56($inp), $out, %r10
-	adox	$out, %r9
-	adcx	%rbp, %r10
-	adox	%rbp, %r10
-
-	.byte	0x66
-	mov	%r15, %rbx
-	shld	\$1, %r14, %r15
-	shld	\$1, %rcx, %r14
-
-	xor	%ebp, %ebp
-	mulx	%rdx, %rax, %rdx
-	adcx	%rax, %r13
-	adcx	%rdx, %r14
-	 mov	32($inp), %rdx
-	adcx	%rbp, %r15
-
-	mov	%r13, 48(%rsp)
-	mov	%r14, 56(%rsp)
-	
-#fifth iteration	
-	.byte	0xc4,0x62,0xc3,0xf6,0x9e,0x28,0x00,0x00,0x00	# mulx	40($inp), $out, %r11
-	adox	$out, %r8
-	adcx	%r11, %r9
-
-	mulx	48($inp), %rax, %rcx
-	adox	%rax, %r9
-	adcx	%rcx, %r10
-
-	mulx	56($inp), $out, %r11
-	adox	$out, %r10
-	adcx	%rbp, %r11
-	adox	%rbp, %r11
-
-	mov	%r9, %rcx
-	shld	\$1, %r8, %r9
-	shld	\$1, %rbx, %r8
-
-	xor	%ebp, %ebp
-	mulx	%rdx, %rax, %rdx
-	adcx	%rax, %r15
-	adcx	%rdx, %r8
-	 mov	40($inp), %rdx
-	adcx	%rbp, %r9
-
-	mov	%r15, 64(%rsp)
-	mov	%r8, 72(%rsp)
-	
-#sixth iteration	
-	.byte	0xc4,0xe2,0xfb,0xf6,0x9e,0x30,0x00,0x00,0x00	# mulx	48($inp), %rax, %rbx
-	adox	%rax, %r10
-	adcx	%rbx, %r11
-
-	.byte	0xc4,0x62,0xc3,0xf6,0xa6,0x38,0x00,0x00,0x00	# mulx	56($inp), $out, %r12
-	adox	$out, %r11
-	adcx	%rbp, %r12
-	adox	%rbp, %r12
-
-	mov	%r11, %rbx
-	shld	\$1, %r10, %r11
-	shld	\$1, %rcx, %r10
-
-	xor	%ebp, %ebp
-	mulx	%rdx, %rax, %rdx
-	adcx	%rax, %r9
-	adcx	%rdx, %r10
-	 mov	48($inp), %rdx
-	adcx	%rbp, %r11
-
-	mov	%r9, 80(%rsp)
-	mov	%r10, 88(%rsp)
-
-#seventh iteration
-	.byte	0xc4,0x62,0xfb,0xf6,0xae,0x38,0x00,0x00,0x00	# mulx	56($inp), %rax, %r13
-	adox	%rax, %r12
-	adox	%rbp, %r13
-
-	xor	%r14, %r14
-	shld	\$1, %r13, %r14
-	shld	\$1, %r12, %r13
-	shld	\$1, %rbx, %r12
-
-	xor	%ebp, %ebp
-	mulx	%rdx, %rax, %rdx
-	adcx	%rax, %r11
-	adcx	%rdx, %r12
-	 mov	56($inp), %rdx
-	adcx	%rbp, %r13
-
-	.byte	0x4c,0x89,0x9c,0x24,0x60,0x00,0x00,0x00		# mov	%r11, 96(%rsp)
-	.byte	0x4c,0x89,0xa4,0x24,0x68,0x00,0x00,0x00		# mov	%r12, 104(%rsp)
-
-#eighth iteration
-	mulx	%rdx, %rax, %rdx
-	adox	%rax, %r13
-	adox	%rbp, %rdx
-
-	.byte	0x66
-	add	%rdx, %r14
-
-	movq	%r13, 112(%rsp)
-	movq	%r14, 120(%rsp)
-	movq	%xmm0, $out
-	movq	%xmm1, %rbp
-
-	movq	128(%rsp), %rdx		# pull $n0
-	movq	(%rsp), %r8
-	movq	8(%rsp), %r9
-	movq	16(%rsp), %r10
-	movq	24(%rsp), %r11
-	movq	32(%rsp), %r12
-	movq	40(%rsp), %r13
-	movq	48(%rsp), %r14
-	movq	56(%rsp), %r15
-
-	call	__rsaz_512_reducex
-
-	addq	64(%rsp), %r8
-	adcq	72(%rsp), %r9
-	adcq	80(%rsp), %r10
-	adcq	88(%rsp), %r11
-	adcq	96(%rsp), %r12
-	adcq	104(%rsp), %r13
-	adcq	112(%rsp), %r14
-	adcq	120(%rsp), %r15
-	sbbq	%rcx, %rcx
-
-	call	__rsaz_512_subtract
-
-	movq	%r8, %rdx
-	movq	%r9, %rax
-	movl	128+8(%rsp), $times
-	movq	$out, $inp
-
-	decl	$times
-	jnz	.Loop_sqrx
-
-.Lsqr_tail:
-___
-}
-$code.=<<___;
-
-	leaq	128+24+48(%rsp), %rax
-	movq	-48(%rax), %r15
-	movq	-40(%rax), %r14
-	movq	-32(%rax), %r13
-	movq	-24(%rax), %r12
-	movq	-16(%rax), %rbp
-	movq	-8(%rax), %rbx
-	leaq	(%rax), %rsp
-.Lsqr_epilogue:
-	ret
-.size	rsaz_512_sqr,.-rsaz_512_sqr
-___
-}
-{
-my ($out,$ap,$bp,$mod,$n0) = ("%rdi","%rsi","%rdx","%rcx","%r8");
-$code.=<<___;
-.globl	rsaz_512_mul
-.type	rsaz_512_mul,\@function,5
-.align	32
-rsaz_512_mul:
-	push	%rbx
-	push	%rbp
-	push	%r12
-	push	%r13
-	push	%r14
-	push	%r15
-
-	subq	\$128+24, %rsp
-.Lmul_body:
-	movq	$out, %xmm0		# off-load arguments
-	movq	$mod, %xmm1
-	movq	$n0, 128(%rsp)
-___
-$code.=<<___ if ($addx);
-	movl	\$0x80100,%r11d
-	andl	OPENSSL_ia32cap_P+8(%rip),%r11d
-	cmpl	\$0x80100,%r11d		# check for MULX and ADO/CX
-	je	.Lmulx
-___
-$code.=<<___;
-	movq	($bp), %rbx		# pass b[0]
-	movq	$bp, %rbp		# pass argument
-	call	__rsaz_512_mul
-
-	movq	%xmm0, $out
-	movq	%xmm1, %rbp
-
-	movq	(%rsp), %r8
-	movq	8(%rsp), %r9
-	movq	16(%rsp), %r10
-	movq	24(%rsp), %r11
-	movq	32(%rsp), %r12
-	movq	40(%rsp), %r13
-	movq	48(%rsp), %r14
-	movq	56(%rsp), %r15
-
-	call	__rsaz_512_reduce
-___
-$code.=<<___ if ($addx);
-	jmp	.Lmul_tail
-
-.align	32
-.Lmulx:
-	movq	$bp, %rbp		# pass argument
-	movq	($bp), %rdx		# pass b[0]
-	call	__rsaz_512_mulx
-
-	movq	%xmm0, $out
-	movq	%xmm1, %rbp
-
-	movq	128(%rsp), %rdx		# pull $n0
-	movq	(%rsp), %r8
-	movq	8(%rsp), %r9
-	movq	16(%rsp), %r10
-	movq	24(%rsp), %r11
-	movq	32(%rsp), %r12
-	movq	40(%rsp), %r13
-	movq	48(%rsp), %r14
-	movq	56(%rsp), %r15
-
-	call	__rsaz_512_reducex
-.Lmul_tail:
-___
-$code.=<<___;
-	addq	64(%rsp), %r8
-	adcq	72(%rsp), %r9
-	adcq	80(%rsp), %r10
-	adcq	88(%rsp), %r11
-	adcq	96(%rsp), %r12
-	adcq	104(%rsp), %r13
-	adcq	112(%rsp), %r14
-	adcq	120(%rsp), %r15
-	sbbq	%rcx, %rcx
-
-	call	__rsaz_512_subtract
-
-	leaq	128+24+48(%rsp), %rax
-	movq	-48(%rax), %r15
-	movq	-40(%rax), %r14
-	movq	-32(%rax), %r13
-	movq	-24(%rax), %r12
-	movq	-16(%rax), %rbp
-	movq	-8(%rax), %rbx
-	leaq	(%rax), %rsp
-.Lmul_epilogue:
-	ret
-.size	rsaz_512_mul,.-rsaz_512_mul
-___
-}
-{
-my ($out,$ap,$bp,$mod,$n0,$pwr) = ("%rdi","%rsi","%rdx","%rcx","%r8","%r9d");
-$code.=<<___;
-.globl	rsaz_512_mul_gather4
-.type	rsaz_512_mul_gather4,\@function,6
-.align	32
-rsaz_512_mul_gather4:
-	push	%rbx
-	push	%rbp
-	push	%r12
-	push	%r13
-	push	%r14
-	push	%r15
-
-	mov	$pwr, $pwr
-	subq	\$128+24, %rsp
-.Lmul_gather4_body:
-___
-$code.=<<___ if ($addx);
-	movl	\$0x80100,%r11d
-	andl	OPENSSL_ia32cap_P+8(%rip),%r11d
-	cmpl	\$0x80100,%r11d		# check for MULX and ADO/CX
-	je	.Lmulx_gather
-___
-$code.=<<___;
-	movl	64($bp,$pwr,4), %eax
-	movq	$out, %xmm0		# off-load arguments
-	movl	($bp,$pwr,4), %ebx
-	movq	$mod, %xmm1
-	movq	$n0, 128(%rsp)
-
-	shlq	\$32, %rax
-	or	%rax, %rbx
-	movq	($ap), %rax
-	 movq	8($ap), %rcx
-	 leaq	128($bp,$pwr,4), %rbp
-	mulq	%rbx			# 0 iteration
-	movq	%rax, (%rsp)
-	movq	%rcx, %rax
-	movq	%rdx, %r8
-
-	mulq	%rbx
-	 movd	(%rbp), %xmm4
-	addq	%rax, %r8
-	movq	16($ap), %rax
-	movq	%rdx, %r9
-	adcq	\$0, %r9
-
-	mulq	%rbx
-	 movd	64(%rbp), %xmm5
-	addq	%rax, %r9
-	movq	24($ap), %rax
-	movq	%rdx, %r10
-	adcq	\$0, %r10
-
-	mulq	%rbx
-	 pslldq	\$4, %xmm5
-	addq	%rax, %r10
-	movq	32($ap), %rax
-	movq	%rdx, %r11
-	adcq	\$0, %r11
-
-	mulq	%rbx
-	 por	%xmm5, %xmm4
-	addq	%rax, %r11
-	movq	40($ap), %rax
-	movq	%rdx, %r12
-	adcq	\$0, %r12
-
-	mulq	%rbx
-	addq	%rax, %r12
-	movq	48($ap), %rax
-	movq	%rdx, %r13
-	adcq	\$0, %r13
-
-	mulq	%rbx
-	 leaq	128(%rbp), %rbp
-	addq	%rax, %r13
-	movq	56($ap), %rax
-	movq	%rdx, %r14
-	adcq	\$0, %r14
-	
-	mulq	%rbx
-	 movq	%xmm4, %rbx
-	addq	%rax, %r14
-	 movq	($ap), %rax
-	movq	%rdx, %r15
-	adcq	\$0, %r15
-
-	leaq	8(%rsp), %rdi
-	movl	\$7, %ecx
-	jmp	.Loop_mul_gather
-
-.align	32
-.Loop_mul_gather:
-	mulq	%rbx
-	addq	%rax, %r8
-	movq	8($ap), %rax
-	movq	%r8, (%rdi)
-	movq	%rdx, %r8
-	adcq	\$0, %r8
-
-	mulq	%rbx
-	 movd	(%rbp), %xmm4
-	addq	%rax, %r9
-	movq	16($ap), %rax
-	adcq	\$0, %rdx
-	addq	%r9, %r8
-	movq	%rdx, %r9
-	adcq	\$0, %r9
-
-	mulq	%rbx
-	 movd	64(%rbp), %xmm5
-	addq	%rax, %r10
-	movq	24($ap), %rax
-	adcq	\$0, %rdx
-	addq	%r10, %r9
-	movq	%rdx, %r10
-	adcq	\$0, %r10
-
-	mulq	%rbx
-	 pslldq	\$4, %xmm5
-	addq	%rax, %r11
-	movq	32($ap), %rax
-	adcq	\$0, %rdx
-	addq	%r11, %r10
-	movq	%rdx, %r11
-	adcq	\$0, %r11
-
-	mulq	%rbx
-	 por	%xmm5, %xmm4
-	addq	%rax, %r12
-	movq	40($ap), %rax
-	adcq	\$0, %rdx
-	addq	%r12, %r11
-	movq	%rdx, %r12
-	adcq	\$0, %r12
-
-	mulq	%rbx
-	addq	%rax, %r13
-	movq	48($ap), %rax
-	adcq	\$0, %rdx
-	addq	%r13, %r12
-	movq	%rdx, %r13
-	adcq	\$0, %r13
-
-	mulq	%rbx
-	addq	%rax, %r14
-	movq	56($ap), %rax
-	adcq	\$0, %rdx
-	addq	%r14, %r13
-	movq	%rdx, %r14
-	adcq	\$0, %r14
-
-	mulq	%rbx
-	 movq	%xmm4, %rbx
-	addq	%rax, %r15
-	 movq	($ap), %rax
-	adcq	\$0, %rdx
-	addq	%r15, %r14
-	movq	%rdx, %r15	
-	adcq	\$0, %r15
-
-	leaq	128(%rbp), %rbp
-	leaq	8(%rdi), %rdi
-
-	decl	%ecx
-	jnz	.Loop_mul_gather
-
-	movq	%r8, (%rdi)
-	movq	%r9, 8(%rdi)
-	movq	%r10, 16(%rdi)
-	movq	%r11, 24(%rdi)
-	movq	%r12, 32(%rdi)
-	movq	%r13, 40(%rdi)
-	movq	%r14, 48(%rdi)
-	movq	%r15, 56(%rdi)
-
-	movq	%xmm0, $out
-	movq	%xmm1, %rbp
-
-	movq	(%rsp), %r8
-	movq	8(%rsp), %r9
-	movq	16(%rsp), %r10
-	movq	24(%rsp), %r11
-	movq	32(%rsp), %r12
-	movq	40(%rsp), %r13
-	movq	48(%rsp), %r14
-	movq	56(%rsp), %r15
-
-	call	__rsaz_512_reduce
-___
-$code.=<<___ if ($addx);
-	jmp	.Lmul_gather_tail
-
-.align	32
-.Lmulx_gather:
-	mov	64($bp,$pwr,4), %eax
-	movq	$out, %xmm0		# off-load arguments
-	lea	128($bp,$pwr,4), %rbp
-	mov	($bp,$pwr,4), %edx
-	movq	$mod, %xmm1
-	mov	$n0, 128(%rsp)
-
-	shl	\$32, %rax
-	or	%rax, %rdx
-	mulx	($ap), %rbx, %r8	# 0 iteration
-	mov	%rbx, (%rsp)
-	xor	%edi, %edi		# cf=0, of=0
-
-	mulx	8($ap), %rax, %r9
-	 movd	(%rbp), %xmm4
-
-	mulx	16($ap), %rbx, %r10
-	 movd	64(%rbp), %xmm5
-	adcx	%rax, %r8
-
-	mulx	24($ap), %rax, %r11
-	 pslldq	\$4, %xmm5
-	adcx	%rbx, %r9
-
-	mulx	32($ap), %rbx, %r12
-	 por	%xmm5, %xmm4
-	adcx	%rax, %r10
-
-	mulx	40($ap), %rax, %r13
-	adcx	%rbx, %r11
-
-	mulx	48($ap), %rbx, %r14
-	 lea	128(%rbp), %rbp
-	adcx	%rax, %r12
-	
-	mulx	56($ap), %rax, %r15
-	 movq	%xmm4, %rdx
-	adcx	%rbx, %r13
-	adcx	%rax, %r14
-	mov	%r8, %rbx
-	adcx	%rdi, %r15		# %rdi is 0
-
-	mov	\$-7, %rcx
-	jmp	.Loop_mulx_gather
-
-.align	32
-.Loop_mulx_gather:
-	mulx	($ap), %rax, %r8
-	adcx	%rax, %rbx
-	adox	%r9, %r8
-
-	mulx	8($ap), %rax, %r9
-	.byte	0x66,0x0f,0x6e,0xa5,0x00,0x00,0x00,0x00		# movd	(%rbp), %xmm4
-	adcx	%rax, %r8
-	adox	%r10, %r9
-
-	mulx	16($ap), %rax, %r10
-	 movd	64(%rbp), %xmm5
-	 lea	128(%rbp), %rbp
-	adcx	%rax, %r9
-	adox	%r11, %r10
-
-	.byte	0xc4,0x62,0xfb,0xf6,0x9e,0x18,0x00,0x00,0x00	# mulx	24($ap), %rax, %r11
-	 pslldq	\$4, %xmm5
-	 por	%xmm5, %xmm4
-	adcx	%rax, %r10
-	adox	%r12, %r11
-
-	mulx	32($ap), %rax, %r12
-	adcx	%rax, %r11
-	adox	%r13, %r12
-
-	mulx	40($ap), %rax, %r13
-	adcx	%rax, %r12
-	adox	%r14, %r13
-
-	.byte	0xc4,0x62,0xfb,0xf6,0xb6,0x30,0x00,0x00,0x00	# mulx	48($ap), %rax, %r14
-	adcx	%rax, %r13
-	adox	%r15, %r14
-
-	mulx	56($ap), %rax, %r15
-	 movq	%xmm4, %rdx
-	 mov	%rbx, 64(%rsp,%rcx,8)
-	adcx	%rax, %r14
-	adox	%rdi, %r15
-	mov	%r8, %rbx
-	adcx	%rdi, %r15		# cf=0
-
-	inc	%rcx			# of=0
-	jnz	.Loop_mulx_gather
-
-	mov	%r8, 64(%rsp)
-	mov	%r9, 64+8(%rsp)
-	mov	%r10, 64+16(%rsp)
-	mov	%r11, 64+24(%rsp)
-	mov	%r12, 64+32(%rsp)
-	mov	%r13, 64+40(%rsp)
-	mov	%r14, 64+48(%rsp)
-	mov	%r15, 64+56(%rsp)
-
-	movq	%xmm0, $out
-	movq	%xmm1, %rbp
-
-	mov	128(%rsp), %rdx		# pull $n0
-	mov	(%rsp), %r8
-	mov	8(%rsp), %r9
-	mov	16(%rsp), %r10
-	mov	24(%rsp), %r11
-	mov	32(%rsp), %r12
-	mov	40(%rsp), %r13
-	mov	48(%rsp), %r14
-	mov	56(%rsp), %r15
-
-	call	__rsaz_512_reducex
-
-.Lmul_gather_tail:
-___
-$code.=<<___;
-	addq	64(%rsp), %r8
-	adcq	72(%rsp), %r9
-	adcq	80(%rsp), %r10
-	adcq	88(%rsp), %r11
-	adcq	96(%rsp), %r12
-	adcq	104(%rsp), %r13
-	adcq	112(%rsp), %r14
-	adcq	120(%rsp), %r15
-	sbbq	%rcx, %rcx
-
-	call	__rsaz_512_subtract
-
-	leaq	128+24+48(%rsp), %rax
-	movq	-48(%rax), %r15
-	movq	-40(%rax), %r14
-	movq	-32(%rax), %r13
-	movq	-24(%rax), %r12
-	movq	-16(%rax), %rbp
-	movq	-8(%rax), %rbx
-	leaq	(%rax), %rsp
-.Lmul_gather4_epilogue:
-	ret
-.size	rsaz_512_mul_gather4,.-rsaz_512_mul_gather4
-___
-}
-{
-my ($out,$ap,$mod,$n0,$tbl,$pwr) = ("%rdi","%rsi","%rdx","%rcx","%r8","%r9d");
-$code.=<<___;
-.globl	rsaz_512_mul_scatter4
-.type	rsaz_512_mul_scatter4,\@function,6
-.align	32
-rsaz_512_mul_scatter4:
-	push	%rbx
-	push	%rbp
-	push	%r12
-	push	%r13
-	push	%r14
-	push	%r15
-
-	mov	$pwr, $pwr
-	subq	\$128+24, %rsp
-.Lmul_scatter4_body:
-	leaq	($tbl,$pwr,4), $tbl
-	movq	$out, %xmm0		# off-load arguments
-	movq	$mod, %xmm1
-	movq	$tbl, %xmm2
-	movq	$n0, 128(%rsp)
-
-	movq	$out, %rbp
-___
-$code.=<<___ if ($addx);
-	movl	\$0x80100,%r11d
-	andl	OPENSSL_ia32cap_P+8(%rip),%r11d
-	cmpl	\$0x80100,%r11d		# check for MULX and ADO/CX
-	je	.Lmulx_scatter
-___
-$code.=<<___;
-	movq	($out),%rbx		# pass b[0]
-	call	__rsaz_512_mul
-
-	movq	%xmm0, $out
-	movq	%xmm1, %rbp
-
-	movq	(%rsp), %r8
-	movq	8(%rsp), %r9
-	movq	16(%rsp), %r10
-	movq	24(%rsp), %r11
-	movq	32(%rsp), %r12
-	movq	40(%rsp), %r13
-	movq	48(%rsp), %r14
-	movq	56(%rsp), %r15
-
-	call	__rsaz_512_reduce
-___
-$code.=<<___ if ($addx);
-	jmp	.Lmul_scatter_tail
-	
-.align	32
-.Lmulx_scatter:
-	movq	($out), %rdx		# pass b[0]
-	call	__rsaz_512_mulx
-
-	movq	%xmm0, $out
-	movq	%xmm1, %rbp
-
-	movq	128(%rsp), %rdx		# pull $n0
-	movq	(%rsp), %r8
-	movq	8(%rsp), %r9
-	movq	16(%rsp), %r10
-	movq	24(%rsp), %r11
-	movq	32(%rsp), %r12
-	movq	40(%rsp), %r13
-	movq	48(%rsp), %r14
-	movq	56(%rsp), %r15
-
-	call	__rsaz_512_reducex
-
-.Lmul_scatter_tail:
-___
-$code.=<<___;
-	addq	64(%rsp), %r8
-	adcq	72(%rsp), %r9
-	adcq	80(%rsp), %r10
-	adcq	88(%rsp), %r11
-	adcq	96(%rsp), %r12
-	adcq	104(%rsp), %r13
-	adcq	112(%rsp), %r14
-	adcq	120(%rsp), %r15
-	movq	%xmm2, $inp
-	sbbq	%rcx, %rcx
-
-	call	__rsaz_512_subtract
-
-	movl	%r8d, 64*0($inp)	# scatter
-	shrq	\$32, %r8
-	movl	%r9d, 64*2($inp)
-	shrq	\$32, %r9
-	movl	%r10d, 64*4($inp)
-	shrq	\$32, %r10
-	movl	%r11d, 64*6($inp)
-	shrq	\$32, %r11
-	movl	%r12d, 64*8($inp)
-	shrq	\$32, %r12
-	movl	%r13d, 64*10($inp)
-	shrq	\$32, %r13
-	movl	%r14d, 64*12($inp)
-	shrq	\$32, %r14
-	movl	%r15d, 64*14($inp)
-	shrq	\$32, %r15
-	movl	%r8d, 64*1($inp)
-	movl	%r9d, 64*3($inp)
-	movl	%r10d, 64*5($inp)
-	movl	%r11d, 64*7($inp)
-	movl	%r12d, 64*9($inp)
-	movl	%r13d, 64*11($inp)
-	movl	%r14d, 64*13($inp)
-	movl	%r15d, 64*15($inp)
-
-	leaq	128+24+48(%rsp), %rax
-	movq	-48(%rax), %r15
-	movq	-40(%rax), %r14
-	movq	-32(%rax), %r13
-	movq	-24(%rax), %r12
-	movq	-16(%rax), %rbp
-	movq	-8(%rax), %rbx
-	leaq	(%rax), %rsp
-.Lmul_scatter4_epilogue:
-	ret
-.size	rsaz_512_mul_scatter4,.-rsaz_512_mul_scatter4
-___
-}
-{
-my ($out,$inp,$mod,$n0) = ("%rdi","%rsi","%rdx","%rcx");
-$code.=<<___;
-.globl	rsaz_512_mul_by_one
-.type	rsaz_512_mul_by_one,\@function,4
-.align	32
-rsaz_512_mul_by_one:
-	push	%rbx
-	push	%rbp
-	push	%r12
-	push	%r13
-	push	%r14
-	push	%r15
-
-	subq	\$128+24, %rsp
-.Lmul_by_one_body:
-___
-$code.=<<___ if ($addx);
-	movl	OPENSSL_ia32cap_P+8(%rip),%eax
-___
-$code.=<<___;
-	movq	$mod, %rbp	# reassign argument
-	movq	$n0, 128(%rsp)
-
-	movq	($inp), %r8
-	pxor	%xmm0, %xmm0
-	movq	8($inp), %r9
-	movq	16($inp), %r10
-	movq	24($inp), %r11
-	movq	32($inp), %r12
-	movq	40($inp), %r13
-	movq	48($inp), %r14
-	movq	56($inp), %r15
-
-	movdqa	%xmm0, (%rsp)
-	movdqa	%xmm0, 16(%rsp)
-	movdqa	%xmm0, 32(%rsp)
-	movdqa	%xmm0, 48(%rsp)
-	movdqa	%xmm0, 64(%rsp)
-	movdqa	%xmm0, 80(%rsp)
-	movdqa	%xmm0, 96(%rsp)
-___
-$code.=<<___ if ($addx);
-	andl	\$0x80100,%eax
-	cmpl	\$0x80100,%eax		# check for MULX and ADO/CX
-	je	.Lby_one_callx
-___
-$code.=<<___;
-	call	__rsaz_512_reduce
-___
-$code.=<<___ if ($addx);
-	jmp	.Lby_one_tail
-.align	32
-.Lby_one_callx:
-	movq	128(%rsp), %rdx		# pull $n0
-	call	__rsaz_512_reducex
-.Lby_one_tail:
-___
-$code.=<<___;
-	movq	%r8, ($out)
-	movq	%r9, 8($out)
-	movq	%r10, 16($out)
-	movq	%r11, 24($out)
-	movq	%r12, 32($out)
-	movq	%r13, 40($out)
-	movq	%r14, 48($out)
-	movq	%r15, 56($out)
-
-	leaq	128+24+48(%rsp), %rax
-	movq	-48(%rax), %r15
-	movq	-40(%rax), %r14
-	movq	-32(%rax), %r13
-	movq	-24(%rax), %r12
-	movq	-16(%rax), %rbp
-	movq	-8(%rax), %rbx
-	leaq	(%rax), %rsp
-.Lmul_by_one_epilogue:
-	ret
-.size	rsaz_512_mul_by_one,.-rsaz_512_mul_by_one
-___
-}
-{	# __rsaz_512_reduce
-	#
-	# input:	%r8-%r15, %rbp - mod, 128(%rsp) - n0
-	# output:	%r8-%r15
-	# clobbers:	everything except %rbp and %rdi
-$code.=<<___;
-.type	__rsaz_512_reduce,\@abi-omnipotent
-.align	32
-__rsaz_512_reduce:
-	movq	%r8, %rbx
-	imulq	128+8(%rsp), %rbx
-	movq	0(%rbp), %rax
-	movl	\$8, %ecx
-	jmp	.Lreduction_loop
-
-.align	32
-.Lreduction_loop:
-	mulq	%rbx
-	movq	8(%rbp), %rax
-	negq	%r8
-	movq	%rdx, %r8
-	adcq	\$0, %r8
-
-	mulq	%rbx
-	addq	%rax, %r9
-	movq	16(%rbp), %rax
-	adcq	\$0, %rdx
-	addq	%r9, %r8
-	movq	%rdx, %r9
-	adcq	\$0, %r9
-
-	mulq	%rbx
-	addq	%rax, %r10
-	movq	24(%rbp), %rax
-	adcq	\$0, %rdx
-	addq	%r10, %r9
-	movq	%rdx, %r10
-	adcq	\$0, %r10
-
-	mulq	%rbx
-	addq	%rax, %r11
-	movq	32(%rbp), %rax
-	adcq	\$0, %rdx
-	addq	%r11, %r10
-	 movq	128+8(%rsp), %rsi
-	#movq	%rdx, %r11
-	#adcq	\$0, %r11
-	adcq	\$0, %rdx
-	movq	%rdx, %r11
-
-	mulq	%rbx
-	addq	%rax, %r12
-	movq	40(%rbp), %rax
-	adcq	\$0, %rdx
-	 imulq	%r8, %rsi
-	addq	%r12, %r11
-	movq	%rdx, %r12
-	adcq	\$0, %r12
-
-	mulq	%rbx
-	addq	%rax, %r13
-	movq	48(%rbp), %rax
-	adcq	\$0, %rdx
-	addq	%r13, %r12
-	movq	%rdx, %r13
-	adcq	\$0, %r13
-
-	mulq	%rbx
-	addq	%rax, %r14
-	movq	56(%rbp), %rax
-	adcq	\$0, %rdx
-	addq	%r14, %r13
-	movq	%rdx, %r14
-	adcq	\$0, %r14
-
-	mulq	%rbx
-	 movq	%rsi, %rbx
-	addq	%rax, %r15
-	 movq	0(%rbp), %rax
-	adcq	\$0, %rdx
-	addq	%r15, %r14
-	movq	%rdx, %r15
-	adcq	\$0, %r15
-
-	decl	%ecx
-	jne	.Lreduction_loop
-
-	ret
-.size	__rsaz_512_reduce,.-__rsaz_512_reduce
-___
-}
-if ($addx) {
-	# __rsaz_512_reducex
-	#
-	# input:	%r8-%r15, %rbp - mod, 128(%rsp) - n0
-	# output:	%r8-%r15
-	# clobbers:	everything except %rbp and %rdi
-$code.=<<___;
-.type	__rsaz_512_reducex,\@abi-omnipotent
-.align	32
-__rsaz_512_reducex:
-	#movq	128+8(%rsp), %rdx		# pull $n0
-	imulq	%r8, %rdx
-	xorq	%rsi, %rsi			# cf=0,of=0
-	movl	\$8, %ecx
-	jmp	.Lreduction_loopx
-
-.align	32
-.Lreduction_loopx:
-	mov	%r8, %rbx
-	mulx	0(%rbp), %rax, %r8
-	adcx	%rbx, %rax
-	adox	%r9, %r8
-
-	mulx	8(%rbp), %rax, %r9
-	adcx	%rax, %r8
-	adox	%r10, %r9
-
-	mulx	16(%rbp), %rbx, %r10
-	adcx	%rbx, %r9
-	adox	%r11, %r10
-
-	mulx	24(%rbp), %rbx, %r11
-	adcx	%rbx, %r10
-	adox	%r12, %r11
-
-	.byte	0xc4,0x62,0xe3,0xf6,0xa5,0x20,0x00,0x00,0x00	# mulx	32(%rbp), %rbx, %r12
-	 mov	%rdx, %rax
-	 mov	%r8, %rdx
-	adcx	%rbx, %r11
-	adox	%r13, %r12
-
-	 mulx	128+8(%rsp), %rbx, %rdx
-	 mov	%rax, %rdx
-
-	mulx	40(%rbp), %rax, %r13
-	adcx	%rax, %r12
-	adox	%r14, %r13
-
-	.byte	0xc4,0x62,0xfb,0xf6,0xb5,0x30,0x00,0x00,0x00	# mulx	48(%rbp), %rax, %r14
-	adcx	%rax, %r13
-	adox	%r15, %r14
-
-	mulx	56(%rbp), %rax, %r15
-	 mov	%rbx, %rdx
-	adcx	%rax, %r14
-	adox	%rsi, %r15			# %rsi is 0
-	adcx	%rsi, %r15			# cf=0
-
-	decl	%ecx				# of=0
-	jne	.Lreduction_loopx
-
-	ret
-.size	__rsaz_512_reducex,.-__rsaz_512_reducex
-___
-}
-{	# __rsaz_512_subtract
-	# input: %r8-%r15, %rdi - $out, %rbp - $mod, %rcx - mask
-	# output:
-	# clobbers: everything but %rdi, %rsi and %rbp
-$code.=<<___;
-.type	__rsaz_512_subtract,\@abi-omnipotent
-.align	32
-__rsaz_512_subtract:
-	movq	%r8, ($out)
-	movq	%r9, 8($out)
-	movq	%r10, 16($out)
-	movq	%r11, 24($out)
-	movq	%r12, 32($out)
-	movq	%r13, 40($out)
-	movq	%r14, 48($out)
-	movq	%r15, 56($out)
-
-	movq	0($mod), %r8
-	movq	8($mod), %r9
-	negq	%r8
-	notq	%r9
-	andq	%rcx, %r8
-	movq	16($mod), %r10
-	andq	%rcx, %r9
-	notq	%r10
-	movq	24($mod), %r11
-	andq	%rcx, %r10
-	notq	%r11
-	movq	32($mod), %r12
-	andq	%rcx, %r11
-	notq	%r12
-	movq	40($mod), %r13
-	andq	%rcx, %r12
-	notq	%r13
-	movq	48($mod), %r14
-	andq	%rcx, %r13
-	notq	%r14
-	movq	56($mod), %r15
-	andq	%rcx, %r14
-	notq	%r15
-	andq	%rcx, %r15
-
-	addq	($out), %r8
-	adcq	8($out), %r9
-	adcq	16($out), %r10
-	adcq	24($out), %r11
-	adcq	32($out), %r12
-	adcq	40($out), %r13
-	adcq	48($out), %r14
-	adcq	56($out), %r15
-
-	movq	%r8, ($out)
-	movq	%r9, 8($out)
-	movq	%r10, 16($out)
-	movq	%r11, 24($out)
-	movq	%r12, 32($out)
-	movq	%r13, 40($out)
-	movq	%r14, 48($out)
-	movq	%r15, 56($out)
-
-	ret
-.size	__rsaz_512_subtract,.-__rsaz_512_subtract
-___
-}
-{	# __rsaz_512_mul
-	#
-	# input: %rsi - ap, %rbp - bp
-	# ouput:
-	# clobbers: everything
-my ($ap,$bp) = ("%rsi","%rbp");
-$code.=<<___;
-.type	__rsaz_512_mul,\@abi-omnipotent
-.align	32
-__rsaz_512_mul:
-	leaq	8(%rsp), %rdi
-
-	movq	($ap), %rax
-	mulq	%rbx
-	movq	%rax, (%rdi)
-	movq	8($ap), %rax
-	movq	%rdx, %r8
-
-	mulq	%rbx
-	addq	%rax, %r8
-	movq	16($ap), %rax
-	movq	%rdx, %r9
-	adcq	\$0, %r9
-
-	mulq	%rbx
-	addq	%rax, %r9
-	movq	24($ap), %rax
-	movq	%rdx, %r10
-	adcq	\$0, %r10
-
-	mulq	%rbx
-	addq	%rax, %r10
-	movq	32($ap), %rax
-	movq	%rdx, %r11
-	adcq	\$0, %r11
-
-	mulq	%rbx
-	addq	%rax, %r11
-	movq	40($ap), %rax
-	movq	%rdx, %r12
-	adcq	\$0, %r12
-
-	mulq	%rbx
-	addq	%rax, %r12
-	movq	48($ap), %rax
-	movq	%rdx, %r13
-	adcq	\$0, %r13
-
-	mulq	%rbx
-	addq	%rax, %r13
-	movq	56($ap), %rax
-	movq	%rdx, %r14
-	adcq	\$0, %r14
-	
-	mulq	%rbx
-	addq	%rax, %r14
-	 movq	($ap), %rax
-	movq	%rdx, %r15
-	adcq	\$0, %r15
-
-	leaq	8($bp), $bp
-	leaq	8(%rdi), %rdi
-
-	movl	\$7, %ecx
-	jmp	.Loop_mul
-
-.align	32
-.Loop_mul:
-	movq	($bp), %rbx
-	mulq	%rbx
-	addq	%rax, %r8
-	movq	8($ap), %rax
-	movq	%r8, (%rdi)
-	movq	%rdx, %r8
-	adcq	\$0, %r8
-
-	mulq	%rbx
-	addq	%rax, %r9
-	movq	16($ap), %rax
-	adcq	\$0, %rdx
-	addq	%r9, %r8
-	movq	%rdx, %r9
-	adcq	\$0, %r9
-
-	mulq	%rbx
-	addq	%rax, %r10
-	movq	24($ap), %rax
-	adcq	\$0, %rdx
-	addq	%r10, %r9
-	movq	%rdx, %r10
-	adcq	\$0, %r10
-
-	mulq	%rbx
-	addq	%rax, %r11
-	movq	32($ap), %rax
-	adcq	\$0, %rdx
-	addq	%r11, %r10
-	movq	%rdx, %r11
-	adcq	\$0, %r11
-
-	mulq	%rbx
-	addq	%rax, %r12
-	movq	40($ap), %rax
-	adcq	\$0, %rdx
-	addq	%r12, %r11
-	movq	%rdx, %r12
-	adcq	\$0, %r12
-
-	mulq	%rbx
-	addq	%rax, %r13
-	movq	48($ap), %rax
-	adcq	\$0, %rdx
-	addq	%r13, %r12
-	movq	%rdx, %r13
-	adcq	\$0, %r13
-
-	mulq	%rbx
-	addq	%rax, %r14
-	movq	56($ap), %rax
-	adcq	\$0, %rdx
-	addq	%r14, %r13
-	movq	%rdx, %r14
-	 leaq	8($bp), $bp
-	adcq	\$0, %r14
-
-	mulq	%rbx
-	addq	%rax, %r15
-	 movq	($ap), %rax
-	adcq	\$0, %rdx
-	addq	%r15, %r14
-	movq	%rdx, %r15	
-	adcq	\$0, %r15
-
-	leaq	8(%rdi), %rdi
-
-	decl	%ecx
-	jnz	.Loop_mul
-
-	movq	%r8, (%rdi)
-	movq	%r9, 8(%rdi)
-	movq	%r10, 16(%rdi)
-	movq	%r11, 24(%rdi)
-	movq	%r12, 32(%rdi)
-	movq	%r13, 40(%rdi)
-	movq	%r14, 48(%rdi)
-	movq	%r15, 56(%rdi)
-
-	ret
-.size	__rsaz_512_mul,.-__rsaz_512_mul
-___
-}
-if ($addx) {
-	# __rsaz_512_mulx
-	#
-	# input: %rsi - ap, %rbp - bp
-	# ouput:
-	# clobbers: everything
-my ($ap,$bp,$zero) = ("%rsi","%rbp","%rdi");
-$code.=<<___;
-.type	__rsaz_512_mulx,\@abi-omnipotent
-.align	32
-__rsaz_512_mulx:
-	mulx	($ap), %rbx, %r8	# initial %rdx preloaded by caller
-	mov	\$-6, %rcx
-
-	mulx	8($ap), %rax, %r9
-	movq	%rbx, 8(%rsp)
-
-	mulx	16($ap), %rbx, %r10
-	adc	%rax, %r8
-
-	mulx	24($ap), %rax, %r11
-	adc	%rbx, %r9
-
-	mulx	32($ap), %rbx, %r12
-	adc	%rax, %r10
-
-	mulx	40($ap), %rax, %r13
-	adc	%rbx, %r11
-
-	mulx	48($ap), %rbx, %r14
-	adc	%rax, %r12
-
-	mulx	56($ap), %rax, %r15
-	 mov	8($bp), %rdx
-	adc	%rbx, %r13
-	adc	%rax, %r14
-	adc	\$0, %r15
-
-	xor	$zero, $zero		# cf=0,of=0
-	jmp	.Loop_mulx
-
-.align	32
-.Loop_mulx:
-	movq	%r8, %rbx
-	mulx	($ap), %rax, %r8
-	adcx	%rax, %rbx
-	adox	%r9, %r8
-
-	mulx	8($ap), %rax, %r9
-	adcx	%rax, %r8
-	adox	%r10, %r9
-
-	mulx	16($ap), %rax, %r10
-	adcx	%rax, %r9
-	adox	%r11, %r10
-
-	mulx	24($ap), %rax, %r11
-	adcx	%rax, %r10
-	adox	%r12, %r11
-
-	.byte	0x3e,0xc4,0x62,0xfb,0xf6,0xa6,0x20,0x00,0x00,0x00	# mulx	32($ap), %rax, %r12
-	adcx	%rax, %r11
-	adox	%r13, %r12
-
-	mulx	40($ap), %rax, %r13
-	adcx	%rax, %r12
-	adox	%r14, %r13
-
-	mulx	48($ap), %rax, %r14
-	adcx	%rax, %r13
-	adox	%r15, %r14
-
-	mulx	56($ap), %rax, %r15
-	 movq	64($bp,%rcx,8), %rdx
-	 movq	%rbx, 8+64-8(%rsp,%rcx,8)
-	adcx	%rax, %r14
-	adox	$zero, %r15
-	adcx	$zero, %r15		# cf=0
-
-	inc	%rcx			# of=0
-	jnz	.Loop_mulx
-
-	movq	%r8, %rbx
-	mulx	($ap), %rax, %r8
-	adcx	%rax, %rbx
-	adox	%r9, %r8
-
-	.byte	0xc4,0x62,0xfb,0xf6,0x8e,0x08,0x00,0x00,0x00	# mulx	8($ap), %rax, %r9
-	adcx	%rax, %r8
-	adox	%r10, %r9
-
-	.byte	0xc4,0x62,0xfb,0xf6,0x96,0x10,0x00,0x00,0x00	# mulx	16($ap), %rax, %r10
-	adcx	%rax, %r9
-	adox	%r11, %r10
-
-	mulx	24($ap), %rax, %r11
-	adcx	%rax, %r10
-	adox	%r12, %r11
-
-	mulx	32($ap), %rax, %r12
-	adcx	%rax, %r11
-	adox	%r13, %r12
-
-	mulx	40($ap), %rax, %r13
-	adcx	%rax, %r12
-	adox	%r14, %r13
-
-	.byte	0xc4,0x62,0xfb,0xf6,0xb6,0x30,0x00,0x00,0x00	# mulx	48($ap), %rax, %r14
-	adcx	%rax, %r13
-	adox	%r15, %r14
-
-	.byte	0xc4,0x62,0xfb,0xf6,0xbe,0x38,0x00,0x00,0x00	# mulx	56($ap), %rax, %r15
-	adcx	%rax, %r14
-	adox	$zero, %r15
-	adcx	$zero, %r15
-
-	mov	%rbx, 8+64-8(%rsp)
-	mov	%r8, 8+64(%rsp)
-	mov	%r9, 8+64+8(%rsp)
-	mov	%r10, 8+64+16(%rsp)
-	mov	%r11, 8+64+24(%rsp)
-	mov	%r12, 8+64+32(%rsp)
-	mov	%r13, 8+64+40(%rsp)
-	mov	%r14, 8+64+48(%rsp)
-	mov	%r15, 8+64+56(%rsp)
-
-	ret
-.size	__rsaz_512_mulx,.-__rsaz_512_mulx
-___
-}
-{
-my ($out,$inp,$power)= $win64 ? ("%rcx","%rdx","%r8d") : ("%rdi","%rsi","%edx");
-$code.=<<___;
-.globl	rsaz_512_scatter4
-.type	rsaz_512_scatter4,\@abi-omnipotent
-.align	16
-rsaz_512_scatter4:
-	leaq	($out,$power,4), $out
-	movl	\$8, %r9d
-	jmp	.Loop_scatter
-.align	16
-.Loop_scatter:
-	movq	($inp), %rax
-	leaq	8($inp), $inp
-	movl	%eax, ($out)
-	shrq	\$32, %rax
-	movl	%eax, 64($out)
-	leaq	128($out), $out
-	decl	%r9d
-	jnz	.Loop_scatter
-	ret
-.size	rsaz_512_scatter4,.-rsaz_512_scatter4
-
-.globl	rsaz_512_gather4
-.type	rsaz_512_gather4,\@abi-omnipotent
-.align	16
-rsaz_512_gather4:
-	leaq	($inp,$power,4), $inp
-	movl	\$8, %r9d
-	jmp	.Loop_gather
-.align	16
-.Loop_gather:
-	movl	($inp), %eax
-	movl	64($inp), %r8d
-	leaq	128($inp), $inp
-	shlq	\$32, %r8
-	or	%r8, %rax
-	movq	%rax, ($out)
-	leaq	8($out), $out
-	decl	%r9d
-	jnz	.Loop_gather
-	ret
-.size	rsaz_512_gather4,.-rsaz_512_gather4
-___
-}
-
-# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
-#		CONTEXT *context,DISPATCHER_CONTEXT *disp)
-if ($win64) {
-$rec="%rcx";
-$frame="%rdx";
-$context="%r8";
-$disp="%r9";
-
-$code.=<<___;
-.extern	__imp_RtlVirtualUnwind
-.type	se_handler,\@abi-omnipotent
-.align	16
-se_handler:
-	push	%rsi
-	push	%rdi
-	push	%rbx
-	push	%rbp
-	push	%r12
-	push	%r13
-	push	%r14
-	push	%r15
-	pushfq
-	sub	\$64,%rsp
-
-	mov	120($context),%rax	# pull context->Rax
-	mov	248($context),%rbx	# pull context->Rip
-
-	mov	8($disp),%rsi		# disp->ImageBase
-	mov	56($disp),%r11		# disp->HandlerData
-
-	mov	0(%r11),%r10d		# HandlerData[0]
-	lea	(%rsi,%r10),%r10	# end of prologue label
-	cmp	%r10,%rbx		# context->Rip<end of prologue label
-	jb	.Lcommon_seh_tail
-
-	mov	152($context),%rax	# pull context->Rsp
-
-	mov	4(%r11),%r10d		# HandlerData[1]
-	lea	(%rsi,%r10),%r10	# epilogue label
-	cmp	%r10,%rbx		# context->Rip>=epilogue label
-	jae	.Lcommon_seh_tail
-
-	lea	128+24+48(%rax),%rax
-
-	mov	-8(%rax),%rbx
-	mov	-16(%rax),%rbp
-	mov	-24(%rax),%r12
-	mov	-32(%rax),%r13
-	mov	-40(%rax),%r14
-	mov	-48(%rax),%r15
-	mov	%rbx,144($context)	# restore context->Rbx
-	mov	%rbp,160($context)	# restore context->Rbp
-	mov	%r12,216($context)	# restore context->R12
-	mov	%r13,224($context)	# restore context->R13
-	mov	%r14,232($context)	# restore context->R14
-	mov	%r15,240($context)	# restore context->R15
-
-.Lcommon_seh_tail:
-	mov	8(%rax),%rdi
-	mov	16(%rax),%rsi
-	mov	%rax,152($context)	# restore context->Rsp
-	mov	%rsi,168($context)	# restore context->Rsi
-	mov	%rdi,176($context)	# restore context->Rdi
-
-	mov	40($disp),%rdi		# disp->ContextRecord
-	mov	$context,%rsi		# context
-	mov	\$154,%ecx		# sizeof(CONTEXT)
-	.long	0xa548f3fc		# cld; rep movsq
-
-	mov	$disp,%rsi
-	xor	%rcx,%rcx		# arg1, UNW_FLAG_NHANDLER
-	mov	8(%rsi),%rdx		# arg2, disp->ImageBase
-	mov	0(%rsi),%r8		# arg3, disp->ControlPc
-	mov	16(%rsi),%r9		# arg4, disp->FunctionEntry
-	mov	40(%rsi),%r10		# disp->ContextRecord
-	lea	56(%rsi),%r11		# &disp->HandlerData
-	lea	24(%rsi),%r12		# &disp->EstablisherFrame
-	mov	%r10,32(%rsp)		# arg5
-	mov	%r11,40(%rsp)		# arg6
-	mov	%r12,48(%rsp)		# arg7
-	mov	%rcx,56(%rsp)		# arg8, (NULL)
-	call	*__imp_RtlVirtualUnwind(%rip)
-
-	mov	\$1,%eax		# ExceptionContinueSearch
-	add	\$64,%rsp
-	popfq
-	pop	%r15
-	pop	%r14
-	pop	%r13
-	pop	%r12
-	pop	%rbp
-	pop	%rbx
-	pop	%rdi
-	pop	%rsi
-	ret
-.size	sqr_handler,.-sqr_handler
-
-.section	.pdata
-.align	4
-	.rva	.LSEH_begin_rsaz_512_sqr
-	.rva	.LSEH_end_rsaz_512_sqr
-	.rva	.LSEH_info_rsaz_512_sqr
-
-	.rva	.LSEH_begin_rsaz_512_mul
-	.rva	.LSEH_end_rsaz_512_mul
-	.rva	.LSEH_info_rsaz_512_mul
-
-	.rva	.LSEH_begin_rsaz_512_mul_gather4
-	.rva	.LSEH_end_rsaz_512_mul_gather4
-	.rva	.LSEH_info_rsaz_512_mul_gather4
-
-	.rva	.LSEH_begin_rsaz_512_mul_scatter4
-	.rva	.LSEH_end_rsaz_512_mul_scatter4
-	.rva	.LSEH_info_rsaz_512_mul_scatter4
-
-	.rva	.LSEH_begin_rsaz_512_mul_by_one
-	.rva	.LSEH_end_rsaz_512_mul_by_one
-	.rva	.LSEH_info_rsaz_512_mul_by_one
-
-.section	.xdata
-.align	8
-.LSEH_info_rsaz_512_sqr:
-	.byte	9,0,0,0
-	.rva	se_handler
-	.rva	.Lsqr_body,.Lsqr_epilogue			# HandlerData[]
-.LSEH_info_rsaz_512_mul:
-	.byte	9,0,0,0
-	.rva	se_handler
-	.rva	.Lmul_body,.Lmul_epilogue			# HandlerData[]
-.LSEH_info_rsaz_512_mul_gather4:
-	.byte	9,0,0,0
-	.rva	se_handler
-	.rva	.Lmul_gather4_body,.Lmul_gather4_epilogue	# HandlerData[]
-.LSEH_info_rsaz_512_mul_scatter4:
-	.byte	9,0,0,0
-	.rva	se_handler
-	.rva	.Lmul_scatter4_body,.Lmul_scatter4_epilogue	# HandlerData[]
-.LSEH_info_rsaz_512_mul_by_one:
-	.byte	9,0,0,0
-	.rva	se_handler
-	.rva	.Lmul_by_one_body,.Lmul_by_one_epilogue		# HandlerData[]
-___
-}
-
-$code =~ s/\`([^\`]*)\`/eval $1/gem;
-print $code;
-close STDOUT;
diff --git a/src/crypto/bn/asm/x86-mont.pl b/src/crypto/bn/asm/x86-mont.pl
old mode 100644
new mode 100755
index 0626b48..57fbf10
--- a/src/crypto/bn/asm/x86-mont.pl
+++ b/src/crypto/bn/asm/x86-mont.pl
@@ -30,6 +30,9 @@
 push(@INC,"${dir}","${dir}../../perlasm");
 require "x86asm.pl";
 
+$output = pop;
+open STDOUT,">$output";
+
 &asm_init($ARGV[0],$0);
 
 $sse2=0;
@@ -63,33 +66,57 @@
 
 	&lea	("esi",&wparam(0));	# put aside pointer to argument block
 	&lea	("edx",&wparam(1));	# load ap
-	&mov	("ebp","esp");		# saved stack pointer!
 	&add	("edi",2);		# extra two words on top of tp
 	&neg	("edi");
-	&lea	("esp",&DWP(-$frame,"esp","edi",4));	# alloca($frame+4*(num+2))
+	&lea	("ebp",&DWP(-$frame,"esp","edi",4));	# future alloca($frame+4*(num+2))
 	&neg	("edi");
 
 	# minimize cache contention by arraning 2K window between stack
 	# pointer and ap argument [np is also position sensitive vector,
 	# but it's assumed to be near ap, as it's allocated at ~same
 	# time].
-	&mov	("eax","esp");
+	&mov	("eax","ebp");
 	&sub	("eax","edx");
 	&and	("eax",2047);
-	&sub	("esp","eax");		# this aligns sp and ap modulo 2048
+	&sub	("ebp","eax");		# this aligns sp and ap modulo 2048
 
-	&xor	("edx","esp");
+	&xor	("edx","ebp");
 	&and	("edx",2048);
 	&xor	("edx",2048);
-	&sub	("esp","edx");		# this splits them apart modulo 4096
+	&sub	("ebp","edx");		# this splits them apart modulo 4096
 
-	&and	("esp",-64);		# align to cache line
+	&and	("ebp",-64);		# align to cache line
+
+	# An OS-agnostic version of __chkstk.
+	#
+	# Some OSes (Windows) insist on stack being "wired" to
+	# physical memory in strictly sequential manner, i.e. if stack
+	# allocation spans two pages, then reference to farmost one can
+	# be punishable by SEGV. But page walking can do good even on
+	# other OSes, because it guarantees that villain thread hits
+	# the guard page before it can make damage to innocent one...
+	&mov	("eax","esp");
+	&sub	("eax","ebp");
+	&and	("eax",-4096);
+	&mov	("edx","esp");		# saved stack pointer!
+	&lea	("esp",&DWP(0,"ebp","eax"));
+	&mov	("eax",&DWP(0,"esp"));
+	&cmp	("esp","ebp");
+	&ja	(&label("page_walk"));
+	&jmp	(&label("page_walk_done"));
+
+&set_label("page_walk",16);
+	&lea	("esp",&DWP(-4096,"esp"));
+	&mov	("eax",&DWP(0,"esp"));
+	&cmp	("esp","ebp");
+	&ja	(&label("page_walk"));
+&set_label("page_walk_done");
 
 	################################# load argument block...
 	&mov	("eax",&DWP(0*4,"esi"));# BN_ULONG *rp
 	&mov	("ebx",&DWP(1*4,"esi"));# const BN_ULONG *ap
 	&mov	("ecx",&DWP(2*4,"esi"));# const BN_ULONG *bp
-	&mov	("edx",&DWP(3*4,"esi"));# const BN_ULONG *np
+	&mov	("ebp",&DWP(3*4,"esi"));# const BN_ULONG *np
 	&mov	("esi",&DWP(4*4,"esi"));# const BN_ULONG *n0
 	#&mov	("edi",&DWP(5*4,"esi"));# int num
 
@@ -97,11 +124,11 @@
 	&mov	($_rp,"eax");		# ... save a copy of argument block
 	&mov	($_ap,"ebx");
 	&mov	($_bp,"ecx");
-	&mov	($_np,"edx");
+	&mov	($_np,"ebp");
 	&mov	($_n0,"esi");
 	&lea	($num,&DWP(-3,"edi"));	# num=num-1 to assist modulo-scheduling
 	#&mov	($_num,$num);		# redundant as $num is not reused
-	&mov	($_sp,"ebp");		# saved stack pointer!
+	&mov	($_sp,"edx");		# saved stack pointer!
 
 if($sse2) {
 $acc0="mm0";	# mmx register bank layout
@@ -267,7 +294,7 @@
 	&xor	("eax","eax");	# signal "not fast enough [yet]"
 	&jmp	(&label("just_leave"));
 	# While the below code provides competitive performance for
-	# all key lengthes on modern Intel cores, it's still more
+	# all key lengths on modern Intel cores, it's still more
 	# than 10% slower for 4096-bit key elsewhere:-( "Competitive"
 	# means compared to the original integer-only assembler.
 	# 512-bit RSA sign is better by ~40%, but that's about all
@@ -570,15 +597,16 @@
 	&jge	(&label("sub"));
 
 	&sbb	("eax",0);			# handle upmost overflow bit
+	&and	($tp,"eax");
+	&not	("eax");
+	&mov	($np,$rp);
+	&and	($np,"eax");
+	&or	($tp,$np);			# tp=carry?tp:rp
 
 &set_label("copy",16);				# copy or in-place refresh
-	&mov	("edx",&DWP(0,$tp,$num,4));
-	&mov	($np,&DWP(0,$rp,$num,4));
-	&xor	("edx",$np);			# conditional select
-	&and	("edx","eax");
-	&xor	("edx",$np);
-	&mov	(&DWP(0,$tp,$num,4),$j)		# zap temporary vector
-	&mov	(&DWP(0,$rp,$num,4),"edx");	# rp[i]=tp[i]
+	&mov	("eax",&DWP(0,$tp,$num,4));
+	&mov	(&DWP(0,$rp,$num,4),"eax");	# rp[i]=tp[i]
+	&mov	(&DWP($frame,"esp",$num,4),$j);	# zap temporary vector
 	&dec	($num);
 	&jge	(&label("copy"));
 
@@ -590,3 +618,5 @@
 &asciz("Montgomery Multiplication for x86, CRYPTOGAMS by <appro\@openssl.org>");
 
 &asm_finish();
+
+close STDOUT;
diff --git a/src/crypto/bn/asm/x86_64-gcc.c b/src/crypto/bn/asm/x86_64-gcc.c
index 0496b95..177d335 100644
--- a/src/crypto/bn/asm/x86_64-gcc.c
+++ b/src/crypto/bn/asm/x86_64-gcc.c
@@ -1,9 +1,3 @@
-#include <openssl/bn.h>
-
-#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && !defined(OPENSSL_WINDOWS)
-
-#include "../internal.h"
-
 /* x86_64 BIGNUM accelerator version 0.1, December 2002.
  *
  * Implemented by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
@@ -56,7 +50,13 @@
  *    machine.
  */
 
- /* TODO(davidben): Get this file working on Windows x64. */
+#include <openssl/bn.h>
+
+/* TODO(davidben): Get this file working on Windows x64. */
+#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && defined(__GNUC__)
+
+#include "../internal.h"
+
 
 #undef mul
 #undef mul_add
@@ -80,7 +80,7 @@
         : "+m"(r), "+d"(high)                                          \
         : "r"(carry), "g"(0)                                           \
         : "cc");                                                       \
-    carry = high;                                                      \
+    (carry) = high;                                                    \
   } while (0)
 
 #define mul(r, a, word, carry)                                         \
@@ -91,7 +91,8 @@
         : "+r"(carry), "+d"(high)                                      \
         : "a"(low), "g"(0)                                             \
         : "cc");                                                       \
-    (r) = carry, carry = high;                                         \
+    (r) = (carry);                                                     \
+    (carry) = high;                                                    \
   } while (0)
 #undef sqr
 #define sqr(r0, r1, a) asm("mulq %2" : "=a"(r0), "=d"(r1) : "a"(a) : "cc");
@@ -186,14 +187,6 @@
   }
 }
 
-BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) {
-  BN_ULONG ret, waste;
-
-  asm("divq	%4" : "=a"(ret), "=d"(waste) : "a"(l), "d"(h), "g"(d) : "cc");
-
-  return ret;
-}
-
 BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
                       int n) {
   BN_ULONG ret;
@@ -220,7 +213,6 @@
   return ret & 1;
 }
 
-#ifndef SIMICS
 BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
                       int n) {
   BN_ULONG ret;
@@ -246,65 +238,6 @@
 
   return ret & 1;
 }
-#else
-/* Simics 1.4<7 has buggy sbbq:-( */
-#define BN_MASK2 0xffffffffffffffffL
-BN_ULONG bn_sub_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) {
-  BN_ULONG t1, t2;
-  int c = 0;
-
-  if (n <= 0) {
-    return (BN_ULONG)0;
-  }
-
-  for (;;) {
-    t1 = a[0];
-    t2 = b[0];
-    r[0] = (t1 - t2 - c) & BN_MASK2;
-    if (t1 != t2) {
-      c = (t1 < t2);
-    }
-    if (--n <= 0) {
-      break;
-    }
-
-    t1 = a[1];
-    t2 = b[1];
-    r[1] = (t1 - t2 - c) & BN_MASK2;
-    if (t1 != t2) {
-      c = (t1 < t2);
-    }
-    if (--n <= 0) {
-      break;
-    }
-
-    t1 = a[2];
-    t2 = b[2];
-    r[2] = (t1 - t2 - c) & BN_MASK2;
-    if (t1 != t2) {
-      c = (t1 < t2);
-    }
-    if (--n <= 0) {
-      break;
-    }
-
-    t1 = a[3];
-    t2 = b[3];
-    r[3] = (t1 - t2 - c) & BN_MASK2;
-    if (t1 != t2) {
-      c = (t1 < t2);
-    }
-    if (--n <= 0) {
-      break;
-    }
-
-    a += 4;
-    b += 4;
-    r += 4;
-  }
-  return c;
-}
-#endif
 
 /* mul_add_c(a,b,c0,c1,c2)  -- c+=a*b for three word number c=(c2,c1,c0) */
 /* mul_add_c2(a,b,c0,c1,c2) -- c+=2*a*b for three word number c=(c2,c1,c0) */
@@ -324,14 +257,14 @@
         : "cc");                             \
   } while (0)
 
-#define sqr_add_c(a, i, c0, c1, c2)          \
-  do {                                       \
-    BN_ULONG t1, t2;                         \
-    asm("mulq %2" : "=a"(t1), "=d"(t2) : "a"(a[i]) : "cc"); \
-    asm("addq %3,%0; adcq %4,%1; adcq %5,%2" \
-        : "+r"(c0), "+r"(c1), "+r"(c2)       \
-        : "r"(t1), "r"(t2), "g"(0)           \
-        : "cc");                             \
+#define sqr_add_c(a, i, c0, c1, c2)                           \
+  do {                                                        \
+    BN_ULONG t1, t2;                                          \
+    asm("mulq %2" : "=a"(t1), "=d"(t2) : "a"((a)[i]) : "cc"); \
+    asm("addq %3,%0; adcq %4,%1; adcq %5,%2"                  \
+        : "+r"(c0), "+r"(c1), "+r"(c2)                        \
+        : "r"(t1), "r"(t2), "g"(0)                            \
+        : "cc");                                              \
   } while (0)
 
 #define mul_add_c2(a, b, c0, c1, c2)         \
@@ -596,4 +529,4 @@
   r[7] = c2;
 }
 
-#endif  /* !NO_ASM && X86_64 && !WINDOWS */
+#endif  /* !NO_ASM && X86_64 && __GNUC__ */
diff --git a/src/crypto/bn/asm/x86_64-mont.pl b/src/crypto/bn/asm/x86_64-mont.pl
old mode 100644
new mode 100755
index 04c4bea..5775f65
--- a/src/crypto/bn/asm/x86_64-mont.pl
+++ b/src/crypto/bn/asm/x86_64-mont.pl
@@ -50,7 +50,7 @@
 ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
 die "can't locate x86_64-xlate.pl";
 
-open OUT,"| \"$^X\" $xlate $flavour $output";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
 *STDOUT=*OUT;
 
 # In upstream, this is controlled by shelling out to the compiler to check
@@ -84,6 +84,10 @@
 .type	bn_mul_mont,\@function,6
 .align	16
 bn_mul_mont:
+.cfi_startproc
+	mov	${num}d,${num}d
+	mov	%rsp,%rax
+.cfi_def_cfa_register	%rax
 	test	\$3,${num}d
 	jnz	.Lmul_enter
 	cmp	\$8,${num}d
@@ -102,20 +106,50 @@
 .align	16
 .Lmul_enter:
 	push	%rbx
+.cfi_push	%rbx
 	push	%rbp
+.cfi_push	%rbp
 	push	%r12
+.cfi_push	%r12
 	push	%r13
+.cfi_push	%r13
 	push	%r14
+.cfi_push	%r14
 	push	%r15
+.cfi_push	%r15
 
-	mov	${num}d,${num}d
-	lea	2($num),%r10
+	neg	$num
 	mov	%rsp,%r11
-	neg	%r10
-	lea	(%rsp,%r10,8),%rsp	# tp=alloca(8*(num+2))
-	and	\$-1024,%rsp		# minimize TLB usage
+	lea	-16(%rsp,$num,8),%r10	# future alloca(8*(num+2))
+	neg	$num			# restore $num
+	and	\$-1024,%r10		# minimize TLB usage
 
-	mov	%r11,8(%rsp,$num,8)	# tp[num+1]=%rsp
+	# An OS-agnostic version of __chkstk.
+	#
+	# Some OSes (Windows) insist on stack being "wired" to
+	# physical memory in strictly sequential manner, i.e. if stack
+	# allocation spans two pages, then reference to farmost one can
+	# be punishable by SEGV. But page walking can do good even on
+	# other OSes, because it guarantees that villain thread hits
+	# the guard page before it can make damage to innocent one...
+	sub	%r10,%r11
+	and	\$-4096,%r11
+	lea	(%r10,%r11),%rsp
+	mov	(%rsp),%r11
+	cmp	%r10,%rsp
+	ja	.Lmul_page_walk
+	jmp	.Lmul_page_walk_done
+
+.align	16
+.Lmul_page_walk:
+	lea	-4096(%rsp),%rsp
+	mov	(%rsp),%r11
+	cmp	%r10,%rsp
+	ja	.Lmul_page_walk
+.Lmul_page_walk_done:
+
+	mov	%rax,8(%rsp,$num,8)	# tp[num+1]=%rsp
+.cfi_cfa_expression	%rsp+8,$num,8,mul,plus,deref,+8
 .Lmul_body:
 	mov	$bp,%r12		# reassign $bp
 ___
@@ -265,36 +299,46 @@
 	mov	%rax,($rp,$i,8)		# rp[i]=tp[i]-np[i]
 	mov	8($ap,$i,8),%rax	# tp[i+1]
 	lea	1($i),$i		# i++
-	dec	$j			# doesn't affect CF!
+	dec	$j			# doesnn't affect CF!
 	jnz	.Lsub
 
 	sbb	\$0,%rax		# handle upmost overflow bit
 	xor	$i,$i
+	and	%rax,$ap
+	not	%rax
+	mov	$rp,$np
+	and	%rax,$np
 	mov	$num,$j			# j=num
+	or	$np,$ap			# ap=borrow?tp:rp
 .align	16
 .Lcopy:					# copy or in-place refresh
-	mov	(%rsp,$i,8),$ap
-	mov	($rp,$i,8),$np
-	xor	$np,$ap			# conditional select:
-	and	%rax,$ap		# ((ap ^ np) & %rax) ^ np
-	xor	$np,$ap			# ap = borrow?tp:rp
+	mov	($ap,$i,8),%rax
 	mov	$i,(%rsp,$i,8)		# zap temporary vector
-	mov	$ap,($rp,$i,8)		# rp[i]=tp[i]
+	mov	%rax,($rp,$i,8)		# rp[i]=tp[i]
 	lea	1($i),$i
 	sub	\$1,$j
 	jnz	.Lcopy
 
 	mov	8(%rsp,$num,8),%rsi	# restore %rsp
+.cfi_def_cfa	%rsi,8
 	mov	\$1,%rax
-	mov	(%rsi),%r15
-	mov	8(%rsi),%r14
-	mov	16(%rsi),%r13
-	mov	24(%rsi),%r12
-	mov	32(%rsi),%rbp
-	mov	40(%rsi),%rbx
-	lea	48(%rsi),%rsp
+	mov	-48(%rsi),%r15
+.cfi_restore	%r15
+	mov	-40(%rsi),%r14
+.cfi_restore	%r14
+	mov	-32(%rsi),%r13
+.cfi_restore	%r13
+	mov	-24(%rsi),%r12
+.cfi_restore	%r12
+	mov	-16(%rsi),%rbp
+.cfi_restore	%rbp
+	mov	-8(%rsi),%rbx
+.cfi_restore	%rbx
+	lea	(%rsi),%rsp
+.cfi_def_cfa_register	%rsp
 .Lmul_epilogue:
 	ret
+.cfi_endproc
 .size	bn_mul_mont,.-bn_mul_mont
 ___
 {{{
@@ -304,6 +348,10 @@
 .type	bn_mul4x_mont,\@function,6
 .align	16
 bn_mul4x_mont:
+.cfi_startproc
+	mov	${num}d,${num}d
+	mov	%rsp,%rax
+.cfi_def_cfa_register	%rax
 .Lmul4x_enter:
 ___
 $code.=<<___ if ($addx);
@@ -313,20 +361,41 @@
 ___
 $code.=<<___;
 	push	%rbx
+.cfi_push	%rbx
 	push	%rbp
+.cfi_push	%rbp
 	push	%r12
+.cfi_push	%r12
 	push	%r13
+.cfi_push	%r13
 	push	%r14
+.cfi_push	%r14
 	push	%r15
+.cfi_push	%r15
 
-	mov	${num}d,${num}d
-	lea	4($num),%r10
+	neg	$num
 	mov	%rsp,%r11
-	neg	%r10
-	lea	(%rsp,%r10,8),%rsp	# tp=alloca(8*(num+4))
-	and	\$-1024,%rsp		# minimize TLB usage
+	lea	-32(%rsp,$num,8),%r10	# future alloca(8*(num+4))
+	neg	$num			# restore
+	and	\$-1024,%r10		# minimize TLB usage
 
-	mov	%r11,8(%rsp,$num,8)	# tp[num+1]=%rsp
+	sub	%r10,%r11
+	and	\$-4096,%r11
+	lea	(%r10,%r11),%rsp
+	mov	(%rsp),%r11
+	cmp	%r10,%rsp
+	ja	.Lmul4x_page_walk
+	jmp	.Lmul4x_page_walk_done
+
+.Lmul4x_page_walk:
+	lea	-4096(%rsp),%rsp
+	mov	(%rsp),%r11
+	cmp	%r10,%rsp
+	ja	.Lmul4x_page_walk
+.Lmul4x_page_walk_done:
+
+	mov	%rax,8(%rsp,$num,8)	# tp[num+1]=%rsp
+.cfi_cfa_expression	%rsp+8,$num,8,mul,plus,deref,+8
 .Lmul4x_body:
 	mov	$rp,16(%rsp,$num,8)	# tp[num+2]=$rp
 	mov	%rdx,%r12		# reassign $bp
@@ -633,9 +702,11 @@
 my @ri=("%rax","%rdx",$m0,$m1);
 $code.=<<___;
 	mov	16(%rsp,$num,8),$rp	# restore $rp
+	lea	-4($num),$j
 	mov	0(%rsp),@ri[0]		# tp[0]
+	pxor	%xmm0,%xmm0
 	mov	8(%rsp),@ri[1]		# tp[1]
-	shr	\$2,$num		# num/=4
+	shr	\$2,$j			# j=num/4-1
 	lea	(%rsp),$ap		# borrow ap for tp
 	xor	$i,$i			# i=0 and clear CF!
 
@@ -643,7 +714,6 @@
 	mov	16($ap),@ri[2]		# tp[2]
 	mov	24($ap),@ri[3]		# tp[3]
 	sbb	8($np),@ri[1]
-	lea	-1($num),$j		# j=num/4-1
 	jmp	.Lsub4x
 .align	16
 .Lsub4x:
@@ -671,50 +741,58 @@
 	mov	@ri[2],16($rp,$i,8)	# rp[i]=tp[i]-np[i]
 
 	sbb	\$0,@ri[0]		# handle upmost overflow bit
-	mov	@ri[0],%xmm0
-	punpcklqdq %xmm0,%xmm0		# extend mask to 128 bits
 	mov	@ri[3],24($rp,$i,8)	# rp[i]=tp[i]-np[i]
 	xor	$i,$i			# i=0
+	and	@ri[0],$ap
+	not	@ri[0]
+	mov	$rp,$np
+	and	@ri[0],$np
+	lea	-4($num),$j
+	or	$np,$ap			# ap=borrow?tp:rp
+	shr	\$2,$j			# j=num/4-1
 
-	mov	$num,$j
-	pxor	%xmm5,%xmm5
+	movdqu	($ap),%xmm1
+	movdqa	%xmm0,(%rsp)
+	movdqu	%xmm1,($rp)
 	jmp	.Lcopy4x
 .align	16
-.Lcopy4x:				# copy or in-place refresh
-	movdqu	(%rsp,$i),%xmm2
-	movdqu  16(%rsp,$i),%xmm4
-	movdqu	($rp,$i),%xmm1
-	movdqu	16($rp,$i),%xmm3
-	pxor	%xmm1,%xmm2		# conditional select
-	pxor	%xmm3,%xmm4
-	pand	%xmm0,%xmm2
-	pand	%xmm0,%xmm4
-	pxor	%xmm1,%xmm2
-	pxor	%xmm3,%xmm4
-	movdqu	%xmm2,($rp,$i)
-	movdqu  %xmm4,16($rp,$i)
-	movdqa	%xmm5,(%rsp,$i)		# zap temporary vectors
-	movdqa	%xmm5,16(%rsp,$i)
-
+.Lcopy4x:					# copy or in-place refresh
+	movdqu	16($ap,$i),%xmm2
+	movdqu	32($ap,$i),%xmm1
+	movdqa	%xmm0,16(%rsp,$i)
+	movdqu	%xmm2,16($rp,$i)
+	movdqa	%xmm0,32(%rsp,$i)
+	movdqu	%xmm1,32($rp,$i)
 	lea	32($i),$i
 	dec	$j
 	jnz	.Lcopy4x
 
-	shl	\$2,$num
+	movdqu	16($ap,$i),%xmm2
+	movdqa	%xmm0,16(%rsp,$i)
+	movdqu	%xmm2,16($rp,$i)
 ___
 }
 $code.=<<___;
 	mov	8(%rsp,$num,8),%rsi	# restore %rsp
+.cfi_def_cfa	%rsi, 8
 	mov	\$1,%rax
-	mov	(%rsi),%r15
-	mov	8(%rsi),%r14
-	mov	16(%rsi),%r13
-	mov	24(%rsi),%r12
-	mov	32(%rsi),%rbp
-	mov	40(%rsi),%rbx
-	lea	48(%rsi),%rsp
+	mov	-48(%rsi),%r15
+.cfi_restore	%r15
+	mov	-40(%rsi),%r14
+.cfi_restore	%r14
+	mov	-32(%rsi),%r13
+.cfi_restore	%r13
+	mov	-24(%rsi),%r12
+.cfi_restore	%r12
+	mov	-16(%rsi),%rbp
+.cfi_restore	%rbp
+	mov	-8(%rsi),%rbx
+.cfi_restore	%rbx
+	lea	(%rsi),%rsp
+.cfi_def_cfa_register	%rsp
 .Lmul4x_epilogue:
 	ret
+.cfi_endproc
 .size	bn_mul4x_mont,.-bn_mul4x_mont
 ___
 }}}
@@ -742,14 +820,23 @@
 .type	bn_sqr8x_mont,\@function,6
 .align	32
 bn_sqr8x_mont:
-.Lsqr8x_enter:
+.cfi_startproc
 	mov	%rsp,%rax
+.cfi_def_cfa_register	%rax
+.Lsqr8x_enter:
 	push	%rbx
+.cfi_push	%rbx
 	push	%rbp
+.cfi_push	%rbp
 	push	%r12
+.cfi_push	%r12
 	push	%r13
+.cfi_push	%r13
 	push	%r14
+.cfi_push	%r14
 	push	%r15
+.cfi_push	%r15
+.Lsqr8x_prologue:
 
 	mov	${num}d,%r10d
 	shl	\$3,${num}d		# convert $num to bytes
@@ -761,111 +848,165 @@
 	# 4096. this is done to allow memory disambiguation logic
 	# do its job.
 	#
-	lea	-64(%rsp,$num,4),%r11
+	lea	-64(%rsp,$num,2),%r11
+	mov	%rsp,%rbp
 	mov	($n0),$n0		# *n0
 	sub	$aptr,%r11
 	and	\$4095,%r11
 	cmp	%r11,%r10
 	jb	.Lsqr8x_sp_alt
-	sub	%r11,%rsp		# align with $aptr
-	lea	-64(%rsp,$num,4),%rsp	# alloca(frame+4*$num)
+	sub	%r11,%rbp		# align with $aptr
+	lea	-64(%rbp,$num,2),%rbp	# future alloca(frame+2*$num)
 	jmp	.Lsqr8x_sp_done
 
 .align	32
 .Lsqr8x_sp_alt:
-	lea	4096-64(,$num,4),%r10	# 4096-frame-4*$num
-	lea	-64(%rsp,$num,4),%rsp	# alloca(frame+4*$num)
+	lea	4096-64(,$num,2),%r10	# 4096-frame-2*$num
+	lea	-64(%rbp,$num,2),%rbp	# future alloca(frame+2*$num)
 	sub	%r10,%r11
 	mov	\$0,%r10
 	cmovc	%r10,%r11
-	sub	%r11,%rsp
+	sub	%r11,%rbp
 .Lsqr8x_sp_done:
-	and	\$-64,%rsp
-	mov	$num,%r10	
+	and	\$-64,%rbp
+	mov	%rsp,%r11
+	sub	%rbp,%r11
+	and	\$-4096,%r11
+	lea	(%rbp,%r11),%rsp
+	mov	(%rsp),%r10
+	cmp	%rbp,%rsp
+	ja	.Lsqr8x_page_walk
+	jmp	.Lsqr8x_page_walk_done
+
+.align	16
+.Lsqr8x_page_walk:
+	lea	-4096(%rsp),%rsp
+	mov	(%rsp),%r10
+	cmp	%rbp,%rsp
+	ja	.Lsqr8x_page_walk
+.Lsqr8x_page_walk_done:
+
+	mov	$num,%r10
 	neg	$num
 
-	lea	64(%rsp,$num,2),%r11	# copy of modulus
 	mov	$n0,  32(%rsp)
 	mov	%rax, 40(%rsp)		# save original %rsp
+.cfi_cfa_expression	%rsp+40,deref,+8
 .Lsqr8x_body:
 
-	mov	$num,$i
-	movq	%r11, %xmm2		# save pointer to modulus copy
-	shr	\$3+2,$i
-	mov	OPENSSL_ia32cap_P+8(%rip),%eax
-	jmp	.Lsqr8x_copy_n
-
-.align	32
-.Lsqr8x_copy_n:
-	movq	8*0($nptr),%xmm0
-	movq	8*1($nptr),%xmm1
-	movq	8*2($nptr),%xmm3
-	movq	8*3($nptr),%xmm4
-	lea	8*4($nptr),$nptr
-	movdqa	%xmm0,16*0(%r11)
-	movdqa	%xmm1,16*1(%r11)
-	movdqa	%xmm3,16*2(%r11)
-	movdqa	%xmm4,16*3(%r11)
-	lea	16*4(%r11),%r11
-	dec	$i
-	jnz	.Lsqr8x_copy_n
-
+	movq	$nptr, %xmm2		# save pointer to modulus
 	pxor	%xmm0,%xmm0
 	movq	$rptr,%xmm1		# save $rptr
 	movq	%r10, %xmm3		# -$num
 ___
 $code.=<<___ if ($addx);
+	mov	OPENSSL_ia32cap_P+8(%rip),%eax
 	and	\$0x80100,%eax
 	cmp	\$0x80100,%eax
 	jne	.Lsqr8x_nox
 
 	call	bn_sqrx8x_internal	# see x86_64-mont5 module
-
-	pxor	%xmm0,%xmm0
-	lea	48(%rsp),%rax
-	lea	64(%rsp,$num,2),%rdx
-	shr	\$3+2,$num
-	mov	40(%rsp),%rsi		# restore %rsp
-	jmp	.Lsqr8x_zero
+					# %rax	top-most carry
+					# %rbp	nptr
+					# %rcx	-8*num
+					# %r8	end of tp[2*num]
+	lea	(%r8,%rcx),%rbx
+	mov	%rcx,$num
+	mov	%rcx,%rdx
+	movq	%xmm1,$rptr
+	sar	\$3+2,%rcx		# %cf=0
+	jmp	.Lsqr8x_sub
 
 .align	32
 .Lsqr8x_nox:
 ___
 $code.=<<___;
 	call	bn_sqr8x_internal	# see x86_64-mont5 module
-
-	pxor	%xmm0,%xmm0
-	lea	48(%rsp),%rax
-	lea	64(%rsp,$num,2),%rdx
-	shr	\$3+2,$num
-	mov	40(%rsp),%rsi		# restore %rsp
-	jmp	.Lsqr8x_zero
+					# %rax	top-most carry
+					# %rbp	nptr
+					# %r8	-8*num
+					# %rdi	end of tp[2*num]
+	lea	(%rdi,$num),%rbx
+	mov	$num,%rcx
+	mov	$num,%rdx
+	movq	%xmm1,$rptr
+	sar	\$3+2,%rcx		# %cf=0
+	jmp	.Lsqr8x_sub
 
 .align	32
-.Lsqr8x_zero:
-	movdqa	%xmm0,16*0(%rax)	# wipe t
-	movdqa	%xmm0,16*1(%rax)
-	movdqa	%xmm0,16*2(%rax)
-	movdqa	%xmm0,16*3(%rax)
-	lea	16*4(%rax),%rax
-	movdqa	%xmm0,16*0(%rdx)	# wipe n
-	movdqa	%xmm0,16*1(%rdx)
-	movdqa	%xmm0,16*2(%rdx)
-	movdqa	%xmm0,16*3(%rdx)
-	lea	16*4(%rdx),%rdx
-	dec	$num
-	jnz	.Lsqr8x_zero
+.Lsqr8x_sub:
+	mov	8*0(%rbx),%r12
+	mov	8*1(%rbx),%r13
+	mov	8*2(%rbx),%r14
+	mov	8*3(%rbx),%r15
+	lea	8*4(%rbx),%rbx
+	sbb	8*0(%rbp),%r12
+	sbb	8*1(%rbp),%r13
+	sbb	8*2(%rbp),%r14
+	sbb	8*3(%rbp),%r15
+	lea	8*4(%rbp),%rbp
+	mov	%r12,8*0($rptr)
+	mov	%r13,8*1($rptr)
+	mov	%r14,8*2($rptr)
+	mov	%r15,8*3($rptr)
+	lea	8*4($rptr),$rptr
+	inc	%rcx			# preserves %cf
+	jnz	.Lsqr8x_sub
+
+	sbb	\$0,%rax		# top-most carry
+	lea	(%rbx,$num),%rbx	# rewind
+	lea	($rptr,$num),$rptr	# rewind
+
+	movq	%rax,%xmm1
+	pxor	%xmm0,%xmm0
+	pshufd	\$0,%xmm1,%xmm1
+	mov	40(%rsp),%rsi		# restore %rsp
+.cfi_def_cfa	%rsi,8
+	jmp	.Lsqr8x_cond_copy
+
+.align	32
+.Lsqr8x_cond_copy:
+	movdqa	16*0(%rbx),%xmm2
+	movdqa	16*1(%rbx),%xmm3
+	lea	16*2(%rbx),%rbx
+	movdqu	16*0($rptr),%xmm4
+	movdqu	16*1($rptr),%xmm5
+	lea	16*2($rptr),$rptr
+	movdqa	%xmm0,-16*2(%rbx)	# zero tp
+	movdqa	%xmm0,-16*1(%rbx)
+	movdqa	%xmm0,-16*2(%rbx,%rdx)
+	movdqa	%xmm0,-16*1(%rbx,%rdx)
+	pcmpeqd	%xmm1,%xmm0
+	pand	%xmm1,%xmm2
+	pand	%xmm1,%xmm3
+	pand	%xmm0,%xmm4
+	pand	%xmm0,%xmm5
+	pxor	%xmm0,%xmm0
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqu	%xmm4,-16*2($rptr)
+	movdqu	%xmm5,-16*1($rptr)
+	add	\$32,$num
+	jnz	.Lsqr8x_cond_copy
 
 	mov	\$1,%rax
 	mov	-48(%rsi),%r15
+.cfi_restore	%r15
 	mov	-40(%rsi),%r14
+.cfi_restore	%r14
 	mov	-32(%rsi),%r13
+.cfi_restore	%r13
 	mov	-24(%rsi),%r12
+.cfi_restore	%r12
 	mov	-16(%rsi),%rbp
+.cfi_restore	%rbp
 	mov	-8(%rsi),%rbx
+.cfi_restore	%rbx
 	lea	(%rsi),%rsp
+.cfi_def_cfa_register	%rsp
 .Lsqr8x_epilogue:
 	ret
+.cfi_endproc
 .size	bn_sqr8x_mont,.-bn_sqr8x_mont
 ___
 }}}
@@ -877,23 +1018,48 @@
 .type	bn_mulx4x_mont,\@function,6
 .align	32
 bn_mulx4x_mont:
-.Lmulx4x_enter:
+.cfi_startproc
 	mov	%rsp,%rax
+.cfi_def_cfa_register	%rax
+.Lmulx4x_enter:
 	push	%rbx
+.cfi_push	%rbx
 	push	%rbp
+.cfi_push	%rbp
 	push	%r12
+.cfi_push	%r12
 	push	%r13
+.cfi_push	%r13
 	push	%r14
+.cfi_push	%r14
 	push	%r15
+.cfi_push	%r15
+.Lmulx4x_prologue:
 
 	shl	\$3,${num}d		# convert $num to bytes
-	.byte	0x67
 	xor	%r10,%r10
 	sub	$num,%r10		# -$num
 	mov	($n0),$n0		# *n0
-	lea	-72(%rsp,%r10),%rsp	# alloca(frame+$num+8)
+	lea	-72(%rsp,%r10),%rbp	# future alloca(frame+$num+8)
+	and	\$-128,%rbp
+	mov	%rsp,%r11
+	sub	%rbp,%r11
+	and	\$-4096,%r11
+	lea	(%rbp,%r11),%rsp
+	mov	(%rsp),%r10
+	cmp	%rbp,%rsp
+	ja	.Lmulx4x_page_walk
+	jmp	.Lmulx4x_page_walk_done
+
+.align	16
+.Lmulx4x_page_walk:
+	lea	-4096(%rsp),%rsp
+	mov	(%rsp),%r10
+	cmp	%rbp,%rsp
+	ja	.Lmulx4x_page_walk
+.Lmulx4x_page_walk_done:
+
 	lea	($bp,$num),%r10
-	and	\$-128,%rsp
 	##############################################################
 	# Stack layout
 	# +0	num
@@ -913,6 +1079,7 @@
 	mov	$n0, 24(%rsp)		# save *n0
 	mov	$rp, 32(%rsp)		# save $rp
 	mov	%rax,40(%rsp)		# save original %rsp
+.cfi_cfa_expression	%rsp+40,deref,+8
 	mov	$num,48(%rsp)		# inner counter
 	jmp	.Lmulx4x_body
 
@@ -1033,18 +1200,17 @@
 	mulx	2*8($aptr),%r15,%r13	# ...
 	adox	-3*8($tptr),%r11
 	adcx	%r15,%r12
-	adox	$zero,%r12
+	adox	-2*8($tptr),%r12
 	adcx	$zero,%r13
+	adox	$zero,%r13
 
 	mov	$bptr,8(%rsp)		# off-load &b[i]
-	.byte	0x67
 	mov	$mi,%r15
 	imulq	24(%rsp),$mi		# "t[0]"*n0
 	xor	%ebp,%ebp		# xor	$zero,$zero	# cf=0, of=0
 
 	mulx	3*8($aptr),%rax,%r14
 	 mov	$mi,%rdx
-	adox	-2*8($tptr),%r12
 	adcx	%rax,%r13
 	adox	-1*8($tptr),%r13
 	adcx	$zero,%r14
@@ -1121,74 +1287,94 @@
 	adc	$zero,%r15		# modulo-scheduled
 	sub	0*8($tptr),$zero	# pull top-most carry
 	adc	%r15,%r14
-	mov	-8($nptr),$mi
 	sbb	%r15,%r15		# top-most carry
 	mov	%r14,-1*8($tptr)
 
 	cmp	16(%rsp),$bptr
 	jne	.Lmulx4x_outer
 
-	sub	%r14,$mi		# compare top-most words
-	sbb	$mi,$mi
-	or	$mi,%r15
-
-	neg	$num
-	xor	%rdx,%rdx
-	mov	32(%rsp),$rptr		# restore rp
 	lea	64(%rsp),$tptr
-
-	pxor	%xmm0,%xmm0
-	mov	0*8($nptr,$num),%r8
-	mov	1*8($nptr,$num),%r9
-	neg	%r8
-	jmp	.Lmulx4x_sub_entry
+	sub	$num,$nptr		# rewind $nptr
+	neg	%r15
+	mov	$num,%rdx
+	shr	\$3+2,$num		# %cf=0
+	mov	32(%rsp),$rptr		# restore rp
+	jmp	.Lmulx4x_sub
 
 .align	32
 .Lmulx4x_sub:
-	mov	0*8($nptr,$num),%r8
-	mov	1*8($nptr,$num),%r9
-	not	%r8
-.Lmulx4x_sub_entry:
-	mov	2*8($nptr,$num),%r10
-	not	%r9
-	and	%r15,%r8
-	mov	3*8($nptr,$num),%r11
-	not	%r10
-	and	%r15,%r9
-	not	%r11
-	and	%r15,%r10
-	and	%r15,%r11
-
-	neg	%rdx			# mov %rdx,%cf
-	adc	0*8($tptr),%r8
-	adc	1*8($tptr),%r9
-	movdqa	%xmm0,($tptr)
-	adc	2*8($tptr),%r10
-	adc	3*8($tptr),%r11
-	movdqa	%xmm0,16($tptr)
-	lea	4*8($tptr),$tptr
-	sbb	%rdx,%rdx		# mov %cf,%rdx
-
-	mov	%r8,0*8($rptr)
-	mov	%r9,1*8($rptr)
-	mov	%r10,2*8($rptr)
-	mov	%r11,3*8($rptr)
-	lea	4*8($rptr),$rptr
-
-	add	\$32,$num
+	mov	8*0($tptr),%r11
+	mov	8*1($tptr),%r12
+	mov	8*2($tptr),%r13
+	mov	8*3($tptr),%r14
+	lea	8*4($tptr),$tptr
+	sbb	8*0($nptr),%r11
+	sbb	8*1($nptr),%r12
+	sbb	8*2($nptr),%r13
+	sbb	8*3($nptr),%r14
+	lea	8*4($nptr),$nptr
+	mov	%r11,8*0($rptr)
+	mov	%r12,8*1($rptr)
+	mov	%r13,8*2($rptr)
+	mov	%r14,8*3($rptr)
+	lea	8*4($rptr),$rptr
+	dec	$num			# preserves %cf
 	jnz	.Lmulx4x_sub
 
+	sbb	\$0,%r15		# top-most carry
+	lea	64(%rsp),$tptr
+	sub	%rdx,$rptr		# rewind
+
+	movq	%r15,%xmm1
+	pxor	%xmm0,%xmm0
+	pshufd	\$0,%xmm1,%xmm1
 	mov	40(%rsp),%rsi		# restore %rsp
+.cfi_def_cfa	%rsi,8
+	jmp	.Lmulx4x_cond_copy
+
+.align	32
+.Lmulx4x_cond_copy:
+	movdqa	16*0($tptr),%xmm2
+	movdqa	16*1($tptr),%xmm3
+	lea	16*2($tptr),$tptr
+	movdqu	16*0($rptr),%xmm4
+	movdqu	16*1($rptr),%xmm5
+	lea	16*2($rptr),$rptr
+	movdqa	%xmm0,-16*2($tptr)	# zero tp
+	movdqa	%xmm0,-16*1($tptr)
+	pcmpeqd	%xmm1,%xmm0
+	pand	%xmm1,%xmm2
+	pand	%xmm1,%xmm3
+	pand	%xmm0,%xmm4
+	pand	%xmm0,%xmm5
+	pxor	%xmm0,%xmm0
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+	movdqu	%xmm4,-16*2($rptr)
+	movdqu	%xmm5,-16*1($rptr)
+	sub	\$32,%rdx
+	jnz	.Lmulx4x_cond_copy
+
+	mov	%rdx,($tptr)
+
 	mov	\$1,%rax
 	mov	-48(%rsi),%r15
+.cfi_restore	%r15
 	mov	-40(%rsi),%r14
+.cfi_restore	%r14
 	mov	-32(%rsi),%r13
+.cfi_restore	%r13
 	mov	-24(%rsi),%r12
+.cfi_restore	%r12
 	mov	-16(%rsi),%rbp
+.cfi_restore	%rbp
 	mov	-8(%rsi),%rbx
+.cfi_restore	%rbx
 	lea	(%rsi),%rsp
+.cfi_def_cfa_register	%rsp
 .Lmulx4x_epilogue:
 	ret
+.cfi_endproc
 .size	bn_mulx4x_mont,.-bn_mulx4x_mont
 ___
 }}}
@@ -1241,22 +1427,8 @@
 
 	mov	192($context),%r10	# pull $num
 	mov	8(%rax,%r10,8),%rax	# pull saved stack pointer
-	lea	48(%rax),%rax
 
-	mov	-8(%rax),%rbx
-	mov	-16(%rax),%rbp
-	mov	-24(%rax),%r12
-	mov	-32(%rax),%r13
-	mov	-40(%rax),%r14
-	mov	-48(%rax),%r15
-	mov	%rbx,144($context)	# restore context->Rbx
-	mov	%rbp,160($context)	# restore context->Rbp
-	mov	%r12,216($context)	# restore context->R12
-	mov	%r13,224($context)	# restore context->R13
-	mov	%r14,232($context)	# restore context->R14
-	mov	%r15,240($context)	# restore context->R15
-
-	jmp	.Lcommon_seh_tail
+	jmp	.Lcommon_pop_regs
 .size	mul_handler,.-mul_handler
 
 .type	sqr_handler,\@abi-omnipotent
@@ -1281,18 +1453,24 @@
 
 	mov	0(%r11),%r10d		# HandlerData[0]
 	lea	(%rsi,%r10),%r10	# end of prologue label
-	cmp	%r10,%rbx		# context->Rip<.Lsqr_body
+	cmp	%r10,%rbx		# context->Rip<.Lsqr_prologue
 	jb	.Lcommon_seh_tail
 
+	mov	4(%r11),%r10d		# HandlerData[1]
+	lea	(%rsi,%r10),%r10	# body label
+	cmp	%r10,%rbx		# context->Rip<.Lsqr_body
+	jb	.Lcommon_pop_regs
+
 	mov	152($context),%rax	# pull context->Rsp
 
-	mov	4(%r11),%r10d		# HandlerData[1]
+	mov	8(%r11),%r10d		# HandlerData[2]
 	lea	(%rsi,%r10),%r10	# epilogue label
 	cmp	%r10,%rbx		# context->Rip>=.Lsqr_epilogue
 	jae	.Lcommon_seh_tail
 
 	mov	40(%rax),%rax		# pull saved stack pointer
 
+.Lcommon_pop_regs:
 	mov	-8(%rax),%rbx
 	mov	-16(%rax),%rbp
 	mov	-24(%rax),%r12
@@ -1379,13 +1557,15 @@
 .LSEH_info_bn_sqr8x_mont:
 	.byte	9,0,0,0
 	.rva	sqr_handler
-	.rva	.Lsqr8x_body,.Lsqr8x_epilogue	# HandlerData[]
+	.rva	.Lsqr8x_prologue,.Lsqr8x_body,.Lsqr8x_epilogue		# HandlerData[]
+.align	8
 ___
 $code.=<<___ if ($addx);
 .LSEH_info_bn_mulx4x_mont:
 	.byte	9,0,0,0
 	.rva	sqr_handler
-	.rva	.Lmulx4x_body,.Lmulx4x_epilogue	# HandlerData[]
+	.rva	.Lmulx4x_prologue,.Lmulx4x_body,.Lmulx4x_epilogue	# HandlerData[]
+.align	8
 ___
 }
 
diff --git a/src/crypto/bn/asm/x86_64-mont5.pl b/src/crypto/bn/asm/x86_64-mont5.pl
old mode 100644
new mode 100755
index 3c5a8fc..bf68aad
--- a/src/crypto/bn/asm/x86_64-mont5.pl
+++ b/src/crypto/bn/asm/x86_64-mont5.pl
@@ -35,7 +35,7 @@
 ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
 die "can't locate x86_64-xlate.pl";
 
-open OUT,"| \"$^X\" $xlate $flavour $output";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
 *STDOUT=*OUT;
 
 # In upstream, this is controlled by shelling out to the compiler to check
@@ -73,6 +73,10 @@
 .type	bn_mul_mont_gather5,\@function,6
 .align	64
 bn_mul_mont_gather5:
+.cfi_startproc
+	mov	${num}d,${num}d
+	mov	%rsp,%rax
+.cfi_def_cfa_register	%rax
 	test	\$7,${num}d
 	jnz	.Lmul_enter
 ___
@@ -84,60 +88,143 @@
 
 .align	16
 .Lmul_enter:
-	mov	${num}d,${num}d
-	mov	%rsp,%rax
-	mov	`($win64?56:8)`(%rsp),%r10d	# load 7th argument
+	movd	`($win64?56:8)`(%rsp),%xmm5	# load 7th argument
 	push	%rbx
+.cfi_push	%rbx
 	push	%rbp
+.cfi_push	%rbp
 	push	%r12
+.cfi_push	%r12
 	push	%r13
+.cfi_push	%r13
 	push	%r14
+.cfi_push	%r14
 	push	%r15
-___
-$code.=<<___ if ($win64);
-	lea	-0x28(%rsp),%rsp
-	movaps	%xmm6,(%rsp)
-	movaps	%xmm7,0x10(%rsp)
-___
-$code.=<<___;
-	lea	2($num),%r11
-	neg	%r11
-	lea	(%rsp,%r11,8),%rsp	# tp=alloca(8*(num+2))
-	and	\$-1024,%rsp		# minimize TLB usage
+.cfi_push	%r15
 
+	neg	$num
+	mov	%rsp,%r11
+	lea	-280(%rsp,$num,8),%r10	# future alloca(8*(num+2)+256+8)
+	neg	$num			# restore $num
+	and	\$-1024,%r10		# minimize TLB usage
+
+	# An OS-agnostic version of __chkstk.
+	#
+	# Some OSes (Windows) insist on stack being "wired" to
+	# physical memory in strictly sequential manner, i.e. if stack
+	# allocation spans two pages, then reference to farmost one can
+	# be punishable by SEGV. But page walking can do good even on
+	# other OSes, because it guarantees that villain thread hits
+	# the guard page before it can make damage to innocent one...
+	sub	%r10,%r11
+	and	\$-4096,%r11
+	lea	(%r10,%r11),%rsp
+	mov	(%rsp),%r11
+	cmp	%r10,%rsp
+	ja	.Lmul_page_walk
+	jmp	.Lmul_page_walk_done
+
+.Lmul_page_walk:
+	lea	-4096(%rsp),%rsp
+	mov	(%rsp),%r11
+	cmp	%r10,%rsp
+	ja	.Lmul_page_walk
+.Lmul_page_walk_done:
+
+	lea	.Linc(%rip),%r10
 	mov	%rax,8(%rsp,$num,8)	# tp[num+1]=%rsp
+.cfi_cfa_expression	%rsp+8,$num,8,mul,plus,deref,+8
 .Lmul_body:
-	mov	$bp,%r12		# reassign $bp
+
+	lea	128($bp),%r12		# reassign $bp (+size optimization)
 ___
 		$bp="%r12";
 		$STRIDE=2**5*8;		# 5 is "window size"
 		$N=$STRIDE/4;		# should match cache line size
 $code.=<<___;
-	mov	%r10,%r11
-	shr	\$`log($N/8)/log(2)`,%r10
-	and	\$`$N/8-1`,%r11
-	not	%r10
-	lea	.Lmagic_masks(%rip),%rax
-	and	\$`2**5/($N/8)-1`,%r10	# 5 is "window size"
-	lea	96($bp,%r11,8),$bp	# pointer within 1st cache line
-	movq	0(%rax,%r10,8),%xmm4	# set of masks denoting which
-	movq	8(%rax,%r10,8),%xmm5	# cache line contains element
-	movq	16(%rax,%r10,8),%xmm6	# denoted by 7th argument
-	movq	24(%rax,%r10,8),%xmm7
+	movdqa	0(%r10),%xmm0		# 00000001000000010000000000000000
+	movdqa	16(%r10),%xmm1		# 00000002000000020000000200000002
+	lea	24-112(%rsp,$num,8),%r10# place the mask after tp[num+3] (+ICache optimization)
+	and	\$-16,%r10
 
-	movq	`0*$STRIDE/4-96`($bp),%xmm0
-	movq	`1*$STRIDE/4-96`($bp),%xmm1
-	pand	%xmm4,%xmm0
-	movq	`2*$STRIDE/4-96`($bp),%xmm2
-	pand	%xmm5,%xmm1
-	movq	`3*$STRIDE/4-96`($bp),%xmm3
-	pand	%xmm6,%xmm2
-	por	%xmm1,%xmm0
-	pand	%xmm7,%xmm3
+	pshufd	\$0,%xmm5,%xmm5		# broadcast index
+	movdqa	%xmm1,%xmm4
+	movdqa	%xmm1,%xmm2
+___
+########################################################################
+# calculate mask by comparing 0..31 to index and save result to stack
+#
+$code.=<<___;
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0		# compare to 1,0
+	.byte	0x67
+	movdqa	%xmm4,%xmm3
+___
+for($k=0;$k<$STRIDE/16-4;$k+=4) {
+$code.=<<___;
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1		# compare to 3,2
+	movdqa	%xmm0,`16*($k+0)+112`(%r10)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2		# compare to 5,4
+	movdqa	%xmm1,`16*($k+1)+112`(%r10)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3		# compare to 7,6
+	movdqa	%xmm2,`16*($k+2)+112`(%r10)
+	movdqa	%xmm4,%xmm2
+
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,`16*($k+3)+112`(%r10)
+	movdqa	%xmm4,%xmm3
+___
+}
+$code.=<<___;				# last iteration can be optimized
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,`16*($k+0)+112`(%r10)
+
+	paddd	%xmm2,%xmm3
+	.byte	0x67
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,`16*($k+1)+112`(%r10)
+
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,`16*($k+2)+112`(%r10)
+	pand	`16*($k+0)-128`($bp),%xmm0	# while it's still in register
+
+	pand	`16*($k+1)-128`($bp),%xmm1
+	pand	`16*($k+2)-128`($bp),%xmm2
+	movdqa	%xmm3,`16*($k+3)+112`(%r10)
+	pand	`16*($k+3)-128`($bp),%xmm3
 	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+___
+for($k=0;$k<$STRIDE/16-4;$k+=4) {
+$code.=<<___;
+	movdqa	`16*($k+0)-128`($bp),%xmm4
+	movdqa	`16*($k+1)-128`($bp),%xmm5
+	movdqa	`16*($k+2)-128`($bp),%xmm2
+	pand	`16*($k+0)+112`(%r10),%xmm4
+	movdqa	`16*($k+3)-128`($bp),%xmm3
+	pand	`16*($k+1)+112`(%r10),%xmm5
+	por	%xmm4,%xmm0
+	pand	`16*($k+2)+112`(%r10),%xmm2
+	por	%xmm5,%xmm1
+	pand	`16*($k+3)+112`(%r10),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+___
+}
+$code.=<<___;
+	por	%xmm1,%xmm0
+	pshufd	\$0x4e,%xmm0,%xmm1
+	por	%xmm1,%xmm0
 	lea	$STRIDE($bp),$bp
-	por	%xmm3,%xmm0
-
 	movq	%xmm0,$m0		# m0=bp[0]
 
 	mov	($n0),$n0		# pull n0[0] value
@@ -146,29 +233,14 @@
 	xor	$i,$i			# i=0
 	xor	$j,$j			# j=0
 
-	movq	`0*$STRIDE/4-96`($bp),%xmm0
-	movq	`1*$STRIDE/4-96`($bp),%xmm1
-	pand	%xmm4,%xmm0
-	movq	`2*$STRIDE/4-96`($bp),%xmm2
-	pand	%xmm5,%xmm1
-
 	mov	$n0,$m1
 	mulq	$m0			# ap[0]*bp[0]
 	mov	%rax,$lo0
 	mov	($np),%rax
 
-	movq	`3*$STRIDE/4-96`($bp),%xmm3
-	pand	%xmm6,%xmm2
-	por	%xmm1,%xmm0
-	pand	%xmm7,%xmm3
-
 	imulq	$lo0,$m1		# "tp[0]"*n0
 	mov	%rdx,$hi0
 
-	por	%xmm2,%xmm0
-	lea	$STRIDE($bp),$bp
-	por	%xmm3,%xmm0
-
 	mulq	$m1			# np[0]*m1
 	add	%rax,$lo0		# discarded
 	mov	8($ap),%rax
@@ -199,16 +271,14 @@
 
 	mulq	$m1			# np[j]*m1
 	cmp	$num,$j
-	jne	.L1st
-
-	movq	%xmm0,$m0		# bp[1]
+	jne	.L1st			# note that upon exit $j==$num, so
+					# they can be used interchangeably
 
 	add	%rax,$hi1
-	mov	($ap),%rax		# ap[0]
 	adc	\$0,%rdx
 	add	$hi0,$hi1		# np[j]*m1+ap[j]*bp[0]
 	adc	\$0,%rdx
-	mov	$hi1,-16(%rsp,$j,8)	# tp[j-1]
+	mov	$hi1,-16(%rsp,$num,8)	# tp[num-1]
 	mov	%rdx,$hi1
 	mov	$lo0,$hi0
 
@@ -222,33 +292,48 @@
 	jmp	.Louter
 .align	16
 .Louter:
+	lea	24+128(%rsp,$num,8),%rdx	# where 256-byte mask is (+size optimization)
+	and	\$-16,%rdx
+	pxor	%xmm4,%xmm4
+	pxor	%xmm5,%xmm5
+___
+for($k=0;$k<$STRIDE/16;$k+=4) {
+$code.=<<___;
+	movdqa	`16*($k+0)-128`($bp),%xmm0
+	movdqa	`16*($k+1)-128`($bp),%xmm1
+	movdqa	`16*($k+2)-128`($bp),%xmm2
+	movdqa	`16*($k+3)-128`($bp),%xmm3
+	pand	`16*($k+0)-128`(%rdx),%xmm0
+	pand	`16*($k+1)-128`(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	`16*($k+2)-128`(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	`16*($k+3)-128`(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+___
+}
+$code.=<<___;
+	por	%xmm5,%xmm4
+	pshufd	\$0x4e,%xmm4,%xmm0
+	por	%xmm4,%xmm0
+	lea	$STRIDE($bp),$bp
+
+	mov	($ap),%rax		# ap[0]
+	movq	%xmm0,$m0		# m0=bp[i]
+
 	xor	$j,$j			# j=0
 	mov	$n0,$m1
 	mov	(%rsp),$lo0
 
-	movq	`0*$STRIDE/4-96`($bp),%xmm0
-	movq	`1*$STRIDE/4-96`($bp),%xmm1
-	pand	%xmm4,%xmm0
-	movq	`2*$STRIDE/4-96`($bp),%xmm2
-	pand	%xmm5,%xmm1
-
 	mulq	$m0			# ap[0]*bp[i]
 	add	%rax,$lo0		# ap[0]*bp[i]+tp[0]
 	mov	($np),%rax
 	adc	\$0,%rdx
 
-	movq	`3*$STRIDE/4-96`($bp),%xmm3
-	pand	%xmm6,%xmm2
-	por	%xmm1,%xmm0
-	pand	%xmm7,%xmm3
-
 	imulq	$lo0,$m1		# tp[0]*n0
 	mov	%rdx,$hi0
 
-	por	%xmm2,%xmm0
-	lea	$STRIDE($bp),$bp
-	por	%xmm3,%xmm0
-
 	mulq	$m1			# np[0]*m1
 	add	%rax,$lo0		# discarded
 	mov	8($ap),%rax
@@ -282,17 +367,14 @@
 
 	mulq	$m1			# np[j]*m1
 	cmp	$num,$j
-	jne	.Linner
-
-	movq	%xmm0,$m0		# bp[i+1]
-
+	jne	.Linner			# note that upon exit $j==$num, so
+					# they can be used interchangeably
 	add	%rax,$hi1
-	mov	($ap),%rax		# ap[0]
 	adc	\$0,%rdx
 	add	$lo0,$hi1		# np[j]*m1+ap[j]*bp[i]+tp[j]
-	mov	(%rsp,$j,8),$lo0
+	mov	(%rsp,$num,8),$lo0
 	adc	\$0,%rdx
-	mov	$hi1,-16(%rsp,$j,8)	# tp[j-1]
+	mov	$hi1,-16(%rsp,$num,8)	# tp[num-1]
 	mov	%rdx,$hi1
 
 	xor	%rdx,%rdx
@@ -322,37 +404,42 @@
 
 	sbb	\$0,%rax		# handle upmost overflow bit
 	xor	$i,$i
+	and	%rax,$ap
+	not	%rax
+	mov	$rp,$np
+	and	%rax,$np
 	mov	$num,$j			# j=num
+	or	$np,$ap			# ap=borrow?tp:rp
 .align	16
 .Lcopy:					# copy or in-place refresh
-	mov	(%rsp,$i,8),$ap
-	mov	($rp,$i,8),$np
-	xor	$np,$ap			# conditional select:
-	and	%rax,$ap		# ((ap ^ np) & %rax) ^ np
-	xor	$np,$ap			# ap = borrow?tp:rp
+	mov	($ap,$i,8),%rax
 	mov	$i,(%rsp,$i,8)		# zap temporary vector
-	mov	$ap,($rp,$i,8)		# rp[i]=tp[i]
+	mov	%rax,($rp,$i,8)		# rp[i]=tp[i]
 	lea	1($i),$i
 	sub	\$1,$j
 	jnz	.Lcopy
 
 	mov	8(%rsp,$num,8),%rsi	# restore %rsp
+.cfi_def_cfa	%rsi,8
 	mov	\$1,%rax
-___
-$code.=<<___ if ($win64);
-	movaps	-88(%rsi),%xmm6
-	movaps	-72(%rsi),%xmm7
-___
-$code.=<<___;
+
 	mov	-48(%rsi),%r15
+.cfi_restore	%r15
 	mov	-40(%rsi),%r14
+.cfi_restore	%r14
 	mov	-32(%rsi),%r13
+.cfi_restore	%r13
 	mov	-24(%rsi),%r12
+.cfi_restore	%r12
 	mov	-16(%rsi),%rbp
+.cfi_restore	%rbp
 	mov	-8(%rsi),%rbx
+.cfi_restore	%rbx
 	lea	(%rsi),%rsp
+.cfi_def_cfa_register	%rsp
 .Lmul_epilogue:
 	ret
+.cfi_endproc
 .size	bn_mul_mont_gather5,.-bn_mul_mont_gather5
 ___
 {{{
@@ -362,93 +449,120 @@
 .type	bn_mul4x_mont_gather5,\@function,6
 .align	32
 bn_mul4x_mont_gather5:
+.cfi_startproc
+	.byte	0x67
+	mov	%rsp,%rax
+.cfi_def_cfa_register	%rax
 .Lmul4x_enter:
 ___
 $code.=<<___ if ($addx);
-	and	\$0x80100,%r11d
-	cmp	\$0x80100,%r11d
+	and	\$0x80108,%r11d
+	cmp	\$0x80108,%r11d		# check for AD*X+BMI2+BMI1
 	je	.Lmulx4x_enter
 ___
 $code.=<<___;
-	.byte	0x67
-	mov	%rsp,%rax
 	push	%rbx
+.cfi_push	%rbx
 	push	%rbp
+.cfi_push	%rbp
 	push	%r12
+.cfi_push	%r12
 	push	%r13
+.cfi_push	%r13
 	push	%r14
+.cfi_push	%r14
 	push	%r15
-___
-$code.=<<___ if ($win64);
-	lea	-0x28(%rsp),%rsp
-	movaps	%xmm6,(%rsp)
-	movaps	%xmm7,0x10(%rsp)
-___
-$code.=<<___;
+.cfi_push	%r15
+.Lmul4x_prologue:
+
 	.byte	0x67
-	mov	${num}d,%r10d
-	shl	\$3,${num}d
-	shl	\$3+2,%r10d		# 4*$num
+	shl	\$3,${num}d		# convert $num to bytes
+	lea	($num,$num,2),%r10	# 3*$num in bytes
 	neg	$num			# -$num
 
 	##############################################################
-	# ensure that stack frame doesn't alias with $aptr+4*$num
-	# modulo 4096, which covers ret[num], am[num] and n[2*num]
-	# (see bn_exp.c). this is done to allow memory disambiguation
-	# logic do its magic. [excessive frame is allocated in order
-	# to allow bn_from_mont8x to clear it.]
+	# Ensure that stack frame doesn't alias with $rptr+3*$num
+	# modulo 4096, which covers ret[num], am[num] and n[num]
+	# (see bn_exp.c). This is done to allow memory disambiguation
+	# logic do its magic. [Extra [num] is allocated in order
+	# to align with bn_power5's frame, which is cleansed after
+	# completing exponentiation. Extra 256 bytes is for power mask
+	# calculated from 7th argument, the index.]
 	#
-	lea	-64(%rsp,$num,2),%r11
-	sub	$ap,%r11
+	lea	-320(%rsp,$num,2),%r11
+	mov	%rsp,%rbp
+	sub	$rp,%r11
 	and	\$4095,%r11
 	cmp	%r11,%r10
 	jb	.Lmul4xsp_alt
-	sub	%r11,%rsp		# align with $ap
-	lea	-64(%rsp,$num,2),%rsp	# alloca(128+num*8)
+	sub	%r11,%rbp		# align with $rp
+	lea	-320(%rbp,$num,2),%rbp	# future alloca(frame+2*num*8+256)
 	jmp	.Lmul4xsp_done
 
 .align	32
 .Lmul4xsp_alt:
-	lea	4096-64(,$num,2),%r10
-	lea	-64(%rsp,$num,2),%rsp	# alloca(128+num*8)
+	lea	4096-320(,$num,2),%r10
+	lea	-320(%rbp,$num,2),%rbp	# future alloca(frame+2*num*8+256)
 	sub	%r10,%r11
 	mov	\$0,%r10
 	cmovc	%r10,%r11
-	sub	%r11,%rsp
+	sub	%r11,%rbp
 .Lmul4xsp_done:
-	and	\$-64,%rsp
+	and	\$-64,%rbp
+	mov	%rsp,%r11
+	sub	%rbp,%r11
+	and	\$-4096,%r11
+	lea	(%rbp,%r11),%rsp
+	mov	(%rsp),%r10
+	cmp	%rbp,%rsp
+	ja	.Lmul4x_page_walk
+	jmp	.Lmul4x_page_walk_done
+
+.Lmul4x_page_walk:
+	lea	-4096(%rsp),%rsp
+	mov	(%rsp),%r10
+	cmp	%rbp,%rsp
+	ja	.Lmul4x_page_walk
+.Lmul4x_page_walk_done:
+
 	neg	$num
 
 	mov	%rax,40(%rsp)
+.cfi_cfa_expression	%rsp+40,deref,+8
 .Lmul4x_body:
 
 	call	mul4x_internal
 
 	mov	40(%rsp),%rsi		# restore %rsp
+.cfi_def_cfa	%rsi,8
 	mov	\$1,%rax
-___
-$code.=<<___ if ($win64);
-	movaps	-88(%rsi),%xmm6
-	movaps	-72(%rsi),%xmm7
-___
-$code.=<<___;
+
 	mov	-48(%rsi),%r15
+.cfi_restore	%r15
 	mov	-40(%rsi),%r14
+.cfi_restore	%r14
 	mov	-32(%rsi),%r13
+.cfi_restore	%r13
 	mov	-24(%rsi),%r12
+.cfi_restore	%r12
 	mov	-16(%rsi),%rbp
+.cfi_restore	%rbp
 	mov	-8(%rsi),%rbx
+.cfi_restore	%rbx
 	lea	(%rsi),%rsp
+.cfi_def_cfa_register	%rsp
 .Lmul4x_epilogue:
 	ret
+.cfi_endproc
 .size	bn_mul4x_mont_gather5,.-bn_mul4x_mont_gather5
 
 .type	mul4x_internal,\@abi-omnipotent
 .align	32
 mul4x_internal:
-	shl	\$5,$num
-	mov	`($win64?56:8)`(%rax),%r10d	# load 7th argument
-	lea	256(%rdx,$num),%r13
+	shl	\$5,$num		# $num was in bytes
+	movd	`($win64?56:8)`(%rax),%xmm5	# load 7th argument, index
+	lea	.Linc(%rip),%rax
+	lea	128(%rdx,$num),%r13	# end of powers table (+size optimization)
 	shr	\$5,$num		# restore $num
 ___
 		$bp="%r12";
@@ -456,44 +570,92 @@
 		$N=$STRIDE/4;		# should match cache line size
 		$tp=$i;
 $code.=<<___;
-	mov	%r10,%r11
-	shr	\$`log($N/8)/log(2)`,%r10
-	and	\$`$N/8-1`,%r11
-	not	%r10
-	lea	.Lmagic_masks(%rip),%rax
-	and	\$`2**5/($N/8)-1`,%r10	# 5 is "window size"
-	lea	96(%rdx,%r11,8),$bp	# pointer within 1st cache line
-	movq	0(%rax,%r10,8),%xmm4	# set of masks denoting which
-	movq	8(%rax,%r10,8),%xmm5	# cache line contains element
-	add	\$7,%r11
-	movq	16(%rax,%r10,8),%xmm6	# denoted by 7th argument
-	movq	24(%rax,%r10,8),%xmm7
-	and	\$7,%r11
+	movdqa	0(%rax),%xmm0		# 00000001000000010000000000000000
+	movdqa	16(%rax),%xmm1		# 00000002000000020000000200000002
+	lea	88-112(%rsp,$num),%r10	# place the mask after tp[num+1] (+ICache optimization)
+	lea	128(%rdx),$bp		# size optimization
 
-	movq	`0*$STRIDE/4-96`($bp),%xmm0
-	lea	$STRIDE($bp),$tp	# borrow $tp
-	movq	`1*$STRIDE/4-96`($bp),%xmm1
-	pand	%xmm4,%xmm0
-	movq	`2*$STRIDE/4-96`($bp),%xmm2
-	pand	%xmm5,%xmm1
-	movq	`3*$STRIDE/4-96`($bp),%xmm3
-	pand	%xmm6,%xmm2
+	pshufd	\$0,%xmm5,%xmm5		# broadcast index
+	movdqa	%xmm1,%xmm4
+	.byte	0x67,0x67
+	movdqa	%xmm1,%xmm2
+___
+########################################################################
+# calculate mask by comparing 0..31 to index and save result to stack
+#
+$code.=<<___;
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0		# compare to 1,0
 	.byte	0x67
-	por	%xmm1,%xmm0
-	movq	`0*$STRIDE/4-96`($tp),%xmm1
+	movdqa	%xmm4,%xmm3
+___
+for($i=0;$i<$STRIDE/16-4;$i+=4) {
+$code.=<<___;
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1		# compare to 3,2
+	movdqa	%xmm0,`16*($i+0)+112`(%r10)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2		# compare to 5,4
+	movdqa	%xmm1,`16*($i+1)+112`(%r10)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3		# compare to 7,6
+	movdqa	%xmm2,`16*($i+2)+112`(%r10)
+	movdqa	%xmm4,%xmm2
+
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,`16*($i+3)+112`(%r10)
+	movdqa	%xmm4,%xmm3
+___
+}
+$code.=<<___;				# last iteration can be optimized
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,`16*($i+0)+112`(%r10)
+
+	paddd	%xmm2,%xmm3
 	.byte	0x67
-	pand	%xmm7,%xmm3
-	.byte	0x67
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,`16*($i+1)+112`(%r10)
+
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,`16*($i+2)+112`(%r10)
+	pand	`16*($i+0)-128`($bp),%xmm0	# while it's still in register
+
+	pand	`16*($i+1)-128`($bp),%xmm1
+	pand	`16*($i+2)-128`($bp),%xmm2
+	movdqa	%xmm3,`16*($i+3)+112`(%r10)
+	pand	`16*($i+3)-128`($bp),%xmm3
 	por	%xmm2,%xmm0
-	movq	`1*$STRIDE/4-96`($tp),%xmm2
-	.byte	0x67
-	pand	%xmm4,%xmm1
-	.byte	0x67
-	por	%xmm3,%xmm0
-	movq	`2*$STRIDE/4-96`($tp),%xmm3
-
+	por	%xmm3,%xmm1
+___
+for($i=0;$i<$STRIDE/16-4;$i+=4) {
+$code.=<<___;
+	movdqa	`16*($i+0)-128`($bp),%xmm4
+	movdqa	`16*($i+1)-128`($bp),%xmm5
+	movdqa	`16*($i+2)-128`($bp),%xmm2
+	pand	`16*($i+0)+112`(%r10),%xmm4
+	movdqa	`16*($i+3)-128`($bp),%xmm3
+	pand	`16*($i+1)+112`(%r10),%xmm5
+	por	%xmm4,%xmm0
+	pand	`16*($i+2)+112`(%r10),%xmm2
+	por	%xmm5,%xmm1
+	pand	`16*($i+3)+112`(%r10),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+___
+}
+$code.=<<___;
+	por	%xmm1,%xmm0
+	pshufd	\$0x4e,%xmm0,%xmm1
+	por	%xmm1,%xmm0
+	lea	$STRIDE($bp),$bp
 	movq	%xmm0,$m0		# m0=bp[0]
-	movq	`3*$STRIDE/4-96`($tp),%xmm0
+
 	mov	%r13,16+8(%rsp)		# save end of b[num]
 	mov	$rp, 56+8(%rsp)		# save $rp
 
@@ -507,26 +669,10 @@
 	mov	%rax,$A[0]
 	mov	($np),%rax
 
-	pand	%xmm5,%xmm2
-	pand	%xmm6,%xmm3
-	por	%xmm2,%xmm1
-
 	imulq	$A[0],$m1		# "tp[0]"*n0
-	##############################################################
-	# $tp is chosen so that writing to top-most element of the
-	# vector occurs just "above" references to powers table,
-	# "above" modulo cache-line size, which effectively precludes
-	# possibility of memory disambiguation logic failure when
-	# accessing the table.
-	# 
-	lea	64+8(%rsp,%r11,8),$tp
+	lea	64+8(%rsp),$tp
 	mov	%rdx,$A[1]
 
-	pand	%xmm7,%xmm0
-	por	%xmm3,%xmm1
-	lea	2*$STRIDE($bp),$bp
-	por	%xmm1,%xmm0
-
 	mulq	$m1			# np[0]*m1
 	add	%rax,$A[0]		# discarded
 	mov	8($ap,$num),%rax
@@ -535,7 +681,7 @@
 
 	mulq	$m0
 	add	%rax,$A[1]
-	mov	16*1($np),%rax		# interleaved with 0, therefore 16*n
+	mov	8*1($np),%rax
 	adc	\$0,%rdx
 	mov	%rdx,$A[0]
 
@@ -545,7 +691,7 @@
 	adc	\$0,%rdx
 	add	$A[1],$N[1]
 	lea	4*8($num),$j		# j=4
-	lea	16*4($np),$np
+	lea	8*4($np),$np
 	adc	\$0,%rdx
 	mov	$N[1],($tp)
 	mov	%rdx,$N[0]
@@ -555,7 +701,7 @@
 .L1st4x:
 	mulq	$m0			# ap[j]*bp[0]
 	add	%rax,$A[0]
-	mov	-16*2($np),%rax
+	mov	-8*2($np),%rax
 	lea	32($tp),$tp
 	adc	\$0,%rdx
 	mov	%rdx,$A[1]
@@ -571,7 +717,7 @@
 
 	mulq	$m0			# ap[j]*bp[0]
 	add	%rax,$A[1]
-	mov	-16*1($np),%rax
+	mov	-8*1($np),%rax
 	adc	\$0,%rdx
 	mov	%rdx,$A[0]
 
@@ -586,7 +732,7 @@
 
 	mulq	$m0			# ap[j]*bp[0]
 	add	%rax,$A[0]
-	mov	16*0($np),%rax
+	mov	8*0($np),%rax
 	adc	\$0,%rdx
 	mov	%rdx,$A[1]
 
@@ -601,7 +747,7 @@
 
 	mulq	$m0			# ap[j]*bp[0]
 	add	%rax,$A[1]
-	mov	16*1($np),%rax
+	mov	8*1($np),%rax
 	adc	\$0,%rdx
 	mov	%rdx,$A[0]
 
@@ -610,7 +756,7 @@
 	mov	16($ap,$j),%rax
 	adc	\$0,%rdx
 	add	$A[1],$N[1]		# np[j]*m1+ap[j]*bp[0]
-	lea	16*4($np),$np
+	lea	8*4($np),$np
 	adc	\$0,%rdx
 	mov	$N[1],($tp)		# tp[j-1]
 	mov	%rdx,$N[0]
@@ -620,7 +766,7 @@
 
 	mulq	$m0			# ap[j]*bp[0]
 	add	%rax,$A[0]
-	mov	-16*2($np),%rax
+	mov	-8*2($np),%rax
 	lea	32($tp),$tp
 	adc	\$0,%rdx
 	mov	%rdx,$A[1]
@@ -636,7 +782,7 @@
 
 	mulq	$m0			# ap[j]*bp[0]
 	add	%rax,$A[1]
-	mov	-16*1($np),%rax
+	mov	-8*1($np),%rax
 	adc	\$0,%rdx
 	mov	%rdx,$A[0]
 
@@ -649,8 +795,7 @@
 	mov	$N[1],-16($tp)		# tp[j-1]
 	mov	%rdx,$N[0]
 
-	movq	%xmm0,$m0		# bp[1]
-	lea	($np,$num,2),$np	# rewind $np
+	lea	($np,$num),$np		# rewind $np
 
 	xor	$N[1],$N[1]
 	add	$A[0],$N[0]
@@ -661,6 +806,33 @@
 
 .align	32
 .Louter4x:
+	lea	16+128($tp),%rdx	# where 256-byte mask is (+size optimization)
+	pxor	%xmm4,%xmm4
+	pxor	%xmm5,%xmm5
+___
+for($i=0;$i<$STRIDE/16;$i+=4) {
+$code.=<<___;
+	movdqa	`16*($i+0)-128`($bp),%xmm0
+	movdqa	`16*($i+1)-128`($bp),%xmm1
+	movdqa	`16*($i+2)-128`($bp),%xmm2
+	movdqa	`16*($i+3)-128`($bp),%xmm3
+	pand	`16*($i+0)-128`(%rdx),%xmm0
+	pand	`16*($i+1)-128`(%rdx),%xmm1
+	por	%xmm0,%xmm4
+	pand	`16*($i+2)-128`(%rdx),%xmm2
+	por	%xmm1,%xmm5
+	pand	`16*($i+3)-128`(%rdx),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+___
+}
+$code.=<<___;
+	por	%xmm5,%xmm4
+	pshufd	\$0x4e,%xmm4,%xmm0
+	por	%xmm4,%xmm0
+	lea	$STRIDE($bp),$bp
+	movq	%xmm0,$m0		# m0=bp[i]
+
 	mov	($tp,$num),$A[0]
 	mov	$n0,$m1
 	mulq	$m0			# ap[0]*bp[i]
@@ -668,25 +840,11 @@
 	mov	($np),%rax
 	adc	\$0,%rdx
 
-	movq	`0*$STRIDE/4-96`($bp),%xmm0
-	movq	`1*$STRIDE/4-96`($bp),%xmm1
-	pand	%xmm4,%xmm0
-	movq	`2*$STRIDE/4-96`($bp),%xmm2
-	pand	%xmm5,%xmm1
-	movq	`3*$STRIDE/4-96`($bp),%xmm3
-
 	imulq	$A[0],$m1		# tp[0]*n0
-	.byte	0x67
 	mov	%rdx,$A[1]
 	mov	$N[1],($tp)		# store upmost overflow bit
 
-	pand	%xmm6,%xmm2
-	por	%xmm1,%xmm0
-	pand	%xmm7,%xmm3
-	por	%xmm2,%xmm0
 	lea	($tp,$num),$tp		# rewind $tp
-	lea	$STRIDE($bp),$bp
-	por	%xmm3,%xmm0
 
 	mulq	$m1			# np[0]*m1
 	add	%rax,$A[0]		# "$N[0]", discarded
@@ -696,7 +854,7 @@
 
 	mulq	$m0			# ap[j]*bp[i]
 	add	%rax,$A[1]
-	mov	16*1($np),%rax		# interleaved with 0, therefore 16*n
+	mov	8*1($np),%rax
 	adc	\$0,%rdx
 	add	8($tp),$A[1]		# +tp[1]
 	adc	\$0,%rdx
@@ -708,7 +866,7 @@
 	adc	\$0,%rdx
 	add	$A[1],$N[1]		# np[j]*m1+ap[j]*bp[i]+tp[j]
 	lea	4*8($num),$j		# j=4
-	lea	16*4($np),$np
+	lea	8*4($np),$np
 	adc	\$0,%rdx
 	mov	%rdx,$N[0]
 	jmp	.Linner4x
@@ -717,7 +875,7 @@
 .Linner4x:
 	mulq	$m0			# ap[j]*bp[i]
 	add	%rax,$A[0]
-	mov	-16*2($np),%rax
+	mov	-8*2($np),%rax
 	adc	\$0,%rdx
 	add	16($tp),$A[0]		# ap[j]*bp[i]+tp[j]
 	lea	32($tp),$tp
@@ -735,7 +893,7 @@
 
 	mulq	$m0			# ap[j]*bp[i]
 	add	%rax,$A[1]
-	mov	-16*1($np),%rax
+	mov	-8*1($np),%rax
 	adc	\$0,%rdx
 	add	-8($tp),$A[1]
 	adc	\$0,%rdx
@@ -752,7 +910,7 @@
 
 	mulq	$m0			# ap[j]*bp[i]
 	add	%rax,$A[0]
-	mov	16*0($np),%rax
+	mov	8*0($np),%rax
 	adc	\$0,%rdx
 	add	($tp),$A[0]		# ap[j]*bp[i]+tp[j]
 	adc	\$0,%rdx
@@ -769,7 +927,7 @@
 
 	mulq	$m0			# ap[j]*bp[i]
 	add	%rax,$A[1]
-	mov	16*1($np),%rax
+	mov	8*1($np),%rax
 	adc	\$0,%rdx
 	add	8($tp),$A[1]
 	adc	\$0,%rdx
@@ -780,7 +938,7 @@
 	mov	16($ap,$j),%rax
 	adc	\$0,%rdx
 	add	$A[1],$N[1]
-	lea	16*4($np),$np
+	lea	8*4($np),$np
 	adc	\$0,%rdx
 	mov	$N[0],-8($tp)		# tp[j-1]
 	mov	%rdx,$N[0]
@@ -790,7 +948,7 @@
 
 	mulq	$m0			# ap[j]*bp[i]
 	add	%rax,$A[0]
-	mov	-16*2($np),%rax
+	mov	-8*2($np),%rax
 	adc	\$0,%rdx
 	add	16($tp),$A[0]		# ap[j]*bp[i]+tp[j]
 	lea	32($tp),$tp
@@ -809,7 +967,7 @@
 	mulq	$m0			# ap[j]*bp[i]
 	add	%rax,$A[1]
 	mov	$m1,%rax
-	mov	-16*1($np),$m1
+	mov	-8*1($np),$m1
 	adc	\$0,%rdx
 	add	-8($tp),$A[1]
 	adc	\$0,%rdx
@@ -824,9 +982,8 @@
 	mov	$N[0],-24($tp)		# tp[j-1]
 	mov	%rdx,$N[0]
 
-	movq	%xmm0,$m0		# bp[i+1]
 	mov	$N[1],-16($tp)		# tp[j-1]
-	lea	($np,$num,2),$np	# rewind $np
+	lea	($np,$num),$np		# rewind $np
 
 	xor	$N[1],$N[1]
 	add	$A[0],$N[0]
@@ -840,16 +997,23 @@
 ___
 if (1) {
 $code.=<<___;
+	xor	%rax,%rax
 	sub	$N[0],$m1		# compare top-most words
 	adc	$j,$j			# $j is zero
 	or	$j,$N[1]
-	xor	\$1,$N[1]
+	sub	$N[1],%rax		# %rax=-$N[1]
 	lea	($tp,$num),%rbx		# tptr in .sqr4x_sub
-	lea	($np,$N[1],8),%rbp	# nptr in .sqr4x_sub
+	mov	($np),%r12
+	lea	($np),%rbp		# nptr in .sqr4x_sub
 	mov	%r9,%rcx
-	sar	\$3+2,%rcx		# cf=0
+	sar	\$3+2,%rcx
 	mov	56+8(%rsp),%rdi		# rptr in .sqr4x_sub
-	jmp	.Lsqr4x_sub
+	dec	%r12			# so that after 'not' we get -n[0]
+	xor	%r10,%r10
+	mov	8*1(%rbp),%r13
+	mov	8*2(%rbp),%r14
+	mov	8*3(%rbp),%r15
+	jmp	.Lsqr4x_sub_entry
 ___
 } else {
 my @ri=("%rax",$bp,$m0,$m1);
@@ -901,7 +1065,7 @@
 my $nptr="%rcx";	# const BN_ULONG *nptr,
 my $n0  ="%r8";		# const BN_ULONG *n0);
 my $num ="%r9";		# int num, has to be divisible by 8
-			# int pwr 
+			# int pwr
 
 my ($i,$j,$tptr)=("%rbp","%rcx",$rptr);
 my @A0=("%r10","%r11");
@@ -913,60 +1077,80 @@
 .type	bn_power5,\@function,6
 .align	32
 bn_power5:
+.cfi_startproc
+	mov	%rsp,%rax
+.cfi_def_cfa_register	%rax
 ___
 $code.=<<___ if ($addx);
 	mov	OPENSSL_ia32cap_P+8(%rip),%r11d
-	and	\$0x80100,%r11d
-	cmp	\$0x80100,%r11d
+	and	\$0x80108,%r11d
+	cmp	\$0x80108,%r11d		# check for AD*X+BMI2+BMI1
 	je	.Lpowerx5_enter
 ___
 $code.=<<___;
-	mov	%rsp,%rax
 	push	%rbx
+.cfi_push	%rbx
 	push	%rbp
+.cfi_push	%rbp
 	push	%r12
+.cfi_push	%r12
 	push	%r13
+.cfi_push	%r13
 	push	%r14
+.cfi_push	%r14
 	push	%r15
-___
-$code.=<<___ if ($win64);
-	lea	-0x28(%rsp),%rsp
-	movaps	%xmm6,(%rsp)
-	movaps	%xmm7,0x10(%rsp)
-___
-$code.=<<___;
-	mov	${num}d,%r10d
+.cfi_push	%r15
+.Lpower5_prologue:
+
 	shl	\$3,${num}d		# convert $num to bytes
-	shl	\$3+2,%r10d		# 4*$num
+	lea	($num,$num,2),%r10d	# 3*$num
 	neg	$num
 	mov	($n0),$n0		# *n0
 
 	##############################################################
-	# ensure that stack frame doesn't alias with $aptr+4*$num
-	# modulo 4096, which covers ret[num], am[num] and n[2*num]
-	# (see bn_exp.c). this is done to allow memory disambiguation
-	# logic do its magic.
+	# Ensure that stack frame doesn't alias with $rptr+3*$num
+	# modulo 4096, which covers ret[num], am[num] and n[num]
+	# (see bn_exp.c). This is done to allow memory disambiguation
+	# logic do its magic. [Extra 256 bytes is for power mask
+	# calculated from 7th argument, the index.]
 	#
-	lea	-64(%rsp,$num,2),%r11
-	sub	$aptr,%r11
+	lea	-320(%rsp,$num,2),%r11
+	mov	%rsp,%rbp
+	sub	$rptr,%r11
 	and	\$4095,%r11
 	cmp	%r11,%r10
 	jb	.Lpwr_sp_alt
-	sub	%r11,%rsp		# align with $aptr
-	lea	-64(%rsp,$num,2),%rsp	# alloca(frame+2*$num)
+	sub	%r11,%rbp		# align with $aptr
+	lea	-320(%rbp,$num,2),%rbp	# future alloca(frame+2*num*8+256)
 	jmp	.Lpwr_sp_done
 
 .align	32
 .Lpwr_sp_alt:
-	lea	4096-64(,$num,2),%r10	# 4096-frame-2*$num
-	lea	-64(%rsp,$num,2),%rsp	# alloca(frame+2*$num)
+	lea	4096-320(,$num,2),%r10
+	lea	-320(%rbp,$num,2),%rbp	# future alloca(frame+2*num*8+256)
 	sub	%r10,%r11
 	mov	\$0,%r10
 	cmovc	%r10,%r11
-	sub	%r11,%rsp
+	sub	%r11,%rbp
 .Lpwr_sp_done:
-	and	\$-64,%rsp
-	mov	$num,%r10	
+	and	\$-64,%rbp
+	mov	%rsp,%r11
+	sub	%rbp,%r11
+	and	\$-4096,%r11
+	lea	(%rbp,%r11),%rsp
+	mov	(%rsp),%r10
+	cmp	%rbp,%rsp
+	ja	.Lpwr_page_walk
+	jmp	.Lpwr_page_walk_done
+
+.Lpwr_page_walk:
+	lea	-4096(%rsp),%rsp
+	mov	(%rsp),%r10
+	cmp	%rbp,%rsp
+	ja	.Lpwr_page_walk
+.Lpwr_page_walk_done:
+
+	mov	$num,%r10
 	neg	$num
 
 	##############################################################
@@ -980,17 +1164,23 @@
 	#
 	mov	$n0,  32(%rsp)
 	mov	%rax, 40(%rsp)		# save original %rsp
+.cfi_cfa_expression	%rsp+40,deref,+8
 .Lpower5_body:
-	movq	$rptr,%xmm1		# save $rptr
+	movq	$rptr,%xmm1		# save $rptr, used in sqr8x
 	movq	$nptr,%xmm2		# save $nptr
-	movq	%r10, %xmm3		# -$num
+	movq	%r10, %xmm3		# -$num, used in sqr8x
 	movq	$bptr,%xmm4
 
 	call	__bn_sqr8x_internal
+	call	__bn_post4x_internal
 	call	__bn_sqr8x_internal
+	call	__bn_post4x_internal
 	call	__bn_sqr8x_internal
+	call	__bn_post4x_internal
 	call	__bn_sqr8x_internal
+	call	__bn_post4x_internal
 	call	__bn_sqr8x_internal
+	call	__bn_post4x_internal
 
 	movq	%xmm2,$nptr
 	movq	%xmm4,$bptr
@@ -1001,16 +1191,25 @@
 	call	mul4x_internal
 
 	mov	40(%rsp),%rsi		# restore %rsp
+.cfi_def_cfa	%rsi,8
 	mov	\$1,%rax
 	mov	-48(%rsi),%r15
+.cfi_restore	%r15
 	mov	-40(%rsi),%r14
+.cfi_restore	%r14
 	mov	-32(%rsi),%r13
+.cfi_restore	%r13
 	mov	-24(%rsi),%r12
+.cfi_restore	%r12
 	mov	-16(%rsi),%rbp
+.cfi_restore	%rbp
 	mov	-8(%rsi),%rbx
+.cfi_restore	%rbx
 	lea	(%rsi),%rsp
+.cfi_def_cfa_register	%rsp
 .Lpower5_epilogue:
 	ret
+.cfi_endproc
 .size	bn_power5,.-bn_power5
 
 .globl	bn_sqr8x_internal
@@ -1551,9 +1750,9 @@
 
 $code.=<<___;
 	movq	%xmm2,$nptr
-sqr8x_reduction:
+__bn_sqr8x_reduction:
 	xor	%rax,%rax
-	lea	($nptr,$num,2),%rcx	# end of n[]
+	lea	($nptr,$num),%rcx	# end of n[]
 	lea	48+8(%rsp,$num,2),%rdx	# end of t[] buffer
 	mov	%rcx,0+8(%rsp)
 	lea	48+8(%rsp,$num),$tptr	# end of initial t[] window
@@ -1579,21 +1778,21 @@
 	.byte	0x67
 	mov	$m0,%r8
 	imulq	32+8(%rsp),$m0		# n0*a[0]
-	mov	16*0($nptr),%rax	# n[0]
+	mov	8*0($nptr),%rax		# n[0]
 	mov	\$8,%ecx
 	jmp	.L8x_reduce
 
 .align	32
 .L8x_reduce:
 	mulq	$m0
-	 mov	16*1($nptr),%rax	# n[1]
+	 mov	8*1($nptr),%rax		# n[1]
 	neg	%r8
 	mov	%rdx,%r8
 	adc	\$0,%r8
 
 	mulq	$m0
 	add	%rax,%r9
-	 mov	16*2($nptr),%rax
+	 mov	8*2($nptr),%rax
 	adc	\$0,%rdx
 	add	%r9,%r8
 	 mov	$m0,48-8+8(%rsp,%rcx,8)	# put aside n0*a[i]
@@ -1602,7 +1801,7 @@
 
 	mulq	$m0
 	add	%rax,%r10
-	 mov	16*3($nptr),%rax
+	 mov	8*3($nptr),%rax
 	adc	\$0,%rdx
 	add	%r10,%r9
 	 mov	32+8(%rsp),$carry	# pull n0, borrow $carry
@@ -1611,7 +1810,7 @@
 
 	mulq	$m0
 	add	%rax,%r11
-	 mov	16*4($nptr),%rax
+	 mov	8*4($nptr),%rax
 	adc	\$0,%rdx
 	 imulq	%r8,$carry		# modulo-scheduled
 	add	%r11,%r10
@@ -1620,7 +1819,7 @@
 
 	mulq	$m0
 	add	%rax,%r12
-	 mov	16*5($nptr),%rax
+	 mov	8*5($nptr),%rax
 	adc	\$0,%rdx
 	add	%r12,%r11
 	mov	%rdx,%r12
@@ -1628,7 +1827,7 @@
 
 	mulq	$m0
 	add	%rax,%r13
-	 mov	16*6($nptr),%rax
+	 mov	8*6($nptr),%rax
 	adc	\$0,%rdx
 	add	%r13,%r12
 	mov	%rdx,%r13
@@ -1636,7 +1835,7 @@
 
 	mulq	$m0
 	add	%rax,%r14
-	 mov	16*7($nptr),%rax
+	 mov	8*7($nptr),%rax
 	adc	\$0,%rdx
 	add	%r14,%r13
 	mov	%rdx,%r14
@@ -1645,7 +1844,7 @@
 	mulq	$m0
 	 mov	$carry,$m0		# n0*a[i]
 	add	%rax,%r15
-	 mov	16*0($nptr),%rax	# n[0]
+	 mov	8*0($nptr),%rax		# n[0]
 	adc	\$0,%rdx
 	add	%r15,%r14
 	mov	%rdx,%r15
@@ -1654,7 +1853,7 @@
 	dec	%ecx
 	jnz	.L8x_reduce
 
-	lea	16*8($nptr),$nptr
+	lea	8*8($nptr),$nptr
 	xor	%rax,%rax
 	mov	8+8(%rsp),%rdx		# pull end of t[]
 	cmp	0+8(%rsp),$nptr		# end of n[]?
@@ -1673,21 +1872,21 @@
 
 	mov	48+56+8(%rsp),$m0	# pull n0*a[0]
 	mov	\$8,%ecx
-	mov	16*0($nptr),%rax
+	mov	8*0($nptr),%rax
 	jmp	.L8x_tail
 
 .align	32
 .L8x_tail:
 	mulq	$m0
 	add	%rax,%r8
-	 mov	16*1($nptr),%rax
+	 mov	8*1($nptr),%rax
 	 mov	%r8,($tptr)		# save result
 	mov	%rdx,%r8
 	adc	\$0,%r8
 
 	mulq	$m0
 	add	%rax,%r9
-	 mov	16*2($nptr),%rax
+	 mov	8*2($nptr),%rax
 	adc	\$0,%rdx
 	add	%r9,%r8
 	 lea	8($tptr),$tptr		# $tptr++
@@ -1696,7 +1895,7 @@
 
 	mulq	$m0
 	add	%rax,%r10
-	 mov	16*3($nptr),%rax
+	 mov	8*3($nptr),%rax
 	adc	\$0,%rdx
 	add	%r10,%r9
 	mov	%rdx,%r10
@@ -1704,7 +1903,7 @@
 
 	mulq	$m0
 	add	%rax,%r11
-	 mov	16*4($nptr),%rax
+	 mov	8*4($nptr),%rax
 	adc	\$0,%rdx
 	add	%r11,%r10
 	mov	%rdx,%r11
@@ -1712,7 +1911,7 @@
 
 	mulq	$m0
 	add	%rax,%r12
-	 mov	16*5($nptr),%rax
+	 mov	8*5($nptr),%rax
 	adc	\$0,%rdx
 	add	%r12,%r11
 	mov	%rdx,%r12
@@ -1720,7 +1919,7 @@
 
 	mulq	$m0
 	add	%rax,%r13
-	 mov	16*6($nptr),%rax
+	 mov	8*6($nptr),%rax
 	adc	\$0,%rdx
 	add	%r13,%r12
 	mov	%rdx,%r13
@@ -1728,7 +1927,7 @@
 
 	mulq	$m0
 	add	%rax,%r14
-	 mov	16*7($nptr),%rax
+	 mov	8*7($nptr),%rax
 	adc	\$0,%rdx
 	add	%r14,%r13
 	mov	%rdx,%r14
@@ -1739,14 +1938,14 @@
 	add	%rax,%r15
 	adc	\$0,%rdx
 	add	%r15,%r14
-	 mov	16*0($nptr),%rax	# pull n[0]
+	 mov	8*0($nptr),%rax		# pull n[0]
 	mov	%rdx,%r15
 	adc	\$0,%r15
 
 	dec	%ecx
 	jnz	.L8x_tail
 
-	lea	16*8($nptr),$nptr
+	lea	8*8($nptr),$nptr
 	mov	8+8(%rsp),%rdx		# pull end of t[]
 	cmp	0+8(%rsp),$nptr		# end of n[]?
 	jae	.L8x_tail_done		# break out of loop
@@ -1769,6 +1968,7 @@
 
 .align	32
 .L8x_tail_done:
+	xor	%rax,%rax
 	add	(%rdx),%r8		# can this overflow?
 	adc	\$0,%r9
 	adc	\$0,%r10
@@ -1776,10 +1976,8 @@
 	adc	\$0,%r12
 	adc	\$0,%r13
 	adc	\$0,%r14
-	adc	\$0,%r15		# can't overflow, because we
-					# started with "overhung" part
-					# of multiplication
-	xor	%rax,%rax
+	adc	\$0,%r15
+	adc	\$0,%rax
 
 	neg	$carry
 .L8x_no_tail:
@@ -1792,7 +1990,7 @@
 	adc	8*6($tptr),%r14
 	adc	8*7($tptr),%r15
 	adc	\$0,%rax		# top-most carry
-	 mov	-16($nptr),%rcx		# np[num-1]
+	 mov	-8($nptr),%rcx		# np[num-1]
 	 xor	$carry,$carry
 
 	movq	%xmm2,$nptr		# restore $nptr
@@ -1810,6 +2008,8 @@
 
 	cmp	%rdx,$tptr		# end of t[]?
 	jb	.L8x_reduction_loop
+	ret
+.size	bn_sqr8x_internal,.-bn_sqr8x_internal
 ___
 }
 ##############################################################
@@ -1818,48 +2018,62 @@
 {
 my ($tptr,$nptr)=("%rbx","%rbp");
 $code.=<<___;
-	#xor	%rsi,%rsi		# %rsi was $carry above
-	sub	%r15,%rcx		# compare top-most words
-	lea	(%rdi,$num),$tptr	# %rdi was $tptr above
-	adc	%rsi,%rsi
-	mov	$num,%rcx
-	or	%rsi,%rax
-	movq	%xmm1,$rptr		# restore $rptr
-	xor	\$1,%rax
-	movq	%xmm1,$aptr		# prepare for back-to-back call
-	lea	($nptr,%rax,8),$nptr
-	sar	\$3+2,%rcx		# cf=0
-	jmp	.Lsqr4x_sub
-
+.type	__bn_post4x_internal,\@abi-omnipotent
 .align	32
+__bn_post4x_internal:
+	mov	8*0($nptr),%r12
+	lea	(%rdi,$num),$tptr	# %rdi was $tptr above
+	mov	$num,%rcx
+	movq	%xmm1,$rptr		# restore $rptr
+	neg	%rax
+	movq	%xmm1,$aptr		# prepare for back-to-back call
+	sar	\$3+2,%rcx
+	dec	%r12			# so that after 'not' we get -n[0]
+	xor	%r10,%r10
+	mov	8*1($nptr),%r13
+	mov	8*2($nptr),%r14
+	mov	8*3($nptr),%r15
+	jmp	.Lsqr4x_sub_entry
+
+.align	16
 .Lsqr4x_sub:
-	.byte	0x66
-	mov	8*0($tptr),%r12
-	mov	8*1($tptr),%r13
-	sbb	16*0($nptr),%r12
-	mov	8*2($tptr),%r14
-	sbb	16*1($nptr),%r13
-	mov	8*3($tptr),%r15
-	lea	8*4($tptr),$tptr
-	sbb	16*2($nptr),%r14
+	mov	8*0($nptr),%r12
+	mov	8*1($nptr),%r13
+	mov	8*2($nptr),%r14
+	mov	8*3($nptr),%r15
+.Lsqr4x_sub_entry:
+	lea	8*4($nptr),$nptr
+	not	%r12
+	not	%r13
+	not	%r14
+	not	%r15
+	and	%rax,%r12
+	and	%rax,%r13
+	and	%rax,%r14
+	and	%rax,%r15
+
+	neg	%r10			# mov %r10,%cf
+	adc	8*0($tptr),%r12
+	adc	8*1($tptr),%r13
+	adc	8*2($tptr),%r14
+	adc	8*3($tptr),%r15
 	mov	%r12,8*0($rptr)
-	sbb	16*3($nptr),%r15
-	lea	16*4($nptr),$nptr
+	lea	8*4($tptr),$tptr
 	mov	%r13,8*1($rptr)
+	sbb	%r10,%r10		# mov %cf,%r10
 	mov	%r14,8*2($rptr)
 	mov	%r15,8*3($rptr)
 	lea	8*4($rptr),$rptr
 
 	inc	%rcx			# pass %cf
 	jnz	.Lsqr4x_sub
+
+	mov	$num,%r10		# prepare for back-to-back call
+	neg	$num			# restore $num
+	ret
+.size	__bn_post4x_internal,.-__bn_post4x_internal
 ___
 }
-$code.=<<___;
-	mov	$num,%r10		# prepare for back-to-back call
-	neg	$num			# restore $num	
-	ret
-.size	bn_sqr8x_internal,.-bn_sqr8x_internal
-___
 {
 $code.=<<___;
 .globl	bn_from_montgomery
@@ -1875,54 +2089,73 @@
 .type	bn_from_mont8x,\@function,6
 .align	32
 bn_from_mont8x:
+.cfi_startproc
 	.byte	0x67
 	mov	%rsp,%rax
+.cfi_def_cfa_register	%rax
 	push	%rbx
+.cfi_push	%rbx
 	push	%rbp
+.cfi_push	%rbp
 	push	%r12
+.cfi_push	%r12
 	push	%r13
+.cfi_push	%r13
 	push	%r14
+.cfi_push	%r14
 	push	%r15
-___
-$code.=<<___ if ($win64);
-	lea	-0x28(%rsp),%rsp
-	movaps	%xmm6,(%rsp)
-	movaps	%xmm7,0x10(%rsp)
-___
-$code.=<<___;
-	.byte	0x67
-	mov	${num}d,%r10d
+.cfi_push	%r15
+.Lfrom_prologue:
+
 	shl	\$3,${num}d		# convert $num to bytes
-	shl	\$3+2,%r10d		# 4*$num
+	lea	($num,$num,2),%r10	# 3*$num in bytes
 	neg	$num
 	mov	($n0),$n0		# *n0
 
 	##############################################################
-	# ensure that stack frame doesn't alias with $aptr+4*$num
-	# modulo 4096, which covers ret[num], am[num] and n[2*num]
-	# (see bn_exp.c). this is done to allow memory disambiguation
-	# logic do its magic.
+	# Ensure that stack frame doesn't alias with $rptr+3*$num
+	# modulo 4096, which covers ret[num], am[num] and n[num]
+	# (see bn_exp.c). The stack is allocated to aligned with
+	# bn_power5's frame, and as bn_from_montgomery happens to be
+	# last operation, we use the opportunity to cleanse it.
 	#
-	lea	-64(%rsp,$num,2),%r11
-	sub	$aptr,%r11
+	lea	-320(%rsp,$num,2),%r11
+	mov	%rsp,%rbp
+	sub	$rptr,%r11
 	and	\$4095,%r11
 	cmp	%r11,%r10
 	jb	.Lfrom_sp_alt
-	sub	%r11,%rsp		# align with $aptr
-	lea	-64(%rsp,$num,2),%rsp	# alloca(frame+2*$num)
+	sub	%r11,%rbp		# align with $aptr
+	lea	-320(%rbp,$num,2),%rbp	# future alloca(frame+2*$num*8+256)
 	jmp	.Lfrom_sp_done
 
 .align	32
 .Lfrom_sp_alt:
-	lea	4096-64(,$num,2),%r10	# 4096-frame-2*$num
-	lea	-64(%rsp,$num,2),%rsp	# alloca(frame+2*$num)
+	lea	4096-320(,$num,2),%r10
+	lea	-320(%rbp,$num,2),%rbp	# future alloca(frame+2*$num*8+256)
 	sub	%r10,%r11
 	mov	\$0,%r10
 	cmovc	%r10,%r11
-	sub	%r11,%rsp
+	sub	%r11,%rbp
 .Lfrom_sp_done:
-	and	\$-64,%rsp
-	mov	$num,%r10	
+	and	\$-64,%rbp
+	mov	%rsp,%r11
+	sub	%rbp,%r11
+	and	\$-4096,%r11
+	lea	(%rbp,%r11),%rsp
+	mov	(%rsp),%r10
+	cmp	%rbp,%rsp
+	ja	.Lfrom_page_walk
+	jmp	.Lfrom_page_walk_done
+
+.Lfrom_page_walk:
+	lea	-4096(%rsp),%rsp
+	mov	(%rsp),%r10
+	cmp	%rbp,%rsp
+	ja	.Lfrom_page_walk
+.Lfrom_page_walk_done:
+
+	mov	$num,%r10
 	neg	$num
 
 	##############################################################
@@ -1936,6 +2169,7 @@
 	#
 	mov	$n0,  32(%rsp)
 	mov	%rax, 40(%rsp)		# save original %rsp
+.cfi_cfa_expression	%rsp+40,deref,+8
 .Lfrom_body:
 	mov	$num,%r11
 	lea	48(%rsp),%rax
@@ -1969,31 +2203,33 @@
 ___
 $code.=<<___ if ($addx);
 	mov	OPENSSL_ia32cap_P+8(%rip),%r11d
-	and	\$0x80100,%r11d
-	cmp	\$0x80100,%r11d
+	and	\$0x80108,%r11d
+	cmp	\$0x80108,%r11d		# check for AD*X+BMI2+BMI1
 	jne	.Lfrom_mont_nox
 
 	lea	(%rax,$num),$rptr
-	call	sqrx8x_reduction
+	call	__bn_sqrx8x_reduction
+	call	__bn_postx4x_internal
 
 	pxor	%xmm0,%xmm0
 	lea	48(%rsp),%rax
-	mov	40(%rsp),%rsi		# restore %rsp
 	jmp	.Lfrom_mont_zero
 
 .align	32
 .Lfrom_mont_nox:
 ___
 $code.=<<___;
-	call	sqr8x_reduction
+	call	__bn_sqr8x_reduction
+	call	__bn_post4x_internal
 
 	pxor	%xmm0,%xmm0
 	lea	48(%rsp),%rax
-	mov	40(%rsp),%rsi		# restore %rsp
 	jmp	.Lfrom_mont_zero
 
 .align	32
 .Lfrom_mont_zero:
+	mov	40(%rsp),%rsi		# restore %rsp
+.cfi_def_cfa	%rsi,8
 	movdqa	%xmm0,16*0(%rax)
 	movdqa	%xmm0,16*1(%rax)
 	movdqa	%xmm0,16*2(%rax)
@@ -2004,14 +2240,22 @@
 
 	mov	\$1,%rax
 	mov	-48(%rsi),%r15
+.cfi_restore	%r15
 	mov	-40(%rsi),%r14
+.cfi_restore	%r14
 	mov	-32(%rsi),%r13
+.cfi_restore	%r13
 	mov	-24(%rsi),%r12
+.cfi_restore	%r12
 	mov	-16(%rsi),%rbp
+.cfi_restore	%rbp
 	mov	-8(%rsi),%rbx
+.cfi_restore	%rbx
 	lea	(%rsi),%rsp
+.cfi_def_cfa_register	%rsp
 .Lfrom_epilogue:
 	ret
+.cfi_endproc
 .size	bn_from_mont8x,.-bn_from_mont8x
 ___
 }
@@ -2024,55 +2268,73 @@
 .type	bn_mulx4x_mont_gather5,\@function,6
 .align	32
 bn_mulx4x_mont_gather5:
-.Lmulx4x_enter:
-	.byte	0x67
+.cfi_startproc
 	mov	%rsp,%rax
+.cfi_def_cfa_register	%rax
+.Lmulx4x_enter:
 	push	%rbx
+.cfi_push	%rbx
 	push	%rbp
+.cfi_push	%rbp
 	push	%r12
+.cfi_push	%r12
 	push	%r13
+.cfi_push	%r13
 	push	%r14
+.cfi_push	%r14
 	push	%r15
-___
-$code.=<<___ if ($win64);
-	lea	-0x28(%rsp),%rsp
-	movaps	%xmm6,(%rsp)
-	movaps	%xmm7,0x10(%rsp)
-___
-$code.=<<___;
-	.byte	0x67
-	mov	${num}d,%r10d
+.cfi_push	%r15
+.Lmulx4x_prologue:
+
 	shl	\$3,${num}d		# convert $num to bytes
-	shl	\$3+2,%r10d		# 4*$num
+	lea	($num,$num,2),%r10	# 3*$num in bytes
 	neg	$num			# -$num
 	mov	($n0),$n0		# *n0
 
 	##############################################################
-	# ensure that stack frame doesn't alias with $aptr+4*$num
-	# modulo 4096, which covers a[num], ret[num] and n[2*num]
-	# (see bn_exp.c). this is done to allow memory disambiguation
-	# logic do its magic. [excessive frame is allocated in order
-	# to allow bn_from_mont8x to clear it.]
+	# Ensure that stack frame doesn't alias with $rptr+3*$num
+	# modulo 4096, which covers ret[num], am[num] and n[num]
+	# (see bn_exp.c). This is done to allow memory disambiguation
+	# logic do its magic. [Extra [num] is allocated in order
+	# to align with bn_power5's frame, which is cleansed after
+	# completing exponentiation. Extra 256 bytes is for power mask
+	# calculated from 7th argument, the index.]
 	#
-	lea	-64(%rsp,$num,2),%r11
-	sub	$ap,%r11
+	lea	-320(%rsp,$num,2),%r11
+	mov	%rsp,%rbp
+	sub	$rp,%r11
 	and	\$4095,%r11
 	cmp	%r11,%r10
 	jb	.Lmulx4xsp_alt
-	sub	%r11,%rsp		# align with $aptr
-	lea	-64(%rsp,$num,2),%rsp	# alloca(frame+$num)
+	sub	%r11,%rbp		# align with $aptr
+	lea	-320(%rbp,$num,2),%rbp	# future alloca(frame+2*$num*8+256)
 	jmp	.Lmulx4xsp_done
 
-.align	32
 .Lmulx4xsp_alt:
-	lea	4096-64(,$num,2),%r10	# 4096-frame-$num
-	lea	-64(%rsp,$num,2),%rsp	# alloca(frame+$num)
+	lea	4096-320(,$num,2),%r10
+	lea	-320(%rbp,$num,2),%rbp	# future alloca(frame+2*$num*8+256)
 	sub	%r10,%r11
 	mov	\$0,%r10
 	cmovc	%r10,%r11
-	sub	%r11,%rsp
-.Lmulx4xsp_done:	
-	and	\$-64,%rsp		# ensure alignment
+	sub	%r11,%rbp
+.Lmulx4xsp_done:
+	and	\$-64,%rbp		# ensure alignment
+	mov	%rsp,%r11
+	sub	%rbp,%r11
+	and	\$-4096,%r11
+	lea	(%rbp,%r11),%rsp
+	mov	(%rsp),%r10
+	cmp	%rbp,%rsp
+	ja	.Lmulx4x_page_walk
+	jmp	.Lmulx4x_page_walk_done
+
+.Lmulx4x_page_walk:
+	lea	-4096(%rsp),%rsp
+	mov	(%rsp),%r10
+	cmp	%rbp,%rsp
+	ja	.Lmulx4x_page_walk
+.Lmulx4x_page_walk_done:
+
 	##############################################################
 	# Stack layout
 	# +0	-num
@@ -2087,39 +2349,46 @@
 	#
 	mov	$n0, 32(%rsp)		# save *n0
 	mov	%rax,40(%rsp)		# save original %rsp
+.cfi_cfa_expression	%rsp+40,deref,+8
 .Lmulx4x_body:
 	call	mulx4x_internal
 
 	mov	40(%rsp),%rsi		# restore %rsp
+.cfi_def_cfa	%rsi,8
 	mov	\$1,%rax
-___
-$code.=<<___ if ($win64);
-	movaps	-88(%rsi),%xmm6
-	movaps	-72(%rsi),%xmm7
-___
-$code.=<<___;
+
 	mov	-48(%rsi),%r15
+.cfi_restore	%r15
 	mov	-40(%rsi),%r14
+.cfi_restore	%r14
 	mov	-32(%rsi),%r13
+.cfi_restore	%r13
 	mov	-24(%rsi),%r12
+.cfi_restore	%r12
 	mov	-16(%rsi),%rbp
+.cfi_restore	%rbp
 	mov	-8(%rsi),%rbx
+.cfi_restore	%rbx
 	lea	(%rsi),%rsp
+.cfi_def_cfa_register	%rsp
 .Lmulx4x_epilogue:
 	ret
+.cfi_endproc
 .size	bn_mulx4x_mont_gather5,.-bn_mulx4x_mont_gather5
 
 .type	mulx4x_internal,\@abi-omnipotent
 .align	32
 mulx4x_internal:
-	.byte	0x4c,0x89,0x8c,0x24,0x08,0x00,0x00,0x00	# mov	$num,8(%rsp)		# save -$num
-	.byte	0x67
+	mov	$num,8(%rsp)		# save -$num (it was in bytes)
+	mov	$num,%r10
 	neg	$num			# restore $num
 	shl	\$5,$num
-	lea	256($bp,$num),%r13
+	neg	%r10			# restore $num
+	lea	128($bp,$num),%r13	# end of powers table (+size optimization)
 	shr	\$5+5,$num
-	mov	`($win64?56:8)`(%rax),%r10d	# load 7th argument
+	movd	`($win64?56:8)`(%rax),%xmm5	# load 7th argument
 	sub	\$1,$num
+	lea	.Linc(%rip),%rax
 	mov	%r13,16+8(%rsp)		# end of b[num]
 	mov	$num,24+8(%rsp)		# inner counter
 	mov	$rp, 56+8(%rsp)		# save $rp
@@ -2130,52 +2399,92 @@
 my $STRIDE=2**5*8;		# 5 is "window size"
 my $N=$STRIDE/4;		# should match cache line size
 $code.=<<___;
-	mov	%r10,%r11
-	shr	\$`log($N/8)/log(2)`,%r10
-	and	\$`$N/8-1`,%r11
-	not	%r10
-	lea	.Lmagic_masks(%rip),%rax
-	and	\$`2**5/($N/8)-1`,%r10	# 5 is "window size"
-	lea	96($bp,%r11,8),$bptr	# pointer within 1st cache line
-	movq	0(%rax,%r10,8),%xmm4	# set of masks denoting which
-	movq	8(%rax,%r10,8),%xmm5	# cache line contains element
-	add	\$7,%r11
-	movq	16(%rax,%r10,8),%xmm6	# denoted by 7th argument
-	movq	24(%rax,%r10,8),%xmm7
-	and	\$7,%r11
+	movdqa	0(%rax),%xmm0		# 00000001000000010000000000000000
+	movdqa	16(%rax),%xmm1		# 00000002000000020000000200000002
+	lea	88-112(%rsp,%r10),%r10	# place the mask after tp[num+1] (+ICache optimizaton)
+	lea	128($bp),$bptr		# size optimization
 
-	movq	`0*$STRIDE/4-96`($bptr),%xmm0
-	lea	$STRIDE($bptr),$tptr	# borrow $tptr
-	movq	`1*$STRIDE/4-96`($bptr),%xmm1
-	pand	%xmm4,%xmm0
-	movq	`2*$STRIDE/4-96`($bptr),%xmm2
-	pand	%xmm5,%xmm1
-	movq	`3*$STRIDE/4-96`($bptr),%xmm3
-	pand	%xmm6,%xmm2
-	por	%xmm1,%xmm0
-	movq	`0*$STRIDE/4-96`($tptr),%xmm1
-	pand	%xmm7,%xmm3
+	pshufd	\$0,%xmm5,%xmm5		# broadcast index
+	movdqa	%xmm1,%xmm4
+	.byte	0x67
+	movdqa	%xmm1,%xmm2
+___
+########################################################################
+# calculate mask by comparing 0..31 to index and save result to stack
+#
+$code.=<<___;
+	.byte	0x67
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0		# compare to 1,0
+	movdqa	%xmm4,%xmm3
+___
+for($i=0;$i<$STRIDE/16-4;$i+=4) {
+$code.=<<___;
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1		# compare to 3,2
+	movdqa	%xmm0,`16*($i+0)+112`(%r10)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2		# compare to 5,4
+	movdqa	%xmm1,`16*($i+1)+112`(%r10)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3		# compare to 7,6
+	movdqa	%xmm2,`16*($i+2)+112`(%r10)
+	movdqa	%xmm4,%xmm2
+
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0
+	movdqa	%xmm3,`16*($i+3)+112`(%r10)
+	movdqa	%xmm4,%xmm3
+___
+}
+$code.=<<___;				# last iteration can be optimized
+	.byte	0x67
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1
+	movdqa	%xmm0,`16*($i+0)+112`(%r10)
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2
+	movdqa	%xmm1,`16*($i+1)+112`(%r10)
+
+	pcmpeqd	%xmm5,%xmm3
+	movdqa	%xmm2,`16*($i+2)+112`(%r10)
+
+	pand	`16*($i+0)-128`($bptr),%xmm0	# while it's still in register
+	pand	`16*($i+1)-128`($bptr),%xmm1
+	pand	`16*($i+2)-128`($bptr),%xmm2
+	movdqa	%xmm3,`16*($i+3)+112`(%r10)
+	pand	`16*($i+3)-128`($bptr),%xmm3
 	por	%xmm2,%xmm0
-	movq	`1*$STRIDE/4-96`($tptr),%xmm2
-	por	%xmm3,%xmm0
-	.byte	0x67,0x67
-	pand	%xmm4,%xmm1
-	movq	`2*$STRIDE/4-96`($tptr),%xmm3
-
+	por	%xmm3,%xmm1
+___
+for($i=0;$i<$STRIDE/16-4;$i+=4) {
+$code.=<<___;
+	movdqa	`16*($i+0)-128`($bptr),%xmm4
+	movdqa	`16*($i+1)-128`($bptr),%xmm5
+	movdqa	`16*($i+2)-128`($bptr),%xmm2
+	pand	`16*($i+0)+112`(%r10),%xmm4
+	movdqa	`16*($i+3)-128`($bptr),%xmm3
+	pand	`16*($i+1)+112`(%r10),%xmm5
+	por	%xmm4,%xmm0
+	pand	`16*($i+2)+112`(%r10),%xmm2
+	por	%xmm5,%xmm1
+	pand	`16*($i+3)+112`(%r10),%xmm3
+	por	%xmm2,%xmm0
+	por	%xmm3,%xmm1
+___
+}
+$code.=<<___;
+	pxor	%xmm1,%xmm0
+	pshufd	\$0x4e,%xmm0,%xmm1
+	por	%xmm1,%xmm0
+	lea	$STRIDE($bptr),$bptr
 	movq	%xmm0,%rdx		# bp[0]
-	movq	`3*$STRIDE/4-96`($tptr),%xmm0
-	lea	2*$STRIDE($bptr),$bptr	# next &b[i]
-	pand	%xmm5,%xmm2
-	.byte	0x67,0x67
-	pand	%xmm6,%xmm3
-	##############################################################
-	# $tptr is chosen so that writing to top-most element of the
-	# vector occurs just "above" references to powers table,
-	# "above" modulo cache-line size, which effectively precludes
-	# possibility of memory disambiguation logic failure when
-	# accessing the table.
-	# 
-	lea	64+8*4+8(%rsp,%r11,8),$tptr
+	lea	64+8*4+8(%rsp),$tptr
 
 	mov	%rdx,$bi
 	mulx	0*8($aptr),$mi,%rax	# a[0]*b[0]
@@ -2191,37 +2500,31 @@
 	xor	$zero,$zero		# cf=0, of=0
 	mov	$mi,%rdx
 
-	por	%xmm2,%xmm1
-	pand	%xmm7,%xmm0
-	por	%xmm3,%xmm1
 	mov	$bptr,8+8(%rsp)		# off-load &b[i]
-	por	%xmm1,%xmm0
 
-	.byte	0x48,0x8d,0xb6,0x20,0x00,0x00,0x00	# lea	4*8($aptr),$aptr
+	lea	4*8($aptr),$aptr
 	adcx	%rax,%r13
 	adcx	$zero,%r14		# cf=0
 
-	mulx	0*16($nptr),%rax,%r10
+	mulx	0*8($nptr),%rax,%r10
 	adcx	%rax,%r15		# discarded
 	adox	%r11,%r10
-	mulx	1*16($nptr),%rax,%r11
+	mulx	1*8($nptr),%rax,%r11
 	adcx	%rax,%r10
 	adox	%r12,%r11
-	mulx	2*16($nptr),%rax,%r12
+	mulx	2*8($nptr),%rax,%r12
 	mov	24+8(%rsp),$bptr	# counter value
-	.byte	0x66
 	mov	%r10,-8*4($tptr)
 	adcx	%rax,%r11
 	adox	%r13,%r12
-	mulx	3*16($nptr),%rax,%r15
-	 .byte	0x67,0x67
+	mulx	3*8($nptr),%rax,%r15
 	 mov	$bi,%rdx
 	mov	%r11,-8*3($tptr)
 	adcx	%rax,%r12
 	adox	$zero,%r15		# of=0
-	.byte	0x48,0x8d,0x89,0x40,0x00,0x00,0x00	# lea	4*16($nptr),$nptr
+	lea	4*8($nptr),$nptr
 	mov	%r12,-8*2($tptr)
-	#jmp	.Lmulx4x_1st
+	jmp	.Lmulx4x_1st
 
 .align	32
 .Lmulx4x_1st:
@@ -2241,30 +2544,29 @@
 	lea	4*8($tptr),$tptr
 
 	adox	%r15,%r10
-	mulx	0*16($nptr),%rax,%r15
+	mulx	0*8($nptr),%rax,%r15
 	adcx	%rax,%r10
 	adox	%r15,%r11
-	mulx	1*16($nptr),%rax,%r15
+	mulx	1*8($nptr),%rax,%r15
 	adcx	%rax,%r11
 	adox	%r15,%r12
-	mulx	2*16($nptr),%rax,%r15
+	mulx	2*8($nptr),%rax,%r15
 	mov	%r10,-5*8($tptr)
 	adcx	%rax,%r12
 	mov	%r11,-4*8($tptr)
 	adox	%r15,%r13
-	mulx	3*16($nptr),%rax,%r15
+	mulx	3*8($nptr),%rax,%r15
 	 mov	$bi,%rdx
 	mov	%r12,-3*8($tptr)
 	adcx	%rax,%r13
 	adox	$zero,%r15
-	lea	4*16($nptr),$nptr
+	lea	4*8($nptr),$nptr
 	mov	%r13,-2*8($tptr)
 
 	dec	$bptr			# of=0, pass cf
 	jnz	.Lmulx4x_1st
 
 	mov	8(%rsp),$num		# load -num
-	movq	%xmm0,%rdx		# bp[1]
 	adc	$zero,%r15		# modulo-scheduled
 	lea	($aptr,$num),$aptr	# rewind $aptr
 	add	%r15,%r14
@@ -2275,6 +2577,34 @@
 
 .align	32
 .Lmulx4x_outer:
+	lea	16-256($tptr),%r10	# where 256-byte mask is (+density control)
+	pxor	%xmm4,%xmm4
+	.byte	0x67,0x67
+	pxor	%xmm5,%xmm5
+___
+for($i=0;$i<$STRIDE/16;$i+=4) {
+$code.=<<___;
+	movdqa	`16*($i+0)-128`($bptr),%xmm0
+	movdqa	`16*($i+1)-128`($bptr),%xmm1
+	movdqa	`16*($i+2)-128`($bptr),%xmm2
+	pand	`16*($i+0)+256`(%r10),%xmm0
+	movdqa	`16*($i+3)-128`($bptr),%xmm3
+	pand	`16*($i+1)+256`(%r10),%xmm1
+	por	%xmm0,%xmm4
+	pand	`16*($i+2)+256`(%r10),%xmm2
+	por	%xmm1,%xmm5
+	pand	`16*($i+3)+256`(%r10),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+___
+}
+$code.=<<___;
+	por	%xmm5,%xmm4
+	pshufd	\$0x4e,%xmm4,%xmm0
+	por	%xmm4,%xmm0
+	lea	$STRIDE($bptr),$bptr
+	movq	%xmm0,%rdx		# m0=bp[i]
+
 	mov	$zero,($tptr)		# save top-most carry
 	lea	4*8($tptr,$num),$tptr	# rewind $tptr
 	mulx	0*8($aptr),$mi,%r11	# a[0]*b[i]
@@ -2289,54 +2619,37 @@
 	mulx	3*8($aptr),%rdx,%r14
 	adox	-2*8($tptr),%r12
 	adcx	%rdx,%r13
-	lea	($nptr,$num,2),$nptr	# rewind $nptr
+	lea	($nptr,$num),$nptr	# rewind $nptr
 	lea	4*8($aptr),$aptr
 	adox	-1*8($tptr),%r13
 	adcx	$zero,%r14
 	adox	$zero,%r14
 
-	.byte	0x67
 	mov	$mi,%r15
 	imulq	32+8(%rsp),$mi		# "t[0]"*n0
 
-	movq	`0*$STRIDE/4-96`($bptr),%xmm0
-	.byte	0x67,0x67
 	mov	$mi,%rdx
-	movq	`1*$STRIDE/4-96`($bptr),%xmm1
-	.byte	0x67
-	pand	%xmm4,%xmm0
-	movq	`2*$STRIDE/4-96`($bptr),%xmm2
-	.byte	0x67
-	pand	%xmm5,%xmm1
-	movq	`3*$STRIDE/4-96`($bptr),%xmm3
-	add	\$$STRIDE,$bptr		# next &b[i]
-	.byte	0x67
-	pand	%xmm6,%xmm2
-	por	%xmm1,%xmm0
-	pand	%xmm7,%xmm3
 	xor	$zero,$zero		# cf=0, of=0
 	mov	$bptr,8+8(%rsp)		# off-load &b[i]
 
-	mulx	0*16($nptr),%rax,%r10
+	mulx	0*8($nptr),%rax,%r10
 	adcx	%rax,%r15		# discarded
 	adox	%r11,%r10
-	mulx	1*16($nptr),%rax,%r11
+	mulx	1*8($nptr),%rax,%r11
 	adcx	%rax,%r10
 	adox	%r12,%r11
-	mulx	2*16($nptr),%rax,%r12
+	mulx	2*8($nptr),%rax,%r12
 	adcx	%rax,%r11
 	adox	%r13,%r12
-	mulx	3*16($nptr),%rax,%r15
+	mulx	3*8($nptr),%rax,%r15
 	 mov	$bi,%rdx
-	 por	%xmm2,%xmm0
 	mov	24+8(%rsp),$bptr	# counter value
 	mov	%r10,-8*4($tptr)
-	 por	%xmm3,%xmm0
 	adcx	%rax,%r12
 	mov	%r11,-8*3($tptr)
 	adox	$zero,%r15		# of=0
 	mov	%r12,-8*2($tptr)
-	lea	4*16($nptr),$nptr
+	lea	4*8($nptr),$nptr
 	jmp	.Lmulx4x_inner
 
 .align	32
@@ -2361,20 +2674,20 @@
 	adcx	$zero,%r14		# cf=0
 
 	adox	%r15,%r10
-	mulx	0*16($nptr),%rax,%r15
+	mulx	0*8($nptr),%rax,%r15
 	adcx	%rax,%r10
 	adox	%r15,%r11
-	mulx	1*16($nptr),%rax,%r15
+	mulx	1*8($nptr),%rax,%r15
 	adcx	%rax,%r11
 	adox	%r15,%r12
-	mulx	2*16($nptr),%rax,%r15
+	mulx	2*8($nptr),%rax,%r15
 	mov	%r10,-5*8($tptr)
 	adcx	%rax,%r12
 	adox	%r15,%r13
 	mov	%r11,-4*8($tptr)
-	mulx	3*16($nptr),%rax,%r15
+	mulx	3*8($nptr),%rax,%r15
 	 mov	$bi,%rdx
-	lea	4*16($nptr),$nptr
+	lea	4*8($nptr),$nptr
 	mov	%r12,-3*8($tptr)
 	adcx	%rax,%r13
 	adox	$zero,%r15
@@ -2384,7 +2697,6 @@
 	jnz	.Lmulx4x_inner
 
 	mov	0+8(%rsp),$num		# load -num
-	movq	%xmm0,%rdx		# bp[i+1]
 	adc	$zero,%r15		# modulo-scheduled
 	sub	0*8($tptr),$bptr	# pull top-most carry to %cf
 	mov	8+8(%rsp),$bptr		# re-load &b[i]
@@ -2397,20 +2709,26 @@
 	cmp	%r10,$bptr
 	jb	.Lmulx4x_outer
 
-	mov	-16($nptr),%r10
+	mov	-8($nptr),%r10
+	mov	$zero,%r8
+	mov	($nptr,$num),%r12
+	lea	($nptr,$num),%rbp	# rewind $nptr
+	mov	$num,%rcx
+	lea	($tptr,$num),%rdi	# rewind $tptr
+	xor	%eax,%eax
 	xor	%r15,%r15
 	sub	%r14,%r10		# compare top-most words
 	adc	%r15,%r15
-	or	%r15,$zero
-	xor	\$1,$zero
-	lea	($tptr,$num),%rdi	# rewind $tptr
-	lea	($nptr,$num,2),$nptr	# rewind $nptr
-	.byte	0x67,0x67
-	sar	\$3+2,$num		# cf=0
-	lea	($nptr,$zero,8),%rbp
+	or	%r15,%r8
+	sar	\$3+2,%rcx
+	sub	%r8,%rax		# %rax=-%r8
 	mov	56+8(%rsp),%rdx		# restore rp
-	mov	$num,%rcx
-	jmp	.Lsqrx4x_sub		# common post-condition
+	dec	%r12			# so that after 'not' we get -n[0]
+	mov	8*1(%rbp),%r13
+	xor	%r8,%r8
+	mov	8*2(%rbp),%r14
+	mov	8*3(%rbp),%r15
+	jmp	.Lsqrx4x_sub_entry	# common post-condition
 .size	mulx4x_internal,.-mulx4x_internal
 ___
 }{
@@ -2433,55 +2751,73 @@
 .type	bn_powerx5,\@function,6
 .align	32
 bn_powerx5:
-.Lpowerx5_enter:
-	.byte	0x67
+.cfi_startproc
 	mov	%rsp,%rax
+.cfi_def_cfa_register	%rax
+.Lpowerx5_enter:
 	push	%rbx
+.cfi_push	%rbx
 	push	%rbp
+.cfi_push	%rbp
 	push	%r12
+.cfi_push	%r12
 	push	%r13
+.cfi_push	%r13
 	push	%r14
+.cfi_push	%r14
 	push	%r15
-___
-$code.=<<___ if ($win64);
-	lea	-0x28(%rsp),%rsp
-	movaps	%xmm6,(%rsp)
-	movaps	%xmm7,0x10(%rsp)
-___
-$code.=<<___;
-	.byte	0x67
-	mov	${num}d,%r10d
+.cfi_push	%r15
+.Lpowerx5_prologue:
+
 	shl	\$3,${num}d		# convert $num to bytes
-	shl	\$3+2,%r10d		# 4*$num
+	lea	($num,$num,2),%r10	# 3*$num in bytes
 	neg	$num
 	mov	($n0),$n0		# *n0
 
 	##############################################################
-	# ensure that stack frame doesn't alias with $aptr+4*$num
-	# modulo 4096, which covers ret[num], am[num] and n[2*num]
-	# (see bn_exp.c). this is done to allow memory disambiguation
-	# logic do its magic.
+	# Ensure that stack frame doesn't alias with $rptr+3*$num
+	# modulo 4096, which covers ret[num], am[num] and n[num]
+	# (see bn_exp.c). This is done to allow memory disambiguation
+	# logic do its magic. [Extra 256 bytes is for power mask
+	# calculated from 7th argument, the index.]
 	#
-	lea	-64(%rsp,$num,2),%r11
-	sub	$aptr,%r11
+	lea	-320(%rsp,$num,2),%r11
+	mov	%rsp,%rbp
+	sub	$rptr,%r11
 	and	\$4095,%r11
 	cmp	%r11,%r10
 	jb	.Lpwrx_sp_alt
-	sub	%r11,%rsp		# align with $aptr
-	lea	-64(%rsp,$num,2),%rsp	# alloca(frame+2*$num)
+	sub	%r11,%rbp		# align with $aptr
+	lea	-320(%rbp,$num,2),%rbp	# future alloca(frame+2*$num*8+256)
 	jmp	.Lpwrx_sp_done
 
 .align	32
 .Lpwrx_sp_alt:
-	lea	4096-64(,$num,2),%r10	# 4096-frame-2*$num
-	lea	-64(%rsp,$num,2),%rsp	# alloca(frame+2*$num)
+	lea	4096-320(,$num,2),%r10
+	lea	-320(%rbp,$num,2),%rbp	# alloca(frame+2*$num*8+256)
 	sub	%r10,%r11
 	mov	\$0,%r10
 	cmovc	%r10,%r11
-	sub	%r11,%rsp
+	sub	%r11,%rbp
 .Lpwrx_sp_done:
-	and	\$-64,%rsp
-	mov	$num,%r10	
+	and	\$-64,%rbp
+	mov	%rsp,%r11
+	sub	%rbp,%r11
+	and	\$-4096,%r11
+	lea	(%rbp,%r11),%rsp
+	mov	(%rsp),%r10
+	cmp	%rbp,%rsp
+	ja	.Lpwrx_page_walk
+	jmp	.Lpwrx_page_walk_done
+
+.Lpwrx_page_walk:
+	lea	-4096(%rsp),%rsp
+	mov	(%rsp),%r10
+	cmp	%rbp,%rsp
+	ja	.Lpwrx_page_walk
+.Lpwrx_page_walk_done:
+
+	mov	$num,%r10
 	neg	$num
 
 	##############################################################
@@ -2502,13 +2838,19 @@
 	movq	$bptr,%xmm4
 	mov	$n0,  32(%rsp)
 	mov	%rax, 40(%rsp)		# save original %rsp
+.cfi_cfa_expression	%rsp+40,deref,+8
 .Lpowerx5_body:
 
 	call	__bn_sqrx8x_internal
+	call	__bn_postx4x_internal
 	call	__bn_sqrx8x_internal
+	call	__bn_postx4x_internal
 	call	__bn_sqrx8x_internal
+	call	__bn_postx4x_internal
 	call	__bn_sqrx8x_internal
+	call	__bn_postx4x_internal
 	call	__bn_sqrx8x_internal
+	call	__bn_postx4x_internal
 
 	mov	%r10,$num		# -num
 	mov	$aptr,$rptr
@@ -2519,22 +2861,26 @@
 	call	mulx4x_internal
 
 	mov	40(%rsp),%rsi		# restore %rsp
+.cfi_def_cfa	%rsi,8
 	mov	\$1,%rax
-___
-$code.=<<___ if ($win64);
-	movaps	-88(%rsi),%xmm6
-	movaps	-72(%rsi),%xmm7
-___
-$code.=<<___;
+
 	mov	-48(%rsi),%r15
+.cfi_restore	%r15
 	mov	-40(%rsi),%r14
+.cfi_restore	%r14
 	mov	-32(%rsi),%r13
+.cfi_restore	%r13
 	mov	-24(%rsi),%r12
+.cfi_restore	%r12
 	mov	-16(%rsi),%rbp
+.cfi_restore	%rbp
 	mov	-8(%rsi),%rbx
+.cfi_restore	%rbx
 	lea	(%rsi),%rsp
+.cfi_def_cfa_register	%rsp
 .Lpowerx5_epilogue:
 	ret
+.cfi_endproc
 .size	bn_powerx5,.-bn_powerx5
 
 .globl	bn_sqrx8x_internal
@@ -2959,11 +3305,11 @@
 
 $code.=<<___;
 	movq	%xmm2,$nptr
-sqrx8x_reduction:
+__bn_sqrx8x_reduction:
 	xor	%eax,%eax		# initial top-most carry bit
 	mov	32+8(%rsp),%rbx		# n0
 	mov	48+8(%rsp),%rdx		# "%r8", 8*0($tptr)
-	lea	-128($nptr,$num,2),%rcx	# end of n[]
+	lea	-8*8($nptr,$num),%rcx	# end of n[]
 	#lea	48+8(%rsp,$num,2),$tptr	# end of t[] buffer
 	mov	%rcx, 0+8(%rsp)		# save end of n[]
 	mov	$tptr,8+8(%rsp)		# save end of t[]
@@ -2992,23 +3338,23 @@
 .align	32
 .Lsqrx8x_reduce:
 	mov	%r8, %rbx
-	mulx	16*0($nptr),%rax,%r8	# n[0]
+	mulx	8*0($nptr),%rax,%r8	# n[0]
 	adcx	%rbx,%rax		# discarded
 	adox	%r9,%r8
 
-	mulx	16*1($nptr),%rbx,%r9	# n[1]
+	mulx	8*1($nptr),%rbx,%r9	# n[1]
 	adcx	%rbx,%r8
 	adox	%r10,%r9
 
-	mulx	16*2($nptr),%rbx,%r10
+	mulx	8*2($nptr),%rbx,%r10
 	adcx	%rbx,%r9
 	adox	%r11,%r10
 
-	mulx	16*3($nptr),%rbx,%r11
+	mulx	8*3($nptr),%rbx,%r11
 	adcx	%rbx,%r10
 	adox	%r12,%r11
 
-	.byte	0xc4,0x62,0xe3,0xf6,0xa5,0x40,0x00,0x00,0x00	# mulx	16*4($nptr),%rbx,%r12
+	.byte	0xc4,0x62,0xe3,0xf6,0xa5,0x20,0x00,0x00,0x00	# mulx	8*4($nptr),%rbx,%r12
 	 mov	%rdx,%rax
 	 mov	%r8,%rdx
 	adcx	%rbx,%r11
@@ -3018,15 +3364,15 @@
 	 mov	%rax,%rdx
 	 mov	%rax,64+48+8(%rsp,%rcx,8)	# put aside n0*a[i]
 
-	mulx	16*5($nptr),%rax,%r13
+	mulx	8*5($nptr),%rax,%r13
 	adcx	%rax,%r12
 	adox	%r14,%r13
 
-	mulx	16*6($nptr),%rax,%r14
+	mulx	8*6($nptr),%rax,%r14
 	adcx	%rax,%r13
 	adox	%r15,%r14
 
-	mulx	16*7($nptr),%rax,%r15
+	mulx	8*7($nptr),%rax,%r15
 	 mov	%rbx,%rdx
 	adcx	%rax,%r14
 	adox	$carry,%r15		# $carry is 0
@@ -3042,7 +3388,7 @@
 
 	mov	48+8(%rsp),%rdx		# pull n0*a[0]
 	add	8*0($tptr),%r8
-	lea	16*8($nptr),$nptr
+	lea	8*8($nptr),$nptr
 	mov	\$-8,%rcx
 	adcx	8*1($tptr),%r9
 	adcx	8*2($tptr),%r10
@@ -3061,35 +3407,35 @@
 .align	32
 .Lsqrx8x_tail:
 	mov	%r8,%rbx
-	mulx	16*0($nptr),%rax,%r8
+	mulx	8*0($nptr),%rax,%r8
 	adcx	%rax,%rbx
 	adox	%r9,%r8
 
-	mulx	16*1($nptr),%rax,%r9
+	mulx	8*1($nptr),%rax,%r9
 	adcx	%rax,%r8
 	adox	%r10,%r9
 
-	mulx	16*2($nptr),%rax,%r10
+	mulx	8*2($nptr),%rax,%r10
 	adcx	%rax,%r9
 	adox	%r11,%r10
 
-	mulx	16*3($nptr),%rax,%r11
+	mulx	8*3($nptr),%rax,%r11
 	adcx	%rax,%r10
 	adox	%r12,%r11
 
-	.byte	0xc4,0x62,0xfb,0xf6,0xa5,0x40,0x00,0x00,0x00	# mulx	16*4($nptr),%rax,%r12
+	.byte	0xc4,0x62,0xfb,0xf6,0xa5,0x20,0x00,0x00,0x00	# mulx	8*4($nptr),%rax,%r12
 	adcx	%rax,%r11
 	adox	%r13,%r12
 
-	mulx	16*5($nptr),%rax,%r13
+	mulx	8*5($nptr),%rax,%r13
 	adcx	%rax,%r12
 	adox	%r14,%r13
 
-	mulx	16*6($nptr),%rax,%r14
+	mulx	8*6($nptr),%rax,%r14
 	adcx	%rax,%r13
 	adox	%r15,%r14
 
-	mulx	16*7($nptr),%rax,%r15
+	mulx	8*7($nptr),%rax,%r15
 	 mov	72+48+8(%rsp,%rcx,8),%rdx	# pull n0*a[i]
 	adcx	%rax,%r14
 	adox	$carry,%r15
@@ -3105,7 +3451,7 @@
 
 	sub	16+8(%rsp),$carry	# mov 16(%rsp),%cf
 	 mov	48+8(%rsp),%rdx		# pull n0*a[0]
-	 lea	16*8($nptr),$nptr
+	 lea	8*8($nptr),$nptr
 	adc	8*0($tptr),%r8
 	adc	8*1($tptr),%r9
 	adc	8*2($tptr),%r10
@@ -3124,6 +3470,7 @@
 
 .align	32
 .Lsqrx8x_tail_done:
+	xor	%rax,%rax
 	add	24+8(%rsp),%r8		# can this overflow?
 	adc	\$0,%r9
 	adc	\$0,%r10
@@ -3131,17 +3478,15 @@
 	adc	\$0,%r12
 	adc	\$0,%r13
 	adc	\$0,%r14
-	adc	\$0,%r15		# can't overflow, because we
-					# started with "overhung" part
-					# of multiplication
-	mov	$carry,%rax		# xor	%rax,%rax
+	adc	\$0,%r15
+	adc	\$0,%rax
 
 	sub	16+8(%rsp),$carry	# mov 16(%rsp),%cf
 .Lsqrx8x_no_tail:			# %cf is 0 if jumped here
 	adc	8*0($tptr),%r8
 	 movq	%xmm3,%rcx
 	adc	8*1($tptr),%r9
-	 mov	16*7($nptr),$carry
+	 mov	8*7($nptr),$carry
 	 movq	%xmm2,$nptr		# restore $nptr
 	adc	8*2($tptr),%r10
 	adc	8*3($tptr),%r11
@@ -3149,7 +3494,7 @@
 	adc	8*5($tptr),%r13
 	adc	8*6($tptr),%r14
 	adc	8*7($tptr),%r15
-	adc	%rax,%rax		# top-most carry
+	adc	\$0,%rax		# top-most carry
 
 	mov	32+8(%rsp),%rbx		# n0
 	mov	8*8($tptr,%rcx),%rdx	# modulo-scheduled "%r8"
@@ -3167,6 +3512,8 @@
 	lea	8*8($tptr,%rcx),$tptr	# start of current t[] window
 	cmp	8+8(%rsp),%r8		# end of t[]?
 	jb	.Lsqrx8x_reduction_loop
+	ret
+.size	bn_sqrx8x_internal,.-bn_sqrx8x_internal
 ___
 }
 ##############################################################
@@ -3174,52 +3521,59 @@
 #
 {
 my ($rptr,$nptr)=("%rdx","%rbp");
-my @ri=map("%r$_",(10..13));
-my @ni=map("%r$_",(14..15));
 $code.=<<___;
-	xor	%ebx,%ebx
-	sub	%r15,%rsi		# compare top-most words
-	adc	%rbx,%rbx
+.align	32
+__bn_postx4x_internal:
+	mov	8*0($nptr),%r12
 	mov	%rcx,%r10		# -$num
-	or	%rbx,%rax
 	mov	%rcx,%r9		# -$num
-	xor	\$1,%rax
-	sar	\$3+2,%rcx		# cf=0
+	neg	%rax
+	sar	\$3+2,%rcx
 	#lea	48+8(%rsp,%r9),$tptr
-	lea	($nptr,%rax,8),$nptr
 	movq	%xmm1,$rptr		# restore $rptr
 	movq	%xmm1,$aptr		# prepare for back-to-back call
-	jmp	.Lsqrx4x_sub
+	dec	%r12			# so that after 'not' we get -n[0]
+	mov	8*1($nptr),%r13
+	xor	%r8,%r8
+	mov	8*2($nptr),%r14
+	mov	8*3($nptr),%r15
+	jmp	.Lsqrx4x_sub_entry
 
-.align	32
+.align	16
 .Lsqrx4x_sub:
-	.byte	0x66
-	mov	8*0($tptr),%r12
-	mov	8*1($tptr),%r13
-	sbb	16*0($nptr),%r12
-	mov	8*2($tptr),%r14
-	sbb	16*1($nptr),%r13
-	mov	8*3($tptr),%r15
-	lea	8*4($tptr),$tptr
-	sbb	16*2($nptr),%r14
+	mov	8*0($nptr),%r12
+	mov	8*1($nptr),%r13
+	mov	8*2($nptr),%r14
+	mov	8*3($nptr),%r15
+.Lsqrx4x_sub_entry:
+	andn	%rax,%r12,%r12
+	lea	8*4($nptr),$nptr
+	andn	%rax,%r13,%r13
+	andn	%rax,%r14,%r14
+	andn	%rax,%r15,%r15
+
+	neg	%r8			# mov %r8,%cf
+	adc	8*0($tptr),%r12
+	adc	8*1($tptr),%r13
+	adc	8*2($tptr),%r14
+	adc	8*3($tptr),%r15
 	mov	%r12,8*0($rptr)
-	sbb	16*3($nptr),%r15
-	lea	16*4($nptr),$nptr
+	lea	8*4($tptr),$tptr
 	mov	%r13,8*1($rptr)
+	sbb	%r8,%r8			# mov %cf,%r8
 	mov	%r14,8*2($rptr)
 	mov	%r15,8*3($rptr)
 	lea	8*4($rptr),$rptr
 
 	inc	%rcx
 	jnz	.Lsqrx4x_sub
-___
-}
-$code.=<<___;
+
 	neg	%r9			# restore $num
 
 	ret
-.size	bn_sqrx8x_internal,.-bn_sqrx8x_internal
+.size	__bn_postx4x_internal,.-__bn_postx4x_internal
 ___
+}
 }}}
 {
 my ($inp,$num,$tbl,$idx)=$win64?("%rcx","%edx","%r8", "%r9d") : # Win64 order
@@ -3249,56 +3603,91 @@
 
 .globl	bn_gather5
 .type	bn_gather5,\@abi-omnipotent
-.align	16
+.align	32
 bn_gather5:
-___
-$code.=<<___ if ($win64);
-.LSEH_begin_bn_gather5:
+.LSEH_begin_bn_gather5:			# Win64 thing, but harmless in other cases
 	# I can't trust assembler to use specific encoding:-(
-	.byte	0x48,0x83,0xec,0x28		#sub	\$0x28,%rsp
-	.byte	0x0f,0x29,0x34,0x24		#movaps	%xmm6,(%rsp)
-	.byte	0x0f,0x29,0x7c,0x24,0x10	#movdqa	%xmm7,0x10(%rsp)
+	.byte	0x4c,0x8d,0x14,0x24			#lea    (%rsp),%r10
+	.byte	0x48,0x81,0xec,0x08,0x01,0x00,0x00	#sub	$0x108,%rsp
+	lea	.Linc(%rip),%rax
+	and	\$-16,%rsp		# shouldn't be formally required
+
+	movd	$idx,%xmm5
+	movdqa	0(%rax),%xmm0		# 00000001000000010000000000000000
+	movdqa	16(%rax),%xmm1		# 00000002000000020000000200000002
+	lea	128($tbl),%r11		# size optimization
+	lea	128(%rsp),%rax		# size optimization
+
+	pshufd	\$0,%xmm5,%xmm5		# broadcast $idx
+	movdqa	%xmm1,%xmm4
+	movdqa	%xmm1,%xmm2
+___
+########################################################################
+# calculate mask by comparing 0..31 to $idx and save result to stack
+#
+for($i=0;$i<$STRIDE/16;$i+=4) {
+$code.=<<___;
+	paddd	%xmm0,%xmm1
+	pcmpeqd	%xmm5,%xmm0		# compare to 1,0
+___
+$code.=<<___	if ($i);
+	movdqa	%xmm3,`16*($i-1)-128`(%rax)
 ___
 $code.=<<___;
-	mov	$idx,%r11d
-	shr	\$`log($N/8)/log(2)`,$idx
-	and	\$`$N/8-1`,%r11
-	not	$idx
-	lea	.Lmagic_masks(%rip),%rax
-	and	\$`2**5/($N/8)-1`,$idx	# 5 is "window size"
-	lea	128($tbl,%r11,8),$tbl	# pointer within 1st cache line
-	movq	0(%rax,$idx,8),%xmm4	# set of masks denoting which
-	movq	8(%rax,$idx,8),%xmm5	# cache line contains element
-	movq	16(%rax,$idx,8),%xmm6	# denoted by 7th argument
-	movq	24(%rax,$idx,8),%xmm7
-	jmp	.Lgather
-.align	16
-.Lgather:
-	movq	`0*$STRIDE/4-128`($tbl),%xmm0
-	movq	`1*$STRIDE/4-128`($tbl),%xmm1
-	pand	%xmm4,%xmm0
-	movq	`2*$STRIDE/4-128`($tbl),%xmm2
-	pand	%xmm5,%xmm1
-	movq	`3*$STRIDE/4-128`($tbl),%xmm3
-	pand	%xmm6,%xmm2
-	por	%xmm1,%xmm0
-	pand	%xmm7,%xmm3
-	.byte	0x67,0x67
-	por	%xmm2,%xmm0
-	lea	$STRIDE($tbl),$tbl
-	por	%xmm3,%xmm0
+	movdqa	%xmm4,%xmm3
 
+	paddd	%xmm1,%xmm2
+	pcmpeqd	%xmm5,%xmm1		# compare to 3,2
+	movdqa	%xmm0,`16*($i+0)-128`(%rax)
+	movdqa	%xmm4,%xmm0
+
+	paddd	%xmm2,%xmm3
+	pcmpeqd	%xmm5,%xmm2		# compare to 5,4
+	movdqa	%xmm1,`16*($i+1)-128`(%rax)
+	movdqa	%xmm4,%xmm1
+
+	paddd	%xmm3,%xmm0
+	pcmpeqd	%xmm5,%xmm3		# compare to 7,6
+	movdqa	%xmm2,`16*($i+2)-128`(%rax)
+	movdqa	%xmm4,%xmm2
+___
+}
+$code.=<<___;
+	movdqa	%xmm3,`16*($i-1)-128`(%rax)
+	jmp	.Lgather
+
+.align	32
+.Lgather:
+	pxor	%xmm4,%xmm4
+	pxor	%xmm5,%xmm5
+___
+for($i=0;$i<$STRIDE/16;$i+=4) {
+$code.=<<___;
+	movdqa	`16*($i+0)-128`(%r11),%xmm0
+	movdqa	`16*($i+1)-128`(%r11),%xmm1
+	movdqa	`16*($i+2)-128`(%r11),%xmm2
+	pand	`16*($i+0)-128`(%rax),%xmm0
+	movdqa	`16*($i+3)-128`(%r11),%xmm3
+	pand	`16*($i+1)-128`(%rax),%xmm1
+	por	%xmm0,%xmm4
+	pand	`16*($i+2)-128`(%rax),%xmm2
+	por	%xmm1,%xmm5
+	pand	`16*($i+3)-128`(%rax),%xmm3
+	por	%xmm2,%xmm4
+	por	%xmm3,%xmm5
+___
+}
+$code.=<<___;
+	por	%xmm5,%xmm4
+	lea	$STRIDE(%r11),%r11
+	pshufd	\$0x4e,%xmm4,%xmm0
+	por	%xmm4,%xmm0
 	movq	%xmm0,($out)		# m0=bp[0]
 	lea	8($out),$out
 	sub	\$1,$num
 	jnz	.Lgather
-___
-$code.=<<___ if ($win64);
-	movaps	(%rsp),%xmm6
-	movaps	0x10(%rsp),%xmm7
-	lea	0x28(%rsp),%rsp
-___
-$code.=<<___;
+
+	lea	(%r10),%rsp
 	ret
 .LSEH_end_bn_gather5:
 .size	bn_gather5,.-bn_gather5
@@ -3306,9 +3695,9 @@
 }
 $code.=<<___;
 .align	64
-.Lmagic_masks:
-	.long	0,0, 0,0, 0,0, -1,-1
-	.long	0,0, 0,0, 0,0,  0,0
+.Linc:
+	.long	0,0, 1,1
+	.long	2,2, 2,2
 .asciz	"Montgomery Multiplication with scatter/gather for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
 ___
 
@@ -3347,28 +3736,30 @@
 	cmp	%r10,%rbx		# context->Rip<end of prologue label
 	jb	.Lcommon_seh_tail
 
+	mov	4(%r11),%r10d		# HandlerData[1]
+	lea	(%rsi,%r10),%r10	# beginning of body label
+	cmp	%r10,%rbx		# context->Rip<body label
+	jb	.Lcommon_pop_regs
+
 	mov	152($context),%rax	# pull context->Rsp
 
-	mov	4(%r11),%r10d		# HandlerData[1]
+	mov	8(%r11),%r10d		# HandlerData[2]
 	lea	(%rsi,%r10),%r10	# epilogue label
 	cmp	%r10,%rbx		# context->Rip>=epilogue label
 	jae	.Lcommon_seh_tail
 
 	lea	.Lmul_epilogue(%rip),%r10
 	cmp	%r10,%rbx
-	jb	.Lbody_40
+	ja	.Lbody_40
 
 	mov	192($context),%r10	# pull $num
 	mov	8(%rax,%r10,8),%rax	# pull saved stack pointer
-	jmp	.Lbody_proceed
+
+	jmp	.Lcommon_pop_regs
 
 .Lbody_40:
 	mov	40(%rax),%rax		# pull saved stack pointer
-.Lbody_proceed:
-
-	movaps	-88(%rax),%xmm0
-	movaps	-72(%rax),%xmm1
-
+.Lcommon_pop_regs:
 	mov	-8(%rax),%rbx
 	mov	-16(%rax),%rbp
 	mov	-24(%rax),%r12
@@ -3381,8 +3772,6 @@
 	mov	%r13,224($context)	# restore context->R13
 	mov	%r14,232($context)	# restore context->R14
 	mov	%r15,240($context)	# restore context->R15
-	movups	%xmm0,512($context)	# restore context->Xmm6
-	movups	%xmm1,528($context)	# restore context->Xmm7
 
 .Lcommon_seh_tail:
 	mov	8(%rax),%rdi
@@ -3461,42 +3850,41 @@
 .LSEH_info_bn_mul_mont_gather5:
 	.byte	9,0,0,0
 	.rva	mul_handler
-	.rva	.Lmul_body,.Lmul_epilogue		# HandlerData[]
+	.rva	.Lmul_body,.Lmul_body,.Lmul_epilogue		# HandlerData[]
 .align	8
 .LSEH_info_bn_mul4x_mont_gather5:
 	.byte	9,0,0,0
 	.rva	mul_handler
-	.rva	.Lmul4x_body,.Lmul4x_epilogue		# HandlerData[]
+	.rva	.Lmul4x_prologue,.Lmul4x_body,.Lmul4x_epilogue		# HandlerData[]
 .align	8
 .LSEH_info_bn_power5:
 	.byte	9,0,0,0
 	.rva	mul_handler
-	.rva	.Lpower5_body,.Lpower5_epilogue		# HandlerData[]
+	.rva	.Lpower5_prologue,.Lpower5_body,.Lpower5_epilogue	# HandlerData[]
 .align	8
 .LSEH_info_bn_from_mont8x:
 	.byte	9,0,0,0
 	.rva	mul_handler
-	.rva	.Lfrom_body,.Lfrom_epilogue		# HandlerData[]
+	.rva	.Lfrom_prologue,.Lfrom_body,.Lfrom_epilogue		# HandlerData[]
 ___
 $code.=<<___ if ($addx);
 .align	8
 .LSEH_info_bn_mulx4x_mont_gather5:
 	.byte	9,0,0,0
 	.rva	mul_handler
-	.rva	.Lmulx4x_body,.Lmulx4x_epilogue		# HandlerData[]
+	.rva	.Lmulx4x_prologue,.Lmulx4x_body,.Lmulx4x_epilogue	# HandlerData[]
 .align	8
 .LSEH_info_bn_powerx5:
 	.byte	9,0,0,0
 	.rva	mul_handler
-	.rva	.Lpowerx5_body,.Lpowerx5_epilogue	# HandlerData[]
+	.rva	.Lpowerx5_prologue,.Lpowerx5_body,.Lpowerx5_epilogue	# HandlerData[]
 ___
 $code.=<<___;
 .align	8
 .LSEH_info_bn_gather5:
-        .byte   0x01,0x0d,0x05,0x00
-        .byte   0x0d,0x78,0x01,0x00	#movaps	0x10(rsp),xmm7
-        .byte   0x08,0x68,0x00,0x00	#movaps	(rsp),xmm6
-        .byte   0x04,0x42,0x00,0x00	#sub	rsp,0x28
+	.byte	0x01,0x0b,0x03,0x0a
+	.byte	0x0b,0x01,0x21,0x00	# sub	rsp,0x108
+	.byte	0x04,0xa3,0x00,0x00	# lea	r10,(rsp)
 .align	8
 ___
 }
diff --git a/src/crypto/bn/bn.c b/src/crypto/bn/bn.c
index 543c148..e3c55f2 100644
--- a/src/crypto/bn/bn.c
+++ b/src/crypto/bn/bn.c
@@ -73,14 +73,14 @@
     return NULL;
   }
 
-  memset(bn, 0, sizeof(BIGNUM));
+  OPENSSL_memset(bn, 0, sizeof(BIGNUM));
   bn->flags = BN_FLG_MALLOCED;
 
   return bn;
 }
 
 void BN_init(BIGNUM *bn) {
-  memset(bn, 0, sizeof(BIGNUM));
+  OPENSSL_memset(bn, 0, sizeof(BIGNUM));
 }
 
 void BN_free(BIGNUM *bn) {
@@ -149,7 +149,7 @@
     return NULL;
   }
 
-  memcpy(dest->d, src->d, sizeof(src->d[0]) * src->top);
+  OPENSSL_memcpy(dest->d, src->d, sizeof(src->d[0]) * src->top);
 
   dest->top = src->top;
   dest->neg = src->neg;
@@ -158,7 +158,7 @@
 
 void BN_clear(BIGNUM *bn) {
   if (bn->d != NULL) {
-    memset(bn->d, 0, bn->dmax * sizeof(bn->d[0]));
+    OPENSSL_memset(bn->d, 0, bn->dmax * sizeof(bn->d[0]));
   }
 
   bn->top = 0;
@@ -172,12 +172,6 @@
   return &kOne;
 }
 
-void BN_with_flags(BIGNUM *out, const BIGNUM *in, int flags) {
-  memcpy(out, in, sizeof(BIGNUM));
-  out->flags &= ~BN_FLG_MALLOCED;
-  out->flags |= BN_FLG_STATIC_DATA | flags;
-}
-
 /* BN_num_bits_word returns the minimum number of bits needed to represent the
  * value in |l|. */
 unsigned BN_num_bits_word(BN_ULONG l) {
@@ -266,6 +260,40 @@
   return 1;
 }
 
+int BN_set_u64(BIGNUM *bn, uint64_t value) {
+#if BN_BITS2 == 64
+  return BN_set_word(bn, value);
+#elif BN_BITS2 == 32
+  if (value <= BN_MASK2) {
+    return BN_set_word(bn, (BN_ULONG)value);
+  }
+
+  if (bn_wexpand(bn, 2) == NULL) {
+    return 0;
+  }
+
+  bn->neg = 0;
+  bn->d[0] = (BN_ULONG)value;
+  bn->d[1] = (BN_ULONG)(value >> 32);
+  bn->top = 2;
+  return 1;
+#else
+#error "BN_BITS2 must be 32 or 64."
+#endif
+}
+
+int bn_set_words(BIGNUM *bn, const BN_ULONG *words, size_t num) {
+  if (bn_wexpand(bn, num) == NULL) {
+    return 0;
+  }
+  OPENSSL_memmove(bn->d, words, num * sizeof(BN_ULONG));
+  /* |bn_wexpand| verified that |num| isn't too large. */
+  bn->top = (int)num;
+  bn_correct_top(bn);
+  bn->neg = 0;
+  return 1;
+}
+
 int BN_is_negative(const BIGNUM *bn) {
   return bn->neg != 0;
 }
@@ -295,13 +323,13 @@
     return NULL;
   }
 
-  a = (BN_ULONG *)OPENSSL_malloc(sizeof(BN_ULONG) * words);
+  a = OPENSSL_malloc(sizeof(BN_ULONG) * words);
   if (a == NULL) {
     OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
     return NULL;
   }
 
-  memcpy(a, bn->d, sizeof(BN_ULONG) * bn->top);
+  OPENSSL_memcpy(a, bn->d, sizeof(BN_ULONG) * bn->top);
 
   OPENSSL_free(bn->d);
   bn->d = a;
@@ -330,12 +358,8 @@
     }
     bn->top = tmp_top;
   }
-}
 
-int BN_get_flags(const BIGNUM *bn, int flags) {
-  return bn->flags & flags;
-}
-
-void BN_set_flags(BIGNUM *bn, int flags) {
-  bn->flags |= flags;
+  if (bn->top == 0) {
+    bn->neg = 0;
+  }
 }
diff --git a/src/crypto/bn/bn_asn1.c b/src/crypto/bn/bn_asn1.c
index 9d70ba8..efb2335 100644
--- a/src/crypto/bn/bn_asn1.c
+++ b/src/crypto/bn/bn_asn1.c
@@ -18,7 +18,7 @@
 #include <openssl/err.h>
 
 
-int BN_cbs2unsigned(CBS *cbs, BIGNUM *ret) {
+int BN_parse_asn1_unsigned(CBS *cbs, BIGNUM *ret) {
   CBS child;
   if (!CBS_get_asn1(cbs, &child, CBS_ASN1_INTEGER) ||
       CBS_len(&child) == 0) {
@@ -42,7 +42,7 @@
   return BN_bin2bn(CBS_data(&child), CBS_len(&child), ret) != NULL;
 }
 
-int BN_cbs2unsigned_buggy(CBS *cbs, BIGNUM *ret) {
+int BN_parse_asn1_unsigned_buggy(CBS *cbs, BIGNUM *ret) {
   CBS child;
   if (!CBS_get_asn1(cbs, &child, CBS_ASN1_INTEGER) ||
       CBS_len(&child) == 0) {
@@ -58,7 +58,7 @@
   return BN_bin2bn(CBS_data(&child), CBS_len(&child), ret) != NULL;
 }
 
-int BN_bn2cbb(CBB *cbb, const BIGNUM *bn) {
+int BN_marshal_asn1(CBB *cbb, const BIGNUM *bn) {
   /* Negative numbers are unsupported. */
   if (BN_is_negative(bn)) {
     OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER);
@@ -66,28 +66,15 @@
   }
 
   CBB child;
-  if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER)) {
+  if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER) ||
+      /* The number must be padded with a leading zero if the high bit would
+       * otherwise be set or if |bn| is zero. */
+      (BN_num_bits(bn) % 8 == 0 && !CBB_add_u8(&child, 0x00)) ||
+      !BN_bn2cbb_padded(&child, BN_num_bytes(bn), bn) ||
+      !CBB_flush(cbb)) {
     OPENSSL_PUT_ERROR(BN, BN_R_ENCODE_ERROR);
     return 0;
   }
 
-  /* The number must be padded with a leading zero if the high bit would
-   * otherwise be set (or |bn| is zero). */
-  if (BN_num_bits(bn) % 8 == 0 &&
-      !CBB_add_u8(&child, 0x00)) {
-    OPENSSL_PUT_ERROR(BN, BN_R_ENCODE_ERROR);
-    return 0;
-  }
-
-  uint8_t *out;
-  if (!CBB_add_space(&child, &out, BN_num_bytes(bn))) {
-    OPENSSL_PUT_ERROR(BN, BN_R_ENCODE_ERROR);
-    return 0;
-  }
-  BN_bn2bin(bn, out);
-  if (!CBB_flush(cbb)) {
-    OPENSSL_PUT_ERROR(BN, BN_R_ENCODE_ERROR);
-    return 0;
-  }
   return 1;
 }
diff --git a/src/crypto/bn/bn_test.cc b/src/crypto/bn/bn_test.cc
index b00b420..c0af58d 100644
--- a/src/crypto/bn/bn_test.cc
+++ b/src/crypto/bn/bn_test.cc
@@ -67,895 +67,182 @@
  * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems
  * Laboratories. */
 
-/* For BIGNUM format macros. */
+/* Per C99, various stdint.h and inttypes.h macros (the latter used by bn.h) are
+ * unavailable in C++ unless some macros are defined. C++11 overruled this
+ * decision, but older Android NDKs still require it. */
+#if !defined(__STDC_CONSTANT_MACROS)
+#define __STDC_CONSTANT_MACROS
+#endif
 #if !defined(__STDC_FORMAT_MACROS)
 #define __STDC_FORMAT_MACROS
 #endif
 
+#include <assert.h>
 #include <errno.h>
+#include <limits.h>
 #include <stdio.h>
 #include <string.h>
 
 #include <utility>
 
 #include <openssl/bn.h>
+#include <openssl/bytestring.h>
 #include <openssl/crypto.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
-#include "../crypto/test/scoped_types.h"
-#include "../crypto/test/test_util.h"
+#include "../internal.h"
+#include "../test/file_test.h"
+#include "../test/test_util.h"
 
 
-// This program tests the BIGNUM implementation. It takes an optional -bc
-// argument to write a transcript compatible with the UNIX bc utility.
-//
-// TODO(davidben): Rather than generate random inputs and depend on bc to check
-// the results, most of these tests should use known answers.
-
-static const int num0 = 100; // number of tests
-static const int num1 = 50;  // additional tests for some functions
-static const int num2 = 5;   // number of tests for slow functions
-
-static bool test_add(FILE *fp);
-static bool test_sub(FILE *fp);
-static bool test_lshift1(FILE *fp);
-static bool test_lshift(FILE *fp, BN_CTX *ctx, ScopedBIGNUM a);
-static bool test_rshift1(FILE *fp);
-static bool test_rshift(FILE *fp, BN_CTX *ctx);
-static bool test_sqr(FILE *fp, BN_CTX *ctx);
-static bool test_mul(FILE *fp);
-static bool test_div(FILE *fp, BN_CTX *ctx);
-static int rand_neg();
-
-static bool test_div_word(FILE *fp);
-static bool test_mont(FILE *fp, BN_CTX *ctx);
-static bool test_mod(FILE *fp, BN_CTX *ctx);
-static bool test_mod_mul(FILE *fp, BN_CTX *ctx);
-static bool test_mod_exp(FILE *fp, BN_CTX *ctx);
-static bool test_mod_exp_mont_consttime(FILE *fp, BN_CTX *ctx);
-static bool test_exp(FILE *fp, BN_CTX *ctx);
-static bool test_mod_sqrt(FILE *fp, BN_CTX *ctx);
-static bool test_exp_mod_zero(void);
-static bool test_small_prime(FILE *fp, BN_CTX *ctx);
-static bool test_mod_exp_mont5(FILE *fp, BN_CTX *ctx);
-static bool test_sqrt(FILE *fp, BN_CTX *ctx);
-static bool test_bn2bin_padded(BN_CTX *ctx);
-static bool test_dec2bn(BN_CTX *ctx);
-static bool test_hex2bn(BN_CTX *ctx);
-static bool test_asc2bn(BN_CTX *ctx);
-static bool test_mpi();
-static bool test_rand();
-static bool test_asn1();
-static bool TestBN2Dec();
-
-static const uint8_t kSample[] =
-    "\xC6\x4F\x43\x04\x2A\xEA\xCA\x6E\x58\x36\x80\x5B\xE8\xC9"
-    "\x9B\x04\x5D\x48\x36\xC2\xFD\x16\xC9\x64\xF0";
-
-// A wrapper around puts that takes its arguments in the same order as our *_fp
-// functions.
-static void puts_fp(FILE *out, const char *m) {
-  if (out != nullptr) {
-    fputs(m, out);
-  }
-}
-
-static void flush_fp(FILE *out) {
-  if (out != nullptr) {
-    fflush(out);
-  }
-}
-
-static void message(FILE *out, const char *m) {
-  puts_fp(out, "print \"test ");
-  puts_fp(out, m);
-  puts_fp(out, "\\n\"\n");
-}
-
-int main(int argc, char *argv[]) {
-  CRYPTO_library_init();
-
-  ScopedFILE bc_file;
-  argc--;
-  argv++;
-  while (argc >= 1) {
-    if (strcmp(*argv, "-bc") == 0) {
-      if (argc < 2) {
-        fprintf(stderr, "Missing parameter to -bc\n");
-        return 1;
-      }
-      bc_file.reset(fopen(argv[1], "w+"));
-      if (!bc_file) {
-        fprintf(stderr, "Failed to open %s: %s\n", argv[1], strerror(errno));
-      }
-      argc--;
-      argv++;
-    } else {
-      fprintf(stderr, "Unknown option: %s\n", argv[0]);
-      return 1;
-    }
-    argc--;
-    argv++;
-  }
-
-
-  ScopedBN_CTX ctx(BN_CTX_new());
-  if (!ctx) {
-    return 1;
-  }
-
-  puts_fp(bc_file.get(), "/* This script, when run through the UNIX bc utility, "
-                         "should produce a sequence of zeros. */\n");
-  puts_fp(bc_file.get(), "/* tr a-f A-F < bn_test.out | sed s/BAsE/base/ | bc "
-                         "| grep -v 0 */\n");
-  puts_fp(bc_file.get(), "obase=16\nibase=16\n");
-
-  message(bc_file.get(), "BN_add");
-  if (!test_add(bc_file.get())) {
-    return 1;
-  }
-  flush_fp(bc_file.get());
-
-  message(bc_file.get(), "BN_sub");
-  if (!test_sub(bc_file.get())) {
-    return 1;
-  }
-  flush_fp(bc_file.get());
-
-  message(bc_file.get(), "BN_lshift1");
-  if (!test_lshift1(bc_file.get())) {
-    return 1;
-  }
-  flush_fp(bc_file.get());
-
-  message(bc_file.get(), "BN_lshift (fixed)");
-  ScopedBIGNUM sample(BN_bin2bn(kSample, sizeof(kSample) - 1, NULL));
-  if (!sample) {
-    return 1;
-  }
-  if (!test_lshift(bc_file.get(), ctx.get(), std::move(sample))) {
-    return 1;
-  }
-  flush_fp(bc_file.get());
-
-  message(bc_file.get(), "BN_lshift");
-  if (!test_lshift(bc_file.get(), ctx.get(), nullptr)) {
-    return 1;
-  }
-  flush_fp(bc_file.get());
-
-  message(bc_file.get(), "BN_rshift1");
-  if (!test_rshift1(bc_file.get())) {
-    return 1;
-  }
-  flush_fp(bc_file.get());
-
-  message(bc_file.get(), "BN_rshift");
-  if (!test_rshift(bc_file.get(), ctx.get())) {
-    return 1;
-  }
-  flush_fp(bc_file.get());
-
-  message(bc_file.get(), "BN_sqr");
-  if (!test_sqr(bc_file.get(), ctx.get())) {
-    return 1;
-  }
-  flush_fp(bc_file.get());
-
-  message(bc_file.get(), "BN_mul");
-  if (!test_mul(bc_file.get())) {
-    return 1;
-  }
-  flush_fp(bc_file.get());
-
-  message(bc_file.get(), "BN_div");
-  if (!test_div(bc_file.get(), ctx.get())) {
-    return 1;
-  }
-  flush_fp(bc_file.get());
-
-  message(bc_file.get(), "BN_div_word");
-  if (!test_div_word(bc_file.get())) {
-    return 1;
-  }
-  flush_fp(bc_file.get());
-
-  message(bc_file.get(), "BN_mod");
-  if (!test_mod(bc_file.get(), ctx.get())) {
-    return 1;
-  }
-  flush_fp(bc_file.get());
-
-  message(bc_file.get(), "BN_mod_mul");
-  if (!test_mod_mul(bc_file.get(), ctx.get())) {
-    return 1;
-  }
-  flush_fp(bc_file.get());
-
-  message(bc_file.get(), "BN_mont");
-  if (!test_mont(bc_file.get(), ctx.get())) {
-    return 1;
-  }
-  flush_fp(bc_file.get());
-
-  message(bc_file.get(), "BN_mod_exp");
-  if (!test_mod_exp(bc_file.get(), ctx.get())) {
-    return 1;
-  }
-  flush_fp(bc_file.get());
-
-  message(bc_file.get(), "BN_mod_exp_mont_consttime");
-  if (!test_mod_exp_mont_consttime(bc_file.get(), ctx.get()) ||
-      !test_mod_exp_mont5(bc_file.get(), ctx.get())) {
-    return 1;
-  }
-  flush_fp(bc_file.get());
-
-  message(bc_file.get(), "BN_exp");
-  if (!test_exp(bc_file.get(), ctx.get()) ||
-      !test_exp_mod_zero()) {
-    return 1;
-  }
-  flush_fp(bc_file.get());
-
-  message(bc_file.get(), "BN_mod_sqrt");
-  if (!test_mod_sqrt(bc_file.get(), ctx.get())) {
-    return 1;
-  }
-  flush_fp(bc_file.get());
-
-  message(bc_file.get(), "Small prime generation");
-  if (!test_small_prime(bc_file.get(), ctx.get())) {
-    return 1;
-  }
-  flush_fp(bc_file.get());
-
-  message(bc_file.get(), "BN_sqrt");
-  if (!test_sqrt(bc_file.get(), ctx.get())) {
-    return 1;
-  }
-  flush_fp(bc_file.get());
-
-  if (!test_bn2bin_padded(ctx.get()) ||
-      !test_dec2bn(ctx.get()) ||
-      !test_hex2bn(ctx.get()) ||
-      !test_asc2bn(ctx.get()) ||
-      !test_mpi() ||
-      !test_rand() ||
-      !test_asn1()) {
-    return 1;
-  }
-
-  message(bc_file.get(), "BN_bn2dec");
-  if (!TestBN2Dec()) {
-    return 1;
-  }
-  flush_fp(bc_file.get());
-
-  printf("PASS\n");
-  return 0;
-}
-
-static int HexToBIGNUM(ScopedBIGNUM *out, const char *in) {
+static int HexToBIGNUM(bssl::UniquePtr<BIGNUM> *out, const char *in) {
   BIGNUM *raw = NULL;
   int ret = BN_hex2bn(&raw, in);
   out->reset(raw);
   return ret;
 }
 
-static bool test_add(FILE *fp) {
-  ScopedBIGNUM a(BN_new());
-  ScopedBIGNUM b(BN_new());
-  ScopedBIGNUM c(BN_new());
-  if (!a || !b || !c || !BN_rand(a.get(), 512, 0, 0)) {
+static bssl::UniquePtr<BIGNUM> GetBIGNUM(FileTest *t, const char *attribute) {
+  std::string hex;
+  if (!t->GetAttribute(&hex, attribute)) {
+    return nullptr;
+  }
+
+  bssl::UniquePtr<BIGNUM> ret;
+  if (HexToBIGNUM(&ret, hex.c_str()) != static_cast<int>(hex.size())) {
+    t->PrintLine("Could not decode '%s'.", hex.c_str());
+    return nullptr;
+  }
+  return ret;
+}
+
+static bool GetInt(FileTest *t, int *out, const char *attribute) {
+  bssl::UniquePtr<BIGNUM> ret = GetBIGNUM(t, attribute);
+  if (!ret) {
     return false;
   }
 
-  for (int i = 0; i < num0; i++) {
-    if (!BN_rand(b.get(), 450 + i, 0, 0)) {
-      return false;
-    }
-    a->neg = rand_neg();
-    b->neg = rand_neg();
-    if (!BN_add(c.get(), a.get(), b.get())) {
-      return false;
-    }
-    if (fp != NULL) {
-      BN_print_fp(fp, a.get());
-      puts_fp(fp, " + ");
-      BN_print_fp(fp, b.get());
-      puts_fp(fp, " - ");
-      BN_print_fp(fp, c.get());
-      puts_fp(fp, "\n");
-    }
-    a->neg = !a->neg;
-    b->neg = !b->neg;
-    if (!BN_add(c.get(), c.get(), b.get()) ||
-        !BN_add(c.get(), c.get(), a.get())) {
-      return false;
-    }
-    if (!BN_is_zero(c.get())) {
-      fprintf(stderr, "Add test failed!\n");
-      return false;
-    }
+  BN_ULONG word = BN_get_word(ret.get());
+  if (word > INT_MAX) {
+    return false;
   }
+
+  *out = static_cast<int>(word);
   return true;
 }
 
-static bool test_sub(FILE *fp) {
-  ScopedBIGNUM a(BN_new());
-  ScopedBIGNUM b(BN_new());
-  ScopedBIGNUM c(BN_new());
-  if (!a || !b || !c) {
+static bool ExpectBIGNUMsEqual(FileTest *t, const char *operation,
+                               const BIGNUM *expected, const BIGNUM *actual) {
+  if (BN_cmp(expected, actual) == 0) {
+    return true;
+  }
+
+  bssl::UniquePtr<char> expected_str(BN_bn2hex(expected));
+  bssl::UniquePtr<char> actual_str(BN_bn2hex(actual));
+  if (!expected_str || !actual_str) {
     return false;
   }
 
-  for (int i = 0; i < num0 + num1; i++) {
-    if (i < num1) {
-      if (!BN_rand(a.get(), 512, 0, 0) ||
-          !BN_copy(b.get(), a.get()) ||
-          !BN_set_bit(a.get(), i) ||
-          !BN_add_word(b.get(), i)) {
-        return false;
-      }
-    } else {
-      if (!BN_rand(b.get(), 400 + i - num1, 0, 0)) {
-        return false;
-      }
-      a->neg = rand_neg();
-      b->neg = rand_neg();
-    }
-    if (!BN_sub(c.get(), a.get(), b.get())) {
-      return false;
-    }
-    if (fp != NULL) {
-      BN_print_fp(fp, a.get());
-      puts_fp(fp, " - ");
-      BN_print_fp(fp, b.get());
-      puts_fp(fp, " - ");
-      BN_print_fp(fp, c.get());
-      puts_fp(fp, "\n");
-    }
-    if (!BN_add(c.get(), c.get(), b.get()) ||
-        !BN_sub(c.get(), c.get(), a.get())) {
-      return false;
-    }
-    if (!BN_is_zero(c.get())) {
-      fprintf(stderr, "Subtract test failed!\n");
-      return false;
-    }
-  }
-  return true;
+  t->PrintLine("Got %s =", operation);
+  t->PrintLine("\t%s", actual_str.get());
+  t->PrintLine("wanted:");
+  t->PrintLine("\t%s", expected_str.get());
+  return false;
 }
 
-static bool test_div(FILE *fp, BN_CTX *ctx) {
-  ScopedBIGNUM a(BN_new());
-  ScopedBIGNUM b(BN_new());
-  ScopedBIGNUM c(BN_new());
-  ScopedBIGNUM d(BN_new());
-  ScopedBIGNUM e(BN_new());
-  if (!a || !b || !c || !d || !e) {
+static bool TestSum(FileTest *t, BN_CTX *ctx) {
+  bssl::UniquePtr<BIGNUM> a = GetBIGNUM(t, "A");
+  bssl::UniquePtr<BIGNUM> b = GetBIGNUM(t, "B");
+  bssl::UniquePtr<BIGNUM> sum = GetBIGNUM(t, "Sum");
+  if (!a || !b || !sum) {
     return false;
   }
 
-  if (!BN_one(a.get())) {
-    return false;
-  }
-  BN_zero(b.get());
-  if (BN_div(d.get(), c.get(), a.get(), b.get(), ctx)) {
-    fprintf(stderr, "Division by zero succeeded!\n");
-    return false;
-  }
-  ERR_clear_error();
-
-  for (int i = 0; i < num0 + num1; i++) {
-    if (i < num1) {
-      if (!BN_rand(a.get(), 400, 0, 0) ||
-          !BN_copy(b.get(), a.get()) ||
-          !BN_lshift(a.get(), a.get(), i) ||
-          !BN_add_word(a.get(), i)) {
-        return false;
-      }
-    } else if (!BN_rand(b.get(), 50 + 3 * (i - num1), 0, 0)) {
-      return false;
-    }
-    a->neg = rand_neg();
-    b->neg = rand_neg();
-    if (!BN_div(d.get(), c.get(), a.get(), b.get(), ctx)) {
-      return false;
-    }
-    if (fp != NULL) {
-      BN_print_fp(fp, a.get());
-      puts_fp(fp, " / ");
-      BN_print_fp(fp, b.get());
-      puts_fp(fp, " - ");
-      BN_print_fp(fp, d.get());
-      puts_fp(fp, "\n");
-
-      BN_print_fp(fp, a.get());
-      puts_fp(fp, " % ");
-      BN_print_fp(fp, b.get());
-      puts_fp(fp, " - ");
-      BN_print_fp(fp, c.get());
-      puts_fp(fp, "\n");
-    }
-    if (!BN_mul(e.get(), d.get(), b.get(), ctx) ||
-        !BN_add(d.get(), e.get(), c.get()) ||
-        !BN_sub(d.get(), d.get(), a.get())) {
-      return false;
-    }
-    if (!BN_is_zero(d.get())) {
-      fprintf(stderr, "Division test failed!\n");
-      return false;
-    }
-  }
-
-  // Test that BN_div never gives negative zero in the quotient.
-  if (!BN_set_word(a.get(), 1) ||
-      !BN_set_word(b.get(), 2)) {
-    return false;
-  }
-  BN_set_negative(a.get(), 1);
-  if (!BN_div(d.get(), c.get(), a.get(), b.get(), ctx)) {
-    return false;
-  }
-  if (!BN_is_zero(d.get()) || BN_is_negative(d.get())) {
-    fprintf(stderr, "Division test failed!\n");
+  bssl::UniquePtr<BIGNUM> ret(BN_new());
+  if (!ret ||
+      !BN_add(ret.get(), a.get(), b.get()) ||
+      !ExpectBIGNUMsEqual(t, "A + B", sum.get(), ret.get()) ||
+      !BN_sub(ret.get(), sum.get(), a.get()) ||
+      !ExpectBIGNUMsEqual(t, "Sum - A", b.get(), ret.get()) ||
+      !BN_sub(ret.get(), sum.get(), b.get()) ||
+      !ExpectBIGNUMsEqual(t, "Sum - B", a.get(), ret.get())) {
     return false;
   }
 
-  // Test that BN_div never gives negative zero in the remainder.
-  if (!BN_set_word(b.get(), 1)) {
-    return false;
-  }
-  if (!BN_div(d.get(), c.get(), a.get(), b.get(), ctx)) {
-    return false;
-  }
-  if (!BN_is_zero(c.get()) || BN_is_negative(c.get())) {
-    fprintf(stderr, "Division test failed!\n");
+  // Test that the functions work when |r| and |a| point to the same |BIGNUM|,
+  // or when |r| and |b| point to the same |BIGNUM|. TODO: Test the case where
+  // all of |r|, |a|, and |b| point to the same |BIGNUM|.
+  if (!BN_copy(ret.get(), a.get()) ||
+      !BN_add(ret.get(), ret.get(), b.get()) ||
+      !ExpectBIGNUMsEqual(t, "A + B (r is a)", sum.get(), ret.get()) ||
+      !BN_copy(ret.get(), b.get()) ||
+      !BN_add(ret.get(), a.get(), ret.get()) ||
+      !ExpectBIGNUMsEqual(t, "A + B (r is b)", sum.get(), ret.get()) ||
+      !BN_copy(ret.get(), sum.get()) ||
+      !BN_sub(ret.get(), ret.get(), a.get()) ||
+      !ExpectBIGNUMsEqual(t, "Sum - A (r is a)", b.get(), ret.get()) ||
+      !BN_copy(ret.get(), a.get()) ||
+      !BN_sub(ret.get(), sum.get(), ret.get()) ||
+      !ExpectBIGNUMsEqual(t, "Sum - A (r is b)", b.get(), ret.get()) ||
+      !BN_copy(ret.get(), sum.get()) ||
+      !BN_sub(ret.get(), ret.get(), b.get()) ||
+      !ExpectBIGNUMsEqual(t, "Sum - B (r is a)", a.get(), ret.get()) ||
+      !BN_copy(ret.get(), b.get()) ||
+      !BN_sub(ret.get(), sum.get(), ret.get()) ||
+      !ExpectBIGNUMsEqual(t, "Sum - B (r is b)", a.get(), ret.get())) {
     return false;
   }
 
-  return true;
-}
-
-static bool test_lshift1(FILE *fp) {
-  ScopedBIGNUM a(BN_new());
-  ScopedBIGNUM b(BN_new());
-  ScopedBIGNUM c(BN_new());
-  if (!a || !b || !c || !BN_rand(a.get(), 200, 0, 0)) {
-    return false;
-  }
-  a->neg = rand_neg();
-  for (int i = 0; i < num0; i++) {
-    if (!BN_lshift1(b.get(), a.get())) {
-      return false;
-    }
-    if (fp != NULL) {
-      BN_print_fp(fp, a.get());
-      puts_fp(fp, " * 2");
-      puts_fp(fp, " - ");
-      BN_print_fp(fp, b.get());
-      puts_fp(fp, "\n");
-    }
-    if (!BN_add(c.get(), a.get(), a.get()) ||
-        !BN_sub(a.get(), b.get(), c.get())) {
-      return false;
-    }
-    if (!BN_is_zero(a.get())) {
-      fprintf(stderr, "Left shift one test failed!\n");
+  // Test |BN_uadd| and |BN_usub| with the prerequisites they are documented as
+  // having. Note that these functions are frequently used when the
+  // prerequisites don't hold. In those cases, they are supposed to work as if
+  // the prerequisite hold, but we don't test that yet. TODO: test that.
+  if (!BN_is_negative(a.get()) &&
+      !BN_is_negative(b.get()) && BN_cmp(a.get(), b.get()) >= 0) {
+    if (!BN_uadd(ret.get(), a.get(), b.get()) ||
+        !ExpectBIGNUMsEqual(t, "A +u B", sum.get(), ret.get()) ||
+        !BN_usub(ret.get(), sum.get(), a.get()) ||
+        !ExpectBIGNUMsEqual(t, "Sum -u A", b.get(), ret.get()) ||
+        !BN_usub(ret.get(), sum.get(), b.get()) ||
+        !ExpectBIGNUMsEqual(t, "Sum -u B", a.get(), ret.get())) {
       return false;
     }
 
-    if (!BN_copy(a.get(), b.get())) {
-      return false;
-    }
-  }
-  return true;
-}
-
-static bool test_rshift(FILE *fp, BN_CTX *ctx) {
-  ScopedBIGNUM a(BN_new());
-  ScopedBIGNUM b(BN_new());
-  ScopedBIGNUM c(BN_new());
-  ScopedBIGNUM d(BN_new());
-  ScopedBIGNUM e(BN_new());
-  if (!a || !b || !c || !d || !e || !BN_one(c.get()) ||
-      !BN_rand(a.get(), 200, 0, 0)) {
-    return false;
-  }
-  a->neg = rand_neg();
-  for (int i = 0; i < num0; i++) {
-    if (!BN_rshift(b.get(), a.get(), i + 1) ||
-        !BN_add(c.get(), c.get(), c.get())) {
-      return false;
-    }
-    if (fp != NULL) {
-      BN_print_fp(fp, a.get());
-      puts_fp(fp, " / ");
-      BN_print_fp(fp, c.get());
-      puts_fp(fp, " - ");
-      BN_print_fp(fp, b.get());
-      puts_fp(fp, "\n");
-    }
-    if (!BN_div(d.get(), e.get(), a.get(), c.get(), ctx) ||
-        !BN_sub(d.get(), d.get(), b.get())) {
-      return false;
-    }
-    if (!BN_is_zero(d.get())) {
-      fprintf(stderr, "Right shift test failed!\n");
-      return false;
-    }
-  }
-  return true;
-}
-
-static bool test_rshift1(FILE *fp) {
-  ScopedBIGNUM a(BN_new());
-  ScopedBIGNUM b(BN_new());
-  ScopedBIGNUM c(BN_new());
-  if (!a || !b || !c || !BN_rand(a.get(), 200, 0, 0)) {
-    return false;
-  }
-  a->neg = rand_neg();
-
-  for (int i = 0; i < num0; i++) {
-    if (!BN_rshift1(b.get(), a.get())) {
-      return false;
-    }
-    if (fp != NULL) {
-      BN_print_fp(fp, a.get());
-      puts_fp(fp, " / 2");
-      puts_fp(fp, " - ");
-      BN_print_fp(fp, b.get());
-      puts_fp(fp, "\n");
-    }
-    if (!BN_sub(c.get(), a.get(), b.get()) ||
-        !BN_sub(c.get(), c.get(), b.get())) {
-      return false;
-    }
-    if (!BN_is_zero(c.get()) && !BN_abs_is_word(c.get(), 1)) {
-      fprintf(stderr, "Right shift one test failed!\n");
-      return false;
-    }
-    if (!BN_copy(a.get(), b.get())) {
-      return false;
-    }
-  }
-  return true;
-}
-
-static bool test_lshift(FILE *fp, BN_CTX *ctx, ScopedBIGNUM a) {
-  if (!a) {
-    a.reset(BN_new());
-    if (!a || !BN_rand(a.get(), 200, 0, 0)) {
-      return false;
-    }
-    a->neg = rand_neg();
-  }
-
-  ScopedBIGNUM b(BN_new());
-  ScopedBIGNUM c(BN_new());
-  ScopedBIGNUM d(BN_new());
-  if (!b || !c || !d || !BN_one(c.get())) {
-    return false;
-  }
-
-  for (int i = 0; i < num0; i++) {
-    if (!BN_lshift(b.get(), a.get(), i + 1) ||
-        !BN_add(c.get(), c.get(), c.get())) {
-      return false;
-    }
-    if (fp != NULL) {
-      BN_print_fp(fp, a.get());
-      puts_fp(fp, " * ");
-      BN_print_fp(fp, c.get());
-      puts_fp(fp, " - ");
-      BN_print_fp(fp, b.get());
-      puts_fp(fp, "\n");
-    }
-    if (!BN_mul(d.get(), a.get(), c.get(), ctx) ||
-        !BN_sub(d.get(), d.get(), b.get())) {
-      return false;
-    }
-    if (!BN_is_zero(d.get())) {
-      fprintf(stderr, "Left shift test failed!\n");
-      fprintf(stderr, "a=");
-      BN_print_fp(stderr, a.get());
-      fprintf(stderr, "\nb=");
-      BN_print_fp(stderr, b.get());
-      fprintf(stderr, "\nc=");
-      BN_print_fp(stderr, c.get());
-      fprintf(stderr, "\nd=");
-      BN_print_fp(stderr, d.get());
-      fprintf(stderr, "\n");
-      return false;
-    }
-  }
-  return true;
-}
-
-static bool test_mul(FILE *fp) {
-  ScopedBN_CTX ctx(BN_CTX_new());
-  ScopedBIGNUM a(BN_new());
-  ScopedBIGNUM b(BN_new());
-  ScopedBIGNUM c(BN_new());
-  ScopedBIGNUM d(BN_new());
-  ScopedBIGNUM e(BN_new());
-  if (!ctx || !a || !b || !c || !d || !e) {
-    return false;
-  }
-
-  for (int i = 0; i < num0 + num1; i++) {
-    if (i <= num1) {
-      if (!BN_rand(a.get(), 100, 0, 0) ||
-          !BN_rand(b.get(), 100, 0, 0)) {
-        return false;
-      }
-    } else if (!BN_rand(b.get(), i - num1, 0, 0)) {
-      return false;
-    }
-    a->neg = rand_neg();
-    b->neg = rand_neg();
-    if (!BN_mul(c.get(), a.get(), b.get(), ctx.get())) {
-      return false;
-    }
-    if (fp != NULL) {
-      BN_print_fp(fp, a.get());
-      puts_fp(fp, " * ");
-      BN_print_fp(fp, b.get());
-      puts_fp(fp, " - ");
-      BN_print_fp(fp, c.get());
-      puts_fp(fp, "\n");
-    }
-    if (!BN_div(d.get(), e.get(), c.get(), a.get(), ctx.get()) ||
-        !BN_sub(d.get(), d.get(), b.get())) {
-      return false;
-    }
-    if (!BN_is_zero(d.get()) || !BN_is_zero(e.get())) {
-      fprintf(stderr, "Multiplication test failed!\n");
+    // Test that the functions work when |r| and |a| point to the same |BIGNUM|,
+    // or when |r| and |b| point to the same |BIGNUM|. TODO: Test the case where
+    // all of |r|, |a|, and |b| point to the same |BIGNUM|.
+    if (!BN_copy(ret.get(), a.get()) ||
+        !BN_uadd(ret.get(), ret.get(), b.get()) ||
+        !ExpectBIGNUMsEqual(t, "A +u B (r is a)", sum.get(), ret.get()) ||
+        !BN_copy(ret.get(), b.get()) ||
+        !BN_uadd(ret.get(), a.get(), ret.get()) ||
+        !ExpectBIGNUMsEqual(t, "A +u B (r is b)", sum.get(), ret.get()) ||
+        !BN_copy(ret.get(), sum.get()) ||
+        !BN_usub(ret.get(), ret.get(), a.get()) ||
+        !ExpectBIGNUMsEqual(t, "Sum -u A (r is a)", b.get(), ret.get()) ||
+        !BN_copy(ret.get(), a.get()) ||
+        !BN_usub(ret.get(), sum.get(), ret.get()) ||
+        !ExpectBIGNUMsEqual(t, "Sum -u A (r is b)", b.get(), ret.get()) ||
+        !BN_copy(ret.get(), sum.get()) ||
+        !BN_usub(ret.get(), ret.get(), b.get()) ||
+        !ExpectBIGNUMsEqual(t, "Sum -u B (r is a)", a.get(), ret.get()) ||
+        !BN_copy(ret.get(), b.get()) ||
+        !BN_usub(ret.get(), sum.get(), ret.get()) ||
+        !ExpectBIGNUMsEqual(t, "Sum -u B (r is b)", a.get(), ret.get())) {
       return false;
     }
   }
 
-  // Test that BN_mul never gives negative zero.
-  if (!BN_set_word(a.get(), 1)) {
-    return false;
-  }
-  BN_set_negative(a.get(), 1);
-  BN_zero(b.get());
-  if (!BN_mul(c.get(), a.get(), b.get(), ctx.get())) {
-    return false;
-  }
-  if (!BN_is_zero(c.get()) || BN_is_negative(c.get())) {
-    fprintf(stderr, "Multiplication test failed!\n");
-    return false;
-  }
-
-  return true;
-}
-
-static bool test_sqr(FILE *fp, BN_CTX *ctx) {
-  ScopedBIGNUM a(BN_new());
-  ScopedBIGNUM c(BN_new());
-  ScopedBIGNUM d(BN_new());
-  ScopedBIGNUM e(BN_new());
-  if (!a || !c || !d || !e) {
-    return false;
-  }
-
-  for (int i = 0; i < num0; i++) {
-    if (!BN_rand(a.get(), 40 + i * 10, 0, 0)) {
-      return false;
-    }
-    a->neg = rand_neg();
-    if (!BN_sqr(c.get(), a.get(), ctx)) {
-      return false;
-    }
-    if (fp != NULL) {
-      BN_print_fp(fp, a.get());
-      puts_fp(fp, " * ");
-      BN_print_fp(fp, a.get());
-      puts_fp(fp, " - ");
-      BN_print_fp(fp, c.get());
-      puts_fp(fp, "\n");
-    }
-    if (!BN_div(d.get(), e.get(), c.get(), a.get(), ctx) ||
-        !BN_sub(d.get(), d.get(), a.get())) {
-      return false;
-    }
-    if (!BN_is_zero(d.get()) || !BN_is_zero(e.get())) {
-      fprintf(stderr, "Square test failed!\n");
-      return false;
-    }
-  }
-
-  // Regression test for a BN_sqr overflow bug.
-  BIGNUM *a_raw = a.get();
-  if (!BN_hex2bn(
-          &a_raw,
-          "80000000000000008000000000000001FFFFFFFFFFFFFFFE0000000000000000") ||
-      !BN_sqr(c.get(), a.get(), ctx)) {
-    return false;
-  }
-  if (fp != NULL) {
-    BN_print_fp(fp, a.get());
-    puts_fp(fp, " * ");
-    BN_print_fp(fp, a.get());
-    puts_fp(fp, " - ");
-    BN_print_fp(fp, c.get());
-    puts_fp(fp, "\n");
-  }
-  if (!BN_mul(d.get(), a.get(), a.get(), ctx)) {
-    return false;
-  }
-  if (BN_cmp(c.get(), d.get())) {
-    fprintf(stderr,
-            "Square test failed: BN_sqr and BN_mul produce "
-            "different results!\n");
-    return false;
-  }
-
-  // Regression test for a BN_sqr overflow bug.
-  a_raw = a.get();
-  if (!BN_hex2bn(
-          &a_raw,
-          "80000000000000000000000080000001FFFFFFFE000000000000000000000000") ||
-      !BN_sqr(c.get(), a.get(), ctx)) {
-    return false;
-  }
-  if (fp != NULL) {
-    BN_print_fp(fp, a.get());
-    puts_fp(fp, " * ");
-    BN_print_fp(fp, a.get());
-    puts_fp(fp, " - ");
-    BN_print_fp(fp, c.get());
-    puts_fp(fp, "\n");
-  }
-  if (!BN_mul(d.get(), a.get(), a.get(), ctx)) {
-    return false;
-  }
-  if (BN_cmp(c.get(), d.get())) {
-    fprintf(stderr,
-            "Square test failed: BN_sqr and BN_mul produce "
-            "different results!\n");
-    return false;
-  }
-
-  return true;
-}
-
-
-static int rand_neg() {
-  static unsigned int neg = 0;
-  static const int sign[8] = {0, 0, 0, 1, 1, 0, 1, 1};
-
-  return sign[(neg++) % 8];
-}
-
-static void print_word(FILE *fp, BN_ULONG w) {
-  fprintf(fp, BN_HEX_FMT1, w);
-}
-
-static bool test_div_word(FILE *fp) {
-  ScopedBIGNUM a(BN_new());
-  ScopedBIGNUM b(BN_new());
-  if (!a || !b) {
-    return false;
-  }
-
-  for (int i = 0; i < num0; i++) {
-    do {
-      if (!BN_rand(a.get(), 512, -1, 0) ||
-          !BN_rand(b.get(), BN_BITS2, -1, 0)) {
-        return false;
-      }
-    } while (BN_is_zero(b.get()));
-
-    if (!BN_copy(b.get(), a.get())) {
-      return false;
-    }
-    BN_ULONG s = b->d[0];
-    BN_ULONG r = BN_div_word(b.get(), s);
-    if (r == (BN_ULONG)-1) {
-      return false;
-    }
-
-    if (fp != NULL) {
-      BN_print_fp(fp, a.get());
-      puts_fp(fp, " / ");
-      print_word(fp, s);
-      puts_fp(fp, " - ");
-      BN_print_fp(fp, b.get());
-      puts_fp(fp, "\n");
-
-      BN_print_fp(fp, a.get());
-      puts_fp(fp, " % ");
-      print_word(fp, s);
-      puts_fp(fp, " - ");
-      print_word(fp, r);
-      puts_fp(fp, "\n");
-    }
-    if (!BN_mul_word(b.get(), s) ||
-        !BN_add_word(b.get(), r) ||
-        !BN_sub(b.get(), a.get(), b.get())) {
-      return false;
-    }
-    if (!BN_is_zero(b.get())) {
-      fprintf(stderr, "Division (word) test failed!\n");
-      return false;
-    }
-  }
-  return true;
-}
-
-static bool test_mont(FILE *fp, BN_CTX *ctx) {
-  ScopedBIGNUM a(BN_new());
-  ScopedBIGNUM b(BN_new());
-  ScopedBIGNUM c(BN_new());
-  ScopedBIGNUM d(BN_new());
-  ScopedBIGNUM A(BN_new());
-  ScopedBIGNUM B(BN_new());
-  ScopedBIGNUM n(BN_new());
-  ScopedBN_MONT_CTX mont(BN_MONT_CTX_new());
-  if (!a || !b || !c || !d || !A || !B || !n || !mont) {
-    return false;
-  }
-
-  BN_zero(n.get());
-  if (BN_MONT_CTX_set(mont.get(), n.get(), ctx)) {
-    fprintf(stderr, "BN_MONT_CTX_set succeeded for zero modulus!\n");
-    return false;
-  }
-  ERR_clear_error();
-
-  if (!BN_set_word(n.get(), 16)) {
-    return false;
-  }
-  if (BN_MONT_CTX_set(mont.get(), n.get(), ctx)) {
-    fprintf(stderr, "BN_MONT_CTX_set succeeded for even modulus!\n");
-    return false;
-  }
-  ERR_clear_error();
-
-  if (!BN_rand(a.get(), 100, 0, 0) ||
-      !BN_rand(b.get(), 100, 0, 0)) {
-    return false;
-  }
-
-  for (int i = 0; i < num2; i++) {
-    int bits = (200 * (i + 1)) / num2;
-
-    if (bits == 0) {
-      continue;
-    }
-    if (!BN_rand(n.get(), bits, 0, 1) ||
-        !BN_MONT_CTX_set(mont.get(), n.get(), ctx) ||
-        !BN_nnmod(a.get(), a.get(), n.get(), ctx) ||
-        !BN_nnmod(b.get(), b.get(), n.get(), ctx) ||
-        !BN_to_montgomery(A.get(), a.get(), mont.get(), ctx) ||
-        !BN_to_montgomery(B.get(), b.get(), mont.get(), ctx) ||
-        !BN_mod_mul_montgomery(c.get(), A.get(), B.get(), mont.get(), ctx) ||
-        !BN_from_montgomery(A.get(), c.get(), mont.get(), ctx)) {
-      return false;
-    }
-    if (fp != NULL) {
-      BN_print_fp(fp, a.get());
-      puts_fp(fp, " * ");
-      BN_print_fp(fp, b.get());
-      puts_fp(fp, " % ");
-      BN_print_fp(fp, &mont->N);
-      puts_fp(fp, " - ");
-      BN_print_fp(fp, A.get());
-      puts_fp(fp, "\n");
-    }
-    if (!BN_mod_mul(d.get(), a.get(), b.get(), n.get(), ctx) ||
-        !BN_sub(d.get(), d.get(), A.get())) {
-      return false;
-    }
-    if (!BN_is_zero(d.get())) {
-      fprintf(stderr, "Montgomery multiplication test failed!\n");
+  // Test with |BN_add_word| and |BN_sub_word| if |b| is small enough.
+  BN_ULONG b_word = BN_get_word(b.get());
+  if (!BN_is_negative(b.get()) && b_word != (BN_ULONG)-1) {
+    if (!BN_copy(ret.get(), a.get()) ||
+        !BN_add_word(ret.get(), b_word) ||
+        !ExpectBIGNUMsEqual(t, "A + B (word)", sum.get(), ret.get()) ||
+        !BN_copy(ret.get(), sum.get()) ||
+        !BN_sub_word(ret.get(), b_word) ||
+        !ExpectBIGNUMsEqual(t, "Sum - B (word)", a.get(), ret.get())) {
       return false;
     }
   }
@@ -963,538 +250,499 @@
   return true;
 }
 
-static bool test_mod(FILE *fp, BN_CTX *ctx) {
-  ScopedBIGNUM a(BN_new());
-  ScopedBIGNUM b(BN_new());
-  ScopedBIGNUM c(BN_new());
-  ScopedBIGNUM d(BN_new());
-  ScopedBIGNUM e(BN_new());
-  if (!a || !b || !c || !d || !e ||
-      !BN_rand(a.get(), 1024, 0, 0)) {
+static bool TestLShift1(FileTest *t, BN_CTX *ctx) {
+  bssl::UniquePtr<BIGNUM> a = GetBIGNUM(t, "A");
+  bssl::UniquePtr<BIGNUM> lshift1 = GetBIGNUM(t, "LShift1");
+  bssl::UniquePtr<BIGNUM> zero(BN_new());
+  if (!a || !lshift1 || !zero) {
     return false;
   }
 
-  for (int i = 0; i < num0; i++) {
-    if (!BN_rand(b.get(), 450 + i * 10, 0, 0)) {
-      return false;
-    }
-    a->neg = rand_neg();
-    b->neg = rand_neg();
-    if (!BN_mod(c.get(), a.get(), b.get(), ctx)) {
-      return false;
-    }
-    if (fp != NULL) {
-      BN_print_fp(fp, a.get());
-      puts_fp(fp, " % ");
-      BN_print_fp(fp, b.get());
-      puts_fp(fp, " - ");
-      BN_print_fp(fp, c.get());
-      puts_fp(fp, "\n");
-    }
-    if (!BN_div(d.get(), e.get(), a.get(), b.get(), ctx) ||
-        !BN_sub(e.get(), e.get(), c.get())) {
-      return false;
-    }
-    if (!BN_is_zero(e.get())) {
-      fprintf(stderr, "Modulo test failed!\n");
-      return false;
-    }
-  }
-  return true;
-}
-
-static bool test_mod_mul(FILE *fp, BN_CTX *ctx) {
-  ScopedBIGNUM a(BN_new());
-  ScopedBIGNUM b(BN_new());
-  ScopedBIGNUM c(BN_new());
-  ScopedBIGNUM d(BN_new());
-  ScopedBIGNUM e(BN_new());
-  if (!a || !b || !c || !d || !e) {
-    return false;
-  }
-
-  if (!BN_one(a.get()) || !BN_one(b.get())) {
-    return false;
-  }
-  BN_zero(c.get());
-  if (BN_mod_mul(e.get(), a.get(), b.get(), c.get(), ctx)) {
-    fprintf(stderr, "BN_mod_mul with zero modulus succeeded!\n");
-    return false;
-  }
-  ERR_clear_error();
-
-  for (int j = 0; j < 3; j++) {
-    if (!BN_rand(c.get(), 1024, 0, 0)) {
-      return false;
-    }
-    for (int i = 0; i < num0; i++) {
-      if (!BN_rand(a.get(), 475 + i * 10, 0, 0) ||
-          !BN_rand(b.get(), 425 + i * 11, 0, 0)) {
-        return false;
-      }
-      a->neg = rand_neg();
-      b->neg = rand_neg();
-      if (!BN_mod_mul(e.get(), a.get(), b.get(), c.get(), ctx)) {
-        ERR_print_errors_fp(stderr);
-        return false;
-      }
-      if (fp != NULL) {
-        BN_print_fp(fp, a.get());
-        puts_fp(fp, " * ");
-        BN_print_fp(fp, b.get());
-        puts_fp(fp, " % ");
-        BN_print_fp(fp, c.get());
-        if (a->neg != b->neg && !BN_is_zero(e.get())) {
-          // If  (a*b) % c  is negative,  c  must be added
-          // in order to obtain the normalized remainder
-          // (new with OpenSSL 0.9.7, previous versions of
-          // BN_mod_mul could generate negative results)
-          puts_fp(fp, " + ");
-          BN_print_fp(fp, c.get());
-        }
-        puts_fp(fp, " - ");
-        BN_print_fp(fp, e.get());
-        puts_fp(fp, "\n");
-      }
-      if (!BN_mul(d.get(), a.get(), b.get(), ctx) ||
-          !BN_sub(d.get(), d.get(), e.get()) ||
-          !BN_div(a.get(), b.get(), d.get(), c.get(), ctx)) {
-        return false;
-      }
-      if (!BN_is_zero(b.get())) {
-        fprintf(stderr, "Modulo multiply test failed!\n");
-        ERR_print_errors_fp(stderr);
-        return false;
-      }
-    }
-  }
-  return true;
-}
-
-static bool test_mod_exp(FILE *fp, BN_CTX *ctx) {
-  ScopedBIGNUM a(BN_new());
-  ScopedBIGNUM b(BN_new());
-  ScopedBIGNUM c(BN_new());
-  ScopedBIGNUM d(BN_new());
-  ScopedBIGNUM e(BN_new());
-  if (!a || !b || !c || !d || !e) {
-    return false;
-  }
-
-  if (!BN_one(a.get()) || !BN_one(b.get())) {
-    return false;
-  }
-  BN_zero(c.get());
-  if (BN_mod_exp(d.get(), a.get(), b.get(), c.get(), ctx)) {
-    fprintf(stderr, "BN_mod_exp with zero modulus succeeded!\n");
-    return 0;
-  }
-  ERR_clear_error();
-
-  if (!BN_rand(c.get(), 30, 0, 1)) {  // must be odd for montgomery
-    return false;
-  }
-  for (int i = 0; i < num2; i++) {
-    if (!BN_rand(a.get(), 20 + i * 5, 0, 0) ||
-        !BN_rand(b.get(), 2 + i, 0, 0) ||
-        !BN_mod_exp(d.get(), a.get(), b.get(), c.get(), ctx)) {
-      return false;
-    }
-
-    if (fp != NULL) {
-      BN_print_fp(fp, a.get());
-      puts_fp(fp, " ^ ");
-      BN_print_fp(fp, b.get());
-      puts_fp(fp, " % ");
-      BN_print_fp(fp, c.get());
-      puts_fp(fp, " - ");
-      BN_print_fp(fp, d.get());
-      puts_fp(fp, "\n");
-    }
-    if (!BN_exp(e.get(), a.get(), b.get(), ctx) ||
-        !BN_sub(e.get(), e.get(), d.get()) ||
-        !BN_div(a.get(), b.get(), e.get(), c.get(), ctx)) {
-      return false;
-    }
-    if (!BN_is_zero(b.get())) {
-      fprintf(stderr, "Modulo exponentiation test failed!\n");
-      return false;
-    }
-  }
-
-   // Regression test for carry propagation bug in sqr8x_reduction.
-  if (!HexToBIGNUM(&a, "050505050505") ||
-      !HexToBIGNUM(&b, "02") ||
-      !HexToBIGNUM(
-          &c,
-          "4141414141414141414141274141414141414141414141414141414141414141"
-          "4141414141414141414141414141414141414141414141414141414141414141"
-          "4141414141414141414141800000000000000000000000000000000000000000"
-          "0000000000000000000000000000000000000000000000000000000000000000"
-          "0000000000000000000000000000000000000000000000000000000000000000"
-          "0000000000000000000000000000000000000000000000000000000001") ||
-      !BN_mod_exp(d.get(), a.get(), b.get(), c.get(), ctx) ||
-      !BN_mul(e.get(), a.get(), a.get(), ctx)) {
-    return false;
-  }
-  if (BN_cmp(d.get(), e.get()) != 0) {
-    fprintf(stderr, "BN_mod_exp and BN_mul produce different results!\n");
-    return false;
-  }
-
-  return true;
-}
-
-static bool test_mod_exp_mont_consttime(FILE *fp, BN_CTX *ctx) {
-  ScopedBIGNUM a(BN_new());
-  ScopedBIGNUM b(BN_new());
-  ScopedBIGNUM c(BN_new());
-  ScopedBIGNUM d(BN_new());
-  ScopedBIGNUM e(BN_new());
-  if (!a || !b || !c || !d || !e) {
-    return false;
-  }
-
-  if (!BN_one(a.get()) || !BN_one(b.get())) {
-    return false;
-  }
-  BN_zero(c.get());
-  if (BN_mod_exp_mont_consttime(d.get(), a.get(), b.get(), c.get(), ctx,
-                                nullptr)) {
-    fprintf(stderr, "BN_mod_exp_mont_consttime with zero modulus succeeded!\n");
-    return 0;
-  }
-  ERR_clear_error();
-
-  if (!BN_set_word(c.get(), 16)) {
-    return false;
-  }
-  if (BN_mod_exp_mont_consttime(d.get(), a.get(), b.get(), c.get(), ctx,
-                                nullptr)) {
-    fprintf(stderr, "BN_mod_exp_mont_consttime with even modulus succeeded!\n");
-    return 0;
-  }
-  ERR_clear_error();
-
-  if (!BN_rand(c.get(), 30, 0, 1)) {  // must be odd for montgomery
-    return false;
-  }
-  for (int i = 0; i < num2; i++) {
-    if (!BN_rand(a.get(), 20 + i * 5, 0, 0) ||
-        !BN_rand(b.get(), 2 + i, 0, 0) ||
-        !BN_mod_exp_mont_consttime(d.get(), a.get(), b.get(), c.get(), ctx,
-                                   NULL)) {
-      return false;
-    }
-
-    if (fp != NULL) {
-      BN_print_fp(fp, a.get());
-      puts_fp(fp, " ^ ");
-      BN_print_fp(fp, b.get());
-      puts_fp(fp, " % ");
-      BN_print_fp(fp, c.get());
-      puts_fp(fp, " - ");
-      BN_print_fp(fp, d.get());
-      puts_fp(fp, "\n");
-    }
-    if (!BN_exp(e.get(), a.get(), b.get(), ctx) ||
-        !BN_sub(e.get(), e.get(), d.get()) ||
-        !BN_div(a.get(), b.get(), e.get(), c.get(), ctx)) {
-      return false;
-    }
-    if (!BN_is_zero(b.get())) {
-      fprintf(stderr, "Modulo exponentiation test failed!\n");
-      return false;
-    }
-  }
-  return true;
-}
-
-// Test constant-time modular exponentiation with 1024-bit inputs,
-// which on x86_64 cause a different code branch to be taken.
-static bool test_mod_exp_mont5(FILE *fp, BN_CTX *ctx) {
-  ScopedBIGNUM a(BN_new());
-  ScopedBIGNUM p(BN_new());
-  ScopedBIGNUM m(BN_new());
-  ScopedBIGNUM d(BN_new());
-  ScopedBIGNUM e(BN_new());
-  if (!a || !p || !m || !d || !e ||
-      !BN_rand(m.get(), 1024, 0, 1) ||  // must be odd for montgomery
-      !BN_rand(a.get(), 1024, 0, 0)) {
-    return false;
-  }
-  // Zero exponent.
-  BN_zero(p.get());
-  if (!BN_mod_exp_mont_consttime(d.get(), a.get(), p.get(), m.get(), ctx,
-                                 NULL)) {
-    return false;
-  }
-  if (!BN_is_one(d.get())) {
-    fprintf(stderr, "Modular exponentiation test failed!\n");
-    return false;
-  }
-  if (!BN_rand(p.get(), 1024, 0, 0)) {
-    return false;
-  }
-  // Zero input.
-  BN_zero(a.get());
-  if (!BN_mod_exp_mont_consttime(d.get(), a.get(), p.get(), m.get(), ctx,
-                                 NULL)) {
-    return false;
-  }
-  if (!BN_is_zero(d.get())) {
-    fprintf(stderr, "Modular exponentiation test failed!\n");
-    return false;
-  }
-  // Craft an input whose Montgomery representation is 1, i.e., shorter than the
-  // modulus m, in order to test the const time precomputation
-  // scattering/gathering.
-  ScopedBN_MONT_CTX mont(BN_MONT_CTX_new());
-  if (!mont || !BN_one(a.get()) ||
-      !BN_MONT_CTX_set(mont.get(), m.get(), ctx) ||
-      !BN_from_montgomery(e.get(), a.get(), mont.get(), ctx) ||
-      !BN_mod_exp_mont_consttime(d.get(), e.get(), p.get(), m.get(), ctx,
-                                 NULL) ||
-      !BN_mod_exp(a.get(), e.get(), p.get(), m.get(), ctx)) {
-    return false;
-  }
-  if (BN_cmp(a.get(), d.get()) != 0) {
-    fprintf(stderr, "Modular exponentiation test failed!\n");
-    return false;
-  }
-  // Finally, some regular test vectors.
-  if (!BN_rand(e.get(), 1024, 0, 0) ||
-      !BN_mod_exp_mont_consttime(d.get(), e.get(), p.get(), m.get(), ctx,
-                                 NULL) ||
-      !BN_mod_exp(a.get(), e.get(), p.get(), m.get(), ctx)) {
-    return false;
-  }
-  if (BN_cmp(a.get(), d.get()) != 0) {
-    fprintf(stderr, "Modular exponentiation test failed!\n");
-    return false;
-  }
-
-  return true;
-}
-
-static bool test_exp(FILE *fp, BN_CTX *ctx) {
-  ScopedBIGNUM a(BN_new());
-  ScopedBIGNUM b(BN_new());
-  ScopedBIGNUM d(BN_new());
-  ScopedBIGNUM e(BN_new());
-  if (!a || !b || !d || !e) {
-    return false;
-  }
-
-  for (int i = 0; i < num2; i++) {
-    if (!BN_rand(a.get(), 20 + i * 5, 0, 0) ||
-        !BN_rand(b.get(), 2 + i, 0, 0) ||
-        !BN_exp(d.get(), a.get(), b.get(), ctx)) {
-      return false;
-    }
-
-    if (fp != NULL) {
-      BN_print_fp(fp, a.get());
-      puts_fp(fp, " ^ ");
-      BN_print_fp(fp, b.get());
-      puts_fp(fp, " - ");
-      BN_print_fp(fp, d.get());
-      puts_fp(fp, "\n");
-    }
-    if (!BN_one(e.get())) {
-      return false;
-    }
-    while (!BN_is_zero(b.get())) {
-      if (!BN_mul(e.get(), e.get(), a.get(), ctx) ||
-          !BN_sub(b.get(), b.get(), BN_value_one())) {
-        return false;
-      }
-    }
-    if (!BN_sub(e.get(), e.get(), d.get())) {
-      return false;
-    }
-    if (!BN_is_zero(e.get())) {
-      fprintf(stderr, "Exponentiation test failed!\n");
-      return false;
-    }
-  }
-  return true;
-}
-
-// test_exp_mod_zero tests that 1**0 mod 1 == 0.
-static bool test_exp_mod_zero(void) {
-  ScopedBIGNUM zero(BN_new()), a(BN_new()), r(BN_new());
-  if (!zero || !a || !r || !BN_rand(a.get(), 1024, 0, 0)) {
-    return false;
-  }
   BN_zero(zero.get());
 
-  if (!BN_mod_exp(r.get(), a.get(), zero.get(), BN_value_one(), nullptr) ||
-      !BN_is_zero(r.get()) ||
-      !BN_mod_exp_mont(r.get(), a.get(), zero.get(), BN_value_one(), nullptr,
-                       nullptr) ||
-      !BN_is_zero(r.get()) ||
-      !BN_mod_exp_mont_consttime(r.get(), a.get(), zero.get(), BN_value_one(),
-                                 nullptr, nullptr) ||
-      !BN_is_zero(r.get()) ||
-      !BN_mod_exp_mont_word(r.get(), 42, zero.get(), BN_value_one(), nullptr,
-                            nullptr) ||
-      !BN_is_zero(r.get())) {
+  bssl::UniquePtr<BIGNUM> ret(BN_new()), two(BN_new()), remainder(BN_new());
+  if (!ret || !two || !remainder ||
+      !BN_set_word(two.get(), 2) ||
+      !BN_add(ret.get(), a.get(), a.get()) ||
+      !ExpectBIGNUMsEqual(t, "A + A", lshift1.get(), ret.get()) ||
+      !BN_mul(ret.get(), a.get(), two.get(), ctx) ||
+      !ExpectBIGNUMsEqual(t, "A * 2", lshift1.get(), ret.get()) ||
+      !BN_div(ret.get(), remainder.get(), lshift1.get(), two.get(), ctx) ||
+      !ExpectBIGNUMsEqual(t, "LShift1 / 2", a.get(), ret.get()) ||
+      !ExpectBIGNUMsEqual(t, "LShift1 % 2", zero.get(), remainder.get()) ||
+      !BN_lshift1(ret.get(), a.get()) ||
+      !ExpectBIGNUMsEqual(t, "A << 1", lshift1.get(), ret.get()) ||
+      !BN_rshift1(ret.get(), lshift1.get()) ||
+      !ExpectBIGNUMsEqual(t, "LShift >> 1", a.get(), ret.get()) ||
+      !BN_rshift1(ret.get(), lshift1.get()) ||
+      !ExpectBIGNUMsEqual(t, "LShift >> 1", a.get(), ret.get())) {
+    return false;
+  }
+
+  // Set the LSB to 1 and test rshift1 again.
+  if (!BN_set_bit(lshift1.get(), 0) ||
+      !BN_div(ret.get(), nullptr /* rem */, lshift1.get(), two.get(), ctx) ||
+      !ExpectBIGNUMsEqual(t, "(LShift1 | 1) / 2", a.get(), ret.get()) ||
+      !BN_rshift1(ret.get(), lshift1.get()) ||
+      !ExpectBIGNUMsEqual(t, "(LShift | 1) >> 1", a.get(), ret.get())) {
     return false;
   }
 
   return true;
 }
 
-static bool test_mod_sqrt(FILE *fp, BN_CTX *ctx) {
-  ScopedBIGNUM a(BN_new());
-  ScopedBIGNUM p(BN_new());
-  ScopedBIGNUM r(BN_new());
-  if (!a || !p || !r) {
+static bool TestLShift(FileTest *t, BN_CTX *ctx) {
+  bssl::UniquePtr<BIGNUM> a = GetBIGNUM(t, "A");
+  bssl::UniquePtr<BIGNUM> lshift = GetBIGNUM(t, "LShift");
+  int n = 0;
+  if (!a || !lshift || !GetInt(t, &n, "N")) {
     return false;
   }
 
-  for (int i = 0; i < 16; i++) {
-    if (i < 8) {
-      const unsigned kPrimes[8] = {2, 3, 5, 7, 11, 13, 17, 19};
-      if (!BN_set_word(p.get(), kPrimes[i])) {
-        return false;
-      }
-    } else {
-      if (!BN_set_word(a.get(), 32) ||
-          !BN_set_word(r.get(), 2 * i + 1) ||
-          !BN_generate_prime_ex(p.get(), 256, 0, a.get(), r.get(), nullptr)) {
-        return false;
-      }
-    }
-    p->neg = rand_neg();
-
-    for (int j = 0; j < num2; j++) {
-      // construct 'a' such that it is a square modulo p, but in general not a
-      // proper square and not reduced modulo p
-      if (!BN_rand(r.get(), 256, 0, 3) ||
-          !BN_nnmod(r.get(), r.get(), p.get(), ctx) ||
-          !BN_mod_sqr(r.get(), r.get(), p.get(), ctx) ||
-          !BN_rand(a.get(), 256, 0, 3) ||
-          !BN_nnmod(a.get(), a.get(), p.get(), ctx) ||
-          !BN_mod_sqr(a.get(), a.get(), p.get(), ctx) ||
-          !BN_mul(a.get(), a.get(), r.get(), ctx)) {
-        return false;
-      }
-      if (rand_neg() && !BN_sub(a.get(), a.get(), p.get())) {
-        return false;
-      }
-
-      if (!BN_mod_sqrt(r.get(), a.get(), p.get(), ctx) ||
-          !BN_mod_sqr(r.get(), r.get(), p.get(), ctx) ||
-          !BN_nnmod(a.get(), a.get(), p.get(), ctx)) {
-        return false;
-      }
-
-      if (BN_cmp(a.get(), r.get()) != 0) {
-        fprintf(stderr, "BN_mod_sqrt failed: a = ");
-        BN_print_fp(stderr, a.get());
-        fprintf(stderr, ", r = ");
-        BN_print_fp(stderr, r.get());
-        fprintf(stderr, ", p = ");
-        BN_print_fp(stderr, p.get());
-        fprintf(stderr, "\n");
-        return false;
-      }
-    }
-  }
-  return true;
-}
-
-static bool test_small_prime(FILE *fp, BN_CTX *ctx) {
-  static const unsigned kBits = 10;
-
-  ScopedBIGNUM r(BN_new());
-  if (!r || !BN_generate_prime_ex(r.get(), static_cast<int>(kBits), 0, NULL,
-                                  NULL, NULL)) {
-    return false;
-  }
-  if (BN_num_bits(r.get()) != kBits) {
-    fprintf(fp, "Expected %u bit prime, got %u bit number\n", kBits,
-            BN_num_bits(r.get()));
+  bssl::UniquePtr<BIGNUM> ret(BN_new());
+  if (!ret ||
+      !BN_lshift(ret.get(), a.get(), n) ||
+      !ExpectBIGNUMsEqual(t, "A << N", lshift.get(), ret.get()) ||
+      !BN_rshift(ret.get(), lshift.get(), n) ||
+      !ExpectBIGNUMsEqual(t, "A >> N", a.get(), ret.get())) {
     return false;
   }
 
   return true;
 }
 
-static bool test_sqrt(FILE *fp, BN_CTX *ctx) {
-  ScopedBIGNUM n(BN_new());
-  ScopedBIGNUM nn(BN_new());
-  ScopedBIGNUM sqrt(BN_new());
-  if (!n || !nn || !sqrt) {
+static bool TestRShift(FileTest *t, BN_CTX *ctx) {
+  bssl::UniquePtr<BIGNUM> a = GetBIGNUM(t, "A");
+  bssl::UniquePtr<BIGNUM> rshift = GetBIGNUM(t, "RShift");
+  int n = 0;
+  if (!a || !rshift || !GetInt(t, &n, "N")) {
     return false;
   }
 
-  // Test some random squares.
-  for (int i = 0; i < 100; i++) {
-    if (!BN_rand(n.get(), 1024 /* bit length */,
-                 -1 /* no modification of top bits */,
-                 0 /* don't modify bottom bit */) ||
-        !BN_mul(nn.get(), n.get(), n.get(), ctx) ||
-        !BN_sqrt(sqrt.get(), nn.get(), ctx)) {
-      ERR_print_errors_fp(stderr);
+  bssl::UniquePtr<BIGNUM> ret(BN_new());
+  if (!ret ||
+      !BN_rshift(ret.get(), a.get(), n) ||
+      !ExpectBIGNUMsEqual(t, "A >> N", rshift.get(), ret.get())) {
+    return false;
+  }
+
+  return true;
+}
+
+static bool TestSquare(FileTest *t, BN_CTX *ctx) {
+  bssl::UniquePtr<BIGNUM> a = GetBIGNUM(t, "A");
+  bssl::UniquePtr<BIGNUM> square = GetBIGNUM(t, "Square");
+  bssl::UniquePtr<BIGNUM> zero(BN_new());
+  if (!a || !square || !zero) {
+    return false;
+  }
+
+  BN_zero(zero.get());
+
+  bssl::UniquePtr<BIGNUM> ret(BN_new()), remainder(BN_new());
+  if (!ret || !remainder ||
+      !BN_sqr(ret.get(), a.get(), ctx) ||
+      !ExpectBIGNUMsEqual(t, "A^2", square.get(), ret.get()) ||
+      !BN_mul(ret.get(), a.get(), a.get(), ctx) ||
+      !ExpectBIGNUMsEqual(t, "A * A", square.get(), ret.get()) ||
+      !BN_div(ret.get(), remainder.get(), square.get(), a.get(), ctx) ||
+      !ExpectBIGNUMsEqual(t, "Square / A", a.get(), ret.get()) ||
+      !ExpectBIGNUMsEqual(t, "Square % A", zero.get(), remainder.get())) {
+    return false;
+  }
+
+  BN_set_negative(a.get(), 0);
+  if (!BN_sqrt(ret.get(), square.get(), ctx) ||
+      !ExpectBIGNUMsEqual(t, "sqrt(Square)", a.get(), ret.get())) {
+    return false;
+  }
+
+  // BN_sqrt should fail on non-squares and negative numbers.
+  if (!BN_is_zero(square.get())) {
+    bssl::UniquePtr<BIGNUM> tmp(BN_new());
+    if (!tmp || !BN_copy(tmp.get(), square.get())) {
       return false;
     }
-    if (BN_cmp(n.get(), sqrt.get()) != 0) {
-      fprintf(stderr, "Bad result from BN_sqrt.\n");
+    BN_set_negative(tmp.get(), 1);
+
+    if (BN_sqrt(ret.get(), tmp.get(), ctx)) {
+      t->PrintLine("BN_sqrt succeeded on a negative number");
+      return false;
+    }
+    ERR_clear_error();
+
+    BN_set_negative(tmp.get(), 0);
+    if (!BN_add(tmp.get(), tmp.get(), BN_value_one())) {
+      return false;
+    }
+    if (BN_sqrt(ret.get(), tmp.get(), ctx)) {
+      t->PrintLine("BN_sqrt succeeded on a non-square");
+      return false;
+    }
+    ERR_clear_error();
+  }
+
+  return true;
+}
+
+static bool TestProduct(FileTest *t, BN_CTX *ctx) {
+  bssl::UniquePtr<BIGNUM> a = GetBIGNUM(t, "A");
+  bssl::UniquePtr<BIGNUM> b = GetBIGNUM(t, "B");
+  bssl::UniquePtr<BIGNUM> product = GetBIGNUM(t, "Product");
+  bssl::UniquePtr<BIGNUM> zero(BN_new());
+  if (!a || !b || !product || !zero) {
+    return false;
+  }
+
+  BN_zero(zero.get());
+
+  bssl::UniquePtr<BIGNUM> ret(BN_new()), remainder(BN_new());
+  if (!ret || !remainder ||
+      !BN_mul(ret.get(), a.get(), b.get(), ctx) ||
+      !ExpectBIGNUMsEqual(t, "A * B", product.get(), ret.get()) ||
+      !BN_div(ret.get(), remainder.get(), product.get(), a.get(), ctx) ||
+      !ExpectBIGNUMsEqual(t, "Product / A", b.get(), ret.get()) ||
+      !ExpectBIGNUMsEqual(t, "Product % A", zero.get(), remainder.get()) ||
+      !BN_div(ret.get(), remainder.get(), product.get(), b.get(), ctx) ||
+      !ExpectBIGNUMsEqual(t, "Product / B", a.get(), ret.get()) ||
+      !ExpectBIGNUMsEqual(t, "Product % B", zero.get(), remainder.get())) {
+    return false;
+  }
+
+  return true;
+}
+
+static bool TestQuotient(FileTest *t, BN_CTX *ctx) {
+  bssl::UniquePtr<BIGNUM> a = GetBIGNUM(t, "A");
+  bssl::UniquePtr<BIGNUM> b = GetBIGNUM(t, "B");
+  bssl::UniquePtr<BIGNUM> quotient = GetBIGNUM(t, "Quotient");
+  bssl::UniquePtr<BIGNUM> remainder = GetBIGNUM(t, "Remainder");
+  if (!a || !b || !quotient || !remainder) {
+    return false;
+  }
+
+  bssl::UniquePtr<BIGNUM> ret(BN_new()), ret2(BN_new());
+  if (!ret || !ret2 ||
+      !BN_div(ret.get(), ret2.get(), a.get(), b.get(), ctx) ||
+      !ExpectBIGNUMsEqual(t, "A / B", quotient.get(), ret.get()) ||
+      !ExpectBIGNUMsEqual(t, "A % B", remainder.get(), ret2.get()) ||
+      !BN_mul(ret.get(), quotient.get(), b.get(), ctx) ||
+      !BN_add(ret.get(), ret.get(), remainder.get()) ||
+      !ExpectBIGNUMsEqual(t, "Quotient * B + Remainder", a.get(), ret.get())) {
+    return false;
+  }
+
+  // Test with |BN_mod_word| and |BN_div_word| if the divisor is small enough.
+  BN_ULONG b_word = BN_get_word(b.get());
+  if (!BN_is_negative(b.get()) && b_word != (BN_ULONG)-1) {
+    BN_ULONG remainder_word = BN_get_word(remainder.get());
+    assert(remainder_word != (BN_ULONG)-1);
+    if (!BN_copy(ret.get(), a.get())) {
+      return false;
+    }
+    BN_ULONG ret_word = BN_div_word(ret.get(), b_word);
+    if (ret_word != remainder_word) {
+      t->PrintLine("Got A %% B (word) = " BN_HEX_FMT1 ", wanted " BN_HEX_FMT1
+                   "\n",
+                   ret_word, remainder_word);
+      return false;
+    }
+    if (!ExpectBIGNUMsEqual(t, "A / B (word)", quotient.get(), ret.get())) {
+      return false;
+    }
+
+    ret_word = BN_mod_word(a.get(), b_word);
+    if (ret_word != remainder_word) {
+      t->PrintLine("Got A %% B (word) = " BN_HEX_FMT1 ", wanted " BN_HEX_FMT1
+                   "\n",
+                   ret_word, remainder_word);
       return false;
     }
   }
 
-  // Test some non-squares.
-  for (int i = 0; i < 100; i++) {
-    if (!BN_rand(n.get(), 1024 /* bit length */,
-                 -1 /* no modification of top bits */,
-                 0 /* don't modify bottom bit */) ||
-        !BN_mul(nn.get(), n.get(), n.get(), ctx) ||
-        !BN_add(nn.get(), nn.get(), BN_value_one())) {
-      ERR_print_errors_fp(stderr);
+  // Test BN_nnmod.
+  if (!BN_is_negative(b.get())) {
+    bssl::UniquePtr<BIGNUM> nnmod(BN_new());
+    if (!nnmod ||
+        !BN_copy(nnmod.get(), remainder.get()) ||
+        (BN_is_negative(nnmod.get()) &&
+         !BN_add(nnmod.get(), nnmod.get(), b.get())) ||
+        !BN_nnmod(ret.get(), a.get(), b.get(), ctx) ||
+        !ExpectBIGNUMsEqual(t, "A % B (non-negative)", nnmod.get(),
+                            ret.get())) {
       return false;
     }
-
-    if (BN_sqrt(sqrt.get(), nn.get(), ctx)) {
-      char *nn_str = BN_bn2dec(nn.get());
-      fprintf(stderr, "BIO_sqrt didn't fail on a non-square: %s\n", nn_str);
-      OPENSSL_free(nn_str);
-    }
   }
 
   return true;
 }
 
-static bool test_bn2bin_padded(BN_CTX *ctx) {
+static bool TestModMul(FileTest *t, BN_CTX *ctx) {
+  bssl::UniquePtr<BIGNUM> a = GetBIGNUM(t, "A");
+  bssl::UniquePtr<BIGNUM> b = GetBIGNUM(t, "B");
+  bssl::UniquePtr<BIGNUM> m = GetBIGNUM(t, "M");
+  bssl::UniquePtr<BIGNUM> mod_mul = GetBIGNUM(t, "ModMul");
+  if (!a || !b || !m || !mod_mul) {
+    return false;
+  }
+
+  bssl::UniquePtr<BIGNUM> ret(BN_new());
+  if (!ret ||
+      !BN_mod_mul(ret.get(), a.get(), b.get(), m.get(), ctx) ||
+      !ExpectBIGNUMsEqual(t, "A * B (mod M)", mod_mul.get(), ret.get())) {
+    return false;
+  }
+
+  if (BN_is_odd(m.get())) {
+    // Reduce |a| and |b| and test the Montgomery version.
+    bssl::UniquePtr<BN_MONT_CTX> mont(BN_MONT_CTX_new());
+    bssl::UniquePtr<BIGNUM> a_tmp(BN_new()), b_tmp(BN_new());
+    if (!mont || !a_tmp || !b_tmp ||
+        !BN_MONT_CTX_set(mont.get(), m.get(), ctx) ||
+        !BN_nnmod(a_tmp.get(), a.get(), m.get(), ctx) ||
+        !BN_nnmod(b_tmp.get(), b.get(), m.get(), ctx) ||
+        !BN_to_montgomery(a_tmp.get(), a_tmp.get(), mont.get(), ctx) ||
+        !BN_to_montgomery(b_tmp.get(), b_tmp.get(), mont.get(), ctx) ||
+        !BN_mod_mul_montgomery(ret.get(), a_tmp.get(), b_tmp.get(), mont.get(),
+                               ctx) ||
+        !BN_from_montgomery(ret.get(), ret.get(), mont.get(), ctx) ||
+        !ExpectBIGNUMsEqual(t, "A * B (mod M) (Montgomery)",
+                            mod_mul.get(), ret.get())) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+static bool TestModSquare(FileTest *t, BN_CTX *ctx) {
+  bssl::UniquePtr<BIGNUM> a = GetBIGNUM(t, "A");
+  bssl::UniquePtr<BIGNUM> m = GetBIGNUM(t, "M");
+  bssl::UniquePtr<BIGNUM> mod_square = GetBIGNUM(t, "ModSquare");
+  if (!a || !m || !mod_square) {
+    return false;
+  }
+
+  bssl::UniquePtr<BIGNUM> a_copy(BN_new());
+  bssl::UniquePtr<BIGNUM> ret(BN_new());
+  if (!ret || !a_copy ||
+      !BN_mod_mul(ret.get(), a.get(), a.get(), m.get(), ctx) ||
+      !ExpectBIGNUMsEqual(t, "A * A (mod M)", mod_square.get(), ret.get()) ||
+      // Repeat the operation with |a_copy|.
+      !BN_copy(a_copy.get(), a.get()) ||
+      !BN_mod_mul(ret.get(), a.get(), a_copy.get(), m.get(), ctx) ||
+      !ExpectBIGNUMsEqual(t, "A * A_copy (mod M)", mod_square.get(),
+                          ret.get())) {
+    return false;
+  }
+
+  if (BN_is_odd(m.get())) {
+    // Reduce |a| and test the Montgomery version.
+    bssl::UniquePtr<BN_MONT_CTX> mont(BN_MONT_CTX_new());
+    bssl::UniquePtr<BIGNUM> a_tmp(BN_new());
+    if (!mont || !a_tmp ||
+        !BN_MONT_CTX_set(mont.get(), m.get(), ctx) ||
+        !BN_nnmod(a_tmp.get(), a.get(), m.get(), ctx) ||
+        !BN_to_montgomery(a_tmp.get(), a_tmp.get(), mont.get(), ctx) ||
+        !BN_mod_mul_montgomery(ret.get(), a_tmp.get(), a_tmp.get(), mont.get(),
+                               ctx) ||
+        !BN_from_montgomery(ret.get(), ret.get(), mont.get(), ctx) ||
+        !ExpectBIGNUMsEqual(t, "A * A (mod M) (Montgomery)",
+                            mod_square.get(), ret.get()) ||
+        // Repeat the operation with |a_copy|.
+        !BN_copy(a_copy.get(), a_tmp.get()) ||
+        !BN_mod_mul_montgomery(ret.get(), a_tmp.get(), a_copy.get(), mont.get(),
+                               ctx) ||
+        !BN_from_montgomery(ret.get(), ret.get(), mont.get(), ctx) ||
+        !ExpectBIGNUMsEqual(t, "A * A_copy (mod M) (Montgomery)",
+                            mod_square.get(), ret.get())) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+static bool TestModExp(FileTest *t, BN_CTX *ctx) {
+  bssl::UniquePtr<BIGNUM> a = GetBIGNUM(t, "A");
+  bssl::UniquePtr<BIGNUM> e = GetBIGNUM(t, "E");
+  bssl::UniquePtr<BIGNUM> m = GetBIGNUM(t, "M");
+  bssl::UniquePtr<BIGNUM> mod_exp = GetBIGNUM(t, "ModExp");
+  if (!a || !e || !m || !mod_exp) {
+    return false;
+  }
+
+  bssl::UniquePtr<BIGNUM> ret(BN_new());
+  if (!ret ||
+      !BN_mod_exp(ret.get(), a.get(), e.get(), m.get(), ctx) ||
+      !ExpectBIGNUMsEqual(t, "A ^ E (mod M)", mod_exp.get(), ret.get())) {
+    return false;
+  }
+
+  if (BN_is_odd(m.get())) {
+    if (!BN_mod_exp_mont(ret.get(), a.get(), e.get(), m.get(), ctx, NULL) ||
+        !ExpectBIGNUMsEqual(t, "A ^ E (mod M) (Montgomery)", mod_exp.get(),
+                            ret.get()) ||
+        !BN_mod_exp_mont_consttime(ret.get(), a.get(), e.get(), m.get(), ctx,
+                                   NULL) ||
+        !ExpectBIGNUMsEqual(t, "A ^ E (mod M) (constant-time)", mod_exp.get(),
+                            ret.get())) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+static bool TestExp(FileTest *t, BN_CTX *ctx) {
+  bssl::UniquePtr<BIGNUM> a = GetBIGNUM(t, "A");
+  bssl::UniquePtr<BIGNUM> e = GetBIGNUM(t, "E");
+  bssl::UniquePtr<BIGNUM> exp = GetBIGNUM(t, "Exp");
+  if (!a || !e || !exp) {
+    return false;
+  }
+
+  bssl::UniquePtr<BIGNUM> ret(BN_new());
+  if (!ret ||
+      !BN_exp(ret.get(), a.get(), e.get(), ctx) ||
+      !ExpectBIGNUMsEqual(t, "A ^ E", exp.get(), ret.get())) {
+    return false;
+  }
+
+  return true;
+}
+
+static bool TestModSqrt(FileTest *t, BN_CTX *ctx) {
+  bssl::UniquePtr<BIGNUM> a = GetBIGNUM(t, "A");
+  bssl::UniquePtr<BIGNUM> p = GetBIGNUM(t, "P");
+  bssl::UniquePtr<BIGNUM> mod_sqrt = GetBIGNUM(t, "ModSqrt");
+  bssl::UniquePtr<BIGNUM> mod_sqrt2(BN_new());
+  if (!a || !p || !mod_sqrt || !mod_sqrt2 ||
+      // There are two possible answers.
+      !BN_sub(mod_sqrt2.get(), p.get(), mod_sqrt.get())) {
+    return false;
+  }
+
+  // -0 is 0, not P.
+  if (BN_is_zero(mod_sqrt.get())) {
+    BN_zero(mod_sqrt2.get());
+  }
+
+  bssl::UniquePtr<BIGNUM> ret(BN_new());
+  if (!ret ||
+      !BN_mod_sqrt(ret.get(), a.get(), p.get(), ctx)) {
+    return false;
+  }
+
+  if (BN_cmp(ret.get(), mod_sqrt2.get()) != 0 &&
+      !ExpectBIGNUMsEqual(t, "sqrt(A) (mod P)", mod_sqrt.get(), ret.get())) {
+    return false;
+  }
+
+  return true;
+}
+
+static bool TestNotModSquare(FileTest *t, BN_CTX *ctx) {
+  bssl::UniquePtr<BIGNUM> not_mod_square = GetBIGNUM(t, "NotModSquare");
+  bssl::UniquePtr<BIGNUM> p = GetBIGNUM(t, "P");
+  bssl::UniquePtr<BIGNUM> ret(BN_new());
+  if (!not_mod_square || !p || !ret) {
+    return false;
+  }
+
+  if (BN_mod_sqrt(ret.get(), not_mod_square.get(), p.get(), ctx)) {
+    t->PrintLine("BN_mod_sqrt unexpectedly succeeded.");
+    return false;
+  }
+
+  uint32_t err = ERR_peek_error();
+  if (ERR_GET_LIB(err) == ERR_LIB_BN &&
+      ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE) {
+    ERR_clear_error();
+    return true;
+  }
+
+  return false;
+}
+
+static bool TestModInv(FileTest *t, BN_CTX *ctx) {
+  bssl::UniquePtr<BIGNUM> a = GetBIGNUM(t, "A");
+  bssl::UniquePtr<BIGNUM> m = GetBIGNUM(t, "M");
+  bssl::UniquePtr<BIGNUM> mod_inv = GetBIGNUM(t, "ModInv");
+  if (!a || !m || !mod_inv) {
+    return false;
+  }
+
+  bssl::UniquePtr<BIGNUM> ret(BN_new());
+  if (!ret ||
+      !BN_mod_inverse(ret.get(), a.get(), m.get(), ctx) ||
+      !ExpectBIGNUMsEqual(t, "inv(A) (mod M)", mod_inv.get(), ret.get())) {
+    return false;
+  }
+
+  return true;
+}
+
+struct Test {
+  const char *name;
+  bool (*func)(FileTest *t, BN_CTX *ctx);
+};
+
+static const Test kTests[] = {
+    {"Sum", TestSum},
+    {"LShift1", TestLShift1},
+    {"LShift", TestLShift},
+    {"RShift", TestRShift},
+    {"Square", TestSquare},
+    {"Product", TestProduct},
+    {"Quotient", TestQuotient},
+    {"ModMul", TestModMul},
+    {"ModSquare", TestModSquare},
+    {"ModExp", TestModExp},
+    {"Exp", TestExp},
+    {"ModSqrt", TestModSqrt},
+    {"NotModSquare", TestNotModSquare},
+    {"ModInv", TestModInv},
+};
+
+static bool RunTest(FileTest *t, void *arg) {
+  BN_CTX *ctx = reinterpret_cast<BN_CTX *>(arg);
+  for (const Test &test : kTests) {
+    if (t->GetType() != test.name) {
+      continue;
+    }
+    return test.func(t, ctx);
+  }
+  t->PrintLine("Unknown test type: %s", t->GetType().c_str());
+  return false;
+}
+
+static bool TestBN2BinPadded(BN_CTX *ctx) {
   uint8_t zeros[256], out[256], reference[128];
 
-  memset(zeros, 0, sizeof(zeros));
+  OPENSSL_memset(zeros, 0, sizeof(zeros));
 
   // Test edge case at 0.
-  ScopedBIGNUM n(BN_new());
+  bssl::UniquePtr<BIGNUM> n(BN_new());
   if (!n || !BN_bn2bin_padded(NULL, 0, n.get())) {
     fprintf(stderr,
             "BN_bn2bin_padded failed to encode 0 in an empty buffer.\n");
     return false;
   }
-  memset(out, -1, sizeof(out));
+  OPENSSL_memset(out, -1, sizeof(out));
   if (!BN_bn2bin_padded(out, sizeof(out), n.get())) {
     fprintf(stderr,
             "BN_bn2bin_padded failed to encode 0 in a non-empty buffer.\n");
     return false;
   }
-  if (memcmp(zeros, out, sizeof(out))) {
+  if (OPENSSL_memcmp(zeros, out, sizeof(out))) {
     fprintf(stderr, "BN_bn2bin_padded did not zero buffer.\n");
     return false;
   }
 
   // Test a random numbers at various byte lengths.
   for (size_t bytes = 128 - 7; bytes <= 128; bytes++) {
-    if (!BN_rand(n.get(), bytes * 8, 0 /* make sure top bit is 1 */,
-                 0 /* don't modify bottom bit */)) {
+    if (!BN_rand(n.get(), bytes * 8, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY)) {
       ERR_print_errors_fp(stderr);
       return false;
     }
@@ -1516,20 +764,21 @@
     }
     // Exactly right size should encode.
     if (!BN_bn2bin_padded(out, bytes, n.get()) ||
-        memcmp(out, reference, bytes) != 0) {
+        OPENSSL_memcmp(out, reference, bytes) != 0) {
       fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n");
       return false;
     }
     // Pad up one byte extra.
     if (!BN_bn2bin_padded(out, bytes + 1, n.get()) ||
-        memcmp(out + 1, reference, bytes) || memcmp(out, zeros, 1)) {
+        OPENSSL_memcmp(out + 1, reference, bytes) ||
+        OPENSSL_memcmp(out, zeros, 1)) {
       fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n");
       return false;
     }
     // Pad up to 256.
     if (!BN_bn2bin_padded(out, sizeof(out), n.get()) ||
-        memcmp(out + sizeof(out) - bytes, reference, bytes) ||
-        memcmp(out, zeros, sizeof(out) - bytes)) {
+        OPENSSL_memcmp(out + sizeof(out) - bytes, reference, bytes) ||
+        OPENSSL_memcmp(out, zeros, sizeof(out) - bytes)) {
       fprintf(stderr, "BN_bn2bin_padded gave a bad result.\n");
       return false;
     }
@@ -1538,15 +787,91 @@
   return true;
 }
 
-static int DecimalToBIGNUM(ScopedBIGNUM *out, const char *in) {
+static bool TestLittleEndian() {
+  bssl::UniquePtr<BIGNUM> x(BN_new());
+  bssl::UniquePtr<BIGNUM> y(BN_new());
+  if (!x || !y) {
+    fprintf(stderr, "BN_new failed to malloc.\n");
+    return false;
+  }
+
+  // Test edge case at 0. Fill |out| with garbage to ensure |BN_bn2le_padded|
+  // wrote the result.
+  uint8_t out[256], zeros[256];
+  OPENSSL_memset(out, -1, sizeof(out));
+  OPENSSL_memset(zeros, 0, sizeof(zeros));
+  if (!BN_bn2le_padded(out, sizeof(out), x.get()) ||
+      OPENSSL_memcmp(zeros, out, sizeof(out))) {
+    fprintf(stderr, "BN_bn2le_padded failed to encode 0.\n");
+    return false;
+  }
+
+  if (!BN_le2bn(out, sizeof(out), y.get()) ||
+      BN_cmp(x.get(), y.get()) != 0) {
+    fprintf(stderr, "BN_le2bn failed to decode 0 correctly.\n");
+    return false;
+  }
+
+  // Test random numbers at various byte lengths.
+  for (size_t bytes = 128 - 7; bytes <= 128; bytes++) {
+    if (!BN_rand(x.get(), bytes * 8, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY)) {
+      ERR_print_errors_fp(stderr);
+      return false;
+    }
+
+    // Fill |out| with garbage to ensure |BN_bn2le_padded| wrote the result.
+    OPENSSL_memset(out, -1, sizeof(out));
+    if (!BN_bn2le_padded(out, sizeof(out), x.get())) {
+      fprintf(stderr, "BN_bn2le_padded failed to encode random value.\n");
+      return false;
+    }
+
+    // Compute the expected value by reversing the big-endian output.
+    uint8_t expected[sizeof(out)];
+    if (!BN_bn2bin_padded(expected, sizeof(expected), x.get())) {
+      return false;
+    }
+    for (size_t i = 0; i < sizeof(expected) / 2; i++) {
+      uint8_t tmp = expected[i];
+      expected[i] = expected[sizeof(expected) - 1 - i];
+      expected[sizeof(expected) - 1 - i] = tmp;
+    }
+
+    if (OPENSSL_memcmp(expected, out, sizeof(out))) {
+      fprintf(stderr, "BN_bn2le_padded failed to encode value correctly.\n");
+      hexdump(stderr, "Expected: ", expected, sizeof(expected));
+      hexdump(stderr, "Got:      ", out, sizeof(out));
+      return false;
+    }
+
+    // Make sure the decoding produces the same BIGNUM.
+    if (!BN_le2bn(out, bytes, y.get()) ||
+        BN_cmp(x.get(), y.get()) != 0) {
+      bssl::UniquePtr<char> x_hex(BN_bn2hex(x.get())),
+          y_hex(BN_bn2hex(y.get()));
+      if (!x_hex || !y_hex) {
+        return false;
+      }
+      fprintf(stderr, "BN_le2bn failed to decode value correctly.\n");
+      fprintf(stderr, "Expected: %s\n", x_hex.get());
+      hexdump(stderr, "Encoding: ", out, bytes);
+      fprintf(stderr, "Got:      %s\n", y_hex.get());
+      return false;
+    }
+  }
+
+  return true;
+}
+
+static int DecimalToBIGNUM(bssl::UniquePtr<BIGNUM> *out, const char *in) {
   BIGNUM *raw = NULL;
   int ret = BN_dec2bn(&raw, in);
   out->reset(raw);
   return ret;
 }
 
-static bool test_dec2bn(BN_CTX *ctx) {
-  ScopedBIGNUM bn;
+static bool TestDec2BN(BN_CTX *ctx) {
+  bssl::UniquePtr<BIGNUM> bn;
   int ret = DecimalToBIGNUM(&bn, "0");
   if (ret != 1 || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) {
     fprintf(stderr, "BN_dec2bn gave a bad result.\n");
@@ -1580,8 +905,8 @@
   return true;
 }
 
-static bool test_hex2bn(BN_CTX *ctx) {
-  ScopedBIGNUM bn;
+static bool TestHex2BN(BN_CTX *ctx) {
+  bssl::UniquePtr<BIGNUM> bn;
   int ret = HexToBIGNUM(&bn, "0");
   if (ret != 1 || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) {
     fprintf(stderr, "BN_hex2bn gave a bad result.\n");
@@ -1615,16 +940,16 @@
   return true;
 }
 
-static ScopedBIGNUM ASCIIToBIGNUM(const char *in) {
+static bssl::UniquePtr<BIGNUM> ASCIIToBIGNUM(const char *in) {
   BIGNUM *raw = NULL;
   if (!BN_asc2bn(&raw, in)) {
     return nullptr;
   }
-  return ScopedBIGNUM(raw);
+  return bssl::UniquePtr<BIGNUM>(raw);
 }
 
-static bool test_asc2bn(BN_CTX *ctx) {
-  ScopedBIGNUM bn = ASCIIToBIGNUM("0");
+static bool TestASC2BN(BN_CTX *ctx) {
+  bssl::UniquePtr<BIGNUM> bn = ASCIIToBIGNUM("0");
   if (!bn || !BN_is_zero(bn.get()) || BN_is_negative(bn.get())) {
     fprintf(stderr, "BN_asc2bn gave a bad result.\n");
     return false;
@@ -1690,12 +1015,16 @@
   { "-256", "\x00\x00\x00\x02\x81\x00", 6 },
 };
 
-static bool test_mpi() {
+static bool TestMPI() {
   uint8_t scratch[8];
 
-  for (size_t i = 0; i < sizeof(kMPITests) / sizeof(kMPITests[0]); i++) {
+  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kMPITests); i++) {
     const MPITest &test = kMPITests[i];
-    ScopedBIGNUM bn(ASCIIToBIGNUM(test.base10));
+    bssl::UniquePtr<BIGNUM> bn(ASCIIToBIGNUM(test.base10));
+    if (!bn) {
+      return false;
+    }
+
     const size_t mpi_len = BN_bn2mpi(bn.get(), NULL);
     if (mpi_len > sizeof(scratch)) {
       fprintf(stderr, "MPI test #%u: MPI size is too large to test.\n",
@@ -1710,14 +1039,14 @@
     }
 
     if (mpi_len != test.mpi_len ||
-        memcmp(test.mpi, scratch, mpi_len) != 0) {
+        OPENSSL_memcmp(test.mpi, scratch, mpi_len) != 0) {
       fprintf(stderr, "MPI test #%u failed:\n", (unsigned)i);
       hexdump(stderr, "Expected: ", test.mpi, test.mpi_len);
       hexdump(stderr, "Got:      ", scratch, mpi_len);
       return false;
     }
 
-    ScopedBIGNUM bn2(BN_mpi2bn(scratch, mpi_len, NULL));
+    bssl::UniquePtr<BIGNUM> bn2(BN_mpi2bn(scratch, mpi_len, NULL));
     if (bn2.get() == nullptr) {
       fprintf(stderr, "MPI test #%u: failed to parse\n", (unsigned)i);
       return false;
@@ -1732,42 +1061,42 @@
   return true;
 }
 
-static bool test_rand() {
-  ScopedBIGNUM bn(BN_new());
+static bool TestRand() {
+  bssl::UniquePtr<BIGNUM> bn(BN_new());
   if (!bn) {
     return false;
   }
 
   // Test BN_rand accounts for degenerate cases with |top| and |bottom|
   // parameters.
-  if (!BN_rand(bn.get(), 0, 0 /* top */, 0 /* bottom */) ||
+  if (!BN_rand(bn.get(), 0, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY) ||
       !BN_is_zero(bn.get())) {
     fprintf(stderr, "BN_rand gave a bad result.\n");
     return false;
   }
-  if (!BN_rand(bn.get(), 0, 1 /* top */, 1 /* bottom */) ||
+  if (!BN_rand(bn.get(), 0, BN_RAND_TOP_TWO, BN_RAND_BOTTOM_ODD) ||
       !BN_is_zero(bn.get())) {
     fprintf(stderr, "BN_rand gave a bad result.\n");
     return false;
   }
 
-  if (!BN_rand(bn.get(), 1, 0 /* top */, 0 /* bottom */) ||
+  if (!BN_rand(bn.get(), 1, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY) ||
       !BN_is_word(bn.get(), 1)) {
     fprintf(stderr, "BN_rand gave a bad result.\n");
     return false;
   }
-  if (!BN_rand(bn.get(), 1, 1 /* top */, 0 /* bottom */) ||
+  if (!BN_rand(bn.get(), 1, BN_RAND_TOP_TWO, BN_RAND_BOTTOM_ANY) ||
       !BN_is_word(bn.get(), 1)) {
     fprintf(stderr, "BN_rand gave a bad result.\n");
     return false;
   }
-  if (!BN_rand(bn.get(), 1, -1 /* top */, 1 /* bottom */) ||
+  if (!BN_rand(bn.get(), 1, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ODD) ||
       !BN_is_word(bn.get(), 1)) {
     fprintf(stderr, "BN_rand gave a bad result.\n");
     return false;
   }
 
-  if (!BN_rand(bn.get(), 2, 1 /* top */, 0 /* bottom */) ||
+  if (!BN_rand(bn.get(), 2, BN_RAND_TOP_TWO, BN_RAND_BOTTOM_ANY) ||
       !BN_is_word(bn.get(), 3)) {
     fprintf(stderr, "BN_rand gave a bad result.\n");
     return false;
@@ -1806,8 +1135,8 @@
     {"\x02\x00", 2},
 };
 
-// kASN1BuggyTests are incorrect encodings and how |BN_cbs2unsigned_buggy|
-// should interpret them.
+// kASN1BuggyTests contains incorrect encodings and the corresponding, expected
+// results of |BN_parse_asn1_unsigned_buggy| given that input.
 static const ASN1Test kASN1BuggyTests[] = {
     // Negative numbers.
     {"128", "\x02\x01\x80", 3},
@@ -1816,21 +1145,21 @@
     {"1", "\x02\x02\x00\x01", 4},
 };
 
-static bool test_asn1() {
+static bool TestASN1() {
   for (const ASN1Test &test : kASN1Tests) {
-    ScopedBIGNUM bn = ASCIIToBIGNUM(test.value_ascii);
+    bssl::UniquePtr<BIGNUM> bn = ASCIIToBIGNUM(test.value_ascii);
     if (!bn) {
       return false;
     }
 
     // Test that the input is correctly parsed.
-    ScopedBIGNUM bn2(BN_new());
+    bssl::UniquePtr<BIGNUM> bn2(BN_new());
     if (!bn2) {
       return false;
     }
     CBS cbs;
     CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
-    if (!BN_cbs2unsigned(&cbs, bn2.get()) || CBS_len(&cbs) != 0) {
+    if (!BN_parse_asn1_unsigned(&cbs, bn2.get()) || CBS_len(&cbs) != 0) {
       fprintf(stderr, "Parsing ASN.1 INTEGER failed.\n");
       return false;
     }
@@ -1840,26 +1169,25 @@
     }
 
     // Test the value serializes correctly.
-    CBB cbb;
+    bssl::ScopedCBB cbb;
     uint8_t *der;
     size_t der_len;
-    CBB_zero(&cbb);
-    if (!CBB_init(&cbb, 0) ||
-        !BN_bn2cbb(&cbb, bn.get()) ||
-        !CBB_finish(&cbb, &der, &der_len)) {
-      CBB_cleanup(&cbb);
+    if (!CBB_init(cbb.get(), 0) ||
+        !BN_marshal_asn1(cbb.get(), bn.get()) ||
+        !CBB_finish(cbb.get(), &der, &der_len)) {
       return false;
     }
-    ScopedOpenSSLBytes delete_der(der);
+    bssl::UniquePtr<uint8_t> delete_der(der);
     if (der_len != test.der_len ||
-        memcmp(der, reinterpret_cast<const uint8_t*>(test.der), der_len) != 0) {
+        OPENSSL_memcmp(der, reinterpret_cast<const uint8_t *>(test.der),
+                       der_len) != 0) {
       fprintf(stderr, "Bad serialization.\n");
       return false;
     }
 
-    // |BN_cbs2unsigned_buggy| parses all valid input.
+    // |BN_parse_asn1_unsigned_buggy| parses all valid input.
     CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
-    if (!BN_cbs2unsigned_buggy(&cbs, bn2.get()) || CBS_len(&cbs) != 0) {
+    if (!BN_parse_asn1_unsigned_buggy(&cbs, bn2.get()) || CBS_len(&cbs) != 0) {
       fprintf(stderr, "Parsing ASN.1 INTEGER failed.\n");
       return false;
     }
@@ -1870,22 +1198,22 @@
   }
 
   for (const ASN1InvalidTest &test : kASN1InvalidTests) {
-    ScopedBIGNUM bn(BN_new());
+    bssl::UniquePtr<BIGNUM> bn(BN_new());
     if (!bn) {
       return false;
     }
     CBS cbs;
     CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
-    if (BN_cbs2unsigned(&cbs, bn.get())) {
+    if (BN_parse_asn1_unsigned(&cbs, bn.get())) {
       fprintf(stderr, "Parsed invalid input.\n");
       return false;
     }
     ERR_clear_error();
 
     // All tests in kASN1InvalidTests are also rejected by
-    // |BN_cbs2unsigned_buggy|.
+    // |BN_parse_asn1_unsigned_buggy|.
     CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
-    if (BN_cbs2unsigned_buggy(&cbs, bn.get())) {
+    if (BN_parse_asn1_unsigned_buggy(&cbs, bn.get())) {
       fprintf(stderr, "Parsed invalid input.\n");
       return false;
     }
@@ -1893,28 +1221,28 @@
   }
 
   for (const ASN1Test &test : kASN1BuggyTests) {
-    // These broken encodings are rejected by |BN_cbs2unsigned|.
-    ScopedBIGNUM bn(BN_new());
+    // These broken encodings are rejected by |BN_parse_asn1_unsigned|.
+    bssl::UniquePtr<BIGNUM> bn(BN_new());
     if (!bn) {
       return false;
     }
 
     CBS cbs;
     CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
-    if (BN_cbs2unsigned(&cbs, bn.get())) {
+    if (BN_parse_asn1_unsigned(&cbs, bn.get())) {
       fprintf(stderr, "Parsed invalid input.\n");
       return false;
     }
     ERR_clear_error();
 
-    // However |BN_cbs2unsigned_buggy| accepts them.
-    ScopedBIGNUM bn2 = ASCIIToBIGNUM(test.value_ascii);
+    // However |BN_parse_asn1_unsigned_buggy| accepts them.
+    bssl::UniquePtr<BIGNUM> bn2 = ASCIIToBIGNUM(test.value_ascii);
     if (!bn2) {
       return false;
     }
 
     CBS_init(&cbs, reinterpret_cast<const uint8_t*>(test.der), test.der_len);
-    if (!BN_cbs2unsigned_buggy(&cbs, bn.get()) || CBS_len(&cbs) != 0) {
+    if (!BN_parse_asn1_unsigned_buggy(&cbs, bn.get()) || CBS_len(&cbs) != 0) {
       fprintf(stderr, "Parsing (invalid) ASN.1 INTEGER failed.\n");
       return false;
     }
@@ -1926,19 +1254,324 @@
   }
 
   // Serializing negative numbers is not supported.
-  ScopedBIGNUM bn = ASCIIToBIGNUM("-1");
+  bssl::UniquePtr<BIGNUM> bn = ASCIIToBIGNUM("-1");
   if (!bn) {
     return false;
   }
-  CBB cbb;
-  CBB_zero(&cbb);
-  if (!CBB_init(&cbb, 0) ||
-      BN_bn2cbb(&cbb, bn.get())) {
+  bssl::ScopedCBB cbb;
+  if (!CBB_init(cbb.get(), 0) ||
+      BN_marshal_asn1(cbb.get(), bn.get())) {
     fprintf(stderr, "Serialized negative number.\n");
-    CBB_cleanup(&cbb);
     return false;
   }
-  CBB_cleanup(&cbb);
+  ERR_clear_error();
+
+  return true;
+}
+
+static bool TestNegativeZero(BN_CTX *ctx) {
+  bssl::UniquePtr<BIGNUM> a(BN_new());
+  bssl::UniquePtr<BIGNUM> b(BN_new());
+  bssl::UniquePtr<BIGNUM> c(BN_new());
+  if (!a || !b || !c) {
+    return false;
+  }
+
+  // Test that BN_mul never gives negative zero.
+  if (!BN_set_word(a.get(), 1)) {
+    return false;
+  }
+  BN_set_negative(a.get(), 1);
+  BN_zero(b.get());
+  if (!BN_mul(c.get(), a.get(), b.get(), ctx)) {
+    return false;
+  }
+  if (!BN_is_zero(c.get()) || BN_is_negative(c.get())) {
+    fprintf(stderr, "Multiplication test failed.\n");
+    return false;
+  }
+
+  bssl::UniquePtr<BIGNUM> numerator(BN_new()), denominator(BN_new());
+  if (!numerator || !denominator) {
+    return false;
+  }
+
+  // Test that BN_div never gives negative zero in the quotient.
+  if (!BN_set_word(numerator.get(), 1) ||
+      !BN_set_word(denominator.get(), 2)) {
+    return false;
+  }
+  BN_set_negative(numerator.get(), 1);
+  if (!BN_div(a.get(), b.get(), numerator.get(), denominator.get(), ctx)) {
+    return false;
+  }
+  if (!BN_is_zero(a.get()) || BN_is_negative(a.get())) {
+    fprintf(stderr, "Incorrect quotient.\n");
+    return false;
+  }
+
+  // Test that BN_div never gives negative zero in the remainder.
+  if (!BN_set_word(denominator.get(), 1)) {
+    return false;
+  }
+  if (!BN_div(a.get(), b.get(), numerator.get(), denominator.get(), ctx)) {
+    return false;
+  }
+  if (!BN_is_zero(b.get()) || BN_is_negative(b.get())) {
+    fprintf(stderr, "Incorrect remainder.\n");
+    return false;
+  }
+
+  // Test that BN_set_negative will not produce a negative zero.
+  BN_zero(a.get());
+  BN_set_negative(a.get(), 1);
+  if (BN_is_negative(a.get())) {
+    fprintf(stderr, "BN_set_negative produced a negative zero.\n");
+    return false;
+  }
+
+  // Test that forcibly creating a negative zero does not break |BN_bn2hex| or
+  // |BN_bn2dec|.
+  a->neg = 1;
+  bssl::UniquePtr<char> dec(BN_bn2dec(a.get()));
+  bssl::UniquePtr<char> hex(BN_bn2hex(a.get()));
+  if (!dec || !hex ||
+      strcmp(dec.get(), "-0") != 0 ||
+      strcmp(hex.get(), "-0") != 0) {
+    fprintf(stderr, "BN_bn2dec or BN_bn2hex failed with negative zero.\n");
+    return false;
+  }
+
+  // Test that |BN_rshift| and |BN_rshift1| will not produce a negative zero.
+  if (!BN_set_word(a.get(), 1)) {
+    return false;
+  }
+
+  BN_set_negative(a.get(), 1);
+  if (!BN_rshift(b.get(), a.get(), 1) ||
+      !BN_rshift1(c.get(), a.get())) {
+    return false;
+  }
+
+  if (!BN_is_zero(b.get()) || BN_is_negative(b.get())) {
+    fprintf(stderr, "BN_rshift(-1, 1) produced the wrong result.\n");
+    return false;
+  }
+
+  if (!BN_is_zero(c.get()) || BN_is_negative(c.get())) {
+    fprintf(stderr, "BN_rshift1(-1) produced the wrong result.\n");
+    return false;
+  }
+
+  // Test that |BN_div_word| will not produce a negative zero.
+  if (BN_div_word(a.get(), 2) == (BN_ULONG)-1) {
+    return false;
+  }
+
+  if (!BN_is_zero(a.get()) || BN_is_negative(a.get())) {
+    fprintf(stderr, "BN_div_word(-1, 2) produced the wrong result.\n");
+    return false;
+  }
+
+  return true;
+}
+
+static bool TestBadModulus(BN_CTX *ctx) {
+  bssl::UniquePtr<BIGNUM> a(BN_new());
+  bssl::UniquePtr<BIGNUM> b(BN_new());
+  bssl::UniquePtr<BIGNUM> zero(BN_new());
+  bssl::UniquePtr<BN_MONT_CTX> mont(BN_MONT_CTX_new());
+  if (!a || !b || !zero || !mont) {
+    return false;
+  }
+
+  BN_zero(zero.get());
+
+  if (BN_div(a.get(), b.get(), BN_value_one(), zero.get(), ctx)) {
+    fprintf(stderr, "Division by zero unexpectedly succeeded.\n");
+    return false;
+  }
+  ERR_clear_error();
+
+  if (BN_mod_mul(a.get(), BN_value_one(), BN_value_one(), zero.get(), ctx)) {
+    fprintf(stderr, "BN_mod_mul with zero modulus unexpectedly succeeded.\n");
+    return false;
+  }
+  ERR_clear_error();
+
+  if (BN_mod_exp(a.get(), BN_value_one(), BN_value_one(), zero.get(), ctx)) {
+    fprintf(stderr, "BN_mod_exp with zero modulus unexpectedly succeeded.\n");
+    return 0;
+  }
+  ERR_clear_error();
+
+  if (BN_mod_exp_mont(a.get(), BN_value_one(), BN_value_one(), zero.get(), ctx,
+                      NULL)) {
+    fprintf(stderr,
+            "BN_mod_exp_mont with zero modulus unexpectedly succeeded.\n");
+    return 0;
+  }
+  ERR_clear_error();
+
+  if (BN_mod_exp_mont_consttime(a.get(), BN_value_one(), BN_value_one(),
+                                zero.get(), ctx, nullptr)) {
+    fprintf(stderr,
+            "BN_mod_exp_mont_consttime with zero modulus unexpectedly "
+            "succeeded.\n");
+    return 0;
+  }
+  ERR_clear_error();
+
+  if (BN_MONT_CTX_set(mont.get(), zero.get(), ctx)) {
+    fprintf(stderr,
+            "BN_MONT_CTX_set unexpectedly succeeded for zero modulus.\n");
+    return false;
+  }
+  ERR_clear_error();
+
+  // Some operations also may not be used with an even modulus.
+
+  if (!BN_set_word(b.get(), 16)) {
+    return false;
+  }
+
+  if (BN_MONT_CTX_set(mont.get(), b.get(), ctx)) {
+    fprintf(stderr,
+            "BN_MONT_CTX_set unexpectedly succeeded for even modulus.\n");
+    return false;
+  }
+  ERR_clear_error();
+
+  if (BN_mod_exp_mont(a.get(), BN_value_one(), BN_value_one(), b.get(), ctx,
+                      NULL)) {
+    fprintf(stderr,
+            "BN_mod_exp_mont with even modulus unexpectedly succeeded.\n");
+    return 0;
+  }
+  ERR_clear_error();
+
+  if (BN_mod_exp_mont_consttime(a.get(), BN_value_one(), BN_value_one(),
+                                b.get(), ctx, nullptr)) {
+    fprintf(stderr,
+            "BN_mod_exp_mont_consttime with even modulus unexpectedly "
+            "succeeded.\n");
+    return 0;
+  }
+  ERR_clear_error();
+
+  return true;
+}
+
+// TestExpModZero tests that 1**0 mod 1 == 0.
+static bool TestExpModZero() {
+  bssl::UniquePtr<BIGNUM> zero(BN_new()), a(BN_new()), r(BN_new());
+  if (!zero || !a || !r ||
+      !BN_rand(a.get(), 1024, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY)) {
+    return false;
+  }
+  BN_zero(zero.get());
+
+  if (!BN_mod_exp(r.get(), a.get(), zero.get(), BN_value_one(), nullptr) ||
+      !BN_is_zero(r.get()) ||
+      !BN_mod_exp_mont(r.get(), a.get(), zero.get(), BN_value_one(), nullptr,
+                       nullptr) ||
+      !BN_is_zero(r.get()) ||
+      !BN_mod_exp_mont_consttime(r.get(), a.get(), zero.get(), BN_value_one(),
+                                 nullptr, nullptr) ||
+      !BN_is_zero(r.get()) ||
+      !BN_mod_exp_mont_word(r.get(), 42, zero.get(), BN_value_one(), nullptr,
+                            nullptr) ||
+      !BN_is_zero(r.get())) {
+    return false;
+  }
+
+  return true;
+}
+
+static bool TestSmallPrime(BN_CTX *ctx) {
+  static const unsigned kBits = 10;
+
+  bssl::UniquePtr<BIGNUM> r(BN_new());
+  if (!r || !BN_generate_prime_ex(r.get(), static_cast<int>(kBits), 0, NULL,
+                                  NULL, NULL)) {
+    return false;
+  }
+  if (BN_num_bits(r.get()) != kBits) {
+    fprintf(stderr, "Expected %u bit prime, got %u bit number\n", kBits,
+            BN_num_bits(r.get()));
+    return false;
+  }
+
+  return true;
+}
+
+static bool TestCmpWord() {
+  static const BN_ULONG kMaxWord = (BN_ULONG)-1;
+
+  bssl::UniquePtr<BIGNUM> r(BN_new());
+  if (!r ||
+      !BN_set_word(r.get(), 0)) {
+    return false;
+  }
+
+  if (BN_cmp_word(r.get(), 0) != 0 ||
+      BN_cmp_word(r.get(), 1) >= 0 ||
+      BN_cmp_word(r.get(), kMaxWord) >= 0) {
+    fprintf(stderr, "BN_cmp_word compared against 0 incorrectly.\n");
+    return false;
+  }
+
+  if (!BN_set_word(r.get(), 100)) {
+    return false;
+  }
+
+  if (BN_cmp_word(r.get(), 0) <= 0 ||
+      BN_cmp_word(r.get(), 99) <= 0 ||
+      BN_cmp_word(r.get(), 100) != 0 ||
+      BN_cmp_word(r.get(), 101) >= 0 ||
+      BN_cmp_word(r.get(), kMaxWord) >= 0) {
+    fprintf(stderr, "BN_cmp_word compared against 100 incorrectly.\n");
+    return false;
+  }
+
+  BN_set_negative(r.get(), 1);
+
+  if (BN_cmp_word(r.get(), 0) >= 0 ||
+      BN_cmp_word(r.get(), 100) >= 0 ||
+      BN_cmp_word(r.get(), kMaxWord) >= 0) {
+    fprintf(stderr, "BN_cmp_word compared against -100 incorrectly.\n");
+    return false;
+  }
+
+  if (!BN_set_word(r.get(), kMaxWord)) {
+    return false;
+  }
+
+  if (BN_cmp_word(r.get(), 0) <= 0 ||
+      BN_cmp_word(r.get(), kMaxWord - 1) <= 0 ||
+      BN_cmp_word(r.get(), kMaxWord) != 0) {
+    fprintf(stderr, "BN_cmp_word compared against kMaxWord incorrectly.\n");
+    return false;
+  }
+
+  if (!BN_add(r.get(), r.get(), BN_value_one())) {
+    return false;
+  }
+
+  if (BN_cmp_word(r.get(), 0) <= 0 ||
+      BN_cmp_word(r.get(), kMaxWord) <= 0) {
+    fprintf(stderr, "BN_cmp_word compared against kMaxWord + 1 incorrectly.\n");
+    return false;
+  }
+
+  BN_set_negative(r.get(), 1);
+
+  if (BN_cmp_word(r.get(), 0) >= 0 ||
+      BN_cmp_word(r.get(), kMaxWord) >= 0) {
+    fprintf(stderr,
+            "BN_cmp_word compared against -kMaxWord - 1 incorrectly.\n");
+    return false;
+  }
 
   return true;
 }
@@ -1957,13 +1590,13 @@
   };
 
   for (const char *test : kBN2DecTests) {
-    ScopedBIGNUM bn;
+    bssl::UniquePtr<BIGNUM> bn;
     int ret = DecimalToBIGNUM(&bn, test);
     if (ret == 0) {
       return false;
     }
 
-    ScopedOpenSSLString dec(BN_bn2dec(bn.get()));
+    bssl::UniquePtr<char> dec(BN_bn2dec(bn.get()));
     if (!dec) {
       fprintf(stderr, "BN_bn2dec failed on %s.\n", test);
       return false;
@@ -1977,3 +1610,182 @@
 
   return true;
 }
+
+static bool TestBNSetGetU64() {
+  static const struct {
+    const char *hex;
+    uint64_t value;
+  } kU64Tests[] = {
+      {"0", UINT64_C(0x0)},
+      {"1", UINT64_C(0x1)},
+      {"ffffffff", UINT64_C(0xffffffff)},
+      {"100000000", UINT64_C(0x100000000)},
+      {"ffffffffffffffff", UINT64_C(0xffffffffffffffff)},
+  };
+
+  for (const auto& test : kU64Tests) {
+    bssl::UniquePtr<BIGNUM> bn(BN_new()), expected;
+    if (!bn ||
+        !BN_set_u64(bn.get(), test.value) ||
+        !HexToBIGNUM(&expected, test.hex) ||
+        BN_cmp(bn.get(), expected.get()) != 0) {
+      fprintf(stderr, "BN_set_u64 test failed for 0x%s.\n", test.hex);
+      ERR_print_errors_fp(stderr);
+      return false;
+    }
+
+    uint64_t tmp;
+    if (!BN_get_u64(bn.get(), &tmp) || tmp != test.value) {
+      fprintf(stderr, "BN_get_u64 test failed for 0x%s.\n", test.hex);
+      return false;
+    }
+
+    BN_set_negative(bn.get(), 1);
+    if (!BN_get_u64(bn.get(), &tmp) || tmp != test.value) {
+      fprintf(stderr, "BN_get_u64 test failed for -0x%s.\n", test.hex);
+      return false;
+    }
+  }
+
+  // Test that BN_get_u64 fails on large numbers.
+  bssl::UniquePtr<BIGNUM> bn(BN_new());
+  if (!BN_lshift(bn.get(), BN_value_one(), 64)) {
+    return false;
+  }
+
+  uint64_t tmp;
+  if (BN_get_u64(bn.get(), &tmp)) {
+    fprintf(stderr, "BN_get_u64 of 2^64 unexpectedly succeeded.\n");
+    return false;
+  }
+
+  BN_set_negative(bn.get(), 1);
+  if (BN_get_u64(bn.get(), &tmp)) {
+    fprintf(stderr, "BN_get_u64 of -2^64 unexpectedly succeeded.\n");
+    return false;
+  }
+
+  return true;
+}
+
+static bool TestBNPow2(BN_CTX *ctx) {
+  bssl::UniquePtr<BIGNUM>
+      power_of_two(BN_new()),
+      random(BN_new()),
+      expected(BN_new()),
+      actual(BN_new());
+
+  if (!power_of_two.get() ||
+      !random.get() ||
+      !expected.get() ||
+      !actual.get()) {
+    return false;
+  }
+
+  // Choose an exponent.
+  for (size_t e = 3; e < 512; e += 11) {
+    // Choose a bit length for our randoms.
+    for (int len = 3; len < 512; len += 23) {
+      // Set power_of_two = 2^e.
+      if (!BN_lshift(power_of_two.get(), BN_value_one(), (int) e)) {
+        fprintf(stderr, "Failed to shiftl.\n");
+        return false;
+      }
+
+      // Test BN_is_pow2 on power_of_two.
+      if (!BN_is_pow2(power_of_two.get())) {
+        fprintf(stderr, "BN_is_pow2 returned false for a power of two.\n");
+        hexdump(stderr, "Arg: ", power_of_two->d,
+                power_of_two->top * sizeof(BN_ULONG));
+        return false;
+      }
+
+      // Pick a large random value, ensuring it isn't a power of two.
+      if (!BN_rand(random.get(), len, BN_RAND_TOP_TWO, BN_RAND_BOTTOM_ANY)) {
+        fprintf(stderr, "Failed to generate random in TestBNPow2.\n");
+        return false;
+      }
+
+      // Test BN_is_pow2 on |r|.
+      if (BN_is_pow2(random.get())) {
+        fprintf(stderr, "BN_is_pow2 returned true for a non-power of two.\n");
+        hexdump(stderr, "Arg: ", random->d, random->top * sizeof(BN_ULONG));
+        return false;
+      }
+
+      // Test BN_mod_pow2 on |r|.
+      if (!BN_mod(expected.get(), random.get(), power_of_two.get(), ctx) ||
+          !BN_mod_pow2(actual.get(), random.get(), e) ||
+          BN_cmp(actual.get(), expected.get())) {
+        fprintf(stderr, "BN_mod_pow2 returned the wrong value:\n");
+        hexdump(stderr, "Expected: ", expected->d,
+                expected->top * sizeof(BN_ULONG));
+        hexdump(stderr, "Got:      ", actual->d,
+                actual->top * sizeof(BN_ULONG));
+        return false;
+      }
+
+      // Test BN_nnmod_pow2 on |r|.
+      if (!BN_nnmod(expected.get(), random.get(), power_of_two.get(), ctx) ||
+          !BN_nnmod_pow2(actual.get(), random.get(), e) ||
+          BN_cmp(actual.get(), expected.get())) {
+        fprintf(stderr, "BN_nnmod_pow2 failed on positive input:\n");
+        hexdump(stderr, "Expected: ", expected->d,
+                expected->top * sizeof(BN_ULONG));
+        hexdump(stderr, "Got:      ", actual->d,
+                actual->top * sizeof(BN_ULONG));
+        return false;
+      }
+
+      // Test BN_nnmod_pow2 on -|r|.
+      BN_set_negative(random.get(), 1);
+      if (!BN_nnmod(expected.get(), random.get(), power_of_two.get(), ctx) ||
+          !BN_nnmod_pow2(actual.get(), random.get(), e) ||
+          BN_cmp(actual.get(), expected.get())) {
+        fprintf(stderr, "BN_nnmod_pow2 failed on negative input:\n");
+        hexdump(stderr, "Expected: ", expected->d,
+                expected->top * sizeof(BN_ULONG));
+        hexdump(stderr, "Got:      ", actual->d,
+                actual->top * sizeof(BN_ULONG));
+        return false;
+      }
+    }
+  }
+
+  return true;
+}
+
+int main(int argc, char *argv[]) {
+  CRYPTO_library_init();
+
+  if (argc != 2) {
+    fprintf(stderr, "%s TEST_FILE\n", argv[0]);
+    return 1;
+  }
+
+  bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
+  if (!ctx) {
+    return 1;
+  }
+
+  if (!TestBN2BinPadded(ctx.get()) ||
+      !TestDec2BN(ctx.get()) ||
+      !TestHex2BN(ctx.get()) ||
+      !TestASC2BN(ctx.get()) ||
+      !TestLittleEndian() ||
+      !TestMPI() ||
+      !TestRand() ||
+      !TestASN1() ||
+      !TestNegativeZero(ctx.get()) ||
+      !TestBadModulus(ctx.get()) ||
+      !TestExpModZero() ||
+      !TestSmallPrime(ctx.get()) ||
+      !TestCmpWord() ||
+      !TestBN2Dec() ||
+      !TestBNSetGetU64() ||
+      !TestBNPow2(ctx.get())) {
+    return 1;
+  }
+
+  return FileTestMain(RunTest, ctx.get(), argv[1]);
+}
diff --git a/src/crypto/bn/bn_tests.txt b/src/crypto/bn/bn_tests.txt
new file mode 100644
index 0000000..c53eb23
--- /dev/null
+++ b/src/crypto/bn/bn_tests.txt
@@ -0,0 +1,10869 @@
+# Sum tests.
+#
+# These test vectors satisfy A + B = Sum.
+
+Sum = 0
+A = 0
+B = 0
+
+Sum = c590e57ee64fced3ca84d4bb013bba7d633e68b2ff4e27bf1db43f386dbfcce501f112b7fff6fb9436a576ccfccce12867becf02b91961453ea41f414764407d
+A = c590e57ee64fced3ca84d4bb013bba7d633e68b2ff4e27bf1db43f386dbfcce501f112b7fff6fb9436a576ccfccce12867becf02b91961453ea41f414764407d
+B = 0
+
+Sum = -c590e57ee64fced3ca84d4bb013bba7d633e68b2ff4e27bf1db43f386dbfcce501f112b7fff6fb9436a576ccfccce12867becf02b91961453ea41f414764407d
+A = -c590e57ee64fced3ca84d4bb013bba7d633e68b2ff4e27bf1db43f386dbfcce501f112b7fff6fb9436a576ccfccce12867becf02b91961453ea41f414764407d
+B = 0
+
+Sum = 0
+A = c590e57ee64fced3ca84d4bb013bba7d633e68b2ff4e27bf1db43f386dbfcce501f112b7fff6fb9436a576ccfccce12867becf02b91961453ea41f414764407d
+B = -c590e57ee64fced3ca84d4bb013bba7d633e68b2ff4e27bf1db43f386dbfcce501f112b7fff6fb9436a576ccfccce12867becf02b91961453ea41f414764407d
+
+Sum = c590e57ee64fced3ca84d4bb013bba7d633e68b2ff4e27bf1db43f386dbfcce501f112b7fff6fb9436a576ccfccce12867becf02b91961453ea41f414764407d
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = 23f85668bf4d0fa273d8c7f63c5fee57811062a674111e295a73a58e08dd0fd58eda1f473960559d5b96d1862164e96efded31f756df3f57c
+
+Sum = c590e57ee64fceccd54e0bdc52476a756d32e794922dca0acc780d2c6af8852351102b40dfb97009f95e019a5bf38e5d127aa78bc34425edf96f763084a8b09f
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -4b5b16252ba2355e0b87f01baa721783c403607a4c1b5652c09a68e96926c8e314fa580bf0ad3f8f59bd70f14df86a4676661899b54c79a62
+
+Sum = -c590e57ee64fcec882fef3ffd015a3fd9024d8f5f6d53eb537d6abdb0ff5e76a8fb08d5feed113fc9e74745d957adf32704a08339ba42efd5746c5d478e3f57b
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = 908007a2f3c551c58958d1059427a0391d4d768f61cb802e4cb062c778354ea3eaa8f0dfbd14ca8203e07ae6d07269b58088a39f7608c5586
+
+Sum = -c590e57ee64fceeb242f8a0893eaa0d2ccc3dc57ec40fe917cfde66618fba678ce0c8fffc566d4e8c7944d6443def8014fe8ee410a1b8dfd06cb0b436619e0dd
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -1999301bd9877fe07ca711f308b2f1bc4a704fd194ec4dbc297355d6285340d6ad7e90cb0add1770aea19737a06750c3a7a6fa0b778ca995dc
+
+Sum = c590e57ee64fcef321395bba088ca0a867e1e85a1ea77478f8783e6a6cf8f3e582bff83cb2d7d9fd549fcbb40dea22ac140351007030059500bdca81413600e9
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = 219639ed8afc21e052422fff0ae5583231ebca2999404b099628093e6540b1dbc20b9c495aa7229b5965b19a5fcd653b3fa0eccab567c5b5e8
+
+Sum = c590e57ee64fce834a00cc6282cb0eef49eac7a8d5b51988cb49253ed85ae261c76f2327a691fc63eceab02614807048b2816cdb9b89ca66a17b6ed1abdab580
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -4e40fea1cc899fb166dbc721a6639a28be4164ef92545307ed934796afcb9401d75c18d23352471709fbd049c50740ffeebe5590fa2d959581
+
+Sum = -c590e57ee64fce1a17609c61ce02f1020c6eb6e241e3fdd01546ce7247725589de32db95f36718d410f9ce9a94fecc8fb205e876fde75ce83f4d01e1bd5d818d
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = b7739ed1cd3e67cf541943326cf76b4476f767465ee53b94c57c83de417ebee5673809b3bed1c8bac2fc4bce29a4e36d6d2083fdea1c12c974
+
+Sum = -c590e57ee64fd03e2d08c3d8e5110d08e3d36557d82e0e49b408337a8c9d4298802ae5f0145a9587531a70d2f8af932b8262245428b5c549817d333f2dfaeeec
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -16ca20955a9d8a64cb2be217c089edecc02a75a1ea95fef584925742c18a234974c0a16ee7991e80bd8d4106db385eafaf421ac3373548aa3eb
+
+Sum = c590e57ee64fd1bcac71b5b055e5934ba15dd7f56370063369c36e57a6b753269e085d0f4d38bfb711d5579dd1d89d07f266e727b232a497d5b0d9bfbc02d8a5
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = 2eb21724781497ad2f57babeea62a20c3ec5d1559867a0968d74351a337db12c17bc8d1d5446b1115b5441530870f67da4275dfd9f3e2928da4
+
+Sum = c590e57ee64fc7860b0be6ce861bc2f099db7fb623912b7b0729c019a8183c669c73efe02b195483a4cd2c78244cd59678ac4d62f6887fe686a3eed37ed460ff
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -74b7ff38760864efd658bd6699915be16cc058454b78495ade8be42c9f7470ca9b7a43655e1427ab1bc35a5693dac424a6ed92d10f85a9bea02
+
+Sum = -c590e57ee64fc3126776e79d9fca06233bd2ef5570a65e4521183627bdbdbc555e9118508cf63f519bc0caedbffd5b1a913ee8c3603804820a9ce54b1207bdef
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = bbf238886916ca0ba32e9def9f9c8a8e401eb95dea96ef02df9fc25a186e52fbee9ad42b76ba6ca2c381d12cddd4292c5d355341a80c7688d12
+
+Sum = -c590e57ee64fe6dfd728dfbe45aee52380b5a00cf1e05e9f09ac582e2714bb589caf2ad038111c5b1b5573a45706ab1f6fd5d5a1ee7ef4a9bf186dca8a9ede12
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -180e4c29718f394424cd5b03b6bdb8911c57fcfe435cfa66d10941f870f8c5eb1e1fd251f14af03f23ccc1841f014bb42a545f476dfeb12e9311
+
+Sum = c590e57ee65004b3e18a5820de4a6d25e7c3d310003e0b8716bbfd51d5f0f3e87fdf8e00599d713397255281e66ef419a9d9bb228e8f052764f5f861ccca656f
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = 35e2568ae9f1d1dfaccfc211e9c0c6eec9400a0de880a94309992528d428e77772f84e21d0287fa76cc6fb880481ebc43ad20524f895f35a1a6e
+
+Sum = c590e57ee64f84896a5f11f575d34b6001f27d4b4d6e7cd9485260629f8f7f1c6ca6f6115b98d776774295dde4d59cdbbceccad097a0a054b501bfb47d81e85c
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -4a4820a05c39969774f623bf6c03ebe0c56dc45bb46e8d1e6b32ee0fc3c6168d26c4d1c0ec7b81f1ea76f164ebd00b2a2a00aacf40175bee62a5
+
+Sum = -c590e57ee64edf1b2b57b4cbb92d778ea6b9d9878a0374d4ea81691b09811b105bb6dbf23a57d89264f0e6c83f8d00fe00681644feed56e15fc81103ab9b7dd6
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = efb65fa7b963533d48c77ef80fc7af4bcd72222cabb6232ccf3efeffdde537ce25a8e4129b91273a8654ade9a05ba3dd73740008eec82dd4cd2b
+
+Sum = -c590e57ee650e25da7b60146e014f472bfff9809aa8f519db7943f69d9ad09ee75a3427c6127cce7bd27f224b9dec03111fb066956b4903f9f9740cce1aa4ba7
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -1138c1cb69317d3aa341c9a4daeba71400f56aae62a98acff1f9f1aec88a4ef01ceac74246fcb531738de63a94fc8b3e9c5ea3fc64101083a00a6
+
+Sum = c590e57ee653af8752322840ed720f628f9674c81073b58372e49ef26d4a2a9d46a0391bc170336614b27849de98709a4b321da4ddfb978e9f10df29154edb9f
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = 3e0b5c732ba11e1074f0c69e48b78d724733c66368a21409c404debe97f444f4a352acbaef5f077d0e9479ce067043b30cd393f3fdf5d3bde909e
+
+Sum = c590e57ee64bc13634cbd149aae35ee47bde6ea3663f74ff300cfdb2d845f902f017586c6d4f83f08c3b4f0c035055d13fc9d340b7b9ed164432aed44e8f4d7c
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -40d9b56339ce561876171a9d37aabd30fcd47dca1171e5467f14c6a9f616b04d67a4abcc8334d637731816e87e35feb10dd3f1b9e50f78ae0fd85
+
+Sum = -c590e57ee6477eb692705f8da1357e71591336907a5e0a6e39715088d53b2610882765357563fd101bcf05ca545a0c718f52879fdf4f80cb9a12cf108eca60ed
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = 8501af88f0ea16b3541e4cc9eb2bebef137d8d33cc4485772c43ed28f54a1fcc2012b2d347c8f126d7ae11eff2f00c37b4989c5be30bb4aa5ea14
+
+Sum = -c590e57ee669b662e37f5abf13d00d2f0c1c9a8b99ec546361aad255f375bc2742a3487c351c5ba00efef09c77331577460a47c57125c620b643e9eaf36a146b
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -19e791587fec9007654cd8e66ab13c609d121c54fcbd84c6c7d1d7e7ec8ea4c2f65d64c5fb6e43106b8e2497b89124ce5afbcb5672ea1f19f9c96a
+
+Sum = c590e57ee681dcbf1554f22c0b1ffead917dd414299cb37ce6967ffec9c333931e70358729843c8130ac95aba47fa1fa5da74000eff25eecae176f093a4effca
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = 320ded8a5583fcfeb53e576bcbeac4f04d7135d9e86b2d9d154943c3b97bafb75e3e45e7a913523db81aa7af5589604d2794974e466f3d60deb4c9
+
+Sum = c590e57ee5e505ae4a2e1f25a1ae9b7b4d17dd2cccc09f2416d964e55af6d0d31fe259c160f87646a72e6732d5110256b3b35425225d622b81418435c9dd8cc4
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -6ac92340d14f096abc24dad89a0c226c8ea322f5d4afebd1b7197c3ad46016112d87f4a1d51b2691b684fbfa9e627b806d6829de8f7b960f92be3d
+
+Sum = -c590e57ee58c3ef1582bf7a516e36f92b60f5a587e2c8cb071d1d52ff215854e52de1519fd5204fa52292dfdc397d8d76b78005941358b63a3e6ca41b0eb09b7
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = c38fe032d37689f58750c36fa28ef6bb22b5969adc3fa13a98650107d8a4bd74d3f940f6da545ba32fae7b42d9b64761953ef1bbea358a2885414a
+
+Sum = -c590e57ee80262967da4038a143f8ff2e78646108f25ff7183444ba507d76f9b05a34c8310e682c05495d0863ceff264964dbfa7c064adf6d26d2dca6e22ab13
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -1b293c4f2a4955b07d4cf9cc1d45cc155d6bd2a769636d3db29854baaec92ab9ec084850b924e2cd6286b11e7fc09071d99e3a1729c2dfe94b26012
+
+Sum = c590e57ee85427f08e8c89ffebfcc05c73370ad4cb77696c2b2f3878e6f6df341d4d931b5097aba49f14ac0312e7da1c843d6fd08119822e75e6e7a8c7bcb7b0
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = 204591f038d1bd0df9200064d852185922827251e8123a7ba48f4e4c296d943de71ad69561129a9ac2052c9d5ebb92fde4eb7d91615e7dcee4c6caf
+
+Sum = c590e57ee051ca1a363c47a4cc016c3de7f7e17985009b545528289e9fbc9086f4b42a73826eca0c278b0d1b4ef6d74b9a0bfcb7855d40fdb201fbad1074b927
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -5fe04b754c3268a406954183dba07d5b44ea6f2b785ec328cf159c866028f63efb7342f2178753e17d0b0071445b9e91d6d8957adcf041ec8fb91da
+
+Sum = -c590e57edcd6e9ef06fe33f3817ba3d0c50c8122b77615c4b8fa50c5514f113d7ba53ce057d487bcbc373c4384d07b29a527b7ef785ca609474879b42a9a4c3a
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = 978e4e284013a3b8aef1c8560a5682c81d92c8253b3c40bdb5ed911df117cf71a51767e8ccc4615e1f70c290929feb12a6e244c18888617aed5fec7
+
+Sum = -c590e57f0436bdceb586a093522eb1630e0fc08f8790957aba1875a42b7676f9ca936e8f6f3478d6ef5cd590bf6ded0700440dcd769496822af8015f0a6ba2b6
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -1de6eefd2a87326445c3f10ce85dd7404e415333ad6a60d2fec88caa6fdcb4b7fd0e7a9ba659533758a665b451f2572cd3c9cc2ccb27019330fb57b5
+
+Sum = c590e57f1df3f004d5e49f49fa28603b26659f1fd35e0d8d7a2753591dbc12c51e6b588427dbe3faba2f0c1f2f0a2aea9ba1fcb2fe71c6ff40555058d23c8661
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = 37a421334ae5311aedbd9fe500b3b5d09a0ecb466d793e87f10e2875c3b49eacb5b5e5bf712b89c5c842a397ed5046125ba6fca9e084508cf8cc3b60
+
+Sum = c590e57e9a4abf4572fa7c4c9f73e9d3fd1227646fd6d15b51924bd7a5d417b01fe6b4273eaa6ece387422b81c8116f29702d7d66d2f6e8c3454807b3b7d413c
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -4c050f8c1804f1e26cf6d682289fc1eac97870ebbb1bc8f986d9d29f3ad005b0337b8f6d108f5fa14a467060174edeca359b5bc92b7c7f509df309c5
+
+Sum = -c590e57e64216c306f17017ac9dd7085113e16c83168664dbb77c7ad3ddfc79b09f9ea0c474a0b497ca15e7fb258eed9666fd009f691a3b2d691c2c6b22ba3b3
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = 822e62a11be86cb4428d4fd11473d28707e6dbf951364d23eece22b450bccfcb2adbf2f1cc6223d9b46e987947e1e696ac3926a2893f3d052744a74e
+
+Sum = -c590e5806ab4d09773c4f94a4aac09f6ed7609eec1d0bafecb09e30f032f706e9adadc191ff9e6d7dccc821f7a8666a590e521749d24912c5a5ffeff246f7c85
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -1846501c5e8c58b1b3e4149a0c7c4209f888178b7be5bce3dd681861f40242241add3e89c93c8ffc613bedf52e2936ad3fa59c6d6fa8eff334aff3184
+
+Sum = c590e58248cbf5dd61ec57994fc862ab479dc6cda51cc17356c45cef66bbfdd12f5cc421940a561581c123fb17483beb7a1cce2596fa9ca76e722a6f4621eae9
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = 3627c270bd6ece96a435da25521ebdd7e6bcd7f2c4a16481e3a0e1381d4a60a4a21e457da38bda1a1b080b498cbcb1784f42fd2520ea12aa36cb19fe8
+
+Sum = c590e5771a85bdb1f26c0386ce837bec4b0af5656496efdf4f134d875f066dd6d477ca8f87ffb275da07da4dd1bed4232849a526836b47f2d69f2d53b6b3e2f1
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -7cbca111f98936aa83de74469daa6f3e9d4b85267bd9ac749cda77c78863eef47ea264bc56efba80b9508b32f8608117a1f5f82628931d27822bc6810
+
+Sum = -c590e571c76afad23439f904e8a80fc28dcabb6cb732e361ed3eef471be6fa755e3fe746edbfe448c1f289ffed7dfc01fe9066d780564f57f93abbca9b9a995a
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = d1ee4d3ff56c5752a23c2b09397e72de2821c5ee51f6f258a10c6efd9fc76d290846619f28710f85979498b50afc14fc922747afd669644013dd5b1a7
+
+Sum = -c590e598cd5d4a59ff5d6c97c6370fb517f1d492a7776f90063b0ddd6702e37c60fc78bb12857911cea37b7263584d7dc815676de6b8880200acea154b59b08b
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -19e70d7b88745dfe68b9cc4f5ef23feb436e282d48f98cf90c3a54f92d0645bee3a05f7ad6859ff918fc90c62b19c3b0cd43edbdaca0dbea4971e9658a
+
+Sum = c590e5b5829e6fceb77830fbe999a98127b50302fd0f6a86ea4aea27b846747a07e6fcf5457676e6446137d6bdd8ff4fb7ca747b650b066d65d7dc1e172488e7
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = 369c4ea0fd2c78c2ccdd2ee92b020319b3c3c0283fdd9cd5568b988a2aad30431dd35078aafb5db57d571177fd0978bddac2403c180606dc523db43de6
+
+Sum = c590e52a3ab5d5c458634254e2f672a322000750741e969d2f6cd12d172480ad1455300e3a0575b068b85d50b58f9737be13073188d0f03b71494bd0fd2fea16
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -54ab99f90d329c2bda29744db303b1e1fec530aba9dd4143a4158969a2466189c93820888ae04b2508b137f01af03eaf6f19f9da19ee87b3fadc4060eb
+
+Sum = -c590e4880579ef7241bde94e8c7847badc705f53828751f9975f0e66371d2ddff8740b143f32e88be8e686e2bf5a3ce03d864d7699a813b1777b9239af242c7d
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = f6e0d5df5f494184e07ff2789b494189fbb6c7f04d754f066af590bc6f6242aec332f315af601cfb76a76d4a7270cb692a0922b6a3e8556d922a4c1e84
+
+Sum = -c590e6dbe54098694155509e38c61d503ab7e5237d2cdfc2b87fb57e3a8420fe37fe50a0dad4f0eae3d38fad6198e4ecaeae183a12078f53d09ac8099c715242
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -15cfef0c997b655e26f2c5b5cfa1505fbd443dd9d7babd1a0ad0dd636aedd4796c968aef2af9ad00d53fad15d9a005c61996f3cc4fe70c9c83dc3010741
+
+Sum = c590e906254d013be2021ad591e76e26706a6815b8c484b6528fec65416e1066957002713e1183f1005f565983aad7aa031e549e6fc57094ca3e4383e7fdbc15
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = 3873efd326a5702aca6857cadd04ab87ec67f75426f45e1d79414c026173ab94899cbeb85b5b75bd4001ce3505754cc9dfdccfaa63f6a6d43b80e8d7114
+
+Sum = c590e0e0079190d7afd80acd6326fe93cc00903318608df31ee4493d11271dac7291bd142cca0e5dd7dda59dabd460a69b7855d9c2acb5f062de76665e07cbd7
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -49edebe3df9db276361a943c1c259b1591c20eeb453edc9cb941b86cca2e824fcc3455befdd7125dcbbbaf326ac12d960c6e01e1464fcf289657b687f2a
+
+Sum = -c590d9ae456d66c1b132d844eb223867ba4560b36f53c42a616cf8cc657e6d252f813847fb9fc50127227684e5c0f5cd890eceb341d21e788e42f843e9b64080
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = bd0a0e2680fd9cc95ea214887ee6b6c889bc9fb7e1cab411c04c72f7d2a2b35818f7686393a21e10bd4810691852542e7ed60f8abdcd18e0787efba0a81
+
+Sum = -c5910498291472fe1d0047d5bdd9e46deb3f26000e943fce8d83d700d9ae233ab3a28849bbb346803da142db6a471e9f79cd49571f40dbc46f7b727a4bb3016a
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -1f1942c4a42c9200d9a6b16f2417c58d3cb0d544fd8780d5c22fad0038eb58ebce72498d4844f49dc082037f974ccb7b92b67c76116f0faa72ae7242b669
+
+Sum = c59112d841ea109440e78563d9eefef201c81e86ae967083f8b7db80d1eaf58551d30519ca6dd79164fe69a29cf1ba22446cb2999f73292241005bf17b37528e
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = 2d595b9a41c2b5e81734cd843e9bdc16353775472e3cec09c6afa53d0b35f71c4b425847d9561bfae749362a32cf961afbf8fca85ecce12f5c25a1c7078d
+
+Sum = c590671f890ca06c74ac6d2c4d75aabeaaa55312e85a5e1ea9cef0e08e154e2b090eaba869e9f6e4a47ae10b9c1eb0f6ae4fb3ef12b3121d96066c6c8e592b6e
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -7e5f5d432e6516530102bef515977b0c963c50f4e42862df23f09e989c2451a80e2f083c0756a488a14dcaa8d65c000202b19017b837c9ca935f4b171f93
+
+Sum = -c58ff0ae92ab03072154949a7143d45278ef77a0ba71a785d5a370e0d30a9b4b4f7e96a395d13e6afeebbd717365d471ee56ba11c472a63c0532558104bedfc5
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = f4d053a4cbca69aad9949b26ec03acc271ae7edd9ac1370aa3f059a34f040b382333dc54bfd04a17c4e7f361b2e0bffafc8ede5824195a9eaa4ad4b16b3c
+
+Sum = -c5927a5fcc3b31abeca3998ad99c07626112288a6ad95b24929fed581040757fdce73881c48b02daf09986ea436a3f5ceb6833c31fa2e1691567601a26c7a6c9
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -194e0e5eb62da61a42b5bcd31470c3b603f3b318a18dd85f1d886e3928b3082307eaa5265049fa7960490dca2b80a3d167d227cd81713b596604e4d575bc8
+
+Sum = c59395e94d495451e3fea153f3e4361a088004a7d5426c1b94aec44108ad6f5cecc3a80dda0cea9f51b882747258137e171bf021b4fc59f4dcf0106d4ba952fa
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = 2b06a66f9858058ff3324e77975c3e2ce1b589bf329d48800af6fdbff850d920cee3667e6ec6408b5001b0b908c2b68ca398112318f9f7d1f10a1723907f9
+
+Sum = c58bdb26c0fd6766f3affea389cbe7db25c06d5d56356d3d945347775bddf479ffc9e279e7d1ee88eddb239906749815ae4502fbbc6fe978a001ccdafd89cb10
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -50a582552676a974f6f8b829ed87afff17bf1e319d509785acd59d0cff5d55aecd75d8a540fb25b285ec06052ef3d000cb3a4e65ae0dcbfcf32f0dbe67ff1
+
+Sum = -c581afe9b7ae86d4b7053f19649beea6cb935799a553f035f9b9a7fba6d5559e4ecdcd1637c73c8052c6cc52ee1c28d1e5aed9db7261b7356afd6e3dbc213684
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = f35952ea147fcd3fa2f15a7ced1af5a1e91b593fb521112f46cd585d894b10be8ecc13a5ec1baf63cb60678ab5e80c8a2dcc53069131ff4d3918e1d4f147d
+
+Sum = -c5a19f36a65a6a8d52a53a63f99a1b957d6e376b7010ad14695d78d67b0d7c86881006188bd27bbf205c8c9c200dc8f5c08ab6b97dcd512f6cb93ed9a361ff9f
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -10b9b7c00a9bbbc7a5cc34ed2f5b3f57bc4e1c36c16acd5caf64054e5f92372d594c4119ac7d83d7590a42b94641a312390018db0286da0ce83f0dc9f1b49e
+
+Sum = c5cd0e5da24b67a894402b0eee5dd586ab70e5beb0693e263a54995193663a9b770141379c1f097a49d1a889bbf0c348c6f40ed50bd7bdc11a7869c6106c6d80
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = 3c28debbfb98d70940bcdfe1f3153085befc6f7719fbdf2da6848066b8504c1c4a876029f90b3f00ce263055293bf618a25834690cf36bbaa769fa36fc227f
+
+Sum = c54e2c560a00226701b76cf03d5de27a8c69b38a6b85dad9f7c903d2e87f9a7d247522e72491460f6a529e5ca2aaaf690cb238b873ffb49d9fb0ecacfedd4e90
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -42b928dc4fac6a8948013ecf0cdddb994835c4cdc9676d14e510fe442e4fd2364196f04d94b82bdeb0e3fcc41cd7e9a19f7de82ecb15b7c020131eda92fc71
+
+Sum = -c4bfb037f6e6e861efb090ee610c33e7568790259f747dc6e55d442aadd68c0cc93c7617f83980e8813c0fb7dd28c8aaca6ad8fdde5d2bfec9ae096faa9ef54e
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = d13546ef68e66f9b4edd40ab5e8c6ecf2a592999dac4802750d0a67ed75e42917a43bf79ec7d52c7c772a1899ebea7e3e6dda2c46d9e569622f65c2ed155b3
+
+Sum = -c6aa2af8c9ae8be4aada83f66b7f31a8bce5e92c67d8938424a1405903e5502bffc4ee1e333da4bcfd0cb383b19a566372f877a8344b66dbceabc9786dd0e4f2
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -1194579e35ebd131fdb15c75f1471529733ffdd2e89513d17f32b87d73765dca50e3446c117a681b409312a4ad2cf10c4a6c10791809c866edac9ac946099f1
+
+Sum = c8aff66c9bdaa49eafac0f65d3ddff223b7a5471f7400431ca3a54615d600fc4a163f8fb648bddb5fd6915db1991611805040e0f86f152c8fd3333ef70d632e4
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = 31f10edb58ad5cd24aca136c7733ecc15c86b22bdf0c1eabd8c3f9030b2257546ad3f23f265df7ab4659381b2c9d9c556b2576ee42688739d6234239765e7e3
+
+Sum = be1b6eb768e2cef388eebe31f9b21e51b38b351cc8175eba06d49eef04c2936f32167174dcb82297fd4180d0afb5da2c455d158c7a5bf01bdef8c295a4f20390
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -77576c77d6cffde0210affd12b8a2047226b4327137e38d05d975e227eb56e028a04862956ddba34bc20188b711ad2668f4a114286eda3980d83d36347e4771
+
+Sum = -ba32fca1d5cc5f31ecaf5407f376d3aef9f4abc04fd4c6893721d3e50e9141abf356eb2ff6f7a4f9b42983148670d2918e1dff7aa7ae33a6e9dadcb708b4f9dc
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = b5de8dd10836f9f9e501a2718f3eca72bbd3d8ee97a7bbdd58c40ec1e1ca8a3675fcea77b2e594194d9ff44e056b4c12033b725fb1c96ae75f62314d0bb5125
+
+Sum = -e388afbf17c495f86aa7298a45f848eb57e5baaee42b1f7de8c2311bfbb8f74549712c05fd3bd11ab8874fb55abb22a37ba3512e733ecd5c472842e8e6f7b179
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -1df7ca403174c726dfa7bb5b398d88953233d15faadbdd36dc141c4acf0b0cf5eeba722e8b15d2df6f83cd5bf3f39b50cd519a8dd0740306e757431d0d876678
+
+Sum = e891babe65ee02c02e7e876c0df3dc3bb37491008f3642ca7affe2d623fa82a6d5a9e5400944a374ab70fbb8f952dad0c8b27c77475b0dfec7b0694051dcd1f4
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = 2300d53f7f9e33eea37f193d01891be58dc2a7b155e700836e51ce04f74c98577af32b68971ea539626d795f928b537e1a60c5d6a49043a967df6974786c86f3
+
+Sum = 4dfc2f63d60f83fb1d397d2406b02a3b25c1a57c09c2fe02c76696b7c956e44facdef11470074d8fd8220c7bf8e647ba873fe9c3f9e77d6aae7b5fb64f1cf566
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -7794b61b10404ad66dc5f10b05ba961afff043d32f8c444445477e19635705ffadd7c8c3021eb0ab70e175dd6de13f982711ccdca8e34ceab155a0158a53559b
+
+Sum = -3c19bedc60e7d7dc3daaa36795e453d810c952dd5185fcdc857e2be806e520068dbedb91c4a1131b9eb6dcdfd500045209514e3e9f6e6df41d2ec67fba20e10a
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = 897726a28567f6f54d54cac776866c7e14e89671e7c9456a872fe8e925c8ca48ccf7de45ad84eb1faa4ca57991c78300a5006862035c5c6142a2394c1f4f69f7
+
+Sum = -28c2bddfeffbdbdb1ec6f06aa310d1bb6f0c4b88d0106a1b381ae6fe8f65c18bd9895fcba6931ecf06d9dab6c7a3ac9e00361bf165f16bd16af25230d040cd842
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -1c69af880196deee0616f987b24a25b60cb12cf3dc7b75f6c75005b17c9ae2e6e3ddf42e2f70beeb5249a29131373428d55100875bc4bf2c14f5423412a9c8d41
+
+Sum = 372ea360832e30b16a3c30a2157c8bddc4408ce0428169deb09bf68113e4b8482d887de1a7cfc80272e597c3f3f104e6825a1fd2a68b41cbc307caaae17d453e6
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = 2ad5950894c933c4518c39bf24b5dfd861e56e4b4eec75ba3fd115340119d9a337dd124430ad681ebe555f9e5d848c71577504689c5e95266d0abaae23e6408e5
+
+Sum = -5b29f4991cad86845a50949f25ad6cd7c883d71ceec9795cc528f58a4a4aef9dc139e8e87cb82071e112b2d256181eaad0a98fa36b25b67dc673608939b48e08a
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -678302f10b12837173008b82167418dd2adef5b1e25e6d8135f3d6d75d15ce42b6e55485f3da805595a2eaf7ec84971ffb8eab0d755263231c707085f74b92b8b
+
+Sum = 98b37ecc0b42a15f52c8fc8bc2aba294031bc2dfa37dcba0fdf1f5f5da00b8b3daece033b47bf254e8b5e201bae24995034673800d53213f6ee0796be1ca93845
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = a50c8d23f9a79e4c6b78f36eb3724e996576e1749712bfc56ebcd742eccb9758d0984bd12b9e52389d461a27514ec20a2e2b8eea177fcde4c4dd89689f6198346
+
+Sum = -1c15985f3ee941d7ab6bedad88143cf497681424e7456fe30eafbdedfcdf1e927db124c775b87f36cefff17a35972ac40d498c4be818883bfc206f44c5e5eec23b
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -1b500779c002f208d9e0ee3f5907d2344142623b980c20a0c7a30fd92bb270a82e566e0d9e46593893b6edf7dc30633cba9b3a954775bd71a6c09e44fa0c7e773a
+
+Sum = 34ab71257e63b234258027e26bd35dfa5e07f67385b6772c5ed445438478bef5a835e87c9de413e23839849a71f5af99a67427098b682bfb6becb66d20eaecb2e7
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = 33e5e03fff7d626553f528743cc6f33a07e2448a367d27ea17c7972eb34c110b58db31c2c671ede3fcf08118188ee81253c5d552eac56131168ce56d55117c67e6
+
+Sum = -44f9508e3430f93d4e2c8be1b856f46c01d6940e1bfda8515c747a1a95239547322999e500e718ec98ed211ae04ffc76b0e6f2364ce9d913ffb80397f24ee8d64e
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -45bee173b317490c1fb78b4fe7635f2c57fc45f76b36f793a381282f665043318184509ed8593eead436249d39b6c3fe039543eced8ca3de5517d497be2859214f
+
+Sum = bea59d2cb0bf556876d4f8a248339af69644a12d3dc1d9a3d83929929b8db5aa26289bd06e2488a96820ea8f59168cc82f19b5dfaab20d245495d6e24bfb260a3a
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = bf6b2e122fa5a537485ff810774005b6ec6a53168cfb28e61f45d7a76cba63947583528a4596aea7a369ee11b27d544f81c807964b54d7eea9f5a7e217d496553b
+
+Sum = -166abef6a1682bef78d4c5905a833b81a03c0bf0f3735973bf7f02181a8ce5c7f125f41fcbb10c7f5905e492fc3f6b172f23d041620f8a7ac6f76e0c8a53d3cb5e8
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -165e65e84979c6f28bbc1599779274d59ad9b0d25e7fc47f9b0e3736cd7a1ae94c3048b42e39ea1f7551545ad6a8fe9eb9f8eb25f8055dce21a170fc8d963cc6ae7
+
+Sum = 3245e002843eb7116b987b5cf9160e6891a74a6843039f8517fbda68b0e6ad87fd0aa836a2b6aacabcd67d45d327e6cab43ef569f488354e22f4553eed09e83d601
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = 323986f42c5052147e7fcb66162547bc8c44ef49ae100a90f38b0f8763d3e2a95814fccb053f886ad921ed0dad917a523f14104e8a7e08a17d9e582ef04c5138b00
+
+Sum = -464684d68716498baaa3744d20c112a854e148e6d004e4142c79f4e25a36c0acbff72c047925377f377ad690c63fd21a3f05911d11fb8bb79bec4ea68fef9f1d575
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -4652dde4df04ae8897bc244403b1d9545a43a40564f8790850eabfc3a7498b8b64ecd770169c59df1b2f66c8ebd63e92b43076387c05b86441424bb68cad3622076
+
+Sum = bb90e9e393538df233d499955020b8f3c9789b1f18fd5ba31cdcca6afe24842166e6cbf1985f7f9e002335be46de06ce11ffbf6dbfe743642cdeefca1a856219fe4
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = bb9d42f1eb41f2ef20ed498c33117f9fcedaf63dadf0f097414d954c4b374f000bdc775d35d6a1fde3d7c5f66c747346872aa48929f17010d234ecda1742f91eae5
+
+Sum = -1804d154182f4b71cab3529447ced41ac310a1d14121847816c74171759998b707db0f1f3a9d6f6e01a2de48ec83a45e5dc7d0ac9133c8e00ec41814e3d2818834f4
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -18040bc332b06521fbe1c794d99fc7b002ba7c1f57d24b28d48034c360c86c091d8bb46880c5fd48036795456a2a3d96d675225ada932615446eb843e406a817e9f3
+
+Sum = 3b75f0b892eb00075eb21961cc018a2d297764bf560cede3290cab6682a56931b831380b72a9afc3dff88f042ed5bd5d8468d8a1e267b36e508c09ccac2a565936e0
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = 3b752b27ad6c19b78fe08e625dd27dc269213f0d6cbdb493e6c59eb86dd43c83cde1dd54b8d23d9de1bd4600ac7c5695fd162a502bc710a38636a9fbac5e7ce8ebdf
+
+Sum = -4b4bf674436c9b1079c2b24cdda19247d0db44061c562ab6f5300eac53556fbe758151824b6bc6bb63a958895fd7c4205cde5484a9fcbbe787fe38c3d36f4549dc23
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -4b4cbc0528eb816048943d4c4bd09eb2913169b805a5640637771b5a68269c6c5fd0ac39054338e161e4a18ce2312ae7e43102d6609d5eb252539894d33b1eba2724
+
+Sum = dd8af6a278a84889cab2d444efb282a7259a608117db26583287f051bca1b70c21f8c3d95b2f4e0b7d25b6966771a5c41414c386bf4491ef7b055b07455c12b5d8d5
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = dd8bbc335e272ed999845f445de18f11e5f08633012a5fa774cefcffd172e3ba0c481e901506c0317b60ff99e9cb0c8b9b6771d875e534ba455abad84527ec2623d6
+
+Sum = -16cac44109b24fd5d47dfb5994caecbbd534ee11178aaea4a100d9e63bb2c5ecdcafce1e2080eafdda00d26c29e01980166d8db67800e33027f5260d154efe1a98973
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -16cab7e7fb5a6170d790e2a99de7fbf5292f8bb5f8f5bb0facdc691b5a65b321fe0ad872b4e373db7a1d1ddbf1ba83139df862d15c96d9037b4fd0100552408393e72
+
+Sum = 22db04aa783edd3e1a55d263262805f2892c013f78ebb86239f2e5981090158f57bdf3bb171c2e0c1c7bf9bc88ab62683581f8b02c5bec8f631bb24ade9be235108bb
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = 22daf85169e6eed91d68b9b32f45152bdd269ee45a56c4cd45ce74cd2f4302c47918fe0fab7eb6e9bc98452c5085cbfbbd0ccdcb10f1e262b6765c4dce9f249e0bdba
+
+Sum = -4c8c0b74eb7a79a12ecaecf885b9672ac717b1c8db5ad251f1551ce80af89acf3a495066c85a96e6430be8e5888ab1ef3edd5e76645b5914ab55d221c34d07f8d5ce0
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -4c8c17cdf9d268062bb805a87c9c57f1731d1423f9efc5e6e5798db2ec45ad9a18ee461233f80e08a2ef9d75c0b0485bb752895b7fc5634157fb281ed349c58fda7e1
+
+Sum = e3718adf0c2546c8cceb0e8c7d909deaa50b50f51d7b80f8040763eafbf581c017e7e12325b258503fe651ffa4c3d3ff9200515d816dfa3ba372dc937480d121ef056
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = e37197381a7d352dc9d8273c74738eb15110b3503c10748cf82bd4b5dd42948af68cd6ce914fcf729fca068fdce96a6c0a757c429cd8046850183290847d8eb8f3b57
+
+Sum = -18dd84a4e54a29c1b3106ef2f2d92be21ba64d2e26b3f4c2ea68685557d01a07f9229365c6d109205fa116fee59cf385cdd61b7fa5de8de751f02f1dc0eeb304babb4e
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -18dd83df5464aadb63419d67f36afcd5b0e5f70874caa5899b262148a9bb48db4b38440b101731ae39a2dbb5e21a9a1f064ec8d15427ed448725d9bdefeee72b4a704d
+
+Sum = 3ce64e7953aff0e057cdd6c17499461666f5bf8dc3a929ba7ba919486c1631c25c0e142584470d3f759157c045f9f488502a76024b6b7b2bf84c0adcce8dd7c6d6898f
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = 3ce64db3c2ca71fa07ff0536752b1709fc35696811bfda812c66d23bbe016095ae23c4cacd8d35cd4f931c7742779b2188a32353f9b4da892d81b57cfd8e0bed663e8e
+
+Sum = -6a392e555c2ae89dd73f86e11fd98d1d59ed03072a0dd61add633b317d5638d67984a55e51f01a2db94ad6eb6488fa80cf4f25a32d436886599c33b5287a9525f41a4a
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -6a392f1aed106784270e586c1f47bc29c4ad592cdbf725542ca5823e2b6b0a03276ef4b908a9f19fdf491234680b53e796d678517efa092924668914f97a60ff64654b
+
+Sum = 8202089b883a5e77457036254c2a73aaf32f03eb1e61fae428926028b499b7d0a4f4e5256094f34bc2478f0595aa01aa79b5d36d7f30136d3af2be93b70552fc6e988e
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = 82020961191fdd5d953f07b04b98a2b75def5a10d04b4a1d77d4a73562ae88fd52df3480174ecabde845ca4e992c5b11413d261bd0e6b41005bd13f388051ed5dee38f
+
+Sum = -13a2e13d675e3fa89489c870cda617ae92ccb7d2f6b6405eafcad9c89a682b63364c333476adf0322febffad973f3dbddb7cbaa41a64b1ea24dcb2bc2196a0af42eac3f
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -13a2e1310e4fe7ba2f8cdb581daf34bdcc20b2709b97ab6b1ad6b557cf86de506b6d8e3ecb4252bb0d8c1bf9070718276f044579354947dff8300d662486a3f1abe613e
+
+Sum = 2bf9f45c817a8f5c589a208c57c30b52866e75a9b6ee0fb7c3f0c7ec3761f2c114858241a189e331aa9ab440132dc8f5ab7dac0891a69d5573dbe42fda019d30610f07b
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = 2bf9f450286c376df39d3373a7cc2861bfc270475bcf7ac42efca37b6c80a5ae49a6dd4bf61e45ba883ad08b82f5a35f3f0536ddac8b334b472f3ed9dcf1a072ca0a57a
+
+Sum = -40557025ab86f90705fc86e3ab3d8494255bee490822e27c5551037f36f9ca834fd33c11a1a162357cb21eb83254c4da56b9f8f54aca29b95283ac03732a849258e7c41
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -40557032049550f56af973fc5b346784ec07f3ab6341776fea4527f001db17961ab1e1074d0cffac9f12026cc28cea70c3326e202fe593c37f305159703a814fefec742
+
+Sum = d2985750cb9579d3f5dc3db7d2229f06e2a0d57d195819b3646f84c08eafc093def93748aaedf1f430eedb90c1694d894339caa4141ef5f07708e1a3607c5793df599b5
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = d298575d24a3d1c25ad92ad0821981f7a94cdadf7476aea6f963a93159910da6a9d7dc3e56598f6b534ebf4551a1731fafb23fcef93a5ffaa3b586f95d8c5451765e4b6
+
+Sum = -13a024fb88eba47aea55fb69680479058efda97b81fb1e6e7cfe520e8dd8ad12deffb69662852f9a94f3b029a37befc620d792a8589660e2ebc7d6e1bc8c0c8f35ac1216
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -13a024fac35abefc04062c97dd050ad68292e9255c49351f43af0fc7812a9841b251cc4707ce75c322cdb1ee5a786d6cba100b55aa44aa4248fd0c8c5cbb0cc35c3bc715
+
+Sum = 22701a8dfb82a2ddc8a5485b05362205a549bcdd24bbd660f2041a6672732824bbcac4ff58605ccf1d8ee066204a4a639828c41b722fb4a1e6c9bc3f82a89d85fd042f85
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = 22701a8d35f1bd5ee25579897a36b3d698defc86ff09ed11b8b4d81f65c513538f1cdaaffda9a2f7ab68e22ad746c80a31613cc8c3ddfe0143fef1ea22d79dba2393e484
+
+Sum = -4f73fdc6540686b350c859bdbe8f22340786ddb04b7ddb8858d33ce8931bcf660269129607f77dbc1db38d8186d8bae7ebb4ec8716c6eb26342ec8290d8d8988b1f5fb0d
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -4f73fdc719976c323718288f498e906313f19e06712fc4d792227f2f9fc9e4372f16fce562ae37938fd98bbccfdc3d41527c73d9c518a1c6d6f9927e6d5e89548b66460e
+
+Sum = dcbcb3df6508052fd0d1cfb0a6088fe978227066c58317cc359f508bce9f45987ce3152022e19ef068b0381ce7d781ae3e7c04243541744c9f374a3f28dbd746acd3b9fa
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = dcbcb3e02a98eaaeb7219e823107fe18848d30bceb35011b6eee92d2db4d5a69a990ff6f7d9858c7dad6365830db0407a5438b76e3932aed4202149488acd712864404fb
+
+Sum = -163f4ba6595207387ef0956796ac29e3c6862b5344abdce3db4ff7e960b7727fa0a2870dbbe17bd8c446000b3074c1145368d4b84b39029110f915b61916fc29555d7d800
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -163f4ba64cf8f8e0908b987a7dfc3300d5bf7f4de250be4ee7bb03c4efec91328dd7a868c636103b4d23a0277be488eebcfc5c432053e72706cc6910c319ec2c97c678cff
+
+Sum = 3588d982604f471ff0ff784942bd43d85cad820864e0b9ee80cc9a9e3807d2739eb58d447830f73fc8cadc88d864f98577e43adf5150b2eb104e75939caa7de02419b6575
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = 3588d98253f638c8029a7b5c2a0d4cf56be6d60302859b598d37a679c73cf1268beaae9f82858ba251a87ca523d4c15fe177c26a266b97810621c8ee46ad6de36682b1a74
+
+Sum = -4d51ba5f184e5d20b30f8e41d663d14dbe4f692f1a0749789c02290af4c889268c319fad8b9b7c9cc71e8d9878039931447fd6ede967c5c82c1915631f3237aaacf4a1763
+A = c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -4d51ba5f24a76b78a1748b2eef13c830af1615347c62680d8f971d2f65936a739efc7e528146e83a3e40ed7c2c93d156daec4f63144ce1323645c208752f47a76a8ba6264
+
+Sum = 9d7a5610dcfc50699e6bc065584fed73fddbd58dfbefe377eaacc024e33e6b4fd361fac0844489fdf13efd8dca7fae0747603f4b26bb2a9bab9de5241a3af4a935ac940aa
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = 9d7a5610e9555ec18cd0bd5270ffe456eea281935e4b020cde41b44954094c9ce62cd96579eff59b68615d717f0fe62cddccb7c051a04605b5ca91c9703804a5f34398bab
+
+Sum = -1258b397182002c966f064c2cdadb06910e2042d0f51b4af494338c12b6efff052fe564a00e581c5aac0ea79fd8a1ff68ed92b7f74baabb03a51337d4b9b01a2f64ac803cd
+A = -c590e57ee64fced18aff6e2f0c6ac05625b1e94f394f42470cae14d12cadea4f5ab6b9d77225fe3b4903825966c78752ae51b6a0a2caca555fd0ffcbd9704b01
+B = -1258b397175a71e3e80a14f3fc22b0fae1d5996cb92c02c5fa09e97ee46251db81d1a85fb18acb0bd34ec47bc2411c74357263f8220c59f999ae68b2f63b30a32a7157b8cc
+
+Sum = a1eea50170df6807aef40929a52c097081e1755b575a49548ee5868281973a141920234cd0176d64f84a5874dc417cdc8a5c338cb54bca390538e1014d638b51
+A = a1eea50170df6807aef40929a52c097081e1755b575a49548ee5868281973a141920234cd0176d64f84a5874dc417cdc8a5c338cb54bca390538e1014d638b50
+B = 1
+
+Sum = c7c26d68246f16d9d9996fe67616d2fd48809916e8121a5ef95b17bb9b8333d84e2416bf2a5eb3b686c936b9722e0a92a376f357aea7719610e864d9e2a5a677
+A = c7c26d68246f16d9d9996fe67616d2fd48809916e8121a5ef95b17bb9b8333d84e2416bf2a5eb3b686c936b9722e0a92a376f357aea7719610e864d9e2a5a676
+B = 1
+
+Sum = 80d5de21acc1eb10fff4e534d23b5cd39e1eebc3d7f03aea438bb6e5237ced9955bf86898e93c74565c9a197e3ed2ff8edd3acc41ecef97c4fcfd52e1cdbb07e
+A = 80d5de21acc1eb10fff4e534d23b5cd39e1eebc3d7f03aea438bb6e5237ced9955bf86898e93c74565c9a197e3ed2ff8edd3acc41ecef97c4fcfd52e1cdbb07c
+B = 2
+
+Sum = e020b9bd8d194468f8b563c8f586f6959533be8507bd4d3d7e494ef3733007c062caaa65da5c51b52f18cec4894966352f948517ee92d5f9b5ed00f020b1d1dd
+A = e020b9bd8d194468f8b563c8f586f6959533be8507bd4d3d7e494ef3733007c062caaa65da5c51b52f18cec4894966352f948517ee92d5f9b5ed00f020b1d1d8
+B = 5
+
+Sum = dad6af803cf2f40e75cbb564e8229c0d25465930d2ceea73715682c26d582148a943c1c767ac5167c0425975ff75a66eec5ad418ded078569dea2f77359c1cf8
+A = dad6af803cf2f40e75cbb564e8229c0d25465930d2ceea73715682c26d582148a943c1c767ac5167c0425975ff75a66eec5ad418ded078569dea2f77359c1cfc
+B = -4
+
+Sum = de90e3172430754f80e116cc8c848bee88c8e31810c6ef0ded5b05bbef6d5b81f9bf6593622ebfcb2b41be2e87d62ab7fd566763b74428275a16d1da482e5f76
+A = de90e3172430754f80e116cc8c848bee88c8e31810c6ef0ded5b05bbef6d5b81f9bf6593622ebfcb2b41be2e87d62ab7fd566763b74428275a16d1da482e5f7b
+B = -5
+
+Sum = c153ce69e35411c7f1e52809773ce03ce8d2af10b5c7aa3f4c9354de5ca044b7ef25089f1e96bd14d6c62c88b3c39951df19c73751ba25dc758534adba7faddc
+A = c153ce69e35411c7f1e52809773ce03ce8d2af10b5c7aa3f4c9354de5ca044b7ef25089f1e96bd14d6c62c88b3c39951df19c73751ba25dc758534adba7fade2
+B = -6
+
+Sum = f0c843f86e227571d67cfc34ac00d0e6f87f4cbd3273af68562657ae5ca82ddf5fd63476d56d5cccf62dd93f8320c0ba88658493dde282abc22bd09a01f6f2be
+A = f0c843f86e227571d67cfc34ac00d0e6f87f4cbd3273af68562657ae5ca82ddf5fd63476d56d5cccf62dd93f8320c0ba88658493dde282abc22bd09a01f6f2c5
+B = -7
+
+Sum = c5ba28844b8947aa0c2933f06aa88f0b34e0e10ca9baf1cc3bd5ff2dc0590e3ac5a2f2d3a1408009e1b35e08426bdda001adf93e872b03f4f6df28d34a3355e5
+A = c5ba28844b8947aa0c2933f06aa88f0b34e0e10ca9baf1cc3bd5ff2dc0590e3ac5a2f2d3a1408009e1b35e08426bdda001adf93e872b03f4f6df28d34a3355ed
+B = -8
+
+Sum = 84da246c2485e335d1f3b7e31c2408365f2afe7bff7b596440281c1618bbc8bf7a3896ece480fac4a29070539a95f1d718c151ffbfafbb82629bef9d2afbaaf7
+A = 84da246c2485e335d1f3b7e31c2408365f2afe7bff7b596440281c1618bbc8bf7a3896ece480fac4a29070539a95f1d718c151ffbfafbb82629bef9d2afba900
+B = 1f7
+
+Sum = 9673d93165b5be256689ba4e750243537f85bc28daac7f65338074081f114b3a83871683c89fae3c87d44da053557aa16dd074b1bdc16c02a74c5b495f875449
+A = 9673d93165b5be256689ba4e750243537f85bc28daac7f65338074081f114b3a83871683c89fae3c87d44da053557aa16dd074b1bdc16c02a74c5b495f875453
+B = -a
+
+Sum = fce022b2dd492a96f8b095712803f318a45a9a8f00a48dec06accaf793e54e59daa14c56c2fce011e30e6394937f7bd6fa6afa1b6dc3b5359ec7bb4f757c5d89
+A = fce022b2dd492a96f8b095712803f318a45a9a8f00a48dec06accaf793e54e59daa14c56c2fce011e30e6394937f7bd6fa6afa1b6dc3b5359ec7bb4f757c5594
+B = 7f5
+
+Sum = f04028fafffb1aee499812d12f9fcbb23e6a872b3f69fe7a7a246d8f98ba2aa954f78506b39c023397855ead87854412c881fdd16267c07ee12f085b055c7c71
+A = f04028fafffb1aee499812d12f9fcbb23e6a872b3f69fe7a7a246d8f98ba2aa954f78506b39c023397855ead87854412c881fdd16267c07ee12f085b055c6c7d
+B = ff4
+
+Sum = 9c008016815a6580728b3f690eddc7695fed44171557df8a4a6e8c0d5e7c3296832b4ba9ee4a4cd7e6a8ef23cf8c64fcd0518664289c4e72105b404cd6c0ab6d
+A = 9c008016815a6580728b3f690eddc7695fed44171557df8a4a6e8c0d5e7c3296832b4ba9ee4a4cd7e6a8ef23cf8c64fcd0518664289c4e72105b404cd6c0ab7a
+B = -d
+
+Sum = c12bf7e503d2c5845c60886ad5ef87d24e002498003b44922e462f36592a52c878123a6d1037896ce9fb7d2c680d008e80009da72c8e1415e957b2fefb52c34b
+A = c12bf7e503d2c5845c60886ad5ef87d24e002498003b44922e462f36592a52c878123a6d1037896ce9fb7d2c680d008e80009da72c8e1415e957b2fefb52c359
+B = -e
+
+Sum = febba964e2548ed1474dac7c1eb9b1cd169ac913530b7fb358d67197517266707e5a176a814ec82cf8945214b30c36ca7ac0b1ade1848573e72d408dbede8f53
+A = febba964e2548ed1474dac7c1eb9b1cd169ac913530b7fb358d67197517266707e5a176a814ec82cf8945214b30c36ca7ac0b1ade1848573e72d408dbede8f62
+B = -f
+
+Sum = 8a3f9eeb76e96f13446c593fe2cabd4215e0debc54025df7791d924d8afc08dc8f607b82a3d07d75897bfeee0c42b9a32e0e77a098c1cce9c001aabe0481996d
+A = 8a3f9eeb76e96f13446c593fe2cabd4215e0debc54025df7791d924d8afc08dc8f607b82a3d07d75897bfeee0c42b9a32e0e77a098c1cce9c001aabe0481997d
+B = -10
+
+Sum = be825a00c3c6b192d04863b0719ee1e687dbbf2cfc0c331c00b8b947c17fecb7700c9e534bbc49bd61978754ffae1e57d80aab34f5fd23a267e10a4b5a13a9d8
+A = be825a00c3c6b192d04863b0719ee1e687dbbf2cfc0c331c00b8b947c17fecb7700c9e534bbc49bd61978754ffae1e57d80aab34f5fd23a267e10a4b5a11a9e9
+B = 1ffef
+
+Sum = d1c861822ba0e93be81fc78a2628756480146225c79b4a389588a9c3bff9a7500660e99c28807d9ae7bf8c1e89e81d4f9ff2f72d35ea6b34d09df053d46dd294
+A = d1c861822ba0e93be81fc78a2628756480146225c79b4a389588a9c3bff9a7500660e99c28807d9ae7bf8c1e89e81d4f9ff2f72d35ea6b34d09df053d469d2a6
+B = 3ffee
+
+Sum = 98ac65b4c06400baeb40ed137ecdd930a3607423caecbe1f1a936a8210c28fd84b53324e5bb73b7e4b71209b1a4d106796d57a4a23fad2c23abc0c039539080d
+A = 98ac65b4c06400baeb40ed137ecdd930a3607423caecbe1f1a936a8210c28fd84b53324e5bb73b7e4b71209b1a4d106796d57a4a23fad2c23abc0c0395390820
+B = -13
+
+Sum = da02949862a4b26a4fb4bff43b21c2cdd048189199612616303d3ab34dc6f201be256f5889e368867a0da200a0b03e904048d6ba5caee1dafa16f4fdb1f00029
+A = da02949862a4b26a4fb4bff43b21c2cdd048189199612616303d3ab34dc6f201be256f5889e368867a0da200a0b03e904048d6ba5caee1dafa16f4fdb1e0003d
+B = fffec
+
+Sum = ea9523fdde49d481c9f449969fd8e191e118058e0593f2a27ef0ade666ff478c50acb274a6c77d9ec4ca628ab0d7f3dc18708327423de28616235187acb197f8
+A = ea9523fdde49d481c9f449969fd8e191e118058e0593f2a27ef0ade666ff478c50acb274a6c77d9ec4ca628ab0d7f3dc18708327423de28616235187acb1980d
+B = -15
+
+Sum = dab5613ae3756d29f22bc30213363900e3fdced153a3c20852d51c71cbb9af41aba6a16d0b72926192ef48f25e8975881ca7973a69590dc6f0224395e6f3684d
+A = dab5613ae3756d29f22bc30213363900e3fdced153a3c20852d51c71cbb9af41aba6a16d0b72926192ef48f25e8975881ca7973a69590dc6f0224395e6f36863
+B = -16
+
+Sum = c442f3e574310f78e0ac187af96550d4999b79da9c9d6ffa9eb9437a2ac01479003d8e795ce68dfc0f87a4fd9b00b6c172c72c7f580a32af015a3a3375b85285
+A = c442f3e574310f78e0ac187af96550d4999b79da9c9d6ffa9eb9437a2ac01479003d8e795ce68dfc0f87a4fd9b00b6c172c72c7f580a32af015a3a3375b8529c
+B = -17
+
+Sum = b9ac1e23fbfe179d9d3ff99b2ad8399754ea5531e6fce5dad997e2c961110d49d0e3d9c2ec03289edeb39e5a6b4744dd4b3cdd6c43f4e8f4c8e91617772e7fd0
+A = b9ac1e23fbfe179d9d3ff99b2ad8399754ea5531e6fce5dad997e2c961110d49d0e3d9c2ec03289edeb39e5a6b4744dd4b3cdd6c43f4e8f4c8e91617762e7fe8
+B = ffffe8
+
+Sum = e087174c20cba6c4e1e8ffc2ecfeeee770898916454724c24b56d8619c27db123078d406d6b7b836b0dd3092b34b736c472f1afd983971230f1e2b729b00acd4
+A = e087174c20cba6c4e1e8ffc2ecfeeee770898916454724c24b56d8619c27db123078d406d6b7b836b0dd3092b34b736c472f1afd983971230f1e2b729900aced
+B = 1ffffe7
+
+Sum = ba66837e8e8bdefa4c3df73ba5ee65d1ab45a68f51072bf2997446b13b6c73b29c26d15ddff186c9621e156bd3b650caa267dffa54abb782734c443bf502b276
+A = ba66837e8e8bdefa4c3df73ba5ee65d1ab45a68f51072bf2997446b13b6c73b29c26d15ddff186c9621e156bd3b650caa267dffa54abb782734c443bf102b290
+B = 3ffffe6
+
+Sum = fc461dea452aaf0e2c1df10b7cb4293fbc498d40caa7a917a741c6d3534914fc039bb7a62d14cc3e9ea6cc8d2b41228628ad56687d18858c3867c75ae83a3216
+A = fc461dea452aaf0e2c1df10b7cb4293fbc498d40caa7a917a741c6d3534914fc039bb7a62d14cc3e9ea6cc8d2b41228628ad56687d18858c3867c75ae03a3231
+B = 7ffffe5
+
+Sum = d109e7982ffd500ed77702054ccbfa49bb47b5cdb2220988ef58af3cbe0ac90bb3b2ac8a2c558fe744231bf227bf35343e12ecb312242ce50a85fe461e73b601
+A = d109e7982ffd500ed77702054ccbfa49bb47b5cdb2220988ef58af3cbe0ac90bb3b2ac8a2c558fe744231bf227bf35343e12ecb312242ce50a85fe461e73b61d
+B = -1c
+
+Sum = babcba83c01843f6448fc3f91c006a673e514c9626c6399d43c016c31a8fd1a9fc58d1c63ba5b9565dd7320c4a04fe4331fbb79de1e03d68db331bbe2b4b9036
+A = babcba83c01843f6448fc3f91c006a673e514c9626c6399d43c016c31a8fd1a9fc58d1c63ba5b9565dd7320c4a04fe4331fbb79de1e03d68db331bbe0b4b9053
+B = 1fffffe3
+
+Sum = c52e7fb27c4f670109b32cb6d3f705e1685e2cb7474a90d3815e486de77dd2584a0b65d22040059ae5279450682a189eb1b0f847e0d3fe022628a73eeb99c54c
+A = c52e7fb27c4f670109b32cb6d3f705e1685e2cb7474a90d3815e486de77dd2584a0b65d22040059ae5279450682a189eb1b0f847e0d3fe022628a73eab99c56a
+B = 3fffffe2
+
+Sum = b5f074f655dbe68df022b0093534b609b23c17eefcfdc9b1b150c8cfdafe1d320fff7452c147c7d9f9cbe16be25970a23e6499bc90e689497c8bf2d38219e4f4
+A = b5f074f655dbe68df022b0093534b609b23c17eefcfdc9b1b150c8cfdafe1d320fff7452c147c7d9f9cbe16be25970a23e6499bc90e689497c8bf2d38219e513
+B = -1f
+
+Sum = a1a41b6638409305ab9ffa22bb3cb9434f587d4ce6f6da47c0ad6f8f720f397c37cd61254f35fc9f0cda36476ca6d95f233604b9ae5ea2f1a1207caf15682e81
+A = a1a41b6638409305ab9ffa22bb3cb9434f587d4ce6f6da47c0ad6f8f720f397c37cd61254f35fc9f0cda36476ca6d95f233604b9ae5ea2f1a1207cae15682ea1
+B = ffffffe0
+
+Sum = f187feee94925d57f65f9b1200193d8e9359340d670bab27c022d6d63a54635e4573593790e6c6b779becb9e5ea81c9b075baa2d3bc95493b0c5a2da1fccebbd
+A = f187feee94925d57f65f9b1200193d8e9359340d670bab27c022d6d63a54635e4573593790e6c6b779becb9e5ea81c9b075baa2d3bc95493b0c5a2d81fccebde
+B = 1ffffffdf
+
+Sum = dc9c51e1313cb655969b4a069f2e8edd850d4fbc5bbc36f05df42a526f4e5b3ed18886263d86231193442b3ac3e7a71e5a6377021e71ad07dd9411953dbeedc5
+A = dc9c51e1313cb655969b4a069f2e8edd850d4fbc5bbc36f05df42a526f4e5b3ed18886263d86231193442b3ac3e7a71e5a6377021e71ad07dd9411913dbeede7
+B = 3ffffffde
+
+Sum = f2b5e665a6a2e7009bff8b2750b5fb11576bfd49dee5dd7f32b02c46430923b0ec95c3fcee0006b0c2591cbf1fb18dde331d8fb119d92f3196a7dfd8178be33e
+A = f2b5e665a6a2e7009bff8b2750b5fb11576bfd49dee5dd7f32b02c46430923b0ec95c3fcee0006b0c2591cbf1fb18dde331d8fb119d92f3196a7dfd0178be361
+B = 7ffffffdd
+
+Sum = fb0f545b752979151bc6004b3db33bad63230c26d060ba00f5b82e7bee7e2c854b09b2a7c6b4186776c6b3cc45afbc50ef35df7abad11fec62523a12be1cb7a1
+A = fb0f545b752979151bc6004b3db33bad63230c26d060ba00f5b82e7bee7e2c854b09b2a7c6b4186776c6b3cc45afbc50ef35df7abad11fec62523a02be1cb7c5
+B = fffffffdc
+
+Sum = fc197e83249b069fb34552188cd6d06a7e0b42c6a6a9869ede485328a0fabd0c0ec2f79b81747129ccd70ee5c0f9efea62c36d1a4e1fb2b80393fe636469c25a
+A = fc197e83249b069fb34552188cd6d06a7e0b42c6a6a9869ede485328a0fabd0c0ec2f79b81747129ccd70ee5c0f9efea62c36d1a4e1fb2b80393fe636469c27f
+B = -25
+
+Sum = aaf9a8ecbbfee9c3092d9887ec35118a9614a9fa84fc50b79b11d03a4967066c361f67cbf7a8e5beb620c7da55f4bc7dc50ad44b22c9128994781c7816a439af
+A = aaf9a8ecbbfee9c3092d9887ec35118a9614a9fa84fc50b79b11d03a4967066c361f67cbf7a8e5beb620c7da55f4bc7dc50ad44b22c9128994781c7816a439d5
+B = -26
+
+Sum = e74e32fc45d099ed147bcf7d798bd3aef9b046291038d98431698e90d22cf944a92bdcd8a5cf378e9a3aa0001150cf6e4dc37fa4e54a25e13c75099c64b9350f
+A = e74e32fc45d099ed147bcf7d798bd3aef9b046291038d98431698e90d22cf944a92bdcd8a5cf378e9a3aa0001150cf6e4dc37fa4e54a25e13c75099c64b93536
+B = -27
+
+Sum = a3486d022ef4d0a0c72170f05300cee78df844db19c63754c2d631d3d9ae20a0205cfe0fe947f8f4d2f9fa34e2081f448a938a446e8764ac2141157cab01dfa0
+A = a3486d022ef4d0a0c72170f05300cee78df844db19c63754c2d631d3d9ae20a0205cfe0fe947f8f4d2f9fa34e2081f448a938a446e8764ac2141147cab01dfc8
+B = ffffffffd8
+
+Sum = 8952cb3f70b1344facdd7fe79747773f9c101bc2a083fa8fdef0679c24ba93218d14d4d7e848d293ce431119d1542833e9a0624b812f0b31b2b9f7ed9455e8b9
+A = 8952cb3f70b1344facdd7fe79747773f9c101bc2a083fa8fdef0679c24ba93218d14d4d7e848d293ce431119d1542833e9a0624b812f0b31b2b9f5ed9455e8e2
+B = 1ffffffffd7
+
+Sum = de9cb4d4cdd1d58572fa1052edf72bb9241555bdb967bd8cefb26cb12c6622d6147385dc3f72e110b17afbdebc5feb959cb6c320a2ba01f36585b53fb1c5f07f
+A = de9cb4d4cdd1d58572fa1052edf72bb9241555bdb967bd8cefb26cb12c6622d6147385dc3f72e110b17afbdebc5feb959cb6c320a2ba01f36585b13fb1c5f0a9
+B = 3ffffffffd6
+
+Sum = d37f2e1638c0b3bd624104d244d9770ae05bf37f7a6ec32db552af413c0006fdcfc312cf281190eb6738370f3a8c4655beddb6b39b342f0a67cc9af92a2c7fdc
+A = d37f2e1638c0b3bd624104d244d9770ae05bf37f7a6ec32db552af413c0006fdcfc312cf281190eb6738370f3a8c4655beddb6b39b342f0a67cc92f92a2c8007
+B = 7ffffffffd5
+
+Sum = 831aca9ef43bea89f048250aab79b06207458647ce347c68f91013695299c80d610c6e49e2dcd46eb02dd56573d31720efc277469e573f6ecfb71b12886653ac
+A = 831aca9ef43bea89f048250aab79b06207458647ce347c68f91013695299c80d610c6e49e2dcd46eb02dd56573d31720efc277469e573f6ecfb70b12886653d8
+B = fffffffffd4
+
+Sum = da95fd2d2438a79843bdf92c1cadd0e9165d002d22dcacbe4118cc3cf7d5de2fd2106aaefc790aa1559b28b641f83e4e5aa0f8446b57fde5c3663c13efbc04fb
+A = da95fd2d2438a79843bdf92c1cadd0e9165d002d22dcacbe4118cc3cf7d5de2fd2106aaefc790aa1559b28b641f83e4e5aa0f8446b57fde5c3661c13efbc0528
+B = 1fffffffffd3
+
+Sum = bf9e3169dd4b6d336848e744231d1ca85678aa3d1d62d42eac0b16500ef527e028757da54a456b3d684199f3bb3c866a002ee3885c86d2a79180487f4e8a45f1
+A = bf9e3169dd4b6d336848e744231d1ca85678aa3d1d62d42eac0b16500ef527e028757da54a456b3d684199f3bb3c866a002ee3885c86d2a79180087f4e8a461f
+B = 3fffffffffd2
+
+Sum = b5880868d947554eeb536246c312c9765ca8c96888817f3ffdc16cdbafb41fe8f7c151cb316da27562d3b82b2d45abf7c9304f488538386e84c6a23e3dc375fa
+A = b5880868d947554eeb536246c312c9765ca8c96888817f3ffdc16cdbafb41fe8f7c151cb316da27562d3b82b2d45abf7c9304f488538386e84c6223e3dc37629
+B = 7fffffffffd1
+
+Sum = 84b1e4079d09df569a1623b990d917871b1197723b30b19fcf3c063b0e84c9cef1c3ffed16f33aa9bede08b4831bb3ecdadae1622c93e1f86b474a4989496fa4
+A = 84b1e4079d09df569a1623b990d917871b1197723b30b19fcf3c063b0e84c9cef1c3ffed16f33aa9bede08b4831bb3ecdadae1622c93e1f86b464a4989496fd4
+B = ffffffffffd0
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30c6365e1eeb044
+B = 1ffffffffffcf
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = 80695b879bb74400c107619981f3bcb3c9987c76d545f6485ed128082377799534508a83112fbde2ee5558c246332c656455
+B = f6446ca2883d7e27209eeaa01fdec632d4027113b81bb47dacc8f10eadc3b3ffc26d84135d91e70deb8aec84c7820332e8cf786e2af9b4217a4c1d32b5894bbe
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -1b510bc480138145e2a142fce8330ee5f4030dccaf6017a1dd85bc5bbe9b2fee4f9d8fb484661a839dc9613652bcca11a00eb
+B = f6446ca2883d7e27209eeaa01fe0fbacebd20e03107a9f993e30f63358d6bdc91baf4f5acdf81e3ad94ef9af3ffc315c6e9acfff91167f0ce6738f328308b0fe
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = 219f59352ebda4cfb785a18834ec1c99145a6647265baf5d8f3b405f29a746785a5e70777d528ff1526688c01b9eee288e6cd
+B = -f6446ca2883d7e27209eeaa01fe16091c2dcf8a54917eddf26e5c1c43408c33ea356bf1449b339931985aa70a89cdd6a7aca5ec6e7f1c8df5f101d54c47796e0
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -7e5a2ec59519143f7bda2829cfee4ae75cc8038f31303ff9bbb1e2cbfe93c46a1367c9d6a2a3d9cb40f1a6930c18c78f85724
+B = -f6446ca2883d7e27209eeaa01fd760f94330bb39b824b7e28bc5741dbc01b11805f14655543e8ac0e6d326bffa760106d5e85f604c28935c69dda1d968f658ef
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = 9f580ff614b449cf9c46c91256c20983f5c70200739de72b917344db81c1aa1bf3927c38c22d026d6ce38ac746ada2948e538
+B = f6446ca2883d7e27209eeaa01fd5511b3028c1865f22b1187d3d06e1d23821281edd1f7ae1212eaac5daf3e19f57fe5bafc666cdc205d43e2699f88bb8a5cadb
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -15773d29ba363a15a0cb31ac4a60c0c228967e857d7d11c1ebb0a8db855c0d0797c0e409899a50e1b1c989a7dcea6f26238d27
+B = f6446ca2883d7e27209eeaa01ff4bdd95944430511bd40b6baacd3c32ca01416c461d66b15c5f687ef186c0948aef8677cdc23eeca8e6c007aeb4dd508123d3a
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = 2f90f72f59dd7738f5572e31d41b91599ed500d59537bf5c21a1bedad709303cba0d5bf1b5e4eaac1a85c261ce94c45b64646e
+B = -f6446ca2883d7e27209eeaa0200ed7935ee3ea423511ccb340368e93c416529914799118affbe79dee6a192c7dd144df65086e8894f7283934dcf82a3d531481
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -73978eee2b2a4ac8ef12b3042dd5e1ae8724a0a676d0a52035e801d741a61b92c638a3b0cece6a81bfd2703e3c502ad1fa784c
+B = -f6446ca2883d7e27209eeaa01f6baf0d415ee280332d62d20a349d20bbf058f7986d88b433a45ddd3c5169e0ae50fedfc283bb33671cd00694d2133b0ff437c7
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = a462699ec5214f0d7860974a669d1728b4983a1c3c440213d12b2da58bba9dd1caf1d5ed391a3ebd80aa6e9ef0396e62260a1f
+B = f6446ca2883d7e27209eeaa01f3ae43290c4eb7beea414edc3fbd5eb41c2e55e22a8155740091ab16e07555e6f4c45ad86196f5f2b5bf808341e29f77fc8a5f4
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -130f7a12825a6c5b6b109b91e2506505a261c9f7c1a62fdfbe252275d3f6844dda2aca2d0ff6d8406ac5c679c80ab6d29817b4d
+B = f6446ca2883d7e27209eeaa021103e3d57afb390b2cd7f3e2c877952c49d9a37bafebc574fbc980670d278411eb9e4264451f721ef88fede6f8f0ed30b702b60
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = 2863fa82289aff06fb16bd1b866da9ac0ae0f411a8d8c2c084cf78b81d6713a9a4700248ef61d5e52ca7470f1f251380368df10
+B = -f6446ca2883d7e27209eeaa0226586445213bcbb6bcde156c6c94d9d2b258cd95971e5855c273d6a95698136db5e37a80248a6fc3ba716e7c500b49de5578f23
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -6176f648b54dc4e2d11ba7e32d2d9d3f400fbafa489fbe7f126daf1f929ef8f219c78ff1063dd27650d4751c63b6e7ad7d9a588
+B = -f6446ca2883d7e27209eeaa019c7d737a435307ccf0abb06db8f992e767681e89a5a5d7162b36aed1a69206d1f7abe8462eeac7683cf5b250cd2f4eb0a150a8b
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = ccff1ed8726e309c4e0f2e166c497cd718a8eac347674ca57b6f317ea491b743a89d25f87c37f379f6239b13d848eee1ffa9328
+B = f6446ca2883d7e27209eeaa0130f54aea86329c1373b82a3a79ddb34f8eceeec0a6de48efc2352c72949f488068d6523eb8f0a66497a68c59589d477c1f41ceb
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -13d1c041415fbc18179c970fe989ad9e1f10e4ff658c1bc550e93f6ab9f9cc9832fd49cf6f2e75af72a71dbd7b121111ee0d4098
+B = f6446ca2883d7e27209eeaa033b106dd70e9c8e313b90c94f7ec20a089886297a470751ea4c38549cd8cdc9474148152e280ff4d5b83c0344e207477cffbf0ab
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = 27ede3a23479dcc5447bc3b64df32c121761de88086204484cea0782b8d63d72b57192f2b20dd3dff395e937c91e21cdbd13b68b
+B = -f6446ca2883d7e27209eeaa047cd2a3e6403e9904098393b5c559f1481d95c2047465da1a0c44d61cc694d6ef688ca7625605d7ddc728bae9c2c85339f02669e
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -4ad10e7f5637cc48b04d4b250e4ca00a0d102c91caaaf6291f1248b7a1cec979f87b7251c50db8e5e49206bebb30b7f3f25c8577
+B = -f6446ca2883d7e27209eea9fd50e381cd95240824bcf2a600015d2f85d6751067439633034c7fd2771c44682489bc531ae44d0b8044a9bb817ddab71ef922a9c
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = c6b77c2c932d9d5ec6175def706d6e9c411216fe12ac52043c617761d3a37804487f158de60a9c18e7a19646c455804a65bd80f2
+B = f6446ca2883d7e27209eea9f5927ca6f9c5c6f6c360517959df504662965669a2c3807551778ce7d3fef97f7f89821f58d47ed85013b0c300eb8e31b7c312f21
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -187976849837d4ad4cfc9764fd0e3f865fa9d1d9f20d98ccd52a6b3652277100bcfff85fb8414c2967dacd26f269502d3c2caff12
+B = f6446ca2883d7e27209eeaa1a776aee5b307579fcbe5ebd4df466b6865149b375fbde626a680f944360a20081116bd7ef7674c34668974e5f9a36639a4b9af25
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = 33913efb99088ab80c706ee229e7a6ea6b274097f6ed3734452dabe0865eb86fcf20c9c6ae0e613b72dbfb8b126383e7d10e8bbb4
+B = -f6446ca2883d7e27209eeaa358f33655c012b84bc32363a7acdce1a91ceb8717adb7cc9da6b503e7797e96f93323d3ee54389d55169c5b27f946a1e2f2d76bc7
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -5d84033a924ff84666d3ee1a1342ac118224264c439bc658213b9762586e8dbdef141024d757175f30bec23a960ab145832dee9af
+B = -f6446ca2883d7e27209eea9a479f12f30a8a88648edd93e3da37b1ea483518d40527f3d74020cfb98caa341d4fd63535fde113aadcf07ecd72634f0daf0fc664
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = a2aeba6a0d6142f527358ffd4c9139c390c9dfab07947c902085d1f3c367035db0f22f249295b974b1d9ebe7add3dfac7ec237f72
+B = f6446ca2883d7e27209eea95f4f39ffb5975dd7888c375b0454ed6c95dd982e7c59c90574b7d26a2dd22da2131f4453a49f6f252cb3de3fbf5d0689df5cb30a1
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -1e545f433c1bda45a7900793d2cd18ba630fcb11d4a2c88bc7a0fb392d270088a1ad126743b80342bcfcfa9e939c9ccdccb7f4f198
+B = f6446ca2883d7e27209eeabe743e89d84b6452728c240957db7b2d657a428f6ce1ace520f4d57f0c3a93989dee299ec72b55cc5ae5d7410a6fab313299e3a1ab
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = 244bf1eb701c53bc7847a644269277f53b58dc23b55a2f996faaceff22666eece40fe14644aaa2ab0197a5a915fefa394a5c357db4
+B = -f6446ca2883d7e27209eeac46bd1320c4bddc94343c2b9aba0da683dc353a14d9913f2c8fea945017a01fce050f87dc81df5349f80824b8cd2089cb03e242dc7
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -7e3419b44f3596c6486e095c3fc9a84b5599868abd292354278a2520f54929d5bc325dc3d095e84431960265dcae84f0815ef5beb9
+B = -f6446ca2883d7e27209eea21ebc5924cf9f346828e13194544ba27acd0f0f2db15c10531c9b524e9ca693a400eb973b2dd6a456c52da3c9a248972e482f8f15a
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = 81fae0f8555d46ede9e74a93b8a7c6273c9bee0eef0f51b4575aad5cbdc0e10a3d03d53cf2a42e6a3625074c812cd0ae41d94d34ee
+B = f6446ca2883d7e27209eea1e24fe4e46d2431ee114d1e1cc669c4bc5ce896ea92f92a501f92ce92152b205bf3d41fa90cf241f67c3d555f5a63db52408a17b25
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -1558c919b3dcd4cc2eacfee2ae98a3b4286bdb6aa67db97ce35df3ac72f6c6418df10444ce791109a9a71250896f20d4dbf19d559f0
+B = f6446ca2883d7e27209eebf5ac70e1d9fcd6cfb5cc0aa06e989db589282e28001a7c278f33150d0e7ff728db515b846b046324385a01ab0dc51bb124fbc40a03
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = 3a9c8b150408b2449466b8328ccb0a5334f2340479203cb790780e71b6609f7999c691ba19f947d8cac4329a4e45377fd6bf226fed2
+B = -f6446ca2883d7e27209eee49e89096dcbaae5611679f9e51bf07a6518db7c52a42afd260d4c161451d8aa998aa32d92307d0164a2c06475b268660d1d415aee5
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -450c41a9cca23287b6448a0b248d24075ed20bec41c600279fd86869b1a51e1842cb7f4d59144436edc1c052f44428965b3b2d98757
+B = -f6446ca2883d7e27209ee64f5bc4a9d20c619166b37bc33c3c21fd1549b8b97bdee1df5bcd53aac4c1b18bcf892261f22f0f1ac1ccd773329084fdb22f1528bc
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = 9d48745690ee5aa8fc448371f9236153c584466583aa30d999461a3defac314356230a763c204c2595794db93fcd3917f25b83d1b85
+B = f6446ca2883d7e27209ee0cb9899dd8d49df7d06b3e555f2d84d36aa2611255d9bd6bfc4f23666e4507eda9a106fd3c16e90304654010e79ff7ce44029b1948e
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -1a3f8af71d423da8c007022421f09a53034c6e9d7d23572b8b4b273b091a6f024ea4216ebbca25daa4e9e83fb46a1d9e65fea344bcd4
+B = f6446ca2883d7e27209f04dfaad663de6d32ccd1fe409775a8b5764ed914fabb960fe4a47b154ef982955ea06285f34d992d2e87d11c56e0f0acc96485336ce7
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = 3cd13ae384718065169d7e6b600ea1d1a514832649029f92f1d2b5bebbf83454fcde0133f3bb4716cf452a3f930d28f30e7f22f21982
+B = -f6446ca2883d7e27209f27715ac2cb0dafef23687a87d593b0341816ed9dc69ade774b2c099901d747e80cda424b2b3eba6958e3131c3583fc0171e504e0c995
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -5849ade77039ed0b15524c08929a4553a6c0825178f6522915592ffa9638a8143fe8426df9757e8c06aabc97a2ef87b4a58869d1df4d
+B = -f6446ca2883d7e27209e925671f7d662427ef778b013e2eac90ecc41e82604a1ecbb440023dfafa66b7ed013fea93e0df4c682f32c44ff874b59bddd781cd0c6
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = 9c4b4b4800fe2f11e1897ee8c8e147b143a252847548145e77d9a9d3e4e3a79283f833e760bdc69d5f75fc1d0356615b0c10b1e34f9f
+B = f6446ca2883d7e27209e4e54d497459e00782b417d33aca3c6b12f6017f308502a85e17faa0660fb6c008c040d2fd6c5acb52a27ecbf9f2071b35755300b6074
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -1bbe5a805b857ccd9dae7cba6f3dab95d22f7d2e1621a2ab382898bfb2b4efccb263929f752397da4ad030e6d5c8773dde8fe04c42f97
+B = f6446ca2883d7e2720a0a685c7e4fef3fc63e7b2c7c3695fc7bf95fa3d58dfb26997dbe2dfd5712e105e36356b0e89bcf0f736a0f749fefe46ec4c63e6b2dfaa
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = 255c9a10ee08acfe197fecdc7b6cbae27f8dd38887f135cc5adb1b9276c94ccce420887a7476b2d17c2708c84b7e9a8b4160f676f8d1e
+B = -f6446ca2883d7e2720a14069c0ee2726ff6ba4c9c9e42c50bc8a6bdfa2fffcab9baa070b0d01b273e0615204c8be7eeea06a4c0e75615a607bc27975495e3d31
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -4bb5296b4ce3e960ecadc3f15de0a3a0dacf12d34f690cafaa8f2e31b0e9e69d42a3b16bce84361c81b7584be32210daaddefd7184659
+B = -f6446ca2883d7e27209a2f4d892a785d997b41eebd06977ad454c6113d42870773e9b06670bf3740a9bee5c12a5a4f40118a6e28641e7055c56385760ad669ba
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = efb45966d1f6d79c9b4c72c3a584e26e7b7136295fb79a911433a10ef649b47b14b8d76cc42e54852176ef7da7d08b86186cbe6e98b23
+B = f6446ca2883d7e27208fef5a8972272eb5c05803cfe21d36e77abbef07e1821e95d3161f42eae143cbe1c46eca4af49e2b00722ef102256e1aacdc99fb0524f0
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -1e30bf701cd589fa3d2adff0217e8f748d1a254b771d77d342fffe3e3138aa3d4a75ca8c1e6636919636d4d96d8b04d583af4dc208b51b
+B = f6446ca2883d7e2720bd1b5f8ffc1c2629c737aaec3df41482ef8d27b5ee9b1012275957920b7e8950dd85c6cd359dba04e8c072c24a2d7ba89212b3a3f7652e
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = 320eee30dae44f272fc9606477927bac85b677c3333fa55f4c5b5c7e71bc02266a906d8838a096551a8b5b94980cd819ac721a6ca70a71
+B = -f6446ca2883d7e2720d0f98e50ba2aeb56b9d62b60940800bae8297a2daabd3d9e30b4b5d24c01e139fda069c94fd819c86d14f97d74af4eecbad5804e95ba84
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -5819f4921a515433459006c62df3be1c4e642a52340381b5954df3f9dd0ed5f73f8dc9a17e536b88090ae8d5fbc411f16eeca2449ffb96
+B = -f6446ca2883d7e272046d0ab8dc4f547fc447cc435ee81c6f2140ed818437a16894f0b6559fd37091c5382329f98e417eb497eb512e0de64e19f76c39d4eb47d
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = f238bbcd9701966bc4482fb8df8ca395ad15e2b83c014e59898e33a36623580e9c91faa3873eb26a0e97c4d29ff209e22c4faa0a1295a0
+B = f6446ca2883d7e271facb1e452484505c3c5c49b433ce8e178b55d1fb23b7c49e55acb25b074228704f67e019d8ff8d10943f1d9163cb06cf0e213bbd7dc1a73
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -1e00b3b3bab1081231e0f1a2029b146f8391869dad416f6c8443c124ea7c908ee402f6b6fe06d883c2d232713512ed5d8636a07898523f3
+B = f6446ca2883d7e27227ef5db5b8a571d52a81be51c4626cc069b8b6c454b948f0728956ba2820ee801d33f67b0f7a50baf7facc4fc2dd14cab71cd6d6b73d406
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = 2030dfab0a9e0af1764f416171c8eee2d0b87bd5b80e6cddee4ee2a7509a301956050b6e3bb067f827d13c33abf31693d4101951d4a0b96
+B = -f6446ca2883d7e2722a1f89ad089274b46ef00e1133904733b6dfabfc5f864661dc94783c8e3e8e0a8f360b324d23e02f5cf9d61239bd3e0104f64faff38bba9
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -7427bfdba61a57b644fdd11b2a3ea1d3507cdf4ea1389436bade3fbaf751724000774127923658c7b090f182d1d7e320aeaeb1e3dc0b30a
+B = -f6446ca2883d7e27195c6ea2657da120cb3a2fb949788b67d95aa50d8063f454d336755da4652ebb138b9be9c7f3d1f6f8497a85bbbf2444c8237847a42dfd09
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = d23891ab621e6ee43b3b250d66ab139cc97db21429da33e01910635969af402b6792f6d741292a0e1bb6bc30b2a7b32fcce9f5e8c2e48bd
+B = f6446ca2883d7e27137b618569bd5fadebd65a7a25b1c44b41ca97e127d9da5a3d535323bd3f51dc5d19e08ecd04a4e291971ddaddb22743d63fc40755c06756
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -1d6d78b7e83cedb64f0afa17c56360a58eb5ccc4e647bd3c594feb6695531f9434adb169ce314d4c93b4efc260fc92b268ca22143fb7e994
+B = f6446ca2883d7e273e0c6358081c34527e9506e2c17fd62a9d183fc750bf3ad4983444bfe92d65734840c1660f4884d00707796049d935293bd8857a21a699a7
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = 255261901144afcf37c28015f4ec493bfc06cbabf851997d06cdc2fa742a97e234085ce67dcd867451a19d3427acc5ac2fb5b919f1514e06
+B = -f6446ca2883d7e2745f14c303123f66b674c8ce0f108bec10a693eae62c9171545b21c53c804ddc1479b6ce2bee4bdf7c4f426d21089682302c41c7fd33ffe19
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -4c222346b39b4b87631fb26dd9b3a8942374f10ec577d0aced5cada7bb0fb34d9c85bd06b6d52a4229ec662ca5605aff7896f7d74483fe99
+B = -f6446ca2883d7e26d47cc7596c43fb14cc6a5a5d2268ccf0eaed81f3a4ffaceb5187abb198ca9291770d52f58a420d4149662371437c47775a776b8e9d6ab17a
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = b832106ab8bf5c27886927f67c5bb95d81280a5b4a3a044c39c816dfa5c5a4c6e8058d34c3e44bab649194932e42c197b40d16213f6565e4
+B = f6446ca2883d7e26686cda35671fea74a720e4d47fc0bc278d3a68a7203d794c051c4279ae14a1182b8d82c77d32ebd80ec0f50aba99e0df1f014d44a2894a2f
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -1e4bd432a98b6d68d35627f4a46b56f04b378a535b50c7287ec949008e8ace3ed04a128043cbac7a49c6c1cb98dc27b684c4f971d69b51268
+B = f6446ca2883d7e29055c2dcab8961d2964ec8c1542d1e489c1db18381f83f0202b78e9623c8729cc183438007dd1ff280fbea657769f1ddf1f5dfa834ba3c27b
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = 2af2a9aa0364d970115f35b6ab676f4baf1f4ed52d07cd808dcc7fc7bcdf2268f917a7e4476e429200a37b246e786e85a2b62d6b52de13135
+B = -f6446ca2883d7e29cfc98540562cdd9d457d6835b2936a40005760553af455a11bac55d521cc6c6ea50d8e40b7fb60a37d8a3be4d0638ad0fe713a1b0fcfe148
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -5dcc7b06c24160a67934f3adf5f5a468f10b0bfe1b82e133c797674c941c9480bb1e71ceddd1151f88244bebc63c2da41557670132848e482
+B = -f6446ca2883d7e2143d73a33fbc93c349c3ad1eb9cc22ef5fdb1b320b2496a5bc56de4901210fdd361abf30e6405e58af10dcae18519c8357d97f352b9a5cb91
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = fe6a6b7e6ee19b5e4e2a4cef85f637a5b0a76007bf1080fcdc86c952a49adce824573dbb3c0d3f94d519698968594e0b840b6c91ec9153aa8
+B = f6446ca2883d7e1739f832b931c590b74ce53dd29cb8fb2a03ec7286796f6dca7677c42f0a2c775cce1f344880433e3621bbf1076347c1be92579a4718d9756b
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -1f219dbf1e789d4d74f10ff27fb947bf6cc94bf1e742ba203caf33810589005f8326704b8414819d90698fe08d9b3c16bd261beb922a9af9a5
+B = f6446ca2883d7e46423ca9be987c94112099ff4ab56434f1d7ae64e9ad319dd4ee17da5edcdaa5623a035b805598d513dce26a2b8418b933f92a4ef80c89a9b8
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = 25bbd6ed7646662f6dd8481ac4c4a531174bcd05123889d4cf904d12d8d2bcad5425074d9c7fa1ba70ac5c8a3723fe6b20e064fb4a9999e716
+B = -f6446ca2883d7e4cdc75d8166645760a07d2278fc0c1a69c5a2f7814a3015267cf316c322696f333389a5d98c0b8f1f41faf13d50cdb0d97b3735eb07b889729
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -74af822547dd8aa99da2b3b60b1aa5d45c33cbbdca0d2876531b31a25cec244482832671c861b749effc1cf5e150aeb9d8e88583953aacd577
+B = -f6446ca2883d7db2711cc55842549cfe8cd656bfe176a128da96b5385d4f074523b2b6fc67b6015c906c9e33df5fed93773593bc982de89dea88dfd0a741da9c
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = d35d55e21fdf90fb0abaea71ae6d7f44401f615e7dc6761713ec45650b94c02f85e7bca8c2f43ada8975617eb7ae6fa41f4eadedaeb544654f
+B = f6446ca2883d7d53c3490880404e4b91749f9b1c8e9d3144ef011484a4016684529ef44dbf1a16592bd667394cdc5cf9fdf10ae63a6cfe57846075b72caa4ac4
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -14872666f07cb43b47b4b82ef6df5b7696c2ff49a88ec9308e27d27736df05f79d452957297271756ca1afbc47ad011f1b77f32bbff831bb941
+B = f6446ca2883d7f6f930559a7eb22fb177b0cfc38f1d3def13e570d8b570a867abc0bccc74439bfb366288293682e8e4d8e4e4e18b8ee942e52411f65650a6954
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = 2d2316a87167a23eff9da00b857c9423e44feb69620852e9e8d87ac70d96367a8947729b57804ab1d54022442f5504d23ea42a6cb0eddad04c3
+B = -f6446ca2883d80f9520971b69a033696098ac522c55eb3ca0d190922efa61c25c690ca32b741ee738abcc57445c254d77576cc933929c66115b52e74bf9bb4d6
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -4a296521345e531b059bd7bedbdee650280008947bb0de4012c11281d92be141b2d29b92812a4843eafc296fa69c55a697b4e9620a79fa8fd6d
+B = -f6446ca2883d79848a4cd75a3aad9642720e1f0d0db773050dd92b475c937c6c2dbc3bc695c62ab1e9d9e7e99c92f8d3b0bb8f34238238fb847842be4245b2a6
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = a29d4661e53bde02d72f6e0e3d19ccbd85d8c0a0392d7153ed330ff11e6f75c9880dd1f77a89be8c4e48b10bc7b43b46fbffb592a9a2f23b932
+B = f6446ca2883d73fd4c38cc4c61ff192938a928f95f509d2782586f6f93623ec50de547725c7dad5e36739853a52e729ee841cd22a52832b6d7b538cbb2caf6e1
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -1c7a1c6185b0a2d7c02f3a7884e5a11513785520f1a27e8c29cc30707300edbaaef99509e9c4f578d086b2a8c593d0a04d32682c7c71f6a3d025
+B = f6446ca2883d9aa13d007050c2b706cb6a0291b09d3188fd638364a4e903a7646f54cc5a4194f4d8a89cf9c13690080a25fb4f31b97cefa93b3adfd7d8928038
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = 21eaee9881dff114d10dad6acbb6e712c6d1acc6b878ec60253c44ad7e9272bb5ab0e2ceb2023fa9f427a23ebb464b2c8c411bd86032c6873ef9
+B = -f6446ca2883da0120f376c8010f417a9dcf4d881e32f3c56bb292b7b56d7a2d48391d7ebc695a08ff661c1fe80c12bab159144e434092eb7eee6c398a875ef0c
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -46f16fa8b7a3b6ecf476f8cdf5f77ea3a7c9be958ced5db6c6a9e11e6bcf3a156b3fb60bd5ff862c80d7c3e3f23c15df57a8fd7822d4c7d9738a
+B = -f6446ca2883d3735b0f632fc68f2522536bc16d37d78cdbb4fcce6150cc0b6ee5dc5ed8a19c4da9f5d8739fcbaeab6abaf6e9761d2fd4acdd59640911a153c89
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = bdd97dea2fd68c602862b0fdcbbe47d5e2e23ec1a10925cf34e9773d09d90caf70b5beed3ae1509392289be0ee66b649d45b3dc880ce4f48bb4c
+B = f6446ca2883cc04da2b4bac9937f1e397e8c410cb44692a2cfa0d1f944a848aec7a74f80472ad52954a5d51af083a55ad7719b373292ce1b9545e29792a5f4c7
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -145dd43715b37e7df4b56e5afa79caff8668de6fe4c2f725866d0f84522682f38694a26bea588a576900862dee9c9498df909fe788d72db324f6f
+B = f6446ca2883ec404641045d807be91f31539b467ac14dc12f560bf31dccfe46937297bc18312af293a51b584e68dc78bd6317367326a9b80d186f0d8bd20ff82
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = 35094bde0256df169828d23a250e3a10f35f1fe30f168d463ccd8389197b8aaeb326ca86fd09b3d8a29769ac3c6ed856c34f10cb0d993e38252d5
+B = -f6446ca28840cebbde7f100e1148c929532c5dae9d2bab770c93646b3edb4a707775f111fec5784bbc02e0977ea160fa0e16508b6e48d767dfbf3cf9c57102e8
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -578294d2b3d43ffd19b79a65778710da245eb96fda50d50a3aa6ae3295dc50d8f7da1f5c8b98f4a9905ee840dcd139a62697eb45678259d7639ff
+B = -f6446ca2883805fdd373ad5c200dab2289329459ee7a2f997764cdf519d3d32d5bbafb94464ac83d1dca566cf67e3194ef44bc8a4e7a38f81eb7eb4044787614
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = ab192cde88b1cb3e6b094409c1e81ff84715d64ddb7413f6fc5dc1182abfcaca481c8035d16e0d698476d7094f2bf7cb3de1b1210ba68701168a3
+B = f6446ca28832cc9452b65f836bf89607eeedee48fc980427a984bbc12b07b7bc2d61ad5ca735c4171035f91b6a7ef01602bd96de6c28c45bc0fda8fd71dd4770
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -19a7abdefad11d1c9b6c4e0c4c1ff1194c490f63086ede1e4c43d964555a2f5e561a9bf5dc3a670b7ddfe8894271197747860c78949e6c9e357460
+B = f6446ca2885725d2ff99bbbd3c7ab2ea3bd62cbc1568be94716ae1e088c3c171a339b388b230607b096f4a634c95176bfc94fab7602428834ba301d280242473
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = 275ce169251250a596ac64ac6e23ae05f8785db63b9cb83a9dec067472d059ea3aef07cf9fc20b846b3292899a8d3fe1aed5b92f21a89c1d924bbd
+B = -f6446ca28864db0889c3fcf0c575f300dbf830790214ede2c49e0fbaa515699eb35729b33e1534e6e332d207c5826a15fced16ddca8b783002300c01ff80fbd0
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -61039a571c78308b819da54c1849d8d6169a82e25f61f26e30ab16b545080417f2008ef89116e002660f95863c47ac02bc161bbb7aa8817457eade
+B = -f6446ca287dc7a8cc982726f945da8f6e371c2f22605db022c03110ffc46d281899f51553be845501b01f91c3eb127eded1641f1e6208c5b1793bae46d96c535
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = fca0b32bf9e248320b8c10128ff4368a766dd34fbfbf77e66cb2298fa3833bbf24451f508a50afd0131ad49c9ac8e851d4fb53f2fe33675f5e6b34
+B = f6446ca28740dd73f4a50857edd3ba8c1cfa189471a607b1bea2b38a840acb6eaf40d61d94b600bfc308bf4c71041caed6b7c0b59707a722e0102ffe829044df
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -1c6f81990e54d6894188d5b872009c3eb5b2f10137bf7a27999d918790b587594afab3950330296979c354851164f95938d1df77995f6c0a9a3edef
+B = f6446ca28a047640b1843808b3f7d3f7b6aa168ee777a49521de6aa4e41156b0b7efb1cee889f11863c61292d8b36ccbc468d9337c69c06e4ca45a268b929e02
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = 310b6086b85bf12c7e391184e070f623c9cfe07a8e495010fc13d584d748098f070ac4b7c31cbd28acd32ab6270e2a98f48d8d31525ada808858785
+B = -f6446ca28b4e342f8c24a9b2e7c2d7b47d911c2d38b9738cb74708037a38baf08c58d9f2444af22a8fc4dbcecbe46a2ed5c36c4778257b49e834110dea743798
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -4a51109cf8c033e683b1bff229f081d71cd5cafde15dc2d5f8ad0457e79b9b2e015659ee564de59f27204c685ef58977e13e19fe36a2d017fe6860b
+B = -f6446ca283986d1d5112e761b7a42a9d0ceb04ad8a4f18d5304c96d50aecad52c06a9fa673c4e0402e2e31a24ea532bced6331066ac8c0d6efa4366462082a08
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = f3e425af6aa16899624f20b49c4e9115034aa4d06ce9db9aa742a6e60d59d6ce0a067f5645b8e7f896c8561315ef1f7151e073d115f8e38df274438
+B = f6446ca278ff3bcc29f4d41689ba5490e5c523b9abe7cb380793d548c0035329de0ebbec7339dde9af37817cb7aab22241f397a6d3be9b39c1aed52d02c76bdb
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -18b2de417fc4bef91b5dd82b0e93315b306bf3a7f7bf0a486a567e9cd1370587b7e47adcb9accba03a8dfda5871b0bb1bdb569a90c079f7a9a4e87d2
+B = f6446ca2a0f05c68a063a9993b3d1ec73e1d3e262c88692d06217d4ad4cdfc35101b5ee10bbec0bbcd3fdb9c7ba53528fa6d954fa6920c1fdf1602e07c3d37e5
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = 26b556807e84a9bf7cdf2697050cbd7145a42b8ef6fe10666da7a2e69827ad04880bb97ab3108a27da5fcc29a041bd6aebbaf00ab25a841674ff9f1e
+B = -f6446ca2aef2d4a79f23945f9cbe6d333496ca3c41c0a11405608368d81f207ed70c065ddbe5ff59c6a39a241b7703ad13944708d49792818568e77c56ee4f31
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -40b258c2211cc2cb9e2614ab4b23cb9eadb1ddcae903c93646e9f5e5afcaf912a2fdef26c864d83dcdd6f434ca2b0aa7f8ea7a21e790a9e4601de110
+B = -f6446ca2478b2564ff8227d481b931f0e466412c4e6a97ba255ea9cc238d87b28f196046b0dc56b84b2e37be7340434ea9277ef5eff22854eb7db98181d0cf03
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = 97631efbd149bb0fdecce09d14aedf2efe30407c01c68e000be9c7be954999375e1f7720e8e5f1edfc48b92f9a063f6b2b378996459bffeae3d362e3
+B = f6446ca1f0da5f2b4f552f90411265ff1adb2d9bfdec35090c9be5025e8db5d9a99ac021f5bacebe2aad1e0e44ce7e53d94c4a32bda518e08d72637afe1b4d30
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -15f4c3634bbbd1ce04fdf96a69b2b8263290e188ca83956b74c6d190e7b877dbd176657a19ea125dfe9c95d2764002ca5d98e28315cb391779d56fcb2
+B = f6446ca3e789b45bdc5c07806fbedd42cab58f2e252a8e11b69bc9b9b6e496a6ba6bd7166b409d80b23435dc2ae094aad752b643c26acaa82fc1f4dd7f45acc5
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = 39ecc3b285eb99a2ac91329da615e581f791eaebd477d87c7739dd961a2c5c6cf86a34c73856efcf3b812909d830186c910f8f053192cac9fca8ab7a3
+B = -f6446ca62709b94f7f5884cae8f2707690e864ea753b244255dffac9de1556f9e1aa2028da7d925299020ceff929c820f6541066f9d592c9ec3b1005ac7967b6
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -707e64f8bee7a679d9b72bd04b231cda716f5dc1b7a404f8c0679770c46fc944470ee2a221d1e3d166619ba6a430d0349e7e75c0ee021ed027dab5d74
+B = -f6446c9b80572e9b32248302846c89977d583f23e52699699422237663fe068bf7e7c514e2ec1bbcf674d2e5dafd7d193045865400f54667f2ec76636443529f
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = 9ca2c37f4b1a392c34551f570ff06a74c5f027170815454c5ed3535d5232df54fb1f65f2304e32b4995bb77ccd4ece69db98452f182dbeda98d525a19
+B = f6446c98be1146326efb57dcda8d512b3083657e9d1a04148d0e1e3c7d4247c31bb66409a1e3e6bc0eafe4b2ab5bbfb69e65a3002f584f85503275bc549c55fa
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -1190fea35b9a1ba1c280d57888664aa7db5f9d6d4325b35a6276bf61291d67e6e14e3001f5af1753faff61fa53861ab8ed15d15965e0dcb05718bdecc6
+B = f6446cb4193c2182baba8c62a0b4bf2495d4b4a65bb9e2c83415cd64e136dec15c4c403aa20a47d4c2aa63f7407931d6f96d428afeadfbdcb3eb13bcfaac9cd9
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = 209797b717f068e5f808dd2b4e12576fa056879da881bfcc1819228e4f9dc6f84347edbdbe273657d533d7c928e51b68a82c59d93dfb038514c104c1bc
+B = -f6446cc31fd5353f1107d09828bc71ea41e17c6b52a4132d90223f1a839a0be7dcab519c9bc8039d3ac967d174ef00ac586df24615367bb4ce11e87aa2f371cf
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -7198b6aa26be42e97cad682aaa63d68d51952dae52d4cfe5f9a6acef93f35b6d7b7be87a1f2a944cf7fa9483cd6c3df7599d44c5b56e5ff38cd43d23c0
+B = -f6446c30ef86d400625c012372771bf1cbb37f7966eec73239928d08c3ca8e044b88ebddd7f1cbbfe8fec3044682b3b6071492444b97dcc164ae6fd90db18c53
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = cb788549eee4fa559118f0bd66b68d94845bdb7d07b2042d53a64921f3e3df76a2b143e9e9ad39dacaf405cec5fed9fd59050c5d27322142e4e11d4ede
+B = f6446bd70fb834383ba4950f06ee893578fc7846a040f87d5c5e45aec42e5ba45b04e2b6a2965bf5665935314d1168bd74788c44e3d0454fa0ed208100d16135
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -1122c39c2c252ec96e9274bdf713bfa8200e35ed9f18dd087fedd2005e5898b6f8ed37e1cd7e1f7b0c5be137a71a27b7e4e4669b1f412e154e6ad2ad567
+B = f6446db4b47740e9738b8189472b260d6b848ecbdf7b4f769c32fb014797837dc86fc8e8275862b6f58ac0c1ff2ab1f515ce07ec2f46546ae5efb84c8f19857a
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = 2d57e15c8039f8367d2e0198d9fc27616e53efdc9cb0adc0b0199362d08f5698af1f07499cd2b72005f1c09900c71b677e57cd62094743a9b3ae541e74d
+B = -f6446f780653462ac0225272fff8d43bf20023b03b1a3f50193e7e0403adaaa1344de44b444edfac3f05105b5d20c78fe509018365b2c30b4748fea0c7309760
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -539b4413477ef77c15fd53e202d8e5d183eb1c91fecf5b89959bb8d60d3f7907e95c5dd045d698a6a17f0150861b43bfeb2e5d40bdc970839b0712ee17f
+B = -f6446768d3fc49af312729404aa1266ea12cf48c4a53559818a9d9a8aeea1cc44753dac38dfd4181aa08a5e451022f21bf168aeb0308969a3c0629b570bfce94
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = fe46dc4f55346ee27d6ced0256b0ec64f82d5150c3b49d4cc7d56a60ae5d10bb649a57f4c97acc146388a6a9d25d3c3c7e42372e46bb4f8a72171ea5979
+B = f6445cbe1a7888d3d9b0c2c9510f213120c3bd4827076949c48da68513d172b26dd8a30fae5af94766d1c9c3b6ac9a5d9f8ec1b9c569be0b1e15bc447004569a
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -1fbd702bd26d37bb1fa554ad261f1e7161ea438f49b41aab950884c5c87eb1e0b9a3a69807b759a1440ef9e5683c1a13b9d610fd87fb131619cb63997891
+B = f6448c5ff8695094585a0a45748c6cbb4dfb6eb53fabbf39290e080aef3d4616f0c512fcfa724d966d34540b3afc9fbf8d664373f9da2a71e6247d31458828a4
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = 260abc8cb124b3c17698ee342bdbe4b1513a085effb4f79aca252c98c8799ad203dccc9c305cdccd2edc16159d0e2c7a125c50f8abff9e12dbe8d93c655d
+B = -f64492ad44ca2f4bd46061390e137278143b5e05047b753a05fd3d2797104611d9b65d362076763bf0603ed8572cd4919fcc9bfa39d54e7671213f4ebb2b1570
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -6f961198d2039a92d24c53bfcafd73251b575d5e06565db36666545d5994e511c4c3905cc0b93586f05916c08b8f51a0e0fe1b6253fcfa41bfec25196482
+B = -f643fd0c76a4ac23860c1853cc1f7b9ebc64f1739ebe6f2eb0af0c9c161a240359d29495c37d8525de0c1fa32a56abf421b1a89fcd7a4e79d8cca379bcd54b91
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = ed86313f32aabf2f7487dd9f587431e17b9a46e1a78fe89b0ebe81c737a73c2a8fef92c0963fc36e9808309d00c3bd14612fdf4fb236e06add8fe9329252
+B = f6437f1c56fe4b7c616f7618423fee27fda89130b53acdf525c76443e8b045f102b9c969c119af9f502477f4107a36bfb63e286e098cf03ff2a385d5f8bc1dc1
+
+Sum = f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -1741bce7ae27a7b3effa5b08b39f9d03d69efe7b0716cc57dc106aac17925a2d77c18386f7398db17f813c9c6f2dfcc9347e9f55de76b11475fcf77bbedb1
+B = f645e0be56b860a19bddea45d06a8095ffc776bae3cce6f1d3e034091538f6bde1bbd5718c49b977eeab08100ade2a633fe5d187de3a89e1e455c33559aa9dc4
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = 20bd41a0d6d691e8554ee8b90a775e04f086f318b7afdc7b5d6d7c3b7ab6b955aa286809856e1bd195dace84b18b2d0365edc8e066d2e8db9ae8325d00843
+B = -f6467876a24aeb903f243f8eab6fee120fd9153a2da7f082d61849da2e2f2903d43efbdfd4729cc0d0ac6da9296250364388e87a76e30fa560c811e907beb856
+
+Sum = -f6446ca2883d7e27209eeaa01fdf469c2f8a0ccafc1c75850e6273026a777d983ee4595953da45df13930ffc411737837352899de8dca276d30e6365e1eeb013
+A = -685147a1e74dab824bc6cb7fb30a773fbe5e380f46189574038d2d2f3983ced8777a080af6b06e9bb3c2d134a3302fa099b4bc78a4f01a4c157424ee3c773
+B = -f63de78e0e1f094c687a2e3367e415f4bb8e26e77b2813fbb7223a2f9783e55b515ce1b8d32adad829d7d3cf2dcd04807948ee52215253752e4d0c23930ae8a0
+
+Sum = 1
+A = 0
+B = 1
+
+Sum = 2
+A = 1
+B = 1
+
+Sum = 4
+A = 3
+B = 1
+
+Sum = 8
+A = 7
+B = 1
+
+Sum = 10
+A = f
+B = 1
+
+Sum = 20
+A = 1f
+B = 1
+
+Sum = 40
+A = 3f
+B = 1
+
+Sum = 80
+A = 7f
+B = 1
+
+Sum = 100
+A = ff
+B = 1
+
+Sum = 200
+A = 1ff
+B = 1
+
+Sum = 400
+A = 3ff
+B = 1
+
+Sum = 800
+A = 7ff
+B = 1
+
+Sum = 1000
+A = fff
+B = 1
+
+Sum = 2000
+A = 1fff
+B = 1
+
+Sum = 4000
+A = 3fff
+B = 1
+
+Sum = 8000
+A = 7fff
+B = 1
+
+Sum = 10000
+A = ffff
+B = 1
+
+Sum = 20000
+A = 1ffff
+B = 1
+
+Sum = 40000
+A = 3ffff
+B = 1
+
+Sum = 80000
+A = 7ffff
+B = 1
+
+Sum = 100000
+A = fffff
+B = 1
+
+Sum = 200000
+A = 1fffff
+B = 1
+
+Sum = 400000
+A = 3fffff
+B = 1
+
+Sum = 800000
+A = 7fffff
+B = 1
+
+Sum = 1000000
+A = ffffff
+B = 1
+
+Sum = 2000000
+A = 1ffffff
+B = 1
+
+Sum = 4000000
+A = 3ffffff
+B = 1
+
+Sum = 8000000
+A = 7ffffff
+B = 1
+
+Sum = 10000000
+A = fffffff
+B = 1
+
+Sum = 20000000
+A = 1fffffff
+B = 1
+
+Sum = 40000000
+A = 3fffffff
+B = 1
+
+Sum = 80000000
+A = 7fffffff
+B = 1
+
+Sum = 100000000
+A = ffffffff
+B = 1
+
+Sum = 200000000
+A = 1ffffffff
+B = 1
+
+Sum = 400000000
+A = 3ffffffff
+B = 1
+
+Sum = 800000000
+A = 7ffffffff
+B = 1
+
+Sum = 1000000000
+A = fffffffff
+B = 1
+
+Sum = 2000000000
+A = 1fffffffff
+B = 1
+
+Sum = 4000000000
+A = 3fffffffff
+B = 1
+
+Sum = 8000000000
+A = 7fffffffff
+B = 1
+
+Sum = 10000000000
+A = ffffffffff
+B = 1
+
+Sum = 20000000000
+A = 1ffffffffff
+B = 1
+
+Sum = 40000000000
+A = 3ffffffffff
+B = 1
+
+Sum = 80000000000
+A = 7ffffffffff
+B = 1
+
+Sum = 100000000000
+A = fffffffffff
+B = 1
+
+Sum = 200000000000
+A = 1fffffffffff
+B = 1
+
+Sum = 400000000000
+A = 3fffffffffff
+B = 1
+
+Sum = 800000000000
+A = 7fffffffffff
+B = 1
+
+Sum = 1000000000000
+A = ffffffffffff
+B = 1
+
+Sum = 2000000000000
+A = 1ffffffffffff
+B = 1
+
+Sum = 4000000000000
+A = 3ffffffffffff
+B = 1
+
+Sum = 8000000000000
+A = 7ffffffffffff
+B = 1
+
+Sum = 10000000000000
+A = fffffffffffff
+B = 1
+
+Sum = 20000000000000
+A = 1fffffffffffff
+B = 1
+
+Sum = 40000000000000
+A = 3fffffffffffff
+B = 1
+
+Sum = 80000000000000
+A = 7fffffffffffff
+B = 1
+
+Sum = 100000000000000
+A = ffffffffffffff
+B = 1
+
+Sum = 200000000000000
+A = 1ffffffffffffff
+B = 1
+
+Sum = 400000000000000
+A = 3ffffffffffffff
+B = 1
+
+Sum = 800000000000000
+A = 7ffffffffffffff
+B = 1
+
+Sum = 1000000000000000
+A = fffffffffffffff
+B = 1
+
+Sum = 2000000000000000
+A = 1fffffffffffffff
+B = 1
+
+Sum = 4000000000000000
+A = 3fffffffffffffff
+B = 1
+
+Sum = 8000000000000000
+A = 7fffffffffffffff
+B = 1
+
+Sum = 10000000000000000
+A = ffffffffffffffff
+B = 1
+
+Sum = 20000000000000000
+A = 1ffffffffffffffff
+B = 1
+
+Sum = 40000000000000000
+A = 3ffffffffffffffff
+B = 1
+
+Sum = 80000000000000000
+A = 7ffffffffffffffff
+B = 1
+
+Sum = 100000000000000000
+A = fffffffffffffffff
+B = 1
+
+Sum = 200000000000000000
+A = 1fffffffffffffffff
+B = 1
+
+Sum = 400000000000000000
+A = 3fffffffffffffffff
+B = 1
+
+Sum = 800000000000000000
+A = 7fffffffffffffffff
+B = 1
+
+Sum = 1000000000000000000
+A = ffffffffffffffffff
+B = 1
+
+Sum = 2000000000000000000
+A = 1ffffffffffffffffff
+B = 1
+
+Sum = 4000000000000000000
+A = 3ffffffffffffffffff
+B = 1
+
+Sum = 8000000000000000000
+A = 7ffffffffffffffffff
+B = 1
+
+Sum = 10000000000000000000
+A = fffffffffffffffffff
+B = 1
+
+Sum = 20000000000000000000
+A = 1fffffffffffffffffff
+B = 1
+
+Sum = 40000000000000000000
+A = 3fffffffffffffffffff
+B = 1
+
+Sum = 80000000000000000000
+A = 7fffffffffffffffffff
+B = 1
+
+Sum = 100000000000000000000
+A = ffffffffffffffffffff
+B = 1
+
+Sum = 200000000000000000000
+A = 1ffffffffffffffffffff
+B = 1
+
+Sum = 400000000000000000000
+A = 3ffffffffffffffffffff
+B = 1
+
+Sum = 800000000000000000000
+A = 7ffffffffffffffffffff
+B = 1
+
+Sum = 1000000000000000000000
+A = fffffffffffffffffffff
+B = 1
+
+Sum = 2000000000000000000000
+A = 1fffffffffffffffffffff
+B = 1
+
+Sum = 4000000000000000000000
+A = 3fffffffffffffffffffff
+B = 1
+
+Sum = 8000000000000000000000
+A = 7fffffffffffffffffffff
+B = 1
+
+Sum = 10000000000000000000000
+A = ffffffffffffffffffffff
+B = 1
+
+Sum = 20000000000000000000000
+A = 1ffffffffffffffffffffff
+B = 1
+
+Sum = 40000000000000000000000
+A = 3ffffffffffffffffffffff
+B = 1
+
+Sum = 80000000000000000000000
+A = 7ffffffffffffffffffffff
+B = 1
+
+Sum = 100000000000000000000000
+A = fffffffffffffffffffffff
+B = 1
+
+Sum = 200000000000000000000000
+A = 1fffffffffffffffffffffff
+B = 1
+
+Sum = 400000000000000000000000
+A = 3fffffffffffffffffffffff
+B = 1
+
+Sum = 800000000000000000000000
+A = 7fffffffffffffffffffffff
+B = 1
+
+Sum = 1000000000000000000000000
+A = ffffffffffffffffffffffff
+B = 1
+
+Sum = 2000000000000000000000000
+A = 1ffffffffffffffffffffffff
+B = 1
+
+Sum = 4000000000000000000000000
+A = 3ffffffffffffffffffffffff
+B = 1
+
+Sum = 8000000000000000000000000
+A = 7ffffffffffffffffffffffff
+B = 1
+
+Sum = 10000000000000000000000000
+A = fffffffffffffffffffffffff
+B = 1
+
+Sum = 20000000000000000000000000
+A = 1fffffffffffffffffffffffff
+B = 1
+
+Sum = 40000000000000000000000000
+A = 3fffffffffffffffffffffffff
+B = 1
+
+Sum = 80000000000000000000000000
+A = 7fffffffffffffffffffffffff
+B = 1
+
+Sum = 100000000000000000000000000
+A = ffffffffffffffffffffffffff
+B = 1
+
+Sum = 200000000000000000000000000
+A = 1ffffffffffffffffffffffffff
+B = 1
+
+Sum = 400000000000000000000000000
+A = 3ffffffffffffffffffffffffff
+B = 1
+
+Sum = 800000000000000000000000000
+A = 7ffffffffffffffffffffffffff
+B = 1
+
+Sum = 1000000000000000000000000000
+A = fffffffffffffffffffffffffff
+B = 1
+
+Sum = 2000000000000000000000000000
+A = 1fffffffffffffffffffffffffff
+B = 1
+
+Sum = 4000000000000000000000000000
+A = 3fffffffffffffffffffffffffff
+B = 1
+
+Sum = 8000000000000000000000000000
+A = 7fffffffffffffffffffffffffff
+B = 1
+
+Sum = 10000000000000000000000000000
+A = ffffffffffffffffffffffffffff
+B = 1
+
+Sum = 20000000000000000000000000000
+A = 1ffffffffffffffffffffffffffff
+B = 1
+
+Sum = 40000000000000000000000000000
+A = 3ffffffffffffffffffffffffffff
+B = 1
+
+Sum = 80000000000000000000000000000
+A = 7ffffffffffffffffffffffffffff
+B = 1
+
+Sum = 100000000000000000000000000000
+A = fffffffffffffffffffffffffffff
+B = 1
+
+Sum = 200000000000000000000000000000
+A = 1fffffffffffffffffffffffffffff
+B = 1
+
+Sum = 400000000000000000000000000000
+A = 3fffffffffffffffffffffffffffff
+B = 1
+
+Sum = 800000000000000000000000000000
+A = 7fffffffffffffffffffffffffffff
+B = 1
+
+Sum = 1000000000000000000000000000000
+A = ffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 2000000000000000000000000000000
+A = 1ffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 4000000000000000000000000000000
+A = 3ffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 8000000000000000000000000000000
+A = 7ffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 10000000000000000000000000000000
+A = fffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 20000000000000000000000000000000
+A = 1fffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 40000000000000000000000000000000
+A = 3fffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 80000000000000000000000000000000
+A = 7fffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 100000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 200000000000000000000000000000000
+A = 1ffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 400000000000000000000000000000000
+A = 3ffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 800000000000000000000000000000000
+A = 7ffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 1000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 2000000000000000000000000000000000
+A = 1fffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 4000000000000000000000000000000000
+A = 3fffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 8000000000000000000000000000000000
+A = 7fffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 10000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 20000000000000000000000000000000000
+A = 1ffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 40000000000000000000000000000000000
+A = 3ffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 80000000000000000000000000000000000
+A = 7ffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 100000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 200000000000000000000000000000000000
+A = 1fffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 400000000000000000000000000000000000
+A = 3fffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 800000000000000000000000000000000000
+A = 7fffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 1000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 2000000000000000000000000000000000000
+A = 1ffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 4000000000000000000000000000000000000
+A = 3ffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 8000000000000000000000000000000000000
+A = 7ffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 10000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 20000000000000000000000000000000000000
+A = 1fffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 40000000000000000000000000000000000000
+A = 3fffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 80000000000000000000000000000000000000
+A = 7fffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 100000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 200000000000000000000000000000000000000
+A = 1ffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 400000000000000000000000000000000000000
+A = 3ffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 800000000000000000000000000000000000000
+A = 7ffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 1000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 2000000000000000000000000000000000000000
+A = 1fffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 4000000000000000000000000000000000000000
+A = 3fffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 8000000000000000000000000000000000000000
+A = 7fffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 10000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 20000000000000000000000000000000000000000
+A = 1ffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 40000000000000000000000000000000000000000
+A = 3ffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 80000000000000000000000000000000000000000
+A = 7ffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 100000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 200000000000000000000000000000000000000000
+A = 1fffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 400000000000000000000000000000000000000000
+A = 3fffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 800000000000000000000000000000000000000000
+A = 7fffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 1000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 2000000000000000000000000000000000000000000
+A = 1ffffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 4000000000000000000000000000000000000000000
+A = 3ffffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 8000000000000000000000000000000000000000000
+A = 7ffffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 10000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 20000000000000000000000000000000000000000000
+A = 1fffffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 40000000000000000000000000000000000000000000
+A = 3fffffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 80000000000000000000000000000000000000000000
+A = 7fffffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 100000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 200000000000000000000000000000000000000000000
+A = 1ffffffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 400000000000000000000000000000000000000000000
+A = 3ffffffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 800000000000000000000000000000000000000000000
+A = 7ffffffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 1000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 2000000000000000000000000000000000000000000000
+A = 1fffffffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 4000000000000000000000000000000000000000000000
+A = 3fffffffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 8000000000000000000000000000000000000000000000
+A = 7fffffffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 10000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 20000000000000000000000000000000000000000000000
+A = 1ffffffffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 40000000000000000000000000000000000000000000000
+A = 3ffffffffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 80000000000000000000000000000000000000000000000
+A = 7ffffffffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 100000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 200000000000000000000000000000000000000000000000
+A = 1fffffffffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 400000000000000000000000000000000000000000000000
+A = 3fffffffffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 800000000000000000000000000000000000000000000000
+A = 7fffffffffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 1000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 2000000000000000000000000000000000000000000000000
+A = 1ffffffffffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 4000000000000000000000000000000000000000000000000
+A = 3ffffffffffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 8000000000000000000000000000000000000000000000000
+A = 7ffffffffffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 10000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 20000000000000000000000000000000000000000000000000
+A = 1fffffffffffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 40000000000000000000000000000000000000000000000000
+A = 3fffffffffffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 80000000000000000000000000000000000000000000000000
+A = 7fffffffffffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffffffffffffffffff
+B = 1
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffffffffffffffffe
+B = 2
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffffffffffffffffc
+B = 4
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffffffffffffffff8
+B = 8
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffffffffffffffff0
+B = 10
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffffffffffffffffe0
+B = 20
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffffffffffffffffc0
+B = 40
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffffffffffffffff80
+B = 80
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffffffffffffffff00
+B = 100
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffffffffffffffe00
+B = 200
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffffffffffffffc00
+B = 400
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffffffffffffff800
+B = 800
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffffffffffffff000
+B = 1000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffffffffffffffe000
+B = 2000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffffffffffffffc000
+B = 4000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffffffffffffff8000
+B = 8000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffffffffffffff0000
+B = 10000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffffffffffffe0000
+B = 20000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffffffffffffc0000
+B = 40000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffffffffffff80000
+B = 80000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffffffffffff00000
+B = 100000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffffffffffffe00000
+B = 200000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffffffffffffc00000
+B = 400000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffffffffffff800000
+B = 800000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffffffffffff000000
+B = 1000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffffffffffe000000
+B = 2000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffffffffffc000000
+B = 4000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffffffffff8000000
+B = 8000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffffffffff0000000
+B = 10000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffffffffffe0000000
+B = 20000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffffffffffc0000000
+B = 40000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffffffffff80000000
+B = 80000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffffffffff00000000
+B = 100000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffffffffe00000000
+B = 200000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffffffffc00000000
+B = 400000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffffffff800000000
+B = 800000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffffffff000000000
+B = 1000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffffffffe000000000
+B = 2000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffffffffc000000000
+B = 4000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffffffff8000000000
+B = 8000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffffffff0000000000
+B = 10000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffffffe0000000000
+B = 20000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffffffc0000000000
+B = 40000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffffff80000000000
+B = 80000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffffff00000000000
+B = 100000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffffffe00000000000
+B = 200000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffffffc00000000000
+B = 400000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffffff800000000000
+B = 800000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffffff000000000000
+B = 1000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffffe000000000000
+B = 2000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffffc000000000000
+B = 4000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffff8000000000000
+B = 8000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffff0000000000000
+B = 10000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffffe0000000000000
+B = 20000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffffc0000000000000
+B = 40000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffff80000000000000
+B = 80000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffff00000000000000
+B = 100000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffe00000000000000
+B = 200000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffffc00000000000000
+B = 400000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffff800000000000000
+B = 800000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffff000000000000000
+B = 1000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffe000000000000000
+B = 2000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffffc000000000000000
+B = 4000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffff8000000000000000
+B = 8000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffff0000000000000000
+B = 10000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffe0000000000000000
+B = 20000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffffc0000000000000000
+B = 40000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffff80000000000000000
+B = 80000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffff00000000000000000
+B = 100000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffe00000000000000000
+B = 200000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffffc00000000000000000
+B = 400000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffff800000000000000000
+B = 800000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffff000000000000000000
+B = 1000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffe000000000000000000
+B = 2000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffffc000000000000000000
+B = 4000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffff8000000000000000000
+B = 8000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffff0000000000000000000
+B = 10000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffe0000000000000000000
+B = 20000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffffc0000000000000000000
+B = 40000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffff80000000000000000000
+B = 80000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffff00000000000000000000
+B = 100000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffe00000000000000000000
+B = 200000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffffc00000000000000000000
+B = 400000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffff800000000000000000000
+B = 800000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffff000000000000000000000
+B = 1000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffe000000000000000000000
+B = 2000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffffc000000000000000000000
+B = 4000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffff8000000000000000000000
+B = 8000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffff0000000000000000000000
+B = 10000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffe0000000000000000000000
+B = 20000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffffc0000000000000000000000
+B = 40000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffff80000000000000000000000
+B = 80000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffff00000000000000000000000
+B = 100000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffe00000000000000000000000
+B = 200000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffffc00000000000000000000000
+B = 400000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffff800000000000000000000000
+B = 800000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffff000000000000000000000000
+B = 1000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffe000000000000000000000000
+B = 2000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffffc000000000000000000000000
+B = 4000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffff8000000000000000000000000
+B = 8000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffff0000000000000000000000000
+B = 10000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffe0000000000000000000000000
+B = 20000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffffc0000000000000000000000000
+B = 40000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffff80000000000000000000000000
+B = 80000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffff00000000000000000000000000
+B = 100000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffe00000000000000000000000000
+B = 200000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffffc00000000000000000000000000
+B = 400000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffff800000000000000000000000000
+B = 800000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffff000000000000000000000000000
+B = 1000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffe000000000000000000000000000
+B = 2000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffffc000000000000000000000000000
+B = 4000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffff8000000000000000000000000000
+B = 8000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffff0000000000000000000000000000
+B = 10000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffe0000000000000000000000000000
+B = 20000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffffc0000000000000000000000000000
+B = 40000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffff80000000000000000000000000000
+B = 80000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffff00000000000000000000000000000
+B = 100000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffe00000000000000000000000000000
+B = 200000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffffc00000000000000000000000000000
+B = 400000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffff800000000000000000000000000000
+B = 800000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffff000000000000000000000000000000
+B = 1000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffe000000000000000000000000000000
+B = 2000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffffc000000000000000000000000000000
+B = 4000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffff8000000000000000000000000000000
+B = 8000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffff0000000000000000000000000000000
+B = 10000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffe0000000000000000000000000000000
+B = 20000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffffc0000000000000000000000000000000
+B = 40000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffff80000000000000000000000000000000
+B = 80000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffff00000000000000000000000000000000
+B = 100000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffe00000000000000000000000000000000
+B = 200000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffffc00000000000000000000000000000000
+B = 400000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffff800000000000000000000000000000000
+B = 800000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffff000000000000000000000000000000000
+B = 1000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffe000000000000000000000000000000000
+B = 2000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffffc000000000000000000000000000000000
+B = 4000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffff8000000000000000000000000000000000
+B = 8000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffff0000000000000000000000000000000000
+B = 10000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffe0000000000000000000000000000000000
+B = 20000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffffc0000000000000000000000000000000000
+B = 40000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffff80000000000000000000000000000000000
+B = 80000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffff00000000000000000000000000000000000
+B = 100000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffe00000000000000000000000000000000000
+B = 200000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffffc00000000000000000000000000000000000
+B = 400000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffff800000000000000000000000000000000000
+B = 800000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffff000000000000000000000000000000000000
+B = 1000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffe000000000000000000000000000000000000
+B = 2000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffffc000000000000000000000000000000000000
+B = 4000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffff8000000000000000000000000000000000000
+B = 8000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffff0000000000000000000000000000000000000
+B = 10000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffe0000000000000000000000000000000000000
+B = 20000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffffc0000000000000000000000000000000000000
+B = 40000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffff80000000000000000000000000000000000000
+B = 80000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffff00000000000000000000000000000000000000
+B = 100000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffe00000000000000000000000000000000000000
+B = 200000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffffc00000000000000000000000000000000000000
+B = 400000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffff800000000000000000000000000000000000000
+B = 800000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffff000000000000000000000000000000000000000
+B = 1000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffe000000000000000000000000000000000000000
+B = 2000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffffc000000000000000000000000000000000000000
+B = 4000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffff8000000000000000000000000000000000000000
+B = 8000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffff0000000000000000000000000000000000000000
+B = 10000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffe0000000000000000000000000000000000000000
+B = 20000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffffc0000000000000000000000000000000000000000
+B = 40000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffff80000000000000000000000000000000000000000
+B = 80000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffff00000000000000000000000000000000000000000
+B = 100000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffe00000000000000000000000000000000000000000
+B = 200000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffffc00000000000000000000000000000000000000000
+B = 400000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffff800000000000000000000000000000000000000000
+B = 800000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffff000000000000000000000000000000000000000000
+B = 1000000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffe000000000000000000000000000000000000000000
+B = 2000000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffffc000000000000000000000000000000000000000000
+B = 4000000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffff8000000000000000000000000000000000000000000
+B = 8000000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffff0000000000000000000000000000000000000000000
+B = 10000000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffe0000000000000000000000000000000000000000000
+B = 20000000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffffc0000000000000000000000000000000000000000000
+B = 40000000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffff80000000000000000000000000000000000000000000
+B = 80000000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffff00000000000000000000000000000000000000000000
+B = 100000000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffe00000000000000000000000000000000000000000000
+B = 200000000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffffc00000000000000000000000000000000000000000000
+B = 400000000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffff800000000000000000000000000000000000000000000
+B = 800000000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffff000000000000000000000000000000000000000000000
+B = 1000000000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffe000000000000000000000000000000000000000000000
+B = 2000000000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffffc000000000000000000000000000000000000000000000
+B = 4000000000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffff8000000000000000000000000000000000000000000000
+B = 8000000000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffff0000000000000000000000000000000000000000000000
+B = 10000000000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffe0000000000000000000000000000000000000000000000
+B = 20000000000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fffc0000000000000000000000000000000000000000000000
+B = 40000000000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fff80000000000000000000000000000000000000000000000
+B = 80000000000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fff00000000000000000000000000000000000000000000000
+B = 100000000000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffe00000000000000000000000000000000000000000000000
+B = 200000000000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ffc00000000000000000000000000000000000000000000000
+B = 400000000000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ff800000000000000000000000000000000000000000000000
+B = 800000000000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = ff000000000000000000000000000000000000000000000000
+B = 1000000000000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fe000000000000000000000000000000000000000000000000
+B = 2000000000000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = fc000000000000000000000000000000000000000000000000
+B = 4000000000000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = f8000000000000000000000000000000000000000000000000
+B = 8000000000000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = f0000000000000000000000000000000000000000000000000
+B = 10000000000000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = e0000000000000000000000000000000000000000000000000
+B = 20000000000000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = c0000000000000000000000000000000000000000000000000
+B = 40000000000000000000000000000000000000000000000000
+
+Sum = 100000000000000000000000000000000000000000000000000
+A = 80000000000000000000000000000000000000000000000000
+B = 80000000000000000000000000000000000000000000000000
+
+
+# LShift1 tests.
+#
+# These test vectors satisfy A * 2 = LShift1
+
+LShift1 = 0
+A = 0
+
+LShift1 = 13116120bca5df64e13f314254
+A = 988b0905e52efb2709f98a12a
+
+LShift1 = -13116120bca5df64e13f314254
+A = -988b0905e52efb2709f98a12a
+
+LShift1 = 2622c241794bbec9c27e6284a8
+A = 13116120bca5df64e13f314254
+
+LShift1 = -2622c241794bbec9c27e6284a8
+A = -13116120bca5df64e13f314254
+
+LShift1 = 4c458482f2977d9384fcc50950
+A = 2622c241794bbec9c27e6284a8
+
+LShift1 = -4c458482f2977d9384fcc50950
+A = -2622c241794bbec9c27e6284a8
+
+LShift1 = 988b0905e52efb2709f98a12a2
+A = 4c458482f2977d9384fcc50951
+
+LShift1 = -988b0905e52efb2709f98a12a2
+A = -4c458482f2977d9384fcc50951
+
+LShift1 = 13116120bca5df64e13f3142544
+A = 988b0905e52efb2709f98a12a2
+
+LShift1 = -13116120bca5df64e13f3142544
+A = -988b0905e52efb2709f98a12a2
+
+LShift1 = 2622c241794bbec9c27e6284a8a
+A = 13116120bca5df64e13f3142545
+
+LShift1 = -2622c241794bbec9c27e6284a8a
+A = -13116120bca5df64e13f3142545
+
+LShift1 = 4c458482f2977d9384fcc509514
+A = 2622c241794bbec9c27e6284a8a
+
+LShift1 = -4c458482f2977d9384fcc509514
+A = -2622c241794bbec9c27e6284a8a
+
+LShift1 = 988b0905e52efb2709f98a12a28
+A = 4c458482f2977d9384fcc509514
+
+LShift1 = -988b0905e52efb2709f98a12a28
+A = -4c458482f2977d9384fcc509514
+
+LShift1 = 13116120bca5df64e13f31425450
+A = 988b0905e52efb2709f98a12a28
+
+LShift1 = -13116120bca5df64e13f31425450
+A = -988b0905e52efb2709f98a12a28
+
+LShift1 = 2622c241794bbec9c27e6284a8a0
+A = 13116120bca5df64e13f31425450
+
+LShift1 = -2622c241794bbec9c27e6284a8a0
+A = -13116120bca5df64e13f31425450
+
+LShift1 = 4c458482f2977d9384fcc5095142
+A = 2622c241794bbec9c27e6284a8a1
+
+LShift1 = -4c458482f2977d9384fcc5095142
+A = -2622c241794bbec9c27e6284a8a1
+
+LShift1 = 988b0905e52efb2709f98a12a286
+A = 4c458482f2977d9384fcc5095143
+
+LShift1 = -988b0905e52efb2709f98a12a286
+A = -4c458482f2977d9384fcc5095143
+
+LShift1 = 13116120bca5df64e13f31425450c
+A = 988b0905e52efb2709f98a12a286
+
+LShift1 = -13116120bca5df64e13f31425450c
+A = -988b0905e52efb2709f98a12a286
+
+LShift1 = 2622c241794bbec9c27e6284a8a18
+A = 13116120bca5df64e13f31425450c
+
+LShift1 = -2622c241794bbec9c27e6284a8a18
+A = -13116120bca5df64e13f31425450c
+
+LShift1 = 4c458482f2977d9384fcc50951430
+A = 2622c241794bbec9c27e6284a8a18
+
+LShift1 = -4c458482f2977d9384fcc50951430
+A = -2622c241794bbec9c27e6284a8a18
+
+LShift1 = 988b0905e52efb2709f98a12a2862
+A = 4c458482f2977d9384fcc50951431
+
+LShift1 = -988b0905e52efb2709f98a12a2862
+A = -4c458482f2977d9384fcc50951431
+
+LShift1 = 13116120bca5df64e13f31425450c6
+A = 988b0905e52efb2709f98a12a2863
+
+LShift1 = -13116120bca5df64e13f31425450c6
+A = -988b0905e52efb2709f98a12a2863
+
+LShift1 = 2622c241794bbec9c27e6284a8a18e
+A = 13116120bca5df64e13f31425450c7
+
+LShift1 = -2622c241794bbec9c27e6284a8a18e
+A = -13116120bca5df64e13f31425450c7
+
+LShift1 = 4c458482f2977d9384fcc50951431e
+A = 2622c241794bbec9c27e6284a8a18f
+
+LShift1 = -4c458482f2977d9384fcc50951431e
+A = -2622c241794bbec9c27e6284a8a18f
+
+LShift1 = 988b0905e52efb2709f98a12a2863c
+A = 4c458482f2977d9384fcc50951431e
+
+LShift1 = -988b0905e52efb2709f98a12a2863c
+A = -4c458482f2977d9384fcc50951431e
+
+LShift1 = 13116120bca5df64e13f31425450c7a
+A = 988b0905e52efb2709f98a12a2863d
+
+LShift1 = -13116120bca5df64e13f31425450c7a
+A = -988b0905e52efb2709f98a12a2863d
+
+LShift1 = 2622c241794bbec9c27e6284a8a18f4
+A = 13116120bca5df64e13f31425450c7a
+
+LShift1 = -2622c241794bbec9c27e6284a8a18f4
+A = -13116120bca5df64e13f31425450c7a
+
+LShift1 = 4c458482f2977d9384fcc50951431e8
+A = 2622c241794bbec9c27e6284a8a18f4
+
+LShift1 = -4c458482f2977d9384fcc50951431e8
+A = -2622c241794bbec9c27e6284a8a18f4
+
+LShift1 = 988b0905e52efb2709f98a12a2863d2
+A = 4c458482f2977d9384fcc50951431e9
+
+LShift1 = -988b0905e52efb2709f98a12a2863d2
+A = -4c458482f2977d9384fcc50951431e9
+
+LShift1 = 13116120bca5df64e13f31425450c7a4
+A = 988b0905e52efb2709f98a12a2863d2
+
+LShift1 = -13116120bca5df64e13f31425450c7a4
+A = -988b0905e52efb2709f98a12a2863d2
+
+LShift1 = 2622c241794bbec9c27e6284a8a18f4a
+A = 13116120bca5df64e13f31425450c7a5
+
+LShift1 = -2622c241794bbec9c27e6284a8a18f4a
+A = -13116120bca5df64e13f31425450c7a5
+
+LShift1 = 4c458482f2977d9384fcc50951431e94
+A = 2622c241794bbec9c27e6284a8a18f4a
+
+LShift1 = -4c458482f2977d9384fcc50951431e94
+A = -2622c241794bbec9c27e6284a8a18f4a
+
+LShift1 = 988b0905e52efb2709f98a12a2863d2a
+A = 4c458482f2977d9384fcc50951431e95
+
+LShift1 = -988b0905e52efb2709f98a12a2863d2a
+A = -4c458482f2977d9384fcc50951431e95
+
+LShift1 = 13116120bca5df64e13f31425450c7a56
+A = 988b0905e52efb2709f98a12a2863d2b
+
+LShift1 = -13116120bca5df64e13f31425450c7a56
+A = -988b0905e52efb2709f98a12a2863d2b
+
+LShift1 = 2622c241794bbec9c27e6284a8a18f4ae
+A = 13116120bca5df64e13f31425450c7a57
+
+LShift1 = -2622c241794bbec9c27e6284a8a18f4ae
+A = -13116120bca5df64e13f31425450c7a57
+
+LShift1 = 4c458482f2977d9384fcc50951431e95c
+A = 2622c241794bbec9c27e6284a8a18f4ae
+
+LShift1 = -4c458482f2977d9384fcc50951431e95c
+A = -2622c241794bbec9c27e6284a8a18f4ae
+
+LShift1 = 988b0905e52efb2709f98a12a2863d2ba
+A = 4c458482f2977d9384fcc50951431e95d
+
+LShift1 = -988b0905e52efb2709f98a12a2863d2ba
+A = -4c458482f2977d9384fcc50951431e95d
+
+LShift1 = 13116120bca5df64e13f31425450c7a576
+A = 988b0905e52efb2709f98a12a2863d2bb
+
+LShift1 = -13116120bca5df64e13f31425450c7a576
+A = -988b0905e52efb2709f98a12a2863d2bb
+
+LShift1 = 2622c241794bbec9c27e6284a8a18f4aee
+A = 13116120bca5df64e13f31425450c7a577
+
+LShift1 = -2622c241794bbec9c27e6284a8a18f4aee
+A = -13116120bca5df64e13f31425450c7a577
+
+LShift1 = 4c458482f2977d9384fcc50951431e95de
+A = 2622c241794bbec9c27e6284a8a18f4aef
+
+LShift1 = -4c458482f2977d9384fcc50951431e95de
+A = -2622c241794bbec9c27e6284a8a18f4aef
+
+LShift1 = 988b0905e52efb2709f98a12a2863d2bbc
+A = 4c458482f2977d9384fcc50951431e95de
+
+LShift1 = -988b0905e52efb2709f98a12a2863d2bbc
+A = -4c458482f2977d9384fcc50951431e95de
+
+LShift1 = 13116120bca5df64e13f31425450c7a577a
+A = 988b0905e52efb2709f98a12a2863d2bbd
+
+LShift1 = -13116120bca5df64e13f31425450c7a577a
+A = -988b0905e52efb2709f98a12a2863d2bbd
+
+LShift1 = 2622c241794bbec9c27e6284a8a18f4aef4
+A = 13116120bca5df64e13f31425450c7a577a
+
+LShift1 = -2622c241794bbec9c27e6284a8a18f4aef4
+A = -13116120bca5df64e13f31425450c7a577a
+
+LShift1 = 4c458482f2977d9384fcc50951431e95dea
+A = 2622c241794bbec9c27e6284a8a18f4aef5
+
+LShift1 = -4c458482f2977d9384fcc50951431e95dea
+A = -2622c241794bbec9c27e6284a8a18f4aef5
+
+LShift1 = 988b0905e52efb2709f98a12a2863d2bbd6
+A = 4c458482f2977d9384fcc50951431e95deb
+
+LShift1 = -988b0905e52efb2709f98a12a2863d2bbd6
+A = -4c458482f2977d9384fcc50951431e95deb
+
+LShift1 = 13116120bca5df64e13f31425450c7a577ac
+A = 988b0905e52efb2709f98a12a2863d2bbd6
+
+LShift1 = -13116120bca5df64e13f31425450c7a577ac
+A = -988b0905e52efb2709f98a12a2863d2bbd6
+
+LShift1 = 2622c241794bbec9c27e6284a8a18f4aef5a
+A = 13116120bca5df64e13f31425450c7a577ad
+
+LShift1 = -2622c241794bbec9c27e6284a8a18f4aef5a
+A = -13116120bca5df64e13f31425450c7a577ad
+
+LShift1 = 4c458482f2977d9384fcc50951431e95deb4
+A = 2622c241794bbec9c27e6284a8a18f4aef5a
+
+LShift1 = -4c458482f2977d9384fcc50951431e95deb4
+A = -2622c241794bbec9c27e6284a8a18f4aef5a
+
+LShift1 = 988b0905e52efb2709f98a12a2863d2bbd6a
+A = 4c458482f2977d9384fcc50951431e95deb5
+
+LShift1 = -988b0905e52efb2709f98a12a2863d2bbd6a
+A = -4c458482f2977d9384fcc50951431e95deb5
+
+LShift1 = 13116120bca5df64e13f31425450c7a577ad6
+A = 988b0905e52efb2709f98a12a2863d2bbd6b
+
+LShift1 = -13116120bca5df64e13f31425450c7a577ad6
+A = -988b0905e52efb2709f98a12a2863d2bbd6b
+
+LShift1 = 2622c241794bbec9c27e6284a8a18f4aef5ae
+A = 13116120bca5df64e13f31425450c7a577ad7
+
+LShift1 = -2622c241794bbec9c27e6284a8a18f4aef5ae
+A = -13116120bca5df64e13f31425450c7a577ad7
+
+LShift1 = 4c458482f2977d9384fcc50951431e95deb5e
+A = 2622c241794bbec9c27e6284a8a18f4aef5af
+
+LShift1 = -4c458482f2977d9384fcc50951431e95deb5e
+A = -2622c241794bbec9c27e6284a8a18f4aef5af
+
+LShift1 = 988b0905e52efb2709f98a12a2863d2bbd6be
+A = 4c458482f2977d9384fcc50951431e95deb5f
+
+LShift1 = -988b0905e52efb2709f98a12a2863d2bbd6be
+A = -4c458482f2977d9384fcc50951431e95deb5f
+
+LShift1 = 13116120bca5df64e13f31425450c7a577ad7e
+A = 988b0905e52efb2709f98a12a2863d2bbd6bf
+
+LShift1 = -13116120bca5df64e13f31425450c7a577ad7e
+A = -988b0905e52efb2709f98a12a2863d2bbd6bf
+
+LShift1 = 2622c241794bbec9c27e6284a8a18f4aef5afe
+A = 13116120bca5df64e13f31425450c7a577ad7f
+
+LShift1 = -2622c241794bbec9c27e6284a8a18f4aef5afe
+A = -13116120bca5df64e13f31425450c7a577ad7f
+
+LShift1 = 4c458482f2977d9384fcc50951431e95deb5fe
+A = 2622c241794bbec9c27e6284a8a18f4aef5aff
+
+LShift1 = -4c458482f2977d9384fcc50951431e95deb5fe
+A = -2622c241794bbec9c27e6284a8a18f4aef5aff
+
+LShift1 = 988b0905e52efb2709f98a12a2863d2bbd6bfe
+A = 4c458482f2977d9384fcc50951431e95deb5ff
+
+LShift1 = -988b0905e52efb2709f98a12a2863d2bbd6bfe
+A = -4c458482f2977d9384fcc50951431e95deb5ff
+
+LShift1 = 13116120bca5df64e13f31425450c7a577ad7fe
+A = 988b0905e52efb2709f98a12a2863d2bbd6bff
+
+LShift1 = -13116120bca5df64e13f31425450c7a577ad7fe
+A = -988b0905e52efb2709f98a12a2863d2bbd6bff
+
+LShift1 = 2622c241794bbec9c27e6284a8a18f4aef5affc
+A = 13116120bca5df64e13f31425450c7a577ad7fe
+
+LShift1 = -2622c241794bbec9c27e6284a8a18f4aef5affc
+A = -13116120bca5df64e13f31425450c7a577ad7fe
+
+LShift1 = 4c458482f2977d9384fcc50951431e95deb5ff8
+A = 2622c241794bbec9c27e6284a8a18f4aef5affc
+
+LShift1 = -4c458482f2977d9384fcc50951431e95deb5ff8
+A = -2622c241794bbec9c27e6284a8a18f4aef5affc
+
+LShift1 = 988b0905e52efb2709f98a12a2863d2bbd6bff0
+A = 4c458482f2977d9384fcc50951431e95deb5ff8
+
+LShift1 = -988b0905e52efb2709f98a12a2863d2bbd6bff0
+A = -4c458482f2977d9384fcc50951431e95deb5ff8
+
+LShift1 = 13116120bca5df64e13f31425450c7a577ad7fe0
+A = 988b0905e52efb2709f98a12a2863d2bbd6bff0
+
+LShift1 = -13116120bca5df64e13f31425450c7a577ad7fe0
+A = -988b0905e52efb2709f98a12a2863d2bbd6bff0
+
+LShift1 = 2622c241794bbec9c27e6284a8a18f4aef5affc0
+A = 13116120bca5df64e13f31425450c7a577ad7fe0
+
+LShift1 = -2622c241794bbec9c27e6284a8a18f4aef5affc0
+A = -13116120bca5df64e13f31425450c7a577ad7fe0
+
+LShift1 = 4c458482f2977d9384fcc50951431e95deb5ff82
+A = 2622c241794bbec9c27e6284a8a18f4aef5affc1
+
+LShift1 = -4c458482f2977d9384fcc50951431e95deb5ff82
+A = -2622c241794bbec9c27e6284a8a18f4aef5affc1
+
+LShift1 = 988b0905e52efb2709f98a12a2863d2bbd6bff06
+A = 4c458482f2977d9384fcc50951431e95deb5ff83
+
+LShift1 = -988b0905e52efb2709f98a12a2863d2bbd6bff06
+A = -4c458482f2977d9384fcc50951431e95deb5ff83
+
+LShift1 = 13116120bca5df64e13f31425450c7a577ad7fe0c
+A = 988b0905e52efb2709f98a12a2863d2bbd6bff06
+
+LShift1 = -13116120bca5df64e13f31425450c7a577ad7fe0c
+A = -988b0905e52efb2709f98a12a2863d2bbd6bff06
+
+LShift1 = 2622c241794bbec9c27e6284a8a18f4aef5affc1a
+A = 13116120bca5df64e13f31425450c7a577ad7fe0d
+
+LShift1 = -2622c241794bbec9c27e6284a8a18f4aef5affc1a
+A = -13116120bca5df64e13f31425450c7a577ad7fe0d
+
+LShift1 = 4c458482f2977d9384fcc50951431e95deb5ff836
+A = 2622c241794bbec9c27e6284a8a18f4aef5affc1b
+
+LShift1 = -4c458482f2977d9384fcc50951431e95deb5ff836
+A = -2622c241794bbec9c27e6284a8a18f4aef5affc1b
+
+LShift1 = 988b0905e52efb2709f98a12a2863d2bbd6bff06c
+A = 4c458482f2977d9384fcc50951431e95deb5ff836
+
+LShift1 = -988b0905e52efb2709f98a12a2863d2bbd6bff06c
+A = -4c458482f2977d9384fcc50951431e95deb5ff836
+
+LShift1 = 13116120bca5df64e13f31425450c7a577ad7fe0da
+A = 988b0905e52efb2709f98a12a2863d2bbd6bff06d
+
+LShift1 = -13116120bca5df64e13f31425450c7a577ad7fe0da
+A = -988b0905e52efb2709f98a12a2863d2bbd6bff06d
+
+LShift1 = 2622c241794bbec9c27e6284a8a18f4aef5affc1b6
+A = 13116120bca5df64e13f31425450c7a577ad7fe0db
+
+LShift1 = -2622c241794bbec9c27e6284a8a18f4aef5affc1b6
+A = -13116120bca5df64e13f31425450c7a577ad7fe0db
+
+LShift1 = 4c458482f2977d9384fcc50951431e95deb5ff836e
+A = 2622c241794bbec9c27e6284a8a18f4aef5affc1b7
+
+LShift1 = -4c458482f2977d9384fcc50951431e95deb5ff836e
+A = -2622c241794bbec9c27e6284a8a18f4aef5affc1b7
+
+LShift1 = 988b0905e52efb2709f98a12a2863d2bbd6bff06de
+A = 4c458482f2977d9384fcc50951431e95deb5ff836f
+
+LShift1 = -988b0905e52efb2709f98a12a2863d2bbd6bff06de
+A = -4c458482f2977d9384fcc50951431e95deb5ff836f
+
+LShift1 = 13116120bca5df64e13f31425450c7a577ad7fe0dbe
+A = 988b0905e52efb2709f98a12a2863d2bbd6bff06df
+
+LShift1 = -13116120bca5df64e13f31425450c7a577ad7fe0dbe
+A = -988b0905e52efb2709f98a12a2863d2bbd6bff06df
+
+LShift1 = 2622c241794bbec9c27e6284a8a18f4aef5affc1b7c
+A = 13116120bca5df64e13f31425450c7a577ad7fe0dbe
+
+LShift1 = -2622c241794bbec9c27e6284a8a18f4aef5affc1b7c
+A = -13116120bca5df64e13f31425450c7a577ad7fe0dbe
+
+LShift1 = 4c458482f2977d9384fcc50951431e95deb5ff836fa
+A = 2622c241794bbec9c27e6284a8a18f4aef5affc1b7d
+
+LShift1 = -4c458482f2977d9384fcc50951431e95deb5ff836fa
+A = -2622c241794bbec9c27e6284a8a18f4aef5affc1b7d
+
+LShift1 = 988b0905e52efb2709f98a12a2863d2bbd6bff06df6
+A = 4c458482f2977d9384fcc50951431e95deb5ff836fb
+
+LShift1 = -988b0905e52efb2709f98a12a2863d2bbd6bff06df6
+A = -4c458482f2977d9384fcc50951431e95deb5ff836fb
+
+LShift1 = 13116120bca5df64e13f31425450c7a577ad7fe0dbec
+A = 988b0905e52efb2709f98a12a2863d2bbd6bff06df6
+
+LShift1 = -13116120bca5df64e13f31425450c7a577ad7fe0dbec
+A = -988b0905e52efb2709f98a12a2863d2bbd6bff06df6
+
+LShift1 = 2622c241794bbec9c27e6284a8a18f4aef5affc1b7da
+A = 13116120bca5df64e13f31425450c7a577ad7fe0dbed
+
+LShift1 = -2622c241794bbec9c27e6284a8a18f4aef5affc1b7da
+A = -13116120bca5df64e13f31425450c7a577ad7fe0dbed
+
+LShift1 = 4c458482f2977d9384fcc50951431e95deb5ff836fb6
+A = 2622c241794bbec9c27e6284a8a18f4aef5affc1b7db
+
+LShift1 = -4c458482f2977d9384fcc50951431e95deb5ff836fb6
+A = -2622c241794bbec9c27e6284a8a18f4aef5affc1b7db
+
+LShift1 = 988b0905e52efb2709f98a12a2863d2bbd6bff06df6c
+A = 4c458482f2977d9384fcc50951431e95deb5ff836fb6
+
+LShift1 = -988b0905e52efb2709f98a12a2863d2bbd6bff06df6c
+A = -4c458482f2977d9384fcc50951431e95deb5ff836fb6
+
+LShift1 = 13116120bca5df64e13f31425450c7a577ad7fe0dbed8
+A = 988b0905e52efb2709f98a12a2863d2bbd6bff06df6c
+
+LShift1 = -13116120bca5df64e13f31425450c7a577ad7fe0dbed8
+A = -988b0905e52efb2709f98a12a2863d2bbd6bff06df6c
+
+LShift1 = 2622c241794bbec9c27e6284a8a18f4aef5affc1b7db0
+A = 13116120bca5df64e13f31425450c7a577ad7fe0dbed8
+
+LShift1 = -2622c241794bbec9c27e6284a8a18f4aef5affc1b7db0
+A = -13116120bca5df64e13f31425450c7a577ad7fe0dbed8
+
+LShift1 = 4c458482f2977d9384fcc50951431e95deb5ff836fb60
+A = 2622c241794bbec9c27e6284a8a18f4aef5affc1b7db0
+
+LShift1 = -4c458482f2977d9384fcc50951431e95deb5ff836fb60
+A = -2622c241794bbec9c27e6284a8a18f4aef5affc1b7db0
+
+LShift1 = 988b0905e52efb2709f98a12a2863d2bbd6bff06df6c0
+A = 4c458482f2977d9384fcc50951431e95deb5ff836fb60
+
+LShift1 = -988b0905e52efb2709f98a12a2863d2bbd6bff06df6c0
+A = -4c458482f2977d9384fcc50951431e95deb5ff836fb60
+
+LShift1 = 13116120bca5df64e13f31425450c7a577ad7fe0dbed82
+A = 988b0905e52efb2709f98a12a2863d2bbd6bff06df6c1
+
+LShift1 = -13116120bca5df64e13f31425450c7a577ad7fe0dbed82
+A = -988b0905e52efb2709f98a12a2863d2bbd6bff06df6c1
+
+LShift1 = 2622c241794bbec9c27e6284a8a18f4aef5affc1b7db06
+A = 13116120bca5df64e13f31425450c7a577ad7fe0dbed83
+
+LShift1 = -2622c241794bbec9c27e6284a8a18f4aef5affc1b7db06
+A = -13116120bca5df64e13f31425450c7a577ad7fe0dbed83
+
+LShift1 = 4c458482f2977d9384fcc50951431e95deb5ff836fb60c
+A = 2622c241794bbec9c27e6284a8a18f4aef5affc1b7db06
+
+LShift1 = -4c458482f2977d9384fcc50951431e95deb5ff836fb60c
+A = -2622c241794bbec9c27e6284a8a18f4aef5affc1b7db06
+
+LShift1 = 988b0905e52efb2709f98a12a2863d2bbd6bff06df6c18
+A = 4c458482f2977d9384fcc50951431e95deb5ff836fb60c
+
+LShift1 = -988b0905e52efb2709f98a12a2863d2bbd6bff06df6c18
+A = -4c458482f2977d9384fcc50951431e95deb5ff836fb60c
+
+LShift1 = 13116120bca5df64e13f31425450c7a577ad7fe0dbed832
+A = 988b0905e52efb2709f98a12a2863d2bbd6bff06df6c19
+
+LShift1 = -13116120bca5df64e13f31425450c7a577ad7fe0dbed832
+A = -988b0905e52efb2709f98a12a2863d2bbd6bff06df6c19
+
+LShift1 = 2622c241794bbec9c27e6284a8a18f4aef5affc1b7db066
+A = 13116120bca5df64e13f31425450c7a577ad7fe0dbed833
+
+LShift1 = -2622c241794bbec9c27e6284a8a18f4aef5affc1b7db066
+A = -13116120bca5df64e13f31425450c7a577ad7fe0dbed833
+
+LShift1 = 4c458482f2977d9384fcc50951431e95deb5ff836fb60ce
+A = 2622c241794bbec9c27e6284a8a18f4aef5affc1b7db067
+
+LShift1 = -4c458482f2977d9384fcc50951431e95deb5ff836fb60ce
+A = -2622c241794bbec9c27e6284a8a18f4aef5affc1b7db067
+
+LShift1 = 988b0905e52efb2709f98a12a2863d2bbd6bff06df6c19e
+A = 4c458482f2977d9384fcc50951431e95deb5ff836fb60cf
+
+LShift1 = -988b0905e52efb2709f98a12a2863d2bbd6bff06df6c19e
+A = -4c458482f2977d9384fcc50951431e95deb5ff836fb60cf
+
+LShift1 = 13116120bca5df64e13f31425450c7a577ad7fe0dbed833e
+A = 988b0905e52efb2709f98a12a2863d2bbd6bff06df6c19f
+
+LShift1 = -13116120bca5df64e13f31425450c7a577ad7fe0dbed833e
+A = -988b0905e52efb2709f98a12a2863d2bbd6bff06df6c19f
+
+LShift1 = 2622c241794bbec9c27e6284a8a18f4aef5affc1b7db067c
+A = 13116120bca5df64e13f31425450c7a577ad7fe0dbed833e
+
+LShift1 = -2622c241794bbec9c27e6284a8a18f4aef5affc1b7db067c
+A = -13116120bca5df64e13f31425450c7a577ad7fe0dbed833e
+
+LShift1 = 4c458482f2977d9384fcc50951431e95deb5ff836fb60cfa
+A = 2622c241794bbec9c27e6284a8a18f4aef5affc1b7db067d
+
+LShift1 = -4c458482f2977d9384fcc50951431e95deb5ff836fb60cfa
+A = -2622c241794bbec9c27e6284a8a18f4aef5affc1b7db067d
+
+LShift1 = 988b0905e52efb2709f98a12a2863d2bbd6bff06df6c19f6
+A = 4c458482f2977d9384fcc50951431e95deb5ff836fb60cfb
+
+LShift1 = -988b0905e52efb2709f98a12a2863d2bbd6bff06df6c19f6
+A = -4c458482f2977d9384fcc50951431e95deb5ff836fb60cfb
+
+LShift1 = 13116120bca5df64e13f31425450c7a577ad7fe0dbed833ee
+A = 988b0905e52efb2709f98a12a2863d2bbd6bff06df6c19f7
+
+LShift1 = -13116120bca5df64e13f31425450c7a577ad7fe0dbed833ee
+A = -988b0905e52efb2709f98a12a2863d2bbd6bff06df6c19f7
+
+LShift1 = 2622c241794bbec9c27e6284a8a18f4aef5affc1b7db067de
+A = 13116120bca5df64e13f31425450c7a577ad7fe0dbed833ef
+
+LShift1 = -2622c241794bbec9c27e6284a8a18f4aef5affc1b7db067de
+A = -13116120bca5df64e13f31425450c7a577ad7fe0dbed833ef
+
+LShift1 = 4c458482f2977d9384fcc50951431e95deb5ff836fb60cfbe
+A = 2622c241794bbec9c27e6284a8a18f4aef5affc1b7db067df
+
+LShift1 = -4c458482f2977d9384fcc50951431e95deb5ff836fb60cfbe
+A = -2622c241794bbec9c27e6284a8a18f4aef5affc1b7db067df
+
+LShift1 = 988b0905e52efb2709f98a12a2863d2bbd6bff06df6c19f7e
+A = 4c458482f2977d9384fcc50951431e95deb5ff836fb60cfbf
+
+LShift1 = -988b0905e52efb2709f98a12a2863d2bbd6bff06df6c19f7e
+A = -4c458482f2977d9384fcc50951431e95deb5ff836fb60cfbf
+
+LShift1 = 13116120bca5df64e13f31425450c7a577ad7fe0dbed833efe
+A = 988b0905e52efb2709f98a12a2863d2bbd6bff06df6c19f7f
+
+LShift1 = -13116120bca5df64e13f31425450c7a577ad7fe0dbed833efe
+A = -988b0905e52efb2709f98a12a2863d2bbd6bff06df6c19f7f
+
+LShift1 = 2622c241794bbec9c27e6284a8a18f4aef5affc1b7db067dfc
+A = 13116120bca5df64e13f31425450c7a577ad7fe0dbed833efe
+
+LShift1 = -2622c241794bbec9c27e6284a8a18f4aef5affc1b7db067dfc
+A = -13116120bca5df64e13f31425450c7a577ad7fe0dbed833efe
+
+LShift1 = 4c458482f2977d9384fcc50951431e95deb5ff836fb60cfbf8
+A = 2622c241794bbec9c27e6284a8a18f4aef5affc1b7db067dfc
+
+LShift1 = -4c458482f2977d9384fcc50951431e95deb5ff836fb60cfbf8
+A = -2622c241794bbec9c27e6284a8a18f4aef5affc1b7db067dfc
+
+LShift1 = 988b0905e52efb2709f98a12a2863d2bbd6bff06df6c19f7f0
+A = 4c458482f2977d9384fcc50951431e95deb5ff836fb60cfbf8
+
+LShift1 = -988b0905e52efb2709f98a12a2863d2bbd6bff06df6c19f7f0
+A = -4c458482f2977d9384fcc50951431e95deb5ff836fb60cfbf8
+
+LShift1 = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e
+A = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907
+
+LShift1 = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e
+A = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907
+
+LShift1 = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c
+A = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e
+
+LShift1 = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c
+A = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e
+
+LShift1 = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838
+A = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c
+
+LShift1 = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838
+A = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c
+
+LShift1 = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070
+A = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838
+
+LShift1 = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070
+A = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838
+
+LShift1 = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e0
+A = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070
+
+LShift1 = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e0
+A = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070
+
+LShift1 = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c0
+A = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e0
+
+LShift1 = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c0
+A = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e0
+
+LShift1 = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c8380
+A = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c0
+
+LShift1 = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c8380
+A = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c0
+
+LShift1 = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b41386190700
+A = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c8380
+
+LShift1 = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b41386190700
+A = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c8380
+
+LShift1 = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e00
+A = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b41386190700
+
+LShift1 = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e00
+A = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b41386190700
+
+LShift1 = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c00
+A = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e00
+
+LShift1 = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c00
+A = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e00
+
+LShift1 = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c83800
+A = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c00
+
+LShift1 = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c83800
+A = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c00
+
+LShift1 = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907000
+A = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c83800
+
+LShift1 = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907000
+A = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c83800
+
+LShift1 = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e000
+A = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907000
+
+LShift1 = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e000
+A = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907000
+
+LShift1 = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c000
+A = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e000
+
+LShift1 = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c000
+A = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e000
+
+LShift1 = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838000
+A = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c000
+
+LShift1 = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838000
+A = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c000
+
+LShift1 = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070000
+A = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838000
+
+LShift1 = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070000
+A = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838000
+
+LShift1 = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e0000
+A = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070000
+
+LShift1 = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e0000
+A = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070000
+
+LShift1 = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c0000
+A = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e0000
+
+LShift1 = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c0000
+A = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e0000
+
+LShift1 = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c8380000
+A = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c0000
+
+LShift1 = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c8380000
+A = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c0000
+
+LShift1 = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b41386190700000
+A = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c8380000
+
+LShift1 = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b41386190700000
+A = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c8380000
+
+LShift1 = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e00000
+A = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b41386190700000
+
+LShift1 = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e00000
+A = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b41386190700000
+
+LShift1 = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c00000
+A = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e00000
+
+LShift1 = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c00000
+A = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e00000
+
+LShift1 = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c83800000
+A = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c00000
+
+LShift1 = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c83800000
+A = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c00000
+
+LShift1 = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907000000
+A = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c83800000
+
+LShift1 = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907000000
+A = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c83800000
+
+LShift1 = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e000000
+A = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907000000
+
+LShift1 = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e000000
+A = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907000000
+
+LShift1 = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c000000
+A = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e000000
+
+LShift1 = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c000000
+A = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e000000
+
+LShift1 = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838000000
+A = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c000000
+
+LShift1 = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838000000
+A = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c000000
+
+LShift1 = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070000000
+A = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838000000
+
+LShift1 = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070000000
+A = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838000000
+
+LShift1 = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e0000000
+A = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070000000
+
+LShift1 = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e0000000
+A = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070000000
+
+LShift1 = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c0000000
+A = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e0000000
+
+LShift1 = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c0000000
+A = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e0000000
+
+LShift1 = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c8380000000
+A = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c0000000
+
+LShift1 = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c8380000000
+A = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c0000000
+
+LShift1 = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b41386190700000000
+A = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c8380000000
+
+LShift1 = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b41386190700000000
+A = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c8380000000
+
+LShift1 = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e00000000
+A = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b41386190700000000
+
+LShift1 = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e00000000
+A = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b41386190700000000
+
+LShift1 = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c00000000
+A = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e00000000
+
+LShift1 = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c00000000
+A = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e00000000
+
+LShift1 = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c83800000000
+A = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c00000000
+
+LShift1 = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c83800000000
+A = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c00000000
+
+LShift1 = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907000000000
+A = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c83800000000
+
+LShift1 = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907000000000
+A = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c83800000000
+
+LShift1 = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e000000000
+A = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907000000000
+
+LShift1 = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e000000000
+A = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907000000000
+
+LShift1 = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c000000000
+A = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e000000000
+
+LShift1 = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c000000000
+A = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e000000000
+
+LShift1 = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838000000000
+A = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c000000000
+
+LShift1 = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838000000000
+A = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c000000000
+
+LShift1 = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070000000000
+A = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838000000000
+
+LShift1 = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070000000000
+A = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838000000000
+
+LShift1 = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e0000000000
+A = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070000000000
+
+LShift1 = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e0000000000
+A = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070000000000
+
+LShift1 = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c0000000000
+A = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e0000000000
+
+LShift1 = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c0000000000
+A = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e0000000000
+
+LShift1 = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c8380000000000
+A = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c0000000000
+
+LShift1 = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c8380000000000
+A = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c0000000000
+
+LShift1 = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b41386190700000000000
+A = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c8380000000000
+
+LShift1 = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b41386190700000000000
+A = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c8380000000000
+
+LShift1 = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e00000000000
+A = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b41386190700000000000
+
+LShift1 = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e00000000000
+A = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b41386190700000000000
+
+LShift1 = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c00000000000
+A = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e00000000000
+
+LShift1 = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c00000000000
+A = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e00000000000
+
+LShift1 = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c83800000000000
+A = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c00000000000
+
+LShift1 = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c83800000000000
+A = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c00000000000
+
+LShift1 = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907000000000000
+A = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c83800000000000
+
+LShift1 = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907000000000000
+A = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c83800000000000
+
+LShift1 = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e000000000000
+A = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907000000000000
+
+LShift1 = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e000000000000
+A = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907000000000000
+
+LShift1 = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c000000000000
+A = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e000000000000
+
+LShift1 = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c000000000000
+A = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e000000000000
+
+LShift1 = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838000000000000
+A = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c000000000000
+
+LShift1 = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838000000000000
+A = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c000000000000
+
+LShift1 = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070000000000000
+A = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838000000000000
+
+LShift1 = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070000000000000
+A = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838000000000000
+
+LShift1 = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e0000000000000
+A = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070000000000000
+
+LShift1 = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e0000000000000
+A = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070000000000000
+
+LShift1 = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c0000000000000
+A = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e0000000000000
+
+LShift1 = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c0000000000000
+A = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e0000000000000
+
+LShift1 = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c8380000000000000
+A = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c0000000000000
+
+LShift1 = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c8380000000000000
+A = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c0000000000000
+
+LShift1 = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b41386190700000000000000
+A = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c8380000000000000
+
+LShift1 = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b41386190700000000000000
+A = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c8380000000000000
+
+LShift1 = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e00000000000000
+A = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b41386190700000000000000
+
+LShift1 = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e00000000000000
+A = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b41386190700000000000000
+
+LShift1 = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c00000000000000
+A = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e00000000000000
+
+LShift1 = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c00000000000000
+A = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e00000000000000
+
+LShift1 = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c83800000000000000
+A = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c00000000000000
+
+LShift1 = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c83800000000000000
+A = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c00000000000000
+
+LShift1 = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907000000000000000
+A = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c83800000000000000
+
+LShift1 = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907000000000000000
+A = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c83800000000000000
+
+LShift1 = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e000000000000000
+A = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907000000000000000
+
+LShift1 = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e000000000000000
+A = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907000000000000000
+
+LShift1 = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c000000000000000
+A = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e000000000000000
+
+LShift1 = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c000000000000000
+A = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e000000000000000
+
+LShift1 = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838000000000000000
+A = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c000000000000000
+
+LShift1 = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838000000000000000
+A = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c000000000000000
+
+LShift1 = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070000000000000000
+A = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838000000000000000
+
+LShift1 = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070000000000000000
+A = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838000000000000000
+
+LShift1 = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e0000000000000000
+A = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070000000000000000
+
+LShift1 = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e0000000000000000
+A = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070000000000000000
+
+LShift1 = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c0000000000000000
+A = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e0000000000000000
+
+LShift1 = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c0000000000000000
+A = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e0000000000000000
+
+LShift1 = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c8380000000000000000
+A = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c0000000000000000
+
+LShift1 = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c8380000000000000000
+A = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c0000000000000000
+
+LShift1 = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b41386190700000000000000000
+A = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c8380000000000000000
+
+LShift1 = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b41386190700000000000000000
+A = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c8380000000000000000
+
+LShift1 = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e00000000000000000
+A = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b41386190700000000000000000
+
+LShift1 = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e00000000000000000
+A = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b41386190700000000000000000
+
+LShift1 = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c00000000000000000
+A = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e00000000000000000
+
+LShift1 = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c00000000000000000
+A = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e00000000000000000
+
+LShift1 = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c83800000000000000000
+A = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c00000000000000000
+
+LShift1 = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c83800000000000000000
+A = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c00000000000000000
+
+LShift1 = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907000000000000000000
+A = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c83800000000000000000
+
+LShift1 = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907000000000000000000
+A = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c83800000000000000000
+
+LShift1 = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e000000000000000000
+A = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907000000000000000000
+
+LShift1 = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e000000000000000000
+A = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907000000000000000000
+
+LShift1 = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c000000000000000000
+A = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e000000000000000000
+
+LShift1 = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c000000000000000000
+A = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e000000000000000000
+
+LShift1 = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838000000000000000000
+A = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c000000000000000000
+
+LShift1 = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838000000000000000000
+A = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c000000000000000000
+
+LShift1 = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070000000000000000000
+A = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838000000000000000000
+
+LShift1 = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070000000000000000000
+A = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838000000000000000000
+
+LShift1 = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e0000000000000000000
+A = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070000000000000000000
+
+LShift1 = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e0000000000000000000
+A = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070000000000000000000
+
+LShift1 = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c0000000000000000000
+A = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e0000000000000000000
+
+LShift1 = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c0000000000000000000
+A = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e0000000000000000000
+
+LShift1 = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c8380000000000000000000
+A = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c0000000000000000000
+
+LShift1 = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c8380000000000000000000
+A = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c0000000000000000000
+
+LShift1 = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b41386190700000000000000000000
+A = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c8380000000000000000000
+
+LShift1 = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b41386190700000000000000000000
+A = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c8380000000000000000000
+
+LShift1 = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e00000000000000000000
+A = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b41386190700000000000000000000
+
+LShift1 = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e00000000000000000000
+A = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b41386190700000000000000000000
+
+LShift1 = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c00000000000000000000
+A = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e00000000000000000000
+
+LShift1 = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c00000000000000000000
+A = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e00000000000000000000
+
+LShift1 = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c83800000000000000000000
+A = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c00000000000000000000
+
+LShift1 = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c83800000000000000000000
+A = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c00000000000000000000
+
+LShift1 = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907000000000000000000000
+A = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c83800000000000000000000
+
+LShift1 = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907000000000000000000000
+A = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c83800000000000000000000
+
+LShift1 = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e000000000000000000000
+A = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907000000000000000000000
+
+LShift1 = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e000000000000000000000
+A = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907000000000000000000000
+
+LShift1 = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c000000000000000000000
+A = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e000000000000000000000
+
+LShift1 = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c000000000000000000000
+A = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e000000000000000000000
+
+LShift1 = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838000000000000000000000
+A = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c000000000000000000000
+
+LShift1 = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838000000000000000000000
+A = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c000000000000000000000
+
+LShift1 = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070000000000000000000000
+A = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838000000000000000000000
+
+LShift1 = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070000000000000000000000
+A = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838000000000000000000000
+
+LShift1 = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e0000000000000000000000
+A = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070000000000000000000000
+
+LShift1 = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e0000000000000000000000
+A = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070000000000000000000000
+
+LShift1 = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c0000000000000000000000
+A = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e0000000000000000000000
+
+LShift1 = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c0000000000000000000000
+A = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e0000000000000000000000
+
+LShift1 = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c8380000000000000000000000
+A = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c0000000000000000000000
+
+LShift1 = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c8380000000000000000000000
+A = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c0000000000000000000000
+
+LShift1 = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b41386190700000000000000000000000
+A = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c8380000000000000000000000
+
+LShift1 = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b41386190700000000000000000000000
+A = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c8380000000000000000000000
+
+LShift1 = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e00000000000000000000000
+A = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b41386190700000000000000000000000
+
+LShift1 = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e00000000000000000000000
+A = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b41386190700000000000000000000000
+
+LShift1 = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c00000000000000000000000
+A = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e00000000000000000000000
+
+LShift1 = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c00000000000000000000000
+A = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e00000000000000000000000
+
+LShift1 = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c83800000000000000000000000
+A = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c00000000000000000000000
+
+LShift1 = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c83800000000000000000000000
+A = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c00000000000000000000000
+
+LShift1 = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907000000000000000000000000
+A = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c83800000000000000000000000
+
+LShift1 = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907000000000000000000000000
+A = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c83800000000000000000000000
+
+LShift1 = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e000000000000000000000000
+A = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907000000000000000000000000
+
+LShift1 = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e000000000000000000000000
+A = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b413861907000000000000000000000000
+
+LShift1 = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c000000000000000000000000
+A = 1569d01c96acaadb32211d67966be2fa35d07b46768270c320e000000000000000000000000
+
+LShift1 = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c000000000000000000000000
+A = -1569d01c96acaadb32211d67966be2fa35d07b46768270c320e000000000000000000000000
+
+LShift1 = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838000000000000000000000000
+A = 2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c000000000000000000000000
+
+LShift1 = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838000000000000000000000000
+A = -2ad3a0392d5955b664423acf2cd7c5f46ba0f68ced04e18641c000000000000000000000000
+
+LShift1 = ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070000000000000000000000000
+A = 55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838000000000000000000000000
+
+LShift1 = -ab4e80e4b56556d99108eb3cb35f17d1ae83da33b4138619070000000000000000000000000
+A = -55a740725ab2ab6cc884759e59af8be8d741ed19da09c30c838000000000000000000000000
+
+
+# LShift tests
+#
+# These test vectors satisfy A * 2^N = LShift.
+
+LShift = 18c9e860855d594dcb06d00b7d1933608ba906d85fa2d92c9e0
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 1
+
+LShift = 3193d0c10abab29b960da016fa3266c117520db0bf45b2593c0
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 2
+
+LShift = 6327a182157565372c1b402df464cd822ea41b617e8b64b2780
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 3
+
+LShift = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f00
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 4
+
+LShift = 18c9e860855d594dcb06d00b7d1933608ba906d85fa2d92c9e00
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 5
+
+LShift = 3193d0c10abab29b960da016fa3266c117520db0bf45b2593c00
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 6
+
+LShift = 6327a182157565372c1b402df464cd822ea41b617e8b64b27800
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 7
+
+LShift = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 8
+
+LShift = 18c9e860855d594dcb06d00b7d1933608ba906d85fa2d92c9e000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 9
+
+LShift = 3193d0c10abab29b960da016fa3266c117520db0bf45b2593c000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = a
+
+LShift = 6327a182157565372c1b402df464cd822ea41b617e8b64b278000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = b
+
+LShift = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = c
+
+LShift = 18c9e860855d594dcb06d00b7d1933608ba906d85fa2d92c9e0000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = d
+
+LShift = 3193d0c10abab29b960da016fa3266c117520db0bf45b2593c0000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = e
+
+LShift = 6327a182157565372c1b402df464cd822ea41b617e8b64b2780000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = f
+
+LShift = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f00000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 10
+
+LShift = 18c9e860855d594dcb06d00b7d1933608ba906d85fa2d92c9e00000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 11
+
+LShift = 3193d0c10abab29b960da016fa3266c117520db0bf45b2593c00000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 12
+
+LShift = 6327a182157565372c1b402df464cd822ea41b617e8b64b27800000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 13
+
+LShift = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 14
+
+LShift = 18c9e860855d594dcb06d00b7d1933608ba906d85fa2d92c9e000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 15
+
+LShift = 3193d0c10abab29b960da016fa3266c117520db0bf45b2593c000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 16
+
+LShift = 6327a182157565372c1b402df464cd822ea41b617e8b64b278000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 17
+
+LShift = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 18
+
+LShift = 18c9e860855d594dcb06d00b7d1933608ba906d85fa2d92c9e0000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 19
+
+LShift = 3193d0c10abab29b960da016fa3266c117520db0bf45b2593c0000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 1a
+
+LShift = 6327a182157565372c1b402df464cd822ea41b617e8b64b2780000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 1b
+
+LShift = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f00000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 1c
+
+LShift = 18c9e860855d594dcb06d00b7d1933608ba906d85fa2d92c9e00000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 1d
+
+LShift = 3193d0c10abab29b960da016fa3266c117520db0bf45b2593c00000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 1e
+
+LShift = 6327a182157565372c1b402df464cd822ea41b617e8b64b27800000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 1f
+
+LShift = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 20
+
+LShift = 18c9e860855d594dcb06d00b7d1933608ba906d85fa2d92c9e000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 21
+
+LShift = 3193d0c10abab29b960da016fa3266c117520db0bf45b2593c000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 22
+
+LShift = 6327a182157565372c1b402df464cd822ea41b617e8b64b278000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 23
+
+LShift = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 24
+
+LShift = 18c9e860855d594dcb06d00b7d1933608ba906d85fa2d92c9e0000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 25
+
+LShift = 3193d0c10abab29b960da016fa3266c117520db0bf45b2593c0000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 26
+
+LShift = 6327a182157565372c1b402df464cd822ea41b617e8b64b2780000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 27
+
+LShift = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f00000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 28
+
+LShift = 18c9e860855d594dcb06d00b7d1933608ba906d85fa2d92c9e00000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 29
+
+LShift = 3193d0c10abab29b960da016fa3266c117520db0bf45b2593c00000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 2a
+
+LShift = 6327a182157565372c1b402df464cd822ea41b617e8b64b27800000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 2b
+
+LShift = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 2c
+
+LShift = 18c9e860855d594dcb06d00b7d1933608ba906d85fa2d92c9e000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 2d
+
+LShift = 3193d0c10abab29b960da016fa3266c117520db0bf45b2593c000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 2e
+
+LShift = 6327a182157565372c1b402df464cd822ea41b617e8b64b278000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 2f
+
+LShift = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 30
+
+LShift = 18c9e860855d594dcb06d00b7d1933608ba906d85fa2d92c9e0000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 31
+
+LShift = 3193d0c10abab29b960da016fa3266c117520db0bf45b2593c0000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 32
+
+LShift = 6327a182157565372c1b402df464cd822ea41b617e8b64b2780000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 33
+
+LShift = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f00000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 34
+
+LShift = 18c9e860855d594dcb06d00b7d1933608ba906d85fa2d92c9e00000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 35
+
+LShift = 3193d0c10abab29b960da016fa3266c117520db0bf45b2593c00000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 36
+
+LShift = 6327a182157565372c1b402df464cd822ea41b617e8b64b27800000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 37
+
+LShift = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 38
+
+LShift = 18c9e860855d594dcb06d00b7d1933608ba906d85fa2d92c9e000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 39
+
+LShift = 3193d0c10abab29b960da016fa3266c117520db0bf45b2593c000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 3a
+
+LShift = 6327a182157565372c1b402df464cd822ea41b617e8b64b278000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 3b
+
+LShift = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 3c
+
+LShift = 18c9e860855d594dcb06d00b7d1933608ba906d85fa2d92c9e0000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 3d
+
+LShift = 3193d0c10abab29b960da016fa3266c117520db0bf45b2593c0000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 3e
+
+LShift = 6327a182157565372c1b402df464cd822ea41b617e8b64b2780000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 3f
+
+LShift = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f00000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 40
+
+LShift = 18c9e860855d594dcb06d00b7d1933608ba906d85fa2d92c9e00000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 41
+
+LShift = 3193d0c10abab29b960da016fa3266c117520db0bf45b2593c00000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 42
+
+LShift = 6327a182157565372c1b402df464cd822ea41b617e8b64b27800000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 43
+
+LShift = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f000000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 44
+
+LShift = 18c9e860855d594dcb06d00b7d1933608ba906d85fa2d92c9e000000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 45
+
+LShift = 3193d0c10abab29b960da016fa3266c117520db0bf45b2593c000000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 46
+
+LShift = 6327a182157565372c1b402df464cd822ea41b617e8b64b278000000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 47
+
+LShift = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0000000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 48
+
+LShift = 18c9e860855d594dcb06d00b7d1933608ba906d85fa2d92c9e0000000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 49
+
+LShift = 3193d0c10abab29b960da016fa3266c117520db0bf45b2593c0000000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 4a
+
+LShift = 6327a182157565372c1b402df464cd822ea41b617e8b64b2780000000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 4b
+
+LShift = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f00000000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 4c
+
+LShift = 18c9e860855d594dcb06d00b7d1933608ba906d85fa2d92c9e00000000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 4d
+
+LShift = 3193d0c10abab29b960da016fa3266c117520db0bf45b2593c00000000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 4e
+
+LShift = 6327a182157565372c1b402df464cd822ea41b617e8b64b27800000000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 4f
+
+LShift = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f000000000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 50
+
+LShift = 18c9e860855d594dcb06d00b7d1933608ba906d85fa2d92c9e000000000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 51
+
+LShift = 3193d0c10abab29b960da016fa3266c117520db0bf45b2593c000000000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 52
+
+LShift = 6327a182157565372c1b402df464cd822ea41b617e8b64b278000000000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 53
+
+LShift = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0000000000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 54
+
+LShift = 18c9e860855d594dcb06d00b7d1933608ba906d85fa2d92c9e0000000000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 55
+
+LShift = 3193d0c10abab29b960da016fa3266c117520db0bf45b2593c0000000000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 56
+
+LShift = 6327a182157565372c1b402df464cd822ea41b617e8b64b2780000000000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 57
+
+LShift = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f00000000000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 58
+
+LShift = 18c9e860855d594dcb06d00b7d1933608ba906d85fa2d92c9e00000000000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 59
+
+LShift = 3193d0c10abab29b960da016fa3266c117520db0bf45b2593c00000000000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 5a
+
+LShift = 6327a182157565372c1b402df464cd822ea41b617e8b64b27800000000000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 5b
+
+LShift = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f000000000000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 5c
+
+LShift = 18c9e860855d594dcb06d00b7d1933608ba906d85fa2d92c9e000000000000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 5d
+
+LShift = 3193d0c10abab29b960da016fa3266c117520db0bf45b2593c000000000000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 5e
+
+LShift = 6327a182157565372c1b402df464cd822ea41b617e8b64b278000000000000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 5f
+
+LShift = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0000000000000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 60
+
+LShift = 18c9e860855d594dcb06d00b7d1933608ba906d85fa2d92c9e0000000000000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 61
+
+LShift = 3193d0c10abab29b960da016fa3266c117520db0bf45b2593c0000000000000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 62
+
+LShift = 6327a182157565372c1b402df464cd822ea41b617e8b64b2780000000000000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 63
+
+LShift = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f00000000000000000000000000
+A = c64f43042aeaca6e5836805be8c99b045d4836c2fd16c964f0
+N = 64
+
+LShift = 1d1cf8b5ccbae667bd05797fbaf9d4c1ff623cc01546111d91c
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 1
+
+LShift = 3a39f16b9975cccf7a0af2ff75f3a983fec479802a8c223b238
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 2
+
+LShift = 7473e2d732eb999ef415e5feebe75307fd88f30055184476470
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 3
+
+LShift = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e0
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 4
+
+LShift = 1d1cf8b5ccbae667bd05797fbaf9d4c1ff623cc01546111d91c0
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 5
+
+LShift = 3a39f16b9975cccf7a0af2ff75f3a983fec479802a8c223b2380
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 6
+
+LShift = 7473e2d732eb999ef415e5feebe75307fd88f300551844764700
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 7
+
+LShift = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e00
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 8
+
+LShift = 1d1cf8b5ccbae667bd05797fbaf9d4c1ff623cc01546111d91c00
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 9
+
+LShift = 3a39f16b9975cccf7a0af2ff75f3a983fec479802a8c223b23800
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = a
+
+LShift = 7473e2d732eb999ef415e5feebe75307fd88f3005518447647000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = b
+
+LShift = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = c
+
+LShift = 1d1cf8b5ccbae667bd05797fbaf9d4c1ff623cc01546111d91c000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = d
+
+LShift = 3a39f16b9975cccf7a0af2ff75f3a983fec479802a8c223b238000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = e
+
+LShift = 7473e2d732eb999ef415e5feebe75307fd88f30055184476470000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = f
+
+LShift = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e0000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 10
+
+LShift = 1d1cf8b5ccbae667bd05797fbaf9d4c1ff623cc01546111d91c0000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 11
+
+LShift = 3a39f16b9975cccf7a0af2ff75f3a983fec479802a8c223b2380000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 12
+
+LShift = 7473e2d732eb999ef415e5feebe75307fd88f300551844764700000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 13
+
+LShift = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e00000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 14
+
+LShift = 1d1cf8b5ccbae667bd05797fbaf9d4c1ff623cc01546111d91c00000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 15
+
+LShift = 3a39f16b9975cccf7a0af2ff75f3a983fec479802a8c223b23800000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 16
+
+LShift = 7473e2d732eb999ef415e5feebe75307fd88f3005518447647000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 17
+
+LShift = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 18
+
+LShift = 1d1cf8b5ccbae667bd05797fbaf9d4c1ff623cc01546111d91c000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 19
+
+LShift = 3a39f16b9975cccf7a0af2ff75f3a983fec479802a8c223b238000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 1a
+
+LShift = 7473e2d732eb999ef415e5feebe75307fd88f30055184476470000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 1b
+
+LShift = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e0000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 1c
+
+LShift = 1d1cf8b5ccbae667bd05797fbaf9d4c1ff623cc01546111d91c0000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 1d
+
+LShift = 3a39f16b9975cccf7a0af2ff75f3a983fec479802a8c223b2380000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 1e
+
+LShift = 7473e2d732eb999ef415e5feebe75307fd88f300551844764700000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 1f
+
+LShift = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e00000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 20
+
+LShift = 1d1cf8b5ccbae667bd05797fbaf9d4c1ff623cc01546111d91c00000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 21
+
+LShift = 3a39f16b9975cccf7a0af2ff75f3a983fec479802a8c223b23800000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 22
+
+LShift = 7473e2d732eb999ef415e5feebe75307fd88f3005518447647000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 23
+
+LShift = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 24
+
+LShift = 1d1cf8b5ccbae667bd05797fbaf9d4c1ff623cc01546111d91c000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 25
+
+LShift = 3a39f16b9975cccf7a0af2ff75f3a983fec479802a8c223b238000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 26
+
+LShift = 7473e2d732eb999ef415e5feebe75307fd88f30055184476470000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 27
+
+LShift = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e0000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 28
+
+LShift = 1d1cf8b5ccbae667bd05797fbaf9d4c1ff623cc01546111d91c0000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 29
+
+LShift = 3a39f16b9975cccf7a0af2ff75f3a983fec479802a8c223b2380000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 2a
+
+LShift = 7473e2d732eb999ef415e5feebe75307fd88f300551844764700000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 2b
+
+LShift = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e00000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 2c
+
+LShift = 1d1cf8b5ccbae667bd05797fbaf9d4c1ff623cc01546111d91c00000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 2d
+
+LShift = 3a39f16b9975cccf7a0af2ff75f3a983fec479802a8c223b23800000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 2e
+
+LShift = 7473e2d732eb999ef415e5feebe75307fd88f3005518447647000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 2f
+
+LShift = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 30
+
+LShift = 1d1cf8b5ccbae667bd05797fbaf9d4c1ff623cc01546111d91c000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 31
+
+LShift = 3a39f16b9975cccf7a0af2ff75f3a983fec479802a8c223b238000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 32
+
+LShift = 7473e2d732eb999ef415e5feebe75307fd88f30055184476470000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 33
+
+LShift = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e0000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 34
+
+LShift = 1d1cf8b5ccbae667bd05797fbaf9d4c1ff623cc01546111d91c0000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 35
+
+LShift = 3a39f16b9975cccf7a0af2ff75f3a983fec479802a8c223b2380000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 36
+
+LShift = 7473e2d732eb999ef415e5feebe75307fd88f300551844764700000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 37
+
+LShift = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e00000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 38
+
+LShift = 1d1cf8b5ccbae667bd05797fbaf9d4c1ff623cc01546111d91c00000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 39
+
+LShift = 3a39f16b9975cccf7a0af2ff75f3a983fec479802a8c223b23800000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 3a
+
+LShift = 7473e2d732eb999ef415e5feebe75307fd88f3005518447647000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 3b
+
+LShift = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 3c
+
+LShift = 1d1cf8b5ccbae667bd05797fbaf9d4c1ff623cc01546111d91c000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 3d
+
+LShift = 3a39f16b9975cccf7a0af2ff75f3a983fec479802a8c223b238000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 3e
+
+LShift = 7473e2d732eb999ef415e5feebe75307fd88f30055184476470000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 3f
+
+LShift = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e0000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 40
+
+LShift = 1d1cf8b5ccbae667bd05797fbaf9d4c1ff623cc01546111d91c0000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 41
+
+LShift = 3a39f16b9975cccf7a0af2ff75f3a983fec479802a8c223b2380000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 42
+
+LShift = 7473e2d732eb999ef415e5feebe75307fd88f300551844764700000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 43
+
+LShift = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e00000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 44
+
+LShift = 1d1cf8b5ccbae667bd05797fbaf9d4c1ff623cc01546111d91c00000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 45
+
+LShift = 3a39f16b9975cccf7a0af2ff75f3a983fec479802a8c223b23800000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 46
+
+LShift = 7473e2d732eb999ef415e5feebe75307fd88f3005518447647000000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 47
+
+LShift = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e000000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 48
+
+LShift = 1d1cf8b5ccbae667bd05797fbaf9d4c1ff623cc01546111d91c000000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 49
+
+LShift = 3a39f16b9975cccf7a0af2ff75f3a983fec479802a8c223b238000000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 4a
+
+LShift = 7473e2d732eb999ef415e5feebe75307fd88f30055184476470000000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 4b
+
+LShift = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e0000000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 4c
+
+LShift = 1d1cf8b5ccbae667bd05797fbaf9d4c1ff623cc01546111d91c0000000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 4d
+
+LShift = 3a39f16b9975cccf7a0af2ff75f3a983fec479802a8c223b2380000000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 4e
+
+LShift = 7473e2d732eb999ef415e5feebe75307fd88f300551844764700000000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 4f
+
+LShift = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e00000000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 50
+
+LShift = 1d1cf8b5ccbae667bd05797fbaf9d4c1ff623cc01546111d91c00000000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 51
+
+LShift = 3a39f16b9975cccf7a0af2ff75f3a983fec479802a8c223b23800000000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 52
+
+LShift = 7473e2d732eb999ef415e5feebe75307fd88f3005518447647000000000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 53
+
+LShift = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e000000000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 54
+
+LShift = 1d1cf8b5ccbae667bd05797fbaf9d4c1ff623cc01546111d91c000000000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 55
+
+LShift = 3a39f16b9975cccf7a0af2ff75f3a983fec479802a8c223b238000000000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 56
+
+LShift = 7473e2d732eb999ef415e5feebe75307fd88f30055184476470000000000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 57
+
+LShift = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e0000000000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 58
+
+LShift = 1d1cf8b5ccbae667bd05797fbaf9d4c1ff623cc01546111d91c0000000000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 59
+
+LShift = 3a39f16b9975cccf7a0af2ff75f3a983fec479802a8c223b2380000000000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 5a
+
+LShift = 7473e2d732eb999ef415e5feebe75307fd88f300551844764700000000000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 5b
+
+LShift = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e00000000000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 5c
+
+LShift = 1d1cf8b5ccbae667bd05797fbaf9d4c1ff623cc01546111d91c00000000000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 5d
+
+LShift = 3a39f16b9975cccf7a0af2ff75f3a983fec479802a8c223b23800000000000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 5e
+
+LShift = 7473e2d732eb999ef415e5feebe75307fd88f3005518447647000000000000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 5f
+
+LShift = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e000000000000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 60
+
+LShift = 1d1cf8b5ccbae667bd05797fbaf9d4c1ff623cc01546111d91c000000000000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 61
+
+LShift = 3a39f16b9975cccf7a0af2ff75f3a983fec479802a8c223b238000000000000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 62
+
+LShift = 7473e2d732eb999ef415e5feebe75307fd88f30055184476470000000000000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 63
+
+LShift = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e0000000000000000000000000
+A = e8e7c5ae65d7333de82bcbfdd7cea60ffb11e600aa3088ec8e
+N = 64
+
+
+# RShift tests
+#
+# These test vectors satisfy A / 2^N = RShift, rounding towards zero.
+
+RShift = 6ce746ffa7979ce10b751cd2308402a95d00d596cd97b36380
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 1
+
+RShift = 3673a37fd3cbce7085ba8e6918420154ae806acb66cbd9b1c0
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 2
+
+RShift = 1b39d1bfe9e5e73842dd47348c2100aa57403565b365ecd8e0
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 3
+
+RShift = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c70
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 4
+
+RShift = 6ce746ffa7979ce10b751cd2308402a95d00d596cd97b3638
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 5
+
+RShift = 3673a37fd3cbce7085ba8e6918420154ae806acb66cbd9b1c
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 6
+
+RShift = 1b39d1bfe9e5e73842dd47348c2100aa57403565b365ecd8e
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 7
+
+RShift = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c7
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 8
+
+RShift = 6ce746ffa7979ce10b751cd2308402a95d00d596cd97b363
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 9
+
+RShift = 3673a37fd3cbce7085ba8e6918420154ae806acb66cbd9b1
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = a
+
+RShift = 1b39d1bfe9e5e73842dd47348c2100aa57403565b365ecd8
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = b
+
+RShift = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = c
+
+RShift = 6ce746ffa7979ce10b751cd2308402a95d00d596cd97b36
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = d
+
+RShift = 3673a37fd3cbce7085ba8e6918420154ae806acb66cbd9b
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = e
+
+RShift = 1b39d1bfe9e5e73842dd47348c2100aa57403565b365ecd
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = f
+
+RShift = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 10
+
+RShift = 6ce746ffa7979ce10b751cd2308402a95d00d596cd97b3
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 11
+
+RShift = 3673a37fd3cbce7085ba8e6918420154ae806acb66cbd9
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 12
+
+RShift = 1b39d1bfe9e5e73842dd47348c2100aa57403565b365ec
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 13
+
+RShift = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f6
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 14
+
+RShift = 6ce746ffa7979ce10b751cd2308402a95d00d596cd97b
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 15
+
+RShift = 3673a37fd3cbce7085ba8e6918420154ae806acb66cbd
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 16
+
+RShift = 1b39d1bfe9e5e73842dd47348c2100aa57403565b365e
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 17
+
+RShift = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 18
+
+RShift = 6ce746ffa7979ce10b751cd2308402a95d00d596cd97
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 19
+
+RShift = 3673a37fd3cbce7085ba8e6918420154ae806acb66cb
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 1a
+
+RShift = 1b39d1bfe9e5e73842dd47348c2100aa57403565b365
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 1b
+
+RShift = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 1c
+
+RShift = 6ce746ffa7979ce10b751cd2308402a95d00d596cd9
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 1d
+
+RShift = 3673a37fd3cbce7085ba8e6918420154ae806acb66c
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 1e
+
+RShift = 1b39d1bfe9e5e73842dd47348c2100aa57403565b36
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 1f
+
+RShift = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 20
+
+RShift = 6ce746ffa7979ce10b751cd2308402a95d00d596cd
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 21
+
+RShift = 3673a37fd3cbce7085ba8e6918420154ae806acb66
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 22
+
+RShift = 1b39d1bfe9e5e73842dd47348c2100aa57403565b3
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 23
+
+RShift = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 24
+
+RShift = 6ce746ffa7979ce10b751cd2308402a95d00d596c
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 25
+
+RShift = 3673a37fd3cbce7085ba8e6918420154ae806acb6
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 26
+
+RShift = 1b39d1bfe9e5e73842dd47348c2100aa57403565b
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 27
+
+RShift = d9ce8dff4f2f39c216ea39a461080552ba01ab2d
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 28
+
+RShift = 6ce746ffa7979ce10b751cd2308402a95d00d596
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 29
+
+RShift = 3673a37fd3cbce7085ba8e6918420154ae806acb
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 2a
+
+RShift = 1b39d1bfe9e5e73842dd47348c2100aa57403565
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 2b
+
+RShift = d9ce8dff4f2f39c216ea39a461080552ba01ab2
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 2c
+
+RShift = 6ce746ffa7979ce10b751cd2308402a95d00d59
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 2d
+
+RShift = 3673a37fd3cbce7085ba8e6918420154ae806ac
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 2e
+
+RShift = 1b39d1bfe9e5e73842dd47348c2100aa5740356
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 2f
+
+RShift = d9ce8dff4f2f39c216ea39a461080552ba01ab
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 30
+
+RShift = 6ce746ffa7979ce10b751cd2308402a95d00d5
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 31
+
+RShift = 3673a37fd3cbce7085ba8e6918420154ae806a
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 32
+
+RShift = 1b39d1bfe9e5e73842dd47348c2100aa574035
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 33
+
+RShift = d9ce8dff4f2f39c216ea39a461080552ba01a
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 34
+
+RShift = 6ce746ffa7979ce10b751cd2308402a95d00d
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 35
+
+RShift = 3673a37fd3cbce7085ba8e6918420154ae806
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 36
+
+RShift = 1b39d1bfe9e5e73842dd47348c2100aa57403
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 37
+
+RShift = d9ce8dff4f2f39c216ea39a461080552ba01
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 38
+
+RShift = 6ce746ffa7979ce10b751cd2308402a95d00
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 39
+
+RShift = 3673a37fd3cbce7085ba8e6918420154ae80
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 3a
+
+RShift = 1b39d1bfe9e5e73842dd47348c2100aa5740
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 3b
+
+RShift = d9ce8dff4f2f39c216ea39a461080552ba0
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 3c
+
+RShift = 6ce746ffa7979ce10b751cd2308402a95d0
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 3d
+
+RShift = 3673a37fd3cbce7085ba8e6918420154ae8
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 3e
+
+RShift = 1b39d1bfe9e5e73842dd47348c2100aa574
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 3f
+
+RShift = d9ce8dff4f2f39c216ea39a461080552ba
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 40
+
+RShift = 6ce746ffa7979ce10b751cd2308402a95d
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 41
+
+RShift = 3673a37fd3cbce7085ba8e6918420154ae
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 42
+
+RShift = 1b39d1bfe9e5e73842dd47348c2100aa57
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 43
+
+RShift = d9ce8dff4f2f39c216ea39a461080552b
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 44
+
+RShift = 6ce746ffa7979ce10b751cd2308402a95
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 45
+
+RShift = 3673a37fd3cbce7085ba8e6918420154a
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 46
+
+RShift = 1b39d1bfe9e5e73842dd47348c2100aa5
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 47
+
+RShift = d9ce8dff4f2f39c216ea39a461080552
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 48
+
+RShift = 6ce746ffa7979ce10b751cd2308402a9
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 49
+
+RShift = 3673a37fd3cbce7085ba8e6918420154
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 4a
+
+RShift = 1b39d1bfe9e5e73842dd47348c2100aa
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 4b
+
+RShift = d9ce8dff4f2f39c216ea39a46108055
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 4c
+
+RShift = 6ce746ffa7979ce10b751cd2308402a
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 4d
+
+RShift = 3673a37fd3cbce7085ba8e691842015
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 4e
+
+RShift = 1b39d1bfe9e5e73842dd47348c2100a
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 4f
+
+RShift = d9ce8dff4f2f39c216ea39a4610805
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 50
+
+RShift = 6ce746ffa7979ce10b751cd2308402
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 51
+
+RShift = 3673a37fd3cbce7085ba8e69184201
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 52
+
+RShift = 1b39d1bfe9e5e73842dd47348c2100
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 53
+
+RShift = d9ce8dff4f2f39c216ea39a461080
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 54
+
+RShift = 6ce746ffa7979ce10b751cd230840
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 55
+
+RShift = 3673a37fd3cbce7085ba8e6918420
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 56
+
+RShift = 1b39d1bfe9e5e73842dd47348c210
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 57
+
+RShift = d9ce8dff4f2f39c216ea39a46108
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 58
+
+RShift = 6ce746ffa7979ce10b751cd23084
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 59
+
+RShift = 3673a37fd3cbce7085ba8e691842
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 5a
+
+RShift = 1b39d1bfe9e5e73842dd47348c21
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 5b
+
+RShift = d9ce8dff4f2f39c216ea39a4610
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 5c
+
+RShift = 6ce746ffa7979ce10b751cd2308
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 5d
+
+RShift = 3673a37fd3cbce7085ba8e69184
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 5e
+
+RShift = 1b39d1bfe9e5e73842dd47348c2
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 5f
+
+RShift = d9ce8dff4f2f39c216ea39a461
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 60
+
+RShift = 6ce746ffa7979ce10b751cd230
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 61
+
+RShift = 3673a37fd3cbce7085ba8e6918
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 62
+
+RShift = 1b39d1bfe9e5e73842dd47348c
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 63
+
+RShift = d9ce8dff4f2f39c216ea39a46
+A = d9ce8dff4f2f39c216ea39a461080552ba01ab2d9b2f66c701
+N = 64
+
+
+# Square tests.
+#
+# These test vectors satisfy A^2 = Square.
+
+# Regression test for a BN_sqr overflow bug.
+Square = 4000000000000000800000000000000240000000000000000000000000000001fffffffffffffff8000000000000000400000000000000000000000000000000
+A = 80000000000000008000000000000001fffffffffffffffe0000000000000000
+
+# Regression test for a BN_sqr overflow bug.
+Square = 40000000000000000000000080000001fffffffe000000004000000200000001fffffff800000004000000000000000000000000000000000000000000000000
+A = 80000000000000000000000080000001fffffffe000000000000000000000000
+
+Square = c2fa18e1d110a4639781
+A = -df6a253c3f
+
+Square = 4805f01d379f4ce8dc86ed269
+A = 21f253ddb5a6d
+
+Square = 57def107babc1c2bffeff858947e69
+A = -95fbaee5a09c86d
+
+Square = f3b01f7941961b3f5cc3361e3ac82423690
+A = -3e71292dd4ad3ed3b4
+
+Square = 5e2d9c36d498ad1e8b6113f442ac513eaca74601
+A = 9b45cf6c7a43d910dcff
+
+Square = 7b7c2eb3fe55615e422b41c6f725341527626398cdee4
+A = 2c7314e72a2ffeef170de2a
+
+Square = af57c0ed328886642ed5d631b375fc89c03a99f1b427c6bbd1
+A = d3de077f8286a04daa9c497c9
+
+Square = 4d9eac3058e6cbc0d12e639ced961c02ec1870afed62fdd44c67ce4
+A = -233da7e87ea4421ee8fe7e00c856
+
+Square = 83c292d277fae28cfede74e8e80eba11dc132e16f78cdf64595c12c7dee4
+A = -b7a8aa7452678abd45d2ae6c349e2a
+
+Square = c80e07dd01f9d19a5cf7f3c328ccf4de70fdd113de69382701294dd29674b9a90
+A = 389387eead58fef2c76b5cf920f35c5cc
+
+Square = b9f69ca47ac855830fd7ed39c81822c520880c51c3ea60d3ccc106db37fc2b04c47831
+A = -da307c28ea67ca8d3117364ba93f0731bf9
+
+Square = 81bbe3a13a22a73778233294ba0c132d9dddec111f768300f177468c204f8eab69b98e62d99
+A = -2d8f715bb32d410b4f475c4d000d56fec7cfc5
+
+Square = f815ce34e9bc2e31e36e75cf49b2d15306d438a2a713b2a85b3ea156ba60c867c28cc65aa58fdf11
+A = fc02f2e1a26cd69f6a0e54cca4bbced739b43597
+
+Square = 5f968707f58ea15c492ec9677be09c309d91164aafa754ab16ca47a411b5b2249858fb6f96135992e8a04
+A = 271b8eae3e96cc4900d4413d6c00b73736a5d89ed7e
+
+Square = 4aa616aabcdc7ad48dcfd40d71e00a3789bbf549ff39b3e2ebb52017cb56014941961a5a6d52d7a9980fc99b49
+A = 8a3d3f15e6d7d2130aebd8cb99767defbe4c7704e3c1d
+
+Square = 845e46db8c40f3f6f6f4928b5748618f021f9064c6522bcf2df004f8d2105e90cd354785c15a6cc32fcc77da2ea3001
+A = -2e0543ac8b8255ce30253cf2047a0ff353dea55a58551801
+
+Square = 5dc5706dde9b326feb79941f08bd296ec3b6fb67270516b70fad9921438b9175f395310fb756b60d72d8e73e84ee8673cc40
+A = -9aefd7dfa709dec9e721f5c22867229435b2d6366462d0e438
+
+Square = 63dc6565adba27974a66bdcc626596e16cf399541d679f754d9063ceeb320649bec09a940309dd1eae5fbba0b558939afae9689c9
+A = 27f8e071f70b0053d70eca9c6d1e28303b8da2d3c58083c2cc45d
+
+Square = cf2176449bb8b215fc37288b904ca27d5d410780fd054d2a190a94b405f6aa41970b41ba3cc43eaabb97c2248e1e21457949070ec0f6a4
+A = -e645c7edc27512d4b3170d3c5430d0712a25c13afcc09c9b30bb11a
+
+Square = 43194e5f12e828db6735824c194985108269ddec12c49a14658be3c2b7d298c2846da1aa3ecb7064e73c317af595601de59035faab6dc0fd911
+A = -20c3fb73a03217893fd4a9db6e53a3d83a8414d900213d0460dc91bf69
+
+Square = fcee79e598f061157ca9416491f2eb069bb95a4d78a1d0538dab5c8008653db71b90ce3139e693ba284846be7b75d6b7aa80228420fe75599c12f090
+A = fe760dd61798c8f78e52b328fa27cfbe41b898de6e6bb4f4a684f038b5f4
+
+Square = 4f0db9f9e6eff9fe7fc938f6d6f5e4fb017ffea0cea0f7c57f4fc1e5b2bdc00a1cb9c1e6c865e53309b6b73c4339b0bd485860ca9edde3019804902da6b61
+A = 23909968dd5d139994fe9baa0a7bbfa009b013df3859ff294c5872366eb7ecf
+
+Square = 4441ff36d785d18208481470a5b8ba8cd65a45436c39190dde0b8a2b7d00bf67b185d98ab5c4a7853423778d6333abf6b115dc9567a9f9c71916d3f9db3af82c41
+A = 84307277f79cfdf33d83d7093f1fd8aeb94499a7075ca32733b68fcf88e819421
+
+Square = 50ee0dba369b0fb61d75706652487ca08043eee712ebb51399122353f77f13745ce2ef0d8f0ea7b3fd94e928b0b2b42c2c9141b5697b13b6d1f3d66c6a9186625b87e40
+A = -23fc02d45c820c3a4250124cc457fa3886beabb41d3c1e26f711309604eb253c6da8
+
+Square = da11876b316d4891a2d650692ca776f77afd32a1db08f591c9579fd1053a4a46cf78b4e4cf417eb99eb067ff701dbe3483dff22e7878d2ef2b234244cf7a29d93f62d6d6b611
+A = -ec463653389de3689fe1881679b83ca65134a1498a3543168dd4833a51b23edd3fb617
+
+Square = b342b4aff7e5bad38f7f532f0f32a3672f7ea6521d23652fa09ef7aeffcffe52f056ab1b54a0f3a2147f43330fd199d1f290988c866f61360dc4928c84b3dcde8f395120008472100
+A = 358e27805e2a56195fab2ccbe3f931a4bd14023ee56c8a191697926f387c40decc578cef0
+
+Square = bf4045fd680caa514e9c410fb4404e5e3a381abee023d5b509d6dc0b97386421f55090af8bab5ac08e9b2eb8a36a64c55960be9179d564c5429f4ec595d03d12111defafb7359b418902b1
+A = -dd450a0fa0914f0d65a1b555baaaf9380eaf8d58b272bf9d95435bad53b01337ac8de562cc7
+
+Square = 86abcdf183ca059257c2f6bb91efc9853f4ab42801d3cde88df72d4c904be184e93d6bd1af6fc21a6836c93c4e0a1f728b3722d568572f7ade418274ef2e6ac3463c5cc50990f1017e01cfb91a9
+A = -2e6b4d9eeede7a72b8d0fcf6429c7e30cf291352e1bb43e92c14236716aadc02c02f75c7e6aa8d
+
+Square = d5f37112733b097cab2bb11daa3d9481255060abd7bce42b752a7641a98e140922c375fcb68bf13d4326b374eabe3b01de0f8f6324b7b3e4142051c02d2f18ae2e748cf3c4bcc3fe157bc94227631d21
+A = ea087236372fbb01b80e57b1ae4edeeaa776355457e18165a5dc60ef4b6ddc0b127ef494dc44ae11
+
+Square = 9e4db7885fa5f928ef236f99df3e7c8d17a5a21983ff882032817edd5658575f443eb9c5c97d95ee798a3809cda76d7a0ab9fde757a310e2f5cbb299ab88e92a5771027ab9f26816c02d0c97894da5976ec90
+A = 3253d712d4ada4c12dab41036fcf79b02e80d1a632ff6ccc44d3c1d08467a019cd6221507459b231c8c
+
+Square = cf9c50ee8773ba94c9e943989a35513fc370adc3622beb125252bb92ff9b258b81a497700e3bb15bcb23a5b3082c095f7a5d6eef20433d689c20a5427b661d43fb0f9b7d1b16d1b73b8fd59ed319a26c5eb92fce90
+A = e68a0812d2de2a922f24c4e63b4c33e62f93943b7673e900d12405dedd0bc2a906daf8b4bc336bdeb52b4
+
+Square = f3aa49c906844692d3bc0cf101adcba80351c2e744be01762a8c24804a9d8d5a4cc3c113ccf529eb79cb3304aefa74178afa53f235c5211192d4cd8610c3b42e246621acb3e5d1f9d86ff39a20a7fa9c568356de5b86919
+A = -3e7069ce11472563b0dbeb9a936884df66db83273a690c40e5d3b5f8926fb502d3988591abfaea7b7bd76a85
+
+Square = 7c9a5057ca8095cdfa289b2d60eec80548f9ab2f3a996137ff9be403b529c4672e003d1eb074c76c0086e3d875cfbc90a40ccb61b799cc0401ba160d8d6b6ee46b2f14ed31c83de54cdf83458dcfc01e3234d9717b5f2c7e5079
+A = -b299da84ef84095d8191fd1cfe847b960729a3d1857082f05b2fa30ac45e90d2fdc778013b023f38db2c8e780b
+
+Square = 488294b528e2c2da0145217ec69de2d021ca27f145f7321f06c03316fcc14bd4a9a900bd6a144086acad6d5ad32a6245f5a655e007742aa336430c6bfbe174278884d19fd93916ef57215069268ade899cb92dfed29628327b84d8240
+A = 220fa6eaae0238e78a91e43fd8c2fbd5db0c8501cb96d66265c8edcbd376814c39e4a6f21ec9a6472c6abe8c04818
+
+Square = ebd685edd991dd5180706b72ce20ec4f6c5d9ce038cc8768f2ae2d0e676bd549d6d3f97f6c26f6e36bb664e8a7e6102192bccb354c024670085711db30159c6b7badab7c7c0b91925675ece3e23126ea6feaa28e977598a890e4e476ead100
+A = -f5b657cc38fd11ad2f1b188c61721b5ec6c9762c09dcbfac3edc1f07e675bc058e77eacd01a2b4139b1b00c40a6cb70
+
+Square = d1b3ac1d7042c0200f80a989e053dee31cdddc835889a57482a0988afd82b0fe8d3667270a72967401c3e8d80dae349ccd4063f11cb24dd7f9a5aeaaa7c0bd7bf7991367b0d7b4d374dc9c5017da81ba39fadfc3b760f68da95ae1eaa2eea3fb040
+A = -39eca1bf5e4807fd6a9ccc9e3138a6fb390b10a330f0027f0ba9868beb77c93160b623de58054a4522183fb3e4e2d86b08
+
+Square = 41c5e4bc851d48673e0a16336f0decbcb59dad36959b310cd1a042d24de00c587db47058c2d91d7f9982bdbf470c73f86e591a122b3fda71796e465513e10e3cdbd5e6bf035595644d588c091e23a57cc47b5173743b0dca965902918d61875f88735a59
+A = 81c2caee75e98f1822c854448302243feec55a5247bba948647f12d7e0bcde4b1dd6af63eb1ef948eec22a87d2f3213de75b
+
+Square = e712c3705ef2779ec997c430f1f8b7689d7edbf2daa733dca89612bcb298180b882cdfe8e5cc1104b9f5d6d8f0978b46eef4f297dcc83fce4c39821ed3205e399328d69ad484d8b3189e207193203ef79b763f5e11778dc24839b4feaab291a0464cc66edbe10
+A = 3ccdebe5106ff5642b4ac0751bb799c27454f904fb72863d1055d1412b2359120ad196b768f6137dce4cb85cd29a990838a95c4
+
+Square = b5063c05ac122d0d4b1e0d15c913f70f1309933ba737fccbc02d13a6c712e7b75fa757ac0e4fbe65977f17bbefde31c8fcf51f867a698233bf25bbdb1f03c104dcdbf1173886a48eb5a8b4d27cd841196de0b53466a3f1d28500fb4dbcee8d3458662443eb2aaa5de9
+A = d745c04ed95d4090ed66784339202f9d0e57bdc1a6f6b6ca09337153f0236cdf99b61db85604791b3a373885210f6aade8530c8d3
+
+Square = 974463573c968f1734741dde2a800761fa749b553dd6499b920d3af9bab73a87f40c9cad39c51cfabcfa0895f1970281af063d80f89f4103624a75bcb0d23f5ef6c1cd9a10930118e1459ee8732728ceb7961f7d83cd2344a51e6229fe708bda46382e142706137facf7161
+A = -31323f98f0f73fb66e541471774ce0e0fff53d69b2b726480b9ec7b0775b345ec4ec57c4334ab8ff4b388f4c7fbdfa3beeba0f3e0bcf
+
+Square = 673a62011d769ff0333f69f10f00b28781fece47ddeed25fb0bf4f8d95dde4efff60690076aa520ebaa3ba63e6d445541b9586241141ecc37cd75b178389265224533055ec82a393e5dd61640d3f442adaab917c8fee1f8fc0ff8ca8d577e1d2d976c2a8b873f699aa92c272c164
+A = -a28fdafefdd393f993a8fc1ae321e420451dd0c5071410367d5a911b2a3a668bcae4452e134159e0b1974505f99865cd97cdb020bab0b6
+
+Square = c4f34585a29667b582a3ee69b1a5f6c04746d105a57bc92763958c5add45c64b5c1cfeb1a321fc5194aab818c92ede5408afae0a2a74ed4c7757dae0bcc602169a805d525c5a63ca97391a9a7987a3eaf04bc44c89547c5d312f7193fc571851b1a8f8f091849f649ae91e15a050f5799
+A = 3822b607fccfbf0c5be97d4358bc682784e6453c71781fd3eef9d247485211c55d742279a35bf35e64ba8ec8cfe20dc0889688e2bc81fe0c5
+
+Square = cfdf0eb68dc27d60840b8afa8daf96bf831002dadb2801c5d6f7ca558256bf3c7c5372fa00f2b3e300287745f8664dcf8e679fa35adfcac93839cec53b349553f31058a4db05af40b047bb367234dd78717aaeb80334f0deabb09d2d4d90394ec28cc3589b0aa78cf227ce8678b8bb5cd775e9
+A = -e6af13779d5a5eedfecb7c4d34009affee1f0bb65934ea9656ed6eae02271ac8a29104439000650a3a8cd7fecb171a7154c0e2bb2b1cb908cd3
+
+Square = 6ec1b1333481c37be059ed7e088c862f869bb559b34360781f7263eeb206a210b90321aca198aa41c2a79e3a8d7df4336c75c87ba2ed4b02052a07b234afd9d2cb55413d4296645cd0dc8f987120acbc82fbfb089190f50e55eb1f509c86734dc14b2e8ae42ce880023dc7a014b02727b53d0e5f779
+A = -2a18acca3306bf06fd90da4ec2cbce995fb08beaec6d1cf4b30694d682c83e04b39f9a569eec52782b9eda7db0680165c77a1b0f54a1b995f8bd75
+
+Square = 5382be4ee86b9d80dc2d4ec58606ac538ba7074d57e2011346f0dfb9a9d6677fe015e4015ed607906e9068a3c5601f0bb77186a9d147416ac68e344318cbae5c70c437c5e1dfc2d6c3c8725198937ac2d8e796f749bfe95c7fe6d0e460a633be2d86462d48290a2f8b344ebcda2f6ad353d6fd5f3355d819
+A = 9236f7ad22da9cdd8c187082c630098bf3a558b04856e876433c570a63d39863416c9890dd089f7665d6ba073b2ce90f88e7d04af96f1c82287903fb
+
+Square = d68e15e8a46e001e47022daf63d2b33fee0f9d3dfefe9d204b0de6daea31dca4b287a60827bda9de2860c433b77186aca10bf3ac1d02a204ddf8bf070c3c20ea69d9638a865c8843e8e63211951e10a844f8527345c5bb5417e3301a19c929e6fc48902f0e0be8e393ecb3fe0e9de6188a72d102fbae846d05dc1
+A = 3a973dd50d4239f05d86ba25ee6ca8f8ef46424951a8bb89e7d1d6e066d6fcbabb3758ad9e1647a440e51976c0ce628d78b59a4d9e42fab0c723182b31f
+
+Square = f03a448bc7405d2d54c0ea1a9016d8757d4af893024e542df80fcce448491d07a4b451d67c9e7d9a6c7c5a6155bf156d3cdf8103162d8e0265111655fc0ae46f4be944fdf275221b217274357977abf64316615dafb6ec84c5466f617c4e8d9ad4739f3e5050e583892db75366a4a7d2c4558436ed036a79084c7f9100
+A = f7fd0a9634d14d540daea21c7b804d37de49b7c13bde85c045859ddae1dd3142994e385f455becb7ee30576d55d4dc2f3d9d82e86032e170da1730b2c8a90
+
+Square = af945dc2241029744548517dfd7858d42097076b06427419e74ab08071a23aaaa1f5daa6290287ce8e832a0524ba5581d64abf054408ecf6ed21a4f8289c1e4c7a8087384d268a1ccf7ed40e74922a619b5c1f2c08d810065710046190b7cfff33d4f67e58927477500eec54ba4f63a57532ed10c6b861fca9d46bfc3d32640
+A = -3500a8b6d244f1a21e10de7cfbeeb75d57ffa62e9dfbbdba8fe93d17488c56dc89787f13e660d0d7c7755242f8412d00988bfc7d3f6704782324c48691e7ca28
+
+Square = a466e34dc7875aaf945c088bac23f3347a41f7cd039b0c9120c2517ada94b96bdd72d7c9bb55539af12931a3a39f6e09a4cd4311fba57dbfcc51bd17b03905e2560275c8bb3d786defeb131a634e86ecb793867355b048dbaf2db8b654a4d50aace6bc9d60de6934ce25ab58381f6ddbd1c063652e283c30a2dcd61d9d776d60e209
+A = -cd26a0c3d84e83d9f14dbe95cc39e3ed2e8861b76f4bf55ab120ea636d8f9efb0b6198986eb52075108d0a5c6ae0ee762f834f3db802c3f20bedf938f47b8bfb03
+
+Square = 9f3f4d5110ea1bad21fae923825ba869a9982b753284f1946edea19f22cf0a49485b9336a2af7df8bf2641cb2083f4dce82202162d85a5779a4394213bf3bb3e47356bfc1150e66ddb6cd945092c9af14eeefd2d08b76c5e4a585ed8ef39202c42dbbceb25697f22f9508e7d954d3c1da103818aa6f63121f895e2c26d3d7463aea7ca749
+A = 327a2f6607c41ce920c14e9c9e8a059a931d71aeebc3e05e93107265a2810ec286819a4b2af9d2b70b754bdab6022b10ee6b81b32a7382cee99fb2bbcf6fe85af05e3
+
+Square = 50ac4c46f2014a7a382b0d5ec9db4a67f34ffe9fd5410995810d3ea8d7d87d47442d0253c7eceb1799272bb5f5e7bd63174959f9844e5b4b65b6a4920166d83d01a5c2638b4d3b6db7fed99e28b9128dcb7c10be539114c5887842f8e5a7fb743298ec9642e50bd0979156cc6aea9ce802a0c1b14a2a1b7afe28dba534c9933209f14474b6e484
+A = -8fb585e01a0c62367dfa8a1953e553476b1564e843bdc2c5d964864ab2da56e0bfa7f5ce5b7850398451619a061de02ffbe0c336ecbeae818d32dcd40355fd11a7a3822
+
+Square = 9214e31bb62f62a7f92d6c7f1453bc4430595a1765b7223a1e50ec30f934908c19fe82d7bb8ef1174bb6787aba9df1a38a84203630ae9f62e08fb4ac55ed329282315937d193992e9e12adec9727ef91df5a065cc5858062c765f34bd2630fd3f654a8f8421b75dc384477744efef3d6f0d15820c9328bf43a43409f6527dce48a92c3e1ef145b5e284
+A = -30587ef092cb9456caa844be9629d77ef1bfe21d2ffd5625ea353beb1f294e38a7fdddd5bf77cffe5caffaf609b8976756c9eb4908ca77b1630ac0d706503c46177c5d905e
+
+Square = 54bf52644a244276ad3dac90661a1e21468f23a117a1fcc904c66119d86ce98a0b90fd4096708bcefa7a9df87c6bb85149305f193cf5505802172ef9ec343f662a4c895a9d19edeeed5d91e20abc894948fe59c1869928616392f3694d82aabee325b651e1170006ca1fc355212308442a5ec8a8fda4f5f90b7fef2aa731f3fe0f028143ead04490d78b2151
+A = 934b16f56700b455d5791ee8c119b5921976a829bb5d1fedb201e63c9ebb82afe4e29aaf0ae27148e4d34269c48dfa42131cc8b3b78e23ac3e7292eb0d715247a345c800f377
+
+Square = 63b7884fbb6d5521c38f7deea5cc131ec6bea15a362322a8e27c762880836cffb69a069a168663908707bee9d83aad41c045bc84dadc6cd927ad62140f8c2fd001d34f0a7462bc939cc8996e17ebabafda95a73483c70191311a6fb7c670c76c9e2ed7e589e464617888d30cb7793e91672d7de9b3b4b1811b2c009dd1c690d44710bbab832d91f16f9b3564a0c49
+A = 27f17f0865513350381ea1aa1545439fde427ccc64385979bc787cfc4c7e6b624b2c77140da2c4176c55dbe43c506fac14b4cd7815e87f3120330dd3003bee087a371f85d6f4e9d
+
+Square = 9d1c4239accb286c3c7868ad3b4dd97b93774fd0c65e04ca8dd405c0298ec6d1f52d60be6ddb5f8f0389cde756b49b23dd2f0de568a432fb99dbbd40db798261d1dd39bf5017e6dc74cb9ca91f8b2f892c7eaa28485c04a96add206c7c38943912de065be17b65292db5a144f82427016b5e0eb4ded2e4d0b7d12b01cb0b2b61e5e1bf22dcf1567a8b149cc0ef5299a8b1
+A = c88cc5a46bc1cffedad4f45e66fb55dc4347eb2a24a09878358d40fbdb03e738ca1d54a1d26a777915248fd730daffb0d3b5305684709db0f258f581fde06b11a33a3f76b3fa53e39
+
+Square = 789545f15fded8fbf0b4275cec30c3ac65eb42ab8cc75670fbb2ab0b4cd90ed41a1290383b5f14bf87a88c67ff1e04d0f478fb11fefa64e86eae5777855ddeae451e166e23ec30227fb4021d51ec7cfe4ce531c78ba1bf6c797dc73f093b0a5a5aa59ad8de3234808e776d690007c8c332b3f03331dbdbb8645b91552091afc36c28c3229220b1a7966c7cf13db6bdbd4673440
+A = -2bec94112014c1a506417e659157192dca1df58f933510d7a8d6f6feda5031d799a66d2746c09f827199ad9fcbf11f323a636feff5806c9fecb2ac684c2870d60c8a72358562c4eaddb8
+
+Square = caa64c9f6bd66f76c99604d1f2b8a29a9a10c0d6a41cf32b5bc40edd7a1d97b295c63aa62c30498f15d70e427d5612ec3f6a2c1f2997fa9283f48018435fa6092269dc2e4ad524cc6da9689302f5c398d79e2b2d19470ea8240db9df0bc0bdc911c4d53f4f24a7ce44ec76378794d16d367434b4f8b6184c7651db77fcbebb8fcc5d3a51ee9739922cf20d4a8888139fe4669a164400
+A = -e3c4a10a64b7e67d786aeb81bb7ea14655637ce963f46cce59bc0cb6b5a9cb9c92afec3d527119db97bd2605d315cf28198992b4b2206e5616d3c560bc8163f56cb1f5626a7ac6d8427520
+
+Square = 429e4283af7f895fe732ee88e4904348ed01bf579a93cffb7aa8e135d41cb9be218f8b9a9cb4f556124105cf042de51f34c8162fdc7a981de88e005a014149c955068e87214c174daa40fbc618c536a6e507ebd313763fba197059d68c69bd39933d614b2c32f235cc955e335c4a37b9e98cd7f98c7f26ea2da932c7f82ffd95be22a7741da423123f8908cb188abc26afaf4ba6d47b56e11
+A = 20a5e2a911627544219a1639c3321bbcd6192a32129b248cf62351f85b7a719cb275a4e44368a74f4d1a307ffd27ea2cae4d8584a57070609a30fb4e365564908f3d501b53c1a54f0e37745e9
+
+Square = 9bcc8d423c3fdfaaaabe24a910e6ac3619eaa15e23b9f317c844d39d164c952fdf5c4bd270a83f3902e54d3817fd78c96018a706c1f652025dde0b98afe35597e0d8782deaeed23337ef6b3edc9317d54e3c8a57e4e7e2695f9d2681bf82927bab193ca1f135bd0e542696772f08520faab61fb4ea6ff0d15bb91f21e68bd7f084a6b8f24a47ecc30a779ee86610387b29a1de94de517f81318001
+A = -c7b60f4c355f2ca3937ba3c124eea2cd8d3536226a44afcaa3d17abe931c09ccaabf25a1986b172fcf46fb02a0fc36f2c163b6e42cee047c54ab05e9d30f03f6943b9fbab83aa6da12d7898c001
+
+Square = 45df25540de94883dbc182009c29fec43627d3e5758e6a07cf40064e0befa0df184528a84757b445dd079c2b0feded48b651ab18b4bede2a81796be45caad0125c3692560d19cd9a6c8c0de8383fea0bc1ab46f6aca4e9c36b26575cff88fdf1eb1e13182308295457374968fe3a9ca34c6acd24c753fb84d41246614789dfe154faf34fc684cd15035dc9c1c6b0ea171e089e0f3236840e355bd123ac4
+A = -216f8a9a3e54d4afadf368c2693743efd3eaa4cbda7a87cd07f5b1a713eefd2548343e7f091ee4d9d6ed1d4343c06a0597db0eb5194b91bf2c858210557a8288c1aa7b0e0607a24dcff9de04146d8e
+
+Square = 5cc707d97eb107c5c40c0f19fd432cbac9855f280082802dbe4deb45bfd193ac7a9149fd12c4ae6e9282411e2f1f2ca92135424f215b800634092ed4ff2859d16ab9fb8619ece41b50f8888d3e13773d38789e19158e18396096dd57fa5470f50b391c22378d980e59b4585f013e6db52c1e24c14ad83262fd37d42f52323896f7d4cb3e38868abea8a07e7ad3f90512eea001c5147645bf00396cb0e7a553f1
+A = 9a1d1b0beea76e7f32bde9f4f2c8bcff9094db2d32c04fb7ff43624b61033646e482aa0fadb9f8b4225b47121070b4ee5d6818d3606ed775aa631e0ed42da68c2a09dab26b6a4d09ac226cc09321fed9
+
+Square = a32fd053eb90c365e77ff47573a24add3b25b4c301f4c662dfc1fa635af8e18e7947381989b37a9c9de2713ca438b9f85890b7b160fe251933aa7dad1c3839d502debb42ddc927fa0e9b40c80dc3d408889be567699a856b1c9cf3a393b3b818432e95feea825c17d0981b942236b3779f2acaaccaf9a5817ca47bd03045fc4de454d8f1d4377e218c5f7ece369aacc35369ab57a71652dd42621491834119afbe729
+A = 33190b787a2c3327b122d1f5823bdee5c93b19b586ce1bf79d801a19b2558aafc8f6274d0908bb7a8362f7f71d3fb52b8ffc87d458249caba7af3a516ce868e8a620e3126ad43d6aeffee11866fe77677b3
+
+Square = 74215d33fa398e21c34034af6f9c7af6a3e01982320ec8cf23074a938f1a31543f80e6aece01de247668fe67f276cb4411db27666e1dc8fb2bfa4eb68cfd3563167d1ac4efa3361f920d8dd0fbb7f06362167f5ab5ecfb72956c20db934f67ff1c75aabb594c853fa61f43d219a3f5d0d45274005e3b167cfff5493b0f26d15f85d8e906a0a6e7645eac1f40c6dc637e6d1e061e5b9071a1227469cfb2c0f17ff983684100
+A = ac6c0b9c69785f35dbe244dc85a54313ef836ac67c853531ef5db45b28835ffe61dd258c5528b0acea50f5aa5c0f5d08dcb8d82ee19bc432fa8a45badadb50693fedc1cc79a17d63aa73fe9597f1d4ce8ddf0
+
+Square = dce5cac967c47b8a58ed6f1bb1d1e6185e849400228afa2bfa05b9c2dd327b04a86f2a4da2d02ea102868ea0c4da0f3e5a40bd02c87a08aaa5cd8d9358b3a5ebd8c9fc2dbb1268c261f46d6717b0307b993deff0adc8190d32b4f2bf695eb2cc74a6a9a712c5a621c673219ff8a24ded0997508f8f9eb1ea872008c46e71fa97f55b839950e63130c38b49c0ce3ce724a0e8faa9738d2e28ce6e7fc7eab62b3561d2981f314f751
+A = -3b735400064b15fad81b08362b8557f8318c20656839ffb4d2513512015036ab0039442032f1cf515f8c10c9933afe4206a2f309e933d1561b06bc665af2f04f4d064e073eed2280053f56cbeb137a9482c0a077
+
+Square = 6b619bcaf632f0d8b1d715e8850c0cbbd29ac6373a9a5e93dd1bbd2b82744a8a50a7446b48c6e215911ffafcda9ed7becaf5d26b7d6df7dc8798d53239f62a482f974bdb654750def1c941c49a24fcdfcfe73881b556a7b528d88daeeaea8d62b357211a1946c81cbf0819ad8d0188f60aaaab4ea2dfef7e9012ade7abeaaa4a23d7403c1248c36aa26b43b8e7de8a5aea639a0449f50359e9b4c1b125a548383af33703f8dfbc2528e4
+A = -a5ccc69663a8712c15f96e6fc746252af89a8c2a6317caef905dd2d8a6d4fe878ac7aa66cdb3c3721ba7dd36da310753dde9801b31d759339ac919a464ab52541bb2e0dc938752bf0f1ff7a9524eb98340d62576aa
+
+Square = 77ea5b715823045afe13d10416dfd46a511141a7d1279ebd624f1de428cc04a4f246246e65c3f84344cebfa32864de9264b2e54d4b3010c4de9d3e6a27aae8f5f9e9d8e49fe26b73ac7e65bb216aa6a42db36ac03d749b5dc04192df819631593202a58264714628686507fc5655f169483b0ffecf45995cbc12faa105895564d287a9f4b220947d6c93786c85b2ee84a0a29183483f7c241d6a67fd0b1c38c7f74421355a14c6d9ed5720e24
+A = 2bcd67e6bde3f54c4ce0ea428418fc5c97272217c6c7de90549238ee322810dcc1bb9385967673aa3f9f5a5c05d987c6445135cf1efc26b3c17e55b93cc052761a77c9dcb5c22927b09e90a92e053ec1bc799bbe7597a
+
+Square = 40d113460ca3e70545bf3613c2ba5de5d8485641ebf531a43b6b8bb76884ff4f348727ac6606e026981d2116ef1e60d4b37b44ed7e2003410d7d636b58aed2f92e962003f28342aa5f059d23b3d58a1ddfb47833ffe1d1deee0a7e78b8f7d9d6487f22376664f1ed9ddb5ee3d17f43afda296bead11680fd17576a122c2599fa9802ddd84a2115f9fda03aba898f66e303895f452077c920a322b6aaa0965f51fbb36f01b1d412c6ccf390da050d24
+A = -80d0699a46619db033461aa6060983def7deeb976d1a71f5c6ddb85e8b46dc70b7ddb1d254971d38ca87c7ee3905e63506c6db105dd683375f4239523cbf1874069266c2c0f4b37edcdd261c51088081d25813758bdbfc6
+
+Square = ace99f98cba0d1dc1c758dc7211aa4078a2aeb6d3fff19bdfa6981ded0982b15bac792e6b542ae48a86f9b40c6de937e402e230fcfc390b10c3e60202dee1337ab39da7a342999487b8d8b0e494f2809cd1bfdb39209da5daa590f78ded211b6bbd3fca9013300b951d8906c9ce8d1c0dd9554d5d1d352f9784f822c928dd9700ef8a5fecf3771966abb1dc6a70b301461eb6b6087d6ab80a4b624205489584224cf6578f75acd8091fd621d02306504389
+A = -349936d60c9d77a0974dc8985930d8674976db6b3cbaa067554ca6b30b1de33f2d4e1c9564ce102ac6387755aabf42916f63632a375d995913f9d45ebda54bee3fdb7cedee46ebb5c8ae7764e4de323c17c797d3b529230cbd
+
+Square = db6c73be2a59bdd35dd312240aef18dde4231c72aa28551bb370a87dded587accec2279bea24c930236f06f24d537fcf242497aafcbf72f085fd3ecf030cd750fb382efea0f82ad9d3195680324d73fa99d48802d085c150164aec0d29fdcc3262264bbe72311f89989cc71a4afdac6ab103ab4fbb6e973a42a1f8711bee463d198f727dc7bad848ff8fa77cd3b2f612d142ba46e95bd79a86a1fe4c2b8f9181be84825d05989695842113828a83b826e7d2c8c1
+A = ed01dd49d2e5d51fd30e9c578259cf107771b4ded6bf21f8b9b632fd360e34da740e0b1af6b5a67789fda5a44025af0f1547271ca8accc7a975d98ea7ec3d41c9697018d84ffb5d49b88d884ccdb011f715a199ddc44a4109261
+
+Square = d6e38250ab89ffe11abaf8c5d07ba11e9053f1924ee1228f834111af16ed282389d04330cb0f47dbb186dee577aed82878ecb065b759312eaf167c4698eab5ed03a8657341bf5fb14a8e28e3b443a6b657c1f4379ff2549498a33922ea84f1fb19d10866fb0ad07ce1cc44c93cd4d9ec6bbb0e61c797750c6b5d7e8d55499655dde112f4747798f0e985fc2b937a44da9b04c2dc4b0816cfc57da1f80179db653c1ce287e786ed7eff7ad6d1383fc6de8c941d4af7bd1
+A = 3aa2e696ee570160b2a869c3f21c3f223959a185cda2274feea1c829af2234c70a504c959bcc49fe0313f4f5ffd27448e28aa0fc6ce24f36943d334c626459d7e6017339e787ab074879ebf697a93ad93835d69ab09294d007a0837
+
+Square = fc39360cc0fe040b6f8340e0728c650e5e74cf1664f7b301e79986fe066f36e8df34d38d1a06b74a1bdc76867baeb3f39a9161acd200bc7532fa4aa0ea829377659646f073db82ee044279ae5fd797edd37d3261970819589853cb320887a085c4011c23d0da9b6d6f1b5911bb3399146c2912a967ab3b3f611f0bd52e00f418e6a6f0297fcf5c4a1f71c6bb8cc8e1c76694bb7301502d1d00c8b6c05bfabbf5d350590561abf3e2b1a82e98b56583e2e4e25cf707320a0e40
+A = fe1acf3d7b54e718c901c53f365894c22c8bb4182fee8a4c2558731e01e1519bfd1bf6e353483b8c4219453fa66f06063c6c99050068c15cd13cd1648ffc42b5badfc70f6fd4a0a5552fe637e54c4f92ca45c60cf9a0163978ac08d58
+
+Square = 9abf1324ef65c726330f64643a024c466fad37604f4dd3dfc404d31c2a430fcfaa0c78283666c15a094d494b96d3c12de6e29a34d2c99f4f8cae8217bcd2a989d59807ac68c46d60600238a86155de499eeb35642d0f581045481b40e4f0a76905f9b6bc5b9585f77f8410b99333f7ea983c3f29f3fe66ca7b793b784a5a6a4f74512aa4385dd1e996832b1f41bb3af965be58c4ac5e867cdf8dc6a4f9d20a6f1e16e153fcbb45ae5fe8a798cb06a4ffe467d6b6aca2b31f335a344
+A = -31c243593ea611dffecc65d1439db345b2e89941113f9792c91a76b4890db6e4dbaf1482ee812e295d27956e48d07a14de38357f15b5931c5cc08d1d248df7bfee1cae5b5ce98984c5043a3e1a2b449ba1671bf1cfef91011e12bab94b6e
+
+Square = 66aee3e4f43c672e0478c76e2092bef33e7c60afee5d4c7defbcc5c0c86d8fe956c90a740cebe604224cc3f518463b1208699b8ea2316315474991d0f120ae905a67028492cf46fff2ae244869db2a02d06aac6ac6eb054fb3c14c756d8a3e7ca64f06586e3e86e4477f185ed527a8aea6a3c741f3fd4b64a2ee77ff140190260c431cc53f411fb227377c02f85d0258a75bf6d44dccbb8bd04ebdafa115dd55b176b6eff5567e5b1bedcae15110826574053681fe25a695ac4540186e90
+A = -a221dfee30286adc076673cbcebd24a41a438a0a7a6a547c75d33149cb1a094a8425feaa5a23cc234a722db4cca8d5912fe1dfb6db4e92bd87c12f0d06b6d954fdb9b172955412b2eb5c9fa3b4df2933390384fd1f929a2b1a8dac479ec94c
+
+Square = e880f8655b51739e34393c3e6d69d63e0256b1a887f7e69f40c78d21133b17e92277a136f5e37da2533ed599efad189975d22ad0340005ef58db0b471651d749dfbd48b3f7b3b8a42d4677048a855e99dae6c729d8bd7eef86911feca9f5490dd216b06d9e8d1ab695c1081e72449baad28dfe113744853382901e6bdab5413c67c52d6cbbb2e0bea711edbb3a219a4046e8739c04729cf8c8210028dbc4087737bc6c1d7e0c15ecf16774690168342b1372d3646d4d8696384bc932144c98529
+A = 3cfe075d4525a3c780d6d05f7bb708b2fdf7277a0f9967e0a209fee9d42136a0bbf98660d8ee8cb4720a8042da09f6271c45ad13db24eaac465f8207f78629e9085c1c890675f441c78efa38e5022b1b80afde5e3fd08e55648f2817631eb6cb3
+
+Square = 8d6cf4eaf58099b1323fc598b7554b371f4afef5ab501dd162ab8429333d46916fe15dfc4ed6a99ca7fa7fc1aaa0cec3533b41e291fb7f69b560259507226eca87aabd07b1ae2eb93bb53f98fec508f051cc04db4a172901e06b74229c4fa3f550a81626c7a63fa99d41e46c2cf792287a5cf7bb68946971bd43c7c0356312cdc25e524665dd39a24b6464bbbe64fe8e87ee313b860639728a9143c3a6118bc8b150dde6c10a13bea637fa8873c393e6338319c506aec6ee973b4b52a272a74bb62084
+A = -be46a8072aa44b3bff0f90c81474dd576756fca624c15f55a17e1d0bd2842467ae000b04f79f561690c93ca7118ce17ecf830a8da3678c15436876d2a74324d9714dc8ad8181904be657d7f1da3313b78448cc06e32299a09ed59bfc1961e8bd722
+
+Square = fbaa4fcf9800673fbd3a132305ed3e14f4889518fb56ab82aa5e9b3529b74d7f9a467626d68f4709a2030264aaebcf05c0a0edb511e81f357d85b79d925a24605f1bcd4645915bb75d363654b676266329df532cdb39152fb360df1b9500e0c296014289650ff77faa78a604397a82b34d16484e94a8de123fe720e514c88f11ec276725111563db91477480c3245542ec6bd0bb2f4aaec02c6c4eb1769030a31b05da3798c224c9117f7c38d3e98a343fca03ab584ec2d7e6db60fdc4273c3d8e23cc1ce09
+A = -3f74b25f2a9c4d8d977e69a4e067f9fcec281136a508e365b282e5fc3b1d097bc6a0f59f7827fb90d4890b08840a0a1919032c67448f8f1a771f785a0f125a4aa4137c154fdb489dc1099d57bfcfc75f4ca5e69f93f2bb87ed09cc0dc620d3e76ecd03
+
+Square = 5135becca97d93dd4b16a5a1105ba3a3e3fe02bd6a7c3cd182186fc63ed4351641182a2727ab6715e9672458dfbc31aded4781fa345054eb4c317872e2af6d4ed64b2ca7e8c25e1e664b5349df937118632a64e4ce439ffc625a5ad3358270dc83fdfa73c7afba03406094fa36d87517e5e2e1fee5526fd2dc00d9210a0f6c3745b3d4bceee5f8b03d976d696c57a09d1e08e4ce780972eca4f2ed6500c23bf5782c31f13059e48246180fd09db693d2fb5d48d51846ece8beee45cef7efc87c003b44d7b137a900
+A = 902fbe2127354a7df5cb7fd057f3d080a7bebbdb83c86a50560b8c287a37a841bb9c8421c63d359078d2948b6b57559f98fad8f8014f93c912cb70a6701c4dc4fc5e88aa413fcfb685c32975a8b72424742eeff8262d28cebad00c5fcf88baeafe8f6730
+
+Square = b5976cf6a6560412aefa6704b126e0d987dfcedbb4da436c08ce17b1bf1b6e0bab9f934abb5c4186a5415fa38724fb8fa341d381319e7d768209ab108c8debd99075d31deb3e03ff7d23957d4f3204d543b7d9079cf337be3037b1cb4908fd8c104d92e52f041b4cb27c045a741f4d64009980e8d27af75d9493920ed98c7234777592d6577f2d1b3a0eec645ab4cee2f28d9e4efd3e4514db6796487ba68a462fa0e316e1420d6604db2b901de46553546cab42976fd0d459afd81196275cd88ec4dd448ff331bb35499
+A = 35e700e034950bdd7318d5b3c17e90a4772ecdacdb055b9391b31538eb823fc8a4599f029e78e4fe5299ba1a423a449dc257a431d189dd5dca275c02cc1f12417e111c73b731631d8a1741b907dd8f24de226ddf9e3044cf4064e8e51ebd55be774be7ad2bb
+
+Square = b7de0f73397893a97928e266bc56299cc8d43b16a251992662646072b58fa578ca80f7be1e12619012b130e9514be803dc166b12ddfd26f558d36c2053ee6209b01458379e49469753300ef20f6b3dcd5383b121861c76ab25debb28c448ec33a81250d05f7eff80a5a4133d522d270fab29f739b607395a77278609aa5e1a55ef58d1d48492b71ee30a24a6505aab1a3ac22b9d143c9d6781fae14bbb980fe3a99dfa9a1a406611d7d0304493342f53faf5fd79f9c96b9583a219a1b22aad02dd58f32ee98146b3a8cf054bf9
+A = d8f4d3bcfc7eebd7068b851858c3668ce062a834927e165679b49132d4f780ca682876c65c7cf2e7ce34ed10e43696477da6301d13f92abb8c76e2424c4bc28a6565f15e59563d607b852dc946652b68fbfda1c3200ecc2976400ce7296b96e75fb059a4c8eb5
+
+Square = 5ec02661f49fb9807bb73debc3c6eccdac1df1735e0d61fa7e0eee07471068a5809796a2af490c46a77d61f618b44a3168dde67aae1cf9e530382411056958d55bd18f0e76fe2c31c98b00f87fcb7f5691ed5b65424f82204156dc361ef6dec5d44cf690582599b3994ee47ef42850d5d2370a4169c5f73942657f85422ca24f66943877f73af493c865fbeb29574cc1cc730e9bbb097b598574f6b90257748e950bff867bcc01bf62f8df67d7aee1b6dc1d5db88826e86a3f9fcd8663e09cf8393ee71a09c43d0d38ba6ef643f4ab1
+A = -26ef9b6708a80d00f4d01e0f0a5546ed217085ff23519819ee89af430580ea1f086beb0eb51982682c6d3b922a2c92752dce63657836223a9d94964bd584bc8e37c6e30fdcaffbdb128344d51a92705e1c9f94205ca36452c15a08f7e62e0e02479ecd48085de8c7
+
+Square = f6364409467a829abc2b13c93979dec84984caa12154b7cda2f4c8d91bf24ad7c45a968ffaac8d6722cc26e6aaf52dd29ea2f09370ba46d79684b7a06faedcd17136f35a58e5b550f3a2caef7b195d8409914fedd3c3154101bd735155098e8b10fbbb1b2e13555d2ab5d5b52b203d4efb27e498b240f37178f2e89b413f94859b0e8b2ec10b926c8c0b6f2937ee2d0355445364841c7e0539f7073b88c7d568edf1b253f3c10627e22c2ed731b7d4d199449cb0b5e7a66109932fe2c9cd741d75170deb9f98469049549c10a7a622bf6e91
+A = -fb0eec3246e99212879e51b17ea6615275818ecc5ea3058b13dbaba2576ef90e1519e3629b09fdaeb02661091c395c862b848f6326b9f536f7af45718c4412f09f19261b537bca36742d3ec66f964343516aae2ac27e249a15beb545b447e37b4062180f6c82809429
+
+Square = bc4193ecb5dac900191e02be06297106155c6840c4908fbf6e41e9aae137d53c3d4ffb87f334f49837dc4ab7a66299994e4f5c9bf6ea03e7db663bdef066e94c610580a8896a9ae9c8f6587eb83d789683f5d6391bbac3a1dc1de60b4108428e6f5fdeaed6cd3e74fa01f85c6368023b61a413b69b14276b66f22653491e4f25790985053d075387cb13c79dcf963b6d880d01174314921afe1cc700c02efd2979dcbc59c417a6316db9ac45a2d60d2a036571bfbd75f9f5e42048ca086cfb4b818a9beca4a6e0ed51afa320ef3549151fb39e100
+A = 36e1f16043b4c9b4a304496c39dd63459d6521d2ac92916d348daca3f972835973fc8d21b07b09d8f5e3197b39a8f3fd0011168b815d67c48143c413e169ffe0f56ff2cf8b6596bd0a3b5b7a6b9a14ffb797f350b7e6aa7020d84d1d1b8006850139795abe2c74f03b8f0
+
+Square = 4cbb5bc1dd7112326e2c94581f19efc8fb25339a299fa9c007114c3a22b395e9d39a8ffe21134e97ad1b87b97e667ba48b2a40af61afc81fb1e20e8e38c7ba666b146016af4dff3faf5de306591e5ce6eddc1173fdda6fe241a9f2fc6e054c41e56d296f8954377df0d140096b9e9d6a5a23a231db4dfab0cabfb11190c7a0d1c55ae35203836d433da96ca7339682bac0a7edb8b5b4dc267c6e83ac9b67a0d0d564717ee3c20aaf52c0a750f3aad94a12537c6971ee009d0f82ff576e984b06c7f7b357f5c049454e31326b952af17aa62104780e9ca1
+A = -8c279ebe466de3115b8740f3ff9c1f605b4eaa75512d82fdc8ca5ce84e11a68688154fd603ae1d607807dbfcbb822a8dc259098842c6a7b7ec350be29a3daa20fd5b093a56692e9d42e7a389c4ad2122a74205f835e268c9742d09ad36238c34e143f6e2ec69c0f490d29d1
+
+Square = 4f771ade09cbd1a033d2bfc6036fe46ae6c12acc6f2b9bd52e7781693fa6358cf93089f23d1f0ee6fca476a43093b9b52446f3a7abd72ed0ce9b562dc438822ffd84bcd898ef9d092f1b0b7ff89c4fdb33d8715dd4a0d68ec49ad41338fbb62ca87867d847a4d99310641a37ea78b04c85606069d0c0950484ddbeedac8ec6f95124e7fd83da4e942d40103bc14474f5cb125fa0b06cf167f076979948003dd8dc3711923f5af5beb5f56c0a48ac0c5240b62738c1cdb06b87ac3dfa17befbe938ddc7281f6c248c41a1c7b99b93f69fac83a46eb298a9fd8b9
+A = -23a845bf2007ba8480e3ece0a1bbaf8bfccba6bf061e3fe1d8bcbcd6c761e650891c0958bac68618a1f55b27d2bc6e1e1b50afc29f58e2e034bdda8405e5378cb5bff0d84efcb458c5428fc607597d89d589d85d90f3da4b89a64c9d1623b98b10518a6f2e7d2295c37527026b
+
+Square = ab45d12a4e15a294830741f4b9d4a14cc7dbed1c3454612047f890211c749d92ae0418f11cd44acbf1585b1f7323b33ac9a4b13c44e1a7e31b0dcc1c6dd4eaa12a655b5de08f3b948270a152db7d9e04dc54677075797bfad6a9a0e3958458d40e3df5e15028954bae99518de4dd3adfb2ec4b38897a8a4e4807849e1416aa4040c95a0e49a8d2889f6fb0537875f87516c3723e8d3b46da8da855929c67c0eb83daad62ceced52b4f52d2bf1c4e34f26bf16aa7da3afe0f5df76c0858ed98f21e1fc3d01e1572715b774bd5c2faabec5fa3fa59a7a1f32565a4f1f9
+A = d164d875e1f766b4567e9228241213e69d6b6c58620600166fac56938c5d9643932d01f1f4a2263dca4b9ad26dca1548e4b5b7e27581a63375d0e624f4e4c99b7fb9aeb25307c61142760bc4771e48c7ce38f5eb2408def632096fe40b80d488fe17a455d80edfc1c23c429775b5
+
+Square = 5ae4e7dc5727543af39ed3d5e9ac086d1a2220421231b82f6f41caee7b9815b4049aea0d43ff499c6c9e1f226f8641351d03f37731c64686d9a9ce68e9234d6a762efcffdecd42f81044111599963d9b6873cc20bf4c8284fae03d2e4f238a14a74df4388fdc80fad0375a5d0d974da7854ede5896ed2ab25d2b49a3c39093600f73120e4fd2faf75381854f6ae80f81b977f62fc72f1fd01c278d183544052b77bd753dd88ffdf5c01745521fb8474b5c23b0b7dc709bafeb91cee0863a0c23ad7192c43cf15fc181d629853cb9b8334082c915dd3d04e3a0a81511d2e84
+A = 2622a7bf45ccd3cd567c757f4c5796b5a0fbca555bd0ac2759c24083172d82d6a887dcf93d9788fde052cb20a8963cb6db22bf5eee6151600f9d1896a7606b11a1b100cbc0925bce037bcea57e361efcc560a9abc495d7f7f45831c6429ac8f979dedc08c304f4da9c0d4d687376d5e
+
+Square = 473cc933f5a650a4ae358c7f486d325c0e20c83b54838fc08b6ac3ff010f7c4b6a609bdf472974dfc5abda0c6b33c5ec7dc4628d85cb4276108e2b0bc4e19cba135533b3d7bb6a94332aea3165dccb230860d2353166b9905635e606185b014730e9dcf2c433e18cba83859fb2eac4aabef68c8314ef86dec2d534a184ebc4cb193643add0897341690cbe18bc2e775327fd7d71ffc7ebc49bad83cd68394eb276b2e615ec430180303010a454ef73b6a8f02bc48a1fc8a32f8150ef1b733f07da752b8e808000329f4924976bc8b8573927f18ca7c88c210845de6dcd0dee2904
+A = 870b2c4b054076d0d02877b19fe1210a8fad3422b00905a6db748239b8e807716ed9fee0d8c25496593717917edceb5db57f9960bddc1956b6652868d6ace82827bbbada5ae8c15efa26fda22657126c6300906f90e8fabfd58ddf312ce0eee760e0090fac44f00378c676115cd0639be
+
+Square = b151124402d2f04b0e6599222d380dcf67b9716ef50d2d9ded0b21521b34a7294171f71b41762511b7cca93d9f50e9e30083ef19144882928011dbb143807d1b88c55eea6b19f0c4180023be6da63a59b6bc027aff3f5abe2f65c73b2de1e71c5f4b248bc4547040764e83a860cb3f882bb8b5f7821f92802808fa37c50f2f94d8f56daca841f42d3362762ba843aedbd03d3cdda887f75ba92423965ab4256eb842ad755aa7a2af331b488186f891065b07f5a299c807dc24fc176e085a8024bbbf12f386ef49ccc91bd4ada0936b6de78088cf5952ae6c04f6916799378bc0ede0da4
+A = -35439da9e361700152a35ebdea253378a1febec5f288e5b2bb0bdf25b84751b47e4da5aad7453b70cfd6640d5832237d2115575c738482ac6036c5fc21a981c0a7f979c8d621a92c02166b777475618aa6362a0e225dd6138ead3b2766ed9785ee01e4950a863d2fa0b7f5cb4c9a108bb626
+
+Square = 4ed7263ae5beb0069f24318b38afe951a5a058a2e960e67f086c9680d0cc6d713f943812070bf94152f7926bdab9e5908941261244542b832f458f05ed5dc048c8b9eb84c2a85efe717e257796b4ca816948a6c8ea209c0675efb2fb5af4622b44e36066593db01b17f4dee21d7c1337ff41436cd0e5a8d01e4030dcd3d49839e59996fbbf1d39bd205343a424f2395b4d3eacdeb9ed3235d8df0dd00a2573260af63db3116a7c65d1dc69684a05caebff34e3d2cba9d4869a953a7b1fce10ebd008cba021008ac3187bba846abd7b39a1b97c9c07d8080549e313dd58b716022de3c1920329
+A = -8e1141dcebae61d5c4d81697f001d792ee2e847c589816f923f0ed42bb4de0d8f911b8ca47ffe77f80b9da6896a9b42f0030a3276218868bbe1a3fa64fb0a577704339af5dd82e66780da6f58900da3f1d75ebfcc302f78ed66ea3c7a737898a29b1f2500686b43bae1e6571addd2842cdce4d
+
+Square = b09f5e9472cbb75070a67d025957fd5ac3be89c41e4acbcd5f75780ca459562461082c3f19c5a4a416a668b0a55f31f74cf2ec44555ddc43fde64da0ba781adfac4520dd0f78d04d9d2fd33d8b49c72663a6bc845015523e2e4e7ccc69e5b748b8b891e4089420bf0a3f6032602824c7230b5ff95f85a688dcdcfc890af3384710a9fe32ecf9ad7c6cc5761f13079b19d7b2906c7e63c14b64fc88c6f4bd7c41c0356c777d35c3626d49db8cb2d1e89ce682c7fccc3a459b08c20c4e5fc3a8eced9b37d01bed5af6ce9baff0d2b435e6e62871fcb20cf9ec10d1897a5c76e73a441e07fbcc2d9f4e4
+A = 3528e6581de547de385c93ccf1086a17614f23356a918b25bc6d73656a2302b318963bb679c9a93357f4a4f614e74f2e5e88e9c8aed8a6fdd8434630f664ed15ebb6095cbff1593f188a12f4dd6087a85b202f6c24df68ac3b137406c88c5098faf47d1eeec0743b35baaec7dae29b5a44eb09daa
+
+Square = 5d5dc40783411475a4aac7c1a1eb760f76fcc6ec68dfebb754251cf499870654cd309422935ec841e6be4f5a15078356235c2b8cbe1ae755cd6d814e811072bdb76156b83c7d2064a202ff90af1e0f88f5889e5729a3cffa9faf33c463b74d0ad21fbb4473d4d3ebfa8a52e9c209ded5ce5131b12b69747c365146fa17ee5810e0dbab992f9da28b6c323062484d62472232721d608cdb9b5a341a677e2d7a6e5a983247d9a4001e16687b489b10b18bbf205f982b7ceee27cc3e9c6641827ab7952373f15d36e5f177b82d7eebb3f5054e12cec82c5f520a2675afdec6cbf6235d358c2fe73344002e400
+A = -9a9a19fcdf11bba84b0395088c5d187d84d69b68b77bc6418f63c88bbd8dbbccfe02917d814f9e2241fa0709817a0c85bd554fe887babae7439d96248514c12d71587c906247b3e965e954cdd57f1e51f1979f73c3237509863169efdf281c1359488daad3d9eb990a50ecf4d3fd25d4820077832a0
+
+Square = a4d69ed4c4c9c08116ec5cc49ad458f0fb2ca00f356aeb148f18037bc49621e14820f325af39f3954bddc9cf01de7ba1e443088545883a94c04ff41a7ed5f65676109c5b711b4115775489667e00aa1b77f6dee5ac5c1789bc71c9fc797abf41c7c5ae3e2c1cf82d5b49b6c0da25190dfa9360b99b2f63444d21ec6114038b8284bf598eed24a2ab2b9802d6edd5b0fdb52f60621a87a14612844ffc71ca98180ff0915cf75f47432f73d28dfd7a932a125095655f07f50722b1673df2cc4f7566a1c6035792ff3f02356b9b9d25e905121df768dc6a1884cf5483eeb813c1c009fe4ed043febd61800ba978a40
+A = -335b12e40bfe0b847ed6ec143490df33d2e64ef4363869cb78dec008cb5cd66ea671dba964a53e48267da288ef4040e06371e1209691b81df02f2c86a79cac85fdcbb6732a1e5309fbbdbcd899fdfed18518d47258c9e63ff7f116ef4a8f5c4867aedd907ccc7d222cf8087afebc108f2a0f197c717198
+
+Square = 74dcdacc1a4f02a99e3642f54f9d917b117d2ae8d9c392f8b6dee53fac66ebe1680c8e8cc29f5330e0eed3f63d10980060799bc37b34c93dd7b384d4ba30a5b5d42a145acc412ae838d7b9b7137637546d1118f7cf3eadf88b785f0aa01da8638f027c56faa16aba8591b64b45dae6138c9a40309b2ad29c5029a867465f9c6de8fbc5fc4b0442c8a8946272667c7622454ed6f2a236103bed7697dba20db84b5154ff3fbc6b4b9eb67ee43bcaae741d87ee2093ee67defb8eebc4a4a22d97a4e2aa7d4c31a1c88abf4a440ba4e2a5e40c4d903ba5ee4d80b4e8dffb8864bcb9806e015c1ce16490068df87282393111
+A = acf70350e554732c1972903cce269b215e985ecb8d6eeaa67fd5398d0a1b57c0db63368c0f8c2288c3a0466e2b3db081106b90920c46462faf00b5bd654f7140a689b78ef656a26b82af8dd1988f166ea04e9aa777a094d892bc7da4bc7bcf0618526f496cddea6d67df7bb0de9e99a35a0b1b210ff07497
+
+Square = 9668b9e40a8bdde3c93943a918ca71fa0009cb05a1f592b2bb2c6c6172b2950719bfd80cddaf45d044cbb6aa99715046088f40ec6812945885679231c07f4200023548ead086b834abd8c8f8294db28b203329553242fd2f778ef5cc5ed0b48c7356d8c2d782a01809ccdb6b012896617f11d963300e7bd38ff512829514d94343476818ddf9d712bc70cffe7f767a9fc75a5630e6250ed45e6831b4660eb49d47dd1b8b6a0dddf3fb3ff0e12834337f145f741f70a2aa43769af50f099e004269ac47fab79e060800dc74da88141adbc46c15c7330931e3a2bed9b958f78b30214f81a64d121f96fbcebf7569fec0cdc6b11
+A = 310e7a40667d9d5dc29744b123cdf6a663a1b995f62fa9d4d853cbae0dd23669f4778bb2040317ebf6a06ac6299b21067aece5c5c1afbe6e789d656745ad66464991cada0eb237c6ffe991cac4670bfc90eed5f8c75073f4f846ea244bca0e9502ff56f8e9bc9b6caf275aaef38e26566fef35329ca45392069
+
+Square = 49e677c8b052b7db97542948542449af47e14248021f8d3d3f92b9af41c803072f71050f16dd848aebb270affc47e85427a7c73f227f0d63f140d0d293157af0d972eb5b38de494fbc78ad3a4c3d1ab40197bc4427752b6102d1ced6d6cbc9d7caa0d1bcc57e708535822180055ecc9d9667e0590274b778480a3720823e931ff6daef358b1a1a9092f1f05fbb5b10ad5707a124e8be63bc696f083eb74e5b4f0e3110de8f297ecd30dfd2bcb010dcad4e387520d3d00365fc51c2a3dfe064b1ac77a9295f66beffbe5dd4333e5cd823b0f36b0b94d66507b1d9381060980f62f38a62e38e5a75203233bb8d64089bfd100f3205f1
+A = 898b5f3655de74cec3b0fde2ab03fd18cdbcfc3eeea48ba39317d26917130c2b78e05237cb0454ece268f091cab699fbcd51ce341b53d6ec0cda5d0d5388bac25c6517214a39d03450ef8502e1675bfe8e57bb6086f10ce4cf8ce65eadc865b5bd8a00dc26394f3adb2ace609149e3582cf44246184b2adc0ffd9
+
+Square = ad00f10fed55175159b2409dc80899f9113ba7c8099d0402ec0f520ab4aeeb46d36369494a4e6fa23675adb38148fd2efa082df5094c0acfb77a9ab6ba7a299298d69b04b58011c35325f46b765e580b5c05eca721904f1fcc355dbe39faa92af5c9a6dbc4ab80e62b815b45983d9506ebd52b9efa7a6b9da352d1e4fd6ffa81d3b4596a0c14fb825297da361461ff2240e4378340d2ae529932d78f3d9f6b3c6d65d717e66122e5f590c50ce0a5d81ad8e0f24e104c0913cd8d0eb2de4c8cf62a7535bab5502df3fba08bb4dfe73d89c8b00edaa7d5f3274be9959e7ab6b6dde54f2491728a1dc11fa8e1c6a95e67eb7617e9b7471ee40
+A = -349cc2a5658fdbe9ba5c350d3b25baa38b1ede01926694bd550d36883e53d8758e8f1ebe83e2f4560605510413a7d880929e2d9cbc2730b1736dc2689cf7bbcdc68a342b6398e547a9bd67cabe298796d76b98ed4c1dd9c22e36145892e8fcf2258529aed24252a70b6ca8fd2aad8a84becf7e1bf98b1e9bb024b8a8
+
+Square = daa3835d3189ec9ade592e6076e76d441838077a9431273bdec02379b3a6ac38aecbbd57c3755ea58ddef8105ac28f2ecc8598ec0c4bfc9c1c80222fffc776722eb0621cdd8a0d55f08767fc2922282a76e529d81e4d6e21a2542b8c9a403709ed1132e3b52786b81e684591438fdddb5df2f0b72e6b39cd2db6c0cc55c759c2dc1b6ccc20a5cfd10c6fd345fc766035c7478570d4ac534db3fdb718e2bdad3d096b137bfc09a562043800957e2afe4fdcfe292881f6189edfce52370c0438c2822ce3b14d73b3eff32f7e5ca97e989326b4e3a8fa35544193f8590bbb0ddb1f914894ab87998090771a0be1fd23917cd792be86ea0b98e6eb24
+A = -ec953f1b7ba7d561edaaa23076987daf86f50e9a66c36f0993290549a9006dd9d424885c0fa77295cfe34fc81c5edce9e2371b3039ea18d8f998d1956196284e6d81eb1c62ecaa8cf3fcaca28ca7e64342803c8dc3c139080bdd4a1ff30d7288b085a579d9e90903bd363b48f2072bb6fbfbd9ba2cab30a8a63784d246
+
+Square = b33f4f3ae453058f4e865ec78f0844bab7af66a97dc2f265ca73ae2232777474bfdda39e10652d7386c16f145272192af728893c3d8a8e92c60d77722b924c30269ff5a399a2449ce15e50320c528c22655ad06227ac4efe5a993179ec61c2fc9115f89d75b53961fd16f7797657f6fbf55662b019608a1d30f64a2c0838e0018b7526921fdd34fd462bfcb2462b7065e2bc7abd57d71371e45dfd8fcfcc00a71f7e45430820747c9a060b72e4f6d2919cbffd00beb0c31a2bdc32afe2cc540b38dd04a2b73ae5ba481a6e535f37a757bbd6aaa972986213afadfa47cb7a15a6f1d443f93cb0ed824a10b4b7d82cae524a096b65ccb39be3c37c07f59
+A = 358da59ef65f62f633675764e292e5a68879df24a4727eca1fc4d232b3a6d936976c92eeb11456b5e8c11319838c145c6529d2f3acc828e55b8274bfe9afb5db241b102715f8e8164e454ef39f13ff1b37cf367a5a66c4f743c750896b7c3c29026e448bb36c6c06b0d9a3d048086ef0c3cd922a02e794223f388b5d646db
+
+Square = cd4246489f6f221f920acbd8bdcdd17f47d2b77268f72254de4190685c123e8c5eab8517fded1852e8316c9e549d3fa355142d91b2921a3c94aafd8862cd2235429340da38a2af131b8d002f17662354f5805f6a7af7afb6dbd2f641036600614cea42bd8b24d86a5109eed29c0865a5f30c5291b1d1ef3223f9b9826dee773d98ce972da92daa19e843f84ca5f1cd77925a3c1117242ab0fb509b94a83f8de4fc8d21f856f37a4d025b3024bd0dbb6d8acfda4ab2993fd6eb7a7448d4f66ec725d37f0eb14eb242c0ff3f0c4572ba6b98a4ce905fe1b7ca3daca56c225171428c56af938fb66b37e99e54139157bbf41f536989ef813af738837afcd62290
+A = -e53ad05c88568f09f616797f0b7f2756fb543d691ec2a5b645c1e5892a247302826419a35b1348cfd2c1c569c23c31b4c46d6c57d4a488c29ab5beb77904d4adfcd0a01ea0a26bb0cc8790441cc2c8c900f030d7315b4319f1a3cf5685a140e03abe6b94730ad79e8de1f4a0cded86a3d6cfe2db267fa7dc9b2bb32872a90cc
+
+Square = eea8028b26e0df090504d54da714a6f5f2695202e53cff479c78aedd47a8dc676243ec586740fde53b3eca9ca02b91031ce766242184109503fbe25b1b6d318e3cd5970fabd16dfa22984dd2e9f1e0f14c189170fc69c031d66663703e6235a942d51a4545bd7b0769d01d302ce2b00b83f01568a1e378f61fd0ca6201b0490330580cd9de85719e174a71915d7efbf65cd73d8f4e66f27e0dd3144d58ec09ed0f7ed7d1238ee596922807100fb7a11127944ddcdec6a9ca3bbf6df7301e354f3f049bfb7c275b43c3d8cda5907a932fba507c9145ea3166081c1b48fcc710ee32cd931f936c796b14f8a78a592e67753a7c9e428a01719c8ba82652f3a89fae110
+A = -3dcb44be1e54c5a5d7db48055ca9afa1ebe2ae648aa6e16ac497502a7deee09ffa124720fad0ab163ce8b3ea6a90f110ea52b67dbc424d0cf1e8c9726dfd9e45bebcefaa5cd5706edeed27896525f31c6bbea3d67ee97badefabf3e2532470b66e3ae3100f66ddf50cf02fc3a8e3f44c304251d3b6a7ca3a6e4bd5d16a41bd97a4
+
+
+# Product tests.
+#
+# These test vectors satisfy A * B = Product.
+
+Product = 5befab3320f8f90542f3120235abd926aac3805a19e343f690
+A = b057af553afb120db6b7764f8
+B = 857734c4c27a1d17f7cf59dee
+
+Product = -ab1ce167f4b2945c55ae3f87df50ad07d4be87cf9f8aa07b0c
+A = ae7a6a87ea8981a567d0b3ecc
+B = -fb0fed5f8c737bcacef4d6cb1
+
+Product = -c2606cd48e6b075c8da79eb4668e7157f1f175c2860fd4c475
+A = -c28dc31984d4583e9d45424c3
+B = ffc4581a5c3f885cf42767e67
+
+Product = aa6805b5408aff7f914472756da07830dcad902834dbdd6944
+A = -ffa07ff9f503511954e5dd3f9
+B = -aaa7af472ad8957763f5a7c64
+
+Product = 58ca2569173389df29b5ce4b784086055dee821a7243db7210
+A = af417d936f4690008811a1ae8
+B = 81b26b80b43aa65aa55ded52a
+
+Product = -a043d31dfce8bd01724d31c863d0a64f1bf013509d77737c42
+A = fb5fae5edefb6997d44a1ecd6
+B = -a336e50c6f7845a1686cc88a3
+
+Product = -b5d6a45ffce851b201239d938ba551bab7dcb59fc11fc35fce
+A = -f918faa58bb57a2ffb8b01f05
+B = bae08c3006fade695029a1df6
+
+Product = 6f2fde7d1a18625d727c6345ed85e597d546d9228bf7f0564a
+A = -8d108d7a16f0696d4ceb24445
+B = -c9c764cae465207097ef8d2c2
+
+Product = 93808b1140841dc9735cd61c6f855ddbbb83066689b0d7e1a0
+A = b386d08daf3fa2154e9c768d6
+B = d2557dceb2d02d04d9c578670
+
+Product = -ad04212ca8cadb1f7861c5130ba3a747046a2a7e4a0c72b69a
+A = e4e5f7d1311e0c5f2e404d55b
+B = -c18057a328d8c7375afdfd4ee
+
+Product = -685e75c232f2b4a0e455fe5ee8aea52f292ad8b8178320e692
+A = -a683312f132b2320632e74ef6
+B = a0758f12791453b4af354730b
+
+Product = 6f588c53185c503dc5b0dc3002d3817ca2e7eb2370b3e9a647
+A = -d70c9b93170261091f0c53f27
+B = -848c86c51a186ac4c9080d3e1
+
+Product = 5e3bc5a04e054a9a244bf7c86cae215072fdb70e9199989427
+A = 898b64ef09d7cf63966e1a3b5
+B = af638b12f26aa5d12e97439eb
+
+Product = -8d8372b235b16108285203c03a8aef6fdd3c0e1a9fd31d4f68
+A = f6003dc83818c14fbe36c9998
+B = -9343f6cbcc81fa4c9399dce5f
+
+Product = -5ee6509abeeb7af7fc5caef40d1822ad3150c8d74f522dc7c8
+A = -875ff6f56ca72cbdf614bb9ca
+B = b375a68a21dfb1f159c22fa14
+
+Product = ada25be404a17385af5a330da799e5909da81bfa0715baa6f4
+A = -c9b8df392e76abc3eb7d5ce04
+B = -dc5ab818c70594dd917b4243d
+
+Product = bb24422ee4656ddfcd50ec38201b15baf679d3b75e5cb878ca
+A = f8e12cf4defe388b78510f687
+B = c07ee817b4ae95c2915b88966
+
+Product = -93da296ba164c7220a17330647aef0980c94eddd2cfa2a3b2d
+A = bc5dc74ddf7a1363d1c2b1f25
+B = -c8f069bad7f93cbfe6df51169
+
+Product = -6b2e1d132c4e0b0dc9b7e7de7d424fda5180480cb5ff47c755
+A = -a8048acb66a8bb88df39266e7
+B = a34e0b265d71435ae8c92a463
+
+Product = 6ccb2cd93783576a8602ae43f41c786008b6623a4cca0a010a
+A = -b071f1f54790c951c1dd2a1cf
+B = -9dd89bb4d9b546207e282e2d6
+
+Product = 5c742ba47d0d64bd97509927ce957deedb855766cc24c60016
+A = b44f3f252c368096fa62747f2
+B = 83439b97dbac579fa4f7b7d23
+
+Product = -7347ba65691c913286c2fb55e45b177f031c1d86ae0e9f654f
+A = 937cf0643ffa53cdea24d642f
+B = -c81881f78243dd5737a7d28e1
+
+Product = -9bc0649a703674e59f83ff9b8a560e5cbf51f65ca310f80f95
+A = -b536f8d9769be6f62da941ae5
+B = dc0746fb101881ae0cacde6f1
+
+Product = bf4992fc3a124de350f9fb90ea825cf663b1fa051282ef22e2
+A = -ff7eacc7de1bb01d668c693aa
+B = -bfaa6627f9fc7ba68ae41bb2d
+
+Product = 7c8992d34cc0b63f1c953f68d4e12a99d3f3a34d16bd76caa9
+A = 9e0d5a850d078890a983c0ec9
+B = c9b72c118b3e1f1023a696ce1
+
+Product = -a75840c95082b9a0ae0d6e0a4eb5e09288e4e2a66e9697d9cd
+A = b2b042a21045a74ef1a5091d9
+B = -efbf8b120b384e869692a1b15
+
+Product = -a510b333bdb4ed7479c142e8fbe2b12f7671a42acbe16c0998
+A = -e7fd5e0bb5496b9d876c27f65
+B = b6262653b2be44501af1d85b8
+
+Product = a1c1e90afc4684754155526e307fc6ed798746f347bae2c880
+A = -b84674832b26ded0a690a8ff0
+B = -e0b7bdf2fd05a038ed3640b78
+
+Product = 5588e0c33bffbefcc5695ca0615abd383343f21a8a0d22b222
+A = 80cad81ad9a66ab6a1c2e5669
+B = aa0453a77c8af1584f54750d2
+
+Product = -6460c2fcd6cf3304ab163ea883ac48e2031cd10f2e9014c0ab
+A = c49ad3d7c8848d4fbf913b10b
+B = -82b3dedbe3cc7cd532ad632e1
+
+Product = -a18717330b711669e85abde8c4dce426529aa621ba3da2a477
+A = -cab4a9c0a331a5a5e826dda1f
+B = cbfee5041c13075dfe3399aa9
+
+Product = 8ab6282ee892b53c083d319a9dcab48af97a1ac8493c0bfcad
+A = -f7d13e47f9aaac8c25f9bf75b
+B = -8f4aa95231c1e2336aa092297
+
+Product = 8f2d1c23c78777ed371f13155445ca3c88cbc0a9b299bdf9d3
+A = 9d8248d00defce1ad081337c3
+B = e8b479295ecd9cef7301f24b1
+
+Product = -86d5e0c5b581fe59819730b4b71e33d1f85f9ab504c7dbe2d6
+A = b21b45e88acff48562a19729a
+B = -c1cdfebccc763beeac394b997
+
+Product = -484ca05aefa113bdfcb1bc623f730c9f9555b462a8ab4c9606
+A = -8c12b406c02c4417163c0956b
+B = 8422b15c80c1c087b17eedd92
+
+Product = 614c3c91f60050c785fd229a3ad74674577a90cacb654e0a5c
+A = -93d45bce155a23a397506d96a
+B = -a87e339c3fd5aebede5fb1b36
+
+Product = 9683285f194a7e4feeab196a36bdfc4f828035fd184b9cc692
+A = f196d8fe760fdcae7eb60e2f7
+B = 9f7d88a2163ad818bf3a6377e
+
+Product = -988a64599c19cc64f3cadc1a83fea6550185f6cc3ab82af822
+A = d0584b2a306671e4d2c9d0c7b
+B = -bb6e7559df199c68d6df3a3c6
+
+Product = -68456814cb0edd951196d04c853172afdd5787a5bd69a57876
+A = -cefce1b0a1fb22862418bb597
+B = 80f614139947aea5e76cd55fa
+
+Product = b4b1cbf5d6566e7a57aee0cc5c9c8ec4ad885e8766aa7662a4
+A = -d68ed1bea046c6cad057e21db
+B = -d7988b9be54f6e332d019032c
+
+Product = 6b09212675ff5257a1384371e17b37dcc268bbb141577902e4
+A = a8208053adc20a609d5d01404
+B = a2fa927c5458c4fe662d7a3b9
+
+Product = -8361bc26f9bcf55f677e047d822d3004027da0d0455b244d10
+A = e82b6410b29020c2d6810a977
+B = -90ddfe0e7f0d6b9cdc0815f70
+
+Product = -f1b6da00923fd513a83e32040a515649fbd362f69ebc016d9f
+A = -f9b697d9ec774a8d1ee5ea905
+B = f7ccb46a8869cb028492bed53
+
+Product = d06206963f2e150bacdb32c823c3a47f013d5a267c3c0d0c88
+A = -ea8e63afa99c719897ad7f2ab
+B = -e36f11f55b6148d1b4f46e598
+
+Product = af774a5eae6084df5ca499ef005642730adabf6a4f9533e2fd
+A = e4c7af7eea3ec9cc2443b7319
+B = c457bc264c8461789931baf85
+
+Product = -76350f428bfbb95e6c253ec0f457aa84cebe8c7cb1af2a2120
+A = 8fd1ff97465775d44dee58ae0
+B = -d268a7d328f44baf80e35119f
+
+Product = -787ae3f114f9a8dd4d249d5d3f3b0897b02564b9469416cefe
+A = -bc0b398bd0ec045b0cf147b7e
+B = a4050955c234e473257d0c641
+
+Product = 9d6320b3d4aabac097a079b9bd2aca7f1898bcab0f23409fd0
+A = -9d7a4ebac630cc0662b816fb5
+B = -ffda517d3eb3214986b04e290
+
+Product = 80bab8bd800ac8c9dc3bb57dca306f10af6fd88c5d8314833c
+A = 834bc50140d6c6ab938dc58b6
+B = fafee47793cbc533b3c66af3a
+
+Product = -b08920f5922226b1dec87151ae087d8a7e5c1aea8c9be148b6
+A = bfd5b1ad323c79428cb2db36a
+B = -eb956a10edebdd658e6810fcf
+
+Product = -6d428e08e8350bb4b0fae3b662c82df2aef7beadaa17430dbb
+A = -a57da276998c548101f514e9f
+B = a9040c1909712e1149d295765
+
+Product = a57da276998c548101f514e9f
+A = -a57da276998c548101f514e9f
+B = -1
+
+Product = 14afb44ed3318a90203ea29d3e
+A = a57da276998c548101f514e9f
+B = 2
+
+Product = -295f689da6631520407d453a7c
+A = a57da276998c548101f514e9f
+B = -4
+
+Product = -867614005cc204a8d19720fe13
+A = -a57da276998c548101f514e9f
+B = d
+
+Product = 12bf3b676f64e5929d38c35e803
+A = -a57da276998c548101f514e9f
+B = -1d
+
+Product = 24d8f92c68303ed0b96f91a8167
+A = a57da276998c548101f514e9f
+B = 39
+
+Product = -49b1f258d0607da172df23502ce
+A = a57da276998c548101f514e9f
+B = -72
+
+Product = -6fd5e6ca25c3d51b2e529f22173
+A = -a57da276998c548101f514e9f
+B = ad
+
+Product = 1276d4705b81b82da4c7e82559d7
+A = -a57da276998c548101f514e9f
+B = -1c9
+
+Product = 1ddb9abfc5d4017f068a67b5f4fd
+A = a57da276998c548101f514e9f
+B = 2e3
+
+Product = -3a8b41c914b1b4a4e341433601f7
+A = a57da276998c548101f514e9f
+B = -5a9
+
+Product = -97c0f4ba414d6e7d4c8b7ced84d4
+A = -a57da276998c548101f514e9f
+B = eac
+
+Product = 1198739e0c23639c176d46d13f7c8
+A = -a57da276998c548101f514e9f
+B = -1b38
+
+Product = 159150954ee0dedf541e4dbac0ec3
+A = a57da276998c548101f514e9f
+B = 215d
+
+Product = -441d4bc44c86f02ff12c3d91a1562
+A = a57da276998c548101f514e9f
+B = -695e
+
+Product = -64726b76005ebee27592237ba5dde
+A = -a57da276998c548101f514e9f
+B = 9b62
+
+Product = bbe4ec7cf7c5bbd198e0ea86bb658
+A = -a57da276998c548101f514e9f
+B = -122a8
+
+Product = 21f717d05681fd2eb1796776a69ef7
+A = a57da276998c548101f514e9f
+B = 348a9
+
+Product = -396ac788a1748bc6955f99be4d2c64
+A = a57da276998c548101f514e9f
+B = -58d1c
+
+Product = -54a213eb083aed1a04f3d1b2da62e7
+A = -a57da276998c548101f514e9f
+B = 82eb9
+
+Product = 1366fb9c20fb14b8b9a9be4b3e3dde1
+A = -a57da276998c548101f514e9f
+B = -1e037f
+
+Product = 238d65fd26da4733e5d93ab2485d40b
+A = a57da276998c548101f514e9f
+B = 36ff15
+
+Product = -38272a99be154d531e922be405aee9a
+A = a57da276998c548101f514e9f
+B = -56dd26
+
+Product = -64651b62b6a454c08951632c7f2c398
+A = -a57da276998c548101f514e9f
+B = 9b4d68
+
+Product = fb272e3597b816144f8b945ae6130e0
+A = -a57da276998c548101f514e9f
+B = -1848320
+
+Product = 280d9f5ed7243712ecb9a7c6358bcb8b
+A = a57da276998c548101f514e9f
+B = 3df5795
+
+Product = -2fbb6bb8e1ba78cefc47fbbc20e188ee
+A = a57da276998c548101f514e9f
+B = -49d6652
+
+Product = -57f29c13691ffa1642d2860dab9d288e
+A = -a57da276998c548101f514e9f
+B = 880c2b2
+
+Product = 139c19d7668e6aabf2d7206cb0723ed34
+A = -a57da276998c548101f514e9f
+B = -1e55aa4c
+
+Product = 2950ce04bf0cf836d4fe94b88fb757d0a
+A = a57da276998c548101f514e9f
+B = 3fe968b6
+
+Product = -5175239488dad05a58414251496d2a06c
+A = a57da276998c548101f514e9f
+B = -7e020414
+
+Product = -945ff0ed38bc6020cf679cbd3e0758c6d
+A = -a57da276998c548101f514e9f
+B = e585e573
+
+Product = 11c69ae98f6b27e95477986f796bc67c8c
+A = -a57da276998c548101f514e9f
+B = -1b7f653f4
+
+Product = 209afe75e8fb5ac76d13c06b545f5d4d73
+A = a57da276998c548101f514e9f
+B = 3270154ad
+
+Product = -386d64b215e41506514f4988ed237e4da2
+A = a57da276998c548101f514e9f
+B = -5749c891e
+
+Product = -6c13cccdb1d140d0babd52707ea72fa278
+A = -a57da276998c548101f514e9f
+B = a72fb6288
+
+Product = 136228a8a45540372b9b3cd7f82021f6546
+A = -a57da276998c548101f514e9f
+B = -1dfc08a2fa
+
+Product = 1f0ad3babf9d132eaa08cf5cdb8f19dbf01
+A = a57da276998c548101f514e9f
+B = 30050f2e5f
+
+Product = -50d615ce183258e95af77319b766fac81e2
+A = a57da276998c548101f514e9f
+B = -7d0bf92cde
+
+Product = -817d358293b86a56a4e881e50257c549471
+A = -a57da276998c548101f514e9f
+B = c84efb12ef
+
+Product = f09b9e80be251de474d726b16e25a6865fc
+A = -a57da276998c548101f514e9f
+B = -1743322a484
+
+Product = 22996cb0f9c60e35dce49f3825f8a479db26
+A = a57da276998c548101f514e9f
+B = 3585acec11a
+
+Product = -2b307a37c91791a61c0691858f5f783e4678
+A = a57da276998c548101f514e9f
+B = -42cf6be3e88
+
+Product = -8826698fcba6c30d755fc523de1cc25301ae
+A = -a57da276998c548101f514e9f
+B = d29cc8af592
+
+Product = ae37fc99fd419809310782714530d7428d77
+A = -a57da276998c548101f514e9f
+B = -10d8059d4a29
+
+Product = 1d544a20f9bc7d95ab67d1f65743979f23bba
+A = a57da276998c548101f514e9f
+B = 2d5eadef1c06
+
+Product = -367897184e9929a0294d320f10278889fbeb7
+A = a57da276998c548101f514e9f
+B = -54431582d0e9
+
+Product = -943a509076a00060a2e7fa1cddb7468d734a1
+A = -a57da276998c548101f514e9f
+B = e54bb102f4bf
+
+Product = fcce6e42879af5ad13545c0bcaab85b690cea
+A = -a57da276998c548101f514e9f
+B = -18711db522cd6
+
+Product = 258c49f86d0cbb14ae9edbd3456be8cede2022
+A = a57da276998c548101f514e9f
+B = 3a1562c7c269e
+
+Product = -4a8bbce59ad7daa51136d557f7fa16e9a2faad
+A = a57da276998c548101f514e9f
+B = -7350e780b0f33
+
+Product = -82f53ec9333275d5cc271876a7db936db49280
+A = -a57da276998c548101f514e9f
+B = ca94ad312dd80
+
+Product = 11daee4fcc713db5b2806e47fa5dff3b5b770eb
+A = -a57da276998c548101f514e9f
+B = -1b9ed6758f9635
+
+Product = 17038cac4f0c94dc24985ea108ae6682e175752
+A = a57da276998c548101f514e9f
+B = 2399b8a9b1116e
+
+Product = -37e5f14394bf347a3ed061769fe8e6424af4348
+A = a57da276998c548101f514e9f
+B = -567840a7569fb8
+
+Product = -9253d4a32a88d8f725984514d969012ead7cc9a
+A = -a57da276998c548101f514e9f
+B = e25b246f733f26
+
+Product = ace3648371c16a931d29004e79f5b9678391da5
+A = -a57da276998c548101f514e9f
+B = -10b717b27b6a13b
+
+Product = 1faa5b45d04c143c339b09d3aad94d39b94ef960
+A = a57da276998c548101f514e9f
+B = 30fbd672e106aa0
+
+Product = -3fdfe246d27aae0d08d63b2bc501461d2bff3b8d
+A = a57da276998c548101f514e9f
+B = -62cef5f078a8253
+
+Product = -5b792bfaeff04ee3d948cb343a249d49eb344f57
+A = -a57da276998c548101f514e9f
+B = 8d805ac65649c49
+
+Product = c5f824406161eec321da5a58e3e00d393b55abe9
+A = -a57da276998c548101f514e9f
+B = -1323dd41d2e1e077
+
+Product = 2226dec8a57be8e84e42559007e2d101ccbe67f8d
+A = a57da276998c548101f514e9f
+B = 34d47842b5d0be53
+
+Product = -340f50f812c7420b502000940788a700f6769788a
+A = a57da276998c548101f514e9f
+B = -508836d8e1193d36
+
+Product = -a00f1d96e19c590479625c5329a87774b5964cc78
+A = -a57da276998c548101f514e9f
+B = f798fc858657f888
+
+Product = cb94f830cba8997331912a6a31c34f1bef826d121
+A = -a57da276998c548101f514e9f
+B = -13aec7a5c52a0883f
+
+Product = 16b45140b048d6dc0b9fc811df7ce7dd88357fff04
+A = a57da276998c548101f514e9f
+B = 231f27f3e347bd67c
+
+Product = -2aa94179351b4e87de5849ab619d94f47450640199
+A = a57da276998c548101f514e9f
+B = -41fe3ec2189599cc7
+
+Product = -5489401d3da93158d4284e557d74016c0a7cfd935a
+A = -a57da276998c548101f514e9f
+B = 82c5281df41bfc066
+
+Product = ae04d5b212ecfc9a6d7df07794d565df52991fb70e
+A = -a57da276998c548101f514e9f
+B = -10d3139229f5d02432
+
+Product = 27821bc811f45d63089790b41d307be978d4b19564c
+A = a57da276998c548101f514e9f
+B = 3d1da85cc012b3e234
+
+Product = -3de3c9e9d7fa3020a578706339314890dccf63096c2
+A = a57da276998c548101f514e9f
+B = -5fbcfb28bfc9044bfe
+
+Product = -627dcb299a6720044abcf11469bdfd3f951edbb5bf7
+A = -a57da276998c548101f514e9f
+B = 985b930517b78e6ba9
+
+Product = cc0622441497a37fddf1856d5e2c99df52b99ea4573
+A = -a57da276998c548101f514e9f
+B = -13b9b88948fb7e95cad
+
+Product = 1a5168e1a492210591ad1ed660adde9110390e4caf32
+A = a57da276998c548101f514e9f
+B = 28b631c6e04b6ab0d8e
+
+Product = -4d8ec27b7460ce616421b9f5cae708c2ac241daa59b4
+A = a57da276998c548101f514e9f
+B = -77f99bdf1eb09da6dcc
+
+Product = -55afd796db7bce822a00073fc8926d3bd0c79772f036
+A = -a57da276998c548101f514e9f
+B = 848cdd6212b9bb3620a
+
+Product = dc494b0d73e8ec07cd2bb6dd8191d2b4d48e7700cc34
+A = -a57da276998c548101f514e9f
+B = -154c39567bd8be5f6b4c
+
+Product = 240e9301b4345b914ecd91a49a0e651524dcecb6fdc6c
+A = a57da276998c548101f514e9f
+B = 37c6e7ee89cf87674814
+
+Product = -39002ecfd6d96661b336157ccef6536756ad2e9219be3
+A = a57da276998c548101f514e9f
+B = -582cdab09915a652203d
+
+Product = -695f49fc891d53f396f0593efae3973082b76d4f9e944
+A = -a57da276998c548101f514e9f
+B = a30074dbce2246af043c
+
+Product = bba2b7b45b97cb0d7fb30fed95089870742ad69e7aed7
+A = -a57da276998c548101f514e9f
+B = -1224195afc7b394ae8cc9
+
+Product = 1910edc278515ab7d4cc09b496dc3c06c32c75bc7368af
+A = a57da276998c548101f514e9f
+B = 26c6701c39334169e7bf1
+
+Product = -3670b7f9b661aba35ce50984d83173c84c8fa60e04d100
+A = a57da276998c548101f514e9f
+B = -5436e84b4a29858a68f00
+
+Product = -7fa0d3e0082b37475342b7e22e5dbad7b8d4cb5d64f871
+A = -a57da276998c548101f514e9f
+B = c56e0f44fc63bca242eef
+
+Product = da7fe3367ce640fa5941c033ac1874312f10ba5950da75
+A = -a57da276998c548101f514e9f
+B = -15200043166ff309f0426b
+
+Product = 1871d72481f66b1d413100edd6b339cbbaa67b3b2b3cd57
+A = a57da276998c548101f514e9f
+B = 25d057879db26fa29a5e49
+
+Product = -3cf1dd1e2df3456757d72f35353c3c7a659b2ef844ad857
+A = a57da276998c548101f514e9f
+B = -5e46be70de21949df67349
+
+Product = -5e861cbe47aefab2a7ea59292aab1258932b9a322f66e63
+A = -a57da276998c548101f514e9f
+B = 9238670897685a6c9cbdbd
+
+Product = f623344788efb857db55c924e95a437effa4dc8bb2bcd24
+A = -a57da276998c548101f514e9f
+B = -17cc0ec84c228225a7cf45c
+
+Product = 15514c916b0ae7cde6add16c629d3e19ba52a101d75dff72
+A = a57da276998c548101f514e9f
+B = 20f9f925b3ed307edbb154e
+
+Product = -460cf5b14f9d0b547c3084bf44207bf881745c409b08d07f
+A = a57da276998c548101f514e9f
+B = -6c5cbfd29f3dae1dce99221
+
+Product = -5ddf7fb91d765af97dfda5333d8779e80837c2b51cfb4f43
+A = -a57da276998c548101f514e9f
+B = 9136aa79080defd1bcf90dd
+
+Product = 12c1a0edfb6ab6a0caae2553fb3743827e1470a8954e0a3fd
+A = -a57da276998c548101f514e9f
+B = -1d03b512470dc3052779f3e3
+
+Product = 28388a244214abf046488a8d95308d95f021eae4b994a5a52
+A = a57da276998c548101f514e9f
+B = 3e37dce784274962ff862e6e
+
+Product = -4da476e76119deef291c0f56934a912a0877278a19a561ee0
+A = a57da276998c548101f514e9f
+B = -781b2f2dc40094a7f8fed520
+
+Product = -5792496d33dd45e225f9dfca17419a04e075ffc0c90b37b82
+A = -a57da276998c548101f514e9f
+B = 87772a4fb582acafd3e4ef3e
+
+Product = dd3a3506a7d748de16fb43d666928a87de0354d8e8a1bcaaa
+A = -a57da276998c548101f514e9f
+B = -1563841bf7851ff158a395716
+
+Product = 24e8fb09a9ab0808ff643122479dea5ed41060c6c5b74e8752
+A = a57da276998c548101f514e9f
+B = 3918c30b5568318a58e9be16e
+
+Product = -366c125f96b38b58d01c939c27c4100af3377eabb792b5491a
+A = a57da276998c548101f514e9f
+B = -542fb814f45924aa09a16f2a6
+
+
+# Quotient tests.
+#
+# These test vectors satisfy Quotient = A / B, rounded towards zero, and
+# Remainder = A - B * Quotient.
+
+Quotient = 1
+Remainder = 0
+A = 8cdaaa7c422f3c2bb0ace2da7d7ff151e5bdefb23e6426cf3e6b21491e6e80e977bfa6c65931a8dee31fc7992c0c801d5d7c
+B = 8cdaaa7c422f3c2bb0ace2da7d7ff151e5bdefb23e6426cf3e6b21491e6e80e977bfa6c65931a8dee31fc7992c0c801d5d7c
+
+Quotient = -2
+Remainder = 1
+A = 107f0e6cebfe22ac11294a06fed2b994d01c9b3610d50bdd254adafd08c93be8ebdd1e85e1286fe9c9e682a90cbbd6351681b
+B = -83f873675ff11560894a5037f695cca680e4d9b086a85ee92a56d7e84649df475ee8f42f09437f4e4f34154865deb1a8b40d
+
+Quotient = -4
+Remainder = -2
+A = -3d8746ae2123c2d3f1d35910b42af1f86f5e81f8e98986cea20b2a1bdb8af6cf111f1258f112c837accdf4868463fe9eba536
+B = f61d1ab8848f0b4fc74d6442d0abc7e1bd7a07e3a6261b3a882ca86f6e2bdb3c447c4963c44b20deb337d21a118ffa7ae94d
+
+Quotient = 8
+Remainder = -3
+A = -5645d65662eaac73050de06f8f982a9b2ae680467712284be3e2b0e58ef4bf4d72b5be5e12ee1fd803b47f161759662ff5c4b
+B = -ac8bacacc5d558e60a1bc0df1f30553655cd008cee245097c7c561cb1de97e9ae56b7cbc25dc3fb00768fe2c2eb2cc5feb89
+
+Quotient = 10
+Remainder = 4
+A = 813bc46ee19ffeab364073a89f96913f340d43ee72129ea9edac1beb4ebe1336450d2eabc7b26e51c400cec60d6ee459033b4
+B = 813bc46ee19ffeab364073a89f96913f340d43ee72129ea9edac1beb4ebe1336450d2eabc7b26e51c400cec60d6ee459033b
+
+Quotient = -20
+Remainder = 5
+A = 12805392c55ffa0e27e85e15f2b339872793664e9ed3074cd2600aa52459a57197130d1ea46775ef43115c9413248cc7b34805
+B = -94029c962affd0713f42f0af9599cc393c9b3274f6983a669300552922cd2b8cb89868f5233baf7a188ae4a09924663d9a40
+
+Quotient = -40
+Remainder = -6
+A = -3579fc4d6083394c691b060cf9e20318fe17da0487337f76710bd11512578830ba94ac7b587a2d5ab7cb4afe611e349cdcfb86
+B = d5e7f135820ce531a46c1833e7880c63f85f68121ccdfdd9c42f4454495e20c2ea52b1ed61e8b56adf2d2bf98478d27373ee
+
+Quotient = 80
+Remainder = -7
+A = -74ebad4b39ebaaff82cd91082408c979527907c363d8f0f75db410523f8477c074c45ff85851b6275b1ebc5279029818e78d87
+B = -e9d75a9673d755ff059b2210481192f2a4f20f86c7b1e1eebb6820a47f08ef80e988bff0b0a36c4eb63d78a4f2053031cf1b
+
+Quotient = 100
+Remainder = 8
+A = d2d8a4419fb3b1c22bfca04ca08c2ee066ccbc9fce2f41861b5eef91efd3c13eeb7eae5abea0ef1849662cfdfef7bbff892c08
+B = d2d8a4419fb3b1c22bfca04ca08c2ee066ccbc9fce2f41861b5eef91efd3c13eeb7eae5abea0ef1849662cfdfef7bbff892c
+
+Quotient = -200
+Remainder = 9
+A = 1bf534da2f4365c96fc5dd4928e73ac24b157b5136ead90cf6596033ec387a2c14bca828000ae1725f3a5ace8ad67a8c07a0a09
+B = -dfa9a6d17a1b2e4b7e2eea494739d61258abda89b756c867b2cb019f61c3d160a5e5414000570b92f9d2d67456b3d4603d05
+
+Quotient = -400
+Remainder = -a
+A = -3a172cc9483774544311a1366659d9e61cc9fac7dc11c68e36aa991ef4d5e96becf5bac3e0967c904d926617ea11bb9551b980a
+B = e85cb32520ddd1510c4684d9996767987327eb1f70471a38daaa647bd357a5afb3d6eb0f8259f2413649985fa846ee5546e6
+
+Quotient = 800
+Remainder = -b
+A = -5ecff3a3e47fa615b6e3ce2dedfdeefbfe1d437c394631820968a9650b59dc3a2dd1c9a0b06537e4e5c408a59e580921503580b
+B = -bd9fe747c8ff4c2b6dc79c5bdbfbddf7fc3a86f8728c630412d152ca16b3b8745ba3934160ca6fc9cb88114b3cb01242a06b
+
+Quotient = 1000
+Remainder = c
+A = d3ef80fca0ab3ac3432b22e2b485131d816810c39d02a9c82dcc05ec5e6406bc216026de3abe53ab103ea3b2ddbc2ea377ae00c
+B = d3ef80fca0ab3ac3432b22e2b485131d816810c39d02a9c82dcc05ec5e6406bc216026de3abe53ab103ea3b2ddbc2ea377ae
+
+Quotient = -2000
+Remainder = d
+A = 163956bc32325f28f48d41d32bb08d2a9c4ccbb0d818368fb13941e82b27da21d04094f7e897ce79c2d0ff8470505f1ef63fc00d
+B = -b1cab5e19192f947a46a0e995d846954e2665d86c0c1b47d89ca0f41593ed10e8204a7bf44be73ce1687fc238282f8f7b1fe
+
+Quotient = -4000
+Remainder = -e
+A = -3763f8e43bd05e6ffeec6d509bbe6ff9a9022ced8cb191c9abaf5fd0e0b75a53e2ad581455e3af09e702a77b164ed3fb54ae000e
+B = dd8fe390ef4179bffbb1b5426ef9bfe6a408b3b632c64726aebd7f4382dd694f8ab56051578ebc279c0a9dec593b4fed52b8
+
+Quotient = 8000
+Remainder = -f
+A = -531dd44dfa9e79a5aec8fa7c84bd3b753c146770d22d2c14a6d2125f7ab95e9b320e84c31cf3e0d883e1295a220f2a546550800f
+B = -a63ba89bf53cf34b5d91f4f9097a76ea7828cee1a45a58294da424bef572bd36641d098639e7c1b107c252b4441e54a8caa1
+
+Quotient = 10000
+Remainder = 10
+A = 900996b61f58713f0755e68bbdfa4e0bb47f034bb0304f77829847923d14715def1771f43b526c41b9667438b434d2b966c20010
+B = 900996b61f58713f0755e68bbdfa4e0bb47f034bb0304f77829847923d14715def1771f43b526c41b9667438b434d2b966c2
+
+Quotient = -20000
+Remainder = 11
+A = 179d7ede3db0c105525286551331d5b9e1f97a7883f0c13cf250afe9765bb5aaa527af7945c19cdd4596565cbc8532a3cfa5c0011
+B = -bcebf6f1ed86082a929432a8998eadcf0fcbd3c41f8609e792857f4bb2ddad55293d7bca2e0ce6ea2cb2b2e5e429951e7d2e
+
+Quotient = -40000
+Remainder = -12
+A = -293dc443c294c6a6c53dd49e84f58305d59a432afb6c7ea2039cd02a513231239571ae07f29b5427e869b9faa485511ca45980012
+B = a4f7110f0a531a9b14f7527a13d60c1756690cabedb1fa880e7340a944c8c48e55c6b81fca6d509fa1a6e7ea921544729166
+
+Quotient = 80000
+Remainder = -13
+A = -5b637eb8aa51ef15a18d9b144031c9756527fc0fb96c84b6df03700e5079ae1b3e96940a2c1e07f3b47ad8a9b2b8ca99171a00013
+B = -b6c6fd7154a3de2b431b3628806392eaca4ff81f72d9096dbe06e01ca0f35c367d2d2814583c0fe768f5b153657195322e34
+
+Quotient = 100000
+Remainder = 14
+A = 87c846f5469d4c5819aed0c7e77797209b2c1b83a7a0e2be70280b9f30946b5db9bd0f25a06cf4bdba1c7183a1b9eb75c19400014
+B = 87c846f5469d4c5819aed0c7e77797209b2c1b83a7a0e2be70280b9f30946b5db9bd0f25a06cf4bdba1c7183a1b9eb75c194
+
+Quotient = -200000
+Remainder = 15
+A = 11c2a4509f419aa977c3d37fa446fcf21b4b3b9f983fbaddeba4f51c285ac4032200711a54cc6edf24297b1f3d46ad020131a00015
+B = -8e152284fa0cd54bbe1e9bfd2237e790da59dcfcc1fdd6ef5d27a8e142d62019100388d2a66376f9214bd8f9ea356810098d
+
+Quotient = -400000
+Remainder = -16
+A = -39e37ae0edd92b957e84682358039f5e432c42492a44f3de01cdf74d643760260f2837946608663e12291e9b0695449c1153800016
+B = e78deb83b764ae55fa11a08d600e7d790cb10924a913cf780737dd3590dd80983ca0de51982198f848a47a6c1a551270454e
+
+Quotient = 800000
+Remainder = -17
+A = -72f725edd5a3dd6f20b5e9ca7da08a99f8ec9214c80588182c0d42e03bcff34b488b28c03cdf41813a6193c10672a8ee68f6000017
+B = -e5ee4bdbab47bade416bd394fb411533f1d92429900b1030581a85c0779fe6969116518079be830274c327820ce551dcd1ec
+
+Quotient = 1000000
+Remainder = 18
+A = 966df62c26acab2d3d1dbe729e48d0181c68e9f5eba45f6caefa38d60e34057d09fe620abb8640cec8cac755957aaad7c6fd000018
+B = 966df62c26acab2d3d1dbe729e48d0181c68e9f5eba45f6caefa38d60e34057d09fe620abb8640cec8cac755957aaad7c6fd
+
+Quotient = -2000000
+Remainder = 19
+A = 190790727c1514b4ef83a1c6aa07493c0af7087fbc8a675bfd9a1e97b8ef80ef684219d6c6f1a5fb5b919f105fd7717cdd5aa000019
+B = -c83c8393e0a8a5a77c1d0e35503a49e057b843fde4533adfecd0f4bdc77c077b4210ceb6378d2fdadc8cf882febb8be6ead5
+
+Quotient = -4000000
+Remainder = -1a
+A = -22d115ab02f8663d8c009960086a0275d301d358cd3b250bb9e7c16cc6ebed4a8fbe43bbced856d93be64a17377d95f5f9c8800001a
+B = 8b4456ac0be198f63002658021a809d74c074d6334ec942ee79f05b31bafb52a3ef90eef3b615b64ef99285cddf657d7e722
+
+Quotient = 8000000
+Remainder = -1b
+A = -41f2e708ba47494a13607223b08e6d99c0b4247436632961d873804e83446dc97139ffaef3e25969950bd4b5bb4ff73b1a25000001b
+B = -83e5ce11748e929426c0e447611cdb33816848e86cc652c3b0e7009d0688db92e273ff5de7c4b2d32a17a96b769fee76344a
+
+Quotient = 10000000
+Remainder = 1c
+A = e4b52f78179039499c2f6b500840f41103fbd60eac0d7082297236f25189c18a8301a92f533945047fbb83427dcade334336000001c
+B = e4b52f78179039499c2f6b500840f41103fbd60eac0d7082297236f25189c18a8301a92f533945047fbb83427dcade334336
+
+Quotient = -20000000
+Remainder = 1d
+A = 10888959278661bc36089519a215bda60f9ce24ff7c0ac1f543b6e652f94dbff1f32aa40cad2b4b4d676f16948551501c29f2000001d
+B = -84444ac93c330de1b044a8cd10aded307ce7127fbe0560faa1db73297ca6dff8f99552065695a5a6b3b78b4a42a8a80e14f9
+
+Quotient = -40000000
+Remainder = -1e
+A = -3ada453530a180fda58533ab8c62beb4f693a134f512e4d23e487dac3b575e5390c0a90992400e402bb47aac93d46ded55f54000001e
+B = eb6914d4c28603f69614ceae318afad3da4e84d3d44b9348f921f6b0ed5d794e4302a42649003900aed1eab24f51b7b557d5
+
+Quotient = 80000000
+Remainder = -1f
+A = -57879eb5d92d565daac3ac5173639bfe44b6ecc69ff770af57bd79c9b93841c5677042cb362b794f3d8b24b0d3b73ed1cba58000001f
+B = -af0f3d6bb25aacbb558758a2e6c737fc896dd98d3feee15eaf7af3937270838acee085966c56f29e7b164961a76e7da3974b
+
+Quotient = 100000000
+Remainder = 20
+A = 89a2f1792afc54467955839eddc9ef2e37d391ce7a1a4a205291220c1f49f59ee31fc7a7a7f7706c199bf5c8c951a0d0743d00000020
+B = 89a2f1792afc54467955839eddc9ef2e37d391ce7a1a4a205291220c1f49f59ee31fc7a7a7f7706c199bf5c8c951a0d0743d
+
+Quotient = -200000000
+Remainder = 21
+A = 1c267719338a4562e934bc57fabe6da86ca534a34244bd38c15032f01f47c2fd498c83f644b345c5c661ada0e586a096bb63000000021
+B = -e133b8c99c522b1749a5e2bfd5f36d436529a51a1225e9c60a819780fa3e17ea4c641fb2259a2e2e330d6d072c3504b5db18
+
+Quotient = -400000000
+Remainder = -22
+A = -250249f2185d4b428fa9534f03ef3cbed535bd31c56c0b273e6c3d35e0266f7777a6e59a99da5738b8e3af8ac60061d6716ac00000022
+B = 940927c861752d0a3ea54d3c0fbcf2fb54d6f4c715b02c9cf9b0f4d78099bdddde9b966a67695ce2e38ebe2b18018759c5ab
+
+Quotient = 800000000
+Remainder = -23
+A = -710b30c23c3c4e646ba90da33d2ce35af2ff181c40b02e3ffa607966730c6b6e274dd4c3c78e578e0b10f431f2d832274bf6800000023
+B = -e216618478789cc8d7521b467a59c6b5e5fe303881605c7ff4c0f2cce618d6dc4e9ba9878f1caf1c1621e863e5b0644e97ed
+
+Quotient = 1000000000
+Remainder = 24
+A = 877f1caf75e7166ef18484d0718947893fd1ec016984387debc55c19e378a487a5ddbb03a80a88316f6fca16ae148933e719000000024
+B = 877f1caf75e7166ef18484d0718947893fd1ec016984387debc55c19e378a487a5ddbb03a80a88316f6fca16ae148933e719
+
+Quotient = -2000000000
+Remainder = 25
+A = 1ed1b7d9e4cf3d44ee98ef69850e61a39f54cc407c6795c07c887374441fd9ec258c21193f8a8c55802fb8f8c579cf94cb0ce000000025
+B = -f68dbecf2679ea2774c77b4c28730d1cfaa66203e33cae03e4439ba220fecf612c6108c9fc5462ac017dc7c62bce7ca65867
+
+Quotient = -4000000000
+Remainder = -26
+A = -35d324ba37d2000f960ca1c9e1ab96e341a2ae6a5ea5cef014c73a39dde000d8ad9606b817ad67e4e4593cc5894d354854898000000026
+B = d74c92e8df48003e5832872786ae5b8d068ab9a97a973bc0531ce8e777800362b6581ae05eb59f939164f3162534d5215226
+
+Quotient = 8000000000
+Remainder = -27
+A = -7039477c3e0a6f415e25e9f9b1dab1edcd8a23f984e7e3bc149c206a3b756b1be001450af4049cd4535e4243d7032afcf6790000000027
+B = -e0728ef87c14de82bc4bd3f363b563db9b1447f309cfc778293840d476ead637c0028a15e80939a8a6bc8487ae0655f9ecf2
+
+Quotient = 10000000000
+Remainder = 28
+A = d6c59dd07409da98f7bbc7ee471b6e06c4d9e832e9f4d04ed9da63564d37d3072a950564cf549bb5d6e7dc85565d3cc8ba340000000028
+B = d6c59dd07409da98f7bbc7ee471b6e06c4d9e832e9f4d04ed9da63564d37d3072a950564cf549bb5d6e7dc85565d3cc8ba34
+
+Quotient = -20000000000
+Remainder = 29
+A = 14d27a16a9cf2fdbc85b88a604dd8f0e57b5b34a27089d75d805e05fbb367dfa61c085aa98b896e3e53b85ef774a3fa52417a0000000029
+B = -a693d0b54e797ede42dc453026ec7872bdad9a513844ebaec02f02fdd9b3efd30e042d54c5c4b71f29dc2f7bba51fd2920bd
+
+Quotient = -40000000000
+Remainder = -2a
+A = -3bd0119619fbb5b260c44050d61e6b1925a49713d754ceb06bafb1d730a93f199df654b153c40e75096ebbaf5a6ce3c801820000000002a
+B = ef40465867eed6c9831101435879ac6496925c4f5d533ac1aebec75cc2a4fc6677d952c54f1039d425baeebd69b38f200608
+
+Quotient = 80000000000
+Remainder = -2b
+A = -61a283fe41d965ee770704bb453f689cb82a81089422d6d904a91776a06d32857220286e6ef6327807b724062dda143b46890000000002b
+B = -c34507fc83b2cbdcee0e09768a7ed139705502112845adb209522eed40da650ae44050dcddec64f00f6e480c5bb428768d12
+
+Quotient = 100000000000
+Remainder = 2c
+A = 87bd03a64d9c56fe340137065ba36bd07b556119546dd1fc3ae087ead32bc79ca7efb5c7230ea7bfb00ad419096d9279fbe10000000002c
+B = 87bd03a64d9c56fe340137065ba36bd07b556119546dd1fc3ae087ead32bc79ca7efb5c7230ea7bfb00ad419096d9279fbe1
+
+Quotient = -200000000000
+Remainder = 2d
+A = 1eb7cfb197d19f56ad994eca52d1af6466fd09da07d68d63067602046b2d42d3063ef5eda6b58afd69fd92b0b727a0ecde1420000000002d
+B = -f5be7d8cbe8cfab56cca7652968d7b2337e84ed03eb46b1833b01023596a169831f7af6d35ac57eb4fec9585b93d0766f0a1
+
+Quotient = -400000000000
+Remainder = -2e
+A = -3ab858b3329e5bd0469118be52a867b2febbe2894d962cedeb3a5be1738db1cea106cd0710c9f6937348c2c63b109ae623d500000000002e
+B = eae162ccca796f411a4462f94aa19ecbfaef8a253658b3b7ace96f85ce36c73a841b341c4327da4dcd230b18ec426b988f54
+
+Quotient = 800000000000
+Remainder = -2f
+A = -6137bae6cf7573afcbb6fd5c066ba37648cba8db0ecafe9dbc66959b19deabf42f3083719a2268b7602bafa2140a1ee8ce7d80000000002f
+B = -c26f75cd9eeae75f976dfab80cd746ec919751b61d95fd3b78cd2b3633bd57e85e6106e33444d16ec0575f4428143dd19cfb
+
+Quotient = 1000000000000
+Remainder = 30
+A = d00fec043edadc093673e5f5abef0c6bacdf1f3faa49a831a645bf80db7539d657f69403b122a5c6f879eb8e63be54d35ed7000000000030
+B = d00fec043edadc093673e5f5abef0c6bacdf1f3faa49a831a645bf80db7539d657f69403b122a5c6f879eb8e63be54d35ed7
+
+Quotient = -2000000000000
+Remainder = 31
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -940693131e2ba7b2af531803794983337dd526f0d84d08d58723edf002a388d55c8502d88c2a2a6e78233a2a1b1c8d339a13
+
+Quotient = -611b743a0e2acb1043bb33de50a59eaa0405b37bf6b622075dd69291fe5b53305dbfcc377d1f3082319c153d0c1ffb3b3346
+Remainder = -16e346b6a4297
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 30c77f3380ccf
+
+Quotient = b9e34073d5e6e5b9e5d2d7250150f8ad86870faeb88d5aed5029fb25c176de216e2388e0f5d33f7c3b56102873eb40b06f2
+Remainder = -16ebc86eb88339
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -197b6f6ad5b75c
+
+Quotient = 141bc8752e846cd63743e6fce4a22efc3eb5f0ce46ba81b8f578c94c516288ec3610fc9923f45d4af2b94c0b0a20b48ed0a
+Remainder = 9bab19f12d81c3
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = eb90162ecae18b
+
+Quotient = -381bd85c951e1dd775b0d7fab344aadf06b1b592c643b5852fa44aa55159eedf3b3e47fe0d9f399ad92da85ab2bfd18240
+Remainder = 1e4f817a2f52b71
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -546c109fa8a9d7b
+
+Quotient = -5e385a83b56830626cf8306acc232f955178080e86384bbcf92eec3a8961360223c4cfc1d8d118022972e61866cbfc46b
+Remainder = -292e149300fdd1ad
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 3246242094394c8c
+
+Quotient = 9af0246f4b49316df43f61ae3795a764fe9b1d071ce227982ebda7988a7a7a98129c94a76635c6913cb15e4f75ea1608
+Remainder = -dd3b3e32ddc79cb9
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -1e928618913898b2f
+
+Quotient = 1fe40099811c648aa4e84e4fbb8cbc19706774a11391fc03a9667d8dc72dd0b26c4a46d0bae56ba90fe4bfac1517d241
+Remainder = 16e021603d30dde2
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 948887c1634f4b08f
+
+Quotient = -3f4fa4c179dab02ad461bbea8f890292c934496db560f72878323a4463d77ae261363f4dc8f53eab145fcc3815d3253
+Remainder = 407ccb4f0b814dc5c5
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -4ad17434071e1ce664
+
+Quotient = -4d17d19f7f6861189a520776339a1e425876808111c303e391118714370111151ef4ad2e6e84250f59b0fe09ab3293
+Remainder = -36f745b0f421d16db7
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 3d71635bcc25183cdde
+
+Quotient = b976d544af44e711351c6618106d3a002c42ebbe22fe939a2457d24e8dcc35c95dde5c7c77af6b4545344a198be82
+Remainder = -107334ab98e5099fec5f
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -198a54e35fa0cfa328a9
+
+Quotient = 1307bb8e89aaff7466bc238d32672fbbde7be19d15423bcfa14f9a23fe85af9739b72807fd4bc420ad0b0fac37a42
+Remainder = 170ebe9b83d4c43b79ab
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = f8e923a8bbc0242eafe3
+
+Quotient = -3925a167c1c4d2fae265f277302b989466e309a7211e0b7173031cbbb91ab7fac8dfe43c9d832764e222e9d8581d
+Remainder = 4d404e93edb435dbd60af
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -52e36cee22274556059ea
+
+Quotient = -4d5a6ef346a872142b999ff9a5429198b3c2a97e968f55aa2c01583efe30e9687c57e2bca2372db4d3d443052b6
+Remainder = -3a2ea5f9d204dc31f21833
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 3d3c79a115d9071b573d2d
+
+Quotient = a49dee54430f1737a04543d5f549efafab25f0f28f5e304f1bbca191f99521c2c4be1b9927bde19e1ec2060bb2
+Remainder = -17d02758f8fcadca911a95f
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -1cc65a75211f2826c9d0811
+
+Quotient = 1808ab7c0ccac2ff8f7cb61248bf4624fb60352a356fdd1408904f8c6fb0cc52b7642ec59183bcaf5dd89ca0ac
+Remainder = 5c95323f3b8861261dc31ed
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = c516e6e3fa6e3dc52cf5933
+
+Quotient = -437e04d7076794850aada0cb4ca7a1055df103e74e00766be6a2fdb2631bf294cdbf2695d0a2f8f9eb5587aa5
+Remainder = 1fc63797594c56160536faa9
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -462ee529b488d1db2b6c60e8
+
+Quotient = -5dde5497accc4575a412e7232ce75bdf7905936e09e382d5c9f133faf82a05ad9dcc94ad858aed34cc14c714
+Remainder = -15e79293d5e055f906381a899
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 32765b0a34c88864d39bedaae
+
+Quotient = 11ac52a9287472e1d3b8577b3d50c95076e190714796761322b3ce869d96b44387e190e824849ee345d0a22b
+Remainder = -a158ccc7c055d64e7df3fbcf0
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -10c061a37f6cbd11bf0c327643
+
+Quotient = 1ff5cda1551867577c5ca72c86516a82fb8fc5f59ce967b73c6bcc1b85168389872c9a747ddf044d6dba174
+Remainder = 21e766a0020ba429b330a325d5
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 9435cd2dc2a92c950bb9e69b83
+
+Quotient = -2719c892fa3f4dbc9951b2095056a16159adaf32dff902e20a800a0cc2e858ccae408f2161aae25d3e1f6d
+Remainder = cafbe9caa1f83fd0dd3d5a6881
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -7924e4dcf8f96da61f54bf83870
+
+Quotient = -5080dc99dba295f4a2d9a474c2ddfa3b232a82fe629fe62177514988983eff8195b37d3fee3afa343b497
+Remainder = -94ae72f78982ac1ff83f300cfe8
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 3ad70d4b6b9b5f5b2eb65da67e1f
+
+Quotient = e475eebcfc53d49ffad2e0c2a4ba48fe7ce02c42ff107e01ab3fe5b26eee45c83c4f58c181d77c259155
+Remainder = -c83ac7582a02b47ee734e0f24dc5
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -14bbcff5423a260b21895327b18bc
+
+Quotient = 201308a421b85291d23465d648ad2a8d6f3393efc16fb675a42ea7bbca635ddd8c2449b1b34e5db30a03
+Remainder = 8e07efb8ae4c9df39533042362081
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 93aebb72a81ba68e8881fd1a56a90
+
+Quotient = -2584cc534f88f091fe471c652ac66a695906a7cde1fc1cde9be3ee09026b690c1a899378ff31f6acb90
+Remainder = 794801d9d5770a60e312b99d6b9f91
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -7e408caf387a0ce9bbf4309c80755a
+
+Quotient = -63f7bfc0fe5a5421bc0a19fa6c87713a72eeb2a33e5eadee8c2f32c20d14f403ab8bdc424b9e8e0c68
+Remainder = -24227c242afedee2473c1a66a5cc29
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 2f622c665af7f8126eabfd90df8e9c5
+
+Quotient = e557e6d2180aeeee5d2cef453fbdf38e84cc148f4608ade8836045498be2d318520ffadcea6319432
+Remainder = -dd290149e0e159f9ba6bb9f5a4b003d
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -14a7623d1d9dfc177e913d3119d0d30a
+
+Quotient = 1651d852316d472b41ba0460566e43fabb9257861859ad0fb6ea5a6433a4164299e078f4d50c58afb
+Remainder = fb60aff5fdd2a2b794b0d973ac4d92a
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = d439da27b5e70342aa5cb365ece15665
+
+Quotient = -3ae357761a8ff43d3b1bc53eb336260342a39d22f8fac44eeeac96c2f6de32580dd6a688faa9c515
+Remainder = 4fa6f7ee4faf2f6be99c5ce4b65cd642f
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -50700f9c0da59482165a47a3eda2bf07a
+
+Quotient = -543b4390e4e254226683aa0b83b2ca176ec27a373969fb88f766ac72adc9125ff83b2652e46afd3
+Remainder = -12ff398d9a7d9e97a7f63a0bb293c8fb0
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 383c5a4f1767e83fc382ad4f1c7c2b7ddb
+
+Quotient = ecb72c14c59d49287fb6b2cacdf04619ee617d5f3f0f1b2890fd4e79746a4fbd848613cf5eb437
+Remainder = -1035512a2717a89062d48f1bfd213333ed0
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -1402b751a1e5f3fc46e22b43240d6ce9b27
+
+Quotient = 1e800ddc5d5126f322298383f32fd593623eb88a91b2d68c5d9f56e20c16ffe2cefabe873570ab
+Remainder = 72935d534bed5ba557b91ea023601f50b1d
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 9b4df766c608ff3efe5ea1f65cc850fa73c
+
+Quotient = -2c2dc2378abceb983904cdf6728f361d279b4c821710ae785724a7251c43fe4f705f023afa7e2
+Remainder = 249f6433af4e8e224eb570fd438197af62f3
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -6b382f812816c77d65c94c0c660b31a69b8f
+
+Quotient = -5f3ced1e42fbd3c6b2c6f1e16953e0c1bb6efb4e49566f974a968f69a1a66a3d7558f5a802a8
+Remainder = -317a7fb1af65982fe4641fbb1e5837e6ea3e1
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 31bc97372d17038fd842b72eaba2abb26df62
+
+Quotient = af3fef8111c449b9e0858e7e53e1d00b764232f7a077d75043249c387ece30af351c8a40335
+Remainder = -a1493bcbf57a8480461d62796aa8f8541ece4
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -1b076b2f7b78b4a0f0e24ba3a05d6c697efab9
+
+Quotient = 196734cefb08f09cb32ffefc07da8d9545d3451d5a08736757184bad94c73be71311cf1e01c
+Remainder = 273e33521f4d74840a96b3fffe169f79d32855
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = ba7746f4400f812919a3dc86b00642e1487691
+
+Quotient = -3c5989cf33145057a9c8e904435d12939db519cc6b9ca1c0a11934399cb139a73613950f2f
+Remainder = 456ebf56c636d54e37709b9e799e83b7a08cb93
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -4e7d4f389423f42e980eda55b4a6a45f6f4bdc2
+
+Quotient = -8432cf3338bce1d12586f83025aea50cff3864af3eb2103a36bbb0aba10b0ba4831641633
+Remainder = -4f62c678137df301c4bef216e6aa910104e76ff
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 23d4c57b5a8162aae8d937be12efbcfd7b96ec06
+
+Quotient = 9f94c4399eef16dfc65a1e015e0786c86470299865932c4d564b71c9b1551a9c0308af38
+Remainder = -168b74a6073b4a5b54fa14aacb5c3bb7897ed0fe1
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -1daecf01ec633610373b79e04c22cd7499012bc66
+
+Quotient = 1d5b838dce6c0324f157ad125adefde6e1045dce9ff97cf8d1d39b79bce02128e3433ffe
+Remainder = 3aa816216d55fc3c910a030fd10fbda1e12f2ac2d
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = a1598a12a84e9cba42ea0e200e88d4599c9f615fe
+
+Quotient = -3edb182b53890ca8762f3039d2d71a8a27c36cc884d0879e0635e6326af0182bc47cad7
+Remainder = 4610b2b1305220bc0de584dd3f87d90109012a8077
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -4b5c2f1ba3a82047c9de61d47cbf1bec86b6ef90d6
+
+Quotient = -7571ed4c509630886483f6ca0923859e644063acb38cfb338bf3a681fe449501262516
+Remainder = -21c579846594fc3e5efc53ab01576a7b32d69faf41f
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 28550e1f7c6492f4cb682c37b105f92b049c13fc03b
+
+Quotient = 9ed8fb31327a110ef4377258681c5287de8ef9dbe62aa4fe84a7f2a94bb69607cbdb2
+Remainder = -1b7bb759dd0ebc346cbe216e56be8063f063490c17c5
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -1dd1e61caed1efc07d21ce05d889de1ad65808cae026
+
+Quotient = 1aa716227d1ca6af68286062b2d6dafd7ade16abbd5d6fa4ada0365832fe18f73bf35
+Remainder = 32e714b0c4ecefb38735cb88cd5e07c21c81be858cae
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = b1b959a7b3262d7f4dff488315903aeaffd982b726d7
+
+Quotient = -2a9979a530046939e0b43a25edfbea6775784eb5cf346a9fc3a2d22e1aad473cdada
+Remainder = 4edeb91a2472e80068b1883cf2cc45d68ff9bbed1756b
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -6f31bbe097587a68fdf01d0bf93830bd03a23920ccc0f
+
+Quotient = -566ff76814e1c7d31ad53bfb9f3c0607ef1f7d1cf9bdee6e1cfb78b3ad7018f8bbd
+Remainder = -1eac095d6d84021c33aa9b219d191bd0637f20b5920eed
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 36ccf5bdece624b4f54c729a8cde13325d8dd764f44894
+
+Quotient = aee4f377611179d8b6315811dd94639aaaee63e99bddcfa8eee297ce1dc04daf8e
+Remainder = -59cb3ba7efa1637c46b21795872e8deaff90f13402cfaf
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -1b157ad838684b45065aa77ca3238a4d8c5427f719cdfb7
+
+Quotient = 1c72d32cb83cf4a9043d3bb5002f61b03e29c34e44a9fc5cc4d613726f5e618546
+Remainder = 7312d11fb5828c7f1a0060a5152a7644fc1e6a59de28d03
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = a681444c4d47d829f7b629b561ffaa0c3be1232346c907d
+
+Quotient = -2702afc4095a0396215e3ca36e2a59725f743b30de0dd8d4ec4d943fef6c37162
+Remainder = 223dd3080ede3a64744b14df8742cedd71388b0df99073bd
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -796c9ea38ccf516a2054a1e584c18b64b996c9679960585a
+
+Quotient = -805585c6a7badc933bced6f8373ffdfe9796e963d3fc90e85b1a22c38f842062
+Remainder = -a6ebff3f651644915d5c466cc2915d104f0f85a44e08fd6f
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 24e8fb7a6a3057ddcafff92916c46f7e4038b98c3104ae831
+
+Quotient = 10383ff8feeb180d4fde925b534be97ec3d5f1f1dab5d8cd9ab5d8ea646cfcdf
+Remainder = -a7efdd0401c74a69cf74442fe3da907acf92e8edc51668828
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -1240a71ed8d81e86fd9b16e1d64f438b35d6f8eff672494017
+
+Quotient = 195d95a520fd22317492117dc756ff97806c48c1aac67a41ae56fe503a60cec
+Remainder = 8b8692bee56f8a1ada9ffd8b3583eae33a0df9b73a7d8585f1
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = babe02063b61cb90634ac0493174073d2419e00728d46ad2b0
+
+Quotient = -37791adae674b866e4791c107a697363847dee4a58a37806391426ea48b8c9
+Remainder = 33986fc6a5f5c4f4e31458fc7de55e08a4e9320509d90299b93
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -5563bb852e7338c65aa21c516eecf47f498e5788c608ed46cae
+
+Quotient = -68a30494eceff55e4f54a556dd9b30025ccfa22c0952fd746adfd13d31d00
+Remainder = -1b511d0ab81d528d00a1058850bef48df2e9ae9357e779bb9231
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 2d44e919fd27bb3fd2093062d11830c30fa77febafe0a2082cc6
+
+Quotient = bd30999592dbeabb8871b76aa04cc1c6c3794a83f0178c2ad505d8189485
+Remainder = -b0dbce286df5faccf0bdb40ca60f508d436f9410c5e49c3f1360
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -1909930e2d16fc877c15895a3ec8b2125858bfa1c5a1b8776bedd
+
+Quotient = 2171694ef4a9d57b83b09357a511d4e11cecbab5e9387928b480d686a0e9
+Remainder = 29abc8898d5ef85f87323c2a6fa36ab6e1bdbcc0ca742b1a2347e
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 8da37bc9c7c9bdc62f49cadcd40e156e776b7f4c8f7ad543f463b
+
+Quotient = -267d470f32911150d9944e684c14e1834734b15475bee968748dd5f6502
+Remainder = 53a2ffef61709bd7143c4c876e021f20a99ba481f2b11abcd45da3
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -7b117ddccee97816c2ca2f1a612cc0d94ac67f5a79ed41744c8fc7
+
+Quotient = -5a21a3bdd3a3d4f1361a978706ba1cec409c296a5b3c369e91fc8317bb
+Remainder = -2cdc818f1e445fb3772d2a56833aefb2f5565a5fca80662e6fc1845
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 348dfba3c793f0018d7d3a70c4060c3148b4a3163ba60af9d6f8b04
+
+Quotient = b301b4050fdf4ede8f9c746b26d968110e1eb119ca42cd9c9bd8d4fab
+Remainder = -17993daf81711fe59204ec82e363d2b91971129af9206ff9506d3cb1
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -1a76328184b9bea8770c91cfccf8ab98e75b2224d666af58022aca80
+
+Quotient = 19c401336dd43c221a61264f8b91791d250e6c99c61850efe6d1e3532
+Remainder = 6c9e547a77c98eaba1b021777dbd98ea88f7fd37c95a2b182f2b9067
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = b7d7b1f95f4fe2f267af88b81af88fbdf603e54ab6de73ccd000c32d
+
+Quotient = -38a77853de88a8db14612884b515e3cd7c673175779d4ab71ba58f83
+Remainder = 51851549cfa00dbfae388cc3b46fd4824268e00e12fba288acceab339
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -539c0171f48e4160e5c308ee9e74f35d8b6d032e946dbcf748b1335a8
+
+Quotient = -79a7eab82e5b65f4f6734e8803fa7c30852ea3ae56e801c5dd11778
+Remainder = -f89592eedcbcc68d5df80663b3cdc638d9d779707d4ae5a552d97d009
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 26efac15401a945ffd37066bc5af23191292765164a0f1e4fd537fd64b
+
+Quotient = d33afb58753a21581c5b2351a74f3d220599ed56ebeacf1d43eeb2
+Remainder = -f699437f44af44b3ddc080f5b74f753d35f70baf3866040ba3c64b30f
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -166cc6a3c60facfa0d8d318f26c6514c7eb9113f6b625c1de804ad379f9
+
+Quotient = 19e55bdaaa5a375c36e6869700f8677db563e5cf985be2a8d1b012
+Remainder = 7bccc3a653f29f3f45b52b8de2449c868c64d976666c01bff2dca03a8d
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = b6eae7a82b5dd1554795573cbf558d7cfed813eec270c326bf290adccc2
+
+Quotient = -297530094c3e4270ab5cf67e60fa5af6a32eb41b18b050fa6d46d
+Remainder = 62d8b502e172da7bce53fbb7c1ae376b6c21b3a3a47523aa0023406e353d
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -7241ae5f1aaee9340d437ad2dab94b70dd29fc6fff7fe31b100aa5001644
+
+Quotient = -640f3c38230962c6d6fca459afe0e46137525e8d62dd9b84da73
+Remainder = -16fcadd5155910764ecf0b4bd0afc3707e2ce49cedcbd5414f1c7d860e95c
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 2f570d2da7a4e62097eb494ca43f7bde33e36525308dc864ffbaeb5d48f97
+
+Quotient = b3895ebba13c8f383ac0482be02e1f5518511420cb4513426bb
+Remainder = -21bc847fdfd48c7a4c36c778681ea20481081cbb7af6b281c8b8ebf2b2c3b
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -1a6233954b3480af5f911a6bb8ad33967d5e0446c3e56f521e892c986b6b82
+
+Quotient = 243f3fbefbf842c79c5e96162fc42fe4f177a59d27681c54b3a
+Remainder = bbfaf15a90e744dc4a1caceda3cb339e5491e4507a1118613c5e9739f976b
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 82ae783b8a13e2e65d52dd3a6d6b057163347872f4d72245ff364dbf2421ff
+
+Quotient = -30f7cef2948c9ebed8fa3c5ea9a9bfa96ee4e9729c9b18e9d3
+Remainder = 1feb3fd887629cca60c664e385dddf538d9bf7fff2d34ca9e0e7614946d807f
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -60bba60d69093c0134fcb90aefdb9c190e7bf037ecc13dab3cc7915d7893046
+
+Quotient = -6b6f0183c1f598a68683ba7435c05d700d74681fe472669a1
+Remainder = -1f4d58f81a8c18523918d31791a00ea9aafbbb87792d90a5392273ec4e405da2
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 2c17372a5128d7c403a3b94838072ecf9aff88d164764b12bfbf6261df957e2f
+
+Quotient = c4347fe42b2a7d9d5a650b72724369c5c1f59262a7be3fc2
+Remainder = -1103ec9c4a15373949cae4e34b7b42e242da41edbf5ad8362ce5e5426d3154a1b
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -1824671758069b7660bad819f06c86fc76a9344ea38412058380363e5c5b4086b
+
+Quotient = 15e8c8d6847dfe974cefeef5fee93da9e58b74d640c6c413
+Remainder = 61dac240f2b39832903d5ecad9cfda5162bf8ebb0610545f259b75c3dc6ab8771
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = d83386fb9682576cc70cf84520c53169e391b414f5421cddca6e257bd77753c40
+
+Quotient = -3572711bf994e6ad48535cc4d65ac323ef1ccff530b4337
+Remainder = b5899d4cb879e37022c539962959339d055900cca16153da09b54c658753cf50e
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -58a05faf5c61f85ac5a090b6bb045c851ea17332d9bfad4309ce2b7a79ad3cc575
+
+Quotient = -6931ebfc6e34305e5d7cba5284829d088d1ec0abdde508
+Remainder = -1b09eafde481064bab3a5c7fd895edceca40b1e62a9cf953eae1061dfbe00936391
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 2d0769f392ca9ec629ef1bfbdf08cd8cc9219330ffe3c05343df792dd94b1147714
+
+Quotient = 9a4800f0cb2bfbe8d234410deb510103b7da30cbac7d9
+Remainder = -971e4a529e439a1b96b942001631027ff2fbe40b8939e224adb7f2ed30faff64d1c
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -1eb3d7971125a036c3a67d9f5ce580a4ef4c469a492be53a55bafd2eafd4032b5b9d
+
+Quotient = 23116704b7a1a86cfa2ee5707ee46268634db5d50dc0f
+Remainder = 467c6b64c8121e4f250492191ea36a27119a0a6d19af519bf7ccdc2436c885c99d85
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 87134e98f73470e23a96c6a9139af3d4d21574de8aa9ea1d720df8940bcbda343694
+
+Quotient = -3b7f72ecf4f55c02366c52f38a827f5773b7cdebb9ba
+Remainder = 194b334b2046a66be3ddd7c6df01c88967fcb11e97b8206d000bcf6043c6e9ccb13f5
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -4f9d0341cadfb1f0bc38184d93503faa196fb8170f8ba2b5d3b512c09d39b7f79a5b6
+
+Quotient = -6db1d69019dd4cb26fd65d5b88a31bb6413b30278a1
+Remainder = -2042a060391e181882dc0c8d91c3b03c1ea35e2eff01babb3ae876ba1e57a505d44856
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 2b2e8f445c0c3aaef0285945e4ca37a700310e003086f34d02c891b94b117f3d3032fb
+
+Quotient = c0e5b9a5853bb21b5e2e37f469764579d5cb2bf984
+Remainder = -154669d4bce7914cdc8d79f2b8d1faa43e8cc3b20fb0767e1c9a47c9e1daed4b665cfdd
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -188e619dbb719381e701363de874fe168529c10f30d3ff184e4356991fdec1649f72235
+
+Quotient = 180054f8c36833d44cab9dd61e6d89d28605c564af
+Remainder = 59192ec5c6fbd9773b8b7dd7d8ab1800dfecc8eb01c29997d15ad75b79575d9e26e1fc9
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = c55b5eb165c63ac2794bfac21980ebacadb93f1e059309fd2b855621572e8d9b3f29018
+
+Quotient = -31412e97045c19ec38951b0e3884c66d1d7479437
+Remainder = 56f1425227bfc6eb1ecda7bfae0e5cb59e92a2cc5306b28465c8739e40893dc5c1e94cbc
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -602b8c25ded1ab3877f58cb048c733649c7dcadf87b2652e35c4e5544d2306107ebff7b3
+
+Quotient = -8da1489ccf7203ecead94c67a5750884122b6e75
+Remainder = -15162026586a1e55dda72785f31c9e6140d166a1fd34c87a7d8c78f8d8f87bbdcf8f75b1e
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 2171ee4a6f7f67d5a33d0a08c367184d70ffe39da28562655e75f6b66c866b1c2ac93e467
+
+Quotient = e635f8bdbf80e99723aa5718d3fade4e573be2c
+Remainder = -ffbd73bfe05f95bc2b135f12682288c620215eac3d6d56503d93a90e06f236e597d1df975
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -149375d478a096e724b84faf795c589ef0d772c4623f5be38da99006cd833dc5b28363faed
+
+Quotient = 20f76f5c6d0c8284764a10f6936c22bfba5f851
+Remainder = 82e3fb3f7252dd87b5370d26d9e8b9e98c7d333701f0ce8a05c337054c7aeb343d04d7e342
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 8faf8c0a3ef94ab1069394998e5412a7d84f44aff97edf63abc46d96f897172c38faa0b13f
+
+Quotient = -382586dfe93872abbe3a504fc62a8973913f96
+Remainder = 4d407323ef56093eea2f3993334215950f4e1a85ba18cdcd77d819d92b8b292c3ec8edea425
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -545d81ed25602b158bc79aadf98a8f655fc399fb8652ae94333bf54c8c9ffaf8c6b3f2a9d52
+
+Quotient = -7d179efc493eaceaf46572a1f3a62bdfc4a38
+Remainder = -3de3d817a9cf7d529b5229a503e8ebbbd2c53215ac3c584c010947f780198dee16ffbf47791
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 25dddb00f65d6a1ba8caf7815a8063c5da656d775eae9e0108c68ce11dc925183810888dd04c
+
+Quotient = a9f7e5f235bae0e3e29393ac5c99d510b009
+Remainder = -150478b4a0df3eb20dcd1be8da283a00636c021c5c6337e7732aae9c4b49853b95f6d2475ea7
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -1bde6cae7f5ced9006c0b1a61fb50982a433e4e2050aa486298f456556d8e909e96933e2ba3ba
+
+Quotient = 16de125df5936181981b4c2d0051a8b4d211
+Remainder = 29ac7c8a11f9beb9ad649257994216146b663bf4f237c561bf315d95778fcdb1010283475ebf1
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = cf24735a60ff5906410be5c4d98e3c9247919b57e404aeabc7eaefbf07bd64762bc61b96c9040
+
+Quotient = -268a52cd10ab4814268f66d9f44f71a98eb
+Remainder = 20293699f12fbfef2e391963866fc082a7884cd13b1c9bd8d5d203558feed2b889720be936451a
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -7ae7d548212830013b7d653072c33f0dd54a6ebd8792bf75809d29a8c798dbc67c3edd99a69b85
+
+Quotient = -8f051067ccb82b6a3dffedd0ff2ee97c46
+Remainder = -100dac0d3bf5aacc5fade281c071eb2399560a65349566567ce1c0c34e43f175a575ed1eeeb3b07
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 211ebb5dc59a051fdfa3b18ac491971e863f2086cdc099672c1215af4ec877e29950efa4f487be7
+
+Quotient = 9b7ee4c499386f922432fcb1a453ee2ec
+Remainder = -f410122a74386d724cdd45b2e548645ac5ee4a44cbfecb82aad34ae470526674da44ebbf557bb75
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -1e76750814dec1ecbb1af0fa2281ab3185e94e47fc16a77fed312f23f261ad7709ad7c9f85862c1d
+
+Quotient = 23efb26228d7bcf281cd45f54572e2b3a
+Remainder = 65bf2ef1c2f8e94d98060aa305f85e6cb869c74eabad99877010d30654aa2e578ef6aa3c5f1122e3
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 83cfc25e90a61cf8686e3d5857b2f958674d478622c54cf8427275ca5e9312ed24e44ed4a1b5e413
+
+Quotient = -2cfcae0e922f2d884bfa0a3346dc9812
+Remainder = 14de2725b11a9c6784d9608c52770d29b9fbf824ecd4890bf28f3ec0dc6c52e4df9be540332b8882d
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -694b057ff381badb37c7c15c81e74cbd6774e8d61c9e7d450811c36262ea834fc1287fa59708ee072
+
+Quotient = -4c0238ff3c18d4d58e543f020002802
+Remainder = -2ddef796c50817e82ea6f64a02a8c6b30ab40070ff5401c2d39ca14b9c4d99de33834bfe566a0c2efb
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 3e51c9ab14f522b55e8f9d3ba995c0846a864dfa2d568ea211b0cac1463ce6a1da72d0a15746fdcc9b
+
+Quotient = d41f9102a7785ce64f76b7d7b870b0
+Remainder = -106eaafdd518c658bd371164ee43ccd915a01b513fc7d220900039ff840ba36450e16ce9987e08e7141
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -16549c5d57b531528dd4d781f03cf275b66cb94eba038b782b739c3ab30b8631c8706abac06004a942d
+
+Quotient = 1616b432b3277e774aad92b0cf544c
+Remainder = 2c89373720b834d718ff3df985ae47c3a7cde0e0309f682f5fd48dc97a1ff3d69fa0dcaa1245e956445
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = d6721300e877a8145d05f4f3d8085697c2ca5f34a5357fed0bdb7169f83b6f8d855232eeea594846b79
+
+Quotient = -320fd6a7375a42a3961362ae196d1
+Remainder = 5336711bf81237ea3449f4e9f4e6358dc250f8ebd86082cab92a8079f2c8f835bc783082efb0ed7e3f66
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -5e9e8e1d446fdd314d487cac1226088696e33161d923acb67d3c75e87e428bdbc193e02f53200610fcdb
+
+Quotient = -4bd06daed3f30345d269f51e4381
+Remainder = -1f3513bdefa40662f0f50a04b418a833aa2f85522dc6c399298b1b147662ef2164ddbfb7247ba9511b8ec
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = 3e7ab7ffe5f63a6c1e109b95b83af470ff820cdedbb3c90c398ec42e44a45e1ca894870a7fa51f17ad5c5
+
+Quotient = d6fd01a0c5b55fbe36e58bbe77b
+Remainder = -c51af3e8b430870388357cb366ea888bd7b4ccde09ad3a1d2ee1426af060245c6d6b5980ae87fb66c4642
+A = -1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -16086df3dd5e665f2631a294563c68931faa19ee67d6a2153d262940a648ae71bb3c1745daca5ea977331d
+
+Quotient = 18bd9a8f5678d28cefd955cf99d
+Remainder = e193f2fece67b7abe16373c3f84f18dfedcf654d951bf47585fccfaf67ee04f5037354d057c9f5eaa8eef
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = bf758acacd11f3f3e6665cd740517c9ab2384266f3c7ff9afd0888cdad2f6c9401c24d6c11fc3949aabbaa
+
+Quotient = -371239db55c79521206c9e60c0
+Remainder = 93773085af7582dd298b09d7098835787978d820289ea6850f27d0d77eecce8614785e32b228f46ca4b371
+A = 1280d26263c574f655ea63006f2930666fbaa4de1b09a11ab0e47dbe0054711aab90a05b1185454dcf046745436391a673426000000000031
+B = -56033fd85be464301f10177b58d895fbb6df6154da5c2a2a7cfc3a24d83a96f5295fb17a08148a4e51dde91
+
+Quotient = 696d8e378d12221e2d970c53bf63a20ef381db8566701972c22fe067cdba99c57b68706a5c6e52f21bb3de861e49ed2141b3036f07d1fd0ee
+Remainder = 9f0e50ca76031b
+A = b2668f5fbcf4170820ed3fc9b12a61862acf8e3cb17175482efe23c5cfd3556e77634d407b6d1f98a73437a8d6066319a7a860afcab2338a1b1313037e30f4d9
+B = 1b1313037e30f4d9
+
+Quotient = babe271ea266bc7bc16d193097903037819f82366c7e9ff8f2cb14157b40433c6ee327038d5dcc44140b070d823befaefbee5e13419f6f17
+Remainder = 93d7c547a9ba0a4a
+A = 74b1a591f449377836f378e05d2902b29964df59c6926e5a9182cc09ce3111783cb7021a185340b4880d56635de268d6f3855c4d9997373b9ff8df899ee3b3f1
+B = 9ff8df899ee3b3f1
+
+Quotient = 890139fef28aa3b77814e1122b9c7f26e746ee3c507e6082b508fcbe380de83b06a01f735239c6847c30eae44749fc8c5e3bd97eb40ba297
+Remainder = 6c97aace900389d0
+A = 7e89adea82b4cb6feb41297b6dc8d948e72c3d5554a987900e7fae48cfb38fb5282b13d9a1f5793cf7cbf1ef551865041c3ffe0e287714a6ec7123556af55a48
+B = ec7123556af55a48
+
+Quotient = 1fdeead441e2d7a6ce3cce2389b2a22248ddca7970ae3f7e7d8453052fd08534ff7c46f6a4537fb6f28df6c5fc8a7d384336e679b74205315
+Remainder = 2903c7cc2651bfa8
+A = 9ca66de3d83f0a747fe986464522bde5e42aeac20e8ace1ea13fa6bc9514c58517479a4281d4128c6d775489b85dfd114ad184613f308f6c4ea484a22ab0ad1e
+B = 4ea484a22ab0ad1e
+
+Quotient = 12f16c8f9f898a08853982e2ac5a906d784c5ab8d74007ba3ab311e861d7c1ac115efe694cab7583f75a4a59ceff2887dab53b2f1022aa452
+Remainder = 4bdaf1f352e87aa5
+A = 6e6a97b358b591b78db43772378dc084a11836ddc9dd4607f263ce620714e8fdf6bf67387c163b6f2999f84270802b4bd5c0f0377e949fbd5d42fe145e66ffeb
+B = 5d42fe145e66ffeb
+
+Quotient = 14e0c06c8cff1f9f5dd8afb6fa6c340f0953a18ba7d2b26b22d8e7f946ef20fd5ac277ceb59cbd4ce3e8213803c3b5b0452ed449e22bf2c29
+Remainder = 55422f1caf4a9a00
+A = bc9c054ff568af73e301e0751bc1ee055e82826cdc53449f2d9f45feda2ba227bedd6df9b74fb58a85917d60b087bef04a156a571716e9bc908ae83784ee35c0
+B = 908ae83784ee35c0
+
+Quotient = a457ea94da3237c0dd15ee30e9c13e7b4ca1dc90fcd67951b873787206babaed837a3eb17e298d74cae92d1059636f9aefe11aef9ffa31053
+Remainder = 124768541b600598
+A = ea6dc82b1906c277526ed867fe8b0fbe32feecfb935dbab860aef59a7d72799fd4e952e70b4c9304c7b2a06af8badcd6cfa12d0b6c9db38d16d2c4a24099ca14
+B = 16d2c4a24099ca14
+
+Quotient = da0a37eece8972a0e2e8817c54e67c4d9f92373340488539d5051984bce0ae3300ef6ca9d0902daa4d485dec3b4db6c8b1ffd2c5d08b18ae
+Remainder = 1ba15c46023500b9
+A = 36ca8763e20e6ebf07a55cdfdd83892bef0bab68ac092093bfdac1a49c1da015541196a24249bb2262e70f7ed53e0fbae61f02ebac4b61f740548136ce50f243
+B = 40548136ce50f243
+
+Quotient = 3d8c433daedfbf681b528f88d610204d33bbe74d0b13978c34a617ae94177e07a757519b5a8f1a93a73d0751c7b5b72b4bdf475a9708fecac
+Remainder = 4cdfd72349c6110
+A = e0dd7e73b2a64dc017da65992176e2535c43b6fc14f2f7b0a7d894d768bbc77507eac0112b2dc3ca83d70989a1b949ccf374be6a012d80a23a74bba39671fcd0
+B = 3a74bba39671fcd0
+
+Quotient = 39d084b444e39c32f2883e9968301151802da15141f65893f37b8b834eb01c074aa1e1a978c5c99732c87ae106bf8db09e1728c8bf2aae88
+Remainder = 2950443357cd7477
+A = 16df31dc290559c3b6a3d192cf15d825cfe79f8dbd5c9848eac7fa90eea5d87f8b430cccf9baab3e8e4dc33467a4234d8551ff25e33af175654686ff1368e96f
+B = 654686ff1368e96f
+
+Quotient = bbead8f70c8e61114f22d36e97861f16037efabe1347613e78c51d7f539065421a66c907faddaed13ad2a0f0b00f8fd594e917799cd937e5
+Remainder = 3013136f5f728b68
+A = ba5e688ab4f8ab5c25592bc4334b6dc2b7a06d491d0f919b716bf1cf109b62a30d9dd59dd4bdf870dd2687894edab303277a5f3e3a537cc8fde3ee3bb61767d6
+B = fde3ee3bb61767d6
+
+Quotient = 42aefe467ff2a5614efef1edce25a1acba9c476b3abbcd680140a3aecf8f51c1ebaab8912de217451bfaca2842c0bae717b8a030b6318c0
+Remainder = 1f130dd2ead0d35e
+A = 17bd50b5322c51ac883852ad2a4446c039dbc210ca3aa0313065fc88cce6819b324e93b036bd0c71be58586cd2b243d01a4a918c10ea0cc5b22f9d795df09de
+B = 5b22f9d795df09de
+
+Quotient = 13de73dcd72a3638fe2a907fd7f6574bbb228698fa60e4ecffb082911c5f09c74bb4f50564d3d4035d07eedea38b634a3e3acc26c8e9aeff8
+Remainder = acb8702f0113e0c4
+A = e0327b2e59236a3f91ccf960490cc69b2afc854de9299ad2edff9618f9fe24251886afc65f5c581a9bc86013f356d599e98b8b10f5236a51b48a6b29025983a4
+B = b48a6b29025983a4
+
+Quotient = 27d11481f00519b786eaee96220afd45bc51700f7366fb5e7da35bbc84891aac3d9d2b709dddae371a6b78439fef810c68eef586e1d68350d
+Remainder = 3d1890c5e1555d74
+A = f3504d5d96c9e27a1527725ced337f1cd0a183531642051e166507432c01e8d44c4e8918701c2a05eb8a9d7e26bf04993f9adeef2826ae4e61c602477f849121
+B = 61c602477f849121
+
+Quotient = 10bdeac209c67b023044186704735c7291423054bcddc24b731ad601b49372f4d5ce6e9d85002f8dddf0411efce943f81a5e42cee2d0c9fe5
+Remainder = a93a0c5bd51004e4
+A = fa29e37b0d0410d19fd180149b14f94ec2edccd347da65f6832850aa06a61b7b78c96faf64dcb347893c93c560b8043466419864a382c6f2ef1412873b2d8cbf
+B = ef1412873b2d8cbf
+
+Quotient = 1c9b6cffe44241292320c0660b89f2f77aaadc8d36e33f5ac3da0f12b3c114a156870a92079f7192d237f8bf49aeee6282531c929cc56d75
+Remainder = 1ce3e5eb13ac7958
+A = 144325a641463ed6bddfcbd73e50620a44c606d71fac38efb1c9d2747b4903f7b51fdedacfb66db022aea09b43c7c2ad7b851035165ebe59b552d4f7eee617b2
+B = b552d4f7eee617b2
+
+Quotient = 1b4ad18dc0e634053beb3cf840b53e35117ea06309ea8ca22e37123fd7e1d391c96c792e5125e322c27daa73301024080d73ba3491484b659
+Remainder = 3286bdce6dc3a828
+A = e3a2b90d3ef446f6bde30d3e726cf3e78212324054b40deb0b18fe00645568fb0a6234b6bded6240977373731bb30d1349e25cefd54b7a9985735e9b78002691
+B = 85735e9b78002691
+
+Quotient = 28f5e8da6733240cc2f18e3cf4d42a50d92816062af33a9e1871fa89bdb39a0d905c49faf51cc1c1378741bea34d25ac2c8e522881a6f6087
+Remainder = 135784870eb40c68
+A = 593206f9367b72f9cc59b3e37d2eb23b2061422859162ee53656899c2471017474f500c6e23efe1f6b1e57852cd4229329dc182ba01a257122d76a26aaf9b844
+B = 22d76a26aaf9b844
+
+Quotient = 1ab276448d16c533b6e90b5b5ca266e13ec27b5a58c80b7657df963ec2d1fe4eb1c1d24873eff6408bcb3d0cf97c31e85240eedf0efcc1e5a
+Remainder = 27b105741264f875
+A = d84fde3d851b52ed3b2a1268e9b765ec6c09c5768bba709b3b799802fadac30a6c3184185e6d57249b1c34619f3c9d2b90bc0c348b22537281a39fcadf738083
+B = 81a39fcadf738083
+
+Quotient = 84a87678485b3e60ee1cae3701ebdf0a29ee44115a492c34a0c8e84090e14070eb2ad0abfe2c339f26b5099327515104fe3d1c5546feea98ed
+Remainder = 95f7434941f9d8
+A = f79a0643bcd9c28cc22cc7b4178b3340e4685dd2672792516d6fc08567d2de2d3e25d43f100a58826edb146ac94acac4213bb09bdf8a258001ddd0ab110b89fe
+B = 1ddd0ab110b89fe
+
+Quotient = 516a2ac26e5b3afa502c7f3c6f15376f7a380e5842c229443343b5b74dc3de84db3ae99a0c57043e32a504ded19943c0310cababb3e92cf8
+Remainder = 327cf78eed336523
+A = 17c0d5814e1020d5d69674bdf6b9df193a16c0c8567a589d014e8eb7f6c9c36560791f7acbbbacee7c456eb51a4cdd7ca88011e9d8d9f2d64ab08ad74f7be5cb
+B = 4ab08ad74f7be5cb
+
+Quotient = f0da0beebcfaa716f494cf3fc81fe65117c90adde3b3942e8e66986fe8050fd5c9ebe1c88c5db04cea4c4c14779555d70cafb53870671f95
+Remainder = 3b2f844440d7be00
+A = ebba8c393c2a22b094d824ed95b4acf6875719fc165f73ee6d359e1134949169fdacbb42d5deb8cea96e11e3aac985635b5bcc6c02a6778cfa8e03d9ce6fc680
+B = fa8e03d9ce6fc680
+
+Quotient = 56527f07593774f0fa642241400985d0bb9b41d3dc9e025ca069130d93afc972d75e3fe0f798e127c3e1b4e925000459a3a5a83b15186e516
+Remainder = b620b7a3b752b78
+A = 5d6cad9e26267abb480b2b9ac5ea323bc4c3c53e0de8ce40c89c85accf0499aea5b11703a04296519047585ff12f8795f98da0546c20016a115100eddabfb468
+B = 115100eddabfb468
+
+Quotient = 294dca3b56ce9529aed2c132a9bd6c0c61de7a58ac50582f396b4fadcf7873b502bb869f801a9ab1f12384631cefee72b3e6050a7f69eba4
+Remainder = 53a0fcf5486c7a6f
+A = 24aa73803f270185d23310df2cf3ef67b18d7800bc41aad2ca13f372a27ef0a9217194f3f512e79f545a903895def195a5eb9a1a1b6b3f4de340e9da9b305d3b
+B = e340e9da9b305d3b
+
+Quotient = 16bf4dab1c29bd284c9b6649de65a4ee58f21d6a8b51627ca133fa817872b1a4a9956662db0aead5898ed0eda08511be7c47449638f2fab95d
+Remainder = e7751deb047d98
+A = 77b04d93272491322ed2fe651044e28cadb2ae7825f02b55aeb0f73b8b8a8b336802416fe08c718ab681581ac04d87116323f61f50bfd2180542fcd4a46dcff6
+B = 542fcd4a46dcff6
+
+Quotient = 388ae1c243bc9111e663c0c80495c36e8767bafe188b532b7ac84b5160d902af1b638aec6e4c66955d16bd8ce94ce6027a7bf95910f705ad0
+Remainder = 7c667ea307017c2
+A = 52f357e9a57722a867d8199242e100f06e8df810ee913d6992bfd9dc03ed78bcf44d692aaa7be806df0c9e0802851d7ae8405f76114e6322177907198f85cb62
+B = 177907198f85cb62
+
+Quotient = 33dc2fcceef7dce92e3a9df58566c6e28d03b58ff6ecbbb31e43936cda6380a56788285d37b5e8f11487afd78c39cb2150cc98d9d78a0c6cb
+Remainder = 429a380c9f8eeeba
+A = d99cf9a0bfc347c9631ae8c69defe1f1509c3ecaeeee5dbc61317bb73fa5cc6e704f64c865cf4d898f8a2f63214dbd511f61aa6e09856222432376698f8d2f67
+B = 432376698f8d2f67
+
+Quotient = 18ecac9e5539a014cffd8310ceb1170577cb23aa9cb3c523d57ad83069d1609ff743cd3c275b67097a038b85afcd7105ad21672f9ecbbc7df
+Remainder = 37924fea665f5c92
+A = f87aa8b6e62b09291e0e9b832ad71d8f85d60501a8d89d2638dccd4022e89bc4932c186a198557282527dfa86dfacc2f90fe0656695b61429f8220509f5106b9
+B = 9f8220509f5106b9
+
+Quotient = 37c0649a53c8cab91a7458702870bf64cb1de9fc1c6b9a3b92444119d368501b62d3a5138af72bdb7752eab8af6bf4e3bdb9e3beb1805b88
+Remainder = de179463e3e91ad
+A = 995c04c1f24c4efe88393bab7a7545e39193662d5db7c8e557d6c554ed4367f5af82c463d0ba6bc3148620481140add5677937989e03fb52c0323980d8841d5
+B = 2c0323980d8841d5
+
+Quotient = a6d193cfe7d8983768ff29908ee6e07fee99927a4bc4ef41d01f63f3b4a2e7029630b7d925d0979458cdaa903771286af672253cd99593b3
+Remainder = 6bf69921db298b3e
+A = 55c856daa8110599cc4fde0a44acbd69a68eb177e0438f7d843ba0fb74caab2a7e0c8a6f176f5555779e65c555e9157a16a1497edf36ccb583a458f0372a57c9
+B = 83a458f0372a57c9
+
+Quotient = 63f379bef9866b59f8bfd6bb0120a75dc03506b0034e7440764afc8ec14d8d735aa6f03a568ea98d0a74ab9bbe9c6e11b288467e5f79a2539
+Remainder = 11c077beb8667d88
+A = ff1fc3ea60fb37ff23e2f2f4e207a86e055cca41eebcc5bd6376904b51fb3d233cb04666fdc92be33239b5ee552870e45717890e35fdbe3728d6ff55d5662419
+B = 28d6ff55d5662419
+
+Quotient = 285ba8cdfbf00b112e496ce65cdba2271c82a273b3d30bed82ef2d360790c5deb97f3311bd5eb9876a61e33b3a37782d00c2d5ffbeec752ca
+Remainder = 1672a8aa119c3a1d
+A = d614352268930d301aa4046cd38e2eda4dcfcc52eac984943f2c863de5c4f8a44473a8ecebf12cb8f4da4722d305e5c9c3eddc0109d416e854df334dbfcfdd4b
+B = 54df334dbfcfdd4b
+
+Quotient = 358178128648fa9ea28dcfe68b4cecc7071e129e3ce4d113f5d1e387f7e5a412e9d2dfe5ff16d9987a544004d213ade9c134cc240eeb6871
+Remainder = 44c3fdb374bc0c30
+A = 18b973dd011969e29a1f4a5b8f118313f715c2e31dfebd9fe0957cf23cf36eded89c38637a8d3512bb23324ff2a3627d5b942300200c823d764b7a6c12d1c91b
+B = 764b7a6c12d1c91b
+
+Quotient = 19ea7212f6604d423b308fe3f2f4986f31aea9d6a117a3e207e38ce5bbd8d7a866285ac60433630de547fc84e364c451457fbf864a82c6613
+Remainder = 2718de2dd0796f08
+A = 83577f755a448d5586e19486b04de7836818223ea920465c4eee979a9ce5696ad8e2fd5253b5d5dcfdf355465e8c0819658ccc5580fd29b351169b54c62b779c
+B = 51169b54c62b779c
+
+Quotient = 13e0c5b9905770b60a6f978d1c983cbc84dccfaed0f4222f534df80c7d3d129f5e8f74f19581332a7f6d383915424c71db4ca19bde2591fcd
+Remainder = abf5f6c8ab6ed4f4
+A = e2bf43c91cdbb244790eb165cc13feafea36f5187cc9bf8aa8cf202042efd5441e3822a1164992da5be750aaac0bb11f09375bdfbd4a39e3b682c7ee6ab5f5f1
+B = b682c7ee6ab5f5f1
+
+Quotient = 3919f31521e87f90df3a4463d0c83fa31e3f569449009d307962d26f07d854e8d3f0badbf55311c206bf34e6227949327a93b1a5ada7a930
+Remainder = 6c3802d44dd4668f
+A = 2546880cc6f97fb379afbc4a2664115ba7909414f35a5bf88be2ed5187bd1a24afaf82eeceb0b438d4999ebf9b7ec752236669425bd3cce6a71d9ad67ff2ff5f
+B = a71d9ad67ff2ff5f
+
+Quotient = 121d5ad4115c2768b962e51d09f426d61624e0f203ac6c923289b4e7964e165b34f3dc1ff938a7cf37478d407de251c64db71d3ee629c1035
+Remainder = 660a35e1c1245910
+A = a36d3250c123697adbbbdf489e6cb40be57febaff654ca951c9fa0b396b1714c55ed6e05e468153ac443dabca29de9b43cc0cc4e62cdf24690593662c86fb5ac
+B = 90593662c86fb5ac
+
+Quotient = ad81debaa02f6e60da58b46e76ce041fc4da64138634ea7b3c165b8fbda027eb64b6b5339e70babbb83430d60383c2cfe22029e617fd03a7
+Remainder = 2e4aeafa2ad76832
+A = 8992cd131757ba5cbe54aa58be115723ea3438ddc782a4d1996980b7b312fa76e4483584df744b10340e5fc9e468690cef538920a732a8f0cafb4e30846cad1d
+B = cafb4e30846cad1d
+
+Quotient = 67a71b9ebaec91121a8cf6bc2932b6be01af7954eca69c5202d771c2c2d13683cdf90ec942a3445771ccfe484f947f078de825ea88b3c05a
+Remainder = 8395953f744cfb31
+A = 4f8ada84096198175174896167405b85cbc03fe0642f6b263a70f9a22f19ad6c9aef38da8ac036d409e6fd925023c95312cebe04eb653e0ec473dc8dfed98967
+B = c473dc8dfed98967
+
+Quotient = 9416326e2347a541b777a0fa1b0c35d8fe76c940d24c6f6806d6ae8ac1e280c16e480786478bda3f780ee92f3f3c361574efc2ed5ca98e26
+Remainder = b8ff45f31bdb58d8
+A = 902f5e48b96b9b1fd16c3b21292ed495987ddac4e1d92b2ab10378f2966c4399d6a41eef622a4991ccd1f647531dcd145de4ac99b3036779f9414ed2f4ba7e08
+B = f9414ed2f4ba7e08
+
+Quotient = 403c651b4e571e8301c4158fc185396554bf61d900708d2af5c2bdf495b3cb539b0b9b5acd0d71654b3aa68024961d5a7bc9e2788e6c822b6
+Remainder = 7856ec047cec8dc
+A = bdd6d846983fbf140173a26d2b709b9f31b4fee1eac9d25fdf0ef3523be0e6afb372acab470cfe1806b36d84017ec99302eb9eb5eb2862222f4916d8b6201d14
+B = 2f4916d8b6201d14
+
+Quotient = 1b6d967173f9777cb6194c8f69289b91da731456fe5a1515a49e4463cd906c84f97381cabdf9f358d97fad5d3cb140e3a3de397e7f9f683157
+Remainder = 83649246ade8bb4
+A = e3da80658acd53ada7c2dc57178e697f2907c5b0c64f4a87a794ca7521105a0568a32874207646df3768ee60964b7d1d2e29ea6bf7fbaa7e084eabd4ea553a72
+B = 84eabd4ea553a72
+
+Quotient = 27b8f1e49e404455cc68217a20766590e749507976a3a6de25a7cf2c32593aaabb04d84deba1ec6bbe048a2959ffd747243c396dc53c9c811
+Remainder = 3daa032278ce53d0
+A = ff3ead7c7b27f607d16f1ef4ffa91b6cc28301b9256cfcb0c22b6818371ce648ae8812dc50a86e4bdc0d0b1e5b0d55c6ba07b240886a6d5766cfb3ed0937a543
+B = 66cfb3ed0937a543
+
+Quotient = bf987f58700508356fb6274f64a9f78d455e4c436fc6fcc980ec0800287ab3789b91c29a8a72b16645ecfeec926b6f8242f3c7dc3adb40cd
+Remainder = c007da44faa80584
+A = 971aa67c9af10f70977f600e10f9278b8e66d2471956da38e5f4b3fedce9a5fc7ff42b800bb4a78314c70bb59394d0880383f5182b6c1960c9e5b47ef8e63be5
+B = c9e5b47ef8e63be5
+
+Quotient = 7332104442474715d7c4cdac15fc1731240f8b4dd0e6ff3284a15a62a8f9a071dedb87f2220efcc5839cb7e6933a8f65d767819db26e134dd
+Remainder = ef65a7789f54174
+A = bcea2ae4b1edfebf905a5820f0481b6c58d76a69df9dbe84764add3f49496a5d7005d645eaee3754e0ed105c13a114e6a0eae5cc4efab6aa1a3d3a0050fa86f5
+B = 1a3d3a0050fa86f5
+
+Quotient = 3f6182804a7ff12fe7ed3c8521b55564559b1a47a78e1fd56597b9470e7e0f6e7e48c58bc8841c9d118718ccd5e0c0bf9a08d8e244ae60da5
+Remainder = 398e30aff5bd284
+A = 2b877181a960c5e29ab1b2672ee22539256a82369e8f6cb5bcfb69e5e4a41f782e89b58fc0ef6ca336469ff929729f8492b44f12199f0e1c0afd12b2c999e787
+B = afd12b2c999e787
+
+Quotient = 1a80a681d2c42edbcbde552323dac3a1c03b43251a99b5549da6cb39ec6947daa0d574f0df68512984fa8e269b0b27a5576b3aaccb76ebc23
+Remainder = 378e44fdc7a5ec4c
+A = d37e62f44de27a1418f348139eac5ab9fcc1ada21ea6d7695273daf638b4d7eee6745f54b99a9678cf742d304736ee356f66d16d874f8cc67fae9be5dfd41a3a
+B = 7fae9be5dfd41a3a
+
+Quotient = ee982a63816d56758c29d284c19b9b984908cf0a9ae3f1f926e162a2cae4f88703aa477c5c14042247635c103494d11593c2c3839baf4d93
+Remainder = 39afe3275c01aae6
+A = 9a0b0476cd33861d2fc3137df292728e1f636f6fcba5105f384533723231a3104e7c77df46f7f34a4bdc63d5c67b418cafcf106b26ad020ea547d34edac1d3a5
+B = a547d34edac1d3a5
+
+Quotient = fb3f4a39a661e5c31228a6b7b4c27e6e52d1954e8ce262b98b61650efffd762cf2a1aec228bec5d5787683cad6b2e6e49a0de91c15c81874
+Remainder = 63e5ed36ff73a42
+A = 4453712f56467328401a69d4d749a0771732734a760a74094e50a62a030cb604e735bfe0bf0641754edff94ac0e0549e8c10941255f0f21f459e52a6cfe4d9ca
+B = 459e52a6cfe4d9ca
+
+Quotient = 7af60a7c0f995178be76c070cf49eee311e6d1e3afaf50c8c93ff200c1b3fe742b23259b4fc0b9ed0947be4fc9a6c212d86de9a0f7dbb5279
+Remainder = 19657d8ce516a138
+A = c9c92a31ad0f3cfb56a294c42a26eaecb77edf33ed40a7e6797927a0c996a7c0a701b484741163df388bb082e3daebf4e1b7a99002632d6f1a41c1d517238557
+B = 1a41c1d517238557
+
+Quotient = c890c55a8e2a3105b9bf9344a57a9b9fab5fa1fd57083d52431b695553bfbe7a44a9b6cd1f83958224f351f8511b14215d1648e88e938573
+Remainder = 1bab5b03c372daee
+A = 88341550e470016c7ab600b9f6cb410071a77f907a58cb6da4ce3e955d1e859534c2c1098fcfd91b9fa66926e51896733c36a824c3a20844add94e27f30ca651
+B = add94e27f30ca651
+
+Quotient = 34c240c42da400317f66f5151630493a2f200ee418d5ca3300cab10dfb429c2acd7280bf066fe19115f86db83d8f5b93cda714533b16abfdc
+Remainder = 18cd326996ccebc1
+A = 7e96d7b90ff09b114dd4393e9bdfb13d8ff517681126c566e18dd6369d87d248734d94bd02a1f19cca90be7642822b636369c51dee441a9d2663ec896e1d6c6d
+B = 2663ec896e1d6c6d
+
+Quotient = 10d18159e75efa8204e325e6be830b4ee8d2c07419e8276edeac6cc286488fc0c888300db3ebb5f935aa82654d3b932540f0093d1880e1d6d
+Remainder = fe9b6b8ba7c30f8
+A = 731aa6e2fb2ad1e1f80d7668c7b0642203af24af382abd207a5ffb588209e8b5caf953e9a96b478f39ec03a397d1433998e3c95e382d93376d80cf0c957788e6
+B = 6d80cf0c957788e6
+
+Quotient = 450d1f4a105ff8d1a3efbb12165ca98c67ae70404472e4862db479e03313b08783ecc42104780c9d57df0ddf19c5b4547ee9ba52ea82dd0c7
+Remainder = 169e15b4d5aa180a
+A = 902bcb1904b80183656dcbd51879e2982e2b46a547c9ae3119ffc12c6a003e4321b519289b7f22fad19d16480182d1d797c3045b2d29dcc12167f9ce5e233d89
+B = 2167f9ce5e233d89
+
+Quotient = a426f71cb3d75365cd076a6c35c10765bbc3f4bd317fb83a70083b0f7dc43a4e0b95508e60dc1dedb780e9b485f4f7a8870960de669b73af2
+Remainder = da381ae5c97a506
+A = bd59dcdefcbaecd9292c4c3685fb87d3a94c0f0ed01e43e63e1f36fb65d6c5eab3b584f3d1f76d31458c9f6b4c69869d96e943c61df102771274c5b4d821469a
+B = 1274c5b4d821469a
+
+Quotient = 26ccd4b7be090af22221729b0ca51a5e66435c2d33f8d88f94405f6c0123ccbbbbc8080cd8448a977946019ccbf5d267ac3f151ebe686720
+Remainder = c41f9e7bf20b376c
+A = 212dbeff03f14b5825f0d7cf8a7501db21b60581a01a26d522ee44e7fe69545cfcaaac64dbc76c7e3027ac39ddc2d80af6f3fca1824c6ff6dae90967d9ab48ec
+B = dae90967d9ab48ec
+
+Quotient = 801df28f4fd987b4e980760f4f2625276a2a7191d453095c82aa98a2253324ad2873abae70cd98c28ef3ce102fdd53469b9f01889f3ba8b0
+Remainder = 8e435da582e59809
+A = 48341b28138dd04807e522e341f74ac46b0449fa45f96d7fc586997c056a21eb3c399752a6a6c023509f042cf9e879f397a34af9aa2ec2e8904674f2ea3ff739
+B = 904674f2ea3ff739
+
+Quotient = d3857b72b70adff9b5dec3cbc63de7c90ccd7aab6595339b2de39bd6b9789045141d224aa4e6bf9a06e017aa3edd00e716a771b3f5b97771
+Remainder = 14135c686d2e9f70
+A = c1cea45dd46409d5e24fb7ed7d849dbb079247af2d312e01083754ed07f65f090e4dd50d23a973488702ef00936c5d78af603ec0fdf03dceea8f939c922b1e7f
+B = ea8f939c922b1e7f
+
+Quotient = abe20c90896e261e7d31bf40e7f3136d36b0b78006d12225a4dbef6aaf2062b609379eefe7e5af5bcec17126286f196f1330da8477096763
+Remainder = 230307c44cd55896
+A = 19a637e4f3051be0f7c4d35513bca4a91ca9b8082fe3c73899b70b6805a7aa0458512495cb6ee1ade55ecd5851be1dba96d65202f06bc7122633a0d905017545
+B = 2633a0d905017545
+
+Quotient = 5ed3765c4a777a903e182f7c9ce39d19c01460f389b904c3ce1d3525edf25ffe7dc0f4d9e24f0bc8b7e01bef19c83e74f17884bd7bfabb2c
+Remainder = 40f5346f8775e20
+A = 546578393e914be30581e24508a33f6560a5805dfb1c675d1ff1d6f5eaa7ee638b9e0265f543413e04e3f1f3b0895dec271c9897a48d9ce9e3d7df32c15b75a0
+B = e3d7df32c15b75a0
+
+Quotient = ed73a67932746985465fb0606fb0e81595514f1647c911c303d4d31eb0306e3b2aece07320f6fea57a7071d73150591ab2a82a7d53968a81
+Remainder = 2e495a881876da00
+A = 8976445bc318921f7e12c8d4e8e50596849a1503b5efb65e939c291de136597c05a1fd16137f0bbbd7197df943cd612118d1e55a50ee097c94331c1cfb1e941c
+B = 94331c1cfb1e941c
+
+Quotient = 5dce24b7a16d847b0c43cf365ea20bee9679fa0e8732813e827cf6ef3c9bdb7fd8846b5689ce8b80a7dc0dd05721cb06d2700aeeb7ff04d6
+Remainder = d8ead1ae3126aded
+A = 59b99e5d028e6771d27004bc19830a5fcb347f7ae04c0ba7c49130bfb198c5b16821e425c979e6d2dddc14889ae58475bb52c6cdefecf2a8f4dd6e462bbc8f47
+B = f4dd6e462bbc8f47
+
+Quotient = 170e10b399a4c5fe354b536fe59d53602102f215d5107493680ab6e181f67d75ffd45bf49ffb23cf9269b856156b5ac6b1c5def4ab1abb18a
+Remainder = 57131776937c5df9
+A = aeb35966e2a616762768b7f63ce3aee5e81561080617bbabd7846b3ca03fafaaef83dd05b8d16cef40db0a56f3b0ef6eca5e236681cb57c8793dc0907d9aa30f
+B = 793dc0907d9aa30f
+
+Quotient = 1acdb88f047f9bf679c50ed67ba01dd24dca92103f8ea2677215b6142083b64f9fd2a365499dc8f2bc61e29fa176f7d76b55557fa58e34f9
+Remainder = 5065b726dc6b3758
+A = 15a6292c9fb66c6770a8dbc6fd431d2a4b57338581f78d0860fda90182cca563eb2272a79fb4f5a6fc72c90dc23e8a95713b65988b5b3f9bcec4f0466c1c47cb
+B = cec4f0466c1c47cb
+
+Quotient = add8127c0a27c961203ea0351aed5b3c75aa816e9c2684574e55f55c7140adcbf69d2cff843e5f53c157bd60b43c45c8b6658de72062fbba
+Remainder = 67f48d3584cf4fe5
+A = 4e8938c8cc46d34e3369c5d8536b18c963dbde56020678f77cebac5f8777e0afc62ca2ba4f533cf6cf7561bdce77b6f495bc1b05f1416d1173a6a288012c7c73
+B = 73a6a288012c7c73
+
+Quotient = 688ddf883a0bcc1ff9bd582119c2fea7c059e19aded8c048390a1d8fd7d769666987418bbe0d4cf4b67009a342958928769375c1c0d558acf
+Remainder = a5356d04b64ee12
+A = e0c9e32056977aeca72e229d83f0d320fbaf5cd8bf3e033289f46101c75ef59a854982f33bcbcfd200034e8ff439d669a03fa404e7dbfea822664967d67dd5f1
+B = 22664967d67dd5f1
+
+Quotient = 39d4d94587fd1445f31457c275fd6294fcb69ba155e7da3e6cfef38ed1272d6c95755bca49007ca62cc101b038d264876f18594b8fd4c329
+Remainder = a34980d5046e2ed0
+A = 2efcb12fb55c923f5c6ca7ae076765059e15d9e75240a6e5fc3db92de184143fab1934c7450c3a380a9851846c9f43d67bc199a314e82e72cffee795d695f82e
+B = cffee795d695f82e
+
+Quotient = 145ea82eff186b7db4b11fa1514674fb9d41c698efb33227eb1abbc4eb78bdb2a280c0c4c47adaf4e010a4336cbb5650becd1ef544e223e53
+Remainder = 36052bba2867f5f4
+A = f6a6c7e33fd4c664652d696c495df387b85b132cfdfe34bbd35759477b4a3c052f610df57e49e85720489e4bb8dc923696400a4a28dd000cc1bd491446a50b96
+B = c1bd491446a50b96
+
+Quotient = 35d0c9d870348b113868282aaba22b21ec87cf421519a23b288b150604729356f924090ba038d7400c0ccd4932836c65902b4d3c46a202a0
+Remainder = dc8c7d087bf24b0
+A = 22228c8a5966ebdec64007704a373b0596ae702d62e29e468653b21a890ace2f02c27f26b043f48495687ce8c2ca8092ead21aa250ce0f6ca26129615a2432b0
+B = a26129615a2432b0
+
+Quotient = 52fc995a486c4bfd17ed9722948e9ede1c4ac2fe80e6bd7482fc47944c4337a185a506a9ca473d49073e1b813ad742f19b13d57914888d5f
+Remainder = 75c703f654ad630a
+A = 3473041ae301dd2806da30dcf06b9c09600086d6873cf3ee9d5a0be638849afb56bce2664f797de4123f6f8fe3e12acd32e33a285bb7f493a1cc13a7108327f5
+B = a1cc13a7108327f5
+
+Quotient = 1744946730b2789977620f2e7439641125dd338d1b31fc50813b34dea70b83d209330bd17fd527db9a402ad9752c26b8823082ec9971f4ae65
+Remainder = 453a3d59303ec3c
+A = c0f592d83649bcafb7e2de1a8a71fa863c1f51b595bfa638c8fe30731c6fca36da975b6f19c657e3ca29efff6febfb311c003ec68189998c084afe4979b5bb19
+B = 84afe4979b5bb19
+
+Quotient = 468f3eece20aa9d6473f3c559760793e702758a3d9cc19d7817216392c7cc7c3968778cf2fe0c3f0c1424d7512cee19ac0717952f18aa287
+Remainder = 5904e71034e3a02
+A = 1f0c99a128c757d76ae6dfcd01012f0453c8f89b00476ec46321ecb872f99a48b4da29a4abffd0bbff2b727dfa182652ca85350b4ce100fb70a6a40ab6c41d95
+B = 70a6a40ab6c41d95
+
+Quotient = 12198913ef16c1cfc7c1be13f1cc5991a61ff74935e09f0c46d26456b7cf2825403b9851d07d27e0197c1fa2ac5e32e836979a184f14cd94a
+Remainder = 33431c3df719f946
+A = fbfbf5494a9c5384c7ae3df6c02a5e1f9f32dc31cd7f437832696bba164bae1a9d95daefb8bc08e0e8e637436fb747084460697b5ef5ac9ddec06757dbe61aea
+B = dec06757dbe61aea
+
+Quotient = 376c2f902566d83c21eb7c3aa3a6fa0482ed52c253f67f00d5b915d0183c2d9a2891c2ff837fcb426a4c990c48bda4f90e0bf69d13558696
+Remainder = 31540f5e05e8b4df
+A = 2527f8cafaf7e8319ca53104229199188ab1ca5fe592bde8ecf605e17ca6446414e06898a85e177d6985b5cc6d4eeabd6b222b5f44b4fc1baba050665c090b5d
+B = aba050665c090b5d
+
+Quotient = b8fdd5cd7b2d9295258bd99e2780921cb2ea70627a79088039fc3ab1c62bcfc6307e86db4a7803f18e5339f152063f9e41d370e97b1ba2f5
+Remainder = 4ed4f2d12e4f4ba0
+A = a25bd113c5a8c67ef65aa80f1512de43c9441fec0c41250048d29c406fbdae80912eb3970457d621c552e3af7ef2d6bc1b5448e7df5be724e0adf6f71df7eef8
+B = e0adf6f71df7eef8
+
+Quotient = 5421daac8cdeb6acc2b8b0dd85b592f255ee4fedb3a9e90f2a5bedfb0f9f033d7c562c96958346bcdda4664c67848b9d9fa7d3892bc4e9af
+Remainder = 7e5661558c345eea
+A = 490aef65c81b32f5df76dd58decdec3e3f73bc1fcbdb6aee0c93cd98725056153b572509e75d2cc4b042bbeb0a77d27fbca1e39efbc765adde41a7dfc5c3576d
+B = de41a7dfc5c3576d
+
+Quotient = 156a8a24e7804c5f576cd1757dba44cb4185bc13cb56603b54ee3b70fa35cd98db1992904d4f7d99a63b3a486e6fb31141a9d39cc0301f897
+Remainder = 29e9c1627537e5a4
+A = 5e4a10e772de8dd2c96acd714f7d3880ae8ab460095a01038f3aa9b8ac8165889403b42019a1e70e0e7f32e77fb388eae3579dbcb690729c4671868b0526aeca
+B = 4671868b0526aeca
+
+Quotient = 1b0eff2ff0aeb2c02ee3cc9e0bff808f4d616eb290293b13a6b58a84127972bb417d55e1d001a9720ec72562ef3ea688e64c4f32c7e26cc87
+Remainder = 664d57c57d4952e
+A = 806b8504abfbeec4d5923f83ddc071be88e11c4394168854448df96160b95adb1fd9c288852e2f3df3e36916ba5118815ca2e83a6a7d9e074bef9c961e2958e3
+B = 4bef9c961e2958e3
+
+Quotient = 2e363b13b0457a0e9effc2d7e297df78f35e5d24d0f8ad4525b573fb2f66f374871291ee8a8ee3d15a823b560156d474c678f79ee480bbe4
+Remainder = 5ba8f49e0ca36ab4
+A = 2e1bb261d98ec405dbb068daac5efeb0a51f08149181864e9dd6bf6cfcb617b76d8facaee2ef468807e0403bc550d58e8ad9e5cc0f094b02ff6d0277fe642f44
+B = ff6d0277fe642f44
+
+Quotient = 149a5b1a81b9e47ed36be76252055bb202dc25f8fe7beaa1ce59c279b32941cfbaf8fe4555867850b2fba43b10b74534db82398320f9786d25
+Remainder = 1ef621737e81780
+A = 63de892cf5df40c98de78c755c99e94e0e76cd5dc0b49b8856fe69dd0abcdc535bb1416f0d02b4eeb54e8a939cf7ad4edfb7de4dac87523e04d8ea8637e50920
+B = 4d8ea8637e50920
+
+Quotient = dea8a9211974758752d89965eeeb93cc616f88ce757ec2809f829cbb8d99b4ffdc3f0f643779fc5e0bb53b5273a5b15965f4a364863592f
+Remainder = 9ae7de3edb6c7edc
+A = acd5cebd069f7febc38c318867ba3a562bbf8ea9b19a6b33538ba107e49439f8ac6e880c6267c29b39141dbe2273d93062464de307efdb7c6b738c0bb282c3e
+B = c6b738c0bb282c3e
+
+Quotient = e9149b347cdea84d740be70060b239af000c4336ddf36fd5159083b795c4763588c87a959df0104212a04cc928baf60b0ea72e8cccc6d477
+Remainder = 3ef5c6ee67e6f5da
+A = 6ccf1b8b406e6a106160e73ac4122a04c0814ef5a47708a6776eb52002d52772d3fce3fc05398172bba191390aba925bb23aa1eee626410877822f27d1e3cb09
+B = 77822f27d1e3cb09
+
+Quotient = 1606c2fe44cd0b780ee474a9c7daf0b2bebf62db0ba8ef5a99fe22036019890a4c7dff73e678965bb0e2a6e61d00a74a1d33dc1106842115a
+Remainder = 7cf920ba2897f714
+A = ef9a3983f26237576311a871e4a3df0538593dd0cfda58ab90b889fdb35c700f7d158abafad127605057ca0532e846992c41ec06902ce58cae0c1fe238c726cc
+B = ae0c1fe238c726cc
+
+Quotient = 8ccf17de5068451fef1c2808c62e19997c7f920d5cc0fde1f5a247cc57c6d730df553cf33094b786597a343a0ce9e4bffef568247e904343
+Remainder = 2689c40a54df34bc
+A = 8435babd279b7a3833d01988c58005d4557f7689ea9b7168ef42ce2b31a1a3c32a982aff654f271a651085335496dd826ee4b3bc27f58920f05dc6676e51c662
+B = f05dc6676e51c662
+
+Quotient = a9e78c48c779140b1d15843089765ce9ece3855537ce88cad3eb7aa7bd6ec72df65adacba2bdf6c491066406bdc3dd3dd734a70e93eed958
+Remainder = 53da0b15ac079ccd
+A = 78550cb7b58b58d6878b615dfa25a5b90a1ff631740e631c7f8829962446903c686c810c46a1551b6c1f7a89ae898435bb8e36d1bae24a80b54edbf4bbc9af85
+B = b54edbf4bbc9af85
+
+Quotient = 1e3b41304ee07f6baf1ca061e0e28a3740991c6ca2749eba70d3ea1f9cba8adec45cb69a31cbff22784a9e056e884713c0812e8c7981e49328
+Remainder = 3d051148ec43a72
+A = 76b9453d315e7a9c592e1f2640f5b6b90a65e7f2ff8ac24b9b47e35abb76fa5d303be6d501b341a882bdd9d2a1c81a9280724673f87fbe9803ed5a2e7edaeec2
+B = 3ed5a2e7edaeec2
+
+Quotient = 1921410e1a538a71d33d9c5de95593fada116200c399fa7590ebc374282570477f5f4abdd5166784ccee9671a1a23b96378df62168049f6b8
+Remainder = 1a1f4aeb882d7546
+A = e4aa84f782a65d376b10e7789a7d56695885aae274db6cb37e0a34414397a57b4a5f76dced11376af5fd11d31828203e685861a6dea239789196fe73d0e46116
+B = 9196fe73d0e46116
+
+Quotient = ed2afbd2e63617a651911017d9d02224d521e99275ab642ad1a941827983b17ef0f2067b5405b20e8e97f2ae6099150a1989df94276aadee
+Remainder = 4578107045b9cb81
+A = b547cd987638ff7e3c30fec9b728bc10c3b8cf16e7040bfe0fe9a26e44d2898c4c4d28ef525cde2b4007b2ffb3aa80fc4514a99b9aa2e112c3acc56b72ddbe9b
+B = c3acc56b72ddbe9b
+
+Quotient = 56181509251931afca3bb9dca21eedd6ed4226be67497d8d1bd0ec052af146993e7358f132e842f9b6c4934cf1b4501f5d6c5912e65c8d3ce
+Remainder = 1b9861df51429a6
+A = 32988a4e0769a5aca200f6f6f1498512e13b4904a9a311cd8a962fdd688de0c6e50b04f42cdd2cf8bf9b0a6922657f9ad195773e1250f85509672452618da9c2
+B = 9672452618da9c2
+
+Quotient = 1fa45bb973dd1d2df0002772afba55284a1e41f6aa4b0d1a6c6a4beb8ae00b52e88a9889037b8bfa9b7ee38036c57b713b48af156c3f9e8d8
+Remainder = 2525d52ecdec8814
+A = bda657ddeabe24c82c883e85822941bf64448b7cbb368468078101289b6fca36680b3884e35edc1fce5a5cdbdfc11359a1ba8ac0785c09ba5fe5cdbd30726df4
+B = 5fe5cdbd30726df4
+
+Quotient = 63e21f5568d07976aa81a2690b9e81b76fc3291cdeb010d1693d0e80191186815c7b2f83551a5f1b172640425d4733f06f4df1b2c8a7e6ed7
+Remainder = 14781a368471ecae
+A = 9f3dad0b3b56de15ac46cde1d79aba6a2f3b34d685cc810e9fa3f2d865bea4afb480d58653630319a258e9e8ded9be93cda3bc52b80a9359198221221724cc3b
+B = 198221221724cc3b
+
+Quotient = aae37878db016dd758003b85ef52acc7288b7b74c4723e3876a710baed4751d3be2ae49123b248f2b2c55a5be702c4428b1dba9b8a6ae8a9
+Remainder = 6c754d5c167e1228
+A = 4b93a98eb7b92cea0a4f5c2223e77abdfbd332b39f295b4ac40f71625d88e4add7e482adf3010082d8dd8854cf714a54fba0887de87946e97137cf7eabda038f
+B = 7137cf7eabda038f
+
+Quotient = 9881f551c4b7e67611f37df29e77cbe4e2d9fd5e17b7da3d013d6f3d4312e53dd26dfe3a2a12525cfef1ef81e6ebeeb7ef8fb4f918bf15ee
+Remainder = b14595005716bfe3
+A = 7737f8e7337160c14cfa8411236ca0354d8aeabf389b9fc4b14bb2ec3bb68286f3d82eb394dbd8062862b955e9fc8e86eb646317d1315d09c81ef51b30288cf1
+B = c81ef51b30288cf1
+
+Quotient = 4c8519d4d85ccf845fc5b8f31c27c60f0893ffda29ba86e8a3fd5fe67de5d29cb29362679abde996039b8febda2ecf71f6b9e1c1874361464
+Remainder = 10fae644af084f8a
+A = 900f7846e927760d9986894de6489e53cbbcdd59f7707917e7581422508f2ce79b77bd2c56d964a41e60baa927ca679faedcd9cd8102dde91e1f583ae834b092
+B = 1e1f583ae834b092
+
+Quotient = 16ef17b40bb73063f3cd0929cfe2405ca0ff2d3d426ac05f8a8dfadc85659105f7f728e113baab59247c4c7936ab975c08d6f1c72c12c532
+Remainder = baff11e6961c72e3
+A = 130b212cb6f3d854e4f17524953fd8592f5e59dfe92fc7d955e2899d1dde1ae4aa20d749caa349ca8d1bda7eeec2310532a7af54660e2a1fd4929335a1623bad
+B = d4929335a1623bad
+
+Quotient = 1cdd7ee2eff733b83beda5b862673177e2f2151ee0fd9ac0bf0ec5b7e05516f1d1b59ea754b0483d0e4bfb7668bb99117907a58a8ceb78028
+Remainder = 29e33e0c2a515780
+A = b0131ec2c1ffe9a523591a9453d2fc740bf885e7efc1a0158905da1e646745ef1bbf39b406564cb3da2f842bee307b36219bdee5991c969d6199279c25d4e380
+B = 6199279c25d4e380
+
+Quotient = 20bfcd06f9c54c537ae563e33dab31047aa30a6bc4e7eb0902bfbab3bbb7e65df442c46625c39e08c88310116348e9ebca2450ab463727f90
+Remainder = 11d8f2f6d4c1f55c
+A = cefafbaa2990eaa88184162ecb118d20e5999e5a8fdd25ae7f6248650ea74a8cfb92c58efecdd5d31eceb618f1596d7a6bfd31d092cf86da651f629975faf91c
+B = 651f629975faf91c
+
+Quotient = 37204c5735e4ba5e47e845d8b652cfc2b1dc715abf21ea0ecf5b1c6c8b9e596591fd7a7f41787be1a028c147a721ebb891b0abe3bd079b589
+Remainder = 1ee700ffb0ea02d8
+A = ce22d36b3cb913b32bd0e25cc14c7270d3f7b8e600a9b6732377f846adafd7fbd8a09d12fb7011f2283d988fc29aa25948dd4a0f24512b4a3bd460ee19887d35
+B = 3bd460ee19887d35
+
+Quotient = 191051194e4362bb201f5471d4bfaf92f79b6fbd119ca3dc1afffba334869ed9f8acd14fc42a2d8f616d652610a483ad90f5140e9a5ca4172
+Remainder = 74785b6874d8fa37
+A = f3c79f9a6af1c5bec72218d969620149afe8bf068cf7a7aceda977076665bb5a2c30729ac3aa976c9be379c6a5458f1501db8802652ef69d9b9f4f097027ddd9
+B = 9b9f4f097027ddd9
+
+Quotient = 6c46c17fdb03d192f75d636e1e2ab4e858d55f0f205cffd75550c4347726b5cfe036c6c901782cbe5a04f1985d9fd1dd39d747d25a6a7a88
+Remainder = 9a836be71a24e72e
+A = 4f6cf6e357b4985442a25b5c84e2cc0a5e685e2f5ff71ceba439b81f4123e16db2296dd4333fff23eea92bdbb812daf1d27c721412fa9847bbc9a0bf08879b1e
+B = bbc9a0bf08879b1e
+
+Quotient = -4984390f93e11c9a77880cfbe157dc41d43fe901c8895ac5091c5367a77370b16d42e8cc260058adf4d3fc8ee8cc6c0099804f4c319f15561b0a2b1caa7d703db82a726c9eab569c
+Remainder = -19374dcf21822188d720d6ec892bda2c084e8af84f38012da7029a3c3660c7e813fd4f7644ca80373575ff98ab6d743e939269c51bf62e04f
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 330af318ce0ffdaa92448777ed117de9c104e0f975651322c8e01b1c470f3cfb7a78b11f7daeea57614cec37d18b89155f19babeda0016171
+
+Quotient = 1a56f7d6c06a316a9a466319cbd558a99f06843782673a54775d859768a61933de3fc410068d00d5f6ab13fafc9228fd40ad41434501f8827bd7461441140eb6977f18d102d446
+Remainder = -3c3d566cd48a909292be2ce30f88ebb68e9122a3359f52d1d7b0189c467b829a9f226c0b64845715020dee12d179913ddb7f17da2db86d854bd
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -8e770450768d07ce20ff8f5f6af464b1ee5f1d0e8faaf927a19d3ff801f6089378133e822b8e63cf29c4c9ed721adfc91d3355a3c7bbde77bdd
+
+Quotient = 42131cf8f52a6a3f189697ce402a8c9439bf05cb3dc1cf8bc49dc2f07cef15b3bf0102c941b5b3bde6440abc6eacfbf77ea8da06ce932fffb226b33dedf001e9657464b0f06
+Remainder = 4cd483574fce075404dd22072abe61200fc455c15b382c7f2962ffd82c38ec1e2c60f71267cbc35fcf77fe1f9301d6b5f884f1c416304aa9f4d4b
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 38caa64e74b29a7e9bbf341edbab112a730b17103831a9ecb70ef077e9660b2dd1fbf71d7f6bb4cdae2ed7cdbe9070ec9fde996c91b9bca5b83450
+
+Quotient = -11d6883fcd705ac97cae5bb7f8a2929d6f636f4f232ae9a4af9769183dfce9a9296fa0714c3f4fa1eea467a5c96a484a59d0cdd87496b9398e7a818daf89a58add3a39e80
+Remainder = a6b7984fd80d719ffe2e6eb756e4e3bd7ab51f6088e04ac8fecdc744b0385294dd23b5007910109abf40cfca814c10addcb5330e422b6f5eab6efa2b
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -d25d50f53c694cddd56aadda2654ae5888603b39cdbace93d19c117af5505750aa24e615f95446862bd693f5b444e2a876eb2cf49f6c7acd007eae02
+
+Quotient = -3fa898b02c621915f44b213ba4e80b8e85c7a2f4c78df2bda7d99494bbca3eb2d9354965d83e1c9001f10aad9b3f3ed837a630b329f5a4b28935158fbd9d291a120b08
+Remainder = -320d41a3875da2e83ea9a83947f5abb1a7026c84020e983381722bf7aa87d5987ab088cb2c37fc3781c82c81bef3263fec560023e236a747030618e9d2b
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 3af2721aad4b18db27842b5e539d8cada9dcd7ac4c5b885065dd2496a6f76fa73c8a51b239b5c068ea6feffda22d8ea806fb488ad5a94210264597edb40
+
+Quotient = 179307c3e14de14a744d082825ed723b996a4e15f156ac473960583138c43f4275b4436c50ef8f21a7b450a969819b81c15bc355fbc5fb55cdd8e124d931d142851a
+Remainder = -9c8eabd36a25e995c1811b79a2a0357f6aeef4477cac0ffdd130046cb2a647f928a34d91d9b489d394965719cd58604b957c693a93145328e5568d33d88a9
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -9f2d3da1da77914df66bc889a40847a0d705d4648a11f282e09173d170e96d84b5a45092d995318fe7a954b54b88b784423402519a38bb521e84a4f6c5485
+
+Quotient = 6c0f316406afb4cc2aebe34f7948422de0b612a02dc47f4ae59419c579fc465ceae1980a3e524fdfdbdfad4862f168a9851664688c9ba01a8bc1ac156a6276643
+Remainder = bf52a2fb6493eac22fc8b334ccd8e8fa347620539d9189d535373f94503310a027c5423197c7279bb51ab8c459e27f548d57b55740320e80b753290d077aa7f
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 22b9e55639ad3ff4f071a49c8bba6bd9047e162fb31882421db8ec5ce46f28fbc35040bbc74ead5a948c47c43e9c7adc32fa52046b53f12b07b5224e0d8e93e4
+
+Quotient = -1008fcb6894d8c411905136fb3e05b38ec5d8df35db06379fc2d6d3e3579bcb34fa6e021b98b899d9d082c111b1a6ac8e50418fcd5968ade6aff8828d8e4777
+Remainder = 3d7dca387b00c677d855fc4af4d86d86331fe4309929039e828765f0937990bffa964d3ffc5d4f2f4b8bea978329e7cedb847c7cc341ee52217f903ddcf9446ce4
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -ea045323f406bd7ce25b3ab4993b5f6dd92ca80e3a02607a862deb13470ccef229fad67ae958cd87fecf4f08d9609595077d0d1360d9fe48c4566e237aa877e7b1
+
+Quotient = -42a50301031962754ebf9c4b1e125e6df3dd40ffbe09c044b1cf4b62ffb4f92d298b05933a450bcef65e86398da80740a610ba45928000a5c12d26e9f6a4
+Remainder = -c5485b82cfefb3f980e0fc7c6cd89b1345a8fb942299bdc36ed4ff8916016315a0da84ca0ee2824dce3c7e5ed49d517c45173c9c8e30b224940af6cf828c73db8db7
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 384e523d5a687bd1a90101e43334894b6a27e8c6809a8bf5bffabc34d558a8309997dd6f2a3b7c1a63100dcc0b6647b444ef7e5aa4a9c52c7caba1ebd096c3fae6f95
+
+Quotient = 1054439945ccb5bc5461fed04e364c7a36d5dd2c0428872676debe07654b2ce31e435a90c81f2bac1032143acb0c49ad101398feee8426bf270bdc0229
+Remainder = -7bf919e14b2559ab82b3c1bf428d083a4c851a7a1fea44718377e9e945caa5cf48e0b1ad727e251bbb330292402a75ecd96a56db4ad07146533a3ab5a717d0a25a3a7c9
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -e5cd83a644ec86b94f5e33d4dc307a2f14ee8653288145dabb2b5f894560c164470197fb9e37749656f47df343c245258627aeea17965fea10a57336bdc6b4a47443492
+
+Quotient = 62675274798218da426a54ed7158f8f737b7b3c328a9c351371f0cf61f41712f9b28741f187eb635ce45866762fb5fc5051776151d202e2556c5845
+Remainder = 1aeb5d1fde3c259917e430e6790b00484d0d9508391ba6ebab0f6299190d4b34f5f7d8ea2174974471a1e28ee2c15e05da645db971f699d5d0e80569b7eba7908ae579f5ed
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 2622350611b486e6be7a7c1c073c230d604d782c2696038a3233ebcc3f01c6a711969094e47f49e294f2c5bcd04fb1b7c0934f19bf6e7aa519a8d4ec2c172ac59cc1a57b26
+
+Quotient = -12970cdd96b92c37787971cd8dd166999ff241be881eb9543ff29165a9c1a3beeb38b1910a5724ffe2b73ab95ac1ca88d3989aa531374d4ec6122
+Remainder = 627455cb555398150e5b4c1c53ee16dac8d80d9616ed1ef40031424287f8028a9cad1a10bdd8430f6f65368cfd00390c8d4355aa5ecdbd1ff0266a1ade235f33cb5309446961
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -c9dac93cfb7abaa3fcde359e09a92ab0b5c06359bc09ae9bade3c6783064dba90b233b4c8d5c6236a13ef96c7a223e37bbdd931eae61e845e5a10088f75b3ff5f1158e833b15
+
+Quotient = -6742b3871dece5986d4e219bf5f43c101da8896f247521fa286fde696e0b71ffeb3b6a3e4f33710c9ab150b7a1f747cee76839c5e7f2509f62
+Remainder = -203b2d6eec9d485f7b439fe9d4c640bb31170af38418faf4daad577c30e44ca06efda55ceea4fbd959b3809fa2002b6e2cb891decb09334ed89ac66ff05502036b2155ff62f8aeb
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 2457088096865cd052e9cd9349c6e5e34e46c89d6e860a36f8e2a0bb1e5d983e07d05e6f6b31edc67e4793cb4d40979c029c80a13e654b66c8acf6b894f615a3ac800bbd09ce020
+
+Quotient = 15eafc416460d757d0abbda8d094eb535262a71dd033c25e704a6df54265b6123247e5625da476e0c220ba88582a1ed94265135bf8bf1fb1
+Remainder = -64ccd9a0ae0b0abcb5507d51b2e6c8e52e67907474605c439796febda06eabd8a3185fdfc0bd088cc49fdf564b5b45890b07269c15b1aa2f993cd9872b97aa6cc37dea2f03444b3ed
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -ab34d3906d8a2b806b22c73d44948d703c1e05a9337f75cb0b5df5205c5e2d23f8a92d8381372f9398c9ac2f7b9302b83e48b26512ccd0b06e6b8ef1b930ec2678d71e2eddbf7349e
+
+Quotient = 3b22916d9fe3145fcc3b8872bebf5aee4e14235f618e0aed09199852c6bed80df39256d8407d334c06f4479f230913370b7d451fad99d
+Remainder = 1b02a7b97f9ac1f6306aa00fff0e59f55fce463ffdc640364a950df29474e08b67cdfcec0628e973d42fa1e4f98e988ec4c47e4915651a1731b71d5e36a10a0d1b3420427dbb79ba7d52
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 3f74cafe9ab0c1b307cd7571fd442665fa3205fb2f45b3811b92d1d38b096a2025b8170663a29c52ca84da102e62048e583fba96a594c0b23952fec587814857c25221ff2cd0533cba6d
+
+Quotient = -12ffa4b6fc369404968911c17358012b993c18c2ff34122e06f450d3d441926b5f5638b40efb012d76d8bcd3c0012d0a0ce5d55c596
+Remainder = 64548684fd5f6c816bd296234740a4eed772570bd4a48852462f9cddf14f1350ce7c7c6a58aee8f66ad7df87927458db09e3af08eb5376de08444f35e5171cfa0992fb27f70b81574f6e8f
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -c58383afca9e1c480ee75d3cb6b0b99ea42e827d39fc96bab6b0dddc97e3eaaaec02a74847f9f7d49937f5ade3580bfcd491990737d172d4079437067251ab403c36a9826e974b113e2d2a
+
+Quotient = -4964410c2b038573107b0151b36177cdd62495e0dbef536b59c8aacb8836bb45e7bb014e5022360621e8e82a273d0d462b8eb6fc
+Remainder = -1250c42f8c9b129a5c477be446b86356edd1b19409d362c3a5fb5d59c30f1c3fdc1424a88a0d6ce20bae885905d98c8a5a6495931f73edf4c60112ed78834e3bff6de3ed54c867fbf16a1cd53
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 33212ef4a8e80daf1049ac6f639f8e1990142ac32f7ebc97675ec90f8eb1a2814dfdd295ae67317253d0187ad33f3932a3a7efb056d0a3c87d28e64e23e9f1de751ee6f0f61c6f39d08d72f0a
+
+Quotient = 17f77efddeed52ef2e423bc2c10d2ae15c97384b766f4108474964c2a44789e61249103d9f5fe00b4d612772dc6ea12a42e395
+Remainder = -1ec95323b7b95169d5ec0667f3cbf683e98c15dd0fe44df4ed9de9586e43f1f69337e41a6d11d889452665dc0b03cf8d9ef2effe0b350eeb9f6468751b8a2c42608ba2a33192b770cb62381a966
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -9c91fdf2dd1827ed103a102db254630c278bf8b47bb12a342a92f081acbdd8ae5f5476ae194e24b187011ac25b19fd09e6e690777f9d3efb6b3a32c8f5905e1478a27fe4b1adf17a70abb4e7571
+
+Quotient = 4f5dec525ffc737094f40d27446ca0be5b7a2aff02d51d99609165c4cea0dbbc1d92bc0a8680782b616c149bbef7f5ca912
+Remainder = 1bc84ce56a9a0c74962681c02ac927051c81f3824d9f3f0f91465df333ecdb449473d9c26ae3abb9509add5795e89ba5eba6ec7c89b114c86e6991ca0c185b34d6e66925a14fd82809dbc4936d273
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 2f47be01e6dc6a86097676fbd472c2af0c83a2f743fcaa885e44fda7e9f350e9fb7a8cd07fda59ccb7963f1e95e6a1236f5f94939decdc85afc0e523c711b24641c844cd3113c17fe35ca988ba407c
+
+Quotient = -163cafed5bcfdeda88555f30bd4cc2da2cefe2bcec9a7c19c36ccd04a45121a5a0dc28d0bf6ab7fa4b78933c47a5d5286
+Remainder = 93f856077f5b2907cefcddc4d767ffeb0acb7af64bb9dd8a15dcfdda6c244c24fb8404ff9ea2fe1dc337faa05930d33cac4f61e171d0236e222374cb3da76396ae1329a407fb4ac652fcbdc568d0fafb
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -a8bfcac452a5e48fee9132b73bc2fef771450143ab80aabd8690ce54c9b52c2b5a669076a7a35fa6d926268077bec6d90b722b5d074f28ce3843fb0147e567c45f4e91a11416c082762e71b5c6129c08
+
+Quotient = -617dbaeb8c6f9d584e8eae923c872048f9f9bf039ec6b50cf8f09c061bf79acc3311b37c2502e560848c05ab316fe8
+Remainder = -1ab4613767c4f1f7d127e848f2bb7c72a3a9e1dd6173b63198b80d3bbebce6a31494f19b53ad9e3a77248e6f9b26fc59060e2759a20dcdbe785297bbd912da9a1819527fac550d64bfd20ed1f96450c30f3
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 267d9397138fd0374a7a58593d41627ba1203a646ec2c04997acf607e9d217b8f40183d2f9304447d6f7e727a476e636ded4697a5ff30a9ae3d249baf97969658209c1b32ddc0edf920b0b278e9b5464313
+
+Quotient = 10ad85703fd51870306c5e36b51512341d6d39e0bac47a03732787b2f62e49c76666f7f49b2596de6cb5c5b2f31b
+Remainder = -846b4479713bb19ebb8c1f1b75d2be0f39fc1095a3d2ca149b5565146bc19382b86e5ab0d098ab1fca1ce701d582400190fee34b602845c3c0c498925710f0b9e3af2412ed5ead1fe03d77e9b2b407ac83823
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -e0ffa4e120f2f46fd1430b6022fd03f71a22f9b120f8d40e901279be235b32d94760fb8c2403d23cdeb728ae73e2b16af7322d6ebd5f5673187668c99805e700f1e997423886bbcb851448dc1ed4cd66d6598
+
+Quotient = 41567bbf616ab41da51108d7edcb5a8a4877c5a8663b3aed7559421b1fcf4b535a54989efedfcc935b3917fcd
+Remainder = fc026e554a0821e0d36b796fe6a676fcd7383a55fd6158d78ace4edfc3d8aa87c65f0eb41baa2aafadc51218b0562ff4b5c9b17bbe84afc491d9e309217a5138ad48dd51e1b1a9aa51d69963b608ec47d63fcd3
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 396e9b45ce43d3f89386cfad8ddef4b483ecb5173234530c67447ab74629d246c18b9da09522c77f598957e3fd2a1c0c9417399912fd547fb1023ba6b90d63d223bcbf3e7ba155e51bba7e8635aa5c39d2b9dbb8
+
+Quotient = -18f1f395347ce8df530d9330c61c0e30ac9531b50a0af2ae7809db1258285c15ba7a436121287990fcdbda2
+Remainder = 51417b9e9995de34316a66a2f70c146df8e36952fe64124819607bd8691a465f4fde98e590dcd56f0faeb95d1b67751081c2393626713c27ec2a2123aec2a4ec3761e5ace4aaeb612d46e52e16d72a186d2ec8a7ff
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -966dfc779cbf9c388a84e947d1128e2392399ff45d9491259c7cb19589154f82f41e852e0c6bb5a728f6e87ff4ff95abcb9b2b57af1b6b7fc125497775ecc1338e4bbcb5315f7afde4e283347184b908545211afb6
+
+Quotient = -3fd962e88dc1d501fe9335fff8b6b2d50eea967c3035a3dcbcdc9599b81f9a445ed5a6ae7413b8865fd4
+Remainder = -97f06f6155f8d0ee6850728192e0b4fcf55fbd9ba982c5f1d598ddcbc4e1c4be0e209fefa6ab3b7eb2b4c645e4dc40217202285ab0a7270d085dd9d4fd24e5293faf6797b4c3c79bbf3ec63fd82942549f9e8f862297
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 3ac566d6b2d18572360fbdc626ec488aa316a74f33d71a17a2d0e1d2bf26395623eb91dc4abebf2f944e9bc3d669fae2e4332088e9ff9d9f43927a7888b1390ef60f05efd6e63ec606ecb3e164ed6dbdc9d088586aa71
+
+Quotient = fb5ce21bcf28490afb64e6746a1a81792c90eae17407c0b4c5ebf2464eeea43e516be2c615f84901d
+Remainder = -3d255bf94c3d610c32266fd472d070c0f5e7dddb88d32723b2e1a20709aed2faf28701e0d0227c2b33ecfa9e708e5ac354a97be732b786210d86f1f05d191513386c580b1ad1f4ac6890f87fd0d4270f23cc5c2064502c6
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -eedb64a6e204ee3d6df508830704f1d5b2d2e627698d38a114c07458ea0befd593a80dfd2e08fcb1893adf57061ec4fbcd3130692de7c46f5ca51361e9b79bb7a91963618b8e5b7591392a5f0e3be954e8b9978c97f12e9
+
+Quotient = 6933a3123d0b32693351a834751345300c49324b861a663e8700bdb3b70ad996747b284a8ea5c02
+Remainder = 13849ef93cbc77460c3c496e8f31f7e01a98c21cdfcd6877547161f9601680665b394933d3a0824f0d32854508c89f0e4a0873280c779c7ca636cd89cf6ee5d42a917b4f382be3b9654039f623c11b43164827f870fa0f0781
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 23ab6042240a7709d43de7ee17332a9710bd0d913c42b3591341527bf48d5bc30abb962482292d45a15cb03c9457cc8d78d1e00aaa63358427b000e59e4260bfe1e2cc603e175d7fcf02bd9f61fae3740cb8e10a510ea3d1d5
+
+Quotient = -10e67cbb33dc6e24765893a047252766c2bfad8385150689dd4fec9ef495dff63ede1fdf78bb6
+Remainder = 9dabe2cbc734b910fa1bd25616daee5657d25b6e4dbc2cd93cf8549715c87974a8336fc5070d86c11f6b670d4b3bd5ee8ae3af2bb321fbb4f8fade3f5c6c2d6c366b4d800dd13ce897f13b0d3fb79f1d9ca525b4e7286c56ff29
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -de093dba98747499f2876c8b6b7a6b9587284835ae35f0716dd594c826cdf5b9179f2c6b08d800a77a6936602ff2b64ee0b7c94493bd5009633f5bbe423454b7f018ae96c21230510ab4bf5db394ff153b0e9eda3ef90eb4c253
+
+Quotient = -521f5e35300b9ec2742ff472cf61235dfe2e449772afa638b1adb812cccf269afd164b7602
+Remainder = -2ad10e8758e1d358d4744ad344ce319617027107c0b8db195d1b58c6e6035450c9b377f026fdf9e5737750af5615cff2ac3ccee623c060d779373136d48a735b353d64bcc5f2e6ea1e46083fd799b5f57dd5ad0ff3e6df9764af977
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 2db1990ba1e353a1a62de1b914ccb691380b6ea937c13621a29f0a40ecef460cea52cfbc77d98706fb3c9939ceaaf962fb8003b0cfb40535e0dee22e8e7d04b5648fce2e58803242c199421cc4b26cae776d3603f2ce410ddd1e0da
+
+Quotient = 1d45aa6fe6837a1b7ac95efd55d1690b66487202949a286fc85da7ac0b50b860215e44fb
+Remainder = -7984639b596f1d4e6efea9d8b4719215588620ac959034b303584679a44fa84a4be0c89fd2e29f54e62959f9b7a858c06b0cc051176af82d4b85e7334555ba11c39e6cfa1829995c383ba81dbc220e527e90a1d440c1d069703cc1370
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -80316fdc405bb002990d3ef7d0e98defcd1f0e370d1e51db2d21ecbd96230baf69d00b168afcb7b8da9edc3ef7f6621ae5c5a0d7797e5c92283342e42468dba1036fcb2ffef1f493ff97826477364f6b5a41dc56d6389a01b83eee041
+
+Quotient = 3c0c3f7a777e611d1bd0d17d669a1ef7920b72ea8de06d4b415a73b836e37d6cf0780
+Remainder = d8c77134a75584ecd5ab29e97a909ec139464901f9cfcb1d3d9e29a63d204615b6845d466c8710873980f107c40ab54eca9f8933ef6d726f9bd0f3e9e97eade5eb1a9bcaa7b01b6ad51ff3ecf67d6e4d345f128e990494a2db434fcd3ab
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 3e7dd961be36c0c286eb9e78bf3b33e6f9bdf2c2137a0c660f1d21dea31ac9a044e526bf47ec8190e137a60f1f55e947046b9cd04a2485679e48cac80a1bb064a915208889289d63a6e338cf7069ad799861c31ec6eafe02a4ef2c2641c9
+
+Quotient = -178d749de2dae3a2ea4898c59aaba98ad9f340762040f5aea13cad45a793f1256ef
+Remainder = 6c5d9b19aed9f099255b6e3d251aa50d1e534e6c86d82eebe097dc8dd0748201e48ac62eec070a999c21f5c7684e5a700212e9079b5fb731321dd1e16ca82ce80c1f5c17fd1720f1353bb90997f47f5fce335a43a6f59facff0b3724423393
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -9f52ead13916f9807d0cf0c6699578af52c54816828f22de62328fbd7b4fd6c3740ffc82af4e24892092c7ecac44b5e775944445e6615fce25610984030a345731f944128f5734e6e315a0ea97aafd7563105695d026880d065761687b75e8
+
+Quotient = -4fe43bfa9417839ee408b254603c3dd176653b6915a89de5b781b400162fbed6
+Remainder = -1c15816e03751a203ae23c48965c8541849b09996bc81d28e28d7871fa87d1c3b2d383c056d3084d7d01d853bebe270fe2c0839e71851e169d417c47caacab2aff8a8e05f65dfb20eb17ed8f67475702fa83087bd868246cbb885d52639797b85
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 2ef8419306ebfd215d9079c7a2b959a53ca2f4553845e3cd32caab2635c0e77fee8c5c016c121e3cbedfac57f810c132486ba78df9e719a976e0112516893f14cf9b89f95a89aaabf31cce509ac8e7e62ec3833f0be4336afe6d7d73518141d39
+
+Quotient = 127e8c06e12943017f9dd57ca24dca0ead230092811d307386c81b6efe009c
+Remainder = -24f3431858d5aee412443feab243b465b849f5dc97e4de4db88c7adf774d9bdda65fa0a28cf6b18eac6078b00cbeed2ac406f8426aef868d4b59ab045825d4b0a18af6c9105e32abc72fadef55b221278d329ff6fb9019630411bec143c4156df7f
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -cae6399216401dec0f8ff5eaca884ab061469082ee3a18e49e0b4d5f9cfc98a598c373249a8ad2374e0b3de71370e93a98650684fbb931aa5d8b4482cb0be142492bb71743c251346df66896806f926a4a5dd4c16ca3294f01bb998835e6583d29d
+
+Quotient = 3f180694e59df85f48ac02b6d4faa26278af9641db18d79f198da5d802f
+Remainder = 36cf82dcf8c7ec783b4de68e0627a4a4b2a508637c176de09feef62dcf382bfa5d8b88539b5ca2cab6cbbdbbd0e54c092f00ee13f4a352cb570034cb0a012cc0fbdb6ed32967f3b81d146f352139bd3d9a5c27789468b7d79b84d6a8f6085f859532f7
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 3b7983bfaf565c5ca444367654a07b8bc2bf7fdc04ef12128c392bef2f6b67d9475b4d2f0ce1c380913aa98616fbe1d74dc5c9d64df15f5c9b87a8bfbcadf335a6e8f863c7a01ac175a7d79645ababa5f961fad7d1b9926f7284e254fed33765339e0c
+
+Quotient = -11f635baf7b7d613e84dc38978a21ade2f4cd741d0c4f6ae592d93af9
+Remainder = 4317c686dfd56216bc4865f8dcb6a3446e13d8b33861e74d6c4a3223c387ffb8caeea0141049898609ed1abfc2adbd21756cf64a72272aab6c0b8f2177419abcbf9086635dfbea80a7b884181f2f2ec9a402cb0505e8208909fe062d5e6dc7094d66af62
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -d0ea50558197566f22704e66a70328cacd6f4b7ca9b00c16b7c4b4e7dcbd47c9b2526b3858ebb4de7a571ac570872f3b44ba1fec655c0778a8a87ca24851f6072c5c0b7591b5e67a8cdaca78fa46f201e02379fcb9a8470e4a4971acde36cf501d369751
+
+Quotient = -64a078497f85588d3402355bf3e83d25ca1f0ed2c24a395ef6de6b
+Remainder = -87fc31ac66a24ebd629a26209ccac1b2c85e52dc83c5240269ae5a27333f33d31152c9470efd41472af034e8536bbe94b0a49e892b1d23db3c13fd84b7395d7e3f19d7d4cb4a4c07dd1860826696cf7202483446452aed2b4980388e7eda0ccac792d77a33
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 254a85bf512d9159b00a70678239902ee7e15ac2790ce5747c4a4743c6a0851e6a179b64c75acf312dd37a7b82a729246f79196b8a399ff476c48a05f89c29fb106bb06ef0300c4b330a7b2bcd4ea1e82584c7a96b99ec2131c885c5851343cfa6ae4d384e8
+
+Quotient = 116a06b1d38067cef9f55875fee1254c8ce39b42c19fb232a287
+Remainder = -c15a797fed3810e4f536e9509564b2142ffbfc0c961ee5aa923d43a824765c05d2a99fef79bfcb6310c77a91d9bc6d0762bd687493865de270c99989e891fbf6da7ea5c7c7a1032449457eb73222a011bb755ff44e4bdce8e86f8aa9f687840c0832f7fd8ce48
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -d77c14100d19fbaff6334ca6aa504001a1d56f274632dc89d48e1d517935503c26b60c047cab9e186a55b72439761c884f63fdd2a38ca1acc653f6ccbb4b7262e6215e6d00c8829b448b7ac8716fe0bfdbf8088c8c61eee8f8db43b7b5551f6278081ac2eb1c5
+
+Quotient = 6fc9533f6d0e6c55494cb1b319ec47bde8e621aa92d91155e
+Remainder = a1a70f674cb141a896c4adace0dc58cdcbe2503fd0ad36ce348dc5b8afc96d0f2f8c65bbbadabf2920012798b7ccaedbe8d896dd2674082ad3cc75b54c5c190ad56ff34e8cb5dd29c031656497d48571295d6da396d5f4cdb652732d874a79a674d06a1d7b979f5
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 21917f48bb8e65646c618068fd9069c06e22ce8c679a845f9c4ec843849010abeee12e2d3c61fb963297abca30813c446f2ae82e909ca6ac7839fb58974fa65f3b5d91fb8b3f99d948519ed56653d50026d694060208cf48e3c757f64885b4ed4328c6f071e9f5d5
+
+Quotient = -1abc689fd19523d2e295f260d248041bd00ad3009cc7581
+Remainder = 1ab5af1478fe7373d012befb319b53ff9e36899c1749ea763fb74f7d24624e70ee78faf3115c2a423629528f45295e4adec7b122b993b5c29260558be4831df06468bb1c63e8afcfb1b9b533ec6acf754563d2ae25e2adb4cfe5ee3024611e03a156484a130ee01f3c
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -8c5a7b6bc8ed6ac015ec24efff607b0446c1b736dc8b409e2f433e69d0ca015d70c64b4c924175d0e0102ebc3e1dd96dd4d5bb01cccad229e699f9d8f9ad0e04339d70cd113e93d50c10c03083a81264396f5db2d979d272798ed30efa15d52289d0c72f42582ea56f
+
+Quotient = -4aa210fbc0457fa7366a8aa9a3acb3f9fce812303ec9
+Remainder = -737bc4fdd3d5496fc7f936ccf14bfc3d93f5b7caf4718c444db7a3228b41015c67aed304fec7704ea8238ba6cccb1e94cac3bcf4764a44bafb49e5fcb0339ae44c0114cc304b9c4370363657cd2bec09bf962ccb21f6091b081e71d2bff8556600576e18d4f78fc68b12
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 324774e49bb429553c10156e8db122670d6dcaf6ef5291f515c517d7ffaee36ec5ec5ccb4d12dff71ae7a05bdfbb03ebaf4dc6c4e8bfdc165b77cae20153c27d53bf27d92ff25643b4888cb586e773955a1c02ecbf0fa6958a8ec0b832332eab2e449be6e72c48d2f1ad1
+
+Quotient = 1c8631a18d189f1fb689f896005f2dd2098e0dae9e
+Remainder = -1a1ac9612fc3354056a5378de5b315f12591ee71f0fa9d8a6b2ea2b1c4eca9947e5c4f5ed3d4b78e69ef7a1f5a9894b9c7d85f6e2244ae76881eb06584eaa98c78b60b46084b517f4882758691f91d9e2acfd580d5e901dae14ff4a4fd6b0d7c73450e4928fc6f02fb5463
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -838df2a27bbb033fa0e581073b879d6e8747fff38539801a1870f2e52d91bc84cf10f2560e93784650fba080304244dbfe9da679f207b6920be46b0214a1e490537e56d99beef3f58b30f311a12283501ad79a5407ff209d19a6efd0421aa144e0cd427380d89bfae5d1f5c
+
+Quotient = 4213d04b9f0b30026bd355404bee887b22b2cf9
+Remainder = c2bc097d1c20f050e88912f066b658446cacc7a4d510343a8d88ed007a8c0cfd5d44fe5f067a0e81536d121b39f2d0feb8dd053bb5632e3f9c04be5f6bf4091d646860cd38c96271cdba466ef8b7e2377a51d5669117e664269fe3c08a51b10e1e019ac063d670a3c7db12563
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 38ca0c2f03a5c56676a2f95cd7a69d4aa2085343af6b1d2a71e0d1c54157ec0e8f9125df2a499cdd484c04feb23b1e0042ca908db74744584036c79f21c25c40401d551a65afed0ef35f1ea000fa1a99cb29e6307f6ca0304145f7e483d008cf9efb028ebb654115a8c6b87a08
+
+Quotient = -134e043b3b88b31f89ff4bc709cfa1bd2c1a8
+Remainder = 99c1c846cbce5e9a26c5afcc0186bb1e43b2501ab3205d13fdf01dccb9b1a935bc1cf8adf74d58f1c316381577366b6d126da49991a0d5e02acaa678085f335ff8b8e975e5bf2e52a05488ebfc21a3e0d0bc5bbe67442f77bfc3c1f0c03b7f7ce42bd0fedd8a498f018d8cbea47b
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -c261a6c562fcdd56e67fbd2b91027f17c95da43175eaca6e4069c16d240ebbd240582dcde953eea739a4668fbfcdc6af8ff3ab58674c95de90fdb43f64a61108b030d644a44b0319b912bb563f61e520dca9c88f411b32e99c872cf00a01f5badad584636352913b7429b99ecfbe
+
+Quotient = -448c4922b7a7d5e1efec2c3f41d0264b76
+Remainder = -2599e928027d10d3a11056eb719768e5edb1a625fc0b8a1dd4439ebd30a82bfdf89e617ac7c71622058cc64ba32dc242d96fe3ecb856f1b146f831334af562cf88139a99410dcb869b9ad6ac4826563b400b59f55d8fff262dc920fe525b12b2fa167ec237028a098c9117cb77bc3f3
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 36be11eb72832f8ae7b6bdf689f794f62cc1c885e64706d14a77a11df9761c2e9cd81d8f6a0ad0cb1696c69afd80c8bb992cda5100cf1162d600515568b9dc9c81a518da9d240888d4984df65c129ac0b4c557b4e63ee5be79a27473ff5bca58e559cb04c4ac93b61545e7351bb6514
+
+Quotient = 152474a1a76700598c18d9301866ec00
+Remainder = -274a2f9e2bc5f9d75f9897b28f840b71bb10a3e4e7a35ee1dc1150be61130b4e0e987e8742c5edb75a1ce3158eb8bdb7d657b8ba39436d7c88fbff160c7488ddff2f13b3b95ffe149a3d0d2d406b1737a7671f69c0e5d7074a151cb2776b2d13ca24bec261662f2967fd22339ed6c3f2b
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -b17c79a31d5085b49793b6a6d628109a6047e3b1afc947e5212d0a9ae32b1955cfd6fed07fc60634ad15f32a9e402d7d5f750fb6d1ad958211f9e8ecda8990689e5212cf72b24e9b51bd07a6e0477dd4c02381d0ab6c0ad3cac1f620f723ab004880800736804751349f6bb19d3db48da
+
+Quotient = 5665f53d5a7405c83a5ff382ec376
+Remainder = 252d055186ec896cb3142c9e4e49c441e2ddad365b86ad21ae4ef1c522d3306c2834d6993a5e1f8c64a1ed582bad8ab746f7e773fc004b1c47814f73560db72f7237ef6e2f671d3b19a8777be2e4c662a76db87ea64f32c48ea371b1ffb15df26726854a417e18afcf49054c6d2e0e337e71
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 2b6eb2caa3ca650be02fa199e9ea6c48646a76434e268713753a547e49571f9817ad396f2cb7b16d307801fc8892f0af3e7f93ce08f7955a8acfbc0b56add4b4c7ef7351f60e402b9a8ef7fe02ccdcb4b00b7ffe78c7009268dbcf1d606c3a1b5307d9a8ee6121c6a635a742b8bf36b56cc7
+
+Quotient = -eeda035247bb13860f228d8f2c
+Remainder = 3976edf710ab42bf069e5829de7e16962d1b765f6ae6ad0ffabe723e21ab01cb9f3f5f4edb1d8c13cafc0556c0aa93d72dbcff754ae9260abd294647b71785bb049bbb865a26bba22defc458a14af019a796e942e77d03484028aac2b3798fa730ae0193d89728bf80a8728715a0807b3c497b
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -fb5e55f261aa96f54983869d58b3e9f0757d363b9c43aca5580b7c0380096f396ec79d1b30037702c19be5889fc6376793cad51975100f33ebf43e0897dfabcb9adf3adf8d845aa7589ba1f6d155b25f73dae3b2f835595ad6050401fd4e6392012d06194af415b810b0c10a53bc56350bfcc4
+
+Quotient = -5b37eb0c3e3f8f8d9ac6f4e4
+Remainder = -28fde388257b9a11441c592580cd38caf2d69e2ba57d43151c77d26535226e05e08a9e6d8ed470d4354e9f46b7626e5f2b22b652a2d78f817bb51598c727a765941fba63510b58fb3dd5f30717f237da43b42d20bc260b06d488c9c912bfcea1e7808544c58960a3e1355c50c889cefe75d4d9937
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 29232a3fb059242cae6e0b419ff13c479048cfe46a9063188706c6a3842674b16a1aeaf771c5b0ef401d2dc8a57f6fb4fe1b3c7bb545c18ae763e39421e6a07c4469d234f9fc737ac21ca67a5553c7ed693eede4325dbd132dbd9889d815c02f426801eff1f46e7a52f72845234acc6c153f34065
+
+Quotient = 1c7ac058af2e7bfbda9484
+Remainder = -54d7aa6dace87e61e24d87053b9d094bd160916b720d7cf4f740a4fc5a7f03909773d0456c530ea0204427146fd44d3ecec51d8627b5768de1494bf42081a8a4fa97163b0b93b59e70e533f3257723e441cafa4aab471ec4086601021c4462e1f74bebf298ef45fec98fa8e6ea97415f84c93c12633
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -83c2cdca7577b32c20e9e20fb498a2bceb7174ea9aca09d4dd2fc7a1d3b922797b4e9640c7eb9dbdb4d93c7fb9daadd680c1c7645d8102d77e9c877a9f65b13239f9a650dceefc1fd41ea9bd2b38a622bbec99cfddbc6e88f377cd51cc29fd17a27f3d0d970403a2aeeac6ff9fd69c3bbc5c2b0fe7e
+
+Quotient = 472df5f4393f33cc382
+Remainder = 16579a289cc776a47611353e158c43dadf0a78833396f8419fcbbe47d90c7e840e2c90e73e563e6c505bfcf691120ab0f1e9ef9c31db608cade70eb8e487b1113a46e2b5c7f4a172ad99b502eacdc0f91c295fe608389e61d030607a94d09d349fe1a0cc46d1e07c8db533cedebcb4a3b89afd8b924993
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 34b7f6780620246f5a0a92a768072185f02e57a52db1d865c21c952f4386ddb7e2dc1df076316cb4f2f394397cbcde1af0197fcf33e6428e6f5d42a9ccf623f75fae5940873097d4591d9b1a4cbd00074d134272700ab06d901742da695c3ca9d4f917a808113336f883e769fa8051cdcb0cad7cabd1cc
+
+Quotient = -12b4e74d76bd306d9
+Remainder = 8768fbe8ddbf60b548938d8b4a74c4a326ef335257e5f513e65a7d2cfbe9d456425ceb719407bde3cbc74c9c978970597b5663a0ec61962e77eb351adaee2d2d37f1fb55b5d2ceccf282ea3a0d398be1dd1b166d55dce04a39ef434fa392893618003adcfa61401276ce4e599051ad93152e3477ff524f0c
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -c898a753745f0fc178227a7004d917557cf3dcae2e85e95aee51e137b29c895755853ce2d61f214b80070174cad8ebc2795a7d070790acd335b383f9dc88c01227eeab85f1f29d76c1136ffcc7b9fdc073a3a03d8812c7c561b32d8e69754fff64acfd64994b7e9574d2a7cae6bfd5a6fd61dee7ee993bb7
+
+Quotient = -548c97fd02eca7
+Remainder = -939e90e281f97a433eb1c6510668d0fc448f03d737d92693b6362c692167add7e4442105d60ff3db29c03ed06c3121aa4a53c4625906519a4092e4821c918d2264ed0cf088b7da43a222877f3ad9a9fe8ec06fc66b9cfbb44e0fdca1dbe4e461dda9b85231b5b9733e0c78852da83bae557755de3680ab61d4
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 2c61dce04200e725ab0ecc5016f66044218391bdf650bc0bd31f3749ac06c24707e79526ee459ccfd4bc22834f8d23f391f2e99135f92b5abd0b04079ab75a263c0e98e46edfb440cd865269ed7872e8c1ada312df1bfd6a5fcd2ebf548d7b7d1d75bc36f62e5e9d15262bb8652a8041e5c8f4d673eecb777d1
+
+Quotient = 14622572f311
+Remainder = -6d197a84d2ed486327790059adb5c073218c56345f48c15caf6892734fff0aa7af4782738bebf24d984bc8adb3056f67e57f9960001a67fa462afd8c57ac9d60ae6517d58ffb4773b637ebe6bf2473a5490511fcdc576a4c40ed03b3afcb2fd27c57b66a26f6d3f9b2bb101502b1117ba3ce7214c9db6302fe20b
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -b818674faf69bc92085b7230d9335d7bead0413f2905539a54e8d1233843ef13f07cb5538e0787097cb24f152cf54a92e62ef143e31cfbbaf3c09650b14229a4f61a783eead26430949c88a87f1618788abab9728aa52dd8419f5d568e6a109f278b2afdea91cdedca43e562d4bb8fb7f1b7aef13992fa7edc320
+
+Quotient = 5cdbb03ee
+Remainder = 1cfa68d5da7a600a7ac598b9ca1a0759f972fd9a46ba62e5e96d8f6f00fbccd0ab26ca03d14470b43793411ea9803c9409908625fd74ef8f9b2d7c2064b2e3439adcb684e6f01432a1feb0f492fcdd2b8b5a6cdbd0bf460272218bcf763974be8784e5306c219ee535baf5541b8580952e3690b585fd99f77c46d69f
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 2869338cd16322409d3efbd328b27e2ba53cbf71816ff5c093849b1d866b8cdecbd6bd8ffea0b7787251acb760f85c277ded21e56acef05d29bc728cf44f55be87cb4c8913408a01a1ad53461058a1cf94538f05ec14a6d3eba804264df957de7eb1a61b794a1141218966463dd42402c260c229241ec46afdb5a06a
+
+Quotient = -f16da1
+Remainder = d8b66b622b5a54963c2c84aa186bfde5b67a3562e07a23a5f6843bdb615a3c5d4f007ad8b275ad7e4c5b1436252efe35699cff2e0546e6dd8c7230d6ad560c51cd54db6d312be32ae4c708e9047c3a25c211e2566c58d6b9291de31612006d4e847c6916702be99b3f7ce40e1ac842908acb7f03dc120aa8998c60737
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -f8af8fb7002a9d2218dcd0f0c139b8e3dbbd48e25a5c910f6d0b6684bca224f62768b64955580306bac6bfd45b99ad77483563fc7dbe015edc06bee3ff93b0afa8f5866c23c7a7570b366550490c97ad84062c2495cff30717aaa965a8e15e270b504dbd4fa943be4f97a7fd1f3b589bc9fcf4f907a7690d99c978a374
+
+Quotient = -71bc
+Remainder = -13316e9b053a06520526f579718c326402d2a9686d51a340375cb53d7cebba99c8d1ae93388db0a41cf55d5753dd1174014ff3305fcdbd5b02de9e90c45ec0d2900ebf6ef847c2a045eab7f80f07f01c81b9fff093a779a280ae42239df79de8d2ec4bff6723788c86786fe276ae6a4dc1472442b552258e1e5b597305187
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 20fe256859a2e4c4f77db6adef78b2aa4758b29ad0787ce7e277bc68391d5949bb4dd07a9b1a79fe890c8a760871d81adfd3858e27d1bd6de33fd31b8aa6131fef9130a50f995c3be1d615d1bfb9878804b7f6494237d8ad78ac219488f17335ae54b494532f03a3fc8e9576cab6facd90c662658878fec86db66bacda3a7
+
+Quotient = 10
+Remainder = -23e09736f469c83f280052ff01071b1bdb52b7e2b061e8a1a8c6a4e091fcd7ca0b33ade885d928a11a3375599aedfe554d1c2289795daba08f07327a19a8adfc219592bcdf9fc5aee5961a48b3b1b5fc380eff5ed2ba7d7e564462397fb6c6187254ee41c74602b141d7adba99205d2e0b35da57efa96397b3a5d112751cf7b
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -e849bc0bfd9560cb90e42c8e4e88df175133c14466e530716d89ad0326b660b0e617b4efe8df6b000f517d3cc24d9dd4cafa2773dafd4c6bace0aba54e43c17e8e3ff9497a97ed83e6408aa0aee0e6485dd1d89d52520d1acf4d587422b0c5cd2d5e7e81fdcf842d6331779e800f96628206e8be020ad4021789008a641f67b
+
+Quotient = 0
+Remainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 22004040a65f9b6f120bb7243c638cf3a4cf6fc58c230da932c79568f68e31af7a7b8569aae77af671f8335ae68d6dc1698baa9d6ba9cd633a662101b45bde51d55098b50fabde8546f317ecc2ae7a39521bc075942e3751a349f51ca3c371f3b8a6cbbea3e11a334d677c07612bcdca767194c07fca78ea8a06cc3b0dc6dcb8ba
+
+Quotient = 0
+Remainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -cad46f410062dc33ad4d712c3b743ae2b7613576b2bd7c346a8479ed679a08e3644c7ee4f23b95f1cc9111905714b170abc37ee1003956f64f0a7e876b38d524fbb2436ed56069479d8d2e4029770f7801a7278fff99b3dc76280f35c7d43ee594073f725554a92eaf4f785c18a7cf6669dce5adb0995233241f3294cfb5bd8f4741
+
+Quotient = 0
+Remainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 2fef69f9745646aa13e0c38d77951161a1f881a7ceef032698da3fce00764959f11140bec7d7f53d6777c3622453d4525fb068da48047609d18d463a8fbacde1d21035963b668ca11d5b9ae66db13de7a7a5b66a40608dfb56d9f9f0c8880426641083a05b5ff9e6ba0d6da3a04af1af01dc218e9b4f6ad7b1d3a4d1d26a5c906093b2c
+
+Quotient = 0
+Remainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -c50a24e5ddafb768f64677233c5cf09da1b4f06894bd68e194b23feb5c5d6844320a12a02d13ad012f13b1438eedd6313bac9c1f9bb4548fcd314988d8fe0ce6458306735307afe08a96a0c2bcd9cf126f529e48b7ff4b8266caa28c40b5c3d2a473ab8805c860d27d7ee9c032423148d96fad019490ea019d40679de7a2a3323e80979f9
+
+Quotient = 0
+Remainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 3a8682d0e5a4efa985dfa8bbddc2c0d72a4400b8b070a8cf7450aa8f831d8a91c9ae3542641b7a4ad793e232a0d301b82664fe2c7f20bd9bf8275828a2a20027d6056b211638b9b0220fa4252d058bb485dd3c4622b1eac97d54b9634b558ff1bd5bd11085d4f3d288f7965af52beaa922b23ac0207d5763c24c085076128e0ef7370eeaa19d
+
+Quotient = 0
+Remainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -f00fb238bc9383079c7ecad9b9f6efc622d58a76f2d5d40ec7cd7c3c083c459fbcf3d128df4d20ead5f585505515aab11c36584ca622d28e0cf037419a649d598346063a07e29c61b7a8e76d1949dbce3720d45576763aa0d391b39dd6b694c7cc60a1b4f4f107d87130402985695e1847e82cce39b8d0fb5c88bcf3b37d6dbb90baf5a8553c3a
+
+Quotient = 0
+Remainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 2b809f6baacecf61198856d9edbb768ca2df2abe9b7b8ce1669fd9259732c8569c0cafde2e32d253094480ed281a8db230f84e780c6e8bbf3657c0b0baaf19ea973fd8daa2870c9d79f3695d78e063f9130fe07ce806a088ca267fd2820f10dac34b5b32aebec20e4362dce26eee0c29d2fedc1e020d452bc2499234d07a2a6e54314e3fd6dd85fe5
+
+Quotient = 0
+Remainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -90ed75629073df816ec1d6dfedd1cdbed9239661e362db706288dc4d774d806bfacfd4b32c3013ec67d8c2af133b46989f12f809fe202d33d5ba53659bd2a9a85d3fa542de4a5c656aacbbf8899aa66ba816b809f2629f37b0444cd3a6dfc99103bcf2a5ee87790b8401be806b5d7fb7064ff0a6fc8ec769d0ccbddbc3d35f7dc4d388d8d28021c95b6
+
+Quotient = 0
+Remainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 3f60052c9dfe0bac797a674ca7f11377a24c28a1396ffa0f46acab7909543086aee1995cf51852ea4a21ff4bbf6e7309cba9848a7b2e3b33dbe660bdc58d513d16bc709f1f2253648b46daa7aa037332552db1da81b4ab9850ac4ec66621648fc856a71eee3cedc6617071600ecbc5ac8636233f288ec249b7ae0bac942a5fd539d03990c4fb28a46653aa
+
+Quotient = 0
+Remainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -c12fc156d9345cdfcff94bdd324429530ad8caf8afaaa1a82297eb3a8aecf2ac021384036749e489fae05e8776da0deca7e4325436bc8f383bed579c2d67a456c4e23871489780d760d63d0bc0d1d0ab41f06a091b44f602bcdc0bd4e817202e39ca6a934c0c9405adb5a14d24da895c58a81d1c7ce52734183e00d80a414ddd8869998822364e029b3f42cc
+
+Quotient = 0
+Remainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 205dc6227dbd3adf8ee49dffd43f835882822b1c94f92cf38f5efc62f943075d80b33588973a0e0a8ff5e800ede21d394736ba98d4eedc53a9122f8c262cd09fe9e91cedfd0237003b0124d757797ee13cd03e7a3a257bd8df756940a4d22face9287edca00ca23e7d5e629966ef710b07e54241dbace041aa6d9f82687c3ecba818203adb376ec0b201894a500
+
+Quotient = 0
+Remainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -82c30a9ef6a83d81b77825c71ddc563939b8508f1b7e44c725ae0f61006646ba9b86507ec9a4dfd3755ecd8bfb451c2d43a61599732b8aaeedff7a304ce0a9327e2333f75e9a010556ecbc3abaed02214f25e1c8373bfafc2c288ea36b8d5f848b76295a141d8f633609a6656c07f3d98177f5fa83833476dcd111aad179001f81d6013ca3a54cddcd8dc0ce7eb24
+
+Quotient = 0
+Remainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 33aeafda3cfc20710f0b4a3d9ace4817eed80ca57ce6c82dc2e7946058a40983c9204ac95a1399fa633bc96cb10af3ddeee3ad2337c64391a42dc7794fca629e3e1e4e03a2ae24a000e7113b91c1b6230cce9592e45b6ee7984680b45aa0aabd7f56cab1a64ec310cefe5211821a75deef2e0c8e43eb467dea79dc8c03d2d523734498d079d5493c904a2ebfd8a3a9bd
+
+Quotient = 0
+Remainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -b897bc87a40211ef8f93645b1f6c981fa00ab3b12e117a89375400ab5f4c64bfbba01d265c7bc6f5e3a8e26de5de9df3b8f70f4a39c0eba577db5e4b7a68f751b4a69ff4a38915983cbf70dd7e066779405d572f5bbe0719c978b6865ea1a72d90d3ec8a8c146f20d98595036b3de88a7500d7b476644913e4b63e85c4e2632048e9600d553e560759770a902cca680b17
+
+Quotient = 0
+Remainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 20604e080549e1c503049ebf4a56cf9447d90fe699a9773915b0a65588890e15bd58f55ad7b52bd7b7992a8b24704f1dfd5fd07c70aae4ccba5646405ff8a9cbf542dc334cc0c27a790c05420b552539fbf0a155861bec0e4d9e3fbf045720ea3aed58307d5738b64252a963f3fd5ecd0587cb4d7e159b4980dcb112e26c9c34f10a192e090ade157eac1d7a6f970871eaa69
+
+Quotient = 0
+Remainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -f11fc9682601cab97c25533b2599f50edb1ac65d46f1969bd9c3cb3717461627621c8cd401a0a0b91f3645b8804e095aecab31c1bab0c26df556adafdd7e7f4f0510e0bceefa3619e26b8c9a1bc613db03857f53e9eb5d4b8f75a8cd1429feb81edc705e5a779d5f95373d2243368ce17ef22da79a6a2672496bdf629171b7973fc4659c8eae9ae867cf38d6d7617029bf59d2e
+
+Quotient = 0
+Remainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 3cb0ffbd9ad21d0e86e4e4dab4d237e2a17d97356bdd305fda772fdd99acefcfb8309d813643c852f66e1c6c7fa41ffd44f8335ef7333b2b3e846139fa9be2c4ea762afba4e11263c0b5fab18c5efff2a18d83ee89844f5f4db2c1325f0f55e066a9e01030c07a85e2c9bbd37b5e767ebcc9b95f474ecff24df9ae52a19edeb66546a3a28980f616eb5a351cd399e5f8436f17faf6
+
+Quotient = 0
+Remainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -b8aaffe779855c6ae51807f8cba780aa64bc22e8fa5e33f7f1dcb084fc476791565bc33eb37b4f791ef5cf46d64576f48b5fadc9f096f20c798355861ce5d24a7be1450bb871f9821099f98213d74a5e5cf83b895ae65e0e0fd096698463906a112e6e169a1cc0769df7a5ba6812300fdd33611761b6339385e1a70f8f8b2be7679ca216f5b183140e69586a27aaa9f2fac118118875
+
+Quotient = 0
+Remainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 2b7ee3ee34347dd89ba4a81415aa1269d0390346597b07444f0febb71d490a01b6fee174634bd88e8aa180409549b2726d044b4690353de2fb2294c8f69c612485aa066f68fdb89466760a85901cbc7312bfe5a6f656e67dfd2d4ee099ff97694b01d6d5b8626ab1650eac5267be53f5f3ced5dda1aa86bf42ae132a28fddb94902a515da40e0fd0586dc8b17a34af8eb03d06f70ab89df
+
+Quotient = 0
+Remainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -bf8213944ba785e01b8d37a12de77b2ce1492f34bf6f67406cb51da89675b4f70f4d4f314f30ca8d65cbc48ee2fa1f0a3e4ac0de3a87d2c4c589b6812e850623d78ef2e46fbb555f6d3c69b211892c11a4a2dc3d8a9a19e96a07952602ed5ffc0232c140c3e828acf990e5425d8dd9ce0c1107ad1c6f96c8fbc90ffa457abab0d843094dca3c8a45ddad81b7850190625613a4851485f38fd
+
+Quotient = 0
+Remainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 3083421e375f0722b9397e156de47f77635d62ba1d51794469371b473b71c02e3722841bca2ca06b5d1cf1492bbacfa0abfe394dfdaa7bb8787550ddbd953540e9c97631d9a1efe0c8f8e14f395c82d20245cec6d8021f8564b4d66e7779c3245734c56fb74481172f4e349d9a113cd0ee5263c69ebf746c5285cd4c0fa91d9531f769fea3610c2972ccfe9a22c00aa62ebf52b3a4c6135f3069
+
+Quotient = 0
+Remainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -d736bce537f47ae4797faad797af8cfeaf8a4fd42df1f7e61febf8ebf6e47dabc48252ff7948f3dbf8cc369b6952dc58f64cf09b4c53447d135c7a753c21b6052a9726a47a61e13628edf0f2bdb357f2e780ac1ae1f28f211296c8961c2955b773d7dc2904dfea96780b2877af133c9591a0dd54cb20884f014f363862478ee7ec45236bfdcf0321af0692e68f744af28fbcca827ebdc7b210da38
+
+Quotient = 0
+Remainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 2cf1708f1e675ba688c0d19eb61a05d2c8642528ea6b1512375faa732acc59ec04ea0aa55e0049144be09eae1292b6cba6db7a9823f1e912df6a5032bb9674f4f26c0c8244ea0dde7acfda566574956cdc33e4a27bcdea25fe255c19f218cc4316ae8428ea61d1bf865197a066b959c5fcbd7c9596207997d05fc38e32322aa189ea06cf5139522571661745c0d72b740dc6d842f1dd8481e318b5792
+
+Quotient = 0
+Remainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -a9180e44a284b5bbe72fff46e55869f749b626ac33c8cb17be1fc260d7c6f460f24a89e1367112e00d0da4d213a821d09f103f35bc4eade5605bef23c5d048b1cfb45dace8b9c637af626a85fc773cf51e6602a7a5999a030030cf114ed6a4ed7583465b9303a72e7f60824c12329517c6763b0f64abd8ba2b9b26cebe882a51f05ef8076e527d53a213db910a5f42be5fb78729a3dcd08d69a709920a2
+
+Quotient = 0
+Remainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 2f26e156b3b1117f7cec542b20fcc06ca66cec03a19b6f5eeebf22b4c0fc265df5ff06fc9dcac569735135bdc142b526b295225711efb71577b10aacda2fa446f5208487c725407c2188b3185237740c813e4455a6f1dde4f62916237f23164a3471aac0fcfe24ad1ce1dd81a6144f5861ad0cf22dc337abe10fc4a88b36116dc4929602ab48eb971fdd7a5ff747d6b9e0b2bff75c59621550991966a0a19f
+
+Quotient = 0
+Remainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -9fe18ae697576dd36ebdb621d14cac1cfdfd1f5cbb7cfa8962c5a7dace96f9f54fb4f4cf2e650dbec5d1ba89ba53d251ecef7dcc1cab8c2ff3d77903f5fb5f29a4e8e3a2a3c05c105d5733b5132f2f8d88f99d17de86ca1191c32ad8ed469bb649ef188306f69f183bd0fcc32759e4f855170f88c0a3f6745aa98f6225536821bfa056a42b37535a622f42b009859c974cabf2e14f75c749d0fe5a01fb3ab0c0
+
+Quotient = 0
+Remainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 33ab185854b20a8126884eed85181b14e75d4ee452958cc1043b099bc16c24b9c2f3e0b792744f230013907844496e600389800e45fd55133fff0cf19c9c152b9d031039eb90da568f9c5212a3ba283f4d1353ff8ff9dd04d292c265bdcb77c3e411716f471930bccbb8ddb819ebb0e0036dc1a18457cd97f4f5909a725baabbd15e8ce33875895aa8dce77a4dbedeb0271a2a4a17f77f5920c3776caa4a75ac650
+
+Quotient = 0
+Remainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -e7ca0c037bf8bad5f8d9c5a2737e044d9f7284c616156d142612a53eb217f57f4aa00b6daa424e6c0d9163939e1ad0510a1cd64fbd576f3e54c59d7aa6228fb3caaba7cdcc951e00ed141ac3a68abb9780bf46bf544fe0e347f677288e962fb69782741df49b27cbbe8720c6f8f2e769147d89df6e17e3c592bede2e696d384b9f01b99b31c505d67eb6193a8844f8c4cdadc9fe45dd446a0dc572c9da6e58ed303f2
+
+Quotient = 0
+Remainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 22b76d6973e37aff4a09216e57662f186c0a0748c4375d6bed370ea61d1f6fac2d9bbe04487a629118b6b0b0c8cc4179fff7bedcf048cc529498bbd9cc81ef3a103d6cac49d58bc41c83f961b6df7f00c7171fb7d9359e03c76e4364cffae5f67321ce646e9b05f9c04aa16ea65389e940022eda6dc740ddc070bfc7e589b86fd1559dc320701c39de20d54d0483fdeef6c4fd012850630b982c2e243ac1ff918377ceb4
+
+Quotient = 0
+Remainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -e6e4d69a82b83e26ef8ac0f4c3a211153ea6655b7ca12840e7b866510d114693049c5b8b22c3a097eac832bbd1986e60564298e54dba3316807ad64bd6c18903a0f22660c9e8d5dac180f57cbb90b176b842d5b58d6dd9f47499a037833a92a18f397238a8bcdc4afd129382fd6d200d3d267ca1e6bcc2cc65950831cb8e30bcc01665c8149b874c9f11168153c187341afdc43e4d8652ce4fbed9f9eac75db40d64344ade
+
+Quotient = 0
+Remainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 319a81f052db21ee213c536db2cb8a71e0dcd0a9b2ce780a9588c38b717c5e487a337f82b5223f638fb552e92b826192e6a1c27771d1e86584bc6c7cbc5d9a6ce6edf2ea2ccf6939485959ccbf3183b40e410768c4665adf90a0ae2792fb4b5d8aaa06c6294e31893620decc3bc72fb4eb68f1e56b48e39c59abe869d07509b7564268d0b7f178ef09ef5dcde6e7dbd2a20fd1d4fcd707943dd63adf590a117ead1ad10ff85cb
+
+Quotient = 0
+Remainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -eced809145e696ceaa0ee8f831eca67049509b31a1b15e7fc86cdd97a73a2ca05bfea5f4b283d287e49906463ef36f2f8ea23c2aa12d5534c08e9769055e04822be0f8ac85f404f5c025a6833b4115f78da9470451c852ba0f24062397d20385f58c5aca10f3f09072b2592e5672ffb989a390abf86cbce74268aef1f4ffde730b3b962df1088bf8745105a7462379ce142f819c2538d9bba99e094ffbc4478625bc54df16c5e1a
+
+Quotient = 0
+Remainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 2c1ffbbb30e71d5fa77b5473392f95297b489c85f83013262abbe948842473154e00c86b2e354278844083f960fd746a3b7cb9baecb9c66932774b3a28f678d50dd8fe52fbeead43d8c8adad7c0fcdbe5e02664b0feb0ce214c5fa007c5fa2d08c5fe96787b95639311cc4b7eb2a7217c9c38c6d93444fa60c1f52ddae9bb2ec1a49a593e210e47377d3623cd2c4994ad9343863443911062e12233176f4a65ec715b3c9731c4a0cec
+
+Quotient = 0
+Remainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -c3bf056b905c0392a7b5fa57446ed350f325eb67d59f1784c744b04c7f4d8f5397db913407aa8a7f1dd0225c1a9673828db0d8bf3d4908ef53307131bf5b5c4c6068ad73b874aab98e8db33b0a758532172acd8b2c830d0679a8226537090166317b8eea91e8ee4a7282c0ab0ab6f2b7b63d728d22b534fdc88294c376a8d036ba9a644c2489bcc84f6aec83afbac08067a7b93f3897f8dadfb68c327b751841927a728faba47dc44ec4
+
+Quotient = 0
+Remainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 23fcf9510caa531a304eee8d0b2d49050fca83abbf287b6b6dea06501c5afc6d87d2924df1d45b1bf6c4bf77b563a3013cfb4ad9094f8ee9892d33f6ee1c70131cd5721c5af804a9da7654510e8591aa185ee723f8caa78046d9e6fbb891e6024d2ec70110ae61c3969995e35941d2c7f3779d5bb71ce5b693bc9ce4b087068adbb554acc4ab23624e060f7cea169ab512a06ff3d2a36c2b6e3bd9a75f1a9ad30a6a16b0256c42eaff2c3f4
+
+Quotient = 0
+Remainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -c32d5e643b12db6616554116299c1da672efff1eee394378c5e9e5f702ea4ad64f0dac8904bd2751d2cef91adcb283599f6c661967dbab27059e94dd50025489cf74c6897a22e95013669aa3063fcdd4b73aa6a9a1ba5cad3956bb26346e22df6741cd0ba1c0ab87fbe74035618a394383823216df47b910cae495b8fe7ac5feb3b2cf0d0ef6c75db477160b75324db8eeac48a0fce72b9abbd7079ce6f529a89025a03a3777cc7d1deaf3e4a
+
+Quotient = 0
+Remainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 2a8f2c530342bb6ce683a760540e956a1155c0fe065476e400caec59861ca97ca71e51a11b3213b2baea1a41a29449998778e0f533fcc181698d293f05e28bff2750ef4095170de98a19a36ddcf59a65f3789a3808ead51680245070262c9544e446f23652eba47065a2bc4701c55378bd49733619ed2c213f8ed12a4a317c465f37efe07ff2df8e88fc33d3eb42cde9408dda28215702bfa607030839285a8bbf89b5e8842fa7d7f50d83fd4ab5
+
+Quotient = 0
+Remainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -bcd2b2362aa146cd120b729e81c98ae598804006d046a7ed0f9782baa10a85e37c7c22288dc61c24830a1b42b123d63779e88d7555028292fed5ada1793264b35e961b608bdd7398e421c5474c33a65059ef13787e0cedf4f8f032beac48c4b5e5a67417109142a43b198ab617d1de1a38d6fb4922c6ef70a5aad3faf6f8d5da3af9679c94cf61ee760ba792d2972376425e2ec9c4109e969e3d9c3dd90cdbaeaeb7382cb7bd024b75a1fd6d621c13
+
+Quotient = 0
+Remainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 3940430ace4b5b87bf4baa2673582db3d27307ca4cd8e55e976ea3e10da72b6deb7de932253bc9228c85cd4ae7766cd0264004c658a66d81e60bb9bf4dd66e2afe11057b7f7b53a1ec222510748be53a93970fb056e8082631b2b77413fccb6e61cdc6f224b7903d75345afed8a4f194b4bcedfee1f16dc256c2bb9f4a129fab6a9fe752895a93937a3d087ab7ca212991ff34f1bf1c55987a574674af43986312bbc3bad3280bbddf4ab0217440f851b
+
+Quotient = 0
+Remainder = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = -ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -f0dc20b88450f45381791e85d080e4f2cf38837391e16e608b8cb5e0ac0ca75e9f72cc04bf2f56f130d46aff31efbabc0ab14f0c0ad680d6899797297152be85ac012644c8d0927b5b6c70dc3e5a8d79ef92a0873ec22af3d9683bb5db1ffd5ebfb698c5ea64cbe2b6a8b9f14d4c18624be1b78b19eca14942ae9542012692cd0d5289ebf75fcf5486596f92659143e9f952af3622137e633376fb95e628055e0fb1ba3a37ccdf0af69a4c0d6b0793078e0
+
+Quotient = 0
+Remainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = 2f2135850715f623909e41a745eaf7b37593567fa8be2d1ccf76d10b93a096e244b91d8700cca37a2ec1bff7c3d21cc3211ea8b03a3594921dec32faa185e7f3d9d17e98cbf8d881fd2abb944181659242ede21df7e5e8784f541cad678df1ef6ca4a5fa91f7856c62fe593c4d24436810cf4fbd11125bcb571f6975d82afeb81bd0c7700e053fc175fb5fc7b329c438479a863b8d5fbe6b4436b67355c51d0306e8847a27a30c9e61f0e08232673cdf0ba4e0
+
+Quotient = 0
+Remainder = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+A = ea87c57f6cdbfd4f836431be3e9950c90ee8ecc291eb4efb881617512fd62e2d86caefce713cfd8a20f4b4925bfc7dba1fcbe99c72932725b5d11eccefde4c5e505952754891e9ded499ec453a1c01a82152c8933f7db4f2b4b19e97baac322eb483cd661a43e458774ef27a29a19c3562ba466381056a3b92c35d9b8b71372b
+B = -cf429f101a2e19a65af1e238f6745215cf476ff2609c846f10289f1ef21b89af2aec53def3f4ec07ea42041f8b5862dc37fd03b2df12adaa8c9f1933cc69b526d47797b40f49545fd093b8ceddee3c55721d1fa19b336218de0cac56d410cc6cff4e620578cf820f5cdaadc367dc4d6372aab1e0ae3831a6d153c14920b1dcf09e7629b7442a06385420d79742e409677e3b82ec58bcbfa668ca072e981e20728a983d84a432605389c855a6668e0ee0d2b67449
+
+
+# ModMul tests.
+#
+# These test vectors satisfy A * B = ModMul (mod M) and 0 <= ModMul < M.
+
+ModMul = ae2ca2ce7addaee2e2b7752e286b2bb6a58b51cfbed5c924f00398e59ec36fe6341cd83da43a33a12410f45f6228079c4aeb3912be87e2e81fa1799151bfa0fea29873097475b2c3efa312145d0bf7e51b2a7c9bc961a4f4dcf0c883ff90b919b87c21099fba40257645be31f95a3a277
+A = 6b18497fed9befdf22a01d988d34213f6687d8a96e86c188dea4172e7c6095a0d18d3c86c0f5a1af9c6e3aaeb6baac2a510930b3ed06ec78ec2e12b
+B = 1a058d99397db0d209f01212dd4023ae01b15da04fe62d1f76f21622b2695558c67d706c535ca7f19b36f8ef2d508ffd6cf6fcf25e5
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = c462c7cdd79b7604246a0cd97b40ea5a9a77408f13cbb548b56ee713c690dac0507fd988bf28e77462832f4307b08564a51510d4a951c1ad7564316dbead2b53540090827a8ade8092a6133af0e5fac7310f787dc1472836178ed6992b9f71224da3e884bef8e8379a58e6d4be0fbaf59bc520f786631857213305e23fd5ca65
+A = 16c92f77c139706430f396f72ec7adb045745cd9f5899b0074d9955bd32de66f57c05c7929b575312a7f1c04f19e724d64744bff7b31ad0e6171437763
+B = -8734c4a2361fc530f60b28a5f1c7e93136c5ff6bfc7553965eaca54c61e6befb3c0f8cef4280e780cc5940d21a740debba31f863ded75
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = c462c7cdd79b76042469eb41a7a83115eb84103da4ba438c3e33227631dc185054ba4e607141d1e60990d8aad4e0bb0ceb645ce9ccdfe72d4738cbe1f6a73ed3e070194fa4feca6001c4a853940a227d15c1f1cc153d8c96e90e24805929fb11e0665e0c41c77d5a97fc5903a8b215360e26f6a19922d650f460f7056274ee92
+A = -6715098ab2ba3ea1e6341e89936e3ae913cdd450dc831c8534071f3c362841e47d88f2cd29c0d1239aa0949f3685f12f8519625bbf10b2c7a515e6d00942
+B = 536d4b3e4815ae5ed55bae6950f5a8a61d52439d2800ef1b5ba2285b85ed0f6ec4af9fa0e364a6b14f6f6b8bebce9200467804e787f9f3e9
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 309b3e30f74c58beca8b2c23f64fe1203830db8a7e306e1fa2e2022f0d6d422851da509d1b2936f088f0e35effe12a7463f47ca369bee2f2980bc48dd8e696b2d8c6f35cf55fb8baafc2e613b4c684de26129cf196741aab873f81e498b1e03018a539b5eadffeb5953029f31f8579df7ec0ff3f752491910
+A = -11fec955948e007b59fc50e729941ee9d43d552b9411510b73f6b4faafc0465f261f8381d96f647267f72175883172918b5c866cf1f1ffc43c55f3c96a60c01
+B = -2b3792f39499767e0a8b7a6a406e470a78f97ebb36765beab5fe52e95abf7582736db72a2ebfdb2405e3954c968b350a459ff84ef815dbc5910
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 9143ec3e9f74a8eec476cab17ad8636eaa7c60e108e89ae0702dbdb2b255a217ba2530c6fd52658cd931b962054a9c20c8713976ef3b7989c40611cd25b0a9ad0635d61f6dc95dba6e0c4a7d53ff539b623b97ba3d66344fa324f905abb861c6b1e830c4b0fd5f6a4b01f09c8e1408941291b2285c4625267a108c
+A = 7713413d87f1e50840255927ff27bad79e5de5898725a876e4647913158cda9f5fa031dd7fc11d2e8130a0ba99e8706341c1a98d5fee3218763ceb1d131e9cdcc
+B = 1384e60753dd4bc20cdabf398525e7c4aa40065255c5058cae0b2ec90a3821bea8de672a712431aef5864eab719ba621cbbd8b46fe86fb31286091
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = c462b3b4a0432890d141c0f46a28190a2e30ebb2e4ba90ed132169cd72316b290dbf5c261984d98e63eea6525fa890bf52185ad7f164cf49f67ca91c2f35511f3bef6eb7f3da31a602a78e4752e326d79dea729f4ca6438f2aa65eff44bc60979b42e44f6a301cb5de8fb42abb47bce5633c6ae9479d39c9e8b507d96161e0fc
+A = 17d806d7c76aa8acb051fd9c0c782443f1b1b6387455f7cfb737c41658d0459bda5d13587055eafb87ad8d209bccac1fdc392aeca0774ea48799511c1fb9141cad2f
+B = -d7c9b6574354e131de4b8643d766641e98554a03238ebfce1112c3da5f049d6c410a7f05758571aa2625f7190b936a214797570539317b32fb94cfd8
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 16c84ed15ec6352a8ce6d5c2bdc0d9f13b333072fc7041146e944a29391f83e346b8ac0bee6dde98a420ba4f8852801d7c5bea6f1177a6cbf799edf2146f8297013e0e796917cc967786788ff12d9c1d07d9ce4b897bd22a1b8a391d3b4ecaa5b5c85d0a03aea5145db6350c42a964a41ee5f83e7d35e14cf442e5d99ccd0ac8
+A = -6d84cdf18a2f53fe496248fafef183914d55c42267af3dd42a39515e80cf29211fd58454986f5fb6afb56170dd9865d3158249090270bb9af341c830522a4dcabfd494
+B = 6f6f3f74187b7d74dee92f79be864d0a2c56d4bca3283742e9cdf15112c8f4208e3ac8ecc98b44b4ad74b0671afa4aa9e48dc31d34224a1f66bb2b4658a
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 8fb782e4883ccf3aaa2d3e020b08993d580c69ec8fe66ecac152c5babc8aeffafe406736cea492450fe6adc25dfa2e12723a3f9baeb02fc0f785b3db760ed28048e1710a78a2ae0c96b67c109c5034375a512b6fc7906847253f66316baa0ef90facc9ab992235153684d49d6939ab9e91086529494d7386f604ed69aca2f53
+A = -1f745c8f0c8fe6ce3f893d77fb274c61b72b2d9f9c5a2eb2467bc00d1f496d0ad469d76bce318bd64ff1107ee5fcad4469f84d658586a5789c068b0cb9b866d8fdcbcac5f
+B = -3a2347b491813252e8ebef1bd181534b074a368d076b8c80bde2e54ec3b4ec99001f43080c7857427e069d99b1b65cff998a141ca6963aa5fad1ee632986ad
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 7c0c1c05ae1d6420bd93596a01aa0153000ecce660a8a14d6fde7d4740719cc495fe6681a9a08163b2dfd51659b3ae7db0fbe09504370bfc695457d7b32665a4df53e879ac817bf715d5bd6ca0e242b1ebacb1ffd6698ec90c442910a92b35ec103b345f9a9e5c7b005f8028da4dde80f36f6f6e5675040d19e46aef06040eb3
+A = 4c09264420a9452c6f0b55baee42c076aae5a73697cc6bbb88b7c922f236ee4c18e477f88e2c40cee03f0bbe87d3ac8dffd75f635315f856a3881c6373e8b9a286c813325d3
+B = 10474ece7ddae5c53c4df5b594439124370932dd94aa5d5b4ddaa233b1a55634fb7d72e33bf1b02965fa9d1538f97e1cdb5ec0477cec8ebaf202aff8533211169
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 481543f1556df756ae2e422ffe35aae020c9bde9e9b1f760b43043a4654de363dc67f381c0df1c3c1b90edb4343c47ffb8345a1aaf5dae56f446fee08a0b9ee8c42fff57143e10846610a9925be96418c4c957b4e92af734b96fd6f21974877dba52a0db1fec4aa97640e357434f95ba74b6b8323cbe17118dc489552844602c
+A = 11bccd165d9fa2d8b01a48c0ec549a6e600396cd2023f0240056193ad27e971c604eda8aaed6ff6be8be1001f3dbdc8655f1ae84eceb963938ae7bf428eb5c968f584798c1bd8b
+B = -cfb6629ddfc98a242e3290959f4d0726c0b1770b52393bc7488a471a90f7f0951362c03e67f443c9ecf4987f5303a789bf65e0fd59cc5eeb9f5d4f40d3e4a14080c
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 2a770ccfbcb2bad207d0e2dfaeed04b6e7509daef00a1df88e57509451739a8a0f15106ce8b53d280a4b4e09900420714cb6961ebb0e00e88567c5df50d2f2908b4bf8e0a9a5a8b3c6120503c14f16a99297459543c467dcb67915e0a10e19f72ed5b6891a6121b66abaa602818801d3306630bb04ea57e6b31b2c05e368d398
+A = -442c80289bfbf00db06eafbf06109b55f99786a323fc2c6db5686f99094cc24aef50475841243ec3ade2a1e0ff28b4032fd8afb8bb5e28f3b2863bdb9fc8f033adbaeb5f2ab16fe9
+B = 6d43e3c46f4a55d49e78f40d34033a7f5fcbe50873930e7c5452b6b3b176534e6e70033868c85b4d63052964093214dfd0bda6a84e893b1aae3cc72aa83d039e51c014
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = ba0e8c91a86af1001b13deb115c77609a1e7a3736a6b807255aee898e3100f469ef6222be532dedb1b8d3db4b3b55aa4b5da5629c83e9b2bde76bf2f2a4119a5378b5cde000980b3e58595d988ff776f0388fe025625ccf368e20914fa90dc771c826e4a836b2890e82ac2274471d586b4de5dab3278f0e70207562ac6e6493b
+A = -14be403d28c8451cac4dc83fbf895a9d2b74f730c39b0fcb33d7258f99211dde31a78f182ad1d27a559031d67d6f2f94a741f141bab80fc692afb452ee2d502099ebd5760ccec7f7ebf
+B = -2742dfd02134594edc6d3025aba5ca4a34dfeb43821ad84164510b43be4fb95748f8d0eed7bbcbeca14efe843fb676882784bb36c889be29bdad9270e0956286552119561
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 20c691d6544912fadfd9894cbfd42745991f39a29cbe3a1cdd302bd0487bf70c0179b9579b77f8481bee13ddbe42f32d734b6118af92884c946ea8576f6dec867c1c251c73777cad7c7c76e90da00ae07f96c8d6a751e5b18157dac4468c05d32eb86e74e0e8312bef85905af8193a3f5c799c5875badbc9eb7ead1258e56d7c
+A = 7ae9b4d5151b11bb7bd4d1569a6f4804f3b4d77948e0c6300e4f28d51c9a0afed2ae7503e53489edca5359e2b3d0c82a9cef316cd7e1c1275c31fc9c51a8c1e5fdf23935484e467d6460d
+B = 1f46f88d39fbedffa8501fa1268bdf3460aa98e12b629da59676e61852a4d3f8c59f72a2fd717fe2faa09639bc651ba516cd39297e0cac67444ec57c0db47c2a4e250033d02c
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = bf21b3cd55c0df8d4d568d00f757b10ef3de782ae71b289cb2b59d36df1341382bdc1825ba13199f2cf279a72968b3bbf5f7e3d13ea9adeb96d81132788231fd988eef04828119dcca21ec1fe844998909cc95a8d01720e883df27f07ef4dc3f09081015dbbdf019b96707c18b0b1db6e689e8f86466a2afea4a9cafc576e10c
+A = 1243b14aa3d16a55935f6f8ca49295e35e7f75b03de7192e1e8a479abc0a430e0d340acc05eb9a61a5dcbfe3ce3a4c5c940699f5043e924f282bd21e341edf8b7a6741c6ac72d7587a9e7a60
+B = -bcf08b2153e8ca911096189e35dbdb21b77ce89685484f574c89f1747612f39340bf1b204a23530abb36b2c5e195940b86ef1252d6729393c25d4c73dd434b6dbc3057b05d3f15
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 460539d96c07e72acba5b59c88fe904bf7f1e1648612908444b0b08172d05968b31b43456918b4287dbe01afc3cb4860d9c2fe549a580c989b6507094f6c241eadff910d2603f747f8e289e7a8176ca4a978bba89288a4cf875bf3e03939af966c54e77c28119a39d34a2b7055465f58ef2efe7c82ac547fb675653198e4b504
+A = -5a44cb669c055ba7c28d49f84bf8d12179aa30bbb9db2a48d7a6b09e44dc0e0f7471e3629cd2fb51e5a53346ae025fb49f9591ed1d71bc79daeb3f1254342d8a2b091ae07a758c1555efe59e78
+B = 646cc0f766346aaecbc5147a4488ce157a6d844045b80884eaee9d419087285fa71108b5ab4a05689aacc8d2e3dd0e6714c55eb8f77487a3fc5e56c3c2df0c4acf28a457051118560
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 79b536f4f30f9f7483f90e65e6456ef8072d9a7430405cf8c9377ceea2c676afc338837643436d55ac6af2326ebb362684bccc5092367209822581700d641cb8d331432b761e4c6e22639a27335f45a25ec019d180fc53dfb53d69216d7cfaeaa07db8288adc35b7bbccf2829631c1eebb821e4d3299015c3d462dc17aee5024
+A = -167529b1e8668938ec02a68bf4d76c22dd018c41e19be25e2f821f63c2046085d0af30d8b4212ea0f3f9943be1c14fb2d2a944551107cd2bbf8dda5bf258957325f06277036282977db4575b0deaa
+B = -378e1be10a57e03b197bc2b1287d643ba6d89da4bf6a6170816691fb6529c602eced237863ee39659be3729825f032a57eb5de0a87b0894d1a1244523e85b6f50a3d9976dbb038490e46
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 658169197ddd0bfae101c10c3e6a2b10dbb456048e81160b47b197fef439b1e0ed710399cfc80ead8e436f1c0399064f92da50afc335847515686e055fc7bcc0ca721184435955b896b0af4f4d96672ebed2f154538d49fa507b945c0a6ae926793751231980274213c80046666c28ada213a2f87509d1466b8d1b2122e93f8
+A = 49136d37ae8f3da71a6114327833e8aaf3dc8b5a9a27e9d04c953988456e525263f86ba94397321c2093803b789f8db3ed7cdba19c4b796500b979e02952e1625246f8e977e01fccc133f94cb22832c
+B = 1dca005663385fc00b4fd58c73adc7589d15ddbcb8cb2fba03a737a320c447a2b21e576ceda73811a31d8277883fd31e22f776bff3261a098ecf8f40f2855b0c723d1265eeafb43f85323e3
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = a49fc8084f3e780537b4038bb769b8db3653a3315298a99c2ede6739a1732a636e9787f2e8b09d0b9bea08fac43cccca71a315e6f4a7d6417d171b4693dbdbee8cd9f95be0847ffd40ff027267125d67b89737e1d0365bef6c4429504d13cd8ddc7810f456d6293c0c57c14a307b94010d79d5c13b92a907f923966fd3c5c8ea
+A = 1e7d8de2061cca59d1cc19b356a8fcdf2ccf917e0d81598f014167c5a8de027ccfc8f2cb8c37c396ebaac83ba862c146bb2d551d10ce03de9528f97725804e8a6de57b9d9da811200604c2a032462b6ac1
+B = -e38592f3acd75b575f64ced439d5ef2377d21c61bc70625639b01bf755fa2c6de803ce155744993493debcd4de40860bbfcee86d0b117d7f8c3f8ace68b67cb6fe7a81a145535553896424f7a
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 5a99c8a6afaa97d8e7d84f4899803c7786b1bfd2ecabdbfbb3bbb92247ff91ac213a72f6d23c24699d60babe91a7d9cea751e686c027fa1c954474fa5680f0059118426c71299462b11de5f2817d190599cc4b352df4d2e80605f9ad1e32eb13712d3027a2b6a19d52151e37e7fa057d8fe59dfc8a943a42a1756a38f103a75c
+A = -7df29221e6a102e32757c18f87927cdc90ecb012ab0557e0ab855daba832d76ddf595b9c5a62988ca968b64fd5bba2a147a5991810c17cae7edfde38bdbb7e13a1fe5206724c05a9fc9276c8d4e503a860c7
+B = 5c586d1aff7dafea3b8ee42e0e8854712c95385374b5bd1fc8ec41a72b296e070940c4160509a4a1699a678533ff3d12299338fc441b0f01e29a48677bfc5aebc644555285756e97c74e1af6aaa8
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 21fd2d881b6a52332dceea42664aeae1ca110512c13bb33e25ba4ec0f39f80eb73b1fa0834c998c23a2453dbff971eadb183c51a30ba78d593f23be9cb6b2b33a554ef31e4a36e0314fc2ec889f18debb956b89d1bf8172553271bd56d89ed0b30abb70e68abaa2c76f73cd5a3de93433747d09c845b5f8843f9fdf9f6c975c8
+A = -19fe3bdddcf08190a037768b77666de803ca4f7f0d7dbe6aaaf334a486dd0da7ca024d1b3df11e0406b0326595a171be30b04574c1a7d04f4d2ccd334663690fd20e4fd168386280510a00a70c1a11e99483048
+B = -33b2400173c057980b0e0cfabbda1a5cb5b83b7ae80708c199f28142237f04b071c6eeb63d42e80eec04b76152250c9e4d4c4f19a048cb9815dce6e66710fad1d27494db5c31d9af37d2aa779d12d7f
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 1c45cfacf30682a876cfe253f05b393a2cd4dc065ce73126508ce897a99a723cf5145187643ee62d746f6edf70269ddce3c348a1432316286a648ee9ac31ef87feb14f25c42f2dfc2e84bb5bdb4ec0124e249c526c55ff2cd0ae938555c5f86d856eb181572ed01dc045f1ababa52d249e56aba0ecccda905d7d1e64bf89bfe8
+A = 6a40d948eac2fe5bf6db15d7f6b89fdc0712e32d39a881c21859e8f7722391ce05973efc7c40e2c0d7f56c217d8a986bfdb08bf87bc0435873cfe4d01967c46f7d39464bec411d0369f6f5d1d83f42596fa47451d
+B = 12529775e8253ba220d890d4912fb95f91e4edb59610e889431208b6bb42b089cf2aaa12ff9ff98c2482e7f4cbf35b22d15fa28aa288217bf766e937a706fe1e600143087b0a67f668cb7b762c9b9f38c0
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 3b3b08e8eda8be3918bf648227eb0d569dd898729d9cd54deb32b1a1dc69cf7b2c4184c8ae9641f0f75950df263a5e236f428ca86244e617b14a04edd0f31c02bd4d84f25bacfcd4a2786825f0361251475eb6c7e99020dfee4298a1f1bc260d4e364a332bc6f651dde7ce5026dbeb0e5aa75ee98874da54c7930108ad28e3a0
+A = 149d36918fffa682cf90c4d3f3d48e6408e7ddcbeb44e78b9cc7fbb08108f65215761a61d79f37ec8f67cc51e0a9b4bcb3834b0ebcf6734985153f29a2778473b80147eddc813b4fbeb98843f5c1ae6cea68f88dbb4c
+B = -ca87f66182e271a69c0964eda92a009d438078b584c3eede28ce1a501838c5f497186d305c09922f32ba858fb55f2a0dbfc9cd0f93b789c1f800cf092726d6d33db19e4f26c7dfca69b83925db14544ebfe2
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = b199655160d88b6b4157ada0e5675f82b33b5592408bb57c46e2f7d8791bfccaa51436dc3b772b83e907c20ce7edc2835ce96595b78c0647d244e9bad6f4184e0003eb0899e7a47ba0be888b9bf795eba95e5073a85c4d20416fcd4a8d4e1e16b403deb38845fb8bf9e9264d68807acf02d579e8cd104cf2bd555e6cf73d0450
+A = -70ccbb73e33a7cec30ef2071f3b1f2e008e70fd6d00fe8b7aa4b9146fc6d0549c57d984cd014c7e0a4ed6d33376998b7c2c9778fb9580d8ca4ba795c88612721c153c186740c58df3fa63b6cf7a4de76e049217218c05c
+B = 6cf4168d44a8da8e8446b4420466fefbdeeaf9623a40e10b77547687b25f36916f2c18cf6060c03b3b40e0959479f6aad5e44dcff0ba799262ef53e280f4a7f667d262d472b2e573265774deb5ff8f25dc1822b
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 6ff91af444c61d2e2fe8ad73bdc5377d5becd55074eb60f0f98eca3d8f4be8c02f196b3afea12c36f78b78ae6a5ab677ffb7d9c0bd58987cca816affe468c7fb4b56055f5d2326532d6ed1c00ca2d052ecd103994e8929bce04e067082b4ded7e1973566f99c514b4e0d95b9a8a931ef4f6355066940990fead70208a63841f8
+A = -1c924bea12ad6f8b65abd1796e381fee2cfbec15138191bc22d57165928794bb080c83878fa5fd19a5d657b2fa91165459966f50aabf19440f7d75f027b32e999ff4d3f7a7ce878fe0f33a847d644d86ca19713ca9968d97c
+B = -3abd4b281b8f25f5957d1f2fde904457d49a3a7eeceada26b454ceb4ae0e879135d376571f08b5038b7b3d73a9a9fecbe265b72375756a715a523ba66737085e5ef7a4ad988155adc93eadd5d95a0faea56914983b
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = b9076229b1a1241e8b4da3fe143ac31d060785be6ac1e841c2fa9683d2bacff2e2b5dbac33f58b0b1718ad2053c37ee55ea54a9d258ddd8930d2784852844d85db24e4721762839a5c73cfe588efedc8932ccfa585e1b5975083919be9e32a86dbdf5cef84d3d4b2ccaf7a006c0cadca1e35fff2da9da7d7e779494d8f85bf4c
+A = 75eb0fe6c07559c2b0c7b2acd7d29b5798f6c4cda64a504ebabdf54bdc773ab28b218f0defc040016178958d5561796230b71edf49bbdcbd3f14494859843c8ca7a0f777cb05827f2839f3982832f4f3e3c5e50af17ecebbbc3
+B = 1b8aa718d61447003fdbaa748a9d86befdd2675a677cf34a1be7c81e4577f665d71135a8a243976a4f6ffa1636695567bde522f8fb1948033a7e0941f833d827e957781cb4349a08c6be418befc8959960fd5fc1b288c
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 9df82b7c34ca97a3a5d4efa28d5ed4f35484914dd73af9090c4bb31ea3496ece8ec650f4e7b07dc779c97e597e76e43cdadbfc6e72b61ea718c073be1cd204f8ad2bad0df1e530e75705f3d3dc285e9d793c8d42f04dc20773d3fcda8ef3ac1cb10d33d20a91add0358ab8658f49d2fe51d0d2d72684e31c0eef85e5695bb4b4
+A = 1fc2a171445ee6add5c2e4d29e50b91d83338f8d63c111e4d3e95f16d2a33be02bef24dcc3d6ce6bb8f1ef980dbf8fed409a0232c0566153014eef840aff58ed8c33e8d463d408f93e2f5381a26fdea63676c4e5397eba1d39f928
+B = -bdac7a177c77451104852bb99004ce8e617036906667258d85adcbe8cda21ab7d03aa7dcf62cb210a9db8fc750c7e1ad290b35473be0fd607fcdc686de0b78fd9f258f5b25e2ed43c2ad1a38859f882b9f6b293dc258659
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = bd9f3d2e8a1086b177698f87a9860e3a5f030e04a0bf4ee9436ac55e005bda01ff4ac662cb85d39e98a41c723ae542a83a936c3bd0280c6801ffda080ec0aa4230b45dcd0bc5eb41cfcf272028bce3572847637a92d1543bb2b8408e880f5b776e1cf14fa28d15cfb584f025596ff10c9f091c837a3aa622d9e5c856db8ac207
+A = -7fd5357cbee7c5e31fb62ad03bd47b705b574d915200fc7f1013d836b9cb683db020b152ae9464de6aeb8baf14999ac7025dde6173fae6ade325c60ec310eff6dc4130a8efffb15ddae90d760cb7f76a27d0368175d4a44a22f7f223
+B = 5894a0223e4aafe4efd4572752fbde4952c8b09cdfc35137e7e6ed650f8fdcfce9de673853dbf73730b159b2656047e69377d7c5025a6b346fb08831e64bc8bc34b75765012460d8135a4f7a0f41d768fb85abf17f5e2f5c3f
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 2c61867bca70e8662c7e5435a5aec020faae86fb079b992bf49d8497fc5f96abbd38a6f04f6ca8510e0160e546b3f68b7baef4ef0f404e881771cc12ec5ed3e3787c2d2ad6bb957cc59f8d56f0afb4bea49cb671cb42f4e8a0ee1dfadb6fa14f84a5b3269dd33e20d658ea4cc39499c7a39a4b5650ad7018d32f97954610f676
+A = -1bf5ae15f24c7c14eb59605136a3f679f303cd5b81e4a27465281d17715afdc2c231d7ccbc59f80ad176f4e0326eb757b52e3695e27c6776d7936da47e3a8a904f735b151422029535045ef489e61ec93f02e6d588491c8dad1cc311f52
+B = -3238dcafb85ce557036d19e42e7e7e473de9f9da6f920e18845dd010546868d2652decc94596cd2c36bd16b02c02559892b9f573bf21ab18c3c75591413d046b385d08aa66d849ab8adc9fbf788e837b047a7ce2b9c63f7fbd263
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = c1d04b831b712d0619db462c3f3fb5973f5984e9a48493ff273a5abe17a548e185d751628899e2851e425a7d4b2c72d4d908dc813cd122b8f497e08e299dca9166f19752ff8cd9840a70155ed9e8c063a3840838b3679f96f1cd5f1cbf0e037d222029e02769dce7fdaea0bbb5417f85497d77c76a387c6b970eac15dcd128ba
+A = 7aeb60c134e84f289e419b74f99a5ce5b4aed5fc630d5d591ac7643251ad32d6ca7f052fdf8857f67138262d221de644140e9018f7b84879d74883f8f251303f65e06bb52246ec6a912772cb698b47de41c1826ddd065359f6b9f1ccb0cdf
+B = 17f81e53d9fa6201e4d3eeebb32267929cd5258d10f053e7c021c4afd17094f8ecf433b1ca752f8740f6d6bd84f801b1b9fd64bc4787b9ae5e5aba0b4318a63dfe27e92d5a3ade192af7563c74c9d6006ae7701240efdd6021a83cf6
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = aef89874854ed34deae1b77286f9cb0e3017e3ae77fe050bb244acf4f30dc03504c73c1a4d44b769709bdb53811a5d0f8a76a08e6a66fc2cc4e98537ad6a8049f02494305b89a49a55e71fcc3f5fc42d6b478456ada9b19ec0a03f5ccfac5538c0040092771660312be5e51996073ff1a506d7460c57d54e10dc2991c028606a
+A = 18d3af14bbffbfcabdaabe44074b407d69abdd80a6eaa5954f0e45fac85af7ced1715c78da872f7a8fabaad3207e31f12b7195cdb25abef0a1e54d3b13349d997f207fe130d7985e2033cfec899a0af310c9827749cd22bd062eb0b1faa254de
+B = -85a7d9f08a60031e689b0e611d7f7f46e1178eaa2e6459602e738990c77f4d3783ac43fc04d53504cf67fccbeb02f9846756f8e32fa4a9316b6d3b45f644254077bef096a72bcff17ffa17070a4355121cc5daa2f782fc0d0bb48101db
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 14a85edc6297763547702c212b1a8274b8f85d53ef35cd1b01ed51039bbe030d0a1b9626ae2f571a43f1224d723847a1c6708f2238f6f6fd75db6656e6c703a5acb57f69717efe8ed58a3713ba2720d8c001d026d83de0ce5e24b67c41daacedaadfe404aaa9b672f00562e6901fbd0710c4303fec41ee3338100beb36c9b1ed
+A = -44414ec207060d105f599b9a66aafecc5b232b55214c1a5e1922f6b59439b3ff77cd3a327bce4f7406871196b90350e6dca9aae147ce03027dc4de7563c734f111d95171f489105de5ca80047cfa43f7e932917b816ba7d41fb95b4106745d700f
+B = 45f2cea1b9b75880ac3ec206740cfe0ecceb488c9155cfacf5885a8cb49be78af8cf221ff8de2328f4880479c031f830a3c9eaebfd83f7de501b7c5cde03c4720c56a676d331b2a13c4689a2e34a43fc11f62825b8776e75d31225ca7ff65
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 7670c1e2e141d8f8f5466de8ae2e0ba2eb3eb7634699eab8415d3a37f8df291d00def88361e9fb64a2f116433dac3ac2764fd62f3201dce4e48a3b7019e5465f82241ffda29d5eb0462fde74dea3168f8993ccd4d090b9c31a5a6cd7e05f725bbc89479836b89379b422250ab049f31c860110df5ed69089716877fb0ad7b0dc
+A = -15b4a2f808a85a5bd466a342c4853c04ac0ab73f8e53a4a0477f73dfeb8d7a911ab2eb5d3d192b9b084d0e38db491148947c66f838aa5f460c37341b129137614259efa531c0e6ffdf163ec6851737037a5299060418d96da035e6f583e6ba79d0414
+B = -3e94fdf22004384f7881875b1d8f58019ed8afb1b6a31f5d591e77b0998f3100b34174d6f3466da44b4c7fc8b92ccc5679c26c146b704198a65a88554d24291adcf897bd758a035361f671a82972b5962002c6a828792980f86a64547165327f
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 35b49beccd8d2010a8d777c1ff69e28e01a1bb78c6466e717f0a934bb62f9bbcec5ed29f9cd2c14d240a6c33b28c986eb9c8912a4927605532483dcfd31a50876e1819f3d7a0f49bd276ced5c4110470244fca52d2611ed7e31cd8b73e749aa70743b39e92810b3b52320342a65cad3180f6e2966059d15f79e5574348f5f66c
+A = 6fd078e3cbcda6a71a710e99204da640edc71a65974fc765999a74ab50a0e4b090d57ed0ee869c8da2cf694b6fab56e87c4af62fbe73eb8890bc066ec3460beba04dac3b8fae7e4f316e8f954c6e8d934e946dfdc9f4cde0f26bb3d40d5c444b03bfc65
+B = 14d8041a3b83468d2f44f150ad8d8d0a1a22035d630f2a17b70d5c3d557d3abc7e4d753e1ebfb3a3ba465520b84746073d211a67e079ec7f47c2cff9c06da69bb5cbafcb6cabe7e0018867c42e07931d6797d4499463e3cf786c6d5d6c8cbd600d8
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 2f6e0fed8a9720fbd83ce950d7545d2c6d5b271582194570424f90309227a51777cac974bca0ad3c1289ceb91cf75af73b0645cc20d71e7789144876b8c1bdd550328d9907accc316189e8ad81310848cddd2dbe362c9398d814a048f93f9368fdbec0f19ab87ad2a59d4066d738c3da3cb71d4716f2cd2336ad35ea1438276c
+A = 14bda9e4aac85b0ab7abece728f61450b7779d3b5fb83be813758e742d2ad76597f132aed91e20a75c554f0d61ec4dd118eb733d04942b2548b1efdb4dd22fdb543d9bc1e4bf0574ae2cb2c46fb98cc4835b6a074d6df1a3bc5443beabdc784d542e3349ad
+B = -efd765f8ffd72d041ac3244078b8dc4482233e9411b289cbc2cfc26fed2cf28e286835010438ddc9e7021ceb098b10c68bcc4732608ec1f4052df9362176ee14812bbf09ccf7c2882714ecbbf92bbff61c06e9dc35a368208a05dde949fa2cd091ce0
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 1f0c436379f6dff55a59093ff2a0626a9b959e3e3e59365afc33c7a7893f04bca863ec910c446957baa8de4e35a1f4e9c4a776ef41b053f03b775f327eb7e5fbe68bbb478aa4339ae703ee4b573d6931e47e09271d40239d527fe77098a7fbe519f5eda1f26dd6a7d0ee6833efe37187d8a85844690fecf9fdc3a4d80b921130
+A = -51eb34de29ba24d2b1fbeb0a1c324f4ebc69cda2dff971a315c0c2775d988b03ca29891ed0790f3dd507a1d26ead461dade9284613e45df338dd83aebfb66050465d8aee554970b43f7d4e0428e1512289fa1f9b23867b67095c455b66d536b91207b749189c
+B = 55259a1122eb7eb611a69118d3d42c2f05dd228d71c0e1e42ae3a8d3d180a95b74150d844e916ac85105805126e4b995f2ed1cd3fcdf28e1fd241dbe3125dfb3e4d90556256eb513a2f7c9b596719c83b26931d92bfd3573560e8bf054138f5d6b9cde72
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = ac321a272d2206df4dcd6ed8ca194a1049c1e3a20bf325fa44809d302170f850721c077bb5d792f86f7ab03ca259567397cc2fa1429771190bb632ac2c92d3fccf6e05e13cd33149994cda5f9c57da155439663f6a13c66f9da553f5038fb92fdba186ed9ca04b8ec87cba4c5a68c8edeedb94e38a6dbe293340dee1a4ecc768
+A = -19ac99d7d51456b00a193b3b04693c7e5436e05763f0154768db078ea5111cfe9eda3451091af213b9c8cc649d341de66c12ab2803ea39655d3d7de182a77355ca444c5d2778f791d39952a7a11839e497f5dfd8a703df49ec4d7628bfc25a992e94a6477e6be39
+B = -286d1d436f113308be594f0f43d7a05120639152b7e2f93058cf602cbdbc016512bfd23f7aa937fb358b7b602d15998ecc150f2b9224c58527c0c1267739e065e24236771e2c683957871637468181e6e896b513569bd004b9845f0f0e4c26a5ca123365e1c
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 3466804a1b7d1af8b6060aa93a4c325d9cadb33ebcc8bd991f9e44cc2cca8918411efeed0f005790d649382ec40278c8cff903cf3db177d24466c58cf6a56ffc14e595c36bfefaa2327d37f616b1466eb702f5c49170598bc361d892e18051b8233dbc5b3fd6832befd9a995bcef3b0f3beda6efaf09f7306ec203172e78264f
+A = 6710c19330d3f974fc377e28039e0c0ee0a558621fd67fe724c326537c18c66dc5eec60980e07d401ad5556a05688d2dbe7b271f9d5eda3032bf7cb7c420e7b5d65a195bc037090b6fe83064ac3731624ce2baaaa62a6eb07156ca12ee51d4321988026cff573ede9
+B = 137ca18f47a151363a3e8c52dcf024262ba525ec8852e8e406f460fffc2cf88f1999b17a5821849317fcd84d09c88ebb6eb0340120f113d7ca5fbd91c6a40cd790bce7b422552cc0cfd2a6417add2501db1667f2802e5d0f4df824adbd033a90a155cebfbe0b53
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 6f248a70b2cddd9627b32fbd130f05a604866799365f94d97f1eb582b28192959692a870be7c2614536a8de84cd8c1364a75a3927ef9dddbb8c6c87dbf526f2d3a7916384f2daed96002831173fa4a51863c28b4378f99b1b201010581d5eabd66ad1e328cc4e647bf5e0588bb775e130b4a4d029eeeeb5852c5742862ddbc3e
+A = 1f014cdd87cb33ffee623cf454edf2c476e91df279b4f0879637eb6e8e5ccab305186de67585595d34ebc195fb150408c4620cf6c7a0b0d9695ba0e0e1d7552ca7d0be3dd678b1cce2beedd11939891a6804770f1c843e16dc2ea6aa8e4043940c37fd3d950caa122845
+B = -8d8d9dedc80994fc5db04d8c935301e47054250fea9020bde8d5fef01f2307cbf458d5afef5210a369c396287c5eb453637a2d721085af3de0d75a5dfb5dfd22fde3b229d438439af7b296b9e68ffc982efc6c825556c52a735f8be12a214a06c4270824d5268fb6
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = a35ff7e232f047e575b200b9fc4c9253de6ac04c612b8a82c275a951075eace5e7d6664fe8f78301d554cebe7b996c1f4ec3ca59d8d12d7196eb3909223de94c220f0445d24233534af1c93433b05c5924799d2c781fdb88c4537bb8d442e6bf76b2d966827bfb4f40378a3f135103513da056bc0d375b1339561700d15a0227
+A = -58346cc8a9a1e5b8babaed8e7f59415388e0db654ea7cd465d96781c57faae7a8af8e7578e46f3a8de7bd1027188e1cc32fd1c0d60be24fa3289a12cd822a6c9a77dcf8799624856c27ba88fbdb047473274e651760581b44457ed048cf76c166d38bb9b2afd3416ac7e45
+B = 61951a16dc6466a9fabae99df29b7229f1ab96b476092dca1e4f8fc8e7404e2fba56ee66486d1f27f89bb3f86f271307228d7d6cbcff943961e177300b6acec1eeb46af1c5725f745a2d2af0fd9642f57a09c9ce6742114be0aa6e939e638bd5c7a92a7c206b2d36e35
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 90b441d8277eb1ed454964acf567067925881b5db0b446a7d554dc61ae87ff979bfb0e58ca1706123453e62ce31284a5a2db1228d259e27abc7fb5cc5848dbeb9a6808fa1b4afa844ab39b652abc41423c2833e1209a1674db518b6df7ebae315dd7f416df54e73088762ef64cc2cd0a08b1cb01c49d9299d149cbe84145a55c
+A = -1ebb693ea7d18e0ff4a9a51124ebb78bfa3a4635b75a6387e9fc745a2325409f927324d1289be8a4f5cf2d5c04adc7ead20564f97e453287f03e5ab59a6133584f970446652d05a131d7d382c47b7cb97580ef6710a532dd4f5a0369dd3db500ae5a3c5efb587cf0cd2638382
+B = -3916ebc4653e7d6e0a4f1e234d765d41e9e948b5acd7ebc73cb595559c1b20b037a3c8da0a7aebfa5fd327bdcc922551cdb8db3fb0a581fa0620ca2d2559ccde3ebc44542b4d80926d061e2a35c08c09547e0cd587c396ff2959ee93ea64b1e6b7e2b624cdf445988e1f42
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 3ac61c3a028f4a2df6645acbd36818a2f76a3229d229ce22471760807585a909727411e8b68bfa4e76adc459409a101a1ce83900d46918e8d0903a163de87c07bbafbd60c7f536a62c59370ea53b6cea4384345343146bbf529334b4201ebdc7585b6e5eee42696400c9be9f496406a4eb51d2fd1b40466224f1752b181774ad
+A = 5a16d5fb9047949684b80805e5d962bdb939d0d0368b48517a2a826679c37ee0ded4fa83e657192d9ae84294e450f7e2f2773d1f13395169582cbf95860891b9fdf8f3240a16aadd1198e884f22b2718219d478e2410fd4bb98ea534a3626201959af099fa55488f5390791bcc7
+B = 1f67066dd06ed4a49cb556dc2fce22814754885a7cf6c13915d974b46b0e6269c0fafd688f45ed2deeb026a7cbb772c080dfd577d21ed2c81e50e7537a70dd550eb94fcdf626500040da88c43dabce13c82a93769a9e0ef66a471661292dfd3b3af07169e2dc909e43678400b
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 7087dd62eed6ccffc7e1370cca9444dccc4ff160458941aa9f49dec1a2e9ecce4cf50ac2daf06994c5010cf225cc92238cd60e1aed9edb2befb0fb354ffdde94ef5e8ad0415bc95851d59095a5c4850ec52a74c78eab58309f395d3078dc481feb9d30bcd9f113af7a01611b94d085e32193dec738a64c5fe9bdfbf5dbc98cda
+A = 13596eeefbf06e9ead8d883113d8ae6cc3da8b6fa13ab66681db5a9c083ef9e49d905ec19c39b149cc09452eea0446b29cc92d4e865e6f681827336945282fa6b276ef552363229a976c503b822e6e4a9862d3fb30dd0c3627ccb97a7046a6a679050a39166388a9daad5ec5555dbf
+B = -a4e574363f2e5982cc087b38110d257019962fc166c2d6e6d396220bb308a8a0dc7d90c5cb2ab85faa19b07ed7dc11eae9bf2abde0a5fed279e77a717b43d35e70fec4e18445e37741262d0b0c20dc4375371d87d839d39934f1dc41122e815f3f37352d04d0cf514738b351f02
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 8495eeee238164082240ae1db1e3c1e36fb6621e6b714c9de914f9de8a587d7106b8dc5214f7c60c0ee231d7441e03cc26462e71adf8e29772ac95d0395722d2756f9f64daa8ed41d7ce824a572d7f9fd419112ae823b5b48b8aaae09fe093e9ed05918c4ec88ab159890910837ad0691849b44be95993682b2da2b124de39ec
+A = -403f21e1a7911806747bb78a4f20c4e6572d49c6c4ce071db0c8c91ee985e68a16e60093e4628414b2673d25c9f13c4c43600633af95017e3846512197c9515aaf9953570ce5861620716b3d80eae7de0f033772fba82652484cb3ce7cc189d1fafb14e044e07a88da302547f2e623d8
+B = 689d1b4a968b7c00082ae3a29c8571f826c4630c947a7767fe4a71af43a5de84db9b5baec0980eafd0019e09de1b5c56173ede68c9a6acf260bef3d9a03f4c83a33106c94ca7e1a8615b3553088d1d05a62ddab0f1e5a126df5d960f67e3b92981022e1f0358c7970bb2fd5dce7a7c
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 397df584bcd3b2e1ec7ed89de624e9d104bd6812901e38c5740755ce91bd54155c0b624c590ded199590be5d98bd1ad4acee56a62d05d6b5fdd1ade12f7db8e3eb08c4a5996450cc1204be7ba61b768af0efd563ea478033324731e24fedada1ad6e564238c891494e85ded4feb2165fda22f75bf120856034a9206511885fd5
+A = -19cc480d1e07523bac502872a971d78bb26955c5453386f5d51767150e229daad3ab2dc85e0fa0cf6e72389391fe627fd2d9f263f105508642eae5a095ec4d88545dc9d0a2c436907460e1ea7db174673000eb2e0b60d57163ced261bd0f6cd8ce54133cfa10591f1fd27996353110060cf
+B = -39c45512fc7c9620194fb7ad22abea8f6dbff4a137dc4523115ad7e262934143cf1f320892f8c097a400d4099e787ea7041d0d69b6269d191fcdc8ea28340ecacab71058cb39a9c7362c848826b35ab560c27113fe53c497ca452397891c81365b6e7f07f916d47961e50b8c7c5cab38f
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 263ab04c98efac12210beb66b13fec7c260c5b1cbc20cd732a511fb3786b917a617d6622847f4eed70f25982ef5d0b0d13848c62dcf447e3a1d491f4c80e69cec03cd318f6f93134d582210bfa81c1790562053a71091333348c6624d4d793fd6ef971d284a4ebf0be0771efad302015abfaf3edba017907f10ea14a46d9fdc4
+A = 7a354753e39b9ad1c0ad6b65575fc7247487f3ea320fa82d1d333ba8dd5d0ff925331994a6961c9c603be5775ef1842159551f0bfb34920b93d90ca60e6abd514650f77ee8ffff2bac0eecd0fe8ea0fffc6ed0285c9f3c3cfaacf338043975457d62f9c8dda8cce1e99f34529435016fe2ed4
+B = 1a4384f9620567c698ced05870b4dae983d8f0df6aec888353f9dd6ac8ad54340c3ba8346bfa47bac38897f3963fce972f6d55f3407ae03f5c7637be1a34e483e50dcc27148b76ef079f117104162beb191d146ec828ad5c5bde5ee1683a031d554c276d837bf1f2f622cd11baabce10212e
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 91cf4d1899e170bf75dda0d51a6481f79eb94c333b876382c9d04681073e949191223926523f6531f0a45765d7f382221eaa080d7bd05a3c19220ebe18802b15d8009714e8e4e9872223049622ca02040eb041707c7e525f698cc361847c66fe3673a72e4d701466bc374f55fa5437216eb59375c0e2c4f7020149d0118ea72a
+A = 12f35c48024e8271e8f9a60a48b5a214bfb6595a837c041b230e6ac87a4c1d4b3f93a2d3a193c750c9857c8627d0f7c454d6c4f224dbf14a865eb83e990b1d9b8bfb729b8d3dedbbe9c95032e4d60676c2baa2aabafa698392590add3b83b521a7a5e7d6f8af207e44ebecd735374acd01ef5822
+B = -8fc18f92c0613d085cf3ee6f586b39b99ecca864bcbe60fffc63c585e5613df68f3534ad46e244916b1f9188507a3692526c9e403b8e93480b0a5a6297f65215f1a5d8e20631a9d559fa1acc15a98c9397761ce18903f393b10444ba51bc92ac44df90d4cf0852da9d75902230c6de6f26dfdb
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 9af562a7b61c6c84c91bf979f32ba5d246d2ee2050f07ec2dd5cb3f9496bd37c3922ecb2b5b17085a13e93ab2dac6022077cc18c621cce3a2d2247e5e89de8692a36f596e5dc7a6969a4f3ff0d1580eed380e6550c6218c1938caa2b7ab401ae6f520063c811088504d60a19da3b5018d640ab8d340f35d1337a2ede8bc64bf0
+A = -63bc10b8fbcb391dea305fe61b404d3bebd035514a812d0e1d38daa3d67f9f1bb8f02d2979270cb9147aa51d66ca73d4b5787e472456a13fbe0d568e92b622439d33ad3c357a56dd26806ebda7b3bb592385ca5dba7e5eb5d85eed0a1746441e8d56e22decdbf8f4296e30d222da5af17c427e832b
+B = 57a602bbdefcdd00f42ed1e2cbde2ba858d171804da56b0ac87081424ad1569df1308fee7c9ed349eb496d5409c4c46921f09ff0830bc9f57e920e17df16523598fd90314141955ddb84a1522ff3ebfa812cfeb6670525123476a739f64ebe6a5f1fc805a880f8e5a71b908c483a121b38d05cc2c
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = b395c9f264172a3653af6637e72c4c8e564d1ce68032a5d761bf546e0c4b51b33cb026bb4256fa639ae98e54e5ff7d8921ae411497272b53d97c2c44b5b9ecc5aba43dde201f64f1d033056f19ceb0cbd04decb486a1d07ab1c64fd213d7eb6db9cd11efd743462e137f368acc4ca0b49a7f85587bbb5ede4be1616889e2699d
+A = -1e71df5f04001f6468c3a192086bda948aedd19c5da9a5286856f30524238d95b0ae71940f2af123315ab5d2fc61964d3e970d5858b7c1a78d0f2cfd10cba7ba4830a8c19a09b59794ca5d7da32cd8376b5ab06079b51cd9819c0021ea41a9e43aee147befdbb17a92cac7c7767705fdd908bcd291fbb
+B = -394c187308320ba1b14d91d75b8ff993dfd57f9c84e8185f12bf9924e046629ffcd7174879f9925bb643988259cbe9dc9277fa83a25012f91159b012f1964aefddd5a94ac6c2a55a22bbae93085dee079f84cea1d53dc4771901db9a3db5a14eb17c25aaf5377e2beaff6276cbce7cee97a9b8f32737
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 6602ce0fb5002eca37e85b60cc871b7b2eed13d38c20a37a6e0886ee4814f3ce2515f8714c67ad81e8c3abf6a00464e6a51b15e55b6c11296ada43cf459e15915026d3260cce8fb796241fc2b0bdd2b65ec04bee3b7ab6626e10597f3b13b43d16c34afd5b43a219917626c88b24c6f8392bde1b2e65a50b7f1a8dc5eb096702
+A = 4855ce75a3d7dbb72a257f6291e9f6ccc158647aeb2f8beb3e8fb32f6f59af1a46617b77440798562d6f58bfe826d3ea7dd28daee8f5162d7d24ae6c24c2deb2669b15898689ca789e2005903f3a94e991e7d3c8f3ae6181029d959bb15e71d7ba94d2dfd3ddd10f6fc49a65798b5f6ffd64682c78b5d91
+B = 15b3e9992aa3f042fd58ff97a8c04aaebf46b75fdc38caa9224394a1805cc26e4311bfb498d5a04d19396e98d11c8810620979362df82b23a115fc1711b57c7a56b8408e2682a2edca36cf9311addfedd2d0889a78cc1ab170d1379245de6f1f6f4db815fea9130463dfe5283f195e6e81486a1d39634aa
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 6a81ccd82f00d829bac186fb38b85097d52afa3ca83a026856bb83f94d6af6f6c6f3141d433f8fc159d11397df8d2f44c769f255cf8148249d8e9fc4f59ec3bc8e804d7d5189e71e20b8d0e540b59a2854ddd7feeebda5a95f17605e8bd5f311a63cc2e4ce23a51229d0a49ca04982c1bff79c201de6cc6150b690c98106a39c
+A = 1f1589c9b5ad9d878631cb03c23ea7e94680220856285668838452a63b726e01709588b38e578da8a4845aa5cc2e4723beafa4f81a1a2e463f67d9a3e432de7064ba8bfcb943cd9efb0e5a136649cdcf5e85a667917075804991b997f318752304f4946d69abf161625ed0c03bf9abeb4ef28034f818e2a643
+B = -909dc7fcbd27d0bf7d6a3d0e2937ce725b5cca0acf78c103d633206cb431e2e2c785aea4bfe2042df32417143de76b71d21587112f36d067f878e556b94ef63d59a07d19647593efdba7f3f5324d64c55f93a283a0dafe080167f6576053f9beb326994f4a1d53e18e3f3e770e69450bb70f276d128e48ecc
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 69139f2e10726f83300505d15dcbad5b5f284d1c06789181683b7b8caf35dff063dfa4968c35facf32a3628dcfc19b3fa4c30ba0e030b06773832a2631529fe0c0c402e05a0c4e9446a8b6c22754c70ef540f90d903d83a2e3592169ce6b5edf939ac5ff25b8bd48aa2425321602a9571661a1109e275a3b3039ff0c2f430b18
+A = -5d02cf3969bff8789850ac898c00fcb3ff1fc49a22cb243ad18703bb8fae25f83502bcdd885417fe46e8237fd0b444712c4fdb8f4972dbf9278a83eb305efc7a8210ce55167c069d1c4136a9b66d0c4dfadbf036c079d12aa082fbb42bfb0098006136a61f3da43aba3d3bcf2f5ac2d7884caddd0cfc28681d33
+B = 50b369234d993721288662d83298d99b9052a0a66336a5a31b76dfb20ec2b5be3aa76f78b2c17c63d78402a15aacb585be5c8d2e7083145e316e71e111fd34f5c79363c4591c247b1a94b20ee042d840c42a3001d6c8dc7cc1e1348e0e3ea8c6551f9d24af2dc2d0c38a54ef065ff048b148ce4f11ed2b549c50
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 87de406a6c957e85c759f8ff684023a0f98e93ad4ffcbc6fb0038c7a7ceed2486f15f36555d286338aab3283aef677118f7cc3f88a7ff0ac9fed31da6786ce895c3c08d3edb652bbc9ac2b44c4cd24ad281ca3a8e8e6e4d730f4f0c25487cfc1b2afe222934eca8b1e1572780dcc149422a88eeb1bf31065c929685a0a97ac3a
+A = -1878e0497aa1c2942a2e6956957c876dac73c4bdbf42bc92498f29a006bc92f788c24a4624b87324a7c8aedc6b2c0c8a1a442aa91557aed9bf2c02b6664979e8a9a21330dd839f4ba8f84515fa6f7db9287f7c20f31732b98fc09ee7796dc524870dc35851814bc57e1a8ac49d8935fea04bb08b8760df33a98149b
+B = -32f4e94bd073cf3f70810d9af7a873996a0510109bc6fdebb855f27dcd012c59507491152d30849d75f95dd868992c6fbbf29b1d899cfd401e9e7f4e0436732cb4cc9e6a6d6b0cb63fb0bee21e422b7f7b7b14dc5d2b6d10447fc4add390fd3c8e7b06f1d9b181adfa8d04459ed051bbdc9666623b00e3871e597be
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = b456ccf9d066dcf4247a21c7f3820e324ac9cf004cecf8dd1f6c3aa40c2a33e24c423e97190fc71bb9fec21d36c5a687065a7877237a2a05e64cabfb3b20bfff0b1f5ef2e9adb7edcd7140d1047b0919a2c770579ab44a08e5ad9f63a06f90ec7d5885b91de5e524b2e187937609b4b81d40a0b33e31a48d7b9868add75286a6
+A = 6c484e3c6b530dcd3644b19fee66c41c7c2c1dbcde574d87ee13cabef9dccbe5b41e25c32c6a56df23f2e87176afd28249e5fcb918723707fca94d7e2c9623a3493d395db802a1b49d550f52c29666f785652fe81afcab00a60a5b50cbf523cd13dfa06d5a5b0809c68ff7264a2cb35b8d52284172c62ee658e8417e6
+B = 1b4fc753d0530bd07094bae09a02b1ea684fb4e8519086b1e2ed9d59af011f61d1b94ffca6f354a5b428417b328bb1e8af3f6c7ac9121dae58de9f1dcbaa9c73a357f408b870e62b0c7db1a72c4c440f2e6fe90b199b9dab29fc23927190d3f2bf8a7ee926a152e64474283695614ad696c85ea547f5f51d02d1b823e3
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 5e7c63276f350f04816a6ed9f98507a78314f1d99081fcd906affa3b8395fb58d029ec657af82e77ef45611bc988095bba9c26f25f8fd404432fecd02398e69635f3315a824d6a98b33eaf6a91f12957a5e80cb48d5b086c795eb3b1e04da5432a7e8be3d683addc586a44b6243ffbb7a979bf9664cc7ec41e75f267d58a7127
+A = 18efe267d4c62576294f4ba44c67a058cdc0bb44c48f4035682b2d6b8a63106081af43d99098ce133f8d7f9cd04d4dd7414f704e32871d43d6e5d73fa9f447873168b43b32d6ad19378d74a967f92ec7629a690d29a62a5a6e734e9ccf5b84857a00d97b9db846b057004b03d88b827dde717fc30e6a5246c752d65dd625
+B = -ebaa580d3eef5361547c692e107439c8391ac0a2d1cec0cd275d0be69133eba8a94bd186ff9a129af3f5a015d5ebd30215643554d7064635dc11ec7a8ed2200fd637b099e534237f0495d2b629abd4c8f84aa1d925d53e98490d02f9fe51bdda08b043f67f0903c0195fcb886c04397d3612e4501ab8c7b7db69f781e169
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 76fcb39f94dd2756e8266c025cebe8e801524a757b976e35ed45e3da3db720061cee9037fdb34776c704ad2059ad8920e400bfbf10eca9bb157eca7750cc31fda06473bd22d4def80189c47ba32e2824c721425f225563df2a2ea1edd090e01c0bf980677db5a5dcad37d21a68e2832d1012586f506480e929b2fd9bb4aaddf0
+A = -75f903ed9bb0b6db8e3be16e797258f6c18f6cb7b16f835f04e3045f7e4974d7a86a63f2ec351c88fadc0635b6dc83a797cdcb5cce1a1674f89e44190991e0930575b19e2aa1512bbbf2ef6f8c3e707b17516756fadb635d8c6bf9caddeba14834b5950a4d1e98bca79a4d15e5fa5fa3c1727d7a49b33d481d32fb14ae4164
+B = 4ccc582c8460f7def2d26167b68788a681c41bdf6dc805dca83127a18bff6f5ebea6db75cd959beb859637b200ccb5c7644d571f436e46a357d027edc9769da226278f7ab947963f7caed1e7e70e572980e960e9764a40c6db67bb526694b084976142471270b2331da563a10427cbbb38e76203d7da5d67487eff701d75188
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 5adef30c67aefea4da3884b8a1d0ce6724492bc76b477f1053621e7d19f3cac15448e9401d34e05ac4b508b9d1db9a8d323cf43722e0af6e3c3b6d463c6007449c3bc3236d156cdf988dfc308a1b4911554ecace52938a7b10f463d14f917ec3d9fddcf6d33081745009c59b58aa22bcd7dd8c3bbd489997d4e0bff5473ab9d5
+A = -174e8e057a1d66e22eff88de26f43fde1c8efe5611f6ba4f318f027f5a5818df02ec3f014dfedcdfc8c143c5005c3c5098d409710967c93474f5854c1113fe4030e6682bd56d389ca8b9a4587b8b9262d146bc92fcd81d75c3bfa4281898f394f45d5dd11cd4c7344ee7a933ee346bdaeb6f5188967c388b919a0ce6730c0bbdb
+B = -22702bcc4f9d5bc6f803af6af8072780ff7de7a346d6b9293ca751d6ee3a81493fa86738c44cf2b7be4bf14a55a4f8179c35c09dcb1485f4c08ec5e9f9b1efa91f4b5f15a31a46e1ed71cd934ba6bd271bb22bb5703aa468d297f360ecbb48f9fd6c572683e83ebc3d432203347dc62e19fa06f93e087283347950829d4256bf5f
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 5c2f67b1607776c10fe2c30b112e541c4d8229f5f99f615fa02cf715d3f20556a28eff5c233c58994e9c6c1fcc37b3416b0875b9a62fa5a09a4b8f9e216487203b387ff97fad1f39f674ab19c5e34cb2f162e6b0b0b0084f0618e64928423b73b189c744e3de9fa50d66f45975f68b14866cc16c8c6c722a54420adf027880aa
+A = 67056e93b69e8a7b789f1f8b835d9c6ecb7762f844d656b26df9844a60bfbe0d55684f61debeed31a24ef4246485e8a1d43d49eaf97ed9e7b9f2d2916a8d85b8c9e8ad5575cf5a3fea42392e5d1dfb23f7ad41a7b56a4f21e2828aab38a602d560c99783a4f807120292ceae366b1fbfb4be8e5d4561bc8944e7f17ebbcb0fb6296
+B = 1f874f244ed6cff9f910ba9a58db0dc0a7435e8d99ba6412e976b8f64d4106d3c5c57ba079384fced1c261aaa538e131734451fe84fd3cc5cc8b3ab46b2031f888d95084cd3a35a61092672a9118eee4ed1a0df0409e3613b3ef45a8b16b71ec892755dc3f83c5492b67fb9a143ee6102d053078f4875636b20b536d5cf851768cf73
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 7850019c6712f18eab877faa8489daba23cf34b512a3193852508185b13cd5a2e9f503fe8d61b74b5d3930021a5b8c38322aae9b9b1b4814fa4c2c5bc409b58f11fc8fd7854b17baa94a6bff5f234832f9468d90d148fa2bfed774ac03f2dab6a506a70db4ce363f932adcae202f04fdcae968f632dd674416c23d4e21345ef2
+A = 1e378a0f27e6259763890d29e112e3d8d2bdeb9994c49fb67ab680b6e71a52fa0a7db886d3baf52f36d943b5430ae8bcd82e229f4197239c35678eed254c5816722b995e9c311be942f8124e2f80c1e59658433a57f346adfcdb83202e55457308161d2f928b60efc39538a6469f90f1a868cf6077568c8241623896ddc2705cf04e4f
+B = -f4ee37e39d4cadb692bab5483ceaf0258b068f2c0354c540438803780c983469ea28324ce7e209c3bf55b91f0a2f4544bf318585e4514333eafb9b8c2f02170c620e9b5280a828ce1d8dfc64ae9c28577e15071825a85a59656c5b47d9a382af6b78a5b3dab1078dd647e0b473174b8415d401543d30a4018cc3eddbfa546d0fad9cbb2
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 4c8f8b671443a3af5ef5749885ce5de8e2afeadef9051bc49c0d7e72922d049b1accdb79d82288e472b07578e8b6d2176d6cbdd7f0caab593dc0fd9224a94920235410501fddd6001b62a7f7d8eceaa7a8e4c0de52029fae68656e8120972b5cc1c2e909c2742e836f2fecfa51e12e4f8a2ec7e69eab061c81785374ac607fbe
+A = -5769eae759dd6bf94468eae94189d3396886d4569b0ce264c22d39b623be3abb01bd5008b9fc86701a3373f7764118becadcc69481cbb134c20f669cefeb376dfc489dd4ee91cb333d06afa391dd322abe2b3b715d11ee372666473a473e29dd90fcc97e939049b455be52b3f288db306999019c1177ab5820d94859a9d2f050b7ee1d4a
+B = 44adcaf1e2afbfddae19b23cfc0f0ba1f940d32945d0b541db23f3a0a9d06fb1f67ade9a8e620bd96f4005ced99430c7a55eb7e93a701c829fd5b9e55dbb4d3833afbcaa0d9c946916b1a86af4a6393b1155c6439b8b82260e09ccf0ce5d1c4856f4d524983e4b0fa123267694a1c6118beb8be26113a02721a02d7b0ccb01ec6e9c0f9e19
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 51e25767b8d4d7b2b0c2652d9ca6bfdbfea06acba543b1bc8d3d25b2fe5f2998febe1a6e742abc3f482b4267854c2223a5918a9b5c84e0864278283bcb5bace0c046db1d0240443404fb62d70ebff3ccc655e5f5977958df4c878d9859a69731744f3d33978ac31551487270bb4fb56ccbf59402ef9fee42cbc329420180de08
+A = -1966812979042198f70b3f1238c93ac5c6e5749f1108c2bba869b1dac7680f910e56318c9b59be9212e713a348767ba6e75917fb599e929ea2144880d18d4fbda4f4663c7abb49b02245169f385e09098a4e01b56dadfca8c803acb7cc244f3c98bc17440ab2afce318476b80e1d0b4ed9a8d6f2a0be64633f8faad5eb48de2681a38a633ec
+B = -2e4f5eb92fc34c753c61dcc826abab6fc4f427c6ac7e73ffdf65b1037464b2a9a0b0290e713d81ab57c0e1dc30e76fdf96046fe10a34cc4511398319ee34bcaf73763a9042fcacf59a100c43d3333ffb3743048e8df0dc61fd0da3f935fadf882ffdfa9f0f42980c1af6edfdf161c4b16087e2b14277f655abe54582de79c51193e13169b55e6
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 33539b5f38a9943b15801d449adabe02da6e21651d96acd9aa40e866bf65015fa40178399254e8af6bb082d021e2a05da0f45b699d193b70112e114f0d25287476dc0c733c5cf9df57667ad0d3ffc4ea2f85b43cd10459cdca9465b0974e578c00a6e275e0b97ef2a4c9886aab7b5947b78a88f84a3f1d8c5f26bd07bcc59886
+A = 531b891fe9e8db322cec59a2115574c7a304c423e6b11516906b840542b2c608785e2c18033262ab9cf68f63edb40ad4f073ce8841db602cf8fae0a6771d741c6392976c9b333ecfcd0c8e9997da40616ae2a9e0c6be93fdc7af0dc0668ded1e42a9f729c70f74500ee76a91d3d993c075c2f645b35792a20edf17c157459e35c0a48da6c4c6f
+B = 1a6fdbfed1054a0c5758f92f72db7e5737b0740c4d8c3ae4713366ef6709b21eaecb6b74c92541a9a0c99ae18ac6ef7de79d4c84ce39ad59cea9c203734a99bbb895916275e8778cfcf7fbb7b7d081a677769e4ab96bc7bcf23303100e629fa8e07f5b8fc2e39c7b5724c72907eaad09d3088783b3118e57c9c8ad1799b43a13f73864c5602c478a
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 2eab6018361f557ab06725ad90f6886d4b468ab1a193f8fdcfb4ad15fff781c8681329a27aeb5f03a81d7c404b8017b12fe23165e941ea767c733513a07e921aedf20596763f6f977316e37bed70f6a617e5c2757c229c59b3d7b1fe8755b5f65f7f407f13634aca7c8a267e661ae2f77fc5a95f56cd6c8458119df587478b1b
+A = 1cc779145b2b7bf9ef4c9692845e162329940f96eb43e04db8728bfe736698082aae6b6a1b3c32867c293b08547a0941cf4059d2d567840ab6ea526e3724ad59e715a3782ca656cbb739dfdf0c113a18f0dd62423d4edb60057fcaedbb852178d38f1b5a232842b4fc645cbfd97a8cac0b094b870064302dcdf23df2c9e9f736d93409cbb8ce9ab3
+B = -cbba16086b51bd83d3460e51cf193ebc79b826e4f30978274eac3b2dcb04e9d7b56a1449b7cb128bbfeff5c4720bae45271fcc64085d3ee501f0f21fe73cb7db5f275d88be55c339f9180ea21a8cf3755a875331931b75d23f57c2030c89c6f9c1ead431cb4dbd4480564c83f8470610e5673c7eb6c0fe7351ffd7ee460df5db7872c67041aff0227f
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 96fd93535728b961b4167be8b304e570cc34e787c12a9a5d76e099b336ed6b837cfc246c5bceb04b0f4744c5da7071fc01d70e342509473e5bd7c60d6046c9b4f21c5ee71c4e678447f837db3a7694fc3936ca733efdb7d387f0f6e263b3ac0b89054a826da9716691c9d580ad38d701d08ca090b6c59be466e1b9833e75d820
+A = -6791fd686f46c3773fc8d7f4753d178a93f6fa4941f4305d9689c2a305bc67840bbef80ff05c7bc6de3a595f73846609327d28540cd705f5aa94a3ae5915ef55304c37c4c43a4b46906889331ee16585629bb303673d439de9c0236f708fd19a977e6e1032e0576a921853f7dd328979ad1f1aa945905dae93a82b3af9451a541f544c18ed2546b66e
+B = 6ae062b39c77bebc2fef05743e6d35e14a31c6fe1fdc42d8de2db94ce70a6d60d66263c7414b1081ef2fa6ab511b361b8baa9c71ec628dba5bfd772c440baefc2fbed68d40897878232d9715c4b7e7c9bdd41cfe7b6986d825f68be8cc16d04afb0cf593f3028f3dcd91bc94923f3d7211aa5f0f12d3270e8df8bc191808f0e266c4fce2af97ac7ce06b0
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 949ea5f645ffe5d0d03359d51a663c7dd6e6013812a47be309575e036503126f48677c68c4ef6e7b3f72d76657fa282ad5881263e649b5297da82e24298300d032af3f5e8309ac7eb597b16e257a6f7af3476a264415aa7783433e83be57ffb3fdb404a9ddc3527d6a9c297f8cb7b6674961b3af837ebb65f218147a46c39cba
+A = -10f59ba073126d92a201529a5374500612bc59a9e66322c6706b422d35a4f82d97e668b268f5527b4641c6099c80bcea504234f3c1e3fd29eba0f161da97c50aea542becba499f29d4ba5571873d4dd9eb3f48cb26fa6c929a704fe8e49791b2ca3293c2428d9cb453263935c9c90a4a2b39d23a0baa12535845f907d42b729033a0a1e74d18da30a88ed
+B = -34fdf9ae6760d4f434d09ce2a7760ca2dda14bc256015809745524dc49d841b07102aefe5a1d0182e3e09d4d45b415e46f653185742b9b8ea6960160752080e5c9577a12182ccf1a293407b534ea8ddd33ad16cd19ba537d8db5b542f86a2a292423d452bf18d82361240a7efa831518184572c5a8b73b108a81d5036b3b530d98bd47c7fb2123418f12e05e
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 9ab739ddae55a0d71b39974628d4601122ba6c5035c3ad0439691317f23dc33c0014f3e870a105e4dc1432ec79693bac658433b21cfc218ed411e003990b94ebfa87767f3614ec19f5bc30704adcaf85a9d3d15ea764c8f0bbd52ff388659637746d39859398c79016ace8c6f97d3a5616711a235b85f334fb889b9280ccbea1
+A = 76b15a0aa0f59ec804a5e9a627e1fed524320b29120b6789f8e71b1ac4e00a9a8c826919035b84f87d291e2f35460bee181342136dd9eaeb99ed00c6328b8e44c49ede3921d6275f6e7f03de179fb2374ae2fa6c58852fbb2649e214691daef945ead6c8bd5a53ad2b130e9eab6ad046ddd6b80874ca6515322bc171ee32749333669de0d9c883058423579
+B = 1fe2171056ed4585a143b6b2bb5f44047664f64d710dfc05c18be5840ef9426ef05b6e92e4ecb5544ee4622e9030153dd9827f2f01ef38e62b88ecd6c46b4457d16644ef6d863c226acfd6928a40de614a5853137124fe69127a7f05463eaa49bc742d8f7be300d06b302dfb0ba86801119bcdc01b516afa360aa8b22b7c6c1839cff859ca1bf26e3f7e030512d
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 5631048ffdb2767aa04d59d8a5750016b38b983a2d53743ba4de5d93bcfc8ec30183a84bb1e290ef9c72c7ad357728acecfc613a6f9b3d712456d545ed54a337930937f4589fe41e66ee930db3dc10a4fe41481008c69eced65b9d1c46b8574c5ac8f7d94025d8fff00ced17a5e17508527681bf94c2dedd51502a2c4652538c
+A = 1aca12b1933f25ea081e12ff4a4f6f9ce379f96d976da2ff7b8eb8ad791fabe31c1148fdec22dfd67828e540c955a1e13f40c5b125e1c7e6bd839bfa84e5bfb58bfed76058c6db77af7a34ffd25fabd60e19f65e1faeeea6371d7785f2e5bddc8650a7492e06691d61f997483661eeff54a30656f1daacf31182486bc40647975151fc05d2f64b50e632f5d5c4
+B = -88ed894287043e7e5cd2eda3c1e5c97f85809f7a246b0c20891fa9a024f3aba4ec1f3d112580fe6ba6b0bdcaa1325ac7ec9508aa88c187af08e4f37631eb6cc97e4481b18f747ce6d35ff355e425a4833834ffb8d34a818bdb015fb818ac9f58feb87020234243aff912da5590ea3f6cba74f1a9fc3ffa2b4aeea25479c55a3b572621e75d86d8c8f6ee4f587e0f5
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 6ce341aa4a571cd5bc110dd436acaa09f409661967de0bd096c77c60db58b2b0ec95cda50acd7fa20ea4266b2c579eeb6ac214a75d40abbb70845db74c4d6c93f8c545add269d45fb15d985e7e630d0425565d06dad4a3ff9835411e51fdd9780c24f466dbf29244cd1b8c3445af181d0928db399bbc8632f7ebcb9d48c0b754
+A = -52c53999b02a92d6254557203cb31a21dcb896495d1f29f3277d19129ee43e521ab9d5a297204a844a9537d63b74686eceba72ea2e7b98ee8895513395cf7c44c99348f5c4eb657874a8115f0027d6a416b8a04a1ec0e6809b7701ee7d41e99996e307bee9c295ab3df1faf674e0067d0ab3bec4da998580203e33760870ae472a3045bbd66e352b8f4d284efc00
+B = 4329d110504caeb71ce0453b0706ff675f646e70a6bd9575791a38f672eff226f4958f8b1fe4123c0001d8f8595d8030d0e9798232942725a9b9d654ecf50546adfba7103fed796b455ffbb4c153e70f941bef7953c8a210d6f2f4ddf5d9a79d9938503ae8f24d69d5d7df1c988630ed960e12dd877bb80a1ab0bcf6db67e0c0578fc0c40408f72b19052534da8d31ed
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 4b9fc1e0eb4be199427c48bbe1b53948d0135bc1965b8aa5421a4ec704b13cf934c650405ba02ad611b0f29d46d82d4a1fc5a84651a29364524e37be2fc7001cbd3c792aa477802999841ff19620cf66dd2453c9b05aac349b9094d43b40e358f32805d87cea3cfa98e05240ff95ec57d88e0a12917628ebd34946eb1ad6799a
+A = -15a223b691d8b3696306b0ccdb52c1d62c7c2d1ac71e5f07cd8fba960417b42fb5ebed5eb9469be67f231b5254bb0fcfadf5ac5d2906769e8bf8292f0442986cabd88805a162c0c1f60f9ff0bcc2029ce33452d05f754375c0bd147fba745bf8a0008792d4f90d0e0f2cf391f2d7865705544f4a220ded44732321473c0ae7870394d4e625df11bd0923340cb70b995
+B = -340e5ccd644849d982bdd455ddb3b9a23ca14e168bb87256bcc370ffb6b7fe78fd062b3bcc1ad3c8c3b8cb549f2baaf1b7f0f6522aba02fd35b651f7de52b3aa2e0e40352bfd6ed0f84a2bbc3b3a396dc8512ca1db01cc69611925f1037794c82a418f10e0d994f458d1f19051e8bea32b90ce744d46718f42e711c094ad0a1ee96c88920188078f1b044ccf307e4cad7de
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 31c090e5160faff9a136a7a482b42a43ae3c7d00c215cbdad28804be0e7b12b0b3af820c1350b1622a22c8875f24d48ff16231c826d1a946c66f70aef92d4e6582e3ce9213d907267251ac74fa3cca9f1c8fd53fe9898aec19936a2b797fc345d68f0791cc740199be39c05053d5591d874b415e62653b04a3f41e263d00f230
+A = 5419e87e50b28b6d24927934b541d8de548a8f4ec7e9b00aadb6d23f2d33406177d3fc72d29ad2c2e141ab2916adfd30ec4791c626af61d8d192276d632aaf3b54e2ffe83b44f6f1ac441e6823b6b58cc08fd7a0af945a02eabb5aebb2c7ff0622a17b38077cd0cba906ce23e71ac7f4da40ef6066565b4cb3a62ebda28f3629eaa251dbd9979b123a5447ea20331723e
+B = 184782ba4daf429cbd13ac13fe93fe5833f09915cbbc707feca3293e505ce9cf0b4b12ffc8b178e0a4617f809be53d4895a4182e7a8a65043361e654befe8b01429ba4b7420193d1d7d90930ee19cee0316f33a5795335f5fa517e1ffbc99b95101b0f936353afd3bcfec34851ebff1ef02fea991a01b587d28640c935ec91496d1aa3ab8d38a6ac75b3a4198ed27b9019bb3e
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 5eb9f3ca660de481968a3c7321281f22fb9273b16fc10d8eff1fe34842364dabcfaee4993c1c8ddb7c8d6e509a8d2afc005075d5fd3c4471f0622753c7797aea900e785ceef905e2606f64f34e47239c40b74f07e2ca70bd5a18cb0a88780489f3e98232221f65ac9c5ce703a256b7b75eb1dd38778d8bc05a37ac9ad8d36b35
+A = 1c73d8e3d5db127a81477a5c4c6d61ac62af446981773ca15a9a01fd5175a2826a8763f91d68df28ee606e8ffc203305875a238d2095345556f12f3b5e10c5bb6ce3f90342ac74b9ac057195c863c4b9d28ca1d958a98649c7f8897bc6abbc39becae963f61b33bab4fd20d9d0e5464f21c2cdf06d00f597dfde45dc5919f5124f26888b12d72cbd2f57de3f2de7c014f891
+B = -e406fb60e35f0abdd313b8431f4cc89fbb034daf71fae0cc727e9a93cdfde53566fc74e48f4cc2111fad158c63293bca0b21b98416381b81d2443d0e91647679481cd6b6869b37112d3b6e575eea7fbb5bdea422558d817b49ac36a829926553202cf9dcef09423c085d26176a89be741ae20a434ea461def090dbffaf2e2ef97bbd4ec779041ed69ec07d125c7b85a2d215bb0f
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = acf9d363fc9b76ecf7e61c33270031340e66595e559dd1c9dd4d2243819b660183521a4124558fd4b216dcf5c52c4127fe517c48cef428b9ee0f1bebabab487c968a80b9815e82c12e807c096974ea3893a8d5597f745365c352a6bc6ce92479176092f02907538c5e784bf26dcde7672338f402753b08de8aa21b9480df6955
+A = -7c03ba6e3939ebbeabd35cca277eecaec31f326ab75f1a29e05af50c4e62e0175d4d6a57acab87cf1fa3a51791e9a2b2d4d5db570ec3941263902b0c74544c323c106557cd5139d2a25f3c3ef81ca009d4e3c16f1abf6e2b5196df1b30def46d61eccdcb3741a6dfc8e8c5e6db68ec29c82b0adf6e35ce7aacef8da806b3b58bfa489d319869b20768f8eebb604a9624d048f9
+B = 4e021959da96ebeaad17f9896ed53010d80ed3fd4c3a826a266e82b80ad81b3032303e7c0e58034a652b8aac00c08d42a530039de60d74ad349438f5ecca1256342ded6f30e3bd2aad5bf2b49124cb27f45f697e157550dbbb37f5aef0f04839aaf1ba43bf1e77a1529818d0fa91d940904eda6b748e5c86cd1b37592542c43b7b4afe2b8926fef6dc01784fa431d43900edef27f8b
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 24124c69aaabec7a7b4e7a82245f6cb14b199852a8b314a7b8d9049cb66096d5ac93ac75eb58a2004de8b0fc8375638c0878fb6a45be8bfbcc292e3571df1bb8d6e346d5595fa395fef983a365e4e868154fb3e337d47771419e7f1dd5e4220900c564d7cbe8e7792ab288f99d265aeb296c5ebfdaf08b88d9b30ac660cc3ff8
+A = -167c959417e9566c93e7e05d2a410f4850e3a313e516ec958c3d2fbdecbf58072d05691c68981e176a867d7467091dfeca11f695f750c8c44ebc4d08e39e679d96c4791ceb1ea3b89fa3ce26f7ef214c5368c03ba694f7ae592bcd8ae53a66cb3eb1e0cd3c105faae6eb7e7a8fbc88248be722406f2d35e46c751b5ceabd992091eeba15191ccf6dd61a7ee0c624d43b188c42b6a
+B = -343940f3b2a5f73a51d6f609e8af306f44ce7b5c2e79edf6f4dfc07866dc5c4b2e0ba48099b5503af87762a44ae451d166f8914ba25b3cc41a766583bf73d27e40784064582fd9fe952fc00e9aa2d4e4f1ef35818978e725e69c1bcf267fda4d635d1d292d54d3ad10bae9763dc5d7f7226f371184465695f2d384d749fe07967a1bb64df22f294ed88b13600c7068d881f713cb8e3ce6
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 50cac148215963e58cf6d2ebc36fa518c63a0ab8fb136ab84c9657fee459043ee9f42aafec89e8ba5fd1cc5c4495a41e80590ce197e12c087ff7e6ea88ed798735f55a1634562b82f8514488ada526e5dc10700058980885000e266cad55948d1e080f6343f84b12a3698d9ad5427fad4017d931df77ed2e45e2fb8380b7fa39
+A = 6a9833d768a22ea46aab1a1619f30283a1ec254a2de5652981d73146aabe31041ed04d271c6f2e5e2d090cd615518a06563a94ee2b12cf9f142de3f15599998a712974d0ce9b122a2aa65bf8750f54c6324f12e321a888154330f0f9e1e5b7999acd70d4e6da95c2df1da2d19544b7abd2bd3041e3228c7cdba44f7d1cbfbcf968f8fe87fab523eede0485efaf5cc9e56095cec8983
+B = 11e782e2b3f469b1e3d14ccd1b8301ffcde7e371f6e9afc99af5809110c6d70e1cca5c0bbfeb95fc3ef8352581c11ba75c0f8c445ce2aea903769a24289581c95ae5ebd9553fee61a30d155bf6011278807833eb2ce7ee2a98fececa23fabaaa259409e88e3c4f4eb1e04176d44878ad3f6961e0615ade2fe86b6eb02adeaa7c9019d63231a28f84b7dcc8bb0e71e2a717db09301e1dca20f
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 7cd49d72bcf5ff4fa2c686f21e1f0146c4f24b9ad2e900dca1c0a5d2fac5047509064e65ac582946b251a3f04850c9abd8b80c92af0fb11ac13debdae8b94927f1de0e4bb217e78f5d04897c6a0762667d3d883cb754dc610442c9dbd44228a7ae4f14fca145550d813655befe3bfeb52f1c76f989ea8a1dd9c10fbc7e9d6574
+A = 109fe33568598972063279b71ba0efdc2e03f770cdec331428fb8ca084c9b20d0fdb5cf9ad7ce90c8cb8f0fef10d219d7dfcc6b4599440db8cff9971da7852880bf004266886eced8763b3569720df3a1fb0dde2717ce0183f2250034871146628430f206c12f5fd87574c206b203d90c0f2c705cad3484c73da8bf4e9f7e1bd433a6f7fd27df63079d30c490aed7161bc594eefad4bc0
+B = -b95da952cabdebe0194b7fba519768e1b56149353cd12023b97397b59e0d7f4dd1d27b65b833948f58e66d3f6928cc3140cced835dbd612cc82a7e9fae1621986f71ddb6707ad57926b03e87e165d30fb145795a70627975bbf9d9ac9bce07492de5227c666663cc28b3e70b19dbaba7f16849535ce5fd61e91cd2875e0a534a10c60d21f919d566a3469d108a35ec3f023210efd5d318c7210
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 98a89cb3c9602fe503c32c44609bd4487b6c8323737b3376dafacc3eff96efcce7a31f1b61ee6799dc9561e77ac058fe5195cc013e72a2864f7e492d9f35244b321d46270a582f6f14f15fa8203d392e81b183a1d64d48b51d70e38d49c93869ffb9d7509f15ccde547d2d9c4dccd50eba49190b6e831a9f4f9000a95dc83f3c
+A = -67d7fc8f1766c40bd476cdb65d4dd161c3d4c2c5860a0c559f0e87ada213c9ed33308c36bb1c7d615fa69ec53656bbae6b57181a0134af23ea2a75f8fed3290a2f483392a3745fb57adf2121738c84f6d34325121a702c8ccac0090ea27fe9a5ebb6ba9d4f397e4a7e3151850b3d7d25643398bd3e4c1da081471389799245d986cab825a2e6ca72b38ff978a2753c835299ab4597bc65fc
+B = 676ddc4d18960817ff8fd2adffaa68c87d234d62d445d6ba3847ded849356d929d9e4ff01f517d7b1c0778bf90f475923517d855956f17ece1e032e2fd474d2133d6b8a591995454d8b587cb4f6fdd0fa29305f146d340cbe6b6efd28a926c73735621be0c5decb792083b3f063a43dd9f635e03f78c1bb56389a5cc993c8f36134d755a324d4fccc2ac3bafa270df67db0a4ee6ea4497aa33b5a8
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 76c31404854006a7d55554762094df6e11e0393f5b0451d85de2e5b104432df72023a35f44da10dbde01cebf77b8f9d3ad582373c5d32232564729af0d03c5450e439045d96a2f0a38871c922af2bd38c545d219adce0ec80fccd121d6a733bac09253604a8a0b1ecf0f24e44b818ab9e9974181cef10e9eb17684c57d72257c
+A = -134e8784878a8f3cf49ccb952075f9f9bcd24a20f8883955f262867045c11a9c566abee00638927e5de924872fb98f6376e321ebf3f567db6cfeede62e04f839617d78b7c9d3487b60a0d3897b3fa49b14c12511d04854bde4a9dbe5f31424a3d05cb75d23b46f6c0819536020880afa5a2c173f6881754b56f82a2864c99c820156f96b5cc4665d603597331d98d90a52f4a30c6215ee5eaa2
+B = -3c5c0d35de5fb21c84d2db228829f43b31132b582556b92b495f59df502a6d00584bb5bacd9b8c1a8c7eab91db0ea24b40f07e62a712842d5c2e1d208a6412a068cd5c6394d715260b67fbc03e3ae7eb4862f74f4d7484f747774fff03830c65fe022d579adb6737f6dfe297db750e6a58d1004e7e2716838befc2ea97179ecd53b7f36e3540e1c3a0f3e044bfe2d0efa9b89d2d308cbd0bd88ab3706
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 5b704b3181e5d0494937b4d6aa8172eea82919fd1d884493197a6a85ff047a7bcd5dcf072bdcef0287be20d4ac49918d1df550d184f86d7220f0a84fc4da3ad05e131c443fb529df01fec9fe4fa6fa2f36e791f9e16b4092759016d2f9b1ae7c3d071c57edf26386aaead767a3109c12a5004c7b9fa595e6d592daaa2dd1df04
+A = 48a0ccd2d14e14e2aa862d306501efe5de239e8ef36ff6251c861a0aee9f739411f402491bd99aebacdc26c4f30306f9137ffe4579c2f13efa81b979ddfffcd23675ac6307c0aa3ba8ee77a2e3a3c8e241bd2ade6484e6ead32ce8d752fb3584d14688f223758c5cb8705cea9c56136b219d87f9904bb56be2ea1c9a035df33455206e6b7972cba32ca4c3db41991117d88da3521780fe65c4023
+B = 160120a35ae3edac3edbede9ff1c6f317d95481227d87785b7ee46cfb80fac9973e418244884caca3211a3f6cd3bb419cf70fbc22d82ba5ab98ad80e1f6c2cda753aaf7be78613ef25577107a47ad1ee3c3645db85c4d29bd77900e99e1f439cb23c6c68662c05322f94feffcd9e37d8665cde984387093a043447de590e7874e6acfa37ed302040df4d5c3dcdf9fed91b3d17ab5c141d4494d0f301b508
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 448c3a64958b82ccaaed3c74706ce0a48c5e059c3610cc03a6b5a03a7de5d4f1d1e4b08a31478fa8edd58401f0171697f0662146ce2b371e335d695f9e4a671255f29fc0b9b7d1b2eca4cc7f8357aa0920b5942e31bcfae84e909828fbe5d02251ddf10dbe4c15351f675e96e2eae6d044da1f0858ce8ba9b7aa146850b85d93
+A = 1b2a52aefe44170376df29d17ae2dc1501c9c296f72f271c21f53db71247e72c3eb2b780190c45343bcc8f548507559ced3bd4a6fb13f9174dbddf965b9c4a56c3d88727736d78be9db2268cd02382e50c6fa28ddaf8eab9f44ad45d5882a5100b3027c150a7f3bb36f29d24a76e40f3820ba116d645800459f06c20679321cf5be72450879462f0eac99ab6ff8d26b464cd0e6d78621c9263394c15
+B = -b7d9bd08d7d8e0e9596851b7e03c78973a502afcc7b5fe5b0db6034ebb8a11df1ef7ed0ae1371eb4111cefd61c61935d768be3e3755e481daced219874cdf0d07a76e7144be626cf1fc21c8a0e9db4389ee213193775e95d4d86741d8d8fc820c239b7a90937000dc3e89b2fcd61b44e1c38c655bb3d31aa7e422b4406c9e4a88e6a2c18ec7c048f4a6b5b270c90d9fb378f64be3b5b351621db48a6c18625
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 2192157490ae044a26c23eea6da51d3a3dd08c7fb67a9beb76d37ee24ac0089863aa7f00849b81bab8259f3a0e1bc744d841e07aa413c286e4bef2ff3356bdbecee756026915894584b4fcef7e49da4012cd9fcb5dbe3f3b867cb6a7ee959a328b0fd56a9eac1f4e40a22bf0a30073cd2d48f99245ac03c373810c54eaf3306c
+A = -598eef47b40d1fa1ce260edc561bd1c1ab286a7e068af412ec2baaecd07c5b9cd596505ea1bf0370ea961c4ceeb9be76baec74e6952cb846f20e5da406bd01368b85d59569b403b7a305cd7448f331f10a34def43c738fd633df9a3eb194c32d53aeb567889927271d71d3929d43fb9338248b64f7d23cd1b053239e09cc2ccf5fe9c9ce240f1a10fb151a8583e4b4cbc70ec3082dd20a9962d564544e
+B = 559fc917de34bd7dd7a23a432142ed79e3ac4a6caa357eea21e423eb9af7fd94f1eca735d2588ec4c2ff013520c3a0e209627217cc69bd5a07ca46a43ec1f1bdbee5f09ceb1b2c18bd388d3852e51070943f16152a73da624be680c671057677356c6f281a4ba1f7c60609125d7fd9086c907ca5c191820d80e483886b70c1074e2963c49996ee92577334881edafd88270bb967da795aa4fefb739e4367390ae
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 3488bf00f67b852592922fbae64fa56d2e4e7081678e789bbb3b4f48df62576d537da2e99c9bdd721c725b9a828194662bbd51ee20ba73d4ed5562482540880686d9fb1e8ae62d08e39fdbbab1d18e399ebf07b3a6559dda8b043fc25a8152858d39b10ff64776e00a839950e7a9ed5ea95b594b6e9e9d4348ceae08071ec5d9
+A = -1b135d8cec9969561be396323e2f8be0c60903ca59b6c418cb19876e9e3cdcb9ce4f5251eadea11fd6e785476c70822aebdc94617063d161ebe55584a8a774ab230b8228a2b65bd5a6c873bb6b261429eefdc7d0c64c7e78133e739efe57f835ad03ef8f84601e1a2310659db5e0ee706f23e3c5c38c9f8c36e5b15b654d1cc528f1dd392f1b08921af8be6fe4e4e6db774392441883ef867bc729338943b
+B = -34fb63435c90018e5843098e379c76ef3ba0615b6b500854b3dda3e77fc5646228fcf3a6e1cd87a506e4959ab05e24474990ad98ad0865942737734c03dc289307f1b1f424b9a8c2264350943449b3d2b0f71f989039131e23095d122ae98c0089a184dc530669e804140134e5b602861a5e61c030fc3d3b3eef0a59f8c0579fc9b0afceaf16698de3fa07c43231312254c04ab11ad7a29efc4597780c2cd1b64b43
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 8ea5fcf7fd41803606c95729d2d910941e43b222f9b0c93a1a803b197fababbd653a92ee34e805906fde29b307a962a294aa4dabebf0d181c046653ad0fe6da1295eef817f3289dcc6579cee8869198c39a9f79992cf6894162d35d812df327a64470c935994aca4985d0e6a783b853ad762338dabd575ca71034e29d768d014
+A = 6858d029a62b0f75e4c59f3ec067e3990b2304c90a097daccaf554abec49a9d297ca14648471dba08f22ebbf8e238c89ea06f188203599aba56611eb3d4df09ea795a7e28f91f4a9a582c6b949c6ffc584a076de653446aff9b24e87202037974aede37aa9a121b5b70a3e9b5ca376c9056c2c91f5d5484baebb64cccb6a09b4f40529afad1ed64b4cc4aca586892693fb5f92edb6b4d5f678f7a2441e51410
+B = 197d6deff7adc30b025e7e418cca0a641e1a1b35f78fb56b9d8847f0690313475e6fbc6f73c3a718b10bf37434dd9fb1eca33a99bbba674195b20d35e3b34ba9d7c8438eede24ebb48e6d39eecd93fcd7dac44235ad32f208919f57b261da70ca378f9b03ae5e5a733f97f0b3f4102d971272015bf50b6f3e50c7b36cdaa14a8a580366c9cb0118ceec6e627827b0b8f614656292675ddb66e1c55355d5a1d78e69ed31
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = a25db977e7a8fa4578fc530995335411432ced67e131fee2cd7ff56970df64a6f0f4a7d225d2f4ccec8e98273ec9a0f1aef01dc0b866e425d64e09cafb9ebe3f80bc0ad71c769f1ecd5efdb4a990ebd3a94303f52f4a97e3a1d615918f8b2df5321c4aa9339b4453d7a710a803106dd0ab49c6cd9aea431f97fea9fcae0bbd90
+A = 13f97ba15ce46ae32147a0aa4c1639b6b555f4d8a1af15ede4f1103f7a0b06b4625bf456d667720adca0c4e26e858f008b012fae63cd89322b33fe51e87714519e7dc3cceea27d968b46ebc04024d063b17901a7ae978591ca6ca41afffd81769f04b714134cfaa6700cf23bfda6ce67313988bba5fd3782bc62f76cf551d140c978dc002a779ae37400d34cbea013a5d1338b203ff267861edd88ab8ee1e4c4d8
+B = -88d8a4c8c680fb01f493f73753c70ee753951d4734627da14962e36449db5490b8c575729fafbd203a125b500b96364e6799d9cfcf0efb4ec877e86865eea5e99e2fe5e7655c1ee0eac641e73b71c66d7a72c2934d1ccfefcf59781035b2c7b89e5de3f7d1e9128cac57947d22e7577832ba374492a2f53be37e17733d8bc625fa77fa5cf093975049a5c477f792fe75e85da26cceec820c8b255df0292824b4c3a8ed455
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = c1f2165a402fe9becea284dae60453965ce327f540bb8969562485fd1bb60372b8689d9c9c97c91bcfd699dc370117ea8b704f06cae3d972dc6e5eaac971597c69d4dc24a68b256f97229e643706aa6d2d844078a5fee2d08270820055ea58155d7bc754f09d0c6f804e55ebe53e3ec418747d4130cec68533f6f0c2f8fd2409
+A = -626a1580e52ba52a877cdcd62b34cbc7f949148671d4a61201e03e98985d704b2975b9a2d9c4557deae065becd662ce8448171ac582894bfa2c59d4ed20c6d0471fcad1d0fed1291df5e4556aba72f3645486580c8bfd0e3c8f6cb34fe17ccdd75fad4d4a2db4e00bb8c2a23ed17a31e95631320590f40416c153efdaf897e3b278a1faf1917554d9292f90c4edd5992748b58492289eecde1af34976ea8ff507fb9
+B = 44c336d7739118340048939d6c198f73f90e13030b69be286ef920902391d87a58df3632091d0ef25340eab395203e8dcf3389e95debb7432165147e145735d2e3226637b4b8cb7d85d68308be07f217f57fe439b31fddf3fd469869a20f1f852e1645b0d4903432ecd1fb6397db4c11f6b6b9c0fd25778b0ff00bab9ff576b16538a6b7da40f01fa7b987af8ead41ecb66b8940c0e8a1208d0026773e711153d99348e92303
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 98eaf476f11168bb63fddf7dbf3347e619f9b580ea6804ab893214e94ebc089cb652e307f1f37ea7ab9052a352e260ff7d1e8c17461bae68c52a8a8f1a57a84c79b2c8fcc2d504ac4f553d2534f2a776ca129ec1942d83c8ae24c772f6a8429bd61949ca1aa714cc3881ed731497b84415c88ad4b9be34197a549737edcfeac8
+A = -15897a5a986641fc2cda42d185d72aa1552eb92f788bb71cc74c0e424bd038e02c620d0686ff88ebdf0bc1632093c0d89e724e7d5b526b0ddc4c7e145aa90b36be0d8574901fdf286df84a6b52674a78cf21ae4865618b4347bd905461d878537b33cc41710ddb290964c48e44d4d2ce2ed82847de75938d23ed418bb9ff1caa03b5c1ac5d65692dd1defbc6013b3270c4314a45dc67883762fda5509b915e8277c1924
+B = -3a7141f54a0bcef68cbc3006166f7e15a5c2394892a428fa417a485981316a537cb3ec757d4a2473fdec2cd61010a9ff865852af8f43afc79a97d394bb6c58643858e2b4dc5cb958c33781b5c35aced7882e8b8d7b4e4249c2b82150adfb0c8f2bbb1cff3d2ea27ed24eae030ef468ae4d6b7462f0b072cd2a2f02426b3290b87b14d14b34e91a94c5bd69e9eda53335cdfa7df90a57f97f3d023ff85537fe0a8bc5d8fd7901722
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 34464b7a50713d17b01b5940b5acfaa7006aa6b9b083bc17e0535b08783761391eaca8703af2edbe13dd0fe9036d38aecfd9faae08c0861042ea1a25b41fa8a15b7721909783de3aca127e955e177987518dd010306a795bb66466fccd55bd9e2bde17470cbd36b1e8f8b63805229754387a5fb40f3ee9a8afb2e51e25c8bea
+A = 701ae8c5bafab7f41c999e492f04a7626b2b1054e6dce1b83002b2d3de46717225b018733b0fa8fe3f973202da8a090ae3fd14f48b27097513ecd4ceb1b9729e7783c17fee9be5221fce4ed3860275b3b36b7416594d2b65e198ff564e82301cae23756c878494e57b5ea8fd22ad800a582cae32fbc985d122cbc6e0eac77c1000d3ede45ae7aa087534adfdea8e9f924efa1b19c43dfd3b7bc83d7c40df7c6578a320a19
+B = 18e0256543619a750384d30b6a7afbbcbdcd9a2ce644dbfc97a8ff699e118032558f706502c9b956695cb25a46d7526596b3d0b67b69611009265838bec533a9488d24583e7d7f2284e23c3cc4ccc5920fc57e24f60da0d479d41f5b9c6ad9152903a4f37842176c6257fb1e3e0681d6d583e704c1d1b24cf616fe638106638fe9d79a0c74f0df67cb2df9d99185324ebb037d01ba0066ba947d5345cd3201b19769d438c43292f572
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = bc57cbb3e1051d3a3035f77c2e375c7e3221dd472edb1a5ccaa7521849fc0ccc7568238aea9335a733d839e89ace6f2b66ef238267e0050c065c3d9553cf50cc5cd93d34fb43c3ea1c31b8ebf0b751f595a7e5e3e860b366229de4286b9d3f0267f78c6888ab3f208c55d9292079116ea0eb9f4ec2934c97149aa132c03336ea
+A = 1ffb0aac11f6d1d257ef7aa997a030e2a12b0615fb11ff04f344f6ecd550e8e77e9883c246e009af33a51204e4066ed4249950e022a61337848dae17c88317e15ade5b5499c0d7597a69a02b6c18db0f975c19c16d2167c583571e947676ae9c15be60e69d76e78329aed5fa57dc5e616795b5487f3d52bfe74b54bbf93ceda093c2e14104a6d2f017f0d200a9fc89deaa283e04b0bd9015ec67598425312868eeefeae9c996
+B = -9de2d82e25b449b8ca4b02b2d2fc0a023fc5804ea553aa84674a815bd74193a2e549070e2cfa0b90a53070646875282fdf855940905f834f5a07f073093c658cd1813fc5cd7092af592092d789ab5481bfb14b6683139646cff8eb1c5dcdb6a33113d1c97d4b587f15f972c06046730b7e712a8e3dd5f4bfd07cfae289047de31776f222d11510ab6b70a200ceeb6802d6c33f913c509b31b96e2b8dba9e25b0d2250c3b102d814683f1
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 9f7f4e010370ec1d76fa83f73c80825c3b71521855fca5db06d7ed830c910d0430375bf319671f6a83bf6b57d9d53cfaaed5bc5d615c5690df0067b18791c33cb9f0ac9fa5f0473e4f4eb7840b0b660962097606b3de5744089ffb37d9c0df1123a91a5896d4deeab8aebec469b099a3a9a4f6d822030ec2fc4d11636706fd0d
+A = -7f56093243ec2399548ed95df79363e6ff09de211dfffc314b7cee526535def0f9a8eb9aa6f1736528ee7aae8be55c06645708d576111766ea33e0564c12103edd61ede3128a7a642f968eefd0d7f3768b1325c2dd910d459b15e54145a234225fd29932234e59d3ff5099ec4d5b5c6075f56382ade1101115c7b94e1e2a7bf075dec210fdaf2357c735416dd5d616335002d1cde6056bf7c478f810b78c661a3dbe6e54084bc9
+B = 4df1a6296428d06f51f31a1b0f66d0b77a04db3bb8e1b80d64da649899a1a55d4041bf0bb47d3e3936ee0f3740e1e8c2b235e1b8944d28c7d617d1f968abcde9dce10d6e3c27b2e3607d8df815f5a39da9b5569e95eee1fe5532c0a80011e7415800d8a9ec175fb1d13dad959becf04964b70dabde6d37072dc9f6d914309b850cda33a565515dd6c0181fc48bc7033b314ae0bd5872480e02ffc08dac4e3030d83b33488cf149e19b0021b
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 6da5fcea305cc6eb47fb17190889e6a39c339da1bea2d7c95e997fc538b4aeec8b0edf7c109faad7fb6c656420f4afa104ada7a0d3d14d3ef0fc6774b59aa2687c0b4efe7c3fc83194a89c832f7168346cadc2b1fa6fa9a23a67c91ad731b4cfb9943738c7f9951945b2eabb3743473d9c0444ade756291f53fc7641501597a2
+A = -19dfb98f9f7d20fd331ea749d2019d8367935fb75ecde45d6dabc815ab9e593e51178a72816f85aa678304e6ff3a2c24079a59aca253d76c4ac633fea1070753ce770765bce47428f8f5ae40c26a3ac91ddb551b3d575bad9a3b6fc7954acc93aad2131b78fd212fb0db7cca4195b41651a5311bbd4d8c64f1c93e6520eef8e6308e98caa1cd0d3c9b4041182cbfa131c4948257f1200b1c5351bee77ac8bc8e44680ce64ed0648f3
+B = -2736d5038c60553927f389c0650bb1355b0ce745a7dc5f52c9909039465344af910a5f6a9cc4ec130b9877c1cbb52fc08b20d672e42b853d26a02bc07eabb9e3f91399db8465b6a8b1c9f4a4b9eeeec6e9b6180f1a770c139c8f29ceced61cc7ba182884ae01d14dd85bc924391333e8ef039b586b6a0ae18db3570aa560c2b0226d5e23e7e753873637c25aeb19e74997da4f5d0755571785bebbc7dade57446e0df4cdb8df23c1003533f60a
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = c0265805aa8ab52da5aec06ef7cad2026fa0b18edb27b4903e3c068ca6464465e34d3f3bdb4bcc10a19441040deaf5569645f7e09b36c56631b3a6144d6206d39c9bcac53b54210db6d484cd6a2780bc68c07272de03a9bba7e51c9d86cc8883cd2e1864a2ed711d505930143c883c57545e9c40851c6df8b3314a8c9a0d201c
+A = 5622f906b077d243521325be82a43fce321412bdab1f15e4ff0c11a7066a288b7939afc01d30243c8a4150e74286611ac1ca4daf457aa23508a7af869d2d55f54f2746afaec477cd7df0d5711dd636802ae7f673b3f730236ac3899330f89cb71d48c2838322fe856d9d8b4053d9c1e66acdb5e43614ecff954dbe37c5269d7ffe00b34e682c0be3d7cf653ef212daa3d55dff92b329126636e440b0bab55f4810a2849f77c39ebb93e
+B = 1ebe0d1800b1fcfb67d7d54568e45dc604450c1dbe103ee21d48dda300c1d9b9415dcd9f5a56cf12c2ede3c862e895efb83621435377387b29b882b2acac78386895c7daa90810092bd3062a3a4867f92d54622d7f0b89b40fabc4709fd507d4002ca80de231596630c234fa418611ede0ae4a9616d570232c1b03329bad02220ef64e455c164aadc16190ce35b78060a6b117b4b0641fa64dd8e8cddb5914e7657573804e63dc7b216b1a9aa175c
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 606d2b6f756548568013bdaba6e811dbae88fb01f5f36d30d15dc1e099d86bdca9fc1eb3a785034ea14cb7f4776586327d57ca5a52ea1b30f26e2a76140bbb0e930c7780673770fe22c5ed443c349510e1494ebe402f2621b1e6bde39b8691edbe5c7242efaa6634553e6af146dd40666edf4a3db5d1e7f9347fa1189c1e5168
+A = 14ea5e6fd612945c71fdb17ec44d95015773edc908a85a6645a8eb823d11226545d05b81791401cefc81ce9765eacea7a619cb482f29d38988d355ce731bc9009969b7487a3acca2d2065c1faadc5d6dd8ca1dcd3f3d4ff61d0a75ef75272e62193618f6b802f70795041de26d6ce367ba996dfb91167cb1fa16c8977f982e1718de7d60275a7f66e4ad72ee55ea06267cc4e8b08f488579825cc674b0bdfd34a01bed08b62004fda15b7c
+B = -8a542280f6c8bf4d9fbc96d5bfa6ee0d16a09dffdcbfeaa2dfa1097a760dec7bc540a0b5b2020bab1eaa594117a40a9bb99c3f16fc340c262b29909608740b8e77fe4706a88dc0fc3bcd47998e88fa02f617062393978ac1bfe14235d43f3d5edbdfb9f140412f4fc2dfc05a700f47b1f0f90da7ae07ae781d9ccdbb951f19a8b8a9a7dd8a65942842cf207f3baed3a0b2f08a06ad0d9ab7ad0110346293d51ec53ff8165b925c0e7906be8b7303252
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 512220042f151479a6a8b7c743ba83366cb7733caf37164e9c823422ccbf78b0b83f426a7230f559d50bb0ed3d9486c6a6e25f4cf96c4fdcb2c861566c6a73215b6d08995a14569710cf9e54abded1d77fc7722d06fda4557a3a99862e5ce963e1be25336fb42a4629391cde3aacd47ea5f5426e7185c5df27d9136a6df26f54
+A = -4d108217b778694931088bc255d1f69cf8f5a14252156163f948ae58d58f2ed54f518177d668e795474952c930052c1bcfcae11bcd15af168ec2e881e6ddc8de257d0cff90ff3ad409bb3a080d30fdfda99078cc3ad8302a4bdd77de66ac082b40fddb3cb36c75a86bacaf60984a74a0fd575d751ed2830650d85844aba9e3f781b2dc6b515bdb8d9459b083e1aa653ef177de76282e86c99e97dae9c0b050c9e6456a051e7d99adad7be4e4
+B = 7b9079504c635655a588ac360955fceb10cdea5f3de548ca2db681da38c17a70df5798f72cf18691d14a5f400ac69fbb47e64115cf071466c54bc7077a228249209542683ba57791352ef3409f6a947865d8f234ea9d39491b5c001685487b32130bce9aeade97d9537afe3f2f87e8f3315619ef7f215a73cb724f1adca99b90912aeecdc81485c0d00a74387ea99c965118fc6a9af1163e60d1ee6a1eeb12d7c2bb9a54f747a415beb5873d616fa0eafa
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = e36899d83a143c82e19e11494ba18478c0a9497fc89fd83df38adcb6b33918645a416626409a156899c6583ab9a4426438d9c32cac54b78df579cb7b6b1feb3f39ca4a6183743a4b823082896a89f9f1722be842cb2d2ceb605f84a9f9b61cdc7e184593fc2f9ff2994fe6cc4860d255809d04ab47e154eaec9ecc807ceb298
+A = -1422272d9e91a14b38b3e81cbd9411a0cafca23addf4f33c94a1bca70603db879dd8a9c0b95f5986bcb447731219c4f9b32a1e3253b027b7963ce40279dbf4008e526adc0bd7bcb2b533392a105c6e8e1bddfdd2bde7dfa0d2e3b1c6ffa07fea07ecdb9fc828283e93b0ce4861945562478b1a56de32251b7d31f9a2309488f7cbdcc38cd6b1c951570675ef0d61e1df69fed78979dc755f160d93ab5a3e65dc2944d3333cb85aaf87a153a90fa
+B = -2424fc1e71286ce3be684a10dd885e4891b52e9009c3021d90ebcaf68b6db81130bdbb74869cbf142e0f44ae72684fc12c85abb5157987428c7812889beecfd7bb43fcac2eb6298ebf1dbcd2e70e4274841c2703b8685df18f6e5bbaa1422004797defc6ba843e77f891bbb46699a863bc1d77c5e3cab809c247e2975e8170da00fd9c8b232abc3fc6b16951ac4e6c96f9503c1ff2d6832ff9c35b2c8aa408645849c577d2b8599ef520da57fe2a9eccfcba6
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 4e8a59476d47ee2cd0217bae2981cf25a2c38e5f5d5c30c2d8bf95856a6e8f42429e565f1836365e550d85207246514624e7ed932d6f5802a50ff9f15d500dd84b27729c1717a3df0f2d6dfd40f0094208445193ba6500ba03fa3f4bdeaf9251aace8729b32ec3215bcfa170575e26265fe523cf44a071470e3b1547901e9227
+A = 452cfc78cb9597e67aacd4ec83e5b473ab8b7a1dcb6097fab37e25d5a6e25c69c73a6c20de0e2a744375bbfe7f612036e69c7a503255d9e17c6ec1dc6cc6f634d4c79bed4764496e5c7c026fdf9408242d3b234195e67a5681e7d7b861f58eb631ddb9aeeb0e5b3ff7a7657a7fde5975b8a9e1f643893bac47debf7918c7ef8f6d7439320dccaf63b80ec9761559078baa8e35d98fb9dc242ba83536eef7ba9901395ef02b19990d8312203df7dc1
+B = 1dc222e7a737e6d97a703fa232defc6c0a4fb2bafd247c8e547b9c474421cacb7692ec98f94be19a5e40269e1f5713d06a6d081a943dbc667bc867e481b99c55e437061cd44c4482649faf870d9347e0252ba9dbe116fb4992dc2c2a0583c1351e9e01e71e9324f5fa942322485bca93c2d95cf304028e68224fed446966073ec7326c93ae326a7a533a36e053437910418bf1761abd9c4c5ab7e6f538e9bf963903e6c80f21a0a38a683e8166e4626a8d8b743f
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = a4d5e9fb7f0d75ce41ffecacd2ee1e4d15f82dfd4decf5ab1bee75fb97792d0d574fee60a30b15af80bd38e6a25b1821e61628dbe456e39fea3f8a9ee6ef3d2332412be1500fada0c1728a1457656eb3e9d94c64fb2d0ac89f10f2b9ff57d73207274ae7e8c7538936cb7241615b830cc9011d4363ef88f51c7b3ed503c25179
+A = 13eeef030b3110451fcb1a258434aeb51d3dc805b38c72ef7c79d4b0e18d600e5dd28b552b59f3dda1898367ec7da5dc6d9089a585cf52002eaf8f9ec64b8d3ec50d0bef7dc3faf203c48583ec89757cfeaf888ec4a91470a6b8ec9f26a6b07f3311b4fe972cac2f2ffe47f5c11d2dca87c62680e2229120cba4de9cfce9f7f5c33af8398c07ffabac1675de1845e05a32536329647214e54e5d9216fc0cbf2730898eae19e425688bf184d16bd1d655
+B = -ea324da99252edb03f40100e528d9a5080c43be97fe4b7e03d9563ba48040d328e57d0defd4b7ffa9bef3ca0d2682aefd2a0ffca8566e755b11f2e3c6c1b707f1b9465592aba6181e583babd5c70588e7123361a8ae77d8c398e33f894ee288babea1d7eb63e2f3de469e502b5048417043c5a9a9a3eb921cea1533162e3ce9c79e6caf62bbe7e17b180b72c59b9ef5fe1a001b733d909a8278029fb4a63077ef9b3545f1159ad73dd75030aad599ea4884677e01f
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 2f096fb8fe2156c41ab695956f13f0fd9a084f87ea5f5b1acb6b60c62617b8d7079f4b072223ba18cde474af3942599fe070ddb0ac1a99f42b9506a2648e1b8f6106015aba0bf7a824842403bd3f4ac8b6fc4a9861bf0e8ac59be0322f0495e4b515fd579dfef273160ddf96e453f4ab663e703609c709fb1f016ca919fb26c
+A = -4212bf679cc00adb2ca502604b71dd5dab99cdfaf55ae92aee6bcf8b3b6354a384656c09eec6175a95c8cb4591ce118e783d6344525c25e5b356e45802ea3ce1fe764833132e6b7bec434e4481c9cc2986904988bd8da7dc2e31cdc481fd0e359674bbff524124bab1ba4379885a6cfc1b73d953e6d1aa1b938129d74fac9dc597c31383f2f7e02fd995f7065290a9812ba8e205316ad5bac6fc65c6c7310f1a6b033503ebfe85bf6d3851bea1b65b9c15
+B = 7ad83f97f40d5be508cb394c128764532f0aee9a108eb02840ca1c635860b6d751d5f676e8670e2f61466397e1bc68f97ea52d64b335d07aed22f20bb1ed19e3e42e4205d650e6d37714c2f80d39b111577725e3bc7ce75bd7ed5e44f8377d5fc2b97f05c3c1ed5ca1ec90ba3ff7935a25a8acbcb15fe1fc7aeaa1e444cc2f06c1e6711721d24b8969d465e4958cb87924b3e0fe99ccb371009b5b15747bf6dd5d0fb73b8fdf58d955c8773a55424a34c741406f6f904
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 909626a69c803e9acdca97c56781eb672d6fb31430a53b853f467ca26d4ae96c182d71c0212894b776c88e773acbe9602e3ca56584c39b5947724290def7dbf04c6853a108c1282def95dbd5bdc015b68daeea0ee959b35bc5af98a4ae4cc7486e627bc9432bd009b21ee9af3085f074a3ae1bca879e321018e991e7898f2897
+A = -14eb8e28dd04a159c576eb10578c24fad9eedd3d8b7560b681002a54a4bce2167de05cd061338f63c50b86327a79595a2dbfc1d3f4e76aabaf88cfedb69faf5148c61f8cfb2130511a3bf4a17d846ededd4c08f3b635182dff1854e8c4c48007af028e06f01235fc2becdb32adcb9e2058dcf8f8655624bed9915faa06be972282cfbf8530bc0cf2de5b2057df32e4a6cbc3c772feea0a511cfe3408a6dab0e2714fc4cf15602ba0da03bf0016f1f3f5ddfe1
+B = -388da160568aef9f82fc16f48a22e8d7aeac99121cfac9b748c815e5d3a823b673ddcd20c1168f98ba204df5e52535f61b224fc0374092f8c834321949fa0a812b5e65c492fd9fe8246b74143a943bcdbeba16024e311d673357a3dd3eaef9ae3a72bb06e03e34e091cbe5b6a9eb9fa3d7f36c03baa5c3e242f2c186b58db5dddbd73f6aa54aae027529b8f8f0a536b9b283ab08247b9977a2ac2d0d9f162ad03a2fe247d2c589b1a2d14b5f90d5b9c0a95918ea956e261b
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 128e8844a2f04704a4a60cd33e85cb7ad373ff683abd167894a35a1daf947f504c0abd7a614e293ce10797a5330147c88c4d5e1dad1bdbeaf74095e3f5a515f2af68b7bc11ee1f53b493133905b654318dcfe73118ef1931eac47deb6c4958406b704ce027d9b027803eb8e639b52d5983094b8ff4b54e86a7dc6ea169ff1af4
+A = 75e6b045aa44dd9b8f4b434dd4bb1346fcf558a5e96b00fef9b6cfaca72fe8b1672edc2a64beee8b959683b1861138b297629b44a0caec6bad2ac05665728379cffaf66a129f0ba40aab7c6b1c3fbdabaabc87ed3dd580ba80ec7ee765e9a8fbe845c0d207eee7a1a3a0c39650c75ccb6bcdae2e0d5149991dc3bf899ae9b7626a2baa17b168b260d82fba84a12f10e09234035e08b730cfc230f0d2651c03e34d4952fca6409b5c6ea5d8791c90466bdc4adf2
+B = 102fc193633b0e60a48dcc17aa76f3e52cbbd1012f179736a0ba7a102f8dfadaf434063b0ed1b1528a018b349eaf192fe62f868b538cddd7e8e6fd98b93147727d58561517b2836e4a373bb31fc8d5e42d16126ed80b880c1a37940c138fc1f7255ee0b7fd39b1b799c34e5178580cdc076ef3fbff65fdff7497398fb1cac75e5c09cc7df1168a20f88a16e7b3ac78091a90f1169bccd48c0d06b4707ab79b741a168deae5ced5d48bb5f5dd3f465e43c82b9db7edab24569b2
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 9aa9699d1e5d2c6acb21e31890c1899f30a925b834adb5b8bc8cce83a1718944a2c90faa71b34379a21340457478c0c43121dbd65d62e290eda2ba6230bce4e6f18555a1380c7c95c1700793157f7c1cbabeb09460ca28dc596bb17851ab2ba6dc6bf311ea69bdb7fa8eb78df74adf171d4677a154b8536f8104d919bdd58648
+A = 157fb9e1b38f288db78a1a0e22fdd9f48a59779487a9ada2774a094d34536b85993e7b9ab6e24f081c4cdfb64a82271100a054169e4f1c24e3957ae9aa8300e85eb2a45a6d5987eed4f0fba6fe8557cbf6128e018c5f9df028131bbba6c544b2c6312aeddc71405f0e4ce648fbab9e5d51685949408e4ccbe06fe501a36fc13ee65c31f062313135054b7679eef45964c77f5a1556ac09b11c496d0ba8c6057e283bdaebb4e6d9e5c557d975745f9f98a288d5bbe4
+B = -82cb6334479bd997c771e894cac1ead87dcbaf8f5006be5c70ad48ef94303137bdc45f261af91a201b276a17d884a56ff27af7dc06cc5b7b9c94f7c4d4a36f68f8d309c477b4969a6e7cd1b2afab9deec06555cb753d8a0eb00965359ef865a84bfa87b815a42b2050e1635d5ae5e3743c007bd79e820aa37a968702a960fafbddecebe63f022553cadd7a4d4fb27b4dcb981e8b490e80bbbf13af8c4412d158775db71f5fbc9986e7b8a8f9299574abf7bdf9ce7544e8c4e85bc
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 46e401989fbcde9d830dc6e3c42768999f153d44d270d4805c5beefb470bc1e82706aa7173b359763c5e15d146eca91a32a36f0a80802871933cc7f2ed15a5472988849a2d2f57543345b531538db57ab9bcbfbe787efb0a82e61baa505aad628df5f9e881dababb35bc2decff267eaed3d3671757ae1764ec5163b792b4db3a
+A = -590c16ea2cf7fa7f63b5cf74804333f22fd2d0e1da7d226da8425abad2b39a4672fcebcf5cc15d220b0ecfeec09665e682fff0140f16889f7a6ade9ec11aae3fa3a369b3fc133babe52e42b7a8bb9a24777521f4d9e0efe7d7977dced9e40784c24d2c6056b3b668ada7856da71af73d2dd33d2e481ddf40999d86a6e236d0d73f31a67c52cc8b38203bb2840c0b92c2612ffe5fdb6be87f9a787d70b3dd506f9a63d144db3417495f0a48523c812d14a89710d95bc6
+B = 5a2865cf2254710a1a51ee3056b0c1f6c5f77d22d7aa8f939e6f48ecec529a169e630c554bbe682a8c4de9ce4daca77a278d7e752cb678141ddefa75ba42e661885a82ab55d699414ffeb75802cb8f4e7583bec8a7ab58803b378bb60fd46f476ea490c9aaba568ec17f3a6afdd6f20ec54a512f7aaf62d2f941e35b4b72dea77095e863dcb38bcaf8777707c1dd437ef2ac6b6a8b2b832f80ad2a6d6f279c053d02058b1a657a1cf5b6b269e15d29087b0cfc0c2d4c3fbf32a167a3
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 1c9649f4540556ae82ffd71b2c71ea8588aeb845c50dab595db9f8faa01a26c809d30d8433b6c0add465e164cda2b6723c942ee87241eb7baf9944cae08babd8e22a0eaf35c09e9efdfb9f8bfa65d53ee6eb23fcbe1d12a66ae05e7592ed788b231b000f895d098a24febcfa4372d249575926a5faf966072f29a62a401ec51c
+A = -1bc9ae5fc2f6a3f1274584bac1e145f02c5e8c4779f4df15e98dd34344c988c1437ee4428485a09090d81b18606a6ea5c1b9136872ab5b37373fbffbb5b3fa8fbeca1e112b9f1643658c2f38b9548cd8f0f271779ce0acad403177057ea0a2af2e7435109879941fbf463488a2522b831b95c1cff21d2d816d70c25156369dbcf04a0e28e1d746afb8a77713703fefa512816fe73e203bb4c3428efe09b946b750199bd7a03d30feb90230c219a103ad4528cbe0de1e5f6
+B = -39cae179d955049f830867d4115d3bae25127c945b1fa0c16fa850e8fd77c1b3b9b7916b9983c1659b7cee77b7dc72abfff1c56681b7931c5e58cfe4f1bf0168ae32df0df8f652223885717a98f858a497b1a4be62a2215c39316c34451b0d957791f49139921d9ac8041899b8fdd5d3d443547a26ddf5748147e4c3e93f5043ede42f38a9baa628df65d3d6148ac2ce182056700f0f94029be05d3ea3a218b40f65a87b4baf097fce107c080de24880259f1046175db1297016af76d94
+M = c462c7cdd79b7604246a0cd97c017700feb25908656b4733353af8119ecfa0212e4bd24304edd566adb5c1e9daa40894290a9e2e20d523bfdb5a2603409b312cba43d567a27118c15d4bb2f3867a7ba7594e02859850b77b929823049d43573a881948d674e95c7427e2d04d4ed81b5f4de21e0d5904c8e0359c99d4bdc901a4
+
+ModMul = 9fcf6a47addfa336557749821a88ccd2573a5ce2c3094a17d9a29b33e043bea165499e89fd2c939f17a670694aff05e9af46836b62c96e597c83681092d63ab9d6e22751aa8fd4b9ea94a90a373876ef0f6514304a495edb5ca1795c9ade7965c70f9aa92f8ea460ccb670e9a62c81e9c
+A = 71b93fbad39b1c2755f2051ff7d532d59c985756410d58aed3947d6ae737ace5aadc35e7e0d29c684b9d4bec9c0fa277996bb30230f70431cb7b905
+B = 167be8381a3392dd4df62e150025e13b388bf366922ba8632614928922cc290772135857d1b5234d51c27862cb1a055c1b86260b6ec
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 8e2ba940fc5165c6c5f7f4cb55cd89d1d5f59e90e78730bd66fb120a814514784879dc43ad4f355030ddb3486a59bc34b601474978a94ddbceafdc0ee23cb18708bdbd824d37cc32577802ac6057fef29a71f168e816309fc80cc46f251e7289c6a57fd222d5868263360af63dd73e7c8b1dd6b3f3b6939849580b9231940a4d
+A = 1220ac4bde4feca135268550ddc79d8b05ff72f483b39f77436f348c4f5360c22c598f7dfb76697bf6d2ae86c68e90748b8b729b25f932b2e5fd33f3b5
+B = -bfee56cd412318cd62e7b6cc49217345d3a94e7fbf6fa19053fa685efbc0f8b320b7e43883189396781c49371dffe7d126c032d1ae4b6
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 8e2ba940fc5165c6c5f7bcac0e449b64801e75134a390f120acc58cbee43888f50d07f7aa6dc2b33643c025cf745434d20eb1aeda8fcee5fa3fa5baf10d67c21390297857aa50bbcc4a29a6b10885f97fea60f1b88fc72512c111b938142ee8d67545efe386622162e8fd50418b09769b8c22efe54fdacd652580d609f0528bf
+A = -7bc53f6f2e78628678ebc8e35ae4905caeec61acca5c64fdf595689cf005bde2265cd43172802fc133dafd933d7b48def44256868d202727a4aa6c0cde66
+B = 74147c93e729707111d0d531b1c135453f3e59f63a7e082b43dceb8b16cc5debdb6d7c0ce0c00ec9b5ca51e7673e411c3cab34938124db6a
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 43c47d7e319c32a758360dd726a1d91e2cf5c57f73cdf9ad2040e61a9c282a2962d96d300e04288461eb1ed37df19e6b88f104a250f9885898740f6487b081515314e0a217df2d4345d3cf81eabb2bfb346b634b9c251624748f6e9407cb677aff4c53fcf42cc027de267e6ec011e14bc7f3bc6666f693d21
+A = -1e6ce0b44105047d0da0eca7b936980267db41d41319dd5315889fe8fa2329023d7cf54f71ee179b5bfedf442cdad1920d311966f7175cbb953bb42ee105393
+B = -23a330c7e06cdef4b6b121d15a9c0bc774eb5e432e72d04c5f03a0c588e55e010b61f57c03c51edb1211685d8dfd2a35393091fd0e3ad2304fb
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 768293c84c431b9c8dc6e538ca3f856c60ae5e1aaf42325865418b7bed16c7fc2589968319cf41cb370657c8edc7b969de10e0566b64ec796470b630e22477e7aafb38e99b6012f100c9d23d5517d486e3cab1fc60c1568c0228c9b55d2d77d23b1351fe37ad4fbf9c07f29330a539de4a32709d043dfc9e21aa1a
+A = 6bbaeec78b6a41818b7eec42fa3be7d639dfd86fbace2bc14e0369dba6dd3f04ede8b808743d809f43f70f1146dfdb1d649546441919e27f1f7a9760da4a3b152
+B = 1199dc2f52868a0cf440f6666b576541c7aec1e9cee14c1d22010ab0f53fe8bbf3029c639ff78d89dce82de85fd8eda4e67395d435df60158623c5
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 8e2b90afbdafa02ce68d537ae807b4e7f3e05a66b20b84cff309941fc3150f99d083841ddaf6f19f5a76886ad5d853c73051a0457e95eeb0fe3776a084a027ee77d14f3825713a59622ea163a679cff904db33bf6ab23b06eb4b31f4e34fb122c8c170321164439db783e7bec1c265eed33f33bd9cb6d1611c00aa18a9b4b90d
+A = 1c4821515167f7073d4b7cfa318ead1da1131499c12497447846caa84176a9d4af576fe549fd8b0f77bf8dbebf6c395f84dffd40400101bf28b1dda0bbdcc5da255e
+B = -de60cd639044e863c6a49c73213dbc2ca84e4225aefa5f880e829f2d9cb48ae92e3f2680c462ac697dc34da38f65fcdc1b4d8c3c99e8cbe29660b539
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 33e8e8e193b4b99d8bb382c29c1fc5403190d7654f43cd77e28d1bf77bc3a728dde9de9a89c6522ebc7222d25f46833fd1753a44275b04485c77b675d816090280b3541ca61bfa33921a79f7286830131d6eba13acc46cc2c449b3a359f1cb49d67a4d0cc1245f3f8b59b1684aa0c3ff1c928b8e880a3375ed811dffc991fd1d
+A = -50ff3e00feeb2efc6df6387d6409a622b7a8297a717b8d94d0dc41c6ec6f29a8455c3580019349660b31dea1e4f66b74147de93535e671c853b604ba06a9b62d34646c
+B = 49ff858c7081392defc3ba12ea8869fd61188ff15d9339be72657b00530b851de53b1fcbe16034816e73251fe1ec97bcecd8bccc470373974287ca328af
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 2c88dc40414969e8b614bf8db05fbc38fb2b7ce144d7e707f9f8eca40ae2309c1fc67e713a8da5fbb20e808ad20aeb369cb72a77fd285e38a7895ec0fc795ade4ef1f1680f3a3b3cee4569cc9d5e699984daab3385815d2e515ba5d67d21dd1defc12ca81bc8ea645f8f8d103b4a0a9cdc92eb50690c07a037df274bbd5217e4
+A = -167ee0fa8e5d8b569d7848b068df06f6baed80f6fa6a442f9d11d9712622b512249b92c7ccb821ac751fe4ec0a7a47e04ea5571c7cb45a7985749ecdd87f0c0faea01d232
+B = -2207fd8dbf2b8e9a5e3cc515479cde241dd3671803f9fbf7859459ac66705be055fa759c85631ed2a61139657eee7eb08fd963b49e33666e60b7e75dd26b5d
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 674885ca3ef617a53eaedb9564cf96bcde131760ac541a81f4b25c174a6fe1444c2c206f7171e343e1bb43f81610162994c497419e75aaa25b664c122ed2b27640b45bf646fc5da1703fbf1cc66e10a3c306eb69ae5f937081a1a18dfc8db376ea18f4c1c499109b0cf8806eb32cb1f28985da790047bd7b32c1f67bffb9761
+A = 413cbcbbb5851a4ae12555801f7f80ccd888bb82ef1b5c31b99e1901d7e0ab91ee489c84044bc21fa2010f11aac21d0531fac09feb482fda579cb9f224c3149dd6249b0225a
+B = 1b6bfea70f1d80350eeb45f9a5cebda954d72cf5cd27a299ef5a42e1ed0b50a541d1657b70e50b0cab69b22e31d0944fd735957b1ff764865d9385af302bb802b
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 8d74ba5fdc67733ced4d468f6eb6ec4c1ebd79c97682c1d4daa06105788ed9c5144992e555d903804d7ed0dd9b29ef2648568ab7ff462a03e0bceb5482485afc3b91448fcfeba435dc587db6f3a022428d37fa0e85392d0e48e7d4ed6b21253084e653da8175587b3b709e28426cddfec8d9dc582d4ac2f3d540305c0fe17327
+A = 17c0b7f0e2cdf316e4d32f040e26d41dbde1e6689d98f0652da1c380daf5dfeb6a511b72d82f1b32d3852e9aa2f594be10776a8fc89a8a35c160e8e41b42a06a342fa1c309fd82
+B = -d7b7701340c5a358455ca5fa314ad83860d9f765978ff652d7f542de2e123bb976930b8fe84b9608648324450d8ed2bac4e44f2fc71711ae813cd8793af8d3796e8
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 57e60f79b4e156ccec4c253e70df8d86e4aef326150d612a5ac4dc285761e88ede412d28d9dfa5a6f5c073d3c91a65ba9c86067d81f296935f0d0ebd2af82e7f6b5b336422429cc3b8427fd8d3f5a6fe936f4208362632093bdd3cec1aa8f4b176d260f605caf4a12cc011f3d1b76135ac2507346674e41673eb16c0f55d8010
+A = -4f1568c207a9ec970b5c26f068f3cc8019e8cb483525d251cd2919b368d072ac8f40017a19fc7437cf88e927c9e7d6f539ee84865f0af24be0d6d98fb33d74e3e0d28020c00bcd61
+B = 723db98a78f42aa45496f31cf78695583526d25e167da48ec310e447ad3540be2636813a2c2f7b8c622795ac451992e91bb8e43e5737f0dd95623282e729d815b08ed8
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 237eb5726e2c628a515104bafd44348dbf099569815784eca5d6a415d3c12421c8c70fee23d6d82f7b5b136b70ffed3b6d9e98cb47854e79239d96c26f2ec955e4ea8dabc29a1b0765c9b7af6ef09ca673d1ee21c680e4b8cfebf47bbc74c993d017ead6cb6f3319ce4de9e9765cdb3ed8fcc57a1b153327e1a6a965e5dfa89
+A = -1fd1f634685eb1470dd9080529a891253a28a0b31e15c662733e20d43fc4cd71f4cfe83c3774adf8293a0fc3bd806d0b31b61c6ed0b4414ccdb91e2994e22797e5771c63defcc0887f1
+B = -3ec0478afdf54c949a097ca411be41f931acb750ef4f0ce97d0f0fc77cf15970cfbe24b170aa332de04836b7a0e6c5d456814182d27c8310d5fb662a818bc421587d95fc5
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 2f1d500443fc4f4b86e7ec93e4d0dfd3faabda35a6dd31445021928373be14c37fec369ce80ebcb77aff2151b7ea94d21592da1823ebfa0af196f286d7a69ea54799573bdcd4d09ca4f33b8a3a93b35de5ff7f65099d59367914f1c79440b471ced6773b0802bd8ca99cf531b62892eb1e78d67f8210592208859b0aa1754b14
+A = 572de2984fe2ed0d5ebb5bc3f62b197fd592795d91cb16b48a0c898991ee3e884e5870b92405f248036ef9b3898c5ee6100a09ede5a48bf7edf3a067e4fc77e7e6bf6a6e3d4f538e3d66f
+B = 12c379402b18a34dc8b80c0dcd25be16c99d6f76d5d64b6050b90910cce594bc022794640735710c7ded857ebd44fe5b2e51574a2296f7d7a61b59c0123051bf2ba4a168cf8f
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 4001c734e1391a88640007893f167eb79ef61e4717d5eb14b8d80c25ed59c753be63fc8e54bdaded22c9c7d3e49753eb49efa010439807dba0d90ec4f9b498aa97f109af542bb41922936223213ddedac4d0fad8f1446498f4228b758aafdf1d9692f59029c76ca2832125ba50e811cb95f2b982a7a4d87b4726e6dd8b1963fe
+A = 16792909716b581a936287d0a8550a1f3e840935f0f3ddca75aa32e3489269b078fd19a16f8d6b2326eebaf46da76e90890c0ead3b35689bfda8c1ead17a4f672588f982cfd3da2c2b9bdad9
+B = -95ab2c47f85001aa852d6999f29644a6a55f9e4e12bf905f911f90d29cd1e4fa4fc9d1a2aa6c215bcb5c5643561499aab8f2678fdc5fa9c6ec138aeb2d62f635c45f239e46b0fa
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 1bfad44b58d3f8bc987116d4cc7ac98f89f838a8712d81d726189e9e1469cf46fe04675dc0b82e6e556b02c350ef4e30ec6203c7f1df937ea80f435af7c10f48538fe7755ba78993f304e64ca0d783b0f46f61bd14fd3fd30768f233c59018ce911a94b495f58eb96438e416ca3c7eba5b1bca9dea5a770c1d2d9f2f62f821e5
+A = -78a6a6ef40e443c52036e75f0b35938d632bd45aebf45a1fff5c2e1b6f601a57382b9a82c3e8b2984e643eb1570cd83f3a6be6daac567ddf9f37bd96785662bc3cfee6f47503d239c77781a8df
+B = 4920f870cf9f371050e64a419ebe07ac92dd3525b41e8ecf6939a267e1ba853d54862dfc95dd21b3526eb0a0a7a7f8fb67df2e9472dbec81e15cb13266257177c5f2b92fced4cea5d
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 6b0b84505907a5ca37abeff9a5ba169975792c69b5751d9845c0f09dea833fb679c8dfbf3895bc470529e0cc736c9b4a0d08b75d709a1d04525ae583c5ba082d3bca1355055c7bb674aa1b92689cfdec4dbac84a96e81c855280e417f60e7e4931ef4f428420c0b85d2cd11c1030a47788d6ee6af0a76b5364fcf23b270e9d4f
+A = -143d843e3b12431fa0d873815a757a214cf731c298db61ab13cb87fe78b0a6184bd1fdcfec0c7661b10775b4ee2c815dede0ed497977c9ec5154f7b24a8a786501ddb8dd257bea51b9fd9401ff760
+B = -25d4da7b64f439987eacbde66abadf0da7c1653c1c1c6d9b2092351fbc714a20d2d7ad8093209da371150b69b3602480595533ecc1f3c5005a8ead10732272246d8cdfbab87c49e65223
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 6bce40524278ce242b0b5292d27751a3dc414f962d9c1cacb45fa3ee693ac6890d2ff1647abe578c40ea8d4b326a2e0e2fa7cdec28fe2da089338b5fed91c4277cc5be37537eec2f17edbf48a45fbe38f15c58c3e733d408d001262dbd40c9d246c323e7978df4fb7207aa9270a12921743cee2a483e7e71b221b09a6b2c667a
+A = 402671b0cfe14655bc650bd35dd0c36ce7f65de274a0cc4b708c6f6c3e84c2125ab2430e702421904950b29aa8a03b049910305127890457cd0cc97a3e05df67f29d28b0452969986959df02f59d207
+B = 1648c29205f19fe4c646eb62e8ae9b65260c2cb8424a526423c6bc04ed55870cefef9b8ba808f8ed2e1ab170e2e411f68b934abb1a22776969f79f9420f8bcbef28417582942e26646af60a
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 40db38dcdc201648da555f1062bbbb92c632c29b66902eabf90d98dec69ab3f3b28e60cad1571e7246f4c9e6aa62ad26a6d0bc08598c7a8571fa830cae4c2875c5c95a59f3295f998681edba7749b7e38cbece8887a7823b4752165e1a897e638836d408f439f009d0fb6c196e83e83ca3289d2bd0f0eb36b721331e4f9f80fd
+A = 14361ace8ec5223bf0165b78913b77ef921b7089bb5e28891d120bd3db6513ddc90404a4e6cd027f9b51fbc02e80d376d59e1f2b043954199ef8218bf26cacdc5e749f668ad3b4ab35cd796f94c06307e6
+B = -851a39d8b0101fdb22ea9e367286e572dd132b8a77a6a14dd0e995131467aee898230f37dc6224e35bed2eaf459aae579181a161450bd7ebe6b62ea7154a8a0ab590ca4a6c2f05531c4e24650
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 4b085796665458b798f824d1c1a88c23ecca456fb88713b433228ca8735141a616633ccec4bc53ea4f6e0c74e4aab6fece2e4cc4c4efb479638cf54caf55d4addf75908076f5fb487ed00d540e5b984acb8f81cae3ef51db926a06382a288092b352793de721c23c371fd0ce7a789486b2e8b867d35f47b5daac2d339d22dbde
+A = -511565611538828ff7dbc45c273fe46f4f5105d41ccf5dd343b41e9dc579429e56a9cefc54657ef0422960d1375b72411a5cc93ffa323455e006e242580358d6cfb641f46b9c36fa777a613b17dd4a187454
+B = 4f22597947638b9a9e9b9b7c2a8d37f77259f1bb1c7db65003b6e1a1c807469c84c89a75b80bbe0324fc3aeefaedc6ad9c0d9e470dac9c30bc48f6abbbdce9547ad7624f0ce9ff3cb6be23e47bc7
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 2b90a57349ea94ea818207fe15c164f9d3530c7cdffcae178557274552f79c4ab56acd78033a570bd6c3e45789704ef0b0ef586594fe4cae3ccfbf9ceef46e769589b084adcee3ef8345375b7103232465b991273df724964248737d5eccbac558e35e4190112571d3e7c291baa7aa8b1800121bd573b8419f627c0091e1bba8
+A = -170cc62ad57094d307ce1b317ae5e825c2f2e317ad6060437afa105501caea00dc9a86af8729e2f3c3a854387dc3ba368c0a84aab1a527ab34fe27b0a69bc71c728cca87be728457c65eea7d7538ef3aa282615
+B = -3d9da1377a88f647de57ade46dc7caf71b4f42bbfaa5e77f16cfcc90f00b5d3e9e9d82355104c7cd0db4c1dac0496be3aa35706cfc0a30a1329755faa439694e8e9b41fba8f1ebb46140818c7008e27
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 4cd4da762c7576d582572d3427abc4b4297f740705fc14a32b46347541b152d0d1e3a11f27213badcea1e2009e34a63350c7a59e4d43654b28298d2757d6b54c4d82f580e98de4230cd119ba350416452cd4b8adff29b9f35ae0c533f666cfed716838e2b91941dfbea8d6a978a369d5f27554ef411f15e5a89850655d7f3f5a
+A = 4f4a28af27b926d8ac347503d6ac0bfec388a6c0b38a577501c3ca4aa709c69601824ddeb5eba4d9e437a97f3e4477e1487d5ce7b4a35b90fb863657a5b2d901bb8c3c838db40b89b495ee9875e8eee607d7b8013
+B = 13ca192603bc8b2da29dae67159e4f8d32f351a503434ed9e4e24f74abb5908ef7da80781c71b1a5ce64fefd13a16cc1eab05a370bfba2a97e6cf90cfe98d3a487ba72dde0762c36c10e1da175f1c1b5fc
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 3812e9e835ae355fdf328b29ed8b86dc3f6895e379b8b5d65a5de41eab5fb20ad3e2290c8ca69f9500248ff883d9715f59d0db6257d13c5cd612211bb1fb99867161daffc77968bdffc1fe48bcde0fcce02ca93975b3cd9e93b56974ab4beb59582c3d0ef2a65957f701549f8bf858de0c5bc98af3e5722f1450de391876a2d9
+A = 14ca6101af00d67139b985ac9f149accc260336237dd2dee802b5cc6e506e217b74c1a007ec10c20012f071ddad34e7407012669109ec1f385566ff04cf1a1ab7562353c0af1ba1be0baaef920a188c60db27970f64d
+B = -94b683326e9de19e414f653aeb2cb4bd7b17e76a23de6a4d91c43d717a35e08f2155b444a9549dfd01a8aec4dc901ea9f629f16bafd2c84828b12d2f63dc154323eb2d54938895ec4c9efbcaaede274fd4ab
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 5ad7411cef0581b2e675d03b0ecb9969102a283eba5e779bdcbb7646d94e843083a07269c932d18b973b57abe54eaaad0aa76cf7b61f30505a263bc95aa063efb264ae829eb1d1d5f7d380a0b4db59839de9ae6230ba51901e71b3e3d59e8c34a79678e751c8b7ab139123bdb2f04d90a18ed81d2046ae86da1a73c8dae4fc4f
+A = -469f61cbff01f0e4124ba69a860ec6dbc75cd758dd8ac7cbfed97645b16488a329adee62d1a66e90ee4212569d56d58b61676262f49dcb68296bbe5d8e23853e3fefe8a304710cea568ca65c183531a992ec5b4d82e226
+B = 4a0d48e31cb8c24a3b2c9c95fd19edbe46823032ef4c97fe65d0a30d5c2cad7a4fbbe89e0ebc9940ed9f9ccb8ab18bac269759a9740a7985809d0f38259e680f0703febe7fa012d1ded47f0cace4a133f59a721
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 2b2953981db406ebc544c39dfeb08a8b089064533221536c7fa2bf2a7a0d3a1192859b7dc0ea5036eeab5aa371e3e0070c3980433adb3e3a5202ff257bb546bcb9550423201a35501fd717ed4c0016eb3a675ed399340bac7f058a04e69c1774590fe747ffb9c27e78ba50fcee30ce533a1659fc49dc080a60f21357a6265d24
+A = -122621d97f42b65b060c84df3f0c0da097b5e240731b77a37bb9471e7e398b242db6f1b5e25062a9bed702860ccf6aaf386c1d6fcf60fc31b8c190d3486949c5772b9e621b863a7cbf29449ddd68b7e0c21e669492e58e94a
+B = -33978406dd30ec2b192c416e422428683deac210017cac9e4355e8446d6969295b0fbaa8cabc92c1fc0068da70efa047f938a419bac160ed6f794a9f69f53a88648c9725610d5f309b652f5462bd3011cf68ea859b
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 2104dfef151526e072c09a4a277eb981a035379de3b1a55a88cb060681706f26131c388f5572c5646826b119c85ed450207f32733487e3c4e1e9d701a65058c4b4ef0cd1db090495643038229ed177b54695ac32110619038f1c1cece14faa693d88476e3d70329b0084d0ba5d547bbaa5b59ba1ce1fad5aa2f1c11a75bc7c0
+A = 7b79e6f1330fefffaf8521089c3348593e40ab7e8d4da3d4346571b43b12740958336580afd13619be3dc2d42eefd9e30599405da3e32e7f3a5655ece8b77a367059668021aa092460de75e627526da08e6206b0f8f539ef40e
+B = 156e234931907c0c0970c1fe6bd4b24225ed94d5f5b1be4693c8e141e9a6032425b4a47b6eac6265afbeb9d796eb230efa707d5ac4a73808225181cf814b319142e9d175ac461c75e6d479bb6bea53954bb981062eb16
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 2a392c5fc96c29df2f5ae9eaf76e7d981dc1e2f3b47b43a98eaf556a9465ae8727c622188123c64658053ec50c25e54ac5c6c8bc279b134d326e911f14c873357647866eccb4f9038ed0cef5082c2058ebd71e1619f7c8f8f2fb80871ebbca3fbfb7845bd855d307d2efd853f1bfd467fbe030862f165e53a9cfa633d0d3fa23
+A = 1e0430e7cf15173d00592037e83e717c90d7dab4f54a5b2f0f5772762fb5f56bc0b2a53ec1bc3b960afc35e7b043f9d85d0af6c29288486af3e186e52bae6300b58917647231b40a12648cc8c020a797683a9bd7ff34eb6d41b928
+B = -e08372fc766eba6e0ef55a9149d700b503e2e3f978c8a397912e2735d5bcff69c461561ac0822c44160c7c1bbf722df421b74beada57462ac54a9bdcdb42d6a27b86413036ed2282abf62800fb2518a32a4a135bc948053
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 2608f68632ef14dc3979725c8cf1a0db10a1651f17d91247edfae9935b53f6364d233b030eb99871a87b7bd876ab2cfd5a643387a7af9d337e81770db04a14f4f8dbda2cff604838c9af9a31e8dccf9277d453176589ba33abf77855b9501e63370b2e6cd22831e1e70ff1815302c0a026c70042957d08e74dfaff940a91a7b9
+A = -5d3568858c05a15bc9777af949eb01d33dfdba58439fb3f7af2ba792efe8e78b16d7fbc2a303a4c4c4be7c9d43f57405e88be54d6ab55268a4739945ef582921d2877019659dadbc76e0939f4b2cfbc91e5356ba2ed531526ed5b9b3
+B = 47f81f65ea1af04f702757c02a175a299b23cd8ad551fdb67020c50cbb4110b5371dc5790b12484e9ce647eeb24c0220a5e62aaec3461a9dcdaf1a22814b6f22d66372cc5ee31944bef33469f905458c172ec7871d9dc9c301
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 5735109bd21d31b5f54e9221bbed78c54cf387e39c13d31557e8173e173f786b2d2f1acf3966c3bf4552fe9bc802d0868a5a7632404cb91609a7a45fe0fb83fea8d83b0319666c1b0ac520169c15be708343359447f2fd37960c1e96d32799ac9394e839b391f59dd347acfb79bcc4e34e76490880d163ac97ee69e3a0a6e68f
+A = -175011349a0a1ceba11756bd528f2bd631c106e709aab223032d08d52d7d6724e8c5b055b6f97b48261f4860eae297badc1214cdae9b2500a7a47b4b777dd7b8f1006757754ff1143b637d2a3adc555f38eafbd5478cde0b04e5f46d3f0
+B = -2aa7f75d6801b04ea9f690aa0c5448906595fd28b53775059c01efe54b463f1d87c9fb4b39cb038e770f99bb995a2118b86ff8d004bd964e958c2af82becf362fb0b927c671cc3bd7185990419d26a827a2d81bbc0126e1029556
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 3b4ad19b75e1301d19b57ba9b68e0666c28c7c5c99df1d5fbbe0685dc1d3489ff39c919222719c5d8b7ce2d7ff967730d776a02b36a86064ed66a02011bab82eb575390f85f0104715f6e4954a1bb28518450182a8ef58af35d00e2fe417f07ba25dd9c85e00c3451082becd22e3aa0c9bcedaa96e6423c7df6c375b4c799c65
+A = 58e1ce4a9b512eb0632b02cf1207936d6707b802140540fbcbbdd712e5ac1426b4f36e74a9a9ddc812e572855d4fe4fca8a0de6644226f5698fb46a5f2a479dfc8b588aa8e02ddb15acdc79ed3d17143e290f1317274f425b869df54a4807
+B = 14e341cbb5f5a7f3b4dd864172b82ceed2887fcf20aae7d0598b3d8afafd2f10c27bc7456c1488abb570be3df04f43d892dc6a8dbe7621f55bccb0ee3acb1ade989a510b4e0cbe29b6b93968f323f0016d87944c908824d249769f8b
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 7fe0bbbccad6032069b1a335b3f2dac16089051cd9321f903181fad23be6853e2d209958e8c48e008be94a62c6206b34b4e994ca08b8f24a2df0e6394ea65b3b7aadb3bc43d04dc9d35a77e673c4476dedefd4568b4ade5d16f9d89486f3d5ed0566b1eb428cb0b688f10fe3901037744f278385754fca481f937cb630f60308
+A = 1cc0e3ed58090db55063c9ba11401636f89262d6ec096d361f448496e05181c5f7f2604333f26d511c13534618e90637adc807d622097f7eabfc03266135cb626e1bad20997e72da71bf2b3f65a4973dc27d2a594b1fd96b7bf7ec14b9e4b983
+B = -87871b2058d33cb67d83b6a56ab27839c6a6c771bd94e55f200a1257f2c737e39c4a0403fa410ea64e8f442d300df1c19c2f03d07fb74d94f86d26814fca23d4cd2cd3718252cf0cd8a0e36726f6e68827a1dab6bbb1d23b884381c702
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 35d7ac5cbc7e6c262ffa41be168b02a3bde9e112c512d1f68421d705ea34461ce3e0dafde67f44d44cf31d91b38d4d5f2fbf8c6c6a44ec3ed0298dd58f3d45c04346c11e57229dc3d2cdfea02c802732d9a811d7be5e81094d72172cd04caaa3c9d55a951c09f454f42add6e89e2d8a98e124aac86379df377606e7af9bc6baa
+A = -4ee01518f6581c560a186fa05c6f4bc26809c4822cc74a0bb74d5a6b0a368aa9bd0108f26113443422b8c589084ad49f919a9e7821d99127bb210670e732b7cdf610e464e300a39d3dfa7c82f90cf00ce329bc6763d7b1d4224a020095112fefa7
+B = 72dc8973f7af7122a05c90df190bbf1e39abca908c197590dc7ac41fd0712f48f838ca62a72a177a293ee6b2afa7a10c21e7993347c3df4f161a5641ff62ba123999bf1eabef29ec0d33ed0919818f4b7c35b5f41e654759fc9abdc0f80e7
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 5d83a9b34631dd6c63c05a0c012adf97b4d0f20f61907e1c2145330211e9a7e38128517b058e0a85e993c385068d1cec768deb814bea1323dbd333de091ad2cad72431f20c1e70ff7e1b119768ba44e14292c38b88dae7e55ac9e10ff98e9bcd5f0ac05af499196b4be0c6222d1a63227ee895fa6a8221a4a182a1323183cd7f
+A = -17b3e0c9288be15fda58c8fd228216bc466731d631218a7ddf1d2c9cc858c0219cb0757d3b680bca1b1964eb15031b5b9d761a8bcbd160db89be339067a2ea35e1ac3cfed701912a17ef9ea03999d92e3592e893183ddc05cbb98a656983b54590c72
+B = -269f96a4634eb37cf8a6608408128587ba45958405a29827d0d03d34816fcb1a2297f1319485439d3e8594532545086efbe4d21d31d30e2daf09b74fa8cb27df54e8f9f993630cd9a292c977eee70887158bd3fa3cfef321ef900a0598ac8cea
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 7fc1c65eade94d9de7440eb8dfaecf1004905135efd4f98257c3295b1e76ccf1e2ab6808d158d360b7419c6210c50efe960610973d9ae855c72ec0e81d423e5863c80b542ad455700d2d0dee5fc403dc01eab460c24687401cf6a3179642e59f2a30268df95fa80dcdac230702352bbf6b60acb9ff5d45c5b09a3403b954d173
+A = 7906bd8d3bebb1303c1df1fea0b2503b0abe9c69b4f4f5bd01eec9e314788cb7d44b93428adbcef570477e8ecac2a64822e481bdf520fc381e1bb0b2cdae2fe94e484cef5236dd524e4dc364b72f4c06d57f29dd3c5079e532b1ab1e71dd6a65b3362df
+B = 1479ef2807b9c23c094d0416f513894cc92e023b134f44a5333360dbbe98b8161ab899302f4fa11b470b97dca0c4e8ab7ae47e5fd0962834e6cc1763618193f4ee027f667368da580c623080de137b5869c3081128e6081b9d5e2dbafd791773242
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 730c04094b1ce944588e8291f7e6cf763c70b79cf362dc8a1bc63bb8790cd4cfe4eb51cf15a45a8464d69ddc3e1b9383cfbfd643f317108cd9ca6a6eaaea177c5c8b6747bbf40108cbc0437eb8f11bd2a0939da59b70c0c6129e2c249823897f2ee536b0427bc45035f121d2cbe7441c175899b97c490e6c3ca01539bcd05848
+A = 102cf23cc3b81785c73ac3613c816de47fd585c7d5f175185818dbb4bf0bd47d0dda9702bce97b29d66e48bfaae0fd07b47b40be2b48ed702ef21c54b10bb927f9d6b43604bec4f4b2796b44aa6b4e83f8bcd00f2fa3871dd901570e1a32888d8691454c40
+B = -cc5349a9c5280a933e87ca38ce458a711c71ffebb40bb1f7612b42b4684afc495e99c4a5f32eef1c9564c2b7612ea4cda7a0f5df6b3ec9026447dc565ca08563d46aec7ced9fc4cc5645960210d44cdc3944149051d569c9295dc50862f8f6d1f6cd1
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 1cfe1842a53d00e4619265e2fce7cb566ffbd912c9213925d01408a956af304eacb85e29fb6edb812a95e90769bf1c3d62b0cf6cd5bb8f8992391d2ad70f38a14fb9d1d1eb522aa7b7fd9f1b52790beebfc887193882377b7ce567d317d8432e1d9a908d6ccfe8d2de7de497d77b023b3959cc042ae30aefcc0229617fd2a146
+A = -5c3d24fdb193ed83f5f6a825c1716f98e3cde6b32e09659f253ca3fd2a39402b5bc3a6497ed7bc908838e93422559a13cf59156254bd3fe1e3b8600b2a777943cdb39b9d42c58043f1d587424425d3ef5f5538ea157112970ce3e09a87fbb5f7c96f1b5e65fa
+B = 675d9d2a05288b438ddcb330acbd59e4639375f3f14ac2d0e9e8b72de6ffc1d217ce62f997577f7eaddbe4603541b132cd41f2f2740363d9c331ef22df92029d143fc8495ed0152b918aed7ff22f564c7cd94fd3fe4178c90365ace43def8fe30ab05c0e
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 83ed1948276d689bb7fde814e67fcea72c4e3509c48873c3e7349a8fa1c08ae11ea4d814d8deb1021eb8b8ceec342cba5002a2ca45d5f340ae1aa500af4c7db120d0402c6cc8a840404be7221bbc46ffa10236043e5ce4415d3ef1355bde26d2d26eb7127326d4b8d671bb96a08e38a2c1dcc281830ac77202903a5e4777ff02
+A = -1be86e7c87827922d2e8a06e3cd6b64ac9a280c525749bcdbfac4856916321a964c9346d17465378251e6eada42dadf38bc9d7d87367bec94ebdc21af6b1302e520db08a64ba6b39920683725ef02b011a3e4ba46ef0eefadb98582cb911d0cbeae9c231b5e432c
+B = -352059faf97b433089a688c702b97adefd0c91d51a0395647f822c6762fee3287693e302fc5a5584a12c048dea1a320cb96fa70b5daff7c2ea21d249467d14c6bbee15a1e94c030e908342a939fbe8ae0de58cb6d6eae7758485e392ff6d5d64465b701692c
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 402525e19b6b68942253d1a51fd9b2ca36fc84cf938d80b3d52fd4302de142b9d93d1663e89340fff10c2b5efc8cd47fc3b5cc5ccd49a6ea3038ead6454bf190b7f88f52c56bcf00c6ad5b0f5dfb7615915ee8af137dd99cd3d21172ab772f36d291a6856a8e7912750139c09aa024b930a0a6b9eccc83c2c5c0ee2473ea32c
+A = 65e5db532ecae639bd56dd63045bca39b33b4d70b2db82ca3d0ee8ca436e671828cde80217b48eae7487fe110830589ab1be889f1e1463f3b0757d529b2f0cdd2ac92c35e8ec141885bbefb6040a3b5e00e64a541913a38fe05824a929f8c5a2c46568c61989c3ca7
+B = 1d9c73eef8373cbb1e8393feb26d55c33a245c33d7031c234abffb2f06a1601f7f3a79ef1e8664c51ce5dba5f5aaf3b9a9e42470d381219b4616ae93c7f6e64792d23bae523b6a224c1f714ebc82a11f9be42618922b8d2eb7b55e4d45572e68a19fb0ba72228b
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 7a9cdb5dcdfb6e04351057d731fddb9e85f41eb432f01c0d980673d294d05ba9b0180133a89930e74cfce78ed54991b494a19e7f80f310b85904784cebc5639bbc631e80751807868e7fe16719e8ffcd1f2cbd1b9f303c3ed488b647670be3080668b5fa0e53b6342c33c87f0ca1efe1ddb1c877bfe2556aeb61805b06f41343
+A = 1e412c3d66aea2c503f3aa5dbad368a61d969a2951c0094f9da32d2794e47f3bf4c481ae23636baabdebdcf0753d431426b1865e62de8eae7238a9245d62820ad7f17b5380d701f5db776cd4e1ddbdfd542901731ffcea5bcdc247fa9c83f7e08a9389e5a76d38be21bd
+B = -afd61df72361260484fade8b432713eb740df83a401d73492883a5139c918d5c911ff5dc00140637da1c6acfbab4b0bc8fc1f337243d90beeb1c2a083ad8069494c73a99372bd38712a5b5393c779ec1915e878600e0b48157bea44ca8e97c6099c4ab07fbda57d1
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 712580a1ffde78c8cf98ba71843c8130e835fee3afbb45e372d04c04cc388e403c9efac742611d7974bbae982c3aadfd1893f5da280afe0c1db1d81a9ed73b6ed9b7f05a20ce828316103259112d7754560d66733041e9470ae0d4dc95fd0484bfd56d66739f38ead7efa4051187ea41f7bea8fe5d958a29af41328246e2bc35
+A = -47c5755ca61ca8b7ea927f6fbe347f1362915548ab38c40f0418f4c9ba4ad520c3b2469d9ba3976669dec0b278461bae80eda53e9d11447512963e797f45460f74678acdd69fb9efe3897913b6568f8e03a6d90b4cb5bfb06af132bf118574b70e6bd2f6d6cb4d0089379d
+B = 5bda68c0a64218d3609d75eb4832d5468298f19498507d7d515f4c410f04dee535947571a5e75f1af7f94a5b3b05fb742fde23e7cf3f8b3dbee0a569e5a36d7a3d31a26c4a48a299044fd72339d2cee1a68966c851e76b93ae34130b75f4abe4f2260207d2254d23f56
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 4a1a514aa4d1ada84fa841d0b668930c904783fac521377a7d622201867d773ad23dbb667e0d4181616358f3cb088cd157c8e72bcd03db64647b37aa1813f870cbb0318ae0a3667f8e6c19f6e0706217646ce633f0cc8bf4e8f0f4d7329a8647252ca6d376416d545e73cb9a3cba40f8f9465d85d57c2481b84b6d95dd42d50a
+A = -1d68bddd8c3e6b78daa0acfc63a6f39e97f19527a43f6cdec47568d57b47f4e4b7ee88e4a28d683b569e406ecd2510351dba25f10b9f7c82d6da16d848bb970cedf7675e67937921bd334eec4bc8fde83d67aca57eec804ce22bb342167602fbff452d5f0f2a7f38b576e1e50
+B = -34d219765916a4c8ec843ebee9a7aa1162974d41cb4d6b60532513608452da9993749455d9701af6b7b6c7454d7f2fd5c344cc938baa5259301d4b56ae8d25b6f6510ae6bca114cae6791fa5a9551e8a405f5b1c0bbfc27138563b2d64f9a4d7a8f42a23bfacc3f1ec9393
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 3fe24e66e381eca525b24cf767215837019f44ed4fac6ab118d02cdbd658066505ee5b0feb7af51859992ecb97d727121e38873f748a61d70201cc43228a7732156a80dbe399e05764be19e37dc1b93222bcdcbc45b1a4817460f7021dcf1d70e632bc6a306628790201222bb522f4cc80adcc907463a539b02f74004d42adff
+A = 773454a43f495959dd55b8a064d70b1b1ffe45c084f5f9553582e24fb402b564de68e5379a8d9d02af101594e717a6c6db2e7173e557a64d2f28fd45c4e06041deda040705d99acacf8086830af19c7ab5e27f91738ffbd937dc27e5b7869bb6caa12c2d7930366ff75eadc570a
+B = 13d884a2396268f1a8186748a15722156a172a56dd3d8c77b9cb7001b6ee06720653507eba9bb9918f2f699cb37f3b5ae514f5180108a704647f19b0fc075826153edda66dc1105c1008ea8ec6f8c10057f8e8e479e1a1274edfed9ef719b30827a30f26da78820c3696d01aa
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 715bab8708e53f76d2ef2afbb845bdaaf978b54ce25f84dbbf9074f16d30a18733a02a4ba5d7b092fa6c25d3b9b0d8243c743910f1b7b785d9cb02343fc6d59eb0817bcff05646030ce4fbb2b9ff76781cb1af66b46553d365d02c61e677ae97defe92d057d4378dadf8cba9824b0022c086e0d78b5442bf3d3263ba22c643f7
+A = 168186208c734383d472374fbedc2d5d430e85690a4881b740008623120a4f7f83b2cdf85dc28bfaae5870abcd7ff1bc782ef11c78a75c99d41f8aacb52fceeb5f10266dc65eb00b0868937340146d8850887686d54218badb97647a6d82c0c6650ca1f9078d73fc6222aab95c2967
+B = -9711e5b3965654bd9427f79c89a0b3f3cdec1c857f4451eec236c1f221bb6773e5dcc30e7381a18a813ac2b03ff4a4ba679aad41e0e5d7181d4627f682ca2dc8af9a8b4f878771446fb225a979ef9c7e641cac819c307c8dc50d9c1ebadf912ec7c844e416f95b546cf09391f9f
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 2714b99dcde70d6c3be8b671d78abc155793f13105fd4b7c5d760a4c68ae89987311dabf2a9238d18299f983b8aca69a9ce398fdf2c9775d90b11b3dba17bcd8edf661efb6e9c50b4e37553cbecb54eb214fed1d0847287732810e550a4c86b51d4e5da1cb7722ce4317e69644620ad806d6d1c94e1e3fb4d87de6178a997453
+A = -75231ed37f1dfa4487c9fc79a6f7b36929fdca086e42ed41f79430b2dff521919236fe415ccce590e1d3b986e16dda866f3f0d29ac1adcf55d87fa5cb67dbf4693293188516e360bac513303769c42181483fbef7abcbc4fea1310c916396d29f37d9058a62aead94511aded7c4b8de8
+B = 5aadfe65df0e5b877fe45d42d7ca02882cb6c686d486374da5ece6f87771675153c84d74b6f40df1db567b7e1e3c60c41d21816f958f5576fd2ce2f84a8c3be4749dfc7e5561266b7c9698c7581292d0d813cb77955458d63bf94ce87472924c4ca79504d1ae9d5f025c7a2504156f
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 6613b1c8ccac0cb8fe2f59e76fef4dd05acf1f1b2bfc20aa3f193622ce3e9d4c7824ad544477553bc68f05f0b546e7c1ee87301e111af7929d1f40525291b88e211db7175f4e5c0953141914fcb4fb951dbf77442e7cb28fde495704f1b5141de1e50fbd0e359d0d86ad709c8f564c84dac81c7602717c269219ab1cf12e809c
+A = -1bc03897b02d1edb633e2c019e40c20c1d89a210b0733412aab675563fae8bd75dd7e65988cd8df4d9b343586e27f548becdde274f62dd421679554ed9eb127e527a69d69fa8b17aac0424dfa2a7692d1e63617ea45564b55f01a70325bca050862d583cdad96c4a2e123d0ed827348a745
+B = -3d5239dbe7bb3dcfd8027204eccf5e9444e68d322a0b0c535a203a1d0c054e7dc1e588bacb891388241462a5d2b43e6cce34ce46a23e6ef29670603d31001374dfa347dfcc794988e58945d0d2d17da6565cfea559203dec119fc357d396f65b296deb07686b0ad2d25a13fd4fad88d2c
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 3a7fc5680aae875b9241200b9f4112a82cd624ffd9044138ae3cd65200631ee9d7b918fbffadcad7e598791a9f0bef3e23005d6bc0048ba92461283492df3bce74c66e417b082ee052fd8f808d71f3ab18f9ffc40f8fb51ebbb936d09c26a3514bf868141f7cf238c1abb3d88e5d50dfc188902254f07d63fb8cb611ef8e4149
+A = 4a30f32d467b29dc83b40bca2fc4ccee5f08a64069cb87f20e63387b2219b12aa312400c4ca59608f50a71d2535cde40a6d248290793fe01693ca40b93a5cded2dcfbc9aeb36e187c9d650782d12bea917daadbc6525f266e074037803e4b2f300778ca8dcb304658cdb502c93c94a16c6261
+B = 1ca5e5218dade077fecb81d579e1c9290431b34df5ec84aefaaf233d68f17dcf60ee010db26320685af13a821b6daa9d73d8f3a30826c3ae7b2bc5e219cadcff826283cd7dddd04cea7a5e0585d6e7c9f23b27f14ff815fe53bcd75fe700b1b91671bddaba737fb43bfecd2a77e5b752a206
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 768d312175ce7d2601f30bb38339f046e4c2ba5c19ae5f7ca5a562cc2462c579fce9985e9e8afe2578db542c8d9e7693e0c74ba161334b249ce720d568e9c18f09c87cd701e6f2080b752362f2fe6252a1d0caaaf1fa18199776e4c6078d89d520b9c63db159d5fba7e0838811e68794b1413c248f3f7173ef29eff28f15b656
+A = 149353e91bdb70cdca8f06648388508511a64d05221305cad7187ea40d9ccef91fe17ceb1e79667bf66e8e6b7a57faa90a83bad119c02984a8f860bc1f23ffd33d4ad84896610301cd2e8e80a5ca7e8d3ee63e7dfa459793c9dbaef3569eb4f8a021c6a3d032a9c94d3f6b8278274d0088a98228
+B = -a7cbbb6a434e4b022d312ecd4a45fc7fc4d3aaca038cca0fc56e529fe7119ccdddc8e76d51a2fb862ad3d27a16ec8a51e5f66b9c7fdfbddcd05a0ddea14172339cee340c8c651eb653c6aab6551c99ae94f26116e15dc62f2c2e63305bbf84590fba1327ee721150d46464d7e22d45d53ffd44
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 763912f4b16549e6ccd60eaf7a0a1f64d9c3bc83e4a9b87e209a3959ba3cf609cf47183bc543f08e346b6e12b8bdd5d1c07c603f74b286ad432d58d7001299ec7a4dcdb56ca875dfc7ee5c75bcfe2aaba14959bf3facaebf8df92bc12937cfd4a4865b3dd74b243ff62ba256d110b01b4089730cf48efdc66fe272f9241014e
+A = -4df3899b40d51c83dacb442fb143835bcdb550136921df78800f0515a6cee77fe3236dadd2a0800b79ebdaaf8cf4aba5ebb60cdff3e4b4531ecd0903c1674a4559339123e9f09158080fc53c4c6ae72c961c8da2f357b7c05368157b4956e592c41b25642457651abfecb4fed5d9fc1fc3825b772d
+B = 450eff382e73f2f38bc3a4abecd5f8de478f80a6b99fb6252173c90d7099629afe859442bb1f796855ee9a2940f21d1f9dc44f462edd74b479e1f2926ff6faefeb55adbc6152b5c97967b1dc8c44dfb85b5e02e870d2920b75422c8a427e99e35e2a4be92cb0ddc04cb7f4044f716be97b36f045a
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 56ef57d56c6d1b94cf0fcdedd3611a8ee444c2e25522b9ad175587619598da341916b183be03b1e73be300f9969120d8f3a23750cd8c4ffdb87124a2139e8ff2c15d8dc944bc3c3a066aa16dbe6dba4a74925e16acdb2b2e83cd7fd5cedade6a7f7409a509c00dadc182b2860609cc9a375cb8bbdcc350bcb2c0df9b3bff882e
+A = -143caf995b7783b1316b5551978727f06512fe114b419c735b3381ec351275fb7fbd6ca88b848c3e8c9faedebd6d084cb8a231636f68f6803d14bafd90534609d4a4ac0fb953417be7fee4e4cfefa452c5ee5d1e1b97ee75f83cca8691a0efeaa8bcc1f1e0f18c0c5d6c7684c9da6c9495d31a32f40a5
+B = -3025fa05c55826c40089b12741b7d406f748cabf692bb0227519a124653160142633700e3c0676000943556f97551171d231c1a35f7b7d8f96b0366eb74942466ceb4660f09aecb2fb2ac050ef699eb05bd8834a2ba959ac71550b5c026b9093c8cbbb7c5fb9390a7818db682b7c11e58996c9d0add5
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 42f363c34c20c443c1ea7a1c54f98c6977b6671164a80308000533b2404a7f280adb1f3b98101cba25249131288f7ac68b0ae2572c7777e7381c1f4d05fd82188c4b1ed5636652e0bfca4d096bbf4189a9358b79f6b6333b99e5c4b7a940c2f7d1413bf9f47a2ef66b620b5e220b2c3dd7267452eb1b9d8d9cfb17bbfcdb6abb
+A = 499d05de867bda3118a8cb82b80ac91fc505e0fbc6c7dac5fb61713cb6e715f56a31ae8af4b400461d7ad1687a2631faecd90d7829f67d1b9e36ed7d55704b3f2aea65eac061172d698384daea710ed92cf1140cd4da427174bebd173c2ff1675b2407a84649b0a318602f33105006fe4d5ed8d0e015b99
+B = 17a426a12a0175bb46bf7a7e727eb5238af383cee6f4d5e2bd82b0d29b9fed35f3d8ec95cfdfcac49bee47b25d3b5f375a3340fa83f8dd9330a593a974d208debb7e567e59dbb7251b54e42dab2cd50fc63aab050a41bd88282373f8195c94c35f61bb48aa921f574cb4ff0984ccedc070efea8c46e5cf8
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 2f03374e9596cb56cbbd89794090ca7a4b437f4c05fa38a09db60e5ca900b208fb85b52f71c29fd35e62c9f9529d7ffe46fcc54607ccb07f6f8e13fdd4ff1185033ba4fcefb1ed4bfc42c3ea9f05276767d8dc9b7b4aea4c8bc0ce84951d1f590cec0751f73667db19060e2bff64da30fc048a1f5700fe3f489920675cc3540a
+A = 1073531f678877ba854fd1e7f857659614c526847ffbe8ed131dc9f2ccf69e1f1e917bb44a7b905f7ff758f61c06dd59ee09567d9f0df2550fcb98b776ed1381ce052988aa08fc5153e31c621c6a51ca61b386e3a9163a5cd69608b3e200476a8ada35d906c41d044bafe71ef5c6f732935f15b53bf36f7ef8
+B = -de3563925474e5408e245184b57f328e265b6cb62eedcaba809d8f257eccc0a457eeb82c451f93af93ce9f36dd1aab386e7c02b356f31c2d170169dbe15e70cf5bb9073b35fe0e7c7fd7faa91c5b2b0740734f12eb741a9d9ac6dcf7cff59f6e16324ea39e1e07dc5b9daea27ac674dfe5d0a5790abaebde9
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 1aa22f9013bc1cdebbdfecedf710c1bcaa41c696a3d7dfc1c8c601fcfcc1c85c8cc24be7df2cf3c7311b3b17a4ef2dbce545dc467d2a92d371e02a196a9977cb9042b236acf99d8c0d34a1c4dd8792d3497cffbc87c397ccee5d01fc2c89ef051324a7061e423720d0a3821a36739797393bdf7a45b5fc600824a17043312bc
+A = -4fb2e3fde2a0c653104c077cc6459c9234f86cc2d7b317329b68289826d3e2b975f1a69bed1a53418a0dd86e1b2723f4c4c5a29d003161e667c2315ec24a36f8bb5f2eb0a94f261e791bb829db685cd0ec9e1e301dc140ea57cac1da228124ae029e2b8ab1fa3ab99c55a9ca94dc7b767162c0a24af851fbb984
+B = 63702537a07971e399aa9a1a0795db052d6c8185c79107216babe11d6d8d472b61e604cecf9eaa6d44a2fcdd1ef0b6b52226ea0c6902d929b09e16576e6d1a6921765b2134c5d23c69ed61f36ea9a5552e5819350366240693558fac7a9d09ecd3702076c8c758a4bf6843fa843dfd688bef3f73515db31bfc26
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 6acb23ea695d4b60cce53079390da3cb3a4bc3a6486c238c421f3bf6c93c027a0475f656c3e5435f0211e90458ae81772aa956ef284093020f7b58ccd9373f3fdd39fdf4adb8dd64590f4a7fc05238ba20017bdad07f5f9a6f076b71554a7741bdd8c98ec68f8fee88396cb1f47c64d6da4c228caa3dfc7a9a1c032a9ba4fedc
+A = -1b2496ef929bc673042996ae80f27c6bbd33fa7c20580240ef8fba985d1a6117d6e746989924e34f281e7d2509175d0773dd999bde16662e88fcef52978d19cc45fbae3997fa580a66171d398f4f0e7605d9f4aa4f728902cb886e6b6dc9f0161e7cf1ebac05a09c5a1bd69a92273280758173fd2c14550ec221275
+B = -28399206ae2820d26a5aa0bddc4903776611d08fc4cb34a22a8bdc2a19e9f8cdab94217f346a8070a4145f989e1dfb49cfd100267635af0e062872cc879c534ff138fca603b5d45a6860ea85b6de37cfca000c81fcda3d14ffe81da919b2a25214209b085bab9cb511889665fc845acbcd038711533da171d8308aa
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = c012c4d17ea4c95a360218adfc3363f6d89f5aa524aec70049ef94c2c05e59a66ce01e25588e164bf2412f9517b7740de53d037e71ec3a1d426f05b18b128c41a878da75421e8c8ef3ebd5effd40735c00818eeb1ec63182b44e817403c9f1f6c1a0155334be63a3a15109be6d45ac0d1b1ef5cc99e9b284b00c487d91e5472
+A = 796fba6276fb7129eef2d1572b305f63d7b8c49371cfb3b2c67b141071e66ccdb5e321fa2c1bcf624c77317e2aa135e1137dfa46a34c3ffefa2fa3e316be81f45614d422bf86fe4518c2fdb7e416bec199de033cb5fef7f193a80c0f0e6ee924a12c8f705f5ed3793ab770914924b45cf2578bdd09c701169f0a881e6
+B = 12cf934763127284e642ddc232b1c889cd86617307b6ad72a9fe0d48befd7c5c5370a0062dfbde2add256dc0af850813b22320ceeaeed347eb9319bf22320b2fcadeb51c4bb26a160f7459fc172c27a91d367d5a232d00cf7bb778fba83afb744177bf1ddf45446baa035fcd0065f9b493d92eda37e9138f4fecf3ec55
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 3de123bbd50c35805b943e76e97b7e664eb9feb99860750bf97e275029e836217375cc1910c13269ffbd0bd72bb82ca445ccc4b693742a96d19d3dc23f78e5ccbba46d9ff5975f239551c36403ad5fe86997536456c4a5ce54807c24e3b5317b1c7b2a1661aad85b63859d427f0703b460cf72b9acd3f87e2e69d7f8f15e972d
+A = 1d0433d84f1de082d2058475e0168ceb369013a67aa9417f066c29c28272a0b3f8be5ac7190ab78591ae72a1dc8ce628c683281a9ad563e134387b9258b9c96d2df288fc118a8cff068ee49d635343772c2fcc252facdfc93112358414e1734d6948b909b53e46263e9a0cbffa141ef77bc98e7fae8ae2bd85bd875aa7c1
+B = -a31a574d105305e47f4fc00ccea0cdf854556886b524901c22e6f3b59a42915932ab209a8d5da29ab70d1472dd5378d9c79a7447d17665f9d1f1edc1e545e417cb65415cb8a368075c16264f42555d26e83adc704b5c126c6129318a8f394af8bdbb32c8114470d11b2acfe806acdc7b96e1e348a32ff96a988de76d4623
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 770f0c3104c0f3395fabeb75ddfa2c21a111d23438463941239f7c63e4b6e6832b84508ebf3cde1d90cff0a2801beee05cd5118f9a726a987eb58def6780be899b473ea71c697557ff63a4c6db894e9438595acdd98abfb529d75bdf3c1d619d6165a9edb6aaab8ada50b61a3a84de654706a9aedb7321b0523558e8f18116fd
+A = -5fafbd498d610e9f29c38a5c6c262b71672fe9e9c84f0f071b549390353e4fd0101a059b7c547007e27df97761767302458f1936395142ce5776b0959fc5ea039429d64ac5d50c2ae0ee45d60c0c50b7ceb4ff9853d57c6e883f588017ffcaddf5a1aa3e23ab068877a114d9a2cf742f01f5f5d611424c8ec0d082f5c165b1
+B = 552155ef110c126afcb87dd20251220c7a43bd0215ecd22249a21c93583e120ba6f046c6fe03086ef3c97311c4d520110a450470a473d8633e3560d2cb44c25559af07516aff50d6d176e8782c06cd9aadd3354cc695c4ea8dbf85e01dad479c8e8438154351fd5fcc6fc7e9d2162ce2f0179247f756f0b9b34b54be74821c5
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 2e9ed66317734668c4c354d720a011fc65bb67439b2ac9203dca65a8f567682be40cbad4f55a83e836f1fc135596b624e4327acb085a61b6398237fef5a6e6560b488d4a673b5ae7d734b896d9647d71087621cc81e94d58e01fc2cc2dc775f9ab1b6031840a672fb715b77bd636e3d87b4949ec7bd60721bec8f9907b7c072f
+A = -1a6b046d691830d33eecf2c53953676ed3f6fdd20c2252f6e915052ec28ad1fbf7a5f264acf87ef8ecd515ed921ce6b85017f3d8a8f1d14f269f31e3307c6f935ad468cf012a912b0650a15106fb949cbae7b36c9cd496538bb0646a7a28989dfadc719424519bfa43cd8833d3a748c758f813881d83c98f7cb2a63c2a4d06b8e
+B = -34f87db0f839af6e4c4bf146789db36b3d0bcebb9bad81db690ccc3a35070d8830c9745b2fe730a1f3a252612e7026bf9889169b57b8984a5479cc4cdd6844ee3e150a2e7bf7680eebbef30e0591c895cc8b2ca488d489554f2339e2f55598717ddd8ce444a060cc95cad9eb478491ee8d3b8358c3762a970224abdc1068af0bde
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 6455ff7c12bf3bc37120fe3f1302a9916a6ffdae6ee6a37fc23ca2f3a7ad910dc0e1027d4dc304a8eb4eccbcf3c87cf52a13dde472c07e2df2420c1d36bdd5e88c3d76e774ccd2ecaf6a0ef55b8c60231b1348a738f812a4fd9d0c158fd5a9fb19cc7cf9f000860d4cb6509271c8e43ae4193843324db02a029beb58ec2955ad
+A = 54ec203e2ababdb0348135c0679eca2a8e778ed46e53f195331a48d3828e5e40da804ecf95eed819ecefaeb9c5377cc1afb1fb220175990d347981353e7d90637adf8cbb16812af8a3783dd312d967a490f8efe3f23746929cf2a5a8df58e0b878367f6c5e4d3c086f947fc2bf70bfc3a0008a8bb1d7d83f002930640b6ed94c334
+B = 1311b88a05224e15f1465c8da26784dbaeae84f818e029301ea39a982f714c64312f9f02d094c401abb6a89e8537d64c178637364bd261f4a27beeaaa901cc7b3d4e36ebcd9453cda33d47a53c6dd1d121dfb83a222cfd16158eac23482c8abbfaca59e765f6c1fe871d884d281793eb19f6409dd6bbe4083bf762ef24c24f0127613
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 64104f6c06e563ec66de4442d35d88117f2535edf9e012897f44daab5a1b8a8696f84db7a68d64ae24a394debb993bf6734c9df542c7e473b2e497396ce39a064789d5d7b339b65766b002a18096e7fb9f312ea5997c2a85463fbd6fc18f25769ac2a2123ccb0e72f14b0608c4c22add72bda138b83f986e78d5c9da31b15b9d
+A = 145f580c2ebc6c0354ebdfdbb1d3d7fa17f0b55493b0b9a11b71001c840a967dc77f0206c3dde161b5a773a6b5fd9471fa08b205cb6f728e3afba440b55268d6a9542e234ec313d53583c580a391d8da5943f4a900b279ec9d8933f2cfbb260b74ab714a8b9a1af3190d914b6e42212df84f933a237728a5fd5473ce2e272eb82bc83e
+B = -c67f9b9295dd5844307b8fe3cb9c1875257258e4be6229ab097e148c0175ecd0de4d84fe03c8da6e27153c709c2526092b1abc73b5fb40f1d4da9e0f3d8d2fd5f8a4e6f3c30befd80e189b73fbd77e8547b34010d2aa57072db0f00537cf3ced95eb517b23e0c854b4becce128a575a31037c3a9e106a476d8b0277d26dcee435cebedc
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 11913c40d577f70a5346ff1cfdca492ff52b640eaf257510d311872c8df7ba9756973da5b9206c6e5254bcbbb4bcfdad5fc4594e41ee44e77f168e2d20a4b228480a9908b102dafddd039ba7f7619eed7057e8af3a72ee491a61dd049bd947e5b09a94ef94d5f336945f47104fddb8493ef22fb648ff5376b68e96c0555d74ca
+A = -5537630b7cfb8daf76d14e617f7b69f7b75b472801a9a818179d83ef2984d0abc8ea4214ed3d3d2bd785060e9c2819e861d0df760fc1daca8340e8a2c997c9ad201d6d2f12a82ae3883cf9f5c51ff1c25277c28175859a7b8e5b6cdec7cb3875071cbe415bb698b85cb19f617162587516f93c728ba8b2cfc19f238e2cfda115b8ec0431
+B = 597296cb27080f33a24241c1e98fdec32f7a4013a7340d367e4cf2a521cd462a2803109c27fcec353a30dd20053a1f744394fed75829e8396f8de434399bafd6cdb6e0ee81343f0cb99ef3087a7c69bd43bd722745a46cdff0c2c837fd87543c3c63df3896ac101a145b478dc224644996fc72460a89beb5741b91a42f2fbaf0d62c099b32
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 42f420adf5c6b32ce53fe23af4e392517e37013b8c3a7d035a93f6ff45142b0b0bd5525cde85f9b7bd9ce219bd3514617e89ef4d9279cb9a3e89e44f1994d72febd23ffbdb0a4f19cb76448199b31c5cc6d7ec1e46fdb67be1211c0ccd93c123d56ac0d9cd2ad11f0c58c713165003495b75b60665047ef80f6a393474cb727f
+A = -1c6ac9565d1950ae6c55025f76e0a040eed0462218e97aea87208ba879acedf413ffd5e63a92dd8658cf5f49d633ce7b126091a55701168ee4932db004dfe8c35c939887fae3a892b0b04d8eb74191bf8fdcf5566b4d3796a5d2596b1e750f64201057ae60aa705edd58aba4b48f6a2e511bf5007a6c44a27e3efd5bf2708f7046c1fff7864
+B = -244f2a90a57e5d066fe22f4d52f91b44882b8ef76d1dafc3387abcb224eda4a2100239e729bbc745237f8129d457e98eafb2ede2f3afb81e63520493da2a5730f1170b31fcac21259e90c894f8bc488c5e5dab2c2635bc7b1ff56c3685607f6fead73a09f83a7a168c4245729ce5b06e482d7d3d72eff33d14cfe2f32f72175484ffa292a9af6
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 2239459025b257fd0b6659f54b8874f93f07f4d6240f8ad761c9da288cf1537d8bd001eced284bddf78edd611c7f28f1393c6fb879aab6e7df8eefd347d63628b1ae086148f488b01272f67ca19db71a2b284eb17e17aaf1e3e8f23ea253595de474d5cf47c16aecfae360eab7855868b8af361491f6ad96f893f9d3eb66d07d
+A = 558613de283911aea1ee21d6b926f531f778c5226e978ce329860682b5375fe5e5328ae27b00f504f2a2d24470d16c1edcb8e76b4d1a740e55538e79ac7da4b45c5299993513ec3bba7e7395dc829a00d4e228618dd348fbf838eaf0bd50f6c70253fb1c1c734a07d0813915be25d3163df13511f3675022cb85af7646c14ba5d13f615ded8e5
+B = 1f3c3c468146c29408d9207e15b25186d3b06b3fbf9556eff7ed7ef7788032d87ae1a4d2a0983902d4c70936c615d8c9ee26c89af8b58d60231ede54e859763237d5ac59af686300a3e92f456484ce77700557ddc0f93bb40e5d2e5117f2356ac7ffca26dcafb3ce7a5573e07ee97515b6b082fe75fcc9dccd76b4fd416e69a247fab2b30965d9be
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 7650985e7c6e5461268867dfa9782cd8154bd6a4bb5857d6555e9d9746ee79b37e44638940bf8d5e974911327f0e53bbcfda0739056bae2248015c35839f35e7e359e93d3a339e7af38c0cb43eac5b41e1406e34cdd4afd458a5d126f70b5d683415b490e0ad61269ffe7ea8972eda6addd447d97e60891e5099ee920e18f233
+A = 184845d3762ad1a9c925c51fabc7b9e15570a84a06ecef994910845d56869264273d75fbb84a31c97c27eb9779e8b39f6829638a78b266326b60546507f65128caaaf36d4e7f85939b75cfb3145e2b1bd8372531cda579f59efa0da9c95a8efc72faf326d35c660b4444627d328bedf50a919029dd164de051a4c0c924103e365cd640b9637d8244
+B = -977390f52af784b52c1d54e82131b072a1c308406e9b82587102e67c6f7145f0020952231a5f0ce9d130677bb5a7a37d5a06dc570a13a29673c8a9068f06242ac438806c37ec46136e7c1c1487ca2d330fc1f3c1f42ea51ba2805b74c44a61fb2fac109710dc3dae78a07057a753898d4e849b910f035bfd807178f0108812778345b256c7b59f8883
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 35d48c3e43070a10dac0e256afb83b219aacc0036f554bd998b9092ce3bf87bb5d3b00947f2c86fd4e7ab830502d15fb2d4e47ead087f5c779a9ba56e272ea86116e2c81345d379dda6b581e9c8f4df8ea56c78f04d4f7412d245e00ac645847af6ae97d5d2ab27e48cc878d8b510c2dc753f6ceb1b9e7bdd923e0e065a6c11e
+A = -76e575cc79d7f0c313a489b255e85d114f3933383cdfe75cfef649f639921eefb9b3b3184351fd0ad252c6e477e153ee586a0ff6da1e1b2bfd7e953e6dd778c849843fa5cc355b31f5529ca45aec81ba67a1e364d5a74a4656d266f7decdd47b2fc2d81d6c298afa2d1c39b5e8eed519a9997a14513537cdcddde0b5b41314476264d59b7d3f0e9a65
+B = 6b7faa437b4e8db8fba56c62eddb8a81e9090d1b6655a2185d656b2db0e85225992297381d653e707aa15f3017880b0f07abf3dc455cb09c4e551b3df3516c6db4ead79b88339fc33dda96bba76ff7c388363c36b67fd5dd0ee63f92f67549dd77e37e9902ae51cb58057579f03286fc48e3b7fba763fc5844c222e6a1eed9e1634d0bd034cff222bf147
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 445039f359b55eec647296fbff4f22beac09cad32cae79c13d591e314fafc2b77839816aa4f641250938865b0a2c30a10e23da71a6dff5985ebf3df4429fe64c327557b12d987ad9e9971f7c7b1e4ad01c94e1e5322dbcbc4707a959a401624619029558fd6f5b14564469b13146f9a2555916491e4d77caa70f51716b299135
+A = -18ddf976fec2090f7d1f4d41b8f875e56c813c04338f595d6e591b3eabf9e105be792f45354ee9beff997e6c0e8ec3fdc714c07b3466ad1a949b9d30da0115f5484c3b9e00c7cf0c117db57c3c6cd7434371c6d9ac7a5da1a0e2d705bacfc22f62785222d59bb5bcd3e3bf2df8e845953c6ddf1b546cb75b1698dc8e20bc611294ff288056723f1e46ec9
+B = -2cbaff39103570df7d85a5673b50fb8818434bbc19ab4e33bcc8289a4047d85de1b7029a5cda3976ab12e1d891b7efe3d5576bcb3713c597771f93532853290068761bea04200fcaf9b05d8553b960ef5e28064de89d9e5097d12b26af0b64beb40b33ff82a55af7c5838b44282917fd4342e2065942c724f3cca515d9142fb8e46652242e8f0ee5ae07b6cb
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 6727c0d0ecb4a375d0fd1bc52146da1242099d445ed9e87b1fad4daf8369fbeeec49027d88bd98efb425c1e3f73e412fb327680068ae57d4a53992f3759af0ac1b96a92f56c2cf552e6682d1fa90c3910bbc5c0b1754862ee13c5ebd62d5b98bfe8dbbf9bf53bf9ed0b967f3c9da24d4334b9f3f75314b429b05b8e27142623c
+A = 5cb6c49efc6767cf956885690ef740337aa71b90c1d4b9b0a9e4734de0c0c50f2358fd45aeedaca6e1dd0fb510bf097bf46513ee09f3343bbd1c11f507eb61d51ada40c5d6b730561756480063f60caf05141bec9a769c241d367cb92fa8e229ba2e471fc73f48812a25bfc7553c395ca77b80443ccaa82fbb7198f8c35c3b5a2fff977d8b2a29cf9358ee1
+B = 16ff229a0e67a410555dbd4b687f1470ec854ef67db73a902f2d19953c55071c4a26dc320baa8571586f1fd54fa490b0d87dc83e5bf20b78956084275518b307ce69aa4ca1079e3aa753d97fa1cff62e0b5f3b99d96a24e411fc3a3e375ea21b7b35a578a72df68d28286fd9a324c06930905f696424780083715f77961532bad061f3901ed276a9eb6e81ad4b4
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 6e9947beae4d934253e481d27e854a59c4047eeee4fdc7df7e174a8f045776109c148ba3721685195b8fb59263def88891c5953b5a0ae85fcdbf02abc76f4d3c0f5d9496327d063ce8b3ba875b4f119dcd8beefb3ac884c25955af61c35a69d0670c3c349564e5b84f7df4252d6d3b29d9a75f09e9ef79f0fa9f797bf75b8ccb
+A = 188785951a3befcab56128cb6fb9576bee2412e6cdd7dd1bf5643babae83c8011af99aada405e119c3be33653862440005be994bf37d3802cb6c73cc312824c56841004c8e871ffb560e93a1d222c93d63684e90a91394b9c8ba8cac27b414bf818ee0de7217bc2faf099783800485ce2e93612ce39fc7e2f1db708bf9bb032d92b66159073fecdb2e0257058f
+B = -8dddf094f30284c213577ceb7f1b2efb1e4213a548e6aa840f801cd6382fb6d4995908b7827078dc3f46fccdb9e071bb8531ea8971de0ddbb714d678bb71ba9d961e58cdd5f41b8472146ff9b814a5d1d6368bd94812f8d38f235f39aeb2421a57499fe7102c1ab167df7d33b32a6dc7c8eb8f4babdd6b6c929d1ebd9bf4774aa40cefbf136feda7b6e10ba4dbef1
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 3f4a8d90017dbe8e77205e65fa7a0875a1ace6f3f215c2974e47dbac779804143da3dbce92db391c2614c078997c7d1a15439ffb51a5787f5bbaf98a4dcef576a6317b9b92dd8141a8fadc05d3be7c150630668e620a4e07b4b00519f34e422610a160de112f1ab8adf09a9169ba95b60242c89196ac6e155021dd84b3054511
+A = -65ff4322f8e46e03aa6c1fd10a207a5e51db6991bdca232c0dbc9d73ba77fc485d881868be7b14c25b05bb59b7f5bb6c4b2a7d53f35d2d7af282a0423285c5de656429ab7d3af7d92837e41ca701f527845e98c2bfcb51647512e6abc6675cec2a7d34ce55ea4dcfe9e7a8397d45a7a3e73bdff06e303a8f04ab6285eeb1bb78b1455931cae203078eaae826a6e5
+B = 4d936b603eba3aeec3d3f1f9acff02a0ecc28a8ec64b6bfd9b153b1bbacf4f1e186d3deda8c1c81e759237921cec53251250e3e838f5063c4a1eb6cc93637f35aca10b965533d18b713617a312e74c446d63eccee93cc97e3723ab27357ae9b3cbfcb3e2bfc589a1bd582480e776198df047c3ad85f611ca6fa480c70aeb98af02f57d56dc9659b2a6bee222dc3e0566
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 8a7f3cde3230af1f1fc25e0c0e9ebeb69161d3864fa5a03e5d7f8c82d9940ded285df35c008f61cc151b4578e2677b2f2cff3236935de5bb1d113597eee448496fe29bb18343687f6e9f1c783863e949a0954de2993d47a03607423b458bfd18c844ab57e9e2a43930df159ce8564edb5a2a37a06425626502e3ff9363b73c79
+A = -100f2984dc1451fd7b71e5d290e4b7de2d26175a47b9bed524fae02bd5abf96faba06e955107329559bff3805689633a4a57275732bc42183acdc792cbf7b6b24dbdc8921b73c0308d0c0ce5d8aad75f7eb16352e67116e859b323deccfe5d9ffdd1f0265297bc9eede073146a06acc3c330458b07b8fd0bb652c7325cafdcfa165f69cd0de8b145d49ddd576fdde15
+B = -21ac4953e54347a56800d75f6feb6ad660b0442174cf3c5dcbcf6528e2b5da95a614d3a8399da14507df4b8eacaddcddd627b10ec2dc5fb8c43d96a38e6dff37189ba275afb9484df800587f4953e327af71dbd58780bd5885b4cdab15ea0f2864f961bbfa9bba6b2d9448443af87c0cf178990254c1ae6e19003b1621f3240a6e5d0a3be2deb5dd253f5e1f88dbb60b522
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 76f8b44df8d8547f8b3d8537393d2805c699eb37d19bd115bd5539adb6b6a00d004def3b7793d5c71e0ccd2b7e9fb87103c1a5f56a8f18ede1bfe1607a346297166596aa78dc584c7c32832e11b72fb4f2d40ae1591f341919bc0157080ee8febb7fee5461a918d2178fa407c37a8243e24206ce2c19c3addcc2b7c3c1912b6e
+A = 56f4d397530f5c90203df1ec799f82a0096888fd370d543e33b5a2c8042108bb75a86265204c40fa5a9a44965ad2fb41896b134ea56c79699a230f38c0e3fa4e5d346cda70e0253b9993c9da5642f4e645a0d96cb732f8f04c99a83d1f1360a385c6e1a972b89915489245ce58830788ce23b9e62d6b48a7ff9a486614d6979033f7914a0735d201c6f29e512374088db
+B = 10fe818f6af7a95cfefb0ea0726f9a3e0e7c30dc9785b1fdf6e2b810515448386c7efc656479794d389e109ef3efe37fa6124c5a7db3164268da0d98538606c57bd2f7df9482860e81f272a27c727d7d81a66fc1a9bc8c385cf02b7ca6bc7ec2d8d6ba1dc992caa216d02c9bf0fba8ee754af77567c6e275ac1b6b1b36b065760761300d156e40da8445712b8fb206c0df346a
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = f580f9d2438b22700c3ebb23d1dc296f3d33deae2d32dea51c7ed3a0ce7b06af11046bc1cc279bb744bc31e7f822c17ffcc5dcbbdabe213bf97bb85c7e19ee71a513bf59b25b3b5787e42e9f3ef6aa1acb8705d69924a107b4f88e0cf9276c2c7c47fa4bf56c4900b557aa5587418f0ddd899630ad3ff678b5b907c07247b2b
+A = 1017a4fdce8bf41ce804b7c9c836d85ff6ee899807e1736bf0357b015b701b9675297e5ebf588ac6c295feed3c6a367987e192be0d89523ac7d64b0b9576f311b5b2705c5398276a52f06085027480c2ca72884ad7be34967bcc6c8cb4ec4fb761e88c16866a2e284b40180eb14536810eeeb180ab701ec47ece62af65a0753f95ca657e7d04ebf3c3a7db02993da9089840
+B = -aeb03379fcd4e87cfd18957a72fce42e016951a72b673a9e81f666b3cb20d2bba81400ecc2b38601bc3270eac46a633a1a6b55c50f00e9d7fc8a20176b93e971cfaa4f41573b17b8ccc498f8a3230825afd0d7f102daee347a9d59cc0914ac8689c1d8b39ccef1f3def44054307a7cb7706535f0cf4007231ba21696424c3d5b42c8e85c278f7c2e8b7d1787effa601ad357eeff
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = be05efeee19cc91e30a9277a6551aaea63aa3861b63f6061efbb0b92296e09f4709529eb849d9f40406fc59c526a4697144cef9661b556040458940ffd6a87ed56cb073d2ee0e6d1f05936fddd1b9a8974a3088577847ddde6bbdfb3d69158d5b3899c13ec78fb5cb6aa7204efe308bbe0b52f18381fe838536707a8a27ba0d
+A = -669660e75eae9930dcbdb99c477c980869417ec9c0e8c4053f0bd8ae62d496daf7539f37af96fd1cfcf3149bc02b8182a46b413e3397b49d4b4d204491440eea65505cf5d33a8e797af08f3da41f5a0804214846bd95d730260c6545d51126278181719ddd396c55f119e84da71f0683eb6db8393b098b3a0c5999862644e073b4918b5c8aff17efe860744d85bc94b582d45c
+B = 6045f903a750b69b709cfd6a1c8ec9fc0d7da9c53a9d26fdb0ce9a17c6a0ed5ba633d6fc01f004f4a48cf247d61f7df609008ca5bdc8eafe06dcfa06bb67efa6a584b5a2f02768718a908978edd475a2d2926af2a6e523549a5cbecedc78323c5c295bc0b8d3e14053078492e82e339ea2c6301412a5dd7efc20da0aad0577a37d853eed820776e672bc6d23dc821b5855eabcceb18
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 705bf20b7d92e68a69019cfd721b27373c7ff22f911066907f556321371fba70dbcb9774d3a26ca43e44ab20c586a3c1546fc3152ce011be66e04a59c6631bc8bde18efb7bf1743b9ed75a7a6c5bf5a4117368b81b112a3cd4e1c44a621f534a11c426451ea5fde880939ee5bb28d9843730e284520a976cd9f60c94751050ec
+A = -17c1dbc1ad1d2d33dfe1af7b4cdc7b69fefec5a92656957e111aac292e44719c7c752ace33dc74a6568be38b576a5ba174bcba77a034af5fe101699c99ca39f8a3b0a20679e6d0180868a232fd8fc775089e185e5eb81585403f32619a2f4d857bb091a824a89de2e84529e5b0702b45771a5816c5a823d81ddc89f8a70cc3d3a0c6bd6d85e9d72b69d2713b61c46161f7f4700bf
+B = -2252b54c602456c5deb86a0f249f3982c3836b70a946f636b22fe00c6e3b91b94e19200a33087fe734ce9a3f92a6099ad03a95ca523b7edb9e1ed3464d38fb96c470464e1c54790cd48769677efc5e1d22f5be4c15288bc5ea1dc184a05fddd5e576b3b4962f37437b4f9709dcec374377db44c8ba1d8611c0c3ec35f9bba213eac59a047e78195ebbbeff941c7f862e8c80eafb72b1e8
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 7306e3172929c00c29ca1db360eb4ce82066f237e9cf6aae368d1f531620e9b61eb64f5b3e2b735a3b565587d7e955d052df94a20e4aaabe493dba2c18e85fcfb65df166cc48733632d165129b112598bf5e4c58dff662e558e5f71b25f36708d3ab6536b1cbdb5aa2ee56d9e019a9c3629185b188af909831629ffceab634fc
+A = 6b31ef80767a7693e7d0a9ecce54beaf5848120f036923d80b7a0245aa6a46135e32314f3b227268e0bfa1f45b4dce83bea890526c7ac3efdc8e485189ce2c51597c2864c2d3664584be23559c03670622a53edc2c17b3f1a92640078ec35189dd7953e55e4da0290ff1e2996d164d69f1bbe6f5285ae89209d611a7d760e413e23285066eab8e126c320bb6130a91d67ef26d4dabd
+B = 183f06828033287497322b05ac08f62dcc5fa67b7a10c6c5a319c9a1e642754230c6d9809dcfd2de4bb9e360d6e6e1180f6ec6e0d4c6185e34ed299b6171e653521d0f7b8975ed5e7d2c51d27f9784a4b6f9b5e97379fcdb42e4df981462cd5bb9d0501f93f217d954f6baf70343ec710065eacbd2b778430ddc36a7ef0515f29d5fe78d8708d8ffb6c3391c6f632cb1bacb4ec52972ce0a5
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 361ce44d153f4d251952c0b90681a19b7d2d8df7a6c5d459691a80c06107b2e818f93f30f8dad352d2dd87b01530d51fd1c67cede9b1a6167697098e41bdc5dc5e7a3c310116aed0c7b5fd99dfcdb3517c13daaba6ad10879f600eab846cdc110d392d9bdc0e8ab34b317840a725a7a12ceb48c75e8dfeffe2947aa85b2a5158
+A = 1e1f2e44bc7c79a00afc3b2570d5cd27ad5ec9f45aa94f63f2ec3fa6b69077480212a1cbde25ded7ab1c6cb1ec26d5905948e5c1d6d109bd5047b1e038666054606b42e880b609f6f00a219dcfb504d481d6fe709f4362940f6c4b6f2e05d243722cb32bee5508ec94eeebb53b5befa551d3ab5dff9cba3daebdbc97179e56cb778aefdda6a0c24265728ff9e59ca3c2d615398d97e66d
+B = -e018708df037aa2918850fabcad82731487fb812213b1c067d0688462a4d518e5ec7c4c84f2cb2017aa6bc960e2faabbe361ad8f66355366cae869d366f06d7cc32ea08dc51631e7f36a4c775611095d8aed06a0086d0a471749246d7157947a1eb5d5503f207723a7062382b3e45bb84c6f555e48f6d63aaa1c04fe13c0108507c0ced669a5296bcc16debf18e03c32eefd177bbc1dd2f19cd
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 3aeb3ff6e797d271fd2271499a740a91569f300d7392a7b5898084012a3c5ad379a57d5169e43089cd58fc7210314758d5368dabca2f0ec5cf6786801bc99b45cd60403c732d9f98936aed76da724bd3e7d4b622dc690778f11fb0310fd4cd980b220627f7a864e107f93a6259081c6581e5dddba4890508af8057c1af29a745
+A = -75e06b47f60edd23148c3736c9c125a617beea7c8fd47e662c9d9be883ae925b7801a0030df3f4bdd3c9fc386f18c4e002e5daf4a6f7fa27b2f71252c83d5f1695e50d62a10b99e1900987b342290decf681a064f789e11bc3fd75d64e2e78ace56e7491fbe0eddd6f9958a5f95775c920ad6c051ebe7750fa76891ab00f42c910550a42bbc1c1e5aea0ae13b7e6f916a5d228bd57e854f7
+B = 434c8e4767d0d7df2125def75a978bb1509a26bf8305cd03df748c6c12b6dc580a2c1ca9a4526eaf3936fbc4ec797d0733217a54ffc9e1d7c6ca04fb39679859d5bd3fa64cd0a09cf1a056094b9c20ddf1f00e134533ba9892c2ca7346ac8d0655250eb45df9f0b7983bbf71102c6f1a2d9497e7a45eea7b3095cac037b7aa755beeea8a6191da268780179a652d94a732a2a5c7b626c0de3145f4
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 734a429c91f5b0f06fd47725ded06222c0193dd407e9daf136696f203e153c9bf6df59016849284cef93fbd35edef2cd31c9b956fbe562d2a22100f177254144718ac7d22c99783fd523b642984794bd7beb0d0b363e28d3f3469ee332ee364faaafef25c1d4a11b5e517e44a412ba717a113ea9e1e8f2d6db8fad6f10d06950
+A = -18dcd213e9938fe4b6a64abee3b9867f65e47e5b0365d45a8dee14ddf787f34072ce32f38d4d48ccad236005a23c5fcdc02b72cf27001495663fc56f428072d3f1bf5e33ab2c5f9dd9facf122f7225ea03c2f67321530a642803f65a2e9428f32d0d974e68a25f705e4f8140568f7e4b132942b49f9ff53f04f241feaa29aa353925fcade33a0cc192fee2628c2111da1e652cace9d304d0f1d
+B = -2e5397658a5e6db9d30f09e93e67a30dc84b1e17c25786e041fca48ab710e1d0497ce615264f1abcb23d5aae8412b58430bd801775acdce06cd362438898697940712062b611c92ae6ad10da31784207c5e7b9362b20d7254da0df8caafe0736002dd466d76b1a03e91a8dbe8a71107abd5f07b00fcdca2017391c7c3263881a3d02a89b0e16a2a765a32d24ae6584cf44a88975c539402db9a301dca
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 427609751f28edb62c717bd98ddf999cfcf65128b652be1b5aac0dfe1bc0f7687c580ec70c8290455a9448c69dcb550c0cfdd109af561ece2ec8707c1d02e8097e780f32ddd932e706f81f68711acda0e7610f4dd0fd55f6ac7ca3a3184f655b0b29d2d62974739b43ded96b413b9e3f0033ca1edace24b6bb610bf06b5d940a
+A = 6576c31d48daaf7d6bc3658952c4ba18095f1a0d73726f6fe59381af45a2a6b592adc79fbc3b597e1eea711ab295cd991441fb5fc4ce5f047e571a7d949c709e0d31156184be4b8a6a49691ef93d7d3b120193f6ee82246aeb896b8b7b4c74c27c02cb39fe0335883a3f088a71ab42b947a0cd59dd2155c65a0274ec0836bb8c2fe394500724ef84d869bee40291363389e7012d672b1eab6696b
+B = 1ba2888f30be283b588cddf00eb3ae3c641e35fc0bb3a9fc85d7fac1e81052129f499afd3e8458d4cf893d51fe4a2bcddf70f28c8edef16c7bbfb791daedf1a8248faebe36953560498af652d1f1c7aa0e9a5a667d9c94f7d9525cbd5a82147d58b738dfbba5aa162858c2c66d0dd7d8db38d41a2261e6efc7d0c8b2dd2d6962be0fc796705cec8e87a13092e4a3febdda3d4dbed9d11a1d5f92d7dafcd6
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 533d6d8d7384e6e65569ba0daae0a8cffbec1d20e417a6edb42d401a59de0a91a7e6854db081ce33b76faa63f6d866993c245e69ddbe6c86d339f7107a4807856cbca23cee2bf5496388ae8fd8d7c78767d0775acd7bd6202dd75451b424034e2766185969b5663b638d539f718e50a9f752f406c224c000bf1ae1fdd60a2a82
+A = 111940235b144a42a13201a41a3f9e4ff02948f8e9127d9a3007906988a50b36d7622d1221155f2516812074a7888b1d8334a01c02ee33b3164d761d02b36729c299ce2455a462bf18471fca42e5b01615d53723c3fefa5aaf4a039a6caad35c348a0a4dd3f0204f084f35c0b93ab233c4066dc50c5fd3897a769a7c5bf309f7a9c30e905466c8394d509b79d62a69b58c73d8d3f1665ecd9a8a4dd5
+B = -e2633e43c38c0b4b8713c20bf4e2b8ccba680ecfc1139954fc42724277beadea438596942fea1094091671c2060dfccd0351b2fba8cbed35dc963cc18f8e8835052da884799d88ec1887712000a0726b17cbc4302421011d5be8d234440eecc363f09e2c04bc9cded3cbbac9a5bdf0b6d418822fdd90dead20e5bbbb3566ca94ab85f3a00d32842eee6521edd18b9aa6872340b2f47deb961f58bf231e01f9
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 33960d7ceac73f342d46275e04fed56563decf2fa4c0e9307c90288e911ac8782f8e1354fb051a9da8e2db83d7c710b5d2b611495e72ed42259ce783a7e7a8f601c07061ec749481d39a082f29dda1f9c7f444a33ae1c1055d37a677b848af371cd3bd41c851d31a07e144d7add66df39576b8200a8b918201630b3da8e664c3
+A = -402034484e499a8efd610200790d443c5d3be35d19d8808da85954d42dca3f24177de48f55fa2efd7e4f7f624d806a8d461c3bbe0b626fa1f3cad2145746464108b367b13f3537ff395262256bfccce5f0414e1f98b59ed29940171d46ebc4bfa1a27802cc30d9221cfbceeb92abdfa6e84ab4a54965568aa10ea631e82067ae358a1a93a3a3fe3a5ed5636a0c4cb373b4d49f46f8fbbaa665a19200b7
+B = 78ec7dbfa2b28e268619ba6db34a23adab25e7f8690aa9464a7d8fb7c6b87d5dd9d33d4c023bb665f2d96febf2638fc087ed30796fe7517fd58e4120c0d319688e67a32bbeaf62a987a9764be75384bd499b0e00a850f27e303f615031299c631844d10abc571f9f2a0f742cc0e8df2fe3c244bd825bf1d9134b2f1059e2a1b61985ae8daf9bfbd9eb24ba268ca58553891945ff1a314a78fdebb5444677ac081
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 3a1ea3fccd6f336e6d444d68af1753b83145131954c20f1e3c433a89eeb7e267425a34d91f67fd65191dce85769ece2fc7ab12d032f3e30f8509095ecc05148e47a85391b21a18257c338a6a3ca9816987abc8143fe443342b34afd8a52fff00dda2e42b1b39322bd38c6a1f711051f791d6cad2a47ebd423a9b933485fd5861
+A = -1869c53f86755aa350115a9f49d6248cedd42a339506b8ff59cb878b7745956f142fc4387322c41f369773ed375b72665026771d4ed1b9ece08f84e4782d4c3b0177853cf9ac3a55f7e52f39c1b82aa42b30628a4fa6a838754ec6ff9809308f675e455bca6f44e298394888d85fee29d8a0c8e9cdb9aa08d68cd70e13a243b5804a3ec199f52ccd462ba6594d856602cf1d5efa509047633923d31f78da3
+B = -2023c544b6cdd8d971bbb345300f7a101f6dd44dede6bfb5f4e6b4eafb7a40728a3063f6d4bdd0f606ddecf062828cf889b2f632d0c9254c28f36dd974aef116b73cabeb2bba98635841c2b4d2aea833e35eb1db9fa9a9d33bf7b51c49a14907dbc6036b027a039192b47406bcc56bccf375fbdf40b82ac4b3c660a43d5a6eb656868d383cebd099d2a73506f675cf29649617fe06097a46de93c13d1e590ef2cc71
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 4331f18a94c169cf0253136bc4eb7480c9fa4401c18db1194371dd53e5f7b75f07ec2e1e1c4116a5d2a8b2cded4b22925b67a88af9b8479c6e821d58cec7ed9f780a4c41e729982cb33f69b87d01c11cb9a8f7952db1920b6eb2124fd5d820555a99327117d7e8e26d18e748fea3ebc17e1d07161fda57a21a70c7f4e251612c
+A = 5e7d4ef7d6ace6cb106e38d96085d3f3505983fd952498af3c1d9b2af61e4ba10e14961b339c6e64e11ac758d5fa18c3222138290866970d67d0a4f4e19f453503eb8dfb85b44d1050c86943e7c5d6faf7851bedf7d0cb6b13d2acee25372243591d37dd230907457fb440f83b62395f80f59a2d02b87134887406a78efd77614f3193e517f234434ab3be084f1484d3f2c1f68c67c0d6e863585a8a5ddd0be
+B = 114b6e6726433ea88a2ba965f0881beb3ff4d377526e4e099741f069abfaf29e129a1f5fd243c6599f725a389728f755f9cad767ca1d6ae5c8b3a32102e47af211e86d67574bddfa42b2cb466d968f38b47333b1b55211fd9a315acd5ef62cfd3e83c13ee9d3fa20a06b2292177961dddc7dc39abad9ea31ead1fedd3d699f651b656edceebb0bace11bebd0cfa581dad577b8b42f0a844bcd8c8227880876dd7b0aad1
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 2468cdb1a26eaee34db3d2724e37f023c8a1788526b3dca99321b574685cc8303c609c85401a58fe6da181daf4111fe8c6d4b7428b1cd301cdb9bf8cb6f33140756c8b490d3b2e538ff294fd6471c4d17b9d9e4adeae0df088cb9daee18e825a368be57af4a096056b9e76b94c8d3b911b6a074ed41082926773a585007752ce
+A = 1e6a59efe0b14fa017c32ffd0962700fa9752242b06ffd0b604b9bfd125114d4e0909534ede704cdf1c9e88a6567f4a2989df752510d087d7b7afb515ad594627ece54b8a8e539074386121c9a3e1c12eb2641ded8719e56d42ef50e2f3b5d7d59f8a6f897174cc00a7449d2b91f33e9df07902a95479731a44fc4ebe8048c449bd515ef6cffed70ae78c832cd43491203a247fcfe0a403862266777947fc2542a
+B = -8a9d3646831dcc852fecc8e2335549e8baa2e2d82fcb90846ee82bcc715c716d4a9f62be29d5e1531db73c2186a4d2f118266de33d966b78f989600d772ffc55b1364117d6750cef67f4bae851e7e3f8fbdae7b79de7eab54cc1fee56e25d0632b2929e352c882ce78fd64dd0a1473e80b6572f0d4eb67f6bd6e45c7617314219d6f7de5e505a9b395096cd36650d23e8d57d6abfa9faaf0ddbff90d32865bf5ddddcaf28
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 2909d3aef7a21244efc9b5b16626e260907ac11f3d00647f2170ba37197e47b9767030195c2f6d5eda717a83a152141bffed2e26777417ecd8e27aed8666698c2e85a414dddd52b07b52b0da7e08b3217fa6a331f84820d21086a4424974e1e8cfed3501eb054242a9f8bf0803a94981b7b81776eca6d07cd50c050dddf81d68
+A = -73ecc8a6a1507fb5dad40677dc6ec75f0d130ea704d1e87b00d2bd56a6be21714bb30202739170b8dd3605f0553ff57439051efea2a97def70a6d2cc3fa2b9ec27a00c1338bbd588513f0f320272b8933fdf6635e585d1e79203efb5c95a454fcd7f33aa2aeac08902107e9bfb29587ce8610d50cdb7f2033c5b726742fa9f7f20b4780cf9244e6abf6b812171a64b870c3ca4c9e898d4c15e9f5b0194ae736c3783
+B = 4049ae926bb52e862606842bbcb4a5148bd1063b6a56f331cf10000c524b4aaa80b3bd914cd697ebc98d68bd3c2bd5c87fac4ec68606c264c56e25b19d118dc9f2eca19bebca07269714f2955e107b3fbf85530b1fe99c42d33031958280b8e8abea5a918a41cc7e6980149ad68fbf1c0041798d2046d7f88a395348b295858c61c2f33d8512b6fe75aa8fbad62e2f9b0b7876ef95af8a7b7338a2d6b25ec6355c276fc6ce23
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 22407e4fe280ff5a10eaf46d8e1f5a1e77a07410cba4106466d703b11764c60124fa355733b47327e952a12869476306926cabbd797fc80b4a6dedfbec0b7718ee754d447825cc405a98b85f1e09ebb9294c4a4636aebfc61af4545b921cbe759d3f389beece3f29c2c7c07691a4c46a1a72ce418a239fdec80df48732627866
+A = -1e165ca7e1eabd2ad1264d5ed9c3d2b687f2db5b507a0e4d21d9e042cd46e93c2444c6aea8491b5caba2d8146bac656b7754b7b1ae0f6216029c7167fd3b1c3ba2e20469d386d8566ebbc05cb51bf1f1eb2cad9dc4fa454b07cc1bcdb9b8f5a43e354c4e0f4e62d52798f667080a0e0a15414391269fe8c92f06da74f6209a3b215adafa1eb6866f8b3e419468e2e5b4db0d0ada80514249320cecf034477977bcceb91
+B = -3f314681eaa4cb41a3feae8467f7d76b8b05939731fdfc943235aa4d67bdca30e64de541d17a8971e829bc0159384643672bdffbc93b3eaded7844d824604f46aa58b1f1b9d788106aff53438954af015a0387268266a6ba262e2fe7a4c51b5af6ff7f918674b7407ce8282f66e84fd2582edd809b465e4401c67e5faaa9e5748c06e3bb8ddb23fa649ccaf9657dbf79b937eb8959aae8d5bd9513c1e601c0e536cf60c4fc3802d
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 385ba217033463cd9cb882fe30373c2d8e8475dee54aba1ca9713a709f40844905c2544ad792784cc8eafbb412dd68de6f98522dfca1c3de8e3bf4cbd09bee4656c4341153b17c98f9ac09411d16ec9880835cae772bdd8eee51eaba7c02ca6a1034c2c5d2d48e7ae3eb0e22f59bf69537ab6f1e49e58a71c64b8934113eb069
+A = 5137226623f4ce4dc9b80a783777ef4e53ad3c2ec648264db472c517a96383ba1173e52c2659a97ce36341a11e832f4ad293b89696f91a051c35bb1db6182260d4a276d1a9b4be848c206899f87a361d318d38b4073a7470c5743b816cbbc3bc1b20dfd7971b11ad4e20d947e352d42760104a5a3cc590b985ee3b5e98c779e38d2581413a2208d31873f9644ec979602671c9da72fa6f66c603c1bb6d8e690dba8bf4933
+B = 13b45d4105e3f5e8e0ba36c812faeafccea2f1a30e2ce8ffad57ffe0dadeae3a23e813758f270423ecda3da083b42432eead7f04842db8865f9f1e2226a3d298ec1895ae69adc55d1d338c3fb787f0676664564eefe46ca95206e81678cf1a2f173c52d809b1e06641a9b467f191ea09fcdc597271eb43da1a9a856784972ce0eeedd49ad363dee882438f09863ba5af063925871c525c6c0ffdca428054e039e149a424c6d1b5b2b4
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 7865f718cb30026837ca006f5cd997c5b917726ac6d9bd8c3fb9eabda0854d528d6cfc10e4cd3f93f6848582690c6a83955072daefc6959d33192fcf42a111650e50776ba9ae43d3d26e0ef2c6b60c3871aec33eda8c56353903e7ae96592fbf350b88d2f56e03f7f327022a2aa9b7c484a000135b85bbaba6f8836cbfc81901
+A = 16978c06a03276fa2e0bea45740a98d55fccc9d27321fd0a5b8522298a2a90d391c06c5c59e7eca85efeb9b4c91d4a1e9178adf816d597311f004ef98d209b59a2d4b901fa14c57b7297861ee58b89c9b2e931e4ce5818dd4006f3c40168bb4d3dbbd059c1f1cc24ecdc64d37df16b8e8d0529247c06f905ca88a5d283ca1b9e6856fbe8115a326061905b369791772a47900974339722d19b3aac16a0bedd93e1e4e4289bb8
+B = -de6dad276dcc0a9e271ad523620ec570fe6e3b350b934932ebbe36dd571edcde968b6590be14326e0f6394c0a2172052ff8dbc3ff15d94fb6e36a098286333768a84fd0404dfa354173d01f98484fb20897c439c48952b7f1791209fed94e9e72bfb3df5f368d420d587ae8bf036db6700f77b130459e9de2a541ed885c69c5641defa9436a4f7a69d2848d0e5d1074f77fa688b6dcc4d4c7de25a3b1b040546ef7f418112127cff173b
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 2d3dfd14e7ec60f842d1db83e29a0f6b052990fe8900887dc44476ed3948870c57e72e91e1941c476baa6aa86f76dd8ab6e6ea41707242c46d39b54215bebdb1f28e59d719fde18bea9994610214ea68ad9f2da24e1ad8a06f8bc698f8e76379ff332a2745af472d52a4b8e57d60280e19f93d5be669e0832824321e9ad8e76b
+A = -5144d5ca834f7bbb35d3fb95818c1f89ebe08efdffd35993a7691c05aa1b67f6a28e219b27fdcb66e516097c9ef5f00e4257c561b1f94c52c577471cfcd7a55314d3b0fa308b59449a36adc884c48ef5f34753bea746bd6fab2f20b86814c9fe50e8abaab742916313a50e3c390c67fda8e3729ee3329dc5e4b7d3107083aa3a07daf7952ebbcfea15fae7338cd0b114e9ab2f81dc2e80f90abff7a7ac59e3aecf76fab87633ec
+B = 48b927a46dbc4e23d714b256084fdc7cb9d4c96a988a71c956e0bf98785ebc9bf22b9d5c6ba0c419e60afbef7b96cc0c4a13e397aa2d2dd7995875d2ccb127169423455d138131199a263151f28d232ff4ae24e316907ace1fedd02a02cb5ff9c831de33e6702010fee2232bbe3c1c193ce792eadcad0c81e7d7c17e49168377b68690bc61f22dfddb17d82a3b993804726037cfac8aabe8548befc52a3c6c6baaec89a392133cd9c45b1b5
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 3f66970f600a9d09d73fd1ff813e977f539d69fe1784b8a2f99506d868418e4b47338ee0cbceed555f88824f98ffed39befb69e8907a5822ef7cd2a9950a070aec8fe4db9d68e1c0620f9eab4ab529c7e69466e325fe1c6c011bf7ab62bfd1a136597d7d5c47e8eb161ea048477bedc88fa30e4f7ddab2cfeec3fd0bb3fb61a3
+A = -1343c391be3f2b72c4b79d8d6091389c9602e97774b18eabeaae81fc0539336cd8c899341cf75fa758421c7f32eba9df474c934642003408b32db66cfa92e6e414b42b1d49c7e655ffb4c80f5bbff8d2774ee4f7198839680175e1ffec0428939653c6697eb3681d0f92634cab1cabc63f423d5a71d65fc7150aaeea74f9e0153923a1c65dee4a165e6a01a88655fbecd2db7697f4d2b49fca2508e2b8f84129785d36d88bcf59f4e
+B = -225a0a4afdde6f6450f28736c3ef6e67d67ec6206a63b11763bc6e69b03f1494b275ac504868caa6d56d684a12dc1098ab0d030583e73a2f45a42b8607c0f19031b9c5f07fb71919868911806d210d43aaaced5894e844881e89bab85a203af9ec3adb105e50b4250343ca50c26df14c46d73a22c2e4804d26d44ff0bbcc13d0dc7e326c9e4eb441f493c9743ae0eea0de045e05d19ac32d2379196a165e63ba640ca42e4861caa24c29cbfabc
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 54e95e86e87bc220c8f53f8485402327885be34e34063a1b81e52a23fc3056758cea1c039ac4e513f70ed9d394f5806fb771dca8e342368184e674e6296b9a705c6380bdaf11550cffc73f9f55b9385c85fb648f105f11138a3e1f9dc0a39a0f9755f8328701484d45784e3e4b2ebddb32c9d9132867c6513201116428b791cf
+A = 5f1239e0b5dbfefaba906bfd9003336489ffdf634333cec2484c582dbc19b66782ba40942d047c3749597ec4d89ef61b7803d33a9842f0c903461be37c679ca213aea894d36c1e12bbcaa1c679599d2adda9bd23e712dd0d0bd3f91d146e7a04f3e7ddec8b0db7e12377ab32ba241ed1e01da070c1f3ec85efd8387a7b9421453969ecba8cbdeeeaae6ddb098084bcd250601af780960c32f0a1ad7d7e61fb19f40dff1060c5f332830
+B = 1113f145de014bb6dd6ca05de159b97e9736c45bd3bbd8477f739daf79615fe329ce948cab9787838d7daf797218af5ba7925685ea341b802690bc9588ba3e916145cd3ae9d0c4a149637b890cf50fdfa8f89a62e508eec68f9332787733aacdd57ec1f359ff7fde76138d5b33d32e64cf7d252f2bcff14be3adb1afd8da9dc930f5261e6d715ac75752b29f083bb1de7b0b89ddba633b8137f3fd299a7f77abf79781a10d897e7bf2c958a097227
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 6e0160eaac8e1c31cd3cb6c5fb91ba086d033b4b69e41dfffce7569e61770f6629f23e12f0074c47c46653bbba94701ca798e1a242f7c4e25708d3acb5af6ea307b95cfa220f8879cb4cfff96b843d6eeed2b15c8f1bb21bb2b511cefbad0618d49d9ba33cade6da6ab3b846a6a24e35fb36d41201d3b85be831522b9bf509e0
+A = 14f4e24627c773527ed2243c0d1947395aba5c9cf95ae62a48827ffc1477614ad9c7aaea4b4fdd97e3272d3e220601565aebf87928c301656e9edb08d6e680de845615bb3a81c61ed043adb9d708ec1447f057087211673fa6ad8977166a2b4a8079a4f29d48e7fdd6875ccad05d2c219922b814589996cd9642ea2b798197407acd274da30d3ca008fefb40a25b38cb6042a581393283d6448cc69df9a5dc2b0777052566a8608a1010d7
+B = -b4188ebc5bf3ba31cf7c5e100e79806e92ff6f863c3d68a66aeb3ae8385f596dabe6f627f3812d0f2baea319d93ae00de41ab65e42eae7d396cc8fd0a2dfd35f303117fde4db5e8438df0c2b3b680dca538b42a7c844a9bf0d3697fc89ad0a73594627578dabdc214e0f4aa06b40987aed473e7f42d318bebf7392d9c898b4b8d73a94726aef65807b2ff746d4a9aa76303ed7b4fefbab34f5c87c2df82d20457f68289f7b96dbeab581294974e322c
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 8dd91f390c1f85f153f332de17e5de82979755d835398cdf3dbda1ee73c68f8e7565a964ae33fd5b1f1060572bb3af67eec79c4c3e2eb4de118d471f74351b80a5dcafc682bc3cfde642e611ac1d5bc2c49b308c30985b1161c4d78cf7621b503e2dfaceed886befc004f3a729b4a9bcbb8f13791d973bf38fb8101d6b7a4d4d
+A = -70e99398673324ee83495aa0aadfffd7bb9c94ee5251fff365124fabc50175d794fa84509f034c2b86d83607789338b0eebdbbf709a129a0ed0afd21c130d94b279c56f1c7c1eacfc6cd13f724a9352b2b37412242a47b23ec61ef0040a8855371aaf238003c45ab9d18a66cc7dab9653b93c323815e5404762d3f964d4654a6995af507bb2db2149eea59acd72af4d034217eaec0be5ba1d23890081a6a234e125572e3bcf68a6ea52d9437
+B = 661d8832671a4974b493e5d71e547cd46b36730f4017e50c5d1a7520fbb75f0314cbc2ac948744dd494d566ba580a2108106b120a797cfeb1fbfdefdab6bd6b2e073f90c77e814cafd0b7f79afeecd59778b1dfee3446fb32139b2311011576674f96f151f896b477c631237995e11e61e715dd8dd38e802af93124c66eee735c472972000cb4788b26752a630ba63b45e8ebbd979f0a4da5b359abd2905f0b7f3a21b1d381cd02ac08e284218ce41c907
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 2b591d2c57f6a5484b43cd7ca247c48a1b38319e843257331c8807d499c7763de4eefed529e70d4c144e5e843ac00ee8d106d0d82163cfb7afe528a7daad8e7ed105942d1128a67e38d59325cffc0c3dab9185247e0082e3ccca82a900d917c9bd0f892d4b518a752f8e9d38eab2acaf3b3b59f15b0fe4cb9a3dabe6e0191493
+A = -1896f67485a740720e23e1642ef02742ce5f10a92e51af19e112cc99c0fbddb60d7190086c942d293d076b474d056e74ec9f0c42055d745a57ba370c51ab2b761d889b766cec909811e2b2fd11d6916b753ae00622f038a4bc55b813a5d06e6ac136e81689407de721ee852cd21ea989ea7c8cbd00b64614caf0974a62097b2eb865f46fdb0c1a2e4f2d839066b797e51392e5ebd14dd92630c070acb546dc7438631fef01594878643a4cf77f6
+B = -3a8e2f3b8378a2605f5affa21c4fadcc655f2f8357a3427d2cec0118e55fc2bbc25931259e294d91bde8dcbacd39e6cbc125683da7d0dcbbc67d7c5866f08e7c4732cd4384d9366868370ea40a75beb23b81306303da4a3e26ad357c5c743d0a4ae775a472afddf8f21cb4a1a3350bb6aa71037607c334a0c79468668d3e727cf1d0610e49f27780901c68aecf1d145953e45f5b090855be714cb39aba2efb0f7db2786b331dd9bb8843de8c73c95ab13b6b1
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 2f53bdd643b5b22445e2af3667a93de52f8bc7bc151e196c0ab0bf3b4e4dc0e5dae9e507508711a9e3de52e2aeece6aff7fc8a1db65588de3272839390a35a847e29204d3b9b70e10352c88a10c86cd33e067fb530d20a3a5ffe67938c5a7a9218f1164f36a73324adef64da64d5fa5540d29a76a87ce010fb7d73a59b109280
+A = 75e31ab221c08b3bd73bed03f878bf7742f9b36a89bbfa7e90f9b05ec11edeb0140dcff6e9ad1d62cd7af34bb4284b3a52bf1b48a40f744b561d9ece056a9405ab15f508700b14914e4f427ea1df3093497410a0108066e9b259c1a26ea72082b3cf0e3a99ad054804da7bfa0200d93d65354b75e605b47a4e1e17ef851a37c59a95e1b5172801e6ecabf70f1e6e382740998fcfd8a297aaaba7d04b668e3d6eed40358247767323a8393ec359628
+B = 107aca18938a9cb244ad646a37a212859b3dda7518a5827aa2146b47bfb3bd08d772eb7a866e1f674aab7a1c74cfdc2bc6e9ad1a365686213655b2c7b1977855bcd42ccecb804bc01d92bd7d2667069d853f18a0f0661f028955e39f71ee82b9ce6a81dfb2951b33b123e71264e819bba4d0a8c53a1d99964ad9ffb58b7cb5cfcd3e30b1baf5aa5b3cbd20a0df7ec37563e2b32b4cba91bbf3bb6fd1cbfb2fe0f84d720efdf36e9645c7e9ec70442ea5174528bb
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 32d16f7ae2632b5cec2e90c34d191599acd9a1b5f97845595988c1d0d4ceb9acfafbc4aeee9924ce55e109ec88c57610fddc664316e0f9a5e3ed56ea447111c0383ecdf117ab42351b80e72720a4b1d98d4c73f5235507c5b4f7849d5e9b527d054858c0436ac3d2de2704c4bc25de4cc702f5880d5ae34094766938bee555c8
+A = 133a439cf006c753c132a8559ea13c64f598c5f8bd5043b89d04d7ecbf0ec58b225551c8df8dcb341198fb0b487774867e5b68f9058f58b3cc98168fbed0d0ffa86bf74b4fb0d4235976fa86d52b8dc7e82df176d70892954223cc484ae58b6a60459a9a0803ab856ff9699789172b163615e322e193bd758016f634c83cf50403e416ae241d9b1e44add17c2a663771ac88cf8b9dd94622d80d879ae41f0f4e7a1a32a1ab164f981900fc159aa85d82
+B = -fef33e21c07dc26a47d692c3094205bf4efae6af32f1c0f46ee579c1a22746a3663d66f2919f46f973fe558c61264157d531e66bb9ea10b4b49d9f6ad3ad8762a6ea8169a9cfe01d3dd65518c2e6e58e8c88d1b2f42d207399d7326752560cd45d0ff571309301683770793fe3765c1337d14021d39ea6980934c5fefadb93047ef07c807d0ea5625ae0cefd098988d6eb7af993c062ba313e23176e7abdebcc6e566304a5f9e03da05bc1cc58dfbbc898a67a5941
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 20877c7f53fca97f8e484ba31f23dcf51ac0f4fe4c5121eec576e043c6ec5492725f1b9f9ecfa64195f71909500a69fab2e591377cc2120bd5f60d3fb3812f9e80b2f6c787e0081c1439dbea76b819ab44bf6bffe87dffd771a870e4f5502609249c5260f91175fb217a9eece4166540be877d564049389306e0d6b313706297
+A = -534042b0811c9afca04d20d83898e7653f91a73de1e4b516f3228c6d6d9b963c7f8f4c36e05383da90f4edd072a7eda382c47b84b46b4dfa16f269c2d9ad0fc53ed2ce51cd31e4e32d0c1ee21604d3c7eed2deb35cf8df6fe1c0740a1515e4c702a2074ad6c0fcd403603b4a4e2195d19b265958ae854ccb0b41cf22480389a053f71544cf594f6833f3e4d91fd3d9091df0978d04d3922ed72a4fa3579c5fff50eee812dfb2a334148227a0f5739f8ac6
+B = 6935a3444434b0b03d27545721e253e4281884da027246e46ddefb01fa7cf7a9a030581dfe618431a68ef6d79b03b34f3ed598e7c8ac030e2b4cc887dd31664604fb8afe4e71fbc3135d6d3b4e596044d6b615de7184ebf8dae8fd58506286ae4d3b797aea911eb59ada39dac756d0e9eb6a6c767ab77b9348929a00f8e311f639d19ed88c86eb91f0d4cfddd34e98130eb520fcd2b77507c24b6804d3d65d1b21e6f6d55d1f6e92bba0544829687a096be79eaad7d88
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 24823628d4fe9540103ce5f611f8a6ccf18788120280179a40c2636f30a13e5076503e8a4b6b6ffca21da5b0f9f0d85feb2ce10b51292ed069f35289ebf5130972d720d20dfb8e6ee80c3ac598570d38e57ba33dbd75f1b03eab7847d865c3e8e471ccaf302461a6136dd13b8d31c9f163799a3c24c7284b8826608a9543816d
+A = -1d476cc98529efe5b926aba3160b261723b009e9b880bdea04e9b5b03f173040ffafd1627b38be8e00840e85d7acd3abbae2f7a60b305256b920c2b25a8a4373ebbf1a0c69f6e74792cb0d849872500519b6d1c190da30c572e26b44590b7ffdb464a900fc38db013feecf909b43bea549e05f1b7e70d6ad879c613293cf61f0cecdba1a6565eff1bfcdf740bf553ffd5bb7d74f7e9537897184c527b990dea20387bab0dec3e32727786bb14975b23ff09f8
+B = -2b6e12c87ad91a2fa878b9245875209cbfef400e637b557c868ccbd6e94dae65f1ef8caab61f292d739b139e384137a747210c09ee6f3b2ceb6dd212e14525852b8c54215191e116b7097f6729f6426a8bebdff86cdc16effa08d932ab512d7265cc0f57303aa5e6fd2afe0a45180557935c230558d02c3030b38ca88de5fc75c1240d25a22fe32c4e5096aad0078d50989812d7dd0cbb02c736fa563efd32d14109c44297cdb3d4fa3b93a2e15bbb6eb678e93e943979c2
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 2c4bc23d0b4b1f79141be9149ee20cc9f1b58ee0a76d5f4205e0862492c18daa20171285d6ff0b600c358be487e78cb5450d151efcff8d53004eece94c5a37f49a15fb2b5f62a79568382cf0a4232407b139e1ec5a9595bee8435b4f138dd72fdc2946b03817e49864812b7b61f179bdd8389791178a95bb6311df0a5c60db2
+A = 5b0a181f07068af6e1e4b715d92c1b8391949a1e3cf0fe0aa49f3333c826f5582615d39ec28b1367804c1ef54f15fb83b3c578ef3ae957fc89ef22a343175df3ef2fd425f724ec1c3363aa000ef624d64c6d678a4cbd90b41cf7d69a7e03dd60c5d3470dbb75228b34d35469847772ff3d74b1a89a2c492c082d3ddb45ba4df6e3f228de6c64913b79679cbbbc36a2924e722c2c640d0c5a0e90ae86b5364dfbfae80df3d75823aa58ac6c1da78e988a11831bf
+B = 19567bbcf615b777b35fa7030db7da18126cd695ca7dda67f5146c97beeb20df24ba0fda4a4f03523a0d9b9f85d9acbdb5793ecf9c1f4ceac81299a1aa34417779175a4bddc0e95ac68309da51e4f115dad6fec33a75d0c5520692a38df64e8d684c9304f9e2e6ac6a66d2e16a03c19a30efcac712aed2b9ee774ea28af4f37c45609464289de3f9be379c733d711875216bc223f2f468a0c9b4a8277bfe49c590ebce2e027102537bddbf2856c3b6e9389c4d1f5390cb0f346
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 36e1e0b44e5afc35d1e19e88e75f030569eb99d326721ced9bd7416ea7367a98305354eeafd204f1f8a652a8442eb0823d2e6644e6320933ac481a3709777381dce8a7c165b23aebf31b2ea2745ce5b352acdf0707234c824da9e1af98bbedf80e940fba00c229539f310838bd625f1fc103f267265ac1243855622c5df72c17
+A = 1dba8bd9d1e6cdc117a5a01b5046353084946fdddf2696f831a942d9db4637a5ee76b84d4ba63156b8cbc72e40559a2fe9b8e2682d8ba1db0cea042bb86f8ed71f6609df52526c42e7494f6114bb62263d36784dd55d396018b8fa47fa49ca6e5c76ebb0b00e6c764e36cb3ec75e3af6a2c14dee01fab78070239638521743d04f184dae79d49a2bf209ddeb4cc72e0c94a93a47c107f5369070ad95ffce034c554fe2a8391e67f817c6cab5b88ae9748072da5c9c
+B = -849602ea3b79b33af2bd3ef9d1250c507d332e759d428902dbee054fdbcdcdc0a357a51d00aaafdacd696a15a64cbbdb7e1fdb347be5ddb1f609a4390a6f29f79ccdb51bd1f0547d0d9a2780517f8753a906428fd236f8ee1b433e57f2810d0ad51846304a5729f53a871d8b0e14355d24d3f092e50de4f044e2b8aa14cd8a51fbb2ff36b0b37defa7be768c56fbd4f5169d9d4698fb9072cbb0a037c219552728587d7c35f27456c02020f5f9374b6c53bcf8eeaa14be51899d3
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 77eb3cb5277ced02b72368e41f04a35796c2c6cc1273f109336fdfa745aba7c755b6ff3833e9b124d9c78584f6bfda1c94273522f020371107870c288592b7c23964320729d2308bac8813586e72078119852e1d7706d8e15c195486b8d94358736869b15d59c037ba4dc8032ceaa31eac3a9e3dc51ee17706a6956cff8537b8
+A = -6a0753edddef8b74f762bf802d7fe9b38638923ee2d81bfdda354d40df4422e6ac43724de1715c4088da2e68b63c10c90b236d7dcab39b9a0ecbce57628f4c2950c79cc88a89daa20d7a8679232c8ce5fa30525c56011570107697222e0eaee6871adced52ba01a3aea0ccc9901cb3a09eb4db2f93aba0083180bb41f3f9eaae00fb458381213dad01997e9b88f21b0a79ada1ec3837ac2b63611455fab6839363b796b105c3be6106ff284544bda2a32352bbce6ef8
+B = 542c5fde65111ec8a38d76d8c5735cee17329dc41cfd0f13bf47e6d0e0093a129f3449db380ee9a70ec1e44640839ff18b950c8fd89346cb4701ef753e6ef49dfd9bd27d9987e572bf8e68df399cf945813582fa1d33e07be938a7729efd9a5e7d730bf61c537770a0727f6bb9ea6add5aac9267bf910eac1b7d92ab4184734ef8b1d184c292b2b4295ec1bfd17b8a2a2e4d315a8b37b8ff9bf6a1e94a4772267195c5a7ea6f0a0c267337fb97a023f1b50ad697ea31451192cebcbb
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = 660a1f378a23fc3b47f693a347d90640fef43add9729d74546933f4b78a26968cc9a70ad6fe8d85bf28164881bf7a99e8b96683c6f4fb54162c144f99a27e3feb736f0d382d7e5b934cfa835c723191e5692b7672cf6918c4a7a93b24af00b1beaf1b80320b14cf2d1539e3376779872542406a5df961f765e59f3480e1cd40b
+A = -1cd74c052e62ee8156ba5d97f28aada75211979b1c5925ed015ea75f693a04c4dd0a705f6a723ae7b79958884c96fc07f81fca064ce2affc70768923bfbca6049952eea3ae048425b7c6ad1611ed4b8b77f7605629b9d198a77a27f25eff2f82867845cc868edee4ae31afc5d022b2ffbf43c14fa01bef8d7cd9d0e58362a0ff9abbf250e43ea5065512cd707791ea4868e95d8fd2357b3b3aec1a06888ae940751ceab01cf9e49015d42371fac30d48ef5853b6894ca83
+B = -2ac904d3632e25a4d536097d80a157791a6aca6eb10246ea21f4cae07aafe907c6e4c726694e14ce12e376c02d326f4bfc02ed539a5b4615a3cf5c838ffa52124f9b843598a3821cf9f1fe94e7206d6a525fad1ef77e7e77162e8c6d3d860d4f568e8f81153dc47f167860cd52c1ca59b15f1eaac6b9023c8b375bb63b6adf6972af8ca62b39f044378b11c4a969f3939d9fed5cbe18c06749956c7acbf963f640a1e1ceab73fc4c77463ee8d1575d018f49bf0f08161ce4f88aaab5a70
+M = 8e2ba940fc5165c6c5f7f4cb56a6fde2fab687651099c880d38f6eff2889f6a3b2a3a186d1fee05ed452d11ac712cfd30340d22da763af7b2ff65a3f6e202e8b4f42cf5652c625fd9913b4a032ea9448591b9a839b8c25d2323cc2d0d3bf7a6d15896aa85237b6ac4c9c9a854a23449e30e6a2b7c4a2aee199bc20d30af280fb
+
+ModMul = cbbeda9c467ca801ec66fce801c6765a20148787dc6becb199a15c58fae8d20c1d391a1d9d57e1c74bb412e1b8f271dc2cc53c3355c83f3e2f00f15eaf0df735160a48e2273fd1bd75533cf94c5175ce67e79fa6c1422996fae36ba288a658a7a5422a59d39dd81ddea50979e933efc02
+A = 7ea551efeccda23622a1a5029e5525f46d5ccb83c28ec9adb7a3e97c2b7d936238c483a4a9bc92fe0e21208d5703611e2795b91fd5019272d255eeb
+B = 19bd92c534f56dc4235dfb7efff6d941112d66acf81b079382c86fb10dc5473bb8adebfa53ea3fe6e4df8412e7807aed029694ca786
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = b18a9cd6a0a89578ea773fbfbf642e05935a995a38bbd54480ea3ecea1751370ef95ff5ad0e3203613f0ef6833237d549676a95b720848c5e9897cda82642a2f373951d5746b559bae2d98ac00fae26e5957c61ac1de95318b1b1aa6d5c64a6ceb6575f1b807060f9e2a241e378e6ebd72ade7d2df18d5353db7737caf52f888
+A = 13c68e450e9e091ae45863f6c1faed25906dcd90a43620b1a40e7a506e7a954256bab0225f3678e7ce6c4ba6e3a83c8f04a3491d9bf097adbd98fa6e78
+B = -ddef76382342178fa6636e62887fce6e19590065c766b047073329ea15fbba96f2cf088fa5a989f6ee3f6a513fbf66f621c6ea6ef2fe8
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = b18a9cd6a0a89578ea772021f58ce74cbdd8c44a09b3937b198adbd8e95e8e35541eca26438351bfdcd8600b4f9b71616e1f16cee707c712d40da9a440681f8c8647bc90ba4c68b08ce4cbca458bebd5110222f06b2ca980a2e9419e71064324e8c36289eff9c67f6d5d011e6db8538a54aeff8c20800b0949fa42c38fbabfa1
+A = -6d7e88715e9854b435876fc9bb2d25218a1451efb73ad9cc5f52b2bee929530e6618a858000b3f24fa5f47b5f461c84eca971e38cda6e1f475f6612ec32f
+B = 49eb76e4614ac7b0ed3f534811a4ea6da5ea24be925ffeaa38bb228fa117ed56ae976b590d6c9d9a7a8546d8a6ebe4bba771d6587ac44f09
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 44f8596fc06afdb72a6e4f876b70b8d5d734589f41089c510b0da60ade642fd79cf8e705f09910912624fa1f646da596c137f124ec1a327beccba62a44f228f3c0977fda2af631e249b2a4de17d170df07bd812c233a96d17e1e93910267682d24c5c485f99aeeddceb658a7db258a2fdf73eb0266d26b92e
+A = -122231b14c249820f0dae625342415f0c6e7f93787b4206b79e9ecaeb09623636730810c7936e17a1eece68edc7c97218efb17c069bc59bdb9681a79c910c4a
+B = -3cdaed858523fd55553ef85d018c1097d7b88f6c30060d1e77b84821ca20b5625723c7d4331ccad1a70371eacc7f7aa11220f83f1bf3595650b
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 6de7efcfbc1e8d2cb14cbe4465c4ef71f0d1d7e80a1d80d9ac2d0b161d45fc9d915c54e33131591e8daeaa11ce02404c9b8494added1bd83e344ad4de7c04f626315caa56fcc5ca2ddd4e1ff064a2957afeb5d280477bf1f1195c7294d89049024fe821dceb53c7d270a8b4653e2fc0a4d8a3863a854bc3794753a
+A = 47423c4fec1eb6779fd23e3d4070d0a7bf9a946f5610eb469876797a39c58577242daef8c34926f6974089fc595508d9c573d0a275cbeaf37172f10b8c849a493
+B = 18ad789cf09e9ea182eaf43b28b4f2540e533f0fccad325430b73101c00e440bb64b70ce0f2680184aa8caea2f6f6517e9b80285fea8b61887a41e
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = b18a906994d3247bf8a00f20e4b349a500159d086aa863772e71a68f91af9d19e4c021843f8bb6eeed1df708d55047dc8faf219e00d559517632dbd1cbf4bda61651b9644481d052903be1970f04bb4ee8faab9adbbf858324e6cf5aa9384ceba655a1a107210a9497552ba8a56d5e0e70b0c757baa71d1613683707357827f0
+A = 122773509ee608cd9ab3ff6763629a18eae41be64bcfb05122e0b3e112db48c64d2a5a515d96a042850c1c848ae5fd5f0ccc57b273d25bd8d68568cb00bb17b1589c
+B = -af398208c01ec9700e332f3e694894c7cc412a73bde8a79e08764ded92f0d58db8056883972c79a0c9e0ce810786cdaa3629baeb9e5c370a5a59d3ba
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 64ef5e7063a1d95226569a27218e35e93d870a19a43fba9889a2ca98ca5c573fa56ebd77f1403b3bcad17c1351803a809c245a97bbe32b45e21768f28c5b11ad542f5e687a17f7811df6c8735e1778e94d9313c19fa32a6703af7ccbd88b489c96632d10eebb580cde3b905f6345a2a2b86a871b4fab36fa4b0dab9a6c1c5096
+A = -7dbdc37a51b601417efdda2516aba15827a40ffc304c523a47c544d5c0bba6c1367a20d8a6268a5c3f723b1b68de57eceabbb00d44185ec4ba7ecdce5d80456f8cfe7e
+B = 641cf85fcb5fbacd6214be4b7b06fda1b80f4683c21c1d08311f6e23a15434b42d30a51912898a1c46b46c00aef7ab7663ecba683897825a4b07d2b7dd7
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 370f20360ac844bf4275f78b7fe71ba5db6f0bbabfbac3384c04b256eddaf04725d2d57b31afa48f047aade156c34441b4a41c0b2146790a2e15d13b584021ad55965588c6e55ed3b5cf5c36b780a27c5dfb72678d57528ab17ca2ac696aed3d9abb0ca448d9d5789fe37e632fa9709f3bb924c4ce34244d239a940dcddd9c77
+A = -1a0cc5b07271098a23f01b3c0d47cab8b294794b74a8b162ff3b313fcf85ea81fc99433cdf4450970311e1d5ff81e9ba27eb867073ed250aaa7795e44ba8d4000e879bf31
+B = -308f93984acb78c5dac2426d9bccc2e3ac361143807c7d34c24ef8f8db5e68a904ac8bfed1edf3cc90d21c87ae4d224b8c46fa42eea77797f94aa848160fef
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 4c8f466d1d9829aaca1a22fb6ca5bdba885606b9264933ac2b4c18e3afc0c406aa71ee7ff490fcaa804f457096e44576ff8096fb1d2b3c68450a8bc36d1a2797ab8b621ddc91d75e7d6ba01d86e959171fa428a5bb1f26766f94a553c94f6dcc2e0af90d7776ed3d9fb67e842e88f7d7342afd86e2f5d159db7304ae4d204a3f
+A = 57e894e37159cf3c161be9c97a946454e43bf09a7ae8e1437570a86c6b06f84005c1463d27d726afd2e25aebb1657eb78957a9a12c8749049d12007a81d766dbe008aad6d83
+B = 16dba5cf077403ff4af47438f5840f65fa4e058c5cab3cb730154ae0fcc982ea097c6d0e75bbd635e97314f33ec7e31f0e41cf285ecfafaf36382b33d5e83cd55
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 29d13ec304f26247a45ab6869720720fe019d6cf370b9e2df9a65828214aeb4f8b17969b8dd54339d08eb99bbc66720ed78ef79033fdce6da33501fa8588af86ec18be4c4ecfe01781f9d1379865100dbbc020b892e77027d1f04f8171ca51fb73129dd9a96568904eb44e19f56f842b223724a9ffe28826803185e4208f0ff0
+A = 135ebb133a0beb909101da896e3aad7e26ea72b23e60802e54cc6c58a07b1205e2ba1fef6eb86c420f011b70e3f725aaf9fd1873b6e1c1cc7005c7c09e55550414875cfe846357
+B = -e8cbf3feb7be7fd12b01d5bd024e47538f434b496613320ad71f48a8972f687992f97e4b69b5842d2d6a4176a5701327c40325e98b27e4c0f8fee5a457d92181e40
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 4309b728306535bafa6787dd79e58324b3f86eb5409d772018cce2159f75832b87909a672b8b4b14342b352e76ec5a6dd66737cb0a20b81c5ce222133bfddfea878b132b6f9fd557133973a0b44aa41a01d54ab565d6b9c62da67378a4058255047a95923daf5f0f7adff2a3f06074ab1facd986d7d26cb475ee818199a390b6
+A = -7a63e108bc9790ab687e0fb8a1cbe1e9ff876e7b5eccfbc136ba05fed93412dbc2ffb1ec49518e9fb867429cea1d7f82e2b159b75bd40eb8370e8a54bf0e0ac0ff24aa3662774bae
+B = 51ee025b2ee8abf9dc5ebf1a4600131c00ae4b6bff966dae5c49ab5b9017e6b1abd6434736df6daabb2bde254022783764c94e66743dc752c9040563df7016a1581fe7
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = b9ddcb9ab858d2229cbfab87d87236e8206cf5e1a042eb5ddde201d56e2695a3d0b2a42bda6a284fbd2a5b2c2b80446ce88c024137780c277ec80bfa6e9d15397cc5bac98e58c9130756ed0fde58d475a033fd94b1fe0ecc6fd91a8b42177abf3f77e87c0847a4244b9fd4980f3b42c7c955836bc994f2babfdf9c5b43315ca
+A = -1f971ee9a7c966d1e82166503681afc280fab255665b850645321f67da8934baba1226e9efb59e0ac4483c8724f63556a213f2224b993e4e082eefff0056f7aa8a3cf5b655e0f72ddd6
+B = -39309313b04bda1103ca6f56514026538b4a29ae258a2a66424abe2c652b959f5c1dc4755ea37ebbfe404839505c2807ebe069c9abb9150205fe35bc286ca12b64ac46133
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 47555924c31f040619681d4a12064790e981db2c7853efa17e4d20f741f33c56d80862caf86bfe0730870b6c0afa9caf66e15047e60256fec29469d1760d5e9b77d79a84fcf7a1dcd0168a59f870f1635eb033e0ae0ac17bdb73da803206d48cfc1da48507cb812bea540daa2393321ccb0d88b57abdbf3a3bb765692a2c2ebe
+A = 754d78d5608fe8c7ed8e26a174fa27833a24c48d23f0e702454b7eb578cb107da537dda11027dd6b41daad329e036794de562d7623bed8d9b0e909cb3fa38d4d21a95c5f4246e0b030a32
+B = 1839baa8b8fb6575832136f1d4632f72f36cdbbdcbd00f197fff3cdb88b851cbd74910ef6d43cfae9d3248e9c85662d7fb596ae45a460feaf308823f06345bc5fae8823230af
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 9b2f026b11d0674e9ec060fdb24b45fceade3070db4405b363d53df1219a02a664882819fe602f430636fc0bda935b14c55c8a0bbcc9b6683417e3ffe7f5d58fae229122ac6e42e76899254295dc5a08ed43c79120a5e5e4124b8fa6048ee90836bd2de51bbd2c6b9b53212e913cde871f11bf32f91b3a78575a006da36627f0
+A = 11402b3b1a45d67cde9730062e38aafe1d04fb1f8bb1975f25cd9098813efa2727cb229adf9490267bd437220d9ffa05bb993e45d2f889f140faed3ac3c7b53216455a830d6edceb02e8db92
+B = -d8e011f18bde068badedce8106f6602429fbcac4766334a0101b57fe94603203a4a8975fa499d8a68198aefd9e68f28e68914f920eea1083e37c67d59476bca9819a8bd628b89c
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 3a74066e7eebd9b63a1dd28548be60573c95f29816f3b3ceef68a5f6bb797d7eb0b0f4ee612dca794ff82f5d7461d995b9dcc09649e2587639ea017865328bb5deef17b5283691724e8aa331d75c635d5e19ebfd268fe5471714aaca8b48aeb846f241c1675e18d35f029b132f81128f19028b0a471b3f75a530321135e35fbc
+A = -6c5dca3fb7b85573d1c8899868940794e428171e207b5f9f89fce4b7159236c0755e2959d870754e902e9c40dc1fddeeff6364f898ec0dd669283e6d26a612d9af3c3ab04468707bb8a7827756
+B = 5446269bbeb613e69286f1012ff62ea767965533624542f3b5c866cfb569d6193aa603061701992cb4873ea8b766606da1b57d7b37cf52f52bf85b58309387200b0ed36164f30d52e
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 2a4e727ac67451ca9dcba648050a085196460e4aa4836c5652de863c3e2a76213e0f590de3aee8639304c54a9dcd5f7d5d3592f647e3d07d322708e1e26329f4a31d66c7f2e9d482f22cd9823074dd57d14040a4f00ac2af9677a2c98d58ee1e094b1a8c40092e77eae454638bc3655e77441d4f218c637f95c147776f5bdac1
+A = -19fa688008a12cae228c6ac4982ecbc88da248d7ec785bf2289dc9103bfa3a91eb1e5fd6afe9e0cc035d3312e9ba64028fa6a229db6d0eaf8af43d8c410be7c689c3e557137ebd60d3fa04edb60cf
+B = -3e8c87fba4a41c3a84874c987acee9f560b9f027338b584a775c1fcabb766700f758c4d451077a9427257334a569037b0bd006375f71223add62eca19b1e26b86dde0cc251e48d3b60ef
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 52e4a3f6892b425b935c6f9d1396d2034eb0331cbc5241e1d745a9619fa0cf0fc521585cb9d6b1034c5fbbbbecdc81c757f768c7a82f6ca291cf5afc98500c579f82ccf0be233066730f738c205c3c188f94b878c11268871ba42a5d950dc8a399887997cef2b6b68badec1ca641b88d1455e6d97a2841da49df7eeb766b7be6
+A = 67df01e34a26e8239c8edc7ddfccc3850f39864ed237d4dd67588efbeaaed1f884105508f69e20ff6a5cfae1516f6179ae6fb515a66ef0a7d633ba4218c30875287ecd0cfeb5bafafc492619942f97a
+B = 19f5076405b3c81519c0863d0c963d545b2834343e42bb3c779788cbb46d89be3f775b62f4114268a0ca0e6af6c0dd659607d40071dfe7f1ad0df9a5c53b741c04612158de396e9c96f7523
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 8ac1d96abd2cbcaa8f7e3267b716f675aebd23694d24c112d202653979636d4d47e27cc36f850355cfc5ca16b78cd1848944f8759fbf6b03fbb7eb347536a9328a5cbb778a6bcd983081374a3f543b1380add14a9468358009ec2baa7ecdf13e7260968eea74083459406e8889936b2fb98c8b9a3597e5f9ca10b76e1dd0337f
+A = 1c9ab23ea37f324544280d176cc02762db7a39935f1ede9695b53a3ee2db49d0485c6a3742a3b5cfb51f3c21711bf89ed05afd0886bbf61cbd57b23439a8a165484ee8e4c0e1c0ca2b6478776aa2897d87
+B = -e30d28dd01655b7a419d939e3e7530258a667420fc759bad585802c63fe5efbb309cb502babdad0afb208aff5ce5830071c5a974604c69ee47f76fd87e2460a5b03a57ef0185881502625886f
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 5df0700adbd880a5730d8c0637a362a9d42c64503c3b9784046b946c2459a619b5bf804a41c92ed6370bba730c7d39fb2e01558f7ec38511b0449d6e9db8df2cece4ed348782ff1582396ca8b3196474e7e5817f8c197c44d771923b6e286e41e7e23c33fcd8765e06793169999544a310f2e080ffe13640b85f21a18fa11928
+A = -5c01fc52e86f3a344180bac284d2376d1bd693f20a46479c77fa57077df62f83b1e81c94e577d1d6733d276f9cf70555b20e3afcb97534e4e0108a6cce87e9292d78b2d7367ff15fb33d2c3289d2a2913b58
+B = 6bbc39283be06382ea91ad6b1630b38f32385ec90019d2ded7ca6fdaa39defbe22585be0df9c0cf613f6f146c71f901adf525336f6573f7f43e661c44b7097f110d4551e8c75449da8fd39201ca0
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 2a01005f1f387c4d8d24a365708e2506b044f86dfc011262d3577f7313a8f51ab943037361bed1858e021f8a46491a5c73284c666eb65cea1392a780219f13d7188721d7d4b975272293a5eef63480f30cc9618aa74bc51f4175246301a46fdbd34a6ec72d5974aa920be5f321a97b8f19c0ec56ba10eaf2e61f2b45f134b304
+A = -108bbd8824e8c16b81dfdd4dfee691e012e578cb9cc80cf050c0ec4cebf71a968732da36552979ffaccce6667e46c29144dab75132cb087681d5549dc5508f3719e129553fdc97f545d7ddb7d3a4fc575ea67c5
+B = -2ad4d4078c47a3c8f5f9b48e10d52d72349ecf0f54abc60bad63bbbf4d8efb185de90e5e1a686859e1c429e30977fca492aedbf084019e9ceb4490aa471776ed2e8a09151b37c5caed9ede66922b7ec
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = a1b1b2d33cb610f1b398e03f274ef39a583d13af14b79e6766859b9ca748237b481a3cfd5d490a073e82e3c53d3ff5cb6219b2b2f71927f27ab6f567547a22dd35fb5919e1ed2b6dfae4d536d6d44fa6216d94d26b33f52db06c4ecb29702588b73ebce87569639f786df4fcf569bb07d5379bf8b83743327248c2d71b5dec6a
+A = 5bc53b3895cff2bf7bf10e24fbdc43d17d277a982d5d92f17b9b5a2b9ed8b6104229292ef3997591e2e6a116fca21ad5d061ce438f33b7f7110293770f8313077152c7546cd522ef4054147edbe1878072b1043e6
+B = 1599b541c9809779df3ef40971e7a83f21564bd5d6596d51a3d96defa4dff41e83ca6247969a3dd9a746ab72ce21137f2d7ea015ac6b2ffa8a32997e8b821064d35afde3435b23e47cccafa74d5192535b
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 4fe8897417446c493725521c0ea5b2110f91a1b5ba236cbb6ff3f52b0036a49fc82274ca949ac2b592fa4bcc792114bf2f2a78a2cb44cb22c6fe7e4bee7981604de47f6da2ed1fc6a8eb32cd9b8aaca0f2feec76a2438126ae6f409645d897769a6d340308f82dbc6a98ac059fca6f903c5aecd668fa838b67300c654d4013e3
+A = 1717c6503d069103f10bb4b36427fbdd2371b30793e492e4161fe185b2e27469fef6a25566d6b46f6a7f97446315a22d1f1f662f912b17e71feb2c82411ed7eebb84d4f594deffee14934b75a845d83761f36141ecb7
+B = -8808f540521c20eefaa037fc5da782c891fdfc668b955eaa2e4edb592e027a964b4cfbc94c548d785d92992abe282d90dd137c4d76419926740ce138d567da7350d89f2e56772d8f5bcc9ca8d7076540fab3
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 8b9311808bef497d8a5d14f7d851567a196a051610246964917a1f9d4f4449357d2411ba9fd93983f6edd76b8a8e1501146b08b6e1fcdd97b6a41cf637b6ff0cff7a2d6351aa1ded93f8fc1cedc81879eef751bebfbd1559d5d0320595c79e3eb1db0951d7c67c663bc57a672faed9e14c7da6be6b0c6bcab3d4d515e51a0b5d
+A = -511312fce1849c3d177d42088e55d534f9f7096282916e16b041f66ea90e2cccddab5cec0ba8ebf0b047ccce72da349f420cc28ab19bc156c1cccdcf5216f19ea922698127f090e97444751dd58fe7a2c90197a9ab3d35
+B = 6a5cab5e322d5f651f798aebf43a62af772fa2cc379905e72d253c49be8193a07ae6164f21cf08baff906ef800e361e1cdf1604f454483e10c8b2bfdcce77c12b0320dea63f9ac0afbb86115b656d0198aa883f
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 665e16ba6cba87c646637a233ae04805a302ef4a10d79c5b65b146cbab8c9ccd491faa32937d0ee955dff7dd0ea3f79fa43c133021c8680490b91d9c1d8a8102ab709ada7508bd59042940b2bd3a4f8c195f781313e45fa8d3abda1f8e13b35811b638b2ab101d1caaa92188d2b75b2b10d596ab159583135b0d4d15fcd3d882
+A = -1375af024e9974cf8170801f4a709b4e5862ab7d18464077727bfc2581e557cada991e9484a1acf80182458158c44871e67e783f7573f214ee4ea1f1821a65068f2bbbed7575f03a4bba36b0fa8cb6dc58c73b100a6c4a6ce
+B = -2d64b6bd987d496a3c121e89f4b0c88b6ebc6e30fa9d47981b52862551f3b7251a3fc376db0f2d6daab6e6fc5ea8fa10b040d0dce334ee91d8cfa6db9648df907b199bb11b2b5c41c67d72b760c404b0451f70fccf
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 49e9709810d9f3fef159e5cb45211453e7a94878dfdece19af839b89c0e43b226d7cfd46859963c7ccc753350e74c2501131474e3b8e0edcda18583b0392ee15f1dedcb7144000fc7fa7eabcbc83d12983d2ade477b4687d75b723c1a98a951d21b2e8ed95735aaec77e00de288d16422fd259c665a08a34331cb99299ac11e2
+A = 4e550ba2fc2a44452f068860ce2a59230738a7a15f5de0aeb4d15bda8c61ee3003568dc5971e48343d402112d7a86860a7f08f5cdc0de21fb1aa064ee5df26fa23839b5ff6adaf64a4a18c07efb3582c2fc9612d2208fe99f8a
+B = 16f31365545772f276d8ac952506bf4033a884edf1ce583a63d8d9f6809e29d9cce3b3d227f839e6c09b459951465ab4570d2d36127c0f677fc0a63975801896f2fd17887ca16ff7f265e2e7adab1516ce56ee1ee9de1
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 89ca20a3fa109a65b9449edcc729fe97ed45a9bd69eeb31d4a566ec1787b24cb7a2c25b3f89b36fef1cb3645b17c69ac8ae243cdba35e17f5738b35278478bcc391add0b5ec42db9ec1eeffa63a3ecd2ac0338db57cde9d2eb9ca4bb1df84f1a62245c4e585c4f20f26c98fa1957df34409a99a18bb442ac14f0bd309266a35a
+A = 1fd8a096be30e4435ce8cc604ded337a3d9d2fbc9666d1893c38546c4e155315b536d1bc323c1e7be162bb0fcd58440915b053ca0d0896e99265241f2afd46605a2a7486e1394a07b23f3382cd190e943e596c747b6529b04bdb13
+B = -a3960a51af5ecaaa70146ce55d639005e9b6b9b58592441d5876fa71470ade6d1e2cdde17bb80532551bee0dbbb71a0cb24dc8a129c1f6e28920055d87e9c66be27fc4b425737f36add7d72e39bc83aabee5534637e2e22
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 654d9c55d4a62976670a5ecac3a6165734a65f1edcc1ca81a8c444dbc98c3409ac8c4f6fbb92f122045fef8b7971a276c7dc4eaba21f7be7495394053d4f9bb14b63fc02c8a55ad8fa9bb9aa26aca5c47968ea1b7646ec606f53606d5529ded83639984683b8a020e8ded4b2d9f668ceadeaa8160245b36a819db14e58cf2bf1
+A = -67abdbc70db183b8c25b0664805ada269922556bf15aa80a47d31f215e216673b8d59edfa10a74f3f09d066055c3b9abd5434ce95eba91dd51576adcfbc7e2556df95fd6642a3b7e0486a635ed5699eb7fb285589c887c8659a2b7db
+B = 6ad3e854ea57aafb8980f1e99ab9cda24f183dbbc513e1fc92d4e239077816843f47927bac28e41d3f31c9ef134b72c09dcf14e2e9677a430d43002ae70c577d9958341243030fe58a800a068d6b01fd377e61844f0d434dfd
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 74bb23f7b0cde7924ee52e58bc0680f151e6898cc1bd4a2eaaa05faf218b419a19ebf85b0219f924a26002f9251b83506684af659e5b680e05138432ba227977f38a479ad9d1f3cf68a86ea214645fc4bd1a032f995307e9c9ee432e816fd852655ef20214e24522c17799ef41d1eebc6e097b9792757f7fc43124c609ef9696
+A = -19d3e6fd6de9092cbea55d65154208a0c93ae409c3ee35569cf774b8c8b7b1c9dfdd52e9f408e14ea3153073ed8d92746474e524a903a45a882fe46af92b033f2c41eacdd7e3c1ff661dcc5349ed6bd1aa845eb1762f27593708aa185c7
+B = -3d466d29e8c0008ee6f402551e3d62fe044787bc9f243db9252ea97da9bb75f5be416def97f13cbb008fee77f2eeda672bccce1f36fbcd26e1f1299619535da0a3fa3ffa0c6fee82a494efd7407cc770cf46ed1b8b143f42790a2
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 197eaeb8221b431d5fed3d701a175abc146a9fedf8060e8e611a54f8da2fb27d2fee4539ddce1f3481e6a64435f09a2d5012540d6069900a332461471b22192fb87b63221c7822d3f2fcc35cc38feb6b3e49b5b0fceb52b0ccbdb4e1fd7b0f3eef3d582a6ae194c249ebc52f215b568712b3e50bb8e01c64b114955ebac2da48
+A = 7bd216d0acd4ee392258a7341cd56bfb0968492fe75da0c9d935713a6ac883525a4a520b5b7940b05e3f5e0c40372cb11b7ca193e93f0d3883fe5840e66346aff0f38829322bbc1f0a0e63ce5e528ba5b13596ad7ca19d20b2a7c9bea4214
+B = 1ed4805e53630b886cd733e5281f6d2699b3c79da615f4056120165cc63858ed2ddfcfd0af0c5fc54662aad90f26c55dcf70a30d04ce05bdf61028730b900587716e690dc0c6e02419622ab8c115078b92315e7c7a5ffe38c4a404a2
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 40f69f2d1660eeb6e1840164817621dc95eb930875333bc3f62a644ca5910c1080505de0d54fc9fb6404a61bb2c03b3981e558abf9e86f2047c3928599b529ef3d91c7ccd13c1d69431fb9ea3f02b001427cf519d9fd8182219ad904f47b3785fa05ed24cb0ceafd537311633a2e26c27e61be92eefb28a49d7f583cb6e072c2
+A = 155fb75044fc54a6ba6c46972e2f97531861b8d6afbc358db456bac33a44bb0545deea2fc83023c08b7be473eb68accf5b65b3c5d6af88bc6d8ce722c80d5d1527e475905226b01ab9d7b5a6557250cf8be935339db330df2dff92f2e88e80da
+B = -8c6016966a2cdea4b2d8625aa367e1d079638870f1b61e6b3c3a1e6281ece41018d2ce93684d1f0088d021107fb595390664c11435c6c0a7b93c2c6895217a89c469a37d3250dfa457b928ba6119b5c9ca5f2d47b36e60e4325bcb4383
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 9b9e6e1727326fea099eeb008a36539f3d47e3882b77d6089032b99c6cd36ad79fa75b7c19d1509b3ff022ef781b6a8c16fa6881f9ee2c4e00a4dbc93a49829622f4ce6ba9c55639656102d81167ab8a5e1fcf14d71caa60be732f1fbc71250256520c7c5a4579c3fdafc39356a2bbf2c7ecc526dacc0293c7578424c939ab6e
+A = -54cc11ea9806ef27911ba721f19e2ccb111045711d301863792f0cfac798758f0a29111e3a0f84d294a79721067f50858767abf507cc10ec9ea3eb27a91f06e7f6b7b4be7001b548cb7fb734166bad6739935081bdf6d35d58ef56180d377e5fda
+B = 7263e8b9a6f5387f44c55af64b64160efe97ec8a8159e723ca8977bc17c861e22041ea227c9c9bb467faaacfe352b03cc620eceecabb6db2db108b49c69752bd0cc61a5e998ac2f404ad052a51286ccbcfaa214ea8ec14cd9a2a6db56c3d9
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = a18a7498ac9194f600cea3d66615595c27a3efa7ea196ba12a80b5f608f85fa72afc366d23f5ca98452dd190b8f86031a9dc097f94a217b29fa676a6042a3aed2355cc8e767d464a8adb888491c8cb82dbec8f117f57c4a07b41e7e6f6cbd7dc25418603b1d1d865dd2140a649c9d52019ef39dbb6809d1b28b3c1ae64fc6813
+A = -1b663403c73e4a9003467ed12766f16354f79073ce89b66066857d19f3b42791eb360004d23e02874254bc6db54662717739eced153944c4776f334576746c5c4145b21a23caa2b2a137498554c7b749efcaf3393c5457b2bb87ee2ca3bef5f191107
+B = -21d12aad97a5c6e639a2ea0a82b1292aebd418567718014465a22b9ac5c8c927963a2a4530c41d5a7a6c14805e56a7092c8716e4767b54a393d8552c5d3c366b39fb3b8667c60e6075e9293bc938e407c53afdd1174843b76aed187f56bb4be5
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 1983576ed73d4d87d8b94cd3f70c149c0273e966176b85fbbbb7b3202e2c843bf1f8f4546ad7a4916ea4c731a22bd337b6177fcd2da8bd301f3af9bdcad800449b57986e7cbcbc7eb313d6512b2894c0cbb6cd753a870860a49d6a682c20b5e883b8c4839b3321aede51bfc42bca163a924191feaf05e196d8dcb7fdd9941a60
+A = 576759af0f02406e8dafa330babe9473d9d970bf371ceab30d2f98f4470f669e042e1708e2677d52cb9f99deb9b53f30727d16c389bb63e71e923475314b615762c7612269b5ad7bcb5108068bb5159cb8dbb8d08de2bd4fa4d9db6cf6e3f5997b9b416
+B = 1a4e34794747cf4aa626e964b839ac497b1357090ff63088f9fd4399312df894e41b395d17b8ca1806baec6115b1476912ca9c4309f00a46d5f7a52c8f640075422af06d6d6d796359132f4955072ce90e61b40c992a155b2bc31c262e753aa7d00
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 3448648ff9f7425937b6faa54551ce14dd15566e5d41b2bdb1a8db62037459235a5b9546d289cc2295b0ed584fab2e1a798bc25a0c114238f61ad3381a5b441cb67f92cbf66007c980db3351adb9cfd2cfc769b5b9b0bd1701425ce1ee8d4b9f438ce1207fa850aaa1d3d1f970aef874c2b2499a150d29c2ceb7bac375009b77
+A = 1fb54cec882c274b98913e76342a9b8e631bf1d381fd8a4f7e0eaef475642ab3f5da70ca2e38741bd0182a959e5e985f1e0e7d737beb8c725c9b5ea22f7ec25b6e564809601e8405a5b1362e7792791f55ab64a57c03a99a8518d7f65feb0e21be619a6a95
+B = -8180d172d3afe00e0423245f47591d5f750f20d2cedd8ba6ab6f9aa24f74498a96c9001a0124c4f98dbd402b63e71eaa3a7af8b0d2fa417fb1d45f64e10030232b9155169153496aa202745a432e547002954eedda7cc9c1ca76811bd902b192f1a1d
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = ae0fd585408a99643271eef575285a6261a4c4a92c1956b1ab436d3cacc8d4cffc07044e57b357ffa43bfa9aaea57824319579c5c3e2fe4dd48bc818178beb5fc1ed60afa08828657d00bb88894c975378b1dfb452a5b88fc3c1d81099644a998a47a497c8a2b12c444fd2a088f47576b7f4fa40f34a208fbc3348ce33e59150
+A = -7dc7dfb753c0bc3ab4d07d5aa78664a7f57d64be4d4780ea81e3efc967fbf1bd1390248bbe259da32108ad96bd8b39f2c9f118bfdc96bd06147f812af831288bb687e4e1742dcd1dbf2b7adc41afa28d07dfb8df8bb2da5359e66330f5c65964096a96b31dd8
+B = 756f3e407a3ae698f103fa37759e90554f38378a9b8eb38581e0970ec8f9c00f8392612c61aca5fd37d1063b78c19e3109f35c0684ce523c634190b3164ef06959cc42e2b77e1bb2fd50eb59c3dccdb6090beb809ecb0ca30457a5c5948328eb218e219d
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = a2aa4550e855623a8ed488bb63db8fa4ac374c1ae953781aac590f78a364fc33380ca2806445fca5bb9ca2fc7ec4db5819dcd5769e3b746286c49a7c80149e7fe276d095929e2cac6ae57e8102f7d4c96261ca44cb6f1601f429528495b6c3169e15f9babc5be696074d45559d5abdac42393094c450d6a4a45bbf60ed7847da
+A = -16d0aea9c752b2e6e4e13f7ab1f0a2c1776874967b0dfeeef7e00f8d9edd1e11d2aa702be45fffc284c47811c51dcee184a134b8f6d1874026eb51e2ec80c94837af4602cac3efde556ebfff578fcc56c00de99a43638ab68387ec087ee269ca64233eb5b1762ae
+B = -3c6b60b0ce4b13a5d6d9ccd67c76ec6b71b94ea7205e408eea099c7ced2f3a462954741d353d0af850b10ffede8ce0bf80b6893288413674504829793d7ae0cba53b163e3f26cd99beb0a9ad540f6d2cd5097beac604b1694a9a2f4c48b28338f9d6a63e75b
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 8a1a8fcb68c53846b3edae33ec070ef5cdcc1346ab3a98a116344e6d2810e2e3f60f0fe435fe7ff257c7ef4c122b3c34c776f4912a9621b6949308e2cfe2e0827536c7464371ce804bd7cac1d76c5bf8b4a6fd4ed56b65434c3fcf0ac7be543fe2d09ac01c564d7b9b463740dcdfa9068d4d8e33f29297ab452e6ec55c263de
+A = 7c4878334ccd9e20cb11a643b206626ea5d0b20973f18535cd8f0fc2f0325a67d3558e4cc9cceed0d88c6d2215c220b8d0ce230fd701502b02081e3f6548e58e02bc2e79e4991f8ef188a84b0a367758b4e534b72cd87de7f82a26de14fafd162a50b359574812cda
+B = 117d8b1d2a3e2049e6edbb9494c68a97145ac3e658aeaa05e8ecec4b090d5f467cde34e05fa7f5fbfa32f1d9dad70955f22130c358468eb371555fdf57a40e1df398c166a22a9df2e1f4e18590b00856b4f880f6629f1a4296056dc66a29b6f0f25490c6a8209b
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 2cd3de06953acb87b773b8bb28172b24adb283d6adada676f5f4548990827635c51506c85670767828dc5b4b91b45a7ab89a700d70bdba4e0355da32b52c173305767721d18dd2cb6c55f890611e7abc854277a453c7500efc4cd4fb8e6c9bb7a73fe5c77045e715fd35d415b3496f7463ec902cbdc18f9f6f67c33fd78c3210
+A = 1a20ad042f46330df937b879c72ef00dcf39fb85b59186b8e7a9d40723288677ff6ab2b9bce95f34f2de37887c8a9cdcaf231254bd00c7e25b6042695d7dfc05a11765120d1dbce29dc74f35aa1492ba0c5ee65114d9a246b57dcc2eb2ea4a310be98383fb934121db20
+B = -f8ec67323cff9d53499ceb3afd44b28f0538c39dae8c965ea27d645b430c2f8a4965eadc8ed864f2549eb636ec558419be71f986f4c5783d0dd5253738b876d9034735bd13b18fc670438387f84848308d9357ec2aa4f6a453bdd36ff08d54a6800bb41df416b17d
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 1aebe2bc35eb2e449bda63513b1bfb55988cc8e6ec8b3c8fed5ce4dcf53b95f1b438c41e3b2348412b35e1f734edba30273935b03d16efaede429960442a01849c352349e23b4af88de4d01e9ddb53ae900418d49a84b7fadd2669261a574557c4fbd782f8e8f400895f6a6c9679b72983ce01bcfdb641f5067c94694e9eb80
+A = -5f97994c39265b5389526e3847876a10aa3699e3c3762a127d1a9f892180cce68ca6139a6f71b235da26c287bd3e1aaa1436746d983c23c3105c33ed2e06baa1e880f1744d81a80b98ee1f16220940d721a92118a9b949d4da7d1477db8f5b357b3ceb7df34eb5f62078cf
+B = 4bb4f8f4f4c8e63238e8774ed61a7eeafb3fe9a6e19cffa648defe82f4846e3378c892d223957564fcce79596151658a726031a6921cdca0adf0f5325d858c048a6b94312ebfd19b803eefcb93bbfaaddef120ec3b8c366b6d978524d5c74218da77e4c3b5ebbc66cf8
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 5d64678a32c163874d1c81824d628a1051bce3b55c37055acc47a8630d3fee648df5d319e50b4c56f465bbf696433409b89c07e442425d3018a059ec757d77b3a40d516ca3148010036b003721ec9c999665915a3c442d95ec3c01c232feb201be08c88fa3c6b0769e3da30f1d73b66f98e31f4306bf4e23de78e74743b224ab
+A = -178d81e419f0473c426e24428caf25d61b648bbf963f7fb753ae15e5ea3706b53b00bfc8fe917ac9fd6c7096518584566ff71e6d35197f9aa25107a235678cf9ff8ae1501c1d5a15d2a27d39d066e169745e1e8c808209bcede0d732423d0c9cfbea322ba3201ebefc5315c0d
+B = -27ed464895b65d9518923fde5caaac0c72aad0d1b38fcb7827d6ad4e0c8dc09e119b8b98183f0ef8d5d1133f3f108e951caee035bed0d48bbeee6d1ddbff5864bc192b84eb8a500cefd223972ed51c7f720d1736646825f95f2f10ce6ad47a267bdd8c80f65d644df158d7
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 52dfb6bcbbc5cff46942d76ba45301cbff76e9b894703a6a7fd1af29d615336372d147c3932589affe5c6533f28d3e6a57ce2d3cd7448bbd81e09a13266ea31630cf044f654b87ec3fa3294eb65873964110fd42d86e78d128bead5f117cac98145051552cc3a86c193d738b973f866d068a8994a49df3fc7c7314fbd9805e80
+A = 797c67ebdc083f3c8b3ddf9847b7f3c2a39e35ce2119f746ec87fd5d86671d8fcf2b4f6d440c43e93f45019032e629879799eb58adea729d43d2e40ede6485143bd35979609a12faae7e4393879c40c0511c886c66a24454e4f9912bea944eaa417c9942f09ddfb227feb14e4b4
+B = 1a599d1cd0ab3614f50b71b93c999942bd3d4cbfe7900122d5083151c71d9e0c299bd927095c5c3291418424a7c12947389bd4e0a3c2fdf67b3f512094ec0ce5b52695e527de2b3804dca2edaeb1ea4b487911053272ea926cf2fb3386dc4b1dc268b808bbcf4eaedd21168ca
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 99bb9082e4537426c61f3b813f8c97675c44ba9ca418960ca6e2464cf61ad4eabb01ba00798463567ed3d829d3f14201c740f19fca623b1e9b57b534a65df0f070a2130489afae89b91003cee432fab11426c4d13b7721e6f9db1bbaf0adc0064b33e4b9f4b795511a0744b52f93e3db7bc9c0a991e4e122c463ff344fe14cba
+A = 187a8144a0045a92dcad94f0bae7285309ec8fac7dc864b08914e5a4dc3b1a6bb9212161a18c22682ace16a4bf3c03dbaef088b09844902a3255fd6adc0b7c6397dda86d6ab67204d8061c36ca20fd4bb348202037b249f6c110c31580148db46dc5b1bfffa38a683a27054c35326b
+B = -e93ff16817b725016279a32dac247961ae9bb00af890fb49c4fd8cf5e815cf98b58cfa1e3735095e6034c9a2f2b5d8030ab30e2271abb45b347d755cd9ab5ab5ce37950380cb306bbec42b6b8056793a0955bcaeb23e2d6a9548684030566eca2d34c458f224c8e337cb8e3c252
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 631f53d02c031f592b3dfaeed106160488c08e0672083ff195b22a2c0b006f11165a245acad6f35dfb15a871a9a2b45c544111f71f86c920b42fdb6551e56c55199e6173c00e27c9f47256349a80236bcfd3acd1730f823031ff9ef594725cb9429ea183a7fb2e03124ebdd98d435313e43819d995c4fe81fdd4ba718aeade94
+A = -72e20f1aa2b5f2c4218fb9e11ced3f45a218f4c83a2017d97d0cfbbf227c9082cd43f939c8909e52c8795cfaa75d80392d3649dd85ddc35bf1cc54ba389bed9e9dcf867da1c05eda080274beb6b868b54fc85e12ae127dcbfffeb043f9d59333d0ab3374c24971e1bc7269450b418c8b
+B = 61cb021a3a957703d14061c21d3b0fc19598e19a17df9d6f2418c76d4d37b3f62bd4037aeeb1eda37f83df44c440f5e49924cc72ec5b153856c6b621350ec89d98859d9d1ec7ac4f0c418c6599674322e7d618c5ca588d5a873d5af356d4771c6cd375f5dbbbc69f50b982b8c4d1ec
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 4654a62d9491f28599a976288cd2068d8e3228da12f645413a92f482efc66d1737495cd4a4c733f147eb5414a2ef6266a116ce264491a3463c9df1b030d83b315f76f3bef8cbccb5c538478a65092547b91e991e6be91ce4549c3a6e34aa7b466e63eb3b88054f6714083695c616a078ed54e1ae46e00f3593af845fcd0ff51a
+A = -1a342c154aad619e567fd32e7053aef8d98335a4fa0e35bf06acd7998c43d821de1076dc1fb67dfa1156d7ff30203ec736384a9aa7f5f08cfb302eb3a2a7179b2664094c2cc0df73fa05bf2af24a62b8e394fc76014dd83b434df26f8a67a624884a0b9b4f08f33e9828ae64f5d0c8cdc2b
+B = -2c57e15889c3dc9c94361c17585d506933a72fa954ce44dda9f5e33408552ebf49cae87bd0be35197f887fc6c7deca1452a4345eb67d19bd2e7d3dcf651667a8900388e4d5ec71e9433e3b01d2b3d91bb94d0fc3c51c70793f978e4b5ef93a9c6356c0b2f7accb9e4eb457a2174b50dc6
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 6124d9ce4de2880ae3811836235d6d89a1a4b710f1d5a517153ed7729dfb5b56b0ac10a4bbc811db9b26465f03cda355701f9f28c5257fe288743cc0789cc54a8661f46e36eec357580b00a84f1d4c8e3d689bbc18242f1cac30a87cb7a47ea06f80d7c5633cde4c8cd8a1a7e27acdc3a2aacd608cce9e2efe7864d41a56ceb8
+A = 7b48a9663d914e0225d7275e965d866ee6649d7267474d5336d28d54027ffe8572f4aa26230dc7abe9957d211e6c2c8f3185cae962b878cfdfaaf6cfe32058c299247f372ae170a1f7cf71380787f6e90995da9ca5a4be8ab1ddfa8e6e5dc65b6f168b9b8e29e0257e0eec853a6e1911b1afa
+B = 1fc4dc77f4a18d4406a4ba536e500aff68d133c6e7725717ae6537b527c6f40f93202a2292522fe7d04e0ef804d1a7013b04cd3d88462fba31534770b56d2e5672e8a6ec7a723186024c40b4717defd1433b9967bd692ef81d5d4e39ba10a3223d250ab6e71d5d253dd0a732ed386ad57e54
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 6443de73e1c826c90aa36fd7ec5d0c3324c42058b1c35d3adeda1685470d363732d23cceb08c3f973034c24fe65506bd33dc45d7d617a53048dcc103d3d1b4fd0534586c2fb7489ff5ffb98303bb068fc14b1bb6bb43f763dca2c891095e613bb7b6920163aa6cbce8cd93d9d39f4512b6e0b28d361ae11cf76037eab4cbc819
+A = 13f739846ed2c3aa0a1923168cbb46f4f0a2f3942ba57bfa5c426cb4d4b3d80d9530405a31bda329a1814c560d54defa3e03fc4f808606a598607783d539dbb1338d5bc0c2e272a7ff6ee6f93e1665d6f5a0ade30308fa047db086646c763106cb875e014e2c18ff8837e4d4d86861b85a5b7197
+B = -ba019333046f76325fa9f258006a7c10d27e89f6d482b95c79296c07a65b8e3bff4a9c9fa7e5d0038da129390ac851f8c0651dcf655a3d4164a731cd20a701895c12a906c732906038a8e459aaeb293fda21346964a6d53fa3e370ebf43c7ec8f66229405095c6a509d0fa15dcf45de8d0e901
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = d3a6fdf4a26993edd175de9a0f012e1eb15a5a1c4dd2741dfc6d0f9177cd5645508b8ab09c7fb34066ba893c38144c7f2ecadfc2b0d15728b407e5db4fcbbaf1871580426400433f14dceac43d28f03376e791b7ad01a112981f29ff4b66102305f0ecc4fd134c2cdc79a5e9d9f085bfcb7e6c187980e68b6c7639c12e8d200
+A = -464cb16fdd395e32fdc613c63ab4768f8cf72a5b74a0a5b0cc581ee4aad1972cd97db7966d3124e30c9a1c80d85c46da2d36eecd7c3bba5866f9eab4d0fa55b2d440a311654466432c681372a80a7896c9163c12314ac51f652aad68fd9012dc63fae6c7673c5da8faafcfa1b4ed5550f2baede5cc
+B = 40389ba4d2f5fc152308c9e8a8c36258c770fb2d03e6189b96c4f8dee97ccbe426cc14595c8482e9e22486b61fc570f0e7aeddad2f4e3a480d4b75d14294a3b912928da5692043bd98ab88ece87a9bbd973ec82f990c0ae6091245318c2810187d69c38fa80e835300ed06c0723fe475f3fb22de6
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 8a0f9eff3a210912828fd7b5f2d72479cc9ccdcfd3e8d21739e301de02dd5c257c7ce4bee2def06c9d0c90d5a86bc45fa9f31e456d353775916b3d5684759e4500f99ca1f91f6767a5e2f4b735ae4b756d56c358a06447fa2c2ccf0ce667be4ed143e9e1dc627a561d92ae53a62477270a7944482cbf671138bd2a85fce92b08
+A = -1da555639228fc6ead68049d836d60a4927ee77472fa0ffd3c787d55b6067012560f5b1c2ef8bbf6119345dc6419444c675c1c9cd50602a93ba3718a5b3e1a30bc108d796998b24474cdad19bc2960b295fee97e03f2ca7589a3daf35bd28eb37a67b5d2cb35a30998d5f8622bd7e6b7d3fddd1ae9670
+B = -291fea1ae6dd1c66c62ae3a3d22904f4b4adb2a48cb795d50074095345d661a033f67b20c5d7231236dab871892deaa9458c235c342bc81457cca3f014a75f5124ff4da005dcc1108e75527528e5cc9c051a97fc6cd202bb9166f9e72e366bdd77c965a70592e5684fcaaf2e03421a2025ca190fe158
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 50f4d25875150bab63e4162265a632109d6b4743f9d6b55306858034732a4895ffb3720286acceff287c38320ee9945dcd0a1bbe5ae1456b7f36337cb7d22b679a6821a450765471257d52b6ab7d59a763e75e9e64581a93aa54761f6a760866d6baf186cdf4ad2b1a6af26a3e76cdc261d1f07b0a7122c8ffdef595812e7208
+A = 78a1609a7f08c93c9bf9090ca7c93459aef815719b5dde5f217567a9f68ceca05594f6ab17a4666ce1c0c4434e0f4f38ca1f33e501d6958a10da47211cc011da219d4373d2bec4b7c6477b1ab3b00b6c45279212db39bcc11d1e7ba49916c4271adca7eea531adad509ae119348f374ef1203c5af8bc019
+B = 152b46095d3f8db5e6e1a9e3f35c085da00e52764b261c3aa775ecfcd38572d2e86bab2f4bf29c2de4fd2fb6f35f66e8685714634e1be980773526bdbf9c43b1335c5d59f4dffe1a1fe2495ff9b7a3fae3e53e7c3208968e1ad1dd1dc8cf2e2415cc76dfe5df9e2e1eb63f7c7687d539706502d56247728
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 5a3ad8d6f1b0763b77f5d40169ff0013de638b459e401f50f4cfb505565c8a4465e28ca1bf988071701dbf52ac456e01e170788ebd2b7cccb50dbfe1a65a89a8aee18b3c11986c9d6e6571f964f376f322e10a1ddd9310bbb40f14b0680385c40975aba43153970237c535c6b0e2cbf6bec918a8fa26cb2f69e98d77215c23a6
+A = 1d5c14b0b51cf31e9d97b7c49cd26097d40454978663f8a74095fcbf9c63e533708befb1a467f94cf599a41220ce13493a273fc30c49275412c5205db712d5e1832b39e65c150c3a4b251e2aab853e4ecb4f00ee5ce6982ef9215775a33565bde3ddbd932665aae506941d3ee31b3f9e4ffc0651f1fb4a5c6d
+B = -93cae5dd84584a2a3d88028d6d4cec4146cc5e350b4d92c52ba2393ab69fc1dba96e244f98e2f93f31230904169641aff30dfbdd3dc5fb1f3489d63aae1efd29335345a79ded546e42f2ee4a70ed932699fad17a771ba65fe6e689664bdd1135219aaa905c962d39531eba3e82c3425c24041e17858cbbcf2
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 61211c706730a1b98c628b3c8cb070a42e2ccf9fc6302bb1c2960fb165087f210e9d93416ad9fa21634a05dd0723cc23b8d2a846ab7c3bc402999138433725e737102094db5792249b4b5b1514a416b80c804ecfb04653c5ab18b0a34d8777f6c2955ac66fef62c9ec2819f0e3c075920f951f86b32e02bc43239d9218580067
+A = -46c8c68f492d8f7ac7834f89bc76098146432c59b3301d4eb70d9861a6e24c7c9073f910108c7b35538a79de10640291b54e5755359baf47482b97af56475211573576e9412ee017dcf961a090a6ffb5cd995992ab68e3fe60b6186f7595bd9b8acf8695c4f7359cb2ac709f032fb993d16a74822b4935536453
+B = 46953f424d988fd20700ea08880e7e09ac22d60cfc294bd4aefe637408a3cacfcd0ea6822a679b68b665d6bebed3506d25edc83cc7154b83e22953f9d91157cebd219cd5177fede28c63a15710d0f92bd9e542a7586855bbe57a94c520408fc920b3f8d65b194af2b2a580c90db1cdb27ec26ba929de4573c6eb
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 50a063fff02f2cdc68edccc23976f4b3db99641073c85709626292b9475b9a988fb8509a6223f0a517dbae0cf7cd39dcf1e8ae75196d9f5008c661d8b5153cbdb9520c71068e4719820bffda4c393032edabacf99339e0cbafddb6042ef887b8c498e87e16b62417934015172e63e7457242b864a47aa10e203f47320f03c0e5
+A = -1740e8be7b4775725516d37ba643fc64203f3a61e6b0164d112af56666ad97afb0059c2c4981fa81d72264f8669db4e50e11865907655b1f669c88f5935cacf1b12c1db63cc84507af12cf0210f990994055d04d93f148f213e3d4fdcfe9dc42117c059897697914e3e3fa8fdbf0eebbbb9c3b9fdaa7efa0c9d5c93
+B = -226308f8fbb35b5f9d129c0f6a2bd3e5c272a408bf32020905acc6d02d7e506191e76a3a2ac47cf7a63e6306b256f489ca5cdf76c7c3eede175ee4a7acedf922955e92599647b69d463cc14f2b178b88cd471b8a1c1512caa66b6d5fd8840b98b8d070e6593136e98cce9643e006b714388768920a79944be36624f
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 747cba0d1cde75dfcc0b2af9072c5027986b3e3917845870c73c452858ba21d6d1615eb71ae1b5a03ca44e22845d5432b368541b52a4bb02498668e8b99dfa2eb90ec1948d90564e6ebc388ee9816e329e1d8da0d3e2b12d901d47e22e8a1fabc37408be0f89e7a4ab0f30a03f7e2ed817006809e69c21104d0efe548165f64c
+A = 5fa76e37aaf0eb3d34d4f4c590e02b6c63fc62b1d4c9e172cb0dd82409df87ecb43a1680a2764f62d13a5e919db2db08feaf98d5cb92a859dd42bca1047ff57b8fe5974fb3ac11ba2c0d8e2203750f30650db4b2cbd31d07fe18c4df84a0dfdb30f9e528932c097e89d8f8be6ff029dd970a7d2c2551529455b9131e7
+B = 111199f91b3749f8cecfe90e9b9b6951472cb701beb39d63068c064cbb2a1e1d30736026f781836a52ad0d828be6c20303c6c0bd03ad664dbf6044a5bfb67fc20a049fd37c62ab0795d836487b883768ef7c8f427eb98e5ab6621fece77b4955822f8efd190c417ced398c221215b50e9532a869eceeb605fa1c936554
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 646cdb3ed472a7b4599f02329054846a8da173000eee7533240ade4dba82ee3d7a6a92baa3783c19dbd3f76fce6b5bdd83f1f229b1c71a6faa18602e368f1b0b9f8c62bd8c854844af85c2081924c9a153e27853b2a48147950fb614028e090e2198e613631c95e565c2b9b64a43237fd4052089f9d1dd2c00525dd35fa946ca
+A = 1c8438247c0ca376f508ccef7933724df512f9e0877596f7f4ea73dcd824809bbc472749833b537eec01ab23656e9758da22ab8a4aaca1aab3fe8d2cffa6672ca0c44ac029c2ca6c3e71780c28c31b5f154c8dee782f6ba009a69d83b1a3a03a2d6275bb8bc3932a1170470fb7e405ae081f4770b535edf49f73a12ba589
+B = -e365c8edbca8dcc4cc11986a5a901e4ed0adbe89b0ab70a53aaf5821862432a1320cf1850b515177b630e12692cb025e3aa43e9acee0d8ad5e48bb15e9a3f34cbfd39d285127b52dde58751f572ae68ad98692899ab12d35e33652c4426ec60c5029e51f7e32ec3d2031032aa7b6b2b63f84fb0023c81d031773f3652cd6
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 7a3e22f4a3f7ae7512ed73a07abb5ce291bc90bad507a5ccc0c17185804b9d231b0ae2e72bf270dbd60170f34b240f716529a449abea0b3d98ea2890a4ce3d9e2214819aefd070e00201e9f271de925c4ba59651e55174c97a13a30197e46997c6c2b152548111aa98df120a617c54b71f8eb8b0c8b4dbd5251f5509fdb8a1a8
+A = -78a99d206b4f095847e9a21de273aa6c47034c9afd4c081a8e93c2d75f4ae5b090921ff5108c863785c413e2f7b4a361506fb66b7561b8b1c5cd537e90274bddaa4e91ce74ad81c6dfbfe1a34a631dbe455d74ed9d041a9183da3bc469bdb214d2ffe893f89c3ae30f8ab99c3aac4d2fe864b891fbf4f537745fddcc60504e
+B = 5c41274e9590c1ea44c113ce505931758f2cef80ba3b10440941ec9aa2ac984b29868bece2922eaa225555dde84a8334f1caede99091165151a39538e5b7390e81df757f521236314239c213e9b874e396a022f04629c09bfaf929a0e9fe0b0c7386b0541446f6a2570491067f64e662d8611c4fd6d1c78a9f3ae69f34d14fc
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 7fd27b6549494c9bc860146a3e8ceee785ca03faa94b0ce0a964844e7871e813414cf3f111da49fed1ede5e71e5539f34173d41f9a17ed129016bb9b04c86487f5def9fe350fd4dffc67b6e181e3cb26378ea15ff9b9ebdf1fc86c072c82ecd8bcdc241301daf1b774af5f90f37e45e6126c5da7dd3753a1e5b366038af6ae31
+A = -1930548d105661dc25a5ee303b61b559c4bc1f2e28b2c40cf3e25f98dfe01a7dcca0f3dead6463b55a5b2e0440a651cc9e08e125535e081c742bb3b2f8955ae897909cfca683a4822896d8a4a7073c29a80571445c6a0d53d2efe4a30a79d2fb5d08c0f95b735a1cab17ba40d71b054c9270ba6bc870e58591fb1bf9dc9b7ee8f
+B = -3e2a4c1509494f94406e3843c9446edaf0a6060144637234c6d9ce84d70fac54ed163d77d210bf557bbea0404922c8aebec67a0475a3c7b74bfa2f226403ce987c705c712bb8eb0934c2b390a173c3836378fe71a6939e48d187b27cc7236ac115309fbeabd9ffd0396fb7fcd6d46a1dc683606c757ddc3212f5d2ff3f2e450fc7
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 2078bb5c82a394c30a287aedcfdc5271eb3246be05954181ae4f86ad2880ce674640ecd55c2ee3f4e89e2762139586516a28558481303e3071cc9ccb9a538f887553bf5726f3849fc41ab027fb1c680ce7dee3982587ec71b3760e5da6956d6894ad8c4526d8de953c0e681ecd44883a21f0abef1544fe601743efd3e5eadb8e
+A = 40b4ba1e977825b7accb941fe0c0a49936a8a47429dfff53502fc0680d705b9fa0efe003eea3ff0b649998fdbae8d0831bea7f34159aa4c7add6bc7cd56fea97d25fb9a6a10f4572c26d792b76c18ada19b0ba06b6142c420dbb40d66be669b7c51d8cd2a5022fe1a8aef7b60965c0176eee69c32ca5023782c5410adc1b15dbdc7
+B = 1bb2f18d7c8d306bf80ae1901115c8dc3d286baf537b812ce06d6872b61e5bd44f3c53d7f31ca8461b3628b255f85338cc325856fda5a6248b7c476532c1bcdf9713dff9932a50e52a9441aff96092d3fb0fd76046a8d88288d0cd55741083a1bdb20fc6e9c20e82490273354bd826bfe001322dde9a15763f2c0e6ffd2cf60019aea
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = ef21dcee9eadceaeab13287d6e3c9741811f6ea9d5bd111799ae05260b1de2ffbc192818fa45dd7befc3baf6840e3b9d24cecbcb2cb1c3d653c4aec6531b941d926fb6692f548cf81526acd0b6b0289d70dd11ba50ca8de6e174f502eddf47e57440142c7f74f594a9abcb48ce1873df057b132ccce8b364de3edf411089d28
+A = 19d0109e0c47ad45f57b8bb8519265a4390534d2ea07f969d84ad33556518b6234d40d1631be3c3cce6d59b7be14750aed114008458f50a6a84ff75b4ee7e4b826ddcb2d2293842ed29e4e484260a92199c5c66367c402bdff0f1a8057127c6ffe452498bb352802e0005e6cb084663bcfa82783a3d72f3a2a341b8075983892e86756
+B = -81fce71491eda139ed996f6a289dde8635a3a257ad6756e844c768e66746011fd797658184fb44b0e3f3c5600c56238ac7687b5be42529d5c9b97c3ce10f3219e1e451bb2dfbbb44cae0828ef894eff3b52b8dba4c115c3b471984441045f2c2db426cf5f86949d5bb7662cd40bb3b3172a19ca3fb6858315d688f13c17550e700cd5dc
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 8a5f90344071790373044193cc4fd92116248aacf05ce639b6aac4461ec3ccb0805ff9876ef44fa71088c295db14fc820f7ae2c0aeeffca055f8f7238c6c90db706d02f2cc43b4960abe3ca4b6dec8bba55327b958e75c60c5d1f43fcf9136f12481c267481a725eecc403a16aa6221346df680560ff316a63ec8b51dc37aad6
+A = -7a54e7ca04b9a22e2b986e72e634317ffa20f6f4ee90353d559db3f3c1bc6b3b92ac6b364f6c5929090373962b49b59cb5d87554387761164982955470cb45dd00c4a8982dbaae3a1ffe700e8903a4a8e4a21eff9d00fa496d475e0e1a205be267499dacecd31551f8a9d437f37dacfdf5a2754f0876a3e02509b78674e7ea2169c43f29
+B = 652001f073d63ddd526abc957bbb48ca74154c8f9698b988178b3313dcde9acbb19ea11a935184fcbcc31e0117d8d2ec695ac56b5a71614a12cf90f21c8882187428755b6a5f11c314ac8b952ced0f65db0987f0f87e20b82a811599f4160e65c7418af7f33604e7b8952b70581e3e02dafa025cecda970d04383ee552abc620dfb9c5df9a
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 67f903e0e5623258826b681506f3e94cc0b086e262bafaa1395294aefc9f6b6323410a44427010d5e8d8288993973ad9939199b85cf02ae0a09dfb69801536a3fa6af5ac373add7efd25ba5fee6d8f040e97056f9f6fbb45795c0bac94c51ffeaf496710b00bc9ddd8e445261d976168771060c9bd9d83838a84ee9428f59d6f
+A = -19c695ee3a4ada840a7e3626e61047c5081867b15843ee9a6506ce45540d23ad25ff23b72f988bf26ab8b98363d9a2997773604f43fa732f59a4b16ddf3a45acdbc7976a1fce01b3dd55559c20acfbb7501730f794bc45fc09b1f035d60413bbcf32a83fd3c41599049a674f165ac5283c42aef213d777ae47eea960f7727f5758146efe5bf
+B = -210697d47beb73f45207340a183a729a1e78d84bdde1c7d8f80bc84559c4aa4572ab0e6927ea175acc7a268d05616201cb235e610d1012500c8ba9351a37bd68b4ec42227bea55cef5ba7d12ffb180873ab9d33d09e6e969df99fca728dc12dda6903169acbad38388fa9b001edb09056a2ee2aecfab0468822bca14a4bcdd3a4122290ec5ce1
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 5fbaff0ffcfb2330283fe59611ef51cf045bc2690e31f2ad3265046fedaa990b5d5060b3c38f17bbe8b2696e527fd77ead8650d329c2e0c1f3b2f5bec4dd85641022f3e0ae6f66ce98cde1a785bb52eca796ae45c33142e8264621ab447cafe988de926544e1a7036710128c42fe8b574f7ad69d830894237d95a55d1bc7f5ec
+A = 482db04e35f9fc1d87b42bc5efe25a049ed924f816e1b0f9c8ebe34bc771e67e26d6057563fd5d5320681e1207c0b0f4b7df547cd6d5be6a2e0f2bfb088f990b0303d0ef263cf45681e0e9a1147c29f2ca5251faa633ca53f6e0b109ba69bbe20c58a76a22789243d1acf128dcc936602e832a20a2bfbfedf963bc1027650f483814d7f5e6905
+B = 105aaf563d4c1d436c6a4552770a527776f40bbb844b7701313c5ada95180160e7cd4b7175ddb943e5a22c910585dfc184b52935f06b12c84b6431395f28af2eb9ccfa66b2ee8f40fd44d753c6a83d67a6f3fe3658fecc7fb2f4a8f357c5d244422e48a33d0e2971059695a59d0d39b235d5194e919facbae7623ffc92d771532b6b0cf771912c24
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = a9d204c1a497f350fa1300cbaf682c947eaeba8b3aa0450c1db9120852a2edd2a0249dedef3b3746298ee42834d869e9f765ce987a2aa4712a1f35ed10d0f7ba9cdef938b073c3a526e5bf45f3510c94ff1fb84bc77b08e2aa50f5cc75e2f4da37a8a711f8aed5e92f7e486877229cb4ff2a4d0755029972323c0b51a14fd1e5
+A = 13fd3d7cc9d6d6821d2f2b1c40c8e070bfa85b994ee8f3e0baab544dc71328a1a57b7ee57392ab6d24bd85f9ea0f2a312148fc4f4b22c589e9a265d97e73c7a5b420bee180409ec179c438a67abf37eba61ac76197f3c9ea5edf2d4b8aab91e9bb1a432ef1f214c043664a51ceed1f2854880dd458ca253f09d6f6acafafec310774a672d07147b1
+B = -8c90ecd56d6c7cb129d1c9c26e94cf919c5747450542cab52281d11d8fbfcf9ea797b29588340d146cc40e77dce007b68c0c24356d4b75513b75eccbef6e22a5b88417cb6c516578d17d871e7d0957c09795f9a0f19b811db75d61c27e1827fa2773846857fec020f98444e307d3e52af501114b962ea705cb0cdf815109054abd00810dcc270d7bd3
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 57aef35a3f5388c810f576dbc30d4e4e5a39248b319b7766311157179d8bc1d7ef019cdd8c2c0175a8424abe7b33565afc0128724fa38f0900140b6f96bda2e78d7c803124cec8c2f2d6649afde4030c76cd33394fb386342d1ce97a4ecd180872134fd4e22667a687915bb4fda21f7e0bc9100ed8cd3a6668ed3a235d7b15a8
+A = -673bb11795d9d20a1e4ce8ae71d041705990463964505befce5949f895fa31c92d53f91fbc110df4e789b3f3f01f184c55df92927b8b680cc92864466ce5590ed2e98901cfb78b32ea79bf68b57a14cddb53209e08a7f430fee23f4a1475fd2640a515f8b609e98c760b4301747ecb61f1e6209b07455f1c8a7bb4e20c269e17937f39c6a2fb7b2990
+B = 46beea6005cf96a2acb16f37e357bc8975f4dad502fc3aefb4666344dde456c0ee7ea43ec493b6aecbc7aecc7d4cd107aa09e874ff564f5d59d7e12047b048c1da1faea36a7e2d02d0567bc4db41b54a75110626d13597db698fffd577a5810286ea8bf50625296ee8070419345fa269a354ca2eb47fa3108387f6a4b2c0ea3e779908a14469106eefc14
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 5cdb7c451b2950c9d87638857407276959142958b06241b2010a9f93625f9106f065798f79ce5c534b9e5a31fbcbfc63cd200fc1cf10217096aa0194acb9043ccf7ced30d9f0bf66e0dfe27ee2ecc40bcd8de66fe2ed6f8cb0d874ff7b5fe71951412731fe4e19c34bee64c9312577b9e7b2ac08ed15aea753a6cd3e286192ec
+A = -1eee9d5d3854db52f9b43698e05d6a0f1d1f8df5f32884a775b25110309c46ec5c7e112eb64b2d7f948868bb9670068779b0a78bfc7e17860ee02692ec6790222b4384b9bd7db5abf29c46261c10d95f503b821a4694c45553e0dbaaa977892b916cb8990ac9ec29ab5c3d63ed77138fa1e95f395b3b233d039ab5daecb0296203166e9386d1071c61cb1
+B = -34587c2bf3473a2c5d7f3399d5ba2bb09be8105a0b9f3d8737d67b03d8b91b1c869f4e223d6246abd36d99d84052ae5894e58288a614a0da8d69f1aa57428632c2b059ba99315ea2f68ee210e65a741e94125ee4a723a7828bcc410aa2dae06ea8ed6cd23f66ccca7e85d2e071055787f230ee405e50d1519377cfe0cab4e5f97b6cb893b01134813a7c2c6c
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 95d0b209654de56bd7d6f74afaabed2cbb3247f449d80511d2d3c689f84c9b79587d78abdf0eb37f1b89f1f8dc8a83f7f9fac2c8cda1fd3fd64e16f5597b7f0a1df6da6db9e828ce7be0e876012bd52f5a74ca73ff8ca4611dd9f342bf77b485305ac28a1f8ac7538169f2bf3e4ff4dc5fdb9dedb97fa743fd8ac8791b8e288a
+A = 7821d4b65d529c30b8747e184e450cefb11b5ac5dc77905e6fcd3df64336661c82ea68d588ba616d23df485ff0658fb3376d5276027a40b392f47219edc5ecbf510cf0c5b431b02c65e5f432092f941d32ac5f71ce3496e403c7637f63a23b91e3326d01d2d32e99e0ab265108dc5e7919d3983839b3c7541848dbcd420a594e850e587f1846951852ed76d
+B = 1adf5c428f2a95c27a943637758d5dcd7ca36592fcb9d52ac0b7d27adddad5804e3edef257aa51c716801ad0c731e13c5dd000f11b5ff1b69c198f236695c1b2f99c0afffb5d084f80fdc534de3b0df4597404b50c7e784c3c55dfc9753c414d145eb0ca4d07e2f65b63f3eef8d391250a5500ef64d9bf963d7250d6906694e7670f92e3d5a7930f0f85964a21a
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 46914b197b84fa99addeaf55dd803182083a7ae34d6d4d3a55d6272af40a600563cc8d9f6b48110d0521b8b99751235bd5a340b1743497ef1cc459dccf5d6da970c4c3103c978ad2d513298f1fb3e68b24a9c7b0795f47d8f7f6ca9caaab9a9d80f15982599d764f8738217f9158517806fded5f3552fef8b7dcd2e725ee04d5
+A = 1c9f5f2a0d72806dcca92dac1450a50cba05b5dd571c2b3b988d33528d90ecc83444e3ea8df80802c30fbd5a6ec2ad9969be73aba6dd27e0dd2c842b95371d7547768916c0cb036964d041284cd323c8073095b2a8cb8797add5cd80f03595de9d18af8df7dee0d250ea7048faa47ae0131ba3f350d82864dc95e5829b88eeaf2681433dd4d58b2c6f70426af3
+B = -aa1e1b3cfd5ca0facc75e46d872584d55144620f849ab05931210b4e1526f12679bbd9cf00efdbd8863970e2abe8fc9fa7bbd21afa9e364e3c9e32f51fe66844fea4bab7f3b1bd278fd803f6bdbd0d296321e67751a0b894da338ab431871adf1514269ba05e0cea5558cd5691920fbc18237914f3dbe4b253f774e5dc1dc57023c080a3b90a004b809d237658ca1
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = ada55d93c533716ebd8c16e23603071950aa714deb942ebbf77206753d2676a7aaf61673c03a4db69d67faf6273828594d85e3c8cbf38460fa2af603fe9c1b6ce104854e7281757b26589f079da80685aec153fc5fd1a223004cdf30247f8398b8e92899857dd199d5d5c32412bedbf9d55f20e52895fc1dbd04c84cabfe1264
+A = -7d22392a8da1966e6cc5ef50d7409c614f8c8f8e5791778f68a00b4a056d0002707933043d05e48347bbd4d0dc1b6ca32a1aa4bab9992e7e620263283eb68d97af13b90a29c1b7dce39ec0b8a63878e8d65aebfb3bff4e67129e3b3725f999f1ec9ae92007911f2cdf738499661c5b6c9bf27712d0f29e871b17318e95c3d14b2e472cf9e466bea91fb71a493b2d
+B = 40279eefe59f954aa8c51c9c214fa07707b1d095f697ca40edb820401a45c472d1d7bb413eeddb64c14ce6144b4863fe9337ae4ae8698db92facacd6a56f3b33129c5b608eafa29e9d92dea620113051b926b80b75f320d7ca3d2ab597168c68774e68c47670458f5ef2ffd4604f20bffcc7817eb09c9057fd9989a6786a7e067ebe6724a89e7d1580f94ee4ed502cd4
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 4dcae9def5467526b0ff071003e56f5537852cc0bde9d86eaed2c15e36e6429c68c061e12d321bad12e29626b5013c28f118ee59624ae2f35d2c53bfd89e6afdb6db79f0321ad5c55cab03e6a1a97ff7bd58c760d0e9fd7507de987ed2f94f9c79569fe7f03652cd53c67ebc6bd3c9e6c5672891a9d2ee11b300ed3b19753c0f
+A = -127f5ca6924851faa2340c4c8f425b1dcf41b313c5c2910e5eff8ef2faaeaa43305de2b3a65a75fe54c00fb30c0ce3e8007db1ea222521190ff1de6d0cf2e777ed61ce8211dc167bf115a77890d0bd1ca786e967a04f077c89939ce484bbb1c560f669aacf7756a4338d97cbd7f09a376d2dfd4d632bb451f52c03c05762f050ebbf112f8dc5acdd9b631292fd7073b
+B = -3bc5e9c352c46449a9155b7ce5478c771293599cd2dda58a962010f1f21d094aa6bee03f9311545e8dc6213f6aa73c08b55bcdf4d1d84fecb9eda35c83eae5fedee75b2d15a003f8a82b2b788ea19f7460fdd8f447d973c950b3b250a3022c19ff312ccdc86b6ab50c4ba627b15968c8a66d306bbdae8e88fe28c1853fdfb3fde92353f46b5bc448ae42306a4c91202f03d
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 62a812e35f46e04b3afa7d26c8fd4eb168b6b64cdc839ebd0a46bf2a3a712af8e97380cdf0bfa8a274f7b73e887bb4cc73c6104a176d425aaf5352f14ee51ba549a6926bd8d059b8e3826b174385d4635b0c36df75a4e7da44c34e51eb82322b34ae00e8c712eb75b3882822bce5a2f2f5fd74355319ebe1973284c690bed2af
+A = 71c57b08127a956f0c17fd3c639bd1923ba19bfdb83c0cb9dd78e62b8fe4b7e0019cd0a6b73a334c622118f96fd6d91c1e06d4dcef8a3d0d6bf8f5beb6389226c50d14d3947ce9f24f7e0e6a7befad2e4e92dc9ed8fbb9811d908c03ac074b2a5c67b67831a350c4d548ac70810bb5617d261a045e53cdc48117b9fe86d35950d0a181b73c8cfd35edd31af031178523b
+B = 1cda2a51a707f8c4d2cbff6337c3f63519705614c26a489b545b1faf366b705af1d953701b568a684856fd3186c035f878788f7e5dbea16b5e7b6e767cf611452a4272abf2a9c5e72b7251a1ebea5098c60cc5bf649cb70980b97d48580967ffe2913309b6b78cc12d91025ae403928851902dcdaaa60f5b323a1302a5ce114cbe174e3eb3c2fb5eafc44076396c23d53b028d
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = a9213cd809d41b6bbfc2123bb84860788ce22d5b91f8e24fb616efc286a218ae9652b42912a58bf8ce596a1b48e4c72f27e52c36be1940f7d2138eb895ee36bbb917a59f73e0b6c3266bf4759ffe2ffaee3f6179492658e0778bb43c4df4bfa1a46300c9da496033142ae2c1e33333fd7e82c5a14686b255e224c51aecc2a590
+A = 1cf4e2d5924510a5fd06ff4eeb94a740e430613277149993004b8de1a2b96ada54b05365f305e896df5fdffd3d7bcb54f9a9dba9689e5ad498012f7a684d083c31d7017aaaee720bbd42382e526a35d2add21d9369f7faa41dbcfe3dae426948a402635771a977e19d5c353ec7c1abd279975f2effc0b7bc19990154b723f2f8c29e606581ab9d3966702f68d8bb8065e9d8
+B = -cdab60f9b8e1add4c54427b638ec5f76b30654d3649b500f833b2943bf6cd5d8647549657a8ff999eaffe413ed87e06267b97bfc1b77637b57f29039235548a7569fe6d4bb16ae9c6cfd38c0b8c73aa60797d0d69b03d5a98314f7f7ee25df8b896ecdfc782cf8057f038b6c3e79c99df52f839fd4eff302ddd1256e51eb31cee24585782a0439da3db2eee79a58f889d8847fe2
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 4dde3d63aeeee47441a7e733bcccbd4f2e495ca3c746468e9855177f7672d5d82e51da8e268ac24e8971d802e25d842a16a6b8d76b8e46a7724108c02d38a4830453408ca5ced7093676a1db4bf4c94b9b7a9531ab7c26f8de520bafe4431a55a5f5d8c7576427a0f5bf2081b998b82da2e8e959f2ec4d5141b55e40bf6ddeef
+A = -5770ea0a75ff451fc2c86d428f2569884b2c88cb6d9d407cc22b191849d389f57a5765b83adcea21c350b37bc6d750d4859f547da22ea8a3698a5cb6154b946331ae2ca18e7eaace951dcd49405bf8d8a716f7762eb242b8bf5e4c53a662c906c3be89e53ddf7a706ee2406c7d0ac17b54ff259c1bd5a092325938832763ac4caf0232e80a016cd1994441808d8db7e546de3f
+B = 7e4246ad4af268695a51912053ab6628969af4fcaf7f1e97dd977984a1604e8c9fe6b920f39a764c27d89f75986a4bbc122f92ccd1860f24677cf346474fd9441f572f769daf834e6a00cbc027e15d6aa7ec2030becad41e1068740cde82abed768de7e2cfd325848f6063e2186faa76982b9ca73ef22434a28bd2e3a5ac477af50f258140bff938d3fa02fb904a8ee0ef3c1f6fed7
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 3d8bde8d0625fc46dec46fc657c49c8ab12a988cec4ec1c24e6f4d8ff94514c8d8fee4a08399c6bd23fb6464a38bb5f249591456c283325e343cc289c85df0ff2c1707a6e407ff7a24383b66ab603b75e2dc3835ffe9274eafea148f20764b8ca30cbe483c1cefd51f82dfb93d7793b3ec19a57f2ba03d884f345bcc3188fe28
+A = -1680dd51d8be6069c86ae157922d55df3b58ee6f53738677bcf7332d6e7ef304ecc7ff7c5a5e1f525459d77202f3e815c68f17f9a6bf358654a92f9f9acb252ed8e9e6a849da7491f26d0e33900541ab67ce966d042607258b4382b8108729a703b429babc34496528f198a7e0f814db80fad4900fbccdfb64908febf5e09805d3a3049c0f164f0bcdaaa9bbb06df8f05309be83c
+B = -2c6c6b3c89f6e1d1cdd9abd1a9706e4f642a25738aebbc97cbd60e1f4ad79b419dd54bd14f2bd147b1d8e9bfcf92faccee61a43dbd1a2c084bf06a2ca476b3d169fa2c99794fc827b7f4dd010c0534e7cdd03d00456033ae0203b78a7ed229afcec2d1cb96892eb18898bf53584dde56b4316b3bc5186d97e3a9edcd059d7fe14561eefe4881beb8519c1cb7c3ba22cd2e13d874aab77e
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 5b4fbf0445807c8feec7efa3c2bf8dd86b1070638f3c87f1e173ee980412a28847b263a266506e70381aae919ae05d306d3a67a6c1e72c8ccf1c27d6296526e87f0f436c98fd1391f83440b58fadd4fb1905a484bfe8f516661e7176a268660387fe6a7266ef02e5fad91ffa69247bb11cfc1b5c3a88c76b7923a26f8a31ece4
+A = 65fe4d55bfcbba2bbfbdae831aef3dc8c8746e1d04cea174c1d336974d81d026f562225b4a297b1c3b044ccc5dc9c830a805a399bf26c0369b52ab0dd2c0ad19e723fcf9f5de2990ebe5a1266653195a2aefd9a392fd3da8c22c523a362f195babbbf5329018e3b454221b3e77cd0dee79f612f86332b1d104aeae7d8d84ad06b107715bb76bce20220d1340ecfc666b2bfce812814
+B = 12f775dbabf1c112523feab443f6e95d773e8220d66fd87bb7fc702588136a048e17ab6845a9c784dca275cfa445d007e8d8383740b156df7048650f89c5ef1a84148488fc405898f9e326cb8052f626c8881abeb70f3a0f52dd83e3ae0cb82d178cbfe8c393449caa2a87e7c8e2901a87e276b49b6d012f3cbb65641add3694fed3e3177777e78fe375f3a3b378091bb8d2998286562faef
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 4f0af7cb0c4e82d0e6589b24b55528818bf2164d41f58505a2b302a8f677df146f8077945dad3790c323e19b37e3379eb95de8abdadfbe4417f8bf8da643768a622ad4898513fdbc72d3b1d2791ec9ff40634678faf0e17d6e0851f08c39405907db85b74937ac403a9a3a1004013c7bd95a585728010689fcaf63b2031bc8c0
+A = 156dcadeca94985ea8bc0d1378daf1e85ecc4c7f8b6d6c7a5cb9f9ac368a97c07e381004023bc575691c082b5e9e13a02fe813a55e76196e4ad4b0f9b1e089bb71a0d5c94254b66e3e645fea25d69bbc5af266e730482a60105306d664f0ddecbd76d54e7235979aa2d806b809b3468078b5d90aa22cbd2c441198d4a52f6259972cf3d02003dc39dafdf3581638e56d08c5181d36e9e4
+B = -9a54586072d093939ad86df11fcd3337ad7e9e478dcbefb2b89d7555883fe8565abcd5b0a9c88ab135ce5327b2a326db645bc7c0e3ce24f902544675ff9d946abf30302f123aeed0f4e28edc72758ffa760277caaf4817a3ae8615784c81896d2404e2cf47c06b09085cd0ad1ec46cfc1f04d0272eac29e774b30f19939d08c036b185983c93ba15d1d27aebe4a357b9f6a298acca3940d2730
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 7c3ac09486a6fb518b98a9bc8a8b382bf2293e2c1154470ff7961212430fe2dd28697e49256b1ad8add082ee27b6ecc016b120e971665be801b720069d30c0a8c6ea4795613017e8883e5c0d0e68f982c328379d7a0afb7825c553e087b33e9d78f90e0b95a6597076b8ec2c1d375e2143bb778c318ca0680a64072cf9a4fc08
+A = -71d8e7ef13d63b4f417c01ec1241020a8ff4c9b2db531500984fd3e45d22b2bd581894c8a248ed7cc345e70a5698407df8f0e4ac71ed2c0d42122a4f92279346f463aed899253206786928a0eb7c37f2e51e1cde7f97cf9288d85c3ed7f49e62af0bf9abf062d2c6544d83b9d3438b3881e0d07b1fa0f2a4446fd43ab3b4f81fa2cdaff199c87965e298943c68cc15f2f3f3225efad68b73
+B = 64d52de221f102af62ab1e9526935b005c81658f8fefa019bc58e641023fa785798ed0dff8f7f999dbcc2ecfa47d5314ac6676c82170d6f2b18122c17c1e1ec1b9b54e333a184a46ad35b2150c8165f0de19a24b98327715e5a641c1b6d3ff9d247c89c8749e775e6fcf5f967c6eb5e73523d4f1ec12db7321b14398f26201a364e1371f0ac922781ee252c6d2b3c657ef259ab73cb7992a370598
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = cd08b388ffd41d0aa29a3dbde74106c57b18d325be8f446a2d9ae95fa4144037dbd41eccd50fa34096984cb11bce555c117c5568d76a8f79d308ce11043fe2413d37d6aa60c366af6c1da93d525e4b2d79fc82c0a53ed62fbf72c919db8a3ae11f5ff8057d7501f5f6dfc9ae461c308d21919d0de9e31b759d1d8e3526fee58
+A = -12e58708c30c93383cfe6e99ee3c5caf1900a7e610605706e77d8f428fd59db2884f5021d7a382cb18b75ed22528961cf43be1c700c581ceac3877e83eabd860583e6e94f3f2989c179ee5047c82b53d37054c9cb7ae08be60a91b10d49510e9f0b90ddf89f93790c3e18cccad5a9d223c605a6c567550e2b4950e184fd97dd68bf30681d3f9c585365de2cadf36a43f5a5305dae555396dd50
+B = -26ea5079ba7ed137a14d00d413d6f818e911cc183c88764de4d91d7a9b4cc7af3fad703142dc7905992eb8bf489f6d8231bdb25603ddf3c31fda8bd9bc4d78835f9ddc1e6445037f05125cb1ccd92eea2e927297e5eb915d5d965a25e5d58feb8d79a890e6036c80ee91e7469d9eb672d7a8db68905d06f5981fc40bf486575a067d35cf14ceee3ccb79b72871bf8f52b92e4910ab17e5e59ab3ae6f9
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 34714506322dccb91308c403c267f1ec75f80faf3cc4272dff4a84c13eb1e6133af6681387006c61e7e087046b64e7ae74eea8a3c0564a7c1f381e1c940d92b2c766fffdaa7318d07dbeb877943a73b50517b49e5117778b8a60212284fb92f29a9f5304f8f537e88acf8afaf01fdf64773f988cfa9551d6884baa70587ab76a
+A = 638b7c549ed14256956bad532945ef9e11a50313172965386635a2fc7db79deb0cb5c157e9854117c17f1509d505d01a0e138d2e510dfcca45b4f7ec968b5214a6699b61b8ac68adf64d5394f50d577a154c013612090e2045462160d1f552592197d7da78e03491ae284dc9faf643805f2674af8652bae93ff230fc3eaa833dc62781e5f74d0f0b90290d51d481b0a94ae6e972197c6e84ad7ae
+B = 141f62297ee88ad527fd1e0e09d9ab5dd80e17b32f34a674a27b00d719839701664ccca1b00da2613396cf633b0bdc4482ad3a0c3e209eaea7c22f33706ae44155f527c9ca4e341e651760d1c39f65d5e99e649d013730d2502b6b65adb8a73e6bc734b7d879b430798dcd53fa6c0badd57896cb566d9f1e0a7b3a9161e9808e762ca819330ce9319dbe7f49bd663a9f57ac53d65c6851dc7bc4ee66e08f
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 7adf54c77eaea2a1743bc5011ace45b7651846e77f90402297f117d8b1c0377f93f49e92a2457f3d3debec3022a96c74c166d01b2279553ef518ec0e612bd7b382529184640c55b89255b2679da9cf370913351592de39f804f1724de36db90c045fa644e8ff20627f67d6afd4546f00d7af093f668629f9a06c07fab5654ac8
+A = 19c491d5b55aa25f2e18cfb7fda18ed4b020e3f63244eb9f6c4dfa86eb8a70875cc898e305a7acdd3eee081300edb3e4c837940bbc1927f5ed9f651e46581639e133515457464e9c451390828e5e7e00a688daaea74620363706cb69e02717489ba9ad05774c424c18e295278caf4df4ced80b4cbd20cd631df43f2e16ec0334564d9dc03dfbc7111e4252504fb449d5a25cb13630b7c0c565a82ea9
+B = -c3f765349639beb80f888d9c8b7b335ab46b55064ce2a88180c80ad280c6b7314df52b7e73095dfd82896e24604854a48121353aa1de663eff07882771803010005905896357cd5a56a59f0db0045f1aa2c0b5626e132c169abc64b9893f95932f54c1d8cc25f215a9ef6e4cfdd6dba85f6faefeca81793b2258ae1d1427e81e458482aab87f6563abf435be69a05b195d1eda90146a8cc92748ca6f798b10
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 32ba5fc81a7747c3d812cf036bc0edc49f08824d53b91a65a6d41edfb1651d99c11ccb4c074d7f04e652276ae3fdc8d6eedb72c6e46cbb1f7f4070dc9d179ce3e21a3826f7dd2c27943a8d26b192d7f5c4aee9ba0647e406133e3e89c262d37cf468aa3ab8c5dd1b8900dd06cd600abc6d372d9408497d9e20c86a9a6a4ad9d1
+A = -73958019a5a52357b9c1d954c9b14f51ddaced32a4d7b7c95730697cf90029564118ea168d23a54381f7bbd6718a6b662e4c87410e48ac53b7767148582b0bd6a3d35f488e7fcf2b128e0a58b5d468dedabde4d624f4a82e808dd7b175af0d3658c6df1ac0da6495bc9a8dc012f8de55c2003da9b2d478e1a089fab776d99026684026968fc309dae46a6ef2412039a8207c3084f96b4e38e4fa01d131
+B = 4330fdf00bc6d13ffc267073b68aea7419ebef257d63f8f244accb9ee46edd04fe5481292de69d377ba6b6304804ba7ec0a063b42339e6e37867261b9945ec705d3a0029c6f499420e02a773476546993b3c5e1efc2417f51afcec7145a9c2625496865c11636e285d4c8b053ffe66887333c51a712fe9c8ea57606103fd689dc88f1fe37dbc33ae4e92067c5bf51b53e2f8205164c800e5abd677c73949b00ef
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 69b850a99b471003a56931f7856da357a2254ac50ed81dfae019c9b722b95af16047a0d5422cf7ab66ccd898e85caf0e03e74cc8a5a413661e5da483b3f0363e63a7031bb30626c8f73d6e99e290071094b7fe5bbaf4d303192e59acb5e53fc7cdee78576b51595d9f7a25ccf3c7f8889de68b9deec167778ca27ac9d4c71c3e
+A = -1976b3bbbf92acbfddbc05b5d9e7b62a7666b239c1e6270db7ec6dc2929bad1024e745b897840853d14cd815aabb01aed580e1cc66ce37f9d1cc4c9bef8ddd35d28285faa29f2003d2a4623ead7d73302ea9f380f16b3fc06b7c2b8bb4ce4c8b03bfb6056a61c620e4decc6048cdda5e2d3ed8a13b779b8829e2bbab91e9f6b0304b1c08bf8fd85e0f3cd7ee72255e5342e077ababdbb545d7f809bdf8145
+B = -2cab554f7a5d21c499a1025f61e6c81ab0fc68a874bf60470cfac57425a451365be62c380ddd31f6e202f29769e2b6106868da7c81522e03fa6f0704522a5f8bfadbd007bac65595e149f6c585d7fc022db016bab32819049e7547bf85d4232a7fe19084907c528e7eb0434f2e5a375ad9b7d463821bef2f6a721a635252576c176ba42519bfa5d97d0e47facb4426aea0d755507dac81ccf1537b1003ddbb0727f6
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 2ce33adf34f2249f8a2d2e073976cb4c78b71414e027657fcefd56fceb022a06c1969dfafd519eb9e2542662c7647102f5c528734dd005fca666be57b46234123bc3db286cfce07bcbb399eb6764daf2b9aafbc2898a5ff43ddfae849c7549289640edc4ab7c4b9fcf5e159623e5497f509ad6f0270a41fd864c9437302ce380
+A = 509f5d5b160e923b4fdd72f4d522a713d780daa4bfd10ddbd62b26497a2e7925c495afc2abf0ecfcb7980e588f96c4078bde51c7b2c19d86d15bbdad5de72fec2e0a284dd693ce0902b40e54af87ac5a5df38ae6d1d882ea6299fbe6910121ebfebd06b454ec5f855bf3e7cd544a4b0d9a764428662e824e2a6185723534f5e6ad829734347d240c48c2c0f8bd6be6ae8a495a9e383fbc7402a4096b8c2c214
+B = 1a3b7f55307031609afc974857a6cc75821e73a1a9535bd6b8e141437c3fd4a6871c904e22c5d9289df7525ac69a0341d3620bcfc5f04b38ae540e26beadbce0002a8a8bfd0f6a270007e4c52aec2fab11fb2a831b9886997256e4b7e7ad3b0ec64c0f31fb0d637869143712291f5073a5756466d7c82c31e08e09683478229bccdedc2cabb7e426af9025185d8dd5124e08afa4e981236180e0a390004adb7918de6ba
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = a81fcf9a18ce476a839c896cc5d9b639fb1d74610e2f618c25310147b57cd77806c2aab90be7be4ed10f0122baf9b862b141ee8e4be5e0c23ea776267f14c31e50b119bdd33f2b41f6a4c43d35bf6f095864593e0d8c0f1fd4656d8371af844d197308bbff14e5a28b7181eb6e6a2b31ead7361e287f3b4550ab0484bf7baaac
+A = 19f1ce60ca50bfdf8e02313f1c9a45496720a2ce467f1e8bdedbb32525d762878b61476989c7f6ae8dd29c983ea596e521bd4cbf74dba4d505dd9ea5df423474fa9725d5b65f1575d26ead95725e2a59a6c8a5397ebd6b54123e42bca44781b84c014b8e5d2c1a86cf34d764b242baaad5be285cec72ba8ace808058a0226c04f95eb2b53a828d0ac41e6b40e5a4c4092788d9f7e988752f175f075d545f421205
+B = -b115a1101d97664759538d22154de4b000c008e551e2ab10ad05f12274b10a4cbfee762d232df5188fa1161f37ba61d146e8b95fa715d98e016da8beb0600de65216cecf8b8816f6e7e73e2a2bfa7d0bac74b517b906bbc43357fca69de9cb5507bd95205515b97b3a4d6842f3d7b09606cce1c7436c462f49dd05e915d04ab6fe2748ccaf025bd5d19749cc468d228ba43452ccc479c146ac6d781717bb9966bf3835dec
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 1473f092540ae30de595666beb33e430cbec42d7a28d4f7982e62f58025cdb617cfc33f1e5ab93d2ebefd7345561b81271bdc50bfbb0db6381dc0ea023ff7c72605da26dc7da2b5664d2ad7967426ca97b3745f82528964bb68e70087e14dcf2d71d30fa0d1f7b3f10b19b357e7053fdf22bccc5188c6919eff1e5c402b750a4
+A = -68f280cecc512d51ae534f30aa198cf7b170c346c1159fa9cf158d0127d43e50a8d4704ec54b8b4295dd7f51c6771cb5767fe0c975414cbe6d2bb58ae66a095e8832d5f443498b1ade1f5bf249da58595ebd878677b34e3b4c99ba6124e2b71d86a8d99727a16746469de51b0a61d9d981459a6cebe206cd36a09f00ffce7f532e2c31999847ba000b9e01a4b84f454544b6362a5c093b9abe9d583716f4534f2de4
+B = 5b79684387f18d7de6eec3a63d737490dc2a46c0616ec16388dca2be60adcda11ae13063ede3fec177171a51dbef430f8c4b3f6d297b9d6c020fc44e3ffab891d0d751d033fda813861bc067c181118dc613335ce89c5960f952e5fd28bc72c41b7b6e374ec29b837f1e00271cab646c794579d315260921dbc3b984b86d98b8f8816aca4f16de50657e4102f34d9e29ec3a03e0da06e70f69952339bf2ec4a7e74daca82239
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 5e4b3f4aea7115d592bde9bf7c6594fee77372ffb19f7745b4de878a4024f81e8290c77d2915424df20004a7abb64c214104a3123e7c8f230c159ccb99bd937521b433dcfb065b186a685fc40f9166bad9380a02e297ffd6a307ce8d2c8f2f1330447a9c06c327b74f3cfc2e98f3351a8b385bae855941228969d1c29e9da3e4
+A = -11c1d396693139df5bd91825c119d1241c3f57b7ce95b46472dd82081738cdeb0868d18eb7c8ee7808016b3311f982adebd5a2e5f4e201ec4a34f3037d260fe580e771222de5a1a67947a4552cc03c5c59f9e60e25063a702ad3c3aa43f061a22567f938a91f1dd697c3e3978fa11ab1d65030bf327f8049bda745658bdd4ba8f3e34b060c6a2c6c5a8be54c7cb5f6b106f54a37d2be9f674f7747744d4350b3acdf373
+B = -25a65b6acda692ba3330d70dbc3ea4dfe208c0df358c50b7872245a909c5ac19ec568b1a1340e1a094f5b8e7d1e3b7e04bb4df002558aefd4540135d62d75bd5ce959128c1300b9d98429d7369610866d98b22c345e531f2beb80b042b6ad48da077043401a82e223e9e529e7407bfa466dd2680973006d047d837c26a60cabc36a7ef538f603ba19f8e923f168ebfc3834df8f77a559c9e0342e33df245f551bb242e5a66e5904
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 47872b544fa0425981ae17bb450ea346135e6ed7a9de0572ae14a6e85e8319f27cfab778cdd8cb5f93b417d9c66ae0fb7bcc6652620f7f3f74acc2bc9f2c090129fa8315aeec9ca7adc5356484474ee803883ba4695d7bc47c87eec508d16a15150cf3f757c4713de71366e958d6af045b2d282b6ce96976692c80b1e0b6f846
+A = 7e8f55c040862f12d8cc6e506608eeca65ce38e9e8ab18ef7007e3cf0f1c9a0696795bd10f8e1e1f55bb4f4f3a35c2e0ad18289e250571ccc26a961f730346efb1e29fb143ed97cf72deaab19834fa2e98e9c12ae4cd23b9c5ecef4a04c439f7d42e110b30caedc4334372ca24cfe4171ef1430528f7b57bbc823fd606fbd30915c5817e6c57c967c4c404a0847b1455da17effeebbec3f9357358e00001239aae209228f
+B = 1cc00b95f6bd3abfa697400c98110725a7e109aa9b8cbbe9ae16327c4fc8e5bc93afc7a94da32e98e85e4fd5eb545192c73007d97a4e84ba64fe187ef61d17f0941e165c9fe64c7b8054e24dad30f92b50d1f526b4bb031e6b1b9058be24884b170a145212273c51692b71bc57ee53176d8702b975bb6ba96284b462da2ce38e12d86b342c7f4d3cd489fbce88a309c7df1121d7bbbaab6814cd1e54953e5cc46813ead98f02360372
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 5d193b085e57c3f1e825cf3b36c8bdc936c603136bb782a244b04a79fa713dc7b08436b85ca3b483d2e100a012d6430679b30c8e4101c8f08ca0f9010dc0f27fb37be842054dfdd99362e03a7f55ae58db7b47f694bd35d91a58975ae1f255c41617e773f91c2640f768bc702a213f073682dc761e056b34c57edd85585fe04
+A = 1bb1c759ea94b61a1721ef5680f42af30fa31444b27591a03b7c9bf5b90845ab965339f463a78bddedcd62fa21197c32d6850c61bae195f86e1c7a23e7a20dc618c59ce3a1c6ea6306c0b01b11a36d0fadf8214c36a133d689438021ce7c78b20c85256ec607360cce14f139513d9f3ea6eab067b1ffd0935d7c43419b93ecfadf2c5a902b7c39a69bdc023173bdad574adc77706c1a666d66f69578a5bffdc7cd6eee28ad8a
+B = -e8072c49cea603d48f20276df188fd2fb28f8721d578220cef7db1e56379c04a6b372e56a047cbe59ea84ad026adc5d0aa930011db63bf4959f15781e060e0240dfac0e2a2c26be12a21e5650d12140bb49a2a8e0f6a86e4b1eb79d9b8aab3202bfd339096529170cfe3e0c18263128686bd9305e92a3c43e1523f97d8a6a2707773e3d441da162a79089c9ea1e094cd5a23474121188013c8c287965a5e77599f6a7d64174b06cc165e
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = aa79c899c2b9518857c9e4f96523a44607c3f6a97d1f40d6474ec79deb2feadd955fe92d789df4d362c828084559fab56b5e33a971abc5449208d31671c7e220c5945886e33ed1d804c059a8e439a92524a785076f9730732bc5a152aeffb5b9ecf3a7e4b55983016355c4c29827496fd4d7e6532c270cb9ef263573e4c63074
+A = -41b326c2b86e7ac14a2050bff67bb5bf9697f02594789c4a2b3e8455df4522546278d0620f28a680f6a88ab545de5829305485422f4e70a5ebf0ad15508dfe3f16ac556436d8fe8a8cde83ead549d88e0bb24dee52ebbb49159ae71589d918d3fac8011cfc3afad613ea09173856b7b79b55a2e43e0f7cd21eb9122d5f6a1fc5408414f5aafcff863b870c67b740256d317a0c58af9a81d8025a086a1f3d79f7408d4bfa06b9dc
+B = 4730f03c389f9bdd92fd864177e06140c9dcc02d01fe7d37b51d44de140696f116d11bb67adf7db797edeb7c304386a7f5e37bfac46a5462a6d4c49b1bc034c2e0dfa56f14bbd2a4bfaf86bbad4f6d0dfa13c782fe680847d4b43373d7137f5c2ebe4ad58c695a7d4c407bfd888ce04abaaec60a3fd33db10eaba6b6acf0e16cb61d1beb9212c2b07921bfb5595ef1eb389200b356eafe8b5288d8f0e2cf252b38301de65190d56bfadf57f
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 23f9850dccd2af799f18268c3a2918a69019513c55268faf2477c50677fce277d8ce58a0cc06dfe389170faf5f0ae13ffc4954c746eebae66efc14eaef2c2ac9001f3c7ef7e32fdc31dd725b6a8093e33daa6d19808908e0c2d3e7c1c58e0fe9ed92f4d7cf3cc222393ca4f95feab5d34fe29116410a1882dff7cd92acb87590
+A = -10a75953e5fb9903411869a2949f8f04144d6e2d61f95704ff55a02f40c4f283add405353a68bf7d6acc1b8cce738f0c6f9271a538b4c688dbeface58eef0a0a1d491a9e66958750db97bd01466edfd245cef03bb6a3acb81acc63c38538e7f15deefd15afc422a8641c357c31a069258dc0ebb63f06094ed8fe7d4d420246b40302361967c81f0a9ca542fd1de01967514ff2565de7ae3b4a200d63feaa22fb99a251cad66624df4
+B = -351242b6e6d0122f7120deb8357c3bcf25d221a15f83579883bfb4dc2e6099e6b7b95fd08f6e573d93354b0676f7bc9fad563d6eb0f3567ef43efe3d874b9c7733e4fe1ef491043e1f80aab6094cc9b9c236570972233ea74e8779a6eecda23a65d08d878850cab6005159265893dc0f66920a12c26dfb421ec326a1ac09e9ab8085825c31aba488af02cd51f96b205c50e692dbf2d844ff0a989c3ba9f1c2bc7f2e7dd9458a72d310eb28d490
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 69c7fa326630d7de69249807cd8bc55c9315acac26fed3caa3c8a9c6b51ee96a7dd0b3bacd5cc13c15f199e268c5eb91d1ec36c085f83b437b9906caa6e39ed7bf09778610b621426cc8d36d96f541d0bfcc7693525d33e0c2ecd77ccfe80289a11155b37c7ea7791b5c2be3f9b954e230c19d746575afe9a1a3a9677d23c5bb
+A = 7cb78ca8e5d903096630744c85975719c16333e2e44931956d8c45b001d35ed4e184dec88c9e2167d2f338fe6f25540a144cc419590a4ac7caedea3bbbc565365d3357baa62fdccef2c5ea616614e0bff60e81916eb4abde0c9725b1bf6869e8b1e11f6d0d08fd712bc68003e55ed462ad4946f7f982e663f65d45c07c659d9620d5139d2b3332a68d33aec36e21716a3b75f44272a19f860e6ab3864f06def9a5ddeed340ac0733353
+B = 16d5b074e008fdd30e73ea95cb5fb87de806319388b3a44f33c94d38be0e6f1a92103dbdfb3d23b6e1d19bdb29ac14833003e9482cb7524d0d7b4c377f4911e3372f2cea6f84c938d84e3994e80f0d68e7e385ca29e02f70294c921dce7cd3829c5854ce51d1f4fcf7dba910b51b48a3f53cb1f187182435f21f6981cf8440f9c8287a9749c92c0304cc2bc91eef32d8e6526be802de8aa16684e8854cb0b67d9f7ea00f6f0145d14e3c251f70881
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 72192604b2f3f68b9ed3e261120ea52b06a05869f6abd21828ce8abadb3a71c360a14947bc738e5d1d530b9636d796f785bb44508477eefa80c4b77d4e8e35463e15ea2a48c682d3288c5abeb66181e4bed7d5b4e0db20fdf5ed68513aa5ae7e0978ec1c4646368f206636ec90e808817bd1d03acf9adb9ba57dc153873fec11
+A = 1112d291463b28ef45e879412e6607a3e20d50dba5044e71883bb3cdfe9bc694a577fd7d896dfb836a171f3a4d8fd025d3a979b43e41baafaf7b535d9050e47f4880828640e952435648960bbb74a3c25dd90bccb3fedd254dfc0f031d0e8a468e93bb69f771ed35f1653cffea1a763491fdf6efa21aefc287cb611f5ea0085f64cc3705c784f87ce00846901833d01a3c45ce047d822ba390b538f0a24720155409f60ca0d90e13991aa1
+B = -d553fa2dff0265cd9d083ad097af87a99af3d8d93a9f4c07440a28a427082004ae5c81d22bda1dd2429f540de8df175c1b4d0d50f0227489ba570b28baa35055df951d05b584ae6b051a135d7eb2a501b2441f82c135a8ec0eb81d379b96ef8f2fd526ee62293bcb934c76ef8083727a4b28bbfc9f515ebcc2bb7ed9594a106e137ce94e9105b2e2f4776aa9c6abdf426a181181fece3251c3ef4f8eecb634e6bd47c5878663fd51c74a66b92713fb7
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 459e19faf105ab17ff794927aff86196b3cc3461e69cada53ab8c8c81e2b1820408421ea1af6ae10257e8cd9dc16386906410761fed62cf9ddcf0da2a92800d99563fbb9cb1ab0ba46a17cb9dee3f2b68992c2b832a5932e4533fbd5c4487d870f3fb5d7a1c358f4aef02993360915a9e9cfde234df5f51c761d84568400b618
+A = -7a964c62e38e4124cd2bad727138dd12a086a2bf01c095b078ce2f81288d3c8435ccce0c8e00229184091130989434bcd107a3a0787a2f5f4b0e8c23b1cee9a8f39ea279fb6081efb6c3df1704fae9e87d63ac6eac4c6687b3551ab7ddac5ca0541e12047d04c2fc760fda0916cd2b585a90d25880fcc1bde8f0a1a413969938d42e8b3b5f73118798e85b901c2e15860e29e2ee8b1c95336b97dc10a21f5300e0352adb60b40a8a99333380
+B = 743ff4d91ea3e0f9c4f72e5daecb4fb00b15b86e30bacebbe4384324523d14e22abe29b00573733f594d652a88d98c987f8db08b27b4dc68577784fde02dd410ebdbfaad9e9afc6a22a8cbb13a780222bd212fc61e38faf409e940fba35ed909e6938e83b0fdf5b5e3ce138604823e788efc3aa0df924554fb70fd2faf8249e17a827c5d85942005b328bed97e5ea1f1810219d77f2fe121ce66518e37c84d64aebda3c397684212384deebd520a776b95
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 183950095d9424b0ed09985aafbbd2e5d64bf541a56b68b42ea8cf9b2c051615ee7bb6c0687ca6fb0036888fbc927cb7aeb303750871442ff2c0087a95f4efad568f48b03bd2b9a9ac26af8c259a3fa97cd2af7e3d8f36148c26785489cda6c00a21e7eca219d1f41b2e82ba8e2c1cd752eb08a2fd50c6f9077f3096e2eba05e
+A = -1d2fc778cf44c6992d1f3a056860eeb12f969358cadb087dcaebf5f96bec42bc0aa98672260adf1732da057e9e0d22081e33f5fa71f248cf89dd361036ad58692637cdfff584a191279f178242ec0ad397efc52e99462f496caa0f3133c4238aaa877fa7094662f080eb284c4cbeb992a368c2d157ac5c8c9160c167716406190fa39ce0abcdac52c8020969b87a4f84bc09a51f7b2ca288c93b1aac64e19623a7d9e69976a31074f637e4c82aa
+B = -2f188f1245b75cd21d052ec76edeb5881944a143fee31c67370fab0420a748f3f1957bb8332ffefdeabd0ca806169629f130c86c99bab490a9668fd8200f4a9b1704c589e75b5c8c855f133d50b2ce06191875e2872b36c78438d6032d53004c047f49e4cb81e19fa84da16d053e6cbc7c8eec0b9129a8831eba690e0542ca3fefd204258624e92844c8b7bcdccab986475a47c8b22e89079ea6580ef8f496099cc24dc2911dcb1921d1451e2163b55bbb7db
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = a02c38d5df9ff7055ff84122342ccdf6ed7f7d54fe8227af091371f5ae62844645586adaae99c11f4ccd828103a81471bac72dc20625962e41d603e760591bb3569a21f45bf062b86b5fd1c617a4769a4d767a0ee14d104084c12ae875316a8f2be7adec0104381dc02c20b5851efdf7d4bef0d68076975e0ada3e58e101e8b4
+A = 5daf37d616da184acb278a75fda4e4fa49e544eadcf373c054b203a309ba198233f2285a1b55dc92e05d0213b26c82e261d8383a845813077b2e1b5f4553400f09410987c8dd21d4383e0f05747d0482d1a89f160a5220b22c78393873564fc5b1e4d5627ef3d4a05612709f301381df35606e99560fba07a917d7ea7413110fb5a8290e114d5200cfecb00b6c53b2ee29911bcb2fb2930eadba0ab9dfaf46443370307d9c3b61a329f0b8b8cbe7d
+B = 1d9539fdb1afabeb9be6e774dc7c7cc4bb4fd63af7abb557a5fc80a3fd23a4600de3c7fae89b91f3d441b61d3e24b2fd3d7803cd71620e7313917b4afb89ef5171a3d8a68c3c74aa3dfc8058d555eac429dfb6db40a9e0c25aacd2050418d6f32bf21cbb76981269dcd5883178d4b69a931a0338b93022a2ed0f78f3d8877989cc406f19d6d082ea344309318c56be7946412ea0867c78418ec32b9fa3a61017c10939c9345021133116933a3d1eb86a3ef16424
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 5fca287abf1f487e0ec18c230860eed4a2e550228b1500b1e33bcd6675646b5afe505b55073129f22352dc2b113c584ea1b98808214b6916933e90e036b129b61657cdea9026e1fa087ee300e055ae8f94ffca933a2d70453ed220468a5a3cf1a65d81eca11cf570d7d038722397f487af60531f24a5f069671354882c8bd2c1
+A = 1d9fe15171dce97475f4ad329fc8fb5469fb2b8086e4b01eddb6ceffe5324cfbd28d791705848569739b6758ca7e7d7d49adf0c11d891b0a5879ca870d1ca5ff475513322ff218cd26024f97623bb8a53084594e1fd64154e1db702522883fcf4c0d677a7fe90096fc76dc3800816996308d8f0be2dbf3b879f8a000c0ac534511437e2ce2d7ebcf42fd1698a829eb846b3afa581c24d5bf97abc6e247f110f4e872a2474e3acca6c8c0d518104c3375
+B = -dc0da8f7adb8e9f7b0e3f293cf623528dc8e9668317910417e52301c50c62e7d30e77ec7e38d6817d1f5a93e851f8560f642f23a0b9f836812d27b1b41c0867088a3108332b8711047560052ea30c8840f03a25c65b227a175d8f340095823788adb5bdf2b7ebb801e20f6b6435e154f78d17b8fc4373aecee56ec7b8f5686a7d22c8571797fde85cec884d45ddc4b1f2cc47ebf56a879bf286f349a0edfb531168b733d43de3b86b49eacb10b06a432c96c63440b
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 6222c1a14c6390d73944cead58eae5e7a6c19d19e4563c36cf624f5b61d99991bed7dbf6a0723abc56469eedfb1f7982987c2c7af6191178cf0933ed5f191b8117c9d726cdfa8b82a2fb25ca5436023f5860aff5fd482c611f134569ae87395dd99e5e9d400b5ab1e3064210ded096411654518110ea45899f4be2516e35a229
+A = -7f6766be6c6ca9bd1fd7ea1f80bfe68693f7ee4b5ba2946846839060d6028eabbb9079a165c1a07eb6a01239f3f14095225b8617753a1cc3d9c1e69b516d8705cfda396f4f0d05b0944a0f08b478d261e968c06918914ba87c8e7b7adef5cc2a875917d00585571542af219bd726e502b7f3f0bdf0cb1dfc6796be2e22e8ffb5b8bfac7e15e991022974e75d3a5eba214ab8a1aab2fcfcdbc6ded2abf834d1899d2e3ff94bad9c696aece045212531773f
+B = 49c6f869745983cae44d33cb7ba141234905441ca53172abd1a2dd8bfeeac4b236605cd2dc5b04ff9aa13de84872145b935b85479136065d2d57fd15fbd97480c25c6354636c17ffbca33c9319d65e82523e39fab49321380a130fc160857a451a69b1d0509d5718a9cff8b49c2d677c1f66bf77333d2511f58d3eb2fb47b3c162cc9be8b012d8df70278f0e21123a69724a1f126369a236d54da026ebe222c513f24b577707b5ab4b90ab0e22b4e38ceb4181d4ca101
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 9e9cc8c5342dc6d6daf55fc9aa9f79ec18592e8b9724a66881c379245c91f06a7df50a6ba0964603a6dac97e77a55d06efff17c93d5faf107fe65788d0f56483915f6ea0f1ccbda7656eb58fc032b5771600beafdc12c2076110a9b9670bd0754ff6a72c5d6e1a9e4e42c688e1cc96d7aecd815bdf5dcb16fcd1be1275ce7282
+A = -11635fe16dafce21efb1c599305e9a16eb5651187cbf054cd9d911c13e8eafbb738013e212f9c2b3662ea15ac9bd82b5751d43a38e4475d2310945a812262309094ae9cf59e0e9f3d02c92d8ab01f5733a20f051054a240bcbe3a7b6bb3f7c434229f631c4af239d33bd3ce30a372a480fdb49b2716091d26071aef372b8bd8ee8eb7f2965a372a836000b3737d2a833a39230e721e4844e16031ad69cd45ced60a64510c1248fd776611934d8d2a913d965e
+B = -3bb2cde9d3fda96fd7e6b24645f8e00b43affb223f2b5c3f4b7cfee905ddd6703a9d6c01f1f099ad1174da215a645ca4707d8156e762e2a253d7cfddd05ca19823ada9d33924013f677cfe4d86bde025391e0aaf91c6b776a9cf8a09dcad7cea59ee7aea1cf5f5bfe67c9d4456332d1f98e5310db9a0230381e1867a8f75b8757283f911f1a5e0d4afe5d544afa8d86637f9c9d87428fdcf8b4eb8f477e617960948253b24565b2f23081c47e211cd3c788a92732a49077f
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 30dc89bad4b449d1df9ea9b8f9d40b323c71d7e1133bc44d33bdb87c38cddedf83bb849e83436e4c92a06546fcf3e24ce6cc89d2e97a48aff2c7e3703da1b167a112f662a89742355e11e131e41052f1b379753cfa32cb0efa3a07465a258c585cd68c86bc9a473f5262c86c50992aeccbb9725b69ea8b3a7ebd2b6a24db52dc
+A = 60463fae1e9354559160d55a453c12d75775a53d1606d1fd16bef7e4ad1c78f9568954112f9280c46781180951534c5372dd5aaff3f33ac9c2e0ce4934d7009aad2ab5d6a5e5a141a36846e8925c7a28d116c68fb78aa9a687ec9bef173c1b69e0d7261f96eacacf237e1fe5874e5d553985b0fe7692ce8f2a5feab9ad9a2ad9c4bbf050b73b8030ebc36b94af8c6ecb67f8c94607d80cf600efd4ce4aa006f9b1832da8a1fdf8a564be0b4369149e8639e1714
+B = 15bfc50290b771ad147695a4c6701c47f2e8aec0657a4ef999eb45685200981b0ab5f8abc143d64878b85e9548651a1afd0913e3b14d11d3a26ab9793596801662a67b0062fdc8888feb029266f71d170518b6a4a040f59996bd4f257f221e830d0faaa9688aaa6afbc1f9b40d25097eab9d71d80aabc085f3a07e48bcfb37119aa00de60be55fd07d5b1281adf7b98bb589cdf2026252edf2f075ee176e23afa6b1f924c9fcf3c34c76752e833278a2e6b62017b88b77eece5
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 8b506c9bfb75ab7ab420ae6c9b371ef035fab512188d9df76f0b31831573b44cb08266186a04d20cc761d61b6df3e33ecb86c269205c2c79ae6aa4d3ebacac8ec71d9bce1d7ab146530b131c9038041c6ce8152a6f1c09b9bec8eea4462dda0f08d75edf296eacbcefd62a0c197ed30f799343268bf6edfee4995958db7e0420
+A = 11c16713fbf8bc9696782cb5a88174cddbe68a04e8fe93dd074aab33dcd85f92baa178b2f3b8817be0cecb802cfd3ebb06734c9d399a1f090e3a8a2110aebbba0e920427bcda74bf11700b945985bd532286d44a1a615cf7c501412e454edd647f8371cb8149474557a0d47cbb782f460de7a3cc28991491ea0fc510286711b882987b09341c079565414f2c930e7c3c3a3e3e0f1d786260a7f45c70e0fa20dfc63849906af61707cfdf5a9b7a4291a1c1586d16b8
+B = -cf5638af39c6da3757a09a92e0bd54f852742682dc91c71dcdc6e72f7825a0979a1ead2e158479ce5565d22472dc3853e6bf7ba43296a5e0e0a355f0703cecc02ec79da83e3e9de10a6eccb858dedf7d4c400c27486a5b8cb34d787cde6a5fd271e83a6cf66057838fe30db1f30663cdfc22ef5d002b0b5a05831228ea200f95382a58d0d8aba36523d9b5cb7506f193131916f3ab66ac9552c26cd0c2ab1c449eaeb8fde752f4f3c3f9b060cc1f8a1e37c4fe5ec306674b66158
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 347706abeb168205cef9b0b8c6b9d6449ac501af7dfbdfbd41a20a6a47872cbd7d4cd32f7b0805ecf1573d534418b7cce98181e079d5061b02639fdf0161cea5314dbbb2ef39ec841f695281f3c7de45f33664e0dd1658f645adc1dd225f781a3fb1634517c556403587b2aecd56dceca9ec19b930cead2b1d303aa056d28bc7
+A = -5e1c869e5dbcc684c245d5c69093bfeaadf388cbf928d33a8ae2148a2b5145937e4f654c5f6a36de1124bad1de8bcc9067fe1f9a44fc6ffe55ce7ed5cd0dbb6337b0e1e96bac1eb2a3606dd97b0bdb975ea59448be50191cc7ea36481ca9fc85c1c3e1c97378dbcd6b355622046888df2ab3d18d805f4d31d464f62a8e630e955beeeb5e00c70242b8f8df708705abbeb95dea3561756298b5f3f7fe16e965294eeeea4546f5e8bacf9d6b4f2136d2e206a87dad1f47
+B = 70225f0cadd328be36ece2172c836405db3fe80ef99ec74fca25406b73a537adf5073f2b550abfc4c0fcc2c2850dace0da9a266768cb4d5ff7fc6c1c248ad74f47592101b61ef96c1302924381abbd96cf49f50c44bf7e0551721a8ae85abdf9925548d13b8c5d1a27be8a40d0f43eec3136bc3035057b75aea779b4262cc66e6bc68da93c218f1920979291105d4b02117d66deb92c3e511aa588b27130202acc9f69521957f79c7e731bbd5461552b9b6b24240dd71ac449be9777
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = a2cb238f326d47f95869e2dcb295eba819a443dcc7c2785461389b58327742702f4c86e47af129f1fd4611cda93631f9333c358a29121d58286333083d13e66f30a9533b77ba3e26089e7eff7baf19bef8054af4e24735525908864ea9c4756b42a69c897003cab7b63cfd9a5927ed562e29845308eb2a55e7f8f03c87a5b7ce
+A = -1aa7ae6f56c38b654b281525b9da953ef366c2b9cffd3042105ed428dc7e5f2f2d53ef90b468bb471753606cc7a3775d86bcd2f4d5119cdde3c487cd39bf31752c5ba297e529c1b8121487e0e1de702156d0166ccaf51888a24fe7b48624eefaec855e2200929c21858676ec9bf4ceed0a832b69efd5065af544e49a3d209b85a77b0953652cbf0aa897527c52c9a98de9ae4c827f762e251478c88d410123625ea52b3478b52f6b9987d42009ae427763357ab53195772
+B = -226630b6fcdb5e274a25066ae2ca2c803549dbb935a97c0d7f6ab2c971d74cf6acd265c9d6815a6b2dd23dcb3c23b390fe8b1bed92b8c64c76c0ce62d5e7ddd7ce445bab0ca905dcfd0f128e5f4ffe966f3903d7ff1c61fe174e373cfe35a6d83249ec40b4a354d46fa1c90682efe468e895ea3da710838c262e8a47752dc6e7a79fe20051f51180173b58e0aa37b22eb8efee5b6dc264459ce4d135f430cb15afbf8c53f0de894bd2aca1f7ea32b4209a22a075f7b3b18e86f778a9e47
+M = b18a9cd6a0a89578ea773fbfc0767c8ab817cdd585c16afad3600540d056c323d83e7756b1b74e4c2a84df7edd562e011412a0e2eb6b64178a9e04f67550f3081797873f444dbd03d776835d696e464443a0a6f48d509228fe976c54cb82925e8a80ee65c01ad9a5f56784c54192112fbca30a76ce579d3eb6e783643e971d48
+
+ModMul = 9ea62ef634
+A = 55cc58c9d8
+B = 6b49179821
+M = f753311ac9
+
+ModMul = e9ab3a2aa60edd30108
+A = 5134a36c2bad180dd5bf
+B = 2ba6485656d041690666
+M = 9b9cc4409e86c8b0fbbf
+
+ModMul = 621f9b797e866028b7bd1ff828bf29
+A = a202338dffe171c99434d84f3
+B = fb71eee7045b3e3ab5dd809dd
+M = b3e6e8d53b7249df670e3c59c55d33
+
+ModMul = 808d463d06b7b7f98e3cb2783e2196c349d62672
+A = c669426a92d3cb5b316e2b5b9
+B = ccaea3874008dcc92450d8b2f
+M = b04dd2bb325baed1940cd000e8cb2d786009ccd5
+
+ModMul = 872164b92b9426b237858c4cdafe1694f96b0e0e4c19e894a0
+A = c3255cb24a813e27c3dc410f0
+B = b144f39e7c2d33605ba7bee16
+M = f3639f4dfb782f3107eb402fabb5fc878903acb5e02e129077
+
+ModMul = 6124d7d171
+A = 235b938139
+B = 3a56a22a28
+M = 83eb4af4e5
+
+ModMul = 9c006f56095d442ba98c
+A = 207e14237c42e3764e5e
+B = 8a495a26872432fa8e33
+M = d0cf2b8ae5c67d6736b9
+
+ModMul = 97387cfaef652932a230c82de59cac
+A = 82ae0fc5e943af5bb8c4adebb
+B = db1279be12d59ba3a9c036a61
+M = aa36dc1d13390169cd54d711eb511b
+
+ModMul = 32ee73c98da657464c6fed4274df20b099689e00
+A = 9baf08248ee24bcb17714e420
+B = a7f0428147bfe098666180749
+M = ce0bc198331c9ed1d21f0d498326e8185d3d602d
+
+ModMul = a8b3fc0b53df3b92753edecd6fbcc5f4840dad3a44da704e34
+A = b36249e259b303e453757721c
+B = f0c1db50670d92abd93bdc84b
+M = b05cf978bf2dc7e093d7d164e46d547219c480382df32b33d9
+
+ModMul = 2663b741ff
+A = 58c8e7f7f6
+B = c84681fc87
+M = e0a50dcb45
+
+ModMul = 21af3c0b42328f41b81e
+A = 1f79f5b5bf78c9700d
+B = 5bd1734ba0f0e59c2a25
+M = 9ff3fdfb5c089244f327
+
+ModMul = cbc280b5106c2c36cb31ad7e7c986c
+A = cadf6482b769e83ce7f7277dd
+B = f9862a06da1a9c89547b76c61
+M = cc36144c88139ce921d2fd1740bc4b
+
+ModMul = 3813f2fabe016e19fd8e70687ff473651a5fbb4b
+A = 9c51a5bacb5d9f055a9ac2962
+B = bfed5625b21b4e82d1f105a0b
+M = a47977acad7c5deeb683ccd265cb30cb193f22a9
+
+ModMul = 76ff291a02715fc87ebfb3e99153c04e53358dbd7beae43478
+A = 997c4a7b537d9500d73a205a4
+B = c679ce666af284a459ae5a26e
+M = d0d0fd4922953941acad8beb65c00603b19eb44fb8ca51e3c9
+
+ModMul = 1a90c92fdb
+A = 94fa7bb475
+B = 564b0a3339
+M = a1501bdc75
+
+ModMul = 5e7ae5470686bad7996a
+A = c725797912c6c5f30d94
+B = 3a7f4c99ee3f5fa9582c
+M = cc50c8b7408f09a74973
+
+ModMul = 72a15b13bcd1b63747342a6be8f0f2
+A = c33357af48a2df569e3c11ce6
+B = a4b4c5c14d7796adab54b6cae
+M = e22a0fdca62a37f4c8a61c96a429b9
+
+ModMul = 31e179bfbf65b0695dde36a4fb72d131830dcdd6
+A = ce8d3adab8cbf15c332c0b289
+B = 9333f94eeb7d7a86b82becc51
+M = a532a76bd5cff409b580d54d12ef75ad8179b381
+
+ModMul = 8f4b8a585415adff3a7bc35fa88891ba31e4a82672c664fb14
+A = 9a2b56a54bd0727ab4be57ff2
+B = edf1781b4296567990773005a
+M = c5a7c3b97ba00d6f174a019c6d37eda52036c528f351bef0f1
+
+ModMul = 917bcdb402
+A = 55c7dbd314
+B = 997b29ef79
+M = af5b4cbd0f
+
+ModMul = 660c4bb2b771f523a4fd
+A = 43fe52461d5139620a11
+B = 1f8ec4b67de1db54ddda
+M = d0458e215b7e6903d96f
+
+ModMul = 7aeff02c143e4426fcbcf32bd1277b
+A = a2671586369a990dde7829f36
+B = c7ff67937c900daccc0ab1d8c
+M = 8ad9c1d4d3cce681d1ae27c27982df
+
+ModMul = 4b153d57433f0f7276674d3484e9bd0d25227d07
+A = aea36cf51dd2ce06c66b7a407
+B = 80c9fe5bb0afd2bf8b3644f96
+M = 8cc22a67ed7e5a7a2322aaa09ec2be94998494f9
+
+ModMul = 7f8447dd983b113f04c6288f9539e53a2e9cddbca8b2fefcc0
+A = f67636b03821c8f13f21217a5
+B = 8473a29f4ae33f36a0d2c6dc0
+M = b829af37b557c3ddbb5257c8b19144b90708a45a274d6655f5
+
+ModMul = 17fe4644a2
+A = 912611576f
+B = 7a10d36b80
+M = c5fa605133
+
+ModMul = 8159b23d4fd697b4fd35
+A = be2d646e76494439e60
+B = 60fa770d05ebc69772b2
+M = a6e7c940cd749925a85b
+
+ModMul = 7c412dad5c9fff91357bf181caf2bf
+A = 80f476ed5acae75b34ed54c52
+B = fb818e2bdab3b5f4bd84db3d0
+M = d0339f7ee41337d8462d1a9c207d1d
+
+ModMul = 70432c749da4ade2c38237545ebfe6c4c6a92f6b
+A = ee9c92de52210e61adaa6eb4a
+B = 8ab55a85b1abab62d33e75fe3
+M = cd3faa6de4cb62fece4c3f94492d457834a6a041
+
+ModMul = 9fef1c18778a8691c5e71c0b5208e82778e9bfb632da0b7e28
+A = bd162c90bed25e84dd5b6b77c
+B = d887ee03020c5df356f091db6
+M = a2c2d45fe9decd93a0ca3edab8fee46d27ba23fad9b5294d5f
+
+ModMul = 958951bd0f
+A = 12bd0d3375
+B = 668bb65b4e
+M = 9c617dfaad
+
+ModMul = 8a109ebc9cbf86613e43
+A = a3e7019f1bbc35689a77
+B = 3189ecd3fd4ffd0229ef
+M = ddadc50600dff2abc1af
+
+ModMul = 2b4d9f85a398c852b3a0cc82524619
+A = c244fd157267f707319ba6c6d
+B = 8a07018a748992429bbdbf326
+M = bf3813fb54f749ea5627f59ce30e07
+
+ModMul = 28cab7d574e6dc56a6a622f8a7523cbb8dcc5e0f
+A = c9909dcfd3a59a3cfa538b267
+B = 8bbf89cd5a4e24adc2d8c646b
+M = c8f02682b9d480ea98faaca53b747ced33ed0419
+
+ModMul = 69b2dfb3f1d8dbb13e9e479f38edcc427d5968acb7751a226a
+A = 8019266c548982a520ab48eff
+B = d33c3e3b13576dcdb3ffaa796
+M = e6255103732475604df7c6f7ef7e6b49a8ef9e2b0c717925a1
+
+ModMul = 3eaa4c99fd
+A = 6fc42faa85
+B = dd0b4e318e
+M = fd7f22301b
+
+ModMul = 56b6b811ced3433755cb
+A = 145573d17cb0c996c69
+B = 9d3297d5ccc184896822
+M = dcfb3b383506239e83e1
+
+ModMul = 34315b6bc6d3690c28060485ae331f
+A = b963a26973894cfb42fcb2d22
+B = e8523304bbcdff1a0ed4141bb
+M = d7a379aeac7d8cf94f19e7924d35d1
+
+ModMul = 2ec9466e8b3357496f07e37ba24d36a237883846
+A = a75f3904e564997695b6707eb
+B = f9f47bd779834dc1f5fba0654
+M = b3ae5abed45d09c4dc5abcadc3ac9abebe1949ed
+
+ModMul = 88b4d86b2c1e1bd780e8d2499c2221e05fab4f9b7047c2a044
+A = a38eceb9c551f0e69a544072c
+B = d5f8e7c2d534b2b8985bfd213
+M = ff81809b84fb8eed3508ad891d3d8208249d8a902a12d6acf7
+
+ModMul = 172f2e2e22
+A = 1584ff1055
+B = 2e0aee014d
+M = b904cb0bc9
+
+ModMul = 122c10d3200270b9eaa1
+A = 86fd189e62a6dc1e4ba0
+B = 5235635f7b0336f5f235
+M = c93da97d0e95fb63dc4d
+
+ModMul = 3e461e10ac4eb749512097fbf76616
+A = cf4ce10cbca07164f3812f89c
+B = b7e4639c233fbb0f923fb5104
+M = 949647857e1406871593fad5c30101
+
+ModMul = 88117b59d9fed79dd6aaf083ee938215a995a221
+A = 94c888795567d434123d441a7
+B = c60ca79e61a352e34e0f78bee
+M = d2553a7c5dccd639a3927697a2e1af03845f2f25
+
+ModMul = bc5f0076a8c2f6cc8f4e61540d2d6f6d6b13b775b363dcd71c
+A = c170eaddca5295d6ec6272dc2
+B = f94a5685ced7661df2efbd34e
+M = fa6bc46aa05033af72aa42793e9174af2e3ba38992f33572fd
+
+ModMul = 1110cdbe5b
+A = 5db02b38f3
+B = 3369537903
+M = a8863f7979
+
+ModMul = 90fcc5f3a346d3d4ea4c
+A = b93373680ea0feeb31d8
+B = 37f9dfaf0e180be64bd5
+M = d595cc29237d1c19e2db
+
+ModMul = 8623a9997e514cf3c1d06c33c14053
+A = b396f5ede6212f1fdfc7e7b77
+B = 81a1ddc18306f2d2e84030148
+M = a6be32a91b34857842255ef8b1aafd
+
+ModMul = 63f8f0254df06356f5cab8941b77619ad58025ed
+A = 806b2627b08d987438f920bae
+B = 83297039f4aa8efc1a185fea3
+M = bb8a7e7c19be02c25cf5682a0eee655fcd5b69a5
+
+ModMul = 697238dbe3d395e81f20c9fcc8db30c234a1f75f3b2bc27438
+A = 930b04224bc097ac1d8bae8be
+B = b79496a80e45212c4663e5b64
+M = 8ff7e19d967d317c255380411898d73e3786269f09079f19f1
+
+ModMul = cd93b5b8b1
+A = 47a51b2d5a
+B = 86d6ba5155
+M = efb0ad3643
+
+ModMul = 2037821ea789118bde0a
+A = a92215dcae19be637ff
+B = 93b9a3664a406737958f
+M = 9df360b69ed26f610253
+
+ModMul = 3bf11785d28ceb668dc55b870faf7b
+A = bc8758854dc48e057cb6210de
+B = f03ca689620a77ecd8a6f0de3
+M = f3ff0747d6e5f34a0ba4200f579259
+
+ModMul = 7b30b44f75ed12f54136858ce4fe77d00e0952cf
+A = 993cd09f3e46423a8ba2053df
+B = feabee384158032dd013dc08d
+M = cd0b21388cb2033b1e792ec4078334df70b6c8f9
+
+ModMul = 8ce1e17972f1a9d2e9437d0c5219354728a5f31337808d7650
+A = 90e5d18b017118177ffb080da
+B = f8e7e09032574f6c66e623ec8
+M = da795e6ef63ff7dc4baef5c327022ccf65d44e3c4e24823f11
+
+ModMul = 8fcd412054
+A = 2e7f9b1a
+B = 6283de2c9a
+M = 9bff560ae7
+
+ModMul = 57d0d3b79f1e2f3632fc
+A = 2f8cc403de5af54cfa39
+B = 3b798c3ead52878dfb2f
+M = 805e6cbde400d4b4bc9b
+
+ModMul = 23331614e88633af879201f568c359
+A = f21f19da4b20980979a645dac
+B = ea752050b79883dcd69222536
+M = aed3faf4c88f7c4afe257c5ed90599
+
+ModMul = 56dcf9ae1c787e773774df3c8762babb4675a212
+A = 9accf901fa599da05fa6ab5ff
+B = f7f6b9b1d7bae06237532e39f
+M = b5bcd776bb2eb0805ade3c8b47e883962d3cbdf5
+
+ModMul = 61d0ee0786963906a028a1df01f836841ab6d39d88ca2717c0
+A = 8e57680f213d088ff1a1e7db3
+B = afebecc9943b0093f87022940
+M = b6201f68a45265d7e9183c3255feb4c110c05dadbcb13881bb
+
+ModMul = 143ae78a29
+A = 334abb952a
+B = 74203e7a50
+M = c9535a9505
+
+ModMul = 897a2b57e69f5a1469ea
+A = 1ec8ca0ea4fed52bdbbf
+B = 3a6273cab05e478a57b8
+M = dcb33163a8ea42c1ae6d
+
+ModMul = 4a2c10e90e2d37111db79a44d3e31b
+A = a90e7bbd63fc4af6de83029ee
+B = cf09c3dd50b41afc7045e057b
+M = 8ab85d47e4270116a64f97dc4f0f15
+
+ModMul = 70f94276c9d85fd3f71edfaad6051456f754da85
+A = fa3e9ff6e1aa1fb78e51711cb
+B = b115ed197c50b7ec4040ca255
+M = ad63f69ef1346e7549ba71c13b24b279f53bc9bd
+
+ModMul = 861e7ef401866f815b983ba18a612913ecc20a67016d79cfac
+A = fc41a9ce06e882942f751be7a
+B = 881c05a51d1ba8134d126a48e
+M = b12200b39526c33b70e8aa23ebc400dea0d4d8fe42be103d5f
+
+ModMul = 4e0051898a
+A = 2a06523f70
+B = 651b5044f0
+M = 9da4eb09b5
+
+ModMul = cc8274c88d6affc3742f
+A = 9ccf0133f9628532f4f6
+B = c1d80907057be7a67b01
+M = d6e76e362da831f32685
+
+ModMul = 568f15bed5c4405be9dd04673a9c46
+A = dd6029c3196feb6da7f0f4a48
+B = a5f6745f2cb64913d1d3236d8
+M = f62f02c9b9ca8993e3be9a02b444bf
+
+ModMul = a629452d5ed19df040eca26eaca37d82c0fb1d8f
+A = 963c51a9415b03e85ccb09f25
+B = b1cffe333afe44311cb968ffe
+M = ab2128698d498e8d75455033cfbbf4487535773f
+
+ModMul = 814030123025d287aaa8b826792999d72f2d589e0c7f7f3dbf
+A = c3b33f391e78bee97ceddf313
+B = a9136f3af450fdeb245eff425
+M = b6aa9c517eaecb70781e597b907583bbb569e970d229235a35
+
+ModMul = 8735bd486d
+A = 563e15c52a
+B = 31293264e1
+M = 92f4b193df
+
+ModMul = a541f69ca163b288dd0e
+A = a608b48c1dcaa18424b2
+B = 891b0b296e911068b00c
+M = d4140921f4b2c84f1eb1
+
+ModMul = adc1b7cf65967b013d046866b4ed9d
+A = e97941448f65060cf63ecd486
+B = ca68936f76cb87a8fbdd37311
+M = ebbca2482fb82eeca2866057cf1179
+
+ModMul = 44aa9f0dd58d4510a7364e130698b34eda23a632
+A = c11f83f01bb964ffac93a2e30
+B = e05ee40eea39f4538d735193d
+M = b5e8b511738979dc740a6a1f7291cf4561787be7
+
+ModMul = 8b16b82f064f471983c7154abc9f9ba355111bacb90400372a
+A = acff8da571e1c96810bf95707
+B = cdd23e5504cc26d0c34a62b06
+M = f38902a99190ae0b5ef26849a6e943d651925666fea271fee7
+
+ModMul = 193f453197
+A = 8cb3078675
+B = a8fb003a87
+M = b60ff22f4b
+
+ModMul = 849c26c8cf5cae426a80
+A = 5d1e3d2b4d038a0a34be
+B = 34f70325565bf0523314
+M = cbc189f9a732cad8f425
+
+ModMul = 9a4e64ff530c53a4c6c5b6b5021920
+A = f53b81723cf74f520a61e614e
+B = 9d8ac2e6b839143fdd079a2ff
+M = a115375435151798f3644bede9d863
+
+ModMul = aac303a4623e80158af1cb3331965cc8e3184edd
+A = cce0a88606ff962fdc37e72c9
+B = 9840a500a2051625c517104db
+M = b99dafdbd91ec3c05791031df5e193c03d6a441d
+
+ModMul = a31401dfa761bbe82b66b5f094151865b18a4ba75bb9b3dedf
+A = e6f48c027284856aaf3b96425
+B = b4c326f72a6a22fd4b93ba5b3
+M = e57d9608ac6e5b129b2c014958bfc59137f63838b1ba88a4ab
+
+ModMul = 8b0929adbf
+A = 61fdf77ac0
+B = 8892f05400
+M = f12b3766eb
+
+ModMul = 91b57f353307b173679d
+A = 33f8e73752072b4b5cfa
+B = b4c730f79f4f2c07945d
+M = d41be1d8d2e5753e3ae9
+
+ModMul = af04c564adfeb120bc4770bc8c650c
+A = af151333b3d4cd1d29fd801db
+B = 9ccaac44ff91be11b30bdcdd0
+M = e0bd6e70d5f5ce08fbbfd48d43101f
+
+ModMul = 1b8d623796a5065d9e993a53a9587a0fdbea1bbd
+A = a2fd08df2d4eab0cd6d29e213
+B = 92c9d26ae7c215b52199ee28b
+M = cd529f4cfa46f3bd3e7fadf167fdc02f6f881da3
+
+ModMul = 4a8573dd8dc50a4fa39f3579d3869745eb8c1153ca508deefd
+A = 855f941d085305725da617f5d
+B = 8f09b7d2c36e0340523da5421
+M = fd8caa05edeaa81beefa01957eed97a981ab34bdeb6d8c704b
+
+ModMul = 2d278e089
+A = 59d20a1716
+B = 8e2a58bc75
+M = b3d61ef699
+
+ModMul = 2f937ce359d0f6cedd1
+A = 1019d11d26040ffd5b1d
+B = 7cdb6252087423d43e08
+M = e8f537323004447e669f
+
+ModMul = 6567332e25af83089f7458786ab0ca
+A = bf9565e9f8a098894447b58fb
+B = fc867626f268c24cc0ab7bf8b
+M = 930f39183353363dcd822933a438ef
+
+ModMul = 3692e73ad1d91ddc19cad3808eba2c5fc88e2bf9
+A = d0a42ce512629f0ffd233a9aa
+B = 97f6d3c4c655c7353a62d6ac4
+M = eac2ea84851f880214b8f40f881a2e56a6ba6f2d
+
+ModMul = 81df390c9e51b30bd639db15adb464c7cb1d011cb5e260be58
+A = c237eb242c40960861c938c08
+B = ab2f481f0d768eebd90d2574b
+M = 8697d7a28a5f42c9a7b31949b8b568f861142f44fe66c6cd3f
+
+ModMul = c952f9aef
+A = 81973bbcb3
+B = 28ddee3bf7
+M = c4a40993c9
+
+ModMul = 241dd53d93f7bdbbb2ee
+A = 2136eda4495c45c9f96c
+B = e74c4baa8ca3f6b7cd5b
+M = fff4594e7a5f0a1d3e15
+
+ModMul = 5f861ed8b0aa835761613e6c869cfd
+A = bfc5c1572086079f5f5d18d1b
+B = 95902e14923c8010b7e905178
+M = a819c6c109d623f9b845aa23712c9b
+
+ModMul = 5b8ab089c4e4c6804e48a2bc1d218718b3a32598
+A = fbe65d3852224a812c432672a
+B = d57a3f38da966d2471d70a048
+M = b9e6a626d3ad026d14248fc90c882bedd64a1f13
+
+ModMul = 761438baf5b02dc095b7040e082da7b167c2b9ace956284ed
+A = fd91701ed2151f8e994bf4ee1
+B = 88b66e735b76972bccd9db182
+M = 8008b2d1274456aa68dc627b1ec3e1762c6ed2d660c64a1a55
+
+ModMul = cb743c97a1
+A = 9c69ca9b60
+B = 7488f48f5
+M = d67040ed0d
+
+ModMul = 931b2bee1bc30725a31
+A = 650f567b544ce02303d4
+B = 5858da30dd1fae88a675
+M = 91ce30234bb29fb9e833
+
+ModMul = 5b4f262cec958a20390b5e568ccdaf
+A = f7e240e8a077e8e87506db2f1
+B = f8653fe64e3bd414782f51634
+M = fdb8225eefc1620648737d31dfe1f7
+
+ModMul = 4c011d1ddfa30c901793cc6ce74db47584cebbd1
+A = eda8e9a9ea3cdae17bd50b1b4
+B = 992e8ef4a45593e4ceff67876
+M = 95e2f120cfcefbada1058af6c8853cbebedd5763
+
+ModMul = 6e99aa5b8107399848cf24fbd88ed6350efb68d737e505b466
+A = ca6c51ba2f410d09bf71d60fe
+B = 8bdfa8fe5ef3b2ad02bc63c4d
+M = 84daecf412b8c50ad6dfdb546c3eb783dcc6f32003eda914bb
+
+ModMul = 536175913582e73c1002083cb0cfce5471d4193a5b717881e60abfe927c829d
+A = 9b474b6f7d7f11dfbeb7a0724694f2daf9ccbaf2ec13269b5ae3329e8df95f7833baa68324509dcddfb5afa1d14f2dafc55e2c225475f16fb396beecc7a66dee
+B = d74a5081f00af2361c3537642c06cd47aae7e366741c9b4785e185af8b328acf3e2ed71e3b9a4b6fd49d956eef76740b3c6ec5850a90e7e444dfeaa7214c5eca
+M = 5efaeebe212752b28b5441a5d0b2600190504467c6359e9ab26320ee72cffcb
+
+ModMul = 6161cceee2b74e7965a926fdf5344ddf8cc41994d72154a8b6014c18cf71634
+A = e7d6b74a1af0834aaf93e09a6488340b661449ba2bbc73d775e7d828163813ddbcd82719351879a6d67ab6b518011e1db43a3d620d1f24403917691d15ed6f90
+B = 3ecc8fd3103fe52a7e73ec4be4e60b69584bd886a030f017b482bde9d4b0b964ba8471cb32b3e9bd49864d9028a22d6b6b46be0451bb4222c3987b74a509f8fc
+M = 7c3e3b8b1a6110da82674aaf88c288cef4cfddf22e7c9b75640fd67fa5fad59
+
+ModMul = 2acd55bdcccd55882eff0bb262bb62f78bff8e932aefc9d32f54d5d4e9b8bd76
+A = c221d1f0d1b7efe7e078dd01bed773f8876fa324b3fe91985d47d343e7f3878b457dae2f9ae68971245278a1d23cb541c56b94dd9ac43a9fbe28a46efc627651
+B = 49f94c19ff7ce990637c3d2019ed66f7e6dbb1442b04a4593cc480521b991cb1b878f8c31903240f89e34336d9e6785433617e729b71adcbef622a683357e035
+M = 43760c71742e9cf22cae6fc262c008b7f1b97a78c8063957b74aa4cd370c1eeb
+
+ModMul = 504c11e38284a30e3647c1ddfaed94503d833bcecdff05e749422ad1d9442540
+A = 3fbabe2d65f443e7db0a6f332330ecc4d1d40e14fcb510499552020405cafcf10a50a5ee47cf60fd8c22a22b3f753b4167c213851f32109babe4b5c298d6c4cf
+B = 62e5b0f887dcb1f1794bae7dad46a066f810cf5f82a1eea99207b5f0fb0ae9084c5e62cc97b2672b1cf4cc1400a19bdcb093c97404876b584a6482931e7ba9b7
+M = d79fab3eb31189268b2a0689cafdaa0826f07d432591e8aa8bd3c7cdce1470a7
+
+ModMul = 13a6431c57ddf0ed3979412ba8454a0dd9a2694a0dd76453aae63366c46e41db
+A = 7e1fd0bd9ab0aa75b264475604aea09f24239f94847ce2549d43b71890c0549938d167adebc7890d3c492b5874da7bf18d895ccaf1803b9776820598928b407c
+B = 5e54e5185bc86f16177f1354a57d36ac2980def141b389e4bfda134fae7c158009ccc61ef66281905128b6297f876662104ead2315024f129c56eaa387f80b4d
+M = 182572149b860615dd853f37f7d51a35e85f5e4a4249a60fde58dc68e0dd7401
+
+ModMul = 145a44566bd75103083b7556a822ea6008ed3a6a1bf135b68fcf87a294c09b4
+A = a195e4315caa8cc0707063c7359c28139d4dfffb57eb726156336e13227ad9766ea1fc99152893ebb194fecfc153d47cb927a633217328f05e4d8782aeb89d04
+B = a97ae97dc7e9a224cab94ecedc08d0cbf7a012dc5209b1e1e8b5b843fcf61e65db3457d6085545a633be47b742e8237cc716357ff5bce9b00e23671ec1d049a8
+M = 29b060ee2aef7e43e02163d279ce49259127198adf462d13aa195c7dccf573a1
+
+ModMul = b00740cef7791692d45f5a7110f3eeb260638f19f87c9245436fc0422de90658
+A = e6b97c11ad44fd451d168d65d1691d2220db8c3b6c8436d59f4c1366aac52558d0d6b61f5d6966460a4a31085fac711e5a09af5563d938963555d4730982eb0
+B = 6805eab5a4da534f07def6d2c320a6cbdfe4831fc2163dfcef740607b3181d8647bfae8f8c16237c1c1c5d14b9e3417132f81b3a7db4b7fc11927aab30dca590
+M = f975a94fa62b4c0e68df5c3ac5917d18927c0a6d9cf39c26f6ed97a81cedf227
+
+ModMul = dc04b6ba2eb1e34ea8942a50d1d0c5479dd22109895796ffdc9cd32b53d4764
+A = 7fd3310af09a67e0684dcd8e3b4b651c7c13c2f6a0a47b59a7f5cd8bd80854d1d4fe02eaa61843d6bb2b87f99d8ec4842864681eaf056538ffff610c231e1d
+B = 15f1661c59ee9f93400073e18a91503a93d47537d2da5cf5e4bc69ccc87b07bed171a95f1c5eaa9c7d7ab207ab3f1f7634c5d16e706969e869364207f61d84bf
+M = 22e2856f4c2b6c01448d4aef74aaaee3a14e9660b5b277200f2e67464ecadfab
+
+ModMul = 19299c9e960ce15087e9fbd66f95cafe82546431b92d70db1de87c3425c1bef2
+A = 8e3abb1f24e1f91496db99be9409f57f67cfb6e0e33d603a2a31e1309f1d0bbdc413c3e4fbb5e3d923f683afa9942b9b9fad6a6e558b2297889fff47ccef7d23
+B = dbdf5940dcd68127d476badbd5a2f3018aa4d8db79f81337ddfcb108637110b934e946d3284ec09d5255605ad72424f1894238ee4f7964dffc27fad838532321
+M = ab6b4e3d3909512f5d1d62a30c1ab8dd5e584cadbce9dffd12fe203f8936ee93
+
+ModMul = 4f88ad4e30e6e8e38cba0452d98d4a3547c680f16308692e33e5577772658764
+A = 5137697bf48982edd869e4a42f3cb858bf65ad5b25d1c0e8b75d054460d0944ecb5a6924721c5728964d84231c7ae808f556837aefb23fe3ad36aec9f5f60f20
+B = c79554304620f8116b9a8bb56f6a23620e9fd504f7163f732e1e6367d25c6ff98cb01d16faf3e018dec6a067d1204a6aa95470598ce757bcfbc3ab4f5d8ec88
+M = 9ba20dd78923d8ef82897ac46a509cf22c9b7986a4facf42e5416bfe3576a735
+
+ModMul = 985a4d2a7431e09fcad03e6a3f926582dbc0aedc588f17aa5db40c2d3566233
+A = 908bff40440aaeee6c90b6312dc017c3bdae884a9074e02b26f01be1f018390e01f0d111f99a06c16e20538df8000d4066cd4bb3628da88a3a5cc240cfac719f
+B = 6ebfe9fe53909876784f9d6e5dcca4cfa9463fbd8426c5bb8890ae84c2fad119615fe1e1f2ee5fa544a5ac713ed1da8c1e04f282f1f1b9fba4b4c4bd9db20538
+M = c66842e0a11ed6ad1e8f192ea97f5f244536cfc5234c7fdae1ff905123c72793
+
+ModMul = 133d7b31537b627da2c042217cd28625437c28c3e06258427d9a4384046a1f4
+A = afb695e3e40347f60a500e01fba4df1c1f2fd4ed79e3f65913d82369f79d80db6b3978e6351c70c148f572b9c0c2b1efeefa605251b3156d9b66d240467e550f
+B = 8855046dcf50f80f278227d5260b9be53ca2e4a1cfe1afce4d35b11d0fa17a36a8bee8126e13bbb318d476becad5a935e9d160fa481e1437b292bdc169dc7d45
+M = 3eae4f0d6c7e1fb9de1a4c160404a8767783c7f839fe27a543f5c389c679d47
+
+ModMul = 7f4576a315bad5c7fbb1616e8b26c5b34ca6f701b9b1adf0485fec181c41dee9
+A = bc2baf0153a4598f6b5f488c43b2546cadfaca2c1931b919f98ba71835a8fe78886da1fea25b194e60ed6f9e0ad23c988b64af9278155c1722dcf4983a1566c2
+B = d8374d91fd3c523ecdd6bdd265c9a8958dd222f9f0e25454fd683bd86d7900a273b56f1f47e033c46527e32c721094ce6bc927d25fac05d7fa6db4d7a6773c94
+M = 9975d8e7f2a4d9d1ff8d442b93ff269a83fee43a18bbfa8c2ccd7ca5fac3a8d3
+
+ModMul = 57ebfb39605d4fa6ef5fd03bd8e4fd685664297c29b7ad75a40b133e15fc5ae9
+A = efed8e442154b1eb6c75775cc23e01fa65c9c361e222da123d07daad3039f305e7102edff23b65c333f0caae4f7929857c3169f4ae47c9f0fd920c38eb42bf2f
+B = db05415ea90269a74b0919ff772c148c0eeb2ff9dea76a6e73e82eb86bc76fb42308b55ef83a769a91d23b7840d5d2f5129f15279dfab7cd8d63778acf202f26
+M = 7704390c4b1da86d51ff817003e5451d601a5352296e339e5da219ec5a330479
+
+ModMul = 40b6b0d44cf8a5ca7f4fd03dd6e1e2a11f74f3911dcd8727e57db8d65cd490d
+A = 6500f3cf686eec4e1f243616ac0ea8e8d11ddbade490b86baf231e7b2fd55968ee14b6bb7badf8c898874099831976af46bcbfbfaea10d49aa803c6e51238e2
+B = 1fac744fa1e26e789639e049679d0e2eb57336279f09555e10210e7143199a3df5fbf5294edc386ac762fa3a3b0b4bc28945adf21a8af747a29018bf76d3710a
+M = 5c0781a87b84ecb4362b09c623d511de53c085671dd4f08e9a551685b55ddfd1
+
+ModMul = 6b778ae9822221e6a8376379e0032d7edb14d7b5e32a7310897b54d1d5626113
+A = c4a5737a9496129a136753f8c2e52bbd2660f2d3fafe4ed702900b01c14e506d13e3bbeab19b357e5ba9fce8a4fc3dcc469406a16248d6fb53862781fd9d55e4
+B = 444e5a673eeb37fd3b4f6b6f5133b0f46c2ea532e1953da4a0e144407a8e2534c5ff40cc9af7756e5aff9df57d938fcedaffb868dcf4e458b36f506ed7fe0ce5
+M = 7f5978c0c066132a9bdcb00727bb802b72777b9e8e4265f76b80cfdc3a788817
+
+ModMul = 5c717e5dd25abe60f761d6f9326ed056416add4c1384682d87b7ff12e112f855
+A = 4351965a421c75c5b4c251861e53316a300ed7983e27e17f9308420f0d2cb11e9c476294fcd9042a525bc1a044bb442d1d9f853c9e07245170e0e2711010cd1c
+B = 4e1046647c362c8f9c414be54075b4e9d151c6fa0c3da40d90e6042625947ca2c9f20cfbcfdab8666dac5a15f6cda9d47b09f654131fc5addc07e382c9639323
+M = a6c789884c66c7f028099e0367b3ed86871277bf070c541ee12fc02fcb6181d7
+
+ModMul = 4452688244f542125168853f1d444f96ab0f82903bb12a97e59f0db633edfd6
+A = 9fd1cc81981bff977244c044146918057ad06d3cc26edfb8fb4118ee02b959d45555f9507ffeb23c3688e29ccdfe5f583fa3761f6727573542bee8ab5f5b600d
+B = 856e6a03b5c93fc19deea51b3bfe42c810c5bcf9ffbd08e2625eb209baf6a4e24943a3c090d89c1f70aea9f0128e511fe92e03715d917168c1e1ca77a3a8731f
+M = 2c245d407a78903ef2b279ddbe32106e6333b6f44cabf87b8641b047c79ea06b
+
+ModMul = 375f8474ee47df6b9a038512002e56cddd374d69c69719d8d369232c64a839e2
+A = add40f1dd6d4a2414b17f0c628eed9a8f082f3ad1f34ec41935fa86b34d4505b22ea80c062386a9ed63f95c67e55c686f837bddf8f4da791f98b08c02f32d4b2
+B = dab1caaa11d5a208b7a6b7a1d6482a4859daaba5e3a77b1b1020e8ae62a664953dfddd0b47d40526e7a3c6a5363c6d41dd9f529fd8b58d5d31bb67e745cb71b3
+M = 4f506313a4f49873a405f2e5a6e9cfae9cd5e9f67b5ef900153366570e28a955
+
+ModMul = 36fb0733a26902f0f8f11625305a3c94fcdfffe294eb6ccba110aa628a314df
+A = 52ee1498bd6a1677db801ae2eab4951345a1fcf8fe7d38e3f28dbc27fae508d87c9958e02a375ff4891b88ee916b96331e7cc082615faa028f6d541b5ce37876
+B = 9343cfa074f50c20e8472f8f7c4a7d330aa30ee417ed8027a4c956e84cc5cb31d5411c14796d9325fceef79a51b5d8a4c89182ca273ab633e6a7b22a27352300
+M = 9d7c334aa33634f9f313b71b42476a3b627a6c5bb8ac1d07a8d732d5c087bd9
+
+ModMul = 4a377267508eb045e00cea66a417112dac07545304bbeac6315625275b7cbfad
+A = 19616a82b75b08499d4b1f869df2db8f71398672f3f97ffc6177a4a5aa913605ce8a6ab5f778cac508f0b3f2aa680b01ccdc57c0fdd6cd678a2ff2dcd7f01f3c
+B = a5643a9a9fe3be4134082daae4ee7dfd85d9452beee856fd939d3be9788b6bebcf3571c67ec481ff9b20f70d23e82e2171b1d0ddf0a9435b40115d32aedb6811
+M = ea0477e7f1a02cb6c21171066f3dab69d4e24429043b0f049de660fc80e51937
+
+ModMul = 7952dfdb91252658430e365adeefd9093740de92cfc9dd3d92294f2dab6ca0b6
+A = 8e6cd7639b7c134b53e6ae6ac5f51268da83ed09e8e96d65e4bb130dcdbbab9e48226ddba6efe93faa510bde8ee92f2a641774c4272b5a2f88024b77a2cfa110
+B = fe4e8109a49b16b96871e384564cc096277dad4e1bbca8e5feb33f140a4fb800c8f3096b1bc7042bccf249aede88e6055c0db609f94e214b1251eda494be724b
+M = aa46853682af960824140c35d145a6dcff6283b2c59994b30ecf9b8def41a025
+
+ModMul = 1aacec7f7e66b0cf4eb2dfda9d8d3fbf4eb8e928cbbc967d13e3e38612f0346d
+A = b0fd7a936b0908ba6fa797e4b855d673ff85d665ef3a345e560e2c0049becf5c25b6c0068dd617ab47a8fd151939ea0631f86806ddd40e557933c0e880fcdd0b
+B = 105c87fe2b1bf0be5405ca0d530beda1780f0045e892d7810f8a8abbe890f0a19de66497cba55bf38e190c52992467c22a320c38a4bd167f774ed812f1271d5a
+M = ac4f0a2b22df691331ded955a5d0e7d1910d7920a59d4a87636b2635397b7335
+
+ModMul = 2c25d180156fa7d2fc20c9bd6d9ff0b111c9ad76ada0784e2f8fa0bd06413f66
+A = 2aa4a0a73df11f4e60956619d0b35eaef45730d619f9b920298e6d369b9861f6411de28a34af038f288d7a3d6a35b10c8082b8ad0fb275a8f67c6832ac46ba9
+B = fae1d50b72feb25da2581829409391bf289cd9f730c99d265b5b2d63889381cde4adbf85c3998c2478f2866526b8f64605d75765edd09b78ea45337207d173
+M = 65c9d79a09a820adbc9beb152bef387c1439147ed50cef872d36a69f1c7d5fe1
+
+ModMul = 56ec8624fc199e7b4e68358f88f1a99f1d4d02577b8c6f7e28e4ccfdd981f995
+A = b0a0f9d05d144d2ef257c1e63a7127a3b8e0d8b64ff8f6447618560593574b5c5da6258b274efc28da0defd988bef1efca0f481f809665a78954b36741d668bd
+B = 10901b9dbf0016cbcc671da75a75b7a6ec6a66dd17b53a97344864b08f037098537380bfb0137b6becfc36a75206686d16bc4eb8fd54299494374e3f383d9b10
+M = 73882376ca850c125ce9f20c291e550ee48f0eb0d571109ab08c22d6719496e9
+
+ModMul = acceebe131aa34ff21b3235f045bccc8a8f762dca20c1dd1ef6eb461ea971c6c
+A = a7714b249eb0f0cbe3e6fa0b04e895fcf14c404876197defafc6b57026ae7e5e993fc47c1819581adc03860ce07f2b7877a3f6d0912c0cbc659f5f6170a1cb2b
+B = b7278ecd154ef5243ad973ead291ea186acb63e09977e644a6a9fde195d1a33993fc47c1819581adc03860ce07f2b7877a3f6d0912c0cbc659f5f6170a1cb2b
+M = c52ae49e1a4b21ec392b76844ad559653b7b9f67a58b3bba6c2ce250017eab09
+
+ModMul = 62b5b04dc84bb4ee04934c03ef361bc6e59b42144dc117b9f7771525c67c3688
+A = 2b65f491caf0b5cd9c66c859fbcadaec7213e6b848884638791b1620d6e4bc9dde087af0e7329d3b15a45df2d43ebde61b053ad7f63917aa922d58b4f3222620
+B = c1bfcdb34b0766be980540dc3256b9ee4158310fad2c43cf24bfafca08ee185647043f5842a9d9eda224449259341b7c50998086434528d47661bf5762a7ab5f
+M = f73398c32191b436d14a0b76c6069b1d61395568753c832dd0c707780a232dc9
+
+ModMul = 5613c8fb0721bd3f605089def48fb2c38a4862bb387886c1edc1bc37d10f0e15
+A = a3d8b12a2c8f4021ca045a4e4903687dea63ee7e88893b1911aea77efbff00f8f5c7884cbafc71f59fa2636195c2ebee61edbf642923f34d87ba5eb49b06a7ee
+B = 3231829c81b26dcac432b502ce22e126ab564922b1e9818cd3da46edc5ce7df026d0e515809c97bcfdb9666581efbfd364437ba9959dfad099f90472f97c69ec
+M = df8344fa848d1066afe4f8d985cff65441751677dcf3a4e99b40365fc3c978e9
+
+ModMul = 30325f7ccbc2c69e11d739ad7132a947c53377aa902ec70b152f3a75e050c244
+A = e4ba620125f58a63fe12fbd3eccdea477d56b120c76d5d1421bebd74e8686b4093f8169070453ccc04b63b173568385313a1d9c841a4aa82a61cb84d4286a941
+B = e87aaa990307855f8e5f2e5509d2ce31dd4b13bb7199cf5fa0593e350326e222efc33a26c69245565d6ebb5a484cfef7d2558f22dea8054d07831d536803d0dd
+M = 43d57108eb0ab9bebaa8ce137628ea825951c6accb9acb7f1e991c93b8563897
+
+ModMul = 1975db7b72434ad32c9aee412645f6670b7f4af1f8a424a5031c559d3e18dce6
+A = bd64b1db27fa7da4c92a4ee092f58a2a53ed0f12d009fe13b36d5fd585defe778fafea4a60e8fe567d03e9ba3b72b189e22504ae8ca6aad7c2ac0f44abca2f6
+B = b487d8116198560d6c5b08c7ce63b0acc0c98e6f2a8d709cf4e3a409edd55f64d72fc27a70dc341e280ff5a1b09fe131773d466cb31991d2db23a2a86d225c80
+M = 39d57af763eabe569dac1a103e169e6e3b4375168e41e5c3b961b6e743915923
+
+ModMul = 3bbb5bde9e3e240694326571360090e1fc0a4ea7b2311c1e0bd3961f6c159385
+A = 4181ee3bf9a98bcd49eaea243a179cddbf160981efc720685c7be1dfeb5aa552685a2cd46f340e1e1da893b3b460692fa2eaf6c100f24a14f239e45123242d53
+B = 77cd04d86dd5da322af78be54246dd6b7af490d903db1db03cbccde535570b81c6053a84110c07f097540ffe7510320024b7bafb77e9e239761def76092e1d59
+M = f3b9833a303eb540cf8b6cbc3cf16394b1634ef517be57684e42d364d8bec3e5
+
+ModMul = 2d8174211f0367233b3a8df7c5bf0066d6aa792be7cdc5e850a477454d5c829f
+A = 1c08cec52d96136fbd9078b7b8db36ab63b86e19dd3dba7b2e3190ff566180e89dfee9423fa4e99be2187eda6aedfa86b9a45eb1e4655257315ae6a280f0a6ee
+B = a8b4bc9647d8df9b7c76cc6d0f2248cdbc41f5da9c061f9864aa8415c9557582cada456cf23cc32d47d1fc1caf19d36b398019aac4734e10f55ce3cad419e5e7
+M = 7eacffe21f88413af94155a2a8e37f70a431a59653738afda04a1bec72d0d9ed
+
+# Regression tests for CVE-2016-7055.
+
+ModMul = ccd6f75b5f24b7c5ce2ce755fa89c2450c6a7d96ce8c8791e659eab84577a7695e3b2caa7c980fb23f60634233e9798499c28b0338c1f1a326d0ca89fd41f2fd88b759f317889832966b551a950043ec7a4b6152d3e2cbfb40e88458e70ab783b96f12d271f828d5b39e198ccaf8665411d85026282dbead5d24cd01b6c8a8e9
+A = 7878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878
+B = 095d72c08c097ba488c5e439c655a192eafb6380073d8c2664668eddb4060744e16e57fb4edb9ae10a0cefcdc28a894f689a128379db279d48a2e20849d685939b7803bcf46cebf5c533fb0dd35b080593de5472e3fe5db951b8bff9b4cb8f039cc638a5ee8cdd703719f8000e6a9f63beed5f2fcd52ff293ea05a251bb4ab81
+M = d78af684e71db0c39cff4e64fb9db567132cb9c50cc98009feb820b26f2ded9b91b9b5e2b83ae0ae4eb4e0523ca726bfbe969b89fd754f674ce99118c3f2d1c5d81fdc7c54e02b60262b241d53c040e99e45826eca37a804668e690e1afc1ca42c9a15d84d4954425f0b7642fc0bd9d7b24e2618d2dcc9b729d944badacfddaf
+
+ModMul = ccd6f75b5f24b7c5ce2ce755fa89c2450c6a7d96ce8c8791e659eab84577a7695e3b2caa7c980fb23f60634233e9798499c28b0338c1f1a326d0ca89fd41f2fd88b759f317889832966b551a950043ec7a4b6152d3e2cbfb40e88458e70ab783b96f12d271f828d5b39e198ccaf8665411d85026282dbead5d24cd01b6c8a8e9
+A = 095d72c08c097ba488c5e439c655a192eafb6380073d8c2664668eddb4060744e16e57fb4edb9ae10a0cefcdc28a894f689a128379db279d48a2e20849d685939b7803bcf46cebf5c533fb0dd35b080593de5472e3fe5db951b8bff9b4cb8f039cc638a5ee8cdd703719f8000e6a9f63beed5f2fcd52ff293ea05a251bb4ab81
+B = 7878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878787878
+M = d78af684e71db0c39cff4e64fb9db567132cb9c50cc98009feb820b26f2ded9b91b9b5e2b83ae0ae4eb4e0523ca726bfbe969b89fd754f674ce99118c3f2d1c5d81fdc7c54e02b60262b241d53c040e99e45826eca37a804668e690e1afc1ca42c9a15d84d4954425f0b7642fc0bd9d7b24e2618d2dcc9b729d944badacfddaf
+
+
+# ModSquare tests.
+#
+# These test vectors satisfy A * A = ModSquare (mod M) and 0 <= ModSquare < M.
+
+# Regression test for CVE-2017-3732.
+ModSquare = fffffffdfffffd01000009000002f6fffdf403000312000402f3fff5f602fe080a0005fdfafffa00010001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000002000002fefffff7fffffd07000109fdfffef3fffdfd06000405ff00fdfbfffe00010001
+A = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000ffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff00000000
+M = ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000ffffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff
+
+
+# ModExp tests.
+#
+# These test vectors satisfy A ^ E = ModExp (mod M) and 0 <= ModExp < M.
+
+ModExp = 00
+A = -01
+E = 01
+M = 01
+
+ModExp = 01
+A = -02
+E = 01
+M = 03
+
+ModExp = 01
+A = -01
+E = 02
+M = 03
+
+ModExp = 01
+A = -02
+E = 02
+M = 03
+
+ModExp = 00
+A = -03
+E = 02
+M = 03
+
+ModExp = 02
+A = -04
+E = 01
+M = 03
+
+ModExp = 01
+A = -04
+E = 02
+M = 03
+
+# Regression test for carry propagation bug in sqr8x_reduction.
+ModExp = 19324b647d967d644b3219
+A = 050505050505
+E = 02
+M = 414141414141414141414127414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001
+
+ModExp = 208f8aa0
+A = 86b49
+E = 2
+M = 30d26ecb
+
+ModExp = 27308229
+A = 17591bb
+E = 6
+M = 30d26ecb
+
+ModExp = 2bdf498f
+A = 21292626
+E = d
+M = 30d26ecb
+
+ModExp = 11317167
+A = 4a655df24
+E = 10
+M = 30d26ecb
+
+ModExp = 2e1b88e
+A = da6b761a86
+E = 35
+M = 30d26ecb
+
+ModExp = 20a12ec3
+A = ea811
+E = 2
+M = 23bc042f
+
+ModExp = c42ced
+A = 1011a6a
+E = 4
+M = 23bc042f
+
+ModExp = 4637d79
+A = 28d9a601
+E = 8
+M = 23bc042f
+
+ModExp = 20e5669b
+A = 72fe6bc20
+E = 11
+M = 23bc042f
+
+ModExp = 142ab9e3
+A = 9a07b9363c
+E = 29
+M = 23bc042f
+
+ModExp = 14c64646
+A = 822df
+E = 3
+M = 30915765
+
+ModExp = 160e35a2
+A = 15ea542
+E = 5
+M = 30915765
+
+ModExp = 2f23a488
+A = 34d2e02e
+E = e
+M = 30915765
+
+ModExp = 28e67f93
+A = 636a32703
+E = 14
+M = 30915765
+
+ModExp = 29bfeaa5
+A = c8646998e6
+E = 2c
+M = 30915765
+
+ModExp = 30959e22
+A = 81dad
+E = 3
+M = 326dd68d
+
+ModExp = 1a1da4fa
+A = 116adb9
+E = 5
+M = 326dd68d
+
+ModExp = 272bf0d8
+A = 2d21ef08
+E = 8
+M = 326dd68d
+
+ModExp = 29f5054b
+A = 76989850a
+E = 16
+M = 326dd68d
+
+ModExp = e6c7b77
+A = b88ee70d2a
+E = 3e
+M = 326dd68d
+
+ModExp = 369605e1
+A = cf26f
+E = 2
+M = 3ce082eb
+
+ModExp = 168a3c5d
+A = 1f82caf
+E = 5
+M = 3ce082eb
+
+ModExp = 125c4bb8
+A = 2e9c4c07
+E = 9
+M = 3ce082eb
+
+ModExp = 1c5fe761
+A = 523ab37f1
+E = 14
+M = 3ce082eb
+
+ModExp = 21703009
+A = dc832165e8
+E = 20
+M = 3ce082eb
+
+ModExp = 1228d1e
+A = a5555
+E = 3
+M = 24665b27
+
+ModExp = 5226af4
+A = 1077bd6
+E = 4
+M = 24665b27
+
+ModExp = 1b14eac1
+A = 2db3a834
+E = f
+M = 24665b27
+
+ModExp = 161727bc
+A = 6bd962cb6
+E = 19
+M = 24665b27
+
+ModExp = 10d61d0d
+A = c10caed407
+E = 28
+M = 24665b27
+
+ModExp = 233da406
+A = b125f
+E = 3
+M = 33509981
+
+ModExp = 24032799
+A = 1656b7c
+E = 6
+M = 33509981
+
+ModExp = 129ecebe
+A = 2e671504
+E = a
+M = 33509981
+
+ModExp = 20c20bac
+A = 4d7a2de44
+E = 1f
+M = 33509981
+
+ModExp = 2e3ce9d3
+A = c53b3def4d
+E = 31
+M = 33509981
+
+ModExp = 12fadfd6
+A = b4cf8
+E = 2
+M = 36e9d4ae
+
+ModExp = 457ac85
+A = 1b1c7e9
+E = 7
+M = 36e9d4ae
+
+ModExp = 31debef4
+A = 3a973028
+E = d
+M = 36e9d4ae
+
+ModExp = 2333ad93
+A = 552b97c45
+E = 11
+M = 36e9d4ae
+
+ModExp = 99ba1fb
+A = 8bfb949cbb
+E = 28
+M = 36e9d4ae
+
+ModExp = 27b691de
+A = 93492
+E = 3
+M = 298fdb16
+
+ModExp = 3c2b70f
+A = 14e7b0d
+E = 4
+M = 298fdb16
+
+ModExp = 1486cda7
+A = 29acff81
+E = c
+M = 298fdb16
+
+ModExp = 11725275
+A = 507489205
+E = 13
+M = 298fdb16
+
+ModExp = 24d14627
+A = e71c55606d
+E = 35
+M = 298fdb16
+
+ModExp = 222b8d14
+A = 9b1a0
+E = 3
+M = 3db59d12
+
+ModExp = 3b8bd47d
+A = 13f4e8d
+E = 7
+M = 3db59d12
+
+ModExp = 17e72356
+A = 334774ce
+E = a
+M = 3db59d12
+
+ModExp = 306447ca
+A = 47079ddd2
+E = 12
+M = 3db59d12
+
+ModExp = 90bef3b
+A = a75d62616d
+E = 37
+M = 3db59d12
+
+ModExp = 1
+A = cddd44f47e84b3276cc36a5c0d742cc703e61c4756168601fbb1b6eb598c161019562344dd56ab6f603d920a12c360b285e6496a3605a2f8d691c3598233ee9366b5f2692554893bdeb67b7bdaf35ab7273ac593145e26bed82c70ba5793bf4bc5cac4c80b01785d1496beede493806e4f4aa89fd8d41de80dd6d0a3e2742678
+E = 0
+M = c95943186c7567fe8cd1bb4f07e7c659475fd9f38217571af20dfe7e4666d86286bc5b2bb013197f9b1c452c69a95bb7e450cf6e45d46e452282d5d2826978e06c52c7ca204869e8d1b1fac4911e3aef92c7b2d7551ebd8c6fe0365fad49e275cc2949a124385cadc4ace24671c4fe86a849de07c6fafacb312f55e9f3c79dcb
+
+ModExp = 0
+A = 0
+E = 8de689aef79eba6b20d7debb8d146541348df2f259dff6c3bfabf5517c8caf0473866a03ddbd03fc354bb00beda35e67f342d684896bf8dbb79238a6929692b1a87f58a2dcba596fe1a0514e3019baffe1b580fc810bd9774c00ab0f37af78619b30f273e3bfb95daac34e74566f84bb8809be7650dec75a20be61b4f904ed4e
+M = c95943186c7567fe8cd1bb4f07e7c659475fd9f38217571af20dfe7e4666d86286bc5b2bb013197f9b1c452c69a95bb7e450cf6e45d46e452282d5d2826978e06c52c7ca204869e8d1b1fac4911e3aef92c7b2d7551ebd8c6fe0365fad49e275cc2949a124385cadc4ace24671c4fe86a849de07c6fafacb312f55e9f3c79dcb
+
+ModExp = 5150fb769d5c5d341aaf56639a7bcc77c415fe46439938a2190283409692f29cd080bfe3433005d98d24718a03a3553c8560c5e9c8ed0f53b8945eb18290e1c1a83d919302510f66dd89b58acc2de79ad54b8a30d3e1019d4d222556beefca0821b094ecf104b5e4cfce69d2d520d2abf54f3e393d25ed3d27e8c2e3ca2e5ff9
+A = ead8c5a451541c50cab74de530c89376d9a55c723e0cac3c84b25f0093c08a2961e49ab48966361c42c9f99111587252d98395b76788400d75c66ef208ea2767a28d6f8dc3a859f39c95765d57f139e7fc14f47c908c62df051e7216d379f52028843b4d82ef49133cce8fe671ae179423ac8da5be43b01caaf425cd969300cd
+E = 8de689aef79eba6b20d7debb8d146541348df2f259dff6c3bfabf5517c8caf0473866a03ddbd03fc354bb00beda35e67f342d684896bf8dbb79238a6929692b1a87f58a2dcba596fe1a0514e3019baffe1b580fc810bd9774c00ab0f37af78619b30f273e3bfb95daac34e74566f84bb8809be7650dec75a20be61b4f904ed4e
+M = c95943186c7567fe8cd1bb4f07e7c659475fd9f38217571af20dfe7e4666d86286bc5b2bb013197f9b1c452c69a95bb7e450cf6e45d46e452282d5d2826978e06c52c7ca204869e8d1b1fac4911e3aef92c7b2d7551ebd8c6fe0365fad49e275cc2949a124385cadc4ace24671c4fe86a849de07c6fafacb312f55e9f3c79dcb
+
+ModExp = 1
+A = 935561297d1d90255aef891e2e30aa09935409de3d4a5abc340ac9a9b7dce33e9f5ce407f3a67ec30e0dc30481070823f8542463e46828d9cafb672a506d6753688cbad3d2761079f770c726c0b957071a30876c4d448e884b647833befbcd6b582787bf769d63cf55e68c7b869a0b86374f8920516cf5d528f348b6057450a1
+E = 0
+M = dcc24236a1bb94c71d9ec162a6aa4697b932717e82b667cad08b6bd1bbcbddf7cd167b7458de2b0b780486b39574e749d6405f9ede774a021d6b547271523e9e84a6fdd3a98315607ccf93356f54daa9c75e1e311e1672d0dc163be13f9ed6762f7dd301f5b0a1bb2398b608f40ac357ae34fc8a87d4fef3b961cbdb806d9061
+
+ModExp = 0
+A = 0
+E = bb552be12c02ae8b9e90c8beb5689ffefe3378d2c30f12a6d14496250ecce30317c642857535a741642c3df689a8d71a276d247ed482b07b50135357da6143ac2f5c74f6c739c5ff6ada21e1ab35439f6445a1019d6b607950bffb0357c6009a2bfc88cd7f4f883dc591d4eb45b1d787e85aba5c10ee4fe05ea47bf556aec94d
+M = dcc24236a1bb94c71d9ec162a6aa4697b932717e82b667cad08b6bd1bbcbddf7cd167b7458de2b0b780486b39574e749d6405f9ede774a021d6b547271523e9e84a6fdd3a98315607ccf93356f54daa9c75e1e311e1672d0dc163be13f9ed6762f7dd301f5b0a1bb2398b608f40ac357ae34fc8a87d4fef3b961cbdb806d9061
+
+ModExp = bbad67352704a6321809f742826bf3d1c31c0ad057bf81432abeb30dc9913c896c03e69eb1cde6b78ffcb320c4625bd38ef23a08d6c64dc86aec951b72d74b097e209ce63092959894614e3865a6153ec0ff6fda639e44071a33763f6b18edc1c22094c3f844f04a86d414c4cb618e9812991c61289360c7ba60f190f75038d0
+A = 855144760f2be2f2038d8ff628f03a902ae2e07736f2695ec980f84a1781665ab65e2b4e53d31856f431a32fd58d8a7727acee54cc54a62161b035c0293714ca294e2161ea4a48660bf084b885f504ad23ea338030460310bd19186be9030ab5136f09fe6a9223962bce385aaaf9c39fe6ed6d005fa96163fe15cdfa08fc914d
+E = bb552be12c02ae8b9e90c8beb5689ffefe3378d2c30f12a6d14496250ecce30317c642857535a741642c3df689a8d71a276d247ed482b07b50135357da6143ac2f5c74f6c739c5ff6ada21e1ab35439f6445a1019d6b607950bffb0357c6009a2bfc88cd7f4f883dc591d4eb45b1d787e85aba5c10ee4fe05ea47bf556aec94d
+M = dcc24236a1bb94c71d9ec162a6aa4697b932717e82b667cad08b6bd1bbcbddf7cd167b7458de2b0b780486b39574e749d6405f9ede774a021d6b547271523e9e84a6fdd3a98315607ccf93356f54daa9c75e1e311e1672d0dc163be13f9ed6762f7dd301f5b0a1bb2398b608f40ac357ae34fc8a87d4fef3b961cbdb806d9061
+
+ModExp = 1
+A = 9d92629c1ab181c50c31619e8acd0d235a1f5fc7a0bef4d4fd54b4f1968d45921f8522efe88e69c6c14c576c564592b9feb00d1554b88b038934eaf4a8ce81a2582732387490181ef158360c8b2d9ccb326ffe043f776a50cb8202837f08ca743b562eefa007150ab7012c341b16248478d4775c02ad71ea13d5e82b71e2d600
+E = 0
+M = cd607549668469b792f495c141e500871880b0611c8004293a561ec7f9ab6561f8a9b90872742386adafb5cd1890e8204ae12aec529cca0a9e382c96439137f09de9973b12c8492c62847e107deabb7dd946ffbb9d0ac73b462c481092bd65326a17f21d8d6527c47a5dba50aaa20c7048b8788a49eb3ea5f29bd5cfce24eb3b
+
+ModExp = 0
+A = 0
+E = 9f43dcb641f3ecf4dbc97450f2bdf3b7ec6a2f3e8e96bb1df2bf34b8d2d78e1a9018d04d960ffd0e932cfc60d3b9b923e3f9f29b3f3d61cae3a9f7245078143475c7fcb896ff200f7d94c4f2708bb42750e37c185a31c876814e4f06a00771707654e1da2fb69c16b6500b16385e3b933e2276ad3569977473f699b1c7926c3b
+M = cd607549668469b792f495c141e500871880b0611c8004293a561ec7f9ab6561f8a9b90872742386adafb5cd1890e8204ae12aec529cca0a9e382c96439137f09de9973b12c8492c62847e107deabb7dd946ffbb9d0ac73b462c481092bd65326a17f21d8d6527c47a5dba50aaa20c7048b8788a49eb3ea5f29bd5cfce24eb3b
+
+ModExp = 24eaead5b57883c2f454928f8edd470a344bfe07a953194f7d635d705ef13ddfc64140c8ad6f363d4c828e7c7891a6b6d4df37335de4552c319dafd1c06d1f743240082a3535df4da1475d3eea3fead20e40815fd5a0876c881c162ab65a1eda494280c258901ca953d1d039a998bf0e9aa09273bbef4865f3054663b72d75ff
+A = a31618b4532f53729ba22efb2221432fab1dbb70853d6a1159b42fd19fc949965c709b209de106a652aa422d88922ce51dae47f7f6deaf0055202e13db79ee84fc3d3c6f4c003ef96597c49d6895fa53c22ac9e4819f7048146b5272f6279424fdb389819a0b251c823c76f4bebf4f1246de455aafe82a0d34454f5039e90839
+E = 9f43dcb641f3ecf4dbc97450f2bdf3b7ec6a2f3e8e96bb1df2bf34b8d2d78e1a9018d04d960ffd0e932cfc60d3b9b923e3f9f29b3f3d61cae3a9f7245078143475c7fcb896ff200f7d94c4f2708bb42750e37c185a31c876814e4f06a00771707654e1da2fb69c16b6500b16385e3b933e2276ad3569977473f699b1c7926c3b
+M = cd607549668469b792f495c141e500871880b0611c8004293a561ec7f9ab6561f8a9b90872742386adafb5cd1890e8204ae12aec529cca0a9e382c96439137f09de9973b12c8492c62847e107deabb7dd946ffbb9d0ac73b462c481092bd65326a17f21d8d6527c47a5dba50aaa20c7048b8788a49eb3ea5f29bd5cfce24eb3b
+
+ModExp = 1
+A = a8558e7f455b27c0c46d7d0862eb409cdefbeca945e0284b5bf425b7ac0f3d316bc365594cc1639decffc621214d61479bc75135120d4ac09ea8b742ad7ec1822091b62b1c6f564fe5e2f4f5b7def92cbaaa9a898549207ab01b91c2324fbd306a87f7d6379b6fb6493c5fca76729767f136120da9c90bdc7d364f7d242d5acc
+E = 0
+M = 88f3c87ac5e3272a21b8a858da640d6939fb8113a95412c38663a0f352686d69a5d7927e60b484b9fcb8ef12978fe25ff2ebc9b61c5450e04222ef20ba3cbbdc5ec45581ce0f58e10be7bb9de7fa08752303a7a1db23b2ac9c6692ec63bf09ecd6639e06c5491ba568ea886620d71da32d329615f0e1443a75d09ae35b8a2d7f
+
+ModExp = 0
+A = 0
+E = a5524b41dfc6b570df1d8f6633ac7777c1131abe3a99c6166b0d29d3b8883c41b00a0c53cdd6f42820bf05c810b6ec53e77a8c1b9344ea0c91d4f410a2f204c369f3db33bf8c88217fc2cf802a9d9bce8119242d8e781875b85431be170076498c0963574ee423551aec9557e2fc672ab1ab5d0cbb1c400535df9481e7934d8f
+M = 88f3c87ac5e3272a21b8a858da640d6939fb8113a95412c38663a0f352686d69a5d7927e60b484b9fcb8ef12978fe25ff2ebc9b61c5450e04222ef20ba3cbbdc5ec45581ce0f58e10be7bb9de7fa08752303a7a1db23b2ac9c6692ec63bf09ecd6639e06c5491ba568ea886620d71da32d329615f0e1443a75d09ae35b8a2d7f
+
+ModExp = 292f0b39ca0f1c850b1a00cffd2d54924fcd5fc7e7504c9d593e6c0ff74760b1f4bdd81679fe06c50248336f3108c593fa111072ee87d0fcc89a63243a1dc89044503663eee9bc18f51c3e0193d9108303e12ac90ff78f6ec752a4386af09c42db524a7cbe9a3d4fcccd56c34d283bcc9debc17158b5fe8df0c1888a9841bf8f
+A = b4fde2908745ff92cc5826a27dcfdda09e8fffee681844fa4c7f1354d946d5d84e0e0c7a4a4cb20943d9c73dd707ca47d796945d6f6b55933b615e2c522f5dfc33e0652917b4809bab86f4fa56b32b746c177764895492d0a6a699812b2827fe701d40ef7effd78ea8efe1cac15ff74a295a09614bf04cae1a5017872ba22efe
+E = a5524b41dfc6b570df1d8f6633ac7777c1131abe3a99c6166b0d29d3b8883c41b00a0c53cdd6f42820bf05c810b6ec53e77a8c1b9344ea0c91d4f410a2f204c369f3db33bf8c88217fc2cf802a9d9bce8119242d8e781875b85431be170076498c0963574ee423551aec9557e2fc672ab1ab5d0cbb1c400535df9481e7934d8f
+M = 88f3c87ac5e3272a21b8a858da640d6939fb8113a95412c38663a0f352686d69a5d7927e60b484b9fcb8ef12978fe25ff2ebc9b61c5450e04222ef20ba3cbbdc5ec45581ce0f58e10be7bb9de7fa08752303a7a1db23b2ac9c6692ec63bf09ecd6639e06c5491ba568ea886620d71da32d329615f0e1443a75d09ae35b8a2d7f
+
+ModExp = 1
+A = e2845c572b46496ac158a731f612fd40ef626fa7134755c25b1b7614f4d7b29164e6142ddb7985e4c7ebc575855ff901e95927fe98a5aea2ad3a4720c75782323bea1518b2c57790f44efd9411be4e95b3896bad1e73c59658290b309e5a7eb5ef8be08125063e57336b80f17eacee88966d12bbaaa15a25929c82e027cf696f
+E = 0
+M = cf0dee80177869a532f0c6c3a0bda3aad79bdb6b70b6c227b32d75c26e394a90c1f2a6c2bb841ba9f6556b15654a79d8b1dd0c90709a093497bf40be0807cdbb378a74de5893c25067224d3ea8d37387ed6c4a981138853cb89caa9ce6cd0f6a1e95de24d558e90960f93844db4d01e372650350d45a9d34a36042b4d4b9e78d
+
+ModExp = 0
+A = 0
+E = a55703a72ca3f6074b939ed3d748196a684a3c8e411c2b39a9beb98993b6eb7ea3fa16f41bc5b5c3710b91c0fc74a8072793052f872f61695db3a2df872eaa427a110f1a8d568c85d58bd350d0df8eced7a10be80f7567360c1a8047b9c44aa2967cd0d9dd2caea2c1492358c2db4f0214da343fdf2e34272865dc5c63be2ae4
+M = cf0dee80177869a532f0c6c3a0bda3aad79bdb6b70b6c227b32d75c26e394a90c1f2a6c2bb841ba9f6556b15654a79d8b1dd0c90709a093497bf40be0807cdbb378a74de5893c25067224d3ea8d37387ed6c4a981138853cb89caa9ce6cd0f6a1e95de24d558e90960f93844db4d01e372650350d45a9d34a36042b4d4b9e78d
+
+ModExp = c90e4c69df92e26549b016950b59080947f5403430698e128477782480dd70be96bed2b9042dd8c708eb432e02710555b97af11ce6fa9b53395022851c32d1f53f04237fb0763563b440ca6e81a50d909d907d9c26b7d3c420dbf88f7dadd488666848135f8cdc608dcfb0691989289fb54379c2e84c262f9765f68c012ca1b9
+A = 882ea1b9b6c79a3b1bdfd284658cb6227ad825e0178cab713c7413c2ec34f03cfaec470c4f5c521f5e9899a2123878ff0f5b36a4196c08ad1b04d03746c4bfb5d126f5eefbfe172627d6732710a8ac8890cedbd4fdef69a19f2b3253a5aa0e5dd5484f72d59b17bdd1dad3db209a3ab839368ed3975069685911d7b35e41a9e6
+E = a55703a72ca3f6074b939ed3d748196a684a3c8e411c2b39a9beb98993b6eb7ea3fa16f41bc5b5c3710b91c0fc74a8072793052f872f61695db3a2df872eaa427a110f1a8d568c85d58bd350d0df8eced7a10be80f7567360c1a8047b9c44aa2967cd0d9dd2caea2c1492358c2db4f0214da343fdf2e34272865dc5c63be2ae4
+M = cf0dee80177869a532f0c6c3a0bda3aad79bdb6b70b6c227b32d75c26e394a90c1f2a6c2bb841ba9f6556b15654a79d8b1dd0c90709a093497bf40be0807cdbb378a74de5893c25067224d3ea8d37387ed6c4a981138853cb89caa9ce6cd0f6a1e95de24d558e90960f93844db4d01e372650350d45a9d34a36042b4d4b9e78d
+
+ModExp = 1
+A = d7a99e65b8af86b1c51d851f0447e43cd4f343cb0ada7236283e69aa7ebd383826acc9809e5dbc4002d0f2430022cb026458189db3805ce2de1142a31ba71a6c064ab51f0059eb4b931b8bcbaef023c38d57aa5f3e14f5df77e547fc028702071b58bd57338be1e1e4f98d3553484e4de359cefa29c5f58d3fa5d823f389dbef
+E = 0
+M = 8315dacf124bd473c578946347e83d1b20c750a7d9533d6215591be40bc78bcca77821f8c8f95375bbd6372515ada63d22bed2fa49bd6fabb0040c538d08db25b09d2fda02a93ab086cd1c27df93c37ee9c6a0527d089179b8f92b5dc3acf5ef1c75906fb80b03f5c2442a7a4088640f66376575ecfa4c697c1a571397ee5a0d
+
+ModExp = 0
+A = 0
+E = 95793fe33696f53e37498b2b65aaf27079e27acf1da97dda2c3e0803e8a02139f574e04ee03f7d1ddd029f528e3f3644515ad6f10f0beac2767f23d9cd8a8b9b6c6e376e36b64a0ae2711d7d31a5a75011641935b503110edbefe9f0ff2da27b5c5f6bb8cc151fdc86f67191bb99160c6cacc86ca368d5bdfafd3f3ff5161b1e
+M = 8315dacf124bd473c578946347e83d1b20c750a7d9533d6215591be40bc78bcca77821f8c8f95375bbd6372515ada63d22bed2fa49bd6fabb0040c538d08db25b09d2fda02a93ab086cd1c27df93c37ee9c6a0527d089179b8f92b5dc3acf5ef1c75906fb80b03f5c2442a7a4088640f66376575ecfa4c697c1a571397ee5a0d
+
+ModExp = 186c50ae259aa0fd31859cbcfea534e626a254de33956d5d719334bb32e7cf37cf199a21f079a5b90497228994d05efe19ccd8c769cd81f896286e8ae557cacd1630a928c629ecdfece29ab3697794aa707734e007318fa7029b050bb09ebbe6986187c6ca843f55266d275620b3f0fec0ad5f847ce8b314d929d128b33a249e
+A = 9d5e345793faddca9867f23eeddf6816c1e837f7a2cf96fa077212514acb6be87ac01a237d8f2f1d07d27a8ddd1b0ae0d97e1bda4f205a89435017284cdedea3e407b1b940d6f52112b6359b3e86e4c83074b17c210ae2c8856b42b169b4a7a6dfa65b368a7959496cf9bb1ee93d019dbd79101830e3f5ed08604ab90890b914
+E = 95793fe33696f53e37498b2b65aaf27079e27acf1da97dda2c3e0803e8a02139f574e04ee03f7d1ddd029f528e3f3644515ad6f10f0beac2767f23d9cd8a8b9b6c6e376e36b64a0ae2711d7d31a5a75011641935b503110edbefe9f0ff2da27b5c5f6bb8cc151fdc86f67191bb99160c6cacc86ca368d5bdfafd3f3ff5161b1e
+M = 8315dacf124bd473c578946347e83d1b20c750a7d9533d6215591be40bc78bcca77821f8c8f95375bbd6372515ada63d22bed2fa49bd6fabb0040c538d08db25b09d2fda02a93ab086cd1c27df93c37ee9c6a0527d089179b8f92b5dc3acf5ef1c75906fb80b03f5c2442a7a4088640f66376575ecfa4c697c1a571397ee5a0d
+
+ModExp = 1
+A = e6a079bdf7b0638d50b183475e9ddfd5cbdebfb29f5fae8e9be402a0bd36085737b556492ea7fb4b1000ae9ce59db66098129b757cfb29224275fdaa46b8b7eb18a93ca7d3e446dc38c734b683d7ba7927b008d993aab01f44239d3c76be76d1503908e9b5e73b36c43ae0771368b01f39c042693bd92c4fc50810f059e1b332
+E = 0
+M = 81dd561d5d5327fc5ed7c9236b5fb21ef713c6d5e36264ba65ccc801b8eb107b714aad65bb503bb1f4721c0a6f97e5ab89300f049f42a4616ae43d29c089c286687484d18629c1be1b5befbdd0b3cfc86b1d28add89df4cc5e68dac3f56f2490a9068ca9c634ec258c030ec5023baa9133fd2af32fd1112895f9da549d410247
+
+ModExp = 0
+A = 0
+E = f0460c5ca9b3a5c2d1b93c201d020dc43e1c81d1daba432e2cd310902da23eb81a5172b0b357484eb8fa2c04c270893b8198c8ad35453405dadaf05195b3aeb5ec0ccacecb4b6227ca43b27b97e240a4148a472670ed60f304302f757495fd4a91af0fe09800db0c3043a6ae213bee6703ad80523ca433d99ca0eab1e0b7c929
+M = 81dd561d5d5327fc5ed7c9236b5fb21ef713c6d5e36264ba65ccc801b8eb107b714aad65bb503bb1f4721c0a6f97e5ab89300f049f42a4616ae43d29c089c286687484d18629c1be1b5befbdd0b3cfc86b1d28add89df4cc5e68dac3f56f2490a9068ca9c634ec258c030ec5023baa9133fd2af32fd1112895f9da549d410247
+
+ModExp = 60719701a2dc0bcde281a93ce0b8421d1a718adee43c1b5d9fe9e697a48ab3db4f9f33c73cff305ab6b6c300c149b05c6b289dce4580860dc56bc59de81ac074ecebdc65aa3ca040b44e5b3c80ddba1658d78b9abbc4c77e5f171f5582e70ab4438a8e1e2f062d618c4ad09c70c73b5b5fbc9f8f0bbdf1d530a933b705f85af8
+A = e1b400cd3b1f2f1c6b437adfdb970d2c8108f1b39bdbb13582179552011c6c97cba6bff2c463212b7f62776aa3e3aff9f175990e79395e819c144350b0a23d61638d500ecc97726b098e1af334aece23a851c718612442c04eb7b3805a24cc8f5b90042145eb5e5d6a408092832b6bbeb8a621419a9282fb5c075f41c7f1fdc1
+E = f0460c5ca9b3a5c2d1b93c201d020dc43e1c81d1daba432e2cd310902da23eb81a5172b0b357484eb8fa2c04c270893b8198c8ad35453405dadaf05195b3aeb5ec0ccacecb4b6227ca43b27b97e240a4148a472670ed60f304302f757495fd4a91af0fe09800db0c3043a6ae213bee6703ad80523ca433d99ca0eab1e0b7c929
+M = 81dd561d5d5327fc5ed7c9236b5fb21ef713c6d5e36264ba65ccc801b8eb107b714aad65bb503bb1f4721c0a6f97e5ab89300f049f42a4616ae43d29c089c286687484d18629c1be1b5befbdd0b3cfc86b1d28add89df4cc5e68dac3f56f2490a9068ca9c634ec258c030ec5023baa9133fd2af32fd1112895f9da549d410247
+
+ModExp = 1
+A = 9dd1e6f2d3ff24096b54e0ebf0f10e283e484a1cbafc0431adda1296ed97692f3ba99440fd4f67c96dd8bab850e1123361c99362df9ea205ff8e90d1b329459f54730992d5a360e46fcc5f5a909e691abb9a06613d6991bd7c2aa609f0d7b441d7ded0c07b8c394327672d38a905efb2d76aa3be5bb14d0c002aa37e287aee79
+E = 0
+M = fda6f9d8588e3614f5a68ce867a5619f6ddbb8d64450ff402e1c4f1a08b518f79dca21e5983c207c5b7324c16895a1e9f1282fc6cf60b0645f6b02b652ed5b129e67c939e854ab492dec30ea878c3edde10a4b7d1d14c57100c6cbcc5fc085a0d7308715ed132fb917251919c727487fedb66500d5610b0014a43419acfbb92f
+
+ModExp = 0
+A = 0
+E = 8622c37631e428402343dccf8ed09d47b3f4201e95058910289a62707c3ce0b7113c390056cc4796cc9893e471b12cb3f63f900f3356ffd25c8b2fed6f6a7fba2c684eb241ca706c76cecbf72473d8a58c02338e40714b5610465cc319f0a529a7aa3898d9e638b247abd1380c6e8f7fa210c9f1a1a2164db6db83a6bba79436
+M = fda6f9d8588e3614f5a68ce867a5619f6ddbb8d64450ff402e1c4f1a08b518f79dca21e5983c207c5b7324c16895a1e9f1282fc6cf60b0645f6b02b652ed5b129e67c939e854ab492dec30ea878c3edde10a4b7d1d14c57100c6cbcc5fc085a0d7308715ed132fb917251919c727487fedb66500d5610b0014a43419acfbb92f
+
+ModExp = 86fb0b8dc161c41de2adb0f3ddcc8ad49c1efd729a52793a3ac987d4011c9c1dadb18657dca718df75c8ddcc49d60f152c46ab85ae9076ee7bfd405679a7da3a5195a1bbfd7d2b998c7b135ea91f8c445cbafe1276fa502c2a85477716829a2e0d24ba02623405a3654bed8f355bc7ccdb67c3f9a01e249e358b60d7699498a9
+A = 816610e6018ca47074d55750dd16a281019dbf95dc752605794cbb8ea8d75775317ce685737859728320b529fb3b4414b40bf3a93d08d8994a21ae54682cc1c357eb529837a7b0129a0843eebd9341c9bee3a8ae30475bdbff517e885a0c9f2b6a680643bd981efb53bf9dd49f3dc3cb757e117895fb34b1b4336d9bf8384558
+E = 8622c37631e428402343dccf8ed09d47b3f4201e95058910289a62707c3ce0b7113c390056cc4796cc9893e471b12cb3f63f900f3356ffd25c8b2fed6f6a7fba2c684eb241ca706c76cecbf72473d8a58c02338e40714b5610465cc319f0a529a7aa3898d9e638b247abd1380c6e8f7fa210c9f1a1a2164db6db83a6bba79436
+M = fda6f9d8588e3614f5a68ce867a5619f6ddbb8d64450ff402e1c4f1a08b518f79dca21e5983c207c5b7324c16895a1e9f1282fc6cf60b0645f6b02b652ed5b129e67c939e854ab492dec30ea878c3edde10a4b7d1d14c57100c6cbcc5fc085a0d7308715ed132fb917251919c727487fedb66500d5610b0014a43419acfbb92f
+
+ModExp = 1
+A = 9edfce4691f46eadaa2043c7b1092b831ed50f3429f0bca02f985c0b77c686d951be84d772ae4b55f08935bed6e3206c8441574f215736b5c1c1b7595b3b789b55cf56db83741b10144d6767ba2b97b23a5e83504c60e06ab22834b0145655aa0463108317a379cbfc8a93de8a66925a999b8b02bf88dd85fb9898cefe9c95c8
+E = 0
+M = dcb68f6aa530ae9b31d078e2e82670adcc98228e7cf1aa59f81e66426ef14b1591b833d889463564c75b5fd5551ea295a0da581dd80f62c7008ff0f26a1c9f4f756431d48198af157149be8698336b306b0a8b8635d3fc2c4c2194ecc4d2af31ca1892917cc2e621d702eaaeed0d9a0c3dca575451eb8bc5487e313988cae745
+
+ModExp = 0
+A = 0
+E = a3be10ef04535fca6784e5dbf3733d677dedd50fabbc3a860496628950b4747a328c2ce0d903cbe1e700f0af30f59fb917202257815097a2b516df5d0a82642faeffdfc3b7883766c78fc4be5901ebef891a9ca27f3bcf00960729e659bb3fddd54a19ce628e95ab86e4c7a168588bc9f67b05dd21a583acd8dc36e615945648
+M = dcb68f6aa530ae9b31d078e2e82670adcc98228e7cf1aa59f81e66426ef14b1591b833d889463564c75b5fd5551ea295a0da581dd80f62c7008ff0f26a1c9f4f756431d48198af157149be8698336b306b0a8b8635d3fc2c4c2194ecc4d2af31ca1892917cc2e621d702eaaeed0d9a0c3dca575451eb8bc5487e313988cae745
+
+ModExp = 442866609915aa6f1bae9dfb59e721e1b63f42c0f75fbf0a88344120fbbd7aacf15208fb7c9d8bb8477d553cbd826d7e685ad764a8423e81c2131c040ee83a03cab8d5ce50866a941b48c78e9f1330794d908562d4141cfbf26e8c80c69551339eec41e37e2b37b54330f7bd75748f8d26d56ab9eb3b0c127540484c6445a7fa
+A = 8ff65e2cbcbcd8697cc3ce9a26855d6422ac7eb4e66500648c08be697e005cc3c854a54cfab91d43489cd60be8b516a9b3c9688e5e009a1689c6b164a133859a5464ef422c86344fef42cc477c9df27768377c126a066d1b62f593b7f6d6e906feaee16addb7cfbfc043d741b7dc81a87c17f167b7b8ef1b1fb3dfd1eb14102d
+E = a3be10ef04535fca6784e5dbf3733d677dedd50fabbc3a860496628950b4747a328c2ce0d903cbe1e700f0af30f59fb917202257815097a2b516df5d0a82642faeffdfc3b7883766c78fc4be5901ebef891a9ca27f3bcf00960729e659bb3fddd54a19ce628e95ab86e4c7a168588bc9f67b05dd21a583acd8dc36e615945648
+M = dcb68f6aa530ae9b31d078e2e82670adcc98228e7cf1aa59f81e66426ef14b1591b833d889463564c75b5fd5551ea295a0da581dd80f62c7008ff0f26a1c9f4f756431d48198af157149be8698336b306b0a8b8635d3fc2c4c2194ecc4d2af31ca1892917cc2e621d702eaaeed0d9a0c3dca575451eb8bc5487e313988cae745
+
+ModExp = 1
+A = fe9f77f7d0475e00ec964c0effb9b8e079c32e376ce77a9c40ce4018c3df44a77b4f294d9565502b2b79accb30cb58dda6d15e1543b6d4a53296543ed11c7f51baab60283ef03fae37dfeacb431392487ec2839551a933895c4dbf18844f7b375d3e6f558d3c39993cea1bbf7fb743a6a07bd3753c03eb7298811476d7f3ff1d
+E = 0
+M = e7a96cf6fa930f73c8bdc2726bbba246001a9d27f39cc2b978c99dc6f15af0e8aaf26b565302f1112e607e2df4066948baba931b89cd9bbdea2072e05b9a4968fdf282c43d997987c3a3a0434e925a679ac81f316b7a7b724b79be3d6888b66f4512759bf66cfaaa88b9513dd27a44aaea75437268a014c4eb50ba2e50093511
+
+ModExp = 0
+A = 0
+E = a0bc148ed50a9b54036bb8fa1f214979052ebd47db8b347af3bb03b806bb457b468ba34781f8a25f289a7a90af4903dc14809a166df2f4c3527de2ea6911cb1afb9071a4afbb522a7d50634d66fd584c73f32d05217dc9f7f16394c68a692a953492ca85f89cc11da95fd8cac6231647923ced48a1b3b0ee68c010286d452836
+M = e7a96cf6fa930f73c8bdc2726bbba246001a9d27f39cc2b978c99dc6f15af0e8aaf26b565302f1112e607e2df4066948baba931b89cd9bbdea2072e05b9a4968fdf282c43d997987c3a3a0434e925a679ac81f316b7a7b724b79be3d6888b66f4512759bf66cfaaa88b9513dd27a44aaea75437268a014c4eb50ba2e50093511
+
+ModExp = 91fd879d02f95a9f40fcd1037726f73892caf84e9b43b4aa4126d9062a0d22c464e7af2fbd91aa849612d99d9519b724a7fb1cb018fffdcff321d883ab2519953c9f174f09dd8f13ac87339887385966eb4a94842276637b2c36c0a5036b1d3bbea438bc6efd4b4851c7ec06879d60694df894717569bcd31c4b13d80df6cbca
+A = cdec5edc1cb3ea974342b85aabc0f9385cf877ca328747d40dd4d297623ad69ab6582653faeed5aef225208305135cfbee32e066cb43e18afacea3a32acc8aabbc49617ac33e741651924ae56dd6aa044a12a1ea50fef573b5befb2f4b21b9cf83ab2aaa6fd153580a0761666ade8fb94f202a3c3dc4f33297eabb4564374168
+E = a0bc148ed50a9b54036bb8fa1f214979052ebd47db8b347af3bb03b806bb457b468ba34781f8a25f289a7a90af4903dc14809a166df2f4c3527de2ea6911cb1afb9071a4afbb522a7d50634d66fd584c73f32d05217dc9f7f16394c68a692a953492ca85f89cc11da95fd8cac6231647923ced48a1b3b0ee68c010286d452836
+M = e7a96cf6fa930f73c8bdc2726bbba246001a9d27f39cc2b978c99dc6f15af0e8aaf26b565302f1112e607e2df4066948baba931b89cd9bbdea2072e05b9a4968fdf282c43d997987c3a3a0434e925a679ac81f316b7a7b724b79be3d6888b66f4512759bf66cfaaa88b9513dd27a44aaea75437268a014c4eb50ba2e50093511
+
+# Craft inputs whose Montgomery representation is 1, i.e., shorter than M, in
+# order to test the const time precomputation scattering/gathering.
+
+ModExp = 9442d2eca2905ad796383947b14ddfcc341f5be8fec079135c36f6f0d9b8b2212f43e08bf29c46167ff0fe16b247cd365df4417d96cc31c94db1cf44b73b0ee3ebcc4920d9b0d003b68e49c1df91e61bc7758a8a1d2d6192ff4e1590b1a792f8be3a1b83db3ad9667d14398d873faf5d885ec3a2bef955026fae6dbf64daea2b
+A = 3a4b4c57e62c5e9d1a9065191f8268fed9d5f6f424d071acef66f0662b8210f4c029ed991512e40c9c912043c816d2c4c5b53fa0e5c253e16808aad4225130dafbbb89fd4f30cdfc1c2f2179b636a7ddc4be579795820b4b9377637bd8a21a0ef5a90d0e0f865321eee23d9be2a3b7320b4012d02941b892df2c40bdc85c1898
+E = a2c56ea1362511cac0301918e15a9afe7d37edd438a5c3538d258ea01f0a6df758de07111e868b3ad8fc89b629b4955d78a1b3af902be1806410ddde25ccc6a196ba5949395c1ad5d8725b18815dc1cd5ac1c7dd17773f571e3f2e628255af14476e0494be23a4a4dfd18e23142f33d7a59c236fec61660e360d9676a747c69f
+M = ede35a3a7afac817d413373a2032abbc067b1493f709ae6e1282ee5469743391d891b904938857168802b7872d3cd7ac18ab249a9e540a86f970b1d0f310a4cc29df1cc9d4063d98c554f1a32f4ca5eba3523cdfb142e0fc609907c7a92bb0187009d97ec471db3545f42dd5fd29c07b7816085d09477ba31fcf90084660116d
+
+ModExp = a7f5844fa9e7202d4b70ee252c9846e63d3d091b0387768ded872cec53458e19df0d9b4960226e269b8ca5dd4c4eda423a67b6dbb48235c08c12c6c7c78db47287756d3ed9cecb9232f7d18d5d80b9676cb68ba4a290c97e220beb1a069976b5e6022a4c1e5ddbeec86b62dda24ffea1deda37695c9f61a8817218e6370c0679
+A = 7d6d0cc947ceb949cdc4e9e1044f5deca5bb05a491041e0d85bc4b92a0944a57c72845fad91e59010c61ad1712bd2f612d53a846a044632262a9f2e3373b062fde2484e0c165ff947f2469f743ab6e2e5e13c640fc4029b1c9213eb8473c674e7f9e95a4a5c5636d4656c1e696962340d77b322daba47d6fc894f2a2cd9e0afc
+E = b78012afe806e2344d004c739c97324256850980ac97d88c4ed9a838517639ca112e235978d21a176c33f5a68703aba0f2a05501bbe3fc8d49a000fbf530cdb431581dfaf8683cb15a2aee5e239cbc542827100da3b47babf4a16ca7c588aff9912e674abb449e0b767a15e415f4e7f2bbd6380d7131da3df8d49b13bfd35ce3
+M = b72d5c55bd2998472f1965e75a51be6155c1ba04656da8f66bcb34db36a7b1db66a89d1d05b1bde10206acf85be7b474ab689220faf1bb52ab39d8dc00512dd4e26df1179c11b973e1274db85a88c7cc2a17113abdffe58cb930ddc5f3ccc4d68b4e65c913730509f7ce5656e8bbaba9b1be177ab9f766678f018fea05da9cdf
+
+ModExp = 465ff295786a88496828fdc763e9292d557957544e9322b7996807b87fdbfa7a11614bffeec557ca831c4824c8e4ca3b1a1c7f3f4f95ec3fd6a86b73bb13d78b73af2b3c7e76954d0cc03bcb0cd606867ebb3765a8b3d0108cbe4f343a14016be9c33f6d200f0dc547e7d6b02bfab1e79dcdf9c9835a814cc6c855a12ebeb66d
+A = 89ad02bea3e9ab839a6e23f20122409daba52c68e1e893034b30d321c0305434a6af940015e3fa5ca9c35230da34beeb1ed4fbce6c1da3a8bfe3f3ae172276c1d1723b47ee61e6f8fcfdafad102d6f7ee2a79f510c7edb93096205a40a6c9e665b88b18f39a979e2e61286d939952a6f02fe8148b7515bb25f4252337cb6e60d
+E = cbd6ac628cc7afa3c61bee9c22a06a395087ec1811fe9681b55216700c435996c815e7cec8aaa90016dd2382d0306a5414630124e14f3d396a4ba02ee17851bf720f1607ff813e4bbddf01338983db12f59bd6371a738eee3eeb716f21051d6174d2d6c77602942b9edaac18d4b3a723096c0d00dd23a8a605c585022f311560
+M = fa7a3e40364c8a8d0f14f0213a3f3e035222ca0ea19d46d10ba41580e5dd2805c8a133f3856d7d5d97f922ea540e5eb0d10ad04dfdbb74f518f58da0099a6fc2b3f3def92985176e07fc78aff2faebccca10a429794e5f15ff92f75fe90f527c60ddea8093a9078c703c372ca09f7aeb27ade02f3595308c61dd9c44e62fd101
+
+ModExp = cf08bf00261402102e9fe03f3074471dcf0e9b3c96d4d1503f099f24ec85e1901b023e9e048c1ad042244f5f70b38b25a99f4c0a7b57d5844bb0d0137367f45f4ce2cc7746105b77414768cb97648dc5721149aed2d4c682408cc0d50d26dd0bd77e848911f8625c727cac5f32e63bcb548f41a57d718d772f23983a42f603bd
+A = a419646a6631c2c69b18f7aa65011825eb31692eecaee9d74f92d92203811b68e9764bda31a1585bdf69b6273fc6f9f508c395ac081336506525dad88473512f08a205621ac8b16e9864c7a7c5a4f17435de00d0b32badec6ce4897e3e1076c562b6d9523f63d0b2079eaa416cb090471657763f24931d955d1fa2720c80a9c9
+E = d5a6f4a1842aaee39805356dc8d0d678ee03b2c81277345beccb2742f899132feb43271f95968a01ae68aa8277201851992dc0aa7a71c90aae71b124d873ee264ea400fb131be0fc6c4ce8c04c45f6bdaca89ac743635caf6158983d257e21cef6800d7f990e912ba21bbfb8fb779afa4abd19e07e7e07eee9908493d1ca502c
+M = e739689b6cc6def1d45fb1a2ab551643beeb303f4aaa4da47ee5e4948510f8445b4c40e99ae8354dede60b2ba6694e93bc4d573b7e8adf871b7a9a9636eb7d70f2e49328e2d7978143b177cee8374ef01bd1ee2d95862765883f5e7971668b53ef0ff41b6539faf63c397522b0bdce916388e72e26c8d3d2e58dadeb9eb5d479
+
+ModExp = 827e6312ec3b14600203bb83f5b277ded197b2967363630ef673240df05edd3ba8ab2b11c86251a612206569c6c33952b31e264f129909bfe723bd0ee1624b36cfcfaa893a6ec8b5a1f7de79f83e79b459a3350f89f412ad1cfd6bc4c2a7a29272c783d6ecceeb1398fa17041835643f4debef9b5e87b098d104bb8912dddf7c
+A = b8e49c637829021d32db3a39a0c1e58cdd4c6e4eda7e8e9293be379e9c2e2d184f929d278598a81ae231cfedcf69cce4a6e31cda3c8ac14d753a7311f2436e29795f0dfb60259a0f61a997918ff984aa2284b43a9d64c974059e9682adfffd018305835f74eda8c75fe4877d811c1620f654ec9f7f32d1af5ce59115e2f41785
+E = 80e0febf369d234bf1aaad4f82df2e2ff02882c3184781f6ccdf4f7cd93b6887af86830077c84dfb02109ada05b40970b1c65228b0c19030bd6361c3537fee22a8155c03b4e7007ca006c6daa3659518d05bb81ea0079456d0ef6116df248dffdb0c935f321f5a1034deefd5a9414a0652aa6548de33325b474b9e5a8507a082
+M = d5eb1d14af842a9973274f7463d90cf0ccff19c47d710edbae184478d4f29b02693ed7958bd487054327b9e6d8879e24c9af7730b92f323eeac05558da6c1b952e5dbf13de236050a77628bb5325fe0d14cc5773bf73338759d5ab43c212b414581280f1cee250007e53791b800b61c90de0328acd7bc43fbdda48158939392d
+
+ModExp = 4a1efd29c7e78549f5cd4deed1454b37462c7810ee6a8a2493b764dfa479be13b314cf9ff98259517d61865567ef499a511630c0038c97914625df181c6fe07892f329f98b344a78d751e9471483eebaa7977371bf97bb25187ae7e93a9227d6c124ccb4644423c961a11ae59c4354f89d5a95164c23d9aa256e289e9cc0858e
+A = bd86c9211fa6a47a06e5016c46cb8a99e34a043a29e22f8c3196fa7197c26b38927b8d9bc0ddc11a5fa4bcc44deb69dbf37cbe7ebc9a2fad6c74e09ab5a9dd929fa04ab4319b6caad1035739be78ba631fb0748d9e53944836d37ccda6e6a62823c696d8f31139ccd7f2f86b22fa026ecf433cfb1271a3539ac4f1c83aaac059
+E = c40b9972006d28a84c2769a86e526a2b274f73afc7c5c6a2742166757f61b5f5fdbb228afa157af62af989ffe966f232bba9e6beef5403d1690ade31a6410f7f349a35bc4267a129afd647993df7d45cc0e1a1ba4678d7f1b6e8a344d8ff7037679e1f4db25a454e4246f6b55c416567fcfa188e8a3865115851d9edf0aa8902
+M = cf424d7af75ce7eef90cad75ae55ca8810cc7b4703fdb5bce701e7bac07e0c371cae06df2aa8facb55a0faa6793e4d2bd9d7969703743b9be170be82792aeea55e2bc0f7ab7617b276486bf474dee2f4556aab595ff3ef115139cfe5e21ccd4ee05c0e1cf901bd85df86cc17195a783b0be836d00bee82ce064077f9191188f9
+
+ModExp = 3137a3049fd4ad2e26d870f5c998cf11bfe82101884a82e85e43facd0928cd7434a2e346ca124619769fa141bbe92ad6f36b99231032ddaec3b349a410f82b5ca36f45e56e5fb85dc63d32053dc90805d3f1854ab385281a71a57726bf97158494e7476057214ca7379ab8b70f5bdc15f70bdad3adf33c3a1f9cd1b6bbbad556
+A = 39a1dc6a4c3f14d9c350ee968d5ce139ef725952c967a2d1bedf48ace22091283525be03807e2e263d2640be77f0525247bcd07149bba50568cec5a082c87d72962cf9e43bcb5cdb1e7e9a650fb53e0ec2fad37f09a9f036c0d7dfa528fef846769f80a9a60854910ca1b4ee05dba82ed2ee018348d6b3e52a764b8ffae61e0
+E = deaee3a3f80c9f684ed7110c0653847ccc7be5ff6d982fd4b49f59b5dd35f7210b1077babbcedbc127df35cd469dc6e569a0f84e58149b5605c94b09fd7f0b098d02b4a04631328b3fae39e6c2fce25334225cab71829abdb9507cb903701559660f2c08c3b743336119d1260a0db27054cad3f28bc1b04b2289baa58fb33965
+M = 938388927d06ed3bb1286c0f06d3054cb0ee16dc7a0bbbf13a45293c09a5f40f1d611b2e1a1b0ec2ef109b508e27af4274954905cae52034f8740a744153b4d22059f0dd262ea51785522098ecacced6da07709ee6b5acc8c4e99331379a7c3de7f4e2d1431e43b19570140955b7bcba118dfbaa552cbfa2be531e8f781166ed
+
+ModExp = c15ae334455d9f4d1030cd33e734726a27c63624c2afc576238cce5e0498298a4a0c93090a0d19568b41290303c4b558f3d9dd74f9cde8798710f68569ea0d6fd971ce67ec5b54495031de3d8842b8b49288725bee5c9f72b99054d64986ccd4e18d70d5f33943f08cd694eff538f84438ea993ebaba0910c95b3a694f213510
+A = def633b955a917569df3ba8517455eef0655e7a35985edda27097a063e0d82c7c3a76dc36c5d8a71ba9d540790ddd0ea514aaed98925f9a1808eb288d387aaf9605a9ef8a333ebee7ad7057bca012efd619d5867f02266f65976ef4b16da17468426ac4f99b3e8921707e01b4de20f6f9a068e6a19d872079a27f3a44449db83
+E = a465c47b0d15d48e01bb8b1d8e3b3253e11515f6874dbed6c25818adf1a8fd927124d5593beb367f685c11e46f18415be73ccdf16fa2e93a600b728163d21d232849e5278c3749d903edad3f1c4535a2f55a2ab65e7ebc64888bd2a0527e876ecf38cec3ab1980d08138709fad8eb88ae65d960adc3f0f8e92f784fe96fcb693
+M = e43cb9ac1446154356cdc31ec771c79b0e461e22d95185bbe1a279c0945e3af07903a0cb54d553380716fcdcafb4b7cf5dc6da481dc74a8c583d75ff6c1f8e429182d200246ebc473bb56e173787987c1b7fb2dd23f5b2e438a97bc4a1df628bc044fdd1e80c0cf37030adb7b04784dab827d0dcd64f0dbf37c980612570ce11
+
+ModExp = 75c3f79ab7c991b98e65505342a8a563cfb08b5d3ccf8664c7db1de50256b1d17ebf7096dc98c7bb5d7f027a894ae5cbb14dee04d5d445e775ad7e239acc82673b0ac2d819a69c83864f34e73d9a636f05de8279619a067b4c90ad038db5910447e03841d2034635018f08cbcd21efa00994247763a249082594128112f95232
+A = 34def7d76f6f158a359fd12759fb889cdf6af0a24830dc3e84283a1ab4e9b2647a6a36b86482f829b2cdf3e3d6028f9a884b1f64f7262315446bea8b0231828e2f3d990fb103c17f820b39e4b8427c85643ceeca8f5dc8f191d1255768300e859bd7d88c770319ef38269660d221cb3bc061389b6fc0783485ef042b1c7d6fef
+E = c6c46453dd5aac6b37277a446b1d0c69cbe476eeff55b3ac35edb89ba97116b0e7783660f2c7b31b2a2d6c4709d0ab45d01a838100694b0777c9c9c14c959b07c437c73a5eabb7402f1001e802d797a2e7707285834fb6440a1c2f727f7bb84ddb2a49312d32fa0ce620c43872655cb5c394749c9e75d7fa25be00efe50d47d6
+M = fbbab6698a9142095c46b38a732592e4366c1838b84bf40f8c8fc7b630f73380a0d09765562365798f8c8030ed1b6728329d8bb06e882c35a1d59bfe84146a9db2afe42a414014e247390281c782fce806d62adb54778d2bcb49555459429d6ed446af5359657667f6aa19e8e3e0e24ab2bc312b2d90b5cb1ce6f2f15af15d9d
+
+ModExp = ba16d7f3f6e162ce248490d164a13c00e7720d8a667e2d3ebeb13f1663e15ef5408d5b56cbc7bc793a8ca787cc50f8e15e0e9d4ee764531d04a9114eea556bb3e206ed7d85267151a056b6e68fbf35e03f2cf829708ffe1de13e95ecfe365aff1eea36340ffcd3892dee659fb1ecbe50f5080e54737c10f9c1ba638b14ef537e
+A = 9025e6183706105e948b1b0edf922f9011b9e11887d70adb00b26f272b9e76a38f3099084d9cccf12d04b1a99c0f654f8b9ed90c6dff9478c60bf05d58d734ab60eaefa14a22230ec60c90dc1f0704b61eef0bef345785ae0e6a9af7db069cf6bd2b4e0fe58a0ade83c7e46a04b9fe1d24cb9b65c6f80de713e61d70eae5b286
+E = d7e6df5d755284929b986cd9b61c9c2c8843f24c711fbdbae1a468edcae159400943725570726cdc92b3ea94f9f206729516fdda83e31d815b0c7720e7598a91d992273e3bd8ac413b441d8f1dfe5aa7c3bf3ef573adc38292676217467731e6cf440a59611b8110af88d3e62f60209b513b01fbb69a097458ad02096b5e38f0
+M = e4e784aa1fa88625a43ba0185a153a929663920be7fe674a4d33c943d3b898cff051482e7050a070cede53be5e89f31515772c7aea637576f99f82708f89d9e244f6ad3a24a02cbe5c0ff7bcf2dad5491f53db7c3f2698a7c41b44f086652f17bb05fe4c5c0a92433c34086b49d7e1825b28bab6c5a9bd0bc95b53d659afa0d7
+
+
+# RSAZ 512-bit.
+#
+# These are regression tests for code which historically reached the RSAZ-512
+# code. That has since been removed, but the test vectors remain. Note that the
+# lengths of the inputs, especially the *bit* length of |M|, matter a lot.
+
+# Control: No relationship between A and M except that A < M and they're the same number of limbs.
+ModExp = 7f34c1cd63377bc3abf2bb5b2d1bf5f06454e1e8040fe19a72245ce9731cbee1bf9e84532300776c8021ed4f3a8de508d85b4cf320bd82065a013754857b50c4
+A = 8e4e67da6ff890643d0599387955996ef6f0c2045eb9944576ddb965ca64cdb6247727ce128ef178d4a84e5a56d2e67eb0fe389ecbf691f9244ae80f4c11b364
+E =  be99d8f0650e540b9b191e9cf96f74881b902e32ed169ffd8a1776c3f3e80f0ac765aa14615713e1549f250a20fe4ee48c4e0c6176162fc7842a0dd64d640d1
+M = f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725491
+
+# Same as above except A is negative.
+ModExp = 71fa6a4c8ae75368eda8cc6282c26afa69e2af12a97fb9444f16b7dd6c99e0a5d6034cab4248cae4357346b211039f4a2bc4c5a20a297372094162417af703cd
+A = -8e4e67da6ff890643d0599387955996ef6f0c2045eb9944576ddb965ca64cdb6247727ce128ef178d4a84e5a56d2e67eb0fe389ecbf691f9244ae80f4c11b364
+E =   be99d8f0650e540b9b191e9cf96f74881b902e32ed169ffd8a1776c3f3e80f0ac765aa14615713e1549f250a20fe4ee48c4e0c6176162fc7842a0dd64d640d1
+M =  f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725491
+
+# A == M - 1 == -1 (mod M) and the exponent is odd so A ^ E (mod M) == A.
+ModExp = f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725490
+A = f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725490
+E =  be99d8f0650e540b9b191e9cf96f74881b902e32ed169ffd8a1776c3f3e80f0ac765aa14615713e1549f250a20fe4ee48c4e0c6176162fc7842a0dd64d640d1
+M = f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725491
+
+# Same inputs as above except A is negative. Note that A mod M with a "correct top" isn't the right length for RSAZ.
+ModExp = 1
+A = -f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725490
+E =   be99d8f0650e540b9b191e9cf96f74881b902e32ed169ffd8a1776c3f3e80f0ac765aa14615713e1549f250a20fe4ee48c4e0c6176162fc7842a0dd64d640d1
+M =  f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725491
+
+# A == M, so A == 0 (mod M) so A ^ E (mod M) == 0. Note that A mod M with a "correct top" isn't the right length for RSAZ.
+ModExp = 0
+A = f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725491
+E =  be99d8f0650e540b9b191e9cf96f74881b902e32ed169ffd8a1776c3f3e80f0ac765aa14615713e1549f250a20fe4ee48c4e0c6176162fc7842a0dd64d640d1
+M = f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725491
+
+# A is negative, and A (mod M) is the right length for RSAZ.
+ModExp = 8d76eb0f8c7bc3160cc8bb0e0c3590fbed26c5932f5f525b48045c0bd46dda287ba5483f97c851fb7c12c2e858ee7a4a4d1af745cbfb3eb311fa54bea12cde25
+A = -80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+E =   be99d8f0650e540b9b191e9cf96f74881b902e32ed169ffd8a1776c3f3e80f0ac765aa14615713e1549f250a20fe4ee48c4e0c6176162fc7842a0dd64d640d1
+M =  f12f2c19ee1ecf2c999b87bdafde60eace3790faad8f9adec13b14c6dfb69f8795a1d0fe65494250b59534014b918453042012952ae6f5786342999600725491
+
+
+# RSAZ 1024-bit.
+# Note that the lengths of the inputs, especially the *bit* length of |M|, matter a lot.
+
+# Control: No relationship between A and M except that A < M and they're the same number of limbs.
+ModExp = 8984f8c16044f9c0ad7bd72347af90f58e6e003acda92b76e3c7c4a56ea8e918409d8e9b34884d4c89d0b17cb40fe898f2627c084a0f1698e46beccbf6f48eecc281e11ea9e5135adba460ddae157f2c655b5f589ce29b254d43a960a71cede8a08dbb86be4dac22458da232fb1ec2470856827302ed772c9ddafa408c931aa7
+A = 21158da5fe20356825e72b3f5384ec57720d22f727b27ce2f945c8ee311db781add73bf8fae96b775c909bd22fca75c44c2b0584284a5bb1c07f8eefcd6b0a44047a02b185df34f897f11d4fb9a86c9eb841b4cb8d0383441fdc5af3ef385b5e8380f605d73ed41bb42eb2c2a5704d6034b3ad058dafffce83dbbfb6295daaf8
+E = ecdebd112b3b5788669449dcddbd479a203ee9ab72a9bb9c406b97623513bf0ab9a22f1f23634d269e16bfd6d3b64202b71fc355057411967b6ac70f8d9cef0a4e06819a9a18cc06bbe438243fa9759303d98be8a65dc1cb13595ee9b99f138554425d50f6fbc025d8ffa3eaea828d6f3b82a3584146bafde34da257995f0575
+M = ff3a3e023db3bba929ca4ededbace13d0d1264387b5ef62734e177eaf47a78af56b58aacc8ac5d46f5b066bafb95d93d4442bb948653613eec76837b4ffb7991cb080b6c8b403fb09bc817d026e283ee47ab2fc9af274b12f626eda2fe02004a8e27b9ed7d3b614e8955c7e7c2c0700edd079455237c4475fbd41857e206e4b7
+
+# Same as above except A is negative.
+ModExp = 75b54540dd6ec1e87c4e77bb93fd50477ea463fdadb5cab05119b34585d18f971617fc1194240ffa6bdfb53e4785f0a451e03f8c3c444aa6080a96af5906eaa508862a4de15b2c55c023b6f278cd04c1e24fd0711244afeda8e3444256e51261ed99fe66beedb52c43c825b4c7a1adc7d4b111e2208ecd495df91e175573ca10
+A = -21158da5fe20356825e72b3f5384ec57720d22f727b27ce2f945c8ee311db781add73bf8fae96b775c909bd22fca75c44c2b0584284a5bb1c07f8eefcd6b0a44047a02b185df34f897f11d4fb9a86c9eb841b4cb8d0383441fdc5af3ef385b5e8380f605d73ed41bb42eb2c2a5704d6034b3ad058dafffce83dbbfb6295daaf8
+E = ecdebd112b3b5788669449dcddbd479a203ee9ab72a9bb9c406b97623513bf0ab9a22f1f23634d269e16bfd6d3b64202b71fc355057411967b6ac70f8d9cef0a4e06819a9a18cc06bbe438243fa9759303d98be8a65dc1cb13595ee9b99f138554425d50f6fbc025d8ffa3eaea828d6f3b82a3584146bafde34da257995f0575
+M = ff3a3e023db3bba929ca4ededbace13d0d1264387b5ef62734e177eaf47a78af56b58aacc8ac5d46f5b066bafb95d93d4442bb948653613eec76837b4ffb7991cb080b6c8b403fb09bc817d026e283ee47ab2fc9af274b12f626eda2fe02004a8e27b9ed7d3b614e8955c7e7c2c0700edd079455237c4475fbd41857e206e4b7
+
+# A == M - 1 == -1 (mod M) and the exponent is odd so A ^ E (mod M) == A.
+ModExp = b5d257b2c50b050d42f0852eff5cfa2571157c500cd0bd9aa0b2ccdd89c531c9609d520eb81d928fb52b06da25dc713561aa0bd365ee56db9e62ac6787a85936990f44438363560f7af9e0c16f378e5b83f658252390d849401817624da97ec613a1b855fd901847352f434a777e4e32af0cb4033c7547fb6437d067fcd3d964
+A =  b5d257b2c50b050d42f0852eff5cfa2571157c500cd0bd9aa0b2ccdd89c531c9609d520eb81d928fb52b06da25dc713561aa0bd365ee56db9e62ac6787a85936990f44438363560f7af9e0c16f378e5b83f658252390d849401817624da97ec613a1b855fd901847352f434a777e4e32af0cb4033c7547fb6437d067fcd3d964
+E = 61803d4973ae68cfb2ba6770dbed70d36760fa42c01a16d1482eacf0d01adf7a917bc86ece58a73b920295c1291b90f49167ef856ecad149330e1fd49ec71392fb62d47270b53e6d4f3c8f044b80a5736753364896932abc6d872c4c5e135d1edb200597a93ceb262ff6c99079177cd10808b9ed20c8cd7352d80ac7f6963103
+M =  b5d257b2c50b050d42f0852eff5cfa2571157c500cd0bd9aa0b2ccdd89c531c9609d520eb81d928fb52b06da25dc713561aa0bd365ee56db9e62ac6787a85936990f44438363560f7af9e0c16f378e5b83f658252390d849401817624da97ec613a1b855fd901847352f434a777e4e32af0cb4033c7547fb6437d067fcd3d965
+
+# Same inputs as above except A is negative. Note that A mod M with a "correct top" isn't the right length for RSAZ.
+ModExp = 1
+A =  -b5d257b2c50b050d42f0852eff5cfa2571157c500cd0bd9aa0b2ccdd89c531c9609d520eb81d928fb52b06da25dc713561aa0bd365ee56db9e62ac6787a85936990f44438363560f7af9e0c16f378e5b83f658252390d849401817624da97ec613a1b855fd901847352f434a777e4e32af0cb4033c7547fb6437d067fcd3d964
+E = 61803d4973ae68cfb2ba6770dbed70d36760fa42c01a16d1482eacf0d01adf7a917bc86ece58a73b920295c1291b90f49167ef856ecad149330e1fd49ec71392fb62d47270b53e6d4f3c8f044b80a5736753364896932abc6d872c4c5e135d1edb200597a93ceb262ff6c99079177cd10808b9ed20c8cd7352d80ac7f6963103
+M =  b5d257b2c50b050d42f0852eff5cfa2571157c500cd0bd9aa0b2ccdd89c531c9609d520eb81d928fb52b06da25dc713561aa0bd365ee56db9e62ac6787a85936990f44438363560f7af9e0c16f378e5b83f658252390d849401817624da97ec613a1b855fd901847352f434a777e4e32af0cb4033c7547fb6437d067fcd3d965
+
+# A == M, so A == 0 (mod M) so A ^ E (mod M) == 0. Note that A mod M with a "correct top" isn't the right length for RSAZ.
+ModExp = 0
+A =  b5d257b2c50b050d42f0852eff5cfa2571157c500cd0bd9aa0b2ccdd89c531c9609d520eb81d928fb52b06da25dc713561aa0bd365ee56db9e62ac6787a85936990f44438363560f7af9e0c16f378e5b83f658252390d849401817624da97ec613a1b855fd901847352f434a777e4e32af0cb4033c7547fb6437d067fcd3d965
+E = 61803d4973ae68cfb2ba6770dbed70d36760fa42c01a16d1482eacf0d01adf7a917bc86ece58a73b920295c1291b90f49167ef856ecad149330e1fd49ec71392fb62d47270b53e6d4f3c8f044b80a5736753364896932abc6d872c4c5e135d1edb200597a93ceb262ff6c99079177cd10808b9ed20c8cd7352d80ac7f6963103
+M =  b5d257b2c50b050d42f0852eff5cfa2571157c500cd0bd9aa0b2ccdd89c531c9609d520eb81d928fb52b06da25dc713561aa0bd365ee56db9e62ac6787a85936990f44438363560f7af9e0c16f378e5b83f658252390d849401817624da97ec613a1b855fd901847352f434a777e4e32af0cb4033c7547fb6437d067fcd3d965
+
+# A is negative, and A (mod M) is the right length for RSAZ.
+ModExp = 9cf810b9e89d5cbc4b79ae64e123ea06d92965e2bab077df97a1b906dc2e1ddcf96a9c4ed14e2cd96309b829ea9cc2a74a7d4b43c5f34d792a7c583201427754b8f78b783608070a84b61f18913e3ced7f7f530972de7764667c54e29d756eea38a93cd1703c676a4587231b0ebfeadddf908e2877a7a84b5bfc370ecf0d158d
+A =  -8000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+E = 61803d4973ae68cfb2ba6770dbed70d36760fa42c01a16d1482eacf0d01adf7a917bc86ece58a73b920295c1291b90f49167ef856ecad149330e1fd49ec71392fb62d47270b53e6d4f3c8f044b80a5736753364896932abc6d872c4c5e135d1edb200597a93ceb262ff6c99079177cd10808b9ed20c8cd7352d80ac7f6963103
+M =  b5d257b2c50b050d42f0852eff5cfa2571157c500cd0bd9aa0b2ccdd89c531c9609d520eb81d928fb52b06da25dc713561aa0bd365ee56db9e62ac6787a85936990f44438363560f7af9e0c16f378e5b83f658252390d849401817624da97ec613a1b855fd901847352f434a777e4e32af0cb4033c7547fb6437d067fcd3d965
+
+
+# Exp tests.
+#
+# These test vectors satisfy A ^ E = Exp.
+
+Exp = aa6d7ac431
+A = d0e07
+E = 2
+
+Exp = 12d416b110dbb4e467ff0c89a22122f4da8240
+A = 1a18cf6
+E = 6
+
+Exp = 49a3b33e23d84f1ce0d5d83f5dcb651d50cf3920f0143da2310d0512a90a06cd8f38977df8a756c30883de38df092000
+A = 2a3acbd2
+E = d
+
+Exp = 5b4a0d5a956f885f275712b194459980f24708bfb6393d71bd37dce852ce455724f5ee5030775fb86b4295edc98afaafc097e4d82a97c0078ec0eac763db16549c5145c4cf2d3124f88cf9a5c71da0625afb99b26801786fe49a778415dc025954021753d08691947a208b613f0be5c1
+A = 54b3ae461
+E = 1a
+
+Exp = a0ea5f6a4de49beb8fb7f0dab280d6a32c5a3814c9a5153a7944cec0a9028497846a8a89044348721a0bb5f0c3ded3e980574ea321b0cdb0ead4f4e93841ea7478a7f15d9729b646a8165813a0750e8124f5465dda9b105e1bbeff18fd09c09a2e26610d9176d253b877c3a8908a6be521cbe1e472a7a1b7820e4e890f8f28aacd34609c686e76e15b01bd9324a71290812724ea564d11c874a6765b262c3e57d479da0287a76026a1e8fe53da0b02405da1d379eaa30fc65f
+A = fccec0f6df
+E = 25
+
+
+# ModSqrt tests.
+#
+# These test vectors satisfy ModSqrt * ModSqrt = A (mod P) with P a prime.
+# ModSqrt is in [0, (P-1)/2].
+
+ModSqrt = 1
+A = 1
+P = 2
+
+ModSqrt = 1
+A = 1
+P = 2
+
+ModSqrt = 1
+A = 1
+P = 2
+
+ModSqrt = 1
+A = -1
+P = 2
+
+ModSqrt = 1
+A = -1
+P = 2
+
+ModSqrt = 0
+A = 0
+P = 3
+
+ModSqrt = 0
+A = -3
+P = 3
+
+ModSqrt = 0
+A = -3
+P = 3
+
+ModSqrt = 0
+A = 0
+P = 3
+
+ModSqrt = 0
+A = 0
+P = 3
+
+ModSqrt = 0
+A = 0
+P = 5
+
+ModSqrt = 1
+A = -4
+P = 5
+
+ModSqrt = 0
+A = -5
+P = 5
+
+ModSqrt = 2
+A = 4
+P = 5
+
+ModSqrt = 0
+A = -5
+P = 5
+
+ModSqrt = 3
+A = -5
+P = 7
+
+ModSqrt = 0
+A = 0
+P = 7
+
+ModSqrt = 0
+A = 0
+P = 7
+
+ModSqrt = 2
+A = 4
+P = 7
+
+ModSqrt = 3
+A = -5
+P = 7
+
+ModSqrt = 4
+A = 10
+P = b
+
+ModSqrt = 0
+A = 0
+P = b
+
+ModSqrt = 3
+A = -2
+P = b
+
+ModSqrt = 3
+A = -2
+P = b
+
+ModSqrt = 2
+A = 4
+P = b
+
+ModSqrt = 2
+A = 1e
+P = d
+
+ModSqrt = 2
+A = 1e
+P = d
+
+ModSqrt = 0
+A = -d
+P = d
+
+ModSqrt = 0
+A = -d
+P = d
+
+ModSqrt = 3
+A = 9
+P = d
+
+ModSqrt = 8
+A = d
+P = 11
+
+ModSqrt = 6
+A = df
+P = 11
+
+ModSqrt = 4
+A = 10
+P = 11
+
+ModSqrt = 5
+A = 90
+P = 11
+
+ModSqrt = 3
+A = 80
+P = 11
+
+ModSqrt = 9
+A = -e
+P = 13
+
+ModSqrt = 7
+A = 7d
+P = 13
+
+ModSqrt = 6
+A = 37
+P = 13
+
+ModSqrt = 1
+A = 1
+P = 13
+
+ModSqrt = 8
+A = 1a
+P = 13
+
+ModSqrt = 54d4cf0fafe265056a29016778cea6b712bc66a132fb5e6b6865e9b49e4c97ec
+A = 599c10484b22d0b5a115268c7538ca99b3253a311a4ab1ca11c3665b0bec393a1167d1ad94fb84cb2c7ad7e2c933e8f613bdd08fe1f1aa4a9b0b9de0c8a7c9d4
+P = cfc4ccae35458ab5be1a1bc0664188253301f8702af4f8fb19fed12de0c653b1
+
+ModSqrt = 38a7365a15365e911286c1be2a7afe76ef390234d76269e04dee17313f6ea54d
+A = 1c4aabb4d8369710131c664ecf2849e963c1bc31d66e0b939bacf99a870c71f24ed71bdddcf566f3908271fee43fc1ebb51eac7e3153efae641b49d2e796a12a
+P = cfc4ccae35458ab5be1a1bc0664188253301f8702af4f8fb19fed12de0c653b1
+
+ModSqrt = 35ab18a560dece04725667f640ca61d1d59f14d191f94c79f58531acd097d444
+A = 685168ae855d60eba220d803f5296459b30a289580668db9ed51bca51cc2d453a937e13819ae34f7a9a143ac96d17420c53919167e46279b562b550be1cd9abc
+P = cfc4ccae35458ab5be1a1bc0664188253301f8702af4f8fb19fed12de0c653b1
+
+ModSqrt = 288370029e87024175e5bec0eab0929179f42e16995e7f6194eefc61061e54f4
+A = 2a14ab77c045bdc48220ba9c463e1a4b4049cb01edb53be0937767eb2ec19b7d719855052281250a36a0b76d9a5d967d0756e1ded7a052f7056191ad66bcfc9
+P = cfc4ccae35458ab5be1a1bc0664188253301f8702af4f8fb19fed12de0c653b1
+
+ModSqrt = 32255cf01dc943577ec2bcb221b98491d7a1130d046d6c68e95fedff643ce3a4
+A = e26f6dd46a513a1dd3fb14b71be1d4c9e9d79eda1cde10ea4d1eb8abfd4d5857572205e247184dd0cbefa37b5c0bf680ba2bd28c5741f725cfe2aae37419baf
+P = cfc4ccae35458ab5be1a1bc0664188253301f8702af4f8fb19fed12de0c653b1
+
+ModSqrt = 5172345e801ada63fbc4782e32583cc3b4fea88b9e6dfd542f3542f8538ade66
+A = 40dafa8342b302bb04b1f3ddb3b9015a8fc1b597857c115b40631c7be9e22de89358fca23b331596ee5ff304dad7811e6d8e8822f7aa533c9e7c882634ea550
+P = a6813d316f9aca30f98b4f864b8b4b8f51493af930bd4d3a1b205a710e99add3
+
+ModSqrt = 4dcf63c423bf0e39aca2293d57f6792d023db649d6719fe936446904b9f7e60d
+A = 5bcdb514bbe84261e169203e8017909b60c9bb330400c766ee01b0189378e70e61867a164a12643ddc9e94b61e09e5b158cbe85be228a3cc48f95a552958b8f2
+P = a6813d316f9aca30f98b4f864b8b4b8f51493af930bd4d3a1b205a710e99add3
+
+ModSqrt = cf77c5c2d12a500b75cbfb1f3e66ee75d886b9365cf4f8b4d1bd18a6be0f387
+A = 4652ddc2ea7b460d8ec3c9059b8f9b5dae6cac55b51f2ad86fcb336b25235737965cc515e2ff0b54835015b7ebeeda6fadd986471d8cb424d309fc353d1e269
+P = a6813d316f9aca30f98b4f864b8b4b8f51493af930bd4d3a1b205a710e99add3
+
+ModSqrt = 1e0549e4c5a26023e9d24fd8c67419960746f82b1ecd113bdac66f570a475d87
+A = 5f4a6d450ab1390d96ab1deaa0ba18f897cb63daf0c9e1ef6c08e804c26b5e842f6c08f13db5d4a6e88f07af2a3cb04fa06fc3e59c410b9356f025ed81acc74
+P = a6813d316f9aca30f98b4f864b8b4b8f51493af930bd4d3a1b205a710e99add3
+
+ModSqrt = 144481a781d831c1ca046ca9e322d79ad4d2c6dd9f780bea9d1ced9cd20b7b23
+A = 4c254fabca441017132b9eacd4ca40a336db3e5c09715773fa07af095989a91cc968ff07a9ff56ed06b0ce0c5269f7b2ab68564ecab9f4467a7e96b6cc6b21b7
+P = a6813d316f9aca30f98b4f864b8b4b8f51493af930bd4d3a1b205a710e99add3
+
+ModSqrt = 216fecc7667f488a3d2d102a38b46b4860ab858300b8638af4f34e1103fd73ba
+A = 17878f8048227573a9d70f53c0e76ff13fe9f56e9c984c92514d3d13dec23c816661f0618d21371b80dfd885cb59551bdf80046f65f22ea9b89c78645a6e455a
+P = bd37c850cf7d702bac879f3c21a51a5a4df2b8eb0935861e0753a6eb62261a95
+
+ModSqrt = 458e5e789ccd2417174f7e30bb31914b9656bd8cf2b9f5a9752a8737a67707bc
+A = 5c7d39a4bb04e69201aa519f80ee7e62ea14ca55e13656d1da3f45367e2fb2d061aa2940708d02ac67d35cd2ccf54a1bf95bcbc759779e692cfdcbb3aa1a05b
+P = bd37c850cf7d702bac879f3c21a51a5a4df2b8eb0935861e0753a6eb62261a95
+
+ModSqrt = 543125a16c2bb8b8f8a2c39c497e5224ec77533602d7dbe24002e32dcbd2ef1a
+A = 3413afae333b2ad9ff45c7f3c7e5934b3127e8b1a55225958ee6ccf42423e81559bf070ad3f3353b78c0ffd41475af49f59d268ef78bdae879f5155e8d1cc07
+P = bd37c850cf7d702bac879f3c21a51a5a4df2b8eb0935861e0753a6eb62261a95
+
+ModSqrt = 10e16859c67bdb2eaab52a7c847dbf37162eda258a9f6262ebacfe4cbbbc1080
+A = 21ce7905894faf220bdf4a82a2d855994ca2dc9feaecaa53c7f146e1f49934215695e9bb46ba370b7005a90c399674caa8969eb442e7914d90f749774d7fd194
+P = bd37c850cf7d702bac879f3c21a51a5a4df2b8eb0935861e0753a6eb62261a95
+
+ModSqrt = 32a00586adc6f6cc2b1a04e1be0ab569fde235e1436c38b6af92bc5ebd60bc1c
+A = 350da4fd8cf03c12f7dd6ac6d3ab801a3413964083e374662aaf878d6838b97d4feb9e52cd307a25b113e101661a865463ee2480c626aa4e2ec437d72e7bae4c
+P = bd37c850cf7d702bac879f3c21a51a5a4df2b8eb0935861e0753a6eb62261a95
+
+ModSqrt = 971f75bc7afa8b4b50f1d4b05e52deac7d4836a08d30546f29649bf1ca6a247
+A = 655ed4c5d8d0afb4f9360372ee1ef1303898d2423e585108a3303faedb55064d2ef25666ed4c4d71fe6063fea1f3142b435714b0e30b339dd791d347c884654
+P = 9810151ad4bc9c5d68fc326395b509f2625bfebca1c3801ad4da7539fdbaa6f7
+
+ModSqrt = 48fa882b7cb6a29de9e3769f72eb67f1efd4d2af56f0c7e410c610efcbce2065
+A = 14f3503f33b243800eac1defaab33e04c01e80163fb3efd03860970cc016832431ca4fc6d1b760f4f40166b0b8b3c40dbebc81460cc10890172243770338f090
+P = 9810151ad4bc9c5d68fc326395b509f2625bfebca1c3801ad4da7539fdbaa6f7
+
+ModSqrt = 236fd7e397ea7f8bc2a288eb7236ca41936fa702b7dccca56c8852e147511f7d
+A = 1bbd0980feac854782813bcde4da85e8a054549a1b515e065da4236528035e756882e29e762cf60453e375cca9dc6ff637f9558bf86646e3b928f68f82af7efe
+P = 9810151ad4bc9c5d68fc326395b509f2625bfebca1c3801ad4da7539fdbaa6f7
+
+ModSqrt = 693f0cbe8c81b0afde0cd2f83e53795dcae6b0cc4ba930ab5c752400d787f14
+A = 7b20f9664b23907e152ab8c9a907f72e8670c1c38ab4cd1411ea7c2159c09aa131afe068929b8e6ad1409b74c04975180d1cd0a9fa74e923c3fd451e8da2c34
+P = 9810151ad4bc9c5d68fc326395b509f2625bfebca1c3801ad4da7539fdbaa6f7
+
+ModSqrt = 4a086c50b0bad576501ddb6280743b2c9d247841eb7f14d90561432ff7dca6f0
+A = 4367431ec0cd0d7626538b93a090c30fe0c97c18ca03b97ddae304b619112b5b4d02bf0f041fa3fd673f9ef2ceb07eb2079d11c56dd903b1a87e8252a97b8079
+P = 9810151ad4bc9c5d68fc326395b509f2625bfebca1c3801ad4da7539fdbaa6f7
+
+ModSqrt = 18f8433fa468d8065157708f1f1e53b8e31d39c6011fbc2bad93de1b5548e19c
+A = 739c032bb4139c199c40f548d37234298772e4ccb9d3ba28412b60ad23b4c465b0787e2382f1c5a4a87af2d20eb978b7dcbe73f2112249477d15c8a85e54a79
+P = adcd56924f73836ebe4dccfe006ad3b1e5076562cd11b161642cab7af2284659
+
+ModSqrt = 49e3c8eef5e067cabd51a7c01384ce05ab8f4342f655559d8a689eb7b20e0106
+A = 18400c2cc3e06b99b4e39c77b9af5ff0e9c683f1708321afa4cd5b6988d13b36b1d9eb4379b7902d9ceb40c03f814b2b6a01b90509bbb4532f13ab1571c4d04a
+P = adcd56924f73836ebe4dccfe006ad3b1e5076562cd11b161642cab7af2284659
+
+ModSqrt = 35548c530745f440329325cc8a5fbd90c16a7f0788879a4869bc4d4f73acda0e
+A = 181a3c5ab02566e7166c4d6d2f2bd4a8ecc25991a98d270bde80cf4332766a7068b14240bf5f5dcd45e90ef252596da3eb05b11d68b2063f7b3a825742593ca9
+P = adcd56924f73836ebe4dccfe006ad3b1e5076562cd11b161642cab7af2284659
+
+ModSqrt = 1ab7046e6af061ade5f9719008fa4d989007e2a579a134a5b9f19ec410984096
+A = 1008a03e211fab0d45856377079bc96b0776c2d4c0175661f3493246cea2ab0a02a706c85314fb707ad9906bedb2cfd577d62092ae08ff21d7b949373ea954c7
+P = adcd56924f73836ebe4dccfe006ad3b1e5076562cd11b161642cab7af2284659
+
+ModSqrt = 2be9e3e7515960d90f115b89f60dedc173a73ce163b4036e85b7b6a76fd90852
+A = 392053a9f0100540a8e1a0c353e922068a84dad3a4a8e8962fbc0bee2b6a06e20d08ade16eb1409a16acfcac3db5c43c421505e07035ca308b15c4a6db0864c0
+P = adcd56924f73836ebe4dccfe006ad3b1e5076562cd11b161642cab7af2284659
+
+ModSqrt = 5b301bb93bdcf050183107e36258b53b4805918114ea1c2227b0911d5b4dc077
+A = 55e55e5f94dc3d7aabc921f6469d85fa2e1e92a87347c57afad5872306ae69f9fb99297d1e3e793dd9e8632244208154de5da7114fd876383bf1422f7ece024
+P = d43280ac150f725f4a2a1dceb1c79bcac57855a4eba72ae93762d09bcb2444fb
+
+ModSqrt = 2df9609e2f5a5156c3260461b2ee52eacdef00bd8b091479813143a6c5283f71
+A = 2099325b7f12fe77353ddf3f2b2c5ef77b49671b150af954cf84e9675e3ecde3e057084641a633d19533b4712ab49924c8b5c31d591abcc88291f51253fa2a7
+P = d43280ac150f725f4a2a1dceb1c79bcac57855a4eba72ae93762d09bcb2444fb
+
+ModSqrt = dfab751710e9008e25e422d1199d6fbec4dc7fba35b4da9d225a746eb4126a0
+A = c006af53d4737fb293584df6ffe2e4cb3fd8dc77fb7c1f13b97bb9c249e3ee5fb9feff7488265b3093906c08a4946f142ac7b491937d24bfba6413366ce371d
+P = d43280ac150f725f4a2a1dceb1c79bcac57855a4eba72ae93762d09bcb2444fb
+
+ModSqrt = 26bc030008d6c60a09fb0e16093a649fcb40c6c21a8e2da2353ba4b07c4f85d5
+A = 1eaabcfad2ed349ac9356e6f4da0b301266ddde811cb0f817aba8f5c10fb8b8ba9d0ef2dd386b668f16eac296118fdb8cb7afe1b865648c81c2fa3cf21f2711b
+P = d43280ac150f725f4a2a1dceb1c79bcac57855a4eba72ae93762d09bcb2444fb
+
+ModSqrt = 35051b1482ec2578f3dc0000a422cb5111e43c37f1ac20b1844d3de2128c4556
+A = 315ff9de178681116f2a5fa78eebf4818e1d680435eacdfaf9d0e5c4fc01fc034b352c82fd52c81ca30d68864952dacc99d08269c9dd7ca99ccf22da98c3840
+P = d43280ac150f725f4a2a1dceb1c79bcac57855a4eba72ae93762d09bcb2444fb
+
+ModSqrt = a5474252885cacf004c460a7793ff0b0a2187bb1a9ed700ae3470199faef71f
+A = 19856fc1351c4b02abf573bb2fc6ff92355fa369d62bb8f2260fa772fb1693f509a56cad661930abcac049dd70f4b16bed4a4c172e73e772504c9990ce7f92f
+P = dc315fd52684fba79e577a204de9053b11a5d7a414263fec9eff6ff62188829d
+
+ModSqrt = 12daf4722387ecf47de1b0b6b110a062dc5ea2685bc9dbde66b8d15622985029
+A = fb8479787069116abc42abfd7dc0c24d2ad04fe0c04b42a6dff714af715d17e0fd77855f950f264542b06d48e8818de813ddb7975798b7debefcdaa5ff86beb
+P = dc315fd52684fba79e577a204de9053b11a5d7a414263fec9eff6ff62188829d
+
+ModSqrt = 397996ed5c0ac6ad32e43c337e9de421b87774cc162bf7ac7bbedf4a9029255e
+A = 5aa04353321bd2de92481be740357f979da464b53aa39111fdbb734cf7af6b3857d1baa08d3a126a3dd34a2fbae2bf2b84e900686c1d31505b390185acef5fe5
+P = dc315fd52684fba79e577a204de9053b11a5d7a414263fec9eff6ff62188829d
+
+ModSqrt = 2cf4b844a54ba359dc592ef1b49f43fcfeae84d1087edfefdd0b9174b43c0a3c
+A = 365a8650510bcfd8fa87432f167cf487234c215857403b9270b5eebeafa48cd6da47fd60dc311b94d1d72baad0447c31f0b212d755f46c256e16e5e015e6546e
+P = dc315fd52684fba79e577a204de9053b11a5d7a414263fec9eff6ff62188829d
+
+ModSqrt = 9277c73043ff767c3fa606f0cd66b9d854a600c8c18287f191ce277758c3f31
+A = 62cec3901626d03e8df66299a87c54b1f7a55cafc99f0b6bba1b5d51a3d2b7d2171c9135a9d8a5346d436e0136b12e515e703e3cd84ecfe154eb94c6772a6d72
+P = dc315fd52684fba79e577a204de9053b11a5d7a414263fec9eff6ff62188829d
+
+ModSqrt = 4189e5a90c1b1abdc1c7c05b3587e6f362e06f927b6cf5f0d271aab3d6f90765
+A = 336b8d0f9dac842c696bc020f49c6aa023842c16f2052eb02f17959006554ca0012042c80c72590f21c6bf5a3714c9cb552aa69730e33db93a56a909b273f39
+P = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951f
+
+ModSqrt = 36ccd38cb5a6bd8a73bca55936a2227c503664422c2296faf7e2b1c6a375a43a
+A = fecfd60a376befbe48d2c4f6d070d716d2f403cd5daefbce62b720df44deb605162c8f20f49fd7ec30d4f8e70d803d45b3a44b5d912baa3410d991165d7c507
+P = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951f
+
+ModSqrt = 198fc8569be172dc9b71023ed3d42d2ba94bae4099643f6517ab03f540527fdb
+A = 65bebdb00a96fc814ec44b81f98b59fba3c30203928fa5214c51e0a97091645280c947b005847f239758482b9bfc45b066fde340d1fe32fc9c1bf02e1b2d0ec
+P = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951f
+
+ModSqrt = 21b7f74c30ded681d6138cf8e6fd798f32a049e94138e982f1845df3dc9e686f
+A = 9a30b791c1ba4f394b4e3dcd5837e474237f4fe8987b255c098a47b2c14c598ec69d2beae444dd4fe9c4ede8173d2b187677cc706a3c28f3b81627d8a5fb6fd
+P = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951f
+
+ModSqrt = a1d52989f12f204d3d2167d9b1e6c8a6174c0c786a979a5952383b7b8bd186
+A = 2eee37cf06228a387788188e650bc6d8a2ff402931443f69156a29155eca07dcb45f3aac238d92943c0c25c896098716baa433f25bd696a142f5a69d5d937e81
+P = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951f
+
+
+# NotModSquare tests.
+#
+# These test vectors are such that NotModSquare is not a square modulo P.
+
+NotModSquare = 03
+P = 07
+
+NotModSquare = 05
+P = 07
+
+NotModSquare = 06
+P = 07
+
+NotModSquare = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951e
+P = 9df9d6cc20b8540411af4e5357ef2b0353cb1f2ab5ffc3e246b41c32f71e951f
+
+
+# ModInv tests.
+#
+# These test vectors satisfy ModInv * A = 1 (mod M) and 0 <= ModInv < M.
+
+ModInv = 00
+A = 00
+M = 01
+
+ModInv = 00
+A = 01
+M = 01
+
+ModInv = 00
+A = 02
+M = 01
+
+ModInv = 00
+A = 03
+M = 01
diff --git a/src/crypto/bn/check_bn_tests.go b/src/crypto/bn/check_bn_tests.go
new file mode 100644
index 0000000..34cefbb
--- /dev/null
+++ b/src/crypto/bn/check_bn_tests.go
@@ -0,0 +1,262 @@
+// Copyright (c) 2016, Google Inc.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+package main
+
+import (
+	"bufio"
+	"errors"
+	"fmt"
+	"io"
+	"math/big"
+	"os"
+	"strings"
+)
+
+type test struct {
+	LineNumber int
+	Type       string
+	Values     map[string]*big.Int
+}
+
+type testScanner struct {
+	scanner *bufio.Scanner
+	lineNo  int
+	err     error
+	test    test
+}
+
+func newTestScanner(r io.Reader) *testScanner {
+	return &testScanner{scanner: bufio.NewScanner(r)}
+}
+
+func (s *testScanner) scanLine() bool {
+	if !s.scanner.Scan() {
+		return false
+	}
+	s.lineNo++
+	return true
+}
+
+func (s *testScanner) addAttribute(line string) (key string, ok bool) {
+	fields := strings.SplitN(line, "=", 2)
+	if len(fields) != 2 {
+		s.setError(errors.New("invalid syntax"))
+		return "", false
+	}
+
+	key = strings.TrimSpace(fields[0])
+	value := strings.TrimSpace(fields[1])
+
+	valueInt, ok := new(big.Int).SetString(value, 16)
+	if !ok {
+		s.setError(fmt.Errorf("could not parse %q", value))
+		return "", false
+	}
+	if _, dup := s.test.Values[key]; dup {
+		s.setError(fmt.Errorf("duplicate key %q", key))
+		return "", false
+	}
+	s.test.Values[key] = valueInt
+	return key, true
+}
+
+func (s *testScanner) Scan() bool {
+	s.test = test{
+		Values: make(map[string]*big.Int),
+	}
+
+	// Scan until the first attribute.
+	for {
+		if !s.scanLine() {
+			return false
+		}
+		if len(s.scanner.Text()) != 0 && s.scanner.Text()[0] != '#' {
+			break
+		}
+	}
+
+	var ok bool
+	s.test.Type, ok = s.addAttribute(s.scanner.Text())
+	if !ok {
+		return false
+	}
+	s.test.LineNumber = s.lineNo
+
+	for s.scanLine() {
+		if len(s.scanner.Text()) == 0 {
+			break
+		}
+
+		if s.scanner.Text()[0] == '#' {
+			continue
+		}
+
+		if _, ok := s.addAttribute(s.scanner.Text()); !ok {
+			return false
+		}
+	}
+	return s.scanner.Err() == nil
+}
+
+func (s *testScanner) Test() test {
+	return s.test
+}
+
+func (s *testScanner) Err() error {
+	if s.err != nil {
+		return s.err
+	}
+	return s.scanner.Err()
+}
+
+func (s *testScanner) setError(err error) {
+	s.err = fmt.Errorf("line %d: %s", s.lineNo, err)
+}
+
+func checkKeys(t test, keys ...string) bool {
+	var foundErrors bool
+
+	for _, k := range keys {
+		if _, ok := t.Values[k]; !ok {
+			fmt.Fprintf(os.Stderr, "Line %d: missing key %q.\n", t.LineNumber, k)
+			foundErrors = true
+		}
+	}
+
+	for k, _ := range t.Values {
+		var found bool
+		for _, k2 := range keys {
+			if k == k2 {
+				found = true
+				break
+			}
+		}
+		if !found {
+			fmt.Fprintf(os.Stderr, "Line %d: unexpected key %q.\n", t.LineNumber, k)
+			foundErrors = true
+		}
+	}
+
+	return !foundErrors
+}
+
+func checkResult(t test, expr, key string, r *big.Int) {
+	if t.Values[key].Cmp(r) != 0 {
+		fmt.Fprintf(os.Stderr, "Line %d: %s did not match %s.\n\tGot %s\n", t.LineNumber, expr, key, r.Text(16))
+	}
+}
+
+func main() {
+	if len(os.Args) != 2 {
+		fmt.Fprintf(os.Stderr, "Usage: %s bn_tests.txt\n", os.Args[0])
+		os.Exit(1)
+	}
+
+	in, err := os.Open(os.Args[1])
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "Error opening %s: %s.\n", os.Args[0], err)
+		os.Exit(1)
+	}
+	defer in.Close()
+
+	scanner := newTestScanner(in)
+	for scanner.Scan() {
+		test := scanner.Test()
+		switch test.Type {
+		case "Sum":
+			if checkKeys(test, "A", "B", "Sum") {
+				r := new(big.Int).Add(test.Values["A"], test.Values["B"])
+				checkResult(test, "A + B", "Sum", r)
+			}
+		case "LShift1":
+			if checkKeys(test, "A", "LShift1") {
+				r := new(big.Int).Add(test.Values["A"], test.Values["A"])
+				checkResult(test, "A + A", "LShift1", r)
+			}
+		case "LShift":
+			if checkKeys(test, "A", "N", "LShift") {
+				r := new(big.Int).Lsh(test.Values["A"], uint(test.Values["N"].Uint64()))
+				checkResult(test, "A << N", "LShift", r)
+			}
+		case "RShift":
+			if checkKeys(test, "A", "N", "RShift") {
+				r := new(big.Int).Rsh(test.Values["A"], uint(test.Values["N"].Uint64()))
+				checkResult(test, "A >> N", "RShift", r)
+			}
+		case "Square":
+			if checkKeys(test, "A", "Square") {
+				r := new(big.Int).Mul(test.Values["A"], test.Values["A"])
+				checkResult(test, "A * A", "Square", r)
+			}
+		case "Product":
+			if checkKeys(test, "A", "B", "Product") {
+				r := new(big.Int).Mul(test.Values["A"], test.Values["B"])
+				checkResult(test, "A * B", "Product", r)
+			}
+		case "Quotient":
+			if checkKeys(test, "A", "B", "Quotient", "Remainder") {
+				q, r := new(big.Int).QuoRem(test.Values["A"], test.Values["B"], new(big.Int))
+				checkResult(test, "A / B", "Quotient", q)
+				checkResult(test, "A % B", "Remainder", r)
+			}
+		case "ModMul":
+			if checkKeys(test, "A", "B", "M", "ModMul") {
+				r := new(big.Int).Mul(test.Values["A"], test.Values["B"])
+				r = r.Mod(r, test.Values["M"])
+				checkResult(test, "A * B (mod M)", "ModMul", r)
+			}
+		case "ModExp":
+			if checkKeys(test, "A", "E", "M", "ModExp") {
+				r := new(big.Int).Exp(test.Values["A"], test.Values["E"], test.Values["M"])
+				checkResult(test, "A ^ E (mod M)", "ModExp", r)
+			}
+		case "Exp":
+			if checkKeys(test, "A", "E", "Exp") {
+				r := new(big.Int).Exp(test.Values["A"], test.Values["E"], nil)
+				checkResult(test, "A ^ E", "Exp", r)
+			}
+		case "ModSqrt":
+			bigOne := new(big.Int).SetInt64(1)
+			bigTwo := new(big.Int).SetInt64(2)
+
+			if checkKeys(test, "A", "P", "ModSqrt") {
+				test.Values["A"].Mod(test.Values["A"], test.Values["P"])
+
+				r := new(big.Int).Mul(test.Values["ModSqrt"], test.Values["ModSqrt"])
+				r = r.Mod(r, test.Values["P"])
+				checkResult(test, "ModSqrt ^ 2 (mod P)", "A", r)
+
+				if test.Values["P"].Cmp(bigTwo) > 0 {
+					pMinus1Over2 := new(big.Int).Sub(test.Values["P"], bigOne)
+					pMinus1Over2.Rsh(pMinus1Over2, 1)
+
+					if test.Values["ModSqrt"].Cmp(pMinus1Over2) > 0 {
+						fmt.Fprintf(os.Stderr, "Line %d: ModSqrt should be minimal.\n", test.LineNumber)
+					}
+				}
+			}
+		case "ModInv":
+			if checkKeys(test, "A", "M", "ModInv") {
+				r := new(big.Int).ModInverse(test.Values["A"], test.Values["M"])
+				checkResult(test, "A ^ -1 (mod M)", "ModInv", r)
+			}
+		default:
+			fmt.Fprintf(os.Stderr, "Line %d: unknown test type %q.\n", test.LineNumber, test.Type)
+		}
+	}
+	if scanner.Err() != nil {
+		fmt.Fprintf(os.Stderr, "Error reading tests: %s.\n", scanner.Err())
+	}
+}
diff --git a/src/crypto/bn/cmp.c b/src/crypto/bn/cmp.c
index fce7233..71c0465 100644
--- a/src/crypto/bn/cmp.c
+++ b/src/crypto/bn/cmp.c
@@ -56,6 +56,8 @@
 
 #include <openssl/bn.h>
 
+#include <openssl/mem.h>
+
 #include "internal.h"
 
 
@@ -183,6 +185,17 @@
   }
 }
 
+int BN_cmp_word(const BIGNUM *a, BN_ULONG b) {
+  BIGNUM b_bn;
+  BN_init(&b_bn);
+
+  b_bn.d = &b;
+  b_bn.top = b > 0;
+  b_bn.dmax = 1;
+  b_bn.flags = BN_FLG_STATIC_DATA;
+  return BN_cmp(a, &b_bn);
+}
+
 int BN_is_zero(const BIGNUM *bn) {
   return bn->top == 0;
 }
@@ -198,3 +211,29 @@
 int BN_is_odd(const BIGNUM *bn) {
   return bn->top > 0 && (bn->d[0] & 1) == 1;
 }
+
+int BN_is_pow2(const BIGNUM *bn) {
+  if (bn->top == 0 || bn->neg) {
+    return 0;
+  }
+
+  for (int i = 0; i < bn->top - 1; i++) {
+    if (bn->d[i] != 0) {
+      return 0;
+    }
+  }
+
+  return 0 == (bn->d[bn->top-1] & (bn->d[bn->top-1] - 1));
+}
+
+int BN_equal_consttime(const BIGNUM *a, const BIGNUM *b) {
+  if (a->top != b->top) {
+    return 0;
+  }
+
+  int limbs_are_equal =
+    CRYPTO_memcmp(a->d, b->d, (size_t)a->top * sizeof(a->d[0])) == 0;
+
+  return constant_time_select_int(constant_time_eq_int(a->neg, b->neg),
+                                  limbs_are_equal, 0);
+}
diff --git a/src/crypto/bn/convert.c b/src/crypto/bn/convert.c
index 8646e59..1fa0dd4 100644
--- a/src/crypto/bn/convert.c
+++ b/src/crypto/bn/convert.c
@@ -118,6 +118,42 @@
   return ret;
 }
 
+BIGNUM *BN_le2bn(const uint8_t *in, size_t len, BIGNUM *ret) {
+  BIGNUM *bn = NULL;
+  if (ret == NULL) {
+    bn = BN_new();
+    ret = bn;
+  }
+
+  if (ret == NULL) {
+    return NULL;
+  }
+
+  if (len == 0) {
+    ret->top = 0;
+    ret->neg = 0;
+    return ret;
+  }
+
+  /* Reserve enough space in |ret|. */
+  size_t num_words = ((len - 1) / BN_BYTES) + 1;
+  if (!bn_wexpand(ret, num_words)) {
+    BN_free(bn);
+    return NULL;
+  }
+  ret->top = num_words;
+
+  /* Make sure the top bytes will be zeroed. */
+  ret->d[num_words - 1] = 0;
+
+  /* We only support little-endian platforms, so we can simply memcpy the
+   * internal representation. */
+  OPENSSL_memcpy(ret->d, in, len);
+
+  bn_correct_top(ret);
+  return ret;
+}
+
 size_t BN_bn2bin(const BIGNUM *in, uint8_t *out) {
   size_t n, i;
   BN_ULONG l;
@@ -130,6 +166,23 @@
   return n;
 }
 
+int BN_bn2le_padded(uint8_t *out, size_t len, const BIGNUM *in) {
+  /* If we don't have enough space, fail out. */
+  size_t num_bytes = BN_num_bytes(in);
+  if (len < num_bytes) {
+    return 0;
+  }
+
+  /* We only support little-endian platforms, so we can simply memcpy into the
+   * internal representation. */
+  OPENSSL_memcpy(out, in->d, num_bytes);
+
+  /* Pad out the rest of the buffer with zeroes. */
+  OPENSSL_memset(out + num_bytes, 0, len - num_bytes);
+
+  return 1;
+}
+
 /* constant_time_select_ulong returns |x| if |v| is 1 and |y| if |v| is 0. Its
  * behavior is undefined if |v| takes any other value. */
 static BN_ULONG constant_time_select_ulong(int v, BN_ULONG x, BN_ULONG y) {
@@ -160,12 +213,9 @@
 }
 
 int BN_bn2bin_padded(uint8_t *out, size_t len, const BIGNUM *in) {
-  size_t i;
-  BN_ULONG l;
-
   /* Special case for |in| = 0. Just branch as the probability is negligible. */
   if (BN_is_zero(in)) {
-    memset(out, 0, len);
+    OPENSSL_memset(out, 0, len);
     return 1;
   }
 
@@ -175,7 +225,7 @@
     return 0;
   }
   if ((len % BN_BYTES) != 0) {
-    l = read_word_padded(in, len / BN_BYTES);
+    BN_ULONG l = read_word_padded(in, len / BN_BYTES);
     if (l >> (8 * (len % BN_BYTES)) != 0) {
       return 0;
     }
@@ -188,9 +238,9 @@
    * leading zero octets is low.
    *
    * See Falko Stenzke, "Manger's Attack revisited", ICICS 2010. */
-  i = len;
+  size_t i = len;
   while (i--) {
-    l = read_word_padded(in, i / BN_BYTES);
+    BN_ULONG l = read_word_padded(in, i / BN_BYTES);
     *(out++) = (uint8_t)(l >> (8 * (i % BN_BYTES))) & 0xff;
   }
   return 1;
@@ -204,17 +254,14 @@
 static const char hextable[] = "0123456789abcdef";
 
 char *BN_bn2hex(const BIGNUM *bn) {
-  int i, j, v, z = 0;
-  char *buf;
-  char *p;
-
-  buf = (char *)OPENSSL_malloc(bn->top * BN_BYTES * 2 + 2);
+  char *buf = OPENSSL_malloc(1 /* leading '-' */ + 1 /* zero is non-empty */ +
+                             bn->top * BN_BYTES * 2 + 1 /* trailing NUL */);
   if (buf == NULL) {
     OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
     return NULL;
   }
 
-  p = buf;
+  char *p = buf;
   if (bn->neg) {
     *(p++) = '-';
   }
@@ -223,10 +270,11 @@
     *(p++) = '0';
   }
 
-  for (i = bn->top - 1; i >= 0; i--) {
-    for (j = BN_BITS2 - 8; j >= 0; j -= 8) {
+  int z = 0;
+  for (int i = bn->top - 1; i >= 0; i--) {
+    for (int j = BN_BITS2 - 8; j >= 0; j -= 8) {
       /* strip leading zeros */
-      v = ((int)(bn->d[i] >> (long)j)) & 0xff;
+      int v = ((int)(bn->d[i] >> (long)j)) & 0xff;
       if (z || v != 0) {
         *(p++) = hextable[v >> 4];
         *(p++) = hextable[v & 0x0f];
@@ -398,8 +446,7 @@
       }
 
       const int add_leading_zeros = !BN_is_zero(copy);
-      int i;
-      for (i = 0; i < BN_DEC_NUM && (add_leading_zeros || word != 0); i++) {
+      for (int i = 0; i < BN_DEC_NUM && (add_leading_zeros || word != 0); i++) {
         if (!CBB_add_u8(&cbb, '0' + word % 10)) {
           goto cbb_err;
         }
@@ -421,8 +468,7 @@
   }
 
   /* Reverse the buffer. */
-  size_t i;
-  for (i = 0; i < len/2; i++) {
+  for (size_t i = 0; i < len/2; i++) {
     uint8_t tmp = data[i];
     data[i] = data[len - 1 - i];
     data[len - 1 - i] = tmp;
@@ -522,6 +568,24 @@
   }
 }
 
+int BN_get_u64(const BIGNUM *bn, uint64_t *out) {
+  switch (bn->top) {
+    case 0:
+      *out = 0;
+      return 1;
+    case 1:
+      *out = bn->d[0];
+      return 1;
+#if defined(OPENSSL_32_BIT)
+    case 2:
+      *out = (uint64_t) bn->d[0] | (((uint64_t) bn->d[1]) << 32);
+      return 1;
+#endif
+    default:
+      return 0;
+  }
+}
+
 size_t BN_bn2mpi(const BIGNUM *in, uint8_t *out) {
   const size_t bits = BN_num_bits(in);
   const size_t bytes = (bits + 7) / 8;
@@ -539,7 +603,7 @@
     /* If we cannot represent the number then we emit zero as the interface
      * doesn't allow an error to be signalled. */
     if (out) {
-      memset(out, 0, 4);
+      OPENSSL_memset(out, 0, 4);
     }
     return 4;
   }
@@ -576,12 +640,14 @@
     return NULL;
   }
 
+  int out_is_alloced = 0;
   if (out == NULL) {
     out = BN_new();
-  }
-  if (out == NULL) {
-    OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
-    return NULL;
+    if (out == NULL) {
+      OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
+      return NULL;
+    }
+    out_is_alloced = 1;
   }
 
   if (in_len == 0) {
@@ -591,6 +657,9 @@
 
   in += 4;
   if (BN_bin2bn(in, in_len, out) == NULL) {
+    if (out_is_alloced) {
+      BN_free(out);
+    }
     return NULL;
   }
   out->neg = ((*in) & 0x80) != 0;
diff --git a/src/crypto/bn/ctx.c b/src/crypto/bn/ctx.c
index 48d9adf..bca6619 100644
--- a/src/crypto/bn/ctx.c
+++ b/src/crypto/bn/ctx.c
@@ -59,6 +59,8 @@
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
+#include "../internal.h"
+
 
 /* How many bignums are in each "pool item"; */
 #define BN_CTX_POOL_SIZE 16
@@ -218,7 +220,7 @@
       return 0;
     }
     if (st->depth) {
-      memcpy(newitems, st->indexes, st->depth * sizeof(unsigned int));
+      OPENSSL_memcpy(newitems, st->indexes, st->depth * sizeof(unsigned int));
     }
     OPENSSL_free(st->indexes);
     st->indexes = newitems;
diff --git a/src/crypto/bn/div.c b/src/crypto/bn/div.c
index f9e144a..de3fa1f 100644
--- a/src/crypto/bn/div.c
+++ b/src/crypto/bn/div.c
@@ -56,62 +56,139 @@
 
 #include <openssl/bn.h>
 
+#include <assert.h>
 #include <limits.h>
+
 #include <openssl/err.h>
 
 #include "internal.h"
 
 
-#define asm __asm__
+#if !defined(BN_ULLONG)
+/* bn_div_words divides a double-width |h|,|l| by |d| and returns the result,
+ * which must fit in a |BN_ULONG|. */
+static BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) {
+  BN_ULONG dh, dl, q, ret = 0, th, tl, t;
+  int i, count = 2;
 
-#if !defined(OPENSSL_NO_ASM)
-# if defined(__GNUC__) && __GNUC__>=2
-#  if defined(OPENSSL_X86)
-   /*
-    * There were two reasons for implementing this template:
-    * - GNU C generates a call to a function (__udivdi3 to be exact)
-    *   in reply to ((((BN_ULLONG)n0)<<BN_BITS2)|n1)/d0 (I fail to
-    *   understand why...);
-    * - divl doesn't only calculate quotient, but also leaves
-    *   remainder in %edx which we can definitely use here:-)
-    *
-    *					<appro@fy.chalmers.se>
-    */
-#undef div_asm
-#  define div_asm(n0,n1,d0)		\
-	({  asm volatile (			\
-		"divl	%4"			\
-		: "=a"(q), "=d"(rem)		\
-		: "a"(n1), "d"(n0), "g"(d0)	\
-		: "cc");			\
-	    q;					\
-	})
-#  define REMAINDER_IS_ALREADY_CALCULATED
-#  elif defined(OPENSSL_X86_64)
-   /*
-    * Same story here, but it's 128-bit by 64-bit division. Wow!
-    *					<appro@fy.chalmers.se>
-    */
-#  undef div_asm
-#  define div_asm(n0,n1,d0)		\
-	({  asm volatile (			\
-		"divq	%4"			\
-		: "=a"(q), "=d"(rem)		\
-		: "a"(n1), "d"(n0), "g"(d0)	\
-		: "cc");			\
-	    q;					\
-	})
-#  define REMAINDER_IS_ALREADY_CALCULATED
-#  endif /* __<cpu> */
-# endif /* __GNUC__ */
-#endif /* OPENSSL_NO_ASM */
+  if (d == 0) {
+    return BN_MASK2;
+  }
+
+  i = BN_num_bits_word(d);
+  assert((i == BN_BITS2) || (h <= (BN_ULONG)1 << i));
+
+  i = BN_BITS2 - i;
+  if (h >= d) {
+    h -= d;
+  }
+
+  if (i) {
+    d <<= i;
+    h = (h << i) | (l >> (BN_BITS2 - i));
+    l <<= i;
+  }
+  dh = (d & BN_MASK2h) >> BN_BITS4;
+  dl = (d & BN_MASK2l);
+  for (;;) {
+    if ((h >> BN_BITS4) == dh) {
+      q = BN_MASK2l;
+    } else {
+      q = h / dh;
+    }
+
+    th = q * dh;
+    tl = dl * q;
+    for (;;) {
+      t = h - th;
+      if ((t & BN_MASK2h) ||
+          ((tl) <= ((t << BN_BITS4) | ((l & BN_MASK2h) >> BN_BITS4)))) {
+        break;
+      }
+      q--;
+      th -= dh;
+      tl -= dl;
+    }
+    t = (tl >> BN_BITS4);
+    tl = (tl << BN_BITS4) & BN_MASK2h;
+    th += t;
+
+    if (l < tl) {
+      th++;
+    }
+    l -= tl;
+    if (h < th) {
+      h += d;
+      q--;
+    }
+    h -= th;
+
+    if (--count == 0) {
+      break;
+    }
+
+    ret = q << BN_BITS4;
+    h = ((h << BN_BITS4) | (l >> BN_BITS4)) & BN_MASK2;
+    l = (l & BN_MASK2l) << BN_BITS4;
+  }
+
+  ret |= q;
+  return ret;
+}
+#endif /* !defined(BN_ULLONG) */
+
+static inline void bn_div_rem_words(BN_ULONG *quotient_out, BN_ULONG *rem_out,
+                                    BN_ULONG n0, BN_ULONG n1, BN_ULONG d0) {
+  /* GCC and Clang generate function calls to |__udivdi3| and |__umoddi3| when
+   * the |BN_ULLONG|-based C code is used.
+   *
+   * GCC bugs:
+   *   * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=14224
+   *   * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=43721
+   *   * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54183
+   *   * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58897
+   *   * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65668
+   *
+   * Clang bugs:
+   *   * https://llvm.org/bugs/show_bug.cgi?id=6397
+   *   * https://llvm.org/bugs/show_bug.cgi?id=12418
+   *
+   * These issues aren't specific to x86 and x86_64, so it might be worthwhile
+   * to add more assembly language implementations. */
+#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86) && defined(__GNUC__)
+  __asm__ volatile (
+    "divl %4"
+    : "=a"(*quotient_out), "=d"(*rem_out)
+    : "a"(n1), "d"(n0), "rm"(d0)
+    : "cc" );
+#elif !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && defined(__GNUC__)
+  __asm__ volatile (
+    "divq %4"
+    : "=a"(*quotient_out), "=d"(*rem_out)
+    : "a"(n1), "d"(n0), "rm"(d0)
+    : "cc" );
+#else
+#if defined(BN_ULLONG)
+  BN_ULLONG n = (((BN_ULLONG)n0) << BN_BITS2) | n1;
+  *quotient_out = (BN_ULONG)(n / d0);
+#else
+  *quotient_out = bn_div_words(n0, n1, d0);
+#endif
+  *rem_out = n1 - (*quotient_out * d0);
+#endif
+}
 
 /* BN_div computes  dv := num / divisor,  rounding towards
  * zero, and sets up rm  such that  dv*divisor + rm = num  holds.
  * Thus:
  *     dv->neg == num->neg ^ divisor->neg  (unless the result is zero)
  *     rm->neg == num->neg                 (unless the remainder is zero)
- * If 'dv' or 'rm' is NULL, the respective value is not returned. */
+ * If 'dv' or 'rm' is NULL, the respective value is not returned.
+ *
+ * This was specifically designed to contain fewer branches that may leak
+ * sensitive information; see "New Branch Prediction Vulnerabilities in OpenSSL
+ * and Necessary Software Countermeasures" by Onur Acıçmez, Shay Gueron, and
+ * Jean-Pierre Seifert. */
 int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
            BN_CTX *ctx) {
   int norm_shift, i, loop;
@@ -119,7 +196,6 @@
   BN_ULONG *resp, *wnump;
   BN_ULONG d0, d1;
   int num_n, div_n;
-  int no_branch = 0;
 
   /* Invalid zero-padding would have particularly bad consequences
    * so don't just rely on bn_check_top() here */
@@ -129,28 +205,11 @@
     return 0;
   }
 
-  if ((num->flags & BN_FLG_CONSTTIME) != 0 ||
-      (divisor->flags & BN_FLG_CONSTTIME) != 0) {
-    no_branch = 1;
-  }
-
   if (BN_is_zero(divisor)) {
     OPENSSL_PUT_ERROR(BN, BN_R_DIV_BY_ZERO);
     return 0;
   }
 
-  if (!no_branch && BN_ucmp(num, divisor) < 0) {
-    if (rm != NULL) {
-      if (BN_copy(rm, num) == NULL) {
-        return 0;
-      }
-    }
-    if (dv != NULL) {
-      BN_zero(dv);
-    }
-    return 1;
-  }
-
   BN_CTX_start(ctx);
   tmp = BN_CTX_get(ctx);
   snum = BN_CTX_get(ctx);
@@ -176,26 +235,23 @@
   }
   snum->neg = 0;
 
-  if (no_branch) {
-    /* Since we don't know whether snum is larger than sdiv,
-     * we pad snum with enough zeroes without changing its
-     * value.
-     */
-    if (snum->top <= sdiv->top + 1) {
-      if (bn_wexpand(snum, sdiv->top + 2) == NULL) {
-        goto err;
-      }
-      for (i = snum->top; i < sdiv->top + 2; i++) {
-        snum->d[i] = 0;
-      }
-      snum->top = sdiv->top + 2;
-    } else {
-      if (bn_wexpand(snum, snum->top + 1) == NULL) {
-        goto err;
-      }
-      snum->d[snum->top] = 0;
-      snum->top++;
+  /* Since we don't want to have special-case logic for the case where snum is
+   * larger than sdiv, we pad snum with enough zeroes without changing its
+   * value. */
+  if (snum->top <= sdiv->top + 1) {
+    if (bn_wexpand(snum, sdiv->top + 2) == NULL) {
+      goto err;
     }
+    for (i = snum->top; i < sdiv->top + 2; i++) {
+      snum->d[i] = 0;
+    }
+    snum->top = sdiv->top + 2;
+  } else {
+    if (bn_wexpand(snum, snum->top + 1) == NULL) {
+      goto err;
+    }
+    snum->d[snum->top] = 0;
+    snum->top++;
   }
 
   div_n = sdiv->top;
@@ -223,7 +279,7 @@
   if (!bn_wexpand(res, (loop + 1))) {
     goto err;
   }
-  res->top = loop - no_branch;
+  res->top = loop - 1;
   resp = &(res->d[loop - 1]);
 
   /* space for temp */
@@ -231,15 +287,6 @@
     goto err;
   }
 
-  if (!no_branch) {
-    if (BN_ucmp(&wnum, sdiv) >= 0) {
-      bn_sub_words(wnum.d, wnum.d, sdiv->d, div_n);
-      *resp = 1;
-    } else {
-      res->top--;
-    }
-  }
-
   /* if res->top == 0 then clear the neg value otherwise decrease
    * the resp pointer */
   if (res->top == 0) {
@@ -260,23 +307,10 @@
       q = BN_MASK2;
     } else {
       /* n0 < d0 */
+      bn_div_rem_words(&q, &rem, n0, n1, d0);
+
 #ifdef BN_ULLONG
-      BN_ULLONG t2;
-
-#if defined(BN_ULLONG) && !defined(div_asm)
-      q = (BN_ULONG)(((((BN_ULLONG)n0) << BN_BITS2) | n1) / d0);
-#else
-      q = div_asm(n0, n1, d0);
-#endif
-
-#ifndef REMAINDER_IS_ALREADY_CALCULATED
-      /* rem doesn't have to be BN_ULLONG. The least we know it's less that d0,
-       * isn't it? */
-      rem = (n1 - q * d0) & BN_MASK2;
-#endif
-
-      t2 = (BN_ULLONG)d1 * q;
-
+      BN_ULLONG t2 = (BN_ULLONG)d1 * q;
       for (;;) {
         if (t2 <= ((((BN_ULLONG)rem) << BN_BITS2) | wnump[-2])) {
           break;
@@ -290,33 +324,7 @@
       }
 #else /* !BN_ULLONG */
       BN_ULONG t2l, t2h;
-
-#if defined(div_asm)
-      q = div_asm(n0, n1, d0);
-#else
-      q = bn_div_words(n0, n1, d0);
-#endif
-
-#ifndef REMAINDER_IS_ALREADY_CALCULATED
-      rem = (n1 - q * d0) & BN_MASK2;
-#endif
-
-#if defined(BN_UMULT_LOHI)
       BN_UMULT_LOHI(t2l, t2h, d1, q);
-#elif defined(BN_UMULT_HIGH)
-      t2l = d1 * q;
-      t2h = BN_UMULT_HIGH(d1, q);
-#else
-      {
-        BN_ULONG ql, qh;
-        t2l = LBITS(d1);
-        t2h = HBITS(d1);
-        ql = LBITS(q);
-        qh = HBITS(q);
-        mul64(t2l, t2h, ql, qh); /* t2=(BN_ULLONG)d1*q; */
-      }
-#endif
-
       for (;;) {
         if ((t2h < rem) || ((t2h == rem) && (t2l <= wnump[-2]))) {
           break;
@@ -369,9 +377,7 @@
       rm->neg = neg;
     }
   }
-  if (no_branch) {
-    bn_correct_top(res);
-  }
+  bn_correct_top(res);
   BN_CTX_end(ctx);
   return 1;
 
@@ -576,7 +582,7 @@
     return 0;
   }
 
-  /* normalize input (so bn_div_words doesn't complain) */
+  /* normalize input for |bn_div_rem_words|. */
   j = BN_BITS2 - BN_num_bits_word(w);
   w <<= j;
   if (!BN_lshift(a, a, j)) {
@@ -584,10 +590,10 @@
   }
 
   for (i = a->top - 1; i >= 0; i--) {
-    BN_ULONG l, d;
-
-    l = a->d[i];
-    d = bn_div_words(ret, l, w);
+    BN_ULONG l = a->d[i];
+    BN_ULONG d;
+    BN_ULONG unused_rem;
+    bn_div_rem_words(&d, &unused_rem, ret, l, w);
     ret = (l - ((d * w) & BN_MASK2)) & BN_MASK2;
     a->d[i] = d;
   }
@@ -596,6 +602,10 @@
     a->top--;
   }
 
+  if (a->top == 0) {
+    a->neg = 0;
+  }
+
   ret >>= j;
   return ret;
 }
@@ -612,6 +622,20 @@
     return (BN_ULONG) -1;
   }
 
+#ifndef BN_ULLONG
+  /* If |w| is too long and we don't have |BN_ULLONG| then we need to fall back
+   * to using |BN_div_word|. */
+  if (w > ((BN_ULONG)1 << BN_BITS4)) {
+    BIGNUM *tmp = BN_dup(a);
+    if (tmp == NULL) {
+      return (BN_ULONG)-1;
+    }
+    ret = BN_div_word(tmp, w);
+    BN_free(tmp);
+    return ret;
+  }
+#endif
+
   w &= BN_MASK2;
   for (i = a->top - 1; i >= 0; i--) {
 #ifndef BN_ULLONG
@@ -623,3 +647,82 @@
   }
   return (BN_ULONG)ret;
 }
+
+int BN_mod_pow2(BIGNUM *r, const BIGNUM *a, size_t e) {
+  if (e == 0 || a->top == 0) {
+    BN_zero(r);
+    return 1;
+  }
+
+  size_t num_words = 1 + ((e - 1) / BN_BITS2);
+
+  /* If |a| definitely has less than |e| bits, just BN_copy. */
+  if ((size_t) a->top < num_words) {
+    return BN_copy(r, a) != NULL;
+  }
+
+  /* Otherwise, first make sure we have enough space in |r|.
+   * Note that this will fail if num_words > INT_MAX. */
+  if (bn_wexpand(r, num_words) == NULL) {
+    return 0;
+  }
+
+  /* Copy the content of |a| into |r|. */
+  OPENSSL_memcpy(r->d, a->d, num_words * sizeof(BN_ULONG));
+
+  /* If |e| isn't word-aligned, we have to mask off some of our bits. */
+  size_t top_word_exponent = e % (sizeof(BN_ULONG) * 8);
+  if (top_word_exponent != 0) {
+    r->d[num_words - 1] &= (((BN_ULONG) 1) << top_word_exponent) - 1;
+  }
+
+  /* Fill in the remaining fields of |r|. */
+  r->neg = a->neg;
+  r->top = (int) num_words;
+  bn_correct_top(r);
+  return 1;
+}
+
+int BN_nnmod_pow2(BIGNUM *r, const BIGNUM *a, size_t e) {
+  if (!BN_mod_pow2(r, a, e)) {
+    return 0;
+  }
+
+  /* If the returned value was non-negative, we're done. */
+  if (BN_is_zero(r) || !r->neg) {
+    return 1;
+  }
+
+  size_t num_words = 1 + (e - 1) / BN_BITS2;
+
+  /* Expand |r| to the size of our modulus. */
+  if (bn_wexpand(r, num_words) == NULL) {
+    return 0;
+  }
+
+  /* Clear the upper words of |r|. */
+  OPENSSL_memset(&r->d[r->top], 0, (num_words - r->top) * BN_BYTES);
+
+  /* Set parameters of |r|. */
+  r->neg = 0;
+  r->top = (int) num_words;
+
+  /* Now, invert every word. The idea here is that we want to compute 2^e-|x|,
+   * which is actually equivalent to the twos-complement representation of |x|
+   * in |e| bits, which is -x = ~x + 1. */
+  for (int i = 0; i < r->top; i++) {
+    r->d[i] = ~r->d[i];
+  }
+
+  /* If our exponent doesn't span the top word, we have to mask the rest. */
+  size_t top_word_exponent = e % BN_BITS2;
+  if (top_word_exponent != 0) {
+    r->d[r->top - 1] &= (((BN_ULONG) 1) << top_word_exponent) - 1;
+  }
+
+  /* Keep the correct_top invariant for BN_add. */
+  bn_correct_top(r);
+
+  /* Finally, add one, for the reason described above. */
+  return BN_add(r, r, BN_value_one());
+}
diff --git a/src/crypto/bn/exponentiation.c b/src/crypto/bn/exponentiation.c
index 72a8db4..933a731 100644
--- a/src/crypto/bn/exponentiation.c
+++ b/src/crypto/bn/exponentiation.c
@@ -140,12 +140,6 @@
   int i, bits, ret = 0;
   BIGNUM *v, *rr;
 
-  if ((p->flags & BN_FLG_CONSTTIME) != 0) {
-    /* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */
-    OPENSSL_PUT_ERROR(BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
-    return 0;
-  }
-
   BN_CTX_start(ctx);
   if (r == a || r == p) {
     rr = BN_CTX_get(ctx);
@@ -209,6 +203,7 @@
   BN_init(&recp->N);
   BN_init(&recp->Nr);
   recp->num_bits = 0;
+  recp->shift = 0;
   recp->flags = 0;
 }
 
@@ -436,12 +431,6 @@
   BIGNUM *val[TABLE_SIZE];
   BN_RECP_CTX recp;
 
-  if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0) {
-    /* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */
-    OPENSSL_PUT_ERROR(BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
-    return 0;
-  }
-
   bits = BN_num_bits(p);
 
   if (bits == 0) {
@@ -575,41 +564,7 @@
 
 int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
                BN_CTX *ctx) {
-  /* For even modulus  m = 2^k*m_odd,  it might make sense to compute
-   * a^p mod m_odd  and  a^p mod 2^k  separately (with Montgomery
-   * exponentiation for the odd part), using appropriate exponent
-   * reductions, and combine the results using the CRT.
-   *
-   * For now, we use Montgomery only if the modulus is odd; otherwise,
-   * exponentiation using the reciprocal-based quick remaindering
-   * algorithm is used.
-   *
-   * (Timing obtained with expspeed.c [computations  a^p mod m
-   * where  a, p, m  are of the same length: 256, 512, 1024, 2048,
-   * 4096, 8192 bits], compared to the running time of the
-   * standard algorithm:
-   *
-   *   BN_mod_exp_mont   33 .. 40 %  [AMD K6-2, Linux, debug configuration]
-   *                     55 .. 77 %  [UltraSparc processor, but
-   *                                  debug-solaris-sparcv8-gcc conf.]
-   *
-   *   BN_mod_exp_recp   50 .. 70 %  [AMD K6-2, Linux, debug configuration]
-   *                     62 .. 118 % [UltraSparc, debug-solaris-sparcv8-gcc]
-   *
-   * On the Sparc, BN_mod_exp_recp was faster than BN_mod_exp_mont
-   * at 2048 and more bits, but at 512 and 1024 bits, it was
-   * slower even than the standard algorithm!
-   *
-   * "Real" timings [linux-elf, solaris-sparcv9-gcc configurations]
-   * should be obtained when the new Montgomery reduction code
-   * has been integrated into OpenSSL.) */
-
   if (BN_is_odd(m)) {
-    if (a->top == 1 && !a->neg && BN_get_flags(p, BN_FLG_CONSTTIME) == 0) {
-      BN_ULONG A = a->d[0];
-      return BN_mod_exp_mont_word(r, A, p, m, ctx, NULL);
-    }
-
     return BN_mod_exp_mont(r, a, p, m, ctx, NULL);
   }
 
@@ -626,10 +581,6 @@
   BIGNUM *val[TABLE_SIZE];
   BN_MONT_CTX *new_mont = NULL;
 
-  if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0) {
-    return BN_mod_exp_mont_consttime(rr, a, p, m, ctx, mont);
-  }
-
   if (!BN_is_odd(m)) {
     OPENSSL_PUT_ERROR(BN, BN_R_CALLED_WITH_EVEN_MODULUS);
     return 0;
@@ -787,29 +738,65 @@
  * pattern as far as cache lines are concerned. The following functions are
  * used to transfer a BIGNUM from/to that table. */
 static int copy_to_prebuf(const BIGNUM *b, int top, unsigned char *buf, int idx,
-                          int width) {
-  size_t i, j;
+                          int window) {
+  int i, j;
+  const int width = 1 << window;
+  BN_ULONG *table = (BN_ULONG *) buf;
 
   if (top > b->top) {
     top = b->top; /* this works because 'buf' is explicitly zeroed */
   }
-  for (i = 0, j = idx; i < top * sizeof b->d[0]; i++, j += width) {
-    buf[j] = ((unsigned char *)b->d)[i];
+
+  for (i = 0, j = idx; i < top; i++, j += width)  {
+    table[j] = b->d[i];
   }
 
   return 1;
 }
 
 static int copy_from_prebuf(BIGNUM *b, int top, unsigned char *buf, int idx,
-                            int width) {
-  size_t i, j;
+                            int window) {
+  int i, j;
+  const int width = 1 << window;
+  volatile BN_ULONG *table = (volatile BN_ULONG *)buf;
 
   if (bn_wexpand(b, top) == NULL) {
     return 0;
   }
 
-  for (i = 0, j = idx; i < top * sizeof b->d[0]; i++, j += width) {
-    ((unsigned char *)b->d)[i] = buf[j];
+  if (window <= 3) {
+    for (i = 0; i < top; i++, table += width) {
+      BN_ULONG acc = 0;
+
+      for (j = 0; j < width; j++) {
+        acc |= table[j] & ((BN_ULONG)0 - (constant_time_eq_int(j, idx) & 1));
+      }
+
+      b->d[i] = acc;
+    }
+  } else {
+    int xstride = 1 << (window - 2);
+    BN_ULONG y0, y1, y2, y3;
+
+    i = idx >> (window - 2); /* equivalent of idx / xstride */
+    idx &= xstride - 1;      /* equivalent of idx % xstride */
+
+    y0 = (BN_ULONG)0 - (constant_time_eq_int(i, 0) & 1);
+    y1 = (BN_ULONG)0 - (constant_time_eq_int(i, 1) & 1);
+    y2 = (BN_ULONG)0 - (constant_time_eq_int(i, 2) & 1);
+    y3 = (BN_ULONG)0 - (constant_time_eq_int(i, 3) & 1);
+
+    for (i = 0; i < top; i++, table += width) {
+      BN_ULONG acc = 0;
+
+      for (j = 0; j < xstride; j++) {
+        acc |= ((table[j + 0 * xstride] & y0) | (table[j + 1 * xstride] & y1) |
+                (table[j + 2 * xstride] & y2) | (table[j + 3 * xstride] & y3)) &
+               ((BN_ULONG)0 - (constant_time_eq_int(j, idx) & 1));
+      }
+
+      b->d[i] = acc;
+    }
   }
 
   b->top = top;
@@ -873,6 +860,7 @@
   int powerbufLen = 0;
   unsigned char *powerbuf = NULL;
   BIGNUM tmp, am;
+  BIGNUM *new_a = NULL;
 
   if (!BN_is_odd(m)) {
     OPENSSL_PUT_ERROR(BN, BN_R_CALLED_WITH_EVEN_MODULUS);
@@ -891,8 +879,6 @@
     return BN_one(rr);
   }
 
-  BN_CTX_start(ctx);
-
   /* Allocate a montgomery context if it was not supplied by the caller. */
   if (mont == NULL) {
     new_mont = BN_MONT_CTX_new();
@@ -902,6 +888,15 @@
     mont = new_mont;
   }
 
+  if (a->neg || BN_ucmp(a, m) >= 0) {
+    new_a = BN_new();
+    if (new_a == NULL ||
+        !BN_nnmod(new_a, a, m, ctx)) {
+      goto err;
+    }
+    a = new_a;
+  }
+
 #ifdef RSAZ_ENABLED
   /* If the size of the operands allow it, perform the optimized
    * RSAZ exponentiation. For further information see
@@ -917,16 +912,6 @@
     bn_correct_top(rr);
     ret = 1;
     goto err;
-  } else if ((8 == a->top) && (8 == p->top) && (BN_num_bits(m) == 512)) {
-    if (NULL == bn_wexpand(rr, 8)) {
-      goto err;
-    }
-    RSAZ_512_mod_exp(rr->d, a->d, p->d, m->d, mont->n0[0], mont->RR.d);
-    rr->top = 8;
-    rr->neg = 0;
-    bn_correct_top(rr);
-    ret = 1;
-    goto err;
   }
 #endif
 
@@ -935,9 +920,8 @@
 #if defined(OPENSSL_BN_ASM_MONT5)
   if (window >= 5) {
     window = 5; /* ~5% improvement for RSA2048 sign, and even for RSA4096 */
-    if ((top & 7) == 0) {
-      powerbufLen += 2 * top * sizeof(m->d[0]);
-    }
+    /* reserve space for mont->N.d[] copy */
+    powerbufLen += top * sizeof(mont->N.d[0]);
   }
 #endif
 
@@ -954,14 +938,14 @@
   } else
 #endif
   {
-    if ((powerbufFree = (unsigned char *)OPENSSL_malloc(
+    if ((powerbufFree = OPENSSL_malloc(
             powerbufLen + MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH)) == NULL) {
       goto err;
     }
   }
 
   powerbuf = MOD_EXP_CTIME_ALIGN(powerbufFree);
-  memset(powerbuf, 0, powerbufLen);
+  OPENSSL_memset(powerbuf, 0, powerbufLen);
 
 #ifdef alloca
   if (powerbufLen < 3072) {
@@ -991,12 +975,9 @@
   }
 
   /* prepare a^1 in Montgomery domain */
-  if (a->neg || BN_ucmp(a, m) >= 0) {
-    if (!BN_mod(&am, a, m, ctx) ||
-        !BN_to_montgomery(&am, &am, mont, ctx)) {
-      goto err;
-    }
-  } else if (!BN_to_montgomery(&am, a, mont, ctx)) {
+  assert(!a->neg);
+  assert(BN_ucmp(a, m) < 0);
+  if (!BN_to_montgomery(&am, a, mont, ctx)) {
     goto err;
   }
 
@@ -1008,7 +989,8 @@
   /* Dedicated window==4 case improves 512-bit RSA sign by ~15%, but as
    * 512-bit RSA is hardly relevant, we omit it to spare size... */
   if (window == 5 && top > 1) {
-    const BN_ULONG *np = mont->N.d, *n0 = mont->n0, *np2;
+    const BN_ULONG *n0 = mont->n0;
+    BN_ULONG *np;
 
     /* BN_to_montgomery can contaminate words above .top
      * [in BN_DEBUG[_DEBUG] build]... */
@@ -1019,14 +1001,9 @@
       tmp.d[i] = 0;
     }
 
-    if (top & 7) {
-      np2 = np;
-    } else {
-      BN_ULONG *np_double = am.d + top;
-      for (i = 0; i < top; i++) {
-        np_double[2 * i] = np[i];
-      }
-      np2 = np_double;
+    /* copy mont->N.d[] to improve cache locality */
+    for (np = am.d + top, i = 0; i < top; i++) {
+      np[i] = mont->N.d[i];
     }
 
     bn_scatter5(tmp.d, top, powerbuf, 0);
@@ -1041,7 +1018,7 @@
     }
     for (i = 3; i < 8; i += 2) {
       int j;
-      bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np2, n0, top, i - 1);
+      bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np, n0, top, i - 1);
       bn_scatter5(tmp.d, top, powerbuf, i);
       for (j = 2 * i; j < 32; j *= 2) {
         bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);
@@ -1049,13 +1026,13 @@
       }
     }
     for (; i < 16; i += 2) {
-      bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np2, n0, top, i - 1);
+      bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np, n0, top, i - 1);
       bn_scatter5(tmp.d, top, powerbuf, i);
       bn_mul_mont(tmp.d, tmp.d, tmp.d, np, n0, top);
       bn_scatter5(tmp.d, top, powerbuf, 2 * i);
     }
     for (; i < 32; i += 2) {
-      bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np2, n0, top, i - 1);
+      bn_mul_mont_gather5(tmp.d, am.d, powerbuf, np, n0, top, i - 1);
       bn_scatter5(tmp.d, top, powerbuf, i);
     }
 
@@ -1103,7 +1080,7 @@
         wvalue >>= (bits - 4) & 7;
         wvalue &= 0x1f;
         bits -= 5;
-        bn_power5(tmp.d, tmp.d, powerbuf, np2, n0, top, wvalue);
+        bn_power5(tmp.d, tmp.d, powerbuf, np, n0, top, wvalue);
       }
       while (bits >= 0) {
         /* Read five bits from |bits-4| through |bits|, inclusive. */
@@ -1112,11 +1089,11 @@
         wvalue >>= first_bit & 7;
         wvalue &= 0x1f;
         bits -= 5;
-        bn_power5(tmp.d, tmp.d, powerbuf, np2, n0, top, wvalue);
+        bn_power5(tmp.d, tmp.d, powerbuf, np, n0, top, wvalue);
       }
     }
 
-    ret = bn_from_montgomery(tmp.d, tmp.d, NULL, np2, n0, top);
+    ret = bn_from_montgomery(tmp.d, tmp.d, NULL, np, n0, top);
     tmp.top = top;
     bn_correct_top(&tmp);
     if (ret) {
@@ -1128,8 +1105,8 @@
   } else
 #endif
   {
-    if (!copy_to_prebuf(&tmp, top, powerbuf, 0, numPowers) ||
-        !copy_to_prebuf(&am, top, powerbuf, 1, numPowers)) {
+    if (!copy_to_prebuf(&tmp, top, powerbuf, 0, window) ||
+        !copy_to_prebuf(&am, top, powerbuf, 1, window)) {
       goto err;
     }
 
@@ -1140,13 +1117,13 @@
      */
     if (window > 1) {
       if (!BN_mod_mul_montgomery(&tmp, &am, &am, mont, ctx) ||
-          !copy_to_prebuf(&tmp, top, powerbuf, 2, numPowers)) {
+          !copy_to_prebuf(&tmp, top, powerbuf, 2, window)) {
         goto err;
       }
       for (i = 3; i < numPowers; i++) {
         /* Calculate a^i = a^(i-1) * a */
         if (!BN_mod_mul_montgomery(&tmp, &am, &tmp, mont, ctx) ||
-            !copy_to_prebuf(&tmp, top, powerbuf, i, numPowers)) {
+            !copy_to_prebuf(&tmp, top, powerbuf, i, window)) {
           goto err;
         }
       }
@@ -1156,7 +1133,7 @@
     for (wvalue = 0, i = bits % window; i >= 0; i--, bits--) {
       wvalue = (wvalue << 1) + BN_is_bit_set(p, bits);
     }
-    if (!copy_from_prebuf(&tmp, top, powerbuf, wvalue, numPowers)) {
+    if (!copy_from_prebuf(&tmp, top, powerbuf, wvalue, window)) {
       goto err;
     }
 
@@ -1175,7 +1152,7 @@
       }
 
       /* Fetch the appropriate pre-computed value from the pre-buf */
-      if (!copy_from_prebuf(&am, top, powerbuf, wvalue, numPowers)) {
+      if (!copy_from_prebuf(&am, top, powerbuf, wvalue, window)) {
         goto err;
       }
 
@@ -1194,162 +1171,32 @@
 
 err:
   BN_MONT_CTX_free(new_mont);
+  BN_clear_free(new_a);
   if (powerbuf != NULL) {
     OPENSSL_cleanse(powerbuf, powerbufLen);
     OPENSSL_free(powerbufFree);
   }
-  BN_CTX_end(ctx);
   return (ret);
 }
 
 int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p,
                          const BIGNUM *m, BN_CTX *ctx,
                          const BN_MONT_CTX *mont) {
-  BN_MONT_CTX *new_mont = NULL;
-  int b, bits, ret = 0;
-  int r_is_one;
-  BN_ULONG w, next_w;
-  BIGNUM *d, *r, *t;
-  BIGNUM *swap_tmp;
-#define BN_MOD_MUL_WORD(r, w, m)   \
-  (BN_mul_word(r, (w)) &&          \
-   (/* BN_ucmp(r, (m)) < 0 ? 1 :*/ \
-    (BN_mod(t, r, m, ctx) && (swap_tmp = r, r = t, t = swap_tmp, 1))))
-  /* BN_MOD_MUL_WORD is only used with 'w' large, so the BN_ucmp test is
-   * probably more overhead than always using BN_mod (which uses BN_copy if a
-   * similar test returns true). We can use BN_mod and do not need BN_nnmod
-   * because our accumulator is never negative (the result of BN_mod does not
-   * depend on the sign of the modulus). */
-#define BN_TO_MONTGOMERY_WORD(r, w, mont) \
-  (BN_set_word(r, (w)) && BN_to_montgomery(r, r, (mont), ctx))
+  BIGNUM a_bignum;
+  BN_init(&a_bignum);
 
-  if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0) {
-    /* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */
-    OPENSSL_PUT_ERROR(BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
-    return 0;
-  }
+  int ret = 0;
 
-  if (!BN_is_odd(m)) {
-    OPENSSL_PUT_ERROR(BN, BN_R_CALLED_WITH_EVEN_MODULUS);
-    return 0;
-  }
-
-  if (m->top == 1) {
-    a %= m->d[0]; /* make sure that 'a' is reduced */
-  }
-
-  bits = BN_num_bits(p);
-  if (bits == 0) {
-    /* x**0 mod 1 is still zero. */
-    if (BN_is_one(m)) {
-      BN_zero(rr);
-      return 1;
-    }
-    return BN_one(rr);
-  }
-  if (a == 0) {
-    BN_zero(rr);
-    return 1;
-  }
-
-  BN_CTX_start(ctx);
-  d = BN_CTX_get(ctx);
-  r = BN_CTX_get(ctx);
-  t = BN_CTX_get(ctx);
-  if (d == NULL || r == NULL || t == NULL) {
+  if (!BN_set_word(&a_bignum, a)) {
+    OPENSSL_PUT_ERROR(BN, ERR_R_INTERNAL_ERROR);
     goto err;
   }
 
-  /* Allocate a montgomery context if it was not supplied by the caller. */
-  if (mont == NULL) {
-    new_mont = BN_MONT_CTX_new();
-    if (new_mont == NULL || !BN_MONT_CTX_set(new_mont, m, ctx)) {
-      goto err;
-    }
-    mont = new_mont;
-  }
-
-  r_is_one = 1; /* except for Montgomery factor */
-
-  /* bits-1 >= 0 */
-
-  /* The result is accumulated in the product r*w. */
-  w = a; /* bit 'bits-1' of 'p' is always set */
-  for (b = bits - 2; b >= 0; b--) {
-    /* First, square r*w. */
-    next_w = w * w;
-    if ((next_w / w) != w) {
-      /* overflow */
-      if (r_is_one) {
-        if (!BN_TO_MONTGOMERY_WORD(r, w, mont)) {
-          goto err;
-        }
-        r_is_one = 0;
-      } else {
-        if (!BN_MOD_MUL_WORD(r, w, m)) {
-          goto err;
-        }
-      }
-      next_w = 1;
-    }
-
-    w = next_w;
-    if (!r_is_one) {
-      if (!BN_mod_mul_montgomery(r, r, r, mont, ctx)) {
-        goto err;
-      }
-    }
-
-    /* Second, multiply r*w by 'a' if exponent bit is set. */
-    if (BN_is_bit_set(p, b)) {
-      next_w = w * a;
-      if ((next_w / a) != w) {
-        /* overflow */
-        if (r_is_one) {
-          if (!BN_TO_MONTGOMERY_WORD(r, w, mont)) {
-            goto err;
-          }
-          r_is_one = 0;
-        } else {
-          if (!BN_MOD_MUL_WORD(r, w, m)) {
-            goto err;
-          }
-        }
-        next_w = a;
-      }
-      w = next_w;
-    }
-  }
-
-  /* Finally, set r:=r*w. */
-  if (w != 1) {
-    if (r_is_one) {
-      if (!BN_TO_MONTGOMERY_WORD(r, w, mont)) {
-        goto err;
-      }
-      r_is_one = 0;
-    } else {
-      if (!BN_MOD_MUL_WORD(r, w, m)) {
-        goto err;
-      }
-    }
-  }
-
-  if (r_is_one) {
-    /* can happen only if a == 1*/
-    if (!BN_one(rr)) {
-      goto err;
-    }
-  } else {
-    if (!BN_from_montgomery(rr, r, mont, ctx)) {
-      goto err;
-    }
-  }
-  ret = 1;
+  ret = BN_mod_exp_mont(rr, &a_bignum, p, m, ctx, mont);
 
 err:
-  BN_MONT_CTX_free(new_mont);
-  BN_CTX_end(ctx);
+  BN_free(&a_bignum);
+
   return ret;
 }
 
@@ -1358,37 +1205,12 @@
 int BN_mod_exp2_mont(BIGNUM *rr, const BIGNUM *a1, const BIGNUM *p1,
                      const BIGNUM *a2, const BIGNUM *p2, const BIGNUM *m,
                      BN_CTX *ctx, const BN_MONT_CTX *mont) {
-  int i, j, bits, b, bits1, bits2, ret = 0, wpos1, wpos2, window1, window2,
-                                   wvalue1, wvalue2;
-  int r_is_one = 1;
-  BIGNUM *d, *r;
-  const BIGNUM *a_mod_m;
-  /* Tables of variables obtained from 'ctx' */
-  BIGNUM *val1[TABLE_SIZE], *val2[TABLE_SIZE];
+  BIGNUM tmp;
+  BN_init(&tmp);
+
+  int ret = 0;
   BN_MONT_CTX *new_mont = NULL;
 
-  if (!(m->d[0] & 1)) {
-    OPENSSL_PUT_ERROR(BN, BN_R_CALLED_WITH_EVEN_MODULUS);
-    return 0;
-  }
-  bits1 = BN_num_bits(p1);
-  bits2 = BN_num_bits(p2);
-  if (bits1 == 0 && bits2 == 0) {
-    ret = BN_one(rr);
-    return ret;
-  }
-
-  bits = (bits1 > bits2) ? bits1 : bits2;
-
-  BN_CTX_start(ctx);
-  d = BN_CTX_get(ctx);
-  r = BN_CTX_get(ctx);
-  val1[0] = BN_CTX_get(ctx);
-  val2[0] = BN_CTX_get(ctx);
-  if (!d || !r || !val1[0] || !val2[0]) {
-    goto err;
-  }
-
   /* Allocate a montgomery context if it was not supplied by the caller. */
   if (mont == NULL) {
     new_mont = BN_MONT_CTX_new();
@@ -1398,156 +1220,21 @@
     mont = new_mont;
   }
 
-  window1 = BN_window_bits_for_exponent_size(bits1);
-  window2 = BN_window_bits_for_exponent_size(bits2);
-
-  /* Build table for a1:   val1[i] := a1^(2*i + 1) mod m  for i = 0 ..
-   * 2^(window1-1) */
-  if (a1->neg || BN_ucmp(a1, m) >= 0) {
-    if (!BN_mod(val1[0], a1, m, ctx)) {
-      goto err;
-    }
-    a_mod_m = val1[0];
-  } else {
-    a_mod_m = a1;
-  }
-
-  if (BN_is_zero(a_mod_m)) {
-    BN_zero(rr);
-    ret = 1;
+  /* BN_mod_mul_montgomery removes one Montgomery factor, so passing one
+   * Montgomery-encoded and one non-Montgomery-encoded value gives a
+   * non-Montgomery-encoded result. */
+  if (!BN_mod_exp_mont(rr, a1, p1, m, ctx, mont) ||
+      !BN_mod_exp_mont(&tmp, a2, p2, m, ctx, mont) ||
+      !BN_to_montgomery(rr, rr, mont, ctx) ||
+      !BN_mod_mul_montgomery(rr, rr, &tmp, mont, ctx)) {
     goto err;
   }
 
-  if (!BN_to_montgomery(val1[0], a_mod_m, mont, ctx)) {
-    goto err;
-  }
-
-  if (window1 > 1) {
-    if (!BN_mod_mul_montgomery(d, val1[0], val1[0], mont, ctx)) {
-      goto err;
-    }
-
-    j = 1 << (window1 - 1);
-    for (i = 1; i < j; i++) {
-      if (((val1[i] = BN_CTX_get(ctx)) == NULL) ||
-          !BN_mod_mul_montgomery(val1[i], val1[i - 1], d, mont, ctx)) {
-        goto err;
-      }
-    }
-  }
-
-  /* Build table for a2:   val2[i] := a2^(2*i + 1) mod m  for i = 0 ..
-   * 2^(window2-1) */
-  if (a2->neg || BN_ucmp(a2, m) >= 0) {
-    if (!BN_mod(val2[0], a2, m, ctx)) {
-      goto err;
-    }
-    a_mod_m = val2[0];
-  } else {
-    a_mod_m = a2;
-  }
-
-  if (BN_is_zero(a_mod_m)) {
-    BN_zero(rr);
-    ret = 1;
-    goto err;
-  }
-
-  if (!BN_to_montgomery(val2[0], a_mod_m, mont, ctx)) {
-    goto err;
-  }
-
-  if (window2 > 1) {
-    if (!BN_mod_mul_montgomery(d, val2[0], val2[0], mont, ctx)) {
-      goto err;
-    }
-
-    j = 1 << (window2 - 1);
-    for (i = 1; i < j; i++) {
-      if (((val2[i] = BN_CTX_get(ctx)) == NULL) ||
-          !BN_mod_mul_montgomery(val2[i], val2[i - 1], d, mont, ctx)) {
-        goto err;
-      }
-    }
-  }
-
-  /* Now compute the power product, using independent windows. */
-  r_is_one = 1;
-  wvalue1 = 0; /* The 'value' of the first window */
-  wvalue2 = 0; /* The 'value' of the second window */
-  wpos1 = 0;   /* If wvalue1 > 0, the bottom bit of the first window */
-  wpos2 = 0;   /* If wvalue2 > 0, the bottom bit of the second window */
-
-  if (!BN_to_montgomery(r, BN_value_one(), mont, ctx)) {
-    goto err;
-  }
-
-  for (b = bits - 1; b >= 0; b--) {
-    if (!r_is_one) {
-      if (!BN_mod_mul_montgomery(r, r, r, mont, ctx)) {
-        goto err;
-      }
-    }
-
-    if (!wvalue1 && BN_is_bit_set(p1, b)) {
-      /* consider bits b-window1+1 .. b for this window */
-      i = b - window1 + 1;
-      /* works for i<0 */
-      while (!BN_is_bit_set(p1, i)) {
-        i++;
-      }
-      wpos1 = i;
-      wvalue1 = 1;
-      for (i = b - 1; i >= wpos1; i--) {
-        wvalue1 <<= 1;
-        if (BN_is_bit_set(p1, i)) {
-          wvalue1++;
-        }
-      }
-    }
-
-    if (!wvalue2 && BN_is_bit_set(p2, b)) {
-      /* consider bits b-window2+1 .. b for this window */
-      i = b - window2 + 1;
-      while (!BN_is_bit_set(p2, i)) {
-        i++;
-      }
-      wpos2 = i;
-      wvalue2 = 1;
-      for (i = b - 1; i >= wpos2; i--) {
-        wvalue2 <<= 1;
-        if (BN_is_bit_set(p2, i)) {
-          wvalue2++;
-        }
-      }
-    }
-
-    if (wvalue1 && b == wpos1) {
-      /* wvalue1 is odd and < 2^window1 */
-      if (!BN_mod_mul_montgomery(r, r, val1[wvalue1 >> 1], mont, ctx)) {
-        goto err;
-      }
-      wvalue1 = 0;
-      r_is_one = 0;
-    }
-
-    if (wvalue2 && b == wpos2) {
-      /* wvalue2 is odd and < 2^window2 */
-      if (!BN_mod_mul_montgomery(r, r, val2[wvalue2 >> 1], mont, ctx)) {
-        goto err;
-      }
-      wvalue2 = 0;
-      r_is_one = 0;
-    }
-  }
-
-  if (!BN_from_montgomery(rr, r, mont, ctx)) {
-    goto err;
-  }
   ret = 1;
 
 err:
   BN_MONT_CTX_free(new_mont);
-  BN_CTX_end(ctx);
+  BN_free(&tmp);
+
   return ret;
 }
diff --git a/src/crypto/bn/gcd.c b/src/crypto/bn/gcd.c
index 41ca6d2..7c20b8e 100644
--- a/src/crypto/bn/gcd.c
+++ b/src/crypto/bn/gcd.c
@@ -108,6 +108,8 @@
 
 #include <openssl/bn.h>
 
+#include <assert.h>
+
 #include <openssl/err.h>
 
 #include "internal.h"
@@ -223,54 +225,44 @@
 }
 
 /* solves ax == 1 (mod n) */
-static BIGNUM *BN_mod_inverse_no_branch(BIGNUM *out, int *out_no_inverse,
-                                        const BIGNUM *a, const BIGNUM *n,
-                                        BN_CTX *ctx);
+static int bn_mod_inverse_general(BIGNUM *out, int *out_no_inverse,
+                                  const BIGNUM *a, const BIGNUM *n,
+                                  BN_CTX *ctx);
 
-BIGNUM *BN_mod_inverse_ex(BIGNUM *out, int *out_no_inverse, const BIGNUM *a,
-                          const BIGNUM *n, BN_CTX *ctx) {
-  BIGNUM *A, *B, *X, *Y, *M, *D, *T, *R = NULL;
-  BIGNUM *ret = NULL;
-  int sign;
+int BN_mod_inverse_odd(BIGNUM *out, int *out_no_inverse, const BIGNUM *a,
+                       const BIGNUM *n, BN_CTX *ctx) {
+  *out_no_inverse = 0;
 
-  if ((a->flags & BN_FLG_CONSTTIME) != 0 ||
-      (n->flags & BN_FLG_CONSTTIME) != 0) {
-    return BN_mod_inverse_no_branch(out, out_no_inverse, a, n, ctx);
+  if (!BN_is_odd(n)) {
+    OPENSSL_PUT_ERROR(BN, BN_R_CALLED_WITH_EVEN_MODULUS);
+    return 0;
   }
 
-  *out_no_inverse = 0;
+  if (BN_is_negative(a) || BN_cmp(a, n) >= 0) {
+    OPENSSL_PUT_ERROR(BN, BN_R_INPUT_NOT_REDUCED);
+    return 0;
+  }
+
+  BIGNUM *A, *B, *X, *Y;
+  int ret = 0;
+  int sign;
 
   BN_CTX_start(ctx);
   A = BN_CTX_get(ctx);
   B = BN_CTX_get(ctx);
   X = BN_CTX_get(ctx);
-  D = BN_CTX_get(ctx);
-  M = BN_CTX_get(ctx);
   Y = BN_CTX_get(ctx);
-  T = BN_CTX_get(ctx);
-  if (T == NULL) {
+  if (Y == NULL) {
     goto err;
   }
 
-  if (out == NULL) {
-    R = BN_new();
-  } else {
-    R = out;
-  }
-  if (R == NULL) {
-    goto err;
-  }
+  BIGNUM *R = out;
 
   BN_zero(Y);
   if (!BN_one(X) || BN_copy(B, a) == NULL || BN_copy(A, n) == NULL) {
     goto err;
   }
   A->neg = 0;
-  if (B->neg || (BN_ucmp(B, A) >= 0)) {
-    if (!BN_nnmod(B, B, A, ctx)) {
-      goto err;
-    }
-  }
   sign = -1;
   /* From  B = a mod |n|,  A = |n|  it follows that
    *
@@ -279,225 +271,99 @@
    *      sign*Y*a  ==  A   (mod |n|).
    */
 
-  if (BN_is_odd(n) && (BN_num_bits(n) <= (BN_BITS2 <= 32 ? 450 : 2048))) {
-    /* Binary inversion algorithm; requires odd modulus.
-     * This is faster than the general algorithm if the modulus
-     * is sufficiently small (about 400 .. 500 bits on 32-bit
-     * sytems, but much more on 64-bit systems) */
-    int shift;
+  /* Binary inversion algorithm; requires odd modulus. This is faster than the
+   * general algorithm if the modulus is sufficiently small (about 400 .. 500
+   * bits on 32-bit systems, but much more on 64-bit systems) */
+  int shift;
 
-    while (!BN_is_zero(B)) {
-      /*      0 < B < |n|,
-       *      0 < A <= |n|,
-       * (1) -sign*X*a  ==  B   (mod |n|),
-       * (2)  sign*Y*a  ==  A   (mod |n|) */
+  while (!BN_is_zero(B)) {
+    /*      0 < B < |n|,
+     *      0 < A <= |n|,
+     * (1) -sign*X*a  ==  B   (mod |n|),
+     * (2)  sign*Y*a  ==  A   (mod |n|) */
 
-      /* Now divide  B  by the maximum possible power of two in the integers,
-       * and divide  X  by the same value mod |n|.
-       * When we're done, (1) still holds. */
-      shift = 0;
-      while (!BN_is_bit_set(B, shift)) {
-        /* note that 0 < B */
-        shift++;
+    /* Now divide  B  by the maximum possible power of two in the integers,
+     * and divide  X  by the same value mod |n|.
+     * When we're done, (1) still holds. */
+    shift = 0;
+    while (!BN_is_bit_set(B, shift)) {
+      /* note that 0 < B */
+      shift++;
 
-        if (BN_is_odd(X)) {
-          if (!BN_uadd(X, X, n)) {
-            goto err;
-          }
-        }
-        /* now X is even, so we can easily divide it by two */
-        if (!BN_rshift1(X, X)) {
+      if (BN_is_odd(X)) {
+        if (!BN_uadd(X, X, n)) {
           goto err;
         }
       }
-      if (shift > 0) {
-        if (!BN_rshift(B, B, shift)) {
-          goto err;
-        }
-      }
-
-      /* Same for A and Y. Afterwards, (2) still holds. */
-      shift = 0;
-      while (!BN_is_bit_set(A, shift)) {
-        /* note that 0 < A */
-        shift++;
-
-        if (BN_is_odd(Y)) {
-          if (!BN_uadd(Y, Y, n)) {
-            goto err;
-          }
-        }
-        /* now Y is even */
-        if (!BN_rshift1(Y, Y)) {
-          goto err;
-        }
-      }
-      if (shift > 0) {
-        if (!BN_rshift(A, A, shift)) {
-          goto err;
-        }
-      }
-
-      /* We still have (1) and (2).
-       * Both  A  and  B  are odd.
-       * The following computations ensure that
-       *
-       *     0 <= B < |n|,
-       *      0 < A < |n|,
-       * (1) -sign*X*a  ==  B   (mod |n|),
-       * (2)  sign*Y*a  ==  A   (mod |n|),
-       *
-       * and that either  A  or  B  is even in the next iteration. */
-      if (BN_ucmp(B, A) >= 0) {
-        /* -sign*(X + Y)*a == B - A  (mod |n|) */
-        if (!BN_uadd(X, X, Y)) {
-          goto err;
-        }
-        /* NB: we could use BN_mod_add_quick(X, X, Y, n), but that
-         * actually makes the algorithm slower */
-        if (!BN_usub(B, B, A)) {
-          goto err;
-        }
-      } else {
-        /*  sign*(X + Y)*a == A - B  (mod |n|) */
-        if (!BN_uadd(Y, Y, X)) {
-          goto err;
-        }
-        /* as above, BN_mod_add_quick(Y, Y, X, n) would slow things down */
-        if (!BN_usub(A, A, B)) {
-          goto err;
-        }
+      /* now X is even, so we can easily divide it by two */
+      if (!BN_rshift1(X, X)) {
+        goto err;
       }
     }
-  } else {
-    /* general inversion algorithm */
-
-    while (!BN_is_zero(B)) {
-      BIGNUM *tmp;
-
-      /*
-       *      0 < B < A,
-       * (*) -sign*X*a  ==  B   (mod |n|),
-       *      sign*Y*a  ==  A   (mod |n|) */
-
-      /* (D, M) := (A/B, A%B) ... */
-      if (BN_num_bits(A) == BN_num_bits(B)) {
-        if (!BN_one(D)) {
-          goto err;
-        }
-        if (!BN_sub(M, A, B)) {
-          goto err;
-        }
-      } else if (BN_num_bits(A) == BN_num_bits(B) + 1) {
-        /* A/B is 1, 2, or 3 */
-        if (!BN_lshift1(T, B)) {
-          goto err;
-        }
-        if (BN_ucmp(A, T) < 0) {
-          /* A < 2*B, so D=1 */
-          if (!BN_one(D)) {
-            goto err;
-          }
-          if (!BN_sub(M, A, B)) {
-            goto err;
-          }
-        } else {
-          /* A >= 2*B, so D=2 or D=3 */
-          if (!BN_sub(M, A, T)) {
-            goto err;
-          }
-          if (!BN_add(D, T, B)) {
-            goto err; /* use D (:= 3*B) as temp */
-          }
-          if (BN_ucmp(A, D) < 0) {
-            /* A < 3*B, so D=2 */
-            if (!BN_set_word(D, 2)) {
-              goto err;
-            }
-            /* M (= A - 2*B) already has the correct value */
-          } else {
-            /* only D=3 remains */
-            if (!BN_set_word(D, 3)) {
-              goto err;
-            }
-            /* currently  M = A - 2*B,  but we need  M = A - 3*B */
-            if (!BN_sub(M, M, B)) {
-              goto err;
-            }
-          }
-        }
-      } else {
-        if (!BN_div(D, M, A, B, ctx)) {
-          goto err;
-        }
+    if (shift > 0) {
+      if (!BN_rshift(B, B, shift)) {
+        goto err;
       }
-
-      /* Now
-       *      A = D*B + M;
-       * thus we have
-       * (**)  sign*Y*a  ==  D*B + M   (mod |n|). */
-
-      tmp = A; /* keep the BIGNUM object, the value does not matter */
-
-      /* (A, B) := (B, A mod B) ... */
-      A = B;
-      B = M;
-      /* ... so we have  0 <= B < A  again */
-
-      /* Since the former  M  is now  B  and the former  B  is now  A,
-       * (**) translates into
-       *       sign*Y*a  ==  D*A + B    (mod |n|),
-       * i.e.
-       *       sign*Y*a - D*A  ==  B    (mod |n|).
-       * Similarly, (*) translates into
-       *      -sign*X*a  ==  A          (mod |n|).
-       *
-       * Thus,
-       *   sign*Y*a + D*sign*X*a  ==  B  (mod |n|),
-       * i.e.
-       *        sign*(Y + D*X)*a  ==  B  (mod |n|).
-       *
-       * So if we set  (X, Y, sign) := (Y + D*X, X, -sign),  we arrive back at
-       *      -sign*X*a  ==  B   (mod |n|),
-       *       sign*Y*a  ==  A   (mod |n|).
-       * Note that  X  and  Y  stay non-negative all the time. */
-
-      /* most of the time D is very small, so we can optimize tmp := D*X+Y */
-      if (BN_is_one(D)) {
-        if (!BN_add(tmp, X, Y)) {
-          goto err;
-        }
-      } else {
-        if (BN_is_word(D, 2)) {
-          if (!BN_lshift1(tmp, X)) {
-            goto err;
-          }
-        } else if (BN_is_word(D, 4)) {
-          if (!BN_lshift(tmp, X, 2)) {
-            goto err;
-          }
-        } else if (D->top == 1) {
-          if (!BN_copy(tmp, X)) {
-            goto err;
-          }
-          if (!BN_mul_word(tmp, D->d[0])) {
-            goto err;
-          }
-        } else {
-          if (!BN_mul(tmp, D, X, ctx)) {
-            goto err;
-          }
-        }
-        if (!BN_add(tmp, tmp, Y)) {
-          goto err;
-        }
-      }
-
-      M = Y; /* keep the BIGNUM object, the value does not matter */
-      Y = X;
-      X = tmp;
-      sign = -sign;
     }
+
+    /* Same for A and Y. Afterwards, (2) still holds. */
+    shift = 0;
+    while (!BN_is_bit_set(A, shift)) {
+      /* note that 0 < A */
+      shift++;
+
+      if (BN_is_odd(Y)) {
+        if (!BN_uadd(Y, Y, n)) {
+          goto err;
+        }
+      }
+      /* now Y is even */
+      if (!BN_rshift1(Y, Y)) {
+        goto err;
+      }
+    }
+    if (shift > 0) {
+      if (!BN_rshift(A, A, shift)) {
+        goto err;
+      }
+    }
+
+    /* We still have (1) and (2).
+     * Both  A  and  B  are odd.
+     * The following computations ensure that
+     *
+     *     0 <= B < |n|,
+     *      0 < A < |n|,
+     * (1) -sign*X*a  ==  B   (mod |n|),
+     * (2)  sign*Y*a  ==  A   (mod |n|),
+     *
+     * and that either  A  or  B  is even in the next iteration. */
+    if (BN_ucmp(B, A) >= 0) {
+      /* -sign*(X + Y)*a == B - A  (mod |n|) */
+      if (!BN_uadd(X, X, Y)) {
+        goto err;
+      }
+      /* NB: we could use BN_mod_add_quick(X, X, Y, n), but that
+       * actually makes the algorithm slower */
+      if (!BN_usub(B, B, A)) {
+        goto err;
+      }
+    } else {
+      /*  sign*(X + Y)*a == A - B  (mod |n|) */
+      if (!BN_uadd(Y, Y, X)) {
+        goto err;
+      }
+      /* as above, BN_mod_add_quick(Y, Y, X, n) would slow things down */
+      if (!BN_usub(A, A, B)) {
+        goto err;
+      }
+    }
+  }
+
+  if (!BN_is_one(A)) {
+    *out_no_inverse = 1;
+    OPENSSL_PUT_ERROR(BN, BN_R_NO_INVERSE);
+    goto err;
   }
 
   /* The while loop (Euclid's algorithm) ends when
@@ -513,47 +379,107 @@
   }
   /* Now  Y*a  ==  A  (mod |n|).  */
 
-  if (BN_is_one(A)) {
-    /* Y*a == 1  (mod |n|) */
-    if (!Y->neg && BN_ucmp(Y, n) < 0) {
-      if (!BN_copy(R, Y)) {
-        goto err;
-      }
-    } else {
-      if (!BN_nnmod(R, Y, n, ctx)) {
-        goto err;
-      }
+  /* Y*a == 1  (mod |n|) */
+  if (!Y->neg && BN_ucmp(Y, n) < 0) {
+    if (!BN_copy(R, Y)) {
+      goto err;
     }
   } else {
-    *out_no_inverse = 1;
-    OPENSSL_PUT_ERROR(BN, BN_R_NO_INVERSE);
-    goto err;
+    if (!BN_nnmod(R, Y, n, ctx)) {
+      goto err;
+    }
   }
-  ret = R;
+
+  ret = 1;
 
 err:
-  if (ret == NULL && out == NULL) {
-    BN_free(R);
-  }
   BN_CTX_end(ctx);
   return ret;
 }
 
 BIGNUM *BN_mod_inverse(BIGNUM *out, const BIGNUM *a, const BIGNUM *n,
                        BN_CTX *ctx) {
+  BIGNUM *new_out = NULL;
+  if (out == NULL) {
+    new_out = BN_new();
+    if (new_out == NULL) {
+      OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
+      return NULL;
+    }
+    out = new_out;
+  }
+
+  int ok = 0;
+  BIGNUM *a_reduced = NULL;
+  if (a->neg || BN_ucmp(a, n) >= 0) {
+    a_reduced = BN_dup(a);
+    if (a_reduced == NULL) {
+      goto err;
+    }
+    if (!BN_nnmod(a_reduced, a_reduced, n, ctx)) {
+      goto err;
+    }
+    a = a_reduced;
+  }
+
   int no_inverse;
-  return BN_mod_inverse_ex(out, &no_inverse, a, n, ctx);
+  if (!BN_is_odd(n)) {
+    if (!bn_mod_inverse_general(out, &no_inverse, a, n, ctx)) {
+      goto err;
+    }
+  } else if (!BN_mod_inverse_odd(out, &no_inverse, a, n, ctx)) {
+    goto err;
+  }
+
+  ok = 1;
+
+err:
+  if (!ok) {
+    BN_free(new_out);
+    out = NULL;
+  }
+  BN_free(a_reduced);
+  return out;
 }
 
-/* BN_mod_inverse_no_branch is a special version of BN_mod_inverse.
- * It does not contain branches that may leak sensitive information. */
-static BIGNUM *BN_mod_inverse_no_branch(BIGNUM *out, int *out_no_inverse,
-                                        const BIGNUM *a, const BIGNUM *n,
-                                        BN_CTX *ctx) {
-  BIGNUM *A, *B, *X, *Y, *M, *D, *T, *R = NULL;
-  BIGNUM local_A, local_B;
-  BIGNUM *pA, *pB;
-  BIGNUM *ret = NULL;
+int BN_mod_inverse_blinded(BIGNUM *out, int *out_no_inverse, const BIGNUM *a,
+                           const BN_MONT_CTX *mont, BN_CTX *ctx) {
+  *out_no_inverse = 0;
+
+  if (BN_is_negative(a) || BN_cmp(a, &mont->N) >= 0) {
+    OPENSSL_PUT_ERROR(BN, BN_R_INPUT_NOT_REDUCED);
+    return 0;
+  }
+
+  int ret = 0;
+  BIGNUM blinding_factor;
+  BN_init(&blinding_factor);
+
+  if (!BN_rand_range_ex(&blinding_factor, 1, &mont->N) ||
+      !BN_mod_mul_montgomery(out, &blinding_factor, a, mont, ctx) ||
+      !BN_mod_inverse_odd(out, out_no_inverse, out, &mont->N, ctx) ||
+      !BN_mod_mul_montgomery(out, &blinding_factor, out, mont, ctx)) {
+    OPENSSL_PUT_ERROR(BN, ERR_R_BN_LIB);
+    goto err;
+  }
+
+  ret = 1;
+
+err:
+  BN_free(&blinding_factor);
+  return ret;
+}
+
+/* bn_mod_inverse_general is the general inversion algorithm that works for
+ * both even and odd |n|. It was specifically designed to contain fewer
+ * branches that may leak sensitive information; see "New Branch Prediction
+ * Vulnerabilities in OpenSSL and Necessary Software Countermeasures" by
+ * Onur Acıçmez, Shay Gueron, and Jean-Pierre Seifert. */
+static int bn_mod_inverse_general(BIGNUM *out, int *out_no_inverse,
+                                  const BIGNUM *a, const BIGNUM *n,
+                                  BN_CTX *ctx) {
+  BIGNUM *A, *B, *X, *Y, *M, *D, *T;
+  int ret = 0;
   int sign;
 
   *out_no_inverse = 0;
@@ -570,14 +496,7 @@
     goto err;
   }
 
-  if (out == NULL) {
-    R = BN_new();
-  } else {
-    R = out;
-  }
-  if (R == NULL) {
-    goto err;
-  }
+  BIGNUM *R = out;
 
   BN_zero(Y);
   if (!BN_one(X) || BN_copy(B, a) == NULL || BN_copy(A, n) == NULL) {
@@ -585,16 +504,6 @@
   }
   A->neg = 0;
 
-  if (B->neg || (BN_ucmp(B, A) >= 0)) {
-    /* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,
-     * BN_div_no_branch will be called eventually.
-     */
-    pB = &local_B;
-    BN_with_flags(pB, B, BN_FLG_CONSTTIME);
-    if (!BN_nnmod(B, pB, A, ctx)) {
-      goto err;
-    }
-  }
   sign = -1;
   /* From  B = a mod |n|,  A = |n|  it follows that
    *
@@ -612,14 +521,8 @@
      *      sign*Y*a  ==  A   (mod |n|)
      */
 
-    /* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,
-     * BN_div_no_branch will be called eventually.
-     */
-    pA = &local_A;
-    BN_with_flags(pA, A, BN_FLG_CONSTTIME);
-
     /* (D, M) := (A/B, A%B) ... */
-    if (!BN_div(D, M, pA, B, ctx)) {
+    if (!BN_div(D, M, A, B, ctx)) {
       goto err;
     }
 
@@ -668,6 +571,12 @@
     sign = -sign;
   }
 
+  if (!BN_is_one(A)) {
+    *out_no_inverse = 1;
+    OPENSSL_PUT_ERROR(BN, BN_R_NO_INVERSE);
+    goto err;
+  }
+
   /*
    * The while loop (Euclid's algorithm) ends when
    *      A == gcd(a,n);
@@ -683,29 +592,44 @@
   }
   /* Now  Y*a  ==  A  (mod |n|).  */
 
-  if (BN_is_one(A)) {
-    /* Y*a == 1  (mod |n|) */
-    if (!Y->neg && BN_ucmp(Y, n) < 0) {
-      if (!BN_copy(R, Y)) {
-        goto err;
-      }
-    } else {
-      if (!BN_nnmod(R, Y, n, ctx)) {
-        goto err;
-      }
+  /* Y*a == 1  (mod |n|) */
+  if (!Y->neg && BN_ucmp(Y, n) < 0) {
+    if (!BN_copy(R, Y)) {
+      goto err;
     }
   } else {
-    *out_no_inverse = 1;
-    OPENSSL_PUT_ERROR(BN, BN_R_NO_INVERSE);
-    goto err;
+    if (!BN_nnmod(R, Y, n, ctx)) {
+      goto err;
+    }
   }
-  ret = R;
+
+  ret = 1;
 
 err:
-  if (ret == NULL && out == NULL) {
-    BN_free(R);
-  }
-
   BN_CTX_end(ctx);
   return ret;
 }
+
+int bn_mod_inverse_prime(BIGNUM *out, const BIGNUM *a, const BIGNUM *p,
+                         BN_CTX *ctx, const BN_MONT_CTX *mont_p) {
+  BN_CTX_start(ctx);
+  BIGNUM *p_minus_2 = BN_CTX_get(ctx);
+  int ok = p_minus_2 != NULL &&
+           BN_copy(p_minus_2, p) &&
+           BN_sub_word(p_minus_2, 2) &&
+           BN_mod_exp_mont(out, a, p_minus_2, p, ctx, mont_p);
+  BN_CTX_end(ctx);
+  return ok;
+}
+
+int bn_mod_inverse_secret_prime(BIGNUM *out, const BIGNUM *a, const BIGNUM *p,
+                                BN_CTX *ctx, const BN_MONT_CTX *mont_p) {
+  BN_CTX_start(ctx);
+  BIGNUM *p_minus_2 = BN_CTX_get(ctx);
+  int ok = p_minus_2 != NULL &&
+           BN_copy(p_minus_2, p) &&
+           BN_sub_word(p_minus_2, 2) &&
+           BN_mod_exp_mont_consttime(out, a, p_minus_2, p, ctx, mont_p);
+  BN_CTX_end(ctx);
+  return ok;
+}
diff --git a/src/crypto/bn/generic.c b/src/crypto/bn/generic.c
index 7303ca5..de77cc5 100644
--- a/src/crypto/bn/generic.c
+++ b/src/crypto/bn/generic.c
@@ -61,42 +61,40 @@
 #include "internal.h"
 
 
-/* Generic implementations of most operations are needed for:
- * - Configurations without inline assembly.
- * - Architectures other than x86 or x86_64.
- * - Windows x84_64; x86_64-gcc.c does not build on MSVC. */
+/* This file has two other implementations: x86 assembly language in
+ * asm/bn-586.pl and x86_64 inline assembly in asm/x86_64-gcc.c. */
 #if defined(OPENSSL_NO_ASM) || \
-    (!defined(OPENSSL_X86_64) && !defined(OPENSSL_X86)) || \
-    (defined(OPENSSL_X86_64) && defined(OPENSSL_WINDOWS))
+    !(defined(OPENSSL_X86) || (defined(OPENSSL_X86_64) && defined(__GNUC__)))
 
 #ifdef BN_ULLONG
-#define mul_add(r, a, w, c)             \
-  {                                     \
-    BN_ULLONG t;                        \
-    t = (BN_ULLONG)w * (a) + (r) + (c); \
-    (r) = Lw(t);                        \
-    (c) = Hw(t);                        \
-  }
+#define mul_add(r, a, w, c)               \
+  do {                                    \
+    BN_ULLONG t;                          \
+    t = (BN_ULLONG)(w) * (a) + (r) + (c); \
+    (r) = Lw(t);                          \
+    (c) = Hw(t);                          \
+  } while (0)
 
-#define mul(r, a, w, c)           \
-  {                               \
-    BN_ULLONG t;                  \
-    t = (BN_ULLONG)w * (a) + (c); \
-    (r) = Lw(t);                  \
-    (c) = Hw(t);                  \
-  }
+#define mul(r, a, w, c)             \
+  do {                              \
+    BN_ULLONG t;                    \
+    t = (BN_ULLONG)(w) * (a) + (c); \
+    (r) = Lw(t);                    \
+    (c) = Hw(t);                    \
+  } while (0)
 
 #define sqr(r0, r1, a)        \
-  {                           \
+  do {                        \
     BN_ULLONG t;              \
     t = (BN_ULLONG)(a) * (a); \
     (r0) = Lw(t);             \
     (r1) = Hw(t);             \
-  }
+  } while (0)
 
-#elif defined(BN_UMULT_LOHI)
+#else
+
 #define mul_add(r, a, w, c)             \
-  {                                     \
+  do {                                  \
     BN_ULONG high, low, ret, tmp = (a); \
     ret = (r);                          \
     BN_UMULT_LOHI(low, high, w, tmp);   \
@@ -106,120 +104,26 @@
     ret += low;                         \
     (c) += (ret < low) ? 1 : 0;         \
     (r) = ret;                          \
-  }
+  } while (0)
 
 #define mul(r, a, w, c)                \
-  {                                    \
+  do {                                 \
     BN_ULONG high, low, ret, ta = (a); \
     BN_UMULT_LOHI(low, high, w, ta);   \
     ret = low + (c);                   \
     (c) = high;                        \
     (c) += (ret < low) ? 1 : 0;        \
     (r) = ret;                         \
-  }
+  } while (0)
 
 #define sqr(r0, r1, a)               \
-  {                                  \
+  do {                               \
     BN_ULONG tmp = (a);              \
     BN_UMULT_LOHI(r0, r1, tmp, tmp); \
-  }
+  } while (0)
 
-#else
-
-/*************************************************************
- * No long long type
- */
-
-#define LBITS(a) ((a) & BN_MASK2l)
-#define HBITS(a) (((a) >> BN_BITS4) & BN_MASK2l)
-#define L2HBITS(a) (((a) << BN_BITS4) & BN_MASK2)
-
-#define LLBITS(a) ((a) & BN_MASKl)
-#define LHBITS(a) (((a) >> BN_BITS2) & BN_MASKl)
-#define LL2HBITS(a) ((BN_ULLONG)((a) & BN_MASKl) << BN_BITS2)
-
-#define mul64(l, h, bl, bh)       \
-  {                               \
-    BN_ULONG m, m1, lt, ht;       \
-                                  \
-    lt = l;                       \
-    ht = h;                       \
-    m = (bh) * (lt);              \
-    lt = (bl) * (lt);             \
-    m1 = (bl) * (ht);             \
-    ht = (bh) * (ht);             \
-    m = (m + m1) & BN_MASK2;      \
-    if (m < m1)                   \
-      ht += L2HBITS((BN_ULONG)1); \
-    ht += HBITS(m);               \
-    m1 = L2HBITS(m);              \
-    lt = (lt + m1) & BN_MASK2;    \
-    if (lt < m1)                  \
-      ht++;                       \
-    (l) = lt;                     \
-    (h) = ht;                     \
-  }
-
-#define sqr64(lo, ho, in)                    \
-  {                                          \
-    BN_ULONG l, h, m;                        \
-                                             \
-    h = (in);                                \
-    l = LBITS(h);                            \
-    h = HBITS(h);                            \
-    m = (l) * (h);                           \
-    l *= l;                                  \
-    h *= h;                                  \
-    h += (m & BN_MASK2h1) >> (BN_BITS4 - 1); \
-    m = (m & BN_MASK2l) << (BN_BITS4 + 1);   \
-    l = (l + m) & BN_MASK2;                  \
-    if (l < m)                               \
-      h++;                                   \
-    (lo) = l;                                \
-    (ho) = h;                                \
-  }
-
-#define mul_add(r, a, bl, bh, c) \
-  {                              \
-    BN_ULONG l, h;               \
-                                 \
-    h = (a);                     \
-    l = LBITS(h);                \
-    h = HBITS(h);                \
-    mul64(l, h, (bl), (bh));     \
-                                 \
-    /* non-multiply part */      \
-    l = (l + (c)) & BN_MASK2;    \
-    if (l < (c))                 \
-      h++;                       \
-    (c) = (r);                   \
-    l = (l + (c)) & BN_MASK2;    \
-    if (l < (c))                 \
-      h++;                       \
-    (c) = h & BN_MASK2;          \
-    (r) = l;                     \
-  }
-
-#define mul(r, a, bl, bh, c)  \
-  {                           \
-    BN_ULONG l, h;            \
-                              \
-    h = (a);                  \
-    l = LBITS(h);             \
-    h = HBITS(h);             \
-    mul64(l, h, (bl), (bh));  \
-                              \
-    /* non-multiply part */   \
-    l += (c);                 \
-    if ((l & BN_MASK2) < (c)) \
-      h++;                    \
-    (c) = h & BN_MASK2;       \
-    (r) = l & BN_MASK2;       \
-  }
 #endif /* !BN_ULLONG */
 
-#if defined(BN_ULLONG) || defined(BN_UMULT_HIGH)
-
 BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
                           BN_ULONG w) {
   BN_ULONG c1 = 0;
@@ -298,174 +202,6 @@
   }
 }
 
-#else /* !(defined(BN_ULLONG) || defined(BN_UMULT_HIGH)) */
-
-BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
-                          BN_ULONG w) {
-  BN_ULONG c = 0;
-  BN_ULONG bl, bh;
-
-  assert(num >= 0);
-  if (num <= 0) {
-    return (BN_ULONG)0;
-  }
-
-  bl = LBITS(w);
-  bh = HBITS(w);
-
-  while (num & ~3) {
-    mul_add(rp[0], ap[0], bl, bh, c);
-    mul_add(rp[1], ap[1], bl, bh, c);
-    mul_add(rp[2], ap[2], bl, bh, c);
-    mul_add(rp[3], ap[3], bl, bh, c);
-    ap += 4;
-    rp += 4;
-    num -= 4;
-  }
-  while (num) {
-    mul_add(rp[0], ap[0], bl, bh, c);
-    ap++;
-    rp++;
-    num--;
-  }
-  return c;
-}
-
-BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w) {
-  BN_ULONG carry = 0;
-  BN_ULONG bl, bh;
-
-  assert(num >= 0);
-  if (num <= 0) {
-    return (BN_ULONG)0;
-  }
-
-  bl = LBITS(w);
-  bh = HBITS(w);
-
-  while (num & ~3) {
-    mul(rp[0], ap[0], bl, bh, carry);
-    mul(rp[1], ap[1], bl, bh, carry);
-    mul(rp[2], ap[2], bl, bh, carry);
-    mul(rp[3], ap[3], bl, bh, carry);
-    ap += 4;
-    rp += 4;
-    num -= 4;
-  }
-  while (num) {
-    mul(rp[0], ap[0], bl, bh, carry);
-    ap++;
-    rp++;
-    num--;
-  }
-  return carry;
-}
-
-void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) {
-  assert(n >= 0);
-  if (n <= 0) {
-    return;
-  }
-
-  while (n & ~3) {
-    sqr64(r[0], r[1], a[0]);
-    sqr64(r[2], r[3], a[1]);
-    sqr64(r[4], r[5], a[2]);
-    sqr64(r[6], r[7], a[3]);
-    a += 4;
-    r += 8;
-    n -= 4;
-  }
-  while (n) {
-    sqr64(r[0], r[1], a[0]);
-    a++;
-    r += 2;
-    n--;
-  }
-}
-
-#endif /* !(defined(BN_ULLONG) || defined(BN_UMULT_HIGH)) */
-
-#if defined(BN_ULLONG)
-
-BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) {
-  return (BN_ULONG)(((((BN_ULLONG)h) << BN_BITS2) | l) / (BN_ULLONG)d);
-}
-
-#else
-
-/* Divide h,l by d and return the result. */
-BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d) {
-  BN_ULONG dh, dl, q, ret = 0, th, tl, t;
-  int i, count = 2;
-
-  if (d == 0) {
-    return BN_MASK2;
-  }
-
-  i = BN_num_bits_word(d);
-  assert((i == BN_BITS2) || (h <= (BN_ULONG)1 << i));
-
-  i = BN_BITS2 - i;
-  if (h >= d) {
-    h -= d;
-  }
-
-  if (i) {
-    d <<= i;
-    h = (h << i) | (l >> (BN_BITS2 - i));
-    l <<= i;
-  }
-  dh = (d & BN_MASK2h) >> BN_BITS4;
-  dl = (d & BN_MASK2l);
-  for (;;) {
-    if ((h >> BN_BITS4) == dh) {
-      q = BN_MASK2l;
-    } else {
-      q = h / dh;
-    }
-
-    th = q * dh;
-    tl = dl * q;
-    for (;;) {
-      t = h - th;
-      if ((t & BN_MASK2h) ||
-          ((tl) <= ((t << BN_BITS4) | ((l & BN_MASK2h) >> BN_BITS4)))) {
-        break;
-      }
-      q--;
-      th -= dh;
-      tl -= dl;
-    }
-    t = (tl >> BN_BITS4);
-    tl = (tl << BN_BITS4) & BN_MASK2h;
-    th += t;
-
-    if (l < tl) {
-      th++;
-    }
-    l -= tl;
-    if (h < th) {
-      h += d;
-      q--;
-    }
-    h -= th;
-
-    if (--count == 0) {
-      break;
-    }
-
-    ret = q << BN_BITS4;
-    h = ((h << BN_BITS4) | (l >> BN_BITS4)) & BN_MASK2;
-    l = (l & BN_MASK2l) << BN_BITS4;
-  }
-
-  ret |= q;
-  return ret;
-}
-
-#endif /* !defined(BN_ULLONG) */
-
 #ifdef BN_ULLONG
 BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
                       int n) {
@@ -633,47 +369,51 @@
   do {                                  \
     BN_ULONG hi;                        \
     BN_ULLONG t = (BN_ULLONG)(a) * (b); \
-    t += c0; /* no carry */             \
-    c0 = (BN_ULONG)Lw(t);               \
+    t += (c0); /* no carry */           \
+    (c0) = (BN_ULONG)Lw(t);             \
     hi = (BN_ULONG)Hw(t);               \
-    c1 = (c1 + hi) & BN_MASK2;          \
-    if (c1 < hi)                        \
-      c2++;                             \
+    (c1) = ((c1) + (hi)) & BN_MASK2;    \
+    if ((c1) < hi) {                    \
+      (c2)++;                           \
+    }                                   \
   } while (0)
 
-#define mul_add_c2(a, b, c0, c1, c2)      \
-  do {                                    \
-    BN_ULONG hi;                          \
-    BN_ULLONG t = (BN_ULLONG)(a) * (b);   \
-    BN_ULLONG tt = t + c0; /* no carry */ \
-    c0 = (BN_ULONG)Lw(tt);                \
-    hi = (BN_ULONG)Hw(tt);                \
-    c1 = (c1 + hi) & BN_MASK2;            \
-    if (c1 < hi)                          \
-      c2++;                               \
-    t += c0; /* no carry */               \
-    c0 = (BN_ULONG)Lw(t);                 \
-    hi = (BN_ULONG)Hw(t);                 \
-    c1 = (c1 + hi) & BN_MASK2;            \
-    if (c1 < hi)                          \
-      c2++;                               \
+#define mul_add_c2(a, b, c0, c1, c2)        \
+  do {                                      \
+    BN_ULONG hi;                            \
+    BN_ULLONG t = (BN_ULLONG)(a) * (b);     \
+    BN_ULLONG tt = t + (c0); /* no carry */ \
+    (c0) = (BN_ULONG)Lw(tt);                \
+    hi = (BN_ULONG)Hw(tt);                  \
+    (c1) = ((c1) + hi) & BN_MASK2;          \
+    if ((c1) < hi) {                        \
+      (c2)++;                               \
+    }                                       \
+    t += (c0); /* no carry */               \
+    (c0) = (BN_ULONG)Lw(t);                 \
+    hi = (BN_ULONG)Hw(t);                   \
+    (c1) = ((c1) + hi) & BN_MASK2;          \
+    if ((c1) < hi) {                        \
+      (c2)++;                               \
+    }                                       \
   } while (0)
 
-#define sqr_add_c(a, i, c0, c1, c2)       \
-  do {                                    \
-    BN_ULONG hi;                          \
-    BN_ULLONG t = (BN_ULLONG)a[i] * a[i]; \
-    t += c0; /* no carry */               \
-    c0 = (BN_ULONG)Lw(t);                 \
-    hi = (BN_ULONG)Hw(t);                 \
-    c1 = (c1 + hi) & BN_MASK2;            \
-    if (c1 < hi)                          \
-      c2++;                               \
+#define sqr_add_c(a, i, c0, c1, c2)           \
+  do {                                        \
+    BN_ULONG hi;                              \
+    BN_ULLONG t = (BN_ULLONG)(a)[i] * (a)[i]; \
+    t += (c0); /* no carry */                 \
+    (c0) = (BN_ULONG)Lw(t);                   \
+    hi = (BN_ULONG)Hw(t);                     \
+    (c1) = ((c1) + hi) & BN_MASK2;            \
+    if ((c1) < hi) {                          \
+      (c2)++;                                 \
+    }                                         \
   } while (0)
 
 #define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)
 
-#elif defined(BN_UMULT_LOHI)
+#else
 
 /* Keep in mind that additions to hi can not overflow, because the high word of
  * a multiplication result cannot be all-ones. */
@@ -682,10 +422,10 @@
     BN_ULONG ta = (a), tb = (b);    \
     BN_ULONG lo, hi;                \
     BN_UMULT_LOHI(lo, hi, ta, tb);  \
-    c0 += lo;                       \
-    hi += (c0 < lo) ? 1 : 0;        \
-    c1 += hi;                       \
-    c2 += (c1 < hi) ? 1 : 0;        \
+    (c0) += lo;                     \
+    hi += ((c0) < lo) ? 1 : 0;      \
+    (c1) += hi;                     \
+    (c2) += ((c1) < hi) ? 1 : 0;    \
   } while (0)
 
 #define mul_add_c2(a, b, c0, c1, c2) \
@@ -693,14 +433,14 @@
     BN_ULONG ta = (a), tb = (b);     \
     BN_ULONG lo, hi, tt;             \
     BN_UMULT_LOHI(lo, hi, ta, tb);   \
-    c0 += lo;                        \
-    tt = hi + ((c0 < lo) ? 1 : 0);   \
-    c1 += tt;                        \
-    c2 += (c1 < tt) ? 1 : 0;         \
-    c0 += lo;                        \
+    (c0) += lo;                      \
+    tt = hi + (((c0) < lo) ? 1 : 0); \
+    (c1) += tt;                      \
+    (c2) += ((c1) < tt) ? 1 : 0;     \
+    (c0) += lo;                      \
     hi += (c0 < lo) ? 1 : 0;         \
-    c1 += hi;                        \
-    c2 += (c1 < hi) ? 1 : 0;         \
+    (c1) += hi;                      \
+    (c2) += ((c1) < hi) ? 1 : 0;     \
   } while (0)
 
 #define sqr_add_c(a, i, c0, c1, c2) \
@@ -708,66 +448,14 @@
     BN_ULONG ta = (a)[i];           \
     BN_ULONG lo, hi;                \
     BN_UMULT_LOHI(lo, hi, ta, ta);  \
-    c0 += lo;                       \
+    (c0) += lo;                     \
     hi += (c0 < lo) ? 1 : 0;        \
-    c1 += hi;                       \
-    c2 += (c1 < hi) ? 1 : 0;        \
+    (c1) += hi;                     \
+    (c2) += ((c1) < hi) ? 1 : 0;    \
   } while (0)
 
 #define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)
 
-#else /* !BN_ULLONG */
-
-/* Keep in mind that additions to hi can not overflow, because
- * the high word of a multiplication result cannot be all-ones. */
-
-#define mul_add_c(a, b, c0, c1, c2)        \
-  do {                                     \
-    BN_ULONG lo = LBITS(a), hi = HBITS(a); \
-    BN_ULONG bl = LBITS(b), bh = HBITS(b); \
-    mul64(lo, hi, bl, bh);                 \
-    c0 = (c0 + lo) & BN_MASK2;             \
-    if (c0 < lo)                           \
-      hi++;                                \
-    c1 = (c1 + hi) & BN_MASK2;             \
-    if (c1 < hi)                           \
-      c2++;                                \
-  } while (0)
-
-#define mul_add_c2(a, b, c0, c1, c2)       \
-  do {                                     \
-    BN_ULONG tt;                           \
-    BN_ULONG lo = LBITS(a), hi = HBITS(a); \
-    BN_ULONG bl = LBITS(b), bh = HBITS(b); \
-    mul64(lo, hi, bl, bh);                 \
-    tt = hi;                               \
-    c0 = (c0 + lo) & BN_MASK2;             \
-    if (c0 < lo)                           \
-      tt++;                                \
-    c1 = (c1 + tt) & BN_MASK2;             \
-    if (c1 < tt)                           \
-      c2++;                                \
-    c0 = (c0 + lo) & BN_MASK2;             \
-    if (c0 < lo)                           \
-      hi++;                                \
-    c1 = (c1 + hi) & BN_MASK2;             \
-    if (c1 < hi)                           \
-      c2++;                                \
-  } while (0)
-
-#define sqr_add_c(a, i, c0, c1, c2) \
-  do {                              \
-    BN_ULONG lo, hi;                \
-    sqr64(lo, hi, (a)[i]);          \
-    c0 = (c0 + lo) & BN_MASK2;      \
-    if (c0 < lo)                    \
-      hi++;                         \
-    c1 = (c1 + hi) & BN_MASK2;      \
-    if (c1 < hi)                    \
-      c2++;                         \
-  } while (0)
-
-#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)
 #endif /* !BN_ULLONG */
 
 void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
diff --git a/src/crypto/bn/internal.h b/src/crypto/bn/internal.h
index 72ef4e9..1ee29fd 100644
--- a/src/crypto/bn/internal.h
+++ b/src/crypto/bn/internal.h
@@ -125,13 +125,15 @@
 
 #include <openssl/base.h>
 
-#if defined(OPENSSL_X86_64) && defined(_MSC_VER) && _MSC_VER >= 1400
-#pragma warning(push, 3)
+#if defined(OPENSSL_X86_64) && defined(_MSC_VER)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <intrin.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
 #pragma intrinsic(__umulh, _umul128)
 #endif
 
+#include "../internal.h"
+
 #if defined(__cplusplus)
 extern "C" {
 #endif
@@ -144,7 +146,7 @@
 
 #if !defined(_MSC_VER)
 /* MSVC doesn't support two-word integers on 64-bit. */
-#define BN_ULLONG	__uint128_t
+#define BN_ULLONG	uint128_t
 #endif
 
 #define BN_BITS2	64
@@ -154,10 +156,11 @@
 #define BN_MASK2l	(0xffffffffUL)
 #define BN_MASK2h	(0xffffffff00000000UL)
 #define BN_MASK2h1	(0xffffffff80000000UL)
+#define BN_MONT_CTX_N0_LIMBS 1
 #define BN_TBIT		(0x8000000000000000UL)
 #define BN_DEC_CONV	(10000000000000000000UL)
 #define BN_DEC_NUM	19
-#define TOBN(hi, lo) ((BN_ULONG)hi << 32 | lo)
+#define TOBN(hi, lo) ((BN_ULONG)(hi) << 32 | (lo))
 
 #elif defined(OPENSSL_32_BIT)
 
@@ -169,28 +172,26 @@
 #define BN_MASK2l	(0xffffUL)
 #define BN_MASK2h1	(0xffff8000UL)
 #define BN_MASK2h	(0xffff0000UL)
+/* On some 32-bit platforms, Montgomery multiplication is done using 64-bit
+ * arithmetic with SIMD instructions. On such platforms, |BN_MONT_CTX::n0|
+ * needs to be two words long. Only certain 32-bit platforms actually make use
+ * of n0[1] and shorter R value would suffice for the others. However,
+ * currently only the assembly files know which is which. */
+#define BN_MONT_CTX_N0_LIMBS 2
 #define BN_TBIT		(0x80000000UL)
 #define BN_DEC_CONV	(1000000000UL)
 #define BN_DEC_NUM	9
-#define TOBN(hi, lo) lo, hi
+#define TOBN(hi, lo) (lo), (hi)
 
 #else
 #error "Must define either OPENSSL_32_BIT or OPENSSL_64_BIT"
 #endif
 
 
-/* Pentium pro 16,16,16,32,64 */
-/* Alpha       16,16,16,16.64 */
-#define BN_MULL_SIZE_NORMAL (16)              /* 32 */
-#define BN_MUL_RECURSIVE_SIZE_NORMAL (16)     /* 32 less than */
-#define BN_SQR_RECURSIVE_SIZE_NORMAL (16)     /* 32 */
-#define BN_MUL_LOW_RECURSIVE_SIZE_NORMAL (32) /* 32 */
-#define BN_MONT_CTX_SET_SIZE_WORD (64)        /* 32 */
-
-#define STATIC_BIGNUM(x)                                \
-  {                                                     \
-    (BN_ULONG *)x, sizeof(x) / sizeof(BN_ULONG),        \
-    sizeof(x) / sizeof(BN_ULONG), 0, BN_FLG_STATIC_DATA \
+#define STATIC_BIGNUM(x)                                    \
+  {                                                         \
+    (BN_ULONG *)(x), sizeof(x) / sizeof(BN_ULONG),          \
+        sizeof(x) / sizeof(BN_ULONG), 0, BN_FLG_STATIC_DATA \
   }
 
 #if defined(BN_ULLONG)
@@ -198,10 +199,13 @@
 #define Hw(t) (((BN_ULONG)((t)>>BN_BITS2))&BN_MASK2)
 #endif
 
+/* bn_set_words sets |bn| to the value encoded in the |num| words in |words|,
+ * least significant word first. */
+int bn_set_words(BIGNUM *bn, const BN_ULONG *words, size_t num);
+
 BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
 BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
 void     bn_sqr_words(BN_ULONG *rp, const BN_ULONG *ap, int num);
-BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d);
 BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,int num);
 BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,int num);
 
@@ -223,69 +227,29 @@
 int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
                 const BN_ULONG *np, const BN_ULONG *n0, int num);
 
-#if !defined(BN_ULLONG)
+uint64_t bn_mont_n0(const BIGNUM *n);
+int bn_mod_exp_base_2_vartime(BIGNUM *r, unsigned p, const BIGNUM *n);
 
-#define LBITS(a) ((a) & BN_MASK2l)
-#define HBITS(a) (((a) >> BN_BITS4) & BN_MASK2l)
-#define L2HBITS(a) (((a) << BN_BITS4) & BN_MASK2)
-
-#define LLBITS(a) ((a) & BN_MASKl)
-#define LHBITS(a) (((a) >> BN_BITS2) & BN_MASKl)
-#define LL2HBITS(a) ((BN_ULLONG)((a) & BN_MASKl) << BN_BITS2)
-
-#define mul64(l, h, bl, bh)       \
-  {                               \
-    BN_ULONG m, m1, lt, ht;       \
-                                  \
-    lt = l;                       \
-    ht = h;                       \
-    m = (bh) * (lt);              \
-    lt = (bl) * (lt);             \
-    m1 = (bl) * (ht);             \
-    ht = (bh) * (ht);             \
-    m = (m + m1) & BN_MASK2;      \
-    if (m < m1)                   \
-      ht += L2HBITS((BN_ULONG)1); \
-    ht += HBITS(m);               \
-    m1 = L2HBITS(m);              \
-    lt = (lt + m1) & BN_MASK2;    \
-    if (lt < m1)                  \
-      ht++;                       \
-    (l) = lt;                     \
-    (h) = ht;                     \
-  }
-
-#endif  /* !defined(BN_ULLONG) */
-
-#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64)
-# if defined(__GNUC__) && __GNUC__ >= 2
-#  define BN_UMULT_HIGH(a,b)	({	\
-	register BN_ULONG ret,discard;	\
-	__asm__ ("mulq	%3"		\
-	     : "=a"(discard),"=d"(ret)	\
-	     : "a"(a), "g"(b)		\
-	     : "cc");			\
-	ret;			})
-#  define BN_UMULT_LOHI(low,high,a,b)	\
-	__asm__ ("mulq	%3"		\
-		: "=a"(low),"=d"(high)	\
-		: "a"(a),"g"(b)		\
-		: "cc");
-# elif defined(_MSC_VER) && _MSC_VER >= 1400
-#  define BN_UMULT_HIGH(a, b) __umulh((a), (b))
-#  define BN_UMULT_LOHI(low, high, a, b) ((low) = _umul128((a), (b), &(high)))
-# endif
-#elif !defined(OPENSSL_NO_ASM) && defined(OPENSSL_AARCH64)
-# if defined(__GNUC__) && __GNUC__>=2
-#  define BN_UMULT_HIGH(a,b)	({	\
-	register BN_ULONG ret;		\
-	__asm__ ("umulh	%0,%1,%2"	\
-	     : "=r"(ret)		\
-	     : "r"(a), "r"(b));		\
-	ret;			})
-# endif
+#if defined(OPENSSL_X86_64) && defined(_MSC_VER)
+#define BN_UMULT_LOHI(low, high, a, b) ((low) = _umul128((a), (b), &(high)))
 #endif
 
+#if !defined(BN_ULLONG) && !defined(BN_UMULT_LOHI)
+#error "Either BN_ULLONG or BN_UMULT_LOHI must be defined on every platform."
+#endif
+
+/* bn_mod_inverse_prime sets |out| to the modular inverse of |a| modulo |p|,
+ * computed with Fermat's Little Theorem. It returns one on success and zero on
+ * error. If |mont_p| is NULL, one will be computed temporarily. */
+int bn_mod_inverse_prime(BIGNUM *out, const BIGNUM *a, const BIGNUM *p,
+                         BN_CTX *ctx, const BN_MONT_CTX *mont_p);
+
+/* bn_mod_inverse_secret_prime behaves like |bn_mod_inverse_prime| but uses
+ * |BN_mod_exp_mont_consttime| instead of |BN_mod_exp_mont| in hopes of
+ * protecting the exponent. */
+int bn_mod_inverse_secret_prime(BIGNUM *out, const BIGNUM *a, const BIGNUM *p,
+                                BN_CTX *ctx, const BN_MONT_CTX *mont_p);
+
 
 #if defined(__cplusplus)
 }  /* extern C */
diff --git a/src/crypto/bn/kronecker.c b/src/crypto/bn/kronecker.c
index 23ef79a..2089851 100644
--- a/src/crypto/bn/kronecker.c
+++ b/src/crypto/bn/kronecker.c
@@ -144,6 +144,7 @@
       i++;
     }
     if (!BN_rshift(A, A, i)) {
+      ret = -2;
       goto end;
     }
     if (i & 1) {
diff --git a/src/crypto/bn/montgomery.c b/src/crypto/bn/montgomery.c
index 18da0da..29e82a4 100644
--- a/src/crypto/bn/montgomery.c
+++ b/src/crypto/bn/montgomery.c
@@ -108,6 +108,7 @@
 
 #include <openssl/bn.h>
 
+#include <assert.h>
 #include <string.h>
 
 #include <openssl/err.h>
@@ -124,6 +125,11 @@
 #define OPENSSL_BN_ASM_MONT
 #endif
 
+static int bn_mod_mul_montgomery_fallback(BIGNUM *r, const BIGNUM *a,
+                                          const BIGNUM *b,
+                                          const BN_MONT_CTX *mont, BN_CTX *ctx);
+
+
 BN_MONT_CTX *BN_MONT_CTX_new(void) {
   BN_MONT_CTX *ret = OPENSSL_malloc(sizeof(BN_MONT_CTX));
 
@@ -131,7 +137,7 @@
     return NULL;
   }
 
-  memset(ret, 0, sizeof(BN_MONT_CTX));
+  OPENSSL_memset(ret, 0, sizeof(BN_MONT_CTX));
   BN_init(&ret->RR);
   BN_init(&ret->N);
 
@@ -162,141 +168,69 @@
   return to;
 }
 
-int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) {
-  int ret = 0;
-  BIGNUM *Ri, *R;
-  BIGNUM tmod;
-  BN_ULONG buf[2];
+OPENSSL_COMPILE_ASSERT(BN_MONT_CTX_N0_LIMBS == 1 || BN_MONT_CTX_N0_LIMBS == 2,
+                       BN_MONT_CTX_N0_LIMBS_VALUE_INVALID);
+OPENSSL_COMPILE_ASSERT(sizeof(BN_ULONG) * BN_MONT_CTX_N0_LIMBS ==
+                       sizeof(uint64_t), BN_MONT_CTX_set_64_bit_mismatch);
 
+int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) {
   if (BN_is_zero(mod)) {
     OPENSSL_PUT_ERROR(BN, BN_R_DIV_BY_ZERO);
     return 0;
   }
-
-  BN_CTX_start(ctx);
-  Ri = BN_CTX_get(ctx);
-  if (Ri == NULL) {
-    goto err;
+  if (!BN_is_odd(mod)) {
+    OPENSSL_PUT_ERROR(BN, BN_R_CALLED_WITH_EVEN_MODULUS);
+    return 0;
   }
-  R = &mont->RR; /* grab RR as a temp */
+  if (BN_is_negative(mod)) {
+    OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER);
+    return 0;
+  }
+
+  /* Save the modulus. */
   if (!BN_copy(&mont->N, mod)) {
-    goto err; /* Set N */
-  }
-  mont->N.neg = 0;
-
-  BN_init(&tmod);
-  tmod.d = buf;
-  tmod.dmax = 2;
-  tmod.neg = 0;
-
-#if defined(OPENSSL_BN_ASM_MONT) && (BN_BITS2 <= 32)
-  /* Only certain BN_BITS2<=32 platforms actually make use of
-   * n0[1], and we could use the #else case (with a shorter R
-   * value) for the others.  However, currently only the assembler
-   * files do know which is which. */
-
-  BN_zero(R);
-  if (!BN_set_bit(R, 2 * BN_BITS2)) {
-    goto err;
+    OPENSSL_PUT_ERROR(BN, ERR_R_INTERNAL_ERROR);
+    return 0;
   }
 
-  tmod.top = 0;
-  if ((buf[0] = mod->d[0])) {
-    tmod.top = 1;
-  }
-  if ((buf[1] = mod->top > 1 ? mod->d[1] : 0)) {
-    tmod.top = 2;
-  }
-
-  if (BN_mod_inverse(Ri, R, &tmod, ctx) == NULL) {
-    goto err;
-  }
-  if (!BN_lshift(Ri, Ri, 2 * BN_BITS2)) {
-    goto err; /* R*Ri */
-  }
-  if (!BN_is_zero(Ri)) {
-    if (!BN_sub_word(Ri, 1)) {
-      goto err;
-    }
-  } else {
-    /* if N mod word size == 1 */
-    if (bn_expand(Ri, (int)sizeof(BN_ULONG) * 2) == NULL) {
-      goto err;
-    }
-    /* Ri-- (mod double word size) */
-    Ri->neg = 0;
-    Ri->d[0] = BN_MASK2;
-    Ri->d[1] = BN_MASK2;
-    Ri->top = 2;
-  }
-
-  if (!BN_div(Ri, NULL, Ri, &tmod, ctx)) {
-    goto err;
-  }
-  /* Ni = (R*Ri-1)/N,
-   * keep only couple of least significant words: */
-  mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0;
-  mont->n0[1] = (Ri->top > 1) ? Ri->d[1] : 0;
+  /* Find n0 such that n0 * N == -1 (mod r).
+   *
+   * Only certain BN_BITS2<=32 platforms actually make use of n0[1]. For the
+   * others, we could use a shorter R value and use faster |BN_ULONG|-based
+   * math instead of |uint64_t|-based math, which would be double-precision.
+   * However, currently only the assembler files know which is which. */
+  uint64_t n0 = bn_mont_n0(mod);
+  mont->n0[0] = (BN_ULONG)n0;
+#if BN_MONT_CTX_N0_LIMBS == 2
+  mont->n0[1] = (BN_ULONG)(n0 >> BN_BITS2);
 #else
-  BN_zero(R);
-  if (!BN_set_bit(R, BN_BITS2)) {
-    goto err; /* R */
-  }
-
-  buf[0] = mod->d[0]; /* tmod = N mod word size */
-  buf[1] = 0;
-  tmod.top = buf[0] != 0 ? 1 : 0;
-  /* Ri = R^-1 mod N*/
-  if (BN_mod_inverse(Ri, R, &tmod, ctx) == NULL) {
-    goto err;
-  }
-  if (!BN_lshift(Ri, Ri, BN_BITS2)) {
-    goto err; /* R*Ri */
-  }
-  if (!BN_is_zero(Ri)) {
-    if (!BN_sub_word(Ri, 1)) {
-      goto err;
-    }
-  } else {
-    /* if N mod word size == 1 */
-    if (!BN_set_word(Ri, BN_MASK2)) {
-      goto err; /* Ri-- (mod word size) */
-    }
-  }
-  if (!BN_div(Ri, NULL, Ri, &tmod, ctx)) {
-    goto err;
-  }
-  /* Ni = (R*Ri-1)/N,
-   * keep only least significant word: */
-  mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0;
   mont->n0[1] = 0;
 #endif
 
-  /* RR = (2^ri)^2 == 2^(ri*2) == 1 << (ri*2), which has its (ri*2)th bit set. */
-  int ri = (BN_num_bits(mod) + (BN_BITS2 - 1)) / BN_BITS2 * BN_BITS2;
-  BN_zero(&(mont->RR));
-  if (!BN_set_bit(&(mont->RR), ri * 2)) {
-    goto err;
-  }
-  if (!BN_mod(&(mont->RR), &(mont->RR), &(mont->N), ctx)) {
-    goto err;
+  /* Save RR = R**2 (mod N). R is the smallest power of 2**BN_BITS such that R
+   * > mod. Even though the assembly on some 32-bit platforms works with 64-bit
+   * values, using |BN_BITS2| here, rather than |BN_MONT_CTX_N0_LIMBS *
+   * BN_BITS2|, is correct because R**2 will still be a multiple of the latter
+   * as |BN_MONT_CTX_N0_LIMBS| is either one or two.
+   *
+   * XXX: This is not constant time with respect to |mont->N|, but it should
+   * be. */
+  unsigned lgBigR = (BN_num_bits(mod) + (BN_BITS2 - 1)) / BN_BITS2 * BN_BITS2;
+  if (!bn_mod_exp_base_2_vartime(&mont->RR, lgBigR * 2, &mont->N)) {
+    return 0;
   }
 
-  ret = 1;
-
-err:
-  BN_CTX_end(ctx);
-  return ret;
+  return 1;
 }
 
-BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, CRYPTO_MUTEX *lock,
-                                    const BIGNUM *mod, BN_CTX *bn_ctx) {
+int BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, CRYPTO_MUTEX *lock,
+                           const BIGNUM *mod, BN_CTX *bn_ctx) {
   CRYPTO_MUTEX_lock_read(lock);
   BN_MONT_CTX *ctx = *pmont;
-  CRYPTO_MUTEX_unlock(lock);
+  CRYPTO_MUTEX_unlock_read(lock);
 
   if (ctx) {
-    return ctx;
+    return 1;
   }
 
   CRYPTO_MUTEX_lock_write(lock);
@@ -317,8 +251,8 @@
   *pmont = ctx;
 
 out:
-  CRYPTO_MUTEX_unlock(lock);
-  return ctx;
+  CRYPTO_MUTEX_unlock_write(lock);
+  return ctx != NULL;
 }
 
 int BN_to_montgomery(BIGNUM *ret, const BIGNUM *a, const BN_MONT_CTX *mont,
@@ -326,14 +260,12 @@
   return BN_mod_mul_montgomery(ret, a, &mont->RR, mont, ctx);
 }
 
-#if 0
 static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r,
                                    const BN_MONT_CTX *mont) {
-  const BIGNUM *n;
   BN_ULONG *ap, *np, *rp, n0, v, carry;
   int nl, max, i;
 
-  n = &mont->N;
+  const BIGNUM *n = &mont->N;
   nl = n->top;
   if (nl == 0) {
     ret->top = 0;
@@ -351,7 +283,7 @@
 
   /* clear the top words of T */
   if (max > r->top) {
-    memset(&rp[r->top], 0, (max - r->top) * sizeof(BN_ULONG));
+    OPENSSL_memset(&rp[r->top], 0, (max - r->top) * sizeof(BN_ULONG));
   }
 
   r->top = max;
@@ -376,13 +308,13 @@
 
   {
     BN_ULONG *nrp;
-    size_t m;
+    uintptr_t m;
 
     v = bn_sub_words(rp, ap, np, nl) - carry;
     /* if subtraction result is real, then trick unconditional memcpy below to
      * perform in-place "refresh" instead of actual copy. */
-    m = (0 - (size_t)v);
-    nrp = (BN_ULONG *)(((intptr_t)rp & ~m) | ((intptr_t)ap & m));
+    m = (0u - (uintptr_t)v);
+    nrp = (BN_ULONG *)(((uintptr_t)rp & ~m) | ((uintptr_t)ap & m));
 
     for (i = 0, nl -= 4; i < nl; i += 4) {
       BN_ULONG t1, t2, t3, t4;
@@ -411,129 +343,66 @@
 
   return 1;
 }
-#endif
 
-#define PTR_SIZE_INT size_t
-
-static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, const BN_MONT_CTX *mont)
-	{
-	BIGNUM *n;
-	BN_ULONG *ap,*np,*rp,n0,v,carry;
-	int nl,max,i;
-
-	n= (BIGNUM*) &(mont->N);
-	nl=n->top;
-	if (nl == 0) { ret->top=0; return(1); }
-
-	max=(2*nl); /* carry is stored separately */
-	if (bn_wexpand(r,max) == NULL) return(0);
-
-	r->neg^=n->neg;
-	np=n->d;
-	rp=r->d;
-
-	/* clear the top words of T */
-#if 1
-	for (i=r->top; i<max; i++) /* memset? XXX */
-		rp[i]=0;
-#else
-	memset(&(rp[r->top]),0,(max-r->top)*sizeof(BN_ULONG)); 
-#endif
-
-	r->top=max;
-	n0=mont->n0[0];
-
-	for (carry=0, i=0; i<nl; i++, rp++)
-		{
-		v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2);
-		v = (v+carry+rp[nl])&BN_MASK2;
-		carry |= (v != rp[nl]);
-		carry &= (v <= rp[nl]);
-		rp[nl]=v;
-		}
-
-	if (bn_wexpand(ret,nl) == NULL) return(0);
-	ret->top=nl;
-	ret->neg=r->neg;
-
-	rp=ret->d;
-	ap=&(r->d[nl]);
-
-	{
-	BN_ULONG *nrp;
-	size_t m;
-
-	v=bn_sub_words(rp,ap,np,nl)-carry;
-	/* if subtraction result is real, then
-	 * trick unconditional memcpy below to perform in-place
-	 * "refresh" instead of actual copy. */
-	m=(0-(size_t)v);
-	nrp=(BN_ULONG *)(((PTR_SIZE_INT)rp&~m)|((PTR_SIZE_INT)ap&m));
-
-	for (i=0,nl-=4; i<nl; i+=4)
-		{
-		BN_ULONG t1,t2,t3,t4;
-		
-		t1=nrp[i+0];
-		t2=nrp[i+1];
-		t3=nrp[i+2];	ap[i+0]=0;
-		t4=nrp[i+3];	ap[i+1]=0;
-		rp[i+0]=t1;	ap[i+2]=0;
-		rp[i+1]=t2;	ap[i+3]=0;
-		rp[i+2]=t3;
-		rp[i+3]=t4;
-		}
-	for (nl+=4; i<nl; i++)
-		rp[i]=nrp[i], ap[i]=0;
-	}
-	bn_correct_top(r);
-	bn_correct_top(ret);
-
-	return(1);
-	}
-
-int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, const BN_MONT_CTX *mont,
+int BN_from_montgomery(BIGNUM *r, const BIGNUM *a, const BN_MONT_CTX *mont,
                        BN_CTX *ctx) {
-  int retn = 0;
+  int ret = 0;
   BIGNUM *t;
 
   BN_CTX_start(ctx);
   t = BN_CTX_get(ctx);
-  if (t == NULL) {
-    return 0;
+  if (t == NULL ||
+      !BN_copy(t, a)) {
+    goto err;
   }
 
-  if (BN_copy(t, a)) {
-    retn = BN_from_montgomery_word(ret, t, mont);
-  }
+  ret = BN_from_montgomery_word(r, t, mont);
+
+err:
   BN_CTX_end(ctx);
 
-  return retn;
+  return ret;
 }
 
 int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
                           const BN_MONT_CTX *mont, BN_CTX *ctx) {
-  BIGNUM *tmp;
-  int ret = 0;
-
-#if defined(OPENSSL_BN_ASM_MONT)
+#if !defined(OPENSSL_BN_ASM_MONT)
+  return bn_mod_mul_montgomery_fallback(r, a, b, mont, ctx);
+#else
   int num = mont->N.top;
 
-  if (num > 1 && a->top == num && b->top == num) {
-    if (bn_wexpand(r, num) == NULL) {
-      return 0;
-    }
-    if (bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) {
-      r->neg = a->neg ^ b->neg;
-      r->top = num;
-      bn_correct_top(r);
-      return 1;
-    }
+  /* |bn_mul_mont| requires at least 128 bits of limbs, at least for x86. */
+  if (num < (128 / BN_BITS2) ||
+      a->top != num ||
+      b->top != num) {
+    return bn_mod_mul_montgomery_fallback(r, a, b, mont, ctx);
   }
+
+  if (bn_wexpand(r, num) == NULL) {
+    return 0;
+  }
+  if (!bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) {
+    /* The check above ensures this won't happen. */
+    assert(0);
+    OPENSSL_PUT_ERROR(BN, ERR_R_INTERNAL_ERROR);
+    return 0;
+  }
+  r->neg = a->neg ^ b->neg;
+  r->top = num;
+  bn_correct_top(r);
+
+  return 1;
 #endif
+}
+
+static int bn_mod_mul_montgomery_fallback(BIGNUM *r, const BIGNUM *a,
+                                          const BIGNUM *b,
+                                          const BN_MONT_CTX *mont,
+                                          BN_CTX *ctx) {
+  int ret = 0;
 
   BN_CTX_start(ctx);
-  tmp = BN_CTX_get(ctx);
+  BIGNUM *tmp = BN_CTX_get(ctx);
   if (tmp == NULL) {
     goto err;
   }
diff --git a/src/crypto/bn/montgomery_inv.c b/src/crypto/bn/montgomery_inv.c
new file mode 100644
index 0000000..9264adb
--- /dev/null
+++ b/src/crypto/bn/montgomery_inv.c
@@ -0,0 +1,207 @@
+/* Copyright 2016 Brian Smith.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/bn.h>
+
+#include <assert.h>
+
+#include "internal.h"
+#include "../internal.h"
+
+
+static uint64_t bn_neg_inv_mod_r_u64(uint64_t n);
+
+OPENSSL_COMPILE_ASSERT(BN_MONT_CTX_N0_LIMBS == 1 || BN_MONT_CTX_N0_LIMBS == 2,
+                       BN_MONT_CTX_N0_LIMBS_VALUE_INVALID);
+OPENSSL_COMPILE_ASSERT(sizeof(uint64_t) ==
+                       BN_MONT_CTX_N0_LIMBS * sizeof(BN_ULONG),
+                       BN_MONT_CTX_N0_LIMBS_DOES_NOT_MATCH_UINT64_T);
+
+/* LG_LITTLE_R is log_2(r). */
+#define LG_LITTLE_R (BN_MONT_CTX_N0_LIMBS * BN_BITS2)
+
+uint64_t bn_mont_n0(const BIGNUM *n) {
+  /* These conditions are checked by the caller, |BN_MONT_CTX_set|. */
+  assert(!BN_is_zero(n));
+  assert(!BN_is_negative(n));
+  assert(BN_is_odd(n));
+
+  /* r == 2**(BN_MONT_CTX_N0_LIMBS * BN_BITS2) and LG_LITTLE_R == lg(r). This
+   * ensures that we can do integer division by |r| by simply ignoring
+   * |BN_MONT_CTX_N0_LIMBS| limbs. Similarly, we can calculate values modulo
+   * |r| by just looking at the lowest |BN_MONT_CTX_N0_LIMBS| limbs. This is
+   * what makes Montgomery multiplication efficient.
+   *
+   * As shown in Algorithm 1 of "Fast Prime Field Elliptic Curve Cryptography
+   * with 256 Bit Primes" by Shay Gueron and Vlad Krasnov, in the loop of a
+   * multi-limb Montgomery multiplication of |a * b (mod n)|, given the
+   * unreduced product |t == a * b|, we repeatedly calculate:
+   *
+   *    t1 := t % r         |t1| is |t|'s lowest limb (see previous paragraph).
+   *    t2 := t1*n0*n
+   *    t3 := t + t2
+   *    t := t3 / r         copy all limbs of |t3| except the lowest to |t|.
+   *
+   * In the last step, it would only make sense to ignore the lowest limb of
+   * |t3| if it were zero. The middle steps ensure that this is the case:
+   *
+   *                            t3 ==  0 (mod r)
+   *                        t + t2 ==  0 (mod r)
+   *                   t + t1*n0*n ==  0 (mod r)
+   *                       t1*n0*n == -t (mod r)
+   *                        t*n0*n == -t (mod r)
+   *                          n0*n == -1 (mod r)
+   *                            n0 == -1/n (mod r)
+   *
+   * Thus, in each iteration of the loop, we multiply by the constant factor
+   * |n0|, the negative inverse of n (mod r). */
+
+  /* n_mod_r = n % r. As explained above, this is done by taking the lowest
+   * |BN_MONT_CTX_N0_LIMBS| limbs of |n|. */
+  uint64_t n_mod_r = n->d[0];
+#if BN_MONT_CTX_N0_LIMBS == 2
+  if (n->top > 1) {
+    n_mod_r |= (uint64_t)n->d[1] << BN_BITS2;
+  }
+#endif
+
+  return bn_neg_inv_mod_r_u64(n_mod_r);
+}
+
+/* bn_neg_inv_r_mod_n_u64 calculates the -1/n mod r; i.e. it calculates |v|
+ * such that u*r - v*n == 1. |r| is the constant defined in |bn_mont_n0|. |n|
+ * must be odd.
+ *
+ * This is derived from |xbinGCD| in Henry S. Warren, Jr.'s "Montgomery
+ * Multiplication" (http://www.hackersdelight.org/MontgomeryMultiplication.pdf).
+ * It is very similar to the MODULAR-INVERSE function in Stephen R. Dussé's and
+ * Burton S. Kaliski Jr.'s "A Cryptographic Library for the Motorola DSP56000"
+ * (http://link.springer.com/chapter/10.1007%2F3-540-46877-3_21).
+ *
+ * This is inspired by Joppe W. Bos's "Constant Time Modular Inversion"
+ * (http://www.joppebos.com/files/CTInversion.pdf) so that the inversion is
+ * constant-time with respect to |n|. We assume uint64_t additions,
+ * subtractions, shifts, and bitwise operations are all constant time, which
+ * may be a large leap of faith on 32-bit targets. We avoid division and
+ * multiplication, which tend to be the most problematic in terms of timing
+ * leaks.
+ *
+ * Most GCD implementations return values such that |u*r + v*n == 1|, so the
+ * caller would have to negate the resultant |v| for the purpose of Montgomery
+ * multiplication. This implementation does the negation implicitly by doing
+ * the computations as a difference instead of a sum. */
+static uint64_t bn_neg_inv_mod_r_u64(uint64_t n) {
+  assert(n % 2 == 1);
+
+  /* alpha == 2**(lg r - 1) == r / 2. */
+  static const uint64_t alpha = UINT64_C(1) << (LG_LITTLE_R - 1);
+
+  const uint64_t beta = n;
+
+  uint64_t u = 1;
+  uint64_t v = 0;
+
+  /* The invariant maintained from here on is:
+   * 2**(lg r - i) == u*2*alpha - v*beta. */
+  for (size_t i = 0; i < LG_LITTLE_R; ++i) {
+#if BN_BITS2 == 64 && defined(BN_ULLONG)
+    assert((BN_ULLONG)(1) << (LG_LITTLE_R - i) ==
+           ((BN_ULLONG)u * 2 * alpha) - ((BN_ULLONG)v * beta));
+#endif
+
+    /* Delete a common factor of 2 in u and v if |u| is even. Otherwise, set
+     * |u = (u + beta) / 2| and |v = (v / 2) + alpha|. */
+
+    uint64_t u_is_odd = UINT64_C(0) - (u & 1); /* Either 0xff..ff or 0. */
+
+    /* The addition can overflow, so use Dietz's method for it.
+     *
+     * Dietz calculates (x+y)/2 by (x⊕y)>>1 + x&y. This is valid for all
+     * (unsigned) x and y, even when x+y overflows. Evidence for 32-bit values
+     * (embedded in 64 bits to so that overflow can be ignored):
+     *
+     * (declare-fun x () (_ BitVec 64))
+     * (declare-fun y () (_ BitVec 64))
+     * (assert (let (
+     *    (one (_ bv1 64))
+     *    (thirtyTwo (_ bv32 64)))
+     *    (and
+     *      (bvult x (bvshl one thirtyTwo))
+     *      (bvult y (bvshl one thirtyTwo))
+     *      (not (=
+     *        (bvadd (bvlshr (bvxor x y) one) (bvand x y))
+     *        (bvlshr (bvadd x y) one)))
+     * )))
+     * (check-sat) */
+    uint64_t beta_if_u_is_odd = beta & u_is_odd; /* Either |beta| or 0. */
+    u = ((u ^ beta_if_u_is_odd) >> 1) + (u & beta_if_u_is_odd);
+
+    uint64_t alpha_if_u_is_odd = alpha & u_is_odd; /* Either |alpha| or 0. */
+    v = (v >> 1) + alpha_if_u_is_odd;
+  }
+
+  /* The invariant now shows that u*r - v*n == 1 since r == 2 * alpha. */
+#if BN_BITS2 == 64 && defined(BN_ULLONG)
+  assert(1 == ((BN_ULLONG)u * 2 * alpha) - ((BN_ULLONG)v * beta));
+#endif
+
+  return v;
+}
+
+/* bn_mod_exp_base_2_vartime calculates r = 2**p (mod n). |p| must be larger
+ * than log_2(n); i.e. 2**p must be larger than |n|. |n| must be positive and
+ * odd. */
+int bn_mod_exp_base_2_vartime(BIGNUM *r, unsigned p, const BIGNUM *n) {
+  assert(!BN_is_zero(n));
+  assert(!BN_is_negative(n));
+  assert(BN_is_odd(n));
+
+  BN_zero(r);
+
+  unsigned n_bits = BN_num_bits(n);
+  assert(n_bits != 0);
+  if (n_bits == 1) {
+    return 1;
+  }
+
+  /* Set |r| to the smallest power of two larger than |n|. */
+  assert(p > n_bits);
+  if (!BN_set_bit(r, n_bits)) {
+    return 0;
+  }
+
+  /* Unconditionally reduce |r|. */
+  assert(BN_cmp(r, n) > 0);
+  if (!BN_usub(r, r, n)) {
+    return 0;
+  }
+  assert(BN_cmp(r, n) < 0);
+
+  for (unsigned i = n_bits; i < p; ++i) {
+    /* This is like |BN_mod_lshift1_quick| except using |BN_usub|.
+     *
+     * TODO: Replace this with the use of a constant-time variant of
+     * |BN_mod_lshift1_quick|. */
+    if (!BN_lshift1(r, r)) {
+      return 0;
+    }
+    if (BN_cmp(r, n) >= 0) {
+      if (!BN_usub(r, r, n)) {
+        return 0;
+      }
+    }
+  }
+
+  return 1;
+}
diff --git a/src/crypto/bn/mul.c b/src/crypto/bn/mul.c
index 029a59e..fdf2c69 100644
--- a/src/crypto/bn/mul.c
+++ b/src/crypto/bn/mul.c
@@ -62,7 +62,12 @@
 #include "internal.h"
 
 
-void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb) {
+#define BN_MUL_RECURSIVE_SIZE_NORMAL 16
+#define BN_SQR_RECURSIVE_SIZE_NORMAL BN_MUL_RECURSIVE_SIZE_NORMAL
+
+
+static void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b,
+                          int nb) {
   BN_ULONG *rr;
 
   if (na < nb) {
@@ -107,31 +112,6 @@
   }
 }
 
-void bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n) {
-  bn_mul_words(r, a, n, b[0]);
-
-  for (;;) {
-    if (--n <= 0) {
-      return;
-    }
-    bn_mul_add_words(&(r[1]), a, n, b[1]);
-    if (--n <= 0) {
-      return;
-    }
-    bn_mul_add_words(&(r[2]), a, n, b[2]);
-    if (--n <= 0) {
-      return;
-    }
-    bn_mul_add_words(&(r[3]), a, n, b[3]);
-    if (--n <= 0) {
-      return;
-    }
-    bn_mul_add_words(&(r[4]), a, n, b[4]);
-    r += 4;
-    b += 4;
-  }
-}
-
 #if !defined(OPENSSL_X86) || defined(OPENSSL_NO_ASM)
 /* Here follows specialised variants of bn_add_words() and bn_sub_words(). They
  * have the property performing operations on arrays of different sizes. The
@@ -332,7 +312,8 @@
   if (n2 < BN_MUL_RECURSIVE_SIZE_NORMAL) {
     bn_mul_normal(r, a, n2 + dna, b, n2 + dnb);
     if ((dna + dnb) < 0) {
-      memset(&r[2 * n2 + dna + dnb], 0, sizeof(BN_ULONG) * -(dna + dnb));
+      OPENSSL_memset(&r[2 * n2 + dna + dnb], 0,
+                     sizeof(BN_ULONG) * -(dna + dnb));
     }
     return;
   }
@@ -378,7 +359,7 @@
     if (!zero) {
       bn_mul_comba4(&(t[n2]), t, &(t[n]));
     } else {
-      memset(&(t[n2]), 0, 8 * sizeof(BN_ULONG));
+      OPENSSL_memset(&(t[n2]), 0, 8 * sizeof(BN_ULONG));
     }
 
     bn_mul_comba4(r, a, b);
@@ -388,7 +369,7 @@
     if (!zero) {
       bn_mul_comba8(&(t[n2]), t, &(t[n]));
     } else {
-      memset(&(t[n2]), 0, 16 * sizeof(BN_ULONG));
+      OPENSSL_memset(&(t[n2]), 0, 16 * sizeof(BN_ULONG));
     }
 
     bn_mul_comba8(r, a, b);
@@ -398,7 +379,7 @@
     if (!zero) {
       bn_mul_recursive(&(t[n2]), t, &(t[n]), n, 0, 0, p);
     } else {
-      memset(&(t[n2]), 0, n2 * sizeof(BN_ULONG));
+      OPENSSL_memset(&(t[n2]), 0, n2 * sizeof(BN_ULONG));
     }
     bn_mul_recursive(r, a, b, n, 0, 0, p);
     bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]), n, dna, dnb, p);
@@ -493,7 +474,7 @@
     bn_mul_comba8(&(t[n2]), t, &(t[n]));
     bn_mul_comba8(r, a, b);
     bn_mul_normal(&(r[n2]), &(a[n]), tna, &(b[n]), tnb);
-    memset(&(r[n2 + tna + tnb]), 0, sizeof(BN_ULONG) * (n2 - tna - tnb));
+    OPENSSL_memset(&(r[n2 + tna + tnb]), 0, sizeof(BN_ULONG) * (n2 - tna - tnb));
   } else {
     p = &(t[n2 * 2]);
     bn_mul_recursive(&(t[n2]), t, &(t[n]), n, 0, 0, p);
@@ -509,14 +490,15 @@
 
     if (j == 0) {
       bn_mul_recursive(&(r[n2]), &(a[n]), &(b[n]), i, tna - i, tnb - i, p);
-      memset(&(r[n2 + i * 2]), 0, sizeof(BN_ULONG) * (n2 - i * 2));
+      OPENSSL_memset(&(r[n2 + i * 2]), 0, sizeof(BN_ULONG) * (n2 - i * 2));
     } else if (j > 0) {
       /* eg, n == 16, i == 8 and tn == 11 */
       bn_mul_part_recursive(&(r[n2]), &(a[n]), &(b[n]), i, tna - i, tnb - i, p);
-      memset(&(r[n2 + tna + tnb]), 0, sizeof(BN_ULONG) * (n2 - tna - tnb));
+      OPENSSL_memset(&(r[n2 + tna + tnb]), 0,
+                     sizeof(BN_ULONG) * (n2 - tna - tnb));
     } else {
       /* (j < 0) eg, n == 16, i == 8 and tn == 5 */
-      memset(&(r[n2]), 0, sizeof(BN_ULONG) * n2);
+      OPENSSL_memset(&(r[n2]), 0, sizeof(BN_ULONG) * n2);
       if (tna < BN_MUL_RECURSIVE_SIZE_NORMAL &&
           tnb < BN_MUL_RECURSIVE_SIZE_NORMAL) {
         bn_mul_normal(&(r[n2]), &(a[n]), tna, &(b[n]), tnb);
@@ -618,7 +600,8 @@
     }
   }
 
-  if ((al >= BN_MULL_SIZE_NORMAL) && (bl >= BN_MULL_SIZE_NORMAL)) {
+  static const int kMulNormalSize = 16;
+  if (al >= kMulNormalSize && bl >= kMulNormalSize) {
     if (i >= -1 && i <= 1) {
       /* Find out the power of two lower or equal
          to the longest of the two numbers */
@@ -754,7 +737,7 @@
   if (!zero) {
     bn_sqr_recursive(&(t[n2]), t, n, p);
   } else {
-    memset(&(t[n2]), 0, n2 * sizeof(BN_ULONG));
+    OPENSSL_memset(&(t[n2]), 0, n2 * sizeof(BN_ULONG));
   }
   bn_sqr_recursive(r, a, n, p);
   bn_sqr_recursive(&(r[n2]), &(a[n]), n, p);
diff --git a/src/crypto/bn/prime.c b/src/crypto/bn/prime.c
index d07e609..0f668d7 100644
--- a/src/crypto/bn/prime.c
+++ b/src/crypto/bn/prime.c
@@ -496,7 +496,11 @@
 
   if (do_trial_division) {
     for (i = 1; i < NUMPRIMES; i++) {
-      if (BN_mod_word(a, primes[i]) == 0) {
+      BN_ULONG mod = BN_mod_word(a, primes[i]);
+      if (mod == (BN_ULONG)-1) {
+        goto err;
+      }
+      if (mod == 0) {
         return 0;
       }
     }
@@ -647,13 +651,17 @@
   char is_single_word = bits <= BN_BITS2;
 
 again:
-  if (!BN_rand(rnd, bits, 1, 1)) {
+  if (!BN_rand(rnd, bits, BN_RAND_TOP_TWO, BN_RAND_BOTTOM_ODD)) {
     return 0;
   }
 
   /* we now have a random number 'rnd' to test. */
   for (i = 1; i < NUMPRIMES; i++) {
-    mods[i] = (uint16_t)BN_mod_word(rnd, (BN_ULONG)primes[i]);
+    BN_ULONG mod = BN_mod_word(rnd, (BN_ULONG)primes[i]);
+    if (mod == (BN_ULONG)-1) {
+      return 0;
+    }
+    mods[i] = (uint16_t)mod;
   }
   /* If bits is so small that it fits into a single word then we
    * additionally don't want to exceed that many bits. */
@@ -727,7 +735,7 @@
     goto err;
   }
 
-  if (!BN_rand(rnd, bits, 0, 1)) {
+  if (!BN_rand(rnd, bits, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ODD)) {
     goto err;
   }
 
@@ -753,7 +761,11 @@
 loop:
   for (i = 1; i < NUMPRIMES; i++) {
     /* check that rnd is a prime */
-    if (BN_mod_word(rnd, (BN_ULONG)primes[i]) <= 1) {
+    BN_ULONG mod = BN_mod_word(rnd, (BN_ULONG)primes[i]);
+    if (mod == (BN_ULONG)-1) {
+      goto err;
+    }
+    if (mod <= 1) {
       if (!BN_add(rnd, rnd, add)) {
         goto err;
       }
@@ -786,7 +798,7 @@
     goto err;
   }
 
-  if (!BN_rand(q, bits, 0, 1)) {
+  if (!BN_rand(q, bits, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ODD)) {
     goto err;
   }
 
@@ -825,8 +837,12 @@
     /* check that p and q are prime */
     /* check that for p and q
      * gcd(p-1,primes) == 1 (except for 2) */
-    if ((BN_mod_word(p, (BN_ULONG)primes[i]) == 0) ||
-        (BN_mod_word(q, (BN_ULONG)primes[i]) == 0)) {
+    BN_ULONG pmod = BN_mod_word(p, (BN_ULONG)primes[i]);
+    BN_ULONG qmod = BN_mod_word(q, (BN_ULONG)primes[i]);
+    if (pmod == (BN_ULONG)-1 || qmod == (BN_ULONG)-1) {
+      goto err;
+    }
+    if (pmod == 0 || qmod == 0) {
       if (!BN_add(p, p, padd)) {
         goto err;
       }
diff --git a/src/crypto/bn/random.c b/src/crypto/bn/random.c
index 3116e54..6f922c0 100644
--- a/src/crypto/bn/random.c
+++ b/src/crypto/bn/random.c
@@ -115,6 +115,9 @@
 #include <openssl/rand.h>
 #include <openssl/sha.h>
 
+#include "../internal.h"
+
+
 int BN_rand(BIGNUM *rnd, int bits, int top, int bottom) {
   uint8_t *buf = NULL;
   int ret = 0, bit, bytes, mask;
@@ -123,6 +126,17 @@
     return 0;
   }
 
+  if (top != BN_RAND_TOP_ANY && top != BN_RAND_TOP_ONE &&
+      top != BN_RAND_TOP_TWO) {
+    OPENSSL_PUT_ERROR(BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+    return 0;
+  }
+
+  if (bottom != BN_RAND_BOTTOM_ANY && bottom != BN_RAND_BOTTOM_ODD) {
+    OPENSSL_PUT_ERROR(BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+    return 0;
+  }
+
   if (bits == 0) {
     BN_zero(rnd);
     return 1;
@@ -143,8 +157,8 @@
     goto err;
   }
 
-  if (top != -1) {
-    if (top && bits > 1) {
+  if (top != BN_RAND_TOP_ANY) {
+    if (top == BN_RAND_TOP_TWO && bits > 1) {
       if (bit == 0) {
         buf[0] = 1;
         buf[1] |= 0x80;
@@ -158,8 +172,8 @@
 
   buf[0] &= ~mask;
 
-  /* set bottom bit if requested */
-  if (bottom)  {
+  /* Set the bottom bit if requested, */
+  if (bottom == BN_RAND_BOTTOM_ODD)  {
     buf[bytes - 1] |= 1;
   }
 
@@ -181,65 +195,68 @@
   return BN_rand(rnd, bits, top, bottom);
 }
 
-int BN_rand_range(BIGNUM *r, const BIGNUM *range) {
+int BN_rand_range_ex(BIGNUM *r, BN_ULONG min_inclusive,
+                     const BIGNUM *max_exclusive) {
   unsigned n;
   unsigned count = 100;
 
-  if (range->neg || BN_is_zero(range)) {
+  if (BN_cmp_word(max_exclusive, min_inclusive) <= 0) {
     OPENSSL_PUT_ERROR(BN, BN_R_INVALID_RANGE);
     return 0;
   }
 
-  n = BN_num_bits(range); /* n > 0 */
+  n = BN_num_bits(max_exclusive); /* n > 0 */
 
   /* BN_is_bit_set(range, n - 1) always holds */
   if (n == 1) {
     BN_zero(r);
-  } else if (!BN_is_bit_set(range, n - 2) && !BN_is_bit_set(range, n - 3)) {
-    /* range = 100..._2,
-     * so  3*range (= 11..._2)  is exactly one bit longer than  range */
-    do {
-      if (!BN_rand(r, n + 1, -1 /* don't set most significant bits */,
-                   0 /* don't set least significant bits */)) {
+    return 1;
+  }
+
+  do {
+    if (!--count) {
+      OPENSSL_PUT_ERROR(BN, BN_R_TOO_MANY_ITERATIONS);
+      return 0;
+    }
+
+    if (!BN_is_bit_set(max_exclusive, n - 2) &&
+        !BN_is_bit_set(max_exclusive, n - 3)) {
+      /* range = 100..._2, so 3*range (= 11..._2) is exactly one bit longer
+       * than range. This is a common scenario when generating a random value
+       * modulo an RSA public modulus, e.g. for RSA base blinding. */
+      if (!BN_rand(r, n + 1, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) {
         return 0;
       }
 
       /* If r < 3*range, use r := r MOD range (which is either r, r - range, or
        * r - 2*range). Otherwise, iterate again. Since 3*range = 11..._2, each
        * iteration succeeds with probability >= .75. */
-      if (BN_cmp(r, range) >= 0) {
-        if (!BN_sub(r, r, range)) {
+      if (BN_cmp(r, max_exclusive) >= 0) {
+        if (!BN_sub(r, r, max_exclusive)) {
           return 0;
         }
-        if (BN_cmp(r, range) >= 0) {
-          if (!BN_sub(r, r, range)) {
+        if (BN_cmp(r, max_exclusive) >= 0) {
+          if (!BN_sub(r, r, max_exclusive)) {
             return 0;
           }
         }
       }
-
-      if (!--count) {
-        OPENSSL_PUT_ERROR(BN, BN_R_TOO_MANY_ITERATIONS);
-        return 0;
-      }
-    } while (BN_cmp(r, range) >= 0);
-  } else {
-    do {
+    } else {
       /* range = 11..._2  or  range = 101..._2 */
-      if (!BN_rand(r, n, -1, 0)) {
+      if (!BN_rand(r, n, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) {
         return 0;
       }
-
-      if (!--count) {
-        OPENSSL_PUT_ERROR(BN, BN_R_TOO_MANY_ITERATIONS);
-        return 0;
-      }
-    } while (BN_cmp(r, range) >= 0);
-  }
+    }
+  } while (BN_cmp_word(r, min_inclusive) < 0 ||
+           BN_cmp(r, max_exclusive) >= 0);
 
   return 1;
 }
 
+int BN_rand_range(BIGNUM *r, const BIGNUM *range) {
+  return BN_rand_range_ex(r, 0, range);
+}
+
 int BN_pseudo_rand_range(BIGNUM *r, const BIGNUM *range) {
   return BN_rand_range(r, range);
 }
@@ -284,8 +301,8 @@
     OPENSSL_PUT_ERROR(BN, BN_R_PRIVATE_KEY_TOO_LARGE);
     goto err;
   }
-  memcpy(private_bytes, priv->d, todo);
-  memset(private_bytes + todo, 0, sizeof(private_bytes) - todo);
+  OPENSSL_memcpy(private_bytes, priv->d, todo);
+  OPENSSL_memset(private_bytes + todo, 0, sizeof(private_bytes) - todo);
 
   for (attempt = 0;; attempt++) {
     for (done = 0; done < num_k_bytes;) {
@@ -304,7 +321,7 @@
       if (todo > SHA512_DIGEST_LENGTH) {
         todo = SHA512_DIGEST_LENGTH;
       }
-      memcpy(k_bytes + done, digest, todo);
+      OPENSSL_memcpy(k_bytes + done, digest, todo);
       done += todo;
     }
 
diff --git a/src/crypto/bn/rsaz_exp.c b/src/crypto/bn/rsaz_exp.c
index c802752..c7eed38 100644
--- a/src/crypto/bn/rsaz_exp.c
+++ b/src/crypto/bn/rsaz_exp.c
@@ -48,6 +48,9 @@
 
 #include <openssl/mem.h>
 
+#include "../internal.h"
+
+
 /*
  * See crypto/bn/asm/rsaz-avx2.pl for further details.
  */
@@ -58,42 +61,30 @@
 void rsaz_1024_gather5_avx2(void *val,const void *tbl,int i);
 void rsaz_1024_red2norm_avx2(void *norm,const void *red);
 
-#if defined(__GNUC__)
-# define ALIGN64	__attribute__((aligned(64)))
-#elif defined(_MSC_VER)
-# define ALIGN64	__declspec(align(64))
-#elif defined(__SUNPRO_C)
-# define ALIGN64
-# pragma align 64(one,two80)
-#else
-# define ALIGN64	/* not fatal, might hurt performance a little */
-#endif
-
-ALIGN64 static const BN_ULONG one[40] =
+alignas(64) static const BN_ULONG one[40] =
 	{1,0,0,    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-ALIGN64 static const BN_ULONG two80[40] =
+alignas(64) static const BN_ULONG two80[40] =
 	{0,0,1<<22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
 
 void RSAZ_1024_mod_exp_avx2(BN_ULONG result_norm[16],
 	const BN_ULONG base_norm[16], const BN_ULONG exponent[16],
 	const BN_ULONG m_norm[16], const BN_ULONG RR[16], BN_ULONG k0)
 {
-	unsigned char	 storage[320*3+32*9*16+64];	/* 5.5KB */
-	unsigned char	*p_str = storage + (64-((size_t)storage%64));
+	alignas(64) uint8_t storage[(320 * 3) + (32 * 9 * 16)]; /* 5.5KB */
 	unsigned char	*a_inv, *m, *result,
-			*table_s = p_str+320*3,
+			*table_s = storage + (320 * 3),
 			*R2      = table_s;	/* borrow */
 	int index;
 	int wvalue;
 
-	if ((((size_t)p_str&4095)+320)>>12) {
-		result = p_str;
-		a_inv = p_str + 320;
-		m = p_str + 320*2;	/* should not cross page */
+	if (((((uintptr_t)storage & 4095) + 320) >> 12) != 0) {
+		result = storage;
+		a_inv = storage + 320;
+		m = storage + (320 * 2); /* should not cross page */
 	} else {
-		m = p_str;		/* should not cross page */
-		result = p_str + 320;
-		a_inv = p_str + 320*2;
+		m = storage;		/* should not cross page */
+		result = storage + 320;
+		a_inv = storage + (320 * 2);
 	}
 
 	rsaz_1024_norm2red_avx2(m, m_norm);
@@ -224,8 +215,9 @@
 	rsaz_1024_scatter5_avx2(table_s,result,31);
 #endif
 
+	const uint8_t *p_str = (const uint8_t *)exponent;
+
 	/* load first window */
-	p_str = (unsigned char*)exponent;
 	wvalue = p_str[127] >> 3;
 	rsaz_1024_gather5_avx2(result,table_s,wvalue);
 
@@ -235,7 +227,7 @@
 
 		rsaz_1024_sqr_avx2(result, result, m, k0, 5);
 
-		wvalue = *((unsigned short*)&p_str[index/8]);
+		wvalue = *((const unsigned short*)&p_str[index / 8]);
 		wvalue = (wvalue>> (index%8)) & 31;
 		index-=5;
 
@@ -259,68 +251,4 @@
 	OPENSSL_cleanse(storage,sizeof(storage));
 }
 
-/*
- * See crypto/bn/rsaz-x86_64.pl for further details.
- */
-void rsaz_512_mul(void *ret,const void *a,const void *b,const void *n,BN_ULONG k);
-void rsaz_512_mul_scatter4(void *ret,const void *a,const void *n,BN_ULONG k,const void *tbl,unsigned int power);
-void rsaz_512_mul_gather4(void *ret,const void *a,const void *tbl,const void *n,BN_ULONG k,unsigned int power);
-void rsaz_512_mul_by_one(void *ret,const void *a,const void *n,BN_ULONG k);
-void rsaz_512_sqr(void *ret,const void *a,const void *n,BN_ULONG k,int cnt);
-void rsaz_512_scatter4(void *tbl, const BN_ULONG *val, int power);
-void rsaz_512_gather4(BN_ULONG *val, const void *tbl, int power);
-
-void RSAZ_512_mod_exp(BN_ULONG result[8],
-	const BN_ULONG base[8], const BN_ULONG exponent[8],
-	const BN_ULONG m[8], BN_ULONG k0, const BN_ULONG RR[8])
-{
-	unsigned char	 storage[16*8*8+64*2+64];	/* 1.2KB */
-	unsigned char	*table = storage + (64-((size_t)storage%64));
-	BN_ULONG	*a_inv = (BN_ULONG *)(table+16*8*8),
-			*temp  = (BN_ULONG *)(table+16*8*8+8*8);
-	unsigned char	*p_str = (unsigned char*)exponent;
-	int index;
-	unsigned int wvalue;
-
-	/* table[0] = 1_inv */
-	temp[0] = 0-m[0];	temp[1] = ~m[1];
-	temp[2] = ~m[2];	temp[3] = ~m[3];
-	temp[4] = ~m[4];	temp[5] = ~m[5];
-	temp[6] = ~m[6];	temp[7] = ~m[7];
-	rsaz_512_scatter4(table, temp, 0);
-
-	/* table [1] = a_inv^1 */
-	rsaz_512_mul(a_inv, base, RR, m, k0);
-	rsaz_512_scatter4(table, a_inv, 1);
-
-	/* table [2] = a_inv^2 */
-	rsaz_512_sqr(temp, a_inv, m, k0, 1);
-	rsaz_512_scatter4(table, temp, 2);
-
-	for (index=3; index<16; index++)
-		rsaz_512_mul_scatter4(temp, a_inv, m, k0, table, index);
-
-	/* load first window */
-	wvalue = p_str[63];
-
-	rsaz_512_gather4(temp, table, wvalue>>4);
-	rsaz_512_sqr(temp, temp, m, k0, 4);
-	rsaz_512_mul_gather4(temp, temp, table, m, k0, wvalue&0xf);
-
-	for (index=62; index>=0; index--) {
-		wvalue = p_str[index];
-
-		rsaz_512_sqr(temp, temp, m, k0, 4);
-		rsaz_512_mul_gather4(temp, temp, table, m, k0, wvalue>>4);
-
-		rsaz_512_sqr(temp, temp, m, k0, 4);
-		rsaz_512_mul_gather4(temp, temp, table, m, k0, wvalue&0x0f);
-	}
-
-	/* from Montgomery */
-	rsaz_512_mul_by_one(result, temp, m, k0);
-
-	OPENSSL_cleanse(storage,sizeof(storage));
-}
-
 #endif  /* OPENSSL_X86_64 */
diff --git a/src/crypto/bn/rsaz_exp.h b/src/crypto/bn/rsaz_exp.h
index c752b45..4a8967c 100644
--- a/src/crypto/bn/rsaz_exp.h
+++ b/src/crypto/bn/rsaz_exp.h
@@ -50,7 +50,4 @@
 	const BN_ULONG m_norm[16], const BN_ULONG RR[16], BN_ULONG k0);
 int rsaz_avx2_eligible(void);
 
-void RSAZ_512_mod_exp(BN_ULONG result[8],
-	const BN_ULONG base_norm[8], const BN_ULONG exponent[8],
-	const BN_ULONG m_norm[8], BN_ULONG k0, const BN_ULONG RR[8]);
 #endif
diff --git a/src/crypto/bn/shift.c b/src/crypto/bn/shift.c
index defec92..dc9b795 100644
--- a/src/crypto/bn/shift.c
+++ b/src/crypto/bn/shift.c
@@ -94,7 +94,7 @@
       t[nw + i] = (l << lb) & BN_MASK2;
     }
   }
-  memset(t, 0, nw * sizeof(t[0]));
+  OPENSSL_memset(t, 0, nw * sizeof(t[0]));
   r->top = a->top + nw + 1;
   bn_correct_top(r);
 
@@ -182,6 +182,10 @@
     }
   }
 
+  if (r->top == 0) {
+    r->neg = 0;
+  }
+
   return 1;
 }
 
@@ -215,6 +219,10 @@
   }
   r->top = j;
 
+  if (r->top == 0) {
+    r->neg = 0;
+  }
+
   return 1;
 }
 
diff --git a/src/crypto/bn/sqrt.c b/src/crypto/bn/sqrt.c
index 2ed66c2..f806ea2 100644
--- a/src/crypto/bn/sqrt.c
+++ b/src/crypto/bn/sqrt.c
@@ -57,12 +57,11 @@
 #include <openssl/err.h>
 
 
-/* Returns 'ret' such that
- *      ret^2 == a (mod p),
- * using the Tonelli/Shanks algorithm (cf. Henri Cohen, "A Course
- * in Algebraic Computational Number Theory", algorithm 1.5.1).
- * 'p' must be prime! */
 BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) {
+  /* Compute a square root of |a| mod |p| using the Tonelli/Shanks algorithm
+   * (cf. Henri Cohen, "A Course in Algebraic Computational Number Theory",
+   * algorithm 1.5.1). |p| is assumed to be a prime. */
+
   BIGNUM *ret = in;
   int err = 1;
   int r;
@@ -149,7 +148,7 @@
     }
     q->neg = 0;
     if (!BN_add_word(q, 1) ||
-        !BN_mod_exp(ret, A, q, p, ctx)) {
+        !BN_mod_exp_mont(ret, A, q, p, ctx, NULL)) {
       goto end;
     }
     err = 0;
@@ -194,7 +193,7 @@
       goto end;
     }
     q->neg = 0;
-    if (!BN_mod_exp(b, t, q, p, ctx)) {
+    if (!BN_mod_exp_mont(b, t, q, p, ctx, NULL)) {
       goto end;
     }
 
@@ -282,7 +281,7 @@
 
   /* Now that we have some non-square, we can find an element
    * of order  2^e  by computing its q'th power. */
-  if (!BN_mod_exp(y, y, q, p, ctx)) {
+  if (!BN_mod_exp_mont(y, y, q, p, ctx, NULL)) {
     goto end;
   }
   if (BN_is_one(y)) {
@@ -328,7 +327,7 @@
       goto end;
     }
   } else {
-    if (!BN_mod_exp(x, A, t, p, ctx)) {
+    if (!BN_mod_exp_mont(x, A, t, p, ctx, NULL)) {
       goto end;
     }
     if (BN_is_zero(x)) {
@@ -457,7 +456,9 @@
   }
 
   /* We estimate that the square root of an n-bit number is 2^{n/2}. */
-  BN_lshift(estimate, BN_value_one(), BN_num_bits(in)/2);
+  if (!BN_lshift(estimate, BN_value_one(), BN_num_bits(in)/2)) {
+    goto err;
+  }
 
   /* This is Newton's method for finding a root of the equation |estimate|^2 -
    * |in| = 0. */
diff --git a/src/crypto/buf/buf.c b/src/crypto/buf/buf.c
index b918f01..ca1d70b 100644
--- a/src/crypto/buf/buf.c
+++ b/src/crypto/buf/buf.c
@@ -61,6 +61,8 @@
 #include <openssl/mem.h>
 #include <openssl/err.h>
 
+#include "../internal.h"
+
 
 BUF_MEM *BUF_MEM_new(void) {
   BUF_MEM *ret;
@@ -71,7 +73,7 @@
     return NULL;
   }
 
-  memset(ret, 0, sizeof(BUF_MEM));
+  OPENSSL_memset(ret, 0, sizeof(BUF_MEM));
   return ret;
 }
 
@@ -88,34 +90,26 @@
   OPENSSL_free(buf);
 }
 
-static size_t buf_mem_grow(BUF_MEM *buf, size_t len, char clean) {
-  char *new_buf;
-  size_t n, alloc_size;
-
-  if (buf->length >= len) {
-    buf->length = len;
-    return len;
-  }
-  if (buf->max >= len) {
-    memset(&buf->data[buf->length], 0, len - buf->length);
-    buf->length = len;
-    return len;
+static int buf_mem_reserve(BUF_MEM *buf, size_t cap, int clean) {
+  if (buf->max >= cap) {
+    return 1;
   }
 
-  n = len + 3;
-  if (n < len) {
+  size_t n = cap + 3;
+  if (n < cap) {
     /* overflow */
     OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE);
     return 0;
   }
   n = n / 3;
-  alloc_size = n * 4;
+  size_t alloc_size = n * 4;
   if (alloc_size / 4 != n) {
     /* overflow */
     OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE);
     return 0;
   }
 
+  char *new_buf;
   if (buf->data == NULL) {
     new_buf = OPENSSL_malloc(alloc_size);
   } else {
@@ -128,14 +122,26 @@
 
   if (new_buf == NULL) {
     OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE);
-    len = 0;
-  } else {
-    buf->data = new_buf;
-    buf->max = alloc_size;
-    memset(&buf->data[buf->length], 0, len - buf->length);
-    buf->length = len;
+    return 0;
   }
 
+  buf->data = new_buf;
+  buf->max = alloc_size;
+  return 1;
+}
+
+int BUF_MEM_reserve(BUF_MEM *buf, size_t cap) {
+  return buf_mem_reserve(buf, cap, 0 /* don't clear old buffer contents. */);
+}
+
+static size_t buf_mem_grow(BUF_MEM *buf, size_t len, int clean) {
+  if (!buf_mem_reserve(buf, len, clean)) {
+    return 0;
+  }
+  if (buf->length < len) {
+    OPENSSL_memset(&buf->data[buf->length], 0, len - buf->length);
+  }
+  buf->length = len;
   return len;
 }
 
@@ -189,7 +195,7 @@
     return NULL;
   }
 
-  memcpy(ret, buf, size);
+  OPENSSL_memcpy(ret, buf, size);
   ret[size] = '\0';
   return ret;
 }
@@ -230,6 +236,6 @@
     return NULL;
   }
 
-  memcpy(ret, data, dst_size);
+  OPENSSL_memcpy(ret, data, dst_size);
   return ret;
 }
diff --git a/src/crypto/bytestring/CMakeLists.txt b/src/crypto/bytestring/CMakeLists.txt
index 33d3c21..362e702 100644
--- a/src/crypto/bytestring/CMakeLists.txt
+++ b/src/crypto/bytestring/CMakeLists.txt
@@ -5,6 +5,7 @@
 
   OBJECT
 
+  asn1_compat.c
   ber.c
   cbs.c
   cbb.c
diff --git a/src/crypto/bytestring/asn1_compat.c b/src/crypto/bytestring/asn1_compat.c
new file mode 100644
index 0000000..50df9cc
--- /dev/null
+++ b/src/crypto/bytestring/asn1_compat.c
@@ -0,0 +1,52 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+
+#include <openssl/bytestring.h>
+
+#include <assert.h>
+#include <limits.h>
+#include <string.h>
+
+#include <openssl/mem.h>
+
+#include "internal.h"
+#include "../internal.h"
+
+
+int CBB_finish_i2d(CBB *cbb, uint8_t **outp) {
+  assert(cbb->base->can_resize);
+
+  uint8_t *der;
+  size_t der_len;
+  if (!CBB_finish(cbb, &der, &der_len)) {
+    CBB_cleanup(cbb);
+    return -1;
+  }
+  if (der_len > INT_MAX) {
+    OPENSSL_free(der);
+    return -1;
+  }
+  if (outp != NULL) {
+    if (*outp == NULL) {
+      *outp = der;
+      der = NULL;
+    } else {
+      OPENSSL_memcpy(*outp, der, der_len);
+      *outp += der_len;
+    }
+  }
+  OPENSSL_free(der);
+  return (int)der_len;
+}
diff --git a/src/crypto/bytestring/ber.c b/src/crypto/bytestring/ber.c
index 9e8daaa..54bac59 100644
--- a/src/crypto/bytestring/ber.c
+++ b/src/crypto/bytestring/ber.c
@@ -14,9 +14,11 @@
 
 #include <openssl/bytestring.h>
 
+#include <assert.h>
 #include <string.h>
 
 #include "internal.h"
+#include "../internal.h"
 
 
 /* kMaxDepth is a just a sanity limit. The code should be such that the length
@@ -24,11 +26,37 @@
  * input could otherwise cause the stack to overflow. */
 static const unsigned kMaxDepth = 2048;
 
+/* is_string_type returns one if |tag| is a string type and zero otherwise. It
+ * ignores the constructed bit. */
+static int is_string_type(unsigned tag) {
+  if ((tag & 0xc0) != 0) {
+    return 0;
+  }
+  switch (tag & 0x1f) {
+    case CBS_ASN1_BITSTRING:
+    case CBS_ASN1_OCTETSTRING:
+    case CBS_ASN1_UTF8STRING:
+    case CBS_ASN1_NUMERICSTRING:
+    case CBS_ASN1_PRINTABLESTRING:
+    case CBS_ASN1_T61STRING:
+    case CBS_ASN1_VIDEOTEXSTRING:
+    case CBS_ASN1_IA5STRING:
+    case CBS_ASN1_GRAPHICSTRING:
+    case CBS_ASN1_VISIBLESTRING:
+    case CBS_ASN1_GENERALSTRING:
+    case CBS_ASN1_UNIVERSALSTRING:
+    case CBS_ASN1_BMPSTRING:
+      return 1;
+    default:
+      return 0;
+  }
+}
+
 /* cbs_find_ber walks an ASN.1 structure in |orig_in| and sets |*ber_found|
- * depending on whether an indefinite length element was found. The value of
- * |in| is not changed. It returns one on success (i.e. |*ber_found| was set)
- * and zero on error. */
-static int cbs_find_ber(CBS *orig_in, char *ber_found, unsigned depth) {
+ * depending on whether an indefinite length element or constructed string was
+ * found. The value of |orig_in| is not changed. It returns one on success (i.e.
+ * |*ber_found| was set) and zero on error. */
+static int cbs_find_ber(const CBS *orig_in, char *ber_found, unsigned depth) {
   CBS in;
 
   if (depth > kMaxDepth) {
@@ -49,10 +77,16 @@
     if (CBS_len(&contents) == header_len &&
         header_len > 0 &&
         CBS_data(&contents)[header_len-1] == 0x80) {
+      /* Found an indefinite-length element. */
       *ber_found = 1;
       return 1;
     }
     if (tag & CBS_ASN1_CONSTRUCTED) {
+      if (is_string_type(tag)) {
+        /* Constructed strings are only legal in BER and require conversion. */
+        *ber_found = 1;
+        return 1;
+      }
       if (!CBS_skip(&contents, header_len) ||
           !cbs_find_ber(&contents, ber_found, depth + 1)) {
         return 0;
@@ -63,129 +97,94 @@
   return 1;
 }
 
-/* is_primitive_type returns true if |tag| likely a primitive type. Normally
- * one can just test the "constructed" bit in the tag but, in BER, even
- * primitive tags can have the constructed bit if they have indefinite
- * length. */
-static char is_primitive_type(unsigned tag) {
-  return (tag & 0xc0) == 0 &&
-         (tag & 0x1f) != (CBS_ASN1_SEQUENCE & 0x1f) &&
-         (tag & 0x1f) != (CBS_ASN1_SET & 0x1f);
-}
-
 /* is_eoc returns true if |header_len| and |contents|, as returned by
  * |CBS_get_any_ber_asn1_element|, indicate an "end of contents" (EOC) value. */
 static char is_eoc(size_t header_len, CBS *contents) {
   return header_len == 2 && CBS_len(contents) == 2 &&
-         memcmp(CBS_data(contents), "\x00\x00", 2) == 0;
+         OPENSSL_memcmp(CBS_data(contents), "\x00\x00", 2) == 0;
 }
 
 /* cbs_convert_ber reads BER data from |in| and writes DER data to |out|. If
- * |squash_header| is set then the top-level of elements from |in| will not
- * have their headers written. This is used when concatenating the fragments of
- * an indefinite length, primitive value. If |looking_for_eoc| is set then any
- * EOC elements found will cause the function to return after consuming it.
- * It returns one on success and zero on error. */
-static int cbs_convert_ber(CBS *in, CBB *out, char squash_header,
+ * |string_tag| is non-zero, then all elements must match |string_tag| up to the
+ * constructed bit and primitive element bodies are written to |out| without
+ * element headers. This is used when concatenating the fragments of a
+ * constructed string. If |looking_for_eoc| is set then any EOC elements found
+ * will cause the function to return after consuming it. It returns one on
+ * success and zero on error. */
+static int cbs_convert_ber(CBS *in, CBB *out, unsigned string_tag,
                            char looking_for_eoc, unsigned depth) {
+  assert(!(string_tag & CBS_ASN1_CONSTRUCTED));
+
   if (depth > kMaxDepth) {
     return 0;
   }
 
   while (CBS_len(in) > 0) {
     CBS contents;
-    unsigned tag;
+    unsigned tag, child_string_tag = string_tag;
     size_t header_len;
     CBB *out_contents, out_contents_storage;
 
     if (!CBS_get_any_ber_asn1_element(in, &contents, &tag, &header_len)) {
       return 0;
     }
-    out_contents = out;
 
-    if (CBS_len(&contents) == header_len) {
-      if (is_eoc(header_len, &contents)) {
-        return looking_for_eoc;
-      }
-
-      if (header_len > 0 && CBS_data(&contents)[header_len - 1] == 0x80) {
-        /* This is an indefinite length element. If it's a SEQUENCE or SET then
-         * we just need to write the out the contents as normal, but with a
-         * concrete length prefix.
-         *
-         * If it's a something else then the contents will be a series of BER
-         * elements of the same type which need to be concatenated. */
-        const char context_specific = (tag & 0xc0) == 0x80;
-        char squash_child_headers = is_primitive_type(tag);
-
-        /* This is a hack, but it sufficies to handle NSS's output. If we find
-         * an indefinite length, context-specific tag with a definite, primitive
-         * tag inside it, then we assume that the context-specific tag is
-         * implicit and the tags within are fragments of a primitive type that
-         * need to be concatenated. */
-        if (context_specific && (tag & CBS_ASN1_CONSTRUCTED)) {
-          CBS in_copy, inner_contents;
-          unsigned inner_tag;
-          size_t inner_header_len;
-
-          CBS_init(&in_copy, CBS_data(in), CBS_len(in));
-          if (!CBS_get_any_ber_asn1_element(&in_copy, &inner_contents,
-                                            &inner_tag, &inner_header_len)) {
-            return 0;
-          }
-          if (CBS_len(&inner_contents) > inner_header_len &&
-              is_primitive_type(inner_tag)) {
-            squash_child_headers = 1;
-          }
-        }
-
-        if (!squash_header) {
-          unsigned out_tag = tag;
-          if (squash_child_headers) {
-            out_tag &= ~CBS_ASN1_CONSTRUCTED;
-          }
-          if (!CBB_add_asn1(out, &out_contents_storage, out_tag)) {
-            return 0;
-          }
-          out_contents = &out_contents_storage;
-        }
-
-        if (!cbs_convert_ber(in, out_contents,
-                             squash_child_headers,
-                             1 /* looking for eoc */, depth + 1)) {
-          return 0;
-        }
-        if (out_contents != out && !CBB_flush(out)) {
-          return 0;
-        }
-        continue;
-      }
+    if (is_eoc(header_len, &contents)) {
+      return looking_for_eoc;
     }
 
-    if (!squash_header) {
-      if (!CBB_add_asn1(out, &out_contents_storage, tag)) {
+    if (string_tag != 0) {
+      /* This is part of a constructed string. All elements must match
+       * |string_tag| up to the constructed bit and get appended to |out|
+       * without a child element. */
+      if ((tag & ~CBS_ASN1_CONSTRUCTED) != string_tag) {
+        return 0;
+      }
+      out_contents = out;
+    } else {
+      unsigned out_tag = tag;
+      if ((tag & CBS_ASN1_CONSTRUCTED) && is_string_type(tag)) {
+        /* If a constructed string, clear the constructed bit and inform
+         * children to concatenate bodies. */
+        out_tag &= ~CBS_ASN1_CONSTRUCTED;
+        child_string_tag = out_tag;
+      }
+      if (!CBB_add_asn1(out, &out_contents_storage, out_tag)) {
         return 0;
       }
       out_contents = &out_contents_storage;
     }
 
+    if (CBS_len(&contents) == header_len && header_len > 0 &&
+        CBS_data(&contents)[header_len - 1] == 0x80) {
+      /* This is an indefinite length element. */
+      if (!cbs_convert_ber(in, out_contents, child_string_tag,
+                           1 /* looking for eoc */, depth + 1) ||
+          !CBB_flush(out)) {
+        return 0;
+      }
+      continue;
+    }
+
     if (!CBS_skip(&contents, header_len)) {
       return 0;
     }
 
     if (tag & CBS_ASN1_CONSTRUCTED) {
-      if (!cbs_convert_ber(&contents, out_contents, 0 /* don't squash header */,
+      /* Recurse into children. */
+      if (!cbs_convert_ber(&contents, out_contents, child_string_tag,
                            0 /* not looking for eoc */, depth + 1)) {
         return 0;
       }
     } else {
+      /* Copy primitive contents as-is. */
       if (!CBB_add_bytes(out_contents, CBS_data(&contents),
                          CBS_len(&contents))) {
         return 0;
       }
     }
 
-    if (out_contents != out && !CBB_flush(out)) {
+    if (!CBB_flush(out)) {
       return 0;
     }
   }
@@ -209,13 +208,57 @@
     return 1;
   }
 
-  if (!CBB_init(&cbb, CBS_len(in))) {
-    return 0;
-  }
-  if (!cbs_convert_ber(in, &cbb, 0, 0, 0)) {
+  if (!CBB_init(&cbb, CBS_len(in)) ||
+      !cbs_convert_ber(in, &cbb, 0, 0, 0) ||
+      !CBB_finish(&cbb, out, out_len)) {
     CBB_cleanup(&cbb);
     return 0;
   }
 
-  return CBB_finish(&cbb, out, out_len);
+  return 1;
+}
+
+int CBS_get_asn1_implicit_string(CBS *in, CBS *out, uint8_t **out_storage,
+                                 unsigned outer_tag, unsigned inner_tag) {
+  assert(!(outer_tag & CBS_ASN1_CONSTRUCTED));
+  assert(!(inner_tag & CBS_ASN1_CONSTRUCTED));
+  assert(is_string_type(inner_tag));
+
+  if (CBS_peek_asn1_tag(in, outer_tag)) {
+    /* Normal implicitly-tagged string. */
+    *out_storage = NULL;
+    return CBS_get_asn1(in, out, outer_tag);
+  }
+
+  /* Otherwise, try to parse an implicitly-tagged constructed string.
+   * |CBS_asn1_ber_to_der| is assumed to have run, so only allow one level deep
+   * of nesting. */
+  CBB result;
+  CBS child;
+  if (!CBB_init(&result, CBS_len(in)) ||
+      !CBS_get_asn1(in, &child, outer_tag | CBS_ASN1_CONSTRUCTED)) {
+    goto err;
+  }
+
+  while (CBS_len(&child) > 0) {
+    CBS chunk;
+    if (!CBS_get_asn1(&child, &chunk, inner_tag) ||
+        !CBB_add_bytes(&result, CBS_data(&chunk), CBS_len(&chunk))) {
+      goto err;
+    }
+  }
+
+  uint8_t *data;
+  size_t len;
+  if (!CBB_finish(&result, &data, &len)) {
+    goto err;
+  }
+
+  CBS_init(out, data, len);
+  *out_storage = data;
+  return 1;
+
+err:
+  CBB_cleanup(&result);
+  return 0;
 }
diff --git a/src/crypto/bytestring/bytestring_test.cc b/src/crypto/bytestring/bytestring_test.cc
index 188c63d..6ec6fcf 100644
--- a/src/crypto/bytestring/bytestring_test.cc
+++ b/src/crypto/bytestring/bytestring_test.cc
@@ -22,11 +22,11 @@
 
 #include <vector>
 
-#include <openssl/crypto.h>
 #include <openssl/bytestring.h>
+#include <openssl/crypto.h>
 
 #include "internal.h"
-#include "../test/scoped_types.h"
+#include "../internal.h"
 
 
 static bool TestSkip() {
@@ -43,7 +43,7 @@
 }
 
 static bool TestGetUint() {
-  static const uint8_t kData[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
+  static const uint8_t kData[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
   uint8_t u8;
   uint16_t u16;
   uint32_t u32;
@@ -58,7 +58,10 @@
     u32 == 0x40506 &&
     CBS_get_u32(&data, &u32) &&
     u32 == 0x708090a &&
-    !CBS_get_u8(&data, &u8);
+    CBS_get_last_u8(&data, &u8) &&
+    u8 == 0xb &&
+    !CBS_get_u8(&data, &u8) &&
+    !CBS_get_last_u8(&data, &u8);
 }
 
 static bool TestGetPrefixed() {
@@ -129,7 +132,7 @@
   }
   if (!CBS_get_asn1(&data, &contents, 0x30) ||
       CBS_len(&contents) != 2 ||
-      memcmp(CBS_data(&contents), "\x01\x02", 2) != 0) {
+      OPENSSL_memcmp(CBS_data(&contents), "\x01\x02", 2) != 0) {
     return false;
   }
 
@@ -190,7 +193,7 @@
       !CBS_get_optional_asn1(&data, &contents, &present, 0xa1) ||
       !present ||
       CBS_len(&contents) != 3 ||
-      memcmp(CBS_data(&contents), "\x04\x01\x01", 3) != 0) {
+      OPENSSL_memcmp(CBS_data(&contents), "\x04\x01\x01", 3) != 0) {
     return false;
   }
 
@@ -227,6 +230,25 @@
     return false;
   }
 
+  unsigned tag;
+  CBS_init(&data, kData1, sizeof(kData1));
+  if (!CBS_get_any_asn1(&data, &contents, &tag) ||
+      tag != CBS_ASN1_SEQUENCE ||
+      CBS_len(&contents) != 2 ||
+      OPENSSL_memcmp(CBS_data(&contents), "\x01\x02", 2) != 0) {
+    return false;
+  }
+
+  size_t header_len;
+  CBS_init(&data, kData1, sizeof(kData1));
+  if (!CBS_get_any_asn1_element(&data, &contents, &tag, &header_len) ||
+      tag != CBS_ASN1_SEQUENCE ||
+      header_len != 2 ||
+      CBS_len(&contents) != 4 ||
+      OPENSSL_memcmp(CBS_data(&contents), "\x30\x02\x01\x02", 2) != 0) {
+    return false;
+  }
+
   return true;
 }
 
@@ -266,7 +288,7 @@
 }
 
 static bool TestCBBBasic() {
-  static const uint8_t kExpected[] = {1, 2, 3, 4, 5, 6, 7, 8};
+  static const uint8_t kExpected[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc};
   uint8_t *buf;
   size_t buf_len;
   CBB cbb;
@@ -282,40 +304,48 @@
   if (!CBB_add_u8(&cbb, 1) ||
       !CBB_add_u16(&cbb, 0x203) ||
       !CBB_add_u24(&cbb, 0x40506) ||
-      !CBB_add_bytes(&cbb, (const uint8_t*) "\x07\x08", 2) ||
+      !CBB_add_u32(&cbb, 0x708090a) ||
+      !CBB_add_bytes(&cbb, (const uint8_t*) "\x0b\x0c", 2) ||
       !CBB_finish(&cbb, &buf, &buf_len)) {
     CBB_cleanup(&cbb);
     return false;
   }
 
-  ScopedOpenSSLBytes scoper(buf);
-  return buf_len == sizeof(kExpected) && memcmp(buf, kExpected, buf_len) == 0;
+  bssl::UniquePtr<uint8_t> scoper(buf);
+  return buf_len == sizeof(kExpected) &&
+         OPENSSL_memcmp(buf, kExpected, buf_len) == 0;
 }
 
 static bool TestCBBFixed() {
-  CBB cbb;
+  bssl::ScopedCBB cbb;
   uint8_t buf[1];
   uint8_t *out_buf;
   size_t out_size;
 
-  if (!CBB_init_fixed(&cbb, NULL, 0) ||
-      CBB_add_u8(&cbb, 1) ||
-      !CBB_finish(&cbb, &out_buf, &out_size) ||
+  if (!CBB_init_fixed(cbb.get(), NULL, 0) ||
+      !CBB_finish(cbb.get(), &out_buf, &out_size) ||
       out_buf != NULL ||
       out_size != 0) {
     return false;
   }
 
-  if (!CBB_init_fixed(&cbb, buf, 1) ||
-      !CBB_add_u8(&cbb, 1) ||
-      CBB_add_u8(&cbb, 2) ||
-      !CBB_finish(&cbb, &out_buf, &out_size) ||
+  cbb.Reset();
+  if (!CBB_init_fixed(cbb.get(), buf, 1) ||
+      !CBB_add_u8(cbb.get(), 1) ||
+      !CBB_finish(cbb.get(), &out_buf, &out_size) ||
       out_buf != buf ||
       out_size != 1 ||
       buf[0] != 1) {
     return false;
   }
 
+  cbb.Reset();
+  if (!CBB_init_fixed(cbb.get(), buf, 1) ||
+      !CBB_add_u8(cbb.get(), 1) ||
+      CBB_add_u8(cbb.get(), 2)) {
+    return false;
+  }
+
   return true;
 }
 
@@ -333,7 +363,7 @@
     CBB_cleanup(&cbb);
     return false;
   }
-  ScopedOpenSSLBytes scoper(out_buf);
+  bssl::UniquePtr<uint8_t> scoper(out_buf);
   return out_size == 1 && out_buf[0] == 0;
 }
 
@@ -366,12 +396,13 @@
     return false;
   }
 
-  ScopedOpenSSLBytes scoper(buf);
-  return buf_len == sizeof(kExpected) && memcmp(buf, kExpected, buf_len) == 0;
+  bssl::UniquePtr<uint8_t> scoper(buf);
+  return buf_len == sizeof(kExpected) &&
+         OPENSSL_memcmp(buf, kExpected, buf_len) == 0;
 }
 
 static bool TestCBBDiscardChild() {
-  ScopedCBB cbb;
+  bssl::ScopedCBB cbb;
   CBB contents, inner_contents, inner_inner_contents;
 
   if (!CBB_init(cbb.get(), 0) ||
@@ -406,7 +437,7 @@
   if (!CBB_finish(cbb.get(), &buf, &buf_len)) {
     return false;
   }
-  ScopedOpenSSLBytes scoper(buf);
+  bssl::UniquePtr<uint8_t> scoper(buf);
 
   static const uint8_t kExpected[] = {
         0xaa,
@@ -416,7 +447,8 @@
         0, 0, 3, 0xdd, 0xdd, 0xdd,
         1, 0xff,
   };
-  return buf_len == sizeof(kExpected) && memcmp(buf, kExpected, buf_len) == 0;
+  return buf_len == sizeof(kExpected) &&
+         OPENSSL_memcmp(buf, kExpected, buf_len) == 0;
 }
 
 static bool TestCBBMisuse() {
@@ -452,10 +484,10 @@
     CBB_cleanup(&cbb);
     return false;
   }
-  ScopedOpenSSLBytes scoper(buf);
+  bssl::UniquePtr<uint8_t> scoper(buf);
 
   if (buf_len != 3 ||
-      memcmp(buf, "\x01\x01\x02", 3) != 0) {
+      OPENSSL_memcmp(buf, "\x01\x01\x02", 3) != 0) {
     return false;
   }
   return true;
@@ -476,9 +508,10 @@
     CBB_cleanup(&cbb);
     return false;
   }
-  ScopedOpenSSLBytes scoper(buf);
+  bssl::UniquePtr<uint8_t> scoper(buf);
 
-  if (buf_len != sizeof(kExpected) || memcmp(buf, kExpected, buf_len) != 0) {
+  if (buf_len != sizeof(kExpected) ||
+      OPENSSL_memcmp(buf, kExpected, buf_len) != 0) {
     return false;
   }
 
@@ -496,8 +529,8 @@
   scoper.reset(buf);
 
   if (buf_len != 3 + 130 ||
-      memcmp(buf, "\x30\x81\x82", 3) != 0 ||
-      memcmp(buf + 3, test_data.data(), 130) != 0) {
+      OPENSSL_memcmp(buf, "\x30\x81\x82", 3) != 0 ||
+      OPENSSL_memcmp(buf + 3, test_data.data(), 130) != 0) {
     return false;
   }
 
@@ -513,8 +546,8 @@
   scoper.reset(buf);
 
   if (buf_len != 4 + 1000 ||
-      memcmp(buf, "\x30\x82\x03\xe8", 4) != 0 ||
-      memcmp(buf + 4, test_data.data(), 1000)) {
+      OPENSSL_memcmp(buf, "\x30\x82\x03\xe8", 4) != 0 ||
+      OPENSSL_memcmp(buf + 4, test_data.data(), 1000)) {
     return false;
   }
 
@@ -531,8 +564,9 @@
   scoper.reset(buf);
 
   if (buf_len != 5 + 5 + 100000 ||
-      memcmp(buf, "\x30\x83\x01\x86\xa5\x30\x83\x01\x86\xa0", 10) != 0 ||
-      memcmp(buf + 10, test_data.data(), 100000)) {
+      OPENSSL_memcmp(buf, "\x30\x83\x01\x86\xa5\x30\x83\x01\x86\xa0", 10) !=
+          0 ||
+      OPENSSL_memcmp(buf + 10, test_data.data(), 100000)) {
     return false;
   }
 
@@ -551,11 +585,11 @@
     fprintf(stderr, "%s: CBS_asn1_ber_to_der failed.\n", name);
     return false;
   }
-  ScopedOpenSSLBytes scoper(out);
+  bssl::UniquePtr<uint8_t> scoper(out);
 
   if (out == NULL) {
     if (ber_len != der_len ||
-        memcmp(der_expected, ber, ber_len) != 0) {
+        OPENSSL_memcmp(der_expected, ber, ber_len) != 0) {
       fprintf(stderr, "%s: incorrect unconverted result.\n", name);
       return false;
     }
@@ -564,7 +598,7 @@
   }
 
   if (out_len != der_len ||
-      memcmp(out, der_expected, der_len) != 0) {
+      OPENSSL_memcmp(out, der_expected, der_len) != 0) {
     fprintf(stderr, "%s: incorrect converted result.\n", name);
     return false;
   }
@@ -579,7 +613,7 @@
   static const uint8_t kIndefBER[] = {0x30, 0x80, 0x01, 0x01, 0x02, 0x00, 0x00};
   static const uint8_t kIndefDER[] = {0x30, 0x03, 0x01, 0x01, 0x02};
 
-  // kOctetStringBER contains an indefinite length OCTETSTRING with two parts.
+  // kOctetStringBER contains an indefinite length OCTET STRING with two parts.
   // These parts need to be concatenated in DER form.
   static const uint8_t kOctetStringBER[] = {0x24, 0x80, 0x04, 0x02, 0,    1,
                                             0x04, 0x02, 2,    3,    0x00, 0x00};
@@ -609,6 +643,16 @@
       0x6e, 0x10, 0x9b, 0xb8, 0x02, 0x02, 0x07, 0xd0,
   };
 
+  // kConstructedStringBER contains a deeply-nested constructed OCTET STRING.
+  // The BER conversion collapses this to one level deep, but not completely.
+  static const uint8_t kConstructedStringBER[] = {
+      0xa0, 0x10, 0x24, 0x06, 0x04, 0x01, 0x00, 0x04, 0x01,
+      0x01, 0x24, 0x06, 0x04, 0x01, 0x02, 0x04, 0x01, 0x03,
+  };
+  static const uint8_t kConstructedStringDER[] = {
+      0xa0, 0x08, 0x04, 0x02, 0x00, 0x01, 0x04, 0x02, 0x02, 0x03,
+  };
+
   return DoBerConvert("kSimpleBER", kSimpleBER, sizeof(kSimpleBER),
                       kSimpleBER, sizeof(kSimpleBER)) &&
          DoBerConvert("kIndefBER", kIndefDER, sizeof(kIndefDER), kIndefBER,
@@ -617,7 +661,59 @@
                       sizeof(kOctetStringDER), kOctetStringBER,
                       sizeof(kOctetStringBER)) &&
          DoBerConvert("kNSSBER", kNSSDER, sizeof(kNSSDER), kNSSBER,
-                      sizeof(kNSSBER));
+                      sizeof(kNSSBER)) &&
+         DoBerConvert("kConstructedStringBER", kConstructedStringDER,
+                      sizeof(kConstructedStringDER), kConstructedStringBER,
+                      sizeof(kConstructedStringBER));
+}
+
+struct ImplicitStringTest {
+  const char *in;
+  size_t in_len;
+  bool ok;
+  const char *out;
+  size_t out_len;
+};
+
+static const ImplicitStringTest kImplicitStringTests[] = {
+    // A properly-encoded string.
+    {"\x80\x03\x61\x61\x61", 5, true, "aaa", 3},
+    // An implicit-tagged string.
+    {"\xa0\x09\x04\x01\x61\x04\x01\x61\x04\x01\x61", 11, true, "aaa", 3},
+    // |CBS_get_asn1_implicit_string| only accepts one level deep of nesting.
+    {"\xa0\x0b\x24\x06\x04\x01\x61\x04\x01\x61\x04\x01\x61", 13, false, nullptr,
+     0},
+    // The outer tag must match.
+    {"\x81\x03\x61\x61\x61", 5, false, nullptr, 0},
+    {"\xa1\x09\x04\x01\x61\x04\x01\x61\x04\x01\x61", 11, false, nullptr, 0},
+    // The inner tag must match.
+    {"\xa1\x09\x0c\x01\x61\x0c\x01\x61\x0c\x01\x61", 11, false, nullptr, 0},
+};
+
+static bool TestImplicitString() {
+  for (const auto &test : kImplicitStringTests) {
+    uint8_t *storage = nullptr;
+    CBS in, out;
+    CBS_init(&in, reinterpret_cast<const uint8_t *>(test.in), test.in_len);
+    int ok = CBS_get_asn1_implicit_string(&in, &out, &storage,
+                                          CBS_ASN1_CONTEXT_SPECIFIC | 0,
+                                          CBS_ASN1_OCTETSTRING);
+    bssl::UniquePtr<uint8_t> scoper(storage);
+
+    if (static_cast<bool>(ok) != test.ok) {
+      fprintf(stderr, "CBS_get_asn1_implicit_string unexpectedly %s\n",
+              ok ? "succeeded" : "failed");
+      return false;
+    }
+
+    if (ok && (CBS_len(&out) != test.out_len ||
+               OPENSSL_memcmp(CBS_data(&out), test.out, test.out_len) != 0)) {
+      fprintf(stderr, "CBS_get_asn1_implicit_string gave the wrong output\n");
+      return false;
+    }
+  }
+
+  return true;
 }
 
 struct ASN1Uint64Test {
@@ -657,8 +753,7 @@
 };
 
 static bool TestASN1Uint64() {
-  for (size_t i = 0; i < sizeof(kASN1Uint64Tests) / sizeof(kASN1Uint64Tests[0]);
-       i++) {
+  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kASN1Uint64Tests); i++) {
     const ASN1Uint64Test *test = &kASN1Uint64Tests[i];
     CBS cbs;
     uint64_t value;
@@ -681,15 +776,14 @@
       CBB_cleanup(&cbb);
       return false;
     }
-    ScopedOpenSSLBytes scoper(out);
-    if (len != test->encoding_len || memcmp(out, test->encoding, len) != 0) {
+    bssl::UniquePtr<uint8_t> scoper(out);
+    if (len != test->encoding_len ||
+        OPENSSL_memcmp(out, test->encoding, len) != 0) {
       return false;
     }
   }
 
-  for (size_t i = 0;
-       i < sizeof(kASN1InvalidUint64Tests) / sizeof(kASN1InvalidUint64Tests[0]);
-       i++) {
+  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kASN1InvalidUint64Tests); i++) {
     const ASN1InvalidUint64Test *test = &kASN1InvalidUint64Tests[i];
     CBS cbs;
     uint64_t value;
@@ -715,10 +809,15 @@
   uint8_t buf[10];
   uint8_t *ptr;
   size_t len;
-  ScopedCBB cbb;
+  bssl::ScopedCBB cbb;
   if (!CBB_init_fixed(cbb.get(), buf, sizeof(buf)) ||
       // Too large.
-      CBB_reserve(cbb.get(), &ptr, 11) ||
+      CBB_reserve(cbb.get(), &ptr, 11)) {
+    return false;
+  }
+
+  cbb.Reset();
+  if (!CBB_init_fixed(cbb.get(), buf, sizeof(buf)) ||
       // Successfully reserve the entire space.
       !CBB_reserve(cbb.get(), &ptr, 10) ||
       ptr != buf ||
@@ -731,7 +830,148 @@
   return true;
 }
 
-int main(void) {
+static bool TestStickyError() {
+  // Write an input that exceeds the limit for its length prefix.
+  bssl::ScopedCBB cbb;
+  CBB child;
+  static const uint8_t kZeros[256] = {0};
+  if (!CBB_init(cbb.get(), 0) ||
+      !CBB_add_u8_length_prefixed(cbb.get(), &child) ||
+      !CBB_add_bytes(&child, kZeros, sizeof(kZeros))) {
+    return false;
+  }
+
+  if (CBB_flush(cbb.get())) {
+    fprintf(stderr, "CBB_flush unexpectedly succeeded.\n");
+    return false;
+  }
+
+  // All future operations should fail.
+  uint8_t *ptr;
+  size_t len;
+  if (CBB_add_u8(cbb.get(), 0) ||
+      CBB_finish(cbb.get(), &ptr, &len)) {
+    fprintf(stderr, "Future operations unexpectedly succeeded.\n");
+    return false;
+  }
+
+  // Write an input that cannot fit in a fixed CBB.
+  cbb.Reset();
+  uint8_t buf;
+  if (!CBB_init_fixed(cbb.get(), &buf, 1)) {
+    return false;
+  }
+
+  if (CBB_add_bytes(cbb.get(), kZeros, sizeof(kZeros))) {
+    fprintf(stderr, "CBB_add_bytes unexpectedly succeeded.\n");
+    return false;
+  }
+
+  // All future operations should fail.
+  if (CBB_add_u8(cbb.get(), 0) ||
+      CBB_finish(cbb.get(), &ptr, &len)) {
+    fprintf(stderr, "Future operations unexpectedly succeeded.\n");
+    return false;
+  }
+
+  // Write a u32 that cannot fit in a u24.
+  cbb.Reset();
+  if (!CBB_init(cbb.get(), 0)) {
+    return false;
+  }
+
+  if (CBB_add_u24(cbb.get(), 1u << 24)) {
+    fprintf(stderr, "CBB_add_u24 unexpectedly succeeded.\n");
+    return false;
+  }
+
+  // All future operations should fail.
+  if (CBB_add_u8(cbb.get(), 0) ||
+      CBB_finish(cbb.get(), &ptr, &len)) {
+    fprintf(stderr, "Future operations unexpectedly succeeded.\n");
+    return false;
+  }
+
+  return true;
+}
+
+static bool TestBitString() {
+  static const std::vector<uint8_t> kValidBitStrings[] = {
+      {0x00},                                      // 0 bits
+      {0x07, 0x80},                                // 1 bit
+      {0x04, 0xf0},                                // 4 bits
+      {0x00, 0xff},                                // 8 bits
+      {0x06, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0},  // 42 bits
+  };
+  for (const auto& test : kValidBitStrings) {
+    CBS cbs;
+    CBS_init(&cbs, test.data(), test.size());
+    if (!CBS_is_valid_asn1_bitstring(&cbs)) {
+      return false;
+    }
+  }
+
+  static const std::vector<uint8_t> kInvalidBitStrings[] = {
+      // BIT STRINGs always have a leading byte.
+      std::vector<uint8_t>{},
+      // It's not possible to take an unused bit off the empty string.
+      {0x01},
+      // There can be at most 7 unused bits.
+      {0x08, 0xff},
+      {0xff, 0xff},
+      // All unused bits must be cleared.
+      {0x06, 0xff, 0xc1},
+  };
+  for (const auto& test : kInvalidBitStrings) {
+    CBS cbs;
+    CBS_init(&cbs, test.data(), test.size());
+    if (CBS_is_valid_asn1_bitstring(&cbs)) {
+      return false;
+    }
+
+    // CBS_asn1_bitstring_has_bit returns false on invalid inputs.
+    if (CBS_asn1_bitstring_has_bit(&cbs, 0)) {
+      return false;
+    }
+  }
+
+  static const struct {
+    std::vector<uint8_t> in;
+    unsigned bit;
+    bool bit_set;
+  } kBitTests[] = {
+      // Basic tests.
+      {{0x00}, 0, false},
+      {{0x07, 0x80}, 0, true},
+      {{0x06, 0x0f, 0x40}, 0, false},
+      {{0x06, 0x0f, 0x40}, 1, false},
+      {{0x06, 0x0f, 0x40}, 2, false},
+      {{0x06, 0x0f, 0x40}, 3, false},
+      {{0x06, 0x0f, 0x40}, 4, true},
+      {{0x06, 0x0f, 0x40}, 5, true},
+      {{0x06, 0x0f, 0x40}, 6, true},
+      {{0x06, 0x0f, 0x40}, 7, true},
+      {{0x06, 0x0f, 0x40}, 8, false},
+      {{0x06, 0x0f, 0x40}, 9, true},
+      // Out-of-bounds bits return 0.
+      {{0x06, 0x0f, 0x40}, 10, false},
+      {{0x06, 0x0f, 0x40}, 15, false},
+      {{0x06, 0x0f, 0x40}, 16, false},
+      {{0x06, 0x0f, 0x40}, 1000, false},
+  };
+  for (const auto& test : kBitTests) {
+    CBS cbs;
+    CBS_init(&cbs, test.in.data(), test.in.size());
+    if (CBS_asn1_bitstring_has_bit(&cbs, test.bit) !=
+        static_cast<int>(test.bit_set)) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+int main() {
   CRYPTO_library_init();
 
   if (!TestSkip() ||
@@ -747,10 +987,13 @@
       !TestCBBDiscardChild() ||
       !TestCBBASN1() ||
       !TestBerConvert() ||
+      !TestImplicitString() ||
       !TestASN1Uint64() ||
       !TestGetOptionalASN1Bool() ||
       !TestZero() ||
-      !TestCBBReserve()) {
+      !TestCBBReserve() ||
+      !TestStickyError() ||
+      !TestBitString()) {
     return 1;
   }
 
diff --git a/src/crypto/bytestring/cbb.c b/src/crypto/bytestring/cbb.c
index 8fc5187..14116be 100644
--- a/src/crypto/bytestring/cbb.c
+++ b/src/crypto/bytestring/cbb.c
@@ -19,9 +19,11 @@
 
 #include <openssl/mem.h>
 
+#include "../internal.h"
+
 
 void CBB_zero(CBB *cbb) {
-  memset(cbb, 0, sizeof(CBB));
+  OPENSSL_memset(cbb, 0, sizeof(CBB));
 }
 
 static int cbb_init(CBB *cbb, uint8_t *buf, size_t cap) {
@@ -37,6 +39,7 @@
   base->len = 0;
   base->cap = cap;
   base->can_resize = 1;
+  base->error = 0;
 
   cbb->base = base;
   cbb->is_top_level = 1;
@@ -95,7 +98,7 @@
   newlen = base->len + len;
   if (newlen < base->len) {
     /* Overflow */
-    return 0;
+    goto err;
   }
 
   if (newlen > base->cap) {
@@ -103,7 +106,7 @@
     uint8_t *newbuf;
 
     if (!base->can_resize) {
-      return 0;
+      goto err;
     }
 
     if (newcap < base->cap || newcap < newlen) {
@@ -111,7 +114,7 @@
     }
     newbuf = OPENSSL_realloc(base->buf, newcap);
     if (newbuf == NULL) {
-      return 0;
+      goto err;
     }
 
     base->buf = newbuf;
@@ -123,6 +126,10 @@
   }
 
   return 1;
+
+err:
+  base->error = 1;
+  return 0;
 }
 
 static int cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out,
@@ -137,20 +144,25 @@
 
 static int cbb_buffer_add_u(struct cbb_buffer_st *base, uint32_t v,
                             size_t len_len) {
-  uint8_t *buf;
-  size_t i;
-
   if (len_len == 0) {
     return 1;
   }
+
+  uint8_t *buf;
   if (!cbb_buffer_add(base, &buf, len_len)) {
     return 0;
   }
 
-  for (i = len_len - 1; i < len_len; i--) {
+  for (size_t i = len_len - 1; i < len_len; i--) {
     buf[i] = v;
     v >>= 8;
   }
+
+  if (v != 0) {
+    base->error = 1;
+    return 0;
+  }
+
   return 1;
 }
 
@@ -185,7 +197,10 @@
 int CBB_flush(CBB *cbb) {
   size_t child_start, i, len;
 
-  if (cbb->base == NULL) {
+  /* If |cbb->base| has hit an error, the buffer is in an undefined state, so
+   * fail all following calls. In particular, |cbb->child| may point to invalid
+   * memory. */
+  if (cbb->base == NULL || cbb->base->error) {
     return 0;
   }
 
@@ -198,7 +213,7 @@
   if (!CBB_flush(cbb->child) ||
       child_start < cbb->child->offset ||
       cbb->base->len < child_start) {
-    return 0;
+    goto err;
   }
 
   len = cbb->base->len - child_start;
@@ -207,14 +222,14 @@
     /* For ASN.1 we assume that we'll only need a single byte for the length.
      * If that turned out to be incorrect, we have to move the contents along
      * in order to make space. */
-    size_t len_len;
+    uint8_t len_len;
     uint8_t initial_length_byte;
 
     assert (cbb->child->pending_len_len == 1);
 
     if (len > 0xfffffffe) {
       /* Too large. */
-      return 0;
+      goto err;
     } else if (len > 0xffffff) {
       len_len = 5;
       initial_length_byte = 0x80 | 4;
@@ -229,7 +244,7 @@
       initial_length_byte = 0x80 | 1;
     } else {
       len_len = 1;
-      initial_length_byte = len;
+      initial_length_byte = (uint8_t)len;
       len = 0;
     }
 
@@ -237,10 +252,10 @@
       /* We need to move the contents along in order to make space. */
       size_t extra_bytes = len_len - 1;
       if (!cbb_buffer_add(cbb->base, NULL, extra_bytes)) {
-        return 0;
+        goto err;
       }
-      memmove(cbb->base->buf + child_start + extra_bytes,
-              cbb->base->buf + child_start, len);
+      OPENSSL_memmove(cbb->base->buf + child_start + extra_bytes,
+                      cbb->base->buf + child_start, len);
     }
     cbb->base->buf[cbb->child->offset++] = initial_length_byte;
     cbb->child->pending_len_len = len_len - 1;
@@ -248,17 +263,21 @@
 
   for (i = cbb->child->pending_len_len - 1; i < cbb->child->pending_len_len;
        i--) {
-    cbb->base->buf[cbb->child->offset + i] = len;
+    cbb->base->buf[cbb->child->offset + i] = (uint8_t)len;
     len >>= 8;
   }
   if (len != 0) {
-    return 0;
+    goto err;
   }
 
   cbb->child->base = NULL;
   cbb->child = NULL;
 
   return 1;
+
+err:
+  cbb->base->error = 1;
+  return 0;
 }
 
 const uint8_t *CBB_data(const CBB *cbb) {
@@ -274,7 +293,7 @@
 }
 
 static int cbb_add_length_prefixed(CBB *cbb, CBB *out_contents,
-                                   size_t len_len) {
+                                   uint8_t len_len) {
   uint8_t *prefix_bytes;
 
   if (!CBB_flush(cbb)) {
@@ -286,8 +305,8 @@
     return 0;
   }
 
-  memset(prefix_bytes, 0, len_len);
-  memset(out_contents, 0, sizeof(CBB));
+  OPENSSL_memset(prefix_bytes, 0, len_len);
+  OPENSSL_memset(out_contents, 0, sizeof(CBB));
   out_contents->base = cbb->base;
   cbb->child = out_contents;
   cbb->child->offset = offset;
@@ -309,14 +328,18 @@
   return cbb_add_length_prefixed(cbb, out_contents, 3);
 }
 
-int CBB_add_asn1(CBB *cbb, CBB *out_contents, uint8_t tag) {
-  if ((tag & 0x1f) == 0x1f) {
-    /* Long form identifier octets are not supported. */
+int CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned tag) {
+  if (tag > 0xff ||
+      (tag & 0x1f) == 0x1f) {
+    /* Long form identifier octets are not supported. Further, all current valid
+     * tag serializations are 8 bits. */
+    cbb->base->error = 1;
     return 0;
   }
 
   if (!CBB_flush(cbb) ||
-      !CBB_add_u8(cbb, tag)) {
+      /* |tag|'s representation matches the DER encoding. */
+      !CBB_add_u8(cbb, (uint8_t)tag)) {
     return 0;
   }
 
@@ -325,7 +348,7 @@
     return 0;
   }
 
-  memset(out_contents, 0, sizeof(CBB));
+  OPENSSL_memset(out_contents, 0, sizeof(CBB));
   out_contents->base = cbb->base;
   cbb->child = out_contents;
   cbb->child->offset = offset;
@@ -342,7 +365,7 @@
       !cbb_buffer_add(cbb->base, &dest, len)) {
     return 0;
   }
-  memcpy(dest, data, len);
+  OPENSSL_memcpy(dest, data, len);
   return 1;
 }
 
@@ -397,6 +420,14 @@
   return cbb_buffer_add_u(cbb->base, value, 3);
 }
 
+int CBB_add_u32(CBB *cbb, uint32_t value) {
+  if (!CBB_flush(cbb)) {
+    return 0;
+  }
+
+  return cbb_buffer_add_u(cbb->base, value, 4);
+}
+
 void CBB_discard_child(CBB *cbb) {
   if (cbb->child == NULL) {
     return;
@@ -410,14 +441,13 @@
 
 int CBB_add_asn1_uint64(CBB *cbb, uint64_t value) {
   CBB child;
-  size_t i;
   int started = 0;
 
   if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER)) {
     return 0;
   }
 
-  for (i = 0; i < 8; i++) {
+  for (size_t i = 0; i < 8; i++) {
     uint8_t byte = (value >> 8*(7-i)) & 0xff;
     if (!started) {
       if (byte == 0) {
diff --git a/src/crypto/bytestring/cbs.c b/src/crypto/bytestring/cbs.c
index 5e0c538..14c55a4 100644
--- a/src/crypto/bytestring/cbs.c
+++ b/src/crypto/bytestring/cbs.c
@@ -20,6 +20,7 @@
 #include <string.h>
 
 #include "internal.h"
+#include "../internal.h"
 
 
 void CBS_init(CBS *cbs, const uint8_t *data, size_t len) {
@@ -76,7 +77,7 @@
 }
 
 int CBS_contains_zero_byte(const CBS *cbs) {
-  return memchr(cbs->data, 0, cbs->len) != NULL;
+  return OPENSSL_memchr(cbs->data, 0, cbs->len) != NULL;
 }
 
 int CBS_mem_equal(const CBS *cbs, const uint8_t *data, size_t len) {
@@ -88,13 +89,12 @@
 
 static int cbs_get_u(CBS *cbs, uint32_t *out, size_t len) {
   uint32_t result = 0;
-  size_t i;
   const uint8_t *data;
 
   if (!cbs_get(cbs, &data, len)) {
     return 0;
   }
-  for (i = 0; i < len; i++) {
+  for (size_t i = 0; i < len; i++) {
     result <<= 8;
     result |= data[i];
   }
@@ -128,6 +128,15 @@
   return cbs_get_u(cbs, out, 4);
 }
 
+int CBS_get_last_u8(CBS *cbs, uint8_t *out) {
+  if (cbs->len == 0) {
+    return 0;
+  }
+  *out = cbs->data[cbs->len - 1];
+  cbs->len--;
+  return 1;
+}
+
 int CBS_get_bytes(CBS *cbs, CBS *out, size_t len) {
   const uint8_t *v;
   if (!cbs_get(cbs, &v, len)) {
@@ -142,7 +151,7 @@
   if (!cbs_get(cbs, &v, len)) {
     return 0;
   }
-  memcpy(out, v, len);
+  OPENSSL_memcpy(out, v, len);
   return 1;
 }
 
@@ -181,8 +190,14 @@
     return 0;
   }
 
+  /* ITU-T X.690 section 8.1.2.3 specifies the format for identifiers with a tag
+   * number no greater than 30.
+   *
+   * If the number portion is 31 (0x1f, the largest value that fits in the
+   * allotted bits), then the tag is more than one byte long and the
+   * continuation bytes contain the tag number. This parser only supports tag
+   * numbers less than 31 (and thus single-byte tags). */
   if ((tag & 0x1f) == 0x1f) {
-    /* Long form tags are not supported. */
     return 0;
   }
 
@@ -191,6 +206,8 @@
   }
 
   size_t len;
+  /* The format for the length encoding is specified in ITU-T X.690 section
+   * 8.1.3. */
   if ((length_byte & 0x80) == 0) {
     /* Short form length. */
     len = ((size_t) length_byte) + 2;
@@ -198,7 +215,9 @@
       *out_header_len = 2;
     }
   } else {
-    /* Long form length. */
+    /* The high bit indicate that this is the long form, while the next 7 bits
+     * encode the number of subsequent octets used to encode the length (ITU-T
+     * X.690 clause 8.1.3.5.b). */
     const size_t num_bytes = length_byte & 0x7f;
     uint32_t len32;
 
@@ -210,12 +229,18 @@
       return CBS_get_bytes(cbs, out, 2);
     }
 
+    /* ITU-T X.690 clause 8.1.3.5.c specifies that the value 0xff shall not be
+     * used as the first byte of the length. If this parser encounters that
+     * value, num_bytes will be parsed as 127, which will fail the check below.
+     */
     if (num_bytes == 0 || num_bytes > 4) {
       return 0;
     }
     if (!cbs_get_u(&header, &len32, num_bytes)) {
       return 0;
     }
+    /* ITU-T X.690 section 10.1 (DER length forms) requires encoding the length
+     * with the minimum number of octets. */
     if (len32 < 128) {
       /* Length should have used short-form encoding. */
       return 0;
@@ -238,6 +263,20 @@
   return CBS_get_bytes(cbs, out, len);
 }
 
+int CBS_get_any_asn1(CBS *cbs, CBS *out, unsigned *out_tag) {
+  size_t header_len;
+  if (!CBS_get_any_asn1_element(cbs, out, out_tag, &header_len)) {
+    return 0;
+  }
+
+  if (!CBS_skip(out, header_len)) {
+    assert(0);
+    return 0;
+  }
+
+  return 1;
+}
+
 int CBS_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
                                     size_t *out_header_len) {
   return cbs_get_any_asn1_element(cbs, out, out_tag, out_header_len,
@@ -413,3 +452,40 @@
   }
   return 1;
 }
+
+int CBS_is_valid_asn1_bitstring(const CBS *cbs) {
+  CBS in = *cbs;
+  uint8_t num_unused_bits;
+  if (!CBS_get_u8(&in, &num_unused_bits) ||
+      num_unused_bits > 7) {
+    return 0;
+  }
+
+  if (num_unused_bits == 0) {
+    return 1;
+  }
+
+  /* All num_unused_bits bits must exist and be zeros. */
+  uint8_t last;
+  if (!CBS_get_last_u8(&in, &last) ||
+      (last & ((1 << num_unused_bits) - 1)) != 0) {
+    return 0;
+  }
+
+  return 1;
+}
+
+int CBS_asn1_bitstring_has_bit(const CBS *cbs, unsigned bit) {
+  if (!CBS_is_valid_asn1_bitstring(cbs)) {
+    return 0;
+  }
+
+  const unsigned byte_num = (bit >> 3) + 1;
+  const unsigned bit_num = 7 - (bit & 7);
+
+  /* Unused bits are zero, and this function does not distinguish between
+   * missing and unset bits. Thus it is sufficient to do a byte-level length
+   * check. */
+  return byte_num < CBS_len(cbs) &&
+         (CBS_data(cbs)[byte_num] & (1 << bit_num)) != 0;
+}
diff --git a/src/crypto/bytestring/internal.h b/src/crypto/bytestring/internal.h
index b4ea7e5..2fed413 100644
--- a/src/crypto/bytestring/internal.h
+++ b/src/crypto/bytestring/internal.h
@@ -22,22 +22,51 @@
 #endif
 
 
-/* CBS_asn1_ber_to_der reads an ASN.1 structure from |in|. If it finds
- * indefinite-length elements then it attempts to convert the BER data to DER
- * and sets |*out| and |*out_length| to describe a malloced buffer containing
- * the DER data. Additionally, |*in| will be advanced over the ASN.1 data.
+/* CBS_asn1_ber_to_der reads a BER element from |in|. If it finds
+ * indefinite-length elements or constructed strings then it converts the BER
+ * data to DER and sets |*out| and |*out_length| to describe a malloced buffer
+ * containing the DER data. Additionally, |*in| will be advanced over the BER
+ * element.
  *
- * If it doesn't find any indefinite-length elements then it sets |*out| to
- * NULL and |*in| is unmodified.
+ * If it doesn't find any indefinite-length elements or constructed strings then
+ * it sets |*out| to NULL and |*in| is unmodified.
  *
- * A sufficiently complex ASN.1 structure will break this function because it's
- * not possible to generically convert BER to DER without knowledge of the
- * structure itself. However, this sufficies to handle the PKCS#7 and #12 output
- * from NSS.
+ * This function should successfully process any valid BER input, however it
+ * will not convert all of BER's deviations from DER. BER is ambiguous between
+ * implicitly-tagged SEQUENCEs of strings and implicitly-tagged constructed
+ * strings. Implicitly-tagged strings must be parsed with
+ * |CBS_get_ber_implicitly_tagged_string| instead of |CBS_get_asn1|. The caller
+ * must also account for BER variations in the contents of a primitive.
  *
  * It returns one on success and zero otherwise. */
 OPENSSL_EXPORT int CBS_asn1_ber_to_der(CBS *in, uint8_t **out, size_t *out_len);
 
+/* CBS_get_asn1_implicit_string parses a BER string of primitive type
+ * |inner_tag| implicitly-tagged with |outer_tag|. It sets |out| to the
+ * contents. If concatenation was needed, it sets |*out_storage| to a buffer
+ * which the caller must release with |OPENSSL_free|. Otherwise, it sets
+ * |*out_storage| to NULL.
+ *
+ * This function does not parse all of BER. It requires the string be
+ * definite-length. Constructed strings are allowed, but all children of the
+ * outermost element must be primitive. The caller should use
+ * |CBS_asn1_ber_to_der| before running this function.
+ *
+ * It returns one on success and zero otherwise. */
+OPENSSL_EXPORT int CBS_get_asn1_implicit_string(CBS *in, CBS *out,
+                                                uint8_t **out_storage,
+                                                unsigned outer_tag,
+                                                unsigned inner_tag);
+
+/* CBB_finish_i2d calls |CBB_finish| on |cbb| which must have been initialized
+ * with |CBB_init|. If |outp| is not NULL then the result is written to |*outp|
+ * and |*outp| is advanced just past the output. It returns the number of bytes
+ * in the result, whether written or not, or a negative value on error. On
+ * error, it calls |CBB_cleanup| on |cbb|.
+ *
+ * This function may be used to help implement legacy i2d ASN.1 functions. */
+int CBB_finish_i2d(CBB *cbb, uint8_t **outp);
+
 
 #if defined(__cplusplus)
 }  /* extern C */
diff --git a/src/crypto/chacha/CMakeLists.txt b/src/crypto/chacha/CMakeLists.txt
index 266e869..63de061 100644
--- a/src/crypto/chacha/CMakeLists.txt
+++ b/src/crypto/chacha/CMakeLists.txt
@@ -4,7 +4,31 @@
   set(
     CHACHA_ARCH_SOURCES
 
-    chacha_vec_arm.S
+    chacha-armv4.${ASM_EXT}
+  )
+endif()
+
+if (${ARCH} STREQUAL "aarch64")
+  set(
+    CHACHA_ARCH_SOURCES
+
+    chacha-armv8.${ASM_EXT}
+  )
+endif()
+
+if (${ARCH} STREQUAL "x86")
+  set(
+    CHACHA_ARCH_SOURCES
+
+    chacha-x86.${ASM_EXT}
+  )
+endif()
+
+if (${ARCH} STREQUAL "x86_64")
+  set(
+    CHACHA_ARCH_SOURCES
+
+    chacha-x86_64.${ASM_EXT}
   )
 endif()
 
@@ -13,8 +37,12 @@
 
   OBJECT
 
-  chacha_generic.c
-  chacha_vec.c
+  chacha.c
 
   ${CHACHA_ARCH_SOURCES}
 )
+
+perlasm(chacha-armv4.${ASM_EXT} asm/chacha-armv4.pl)
+perlasm(chacha-armv8.${ASM_EXT} asm/chacha-armv8.pl)
+perlasm(chacha-x86.${ASM_EXT} asm/chacha-x86.pl)
+perlasm(chacha-x86_64.${ASM_EXT} asm/chacha-x86_64.pl)
diff --git a/src/crypto/chacha/asm/chacha-armv4.pl b/src/crypto/chacha/asm/chacha-armv4.pl
new file mode 100755
index 0000000..13698e3
--- /dev/null
+++ b/src/crypto/chacha/asm/chacha-armv4.pl
@@ -0,0 +1,1151 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# December 2014
+#
+# ChaCha20 for ARMv4.
+#
+# Performance in cycles per byte out of large buffer.
+#
+#			IALU/gcc-4.4    1xNEON      3xNEON+1xIALU
+#
+# Cortex-A5		19.3(*)/+95%    21.8        14.1
+# Cortex-A8		10.5(*)/+160%   13.9        6.35
+# Cortex-A9		12.9(**)/+110%  14.3        6.50
+# Cortex-A15		11.0/+40%       16.0        5.00
+# Snapdragon S4		11.5/+125%      13.6        4.90
+#
+# (*)	most "favourable" result for aligned data on little-endian
+#	processor, result for misaligned data is 10-15% lower;
+# (**)	this result is a trade-off: it can be improved by 20%,
+#	but then Snapdragon S4 and Cortex-A8 results get
+#	20-25% worse;
+
+$flavour = shift;
+if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
+else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} }
+
+if ($flavour && $flavour ne "void") {
+    $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+    ( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
+    ( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
+    die "can't locate arm-xlate.pl";
+
+    open STDOUT,"| \"$^X\" $xlate $flavour $output";
+} else {
+    open STDOUT,">$output";
+}
+
+sub AUTOLOAD()		# thunk [simplified] x86-style perlasm
+{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; $opcode =~ s/_/\./;
+  my $arg = pop;
+    $arg = "#$arg" if ($arg*1 eq $arg);
+    $code .= "\t$opcode\t".join(',',@_,$arg)."\n";
+}
+
+my @x=map("r$_",(0..7,"x","x","x","x",12,"x",14,"x"));
+my @t=map("r$_",(8..11));
+
+sub ROUND {
+my ($a0,$b0,$c0,$d0)=@_;
+my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0));
+my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1));
+my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2));
+my $odd = $d0&1;
+my ($xc,$xc_) = (@t[0..1]);
+my ($xd,$xd_) = $odd ? (@t[2],@x[$d1]) : (@x[$d0],@t[2]);
+my @ret;
+
+	# Consider order in which variables are addressed by their
+	# index:
+	#
+	#       a   b   c   d
+	#
+	#       0   4   8  12 < even round
+	#       1   5   9  13
+	#       2   6  10  14
+	#       3   7  11  15
+	#       0   5  10  15 < odd round
+	#       1   6  11  12
+	#       2   7   8  13
+	#       3   4   9  14
+	#
+	# 'a', 'b' are permanently allocated in registers, @x[0..7],
+	# while 'c's and pair of 'd's are maintained in memory. If
+	# you observe 'c' column, you'll notice that pair of 'c's is
+	# invariant between rounds. This means that we have to reload
+	# them once per round, in the middle. This is why you'll see
+	# bunch of 'c' stores and loads in the middle, but none in
+	# the beginning or end. If you observe 'd' column, you'll
+	# notice that 15 and 13 are reused in next pair of rounds.
+	# This is why these two are chosen for offloading to memory,
+	# to make loads count more.
+							push @ret,(
+	"&add	(@x[$a0],@x[$a0],@x[$b0])",
+	"&mov	($xd,$xd,'ror#16')",
+	 "&add	(@x[$a1],@x[$a1],@x[$b1])",
+	 "&mov	($xd_,$xd_,'ror#16')",
+	"&eor	($xd,$xd,@x[$a0],'ror#16')",
+	 "&eor	($xd_,$xd_,@x[$a1],'ror#16')",
+
+	"&add	($xc,$xc,$xd)",
+	"&mov	(@x[$b0],@x[$b0],'ror#20')",
+	 "&add	($xc_,$xc_,$xd_)",
+	 "&mov	(@x[$b1],@x[$b1],'ror#20')",
+	"&eor	(@x[$b0],@x[$b0],$xc,'ror#20')",
+	 "&eor	(@x[$b1],@x[$b1],$xc_,'ror#20')",
+
+	"&add	(@x[$a0],@x[$a0],@x[$b0])",
+	"&mov	($xd,$xd,'ror#24')",
+	 "&add	(@x[$a1],@x[$a1],@x[$b1])",
+	 "&mov	($xd_,$xd_,'ror#24')",
+	"&eor	($xd,$xd,@x[$a0],'ror#24')",
+	 "&eor	($xd_,$xd_,@x[$a1],'ror#24')",
+
+	"&add	($xc,$xc,$xd)",
+	"&mov	(@x[$b0],@x[$b0],'ror#25')"		);
+							push @ret,(
+	"&str	($xd,'[sp,#4*(16+$d0)]')",
+	"&ldr	($xd,'[sp,#4*(16+$d2)]')"		) if ($odd);
+							push @ret,(
+	 "&add	($xc_,$xc_,$xd_)",
+	 "&mov	(@x[$b1],@x[$b1],'ror#25')"		);
+							push @ret,(
+	 "&str	($xd_,'[sp,#4*(16+$d1)]')",
+	 "&ldr	($xd_,'[sp,#4*(16+$d3)]')"		) if (!$odd);
+							push @ret,(
+	"&eor	(@x[$b0],@x[$b0],$xc,'ror#25')",
+	 "&eor	(@x[$b1],@x[$b1],$xc_,'ror#25')"	);
+
+	$xd=@x[$d2]					if (!$odd);
+	$xd_=@x[$d3]					if ($odd);
+							push @ret,(
+	"&str	($xc,'[sp,#4*(16+$c0)]')",
+	"&ldr	($xc,'[sp,#4*(16+$c2)]')",
+	"&add	(@x[$a2],@x[$a2],@x[$b2])",
+	"&mov	($xd,$xd,'ror#16')",
+	 "&str	($xc_,'[sp,#4*(16+$c1)]')",
+	 "&ldr	($xc_,'[sp,#4*(16+$c3)]')",
+	 "&add	(@x[$a3],@x[$a3],@x[$b3])",
+	 "&mov	($xd_,$xd_,'ror#16')",
+	"&eor	($xd,$xd,@x[$a2],'ror#16')",
+	 "&eor	($xd_,$xd_,@x[$a3],'ror#16')",
+
+	"&add	($xc,$xc,$xd)",
+	"&mov	(@x[$b2],@x[$b2],'ror#20')",
+	 "&add	($xc_,$xc_,$xd_)",
+	 "&mov	(@x[$b3],@x[$b3],'ror#20')",
+	"&eor	(@x[$b2],@x[$b2],$xc,'ror#20')",
+	 "&eor	(@x[$b3],@x[$b3],$xc_,'ror#20')",
+
+	"&add	(@x[$a2],@x[$a2],@x[$b2])",
+	"&mov	($xd,$xd,'ror#24')",
+	 "&add	(@x[$a3],@x[$a3],@x[$b3])",
+	 "&mov	($xd_,$xd_,'ror#24')",
+	"&eor	($xd,$xd,@x[$a2],'ror#24')",
+	 "&eor	($xd_,$xd_,@x[$a3],'ror#24')",
+
+	"&add	($xc,$xc,$xd)",
+	"&mov	(@x[$b2],@x[$b2],'ror#25')",
+	 "&add	($xc_,$xc_,$xd_)",
+	 "&mov	(@x[$b3],@x[$b3],'ror#25')",
+	"&eor	(@x[$b2],@x[$b2],$xc,'ror#25')",
+	 "&eor	(@x[$b3],@x[$b3],$xc_,'ror#25')"	);
+
+	@ret;
+}
+
+$code.=<<___;
+#include <openssl/arm_arch.h>
+
+.text
+#if defined(__thumb2__)
+.syntax	unified
+.thumb
+#else
+.code	32
+#endif
+
+#if defined(__thumb2__) || defined(__clang__)
+#define ldrhsb	ldrbhs
+#endif
+
+.align	5
+.Lsigma:
+.long	0x61707865,0x3320646e,0x79622d32,0x6b206574	@ endian-neutral
+.Lone:
+.long	1,0,0,0
+#if __ARM_MAX_ARCH__>=7
+.LOPENSSL_armcap:
+.word   OPENSSL_armcap_P-.LChaCha20_ctr32
+#else
+.word	-1
+#endif
+
+.globl	ChaCha20_ctr32
+.type	ChaCha20_ctr32,%function
+.align	5
+ChaCha20_ctr32:
+.LChaCha20_ctr32:
+	ldr	r12,[sp,#0]		@ pull pointer to counter and nonce
+	stmdb	sp!,{r0-r2,r4-r11,lr}
+#if __ARM_ARCH__<7 && !defined(__thumb2__)
+	sub	r14,pc,#16		@ ChaCha20_ctr32
+#else
+	adr	r14,.LChaCha20_ctr32
+#endif
+	cmp	r2,#0			@ len==0?
+#ifdef	__thumb2__
+	itt	eq
+#endif
+	addeq	sp,sp,#4*3
+	beq	.Lno_data
+#if __ARM_MAX_ARCH__>=7
+	cmp	r2,#192			@ test len
+	bls	.Lshort
+	ldr	r4,[r14,#-32]
+	ldr	r4,[r14,r4]
+# ifdef	__APPLE__
+	ldr	r4,[r4]
+# endif
+	tst	r4,#ARMV7_NEON
+	bne	.LChaCha20_neon
+.Lshort:
+#endif
+	ldmia	r12,{r4-r7}		@ load counter and nonce
+	sub	sp,sp,#4*(16)		@ off-load area
+	sub	r14,r14,#64		@ .Lsigma
+	stmdb	sp!,{r4-r7}		@ copy counter and nonce
+	ldmia	r3,{r4-r11}		@ load key
+	ldmia	r14,{r0-r3}		@ load sigma
+	stmdb	sp!,{r4-r11}		@ copy key
+	stmdb	sp!,{r0-r3}		@ copy sigma
+	str	r10,[sp,#4*(16+10)]	@ off-load "@x[10]"
+	str	r11,[sp,#4*(16+11)]	@ off-load "@x[11]"
+	b	.Loop_outer_enter
+
+.align	4
+.Loop_outer:
+	ldmia	sp,{r0-r9}		@ load key material
+	str	@t[3],[sp,#4*(32+2)]	@ save len
+	str	r12,  [sp,#4*(32+1)]	@ save inp
+	str	r14,  [sp,#4*(32+0)]	@ save out
+.Loop_outer_enter:
+	ldr	@t[3], [sp,#4*(15)]
+	ldr	@x[12],[sp,#4*(12)]	@ modulo-scheduled load
+	ldr	@t[2], [sp,#4*(13)]
+	ldr	@x[14],[sp,#4*(14)]
+	str	@t[3], [sp,#4*(16+15)]
+	mov	@t[3],#10
+	b	.Loop
+
+.align	4
+.Loop:
+	subs	@t[3],@t[3],#1
+___
+	foreach (&ROUND(0, 4, 8,12)) { eval; }
+	foreach (&ROUND(0, 5,10,15)) { eval; }
+$code.=<<___;
+	bne	.Loop
+
+	ldr	@t[3],[sp,#4*(32+2)]	@ load len
+
+	str	@t[0], [sp,#4*(16+8)]	@ modulo-scheduled store
+	str	@t[1], [sp,#4*(16+9)]
+	str	@x[12],[sp,#4*(16+12)]
+	str	@t[2], [sp,#4*(16+13)]
+	str	@x[14],[sp,#4*(16+14)]
+
+	@ at this point we have first half of 512-bit result in
+	@ @x[0-7] and second half at sp+4*(16+8)
+
+	cmp	@t[3],#64		@ done yet?
+#ifdef	__thumb2__
+	itete	lo
+#endif
+	addlo	r12,sp,#4*(0)		@ shortcut or ...
+	ldrhs	r12,[sp,#4*(32+1)]	@ ... load inp
+	addlo	r14,sp,#4*(0)		@ shortcut or ...
+	ldrhs	r14,[sp,#4*(32+0)]	@ ... load out
+
+	ldr	@t[0],[sp,#4*(0)]	@ load key material
+	ldr	@t[1],[sp,#4*(1)]
+
+#if __ARM_ARCH__>=6 || !defined(__ARMEB__)
+# if __ARM_ARCH__<7
+	orr	@t[2],r12,r14
+	tst	@t[2],#3		@ are input and output aligned?
+	ldr	@t[2],[sp,#4*(2)]
+	bne	.Lunaligned
+	cmp	@t[3],#64		@ restore flags
+# else
+	ldr	@t[2],[sp,#4*(2)]
+# endif
+	ldr	@t[3],[sp,#4*(3)]
+
+	add	@x[0],@x[0],@t[0]	@ accumulate key material
+	add	@x[1],@x[1],@t[1]
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhs	@t[0],[r12],#16		@ load input
+	ldrhs	@t[1],[r12,#-12]
+
+	add	@x[2],@x[2],@t[2]
+	add	@x[3],@x[3],@t[3]
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhs	@t[2],[r12,#-8]
+	ldrhs	@t[3],[r12,#-4]
+# if __ARM_ARCH__>=6 && defined(__ARMEB__)
+	rev	@x[0],@x[0]
+	rev	@x[1],@x[1]
+	rev	@x[2],@x[2]
+	rev	@x[3],@x[3]
+# endif
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	eorhs	@x[0],@x[0],@t[0]	@ xor with input
+	eorhs	@x[1],@x[1],@t[1]
+	 add	@t[0],sp,#4*(4)
+	str	@x[0],[r14],#16		@ store output
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	eorhs	@x[2],@x[2],@t[2]
+	eorhs	@x[3],@x[3],@t[3]
+	 ldmia	@t[0],{@t[0]-@t[3]}	@ load key material
+	str	@x[1],[r14,#-12]
+	str	@x[2],[r14,#-8]
+	str	@x[3],[r14,#-4]
+
+	add	@x[4],@x[4],@t[0]	@ accumulate key material
+	add	@x[5],@x[5],@t[1]
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhs	@t[0],[r12],#16		@ load input
+	ldrhs	@t[1],[r12,#-12]
+	add	@x[6],@x[6],@t[2]
+	add	@x[7],@x[7],@t[3]
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhs	@t[2],[r12,#-8]
+	ldrhs	@t[3],[r12,#-4]
+# if __ARM_ARCH__>=6 && defined(__ARMEB__)
+	rev	@x[4],@x[4]
+	rev	@x[5],@x[5]
+	rev	@x[6],@x[6]
+	rev	@x[7],@x[7]
+# endif
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	eorhs	@x[4],@x[4],@t[0]
+	eorhs	@x[5],@x[5],@t[1]
+	 add	@t[0],sp,#4*(8)
+	str	@x[4],[r14],#16		@ store output
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	eorhs	@x[6],@x[6],@t[2]
+	eorhs	@x[7],@x[7],@t[3]
+	str	@x[5],[r14,#-12]
+	 ldmia	@t[0],{@t[0]-@t[3]}	@ load key material
+	str	@x[6],[r14,#-8]
+	 add	@x[0],sp,#4*(16+8)
+	str	@x[7],[r14,#-4]
+
+	ldmia	@x[0],{@x[0]-@x[7]}	@ load second half
+
+	add	@x[0],@x[0],@t[0]	@ accumulate key material
+	add	@x[1],@x[1],@t[1]
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhs	@t[0],[r12],#16		@ load input
+	ldrhs	@t[1],[r12,#-12]
+# ifdef	__thumb2__
+	itt	hi
+# endif
+	 strhi	@t[2],[sp,#4*(16+10)]	@ copy "@x[10]" while at it
+	 strhi	@t[3],[sp,#4*(16+11)]	@ copy "@x[11]" while at it
+	add	@x[2],@x[2],@t[2]
+	add	@x[3],@x[3],@t[3]
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhs	@t[2],[r12,#-8]
+	ldrhs	@t[3],[r12,#-4]
+# if __ARM_ARCH__>=6 && defined(__ARMEB__)
+	rev	@x[0],@x[0]
+	rev	@x[1],@x[1]
+	rev	@x[2],@x[2]
+	rev	@x[3],@x[3]
+# endif
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	eorhs	@x[0],@x[0],@t[0]
+	eorhs	@x[1],@x[1],@t[1]
+	 add	@t[0],sp,#4*(12)
+	str	@x[0],[r14],#16		@ store output
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	eorhs	@x[2],@x[2],@t[2]
+	eorhs	@x[3],@x[3],@t[3]
+	str	@x[1],[r14,#-12]
+	 ldmia	@t[0],{@t[0]-@t[3]}	@ load key material
+	str	@x[2],[r14,#-8]
+	str	@x[3],[r14,#-4]
+
+	add	@x[4],@x[4],@t[0]	@ accumulate key material
+	add	@x[5],@x[5],@t[1]
+# ifdef	__thumb2__
+	itt	hi
+# endif
+	 addhi	@t[0],@t[0],#1		@ next counter value
+	 strhi	@t[0],[sp,#4*(12)]	@ save next counter value
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhs	@t[0],[r12],#16		@ load input
+	ldrhs	@t[1],[r12,#-12]
+	add	@x[6],@x[6],@t[2]
+	add	@x[7],@x[7],@t[3]
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhs	@t[2],[r12,#-8]
+	ldrhs	@t[3],[r12,#-4]
+# if __ARM_ARCH__>=6 && defined(__ARMEB__)
+	rev	@x[4],@x[4]
+	rev	@x[5],@x[5]
+	rev	@x[6],@x[6]
+	rev	@x[7],@x[7]
+# endif
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	eorhs	@x[4],@x[4],@t[0]
+	eorhs	@x[5],@x[5],@t[1]
+# ifdef	__thumb2__
+	 it	ne
+# endif
+	 ldrne	@t[0],[sp,#4*(32+2)]	@ re-load len
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	eorhs	@x[6],@x[6],@t[2]
+	eorhs	@x[7],@x[7],@t[3]
+	str	@x[4],[r14],#16		@ store output
+	str	@x[5],[r14,#-12]
+# ifdef	__thumb2__
+	it	hs
+# endif
+	 subhs	@t[3],@t[0],#64		@ len-=64
+	str	@x[6],[r14,#-8]
+	str	@x[7],[r14,#-4]
+	bhi	.Loop_outer
+
+	beq	.Ldone
+# if __ARM_ARCH__<7
+	b	.Ltail
+
+.align	4
+.Lunaligned:				@ unaligned endian-neutral path
+	cmp	@t[3],#64		@ restore flags
+# endif
+#endif
+#if __ARM_ARCH__<7
+	ldr	@t[3],[sp,#4*(3)]
+___
+for ($i=0;$i<16;$i+=4) {
+my $j=$i&0x7;
+
+$code.=<<___	if ($i==4);
+	add	@x[0],sp,#4*(16+8)
+___
+$code.=<<___	if ($i==8);
+	ldmia	@x[0],{@x[0]-@x[7]}		@ load second half
+# ifdef	__thumb2__
+	itt	hi
+# endif
+	strhi	@t[2],[sp,#4*(16+10)]		@ copy "@x[10]"
+	strhi	@t[3],[sp,#4*(16+11)]		@ copy "@x[11]"
+___
+$code.=<<___;
+	add	@x[$j+0],@x[$j+0],@t[0]		@ accumulate key material
+___
+$code.=<<___	if ($i==12);
+# ifdef	__thumb2__
+	itt	hi
+# endif
+	addhi	@t[0],@t[0],#1			@ next counter value
+	strhi	@t[0],[sp,#4*(12)]		@ save next counter value
+___
+$code.=<<___;
+	add	@x[$j+1],@x[$j+1],@t[1]
+	add	@x[$j+2],@x[$j+2],@t[2]
+# ifdef	__thumb2__
+	itete	lo
+# endif
+	eorlo	@t[0],@t[0],@t[0]		@ zero or ...
+	ldrhsb	@t[0],[r12],#16			@ ... load input
+	eorlo	@t[1],@t[1],@t[1]
+	ldrhsb	@t[1],[r12,#-12]
+
+	add	@x[$j+3],@x[$j+3],@t[3]
+# ifdef	__thumb2__
+	itete	lo
+# endif
+	eorlo	@t[2],@t[2],@t[2]
+	ldrhsb	@t[2],[r12,#-8]
+	eorlo	@t[3],@t[3],@t[3]
+	ldrhsb	@t[3],[r12,#-4]
+
+	eor	@x[$j+0],@t[0],@x[$j+0]		@ xor with input (or zero)
+	eor	@x[$j+1],@t[1],@x[$j+1]
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	@t[0],[r12,#-15]		@ load more input
+	ldrhsb	@t[1],[r12,#-11]
+	eor	@x[$j+2],@t[2],@x[$j+2]
+	 strb	@x[$j+0],[r14],#16		@ store output
+	eor	@x[$j+3],@t[3],@x[$j+3]
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	@t[2],[r12,#-7]
+	ldrhsb	@t[3],[r12,#-3]
+	 strb	@x[$j+1],[r14,#-12]
+	eor	@x[$j+0],@t[0],@x[$j+0],lsr#8
+	 strb	@x[$j+2],[r14,#-8]
+	eor	@x[$j+1],@t[1],@x[$j+1],lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	@t[0],[r12,#-14]		@ load more input
+	ldrhsb	@t[1],[r12,#-10]
+	 strb	@x[$j+3],[r14,#-4]
+	eor	@x[$j+2],@t[2],@x[$j+2],lsr#8
+	 strb	@x[$j+0],[r14,#-15]
+	eor	@x[$j+3],@t[3],@x[$j+3],lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	@t[2],[r12,#-6]
+	ldrhsb	@t[3],[r12,#-2]
+	 strb	@x[$j+1],[r14,#-11]
+	eor	@x[$j+0],@t[0],@x[$j+0],lsr#8
+	 strb	@x[$j+2],[r14,#-7]
+	eor	@x[$j+1],@t[1],@x[$j+1],lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	@t[0],[r12,#-13]		@ load more input
+	ldrhsb	@t[1],[r12,#-9]
+	 strb	@x[$j+3],[r14,#-3]
+	eor	@x[$j+2],@t[2],@x[$j+2],lsr#8
+	 strb	@x[$j+0],[r14,#-14]
+	eor	@x[$j+3],@t[3],@x[$j+3],lsr#8
+# ifdef	__thumb2__
+	itt	hs
+# endif
+	ldrhsb	@t[2],[r12,#-5]
+	ldrhsb	@t[3],[r12,#-1]
+	 strb	@x[$j+1],[r14,#-10]
+	 strb	@x[$j+2],[r14,#-6]
+	eor	@x[$j+0],@t[0],@x[$j+0],lsr#8
+	 strb	@x[$j+3],[r14,#-2]
+	eor	@x[$j+1],@t[1],@x[$j+1],lsr#8
+	 strb	@x[$j+0],[r14,#-13]
+	eor	@x[$j+2],@t[2],@x[$j+2],lsr#8
+	 strb	@x[$j+1],[r14,#-9]
+	eor	@x[$j+3],@t[3],@x[$j+3],lsr#8
+	 strb	@x[$j+2],[r14,#-5]
+	 strb	@x[$j+3],[r14,#-1]
+___
+$code.=<<___	if ($i<12);
+	add	@t[0],sp,#4*(4+$i)
+	ldmia	@t[0],{@t[0]-@t[3]}		@ load key material
+___
+}
+$code.=<<___;
+# ifdef	__thumb2__
+	it	ne
+# endif
+	ldrne	@t[0],[sp,#4*(32+2)]		@ re-load len
+# ifdef	__thumb2__
+	it	hs
+# endif
+	subhs	@t[3],@t[0],#64			@ len-=64
+	bhi	.Loop_outer
+
+	beq	.Ldone
+#endif
+
+.Ltail:
+	ldr	r12,[sp,#4*(32+1)]	@ load inp
+	add	@t[1],sp,#4*(0)
+	ldr	r14,[sp,#4*(32+0)]	@ load out
+
+.Loop_tail:
+	ldrb	@t[2],[@t[1]],#1	@ read buffer on stack
+	ldrb	@t[3],[r12],#1		@ read input
+	subs	@t[0],@t[0],#1
+	eor	@t[3],@t[3],@t[2]
+	strb	@t[3],[r14],#1		@ store output
+	bne	.Loop_tail
+
+.Ldone:
+	add	sp,sp,#4*(32+3)
+.Lno_data:
+	ldmia	sp!,{r4-r11,pc}
+.size	ChaCha20_ctr32,.-ChaCha20_ctr32
+___
+
+{{{
+my ($a0,$b0,$c0,$d0,$a1,$b1,$c1,$d1,$a2,$b2,$c2,$d2,$t0,$t1,$t2,$t3) =
+    map("q$_",(0..15));
+
+sub NEONROUND {
+my $odd = pop;
+my ($a,$b,$c,$d,$t)=@_;
+
+	(
+	"&vadd_i32	($a,$a,$b)",
+	"&veor		($d,$d,$a)",
+	"&vrev32_16	($d,$d)",	# vrot ($d,16)
+
+	"&vadd_i32	($c,$c,$d)",
+	"&veor		($t,$b,$c)",
+	"&vshr_u32	($b,$t,20)",
+	"&vsli_32	($b,$t,12)",
+
+	"&vadd_i32	($a,$a,$b)",
+	"&veor		($t,$d,$a)",
+	"&vshr_u32	($d,$t,24)",
+	"&vsli_32	($d,$t,8)",
+
+	"&vadd_i32	($c,$c,$d)",
+	"&veor		($t,$b,$c)",
+	"&vshr_u32	($b,$t,25)",
+	"&vsli_32	($b,$t,7)",
+
+	"&vext_8	($c,$c,$c,8)",
+	"&vext_8	($b,$b,$b,$odd?12:4)",
+	"&vext_8	($d,$d,$d,$odd?4:12)"
+	);
+}
+
+$code.=<<___;
+#if __ARM_MAX_ARCH__>=7
+.arch	armv7-a
+.fpu	neon
+
+.type	ChaCha20_neon,%function
+.align	5
+ChaCha20_neon:
+	ldr		r12,[sp,#0]		@ pull pointer to counter and nonce
+	stmdb		sp!,{r0-r2,r4-r11,lr}
+.LChaCha20_neon:
+	adr		r14,.Lsigma
+	vstmdb		sp!,{d8-d15}		@ ABI spec says so
+	stmdb		sp!,{r0-r3}
+
+	vld1.32		{$b0-$c0},[r3]		@ load key
+	ldmia		r3,{r4-r11}		@ load key
+
+	sub		sp,sp,#4*(16+16)
+	vld1.32		{$d0},[r12]		@ load counter and nonce
+	add		r12,sp,#4*8
+	ldmia		r14,{r0-r3}		@ load sigma
+	vld1.32		{$a0},[r14]!		@ load sigma
+	vld1.32		{$t0},[r14]		@ one
+	vst1.32		{$c0-$d0},[r12]		@ copy 1/2key|counter|nonce
+	vst1.32		{$a0-$b0},[sp]		@ copy sigma|1/2key
+
+	str		r10,[sp,#4*(16+10)]	@ off-load "@x[10]"
+	str		r11,[sp,#4*(16+11)]	@ off-load "@x[11]"
+	vshl.i32	$t1#lo,$t0#lo,#1	@ two
+	vstr		$t0#lo,[sp,#4*(16+0)]
+	vshl.i32	$t2#lo,$t0#lo,#2	@ four
+	vstr		$t1#lo,[sp,#4*(16+2)]
+	vmov		$a1,$a0
+	vstr		$t2#lo,[sp,#4*(16+4)]
+	vmov		$a2,$a0
+	vmov		$b1,$b0
+	vmov		$b2,$b0
+	b		.Loop_neon_enter
+
+.align	4
+.Loop_neon_outer:
+	ldmia		sp,{r0-r9}		@ load key material
+	cmp		@t[3],#64*2		@ if len<=64*2
+	bls		.Lbreak_neon		@ switch to integer-only
+	vmov		$a1,$a0
+	str		@t[3],[sp,#4*(32+2)]	@ save len
+	vmov		$a2,$a0
+	str		r12,  [sp,#4*(32+1)]	@ save inp
+	vmov		$b1,$b0
+	str		r14,  [sp,#4*(32+0)]	@ save out
+	vmov		$b2,$b0
+.Loop_neon_enter:
+	ldr		@t[3], [sp,#4*(15)]
+	vadd.i32	$d1,$d0,$t0		@ counter+1
+	ldr		@x[12],[sp,#4*(12)]	@ modulo-scheduled load
+	vmov		$c1,$c0
+	ldr		@t[2], [sp,#4*(13)]
+	vmov		$c2,$c0
+	ldr		@x[14],[sp,#4*(14)]
+	vadd.i32	$d2,$d1,$t0		@ counter+2
+	str		@t[3], [sp,#4*(16+15)]
+	mov		@t[3],#10
+	add		@x[12],@x[12],#3	@ counter+3
+	b		.Loop_neon
+
+.align	4
+.Loop_neon:
+	subs		@t[3],@t[3],#1
+___
+	my @thread0=&NEONROUND($a0,$b0,$c0,$d0,$t0,0);
+	my @thread1=&NEONROUND($a1,$b1,$c1,$d1,$t1,0);
+	my @thread2=&NEONROUND($a2,$b2,$c2,$d2,$t2,0);
+	my @thread3=&ROUND(0,4,8,12);
+
+	foreach (@thread0) {
+		eval;			eval(shift(@thread3));
+		eval(shift(@thread1));	eval(shift(@thread3));
+		eval(shift(@thread2));	eval(shift(@thread3));
+	}
+
+	@thread0=&NEONROUND($a0,$b0,$c0,$d0,$t0,1);
+	@thread1=&NEONROUND($a1,$b1,$c1,$d1,$t1,1);
+	@thread2=&NEONROUND($a2,$b2,$c2,$d2,$t2,1);
+	@thread3=&ROUND(0,5,10,15);
+
+	foreach (@thread0) {
+		eval;			eval(shift(@thread3));
+		eval(shift(@thread1));	eval(shift(@thread3));
+		eval(shift(@thread2));	eval(shift(@thread3));
+	}
+$code.=<<___;
+	bne		.Loop_neon
+
+	add		@t[3],sp,#32
+	vld1.32		{$t0-$t1},[sp]		@ load key material
+	vld1.32		{$t2-$t3},[@t[3]]
+
+	ldr		@t[3],[sp,#4*(32+2)]	@ load len
+
+	str		@t[0], [sp,#4*(16+8)]	@ modulo-scheduled store
+	str		@t[1], [sp,#4*(16+9)]
+	str		@x[12],[sp,#4*(16+12)]
+	str		@t[2], [sp,#4*(16+13)]
+	str		@x[14],[sp,#4*(16+14)]
+
+	@ at this point we have first half of 512-bit result in
+	@ @x[0-7] and second half at sp+4*(16+8)
+
+	ldr		r12,[sp,#4*(32+1)]	@ load inp
+	ldr		r14,[sp,#4*(32+0)]	@ load out
+
+	vadd.i32	$a0,$a0,$t0		@ accumulate key material
+	vadd.i32	$a1,$a1,$t0
+	vadd.i32	$a2,$a2,$t0
+	vldr		$t0#lo,[sp,#4*(16+0)]	@ one
+
+	vadd.i32	$b0,$b0,$t1
+	vadd.i32	$b1,$b1,$t1
+	vadd.i32	$b2,$b2,$t1
+	vldr		$t1#lo,[sp,#4*(16+2)]	@ two
+
+	vadd.i32	$c0,$c0,$t2
+	vadd.i32	$c1,$c1,$t2
+	vadd.i32	$c2,$c2,$t2
+	vadd.i32	$d1#lo,$d1#lo,$t0#lo	@ counter+1
+	vadd.i32	$d2#lo,$d2#lo,$t1#lo	@ counter+2
+
+	vadd.i32	$d0,$d0,$t3
+	vadd.i32	$d1,$d1,$t3
+	vadd.i32	$d2,$d2,$t3
+
+	cmp		@t[3],#64*4
+	blo		.Ltail_neon
+
+	vld1.8		{$t0-$t1},[r12]!	@ load input
+	 mov		@t[3],sp
+	vld1.8		{$t2-$t3},[r12]!
+	veor		$a0,$a0,$t0		@ xor with input
+	veor		$b0,$b0,$t1
+	vld1.8		{$t0-$t1},[r12]!
+	veor		$c0,$c0,$t2
+	veor		$d0,$d0,$t3
+	vld1.8		{$t2-$t3},[r12]!
+
+	veor		$a1,$a1,$t0
+	 vst1.8		{$a0-$b0},[r14]!	@ store output
+	veor		$b1,$b1,$t1
+	vld1.8		{$t0-$t1},[r12]!
+	veor		$c1,$c1,$t2
+	 vst1.8		{$c0-$d0},[r14]!
+	veor		$d1,$d1,$t3
+	vld1.8		{$t2-$t3},[r12]!
+
+	veor		$a2,$a2,$t0
+	 vld1.32	{$a0-$b0},[@t[3]]!	@ load for next iteration
+	 veor		$t0#hi,$t0#hi,$t0#hi
+	 vldr		$t0#lo,[sp,#4*(16+4)]	@ four
+	veor		$b2,$b2,$t1
+	 vld1.32	{$c0-$d0},[@t[3]]
+	veor		$c2,$c2,$t2
+	 vst1.8		{$a1-$b1},[r14]!
+	veor		$d2,$d2,$t3
+	 vst1.8		{$c1-$d1},[r14]!
+
+	vadd.i32	$d0#lo,$d0#lo,$t0#lo	@ next counter value
+	vldr		$t0#lo,[sp,#4*(16+0)]	@ one
+
+	ldmia		sp,{@t[0]-@t[3]}	@ load key material
+	add		@x[0],@x[0],@t[0]	@ accumulate key material
+	ldr		@t[0],[r12],#16		@ load input
+	 vst1.8		{$a2-$b2},[r14]!
+	add		@x[1],@x[1],@t[1]
+	ldr		@t[1],[r12,#-12]
+	 vst1.8		{$c2-$d2},[r14]!
+	add		@x[2],@x[2],@t[2]
+	ldr		@t[2],[r12,#-8]
+	add		@x[3],@x[3],@t[3]
+	ldr		@t[3],[r12,#-4]
+# ifdef	__ARMEB__
+	rev		@x[0],@x[0]
+	rev		@x[1],@x[1]
+	rev		@x[2],@x[2]
+	rev		@x[3],@x[3]
+# endif
+	eor		@x[0],@x[0],@t[0]	@ xor with input
+	 add		@t[0],sp,#4*(4)
+	eor		@x[1],@x[1],@t[1]
+	str		@x[0],[r14],#16		@ store output
+	eor		@x[2],@x[2],@t[2]
+	str		@x[1],[r14,#-12]
+	eor		@x[3],@x[3],@t[3]
+	 ldmia		@t[0],{@t[0]-@t[3]}	@ load key material
+	str		@x[2],[r14,#-8]
+	str		@x[3],[r14,#-4]
+
+	add		@x[4],@x[4],@t[0]	@ accumulate key material
+	ldr		@t[0],[r12],#16		@ load input
+	add		@x[5],@x[5],@t[1]
+	ldr		@t[1],[r12,#-12]
+	add		@x[6],@x[6],@t[2]
+	ldr		@t[2],[r12,#-8]
+	add		@x[7],@x[7],@t[3]
+	ldr		@t[3],[r12,#-4]
+# ifdef	__ARMEB__
+	rev		@x[4],@x[4]
+	rev		@x[5],@x[5]
+	rev		@x[6],@x[6]
+	rev		@x[7],@x[7]
+# endif
+	eor		@x[4],@x[4],@t[0]
+	 add		@t[0],sp,#4*(8)
+	eor		@x[5],@x[5],@t[1]
+	str		@x[4],[r14],#16		@ store output
+	eor		@x[6],@x[6],@t[2]
+	str		@x[5],[r14,#-12]
+	eor		@x[7],@x[7],@t[3]
+	 ldmia		@t[0],{@t[0]-@t[3]}	@ load key material
+	str		@x[6],[r14,#-8]
+	 add		@x[0],sp,#4*(16+8)
+	str		@x[7],[r14,#-4]
+
+	ldmia		@x[0],{@x[0]-@x[7]}	@ load second half
+
+	add		@x[0],@x[0],@t[0]	@ accumulate key material
+	ldr		@t[0],[r12],#16		@ load input
+	add		@x[1],@x[1],@t[1]
+	ldr		@t[1],[r12,#-12]
+# ifdef	__thumb2__
+	it	hi
+# endif
+	 strhi		@t[2],[sp,#4*(16+10)]	@ copy "@x[10]" while at it
+	add		@x[2],@x[2],@t[2]
+	ldr		@t[2],[r12,#-8]
+# ifdef	__thumb2__
+	it	hi
+# endif
+	 strhi		@t[3],[sp,#4*(16+11)]	@ copy "@x[11]" while at it
+	add		@x[3],@x[3],@t[3]
+	ldr		@t[3],[r12,#-4]
+# ifdef	__ARMEB__
+	rev		@x[0],@x[0]
+	rev		@x[1],@x[1]
+	rev		@x[2],@x[2]
+	rev		@x[3],@x[3]
+# endif
+	eor		@x[0],@x[0],@t[0]
+	 add		@t[0],sp,#4*(12)
+	eor		@x[1],@x[1],@t[1]
+	str		@x[0],[r14],#16		@ store output
+	eor		@x[2],@x[2],@t[2]
+	str		@x[1],[r14,#-12]
+	eor		@x[3],@x[3],@t[3]
+	 ldmia		@t[0],{@t[0]-@t[3]}	@ load key material
+	str		@x[2],[r14,#-8]
+	str		@x[3],[r14,#-4]
+
+	add		@x[4],@x[4],@t[0]	@ accumulate key material
+	 add		@t[0],@t[0],#4		@ next counter value
+	add		@x[5],@x[5],@t[1]
+	 str		@t[0],[sp,#4*(12)]	@ save next counter value
+	ldr		@t[0],[r12],#16		@ load input
+	add		@x[6],@x[6],@t[2]
+	 add		@x[4],@x[4],#3		@ counter+3
+	ldr		@t[1],[r12,#-12]
+	add		@x[7],@x[7],@t[3]
+	ldr		@t[2],[r12,#-8]
+	ldr		@t[3],[r12,#-4]
+# ifdef	__ARMEB__
+	rev		@x[4],@x[4]
+	rev		@x[5],@x[5]
+	rev		@x[6],@x[6]
+	rev		@x[7],@x[7]
+# endif
+	eor		@x[4],@x[4],@t[0]
+# ifdef	__thumb2__
+	it	hi
+# endif
+	 ldrhi		@t[0],[sp,#4*(32+2)]	@ re-load len
+	eor		@x[5],@x[5],@t[1]
+	eor		@x[6],@x[6],@t[2]
+	str		@x[4],[r14],#16		@ store output
+	eor		@x[7],@x[7],@t[3]
+	str		@x[5],[r14,#-12]
+	 sub		@t[3],@t[0],#64*4	@ len-=64*4
+	str		@x[6],[r14,#-8]
+	str		@x[7],[r14,#-4]
+	bhi		.Loop_neon_outer
+
+	b		.Ldone_neon
+
+.align	4
+.Lbreak_neon:
+	@ harmonize NEON and integer-only stack frames: load data
+	@ from NEON frame, but save to integer-only one; distance
+	@ between the two is 4*(32+4+16-32)=4*(20).
+
+	str		@t[3], [sp,#4*(20+32+2)]	@ save len
+	 add		@t[3],sp,#4*(32+4)
+	str		r12,   [sp,#4*(20+32+1)]	@ save inp
+	str		r14,   [sp,#4*(20+32+0)]	@ save out
+
+	ldr		@x[12],[sp,#4*(16+10)]
+	ldr		@x[14],[sp,#4*(16+11)]
+	 vldmia		@t[3],{d8-d15}			@ fulfill ABI requirement
+	str		@x[12],[sp,#4*(20+16+10)]	@ copy "@x[10]"
+	str		@x[14],[sp,#4*(20+16+11)]	@ copy "@x[11]"
+
+	ldr		@t[3], [sp,#4*(15)]
+	ldr		@x[12],[sp,#4*(12)]		@ modulo-scheduled load
+	ldr		@t[2], [sp,#4*(13)]
+	ldr		@x[14],[sp,#4*(14)]
+	str		@t[3], [sp,#4*(20+16+15)]
+	add		@t[3],sp,#4*(20)
+	vst1.32		{$a0-$b0},[@t[3]]!		@ copy key
+	add		sp,sp,#4*(20)			@ switch frame
+	vst1.32		{$c0-$d0},[@t[3]]
+	mov		@t[3],#10
+	b		.Loop				@ go integer-only
+
+.align	4
+.Ltail_neon:
+	cmp		@t[3],#64*3
+	bhs		.L192_or_more_neon
+	cmp		@t[3],#64*2
+	bhs		.L128_or_more_neon
+	cmp		@t[3],#64*1
+	bhs		.L64_or_more_neon
+
+	add		@t[0],sp,#4*(8)
+	vst1.8		{$a0-$b0},[sp]
+	add		@t[2],sp,#4*(0)
+	vst1.8		{$c0-$d0},[@t[0]]
+	b		.Loop_tail_neon
+
+.align	4
+.L64_or_more_neon:
+	vld1.8		{$t0-$t1},[r12]!
+	vld1.8		{$t2-$t3},[r12]!
+	veor		$a0,$a0,$t0
+	veor		$b0,$b0,$t1
+	veor		$c0,$c0,$t2
+	veor		$d0,$d0,$t3
+	vst1.8		{$a0-$b0},[r14]!
+	vst1.8		{$c0-$d0},[r14]!
+
+	beq		.Ldone_neon
+
+	add		@t[0],sp,#4*(8)
+	vst1.8		{$a1-$b1},[sp]
+	add		@t[2],sp,#4*(0)
+	vst1.8		{$c1-$d1},[@t[0]]
+	sub		@t[3],@t[3],#64*1	@ len-=64*1
+	b		.Loop_tail_neon
+
+.align	4
+.L128_or_more_neon:
+	vld1.8		{$t0-$t1},[r12]!
+	vld1.8		{$t2-$t3},[r12]!
+	veor		$a0,$a0,$t0
+	veor		$b0,$b0,$t1
+	vld1.8		{$t0-$t1},[r12]!
+	veor		$c0,$c0,$t2
+	veor		$d0,$d0,$t3
+	vld1.8		{$t2-$t3},[r12]!
+
+	veor		$a1,$a1,$t0
+	veor		$b1,$b1,$t1
+	 vst1.8		{$a0-$b0},[r14]!
+	veor		$c1,$c1,$t2
+	 vst1.8		{$c0-$d0},[r14]!
+	veor		$d1,$d1,$t3
+	vst1.8		{$a1-$b1},[r14]!
+	vst1.8		{$c1-$d1},[r14]!
+
+	beq		.Ldone_neon
+
+	add		@t[0],sp,#4*(8)
+	vst1.8		{$a2-$b2},[sp]
+	add		@t[2],sp,#4*(0)
+	vst1.8		{$c2-$d2},[@t[0]]
+	sub		@t[3],@t[3],#64*2	@ len-=64*2
+	b		.Loop_tail_neon
+
+.align	4
+.L192_or_more_neon:
+	vld1.8		{$t0-$t1},[r12]!
+	vld1.8		{$t2-$t3},[r12]!
+	veor		$a0,$a0,$t0
+	veor		$b0,$b0,$t1
+	vld1.8		{$t0-$t1},[r12]!
+	veor		$c0,$c0,$t2
+	veor		$d0,$d0,$t3
+	vld1.8		{$t2-$t3},[r12]!
+
+	veor		$a1,$a1,$t0
+	veor		$b1,$b1,$t1
+	vld1.8		{$t0-$t1},[r12]!
+	veor		$c1,$c1,$t2
+	 vst1.8		{$a0-$b0},[r14]!
+	veor		$d1,$d1,$t3
+	vld1.8		{$t2-$t3},[r12]!
+
+	veor		$a2,$a2,$t0
+	 vst1.8		{$c0-$d0},[r14]!
+	veor		$b2,$b2,$t1
+	 vst1.8		{$a1-$b1},[r14]!
+	veor		$c2,$c2,$t2
+	 vst1.8		{$c1-$d1},[r14]!
+	veor		$d2,$d2,$t3
+	vst1.8		{$a2-$b2},[r14]!
+	vst1.8		{$c2-$d2},[r14]!
+
+	beq		.Ldone_neon
+
+	ldmia		sp,{@t[0]-@t[3]}	@ load key material
+	add		@x[0],@x[0],@t[0]	@ accumulate key material
+	 add		@t[0],sp,#4*(4)
+	add		@x[1],@x[1],@t[1]
+	add		@x[2],@x[2],@t[2]
+	add		@x[3],@x[3],@t[3]
+	 ldmia		@t[0],{@t[0]-@t[3]}	@ load key material
+
+	add		@x[4],@x[4],@t[0]	@ accumulate key material
+	 add		@t[0],sp,#4*(8)
+	add		@x[5],@x[5],@t[1]
+	add		@x[6],@x[6],@t[2]
+	add		@x[7],@x[7],@t[3]
+	 ldmia		@t[0],{@t[0]-@t[3]}	@ load key material
+# ifdef	__ARMEB__
+	rev		@x[0],@x[0]
+	rev		@x[1],@x[1]
+	rev		@x[2],@x[2]
+	rev		@x[3],@x[3]
+	rev		@x[4],@x[4]
+	rev		@x[5],@x[5]
+	rev		@x[6],@x[6]
+	rev		@x[7],@x[7]
+# endif
+	stmia		sp,{@x[0]-@x[7]}
+	 add		@x[0],sp,#4*(16+8)
+
+	ldmia		@x[0],{@x[0]-@x[7]}	@ load second half
+
+	add		@x[0],@x[0],@t[0]	@ accumulate key material
+	 add		@t[0],sp,#4*(12)
+	add		@x[1],@x[1],@t[1]
+	add		@x[2],@x[2],@t[2]
+	add		@x[3],@x[3],@t[3]
+	 ldmia		@t[0],{@t[0]-@t[3]}	@ load key material
+
+	add		@x[4],@x[4],@t[0]	@ accumulate key material
+	 add		@t[0],sp,#4*(8)
+	add		@x[5],@x[5],@t[1]
+	 add		@x[4],@x[4],#3		@ counter+3
+	add		@x[6],@x[6],@t[2]
+	add		@x[7],@x[7],@t[3]
+	 ldr		@t[3],[sp,#4*(32+2)]	@ re-load len
+# ifdef	__ARMEB__
+	rev		@x[0],@x[0]
+	rev		@x[1],@x[1]
+	rev		@x[2],@x[2]
+	rev		@x[3],@x[3]
+	rev		@x[4],@x[4]
+	rev		@x[5],@x[5]
+	rev		@x[6],@x[6]
+	rev		@x[7],@x[7]
+# endif
+	stmia		@t[0],{@x[0]-@x[7]}
+	 add		@t[2],sp,#4*(0)
+	 sub		@t[3],@t[3],#64*3	@ len-=64*3
+
+.Loop_tail_neon:
+	ldrb		@t[0],[@t[2]],#1	@ read buffer on stack
+	ldrb		@t[1],[r12],#1		@ read input
+	subs		@t[3],@t[3],#1
+	eor		@t[0],@t[0],@t[1]
+	strb		@t[0],[r14],#1		@ store output
+	bne		.Loop_tail_neon
+
+.Ldone_neon:
+	add		sp,sp,#4*(32+4)
+	vldmia		sp,{d8-d15}
+	add		sp,sp,#4*(16+3)
+	ldmia		sp!,{r4-r11,pc}
+.size	ChaCha20_neon,.-ChaCha20_neon
+.comm	OPENSSL_armcap_P,4,4
+#endif
+___
+}}}
+
+foreach (split("\n",$code)) {
+	s/\`([^\`]*)\`/eval $1/geo;
+
+	s/\bq([0-9]+)#(lo|hi)/sprintf "d%d",2*$1+($2 eq "hi")/geo;
+
+	print $_,"\n";
+}
+close STDOUT;
diff --git a/src/crypto/chacha/asm/chacha-armv8.pl b/src/crypto/chacha/asm/chacha-armv8.pl
new file mode 100755
index 0000000..c2d0429
--- /dev/null
+++ b/src/crypto/chacha/asm/chacha-armv8.pl
@@ -0,0 +1,1127 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# June 2015
+#
+# ChaCha20 for ARMv8.
+#
+# Performance in cycles per byte out of large buffer.
+#
+#			IALU/gcc-4.9    3xNEON+1xIALU	6xNEON+2xIALU
+#
+# Apple A7		5.50/+49%       3.33            1.70
+# Cortex-A53		8.40/+80%       4.72		4.72(*)
+# Cortex-A57		8.06/+43%       4.90            4.43(**)
+# Denver		4.50/+82%       2.63		2.67(*)
+# X-Gene		9.50/+46%       8.82		8.89(*)
+#
+# (*)	it's expected that doubling interleave factor doesn't help
+#	all processors, only those with higher NEON latency and
+#	higher instruction issue rate;
+# (**)	expected improvement was actually higher;
+
+$flavour=shift;
+$output=shift;
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
+die "can't locate arm-xlate.pl";
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
+
+sub AUTOLOAD()		# thunk [simplified] x86-style perlasm
+{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://; $opcode =~ s/_/\./;
+  my $arg = pop;
+    $arg = "#$arg" if ($arg*1 eq $arg);
+    $code .= "\t$opcode\t".join(',',@_,$arg)."\n";
+}
+
+my ($out,$inp,$len,$key,$ctr) = map("x$_",(0..4));
+
+my @x=map("x$_",(5..17,19..21));
+my @d=map("x$_",(22..28,30));
+
+sub ROUND {
+my ($a0,$b0,$c0,$d0)=@_;
+my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0));
+my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1));
+my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2));
+
+    (
+	"&add_32	(@x[$a0],@x[$a0],@x[$b0])",
+	 "&add_32	(@x[$a1],@x[$a1],@x[$b1])",
+	  "&add_32	(@x[$a2],@x[$a2],@x[$b2])",
+	   "&add_32	(@x[$a3],@x[$a3],@x[$b3])",
+	"&eor_32	(@x[$d0],@x[$d0],@x[$a0])",
+	 "&eor_32	(@x[$d1],@x[$d1],@x[$a1])",
+	  "&eor_32	(@x[$d2],@x[$d2],@x[$a2])",
+	   "&eor_32	(@x[$d3],@x[$d3],@x[$a3])",
+	"&ror_32	(@x[$d0],@x[$d0],16)",
+	 "&ror_32	(@x[$d1],@x[$d1],16)",
+	  "&ror_32	(@x[$d2],@x[$d2],16)",
+	   "&ror_32	(@x[$d3],@x[$d3],16)",
+
+	"&add_32	(@x[$c0],@x[$c0],@x[$d0])",
+	 "&add_32	(@x[$c1],@x[$c1],@x[$d1])",
+	  "&add_32	(@x[$c2],@x[$c2],@x[$d2])",
+	   "&add_32	(@x[$c3],@x[$c3],@x[$d3])",
+	"&eor_32	(@x[$b0],@x[$b0],@x[$c0])",
+	 "&eor_32	(@x[$b1],@x[$b1],@x[$c1])",
+	  "&eor_32	(@x[$b2],@x[$b2],@x[$c2])",
+	   "&eor_32	(@x[$b3],@x[$b3],@x[$c3])",
+	"&ror_32	(@x[$b0],@x[$b0],20)",
+	 "&ror_32	(@x[$b1],@x[$b1],20)",
+	  "&ror_32	(@x[$b2],@x[$b2],20)",
+	   "&ror_32	(@x[$b3],@x[$b3],20)",
+
+	"&add_32	(@x[$a0],@x[$a0],@x[$b0])",
+	 "&add_32	(@x[$a1],@x[$a1],@x[$b1])",
+	  "&add_32	(@x[$a2],@x[$a2],@x[$b2])",
+	   "&add_32	(@x[$a3],@x[$a3],@x[$b3])",
+	"&eor_32	(@x[$d0],@x[$d0],@x[$a0])",
+	 "&eor_32	(@x[$d1],@x[$d1],@x[$a1])",
+	  "&eor_32	(@x[$d2],@x[$d2],@x[$a2])",
+	   "&eor_32	(@x[$d3],@x[$d3],@x[$a3])",
+	"&ror_32	(@x[$d0],@x[$d0],24)",
+	 "&ror_32	(@x[$d1],@x[$d1],24)",
+	  "&ror_32	(@x[$d2],@x[$d2],24)",
+	   "&ror_32	(@x[$d3],@x[$d3],24)",
+
+	"&add_32	(@x[$c0],@x[$c0],@x[$d0])",
+	 "&add_32	(@x[$c1],@x[$c1],@x[$d1])",
+	  "&add_32	(@x[$c2],@x[$c2],@x[$d2])",
+	   "&add_32	(@x[$c3],@x[$c3],@x[$d3])",
+	"&eor_32	(@x[$b0],@x[$b0],@x[$c0])",
+	 "&eor_32	(@x[$b1],@x[$b1],@x[$c1])",
+	  "&eor_32	(@x[$b2],@x[$b2],@x[$c2])",
+	   "&eor_32	(@x[$b3],@x[$b3],@x[$c3])",
+	"&ror_32	(@x[$b0],@x[$b0],25)",
+	 "&ror_32	(@x[$b1],@x[$b1],25)",
+	  "&ror_32	(@x[$b2],@x[$b2],25)",
+	   "&ror_32	(@x[$b3],@x[$b3],25)"
+    );
+}
+
+$code.=<<___;
+#include <openssl/arm_arch.h>
+
+.text
+
+.extern	OPENSSL_armcap_P
+
+.align	5
+.Lsigma:
+.quad	0x3320646e61707865,0x6b20657479622d32		// endian-neutral
+.Lone:
+.long	1,0,0,0
+.LOPENSSL_armcap_P:
+#ifdef	__ILP32__
+.long	OPENSSL_armcap_P-.
+#else
+.quad	OPENSSL_armcap_P-.
+#endif
+.asciz	"ChaCha20 for ARMv8, CRYPTOGAMS by <appro\@openssl.org>"
+
+.globl	ChaCha20_ctr32
+.type	ChaCha20_ctr32,%function
+.align	5
+ChaCha20_ctr32:
+	cbz	$len,.Labort
+	adr	@x[0],.LOPENSSL_armcap_P
+	cmp	$len,#192
+	b.lo	.Lshort
+#ifdef	__ILP32__
+	ldrsw	@x[1],[@x[0]]
+#else
+	ldr	@x[1],[@x[0]]
+#endif
+	ldr	w17,[@x[1],@x[0]]
+	tst	w17,#ARMV7_NEON
+	b.ne	ChaCha20_neon
+
+.Lshort:
+	stp	x29,x30,[sp,#-96]!
+	add	x29,sp,#0
+
+	adr	@x[0],.Lsigma
+	stp	x19,x20,[sp,#16]
+	stp	x21,x22,[sp,#32]
+	stp	x23,x24,[sp,#48]
+	stp	x25,x26,[sp,#64]
+	stp	x27,x28,[sp,#80]
+	sub	sp,sp,#64
+
+	ldp	@d[0],@d[1],[@x[0]]		// load sigma
+	ldp	@d[2],@d[3],[$key]		// load key
+	ldp	@d[4],@d[5],[$key,#16]
+	ldp	@d[6],@d[7],[$ctr]		// load counter
+#ifdef	__ARMEB__
+	ror	@d[2],@d[2],#32
+	ror	@d[3],@d[3],#32
+	ror	@d[4],@d[4],#32
+	ror	@d[5],@d[5],#32
+	ror	@d[6],@d[6],#32
+	ror	@d[7],@d[7],#32
+#endif
+
+.Loop_outer:
+	mov.32	@x[0],@d[0]			// unpack key block
+	lsr	@x[1],@d[0],#32
+	mov.32	@x[2],@d[1]
+	lsr	@x[3],@d[1],#32
+	mov.32	@x[4],@d[2]
+	lsr	@x[5],@d[2],#32
+	mov.32	@x[6],@d[3]
+	lsr	@x[7],@d[3],#32
+	mov.32	@x[8],@d[4]
+	lsr	@x[9],@d[4],#32
+	mov.32	@x[10],@d[5]
+	lsr	@x[11],@d[5],#32
+	mov.32	@x[12],@d[6]
+	lsr	@x[13],@d[6],#32
+	mov.32	@x[14],@d[7]
+	lsr	@x[15],@d[7],#32
+
+	mov	$ctr,#10
+	subs	$len,$len,#64
+.Loop:
+	sub	$ctr,$ctr,#1
+___
+	foreach (&ROUND(0, 4, 8,12)) { eval; }
+	foreach (&ROUND(0, 5,10,15)) { eval; }
+$code.=<<___;
+	cbnz	$ctr,.Loop
+
+	add.32	@x[0],@x[0],@d[0]		// accumulate key block
+	add	@x[1],@x[1],@d[0],lsr#32
+	add.32	@x[2],@x[2],@d[1]
+	add	@x[3],@x[3],@d[1],lsr#32
+	add.32	@x[4],@x[4],@d[2]
+	add	@x[5],@x[5],@d[2],lsr#32
+	add.32	@x[6],@x[6],@d[3]
+	add	@x[7],@x[7],@d[3],lsr#32
+	add.32	@x[8],@x[8],@d[4]
+	add	@x[9],@x[9],@d[4],lsr#32
+	add.32	@x[10],@x[10],@d[5]
+	add	@x[11],@x[11],@d[5],lsr#32
+	add.32	@x[12],@x[12],@d[6]
+	add	@x[13],@x[13],@d[6],lsr#32
+	add.32	@x[14],@x[14],@d[7]
+	add	@x[15],@x[15],@d[7],lsr#32
+
+	b.lo	.Ltail
+
+	add	@x[0],@x[0],@x[1],lsl#32	// pack
+	add	@x[2],@x[2],@x[3],lsl#32
+	ldp	@x[1],@x[3],[$inp,#0]		// load input
+	add	@x[4],@x[4],@x[5],lsl#32
+	add	@x[6],@x[6],@x[7],lsl#32
+	ldp	@x[5],@x[7],[$inp,#16]
+	add	@x[8],@x[8],@x[9],lsl#32
+	add	@x[10],@x[10],@x[11],lsl#32
+	ldp	@x[9],@x[11],[$inp,#32]
+	add	@x[12],@x[12],@x[13],lsl#32
+	add	@x[14],@x[14],@x[15],lsl#32
+	ldp	@x[13],@x[15],[$inp,#48]
+	add	$inp,$inp,#64
+#ifdef	__ARMEB__
+	rev	@x[0],@x[0]
+	rev	@x[2],@x[2]
+	rev	@x[4],@x[4]
+	rev	@x[6],@x[6]
+	rev	@x[8],@x[8]
+	rev	@x[10],@x[10]
+	rev	@x[12],@x[12]
+	rev	@x[14],@x[14]
+#endif
+	eor	@x[0],@x[0],@x[1]
+	eor	@x[2],@x[2],@x[3]
+	eor	@x[4],@x[4],@x[5]
+	eor	@x[6],@x[6],@x[7]
+	eor	@x[8],@x[8],@x[9]
+	eor	@x[10],@x[10],@x[11]
+	eor	@x[12],@x[12],@x[13]
+	eor	@x[14],@x[14],@x[15]
+
+	stp	@x[0],@x[2],[$out,#0]		// store output
+	 add	@d[6],@d[6],#1			// increment counter
+	stp	@x[4],@x[6],[$out,#16]
+	stp	@x[8],@x[10],[$out,#32]
+	stp	@x[12],@x[14],[$out,#48]
+	add	$out,$out,#64
+
+	b.hi	.Loop_outer
+
+	ldp	x19,x20,[x29,#16]
+	add	sp,sp,#64
+	ldp	x21,x22,[x29,#32]
+	ldp	x23,x24,[x29,#48]
+	ldp	x25,x26,[x29,#64]
+	ldp	x27,x28,[x29,#80]
+	ldp	x29,x30,[sp],#96
+.Labort:
+	ret
+
+.align	4
+.Ltail:
+	add	$len,$len,#64
+.Less_than_64:
+	sub	$out,$out,#1
+	add	$inp,$inp,$len
+	add	$out,$out,$len
+	add	$ctr,sp,$len
+	neg	$len,$len
+
+	add	@x[0],@x[0],@x[1],lsl#32	// pack
+	add	@x[2],@x[2],@x[3],lsl#32
+	add	@x[4],@x[4],@x[5],lsl#32
+	add	@x[6],@x[6],@x[7],lsl#32
+	add	@x[8],@x[8],@x[9],lsl#32
+	add	@x[10],@x[10],@x[11],lsl#32
+	add	@x[12],@x[12],@x[13],lsl#32
+	add	@x[14],@x[14],@x[15],lsl#32
+#ifdef	__ARMEB__
+	rev	@x[0],@x[0]
+	rev	@x[2],@x[2]
+	rev	@x[4],@x[4]
+	rev	@x[6],@x[6]
+	rev	@x[8],@x[8]
+	rev	@x[10],@x[10]
+	rev	@x[12],@x[12]
+	rev	@x[14],@x[14]
+#endif
+	stp	@x[0],@x[2],[sp,#0]
+	stp	@x[4],@x[6],[sp,#16]
+	stp	@x[8],@x[10],[sp,#32]
+	stp	@x[12],@x[14],[sp,#48]
+
+.Loop_tail:
+	ldrb	w10,[$inp,$len]
+	ldrb	w11,[$ctr,$len]
+	add	$len,$len,#1
+	eor	w10,w10,w11
+	strb	w10,[$out,$len]
+	cbnz	$len,.Loop_tail
+
+	stp	xzr,xzr,[sp,#0]
+	stp	xzr,xzr,[sp,#16]
+	stp	xzr,xzr,[sp,#32]
+	stp	xzr,xzr,[sp,#48]
+
+	ldp	x19,x20,[x29,#16]
+	add	sp,sp,#64
+	ldp	x21,x22,[x29,#32]
+	ldp	x23,x24,[x29,#48]
+	ldp	x25,x26,[x29,#64]
+	ldp	x27,x28,[x29,#80]
+	ldp	x29,x30,[sp],#96
+	ret
+.size	ChaCha20_ctr32,.-ChaCha20_ctr32
+___
+
+{{{
+my ($A0,$B0,$C0,$D0,$A1,$B1,$C1,$D1,$A2,$B2,$C2,$D2,$T0,$T1,$T2,$T3) =
+    map("v$_.4s",(0..7,16..23));
+my (@K)=map("v$_.4s",(24..30));
+my $ONE="v31.4s";
+
+sub NEONROUND {
+my $odd = pop;
+my ($a,$b,$c,$d,$t)=@_;
+
+	(
+	"&add		('$a','$a','$b')",
+	"&eor		('$d','$d','$a')",
+	"&rev32_16	('$d','$d')",		# vrot ($d,16)
+
+	"&add		('$c','$c','$d')",
+	"&eor		('$t','$b','$c')",
+	"&ushr		('$b','$t',20)",
+	"&sli		('$b','$t',12)",
+
+	"&add		('$a','$a','$b')",
+	"&eor		('$t','$d','$a')",
+	"&ushr		('$d','$t',24)",
+	"&sli		('$d','$t',8)",
+
+	"&add		('$c','$c','$d')",
+	"&eor		('$t','$b','$c')",
+	"&ushr		('$b','$t',25)",
+	"&sli		('$b','$t',7)",
+
+	"&ext		('$c','$c','$c',8)",
+	"&ext		('$d','$d','$d',$odd?4:12)",
+	"&ext		('$b','$b','$b',$odd?12:4)"
+	);
+}
+
+$code.=<<___;
+
+.type	ChaCha20_neon,%function
+.align	5
+ChaCha20_neon:
+	stp	x29,x30,[sp,#-96]!
+	add	x29,sp,#0
+
+	adr	@x[0],.Lsigma
+	stp	x19,x20,[sp,#16]
+	stp	x21,x22,[sp,#32]
+	stp	x23,x24,[sp,#48]
+	stp	x25,x26,[sp,#64]
+	stp	x27,x28,[sp,#80]
+	cmp	$len,#512
+	b.hs	.L512_or_more_neon
+
+	sub	sp,sp,#64
+
+	ldp	@d[0],@d[1],[@x[0]]		// load sigma
+	ld1	{@K[0]},[@x[0]],#16
+	ldp	@d[2],@d[3],[$key]		// load key
+	ldp	@d[4],@d[5],[$key,#16]
+	ld1	{@K[1],@K[2]},[$key]
+	ldp	@d[6],@d[7],[$ctr]		// load counter
+	ld1	{@K[3]},[$ctr]
+	ld1	{$ONE},[@x[0]]
+#ifdef	__ARMEB__
+	rev64	@K[0],@K[0]
+	ror	@d[2],@d[2],#32
+	ror	@d[3],@d[3],#32
+	ror	@d[4],@d[4],#32
+	ror	@d[5],@d[5],#32
+	ror	@d[6],@d[6],#32
+	ror	@d[7],@d[7],#32
+#endif
+	add	@K[3],@K[3],$ONE		// += 1
+	add	@K[4],@K[3],$ONE
+	add	@K[5],@K[4],$ONE
+	shl	$ONE,$ONE,#2			// 1 -> 4
+
+.Loop_outer_neon:
+	mov.32	@x[0],@d[0]			// unpack key block
+	lsr	@x[1],@d[0],#32
+	 mov	$A0,@K[0]
+	mov.32	@x[2],@d[1]
+	lsr	@x[3],@d[1],#32
+	 mov	$A1,@K[0]
+	mov.32	@x[4],@d[2]
+	lsr	@x[5],@d[2],#32
+	 mov	$A2,@K[0]
+	mov.32	@x[6],@d[3]
+	 mov	$B0,@K[1]
+	lsr	@x[7],@d[3],#32
+	 mov	$B1,@K[1]
+	mov.32	@x[8],@d[4]
+	 mov	$B2,@K[1]
+	lsr	@x[9],@d[4],#32
+	 mov	$D0,@K[3]
+	mov.32	@x[10],@d[5]
+	 mov	$D1,@K[4]
+	lsr	@x[11],@d[5],#32
+	 mov	$D2,@K[5]
+	mov.32	@x[12],@d[6]
+	 mov	$C0,@K[2]
+	lsr	@x[13],@d[6],#32
+	 mov	$C1,@K[2]
+	mov.32	@x[14],@d[7]
+	 mov	$C2,@K[2]
+	lsr	@x[15],@d[7],#32
+
+	mov	$ctr,#10
+	subs	$len,$len,#256
+.Loop_neon:
+	sub	$ctr,$ctr,#1
+___
+	my @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,0);
+	my @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,0);
+	my @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,0);
+	my @thread3=&ROUND(0,4,8,12);
+
+	foreach (@thread0) {
+		eval;			eval(shift(@thread3));
+		eval(shift(@thread1));	eval(shift(@thread3));
+		eval(shift(@thread2));	eval(shift(@thread3));
+	}
+
+	@thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,1);
+	@thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,1);
+	@thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,1);
+	@thread3=&ROUND(0,5,10,15);
+
+	foreach (@thread0) {
+		eval;			eval(shift(@thread3));
+		eval(shift(@thread1));	eval(shift(@thread3));
+		eval(shift(@thread2));	eval(shift(@thread3));
+	}
+$code.=<<___;
+	cbnz	$ctr,.Loop_neon
+
+	add.32	@x[0],@x[0],@d[0]		// accumulate key block
+	 add	$A0,$A0,@K[0]
+	add	@x[1],@x[1],@d[0],lsr#32
+	 add	$A1,$A1,@K[0]
+	add.32	@x[2],@x[2],@d[1]
+	 add	$A2,$A2,@K[0]
+	add	@x[3],@x[3],@d[1],lsr#32
+	 add	$C0,$C0,@K[2]
+	add.32	@x[4],@x[4],@d[2]
+	 add	$C1,$C1,@K[2]
+	add	@x[5],@x[5],@d[2],lsr#32
+	 add	$C2,$C2,@K[2]
+	add.32	@x[6],@x[6],@d[3]
+	 add	$D0,$D0,@K[3]
+	add	@x[7],@x[7],@d[3],lsr#32
+	add.32	@x[8],@x[8],@d[4]
+	 add	$D1,$D1,@K[4]
+	add	@x[9],@x[9],@d[4],lsr#32
+	add.32	@x[10],@x[10],@d[5]
+	 add	$D2,$D2,@K[5]
+	add	@x[11],@x[11],@d[5],lsr#32
+	add.32	@x[12],@x[12],@d[6]
+	 add	$B0,$B0,@K[1]
+	add	@x[13],@x[13],@d[6],lsr#32
+	add.32	@x[14],@x[14],@d[7]
+	 add	$B1,$B1,@K[1]
+	add	@x[15],@x[15],@d[7],lsr#32
+	 add	$B2,$B2,@K[1]
+
+	b.lo	.Ltail_neon
+
+	add	@x[0],@x[0],@x[1],lsl#32	// pack
+	add	@x[2],@x[2],@x[3],lsl#32
+	ldp	@x[1],@x[3],[$inp,#0]		// load input
+	add	@x[4],@x[4],@x[5],lsl#32
+	add	@x[6],@x[6],@x[7],lsl#32
+	ldp	@x[5],@x[7],[$inp,#16]
+	add	@x[8],@x[8],@x[9],lsl#32
+	add	@x[10],@x[10],@x[11],lsl#32
+	ldp	@x[9],@x[11],[$inp,#32]
+	add	@x[12],@x[12],@x[13],lsl#32
+	add	@x[14],@x[14],@x[15],lsl#32
+	ldp	@x[13],@x[15],[$inp,#48]
+	add	$inp,$inp,#64
+#ifdef	__ARMEB__
+	rev	@x[0],@x[0]
+	rev	@x[2],@x[2]
+	rev	@x[4],@x[4]
+	rev	@x[6],@x[6]
+	rev	@x[8],@x[8]
+	rev	@x[10],@x[10]
+	rev	@x[12],@x[12]
+	rev	@x[14],@x[14]
+#endif
+	ld1.8	{$T0-$T3},[$inp],#64
+	eor	@x[0],@x[0],@x[1]
+	eor	@x[2],@x[2],@x[3]
+	eor	@x[4],@x[4],@x[5]
+	eor	@x[6],@x[6],@x[7]
+	eor	@x[8],@x[8],@x[9]
+	 eor	$A0,$A0,$T0
+	eor	@x[10],@x[10],@x[11]
+	 eor	$B0,$B0,$T1
+	eor	@x[12],@x[12],@x[13]
+	 eor	$C0,$C0,$T2
+	eor	@x[14],@x[14],@x[15]
+	 eor	$D0,$D0,$T3
+	 ld1.8	{$T0-$T3},[$inp],#64
+
+	stp	@x[0],@x[2],[$out,#0]		// store output
+	 add	@d[6],@d[6],#4			// increment counter
+	stp	@x[4],@x[6],[$out,#16]
+	 add	@K[3],@K[3],$ONE		// += 4
+	stp	@x[8],@x[10],[$out,#32]
+	 add	@K[4],@K[4],$ONE
+	stp	@x[12],@x[14],[$out,#48]
+	 add	@K[5],@K[5],$ONE
+	add	$out,$out,#64
+
+	st1.8	{$A0-$D0},[$out],#64
+	ld1.8	{$A0-$D0},[$inp],#64
+
+	eor	$A1,$A1,$T0
+	eor	$B1,$B1,$T1
+	eor	$C1,$C1,$T2
+	eor	$D1,$D1,$T3
+	st1.8	{$A1-$D1},[$out],#64
+
+	eor	$A2,$A2,$A0
+	eor	$B2,$B2,$B0
+	eor	$C2,$C2,$C0
+	eor	$D2,$D2,$D0
+	st1.8	{$A2-$D2},[$out],#64
+
+	b.hi	.Loop_outer_neon
+
+	ldp	x19,x20,[x29,#16]
+	add	sp,sp,#64
+	ldp	x21,x22,[x29,#32]
+	ldp	x23,x24,[x29,#48]
+	ldp	x25,x26,[x29,#64]
+	ldp	x27,x28,[x29,#80]
+	ldp	x29,x30,[sp],#96
+	ret
+
+.Ltail_neon:
+	add	$len,$len,#256
+	cmp	$len,#64
+	b.lo	.Less_than_64
+
+	add	@x[0],@x[0],@x[1],lsl#32	// pack
+	add	@x[2],@x[2],@x[3],lsl#32
+	ldp	@x[1],@x[3],[$inp,#0]		// load input
+	add	@x[4],@x[4],@x[5],lsl#32
+	add	@x[6],@x[6],@x[7],lsl#32
+	ldp	@x[5],@x[7],[$inp,#16]
+	add	@x[8],@x[8],@x[9],lsl#32
+	add	@x[10],@x[10],@x[11],lsl#32
+	ldp	@x[9],@x[11],[$inp,#32]
+	add	@x[12],@x[12],@x[13],lsl#32
+	add	@x[14],@x[14],@x[15],lsl#32
+	ldp	@x[13],@x[15],[$inp,#48]
+	add	$inp,$inp,#64
+#ifdef	__ARMEB__
+	rev	@x[0],@x[0]
+	rev	@x[2],@x[2]
+	rev	@x[4],@x[4]
+	rev	@x[6],@x[6]
+	rev	@x[8],@x[8]
+	rev	@x[10],@x[10]
+	rev	@x[12],@x[12]
+	rev	@x[14],@x[14]
+#endif
+	eor	@x[0],@x[0],@x[1]
+	eor	@x[2],@x[2],@x[3]
+	eor	@x[4],@x[4],@x[5]
+	eor	@x[6],@x[6],@x[7]
+	eor	@x[8],@x[8],@x[9]
+	eor	@x[10],@x[10],@x[11]
+	eor	@x[12],@x[12],@x[13]
+	eor	@x[14],@x[14],@x[15]
+
+	stp	@x[0],@x[2],[$out,#0]		// store output
+	 add	@d[6],@d[6],#4			// increment counter
+	stp	@x[4],@x[6],[$out,#16]
+	stp	@x[8],@x[10],[$out,#32]
+	stp	@x[12],@x[14],[$out,#48]
+	add	$out,$out,#64
+	b.eq	.Ldone_neon
+	sub	$len,$len,#64
+	cmp	$len,#64
+	b.lo	.Less_than_128
+
+	ld1.8	{$T0-$T3},[$inp],#64
+	eor	$A0,$A0,$T0
+	eor	$B0,$B0,$T1
+	eor	$C0,$C0,$T2
+	eor	$D0,$D0,$T3
+	st1.8	{$A0-$D0},[$out],#64
+	b.eq	.Ldone_neon
+	sub	$len,$len,#64
+	cmp	$len,#64
+	b.lo	.Less_than_192
+
+	ld1.8	{$T0-$T3},[$inp],#64
+	eor	$A1,$A1,$T0
+	eor	$B1,$B1,$T1
+	eor	$C1,$C1,$T2
+	eor	$D1,$D1,$T3
+	st1.8	{$A1-$D1},[$out],#64
+	b.eq	.Ldone_neon
+	sub	$len,$len,#64
+
+	st1.8	{$A2-$D2},[sp]
+	b	.Last_neon
+
+.Less_than_128:
+	st1.8	{$A0-$D0},[sp]
+	b	.Last_neon
+.Less_than_192:
+	st1.8	{$A1-$D1},[sp]
+	b	.Last_neon
+
+.align	4
+.Last_neon:
+	sub	$out,$out,#1
+	add	$inp,$inp,$len
+	add	$out,$out,$len
+	add	$ctr,sp,$len
+	neg	$len,$len
+
+.Loop_tail_neon:
+	ldrb	w10,[$inp,$len]
+	ldrb	w11,[$ctr,$len]
+	add	$len,$len,#1
+	eor	w10,w10,w11
+	strb	w10,[$out,$len]
+	cbnz	$len,.Loop_tail_neon
+
+	stp	xzr,xzr,[sp,#0]
+	stp	xzr,xzr,[sp,#16]
+	stp	xzr,xzr,[sp,#32]
+	stp	xzr,xzr,[sp,#48]
+
+.Ldone_neon:
+	ldp	x19,x20,[x29,#16]
+	add	sp,sp,#64
+	ldp	x21,x22,[x29,#32]
+	ldp	x23,x24,[x29,#48]
+	ldp	x25,x26,[x29,#64]
+	ldp	x27,x28,[x29,#80]
+	ldp	x29,x30,[sp],#96
+	ret
+.size	ChaCha20_neon,.-ChaCha20_neon
+___
+{
+my ($T0,$T1,$T2,$T3,$T4,$T5)=@K;
+my ($A0,$B0,$C0,$D0,$A1,$B1,$C1,$D1,$A2,$B2,$C2,$D2,
+    $A3,$B3,$C3,$D3,$A4,$B4,$C4,$D4,$A5,$B5,$C5,$D5) = map("v$_.4s",(0..23));
+
+$code.=<<___;
+.type	ChaCha20_512_neon,%function
+.align	5
+ChaCha20_512_neon:
+	stp	x29,x30,[sp,#-96]!
+	add	x29,sp,#0
+
+	adr	@x[0],.Lsigma
+	stp	x19,x20,[sp,#16]
+	stp	x21,x22,[sp,#32]
+	stp	x23,x24,[sp,#48]
+	stp	x25,x26,[sp,#64]
+	stp	x27,x28,[sp,#80]
+
+.L512_or_more_neon:
+	sub	sp,sp,#128+64
+
+	ldp	@d[0],@d[1],[@x[0]]		// load sigma
+	ld1	{@K[0]},[@x[0]],#16
+	ldp	@d[2],@d[3],[$key]		// load key
+	ldp	@d[4],@d[5],[$key,#16]
+	ld1	{@K[1],@K[2]},[$key]
+	ldp	@d[6],@d[7],[$ctr]		// load counter
+	ld1	{@K[3]},[$ctr]
+	ld1	{$ONE},[@x[0]]
+#ifdef	__ARMEB__
+	rev64	@K[0],@K[0]
+	ror	@d[2],@d[2],#32
+	ror	@d[3],@d[3],#32
+	ror	@d[4],@d[4],#32
+	ror	@d[5],@d[5],#32
+	ror	@d[6],@d[6],#32
+	ror	@d[7],@d[7],#32
+#endif
+	add	@K[3],@K[3],$ONE		// += 1
+	stp	@K[0],@K[1],[sp,#0]		// off-load key block, invariant part
+	add	@K[3],@K[3],$ONE		// not typo
+	str	@K[2],[sp,#32]
+	add	@K[4],@K[3],$ONE
+	add	@K[5],@K[4],$ONE
+	add	@K[6],@K[5],$ONE
+	shl	$ONE,$ONE,#2			// 1 -> 4
+
+	stp	d8,d9,[sp,#128+0]		// meet ABI requirements
+	stp	d10,d11,[sp,#128+16]
+	stp	d12,d13,[sp,#128+32]
+	stp	d14,d15,[sp,#128+48]
+
+	sub	$len,$len,#512			// not typo
+
+.Loop_outer_512_neon:
+	 mov	$A0,@K[0]
+	 mov	$A1,@K[0]
+	 mov	$A2,@K[0]
+	 mov	$A3,@K[0]
+	 mov	$A4,@K[0]
+	 mov	$A5,@K[0]
+	 mov	$B0,@K[1]
+	mov.32	@x[0],@d[0]			// unpack key block
+	 mov	$B1,@K[1]
+	lsr	@x[1],@d[0],#32
+	 mov	$B2,@K[1]
+	mov.32	@x[2],@d[1]
+	 mov	$B3,@K[1]
+	lsr	@x[3],@d[1],#32
+	 mov	$B4,@K[1]
+	mov.32	@x[4],@d[2]
+	 mov	$B5,@K[1]
+	lsr	@x[5],@d[2],#32
+	 mov	$D0,@K[3]
+	mov.32	@x[6],@d[3]
+	 mov	$D1,@K[4]
+	lsr	@x[7],@d[3],#32
+	 mov	$D2,@K[5]
+	mov.32	@x[8],@d[4]
+	 mov	$D3,@K[6]
+	lsr	@x[9],@d[4],#32
+	 mov	$C0,@K[2]
+	mov.32	@x[10],@d[5]
+	 mov	$C1,@K[2]
+	lsr	@x[11],@d[5],#32
+	 add	$D4,$D0,$ONE			// +4
+	mov.32	@x[12],@d[6]
+	 add	$D5,$D1,$ONE			// +4
+	lsr	@x[13],@d[6],#32
+	 mov	$C2,@K[2]
+	mov.32	@x[14],@d[7]
+	 mov	$C3,@K[2]
+	lsr	@x[15],@d[7],#32
+	 mov	$C4,@K[2]
+	 stp	@K[3],@K[4],[sp,#48]		// off-load key block, variable part
+	 mov	$C5,@K[2]
+	 str	@K[5],[sp,#80]
+
+	mov	$ctr,#5
+	subs	$len,$len,#512
+.Loop_upper_neon:
+	sub	$ctr,$ctr,#1
+___
+	my @thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,0);
+	my @thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,0);
+	my @thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,0);
+	my @thread3=&NEONROUND($A3,$B3,$C3,$D3,$T3,0);
+	my @thread4=&NEONROUND($A4,$B4,$C4,$D4,$T4,0);
+	my @thread5=&NEONROUND($A5,$B5,$C5,$D5,$T5,0);
+	my @thread67=(&ROUND(0,4,8,12),&ROUND(0,5,10,15));
+	my $diff = ($#thread0+1)*6 - $#thread67 - 1;
+	my $i = 0;
+
+	foreach (@thread0) {
+		eval;			eval(shift(@thread67));
+		eval(shift(@thread1));	eval(shift(@thread67));
+		eval(shift(@thread2));	eval(shift(@thread67));
+		eval(shift(@thread3));	eval(shift(@thread67));
+		eval(shift(@thread4));	eval(shift(@thread67));
+		eval(shift(@thread5));	eval(shift(@thread67));
+	}
+
+	@thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,1);
+	@thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,1);
+	@thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,1);
+	@thread3=&NEONROUND($A3,$B3,$C3,$D3,$T3,1);
+	@thread4=&NEONROUND($A4,$B4,$C4,$D4,$T4,1);
+	@thread5=&NEONROUND($A5,$B5,$C5,$D5,$T5,1);
+	@thread67=(&ROUND(0,4,8,12),&ROUND(0,5,10,15));
+
+	foreach (@thread0) {
+		eval;			eval(shift(@thread67));
+		eval(shift(@thread1));	eval(shift(@thread67));
+		eval(shift(@thread2));	eval(shift(@thread67));
+		eval(shift(@thread3));	eval(shift(@thread67));
+		eval(shift(@thread4));	eval(shift(@thread67));
+		eval(shift(@thread5));	eval(shift(@thread67));
+	}
+$code.=<<___;
+	cbnz	$ctr,.Loop_upper_neon
+
+	add.32	@x[0],@x[0],@d[0]		// accumulate key block
+	add	@x[1],@x[1],@d[0],lsr#32
+	add.32	@x[2],@x[2],@d[1]
+	add	@x[3],@x[3],@d[1],lsr#32
+	add.32	@x[4],@x[4],@d[2]
+	add	@x[5],@x[5],@d[2],lsr#32
+	add.32	@x[6],@x[6],@d[3]
+	add	@x[7],@x[7],@d[3],lsr#32
+	add.32	@x[8],@x[8],@d[4]
+	add	@x[9],@x[9],@d[4],lsr#32
+	add.32	@x[10],@x[10],@d[5]
+	add	@x[11],@x[11],@d[5],lsr#32
+	add.32	@x[12],@x[12],@d[6]
+	add	@x[13],@x[13],@d[6],lsr#32
+	add.32	@x[14],@x[14],@d[7]
+	add	@x[15],@x[15],@d[7],lsr#32
+
+	add	@x[0],@x[0],@x[1],lsl#32	// pack
+	add	@x[2],@x[2],@x[3],lsl#32
+	ldp	@x[1],@x[3],[$inp,#0]		// load input
+	add	@x[4],@x[4],@x[5],lsl#32
+	add	@x[6],@x[6],@x[7],lsl#32
+	ldp	@x[5],@x[7],[$inp,#16]
+	add	@x[8],@x[8],@x[9],lsl#32
+	add	@x[10],@x[10],@x[11],lsl#32
+	ldp	@x[9],@x[11],[$inp,#32]
+	add	@x[12],@x[12],@x[13],lsl#32
+	add	@x[14],@x[14],@x[15],lsl#32
+	ldp	@x[13],@x[15],[$inp,#48]
+	add	$inp,$inp,#64
+#ifdef	__ARMEB__
+	rev	@x[0],@x[0]
+	rev	@x[2],@x[2]
+	rev	@x[4],@x[4]
+	rev	@x[6],@x[6]
+	rev	@x[8],@x[8]
+	rev	@x[10],@x[10]
+	rev	@x[12],@x[12]
+	rev	@x[14],@x[14]
+#endif
+	eor	@x[0],@x[0],@x[1]
+	eor	@x[2],@x[2],@x[3]
+	eor	@x[4],@x[4],@x[5]
+	eor	@x[6],@x[6],@x[7]
+	eor	@x[8],@x[8],@x[9]
+	eor	@x[10],@x[10],@x[11]
+	eor	@x[12],@x[12],@x[13]
+	eor	@x[14],@x[14],@x[15]
+
+	 stp	@x[0],@x[2],[$out,#0]		// store output
+	 add	@d[6],@d[6],#1			// increment counter
+	mov.32	@x[0],@d[0]			// unpack key block
+	lsr	@x[1],@d[0],#32
+	 stp	@x[4],@x[6],[$out,#16]
+	mov.32	@x[2],@d[1]
+	lsr	@x[3],@d[1],#32
+	 stp	@x[8],@x[10],[$out,#32]
+	mov.32	@x[4],@d[2]
+	lsr	@x[5],@d[2],#32
+	 stp	@x[12],@x[14],[$out,#48]
+	 add	$out,$out,#64
+	mov.32	@x[6],@d[3]
+	lsr	@x[7],@d[3],#32
+	mov.32	@x[8],@d[4]
+	lsr	@x[9],@d[4],#32
+	mov.32	@x[10],@d[5]
+	lsr	@x[11],@d[5],#32
+	mov.32	@x[12],@d[6]
+	lsr	@x[13],@d[6],#32
+	mov.32	@x[14],@d[7]
+	lsr	@x[15],@d[7],#32
+
+	mov	$ctr,#5
+.Loop_lower_neon:
+	sub	$ctr,$ctr,#1
+___
+	@thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,0);
+	@thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,0);
+	@thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,0);
+	@thread3=&NEONROUND($A3,$B3,$C3,$D3,$T3,0);
+	@thread4=&NEONROUND($A4,$B4,$C4,$D4,$T4,0);
+	@thread5=&NEONROUND($A5,$B5,$C5,$D5,$T5,0);
+	@thread67=(&ROUND(0,4,8,12),&ROUND(0,5,10,15));
+
+	foreach (@thread0) {
+		eval;			eval(shift(@thread67));
+		eval(shift(@thread1));	eval(shift(@thread67));
+		eval(shift(@thread2));	eval(shift(@thread67));
+		eval(shift(@thread3));	eval(shift(@thread67));
+		eval(shift(@thread4));	eval(shift(@thread67));
+		eval(shift(@thread5));	eval(shift(@thread67));
+	}
+
+	@thread0=&NEONROUND($A0,$B0,$C0,$D0,$T0,1);
+	@thread1=&NEONROUND($A1,$B1,$C1,$D1,$T1,1);
+	@thread2=&NEONROUND($A2,$B2,$C2,$D2,$T2,1);
+	@thread3=&NEONROUND($A3,$B3,$C3,$D3,$T3,1);
+	@thread4=&NEONROUND($A4,$B4,$C4,$D4,$T4,1);
+	@thread5=&NEONROUND($A5,$B5,$C5,$D5,$T5,1);
+	@thread67=(&ROUND(0,4,8,12),&ROUND(0,5,10,15));
+
+	foreach (@thread0) {
+		eval;			eval(shift(@thread67));
+		eval(shift(@thread1));	eval(shift(@thread67));
+		eval(shift(@thread2));	eval(shift(@thread67));
+		eval(shift(@thread3));	eval(shift(@thread67));
+		eval(shift(@thread4));	eval(shift(@thread67));
+		eval(shift(@thread5));	eval(shift(@thread67));
+	}
+$code.=<<___;
+	cbnz	$ctr,.Loop_lower_neon
+
+	add.32	@x[0],@x[0],@d[0]		// accumulate key block
+	 ldp	@K[0],@K[1],[sp,#0]
+	add	@x[1],@x[1],@d[0],lsr#32
+	 ldp	@K[2],@K[3],[sp,#32]
+	add.32	@x[2],@x[2],@d[1]
+	 ldp	@K[4],@K[5],[sp,#64]
+	add	@x[3],@x[3],@d[1],lsr#32
+	 add	$A0,$A0,@K[0]
+	add.32	@x[4],@x[4],@d[2]
+	 add	$A1,$A1,@K[0]
+	add	@x[5],@x[5],@d[2],lsr#32
+	 add	$A2,$A2,@K[0]
+	add.32	@x[6],@x[6],@d[3]
+	 add	$A3,$A3,@K[0]
+	add	@x[7],@x[7],@d[3],lsr#32
+	 add	$A4,$A4,@K[0]
+	add.32	@x[8],@x[8],@d[4]
+	 add	$A5,$A5,@K[0]
+	add	@x[9],@x[9],@d[4],lsr#32
+	 add	$C0,$C0,@K[2]
+	add.32	@x[10],@x[10],@d[5]
+	 add	$C1,$C1,@K[2]
+	add	@x[11],@x[11],@d[5],lsr#32
+	 add	$C2,$C2,@K[2]
+	add.32	@x[12],@x[12],@d[6]
+	 add	$C3,$C3,@K[2]
+	add	@x[13],@x[13],@d[6],lsr#32
+	 add	$C4,$C4,@K[2]
+	add.32	@x[14],@x[14],@d[7]
+	 add	$C5,$C5,@K[2]
+	add	@x[15],@x[15],@d[7],lsr#32
+	 add	$D4,$D4,$ONE			// +4
+	add	@x[0],@x[0],@x[1],lsl#32	// pack
+	 add	$D5,$D5,$ONE			// +4
+	add	@x[2],@x[2],@x[3],lsl#32
+	 add	$D0,$D0,@K[3]
+	ldp	@x[1],@x[3],[$inp,#0]		// load input
+	 add	$D1,$D1,@K[4]
+	add	@x[4],@x[4],@x[5],lsl#32
+	 add	$D2,$D2,@K[5]
+	add	@x[6],@x[6],@x[7],lsl#32
+	 add	$D3,$D3,@K[6]
+	ldp	@x[5],@x[7],[$inp,#16]
+	 add	$D4,$D4,@K[3]
+	add	@x[8],@x[8],@x[9],lsl#32
+	 add	$D5,$D5,@K[4]
+	add	@x[10],@x[10],@x[11],lsl#32
+	 add	$B0,$B0,@K[1]
+	ldp	@x[9],@x[11],[$inp,#32]
+	 add	$B1,$B1,@K[1]
+	add	@x[12],@x[12],@x[13],lsl#32
+	 add	$B2,$B2,@K[1]
+	add	@x[14],@x[14],@x[15],lsl#32
+	 add	$B3,$B3,@K[1]
+	ldp	@x[13],@x[15],[$inp,#48]
+	 add	$B4,$B4,@K[1]
+	add	$inp,$inp,#64
+	 add	$B5,$B5,@K[1]
+
+#ifdef	__ARMEB__
+	rev	@x[0],@x[0]
+	rev	@x[2],@x[2]
+	rev	@x[4],@x[4]
+	rev	@x[6],@x[6]
+	rev	@x[8],@x[8]
+	rev	@x[10],@x[10]
+	rev	@x[12],@x[12]
+	rev	@x[14],@x[14]
+#endif
+	ld1.8	{$T0-$T3},[$inp],#64
+	eor	@x[0],@x[0],@x[1]
+	eor	@x[2],@x[2],@x[3]
+	eor	@x[4],@x[4],@x[5]
+	eor	@x[6],@x[6],@x[7]
+	eor	@x[8],@x[8],@x[9]
+	 eor	$A0,$A0,$T0
+	eor	@x[10],@x[10],@x[11]
+	 eor	$B0,$B0,$T1
+	eor	@x[12],@x[12],@x[13]
+	 eor	$C0,$C0,$T2
+	eor	@x[14],@x[14],@x[15]
+	 eor	$D0,$D0,$T3
+	 ld1.8	{$T0-$T3},[$inp],#64
+
+	stp	@x[0],@x[2],[$out,#0]		// store output
+	 add	@d[6],@d[6],#7			// increment counter
+	stp	@x[4],@x[6],[$out,#16]
+	stp	@x[8],@x[10],[$out,#32]
+	stp	@x[12],@x[14],[$out,#48]
+	add	$out,$out,#64
+	st1.8	{$A0-$D0},[$out],#64
+
+	ld1.8	{$A0-$D0},[$inp],#64
+	eor	$A1,$A1,$T0
+	eor	$B1,$B1,$T1
+	eor	$C1,$C1,$T2
+	eor	$D1,$D1,$T3
+	st1.8	{$A1-$D1},[$out],#64
+
+	ld1.8	{$A1-$D1},[$inp],#64
+	eor	$A2,$A2,$A0
+	 ldp	@K[0],@K[1],[sp,#0]
+	eor	$B2,$B2,$B0
+	 ldp	@K[2],@K[3],[sp,#32]
+	eor	$C2,$C2,$C0
+	eor	$D2,$D2,$D0
+	st1.8	{$A2-$D2},[$out],#64
+
+	ld1.8	{$A2-$D2},[$inp],#64
+	eor	$A3,$A3,$A1
+	eor	$B3,$B3,$B1
+	eor	$C3,$C3,$C1
+	eor	$D3,$D3,$D1
+	st1.8	{$A3-$D3},[$out],#64
+
+	ld1.8	{$A3-$D3},[$inp],#64
+	eor	$A4,$A4,$A2
+	eor	$B4,$B4,$B2
+	eor	$C4,$C4,$C2
+	eor	$D4,$D4,$D2
+	st1.8	{$A4-$D4},[$out],#64
+
+	shl	$A0,$ONE,#1			// 4 -> 8
+	eor	$A5,$A5,$A3
+	eor	$B5,$B5,$B3
+	eor	$C5,$C5,$C3
+	eor	$D5,$D5,$D3
+	st1.8	{$A5-$D5},[$out],#64
+
+	add	@K[3],@K[3],$A0			// += 8
+	add	@K[4],@K[4],$A0
+	add	@K[5],@K[5],$A0
+	add	@K[6],@K[6],$A0
+
+	b.hs	.Loop_outer_512_neon
+
+	adds	$len,$len,#512
+	ushr	$A0,$ONE,#2			// 4 -> 1
+
+	ldp	d8,d9,[sp,#128+0]		// meet ABI requirements
+	ldp	d10,d11,[sp,#128+16]
+	ldp	d12,d13,[sp,#128+32]
+	ldp	d14,d15,[sp,#128+48]
+
+	stp	@K[0],$ONE,[sp,#0]		// wipe off-load area
+	stp	@K[0],$ONE,[sp,#32]
+	stp	@K[0],$ONE,[sp,#64]
+
+	b.eq	.Ldone_512_neon
+
+	cmp	$len,#192
+	sub	@K[3],@K[3],$A0			// -= 1
+	sub	@K[4],@K[4],$A0
+	sub	@K[5],@K[5],$A0
+	add	sp,sp,#128
+	b.hs	.Loop_outer_neon
+
+	eor	@K[1],@K[1],@K[1]
+	eor	@K[2],@K[2],@K[2]
+	eor	@K[3],@K[3],@K[3]
+	eor	@K[4],@K[4],@K[4]
+	eor	@K[5],@K[5],@K[5]
+	eor	@K[6],@K[6],@K[6]
+	b	.Loop_outer
+
+.Ldone_512_neon:
+	ldp	x19,x20,[x29,#16]
+	add	sp,sp,#128+64
+	ldp	x21,x22,[x29,#32]
+	ldp	x23,x24,[x29,#48]
+	ldp	x25,x26,[x29,#64]
+	ldp	x27,x28,[x29,#80]
+	ldp	x29,x30,[sp],#96
+	ret
+.size	ChaCha20_512_neon,.-ChaCha20_512_neon
+___
+}
+}}}
+
+foreach (split("\n",$code)) {
+	s/\`([^\`]*)\`/eval $1/geo;
+
+	(s/\b([a-z]+)\.32\b/$1/ and (s/x([0-9]+)/w$1/g or 1))	or
+	(m/\b(eor|ext|mov)\b/ and (s/\.4s/\.16b/g or 1))	or
+	(s/\b((?:ld|st)1)\.8\b/$1/ and (s/\.4s/\.16b/g or 1))	or
+	(m/\b(ld|st)[rp]\b/ and (s/v([0-9]+)\.4s/q$1/g or 1))	or
+	(s/\brev32\.16\b/rev32/ and (s/\.4s/\.8h/g or 1));
+
+	#s/\bq([0-9]+)#(lo|hi)/sprintf "d%d",2*$1+($2 eq "hi")/geo;
+
+	print $_,"\n";
+}
+close STDOUT;	# flush
diff --git a/src/crypto/chacha/asm/chacha-x86.pl b/src/crypto/chacha/asm/chacha-x86.pl
new file mode 100755
index 0000000..f8bbb76
--- /dev/null
+++ b/src/crypto/chacha/asm/chacha-x86.pl
@@ -0,0 +1,765 @@
+#!/usr/bin/env perl
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# January 2015
+#
+# ChaCha20 for x86.
+#
+# Performance in cycles per byte out of large buffer.
+#
+#		1xIALU/gcc	4xSSSE3
+# Pentium	17.5/+80%
+# PIII		14.2/+60%
+# P4		18.6/+84%
+# Core2		9.56/+89%	4.83
+# Westmere	9.50/+45%	3.35
+# Sandy Bridge	10.5/+47%	3.20
+# Haswell	8.15/+50%	2.83
+# Skylake	7.53/+22%	2.75
+# Silvermont	17.4/+36%	8.35
+# Goldmont	13.4/+40%	4.36
+# Sledgehammer	10.2/+54%
+# Bulldozer	13.4/+50%	4.38(*)
+#
+# (*)	Bulldozer actually executes 4xXOP code path that delivers 3.55;
+#
+# Modified from upstream OpenSSL to remove the XOP code.
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+push(@INC,"${dir}","${dir}../../perlasm");
+require "x86asm.pl";
+
+$output=pop;
+open STDOUT,">$output";
+
+&asm_init($ARGV[0],"chacha-x86.pl",$ARGV[$#ARGV] eq "386");
+
+$xmm=$ymm=1;
+$gasver=999;  # enable everything
+
+$a="eax";
+($b,$b_)=("ebx","ebp");
+($c,$c_)=("ecx","esi");
+($d,$d_)=("edx","edi");
+
+sub QUARTERROUND {
+my ($ai,$bi,$ci,$di,$i)=@_;
+my ($an,$bn,$cn,$dn)=map(($_&~3)+(($_+1)&3),($ai,$bi,$ci,$di));	# next
+my ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_-1)&3),($ai,$bi,$ci,$di));	# previous
+
+	#       a   b   c   d
+	#
+	#       0   4   8  12 < even round
+	#       1   5   9  13
+	#       2   6  10  14
+	#       3   7  11  15
+	#       0   5  10  15 < odd round
+	#       1   6  11  12
+	#       2   7   8  13
+	#       3   4   9  14
+
+	if ($i==0) {
+            my $j=4;
+	    ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_-$j--)&3),($ap,$bp,$cp,$dp));
+	} elsif ($i==3) {
+            my $j=0;
+	    ($an,$bn,$cn,$dn)=map(($_&~3)+(($_+$j++)&3),($an,$bn,$cn,$dn));
+	} elsif ($i==4) {
+            my $j=4;
+	    ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_+$j--)&3),($ap,$bp,$cp,$dp));
+	} elsif ($i==7) {
+            my $j=0;
+	    ($an,$bn,$cn,$dn)=map(($_&~3)+(($_-$j++)&3),($an,$bn,$cn,$dn));
+	}
+
+	#&add	($a,$b);			# see elsewhere
+	&xor	($d,$a);
+	 &mov	(&DWP(4*$cp,"esp"),$c_)		if ($ai>0 && $ai<3);
+	&rol	($d,16);
+	 &mov	(&DWP(4*$bp,"esp"),$b_)		if ($i!=0);
+	&add	($c,$d);
+	 &mov	($c_,&DWP(4*$cn,"esp"))		if ($ai>0 && $ai<3);
+	&xor	($b,$c);
+	 &mov	($d_,&DWP(4*$dn,"esp"))		if ($di!=$dn);
+	&rol	($b,12);
+	 &mov	($b_,&DWP(4*$bn,"esp"))		if ($i<7);
+	 &mov	($b_,&DWP(128,"esp"))		if ($i==7);	# loop counter
+	&add	($a,$b);
+	&xor	($d,$a);
+	&mov	(&DWP(4*$ai,"esp"),$a);
+	&rol	($d,8);
+	&mov	($a,&DWP(4*$an,"esp"));
+	&add	($c,$d);
+	&mov	(&DWP(4*$di,"esp"),$d)		if ($di!=$dn);
+	&mov	($d_,$d)			if ($di==$dn);
+	&xor	($b,$c);
+	 &add	($a,$b_)			if ($i<7);	# elsewhere
+	&rol	($b,7);
+
+	($b,$b_)=($b_,$b);
+	($c,$c_)=($c_,$c);
+	($d,$d_)=($d_,$d);
+}
+
+&static_label("ssse3_shortcut");
+&static_label("ssse3_data");
+&static_label("pic_point");
+
+&function_begin("ChaCha20_ctr32");
+	&xor	("eax","eax");
+	&cmp	("eax",&wparam(2));		# len==0?
+	&je	(&label("no_data"));
+if ($xmm) {
+	&call	(&label("pic_point"));
+&set_label("pic_point");
+	&blindpop("eax");
+	&picmeup("ebp","OPENSSL_ia32cap_P","eax",&label("pic_point"));
+	&test	(&DWP(0,"ebp"),1<<24);		# test FXSR bit
+	&jz	(&label("x86"));
+	&test	(&DWP(4,"ebp"),1<<9);		# test SSSE3 bit
+	&jz	(&label("x86"));
+	&jmp	(&label("ssse3_shortcut"));
+&set_label("x86");
+}
+	&mov	("esi",&wparam(3));		# key
+	&mov	("edi",&wparam(4));		# counter and nonce
+
+	&stack_push(33);
+
+	&mov	("eax",&DWP(4*0,"esi"));	# copy key
+	&mov	("ebx",&DWP(4*1,"esi"));
+	&mov	("ecx",&DWP(4*2,"esi"));
+	&mov	("edx",&DWP(4*3,"esi"));
+	&mov	(&DWP(64+4*4,"esp"),"eax");
+	&mov	(&DWP(64+4*5,"esp"),"ebx");
+	&mov	(&DWP(64+4*6,"esp"),"ecx");
+	&mov	(&DWP(64+4*7,"esp"),"edx");
+	&mov	("eax",&DWP(4*4,"esi"));
+	&mov	("ebx",&DWP(4*5,"esi"));
+	&mov	("ecx",&DWP(4*6,"esi"));
+	&mov	("edx",&DWP(4*7,"esi"));
+	&mov	(&DWP(64+4*8,"esp"),"eax");
+	&mov	(&DWP(64+4*9,"esp"),"ebx");
+	&mov	(&DWP(64+4*10,"esp"),"ecx");
+	&mov	(&DWP(64+4*11,"esp"),"edx");
+	&mov	("eax",&DWP(4*0,"edi"));	# copy counter and nonce
+	&mov	("ebx",&DWP(4*1,"edi"));
+	&mov	("ecx",&DWP(4*2,"edi"));
+	&mov	("edx",&DWP(4*3,"edi"));
+	&sub	("eax",1);
+	&mov	(&DWP(64+4*12,"esp"),"eax");
+	&mov	(&DWP(64+4*13,"esp"),"ebx");
+	&mov	(&DWP(64+4*14,"esp"),"ecx");
+	&mov	(&DWP(64+4*15,"esp"),"edx");
+	&jmp	(&label("entry"));
+
+&set_label("outer_loop",16);
+	&mov	(&wparam(1),$b);		# save input
+	&mov	(&wparam(0),$a);		# save output
+	&mov	(&wparam(2),$c);		# save len
+&set_label("entry");
+	&mov	($a,0x61707865);
+	&mov	(&DWP(4*1,"esp"),0x3320646e);
+	&mov	(&DWP(4*2,"esp"),0x79622d32);
+	&mov	(&DWP(4*3,"esp"),0x6b206574);
+
+	&mov	($b, &DWP(64+4*5,"esp"));	# copy key material
+	&mov	($b_,&DWP(64+4*6,"esp"));
+	&mov	($c, &DWP(64+4*10,"esp"));
+	&mov	($c_,&DWP(64+4*11,"esp"));
+	&mov	($d, &DWP(64+4*13,"esp"));
+	&mov	($d_,&DWP(64+4*14,"esp"));
+	&mov	(&DWP(4*5,"esp"),$b);
+	&mov	(&DWP(4*6,"esp"),$b_);
+	&mov	(&DWP(4*10,"esp"),$c);
+	&mov	(&DWP(4*11,"esp"),$c_);
+	&mov	(&DWP(4*13,"esp"),$d);
+	&mov	(&DWP(4*14,"esp"),$d_);
+
+	&mov	($b, &DWP(64+4*7,"esp"));
+	&mov	($d_,&DWP(64+4*15,"esp"));
+	&mov	($d, &DWP(64+4*12,"esp"));
+	&mov	($b_,&DWP(64+4*4,"esp"));
+	&mov	($c, &DWP(64+4*8,"esp"));
+	&mov	($c_,&DWP(64+4*9,"esp"));
+	&add	($d,1);				# counter value
+	&mov	(&DWP(4*7,"esp"),$b);
+	&mov	(&DWP(4*15,"esp"),$d_);
+	&mov	(&DWP(64+4*12,"esp"),$d);	# save counter value
+
+	&mov	($b,10);			# loop counter
+	&jmp	(&label("loop"));
+
+&set_label("loop",16);
+	&add	($a,$b_);			# elsewhere
+	&mov	(&DWP(128,"esp"),$b);		# save loop counter
+	&mov	($b,$b_);
+	&QUARTERROUND(0, 4, 8, 12, 0);
+	&QUARTERROUND(1, 5, 9, 13, 1);
+	&QUARTERROUND(2, 6,10, 14, 2);
+	&QUARTERROUND(3, 7,11, 15, 3);
+	&QUARTERROUND(0, 5,10, 15, 4);
+	&QUARTERROUND(1, 6,11, 12, 5);
+	&QUARTERROUND(2, 7, 8, 13, 6);
+	&QUARTERROUND(3, 4, 9, 14, 7);
+	&dec	($b);
+	&jnz	(&label("loop"));
+
+	&mov	($b,&wparam(2));		# load len
+
+	&add	($a,0x61707865);		# accumulate key material
+	&add	($b_,&DWP(64+4*4,"esp"));
+	&add	($c, &DWP(64+4*8,"esp"));
+	&add	($c_,&DWP(64+4*9,"esp"));
+
+	&cmp	($b,64);
+	&jb	(&label("tail"));
+
+	&mov	($b,&wparam(1));		# load input pointer
+	&add	($d, &DWP(64+4*12,"esp"));
+	&add	($d_,&DWP(64+4*14,"esp"));
+
+	&xor	($a, &DWP(4*0,$b));		# xor with input
+	&xor	($b_,&DWP(4*4,$b));
+	&mov	(&DWP(4*0,"esp"),$a);
+	&mov	($a,&wparam(0));		# load output pointer
+	&xor	($c, &DWP(4*8,$b));
+	&xor	($c_,&DWP(4*9,$b));
+	&xor	($d, &DWP(4*12,$b));
+	&xor	($d_,&DWP(4*14,$b));
+	&mov	(&DWP(4*4,$a),$b_);		# write output
+	&mov	(&DWP(4*8,$a),$c);
+	&mov	(&DWP(4*9,$a),$c_);
+	&mov	(&DWP(4*12,$a),$d);
+	&mov	(&DWP(4*14,$a),$d_);
+
+	&mov	($b_,&DWP(4*1,"esp"));
+	&mov	($c, &DWP(4*2,"esp"));
+	&mov	($c_,&DWP(4*3,"esp"));
+	&mov	($d, &DWP(4*5,"esp"));
+	&mov	($d_,&DWP(4*6,"esp"));
+	&add	($b_,0x3320646e);		# accumulate key material
+	&add	($c, 0x79622d32);
+	&add	($c_,0x6b206574);
+	&add	($d, &DWP(64+4*5,"esp"));
+	&add	($d_,&DWP(64+4*6,"esp"));
+	&xor	($b_,&DWP(4*1,$b));
+	&xor	($c, &DWP(4*2,$b));
+	&xor	($c_,&DWP(4*3,$b));
+	&xor	($d, &DWP(4*5,$b));
+	&xor	($d_,&DWP(4*6,$b));
+	&mov	(&DWP(4*1,$a),$b_);
+	&mov	(&DWP(4*2,$a),$c);
+	&mov	(&DWP(4*3,$a),$c_);
+	&mov	(&DWP(4*5,$a),$d);
+	&mov	(&DWP(4*6,$a),$d_);
+
+	&mov	($b_,&DWP(4*7,"esp"));
+	&mov	($c, &DWP(4*10,"esp"));
+	&mov	($c_,&DWP(4*11,"esp"));
+	&mov	($d, &DWP(4*13,"esp"));
+	&mov	($d_,&DWP(4*15,"esp"));
+	&add	($b_,&DWP(64+4*7,"esp"));
+	&add	($c, &DWP(64+4*10,"esp"));
+	&add	($c_,&DWP(64+4*11,"esp"));
+	&add	($d, &DWP(64+4*13,"esp"));
+	&add	($d_,&DWP(64+4*15,"esp"));
+	&xor	($b_,&DWP(4*7,$b));
+	&xor	($c, &DWP(4*10,$b));
+	&xor	($c_,&DWP(4*11,$b));
+	&xor	($d, &DWP(4*13,$b));
+	&xor	($d_,&DWP(4*15,$b));
+	&lea	($b,&DWP(4*16,$b));
+	&mov	(&DWP(4*7,$a),$b_);
+	&mov	($b_,&DWP(4*0,"esp"));
+	&mov	(&DWP(4*10,$a),$c);
+	&mov	($c,&wparam(2));		# len
+	&mov	(&DWP(4*11,$a),$c_);
+	&mov	(&DWP(4*13,$a),$d);
+	&mov	(&DWP(4*15,$a),$d_);
+	&mov	(&DWP(4*0,$a),$b_);
+	&lea	($a,&DWP(4*16,$a));
+	&sub	($c,64);
+	&jnz	(&label("outer_loop"));
+
+	&jmp	(&label("done"));
+
+&set_label("tail");
+	&add	($d, &DWP(64+4*12,"esp"));
+	&add	($d_,&DWP(64+4*14,"esp"));
+	&mov	(&DWP(4*0,"esp"),$a);
+	&mov	(&DWP(4*4,"esp"),$b_);
+	&mov	(&DWP(4*8,"esp"),$c);
+	&mov	(&DWP(4*9,"esp"),$c_);
+	&mov	(&DWP(4*12,"esp"),$d);
+	&mov	(&DWP(4*14,"esp"),$d_);
+
+	&mov	($b_,&DWP(4*1,"esp"));
+	&mov	($c, &DWP(4*2,"esp"));
+	&mov	($c_,&DWP(4*3,"esp"));
+	&mov	($d, &DWP(4*5,"esp"));
+	&mov	($d_,&DWP(4*6,"esp"));
+	&add	($b_,0x3320646e);		# accumulate key material
+	&add	($c, 0x79622d32);
+	&add	($c_,0x6b206574);
+	&add	($d, &DWP(64+4*5,"esp"));
+	&add	($d_,&DWP(64+4*6,"esp"));
+	&mov	(&DWP(4*1,"esp"),$b_);
+	&mov	(&DWP(4*2,"esp"),$c);
+	&mov	(&DWP(4*3,"esp"),$c_);
+	&mov	(&DWP(4*5,"esp"),$d);
+	&mov	(&DWP(4*6,"esp"),$d_);
+
+	&mov	($b_,&DWP(4*7,"esp"));
+	&mov	($c, &DWP(4*10,"esp"));
+	&mov	($c_,&DWP(4*11,"esp"));
+	&mov	($d, &DWP(4*13,"esp"));
+	&mov	($d_,&DWP(4*15,"esp"));
+	&add	($b_,&DWP(64+4*7,"esp"));
+	&add	($c, &DWP(64+4*10,"esp"));
+	&add	($c_,&DWP(64+4*11,"esp"));
+	&add	($d, &DWP(64+4*13,"esp"));
+	&add	($d_,&DWP(64+4*15,"esp"));
+	&mov	(&DWP(4*7,"esp"),$b_);
+	&mov	($b_,&wparam(1));		# load input
+	&mov	(&DWP(4*10,"esp"),$c);
+	&mov	($c,&wparam(0));		# load output
+	&mov	(&DWP(4*11,"esp"),$c_);
+	&xor	($c_,$c_);
+	&mov	(&DWP(4*13,"esp"),$d);
+	&mov	(&DWP(4*15,"esp"),$d_);
+
+	&xor	("eax","eax");
+	&xor	("edx","edx");
+&set_label("tail_loop");
+	&movb	("al",&BP(0,$c_,$b_));
+	&movb	("dl",&BP(0,"esp",$c_));
+	&lea	($c_,&DWP(1,$c_));
+	&xor	("al","dl");
+	&mov	(&BP(-1,$c,$c_),"al");
+	&dec	($b);
+	&jnz	(&label("tail_loop"));
+
+&set_label("done");
+	&stack_pop(33);
+&set_label("no_data");
+&function_end("ChaCha20_ctr32");
+
+if ($xmm) {
+my ($xa,$xa_,$xb,$xb_,$xc,$xc_,$xd,$xd_)=map("xmm$_",(0..7));
+my ($out,$inp,$len)=("edi","esi","ecx");
+
+sub QUARTERROUND_SSSE3 {
+my ($ai,$bi,$ci,$di,$i)=@_;
+my ($an,$bn,$cn,$dn)=map(($_&~3)+(($_+1)&3),($ai,$bi,$ci,$di));	# next
+my ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_-1)&3),($ai,$bi,$ci,$di));	# previous
+
+	#       a   b   c   d
+	#
+	#       0   4   8  12 < even round
+	#       1   5   9  13
+	#       2   6  10  14
+	#       3   7  11  15
+	#       0   5  10  15 < odd round
+	#       1   6  11  12
+	#       2   7   8  13
+	#       3   4   9  14
+
+	if ($i==0) {
+            my $j=4;
+	    ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_-$j--)&3),($ap,$bp,$cp,$dp));
+	} elsif ($i==3) {
+            my $j=0;
+	    ($an,$bn,$cn,$dn)=map(($_&~3)+(($_+$j++)&3),($an,$bn,$cn,$dn));
+	} elsif ($i==4) {
+            my $j=4;
+	    ($ap,$bp,$cp,$dp)=map(($_&~3)+(($_+$j--)&3),($ap,$bp,$cp,$dp));
+	} elsif ($i==7) {
+            my $j=0;
+	    ($an,$bn,$cn,$dn)=map(($_&~3)+(($_-$j++)&3),($an,$bn,$cn,$dn));
+	}
+
+	#&paddd	($xa,$xb);			# see elsewhere
+	#&pxor	($xd,$xa);			# see elsewhere
+	 &movdqa(&QWP(16*$cp-128,"ebx"),$xc_)	if ($ai>0 && $ai<3);
+	&pshufb	($xd,&QWP(0,"eax"));		# rot16
+	 &movdqa(&QWP(16*$bp-128,"ebx"),$xb_)	if ($i!=0);
+	&paddd	($xc,$xd);
+	 &movdqa($xc_,&QWP(16*$cn-128,"ebx"))	if ($ai>0 && $ai<3);
+	&pxor	($xb,$xc);
+	 &movdqa($xb_,&QWP(16*$bn-128,"ebx"))	if ($i<7);
+	&movdqa	($xa_,$xb);			# borrow as temporary
+	&pslld	($xb,12);
+	&psrld	($xa_,20);
+	&por	($xb,$xa_);
+	 &movdqa($xa_,&QWP(16*$an-128,"ebx"));
+	&paddd	($xa,$xb);
+	 &movdqa($xd_,&QWP(16*$dn-128,"ebx"))	if ($di!=$dn);
+	&pxor	($xd,$xa);
+	&movdqa	(&QWP(16*$ai-128,"ebx"),$xa);
+	&pshufb	($xd,&QWP(16,"eax"));		# rot8
+	&paddd	($xc,$xd);
+	&movdqa	(&QWP(16*$di-128,"ebx"),$xd)	if ($di!=$dn);
+	&movdqa	($xd_,$xd)			if ($di==$dn);
+	&pxor	($xb,$xc);
+	 &paddd	($xa_,$xb_)			if ($i<7);	# elsewhere
+	&movdqa	($xa,$xb);			# borrow as temporary
+	&pslld	($xb,7);
+	&psrld	($xa,25);
+	 &pxor	($xd_,$xa_)			if ($i<7);	# elsewhere
+	&por	($xb,$xa);
+
+	($xa,$xa_)=($xa_,$xa);
+	($xb,$xb_)=($xb_,$xb);
+	($xc,$xc_)=($xc_,$xc);
+	($xd,$xd_)=($xd_,$xd);
+}
+
+&function_begin("ChaCha20_ssse3");
+&set_label("ssse3_shortcut");
+	&mov		($out,&wparam(0));
+	&mov		($inp,&wparam(1));
+	&mov		($len,&wparam(2));
+	&mov		("edx",&wparam(3));		# key
+	&mov		("ebx",&wparam(4));		# counter and nonce
+
+	&mov		("ebp","esp");
+	&stack_push	(131);
+	&and		("esp",-64);
+	&mov		(&DWP(512,"esp"),"ebp");
+
+	&lea		("eax",&DWP(&label("ssse3_data")."-".
+				    &label("pic_point"),"eax"));
+	&movdqu		("xmm3",&QWP(0,"ebx"));		# counter and nonce
+
+if (defined($gasver) && $gasver>=2.17) {		# even though we encode
+							# pshufb manually, we
+							# handle only register
+							# operands, while this
+							# segment uses memory
+							# operand...
+	&cmp		($len,64*4);
+	&jb		(&label("1x"));
+
+	&mov		(&DWP(512+4,"esp"),"edx");	# offload pointers
+	&mov		(&DWP(512+8,"esp"),"ebx");
+	&sub		($len,64*4);			# bias len
+	&lea		("ebp",&DWP(256+128,"esp"));	# size optimization
+
+	&movdqu		("xmm7",&QWP(0,"edx"));		# key
+	&pshufd		("xmm0","xmm3",0x00);
+	&pshufd		("xmm1","xmm3",0x55);
+	&pshufd		("xmm2","xmm3",0xaa);
+	&pshufd		("xmm3","xmm3",0xff);
+	 &paddd		("xmm0",&QWP(16*3,"eax"));	# fix counters
+	&pshufd		("xmm4","xmm7",0x00);
+	&pshufd		("xmm5","xmm7",0x55);
+	 &psubd		("xmm0",&QWP(16*4,"eax"));
+	&pshufd		("xmm6","xmm7",0xaa);
+	&pshufd		("xmm7","xmm7",0xff);
+	&movdqa		(&QWP(16*12-128,"ebp"),"xmm0");
+	&movdqa		(&QWP(16*13-128,"ebp"),"xmm1");
+	&movdqa		(&QWP(16*14-128,"ebp"),"xmm2");
+	&movdqa		(&QWP(16*15-128,"ebp"),"xmm3");
+	 &movdqu	("xmm3",&QWP(16,"edx"));	# key
+	&movdqa		(&QWP(16*4-128,"ebp"),"xmm4");
+	&movdqa		(&QWP(16*5-128,"ebp"),"xmm5");
+	&movdqa		(&QWP(16*6-128,"ebp"),"xmm6");
+	&movdqa		(&QWP(16*7-128,"ebp"),"xmm7");
+	 &movdqa	("xmm7",&QWP(16*2,"eax"));	# sigma
+	 &lea		("ebx",&DWP(128,"esp"));	# size optimization
+
+	&pshufd		("xmm0","xmm3",0x00);
+	&pshufd		("xmm1","xmm3",0x55);
+	&pshufd		("xmm2","xmm3",0xaa);
+	&pshufd		("xmm3","xmm3",0xff);
+	&pshufd		("xmm4","xmm7",0x00);
+	&pshufd		("xmm5","xmm7",0x55);
+	&pshufd		("xmm6","xmm7",0xaa);
+	&pshufd		("xmm7","xmm7",0xff);
+	&movdqa		(&QWP(16*8-128,"ebp"),"xmm0");
+	&movdqa		(&QWP(16*9-128,"ebp"),"xmm1");
+	&movdqa		(&QWP(16*10-128,"ebp"),"xmm2");
+	&movdqa		(&QWP(16*11-128,"ebp"),"xmm3");
+	&movdqa		(&QWP(16*0-128,"ebp"),"xmm4");
+	&movdqa		(&QWP(16*1-128,"ebp"),"xmm5");
+	&movdqa		(&QWP(16*2-128,"ebp"),"xmm6");
+	&movdqa		(&QWP(16*3-128,"ebp"),"xmm7");
+
+	&lea		($inp,&DWP(128,$inp));		# size optimization
+	&lea		($out,&DWP(128,$out));		# size optimization
+	&jmp		(&label("outer_loop"));
+
+&set_label("outer_loop",16);
+	#&movdqa	("xmm0",&QWP(16*0-128,"ebp"));	# copy key material
+	&movdqa		("xmm1",&QWP(16*1-128,"ebp"));
+	&movdqa		("xmm2",&QWP(16*2-128,"ebp"));
+	&movdqa		("xmm3",&QWP(16*3-128,"ebp"));
+	#&movdqa	("xmm4",&QWP(16*4-128,"ebp"));
+	&movdqa		("xmm5",&QWP(16*5-128,"ebp"));
+	&movdqa		("xmm6",&QWP(16*6-128,"ebp"));
+	&movdqa		("xmm7",&QWP(16*7-128,"ebp"));
+	#&movdqa	(&QWP(16*0-128,"ebx"),"xmm0");
+	&movdqa		(&QWP(16*1-128,"ebx"),"xmm1");
+	&movdqa		(&QWP(16*2-128,"ebx"),"xmm2");
+	&movdqa		(&QWP(16*3-128,"ebx"),"xmm3");
+	#&movdqa	(&QWP(16*4-128,"ebx"),"xmm4");
+	&movdqa		(&QWP(16*5-128,"ebx"),"xmm5");
+	&movdqa		(&QWP(16*6-128,"ebx"),"xmm6");
+	&movdqa		(&QWP(16*7-128,"ebx"),"xmm7");
+	#&movdqa	("xmm0",&QWP(16*8-128,"ebp"));
+	#&movdqa	("xmm1",&QWP(16*9-128,"ebp"));
+	&movdqa		("xmm2",&QWP(16*10-128,"ebp"));
+	&movdqa		("xmm3",&QWP(16*11-128,"ebp"));
+	&movdqa		("xmm4",&QWP(16*12-128,"ebp"));
+	&movdqa		("xmm5",&QWP(16*13-128,"ebp"));
+	&movdqa		("xmm6",&QWP(16*14-128,"ebp"));
+	&movdqa		("xmm7",&QWP(16*15-128,"ebp"));
+	&paddd		("xmm4",&QWP(16*4,"eax"));	# counter value
+	#&movdqa	(&QWP(16*8-128,"ebx"),"xmm0");
+	#&movdqa	(&QWP(16*9-128,"ebx"),"xmm1");
+	&movdqa		(&QWP(16*10-128,"ebx"),"xmm2");
+	&movdqa		(&QWP(16*11-128,"ebx"),"xmm3");
+	&movdqa		(&QWP(16*12-128,"ebx"),"xmm4");
+	&movdqa		(&QWP(16*13-128,"ebx"),"xmm5");
+	&movdqa		(&QWP(16*14-128,"ebx"),"xmm6");
+	&movdqa		(&QWP(16*15-128,"ebx"),"xmm7");
+	&movdqa		(&QWP(16*12-128,"ebp"),"xmm4");	# save counter value
+
+	&movdqa		($xa, &QWP(16*0-128,"ebp"));
+	&movdqa		($xd, "xmm4");
+	&movdqa		($xb_,&QWP(16*4-128,"ebp"));
+	&movdqa		($xc, &QWP(16*8-128,"ebp"));
+	&movdqa		($xc_,&QWP(16*9-128,"ebp"));
+
+	&mov		("edx",10);			# loop counter
+	&nop		();
+
+&set_label("loop",16);
+	&paddd		($xa,$xb_);			# elsewhere
+	&movdqa		($xb,$xb_);
+	&pxor		($xd,$xa);			# elsewhere
+	&QUARTERROUND_SSSE3(0, 4, 8, 12, 0);
+	&QUARTERROUND_SSSE3(1, 5, 9, 13, 1);
+	&QUARTERROUND_SSSE3(2, 6,10, 14, 2);
+	&QUARTERROUND_SSSE3(3, 7,11, 15, 3);
+	&QUARTERROUND_SSSE3(0, 5,10, 15, 4);
+	&QUARTERROUND_SSSE3(1, 6,11, 12, 5);
+	&QUARTERROUND_SSSE3(2, 7, 8, 13, 6);
+	&QUARTERROUND_SSSE3(3, 4, 9, 14, 7);
+	&dec		("edx");
+	&jnz		(&label("loop"));
+
+	&movdqa		(&QWP(16*4-128,"ebx"),$xb_);
+	&movdqa		(&QWP(16*8-128,"ebx"),$xc);
+	&movdqa		(&QWP(16*9-128,"ebx"),$xc_);
+	&movdqa		(&QWP(16*12-128,"ebx"),$xd);
+	&movdqa		(&QWP(16*14-128,"ebx"),$xd_);
+
+    my ($xa0,$xa1,$xa2,$xa3,$xt0,$xt1,$xt2,$xt3)=map("xmm$_",(0..7));
+
+	#&movdqa	($xa0,&QWP(16*0-128,"ebx"));	# it's there
+	&movdqa		($xa1,&QWP(16*1-128,"ebx"));
+	&movdqa		($xa2,&QWP(16*2-128,"ebx"));
+	&movdqa		($xa3,&QWP(16*3-128,"ebx"));
+
+    for($i=0;$i<256;$i+=64) {
+	&paddd		($xa0,&QWP($i+16*0-128,"ebp"));	# accumulate key material
+	&paddd		($xa1,&QWP($i+16*1-128,"ebp"));
+	&paddd		($xa2,&QWP($i+16*2-128,"ebp"));
+	&paddd		($xa3,&QWP($i+16*3-128,"ebp"));
+
+	&movdqa		($xt2,$xa0);		# "de-interlace" data
+	&punpckldq	($xa0,$xa1);
+	&movdqa		($xt3,$xa2);
+	&punpckldq	($xa2,$xa3);
+	&punpckhdq	($xt2,$xa1);
+	&punpckhdq	($xt3,$xa3);
+	&movdqa		($xa1,$xa0);
+	&punpcklqdq	($xa0,$xa2);		# "a0"
+	&movdqa		($xa3,$xt2);
+	&punpcklqdq	($xt2,$xt3);		# "a2"
+	&punpckhqdq	($xa1,$xa2);		# "a1"
+	&punpckhqdq	($xa3,$xt3);		# "a3"
+
+	#($xa2,$xt2)=($xt2,$xa2);
+
+	&movdqu		($xt0,&QWP(64*0-128,$inp));	# load input
+	&movdqu		($xt1,&QWP(64*1-128,$inp));
+	&movdqu		($xa2,&QWP(64*2-128,$inp));
+	&movdqu		($xt3,&QWP(64*3-128,$inp));
+	&lea		($inp,&QWP($i<192?16:(64*4-16*3),$inp));
+	&pxor		($xt0,$xa0);
+	&movdqa		($xa0,&QWP($i+16*4-128,"ebx"))	if ($i<192);
+	&pxor		($xt1,$xa1);
+	&movdqa		($xa1,&QWP($i+16*5-128,"ebx"))	if ($i<192);
+	&pxor		($xt2,$xa2);
+	&movdqa		($xa2,&QWP($i+16*6-128,"ebx"))	if ($i<192);
+	&pxor		($xt3,$xa3);
+	&movdqa		($xa3,&QWP($i+16*7-128,"ebx"))	if ($i<192);
+	&movdqu		(&QWP(64*0-128,$out),$xt0);	# store output
+	&movdqu		(&QWP(64*1-128,$out),$xt1);
+	&movdqu		(&QWP(64*2-128,$out),$xt2);
+	&movdqu		(&QWP(64*3-128,$out),$xt3);
+	&lea		($out,&QWP($i<192?16:(64*4-16*3),$out));
+    }
+	&sub		($len,64*4);
+	&jnc		(&label("outer_loop"));
+
+	&add		($len,64*4);
+	&jz		(&label("done"));
+
+	&mov		("ebx",&DWP(512+8,"esp"));	# restore pointers
+	&lea		($inp,&DWP(-128,$inp));
+	&mov		("edx",&DWP(512+4,"esp"));
+	&lea		($out,&DWP(-128,$out));
+
+	&movd		("xmm2",&DWP(16*12-128,"ebp"));	# counter value
+	&movdqu		("xmm3",&QWP(0,"ebx"));
+	&paddd		("xmm2",&QWP(16*6,"eax"));	# +four
+	&pand		("xmm3",&QWP(16*7,"eax"));
+	&por		("xmm3","xmm2");		# counter value
+}
+{
+my ($a,$b,$c,$d,$t,$t1,$rot16,$rot24)=map("xmm$_",(0..7));
+
+sub SSSE3ROUND {	# critical path is 20 "SIMD ticks" per round
+	&paddd		($a,$b);
+	&pxor		($d,$a);
+	&pshufb		($d,$rot16);
+
+	&paddd		($c,$d);
+	&pxor		($b,$c);
+	&movdqa		($t,$b);
+	&psrld		($b,20);
+	&pslld		($t,12);
+	&por		($b,$t);
+
+	&paddd		($a,$b);
+	&pxor		($d,$a);
+	&pshufb		($d,$rot24);
+
+	&paddd		($c,$d);
+	&pxor		($b,$c);
+	&movdqa		($t,$b);
+	&psrld		($b,25);
+	&pslld		($t,7);
+	&por		($b,$t);
+}
+
+&set_label("1x");
+	&movdqa		($a,&QWP(16*2,"eax"));		# sigma
+	&movdqu		($b,&QWP(0,"edx"));
+	&movdqu		($c,&QWP(16,"edx"));
+	#&movdqu	($d,&QWP(0,"ebx"));		# already loaded
+	&movdqa		($rot16,&QWP(0,"eax"));
+	&movdqa		($rot24,&QWP(16,"eax"));
+	&mov		(&DWP(16*3,"esp"),"ebp");
+
+	&movdqa		(&QWP(16*0,"esp"),$a);
+	&movdqa		(&QWP(16*1,"esp"),$b);
+	&movdqa		(&QWP(16*2,"esp"),$c);
+	&movdqa		(&QWP(16*3,"esp"),$d);
+	&mov		("edx",10);
+	&jmp		(&label("loop1x"));
+
+&set_label("outer1x",16);
+	&movdqa		($d,&QWP(16*5,"eax"));		# one
+	&movdqa		($a,&QWP(16*0,"esp"));
+	&movdqa		($b,&QWP(16*1,"esp"));
+	&movdqa		($c,&QWP(16*2,"esp"));
+	&paddd		($d,&QWP(16*3,"esp"));
+	&mov		("edx",10);
+	&movdqa		(&QWP(16*3,"esp"),$d);
+	&jmp		(&label("loop1x"));
+
+&set_label("loop1x",16);
+	&SSSE3ROUND();
+	&pshufd	($c,$c,0b01001110);
+	&pshufd	($b,$b,0b00111001);
+	&pshufd	($d,$d,0b10010011);
+	&nop	();
+
+	&SSSE3ROUND();
+	&pshufd	($c,$c,0b01001110);
+	&pshufd	($b,$b,0b10010011);
+	&pshufd	($d,$d,0b00111001);
+
+	&dec		("edx");
+	&jnz		(&label("loop1x"));
+
+	&paddd		($a,&QWP(16*0,"esp"));
+	&paddd		($b,&QWP(16*1,"esp"));
+	&paddd		($c,&QWP(16*2,"esp"));
+	&paddd		($d,&QWP(16*3,"esp"));
+
+	&cmp		($len,64);
+	&jb		(&label("tail"));
+
+	&movdqu		($t,&QWP(16*0,$inp));
+	&movdqu		($t1,&QWP(16*1,$inp));
+	&pxor		($a,$t);		# xor with input
+	&movdqu		($t,&QWP(16*2,$inp));
+	&pxor		($b,$t1);
+	&movdqu		($t1,&QWP(16*3,$inp));
+	&pxor		($c,$t);
+	&pxor		($d,$t1);
+	&lea		($inp,&DWP(16*4,$inp));	# inp+=64
+
+	&movdqu		(&QWP(16*0,$out),$a);	# write output
+	&movdqu		(&QWP(16*1,$out),$b);
+	&movdqu		(&QWP(16*2,$out),$c);
+	&movdqu		(&QWP(16*3,$out),$d);
+	&lea		($out,&DWP(16*4,$out));	# inp+=64
+
+	&sub		($len,64);
+	&jnz		(&label("outer1x"));
+
+	&jmp		(&label("done"));
+
+&set_label("tail");
+	&movdqa		(&QWP(16*0,"esp"),$a);
+	&movdqa		(&QWP(16*1,"esp"),$b);
+	&movdqa		(&QWP(16*2,"esp"),$c);
+	&movdqa		(&QWP(16*3,"esp"),$d);
+
+	&xor		("eax","eax");
+	&xor		("edx","edx");
+	&xor		("ebp","ebp");
+
+&set_label("tail_loop");
+	&movb		("al",&BP(0,"esp","ebp"));
+	&movb		("dl",&BP(0,$inp,"ebp"));
+	&lea		("ebp",&DWP(1,"ebp"));
+	&xor		("al","dl");
+	&movb		(&BP(-1,$out,"ebp"),"al");
+	&dec		($len);
+	&jnz		(&label("tail_loop"));
+}
+&set_label("done");
+	&mov		("esp",&DWP(512,"esp"));
+&function_end("ChaCha20_ssse3");
+
+&align	(64);
+&set_label("ssse3_data");
+&data_byte(0x2,0x3,0x0,0x1, 0x6,0x7,0x4,0x5, 0xa,0xb,0x8,0x9, 0xe,0xf,0xc,0xd);
+&data_byte(0x3,0x0,0x1,0x2, 0x7,0x4,0x5,0x6, 0xb,0x8,0x9,0xa, 0xf,0xc,0xd,0xe);
+&data_word(0x61707865,0x3320646e,0x79622d32,0x6b206574);
+&data_word(0,1,2,3);
+&data_word(4,4,4,4);
+&data_word(1,0,0,0);
+&data_word(4,0,0,0);
+&data_word(0,-1,-1,-1);
+&align	(64);
+}
+&asciz	("ChaCha20 for x86, CRYPTOGAMS by <appro\@openssl.org>");
+
+&asm_finish();
+
+close STDOUT;
diff --git a/src/crypto/chacha/asm/chacha-x86_64.pl b/src/crypto/chacha/asm/chacha-x86_64.pl
new file mode 100755
index 0000000..5ab6f87
--- /dev/null
+++ b/src/crypto/chacha/asm/chacha-x86_64.pl
@@ -0,0 +1,2747 @@
+#! /usr/bin/env perl
+# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the OpenSSL license (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# November 2014
+#
+# ChaCha20 for x86_64.
+#
+# December 2016
+#
+# Add AVX512F code path.
+#
+# Performance in cycles per byte out of large buffer.
+#
+#		IALU/gcc 4.8(i)	1xSSSE3/SSE2	4xSSSE3	    8xAVX2
+#
+# P4		9.48/+99%	-/22.7(ii)	-
+# Core2		7.83/+55%	7.90/8.08	4.35
+# Westmere	7.19/+50%	5.60/6.70	3.00
+# Sandy Bridge	8.31/+42%	5.45/6.76	2.72
+# Ivy Bridge	6.71/+46%	5.40/6.49	2.41
+# Haswell	5.92/+43%	5.20/6.45	2.42	    1.23
+# Skylake	5.87/+39%	4.70/-		2.31	    1.19
+# Silvermont	12.0/+33%	7.75/7.40	7.03(iii)
+# Goldmont	10.6/+17%	5.10/-		3.28
+# Sledgehammer	7.28/+52%	-/14.2(ii)	-
+# Bulldozer	9.66/+28%	9.85/11.1	3.06(iv)
+# VIA Nano	10.5/+46%	6.72/8.60	6.05
+#
+# (i)	compared to older gcc 3.x one can observe >2x improvement on
+#	most platforms;
+# (ii)	as it can be seen, SSE2 performance is too low on legacy
+#	processors; NxSSE2 results are naturally better, but not
+#	impressively better than IALU ones, which is why you won't
+#	find SSE2 code below;
+# (iii)	this is not optimal result for Atom because of MSROM
+#	limitations, SSE2 can do better, but gain is considered too
+#	low to justify the [maintenance] effort;
+# (iv)	Bulldozer actually executes 4xXOP code path that delivers 2.20;
+#
+# Modified from upstream OpenSSL to remove the XOP code.
+
+$flavour = shift;
+$output  = shift;
+if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+
+$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
+die "can't locate x86_64-xlate.pl";
+
+$avx = 2;
+
+open OUT,"| \"$^X\" $xlate $flavour $output";
+*STDOUT=*OUT;
+
+# input parameter block
+($out,$inp,$len,$key,$counter)=("%rdi","%rsi","%rdx","%rcx","%r8");
+
+$code.=<<___;
+.text
+
+.extern OPENSSL_ia32cap_P
+
+.align	64
+.Lzero:
+.long	0,0,0,0
+.Lone:
+.long	1,0,0,0
+.Linc:
+.long	0,1,2,3
+.Lfour:
+.long	4,4,4,4
+.Lincy:
+.long	0,2,4,6,1,3,5,7
+.Leight:
+.long	8,8,8,8,8,8,8,8
+.Lrot16:
+.byte	0x2,0x3,0x0,0x1, 0x6,0x7,0x4,0x5, 0xa,0xb,0x8,0x9, 0xe,0xf,0xc,0xd
+.Lrot24:
+.byte	0x3,0x0,0x1,0x2, 0x7,0x4,0x5,0x6, 0xb,0x8,0x9,0xa, 0xf,0xc,0xd,0xe
+.Lsigma:
+.asciz	"expand 32-byte k"
+.align	64
+.Lzeroz:
+.long	0,0,0,0, 1,0,0,0, 2,0,0,0, 3,0,0,0
+.Lfourz:
+.long	4,0,0,0, 4,0,0,0, 4,0,0,0, 4,0,0,0
+.Lincz:
+.long	0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+.Lsixteen:
+.long	16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16
+.asciz	"ChaCha20 for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
+___
+
+sub AUTOLOAD()          # thunk [simplified] 32-bit style perlasm
+{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://;
+  my $arg = pop;
+    $arg = "\$$arg" if ($arg*1 eq $arg);
+    $code .= "\t$opcode\t".join(',',$arg,reverse @_)."\n";
+}
+
+@x=("%eax","%ebx","%ecx","%edx",map("%r${_}d",(8..11)),
+    "%nox","%nox","%nox","%nox",map("%r${_}d",(12..15)));
+@t=("%esi","%edi");
+
+sub ROUND {			# critical path is 24 cycles per round
+my ($a0,$b0,$c0,$d0)=@_;
+my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0));
+my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1));
+my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2));
+my ($xc,$xc_)=map("\"$_\"",@t);
+my @x=map("\"$_\"",@x);
+
+	# Consider order in which variables are addressed by their
+	# index:
+	#
+	#	a   b   c   d
+	#
+	#	0   4   8  12 < even round
+	#	1   5   9  13
+	#	2   6  10  14
+	#	3   7  11  15
+	#	0   5  10  15 < odd round
+	#	1   6  11  12
+	#	2   7   8  13
+	#	3   4   9  14
+	#
+	# 'a', 'b' and 'd's are permanently allocated in registers,
+	# @x[0..7,12..15], while 'c's are maintained in memory. If
+	# you observe 'c' column, you'll notice that pair of 'c's is
+	# invariant between rounds. This means that we have to reload
+	# them once per round, in the middle. This is why you'll see
+	# bunch of 'c' stores and loads in the middle, but none in
+	# the beginning or end.
+
+	# Normally instructions would be interleaved to favour in-order
+	# execution. Generally out-of-order cores manage it gracefully,
+	# but not this time for some reason. As in-order execution
+	# cores are dying breed, old Atom is the only one around,
+	# instructions are left uninterleaved. Besides, Atom is better
+	# off executing 1xSSSE3 code anyway...
+
+	(
+	"&add	(@x[$a0],@x[$b0])",	# Q1
+	"&xor	(@x[$d0],@x[$a0])",
+	"&rol	(@x[$d0],16)",
+	 "&add	(@x[$a1],@x[$b1])",	# Q2
+	 "&xor	(@x[$d1],@x[$a1])",
+	 "&rol	(@x[$d1],16)",
+
+	"&add	($xc,@x[$d0])",
+	"&xor	(@x[$b0],$xc)",
+	"&rol	(@x[$b0],12)",
+	 "&add	($xc_,@x[$d1])",
+	 "&xor	(@x[$b1],$xc_)",
+	 "&rol	(@x[$b1],12)",
+
+	"&add	(@x[$a0],@x[$b0])",
+	"&xor	(@x[$d0],@x[$a0])",
+	"&rol	(@x[$d0],8)",
+	 "&add	(@x[$a1],@x[$b1])",
+	 "&xor	(@x[$d1],@x[$a1])",
+	 "&rol	(@x[$d1],8)",
+
+	"&add	($xc,@x[$d0])",
+	"&xor	(@x[$b0],$xc)",
+	"&rol	(@x[$b0],7)",
+	 "&add	($xc_,@x[$d1])",
+	 "&xor	(@x[$b1],$xc_)",
+	 "&rol	(@x[$b1],7)",
+
+	"&mov	(\"4*$c0(%rsp)\",$xc)",	# reload pair of 'c's
+	 "&mov	(\"4*$c1(%rsp)\",$xc_)",
+	"&mov	($xc,\"4*$c2(%rsp)\")",
+	 "&mov	($xc_,\"4*$c3(%rsp)\")",
+
+	"&add	(@x[$a2],@x[$b2])",	# Q3
+	"&xor	(@x[$d2],@x[$a2])",
+	"&rol	(@x[$d2],16)",
+	 "&add	(@x[$a3],@x[$b3])",	# Q4
+	 "&xor	(@x[$d3],@x[$a3])",
+	 "&rol	(@x[$d3],16)",
+
+	"&add	($xc,@x[$d2])",
+	"&xor	(@x[$b2],$xc)",
+	"&rol	(@x[$b2],12)",
+	 "&add	($xc_,@x[$d3])",
+	 "&xor	(@x[$b3],$xc_)",
+	 "&rol	(@x[$b3],12)",
+
+	"&add	(@x[$a2],@x[$b2])",
+	"&xor	(@x[$d2],@x[$a2])",
+	"&rol	(@x[$d2],8)",
+	 "&add	(@x[$a3],@x[$b3])",
+	 "&xor	(@x[$d3],@x[$a3])",
+	 "&rol	(@x[$d3],8)",
+
+	"&add	($xc,@x[$d2])",
+	"&xor	(@x[$b2],$xc)",
+	"&rol	(@x[$b2],7)",
+	 "&add	($xc_,@x[$d3])",
+	 "&xor	(@x[$b3],$xc_)",
+	 "&rol	(@x[$b3],7)"
+	);
+}
+
+########################################################################
+# Generic code path that handles all lengths on pre-SSSE3 processors.
+$code.=<<___;
+.globl	ChaCha20_ctr32
+.type	ChaCha20_ctr32,\@function,5
+.align	64
+ChaCha20_ctr32:
+	cmp	\$0,$len
+	je	.Lno_data
+	mov	OPENSSL_ia32cap_P+4(%rip),%r10
+___
+$code.=<<___	if ($avx>2);
+	bt	\$48,%r10		# check for AVX512F
+	jc	.LChaCha20_avx512
+___
+$code.=<<___;
+	test	\$`1<<(41-32)`,%r10d
+	jnz	.LChaCha20_ssse3
+
+	push	%rbx
+	push	%rbp
+	push	%r12
+	push	%r13
+	push	%r14
+	push	%r15
+	sub	\$64+24,%rsp
+.Lctr32_body:
+
+	#movdqa	.Lsigma(%rip),%xmm0
+	movdqu	($key),%xmm1
+	movdqu	16($key),%xmm2
+	movdqu	($counter),%xmm3
+	movdqa	.Lone(%rip),%xmm4
+
+	#movdqa	%xmm0,4*0(%rsp)		# key[0]
+	movdqa	%xmm1,4*4(%rsp)		# key[1]
+	movdqa	%xmm2,4*8(%rsp)		# key[2]
+	movdqa	%xmm3,4*12(%rsp)	# key[3]
+	mov	$len,%rbp		# reassign $len
+	jmp	.Loop_outer
+
+.align	32
+.Loop_outer:
+	mov	\$0x61707865,@x[0]      # 'expa'
+	mov	\$0x3320646e,@x[1]      # 'nd 3'
+	mov	\$0x79622d32,@x[2]      # '2-by'
+	mov	\$0x6b206574,@x[3]      # 'te k'
+	mov	4*4(%rsp),@x[4]
+	mov	4*5(%rsp),@x[5]
+	mov	4*6(%rsp),@x[6]
+	mov	4*7(%rsp),@x[7]
+	movd	%xmm3,@x[12]
+	mov	4*13(%rsp),@x[13]
+	mov	4*14(%rsp),@x[14]
+	mov	4*15(%rsp),@x[15]
+
+	mov	%rbp,64+0(%rsp)		# save len
+	mov	\$10,%ebp
+	mov	$inp,64+8(%rsp)		# save inp
+	movq	%xmm2,%rsi		# "@x[8]"
+	mov	$out,64+16(%rsp)	# save out
+	mov	%rsi,%rdi
+	shr	\$32,%rdi		# "@x[9]"
+	jmp	.Loop
+
+.align	32
+.Loop:
+___
+	foreach (&ROUND (0, 4, 8,12)) { eval; }
+	foreach (&ROUND	(0, 5,10,15)) { eval; }
+	&dec	("%ebp");
+	&jnz	(".Loop");
+
+$code.=<<___;
+	mov	@t[1],4*9(%rsp)		# modulo-scheduled
+	mov	@t[0],4*8(%rsp)
+	mov	64(%rsp),%rbp		# load len
+	movdqa	%xmm2,%xmm1
+	mov	64+8(%rsp),$inp		# load inp
+	paddd	%xmm4,%xmm3		# increment counter
+	mov	64+16(%rsp),$out	# load out
+
+	add	\$0x61707865,@x[0]      # 'expa'
+	add	\$0x3320646e,@x[1]      # 'nd 3'
+	add	\$0x79622d32,@x[2]      # '2-by'
+	add	\$0x6b206574,@x[3]      # 'te k'
+	add	4*4(%rsp),@x[4]
+	add	4*5(%rsp),@x[5]
+	add	4*6(%rsp),@x[6]
+	add	4*7(%rsp),@x[7]
+	add	4*12(%rsp),@x[12]
+	add	4*13(%rsp),@x[13]
+	add	4*14(%rsp),@x[14]
+	add	4*15(%rsp),@x[15]
+	paddd	4*8(%rsp),%xmm1
+
+	cmp	\$64,%rbp
+	jb	.Ltail
+
+	xor	4*0($inp),@x[0]		# xor with input
+	xor	4*1($inp),@x[1]
+	xor	4*2($inp),@x[2]
+	xor	4*3($inp),@x[3]
+	xor	4*4($inp),@x[4]
+	xor	4*5($inp),@x[5]
+	xor	4*6($inp),@x[6]
+	xor	4*7($inp),@x[7]
+	movdqu	4*8($inp),%xmm0
+	xor	4*12($inp),@x[12]
+	xor	4*13($inp),@x[13]
+	xor	4*14($inp),@x[14]
+	xor	4*15($inp),@x[15]
+	lea	4*16($inp),$inp		# inp+=64
+	pxor	%xmm1,%xmm0
+
+	movdqa	%xmm2,4*8(%rsp)
+	movd	%xmm3,4*12(%rsp)
+
+	mov	@x[0],4*0($out)		# write output
+	mov	@x[1],4*1($out)
+	mov	@x[2],4*2($out)
+	mov	@x[3],4*3($out)
+	mov	@x[4],4*4($out)
+	mov	@x[5],4*5($out)
+	mov	@x[6],4*6($out)
+	mov	@x[7],4*7($out)
+	movdqu	%xmm0,4*8($out)
+	mov	@x[12],4*12($out)
+	mov	@x[13],4*13($out)
+	mov	@x[14],4*14($out)
+	mov	@x[15],4*15($out)
+	lea	4*16($out),$out		# out+=64
+
+	sub	\$64,%rbp
+	jnz	.Loop_outer
+
+	jmp	.Ldone
+
+.align	16
+.Ltail:
+	mov	@x[0],4*0(%rsp)
+	mov	@x[1],4*1(%rsp)
+	xor	%rbx,%rbx
+	mov	@x[2],4*2(%rsp)
+	mov	@x[3],4*3(%rsp)
+	mov	@x[4],4*4(%rsp)
+	mov	@x[5],4*5(%rsp)
+	mov	@x[6],4*6(%rsp)
+	mov	@x[7],4*7(%rsp)
+	movdqa	%xmm1,4*8(%rsp)
+	mov	@x[12],4*12(%rsp)
+	mov	@x[13],4*13(%rsp)
+	mov	@x[14],4*14(%rsp)
+	mov	@x[15],4*15(%rsp)
+
+.Loop_tail:
+	movzb	($inp,%rbx),%eax
+	movzb	(%rsp,%rbx),%edx
+	lea	1(%rbx),%rbx
+	xor	%edx,%eax
+	mov	%al,-1($out,%rbx)
+	dec	%rbp
+	jnz	.Loop_tail
+
+.Ldone:
+	lea	64+24+48(%rsp),%rsi
+	mov	-48(%rsi),%r15
+	mov	-40(%rsi),%r14
+	mov	-32(%rsi),%r13
+	mov	-24(%rsi),%r12
+	mov	-16(%rsi),%rbp
+	mov	-8(%rsi),%rbx
+	lea	(%rsi),%rsp
+.Lno_data:
+	ret
+.size	ChaCha20_ctr32,.-ChaCha20_ctr32
+___
+
+########################################################################
+# SSSE3 code path that handles shorter lengths
+{
+my ($a,$b,$c,$d,$t,$t1,$rot16,$rot24)=map("%xmm$_",(0..7));
+
+sub SSSE3ROUND {	# critical path is 20 "SIMD ticks" per round
+	&paddd	($a,$b);
+	&pxor	($d,$a);
+	&pshufb	($d,$rot16);
+
+	&paddd	($c,$d);
+	&pxor	($b,$c);
+	&movdqa	($t,$b);
+	&psrld	($b,20);
+	&pslld	($t,12);
+	&por	($b,$t);
+
+	&paddd	($a,$b);
+	&pxor	($d,$a);
+	&pshufb	($d,$rot24);
+
+	&paddd	($c,$d);
+	&pxor	($b,$c);
+	&movdqa	($t,$b);
+	&psrld	($b,25);
+	&pslld	($t,7);
+	&por	($b,$t);
+}
+
+my $xframe = $win64 ? 32+8 : 8;
+
+$code.=<<___;
+.type	ChaCha20_ssse3,\@function,5
+.align	32
+ChaCha20_ssse3:
+.LChaCha20_ssse3:
+	mov	%rsp,%r9		# frame pointer
+___
+$code.=<<___;
+	cmp	\$128,$len		# we might throw away some data,
+	ja	.LChaCha20_4x		# but overall it won't be slower
+
+.Ldo_sse3_after_all:
+	sub	\$64+$xframe,%rsp
+___
+$code.=<<___	if ($win64);
+	movaps	%xmm6,-0x28(%r9)
+	movaps	%xmm7,-0x18(%r9)
+.Lssse3_body:
+___
+$code.=<<___;
+	movdqa	.Lsigma(%rip),$a
+	movdqu	($key),$b
+	movdqu	16($key),$c
+	movdqu	($counter),$d
+	movdqa	.Lrot16(%rip),$rot16
+	movdqa	.Lrot24(%rip),$rot24
+
+	movdqa	$a,0x00(%rsp)
+	movdqa	$b,0x10(%rsp)
+	movdqa	$c,0x20(%rsp)
+	movdqa	$d,0x30(%rsp)
+	mov	\$10,$counter		# reuse $counter
+	jmp	.Loop_ssse3
+
+.align	32
+.Loop_outer_ssse3:
+	movdqa	.Lone(%rip),$d
+	movdqa	0x00(%rsp),$a
+	movdqa	0x10(%rsp),$b
+	movdqa	0x20(%rsp),$c
+	paddd	0x30(%rsp),$d
+	mov	\$10,$counter
+	movdqa	$d,0x30(%rsp)
+	jmp	.Loop_ssse3
+
+.align	32
+.Loop_ssse3:
+___
+	&SSSE3ROUND();
+	&pshufd	($c,$c,0b01001110);
+	&pshufd	($b,$b,0b00111001);
+	&pshufd	($d,$d,0b10010011);
+	&nop	();
+
+	&SSSE3ROUND();
+	&pshufd	($c,$c,0b01001110);
+	&pshufd	($b,$b,0b10010011);
+	&pshufd	($d,$d,0b00111001);
+
+	&dec	($counter);
+	&jnz	(".Loop_ssse3");
+
+$code.=<<___;
+	paddd	0x00(%rsp),$a
+	paddd	0x10(%rsp),$b
+	paddd	0x20(%rsp),$c
+	paddd	0x30(%rsp),$d
+
+	cmp	\$64,$len
+	jb	.Ltail_ssse3
+
+	movdqu	0x00($inp),$t
+	movdqu	0x10($inp),$t1
+	pxor	$t,$a			# xor with input
+	movdqu	0x20($inp),$t
+	pxor	$t1,$b
+	movdqu	0x30($inp),$t1
+	lea	0x40($inp),$inp		# inp+=64
+	pxor	$t,$c
+	pxor	$t1,$d
+
+	movdqu	$a,0x00($out)		# write output
+	movdqu	$b,0x10($out)
+	movdqu	$c,0x20($out)
+	movdqu	$d,0x30($out)
+	lea	0x40($out),$out		# out+=64
+
+	sub	\$64,$len
+	jnz	.Loop_outer_ssse3
+
+	jmp	.Ldone_ssse3
+
+.align	16
+.Ltail_ssse3:
+	movdqa	$a,0x00(%rsp)
+	movdqa	$b,0x10(%rsp)
+	movdqa	$c,0x20(%rsp)
+	movdqa	$d,0x30(%rsp)
+	xor	$counter,$counter
+
+.Loop_tail_ssse3:
+	movzb	($inp,$counter),%eax
+	movzb	(%rsp,$counter),%ecx
+	lea	1($counter),$counter
+	xor	%ecx,%eax
+	mov	%al,-1($out,$counter)
+	dec	$len
+	jnz	.Loop_tail_ssse3
+
+.Ldone_ssse3:
+___
+$code.=<<___	if ($win64);
+	movaps	-0x28(%r9),%xmm6
+	movaps	-0x18(%r9),%xmm7
+___
+$code.=<<___;
+	lea	(%r9),%rsp
+.Lssse3_epilogue:
+	ret
+.size	ChaCha20_ssse3,.-ChaCha20_ssse3
+___
+}
+
+########################################################################
+# SSSE3 code path that handles longer messages.
+{
+# assign variables to favor Atom front-end
+my ($xd0,$xd1,$xd2,$xd3, $xt0,$xt1,$xt2,$xt3,
+    $xa0,$xa1,$xa2,$xa3, $xb0,$xb1,$xb2,$xb3)=map("%xmm$_",(0..15));
+my  @xx=($xa0,$xa1,$xa2,$xa3, $xb0,$xb1,$xb2,$xb3,
+	"%nox","%nox","%nox","%nox", $xd0,$xd1,$xd2,$xd3);
+
+sub SSSE3_lane_ROUND {
+my ($a0,$b0,$c0,$d0)=@_;
+my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0));
+my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1));
+my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2));
+my ($xc,$xc_,$t0,$t1)=map("\"$_\"",$xt0,$xt1,$xt2,$xt3);
+my @x=map("\"$_\"",@xx);
+
+	# Consider order in which variables are addressed by their
+	# index:
+	#
+	#	a   b   c   d
+	#
+	#	0   4   8  12 < even round
+	#	1   5   9  13
+	#	2   6  10  14
+	#	3   7  11  15
+	#	0   5  10  15 < odd round
+	#	1   6  11  12
+	#	2   7   8  13
+	#	3   4   9  14
+	#
+	# 'a', 'b' and 'd's are permanently allocated in registers,
+	# @x[0..7,12..15], while 'c's are maintained in memory. If
+	# you observe 'c' column, you'll notice that pair of 'c's is
+	# invariant between rounds. This means that we have to reload
+	# them once per round, in the middle. This is why you'll see
+	# bunch of 'c' stores and loads in the middle, but none in
+	# the beginning or end.
+
+	(
+	"&paddd		(@x[$a0],@x[$b0])",	# Q1
+	 "&paddd	(@x[$a1],@x[$b1])",	# Q2
+	"&pxor		(@x[$d0],@x[$a0])",
+	 "&pxor		(@x[$d1],@x[$a1])",
+	"&pshufb	(@x[$d0],$t1)",
+	 "&pshufb	(@x[$d1],$t1)",
+
+	"&paddd		($xc,@x[$d0])",
+	 "&paddd	($xc_,@x[$d1])",
+	"&pxor		(@x[$b0],$xc)",
+	 "&pxor		(@x[$b1],$xc_)",
+	"&movdqa	($t0,@x[$b0])",
+	"&pslld		(@x[$b0],12)",
+	"&psrld		($t0,20)",
+	 "&movdqa	($t1,@x[$b1])",
+	 "&pslld	(@x[$b1],12)",
+	"&por		(@x[$b0],$t0)",
+	 "&psrld	($t1,20)",
+	"&movdqa	($t0,'(%r11)')",	# .Lrot24(%rip)
+	 "&por		(@x[$b1],$t1)",
+
+	"&paddd		(@x[$a0],@x[$b0])",
+	 "&paddd	(@x[$a1],@x[$b1])",
+	"&pxor		(@x[$d0],@x[$a0])",
+	 "&pxor		(@x[$d1],@x[$a1])",
+	"&pshufb	(@x[$d0],$t0)",
+	 "&pshufb	(@x[$d1],$t0)",
+
+	"&paddd		($xc,@x[$d0])",
+	 "&paddd	($xc_,@x[$d1])",
+	"&pxor		(@x[$b0],$xc)",
+	 "&pxor		(@x[$b1],$xc_)",
+	"&movdqa	($t1,@x[$b0])",
+	"&pslld		(@x[$b0],7)",
+	"&psrld		($t1,25)",
+	 "&movdqa	($t0,@x[$b1])",
+	 "&pslld	(@x[$b1],7)",
+	"&por		(@x[$b0],$t1)",
+	 "&psrld	($t0,25)",
+	"&movdqa	($t1,'(%r10)')",	# .Lrot16(%rip)
+	 "&por		(@x[$b1],$t0)",
+
+	"&movdqa	(\"`16*($c0-8)`(%rsp)\",$xc)",	# reload pair of 'c's
+	 "&movdqa	(\"`16*($c1-8)`(%rsp)\",$xc_)",
+	"&movdqa	($xc,\"`16*($c2-8)`(%rsp)\")",
+	 "&movdqa	($xc_,\"`16*($c3-8)`(%rsp)\")",
+
+	"&paddd		(@x[$a2],@x[$b2])",	# Q3
+	 "&paddd	(@x[$a3],@x[$b3])",	# Q4
+	"&pxor		(@x[$d2],@x[$a2])",
+	 "&pxor		(@x[$d3],@x[$a3])",
+	"&pshufb	(@x[$d2],$t1)",
+	 "&pshufb	(@x[$d3],$t1)",
+
+	"&paddd		($xc,@x[$d2])",
+	 "&paddd	($xc_,@x[$d3])",
+	"&pxor		(@x[$b2],$xc)",
+	 "&pxor		(@x[$b3],$xc_)",
+	"&movdqa	($t0,@x[$b2])",
+	"&pslld		(@x[$b2],12)",
+	"&psrld		($t0,20)",
+	 "&movdqa	($t1,@x[$b3])",
+	 "&pslld	(@x[$b3],12)",
+	"&por		(@x[$b2],$t0)",
+	 "&psrld	($t1,20)",
+	"&movdqa	($t0,'(%r11)')",	# .Lrot24(%rip)
+	 "&por		(@x[$b3],$t1)",
+
+	"&paddd		(@x[$a2],@x[$b2])",
+	 "&paddd	(@x[$a3],@x[$b3])",
+	"&pxor		(@x[$d2],@x[$a2])",
+	 "&pxor		(@x[$d3],@x[$a3])",
+	"&pshufb	(@x[$d2],$t0)",
+	 "&pshufb	(@x[$d3],$t0)",
+
+	"&paddd		($xc,@x[$d2])",
+	 "&paddd	($xc_,@x[$d3])",
+	"&pxor		(@x[$b2],$xc)",
+	 "&pxor		(@x[$b3],$xc_)",
+	"&movdqa	($t1,@x[$b2])",
+	"&pslld		(@x[$b2],7)",
+	"&psrld		($t1,25)",
+	 "&movdqa	($t0,@x[$b3])",
+	 "&pslld	(@x[$b3],7)",
+	"&por		(@x[$b2],$t1)",
+	 "&psrld	($t0,25)",
+	"&movdqa	($t1,'(%r10)')",	# .Lrot16(%rip)
+	 "&por		(@x[$b3],$t0)"
+	);
+}
+
+my $xframe = $win64 ? 0xa8 : 8;
+
+$code.=<<___;
+.type	ChaCha20_4x,\@function,5
+.align	32
+ChaCha20_4x:
+.LChaCha20_4x:
+	mov		%rsp,%r9		# frame pointer
+	mov		%r10,%r11
+___
+$code.=<<___	if ($avx>1);
+	shr		\$32,%r10		# OPENSSL_ia32cap_P+8
+	test		\$`1<<5`,%r10		# test AVX2
+	jnz		.LChaCha20_8x
+___
+$code.=<<___;
+	cmp		\$192,$len
+	ja		.Lproceed4x
+
+	and		\$`1<<26|1<<22`,%r11	# isolate XSAVE+MOVBE
+	cmp		\$`1<<22`,%r11		# check for MOVBE without XSAVE
+	je		.Ldo_sse3_after_all	# to detect Atom
+
+.Lproceed4x:
+	sub		\$0x140+$xframe,%rsp
+___
+	################ stack layout
+	# +0x00		SIMD equivalent of @x[8-12]
+	# ...
+	# +0x40		constant copy of key[0-2] smashed by lanes
+	# ...
+	# +0x100	SIMD counters (with nonce smashed by lanes)
+	# ...
+	# +0x140
+$code.=<<___	if ($win64);
+	movaps		%xmm6,-0xa8(%r9)
+	movaps		%xmm7,-0x98(%r9)
+	movaps		%xmm8,-0x88(%r9)
+	movaps		%xmm9,-0x78(%r9)
+	movaps		%xmm10,-0x68(%r9)
+	movaps		%xmm11,-0x58(%r9)
+	movaps		%xmm12,-0x48(%r9)
+	movaps		%xmm13,-0x38(%r9)
+	movaps		%xmm14,-0x28(%r9)
+	movaps		%xmm15,-0x18(%r9)
+.L4x_body:
+___
+$code.=<<___;
+	movdqa		.Lsigma(%rip),$xa3	# key[0]
+	movdqu		($key),$xb3		# key[1]
+	movdqu		16($key),$xt3		# key[2]
+	movdqu		($counter),$xd3		# key[3]
+	lea		0x100(%rsp),%rcx	# size optimization
+	lea		.Lrot16(%rip),%r10
+	lea		.Lrot24(%rip),%r11
+
+	pshufd		\$0x00,$xa3,$xa0	# smash key by lanes...
+	pshufd		\$0x55,$xa3,$xa1
+	movdqa		$xa0,0x40(%rsp)		# ... and offload
+	pshufd		\$0xaa,$xa3,$xa2
+	movdqa		$xa1,0x50(%rsp)
+	pshufd		\$0xff,$xa3,$xa3
+	movdqa		$xa2,0x60(%rsp)
+	movdqa		$xa3,0x70(%rsp)
+
+	pshufd		\$0x00,$xb3,$xb0
+	pshufd		\$0x55,$xb3,$xb1
+	movdqa		$xb0,0x80-0x100(%rcx)
+	pshufd		\$0xaa,$xb3,$xb2
+	movdqa		$xb1,0x90-0x100(%rcx)
+	pshufd		\$0xff,$xb3,$xb3
+	movdqa		$xb2,0xa0-0x100(%rcx)
+	movdqa		$xb3,0xb0-0x100(%rcx)
+
+	pshufd		\$0x00,$xt3,$xt0	# "$xc0"
+	pshufd		\$0x55,$xt3,$xt1	# "$xc1"
+	movdqa		$xt0,0xc0-0x100(%rcx)
+	pshufd		\$0xaa,$xt3,$xt2	# "$xc2"
+	movdqa		$xt1,0xd0-0x100(%rcx)
+	pshufd		\$0xff,$xt3,$xt3	# "$xc3"
+	movdqa		$xt2,0xe0-0x100(%rcx)
+	movdqa		$xt3,0xf0-0x100(%rcx)
+
+	pshufd		\$0x00,$xd3,$xd0
+	pshufd		\$0x55,$xd3,$xd1
+	paddd		.Linc(%rip),$xd0	# don't save counters yet
+	pshufd		\$0xaa,$xd3,$xd2
+	movdqa		$xd1,0x110-0x100(%rcx)
+	pshufd		\$0xff,$xd3,$xd3
+	movdqa		$xd2,0x120-0x100(%rcx)
+	movdqa		$xd3,0x130-0x100(%rcx)
+
+	jmp		.Loop_enter4x
+
+.align	32
+.Loop_outer4x:
+	movdqa		0x40(%rsp),$xa0		# re-load smashed key
+	movdqa		0x50(%rsp),$xa1
+	movdqa		0x60(%rsp),$xa2
+	movdqa		0x70(%rsp),$xa3
+	movdqa		0x80-0x100(%rcx),$xb0
+	movdqa		0x90-0x100(%rcx),$xb1
+	movdqa		0xa0-0x100(%rcx),$xb2
+	movdqa		0xb0-0x100(%rcx),$xb3
+	movdqa		0xc0-0x100(%rcx),$xt0	# "$xc0"
+	movdqa		0xd0-0x100(%rcx),$xt1	# "$xc1"
+	movdqa		0xe0-0x100(%rcx),$xt2	# "$xc2"
+	movdqa		0xf0-0x100(%rcx),$xt3	# "$xc3"
+	movdqa		0x100-0x100(%rcx),$xd0
+	movdqa		0x110-0x100(%rcx),$xd1
+	movdqa		0x120-0x100(%rcx),$xd2
+	movdqa		0x130-0x100(%rcx),$xd3
+	paddd		.Lfour(%rip),$xd0	# next SIMD counters
+
+.Loop_enter4x:
+	movdqa		$xt2,0x20(%rsp)		# SIMD equivalent of "@x[10]"
+	movdqa		$xt3,0x30(%rsp)		# SIMD equivalent of "@x[11]"
+	movdqa		(%r10),$xt3		# .Lrot16(%rip)
+	mov		\$10,%eax
+	movdqa		$xd0,0x100-0x100(%rcx)	# save SIMD counters
+	jmp		.Loop4x
+
+.align	32
+.Loop4x:
+___
+	foreach (&SSSE3_lane_ROUND(0, 4, 8,12)) { eval; }
+	foreach (&SSSE3_lane_ROUND(0, 5,10,15)) { eval; }
+$code.=<<___;
+	dec		%eax
+	jnz		.Loop4x
+
+	paddd		0x40(%rsp),$xa0		# accumulate key material
+	paddd		0x50(%rsp),$xa1
+	paddd		0x60(%rsp),$xa2
+	paddd		0x70(%rsp),$xa3
+
+	movdqa		$xa0,$xt2		# "de-interlace" data
+	punpckldq	$xa1,$xa0
+	movdqa		$xa2,$xt3
+	punpckldq	$xa3,$xa2
+	punpckhdq	$xa1,$xt2
+	punpckhdq	$xa3,$xt3
+	movdqa		$xa0,$xa1
+	punpcklqdq	$xa2,$xa0		# "a0"
+	movdqa		$xt2,$xa3
+	punpcklqdq	$xt3,$xt2		# "a2"
+	punpckhqdq	$xa2,$xa1		# "a1"
+	punpckhqdq	$xt3,$xa3		# "a3"
+___
+	($xa2,$xt2)=($xt2,$xa2);
+$code.=<<___;
+	paddd		0x80-0x100(%rcx),$xb0
+	paddd		0x90-0x100(%rcx),$xb1
+	paddd		0xa0-0x100(%rcx),$xb2
+	paddd		0xb0-0x100(%rcx),$xb3
+
+	movdqa		$xa0,0x00(%rsp)		# offload $xaN
+	movdqa		$xa1,0x10(%rsp)
+	movdqa		0x20(%rsp),$xa0		# "xc2"
+	movdqa		0x30(%rsp),$xa1		# "xc3"
+
+	movdqa		$xb0,$xt2
+	punpckldq	$xb1,$xb0
+	movdqa		$xb2,$xt3
+	punpckldq	$xb3,$xb2
+	punpckhdq	$xb1,$xt2
+	punpckhdq	$xb3,$xt3
+	movdqa		$xb0,$xb1
+	punpcklqdq	$xb2,$xb0		# "b0"
+	movdqa		$xt2,$xb3
+	punpcklqdq	$xt3,$xt2		# "b2"
+	punpckhqdq	$xb2,$xb1		# "b1"
+	punpckhqdq	$xt3,$xb3		# "b3"
+___
+	($xb2,$xt2)=($xt2,$xb2);
+	my ($xc0,$xc1,$xc2,$xc3)=($xt0,$xt1,$xa0,$xa1);
+$code.=<<___;
+	paddd		0xc0-0x100(%rcx),$xc0
+	paddd		0xd0-0x100(%rcx),$xc1
+	paddd		0xe0-0x100(%rcx),$xc2
+	paddd		0xf0-0x100(%rcx),$xc3
+
+	movdqa		$xa2,0x20(%rsp)		# keep offloading $xaN
+	movdqa		$xa3,0x30(%rsp)
+
+	movdqa		$xc0,$xt2
+	punpckldq	$xc1,$xc0
+	movdqa		$xc2,$xt3
+	punpckldq	$xc3,$xc2
+	punpckhdq	$xc1,$xt2
+	punpckhdq	$xc3,$xt3
+	movdqa		$xc0,$xc1
+	punpcklqdq	$xc2,$xc0		# "c0"
+	movdqa		$xt2,$xc3
+	punpcklqdq	$xt3,$xt2		# "c2"
+	punpckhqdq	$xc2,$xc1		# "c1"
+	punpckhqdq	$xt3,$xc3		# "c3"
+___
+	($xc2,$xt2)=($xt2,$xc2);
+	($xt0,$xt1)=($xa2,$xa3);		# use $xaN as temporary
+$code.=<<___;
+	paddd		0x100-0x100(%rcx),$xd0
+	paddd		0x110-0x100(%rcx),$xd1
+	paddd		0x120-0x100(%rcx),$xd2
+	paddd		0x130-0x100(%rcx),$xd3
+
+	movdqa		$xd0,$xt2
+	punpckldq	$xd1,$xd0
+	movdqa		$xd2,$xt3
+	punpckldq	$xd3,$xd2
+	punpckhdq	$xd1,$xt2
+	punpckhdq	$xd3,$xt3
+	movdqa		$xd0,$xd1
+	punpcklqdq	$xd2,$xd0		# "d0"
+	movdqa		$xt2,$xd3
+	punpcklqdq	$xt3,$xt2		# "d2"
+	punpckhqdq	$xd2,$xd1		# "d1"
+	punpckhqdq	$xt3,$xd3		# "d3"
+___
+	($xd2,$xt2)=($xt2,$xd2);
+$code.=<<___;
+	cmp		\$64*4,$len
+	jb		.Ltail4x
+
+	movdqu		0x00($inp),$xt0		# xor with input
+	movdqu		0x10($inp),$xt1
+	movdqu		0x20($inp),$xt2
+	movdqu		0x30($inp),$xt3
+	pxor		0x00(%rsp),$xt0		# $xaN is offloaded, remember?
+	pxor		$xb0,$xt1
+	pxor		$xc0,$xt2
+	pxor		$xd0,$xt3
+
+	 movdqu		$xt0,0x00($out)
+	movdqu		0x40($inp),$xt0
+	 movdqu		$xt1,0x10($out)
+	movdqu		0x50($inp),$xt1
+	 movdqu		$xt2,0x20($out)
+	movdqu		0x60($inp),$xt2
+	 movdqu		$xt3,0x30($out)
+	movdqu		0x70($inp),$xt3
+	lea		0x80($inp),$inp		# size optimization
+	pxor		0x10(%rsp),$xt0
+	pxor		$xb1,$xt1
+	pxor		$xc1,$xt2
+	pxor		$xd1,$xt3
+
+	 movdqu		$xt0,0x40($out)
+	movdqu		0x00($inp),$xt0
+	 movdqu		$xt1,0x50($out)
+	movdqu		0x10($inp),$xt1
+	 movdqu		$xt2,0x60($out)
+	movdqu		0x20($inp),$xt2
+	 movdqu		$xt3,0x70($out)
+	 lea		0x80($out),$out		# size optimization
+	movdqu		0x30($inp),$xt3
+	pxor		0x20(%rsp),$xt0
+	pxor		$xb2,$xt1
+	pxor		$xc2,$xt2
+	pxor		$xd2,$xt3
+
+	 movdqu		$xt0,0x00($out)
+	movdqu		0x40($inp),$xt0
+	 movdqu		$xt1,0x10($out)
+	movdqu		0x50($inp),$xt1
+	 movdqu		$xt2,0x20($out)
+	movdqu		0x60($inp),$xt2
+	 movdqu		$xt3,0x30($out)
+	movdqu		0x70($inp),$xt3
+	lea		0x80($inp),$inp		# inp+=64*4
+	pxor		0x30(%rsp),$xt0
+	pxor		$xb3,$xt1
+	pxor		$xc3,$xt2
+	pxor		$xd3,$xt3
+	movdqu		$xt0,0x40($out)
+	movdqu		$xt1,0x50($out)
+	movdqu		$xt2,0x60($out)
+	movdqu		$xt3,0x70($out)
+	lea		0x80($out),$out		# out+=64*4
+
+	sub		\$64*4,$len
+	jnz		.Loop_outer4x
+
+	jmp		.Ldone4x
+
+.Ltail4x:
+	cmp		\$192,$len
+	jae		.L192_or_more4x
+	cmp		\$128,$len
+	jae		.L128_or_more4x
+	cmp		\$64,$len
+	jae		.L64_or_more4x
+
+	#movdqa		0x00(%rsp),$xt0		# $xaN is offloaded, remember?
+	xor		%r10,%r10
+	#movdqa		$xt0,0x00(%rsp)
+	movdqa		$xb0,0x10(%rsp)
+	movdqa		$xc0,0x20(%rsp)
+	movdqa		$xd0,0x30(%rsp)
+	jmp		.Loop_tail4x
+
+.align	32
+.L64_or_more4x:
+	movdqu		0x00($inp),$xt0		# xor with input
+	movdqu		0x10($inp),$xt1
+	movdqu		0x20($inp),$xt2
+	movdqu		0x30($inp),$xt3
+	pxor		0x00(%rsp),$xt0		# $xaxN is offloaded, remember?
+	pxor		$xb0,$xt1
+	pxor		$xc0,$xt2
+	pxor		$xd0,$xt3
+	movdqu		$xt0,0x00($out)
+	movdqu		$xt1,0x10($out)
+	movdqu		$xt2,0x20($out)
+	movdqu		$xt3,0x30($out)
+	je		.Ldone4x
+
+	movdqa		0x10(%rsp),$xt0		# $xaN is offloaded, remember?
+	lea		0x40($inp),$inp		# inp+=64*1
+	xor		%r10,%r10
+	movdqa		$xt0,0x00(%rsp)
+	movdqa		$xb1,0x10(%rsp)
+	lea		0x40($out),$out		# out+=64*1
+	movdqa		$xc1,0x20(%rsp)
+	sub		\$64,$len		# len-=64*1
+	movdqa		$xd1,0x30(%rsp)
+	jmp		.Loop_tail4x
+
+.align	32
+.L128_or_more4x:
+	movdqu		0x00($inp),$xt0		# xor with input
+	movdqu		0x10($inp),$xt1
+	movdqu		0x20($inp),$xt2
+	movdqu		0x30($inp),$xt3
+	pxor		0x00(%rsp),$xt0		# $xaN is offloaded, remember?
+	pxor		$xb0,$xt1
+	pxor		$xc0,$xt2
+	pxor		$xd0,$xt3
+
+	 movdqu		$xt0,0x00($out)
+	movdqu		0x40($inp),$xt0
+	 movdqu		$xt1,0x10($out)
+	movdqu		0x50($inp),$xt1
+	 movdqu		$xt2,0x20($out)
+	movdqu		0x60($inp),$xt2
+	 movdqu		$xt3,0x30($out)
+	movdqu		0x70($inp),$xt3
+	pxor		0x10(%rsp),$xt0
+	pxor		$xb1,$xt1
+	pxor		$xc1,$xt2
+	pxor		$xd1,$xt3
+	movdqu		$xt0,0x40($out)
+	movdqu		$xt1,0x50($out)
+	movdqu		$xt2,0x60($out)
+	movdqu		$xt3,0x70($out)
+	je		.Ldone4x
+
+	movdqa		0x20(%rsp),$xt0		# $xaN is offloaded, remember?
+	lea		0x80($inp),$inp		# inp+=64*2
+	xor		%r10,%r10
+	movdqa		$xt0,0x00(%rsp)
+	movdqa		$xb2,0x10(%rsp)
+	lea		0x80($out),$out		# out+=64*2
+	movdqa		$xc2,0x20(%rsp)
+	sub		\$128,$len		# len-=64*2
+	movdqa		$xd2,0x30(%rsp)
+	jmp		.Loop_tail4x
+
+.align	32
+.L192_or_more4x:
+	movdqu		0x00($inp),$xt0		# xor with input
+	movdqu		0x10($inp),$xt1
+	movdqu		0x20($inp),$xt2
+	movdqu		0x30($inp),$xt3
+	pxor		0x00(%rsp),$xt0		# $xaN is offloaded, remember?
+	pxor		$xb0,$xt1
+	pxor		$xc0,$xt2
+	pxor		$xd0,$xt3
+
+	 movdqu		$xt0,0x00($out)
+	movdqu		0x40($inp),$xt0
+	 movdqu		$xt1,0x10($out)
+	movdqu		0x50($inp),$xt1
+	 movdqu		$xt2,0x20($out)
+	movdqu		0x60($inp),$xt2
+	 movdqu		$xt3,0x30($out)
+	movdqu		0x70($inp),$xt3
+	lea		0x80($inp),$inp		# size optimization
+	pxor		0x10(%rsp),$xt0
+	pxor		$xb1,$xt1
+	pxor		$xc1,$xt2
+	pxor		$xd1,$xt3
+
+	 movdqu		$xt0,0x40($out)
+	movdqu		0x00($inp),$xt0
+	 movdqu		$xt1,0x50($out)
+	movdqu		0x10($inp),$xt1
+	 movdqu		$xt2,0x60($out)
+	movdqu		0x20($inp),$xt2
+	 movdqu		$xt3,0x70($out)
+	 lea		0x80($out),$out		# size optimization
+	movdqu		0x30($inp),$xt3
+	pxor		0x20(%rsp),$xt0
+	pxor		$xb2,$xt1
+	pxor		$xc2,$xt2
+	pxor		$xd2,$xt3
+	movdqu		$xt0,0x00($out)
+	movdqu		$xt1,0x10($out)
+	movdqu		$xt2,0x20($out)
+	movdqu		$xt3,0x30($out)
+	je		.Ldone4x
+
+	movdqa		0x30(%rsp),$xt0		# $xaN is offloaded, remember?
+	lea		0x40($inp),$inp		# inp+=64*3
+	xor		%r10,%r10
+	movdqa		$xt0,0x00(%rsp)
+	movdqa		$xb3,0x10(%rsp)
+	lea		0x40($out),$out		# out+=64*3
+	movdqa		$xc3,0x20(%rsp)
+	sub		\$192,$len		# len-=64*3
+	movdqa		$xd3,0x30(%rsp)
+
+.Loop_tail4x:
+	movzb		($inp,%r10),%eax
+	movzb		(%rsp,%r10),%ecx
+	lea		1(%r10),%r10
+	xor		%ecx,%eax
+	mov		%al,-1($out,%r10)
+	dec		$len
+	jnz		.Loop_tail4x
+
+.Ldone4x:
+___
+$code.=<<___	if ($win64);
+	movaps		-0xa8(%r9),%xmm6
+	movaps		-0x98(%r9),%xmm7
+	movaps		-0x88(%r9),%xmm8
+	movaps		-0x78(%r9),%xmm9
+	movaps		-0x68(%r9),%xmm10
+	movaps		-0x58(%r9),%xmm11
+	movaps		-0x48(%r9),%xmm12
+	movaps		-0x38(%r9),%xmm13
+	movaps		-0x28(%r9),%xmm14
+	movaps		-0x18(%r9),%xmm15
+___
+$code.=<<___;
+	lea		(%r9),%rsp
+.L4x_epilogue:
+	ret
+.size	ChaCha20_4x,.-ChaCha20_4x
+___
+}
+
+########################################################################
+# AVX2 code path
+if ($avx>1) {
+my ($xb0,$xb1,$xb2,$xb3, $xd0,$xd1,$xd2,$xd3,
+    $xa0,$xa1,$xa2,$xa3, $xt0,$xt1,$xt2,$xt3)=map("%ymm$_",(0..15));
+my @xx=($xa0,$xa1,$xa2,$xa3, $xb0,$xb1,$xb2,$xb3,
+	"%nox","%nox","%nox","%nox", $xd0,$xd1,$xd2,$xd3);
+
+sub AVX2_lane_ROUND {
+my ($a0,$b0,$c0,$d0)=@_;
+my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0));
+my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1));
+my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2));
+my ($xc,$xc_,$t0,$t1)=map("\"$_\"",$xt0,$xt1,$xt2,$xt3);
+my @x=map("\"$_\"",@xx);
+
+	# Consider order in which variables are addressed by their
+	# index:
+	#
+	#	a   b   c   d
+	#
+	#	0   4   8  12 < even round
+	#	1   5   9  13
+	#	2   6  10  14
+	#	3   7  11  15
+	#	0   5  10  15 < odd round
+	#	1   6  11  12
+	#	2   7   8  13
+	#	3   4   9  14
+	#
+	# 'a', 'b' and 'd's are permanently allocated in registers,
+	# @x[0..7,12..15], while 'c's are maintained in memory. If
+	# you observe 'c' column, you'll notice that pair of 'c's is
+	# invariant between rounds. This means that we have to reload
+	# them once per round, in the middle. This is why you'll see
+	# bunch of 'c' stores and loads in the middle, but none in
+	# the beginning or end.
+
+	(
+	"&vpaddd	(@x[$a0],@x[$a0],@x[$b0])",	# Q1
+	"&vpxor		(@x[$d0],@x[$a0],@x[$d0])",
+	"&vpshufb	(@x[$d0],@x[$d0],$t1)",
+	 "&vpaddd	(@x[$a1],@x[$a1],@x[$b1])",	# Q2
+	 "&vpxor	(@x[$d1],@x[$a1],@x[$d1])",
+	 "&vpshufb	(@x[$d1],@x[$d1],$t1)",
+
+	"&vpaddd	($xc,$xc,@x[$d0])",
+	"&vpxor		(@x[$b0],$xc,@x[$b0])",
+	"&vpslld	($t0,@x[$b0],12)",
+	"&vpsrld	(@x[$b0],@x[$b0],20)",
+	"&vpor		(@x[$b0],$t0,@x[$b0])",
+	"&vbroadcasti128($t0,'(%r11)')",		# .Lrot24(%rip)
+	 "&vpaddd	($xc_,$xc_,@x[$d1])",
+	 "&vpxor	(@x[$b1],$xc_,@x[$b1])",
+	 "&vpslld	($t1,@x[$b1],12)",
+	 "&vpsrld	(@x[$b1],@x[$b1],20)",
+	 "&vpor		(@x[$b1],$t1,@x[$b1])",
+
+	"&vpaddd	(@x[$a0],@x[$a0],@x[$b0])",
+	"&vpxor		(@x[$d0],@x[$a0],@x[$d0])",
+	"&vpshufb	(@x[$d0],@x[$d0],$t0)",
+	 "&vpaddd	(@x[$a1],@x[$a1],@x[$b1])",
+	 "&vpxor	(@x[$d1],@x[$a1],@x[$d1])",
+	 "&vpshufb	(@x[$d1],@x[$d1],$t0)",
+
+	"&vpaddd	($xc,$xc,@x[$d0])",
+	"&vpxor		(@x[$b0],$xc,@x[$b0])",
+	"&vpslld	($t1,@x[$b0],7)",
+	"&vpsrld	(@x[$b0],@x[$b0],25)",
+	"&vpor		(@x[$b0],$t1,@x[$b0])",
+	"&vbroadcasti128($t1,'(%r10)')",		# .Lrot16(%rip)
+	 "&vpaddd	($xc_,$xc_,@x[$d1])",
+	 "&vpxor	(@x[$b1],$xc_,@x[$b1])",
+	 "&vpslld	($t0,@x[$b1],7)",
+	 "&vpsrld	(@x[$b1],@x[$b1],25)",
+	 "&vpor		(@x[$b1],$t0,@x[$b1])",
+
+	"&vmovdqa	(\"`32*($c0-8)`(%rsp)\",$xc)",	# reload pair of 'c's
+	 "&vmovdqa	(\"`32*($c1-8)`(%rsp)\",$xc_)",
+	"&vmovdqa	($xc,\"`32*($c2-8)`(%rsp)\")",
+	 "&vmovdqa	($xc_,\"`32*($c3-8)`(%rsp)\")",
+
+	"&vpaddd	(@x[$a2],@x[$a2],@x[$b2])",	# Q3
+	"&vpxor		(@x[$d2],@x[$a2],@x[$d2])",
+	"&vpshufb	(@x[$d2],@x[$d2],$t1)",
+	 "&vpaddd	(@x[$a3],@x[$a3],@x[$b3])",	# Q4
+	 "&vpxor	(@x[$d3],@x[$a3],@x[$d3])",
+	 "&vpshufb	(@x[$d3],@x[$d3],$t1)",
+
+	"&vpaddd	($xc,$xc,@x[$d2])",
+	"&vpxor		(@x[$b2],$xc,@x[$b2])",
+	"&vpslld	($t0,@x[$b2],12)",
+	"&vpsrld	(@x[$b2],@x[$b2],20)",
+	"&vpor		(@x[$b2],$t0,@x[$b2])",
+	"&vbroadcasti128($t0,'(%r11)')",		# .Lrot24(%rip)
+	 "&vpaddd	($xc_,$xc_,@x[$d3])",
+	 "&vpxor	(@x[$b3],$xc_,@x[$b3])",
+	 "&vpslld	($t1,@x[$b3],12)",
+	 "&vpsrld	(@x[$b3],@x[$b3],20)",
+	 "&vpor		(@x[$b3],$t1,@x[$b3])",
+
+	"&vpaddd	(@x[$a2],@x[$a2],@x[$b2])",
+	"&vpxor		(@x[$d2],@x[$a2],@x[$d2])",
+	"&vpshufb	(@x[$d2],@x[$d2],$t0)",
+	 "&vpaddd	(@x[$a3],@x[$a3],@x[$b3])",
+	 "&vpxor	(@x[$d3],@x[$a3],@x[$d3])",
+	 "&vpshufb	(@x[$d3],@x[$d3],$t0)",
+
+	"&vpaddd	($xc,$xc,@x[$d2])",
+	"&vpxor		(@x[$b2],$xc,@x[$b2])",
+	"&vpslld	($t1,@x[$b2],7)",
+	"&vpsrld	(@x[$b2],@x[$b2],25)",
+	"&vpor		(@x[$b2],$t1,@x[$b2])",
+	"&vbroadcasti128($t1,'(%r10)')",		# .Lrot16(%rip)
+	 "&vpaddd	($xc_,$xc_,@x[$d3])",
+	 "&vpxor	(@x[$b3],$xc_,@x[$b3])",
+	 "&vpslld	($t0,@x[$b3],7)",
+	 "&vpsrld	(@x[$b3],@x[$b3],25)",
+	 "&vpor		(@x[$b3],$t0,@x[$b3])"
+	);
+}
+
+my $xframe = $win64 ? 0xa8 : 8;
+
+$code.=<<___;
+.type	ChaCha20_8x,\@function,5
+.align	32
+ChaCha20_8x:
+.LChaCha20_8x:
+	mov		%rsp,%r9		# frame register
+	sub		\$0x280+$xframe,%rsp
+	and		\$-32,%rsp
+___
+$code.=<<___	if ($win64);
+	movaps		%xmm6,-0xa8(%r9)
+	movaps		%xmm7,-0x98(%r9)
+	movaps		%xmm8,-0x88(%r9)
+	movaps		%xmm9,-0x78(%r9)
+	movaps		%xmm10,-0x68(%r9)
+	movaps		%xmm11,-0x58(%r9)
+	movaps		%xmm12,-0x48(%r9)
+	movaps		%xmm13,-0x38(%r9)
+	movaps		%xmm14,-0x28(%r9)
+	movaps		%xmm15,-0x18(%r9)
+.L8x_body:
+___
+$code.=<<___;
+	vzeroupper
+
+	################ stack layout
+	# +0x00		SIMD equivalent of @x[8-12]
+	# ...
+	# +0x80		constant copy of key[0-2] smashed by lanes
+	# ...
+	# +0x200	SIMD counters (with nonce smashed by lanes)
+	# ...
+	# +0x280
+
+	vbroadcasti128	.Lsigma(%rip),$xa3	# key[0]
+	vbroadcasti128	($key),$xb3		# key[1]
+	vbroadcasti128	16($key),$xt3		# key[2]
+	vbroadcasti128	($counter),$xd3		# key[3]
+	lea		0x100(%rsp),%rcx	# size optimization
+	lea		0x200(%rsp),%rax	# size optimization
+	lea		.Lrot16(%rip),%r10
+	lea		.Lrot24(%rip),%r11
+
+	vpshufd		\$0x00,$xa3,$xa0	# smash key by lanes...
+	vpshufd		\$0x55,$xa3,$xa1
+	vmovdqa		$xa0,0x80-0x100(%rcx)	# ... and offload
+	vpshufd		\$0xaa,$xa3,$xa2
+	vmovdqa		$xa1,0xa0-0x100(%rcx)
+	vpshufd		\$0xff,$xa3,$xa3
+	vmovdqa		$xa2,0xc0-0x100(%rcx)
+	vmovdqa		$xa3,0xe0-0x100(%rcx)
+
+	vpshufd		\$0x00,$xb3,$xb0
+	vpshufd		\$0x55,$xb3,$xb1
+	vmovdqa		$xb0,0x100-0x100(%rcx)
+	vpshufd		\$0xaa,$xb3,$xb2
+	vmovdqa		$xb1,0x120-0x100(%rcx)
+	vpshufd		\$0xff,$xb3,$xb3
+	vmovdqa		$xb2,0x140-0x100(%rcx)
+	vmovdqa		$xb3,0x160-0x100(%rcx)
+
+	vpshufd		\$0x00,$xt3,$xt0	# "xc0"
+	vpshufd		\$0x55,$xt3,$xt1	# "xc1"
+	vmovdqa		$xt0,0x180-0x200(%rax)
+	vpshufd		\$0xaa,$xt3,$xt2	# "xc2"
+	vmovdqa		$xt1,0x1a0-0x200(%rax)
+	vpshufd		\$0xff,$xt3,$xt3	# "xc3"
+	vmovdqa		$xt2,0x1c0-0x200(%rax)
+	vmovdqa		$xt3,0x1e0-0x200(%rax)
+
+	vpshufd		\$0x00,$xd3,$xd0
+	vpshufd		\$0x55,$xd3,$xd1
+	vpaddd		.Lincy(%rip),$xd0,$xd0	# don't save counters yet
+	vpshufd		\$0xaa,$xd3,$xd2
+	vmovdqa		$xd1,0x220-0x200(%rax)
+	vpshufd		\$0xff,$xd3,$xd3
+	vmovdqa		$xd2,0x240-0x200(%rax)
+	vmovdqa		$xd3,0x260-0x200(%rax)
+
+	jmp		.Loop_enter8x
+
+.align	32
+.Loop_outer8x:
+	vmovdqa		0x80-0x100(%rcx),$xa0	# re-load smashed key
+	vmovdqa		0xa0-0x100(%rcx),$xa1
+	vmovdqa		0xc0-0x100(%rcx),$xa2
+	vmovdqa		0xe0-0x100(%rcx),$xa3
+	vmovdqa		0x100-0x100(%rcx),$xb0
+	vmovdqa		0x120-0x100(%rcx),$xb1
+	vmovdqa		0x140-0x100(%rcx),$xb2
+	vmovdqa		0x160-0x100(%rcx),$xb3
+	vmovdqa		0x180-0x200(%rax),$xt0	# "xc0"
+	vmovdqa		0x1a0-0x200(%rax),$xt1	# "xc1"
+	vmovdqa		0x1c0-0x200(%rax),$xt2	# "xc2"
+	vmovdqa		0x1e0-0x200(%rax),$xt3	# "xc3"
+	vmovdqa		0x200-0x200(%rax),$xd0
+	vmovdqa		0x220-0x200(%rax),$xd1
+	vmovdqa		0x240-0x200(%rax),$xd2
+	vmovdqa		0x260-0x200(%rax),$xd3
+	vpaddd		.Leight(%rip),$xd0,$xd0	# next SIMD counters
+
+.Loop_enter8x:
+	vmovdqa		$xt2,0x40(%rsp)		# SIMD equivalent of "@x[10]"
+	vmovdqa		$xt3,0x60(%rsp)		# SIMD equivalent of "@x[11]"
+	vbroadcasti128	(%r10),$xt3
+	vmovdqa		$xd0,0x200-0x200(%rax)	# save SIMD counters
+	mov		\$10,%eax
+	jmp		.Loop8x
+
+.align	32
+.Loop8x:
+___
+	foreach (&AVX2_lane_ROUND(0, 4, 8,12)) { eval; }
+	foreach (&AVX2_lane_ROUND(0, 5,10,15)) { eval; }
+$code.=<<___;
+	dec		%eax
+	jnz		.Loop8x
+
+	lea		0x200(%rsp),%rax	# size optimization
+	vpaddd		0x80-0x100(%rcx),$xa0,$xa0	# accumulate key
+	vpaddd		0xa0-0x100(%rcx),$xa1,$xa1
+	vpaddd		0xc0-0x100(%rcx),$xa2,$xa2
+	vpaddd		0xe0-0x100(%rcx),$xa3,$xa3
+
+	vpunpckldq	$xa1,$xa0,$xt2		# "de-interlace" data
+	vpunpckldq	$xa3,$xa2,$xt3
+	vpunpckhdq	$xa1,$xa0,$xa0
+	vpunpckhdq	$xa3,$xa2,$xa2
+	vpunpcklqdq	$xt3,$xt2,$xa1		# "a0"
+	vpunpckhqdq	$xt3,$xt2,$xt2		# "a1"
+	vpunpcklqdq	$xa2,$xa0,$xa3		# "a2"
+	vpunpckhqdq	$xa2,$xa0,$xa0		# "a3"
+___
+	($xa0,$xa1,$xa2,$xa3,$xt2)=($xa1,$xt2,$xa3,$xa0,$xa2);
+$code.=<<___;
+	vpaddd		0x100-0x100(%rcx),$xb0,$xb0
+	vpaddd		0x120-0x100(%rcx),$xb1,$xb1
+	vpaddd		0x140-0x100(%rcx),$xb2,$xb2
+	vpaddd		0x160-0x100(%rcx),$xb3,$xb3
+
+	vpunpckldq	$xb1,$xb0,$xt2
+	vpunpckldq	$xb3,$xb2,$xt3
+	vpunpckhdq	$xb1,$xb0,$xb0
+	vpunpckhdq	$xb3,$xb2,$xb2
+	vpunpcklqdq	$xt3,$xt2,$xb1		# "b0"
+	vpunpckhqdq	$xt3,$xt2,$xt2		# "b1"
+	vpunpcklqdq	$xb2,$xb0,$xb3		# "b2"
+	vpunpckhqdq	$xb2,$xb0,$xb0		# "b3"
+___
+	($xb0,$xb1,$xb2,$xb3,$xt2)=($xb1,$xt2,$xb3,$xb0,$xb2);
+$code.=<<___;
+	vperm2i128	\$0x20,$xb0,$xa0,$xt3	# "de-interlace" further
+	vperm2i128	\$0x31,$xb0,$xa0,$xb0
+	vperm2i128	\$0x20,$xb1,$xa1,$xa0
+	vperm2i128	\$0x31,$xb1,$xa1,$xb1
+	vperm2i128	\$0x20,$xb2,$xa2,$xa1
+	vperm2i128	\$0x31,$xb2,$xa2,$xb2
+	vperm2i128	\$0x20,$xb3,$xa3,$xa2
+	vperm2i128	\$0x31,$xb3,$xa3,$xb3
+___
+	($xa0,$xa1,$xa2,$xa3,$xt3)=($xt3,$xa0,$xa1,$xa2,$xa3);
+	my ($xc0,$xc1,$xc2,$xc3)=($xt0,$xt1,$xa0,$xa1);
+$code.=<<___;
+	vmovdqa		$xa0,0x00(%rsp)		# offload $xaN
+	vmovdqa		$xa1,0x20(%rsp)
+	vmovdqa		0x40(%rsp),$xc2		# $xa0
+	vmovdqa		0x60(%rsp),$xc3		# $xa1
+
+	vpaddd		0x180-0x200(%rax),$xc0,$xc0
+	vpaddd		0x1a0-0x200(%rax),$xc1,$xc1
+	vpaddd		0x1c0-0x200(%rax),$xc2,$xc2
+	vpaddd		0x1e0-0x200(%rax),$xc3,$xc3
+
+	vpunpckldq	$xc1,$xc0,$xt2
+	vpunpckldq	$xc3,$xc2,$xt3
+	vpunpckhdq	$xc1,$xc0,$xc0
+	vpunpckhdq	$xc3,$xc2,$xc2
+	vpunpcklqdq	$xt3,$xt2,$xc1		# "c0"
+	vpunpckhqdq	$xt3,$xt2,$xt2		# "c1"
+	vpunpcklqdq	$xc2,$xc0,$xc3		# "c2"
+	vpunpckhqdq	$xc2,$xc0,$xc0		# "c3"
+___
+	($xc0,$xc1,$xc2,$xc3,$xt2)=($xc1,$xt2,$xc3,$xc0,$xc2);
+$code.=<<___;
+	vpaddd		0x200-0x200(%rax),$xd0,$xd0
+	vpaddd		0x220-0x200(%rax),$xd1,$xd1
+	vpaddd		0x240-0x200(%rax),$xd2,$xd2
+	vpaddd		0x260-0x200(%rax),$xd3,$xd3
+
+	vpunpckldq	$xd1,$xd0,$xt2
+	vpunpckldq	$xd3,$xd2,$xt3
+	vpunpckhdq	$xd1,$xd0,$xd0
+	vpunpckhdq	$xd3,$xd2,$xd2
+	vpunpcklqdq	$xt3,$xt2,$xd1		# "d0"
+	vpunpckhqdq	$xt3,$xt2,$xt2		# "d1"
+	vpunpcklqdq	$xd2,$xd0,$xd3		# "d2"
+	vpunpckhqdq	$xd2,$xd0,$xd0		# "d3"
+___
+	($xd0,$xd1,$xd2,$xd3,$xt2)=($xd1,$xt2,$xd3,$xd0,$xd2);
+$code.=<<___;
+	vperm2i128	\$0x20,$xd0,$xc0,$xt3	# "de-interlace" further
+	vperm2i128	\$0x31,$xd0,$xc0,$xd0
+	vperm2i128	\$0x20,$xd1,$xc1,$xc0
+	vperm2i128	\$0x31,$xd1,$xc1,$xd1
+	vperm2i128	\$0x20,$xd2,$xc2,$xc1
+	vperm2i128	\$0x31,$xd2,$xc2,$xd2
+	vperm2i128	\$0x20,$xd3,$xc3,$xc2
+	vperm2i128	\$0x31,$xd3,$xc3,$xd3
+___
+	($xc0,$xc1,$xc2,$xc3,$xt3)=($xt3,$xc0,$xc1,$xc2,$xc3);
+	($xb0,$xb1,$xb2,$xb3,$xc0,$xc1,$xc2,$xc3)=
+	($xc0,$xc1,$xc2,$xc3,$xb0,$xb1,$xb2,$xb3);
+	($xa0,$xa1)=($xt2,$xt3);
+$code.=<<___;
+	vmovdqa		0x00(%rsp),$xa0		# $xaN was offloaded, remember?
+	vmovdqa		0x20(%rsp),$xa1
+
+	cmp		\$64*8,$len
+	jb		.Ltail8x
+
+	vpxor		0x00($inp),$xa0,$xa0	# xor with input
+	vpxor		0x20($inp),$xb0,$xb0
+	vpxor		0x40($inp),$xc0,$xc0
+	vpxor		0x60($inp),$xd0,$xd0
+	lea		0x80($inp),$inp		# size optimization
+	vmovdqu		$xa0,0x00($out)
+	vmovdqu		$xb0,0x20($out)
+	vmovdqu		$xc0,0x40($out)
+	vmovdqu		$xd0,0x60($out)
+	lea		0x80($out),$out		# size optimization
+
+	vpxor		0x00($inp),$xa1,$xa1
+	vpxor		0x20($inp),$xb1,$xb1
+	vpxor		0x40($inp),$xc1,$xc1
+	vpxor		0x60($inp),$xd1,$xd1
+	lea		0x80($inp),$inp		# size optimization
+	vmovdqu		$xa1,0x00($out)
+	vmovdqu		$xb1,0x20($out)
+	vmovdqu		$xc1,0x40($out)
+	vmovdqu		$xd1,0x60($out)
+	lea		0x80($out),$out		# size optimization
+
+	vpxor		0x00($inp),$xa2,$xa2
+	vpxor		0x20($inp),$xb2,$xb2
+	vpxor		0x40($inp),$xc2,$xc2
+	vpxor		0x60($inp),$xd2,$xd2
+	lea		0x80($inp),$inp		# size optimization
+	vmovdqu		$xa2,0x00($out)
+	vmovdqu		$xb2,0x20($out)
+	vmovdqu		$xc2,0x40($out)
+	vmovdqu		$xd2,0x60($out)
+	lea		0x80($out),$out		# size optimization
+
+	vpxor		0x00($inp),$xa3,$xa3
+	vpxor		0x20($inp),$xb3,$xb3
+	vpxor		0x40($inp),$xc3,$xc3
+	vpxor		0x60($inp),$xd3,$xd3
+	lea		0x80($inp),$inp		# size optimization
+	vmovdqu		$xa3,0x00($out)
+	vmovdqu		$xb3,0x20($out)
+	vmovdqu		$xc3,0x40($out)
+	vmovdqu		$xd3,0x60($out)
+	lea		0x80($out),$out		# size optimization
+
+	sub		\$64*8,$len
+	jnz		.Loop_outer8x
+
+	jmp		.Ldone8x
+
+.Ltail8x:
+	cmp		\$448,$len
+	jae		.L448_or_more8x
+	cmp		\$384,$len
+	jae		.L384_or_more8x
+	cmp		\$320,$len
+	jae		.L320_or_more8x
+	cmp		\$256,$len
+	jae		.L256_or_more8x
+	cmp		\$192,$len
+	jae		.L192_or_more8x
+	cmp		\$128,$len
+	jae		.L128_or_more8x
+	cmp		\$64,$len
+	jae		.L64_or_more8x
+
+	xor		%r10,%r10
+	vmovdqa		$xa0,0x00(%rsp)
+	vmovdqa		$xb0,0x20(%rsp)
+	jmp		.Loop_tail8x
+
+.align	32
+.L64_or_more8x:
+	vpxor		0x00($inp),$xa0,$xa0	# xor with input
+	vpxor		0x20($inp),$xb0,$xb0
+	vmovdqu		$xa0,0x00($out)
+	vmovdqu		$xb0,0x20($out)
+	je		.Ldone8x
+
+	lea		0x40($inp),$inp		# inp+=64*1
+	xor		%r10,%r10
+	vmovdqa		$xc0,0x00(%rsp)
+	lea		0x40($out),$out		# out+=64*1
+	sub		\$64,$len		# len-=64*1
+	vmovdqa		$xd0,0x20(%rsp)
+	jmp		.Loop_tail8x
+
+.align	32
+.L128_or_more8x:
+	vpxor		0x00($inp),$xa0,$xa0	# xor with input
+	vpxor		0x20($inp),$xb0,$xb0
+	vpxor		0x40($inp),$xc0,$xc0
+	vpxor		0x60($inp),$xd0,$xd0
+	vmovdqu		$xa0,0x00($out)
+	vmovdqu		$xb0,0x20($out)
+	vmovdqu		$xc0,0x40($out)
+	vmovdqu		$xd0,0x60($out)
+	je		.Ldone8x
+
+	lea		0x80($inp),$inp		# inp+=64*2
+	xor		%r10,%r10
+	vmovdqa		$xa1,0x00(%rsp)
+	lea		0x80($out),$out		# out+=64*2
+	sub		\$128,$len		# len-=64*2
+	vmovdqa		$xb1,0x20(%rsp)
+	jmp		.Loop_tail8x
+
+.align	32
+.L192_or_more8x:
+	vpxor		0x00($inp),$xa0,$xa0	# xor with input
+	vpxor		0x20($inp),$xb0,$xb0
+	vpxor		0x40($inp),$xc0,$xc0
+	vpxor		0x60($inp),$xd0,$xd0
+	vpxor		0x80($inp),$xa1,$xa1
+	vpxor		0xa0($inp),$xb1,$xb1
+	vmovdqu		$xa0,0x00($out)
+	vmovdqu		$xb0,0x20($out)
+	vmovdqu		$xc0,0x40($out)
+	vmovdqu		$xd0,0x60($out)
+	vmovdqu		$xa1,0x80($out)
+	vmovdqu		$xb1,0xa0($out)
+	je		.Ldone8x
+
+	lea		0xc0($inp),$inp		# inp+=64*3
+	xor		%r10,%r10
+	vmovdqa		$xc1,0x00(%rsp)
+	lea		0xc0($out),$out		# out+=64*3
+	sub		\$192,$len		# len-=64*3
+	vmovdqa		$xd1,0x20(%rsp)
+	jmp		.Loop_tail8x
+
+.align	32
+.L256_or_more8x:
+	vpxor		0x00($inp),$xa0,$xa0	# xor with input
+	vpxor		0x20($inp),$xb0,$xb0
+	vpxor		0x40($inp),$xc0,$xc0
+	vpxor		0x60($inp),$xd0,$xd0
+	vpxor		0x80($inp),$xa1,$xa1
+	vpxor		0xa0($inp),$xb1,$xb1
+	vpxor		0xc0($inp),$xc1,$xc1
+	vpxor		0xe0($inp),$xd1,$xd1
+	vmovdqu		$xa0,0x00($out)
+	vmovdqu		$xb0,0x20($out)
+	vmovdqu		$xc0,0x40($out)
+	vmovdqu		$xd0,0x60($out)
+	vmovdqu		$xa1,0x80($out)
+	vmovdqu		$xb1,0xa0($out)
+	vmovdqu		$xc1,0xc0($out)
+	vmovdqu		$xd1,0xe0($out)
+	je		.Ldone8x
+
+	lea		0x100($inp),$inp	# inp+=64*4
+	xor		%r10,%r10
+	vmovdqa		$xa2,0x00(%rsp)
+	lea		0x100($out),$out	# out+=64*4
+	sub		\$256,$len		# len-=64*4
+	vmovdqa		$xb2,0x20(%rsp)
+	jmp		.Loop_tail8x
+
+.align	32
+.L320_or_more8x:
+	vpxor		0x00($inp),$xa0,$xa0	# xor with input
+	vpxor		0x20($inp),$xb0,$xb0
+	vpxor		0x40($inp),$xc0,$xc0
+	vpxor		0x60($inp),$xd0,$xd0
+	vpxor		0x80($inp),$xa1,$xa1
+	vpxor		0xa0($inp),$xb1,$xb1
+	vpxor		0xc0($inp),$xc1,$xc1
+	vpxor		0xe0($inp),$xd1,$xd1
+	vpxor		0x100($inp),$xa2,$xa2
+	vpxor		0x120($inp),$xb2,$xb2
+	vmovdqu		$xa0,0x00($out)
+	vmovdqu		$xb0,0x20($out)
+	vmovdqu		$xc0,0x40($out)
+	vmovdqu		$xd0,0x60($out)
+	vmovdqu		$xa1,0x80($out)
+	vmovdqu		$xb1,0xa0($out)
+	vmovdqu		$xc1,0xc0($out)
+	vmovdqu		$xd1,0xe0($out)
+	vmovdqu		$xa2,0x100($out)
+	vmovdqu		$xb2,0x120($out)
+	je		.Ldone8x
+
+	lea		0x140($inp),$inp	# inp+=64*5
+	xor		%r10,%r10
+	vmovdqa		$xc2,0x00(%rsp)
+	lea		0x140($out),$out	# out+=64*5
+	sub		\$320,$len		# len-=64*5
+	vmovdqa		$xd2,0x20(%rsp)
+	jmp		.Loop_tail8x
+
+.align	32
+.L384_or_more8x:
+	vpxor		0x00($inp),$xa0,$xa0	# xor with input
+	vpxor		0x20($inp),$xb0,$xb0
+	vpxor		0x40($inp),$xc0,$xc0
+	vpxor		0x60($inp),$xd0,$xd0
+	vpxor		0x80($inp),$xa1,$xa1
+	vpxor		0xa0($inp),$xb1,$xb1
+	vpxor		0xc0($inp),$xc1,$xc1
+	vpxor		0xe0($inp),$xd1,$xd1
+	vpxor		0x100($inp),$xa2,$xa2
+	vpxor		0x120($inp),$xb2,$xb2
+	vpxor		0x140($inp),$xc2,$xc2
+	vpxor		0x160($inp),$xd2,$xd2
+	vmovdqu		$xa0,0x00($out)
+	vmovdqu		$xb0,0x20($out)
+	vmovdqu		$xc0,0x40($out)
+	vmovdqu		$xd0,0x60($out)
+	vmovdqu		$xa1,0x80($out)
+	vmovdqu		$xb1,0xa0($out)
+	vmovdqu		$xc1,0xc0($out)
+	vmovdqu		$xd1,0xe0($out)
+	vmovdqu		$xa2,0x100($out)
+	vmovdqu		$xb2,0x120($out)
+	vmovdqu		$xc2,0x140($out)
+	vmovdqu		$xd2,0x160($out)
+	je		.Ldone8x
+
+	lea		0x180($inp),$inp	# inp+=64*6
+	xor		%r10,%r10
+	vmovdqa		$xa3,0x00(%rsp)
+	lea		0x180($out),$out	# out+=64*6
+	sub		\$384,$len		# len-=64*6
+	vmovdqa		$xb3,0x20(%rsp)
+	jmp		.Loop_tail8x
+
+.align	32
+.L448_or_more8x:
+	vpxor		0x00($inp),$xa0,$xa0	# xor with input
+	vpxor		0x20($inp),$xb0,$xb0
+	vpxor		0x40($inp),$xc0,$xc0
+	vpxor		0x60($inp),$xd0,$xd0
+	vpxor		0x80($inp),$xa1,$xa1
+	vpxor		0xa0($inp),$xb1,$xb1
+	vpxor		0xc0($inp),$xc1,$xc1
+	vpxor		0xe0($inp),$xd1,$xd1
+	vpxor		0x100($inp),$xa2,$xa2
+	vpxor		0x120($inp),$xb2,$xb2
+	vpxor		0x140($inp),$xc2,$xc2
+	vpxor		0x160($inp),$xd2,$xd2
+	vpxor		0x180($inp),$xa3,$xa3
+	vpxor		0x1a0($inp),$xb3,$xb3
+	vmovdqu		$xa0,0x00($out)
+	vmovdqu		$xb0,0x20($out)
+	vmovdqu		$xc0,0x40($out)
+	vmovdqu		$xd0,0x60($out)
+	vmovdqu		$xa1,0x80($out)
+	vmovdqu		$xb1,0xa0($out)
+	vmovdqu		$xc1,0xc0($out)
+	vmovdqu		$xd1,0xe0($out)
+	vmovdqu		$xa2,0x100($out)
+	vmovdqu		$xb2,0x120($out)
+	vmovdqu		$xc2,0x140($out)
+	vmovdqu		$xd2,0x160($out)
+	vmovdqu		$xa3,0x180($out)
+	vmovdqu		$xb3,0x1a0($out)
+	je		.Ldone8x
+
+	lea		0x1c0($inp),$inp	# inp+=64*7
+	xor		%r10,%r10
+	vmovdqa		$xc3,0x00(%rsp)
+	lea		0x1c0($out),$out	# out+=64*7
+	sub		\$448,$len		# len-=64*7
+	vmovdqa		$xd3,0x20(%rsp)
+
+.Loop_tail8x:
+	movzb		($inp,%r10),%eax
+	movzb		(%rsp,%r10),%ecx
+	lea		1(%r10),%r10
+	xor		%ecx,%eax
+	mov		%al,-1($out,%r10)
+	dec		$len
+	jnz		.Loop_tail8x
+
+.Ldone8x:
+	vzeroall
+___
+$code.=<<___	if ($win64);
+	movaps		-0xa8(%r9),%xmm6
+	movaps		-0x98(%r9),%xmm7
+	movaps		-0x88(%r9),%xmm8
+	movaps		-0x78(%r9),%xmm9
+	movaps		-0x68(%r9),%xmm10
+	movaps		-0x58(%r9),%xmm11
+	movaps		-0x48(%r9),%xmm12
+	movaps		-0x38(%r9),%xmm13
+	movaps		-0x28(%r9),%xmm14
+	movaps		-0x18(%r9),%xmm15
+___
+$code.=<<___;
+	lea		(%r9),%rsp
+.L8x_epilogue:
+	ret
+.size	ChaCha20_8x,.-ChaCha20_8x
+___
+}
+
+########################################################################
+# AVX512 code paths
+if ($avx>2) {
+# This one handles shorter inputs...
+
+my ($a,$b,$c,$d, $a_,$b_,$c_,$d_,$fourz) = map("%zmm$_",(0..3,16..20));
+my ($t0,$t1,$t2,$t3) = map("%xmm$_",(4..7));
+
+sub AVX512ROUND {	# critical path is 14 "SIMD ticks" per round
+	&vpaddd	($a,$a,$b);
+	&vpxord	($d,$d,$a);
+	&vprold	($d,$d,16);
+
+	&vpaddd	($c,$c,$d);
+	&vpxord	($b,$b,$c);
+	&vprold	($b,$b,12);
+
+	&vpaddd	($a,$a,$b);
+	&vpxord	($d,$d,$a);
+	&vprold	($d,$d,8);
+
+	&vpaddd	($c,$c,$d);
+	&vpxord	($b,$b,$c);
+	&vprold	($b,$b,7);
+}
+
+my $xframe = $win64 ? 32+8 : 8;
+
+$code.=<<___;
+.type	ChaCha20_avx512,\@function,5
+.align	32
+ChaCha20_avx512:
+.LChaCha20_avx512:
+	mov	%rsp,%r9		# frame pointer
+	cmp	\$512,$len
+	ja	.LChaCha20_16x
+
+	sub	\$64+$xframe,%rsp
+___
+$code.=<<___	if ($win64);
+	movaps	%xmm6,-0x28(%r9)
+	movaps	%xmm7,-0x18(%r9)
+.Lavx512_body:
+___
+$code.=<<___;
+	vbroadcasti32x4	.Lsigma(%rip),$a
+	vbroadcasti32x4	($key),$b
+	vbroadcasti32x4	16($key),$c
+	vbroadcasti32x4	($counter),$d
+
+	vmovdqa32	$a,$a_
+	vmovdqa32	$b,$b_
+	vmovdqa32	$c,$c_
+	vpaddd		.Lzeroz(%rip),$d,$d
+	vmovdqa32	.Lfourz(%rip),$fourz
+	mov		\$10,$counter	# reuse $counter
+	vmovdqa32	$d,$d_
+	jmp		.Loop_avx512
+
+.align	16
+.Loop_outer_avx512:
+	vmovdqa32	$a_,$a
+	vmovdqa32	$b_,$b
+	vmovdqa32	$c_,$c
+	vpaddd		$fourz,$d_,$d
+	mov		\$10,$counter
+	vmovdqa32	$d,$d_
+	jmp		.Loop_avx512
+
+.align	32
+.Loop_avx512:
+___
+	&AVX512ROUND();
+	&vpshufd	($c,$c,0b01001110);
+	&vpshufd	($b,$b,0b00111001);
+	&vpshufd	($d,$d,0b10010011);
+
+	&AVX512ROUND();
+	&vpshufd	($c,$c,0b01001110);
+	&vpshufd	($b,$b,0b10010011);
+	&vpshufd	($d,$d,0b00111001);
+
+	&dec		($counter);
+	&jnz		(".Loop_avx512");
+
+$code.=<<___;
+	vpaddd		$a_,$a,$a
+	vpaddd		$b_,$b,$b
+	vpaddd		$c_,$c,$c
+	vpaddd		$d_,$d,$d
+
+	sub		\$64,$len
+	jb		.Ltail64_avx512
+
+	vpxor		0x00($inp),%x#$a,$t0	# xor with input
+	vpxor		0x10($inp),%x#$b,$t1
+	vpxor		0x20($inp),%x#$c,$t2
+	vpxor		0x30($inp),%x#$d,$t3
+	lea		0x40($inp),$inp		# inp+=64
+
+	vmovdqu		$t0,0x00($out)		# write output
+	vmovdqu		$t1,0x10($out)
+	vmovdqu		$t2,0x20($out)
+	vmovdqu		$t3,0x30($out)
+	lea		0x40($out),$out		# out+=64
+
+	jz		.Ldone_avx512
+
+	vextracti32x4	\$1,$a,$t0
+	vextracti32x4	\$1,$b,$t1
+	vextracti32x4	\$1,$c,$t2
+	vextracti32x4	\$1,$d,$t3
+
+	sub		\$64,$len
+	jb		.Ltail_avx512
+
+	vpxor		0x00($inp),$t0,$t0	# xor with input
+	vpxor		0x10($inp),$t1,$t1
+	vpxor		0x20($inp),$t2,$t2
+	vpxor		0x30($inp),$t3,$t3
+	lea		0x40($inp),$inp		# inp+=64
+
+	vmovdqu		$t0,0x00($out)		# write output
+	vmovdqu		$t1,0x10($out)
+	vmovdqu		$t2,0x20($out)
+	vmovdqu		$t3,0x30($out)
+	lea		0x40($out),$out		# out+=64
+
+	jz		.Ldone_avx512
+
+	vextracti32x4	\$2,$a,$t0
+	vextracti32x4	\$2,$b,$t1
+	vextracti32x4	\$2,$c,$t2
+	vextracti32x4	\$2,$d,$t3
+
+	sub		\$64,$len
+	jb		.Ltail_avx512
+
+	vpxor		0x00($inp),$t0,$t0	# xor with input
+	vpxor		0x10($inp),$t1,$t1
+	vpxor		0x20($inp),$t2,$t2
+	vpxor		0x30($inp),$t3,$t3
+	lea		0x40($inp),$inp		# inp+=64
+
+	vmovdqu		$t0,0x00($out)		# write output
+	vmovdqu		$t1,0x10($out)
+	vmovdqu		$t2,0x20($out)
+	vmovdqu		$t3,0x30($out)
+	lea		0x40($out),$out		# out+=64
+
+	jz		.Ldone_avx512
+
+	vextracti32x4	\$3,$a,$t0
+	vextracti32x4	\$3,$b,$t1
+	vextracti32x4	\$3,$c,$t2
+	vextracti32x4	\$3,$d,$t3
+
+	sub		\$64,$len
+	jb		.Ltail_avx512
+
+	vpxor		0x00($inp),$t0,$t0	# xor with input
+	vpxor		0x10($inp),$t1,$t1
+	vpxor		0x20($inp),$t2,$t2
+	vpxor		0x30($inp),$t3,$t3
+	lea		0x40($inp),$inp		# inp+=64
+
+	vmovdqu		$t0,0x00($out)		# write output
+	vmovdqu		$t1,0x10($out)
+	vmovdqu		$t2,0x20($out)
+	vmovdqu		$t3,0x30($out)
+	lea		0x40($out),$out		# out+=64
+
+	jnz		.Loop_outer_avx512
+
+	jmp		.Ldone_avx512
+
+.align	16
+.Ltail64_avx512:
+	vmovdqa		%x#$a,0x00(%rsp)
+	vmovdqa		%x#$b,0x10(%rsp)
+	vmovdqa		%x#$c,0x20(%rsp)
+	vmovdqa		%x#$d,0x30(%rsp)
+	add		\$64,$len
+	jmp		.Loop_tail_avx512
+
+.align	16
+.Ltail_avx512:
+	vmovdqa		$t0,0x00(%rsp)
+	vmovdqa		$t1,0x10(%rsp)
+	vmovdqa		$t2,0x20(%rsp)
+	vmovdqa		$t3,0x30(%rsp)
+	add		\$64,$len
+
+.Loop_tail_avx512:
+	movzb		($inp,$counter),%eax
+	movzb		(%rsp,$counter),%ecx
+	lea		1($counter),$counter
+	xor		%ecx,%eax
+	mov		%al,-1($out,$counter)
+	dec		$len
+	jnz		.Loop_tail_avx512
+
+	vmovdqa32	$a_,0x00(%rsp)
+
+.Ldone_avx512:
+	vzeroall
+___
+$code.=<<___	if ($win64);
+	movaps	-0x28(%r9),%xmm6
+	movaps	-0x18(%r9),%xmm7
+___
+$code.=<<___;
+	lea	(%r9),%rsp
+.Lavx512_epilogue:
+	ret
+.size	ChaCha20_avx512,.-ChaCha20_avx512
+___
+}
+if ($avx>2) {
+# This one handles longer inputs...
+
+my ($xa0,$xa1,$xa2,$xa3, $xb0,$xb1,$xb2,$xb3,
+    $xc0,$xc1,$xc2,$xc3, $xd0,$xd1,$xd2,$xd3)=map("%zmm$_",(0..15));
+my  @xx=($xa0,$xa1,$xa2,$xa3, $xb0,$xb1,$xb2,$xb3,
+	 $xc0,$xc1,$xc2,$xc3, $xd0,$xd1,$xd2,$xd3);
+my @key=map("%zmm$_",(16..31));
+my ($xt0,$xt1,$xt2,$xt3)=@key[0..3];
+
+sub AVX512_lane_ROUND {
+my ($a0,$b0,$c0,$d0)=@_;
+my ($a1,$b1,$c1,$d1)=map(($_&~3)+(($_+1)&3),($a0,$b0,$c0,$d0));
+my ($a2,$b2,$c2,$d2)=map(($_&~3)+(($_+1)&3),($a1,$b1,$c1,$d1));
+my ($a3,$b3,$c3,$d3)=map(($_&~3)+(($_+1)&3),($a2,$b2,$c2,$d2));
+my @x=map("\"$_\"",@xx);
+
+	(
+	"&vpaddd	(@x[$a0],@x[$a0],@x[$b0])",	# Q1
+	 "&vpaddd	(@x[$a1],@x[$a1],@x[$b1])",	# Q2
+	  "&vpaddd	(@x[$a2],@x[$a2],@x[$b2])",	# Q3
+	   "&vpaddd	(@x[$a3],@x[$a3],@x[$b3])",	# Q4
+	"&vpxord	(@x[$d0],@x[$d0],@x[$a0])",
+	 "&vpxord	(@x[$d1],@x[$d1],@x[$a1])",
+	  "&vpxord	(@x[$d2],@x[$d2],@x[$a2])",
+	   "&vpxord	(@x[$d3],@x[$d3],@x[$a3])",
+	"&vprold	(@x[$d0],@x[$d0],16)",
+	 "&vprold	(@x[$d1],@x[$d1],16)",
+	  "&vprold	(@x[$d2],@x[$d2],16)",
+	   "&vprold	(@x[$d3],@x[$d3],16)",
+
+	"&vpaddd	(@x[$c0],@x[$c0],@x[$d0])",
+	 "&vpaddd	(@x[$c1],@x[$c1],@x[$d1])",
+	  "&vpaddd	(@x[$c2],@x[$c2],@x[$d2])",
+	   "&vpaddd	(@x[$c3],@x[$c3],@x[$d3])",
+	"&vpxord	(@x[$b0],@x[$b0],@x[$c0])",
+	 "&vpxord	(@x[$b1],@x[$b1],@x[$c1])",
+	  "&vpxord	(@x[$b2],@x[$b2],@x[$c2])",
+	   "&vpxord	(@x[$b3],@x[$b3],@x[$c3])",
+	"&vprold	(@x[$b0],@x[$b0],12)",
+	 "&vprold	(@x[$b1],@x[$b1],12)",
+	  "&vprold	(@x[$b2],@x[$b2],12)",
+	   "&vprold	(@x[$b3],@x[$b3],12)",
+
+	"&vpaddd	(@x[$a0],@x[$a0],@x[$b0])",
+	 "&vpaddd	(@x[$a1],@x[$a1],@x[$b1])",
+	  "&vpaddd	(@x[$a2],@x[$a2],@x[$b2])",
+	   "&vpaddd	(@x[$a3],@x[$a3],@x[$b3])",
+	"&vpxord	(@x[$d0],@x[$d0],@x[$a0])",
+	 "&vpxord	(@x[$d1],@x[$d1],@x[$a1])",
+	  "&vpxord	(@x[$d2],@x[$d2],@x[$a2])",
+	   "&vpxord	(@x[$d3],@x[$d3],@x[$a3])",
+	"&vprold	(@x[$d0],@x[$d0],8)",
+	 "&vprold	(@x[$d1],@x[$d1],8)",
+	  "&vprold	(@x[$d2],@x[$d2],8)",
+	   "&vprold	(@x[$d3],@x[$d3],8)",
+
+	"&vpaddd	(@x[$c0],@x[$c0],@x[$d0])",
+	 "&vpaddd	(@x[$c1],@x[$c1],@x[$d1])",
+	  "&vpaddd	(@x[$c2],@x[$c2],@x[$d2])",
+	   "&vpaddd	(@x[$c3],@x[$c3],@x[$d3])",
+	"&vpxord	(@x[$b0],@x[$b0],@x[$c0])",
+	 "&vpxord	(@x[$b1],@x[$b1],@x[$c1])",
+	  "&vpxord	(@x[$b2],@x[$b2],@x[$c2])",
+	   "&vpxord	(@x[$b3],@x[$b3],@x[$c3])",
+	"&vprold	(@x[$b0],@x[$b0],7)",
+	 "&vprold	(@x[$b1],@x[$b1],7)",
+	  "&vprold	(@x[$b2],@x[$b2],7)",
+	   "&vprold	(@x[$b3],@x[$b3],7)"
+	);
+}
+
+my $xframe = $win64 ? 0xa8 : 8;
+
+$code.=<<___;
+.type	ChaCha20_16x,\@function,5
+.align	32
+ChaCha20_16x:
+.LChaCha20_16x:
+	mov		%rsp,%r9		# frame register
+	sub		\$64+$xframe,%rsp
+	and		\$-64,%rsp
+___
+$code.=<<___	if ($win64);
+	movaps		%xmm6,-0xa8(%r9)
+	movaps		%xmm7,-0x98(%r9)
+	movaps		%xmm8,-0x88(%r9)
+	movaps		%xmm9,-0x78(%r9)
+	movaps		%xmm10,-0x68(%r9)
+	movaps		%xmm11,-0x58(%r9)
+	movaps		%xmm12,-0x48(%r9)
+	movaps		%xmm13,-0x38(%r9)
+	movaps		%xmm14,-0x28(%r9)
+	movaps		%xmm15,-0x18(%r9)
+.L16x_body:
+___
+$code.=<<___;
+	vzeroupper
+
+	lea		.Lsigma(%rip),%r10
+	vbroadcasti32x4	(%r10),$xa3		# key[0]
+	vbroadcasti32x4	($key),$xb3		# key[1]
+	vbroadcasti32x4	16($key),$xc3		# key[2]
+	vbroadcasti32x4	($counter),$xd3		# key[3]
+
+	vpshufd		\$0x00,$xa3,$xa0	# smash key by lanes...
+	vpshufd		\$0x55,$xa3,$xa1
+	vpshufd		\$0xaa,$xa3,$xa2
+	vpshufd		\$0xff,$xa3,$xa3
+	vmovdqa64	$xa0,@key[0]
+	vmovdqa64	$xa1,@key[1]
+	vmovdqa64	$xa2,@key[2]
+	vmovdqa64	$xa3,@key[3]
+
+	vpshufd		\$0x00,$xb3,$xb0
+	vpshufd		\$0x55,$xb3,$xb1
+	vpshufd		\$0xaa,$xb3,$xb2
+	vpshufd		\$0xff,$xb3,$xb3
+	vmovdqa64	$xb0,@key[4]
+	vmovdqa64	$xb1,@key[5]
+	vmovdqa64	$xb2,@key[6]
+	vmovdqa64	$xb3,@key[7]
+
+	vpshufd		\$0x00,$xc3,$xc0
+	vpshufd		\$0x55,$xc3,$xc1
+	vpshufd		\$0xaa,$xc3,$xc2
+	vpshufd		\$0xff,$xc3,$xc3
+	vmovdqa64	$xc0,@key[8]
+	vmovdqa64	$xc1,@key[9]
+	vmovdqa64	$xc2,@key[10]
+	vmovdqa64	$xc3,@key[11]
+
+	vpshufd		\$0x00,$xd3,$xd0
+	vpshufd		\$0x55,$xd3,$xd1
+	vpshufd		\$0xaa,$xd3,$xd2
+	vpshufd		\$0xff,$xd3,$xd3
+	vpaddd		.Lincz(%rip),$xd0,$xd0	# don't save counters yet
+	vmovdqa64	$xd0,@key[12]
+	vmovdqa64	$xd1,@key[13]
+	vmovdqa64	$xd2,@key[14]
+	vmovdqa64	$xd3,@key[15]
+
+	mov		\$10,%eax
+	jmp		.Loop16x
+
+.align	32
+.Loop_outer16x:
+	vpbroadcastd	0(%r10),$xa0		# reload key
+	vpbroadcastd	4(%r10),$xa1
+	vpbroadcastd	8(%r10),$xa2
+	vpbroadcastd	12(%r10),$xa3
+	vpaddd		.Lsixteen(%rip),@key[12],@key[12]	# next SIMD counters
+	vmovdqa64	@key[4],$xb0
+	vmovdqa64	@key[5],$xb1
+	vmovdqa64	@key[6],$xb2
+	vmovdqa64	@key[7],$xb3
+	vmovdqa64	@key[8],$xc0
+	vmovdqa64	@key[9],$xc1
+	vmovdqa64	@key[10],$xc2
+	vmovdqa64	@key[11],$xc3
+	vmovdqa64	@key[12],$xd0
+	vmovdqa64	@key[13],$xd1
+	vmovdqa64	@key[14],$xd2
+	vmovdqa64	@key[15],$xd3
+
+	vmovdqa64	$xa0,@key[0]
+	vmovdqa64	$xa1,@key[1]
+	vmovdqa64	$xa2,@key[2]
+	vmovdqa64	$xa3,@key[3]
+
+	mov		\$10,%eax
+	jmp		.Loop16x
+
+.align	32
+.Loop16x:
+___
+	foreach (&AVX512_lane_ROUND(0, 4, 8,12)) { eval; }
+	foreach (&AVX512_lane_ROUND(0, 5,10,15)) { eval; }
+$code.=<<___;
+	dec		%eax
+	jnz		.Loop16x
+
+	vpaddd		@key[0],$xa0,$xa0	# accumulate key
+	vpaddd		@key[1],$xa1,$xa1
+	vpaddd		@key[2],$xa2,$xa2
+	vpaddd		@key[3],$xa3,$xa3
+
+	vpunpckldq	$xa1,$xa0,$xt2		# "de-interlace" data
+	vpunpckldq	$xa3,$xa2,$xt3
+	vpunpckhdq	$xa1,$xa0,$xa0
+	vpunpckhdq	$xa3,$xa2,$xa2
+	vpunpcklqdq	$xt3,$xt2,$xa1		# "a0"
+	vpunpckhqdq	$xt3,$xt2,$xt2		# "a1"
+	vpunpcklqdq	$xa2,$xa0,$xa3		# "a2"
+	vpunpckhqdq	$xa2,$xa0,$xa0		# "a3"
+___
+	($xa0,$xa1,$xa2,$xa3,$xt2)=($xa1,$xt2,$xa3,$xa0,$xa2);
+$code.=<<___;
+	vpaddd		@key[4],$xb0,$xb0
+	vpaddd		@key[5],$xb1,$xb1
+	vpaddd		@key[6],$xb2,$xb2
+	vpaddd		@key[7],$xb3,$xb3
+
+	vpunpckldq	$xb1,$xb0,$xt2
+	vpunpckldq	$xb3,$xb2,$xt3
+	vpunpckhdq	$xb1,$xb0,$xb0
+	vpunpckhdq	$xb3,$xb2,$xb2
+	vpunpcklqdq	$xt3,$xt2,$xb1		# "b0"
+	vpunpckhqdq	$xt3,$xt2,$xt2		# "b1"
+	vpunpcklqdq	$xb2,$xb0,$xb3		# "b2"
+	vpunpckhqdq	$xb2,$xb0,$xb0		# "b3"
+___
+	($xb0,$xb1,$xb2,$xb3,$xt2)=($xb1,$xt2,$xb3,$xb0,$xb2);
+$code.=<<___;
+	vshufi32x4	\$0x44,$xb0,$xa0,$xt3	# "de-interlace" further
+	vshufi32x4	\$0xee,$xb0,$xa0,$xb0
+	vshufi32x4	\$0x44,$xb1,$xa1,$xa0
+	vshufi32x4	\$0xee,$xb1,$xa1,$xb1
+	vshufi32x4	\$0x44,$xb2,$xa2,$xa1
+	vshufi32x4	\$0xee,$xb2,$xa2,$xb2
+	vshufi32x4	\$0x44,$xb3,$xa3,$xa2
+	vshufi32x4	\$0xee,$xb3,$xa3,$xb3
+___
+	($xa0,$xa1,$xa2,$xa3,$xt3)=($xt3,$xa0,$xa1,$xa2,$xa3);
+$code.=<<___;
+	vpaddd		@key[8],$xc0,$xc0
+	vpaddd		@key[9],$xc1,$xc1
+	vpaddd		@key[10],$xc2,$xc2
+	vpaddd		@key[11],$xc3,$xc3
+
+	vpunpckldq	$xc1,$xc0,$xt2
+	vpunpckldq	$xc3,$xc2,$xt3
+	vpunpckhdq	$xc1,$xc0,$xc0
+	vpunpckhdq	$xc3,$xc2,$xc2
+	vpunpcklqdq	$xt3,$xt2,$xc1		# "c0"
+	vpunpckhqdq	$xt3,$xt2,$xt2		# "c1"
+	vpunpcklqdq	$xc2,$xc0,$xc3		# "c2"
+	vpunpckhqdq	$xc2,$xc0,$xc0		# "c3"
+___
+	($xc0,$xc1,$xc2,$xc3,$xt2)=($xc1,$xt2,$xc3,$xc0,$xc2);
+$code.=<<___;
+	vpaddd		@key[12],$xd0,$xd0
+	vpaddd		@key[13],$xd1,$xd1
+	vpaddd		@key[14],$xd2,$xd2
+	vpaddd		@key[15],$xd3,$xd3
+
+	vpunpckldq	$xd1,$xd0,$xt2
+	vpunpckldq	$xd3,$xd2,$xt3
+	vpunpckhdq	$xd1,$xd0,$xd0
+	vpunpckhdq	$xd3,$xd2,$xd2
+	vpunpcklqdq	$xt3,$xt2,$xd1		# "d0"
+	vpunpckhqdq	$xt3,$xt2,$xt2		# "d1"
+	vpunpcklqdq	$xd2,$xd0,$xd3		# "d2"
+	vpunpckhqdq	$xd2,$xd0,$xd0		# "d3"
+___
+	($xd0,$xd1,$xd2,$xd3,$xt2)=($xd1,$xt2,$xd3,$xd0,$xd2);
+$code.=<<___;
+	vshufi32x4	\$0x44,$xd0,$xc0,$xt3	# "de-interlace" further
+	vshufi32x4	\$0xee,$xd0,$xc0,$xd0
+	vshufi32x4	\$0x44,$xd1,$xc1,$xc0
+	vshufi32x4	\$0xee,$xd1,$xc1,$xd1
+	vshufi32x4	\$0x44,$xd2,$xc2,$xc1
+	vshufi32x4	\$0xee,$xd2,$xc2,$xd2
+	vshufi32x4	\$0x44,$xd3,$xc3,$xc2
+	vshufi32x4	\$0xee,$xd3,$xc3,$xd3
+___
+	($xc0,$xc1,$xc2,$xc3,$xt3)=($xt3,$xc0,$xc1,$xc2,$xc3);
+$code.=<<___;
+	vshufi32x4	\$0x88,$xc0,$xa0,$xt0	# "de-interlace" further
+	vshufi32x4	\$0xdd,$xc0,$xa0,$xa0
+	 vshufi32x4	\$0x88,$xd0,$xb0,$xc0
+	 vshufi32x4	\$0xdd,$xd0,$xb0,$xd0
+	vshufi32x4	\$0x88,$xc1,$xa1,$xt1
+	vshufi32x4	\$0xdd,$xc1,$xa1,$xa1
+	 vshufi32x4	\$0x88,$xd1,$xb1,$xc1
+	 vshufi32x4	\$0xdd,$xd1,$xb1,$xd1
+	vshufi32x4	\$0x88,$xc2,$xa2,$xt2
+	vshufi32x4	\$0xdd,$xc2,$xa2,$xa2
+	 vshufi32x4	\$0x88,$xd2,$xb2,$xc2
+	 vshufi32x4	\$0xdd,$xd2,$xb2,$xd2
+	vshufi32x4	\$0x88,$xc3,$xa3,$xt3
+	vshufi32x4	\$0xdd,$xc3,$xa3,$xa3
+	 vshufi32x4	\$0x88,$xd3,$xb3,$xc3
+	 vshufi32x4	\$0xdd,$xd3,$xb3,$xd3
+___
+	($xa0,$xa1,$xa2,$xa3,$xb0,$xb1,$xb2,$xb3)=
+	($xt0,$xt1,$xt2,$xt3,$xa0,$xa1,$xa2,$xa3);
+
+	($xa0,$xb0,$xc0,$xd0, $xa1,$xb1,$xc1,$xd1,
+	 $xa2,$xb2,$xc2,$xd2, $xa3,$xb3,$xc3,$xd3) =
+	($xa0,$xa1,$xa2,$xa3, $xb0,$xb1,$xb2,$xb3,
+	 $xc0,$xc1,$xc2,$xc3, $xd0,$xd1,$xd2,$xd3);
+$code.=<<___;
+	cmp		\$64*16,$len
+	jb		.Ltail16x
+
+	vpxord		0x00($inp),$xa0,$xa0	# xor with input
+	vpxord		0x40($inp),$xb0,$xb0
+	vpxord		0x80($inp),$xc0,$xc0
+	vpxord		0xc0($inp),$xd0,$xd0
+	vmovdqu32	$xa0,0x00($out)
+	vmovdqu32	$xb0,0x40($out)
+	vmovdqu32	$xc0,0x80($out)
+	vmovdqu32	$xd0,0xc0($out)
+
+	vpxord		0x100($inp),$xa1,$xa1
+	vpxord		0x140($inp),$xb1,$xb1
+	vpxord		0x180($inp),$xc1,$xc1
+	vpxord		0x1c0($inp),$xd1,$xd1
+	vmovdqu32	$xa1,0x100($out)
+	vmovdqu32	$xb1,0x140($out)
+	vmovdqu32	$xc1,0x180($out)
+	vmovdqu32	$xd1,0x1c0($out)
+
+	vpxord		0x200($inp),$xa2,$xa2
+	vpxord		0x240($inp),$xb2,$xb2
+	vpxord		0x280($inp),$xc2,$xc2
+	vpxord		0x2c0($inp),$xd2,$xd2
+	vmovdqu32	$xa2,0x200($out)
+	vmovdqu32	$xb2,0x240($out)
+	vmovdqu32	$xc2,0x280($out)
+	vmovdqu32	$xd2,0x2c0($out)
+
+	vpxord		0x300($inp),$xa3,$xa3
+	vpxord		0x340($inp),$xb3,$xb3
+	vpxord		0x380($inp),$xc3,$xc3
+	vpxord		0x3c0($inp),$xd3,$xd3
+	lea		0x400($inp),$inp
+	vmovdqu32	$xa3,0x300($out)
+	vmovdqu32	$xb3,0x340($out)
+	vmovdqu32	$xc3,0x380($out)
+	vmovdqu32	$xd3,0x3c0($out)
+	lea		0x400($out),$out
+
+	sub		\$64*16,$len
+	jnz		.Loop_outer16x
+
+	jmp		.Ldone16x
+
+.align	32
+.Ltail16x:
+	xor		%r10,%r10
+	sub		$inp,$out
+	cmp		\$64*1,$len
+	jb		.Less_than_64_16x
+	vpxord		($inp),$xa0,$xa0	# xor with input
+	vmovdqu32	$xa0,($out,$inp)
+	je		.Ldone16x
+	vmovdqa32	$xb0,$xa0
+	lea		64($inp),$inp
+
+	cmp		\$64*2,$len
+	jb		.Less_than_64_16x
+	vpxord		($inp),$xb0,$xb0
+	vmovdqu32	$xb0,($out,$inp)
+	je		.Ldone16x
+	vmovdqa32	$xc0,$xa0
+	lea		64($inp),$inp
+
+	cmp		\$64*3,$len
+	jb		.Less_than_64_16x
+	vpxord		($inp),$xc0,$xc0
+	vmovdqu32	$xc0,($out,$inp)
+	je		.Ldone16x
+	vmovdqa32	$xd0,$xa0
+	lea		64($inp),$inp
+
+	cmp		\$64*4,$len
+	jb		.Less_than_64_16x
+	vpxord		($inp),$xd0,$xd0
+	vmovdqu32	$xd0,($out,$inp)
+	je		.Ldone16x
+	vmovdqa32	$xa1,$xa0
+	lea		64($inp),$inp
+
+	cmp		\$64*5,$len
+	jb		.Less_than_64_16x
+	vpxord		($inp),$xa1,$xa1
+	vmovdqu32	$xa1,($out,$inp)
+	je		.Ldone16x
+	vmovdqa32	$xb1,$xa0
+	lea		64($inp),$inp
+
+	cmp		\$64*6,$len
+	jb		.Less_than_64_16x
+	vpxord		($inp),$xb1,$xb1
+	vmovdqu32	$xb1,($out,$inp)
+	je		.Ldone16x
+	vmovdqa32	$xc1,$xa0
+	lea		64($inp),$inp
+
+	cmp		\$64*7,$len
+	jb		.Less_than_64_16x
+	vpxord		($inp),$xc1,$xc1
+	vmovdqu32	$xc1,($out,$inp)
+	je		.Ldone16x
+	vmovdqa32	$xd1,$xa0
+	lea		64($inp),$inp
+
+	cmp		\$64*8,$len
+	jb		.Less_than_64_16x
+	vpxord		($inp),$xd1,$xd1
+	vmovdqu32	$xd1,($out,$inp)
+	je		.Ldone16x
+	vmovdqa32	$xa2,$xa0
+	lea		64($inp),$inp
+
+	cmp		\$64*9,$len
+	jb		.Less_than_64_16x
+	vpxord		($inp),$xa2,$xa2
+	vmovdqu32	$xa2,($out,$inp)
+	je		.Ldone16x
+	vmovdqa32	$xb2,$xa0
+	lea		64($inp),$inp
+
+	cmp		\$64*10,$len
+	jb		.Less_than_64_16x
+	vpxord		($inp),$xb2,$xb2
+	vmovdqu32	$xb2,($out,$inp)
+	je		.Ldone16x
+	vmovdqa32	$xc2,$xa0
+	lea		64($inp),$inp
+
+	cmp		\$64*11,$len
+	jb		.Less_than_64_16x
+	vpxord		($inp),$xc2,$xc2
+	vmovdqu32	$xc2,($out,$inp)
+	je		.Ldone16x
+	vmovdqa32	$xd2,$xa0
+	lea		64($inp),$inp
+
+	cmp		\$64*12,$len
+	jb		.Less_than_64_16x
+	vpxord		($inp),$xd2,$xd2
+	vmovdqu32	$xd2,($out,$inp)
+	je		.Ldone16x
+	vmovdqa32	$xa3,$xa0
+	lea		64($inp),$inp
+
+	cmp		\$64*13,$len
+	jb		.Less_than_64_16x
+	vpxord		($inp),$xa3,$xa3
+	vmovdqu32	$xa3,($out,$inp)
+	je		.Ldone16x
+	vmovdqa32	$xb3,$xa0
+	lea		64($inp),$inp
+
+	cmp		\$64*14,$len
+	jb		.Less_than_64_16x
+	vpxord		($inp),$xb3,$xb3
+	vmovdqu32	$xb3,($out,$inp)
+	je		.Ldone16x
+	vmovdqa32	$xc3,$xa0
+	lea		64($inp),$inp
+
+	cmp		\$64*15,$len
+	jb		.Less_than_64_16x
+	vpxord		($inp),$xc3,$xc3
+	vmovdqu32	$xc3,($out,$inp)
+	je		.Ldone16x
+	vmovdqa32	$xd3,$xa0
+	lea		64($inp),$inp
+
+.Less_than_64_16x:
+	vmovdqa32	$xa0,0x00(%rsp)
+	lea		($out,$inp),$out
+	and		\$63,$len
+
+.Loop_tail16x:
+	movzb		($inp,%r10),%eax
+	movzb		(%rsp,%r10),%ecx
+	lea		1(%r10),%r10
+	xor		%ecx,%eax
+	mov		%al,-1($out,%r10)
+	dec		$len
+	jnz		.Loop_tail16x
+
+	vpxord		$xa0,$xa0,$xa0
+	vmovdqa32	$xa0,0(%rsp)
+
+.Ldone16x:
+	vzeroall
+___
+$code.=<<___	if ($win64);
+	movaps		-0xa8(%r9),%xmm6
+	movaps		-0x98(%r9),%xmm7
+	movaps		-0x88(%r9),%xmm8
+	movaps		-0x78(%r9),%xmm9
+	movaps		-0x68(%r9),%xmm10
+	movaps		-0x58(%r9),%xmm11
+	movaps		-0x48(%r9),%xmm12
+	movaps		-0x38(%r9),%xmm13
+	movaps		-0x28(%r9),%xmm14
+	movaps		-0x18(%r9),%xmm15
+___
+$code.=<<___;
+	lea		(%r9),%rsp
+.L16x_epilogue:
+	ret
+.size	ChaCha20_16x,.-ChaCha20_16x
+___
+}
+
+# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
+#		CONTEXT *context,DISPATCHER_CONTEXT *disp)
+if ($win64) {
+$rec="%rcx";
+$frame="%rdx";
+$context="%r8";
+$disp="%r9";
+
+$code.=<<___;
+.extern	__imp_RtlVirtualUnwind
+.type	se_handler,\@abi-omnipotent
+.align	16
+se_handler:
+	push	%rsi
+	push	%rdi
+	push	%rbx
+	push	%rbp
+	push	%r12
+	push	%r13
+	push	%r14
+	push	%r15
+	pushfq
+	sub	\$64,%rsp
+
+	mov	120($context),%rax	# pull context->Rax
+	mov	248($context),%rbx	# pull context->Rip
+
+	mov	8($disp),%rsi		# disp->ImageBase
+	mov	56($disp),%r11		# disp->HandlerData
+
+	lea	.Lctr32_body(%rip),%r10
+	cmp	%r10,%rbx		# context->Rip<.Lprologue
+	jb	.Lcommon_seh_tail
+
+	mov	152($context),%rax	# pull context->Rsp
+
+	lea	.Lno_data(%rip),%r10	# epilogue label
+	cmp	%r10,%rbx		# context->Rip>=.Lepilogue
+	jae	.Lcommon_seh_tail
+
+	lea	64+24+48(%rax),%rax
+
+	mov	-8(%rax),%rbx
+	mov	-16(%rax),%rbp
+	mov	-24(%rax),%r12
+	mov	-32(%rax),%r13
+	mov	-40(%rax),%r14
+	mov	-48(%rax),%r15
+	mov	%rbx,144($context)	# restore context->Rbx
+	mov	%rbp,160($context)	# restore context->Rbp
+	mov	%r12,216($context)	# restore context->R12
+	mov	%r13,224($context)	# restore context->R13
+	mov	%r14,232($context)	# restore context->R14
+	mov	%r15,240($context)	# restore context->R14
+
+.Lcommon_seh_tail:
+	mov	8(%rax),%rdi
+	mov	16(%rax),%rsi
+	mov	%rax,152($context)	# restore context->Rsp
+	mov	%rsi,168($context)	# restore context->Rsi
+	mov	%rdi,176($context)	# restore context->Rdi
+
+	mov	40($disp),%rdi		# disp->ContextRecord
+	mov	$context,%rsi		# context
+	mov	\$154,%ecx		# sizeof(CONTEXT)
+	.long	0xa548f3fc		# cld; rep movsq
+
+	mov	$disp,%rsi
+	xor	%rcx,%rcx		# arg1, UNW_FLAG_NHANDLER
+	mov	8(%rsi),%rdx		# arg2, disp->ImageBase
+	mov	0(%rsi),%r8		# arg3, disp->ControlPc
+	mov	16(%rsi),%r9		# arg4, disp->FunctionEntry
+	mov	40(%rsi),%r10		# disp->ContextRecord
+	lea	56(%rsi),%r11		# &disp->HandlerData
+	lea	24(%rsi),%r12		# &disp->EstablisherFrame
+	mov	%r10,32(%rsp)		# arg5
+	mov	%r11,40(%rsp)		# arg6
+	mov	%r12,48(%rsp)		# arg7
+	mov	%rcx,56(%rsp)		# arg8, (NULL)
+	call	*__imp_RtlVirtualUnwind(%rip)
+
+	mov	\$1,%eax		# ExceptionContinueSearch
+	add	\$64,%rsp
+	popfq
+	pop	%r15
+	pop	%r14
+	pop	%r13
+	pop	%r12
+	pop	%rbp
+	pop	%rbx
+	pop	%rdi
+	pop	%rsi
+	ret
+.size	se_handler,.-se_handler
+
+.type	ssse3_handler,\@abi-omnipotent
+.align	16
+ssse3_handler:
+	push	%rsi
+	push	%rdi
+	push	%rbx
+	push	%rbp
+	push	%r12
+	push	%r13
+	push	%r14
+	push	%r15
+	pushfq
+	sub	\$64,%rsp
+
+	mov	120($context),%rax	# pull context->Rax
+	mov	248($context),%rbx	# pull context->Rip
+
+	mov	8($disp),%rsi		# disp->ImageBase
+	mov	56($disp),%r11		# disp->HandlerData
+
+	mov	0(%r11),%r10d		# HandlerData[0]
+	lea	(%rsi,%r10),%r10	# prologue label
+	cmp	%r10,%rbx		# context->Rip<prologue label
+	jb	.Lcommon_seh_tail
+
+	mov	192($context),%rax	# pull context->R9
+
+	mov	4(%r11),%r10d		# HandlerData[1]
+	lea	(%rsi,%r10),%r10	# epilogue label
+	cmp	%r10,%rbx		# context->Rip>=epilogue label
+	jae	.Lcommon_seh_tail
+
+	lea	-0x28(%rax),%rsi
+	lea	512($context),%rdi	# &context.Xmm6
+	mov	\$4,%ecx
+	.long	0xa548f3fc		# cld; rep movsq
+
+	jmp	.Lcommon_seh_tail
+.size	ssse3_handler,.-ssse3_handler
+
+.type	full_handler,\@abi-omnipotent
+.align	16
+full_handler:
+	push	%rsi
+	push	%rdi
+	push	%rbx
+	push	%rbp
+	push	%r12
+	push	%r13
+	push	%r14
+	push	%r15
+	pushfq
+	sub	\$64,%rsp
+
+	mov	120($context),%rax	# pull context->Rax
+	mov	248($context),%rbx	# pull context->Rip
+
+	mov	8($disp),%rsi		# disp->ImageBase
+	mov	56($disp),%r11		# disp->HandlerData
+
+	mov	0(%r11),%r10d		# HandlerData[0]
+	lea	(%rsi,%r10),%r10	# prologue label
+	cmp	%r10,%rbx		# context->Rip<prologue label
+	jb	.Lcommon_seh_tail
+
+	mov	192($context),%rax	# pull context->R9
+
+	mov	4(%r11),%r10d		# HandlerData[1]
+	lea	(%rsi,%r10),%r10	# epilogue label
+	cmp	%r10,%rbx		# context->Rip>=epilogue label
+	jae	.Lcommon_seh_tail
+
+	lea	-0xa8(%rax),%rsi
+	lea	512($context),%rdi	# &context.Xmm6
+	mov	\$20,%ecx
+	.long	0xa548f3fc		# cld; rep movsq
+
+	jmp	.Lcommon_seh_tail
+.size	full_handler,.-full_handler
+
+.section	.pdata
+.align	4
+	.rva	.LSEH_begin_ChaCha20_ctr32
+	.rva	.LSEH_end_ChaCha20_ctr32
+	.rva	.LSEH_info_ChaCha20_ctr32
+
+	.rva	.LSEH_begin_ChaCha20_ssse3
+	.rva	.LSEH_end_ChaCha20_ssse3
+	.rva	.LSEH_info_ChaCha20_ssse3
+
+	.rva	.LSEH_begin_ChaCha20_4x
+	.rva	.LSEH_end_ChaCha20_4x
+	.rva	.LSEH_info_ChaCha20_4x
+___
+$code.=<<___ if ($avx>1);
+	.rva	.LSEH_begin_ChaCha20_8x
+	.rva	.LSEH_end_ChaCha20_8x
+	.rva	.LSEH_info_ChaCha20_8x
+___
+$code.=<<___ if ($avx>2);
+	.rva	.LSEH_begin_ChaCha20_avx512
+	.rva	.LSEH_end_ChaCha20_avx512
+	.rva	.LSEH_info_ChaCha20_avx512
+
+	.rva	.LSEH_begin_ChaCha20_16x
+	.rva	.LSEH_end_ChaCha20_16x
+	.rva	.LSEH_info_ChaCha20_16x
+___
+$code.=<<___;
+.section	.xdata
+.align	8
+.LSEH_info_ChaCha20_ctr32:
+	.byte	9,0,0,0
+	.rva	se_handler
+
+.LSEH_info_ChaCha20_ssse3:
+	.byte	9,0,0,0
+	.rva	ssse3_handler
+	.rva	.Lssse3_body,.Lssse3_epilogue
+
+.LSEH_info_ChaCha20_4x:
+	.byte	9,0,0,0
+	.rva	full_handler
+	.rva	.L4x_body,.L4x_epilogue
+___
+$code.=<<___ if ($avx>1);
+.LSEH_info_ChaCha20_8x:
+	.byte	9,0,0,0
+	.rva	full_handler
+	.rva	.L8x_body,.L8x_epilogue			# HandlerData[]
+___
+$code.=<<___ if ($avx>2);
+.LSEH_info_ChaCha20_avx512:
+	.byte	9,0,0,0
+	.rva	ssse3_handler
+	.rva	.Lavx512_body,.Lavx512_epilogue		# HandlerData[]
+
+.LSEH_info_ChaCha20_16x:
+	.byte	9,0,0,0
+	.rva	full_handler
+	.rva	.L16x_body,.L16x_epilogue		# HandlerData[]
+___
+}
+
+foreach (split("\n",$code)) {
+	s/\`([^\`]*)\`/eval $1/ge;
+
+	s/%x#%[yz]/%x/g;	# "down-shift"
+
+	print $_,"\n";
+}
+
+close STDOUT;
diff --git a/src/crypto/chacha/chacha_generic.c b/src/crypto/chacha/chacha.c
similarity index 64%
rename from src/crypto/chacha/chacha_generic.c
rename to src/crypto/chacha/chacha.c
index f262033..fe32596 100644
--- a/src/crypto/chacha/chacha_generic.c
+++ b/src/crypto/chacha/chacha.c
@@ -16,21 +16,64 @@
 
 #include <openssl/chacha.h>
 
+#include <assert.h>
 #include <string.h>
 
 #include <openssl/cpu.h>
 
+#include "../internal.h"
 
-#if defined(OPENSSL_WINDOWS) || (!defined(OPENSSL_X86_64) && !defined(OPENSSL_X86)) || !defined(__SSE2__)
+
+#define U8TO32_LITTLE(p)                              \
+  (((uint32_t)((p)[0])) | ((uint32_t)((p)[1]) << 8) | \
+   ((uint32_t)((p)[2]) << 16) | ((uint32_t)((p)[3]) << 24))
+
+#if !defined(OPENSSL_NO_ASM) &&                         \
+    (defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \
+     defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64))
+
+/* ChaCha20_ctr32 is defined in asm/chacha-*.pl. */
+void ChaCha20_ctr32(uint8_t *out, const uint8_t *in, size_t in_len,
+                    const uint32_t key[8], const uint32_t counter[4]);
+
+void CRYPTO_chacha_20(uint8_t *out, const uint8_t *in, size_t in_len,
+                      const uint8_t key[32], const uint8_t nonce[12],
+                      uint32_t counter) {
+  assert(!buffers_alias(out, in_len, in, in_len) || in == out);
+
+  uint32_t counter_nonce[4];  counter_nonce[0] = counter;
+  counter_nonce[1] = U8TO32_LITTLE(nonce + 0);
+  counter_nonce[2] = U8TO32_LITTLE(nonce + 4);
+  counter_nonce[3] = U8TO32_LITTLE(nonce + 8);
+
+  const uint32_t *key_ptr = (const uint32_t *)key;
+#if !defined(OPENSSL_X86) && !defined(OPENSSL_X86_64)
+  /* The assembly expects the key to be four-byte aligned. */
+  uint32_t key_u32[8];
+  if ((((uintptr_t)key) & 3) != 0) {
+    key_u32[0] = U8TO32_LITTLE(key + 0);
+    key_u32[1] = U8TO32_LITTLE(key + 4);
+    key_u32[2] = U8TO32_LITTLE(key + 8);
+    key_u32[3] = U8TO32_LITTLE(key + 12);
+    key_u32[4] = U8TO32_LITTLE(key + 16);
+    key_u32[5] = U8TO32_LITTLE(key + 20);
+    key_u32[6] = U8TO32_LITTLE(key + 24);
+    key_u32[7] = U8TO32_LITTLE(key + 28);
+
+    key_ptr = key_u32;
+  }
+#endif
+
+  ChaCha20_ctr32(out, in, in_len, key_ptr, counter_nonce);
+}
+
+#else
 
 /* sigma contains the ChaCha constants, which happen to be an ASCII string. */
 static const uint8_t sigma[16] = { 'e', 'x', 'p', 'a', 'n', 'd', ' ', '3',
                                    '2', '-', 'b', 'y', 't', 'e', ' ', 'k' };
 
 #define ROTATE(v, n) (((v) << (n)) | ((v) >> (32 - (n))))
-#define XOR(v, w) ((v) ^ (w))
-#define PLUS(x, y) ((x) + (y))
-#define PLUSONE(v) (PLUS((v), 1))
 
 #define U32TO8_LITTLE(p, v)    \
   {                            \
@@ -40,23 +83,12 @@
     (p)[3] = (v >> 24) & 0xff; \
   }
 
-#define U8TO32_LITTLE(p)                              \
-  (((uint32_t)((p)[0])) | ((uint32_t)((p)[1]) << 8) | \
-   ((uint32_t)((p)[2]) << 16) | ((uint32_t)((p)[3]) << 24))
-
 /* QUARTERROUND updates a, b, c, d with a ChaCha "quarter" round. */
-#define QUARTERROUND(a,b,c,d) \
-  x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]),16); \
-  x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]),12); \
-  x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]), 8); \
-  x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]), 7);
-
-#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
-/* Defined in chacha_vec.c */
-void CRYPTO_chacha_20_neon(uint8_t *out, const uint8_t *in, size_t in_len,
-                           const uint8_t key[32], const uint8_t nonce[12],
-                           uint32_t counter);
-#endif
+#define QUARTERROUND(a, b, c, d)                \
+  x[a] += x[b]; x[d] = ROTATE(x[d] ^ x[a], 16); \
+  x[c] += x[d]; x[b] = ROTATE(x[b] ^ x[c], 12); \
+  x[a] += x[b]; x[d] = ROTATE(x[d] ^ x[a],  8); \
+  x[c] += x[d]; x[b] = ROTATE(x[b] ^ x[c],  7);
 
 /* chacha_core performs 20 rounds of ChaCha on the input words in
  * |input| and writes the 64 output bytes to |output|. */
@@ -64,7 +96,7 @@
   uint32_t x[16];
   int i;
 
-  memcpy(x, input, sizeof(uint32_t) * 16);
+  OPENSSL_memcpy(x, input, sizeof(uint32_t) * 16);
   for (i = 20; i > 0; i -= 2) {
     QUARTERROUND(0, 4, 8, 12)
     QUARTERROUND(1, 5, 9, 13)
@@ -77,7 +109,7 @@
   }
 
   for (i = 0; i < 16; ++i) {
-    x[i] = PLUS(x[i], input[i]);
+    x[i] += input[i];
   }
   for (i = 0; i < 16; ++i) {
     U32TO8_LITTLE(output + 4 * i, x[i]);
@@ -87,17 +119,12 @@
 void CRYPTO_chacha_20(uint8_t *out, const uint8_t *in, size_t in_len,
                       const uint8_t key[32], const uint8_t nonce[12],
                       uint32_t counter) {
+  assert(!buffers_alias(out, in_len, in, in_len) || in == out);
+
   uint32_t input[16];
   uint8_t buf[64];
   size_t todo, i;
 
-#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
-  if (CRYPTO_is_NEON_capable()) {
-    CRYPTO_chacha_20_neon(out, in, in_len, key, nonce, counter);
-    return;
-  }
-#endif
-
   input[0] = U8TO32_LITTLE(sigma + 0);
   input[1] = U8TO32_LITTLE(sigma + 4);
   input[2] = U8TO32_LITTLE(sigma + 8);
@@ -137,4 +164,4 @@
   }
 }
 
-#endif /* OPENSSL_WINDOWS || !OPENSSL_X86_64 && !OPENSSL_X86 || !__SSE2__ */
+#endif
diff --git a/src/crypto/chacha/chacha_test.cc b/src/crypto/chacha/chacha_test.cc
new file mode 100644
index 0000000..a40653f
--- /dev/null
+++ b/src/crypto/chacha/chacha_test.cc
@@ -0,0 +1,236 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+#include <memory>
+
+#include <gtest/gtest.h>
+
+#include <openssl/crypto.h>
+#include <openssl/chacha.h>
+
+#include "../internal.h"
+#include "../test/test_util.h"
+
+
+static const uint8_t kKey[32] = {
+    0x98, 0xbe, 0xf1, 0x46, 0x9b, 0xe7, 0x26, 0x98, 0x37, 0xa4, 0x5b,
+    0xfb, 0xc9, 0x2a, 0x5a, 0x6a, 0xc7, 0x62, 0x50, 0x7c, 0xf9, 0x64,
+    0x43, 0xbf, 0x33, 0xb9, 0x6b, 0x1b, 0xd4, 0xc6, 0xf8, 0xf6,
+};
+
+static const uint8_t kNonce[12] = {
+    0x44, 0xe7, 0x92, 0xd6, 0x33, 0x35, 0xab, 0xb1, 0x58, 0x2e, 0x92, 0x53,
+};
+
+static uint32_t kCounter = 42;
+
+static const uint8_t kInput[] = {
+    0x58, 0x28, 0xd5, 0x30, 0x36, 0x2c, 0x60, 0x55, 0x29, 0xf8, 0xe1, 0x8c,
+    0xae, 0x15, 0x15, 0x26, 0xf2, 0x3a, 0x73, 0xa0, 0xf3, 0x12, 0xa3, 0x88,
+    0x5f, 0x2b, 0x74, 0x23, 0x3d, 0xc9, 0x05, 0x23, 0xc6, 0x54, 0x49, 0x1e,
+    0x44, 0x88, 0x14, 0xd9, 0xda, 0x37, 0x15, 0xdc, 0xb7, 0xe4, 0x23, 0xb3,
+    0x9d, 0x7e, 0x16, 0x68, 0x35, 0xfc, 0x02, 0x6d, 0xcc, 0x8a, 0xe5, 0xdd,
+    0x5f, 0xe4, 0xd2, 0x56, 0x6f, 0x12, 0x9c, 0x9c, 0x7d, 0x6a, 0x38, 0x48,
+    0xbd, 0xdf, 0xd9, 0xac, 0x1b, 0xa2, 0x4d, 0xc5, 0x43, 0x04, 0x3c, 0xd7,
+    0x99, 0xe1, 0xa7, 0x13, 0x9c, 0x51, 0xc2, 0x6d, 0xf9, 0xcf, 0x07, 0x3b,
+    0xe4, 0xbf, 0x93, 0xa3, 0xa9, 0xb4, 0xc5, 0xf0, 0x1a, 0xe4, 0x8d, 0x5f,
+    0xc6, 0xc4, 0x7c, 0x69, 0x7a, 0xde, 0x1a, 0xc1, 0xc9, 0xcf, 0xc2, 0x4e,
+    0x7a, 0x25, 0x2c, 0x32, 0xe9, 0x17, 0xba, 0x68, 0xf1, 0x37, 0x5d, 0x62,
+    0x84, 0x46, 0xf5, 0x80, 0x7f, 0x1a, 0x71, 0xf7, 0xbe, 0x72, 0x4b, 0xb8,
+    0x1c, 0xfe, 0x3e, 0xbd, 0xae, 0x0d, 0x73, 0x0d, 0x87, 0x4a, 0x31, 0xc3,
+    0x3d, 0x46, 0x6f, 0xb3, 0xd7, 0x6b, 0xe3, 0xb8, 0x70, 0x17, 0x8e, 0x7a,
+    0x6a, 0x0e, 0xbf, 0xa8, 0xbc, 0x2b, 0xdb, 0xfa, 0x4f, 0xb6, 0x26, 0x20,
+    0xee, 0x63, 0xf0, 0x6d, 0x26, 0xac, 0x6a, 0x18, 0x37, 0x6e, 0x59, 0x81,
+    0xd1, 0x60, 0xe6, 0x40, 0xd5, 0x6d, 0x68, 0xba, 0x8b, 0x65, 0x4a, 0xf9,
+    0xf1, 0xae, 0x56, 0x24, 0x8f, 0xe3, 0x8e, 0xe7, 0x7e, 0x6f, 0xcf, 0x92,
+    0xdf, 0xa9, 0x75, 0x3a, 0xd6, 0x2e, 0x1c, 0xaf, 0xf2, 0xd6, 0x8b, 0x39,
+    0xad, 0xd2, 0x5d, 0xfb, 0xd7, 0xdf, 0x05, 0x57, 0x0d, 0xf7, 0xf6, 0x8f,
+    0x2d, 0x14, 0xb0, 0x4e, 0x1a, 0x3c, 0x77, 0x04, 0xcd, 0x3c, 0x5c, 0x58,
+    0x52, 0x10, 0x6f, 0xcf, 0x5c, 0x03, 0xc8, 0x5f, 0x85, 0x2b, 0x05, 0x82,
+    0x60, 0xda, 0xcc, 0xcd, 0xd6, 0x88, 0xbf, 0xc0, 0x10, 0xb3, 0x6f, 0x54,
+    0x54, 0x42, 0xbc, 0x4b, 0x77, 0x21, 0x4d, 0xee, 0x87, 0x45, 0x06, 0x4c,
+    0x60, 0x38, 0xd2, 0x7e, 0x1d, 0x30, 0x6c, 0x55, 0xf0, 0x38, 0x80, 0x1c,
+    0xde, 0x3d, 0xea, 0x68, 0x3e, 0xf6, 0x3e, 0x59, 0xcf, 0x0d, 0x08, 0xae,
+    0x8c, 0x02, 0x0b, 0xc1, 0x72, 0x6a, 0xb4, 0x6d, 0xf3, 0xf7, 0xb3, 0xef,
+    0x3a, 0xb1, 0x06, 0xf2, 0xf4, 0xd6, 0x69, 0x7b, 0x3e, 0xa2, 0x16, 0x31,
+    0x31, 0x79, 0xb6, 0x33, 0xa9, 0xca, 0x8a, 0xa8, 0xbe, 0xf3, 0xe9, 0x38,
+    0x28, 0xd1, 0xe1, 0x3b, 0x4e, 0x2e, 0x47, 0x35, 0xa4, 0x61, 0x14, 0x1e,
+    0x42, 0x2c, 0x49, 0x55, 0xea, 0xe3, 0xb3, 0xce, 0x39, 0xd3, 0xb3, 0xef,
+    0x4a, 0x4d, 0x78, 0x49, 0xbd, 0xf6, 0x7c, 0x0a, 0x2c, 0xd3, 0x26, 0xcb,
+    0xd9, 0x6a, 0xad, 0x63, 0x93, 0xa7, 0x29, 0x92, 0xdc, 0x1f, 0xaf, 0x61,
+    0x82, 0x80, 0x74, 0xb2, 0x9c, 0x4a, 0x86, 0x73, 0x50, 0xd8, 0xd1, 0xff,
+    0xee, 0x1a, 0xe2, 0xdd, 0xa2, 0x61, 0xbd, 0x10, 0xc3, 0x5f, 0x67, 0x9f,
+    0x29, 0xe4, 0xd3, 0x70, 0xe5, 0x67, 0x3a, 0xd2, 0x20, 0x00, 0xcc, 0x25,
+    0x15, 0x96, 0x54, 0x45, 0x85, 0xed, 0x82, 0x88, 0x3b, 0x9f, 0x3b, 0xc3,
+    0x04, 0xd4, 0x23, 0xb1, 0x0d, 0xdc, 0xc8, 0x26, 0x9d, 0x28, 0xb3, 0x25,
+    0x4d, 0x52, 0xe5, 0x33, 0xf3, 0xed, 0x2c, 0xb8, 0x1a, 0xcf, 0xc3, 0x52,
+    0xb4, 0x2f, 0xc7, 0x79, 0x96, 0x14, 0x7d, 0x72, 0x27, 0x72, 0x85, 0xea,
+    0x6d, 0x41, 0xa0, 0x22, 0x13, 0x6d, 0x06, 0x83, 0xa4, 0xdd, 0x0f, 0x69,
+    0xd2, 0x01, 0xcd, 0xc6, 0xb8, 0x64, 0x5c, 0x2c, 0x79, 0xd1, 0xc7, 0xd3,
+    0x31, 0xdb, 0x2c, 0xff, 0xda, 0xd0, 0x69, 0x31, 0xad, 0x83, 0x5f, 0xed,
+    0x6a, 0x97, 0xe4, 0x00, 0x43, 0xb0, 0x2e, 0x97, 0xae, 0x00, 0x5f, 0x5c,
+    0xb9, 0xe8, 0x39, 0x80, 0x10, 0xca, 0x0c, 0xfa, 0xf0, 0xb5, 0xcd, 0xaa,
+    0x27, 0x11, 0x60, 0xd9, 0x21, 0x86, 0x93, 0x91, 0x9f, 0x2d, 0x1a, 0x8e,
+    0xde, 0x0b, 0xb5, 0xcb, 0x05, 0x24, 0x30, 0x45, 0x4d, 0x11, 0x75, 0xfd,
+    0xe5, 0xa0, 0xa9, 0x4e, 0x3a, 0x8c, 0x3b, 0x52, 0x5a, 0x37, 0x18, 0x05,
+    0x4a, 0x7a, 0x09, 0x6a, 0xe6, 0xd5, 0xa9, 0xa6, 0x71, 0x47, 0x4c, 0x50,
+    0xe1, 0x3e, 0x8a, 0x21, 0x2b, 0x4f, 0x0e, 0xe3, 0xcb, 0x72, 0xc5, 0x28,
+    0x3e, 0x5a, 0x33, 0xec, 0x48, 0x92, 0x2e, 0xa1, 0x24, 0x57, 0x09, 0x0f,
+    0x01, 0x85, 0x3b, 0x34, 0x39, 0x7e, 0xc7, 0x90, 0x62, 0xe2, 0xdc, 0x5d,
+    0x0a, 0x2c, 0x51, 0x26, 0x95, 0x3a, 0x95, 0x92, 0xa5, 0x39, 0x8f, 0x0c,
+    0x83, 0x0b, 0x9d, 0x38, 0xab, 0x98, 0x2a, 0xc4, 0x01, 0xc4, 0x0d, 0x77,
+    0x13, 0xcb, 0xca, 0xf1, 0x28, 0x31, 0x52, 0x75, 0x27, 0x2c, 0xf0, 0x04,
+    0x86, 0xc8, 0xf3, 0x3d, 0xf2, 0x9d, 0x8f, 0x55, 0x52, 0x40, 0x3f, 0xaa,
+    0x22, 0x7f, 0xe7, 0x69, 0x3b, 0xee, 0x44, 0x09, 0xde, 0xff, 0xb0, 0x69,
+    0x3a, 0xae, 0x74, 0xe9, 0x9d, 0x33, 0xae, 0x8b, 0x6d, 0x60, 0x04, 0xff,
+    0x53, 0x3f, 0x88, 0xe9, 0x63, 0x9b, 0xb1, 0x6d, 0x2c, 0x22, 0x15, 0x5a,
+    0x15, 0xd9, 0xe5, 0xcb, 0x03, 0x78, 0x3c, 0xca, 0x59, 0x8c, 0xc8, 0xc2,
+    0x86, 0xff, 0xd2, 0x79, 0xd6, 0xc6, 0xec, 0x5b, 0xbb, 0xa0, 0xae, 0x01,
+    0x20, 0x09, 0x2e, 0x38, 0x5d, 0xda, 0x5d, 0xe0, 0x59, 0x4e, 0xe5, 0x8b,
+    0x84, 0x8f, 0xb6, 0xe0, 0x56, 0x9f, 0x21, 0xa1, 0xcf, 0xb2, 0x0f, 0x2c,
+    0x93, 0xf8, 0xcf, 0x37, 0xc1, 0x9f, 0x32, 0x98, 0x21, 0x65, 0x52, 0x66,
+    0x6e, 0xd3, 0x71, 0x98, 0x55, 0xb9, 0x46, 0x9f, 0x1a, 0x35, 0xc4, 0x47,
+    0x69, 0x62, 0x70, 0x4b, 0x77, 0x9e, 0xe4, 0x21, 0xe6, 0x32, 0x5a, 0x26,
+    0x05, 0xba, 0x57, 0x53, 0xd7, 0x9b, 0x55, 0x3c, 0xbb, 0x53, 0x79, 0x60,
+    0x9c, 0xc8, 0x4d, 0xf7, 0xf5, 0x1d, 0x54, 0x02, 0x91, 0x68, 0x0e, 0xaa,
+    0xca, 0x5a, 0x78, 0x0c, 0x28, 0x9a, 0xc3, 0xac, 0x49, 0xc0, 0xf4, 0x85,
+    0xee, 0x59, 0x76, 0x7e, 0x28, 0x4e, 0xf1, 0x5c, 0x63, 0xf7, 0xce, 0x0e,
+    0x2c, 0x21, 0xa0, 0x58, 0xe9, 0x01, 0xfd, 0xeb, 0xd1, 0xaf, 0xe6, 0xef,
+    0x93, 0xb3, 0x95, 0x51, 0x60, 0xa2, 0x74, 0x40, 0x15, 0xe5, 0xf4, 0x0a,
+    0xca, 0x6d, 0x9a, 0x37, 0x42, 0x4d, 0x5a, 0x58, 0x49, 0x0f, 0xe9, 0x02,
+    0xfc, 0x77, 0xd8, 0x59, 0xde, 0xdd, 0xad, 0x4b, 0x99, 0x2e, 0x64, 0x73,
+    0xad, 0x42, 0x2f, 0xf3, 0x2c, 0x0d, 0x49, 0xe4, 0x2e, 0x6c, 0xa4, 0x73,
+    0x75, 0x18, 0x14, 0x85, 0xbb, 0x64, 0xb4, 0xa1, 0xb0, 0x6e, 0x01, 0xc0,
+    0xcf, 0x17, 0x9c, 0xc5, 0x28, 0xc3, 0x2d, 0x6c, 0x17, 0x2a, 0x3d, 0x06,
+    0x5c, 0xf3, 0xb4, 0x49, 0x75, 0xad, 0x17, 0x69, 0xd4, 0xca, 0x65, 0xae,
+    0x44, 0x71, 0xa5, 0xf6, 0x0d, 0x0f, 0x8e, 0x37, 0xc7, 0x43, 0xce, 0x6b,
+    0x08, 0xe9, 0xd1, 0x34, 0x48, 0x8f, 0xc9, 0xfc, 0xf3, 0x5d, 0x2d, 0xec,
+    0x62, 0xd3, 0xf0, 0xb3, 0xfe, 0x2e, 0x40, 0x55, 0x76, 0x54, 0xc7, 0xb4,
+    0x61, 0x16, 0xcc, 0x7c, 0x1c, 0x19, 0x24, 0xe6, 0x4d, 0xd4, 0xc3, 0x77,
+    0x67, 0x1f, 0x3c, 0x74, 0x79, 0xa1, 0xf8, 0x85, 0x88, 0x1d, 0x6f, 0xa4,
+    0x7e, 0x2c, 0x21, 0x9f, 0x49, 0xf5, 0xaa, 0x4e, 0xf3, 0x4a, 0xfa, 0x9d,
+    0xbe, 0xf6, 0xce, 0xda, 0xb5, 0xab, 0x39, 0xbd, 0x16, 0x41, 0xa9, 0x4a,
+    0xac, 0x09, 0x01, 0xca,
+};
+static const uint8_t kOutput[] = {
+    0x54, 0x30, 0x6a, 0x13, 0xda, 0x59, 0x6b, 0x6d, 0x59, 0x49, 0xc8, 0xc5,
+    0xab, 0x26, 0xd4, 0x8a, 0xad, 0xc0, 0x3d, 0xaf, 0x14, 0xb9, 0x15, 0xb8,
+    0xca, 0xdf, 0x17, 0xa7, 0x03, 0xd3, 0xc5, 0x06, 0x01, 0xef, 0x21, 0xdd,
+    0xa3, 0x0b, 0x9e, 0x48, 0xb8, 0x5e, 0x0b, 0x87, 0x9f, 0x95, 0x23, 0x68,
+    0x85, 0x69, 0xd2, 0x5d, 0xaf, 0x57, 0xe9, 0x27, 0x11, 0x3d, 0x49, 0xfa,
+    0xf1, 0x08, 0xcc, 0x15, 0xec, 0x1d, 0x19, 0x16, 0x12, 0x9b, 0xc8, 0x66,
+    0x1f, 0xfa, 0x2c, 0x93, 0xf4, 0x99, 0x11, 0x27, 0x31, 0x0e, 0xd8, 0x46,
+    0x47, 0x40, 0x11, 0x70, 0x01, 0xca, 0xe8, 0x5b, 0xc5, 0x91, 0xc8, 0x3a,
+    0xdc, 0xaa, 0xf3, 0x4b, 0x80, 0xe5, 0xbc, 0x03, 0xd0, 0x89, 0x72, 0xbc,
+    0xce, 0x2a, 0x76, 0x0c, 0xf5, 0xda, 0x4c, 0x10, 0x06, 0x35, 0x41, 0xb1,
+    0xe6, 0xb4, 0xaa, 0x7a, 0xef, 0xf0, 0x62, 0x4a, 0xc5, 0x9f, 0x2c, 0xaf,
+    0xb8, 0x2f, 0xd9, 0xd1, 0x01, 0x7a, 0x36, 0x2f, 0x3e, 0x83, 0xa5, 0xeb,
+    0x81, 0x70, 0xa0, 0x57, 0x17, 0x46, 0xea, 0x9e, 0xcb, 0x0e, 0x74, 0xd3,
+    0x44, 0x57, 0x1d, 0x40, 0x06, 0xf8, 0xb7, 0xcb, 0x5f, 0xf4, 0x79, 0xbd,
+    0x11, 0x19, 0xd6, 0xee, 0xf8, 0xb0, 0xaa, 0xdd, 0x00, 0x62, 0xad, 0x3b,
+    0x88, 0x9a, 0x88, 0x5b, 0x1b, 0x07, 0xc9, 0xae, 0x9e, 0xa6, 0x94, 0xe5,
+    0x55, 0xdb, 0x45, 0x23, 0xb9, 0x2c, 0xcd, 0x29, 0xd3, 0x54, 0xc3, 0x88,
+    0x1e, 0x5f, 0x52, 0xf2, 0x09, 0x00, 0x26, 0x26, 0x1a, 0xed, 0xf5, 0xc2,
+    0xa9, 0x7d, 0xf9, 0x21, 0x5a, 0xaf, 0x6d, 0xab, 0x8e, 0x16, 0x84, 0x96,
+    0xb5, 0x4f, 0xcf, 0x1e, 0xa3, 0xaf, 0x08, 0x9f, 0x79, 0x86, 0xc3, 0xbe,
+    0x0c, 0x70, 0xcb, 0x8f, 0xf3, 0xc5, 0xf8, 0xe8, 0x4b, 0x21, 0x7d, 0x18,
+    0xa9, 0xed, 0x8b, 0xfb, 0x6b, 0x5a, 0x6f, 0x26, 0x0b, 0x56, 0x04, 0x7c,
+    0xfe, 0x0e, 0x1e, 0xc1, 0x3f, 0x82, 0xc5, 0x73, 0xbd, 0x53, 0x0c, 0xf0,
+    0xe2, 0xc9, 0xf3, 0x3d, 0x1b, 0x6d, 0xba, 0x70, 0xc1, 0x6d, 0xb6, 0x00,
+    0x28, 0xe1, 0xc4, 0x78, 0x62, 0x04, 0xda, 0x23, 0x86, 0xc3, 0xda, 0x74,
+    0x3d, 0x7c, 0xd6, 0x76, 0x29, 0xb2, 0x27, 0x2e, 0xb2, 0x35, 0x42, 0x60,
+    0x82, 0xcf, 0x30, 0x2c, 0x59, 0xe4, 0xe3, 0xd0, 0x74, 0x1f, 0x58, 0xe8,
+    0xda, 0x47, 0x45, 0x73, 0x1c, 0x05, 0x93, 0xae, 0x75, 0xbe, 0x1f, 0x81,
+    0xd8, 0xb7, 0xb3, 0xff, 0xfc, 0x8b, 0x52, 0x9e, 0xed, 0x8b, 0x37, 0x9f,
+    0xe0, 0xb8, 0xa2, 0x66, 0xe1, 0x6a, 0xc5, 0x1f, 0x1d, 0xf0, 0xde, 0x3f,
+    0x3d, 0xb0, 0x28, 0xf3, 0xaa, 0x4e, 0x4d, 0x31, 0xb0, 0x26, 0x79, 0x2b,
+    0x08, 0x0f, 0xe9, 0x2f, 0x79, 0xb3, 0xc8, 0xdd, 0xa7, 0x89, 0xa8, 0xa8,
+    0x1d, 0x59, 0x0e, 0x4f, 0x1e, 0x93, 0x1f, 0x70, 0x7f, 0x4e, 0x7e, 0xfe,
+    0xb8, 0xca, 0x63, 0xe0, 0xa6, 0x05, 0xcc, 0xd7, 0xde, 0x2a, 0x49, 0x31,
+    0x78, 0x5c, 0x5f, 0x44, 0xb2, 0x9b, 0x91, 0x99, 0x14, 0x29, 0x63, 0x09,
+    0x12, 0xdd, 0x02, 0xd9, 0x7b, 0xe9, 0xf5, 0x12, 0x07, 0xd0, 0xe7, 0xe6,
+    0xe8, 0xdd, 0xda, 0xa4, 0x73, 0xc4, 0x8e, 0xbd, 0x7b, 0xb7, 0xbb, 0xcb,
+    0x83, 0x2f, 0x43, 0xf6, 0x1c, 0x50, 0xae, 0x9b, 0x2e, 0x52, 0x80, 0x18,
+    0x85, 0xa8, 0x23, 0x52, 0x7a, 0x6a, 0xf7, 0x42, 0x36, 0xca, 0x91, 0x5a,
+    0x3d, 0x2a, 0xa0, 0x35, 0x7d, 0x70, 0xfc, 0x4c, 0x18, 0x7c, 0x57, 0x72,
+    0xcf, 0x9b, 0x29, 0xd6, 0xd0, 0xb4, 0xd7, 0xe6, 0x89, 0x70, 0x69, 0x22,
+    0x5e, 0x45, 0x09, 0x4d, 0x49, 0x87, 0x84, 0x5f, 0x8a, 0x5f, 0xe4, 0x15,
+    0xd3, 0xe3, 0x72, 0xaf, 0xb2, 0x30, 0x9c, 0xc1, 0xff, 0x8e, 0x6d, 0x2a,
+    0x76, 0x9e, 0x08, 0x03, 0x7e, 0xe0, 0xc3, 0xc2, 0x97, 0x06, 0x6b, 0x33,
+    0x2b, 0x08, 0xe3, 0xd5, 0x0b, 0xd8, 0x32, 0x67, 0x61, 0x10, 0xed, 0x6b,
+    0xed, 0x50, 0xef, 0xd7, 0x1c, 0x1b, 0xe0, 0x6d, 0xa1, 0x64, 0x19, 0x34,
+    0x2f, 0xe4, 0xe8, 0x54, 0xbf, 0x84, 0x0e, 0xdf, 0x0e, 0x8b, 0xd8, 0xdd,
+    0x77, 0x96, 0xb8, 0x54, 0xab, 0xf2, 0x95, 0x59, 0x0d, 0x0d, 0x0a, 0x15,
+    0x6e, 0x01, 0xf2, 0x24, 0xab, 0xa0, 0xd8, 0xdf, 0x38, 0xea, 0x97, 0x58,
+    0x76, 0x88, 0xbe, 0xaf, 0x45, 0xe3, 0x56, 0x4f, 0x68, 0xe8, 0x4b, 0xe7,
+    0x2b, 0x22, 0x18, 0x96, 0x82, 0x89, 0x25, 0x34, 0xd1, 0xdd, 0x08, 0xea,
+    0x7e, 0x21, 0xef, 0x57, 0x55, 0x43, 0xf7, 0xfa, 0xca, 0x1c, 0xde, 0x99,
+    0x2e, 0x8b, 0xd8, 0xc3, 0xcf, 0x89, 0x4d, 0xfc, 0x3b, 0x7d, 0x4a, 0xc9,
+    0x99, 0xc4, 0x31, 0xb6, 0x7a, 0xae, 0xf8, 0x49, 0xb2, 0x46, 0xc1, 0x60,
+    0x05, 0x75, 0xf3, 0x3d, 0xf2, 0xc9, 0x84, 0xa4, 0xb9, 0x8a, 0x87, 0x2a,
+    0x87, 0x5c, 0x0a, 0xbc, 0x51, 0x7d, 0x9a, 0xf5, 0xc9, 0x24, 0x2d, 0x5e,
+    0xe6, 0xc6, 0xe3, 0xcd, 0x7e, 0xe4, 0xaf, 0x8a, 0x6c, 0x00, 0x04, 0xc8,
+    0xd7, 0xa5, 0xad, 0xfa, 0xb2, 0x08, 0x4a, 0x26, 0x9b, 0x7c, 0xd0, 0xc6,
+    0x13, 0xb1, 0xb9, 0x65, 0x3f, 0x70, 0x30, 0xf9, 0x98, 0x9d, 0x87, 0x99,
+    0x57, 0x71, 0x3e, 0xb1, 0xc3, 0x24, 0xf0, 0xa6, 0xa2, 0x60, 0x9d, 0x66,
+    0xd2, 0x5f, 0xae, 0xe3, 0x94, 0x87, 0xea, 0xd1, 0xea, 0x0d, 0x2a, 0x77,
+    0xef, 0x31, 0xcc, 0xeb, 0xf9, 0x0c, 0xdc, 0x9c, 0x12, 0x80, 0xbb, 0xb0,
+    0x8e, 0xab, 0x9a, 0x04, 0xcd, 0x4b, 0x95, 0x4f, 0x7a, 0x0b, 0x53, 0x7c,
+    0x16, 0xcc, 0x0e, 0xb1, 0x73, 0x10, 0xdd, 0xaa, 0x76, 0x94, 0x90, 0xd9,
+    0x8b, 0x66, 0x41, 0x31, 0xed, 0x8c, 0x7d, 0x74, 0xc4, 0x33, 0xfa, 0xc3,
+    0x43, 0x8d, 0x10, 0xbc, 0x84, 0x4d, 0x0e, 0x95, 0x32, 0xdf, 0x17, 0x43,
+    0x6d, 0xd2, 0x5e, 0x12, 0xb9, 0xed, 0x33, 0xd9, 0x97, 0x6f, 0x4a, 0xcd,
+    0xc3, 0xcd, 0x81, 0x34, 0xbe, 0x7e, 0xa2, 0xd0, 0xa7, 0x91, 0x5d, 0x90,
+    0xf6, 0x5e, 0x4a, 0x25, 0x0f, 0xcc, 0x24, 0xeb, 0xe1, 0xe4, 0x62, 0x6c,
+    0x8f, 0x45, 0x36, 0x97, 0x5d, 0xda, 0x20, 0x2b, 0x86, 0x00, 0x8c, 0x94,
+    0xa9, 0x6a, 0x69, 0xb2, 0xe9, 0xbb, 0x82, 0x8e, 0x41, 0x95, 0xb4, 0xb7,
+    0xf1, 0x55, 0x52, 0x30, 0x39, 0x48, 0xb3, 0x25, 0x82, 0xa9, 0x10, 0x27,
+    0x89, 0xb5, 0xe5, 0x1f, 0xab, 0x72, 0x3c, 0x70, 0x08, 0xce, 0xe6, 0x61,
+    0xbf, 0x19, 0xc8, 0x90, 0x2b, 0x29, 0x30, 0x3e, 0xb8, 0x4c, 0x33, 0xf0,
+    0xf0, 0x15, 0x2e, 0xb7, 0x25, 0xca, 0x99, 0x4b, 0x6f, 0x4b, 0x41, 0x50,
+    0xee, 0x56, 0x99, 0xcf, 0x2b, 0xa4, 0xc4, 0x7c, 0x5c, 0xa6, 0xd4, 0x67,
+    0x04, 0x5c, 0x5d, 0x5f, 0x26, 0x9e, 0x0f, 0xe2, 0x58, 0x68, 0x4c, 0x30,
+    0xcd, 0xef, 0x46, 0xdb, 0x37, 0x6f, 0xbb, 0xc4, 0x80, 0xca, 0x8a, 0x54,
+    0x5d, 0x71, 0x9d, 0x0c, 0xe8, 0xb8, 0x2c, 0x10, 0x90, 0x44, 0xa4, 0x88,
+    0x3f, 0xbc, 0x15, 0x3c, 0xd2, 0xca, 0x0e, 0xc3, 0xe4, 0x6e, 0xef, 0xb0,
+    0xcb, 0xfd, 0x61, 0x7c, 0x27, 0xf2, 0x25, 0xea, 0x71, 0x6d, 0xf7, 0x49,
+    0x9c, 0x81, 0x27, 0xf0, 0x61, 0x33, 0xcf, 0x55, 0x68, 0xd3, 0x73, 0xa4,
+    0xed, 0x35, 0x65, 0x2a, 0xf2, 0x3e, 0xcf, 0x90, 0x98, 0x54, 0x6d, 0x95,
+    0x6a, 0x0c, 0x9c, 0x24, 0x0e, 0xb4, 0xb7, 0x9b, 0x8d, 0x6e, 0x1c, 0xbc,
+    0xeb, 0x17, 0x10, 0x86, 0xda, 0x91, 0x6d, 0x89, 0x4c, 0xeb, 0xf5, 0x50,
+    0x8f, 0x40, 0xcf, 0x4a,
+};
+
+static_assert(sizeof(kInput) == sizeof(kOutput),
+              "Input and output lengths don't match.");
+
+TEST(ChaChaTest, TestVector) {
+  // Run the test with the test vector at all lengths.
+  for (size_t len = 0; len <= sizeof(kInput); len++) {
+    SCOPED_TRACE(len);
+
+    std::unique_ptr<uint8_t[]> buf(new uint8_t[len]);
+    CRYPTO_chacha_20(buf.get(), kInput, len, kKey, kNonce, kCounter);
+    EXPECT_EQ(Bytes(kOutput, len), Bytes(buf.get(), len));
+
+    // Test the in-place version.
+    OPENSSL_memcpy(buf.get(), kInput, len);
+    CRYPTO_chacha_20(buf.get(), buf.get(), len, kKey, kNonce, kCounter);
+    EXPECT_EQ(Bytes(kOutput, len), Bytes(buf.get(), len));
+  }
+}
diff --git a/src/crypto/chacha/chacha_vec.c b/src/crypto/chacha/chacha_vec.c
deleted file mode 100644
index addbaa3..0000000
--- a/src/crypto/chacha/chacha_vec.c
+++ /dev/null
@@ -1,323 +0,0 @@
-/* Copyright (c) 2014, Google Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
-
-/* ====================================================================
- *
- * When updating this file, also update chacha_vec_arm.S
- *
- * ==================================================================== */
-
-
-/* This implementation is by Ted Krovetz and was submitted to SUPERCOP and
- * marked as public domain. It was been altered to allow for non-aligned inputs
- * and to allow the block counter to be passed in specifically. */
-
-#include <openssl/chacha.h>
-
-#if defined(ASM_GEN) ||          \
-    !defined(OPENSSL_WINDOWS) && \
-        (defined(OPENSSL_X86_64) || defined(OPENSSL_X86)) && defined(__SSE2__)
-
-#define CHACHA_RNDS 20 /* 8 (high speed), 20 (conservative), 12 (middle) */
-
-/* Architecture-neutral way to specify 16-byte vector of ints              */
-typedef unsigned vec __attribute__((vector_size(16)));
-
-/* This implementation is designed for Neon, SSE and AltiVec machines. The
- * following specify how to do certain vector operations efficiently on
- * each architecture, using intrinsics.
- * This implementation supports parallel processing of multiple blocks,
- * including potentially using general-purpose registers. */
-#if __ARM_NEON__
-#include <string.h>
-#include <arm_neon.h>
-#define GPR_TOO 1
-#define VBPI 2
-#define ONE (vec) vsetq_lane_u32(1, vdupq_n_u32(0), 0)
-#define LOAD_ALIGNED(m) (vec)(*((vec *)(m)))
-#define LOAD(m) ({ \
-    memcpy(alignment_buffer, m, 16); \
-    LOAD_ALIGNED(alignment_buffer); \
-  })
-#define STORE(m, r) ({ \
-    (*((vec *)(alignment_buffer))) = (r); \
-    memcpy(m, alignment_buffer, 16); \
-  })
-#define ROTV1(x) (vec) vextq_u32((uint32x4_t)x, (uint32x4_t)x, 1)
-#define ROTV2(x) (vec) vextq_u32((uint32x4_t)x, (uint32x4_t)x, 2)
-#define ROTV3(x) (vec) vextq_u32((uint32x4_t)x, (uint32x4_t)x, 3)
-#define ROTW16(x) (vec) vrev32q_u16((uint16x8_t)x)
-#if __clang__
-#define ROTW7(x) (x << ((vec) {7, 7, 7, 7})) ^ (x >> ((vec) {25, 25, 25, 25}))
-#define ROTW8(x) (x << ((vec) {8, 8, 8, 8})) ^ (x >> ((vec) {24, 24, 24, 24}))
-#define ROTW12(x) \
-  (x << ((vec) {12, 12, 12, 12})) ^ (x >> ((vec) {20, 20, 20, 20}))
-#else
-#define ROTW7(x) \
-  (vec) vsriq_n_u32(vshlq_n_u32((uint32x4_t)x, 7), (uint32x4_t)x, 25)
-#define ROTW8(x) \
-  (vec) vsriq_n_u32(vshlq_n_u32((uint32x4_t)x, 8), (uint32x4_t)x, 24)
-#define ROTW12(x) \
-  (vec) vsriq_n_u32(vshlq_n_u32((uint32x4_t)x, 12), (uint32x4_t)x, 20)
-#endif
-#elif __SSE2__
-#include <emmintrin.h>
-#define GPR_TOO 0
-#if __clang__
-#define VBPI 4
-#else
-#define VBPI 3
-#endif
-#define ONE (vec) _mm_set_epi32(0, 0, 0, 1)
-#define LOAD(m) (vec) _mm_loadu_si128((__m128i *)(m))
-#define LOAD_ALIGNED(m) (vec) _mm_load_si128((__m128i *)(m))
-#define STORE(m, r) _mm_storeu_si128((__m128i *)(m), (__m128i)(r))
-#define ROTV1(x) (vec) _mm_shuffle_epi32((__m128i)x, _MM_SHUFFLE(0, 3, 2, 1))
-#define ROTV2(x) (vec) _mm_shuffle_epi32((__m128i)x, _MM_SHUFFLE(1, 0, 3, 2))
-#define ROTV3(x) (vec) _mm_shuffle_epi32((__m128i)x, _MM_SHUFFLE(2, 1, 0, 3))
-#define ROTW7(x) \
-  (vec)(_mm_slli_epi32((__m128i)x, 7) ^ _mm_srli_epi32((__m128i)x, 25))
-#define ROTW12(x) \
-  (vec)(_mm_slli_epi32((__m128i)x, 12) ^ _mm_srli_epi32((__m128i)x, 20))
-#if __SSSE3__
-#include <tmmintrin.h>
-#define ROTW8(x)                                                            \
-  (vec) _mm_shuffle_epi8((__m128i)x, _mm_set_epi8(14, 13, 12, 15, 10, 9, 8, \
-                                                  11, 6, 5, 4, 7, 2, 1, 0, 3))
-#define ROTW16(x)                                                           \
-  (vec) _mm_shuffle_epi8((__m128i)x, _mm_set_epi8(13, 12, 15, 14, 9, 8, 11, \
-                                                  10, 5, 4, 7, 6, 1, 0, 3, 2))
-#else
-#define ROTW8(x) \
-  (vec)(_mm_slli_epi32((__m128i)x, 8) ^ _mm_srli_epi32((__m128i)x, 24))
-#define ROTW16(x) \
-  (vec)(_mm_slli_epi32((__m128i)x, 16) ^ _mm_srli_epi32((__m128i)x, 16))
-#endif
-#else
-#error-- Implementation supports only machines with neon or SSE2
-#endif
-
-#ifndef REVV_BE
-#define REVV_BE(x)  (x)
-#endif
-
-#ifndef REVW_BE
-#define REVW_BE(x)  (x)
-#endif
-
-#define BPI      (VBPI + GPR_TOO)  /* Blocks computed per loop iteration   */
-
-#define DQROUND_VECTORS(a,b,c,d)                \
-    a += b; d ^= a; d = ROTW16(d);              \
-    c += d; b ^= c; b = ROTW12(b);              \
-    a += b; d ^= a; d = ROTW8(d);               \
-    c += d; b ^= c; b = ROTW7(b);               \
-    b = ROTV1(b); c = ROTV2(c);  d = ROTV3(d);  \
-    a += b; d ^= a; d = ROTW16(d);              \
-    c += d; b ^= c; b = ROTW12(b);              \
-    a += b; d ^= a; d = ROTW8(d);               \
-    c += d; b ^= c; b = ROTW7(b);               \
-    b = ROTV3(b); c = ROTV2(c); d = ROTV1(d);
-
-#define QROUND_WORDS(a,b,c,d) \
-  a = a+b; d ^= a; d = d<<16 | d>>16; \
-  c = c+d; b ^= c; b = b<<12 | b>>20; \
-  a = a+b; d ^= a; d = d<< 8 | d>>24; \
-  c = c+d; b ^= c; b = b<< 7 | b>>25;
-
-#define WRITE_XOR(in, op, d, v0, v1, v2, v3)                   \
-	STORE(op + d + 0, LOAD(in + d + 0) ^ REVV_BE(v0));      \
-	STORE(op + d + 4, LOAD(in + d + 4) ^ REVV_BE(v1));      \
-	STORE(op + d + 8, LOAD(in + d + 8) ^ REVV_BE(v2));      \
-	STORE(op + d +12, LOAD(in + d +12) ^ REVV_BE(v3));
-
-#if __ARM_NEON__
-/* For ARM, we can't depend on NEON support, so this function is compiled with
- * a different name, along with the generic code, and can be enabled at
- * run-time. */
-void CRYPTO_chacha_20_neon(
-#else
-void CRYPTO_chacha_20(
-#endif
-	uint8_t *out,
-	const uint8_t *in,
-	size_t inlen,
-	const uint8_t key[32],
-	const uint8_t nonce[12],
-	uint32_t counter)
-	{
-	unsigned iters, i, *op=(unsigned *)out, *ip=(unsigned *)in, *kp;
-#if defined(__ARM_NEON__)
-	uint32_t np[3];
-	uint8_t alignment_buffer[16] __attribute__((aligned(16)));
-#endif
-	vec s0, s1, s2, s3;
-	__attribute__ ((aligned (16))) unsigned chacha_const[] =
-		{0x61707865,0x3320646E,0x79622D32,0x6B206574};
-	kp = (unsigned *)key;
-#if defined(__ARM_NEON__)
-	memcpy(np, nonce, 12);
-#endif
-	s0 = LOAD_ALIGNED(chacha_const);
-	s1 = LOAD(&((vec*)kp)[0]);
-	s2 = LOAD(&((vec*)kp)[1]);
-	s3 = (vec){
-		counter,
-		((uint32_t*)nonce)[0],
-		((uint32_t*)nonce)[1],
-		((uint32_t*)nonce)[2]
-	};
-
-	for (iters = 0; iters < inlen/(BPI*64); iters++)
-		{
-#if GPR_TOO
-		register unsigned x0, x1, x2, x3, x4, x5, x6, x7, x8,
-				  x9, x10, x11, x12, x13, x14, x15;
-#endif
-#if VBPI > 2
-		vec v8,v9,v10,v11;
-#endif
-#if VBPI > 3
-		vec v12,v13,v14,v15;
-#endif
-
-		vec v0,v1,v2,v3,v4,v5,v6,v7;
-		v4 = v0 = s0; v5 = v1 = s1; v6 = v2 = s2; v3 = s3;
-		v7 = v3 + ONE;
-#if VBPI > 2
-		v8 = v4; v9 = v5; v10 = v6;
-		v11 =  v7 + ONE;
-#endif
-#if VBPI > 3
-		v12 = v8; v13 = v9; v14 = v10;
-		v15 = v11 + ONE;
-#endif
-#if GPR_TOO
-		x0 = chacha_const[0]; x1 = chacha_const[1];
-		x2 = chacha_const[2]; x3 = chacha_const[3];
-		x4 = kp[0]; x5 = kp[1]; x6  = kp[2]; x7  = kp[3];
-		x8 = kp[4]; x9 = kp[5]; x10 = kp[6]; x11 = kp[7];
-		x12 = counter+BPI*iters+(BPI-1); x13 = np[0];
-		x14 = np[1]; x15 = np[2];
-#endif
-		for (i = CHACHA_RNDS/2; i; i--)
-			{
-			DQROUND_VECTORS(v0,v1,v2,v3)
-			DQROUND_VECTORS(v4,v5,v6,v7)
-#if VBPI > 2
-			DQROUND_VECTORS(v8,v9,v10,v11)
-#endif
-#if VBPI > 3
-			DQROUND_VECTORS(v12,v13,v14,v15)
-#endif
-#if GPR_TOO
-			QROUND_WORDS( x0, x4, x8,x12)
-			QROUND_WORDS( x1, x5, x9,x13)
-			QROUND_WORDS( x2, x6,x10,x14)
-			QROUND_WORDS( x3, x7,x11,x15)
-			QROUND_WORDS( x0, x5,x10,x15)
-			QROUND_WORDS( x1, x6,x11,x12)
-			QROUND_WORDS( x2, x7, x8,x13)
-			QROUND_WORDS( x3, x4, x9,x14)
-#endif
-			}
-
-		WRITE_XOR(ip, op, 0, v0+s0, v1+s1, v2+s2, v3+s3)
-		s3 += ONE;
-		WRITE_XOR(ip, op, 16, v4+s0, v5+s1, v6+s2, v7+s3)
-		s3 += ONE;
-#if VBPI > 2
-		WRITE_XOR(ip, op, 32, v8+s0, v9+s1, v10+s2, v11+s3)
-		s3 += ONE;
-#endif
-#if VBPI > 3
-		WRITE_XOR(ip, op, 48, v12+s0, v13+s1, v14+s2, v15+s3)
-		s3 += ONE;
-#endif
-		ip += VBPI*16;
-		op += VBPI*16;
-#if GPR_TOO
-		op[0]  = REVW_BE(REVW_BE(ip[0])  ^ (x0  + chacha_const[0]));
-		op[1]  = REVW_BE(REVW_BE(ip[1])  ^ (x1  + chacha_const[1]));
-		op[2]  = REVW_BE(REVW_BE(ip[2])  ^ (x2  + chacha_const[2]));
-		op[3]  = REVW_BE(REVW_BE(ip[3])  ^ (x3  + chacha_const[3]));
-		op[4]  = REVW_BE(REVW_BE(ip[4])  ^ (x4  + kp[0]));
-		op[5]  = REVW_BE(REVW_BE(ip[5])  ^ (x5  + kp[1]));
-		op[6]  = REVW_BE(REVW_BE(ip[6])  ^ (x6  + kp[2]));
-		op[7]  = REVW_BE(REVW_BE(ip[7])  ^ (x7  + kp[3]));
-		op[8]  = REVW_BE(REVW_BE(ip[8])  ^ (x8  + kp[4]));
-		op[9]  = REVW_BE(REVW_BE(ip[9])  ^ (x9  + kp[5]));
-		op[10] = REVW_BE(REVW_BE(ip[10]) ^ (x10 + kp[6]));
-		op[11] = REVW_BE(REVW_BE(ip[11]) ^ (x11 + kp[7]));
-		op[12] = REVW_BE(REVW_BE(ip[12]) ^ (x12 + counter+BPI*iters+(BPI-1)));
-		op[13] = REVW_BE(REVW_BE(ip[13]) ^ (x13 + np[0]));
-		op[14] = REVW_BE(REVW_BE(ip[14]) ^ (x14 + np[1]));
-		op[15] = REVW_BE(REVW_BE(ip[15]) ^ (x15 + np[2]));
-		s3 += ONE;
-		ip += 16;
-		op += 16;
-#endif
-		}
-
-	for (iters = inlen%(BPI*64)/64; iters != 0; iters--)
-		{
-		vec v0 = s0, v1 = s1, v2 = s2, v3 = s3;
-		for (i = CHACHA_RNDS/2; i; i--)
-			{
-			DQROUND_VECTORS(v0,v1,v2,v3);
-			}
-		WRITE_XOR(ip, op, 0, v0+s0, v1+s1, v2+s2, v3+s3)
-		s3 += ONE;
-		ip += 16;
-		op += 16;
-		}
-
-	inlen = inlen % 64;
-	if (inlen)
-		{
-		__attribute__ ((aligned (16))) vec buf[4];
-		vec v0,v1,v2,v3;
-		v0 = s0; v1 = s1; v2 = s2; v3 = s3;
-		for (i = CHACHA_RNDS/2; i; i--)
-			{
-			DQROUND_VECTORS(v0,v1,v2,v3);
-			}
-
-		if (inlen >= 16)
-			{
-			STORE(op + 0, LOAD(ip + 0) ^ REVV_BE(v0 + s0));
-			if (inlen >= 32)
-				{
-				STORE(op + 4, LOAD(ip + 4) ^ REVV_BE(v1 + s1));
-				if (inlen >= 48)
-					{
-					STORE(op + 8, LOAD(ip +  8) ^
-						      REVV_BE(v2 + s2));
-					buf[3] = REVV_BE(v3 + s3);
-					}
-				else
-					buf[2] = REVV_BE(v2 + s2);
-				}
-			else
-				buf[1] = REVV_BE(v1 + s1);
-			}
-		else
-			buf[0] = REVV_BE(v0 + s0);
-
-		for (i=inlen & ~15; i<inlen; i++)
-			((char *)op)[i] = ((char *)ip)[i] ^ ((char *)buf)[i];
-		}
-	}
-
-#endif /* ASM_GEN || !OPENSSL_WINDOWS && (OPENSSL_X86_64 || OPENSSL_X86) && SSE2 */
diff --git a/src/crypto/chacha/chacha_vec_arm.S b/src/crypto/chacha/chacha_vec_arm.S
deleted file mode 100644
index f18c867..0000000
--- a/src/crypto/chacha/chacha_vec_arm.S
+++ /dev/null
@@ -1,1447 +0,0 @@
-# Copyright (c) 2014, Google Inc.
-#
-# Permission to use, copy, modify, and/or distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
-# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-# This file contains a pre-compiled version of chacha_vec.c for ARM. This is
-# needed to support switching on NEON code at runtime. If the whole of OpenSSL
-# were to be compiled with the needed flags to build chacha_vec.c, then it
-# wouldn't be possible to run on non-NEON systems.
-#
-# This file was generated by chacha_vec_arm_generate.go using the following
-# compiler command:
-#
-#     /opt/gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc -O3 -mcpu=cortex-a8 -mfpu=neon -fpic -DASM_GEN -I ../../include -S chacha_vec.c -o -
-
-#if !defined(OPENSSL_NO_ASM)
-#if defined(__arm__)
-
-	.syntax unified
-	.cpu cortex-a8
-	.eabi_attribute 27, 3
-
-# EABI attribute 28 sets whether VFP register arguments were used to build this
-# file. If object files are inconsistent on this point, the linker will refuse
-# to link them. Thus we report whatever the compiler expects since we don't use
-# VFP arguments.
-
-#if defined(__ARM_PCS_VFP)
-	.eabi_attribute 28, 1
-#else
-	.eabi_attribute 28, 0
-#endif
-
-	.fpu neon
-	.eabi_attribute 20, 1
-	.eabi_attribute 21, 1
-	.eabi_attribute 23, 3
-	.eabi_attribute 24, 1
-	.eabi_attribute 25, 1
-	.eabi_attribute 26, 2
-	.eabi_attribute 30, 2
-	.eabi_attribute 34, 1
-	.eabi_attribute 18, 4
-	.thumb
-	.file	"chacha_vec.c"
-	.text
-	.align	2
-	.global	CRYPTO_chacha_20_neon
-	.hidden	CRYPTO_chacha_20_neon
-	.thumb
-	.thumb_func
-	.type	CRYPTO_chacha_20_neon, %function
-CRYPTO_chacha_20_neon:
-	@ args = 8, pretend = 0, frame = 160
-	@ frame_needed = 1, uses_anonymous_args = 0
-	push	{r4, r5, r6, r7, r8, r9, r10, fp, lr}
-	mov	r9, r3
-	vpush.64	{d8, d9, d10, d11, d12, d13, d14, d15}
-	mov	r10, r2
-	ldr	r4, .L91+16
-	mov	fp, r1
-	mov	r8, r9
-.LPIC16:
-	add	r4, pc
-	sub	sp, sp, #164
-	add	r7, sp, #0
-	sub	sp, sp, #112
-	add	lr, r7, #148
-	str	r0, [r7, #80]
-	str	r1, [r7, #12]
-	str	r2, [r7, #8]
-	ldmia	r4, {r0, r1, r2, r3}
-	add	r4, sp, #15
-	bic	r4, r4, #15
-	ldr	r6, [r7, #264]
-	str	r4, [r7, #88]
-	mov	r5, r4
-	adds	r4, r4, #64
-	add	ip, r5, #80
-	str	r9, [r7, #56]
-	stmia	r4, {r0, r1, r2, r3}
-	movw	r4, #43691
-	ldr	r0, [r6]	@ unaligned
-	movt	r4, 43690
-	ldr	r1, [r6, #4]	@ unaligned
-	ldr	r2, [r6, #8]	@ unaligned
-	ldr	r3, [r9, #12]	@ unaligned
-	str	ip, [r7, #84]
-	stmia	lr!, {r0, r1, r2}
-	mov	lr, ip
-	ldr	r1, [r9, #4]	@ unaligned
-	ldr	r2, [r9, #8]	@ unaligned
-	ldr	r0, [r9]	@ unaligned
-	vldr	d24, [r5, #64]
-	vldr	d25, [r5, #72]
-	umull	r4, r5, r10, r4
-	stmia	ip!, {r0, r1, r2, r3}
-	ldr	r0, [r8, #16]!	@ unaligned
-	ldr	r2, [r7, #88]
-	ldr	r4, [r7, #268]
-	ldr	r1, [r8, #4]	@ unaligned
-	vldr	d26, [r2, #80]
-	vldr	d27, [r2, #88]
-	ldr	r3, [r8, #12]	@ unaligned
-	ldr	r2, [r8, #8]	@ unaligned
-	stmia	lr!, {r0, r1, r2, r3}
-	ldr	r3, [r6]
-	ldr	r1, [r6, #4]
-	ldr	r6, [r6, #8]
-	str	r3, [r7, #68]
-	str	r3, [r7, #132]
-	lsrs	r3, r5, #7
-	str	r6, [r7, #140]
-	str	r6, [r7, #60]
-	ldr	r6, [r7, #88]
-	str	r4, [r7, #128]
-	str	r1, [r7, #136]
-	str	r1, [r7, #64]
-	vldr	d28, [r6, #80]
-	vldr	d29, [r6, #88]
-	vldr	d22, [r7, #128]
-	vldr	d23, [r7, #136]
-	beq	.L26
-	mov	r5, r6
-	lsls	r2, r3, #8
-	sub	r3, r2, r3, lsl #6
-	ldr	r2, [r5, #68]
-	ldr	r6, [r6, #64]
-	vldr	d0, .L91
-	vldr	d1, .L91+8
-	str	r2, [r7, #48]
-	ldr	r2, [r5, #72]
-	str	r3, [r7, #4]
-	str	r6, [r7, #52]
-	str	r2, [r7, #44]
-	adds	r2, r4, #2
-	str	r2, [r7, #72]
-	ldr	r2, [r5, #76]
-	str	fp, [r7, #76]
-	str	r2, [r7, #40]
-	ldr	r2, [r7, #80]
-	adds	r3, r2, r3
-	str	r3, [r7, #16]
-.L4:
-	ldr	r5, [r7, #56]
-	add	r8, r7, #40
-	ldr	r4, [r7, #68]
-	vadd.i32	q3, q11, q0
-	ldmia	r8, {r8, r9, r10, fp}
-	mov	r1, r5
-	ldr	r2, [r5, #4]
-	vmov	q8, q14  @ v4si
-	ldr	r3, [r5]
-	vmov	q1, q13  @ v4si
-	ldr	r6, [r1, #28]
-	vmov	q9, q12  @ v4si
-	mov	r0, r2
-	ldr	r2, [r5, #8]
-	str	r4, [r7, #112]
-	movs	r1, #10
-	ldr	r4, [r7, #72]
-	vmov	q2, q11  @ v4si
-	ldr	lr, [r5, #20]
-	vmov	q15, q14  @ v4si
-	str	r3, [r7, #108]
-	vmov	q5, q13  @ v4si
-	str	r2, [r7, #116]
-	vmov	q10, q12  @ v4si
-	ldr	r2, [r5, #12]
-	ldr	ip, [r5, #16]
-	ldr	r3, [r7, #64]
-	ldr	r5, [r5, #24]
-	str	r6, [r7, #120]
-	str	r1, [r7, #92]
-	ldr	r6, [r7, #60]
-	str	r4, [r7, #100]
-	ldr	r1, [r7, #116]
-	ldr	r4, [r7, #108]
-	str	r8, [r7, #96]
-	mov	r8, r10
-	str	lr, [r7, #104]
-	mov	r10, r9
-	mov	lr, r3
-	mov	r9, r5
-	str	r6, [r7, #124]
-	b	.L92
-.L93:
-	.align	3
-.L91:
-	.word	1
-	.word	0
-	.word	0
-	.word	0
-	.word	.LANCHOR0-(.LPIC16+4)
-.L92:
-.L3:
-	vadd.i32	q9, q9, q1
-	add	r3, r8, r0
-	vadd.i32	q10, q10, q5
-	add	r5, fp, r4
-	veor	q3, q3, q9
-	mov	r6, r3
-	veor	q2, q2, q10
-	ldr	r3, [r7, #96]
-	str	r5, [r7, #116]
-	add	r10, r10, r1
-	vrev32.16	q3, q3
-	str	r6, [r7, #108]
-	vadd.i32	q8, q8, q3
-	vrev32.16	q2, q2
-	vadd.i32	q15, q15, q2
-	mov	fp, r3
-	ldr	r3, [r7, #100]
-	veor	q4, q8, q1
-	veor	q6, q15, q5
-	add	fp, fp, r2
-	eors	r3, r3, r5
-	mov	r5, r6
-	ldr	r6, [r7, #112]
-	vshl.i32	q1, q4, #12
-	vshl.i32	q5, q6, #12
-	ror	r3, r3, #16
-	eors	r6, r6, r5
-	eor	lr, lr, r10
-	vsri.32	q1, q4, #20
-	mov	r5, r6
-	ldr	r6, [r7, #124]
-	vsri.32	q5, q6, #20
-	str	r3, [r7, #124]
-	eor	r6, r6, fp
-	ror	r5, r5, #16
-	vadd.i32	q9, q9, q1
-	ror	lr, lr, #16
-	ror	r3, r6, #16
-	ldr	r6, [r7, #124]
-	vadd.i32	q10, q10, q5
-	add	r9, r9, lr
-	veor	q4, q9, q3
-	add	ip, ip, r6
-	ldr	r6, [r7, #104]
-	veor	q6, q10, q2
-	eor	r4, ip, r4
-	str	r3, [r7, #104]
-	vshl.i32	q3, q4, #8
-	eor	r1, r9, r1
-	mov	r8, r6
-	ldr	r6, [r7, #120]
-	vshl.i32	q2, q6, #8
-	ror	r4, r4, #20
-	add	r6, r6, r3
-	vsri.32	q3, q4, #24
-	str	r6, [r7, #100]
-	eors	r2, r2, r6
-	ldr	r6, [r7, #116]
-	vsri.32	q2, q6, #24
-	add	r8, r8, r5
-	ror	r2, r2, #20
-	adds	r6, r4, r6
-	vadd.i32	q4, q8, q3
-	eor	r0, r8, r0
-	vadd.i32	q15, q15, q2
-	mov	r3, r6
-	ldr	r6, [r7, #108]
-	veor	q6, q4, q1
-	ror	r0, r0, #20
-	str	r3, [r7, #112]
-	veor	q5, q15, q5
-	adds	r6, r0, r6
-	str	r6, [r7, #120]
-	mov	r6, r3
-	ldr	r3, [r7, #124]
-	vshl.i32	q8, q6, #7
-	add	fp, fp, r2
-	eors	r3, r3, r6
-	ldr	r6, [r7, #120]
-	vshl.i32	q1, q5, #7
-	ror	r1, r1, #20
-	eors	r5, r5, r6
-	vsri.32	q8, q6, #25
-	ldr	r6, [r7, #104]
-	ror	r3, r3, #24
-	ror	r5, r5, #24
-	vsri.32	q1, q5, #25
-	str	r5, [r7, #116]
-	eor	r6, fp, r6
-	ldr	r5, [r7, #116]
-	add	r10, r10, r1
-	add	ip, r3, ip
-	vext.32	q8, q8, q8, #1
-	str	ip, [r7, #124]
-	add	ip, r5, r8
-	ldr	r5, [r7, #100]
-	eor	lr, r10, lr
-	ror	r6, r6, #24
-	vext.32	q1, q1, q1, #1
-	add	r8, r6, r5
-	vadd.i32	q9, q9, q8
-	ldr	r5, [r7, #124]
-	vext.32	q3, q3, q3, #3
-	vadd.i32	q10, q10, q1
-	ror	lr, lr, #24
-	eor	r0, ip, r0
-	vext.32	q2, q2, q2, #3
-	add	r9, r9, lr
-	eors	r4, r4, r5
-	veor	q3, q9, q3
-	ldr	r5, [r7, #112]
-	eor	r1, r9, r1
-	ror	r0, r0, #25
-	veor	q2, q10, q2
-	adds	r5, r0, r5
-	vext.32	q4, q4, q4, #2
-	str	r5, [r7, #112]
-	ldr	r5, [r7, #120]
-	ror	r1, r1, #25
-	vrev32.16	q3, q3
-	eor	r2, r8, r2
-	vext.32	q15, q15, q15, #2
-	adds	r5, r1, r5
-	vadd.i32	q4, q4, q3
-	ror	r4, r4, #25
-	vrev32.16	q2, q2
-	str	r5, [r7, #100]
-	vadd.i32	q15, q15, q2
-	eors	r3, r3, r5
-	ldr	r5, [r7, #112]
-	add	fp, fp, r4
-	veor	q8, q4, q8
-	ror	r2, r2, #25
-	veor	q1, q15, q1
-	eor	lr, fp, lr
-	eors	r6, r6, r5
-	ror	r3, r3, #16
-	ldr	r5, [r7, #116]
-	add	r10, r10, r2
-	str	r3, [r7, #120]
-	ror	lr, lr, #16
-	ldr	r3, [r7, #120]
-	eor	r5, r10, r5
-	vshl.i32	q5, q8, #12
-	add	ip, lr, ip
-	vshl.i32	q6, q1, #12
-	str	ip, [r7, #104]
-	add	ip, r3, r8
-	str	ip, [r7, #116]
-	ldr	r3, [r7, #124]
-	ror	r5, r5, #16
-	vsri.32	q5, q8, #20
-	ror	r6, r6, #16
-	add	ip, r5, r3
-	ldr	r3, [r7, #104]
-	vsri.32	q6, q1, #20
-	add	r9, r9, r6
-	eor	r2, ip, r2
-	eors	r4, r4, r3
-	ldr	r3, [r7, #116]
-	eor	r0, r9, r0
-	vadd.i32	q9, q9, q5
-	ror	r4, r4, #20
-	eors	r1, r1, r3
-	vadd.i32	q10, q10, q6
-	ror	r3, r2, #20
-	str	r3, [r7, #108]
-	ldr	r3, [r7, #112]
-	veor	q3, q9, q3
-	ror	r0, r0, #20
-	add	r8, r4, fp
-	veor	q2, q10, q2
-	add	fp, r0, r3
-	ldr	r3, [r7, #100]
-	ror	r1, r1, #20
-	mov	r2, r8
-	vshl.i32	q8, q3, #8
-	str	r8, [r7, #96]
-	add	r8, r1, r3
-	ldr	r3, [r7, #108]
-	vmov	q1, q6  @ v4si
-	vshl.i32	q6, q2, #8
-	eor	r6, fp, r6
-	add	r10, r10, r3
-	ldr	r3, [r7, #120]
-	vsri.32	q8, q3, #24
-	eor	lr, r2, lr
-	eor	r3, r8, r3
-	ror	r2, r6, #24
-	vsri.32	q6, q2, #24
-	eor	r5, r10, r5
-	str	r2, [r7, #124]
-	ror	r2, r3, #24
-	ldr	r3, [r7, #104]
-	vmov	q3, q8  @ v4si
-	vadd.i32	q15, q15, q6
-	ror	lr, lr, #24
-	vadd.i32	q8, q4, q8
-	ror	r6, r5, #24
-	add	r5, lr, r3
-	ldr	r3, [r7, #124]
-	veor	q4, q8, q5
-	add	ip, ip, r6
-	vmov	q2, q6  @ v4si
-	add	r9, r9, r3
-	veor	q6, q15, q1
-	ldr	r3, [r7, #116]
-	vshl.i32	q1, q4, #7
-	str	r2, [r7, #100]
-	add	r3, r3, r2
-	str	r3, [r7, #120]
-	vshl.i32	q5, q6, #7
-	eors	r1, r1, r3
-	ldr	r3, [r7, #108]
-	vsri.32	q1, q4, #25
-	eors	r4, r4, r5
-	eor	r0, r9, r0
-	eor	r2, ip, r3
-	vsri.32	q5, q6, #25
-	ldr	r3, [r7, #92]
-	ror	r4, r4, #25
-	str	r6, [r7, #112]
-	ror	r0, r0, #25
-	subs	r3, r3, #1
-	str	r5, [r7, #104]
-	ror	r1, r1, #25
-	ror	r2, r2, #25
-	vext.32	q15, q15, q15, #2
-	str	r3, [r7, #92]
-	vext.32	q2, q2, q2, #1
-	vext.32	q8, q8, q8, #2
-	vext.32	q3, q3, q3, #1
-	vext.32	q5, q5, q5, #3
-	vext.32	q1, q1, q1, #3
-	bne	.L3
-	ldr	r3, [r7, #84]
-	vadd.i32	q4, q12, q10
-	str	r9, [r7, #92]
-	mov	r9, r10
-	mov	r10, r8
-	ldr	r8, [r7, #96]
-	str	lr, [r7, #96]
-	mov	lr, r5
-	ldr	r5, [r7, #52]
-	vadd.i32	q5, q13, q5
-	ldr	r6, [r7, #76]
-	vadd.i32	q15, q14, q15
-	add	fp, fp, r5
-	ldr	r5, [r7, #48]
-	str	r3, [r7, #104]
-	vadd.i32	q7, q14, q8
-	ldr	r3, [r6, #12]	@ unaligned
-	add	r10, r10, r5
-	str	r0, [r7, #36]
-	vadd.i32	q2, q11, q2
-	ldr	r0, [r6]	@ unaligned
-	vadd.i32	q6, q12, q9
-	ldr	r5, [r7, #104]
-	vadd.i32	q1, q13, q1
-	str	r1, [r7, #116]
-	vadd.i32	q11, q11, q0
-	ldr	r1, [r6, #4]	@ unaligned
-	str	r2, [r7, #32]
-	vadd.i32	q3, q11, q3
-	ldr	r2, [r6, #8]	@ unaligned
-	vadd.i32	q11, q11, q0
-	str	r4, [r7, #108]
-	ldr	r4, [r7, #100]
-	vadd.i32	q11, q11, q0
-	stmia	r5!, {r0, r1, r2, r3}
-	ldr	r2, [r7, #88]
-	ldr	r3, [r7, #44]
-	ldr	r5, [r7, #84]
-	vldr	d20, [r2, #80]
-	vldr	d21, [r2, #88]
-	add	r3, r9, r3
-	str	r3, [r7, #104]
-	veor	q10, q10, q4
-	ldr	r3, [r7, #40]
-	add	r3, r8, r3
-	str	r3, [r7, #100]
-	ldr	r3, [r7, #72]
-	vstr	d20, [r2, #80]
-	vstr	d21, [r2, #88]
-	adds	r1, r4, r3
-	str	r1, [r7, #28]
-	ldmia	r5!, {r0, r1, r2, r3}
-	ldr	r4, [r7, #68]
-	ldr	r5, [r7, #112]
-	ldr	r8, [r7, #84]
-	add	r5, r5, r4
-	ldr	r4, [r7, #96]
-	str	r5, [r7, #24]
-	ldr	r5, [r7, #64]
-	add	r4, r4, r5
-	ldr	r5, [r7, #60]
-	str	r4, [r7, #96]
-	ldr	r4, [r7, #124]
-	add	r4, r4, r5
-	str	r4, [r7, #20]
-	ldr	r4, [r7, #80]
-	mov	r5, r8
-	str	r0, [r4]	@ unaligned
-	mov	r0, r4
-	str	r1, [r4, #4]	@ unaligned
-	mov	r4, r8
-	str	r2, [r0, #8]	@ unaligned
-	mov	r8, r0
-	str	r3, [r0, #12]	@ unaligned
-	mov	r9, r4
-	ldr	r0, [r6, #16]!	@ unaligned
-	ldr	r3, [r6, #12]	@ unaligned
-	ldr	r1, [r6, #4]	@ unaligned
-	ldr	r2, [r6, #8]	@ unaligned
-	ldr	r6, [r7, #76]
-	stmia	r5!, {r0, r1, r2, r3}
-	mov	r5, r8
-	ldr	r3, [r7, #88]
-	vldr	d20, [r3, #80]
-	vldr	d21, [r3, #88]
-	veor	q10, q10, q5
-	vstr	d20, [r3, #80]
-	vstr	d21, [r3, #88]
-	ldmia	r4!, {r0, r1, r2, r3}
-	mov	r4, r9
-	str	r0, [r8, #16]	@ unaligned
-	str	r1, [r8, #20]	@ unaligned
-	str	r2, [r8, #24]	@ unaligned
-	str	r3, [r8, #28]	@ unaligned
-	mov	r8, r5
-	ldr	r0, [r6, #32]!	@ unaligned
-	mov	r5, r9
-	ldr	r1, [r6, #4]	@ unaligned
-	ldr	r2, [r6, #8]	@ unaligned
-	ldr	r3, [r6, #12]	@ unaligned
-	ldr	r6, [r7, #76]
-	stmia	r5!, {r0, r1, r2, r3}
-	mov	r5, r8
-	ldr	r1, [r7, #88]
-	vldr	d16, [r1, #80]
-	vldr	d17, [r1, #88]
-	veor	q15, q8, q15
-	vstr	d30, [r1, #80]
-	vstr	d31, [r1, #88]
-	ldmia	r4!, {r0, r1, r2, r3}
-	mov	r4, r9
-	str	r0, [r8, #32]	@ unaligned
-	str	r1, [r8, #36]	@ unaligned
-	str	r2, [r8, #40]	@ unaligned
-	str	r3, [r8, #44]	@ unaligned
-	mov	r8, r5
-	ldr	r0, [r6, #48]!	@ unaligned
-	ldr	r1, [r6, #4]	@ unaligned
-	ldr	r2, [r6, #8]	@ unaligned
-	ldr	r3, [r6, #12]	@ unaligned
-	ldr	r6, [r7, #76]
-	stmia	r4!, {r0, r1, r2, r3}
-	mov	r4, r9
-	ldr	r1, [r7, #88]
-	str	r9, [r7, #112]
-	vldr	d18, [r1, #80]
-	vldr	d19, [r1, #88]
-	veor	q9, q9, q2
-	vstr	d18, [r1, #80]
-	vstr	d19, [r1, #88]
-	ldmia	r9!, {r0, r1, r2, r3}
-	str	r0, [r5, #48]	@ unaligned
-	str	r1, [r5, #52]	@ unaligned
-	str	r2, [r5, #56]	@ unaligned
-	str	r3, [r5, #60]	@ unaligned
-	ldr	r0, [r6, #64]!	@ unaligned
-	ldr	r1, [r6, #4]	@ unaligned
-	ldr	r2, [r6, #8]	@ unaligned
-	ldr	r3, [r6, #12]	@ unaligned
-	ldr	r6, [r7, #76]
-	mov	r9, r6
-	mov	r6, r4
-	stmia	r6!, {r0, r1, r2, r3}
-	mov	r6, r4
-	ldr	r1, [r7, #88]
-	vldr	d18, [r1, #80]
-	vldr	d19, [r1, #88]
-	veor	q9, q9, q6
-	vstr	d18, [r1, #80]
-	vstr	d19, [r1, #88]
-	ldmia	r4!, {r0, r1, r2, r3}
-	mov	r4, r6
-	str	r3, [r5, #76]	@ unaligned
-	mov	r3, r9
-	str	r2, [r5, #72]	@ unaligned
-	str	r0, [r5, #64]	@ unaligned
-	str	r1, [r5, #68]	@ unaligned
-	mov	r5, r4
-	ldr	r0, [r3, #80]!	@ unaligned
-	mov	r9, r3
-	ldr	r1, [r9, #4]	@ unaligned
-	ldr	r2, [r9, #8]	@ unaligned
-	ldr	r3, [r9, #12]	@ unaligned
-	mov	r9, r4
-	ldr	r6, [r7, #76]
-	str	r9, [r7, #124]
-	stmia	r5!, {r0, r1, r2, r3}
-	mov	r5, r8
-	ldr	r1, [r7, #88]
-	vldr	d18, [r1, #80]
-	vldr	d19, [r1, #88]
-	veor	q1, q9, q1
-	vstr	d2, [r1, #80]
-	vstr	d3, [r1, #88]
-	ldmia	r4!, {r0, r1, r2, r3}
-	mov	r4, r9
-	str	r0, [r8, #80]	@ unaligned
-	str	r1, [r8, #84]	@ unaligned
-	str	r2, [r8, #88]	@ unaligned
-	str	r3, [r8, #92]	@ unaligned
-	ldr	r0, [r6, #96]!	@ unaligned
-	ldr	r3, [r6, #12]	@ unaligned
-	ldr	r1, [r6, #4]	@ unaligned
-	ldr	r2, [r6, #8]	@ unaligned
-	ldr	r6, [r7, #76]
-	stmia	r4!, {r0, r1, r2, r3}
-	mov	r4, r9
-	ldr	r3, [r7, #88]
-	vldr	d16, [r3, #80]
-	vldr	d17, [r3, #88]
-	veor	q8, q8, q7
-	vstr	d16, [r3, #80]
-	vstr	d17, [r3, #88]
-	ldmia	r9!, {r0, r1, r2, r3}
-	str	r0, [r5, #96]	@ unaligned
-	str	r1, [r5, #100]	@ unaligned
-	str	r2, [r5, #104]	@ unaligned
-	str	r3, [r5, #108]	@ unaligned
-	ldr	r0, [r6, #112]!	@ unaligned
-	ldr	r1, [r6, #4]	@ unaligned
-	ldr	r2, [r6, #8]	@ unaligned
-	ldr	r3, [r6, #12]	@ unaligned
-	mov	r6, r4
-	stmia	r6!, {r0, r1, r2, r3}
-	mov	r6, r5
-	ldr	r3, [r7, #88]
-	vldr	d16, [r3, #80]
-	vldr	d17, [r3, #88]
-	veor	q8, q8, q3
-	vstr	d16, [r3, #80]
-	vstr	d17, [r3, #88]
-	ldmia	r4!, {r0, r1, r2, r3}
-	mov	r4, r5
-	mov	r8, r4
-	str	r2, [r5, #120]	@ unaligned
-	ldr	r2, [r7, #76]
-	str	r0, [r5, #112]	@ unaligned
-	str	r1, [r5, #116]	@ unaligned
-	str	r3, [r5, #124]	@ unaligned
-	ldr	r3, [r2, #128]
-	ldr	r1, [r7, #104]
-	eor	r3, fp, r3
-	str	r3, [r5, #128]
-	ldr	r3, [r2, #132]
-	mov	r5, r2
-	eor	r3, r10, r3
-	str	r3, [r6, #132]
-	ldr	r3, [r2, #136]
-	mov	r6, r5
-	eors	r1, r1, r3
-	str	r1, [r8, #136]
-	ldr	r1, [r7, #56]
-	ldr	r3, [r2, #140]
-	ldr	r2, [r7, #100]
-	ldr	r0, [r7, #108]
-	eors	r3, r3, r2
-	str	r3, [r4, #140]
-	ldr	r3, [r1]
-	ldr	r2, [r5, #144]
-	mov	r8, r0
-	add	r8, r8, r3
-	mov	r5, r6
-	mov	r3, r8
-	eors	r2, r2, r3
-	str	r2, [r4, #144]
-	ldr	r3, [r6, #148]
-	ldr	r2, [r1, #4]
-	ldr	r6, [r7, #36]
-	add	r6, r6, r2
-	eors	r3, r3, r6
-	mov	r6, r1
-	str	r3, [r4, #148]
-	ldr	r2, [r1, #8]
-	ldr	r1, [r7, #116]
-	ldr	r3, [r5, #152]
-	mov	r8, r1
-	add	r8, r8, r2
-	ldr	r1, [r7, #32]
-	mov	r2, r8
-	eors	r3, r3, r2
-	str	r3, [r4, #152]
-	mov	r8, r4
-	ldr	r2, [r6, #12]
-	ldr	r3, [r5, #156]
-	add	r1, r1, r2
-	eors	r3, r3, r1
-	str	r3, [r4, #156]
-	ldr	r2, [r6, #16]
-	mov	r1, r4
-	ldr	r3, [r5, #160]
-	mov	r4, r5
-	add	ip, ip, r2
-	mov	r5, r6
-	eor	r3, ip, r3
-	str	r3, [r1, #160]
-	ldr	r2, [r6, #20]
-	ldr	r3, [r4, #164]
-	add	lr, lr, r2
-	ldr	r2, [r7, #92]
-	eor	r3, lr, r3
-	str	r3, [r1, #164]
-	ldr	r6, [r5, #24]
-	mov	lr, r4
-	ldr	r3, [r4, #168]
-	add	r2, r2, r6
-	ldr	r6, [r7, #120]
-	eors	r3, r3, r2
-	str	r3, [r1, #168]
-	ldr	r5, [r5, #28]
-	ldr	r3, [r4, #172]
-	add	r6, r6, r5
-	eors	r3, r3, r6
-	str	r3, [r1, #172]
-	ldr	r4, [r4, #176]
-	ldr	r0, [r7, #28]
-	ldr	r5, [r7, #24]
-	eors	r4, r4, r0
-	str	r4, [r8, #176]
-	ldr	r0, [lr, #180]
-	ldr	r2, [r7, #96]
-	eors	r0, r0, r5
-	str	r0, [r8, #180]
-	ldr	r1, [lr, #184]
-	ldr	r4, [r7, #20]
-	eors	r1, r1, r2
-	str	r1, [r8, #184]
-	ldr	r2, [lr, #188]
-	add	r1, lr, #192
-	ldr	r3, [r7, #72]
-	eors	r2, r2, r4
-	str	r2, [r8, #188]
-	ldr	r2, [r7, #16]
-	adds	r3, r3, #3
-	str	r3, [r7, #72]
-	mov	r3, r8
-	adds	r3, r3, #192
-	str	r1, [r7, #76]
-	cmp	r2, r3
-	str	r3, [r7, #80]
-	bne	.L4
-	ldr	r3, [r7, #12]
-	ldr	r2, [r7, #4]
-	add	r3, r3, r2
-	str	r3, [r7, #12]
-.L2:
-	ldr	r1, [r7, #8]
-	movw	r2, #43691
-	movt	r2, 43690
-	umull	r2, r3, r1, r2
-	lsr	fp, r3, #7
-	lsl	r3, fp, #8
-	sub	fp, r3, fp, lsl #6
-	rsb	fp, fp, r1
-	lsrs	fp, fp, #6
-	beq	.L6
-	ldr	r5, [r7, #12]
-	ldr	r4, [r7, #16]
-	ldr	r6, [r7, #88]
-	ldr	lr, [r7, #84]
-	vldr	d30, .L94
-	vldr	d31, .L94+8
-	str	fp, [r7, #120]
-	str	fp, [r7, #124]
-.L8:
-	vmov	q2, q11  @ v4si
-	movs	r3, #10
-	vmov	q8, q14  @ v4si
-	vmov	q9, q13  @ v4si
-	vmov	q10, q12  @ v4si
-.L7:
-	vadd.i32	q10, q10, q9
-	subs	r3, r3, #1
-	veor	q3, q2, q10
-	vrev32.16	q3, q3
-	vadd.i32	q8, q8, q3
-	veor	q9, q8, q9
-	vshl.i32	q2, q9, #12
-	vsri.32	q2, q9, #20
-	vadd.i32	q10, q10, q2
-	veor	q3, q10, q3
-	vshl.i32	q9, q3, #8
-	vsri.32	q9, q3, #24
-	vadd.i32	q8, q8, q9
-	vext.32	q9, q9, q9, #3
-	veor	q2, q8, q2
-	vext.32	q8, q8, q8, #2
-	vshl.i32	q3, q2, #7
-	vsri.32	q3, q2, #25
-	vext.32	q3, q3, q3, #1
-	vadd.i32	q10, q10, q3
-	veor	q9, q10, q9
-	vrev32.16	q9, q9
-	vadd.i32	q8, q8, q9
-	veor	q3, q8, q3
-	vshl.i32	q2, q3, #12
-	vsri.32	q2, q3, #20
-	vadd.i32	q10, q10, q2
-	vmov	q3, q2  @ v4si
-	veor	q9, q10, q9
-	vshl.i32	q2, q9, #8
-	vsri.32	q2, q9, #24
-	vadd.i32	q8, q8, q2
-	vext.32	q2, q2, q2, #1
-	veor	q3, q8, q3
-	vext.32	q8, q8, q8, #2
-	vshl.i32	q9, q3, #7
-	vsri.32	q9, q3, #25
-	vext.32	q9, q9, q9, #3
-	bne	.L7
-	ldr	r0, [r5]	@ unaligned
-	vadd.i32	q1, q12, q10
-	ldr	r1, [r5, #4]	@ unaligned
-	mov	ip, lr
-	ldr	r2, [r5, #8]	@ unaligned
-	mov	r9, lr
-	ldr	r3, [r5, #12]	@ unaligned
-	mov	r10, r5
-	vadd.i32	q9, q13, q9
-	mov	r8, lr
-	vadd.i32	q8, q14, q8
-	stmia	ip!, {r0, r1, r2, r3}
-	mov	ip, lr
-	vldr	d20, [r6, #80]
-	vldr	d21, [r6, #88]
-	vadd.i32	q3, q11, q2
-	veor	q10, q10, q1
-	vadd.i32	q11, q11, q15
-	vstr	d20, [r6, #80]
-	vstr	d21, [r6, #88]
-	ldmia	r9!, {r0, r1, r2, r3}
-	mov	r9, r5
-	str	r0, [r4]	@ unaligned
-	str	r1, [r4, #4]	@ unaligned
-	str	r2, [r4, #8]	@ unaligned
-	str	r3, [r4, #12]	@ unaligned
-	ldr	r0, [r10, #16]!	@ unaligned
-	ldr	r1, [r10, #4]	@ unaligned
-	ldr	r2, [r10, #8]	@ unaligned
-	ldr	r3, [r10, #12]	@ unaligned
-	add	r10, r4, #48
-	adds	r4, r4, #64
-	stmia	r8!, {r0, r1, r2, r3}
-	mov	r8, lr
-	vldr	d20, [r6, #80]
-	vldr	d21, [r6, #88]
-	veor	q10, q10, q9
-	vstr	d20, [r6, #80]
-	vstr	d21, [r6, #88]
-	ldmia	ip!, {r0, r1, r2, r3}
-	mov	ip, lr
-	str	r0, [r4, #-48]	@ unaligned
-	str	r1, [r4, #-44]	@ unaligned
-	str	r2, [r4, #-40]	@ unaligned
-	str	r3, [r4, #-36]	@ unaligned
-	ldr	r0, [r9, #32]!	@ unaligned
-	ldr	r1, [r9, #4]	@ unaligned
-	ldr	r2, [r9, #8]	@ unaligned
-	ldr	r3, [r9, #12]	@ unaligned
-	mov	r9, r5
-	adds	r5, r5, #64
-	stmia	r8!, {r0, r1, r2, r3}
-	mov	r8, lr
-	vldr	d18, [r6, #80]
-	vldr	d19, [r6, #88]
-	veor	q9, q9, q8
-	vstr	d18, [r6, #80]
-	vstr	d19, [r6, #88]
-	ldmia	ip!, {r0, r1, r2, r3}
-	mov	ip, lr
-	str	r0, [r4, #-32]	@ unaligned
-	str	r1, [r4, #-28]	@ unaligned
-	str	r2, [r4, #-24]	@ unaligned
-	str	r3, [r4, #-20]	@ unaligned
-	ldr	r0, [r9, #48]!	@ unaligned
-	ldr	r1, [r9, #4]	@ unaligned
-	ldr	r2, [r9, #8]	@ unaligned
-	ldr	r3, [r9, #12]	@ unaligned
-	stmia	r8!, {r0, r1, r2, r3}
-	vldr	d16, [r6, #80]
-	vldr	d17, [r6, #88]
-	veor	q8, q8, q3
-	vstr	d16, [r6, #80]
-	vstr	d17, [r6, #88]
-	ldmia	ip!, {r0, r1, r2, r3}
-	str	r0, [r4, #-16]	@ unaligned
-	str	r1, [r4, #-12]	@ unaligned
-	str	r3, [r10, #12]	@ unaligned
-	ldr	r3, [r7, #124]
-	str	r2, [r10, #8]	@ unaligned
-	cmp	r3, #1
-	beq	.L87
-	movs	r3, #1
-	str	r3, [r7, #124]
-	b	.L8
-.L95:
-	.align	3
-.L94:
-	.word	1
-	.word	0
-	.word	0
-	.word	0
-.L87:
-	ldr	fp, [r7, #120]
-	ldr	r3, [r7, #12]
-	lsl	fp, fp, #6
-	add	r3, r3, fp
-	str	r3, [r7, #12]
-	ldr	r3, [r7, #16]
-	add	r3, r3, fp
-	str	r3, [r7, #16]
-.L6:
-	ldr	r3, [r7, #8]
-	ands	r9, r3, #63
-	beq	.L1
-	vmov	q3, q11  @ v4si
-	movs	r3, #10
-	vmov	q8, q14  @ v4si
-	mov	r5, r9
-	vmov	q15, q13  @ v4si
-	vmov	q10, q12  @ v4si
-.L10:
-	vadd.i32	q10, q10, q15
-	subs	r3, r3, #1
-	veor	q9, q3, q10
-	vrev32.16	q9, q9
-	vadd.i32	q8, q8, q9
-	veor	q15, q8, q15
-	vshl.i32	q3, q15, #12
-	vsri.32	q3, q15, #20
-	vadd.i32	q10, q10, q3
-	veor	q15, q10, q9
-	vshl.i32	q9, q15, #8
-	vsri.32	q9, q15, #24
-	vadd.i32	q8, q8, q9
-	vext.32	q9, q9, q9, #3
-	veor	q3, q8, q3
-	vext.32	q8, q8, q8, #2
-	vshl.i32	q15, q3, #7
-	vsri.32	q15, q3, #25
-	vext.32	q15, q15, q15, #1
-	vadd.i32	q10, q10, q15
-	veor	q9, q10, q9
-	vrev32.16	q9, q9
-	vadd.i32	q8, q8, q9
-	veor	q15, q8, q15
-	vshl.i32	q3, q15, #12
-	vsri.32	q3, q15, #20
-	vadd.i32	q10, q10, q3
-	vmov	q15, q3  @ v4si
-	veor	q9, q10, q9
-	vshl.i32	q3, q9, #8
-	vsri.32	q3, q9, #24
-	vadd.i32	q8, q8, q3
-	vext.32	q3, q3, q3, #1
-	veor	q9, q8, q15
-	vext.32	q8, q8, q8, #2
-	vshl.i32	q15, q9, #7
-	vsri.32	q15, q9, #25
-	vext.32	q15, q15, q15, #3
-	bne	.L10
-	cmp	r5, #15
-	mov	r9, r5
-	bhi	.L88
-	vadd.i32	q12, q12, q10
-	ldr	r3, [r7, #88]
-	vst1.64	{d24-d25}, [r3:128]
-.L14:
-	ldr	r3, [r7, #8]
-	and	r2, r3, #48
-	cmp	r9, r2
-	bls	.L1
-	ldr	r6, [r7, #16]
-	add	r3, r2, #16
-	ldr	r1, [r7, #12]
-	rsb	ip, r2, r9
-	adds	r0, r1, r2
-	mov	r4, r6
-	add	r1, r1, r3
-	add	r4, r4, r2
-	add	r3, r3, r6
-	cmp	r0, r3
-	it	cc
-	cmpcc	r4, r1
-	ite	cs
-	movcs	r3, #1
-	movcc	r3, #0
-	cmp	ip, #18
-	ite	ls
-	movls	r3, #0
-	andhi	r3, r3, #1
-	cmp	r3, #0
-	beq	.L16
-	and	r1, r0, #7
-	mov	r3, r2
-	negs	r1, r1
-	and	r1, r1, #15
-	cmp	r1, ip
-	it	cs
-	movcs	r1, ip
-	cmp	r1, #0
-	beq	.L17
-	ldr	r5, [r7, #88]
-	cmp	r1, #1
-	ldrb	r0, [r0]	@ zero_extendqisi2
-	add	r3, r2, #1
-	ldrb	lr, [r5, r2]	@ zero_extendqisi2
-	mov	r6, r5
-	eor	r0, lr, r0
-	strb	r0, [r4]
-	beq	.L17
-	ldr	r0, [r7, #12]
-	cmp	r1, #2
-	ldrb	r4, [r5, r3]	@ zero_extendqisi2
-	ldr	r5, [r7, #16]
-	ldrb	r0, [r0, r3]	@ zero_extendqisi2
-	eor	r0, r0, r4
-	strb	r0, [r5, r3]
-	add	r3, r2, #2
-	beq	.L17
-	ldr	r0, [r7, #12]
-	cmp	r1, #3
-	ldrb	r4, [r6, r3]	@ zero_extendqisi2
-	ldrb	r0, [r0, r3]	@ zero_extendqisi2
-	eor	r0, r0, r4
-	strb	r0, [r5, r3]
-	add	r3, r2, #3
-	beq	.L17
-	ldr	r0, [r7, #12]
-	cmp	r1, #4
-	ldrb	r4, [r6, r3]	@ zero_extendqisi2
-	ldrb	r0, [r0, r3]	@ zero_extendqisi2
-	eor	r0, r0, r4
-	strb	r0, [r5, r3]
-	add	r3, r2, #4
-	beq	.L17
-	ldr	r0, [r7, #12]
-	cmp	r1, #5
-	ldrb	r4, [r6, r3]	@ zero_extendqisi2
-	ldrb	r0, [r0, r3]	@ zero_extendqisi2
-	eor	r0, r0, r4
-	strb	r0, [r5, r3]
-	add	r3, r2, #5
-	beq	.L17
-	ldr	r0, [r7, #12]
-	cmp	r1, #6
-	ldrb	r4, [r6, r3]	@ zero_extendqisi2
-	ldrb	r0, [r0, r3]	@ zero_extendqisi2
-	eor	r0, r0, r4
-	strb	r0, [r5, r3]
-	add	r3, r2, #6
-	beq	.L17
-	ldr	r0, [r7, #12]
-	cmp	r1, #7
-	ldrb	r4, [r6, r3]	@ zero_extendqisi2
-	ldrb	r0, [r0, r3]	@ zero_extendqisi2
-	eor	r0, r0, r4
-	strb	r0, [r5, r3]
-	add	r3, r2, #7
-	beq	.L17
-	ldr	r0, [r7, #12]
-	cmp	r1, #8
-	ldrb	r4, [r6, r3]	@ zero_extendqisi2
-	ldrb	r0, [r0, r3]	@ zero_extendqisi2
-	eor	r0, r0, r4
-	strb	r0, [r5, r3]
-	add	r3, r2, #8
-	beq	.L17
-	ldr	r0, [r7, #12]
-	cmp	r1, #9
-	ldrb	r4, [r6, r3]	@ zero_extendqisi2
-	ldrb	r0, [r0, r3]	@ zero_extendqisi2
-	eor	r0, r0, r4
-	strb	r0, [r5, r3]
-	add	r3, r2, #9
-	beq	.L17
-	ldr	r0, [r7, #12]
-	cmp	r1, #10
-	ldrb	r4, [r6, r3]	@ zero_extendqisi2
-	ldrb	r0, [r0, r3]	@ zero_extendqisi2
-	eor	r0, r0, r4
-	strb	r0, [r5, r3]
-	add	r3, r2, #10
-	beq	.L17
-	ldr	r0, [r7, #12]
-	cmp	r1, #11
-	ldrb	r4, [r6, r3]	@ zero_extendqisi2
-	ldrb	r0, [r0, r3]	@ zero_extendqisi2
-	eor	r0, r0, r4
-	strb	r0, [r5, r3]
-	add	r3, r2, #11
-	beq	.L17
-	ldr	r0, [r7, #12]
-	cmp	r1, #12
-	ldrb	r4, [r6, r3]	@ zero_extendqisi2
-	ldrb	r0, [r0, r3]	@ zero_extendqisi2
-	eor	r0, r0, r4
-	strb	r0, [r5, r3]
-	add	r3, r2, #12
-	beq	.L17
-	ldr	r0, [r7, #12]
-	cmp	r1, #13
-	ldrb	r4, [r6, r3]	@ zero_extendqisi2
-	ldrb	r0, [r0, r3]	@ zero_extendqisi2
-	eor	r0, r0, r4
-	strb	r0, [r5, r3]
-	add	r3, r2, #13
-	beq	.L17
-	ldr	r0, [r7, #12]
-	cmp	r1, #15
-	ldrb	r4, [r6, r3]	@ zero_extendqisi2
-	ldrb	r0, [r0, r3]	@ zero_extendqisi2
-	eor	r0, r0, r4
-	strb	r0, [r5, r3]
-	add	r3, r2, #14
-	bne	.L17
-	ldr	r0, [r7, #12]
-	ldrb	r4, [r6, r3]	@ zero_extendqisi2
-	ldrb	r0, [r0, r3]	@ zero_extendqisi2
-	eors	r0, r0, r4
-	strb	r0, [r5, r3]
-	add	r3, r2, #15
-.L17:
-	rsb	r4, r1, ip
-	add	r0, ip, #-1
-	sub	r6, r4, #16
-	subs	r0, r0, r1
-	cmp	r0, #14
-	lsr	r6, r6, #4
-	add	r6, r6, #1
-	lsl	lr, r6, #4
-	bls	.L19
-	add	r2, r2, r1
-	ldr	r1, [r7, #12]
-	ldr	r5, [r7, #16]
-	cmp	r6, #1
-	add	r0, r1, r2
-	ldr	r1, [r7, #88]
-	add	r1, r1, r2
-	vld1.64	{d18-d19}, [r0:64]
-	add	r2, r2, r5
-	vld1.8	{q8}, [r1]
-	veor	q8, q8, q9
-	vst1.8	{q8}, [r2]
-	beq	.L20
-	add	r8, r1, #16
-	add	ip, r2, #16
-	vldr	d18, [r0, #16]
-	vldr	d19, [r0, #24]
-	cmp	r6, #2
-	vld1.8	{q8}, [r8]
-	veor	q8, q8, q9
-	vst1.8	{q8}, [ip]
-	beq	.L20
-	add	r8, r1, #32
-	add	ip, r2, #32
-	vldr	d18, [r0, #32]
-	vldr	d19, [r0, #40]
-	cmp	r6, #3
-	vld1.8	{q8}, [r8]
-	veor	q8, q8, q9
-	vst1.8	{q8}, [ip]
-	beq	.L20
-	adds	r1, r1, #48
-	adds	r2, r2, #48
-	vldr	d18, [r0, #48]
-	vldr	d19, [r0, #56]
-	vld1.8	{q8}, [r1]
-	veor	q8, q8, q9
-	vst1.8	{q8}, [r2]
-.L20:
-	cmp	lr, r4
-	add	r3, r3, lr
-	beq	.L1
-.L19:
-	ldr	r4, [r7, #88]
-	adds	r2, r3, #1
-	ldr	r1, [r7, #12]
-	cmp	r2, r9
-	ldr	r5, [r7, #16]
-	ldrb	r0, [r4, r3]	@ zero_extendqisi2
-	ldrb	r1, [r1, r3]	@ zero_extendqisi2
-	eor	r1, r1, r0
-	strb	r1, [r5, r3]
-	bcs	.L1
-	ldr	r0, [r7, #12]
-	adds	r1, r3, #2
-	mov	r6, r4
-	cmp	r9, r1
-	ldrb	r4, [r4, r2]	@ zero_extendqisi2
-	ldrb	r0, [r0, r2]	@ zero_extendqisi2
-	eor	r0, r0, r4
-	strb	r0, [r5, r2]
-	bls	.L1
-	ldr	r0, [r7, #12]
-	adds	r2, r3, #3
-	ldrb	r4, [r6, r1]	@ zero_extendqisi2
-	cmp	r9, r2
-	ldrb	r0, [r0, r1]	@ zero_extendqisi2
-	eor	r0, r0, r4
-	strb	r0, [r5, r1]
-	bls	.L1
-	ldr	r0, [r7, #12]
-	adds	r1, r3, #4
-	ldrb	r4, [r6, r2]	@ zero_extendqisi2
-	cmp	r9, r1
-	ldrb	r0, [r0, r2]	@ zero_extendqisi2
-	eor	r0, r0, r4
-	strb	r0, [r5, r2]
-	bls	.L1
-	ldr	r0, [r7, #12]
-	adds	r2, r3, #5
-	ldrb	r4, [r6, r1]	@ zero_extendqisi2
-	cmp	r9, r2
-	ldrb	r0, [r0, r1]	@ zero_extendqisi2
-	eor	r0, r0, r4
-	strb	r0, [r5, r1]
-	bls	.L1
-	ldr	r0, [r7, #12]
-	adds	r1, r3, #6
-	ldrb	r4, [r6, r2]	@ zero_extendqisi2
-	cmp	r9, r1
-	ldrb	r0, [r0, r2]	@ zero_extendqisi2
-	eor	r0, r0, r4
-	strb	r0, [r5, r2]
-	bls	.L1
-	ldr	r0, [r7, #12]
-	adds	r2, r3, #7
-	ldrb	r4, [r6, r1]	@ zero_extendqisi2
-	cmp	r9, r2
-	ldrb	r0, [r0, r1]	@ zero_extendqisi2
-	eor	r0, r0, r4
-	strb	r0, [r5, r1]
-	bls	.L1
-	ldr	r0, [r7, #12]
-	add	r1, r3, #8
-	ldrb	r4, [r6, r2]	@ zero_extendqisi2
-	cmp	r9, r1
-	ldrb	r0, [r0, r2]	@ zero_extendqisi2
-	eor	r0, r0, r4
-	strb	r0, [r5, r2]
-	bls	.L1
-	ldr	r0, [r7, #12]
-	add	r2, r3, #9
-	ldrb	r4, [r6, r1]	@ zero_extendqisi2
-	cmp	r9, r2
-	ldrb	r0, [r0, r1]	@ zero_extendqisi2
-	eor	r0, r0, r4
-	strb	r0, [r5, r1]
-	bls	.L1
-	ldr	r0, [r7, #12]
-	add	r1, r3, #10
-	ldrb	r4, [r6, r2]	@ zero_extendqisi2
-	cmp	r9, r1
-	ldrb	r0, [r0, r2]	@ zero_extendqisi2
-	eor	r0, r0, r4
-	strb	r0, [r5, r2]
-	bls	.L1
-	ldr	r0, [r7, #12]
-	add	r2, r3, #11
-	ldrb	r4, [r6, r1]	@ zero_extendqisi2
-	cmp	r9, r2
-	ldrb	r0, [r0, r1]	@ zero_extendqisi2
-	eor	r0, r0, r4
-	strb	r0, [r5, r1]
-	bls	.L1
-	ldr	r0, [r7, #12]
-	add	r1, r3, #12
-	ldrb	r4, [r6, r2]	@ zero_extendqisi2
-	cmp	r9, r1
-	ldrb	r0, [r0, r2]	@ zero_extendqisi2
-	eor	r0, r0, r4
-	strb	r0, [r5, r2]
-	bls	.L1
-	ldr	r0, [r7, #12]
-	add	r2, r3, #13
-	ldrb	r4, [r6, r1]	@ zero_extendqisi2
-	cmp	r9, r2
-	ldrb	r0, [r0, r1]	@ zero_extendqisi2
-	eor	r0, r0, r4
-	strb	r0, [r5, r1]
-	bls	.L1
-	ldr	r1, [r7, #12]
-	adds	r3, r3, #14
-	ldrb	r0, [r6, r2]	@ zero_extendqisi2
-	cmp	r9, r3
-	ldrb	r1, [r1, r2]	@ zero_extendqisi2
-	eor	r1, r1, r0
-	strb	r1, [r5, r2]
-	bls	.L1
-	ldr	r2, [r7, #88]
-	ldrb	r1, [r2, r3]	@ zero_extendqisi2
-	ldr	r2, [r7, #12]
-	ldrb	r2, [r2, r3]	@ zero_extendqisi2
-	eors	r2, r2, r1
-	ldr	r1, [r7, #16]
-	strb	r2, [r1, r3]
-.L1:
-	adds	r7, r7, #164
-	mov	sp, r7
-	@ sp needed
-	vldm	sp!, {d8-d15}
-	pop	{r4, r5, r6, r7, r8, r9, r10, fp, pc}
-.L88:
-	ldr	r5, [r7, #12]
-	vadd.i32	q12, q12, q10
-	ldr	r4, [r7, #84]
-	cmp	r9, #31
-	ldr	r0, [r5]	@ unaligned
-	ldr	r1, [r5, #4]	@ unaligned
-	mov	r6, r4
-	ldr	r2, [r5, #8]	@ unaligned
-	ldr	r3, [r5, #12]	@ unaligned
-	stmia	r6!, {r0, r1, r2, r3}
-	ldr	r2, [r7, #88]
-	ldr	r6, [r7, #16]
-	vldr	d18, [r2, #80]
-	vldr	d19, [r2, #88]
-	veor	q9, q9, q12
-	vstr	d18, [r2, #80]
-	vstr	d19, [r2, #88]
-	ldmia	r4!, {r0, r1, r2, r3}
-	str	r1, [r6, #4]	@ unaligned
-	mov	r1, r6
-	str	r0, [r6]	@ unaligned
-	str	r2, [r6, #8]	@ unaligned
-	str	r3, [r6, #12]	@ unaligned
-	bhi	.L89
-	vadd.i32	q13, q13, q15
-	ldr	r3, [r7, #88]
-	vstr	d26, [r3, #16]
-	vstr	d27, [r3, #24]
-	b	.L14
-.L16:
-	subs	r3, r2, #1
-	ldr	r2, [r7, #12]
-	add	r2, r2, r9
-	mov	r5, r2
-	ldr	r2, [r7, #88]
-	add	r2, r2, r3
-	mov	r3, r2
-.L24:
-	ldrb	r1, [r0], #1	@ zero_extendqisi2
-	ldrb	r2, [r3, #1]!	@ zero_extendqisi2
-	cmp	r0, r5
-	eor	r2, r2, r1
-	strb	r2, [r4], #1
-	bne	.L24
-	adds	r7, r7, #164
-	mov	sp, r7
-	@ sp needed
-	vldm	sp!, {d8-d15}
-	pop	{r4, r5, r6, r7, r8, r9, r10, fp, pc}
-.L26:
-	ldr	r3, [r7, #80]
-	str	r3, [r7, #16]
-	b	.L2
-.L89:
-	mov	r3, r5
-	ldr	r4, [r7, #84]
-	ldr	r0, [r3, #16]!	@ unaligned
-	add	lr, r1, #16
-	mov	r5, r1
-	vadd.i32	q13, q13, q15
-	mov	r6, r4
-	cmp	r9, #47
-	ldr	r1, [r3, #4]	@ unaligned
-	ldr	r2, [r3, #8]	@ unaligned
-	ldr	r3, [r3, #12]	@ unaligned
-	stmia	r6!, {r0, r1, r2, r3}
-	ldr	r2, [r7, #88]
-	vldr	d18, [r2, #80]
-	vldr	d19, [r2, #88]
-	veor	q13, q9, q13
-	vstr	d26, [r2, #80]
-	vstr	d27, [r2, #88]
-	ldmia	r4!, {r0, r1, r2, r3}
-	str	r0, [r5, #16]	@ unaligned
-	str	r1, [lr, #4]	@ unaligned
-	str	r2, [lr, #8]	@ unaligned
-	str	r3, [lr, #12]	@ unaligned
-	bhi	.L90
-	vadd.i32	q8, q14, q8
-	ldr	r3, [r7, #88]
-	vstr	d16, [r3, #32]
-	vstr	d17, [r3, #40]
-	b	.L14
-.L90:
-	ldr	r3, [r7, #12]
-	add	lr, r5, #32
-	ldr	r4, [r7, #84]
-	vadd.i32	q8, q14, q8
-	ldr	r5, [r7, #88]
-	vadd.i32	q11, q11, q3
-	ldr	r0, [r3, #32]!	@ unaligned
-	mov	r6, r4
-	vstr	d22, [r5, #48]
-	vstr	d23, [r5, #56]
-	ldr	r1, [r3, #4]	@ unaligned
-	ldr	r2, [r3, #8]	@ unaligned
-	ldr	r3, [r3, #12]	@ unaligned
-	stmia	r4!, {r0, r1, r2, r3}
-	vldr	d18, [r5, #80]
-	vldr	d19, [r5, #88]
-	veor	q9, q9, q8
-	ldr	r4, [r7, #16]
-	vstr	d18, [r5, #80]
-	vstr	d19, [r5, #88]
-	ldmia	r6!, {r0, r1, r2, r3}
-	str	r0, [r4, #32]	@ unaligned
-	str	r1, [lr, #4]	@ unaligned
-	str	r2, [lr, #8]	@ unaligned
-	str	r3, [lr, #12]	@ unaligned
-	b	.L14
-	.size	CRYPTO_chacha_20_neon, .-CRYPTO_chacha_20_neon
-	.section	.rodata
-	.align	2
-.LANCHOR0 = . + 0
-.LC0:
-	.word	1634760805
-	.word	857760878
-	.word	2036477234
-	.word	1797285236
-	.ident	"GCC: (Linaro GCC 2014.11) 4.9.3 20141031 (prerelease)"
-	.section	.note.GNU-stack,"",%progbits
-
-#endif  /* __arm__ */
-#endif  /* !OPENSSL_NO_ASM */
diff --git a/src/crypto/chacha/chacha_vec_arm_generate.go b/src/crypto/chacha/chacha_vec_arm_generate.go
deleted file mode 100644
index 82aa847..0000000
--- a/src/crypto/chacha/chacha_vec_arm_generate.go
+++ /dev/null
@@ -1,153 +0,0 @@
-// Copyright (c) 2014, Google Inc.
-//
-// Permission to use, copy, modify, and/or distribute this software for any
-// purpose with or without fee is hereby granted, provided that the above
-// copyright notice and this permission notice appear in all copies.
-//
-// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
-// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-// This package generates chacha_vec_arm.S from chacha_vec.c. Install the
-// arm-linux-gnueabihf-gcc compiler as described in BUILDING.md. Then:
-// `(cd crypto/chacha && go run chacha_vec_arm_generate.go)`.
-
-package main
-
-import (
-	"bufio"
-	"bytes"
-	"os"
-	"os/exec"
-	"strings"
-)
-
-const defaultCompiler = "/opt/gcc-linaro-4.9-2014.11-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc"
-
-func main() {
-	compiler := defaultCompiler
-	if len(os.Args) > 1 {
-		compiler = os.Args[1]
-	}
-
-	args := []string{
-		"-O3",
-		"-mcpu=cortex-a8",
-		"-mfpu=neon",
-		"-fpic",
-		"-DASM_GEN",
-		"-I", "../../include",
-		"-S", "chacha_vec.c",
-		"-o", "-",
-	}
-
-	output, err := os.OpenFile("chacha_vec_arm.S", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
-	if err != nil {
-		panic(err)
-	}
-	defer output.Close()
-
-	output.WriteString(preamble)
-	output.WriteString(compiler)
-	output.WriteString(" ")
-	output.WriteString(strings.Join(args, " "))
-	output.WriteString("\n\n#if !defined(OPENSSL_NO_ASM)\n")
-	output.WriteString("#if defined(__arm__)\n\n")
-
-	cmd := exec.Command(compiler, args...)
-	cmd.Stderr = os.Stderr
-	asm, err := cmd.StdoutPipe()
-	if err != nil {
-		panic(err)
-	}
-	if err := cmd.Start(); err != nil {
-		panic(err)
-	}
-
-	attr28 := []byte(".eabi_attribute 28,")
-	globalDirective := []byte(".global\t")
-	newLine := []byte("\n")
-	attr28Handled := false
-
-	scanner := bufio.NewScanner(asm)
-	for scanner.Scan() {
-		line := scanner.Bytes()
-
-		if bytes.Contains(line, attr28) {
-			output.WriteString(attr28Block)
-			attr28Handled = true
-			continue
-		}
-
-		output.Write(line)
-		output.Write(newLine)
-
-		if i := bytes.Index(line, globalDirective); i >= 0 {
-			output.Write(line[:i])
-			output.WriteString(".hidden\t")
-			output.Write(line[i+len(globalDirective):])
-			output.Write(newLine)
-		}
-	}
-
-	if err := scanner.Err(); err != nil {
-		panic(err)
-	}
-
-	if !attr28Handled {
-		panic("EABI attribute 28 not seen in processing")
-	}
-
-	if err := cmd.Wait(); err != nil {
-		panic(err)
-	}
-
-	output.WriteString(trailer)
-}
-
-const preamble = `# Copyright (c) 2014, Google Inc.
-#
-# Permission to use, copy, modify, and/or distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
-# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-# This file contains a pre-compiled version of chacha_vec.c for ARM. This is
-# needed to support switching on NEON code at runtime. If the whole of OpenSSL
-# were to be compiled with the needed flags to build chacha_vec.c, then it
-# wouldn't be possible to run on non-NEON systems.
-#
-# This file was generated by chacha_vec_arm_generate.go using the following
-# compiler command:
-#
-#     `
-
-const attr28Block = `
-# EABI attribute 28 sets whether VFP register arguments were used to build this
-# file. If object files are inconsistent on this point, the linker will refuse
-# to link them. Thus we report whatever the compiler expects since we don't use
-# VFP arguments.
-
-#if defined(__ARM_PCS_VFP)
-	.eabi_attribute 28, 1
-#else
-	.eabi_attribute 28, 0
-#endif
-
-`
-
-const trailer = `
-#endif  /* __arm__ */
-#endif  /* !OPENSSL_NO_ASM */
-`
diff --git a/src/crypto/cipher/CMakeLists.txt b/src/crypto/cipher/CMakeLists.txt
index 52b87b6..db46c4b 100644
--- a/src/crypto/cipher/CMakeLists.txt
+++ b/src/crypto/cipher/CMakeLists.txt
@@ -1,5 +1,13 @@
 include_directories(../../include)
 
+if (${ARCH} STREQUAL "x86_64")
+  set(
+    CIPHER_ARCH_SOURCES
+
+    chacha20_poly1305_x86_64.${ASM_EXT}
+  )
+endif()
+
 add_library(
   cipher
 
@@ -19,6 +27,8 @@
   tls_cbc.c
   e_tls.c
   e_ssl3.c
+
+  ${CIPHER_ARCH_SOURCES}
 )
 
 add_executable(
@@ -35,6 +45,8 @@
   $<TARGET_OBJECTS:test_support>
 )
 
+perlasm(chacha20_poly1305_x86_64.${ASM_EXT} asm/chacha20_poly1305_x86_64.pl)
+
 target_link_libraries(cipher_test crypto)
 target_link_libraries(aead_test crypto)
 add_dependencies(all_tests cipher_test aead_test)
diff --git a/src/crypto/cipher/aead.c b/src/crypto/cipher/aead.c
index b1db83d..b5ff48a 100644
--- a/src/crypto/cipher/aead.c
+++ b/src/crypto/cipher/aead.c
@@ -20,6 +20,7 @@
 #include <openssl/err.h>
 
 #include "internal.h"
+#include "../internal.h"
 
 
 size_t EVP_AEAD_key_length(const EVP_AEAD *aead) { return aead->key_len; }
@@ -31,7 +32,7 @@
 size_t EVP_AEAD_max_tag_len(const EVP_AEAD *aead) { return aead->max_tag_len; }
 
 void EVP_AEAD_CTX_zero(EVP_AEAD_CTX *ctx) {
-  memset(ctx, 0, sizeof(EVP_AEAD_CTX));
+  OPENSSL_memset(ctx, 0, sizeof(EVP_AEAD_CTX));
 }
 
 int EVP_AEAD_CTX_init(EVP_AEAD_CTX *ctx, const EVP_AEAD *aead,
@@ -80,21 +81,15 @@
   ctx->aead = NULL;
 }
 
-/* check_alias returns 0 if |out| points within the buffer determined by |in|
- * and |in_len| and 1 otherwise.
- *
- * When processing, there's only an issue if |out| points within in[:in_len]
- * and isn't equal to |in|. If that's the case then writing the output will
- * stomp input that hasn't been read yet.
- *
- * This function checks for that case. */
-static int check_alias(const uint8_t *in, size_t in_len, const uint8_t *out) {
-  if (out <= in) {
-    return 1;
-  } else if (in + in_len <= out) {
+/* check_alias returns 1 if |out| is compatible with |in| and 0 otherwise. If
+ * |in| and |out| alias, we require that |in| == |out|. */
+static int check_alias(const uint8_t *in, size_t in_len, const uint8_t *out,
+                       size_t out_len) {
+  if (!buffers_alias(in, in_len, out, out_len)) {
     return 1;
   }
-  return 0;
+
+  return in == out;
 }
 
 int EVP_AEAD_CTX_seal(const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len,
@@ -108,7 +103,7 @@
     goto error;
   }
 
-  if (!check_alias(in, in_len, out)) {
+  if (!check_alias(in, in_len, out, max_out_len)) {
     OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_OUTPUT_ALIASES_INPUT);
     goto error;
   }
@@ -121,7 +116,7 @@
 error:
   /* In the event of an error, clear the output buffer so that a caller
    * that doesn't check the return value doesn't send raw data. */
-  memset(out, 0, max_out_len);
+  OPENSSL_memset(out, 0, max_out_len);
   *out_len = 0;
   return 0;
 }
@@ -130,7 +125,7 @@
                       size_t max_out_len, const uint8_t *nonce,
                       size_t nonce_len, const uint8_t *in, size_t in_len,
                       const uint8_t *ad, size_t ad_len) {
-  if (!check_alias(in, in_len, out)) {
+  if (!check_alias(in, in_len, out, max_out_len)) {
     OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_OUTPUT_ALIASES_INPUT);
     goto error;
   }
@@ -144,18 +139,12 @@
   /* In the event of an error, clear the output buffer so that a caller
    * that doesn't check the return value doesn't try and process bad
    * data. */
-  memset(out, 0, max_out_len);
+  OPENSSL_memset(out, 0, max_out_len);
   *out_len = 0;
   return 0;
 }
 
-int EVP_AEAD_CTX_get_rc4_state(const EVP_AEAD_CTX *ctx, const RC4_KEY **out_key) {
-  if (ctx->aead->get_rc4_state == NULL) {
-    return 0;
-  }
-
-  return ctx->aead->get_rc4_state(ctx, out_key);
-}
+const EVP_AEAD *EVP_AEAD_CTX_aead(const EVP_AEAD_CTX *ctx) { return ctx->aead; }
 
 int EVP_AEAD_CTX_get_iv(const EVP_AEAD_CTX *ctx, const uint8_t **out_iv,
                         size_t *out_len) {
diff --git a/src/crypto/cipher/aead_test.cc b/src/crypto/cipher/aead_test.cc
index 79d7110..fb5200e 100644
--- a/src/crypto/cipher/aead_test.cc
+++ b/src/crypto/cipher/aead_test.cc
@@ -12,6 +12,7 @@
  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
 
+#include <assert.h>
 #include <stdint.h>
 #include <string.h>
 
@@ -21,10 +22,19 @@
 #include <openssl/crypto.h>
 #include <openssl/err.h>
 
+#include "../internal.h"
 #include "../test/file_test.h"
-#include "../test/scoped_types.h"
 
 
+#if defined(OPENSSL_SMALL)
+const EVP_AEAD* EVP_aead_aes_128_gcm_siv(void) {
+  return nullptr;
+}
+const EVP_AEAD* EVP_aead_aes_256_gcm_siv(void) {
+  return nullptr;
+}
+#endif
+
 // This program tests an AEAD against a series of test vectors from a file,
 // using the FileTest format. As an example, here's a valid test case:
 //
@@ -48,7 +58,7 @@
     return false;
   }
 
-  ScopedEVP_AEAD_CTX ctx;
+  bssl::ScopedEVP_AEAD_CTX ctx;
   if (!EVP_AEAD_CTX_init_with_direction(ctx.get(), aead, key.data(), key.size(),
                                         tag.size(), evp_aead_seal)) {
     t->PrintLine("Failed to init AEAD.");
@@ -78,8 +88,8 @@
     }
   } else {
     out.resize(ct.size() + tag.size());
-    memcpy(out.data(), ct.data(), ct.size());
-    memcpy(out.data() + ct.size(), tag.data(), tag.size());
+    OPENSSL_memcpy(out.data(), ct.data(), ct.size());
+    OPENSSL_memcpy(out.data() + ct.size(), tag.data(), tag.size());
   }
 
   // The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
@@ -159,16 +169,12 @@
 }
 
 static int TestCleanupAfterInitFailure(const EVP_AEAD *aead) {
-  EVP_AEAD_CTX ctx;
-  uint8_t key[128];
-
-  memset(key, 0, sizeof(key));
+  uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
+  OPENSSL_memset(key, 0, sizeof(key));
   const size_t key_len = EVP_AEAD_key_length(aead);
-  if (key_len > sizeof(key)) {
-    fprintf(stderr, "Key length of AEAD too long.\n");
-    return 0;
-  }
+  assert(sizeof(key) >= key_len);
 
+  EVP_AEAD_CTX ctx;
   if (EVP_AEAD_CTX_init(&ctx, aead, key, key_len,
                         9999 /* a silly tag length to trigger an error */,
                         NULL /* ENGINE */) != 0) {
@@ -192,37 +198,211 @@
   return 1;
 }
 
-struct AEADName {
+static int TestTruncatedTags(const EVP_AEAD *aead) {
+  uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
+  OPENSSL_memset(key, 0, sizeof(key));
+  const size_t key_len = EVP_AEAD_key_length(aead);
+  assert(sizeof(key) >= key_len);
+
+  uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
+  OPENSSL_memset(nonce, 0, sizeof(nonce));
+  const size_t nonce_len = EVP_AEAD_nonce_length(aead);
+  assert(sizeof(nonce) >= nonce_len);
+
+  bssl::ScopedEVP_AEAD_CTX ctx;
+  if (!EVP_AEAD_CTX_init(ctx.get(), aead, key, key_len, 1 /* one byte tag */,
+                         NULL /* ENGINE */)) {
+    fprintf(stderr, "Couldn't initialise AEAD with truncated tag.\n");
+    return 1;
+  }
+
+  const uint8_t plaintext[1] = {'A'};
+
+  uint8_t ciphertext[128];
+  size_t ciphertext_len;
+  constexpr uint8_t kSentinel = 42;
+  OPENSSL_memset(ciphertext, kSentinel, sizeof(ciphertext));
+
+  if (!EVP_AEAD_CTX_seal(ctx.get(), ciphertext, &ciphertext_len,
+                         sizeof(ciphertext), nonce, nonce_len, plaintext,
+                         sizeof(plaintext), nullptr /* ad */, 0)) {
+    fprintf(stderr, "Sealing with truncated tag didn't work.\n");
+    return 0;
+  }
+
+  for (size_t i = ciphertext_len; i < sizeof(ciphertext); i++) {
+    // Sealing must not write past where it said it did.
+    if (ciphertext[i] != kSentinel) {
+      fprintf(stderr, "Sealing wrote off the end of the buffer.\n");
+      return 0;
+    }
+  }
+
+  const size_t overhead_used = ciphertext_len - sizeof(plaintext);
+  if (overhead_used != 1) {
+    fprintf(stderr, "AEAD is probably ignoring request to truncate tags.\n");
+    return 0;
+  }
+
+  uint8_t plaintext2[sizeof(plaintext) + 16];
+  OPENSSL_memset(plaintext2, kSentinel, sizeof(plaintext2));
+
+  size_t plaintext2_len;
+  if (!EVP_AEAD_CTX_open(ctx.get(), plaintext2, &plaintext2_len,
+                         sizeof(plaintext2), nonce, nonce_len, ciphertext,
+                         ciphertext_len, nullptr /* ad */, 0)) {
+    fprintf(stderr, "Opening with truncated tag didn't work.\n");
+    return 0;
+  }
+
+  for (size_t i = plaintext2_len; i < sizeof(plaintext2); i++) {
+    // Likewise, opening should also stay within bounds.
+    if (plaintext2[i] != kSentinel) {
+      fprintf(stderr, "Opening wrote off the end of the buffer.\n");
+      return 0;
+    }
+  }
+
+  if (plaintext2_len != sizeof(plaintext) ||
+      OPENSSL_memcmp(plaintext2, plaintext, sizeof(plaintext)) != 0) {
+    fprintf(stderr, "Opening with truncated tag gave wrong result.\n");
+    return 0;
+  }
+
+  return 1;
+}
+
+static bool TestWithAliasedBuffers(const EVP_AEAD *aead) {
+  const size_t key_len = EVP_AEAD_key_length(aead);
+  const size_t nonce_len = EVP_AEAD_nonce_length(aead);
+  const size_t max_overhead = EVP_AEAD_max_overhead(aead);
+
+  std::vector<uint8_t> key(key_len, 'a');
+  bssl::ScopedEVP_AEAD_CTX ctx;
+  if (!EVP_AEAD_CTX_init(ctx.get(), aead, key.data(), key_len,
+                         EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr)) {
+    return false;
+  }
+
+  static const uint8_t kPlaintext[260] =
+      "testing123456testing123456testing123456testing123456testing123456testing"
+      "123456testing123456testing123456testing123456testing123456testing123456t"
+      "esting123456testing123456testing123456testing123456testing123456testing1"
+      "23456testing123456testing123456testing12345";
+  const std::vector<size_t> offsets = {
+      0,  1,  2,  8,  15, 16,  17,  31,  32,  33,  63,
+      64, 65, 95, 96, 97, 127, 128, 129, 255, 256, 257,
+  };
+
+  std::vector<uint8_t> nonce(nonce_len, 'b');
+  std::vector<uint8_t> valid_encryption(sizeof(kPlaintext) + max_overhead);
+  size_t valid_encryption_len;
+  if (!EVP_AEAD_CTX_seal(
+          ctx.get(), valid_encryption.data(), &valid_encryption_len,
+          sizeof(kPlaintext) + max_overhead, nonce.data(), nonce_len,
+          kPlaintext, sizeof(kPlaintext), nullptr, 0)) {
+    fprintf(stderr, "EVP_AEAD_CTX_seal failed with disjoint buffers.\n");
+    return false;
+  }
+
+  // Test with out != in which we expect to fail.
+  std::vector<uint8_t> buffer(2 + valid_encryption_len);
+  uint8_t *in = buffer.data() + 1;
+  uint8_t *out1 = buffer.data();
+  uint8_t *out2 = buffer.data() + 2;
+
+  OPENSSL_memcpy(in, kPlaintext, sizeof(kPlaintext));
+  size_t out_len;
+  if (EVP_AEAD_CTX_seal(ctx.get(), out1, &out_len,
+                        sizeof(kPlaintext) + max_overhead, nonce.data(),
+                        nonce_len, in, sizeof(kPlaintext), nullptr, 0) ||
+      EVP_AEAD_CTX_seal(ctx.get(), out2, &out_len,
+                        sizeof(kPlaintext) + max_overhead, nonce.data(),
+                        nonce_len, in, sizeof(kPlaintext), nullptr, 0)) {
+    fprintf(stderr, "EVP_AEAD_CTX_seal unexpectedly succeeded.\n");
+    return false;
+  }
+  ERR_clear_error();
+
+  OPENSSL_memcpy(in, valid_encryption.data(), valid_encryption_len);
+  if (EVP_AEAD_CTX_open(ctx.get(), out1, &out_len, valid_encryption_len,
+                        nonce.data(), nonce_len, in, valid_encryption_len,
+                        nullptr, 0) ||
+      EVP_AEAD_CTX_open(ctx.get(), out2, &out_len, valid_encryption_len,
+                        nonce.data(), nonce_len, in, valid_encryption_len,
+                        nullptr, 0)) {
+    fprintf(stderr, "EVP_AEAD_CTX_open unexpectedly succeeded.\n");
+    return false;
+  }
+  ERR_clear_error();
+
+  // Test with out == in, which we expect to work.
+  OPENSSL_memcpy(in, kPlaintext, sizeof(kPlaintext));
+
+  if (!EVP_AEAD_CTX_seal(ctx.get(), in, &out_len,
+                         sizeof(kPlaintext) + max_overhead, nonce.data(),
+                         nonce_len, in, sizeof(kPlaintext), nullptr, 0)) {
+    fprintf(stderr, "EVP_AEAD_CTX_seal failed in-place.\n");
+    return false;
+  }
+
+  if (out_len != valid_encryption_len ||
+      OPENSSL_memcmp(in, valid_encryption.data(), out_len) != 0) {
+    fprintf(stderr, "EVP_AEAD_CTX_seal produced bad output in-place.\n");
+    return false;
+  }
+
+  OPENSSL_memcpy(in, valid_encryption.data(), valid_encryption_len);
+  if (!EVP_AEAD_CTX_open(ctx.get(), in, &out_len, valid_encryption_len,
+                         nonce.data(), nonce_len, in, valid_encryption_len,
+                         nullptr, 0)) {
+    fprintf(stderr, "EVP_AEAD_CTX_open failed in-place.\n");
+    return false;
+  }
+
+  if (out_len != sizeof(kPlaintext) ||
+      OPENSSL_memcmp(in, kPlaintext, out_len) != 0) {
+    fprintf(stderr, "EVP_AEAD_CTX_open produced bad output in-place.\n");
+    return false;
+  }
+
+  return true;
+}
+
+struct KnownAEAD {
   const char name[40];
   const EVP_AEAD *(*func)(void);
+  // limited_implementation indicates that tests that assume a generic AEAD
+  // interface should not be performed. For example, the key-wrap AEADs only
+  // handle inputs that are a multiple of eight bytes in length and the
+  // SSLv3/TLS AEADs have the concept of “direction”.
+  bool limited_implementation;
+  // truncated_tags is true if the AEAD supports truncating tags to arbitrary
+  // lengths.
+  bool truncated_tags;
 };
 
-static const struct AEADName kAEADs[] = {
-  { "aes-128-gcm", EVP_aead_aes_128_gcm },
-  { "aes-256-gcm", EVP_aead_aes_256_gcm },
-  { "chacha20-poly1305", EVP_aead_chacha20_poly1305 },
-  { "chacha20-poly1305-old", EVP_aead_chacha20_poly1305_old },
-  { "rc4-md5-tls", EVP_aead_rc4_md5_tls },
-  { "rc4-sha1-tls", EVP_aead_rc4_sha1_tls },
-  { "aes-128-cbc-sha1-tls", EVP_aead_aes_128_cbc_sha1_tls },
-  { "aes-128-cbc-sha1-tls-implicit-iv", EVP_aead_aes_128_cbc_sha1_tls_implicit_iv },
-  { "aes-128-cbc-sha256-tls", EVP_aead_aes_128_cbc_sha256_tls },
-  { "aes-256-cbc-sha1-tls", EVP_aead_aes_256_cbc_sha1_tls },
-  { "aes-256-cbc-sha1-tls-implicit-iv", EVP_aead_aes_256_cbc_sha1_tls_implicit_iv },
-  { "aes-256-cbc-sha256-tls", EVP_aead_aes_256_cbc_sha256_tls },
-  { "aes-256-cbc-sha384-tls", EVP_aead_aes_256_cbc_sha384_tls },
-  { "des-ede3-cbc-sha1-tls", EVP_aead_des_ede3_cbc_sha1_tls },
-  { "des-ede3-cbc-sha1-tls-implicit-iv", EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv },
-  { "rc4-md5-ssl3", EVP_aead_rc4_md5_ssl3 },
-  { "rc4-sha1-ssl3", EVP_aead_rc4_sha1_ssl3 },
-  { "aes-128-cbc-sha1-ssl3", EVP_aead_aes_128_cbc_sha1_ssl3 },
-  { "aes-256-cbc-sha1-ssl3", EVP_aead_aes_256_cbc_sha1_ssl3 },
-  { "des-ede3-cbc-sha1-ssl3", EVP_aead_des_ede3_cbc_sha1_ssl3 },
-  { "aes-128-key-wrap", EVP_aead_aes_128_key_wrap },
-  { "aes-256-key-wrap", EVP_aead_aes_256_key_wrap },
-  { "aes-128-ctr-hmac-sha256", EVP_aead_aes_128_ctr_hmac_sha256 },
-  { "aes-256-ctr-hmac-sha256", EVP_aead_aes_256_ctr_hmac_sha256 },
-  { "", NULL },
+static const struct KnownAEAD kAEADs[] = {
+  { "aes-128-gcm", EVP_aead_aes_128_gcm, false, true },
+  { "aes-256-gcm", EVP_aead_aes_256_gcm, false, true },
+  { "aes-128-gcm-siv", EVP_aead_aes_128_gcm_siv, false, false },
+  { "aes-256-gcm-siv", EVP_aead_aes_256_gcm_siv, false, false },
+  { "chacha20-poly1305", EVP_aead_chacha20_poly1305, false, true },
+  { "aes-128-cbc-sha1-tls", EVP_aead_aes_128_cbc_sha1_tls, true, false },
+  { "aes-128-cbc-sha1-tls-implicit-iv", EVP_aead_aes_128_cbc_sha1_tls_implicit_iv, true, false },
+  { "aes-128-cbc-sha256-tls", EVP_aead_aes_128_cbc_sha256_tls, true, false },
+  { "aes-256-cbc-sha1-tls", EVP_aead_aes_256_cbc_sha1_tls, true, false },
+  { "aes-256-cbc-sha1-tls-implicit-iv", EVP_aead_aes_256_cbc_sha1_tls_implicit_iv, true, false },
+  { "aes-256-cbc-sha256-tls", EVP_aead_aes_256_cbc_sha256_tls, true, false },
+  { "aes-256-cbc-sha384-tls", EVP_aead_aes_256_cbc_sha384_tls, true, false },
+  { "des-ede3-cbc-sha1-tls", EVP_aead_des_ede3_cbc_sha1_tls, true, false },
+  { "des-ede3-cbc-sha1-tls-implicit-iv", EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv, true, false },
+  { "aes-128-cbc-sha1-ssl3", EVP_aead_aes_128_cbc_sha1_ssl3, true, false },
+  { "aes-256-cbc-sha1-ssl3", EVP_aead_aes_256_cbc_sha1_ssl3, true, false },
+  { "des-ede3-cbc-sha1-ssl3", EVP_aead_des_ede3_cbc_sha1_ssl3, true, false },
+  { "aes-128-ctr-hmac-sha256", EVP_aead_aes_128_ctr_hmac_sha256, false, true },
+  { "aes-256-ctr-hmac-sha256", EVP_aead_aes_256_ctr_hmac_sha256, false, true },
+  { "", NULL, false, false },
 };
 
 int main(int argc, char **argv) {
@@ -233,22 +413,38 @@
     return 1;
   }
 
-  const EVP_AEAD *aead;
+  const struct KnownAEAD *known_aead;
   for (unsigned i = 0;; i++) {
-    const struct AEADName &aead_name = kAEADs[i];
-    if (aead_name.func == NULL) {
+    known_aead = &kAEADs[i];
+    if (known_aead->func == NULL) {
       fprintf(stderr, "Unknown AEAD: %s\n", argv[1]);
       return 2;
     }
-    if (strcmp(aead_name.name, argv[1]) == 0) {
-      aead = aead_name.func();
+    if (strcmp(known_aead->name, argv[1]) == 0) {
       break;
     }
   }
 
+  const EVP_AEAD *const aead = known_aead->func();
+  if (aead == NULL) {
+    // AEAD is not compiled in this configuration.
+    printf("PASS\n");
+    return 0;
+  }
+
   if (!TestCleanupAfterInitFailure(aead)) {
     return 1;
   }
 
+  if (known_aead->truncated_tags && !TestTruncatedTags(aead)) {
+    fprintf(stderr, "Truncated tags test failed for %s.\n", known_aead->name);
+    return 1;
+  }
+
+  if (!known_aead->limited_implementation && !TestWithAliasedBuffers(aead)) {
+    fprintf(stderr, "Aliased buffers test failed for %s.\n", known_aead->name);
+    return 1;
+  }
+
   return FileTestMain(TestAEAD, const_cast<EVP_AEAD*>(aead), argv[2]);
 }
diff --git a/src/crypto/cipher/asm/chacha20_poly1305_x86_64.pl b/src/crypto/cipher/asm/chacha20_poly1305_x86_64.pl
new file mode 100644
index 0000000..857f1d5
--- /dev/null
+++ b/src/crypto/cipher/asm/chacha20_poly1305_x86_64.pl
@@ -0,0 +1,2380 @@
+#!/usr/bin/env perl
+
+# Copyright (c) 2015, CloudFlare Ltd.
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+##############################################################################
+#                                                                            #
+# Author:  Vlad Krasnov                                                      #
+#                                                                            #
+##############################################################################
+
+$flavour = shift;
+$output  = shift;
+if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
+
+$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
+die "can't locate x86_64-xlate.pl";
+
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
+*STDOUT=*OUT;
+
+$avx = 2;
+
+$code.=<<___;
+.text
+.extern OPENSSL_ia32cap_P
+
+chacha20_poly1305_constants:
+
+.align 64
+.chacha20_consts:
+.byte 'e','x','p','a','n','d',' ','3','2','-','b','y','t','e',' ','k'
+.byte 'e','x','p','a','n','d',' ','3','2','-','b','y','t','e',' ','k'
+.rol8:
+.byte 3,0,1,2, 7,4,5,6, 11,8,9,10, 15,12,13,14
+.byte 3,0,1,2, 7,4,5,6, 11,8,9,10, 15,12,13,14
+.rol16:
+.byte 2,3,0,1, 6,7,4,5, 10,11,8,9, 14,15,12,13
+.byte 2,3,0,1, 6,7,4,5, 10,11,8,9, 14,15,12,13
+.avx2_init:
+.long 0,0,0,0
+.sse_inc:
+.long 1,0,0,0
+.avx2_inc:
+.long 2,0,0,0,2,0,0,0
+.clamp:
+.quad 0x0FFFFFFC0FFFFFFF, 0x0FFFFFFC0FFFFFFC
+.quad 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF
+.align 16
+.and_masks:
+.byte 0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+.byte 0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+.byte 0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+.byte 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+.byte 0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+.byte 0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+.byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+.byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+.byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+.byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00
+.byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00
+.byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00
+.byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00
+.byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00
+.byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00
+___
+
+my ($oup,$inp,$inl,$adp,$keyp,$itr1,$itr2)=("%rdi","%rsi","%rbx","%rcx","%r9","%rcx","%r8");
+my ($acc0,$acc1,$acc2)=map("%r$_",(10..12));
+my ($t0,$t1,$t2,$t3)=("%r13","%r14","%r15","%r9");
+my ($A0,$A1,$A2,$A3,$B0,$B1,$B2,$B3,$C0,$C1,$C2,$C3,$D0,$D1,$D2,$D3)=map("%xmm$_",(0..15));
+my ($T0,$T1,$T2,$T3)=($A3,$B3,$C3,$D3);
+my $r_store="0*16(%rbp)";
+my $s_store="1*16(%rbp)";
+my $len_store="2*16(%rbp)";
+my $state1_store="3*16(%rbp)";
+my $state2_store="4*16(%rbp)";
+my $tmp_store="5*16(%rbp)";
+my $ctr0_store="6*16(%rbp)";
+my $ctr1_store="7*16(%rbp)";
+my $ctr2_store="8*16(%rbp)";
+my $ctr3_store="9*16(%rbp)";
+
+sub chacha_qr {
+my ($a,$b,$c,$d,$t,$dir)=@_;
+$code.="movdqa $t, $tmp_store\n" if ($dir =~ /store/);
+$code.="paddd $b, $a
+        pxor $a, $d
+        pshufb .rol16(%rip), $d
+        paddd $d, $c
+        pxor $c, $b
+        movdqa $b, $t
+        pslld \$12, $t
+        psrld \$20, $b
+        pxor $t, $b
+        paddd $b, $a
+        pxor $a, $d
+        pshufb .rol8(%rip), $d
+        paddd $d, $c
+        pxor $c, $b
+        movdqa $b, $t
+        pslld \$7, $t
+        psrld \$25, $b
+        pxor $t, $b\n";
+$code.="palignr \$4, $b, $b
+        palignr \$8, $c, $c
+        palignr \$12, $d, $d\n" if ($dir =~ /left/);
+$code.="palignr \$12, $b, $b
+        palignr \$8, $c, $c
+        palignr \$4, $d, $d\n" if ($dir =~ /right/);
+$code.="movdqa $tmp_store, $t\n" if ($dir =~ /load/);
+}
+
+sub poly_add {
+my ($src)=@_;
+$code.="add $src, $acc0
+        adc 8+$src, $acc1
+        adc \$1, $acc2\n";
+}
+
+sub poly_stage1 {
+$code.="mov 0+$r_store, %rax
+        mov %rax, $t2
+        mul $acc0
+        mov %rax, $t0
+        mov %rdx, $t1
+        mov 0+$r_store, %rax
+        mul $acc1
+        imulq $acc2, $t2
+        add %rax, $t1
+        adc %rdx, $t2\n";
+}
+
+sub poly_stage2 {
+$code.="mov 8+$r_store, %rax
+        mov %rax, $t3
+        mul $acc0
+        add %rax, $t1
+        adc \$0, %rdx
+        mov %rdx, $acc0
+        mov 8+$r_store, %rax
+        mul $acc1
+        add %rax, $t2
+        adc \$0, %rdx\n";
+}
+
+sub poly_stage3 {
+$code.="imulq $acc2, $t3
+        add $acc0, $t2
+        adc %rdx, $t3\n";
+}
+
+sub poly_reduce_stage {
+$code.="mov $t0, $acc0
+        mov $t1, $acc1
+        mov $t2, $acc2
+        and \$3, $acc2
+        mov $t2, $t0
+        and \$-4, $t0
+        mov $t3, $t1
+        shrd \$2, $t3, $t2
+        shr \$2, $t3
+        add $t0, $acc0
+        adc $t1, $acc1
+        adc \$0, $acc2
+        add $t2, $acc0
+        adc $t3, $acc1
+        adc \$0, $acc2\n";
+}
+
+sub poly_mul {
+    &poly_stage1();
+    &poly_stage2();
+    &poly_stage3();
+    &poly_reduce_stage();
+}
+
+sub prep_state {
+my ($n)=@_;
+$code.="movdqa .chacha20_consts(%rip), $A0
+        movdqa $state1_store, $B0
+        movdqa $state2_store, $C0\n";
+$code.="movdqa $A0, $A1
+        movdqa $B0, $B1
+        movdqa $C0, $C1\n" if ($n ge 2);
+$code.="movdqa $A0, $A2
+        movdqa $B0, $B2
+        movdqa $C0, $C2\n" if ($n ge 3);
+$code.="movdqa $A0, $A3
+        movdqa $B0, $B3
+        movdqa $C0, $C3\n" if ($n ge 4);
+$code.="movdqa $ctr0_store, $D0
+        paddd .sse_inc(%rip), $D0
+        movdqa $D0, $ctr0_store\n" if ($n eq 1);
+$code.="movdqa $ctr0_store, $D1
+        paddd .sse_inc(%rip), $D1
+        movdqa $D1, $D0
+        paddd .sse_inc(%rip), $D0
+        movdqa $D0, $ctr0_store
+        movdqa $D1, $ctr1_store\n" if ($n eq 2);
+$code.="movdqa $ctr0_store, $D2
+        paddd .sse_inc(%rip), $D2
+        movdqa $D2, $D1
+        paddd .sse_inc(%rip), $D1
+        movdqa $D1, $D0
+        paddd .sse_inc(%rip), $D0
+        movdqa $D0, $ctr0_store
+        movdqa $D1, $ctr1_store
+        movdqa $D2, $ctr2_store\n" if ($n eq 3);
+$code.="movdqa $ctr0_store, $D3
+        paddd .sse_inc(%rip), $D3
+        movdqa $D3, $D2
+        paddd .sse_inc(%rip), $D2
+        movdqa $D2, $D1
+        paddd .sse_inc(%rip), $D1
+        movdqa $D1, $D0
+        paddd .sse_inc(%rip), $D0
+        movdqa $D0, $ctr0_store
+        movdqa $D1, $ctr1_store
+        movdqa $D2, $ctr2_store
+        movdqa $D3, $ctr3_store\n" if ($n eq 4);
+}
+
+sub finalize_state {
+my ($n)=@_;
+$code.="paddd .chacha20_consts(%rip), $A3
+        paddd $state1_store, $B3
+        paddd $state2_store, $C3
+        paddd $ctr3_store, $D3\n" if ($n eq 4);
+$code.="paddd .chacha20_consts(%rip), $A2
+        paddd $state1_store, $B2
+        paddd $state2_store, $C2
+        paddd $ctr2_store, $D2\n" if ($n ge 3);
+$code.="paddd .chacha20_consts(%rip), $A1
+        paddd $state1_store, $B1
+        paddd $state2_store, $C1
+        paddd $ctr1_store, $D1\n" if ($n ge 2);
+$code.="paddd .chacha20_consts(%rip), $A0
+        paddd $state1_store, $B0
+        paddd $state2_store, $C0
+        paddd $ctr0_store, $D0\n";
+}
+
+sub xor_stream {
+my ($A, $B, $C, $D, $offset)=@_;
+$code.="movdqu 0*16 + $offset($inp), $A3
+        movdqu 1*16 + $offset($inp), $B3
+        movdqu 2*16 + $offset($inp), $C3
+        movdqu 3*16 + $offset($inp), $D3
+        pxor $A3, $A
+        pxor $B3, $B
+        pxor $C3, $C
+        pxor $D, $D3
+        movdqu $A, 0*16 + $offset($oup)
+        movdqu $B, 1*16 + $offset($oup)
+        movdqu $C, 2*16 + $offset($oup)
+        movdqu $D3, 3*16 + $offset($oup)\n";
+}
+
+sub xor_stream_using_temp {
+my ($A, $B, $C, $D, $offset, $temp)=@_;
+$code.="movdqa $temp, $tmp_store
+        movdqu 0*16 + $offset($inp), $temp
+        pxor $A, $temp
+        movdqu $temp, 0*16 + $offset($oup)
+        movdqu 1*16 + $offset($inp), $temp
+        pxor $B, $temp
+        movdqu $temp, 1*16 + $offset($oup)
+        movdqu 2*16 + $offset($inp), $temp
+        pxor $C, $temp
+        movdqu $temp, 2*16 + $offset($oup)
+        movdqu 3*16 + $offset($inp), $temp
+        pxor $D, $temp
+        movdqu $temp, 3*16 + $offset($oup)\n";
+}
+
+sub gen_chacha_round {
+my ($rot1, $rot2, $shift)=@_;
+my $round="";
+$round.="movdqa $C0, $tmp_store\n" if ($rot1 eq 20);
+$round.="movdqa $rot2, $C0
+         paddd $B3, $A3
+         paddd $B2, $A2
+         paddd $B1, $A1
+         paddd $B0, $A0
+         pxor $A3, $D3
+         pxor $A2, $D2
+         pxor $A1, $D1
+         pxor $A0, $D0
+         pshufb $C0, $D3
+         pshufb $C0, $D2
+         pshufb $C0, $D1
+         pshufb $C0, $D0
+         movdqa $tmp_store, $C0
+         paddd $D3, $C3
+         paddd $D2, $C2
+         paddd $D1, $C1
+         paddd $D0, $C0
+         pxor $C3, $B3
+         pxor $C2, $B2
+         pxor $C1, $B1
+         pxor $C0, $B0
+         movdqa $C0, $tmp_store
+         movdqa $B3, $C0
+         psrld \$$rot1, $C0
+         pslld \$32-$rot1, $B3
+         pxor $C0, $B3
+         movdqa $B2, $C0
+         psrld \$$rot1, $C0
+         pslld \$32-$rot1, $B2
+         pxor $C0, $B2
+         movdqa $B1, $C0
+         psrld \$$rot1, $C0
+         pslld \$32-$rot1, $B1
+         pxor $C0, $B1
+         movdqa $B0, $C0
+         psrld \$$rot1, $C0
+         pslld \$32-$rot1, $B0
+         pxor $C0, $B0\n";
+($s1,$s2,$s3)=(4,8,12) if ($shift =~ /left/);
+($s1,$s2,$s3)=(12,8,4) if ($shift =~ /right/);
+$round.="movdqa $tmp_store, $C0
+         palignr \$$s1, $B3, $B3
+         palignr \$$s2, $C3, $C3
+         palignr \$$s3, $D3, $D3
+         palignr \$$s1, $B2, $B2
+         palignr \$$s2, $C2, $C2
+         palignr \$$s3, $D2, $D2
+         palignr \$$s1, $B1, $B1
+         palignr \$$s2, $C1, $C1
+         palignr \$$s3, $D1, $D1
+         palignr \$$s1, $B0, $B0
+         palignr \$$s2, $C0, $C0
+         palignr \$$s3, $D0, $D0\n"
+if (($shift =~ /left/) || ($shift =~ /right/));
+return $round;
+};
+
+$chacha_body = &gen_chacha_round(20, ".rol16(%rip)") .
+               &gen_chacha_round(25, ".rol8(%rip)", "left") .
+               &gen_chacha_round(20, ".rol16(%rip)") .
+               &gen_chacha_round(25, ".rol8(%rip)", "right");
+
+my @loop_body = split /\n/, $chacha_body;
+
+sub emit_body {
+my ($n)=@_;
+    for (my $i=0; $i < $n; $i++) {
+        $code=$code.shift(@loop_body)."\n";
+    };
+}
+
+{
+################################################################################
+# void poly_hash_ad_internal();
+$code.="
+.type poly_hash_ad_internal,\@function,2
+.align 64
+poly_hash_ad_internal:
+.cfi_startproc
+    xor $acc0, $acc0
+    xor $acc1, $acc1
+    xor $acc2, $acc2
+    cmp \$13,  $itr2
+    jne hash_ad_loop
+poly_fast_tls_ad:
+    # Special treatment for the TLS case of 13 bytes
+    mov ($adp), $acc0
+    mov 5($adp), $acc1
+    shr \$24, $acc1
+    mov \$1, $acc2\n";
+    &poly_mul(); $code.="
+    ret
+hash_ad_loop:
+        # Hash in 16 byte chunk
+        cmp \$16, $itr2
+        jb hash_ad_tail\n";
+        &poly_add("0($adp)");
+        &poly_mul(); $code.="
+        lea 1*16($adp), $adp
+        sub \$16, $itr2
+    jmp hash_ad_loop
+hash_ad_tail:
+    cmp \$0, $itr2
+    je 1f
+    # Hash last < 16 byte tail
+    xor $t0, $t0
+    xor $t1, $t1
+    xor $t2, $t2
+    add $itr2, $adp
+hash_ad_tail_loop:
+        shld \$8, $t0, $t1
+        shl \$8, $t0
+        movzxb -1($adp), $t2
+        xor $t2, $t0
+        dec $adp
+        dec $itr2
+    jne hash_ad_tail_loop
+
+    add $t0, $acc0
+    adc $t1, $acc1
+    adc \$1, $acc2\n";
+    &poly_mul(); $code.="
+    # Finished AD
+1:
+    ret
+.cfi_endproc
+.size poly_hash_ad_internal, .-poly_hash_ad_internal\n";
+}
+
+{
+################################################################################
+# void chacha20_poly1305_open(uint8_t *pt, uint8_t *ct, size_t len_in, uint8_t *ad, size_t len_ad, uint8_t *keyp);
+$code.="
+.globl chacha20_poly1305_open
+.type chacha20_poly1305_open,\@function,2
+.align 64
+chacha20_poly1305_open:
+.cfi_startproc
+    push %rbp
+.cfi_adjust_cfa_offset 8
+    push %rbx
+.cfi_adjust_cfa_offset 8
+    push %r12
+.cfi_adjust_cfa_offset 8
+    push %r13
+.cfi_adjust_cfa_offset 8
+    push %r14
+.cfi_adjust_cfa_offset 8
+    push %r15
+.cfi_adjust_cfa_offset 8
+    # We write the calculated authenticator back to keyp at the end, so save
+    # the pointer on the stack too.
+    push $keyp
+.cfi_adjust_cfa_offset 8
+    sub \$288 + 32, %rsp
+.cfi_adjust_cfa_offset 288 + 32
+.cfi_offset rbp, -16
+.cfi_offset rbx, -24
+.cfi_offset r12, -32
+.cfi_offset r13, -40
+.cfi_offset r14, -48
+.cfi_offset r15, -56
+    lea 32(%rsp), %rbp
+    and \$-32, %rbp
+    mov %rdx, 8+$len_store
+    mov %r8, 0+$len_store
+    mov %rdx, $inl\n"; $code.="
+    mov OPENSSL_ia32cap_P+8(%rip), %eax
+    and \$`(1<<5) + (1<<8)`, %eax # Check both BMI2 and AVX2 are present
+    xor \$`(1<<5) + (1<<8)`, %eax
+    jz  chacha20_poly1305_open_avx2\n" if ($avx>1);
+$code.="
+1:
+    cmp \$128, $inl
+    jbe open_sse_128
+    # For long buffers, prepare the poly key first
+    movdqa .chacha20_consts(%rip), $A0
+    movdqu 0*16($keyp), $B0
+    movdqu 1*16($keyp), $C0
+    movdqu 2*16($keyp), $D0
+    movdqa $D0, $T1
+    # Store on stack, to free keyp
+    movdqa $B0, $state1_store
+    movdqa $C0, $state2_store
+    movdqa $D0, $ctr0_store
+    mov \$10, $acc0
+1:  \n";
+        &chacha_qr($A0,$B0,$C0,$D0,$T0,"left");
+        &chacha_qr($A0,$B0,$C0,$D0,$T0,"right"); $code.="
+        dec $acc0
+    jne 1b
+    # A0|B0 hold the Poly1305 32-byte key, C0,D0 can be discarded
+    paddd .chacha20_consts(%rip), $A0
+    paddd $state1_store, $B0
+    # Clamp and store the key
+    pand .clamp(%rip), $A0
+    movdqa $A0, $r_store
+    movdqa $B0, $s_store
+    # Hash
+    mov %r8, $itr2
+    call poly_hash_ad_internal
+open_sse_main_loop:
+        cmp \$16*16, $inl
+        jb 2f
+        # Load state, increment counter blocks\n";
+        &prep_state(4); $code.="
+        # There are 10 ChaCha20 iterations of 2QR each, so for 6 iterations we
+        # hash 2 blocks, and for the remaining 4 only 1 block - for a total of 16
+        mov \$4, $itr1
+        mov $inp, $itr2
+1:  \n";
+            &emit_body(20);
+            &poly_add("0($itr2)"); $code.="
+            lea 2*8($itr2), $itr2\n";
+            &emit_body(20);
+            &poly_stage1();
+            &emit_body(20);
+            &poly_stage2();
+            &emit_body(20);
+            &poly_stage3();
+            &emit_body(20);
+            &poly_reduce_stage();
+            foreach $l (@loop_body) {$code.=$l."\n";}
+            @loop_body = split /\n/, $chacha_body; $code.="
+            dec $itr1
+        jge 1b\n";
+            &poly_add("0($itr2)");
+            &poly_mul(); $code.="
+            lea 2*8($itr2), $itr2
+            cmp \$-6, $itr1
+        jg 1b\n";
+        &finalize_state(4);
+        &xor_stream_using_temp($A3, $B3, $C3, $D3, "0*16", $D0);
+        &xor_stream($A2, $B2, $C2, $D2, "4*16");
+        &xor_stream($A1, $B1, $C1, $D1, "8*16");
+        &xor_stream($A0, $B0, $C0, $tmp_store, "12*16"); $code.="
+        lea 16*16($inp), $inp
+        lea 16*16($oup), $oup
+        sub \$16*16, $inl
+    jmp open_sse_main_loop
+2:
+    # Handle the various tail sizes efficiently
+    test $inl, $inl
+    jz open_sse_finalize
+    cmp \$4*16, $inl
+    ja 3f\n";
+###############################################################################
+    # At most 64 bytes are left
+    &prep_state(1); $code.="
+    xor $itr2, $itr2
+    mov $inl, $itr1
+    cmp \$16, $itr1
+    jb 2f
+1:  \n";
+        &poly_add("0($inp, $itr2)");
+        &poly_mul(); $code.="
+        sub \$16, $itr1
+2:
+        add \$16, $itr2\n";
+        &chacha_qr($A0,$B0,$C0,$D0,$T0,"left");
+        &chacha_qr($A0,$B0,$C0,$D0,$T0,"right"); $code.="
+        cmp \$16, $itr1
+    jae 1b
+        cmp \$10*16, $itr2
+    jne 2b\n";
+    &finalize_state(1); $code.="
+    jmp open_sse_tail_64_dec_loop
+3:
+    cmp \$8*16, $inl
+    ja 3f\n";
+###############################################################################
+    # 65 - 128 bytes are left
+    &prep_state(2); $code.="
+    mov $inl, $itr1
+    and \$-16, $itr1
+    xor $itr2, $itr2
+1:  \n";
+        &poly_add("0($inp, $itr2)");
+        &poly_mul(); $code.="
+2:
+        add \$16, $itr2\n";
+        &chacha_qr($A0,$B0,$C0,$D0,$T0,"left");
+        &chacha_qr($A1,$B1,$C1,$D1,$T0,"left");
+        &chacha_qr($A0,$B0,$C0,$D0,$T0,"right");
+        &chacha_qr($A1,$B1,$C1,$D1,$T0,"right");$code.="
+        cmp $itr1, $itr2
+    jb 1b
+        cmp \$10*16, $itr2
+    jne 2b\n";
+    &finalize_state(2);
+    &xor_stream($A1, $B1, $C1, $D1, "0*16"); $code.="
+    sub \$4*16, $inl
+    lea 4*16($inp), $inp
+    lea 4*16($oup), $oup
+    jmp open_sse_tail_64_dec_loop
+3:
+    cmp \$12*16, $inl
+    ja 3f\n";
+###############################################################################
+    # 129 - 192 bytes are left
+    &prep_state(3); $code.="
+    mov $inl, $itr1
+    mov \$10*16, $itr2
+    cmp \$10*16, $itr1
+    cmovg $itr2, $itr1
+    and \$-16, $itr1
+    xor $itr2, $itr2
+1:  \n";
+        &poly_add("0($inp, $itr2)");
+        &poly_mul(); $code.="
+2:
+        add \$16, $itr2\n";
+        &chacha_qr($A0,$B0,$C0,$D0,$T0,"left");
+        &chacha_qr($A1,$B1,$C1,$D1,$T0,"left");
+        &chacha_qr($A2,$B2,$C2,$D2,$T0,"left");
+        &chacha_qr($A0,$B0,$C0,$D0,$T0,"right");
+        &chacha_qr($A1,$B1,$C1,$D1,$T0,"right");
+        &chacha_qr($A2,$B2,$C2,$D2,$T0,"right"); $code.="
+        cmp $itr1, $itr2
+    jb 1b
+        cmp \$10*16, $itr2
+    jne 2b
+    cmp \$11*16, $inl
+    jb 1f\n";
+    &poly_add("10*16($inp)");
+    &poly_mul(); $code.="
+    cmp \$12*16, $inl
+    jb 1f\n";
+    &poly_add("11*16($inp)");
+    &poly_mul(); $code.="
+1:  \n";
+    &finalize_state(3);
+    &xor_stream($A2, $B2, $C2, $D2, "0*16");
+    &xor_stream($A1, $B1, $C1, $D1, "4*16"); $code.="
+    sub \$8*16, $inl
+    lea 8*16($inp), $inp
+    lea 8*16($oup), $oup
+    jmp open_sse_tail_64_dec_loop
+3:
+###############################################################################\n";
+    # 193 - 255 bytes are left
+    &prep_state(4); $code.="
+    xor $itr2, $itr2
+1:  \n";
+        &poly_add("0($inp, $itr2)");
+        &chacha_qr($A0,$B0,$C0,$D0,$C3,"store_left");
+        &chacha_qr($A1,$B1,$C1,$D1,$C3,"left");
+        &chacha_qr($A2,$B2,$C2,$D2,$C3,"left_load");
+        &poly_stage1();
+        &chacha_qr($A3,$B3,$C3,$D3,$C1,"store_left_load");
+        &poly_stage2();
+        &chacha_qr($A0,$B0,$C0,$D0,$C3,"store_right");
+        &chacha_qr($A1,$B1,$C1,$D1,$C3,"right");
+        &poly_stage3();
+        &chacha_qr($A2,$B2,$C2,$D2,$C3,"right_load");
+        &poly_reduce_stage();
+        &chacha_qr($A3,$B3,$C3,$D3,$C1,"store_right_load"); $code.="
+        add \$16, $itr2
+        cmp \$10*16, $itr2
+    jb 1b
+    mov $inl, $itr1
+    and \$-16, $itr1
+1:  \n";
+        &poly_add("0($inp, $itr2)");
+        &poly_mul(); $code.="
+        add \$16, $itr2
+        cmp $itr1, $itr2
+    jb 1b\n";
+    &finalize_state(4);
+    &xor_stream_using_temp($A3, $B3, $C3, $D3, "0*16", $D0);
+    &xor_stream($A2, $B2, $C2, $D2, "4*16");
+    &xor_stream($A1, $B1, $C1, $D1, "8*16"); $code.="
+    movdqa $tmp_store, $D0
+    sub \$12*16, $inl
+    lea 12*16($inp), $inp
+    lea 12*16($oup), $oup
+###############################################################################
+    # Decrypt the remaining data, 16B at a time, using existing stream
+open_sse_tail_64_dec_loop:
+    cmp \$16, $inl
+    jb 1f
+        sub \$16, $inl
+        movdqu ($inp), $T0
+        pxor $T0, $A0
+        movdqu $A0, ($oup)
+        lea 16($inp), $inp
+        lea 16($oup), $oup
+        movdqa $B0, $A0
+        movdqa $C0, $B0
+        movdqa $D0, $C0
+    jmp open_sse_tail_64_dec_loop
+1:
+    movdqa $A0, $A1
+
+    # Decrypt up to 16 bytes at the end.
+open_sse_tail_16:
+    test $inl, $inl
+    jz open_sse_finalize
+
+    # Read the final bytes into $T0. They need to be read in reverse order so
+    # that they end up in the correct order in $T0.
+    pxor $T0, $T0
+    lea -1($inp, $inl), $inp
+    movq $inl, $itr2
+2:
+        pslldq \$1, $T0
+        pinsrb \$0, ($inp), $T0
+        sub \$1, $inp
+        sub \$1, $itr2
+        jnz 2b
+
+3:
+    movq $T0, $t0
+    pextrq \$1, $T0, $t1
+    # The final bytes of keystream are in $A1.
+    pxor $A1, $T0
+
+    # Copy the plaintext bytes out.
+2:
+        pextrb \$0, $T0, ($oup)
+        psrldq \$1, $T0
+        add \$1, $oup
+        sub \$1, $inl
+    jne 2b
+
+    add $t0, $acc0
+    adc $t1, $acc1
+    adc \$1, $acc2\n";
+    &poly_mul(); $code.="
+
+open_sse_finalize:\n";
+    &poly_add($len_store);
+    &poly_mul(); $code.="
+    # Final reduce
+    mov $acc0, $t0
+    mov $acc1, $t1
+    mov $acc2, $t2
+    sub \$-5, $acc0
+    sbb \$-1, $acc1
+    sbb \$3, $acc2
+    cmovc $t0, $acc0
+    cmovc $t1, $acc1
+    cmovc $t2, $acc2
+    # Add in s part of the key
+    add 0+$s_store, $acc0
+    adc 8+$s_store, $acc1
+
+    add \$288 + 32, %rsp
+.cfi_adjust_cfa_offset -(288 + 32)
+    pop $keyp
+.cfi_adjust_cfa_offset -8
+    movq $acc0, ($keyp)
+    movq $acc1, 8($keyp)
+
+    pop %r15
+.cfi_adjust_cfa_offset -8
+    pop %r14
+.cfi_adjust_cfa_offset -8
+    pop %r13
+.cfi_adjust_cfa_offset -8
+    pop %r12
+.cfi_adjust_cfa_offset -8
+    pop %rbx
+.cfi_adjust_cfa_offset -8
+    pop %rbp
+.cfi_adjust_cfa_offset -8
+    ret
+.cfi_adjust_cfa_offset (8 * 6) + 288 + 32
+###############################################################################
+open_sse_128:
+    movdqu .chacha20_consts(%rip), $A0\nmovdqa $A0, $A1\nmovdqa $A0, $A2
+    movdqu 0*16($keyp), $B0\nmovdqa $B0, $B1\nmovdqa $B0, $B2
+    movdqu 1*16($keyp), $C0\nmovdqa $C0, $C1\nmovdqa $C0, $C2
+    movdqu 2*16($keyp), $D0
+    movdqa $D0, $D1\npaddd .sse_inc(%rip), $D1
+    movdqa $D1, $D2\npaddd .sse_inc(%rip), $D2
+    movdqa $B0, $T1\nmovdqa $C0, $T2\nmovdqa $D1, $T3
+    mov \$10, $acc0
+1:  \n";
+        &chacha_qr($A0,$B0,$C0,$D0,$T0,"left");
+        &chacha_qr($A1,$B1,$C1,$D1,$T0,"left");
+        &chacha_qr($A2,$B2,$C2,$D2,$T0,"left");
+        &chacha_qr($A0,$B0,$C0,$D0,$T0,"right");
+        &chacha_qr($A1,$B1,$C1,$D1,$T0,"right");
+        &chacha_qr($A2,$B2,$C2,$D2,$T0,"right"); $code.="
+    dec $acc0
+    jnz 1b
+    paddd .chacha20_consts(%rip), $A0
+    paddd .chacha20_consts(%rip), $A1
+    paddd .chacha20_consts(%rip), $A2
+    paddd $T1, $B0\npaddd $T1, $B1\npaddd $T1, $B2
+    paddd $T2, $C1\npaddd $T2, $C2
+    paddd $T3, $D1
+    paddd .sse_inc(%rip), $T3
+    paddd $T3, $D2
+    # Clamp and store the key
+    pand .clamp(%rip), $A0
+    movdqa $A0, $r_store
+    movdqa $B0, $s_store
+    # Hash
+    mov %r8, $itr2
+    call poly_hash_ad_internal
+1:
+        cmp \$16, $inl
+        jb open_sse_tail_16
+        sub \$16, $inl\n";
+        # Load for hashing
+        &poly_add("0*8($inp)"); $code.="
+        # Load for decryption
+        movdqu 0*16($inp), $T0
+        pxor $T0, $A1
+        movdqu $A1, 0*16($oup)
+        lea 1*16($inp), $inp
+        lea 1*16($oup), $oup\n";
+        &poly_mul(); $code.="
+        # Shift the stream left
+        movdqa $B1, $A1
+        movdqa $C1, $B1
+        movdqa $D1, $C1
+        movdqa $A2, $D1
+        movdqa $B2, $A2
+        movdqa $C2, $B2
+        movdqa $D2, $C2
+    jmp 1b
+    jmp open_sse_tail_16
+.size chacha20_poly1305_open, .-chacha20_poly1305_open
+.cfi_endproc
+
+################################################################################
+################################################################################
+# void chacha20_poly1305_seal(uint8_t *pt, uint8_t *ct, size_t len_in, uint8_t *ad, size_t len_ad, uint8_t *keyp);
+.globl  chacha20_poly1305_seal
+.type chacha20_poly1305_seal,\@function,2
+.align 64
+chacha20_poly1305_seal:
+.cfi_startproc
+    push %rbp
+.cfi_adjust_cfa_offset 8
+    push %rbx
+.cfi_adjust_cfa_offset 8
+    push %r12
+.cfi_adjust_cfa_offset 8
+    push %r13
+.cfi_adjust_cfa_offset 8
+    push %r14
+.cfi_adjust_cfa_offset 8
+    push %r15
+.cfi_adjust_cfa_offset 8
+    # We write the calculated authenticator back to keyp at the end, so save
+    # the pointer on the stack too.
+    push $keyp
+.cfi_adjust_cfa_offset 8
+    sub \$288 + 32, %rsp
+.cfi_adjust_cfa_offset 288 + 32
+.cfi_offset rbp, -16
+.cfi_offset rbx, -24
+.cfi_offset r12, -32
+.cfi_offset r13, -40
+.cfi_offset r14, -48
+.cfi_offset r15, -56
+    lea 32(%rsp), %rbp
+    and \$-32, %rbp
+    mov %rdx, 8+$len_store
+    mov %r8, 0+$len_store
+    mov %rdx, $inl\n"; $code.="
+    mov OPENSSL_ia32cap_P+8(%rip), %eax
+    and \$`(1<<5) + (1<<8)`, %eax # Check both BMI2 and AVX2 are present
+    xor \$`(1<<5) + (1<<8)`, %eax
+    jz  chacha20_poly1305_seal_avx2\n" if ($avx>1);
+$code.="
+    cmp \$128, $inl
+    jbe seal_sse_128
+    # For longer buffers, prepare the poly key + some stream
+    movdqa .chacha20_consts(%rip), $A0
+    movdqu 0*16($keyp), $B0
+    movdqu 1*16($keyp), $C0
+    movdqu 2*16($keyp), $D0
+    movdqa $A0, $A1
+    movdqa $A0, $A2
+    movdqa $A0, $A3
+    movdqa $B0, $B1
+    movdqa $B0, $B2
+    movdqa $B0, $B3
+    movdqa $C0, $C1
+    movdqa $C0, $C2
+    movdqa $C0, $C3
+    movdqa $D0, $D3
+    paddd .sse_inc(%rip), $D0
+    movdqa $D0, $D2
+    paddd .sse_inc(%rip), $D0
+    movdqa $D0, $D1
+    paddd .sse_inc(%rip), $D0
+    # Store on stack
+    movdqa $B0, $state1_store
+    movdqa $C0, $state2_store
+    movdqa $D0, $ctr0_store
+    movdqa $D1, $ctr1_store
+    movdqa $D2, $ctr2_store
+    movdqa $D3, $ctr3_store
+    mov \$10, $acc0
+1:  \n";
+        foreach $l (@loop_body) {$code.=$l."\n";}
+        @loop_body = split /\n/, $chacha_body; $code.="
+        dec $acc0
+    jnz 1b\n";
+    &finalize_state(4); $code.="
+    # Clamp and store the key
+    pand .clamp(%rip), $A3
+    movdqa $A3, $r_store
+    movdqa $B3, $s_store
+    # Hash
+    mov %r8, $itr2
+    call poly_hash_ad_internal\n";
+    &xor_stream($A2,$B2,$C2,$D2,"0*16");
+    &xor_stream($A1,$B1,$C1,$D1,"4*16"); $code.="
+    cmp \$12*16, $inl
+    ja 1f
+    mov \$8*16, $itr1
+    sub \$8*16, $inl
+    lea 8*16($inp), $inp
+    jmp seal_sse_128_seal_hash
+1:  \n";
+    &xor_stream($A0, $B0, $C0, $D0, "8*16"); $code.="
+    mov \$12*16, $itr1
+    sub \$12*16, $inl
+    lea 12*16($inp), $inp
+    mov \$2, $itr1
+    mov \$8, $itr2
+    cmp \$4*16, $inl
+    jbe seal_sse_tail_64
+    cmp \$8*16, $inl
+    jbe seal_sse_tail_128
+    cmp \$12*16, $inl
+    jbe seal_sse_tail_192
+
+1:  \n";
+    # The main loop
+        &prep_state(4); $code.="
+2:  \n";
+            &emit_body(20);
+            &poly_add("0($oup)");
+            &emit_body(20);
+            &poly_stage1();
+            &emit_body(20);
+            &poly_stage2();
+            &emit_body(20);
+            &poly_stage3();
+            &emit_body(20);
+            &poly_reduce_stage();
+            foreach $l (@loop_body) {$code.=$l."\n";}
+            @loop_body = split /\n/, $chacha_body; $code.="
+            lea 16($oup), $oup
+            dec $itr2
+        jge 2b\n";
+            &poly_add("0*8($oup)");
+            &poly_mul(); $code.="
+            lea 16($oup), $oup
+            dec $itr1
+        jg 2b\n";
+
+        &finalize_state(4);$code.="
+        movdqa $D2, $tmp_store\n";
+        &xor_stream_using_temp($A3,$B3,$C3,$D3,0*16,$D2); $code.="
+        movdqa $tmp_store, $D2\n";
+        &xor_stream($A2,$B2,$C2,$D2, 4*16);
+        &xor_stream($A1,$B1,$C1,$D1, 8*16); $code.="
+        cmp \$16*16, $inl
+        ja 3f
+
+        mov \$12*16, $itr1
+        sub \$12*16, $inl
+        lea 12*16($inp), $inp
+        jmp seal_sse_128_seal_hash
+3:  \n";
+        &xor_stream($A0,$B0,$C0,$D0,"12*16"); $code.="
+        lea 16*16($inp), $inp
+        sub \$16*16, $inl
+        mov \$6, $itr1
+        mov \$4, $itr2
+        cmp \$12*16, $inl
+    jg 1b
+    mov $inl, $itr1
+    test $inl, $inl
+    je seal_sse_128_seal_hash
+    mov \$6, $itr1
+    cmp \$4*16, $inl
+    jg 3f
+###############################################################################
+seal_sse_tail_64:\n";
+    &prep_state(1); $code.="
+1:  \n";
+        &poly_add("0($oup)");
+        &poly_mul(); $code.="
+        lea 16($oup), $oup
+2:  \n";
+        &chacha_qr($A0,$B0,$C0,$D0,$T0,"left");
+        &chacha_qr($A0,$B0,$C0,$D0,$T0,"right");
+        &poly_add("0($oup)");
+        &poly_mul(); $code.="
+        lea 16($oup), $oup
+    dec $itr1
+    jg 1b
+    dec $itr2
+    jge 2b\n";
+    &finalize_state(1); $code.="
+    jmp seal_sse_128_seal
+3:
+    cmp \$8*16, $inl
+    jg 3f
+###############################################################################
+seal_sse_tail_128:\n";
+    &prep_state(2); $code.="
+1:  \n";
+        &poly_add("0($oup)");
+        &poly_mul(); $code.="
+        lea 16($oup), $oup
+2:  \n";
+        &chacha_qr($A0,$B0,$C0,$D0,$T0,"left");
+        &chacha_qr($A1,$B1,$C1,$D1,$T0,"left");
+        &poly_add("0($oup)");
+        &poly_mul();
+        &chacha_qr($A0,$B0,$C0,$D0,$T0,"right");
+        &chacha_qr($A1,$B1,$C1,$D1,$T0,"right"); $code.="
+        lea 16($oup), $oup
+    dec $itr1
+    jg 1b
+    dec $itr2
+    jge 2b\n";
+    &finalize_state(2);
+    &xor_stream($A1,$B1,$C1,$D1,0*16); $code.="
+    mov \$4*16, $itr1
+    sub \$4*16, $inl
+    lea 4*16($inp), $inp
+    jmp seal_sse_128_seal_hash
+3:
+###############################################################################
+seal_sse_tail_192:\n";
+    &prep_state(3); $code.="
+1:  \n";
+        &poly_add("0($oup)");
+        &poly_mul(); $code.="
+        lea 16($oup), $oup
+2:  \n";
+        &chacha_qr($A0,$B0,$C0,$D0,$T0,"left");
+        &chacha_qr($A1,$B1,$C1,$D1,$T0,"left");
+        &chacha_qr($A2,$B2,$C2,$D2,$T0,"left");
+        &poly_add("0($oup)");
+        &poly_mul();
+        &chacha_qr($A0,$B0,$C0,$D0,$T0,"right");
+        &chacha_qr($A1,$B1,$C1,$D1,$T0,"right");
+        &chacha_qr($A2,$B2,$C2,$D2,$T0,"right"); $code.="
+        lea 16($oup), $oup
+    dec $itr1
+    jg 1b
+    dec $itr2
+    jge 2b\n";
+    &finalize_state(3);
+    &xor_stream($A2,$B2,$C2,$D2,0*16);
+    &xor_stream($A1,$B1,$C1,$D1,4*16); $code.="
+    mov \$8*16, $itr1
+    sub \$8*16, $inl
+    lea 8*16($inp), $inp
+###############################################################################
+seal_sse_128_seal_hash:
+        cmp \$16, $itr1
+        jb seal_sse_128_seal\n";
+        &poly_add("0($oup)");
+        &poly_mul(); $code.="
+        sub \$16, $itr1
+        lea 16($oup), $oup
+    jmp seal_sse_128_seal_hash
+
+seal_sse_128_seal:
+        cmp \$16, $inl
+        jb seal_sse_tail_16
+        sub \$16, $inl
+        # Load for decryption
+        movdqu 0*16($inp), $T0
+        pxor $T0, $A0
+        movdqu $A0, 0*16($oup)
+        # Then hash
+        add 0*8($oup), $acc0
+        adc 1*8($oup), $acc1
+        adc \$1, $acc2
+        lea 1*16($inp), $inp
+        lea 1*16($oup), $oup\n";
+        &poly_mul(); $code.="
+        # Shift the stream left
+        movdqa $B0, $A0
+        movdqa $C0, $B0
+        movdqa $D0, $C0
+        movdqa $A1, $D0
+        movdqa $B1, $A1
+        movdqa $C1, $B1
+        movdqa $D1, $C1
+    jmp seal_sse_128_seal
+
+seal_sse_tail_16:
+    test $inl, $inl
+    jz seal_sse_finalize
+    # We can only load the PT one byte at a time to avoid buffer overread
+    mov $inl, $itr2
+    shl \$4, $itr2
+    lea .and_masks(%rip), $t0
+    mov $inl, $itr1
+    lea -1($inp, $inl), $inp
+    pxor $T3, $T3
+1:
+        pslldq \$1, $T3
+        pinsrb \$0, ($inp), $T3
+        lea -1($inp), $inp
+        dec $itr1
+    jne 1b
+
+    # XOR the keystream with the plaintext.
+    pxor $A0, $T3
+
+    # Write ciphertext out, byte-by-byte.
+    movq $inl, $itr1
+    movdqu $T3, $A0
+2:
+        pextrb \$0, $A0, ($oup)
+        psrldq \$1, $A0
+        add \$1, $oup
+        sub \$1, $itr1
+        jnz 2b
+
+    pand -16($t0, $itr2), $T3
+    movq $T3, $t0
+    pextrq \$1, $T3, $t1
+    add $t0, $acc0
+    adc $t1, $acc1
+    adc \$1, $acc2\n";
+    &poly_mul(); $code.="
+seal_sse_finalize:\n";
+    &poly_add($len_store);
+    &poly_mul(); $code.="
+    # Final reduce
+    mov $acc0, $t0
+    mov $acc1, $t1
+    mov $acc2, $t2
+    sub \$-5, $acc0
+    sbb \$-1, $acc1
+    sbb \$3, $acc2
+    cmovc $t0, $acc0
+    cmovc $t1, $acc1
+    cmovc $t2, $acc2
+    # Add in s part of the key
+    add 0+$s_store, $acc0
+    adc 8+$s_store, $acc1
+
+    add \$288 + 32, %rsp
+.cfi_adjust_cfa_offset -(288 + 32)
+    pop $keyp
+.cfi_adjust_cfa_offset -8
+    mov $acc0, 0*8($keyp)
+    mov $acc1, 1*8($keyp)
+
+    pop %r15
+.cfi_adjust_cfa_offset -8
+    pop %r14
+.cfi_adjust_cfa_offset -8
+    pop %r13
+.cfi_adjust_cfa_offset -8
+    pop %r12
+.cfi_adjust_cfa_offset -8
+    pop %rbx
+.cfi_adjust_cfa_offset -8
+    pop %rbp
+.cfi_adjust_cfa_offset -8
+    ret
+.cfi_adjust_cfa_offset (8 * 6) + 288 + 32
+################################################################################
+seal_sse_128:
+    movdqu .chacha20_consts(%rip), $A0\nmovdqa $A0, $A1\nmovdqa $A0, $A2
+    movdqu 0*16($keyp), $B0\nmovdqa $B0, $B1\nmovdqa $B0, $B2
+    movdqu 1*16($keyp), $C0\nmovdqa $C0, $C1\nmovdqa $C0, $C2
+    movdqu 2*16($keyp), $D2
+    movdqa $D2, $D0\npaddd .sse_inc(%rip), $D0
+    movdqa $D0, $D1\npaddd .sse_inc(%rip), $D1
+    movdqa $B0, $T1\nmovdqa $C0, $T2\nmovdqa $D0, $T3
+    mov \$10, $acc0
+1:\n";
+        &chacha_qr($A0,$B0,$C0,$D0,$T0,"left");
+        &chacha_qr($A1,$B1,$C1,$D1,$T0,"left");
+        &chacha_qr($A2,$B2,$C2,$D2,$T0,"left");
+        &chacha_qr($A0,$B0,$C0,$D0,$T0,"right");
+        &chacha_qr($A1,$B1,$C1,$D1,$T0,"right");
+        &chacha_qr($A2,$B2,$C2,$D2,$T0,"right"); $code.="
+        dec $acc0
+    jnz 1b
+    paddd .chacha20_consts(%rip), $A0
+    paddd .chacha20_consts(%rip), $A1
+    paddd .chacha20_consts(%rip), $A2
+    paddd $T1, $B0\npaddd $T1, $B1\npaddd $T1, $B2
+    paddd $T2, $C0\npaddd $T2, $C1
+    paddd $T3, $D0
+    paddd .sse_inc(%rip), $T3
+    paddd $T3, $D1
+    # Clamp and store the key
+    pand .clamp(%rip), $A2
+    movdqa $A2, $r_store
+    movdqa $B2, $s_store
+    # Hash
+    mov %r8, $itr2
+    call poly_hash_ad_internal
+    jmp seal_sse_128_seal
+.size chacha20_poly1305_seal, .-chacha20_poly1305_seal\n";
+}
+
+# There should have been a cfi_endproc at the end of that function, but the two
+# following blocks of code are jumped to without a stack frame and the CFI
+# context which they are used in happens to match the CFI context at the end of
+# the previous function. So the CFI table is just extended to the end of them.
+
+if ($avx>1) {
+
+($A0,$A1,$A2,$A3,$B0,$B1,$B2,$B3,$C0,$C1,$C2,$C3,$D0,$D1,$D2,$D3)=map("%ymm$_",(0..15));
+my ($A0x,$A1x,$A2x,$A3x,$B0x,$B1x,$B2x,$B3x,$C0x,$C1x,$C2x,$C3x,$D0x,$D1x,$D2x,$D3x)=map("%xmm$_",(0..15));
+($T0,$T1,$T2,$T3)=($A3,$B3,$C3,$D3);
+$state1_store="2*32(%rbp)";
+$state2_store="3*32(%rbp)";
+$tmp_store="4*32(%rbp)";
+$ctr0_store="5*32(%rbp)";
+$ctr1_store="6*32(%rbp)";
+$ctr2_store="7*32(%rbp)";
+$ctr3_store="8*32(%rbp)";
+
+sub chacha_qr_avx2 {
+my ($a,$b,$c,$d,$t,$dir)=@_;
+$code.=<<___ if ($dir =~ /store/);
+    vmovdqa $t, $tmp_store
+___
+$code.=<<___;
+    vpaddd $b, $a, $a
+    vpxor $a, $d, $d
+    vpshufb .rol16(%rip), $d, $d
+    vpaddd $d, $c, $c
+    vpxor $c, $b, $b
+    vpsrld \$20, $b, $t
+    vpslld \$12, $b, $b
+    vpxor $t, $b, $b
+    vpaddd $b, $a, $a
+    vpxor $a, $d, $d
+    vpshufb .rol8(%rip), $d, $d
+    vpaddd $d, $c, $c
+    vpxor $c, $b, $b
+    vpslld \$7, $b, $t
+    vpsrld \$25, $b, $b
+    vpxor $t, $b, $b
+___
+$code.=<<___ if ($dir =~ /left/);
+    vpalignr \$12, $d, $d, $d
+    vpalignr \$8, $c, $c, $c
+    vpalignr \$4, $b, $b, $b
+___
+$code.=<<___ if ($dir =~ /right/);
+    vpalignr \$4, $d, $d, $d
+    vpalignr \$8, $c, $c, $c
+    vpalignr \$12, $b, $b, $b
+___
+$code.=<<___ if ($dir =~ /load/);
+    vmovdqa $tmp_store, $t
+___
+}
+
+sub prep_state_avx2 {
+my ($n)=@_;
+$code.=<<___;
+    vmovdqa .chacha20_consts(%rip), $A0
+    vmovdqa $state1_store, $B0
+    vmovdqa $state2_store, $C0
+___
+$code.=<<___ if ($n ge 2);
+    vmovdqa $A0, $A1
+    vmovdqa $B0, $B1
+    vmovdqa $C0, $C1
+___
+$code.=<<___ if ($n ge 3);
+    vmovdqa $A0, $A2
+    vmovdqa $B0, $B2
+    vmovdqa $C0, $C2
+___
+$code.=<<___ if ($n ge 4);
+    vmovdqa $A0, $A3
+    vmovdqa $B0, $B3
+    vmovdqa $C0, $C3
+___
+$code.=<<___ if ($n eq 1);
+    vmovdqa .avx2_inc(%rip), $D0
+    vpaddd $ctr0_store, $D0, $D0
+    vmovdqa $D0, $ctr0_store
+___
+$code.=<<___ if ($n eq 2);
+    vmovdqa .avx2_inc(%rip), $D0
+    vpaddd $ctr0_store, $D0, $D1
+    vpaddd $D1, $D0, $D0
+    vmovdqa $D0, $ctr0_store
+    vmovdqa $D1, $ctr1_store
+___
+$code.=<<___ if ($n eq 3);
+    vmovdqa .avx2_inc(%rip), $D0
+    vpaddd $ctr0_store, $D0, $D2
+    vpaddd $D2, $D0, $D1
+    vpaddd $D1, $D0, $D0
+    vmovdqa $D0, $ctr0_store
+    vmovdqa $D1, $ctr1_store
+    vmovdqa $D2, $ctr2_store
+___
+$code.=<<___ if ($n eq 4);
+    vmovdqa .avx2_inc(%rip), $D0
+    vpaddd $ctr0_store, $D0, $D3
+    vpaddd $D3, $D0, $D2
+    vpaddd $D2, $D0, $D1
+    vpaddd $D1, $D0, $D0
+    vmovdqa $D3, $ctr3_store
+    vmovdqa $D2, $ctr2_store
+    vmovdqa $D1, $ctr1_store
+    vmovdqa $D0, $ctr0_store
+___
+}
+
+sub finalize_state_avx2 {
+my ($n)=@_;
+$code.=<<___ if ($n eq 4);
+    vpaddd .chacha20_consts(%rip), $A3, $A3
+    vpaddd $state1_store, $B3, $B3
+    vpaddd $state2_store, $C3, $C3
+    vpaddd $ctr3_store, $D3, $D3
+___
+$code.=<<___ if ($n ge 3);
+    vpaddd .chacha20_consts(%rip), $A2, $A2
+    vpaddd $state1_store, $B2, $B2
+    vpaddd $state2_store, $C2, $C2
+    vpaddd $ctr2_store, $D2, $D2
+___
+$code.=<<___ if ($n ge 2);
+    vpaddd .chacha20_consts(%rip), $A1, $A1
+    vpaddd $state1_store, $B1, $B1
+    vpaddd $state2_store, $C1, $C1
+    vpaddd $ctr1_store, $D1, $D1
+___
+$code.=<<___;
+    vpaddd .chacha20_consts(%rip), $A0, $A0
+    vpaddd $state1_store, $B0, $B0
+    vpaddd $state2_store, $C0, $C0
+    vpaddd $ctr0_store, $D0, $D0
+___
+}
+
+sub xor_stream_avx2 {
+my ($A, $B, $C, $D, $offset, $hlp)=@_;
+$code.=<<___;
+    vperm2i128 \$0x02, $A, $B, $hlp
+    vperm2i128 \$0x13, $A, $B, $B
+    vperm2i128 \$0x02, $C, $D, $A
+    vperm2i128 \$0x13, $C, $D, $C
+    vpxor 0*32+$offset($inp), $hlp, $hlp
+    vpxor 1*32+$offset($inp), $A, $A
+    vpxor 2*32+$offset($inp), $B, $B
+    vpxor 3*32+$offset($inp), $C, $C
+    vmovdqu $hlp, 0*32+$offset($oup)
+    vmovdqu $A, 1*32+$offset($oup)
+    vmovdqu $B, 2*32+$offset($oup)
+    vmovdqu $C, 3*32+$offset($oup)
+___
+}
+
+sub finish_stream_avx2 {
+my ($A, $B, $C, $D, $hlp)=@_;
+$code.=<<___;
+    vperm2i128 \$0x13, $A, $B, $hlp
+    vperm2i128 \$0x02, $A, $B, $A
+    vperm2i128 \$0x02, $C, $D, $B
+    vperm2i128 \$0x13, $C, $D, $D
+    vmovdqa $hlp, $C
+___
+}
+
+sub poly_stage1_mulx {
+$code.=<<___;
+    mov 0+$r_store, %rdx
+    mov %rdx, $t2
+    mulx $acc0, $t0, $t1
+    mulx $acc1, %rax, %rdx
+    imulq $acc2, $t2
+    add %rax, $t1
+    adc %rdx, $t2
+___
+}
+
+sub poly_stage2_mulx {
+$code.=<<___;
+    mov 8+$r_store, %rdx
+    mulx $acc0, $acc0, %rax
+    add $acc0, $t1
+    mulx $acc1, $acc1, $t3
+    adc $acc1, $t2
+    adc \$0, $t3
+    imulq $acc2, %rdx
+___
+}
+
+sub poly_stage3_mulx {
+$code.=<<___;
+    add %rax, $t2
+    adc %rdx, $t3
+___
+}
+
+sub poly_mul_mulx {
+    &poly_stage1_mulx();
+    &poly_stage2_mulx();
+    &poly_stage3_mulx();
+    &poly_reduce_stage();
+}
+
+sub gen_chacha_round_avx2 {
+my ($rot1, $rot2, $shift)=@_;
+my $round="";
+$round=$round ."vmovdqa $C0, $tmp_store\n" if ($rot1 eq 20);
+$round=$round ."vmovdqa $rot2, $C0
+                vpaddd $B3, $A3, $A3
+                vpaddd $B2, $A2, $A2
+                vpaddd $B1, $A1, $A1
+                vpaddd $B0, $A0, $A0
+                vpxor $A3, $D3, $D3
+                vpxor $A2, $D2, $D2
+                vpxor $A1, $D1, $D1
+                vpxor $A0, $D0, $D0
+                vpshufb $C0, $D3, $D3
+                vpshufb $C0, $D2, $D2
+                vpshufb $C0, $D1, $D1
+                vpshufb $C0, $D0, $D0
+                vmovdqa $tmp_store, $C0
+                vpaddd $D3, $C3, $C3
+                vpaddd $D2, $C2, $C2
+                vpaddd $D1, $C1, $C1
+                vpaddd $D0, $C0, $C0
+                vpxor $C3, $B3, $B3
+                vpxor $C2, $B2, $B2
+                vpxor $C1, $B1, $B1
+                vpxor $C0, $B0, $B0
+                vmovdqa $C0, $tmp_store
+                vpsrld \$$rot1, $B3, $C0
+                vpslld \$32-$rot1, $B3, $B3
+                vpxor $C0, $B3, $B3
+                vpsrld \$$rot1, $B2, $C0
+                vpslld \$32-$rot1, $B2, $B2
+                vpxor $C0, $B2, $B2
+                vpsrld \$$rot1, $B1, $C0
+                vpslld \$32-$rot1, $B1, $B1
+                vpxor $C0, $B1, $B1
+                vpsrld \$$rot1, $B0, $C0
+                vpslld \$32-$rot1, $B0, $B0
+                vpxor $C0, $B0, $B0\n";
+($s1,$s2,$s3)=(4,8,12) if ($shift =~ /left/);
+($s1,$s2,$s3)=(12,8,4) if ($shift =~ /right/);
+$round=$round ."vmovdqa $tmp_store, $C0
+                vpalignr \$$s1, $B3, $B3, $B3
+                vpalignr \$$s2, $C3, $C3, $C3
+                vpalignr \$$s3, $D3, $D3, $D3
+                vpalignr \$$s1, $B2, $B2, $B2
+                vpalignr \$$s2, $C2, $C2, $C2
+                vpalignr \$$s3, $D2, $D2, $D2
+                vpalignr \$$s1, $B1, $B1, $B1
+                vpalignr \$$s2, $C1, $C1, $C1
+                vpalignr \$$s3, $D1, $D1, $D1
+                vpalignr \$$s1, $B0, $B0, $B0
+                vpalignr \$$s2, $C0, $C0, $C0
+                vpalignr \$$s3, $D0, $D0, $D0\n"
+if (($shift =~ /left/) || ($shift =~ /right/));
+return $round;
+};
+
+$chacha_body = &gen_chacha_round_avx2(20, ".rol16(%rip)") .
+               &gen_chacha_round_avx2(25, ".rol8(%rip)", "left") .
+               &gen_chacha_round_avx2(20, ".rol16(%rip)") .
+               &gen_chacha_round_avx2(25, ".rol8(%rip)", "right");
+
+@loop_body = split /\n/, $chacha_body;
+
+$code.="
+###############################################################################
+.type chacha20_poly1305_open_avx2,\@function,2
+.align 64
+chacha20_poly1305_open_avx2:
+    vzeroupper
+    vmovdqa .chacha20_consts(%rip), $A0
+    vbroadcasti128 0*16($keyp), $B0
+    vbroadcasti128 1*16($keyp), $C0
+    vbroadcasti128 2*16($keyp), $D0
+    vpaddd .avx2_init(%rip), $D0, $D0
+    cmp \$6*32, $inl
+    jbe open_avx2_192
+    cmp \$10*32, $inl
+    jbe open_avx2_320
+
+    vmovdqa $B0, $state1_store
+    vmovdqa $C0, $state2_store
+    vmovdqa $D0, $ctr0_store
+    mov \$10, $acc0
+1:  \n";
+        &chacha_qr_avx2($A0,$B0,$C0,$D0,$T0,"left");
+        &chacha_qr_avx2($A0,$B0,$C0,$D0,$T0,"right"); $code.="
+        dec $acc0
+    jne 1b
+    vpaddd .chacha20_consts(%rip), $A0, $A0
+    vpaddd $state1_store, $B0, $B0
+    vpaddd $state2_store, $C0, $C0
+    vpaddd $ctr0_store, $D0, $D0
+
+    vperm2i128 \$0x02, $A0, $B0, $T0
+    # Clamp and store key
+    vpand .clamp(%rip), $T0, $T0
+    vmovdqa $T0, $r_store
+    # Stream for the first 64 bytes
+    vperm2i128 \$0x13, $A0, $B0, $A0
+    vperm2i128 \$0x13, $C0, $D0, $B0
+    # Hash AD + first 64 bytes
+    mov %r8, $itr2
+    call poly_hash_ad_internal
+    xor $itr1, $itr1
+    # Hash first 64 bytes
+1:  \n";
+       &poly_add("0($inp, $itr1)");
+       &poly_mul(); $code.="
+       add \$16, $itr1
+       cmp \$2*32, $itr1
+    jne 1b
+    # Decrypt first 64 bytes
+    vpxor 0*32($inp), $A0, $A0
+    vpxor 1*32($inp), $B0, $B0
+    vmovdqu $A0, 0*32($oup)
+    vmovdqu $B0, 1*32($oup)
+    lea 2*32($inp), $inp
+    lea 2*32($oup), $oup
+    sub \$2*32, $inl
+1:
+        # Hash and decrypt 512 bytes each iteration
+        cmp \$16*32, $inl
+        jb 3f\n";
+        &prep_state_avx2(4); $code.="
+        xor $itr1, $itr1
+2:  \n";
+            &poly_add("0*8($inp, $itr1)");
+            &emit_body(10);
+            &poly_stage1_mulx();
+            &emit_body(9);
+            &poly_stage2_mulx();
+            &emit_body(12);
+            &poly_stage3_mulx();
+            &emit_body(10);
+            &poly_reduce_stage();
+            &emit_body(9);
+            &poly_add("2*8($inp, $itr1)");
+            &emit_body(8);
+            &poly_stage1_mulx();
+            &emit_body(18);
+            &poly_stage2_mulx();
+            &emit_body(18);
+            &poly_stage3_mulx();
+            &emit_body(9);
+            &poly_reduce_stage();
+            &emit_body(8);
+            &poly_add("4*8($inp, $itr1)"); $code.="
+            lea 6*8($itr1), $itr1\n";
+            &emit_body(18);
+            &poly_stage1_mulx();
+            &emit_body(8);
+            &poly_stage2_mulx();
+            &emit_body(8);
+            &poly_stage3_mulx();
+            &emit_body(18);
+            &poly_reduce_stage();
+            foreach $l (@loop_body) {$code.=$l."\n";}
+            @loop_body = split /\n/, $chacha_body; $code.="
+            cmp \$10*6*8, $itr1
+        jne 2b\n";
+        &finalize_state_avx2(4); $code.="
+        vmovdqa $A0, $tmp_store\n";
+        &poly_add("10*6*8($inp)");
+        &xor_stream_avx2($A3, $B3, $C3, $D3, 0*32, $A0); $code.="
+        vmovdqa $tmp_store, $A0\n";
+        &poly_mul();
+        &xor_stream_avx2($A2, $B2, $C2, $D2, 4*32, $A3);
+        &poly_add("10*6*8+2*8($inp)");
+        &xor_stream_avx2($A1, $B1, $C1, $D1, 8*32, $A3);
+        &poly_mul();
+        &xor_stream_avx2($A0, $B0, $C0, $D0, 12*32, $A3); $code.="
+        lea 16*32($inp), $inp
+        lea 16*32($oup), $oup
+        sub \$16*32, $inl
+    jmp 1b
+3:
+    test $inl, $inl
+    vzeroupper
+    je open_sse_finalize
+3:
+    cmp \$4*32, $inl
+    ja 3f\n";
+###############################################################################
+    # 1-128 bytes left
+    &prep_state_avx2(1); $code.="
+    xor $itr2, $itr2
+    mov $inl, $itr1
+    and \$-16, $itr1
+    test $itr1, $itr1
+    je 2f
+1:  \n";
+        &poly_add("0*8($inp, $itr2)");
+        &poly_mul(); $code.="
+2:
+        add \$16, $itr2\n";
+        &chacha_qr_avx2($A0,$B0,$C0,$D0,$T0,"left");
+        &chacha_qr_avx2($A0,$B0,$C0,$D0,$T0,"right"); $code.="
+        cmp $itr1, $itr2
+    jb 1b
+        cmp \$160, $itr2
+    jne 2b\n";
+    &finalize_state_avx2(1);
+    &finish_stream_avx2($A0,$B0,$C0,$D0,$T0); $code.="
+    jmp open_avx2_tail_loop
+3:
+    cmp \$8*32, $inl
+    ja 3f\n";
+###############################################################################
+    # 129-256 bytes left
+    &prep_state_avx2(2); $code.="
+    mov $inl, $tmp_store
+    mov $inl, $itr1
+    sub \$4*32, $itr1
+    shr \$4, $itr1
+    mov \$10, $itr2
+    cmp \$10, $itr1
+    cmovg $itr2, $itr1
+    mov $inp, $inl
+    xor $itr2, $itr2
+1:  \n";
+        &poly_add("0*8($inl)");
+        &poly_mul_mulx(); $code.="
+        lea 16($inl), $inl
+2:  \n";
+        &chacha_qr_avx2($A0,$B0,$C0,$D0,$T0,"left");
+        &chacha_qr_avx2($A1,$B1,$C1,$D1,$T0,"left"); $code.="
+        inc $itr2\n";
+        &chacha_qr_avx2($A0,$B0,$C0,$D0,$T0,"right");
+        &chacha_qr_avx2($A1,$B1,$C1,$D1,$T0,"right");
+        &chacha_qr_avx2($A2,$B2,$C2,$D2,$T0,"right"); $code.="
+        cmp $itr1, $itr2
+    jb 1b
+        cmp \$10, $itr2
+    jne 2b
+    mov $inl, $itr2
+    sub $inp, $inl
+    mov $inl, $itr1
+    mov $tmp_store, $inl
+1:
+        add \$16, $itr1
+        cmp $inl, $itr1
+        jg 1f\n";
+        &poly_add("0*8($itr2)");
+        &poly_mul_mulx(); $code.="
+        lea 16($itr2), $itr2
+    jmp 1b
+1:  \n";
+    &finalize_state_avx2(2);
+    &xor_stream_avx2($A1, $B1, $C1, $D1, 0*32, $T0);
+    &finish_stream_avx2($A0, $B0, $C0, $D0, $T0); $code.="
+    lea 4*32($inp), $inp
+    lea 4*32($oup), $oup
+    sub \$4*32, $inl
+    jmp open_avx2_tail_loop
+3:
+    cmp \$12*32, $inl
+    ja 3f\n";
+###############################################################################
+    # 257-383 bytes left
+    &prep_state_avx2(3); $code.="
+    mov $inl, $tmp_store
+    mov $inl, $itr1
+    sub \$8*32, $itr1
+    shr \$4, $itr1
+    add \$6, $itr1
+    mov \$10, $itr2
+    cmp \$10, $itr1
+    cmovg $itr2, $itr1
+    mov $inp, $inl
+    xor $itr2, $itr2
+1:  \n";
+        &poly_add("0*8($inl)");
+        &poly_mul_mulx(); $code.="
+        lea 16($inl), $inl
+2:  \n";
+        &chacha_qr_avx2($A2,$B2,$C2,$D2,$T0,"left");
+        &chacha_qr_avx2($A1,$B1,$C1,$D1,$T0,"left");
+        &chacha_qr_avx2($A0,$B0,$C0,$D0,$T0,"left");
+        &poly_add("0*8($inl)");
+        &poly_mul(); $code.="
+        lea 16($inl), $inl
+        inc $itr2\n";
+        &chacha_qr_avx2($A2,$B2,$C2,$D2,$T0,"right");
+        &chacha_qr_avx2($A1,$B1,$C1,$D1,$T0,"right");
+        &chacha_qr_avx2($A0,$B0,$C0,$D0,$T0,"right"); $code.="
+        cmp $itr1, $itr2
+    jb 1b
+        cmp \$10, $itr2
+    jne 2b
+    mov $inl, $itr2
+    sub $inp, $inl
+    mov $inl, $itr1
+    mov $tmp_store, $inl
+1:
+        add \$16, $itr1
+        cmp $inl, $itr1
+        jg 1f\n";
+        &poly_add("0*8($itr2)");
+        &poly_mul_mulx(); $code.="
+        lea 16($itr2), $itr2
+    jmp 1b
+1:  \n";
+    &finalize_state_avx2(3);
+    &xor_stream_avx2($A2, $B2, $C2, $D2, 0*32, $T0);
+    &xor_stream_avx2($A1, $B1, $C1, $D1, 4*32, $T0);
+    &finish_stream_avx2($A0, $B0, $C0, $D0, $T0); $code.="
+    lea 8*32($inp), $inp
+    lea 8*32($oup), $oup
+    sub \$8*32, $inl
+    jmp open_avx2_tail_loop
+3:  \n";
+###############################################################################
+    # 384-512 bytes left
+    &prep_state_avx2(4); $code.="
+    xor $itr1, $itr1
+    mov $inp, $itr2
+1:  \n";
+        &poly_add("0*8($itr2)");
+        &poly_mul(); $code.="
+        lea 2*8($itr2), $itr2
+2:  \n";
+        &emit_body(37);
+        &poly_add("0*8($itr2)");
+        &poly_mul_mulx();
+        &emit_body(48);
+        &poly_add("2*8($itr2)");
+        &poly_mul_mulx(); $code.="
+        lea 4*8($itr2), $itr2\n";
+        foreach $l (@loop_body) {$code.=$l."\n";}
+        @loop_body = split /\n/, $chacha_body; $code.="
+        inc $itr1
+        cmp \$4, $itr1
+    jl  1b
+        cmp \$10, $itr1
+    jne 2b
+    mov $inl, $itr1
+    sub \$12*32, $itr1
+    and \$-16, $itr1
+1:
+        test $itr1, $itr1
+        je 1f\n";
+        &poly_add("0*8($itr2)");
+        &poly_mul_mulx(); $code.="
+        lea 2*8($itr2), $itr2
+        sub \$2*8, $itr1
+    jmp 1b
+1:  \n";
+    &finalize_state_avx2(4); $code.="
+    vmovdqa $A0, $tmp_store\n";
+    &xor_stream_avx2($A3, $B3, $C3, $D3, 0*32, $A0); $code.="
+    vmovdqa $tmp_store, $A0\n";
+    &xor_stream_avx2($A2, $B2, $C2, $D2, 4*32, $A3);
+    &xor_stream_avx2($A1, $B1, $C1, $D1, 8*32, $A3);
+    &finish_stream_avx2($A0, $B0, $C0, $D0, $A3); $code.="
+    lea 12*32($inp), $inp
+    lea 12*32($oup), $oup
+    sub \$12*32, $inl
+open_avx2_tail_loop:
+    cmp \$32, $inl
+    jb open_avx2_tail
+        sub \$32, $inl
+        vpxor ($inp), $A0, $A0
+        vmovdqu $A0, ($oup)
+        lea 1*32($inp), $inp
+        lea 1*32($oup), $oup
+        vmovdqa $B0, $A0
+        vmovdqa $C0, $B0
+        vmovdqa $D0, $C0
+    jmp open_avx2_tail_loop
+open_avx2_tail:
+    cmp \$16, $inl
+    vmovdqa $A0x, $A1x
+    jb 1f
+    sub \$16, $inl
+    #load for decryption
+    vpxor ($inp), $A0x, $A1x
+    vmovdqu $A1x, ($oup)
+    lea 1*16($inp), $inp
+    lea 1*16($oup), $oup
+    vperm2i128 \$0x11, $A0, $A0, $A0
+    vmovdqa $A0x, $A1x
+1:
+    vzeroupper
+    jmp open_sse_tail_16
+###############################################################################
+open_avx2_192:
+    vmovdqa $A0, $A1
+    vmovdqa $A0, $A2
+    vmovdqa $B0, $B1
+    vmovdqa $B0, $B2
+    vmovdqa $C0, $C1
+    vmovdqa $C0, $C2
+    vpaddd .avx2_inc(%rip), $D0, $D1
+    vmovdqa $D0, $T2
+    vmovdqa $D1, $T3
+    mov \$10, $acc0
+1:  \n";
+        &chacha_qr_avx2($A0,$B0,$C0,$D0,$T0,"left");
+        &chacha_qr_avx2($A1,$B1,$C1,$D1,$T0,"left");
+        &chacha_qr_avx2($A0,$B0,$C0,$D0,$T0,"right");
+        &chacha_qr_avx2($A1,$B1,$C1,$D1,$T0,"right"); $code.="
+        dec $acc0
+    jne 1b
+    vpaddd $A2, $A0, $A0
+    vpaddd $A2, $A1, $A1
+    vpaddd $B2, $B0, $B0
+    vpaddd $B2, $B1, $B1
+    vpaddd $C2, $C0, $C0
+    vpaddd $C2, $C1, $C1
+    vpaddd $T2, $D0, $D0
+    vpaddd $T3, $D1, $D1
+    vperm2i128 \$0x02, $A0, $B0, $T0
+    # Clamp and store the key
+    vpand .clamp(%rip), $T0, $T0
+    vmovdqa $T0, $r_store
+    # Stream for up to 192 bytes
+    vperm2i128 \$0x13, $A0, $B0, $A0
+    vperm2i128 \$0x13, $C0, $D0, $B0
+    vperm2i128 \$0x02, $A1, $B1, $C0
+    vperm2i128 \$0x02, $C1, $D1, $D0
+    vperm2i128 \$0x13, $A1, $B1, $A1
+    vperm2i128 \$0x13, $C1, $D1, $B1
+open_avx2_short:
+    mov %r8, $itr2
+    call poly_hash_ad_internal
+open_avx2_hash_and_xor_loop:
+        cmp \$32, $inl
+        jb open_avx2_short_tail_32
+        sub \$32, $inl\n";
+        # Load + hash
+        &poly_add("0*8($inp)");
+        &poly_mul();
+        &poly_add("2*8($inp)");
+        &poly_mul(); $code.="
+        # Load + decrypt
+        vpxor ($inp), $A0, $A0
+        vmovdqu $A0, ($oup)
+        lea 1*32($inp), $inp
+        lea 1*32($oup), $oup
+        # Shift stream
+        vmovdqa $B0, $A0
+        vmovdqa $C0, $B0
+        vmovdqa $D0, $C0
+        vmovdqa $A1, $D0
+        vmovdqa $B1, $A1
+        vmovdqa $C1, $B1
+        vmovdqa $D1, $C1
+        vmovdqa $A2, $D1
+        vmovdqa $B2, $A2
+    jmp open_avx2_hash_and_xor_loop
+open_avx2_short_tail_32:
+    cmp \$16, $inl
+    vmovdqa $A0x, $A1x
+    jb 1f
+    sub \$16, $inl\n";
+    &poly_add("0*8($inp)");
+    &poly_mul(); $code.="
+    vpxor ($inp), $A0x, $A3x
+    vmovdqu $A3x, ($oup)
+    lea 1*16($inp), $inp
+    lea 1*16($oup), $oup
+    vextracti128 \$1, $A0, $A1x
+1:
+    vzeroupper
+    jmp open_sse_tail_16
+###############################################################################
+open_avx2_320:
+    vmovdqa $A0, $A1
+    vmovdqa $A0, $A2
+    vmovdqa $B0, $B1
+    vmovdqa $B0, $B2
+    vmovdqa $C0, $C1
+    vmovdqa $C0, $C2
+    vpaddd .avx2_inc(%rip), $D0, $D1
+    vpaddd .avx2_inc(%rip), $D1, $D2
+    vmovdqa $B0, $T1
+    vmovdqa $C0, $T2
+    vmovdqa $D0, $ctr0_store
+    vmovdqa $D1, $ctr1_store
+    vmovdqa $D2, $ctr2_store
+    mov \$10, $acc0
+1:  \n";
+        &chacha_qr_avx2($A0,$B0,$C0,$D0,$T0,"left");
+        &chacha_qr_avx2($A1,$B1,$C1,$D1,$T0,"left");
+        &chacha_qr_avx2($A2,$B2,$C2,$D2,$T0,"left");
+        &chacha_qr_avx2($A0,$B0,$C0,$D0,$T0,"right");
+        &chacha_qr_avx2($A1,$B1,$C1,$D1,$T0,"right");
+        &chacha_qr_avx2($A2,$B2,$C2,$D2,$T0,"right"); $code.="
+        dec $acc0
+    jne 1b
+    vpaddd .chacha20_consts(%rip), $A0, $A0
+    vpaddd .chacha20_consts(%rip), $A1, $A1
+    vpaddd .chacha20_consts(%rip), $A2, $A2
+    vpaddd $T1, $B0, $B0
+    vpaddd $T1, $B1, $B1
+    vpaddd $T1, $B2, $B2
+    vpaddd $T2, $C0, $C0
+    vpaddd $T2, $C1, $C1
+    vpaddd $T2, $C2, $C2
+    vpaddd $ctr0_store, $D0, $D0
+    vpaddd $ctr1_store, $D1, $D1
+    vpaddd $ctr2_store, $D2, $D2
+    vperm2i128 \$0x02, $A0, $B0, $T0
+    # Clamp and store the key
+    vpand .clamp(%rip), $T0, $T0
+    vmovdqa $T0, $r_store
+    # Stream for up to 320 bytes
+    vperm2i128 \$0x13, $A0, $B0, $A0
+    vperm2i128 \$0x13, $C0, $D0, $B0
+    vperm2i128 \$0x02, $A1, $B1, $C0
+    vperm2i128 \$0x02, $C1, $D1, $D0
+    vperm2i128 \$0x13, $A1, $B1, $A1
+    vperm2i128 \$0x13, $C1, $D1, $B1
+    vperm2i128 \$0x02, $A2, $B2, $C1
+    vperm2i128 \$0x02, $C2, $D2, $D1
+    vperm2i128 \$0x13, $A2, $B2, $A2
+    vperm2i128 \$0x13, $C2, $D2, $B2
+    jmp open_avx2_short
+.size chacha20_poly1305_open_avx2, .-chacha20_poly1305_open_avx2
+###############################################################################
+###############################################################################
+.type chacha20_poly1305_seal_avx2,\@function,2
+.align 64
+chacha20_poly1305_seal_avx2:
+    vzeroupper
+    vmovdqa .chacha20_consts(%rip), $A0
+    vbroadcasti128 0*16($keyp), $B0
+    vbroadcasti128 1*16($keyp), $C0
+    vbroadcasti128 2*16($keyp), $D0
+    vpaddd .avx2_init(%rip), $D0, $D0
+    cmp \$6*32, $inl
+    jbe seal_avx2_192
+    cmp \$10*32, $inl
+    jbe seal_avx2_320
+    vmovdqa $A0, $A1
+    vmovdqa $A0, $A2
+    vmovdqa $A0, $A3
+    vmovdqa $B0, $B1
+    vmovdqa $B0, $B2
+    vmovdqa $B0, $B3
+    vmovdqa $B0, $state1_store
+    vmovdqa $C0, $C1
+    vmovdqa $C0, $C2
+    vmovdqa $C0, $C3
+    vmovdqa $C0, $state2_store
+    vmovdqa $D0, $D3
+    vpaddd .avx2_inc(%rip), $D3, $D2
+    vpaddd .avx2_inc(%rip), $D2, $D1
+    vpaddd .avx2_inc(%rip), $D1, $D0
+    vmovdqa $D0, $ctr0_store
+    vmovdqa $D1, $ctr1_store
+    vmovdqa $D2, $ctr2_store
+    vmovdqa $D3, $ctr3_store
+    mov \$10, $acc0
+1:  \n";
+        foreach $l (@loop_body) {$code.=$l."\n";}
+        @loop_body = split /\n/, $chacha_body; $code.="
+        dec $acc0
+        jnz 1b\n";
+    &finalize_state_avx2(4); $code.="
+    vperm2i128 \$0x13, $C3, $D3, $C3
+    vperm2i128 \$0x02, $A3, $B3, $D3
+    vperm2i128 \$0x13, $A3, $B3, $A3
+    vpand .clamp(%rip), $D3, $D3
+    vmovdqa $D3, $r_store
+    mov %r8, $itr2
+    call poly_hash_ad_internal
+    # Safely store 320 bytes (otherwise would handle with optimized call)
+    vpxor 0*32($inp), $A3, $A3
+    vpxor 1*32($inp), $C3, $C3
+    vmovdqu $A3, 0*32($oup)
+    vmovdqu $C3, 1*32($oup)\n";
+    &xor_stream_avx2($A2,$B2,$C2,$D2,2*32,$T3);
+    &xor_stream_avx2($A1,$B1,$C1,$D1,6*32,$T3);
+    &finish_stream_avx2($A0,$B0,$C0,$D0,$T3); $code.="
+    lea 10*32($inp), $inp
+    sub \$10*32, $inl
+    mov \$10*32, $itr1
+    cmp \$4*32, $inl
+    jbe seal_avx2_hash
+    vpxor 0*32($inp), $A0, $A0
+    vpxor 1*32($inp), $B0, $B0
+    vpxor 2*32($inp), $C0, $C0
+    vpxor 3*32($inp), $D0, $D0
+    vmovdqu $A0, 10*32($oup)
+    vmovdqu $B0, 11*32($oup)
+    vmovdqu $C0, 12*32($oup)
+    vmovdqu $D0, 13*32($oup)
+    lea 4*32($inp), $inp
+    sub \$4*32, $inl
+    mov \$8, $itr1
+    mov \$2, $itr2
+    cmp \$4*32, $inl
+    jbe seal_avx2_tail_128
+    cmp \$8*32, $inl
+    jbe seal_avx2_tail_256
+    cmp \$12*32, $inl
+    jbe seal_avx2_tail_384
+    cmp \$16*32, $inl
+    jbe seal_avx2_tail_512\n";
+    # We have 448 bytes to hash, but main loop hashes 512 bytes at a time - perform some rounds, before the main loop
+    &prep_state_avx2(4);
+    foreach $l (@loop_body) {$code.=$l."\n";}
+    @loop_body = split /\n/, $chacha_body;
+    &emit_body(41);
+    @loop_body = split /\n/, $chacha_body; $code.="
+    sub \$16, $oup
+    mov \$9, $itr1
+    jmp 4f
+1:  \n";
+        &prep_state_avx2(4); $code.="
+        mov \$10, $itr1
+2:  \n";
+            &poly_add("0*8($oup)");
+            &emit_body(10);
+            &poly_stage1_mulx();
+            &emit_body(9);
+            &poly_stage2_mulx();
+            &emit_body(12);
+            &poly_stage3_mulx();
+            &emit_body(10);
+            &poly_reduce_stage(); $code.="
+4:  \n";
+            &emit_body(9);
+            &poly_add("2*8($oup)");
+            &emit_body(8);
+            &poly_stage1_mulx();
+            &emit_body(18);
+            &poly_stage2_mulx();
+            &emit_body(18);
+            &poly_stage3_mulx();
+            &emit_body(9);
+            &poly_reduce_stage();
+            &emit_body(8);
+            &poly_add("4*8($oup)"); $code.="
+            lea 6*8($oup), $oup\n";
+            &emit_body(18);
+            &poly_stage1_mulx();
+            &emit_body(8);
+            &poly_stage2_mulx();
+            &emit_body(8);
+            &poly_stage3_mulx();
+            &emit_body(18);
+            &poly_reduce_stage();
+            foreach $l (@loop_body) {$code.=$l."\n";}
+            @loop_body = split /\n/, $chacha_body; $code.="
+            dec $itr1
+        jne 2b\n";
+        &finalize_state_avx2(4); $code.="
+        lea 4*8($oup), $oup
+        vmovdqa $A0, $tmp_store\n";
+        &poly_add("-4*8($oup)");
+        &xor_stream_avx2($A3, $B3, $C3, $D3, 0*32, $A0); $code.="
+        vmovdqa $tmp_store, $A0\n";
+        &poly_mul();
+        &xor_stream_avx2($A2, $B2, $C2, $D2, 4*32, $A3);
+        &poly_add("-2*8($oup)");
+        &xor_stream_avx2($A1, $B1, $C1, $D1, 8*32, $A3);
+        &poly_mul();
+        &xor_stream_avx2($A0, $B0, $C0, $D0, 12*32, $A3); $code.="
+        lea 16*32($inp), $inp
+        sub \$16*32, $inl
+        cmp \$16*32, $inl
+    jg 1b\n";
+    &poly_add("0*8($oup)");
+    &poly_mul();
+    &poly_add("2*8($oup)");
+    &poly_mul(); $code.="
+    lea 4*8($oup), $oup
+    mov \$10, $itr1
+    xor $itr2, $itr2
+    cmp \$4*32, $inl
+    ja 3f
+###############################################################################
+seal_avx2_tail_128:\n";
+    &prep_state_avx2(1); $code.="
+1:  \n";
+        &poly_add("0($oup)");
+        &poly_mul(); $code.="
+        lea 2*8($oup), $oup
+2:  \n";
+        &chacha_qr_avx2($A0,$B0,$C0,$D0,$T0,"left");
+        &poly_add("0*8($oup)");
+        &poly_mul();
+        &chacha_qr_avx2($A0,$B0,$C0,$D0,$T0,"right");
+        &poly_add("2*8($oup)");
+        &poly_mul(); $code.="
+        lea 4*8($oup), $oup
+        dec $itr1
+    jg 1b
+        dec $itr2
+    jge 2b\n";
+    &finalize_state_avx2(1);
+    &finish_stream_avx2($A0,$B0,$C0,$D0,$T0); $code.="
+    jmp seal_avx2_short_loop
+3:
+    cmp \$8*32, $inl
+    ja 3f
+###############################################################################
+seal_avx2_tail_256:\n";
+    &prep_state_avx2(2); $code.="
+1:  \n";
+        &poly_add("0($oup)");
+        &poly_mul(); $code.="
+        lea 2*8($oup), $oup
+2:  \n";
+        &chacha_qr_avx2($A0,$B0,$C0,$D0,$T0,"left");
+        &chacha_qr_avx2($A1,$B1,$C1,$D1,$T0,"left");
+        &poly_add("0*8($oup)");
+        &poly_mul();
+        &chacha_qr_avx2($A0,$B0,$C0,$D0,$T0,"right");
+        &chacha_qr_avx2($A1,$B1,$C1,$D1,$T0,"right");
+        &poly_add("2*8($oup)");
+        &poly_mul(); $code.="
+        lea 4*8($oup), $oup
+        dec $itr1
+    jg 1b
+        dec $itr2
+    jge 2b\n";
+    &finalize_state_avx2(2);
+    &xor_stream_avx2($A1,$B1,$C1,$D1,0*32,$T0);
+    &finish_stream_avx2($A0,$B0,$C0,$D0,$T0); $code.="
+    mov \$4*32, $itr1
+    lea 4*32($inp), $inp
+    sub \$4*32, $inl
+    jmp seal_avx2_hash
+3:
+    cmp \$12*32, $inl
+    ja seal_avx2_tail_512
+###############################################################################
+seal_avx2_tail_384:\n";
+    &prep_state_avx2(3); $code.="
+1:  \n";
+        &poly_add("0($oup)");
+        &poly_mul(); $code.="
+        lea 2*8($oup), $oup
+2:  \n";
+        &chacha_qr_avx2($A0,$B0,$C0,$D0,$T0,"left");
+        &chacha_qr_avx2($A1,$B1,$C1,$D1,$T0,"left");
+        &poly_add("0*8($oup)");
+        &poly_mul();
+        &chacha_qr_avx2($A2,$B2,$C2,$D2,$T0,"left");
+        &chacha_qr_avx2($A0,$B0,$C0,$D0,$T0,"right");
+        &poly_add("2*8($oup)");
+        &poly_mul();
+        &chacha_qr_avx2($A1,$B1,$C1,$D1,$T0,"right");
+        &chacha_qr_avx2($A2,$B2,$C2,$D2,$T0,"right"); $code.="
+        lea 4*8($oup), $oup
+        dec $itr1
+    jg 1b
+        dec $itr2
+    jge 2b\n";
+    &finalize_state_avx2(3);
+    &xor_stream_avx2($A2,$B2,$C2,$D2,0*32,$T0);
+    &xor_stream_avx2($A1,$B1,$C1,$D1,4*32,$T0);
+    &finish_stream_avx2($A0,$B0,$C0,$D0,$T0); $code.="
+    mov \$8*32, $itr1
+    lea 8*32($inp), $inp
+    sub \$8*32, $inl
+    jmp seal_avx2_hash
+###############################################################################
+seal_avx2_tail_512:\n";
+    &prep_state_avx2(4); $code.="
+1:  \n";
+        &poly_add("0($oup)");
+        &poly_mul_mulx(); $code.="
+        lea 2*8($oup), $oup
+2:  \n";
+        &emit_body(20);
+        &poly_add("0*8($oup)");
+        &emit_body(20);
+        &poly_stage1_mulx();
+        &emit_body(20);
+        &poly_stage2_mulx();
+        &emit_body(20);
+        &poly_stage3_mulx();
+        &emit_body(20);
+        &poly_reduce_stage();
+        &emit_body(20);
+        &poly_add("2*8($oup)");
+        &emit_body(20);
+        &poly_stage1_mulx();
+        &emit_body(20);
+        &poly_stage2_mulx();
+        &emit_body(20);
+        &poly_stage3_mulx();
+        &emit_body(20);
+        &poly_reduce_stage();
+        foreach $l (@loop_body) {$code.=$l."\n";}
+        @loop_body = split /\n/, $chacha_body; $code.="
+        lea 4*8($oup), $oup
+        dec $itr1
+    jg 1b
+        dec $itr2
+    jge 2b\n";
+    &finalize_state_avx2(4); $code.="
+    vmovdqa $A0, $tmp_store\n";
+    &xor_stream_avx2($A3, $B3, $C3, $D3, 0*32, $A0); $code.="
+    vmovdqa $tmp_store, $A0\n";
+    &xor_stream_avx2($A2, $B2, $C2, $D2, 4*32, $A3);
+    &xor_stream_avx2($A1, $B1, $C1, $D1, 8*32, $A3);
+    &finish_stream_avx2($A0,$B0,$C0,$D0,$T0); $code.="
+    mov \$12*32, $itr1
+    lea 12*32($inp), $inp
+    sub \$12*32, $inl
+    jmp seal_avx2_hash
+################################################################################
+seal_avx2_320:
+    vmovdqa $A0, $A1
+    vmovdqa $A0, $A2
+    vmovdqa $B0, $B1
+    vmovdqa $B0, $B2
+    vmovdqa $C0, $C1
+    vmovdqa $C0, $C2
+    vpaddd .avx2_inc(%rip), $D0, $D1
+    vpaddd .avx2_inc(%rip), $D1, $D2
+    vmovdqa $B0, $T1
+    vmovdqa $C0, $T2
+    vmovdqa $D0, $ctr0_store
+    vmovdqa $D1, $ctr1_store
+    vmovdqa $D2, $ctr2_store
+    mov \$10, $acc0
+1:  \n";
+        &chacha_qr_avx2($A0,$B0,$C0,$D0,$T0,"left");
+        &chacha_qr_avx2($A1,$B1,$C1,$D1,$T0,"left");
+        &chacha_qr_avx2($A2,$B2,$C2,$D2,$T0,"left");
+        &chacha_qr_avx2($A0,$B0,$C0,$D0,$T0,"right");
+        &chacha_qr_avx2($A1,$B1,$C1,$D1,$T0,"right");
+        &chacha_qr_avx2($A2,$B2,$C2,$D2,$T0,"right"); $code.="
+        dec $acc0
+    jne 1b
+    vpaddd .chacha20_consts(%rip), $A0, $A0
+    vpaddd .chacha20_consts(%rip), $A1, $A1
+    vpaddd .chacha20_consts(%rip), $A2, $A2
+    vpaddd $T1, $B0, $B0
+    vpaddd $T1, $B1, $B1
+    vpaddd $T1, $B2, $B2
+    vpaddd $T2, $C0, $C0
+    vpaddd $T2, $C1, $C1
+    vpaddd $T2, $C2, $C2
+    vpaddd $ctr0_store, $D0, $D0
+    vpaddd $ctr1_store, $D1, $D1
+    vpaddd $ctr2_store, $D2, $D2
+    vperm2i128 \$0x02, $A0, $B0, $T0
+    # Clamp and store the key
+    vpand .clamp(%rip), $T0, $T0
+    vmovdqa $T0, $r_store
+    # Stream for up to 320 bytes
+    vperm2i128 \$0x13, $A0, $B0, $A0
+    vperm2i128 \$0x13, $C0, $D0, $B0
+    vperm2i128 \$0x02, $A1, $B1, $C0
+    vperm2i128 \$0x02, $C1, $D1, $D0
+    vperm2i128 \$0x13, $A1, $B1, $A1
+    vperm2i128 \$0x13, $C1, $D1, $B1
+    vperm2i128 \$0x02, $A2, $B2, $C1
+    vperm2i128 \$0x02, $C2, $D2, $D1
+    vperm2i128 \$0x13, $A2, $B2, $A2
+    vperm2i128 \$0x13, $C2, $D2, $B2
+    jmp seal_avx2_short
+################################################################################
+seal_avx2_192:
+    vmovdqa $A0, $A1
+    vmovdqa $A0, $A2
+    vmovdqa $B0, $B1
+    vmovdqa $B0, $B2
+    vmovdqa $C0, $C1
+    vmovdqa $C0, $C2
+    vpaddd .avx2_inc(%rip), $D0, $D1
+    vmovdqa $D0, $T2
+    vmovdqa $D1, $T3
+    mov \$10, $acc0
+1:  \n";
+        &chacha_qr_avx2($A0,$B0,$C0,$D0,$T0,"left");
+        &chacha_qr_avx2($A1,$B1,$C1,$D1,$T0,"left");
+        &chacha_qr_avx2($A0,$B0,$C0,$D0,$T0,"right");
+        &chacha_qr_avx2($A1,$B1,$C1,$D1,$T0,"right"); $code.="
+        dec $acc0
+    jne 1b
+    vpaddd $A2, $A0, $A0
+    vpaddd $A2, $A1, $A1
+    vpaddd $B2, $B0, $B0
+    vpaddd $B2, $B1, $B1
+    vpaddd $C2, $C0, $C0
+    vpaddd $C2, $C1, $C1
+    vpaddd $T2, $D0, $D0
+    vpaddd $T3, $D1, $D1
+    vperm2i128 \$0x02, $A0, $B0, $T0
+    # Clamp and store the key
+    vpand .clamp(%rip), $T0, $T0
+    vmovdqa $T0, $r_store
+    # Stream for up to 192 bytes
+    vperm2i128 \$0x13, $A0, $B0, $A0
+    vperm2i128 \$0x13, $C0, $D0, $B0
+    vperm2i128 \$0x02, $A1, $B1, $C0
+    vperm2i128 \$0x02, $C1, $D1, $D0
+    vperm2i128 \$0x13, $A1, $B1, $A1
+    vperm2i128 \$0x13, $C1, $D1, $B1
+seal_avx2_short:
+    mov %r8, $itr2
+    call poly_hash_ad_internal
+    xor $itr1, $itr1
+seal_avx2_hash:
+        cmp \$16, $itr1
+        jb seal_avx2_short_loop\n";
+        &poly_add("0($oup)");
+        &poly_mul(); $code.="
+        sub \$16, $itr1
+        add \$16, $oup
+    jmp seal_avx2_hash
+seal_avx2_short_loop:
+        cmp \$32, $inl
+        jb seal_avx2_short_tail
+        sub \$32, $inl
+        # Encrypt
+        vpxor ($inp), $A0, $A0
+        vmovdqu $A0, ($oup)
+        lea 1*32($inp), $inp
+        # Load + hash\n";
+        &poly_add("0*8($oup)");
+        &poly_mul();
+        &poly_add("2*8($oup)");
+        &poly_mul(); $code.="
+        lea 1*32($oup), $oup
+        # Shift stream
+        vmovdqa $B0, $A0
+        vmovdqa $C0, $B0
+        vmovdqa $D0, $C0
+        vmovdqa $A1, $D0
+        vmovdqa $B1, $A1
+        vmovdqa $C1, $B1
+        vmovdqa $D1, $C1
+        vmovdqa $A2, $D1
+        vmovdqa $B2, $A2
+    jmp seal_avx2_short_loop
+seal_avx2_short_tail:
+    cmp \$16, $inl
+    jb 1f
+    sub \$16, $inl
+    vpxor ($inp), $A0x, $A3x
+    vmovdqu $A3x, ($oup)
+    lea 1*16($inp), $inp\n";
+    &poly_add("0*8($oup)");
+    &poly_mul(); $code.="
+    lea 1*16($oup), $oup
+    vextracti128 \$1, $A0, $A0x
+1:
+    vzeroupper
+    jmp seal_sse_tail_16
+.cfi_endproc
+";
+}
+
+if (!$win64) {
+  $code =~ s/\`([^\`]*)\`/eval $1/gem;
+  print $code;
+} else {
+  print <<___;
+.globl dummy_chacha20_poly1305_asm
+.type dummy_chacha20_poly1305_asm,\@abi-omnipotent
+dummy_chacha20_poly1305_asm:
+    ret
+___
+}
+
+close STDOUT;
diff --git a/src/crypto/cipher/cipher.c b/src/crypto/cipher/cipher.c
index 4401867..e46e43e 100644
--- a/src/crypto/cipher/cipher.c
+++ b/src/crypto/cipher/cipher.c
@@ -61,9 +61,10 @@
 
 #include <openssl/err.h>
 #include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
 
 #include "internal.h"
+#include "../internal.h"
 
 
 const EVP_CIPHER *EVP_get_cipherbynid(int nid) {
@@ -88,7 +89,7 @@
 }
 
 void EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *ctx) {
-  memset(ctx, 0, sizeof(EVP_CIPHER_CTX));
+  OPENSSL_memset(ctx, 0, sizeof(EVP_CIPHER_CTX));
 }
 
 EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void) {
@@ -108,7 +109,7 @@
   }
   OPENSSL_free(c->cipher_data);
 
-  memset(c, 0, sizeof(EVP_CIPHER_CTX));
+  OPENSSL_memset(c, 0, sizeof(EVP_CIPHER_CTX));
   return 1;
 }
 
@@ -126,19 +127,23 @@
   }
 
   EVP_CIPHER_CTX_cleanup(out);
-  memcpy(out, in, sizeof(EVP_CIPHER_CTX));
+  OPENSSL_memcpy(out, in, sizeof(EVP_CIPHER_CTX));
 
   if (in->cipher_data && in->cipher->ctx_size) {
     out->cipher_data = OPENSSL_malloc(in->cipher->ctx_size);
     if (!out->cipher_data) {
+      out->cipher = NULL;
       OPENSSL_PUT_ERROR(CIPHER, ERR_R_MALLOC_FAILURE);
       return 0;
     }
-    memcpy(out->cipher_data, in->cipher_data, in->cipher->ctx_size);
+    OPENSSL_memcpy(out->cipher_data, in->cipher_data, in->cipher->ctx_size);
   }
 
   if (in->cipher->flags & EVP_CIPH_CUSTOM_COPY) {
-    return in->cipher->ctrl((EVP_CIPHER_CTX *)in, EVP_CTRL_COPY, 0, out);
+    if (!in->cipher->ctrl((EVP_CIPHER_CTX *)in, EVP_CTRL_COPY, 0, out)) {
+      out->cipher = NULL;
+      return 0;
+    }
   }
 
   return 1;
@@ -210,9 +215,9 @@
       case EVP_CIPH_CBC_MODE:
         assert(EVP_CIPHER_CTX_iv_length(ctx) <= sizeof(ctx->iv));
         if (iv) {
-          memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx));
+          OPENSSL_memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx));
         }
-        memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx));
+        OPENSSL_memcpy(ctx->iv, ctx->oiv, EVP_CIPHER_CTX_iv_length(ctx));
         break;
 
       case EVP_CIPH_CTR_MODE:
@@ -220,7 +225,7 @@
         ctx->num = 0;
         /* Don't reuse IV for CTR mode */
         if (iv) {
-          memcpy(ctx->iv, iv, EVP_CIPHER_CTX_iv_length(ctx));
+          OPENSSL_memcpy(ctx->iv, iv, EVP_CIPHER_CTX_iv_length(ctx));
         }
         break;
 
@@ -284,14 +289,14 @@
   bl = ctx->cipher->block_size;
   assert(bl <= (int)sizeof(ctx->buf));
   if (i != 0) {
-    if (i + in_len < bl) {
-      memcpy(&ctx->buf[i], in, in_len);
+    if (bl - i > in_len) {
+      OPENSSL_memcpy(&ctx->buf[i], in, in_len);
       ctx->buf_len += in_len;
       *out_len = 0;
       return 1;
     } else {
       j = bl - i;
-      memcpy(&ctx->buf[i], in, j);
+      OPENSSL_memcpy(&ctx->buf[i], in, j);
       if (!ctx->cipher->cipher(ctx, out, ctx->buf, bl)) {
         return 0;
       }
@@ -314,7 +319,7 @@
   }
 
   if (i != 0) {
-    memcpy(ctx->buf, &in[in_len], i);
+    OPENSSL_memcpy(ctx->buf, &in[in_len], i);
   }
   ctx->buf_len = i;
   return 1;
@@ -393,7 +398,7 @@
   assert(b <= sizeof(ctx->final));
 
   if (ctx->final_used) {
-    memcpy(out, ctx->final, b);
+    OPENSSL_memcpy(out, ctx->final, b);
     out += b;
     fix_len = 1;
   } else {
@@ -409,7 +414,7 @@
   if (b > 1 && !ctx->buf_len) {
     *out_len -= b;
     ctx->final_used = 1;
-    memcpy(ctx->final, &out[*out_len], b);
+    OPENSSL_memcpy(ctx->final, &out[*out_len], b);
   } else {
     ctx->final_used = 0;
   }
diff --git a/src/crypto/cipher/cipher_test.cc b/src/crypto/cipher/cipher_test.cc
index 1cbfae9..09802c2 100644
--- a/src/crypto/cipher/cipher_test.cc
+++ b/src/crypto/cipher/cipher_test.cc
@@ -62,7 +62,6 @@
 #include <openssl/err.h>
 
 #include "../test/file_test.h"
-#include "../test/scoped_types.h"
 
 
 static const EVP_CIPHER *GetCipher(const std::string &name) {
@@ -109,7 +108,7 @@
 static bool TestOperation(FileTest *t,
                           const EVP_CIPHER *cipher,
                           bool encrypt,
-                          bool streaming,
+                          size_t chunk_size,
                           const std::vector<uint8_t> &key,
                           const std::vector<uint8_t> &iv,
                           const std::vector<uint8_t> &plaintext,
@@ -127,7 +126,7 @@
 
   bool is_aead = EVP_CIPHER_mode(cipher) == EVP_CIPH_GCM_MODE;
 
-  ScopedEVP_CIPHER_CTX ctx;
+  bssl::ScopedEVP_CIPHER_CTX ctx;
   if (!EVP_CipherInit_ex(ctx.get(), cipher, nullptr, nullptr, nullptr,
                          encrypt ? 1 : 0)) {
     return false;
@@ -138,7 +137,7 @@
                                iv.size(), 0)) {
         return false;
       }
-    } else if (iv.size() != (size_t)EVP_CIPHER_CTX_iv_length(ctx.get())) {
+    } else if (iv.size() != EVP_CIPHER_CTX_iv_length(ctx.get())) {
       t->PrintLine("Bad IV length.");
       return false;
     }
@@ -170,16 +169,21 @@
     t->PrintLine("Operation failed.");
     return false;
   }
-  if (streaming) {
-    for (size_t i = 0; i < in->size(); i++) {
-      uint8_t c = (*in)[i];
+  if (chunk_size != 0) {
+    for (size_t i = 0; i < in->size();) {
+      size_t todo = chunk_size;
+      if (i + todo > in->size()) {
+        todo = in->size() - i;
+      }
+
       int len;
-      if (!EVP_CipherUpdate(ctx.get(), result.data() + result_len1, &len, &c,
-                            1)) {
+      if (!EVP_CipherUpdate(ctx.get(), result.data() + result_len1, &len,
+                            in->data() + i, todo)) {
         t->PrintLine("Operation failed.");
         return false;
       }
       result_len1 += len;
+      i += todo;
     }
   } else if (!in->empty() &&
              !EVP_CipherUpdate(ctx.get(), result.data(), &result_len1,
@@ -258,20 +262,20 @@
     }
   }
 
-  // By default, both directions are run, unless overridden by the operation.
-  if (operation != kDecrypt) {
-    if (!TestOperation(t, cipher, true /* encrypt */, false /* single-shot */,
-                       key, iv, plaintext, ciphertext, aad, tag) ||
-        !TestOperation(t, cipher, true /* encrypt */, true /* streaming */, key,
-                       iv, plaintext, ciphertext, aad, tag)) {
+  const std::vector<size_t> chunk_sizes = {0,  1,  2,  5,  7,  8,  9,  15, 16,
+                                           17, 31, 32, 33, 63, 64, 65, 512};
+
+  for (size_t chunk_size : chunk_sizes) {
+    // By default, both directions are run, unless overridden by the operation.
+    if (operation != kDecrypt &&
+        !TestOperation(t, cipher, true /* encrypt */, chunk_size, key, iv,
+                       plaintext, ciphertext, aad, tag)) {
       return false;
     }
-  }
-  if (operation != kEncrypt) {
-    if (!TestOperation(t, cipher, false /* decrypt */, false /* single-shot */,
-                       key, iv, plaintext, ciphertext, aad, tag) ||
-        !TestOperation(t, cipher, false /* decrypt */, true /* streaming */,
-                       key, iv, plaintext, ciphertext, aad, tag)) {
+
+    if (operation != kEncrypt &&
+        !TestOperation(t, cipher, false /* decrypt */, chunk_size, key, iv,
+                       plaintext, ciphertext, aad, tag)) {
       return false;
     }
   }
diff --git a/src/crypto/cipher/e_aes.c b/src/crypto/cipher/e_aes.c
index e5104b4..f67cdad 100644
--- a/src/crypto/cipher/e_aes.c
+++ b/src/crypto/cipher/e_aes.c
@@ -54,7 +54,7 @@
 #include <openssl/cpu.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
 #include <openssl/rand.h>
 #include <openssl/sha.h>
 
@@ -67,6 +67,8 @@
 #endif
 
 
+OPENSSL_MSVC_PRAGMA(warning(disable: 4702)) /* Unreachable code. */
+
 typedef struct {
   union {
     double align;
@@ -123,18 +125,15 @@
   return CRYPTO_is_ARMv8_AES_capable();
 }
 
-int aes_v8_set_encrypt_key(const uint8_t *user_key, const int bits,
-                           AES_KEY *key);
-int aes_v8_set_decrypt_key(const uint8_t *user_key, const int bits,
-                           AES_KEY *key);
-void aes_v8_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
-void aes_v8_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
-void aes_v8_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
-                        const AES_KEY *key, uint8_t *ivec, const int enc);
-void aes_v8_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t len,
-                                 const AES_KEY *key, const uint8_t ivec[16]);
+#elif !defined(OPENSSL_NO_ASM) && defined(OPENSSL_PPC64LE)
 
-#endif  /* OPENSSL_ARM */
+#define HWAES
+static int hwaes_capable(void) {
+  return CRYPTO_is_PPC64LE_vcrypto_capable();
+}
+
+#endif  /* OPENSSL_PPC64LE */
+
 
 #if defined(BSAES)
 /* On platforms where BSAES gets defined (just above), then these functions are
@@ -200,39 +199,50 @@
 }
 #endif
 
-#if !defined(HWAES)
+#if defined(HWAES)
+int aes_hw_set_encrypt_key(const uint8_t *user_key, const int bits,
+                           AES_KEY *key);
+int aes_hw_set_decrypt_key(const uint8_t *user_key, const int bits,
+                           AES_KEY *key);
+void aes_hw_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
+void aes_hw_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
+void aes_hw_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
+                        const AES_KEY *key, uint8_t *ivec, const int enc);
+void aes_hw_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t len,
+                                 const AES_KEY *key, const uint8_t ivec[16]);
+#else
 /* If HWAES isn't defined then we provide dummy functions for each of the hwaes
  * functions. */
 static int hwaes_capable(void) {
   return 0;
 }
 
-static int aes_v8_set_encrypt_key(const uint8_t *user_key, int bits,
+static int aes_hw_set_encrypt_key(const uint8_t *user_key, int bits,
                                   AES_KEY *key) {
   abort();
 }
 
-static int aes_v8_set_decrypt_key(const uint8_t *user_key, int bits,
+static int aes_hw_set_decrypt_key(const uint8_t *user_key, int bits,
                                   AES_KEY *key) {
   abort();
 }
 
-static void aes_v8_encrypt(const uint8_t *in, uint8_t *out,
+static void aes_hw_encrypt(const uint8_t *in, uint8_t *out,
                            const AES_KEY *key) {
   abort();
 }
 
-static void aes_v8_decrypt(const uint8_t *in, uint8_t *out,
+static void aes_hw_decrypt(const uint8_t *in, uint8_t *out,
                            const AES_KEY *key) {
   abort();
 }
 
-static void aes_v8_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
+static void aes_hw_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
                                const AES_KEY *key, uint8_t *ivec, int enc) {
   abort();
 }
 
-static void aes_v8_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out,
+static void aes_hw_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out,
                                         size_t len, const AES_KEY *key,
                                         const uint8_t ivec[16]) {
   abort();
@@ -252,22 +262,6 @@
 void aesni_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
                        const AES_KEY *key, uint8_t *ivec, int enc);
 
-void aesni_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t blocks,
-                                const void *key, const uint8_t *ivec);
-
-#if defined(OPENSSL_X86_64)
-size_t aesni_gcm_encrypt(const uint8_t *in, uint8_t *out, size_t len,
-                         const void *key, uint8_t ivec[16], uint64_t *Xi);
-#define AES_gcm_encrypt aesni_gcm_encrypt
-size_t aesni_gcm_decrypt(const uint8_t *in, uint8_t *out, size_t len,
-                         const void *key, uint8_t ivec[16], uint64_t *Xi);
-#define AES_gcm_decrypt aesni_gcm_decrypt
-void gcm_ghash_avx(uint64_t Xi[2], const u128 Htable[16], const uint8_t *in,
-                   size_t len);
-#define AES_GCM_ASM(gctx) \
-  (gctx->ctr == aesni_ctr32_encrypt_blocks && gctx->gcm.ghash == gcm_ghash_avx)
-#endif  /* OPENSSL_X86_64 */
-
 #else
 
 /* On other platforms, aesni_capable() will always return false and so the
@@ -288,19 +282,18 @@
 #endif
 
 static int aes_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
-                        const uint8_t *iv, int enc)
-                        OPENSSL_SUPPRESS_UNREACHABLE_CODE_WARNINGS {
+                        const uint8_t *iv, int enc) {
   int ret, mode;
   EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
 
   mode = ctx->cipher->flags & EVP_CIPH_MODE_MASK;
   if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) && !enc) {
     if (hwaes_capable()) {
-      ret = aes_v8_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
-      dat->block = (block128_f)aes_v8_decrypt;
+      ret = aes_hw_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
+      dat->block = (block128_f)aes_hw_decrypt;
       dat->stream.cbc = NULL;
       if (mode == EVP_CIPH_CBC_MODE) {
-        dat->stream.cbc = (cbc128_f)aes_v8_cbc_encrypt;
+        dat->stream.cbc = (cbc128_f)aes_hw_cbc_encrypt;
       }
     } else if (bsaes_capable() && mode == EVP_CIPH_CBC_MODE) {
       ret = AES_set_decrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
@@ -318,13 +311,13 @@
           mode == EVP_CIPH_CBC_MODE ? (cbc128_f)AES_cbc_encrypt : NULL;
     }
   } else if (hwaes_capable()) {
-    ret = aes_v8_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
-    dat->block = (block128_f)aes_v8_encrypt;
+    ret = aes_hw_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
+    dat->block = (block128_f)aes_hw_encrypt;
     dat->stream.cbc = NULL;
     if (mode == EVP_CIPH_CBC_MODE) {
-      dat->stream.cbc = (cbc128_f)aes_v8_cbc_encrypt;
+      dat->stream.cbc = (cbc128_f)aes_hw_cbc_encrypt;
     } else if (mode == EVP_CIPH_CTR_MODE) {
-      dat->stream.ctr = (ctr128_f)aes_v8_ctr32_encrypt_blocks;
+      dat->stream.ctr = (ctr128_f)aes_hw_ctr32_encrypt_blocks;
     }
   } else if (bsaes_capable() && mode == EVP_CIPH_CTR_MODE) {
     ret = AES_set_encrypt_key(key, ctx->key_len * 8, &dat->ks.ks);
@@ -368,14 +361,14 @@
 static int aes_ecb_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
                           size_t len) {
   size_t bl = ctx->cipher->block_size;
-  size_t i;
   EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
 
   if (len < bl) {
     return 1;
   }
 
-  for (i = 0, len -= bl; i <= len; i += bl) {
+  len -= bl;
+  for (size_t i = 0; i <= len; i += bl) {
     (*dat->block)(in + i, out + i, &dat->ks);
   }
 
@@ -384,17 +377,15 @@
 
 static int aes_ctr_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
                           size_t len) {
-  unsigned int num = ctx->num;
   EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
 
   if (dat->stream.ctr) {
-    CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks, ctx->iv, ctx->buf, &num,
-                                dat->stream.ctr);
+    CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks, ctx->iv, ctx->buf,
+                                &ctx->num, dat->stream.ctr);
   } else {
-    CRYPTO_ctr128_encrypt(in, out, len, &dat->ks, ctx->iv, ctx->buf, &num,
+    CRYPTO_ctr128_encrypt(in, out, len, &dat->ks, ctx->iv, ctx->buf, &ctx->num,
                           dat->block);
   }
-  ctx->num = (size_t)num;
   return 1;
 }
 
@@ -410,8 +401,7 @@
 
 static ctr128_f aes_ctr_set_key(AES_KEY *aes_key, GCM128_CONTEXT *gcm_ctx,
                                 block128_f *out_block, const uint8_t *key,
-                                size_t key_len)
-                                OPENSSL_SUPPRESS_UNREACHABLE_CODE_WARNINGS {
+                                size_t key_len) {
   if (aesni_capable()) {
     aesni_set_encrypt_key(key, key_len * 8, aes_key);
     if (gcm_ctx != NULL) {
@@ -424,14 +414,14 @@
   }
 
   if (hwaes_capable()) {
-    aes_v8_set_encrypt_key(key, key_len * 8, aes_key);
+    aes_hw_set_encrypt_key(key, key_len * 8, aes_key);
     if (gcm_ctx != NULL) {
-      CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)aes_v8_encrypt);
+      CRYPTO_gcm128_init(gcm_ctx, aes_key, (block128_f)aes_hw_encrypt);
     }
     if (out_block) {
-      *out_block = (block128_f) aes_v8_encrypt;
+      *out_block = (block128_f) aes_hw_encrypt;
     }
-    return (ctr128_f)aes_v8_ctr32_encrypt_blocks;
+    return (ctr128_f)aes_hw_ctr32_encrypt_blocks;
   }
 
   if (bsaes_capable()) {
@@ -489,7 +479,7 @@
     if (gctx->key_set) {
       CRYPTO_gcm128_setiv(&gctx->gcm, &gctx->ks.ks, iv, gctx->ivlen);
     } else {
-      memcpy(gctx->iv, iv, gctx->ivlen);
+      OPENSSL_memcpy(gctx->iv, iv, gctx->ivlen);
     }
     gctx->iv_set = 1;
     gctx->iv_gen = 0;
@@ -555,7 +545,7 @@
       if (arg <= 0 || arg > 16 || c->encrypt) {
         return 0;
       }
-      memcpy(c->buf, ptr, arg);
+      OPENSSL_memcpy(c->buf, ptr, arg);
       gctx->taglen = arg;
       return 1;
 
@@ -563,13 +553,13 @@
       if (arg <= 0 || arg > 16 || !c->encrypt || gctx->taglen < 0) {
         return 0;
       }
-      memcpy(ptr, c->buf, arg);
+      OPENSSL_memcpy(ptr, c->buf, arg);
       return 1;
 
     case EVP_CTRL_GCM_SET_IV_FIXED:
       /* Special case: -1 length restores whole IV */
       if (arg == -1) {
-        memcpy(gctx->iv, ptr, gctx->ivlen);
+        OPENSSL_memcpy(gctx->iv, ptr, gctx->ivlen);
         gctx->iv_gen = 1;
         return 1;
       }
@@ -579,7 +569,7 @@
         return 0;
       }
       if (arg) {
-        memcpy(gctx->iv, ptr, arg);
+        OPENSSL_memcpy(gctx->iv, ptr, arg);
       }
       if (c->encrypt && !RAND_bytes(gctx->iv + arg, gctx->ivlen - arg)) {
         return 0;
@@ -595,7 +585,7 @@
       if (arg <= 0 || arg > gctx->ivlen) {
         arg = gctx->ivlen;
       }
-      memcpy(ptr, gctx->iv + gctx->ivlen - arg, arg);
+      OPENSSL_memcpy(ptr, gctx->iv + gctx->ivlen - arg, arg);
       /* Invocation field will be at least 8 bytes in size and
        * so no need to check wrap around or increment more than
        * last 8 bytes. */
@@ -607,7 +597,7 @@
       if (gctx->iv_gen == 0 || gctx->key_set == 0 || c->encrypt) {
         return 0;
       }
-      memcpy(gctx->iv + gctx->ivlen - arg, ptr, arg);
+      OPENSSL_memcpy(gctx->iv + gctx->ivlen - arg, ptr, arg);
       CRYPTO_gcm128_setiv(&gctx->gcm, &gctx->ks.ks, gctx->iv, gctx->ivlen);
       gctx->iv_set = 1;
       return 1;
@@ -622,7 +612,7 @@
         if (!gctx_out->iv) {
           return 0;
         }
-        memcpy(gctx_out->iv, gctx->iv, gctx->ivlen);
+        OPENSSL_memcpy(gctx_out->iv, gctx->iv, gctx->ivlen);
       }
       return 1;
     }
@@ -651,57 +641,23 @@
       }
     } else if (ctx->encrypt) {
       if (gctx->ctr) {
-        size_t bulk = 0;
-#if defined(AES_GCM_ASM)
-        if (len >= 32 && AES_GCM_ASM(gctx)) {
-          size_t res = (16 - gctx->gcm.mres) % 16;
-
-          if (!CRYPTO_gcm128_encrypt(&gctx->gcm, &gctx->ks.ks, in, out, res)) {
-            return -1;
-          }
-
-          bulk = AES_gcm_encrypt(in + res, out + res, len - res, &gctx->ks.ks,
-                                 gctx->gcm.Yi.c, gctx->gcm.Xi.u);
-          gctx->gcm.len.u[1] += bulk;
-          bulk += res;
-        }
-#endif
-        if (!CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm, &gctx->ks.ks, in + bulk,
-                                         out + bulk, len - bulk, gctx->ctr)) {
+        if (!CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm, &gctx->ks.ks, in, out, len,
+                                         gctx->ctr)) {
           return -1;
         }
       } else {
-        size_t bulk = 0;
-        if (!CRYPTO_gcm128_encrypt(&gctx->gcm, &gctx->ks.ks, in + bulk,
-                                   out + bulk, len - bulk)) {
+        if (!CRYPTO_gcm128_encrypt(&gctx->gcm, &gctx->ks.ks, in, out, len)) {
           return -1;
         }
       }
     } else {
       if (gctx->ctr) {
-        size_t bulk = 0;
-#if defined(AES_GCM_ASM)
-        if (len >= 16 && AES_GCM_ASM(gctx)) {
-          size_t res = (16 - gctx->gcm.mres) % 16;
-
-          if (!CRYPTO_gcm128_decrypt(&gctx->gcm, &gctx->ks.ks, in, out, res)) {
-            return -1;
-          }
-
-          bulk = AES_gcm_decrypt(in + res, out + res, len - res, &gctx->ks.ks,
-                                 gctx->gcm.Yi.c, gctx->gcm.Xi.u);
-          gctx->gcm.len.u[1] += bulk;
-          bulk += res;
-        }
-#endif
-        if (!CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm, &gctx->ks.ks, in + bulk,
-                                         out + bulk, len - bulk, gctx->ctr)) {
+        if (!CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm, &gctx->ks.ks, in, out, len,
+                                         gctx->ctr)) {
           return -1;
         }
       } else {
-        size_t bulk = 0;
-        if (!CRYPTO_gcm128_decrypt(&gctx->gcm, &gctx->ks.ks, in + bulk,
-                                   out + bulk, len - bulk)) {
+        if (!CRYPTO_gcm128_decrypt(&gctx->gcm, &gctx->ks.ks, in, out, len)) {
           return -1;
         }
       }
@@ -904,7 +860,7 @@
     if (gctx->key_set) {
       CRYPTO_gcm128_setiv(&gctx->gcm, &gctx->ks.ks, iv, gctx->ivlen);
     } else {
-      memcpy(gctx->iv, iv, gctx->ivlen);
+      OPENSSL_memcpy(gctx->iv, iv, gctx->ivlen);
     }
     gctx->iv_set = 1;
     gctx->iv_gen = 0;
@@ -1117,7 +1073,7 @@
 
   const AES_KEY *key = &gcm_ctx->ks.ks;
 
-  memcpy(&gcm, &gcm_ctx->gcm, sizeof(gcm));
+  OPENSSL_memcpy(&gcm, &gcm_ctx->gcm, sizeof(gcm));
   CRYPTO_gcm128_setiv(&gcm, key, nonce, nonce_len);
 
   if (ad_len > 0 && !CRYPTO_gcm128_aad(&gcm, ad, ad_len)) {
@@ -1164,7 +1120,7 @@
 
   const AES_KEY *key = &gcm_ctx->ks.ks;
 
-  memcpy(&gcm, &gcm_ctx->gcm, sizeof(gcm));
+  OPENSSL_memcpy(&gcm, &gcm_ctx->gcm, sizeof(gcm));
   CRYPTO_gcm128_setiv(&gcm, key, nonce, nonce_len);
 
   if (!CRYPTO_gcm128_aad(&gcm, ad, ad_len)) {
@@ -1202,7 +1158,6 @@
     aead_aes_gcm_cleanup,
     aead_aes_gcm_seal,
     aead_aes_gcm_open,
-    NULL,                     /* get_rc4_state */
     NULL,                     /* get_iv */
 };
 
@@ -1216,7 +1171,6 @@
     aead_aes_gcm_cleanup,
     aead_aes_gcm_seal,
     aead_aes_gcm_open,
-    NULL,                     /* get_rc4_state */
     NULL,                     /* get_iv */
 };
 
@@ -1225,268 +1179,6 @@
 const EVP_AEAD *EVP_aead_aes_256_gcm(void) { return &aead_aes_256_gcm; }
 
 
-/* AES Key Wrap is specified in
- * http://csrc.nist.gov/groups/ST/toolkit/documents/kms/key-wrap.pdf
- * or https://tools.ietf.org/html/rfc3394 */
-
-struct aead_aes_key_wrap_ctx {
-  uint8_t key[32];
-  unsigned key_bits;
-};
-
-static int aead_aes_key_wrap_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
-                                  size_t key_len, size_t tag_len) {
-  struct aead_aes_key_wrap_ctx *kw_ctx;
-  const size_t key_bits = key_len * 8;
-
-  if (key_bits != 128 && key_bits != 256) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH);
-    return 0; /* EVP_AEAD_CTX_init should catch this. */
-  }
-
-  if (tag_len == EVP_AEAD_DEFAULT_TAG_LENGTH) {
-    tag_len = 8;
-  }
-
-  if (tag_len != 8) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_TAG_SIZE);
-    return 0;
-  }
-
-  kw_ctx = OPENSSL_malloc(sizeof(struct aead_aes_key_wrap_ctx));
-  if (kw_ctx == NULL) {
-    OPENSSL_PUT_ERROR(CIPHER, ERR_R_MALLOC_FAILURE);
-    return 0;
-  }
-
-  memcpy(kw_ctx->key, key, key_len);
-  kw_ctx->key_bits = key_bits;
-
-  ctx->aead_state = kw_ctx;
-  return 1;
-}
-
-static void aead_aes_key_wrap_cleanup(EVP_AEAD_CTX *ctx) {
-  struct aead_aes_key_wrap_ctx *kw_ctx = ctx->aead_state;
-  OPENSSL_cleanse(kw_ctx, sizeof(struct aead_aes_key_wrap_ctx));
-  OPENSSL_free(kw_ctx);
-}
-
-/* kDefaultAESKeyWrapNonce is the default nonce value given in 2.2.3.1. */
-static const uint8_t kDefaultAESKeyWrapNonce[8] = {0xa6, 0xa6, 0xa6, 0xa6,
-                                                   0xa6, 0xa6, 0xa6, 0xa6};
-
-
-static int aead_aes_key_wrap_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
-                                  size_t *out_len, size_t max_out_len,
-                                  const uint8_t *nonce, size_t nonce_len,
-                                  const uint8_t *in, size_t in_len,
-                                  const uint8_t *ad, size_t ad_len) {
-  const struct aead_aes_key_wrap_ctx *kw_ctx = ctx->aead_state;
-  union {
-    double align;
-    AES_KEY ks;
-  } ks;
-  /* Variables in this function match up with the variables in the second half
-   * of section 2.2.1. */
-  unsigned i, j, n;
-  uint8_t A[AES_BLOCK_SIZE];
-
-  if (ad_len != 0) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_AD_SIZE);
-    return 0;
-  }
-
-  if (nonce_len == 0) {
-    nonce = kDefaultAESKeyWrapNonce;
-    nonce_len = sizeof(kDefaultAESKeyWrapNonce);
-  }
-
-  if (nonce_len != 8) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
-    return 0;
-  }
-
-  if (in_len % 8 != 0) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_INPUT_SIZE);
-    return 0;
-  }
-
-  /* The code below only handles a 32-bit |t| thus 6*|n| must be less than
-   * 2^32, where |n| is |in_len| / 8. So in_len < 4/3 * 2^32 and we
-   * conservatively cap it to 2^32-16 to stop 32-bit platforms complaining that
-   * a comparison is always true. */
-  if (in_len > 0xfffffff0) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
-    return 0;
-  }
-
-  n = in_len / 8;
-
-  if (n < 2) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_INPUT_SIZE);
-    return 0;
-  }
-
-  if (in_len + 8 < in_len) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
-    return 0;
-  }
-
-  if (max_out_len < in_len + 8) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
-    return 0;
-  }
-
-  if (AES_set_encrypt_key(kw_ctx->key, kw_ctx->key_bits, &ks.ks) < 0) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_AES_KEY_SETUP_FAILED);
-    return 0;
-  }
-
-  memmove(out + 8, in, in_len);
-  memcpy(A, nonce, 8);
-
-  for (j = 0; j < 6; j++) {
-    for (i = 1; i <= n; i++) {
-      uint32_t t;
-
-      memcpy(A + 8, out + 8 * i, 8);
-      AES_encrypt(A, A, &ks.ks);
-      t = n * j + i;
-      A[7] ^= t & 0xff;
-      A[6] ^= (t >> 8) & 0xff;
-      A[5] ^= (t >> 16) & 0xff;
-      A[4] ^= (t >> 24) & 0xff;
-      memcpy(out + 8 * i, A + 8, 8);
-    }
-  }
-
-  memcpy(out, A, 8);
-  *out_len = in_len + 8;
-  return 1;
-}
-
-static int aead_aes_key_wrap_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
-                                  size_t *out_len, size_t max_out_len,
-                                  const uint8_t *nonce, size_t nonce_len,
-                                  const uint8_t *in, size_t in_len,
-                                  const uint8_t *ad, size_t ad_len) {
-  const struct aead_aes_key_wrap_ctx *kw_ctx = ctx->aead_state;
-  union {
-    double align;
-    AES_KEY ks;
-  } ks;
-  /* Variables in this function match up with the variables in the second half
-   * of section 2.2.1. */
-  unsigned i, j, n;
-  uint8_t A[AES_BLOCK_SIZE];
-
-  if (ad_len != 0) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_AD_SIZE);
-    return 0;
-  }
-
-  if (nonce_len == 0) {
-    nonce = kDefaultAESKeyWrapNonce;
-    nonce_len = sizeof(kDefaultAESKeyWrapNonce);
-  }
-
-  if (nonce_len != 8) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
-    return 0;
-  }
-
-  if (in_len % 8 != 0) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_INPUT_SIZE);
-    return 0;
-  }
-
-  /* The code below only handles a 32-bit |t| thus 6*|n| must be less than
-   * 2^32, where |n| is |in_len| / 8. So in_len < 4/3 * 2^32 and we
-   * conservatively cap it to 2^32-8 to stop 32-bit platforms complaining that
-   * a comparison is always true. */
-  if (in_len > 0xfffffff8) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
-    return 0;
-  }
-
-  if (in_len < 24) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
-    return 0;
-  }
-
-  n = (in_len / 8) - 1;
-
-  if (max_out_len < in_len - 8) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
-    return 0;
-  }
-
-  if (AES_set_decrypt_key(kw_ctx->key, kw_ctx->key_bits, &ks.ks) < 0) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_AES_KEY_SETUP_FAILED);
-    return 0;
-  }
-
-  memcpy(A, in, 8);
-  memmove(out, in + 8, in_len - 8);
-
-  for (j = 5; j < 6; j--) {
-    for (i = n; i > 0; i--) {
-      uint32_t t;
-
-      t = n * j + i;
-      A[7] ^= t & 0xff;
-      A[6] ^= (t >> 8) & 0xff;
-      A[5] ^= (t >> 16) & 0xff;
-      A[4] ^= (t >> 24) & 0xff;
-      memcpy(A + 8, out + 8 * (i - 1), 8);
-      AES_decrypt(A, A, &ks.ks);
-      memcpy(out + 8 * (i - 1), A + 8, 8);
-    }
-  }
-
-  if (CRYPTO_memcmp(A, nonce, 8) != 0) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
-    return 0;
-  }
-
-  *out_len = in_len - 8;
-  return 1;
-}
-
-static const EVP_AEAD aead_aes_128_key_wrap = {
-    16, /* key len */
-    8,  /* nonce len */
-    8,  /* overhead */
-    8,  /* max tag length */
-    aead_aes_key_wrap_init,
-    NULL, /* init_with_direction */
-    aead_aes_key_wrap_cleanup,
-    aead_aes_key_wrap_seal,
-    aead_aes_key_wrap_open,
-    NULL, /* get_rc4_state */
-    NULL, /* get_iv */
-};
-
-static const EVP_AEAD aead_aes_256_key_wrap = {
-    32, /* key len */
-    8,  /* nonce len */
-    8,  /* overhead */
-    8,  /* max tag length */
-    aead_aes_key_wrap_init,
-    NULL, /* init_with_direction */
-    aead_aes_key_wrap_cleanup,
-    aead_aes_key_wrap_seal,
-    aead_aes_key_wrap_open,
-    NULL, /* get_rc4_state */
-    NULL, /* get_iv */
-};
-
-const EVP_AEAD *EVP_aead_aes_128_key_wrap(void) { return &aead_aes_128_key_wrap; }
-
-const EVP_AEAD *EVP_aead_aes_256_key_wrap(void) { return &aead_aes_256_key_wrap; }
-
-
 #define EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN SHA256_DIGEST_LENGTH
 #define EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN 12
 
@@ -1506,8 +1198,8 @@
                       const uint8_t hmac_key[32]) {
   static const size_t hmac_key_len = 32;
   uint8_t block[SHA256_CBLOCK];
-  memcpy(block, hmac_key, hmac_key_len);
-  memset(block + hmac_key_len, 0x36, sizeof(block) - hmac_key_len);
+  OPENSSL_memcpy(block, hmac_key, hmac_key_len);
+  OPENSSL_memset(block + hmac_key_len, 0x36, sizeof(block) - hmac_key_len);
 
   unsigned i;
   for (i = 0; i < hmac_key_len; i++) {
@@ -1517,7 +1209,7 @@
   SHA256_Init(out_inner);
   SHA256_Update(out_inner, block, sizeof(block));
 
-  memset(block + hmac_key_len, 0x5c, sizeof(block) - hmac_key_len);
+  OPENSSL_memset(block + hmac_key_len, 0x5c, sizeof(block) - hmac_key_len);
   for (i = 0; i < hmac_key_len; i++) {
     block[i] ^= (0x36 ^ 0x5c);
   }
@@ -1592,7 +1284,7 @@
                            const uint8_t *nonce, const uint8_t *ciphertext,
                            size_t ciphertext_len) {
   SHA256_CTX sha256;
-  memcpy(&sha256, inner_init_state, sizeof(sha256));
+  OPENSSL_memcpy(&sha256, inner_init_state, sizeof(sha256));
   hmac_update_uint64(&sha256, ad_len);
   hmac_update_uint64(&sha256, ciphertext_len);
   SHA256_Update(&sha256, nonce, EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN);
@@ -1605,7 +1297,7 @@
                         SHA256_CBLOCK)) %
       SHA256_CBLOCK;
   uint8_t padding[SHA256_CBLOCK];
-  memset(padding, 0, num_padding);
+  OPENSSL_memset(padding, 0, num_padding);
   SHA256_Update(&sha256, padding, num_padding);
 
   SHA256_Update(&sha256, ciphertext, ciphertext_len);
@@ -1613,7 +1305,7 @@
   uint8_t inner_digest[SHA256_DIGEST_LENGTH];
   SHA256_Final(inner_digest, &sha256);
 
-  memcpy(&sha256, outer_init_state, sizeof(sha256));
+  OPENSSL_memcpy(&sha256, outer_init_state, sizeof(sha256));
   SHA256_Update(&sha256, inner_digest, sizeof(inner_digest));
   SHA256_Final(out, &sha256);
 }
@@ -1625,11 +1317,11 @@
    * bytes is pointless. However, |CRYPTO_ctr128_encrypt| requires it. */
   uint8_t partial_block_buffer[AES_BLOCK_SIZE];
   unsigned partial_block_offset = 0;
-  memset(partial_block_buffer, 0, sizeof(partial_block_buffer));
+  OPENSSL_memset(partial_block_buffer, 0, sizeof(partial_block_buffer));
 
   uint8_t counter[AES_BLOCK_SIZE];
-  memcpy(counter, nonce, EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN);
-  memset(counter + EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN, 0, 4);
+  OPENSSL_memcpy(counter, nonce, EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN);
+  OPENSSL_memset(counter + EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN, 0, 4);
 
   if (aes_ctx->ctr) {
     CRYPTO_ctr128_encrypt_ctr32(in, out, len, &aes_ctx->ks.ks, counter,
@@ -1672,7 +1364,7 @@
   uint8_t hmac_result[SHA256_DIGEST_LENGTH];
   hmac_calculate(hmac_result, &aes_ctx->inner_init_state,
                  &aes_ctx->outer_init_state, ad, ad_len, nonce, out, in_len);
-  memcpy(out + in_len, hmac_result, aes_ctx->tag_len);
+  OPENSSL_memcpy(out + in_len, hmac_result, aes_ctx->tag_len);
   *out_len = in_len + aes_ctx->tag_len;
 
   return 1;
@@ -1729,7 +1421,6 @@
     aead_aes_ctr_hmac_sha256_cleanup,
     aead_aes_ctr_hmac_sha256_seal,
     aead_aes_ctr_hmac_sha256_open,
-    NULL /* get_rc4_state */,
     NULL /* get_iv */,
 };
 
@@ -1744,7 +1435,6 @@
     aead_aes_ctr_hmac_sha256_cleanup,
     aead_aes_ctr_hmac_sha256_seal,
     aead_aes_ctr_hmac_sha256_open,
-    NULL /* get_rc4_state */,
     NULL /* get_iv */,
 };
 
@@ -1756,6 +1446,320 @@
   return &aead_aes_256_ctr_hmac_sha256;
 }
 
+#if !defined(OPENSSL_SMALL)
+
+#define EVP_AEAD_AES_GCM_SIV_NONCE_LEN 12
+#define EVP_AEAD_AES_GCM_SIV_TAG_LEN 16
+
+struct aead_aes_gcm_siv_ctx {
+  union {
+    double align;
+    AES_KEY ks;
+  } ks;
+  block128_f kgk_block;
+  unsigned is_256:1;
+};
+
+static int aead_aes_gcm_siv_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
+                                 size_t key_len, size_t tag_len) {
+  const size_t key_bits = key_len * 8;
+
+  if (key_bits != 128 && key_bits != 256) {
+    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH);
+    return 0; /* EVP_AEAD_CTX_init should catch this. */
+  }
+
+  if (tag_len == EVP_AEAD_DEFAULT_TAG_LENGTH) {
+    tag_len = EVP_AEAD_AES_GCM_SIV_TAG_LEN;
+  }
+
+  if (tag_len != EVP_AEAD_AES_GCM_SIV_TAG_LEN) {
+    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TAG_TOO_LARGE);
+    return 0;
+  }
+
+  struct aead_aes_gcm_siv_ctx *gcm_siv_ctx =
+      OPENSSL_malloc(sizeof(struct aead_aes_gcm_siv_ctx));
+  if (gcm_siv_ctx == NULL) {
+    return 0;
+  }
+  OPENSSL_memset(gcm_siv_ctx, 0, sizeof(struct aead_aes_gcm_siv_ctx));
+
+  if (aesni_capable()) {
+    aesni_set_encrypt_key(key, key_len * 8, &gcm_siv_ctx->ks.ks);
+    gcm_siv_ctx->kgk_block = (block128_f)aesni_encrypt;
+  } else if (hwaes_capable()) {
+    aes_hw_set_encrypt_key(key, key_len * 8, &gcm_siv_ctx->ks.ks);
+    gcm_siv_ctx->kgk_block = (block128_f)aes_hw_encrypt;
+  } else if (vpaes_capable()) {
+    vpaes_set_encrypt_key(key, key_len * 8, &gcm_siv_ctx->ks.ks);
+    gcm_siv_ctx->kgk_block = (block128_f)vpaes_encrypt;
+  } else {
+    AES_set_encrypt_key(key, key_len * 8, &gcm_siv_ctx->ks.ks);
+    gcm_siv_ctx->kgk_block = (block128_f)AES_encrypt;
+  }
+
+  gcm_siv_ctx->is_256 = (key_len == 32);
+  ctx->aead_state = gcm_siv_ctx;
+
+  return 1;
+}
+
+static void aead_aes_gcm_siv_cleanup(EVP_AEAD_CTX *ctx) {
+  struct aead_aes_gcm_siv_ctx *gcm_siv_ctx = ctx->aead_state;
+  OPENSSL_cleanse(gcm_siv_ctx, sizeof(struct aead_aes_gcm_siv_ctx));
+  OPENSSL_free(gcm_siv_ctx);
+}
+
+/* gcm_siv_crypt encrypts (or decrypts—it's the same thing) |in_len| bytes from
+ * |in| to |out|, using the block function |enc_block| with |key| in counter
+ * mode, starting at |initial_counter|. This differs from the traditional
+ * counter mode code in that the counter is handled little-endian, only the
+ * first four bytes are used and the GCM-SIV tweak to the final byte is
+ * applied. The |in| and |out| pointers may be equal but otherwise must not
+ * alias. */
+static void gcm_siv_crypt(uint8_t *out, const uint8_t *in, size_t in_len,
+                          const uint8_t initial_counter[AES_BLOCK_SIZE],
+                          block128_f enc_block, const AES_KEY *key) {
+  union {
+    uint32_t w[4];
+    uint8_t c[16];
+  } counter;
+
+  OPENSSL_memcpy(counter.c, initial_counter, AES_BLOCK_SIZE);
+  counter.c[15] |= 0x80;
+
+  for (size_t done = 0; done < in_len;) {
+    uint8_t keystream[AES_BLOCK_SIZE];
+    enc_block(counter.c, keystream, key);
+    counter.w[0]++;
+
+    size_t todo = AES_BLOCK_SIZE;
+    if (in_len - done < todo) {
+      todo = in_len - done;
+    }
+
+    for (size_t i = 0; i < todo; i++) {
+      out[done + i] = keystream[i] ^ in[done + i];
+    }
+
+    done += todo;
+  }
+}
+
+/* gcm_siv_polyval evaluates POLYVAL at |auth_key| on the given plaintext and
+ * AD. The result is written to |out_tag|. */
+static void gcm_siv_polyval(
+    uint8_t out_tag[16], const uint8_t *in, size_t in_len, const uint8_t *ad,
+    size_t ad_len, const uint8_t auth_key[16],
+    const uint8_t nonce[EVP_AEAD_AES_GCM_SIV_NONCE_LEN]) {
+  struct polyval_ctx polyval_ctx;
+  CRYPTO_POLYVAL_init(&polyval_ctx, auth_key);
+
+  CRYPTO_POLYVAL_update_blocks(&polyval_ctx, ad, ad_len & ~15);
+
+  uint8_t scratch[16];
+  if (ad_len & 15) {
+    OPENSSL_memset(scratch, 0, sizeof(scratch));
+    OPENSSL_memcpy(scratch, &ad[ad_len & ~15], ad_len & 15);
+    CRYPTO_POLYVAL_update_blocks(&polyval_ctx, scratch, sizeof(scratch));
+  }
+
+  CRYPTO_POLYVAL_update_blocks(&polyval_ctx, in, in_len & ~15);
+  if (in_len & 15) {
+    OPENSSL_memset(scratch, 0, sizeof(scratch));
+    OPENSSL_memcpy(scratch, &in[in_len & ~15], in_len & 15);
+    CRYPTO_POLYVAL_update_blocks(&polyval_ctx, scratch, sizeof(scratch));
+  }
+
+  union {
+    uint8_t c[16];
+    struct {
+      uint64_t ad;
+      uint64_t in;
+    } bitlens;
+  } length_block;
+
+  length_block.bitlens.ad = ad_len * 8;
+  length_block.bitlens.in = in_len * 8;
+  CRYPTO_POLYVAL_update_blocks(&polyval_ctx, length_block.c,
+                               sizeof(length_block));
+
+  CRYPTO_POLYVAL_finish(&polyval_ctx, out_tag);
+  for (size_t i = 0; i < EVP_AEAD_AES_GCM_SIV_NONCE_LEN; i++) {
+    out_tag[i] ^= nonce[i];
+  }
+  out_tag[15] &= 0x7f;
+}
+
+/* gcm_siv_record_keys contains the keys used for a specific GCM-SIV record. */
+struct gcm_siv_record_keys {
+  uint8_t auth_key[16];
+  union {
+    double align;
+    AES_KEY ks;
+  } enc_key;
+  block128_f enc_block;
+};
+
+/* gcm_siv_keys calculates the keys for a specific GCM-SIV record with the
+ * given nonce and writes them to |*out_keys|. */
+static void gcm_siv_keys(
+    const struct aead_aes_gcm_siv_ctx *gcm_siv_ctx,
+    struct gcm_siv_record_keys *out_keys,
+    const uint8_t nonce[EVP_AEAD_AES_GCM_SIV_NONCE_LEN]) {
+  const AES_KEY *const key = &gcm_siv_ctx->ks.ks;
+  uint8_t key_material[(128 /* POLYVAL key */ + 256 /* max AES key */) / 8];
+  const size_t blocks_needed = gcm_siv_ctx->is_256 ? 6 : 4;
+
+  uint8_t counter[AES_BLOCK_SIZE];
+  OPENSSL_memset(counter, 0, AES_BLOCK_SIZE - EVP_AEAD_AES_GCM_SIV_NONCE_LEN);
+  OPENSSL_memcpy(counter + AES_BLOCK_SIZE - EVP_AEAD_AES_GCM_SIV_NONCE_LEN,
+                 nonce, EVP_AEAD_AES_GCM_SIV_NONCE_LEN);
+  for (size_t i = 0; i < blocks_needed; i++) {
+    counter[0] = i;
+
+    uint8_t ciphertext[AES_BLOCK_SIZE];
+    gcm_siv_ctx->kgk_block(counter, ciphertext, key);
+    OPENSSL_memcpy(&key_material[i * 8], ciphertext, 8);
+  }
+
+  OPENSSL_memcpy(out_keys->auth_key, key_material, 16);
+  aes_ctr_set_key(&out_keys->enc_key.ks, NULL, &out_keys->enc_block,
+                  key_material + 16, gcm_siv_ctx->is_256 ? 32 : 16);
+}
+
+static int aead_aes_gcm_siv_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
+                                 size_t *out_len, size_t max_out_len,
+                                 const uint8_t *nonce, size_t nonce_len,
+                                 const uint8_t *in, size_t in_len,
+                                 const uint8_t *ad, size_t ad_len) {
+  const struct aead_aes_gcm_siv_ctx *gcm_siv_ctx = ctx->aead_state;
+  const uint64_t in_len_64 = in_len;
+  const uint64_t ad_len_64 = ad_len;
+
+  if (in_len + EVP_AEAD_AES_GCM_SIV_TAG_LEN < in_len ||
+      in_len_64 > (UINT64_C(1) << 36) ||
+      ad_len_64 >= (UINT64_C(1) << 61)) {
+    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
+    return 0;
+  }
+
+  if (max_out_len < in_len + EVP_AEAD_AES_GCM_SIV_TAG_LEN) {
+    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
+    return 0;
+  }
+
+  if (nonce_len != EVP_AEAD_AES_GCM_SIV_NONCE_LEN) {
+    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
+    return 0;
+  }
+
+  struct gcm_siv_record_keys keys;
+  gcm_siv_keys(gcm_siv_ctx, &keys, nonce);
+
+  uint8_t tag[16];
+  gcm_siv_polyval(tag, in, in_len, ad, ad_len, keys.auth_key, nonce);
+  keys.enc_block(tag, tag, &keys.enc_key.ks);
+
+  gcm_siv_crypt(out, in, in_len, tag, keys.enc_block, &keys.enc_key.ks);
+
+  OPENSSL_memcpy(&out[in_len], tag, EVP_AEAD_AES_GCM_SIV_TAG_LEN);
+  *out_len = in_len + EVP_AEAD_AES_GCM_SIV_TAG_LEN;
+
+  return 1;
+}
+
+static int aead_aes_gcm_siv_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
+                                 size_t *out_len, size_t max_out_len,
+                                 const uint8_t *nonce, size_t nonce_len,
+                                 const uint8_t *in, size_t in_len,
+                                 const uint8_t *ad, size_t ad_len) {
+  const uint64_t ad_len_64 = ad_len;
+  if (ad_len_64 >= (UINT64_C(1) << 61)) {
+    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
+    return 0;
+  }
+
+  const uint64_t in_len_64 = in_len;
+  if (in_len < EVP_AEAD_AES_GCM_SIV_TAG_LEN ||
+      in_len_64 > (UINT64_C(1) << 36) + AES_BLOCK_SIZE) {
+    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
+    return 0;
+  }
+
+  if (nonce_len != EVP_AEAD_AES_GCM_SIV_NONCE_LEN) {
+    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
+    return 0;
+  }
+
+  const struct aead_aes_gcm_siv_ctx *gcm_siv_ctx = ctx->aead_state;
+  const size_t plaintext_len = in_len - EVP_AEAD_AES_GCM_SIV_TAG_LEN;
+
+  if (max_out_len < plaintext_len) {
+    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
+    return 0;
+  }
+
+  struct gcm_siv_record_keys keys;
+  gcm_siv_keys(gcm_siv_ctx, &keys, nonce);
+
+  gcm_siv_crypt(out, in, plaintext_len, &in[plaintext_len], keys.enc_block,
+                &keys.enc_key.ks);
+
+  uint8_t expected_tag[EVP_AEAD_AES_GCM_SIV_TAG_LEN];
+  gcm_siv_polyval(expected_tag, out, plaintext_len, ad, ad_len, keys.auth_key,
+                  nonce);
+  keys.enc_block(expected_tag, expected_tag, &keys.enc_key.ks);
+
+  if (CRYPTO_memcmp(expected_tag, &in[plaintext_len], sizeof(expected_tag)) !=
+      0) {
+    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
+    return 0;
+  }
+
+  *out_len = plaintext_len;
+  return 1;
+}
+
+static const EVP_AEAD aead_aes_128_gcm_siv = {
+    16,                             /* key length */
+    EVP_AEAD_AES_GCM_SIV_NONCE_LEN, /* nonce length */
+    EVP_AEAD_AES_GCM_SIV_TAG_LEN,   /* overhead */
+    EVP_AEAD_AES_GCM_SIV_TAG_LEN,   /* max tag length */
+
+    aead_aes_gcm_siv_init,
+    NULL /* init_with_direction */,
+    aead_aes_gcm_siv_cleanup,
+    aead_aes_gcm_siv_seal,
+    aead_aes_gcm_siv_open,
+    NULL /* get_iv */,
+};
+
+static const EVP_AEAD aead_aes_256_gcm_siv = {
+    32,                             /* key length */
+    EVP_AEAD_AES_GCM_SIV_NONCE_LEN, /* nonce length */
+    EVP_AEAD_AES_GCM_SIV_TAG_LEN,   /* overhead */
+    EVP_AEAD_AES_GCM_SIV_TAG_LEN,   /* max tag length */
+
+    aead_aes_gcm_siv_init,
+    NULL /* init_with_direction */,
+    aead_aes_gcm_siv_cleanup,
+    aead_aes_gcm_siv_seal,
+    aead_aes_gcm_siv_open,
+    NULL /* get_iv */,
+};
+
+const EVP_AEAD *EVP_aead_aes_128_gcm_siv(void) {
+  return &aead_aes_128_gcm_siv;
+}
+
+const EVP_AEAD *EVP_aead_aes_256_gcm_siv(void) {
+  return &aead_aes_256_gcm_siv;
+}
+
+#endif  /* !OPENSSL_SMALL */
+
 int EVP_has_aes_hardware(void) {
 #if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
   return aesni_capable() && crypto_gcm_clmul_enabled();
diff --git a/src/crypto/cipher/e_chacha20poly1305.c b/src/crypto/cipher/e_chacha20poly1305.c
index f384950..c6e81ab 100644
--- a/src/crypto/cipher/e_chacha20poly1305.c
+++ b/src/crypto/cipher/e_chacha20poly1305.c
@@ -18,11 +18,13 @@
 
 #include <openssl/chacha.h>
 #include <openssl/cipher.h>
+#include <openssl/cpu.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
 #include <openssl/poly1305.h>
 
 #include "internal.h"
+#include "../internal.h"
 
 
 #define POLY1305_TAG_LEN 16
@@ -32,6 +34,51 @@
   unsigned char tag_len;
 };
 
+#if defined(OPENSSL_X86_64) && !defined(OPENSSL_NO_ASM) && \
+    !defined(OPENSSL_WINDOWS)
+static int asm_capable(void) {
+  const int sse41_capable = (OPENSSL_ia32cap_P[1] & (1 << 19)) != 0;
+  return sse41_capable;
+}
+
+// chacha20_poly1305_open is defined in chacha20_poly1305_x86_64.pl. It
+// decrypts |plaintext_len| bytes from |ciphertext| and writes them to
+// |out_plaintext|. On entry, |aead_data| must contain the final 48 bytes of
+// the initial ChaCha20 block, i.e. the key, followed by four zeros, followed
+// by the nonce. On exit, it will contain the calculated tag value, which the
+// caller must check.
+extern void chacha20_poly1305_open(uint8_t *out_plaintext,
+                                   const uint8_t *ciphertext,
+                                   size_t plaintext_len, const uint8_t *ad,
+                                   size_t ad_len, uint8_t *aead_data);
+
+// chacha20_poly1305_open is defined in chacha20_poly1305_x86_64.pl. It
+// encrypts |plaintext_len| bytes from |plaintext| and writes them to
+// |out_ciphertext|. On entry, |aead_data| must contain the final 48 bytes of
+// the initial ChaCha20 block, i.e. the key, followed by four zeros, followed
+// by the nonce. On exit, it will contain the calculated tag value, which the
+// caller must append to the ciphertext.
+extern void chacha20_poly1305_seal(uint8_t *out_ciphertext,
+                                   const uint8_t *plaintext,
+                                   size_t plaintext_len, const uint8_t *ad,
+                                   size_t ad_len, uint8_t *aead_data);
+#else
+static int asm_capable(void) {
+  return 0;
+}
+
+
+static void chacha20_poly1305_open(uint8_t *out_plaintext,
+                                   const uint8_t *ciphertext,
+                                   size_t plaintext_len, const uint8_t *ad,
+                                   size_t ad_len, uint8_t *aead_data) {}
+
+static void chacha20_poly1305_seal(uint8_t *out_ciphertext,
+                                   const uint8_t *plaintext,
+                                   size_t plaintext_len, const uint8_t *ad,
+                                   size_t ad_len, uint8_t *aead_data) {}
+#endif
+
 static int aead_chacha20_poly1305_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
                                        size_t key_len, size_t tag_len) {
   struct aead_chacha20_poly1305_ctx *c20_ctx;
@@ -54,7 +101,7 @@
     return 0;
   }
 
-  memcpy(c20_ctx->key, key, key_len);
+  OPENSSL_memcpy(c20_ctx->key, key, key_len);
   c20_ctx->tag_len = tag_len;
   ctx->aead_state = c20_ctx;
 
@@ -69,9 +116,8 @@
 
 static void poly1305_update_length(poly1305_state *poly1305, size_t data_len) {
   uint8_t length_bytes[8];
-  unsigned i;
 
-  for (i = 0; i < sizeof(length_bytes); i++) {
+  for (unsigned i = 0; i < sizeof(length_bytes); i++) {
     length_bytes[i] = data_len;
     data_len >>= 8;
   }
@@ -79,50 +125,56 @@
   CRYPTO_poly1305_update(poly1305, length_bytes, sizeof(length_bytes));
 }
 
-#if defined(__arm__)
-#define ALIGNED __attribute__((aligned(16)))
-#else
-#define ALIGNED
-#endif
+static void poly1305_update_padded_16(poly1305_state *poly1305,
+                                      const uint8_t *data, size_t data_len) {
+  static const uint8_t padding[16] = { 0 }; /* Padding is all zeros. */
 
-typedef void (*aead_poly1305_update)(poly1305_state *ctx, const uint8_t *ad,
-                                     size_t ad_len, const uint8_t *ciphertext,
-                                     size_t ciphertext_len);
+  CRYPTO_poly1305_update(poly1305, data, data_len);
+  if (data_len % 16 != 0) {
+    CRYPTO_poly1305_update(poly1305, padding,
+                           sizeof(padding) - (data_len % 16));
+  }
+}
 
-/* aead_poly1305 fills |tag| with the authentication tag for the given
- * inputs, using |update| to control the order and format that the inputs are
- * signed/authenticated. */
-static void aead_poly1305(aead_poly1305_update update,
-                          uint8_t tag[POLY1305_TAG_LEN],
-                          const struct aead_chacha20_poly1305_ctx *c20_ctx,
-                          const uint8_t nonce[12], const uint8_t *ad,
-                          size_t ad_len, const uint8_t *ciphertext,
-                          size_t ciphertext_len) {
-  uint8_t poly1305_key[32] ALIGNED;
-  memset(poly1305_key, 0, sizeof(poly1305_key));
+/* calc_tag fills |tag| with the authentication tag for the given inputs. */
+static void calc_tag(uint8_t tag[POLY1305_TAG_LEN],
+                     const struct aead_chacha20_poly1305_ctx *c20_ctx,
+                     const uint8_t nonce[12], const uint8_t *ad, size_t ad_len,
+                     const uint8_t *ciphertext, size_t ciphertext_len) {
+  alignas(16) uint8_t poly1305_key[32];
+  OPENSSL_memset(poly1305_key, 0, sizeof(poly1305_key));
   CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key),
                    c20_ctx->key, nonce, 0);
+
   poly1305_state ctx;
   CRYPTO_poly1305_init(&ctx, poly1305_key);
-  update(&ctx, ad, ad_len, ciphertext, ciphertext_len);
+  poly1305_update_padded_16(&ctx, ad, ad_len);
+  poly1305_update_padded_16(&ctx, ciphertext, ciphertext_len);
+  poly1305_update_length(&ctx, ad_len);
+  poly1305_update_length(&ctx, ciphertext_len);
   CRYPTO_poly1305_finish(&ctx, tag);
 }
 
-static int seal_impl(aead_poly1305_update poly1305_update,
-                     const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len,
-                     size_t max_out_len, const uint8_t nonce[12],
-                     const uint8_t *in, size_t in_len, const uint8_t *ad,
-                     size_t ad_len) {
+static int aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
+                                       size_t *out_len, size_t max_out_len,
+                                       const uint8_t *nonce, size_t nonce_len,
+                                       const uint8_t *in, size_t in_len,
+                                       const uint8_t *ad, size_t ad_len) {
   const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
   const uint64_t in_len_64 = in_len;
 
+  if (nonce_len != 12) {
+    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
+    return 0;
+  }
+
   /* |CRYPTO_chacha_20| uses a 32-bit block counter. Therefore we disallow
    * individual operations that work on more than 256GB at a time.
    * |in_len_64| is needed because, on 32-bit platforms, size_t is only
    * 32-bits and this produces a warning because it's always false.
    * Casting to uint64_t inside the conditional is not sufficient to stop
    * the warning. */
-  if (in_len_64 >= (1ull << 32) * 64 - 64) {
+  if (in_len_64 >= (UINT64_C(1) << 32) * 64 - 64) {
     OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
     return 0;
   }
@@ -137,25 +189,37 @@
     return 0;
   }
 
-  CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, nonce, 1);
+  alignas(16) uint8_t tag[48];
 
-  uint8_t tag[POLY1305_TAG_LEN] ALIGNED;
-  aead_poly1305(poly1305_update, tag, c20_ctx, nonce, ad, ad_len, out, in_len);
+  if (asm_capable()) {
+    OPENSSL_memcpy(tag, c20_ctx->key, 32);
+    OPENSSL_memset(tag + 32, 0, 4);
+    OPENSSL_memcpy(tag + 32 + 4, nonce, 12);
+    chacha20_poly1305_seal(out, in, in_len, ad, ad_len, tag);
+  } else {
+    CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, nonce, 1);
+    calc_tag(tag, c20_ctx, nonce, ad, ad_len, out, in_len);
+  }
 
-  memcpy(out + in_len, tag, c20_ctx->tag_len);
+  OPENSSL_memcpy(out + in_len, tag, c20_ctx->tag_len);
   *out_len = in_len + c20_ctx->tag_len;
   return 1;
 }
 
-static int open_impl(aead_poly1305_update poly1305_update,
-                     const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len,
-                     size_t max_out_len, const uint8_t nonce[12],
-                     const uint8_t *in, size_t in_len, const uint8_t *ad,
-                     size_t ad_len) {
+static int aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
+                                       size_t *out_len, size_t max_out_len,
+                                       const uint8_t *nonce, size_t nonce_len,
+                                       const uint8_t *in, size_t in_len,
+                                       const uint8_t *ad, size_t ad_len) {
   const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
   size_t plaintext_len;
   const uint64_t in_len_64 = in_len;
 
+  if (nonce_len != 12) {
+    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
+    return 0;
+  }
+
   if (in_len < c20_ctx->tag_len) {
     OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
     return 0;
@@ -167,70 +231,33 @@
    * 32-bits and this produces a warning because it's always false.
    * Casting to uint64_t inside the conditional is not sufficient to stop
    * the warning. */
-  if (in_len_64 >= (1ull << 32) * 64 - 64) {
+  if (in_len_64 >= (UINT64_C(1) << 32) * 64 - 64) {
     OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
     return 0;
   }
 
   plaintext_len = in_len - c20_ctx->tag_len;
-  uint8_t tag[POLY1305_TAG_LEN] ALIGNED;
-  aead_poly1305(poly1305_update, tag, c20_ctx, nonce, ad, ad_len, in,
-                plaintext_len);
+  alignas(16) uint8_t tag[48];
+
+  if (asm_capable()) {
+    OPENSSL_memcpy(tag, c20_ctx->key, 32);
+    OPENSSL_memset(tag + 32, 0, 4);
+    OPENSSL_memcpy(tag + 32 + 4, nonce, 12);
+    chacha20_poly1305_open(out, in, plaintext_len, ad, ad_len, tag);
+  } else {
+    calc_tag(tag, c20_ctx, nonce, ad, ad_len, in, plaintext_len);
+    CRYPTO_chacha_20(out, in, plaintext_len, c20_ctx->key, nonce, 1);
+  }
+
   if (CRYPTO_memcmp(tag, in + plaintext_len, c20_ctx->tag_len) != 0) {
     OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
     return 0;
   }
 
-  CRYPTO_chacha_20(out, in, plaintext_len, c20_ctx->key, nonce, 1);
   *out_len = plaintext_len;
   return 1;
 }
 
-static void poly1305_update_padded_16(poly1305_state *poly1305,
-                                      const uint8_t *data, size_t data_len) {
-  static const uint8_t padding[16] = { 0 }; /* Padding is all zeros. */
-
-  CRYPTO_poly1305_update(poly1305, data, data_len);
-  if (data_len % 16 != 0) {
-    CRYPTO_poly1305_update(poly1305, padding, sizeof(padding) - (data_len % 16));
-  }
-}
-
-static void poly1305_update(poly1305_state *ctx, const uint8_t *ad,
-                            size_t ad_len, const uint8_t *ciphertext,
-                            size_t ciphertext_len) {
-  poly1305_update_padded_16(ctx, ad, ad_len);
-  poly1305_update_padded_16(ctx, ciphertext, ciphertext_len);
-  poly1305_update_length(ctx, ad_len);
-  poly1305_update_length(ctx, ciphertext_len);
-}
-
-static int aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
-                                       size_t *out_len, size_t max_out_len,
-                                       const uint8_t *nonce, size_t nonce_len,
-                                       const uint8_t *in, size_t in_len,
-                                       const uint8_t *ad, size_t ad_len) {
-  if (nonce_len != 12) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
-    return 0;
-  }
-  return seal_impl(poly1305_update, ctx, out, out_len, max_out_len, nonce, in,
-                   in_len, ad, ad_len);
-}
-
-static int aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
-                                       size_t *out_len, size_t max_out_len,
-                                       const uint8_t *nonce, size_t nonce_len,
-                                       const uint8_t *in, size_t in_len,
-                                       const uint8_t *ad, size_t ad_len) {
-  if (nonce_len != 12) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
-    return 0;
-  }
-  return open_impl(poly1305_update, ctx, out, out_len, max_out_len, nonce, in,
-                   in_len, ad, ad_len);
-}
-
 static const EVP_AEAD aead_chacha20_poly1305 = {
     32,                 /* key len */
     12,                 /* nonce len */
@@ -241,71 +268,9 @@
     aead_chacha20_poly1305_cleanup,
     aead_chacha20_poly1305_seal,
     aead_chacha20_poly1305_open,
-    NULL,               /* get_rc4_state */
     NULL,               /* get_iv */
 };
 
 const EVP_AEAD *EVP_aead_chacha20_poly1305(void) {
   return &aead_chacha20_poly1305;
 }
-
-const EVP_AEAD *EVP_aead_chacha20_poly1305_rfc7539(void) {
-  return EVP_aead_chacha20_poly1305();
-}
-
-static void poly1305_update_old(poly1305_state *ctx, const uint8_t *ad,
-                                size_t ad_len, const uint8_t *ciphertext,
-                                size_t ciphertext_len) {
-  CRYPTO_poly1305_update(ctx, ad, ad_len);
-  poly1305_update_length(ctx, ad_len);
-  CRYPTO_poly1305_update(ctx, ciphertext, ciphertext_len);
-  poly1305_update_length(ctx, ciphertext_len);
-}
-
-static int aead_chacha20_poly1305_old_seal(
-    const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len, size_t max_out_len,
-    const uint8_t *nonce, size_t nonce_len, const uint8_t *in, size_t in_len,
-    const uint8_t *ad, size_t ad_len) {
-  if (nonce_len != 8) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
-    return 0;
-  }
-  uint8_t nonce_96[12];
-  memset(nonce_96, 0, 4);
-  memcpy(nonce_96 + 4, nonce, 8);
-  return seal_impl(poly1305_update_old, ctx, out, out_len, max_out_len,
-                   nonce_96, in, in_len, ad, ad_len);
-}
-
-static int aead_chacha20_poly1305_old_open(
-    const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len, size_t max_out_len,
-    const uint8_t *nonce, size_t nonce_len, const uint8_t *in, size_t in_len,
-    const uint8_t *ad, size_t ad_len) {
-  if (nonce_len != 8) {
-    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
-    return 0;
-  }
-  uint8_t nonce_96[12];
-  memset(nonce_96, 0, 4);
-  memcpy(nonce_96 + 4, nonce, 8);
-  return open_impl(poly1305_update_old, ctx, out, out_len, max_out_len,
-                   nonce_96, in, in_len, ad, ad_len);
-}
-
-static const EVP_AEAD aead_chacha20_poly1305_old = {
-    32,                 /* key len */
-    8,                  /* nonce len */
-    POLY1305_TAG_LEN,   /* overhead */
-    POLY1305_TAG_LEN,   /* max tag length */
-    aead_chacha20_poly1305_init,
-    NULL, /* init_with_direction */
-    aead_chacha20_poly1305_cleanup,
-    aead_chacha20_poly1305_old_seal,
-    aead_chacha20_poly1305_old_open,
-    NULL,               /* get_rc4_state */
-    NULL,               /* get_iv */
-};
-
-const EVP_AEAD *EVP_aead_chacha20_poly1305_old(void) {
-  return &aead_chacha20_poly1305_old;
-}
diff --git a/src/crypto/cipher/e_des.c b/src/crypto/cipher/e_des.c
index b1d312c..6834a42 100644
--- a/src/crypto/cipher/e_des.c
+++ b/src/crypto/cipher/e_des.c
@@ -56,7 +56,7 @@
 
 #include <openssl/cipher.h>
 #include <openssl/des.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
 
 #include "internal.h"
 
@@ -104,8 +104,7 @@
   in_len -= ctx->cipher->block_size;
 
   EVP_DES_KEY *dat = (EVP_DES_KEY *) ctx->cipher_data;
-  size_t i;
-  for (i = 0; i <= in_len; i += ctx->cipher->block_size) {
+  for (size_t i = 0; i <= in_len; i += ctx->cipher->block_size) {
     DES_ecb_encrypt((DES_cblock *) (in + i), (DES_cblock *) (out + i),
                     &dat->ks.ks, ctx->encrypt);
   }
@@ -189,8 +188,7 @@
   in_len -= ctx->cipher->block_size;
 
   DES_EDE_KEY *dat = (DES_EDE_KEY *) ctx->cipher_data;
-  size_t i;
-  for (i = 0; i <= in_len; i += ctx->cipher->block_size) {
+  for (size_t i = 0; i <= in_len; i += ctx->cipher->block_size) {
     DES_ecb3_encrypt((DES_cblock *) (in + i), (DES_cblock *) (out + i),
                      &dat->ks.ks[0], &dat->ks.ks[1], &dat->ks.ks[2],
                      ctx->encrypt);
diff --git a/src/crypto/cipher/e_null.c b/src/crypto/cipher/e_null.c
index cfe1d1b..9f89308 100644
--- a/src/crypto/cipher/e_null.c
+++ b/src/crypto/cipher/e_null.c
@@ -58,8 +58,9 @@
 
 #include <string.h>
 
-#include <openssl/obj.h>
+#include <openssl/nid.h>
 
+#include "../internal.h"
 #include "internal.h"
 
 
@@ -71,7 +72,7 @@
 static int null_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out,
                        const uint8_t *in, size_t in_len) {
   if (in != out) {
-    memcpy(out, in, in_len);
+    OPENSSL_memcpy(out, in, in_len);
   }
   return 1;
 }
diff --git a/src/crypto/cipher/e_rc2.c b/src/crypto/cipher/e_rc2.c
index 8ca7bba..e1b4301 100644
--- a/src/crypto/cipher/e_rc2.c
+++ b/src/crypto/cipher/e_rc2.c
@@ -55,68 +55,73 @@
  * [including the GNU Public Licence.] */
 
 #include <openssl/cipher.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
 
 #include "internal.h"
 
 
-#define c2l(c, l)                                                           \
-  (l = ((uint32_t)(*((c)++))), l |= ((uint32_t)(*((c)++))) << 8L, \
-   l |= ((uint32_t)(*((c)++))) << 16L,                                 \
-   l |= ((uint32_t)(*((c)++))) << 24L)
+#define c2l(c, l)                         \
+  do {                                    \
+    (l) = ((uint32_t)(*((c)++)));         \
+    (l) |= ((uint32_t)(*((c)++))) << 8L;  \
+    (l) |= ((uint32_t)(*((c)++))) << 16L; \
+    (l) |= ((uint32_t)(*((c)++))) << 24L; \
+  } while (0)
 
-#define c2ln(c, l1, l2, n)                        \
-  {                                               \
-    c += n;                                       \
-    l1 = l2 = 0;                                  \
-    switch (n) {                                  \
-      case 8:                                     \
-        l2 = ((uint32_t)(*(--(c)))) << 24L;  \
-      case 7:                                     \
-        l2 |= ((uint32_t)(*(--(c)))) << 16L; \
-      case 6:                                     \
-        l2 |= ((uint32_t)(*(--(c)))) << 8L;  \
-      case 5:                                     \
-        l2 |= ((uint32_t)(*(--(c))));        \
-      case 4:                                     \
-        l1 = ((uint32_t)(*(--(c)))) << 24L;  \
-      case 3:                                     \
-        l1 |= ((uint32_t)(*(--(c)))) << 16L; \
-      case 2:                                     \
-        l1 |= ((uint32_t)(*(--(c)))) << 8L;  \
-      case 1:                                     \
-        l1 |= ((uint32_t)(*(--(c))));        \
-    }                                             \
-  }
+#define c2ln(c, l1, l2, n)                     \
+  do {                                         \
+    (c) += (n);                                \
+    (l1) = (l2) = 0;                           \
+    switch (n) {                               \
+      case 8:                                  \
+        (l2) = ((uint32_t)(*(--(c)))) << 24L;  \
+      case 7:                                  \
+        (l2) |= ((uint32_t)(*(--(c)))) << 16L; \
+      case 6:                                  \
+        (l2) |= ((uint32_t)(*(--(c)))) << 8L;  \
+      case 5:                                  \
+        (l2) |= ((uint32_t)(*(--(c))));        \
+      case 4:                                  \
+        (l1) = ((uint32_t)(*(--(c)))) << 24L;  \
+      case 3:                                  \
+        (l1) |= ((uint32_t)(*(--(c)))) << 16L; \
+      case 2:                                  \
+        (l1) |= ((uint32_t)(*(--(c)))) << 8L;  \
+      case 1:                                  \
+        (l1) |= ((uint32_t)(*(--(c))));        \
+    }                                          \
+  } while (0)
 
-#define l2c(l, c)                                   \
-  (*((c)++) = (uint8_t)(((l)) & 0xff),        \
-   *((c)++) = (uint8_t)(((l) >> 8L) & 0xff),  \
-   *((c)++) = (uint8_t)(((l) >> 16L) & 0xff), \
-   *((c)++) = (uint8_t)(((l) >> 24L) & 0xff))
+#define l2c(l, c)                              \
+  do {                                         \
+    *((c)++) = (uint8_t)(((l)) & 0xff);        \
+    *((c)++) = (uint8_t)(((l) >> 8L) & 0xff);  \
+    *((c)++) = (uint8_t)(((l) >> 16L) & 0xff); \
+    *((c)++) = (uint8_t)(((l) >> 24L) & 0xff); \
+  } while (0)
 
-#define l2cn(l1, l2, c, n)                                \
-  {                                                       \
-    c += n;                                               \
-    switch (n) {                                          \
-      case 8:                                             \
+#define l2cn(l1, l2, c, n)                          \
+  do {                                              \
+    (c) += (n);                                     \
+    switch (n) {                                    \
+      case 8:                                       \
         *(--(c)) = (uint8_t)(((l2) >> 24L) & 0xff); \
-      case 7:                                             \
+      case 7:                                       \
         *(--(c)) = (uint8_t)(((l2) >> 16L) & 0xff); \
-      case 6:                                             \
+      case 6:                                       \
         *(--(c)) = (uint8_t)(((l2) >> 8L) & 0xff);  \
-      case 5:                                             \
+      case 5:                                       \
         *(--(c)) = (uint8_t)(((l2)) & 0xff);        \
-      case 4:                                             \
+      case 4:                                       \
         *(--(c)) = (uint8_t)(((l1) >> 24L) & 0xff); \
-      case 3:                                             \
+      case 3:                                       \
         *(--(c)) = (uint8_t)(((l1) >> 16L) & 0xff); \
-      case 2:                                             \
+      case 2:                                       \
         *(--(c)) = (uint8_t)(((l1) >> 8L) & 0xff);  \
-      case 1:                                             \
+      case 1:                                       \
         *(--(c)) = (uint8_t)(((l1)) & 0xff);        \
-    }                                                     \
-  }
+    }                                               \
+  } while (0)
 
 typedef struct rc2_key_st { uint16_t data[64]; } RC2_KEY;
 
diff --git a/src/crypto/cipher/e_rc4.c b/src/crypto/cipher/e_rc4.c
index 3a2c166..e7c2cca 100644
--- a/src/crypto/cipher/e_rc4.c
+++ b/src/crypto/cipher/e_rc4.c
@@ -58,7 +58,7 @@
 #include <string.h>
 
 #include <openssl/cipher.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
 #include <openssl/rc4.h>
 
 
diff --git a/src/crypto/cipher/e_ssl3.c b/src/crypto/cipher/e_ssl3.c
index 7dddf24..f1dad2b 100644
--- a/src/crypto/cipher/e_ssl3.c
+++ b/src/crypto/cipher/e_ssl3.c
@@ -25,6 +25,7 @@
 #include <openssl/sha.h>
 
 #include "internal.h"
+#include "../internal.h"
 
 
 typedef struct {
@@ -49,7 +50,7 @@
 
   uint8_t pad[48];
   uint8_t tmp[EVP_MAX_MD_SIZE];
-  memset(pad, 0x36, pad_len);
+  OPENSSL_memset(pad, 0x36, pad_len);
   if (!EVP_MD_CTX_copy_ex(&md_ctx, &ssl3_ctx->md_ctx) ||
       !EVP_DigestUpdate(&md_ctx, pad, pad_len) ||
       !EVP_DigestUpdate(&md_ctx, ad, ad_len) ||
@@ -60,7 +61,7 @@
     return 0;
   }
 
-  memset(pad, 0x5c, pad_len);
+  OPENSSL_memset(pad, 0x5c, pad_len);
   if (!EVP_MD_CTX_copy_ex(&md_ctx, &ssl3_ctx->md_ctx) ||
       !EVP_DigestUpdate(&md_ctx, pad, pad_len) ||
       !EVP_DigestUpdate(&md_ctx, tmp, md_size) ||
@@ -97,8 +98,6 @@
   size_t mac_key_len = EVP_MD_size(md);
   size_t enc_key_len = EVP_CIPHER_key_length(cipher);
   assert(mac_key_len + enc_key_len + EVP_CIPHER_iv_length(cipher) == key_len);
-  /* Although EVP_rc4() is a variable-length cipher, the default key size is
-   * correct for SSL3. */
 
   AEAD_SSL3_CTX *ssl3_ctx = OPENSSL_malloc(sizeof(AEAD_SSL3_CTX));
   if (ssl3_ctx == NULL) {
@@ -190,7 +189,7 @@
     /* Compute padding and feed that into the cipher. */
     uint8_t padding[256];
     unsigned padding_len = block_size - ((in_len + mac_len) % block_size);
-    memset(padding, 0, padding_len - 1);
+    OPENSSL_memset(padding, 0, padding_len - 1);
     padding[padding_len - 1] = padding_len - 1;
     if (!EVP_EncryptUpdate(&ssl3_ctx->cipher_ctx, out + total, &len, padding,
                            (int)padding_len)) {
@@ -263,10 +262,10 @@
   total += len;
   assert(total == in_len);
 
-  /* Remove CBC padding and MAC. This would normally be timing-sensitive, but SSLv3 CBC
-   * ciphers are already broken. Support will be removed eventually.
+  /* Remove CBC padding and MAC. This would normally be timing-sensitive, but
+   * SSLv3 CBC ciphers are already broken. Support will be removed eventually.
    * https://www.openssl.org/~bodo/ssl-poodle.pdf */
-  unsigned data_len;
+  size_t data_len;
   if (EVP_CIPHER_CTX_mode(&ssl3_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE) {
     unsigned padding_length = out[total - 1];
     if (total < padding_length + 1 + mac_len) {
@@ -297,16 +296,6 @@
   return 1;
 }
 
-static int aead_ssl3_get_rc4_state(const EVP_AEAD_CTX *ctx, const RC4_KEY **out_key) {
-  AEAD_SSL3_CTX *ssl3_ctx = (AEAD_SSL3_CTX *)ctx->aead_state;
-  if (EVP_CIPHER_CTX_cipher(&ssl3_ctx->cipher_ctx) != EVP_rc4()) {
-    return 0;
-  }
-
-  *out_key = (RC4_KEY*) ssl3_ctx->cipher_ctx.cipher_data;
-  return 1;
-}
-
 static int aead_ssl3_get_iv(const EVP_AEAD_CTX *ctx, const uint8_t **out_iv,
                             size_t *out_iv_len) {
   AEAD_SSL3_CTX *ssl3_ctx = (AEAD_SSL3_CTX *)ctx->aead_state;
@@ -320,18 +309,6 @@
   return 1;
 }
 
-static int aead_rc4_md5_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
-                                  size_t key_len, size_t tag_len,
-                                  enum evp_aead_direction_t dir) {
-  return aead_ssl3_init(ctx, key, key_len, tag_len, dir, EVP_rc4(), EVP_md5());
-}
-
-static int aead_rc4_sha1_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
-                                   size_t key_len, size_t tag_len,
-                                   enum evp_aead_direction_t dir) {
-  return aead_ssl3_init(ctx, key, key_len, tag_len, dir, EVP_rc4(), EVP_sha1());
-}
-
 static int aead_aes_128_cbc_sha1_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
                                            size_t key_len, size_t tag_len,
                                            enum evp_aead_direction_t dir) {
@@ -360,34 +337,6 @@
                         EVP_sha1());
 }
 
-static const EVP_AEAD aead_rc4_md5_ssl3 = {
-    MD5_DIGEST_LENGTH + 16, /* key len (MD5 + RC4) */
-    0,                      /* nonce len */
-    MD5_DIGEST_LENGTH,      /* overhead */
-    MD5_DIGEST_LENGTH,      /* max tag length */
-    NULL, /* init */
-    aead_rc4_md5_ssl3_init,
-    aead_ssl3_cleanup,
-    aead_ssl3_seal,
-    aead_ssl3_open,
-    aead_ssl3_get_rc4_state,
-    NULL, /* get_iv */
-};
-
-static const EVP_AEAD aead_rc4_sha1_ssl3 = {
-    SHA_DIGEST_LENGTH + 16, /* key len (SHA1 + RC4) */
-    0,                      /* nonce len */
-    SHA_DIGEST_LENGTH,      /* overhead */
-    SHA_DIGEST_LENGTH,      /* max tag length */
-    NULL, /* init */
-    aead_rc4_sha1_ssl3_init,
-    aead_ssl3_cleanup,
-    aead_ssl3_seal,
-    aead_ssl3_open,
-    aead_ssl3_get_rc4_state,
-    NULL, /* get_iv */
-};
-
 static const EVP_AEAD aead_aes_128_cbc_sha1_ssl3 = {
     SHA_DIGEST_LENGTH + 16 + 16, /* key len (SHA1 + AES128 + IV) */
     0,                           /* nonce len */
@@ -398,7 +347,6 @@
     aead_ssl3_cleanup,
     aead_ssl3_seal,
     aead_ssl3_open,
-    NULL,                        /* get_rc4_state */
     aead_ssl3_get_iv,
 };
 
@@ -412,7 +360,6 @@
     aead_ssl3_cleanup,
     aead_ssl3_seal,
     aead_ssl3_open,
-    NULL,                        /* get_rc4_state */
     aead_ssl3_get_iv,
 };
 
@@ -426,7 +373,6 @@
     aead_ssl3_cleanup,
     aead_ssl3_seal,
     aead_ssl3_open,
-    NULL,                        /* get_rc4_state */
     aead_ssl3_get_iv,
 };
 
@@ -440,14 +386,9 @@
     aead_ssl3_cleanup,
     aead_ssl3_seal,
     aead_ssl3_open,
-    NULL,                       /* get_rc4_state */
     NULL,                       /* get_iv */
 };
 
-const EVP_AEAD *EVP_aead_rc4_md5_ssl3(void) { return &aead_rc4_md5_ssl3; }
-
-const EVP_AEAD *EVP_aead_rc4_sha1_ssl3(void) { return &aead_rc4_sha1_ssl3; }
-
 const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_ssl3(void) {
   return &aead_aes_128_cbc_sha1_ssl3;
 }
diff --git a/src/crypto/cipher/e_tls.c b/src/crypto/cipher/e_tls.c
index b87b0d6..7d9bbee 100644
--- a/src/crypto/cipher/e_tls.c
+++ b/src/crypto/cipher/e_tls.c
@@ -25,7 +25,7 @@
 #include <openssl/sha.h>
 #include <openssl/type_check.h>
 
-#include "../crypto/internal.h"
+#include "../internal.h"
 #include "internal.h"
 
 
@@ -71,8 +71,6 @@
   size_t enc_key_len = EVP_CIPHER_key_length(cipher);
   assert(mac_key_len + enc_key_len +
          (implicit_iv ? EVP_CIPHER_iv_length(cipher) : 0) == key_len);
-  /* Although EVP_rc4() is a variable-length cipher, the default key size is
-   * correct for TLS. */
 
   AEAD_TLS_CTX *tls_ctx = OPENSSL_malloc(sizeof(AEAD_TLS_CTX));
   if (tls_ctx == NULL) {
@@ -82,7 +80,7 @@
   EVP_CIPHER_CTX_init(&tls_ctx->cipher_ctx);
   HMAC_CTX_init(&tls_ctx->hmac_ctx);
   assert(mac_key_len <= EVP_MAX_MD_SIZE);
-  memcpy(tls_ctx->mac_key, key, mac_key_len);
+  OPENSSL_memcpy(tls_ctx->mac_key, key, mac_key_len);
   tls_ctx->mac_key_len = (uint8_t)mac_key_len;
   tls_ctx->implicit_iv = implicit_iv;
 
@@ -184,7 +182,7 @@
     /* Compute padding and feed that into the cipher. */
     uint8_t padding[256];
     unsigned padding_len = block_size - ((in_len + mac_len) % block_size);
-    memset(padding, padding_len - 1, padding_len);
+    OPENSSL_memset(padding, padding_len - 1, padding_len);
     if (!EVP_EncryptUpdate(&tls_ctx->cipher_ctx, out + total, &len, padding,
                            (int)padding_len)) {
       return 0;
@@ -264,35 +262,33 @@
 
   /* Remove CBC padding. Code from here on is timing-sensitive with respect to
    * |padding_ok| and |data_plus_mac_len| for CBC ciphers. */
-  int padding_ok;
-  unsigned data_plus_mac_len, data_len;
+  unsigned padding_ok, data_plus_mac_len;
   if (EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE) {
-    padding_ok = EVP_tls_cbc_remove_padding(
-        &data_plus_mac_len, out, total,
-        EVP_CIPHER_CTX_block_size(&tls_ctx->cipher_ctx),
-        (unsigned)HMAC_size(&tls_ctx->hmac_ctx));
-    /* Publicly invalid. This can be rejected in non-constant time. */
-    if (padding_ok == 0) {
+    if (!EVP_tls_cbc_remove_padding(
+            &padding_ok, &data_plus_mac_len, out, total,
+            EVP_CIPHER_CTX_block_size(&tls_ctx->cipher_ctx),
+            (unsigned)HMAC_size(&tls_ctx->hmac_ctx))) {
+      /* Publicly invalid. This can be rejected in non-constant time. */
       OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
       return 0;
     }
   } else {
-    padding_ok = 1;
+    padding_ok = ~0u;
     data_plus_mac_len = total;
     /* |data_plus_mac_len| = |total| = |in_len| at this point. |in_len| has
      * already been checked against the MAC size at the top of the function. */
     assert(data_plus_mac_len >= HMAC_size(&tls_ctx->hmac_ctx));
   }
-  data_len = data_plus_mac_len - HMAC_size(&tls_ctx->hmac_ctx);
+  unsigned data_len = data_plus_mac_len - HMAC_size(&tls_ctx->hmac_ctx);
 
-  /* At this point, |padding_ok| is 1 or -1. If 1, the padding is valid and the
-   * first |data_plus_mac_size| bytes after |out| are the plaintext and
-   * MAC. Either way, |data_plus_mac_size| is large enough to extract a MAC. */
+  /* At this point, if the padding is valid, the first |data_plus_mac_len| bytes
+   * after |out| are the plaintext and MAC. Otherwise, |data_plus_mac_len| is
+   * still large enough to extract a MAC, but it will be irrelevant. */
 
   /* To allow for CBC mode which changes cipher length, |ad| doesn't include the
    * length for legacy ciphers. */
   uint8_t ad_fixed[13];
-  memcpy(ad_fixed, ad, 11);
+  OPENSSL_memcpy(ad_fixed, ad, 11);
   ad_fixed[11] = (uint8_t)(data_len >> 8);
   ad_fixed[12] = (uint8_t)(data_len & 0xff);
   ad_len += 2;
@@ -338,7 +334,7 @@
    * EVP_tls_cbc_remove_padding. */
   unsigned good = constant_time_eq_int(CRYPTO_memcmp(record_mac, mac, mac_len),
                                        0);
-  good &= constant_time_eq_int(padding_ok, 1);
+  good &= padding_ok;
   if (!good) {
     OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
     return 0;
@@ -350,20 +346,6 @@
   return 1;
 }
 
-static int aead_rc4_md5_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
-                                 size_t key_len, size_t tag_len,
-                                 enum evp_aead_direction_t dir) {
-  return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_rc4(), EVP_md5(),
-                       0);
-}
-
-static int aead_rc4_sha1_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
-                                  size_t key_len, size_t tag_len,
-                                  enum evp_aead_direction_t dir) {
-  return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_rc4(), EVP_sha1(),
-                       0);
-}
-
 static int aead_aes_128_cbc_sha1_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
                                           size_t key_len, size_t tag_len,
                                           enum evp_aead_direction_t dir) {
@@ -431,17 +413,6 @@
                        EVP_sha1(), 1);
 }
 
-static int aead_rc4_tls_get_rc4_state(const EVP_AEAD_CTX *ctx,
-                                      const RC4_KEY **out_key) {
-  const AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX*) ctx->aead_state;
-  if (EVP_CIPHER_CTX_cipher(&tls_ctx->cipher_ctx) != EVP_rc4()) {
-    return 0;
-  }
-
-  *out_key = (const RC4_KEY*) tls_ctx->cipher_ctx.cipher_data;
-  return 1;
-}
-
 static int aead_tls_get_iv(const EVP_AEAD_CTX *ctx, const uint8_t **out_iv,
                            size_t *out_iv_len) {
   const AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX*) ctx->aead_state;
@@ -462,34 +433,6 @@
                        EVP_sha1(), 1 /* implicit iv */);
 }
 
-static const EVP_AEAD aead_rc4_md5_tls = {
-    MD5_DIGEST_LENGTH + 16, /* key len (MD5 + RC4) */
-    0,                      /* nonce len */
-    MD5_DIGEST_LENGTH,      /* overhead */
-    MD5_DIGEST_LENGTH,      /* max tag length */
-    NULL,                   /* init */
-    aead_rc4_md5_tls_init,
-    aead_tls_cleanup,
-    aead_tls_seal,
-    aead_tls_open,
-    aead_rc4_tls_get_rc4_state, /* get_rc4_state */
-    NULL,                       /* get_iv */
-};
-
-static const EVP_AEAD aead_rc4_sha1_tls = {
-    SHA_DIGEST_LENGTH + 16, /* key len (SHA1 + RC4) */
-    0,                      /* nonce len */
-    SHA_DIGEST_LENGTH,      /* overhead */
-    SHA_DIGEST_LENGTH,      /* max tag length */
-    NULL,                   /* init */
-    aead_rc4_sha1_tls_init,
-    aead_tls_cleanup,
-    aead_tls_seal,
-    aead_tls_open,
-    aead_rc4_tls_get_rc4_state, /* get_rc4_state */
-    NULL,                       /* get_iv */
-};
-
 static const EVP_AEAD aead_aes_128_cbc_sha1_tls = {
     SHA_DIGEST_LENGTH + 16, /* key len (SHA1 + AES128) */
     16,                     /* nonce len (IV) */
@@ -500,7 +443,6 @@
     aead_tls_cleanup,
     aead_tls_seal,
     aead_tls_open,
-    NULL,                   /* get_rc4_state */
     NULL,                   /* get_iv */
 };
 
@@ -514,7 +456,6 @@
     aead_tls_cleanup,
     aead_tls_seal,
     aead_tls_open,
-    NULL,                        /* get_rc4_state */
     aead_tls_get_iv,             /* get_iv */
 };
 
@@ -528,7 +469,6 @@
     aead_tls_cleanup,
     aead_tls_seal,
     aead_tls_open,
-    NULL,                      /* get_rc4_state */
     NULL,                      /* get_iv */
 };
 
@@ -542,7 +482,6 @@
     aead_tls_cleanup,
     aead_tls_seal,
     aead_tls_open,
-    NULL,                   /* get_rc4_state */
     NULL,                   /* get_iv */
 };
 
@@ -556,7 +495,6 @@
     aead_tls_cleanup,
     aead_tls_seal,
     aead_tls_open,
-    NULL,                        /* get_rc4_state */
     aead_tls_get_iv,             /* get_iv */
 };
 
@@ -570,7 +508,6 @@
     aead_tls_cleanup,
     aead_tls_seal,
     aead_tls_open,
-    NULL,                      /* get_rc4_state */
     NULL,                      /* get_iv */
 };
 
@@ -584,7 +521,6 @@
     aead_tls_cleanup,
     aead_tls_seal,
     aead_tls_open,
-    NULL,                      /* get_rc4_state */
     NULL,                      /* get_iv */
 };
 
@@ -598,7 +534,6 @@
     aead_tls_cleanup,
     aead_tls_seal,
     aead_tls_open,
-    NULL,                   /* get_rc4_state */
     NULL,                   /* get_iv */
 };
 
@@ -612,7 +547,6 @@
     aead_tls_cleanup,
     aead_tls_seal,
     aead_tls_open,
-    NULL,                       /* get_rc4_state */
     aead_tls_get_iv,            /* get_iv */
 };
 
@@ -626,14 +560,9 @@
     aead_tls_cleanup,
     aead_tls_seal,
     aead_tls_open,
-    NULL,                       /* get_rc4_state */
     NULL,                       /* get_iv */
 };
 
-const EVP_AEAD *EVP_aead_rc4_md5_tls(void) { return &aead_rc4_md5_tls; }
-
-const EVP_AEAD *EVP_aead_rc4_sha1_tls(void) { return &aead_rc4_sha1_tls; }
-
 const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_tls(void) {
   return &aead_aes_128_cbc_sha1_tls;
 }
diff --git a/src/crypto/cipher/internal.h b/src/crypto/cipher/internal.h
index 72ac118..d29ce59 100644
--- a/src/crypto/cipher/internal.h
+++ b/src/crypto/cipher/internal.h
@@ -95,8 +95,6 @@
               const uint8_t *in, size_t in_len, const uint8_t *ad,
               size_t ad_len);
 
-  int (*get_rc4_state)(const EVP_AEAD_CTX *ctx, const RC4_KEY **out_key);
-
   int (*get_iv)(const EVP_AEAD_CTX *ctx, const uint8_t **out_iv,
                 size_t *out_len);
 };
@@ -104,15 +102,15 @@
 
 /* EVP_tls_cbc_get_padding determines the padding from the decrypted, TLS, CBC
  * record in |in|. This decrypted record should not include any "decrypted"
- * explicit IV. It sets |*out_len| to the length with the padding removed or
- * |in_len| if invalid.
+ * explicit IV. If the record is publicly invalid, it returns zero. Otherwise,
+ * it returns one and sets |*out_padding_ok| to all ones (0xfff..f) if the
+ * padding is valid and zero otherwise. It then sets |*out_len| to the length
+ * with the padding removed or |in_len| if invalid.
  *
- * block_size: the block size of the cipher used to encrypt the record.
- * returns:
- *   0: (in non-constant time) if the record is publicly invalid.
- *   1: if the padding was valid
- *  -1: otherwise. */
-int EVP_tls_cbc_remove_padding(unsigned *out_len,
+ * If the function returns one, it runs in time independent of the contents of
+ * |in|. It is also guaranteed that |*out_len| >= |mac_size|, satisfying
+ * |EVP_tls_cbc_copy_mac|'s precondition. */
+int EVP_tls_cbc_remove_padding(unsigned *out_padding_ok, unsigned *out_len,
                                const uint8_t *in, unsigned in_len,
                                unsigned block_size, unsigned mac_size);
 
diff --git a/src/crypto/cipher/test/aes_128_cbc_sha1_ssl3_tests.txt b/src/crypto/cipher/test/aes_128_cbc_sha1_ssl3_tests.txt
index 5bc08f0..ab0c712 100644
--- a/src/crypto/cipher/test/aes_128_cbc_sha1_ssl3_tests.txt
+++ b/src/crypto/cipher/test/aes_128_cbc_sha1_ssl3_tests.txt
@@ -24,7 +24,7 @@
 IN: 936a91d0b5
 AD: d2c0267218cb7090c6
 CT: b7b9920735d05707f3640947
-TAG: f30968fda5d36eed80b2be5e31b53279d1ffabe8
+TAG: f30968fde881c9d54eb5146816cf46b6acc2efb8
 NO_SEAL: 01
 
 # Test with no padding.
@@ -38,6 +38,2589 @@
 NO_SEAL: 01
 FAILS: 01
 
+# Test with maximal padding.
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f6c5078d15ec447d297c5abf7d73f769e9f260ab3f4fbbc53f581d1
+TAG: 93452b062a09dc2c5fa375916a8f72169625ae00
+NO_SEAL: 01
+FAILS: 01
+
+# Test if the unpadded input is too short for a MAC, but not publicly so.
+# DIGEST: 095a8f557f75cba8e2452ddf97c053904b48827f
+KEY: 18cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1
+NONCE: 
+IN: 
+AD: 936a91d0b5d2c02672
+CT: fa2be56dc0df7c762dfed83a406eb6f2b4ed193aee583e4f71f00570b31afa048e699fe17bb40580b7adfea54bab1fe8fea8149eadb13fab2c45dcdff87b90e6d3dae8bae6712d34b12557b8da9b2a27b68e23a8da45506412100d107ab34af6f5b50705a24862447abe9f610c9ac62d77584da9c5f5bcbda5876345e19b9ff97aabd319812474742fb2cfc835fd4285f27a70be6d602ea3b0d7c3b8eabbe0fb3d309074bd46db51733aab23ac136da9747ec8145cf1ad8677894d2a417b6324b49844c8da51103ab0b0cee5c812248c6660e6a3d37ed27492f500255e57d19e697461ed9906ff50a81f981c
+TAG: 0476ce3207a0fa1308b1c70560ae243a143ecfd6
+NO_SEAL: 01
+FAILS: 01
+
+# Test that each byte of incorrect padding is noticed.
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b44059ab8aa3e5156b8f7cbb74b29419a6a5018e939c8f13ab27b91d33f0197470e8b36af42b60276b5dbc57834d3304d422f8b134b00a4cc732b42ce3147c306a047fd4fee78d16d88b04336293e00c1c2e2da501141c5f419407732967a7b210f2c66c75b4eb72e8a82d50b7b61776fc5fa4f34bcae2a72d5919b798d9997ca02127d98be95c809e686bc49f0633156ad3d4601626ba4d5e327474c52d0de00666bd9a4504de3e94eef168752e9c1834dea1d0470e9b8b39dddb258e773a4d7baaef0701db1bfb06d3757060f1fb6581a3766a2f4a44f45fa9f4494c884fd7234a2e3f32afae93acfadc4b023e6
+TAG: 97f8194b0d7fbf945c58cf1a1546058f856c4beb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b440528b55c9ca984344de8ae7b64c6a6b24be05c31b0c6715b9416efa10e5f8776ed4b3ce463d7c8387a7aac52256db1eaf618c6ff76cf703b989a129acfd45b3ad866a3cfe6f2c302a11ca0745507d7daffb88e6f3cd404e12d387c618d01e93ec64389d246f4ab9c58af3e843e3d9711463fee424749f0389b6eea54fc67bc45189e72c3d09679f948d14d8d43daf1040f56872eced0ced75349accab6bafcb80e2b46730e7c93c1c5f671b873c3fdf3ae90613d6a8476cda1bccfbcc3e56b909c3a98c309cf19746ab024c0b275c605e3d86657c60939b6f62d5561f88f69b60e4080c38ea23954b953e283c8
+TAG: 03bd1b443d9e363fb5b2cc9a0a80a2b761b4cc17
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a65bd6b200cd7cda719e9d3e4b2b9b6520ef88d37daa2c0dd66a99d4eaaee5b6061a8c7eb7da2ebeaca47108731e6cb30fb03150a14f3667c2afe6c049fc5cf6022987c0a2ae424989bd2507d72ce90df07a0b5ee00209aa7551eee2d437dc7e05333c2c77f78ea6ea9367c79fbf3396800c7539aff86d9f29ad471a35deb01632139d0fa9629991743ab1c5514d9d103a365836d7feb7fcde55c856591112271be7579403bfe8ef8d808e8a431553761120f73eec23227fb18fc780bcffa8908361df1775755246f43417e4f6a19d89a1c7d316f6324375049668be186685ed6db1f138a7a215a4a1503b93
+TAG: d4b6f3d13ca630f45e13d22e66814844d4c3866a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405fe614ec9384990f063f5a8dc1fd3b514ccdb0cdc63487e235cdaae7e40d064725c86c24f47ceee6972c58148c17db5c6c5b4a734ff461cf4df1f5e18bf6b7c19796c0b819d4d77bd228ce7d105a0b9c77738fbf94c014f2f1b97863e078e7b8709fc0c86eb84be437d2179d43567e10a1b87801cf19eaa0296741ff57220e4a0d162e95d0549525cbe6a419cbf3888b27e622d9213f3d7dbbb4a40841c478959fb9e5abb70e467ad7a8a00ecdf60157c019db7ac68eb5e3c0ec7c546c4a563dc5a135b5a369e7a5765f19858fde8ec6fc0e45d04fbf5fbdb8de2962c9736431b57b2e60f2e34809abf728105
+TAG: e05ffc34cf6f20c8868f8491187f6de7388a2c92
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b44054c5cbf6226f2412877f36f9f9384c25ca623a7ab157850ada336fb6ae6afdec486c0a3efad909edb319e2650b06c7b9641afe23d5d891b98ea95c8f0c7f122bdb48437817f9c4b2e2711e8736262d2b012a8bd5484ff3028a0d32cd15dbe2de2507cdbae4fe8effbfcfc184c0e744960d296ee51220ea40584d5651d93768b73afa7a41dd337a235a394ebdc426d77f6a80d1c630ebbb627463b9c2f836e8ebf84371cb97b87f4799cd58ac402d83962a35dc11a89f58b352cccd527eb228e390a0315a9a82357559b82d540d0bf9e83891ec3b1838f1cb365ac99b03f032cbd4fa0e32997ce5945dd33231e
+TAG: d12b317de2a34a6d75a2fa1c52719260f57c1284
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405c5adabdb5718284a9f74add24b28b71bd2be74f55b0478e88c3630a0d2451ad7fa46d248f8f307931e6d93590027afd0958c4b279355773ddb9f60984704b05dc00bb1ce597d472e9782078cb8904c9b5b046c855bafadf3b5dca41890a165fbe815e66ef0e845bacfbbf753b6c4b8dadc7f15b9552002cf743f229df3f82291fcd0c96e9da43f1603f19663944b052c859e4fa307b05a24778b2935b09a1a9606c131434158aa8c52e49c011094017d77690179270b0ae0cdf2f4ba35e353bb2b3d926b4c16614201eeed3898cb90598502cddaf9ea12c68d2089412c918a1ab0d4a86cbe2a7fa6e299d22a
+TAG: ec38f013d811a669809d02693e3e31aee0d9a894
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405dbd8cb2ec2e530ad5cf6077a53394099df2c39d459e96c225f898df8bbea407eb81d8fdc979775166ec5779829a4249efa68c9c7cee91f6fff1ae756a19ff878e50df724bc8b9d1da86ef33e5e1da2a610a9495b6bf654a8403e06ee2675d19d9d375d2fe879af48d01298d6cc569d702bc9dbd806a0937534bb7bb580f0a76a12ad48e9b77e4f67521ce1d594dd161e682a1fe25e1e9889f82f6cbbe8b576fe255dbf736030c7f085b7837d9becf9ef823fc258735377fe07ee47b6cd748a33a5f9114b52caea0301a85d2cb52e96d7e029fc6aa55bd8d22672afbce748eec047619a6ac6cd2f43cc22ffac
+TAG: 7dc1dbc987f07ee9846492653fda080ec8d1d173
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b440500c0f36b6d8a37fbc14c254cafaaa00e75cfdac41352ec264fae0ee45c3ee0c9ba83da44cd92109d7af2d574b341e23354b57e34bfd646af1183e12e9e8656a47a400c76d1575afe30184f32e746310eb7fa4b2e30bab2c80a981777491bddf73a5d4c5ca2b1ebbf4d40a09895680670b55e6da61b038bde5d129436f41b85a0fa0c987037efd743614a2c71d071b1de6cd39d9cf7df9ebb7ed266e759d18e97069e2b102e1d6dabdf162d3db2234242146f0f744647f17afeea5c460707860112330893cdd97d55df64527c7f18f8546fd2376aa0cda9f93d7da7f175ac8b19b84a62025a0622b21e4177e4
+TAG: 119cd36fc31bd6382d5ee89b74631513bcbdf82b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405394fa3397a0a192c65adab5d01c4c5ea5ba598a5b75f972937a6cdcdb3be2b07e8c14bc422c2eef509e0d4121db73a92b63864b5aff247df5a3d853e66b09f9b67d15cded1cf3f5f1cad992ae87a668797f54d0b4e265f7743a68cf9d75054140068e0bf023863a3a33cc0fb88e1b9dd5e062b078eec937d9eac9916c599be78312e010685a2c2504f962ed233c8b6e3134b97769bc292babffbe821b62966940f76f13e95f65d544bc949c217454ef7fdf465fe6efbe14dfe58148048fd06d1624e03eaa0c31878b6cb56ee380db1a145a17a6a40716db5a4ac5b7b5dad6501012254592b3d650391109bc4
+TAG: f8fef49479b75d9ccfb07c00688d2042804f62fa
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405588634d0ccde646710ffcfb5a68e095bf8b9a19df1711525261a511b435b312dc1971c25eb22605e23b35d334d061579d71f1513e1584740795d06a1df5fc9386ea690d2d206455dcc179af8a265af71bad1872f1df636f900974b6fc637857bbb8f4e91105770cdd77962087f98f29f6c9f6ef8672f8ddf6fa56a06bc9d11ae8daf30ae2ab92ff6e189440ac543d88be2b3a1fb91b88e3db15c2db578625dbf425b177bdd2c2e868b760d9941f361ac48495da288e8f5bee74d98b973878429bdffc97f437e9f00587051c87314c1df4f3ba3f0412f24e66a0e1077f9e28c637938b8907b5347a3ab869935
+TAG: 01cf2c3ea5aaeda2ca4f3961e28089876f7e1fc8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b440544ff11a1bc6957282908577c4cf0fe508c513742198191ff8e715d42ce7df4556865ccf2fe61519fb847c2176b727ca185abf66fd5889bccdbb7149de586b78bfc64b927ce04c639f18d51b4c7cdee45bf89b3632c3e18a077dafe5651838e8c6220e33fe4158a696e79797303443e2c842f0c58e34a6afb73a689fefff18fce4c9b66dd7430d604b8dab55a4b642613efbde5254da90e74f87617a9b2aeae285b06e24b812c45bba019c05ae8602c655ee3ef2050370e53b06bfd876ff951571dbf2dc92fb93451c721113395c96afb577b8bbe06b79f91e8089142f34f75099f10b89363e99b12d44b08ef
+TAG: e13fc039d3b8def7a5cd865b5674c129c2022957
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b44057a2ea3da57f9121c843537e85e3e817babf706774da962a7187445a82fa1c5220bfa267a702433ce8fa9515ea599d4071c6ec5de01cceece43b53afef0b39eaaf1d54a11610457a5037199e4aa670474ea2d5be0cf159db9da272feefcfb5b8509fd47289010495876af6cbdc3582b5bf4d348885e83c53423a5943fa895727f108502d3f1661496767751a59a0673cc723b9b7083472d82399e29b4005cb181ea669f9cb3b6f8fc0068134b31d9da671f3f366dbdc7cbebd62202822221c4b6a796c91cd502b7d47c40b8cc4f723b644b6c52b8769b54bf465580cf50544a9805847e6ca6d761e3c19f2d2a
+TAG: 00ca0ed1ebeee533ee97c97097cd91754668272e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405b3fab2b484e3030b020b9880b73f3c2dd1f994e3ce360ef5a8ba8456380acbbeb3137ef96ce6407b910d82c32feb16560abdb40cd7e237d912116b2fa9aff20abb95e8242e7feb8f501739a3a482004cb4e66423cf97b9cffc9821766bee7c88e124832f1a3e240d0e1892fb7565875bd967afc60717d93048a9292d67c1129e2c087a0f8f82344e55e819ae28ca5f04cacfae89f58be1bed7ce320c97ca6d17a71ff1713e6e58aa3aceb2f8ee1a884d37a1cc84f43cea2ac4afbf24002c1386b08a2c8a6f9758bdcdab8405c4503aa454672f5beeace6d2dfeeabbd23b2f445758aea3f1ef8b374573b71ab
+TAG: 08bbd21603906e638231d93c4b7054d601bbe320
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b44050bbd42de2d8a1a7a7cddb30ac583543bdda8ed409b6fec1ba536c34c7154e5d982d3127555ed9d68e463a08741013008900282875c30e60eafd2f79adf95fa5aa2cc13054600c606a5b9836eca38be106edb41337a75d8a35113bb0d9dfbf57bce555caa42a6a2fdda3e9e2617a5c5d460aefe3bcf6452a8da40df20cad5b4a3eb55f9c7b823483a80aa17552a619223683a147329da73ffc0b00ab7cd09b4a3dc81dc0ac6bd01909564c76328654e5a34819330d1d77e18231b4e12afab6e88c8ecf21c3ed03461af606012f0c4a42e93af15afc253bc2d44eb26c238d438f0b4e42b9cdc0781d2c9885f09
+TAG: e005ca93a04256c454beae74f70e01f3d817bb4e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405517989b9ea5b5a461d7b5c6274788478d01081c30d3d9cc63abcd04e6c355a7cf7a66f661aa26f644ad96f3ea471b24852de8b28fa4d4e27722f77554eba2905bd8a03ed842be90099e3bad76b265c52141d89ee967f1ccca4b752805445025ec3a5b1c9f1b722c74f7bc1fb4113aab1ebd1e351c1634217c771bdaa861b9eb69678de05ae93249e5c65f1aa75708d89a5e946fbe1b8182299ed55d0ab3bcb274d8533bd453210aea39586af40610fbb966b85f973a58c9c9e50a778894ac0c69888d5ddde126abca1ba572542493d9ded8a93e3cb73352ffaf8465d71bbdf16d431065492733921d9f9816e
+TAG: 167286520a6cb22d0cb0df3f3af81d92726a0d29
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b44050f07acf7d53d48b87a19e15d43120003c4f3fee04b5b6574ff91944bc8d9545b772ac8ebbbf0024dc57fe10eb9311a979fc02eab9e34f94756f2ba8d617a3b70846f1f3bad4f42e016ebb3659be952c113b8724f17f6e90a111537216a9ebfef242b0d9780c6afe009d651fec478e3fee84f373fd128396e2d2c3ffea74cb47e92d972a44edfbd079a337ecba725fcbfe37e13411dc46c73a65b7f2ca20f5ede212645d3c80c5461d37c6610790a419904872077db5ec7c8a476f0b0d1468fd004f9bb3002b322c5b828952fc6ee17ce228417e8fcbb91412656cc5a5d3c2ce26bd1d264a396d8897f67c221
+TAG: 795e2827f0da3e1c120550906dee0a5377892e15
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4763b4f90ba67220fcabaf6d6801ba5a6bd2e4d0c3f9df0f7b3aac0adc6533504ebdd8fbcf13f12dd103210ebf866ea9a7bb1f43836b837cd1dd41efb678695f65924ee703e1ee59a2d5a155e49546214ee11347d2576b289f878a85008acb69f6bdff2f07706cefcc1fd3610d613483caee1eeccdf5ec29bf70dbe1cbf586f1783b24743bbb4ced4b70f6e3f7665a8227c9ca3eab2e9490f83dc143298dfdef15c9815c593aac5f4ff5f9a92bd3a35456688b1215013a3844f5eaf99d0e0187b5a28e26ab2c8036474b74ef0ece3342483688520529174570017132a
+TAG: 2e2c5253c305c838e07ba57b46e911571148f37d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4afe319f681ebd78e958d6c54f7cbbb8bdedd7fe971c9635eaa3a21139bed9b17d85b6e38cf99328489c226d243707e7d6100b2216c59b39f60a276eb67fb0bb52dd70275204e477182aa73bcf532f61b72a79a5d995e587e0f53b8b994544d8b8581a515bf04e424a097218eab42698b30097244cfe9644e63c64b0cd8dc2aafc67a24798930a3234c358fa8013daad10538df1e990859799efe466f374436dde84fde95e7dad4381df4f0d95ef15db23061906aa62ac77c3a82fe91ffb8aa61cf57971f0e3ca3a2b87987683fcfd818db9ce4dcbd9d1e53d81deabf
+TAG: f7e0f79f79e513982b85f52322521a96311696d6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b48621f13f52dae06d73f898d2aa6d7d7d93d648224a9c74ebf9b9faa1b3647bdb73ec3abe12d714dc6ff5e92bab71f3cc83cf7ee7ec6c2c98bbc1bb78879abee9f867b95daca2a8c17809758043fb0b7aaf8fd1daca4c49fe57311739952935bc6497f5d870324a82b38b33b79a721afd9c4225fcf0b23333c6786952c8f205253f5f3d9a240883d0ccbab2509a50a1ac93bf9215f7653ff0084501f973f209594ca87089308f840222d312d8dd0015ec20cbd8b47145b3e9c10b975d1c3cab8ad05a8c46c8182b142251e6b83e69d237765688fd462bb83d58b431ef
+TAG: e7da1bb852889b5d599c2a4569e33b879291a672
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b44c2a2cafdcc197def77f6ab18d6e3b765a26934e79c0be2d9505a2a53267cd93717917f5d8b37d4072f80365d631c0aa6530c2f631256e0e7dbc0b081a7b755e0a0f7e27edd0a73978cac998485544a49c9c100253975cbe1a25b8267f7508219f4194dfcaf360318e8ede6a01889cbf82d4a949a10556ecbb0ecae69bf3756e4dfe197a311e8b45ad0e3874c790d83ad5811dee7bcb59a6151d65893592a8cdfaed3018475052e77f0fa0d65f3884cfd6d95d736bcfb95361faebf5f9ea0922107a2d90b3e459c7754cb1aaa0880c05dfff27d9d7176033049ecc9b
+TAG: b9c63c17a85d27b0708dca5f69c5cda073f1cee5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4c5c1b819ae9a6034775292ac443aaed052f2045a42dc6e620f7d58e0d5841e570bc3933b59de96c2373d1ff9df0b79ba7ef738c622d34ccb8fa599790cb813ef379895054b9854215b498665347e2f4f6e31ff1c72b5fb99844c34a0738b2ec8bd4e4b7d0e8ae5bf2daa49aa2e66cf5706072f0fc0942deea876861b82b656148a89ee8670623300d479be2e12d0bca03021ea48064f908ce4d0d8066d0ef43356678dc64f4f832c3ff23f86f3fa047a1dc78b2fff5737b31250c21fe13446e4dc50e4b5970af142ce62c7865fd7b0022347e4a088d8e95f1a9b261d
+TAG: d4317b5e479e6969d075fd0ef955b13535b26a32
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b454d268a4f22ea1ae961c4d518d2410f8dd24ff997129cc907cc0f0babc12fcceddf55b094272d0a6649a4013cade27853b9c4103dec90ef40f758d1b52a62ec54786e50b0734b5842209208e7338960a655ec7c54e8f5a32372028e5a3f30df1a096c28a4c21fd350217fd4b9b729dd7eed57d95beecb5e98fbacb5338742f28410aabc3e6c46ab0191ee7d5516fcd2da0066a4a9b596a09e558349a81dae20b404d612e200d1ed6f6f617d93f1b4c42f64f72ac14763bf0f594e9439d4c19de165ca5b1cb687d612a7411720ce685c504c05b12ba87fd42641959f8
+TAG: ee763f035a1657ed3b54fbed7ff083166ed10419
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b48a39abf67fd14223f9105f7703dc582e509b3b8917d7880f0b8a319efcbe877da7b23ec6ebe6084a2480d37f72ff81333f3f4dc53d3374d3e4777f32517f5464951fca1738fa9fdb4cabb53477dd5163029ec229bbc7936d75672fd7bd8dcddeaa1703c058a34cab5655c317633eef6cb28f38be63393089fba7d8c3ada7865baeec87ecbbe5874d3d1cdf6b5a19d5d0760fb5dded56013f425ec994317cac79eb061e8d303b3730e679f8bb3e13e96076c27a9484ca6d0e261e7dbe03374d01db054b87a29552b9e768e365d7ba70ba3464ca3918f8fef11814824b
+TAG: 8b9f42b5dcdf4de647a62dfb1bcfe39b75511690
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b485264b2714f233b97bf89c0dcc5a44eccba32f951f357a599f03c5998480d697dfd6841296a01f2a50c970ece9515501a243f6ef50f82620bcb16d77eea8904bb7137f6ca703f43dbe7f78ff00ed22a335286170d8e84ef1e6eaa802e6d5c619f38467f083c9e1ea1376b271ac0c700eb373b9060f29ba729f69caa8bcb41e237c639b83868ce6cdf06de560c495915306e457c311c1a4ecc9a566e5db2b1520d2a421bbd115b7193e48f8882291f00ba85248175cc0a4951f3d6a844d4b5cbf08e246822ab61339eb4b42fc48ce40a9f54f59aa4e29348d695bfcac
+TAG: fdb66369e7b13ac9b97b4b706893f177b64c1044
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b408b9f50b305a5882d37ed71c5810f3843a34dd792ae9217864c8ec5b076e4c1e7277d6fb27da2cbd4f76607dc7409f77d273d5cc963ff2964c35a768baefb327bdbc3b5236168bd49b70f63d13f847f7ae53a36f16c49da5064fe66019063cc7fad687365433bf1812c402580f83188cc3477a1e009610a19995541a08df3711f43e4de87fb1c07b61a0fe894c99d5770847089ed2ed63cfd8426f014ea75ee4bec92824234e4628cdafc1fa7bf7852fb265f83fafe618d35359b6fd33ffc0b14ddd5e084db7f4aa20685b1b42e08e307c5b9beaa133e94bfa4a2374
+TAG: 3977a3018de0605682d6eaa0eee7429ff127531f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4104aaad4e1877fda5f3568d80ebf2724238e3061188e96b05d46c92b54c919d7f9cd68fd8d4f19f6f2e2433263cd39322d83b5c35e7961d1d473521c4bd0dee158861d7c2c033a609c40525409e350e38c118db2129668486d2a27067c0cf60f3ae623011d566aaba115e4646423ea18a5e28f20921a0938ae27cec9081fa9d3ff79b6b891669d758a66810774b39ce55228982e815920dee1a9d9246f9a6bf84833560a581338eefc75074da66c98b39cfeadd80e5bc93f52540cbab976a54e6c1a0c0f91434cb54dd5a13e957be26fbbf3032e27ae470e52f3c6da
+TAG: 07466706148415691dad511a3ef2789b07916125
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4a325d09ff66928b41ff9f5776efc3a9e91423a8af2e6eb2a8f01d701b6a2234b62cd1f75cfdbda95e8d7c260a5fde85cb37531c3dd069bf3e7645a33c5f3e15f0a951fa8a82ee9cbffe1ba362dd30d08c226a4e47174665f2f78ac22ffec17447245eee5f33bb5d7865dd3a98ddc5af7bf69a31d8b2b8dfbfe4d701a185aa9344ff736b0ca0d55673914757511799bf9f7ac67be247fdab2286272b897dd2e4c0ded56ebb487a9acaccdb877bb7dedbea9b22ef9098c89943611c2e8012ee48edf2919151c17101432642e1bc4927e84a852ee0bba9edf6c8c35af0b
+TAG: 569183c642eae1bdfe25610f944e96292045cd01
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4ba5750e323c6ae71fe6ef97bbc42c53e7fd2a56cb0dfac0129d0ccb01b6f8b4c6e37463721c9b5406ed23e6a889208fc7b969809e48274b65fb926c621b45f4fffbc07a99929613ff5e1bb7de22682560e8467e47049d110fd408385aa0022f4d5e35517ede1d9fb05bff943538bb5fa23dd525d9541cbf779c33cf8939f0492fb6220f2e163c12adb9d59576fe9991ebceee1d65bd06d3725c57382297851132054efeb1d3642d92db1303cf6874f17e1bf48bbf974a1b21af5ed348420887335ac876839a4a568985c7c0fb98e293713fdffe8e9aa48b8aea26851
+TAG: 2b2edf7ea56972807d52c4000b7d63095b9fb38c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4fc6a362761c0379decec859071b4b8eebcf586d5cb1da98f7b4adc54261c13ba1da34343b7fdfe6ce7efea782b6ea65ea36d772e40606210330c88ceaafce083c526506ad37c4ad6afb9594ede8c5476fd6ffdc6ffefd5bc573e69ed67c7393b015e0fb9aa472ddd267ce288bc79c6a749e56d411b2bc9f3b9cbb319475534112e63d07928e9274d386424c3134f672fac726b74758898cda62dbf528e0ab827d850b4e4c4594be33a4ba5bb2cb3ea7a7abacf929822a24db599b2222e185dd48a7b675095ee1bfbc8a19838e61d70cc370e7f2f3b6c99f0c337d903
+TAG: c8d4e9e044b923cb2a7e641f9be5c08c285039df
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b441845bf36ef9f3092999918820de98a4fda9ed0f4b88d755bd676a279f78acc783f1a19d126bade45c45275d2d02f12b5e52e50005dc09642d060638f52b493a37d2e749bf0d00a16446c152b94caabea0d548354f8ce0d5a92f59c6d7a7c6c259e0f6a5b530c5692c00616279b1bc91de590a9353f6eaca6c0014580b413316568e0ce0c560e517510d721b2d33b5f73091618611dd2b3d17b2be8f4beb0c2f44af91c62749ad94e06762a0d4f04078a96c7f7385872afdafba8c022d78b4b37f1088f8f837f1be9c4fe8aa4fa79c100d8cc0b2b6000f5bafe73ea1
+TAG: 3891bc7e83398b0a46dc1ee6be0bf59f93bee358
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b498e3a68fb60993235a9ed7ca0fb88c02554f32422580f68e39e38809ef4700b852c27a30588b77a0b812f27291915d77bd40bba5c55fe71479a6f0284343ff78056b45bdff98c188555f177271e1e8f371a9ce925ceaa03d9fe082a0ed6b42fbcefae403014c932bed237e740f6b0c7e0021f11451fcc4a8a589020bf193943a4119c227b1384dca1584f9dec0845e5df7c1ee13ce487f6c28f166ccf9439e8ca223e2ecc7c62c5ad23908ad616c4f0024da66c411db01b2ab17a2da53503493ec687548a3a750114a029f9735097a265617ff364e434414f606cea0
+TAG: 78d672537570d4b8e242a9e5e4917b5fd39871ed
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4302e4c88afa000bf15df15eec881187fdb849791468f81fc15a9783f8f512f6c2528fced8c80865efe2d91872ff42e624af24b2ece3299bdbeec7a389511b54e4db98054d3b4299be114153e2274a5f8c18be8334b456d941aa378b346efa15b25497a0b96fb577c354ab0613696b262febe776259cc47a95466c2dc948fecbffb0b29bc4d313046aa43c93708598f571e515a4970f5cd6f039e7b9d2cd644fa177233518025a9ab05036786bb7e7be848f2151d278137708d4e0ae989f808516f8bf12f0c44ca3bd5bfef0ee1ea78ab310ddb93584cff7388ad19b8
+TAG: 551fdae78357a7cd45ab2642ac50bdaa4d7ab755
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a567b5d1bebc1e6d956540fec77754e2272f5c4473f62ece29f453b6ab8292ac8932293f105051e7092aeb21ae259d6cf4add013c29d185ee5412f42878354b1e7087577fc4d82bdc65a0d540a815caf09904f7b2382badf2144e222e0adb11ee07ecfb17d518c71a8bd89578e8181cb04d77243d1958b7c83f557db46f22edd9d8a4e4f51823885e55720b75d60b7ff5e9780f25fc401b5658d4e7fac22c4f0013277e26bedd6fadb1e479c2b20aecd74381a0053940a741b72209256970d917c159932be47900e41ad2c112069
+TAG: 9958906ba66dc7cf740a78cf8d1e59ff2e8a9d74
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a5671cc49efffef621516a50f91e92a3b850ee55936ec11d3929db4f671c599b2e02c46c92331315d1ae08e745c37ffa202754c5939971730abf232157b1b2a1bac8ffcd329a4a00ad3b8b3bed238c9bee9282c686191e06d08ec57ec35406d5acaee18840b51b984a457712ab3e900fdcdf30ba294ea20073a166a76421760df008a7fe3755768ada997b8e9f09032b101aa5f4b66cf625b4058a835b6ddc9bda4fc49e43951eceb425ec1791672b5f3cd36b4013f2d20c363ace676f6ec26695e3c30896ae5983ab34bcdbcbfa
+TAG: dbd3d6a505cd1d061e9479d5319ba5fcd12e4838
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a5678150abea32a7e8c90291e661fab690d8377921b5950b7f578a697a129c9e604f9c750b1c27ecce9281d75946c41bc54b8402e329cf6b00d1b200d0d3df6cf6886cfd22c9b8167ce67eadeab063f2170b4d4095d141f38ebb457a3c9b47e3a509575a9facc3f5949f9677fb12fbe91848361068fe99dbbc0774460b371146653df7b281e7916b6198f28da1ec5a710aec912443c52fe6564d93c78dc9b646cfb15c39379e3b13c659d83c9793e3657b18ae553df67d3690af71471b28257176fb1a3b55c9d8a56adc4c357fc8
+TAG: 825aa769c98d28eb16879f42e602098e0b740c5d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56729d5cc49bc9b9428789561069ffb9721914bba318ea78ad1c357c0260d3e974f09daa1c90620b36776d41e430881a465678c982d77db8fe103d069368cfd52da506f18161f3ab84a641deeb2b7cde41405cd4e561c30fd9c04edef48f8b1758e933ccba613afc701be507da1903233fdf8fe879cecaa41a5a380f668dfb798d07b8a9f88bb64c22cc92b7228b1ece6c2985d3fa0cfc52f5cfdced0c8fd698a34ab34d3b5e2fea752aac6243ede85b56e9dafd91ad8fb0ec33f2da6e8873f3d8b97b638c48a5e040b3b1ba41e
+TAG: f75c4ffa94a43b5b7c91bcdbf76c24c298f3450c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a5671f2f3e2ce71369acb992eda87891719ebed083ff7dc1470a152b7481f385620b15aea431af64f554ed01a52c704548f24e1942bc4f87dfc27881ca62ea5e60eb57032626316b6b2d46f31d94b9c8ea931eda784bb4ab0a5647abb0a67164e3b7d3c801910d24e6474cc7cd638d4a350e73b816a6cc8e3f8246401d4f85cc45058245dee015122dc688883c55f05731bcec3baec8bad98a4e0cf85436ebe9d3d25ce433adb71de387638f8fb0bd870712912119e0803c8f09f98d3969bfb39f42238280686a9a0a5ea3f32b4f
+TAG: 7bfa16fc8c0a24f4970c9e72b4835d3f82f0ec8b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a567790a2467a1503929760de245508438b81d42fec8623cbe41578f193e8fe64c35ca5508784abed1eb4b07d44dee7e03d523d4bb5b428897e9534f0555f9dcc1f074c52db070f42642c0379780c0bb45e2366eddb5bfd489457f02667a00c41ffd065cf77c2158c3d2849815241434bc5b146d30d8d51de883c83db233b5871ffa86d19527c98452a2830fcce5933f0e8e27951650708df2298229a34ab4d2ad8b25cd718092fb8bb21544e2efbf61407906ade63791093e8a47c11288ac1d3639ac527ea5b377ddf8ee33eabb
+TAG: 267d7b70df890809d560025572bdc1328cc0b503
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a5674063b842c38017b6452f39f62f24da2d04996253ce202677cc4c47c6f8e3cfc25020a9103f2da72738f6db6fd3c4e8ed1a0f505f29b84050f1a7bb45404803bc1ec58ac5ea2821c640d8eeb857214d80ce0257d0c25ffe7f2830a9596b4838d63e896433808f68e12161e595bc5d9249faa3c9aa073afbd9660b8f2e29e74010949dd6f9e2dbbfe07f280ccb41dc9f834adb21632c914a1062c3e7064ea11c2833d251a61b7271bf35c34631c7cd025084fb7bcf8d57c65d23f28fbf1c1bae049d5eb5ec6f05a9a89abe3573
+TAG: c6b3eaff656f030a8f7592f635f09884b767bce7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a567893356f36ea091d2fc3c84385e1867642a6aaeb349863eb2281005f3f0514876788b86e6af387e1b317b1317caaceea9093d05e5fd76667a5338c159bf914b5c8fb21568274972a14f2597c009cec323d7b2ad76c611f4acbf6516c3948fe8dbaeb0b68ac97b4d6d3552db5f827df377a7a82d3414ce87d3e8a53deb2679e7da17a439bbb99f18d8a85e4d1b5b9493281d8e50e9143b42d88b84a4e3db47475f139fb1aca3be9f3df8b74a196b1208dfc4d557823aee69b5801f4781741cb74a76369a1ee476c5d48e96919f
+TAG: cd9a7ad3e32e57a35b8f9f05b3bbced6055f182b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a5673dffd1d9e671337d937ad63c7820c979768f6b2bf8161e8622e27d738af25df3f8dbba976b56e73d6bbd5913f013d0f1c4a6d7496f7915d2d8fcd6a324f3455b81b968fdb6690061d407858931afb0a368d54aaafd9e89dd55d35f5d21241ff212deeccdd9d8fee43e47bdef4e4b82d22efdfd9a539b119f9997a37fbadf9b4f184837b696520fb4489d266d4f93c02a09ae5c968401c0d151c37c8d7e550e9ccc0cb9fc5ae107e132d3ab6871fb619ef3e505ef440881cef0e575761d2cb97a29d77b3a3b8098b38309b813
+TAG: ec89377be7f00dd18b28d36248c4f4e9fd969ad2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a567b3038ec763f55385af3832e621bf20e63e9921d03fdd98c8557d1eff06e87af996d1bc5ea98cc6a18fbe23a4f26714b9eba3216479b9cfc31f6b72c58277ecf393ff5898be5e4c98735e1ed3b69cec267fedc16a6802a67b0d344c7f59017d2912698a274e4ab9e4c7ce7a70ab7624aae02ceb01d79e81e6036b860b8ef74c5ff7c0861804e81af25f4a3f5ac00322e5d12fe962b00619c1694881ee0e68016d2ea56b81c35bafce7d50e559a115e79d474626fcd04faadebb68bcb69c7ebbd124c431138c9733eaf65682ab
+TAG: 7e5d6c79e458a14906571250ac21d10a362abf84
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a567f8d998dad81065119e27ed75c544e80fe060be4e7ab019db619c81818b0efdd3e0fff57e6f96e93ed98dc6da6184d588bf12289d2ad5bf2c37b6d894c18a286e72090fb8214cb8665e34fbead428abbae9a1ad29de7d47dbe74ce36b994e89cf5d2c23ffba9fd32c93740b2fc022f34544ed536e728248f1774b330377f5bc88099a09a08914d2977909150b32f8ae77f0804be3976c4ef7b2f79ff6f2ec894179438ffa1a989a1ec6eb57df8ad778189fe78e36aaec9021158ef5081c60b13a35510cd99321d0aa954207a3
+TAG: 6be36f4594542536a44e54542ed97574c0493caa
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56761d6b3bf51181e4482b664bf26d4f907432ab836e6a54f26042f7dc9b9a33db3af9f22f19aa1b72c0aa44986247ae0a3e8ac206780e0f9d3cddff5f5a92840948f5f9c974648a4d9834726b7c93f4738d70b3eabbd5d4af94c526a0666a2bc837b5a24e3792b6cfb1cf07e583a7ef40b068ae4d8cd219281f1cc8a6f58dbaae8b14e5b8ad64d0a01e321ae1f22901c10f304317f5eba4f3808d4b34ea66feba37267cb29d214d063142decf51b875feaea425ccf32b19a1e274afce4c953345cfe0f6e19a5421699e6af5bca
+TAG: f313847bf055244e38997c22ea112cbdeb15c91e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56767987d60192c2ad0d0dd35fcacfed2ee1e2607c58eedc4e62a5067a31231c18d5d1688d7dfe58cf21029ede439673bf32b4f28e9f045d08dcf47e36eb371ac4aebf7cbf62d798c249f5bf7539da745618b6553f13a21b6dcc79917544f1fa1aeb52c63a5bad46f83fe1a70d1a9809899b914399e267d495c263aafa9af0749be648486de81beac253b0d9879bf7ef88156e4b7b5a20381935b36b3a0b225fabf2457aa8e692bb65f7c0c0fae314de36f736f8f9576032412c15e592b0f05be395041d28ecf1ebde97881bfd3
+TAG: b3e5def58601f76489231c6bccc5336920478c78
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56715577c643d9e84b53a00b819996e6f1f9960b2a8c98edd946cffa2c28e06c5a5ad4a3dd667ba22fbfbdffce45fe9d83f8d8de3861da22f1fcf88e3eacf6cd2e79682d65fcede64890ebde1e2fc48cf511561ed6c8b87d6f8c5d630260170492f812eb67c0ef9f96c7db3a2c956e8b511f6ec2cb8185401c5df9a260db3053f64da0c297c0b43d2beb01f199342409630f3563ac88405c696b74bdab4895bcd225d8f29b7619287ee572d07745421b1b0dd370d685f304b61f7d6f99405f290e215b863fc6532ee9abdcce551
+TAG: 97fe9ae91b686d6add2573002c94748a48c0433d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a5673a8d92e901c0553341dc7e446f360133fa33f47418834c7c5f97669f6e3e65e109c3746527ee9c4d367259b919a6b1ee914e2310bf23d0be18d727cf2e58b93c342be0d892f052d377b352ab4333c9a2360ba59e6d2dcd26a1aadb9b69f0b35d80fcd59c19013ccd281d39d342bdb427879aeececeed06e3484284282d7eb71aa93b477d60505d3f1f1e7b3bf5f56ba89daf2f74f4ad377044d80c4fdd54fe585b2157287ef0308e6a8f2c652420e7123465fd45d46ea1cc75cbe5df2de740d5c278b60f29516ffc9c965916
+TAG: aa95fe7a89b403d0c2470d6b173471c6e522da29
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56782386da5ef911b4e8cd6555790396f8be53b12377262570c6cbb1cbf5f4f13c6092f75d5edacc7e4aea4b7c2cae8ab8aae46bdc9dbd20b3154f3fc43c3f4ac34fa403a5dca57f9cfa165282f67b9f37338c272a8e695a48875af0e14523fc344b1320626f8b95b44c2143c5f72934d0ba067bc5e71beda82ab8da8bd9baad81ecf1f8d482889db2bc47f5abf71159aa16dce85f0adc62bac8985340c29e2c9bb30488e8b20f500706d0fe4f76d127436cfc508c04ca065836eef7d3c26cd59a08ee1c802c157f9c0f41a0536
+TAG: 9dde654b247491d5f20c2c51e6e5a43228077fe7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8deddc8257af1927d7dcaf82d8ae26b948af819b88459c3903388b9d9537f9863745a27e238092290423bc7112cc8ee3f12a853245cd05f03de35b589617240ca2ecf7225e87c283d0523bee8772fc03f682bded7956b55f3a4076335c9f5aab6f6a0eb4183f450f157c33d26394cc79c3601c5a0f1426ea24e288f727d723b144bac7e706627f3bac749a9cd2821feef0eb3b151f3e247eb39e496a6d9764fe934ef5fcd55ae91c83365e3e5885093901404ed061dc1ea932eac31e6461b
+TAG: 65a6fd8bd1e5e20e7cd5d24a706a9e5afe34413b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedd491cb45dee8e8b1af1931aef7fca903daa0edd0d7e5c22a7e8e5fb87d16caa3152122c4f8a0f48a83ccb8c15be2ca89479d5e26488ac449e824376d71ed67d84e45f0dd68d9bc49b16a6524b1b066a06f9536e6b21c4c3230b7878fd2af6e20893b4d7e6feeb4df8c6234b5dfdeb5194dfaed7d2efff2d733a91e22bd7f6ad7219bb15009c653f13fcaeeaf4cfda4cdd0a59455f4e8b1d1cfface3ccbbde942aac4c56e3e329b2a8ffaf020184d3ffdc823d7c704f9e8b334646d739
+TAG: 18f49083e7ad91a14a307d732752a39bdf020454
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedd485c2c14b97184de9f702147ccab27195ab7ac35bc182123ad28b7ccbc088abb3ee9559dddcd7ec763091825ca256c02092a29657ce1e8dab5abae4e461ec9442bf8688c44adaac55fa0d5d4194d6897ae7b2940f043d8fc22cf1cdffa94b32a615a331e480d1c6f2106db559d964a8cdba9545a9b421d2ebc0784a7dfa20358c6c55866801230758301c7e33a68f9a7e5564bea449387db5e4502c9e036120bc63a41dc1762d2f7ab22fa3a78dba6e125aefa6322f2330948f177f2
+TAG: 83c89fe4875464310b4de76175fd8ae242285913
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedd675b96980e256448f117e7e3645785c7892b9686e1ca9c04eb05c3519cf4148eee5d7e88ddbd3d90fafef10afc130ae87ea34ee65a472f79e58abfb582cda149f4b79a9f6f22235700547e48c8b0a1f7bbec84bdf32132a8a6136f2923cfbedc8076014b97aec56b53c2baa09a0480a01c3fdf718370ba0e3e1a032771a74187b3c697acd82fe6b90f082d885d967fc94d942a250c5d105c196281f4f0198b352cf791aab15d9be7c310a54c0eafbf40834d2f9b859bf28b8d47560e
+TAG: 12b545bb069142558e93b8a8fc5989cc7575b9cd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8deddef8651abb30d9e45e8cf62ea16d9a80f7875824fabfce174f0cd64644aba149b693cc9e39cfc080bc7e16476fb8f46aa90293183803f5e76c79eded78bd95b12272f660110e57cef238527ce9208c7ad269014bfdeacd3e0088267c0deecc3db337882528972da269faa6e73c6e08a89fc7d8c6f10056d79bf6e07f29e92bb087a3b6a98d1ac40e6bf66d800b8ab4818c761c27f4402c73f8e93d75a5d9436f9a9c4e848d2bb028dcbd9a22eb1f92e643a50f82ed8edef8cb7bd92d3
+TAG: 718e5fb25f2d332188d68f67dddce9be4eec321e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedd8bb6c6ed5f6dc9e5e50732160598763b42daf122ef509da0ea15281fc013c536d2eefbd6731f4b0dd0e9ddabff429a4ab3b2a9d74c9083c424c63deb7dc4d617f9424b5e0e2818424f8cdd38d22153fd90dbc93c46aae4025cb2f6e9747397746926d7c2983edb29d294ac4ca5d1fbda86ebd571ba5f07c3f9bce6215275f4e8096a08a3ce6a2a609c0527839418788db32b843405a2bdafba9d60711a341ca7f1bc0213eada680d12f991d610313b4a99fdbe74c516c37b7c61758c
+TAG: 2776d363c508f5488e85463db071dbff8b315fef
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8deddd873b15b1c51454748234045f88f78c7dff5d0da9658629789db99d8845beb0b49448f51afd559ab02cd39cf6e226898c3c9f54ce2dd507649b9d99523c412450cf31beeec99d5cdc81495f560d7cf92d8cc0c564c99009fdfd4da272892668eb24a146fc9053476955b128785ec416a6263808b4993d17b78c908b7e2ae96e22fe3a052c629ec05dc7daf3a02a64f092bac42efa1b94fc4bab8d4ab3c7a04aac0344ec76ea2a81b712cc77ea2c695e64237c6da863acc17a4ac5faa
+TAG: f62b98ce002bdd31cf9df1b3d5c5fcc6cdee313a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedd9f63f3a6039bc20ccc240333b752573a5b684a9397f8c3c59e9bee6b8c28debb3ea21a274d6a199acba999e43dfe6797910ed80b4b532568788778ddf01e42de6597aefda693f17a3be8865791f2312427feebe4d24938f090c277af3b2f6bb6d59a597ac732aaf5f3808ff867a285ab412dee22e722487904aaf5d73df22f2b066e388635bc3acab16ef61c9b100686b62349167b226583197e22b757ec4d295e56c4bebdf4350d6125877d1a481349e07fba018197cb8c2ac163df
+TAG: 242dd106c91f663502e092bc55ef2a54f1857bb1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedd552003b3525bfcb864951edc8fa0ea1aaae89be23451f560c8eacf5103459bbeee16b3a20db35c3fd6aed4ed21db8a0f979031ca733d0baf917fb64c8179695003e0c05ce2fd3953a8e27b201ed12bfe327bbf04a5197a7ab05b898223ea26345925fdb77d6d11cec63550506f35e9f165c863c50357a58a5b250cce8de711715368cc6927e34a839b2279de2c524f01646146b285104a8d175e54303970e9d8eb90aca29814d4b7893fdd331fd165d74377456b9cf771a897982278
+TAG: 08e248514f44ac3ab83f45d6760cecc1e9eee4ad
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedd518463143417daaefd42d529d475fafe361d0f14b1b3a785cde9617fe09a001a44bbf27a63e832d1879803285439d42030449e79654f6a414b9af3705dcd60f32b7dc1eed2fc641867b321385e3b568aada775d722a18c62afbb3f9b608c6fa1bee9376e9ff9b032f0e90699a2ba5f85da6058c61e334baf7553c5d1f3f0415f0ebb1fe05bb847991b31137af081f4aad351d45f1a502b28d97e4ffb429ae5030db2736077483e0a6f83340053eee913f9cab65a37ccc6c83800652b
+TAG: 3b5d793e4d369763e3513fb6829a9bfa7f694271
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedd56dbe44402c6a1367c460d00337192d01c1023efc66032f81eec298e53c6944d6078a6de7bc90c88c91d5a2f798264e8ac48b7e4333dd55c92a90a2c2db2dac77702f037ffe7a3e4b53327636508205c454d3e0118c0b0f42b5d2defc7ca97536cfe190d42b83349836959ca8c033f83908cc6b70ed1fb617d40db4ec07a5bb3b7e265f4a609179edc52b17e0bf8921ad7714571f9b289472cdc75437f8a5cb67be8272b499b977a1fe59720dadbb4a6da49973e6f1644ba7b073fde
+TAG: 184a26a82d7fc883f750bbad98dae03eb14acd32
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedd8c6ba3bbdf1b145ccb16f0e266d4101ef15756c580ec8fb373418deb5b711a1fba3213c5b0f7f12743863fd12a97b5bf0778ab0539a762750538642dd9a4426729b60b6fbd71a60e58bf29f35885a4d618ec3d3222ee289d8d753adcc88a4c823c33817cd2f696b14947fe6a3a6278f8bc9e918b16b7c043aed2a4312765d32e043bacab66c644c1e280ca9c3e7c02feef7a2286b1ed40a8bebd1043d07a9594ed45a8bed6a6d5b9d495bf3325f7ceb47af3df8c071010cf97d01969
+TAG: efd63bd73b13a05a05124994bfd105885a548024
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8deddaac4e3b20a13b7eba003cc2a6a157dab06e4e99322c7cb6873da030588c03851affa1f604946b843b180cf6ceb8e4635c1907b05dad4e8f9914ebbf9cd0af6ff523351d905b9334b4887b40feb831e91fee77b088b5bb0b32887d6e8bc78a1530f60d4b63b611dd137ff9f00c26299360ae3dc4e93f60ec96774342375d12f53a9b389b8a01d3e95c107753302933685f12d32301d969140e02082cd799aadda089dc5ebe88609c4c94b9b4f570285f1e34db19ef6b27c71e37d4234
+TAG: b344d3660bccd98ce8e220ddd87b7a65a47e6e05
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedd3ae337b2037f685c0ac195fd32a38e4d23ded0f902f40fbe0e8d2c05e96ba0400bcdc8b1b252a15631328726af3151e90ba15bcc9fb1f020ec48ac6ab6d033918f817a126d37a0d787d463d737c1b784d5423b4a5cc9428780b4e09314b62c7aac85d583ed012bfed82b7ee2970e41ca99d65bb1c2c52601a853d265c0966947c7597e9d0ee09b8aa506c85ea916c7148449c4422393f392ed555e15f4bfe649fc6425b4fd7b009e60d0c05b15368605e1a556000116e40f8f1373c4
+TAG: ffd7fff12c51ab43e3aaed9de466388bef49edfb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedd924c7afdfbb99eff99d5101b4453189300c661a16e2335f36691e8cf99a877d89d586eddb75e67dd5c7fe3a1eb86db4789b73a10dedcaade5d7087d12b586d61a6ff35e577144174852732fbec34638f3c7d79499b5c24876dbcce59ec71a76a14d3af42d70574336c548235c52ebef07e6ff756bc72f904494e71b53d792e75b5540745d625dd2322d81384084b0068b81247a4da47e78d038c4351ca2251b861c20cff7fbb77c132ca1fb5c7ffc20c6dd02a3054fc9c60491232b6
+TAG: 690ea0532853020c8800f6de372bc07d2eb7fa2f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedd4fc69dc079f2f1a874a055b9ba488a901b550ab8784268ed12987584e9bebae38ca6f0b0c2553f6ea0f10f1cbe9318b0d64b38269664a02e1458c2a3a498ef8edb47e1b150ffe55466d60850b2062e85b8be6ec5b13fa11e47f888b1f7ede31b4b3f6d557a2ef9a60f0073441897f6a4d21ecc2a28f71241f3b42b5737d98c67b362ab2eafffa641eaa6c6aa3874618e93441b4ca41786ec44050ab2ab00986084ccfcadd3d8c58bfb4156daeee06f6692d60227270478b0ba96f648
+TAG: 48d9dd8d07df6321f38b22e5a64233bf67c816d6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626272d2d42325b2d6a8c2ff75179ee80f77cf348f0be7f4598d3200f2acc53533b7d66caf5e18f496d8dfb824c7caec657fe57e444c37fe30ba9210f6757c9634f834bb8bb3a2b72519064c1cbd50cdd01ac81193ec960c404d9c75a74498af6023a21b4779cb4b37c32e7518023d1102264447e25722e3a13969782ed25dd80539d2bae7d77f265f5218effced85d5ca436c62d7f6a5d93d9a1f05888432ae33941b4cde31184984865bbf57b8
+TAG: 6ecb05c3dce103ad8db2dc4f65fd652ce6312412
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d8856262f8ee3391aea77b1e29f988e3e8724634b048a33bd658824068bfcdf162f590200548c2c12a0777a51aa5a58462364224bd2bb4ecfa2ec462b5a4606b4506d70a6dbf17690f05e6d24a3488ac76ec785f532cc5af7dfa95fe2c463f0133bbdf21315523f9d8ea42009c63942df8a87c5647cd17b02d4324af4591cbeff0d34ab8f5734b8bcd552f05d3532b64444d409317ca81a4bf2328cc87f52ec2d375dcecd279b7952a6a116c81adf8a5
+TAG: 70431c389434b42e4be5caa1eb2e6e551914773c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d88562627c1475d5cec6a530918549df7580e73babccd78a352b848073e7860112b0e30ea2d0ae385493098d8df56924961ac0caad501427d8bef0cab93ecddcf166e954cf6e97f699641b85aa369f27626ebcc28c2ef0aa3301ad5e4b115851bc4370facf24a84da37ab2b8c14e47e5fbcbec3d20b66bc36652863ae37735816dc3afca590bf1e82ef7f7cfeb097decf927df953b394427829de9dbf60fcef08247aeda0075624b3ea3e36e7e5ad5e2
+TAG: dc53d8dd8a9c852e73d3cb32290b08efee3c3abe
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d8856262f32634b1e38f289eec09caa7f9f9acca6506aa9099c0b22ed6a1afa72f1383bf95336f953f15840c40564aee2a061cec115c05e683529416c4daf826ce7256998e698c75efc3e91ba35b0e95158eda244067529479a8af4339d8475c5aaaf96dbaafffda10f74a228c1976c6c4a9a0ae6e1ce4898c314b230fd91009bf3301b2f51624ba500f3bb5d7da0818c13ea9776e9128010000a5a940b32b39b17b0bbe64bd8485d87e9b8dc60cab9f
+TAG: daff9d0d78135e69e8005fb3240a12f56fa040a1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626228fa52726f737774f150feda507de4002f0d754f370fa3cb1a04ceef1c5efbf0686052eaa8f4ff924de02d3215cb6527b6e0675adf8324a095ff62e2a987ac19143cf21758db65f335dd5360f6ef00499e92852422bd12464cea587fa0a77d094a841ca594cc1983473fe94a9c5f5fc4ac4acffaf532d7d00fc894b1a4c810884d350c08c66d4e8b4526bce42c92223ba993280e5e65e207534e4c008555ec88afd257c6968e545e5c605ac3
+TAG: 4fc2762e14d873a40b15221f4094f1e78ee0e47f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d88562628e4c4acf766149e24450cf2187efa55fa4e24f108070116ff2983bc5413235aa16414d5c9ad44b80bdb7f508aadca514184fab7758566773c8677270c6cb2165b194e6234bec75a466bbfb477a4f37c103456aa0e6bf6deadca111364ed42a2d4be2a62246906988e7636871588c77b4041b7f18b4bde7becf47bca8cc32d899fef752f3035202873927125afecb9a494a344ddebddcd5dd9ce138342bb11be5c553c1a9820b5465289d9cf9
+TAG: 91f76738f86a54aacbd5ecece7683d71eb01f3f6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d8856262f98db07a9e15e3291b5320da132eb906ab3ec82f98d3b03292887d02e5e2d6b86a859fcd20114fb4df8a900544b2a8146a9ce29a13eb6461e7a3ff938d1cd203146e293fe2ec4376191a762a8416e28b668ea34544d070bf2315fa67144394c0f5cbc7fcf4bc182f684853747f7f5645dc2d110cda325631127c6d699bce24f23ba3a272f50abcab86bce5cac5dc36b37c86cba5b6d4626ef0359bc64ab2a8774cb2dc330b1622ef7c0bdc1d
+TAG: 6aec0142816717902a5128da3fd78bf63bd5bc68
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d88562620e8ada1497871f194c2e5d35b748c683a3b98a5b4b722575546c3c34a1a3700c1fce2c69bfd6db7f2a4e73224aefce41dd7383295a0206a012fbae39670e2bc381625dd39e1e14a2a89ab68df9f100530a9d88a8b99c5379f0b3d00d70aa5515d2d0fbf3b1daf7b6f3b7f044a80431eee5649db70cb8b0d9222c196454a924e3f2045eae7bbaf98e1b86b1c37695e545bac5042a864d6ad7032f40267fe262a5e2fd4bc34689489e6ad35434
+TAG: 936c8802d548586851495398cf335b81abe3f192
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d8856262e85e21f450ebe1ee935e08c4bda3e5920838be23ee11ce1435d1b2736b2e2b0ad42b2baf8941253a0eddb01ed6416558e48e6c987d8fd1bedb2e9c425354d9fe32ae4ff1ec1cf30e46a5a5e651893a9bcb03465c01372aed9a83dd21dfa3087b925fe2d989fe331abfb04c7c8559afb4910cdfece4b6154522b4811dd988abf6325f94d4e1b835fe2615a8ee58b960c8d43ccf63f7be67cd52fc79c64753198e57e8abeb07a7a418a273b9e7
+TAG: 65ab1c13480810dd2577802446f9d344eea2a795
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626218af4e33ebcd4ecc8a71b8226ef0ad5edcc8277a14f8229405d1c354fa3e93e70297e2a7d0a1518bc77253e4693dcf8412f29a2e5c63ef171b671d53b86d0cb709b86cb0d24b819cf930f66de9c61ad5186e6a7c09e63e0a47cc7e9fc453492bc7e097d32a3243c0e683bb62528fe1e1d24fbe3e3815807de335edf99d16d13ff1e72f1c1e5b00bd5fd9da548c9c474ce1ce55c56993adf3e0fc1f8c19598792798929a1b383da531c703f08
+TAG: 5dd30b9c361090d113d34c104dc8c6dfb5317276
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d8856262723076ed43e1dcf3c4be3aa69b8a105c69d2c45442c02706c64be9a54077ab8716c5e33619644429549f6c62b8ac87630952aa0caefa8bec07ff06939afa2debb15312b21643a3c1f080fae110abe6e4fdb46729227528e3be9af61ceaf7abada506ec873f663cbeea3c1c613ab76513aaaeb42d935c8cd18f5a1e9d6461a828c2f3cd98551efa3a1d5f5c77468420533d572b5814853340cd5743e28567f52655b73ed7157e1d24f5d09dd1
+TAG: bd82455b2c0d793709ff1fdb4a7d0155570ca95e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d8856262592f9d283bcd9c3c2eb9d092c59117f39038d86fd1ad54aaf63e972369f2fcf4426267ce3b408f1672c88f498d9c398c4ab86a64e8658ee615619121155b29c6151080f08fa5b8e5f84112dbf6e8636d27e299bcf7b1929c0d5e2126dad114a456990a9cd2d0beda84a46ff5b8debf6aa1ae37f81f07086ee5ac8ffc74626dec8758de090f3296ccb0f8076cc0049d69bcbb6a3ff704193c82beafdc69ee0dda02beb011d3875197ef394b58
+TAG: 7c2f8469eefec9d96a37c0ce4c29f008afcf3400
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d8856262b21993ec8f2bc4aaec3304ac640ae12e2056cc664a37e0a75f4c929423a0469da972938467ee073824c244885ed9e1475452eddb1c519f0371cd72b01cc4bf2b9025368d9fa06eb631ecc30099a643aba4f6feb4bfca95dd82fb65dd57e62fbd222b3c38b305dc59f999ba5c78f77dd80c18f58706c3f214278bed090c46c7ab023af4feb359f9d1a14d78992d25f76e52192b28e1247482aae4ebd50aaad333ccf30e9a7166fd26963aa6ac
+TAG: f62be4a22f73342521db7843607983a949950bff
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d8856262b5cb715093c2c30f79c6b32ac0d40a94585d7f11f1dd4b98b5b42fed7094ddda8b142fc53b9578c000acc9feb4adfd2eeca769213a7928a041da26a2d07a0b7e7d519b2ac944365003da0be4e2932e8ac0e7e9b761308136d36a8ca3dbb5caf475670743c336717d48de40e95569e63703c15dfc4377cdb366f59eb6d3ab8507bdd67e9d6b54b3ce819ba458190802bfb436c9fa1a9a30875779610cdc295f9dc73023bd8276ef6cf02113bb
+TAG: e421115553d0c5aadffa7374d10e06987830a0ab
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d88562622bc38714230f9f5d14f4204a111d8cf5216fa63796a74222dc31eef70f93c6bd3329cd9cbb7c1c60a23370042be1cf75c7ab3d79a2607fca6f29852404db8a38928f38486ddf8b62c7f4518129e5cb153a44a17852bada082a80e17f92b7b77e0372ad885f0ce967d6b76b82b5d929e4a52bb2175c1e9106d583a163d3535a41835ffc27463e2cdbc00e4a43d13bfcc839f6adf5b4905d84b6b32bc1be9cd33879c3899e39b35dd2afb1a441
+TAG: cb90f057b232e7cb49fb53a7dbafcd17098498fa
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d88562627400b936d5dde679628839a5cda451cba639982cc9a118eb2149c51ef23d66f0efba6f451c7d915ceb1758d62d1d73cefe069c6a31c0a6362554ce500278ddff1e2dab176ebebe9a3b35c00e6864047fd59e82f9f1d7dbd9806cd7d322dc8acf05e22b7a6747b97dccc9f6efec58d306cc3b74b64de1fbd63c41897bc08a30cebb954ed4afbefd623bd01d25c4edd01134445aad903fb6c0a1ce6845b897a41d239ee5401b9ff0676360a4b3
+TAG: f6fb30fa910649866226f3e59ff05b795e00db2b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f26e5e546fd7ccb2827bdd58db6e9862c77bd1b2e7b88fc39fb4f9d23ed1ac17ae23a1d931dd2de8564e891f9829d79a5990c679a2270e76b9c0b498333c8cdc0393516368bda2a6e68c4798fbbd487f50029bd153595d67050bb1fd48c5c2ad0ca4376b20bc5756e7b74cb08a1c7efff1aac0b10e3e0c4a041b987da2cab91080fc51f811a6fda7e299d3c20a2d59d19799bb16a815e72a905ca074ea
+TAG: b56aa32cd6abe5e9dd42a2b62053cf88a5623b00
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f20e63e8504652695474a93b209dd2eff4b96fa0685b0cf649cad5a51cb056f13f3d6a3ee25dea45bf12834342cec2abb2b747b64abd60526e8832311f94c8c343060526efac8db412ee4b9ed64cd9c40c2079f4b04bec64bb60b8abc4d0df9420ccdd705779aae7f4b18c6d959648359793aa08d0a25da96f33b2c0bf3329b2ff70fd9cf1364457135d8e93e77bf4b01a5fccb0af8774997a8fd4bfad
+TAG: bb088cb28e8653382fdeb44c98f38634f4d6eac0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f2da25dc7d32b0f0f0c6b301db8eca9d1157cfc943b587b7b4068e44821b9c1954f4e9993f71f6e5e7cac79332731ed83bb139d049989a97344f780680215d9ffb0e93f2d5de32d8c76b3e1c0b0e3dc96f0494d6276ee4b226138b15993455328e3b24c65224ccb903a655945e3ac696f0d7ae6db469faf6ec4f098bafc07e4f4ab6f591a81b2bc43823fc20a5464d1ac044ca515053d39a1cf3f299fe
+TAG: 003918b37a7e6a4aea636f4d9368624fc704a3c5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f2511e4cf33ba35ae30b5adec36aaf1a5694bda1ecfd9a0bac756f2ceea5a9b41e0af1aa4538f5f3708469e9f4e5bb16f2b3289f1b07b30af3dae30bbcc01ba30b5b5b6cd8bf868cf668348a692aefa31962ada809bdaccfcaecf5e33f7bac02bb1db3925c9e7c30f72f79eec14104045d0f1890dd8d133e6dcdc76ccad3c576a6b1f7f180ddab47fde8673e0e294fbfd7dbdd6d148b46b647476a1e9f
+TAG: 8f3f7f534a7563ec11cee6e559f538f3a9aa4ab4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f2d1dceccc17a1b86b300ff1448a1cc3c50b4eb54c41630542f8bdf5f3a32a7b01e787fa14ba0dd5976bd3286f453fa060c57eef52712c084e4095c2dd0fc153223042e69119ae1cb8e36161e247b3301f31804326d91b1a8d9694f3f11506dcd742cbecdd295443aefb58e737363c189228874cdce4791f48256ebe930599781accda5927b1909a7afc5df21c6b661f5d14ae85a0048067395ceaf56b
+TAG: c538da40aa8698b8b8132d8b36f3fdaebe4f306a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f2528755eef2e7d00a57a47bd8e2cbb97d2a44d2b16c4afb888fc0eb1e94e4503ec251c576d69de37d5acbe447aeec9674dab2a626e3ec03d0606350435ba8d80ce323de8e905604cdd3742aefd03b750fc9a7bf6da63958df88c8f1be0425a8d028eff49c881976c570310a4488dbdb2111128a96b21889f46cdcc1da9e7774a2c0772dc1613c860f0abc71ae2b92e1709ac36f1b33b07292f72c4102
+TAG: b63c2e112479d56ebf72af7c12602c38caed1604
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f23e3e40de5ed5c72c3b16a31c776ef0ba8a4c007c4a2f563a36be6e36e612696092b48e837bda809dcfc0d5b02022bb15b22e99a5e9bb34b6491cadb1b5ab72070cd16556b5839ade21a2887ff12daa0f468b547dde73240b406ba0038e52062cafa7891e13a6e2386145007ef459c6d2bdd793ee57ee9347d45589081bcc109b4fe3469e7d242c489229490428a510b985007061a557ba0ba32601cd
+TAG: 8244f5815fefb68fad061c02e64cbde46fc839f0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f2a032db5d0a227ed536d58944774e1825a541918295d77c695c38db8bf0c18599aee641eb2dbef370fb03096510c85ec45ad9dc6b3174eb80518c6560a61cb48932542159289b0310327100d3fed64262fc75b935a54e7d0582cff31f9f1007aa73a8b25f84ec9ec099023d204f681b47a06833a85c635e2d340ab18c32af45870d083b96487f187f85aee146f031641976cd63d8735c9ad70dae0928
+TAG: b9ba0efc13224e870e385afe21f2e84556ab4960
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f2936a93c27ca2d65842461f45f71408aa9dd355a15eef75af52b334213e7fa6007066f2c2b00c26240b41cc3366e8b67a10f41839bc37af7e4af18a1a94fa6fb8227c022467ad31dd35068c942441c818d6f33ba4ae3c5c6a3fbd835fe9bc1eef252b14e36e544a7b8789b1cf2fa0b12da302b2dc131b2e629ac4b990d5a610c93a4e50e57aa986e29c500ae9a8957e831fb0e0d110465839bffba14f
+TAG: 1a3efe2242508ad928e0657688939e3d954ba774
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f2bc85be744bfce4f051f1dfaffb87972ee92a9d3f30ca0732b685f6868dd6ebacc7b84efcf819e5c6a692acb91556db8598f438dd352c90bcd6f7b09e870cc963dca9b494775df04e86027b462eb544ccf898162ea75459608fb795ddf5b381b421ce2e40782be6281321f1fd88c89a45c353089f9f8218f10a2ddc9761ecd4b00b60b58ea4317e8141cc2c830a0fcbc20a096e399b5d0d85262fea59
+TAG: 465887bb34ec4bead20a823df6648a09b2798842
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f2b6731974ace4825dd2f88f1871c193052d48cac6ab5993d84651f41d3dde5e3d791e3580caba2dfd9cf02362a8cee1d3116b3e6a15428cc2cdbb02ac2d84111f2d12c5884099e1dd4d5b86bb6855054a419ce6a1e5fb841a4d95828da3e9165664fae3e1bbdff9b5c8b7daa3ce0bfe62729913f61cafb89efb83ed927db495996c23c5a5b0d34e436e43ed609f257f744745c897297b0f8ecea34a22
+TAG: 1428ad8c0c038c4c9b205322eddd4daa6fbca970
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f2eb03a0e69a4701ffce318b872432945ec3ff476e322ecd418181641bda881894c3896a7ab5f9a714e0c628205b1c184eb41efc3047a8b8fb50a5a17c33f81be5f13c9da35350a2c9e5302bc3b2049dcef2412a6dcadf888af98a09f5376e2c05c86a49524afa61c9dec00b9132db19a0478c2020ca5bd29a79d7a564e95a0f8eead1fe769c1324916a1959362556935feb7b563aede22380d2ea0562
+TAG: f2c16080ddcee86078e0666fb6519bea0f87e33e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f238d6c739ebac87e3ace360206ce0d0d55f99dd884479e4a0966a0e4d7babc36b6b624669de1e7734b49f7c2728fb3cd7b08f4f7a4ac8667af043f191a7387a40cc0453cdee5a523062691ed8531f660410c50d2266c15d84f9e2b369e7c6811dcc524d45b2d600fc9f227ba0fba5e17a7565470d85ef98252e90ec3bf6d8bdf4204b47f581cdb6c88c9f7a00516fc1e0617a61d44fbafb3aa900d051
+TAG: 038fa86eed11ce146f921d699b94c0239d6278d9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f228b81789e39fd131bf1b2189f6e72fb7e22c00552bf772bbcffde7f56e5c1ce4fe95863d042b516115f5c3815c688317c4081461b1973b7c14becf0f45ae5e11800da6cc78669ec45528ca2324b91b2849facd6528cdbee4bcb4b86d550d6afdf660be6d9e0abccff15d2b49eead3585a14aeff6c38ec19771da2b581993f80f15ce057a314972f6696b89fb28db40fce3dbd56a031e334c9e09d021
+TAG: da308d64510a73e55609ff70e029ed88d1545022
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f2aab4aafe3bd0ede7ce2382a1b8b6320d05939fb368fcf0fa3bf09d4149f57109f31e55d90471cbbfa57732fd779e1e0cedd37bc555ab618204b35491179e3460c3c0e28272804d05e6d8b0e5c6f2dad9aa0d7211ddf25797b24ccdacc4be3df4acb40487eda911361ef54217179f2b8078b7db112fde6c20eae9f01b0e15759cb0e554852e41caf8796a8361f0cee532eda10c7471df08a2f92a517d
+TAG: aabce9a7ede887411f3ee9e02bdbc4b5cedbc657
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f227d93e355b9bebc35fd9d42dbc36e1d2f85e4b5e27906fe5c87275927fa021717c3a898c2af97eca25cf5e890640c469626cb4da4e292d070a2404f861e454ddc0a195880a7df5a1ac92cdd1cbdeb87b43247c788862eee6b489ca221be067d8e269bd099bc1b04fab7f7e8f75810c978346eb61bed3d42ea50410ddc543a411c65e49866011f5b725c11e9ed05f73e13695c000c4f0c419ac121a0f
+TAG: 3476c42c99425e4f8a7b86f713a66374e4949e34
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f62ddac56cdf9567470c07ad761cdabb45f6bc9cfb44ad2799b52d81350535cf51f9547047fc10fb2d947e1dd1c7953257411bcbeeec7985607bce833a75aeae450821d1cf15828366d8b55457b451acbd7d91396ea31fa4c138eec52384a664dc96e61d9770114668e8ffd81656f7ec82c1298982daecd6ae9c1912dfe172404e6496015d09a40883f91c902
+TAG: b4df4b0132183c90a8a5956f1d717e4e2ab901a4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f9dd2134c0451d7bf59a57a09cd24559d894bf6e866998a6b0369172142e2e0f703e7a859cb52b0ce0f98caa2d8c00ef3855139a34e34e04a86cddb43cf49af4d90a555ec3b2193bb08a84a8bf288fa24e4c4a4ba52cc89d233e3a7ad7b31ea08fea1dc60a1fd4d198fa91ee5667a2ec4c739ca680137c295188fbaef4a359108ec81bdab6932b0196f570f37
+TAG: 6602bd3835aee22e21d041ea49fb5d76981f4b1a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f757565a2a1a3ee661fc36c97eb67ef8c078120229a399d7a9168160620c504712f852f1f7047fe3a1c10ddcbafc5135f3ca7ba9606ee9b12b69e3a83b19ff7fe9f928ca75d63fcd154a29afc12dfcd372d1bff8dbc2bedbc0bcc66a23c324363f67a6700488c14023009823396b3a7a0d3f2734b3d9eedea3d1ae445c78d4e95c1b5e4bf890ff9d99426aaf3
+TAG: 24ef7be23a1af00ce2b42b2c8396b970585d2bc9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f232e3c8515c6cc359620cbde420eb385c23faa5776c3107122c34b6aa011c742ec5ee874292b531bd11e70799aefebe43043770f130a068885615e4962c2e9c35ea57baf0c2a589d585da25d543cfaf3ad2b92ba9b07aceeaf1b487e10f570a980ca63e308cadaae34c8a2ebc35ec85f586a61e813f7a6cf5b8d60948b8453cd854175408636e5bb76125759
+TAG: 9700d3d50b67267866a030efb23bc3173fdb236a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6fbcedc328bb0b0ab3d811b06c90924e044b2ad12c20082dd71d91dcd48c1544ad951085a3daa2e739f5f14deb28353a9a5c92f899221f48687646842de1044125803233241b7394b568cba18aa916731459fed640c0fc57a952358091bcb4808d3305ab9548991e4d89e60e9f53eb78f2ba29e46dc14654c3debd10914648f2a90a5f57338553bd18946a10f9
+TAG: 45878787ef5b9841d947df2de199e971c8f1eff3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f18727d468ad5ab21dd0258954aa48dcb0a2efc6d9e238e2f2f21f36fd86a8955a048908ab3979765ef640e9a405ad987eaf82f25e2fea3d613d7021d6407cdd30133d9e1572eb4d6b4524e9eba0e8c8cb01b4c8eb02de1419621562a6e041034f882c9b914458d0d4e41ada64e155d2a33f7b60ac6018bee33f993e0c8f015de5347e2e2d48cbd100e141aae
+TAG: ca0adb0a70eeb3904ce979b96940dae3fec00fda
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f385dd025ee8bb3be45d21814c3cc3370dfd14e08fc3bafd3a03c4e190d75457f71e49719bbd1f421b09ab287ffc455ff56fa06c8eeb16e98d378e11a1ab01b572087a40fd9a3bef2ad80d73caa8b5f18b1237c917182be22292b89565d6ebe55f03b2c19b1b060def5e83b4018396dce83e637f2323114c8f1074f0767240da280c4b60131876c81955839be
+TAG: 9d8e9c18cb7001bb2abbca842168976ebc7b1a2b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f76433978d3f272947ea437f70be6c6cde4c474a2fca330f6c059ebda7464d23982f3d471d4d75444f1e29f0c0ce07b3c07ce7631ebd8d10c7cbb5d4ab788d4bd4762333c26c6955ebf24fb428dd55a1d03027df216eb9a56e90606fcfc2815ed72d068fa766546fc52c7b746039a155c23f21cebd978cfb8e78609ef70f3e556de664fe720d01e2251c9c76b
+TAG: 9356da47cb2a1f51b032eddf5363e226e8f3d77a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6fc7961f27322c952c0e878bcb33059294aa580a9b296c74257a2c08dcbc77ccc5eddd958fc0c71e91e1838ef25be214f4f09546178f31a4f6d73582d5d31535fd8eb72c941cce6f2a9e0281c90eb9786fcbd748c7bddc6517e21999c82a0f5d655ffa885cc490f8fa270c8c70eff6f4158a8b5bc6ea29cff0b513bbb540acf0d7ce771f20959edde8ccec2410
+TAG: 337c30fa092514095c12a64bb72af7098e3ef186
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f1f53ad14e18fd29998e0f4039037275c31624d2763daed1255ef8e44ac51f6595724d4b570c0aa9c61017ca4c6a026630e33440cce31189061192ae92f261e4f2b10d4cd316580ba3ebf4109f41bcf1aab28ec0f46863fbee9726fc62320a7eeec61db55bd5507a23e2d361b1ae54e6df93804552163b262aa824c2090dd88691155924d10564d082d778b11
+TAG: 875ddd405a907d6a20d163d67e8e718ce196fd2a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f044a9864cbb9b926df76fcc775f3d267209a9633e1d2966455aac3aee6f342df3c8210f7831db6b29b1f969e008635db0e7616d928fcfedf2d0fe6cd51757b89b2d09b7a4863169d1596a6b61d4a692e76eb8da1e057f3f2fc0eb4a2e787979d4b0f04da04451e14d5b52ea7b2fe75c0c079e5935594b591a43361023520b2b4a47022efe7e6a61782952ba4
+TAG: c898aa50b631a477dd92292680f71c6752227d2e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f751de45a3526bbfb6b87f090fea408d4f145f19c020e9af0561a04cba36681f08180488402cdb80ab7d16e8a264442fe316139bbd98c2960d61cc7aac1789c081f00f89da47875772129193748712612524fdc0fb368521c6b1aad473a2e6468a7e4559a4ed27108ce96a8d52a0b5d90fbc8ded9ce894a900b71347210d97496bbf0785dfa0f14e181b6ac69
+TAG: 16eda5848e336bfc627db8a1beb14ef33be966b1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6fc8410676d1e1d77f129ca3756173aed017d427d5d905ccba878cfc6ae7eb2bf001865e62156b2ba2c26b026011d1ca07c0dc6e5c64ca97d1ebba1bdf01a6cb61ed69bc36257e7ff96fcf90567e5699929d85ae3ce95703d19cf0b1757e24f1ea390d27e88debfba8894c3277b7d511531fc16ac71cceb65346625a8be2dc10f3ec311bae446ac773338f3b68
+TAG: 3e08a2ea4d42ef34eacf473c0bc70c51f2944c27
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f3b501f5b5d831eb7e0004eeb760057a8c3e11fa029b6b774a83c8aa41582db1187f2b8d6291d7698fc8f842774b7c147138550209dd255a28c8d35c459189be5a67bdfb339d8513df993b359511cfa97a57cbf5853fbdf5ec62ad4f731c3226aff717728a1b9c175c4772bbd59a3fb53a69578992d76052287e2a7490863be8a1cb43e1e76e53f54f84f6efe
+TAG: 8be51081fe987d836b0918f46d02037ecc39d23a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f928b194180e0809641f0d713a960f7789c2f20c83dae3097b7a3a5a7b03e3fc54ad9e95fd6aa863fb01f02246e08cc136b11e919ffcac41b6b47073db503fd86d6caaf97e7a226921c080e5c8e848c64d9c3d1aa62ba0529e946dac196aea21b321da99df231fff121f66ad33c66d205abed7e9a612b818aef3a5704cbbf6c30b85a92f7182365d79261ecaf
+TAG: ae9c9567224218bc8d0ea37673ad19d911e08266
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f1497e25492ad7a887412d9eff6ded23960d95026c2c8182b10190169398c6420c52ea6733cb3462aaa2971333130f3d532c0471a780df2da469390bf157f9d5597bd9b1fd9340ee4a61034b18c188c5f37dfe3d89e5c1af7893454d63b11a5e5540acaf326715debadf5b5674dca55ba2dc720ea0216a8ef2595d3687235c754c1f871b6d52cc27e7a9f2ddf
+TAG: de49a4479ab4f44d9d91524ab8ac323f618213d2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bf495265b11a6b571eac415bb8cca861c4641dbe0567fc285293a1de69d801ea50df484cad136e4a8b5cfb7d430a259d1ffe210518aa0affd8d3447dab3add207d75c1b0f3bcd74a2e31f44405f6da4f3dabedd02a9f17823ee809cc689ea687e4d29607abbd029848f69e2f3c54ad26d55e7a62be8f47e79d6844587
+TAG: 96396562e2594017f32389711348719e7db8635c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660b3df558cadecf184d3a218d18ebd7adbef9e71924d1d15cf3d335741eb1107aaa9291212b30a90c11e0d6c75b3f08a2019934e075992289cc5c696c39c5dd7d0ba73b4612b95a2fd5fbea939f3b3008f32c8174b7e036ba04db2144fff2213596b480edeb1ff88de2c30ec26a045f45c81b0cf5b259a1d419e38d598f
+TAG: a6a3ef04108ac1c46c4971d2e4f59ad210445995
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660b5c44375bb14fc0ec49f0b8caec8761b0fddcb87a17f8d589541afd4fea463e9e3e02b6b38909dc009eec6152885a2475da366108d29c0e3cbc15ed476eb1b97e30dc24d8390dcfd4f08feb282c409448429471e8582a9f834c17d8c130481534f314f22c890867e53457ab3de119a4c8cbb2da5229c577258710d4b6
+TAG: 385f5636ca4a8b53c7953d4685ff9a5749186bb1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660b5c55dd6250eeb86fad40fbec1729d1c7b60a8595af385ea0642dc13502bca943426a97b18bdc79b7d8e6743ef4f9275ac030f0b1215e5a1703279ccda50d9b3d4f9ec11b9f044c040d61fe721eb54340ba97f8c7c1f5cba14eff87ef52f9d918d4de0401c0fb0c22a0a213aa3a21f203f5a45b4c38b195228e695ddc
+TAG: 856ff5f0b0cdbeffd2cb01753306ac3054b7f4c0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660b3af97ad628a89c19e8f93d9b0b0b3b8e936171dd03eff4efa46e8c080a0b16e2b95c692128956a90c3e6d972836adf88647d011251267c4c365c5982de30236b3f15a6eb1a799df8739dadaf992f50194f6f8065ec0510905a428564301ac3ad26a274b31154b6507d194e58b168f6ea305061b5720f087ca037344d
+TAG: 5757b8b6d0a516b8099b39dfb27099c8d1bfe592
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bd1275a6d196ff1f1dd9d784c8986399defe013f4171ce7fb5fce425964594fd2c7d6990809b86e9bcffef671991aa4dc0d37b1082efb6a7353a2e13b259d43e174641ee3e2fd122d7a027dcecec1f9f5a463dce64aba38612a336c23cdb4b3850bc6c6d0a98b32d40935df409c03be45e997ef566ec1a01f4caf7d82
+TAG: 3b50bb0162f96eb64ca7e5497aa15d1a49f20a86
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb230e04b2ae53e7a460f75334a04a041b0c04f0ad6bc8569f113d11e8da499fa886dc63d309d8d18b0507a7ad320b637f4b2506a9ef867d77fccc6d7fd211f9485a7b8c9a05aa7bad75264d90ec3e5de0e3e478d2b0330c37459eba5c63c7aa3265862bf1bf494617438c6fdf8a694db093683773d236956c882f59d
+TAG: 68912e2f0f1c8326e5f7f28882c7c313d5c77d84
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660b4416351b4bdcac0073f615959362157c12fc063fe415cb5b6dee3346e7b89a36658da817271f0fbbf435685c91e54823cdf9cc083dc4a516fa58a0bd382d63b23084fc3d0578bac7a74153e17c5eb48b8ad18d8130d938ad5490820c86d329f42e9d02a02721ca062c45cabc072ba4dfb3be0c117cf59b56a6dd4cea
+TAG: 62346b143e77affa9fdaf6869665f9c71e2ff4a0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660b0197434d19989a6897e07e70187d689e3fc5fc6ac7d877ffa9658334a948426614bb44ae12910e8bdeca4db3bdeb2530d45fd1942545c600cb5ca02f64dc3c15b9b51e407f57fe84c7312eeb392eb26e5b42c1fb9cb1259c5d0fbf7ea294d03ec533e9a211e8c5346a5a9d385bccc7f7328c34e4d1c942f433ba3e61
+TAG: eeb5a8c64d5bb82f01b71bb00691381f2e238867
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660b9a7e0dacc1d36446a069a49d4af21d90bccf3f9ff8d9618b9b59e2c125fbae4df5d8637b272ab5fe1a4cd26a39962fbc34f55cfadcfe55ce9312f0ff3b92783201279cae52b79eee915093aa98620cfb307b76ac56a5ac25775fee0da9434095915e242707d21b4d6303b28286342bbcfa87d2fc295c91c1534560d2
+TAG: 0cebb057d0f801d67c136f21aaefc493ac919f9c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660b1f7d0a9c3498902af83ed335896b05946ec1205ba0b9370df237eb1eafb85680f6c9b010fbbad647d780e60b91682d88e48f0132dd4e121c95008954fa0becf2a540fee081b0b571eb64b85a9365da9670c9e27ab3d7e4367af28529d9c5c45d024bdc4cd974a797010124bd2576280a5fdebfdc6bfcb841f6535825
+TAG: 1e545264af7b56f0ac1686e4480f8833eacc84e7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660b341d45d6962b179c9e018b5cb775576a59bdc11d4da51fc25615415901b3aaa7397a6ee2a94ff10267f82bcb466772680a099a54ea66032313b7ca8fead7b4089c3dc9368fb9fdd04db7fdc2bc0df0a0180b6e2f2b66edbd6841478d5205b2f4606693d9f196805788e6a64179b2c30c7a722379cf5dc466e99d0b71
+TAG: 382a67d4e999deb6a51a6e76ec6607bb4a12f21b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660b0564e0607e6f3d56d977c8bb9616291f989c024215e9f84ca39b7a67f86337718f88714d6a2ff5ee009c494cba00d6ebc4db062b599c9d685a1eff59ceec8b9dba2ed2d8501287d50763fd3ae5c89bb2263c6a58bedb5cf0db2a1f1d72883c0d49461b2ce2c022236087613edd7db5e283cefbba7209f70262a55bb7
+TAG: 015f26015677a98598a8eff3ab6150dc9da2f76b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660b08ce83dcab748ceac68843af80b9f6d7d9ed96b9b83f9037c0215fefae784694dbe9516134890292b7dc277bba8635a62edaa341c330a88f515a5a5c044c3f848ec6106f675c7ef9e0b06cb4e6cfb3a2dbba44c3f7a5610910ba09fc58cd3e52a4556125a4ae3036ef6ca98024fe93dbacca554bb54aadaa04a3b4e0
+TAG: 6614c2588426b1178c9ed3ea5eb0add1313a30aa
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660b97def10a8e08ad315f6b0f2cae4a8b8a221976d60720047575abfbbf13efb3f385751bb9f46b7d4326f7a0fc6dcc65365a093bed380f376d075cf4e2d581f8ddf340c4eea2b468641b7962a96c89edd265e74fff59be03a7c084b61f421d0f1a82da63be6a85265c666040264f5cde98720965db81909044aa2b55aa
+TAG: d9712773a708be8814a2441fc1cab524f0276f4c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660b7c9e8e052dc1b081d66a184242866027871cbad1ac742bded180b7a021c783877f1ca7ff90cfb2d3974fb0f03454949e0e91a7545e1dbc53d6bfd4a04ca6026ee7e723188cef7c8714a28416cd6dc30a8ea73bace6ecdc48c122f5ca7e356ff34568cacc4759149d82fd4dd6d940f8d710493257dfb39c21524a0f96
+TAG: da9d1c395a0f3ba8b53e341f9714da8464293370
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f9024480e7f3595a331a9faf154c691cc8349ee7ea2e059bb7c4929f71466dc7955f1fa039cd14b9d10fa2038b3ae9bac299c5577ce29eb8768d6c810d272231dd8e39bf7ae17e6b7a69ed35c37b17ef8d09eb8971bd8bfbd4d43456537d5e92986b43267645b92b7c6093bbd
+TAG: 7988227d5c15efe135bdbf1f5745b7413b5f672f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f0c4b7471d3b38e0f13757722536b094fe372c50cd7993edf462b749f360fdd41ca336b4f9bdd74e09fdca30e553457e8fcdd0c593f96f334bd8055652c5b72c06642cf7601665d675207f713c6034b19fb7ffad3cf1be4e904d86415e2292b62a88f0c14824b44c5a187ce2c
+TAG: 0313ca6c63fb908e9b5c8a7dba47c9b77963a2ab
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f83cfce0324290f2fe69a0bba000ccd0bbf0843805999b9ad08c774a9c3f78fe9ce887b26095dc4783475c5135f54b692704d09b4c725153da01dfd9d229d9d560789fbe180e15f4e01f10381bec7b7ed72df3bfe3249ca57c5905c0953a5c81b7492b648acbc6a5fca2ef844
+TAG: 2d332dd8205fb5fd3a241d92d994321747de113e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578fb82583264c4849c68863a8852173948aa8cca3e8fdba9beb354919b8d0033f25a218834ac5782a4d71576abc65b8c5fc4bdf9181184cf3be072133cb454d6289da0ef69a975bc89c78b101ab4b3314be32caf20690a65d6a53537ab0fb8b1e4a41182bed8cc77f06525bf4cb
+TAG: 5ce5d83e44013c07e2b7b47f8e1b9b23357fc66c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578fdc88e739c56adfbfbf00cc9dea357fb1e46e085d0d6fb1b1b3aa720df8611300cc809ebc1530e3573eef7dbe8afd7e314218de3d8948724d428bbaeeac4402bf0f6ea8c5c9b01f5e7697d6fc48e336255ddb6a950227f6a0d36645b699c21eb556ff535c4052a76177cabe62
+TAG: a4eb63a7ff2ad407a59dc7a11a2c1e21b316989c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f07d6d75d8c0f83593779f62fd94394c9e598d666909d10bd22bd490275f846f4ccbde264200d8e87140270b7c6452f126eab9a0e59fb2e3dc2d89c5bffdd099003d3dafce6dea8d9e06a4bedb00dfa8ceb012f6a2a203bf639b3902ef7b4ffbe12540617b0ffbf1c05345d54
+TAG: 59817bd08dd6ad2942aad34d00ee52ca8e451de8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578fa11a4941617e2bbd6541da23102fac46ddda067a9bc483791fb98dc18d42b1824c9f977ae7dd7de1c4985b69be78ff2c5e30916520c1a393407a314ae941f399b724b0b3c228d298b2234c6ab2572c3083f40ad7453fe345824c5c705b13cbcc213a69033aadeb661b3e2f8a
+TAG: 4f7283353f132b82efad331fc3ab0a37fa5eb3f1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f4dd8b7673190922d0ba6e5e70d0859a187d2772927f020fa92fa1b5d02996715533533d03a1c078bcacbdbfd0ef45f69717a9ed300cb8f3f86e0284a34942ec36c2a31f7f2c7dc2decba858b0fa7254c09043ef902fd4591583dec52c4d0f65155c75eb23100a40a93cc2650
+TAG: 70fb4013e3f92d51d31243d047194f13560e372f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578fd6502b6b7c2b8d30d3fa495a59369deffd6556855a70e35c923b219209fed6998d477218e49bd560ea8cd37675519dfd3eea726b31659d7acb73a9f2ea64f3606e7301a39e1470fd12820bb4a751a78d2be4463dea069fe213ba9a20a45bff3a658437df928b3f5974aab550
+TAG: cb388a5d376e8356c27bfedd074e8a2504b5ee8f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578ffcd08a482f92478eb055a564971b447bcd46f9ac4ef46705375e1bb379784d00806350513a1b09aae73a667fc3ba2dc639a9675c471cf0cfe3eae93f8bd07a118f1414873add1de1f872f5b853ba1bc975310f8e395952131faf7161fe8c234dff6cc2ec119cefb73e8f14d6
+TAG: 07ea650b9fafb9bb0b1dbf8391ef307487c3bc8c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578ff6c1a9cdb6374bb15c17d94b699949c0eb4358a3b85d253f540c7ee527b97ed593382b94de85503912d9d760e355a067c1afadcf6f5791211ef552be8e8f3e22c31ba46cad395c8116ea2cda7baa862e1b6ae9eafcc38162d8cf5820c2eff5aaea99928a2796f01db19d4fb0
+TAG: 0f3726fe84cf6921ac13c36c03846b18dbf5e879
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578fc84768fa7077ef199c564e34c97ff2686c601165363458c5ba3719c201dbc1bf6f97509d665751689c0040dcc0dd8f0b15f148f6f5ef1a402ab5c66f68168524657e7d6ddcbf36171fddc2e07feb06ca715b96904d371336cb43238fdd30466658ec48ca408cbb06516ddb1f
+TAG: 238a71550e31f443887a8f0cf63c00f059f5cc98
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578fef0f38f2cab759e8eaf59ac6ee15d9be7e9d31dbd13feeb4f2eafeb2e5e2628a0fd5ad3368f1152717326d870e7721dd5f5bb96fa7c5fbc7840dff0d77fdba333195cfeabe410e55ca2e5d9ceaf18207761ea6dfd0747238a8dd5305229221e53a8e88f95de76716fa82329e
+TAG: 0966c6a298e3b4afdea6bfdb373c760a93136ee9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578fe7d5307d0bfc04b83f02e7d60c18be48f9804f2baaa78dea472a9cae8428fbcf3f07634b95ec3480b5fe93c5ede45d0c77f469e7e5b0ef77b999acc6ee821c23a0599d00d1fe52a5f685fd087a5c3a0f6e23e4f944d68bd8474123a7bb8fe5ec3b13fbeecde798f1c79a419b
+TAG: 4734b4931a6a56dcad75d24410862d268d159e3e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f32d4c7ea4a934152d38a1ee7b994c91206eaa83b2412eb0ae998f645642ccdab2d8ef576dbc56b9016e5231720b4a7ed3cbe679803c9b8b5603d0463bed397d1e22403ca786a2d51ceb53ac850b5c238b0532db9e68f7648a6c909235c8f9a4e94cadcca9f3b07e133669903
+TAG: 33b6a11574c10af87e190a8848fa4f2e71f60b72
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f20189a9c926e56beaec19b09c2878586389a3f3f36f123a23835e5dcf9d75ae55b164fc2300fa19499fb0ed245c7fc124398bdd43f5618b9a7105ab37d6812f3aefa3b602c0377d7a7257d2df9332c215525e56c48a00ac95d7d0e522d7532de30de97b9ec2b9239dbf756
+TAG: 78a657cc9143bf1f77b0d3a1d2a552a5d35b3e3e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587df8fa89a7f422a979def971894dee576c3817b3dbc6041cf5346a3e499fcd92a061cca3cc3df536480c635d3bf4fcf57c01a1f05c170c3b10d2e24521da5dbeb623d4e8bb6bcc727ce14277af3130460d862f65d1f16c8cab4c7fba0f
+TAG: 34b1289aaea780e6c5e2c474a98e0d7ae596eaac
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587d9f66ecf45357a97aff91111a9f96973b30387c0becda57d16e898688e7deb698475cd317c4e3703ae996cf2e850c3a6aaccd66557458a4d3df6b524f8a8c596a957c2dbc9dde19aab275b65c406c36ac315d4f29294880c382b2d73e
+TAG: a20a4cba0d8a06387ac6cf9fadce71eb03fa806d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587dc8e944ce3f0a907561e7c56c01c8dd6aaad20d0d3ee101ef48b10996ba84737499fffe40d0432e6f65e44ddbe15e009653c5165fd68073da410559895fa53e052d4994346c4a4702a9f40fd24a39886a732a30903648f3aa27d48097
+TAG: 9c22b2781e1ed1eba5702ed7656985a55f10a11f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587df8e72740f184e517fe5aeaaa404f48edd1bc3f0c91ca3d86e332ae57c6c4669e531ae90e7aa7cf1c4981447cd5c357ddf14144ff48d008a49d4ffe09b3c597c45275adb0444d992456c879e99091d876da2696de4d7decf220dac095
+TAG: a9c4d28fcb1a04807988d8359bc28b4452cdb12a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587dbbdcfd2106efedf501222831a2b3bc10181d3e07ab5b8cc590e844680953e9d1ab866c66c804d4e26b94a6f7b48f1b4fb36cc0fdc2bb11154a77e4558059fe2a65ec7bed298379ba7f6cc3be8b05e4d23ae2357704b38dfeee1dba8f
+TAG: fbc8ed0ae1fa836ed244f61e880809410a7b3f63
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587d87d109a0f755ec95435336df47c8b3e25ba96c2c76b1a507a8fec58043a18bdef2e8bdaefae090a63821451250c4479b3e9ccd4c66fe0ccdaa99a470e974b370152b4a57ffade6b76c1ef796c6ae0c3103aa3827824142c0121b635f
+TAG: 41d8c674ece4854b96cf668047418f728e20944c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587d8f3b7030346508951c6d7257bb5d564ca0065fa822e9848e4f5f1a9c97fc214ffdf8c3d6cf310edb0b8ad1706fb1c3fd3e405d8112644aaf78ee48698ea8c77be5130924807b56143a8d7be68bee5f7b43aeee3d17b75ea6b3a5a834
+TAG: be4e801c8f905fc179699f16a9140d14d7103088
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587d9265a529e12dd046d49fb2808330d973cbe86c4da2bb4169322b50267ae89bc4f774c81ab088b263cf31b5c6990a79f778a60472d180cb1aee8faca1320412cf956489ad7f0aa08ac38c7c6eb85e9ec77af32460e5e0186ed3581df2
+TAG: 87f57be6b895cc71fb8b7b14ae04459131a45039
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587d88d391590dd64b4d03bcd8b47c96c9da55b60bcc1139e3de3ff2b569c4430308d39183df112c2d175227a67d9ba1676c4b9dbfa78c6b86dd1179e0fbfdbd34f8532da3bda9d7d1251626b639aa8b8783436cc51c59d7d6e0c0573fb3
+TAG: 550ebbd7a600529dbfe9feec4c077207bbd9cf9e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587d906724106fa1e9e896de3ea111782edffa7df147f7474faab3d17bbae61ed5c3e8582b69e58ee6eec666626c7d13f744b1ce98f9ec1616b1c8c3232c275a130bc7f3cf89aef944a77d4a36b5281d91e86f169ccd648ac15afd8e022a
+TAG: ab778f8b32dd5a1e105b5cb899ab31affffcca9b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587dc25b313d2fd87b6f680c74a86957395b227fa26d118214f500a481d29bd3f94764b3968d12aa178232316fcd2641dd2f890cbc1deef2757b8428b56d348c4a71894e0dc5d5e48560cbfe9666b76682215789bf93b2a473f1deadca12
+TAG: 3175e5a8a2ee4536646f301ed83e2db6f1ed2a46
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587decedf7ce497c87391c81504e47a19a697352663e9fd63404b12f88de6c0826b1c9244f36bafab6f747a7a0eb151de798ab14b8814babeb70fd2b16b46151c2da0b86826d4ea25446fa06b294cac44502cb63d35ce603978d0d8086f5
+TAG: 96d63bab5169146ebab6334cc9602b86c8a451be
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587d5cfdd8c89ce1c376758f034682ec46a58211bbfa91b81c04a44b4abf82de6d957543b1af4a6c430f79d0b0d930ff7e862ec2358f0ed585e8a0ae0ef7bca85f2ec1dfccee52b059e1f925d2f92c9f14a64c082b902a224b878425e4f2
+TAG: 2e9665c4ef2a9ab17093fb1ff9c8f3faaa671527
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587d62c6da0e9a8aee21bd8fd4e92cc0fa29f2c6d17e84fa8e4d02f147594ddb3ce3de96359785bdc991805605c8f9324ce6c4664a025166fcabcce0a495c5f5ab7b291ad4a06baaa54246d4d31624b01221e1df8cba939a4d6e931019cf
+TAG: 15aa2652a18093d9beef5599b0b3f3f8819a6255
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587d87cefcf6a5f4ac67fb0f322dd7d1137843675df128646e8217eed9752bdc96102f3e71c5b236451293e201f71941e4edfa7c93450f74eaa1bed5a2a6dfe22ccf3f6eadac1ab2da6954cb446f60dd323f3d605c1f6e97f3ad8e942a85
+TAG: 6d799b797d7fd57925c50c2c092a37463edf8575
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587de9ed0c049647015656192931358371b1eedbf254e943bdeafea672506dd02c2daea5b7b09f9473f0e5881ac8718dd1c38b33aef02c98f9aa6fb415d951d978c426c83a68f9f7e5f807d017eb1bb9fa54c23970cd2a08623cba60885e
+TAG: 7a7def1775531fb7cdd9dc46f53e4d9ffc82a457
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a05ded97c1fc8b54a4bac2b4e32651956b48831a2fd19ea5e4407f7ee329314696d0179eb48c2559e48e9af92f15f349c905ecf5c996fdedde6a26953682c9d0c956dc72bf0232bb5568d8ce5dd
+TAG: 1313873fb797bb9d64ea74d92bc2eec776b67c18
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0553a443da980d6169c0cf23b1481966d4c10f50411fb81a76721b20fe8959aa050f4dfe7d6b023c7afccbb481d33e3361b44b5582a7a807820177dd8ab03912ea6853938395b9b9ff3a44b822
+TAG: 5f915d4ba051bd8d1301e4882969441c186c6482
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a05cfb17cc0f69e2c94f7c1deecbda913caf6934d0d6b3ec1672f4a701de5c2552bf266af5f80929b1e960c20c113797c7db93f07c6cadc979890505df512d90b07f67d110dee056a9a551e7270
+TAG: 4fa801a969315d0617609d43a3dd18daa63f3c7d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a05c937ffe1953a2dbee265aeedfc5ff5dbf4e169626edcf99179868f69270abfaea56325077547cc84dc749cb3a0d2477718244b8bd8fc7c2709fe201106c6cbd9eb2245ef49a2ca2d4fb30eb3
+TAG: 90dfa3d195c0168003db086f458df74caf165ddd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a05e03426e741ce31f80c4543761287474241f31257f570a909e3f9e628b92a55d2a2185f3fe9233e170293c594fc08b76ab0c6ff7739f15c1c4d795a1713caedd38843f94ff3caa44955c923aa
+TAG: e68f2ddf43ebeebd70df8e6575170e5f9cbdd7b6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a05cd83e9f7f2b4c5e25b9034e0fd2c127cf864748fc22c5f11e671a15b058409a645ecbbb146ffb01cd90d9f3298139f7fd682f49fdd83968025ff277f46991ff0d8ce54f0b9600d47804f900a
+TAG: 6c051843cf978cbb8e856944ee5b81e01b5cbaa3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a056f7652c5ec8189a961e4a27cfc379a5f3abe6f1f2db99c1650befa06e2cccbbf440ac41144a51e0101c7b8d9d4ee435b36a10f4963fa3f147929e4973ac3790ed8b8832d53f9fc1f1674a4ab
+TAG: cb7440d87770599a303ab17ebcff5698c862ce5c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0556d0825a604d9a99b924d56f1c77245a450377418bd79050d66b520d7625f46927d99c4ca49a69070e44539034de23eba02b7f934f440cddbb73565e3589fe0472a45472d01c65ed98654639
+TAG: fe649323f645dacd7aef72e923d27ab60eeab0ac
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a05997619e0f127e299a10dc0a82716285a3a7c7c73de8a72fc6117462f916d9f6feaa37203c5febb313b017986b60cccf24413598db6165c8e204ea8fcba8cdca1c058bef590c1ac45c22e9ba8
+TAG: cccfa8e4b8a4cd7c22a2a5af9013b59a4acf0919
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a059cb80406467c6941845f4bb8ca7a346323b566c0f2b2084de30abd746950e94e5a709da648370229d1b22d2ba6a0fcfeabd862e4c3f4a13d23442df65f3bdef90d5675d67688bf7056fd7fdd
+TAG: d26a8f91d155dbe5d9846f515dd94b367387b29f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a05f53b4c8646570adf3fa450682e44286d3322e4f2c7d363acb8cf198dd5762b9c3983dbf9c584da976c5d402395f36265387f13719af53bdf5d5fad9c3c6e72c14248328fb19d5b835e676494
+TAG: d9be68018c3e20f3ab44dd8fa4b77dd2b00c3fc4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0524bfc5aa0a54923efbec298ab914553d8b72ca3b98e24cc21aad610e832470d505370b4f08d3e5a9f1219817574b2ef2b5e430a40f4f03f21320ce39bd400c226a7c78657169b4d101ace0c9
+TAG: 5f9702562980f5729507fbc1603fbae6026df2a3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0593d15024202717c4f85a7023c1d7bf66107d1ed44b0fd8c3ddb634f714a004d3c151d1a8577b43305fc3aa144f2c96db5fe0ee8e12c76b88b8fc4df15e8763b186facb7fbc11da1c0a5f6dcd
+TAG: 3d939e7c9cf734001bb37cd95a2809e2cc8e0612
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a054c8989c55cd65d9bc8ba2361d77c9d72fb8a5321a51f0f1b807fa1f523eb611e8174187af495f506e32e43b741bbf6f048c572b50fbd03b613d37b6071a92dfceb4008d18d8685d3c1c96ffc
+TAG: 25f610543137ba776c620717ba84113e8c77e017
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a056e9f3210706e32ee873449d161601a609606f5cafb9c25335d31805d10350507a72221a05f275f181808ff0aa140ebe1bd1f93f60509d05cedaecf019477fb11ab2e488447ee47501c4014e8
+TAG: 1a3a18fbca2becd9c58d5c3f7c4877284040b9f4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a05fbddb91b949b0194b67641ea0da8a9a76ae2451a1456441eac4af319fa4558a202bb7b777fd52789ee53c6c7d644c2a8907b573c92183b88ca573a7acb879fd39b4f587254850513330c1fa9
+TAG: 36521b9f3c0eb3f813e74d09368ee7ab2340eba3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628cb2288d49e057d5b990ef03cdd0bcdbc23b71c37e22a5373bc819df09414356e8e2e988eff54744d8215af506b2857902496f6203f3fb298e8a574535
+TAG: f48593a3348a2ed64baabebe856c2b650042e17a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628cbbf3d925ee166f3d2eddfc11d14da05ce4d764e987d25f748e1a84c8f635d7a7fa33efe19a4d6cd47da18f4db269bc98b39e1a0aae23067e64eb9265
+TAG: 696bcdfb58a955c6eb4bfa43429705e6f94223a3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628c42c06527d8fcd61e406f1cd6d0c35aa406c7727d109882728134f5bba62b91e5406b1f2b99bc1f3e25cf96a404d0fb607b4ef0c619caa357098b9a5a
+TAG: 63b2d4bbd22873db2268cd8f294b0e623e7f7cbf
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628c0290d069dde81238fedcf1d8e7740a0e1275821532ba4f2548417738285721968f273cc2255ed076aa02847e8f6f2282fd8d2ee7b640b9d12148b5f4
+TAG: bb5c13664dfcf8ea3e8e01c7302a8c3bb6575530
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628c1f825e4ff049db3ec69e4d1b35df9778313091fa6fc814a5d5346e3c9ba1d06e0ef2e2415ec3983d826b4ef57d5d667a88ba9551dbb46a1151733c2e
+TAG: 7f3f976d116ba17c3393f7667cad82389770e701
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628c770b3c8a0875c243cd3877d299706990b1d7358a1e1a8eb221a93fdba00e5474a2971f3f1d45c86b6505fb762a4f2279bb8b76a3949b9f84a9b588b5
+TAG: 4c9c03082b228138238a8b8efb7410cf96f42e69
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628c4a8e929baa0e3727e4f50a5d9e5b032cd9dd15a8f05ab273e927ebc7561c03efed98a42e94d6bb85f822a5685e698c603418652c40e9fc2913a380f5
+TAG: 1e3ab70a09c903722246ebac47c220ea3b877498
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628cd01edd64a1695906e12fc1d6f6fc9b2d6e2fcb9ad7d2d9bc578aa268de37c7fd4724210031b306355bd1c40d860d4200cf96bc7aec7f6bd6122f2bd1
+TAG: 8d043440f0c325cd84d4dcc50e4c1069de31a7af
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628cd26cf677d9c112a87c181bce54de90bc6ceb07a977b86917829fa4f22d49fc0416af392d328ef5b333ec701c61cd473c9ee4488dfad31d3ba39ad08e
+TAG: 3f3f38bfd8ca408491263c5cc9947e0dbcc5d564
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ce23a8955f3987f8f93f230cf7fec4627568e0db88428fb08d0200d4e8219e16929ba1de8ecadd95ba136dbfb92bd51a173886144a3bc0ed31d58a8c8
+TAG: 9ecd400a15362bc1bf71fff316631a98c24a1f91
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628cfc26c95ec2a8158b452767384f6ca2d50a771f864e90a4b0893cb3a59e99498f411e5605f734a43acc0d536c7f610e187016712b2d7c85a7de09f9a8
+TAG: 4b3c6ab41a72a34031853ae425c34c9432cf096d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628c1636de859cb485de7eac4ae25e073e917aa0e9ba870abde16542d294f9efa4538b611b5289f9440d17d370543d11f4ad9a25a55b0273279093a082f0
+TAG: 3085353308bb9818a60d967bd895a00168b66295
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ce68d0e9a656b633696eafde704fa06f44d2e6049f0b1fd23aaf11b755427cc6a53c36331f9e4029d2ba0a0683a3ed393ffa2a11afc120c35c9ebef64
+TAG: 83428dd3045517e6b7f2265fa0a067416f5967cc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628c146b5b14f1e03a6502cf0fcdac6147cfb1f3ea361229bd6e1287fd0d4e51d74640fe7e4682ab27447d26471e951fa24464fab2d94f3d152c21e6159f
+TAG: d4dbb42e460a2af855dceb1c06999aca8c6a88f4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628cd8a2f31e805370302f45e6c7cbbe587ab14a3c5f2367a84a60cae30a2569b398da263e1669ab14cac9d607098f5443c4780abe58d9a7bc4a47c680d8
+TAG: 4d395f0808aaa81961a79ea7f693c39d72a2e5d4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ceb2c2ba0d80d63b3549983ebaae279994b7f62abec11ae6def3fd8b8b160e292a818784694ed25d2c70e63f44a7d07c73a63b1a89a966cbe026d72b9
+TAG: d8ef8963744b510c0a9823c982ecb3d222ccbed2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b51b10c8945d78f16a9dd1fd55006ec29236f88f806465d9ba66c80da54eb76f00705f0fc7d3f048d3cee163f
+TAG: fdd5735803c263e1856208f47deb40e8b14d0009
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b73684663a06644594711095d78af90f7070a108adc6e1e98a8191de62ec0cf477088567861503a6e040aaad9
+TAG: a578139f6de9b33cf2dd3657f487706b34e7206f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b0ab04761d5f9b269bc8fe1f262472f25f5a0330bffb86548a1275555678c617fb536284a0110e192b7e22889
+TAG: 341a07a2e8e3ed07856d201395d838556f89b581
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b8bc78f53bdcf2d660c2007cf1a4748559aa92e19daf13013853fb9069304342ac38f51cbee1a292d01720610
+TAG: 614554b5e0a40c1e7b32ee9e1ee81f3cee2247d4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0ba8221659bf585c5de42f4931cdc69c6dddd76377ec1e546b5e9c21a58c1278ae635796e6edde6669844ac002
+TAG: f1d43fd25e0d8097cc1ac61e34929aecd98fa87a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b305a245c1f92a1ed6d7bf7908301c857a6fc72a5ed3b95739064a98de16e6bc1304a75061b864c3e88fe6b77
+TAG: 378c79f9d1e8f39bdc44723980971673c5a3da97
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b7696367cca042317e9f9d027ffcb9040a50edb5a1c56d1fac08244984acaf1a4d57388b49dc76caca21afd37
+TAG: 381f175137af2f328cc5c30e355dc2e18db4564f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0bf9b0d907620960293b8cdbf9d2282e3a7deb53ef1de79ec8789f7c98258ab6469ea096f3161a022945947596
+TAG: e5f65e630559efd0939649a6141eeb5a040a62e9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b567a5cf87c7495a8348c4b5556f008db93260588e8687167dfa1d8b65fd29e31e88f9a232318e6a53303ffe5
+TAG: fa5d0df1fa7727930f738be9ee7dba2c92a0c5e4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0bfaed61243b8a6879ea75838b1836d53b78735aae0f0aa6e3d7e177f157abcae34e37b20b49502e2dd2fd8df7
+TAG: 347b5d83786a69c361ed4c6e8ba0cbe62c1e605e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0ba41df8574e34378aa2b3adf819c5d5bfdc5509a176d6d14c542a7b1ebccabe4abe3f4ab04e3d59f59e5c9349
+TAG: 067e610373a072ae96518ad356ced78d17e133b6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b76c12d7243959bd7d9c753d86d5199e266f0b4874ef10aa3f70e860956eb969e1dbebc9df4edc0a501b6f0c0
+TAG: 93fc9fee263f058278955686168c7b54abcf6c94
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0baeba077bef16c7c97f918ea02769424d9685106645892c5c7647ac197d95e927bb28a5ca19403277d6b3bf15
+TAG: 26c6396b639665e3c82fa83ef24954bbf429c0d5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b6950b8dfad2aade609ccf70bd1d280376e37e43497d9bacb7ada092662ef73211c59b766536160335de85475
+TAG: 593119f83a6fc3d30bc43a53f591970d048c62c6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b77e3d1f43296c6e6e53cec2eb98680ba8dbf4a139cf327a6488dcc735d43dac3734eb21207794026da1372a8
+TAG: 36252fe9de4b3cade24789fd7690d29c486e2c11
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b75e20c01d5978213509c504e4244b105e198cfd504f68e9213cc5085fa9b337c831703b809a739246f8f12e1
+TAG: 75f1bd5ae9fcccaf90ee6506769be1730deadaee
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8473ad6d1f4eed43091e4daa75706ca799725097c673e16f259f5e16855
+TAG: 4909554d22160040f3f980b25108eb1074dfafc7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a847ccf8b218a8a29a08ab0defa33327185bc9b1618f357a13e51189fdde
+TAG: f9369d137cca6ffc185647668ba512b50b1973b2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a847ecc467350e3278280d6d28a8a2d0602f58ac7cbbbe0da2bb9960ef3e
+TAG: 0125f9d5e66c04fed81db9c091bb8ea10a2222d1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8476d6f59d786055e744adf8e91cb27f1ced14263238c378e00e453ed7b
+TAG: eca030cf3406df1c5fcf8f8cdfc255564fb604ba
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a847b05a56b3dda561993a951727764b15b9798eca0c1fa3bab51a742b9f
+TAG: 78c7c0a18ed889100e6ac4dbe87b5c46cb86730a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8477ca923c244e238893b64d2a822ef601bac688e2508b7c7d2458b88e2
+TAG: df570ee5f62873cd9ad4f263795509eb33b33a4f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a847f1b161bd08a7623ea9c3894692bd2c3a2627a0f21feaa32f589daa91
+TAG: 273b1605810b8f70ef841caeb26d0f699973d2fa
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a847ae865ddb9feed96664261da1d75b4a373ce94b186453b9b8e04bf04c
+TAG: bf1fa9f96cbfdd43e92d848cd594f86547c02af8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a847859486948efe59d91dfe73622da608d423606a97a56fba7b60a62f39
+TAG: abfe61224cf7de0375cbd737e7bacffdbd586f51
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a84726b967bdc96872352e2009f5365d2e5e76c3707754ea857620969daf
+TAG: a879af8c10b61dbbde5bedfb09f6818d822fb057
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a84707646787434a7fa82134ee19ddfc2f7d697bd00bdfa471856f2b4848
+TAG: f3628094cf0c47e8566ec09e89435ea2be12005b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a847bd37ee3bd0b0250adc384fe1ab65ceae9d9c9cb345cd50fd465290fd
+TAG: b80765436228767aa6eee96b3bbf9d0da2a04ba8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a847048f3cff325ac376948ca61a70553086cdc0fe4592c5ead9da920f49
+TAG: 6954a8f60c5110fbc9d5ebe4d3ee50a958f4dc8f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a847df91606f20763bd20d58c56f645f3c7a2e032458ef8fd4a199fca421
+TAG: 8ba9d6c1829fdb04f7fa4f8afa6b549d6c588de9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f747582a661353b7da833138da5bf928b0a636da39224d58c27d196
+TAG: 9b72e0a146429b86a07ef81973e80f632ae8bfdc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a847d7f55649c875d8d0489b72e132623b22d6b02e4dbf5a3435e9d7efd5
+TAG: 054f6191078d552b2a05d45a158e65a063a06b8b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f6c5078d15ec447d297c5abf7d73f76b3d177e1ebf68b19c25061cf
+TAG: f75b2f11a447d65370461330efb792848bae4a33
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f6c5078d15ec447d297c5abf7d73f7685c8212de575f4b0c415a3f6
+TAG: 0315c004965a5afb6043292976397a30f891d78c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f6c5078d15ec447d297c5abf7d73f769421c7e5e3b1f62717415c6c
+TAG: 52a6c26d4a5cb92d9beec5f313a0244643db4af6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f6c5078d15ec447d297c5abf7d73f76b3e2175109ad906c37be473e
+TAG: 2e0dc6687a5086796b8a0b5ce291300c848e2294
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f6c5078d15ec447d297c5abf7d73f76f2816d8b131769c91a91c446
+TAG: e46aa1dc9074515bc989a55f1247682558ed1b11
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f6c5078d15ec447d297c5abf7d73f769cbbeb12e4c0edd08cba5e5b
+TAG: b57eb2c8a6af71a3779bb20a6517d90728915770
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f6c5078d15ec447d297c5abf7d73f7615e866a2739f95e101f0e9f1
+TAG: 494a181a7ac11a5e33d6c28e51a8cf5dc75194a3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f6c5078d15ec447d297c5abf7d73f76cc56e4424649ec5401e1cb39
+TAG: 0cd2f5660aaf11745c74d00f89bd5ce09482b760
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f6c5078d15ec447d297c5abf7d73f7623f703cc1882b07a2fe7ae5c
+TAG: 433b12252c18cd7da3118e68cd2f54ad6594573c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f6c5078d15ec447d297c5abf7d73f76adcd77dce57016c70ae492dc
+TAG: f4e569c72ce377eecb95717a02536b7fce3afe80
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f6c5078d15ec447d297c5abf7d73f76e38b9bf9b9157b15be9e63a7
+TAG: 2497affeb732aa561972c30ba2042a9c2052ac3d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f6c5078d15ec447d297c5abf7d73f76c2cc20a4526522d1fc558fb3
+TAG: 0dd2bb1d36f674ea4348ce529aecb610ce17d725
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f6c5078d15ec447d297c5abf7d73f76837d5276a04448081f4a30ad
+TAG: e2ee49a1a27ca1339452654f122d3b879552061a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f6c5078d15ec447d297c5abf7d73f76ec1f5044f3ef8655ca98f669
+TAG: 70bdfeeeb4ac4452141e77183719b75c29068300
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f6c5078d15ec447d297c5abf7d73f768a10b58ab800901730b35850
+TAG: e4449e69a56a338c22754caf1975450f389d634a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f6c5078d15ec447d297c5abf7d73f76c8002d1c8af0e63dd4de8e03
+TAG: 8dae13e10c0e8eba36dc6837222351586425b162
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f6c5078d15ec447d297c5abf7d73f769e9f260ab3f4fbbc53f581d1
+TAG: 93452b061014bd890cce4df789eef73bc3d7025d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f6c5078d15ec447d297c5abf7d73f769e9f260ab3f4fbbc53f581d1
+TAG: 93452b06b7153024e2bbef3589ed4b80a3d965c3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f6c5078d15ec447d297c5abf7d73f769e9f260ab3f4fbbc53f581d1
+TAG: 93452b064d9f466e6ed89fb08dad714f363c0cbe
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f6c5078d15ec447d297c5abf7d73f769e9f260ab3f4fbbc53f581d1
+TAG: 93452b0661cf620009e77542b886e881bf08f38a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f6c5078d15ec447d297c5abf7d73f769e9f260ab3f4fbbc53f581d1
+TAG: 93452b0612f29340400a1e69897c0852cf4e210d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f6c5078d15ec447d297c5abf7d73f769e9f260ab3f4fbbc53f581d1
+TAG: 93452b06a625528a263a37a14013556113dfce51
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f6c5078d15ec447d297c5abf7d73f769e9f260ab3f4fbbc53f581d1
+TAG: 93452b06f90d159b2ccd770b53783681be8a6f5e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f6c5078d15ec447d297c5abf7d73f769e9f260ab3f4fbbc53f581d1
+TAG: 93452b06ea53ca87e26c6dac81fe70f0a5efaa17
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f6c5078d15ec447d297c5abf7d73f769e9f260ab3f4fbbc53f581d1
+TAG: 93452b06d71ed6942ea360f3639dcf3db58df19d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f6c5078d15ec447d297c5abf7d73f769e9f260ab3f4fbbc53f581d1
+TAG: 93452b06b65a97fdb3b21631a76662be7f672400
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f6c5078d15ec447d297c5abf7d73f769e9f260ab3f4fbbc53f581d1
+TAG: 93452b0618ccee5e588d8b9ca226876a76d13a71
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f6c5078d15ec447d297c5abf7d73f769e9f260ab3f4fbbc53f581d1
+TAG: 93452b067dc170d5e05461086f1a390ba7fcc236
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f6c5078d15ec447d297c5abf7d73f769e9f260ab3f4fbbc53f581d1
+TAG: 93452b06865be6e27a8a8e8cf9fcb846caa771fc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f6c5078d15ec447d297c5abf7d73f769e9f260ab3f4fbbc53f581d1
+TAG: 93452b0616474e8107b7870cb2fe52d1244a7161
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f6c5078d15ec447d297c5abf7d73f769e9f260ab3f4fbbc53f581d1
+TAG: 93452b06122647310b916f95a7123fe0eda40cca
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: cd8df431309589084bfa5bcce99cbe08433cba6fd69fbb3e22a492644f3dfa7697d9bec176735e241721025b158cf6c3158503d5e540f784482988db925b4405a653ee4405ad58b3103d58a59a90d5b4d8b55e9c581134d6c522a7e26460a56772b588d8bc71dfa9557bbab24cf8dedde5489673baddb8eafc0f9a14d885626210ca29a5de2d8d3cbf0321c2d4e048f22d15345d18cbb80a5db5b79148ff3d6f8dfb9334e83898157bfe610ac0bd660bb86a77573c13c22d15b70d9c531d578f6f66946e2aaec737057204351ef3587da6845db897482b878cd4e1d38e429a0534f3875f5bf0522ed0a984571af9628ca454035434c3ec11c2f2c098d264ba0b631695a306803bc2d432c47ca051a8478f6c5078d15ec447d297c5abf7d73f769e9f260ab3f4fbbc53f581d1
+TAG: 93452b0632c6d629c5482b71ebc5fb4e56590a5c
+NO_SEAL: 01
+FAILS: 01
+
 # DIGEST: 095a8f557f75cba8e2452ddf97c053904b48827f
 KEY: 18cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1
 NONCE: 
diff --git a/src/crypto/cipher/test/aes_128_cbc_sha1_tls_implicit_iv_tests.txt b/src/crypto/cipher/test/aes_128_cbc_sha1_tls_implicit_iv_tests.txt
index 477f1eb..4beb793 100644
--- a/src/crypto/cipher/test/aes_128_cbc_sha1_tls_implicit_iv_tests.txt
+++ b/src/crypto/cipher/test/aes_128_cbc_sha1_tls_implicit_iv_tests.txt
@@ -23,7 +23,7 @@
 IN: 936a91d0b5
 AD: d2c0267218cb7090c61713
 CT: c6281c1cd562c1935946013b
-TAG: 946a234257dce6ada126887baada8ee4e2b9f5ee
+TAG: 946a23427970932c1b21fc2d10118e7e685e8af3
 NO_SEAL: 01
 FAILS: 01
 
@@ -38,6 +38,2588 @@
 NO_SEAL: 01
 FAILS: 01
 
+# Test with maximal padding.
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd13088ce257cd6ea71706ff8ec9036f56d76c4
+NO_SEAL: 01
+
+# Test if the unpadded input is too short for a MAC, but not publicly so.
+# DIGEST: f0f82752a691ef5866413f2b2e5c1d0ebb41ccc8
+KEY: 7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9
+NONCE: 
+IN: 
+AD: 936a91d0b5d2c0267218cb
+CT: 9e23dcb5e3bb8c16fa099fbd135af44ba895a6ae14bef6699210bf0343bf9e03e529508c859dd6960e7639138e8ea271ab193ddb64ae77fcf7d31dd7a8ebebeb9b0653dd8f16b3ef5710d518144a2c546d8c51107f3f7075e04f2e68a2edc17acae579c83a11aaff0d26df7cfdb0b0afaf374a3fc1754ba9cd93e29e8ad0feef383b8f7935f81f15267c212d9051d1ac4762f6fbb5bdfff1e8c9a867add1c2e34ea839780de77041fee67856e2947325d39537f8bb915e4f312d7144d1bc3f562413c68c42f8c6434c8afeb973bf32c63f85c396852235c1791c0f1aa5ba74f3f176134d6eecbac484cddab9
+TAG: d14a94d979d07fb305b35d7fa0d0e57dafd8a05e
+NO_SEAL: 01
+FAILS: 01
+
+# Test that each byte of incorrect padding is noticed.
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97c1954dcb829d72bb8baf23ef37b700516a6e5b7377c933b949c8864144e8ca0a13b0280a93c2a42285c6548571cda2d857613c74083f722c022d9c90a8a51e981b3b2305a531d604c211cf27248d1d46d671ae76dbd1decadc684993e7fc444a9513d23c69fd264298d3231f205801a309953e41c1a2f6a6770eda074d640ad0887c7755227553fa929e457293bb11ae4b064e413997a21916331e3194b9abe91eaeddb8321040cef865fd2527d3dd14016fdb216dddf8dcff5a659d76086f1b1149c466c7dd3e72b08b7486ed34f7d1816db423c15112e865cb87fa0b0745d910b961f7ef02786407a6bc2f
+TAG: bc6a4e43efc2e1f5d34bd99ad853dce8df7db6ce
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca975883e45e6461c9e89c5bb5f912d4a8fe273a207df1f6bef7766b324fa0810688dcaadf5ff0ce0a2a529a359cacf6fdcd7550bd2b1573f9d2a24f0fa9fa24e16111cb16ba039d8fc17bc0a24fe6fe6aa24786e3acbfa9e54313c637976d6a8c7db48db3ea1c4a149da8aa42b8455a1ebfed371cb1ea287ecb569c59bbad804707d93514731816b9f71bf786748d4c473718cf4f3ee13c29e006840107022822c2f507a1a6552a394fd7c73514fe10020991d42fc7b6413756a61cd63533841aa556f1b98f6087a65475dbd66db6553e8169e655893af6ed6509253a2f5d1b1c71028931d6c28e6d2fa81f2b46
+TAG: 629ea8c1a911542d89b92cd354039670948b9d3f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca978990d885635bbd7814f02b2a32544be86b61160898d7e3970ed6aa2a6e8f6b112d27ccb2601e90a964bccfb169fe9204a3da3a4972c6496fa0cbd6f356e219d06cd6f17dda71cb5b916816934dac150184d65210276cebb5821e2738c57699f96691d4c19c866de94e9990844d547c083bd4d4642803789bf6f2fb29e22760432d8c87f0985f864301e034c89127f88c85a68b0938246e735a303259f7d8efbd8420648b74f1428b02651b9cdb61e41b85c5b36d735145ae5b91297a45325c72486b72d69df0f39f2fd75fc494410905c72b654717bbc7e10646e4eb353f88c18f2427efded0cca0f57708e4
+TAG: 123a0a9c4190ae99af97f03574a050a218420297
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97f653af6e4ae13512054764ee8d232e9cc05d5f9bb4f57d58a0ad086f8628387d0903332435b44bc5f824f0c797f2112a66347f604d1fb62f2916402d23bef65103ffec46349809ead2d897f1bdf388a5a054c696d176c57ef0ff94a4c587fd1e74c723473a15704a214a2889cd0d94d98950a324e46f1f215bc88ae34a55be84ae1c551260b0a61a2c39a322dac47bdbd5a2c4ce7e073f269bcd4ab7566482dddb06818de46b7d1c21a45262e93ff8aa2df2624886b335c1cc0a4023b976c91b4ed3cd1ebbc65cb0c3e786efae5e4748cfe94f63db5e3fa841a102fff74efc29b57a34e8500a9a7675ef3117
+TAG: 079904ae55177c649fa69cf64ad7895f3aafd12b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97b5d213334cbc15a12c5560a9a908cabf5b4f3a4f0e3bb0812e1487a1bfe6aa25769a90dc8f0d1766782607aefcc4249d04c6998f347e3c60123b99843a4f25b1e60b7b7a416c36a4c53b18957870a825b56723e553911685fb9b00a6bb6fd1659ab05cfdcce2da4440299c05f50b98114e08cf3925ef22fa56eb8e213bc6d7845b60c0a59e38c5eed5c8a46cf32c936f5876438797088136fd31237cd0685b2c22c670508c1c24936c1425e47cd00b37cf827fa153c4924a226059b37dc743688ad605d10ed0bc060e01b107a6cac6cd768e029adc9c986ab3f30da8a10ca4e128124b95264ace682d33f4e0
+TAG: 200817b26a83ce7ac8963753d22b595b7e23d54a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca978d9b855d162c28d05112f6cc00c06171bbb8889e9033513038331a6301191c52d4a7067e66beb0d09ec08586ca29a9f2960991ecaa6dbc2760779c04ea42e84116500bd2a059647de2273eed863d1251f3e9851c65ba0e96283ded3bbfadb03fe44fdb62e466afffa7ceb31d77e579eedb243c8228bcf7078e152453bf9651c35b9ea4bd633775ed31baade716b42e6bdf7360a870f8c15bdf3c7af63d229bc4fbe4ffcb706af3fff6dacdef024ff11acc2165e220e059f3cc14fe6a459d5f12c8e2305e7e579a61fc07220d2ce28c14ad94048d636a901875985465418b80ebb6334df62782e31774bc89ba
+TAG: 99fca83d2909ec4a754975b6b212e9ad78bdb6b3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97c15a0b8ddd7692280ef981d5f729b3ad2535f460de9067f891d120e866cd718888a864e293425aa31ee2f59470a81e5bc8a12af2e15e75bc8a8a7a7acf13f9bd1391fbfde54b1073c67e20715719b40e4fd6914b8f8ce40f3da18864f2f2bbdfd0c59702303723429f6f248a4f7a84d3e222bd74778e650da5a6d5ea3a23b802d3515c4d304afb1bf337b9102fd0bdeb19ebfc7c458de6bd0630e0d8b3c74d9b36cd991a5a406d9d28c56d8875f999b0e49a51cbe361fed9434c7ec4124d3905e5a103b5d73bfca98cf34725205ebc57cce68535c5f35c86236acc0c5928306d1b9333e278d3542a442c1e41
+TAG: 8fd4b8617f759b212a0ef6ebecbc85ef12bff8a3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97e3bc785d9163ff8117e8352a4ca7efd8da1de6e0141a2d3061dd5d1cdaeefe60c73f5f350437093f03b1fcae30ce628322bfbeddbedc3b9cf80cd50f4e4901a5d4a1ac05d89e150ea2199c7bdb68063785e3d79f1bc21e6c80787e638f062a920c59c591616fc437eb4e3b91b5ec7dec05a1b1ae6665d12fc8745dbc833ad1bdd607964568734b554ecbb21af226eeb7f33d2a1ca817c23a73db11bf8c0cb8eec5261669a8170d5e22c1049bcf4d9c541c1cd99b9113b1e76fbb627364cb8421e828aaaac88d3a2dcfce513fe7a195cab005a5e603f0cabba1e60ffc51f6a06cef83e0fcb3fbe3cc7ec97174
+TAG: d598ef0ca387f6aec06886fd1053e0d9e1897d82
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97c68947fc7ae4f54867fa7630881e45a31399c51d71c2a3f4d349bdb5d720d26fac75e9010983a87f291ac3a7b43b04320fdc1fbaaf6f54a1c982c8c2fc6c233f0c89b230f0655f54652ccd77967161d0f081fd6fe93f27081e0aa66fe285bfbbfb5b05b8b7c53de8a4ef72a82adfc88ac526161561bcf973daf053d44f053e3eee5a7692a9397d5e393d90dda23b69ce0dc9497a27a02ec0019da21311e89a74d83662b86c98b903b5dd91fada3c6ca6d839d6a3a307286388da93d1f1f721ba57938acab207f7807d1235d8ff15133fa93d6ac4e03c19e837c6f6ecf680c8c5cb5aa33e08f4441b87e9f6c1
+TAG: 7237c10ad9ab6229ea170f4c822dda4d4d194eba
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97fe991554171d8fa89273f712f71992b79ccfb4f26d68c1fb81ebcaf526e6efb37f2e1664dc666b3360a540ee3c520b7f135ba2335c357a3dab1257a2d918aaf50541599482c754e5a03df4f3e7bf00baf50ac945af034cb49816838fda953891a37b4ed44da65f832ad79aa16bef86ec8dacb250f2a73468232367a995a4aaf4b633cd8acbbbd7c3948ebe2bada8c56dc774b998032be2365567c0337d27ba7c9514b9f71950cf3e6ce8b6ae3fdee8872a0fb418eaa6bb4d6d5b9fb00e09fa8738162c796d5483ee4123a69526d2e900fecce653419eb549ca3029210e326490da1384bacd98d0b062458e71
+TAG: 3b64aa08ed6b56011225196313c8d09225fc3018
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca978ce8aca0fee6c4ee6a398a8be738b04536a3acbdb67617ca7e879b9ef42d40a109a6fcbbd2898249b08c90ce4382e289829e3b59b6625fc80a2fd497679e4f83ff69281d727946e32f9e8a80953a95edacd0b372d8621a118f5b17fd83eef14ac6cb4b477fcd35f94a0385c5993385a362cadc8cdc70029450503d7935da8294268837c45262f2a3de566544340fcb56bf5a7c95f1c7cfd47502c8906565d0fba89844ed56519a8d0e091b7e946e21a3df455ce040caef15f13cfb9d34456a91c1b70a7719cf4fc38db1a18c2b4e12c991e1f159470640f1e1f0f55bc04c3f9c0e626ebd627c8ee117af09c3
+TAG: aab8c4e7557a76636d9f533eb965ccaf1d678156
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97a84160b9de87b65f221f7fe4a93871411a6a45ebb891211da4442277201b06057e87c7ce4fc9e1430d099eb2ddd7518c4d1dc891dd344ee7e578e1dbb95908791aa0dc29dec371104fa8b1bda26fc2340a29715db914202b3683c779be1dd971c82d9484b611522d46ae623d6d73c49a368857bfc61c0477faf528549d543427baf39a513a9ddff7c9f42c98e411e0bea4c592f883993bf0e7db802f6d62cee5823224a96407c1315f743fd456183aa30ad2c8670454cd3956882854a7f9bd4f9851effde2d5cdb1ec351f64cdc6f8f20bf57518c9496c2ee3ed3e8d3f11d7e49bfd203646b2404631532794
+TAG: 4ee0fe7bedfdd061d7e074f36f993b31b48758c4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97d510f62985b03068f1dd613c3abe1d3ddbf0bb3c3592746fcaf9008d1f2701505b5170860d117ad96841c30db7489eab96cccb2a6675880a20a712b2e4c425aaa5a8a12680b341ac573cc8932787866d154b9f87f9bd419dc2775e540c96cf4e424978b446fc41c6ac332cef7af77230f033f1930f5c34a0718f894fc48c7dd745265547e6cd27a1f5522c6d8f50a3b778e292aeaaeac30b6dfe4fce24915748bcfc100d3166831b4c8eae9449b0cfd5104a7de90129426fc1ee3d9c05cbc1c37cf8b74cb1259deebad75d967adf0fe3dcbbad1aa0294fc83188e33399cb00e9c6cb0d77588f39ab84066365
+TAG: cb5f3d077be6a0de278b228861b79e39750a3076
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca978f7a64b11a4be63fc97263480d04ca00fa7510aa0fa5a939cf8fada5afda5fa01a5c20604c44829164d2cf2f053d4301df8385724924d41d61b8c35aabcfcf8e0211f98e1cb6fe22a9d9f3cf9c96c4717daee923414614bdea16258b1561ab1c15487659e1ec4ceaccee32b6ecd6f71c6b26633588ec4a60265ed47c9d4671fbdfdfa7a2e8c6158938c82d4b4d7c00b59c7263d7a73839073dc2a6721d100c0bc94c006498ce467be58455ee03ca9df61b87d9e7fa40bfcb3a5d09d3494812f0e476bac5c84167b426720470362051ae072b56726ed9ce3528f1786eae22105a29cfa93b52e64398c7f92781
+TAG: 51bc661c1674933392b16f9090cc5e848936ca8e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca9789461b9f7b09c9aad355bd97a615f70914e12a6bf485d0b051067017c8080df7bad54f3819895407e031c8dc666602ca0e3bc07d6378d4f4f5d5420c58a7aa4e2c20e7214b5540d6cf26ef6daa0517f98927df1ed78dbc87fb1c3bf79915ff1b72b4d8829f6346337f063ee3b3679310552f7cac51638adc8da14124880c1aca85bf08af6f43e7b1dfa5592352c58d7eb8e9642ef7e19e7f27748abfd65f30f878d5fe6c2c7db9f1216811b91a220f3446a12602e79e4886e0881fcf61f1b931e914599d61e9a84e0c5e01a1b11a046dfe08fe5ea8724dfa2cacd6947abc8b5be77cd21da64540d833744eaa
+TAG: b1695e3e367b6632765c066f5b23d1c5e7fa5e91
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca978484b37c2f3ec87170152784f329edb9d9948745bcf8d310b551c51114d300ce49938a4af9e4bec586359d72289d4369a368a487efca7c2a98720d8427617cfe3771b6622ab4ab27f236d3c77deb1f7e8b08df28eb741cb9d7b3a4694956760cfa5554f76c9720f9e05257d8bef58fc0bee5b25b48164214d9e742f9449722e0969a80c8e3575c542afa7ff9cab186dff3dc0fb2597deb0271661a0f6616b292ef03be0c7036b098f8a1b0b9cb9182a7dab5b2b4ba1b8a0c1971800ebdc1f651dc33c3d87d848f84f8d900079a0c4fe540dae52f5447d5582162693cf4db4e17e964b1b1f369dd470a46b929
+TAG: 4b4aecbe2002679edf9bf0e399a9ddf0f9edaa23
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e629504477d93cc5bcdae9dfd28b6d86aaf62779941f936ad870965fe874f1db6f0f31058018c16334fe0f183166d62a3cf46b9fdbb0f956514858227c045192f7c3e73092dc4365aaa1cd74af69e0250182b399ec3f9fe47aef83d97825ef45ab24084d0fd0ff6583f6d23b886f76ead84d6cfddeea73eb4036560807137ad28a4d67c34677e87a9491cf2974e6529297c144947179d73763dbbd0030934e5b6b00b6838ffbba99efc837efbfb43b70217994c7069270d2f8e4be1984f7a8054e66bf9a105ee25939bf4e6b92e02485cd1674ee296107132fb26c32a7a030f8b
+TAG: 5f9ecede08ee67618fe79edf171dd14d69040196
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447caa5a66821859a2dc0e072db2548081ff5e1aebcda6b4199ff0dddf58dae9152fd9461f319c48cd3e008ebf374771d9f0e1b9a462f99388622b75cdeb8be988e10849c325514b9dda1f8d6363d1fd0ee45a4b67d2bab4d05de5467379593218bf7113c732127ff40df1014516bddb528d7509c8768325f0072bf29507611b148fcad1eeb98956b94604f44e9f0be999fd4f84216aa0ad3d21ded254b718a71a01aea874d8fdc926e27df34811cce98b3529c3e89bfa363708e014b4a175f56b167e12b949dbcf9bcc01e6a47d6588f0f39856b51b351e80886c751c8
+TAG: 7d88ad1804ef187e2bdc070ad23fdbaa03f3834a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e629504474a9d2b06ddfdbe267b3a97fd65725236ed9b3546cebda726e9254920d87f9ff1d44d0a6d1787b329b198606ef0095cc0b2d885b8b4af3ee69a8ca0375cab6c81db9b788c3783f92cd20fa991213b4271e59b792ddd0b677ccc9e9888dcc5e60c5d2e53deb3b64d2def43e8cd7a387f62d84902872dabfc69bd5ef03b0c6d0fbbbdc9afc9e6bac85fae183fbaccf1f74d49a7f6d5839495f0a12af4617f3673c4c1bac3c214d8d0c27490e85fec9235aaa3628a3f42292bc4d38cf3befce825b03b5e90946769a2d5c2ffdce80c7165bf3c3c219ddc53c18232cacfb2
+TAG: 0ed84fb74dbbf19c1662225e26cd80381b039dd2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e6295044757466e5106795b66a6387da578daa1d592ea5c97885e6429d4b2074cd60e3a48f25375afe896d1c775c65de33582488dba86322b6d99ed8b9e3ad7e9c9645e38d0c9d7e0abd136b58d52eb003ae701c892038d87b79e897652d1e5f1faf15681fa28294865099e771a2b1ad4887f9745bfe89fd8a97ed03548c66becced0cefc46822dc60afa266ade705961f81734daacaa6ad53a8e915bd330aa51e26607a2dcdb1f5d1988f70bc2e00db29fd296d7e4368eabf0de80fff904ce7ae5f1973aa9024027db038dd7d2a7020670cd5f5de29e17f6605e093320b9eb19
+TAG: b49bfccaba11a093f4a4ce567c8ec5935ffd58ea
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447c735a15b2505840c1dfd310cc00378c036702be3f4a9dc5965222fb12b8ac10c4c759bb737bd096f35f0d45ccff9f70f309e8360ef1e401279a74899e595233ae62663701463cbc115418ecc49b8f37cbd5cfe4d78c30c99fb4e1e83fc57c285feee4860ac0d8b9bf9cd2cec827b7807cb95ee93ff0592ce5c0c2f54f5498f63f6720daf7a525b70cfb72b207bf7bf4a6d7e7222d873bf305f4dbf619740fb924256f9295f2e33d35f4089b0d44b9ac41c1b0b138db13bad70a7cf47508c9558bed88586fba96701f10d3e83ddf992e91780a85d14979acde7e08323
+TAG: 7dd2c48b09e1db88aff7fde9667429c5b1f46ca3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447972e7787a03db3b5a640513542a129074fd43d853c4eb850943ae34f3ee0dce076a1ef06868dc146057174546843483582d54a4cf5eb2793d744ee8e4200f00f53f14f8d6d3e58eaed777578516634cb37bb667068b173f67ebe05b6ac18b73075cec23d43003ed18ef44480f8aa77daf3b291dfa31b9e047c5072c09c4f0a380fa84da7ee1f910bc750135e9c6557a3224c754780b3d4df3773aae59d2d39303409a49637f99346b38388147d0315752ad64cea3ec960bafc235340da18ae9bf632a1e7dfc7d12860a6fedff5a4c82c43c2c45ac2b83ece3a118ac0
+TAG: 7cb0dc7b23e86f8b94490b5c845e9513c52c2c87
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447d7d578266eb5ed8052817f28a1ee1c4a2d57c214cbb4389d9fcaab674fe16e1eaeb835fc8e56b2e55a421e3a8ea2a28404612593aae15020f17806661fdcd1ec33ad645567594b8401cbf213050aca4611c7a2f9bc5b319c66afcbd3d98201fb913afc4df280fa1f6a76c4f5bc5eea21e40b8539f18872b20ccefbaba0671c72c5bdf6bd1edccd12c7377b0c70a9745013eabfaf9fd30b8aaf8842c818004f3a1ac219dc701f3c62428dfaa244146927c7cf63d1222b128bfa364265084c15c16665a1c8e772dae3a88e0bb3c075f91ff4ad8ec014d4b8eb61a4ae9a
+TAG: 7ccf30756d4b6b8727ce2714389b903fcacff085
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e629504472856fdd33a21aa08b5d75a5ce3986e66b47316dfafe9a198a4bad0816fc409bc90278815d738162fe2149714eae6a665806673e8b1f07b4ad0daa33f862f8bfd43cdc5e3769529e68c1db7cf8df6113eaeaf8048b57d62695ebfde4ecdc4155b63c99eb32577a4f29f459982c99012b55e10cf2011ff5e942527e3b5661c9236f606a76b4163f19402001458c1e91ea3493b48763a293207974cca60e6ad902718660b037793a7a78142ade1f58e44ba12b6f64864baefcc3f5e52086086d073d928690e3bdc463d638182e8da13d6e8272b71a529b81d001bb1f066
+TAG: ff4cc938a5e10398f3874a7454f02be9a89c4087
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e629504473a859f6ed9b3e29a97f961f893905b9b0f5137d39711d0dc8c28c689b8ad5537d5ce4a2d9d11bbcf1dfacded581b51753d06a4a4d3e4a8106023cb89cf153e8a92afd3f4c88439133139e2c45c07922e05167b417c7fe400df3a8de3e5ca20d920b131949c693732553a30eb584164afb29d172fe2b4971a82f8407c5a13d27d3ad75de801784f51f7c412d5f1bd88940900f4b895ac7e8c80d3e976154d77f5646beff53c2ec3370fd9f2390104983fd01ee43846973518f9ac28db0474a2e5d35c7d20e55519e00e23e534bc4c256ddd14416aa2d0db9009465055
+TAG: 8d095d017ad836002c9b38dfdfa6ea9368df1127
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447527f28f03d1b0ac9b893534df88f676da599195bcb2cb62e885f860e34f0ea30825ac077406ceba90011d7ad09bae5fe980e579cb83758e57cd6cf6c2c949ebdc6d264b6dfa62baf532dd6f41ffc7f80707876e092be70ee3a2dd977630f1a66227d32d9f6a5acb16cb64e294a71f9b334f5599cc20f0bb0665716e69ba757765e41c55ee8085297f9aa9decc15c67aa5492052bd0cfa61a35700038bb6418507b53abc942da8b8d56ae4514957551f97b2b10c924a09c3bba4f92d1749e3ade97d763ee0abd5e15aca6401701077efc3baf8c05d15a1fd96df7c9aa
+TAG: ec171990ac3344c43fb04e8b2ece7db9641ed2da
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447a1ec93d84ea533bef16d27a607e6f36f546d6041e8ebb6779af52f89611e5dece90af839522463273f9a0fa902c55515e39510d947b63082d1025b16aac06c891ec41e553f60df6f09883dc7e65ebdd66779505bcc6bdd4a4cef73badf29edd99156ba9232695f1245af4f753121f3536ac2511751972589a43773ac84ee053614b49c59bf70d9553c2104c83325777679e261b1466a7641f1fca32356d9bfe61cf853117e7ae6df08c32936bd41f02df7d8112542727310dd4044cde9e3a459a1ceb4dcbaf2cdc13bcda5284ea5a23ff3d3582ca80dd3043b3b71b5
+TAG: a47794b6799d32b042cc3f205ed75aba173d88a9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447731e7b75ee401f3a1c3f57f5a32dd0ec8ab93978d60025f2a1f7ce38419ffd461befe968260d175e9b9d7369cb69a74b830f6a5850f5506188c07bfea225ed6030e88eebc28df0f888c126a17b2f127f1cab288e3e138a026f9497adf801a397be681359fd6d1b8dcceaf5af4bb4a02108d446856ae88a2026dbca715e46dd910e1fbd205aeb6efdf017ddb044914d9f5958ed1fbeb9f1440d15ef6b3619a439d166ce2aec06bb4f47174bd80fd45932aa4e868f3d3b7f157c084934f5ac3c0696b5d6c70a065e385e7a69cacbfa092181f58bf36c76221e58aa1811
+TAG: 977055320dbba3e32930c1e2dcb6e6010567fea7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447458b12e4410770cf350411b81957e3c04e347fa69b198ea8b6c83a576cb85914aef7833309d3e5ff96b63121b7c3f85cdeb7c2a76c77d1b4985463985c3f9dcc04d89b4634bd3e68d906e462eb0d8b46d51a07a0a24a106f87a97cb3bca0f8d9bf37ba9520734dbb20c58680e02d669d09bb166f672172a4c3340c77c8c685d75ddc728ea3f3167e19d05141389f5c8da8821ed5762fa761fc1b9d3592120e80490f3285a0909d3ca1f81023c3a04ae0121c63c7c45cb11c010ea6e8c1fb4d73f5ea402ca6bf4a57ac28de10939da6c61ae13feb2c5c728176b809a2
+TAG: 1956e99a57a26819ca229e68e5fe7fdaec1610d6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447624fcaf8375233318cd8dae4503858d8b1de1dd4e6e8ba0a3016c2827e62451207db10973556242f7ee9711288404602088baed9367444de74eb09f831877aeb2da0c95f6288544d62a4b9534ec092142c7ac253c3ee46c8c8086e462f1b5b4adc4d054c711172292375afa6cec2c553e3de22e847b678aa41ceb2cb08946efcb0f7ff9831ca57f34ed83ab26c6fbc54c4d0f353f278a8184eee9a368980ef58cc2a3e68efae6766616948a11f2eb4a144964d00f0dca7594c04d656d1204888eaa66b3d6b6632d9330c1e28911af23ef4b13fa4afc97364a811ec5b
+TAG: bf23a6ccb3904d060870f55373b2959d7f8f17b2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e6295044758338e5c286964b927a00c8c327ed0eeb7b8e6a27966638d5641db3e86d71d85aa2eca6a2e7feffc00a8c40f1a3a455cf30c366ffa71021681920854c7a40ed5dcd971dc9d07437bc548a02dcc4d8cceadc5a0e4817c22e1a39ab52272f23597f1f2c9d44ee4306e0da617803c1115681ac7752ed280966bd8bb19d3d8ed0de88c23c28d473d4fde6ddd3ae86e7e5c667001b8e9e882452cc03a7cf3130eec7d2b568134db94727695421da4065720f07ef94710d3aca2c7ee4d9a5db8794eebc8789fa6aaad0825c0a83907a341f29342f51c9ffcee3d6ebdbcf622
+TAG: 4c75516533b923ff0a547bb92e3de376b2ac235a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e629504477dcbe76270a38b39d3a9d4844b21c3fdaa9c6fa930eaeb54f7557c1819ec053f6ae0e9802510c89f756a4d5d70444987e9ec5e85bcd748abdb28db7277e6656629fb6ba1b80923af19bf451670404f67358ceb28b5fc86f3aa4a099e8ede47f23ddae9b0379f42163feb79c9985460008f08879975612ee5b9054ab07558930709d75df3033cc09c14c4c6d0176fb6e730e379952521e095bf2e50eb1354d785b25349d21b8c7d56cf85715355268ea8bbd6a1b580d790c27bd1d46328d595e24a83778d33b46521159bc35d22e227815641662e1ef2e7b28e063ef7
+TAG: d54c6698a2b20a34ea32a006ee8c2bd3d36c90ef
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597eafd6d31e7f8776c644bec881cd2563da1832958bcfed82422fb2ea1409c0bc46e5d6ce37c9d0df3d4e61745efd6de5c396097f01667d5b5edc0b2369692358cbf156f9323da3c5968c898250a2b2bde0144e27d364263eaab0b893917b37bd9715e229264356d8012906f60f7c1bee1a5730f2d0c082dc33e99cdc78723d37163f9dae7d18d2a1b1fed432e23539809e2fcf66d57c2f72c38b7c71bc4f02561c82908f4b0f5e58bf8c80d8ba7450dc682a1892acef2252f2b7f22ad33b3228e092032f97e7b449082bfc1992
+TAG: 7158eb1b0c1c49cd414ae73cd9d29316269ed98f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597e30340c5f596a78fe3c81fed7f7f180fc6b7973ecc60af3bc5f74633ea74a18eb2fcccb6bab98693d12f4b7e88b4baf98defb9d4405b77c5c75d2e64f9c3f7fc03ce5a5411601dae73ab4cb1f18c760bea0936107b762052d9d3c4b7d80222265a91fa0abbf64cffa66fe645ead5852f9c326b8b38e1f537787e66886a26150ff5ab0a6692053d1f6319ceff65ac2effa443fa485fa5b73fd02e221b77b69babb96ac2fb87b6a912da279aceafce064775d74a71ffee87894ec40e2d2e2ba6b4673a7d4d27078cd8aebf62c40
+TAG: 6610bb2ff5eafa8b161774c06e7a867362b5e637
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597eec4c06db3442c3cc1bb686039fb7404dd87b15be21e6bd0209d1fa9f030a4bce424324fbcc616b1df72c5f2a0490c53964736d24042a73a2e7faad3355694b45a7af4cc75a7046e2322f0a8536a5f737b8cd14574ee5c56d10316a8d4759239dfc2fc84e1857799aa013012bae6f9c4c1af1964352b91b099185422d6ed2a040f76f62ba486264135dbb13efc6e77fa28f449cdbc0eecc266cf072a4802b5ff2484448b4a7cc2ce2058d09e99ed08916e836ce3ab9cecabcfe1bec05b98118587ce6580ae0c07d6d3dbdeba3
+TAG: a7edadd8960f669279b0230f6d851eb2b6abc12f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ef3a13ef239721dafc41fe370b2c29a9155e94dd9b682109820b6eb35bea85a660dad46edf63a66d4f26fbccabdecbad8aa59626f3eded409d92dc5e8098e6db5e8d192acfda842e3c03d2e84f9d27bd1cfa09c93dade262751211e572d9155da8509fb2598242252adba5d97972f58a619db9788f9b50f276beac43c2e6e9589d5642398a7da8591ef8688e36d291ef32639db7fd8923eb5f892eeba0d1f005d3f182593097f7ba7794e561ffcdded2903f47f5716eeb5ffe792a3ccbd13a27c9d7f5dcdb030c0d209ec9970
+TAG: c5d1ebc7206a1244dd72dbc9e9f786945d6c82c2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597eec1be57df85a20bf65e19b68a36d9e938312a74c14c08eaeb93b0562c57126e4381c3a967cd7ccfe5940e4003b65e423822d0c232fec5ba5d53fd2730f918fbd2c4912061450c04ac851fdbf397c7a464e0ee74598af571510ea866d358e47914e02d8bc4b32b938bc35a04e6b25fbe2ac35cca190edd7b666500d5f972adaa76ced5a621de4c347fde9eb2dc64ad994f1d00660de958e17e7a2b6f4bd75044007130556742a5adc83ffe19220a691e2f811235e7d2b3e1a7e49eb4ba0bf12005c9826b0e5bfde0141a1ab55
+TAG: d660944ef5fb29e11eb48508cdeebaef7776c5be
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597e388d8fe10bfbc41804987f710cab90d14fff33a76ec3ee78184eaa4b31c25af732d614de935e57915e417f2f67a79c06ae805f597fdfc4f4e534fd2a9b6ce76638f0848c63bcb42a1f67fad98f88903d00ced0a8e495a94150f5ad0c9d18d949f73bdf5fdf190c4db968fa94ee0551495f5659d2aa563b79e6ec5a3eb7d8c3cca655b1e33248e94247ed07941ee3221ec015bdb4d2578c27ebbe852edbe2ee4748de49a413b900a6eda5c6bd834fca5d9474239daad22fc8cd716b90d524576693c1cae6eb284e258e4638cd
+TAG: c2b50110655aabcf9e6048263d97714d9b0ddc42
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597eaa85c2e6e570f7618ed1609f7362a22f52fbc866a418ecb5fe0dc9eb23c1a9c2f8aa735ad8687dc1372d6439bfa4fa78ac5c196db0e94ab3ec769edee3d700c15d0ba477da8d780eedfbce41bad4947081200e090d5e233eeeb0665a53ba9695b6956bb5474b428116f7c962e9fef3569d3da6d75617266c9100c61cc8719d46538196c16e26600b0677831fbd97905818c434165cf3f7d65d76ea416a64f7be6db4a92a680c569e91fd73422131da4106f5418801c7648fb23d73fd7ecb3341720cf355779171eec6275f72
+TAG: b97910d7d25638f7b22c18d073573809ec2d7945
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597e07a350450edd380e189ea4152369d2e4c37a9768dfb2885227bedf8d0ff3065ca0fbd21faaae991d2073af32933a4b36ba35b1596577fd9155771c4c14890ebdd89808bde1c46763060236427cc37d950b19a373d72c804cf8247dbbb0744f2d45b19a8563f64fa58c8884f3e47bf91c8931180eafeeea6ef52cd662f93500f648d1b7a0a87a8fdfd63bdd5f2d26d82804b6a6619f58a62913f3e4fdf91ba5d2d8c39977828346a90d05a48930f60e45a5b14ce1d93709e015afd6f73d95c1a4ea31bdca677f03122981c047
+TAG: 96b1b70f5ccc7927d53e8eaf1f1e8638bb975c82
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597e15874fab8c81f34db199487e9a1499630e27c8602ee42ac566c4eb1b75aeaa0c48d97b0a9226db7a24ce17a3ae93c93597340331ce2bbb6f06abdc689211ae54d94929ae5eba8d1561ada0c87bfd2943a6bc361549354434bb88fbb0c07b8f29a560820cd3d03b520dea05aed558e18212af63f3afc48c0177668f20be99390272f7302d87f2ec8bbc5c67456cec10bd14a7d638b7cd4c8cdc1a0bf4206e125f5ab714afc3277a752e4e28f23e03a04f0beb61869f369964e5d7fee4fda7b231895ab19e46f331b1fa535fb4
+TAG: ba56c28de8671a7f97028314ebc1a766737b2e5c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597e7e4b15d5a66966922531f1c59a486cdf2d289e54c9efdf45bb647e3eb50cd51b4490076b2135779ad0dec1d4ac678038da9621cc8468e13875240aa1ab6389936221c526a72fcbb77e7fa9bcb9aef0f9fcffbe6f44a9a07c7c625f570881c8979a8a24659323ca1e96b4528dab7f557ced5b6b3667c4da9e52e8688d99073df12dcac49c525eba34c4b991790d78afbb528eb40e408022da9c8d02990ee85f4066454608c0200cdc3f681d790269ce4dd62a221d8747c3e0a5837865ed19c75fed4d743f276ed3abe9c0e3cf
+TAG: d5cc167566652ae42dd204418174bed3f6527232
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597e0680d279040724fb8d6135de8b310acd04b06fe2cbe82deb1a396de764b3038d4b3ec5a4a01ece03a7f1b8fd94c802c3c14750176738bef3e4fabda2d7d0625889e5544930c2c758afa1281cfd4f2a567c8b7b8d0ff9ad00e2026c7683ee2e430af37cc00d10134f486e1131ad713e0b76721175af6713e20bd7cb7aae2f4eb41fd666b7439353acbff0d339f55d788dbf080948854ced95e4de712ed1090cbe2d9e8af81f872ffa87e4a54c7e53b4d72bb8bb3d0c81ef7d660f40ab0d11b247625aa2508b4528fbfc30b501
+TAG: cdf1947db56c173b522f7a5f2edbac1b9c74e7be
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597e5ef147cc27d0c52c50931c1c4f5bca11b88407512c400602f81da601a7527d87e4d5d0943148b66e220cd557180e725ef4aac14a4dc301ed3c1cd1e589a095d9fea92827b9d98a4ca60944df72ddd9b1485db5169a4d6a86bc005faf77b217577bad63ecb0f789d3becf893d7c6672773c2b52fa7393b9bf851bd87dfb16bce190a958d961c9b395e477798365a57e9faea81ec15bccefa07fab6613ca4d846920e2320c78c3eef88c9c2190f03e464531d7f25119aa9a2bfd936022c4b5c10000f10969297972434605fa17
+TAG: 00af27bc23b594b7af21849cdd8dae3fd166fd11
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597e5f5d1b216a867e070a710660589a260d56c72fbddde12cd5f6f61694f17061e5fedbd43642a4cc9ca2f82b3ac80db2212badc7b42cefe9889fb13fea7c2734d245cc6a7d0680b7e6c2a645db09a3e82e8c6683335b9081b5e4216a5802655f0c9a117efe2f423dfe3b913548cac1b339181378ce05755d77331888c05fd8f2d17af7db5853f905c1fc72183f08927179c85ec196b89b25ea546312fa6e820a925c2fb450f627812a2541bb810e32f8991912e639edd755a5d3872a0d666a9928092f529f263ac933eddad9c1
+TAG: a53e2c94b6e30b88a9d5d4e9ed9cb558a57bce79
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ebe661bf10543f11ddb28643b032ba266167ed6fe7876d0c2f2008e4d42c56587120ec7eaf60cb9e8afedf54a17818a384378b4ae416bf967278df8f8f5cfb85451e704b795c27533999be17cf0066a590523015a77125cc3f9e89152a953b3be0078ac5510d4b127e88b0e7d024a99c46f789bc237de6219822bfa4ca4408bb1953b6e3e2cd9488b8c9a353a50dc5cb8711e51bb5ff98e58353f5dc91c3b83e06607a4ca6e9ac3f0ed760a8be9681e1d54785af9794c2eb28945732cc55ae3e54a11e330b0c424e3999fbe27
+TAG: f0e2e31083390fec347c624b04e49d6a7e5ccd47
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ec92c840cbd076544d3c9c1f9c5e684d1660e748c197d26369c2490a0bbab97a7044ddd06439c6eb28eb9e5e08977415dc42a3419229c33cdd813bcc5b10025302b8f15e7343a8a182cb522bb09d199058738a92ba40eabf20b01d4dd48588c74848f90839b0c6726bfc54aba430afe4ad71837954309b1efe0d3e6985bcea10b0a8ac36972936c5487ed9c7534663d58d877235d70da52447769a259c4e9f50cd11a2ab50671ad44cdaf328f9575feafa401b6c50275dac39ddc52ddf71b4e6dd66d54aa0d52201f935efd55
+TAG: b2e5acb2cab557ef49e8d43f5cb5a952ad355dbd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597e06c977f2d7ad252b2e4be269ad4f97e60d72672f6dd3f9e25e7b96aff14c8216d2ff86a4b8c2a0ab58a02d7322215876de57cc54f73aeb1cbcbee001f564a63ec36e33450e95f96194fc9025c30d93639728d5c69d9fe26b5b62b6ecd1f55a28a28575c616a3634286a4eb99c2fd885f59664f8f5c5777c07b70471bf205750482201ef1d6bb270067dfd133f4c8654fd577ff5c6bf9655905e7e8f99e96091640bb99e129a3cf65dea771ed19ed9b38721fac8b41b5941908115c95ace4eecfdd1f96dfcad8c77ea1cf1911
+TAG: c1a7e8958a5e892a542fce9505e25092b490ed17
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8931dbf8f4b0bf31a0c78329581f879edf17ec58bae30bf9adfbf3d6a642588ee3176a8146f8e0af4d9e02e940fface84bd1774ea789f01f8655d397c0c9b46f6ad38dcf63f2abac0627adbbf5bbd9df5655d6dd89f4e8b2aef1ec82418f0925475404d9ad31ead9532b371428d73ccf12add978f5d9cfe3796027f924420516ee73273ba9b12c62e4bf4c9d0d8133f456462ef1d9d6582a2cbd322e7e1e0795af55548c34bbefd10187730f6f5dcff2607e380c8902ae1b5c559c1fca4
+TAG: 83efeb664402230aaee012c7b9746750991acbbc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e89340cf262a2721159171e4d4da62c2ce27093a4ae54ebc16f0076b1ee089aaa456180a69eeb46faabe413ac306a96fa3c395aed17ab2627ab4dbe714bec2a8cce18664abfbcd428c976a3288848e50436683f07a91097055cd8960089bfef263c61d55080017516e7b7936be9cd7cd0bdf8143a6338355a4f3e18b184caa7b5238239ae2863b49f88e19eab626b5902f5c2e4d7d9c160f2808d0a95ce156c98501997db6afd280dd4f8094f34eaf7013e6f82d3d9d4b886dc53f74e76e
+TAG: d22a04d3990c596a44417a6fe2844d6a7c76f48b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e89329dc7a43ef9d581e67b4bf85049d6574db02e8bfe32eaede9a9dc59ad27337d4faccc9cf9ee8f775fed0f85b27899f4b7c1d70fe0c30bc7dc0b87abde1ad81f55c92272c4709356678419cd9d9832c60eedbd74a24bf9549a0c39772cc6337b5043f9c79c0f076e5289584d01b6f428c1ea0ab0963765a846f5a5875eaa35b6bb140cbbb58480abbed3adba866f96f4c964b2789016d07524ad28370b07ea21a9f2ca86ab973901f5bddd737c8611fdcb848d1baebac5821fd29de05
+TAG: 182f82caef4a96330e0d50d143ea11e60b1872b9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8935d5472f5d66770ac1858278956fde6b36de729db9e8bf14401283cd5f82c89f4b3f1e7baddc5031e59a79b139ce5508464d71297b862c54a5f64325c9f7dfd2c2c9649a4ed050b5a25f56debf1526b150abbc40ef8c9b30663f1c2d064e06e418d1d7f4f26d96e2f3f6651d9b8aac17ea6320671a589e2bd01942adb3dde64c6425f1290ee38e74cbfc31c35727ce8d0fbe48a67e0b9646d8f23e18b114e4e127d3dc231dbef273db5048b86ff60ad998697404b93557fa458e594b6
+TAG: 590b724a8be4f81429536f1b47d431e884054b83
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e89319ffe05c7eecc23c61e36e4c2d2c3d37c5b9152f06d687242ba10083988d343f8eea6b39c29b69577909747f618d8699ad7ef2b7b0c9c935f762fce73669f86f74e923e8aca3b50f25f8dfba9b1f1c6bccfd10e2b9c06d012beedcc4274096f5c77e5ca1fcf891256535931d064deaf552282a9c75a379322dc12ff5ecf9d3146333958a43bedd64ece1bd4c98adf289675ea2fe085d4ecdce6b672a10972803d01a6a645a5a3ff1d3015e72d90cf19ea8a5b10cde4f824e71e6e9aa
+TAG: 5f32ecdfc678ca2d8957cd0fd35c39cab6a88ca2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e893586bf0222884e567e6406560633f87cf9e59cfe75b87bb334a89e569b1959752fca8c49d267de03a71198654c062d5b520726381f43ad5f0db597a3ed236182cbfe2a43b4a83cc32c7d746f5499204a5fff0eb5e0c1c6f2637677cf5a4ab5b3f5bfde072c92227478486a1d78a1ddd11b818f5a3a48bffe2007db88c7895cdfb514c51ff59957f49e95ca8fcc277b3ea9973c5fa4ec361a1279e4f8bc4a5d289e5a15fe2a1cf41869849d8653b452bea33b7fdb1472fed82dac6c122
+TAG: 60a06a529637b745e32508316bd605b4bdf426ef
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e893e5ce5b0efc12a961648fec1bd6b0768c65e996826fe52c4a417bbbec846dd7632f8a2f832b28c6fe050c63b8c6b1a7847285be3e9c7f66a81dc7f94d40992934e0152577fbabb4ac9f08e6a84682b1602d660b1f1dbc25891409166d690cd8dbd00d8fe08245e0438298b9adc52e8b5fb05ea73ae8cc317f0b75db64389095b73d727f1f6b2da68f8a3abe877b8855ddf3843edae5f5450472b082ff05c7d30e14d345580e1c08129443fb3903eb7673df655c9e06bbf26117744c36
+TAG: 8a461dca639998c73d3548690e664f14f4258d94
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e893e1aeb0cd7d81761ebfe0f3aa0b5e6855cdbc5bb51c99521e8dafe9cff970163e2f6e19ca8edda8b1901dfc70464c5ca6ee33b3e534f6471dc622dbe6225295cabcbaff33e78bc3be737deeb1e4065fb77a9115cd57f42247369effe4635c011dc7995e95a96ddfb013d57860fb5af9049a62e139bd50a6d5c34c06e232f5b7ee943beba648aeb10333c6f6b3a197e29d33d1b363d0b5f5d504f58b05c8861fbf35c873fe72b9602640e05187d15ffd93372e9496595ee1d020d37bf1
+TAG: 8b072e3f891ba9aa185e5b346930d47aa9d39040
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8937abb621f87dc1d875869595860d2455b9bbc5552ee6bd99546d86ef2ff37366043a877e0a7b48cd9bfcbc1a665db8f500c05bf431ae28adb4f9da34c73fd35ce385f7ac43b6c1aefbbe81c796c1e4eb5449047dc42df990beca41be2b9ed70060e7fa008078473c2805aadcd872063bb98601870e696b7acf887e52a9b9b0866afe89f5eb89775eb352a44f5658f3909a0a2c3f932f4bd7f074620c389e6f3623727ebc7758a907bc1a1fcb828fc6719f05a62de95a14d95217c0111
+TAG: 2c249c37b88eec4fb1fc64cdf3a25cd8a7455f56
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e89386349c60df134738bf9cd79ff44bdfc27392e88f2ca13ad3c6a7d5cfd8f5953e8a3cd7c260bd7554638e608a3a39f0d097528f34cba64aa13bb0bc97e7b906b92a41c4c47a7131e36723173c9e6b9d6687a3be3e3213e06dd8ec04596171aa2151066824dc8857b1ec468f31745d300c84739f3360c6f2bb5f510a85fe095247adce336fa7a465d9770fe1e760bbf8188b9fc06437ecf06263bcdeb3ffa8e86a6681ec9e4de80c3411b05afa5fbc1d72c8ebddaa2b1b5c6fcec23bfe
+TAG: 28a1699b126b0e495153c21f357409a4565560ce
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e893a281282957fc69b7ca2d9e399dde32ce67d7f803041fd41ac1c5e29d838f4a5a61b5e41c37c77cd99e2086deef1fd3a1f52205fec1609b898fb3269270fd5ed70b99a5d9c50b20f73d83bb224c381b65dfcc63b329cd2eddc41cfb0a3fd34d10578dbf362364ff9e404b72fcdeb00f4f1d7b79c9327781e7f37922f3f74c8ae6b07af55cfccf47b3d3731ced97d83ccca7832ef4ce882fc9438e69eacdd21ec2499c5543436db3835691a7d45dac32a49cbecc752a37d584b588b56d
+TAG: f0928c4c4f705a40af391e61b80e674140868941
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8935a6678457eacc57abd9fac0429320360be153d397dc6898ab6d2de9baefb9be9853042a17e2603fbe89126d7c1ec521d9d6501877196232f22e0246559a410510a937750e119953db4c141a178bb0949ee1bd4875a87e1da89122725db12cea2df70116e02643b4c4e66c9df051acb4e3ae9b49f531b887471ae9e216b6849eb33a99542cc03836f94f74583f13dd15863af8e5b0761eef7fed0f2de6847b6903a406444b4abeae4f879a1c64ab366b6ca251d0e041934f1d492cd96
+TAG: c3f66cff59d1c5cb1ae1b29bff4ce373a1306bf4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e893f56db74314aa97d6a4816e78a1b250947b6d828d930c5332e879b4a9a42eb90cee0c34df145ab46994dbc339768bf5de29724220ab0b13f8ad2aac51aa6d29652e5102f77b31bbaaa398871befda8f2f5e59f8d86c807e3c496154f90710079fee0bec2f02a40ae0bb38a89790393b199b1d0a30ab77d81d7a3c66c920bd15053bd236c294e3ea02482c3b8cb1d8b84cb80347c3ad796a7a2215b469baf8b593fa3ee66330b66bbc91a85bc9569c11b0585ffe36f08125bf215e0676
+TAG: a91688cb695340c22d96c15e984d3649092386f6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e893b4da8f73f9145a48320c562103416b8258ad0d1e1ed9539462ae8e1d05453dc821e9920b5bd8c1a443251c569193fc4dd488d75a1ce30e5533e9ecc77ebf0f5f2f6ee2c134b8d0973effcd4a281b3a2a61115a27f2b8375e55a21dde0d63bd433f7c1b193e6ca85e92cc5a7d5b9d452ebbef688c5f41ec50ab548de0d51343a325c0bc29ef100ccb0c48ea8cb5a54acd46d5c8683ee6d2c3f1818b659c36566f2b2293a0b22643e91e70eabd6d139cc723bd2b1d2a0046339bed96b5
+TAG: 13256c8348f97e72e6c65d9cf7a3ee3c3e9f6169
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e893f5614d3985dc720334f8c5f47d3f727c4d835c4985588d15879b7da6294d2efe710b6b3ed54b106b6cce679c8a27e8d48bd3cca6cfc310f72ec5e9e19425e8a3eae11232a7800c53a1eed56cee6d697a8480f47b5cbd95f91c680be3f0e1a54a25cba02b2ba92d315625e0998aa3a7b75e36b4707da10219e587e3d09b67c2992b2fd29ccd6267fa4e76c161a264abe04f2a222bbe5ab2c0a0981c6e12335f966d04f83f2e87d625fb400324086155963c7b19a98f27f2bcc2d4faf6
+TAG: 4c83d34a3465b7a162b52bcb82e6b0e4093d695d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e893b0fc267ec80b62be97c170de3a0cca7050b4e33ffb74357be1cf0d1a803b65537e24e8f6aa859851f851f4cab2785d86f10b9ba9223d6a64476447e2ba5a8e675295c283a00a6d42e8e1f804a1c23d88af9d36144644d588b1fc75eaf5f0a05e7eac46e4b0d1034cb1275ccca3878fee60cdbbfd83be6be6250e0244ebf5c346f24d1d6a10a7422d7a122db794409b2d8599ea03a2a59011b384048aa8450d9e33f9b6b4fd8cbc48e7d55ae56bd0c4f86046ccc5bfcce22e2af39909
+TAG: 07ab8c747921eb58b2b0564e0345e4aec6c62398
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca230a149ac3543746b8b79f47fe22893590baf22cce4603af7dd15d89c3e4386fd56c373c9a8158e53852bf33c7ebc65ba1508c63e3e596533844b94f80dd122b5e18f2bcbb2ab1abb879a59e550a5701bae52ebee7d93bc079296391af90ab57b6629012aa21e959b8445e87f15fa41142bcd382b91dcd81c4a21ff99381c66120d4288b1c8b555759aa8301961d6a7e47982342e403949018346e61584c36ef033302c9e3876e8bdd5924c1
+TAG: e9adf96d94abda968a5a9a275ffd417f9c842ad4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57cae97580cef4057fd0b8e836c85ab759e530afe1558ce5172a582de5aeda8ab8586462a39f886ffd8f670525be81ece0e4eaa14e6063a9b0a1a958e78e733933c4ec922dfbc90572e85ce0306a8cdb0bbc4d7b1133482358899b3e1576ee13148aeee4286305d586b81366abc2ecec05e8dbcc27ce6b5667575c2bb790af386e912fd8a10e8bd8845aff79b795a5600a642d0aa72b130329a059c740af40434438ee0870555734b1d64c606d47
+TAG: 218c2721948e0500e9dbe65b62a12bab81f62880
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca0820edb5dbfc004ac6b40c9805c3e62634369f085c0e8763fdc7018975048a69cc04220732da0df66905ae1f511d0786926509506f64f52a43a4091227b8a48105e1a89c55940c1d0ef44981181613f287db9a98bf9f74e0bcea71f78552d9e415b6fed0bed4543696d15b4c7221f5f9c888b6d0c62e84e3a341871f60f7ff62738a2df747a2aedd4899a05e7360fd68a1abb8007eb62ebcfe674a7b9e58b7bf0cec098e27807e4349974500
+TAG: 3804494038029d6fa3b624cad7545a294238562b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca3edbbd822c9c60c65dc99c1fa798066c0ccb8075e9f17036d18fe3d562543e5bf911eb29428e8f3c2c8f66e6ad4f98dfdcf941741d259cf429f595eead86b3b18cb3f230cab716dea888c169be203f8dc3573543045bab2d74859d790cbbb2f9334094f57f6d23e1ff29409e47acc00ac0f4561350ecfe99b5c531424099ccd21ba7692d51f9428328ad145a77d3fe18bd14febc2a4b850390d836ac2ee3d9169f7595af250356e9122ab4c5
+TAG: b5d04e448e6d0832f149aad35c51384aae2db5e5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57caff7480a4e61cf8ef66adc10ffbf6f8fe50082056475976d30d9221c70cf6de6086a97929f0ed5942b404282a8fe4dd7a914d2548f13cff13c43bde01450149f6541475ac72bc73b124a3e16c0a4d161c7eea94a8b6bbd1ff4656943e2a60bc72c12a47271d93286c44776aa2812ba52aaf15687a51d967f3de0a1a94b58d74bab75867e857d5e7740319faab7056ecb46e0681f23a4a9299698186519dccfda1ca32f136f710002c82448887
+TAG: c705cec551801a769cad84020c64026ca9b51708
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57caed34b08351ce045806536b0de176c6a5e66fb0c55f4d09214d7bb9ac0fce0edcb4f7c8fe42f6962c820aab3347dc19dc1ab5fd6182a26f979c94979c082cd8cc3480075b323b072b1570a1e11c67eb208a86f2af457967c3642e6eaa66ad5783a5e3c1c43672c2a58a628771f721e0933d0e602aa1061dce573385a5d5cca00bcf95f4f9e8e4b6552f2f4e8970db3e3670b5f0f3fea7f0279d07b9df283658f5472bd695e7ead90304cb5508
+TAG: 0603234347915fef66c43631b624a80d5fd33e47
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57caa468578d115d46a5e01ff0b3754ae705ba33007eb53a1e95623db01e79a6e57d1cab9aba0c01666e1ae50582ca63ccad9dd75eed24409e9e383f95cae155be805292a5b92e4bafa95d69db73d07b191d951abbca9c74f6c6c071648f3c753be911e6a76fe53d8801d6a2f2b8544b35da23b99a2ad72382ca036c6a0b203b05810ae4aed7b2b0d52571f2bd20fed1cc264ae80f79b80502888af72acfdab92387c70966a08f5f78d966639666
+TAG: c9163466ea1cbfa412138448a78074f284dddccf
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57cabf2a8af3aa0264de545df615f697cc36abe251e167a96a2c35ba91a8c315cd5a711665016b23423691ef380f7ee21d4a36ab6e636f0bdb8dd35425e34f3ed535a9d321e94ab9b5c535d884beec4534b295eb9821a4ccd23c18820df4d2756acd73624a3d74e7a6a18285d49ea345a899c3bcecf9cd3948380020ef6c19a6b83fcf2bb4c3eeaff38f2f240b1b848e74c866378f20c2e41dbed10bdf49b86b3e51315d4b9757ea38b5cf3cca46
+TAG: 01ecd18172790c04743534479af9e554e327fa25
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca402fa1a5b0e656580801c32df9421290b7fbaabbd836000df6e572bac7509b1d01046bace99b697183d89c5478377f17593f9ffdcac881b7c4c95ee1e7b54aa6504062c637b4b123d5822dfccd3537a3e13932559fb51511b14dce1bf23e26208b0eba96001287c1b1df97a53d0cc07ec0994df9f958b4e5a7192147c762caddeebbf2ed2bcc3610d4c44318ecd373b95e95e5b45122dd3d90e9c862ed382b8a6940ea424b1d820aa1f19e05
+TAG: f2dd916c458b2819180be842773ef3b898038a4f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57caa02fb3a79a955327409e13d3bc1d63073dfd9baa32413f130c195ad782150c43d8f5362c090db748bac67bf7e407a400e75bc256669f2826ca0b43d6db1e845fad0eb040ca24dc288525d4cc7d82d707081b95d6e60006b6f234d0ea657d2da99d7f2fdf7d684aa03a9b1618bf2d4c6fb1665e85a5011c9cdcea7f41fa657e3d8e01aefd387d2f9e431ae5b62f26e82f4e1ee7ffc75dbf4e5f64e7d1e8ad6d34a393af6833f794fffc088275
+TAG: a622ba9da970a02f9d12aa678a22c6deb59f2a09
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57caa311775c17b04807f4ca083e12ea85cbafa7bfea283f39d8445a21ff3d130882e26091810401298418e1f364965d0b95a6b5339149f898f75574ff2a972148ea59d5f5e9dccc1c305f5728c6b5024ca577d963d4533ec102b6da7f861a7846c9c446c828bbd74520a0f1782ac4d6cbd7495bf732438e47f1d69db326e99efffd87916d676460b4f8839e6eda596aa0675d2a60b6ba115642643f0833b96cc47b23897f6c54fe12eb854c745c
+TAG: 2510d24317a4615e1afa957d88f585ba24c041e0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca204171fdaebe8a9599280614b2c1ce84e1d2e413bc5aac9a73f021f8b606262ed2e5767754a053c6cf303b2e92ee153a9be25323ccf2f9ac8b117e29c3a78273f9af35fec26878c784207715ac6caa59b83f78cf1533ba343b87cf40aedf14f84c8a39831a83c79acea9cac96214fad06cd68b0d7beb7cd45707759563accf4e8d51f069115c18c67d3e9b0dc1f6abb35772083cc891d5f354b4a23e61b4410e6699b798494a17d8bb5611ea
+TAG: 823f7501b9af7753ab549123bac06cd91677bc5c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1deca010fb7067a9fe397c2445878bc01f88c08965f0f64355be203cb3e7c1089d648a4c8d53d16fe66e4702ed75ad77cd87c55305c3c71f501fab5252b3003bac2e607b7c9319b9e2991c95c3f92a97d07437791a5035bf66d791e484560edf2c4e3659753e129064c1ab77dd4c1bb471a49c60ec346cca84d6b89e20cbd173d0bf80e19db1432e1921e910a2d6fec3fb126d4bbb76505c6ce75bd241e82598a1bde8952547b81a2bf93ca6
+TAG: 19a5f0e7441450d3c7db939a16e7774d151440b8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca7007b7c4303dcdbb5092c6943f15ca8d9fb813db929184599228fe6a614cffcc7ac9cc9bfcdcc381faf46995a6078f8e3efd7826c8a5d5757df00edbf72ed8926b7b166b69bc8d121c53792ccad026148f49828a36a449ebc65c2b42129c09f8d816148b12890a02ba68f7f72298b1733f4a67f4b563ef8db6ac951d710b2d4c9ba7971066caa0e5f1a992ff16c94afb91a8a7ba6adab703e0b384e48349d487f96fe4ea8af79cc179cb8dec
+TAG: 00b5d0df4ce01f0bb496c19aca1b746606c48881
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca784b98fdf2bacbd8e4f58e5b573a7859fb564c7eafffec324cf54478335a4451f5195a1ad8810078197dd3b63f7773d8dca49cd58b90b3adaca93e85e2f9a6f3e0e0d4bb3c7369e9a43aeff0d10331e1d30b30d48009e0896a07219203bdc70e48ea3909d20fa1e6cbb3d315e3d40165d44df2c7e913ce805c6f5a677b9c327b78cb52cc910074240fafb2b8f7eefa5b961d16ce3c15f0db02788c38e3af46f065b0f8dff3c835ad44f5d9b9
+TAG: ca3133862cc4f49a45a3d4c1ad64b24bd6fb78ed
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca5bb609bd248736eb7b555c475a74812908c532a07c37c73a15f1c4991bbca5dde25e2425619779ee004779b4e5883db14c2ba6ca4a9189406404be6121d47ae05fea67809723e43a1cb7e90ff65cf737ebebeb7ac64cb4b027c43bcef6966354f87b80547433c98fc0d52530dffb2ea68d07ee0638b4d9b54b3fa126b6eecaf4fe35980600951946318fec9e18529ece014014d79bd031c69a8a899965a7dc7ad9e10436f61a4ff6b0b23732
+TAG: 593d5e64fcf05e6d4bff69e1cf32d625fa5a848f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c036ed67ee5ac89d5dea91dcbee2117ecfa214cb5268bf8ca99231d3759b9dcac90288e66947c8bd91f3ce9ce01abee3144e6a519ef7e262334d73b8623a362f6062f4ee6d17c0e0efb6020de633a3aa81ba27fcab235d084acb9a58885c780cb32479a3c2f1234fe8ab5f89b9c58d5ebd205e08d6dc5425ca0a5f7b834b990fdff6fce3216bf63e15973ab412b9a18fc791181e70010ce9689ecbe5b86f
+TAG: 82d6021f1dd05993e527886464d0072998111fea
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0360d0d74978d37b366c128e03ace2b1fda88ecb1b346549323698edaaccf3d0d2299d2aae049a1d6cb9d0c058648a80a6557ba96740e5cac434d56cec3e815682b76162c402065810cccaf7d6f57c6f8b2ca0510a57eda144e5fb4a20a0b3d1bd8daee8b75526b2451a9e31bc6bb2b1deb789651fb9f030f5ba0e7e5338e5d2a1b6166ba1eeead65c6423d1bd0346d0a49f2942795bf416fe1dd4d66da
+TAG: df9f2438033cdae25fdb1197e311b8d0dad577fc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c03615fcd0e1d611b563974df72e35233f3ccb61bfeadb4e79af4565ff79af28e05c2634340d9e77dd8ba921ea2f1f337d2d1176b97b4c55af64463e17b2607222caaeac755c9cfa7d6bffd0e71b9d6d81aacbcd12cf7590a5f11308acf3b03f4833b1d7d49a064ef54fe1d8305f74fee5c41b9f80a5bd25c62ecf5c688034526be7026ae2e1aeb930a8772a630538ac4b1a19ce79e4bdb9da59b5138535
+TAG: 0dd33c65fe201f7abf8a508b7758f71fd07cfcc1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0368d0d4b9b6c3ba2e2571c26b745c6d05b3ff65e4a51b5e00d0395db953bb2235c82a4201ed9ac354827c2144ffe815cfee86e7fc3fc6e4fce7b2d23342dd04d74334f96aca72002be0826d5990b0a25938775510ac8058b3efa8870516477d3c0760eb0ad37b743ef24c1a40e94668980dc4f5083ce2855e73e3d5506967f5e76fa4efae718dd806353aeca39d80ac4e87efc6e4f795454cca54687b2
+TAG: b5df25f1467145f762c683ffdce7e3940eeeb4a2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c03638b9a0b29ca60f12b33feac43695e9629d11cb6ba9c93d17a57edaea6263ddcda00f4dc3204f44603d6fb46ef924c3363e02a6bf35ee6d35e60400db64f25fe1c796b53db77798d54ec2d113e61fee81987ac414d15b2ae3b7d7d93127ae6ad887af7e26abf7352109b5dd0fec56a28c684c51ec1a328c5d643e5c45862ca591a1ac5274fd2af096c843dfcfa896a8df0d3c3bb67aded34321227789
+TAG: 5c24cbb0593240e9879a358d28fe88f5a2ee8c91
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0364ca6c12d043af08aea654656093063e262e5aee82961e86f4d07c6df657b24141c9d17fcc0559ca09d5a2f2d23817db9d53150071bb7b6730e950d1ac90da8f4edf073bb66a4c2a1e194652e66c26bdcac534bc3311f8c344725746773dce6904f599c330dce60f12b762e935f01df00bc658837de57fa05c3a94c898634518ff7bbc5db9a622e77cc2a5c97b94ab7e22f052a411ef0c2e8ab3c8362
+TAG: e4c302bed57ddb8b5f2c25ba734855e0626ec756
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c036a480c8e6c3db7fe51d4e411238800f5cb3ec1e68b86846238e4b6cad70e6ec53ae014f1eb8c57d5c24cadd6000f878f83676b0958355ee94e003690c22ba1abb4d12d20f30b6d46c9ca72c4176fdcdd8de37af13b032f81834230cbf198c6f9a263e9af1b434b9bc4c8c65498aa64979c2c6ebf199b215d097baa51853257bf6efed16a7c5d486044d0f4f7966e4f153dffda14b545dd5e326f9b577
+TAG: 6414f359863954d807dd018dd6411ede49f0c490
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c036a5cc5e00efb5abd26cb6961ca3eee41e505cfa6316fd8677f162074726bb2ea8b1c9f8ac536216b135fd51cfc3e68d524608964af36a1fca7243bbecefa51c1de51519c174b77df705f3571f87bff1fe1ae0bb8a7889893dc5acb6089c80406c323084298f5315bf6c32c962abceb1c835dac3b6c566a2c867893e10a97458263b6ec9f902f919312b26c149642858d8c9bf515efe135214ecd08e50
+TAG: 68b8a5bf6e79309b9778522afdf4ec939f052045
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c036a88980ec0e8b8f15d8ce68e3e35a55095df4f2d837074d7cf5f3e1dc22a3aa1de6a44ed333730ffa313d55f9ff8847e4f763fbc61c0b01228ce3e499bfcec248e6a5da8fd94b16f8778299f5dc610493fe45786738d896b79b77ba0c56af1d046f3f98f8db15448dad5d312661274fa501e26fdde227ca4d5ff16b21acaca5dc2c58a5ddb44cd9925db19ef131f0cb1f69d1ce521155a3aa29bc4633
+TAG: 91346962a9414b715307d41084cbcb4be9cce205
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c036861652446269c9504762c24be76d96c15be11eafea07d451499a2b4435797a1fd2c5507f94cb293a3683e7c37ab18c9dbdb58e801421e8d124a470c29ea0f329d1eb31c3884f6946bd552cd2431c94e9a0e0a4552ed57a9607c9c29f0907602d7a41e45aefa9c55cfd0dd79122ab2f3cab894c5fa630427fcf698fc2294850d4d74f22a5d3dbf064e51838c2ef8d62b797ec0d0360a1f13fc577dc30
+TAG: 3b3debbf2b0691c0abba67d9923049fc1adca1b3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c036b9677f9d4ba17da73d32124e12e1c3b67a625c61a8c4505f73f9c714509e84b605050821f887761ed3b9d73b9ade8d0539b089220774b4a434393fe2ffa5b27a6ee3566768ff89c33cbc9a49409d66dc9d42711b6c4da7a7b60d1a8c5d8f49aaa3db53330d22c81b18b305578b0ea7e3c33be22f93b9ddd5e3e0f49c95376c357a691c7ea1bb4cd1be74be07f50fb00816fd3662d6b10ff2472b8658
+TAG: 7682e11d34eaf53e781ff0ca2575c3efb21344f4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c036c3e4a1805866367d14e2aaa8815ae87e9e4c13532ec7464a6ca2d0e0b4c481b34e30cfc8b4a7c166077be09fac872e09138987e5cd4ce70d73027480c2477d608896fdd96db70dc73285149dffc3ccbd7d1f7fe303941416d7d099e99b9cd3cca7d596526cd63027840f853f2d67052d22b29514bbe93134f328630eede0b458553278f18cef1d187a63ce446e928038fe77c2438721f402b8ec3f59
+TAG: 1d759b5ed19fc631607f7e3017a4863beb7e7c7b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0360c47539b64f1b67e9a447f16b0faf78366f443ff1a72bb67b471560a1e628a515be5c7cd06dac3ecd89f753be0d0d20906ede2d84bb72f2c44a57bcdf77245bc4e6fd692b83230eae6df324cddcd689d425f681e58a19fb781c6350a6c851ae69c0c55c276b51e6351e2e39fc32dc4c024b062726d3d5c7dcd1eb6f6e22de41c0fff53fad4aac8050a37dce5ad4b16f734aeb51f33fcde378baac84f
+TAG: 89fb4fef04a9ea085a9b1db2b38d331cf4fdde89
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c036b1d5c85aed68f50642d52d7c8567eb668151e3d628ed44aef77ec5085195ebe66a362983a8a60fb527883ca0ba303d4a57880561a71241ea058f3528cca6bfd2ee4b57c4c1e031295afc950605f1a4fcb9fea7d5233d33c85dfc725d99eada540c5cf799a2c9a54e34e7e3fb728ccb0c300f97b0ca811ee2d148e47899e9ce58f6e9e5df757c1377b5ee09647332a626f44461b3443918643b9c6374
+TAG: 9b0aa7a91faa443ccda3a6de7a30af8ee90c6927
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0361ccd884fa8b6cdc163e07234ffbea4739a268a525791333d94468d998abecff4c5c728f5ebff11f5c507ff62a49fc90b83364441c6a1b5eecd0a0fd13fbecaadeed3cde830e28981ef94478334dd0aa7864bdf184caf9e7fe423472b466be451df40a88fc92d8c450e5650c1561373fbb0871ac0d92e09e4187d9afd83d6b7a6218eec6d92898819b7af0da7506f9c99783e34c42a633e930b67c6ef
+TAG: 4e2c5d0884373ef60372442c3c2f9233395c2817
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c03682fb02bd02bc1e5daf4c0bf3c37533de8c71522d597e5be1963626754c0458183146462e39779e755dffd85726194aff58a45fed67fa98bf886aa16450df02c646a96d1e3f58b3ce43e2d2d602512daf5c316792e63610e75e352bf2521127b83ea4d27397df4ad608596b27b3bff2481dc1d530ce6d767df04ea9a7f6580e885b1e3ad334fe750226bef87fddeb4be84497a30edc77e84fc826eb57
+TAG: 369f693e2d94b3a8b480844b88045ed2980e45f7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b9cc5dbfa8e27ce93182b06c101d179aeec13881a9b5ea20b97005b668c0acb6e33af724f2654de22ab8163b8b4de9e7256b39f6a7a8e3f4813aa5efffd6df705d5332cfc3401fcb63af80517065879b98cbf7d8427dd71a7322cd99ed3e1a5939cc58131aa4068f1692c5e19f7d4465308cf214431676346f0ba4be6847532f2f0a48288da83d4277b3728df
+TAG: ee3b0d0f5567056517f9c42cff7b3fff3c36fa56
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b85c3ffb952fb112d4923a5b8fb7facd04d5679820af2a765e846fe749656e0ad1c498d1dac8d3fc98eb700bf98a2719df812927a3d5feb3eda5fbcf8696717d280cade0c3dadab21653b3f7052fb267419e33dc964e786eddea0186a54fdfb5e5583ffd4c38b937ab04d39b38c4b81964012f1e0998382d5f6da5439a0ab61e626a5a4c0bad2aeeb459e4512
+TAG: 4e052dbc65c977da18256485bf83a804ea07bc23
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b66f5768d59c85e8cd17e3ff4867ab9269bf1ae65b0a620b88d95cc3c679f33837922d9cc2864440f402c88ab870203f6421330bb8131786929b25d56359d0077e23384772d12085e770c532df80810d81d239fb4c237db9d793e859b485cf11d7568c73d528477484dce1daa144bb017164b082cf60c3c9565e39d84e35cf80fb7cec35a63483a8ce34bc7dc
+TAG: a021a7214498caacaf5dfb02cf6f69779a3b0fb4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b681786eb44c331d35c79b0069da4cff4a4eb5592689e5ec23653b9af78e1c80557d110586bd2738dacc5c60a3d3f160c90583d3ca056a159a5573783668e56524a87cf3da03aabc4a69360a987c124cbaf38abbefa7e478569aa3a1c179d481aebcba4681fff5582bd0a2099a2853490122dc49f0739ae4d9f00c34cc5727278953daeb15a57aca287390198
+TAG: 3d02b9abf09de24a1c24ef5d171781cdaa6023fb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901bb458ad16e44ecb3dadb1563edba907f6aace74d118568d9ac013f532b8abe1700d8276e35b412cc8c42d718e9b52a052695e983ef34c8cd3e9d8857a8a4b8e8897ebe50996807430e9239ab049528e0fb9601b88ea25a6ec9122d1e18f1d8c462dcc820050e72b082b349f8daea08e99712d23eff5327bfe576412df2e5b059caa099acafc09c459d5ab1750
+TAG: 22cdb12c451f936d6c114f07927f5adf58a4d3a1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901ba231e5366ca76e5e06648a62103690f45daa85d162cdf4d945a4b15cf996126c54c989b5f69be9e421696b0ec5ccb7c4fd6576fcd78442da50bed96b818c243b993b8027e50f44d5d136343d39cbd7351547bb874de9e2115a47c28428babfc9144e6dd757121fe4c1e40f399cf6a8a4323a0be70414df049805b5b86e871ec25c90a319896cd99a9b5044de
+TAG: 68256005517e05f96df55e337224e32260c13006
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901ba9d080cbf30b1f5c071abcb2a0a4a6d0190e06ee83350bd021d0c7a03b98af8753d5b46b853859789805ef2120770b1c0b937db100446589b2c7f853954efce7cebe0d46343893f1029796090648bdae8a58c893596c76a607b18ebb1f4779c3819054121d8bae4a276bb8f029e21d5528be76164a34210b8ee84d67863967b5e0caf1861129e5ee54982197
+TAG: 8956d28fca8a66065738f0f364800ebc10495cc9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b8f640055dd03d5ca77c2914c1c0518faa4932c8f7c757c27476aac132ee40cc70e571b7b84ac4d360b98172b9154183a2d6000ba914ab35f3747132e6f3ad5e9ff798a801e90ad7cb92ef6812d595fe21fd5bbd5d3f1dbc02cdee9b1e5793ff42a53fdbcb1306fbb665b36505cf58015f9a53748c9d1bc565446527bec31ed102fa8ff209b7b4b0311f7b3ff
+TAG: b7b84e3f94199f78c473189427f8cda7b9fcc373
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b27c5309bce69b2002cdb05d92911925a020a08d3e0c8794ffeb45954efe223215c2d80195d8410dbbeb607d842b482de1c43fc93a3293001a6cdf3fcc21e3e13c8809fa0b36cafede973b26c27ed333a8d73f13fcf01839dcff49faeb6799d6a8264a1d7924b09b0a7d867b039c831a4bf18f9b71728e37117111228166c4d24597e921df4d9153aff37c2ff
+TAG: b183bbb10d58618518f65947466902b3f84a9947
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901bf09f47bc08cf21d22cd1bfb820bbeaaa34e7973c84732b3ab8e041bc5e08aaf8c26cef3a34dcb75279caa8746a16eebc5d1709a71a9fbcf1c191a5c2ea476dd012c1b8e5392d501b687134a97687cae429a70bf721a9d81cbce47de658776c7618817ff94106c125fa7126b199d720a9c62acca937a86f3a8359743472f46c79617c9267cba3bff55b78e181
+TAG: 956ea59f980c55139ed28bf16367a3da30a316ac
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b2e7c62e759b3e58c2d8c7af6cb3f4e778b8cc17e756c1563300cb136bfabfe1686393261cbb9f16b12508a4e0ce1927fb126fca6d774dc953f80267a4d82ca12778016fb619363236c784067dfde9a2f3d6bb38aa5d858045b68d9d16df9e97b66ec4522aa8d8ac67bd1a8cf768590600026c2ace36dba9e008af00b6370347e746712d35fc20e32f3fc6c05
+TAG: c83d73c1f7ccc571dc372f61536477c92af4fab0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b083c701c87a3814e58ee83a8cc52144ead842df9344a8faeeadc0f49de88571e5a8fdf6b007434df7018dfda6ff3afcf82a77fae949e826d178dca36504219194372112731f8a4f92b1233c3cacfd77544d9818b5a5de753ea60aab1c6aa68fb2eb272f8e8080e865846a16f96012419d00f8a3b3c34836641fd633212a87a434c4120c41f2c51d1dd71d7db
+TAG: eab2c944da38558d408e8aac16759a349b62f4c4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b68f93a9582e4266c8a0203129d3856bc343a54fa5fb35d185350028fc2f796020bd02cb4c3bd8855901d38e40037a28e906279881d07aecbe6e310f603d113fb69d73fe113e80fb1d3517cf1fc8b19c7d7213df6e7b040d63fb36bb394fc641cf35041446d3f48f235b700a6f84112df638675af933cfaef51cd71f08eaef7897b227ed6339650a7a902831a
+TAG: 5f90b881ab2ee554bd375b3d3244f1fd5257abb5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b617efa3d34466af15c9ec1f7dfda5ae52b81cd868b72564431117cd576f6fc944fdc374e1303002f33c238a7a3d4693ced7fb0ba027ea6534db2041a63195b6ce439c9a45ee2f94a9b70301298141507ff831b26bdedbb737c577df28e64e7cc6dba882fc769f657c4691062ff67fbd416fbe6af886e39c611976e741d03cc17f3aeb9cd8bd65a7d96bc4b51
+TAG: af3cdcfc4e13b11abc1682c970145439b8d780fa
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b44304c1dc06c937680955e0cb6bee9740d4fd551de6b06c5f82fdb9f26fcd50a21b540a238c706c45849668d3abb64802995af7873d051f33a703e37ad22b685f5b1a8e360506eadcc5c8fc15f579561019acd9f2b737b48bc5cbb8b251c267cf4df7df83b6451b6e8a91f2659b0bfd917f9c68c635a31d9af98aad1a7a7a62e5935a2e0c040e48ded837a0a
+TAG: 1b9ca5abfd783cde9a5466e3863804c98d6205c4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b8090c4d36602ed11087bc53dc22df779eaebcff04bee06309e84e702477813c7bc1a5f2f0f62dc1b3d7d92329d17817932e94e11832a0e85e2328451e63adbda190d63863400f847eddc7c3bc58c578bb4c46d0f3c2119cdad0ee95b6a4f4d82492f6c6b29fee08102759c3f0bd35c0e03de4b0d77f967cf03b49746aeb4d64e395160741242c5311d6eec83
+TAG: 56f123a96d0620336b97f7bac1052093df9fc2a3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35ac5e6db62ef74efeb8015b69e3bb0e6b8bbc51b1d3737e14e2fad84a8cd8605e63e8a822168a04c6a844e35d6214a4bbe6e813054cd8b3dac97f923140c49e02edfd35f10ff9be39a8549c3017e02b4cac6bb66ba3290b9a704a06c4571a63aa3fb871ec0903914838b58584f49f196c167bf4fffb84d349350c81a85
+TAG: b20adfba55cb256cea0eb092db28aed67d8ad417
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a324804815204c0c99a1d63a6db4250278cdea22d9cd3b0a8fb82d95f9cfb0d3098c3358208bf80e6883c6e76d2fb85783f3961a04b4a289db72bcc48e27ea0382edb0f251e08a239a7c89c1cc828262093824147403562981f0f1482468444c9511e25bc1447976c8cb78340ccdd829dda39857c74e740288b4d817f
+TAG: 60b73bcd9fa60899fe2b270015508866ce3f60ef
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35af62a42bb25b423d952e08d62ad7ace8a8fdb8bd57d8a134ac1a3747f229e8cd8d5a9f619453cf1018dd65f44ffe8d2e43732cba33251911551724b5225e1f528157c43bfa7f38a956389bc1a6d9488aac14c648ebad7f69222f3781ddbc890204b1174a0cd5d837d1b081499377f1959b24e1989b65ff1c4a2d7ec73
+TAG: 4bdabe289e2a9f241e0cf296db9b3c76cf89de25
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35ae961d008652bbd0299c7f1cd1e9b41d57df6925fab9838c2783cbe2fe9466e7414a6faf5644dcdef57db1f7fb9cf8b7a7c63f08da941923aeb276af5dfa210e4b01ddb563392e4ada1da940d4197874869ca0a4b18b2a116f6194b052f9fe24b59de86269cfd47394ad4241dee8291dfbf1bddc52fb00d894578ee7e
+TAG: 024e05cc0a371b39f35e4ab27a502f93383581c1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35ad82bf9882f202c0c11597e2482800d8ebc852103e9984a63704ef1849ab868f2bcaf610c95fb8b53e31728c6778f7875389c4babb9e4a7281f238bcc3324fbb2ef82e9c466eeb6af6a64ffc93badbd2a3ce6add5ab139ae4fbd4fb43c35fd857ce22e0bda428680f2413c4fff4bbb721497984bbfa232457e7d1c21f
+TAG: 0cc0ec5b8004aae75b5e65df32ef16126617e50d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a55266057dc1768c77a782e76ae4322b51a7add8bc0c835a05f9ad1810b142e6bb17d8c2e75ef9c24d0511c10c7ca1a5baf8bc79ad0681396968d4877ad82d12bf7e661b2637a0089dfc2e89ddddae0fd607094b4eeddb5c223e7617822ab4fde1ffa908de5533541f5f8432f36b11a54dce9a0759975298faa020ed9
+TAG: 9ef3e1e73953360de26623b0920c2a1e26a77fe6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35aee95333843b7a2002225aa08547e42c08d92d6a45b9b4711eba15c513615069fd31d1fae3309c265db97bfee6710785e949623bf72248e88321c59aa56c00f32ce5fc9056be89e5ec45b07ba7ce2c36af31c22bb6d814f56923e312aa45aa5ee78c1b4c6c41dc0b4b174235e3db1000967b1a76ca2dd8af74cf69420
+TAG: b9d5bfde59bb38f58681fa20950efa593031f15c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a5941f413ffdcbd794f1792a369d82bfda0987b2b7f67706e321bf9bdbd3b7556983e6df473cf39ec2239c89f5ec3de22e790b3438087938bc17b92490bc9700fdb1d1d925c6a88010ea5cd92b5c58c4d8532a99cce8846615d0ee2a8df6e9e424e65ca3eea9eeb1c38f749c5d648e1ced0f2cebf3f13bcc942ed9049
+TAG: 7aa48ded84d487f46d5100f328d33bc349ba764f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a9ee0c05fb137dbc1d2f67646eabfefe9dbc28236c8f807ec462590671e937b96206246b6b85c2a33ddc3614698400fde8d0b927937698c6c9ac935c63850180189fa44fc09297f85f29155506ba3ccf6b5615186d8358bd05eb735b27e611ee051e05f710995398ba9398c9e009292ba55338b23171b8c069f380c75
+TAG: d5c5170756253d6a96841a5cea70ab247c35e904
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a47e75a288e7ad4319efefbdede7a0857a8081ce6746d49aabd4b4f2ba8c20d082cf6bf4b5cd05bbdb43b1655fe8b609da3e23ee227b292f1011d395693043be81a9f604d956894293a12cba599299106807717ce971001aa05e0ec9d39be3082f0465c82121b1f49bcd2430e0a0fa541645087680df12b1ab80a2b54
+TAG: e86c6adc7f01f083ca35610bd5f22ebfb78dd1fc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a0629f957db204898fe27a61b405481fe26c5bb01c5d97a65f9736dc50694b7f206d6b9ac37c668f10cade5ee7da072bcc06dc4b12f3f0c2efe835203ff936d11eae15edd63718a2b3a5686f4788aa9f1a2cf0781f3a5654476b741c257072a293555aa3725294e41b8f5c54bce7cc1bc1788b9592c21308718dba270
+TAG: 51114b8e3e90001359f145f58b2d9b3dcff7aed9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a7dbf7e11b17664aac5ed109b440f93c56d4fefebdbd047ed56e2377f9635c7f3fbf196664684776fab791bc34653e0d0bfe00d0a3452a8bb6a305290532fc71da325038664f21c3903d2e1b55c2a270f8ceaa1cea4b73db70bf77f8985ecd1fb91ecf553cdd9a4414cb9026235ea1529ec7c08174123a226184f51c6
+TAG: f4bbb2d62b35bb6c34ab361277cd87d793571f42
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35ac45e1a7b7210d36cfa15a3897ea58b430fdf50a44d5907f59b0689df87b9061ab2917f655072cc5eae46c1d8163f235025ab349f00028fdbf819e67ce585d8fab736f73f9a132b2fbe1cdeb91c065faa6bd5347fb6bf6e0f7008742285aedc05a4766b0de3c6458158f87ce5a811f35252ba2685c1a10a7e50c8943f
+TAG: b083faf57f0a2eed848d7ea95f2caf8a52a0784e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a1873b81c324fedfb7a30874bb531cd1a6c661134c3181edd25e431d66d7765dc143c9afc3c641aaf0b46317af04a5043070584b8cee0d1d395133417d81c2dfc4f5896f232625d8a120159f8f5d28865d8eee1c717e693d30474191d438680752304ed208cc19f724d6a90937976986de7cf9272258a87272a9c9793
+TAG: 1d3f7c28c9866e5cde68afb173c4bc6b8db78087
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2451f6c86c3d7c32a3e2b5a7cb1f9014b1c2fb510c18a679ccb7a01ce030f5866848f9066cb431f2028e856ab498d8482ce34d2edb586bf2898583dd5b0e20bdef796f9e1e539cc13e820d3b53b3c4bfae3ead6ee4f3f1d217b946d53c3f08630feb98ea3947b0efa064650c2be7ea61945db0d42dedde7da6bab7c4
+TAG: 2a4f33438eed2668e9d03c43a2aa91cf7eb78905
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35af5bc521bdb3331f70bc6e108b2867b703b7e07ee77d3977c5a7610f3201d20b041bfba78439142639a931261be3ecd4c243ee936ce59676c3564e6268d255ad754bab9821dff795f4b02451a273b33babd380bf79ee016a56af9fc2d200d95693816ae33b5a17e6027aac69b4ada2242753f454a78baaf19dfd14e85
+TAG: 20fa1057aa2da5f5dc8471f67c924f275dc3a800
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831900c8101397d770df96fb1f6e5ad5b24746aa5586d913bf8e7de42fdd954b14416d7f23e6efb3efbe1c9ffaeb7677497692e901ed2c39cfca5b5a03aed9cd3f322063a1aca1999a8cbbf626f239338ac205482aa6b7c1912631a5414f1277bb34ee7da9c883e3000b214cf59c6
+TAG: fcda8f97d04b93c22d42b1f77ba8b30637e6d28a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa9208319028372b62337fe9bf92b5acfdcf364278f9ddc516733049b177b726d43887beb9c9d6a6d7b5c6934d52d7b6bcc60bdc858497b3349b2f2053319dde939752275ad122b3f2a188245c615d3ceb57943ccc63d3bf45da8b5d63932fc52edf0b9b3f6a3b0886f63ade65dc3aaa69
+TAG: 6a58e81131d0608200216208d0d86dae63278248
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa9208319054aeaf1cab8a9d96513c49ce0f536a7dd94d8602ef98bec7cbeced6651281933d1cbdc32684db2e507af113d8808313db0d46cb1e86e82d674b9df185de3802a210fa1b1b9e8fb47724c3a3c48b30ff3918b821d68b09ff536b3c9a60d59d2f38799a327119efd856506cf28
+TAG: 56aaa71d8af87329bdd488723ea5b0fa44767fa1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa92083190cba5f2cc79daf55c0a8e122b0d9d3a5e3b0b418f4958f6677110f9a3415866ff557b672f457f119aa9cb312f37544953d7fe6f6654233ba5bda98ba6fde6319d31bf521cd1b25e753e01e92f9a909355391403e7c66fa8bf7cb97b3cb6ac4315945c7427e6e173ba0d779067
+TAG: e3f479829716df4da08139894f33ef69a322182d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa9208319008c66e75d6928538553af50ba78d91667149723dde3e63caf5ca4c40a7254e976a01a83b996cb17b50ea76d90b6d89f7992b1765d14b6b10405b1df99d8683d8bc94cd4956597d80df23a2d9c3d7fd654f5e5bd5b8ad108e3d53b851f5ba83f7d59926b3d7da32de28460da6
+TAG: acb39e8591a728295a5728fea402b38580135074
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa92083190a2b35a493ea2d1d3519c59b7325f531e6c0343943ea35454a3b04a465282fd5af9d46243166a40b3457001e766f0665036a52341efc8fa0f23774dc892cf89c958da476c3596474501a3322549a9bc138b7ff611fa2ab9e0d3e44a07732bf89e41dbeebf1d4f0e095e05f11f
+TAG: 465293d68520a04d3c4dd475330298c6b951f13a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa9208319086280c353e7579e8172dcd04239d1b00621e5a239c51da4ab8c6785345eb8dbbe954822f8ddf0502bc7883fc79fddf1d2ed593f15df3e39d40c53ceb5464a979a1f85d5398c9e68edcaec0393afaea4a39215f8d2b7aa2eda93a862025d6e5fa3da3b2f55d93774ae7e6985a
+TAG: 9f2670696970510924a2d956241035f8877945ce
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa92083190d5fe89c5e5bf88f14f82e2cd77b78adde511066a286b7df3c813d8937c9804a47ba246a1ec095d81f29df74d28d3742804a7b233878582888fcf383541215b882da132f301d123c6cdda099e06266205ad6efb385eddfd9f6574ec201b975573d6f31bb75c9430844e17c782
+TAG: 7bc66372a5bfbbcba3433ddaa72214c55a5946b0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831907106c70be9fcc59102e7a5d30a943390b62163ada6b779fc08fa2fedb2549484e194b9968093ea174f1d331241e61706ebb2cf18cf02295e701a664216effa3a694a8d3340b4fa82bdd1c13b0a1bf60e333679c9a364710ed8ce2ec2425395dbcc7e41ff74d41f3f2d770ed4
+TAG: 27fae8338ed14cbfc8e9a9e21060a44755d98703
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa92083190b3d84464610c884b42bd485690d371e2a0c2448ec97c036394521ee045269bf500a45b5ef04de0ce7ab33ae7433b809f6c2e0901de1cf082139e0398fcf2c97a8f746f10e6e58702148095b77c894d3a81d935789ef5bbc33b0be72745c7b818d470d20cb55117d254c3a77a
+TAG: 31517cd3c3d3e1a2f9395482e7269064994000a8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa92083190c5c73d35d0b2380be1eeda8bc20d3a37ba0389392ec3224c65e7edc0e6d6ce73d5e66ca406bc5dc3262e3d03952bb6ccee02c1fdebd0e74aeb3430ba4cc57f10b53805a6ad3c0f3151f58f0e43c196e6918fb641c82c6411a247b3e222bad21c0ccd7c38ff34c2c07b347583
+TAG: e6786ec51d923c1e0463e8dbc9f4e843b2bf5f20
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831908df3161efdc36c2bed60d693a55062f113c005fd81df1632b4c694b3f5d2d2a600a4916a4c9f3e7b5ca3875c785d8e40b61578fff75a99dd85adda91fd8f395fe975be86a46728c624a045765088bb4ce278089d8380e10e1cdf8ebaae47550aa21fceb3c6534f17fddc28bd
+TAG: 23666122b903583ea33ff94963c7176baa270546
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa92083190616d64020be87355d27f8d41285083a762fa6d65647733e186a07ca78d9e3f6e8f199e138c49a273384e08635078df861ac1b1118e371aad66bce6176eb40d621520f607eecb36c09d61899cd36a6341da6a4e7fcf350f94a618de395ddba9e4f43ac8942c16f42bfba6b687
+TAG: 6010ee1a6b1fb64a2258986e4b72c25e022e369b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831904e99824ae2119b36d75b8c7378224f1fe8bef513d8eff1c0f3e0fadf509a944b0c5a58a08a16f41bbc2a02732362d12f302d56146bb3fa1ed8dc0edbd12b250f64b9d57705e7f1437e3b6a05a7b58acbf959cfd929f8ab10200b5559ca8f1ea1029f17baa11f2cc88c44566b
+TAG: 21f491c0e62cd75068335552b526e646b1dd7da0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa92083190afafa12154322db32286a6b46a89efc7d19eb90a964d4154a925347bb5b73001707ca9e6e0098d2a551963b1a42b4bea80964d335d6134c6979b79907726f1c2d96959ba1834c88bcc8e22ab3c7a355797606bd844570334ead844cbef5130c4456735156ae3532b787dfb5a
+TAG: f36fa4ee9cfb82aba13d666710add00db9c9757e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906cd4a607effc96f61d250ba596034e7237852602553d720e1cc34f7878f3090c443b20db730c60bd481b599c9ac2366623699d855d6e3724ab986d7315e6617e18e610e91fc070160a588a346f63852a605e118605e9c24d7620e09ace2e4dd88f2ccffd141c8ccdfeb46ec4
+TAG: ad80ad44da86b3ad8d799f6f383bc05db63f7432
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c116141047fa9aaf84344aa7bf20ac0928dd154d83f60b6304c65f7265a7b826a4b5e4af40e0729ebe39ecf2fc5134710ce0997ae978dc78b8154eef2288d929680c150a61f0ae0cbbe26fa0ba901290340597df92875c1dbdcbea7e863ec6359e
+TAG: ba84b6458859c40f8fb43efe70840ca9de5fec94
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c116141047c165a82e38653eb88ef84db361dd9b48c935fd692d46dcb84f7e5c2b2b18d09a59d810172e53f865c2ab60adfb6044d9cf4cbf4b9dc33ce949d3d12118796dee25e1d028912ecf154c0e757f2188e3fd8f0afaa68776f7d35d6d9eb8
+TAG: a0326c92d3084e4c5824aafaef50ccc27538f55f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104755a4941c2f60857ff6e80bd1ea5a6cfccbc6e673f81cb30c9cb2c9da04230e3eaca9fa3946a8f6eebab33a48b0cf8098fb8f8fffad0ebbd7b639197813d144d2774ab368e56c7d21317360dbd6d628512613604e23edc9bd1ec44627
+TAG: 12a7e9cc7ff5822e48db7ac792dc38e0b89cde44
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c116141047bc52add8725e90a704cc544c18c55a5f26b8dbd80931dbb2bdca4e7feb4761c08ac53aff5b67f171ba75555ba4a02ea92bfb47ac13d707c8863c614f61edd4b8a370f94840b0f4b71a848ca1655c94400d5f40c9e6bc094b7e1ec2c7
+TAG: 7ff5385102256d8a294514a32b8af13e979859b0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c116141047a807c399a212080bf46a0aab9318474c142e6bc54957425861bdee12c25ac4879944d1287301b61409a6cbdedd00c96cd2a27198879c0a5f48a67184ca31fb843b9e2aedf474a768cee7dac5c4edd9b8c8f4ef64fa63baa3301a5071
+TAG: 606920e880ccdbc02289fa5ec99e8ca7d83ceba5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c116141047101daf826d11e16c9c446ebc098221962ef8d59c96d7381ce873a2559043515d975f0dc3b8198fff4a9663ee8c3fffc47238df53fe4606ed58e99e8ab6c75c2b993b87e4650c69add83f8e577b65b480b07e3e09c9210a988f5ae2f2
+TAG: ad6021b573dfdb7f6dcf03741816846e5f89ab34
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c116141047083d07981b07998829d3df64f98882aa021602812b940c0947d738c0b6f957f26c3d5e497a5e17c4c27e1ea56a0da64a629df99ab2e0f4bab31a5c64ae69be00d7f9435d4ccae4353d518f4b166caae430108934098222d2c1a4cfed
+TAG: 7ffad054f571bf7b15a33bf2d63bd1b958b82ef6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c116141047e9387e48f154de2d9436aea7fdd09499324a2c35ef5ed49d769243b09cd97481577270407c8280cb0c7b81ac0c20c3768a7e2de6ba1acb5e4a140c5ccef96aacd97a1e7e14d432ec5474173291bb33a877b09d6b99289037f7df4065
+TAG: 44f9896a991a8b06cb1fb3ac821c790935e7e141
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c116141047a8ca0050293db8d3f058e9269b1b76966d2171a638f48f775cd75b40fcdaa711fe966a77ee25c089f8aa145260a6ea861dbecc084ef71d5bd74782f1993e935ef9dfb1410f2a5077e430f7d1aacda7acbb1a48fb038653be08df3221
+TAG: d298432fef722df2b351cd3dd98e628d42161564
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c116141047f4dde9cd1daea24c1d4a151f881548d91d1411c304c6b9fe5d06dd794d2631f1d2e7a7138d6734fabc7b37a6b960191ad8146347bb8f2a75d401a1b62417f793ac365ad3dffd23caab3c2695ec8aaa671bcf9b8c7dd2d4d5cd2a8c5c
+TAG: 5d38382bab817383f846c6c9b4edb417d5b9d466
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c116141047aedf9fe23dc32e6f5d55d73bfa3b8ef4d3030cfe171c2a28c30e46d9acff763752815364cfc00afe89e0a8cd93227457b25e5a56bddec2489494297f33e8fd7b7a1a871f7337f04d0f8c63c8e615b6470b78881adb326dfc9c1eae94
+TAG: 6ef74447752a4774435e00da7abe997eb151b7ad
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c1161410471e7c657424000e3c540fb033513ce8a4bd3e8e19bb691af840b631debdd424e3d395d85ae2b705110abc530cc1e3a2fe1443910812c910cfc190906d4f72032d82809476ebb68cc20a0bd9e6d2703d700ea5b333f8b2994440cb7310
+TAG: 8f1ec70aae4ad69ae1da278bb70cd0b3a5b141fc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c116141047b1a862597b016c6d814d541ebc0d10833c186d89ba4a735ecc5165b32f7c88627f4b1cbb7b321baaff0481c7a88f7240d7de10f460ff8e894291b25b92c001a55512640e0ac259b828ffd9b73129f66691844a8438df214a667fb6c7
+TAG: ed129d638ac4aefefcba2dacc0df427e6e47edd5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c116141047de6bff50d76cfc47a5eb1b45fe52aacf5e8b338e523d68a5672842494cd0dd7a749dc52826a7e69068500cf9ac816c92f6a308125e116dfa55a355a74d9e10a08c8dc21e9af8472b43bff7172e539c740ed4680b3596383dab96fe48
+TAG: 56ddf2a02b7c6888cdc88544c3a4e0bd01ed8dac
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c116141047cd6612d49261d8695ac0e7566ee1575d53ebd2e6878af1ace30a477e81597ce97197feba029b8cfd8163e6a2a396a36d844ce6c9a6cbfc404bd1a2f490b337791ded8c673902a769189da1d6a687d77f3aed796156bfe22b0e960748
+TAG: 9a1575355769c11e74323d0031d2e4ad12461578
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c1161410473e2eb9ac25b12dcd7ed6d67a7b96be6b1c0b2ce3942ad15d948e6e79a3f917475024885d8509acb2116a8c6cbc07fa501c9d6271e0df97daa50e39eb096d38322babe0ca1328a3c45b60315f27ab40039a2ba148308a07955eeb4738
+TAG: 594e733b2130c0e795b5dad2236b7d360c49c225
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6dca5b9640c7c0da35f41bb00a49f79f652172b979f3c4cd6630b03f88af292c3d4dcdb5604ed380dd74d1774cc9b9882606c11e4607aa94db08b1c65cdea2dba7552a31aad3d28b1565939b0
+TAG: c9de19e361249c858e0af7b1894682cc36d0ddf9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6933104b4870ebfd014c3b50d03df929c631ab1a96cca9894d25e7bb5ec04f401a466e409023f5e7fa502fcb3d8f846e29bda1d602445e5df28c754113a2587e1fb9b5cadd4b076c6fa3e57ca
+TAG: 08c2e1a1197617f34a61a3ab29876a256b14146d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6075e597324f004b34ca023b114c030b9d78336b655ce9a1c3fb5ca4e008c20ab39b5e353bb92efc4e02c614d30dbb3c996ed0023064abde1fa54ea6367d5013300f08a1853c7ce0071ae62d9
+TAG: a3f4de044794d9d3a06832fb683e275d2244de14
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce60a712536e54c3842acaa2cc9a9756744f168d395bf595b778f9994a45a924ae04a415ccc1a83dc41cda7769385ee9114ac6c1143f681e06c50109921fc75c53e5c2639468de93c2f164538cf
+TAG: 9d8991a378dc83a0fe075fbca1c007ce4527ed61
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce61046b32203ba25a317b72207f76532102891aa0cb98680bd0a6682a15787158272197b2a05a82486c10d5818a0e5b2a1ac7e44795608753cd5b4e920bc4b57b3dffecbff4c373e7b6a7a85a6
+TAG: 6707d83b0dab0dcc7b1af01dc483def1c09709d6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6f51ea1baa14eac6ebb25c894bbb0b0f1ef93345965a1bc5b46f7b77287ffc5dfa45ced0b8c0f337d180babfbd89cb73f89a6d6ce3437f3a833dcbca55109d6450263991498624f78dcad432e
+TAG: 70898d6c762d0a991a95ccc0bcb6a6c00bd93ad1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce605fbf9f3cc2901cc8748f4838795e7241640a6e25d06d99dbbce45fa00798c8bcf7121bba5071f88405c24e2db95c6d52fa3fc3e84cd2c129e448d4fc4572f61cd5eb167cd76cf86a83eccd1
+TAG: b041b1ba1dc9693ed4c9c3048842a66d5b0f884f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6b076ec2a88a0494fa75fae994ade65a14433805ceedd17e22978f19830c84e3a94246029733e034ab7a76acf2db5b564fd0da5d1b5287262d534f18c2f32b329f192367ac482eb86cbd18160
+TAG: ecba85db050b2471accb0a555ed94d354bf33ad7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce61e72bdfdb33f5b3f9e8ab9b1bb9a832df8ba04bbe6941b551ea5532571fd5b48d61dad3169e157ccbda40b7c5f6885065b07c6c678546bff3fa3b715ff754acfb30c3d982b9556eb41bc1d2e
+TAG: 9b22efdb32f9dd8fa9b4c85a0f6dfa0e19907353
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6664133a90b40b409694781d907367956d2ab2ee82be3dabcfe9ba7cbc7a33952e72d9c54ad17d5b10c0f4ec864aff5da6583001a34a8844aea48add4b6d77151970da0b22d2726816d3c4df3
+TAG: 8bb5442785ec4c6ec7d2b0e45d8859833ec667d1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6bbbd3530618e26b02b4da998342dee5927a38b0e723df015269d77be326267dfd5eb14efae355b5a5c5b2733329f2ec9d3252b46be009d8840d06ef54a0cecebda3768f79f315126ba931eff
+TAG: 85a7b1250dbff94cb39f6e78c1af942ab2782b14
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce61a922fbf43f23c3cede19a8517983223afeff8552848863886af4fe2b5854a908c0ac1a2a4609ebcc28fcfe20ac503857acd04a9ba03935bd34c1f873b343cf660e4a81cef0eabb2104e4644
+TAG: b17a2b4784927dcf315aeaa199dc21864fa53e58
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6e206d2d6eec5c001a6b8eba1f76765269ce81fbce947a325047bd15af8838005212c215eee7c4da8d64b4e51c66433aaefafc50047876e59f761f0fbe1fe521b263a86d3cc9c027c9443711c
+TAG: 0eb19d3def4dda1a63e677f13affde261edc99e5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce60c075922c8a02cf7615c6a7267d341f310825f9c871d5dd9103998eb737a40a07dcf13634d0d01f49d78c367a9e2aa89883c254b76ed01bcc470e653170dba24d13ecb15d5e52f9a0624de70
+TAG: 67ed29aea3611d18eb1f11fa8fe59c832af894f4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce615de261a7b79ade1c98d2237ccf27e40aea8bfa67f3abc6f3b079bea63c75e31b4c0746b614dfef9abd2bc35f499868214b0a5ce690e0d962749df7bc0043bb90298951fbdd0fd779627cd23
+TAG: 5a086ffe8c5110c860060b68e0ce9af0ef78ec4a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce65997b74ce3bba5431ccfc7f80ded6fa45814454cc38a5caeae0d5e430e4805458824d5a2d2bd5252e062c287832a6c2e1cb3586ab1e40a4c96e6a92ac2316f90b72a5b895b838a35ed80c1d5
+TAG: 5c2c301edee89749678da8b0f5ab66a8d5f95b34
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162a3ab476bbbaa0c34d6e5bf43c33ae8106a92530536814fd9c64056734272d19350183f07507e44dbb458166e9b42c0b969b506df95133312cc6efe73c
+TAG: 4b25635e517874db9ddbe0b49ad53be91373aefc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162a043096e12a22e8c62b68441dae8ccefefdb20c9e4c8d934318fe00ec6b43d95d512708e6b63fd3022b144de7a784edd36af2ecc7cbe149ff49f1f04d
+TAG: 013b81ad21cc3ffb9d49555170c97e40a6698579
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162a5f626b1a77b92ec447c7815bc8b77a7863f0746e870f62a47dd4a77475459b425b42c0fc8c8e5dacbc30ee982933858b0000a0e6515e76e78320caee
+TAG: 6a0048b7c0ff897f0a2be052383b68fdfc9046a7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162a2ca3adca1557dee22780a8c678ec358b166d68dd3ea3858c81c1eb3dc3963816c44b69acabe0a14a042ebd6ad30a69ed32deabee60ed77a61ade638b
+TAG: 8a573aaae4582b75ccbb1270dd0d437f275edb10
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162a3ed2ab39beb101dfb235b2dadd5151b11b66feb92d649d931a887ee5d4b26e35a4ef67ae31030072f6b83724ae2d9f2b1c4f330c46e90dd599d6142c
+TAG: 6de19bad2ed1d8fe80258c4bf5b8e24ec92964c7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162a2de2292b71e282ba086f3524ab8f69ca0a4eaf804b59654872d5829c702c637e60e8343c021764a014071eeb7629f9836224eccfbf877e62b0543d88
+TAG: d9c97d7c6506b7968ffeaeb56c9cfcb216fa7ac2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162a702cbf3be86cba9ab359f35fd9ae056eb0dcb0c93985a62ed5204ccab738b9f95b3b88855c3dcacecd8048e2ff3b680436be2fbc96c5c604c1da18d9
+TAG: 86c1def3fa5d8f2f9930c73c98043de0c002f5bd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162a01a27791e98d888e37d3e884855d55b3a6ce35b6e4f39128436d089dbc6b7e426eabf6534c2c3473a96909af16d1c53529786ee6a9b014df537a3e63
+TAG: 14be7b92c4d6ef8098fbbb69e949a29406492338
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162a881d38d226743c138023afa1be39a91ec47915713767908922eb003f1a91aa2c1a7db713272c6f9aa1264633b75f6bdc92e4c3c4a01d62d351fe1a72
+TAG: 81a8c7a5bccc5e114e8980099169dc546443c55e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162ae257e836b9860d4f05b4acf35e4e3fff09616513167d7ae6c9bf2ba21566529d172265ea4ac7aee9b1804d7f26e24f374bc3be6a40fa676f397acabf
+TAG: 3ff863b5e6beb46c6a3e5f2a64a4f061435a24b2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162ad0e8cb804c0772a70552f0ceac3b79eda7d7243bdbbd133b7bdcd9f28d4563968bfc4b8ee31506dad4eac84add1be7daa266c740f8bf9a18719d0c09
+TAG: 86dfa7ad959e65de4445d740269bfff920065354
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162a1af75b17e84f04ff6b28210158a1266be9083d7aa993165a7481550d7917bd85ffab05740a5137d946f61b1f510f87c80593e3ce50d8dbe3ff8b8e7b
+TAG: bb25c84eec393e08fafd7b592616d4977a455d89
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162ace0f4412d9a391e0f7eb831ae0719cda6def7428638243f399fd49818effc75a327d6d069b2198be3bf904d1391f4478bb520f1506ef7612324b06a9
+TAG: 0da097ffd67a9e6b73e1fae0202d4e836d3203d9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162a04eb78975349dc0ca72958ba71589cb823d2173856e3e88e0ef18ad03e32e3b078844b3ed8b0ec11715705b7e8a64d70c0a3ebe944175f77b4bd8371
+TAG: cda4b2010dae692006ede86c93ecbb2b73a79f23
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162a8090218b865d3cbeb886aa913863f74b5ab86bc01782c1ba97acfc1888b47bed713fb31041326b4afec95d369f5b2f7e9ce58388347e92a2159adc6c
+TAG: a2c56fc4f1d28181526093bc324b1092beb6863d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aaec97736ebcd4c206c89d4fa677bee6a45d69d4a2c1ebd4ac84db78a93785634c9d1f91c1a9b5245d73e50490a7e5e2ce7f36d478a6c38d7949d18a8
+TAG: 0e3bf7f7938d1f85f52c8a687dbd23cf89b2562d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846d791f8fc6d6905429e78b0b4fd1e1c6d900c1c78b3e02cc0efe749bae139a456c9e9800b6596146230b8570fb
+TAG: 3060552b7ae3e6a5588f2756e26890e461aa9771
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846d906bc6c25534cb54e5818fd7d63782314af4b8aa65de9989e73355499226463f92d62d989fa75dd8254cb4e9
+TAG: bf3003b6c4f0889476a67680e21dd3bbe710e7b4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846d80c18b60c43b7d9b8641bad9708faaf2bcb809b0c8d639e2c687630aaf9817012cb446296d27fe65c7ec4901
+TAG: 407fe65a06e4a071be930a2876eeee530363b26f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846df30dece0415a329d00ac77e1f63aa2ecba9528cb74af97cce119221f71bd0cec99232f849147b09a9aa9e7a8
+TAG: 0c350afb05cb7ceddb5558cc638ccbfddb7b1a75
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846db1ee4ef1a05b86698eac204c04e46dc5f5cdd526c5e7aabeab751dc231bfc85091726d61ccf98a1717034f5a
+TAG: 3fcbaa14fb1693a6948861214c2b2b5a7835ba7d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846d6bf1596e8330255ec7e8e017aa63a23168d0c2e8e95b117549469b4ec91b955b7686ad1065a2f71313e46e4f
+TAG: ba4052d639be43334d3efa18e498330d9fff9dfe
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846dde6ab81726cc8cd29f2892ac75df6aa3fb3a80ba664d509638a1b06fdd8924fe5933dd9e5456fcef5ea103f3
+TAG: f15c0b144ff4752cb8d27f636fdb3183bb0ae6bb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846d135bb259ae4d6636315644a41beffa421b58b20f17471441c0676ebaae2fd3aac98abb68a4ba161199da28cf
+TAG: 5deb146ef55d9d06c09d9d7abc83786bb04299bf
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846d6a57ac180669cafbf715b9168bdeed1cb6205f7a6ef405cde06f24f14942d2f893da05977382b9fa1be0e2d4
+TAG: 881bbe52a95e42d8cf70b451219abc0953f44bf0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846d7cce794f2f76911d8bfa76ab178fe73257c530296be2533358db129c82aee8e71975cebce9556ffa79fc2610
+TAG: 8a960780945ea323241d32e1e0b4ac867af75a17
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846d01adef7c2515e7954f82a3ea57721ba9641f59bd5db584c7eba9c6875260e3e5f18df34fe8c77a1fcc41446a
+TAG: bcfe96b878e2171fc7617b68152d32706bbc93aa
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846dcb5ca3db6ca2653658ece22c1345d740388d54919ef17140bcab1b1b93062701a71a7e05535ae1c7135834f5
+TAG: a97ed570b5f9d82d5f1210ae9b94f93a5804afdf
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846d0af56107c7988099ea59dd00cd99869857a9e7b69305f07b6ee7e4e602f2c0229303e63feb5f260b9694be23
+TAG: 5313d589a02931650ffd968fd3e0947a229d255d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846d7368ab5ce95d1d39dcde76e20e8cccb4b7820059762afca3b5f1cc679f2b01778e6cb56935d5dcbe6f8a12a1
+TAG: e0b419520fb2db362c7bb7831b78f3355855722d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846dc1d2b07a58d4df8433c66f180fb668f395b78a871059b574d80ad0093dcb56b6d2e373ba14047d33e6275816
+TAG: e791085b6845454d03799dcf108b4bfa919ce6a0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846d01e823c528a99f01f996aac79fa2cf45fe38ed6d041840cc4b82e20b4c79c58525a30320cf89c9534fe70c07
+TAG: 8d79562b8ba0473ed4b89872a978db92cf19ff8b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763d80465704fa438f52d2b5ba709fca1027eae17fb71dc5ce73d5b8fcd2
+TAG: f123464d64884c359875321dc7e9013563316343
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763d2e0a983d49fd2b7d695394fc3947510255223322204c38edb96f7ef8
+TAG: 97779c4b3c92599f7be37757455d0a86a94a6a7a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763d6284a540abb58cb78d7e195fc6e9c6baf3c4256dc7a3d6a50272e7eb
+TAG: 9805227d87596bc788bf40c44590c1d7e2657cac
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763d3c9172b923f20ec069c79678174b6505d00fad11197cee0591ba7e0b
+TAG: 31aeb5f7399e83b406b97371c38d5f8eae2f289c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763d7f5bfc728808ee2f49dc49b846d504d3e0b7d35ebf09a68813f8825d
+TAG: 1ee73f8022139fd12a2c0668d99ab27bf3d1b5a5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763d250d130fbb722bb24f1323a63b0fa6ce0bd435bdedbbf1ed3573aac1
+TAG: ec65da5f7c9c97b79ba619020501ada5eecb633b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763d038c6a8e87699da488f08fc41c0bd2967826b74ed155a34336931e52
+TAG: 86f05d8f365eb743613d82e393d2fe2e4007e74b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763d80a404cb625221bc8ad042b5c3ce5e0e574692329aab023b17e935c2
+TAG: 61d83c81b63711b686ab9a291531cdddc63d7a97
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763d52a1e7de84d4e2a24ea0006558a3bb6df29cb07532df9ff7a1c8ad18
+TAG: 2fd54df751b4bf4df2b37917b4abd02729600b67
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763d7007db41374283fdeb9542caa0866f77e5af69022a66bb35ab69e4fa
+TAG: e97ff9fb667f3fa74fe3442e77cdff598d174f74
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763d2717d82c0c3c1a976965fb754b94948f9e85d2fff604b3bb76872807
+TAG: 351659f5bcfcd7966d43bfc31888cea71163ac4c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763d0f0a874f5148b609dee63339e905a665d7246a1ecbbb47959a9587ec
+TAG: 3beb6131f7956d40cb07f18a12b8ea530a02fd8a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763d926520fd8752d884f88bf0be5f0b420bf6921d793bf26b451555e871
+TAG: bd06afbb43cbf34c2f3b669d9c637a27a92d85c4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763d72c30cc67e9f9ccad33b384230f1c21f286d1d7473b8e16351b3ff30
+TAG: 35b58bfbf57b6ea6d6fe71250c464bbb9481da9c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763d21b70b15d3a136d9cdac07fac99f4f745de7cd782009df2d1b02244b
+TAG: 4033aa15f3421f36dfccab180750d787c7772c62
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763dbe076d0ccdad6956615ce720a9504fa8881fc12141266795e32c44e6
+TAG: de969b0cc80f307a711764176c45a2b61578042f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637d97076ad63c09bd62b3021807
+TAG: d00dd12bc19a750b761d837d3ce7e23f87bfd955
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd1eb4f367328790d0c336519
+TAG: ef9ce0469baba42cc879905a01c789376dfba48b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637d8930b1cbb8a27a5437b8884f
+TAG: 40899ae1fff5b19f1e483afada346be3881497d4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637d3759c77b88bf27b59355096b
+TAG: 6c9fd8904fd53ec86214b199e5eaa51dfabb9c69
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637d9b25cd67dc32da238f4beb7c
+TAG: 46b5b0b62c09615bec0f4215f14689719d0e9d98
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637d7bc0f6491793a639dab3bd21
+TAG: e2b9f2f688612a1f6a64325d76a5ed922808322a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637df54b0f1aea70534243e0a3ee
+TAG: f9a5276dee067cf0b2d7c961b6aaf3db6cd7183d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637d95600df27b03fcb389c2ad43
+TAG: 2e339a49513c68d4f6468d274314b0867f1e860f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637d3636c6f77341c33c856176d3
+TAG: 730f6db832f8c5b0614240157e54e21d95d9e6a6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dc5c83ab7291ca53f5349a228
+TAG: dd65f3ad41382097b3939856438805fe470f1daa
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637d70db80384ce9fee793c2605b
+TAG: 4c2f874190ac93968d6af4bc15297444ff9543b2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dc4cd19fa4b8dfd07bc79d672
+TAG: 99f4cc199fb22c90f4d12931c0427aeb828b0685
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637df33282eea3d2d6ffb320f2a9
+TAG: c8db582216c76186a6839c6f7bd68c2c974ccb89
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637d791bb34a274999a4da6fe86d
+TAG: c7721c320cd1eeb8493201b14cc50d57d458cfaa
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637d608920d441336fa7af3df86c
+TAG: 6ce3fd8c5f4ac7f63b60444ed756c4bb5025241f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637d34599c44c43e41bdc14f66d5
+TAG: 937da23156114a88ea843b84edbd9fdcb4ae234a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd13088aafd6754bb6b69613d5c6d44e35a719d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd1308887e235dcd863f455f46dcbef58eaf988
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd13088bd9e2635b36ac557c9aec20e9d956946
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd1308857849196067f9006d7f0c68e1d2c8924
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd130888cc8a6dfa951f1658d0e19659e646816
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd13088b7e6027a082d7c1981e33e8dabe64e9c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd13088ea212c55051ce612c08bacf120da3ad1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd13088e1199cb3294649c12ceee005499c28b3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd13088170815e317055cf9047950c2b4a217a1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd13088db324e45f343cd393e5c5a7518f38d1d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd130889fecc904ac7849aad43fc2b71ea818a9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd13088f48901e30f7a0f4a9e4c57ce18111fcb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd13088ed1961c765d373a15c4246d7d74ef15d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd1308827be87e8580773b1703ec6d37da6b455
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd13088d87472c3ea4d1862d1d4db423d8da0bc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd13088200478cc2d41d11ff6032c9579c97bbb
+NO_SEAL: 01
+FAILS: 01
+
 # DIGEST: f0f82752a691ef5866413f2b2e5c1d0ebb41ccc8
 KEY: 7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9
 NONCE: 
diff --git a/src/crypto/cipher/test/aes_128_cbc_sha1_tls_tests.txt b/src/crypto/cipher/test/aes_128_cbc_sha1_tls_tests.txt
index 2b34b7b..b48921a 100644
--- a/src/crypto/cipher/test/aes_128_cbc_sha1_tls_tests.txt
+++ b/src/crypto/cipher/test/aes_128_cbc_sha1_tls_tests.txt
@@ -23,7 +23,7 @@
 IN: 936a91d0b5
 AD: d2c0267218cb7090c61713
 CT: c6281c1cd562c1935946013b
-TAG: 946a234257dce6ada126887baada8ee4e2b9f5ee
+TAG: 946a23427970932c1b21fc2d10118e7e685e8af3
 NO_SEAL: 01
 FAILS: 01
 
@@ -38,6 +38,2588 @@
 NO_SEAL: 01
 FAILS: 01
 
+# Test with maximal padding.
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd13088ce257cd6ea71706ff8ec9036f56d76c4
+NO_SEAL: 01
+
+# Test if the unpadded input is too short for a MAC, but not publicly so.
+# DIGEST: f0f82752a691ef5866413f2b2e5c1d0ebb41ccc8
+KEY: 7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4
+NONCE: 183aa23fd8d7efd88503f78b8ed1c8e9
+IN: 
+AD: 936a91d0b5d2c0267218cb
+CT: 9e23dcb5e3bb8c16fa099fbd135af44ba895a6ae14bef6699210bf0343bf9e03e529508c859dd6960e7639138e8ea271ab193ddb64ae77fcf7d31dd7a8ebebeb9b0653dd8f16b3ef5710d518144a2c546d8c51107f3f7075e04f2e68a2edc17acae579c83a11aaff0d26df7cfdb0b0afaf374a3fc1754ba9cd93e29e8ad0feef383b8f7935f81f15267c212d9051d1ac4762f6fbb5bdfff1e8c9a867add1c2e34ea839780de77041fee67856e2947325d39537f8bb915e4f312d7144d1bc3f562413c68c42f8c6434c8afeb973bf32c63f85c396852235c1791c0f1aa5ba74f3f176134d6eecbac484cddab9
+TAG: d14a94d979d07fb305b35d7fa0d0e57dafd8a05e
+NO_SEAL: 01
+FAILS: 01
+
+# Test that each byte of incorrect padding is noticed.
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97c1954dcb829d72bb8baf23ef37b700516a6e5b7377c933b949c8864144e8ca0a13b0280a93c2a42285c6548571cda2d857613c74083f722c022d9c90a8a51e981b3b2305a531d604c211cf27248d1d46d671ae76dbd1decadc684993e7fc444a9513d23c69fd264298d3231f205801a309953e41c1a2f6a6770eda074d640ad0887c7755227553fa929e457293bb11ae4b064e413997a21916331e3194b9abe91eaeddb8321040cef865fd2527d3dd14016fdb216dddf8dcff5a659d76086f1b1149c466c7dd3e72b08b7486ed34f7d1816db423c15112e865cb87fa0b0745d910b961f7ef02786407a6bc2f
+TAG: bc6a4e43efc2e1f5d34bd99ad853dce8df7db6ce
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca975883e45e6461c9e89c5bb5f912d4a8fe273a207df1f6bef7766b324fa0810688dcaadf5ff0ce0a2a529a359cacf6fdcd7550bd2b1573f9d2a24f0fa9fa24e16111cb16ba039d8fc17bc0a24fe6fe6aa24786e3acbfa9e54313c637976d6a8c7db48db3ea1c4a149da8aa42b8455a1ebfed371cb1ea287ecb569c59bbad804707d93514731816b9f71bf786748d4c473718cf4f3ee13c29e006840107022822c2f507a1a6552a394fd7c73514fe10020991d42fc7b6413756a61cd63533841aa556f1b98f6087a65475dbd66db6553e8169e655893af6ed6509253a2f5d1b1c71028931d6c28e6d2fa81f2b46
+TAG: 629ea8c1a911542d89b92cd354039670948b9d3f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca978990d885635bbd7814f02b2a32544be86b61160898d7e3970ed6aa2a6e8f6b112d27ccb2601e90a964bccfb169fe9204a3da3a4972c6496fa0cbd6f356e219d06cd6f17dda71cb5b916816934dac150184d65210276cebb5821e2738c57699f96691d4c19c866de94e9990844d547c083bd4d4642803789bf6f2fb29e22760432d8c87f0985f864301e034c89127f88c85a68b0938246e735a303259f7d8efbd8420648b74f1428b02651b9cdb61e41b85c5b36d735145ae5b91297a45325c72486b72d69df0f39f2fd75fc494410905c72b654717bbc7e10646e4eb353f88c18f2427efded0cca0f57708e4
+TAG: 123a0a9c4190ae99af97f03574a050a218420297
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97f653af6e4ae13512054764ee8d232e9cc05d5f9bb4f57d58a0ad086f8628387d0903332435b44bc5f824f0c797f2112a66347f604d1fb62f2916402d23bef65103ffec46349809ead2d897f1bdf388a5a054c696d176c57ef0ff94a4c587fd1e74c723473a15704a214a2889cd0d94d98950a324e46f1f215bc88ae34a55be84ae1c551260b0a61a2c39a322dac47bdbd5a2c4ce7e073f269bcd4ab7566482dddb06818de46b7d1c21a45262e93ff8aa2df2624886b335c1cc0a4023b976c91b4ed3cd1ebbc65cb0c3e786efae5e4748cfe94f63db5e3fa841a102fff74efc29b57a34e8500a9a7675ef3117
+TAG: 079904ae55177c649fa69cf64ad7895f3aafd12b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97b5d213334cbc15a12c5560a9a908cabf5b4f3a4f0e3bb0812e1487a1bfe6aa25769a90dc8f0d1766782607aefcc4249d04c6998f347e3c60123b99843a4f25b1e60b7b7a416c36a4c53b18957870a825b56723e553911685fb9b00a6bb6fd1659ab05cfdcce2da4440299c05f50b98114e08cf3925ef22fa56eb8e213bc6d7845b60c0a59e38c5eed5c8a46cf32c936f5876438797088136fd31237cd0685b2c22c670508c1c24936c1425e47cd00b37cf827fa153c4924a226059b37dc743688ad605d10ed0bc060e01b107a6cac6cd768e029adc9c986ab3f30da8a10ca4e128124b95264ace682d33f4e0
+TAG: 200817b26a83ce7ac8963753d22b595b7e23d54a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca978d9b855d162c28d05112f6cc00c06171bbb8889e9033513038331a6301191c52d4a7067e66beb0d09ec08586ca29a9f2960991ecaa6dbc2760779c04ea42e84116500bd2a059647de2273eed863d1251f3e9851c65ba0e96283ded3bbfadb03fe44fdb62e466afffa7ceb31d77e579eedb243c8228bcf7078e152453bf9651c35b9ea4bd633775ed31baade716b42e6bdf7360a870f8c15bdf3c7af63d229bc4fbe4ffcb706af3fff6dacdef024ff11acc2165e220e059f3cc14fe6a459d5f12c8e2305e7e579a61fc07220d2ce28c14ad94048d636a901875985465418b80ebb6334df62782e31774bc89ba
+TAG: 99fca83d2909ec4a754975b6b212e9ad78bdb6b3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97c15a0b8ddd7692280ef981d5f729b3ad2535f460de9067f891d120e866cd718888a864e293425aa31ee2f59470a81e5bc8a12af2e15e75bc8a8a7a7acf13f9bd1391fbfde54b1073c67e20715719b40e4fd6914b8f8ce40f3da18864f2f2bbdfd0c59702303723429f6f248a4f7a84d3e222bd74778e650da5a6d5ea3a23b802d3515c4d304afb1bf337b9102fd0bdeb19ebfc7c458de6bd0630e0d8b3c74d9b36cd991a5a406d9d28c56d8875f999b0e49a51cbe361fed9434c7ec4124d3905e5a103b5d73bfca98cf34725205ebc57cce68535c5f35c86236acc0c5928306d1b9333e278d3542a442c1e41
+TAG: 8fd4b8617f759b212a0ef6ebecbc85ef12bff8a3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97e3bc785d9163ff8117e8352a4ca7efd8da1de6e0141a2d3061dd5d1cdaeefe60c73f5f350437093f03b1fcae30ce628322bfbeddbedc3b9cf80cd50f4e4901a5d4a1ac05d89e150ea2199c7bdb68063785e3d79f1bc21e6c80787e638f062a920c59c591616fc437eb4e3b91b5ec7dec05a1b1ae6665d12fc8745dbc833ad1bdd607964568734b554ecbb21af226eeb7f33d2a1ca817c23a73db11bf8c0cb8eec5261669a8170d5e22c1049bcf4d9c541c1cd99b9113b1e76fbb627364cb8421e828aaaac88d3a2dcfce513fe7a195cab005a5e603f0cabba1e60ffc51f6a06cef83e0fcb3fbe3cc7ec97174
+TAG: d598ef0ca387f6aec06886fd1053e0d9e1897d82
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97c68947fc7ae4f54867fa7630881e45a31399c51d71c2a3f4d349bdb5d720d26fac75e9010983a87f291ac3a7b43b04320fdc1fbaaf6f54a1c982c8c2fc6c233f0c89b230f0655f54652ccd77967161d0f081fd6fe93f27081e0aa66fe285bfbbfb5b05b8b7c53de8a4ef72a82adfc88ac526161561bcf973daf053d44f053e3eee5a7692a9397d5e393d90dda23b69ce0dc9497a27a02ec0019da21311e89a74d83662b86c98b903b5dd91fada3c6ca6d839d6a3a307286388da93d1f1f721ba57938acab207f7807d1235d8ff15133fa93d6ac4e03c19e837c6f6ecf680c8c5cb5aa33e08f4441b87e9f6c1
+TAG: 7237c10ad9ab6229ea170f4c822dda4d4d194eba
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97fe991554171d8fa89273f712f71992b79ccfb4f26d68c1fb81ebcaf526e6efb37f2e1664dc666b3360a540ee3c520b7f135ba2335c357a3dab1257a2d918aaf50541599482c754e5a03df4f3e7bf00baf50ac945af034cb49816838fda953891a37b4ed44da65f832ad79aa16bef86ec8dacb250f2a73468232367a995a4aaf4b633cd8acbbbd7c3948ebe2bada8c56dc774b998032be2365567c0337d27ba7c9514b9f71950cf3e6ce8b6ae3fdee8872a0fb418eaa6bb4d6d5b9fb00e09fa8738162c796d5483ee4123a69526d2e900fecce653419eb549ca3029210e326490da1384bacd98d0b062458e71
+TAG: 3b64aa08ed6b56011225196313c8d09225fc3018
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca978ce8aca0fee6c4ee6a398a8be738b04536a3acbdb67617ca7e879b9ef42d40a109a6fcbbd2898249b08c90ce4382e289829e3b59b6625fc80a2fd497679e4f83ff69281d727946e32f9e8a80953a95edacd0b372d8621a118f5b17fd83eef14ac6cb4b477fcd35f94a0385c5993385a362cadc8cdc70029450503d7935da8294268837c45262f2a3de566544340fcb56bf5a7c95f1c7cfd47502c8906565d0fba89844ed56519a8d0e091b7e946e21a3df455ce040caef15f13cfb9d34456a91c1b70a7719cf4fc38db1a18c2b4e12c991e1f159470640f1e1f0f55bc04c3f9c0e626ebd627c8ee117af09c3
+TAG: aab8c4e7557a76636d9f533eb965ccaf1d678156
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97a84160b9de87b65f221f7fe4a93871411a6a45ebb891211da4442277201b06057e87c7ce4fc9e1430d099eb2ddd7518c4d1dc891dd344ee7e578e1dbb95908791aa0dc29dec371104fa8b1bda26fc2340a29715db914202b3683c779be1dd971c82d9484b611522d46ae623d6d73c49a368857bfc61c0477faf528549d543427baf39a513a9ddff7c9f42c98e411e0bea4c592f883993bf0e7db802f6d62cee5823224a96407c1315f743fd456183aa30ad2c8670454cd3956882854a7f9bd4f9851effde2d5cdb1ec351f64cdc6f8f20bf57518c9496c2ee3ed3e8d3f11d7e49bfd203646b2404631532794
+TAG: 4ee0fe7bedfdd061d7e074f36f993b31b48758c4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97d510f62985b03068f1dd613c3abe1d3ddbf0bb3c3592746fcaf9008d1f2701505b5170860d117ad96841c30db7489eab96cccb2a6675880a20a712b2e4c425aaa5a8a12680b341ac573cc8932787866d154b9f87f9bd419dc2775e540c96cf4e424978b446fc41c6ac332cef7af77230f033f1930f5c34a0718f894fc48c7dd745265547e6cd27a1f5522c6d8f50a3b778e292aeaaeac30b6dfe4fce24915748bcfc100d3166831b4c8eae9449b0cfd5104a7de90129426fc1ee3d9c05cbc1c37cf8b74cb1259deebad75d967adf0fe3dcbbad1aa0294fc83188e33399cb00e9c6cb0d77588f39ab84066365
+TAG: cb5f3d077be6a0de278b228861b79e39750a3076
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca978f7a64b11a4be63fc97263480d04ca00fa7510aa0fa5a939cf8fada5afda5fa01a5c20604c44829164d2cf2f053d4301df8385724924d41d61b8c35aabcfcf8e0211f98e1cb6fe22a9d9f3cf9c96c4717daee923414614bdea16258b1561ab1c15487659e1ec4ceaccee32b6ecd6f71c6b26633588ec4a60265ed47c9d4671fbdfdfa7a2e8c6158938c82d4b4d7c00b59c7263d7a73839073dc2a6721d100c0bc94c006498ce467be58455ee03ca9df61b87d9e7fa40bfcb3a5d09d3494812f0e476bac5c84167b426720470362051ae072b56726ed9ce3528f1786eae22105a29cfa93b52e64398c7f92781
+TAG: 51bc661c1674933392b16f9090cc5e848936ca8e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca9789461b9f7b09c9aad355bd97a615f70914e12a6bf485d0b051067017c8080df7bad54f3819895407e031c8dc666602ca0e3bc07d6378d4f4f5d5420c58a7aa4e2c20e7214b5540d6cf26ef6daa0517f98927df1ed78dbc87fb1c3bf79915ff1b72b4d8829f6346337f063ee3b3679310552f7cac51638adc8da14124880c1aca85bf08af6f43e7b1dfa5592352c58d7eb8e9642ef7e19e7f27748abfd65f30f878d5fe6c2c7db9f1216811b91a220f3446a12602e79e4886e0881fcf61f1b931e914599d61e9a84e0c5e01a1b11a046dfe08fe5ea8724dfa2cacd6947abc8b5be77cd21da64540d833744eaa
+TAG: b1695e3e367b6632765c066f5b23d1c5e7fa5e91
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca978484b37c2f3ec87170152784f329edb9d9948745bcf8d310b551c51114d300ce49938a4af9e4bec586359d72289d4369a368a487efca7c2a98720d8427617cfe3771b6622ab4ab27f236d3c77deb1f7e8b08df28eb741cb9d7b3a4694956760cfa5554f76c9720f9e05257d8bef58fc0bee5b25b48164214d9e742f9449722e0969a80c8e3575c542afa7ff9cab186dff3dc0fb2597deb0271661a0f6616b292ef03be0c7036b098f8a1b0b9cb9182a7dab5b2b4ba1b8a0c1971800ebdc1f651dc33c3d87d848f84f8d900079a0c4fe540dae52f5447d5582162693cf4db4e17e964b1b1f369dd470a46b929
+TAG: 4b4aecbe2002679edf9bf0e399a9ddf0f9edaa23
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e629504477d93cc5bcdae9dfd28b6d86aaf62779941f936ad870965fe874f1db6f0f31058018c16334fe0f183166d62a3cf46b9fdbb0f956514858227c045192f7c3e73092dc4365aaa1cd74af69e0250182b399ec3f9fe47aef83d97825ef45ab24084d0fd0ff6583f6d23b886f76ead84d6cfddeea73eb4036560807137ad28a4d67c34677e87a9491cf2974e6529297c144947179d73763dbbd0030934e5b6b00b6838ffbba99efc837efbfb43b70217994c7069270d2f8e4be1984f7a8054e66bf9a105ee25939bf4e6b92e02485cd1674ee296107132fb26c32a7a030f8b
+TAG: 5f9ecede08ee67618fe79edf171dd14d69040196
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447caa5a66821859a2dc0e072db2548081ff5e1aebcda6b4199ff0dddf58dae9152fd9461f319c48cd3e008ebf374771d9f0e1b9a462f99388622b75cdeb8be988e10849c325514b9dda1f8d6363d1fd0ee45a4b67d2bab4d05de5467379593218bf7113c732127ff40df1014516bddb528d7509c8768325f0072bf29507611b148fcad1eeb98956b94604f44e9f0be999fd4f84216aa0ad3d21ded254b718a71a01aea874d8fdc926e27df34811cce98b3529c3e89bfa363708e014b4a175f56b167e12b949dbcf9bcc01e6a47d6588f0f39856b51b351e80886c751c8
+TAG: 7d88ad1804ef187e2bdc070ad23fdbaa03f3834a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e629504474a9d2b06ddfdbe267b3a97fd65725236ed9b3546cebda726e9254920d87f9ff1d44d0a6d1787b329b198606ef0095cc0b2d885b8b4af3ee69a8ca0375cab6c81db9b788c3783f92cd20fa991213b4271e59b792ddd0b677ccc9e9888dcc5e60c5d2e53deb3b64d2def43e8cd7a387f62d84902872dabfc69bd5ef03b0c6d0fbbbdc9afc9e6bac85fae183fbaccf1f74d49a7f6d5839495f0a12af4617f3673c4c1bac3c214d8d0c27490e85fec9235aaa3628a3f42292bc4d38cf3befce825b03b5e90946769a2d5c2ffdce80c7165bf3c3c219ddc53c18232cacfb2
+TAG: 0ed84fb74dbbf19c1662225e26cd80381b039dd2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e6295044757466e5106795b66a6387da578daa1d592ea5c97885e6429d4b2074cd60e3a48f25375afe896d1c775c65de33582488dba86322b6d99ed8b9e3ad7e9c9645e38d0c9d7e0abd136b58d52eb003ae701c892038d87b79e897652d1e5f1faf15681fa28294865099e771a2b1ad4887f9745bfe89fd8a97ed03548c66becced0cefc46822dc60afa266ade705961f81734daacaa6ad53a8e915bd330aa51e26607a2dcdb1f5d1988f70bc2e00db29fd296d7e4368eabf0de80fff904ce7ae5f1973aa9024027db038dd7d2a7020670cd5f5de29e17f6605e093320b9eb19
+TAG: b49bfccaba11a093f4a4ce567c8ec5935ffd58ea
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447c735a15b2505840c1dfd310cc00378c036702be3f4a9dc5965222fb12b8ac10c4c759bb737bd096f35f0d45ccff9f70f309e8360ef1e401279a74899e595233ae62663701463cbc115418ecc49b8f37cbd5cfe4d78c30c99fb4e1e83fc57c285feee4860ac0d8b9bf9cd2cec827b7807cb95ee93ff0592ce5c0c2f54f5498f63f6720daf7a525b70cfb72b207bf7bf4a6d7e7222d873bf305f4dbf619740fb924256f9295f2e33d35f4089b0d44b9ac41c1b0b138db13bad70a7cf47508c9558bed88586fba96701f10d3e83ddf992e91780a85d14979acde7e08323
+TAG: 7dd2c48b09e1db88aff7fde9667429c5b1f46ca3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447972e7787a03db3b5a640513542a129074fd43d853c4eb850943ae34f3ee0dce076a1ef06868dc146057174546843483582d54a4cf5eb2793d744ee8e4200f00f53f14f8d6d3e58eaed777578516634cb37bb667068b173f67ebe05b6ac18b73075cec23d43003ed18ef44480f8aa77daf3b291dfa31b9e047c5072c09c4f0a380fa84da7ee1f910bc750135e9c6557a3224c754780b3d4df3773aae59d2d39303409a49637f99346b38388147d0315752ad64cea3ec960bafc235340da18ae9bf632a1e7dfc7d12860a6fedff5a4c82c43c2c45ac2b83ece3a118ac0
+TAG: 7cb0dc7b23e86f8b94490b5c845e9513c52c2c87
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447d7d578266eb5ed8052817f28a1ee1c4a2d57c214cbb4389d9fcaab674fe16e1eaeb835fc8e56b2e55a421e3a8ea2a28404612593aae15020f17806661fdcd1ec33ad645567594b8401cbf213050aca4611c7a2f9bc5b319c66afcbd3d98201fb913afc4df280fa1f6a76c4f5bc5eea21e40b8539f18872b20ccefbaba0671c72c5bdf6bd1edccd12c7377b0c70a9745013eabfaf9fd30b8aaf8842c818004f3a1ac219dc701f3c62428dfaa244146927c7cf63d1222b128bfa364265084c15c16665a1c8e772dae3a88e0bb3c075f91ff4ad8ec014d4b8eb61a4ae9a
+TAG: 7ccf30756d4b6b8727ce2714389b903fcacff085
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e629504472856fdd33a21aa08b5d75a5ce3986e66b47316dfafe9a198a4bad0816fc409bc90278815d738162fe2149714eae6a665806673e8b1f07b4ad0daa33f862f8bfd43cdc5e3769529e68c1db7cf8df6113eaeaf8048b57d62695ebfde4ecdc4155b63c99eb32577a4f29f459982c99012b55e10cf2011ff5e942527e3b5661c9236f606a76b4163f19402001458c1e91ea3493b48763a293207974cca60e6ad902718660b037793a7a78142ade1f58e44ba12b6f64864baefcc3f5e52086086d073d928690e3bdc463d638182e8da13d6e8272b71a529b81d001bb1f066
+TAG: ff4cc938a5e10398f3874a7454f02be9a89c4087
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e629504473a859f6ed9b3e29a97f961f893905b9b0f5137d39711d0dc8c28c689b8ad5537d5ce4a2d9d11bbcf1dfacded581b51753d06a4a4d3e4a8106023cb89cf153e8a92afd3f4c88439133139e2c45c07922e05167b417c7fe400df3a8de3e5ca20d920b131949c693732553a30eb584164afb29d172fe2b4971a82f8407c5a13d27d3ad75de801784f51f7c412d5f1bd88940900f4b895ac7e8c80d3e976154d77f5646beff53c2ec3370fd9f2390104983fd01ee43846973518f9ac28db0474a2e5d35c7d20e55519e00e23e534bc4c256ddd14416aa2d0db9009465055
+TAG: 8d095d017ad836002c9b38dfdfa6ea9368df1127
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447527f28f03d1b0ac9b893534df88f676da599195bcb2cb62e885f860e34f0ea30825ac077406ceba90011d7ad09bae5fe980e579cb83758e57cd6cf6c2c949ebdc6d264b6dfa62baf532dd6f41ffc7f80707876e092be70ee3a2dd977630f1a66227d32d9f6a5acb16cb64e294a71f9b334f5599cc20f0bb0665716e69ba757765e41c55ee8085297f9aa9decc15c67aa5492052bd0cfa61a35700038bb6418507b53abc942da8b8d56ae4514957551f97b2b10c924a09c3bba4f92d1749e3ade97d763ee0abd5e15aca6401701077efc3baf8c05d15a1fd96df7c9aa
+TAG: ec171990ac3344c43fb04e8b2ece7db9641ed2da
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447a1ec93d84ea533bef16d27a607e6f36f546d6041e8ebb6779af52f89611e5dece90af839522463273f9a0fa902c55515e39510d947b63082d1025b16aac06c891ec41e553f60df6f09883dc7e65ebdd66779505bcc6bdd4a4cef73badf29edd99156ba9232695f1245af4f753121f3536ac2511751972589a43773ac84ee053614b49c59bf70d9553c2104c83325777679e261b1466a7641f1fca32356d9bfe61cf853117e7ae6df08c32936bd41f02df7d8112542727310dd4044cde9e3a459a1ceb4dcbaf2cdc13bcda5284ea5a23ff3d3582ca80dd3043b3b71b5
+TAG: a47794b6799d32b042cc3f205ed75aba173d88a9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447731e7b75ee401f3a1c3f57f5a32dd0ec8ab93978d60025f2a1f7ce38419ffd461befe968260d175e9b9d7369cb69a74b830f6a5850f5506188c07bfea225ed6030e88eebc28df0f888c126a17b2f127f1cab288e3e138a026f9497adf801a397be681359fd6d1b8dcceaf5af4bb4a02108d446856ae88a2026dbca715e46dd910e1fbd205aeb6efdf017ddb044914d9f5958ed1fbeb9f1440d15ef6b3619a439d166ce2aec06bb4f47174bd80fd45932aa4e868f3d3b7f157c084934f5ac3c0696b5d6c70a065e385e7a69cacbfa092181f58bf36c76221e58aa1811
+TAG: 977055320dbba3e32930c1e2dcb6e6010567fea7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447458b12e4410770cf350411b81957e3c04e347fa69b198ea8b6c83a576cb85914aef7833309d3e5ff96b63121b7c3f85cdeb7c2a76c77d1b4985463985c3f9dcc04d89b4634bd3e68d906e462eb0d8b46d51a07a0a24a106f87a97cb3bca0f8d9bf37ba9520734dbb20c58680e02d669d09bb166f672172a4c3340c77c8c685d75ddc728ea3f3167e19d05141389f5c8da8821ed5762fa761fc1b9d3592120e80490f3285a0909d3ca1f81023c3a04ae0121c63c7c45cb11c010ea6e8c1fb4d73f5ea402ca6bf4a57ac28de10939da6c61ae13feb2c5c728176b809a2
+TAG: 1956e99a57a26819ca229e68e5fe7fdaec1610d6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447624fcaf8375233318cd8dae4503858d8b1de1dd4e6e8ba0a3016c2827e62451207db10973556242f7ee9711288404602088baed9367444de74eb09f831877aeb2da0c95f6288544d62a4b9534ec092142c7ac253c3ee46c8c8086e462f1b5b4adc4d054c711172292375afa6cec2c553e3de22e847b678aa41ceb2cb08946efcb0f7ff9831ca57f34ed83ab26c6fbc54c4d0f353f278a8184eee9a368980ef58cc2a3e68efae6766616948a11f2eb4a144964d00f0dca7594c04d656d1204888eaa66b3d6b6632d9330c1e28911af23ef4b13fa4afc97364a811ec5b
+TAG: bf23a6ccb3904d060870f55373b2959d7f8f17b2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e6295044758338e5c286964b927a00c8c327ed0eeb7b8e6a27966638d5641db3e86d71d85aa2eca6a2e7feffc00a8c40f1a3a455cf30c366ffa71021681920854c7a40ed5dcd971dc9d07437bc548a02dcc4d8cceadc5a0e4817c22e1a39ab52272f23597f1f2c9d44ee4306e0da617803c1115681ac7752ed280966bd8bb19d3d8ed0de88c23c28d473d4fde6ddd3ae86e7e5c667001b8e9e882452cc03a7cf3130eec7d2b568134db94727695421da4065720f07ef94710d3aca2c7ee4d9a5db8794eebc8789fa6aaad0825c0a83907a341f29342f51c9ffcee3d6ebdbcf622
+TAG: 4c75516533b923ff0a547bb92e3de376b2ac235a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e629504477dcbe76270a38b39d3a9d4844b21c3fdaa9c6fa930eaeb54f7557c1819ec053f6ae0e9802510c89f756a4d5d70444987e9ec5e85bcd748abdb28db7277e6656629fb6ba1b80923af19bf451670404f67358ceb28b5fc86f3aa4a099e8ede47f23ddae9b0379f42163feb79c9985460008f08879975612ee5b9054ab07558930709d75df3033cc09c14c4c6d0176fb6e730e379952521e095bf2e50eb1354d785b25349d21b8c7d56cf85715355268ea8bbd6a1b580d790c27bd1d46328d595e24a83778d33b46521159bc35d22e227815641662e1ef2e7b28e063ef7
+TAG: d54c6698a2b20a34ea32a006ee8c2bd3d36c90ef
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597eafd6d31e7f8776c644bec881cd2563da1832958bcfed82422fb2ea1409c0bc46e5d6ce37c9d0df3d4e61745efd6de5c396097f01667d5b5edc0b2369692358cbf156f9323da3c5968c898250a2b2bde0144e27d364263eaab0b893917b37bd9715e229264356d8012906f60f7c1bee1a5730f2d0c082dc33e99cdc78723d37163f9dae7d18d2a1b1fed432e23539809e2fcf66d57c2f72c38b7c71bc4f02561c82908f4b0f5e58bf8c80d8ba7450dc682a1892acef2252f2b7f22ad33b3228e092032f97e7b449082bfc1992
+TAG: 7158eb1b0c1c49cd414ae73cd9d29316269ed98f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597e30340c5f596a78fe3c81fed7f7f180fc6b7973ecc60af3bc5f74633ea74a18eb2fcccb6bab98693d12f4b7e88b4baf98defb9d4405b77c5c75d2e64f9c3f7fc03ce5a5411601dae73ab4cb1f18c760bea0936107b762052d9d3c4b7d80222265a91fa0abbf64cffa66fe645ead5852f9c326b8b38e1f537787e66886a26150ff5ab0a6692053d1f6319ceff65ac2effa443fa485fa5b73fd02e221b77b69babb96ac2fb87b6a912da279aceafce064775d74a71ffee87894ec40e2d2e2ba6b4673a7d4d27078cd8aebf62c40
+TAG: 6610bb2ff5eafa8b161774c06e7a867362b5e637
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597eec4c06db3442c3cc1bb686039fb7404dd87b15be21e6bd0209d1fa9f030a4bce424324fbcc616b1df72c5f2a0490c53964736d24042a73a2e7faad3355694b45a7af4cc75a7046e2322f0a8536a5f737b8cd14574ee5c56d10316a8d4759239dfc2fc84e1857799aa013012bae6f9c4c1af1964352b91b099185422d6ed2a040f76f62ba486264135dbb13efc6e77fa28f449cdbc0eecc266cf072a4802b5ff2484448b4a7cc2ce2058d09e99ed08916e836ce3ab9cecabcfe1bec05b98118587ce6580ae0c07d6d3dbdeba3
+TAG: a7edadd8960f669279b0230f6d851eb2b6abc12f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ef3a13ef239721dafc41fe370b2c29a9155e94dd9b682109820b6eb35bea85a660dad46edf63a66d4f26fbccabdecbad8aa59626f3eded409d92dc5e8098e6db5e8d192acfda842e3c03d2e84f9d27bd1cfa09c93dade262751211e572d9155da8509fb2598242252adba5d97972f58a619db9788f9b50f276beac43c2e6e9589d5642398a7da8591ef8688e36d291ef32639db7fd8923eb5f892eeba0d1f005d3f182593097f7ba7794e561ffcdded2903f47f5716eeb5ffe792a3ccbd13a27c9d7f5dcdb030c0d209ec9970
+TAG: c5d1ebc7206a1244dd72dbc9e9f786945d6c82c2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597eec1be57df85a20bf65e19b68a36d9e938312a74c14c08eaeb93b0562c57126e4381c3a967cd7ccfe5940e4003b65e423822d0c232fec5ba5d53fd2730f918fbd2c4912061450c04ac851fdbf397c7a464e0ee74598af571510ea866d358e47914e02d8bc4b32b938bc35a04e6b25fbe2ac35cca190edd7b666500d5f972adaa76ced5a621de4c347fde9eb2dc64ad994f1d00660de958e17e7a2b6f4bd75044007130556742a5adc83ffe19220a691e2f811235e7d2b3e1a7e49eb4ba0bf12005c9826b0e5bfde0141a1ab55
+TAG: d660944ef5fb29e11eb48508cdeebaef7776c5be
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597e388d8fe10bfbc41804987f710cab90d14fff33a76ec3ee78184eaa4b31c25af732d614de935e57915e417f2f67a79c06ae805f597fdfc4f4e534fd2a9b6ce76638f0848c63bcb42a1f67fad98f88903d00ced0a8e495a94150f5ad0c9d18d949f73bdf5fdf190c4db968fa94ee0551495f5659d2aa563b79e6ec5a3eb7d8c3cca655b1e33248e94247ed07941ee3221ec015bdb4d2578c27ebbe852edbe2ee4748de49a413b900a6eda5c6bd834fca5d9474239daad22fc8cd716b90d524576693c1cae6eb284e258e4638cd
+TAG: c2b50110655aabcf9e6048263d97714d9b0ddc42
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597eaa85c2e6e570f7618ed1609f7362a22f52fbc866a418ecb5fe0dc9eb23c1a9c2f8aa735ad8687dc1372d6439bfa4fa78ac5c196db0e94ab3ec769edee3d700c15d0ba477da8d780eedfbce41bad4947081200e090d5e233eeeb0665a53ba9695b6956bb5474b428116f7c962e9fef3569d3da6d75617266c9100c61cc8719d46538196c16e26600b0677831fbd97905818c434165cf3f7d65d76ea416a64f7be6db4a92a680c569e91fd73422131da4106f5418801c7648fb23d73fd7ecb3341720cf355779171eec6275f72
+TAG: b97910d7d25638f7b22c18d073573809ec2d7945
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597e07a350450edd380e189ea4152369d2e4c37a9768dfb2885227bedf8d0ff3065ca0fbd21faaae991d2073af32933a4b36ba35b1596577fd9155771c4c14890ebdd89808bde1c46763060236427cc37d950b19a373d72c804cf8247dbbb0744f2d45b19a8563f64fa58c8884f3e47bf91c8931180eafeeea6ef52cd662f93500f648d1b7a0a87a8fdfd63bdd5f2d26d82804b6a6619f58a62913f3e4fdf91ba5d2d8c39977828346a90d05a48930f60e45a5b14ce1d93709e015afd6f73d95c1a4ea31bdca677f03122981c047
+TAG: 96b1b70f5ccc7927d53e8eaf1f1e8638bb975c82
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597e15874fab8c81f34db199487e9a1499630e27c8602ee42ac566c4eb1b75aeaa0c48d97b0a9226db7a24ce17a3ae93c93597340331ce2bbb6f06abdc689211ae54d94929ae5eba8d1561ada0c87bfd2943a6bc361549354434bb88fbb0c07b8f29a560820cd3d03b520dea05aed558e18212af63f3afc48c0177668f20be99390272f7302d87f2ec8bbc5c67456cec10bd14a7d638b7cd4c8cdc1a0bf4206e125f5ab714afc3277a752e4e28f23e03a04f0beb61869f369964e5d7fee4fda7b231895ab19e46f331b1fa535fb4
+TAG: ba56c28de8671a7f97028314ebc1a766737b2e5c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597e7e4b15d5a66966922531f1c59a486cdf2d289e54c9efdf45bb647e3eb50cd51b4490076b2135779ad0dec1d4ac678038da9621cc8468e13875240aa1ab6389936221c526a72fcbb77e7fa9bcb9aef0f9fcffbe6f44a9a07c7c625f570881c8979a8a24659323ca1e96b4528dab7f557ced5b6b3667c4da9e52e8688d99073df12dcac49c525eba34c4b991790d78afbb528eb40e408022da9c8d02990ee85f4066454608c0200cdc3f681d790269ce4dd62a221d8747c3e0a5837865ed19c75fed4d743f276ed3abe9c0e3cf
+TAG: d5cc167566652ae42dd204418174bed3f6527232
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597e0680d279040724fb8d6135de8b310acd04b06fe2cbe82deb1a396de764b3038d4b3ec5a4a01ece03a7f1b8fd94c802c3c14750176738bef3e4fabda2d7d0625889e5544930c2c758afa1281cfd4f2a567c8b7b8d0ff9ad00e2026c7683ee2e430af37cc00d10134f486e1131ad713e0b76721175af6713e20bd7cb7aae2f4eb41fd666b7439353acbff0d339f55d788dbf080948854ced95e4de712ed1090cbe2d9e8af81f872ffa87e4a54c7e53b4d72bb8bb3d0c81ef7d660f40ab0d11b247625aa2508b4528fbfc30b501
+TAG: cdf1947db56c173b522f7a5f2edbac1b9c74e7be
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597e5ef147cc27d0c52c50931c1c4f5bca11b88407512c400602f81da601a7527d87e4d5d0943148b66e220cd557180e725ef4aac14a4dc301ed3c1cd1e589a095d9fea92827b9d98a4ca60944df72ddd9b1485db5169a4d6a86bc005faf77b217577bad63ecb0f789d3becf893d7c6672773c2b52fa7393b9bf851bd87dfb16bce190a958d961c9b395e477798365a57e9faea81ec15bccefa07fab6613ca4d846920e2320c78c3eef88c9c2190f03e464531d7f25119aa9a2bfd936022c4b5c10000f10969297972434605fa17
+TAG: 00af27bc23b594b7af21849cdd8dae3fd166fd11
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597e5f5d1b216a867e070a710660589a260d56c72fbddde12cd5f6f61694f17061e5fedbd43642a4cc9ca2f82b3ac80db2212badc7b42cefe9889fb13fea7c2734d245cc6a7d0680b7e6c2a645db09a3e82e8c6683335b9081b5e4216a5802655f0c9a117efe2f423dfe3b913548cac1b339181378ce05755d77331888c05fd8f2d17af7db5853f905c1fc72183f08927179c85ec196b89b25ea546312fa6e820a925c2fb450f627812a2541bb810e32f8991912e639edd755a5d3872a0d666a9928092f529f263ac933eddad9c1
+TAG: a53e2c94b6e30b88a9d5d4e9ed9cb558a57bce79
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ebe661bf10543f11ddb28643b032ba266167ed6fe7876d0c2f2008e4d42c56587120ec7eaf60cb9e8afedf54a17818a384378b4ae416bf967278df8f8f5cfb85451e704b795c27533999be17cf0066a590523015a77125cc3f9e89152a953b3be0078ac5510d4b127e88b0e7d024a99c46f789bc237de6219822bfa4ca4408bb1953b6e3e2cd9488b8c9a353a50dc5cb8711e51bb5ff98e58353f5dc91c3b83e06607a4ca6e9ac3f0ed760a8be9681e1d54785af9794c2eb28945732cc55ae3e54a11e330b0c424e3999fbe27
+TAG: f0e2e31083390fec347c624b04e49d6a7e5ccd47
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ec92c840cbd076544d3c9c1f9c5e684d1660e748c197d26369c2490a0bbab97a7044ddd06439c6eb28eb9e5e08977415dc42a3419229c33cdd813bcc5b10025302b8f15e7343a8a182cb522bb09d199058738a92ba40eabf20b01d4dd48588c74848f90839b0c6726bfc54aba430afe4ad71837954309b1efe0d3e6985bcea10b0a8ac36972936c5487ed9c7534663d58d877235d70da52447769a259c4e9f50cd11a2ab50671ad44cdaf328f9575feafa401b6c50275dac39ddc52ddf71b4e6dd66d54aa0d52201f935efd55
+TAG: b2e5acb2cab557ef49e8d43f5cb5a952ad355dbd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597e06c977f2d7ad252b2e4be269ad4f97e60d72672f6dd3f9e25e7b96aff14c8216d2ff86a4b8c2a0ab58a02d7322215876de57cc54f73aeb1cbcbee001f564a63ec36e33450e95f96194fc9025c30d93639728d5c69d9fe26b5b62b6ecd1f55a28a28575c616a3634286a4eb99c2fd885f59664f8f5c5777c07b70471bf205750482201ef1d6bb270067dfd133f4c8654fd577ff5c6bf9655905e7e8f99e96091640bb99e129a3cf65dea771ed19ed9b38721fac8b41b5941908115c95ace4eecfdd1f96dfcad8c77ea1cf1911
+TAG: c1a7e8958a5e892a542fce9505e25092b490ed17
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8931dbf8f4b0bf31a0c78329581f879edf17ec58bae30bf9adfbf3d6a642588ee3176a8146f8e0af4d9e02e940fface84bd1774ea789f01f8655d397c0c9b46f6ad38dcf63f2abac0627adbbf5bbd9df5655d6dd89f4e8b2aef1ec82418f0925475404d9ad31ead9532b371428d73ccf12add978f5d9cfe3796027f924420516ee73273ba9b12c62e4bf4c9d0d8133f456462ef1d9d6582a2cbd322e7e1e0795af55548c34bbefd10187730f6f5dcff2607e380c8902ae1b5c559c1fca4
+TAG: 83efeb664402230aaee012c7b9746750991acbbc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e89340cf262a2721159171e4d4da62c2ce27093a4ae54ebc16f0076b1ee089aaa456180a69eeb46faabe413ac306a96fa3c395aed17ab2627ab4dbe714bec2a8cce18664abfbcd428c976a3288848e50436683f07a91097055cd8960089bfef263c61d55080017516e7b7936be9cd7cd0bdf8143a6338355a4f3e18b184caa7b5238239ae2863b49f88e19eab626b5902f5c2e4d7d9c160f2808d0a95ce156c98501997db6afd280dd4f8094f34eaf7013e6f82d3d9d4b886dc53f74e76e
+TAG: d22a04d3990c596a44417a6fe2844d6a7c76f48b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e89329dc7a43ef9d581e67b4bf85049d6574db02e8bfe32eaede9a9dc59ad27337d4faccc9cf9ee8f775fed0f85b27899f4b7c1d70fe0c30bc7dc0b87abde1ad81f55c92272c4709356678419cd9d9832c60eedbd74a24bf9549a0c39772cc6337b5043f9c79c0f076e5289584d01b6f428c1ea0ab0963765a846f5a5875eaa35b6bb140cbbb58480abbed3adba866f96f4c964b2789016d07524ad28370b07ea21a9f2ca86ab973901f5bddd737c8611fdcb848d1baebac5821fd29de05
+TAG: 182f82caef4a96330e0d50d143ea11e60b1872b9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8935d5472f5d66770ac1858278956fde6b36de729db9e8bf14401283cd5f82c89f4b3f1e7baddc5031e59a79b139ce5508464d71297b862c54a5f64325c9f7dfd2c2c9649a4ed050b5a25f56debf1526b150abbc40ef8c9b30663f1c2d064e06e418d1d7f4f26d96e2f3f6651d9b8aac17ea6320671a589e2bd01942adb3dde64c6425f1290ee38e74cbfc31c35727ce8d0fbe48a67e0b9646d8f23e18b114e4e127d3dc231dbef273db5048b86ff60ad998697404b93557fa458e594b6
+TAG: 590b724a8be4f81429536f1b47d431e884054b83
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e89319ffe05c7eecc23c61e36e4c2d2c3d37c5b9152f06d687242ba10083988d343f8eea6b39c29b69577909747f618d8699ad7ef2b7b0c9c935f762fce73669f86f74e923e8aca3b50f25f8dfba9b1f1c6bccfd10e2b9c06d012beedcc4274096f5c77e5ca1fcf891256535931d064deaf552282a9c75a379322dc12ff5ecf9d3146333958a43bedd64ece1bd4c98adf289675ea2fe085d4ecdce6b672a10972803d01a6a645a5a3ff1d3015e72d90cf19ea8a5b10cde4f824e71e6e9aa
+TAG: 5f32ecdfc678ca2d8957cd0fd35c39cab6a88ca2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e893586bf0222884e567e6406560633f87cf9e59cfe75b87bb334a89e569b1959752fca8c49d267de03a71198654c062d5b520726381f43ad5f0db597a3ed236182cbfe2a43b4a83cc32c7d746f5499204a5fff0eb5e0c1c6f2637677cf5a4ab5b3f5bfde072c92227478486a1d78a1ddd11b818f5a3a48bffe2007db88c7895cdfb514c51ff59957f49e95ca8fcc277b3ea9973c5fa4ec361a1279e4f8bc4a5d289e5a15fe2a1cf41869849d8653b452bea33b7fdb1472fed82dac6c122
+TAG: 60a06a529637b745e32508316bd605b4bdf426ef
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e893e5ce5b0efc12a961648fec1bd6b0768c65e996826fe52c4a417bbbec846dd7632f8a2f832b28c6fe050c63b8c6b1a7847285be3e9c7f66a81dc7f94d40992934e0152577fbabb4ac9f08e6a84682b1602d660b1f1dbc25891409166d690cd8dbd00d8fe08245e0438298b9adc52e8b5fb05ea73ae8cc317f0b75db64389095b73d727f1f6b2da68f8a3abe877b8855ddf3843edae5f5450472b082ff05c7d30e14d345580e1c08129443fb3903eb7673df655c9e06bbf26117744c36
+TAG: 8a461dca639998c73d3548690e664f14f4258d94
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e893e1aeb0cd7d81761ebfe0f3aa0b5e6855cdbc5bb51c99521e8dafe9cff970163e2f6e19ca8edda8b1901dfc70464c5ca6ee33b3e534f6471dc622dbe6225295cabcbaff33e78bc3be737deeb1e4065fb77a9115cd57f42247369effe4635c011dc7995e95a96ddfb013d57860fb5af9049a62e139bd50a6d5c34c06e232f5b7ee943beba648aeb10333c6f6b3a197e29d33d1b363d0b5f5d504f58b05c8861fbf35c873fe72b9602640e05187d15ffd93372e9496595ee1d020d37bf1
+TAG: 8b072e3f891ba9aa185e5b346930d47aa9d39040
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8937abb621f87dc1d875869595860d2455b9bbc5552ee6bd99546d86ef2ff37366043a877e0a7b48cd9bfcbc1a665db8f500c05bf431ae28adb4f9da34c73fd35ce385f7ac43b6c1aefbbe81c796c1e4eb5449047dc42df990beca41be2b9ed70060e7fa008078473c2805aadcd872063bb98601870e696b7acf887e52a9b9b0866afe89f5eb89775eb352a44f5658f3909a0a2c3f932f4bd7f074620c389e6f3623727ebc7758a907bc1a1fcb828fc6719f05a62de95a14d95217c0111
+TAG: 2c249c37b88eec4fb1fc64cdf3a25cd8a7455f56
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e89386349c60df134738bf9cd79ff44bdfc27392e88f2ca13ad3c6a7d5cfd8f5953e8a3cd7c260bd7554638e608a3a39f0d097528f34cba64aa13bb0bc97e7b906b92a41c4c47a7131e36723173c9e6b9d6687a3be3e3213e06dd8ec04596171aa2151066824dc8857b1ec468f31745d300c84739f3360c6f2bb5f510a85fe095247adce336fa7a465d9770fe1e760bbf8188b9fc06437ecf06263bcdeb3ffa8e86a6681ec9e4de80c3411b05afa5fbc1d72c8ebddaa2b1b5c6fcec23bfe
+TAG: 28a1699b126b0e495153c21f357409a4565560ce
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e893a281282957fc69b7ca2d9e399dde32ce67d7f803041fd41ac1c5e29d838f4a5a61b5e41c37c77cd99e2086deef1fd3a1f52205fec1609b898fb3269270fd5ed70b99a5d9c50b20f73d83bb224c381b65dfcc63b329cd2eddc41cfb0a3fd34d10578dbf362364ff9e404b72fcdeb00f4f1d7b79c9327781e7f37922f3f74c8ae6b07af55cfccf47b3d3731ced97d83ccca7832ef4ce882fc9438e69eacdd21ec2499c5543436db3835691a7d45dac32a49cbecc752a37d584b588b56d
+TAG: f0928c4c4f705a40af391e61b80e674140868941
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8935a6678457eacc57abd9fac0429320360be153d397dc6898ab6d2de9baefb9be9853042a17e2603fbe89126d7c1ec521d9d6501877196232f22e0246559a410510a937750e119953db4c141a178bb0949ee1bd4875a87e1da89122725db12cea2df70116e02643b4c4e66c9df051acb4e3ae9b49f531b887471ae9e216b6849eb33a99542cc03836f94f74583f13dd15863af8e5b0761eef7fed0f2de6847b6903a406444b4abeae4f879a1c64ab366b6ca251d0e041934f1d492cd96
+TAG: c3f66cff59d1c5cb1ae1b29bff4ce373a1306bf4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e893f56db74314aa97d6a4816e78a1b250947b6d828d930c5332e879b4a9a42eb90cee0c34df145ab46994dbc339768bf5de29724220ab0b13f8ad2aac51aa6d29652e5102f77b31bbaaa398871befda8f2f5e59f8d86c807e3c496154f90710079fee0bec2f02a40ae0bb38a89790393b199b1d0a30ab77d81d7a3c66c920bd15053bd236c294e3ea02482c3b8cb1d8b84cb80347c3ad796a7a2215b469baf8b593fa3ee66330b66bbc91a85bc9569c11b0585ffe36f08125bf215e0676
+TAG: a91688cb695340c22d96c15e984d3649092386f6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e893b4da8f73f9145a48320c562103416b8258ad0d1e1ed9539462ae8e1d05453dc821e9920b5bd8c1a443251c569193fc4dd488d75a1ce30e5533e9ecc77ebf0f5f2f6ee2c134b8d0973effcd4a281b3a2a61115a27f2b8375e55a21dde0d63bd433f7c1b193e6ca85e92cc5a7d5b9d452ebbef688c5f41ec50ab548de0d51343a325c0bc29ef100ccb0c48ea8cb5a54acd46d5c8683ee6d2c3f1818b659c36566f2b2293a0b22643e91e70eabd6d139cc723bd2b1d2a0046339bed96b5
+TAG: 13256c8348f97e72e6c65d9cf7a3ee3c3e9f6169
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e893f5614d3985dc720334f8c5f47d3f727c4d835c4985588d15879b7da6294d2efe710b6b3ed54b106b6cce679c8a27e8d48bd3cca6cfc310f72ec5e9e19425e8a3eae11232a7800c53a1eed56cee6d697a8480f47b5cbd95f91c680be3f0e1a54a25cba02b2ba92d315625e0998aa3a7b75e36b4707da10219e587e3d09b67c2992b2fd29ccd6267fa4e76c161a264abe04f2a222bbe5ab2c0a0981c6e12335f966d04f83f2e87d625fb400324086155963c7b19a98f27f2bcc2d4faf6
+TAG: 4c83d34a3465b7a162b52bcb82e6b0e4093d695d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e893b0fc267ec80b62be97c170de3a0cca7050b4e33ffb74357be1cf0d1a803b65537e24e8f6aa859851f851f4cab2785d86f10b9ba9223d6a64476447e2ba5a8e675295c283a00a6d42e8e1f804a1c23d88af9d36144644d588b1fc75eaf5f0a05e7eac46e4b0d1034cb1275ccca3878fee60cdbbfd83be6be6250e0244ebf5c346f24d1d6a10a7422d7a122db794409b2d8599ea03a2a59011b384048aa8450d9e33f9b6b4fd8cbc48e7d55ae56bd0c4f86046ccc5bfcce22e2af39909
+TAG: 07ab8c747921eb58b2b0564e0345e4aec6c62398
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca230a149ac3543746b8b79f47fe22893590baf22cce4603af7dd15d89c3e4386fd56c373c9a8158e53852bf33c7ebc65ba1508c63e3e596533844b94f80dd122b5e18f2bcbb2ab1abb879a59e550a5701bae52ebee7d93bc079296391af90ab57b6629012aa21e959b8445e87f15fa41142bcd382b91dcd81c4a21ff99381c66120d4288b1c8b555759aa8301961d6a7e47982342e403949018346e61584c36ef033302c9e3876e8bdd5924c1
+TAG: e9adf96d94abda968a5a9a275ffd417f9c842ad4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57cae97580cef4057fd0b8e836c85ab759e530afe1558ce5172a582de5aeda8ab8586462a39f886ffd8f670525be81ece0e4eaa14e6063a9b0a1a958e78e733933c4ec922dfbc90572e85ce0306a8cdb0bbc4d7b1133482358899b3e1576ee13148aeee4286305d586b81366abc2ecec05e8dbcc27ce6b5667575c2bb790af386e912fd8a10e8bd8845aff79b795a5600a642d0aa72b130329a059c740af40434438ee0870555734b1d64c606d47
+TAG: 218c2721948e0500e9dbe65b62a12bab81f62880
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca0820edb5dbfc004ac6b40c9805c3e62634369f085c0e8763fdc7018975048a69cc04220732da0df66905ae1f511d0786926509506f64f52a43a4091227b8a48105e1a89c55940c1d0ef44981181613f287db9a98bf9f74e0bcea71f78552d9e415b6fed0bed4543696d15b4c7221f5f9c888b6d0c62e84e3a341871f60f7ff62738a2df747a2aedd4899a05e7360fd68a1abb8007eb62ebcfe674a7b9e58b7bf0cec098e27807e4349974500
+TAG: 3804494038029d6fa3b624cad7545a294238562b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca3edbbd822c9c60c65dc99c1fa798066c0ccb8075e9f17036d18fe3d562543e5bf911eb29428e8f3c2c8f66e6ad4f98dfdcf941741d259cf429f595eead86b3b18cb3f230cab716dea888c169be203f8dc3573543045bab2d74859d790cbbb2f9334094f57f6d23e1ff29409e47acc00ac0f4561350ecfe99b5c531424099ccd21ba7692d51f9428328ad145a77d3fe18bd14febc2a4b850390d836ac2ee3d9169f7595af250356e9122ab4c5
+TAG: b5d04e448e6d0832f149aad35c51384aae2db5e5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57caff7480a4e61cf8ef66adc10ffbf6f8fe50082056475976d30d9221c70cf6de6086a97929f0ed5942b404282a8fe4dd7a914d2548f13cff13c43bde01450149f6541475ac72bc73b124a3e16c0a4d161c7eea94a8b6bbd1ff4656943e2a60bc72c12a47271d93286c44776aa2812ba52aaf15687a51d967f3de0a1a94b58d74bab75867e857d5e7740319faab7056ecb46e0681f23a4a9299698186519dccfda1ca32f136f710002c82448887
+TAG: c705cec551801a769cad84020c64026ca9b51708
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57caed34b08351ce045806536b0de176c6a5e66fb0c55f4d09214d7bb9ac0fce0edcb4f7c8fe42f6962c820aab3347dc19dc1ab5fd6182a26f979c94979c082cd8cc3480075b323b072b1570a1e11c67eb208a86f2af457967c3642e6eaa66ad5783a5e3c1c43672c2a58a628771f721e0933d0e602aa1061dce573385a5d5cca00bcf95f4f9e8e4b6552f2f4e8970db3e3670b5f0f3fea7f0279d07b9df283658f5472bd695e7ead90304cb5508
+TAG: 0603234347915fef66c43631b624a80d5fd33e47
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57caa468578d115d46a5e01ff0b3754ae705ba33007eb53a1e95623db01e79a6e57d1cab9aba0c01666e1ae50582ca63ccad9dd75eed24409e9e383f95cae155be805292a5b92e4bafa95d69db73d07b191d951abbca9c74f6c6c071648f3c753be911e6a76fe53d8801d6a2f2b8544b35da23b99a2ad72382ca036c6a0b203b05810ae4aed7b2b0d52571f2bd20fed1cc264ae80f79b80502888af72acfdab92387c70966a08f5f78d966639666
+TAG: c9163466ea1cbfa412138448a78074f284dddccf
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57cabf2a8af3aa0264de545df615f697cc36abe251e167a96a2c35ba91a8c315cd5a711665016b23423691ef380f7ee21d4a36ab6e636f0bdb8dd35425e34f3ed535a9d321e94ab9b5c535d884beec4534b295eb9821a4ccd23c18820df4d2756acd73624a3d74e7a6a18285d49ea345a899c3bcecf9cd3948380020ef6c19a6b83fcf2bb4c3eeaff38f2f240b1b848e74c866378f20c2e41dbed10bdf49b86b3e51315d4b9757ea38b5cf3cca46
+TAG: 01ecd18172790c04743534479af9e554e327fa25
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca402fa1a5b0e656580801c32df9421290b7fbaabbd836000df6e572bac7509b1d01046bace99b697183d89c5478377f17593f9ffdcac881b7c4c95ee1e7b54aa6504062c637b4b123d5822dfccd3537a3e13932559fb51511b14dce1bf23e26208b0eba96001287c1b1df97a53d0cc07ec0994df9f958b4e5a7192147c762caddeebbf2ed2bcc3610d4c44318ecd373b95e95e5b45122dd3d90e9c862ed382b8a6940ea424b1d820aa1f19e05
+TAG: f2dd916c458b2819180be842773ef3b898038a4f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57caa02fb3a79a955327409e13d3bc1d63073dfd9baa32413f130c195ad782150c43d8f5362c090db748bac67bf7e407a400e75bc256669f2826ca0b43d6db1e845fad0eb040ca24dc288525d4cc7d82d707081b95d6e60006b6f234d0ea657d2da99d7f2fdf7d684aa03a9b1618bf2d4c6fb1665e85a5011c9cdcea7f41fa657e3d8e01aefd387d2f9e431ae5b62f26e82f4e1ee7ffc75dbf4e5f64e7d1e8ad6d34a393af6833f794fffc088275
+TAG: a622ba9da970a02f9d12aa678a22c6deb59f2a09
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57caa311775c17b04807f4ca083e12ea85cbafa7bfea283f39d8445a21ff3d130882e26091810401298418e1f364965d0b95a6b5339149f898f75574ff2a972148ea59d5f5e9dccc1c305f5728c6b5024ca577d963d4533ec102b6da7f861a7846c9c446c828bbd74520a0f1782ac4d6cbd7495bf732438e47f1d69db326e99efffd87916d676460b4f8839e6eda596aa0675d2a60b6ba115642643f0833b96cc47b23897f6c54fe12eb854c745c
+TAG: 2510d24317a4615e1afa957d88f585ba24c041e0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca204171fdaebe8a9599280614b2c1ce84e1d2e413bc5aac9a73f021f8b606262ed2e5767754a053c6cf303b2e92ee153a9be25323ccf2f9ac8b117e29c3a78273f9af35fec26878c784207715ac6caa59b83f78cf1533ba343b87cf40aedf14f84c8a39831a83c79acea9cac96214fad06cd68b0d7beb7cd45707759563accf4e8d51f069115c18c67d3e9b0dc1f6abb35772083cc891d5f354b4a23e61b4410e6699b798494a17d8bb5611ea
+TAG: 823f7501b9af7753ab549123bac06cd91677bc5c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1deca010fb7067a9fe397c2445878bc01f88c08965f0f64355be203cb3e7c1089d648a4c8d53d16fe66e4702ed75ad77cd87c55305c3c71f501fab5252b3003bac2e607b7c9319b9e2991c95c3f92a97d07437791a5035bf66d791e484560edf2c4e3659753e129064c1ab77dd4c1bb471a49c60ec346cca84d6b89e20cbd173d0bf80e19db1432e1921e910a2d6fec3fb126d4bbb76505c6ce75bd241e82598a1bde8952547b81a2bf93ca6
+TAG: 19a5f0e7441450d3c7db939a16e7774d151440b8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca7007b7c4303dcdbb5092c6943f15ca8d9fb813db929184599228fe6a614cffcc7ac9cc9bfcdcc381faf46995a6078f8e3efd7826c8a5d5757df00edbf72ed8926b7b166b69bc8d121c53792ccad026148f49828a36a449ebc65c2b42129c09f8d816148b12890a02ba68f7f72298b1733f4a67f4b563ef8db6ac951d710b2d4c9ba7971066caa0e5f1a992ff16c94afb91a8a7ba6adab703e0b384e48349d487f96fe4ea8af79cc179cb8dec
+TAG: 00b5d0df4ce01f0bb496c19aca1b746606c48881
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca784b98fdf2bacbd8e4f58e5b573a7859fb564c7eafffec324cf54478335a4451f5195a1ad8810078197dd3b63f7773d8dca49cd58b90b3adaca93e85e2f9a6f3e0e0d4bb3c7369e9a43aeff0d10331e1d30b30d48009e0896a07219203bdc70e48ea3909d20fa1e6cbb3d315e3d40165d44df2c7e913ce805c6f5a677b9c327b78cb52cc910074240fafb2b8f7eefa5b961d16ce3c15f0db02788c38e3af46f065b0f8dff3c835ad44f5d9b9
+TAG: ca3133862cc4f49a45a3d4c1ad64b24bd6fb78ed
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca5bb609bd248736eb7b555c475a74812908c532a07c37c73a15f1c4991bbca5dde25e2425619779ee004779b4e5883db14c2ba6ca4a9189406404be6121d47ae05fea67809723e43a1cb7e90ff65cf737ebebeb7ac64cb4b027c43bcef6966354f87b80547433c98fc0d52530dffb2ea68d07ee0638b4d9b54b3fa126b6eecaf4fe35980600951946318fec9e18529ece014014d79bd031c69a8a899965a7dc7ad9e10436f61a4ff6b0b23732
+TAG: 593d5e64fcf05e6d4bff69e1cf32d625fa5a848f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c036ed67ee5ac89d5dea91dcbee2117ecfa214cb5268bf8ca99231d3759b9dcac90288e66947c8bd91f3ce9ce01abee3144e6a519ef7e262334d73b8623a362f6062f4ee6d17c0e0efb6020de633a3aa81ba27fcab235d084acb9a58885c780cb32479a3c2f1234fe8ab5f89b9c58d5ebd205e08d6dc5425ca0a5f7b834b990fdff6fce3216bf63e15973ab412b9a18fc791181e70010ce9689ecbe5b86f
+TAG: 82d6021f1dd05993e527886464d0072998111fea
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0360d0d74978d37b366c128e03ace2b1fda88ecb1b346549323698edaaccf3d0d2299d2aae049a1d6cb9d0c058648a80a6557ba96740e5cac434d56cec3e815682b76162c402065810cccaf7d6f57c6f8b2ca0510a57eda144e5fb4a20a0b3d1bd8daee8b75526b2451a9e31bc6bb2b1deb789651fb9f030f5ba0e7e5338e5d2a1b6166ba1eeead65c6423d1bd0346d0a49f2942795bf416fe1dd4d66da
+TAG: df9f2438033cdae25fdb1197e311b8d0dad577fc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c03615fcd0e1d611b563974df72e35233f3ccb61bfeadb4e79af4565ff79af28e05c2634340d9e77dd8ba921ea2f1f337d2d1176b97b4c55af64463e17b2607222caaeac755c9cfa7d6bffd0e71b9d6d81aacbcd12cf7590a5f11308acf3b03f4833b1d7d49a064ef54fe1d8305f74fee5c41b9f80a5bd25c62ecf5c688034526be7026ae2e1aeb930a8772a630538ac4b1a19ce79e4bdb9da59b5138535
+TAG: 0dd33c65fe201f7abf8a508b7758f71fd07cfcc1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0368d0d4b9b6c3ba2e2571c26b745c6d05b3ff65e4a51b5e00d0395db953bb2235c82a4201ed9ac354827c2144ffe815cfee86e7fc3fc6e4fce7b2d23342dd04d74334f96aca72002be0826d5990b0a25938775510ac8058b3efa8870516477d3c0760eb0ad37b743ef24c1a40e94668980dc4f5083ce2855e73e3d5506967f5e76fa4efae718dd806353aeca39d80ac4e87efc6e4f795454cca54687b2
+TAG: b5df25f1467145f762c683ffdce7e3940eeeb4a2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c03638b9a0b29ca60f12b33feac43695e9629d11cb6ba9c93d17a57edaea6263ddcda00f4dc3204f44603d6fb46ef924c3363e02a6bf35ee6d35e60400db64f25fe1c796b53db77798d54ec2d113e61fee81987ac414d15b2ae3b7d7d93127ae6ad887af7e26abf7352109b5dd0fec56a28c684c51ec1a328c5d643e5c45862ca591a1ac5274fd2af096c843dfcfa896a8df0d3c3bb67aded34321227789
+TAG: 5c24cbb0593240e9879a358d28fe88f5a2ee8c91
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0364ca6c12d043af08aea654656093063e262e5aee82961e86f4d07c6df657b24141c9d17fcc0559ca09d5a2f2d23817db9d53150071bb7b6730e950d1ac90da8f4edf073bb66a4c2a1e194652e66c26bdcac534bc3311f8c344725746773dce6904f599c330dce60f12b762e935f01df00bc658837de57fa05c3a94c898634518ff7bbc5db9a622e77cc2a5c97b94ab7e22f052a411ef0c2e8ab3c8362
+TAG: e4c302bed57ddb8b5f2c25ba734855e0626ec756
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c036a480c8e6c3db7fe51d4e411238800f5cb3ec1e68b86846238e4b6cad70e6ec53ae014f1eb8c57d5c24cadd6000f878f83676b0958355ee94e003690c22ba1abb4d12d20f30b6d46c9ca72c4176fdcdd8de37af13b032f81834230cbf198c6f9a263e9af1b434b9bc4c8c65498aa64979c2c6ebf199b215d097baa51853257bf6efed16a7c5d486044d0f4f7966e4f153dffda14b545dd5e326f9b577
+TAG: 6414f359863954d807dd018dd6411ede49f0c490
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c036a5cc5e00efb5abd26cb6961ca3eee41e505cfa6316fd8677f162074726bb2ea8b1c9f8ac536216b135fd51cfc3e68d524608964af36a1fca7243bbecefa51c1de51519c174b77df705f3571f87bff1fe1ae0bb8a7889893dc5acb6089c80406c323084298f5315bf6c32c962abceb1c835dac3b6c566a2c867893e10a97458263b6ec9f902f919312b26c149642858d8c9bf515efe135214ecd08e50
+TAG: 68b8a5bf6e79309b9778522afdf4ec939f052045
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c036a88980ec0e8b8f15d8ce68e3e35a55095df4f2d837074d7cf5f3e1dc22a3aa1de6a44ed333730ffa313d55f9ff8847e4f763fbc61c0b01228ce3e499bfcec248e6a5da8fd94b16f8778299f5dc610493fe45786738d896b79b77ba0c56af1d046f3f98f8db15448dad5d312661274fa501e26fdde227ca4d5ff16b21acaca5dc2c58a5ddb44cd9925db19ef131f0cb1f69d1ce521155a3aa29bc4633
+TAG: 91346962a9414b715307d41084cbcb4be9cce205
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c036861652446269c9504762c24be76d96c15be11eafea07d451499a2b4435797a1fd2c5507f94cb293a3683e7c37ab18c9dbdb58e801421e8d124a470c29ea0f329d1eb31c3884f6946bd552cd2431c94e9a0e0a4552ed57a9607c9c29f0907602d7a41e45aefa9c55cfd0dd79122ab2f3cab894c5fa630427fcf698fc2294850d4d74f22a5d3dbf064e51838c2ef8d62b797ec0d0360a1f13fc577dc30
+TAG: 3b3debbf2b0691c0abba67d9923049fc1adca1b3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c036b9677f9d4ba17da73d32124e12e1c3b67a625c61a8c4505f73f9c714509e84b605050821f887761ed3b9d73b9ade8d0539b089220774b4a434393fe2ffa5b27a6ee3566768ff89c33cbc9a49409d66dc9d42711b6c4da7a7b60d1a8c5d8f49aaa3db53330d22c81b18b305578b0ea7e3c33be22f93b9ddd5e3e0f49c95376c357a691c7ea1bb4cd1be74be07f50fb00816fd3662d6b10ff2472b8658
+TAG: 7682e11d34eaf53e781ff0ca2575c3efb21344f4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c036c3e4a1805866367d14e2aaa8815ae87e9e4c13532ec7464a6ca2d0e0b4c481b34e30cfc8b4a7c166077be09fac872e09138987e5cd4ce70d73027480c2477d608896fdd96db70dc73285149dffc3ccbd7d1f7fe303941416d7d099e99b9cd3cca7d596526cd63027840f853f2d67052d22b29514bbe93134f328630eede0b458553278f18cef1d187a63ce446e928038fe77c2438721f402b8ec3f59
+TAG: 1d759b5ed19fc631607f7e3017a4863beb7e7c7b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0360c47539b64f1b67e9a447f16b0faf78366f443ff1a72bb67b471560a1e628a515be5c7cd06dac3ecd89f753be0d0d20906ede2d84bb72f2c44a57bcdf77245bc4e6fd692b83230eae6df324cddcd689d425f681e58a19fb781c6350a6c851ae69c0c55c276b51e6351e2e39fc32dc4c024b062726d3d5c7dcd1eb6f6e22de41c0fff53fad4aac8050a37dce5ad4b16f734aeb51f33fcde378baac84f
+TAG: 89fb4fef04a9ea085a9b1db2b38d331cf4fdde89
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c036b1d5c85aed68f50642d52d7c8567eb668151e3d628ed44aef77ec5085195ebe66a362983a8a60fb527883ca0ba303d4a57880561a71241ea058f3528cca6bfd2ee4b57c4c1e031295afc950605f1a4fcb9fea7d5233d33c85dfc725d99eada540c5cf799a2c9a54e34e7e3fb728ccb0c300f97b0ca811ee2d148e47899e9ce58f6e9e5df757c1377b5ee09647332a626f44461b3443918643b9c6374
+TAG: 9b0aa7a91faa443ccda3a6de7a30af8ee90c6927
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0361ccd884fa8b6cdc163e07234ffbea4739a268a525791333d94468d998abecff4c5c728f5ebff11f5c507ff62a49fc90b83364441c6a1b5eecd0a0fd13fbecaadeed3cde830e28981ef94478334dd0aa7864bdf184caf9e7fe423472b466be451df40a88fc92d8c450e5650c1561373fbb0871ac0d92e09e4187d9afd83d6b7a6218eec6d92898819b7af0da7506f9c99783e34c42a633e930b67c6ef
+TAG: 4e2c5d0884373ef60372442c3c2f9233395c2817
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c03682fb02bd02bc1e5daf4c0bf3c37533de8c71522d597e5be1963626754c0458183146462e39779e755dffd85726194aff58a45fed67fa98bf886aa16450df02c646a96d1e3f58b3ce43e2d2d602512daf5c316792e63610e75e352bf2521127b83ea4d27397df4ad608596b27b3bff2481dc1d530ce6d767df04ea9a7f6580e885b1e3ad334fe750226bef87fddeb4be84497a30edc77e84fc826eb57
+TAG: 369f693e2d94b3a8b480844b88045ed2980e45f7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b9cc5dbfa8e27ce93182b06c101d179aeec13881a9b5ea20b97005b668c0acb6e33af724f2654de22ab8163b8b4de9e7256b39f6a7a8e3f4813aa5efffd6df705d5332cfc3401fcb63af80517065879b98cbf7d8427dd71a7322cd99ed3e1a5939cc58131aa4068f1692c5e19f7d4465308cf214431676346f0ba4be6847532f2f0a48288da83d4277b3728df
+TAG: ee3b0d0f5567056517f9c42cff7b3fff3c36fa56
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b85c3ffb952fb112d4923a5b8fb7facd04d5679820af2a765e846fe749656e0ad1c498d1dac8d3fc98eb700bf98a2719df812927a3d5feb3eda5fbcf8696717d280cade0c3dadab21653b3f7052fb267419e33dc964e786eddea0186a54fdfb5e5583ffd4c38b937ab04d39b38c4b81964012f1e0998382d5f6da5439a0ab61e626a5a4c0bad2aeeb459e4512
+TAG: 4e052dbc65c977da18256485bf83a804ea07bc23
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b66f5768d59c85e8cd17e3ff4867ab9269bf1ae65b0a620b88d95cc3c679f33837922d9cc2864440f402c88ab870203f6421330bb8131786929b25d56359d0077e23384772d12085e770c532df80810d81d239fb4c237db9d793e859b485cf11d7568c73d528477484dce1daa144bb017164b082cf60c3c9565e39d84e35cf80fb7cec35a63483a8ce34bc7dc
+TAG: a021a7214498caacaf5dfb02cf6f69779a3b0fb4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b681786eb44c331d35c79b0069da4cff4a4eb5592689e5ec23653b9af78e1c80557d110586bd2738dacc5c60a3d3f160c90583d3ca056a159a5573783668e56524a87cf3da03aabc4a69360a987c124cbaf38abbefa7e478569aa3a1c179d481aebcba4681fff5582bd0a2099a2853490122dc49f0739ae4d9f00c34cc5727278953daeb15a57aca287390198
+TAG: 3d02b9abf09de24a1c24ef5d171781cdaa6023fb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901bb458ad16e44ecb3dadb1563edba907f6aace74d118568d9ac013f532b8abe1700d8276e35b412cc8c42d718e9b52a052695e983ef34c8cd3e9d8857a8a4b8e8897ebe50996807430e9239ab049528e0fb9601b88ea25a6ec9122d1e18f1d8c462dcc820050e72b082b349f8daea08e99712d23eff5327bfe576412df2e5b059caa099acafc09c459d5ab1750
+TAG: 22cdb12c451f936d6c114f07927f5adf58a4d3a1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901ba231e5366ca76e5e06648a62103690f45daa85d162cdf4d945a4b15cf996126c54c989b5f69be9e421696b0ec5ccb7c4fd6576fcd78442da50bed96b818c243b993b8027e50f44d5d136343d39cbd7351547bb874de9e2115a47c28428babfc9144e6dd757121fe4c1e40f399cf6a8a4323a0be70414df049805b5b86e871ec25c90a319896cd99a9b5044de
+TAG: 68256005517e05f96df55e337224e32260c13006
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901ba9d080cbf30b1f5c071abcb2a0a4a6d0190e06ee83350bd021d0c7a03b98af8753d5b46b853859789805ef2120770b1c0b937db100446589b2c7f853954efce7cebe0d46343893f1029796090648bdae8a58c893596c76a607b18ebb1f4779c3819054121d8bae4a276bb8f029e21d5528be76164a34210b8ee84d67863967b5e0caf1861129e5ee54982197
+TAG: 8956d28fca8a66065738f0f364800ebc10495cc9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b8f640055dd03d5ca77c2914c1c0518faa4932c8f7c757c27476aac132ee40cc70e571b7b84ac4d360b98172b9154183a2d6000ba914ab35f3747132e6f3ad5e9ff798a801e90ad7cb92ef6812d595fe21fd5bbd5d3f1dbc02cdee9b1e5793ff42a53fdbcb1306fbb665b36505cf58015f9a53748c9d1bc565446527bec31ed102fa8ff209b7b4b0311f7b3ff
+TAG: b7b84e3f94199f78c473189427f8cda7b9fcc373
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b27c5309bce69b2002cdb05d92911925a020a08d3e0c8794ffeb45954efe223215c2d80195d8410dbbeb607d842b482de1c43fc93a3293001a6cdf3fcc21e3e13c8809fa0b36cafede973b26c27ed333a8d73f13fcf01839dcff49faeb6799d6a8264a1d7924b09b0a7d867b039c831a4bf18f9b71728e37117111228166c4d24597e921df4d9153aff37c2ff
+TAG: b183bbb10d58618518f65947466902b3f84a9947
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901bf09f47bc08cf21d22cd1bfb820bbeaaa34e7973c84732b3ab8e041bc5e08aaf8c26cef3a34dcb75279caa8746a16eebc5d1709a71a9fbcf1c191a5c2ea476dd012c1b8e5392d501b687134a97687cae429a70bf721a9d81cbce47de658776c7618817ff94106c125fa7126b199d720a9c62acca937a86f3a8359743472f46c79617c9267cba3bff55b78e181
+TAG: 956ea59f980c55139ed28bf16367a3da30a316ac
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b2e7c62e759b3e58c2d8c7af6cb3f4e778b8cc17e756c1563300cb136bfabfe1686393261cbb9f16b12508a4e0ce1927fb126fca6d774dc953f80267a4d82ca12778016fb619363236c784067dfde9a2f3d6bb38aa5d858045b68d9d16df9e97b66ec4522aa8d8ac67bd1a8cf768590600026c2ace36dba9e008af00b6370347e746712d35fc20e32f3fc6c05
+TAG: c83d73c1f7ccc571dc372f61536477c92af4fab0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b083c701c87a3814e58ee83a8cc52144ead842df9344a8faeeadc0f49de88571e5a8fdf6b007434df7018dfda6ff3afcf82a77fae949e826d178dca36504219194372112731f8a4f92b1233c3cacfd77544d9818b5a5de753ea60aab1c6aa68fb2eb272f8e8080e865846a16f96012419d00f8a3b3c34836641fd633212a87a434c4120c41f2c51d1dd71d7db
+TAG: eab2c944da38558d408e8aac16759a349b62f4c4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b68f93a9582e4266c8a0203129d3856bc343a54fa5fb35d185350028fc2f796020bd02cb4c3bd8855901d38e40037a28e906279881d07aecbe6e310f603d113fb69d73fe113e80fb1d3517cf1fc8b19c7d7213df6e7b040d63fb36bb394fc641cf35041446d3f48f235b700a6f84112df638675af933cfaef51cd71f08eaef7897b227ed6339650a7a902831a
+TAG: 5f90b881ab2ee554bd375b3d3244f1fd5257abb5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b617efa3d34466af15c9ec1f7dfda5ae52b81cd868b72564431117cd576f6fc944fdc374e1303002f33c238a7a3d4693ced7fb0ba027ea6534db2041a63195b6ce439c9a45ee2f94a9b70301298141507ff831b26bdedbb737c577df28e64e7cc6dba882fc769f657c4691062ff67fbd416fbe6af886e39c611976e741d03cc17f3aeb9cd8bd65a7d96bc4b51
+TAG: af3cdcfc4e13b11abc1682c970145439b8d780fa
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b44304c1dc06c937680955e0cb6bee9740d4fd551de6b06c5f82fdb9f26fcd50a21b540a238c706c45849668d3abb64802995af7873d051f33a703e37ad22b685f5b1a8e360506eadcc5c8fc15f579561019acd9f2b737b48bc5cbb8b251c267cf4df7df83b6451b6e8a91f2659b0bfd917f9c68c635a31d9af98aad1a7a7a62e5935a2e0c040e48ded837a0a
+TAG: 1b9ca5abfd783cde9a5466e3863804c98d6205c4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b8090c4d36602ed11087bc53dc22df779eaebcff04bee06309e84e702477813c7bc1a5f2f0f62dc1b3d7d92329d17817932e94e11832a0e85e2328451e63adbda190d63863400f847eddc7c3bc58c578bb4c46d0f3c2119cdad0ee95b6a4f4d82492f6c6b29fee08102759c3f0bd35c0e03de4b0d77f967cf03b49746aeb4d64e395160741242c5311d6eec83
+TAG: 56f123a96d0620336b97f7bac1052093df9fc2a3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35ac5e6db62ef74efeb8015b69e3bb0e6b8bbc51b1d3737e14e2fad84a8cd8605e63e8a822168a04c6a844e35d6214a4bbe6e813054cd8b3dac97f923140c49e02edfd35f10ff9be39a8549c3017e02b4cac6bb66ba3290b9a704a06c4571a63aa3fb871ec0903914838b58584f49f196c167bf4fffb84d349350c81a85
+TAG: b20adfba55cb256cea0eb092db28aed67d8ad417
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a324804815204c0c99a1d63a6db4250278cdea22d9cd3b0a8fb82d95f9cfb0d3098c3358208bf80e6883c6e76d2fb85783f3961a04b4a289db72bcc48e27ea0382edb0f251e08a239a7c89c1cc828262093824147403562981f0f1482468444c9511e25bc1447976c8cb78340ccdd829dda39857c74e740288b4d817f
+TAG: 60b73bcd9fa60899fe2b270015508866ce3f60ef
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35af62a42bb25b423d952e08d62ad7ace8a8fdb8bd57d8a134ac1a3747f229e8cd8d5a9f619453cf1018dd65f44ffe8d2e43732cba33251911551724b5225e1f528157c43bfa7f38a956389bc1a6d9488aac14c648ebad7f69222f3781ddbc890204b1174a0cd5d837d1b081499377f1959b24e1989b65ff1c4a2d7ec73
+TAG: 4bdabe289e2a9f241e0cf296db9b3c76cf89de25
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35ae961d008652bbd0299c7f1cd1e9b41d57df6925fab9838c2783cbe2fe9466e7414a6faf5644dcdef57db1f7fb9cf8b7a7c63f08da941923aeb276af5dfa210e4b01ddb563392e4ada1da940d4197874869ca0a4b18b2a116f6194b052f9fe24b59de86269cfd47394ad4241dee8291dfbf1bddc52fb00d894578ee7e
+TAG: 024e05cc0a371b39f35e4ab27a502f93383581c1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35ad82bf9882f202c0c11597e2482800d8ebc852103e9984a63704ef1849ab868f2bcaf610c95fb8b53e31728c6778f7875389c4babb9e4a7281f238bcc3324fbb2ef82e9c466eeb6af6a64ffc93badbd2a3ce6add5ab139ae4fbd4fb43c35fd857ce22e0bda428680f2413c4fff4bbb721497984bbfa232457e7d1c21f
+TAG: 0cc0ec5b8004aae75b5e65df32ef16126617e50d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a55266057dc1768c77a782e76ae4322b51a7add8bc0c835a05f9ad1810b142e6bb17d8c2e75ef9c24d0511c10c7ca1a5baf8bc79ad0681396968d4877ad82d12bf7e661b2637a0089dfc2e89ddddae0fd607094b4eeddb5c223e7617822ab4fde1ffa908de5533541f5f8432f36b11a54dce9a0759975298faa020ed9
+TAG: 9ef3e1e73953360de26623b0920c2a1e26a77fe6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35aee95333843b7a2002225aa08547e42c08d92d6a45b9b4711eba15c513615069fd31d1fae3309c265db97bfee6710785e949623bf72248e88321c59aa56c00f32ce5fc9056be89e5ec45b07ba7ce2c36af31c22bb6d814f56923e312aa45aa5ee78c1b4c6c41dc0b4b174235e3db1000967b1a76ca2dd8af74cf69420
+TAG: b9d5bfde59bb38f58681fa20950efa593031f15c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a5941f413ffdcbd794f1792a369d82bfda0987b2b7f67706e321bf9bdbd3b7556983e6df473cf39ec2239c89f5ec3de22e790b3438087938bc17b92490bc9700fdb1d1d925c6a88010ea5cd92b5c58c4d8532a99cce8846615d0ee2a8df6e9e424e65ca3eea9eeb1c38f749c5d648e1ced0f2cebf3f13bcc942ed9049
+TAG: 7aa48ded84d487f46d5100f328d33bc349ba764f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a9ee0c05fb137dbc1d2f67646eabfefe9dbc28236c8f807ec462590671e937b96206246b6b85c2a33ddc3614698400fde8d0b927937698c6c9ac935c63850180189fa44fc09297f85f29155506ba3ccf6b5615186d8358bd05eb735b27e611ee051e05f710995398ba9398c9e009292ba55338b23171b8c069f380c75
+TAG: d5c5170756253d6a96841a5cea70ab247c35e904
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a47e75a288e7ad4319efefbdede7a0857a8081ce6746d49aabd4b4f2ba8c20d082cf6bf4b5cd05bbdb43b1655fe8b609da3e23ee227b292f1011d395693043be81a9f604d956894293a12cba599299106807717ce971001aa05e0ec9d39be3082f0465c82121b1f49bcd2430e0a0fa541645087680df12b1ab80a2b54
+TAG: e86c6adc7f01f083ca35610bd5f22ebfb78dd1fc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a0629f957db204898fe27a61b405481fe26c5bb01c5d97a65f9736dc50694b7f206d6b9ac37c668f10cade5ee7da072bcc06dc4b12f3f0c2efe835203ff936d11eae15edd63718a2b3a5686f4788aa9f1a2cf0781f3a5654476b741c257072a293555aa3725294e41b8f5c54bce7cc1bc1788b9592c21308718dba270
+TAG: 51114b8e3e90001359f145f58b2d9b3dcff7aed9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a7dbf7e11b17664aac5ed109b440f93c56d4fefebdbd047ed56e2377f9635c7f3fbf196664684776fab791bc34653e0d0bfe00d0a3452a8bb6a305290532fc71da325038664f21c3903d2e1b55c2a270f8ceaa1cea4b73db70bf77f8985ecd1fb91ecf553cdd9a4414cb9026235ea1529ec7c08174123a226184f51c6
+TAG: f4bbb2d62b35bb6c34ab361277cd87d793571f42
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35ac45e1a7b7210d36cfa15a3897ea58b430fdf50a44d5907f59b0689df87b9061ab2917f655072cc5eae46c1d8163f235025ab349f00028fdbf819e67ce585d8fab736f73f9a132b2fbe1cdeb91c065faa6bd5347fb6bf6e0f7008742285aedc05a4766b0de3c6458158f87ce5a811f35252ba2685c1a10a7e50c8943f
+TAG: b083faf57f0a2eed848d7ea95f2caf8a52a0784e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a1873b81c324fedfb7a30874bb531cd1a6c661134c3181edd25e431d66d7765dc143c9afc3c641aaf0b46317af04a5043070584b8cee0d1d395133417d81c2dfc4f5896f232625d8a120159f8f5d28865d8eee1c717e693d30474191d438680752304ed208cc19f724d6a90937976986de7cf9272258a87272a9c9793
+TAG: 1d3f7c28c9866e5cde68afb173c4bc6b8db78087
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2451f6c86c3d7c32a3e2b5a7cb1f9014b1c2fb510c18a679ccb7a01ce030f5866848f9066cb431f2028e856ab498d8482ce34d2edb586bf2898583dd5b0e20bdef796f9e1e539cc13e820d3b53b3c4bfae3ead6ee4f3f1d217b946d53c3f08630feb98ea3947b0efa064650c2be7ea61945db0d42dedde7da6bab7c4
+TAG: 2a4f33438eed2668e9d03c43a2aa91cf7eb78905
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35af5bc521bdb3331f70bc6e108b2867b703b7e07ee77d3977c5a7610f3201d20b041bfba78439142639a931261be3ecd4c243ee936ce59676c3564e6268d255ad754bab9821dff795f4b02451a273b33babd380bf79ee016a56af9fc2d200d95693816ae33b5a17e6027aac69b4ada2242753f454a78baaf19dfd14e85
+TAG: 20fa1057aa2da5f5dc8471f67c924f275dc3a800
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831900c8101397d770df96fb1f6e5ad5b24746aa5586d913bf8e7de42fdd954b14416d7f23e6efb3efbe1c9ffaeb7677497692e901ed2c39cfca5b5a03aed9cd3f322063a1aca1999a8cbbf626f239338ac205482aa6b7c1912631a5414f1277bb34ee7da9c883e3000b214cf59c6
+TAG: fcda8f97d04b93c22d42b1f77ba8b30637e6d28a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa9208319028372b62337fe9bf92b5acfdcf364278f9ddc516733049b177b726d43887beb9c9d6a6d7b5c6934d52d7b6bcc60bdc858497b3349b2f2053319dde939752275ad122b3f2a188245c615d3ceb57943ccc63d3bf45da8b5d63932fc52edf0b9b3f6a3b0886f63ade65dc3aaa69
+TAG: 6a58e81131d0608200216208d0d86dae63278248
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa9208319054aeaf1cab8a9d96513c49ce0f536a7dd94d8602ef98bec7cbeced6651281933d1cbdc32684db2e507af113d8808313db0d46cb1e86e82d674b9df185de3802a210fa1b1b9e8fb47724c3a3c48b30ff3918b821d68b09ff536b3c9a60d59d2f38799a327119efd856506cf28
+TAG: 56aaa71d8af87329bdd488723ea5b0fa44767fa1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa92083190cba5f2cc79daf55c0a8e122b0d9d3a5e3b0b418f4958f6677110f9a3415866ff557b672f457f119aa9cb312f37544953d7fe6f6654233ba5bda98ba6fde6319d31bf521cd1b25e753e01e92f9a909355391403e7c66fa8bf7cb97b3cb6ac4315945c7427e6e173ba0d779067
+TAG: e3f479829716df4da08139894f33ef69a322182d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa9208319008c66e75d6928538553af50ba78d91667149723dde3e63caf5ca4c40a7254e976a01a83b996cb17b50ea76d90b6d89f7992b1765d14b6b10405b1df99d8683d8bc94cd4956597d80df23a2d9c3d7fd654f5e5bd5b8ad108e3d53b851f5ba83f7d59926b3d7da32de28460da6
+TAG: acb39e8591a728295a5728fea402b38580135074
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa92083190a2b35a493ea2d1d3519c59b7325f531e6c0343943ea35454a3b04a465282fd5af9d46243166a40b3457001e766f0665036a52341efc8fa0f23774dc892cf89c958da476c3596474501a3322549a9bc138b7ff611fa2ab9e0d3e44a07732bf89e41dbeebf1d4f0e095e05f11f
+TAG: 465293d68520a04d3c4dd475330298c6b951f13a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa9208319086280c353e7579e8172dcd04239d1b00621e5a239c51da4ab8c6785345eb8dbbe954822f8ddf0502bc7883fc79fddf1d2ed593f15df3e39d40c53ceb5464a979a1f85d5398c9e68edcaec0393afaea4a39215f8d2b7aa2eda93a862025d6e5fa3da3b2f55d93774ae7e6985a
+TAG: 9f2670696970510924a2d956241035f8877945ce
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa92083190d5fe89c5e5bf88f14f82e2cd77b78adde511066a286b7df3c813d8937c9804a47ba246a1ec095d81f29df74d28d3742804a7b233878582888fcf383541215b882da132f301d123c6cdda099e06266205ad6efb385eddfd9f6574ec201b975573d6f31bb75c9430844e17c782
+TAG: 7bc66372a5bfbbcba3433ddaa72214c55a5946b0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831907106c70be9fcc59102e7a5d30a943390b62163ada6b779fc08fa2fedb2549484e194b9968093ea174f1d331241e61706ebb2cf18cf02295e701a664216effa3a694a8d3340b4fa82bdd1c13b0a1bf60e333679c9a364710ed8ce2ec2425395dbcc7e41ff74d41f3f2d770ed4
+TAG: 27fae8338ed14cbfc8e9a9e21060a44755d98703
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa92083190b3d84464610c884b42bd485690d371e2a0c2448ec97c036394521ee045269bf500a45b5ef04de0ce7ab33ae7433b809f6c2e0901de1cf082139e0398fcf2c97a8f746f10e6e58702148095b77c894d3a81d935789ef5bbc33b0be72745c7b818d470d20cb55117d254c3a77a
+TAG: 31517cd3c3d3e1a2f9395482e7269064994000a8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa92083190c5c73d35d0b2380be1eeda8bc20d3a37ba0389392ec3224c65e7edc0e6d6ce73d5e66ca406bc5dc3262e3d03952bb6ccee02c1fdebd0e74aeb3430ba4cc57f10b53805a6ad3c0f3151f58f0e43c196e6918fb641c82c6411a247b3e222bad21c0ccd7c38ff34c2c07b347583
+TAG: e6786ec51d923c1e0463e8dbc9f4e843b2bf5f20
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831908df3161efdc36c2bed60d693a55062f113c005fd81df1632b4c694b3f5d2d2a600a4916a4c9f3e7b5ca3875c785d8e40b61578fff75a99dd85adda91fd8f395fe975be86a46728c624a045765088bb4ce278089d8380e10e1cdf8ebaae47550aa21fceb3c6534f17fddc28bd
+TAG: 23666122b903583ea33ff94963c7176baa270546
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa92083190616d64020be87355d27f8d41285083a762fa6d65647733e186a07ca78d9e3f6e8f199e138c49a273384e08635078df861ac1b1118e371aad66bce6176eb40d621520f607eecb36c09d61899cd36a6341da6a4e7fcf350f94a618de395ddba9e4f43ac8942c16f42bfba6b687
+TAG: 6010ee1a6b1fb64a2258986e4b72c25e022e369b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831904e99824ae2119b36d75b8c7378224f1fe8bef513d8eff1c0f3e0fadf509a944b0c5a58a08a16f41bbc2a02732362d12f302d56146bb3fa1ed8dc0edbd12b250f64b9d57705e7f1437e3b6a05a7b58acbf959cfd929f8ab10200b5559ca8f1ea1029f17baa11f2cc88c44566b
+TAG: 21f491c0e62cd75068335552b526e646b1dd7da0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa92083190afafa12154322db32286a6b46a89efc7d19eb90a964d4154a925347bb5b73001707ca9e6e0098d2a551963b1a42b4bea80964d335d6134c6979b79907726f1c2d96959ba1834c88bcc8e22ab3c7a355797606bd844570334ead844cbef5130c4456735156ae3532b787dfb5a
+TAG: f36fa4ee9cfb82aba13d666710add00db9c9757e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906cd4a607effc96f61d250ba596034e7237852602553d720e1cc34f7878f3090c443b20db730c60bd481b599c9ac2366623699d855d6e3724ab986d7315e6617e18e610e91fc070160a588a346f63852a605e118605e9c24d7620e09ace2e4dd88f2ccffd141c8ccdfeb46ec4
+TAG: ad80ad44da86b3ad8d799f6f383bc05db63f7432
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c116141047fa9aaf84344aa7bf20ac0928dd154d83f60b6304c65f7265a7b826a4b5e4af40e0729ebe39ecf2fc5134710ce0997ae978dc78b8154eef2288d929680c150a61f0ae0cbbe26fa0ba901290340597df92875c1dbdcbea7e863ec6359e
+TAG: ba84b6458859c40f8fb43efe70840ca9de5fec94
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c116141047c165a82e38653eb88ef84db361dd9b48c935fd692d46dcb84f7e5c2b2b18d09a59d810172e53f865c2ab60adfb6044d9cf4cbf4b9dc33ce949d3d12118796dee25e1d028912ecf154c0e757f2188e3fd8f0afaa68776f7d35d6d9eb8
+TAG: a0326c92d3084e4c5824aafaef50ccc27538f55f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104755a4941c2f60857ff6e80bd1ea5a6cfccbc6e673f81cb30c9cb2c9da04230e3eaca9fa3946a8f6eebab33a48b0cf8098fb8f8fffad0ebbd7b639197813d144d2774ab368e56c7d21317360dbd6d628512613604e23edc9bd1ec44627
+TAG: 12a7e9cc7ff5822e48db7ac792dc38e0b89cde44
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c116141047bc52add8725e90a704cc544c18c55a5f26b8dbd80931dbb2bdca4e7feb4761c08ac53aff5b67f171ba75555ba4a02ea92bfb47ac13d707c8863c614f61edd4b8a370f94840b0f4b71a848ca1655c94400d5f40c9e6bc094b7e1ec2c7
+TAG: 7ff5385102256d8a294514a32b8af13e979859b0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c116141047a807c399a212080bf46a0aab9318474c142e6bc54957425861bdee12c25ac4879944d1287301b61409a6cbdedd00c96cd2a27198879c0a5f48a67184ca31fb843b9e2aedf474a768cee7dac5c4edd9b8c8f4ef64fa63baa3301a5071
+TAG: 606920e880ccdbc02289fa5ec99e8ca7d83ceba5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c116141047101daf826d11e16c9c446ebc098221962ef8d59c96d7381ce873a2559043515d975f0dc3b8198fff4a9663ee8c3fffc47238df53fe4606ed58e99e8ab6c75c2b993b87e4650c69add83f8e577b65b480b07e3e09c9210a988f5ae2f2
+TAG: ad6021b573dfdb7f6dcf03741816846e5f89ab34
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c116141047083d07981b07998829d3df64f98882aa021602812b940c0947d738c0b6f957f26c3d5e497a5e17c4c27e1ea56a0da64a629df99ab2e0f4bab31a5c64ae69be00d7f9435d4ccae4353d518f4b166caae430108934098222d2c1a4cfed
+TAG: 7ffad054f571bf7b15a33bf2d63bd1b958b82ef6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c116141047e9387e48f154de2d9436aea7fdd09499324a2c35ef5ed49d769243b09cd97481577270407c8280cb0c7b81ac0c20c3768a7e2de6ba1acb5e4a140c5ccef96aacd97a1e7e14d432ec5474173291bb33a877b09d6b99289037f7df4065
+TAG: 44f9896a991a8b06cb1fb3ac821c790935e7e141
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c116141047a8ca0050293db8d3f058e9269b1b76966d2171a638f48f775cd75b40fcdaa711fe966a77ee25c089f8aa145260a6ea861dbecc084ef71d5bd74782f1993e935ef9dfb1410f2a5077e430f7d1aacda7acbb1a48fb038653be08df3221
+TAG: d298432fef722df2b351cd3dd98e628d42161564
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c116141047f4dde9cd1daea24c1d4a151f881548d91d1411c304c6b9fe5d06dd794d2631f1d2e7a7138d6734fabc7b37a6b960191ad8146347bb8f2a75d401a1b62417f793ac365ad3dffd23caab3c2695ec8aaa671bcf9b8c7dd2d4d5cd2a8c5c
+TAG: 5d38382bab817383f846c6c9b4edb417d5b9d466
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c116141047aedf9fe23dc32e6f5d55d73bfa3b8ef4d3030cfe171c2a28c30e46d9acff763752815364cfc00afe89e0a8cd93227457b25e5a56bddec2489494297f33e8fd7b7a1a871f7337f04d0f8c63c8e615b6470b78881adb326dfc9c1eae94
+TAG: 6ef74447752a4774435e00da7abe997eb151b7ad
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c1161410471e7c657424000e3c540fb033513ce8a4bd3e8e19bb691af840b631debdd424e3d395d85ae2b705110abc530cc1e3a2fe1443910812c910cfc190906d4f72032d82809476ebb68cc20a0bd9e6d2703d700ea5b333f8b2994440cb7310
+TAG: 8f1ec70aae4ad69ae1da278bb70cd0b3a5b141fc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c116141047b1a862597b016c6d814d541ebc0d10833c186d89ba4a735ecc5165b32f7c88627f4b1cbb7b321baaff0481c7a88f7240d7de10f460ff8e894291b25b92c001a55512640e0ac259b828ffd9b73129f66691844a8438df214a667fb6c7
+TAG: ed129d638ac4aefefcba2dacc0df427e6e47edd5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c116141047de6bff50d76cfc47a5eb1b45fe52aacf5e8b338e523d68a5672842494cd0dd7a749dc52826a7e69068500cf9ac816c92f6a308125e116dfa55a355a74d9e10a08c8dc21e9af8472b43bff7172e539c740ed4680b3596383dab96fe48
+TAG: 56ddf2a02b7c6888cdc88544c3a4e0bd01ed8dac
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c116141047cd6612d49261d8695ac0e7566ee1575d53ebd2e6878af1ace30a477e81597ce97197feba029b8cfd8163e6a2a396a36d844ce6c9a6cbfc404bd1a2f490b337791ded8c673902a769189da1d6a687d77f3aed796156bfe22b0e960748
+TAG: 9a1575355769c11e74323d0031d2e4ad12461578
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c1161410473e2eb9ac25b12dcd7ed6d67a7b96be6b1c0b2ce3942ad15d948e6e79a3f917475024885d8509acb2116a8c6cbc07fa501c9d6271e0df97daa50e39eb096d38322babe0ca1328a3c45b60315f27ab40039a2ba148308a07955eeb4738
+TAG: 594e733b2130c0e795b5dad2236b7d360c49c225
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6dca5b9640c7c0da35f41bb00a49f79f652172b979f3c4cd6630b03f88af292c3d4dcdb5604ed380dd74d1774cc9b9882606c11e4607aa94db08b1c65cdea2dba7552a31aad3d28b1565939b0
+TAG: c9de19e361249c858e0af7b1894682cc36d0ddf9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6933104b4870ebfd014c3b50d03df929c631ab1a96cca9894d25e7bb5ec04f401a466e409023f5e7fa502fcb3d8f846e29bda1d602445e5df28c754113a2587e1fb9b5cadd4b076c6fa3e57ca
+TAG: 08c2e1a1197617f34a61a3ab29876a256b14146d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6075e597324f004b34ca023b114c030b9d78336b655ce9a1c3fb5ca4e008c20ab39b5e353bb92efc4e02c614d30dbb3c996ed0023064abde1fa54ea6367d5013300f08a1853c7ce0071ae62d9
+TAG: a3f4de044794d9d3a06832fb683e275d2244de14
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce60a712536e54c3842acaa2cc9a9756744f168d395bf595b778f9994a45a924ae04a415ccc1a83dc41cda7769385ee9114ac6c1143f681e06c50109921fc75c53e5c2639468de93c2f164538cf
+TAG: 9d8991a378dc83a0fe075fbca1c007ce4527ed61
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce61046b32203ba25a317b72207f76532102891aa0cb98680bd0a6682a15787158272197b2a05a82486c10d5818a0e5b2a1ac7e44795608753cd5b4e920bc4b57b3dffecbff4c373e7b6a7a85a6
+TAG: 6707d83b0dab0dcc7b1af01dc483def1c09709d6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6f51ea1baa14eac6ebb25c894bbb0b0f1ef93345965a1bc5b46f7b77287ffc5dfa45ced0b8c0f337d180babfbd89cb73f89a6d6ce3437f3a833dcbca55109d6450263991498624f78dcad432e
+TAG: 70898d6c762d0a991a95ccc0bcb6a6c00bd93ad1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce605fbf9f3cc2901cc8748f4838795e7241640a6e25d06d99dbbce45fa00798c8bcf7121bba5071f88405c24e2db95c6d52fa3fc3e84cd2c129e448d4fc4572f61cd5eb167cd76cf86a83eccd1
+TAG: b041b1ba1dc9693ed4c9c3048842a66d5b0f884f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6b076ec2a88a0494fa75fae994ade65a14433805ceedd17e22978f19830c84e3a94246029733e034ab7a76acf2db5b564fd0da5d1b5287262d534f18c2f32b329f192367ac482eb86cbd18160
+TAG: ecba85db050b2471accb0a555ed94d354bf33ad7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce61e72bdfdb33f5b3f9e8ab9b1bb9a832df8ba04bbe6941b551ea5532571fd5b48d61dad3169e157ccbda40b7c5f6885065b07c6c678546bff3fa3b715ff754acfb30c3d982b9556eb41bc1d2e
+TAG: 9b22efdb32f9dd8fa9b4c85a0f6dfa0e19907353
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6664133a90b40b409694781d907367956d2ab2ee82be3dabcfe9ba7cbc7a33952e72d9c54ad17d5b10c0f4ec864aff5da6583001a34a8844aea48add4b6d77151970da0b22d2726816d3c4df3
+TAG: 8bb5442785ec4c6ec7d2b0e45d8859833ec667d1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6bbbd3530618e26b02b4da998342dee5927a38b0e723df015269d77be326267dfd5eb14efae355b5a5c5b2733329f2ec9d3252b46be009d8840d06ef54a0cecebda3768f79f315126ba931eff
+TAG: 85a7b1250dbff94cb39f6e78c1af942ab2782b14
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce61a922fbf43f23c3cede19a8517983223afeff8552848863886af4fe2b5854a908c0ac1a2a4609ebcc28fcfe20ac503857acd04a9ba03935bd34c1f873b343cf660e4a81cef0eabb2104e4644
+TAG: b17a2b4784927dcf315aeaa199dc21864fa53e58
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6e206d2d6eec5c001a6b8eba1f76765269ce81fbce947a325047bd15af8838005212c215eee7c4da8d64b4e51c66433aaefafc50047876e59f761f0fbe1fe521b263a86d3cc9c027c9443711c
+TAG: 0eb19d3def4dda1a63e677f13affde261edc99e5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce60c075922c8a02cf7615c6a7267d341f310825f9c871d5dd9103998eb737a40a07dcf13634d0d01f49d78c367a9e2aa89883c254b76ed01bcc470e653170dba24d13ecb15d5e52f9a0624de70
+TAG: 67ed29aea3611d18eb1f11fa8fe59c832af894f4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce615de261a7b79ade1c98d2237ccf27e40aea8bfa67f3abc6f3b079bea63c75e31b4c0746b614dfef9abd2bc35f499868214b0a5ce690e0d962749df7bc0043bb90298951fbdd0fd779627cd23
+TAG: 5a086ffe8c5110c860060b68e0ce9af0ef78ec4a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce65997b74ce3bba5431ccfc7f80ded6fa45814454cc38a5caeae0d5e430e4805458824d5a2d2bd5252e062c287832a6c2e1cb3586ab1e40a4c96e6a92ac2316f90b72a5b895b838a35ed80c1d5
+TAG: 5c2c301edee89749678da8b0f5ab66a8d5f95b34
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162a3ab476bbbaa0c34d6e5bf43c33ae8106a92530536814fd9c64056734272d19350183f07507e44dbb458166e9b42c0b969b506df95133312cc6efe73c
+TAG: 4b25635e517874db9ddbe0b49ad53be91373aefc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162a043096e12a22e8c62b68441dae8ccefefdb20c9e4c8d934318fe00ec6b43d95d512708e6b63fd3022b144de7a784edd36af2ecc7cbe149ff49f1f04d
+TAG: 013b81ad21cc3ffb9d49555170c97e40a6698579
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162a5f626b1a77b92ec447c7815bc8b77a7863f0746e870f62a47dd4a77475459b425b42c0fc8c8e5dacbc30ee982933858b0000a0e6515e76e78320caee
+TAG: 6a0048b7c0ff897f0a2be052383b68fdfc9046a7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162a2ca3adca1557dee22780a8c678ec358b166d68dd3ea3858c81c1eb3dc3963816c44b69acabe0a14a042ebd6ad30a69ed32deabee60ed77a61ade638b
+TAG: 8a573aaae4582b75ccbb1270dd0d437f275edb10
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162a3ed2ab39beb101dfb235b2dadd5151b11b66feb92d649d931a887ee5d4b26e35a4ef67ae31030072f6b83724ae2d9f2b1c4f330c46e90dd599d6142c
+TAG: 6de19bad2ed1d8fe80258c4bf5b8e24ec92964c7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162a2de2292b71e282ba086f3524ab8f69ca0a4eaf804b59654872d5829c702c637e60e8343c021764a014071eeb7629f9836224eccfbf877e62b0543d88
+TAG: d9c97d7c6506b7968ffeaeb56c9cfcb216fa7ac2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162a702cbf3be86cba9ab359f35fd9ae056eb0dcb0c93985a62ed5204ccab738b9f95b3b88855c3dcacecd8048e2ff3b680436be2fbc96c5c604c1da18d9
+TAG: 86c1def3fa5d8f2f9930c73c98043de0c002f5bd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162a01a27791e98d888e37d3e884855d55b3a6ce35b6e4f39128436d089dbc6b7e426eabf6534c2c3473a96909af16d1c53529786ee6a9b014df537a3e63
+TAG: 14be7b92c4d6ef8098fbbb69e949a29406492338
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162a881d38d226743c138023afa1be39a91ec47915713767908922eb003f1a91aa2c1a7db713272c6f9aa1264633b75f6bdc92e4c3c4a01d62d351fe1a72
+TAG: 81a8c7a5bccc5e114e8980099169dc546443c55e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162ae257e836b9860d4f05b4acf35e4e3fff09616513167d7ae6c9bf2ba21566529d172265ea4ac7aee9b1804d7f26e24f374bc3be6a40fa676f397acabf
+TAG: 3ff863b5e6beb46c6a3e5f2a64a4f061435a24b2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162ad0e8cb804c0772a70552f0ceac3b79eda7d7243bdbbd133b7bdcd9f28d4563968bfc4b8ee31506dad4eac84add1be7daa266c740f8bf9a18719d0c09
+TAG: 86dfa7ad959e65de4445d740269bfff920065354
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162a1af75b17e84f04ff6b28210158a1266be9083d7aa993165a7481550d7917bd85ffab05740a5137d946f61b1f510f87c80593e3ce50d8dbe3ff8b8e7b
+TAG: bb25c84eec393e08fafd7b592616d4977a455d89
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162ace0f4412d9a391e0f7eb831ae0719cda6def7428638243f399fd49818effc75a327d6d069b2198be3bf904d1391f4478bb520f1506ef7612324b06a9
+TAG: 0da097ffd67a9e6b73e1fae0202d4e836d3203d9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162a04eb78975349dc0ca72958ba71589cb823d2173856e3e88e0ef18ad03e32e3b078844b3ed8b0ec11715705b7e8a64d70c0a3ebe944175f77b4bd8371
+TAG: cda4b2010dae692006ede86c93ecbb2b73a79f23
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162a8090218b865d3cbeb886aa913863f74b5ab86bc01782c1ba97acfc1888b47bed713fb31041326b4afec95d369f5b2f7e9ce58388347e92a2159adc6c
+TAG: a2c56fc4f1d28181526093bc324b1092beb6863d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aaec97736ebcd4c206c89d4fa677bee6a45d69d4a2c1ebd4ac84db78a93785634c9d1f91c1a9b5245d73e50490a7e5e2ce7f36d478a6c38d7949d18a8
+TAG: 0e3bf7f7938d1f85f52c8a687dbd23cf89b2562d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846d791f8fc6d6905429e78b0b4fd1e1c6d900c1c78b3e02cc0efe749bae139a456c9e9800b6596146230b8570fb
+TAG: 3060552b7ae3e6a5588f2756e26890e461aa9771
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846d906bc6c25534cb54e5818fd7d63782314af4b8aa65de9989e73355499226463f92d62d989fa75dd8254cb4e9
+TAG: bf3003b6c4f0889476a67680e21dd3bbe710e7b4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846d80c18b60c43b7d9b8641bad9708faaf2bcb809b0c8d639e2c687630aaf9817012cb446296d27fe65c7ec4901
+TAG: 407fe65a06e4a071be930a2876eeee530363b26f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846df30dece0415a329d00ac77e1f63aa2ecba9528cb74af97cce119221f71bd0cec99232f849147b09a9aa9e7a8
+TAG: 0c350afb05cb7ceddb5558cc638ccbfddb7b1a75
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846db1ee4ef1a05b86698eac204c04e46dc5f5cdd526c5e7aabeab751dc231bfc85091726d61ccf98a1717034f5a
+TAG: 3fcbaa14fb1693a6948861214c2b2b5a7835ba7d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846d6bf1596e8330255ec7e8e017aa63a23168d0c2e8e95b117549469b4ec91b955b7686ad1065a2f71313e46e4f
+TAG: ba4052d639be43334d3efa18e498330d9fff9dfe
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846dde6ab81726cc8cd29f2892ac75df6aa3fb3a80ba664d509638a1b06fdd8924fe5933dd9e5456fcef5ea103f3
+TAG: f15c0b144ff4752cb8d27f636fdb3183bb0ae6bb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846d135bb259ae4d6636315644a41beffa421b58b20f17471441c0676ebaae2fd3aac98abb68a4ba161199da28cf
+TAG: 5deb146ef55d9d06c09d9d7abc83786bb04299bf
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846d6a57ac180669cafbf715b9168bdeed1cb6205f7a6ef405cde06f24f14942d2f893da05977382b9fa1be0e2d4
+TAG: 881bbe52a95e42d8cf70b451219abc0953f44bf0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846d7cce794f2f76911d8bfa76ab178fe73257c530296be2533358db129c82aee8e71975cebce9556ffa79fc2610
+TAG: 8a960780945ea323241d32e1e0b4ac867af75a17
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846d01adef7c2515e7954f82a3ea57721ba9641f59bd5db584c7eba9c6875260e3e5f18df34fe8c77a1fcc41446a
+TAG: bcfe96b878e2171fc7617b68152d32706bbc93aa
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846dcb5ca3db6ca2653658ece22c1345d740388d54919ef17140bcab1b1b93062701a71a7e05535ae1c7135834f5
+TAG: a97ed570b5f9d82d5f1210ae9b94f93a5804afdf
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846d0af56107c7988099ea59dd00cd99869857a9e7b69305f07b6ee7e4e602f2c0229303e63feb5f260b9694be23
+TAG: 5313d589a02931650ffd968fd3e0947a229d255d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846d7368ab5ce95d1d39dcde76e20e8cccb4b7820059762afca3b5f1cc679f2b01778e6cb56935d5dcbe6f8a12a1
+TAG: e0b419520fb2db362c7bb7831b78f3355855722d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846dc1d2b07a58d4df8433c66f180fb668f395b78a871059b574d80ad0093dcb56b6d2e373ba14047d33e6275816
+TAG: e791085b6845454d03799dcf108b4bfa919ce6a0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846d01e823c528a99f01f996aac79fa2cf45fe38ed6d041840cc4b82e20b4c79c58525a30320cf89c9534fe70c07
+TAG: 8d79562b8ba0473ed4b89872a978db92cf19ff8b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763d80465704fa438f52d2b5ba709fca1027eae17fb71dc5ce73d5b8fcd2
+TAG: f123464d64884c359875321dc7e9013563316343
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763d2e0a983d49fd2b7d695394fc3947510255223322204c38edb96f7ef8
+TAG: 97779c4b3c92599f7be37757455d0a86a94a6a7a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763d6284a540abb58cb78d7e195fc6e9c6baf3c4256dc7a3d6a50272e7eb
+TAG: 9805227d87596bc788bf40c44590c1d7e2657cac
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763d3c9172b923f20ec069c79678174b6505d00fad11197cee0591ba7e0b
+TAG: 31aeb5f7399e83b406b97371c38d5f8eae2f289c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763d7f5bfc728808ee2f49dc49b846d504d3e0b7d35ebf09a68813f8825d
+TAG: 1ee73f8022139fd12a2c0668d99ab27bf3d1b5a5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763d250d130fbb722bb24f1323a63b0fa6ce0bd435bdedbbf1ed3573aac1
+TAG: ec65da5f7c9c97b79ba619020501ada5eecb633b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763d038c6a8e87699da488f08fc41c0bd2967826b74ed155a34336931e52
+TAG: 86f05d8f365eb743613d82e393d2fe2e4007e74b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763d80a404cb625221bc8ad042b5c3ce5e0e574692329aab023b17e935c2
+TAG: 61d83c81b63711b686ab9a291531cdddc63d7a97
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763d52a1e7de84d4e2a24ea0006558a3bb6df29cb07532df9ff7a1c8ad18
+TAG: 2fd54df751b4bf4df2b37917b4abd02729600b67
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763d7007db41374283fdeb9542caa0866f77e5af69022a66bb35ab69e4fa
+TAG: e97ff9fb667f3fa74fe3442e77cdff598d174f74
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763d2717d82c0c3c1a976965fb754b94948f9e85d2fff604b3bb76872807
+TAG: 351659f5bcfcd7966d43bfc31888cea71163ac4c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763d0f0a874f5148b609dee63339e905a665d7246a1ecbbb47959a9587ec
+TAG: 3beb6131f7956d40cb07f18a12b8ea530a02fd8a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763d926520fd8752d884f88bf0be5f0b420bf6921d793bf26b451555e871
+TAG: bd06afbb43cbf34c2f3b669d9c637a27a92d85c4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763d72c30cc67e9f9ccad33b384230f1c21f286d1d7473b8e16351b3ff30
+TAG: 35b58bfbf57b6ea6d6fe71250c464bbb9481da9c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763d21b70b15d3a136d9cdac07fac99f4f745de7cd782009df2d1b02244b
+TAG: 4033aa15f3421f36dfccab180750d787c7772c62
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763dbe076d0ccdad6956615ce720a9504fa8881fc12141266795e32c44e6
+TAG: de969b0cc80f307a711764176c45a2b61578042f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637d97076ad63c09bd62b3021807
+TAG: d00dd12bc19a750b761d837d3ce7e23f87bfd955
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd1eb4f367328790d0c336519
+TAG: ef9ce0469baba42cc879905a01c789376dfba48b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637d8930b1cbb8a27a5437b8884f
+TAG: 40899ae1fff5b19f1e483afada346be3881497d4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637d3759c77b88bf27b59355096b
+TAG: 6c9fd8904fd53ec86214b199e5eaa51dfabb9c69
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637d9b25cd67dc32da238f4beb7c
+TAG: 46b5b0b62c09615bec0f4215f14689719d0e9d98
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637d7bc0f6491793a639dab3bd21
+TAG: e2b9f2f688612a1f6a64325d76a5ed922808322a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637df54b0f1aea70534243e0a3ee
+TAG: f9a5276dee067cf0b2d7c961b6aaf3db6cd7183d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637d95600df27b03fcb389c2ad43
+TAG: 2e339a49513c68d4f6468d274314b0867f1e860f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637d3636c6f77341c33c856176d3
+TAG: 730f6db832f8c5b0614240157e54e21d95d9e6a6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dc5c83ab7291ca53f5349a228
+TAG: dd65f3ad41382097b3939856438805fe470f1daa
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637d70db80384ce9fee793c2605b
+TAG: 4c2f874190ac93968d6af4bc15297444ff9543b2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dc4cd19fa4b8dfd07bc79d672
+TAG: 99f4cc199fb22c90f4d12931c0427aeb828b0685
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637df33282eea3d2d6ffb320f2a9
+TAG: c8db582216c76186a6839c6f7bd68c2c974ccb89
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637d791bb34a274999a4da6fe86d
+TAG: c7721c320cd1eeb8493201b14cc50d57d458cfaa
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637d608920d441336fa7af3df86c
+TAG: 6ce3fd8c5f4ac7f63b60444ed756c4bb5025241f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637d34599c44c43e41bdc14f66d5
+TAG: 937da23156114a88ea843b84edbd9fdcb4ae234a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd13088aafd6754bb6b69613d5c6d44e35a719d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd1308887e235dcd863f455f46dcbef58eaf988
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd13088bd9e2635b36ac557c9aec20e9d956946
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd1308857849196067f9006d7f0c68e1d2c8924
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd130888cc8a6dfa951f1658d0e19659e646816
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd13088b7e6027a082d7c1981e33e8dabe64e9c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd13088ea212c55051ce612c08bacf120da3ad1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd13088e1199cb3294649c12ceee005499c28b3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd13088170815e317055cf9047950c2b4a217a1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd13088db324e45f343cd393e5c5a7518f38d1d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd130889fecc904ac7849aad43fc2b71ea818a9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd13088f48901e30f7a0f4a9e4c57ce18111fcb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd13088ed1961c765d373a15c4246d7d74ef15d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd1308827be87e8580773b1703ec6d37da6b455
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd13088d87472c3ea4d1862d1d4db423d8da0bc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f2710974350a2a38a13b0434d312ead153f0c9488b88357e81187178465d2416ca97dbf7460c9519ed9957d9e74e62950447e49dd233e9c504876a90fa79273e597ed751da4f32a2c60cecbfb6641ca2e8938774cbc324affa9bb027d219730d57ca1981e87d0dcd0551618493f79ff8c0366383e0698a009bd976c63f089a8b901b5a08fabf0d3f798c349743634d5dd35a2195cf0b74b67d36d65be1aa920831906acbc57cd880964ec948e9c11614104721efb62a47600ee968418b1d197c3ce6ba6246d5ac1f07819f67c2cb3ca5162aedd354e2314d65d5e863964db421846da7603b9f11c503966834ed501885763da3e89a59f89f1e31f78111324b79637dd3b6aeeb71ccf2557f9725b8
+TAG: 6dd13088200478cc2d41d11ff6032c9579c97bbb
+NO_SEAL: 01
+FAILS: 01
+
 # DIGEST: f0f82752a691ef5866413f2b2e5c1d0ebb41ccc8
 KEY: 7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4
 NONCE: 183aa23fd8d7efd88503f78b8ed1c8e9
diff --git a/src/crypto/cipher/test/aes_128_cbc_sha256_tls_tests.txt b/src/crypto/cipher/test/aes_128_cbc_sha256_tls_tests.txt
index c6419fa..a5aea08 100644
--- a/src/crypto/cipher/test/aes_128_cbc_sha256_tls_tests.txt
+++ b/src/crypto/cipher/test/aes_128_cbc_sha256_tls_tests.txt
@@ -23,7 +23,7 @@
 IN: 936a91d0b5
 AD: d2c0267218cb7090c61713
 CT: d25f286de17a05e3727d1399c895b024
-TAG: 64357998b11b7f98525ac704f9cd130a810efebe69fd479ccc46f0cd15a2ba47
+TAG: 64357998b11b7f98525ac704f9cd130ade51ed6fbaeb7156c00d1096706b23b3
 NO_SEAL: 01
 FAILS: 01
 
@@ -38,6 +38,2588 @@
 NO_SEAL: 01
 FAILS: 01
 
+# Test with maximal padding.
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09c7cf88bcfe76c5ffb1512ae5db71c1cc
+TAG: 42bfbc03e6f3dd17b160e4b5696b2741786d5ae3f934e9d6ce0a4c372bf876cb
+NO_SEAL: 01
+
+# Test if the unpadded input is too short for a MAC, but not publicly so.
+# DIGEST: f1402641d69b3d67d63e5bd137ba006c70582fc0ac760c7cc005f22b69aead4b
+KEY: 7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b
+NONCE: 8ed1c8e9ba2fd6773e0d0c302a5f47e0
+IN: 
+AD: 936a91d0b5d2c0267218cb
+CT: b7029343d0e2181977ba2ea5e62cbcbc9f9f04cc0cbd6169898c40da2825c84eeb9c1387dd986966d32ea928e2e9c26d74ed3e403f6fbe45364935411d5812cd4cb55dd58f6abbd097670dd6255c213b7cfe32977683c49292d7744a36f1f2ba946203877bd483dd2776f9993a25a30ca52224536d562294c5ba4b8317fbc726dbac47cd421eff4b01df39efdac427b1e796c790b89dd456d85770b11552b701d87dfe1293e70a1483cc7df6bb7bd7eda33bf929ec93be155503c6d6e69dd1439d3edffa8b5d0a246d4abe646062204396f8e1b195132912777a46606f43d98f
+TAG: 8a77c7ac90907888ea907ba3a2a026fb81882b1662bc2be3bf06bbd6baf868fc
+NO_SEAL: 01
+FAILS: 01
+
+# Test that each byte of incorrect padding is noticed.
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640de8b91caa66952060babd6e9311c99ecfa4fcbe93361b66daac85d5ad275b1fb884284ae386c32d8e3a1dd957905c14e12b163b703dab8a553b2c01a82c560fae26c682d7ed704c41fab181706c674b52c6d63bd0028fbf0b37d699484ade678f4741f39a51012ff62a776b3eb7bef04d11a78321fa3a0584c2d8c961d362edaaff4d203b0bfd385fce29a0e2f38690d47c6183c38c3e7413f1e958bd2715d9d9d57b637b125f3a1ff0a243622bf4cc4bc570ddbfc8d66a2fd523ba46bbe185b9c5e5e5c0a219b81f16924676bba1fdc3a3211bc64c013405e79edc7c5ce7114
+TAG: 5e7bb34e135da449640aae5df761d7bfdb8778931a20875ffa6abf31762c2e0c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640bc35087101b1c687f5a2905010021ed3a7fe2e8df54e55fcd129fd6ddcd4312c6d170605ae15604a5efb4fa3ea7950a43071196cbbad91ca7382bfd08cc838f4669f51fd6c867c6cf37b009c9e80d7a0155bf3ab79ea91073de8f53c882034bdf708bb1649ecfa106c0f07b46f479caf5ed195a10d18cb945e15a87380b929bbdf9a26cc4b362b36047e94d4bd98013d35f97e573e1e4b42d384b7cdd028d727ced875fcd36568e10aa0a2de8c835123963c69e0cf1d62b92877ce68a6113d2279a56eb06c89617212012ec511748678ec040e90fa3c53078734cd629fa9d35e
+TAG: f50e33ba21f754460527c4c2fced548a9cb4ca5dcc86adac2e2efc024016f90d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f30164086f1d64addf77dd68b8010cb23bb4e5077151e81e0de509c3faa6e668a797eb8b5d6e0f8776fe2f709ecfc3c9faa63e1ab65bcde09f2db34cce606cff0cae9a5d411b68d7388102c66229bbcd376bf49a6bc7fcd295f6e5337d30626252aec87d18b355dae948d92e8ddbef20a61680b8d21171adbc5d9152c102858f32ce258358f38d4ae97aae88ddbcb61e40966731f3b088ec668003e1617665491e3d9456fb63fa491e18283becd63cdfd90b99470256535ce48a29eb551075358728d5bf93507be956f4f2ea31739bb43e2dbc9963b08fb3768846493a1e4b5ca90092a
+TAG: e3033d1b293e76509c9ddc79033bd29b4e745da0c36ca7f291a7ac07df8e229a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640904b9994d5a0d52908e3469be58d3ce6de31f6901c1b75345b9ce403743230140d6a49c58ceb20a1384d4bcb3a42b3963ebad957d9cd96160f2aa4d6b0ef1cb0f2c967601eb9a81fa8ca7bbc32e62bfcd5ad7774274724c41f9d90eaf13b0f6b1c57d13be8c3ad3e7d027fcb3043b8f3334669d6e3e015f12ac5d6d624fb6860d4029ccccb09aa53829c83e107cede193b4cc6e47a087e572634ff6352f1817f016a80eed46b9a93809b88d655eb5142c9ce20f3bbc1c6bda7871bb0f3c39f14606f190a8b8abb975c661e88383cde8bbd2de3233d9881787ee7e1d773db245b
+TAG: 6334159b1ffc73d5283f17b098b8c3fbbe3f7eb561e8e45585449d099876f2ee
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f3016406d3621592fe4cb4eea64243b160fec5003cf825d63689c5ccd21bab6a05c0e99e9aaf22ac30a298b19a0b3f47204ddd35770625bea7d1f7d4a2efe167600622b3baffc25496fe7ea0f45142bf2255b04919c5f3029486da355da23f0ccda0c76c7b5b770619fa0a76cca4df0fa21d1c252aefd096d66fc5f85da2392099b2ffa1d5d5e063f006d2f7b93c0cf6e227649681e6ab9f235d030cbd90fafbff3a9d6bb43def90e2f8b5996dfdf377206ba5770bca53730fdf1921f9511485c1675f1fcc53d946f490d9742537d07d625fb2d91ea84acaf8a84236ff2db8f84880a28
+TAG: b3fa36e7cf09bf076797789e53ce51060394f316c3c9c62fafe62f5975df446b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f3016403e685398348b7e5da4515738cb938ec83b741ef8d77c3b92464d91d834ff4202ab1445b4a1e4b25a55361e5280f2e126804fb68d5647b50bd9868dcac4bdd559ea9e536379053cdf84ac777a818de2312b1ffdfa575d96586ff796c35ddd30a52a24f27a589205e43d3d3b4f3eb8cc3cacc37b004bbdb9584c2104127c91e6822e8d0e226521f19cfab25003b44125176855097f0cced675f1f29f8f3a0975dfdd4e65ed62783e5d0c2f35b0bcf725b98f83a228c11d0c66082990be5f2965f25ae3efdf9a2c5d576cda133fe144f0e18938efc5f4a54bd48aaede7b25ab17c2
+TAG: 373634a120fde3e643273742e58191aa3dbd24a7ca13097f5ffc06cbdf93f19d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640fc5d0583029a616c6dff07fd721d4b1f79a087e3d62ff440b91f75507120bde0175a4cda30951a8c0918272995a2975c717222100f8ab37b7a3a357278d34fdceb054682b0f3545b4e245906dc57d7a632d807298679e0885448e91e29ff610961d8490caaef1375e097bdc7d74f3817954a8fc0f94cf227027bcead1072ed77045648b4b67416cb01d4a4928ed3b535f1844e885d56a86118d2a50ed89583c9806b622601f7f64aac691311106b02594335c71f0fe7ec536155e2b6c316ad52d0ad653861f9f50fda1e1bc94edda6f64ac47391fddef16896dbaf45a9fb6548
+TAG: cae967d17f9a7101827d89ced2f171d24f044d1a58fac1980db448c9b3191721
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d2ab0d96507b78a2a4b85b670ad6335010afa4e2382070502a1bd0f03f4be7abfed2667ed74dee8a1b052f45d1480dc0e96b242e4287b5fc738da11bb74678b4fc6618a505a3c7d0f4f82fa2bdb08020586e68b2ed6172c14c2830c5929fecd6fb46168df19117fde6ab912c727da9111e1089d69fa726bb0a21e5cb6ba465d930e3c20c162850e22c9faa010315315672b51b3ff318d3a57192f49f6a1770917d4658a0c0ad549ff798d736c382d2b5292ea77d7a0e01580f63236887fd783a57d915ede0958ab09299969bc8d7667ae8fcc78a5f4c10795d62573fae84f7b8
+TAG: 0a93fb2bedadf958684883d4c3d969209f362895ef8abba55dc10679f9c9a9f1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640632fdf3afb522ea5761929fa33f948890d1aee40f2ebdbc35da04291df9d1e62f3519e54da3dfe5364133a71a207206485066c84f2fb3b09bb48fe09dbb139fb6d80e23a8d56e9eeb93ba3091ae0d19a3407c9cb911b41fa9c56acacf32e5181f58fbe815a786ae8597ed502cf53f6d68002cb0994e2cf999b61ea24b6319629a5b15284028595843c26c774a5de4d265f2624ddc092ccfcb157b34ac39939113202054219ed1d1b338c213b68307d3cd937004ec4d47f0873cd7a2334432817c49c1780704bb337293b9acbee5cc9177509ef15d5205c5e19defac9513f5f01
+TAG: f94789f225401eb501149fc7391ae6e67475d62caf03ff88249f9695364ed9b7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640922750769c846c0b023504160945b8076e1dfe298b145733f281ff50d6bc69b327ce920dd732e3d5026fe98de341cbda8c93eeb02dc962a6dbbd6de8d5d8915d2a823938f190b01fc12207fb94f5f6a33e871c900d42f734fb4fa9a98e0d1e9f9ca7dc2f4af5f61ca807351abc2297b818c911ebdb48bad404834c3014ddfca89afa10f26dcedee813043542930fb7947c50c3eb29f99e037a7b9fcf72c27e6d5c7bc90f248b647797f85bdc7e9f2f81ffc260d25af5a9a1f38ebd07b36fd1c7f2f6ba4b5091cc78a9542f8185b8bc04c88eb82de6a5f77b1530acf3db728008
+TAG: 9f057e241ad4c1052ed1c95b44cdaffc25336af13e654086be093c82f4f2c79e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f30164075aceff0c4236d3d7817d9402f1fd013a2ab905d530a1b433d68e831cc89a7c8fe29e49954a0a836ac729fb16c65789d581e477c389ba9fcbc4167e35ea80d662b45a397e16d78ccb2eb2b05198e46e30056b05f7e13ec6ecb3f9d923bb711e64df1be009c4c89e25272761c5e4a9390d4fb6911bf9f0bc9311583e6118d2f245ad03668bba1c33e71dd9bb68255094d76bdeec71fc673d3dbfa127599cf23c780048654d0307737ab0b2ffb37b79b8013d6203303687d1897ffee2572d66dfc1a82852f06d0ee48217806cd2b07cc1f5057be303866aa8e4c42645400c5f458
+TAG: df498e97482523cf45e9b778126566755b7f5ff164c42a0860f220861e3b3e45
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640364eb33d0a3c231fc0d9531facba30a282db764f4ea464b662ec63855bb8cd77541df6064953fde0d5f4b228735d39acfc8230864594bc76093e459f9dad9373246fa95d933762f8606f6f3b4490701f19556cd5e9a8f05e38af102b0a553e3cf5bf64f1ce123dc70a3f5102af8938a3b653264184d0470dad5ffa9b645d72726a7d233daf8a6869c75a66badc7198b5d4ef4dbcb06338af3121420976d8e69cf55d434838fe2a7904ccc1b919269d7e010296299c25dc0d94338e151542c6c4b16b1a38496ddc23211e16dbe2806820dc4bfceb7f0740bad86e7698f102b42f
+TAG: 0abcb03ff2ab6cd1e90e81b94db37fc7179ebb7b3f9bc470947c154909607349
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640f3d9dceddda858c6f5d1d1ab1a1f94bc8759e20c75884714fa20093116c53a996c5a50d415189b67f83e9fd062f99d2e68e6cc96e6fb682c9138af8606591acd93224d6aff912c4ff0421f6d623a42c18c35aa310b444688dbb46922a7682e8c1698907263df190015eb2ea7aaaae5de092ca5fd4214580385675df4242fa86d39e6d7de70474465d3b60a83f820a7f9b71822ae177c7c4527e8e4dd4db566b53de2a87d94787ebb0d0fe1a3575abd9235b5439fcd09bc73612b81ac266843191758d56f70d313dbf60ae7a801ad75394661e6b028b44682c49e0ecc1e3f7ffb
+TAG: 132ccf70edc0b143b1797352bdd613338d4d6ad45af520318fdd4f5106d8e079
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f3016406d1f4f51c99899257b58f104fcc17dbc7258e427ac49c3845498fcf006bbe583c4ea384a0ea73b0f25dd0a734c592838967b96c32b539c4bb58c495edc1e781b6d47a33a5e35fb90100269d17c49cc6c80467e39526a84afa6d9caafe3032ab1a03ae9f48155d655628a7abe4637d825b2be7abc6e851a1024763a4da9c5dc2d03a6a5acaec78cd12851cf436583e8c952e6acec1034503164c29611c94a97fc8e8c3815a19ce774427dc459536ea10c54a6c5cfbeec725fdf039461ccdfffa60c3ac4c5eea990971ae6e7a7ce7cd5c25d33777b14aaa012a07244dd6da64826
+TAG: 7bda96fc2af20f84da9f36dd1ef0859c988c23f8ba1604e4c34f95ce38139b03
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640a8c12f39059fa9659e1893baa7c0aec02053c4695580f36f2c736b37379ea5e7a9871bc8b994c99cb4021fcd6f4f9b2e7b786248f1d1b533386f9aae430ff21db8dc787e4eb8ff15b2fbaf430e716bb7e5d8fdd2573a576a4e0813cc38b1d8a2bedf9df82f81e4bcd61bbf54ad950ae09e55d7e1e1b8b4b65e3d4292d014e79c535f9fc3a8eb8fc06268676eaa5a4a0e93d77de753f4513662d2ceb10c5278527e8151aa3483432a2863acb8c2321a0081618ffffd423871c3f160ce190171d6b2c9f9f705c8c1bb60a38830139299cb746a2aae7720fe044e5a30f0d28ea92c
+TAG: fcc912baee508962a8d6adaa5dd6181af2605ca3d708bb11bc057e891d9e1181
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640907db7446ea70b885786aba4fd425bc46f1954dcaf461a740b6ca66236ff27bdd8a0f97443778d73f417ac611dcc5fc4513119e8054ab8b347cfb3f0c509884da9b85e03f99f9d8a76e70131ebba89eaed09eb3cc02372359317056c4f6d7c7d42ba00048ba9d46e0447a93108f76bbe663eaf48731d4f2a8fb7802c4044a1cb9bc29fe6a96555cdc4d0ab196c12712c38f3655aae800f5decb13a7cac28e4760af8b5d08e59e9f0856b161363861d644ca8c67432883602403ef2d212ca16a03ee40466620282dab87887c40fd10309911b6df9af95342396e080dbf9ef1790
+TAG: 4d7d1d6ff762de96b3d1078bcab88bc6b501d5648c7f680f41bd789b89b3d431
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c17c8e9bd0bead6e081d677803802e44822903f2d685aced0277f544f564bd59cdc11163f790a9ec0748bf078f77c6c99986133405a0febcaaa6ec042124646a63761e6937e7d7a08964bfda5533f54bbf892f4ba396a308e282a1e19f033bcb79159bd9456e053b18b2e6adda217d09c10a91d8fdc11e5141afc54bc16f9216129ec24d6965d4bb4ff5c96d2227ed875450abaa609a580b066241f2081e301adebbe4946dbf949b6d980166527bd9a29f555a0bbd41812e4584ed4398003e898c80a44c89ba61878908fab79df6d8f10
+TAG: 7fdcab9fffa8e3d0cee9c0232d0aef16c5405ae0d2159ed426b60db7c2fcf17d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c13f5e2422292b15a7a4b57e851a06b4b04d26a8202f215cf3aff9ebda41056d04116bba18d6fa7e4e79da683a8f2ffe421ba63369150959ec667e183e0436a0cd304858e23b79aaef120784699ce3f917128d1305c55e27f8de5c53227207ec1271c6fc79c58f3ed138ca386471c4e8543e5954dfc135106b150a1b418396b0addb16acbb39c9e77adccac74401420345b1ebff39ce34fffcc722a5854da86d3bcae940b58d175a8d74e52efe44f7e645ab6426c4e9f8c6664011b109038ebb4224909dd74718426ec08b4928c895def
+TAG: f359e4966eb1d636717084cd3ad636fd890224bafb67ce1af3e45e9e04de8ec0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c52077d43cf09ae82bf2de362c6c544bbab907c467125992de2a31b267edd0430f0b371cbde19151aed8f85c9e707ed7b21defab75ba9b3721e0b515e6c151d0cc7cf901d3a51903614884d4ced2e2469a59a12ea21db208bca1cb53ca1dc9d255a834f3ce95934ce90af03434e0eedbe735f4f06ef8d6184712c690ab667e025cbee4abc0da9cc44e9e70578ea9a417be4858612b0177337e9b5388648e0a069475291f9d9b6cb32081108cc40a037644dd2eb6c487941cc1118bbe5c495e23348d3adb6ccec8fdcb6ea9362b41104b8
+TAG: e6dec761cf72b9cbe7a962dd6fb2b472fb5d5901dffdaf9249d3ab289c15aed9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c9eaef1c9deb4fdb08cd10ae878e028f93ae774268eae8dbb370527c4f80ab4f794cb0885de1c24b24a6f7fe5e1a13d223d476d18adebe4c211d764c6241923bd151033e4cc2501e2f29f3a9054c58da41013c3801a4a60752f21bdee204129c5dedc71ab27776597ae9f3758beae7e5626428c605a5cab07d28ec2b0b8faed0bc25e99a1623975c6898094171722cb8f263a6f057ad6e3ad09d225edb0afa699e1aab4417d297779c7bf6837bdbb5f2defda9631920fbb7bdea090904d680beb634c7536a913e0ddd7b1a8bdf0ee0742
+TAG: fe24dd76915845ea1c48ce6ab6523f20c21bb0613c75e0b782c38e10e22e8482
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888cb5d4a83a84149a473327db179ef63fe4c66879a9d6c6cb1cf9962fa63aeaff7bc39dd66fc1a878af57ce8220781b541f19a0c53084c6cffecd09243881145bede2b1e01ffe62f3c12c1952bd4c4e7b3cd67f7f7f1f88f39221139f264269e68e4be92c704b84d7a9f67dffa873db489f12e53163c33dd62302084b6e3a8850f6ead7283a21ab5bddf0c376dfa6d0502558ea38217c5cfa515a01da57fd20088c22a2ccf8f37c992fb1ddb07e70d7aec7d7dd55bc573e312c8cdce6d401dbed2a144e8b8868b77cf471254a3eaff37d78
+TAG: f2c8a68db572448bda1c9137d75d2f4fe3c1f901facf65b07fe97bd84c979890
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888cf52e87eb637f4cb051f2b071017b8dddb49b4ef287957cf21dad7c6603df090fafaa6c74dfd4ea81d81f99803f7345818dd1f3384593db127be5fe87419b292624fa8ba76973252836d87d6f7fc66b845c7776977f5e40f933a52e2dafbc70ab6be9b5fecb6c203f4ed8513c5d2091c14098b1b5d0af9fed5638500390f7e51daf4a71531a46a8204150feb8c2e1071f874e514f6a21216d199fa4e33671fac7f71ba9dfb87c3eba862d52390a250518a905e7022b97f8d24fa3d31159f06f0c3bc3c1e60036e107a1e568d4731c15a8
+TAG: 289c6d398c455db8b7f3ff5e28b34c9b66f8f038f4f6ae53760cafbe05ef7d26
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c9625096f547beaa5097fd39fec32caf4897a2046a1ee00c963e71ef3cd694813806a2d5c5cfbea92bb7c663d11fa5c9cbd8edf8626c693e97097a50e1bfa2d4494c93d58d79c86c523212401be7294882dd6b55c247534d23074c497fd3f975bcd3e49d825dd1c16c133d79c75a7915c460686ec95d539b3af395ef48cbc590e362453c8af3974b3446a4492778868c7e3406797f072b556ba426396d4196c7ae9010c97f5dacd2d2a4222110ddf0d23acbd2c2d15700b52e3efd74c92daa489fe02ecf8d3f459270917af1004c1636a
+TAG: 8993a6e76a6d124a8b06f60a33a301cc3612ff1312a59624d3c84f758aa9c56d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c56748450d07f401077f32bc6b08c6586fde7fc1dcf2d1079dddb9e96be3763ff3dc1743dbf4ded18fcd58548e18cf9f160cdf5003e23c5e89a7dcd229b45bb2ab4c4d91c62f21b406ce54a852a7a186ab65ac8e9f41662980e1959076737cc9294a4d5a043919c2152199c603a6975ae1327cb5a055b48d65fb5b9c0bc0c35a36df5dd09ad8d594f8e6f34593cdbdb00786dcfd0f939b3cac9fdd518d50a180bcade5c0bf1c6c4dfcefb4f746fdcac1109aa531595b2ee2cd308a25e61d630d91788e90d05a05d6bbdfeafc4e91707d8
+TAG: 506a0b8a340ea45abb39da3ff236861e96187b9a920da90b2b010e5ab6f59ec8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c2467bc6dbbf17d94fded540ba6787e56e62b32d15d0c91d10b1cf710b2b7f050e7d510bab01cc8c2ab6315acfe1893cd76a02c6022eba6f1b3f791a0a1eb11b5bba3dfaf10ec0de40bbec53537d46cad0a11e95fa4223c7c00a46556fe222b0bef031406bfe3ec82855c12f5b197066927700d128b1ba82731d0186e405511a5ea0b7f7c8aec5e4d7ec5247d9f35f501c4b0f0f1c8a352818690209b0959a2243d984fca8bfa7f23a558c7cc08761d5e53cca96359b4e5e505b16b1fdcaa5dba99b4507efd845da283cc4990e296da00
+TAG: d7bdd59263ef6b2f224a941d1716de57574755c63eb2ea969ca6a7099b13111f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888cd75fa0422898c67bf865c374cf02830f131bee4c4f2a2f2d28ecc72cad6e4a33556c455e0a9fc80bdf704496936dc67c8f7857dadee31104583b8095db6c06664f8df62865d467cfaf92cbdb96f61efa279504ccc9a292922b6cede4a19da9b08eb3b384bf43fe18349ad1c084333d3d3da93aaeea51f559d0b7c1af19106bdec21a0ae19c4781fff2277fe1d0a65c5920ef3aeb6a3d4a818dbadd6a15014bc90ee5b89a3b01d6326a2e35efdb82abbc31de926084c7c866f028561ad4b89812f30b0c4c371abd530558b60ba72fb933
+TAG: be854481c3175f699a7be8693139e4ba1fb57c763ed0d09de6863da1a03a08d2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c40f9a854507abfcd23670675a34727527391a8e4a59e8823244c7e8c567a921727b34ea46c65e7518fc82b3770088a6764e70d6e40ac3eaa8e490d260e73e1c8e441ed1417cbe93595464bc34835ec5d64e9cfc44c421aa2bb2f25825a71d022ff522c9e9447e0687d96d7bf92df737ef76376fc03eb655817f751813ab1ce4d09cb0360f207dfc4215083c31ce9f1c78b3f3f47d6c30af104ff5ec03e7694c3f07305ecc0190637a2bd54a720f670c5bcc00deb63747f2dc98a0c96477b7afa644839fbdcb37418ffce01321d9651bf
+TAG: 5de51b7cd89bf1261b7507e70f32829b2ced637f19fef59ac45556c759c058b4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c2a53e772da4892aed36201b6277e6181314a349df9fe68b19431faa3e009274f3ca268ba00feb0a2b0fae6c0d2a83d9fb20ed3387bb3a64a0f0047ff61b04f797f528226b4afca07ceb344322f6c7090cbd5010e66befd390a893f0c110d9954651739910e7d109ba70e186cc1fdcec3bb34911adf9f2ac71530b9c1bdf3d2647931377eeecb4cc2ce07e2c3dccdec4850361608448f4f9db6669e49feb903663e6ff99667e5a47a3f9c1658f2be6755431175dccc7c07f599a7fb8e94ea4b6b6dc3f2e7171289ee13bee0bbe2958e86
+TAG: abd5b7fc6d910e6ebfdbcf7dfe42d29a62318fe7bc461395c97c34080c04003f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888ce9937dd2aeb4207128a076bc07729b3312a789d9a10120daa18643e05632ca9c6a50b40e00580221cc8e0623cf7de420b23d3dd2c0ef5e8bcda6ca2eb194cbb201a19705804fb5425926ca73e0d4403cb7d09bbb60dc3c5b89cd74c202842237644750b1f6b541d68a7ef425ae766680987210ac2d8544e673222e8e0d42017e6a0ec26e4ef24e5ac0f173c87ea639ae33b5a457b6824cdbb804f8ad814fc1b07b0562950039700f03c5697ec2eee7b78185202a64003c351ab3fce4773f8e5e738da3da7d8b2eb57f0518cb6c03e39a
+TAG: c3d47d32882954d24072f929825b7197e5f7e66375827952cd84a5fbf0466dfb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c99f29ff8ca6dedbda4dbf0938edcd94a62694eba9716a01e28af2e5485cadb61318ea68d67905e915fcacfe4220b6c83383b583932dbe41fb7528aa2134039a10a7a440d258de753a1d04e59ec90214c1c08fa2cfa1e9e7078bb8e0b3f217abf17431daf1ce04c346d3d4973ad88decb3523272601bece8c2a3d38c835bdeb74d38db1bda40c1ed4c4804786bd68590b8aa34b89b47022dfe6793a9747af51e77328236dc81e80f004bb2a5bf216c2e4c1d7a4e9c1b0022274aaadc498a5da811497fb1972efebfe7b1f744be2bf76f5
+TAG: 2fe58128d055e34a2b0ec17750d75a5ad28e697ecab8181559a0945b63789f78
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888cec6c4c0f48623200e407713ce9bd04218d9b4e722f839784c7b6f6f40fe0ce109b8d1adefb67cafe69f93ad95030187d485a52fd5fc2d8af55304ac84d4d239c5b7100ff28e91ac360eb6c263283e84194a67a848a29d1925df36023400f811426571aa1eaa9f0308c2b84964c05de33606c0a392522d233473fd133bdce79f93a11805a4616fca0e2bac00e33fdf972a162ac37772e7ccdc7850141ac93d38e267fa65da726daa43980f5d45eb580700c09edf0c3d14021240cd29e7f97960a83e33a9a97381b872b36c3442e9fc738
+TAG: 0c123e0d9f82b03fbb615b09249507eb893a3bf76000155752b3fd80cc0b8557
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888cf7aa0e1c542553ba82e0c9328199e7b87b9277a4659792551d7c73fa7b8702144db7fca62c5d273c93fd0f565ded730d13749c38d9ea01da85e67fa19867f4163b7613b3869ef5799652347a2710532f5074c1c9b74e1b04f17dedf7f4fb6b54f3e8a102b3bbcc7158db9c38cc409542ad0daab53561a880c2690c4506a9889b2189b31778f6b0060b90e9d75c53b90ae70e82afe0c178b1e7bc168f20e9d145112d597959eb42b57f62a4f73db63db9f769b0b277c1fad3c12ce12eee4ebedc0df4947bcc575daa66a0c0c8470a378e
+TAG: 0e689b70ac7a6837d62309f2dedc2dbbd79ecd3def530e1fae94e0e3e61bb8f9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c30872900874b5b5dd354c35d397009b407a27f952c0c5a127bcc60eed85d3a7f1a1a721d210bf6d1a72af17536f149e7dbd6e9cdc03298956189d03322c6042a4db75d25674c27d1d73c7ec85ec6b675c4035b90048edf7d5eb4123cfa89464c2e70b3573db891950f401db4e444b5c31186d166f62ad8baf9e299cca3badeea5b51a989afdc0d2301272af7c4980e828764d55814272dc9fcb60749fd102831576887a467e01c7ba349c8a9cb560fe563df62f8da6e676cde5f8a8d9be4675b516665e
+TAG: e2523c65e542f6a5de50fa7f908e7279f10939e00c564ed950a8c1c5706e3b40
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c30872904d1c98afb96986197fa3064505a1baae6b224db18fdde596da46738ff9455c8d352f9242a301ffb144e99ce726280fa846f5a8817cc17acb1695db769755071d66f2d84bcde89df76c092b38ccba9f30b2afdc0cad8e7754c3c45723bd0e6b67d6929781542017cb8ec90cef1fbdc79900467ea5dfdbe464f25abe8ea1136596af552b95dc34681189d419f8144a355411166124e6b4d03b17bd00b1b64f03133d96a92f6cbd0d725662e3f4fbeb4e85ab60cafd6a4259d107dc034b47d2394a
+TAG: 6a036a031781aaaac7a7ca72fd6ce4b1872dbbb7dd61dee284ff4427127da874
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729045b1703038e9656016123c2b8b8f3aa8056082e7d82717ccd2d7f1d8e67a9057dc8bd0ae65ef920bad82747666d03387ba2d4d08ac978076640e4f1177785dc422550b0ad3e8f06e2270c2055a0ba795cb76387ac95652cffa50765fbbc0f7b9c1c0923c072c718ee491dfe9f33339e17d9bfd7ef86af4d6db538d3bb12fa51849ae5e3498d5242f72c83c682fd19213458868fdaf59ec92fd645ebb9f2ede5683be0648e41cb674bd5c286f25344e486628d3a6e64171b74bff0dcadf9de940
+TAG: 13fca7ab6bee2e69bbd7af28a8e78bc098c55472b7aa153212a0ddcb0356266a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c30872902d2bef2b8f15769c742d968d19a70e30b4a02ca30ee27b251292275616bc03c17e96896d938cd1dca1af3c707b2463a3272ae3e0cab0f5d67f6729497a6c3c672171e02cc97024ecbb4904cc85481204422a130a8fb8d297916e3af31fa4f432e2489a2d42e3871d44a0a0cb88763ddffc79038adae1ad6b27480225ca404e70878b912e3514ded5287715b7ff2d3d1c95070da734c4399c016be12a6e17c5083b45dc8db8d24ff37e6a97b551b670c004623ec1f9dff039593f1141b8162e84
+TAG: 736a2e797c0f07cbdce803f315006bec141afddba61abfc9ae8c6e687ba0b073
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729082b372b7a1d58c58ddafa032c9fd9aae108ab7b68bf05e5ffdc29f6162ee9d6411ad1bb624dc222942c2b655555ef70e6367d61578ef977647b1a1847317ab135398da71e4e20f97d18aa23663e296a00182ef4c1bc244e73bb0f3c2ef24eace92ca5dafbdc744ddd7f558eeda6ad2b643030ada14aca8ceed198b5720380085c9c4b9d7176214a1014a66ec7a591bf3b382a0d080b17868abe1d25a360bd27a166f9f1f088ddfba0b9b0789295d24a5d29c2c8236837d51b16719881aaaa5bc
+TAG: f0178766ada39989ebb891f645b62206576ff2452212dd83deec7690835db53c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c3087290c8c08f1413d7f9b93bbdeb4367195991794a55ef95c88ae761852dc403fb82c8c80f92482ea85db2153047862fc887b9c709f263b9bc52358221c669e70653c03c7e9e8ea06dd1445f4c98636f983f48d7797dbff895dd3f4bee2ca0b6f072eca94f0bbc115869c7bd8f8f444b8b55baf66a33836c32b86d505f0f9b91ca995104ef4a7f4ad7a89cd47f42dfc398ce261a4b831f14d83cadc71b7e7eb4a8ee44aebdcb2e2c66d44bf7989bc1cb6ebc11516c7cc53f57f5428e5b78a0df6978ca
+TAG: a8f7ae4a8ad45f48786db9b24818dc90d652591deae7f85d6f6ab62f2f71ea2e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c3087290e6acc286d79abd7b8ba7ac4bacf7584ca5108e727f4981dd24957236f60b5993db274dc8878ea352b5c677f1234a09ae4b6091d3bed2c9fa2d5edaf65d43c8d58ebccb82b7ee57911f174416cf5793d4525524d103ce3b0ebc39b872bc338b0f722751cd2e53e65c6ed5ce1a2079d4214736f0fd1e31d90263919ffb98645ec9091bdd2cbcd3e3a5210a68de743068cd69375c2a917a44ea994a31b28454cc7258aaa59ad1f4e52b35a8b6edadaf9988c1adcfc0af8360ddd2b58b34ed016ba5
+TAG: c60cddb507f94dc3a2d352fcf7132559f952f7bb4c05d01cefb65567c80fa519
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c3087290d9304d675a3d3ab6822f0160797114346a858af9c214a32437ebe1acf05cf81d9b3bdb4935a24bc7eab8d4919a41c16f41d2737080fdcf7efc1451d1143ca8830210ac7a9a5d5d17bb73bfb3fb3d4c7274393871eb34fe7ee075f7626c108d9911bddb883ef8dac26c35d2a95210ccff836f95d182b4a2bf925a48bc1726f2c42b4e96a7759c1ef6ff2970f4f4c58f167ddecb756a20ffd2793a2422cc05d71aac5a128d81d47d8260d20b79fa46dd369d97703893099169879f19c9096a972a
+TAG: 3ca2ec808c50b195d26a11b64a19644424d6a56e8a29655ec156470cbf17a00a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c3087290ce649fb534614380b9cbbb752992db08fd4ed9b2bc4400ae791182abad817f799c53efce32c11ce4c21f0e0654df268ef37a098ddb06babbc7058e29688ad11fda8d0cacb0a77de1e6ba12e2c41e4f9541b91f1b222de5b5490c58b93807cdcb38183a5618897ade95a09cb6ea2dbe7316866fa8e7e155caca023823e3b78e63d925da8f1a28f1fce62a2d52fadc513bb7206ed696250b98df3e4a11935ccf481a5267e56a55d9b9e72b4f6bc1a406a4252bc8cd6e2eb1921caa6edf35fd06fc
+TAG: 5d25cb68d2037d03576b0e384dcfff6b54244ab247e9540d25014002cb012883
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729042b555ad678bcbf1761078d5431adac898e4f4bfdaf473bcec6e8aaaea1b1a7f3df52acc057e2ab4840e5aa8f855837bd9c3d04c8e301da95c3c170c13820c360aec205338730e2899c2276b6791f456028569536817cc77a07fd2555d0cb0ef3f4f6f1dda8d6fc69608545a946ca64d099cbf0b936044307291b67529c8c2fbb359429ed252fbd7dceb9f553dbc170410b45d71356e71777642ec5f67be61e63447653b805a015a1e994904a52458ff350d918c4279d8fbbe85a2bee6574da9
+TAG: 97f7f55f024619fd29cd9db035b2ce2070b6e614ddd3ace4447423e2053b5dd8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c30872908f438bd2e19a47247f6a035d79149cbf81807e33fb8b20c5464522af09f88f8ce2a6517588df45dac550d893467e781b2a849b74805063ff3b69772c40739648bbcde64d8bc6fdc4690edbe85b6df288055fa4d197460f6c82e8319555c85f35f986d365b37324455523bdb926f99bac8ecc145134ee683c28e480e6ada96c1653bfa0707fd70fc918c00b8794c331e958f7428beb97ab4cdd3c1d8ea40fb2c05e1ae0abee4a819e1865dee6a3832d41b3ccc8cf3183a9ac18debc1673d35cfe
+TAG: fbf2876ef60b9528f1b825139f155fbdd695f2e46a20018057ee9ac1f5f53cde
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c3087290eb4722743fd4be7f0d297c5d93dff9877e1de546844e8efcf51d0f0d77845b9e2ad1f37f8f045608668eaecec55bd3042858e276eb880c97692e8cf955e9fdd261301e8f917cf64a401f0025482c940a9ab0ef2442ed29fe6f764eda25e5316ec42056cba056d504d2e7277a433b2dd51ba4f6d20296d28f8bcc87a405b68cbccc4d5afe26a8f7d9a12bef62f79f44b1ec0492d62009d5cea0216c1612f063503b516015ad6da38e873d2b62cb915a620c0ffe8d9db063059218797b42720424
+TAG: 9edb4632dcefbc3e6f986fcaa5d3d4972b4e649110ffaa493a95e01c376ee04e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c30872904dc811f6d33a481528dffef98f1ba51bd5c65f86dee732904940afad7618b48dc0598fa1c719a3f60581d357dcf192ae2109321060fca7d06e57e8f74474b9c2ffbbca607d56538bd57bb76ef3926dd0231468d3fb4da334d18084ecea8adb68ccba67accef7130a3c0c74752f0192323aae40f175ae15d202ceb14128bd6cbd7264b83c7d98d4cceaff3c1eebaf1f9e0ce4d2e5037b16b4d74465c944ffd9ac4105fdf48db0031222d3c1f40cd3908171e0f53afe5f139465e655b01a4481fd
+TAG: c1daba17eaea9e215d9e4505c571eec675fe6a27a5aa7fba125769adf2eb69ab
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c3087290f994324221598f0cc7888f2ad3a36fb169bc04e0e6bd190be178f4bcadc18af967c9b58a459abd554429d1ec0e99db4605325d9e979e05ce95dd498605d7dc29b2677743f349dd86745cb53c75bf8b39a673063f237ea8b4df9d07c7b47aaefbe6de5a07b54f3d82bcb8422cfd82e980faec009051649f5992be05ed8be18316f8307fd5358912913fdaed3eb941d161a2976df2df566d73a57bb507720bd420687ecd64879d6fa6142c4634b1141784449cae3273965dfda0eb57374859aaba
+TAG: 10d07877d7f844ec2edebfea300e8b305448c26f58739b549b77e98c47dcce08
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729033a38a5f4f163e7d36b5a56f790cd2d14b53bbfa63d2a6821a4132550edca286587b66611450e4dc9e33a8720c229b4d44d4a2083783592e3b883918588e82a381a154b357263a271427f549c952a91979185aa22498381ea136855227933e66ce126dbfef042bf5f63cbf281d3d3da3a91442d25092a1164a2019322340fd75fb92a6c543097180ef0a17e442fed846193a1f602ce35f7409a128b89759603d96728837d2137de410127d69443c93dac0bb7a2e6edca382abd5d40b54fd39ce
+TAG: a8f20e034f51379620e8d9090df9f6a8af24819229c2a353620f138defdbd986
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c3087290ab864042c815e16c86b27104a5dd5711ce3b6e8e51635e812728c03e8ec76837eaf92e98d212146a59298fd58276498395a990961fa3a04636ee3a65c88f683b58e78b0588abc065251d667210c38a13f1f58529aae8e03fd3a8736439eb6984cfdfa8d51f51dd39ee86f9a3f58ae824d72411d00a95cccfbf26a274007ac9c369edcecd2a80dd2b5070b6e6b3367f69662bc8670f82556233ca21d2e449b5392c337d98c9455b79103a9cea4f92394621a9397a4281cf805982dbdfb97c86e7
+TAG: fd102506621bc843f10fc8218274024c7d19a0eea4b6f7040a855c8fbbf2da4a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711c96e1830adedcb5fdf4d02ce6d91869584bdaed4f1763767cbe90eb74049b365cfeefe8f8c20375ab9cdfc959fb167f7820c5786a57e3d50dd15dae31c5fc7e31ead2e01e43747018671bb2af1799b7bb98bce679c81c91e733e3203cbf2c58f2eb0252e08d9ed2ff0c3fff9dcebcc9cd9b2cf50e9a8007d4b63d04f1fc29143c42345511dbad3bc37d49d6559eaa76e94049ef59c8f038e3a7139dc6b72d3041a7da7ddeb675ab128b84d5cc58969ee4
+TAG: d7a7c0d49c8c927a62aa6eeca3485ace465d1a1fbffc3baee3d011f15ddfdeb4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711c0f02aec89fb5ed24e635656232eb27f239660cdb2150f1ba5d09f5b6867d0b394bc5d316d4f2e639702f21ccaab6cda6ced392b57280b9ec786da4093607f81654dd822182943433637aff8356e18e75922cee19056efeeb0e09df8e59f1afa9c2288e7c07a796eb0c7f64443198c9020ae166d490acc81d7c1f71e95871aeb7ab4434e241fdfa3acae8e6ec4e796a4ed3aabd1b99a21f5dc4ce9777ec3d40f4235546c148dd7405ff2a66d11c483d44
+TAG: ee98fcb1b58051185f2c2c8af2b8e1922e2a4c9e623e0c478af768b5f68341ae
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711cd9a7e5706d91e965b7f554938e180adcf9c9503c47ffd16aa3198e8f3c8812697e8879e2a1196472e784725212265c8524dd34a4bdfbd9f59f30e4a956f166fa4647613191e5366ad0b5fe58e0376e02d4a67169ede2fc07941056a9f14cadd51850cd92b778b4ea8eaaa63accec92662a2fbe63a6d474fc3bd3928e6e27fa25c46894ba9c077144b799cd2150b7c2ca75b49b1520a5eb7382eb8f7fa730a9b47cc474bc9f0799c681e5e3b97c9f56a9
+TAG: 143e4bf2db912005f2b011a0b83d402dfe8d581a29d9d7c156684518d24a10c4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711cded4112e528622fd7d9e154d691707a162a2a06cee6b02b67bb7ea560b28fc7ed8ad15a2bc5c94561961dba2e80c4662c8143c1534369a86051f0ffc02d55b642bf40e790d7d9e96008bb42d7c71cccc7ef3f6a8ce77cac2123fc3d64fbd4bf2649e3abe1cb8d7b1691a1fc5cee27e1379c91a9829fae8488738e01c2841b6b6b0f5ec20a99fb218f7c4858a37c304ed4423935d77c4f78d8cde871f5e16d380202942164691fd1a54a363dc6693ad9b
+TAG: 0057d1ed5f28560cbc98407299ab68653bb46a031e72b6035f522f8b58463818
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711c39fd9e50c786185873a6201139b3495f2958985f39c7fb956c4b3aeb6aae864c6d33090132ddef3f32cafc51710f807a08e941b28f044ba08bf26da2db8a9ff713fd9061c9679476776e074f6c19af27c6a654f365096efed7afe721e27848135e82b7e738ade19beaad9a43491fa2be5014c25b0f066d56defd2c85f8e57beb962d8ad213060e89c4cdd6979abe7f5f4fc09b0f913263560e3a9efc9c08d2b77be694529ce01cd581eda406c51f00a3
+TAG: 55932f3ba76aa262541e7c916380a780f1d2007d9fc4be1f1ed604d83be2a676
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711c53e5ae6dc7d9ddcfaed5698666cdf4f4cd76888f590bff5d442e73672ed9b8f9cde8b3d39c98a7e99a69772629626481cdf51137e3039b32f45728a39110da8944db892d4bf990300aab76e4cb057d4c89356cb8c9d5f85908508468f151e4944d9b0b80ac108be351bbdf91729508b560dbdc080251b59bd95bfece93116469b93383696f70327f569ae9556bb7e3cf872bf38aa461531133953c3cfa61516aa56bda38f156bf091b21f624636f5f14
+TAG: 7ccf366387deea4f4aad5ee8841c2fd897066c8e44cd51c5c73fef682f97e132
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711c0090609c9950c6bcf6db1e14d51bf7d24df8d42d002d92b28c571dfff4471c15d9e14142cec4c35c489c6b5d478c9ad55f4f3b2a1d294481417a7de040ea948152655802d1862d8319c53fa6f60f155063e1f084e1dd830878646e978835a681442282b0575a3fc3527c4df62483669986024f89cefe180e6362721446bc41e4706ff765fd34cfbdab969746ec798a006a66d451cc610129278de97bd977001c10b2c65213b5a2581d150838d6992c9d
+TAG: c2d12dc19c5dc56345dd7cbf9e8b75e8b2c95676e68767245471e476c2d7588c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711c6e727c11774efc507408500ead490f0328da89bbbe9f3d14db31c7a97cb304942fb00e507871158e52dfd8089fad83db93a096dcc871b8651425d7e4e7e3e4d9858da52e4cc60e9be457b7acffd29d7a502d1a49bdd9d9edbf36fd31a7f7e95498df5b4ab8e1d7f047fc39b2ecd0a3b94e50b5a934d0c14ec772599d2b8eea6ec66e060412f9af8f43b41c2b8c74e031f53c295703113b70bae9e7e45d2c5307e336bd34c568f74273b104398acf4abf
+TAG: 1e6acd09001d8c69d7f29ec9cac28815c3faf41ffde2361c4d6d1e00e095b3ee
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711c1d3693312b2dda889e373adc08830a405775b351c6680249f259c7dcf1340fad905ec8a6708dcda839ae09daee66a1d84618bd11d8f0c30947b894f60efa8ee46b303c66f5fb347c11068dc2857cadf6403d3e0d39876da06d15c6875e2ff6131f4468946ae6126c93150a0706203ecf71e5a0db6fc1ac406aecb531e9c560e9f7e648bbd280289ccb545ef2b2ebeb9487bddd5d8050f17e02cdd92e2c846cd00ac17543274ecf4ad7a3ba2e92e150f8
+TAG: 7f7243c02eb87064ab5dc607f02e997aabc74b56416be331edd8c7fd949ccb4c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711c1914e87c2e1d67bb9f768bae747ecf6ad533a490c456c1d1f7ff99ce755ae072a7268b802d805d1635072e219f57be6d00ba64d5ee96d2ebf71cc4bf6d63ab173ab61efbf560d4ddec515775c30ec929d8c08a87696dfbe992942b7b5fd883ae17ac73c54b09bee9fc3a76d905ce21456bdb83a3d145e26ca6900ce26fb6a297e5c676d8c701fb99b3885a6fd7f563115de6b07ecab59b424e268a18abe6f9d79990461d245e1360763338e5787f544c
+TAG: 6a7d878f7d97a7d1e41c899189523aa6b70177f47acc31756edd68975e136bb5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711cc6e198076d04e4ae982f8bbebe910f0358301dcbd21b70c8106080ff2a424a954c393a36ec75fdb3a78e7d21d1bfb38dfc27bbebb57316b012c4c3377e3228502d33f6f87868bdce44e3816715614da79f5a31bb74b45714e74dba7116abd6ed0e222ec9d9e885d4949a10595f98046d6a6f6036d7c3a46a751a7063b3d934b6712121fbadb3fe9c43976964786795f5289c57917d69ddb2db58ec6d2971df07a07ca73ce9a0adf92286db9543cf1638
+TAG: d52d9bc82fccf52b6b464e1b0250f1c391e5ca736157ea5b29dcce9294e20ed9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711c5ab4b9c3debbacfe67193222b246f93522b5474f47cb34efe82016b9a8af21bc3d2289dba9cba724f951d7fb466e0d8bd8ee3c64139a0aea560880f334c0eee5380338170357361a989ca8806079219763091b27f962d08f3bc2e288890615f825f04592197bf7bc972c7c47ec2c196a01847aac063594a1dc9d4e1ef155f1bcee89afa5a341b07375d25010d30f7815170e5a50a514bf0aae7d8c1bffab0027ea60d1b6bbeff4edbe0b3592ac2fd715
+TAG: ae70f306ab2ba7942bfb70cafdd61badc8b680e03fb0b56c5f4e38ed8dfd0ce9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711c2ac3921ab2dbb95c73f83b41cd84c220e4c86750577c808bd4edd37c29c67b654189c583ac3d2287764af1a3d188a873457930e426f1e5fc9308cd69badc349be1c2cf516983eb489d85f45b9f1a7c638f0ed9d6f9ceddbea1aead6a7047877e328bf98ff2915577815787be979f485692e48868870f7fb6b7a2ffe16f5f977b1350f346887077129e8ee1e12f3ec952a918ef55a73c5ce633c4f27b3015b30964007857766ab0760ec92d4008b094e6
+TAG: ab39bd0f333b2946fbb4b0b5bd2d41bc245b67c7188df02a39bfc11e8bee3572
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711c2af7a03b3f4d242bfef6974aa6b45fd97236ec25ee49494ab695021e48b65f5207070d637d690b488c8858f565cb40f97e3f677646177ef0a0f388069f6071d387bd3adcace5fda05ddc7641976089d402ed2fd06d59f2fb56a00e1578cee6f419ac81e2bf6c6665d6ca5b7fa869019df51c7ce3cbcef06e8c3a857fbb9b76e4797dac57008e012d773731e6914e83c5b272ac691215320fe8c250112164307d735dee0d313aafde2adf67f4129df838
+TAG: 99aecb5a6a181207505c6f89d8849b81567d4986f6ca0566b9424435eb8e56df
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711c5531cb52dd18d8151317038c552b8a925e83f05510c880c2b8dac9dfd891728205c9776f1e36b33e7ed33b0e7ab086811b3b3b7aea7db9dfbac1c1403eb5b076dd2e76a1fa8502adb79365607f23fb1814e926e3ba43123d43c6d00ffc0ec5aac0c469909d0830a573336032b537ed11101c43e405c28f3ba4be4d7c65de248b5f77fd49090ab550428616716037378f4217f6ab27d6f154cad883a4d3c0f3088ddd82f87565abda99850552b2f12d46
+TAG: afdf4e46a34e324397f3f4b35258b7757aba38fc618470e3ab54d4610e2a76c4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711c4d7782a78ec8b21d0539ede513a98109ae10180ce1e88e86b1397a1b368a673d4ea5bc6ca0167c9c6af10bc1aa3cd9a9ffd239ada79abd5f4f3e4cfd722c9b8076862c62a0098a5e6a6d56ceaed793dfa1a1beb2f3a19d2e5f841914a818d2b1dd879436482e4e4b5af52cac975dc75ea52ce7ff66d5fafb6dc2a68e2ceb16e9cbd2fbbd74a21889796fdb824d3f0914707039cc13f12fad3f826818de6291c17f6ab79d081cd22fd00d84ba49a829fe
+TAG: dc6a2598483d91fc3a2f93d40e86e790607efe2fee3bf8a1fab321f880e527ad
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08095c075a4494cc212ab186bed00b6f9c953416b86c72d23799fcf394dd62b236c2096223b8625e3cf95f6be049ca0caa0845c76c7306106a95c67d0e6a8748e99a11c523ebeeaddaf3d888b7a19e3f7056498bc638f2be964b5c8ef1e00bebf013a4ba47e36bd29ac4f863d1f6dbf2d61773498d27a07c3c2728106b33cdb5f89a04861b8cf06c5584763b170c9fe08c40fd89ce00e738238b7c69a315c6ddf2
+TAG: 43bf3b7be0751b04f38bf9b914b1010f5fa8d562ca220d38b5c61f66db254425
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca088e4fa5320f9370bc40f446e39f39531895ea3a6ba2fcb0cc0f15962a2e31e0a90b13abd94f332d2a4f9e6bce88b499c2a89b540aefb9d403b75d608086de02f9c2e6a63bef2cce8f85f7584f5b5b2fa399ba8f3a81ac7c6d16f92f921fce5175f305aa0a389dea902d42b24781356b9cc74a9c6e0b5f3e43174e34f69497d20ae012216dc2e4082a5d40b9c1022ce6b52e9894f38a9821fef0953dd894bd37a8
+TAG: a763b251b51339aa4175b0f4da94564874c769fe4daf03b835870b8d9cad0977
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca087f08853ffa8bc00302812048fe7c0813156e3205ec5edbb0c6508066d154054de54baeb869d113b8c82908993aa11b3649d96752ee2bdcb51d78f1422748f2d14c0ff0d238da0e262e4cbd0bbab0738cc8dfbaa50d8fff317133bfc9981be594d0451dfb51379b2d260f07c544212dc4cf015641203e6a5ac6d263c82151a0374f9aeb72730cdfba91890e1f7b65ba88e8f244f27a9b4793c43be8c67096ba80
+TAG: b74bb498cf83235a4a34cb1030e1f5a745148e9bf07e9a6a1fe7a594654e1a32
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08a236846901d91ebfa07df532ac68fb8fa998b92ecf31004759cdb2a16fabe8e5c12d85589323c01d9f218361ce84841e5bbfa61cc9cb7557f8744a546530e4739bfdaba3201d1e81d0d780be189dc47d26719d000463865a2dd4706e1fb3700d2e9c478d1dd505c9ed1d8934223e3e213bd6c2a9710943e711b0d14d9019b3150478635688ea8cd5343a621619bb67132b1d0441c2030a4a27f8601b3f3dc91d
+TAG: fb157c9e131887c592565edd2a15992ac0d5f4ad174145387730b805485f0df2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca083f7fa4cce07411682ee859e7501e7976c13c2d0c5cb729ab03d160d097cf76705c7d54e38df1e148c73dada846b61d479aa03dd6ab24459e95af65ca2a9694a9c6e9df892e0d6053fa6e766a71c0c1531cf05d73758d5e503cb4f259ea9f94133006bb7efb27f01a8f82c9bd5985c888350c5270e139c02c8c1e50628869c28af5525f9e44115c6439af307a4140252a9f5ece3a5de9f729a3394a9ef40d74fd
+TAG: d19f60253cae5b9922fdc3f780660f9b1f2177506f2edb29c030724bdb6c79f7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08acb089b41746b626a257a240a0bb7f895d512b118762108434552f6c2936178325bf3ea42d8dab7188ec85d0ff8d010c8f99968edcc5e65a072c58655eceb05e17f9da10dd7a30ac0e539ff550ca793097edd517266620faa582c7a82d3c78005bc7722f9b1a5bd070a9390f223bc390b40e66744e15c63ec586733d90182e22372fb0c2bda8e6a34833f3af3cd8b57d8fe2dc44c8e74264a5107bfae08af6c8
+TAG: b75c4ee61a6e2b83b757a944c0a7922ee06b9000ee4a922160af04e00fb287e4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08abf6458ebe0ac74af4e8d6f8eb050f69284eb9282141848481fb0ea0870eb5ac005e13e05e1a77263c0f9a6689da3268e3f45285e4e8dc5c487906d59c51412ceb6da4e2bdbdd8f599f99eb6dcd176f94b4313d2bc8312c387b9d98efdaf900ec027fb48caaaa8bf412c589b90718745a59e29e7c8f941d42d88689b7bdcc169c1cfe3ebad64112303b89d1af7b633210c6349608d56c3ce5f0c758ff5cff363
+TAG: ea2f3e0dadc6f168c0aaba4a6e50d2aaf022caed7ec99a2adbf8427e14d24b17
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08c47834ea4fa24e2db99d3a68500f350429365a3b3d24b9887e5eb7d67f436c497f50a2c02deb775d2027f5654c5a52739d0b5fcb2d6e2373e0754183c6fc11317e0b54945c8d4ff8ded2d49f2c3596f07b4a089a1513c4183a680a6f39fd39362d5a4970f34455f7fd1d9e343578e7b13cd82478b125a79f65bd34f023b12dc982adfca22d319816d266ed1a041158a86591670d4b109dad85d55ddf60b09c84
+TAG: eddf166f03a9fc7de83f6d44dd952fcc7a85005d421f53ee8a0ee6eb663a386f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca0860db1591e0df4e25ee213346891d8ba4303e54db09b50ce48c855cf85da60c7cf4a21d56b1794bb3f055ccf6179996961c975c0fac3c96ba0509a5dbfe7262c01f7ad6608323b32ad069267aba2db0855dd71b3be731dc8500c4bf603d4c594de7ad19f98b21b3d1a25b7186c5b24886c8db5c883b69b3ace67a5e3a4af88c8d33c799920b37c6fee7f9e1b446061cace6f7a5450645b00404c5f2b0ec6d95cc
+TAG: e895bbb2db349c4fb0578966500f5ad4d294fcdfc5f219c30b09345b8d7fdb66
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca080a0ef044ed6167d3b510580704ece52cbff6d403c6f6ed1efa31ae691b2dffc908411af520bd45b669d79102e934bca58ec79b7f1b106044ebf7d74187ff3c96c26b9cfc4e6498dc0c9f9a180c5e7adb0c4594f842b6e229336d7195f70bdc7330b31adcc04a19c08eb228d6891b4dd9e5b9b48a9ed63fc655dcd6804eb6bab98919350a1d1917226ba9b0c17bb4fc21927eb56c408dfba8bbb72752017afb37
+TAG: 8f5c4987aba112ce087815026a656e5ebc9e754fc771fe9b55c7ddc414d630aa
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca084bcb548a52c61c8fc8f5f730ceae01f73d2ffb3ee20b68981e0598dafd6cf42492da3b3b360b6d8900fc798015769dba0ddd07c4bfd0c5a05cf66d9594d4aeb751f82360ba8409f981aade80106224e5aecff3e71deee3af8874154eabd835ba3d61f2ba5bdee404edfd566b432d9d9eaf3d9303d25cac7eeeca054f2050d22dc9d9fa7deb7552d38b64d239c05424b13f96b21c41d5ea5a858dd1d8c88620aa
+TAG: b4638c838799923cc5624aea4c77f8b0cbc317fa4617ed89d23fa87a18b71cd7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08005df167544717684267d804266045a92a6067181f758c68373ddb123584907fbceecf6717355f7b76a135303015d3b127c53fd1533d1b6e1222dcae33d43b3326a9f06942e1c671463d4c0ed53dab89030a06b1e4cbc4eae99eaf26d540553c1f4a3ffad5e4c56585917ee12f3a80749f6cf75646e78fcee50a4a4ad07660705a418afa316ba710da8fa91b2a086b467ae4e554fcb968232b8305fbf45fb4aa
+TAG: a02a98ead388a57ae705fbe8992a3a0bd81033f84a35bc114f5ca7464d984314
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08268555e213a88d78deb5208405d075f432e4d9d2c1533b5e8d54ccb29b6b7c78c2a1e8efdc8d26215bb0f267366d8fb4079f14fa56e57aa1ff1ebf93d7f6605d27a858787e1696b376525c6d77868629caab0aa26a3d3494471fc4b084e1d8a7b096dfbfbd5441b5ec8d848de3c5bfa2e2a9ff23584e62bc0b44534e64e345607e6001a38a3ea7bcc1698d5538a17f8ad8b947762738e099621064aeb1a9c248
+TAG: 85ea3eeeedd17b5cde359fa5f9eaeea6bfdc082560dcb2d23d2455a889721742
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca086af0a5ddd3f1249cc9146dff6c4501f641e4d350a2be80577a7cc8b7736f0f08999580d80fd9173f3b24e340fe3d0c97254ee0ac76cb05b264b28935c0fe548ca20d8ca0111561b506e0b103ccb4fcd37738da0ce0547e5bb46bb76e323634e3be86bd537470ccbcb1461d88a1bd501733c020de2ad6f38a7b2c3550068019d2104f28480eb812d72d945e12e7b43637c8e082ffd5685e8cc108540c682e5cda
+TAG: 44c08096ae1f14db409e35600109ba71f573979d1a7e8e05c1be29ff988af204
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca083cfae16d58455818d126198fcec1c4492718c4abe6cd3d493e30e91932173ff601e10ca6bc476600aa708cbe908080340c29cbe9b9f6801407b1c3d410e268b28a730493f2a369ec65eaa1833787eebd391064e28ad7371f8998d9954b7a346603aa2226ffe2659525c2b7ed7123028cfb188ce7921997275f3d10812a56de4f046cbe34854ff03657278f5788864ab6da183acb2be8b55454dc343dd5ff5674
+TAG: 3c1ea1f629d2f70c104e1daf4c8e7cf48c33699dbbf84c297011f72a3e36c9ff
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca0839f62cde725b8124d8690880141ca6bec51e3684f5431b91d1922fcb7b60a2f3066b3fe0293b9949c7eff0de0cb55aecf0cc20f6e5d637ac10ab4348871c564bb3b400ed07f521cfc770c9eb06d905af303aabd7990a50a412c0f47c87899b5da94d27f40663d00d1e4f6abb5435d570a54acba8ac188eed3971ad4ce771cdb2bacd766c61ef76e919078ba387005e897823f0e655a96dd3a4fa2e2ff8d9732b
+TAG: 6b3d1a62898e0e4a0f9371c156ef813df3db52066d126cc941ce4eb076143cd3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed97c505d0a17b5e9ecfd690c3ef3490c85e278eca3324d166d4cdc488e918db093ae0af402ec4e3f8fba07544ff0f428bed5a8f0fd313f4182143ac371475a21b24c3e81563da71d1da599bdc4df4f0e1363aa70a07ea5cc4e53e5ab9d188e0ef289a8630e44da811b5bcd308de9187eba841c6bd14ea901d6f0c267fd02788360a3a42c1e4130db5e3036fe0505c0665
+TAG: cdc396ce8299277fa7c1656622bbbd1c4a1bb13800ae12f89228bac076a03f5c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed6c5599f1e11fabfd3f587e811e5ce8f521d6b15a1ef742ff2908af523ff52f02f44264ce1b65cb83494149db94e633169c700461e0ababee2c9dd3efc9f5699a960bd7b99471b8194a0e038b69a19b4f705ead795cdb99b7bd39d4c40360525d813a94052776578ce961fc9211f039e55d4681a3a26d1ed23a317c0ccf98a98e8c5432df8f2863c5db03b927b5985bb1
+TAG: 068908c7b7470164e513b0bef2417bbafa7af7d2c5da6be6a854f6012a7b74f5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed075c60a6c816d172de2c0fa3833c87abb9267739343eb03c29968f0a877b2ab514ca271aaa55118ae411a83760642b83f552422bdc5032874a2ff876e75139a67a3e36bd26cd7a667a1d034c35bbdd61bd4bebb977477ef7eb0ad7015a785e45349043aa547dcb647201178c66dcb6d2351beddcb1181dc57d579968fc623f072f2516c8c7cd82ec634bf6c147672e48
+TAG: 197769e911c147543cdc99634b6edbe41cbf6a7a276d55ae8a540bd52cb5f809
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3beddaf3b0176ef0b72b78c422374167f199cb18e1e08d0127b10867113e40110f4df9bffabd827c92e56d3d4ef281d4af8f0137bb51649fcc24e3df0f622701d567e349013dc81a65fb66a00c0240d46ec7cfe94005506bc1a86ab37dbab0f6708a85669fb5993a79891130b28c62fcc0dece6c29437e2cb4b75ae89c8f9d0c5e9dfd5c961342a77e1783e05e3e5e06c539
+TAG: b6777d87780a92396e6edb65214bf7a2d59b6e6143252cb0bc91b5a468a20ed1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bedd09eecd1039cbf6660ab6d25ea0895a12cadf7246d40ff459b38d0b407eac6d2dd5f6dce3ce69cb1a4c29f56360dad5384d7e7d0e600d7f3004f775949de02d2dae77aeba46e5659b56afc654190f7db450fdfb4059759d4235d9a86b84983927f34d4d42825b900548e35028cb744dbdc56f2270c0b69ac08758ffe1c25e5112c5ca70dea2ad0da2f66117a68987a13
+TAG: 0ac4e4190d9b0a588447bb3f3b644d0855406ae04d339597fac480abb0d04252
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed158d01ef658a4ae11d6a0f5eea0d4d92827bba87be65b82ed625bbe6682568acbb06799bf140e7b4a8c535998b18ba63dee83185ae840ec6f1d595d25c5f8dfd843a579dd950725bce88e390ca8f880f4ecfc930a39c8c7f7eef47b6f3014991dc294aaa5b7d9b5b7975f7026bab655b48defdb508a7940634f2e7a0039a7a1175b2d92d518ce1b11df50ef00dc5be69
+TAG: f177db3606b786c3fbe5fe272aa94a42e0ab246214db571917746b9a0057995f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed80ea1311832b5c63047e7437105438a903264b5169665ea270ef6d57db2a3e5fd851e3b6df77afddc2c72e5225648ca00e969a05febf7065656d716edeb85834c7da405be742f45134161fd36ab1c6fc2f7ffe5b92ee58cf88f3adf7261e2147f3ddd5bbe3ffa49a459a8126b240bf46debf9e8cecd1e9b6962f2697b93e83a14f947b5f14da637f9e185f9f560841c1
+TAG: 340a862600cc2cb8f6c1e3c67852c505b6fecd1317b6a8e366ca836de50d3dc3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bedda7520fb78be9bdc7d3eea64991627af73ecae388072f05a0affe001569ad43b8ef0619c464ef35f14c15e5007997c4dba7fdaa917cca2e911f0d946e2f822990e8e9b35821cebd5f22f9b09b662638b61c08e2eab80b801f2759de4a492b48482ab6ad92a8118da8e8113dad3aea944abcdd314c2c388daca59dd0fd5c518abb00ca99010388356be5095b89dd2e507
+TAG: f4d91c18dcc18623187f7b3c4df72967705afd142a4cffbef4f39c83ce32d083
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bede3a19edf232bcdbf4d1bfea5f04aa9bb48c5b94db3cafd8d512f19fc98edcf9830945b435980fe6db42c37f71c762996c075c9bb6262597386487b82834b6efc7d3f3b6a5c1b333d3309780c24d53a92b56af8d65308a74e63ece2e9d535ac98c2d9b4fdf8dcdf07ca557486d21bf6f49039f246c65482e40b2376d8f352f3d519e36d6d5e19e523e87887dd82bb49ab
+TAG: 49a364bbe03b879c6e60a3ac36d6b06c34c0742ff8b80010a3083ac01997fccd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bede56ac06a7c3ce381e54582ea8a3f9bff1e035bbfe12a0a245e87ec0e8b46eb0b561bf16e04bd8ad67b78c87e233abcc522ba8114d1a182ff39eb9be823cdaee517545337568265b25b6c920a610987eef135f75f096df1d0502071679aa55b36bb9ffe8a23ff339e3552af675753034ec9408459e9ff0adec9307b44d57076ffcc065e67feb030ff9c3e0de847357750
+TAG: 451c4d890c72ddb7f738afb34cce1cc8f57aa831a3b8c632f58d1e0dcc66baf6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bedb49a85ea6a8b439372282b9d6c4b0713b3bc7f551e06c1156f6c45f1d492737fd57b36c395a7c320ce058ae64fa32bec225d27023833586fa82050e4002efc44db03ec8f4b2656c50b98eea5dec160e561bddb9d6bdb2bd5b6e92ec5707b5e85764bbc429c1ebc3b77b279890a79ab11ad7628fbdec9701a853a20e0261a044113fc4b130f9fe8f791296f416878de77
+TAG: 76fa463e8c6f24d353079c03d67d5a3fdc66200c528612495cad49fd99214734
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3beddf3f56c30e18f59d47943a1339a73d202aa6a2a4e94957409b0f1c37e52911ebe3587091053815e664441356014e08922014c8082e1141487cd3abaa93dfee17420b776839d29c8e3bf180f62882d952fe2e218a745a3e532b8a7fdacacc81e3e8186d66db2ec78d7581ebdf906dd6524682ad2dbba769ccb6301c67e779e36ad87d082420b35acc5c458879af3ff521
+TAG: ae7f9d2ecf167b2317ba08d95dfdd26ffd322ecea0771f9d673a28b15c77e621
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bedb2d361254e567426e2ea300bbb90ead7b7c97859044c0d2d5ba4c990f11a155e391dfda0ba880057df78396d20dc98f67c4e207b9e118136e7a5a833ab1435abb888421f0fbd5030b57f7d0aa3bd03c929ad0b3eee392a3722cfba9f72c689ee1807768e1b6ce2bf55725b1fd0770a613fb9495b232d68144de3d774c70931de23a467eda3dabf1061270b7843ec0ee9
+TAG: 4381969410949f72e7591995a179197f93b1a6b9eb841e0c34cf0500c61f3eb5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed8ea2c087efa8b1724af84630191e7077bdd96717337bbadb395d3f0606ed8088e5396af33a8adc44e83532635c9fa125e3687d89b14ace7c61e990e425ce2ed860b1daf512199c8ce85a94b21f5c75bcade456cfa6ecad494459c8893d034e047408f99cb8a95fd51356c18381c0862459c21654439844a2e9a8899361f2eea71fc0a2f1be824e95bfabf8db051a5186
+TAG: 0db52c5336ce56084c1c4b67f2cc03a43164769395e36398c587fad721a02fdf
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bedae3051b3c28ea8759e8bc52ad8c385bf565ec675bdcedf4bf26551889d8e2251bdfc037c7804a81c67198c37b24a19a28403a9400558cbafbe091833f572e5870b77e193462c124f069632de52da618da078fcc7c80e5d3727ac5573d70f88d37d02770395fd1314e5d2289f52dd099236027bf7c160cee90f034020d0be0a1996279b33aba9bf88f18b78b8d66d7fdd
+TAG: 16150f0cef5d12d8542e0470f0563fe6fe3705383f5d3074848d040ca6a60946
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed77dba3e5726ec9d4c571adac4546374e0a23fc27446e2385776aabad5f00a9825fd2804aca4de42c19229e936b2cc6f1555387c692aac5e663cb6bb57bff552c787c9cab96e539ceb10dabedb4cd3e121079805c1592028d20d5c22c36f6f9538293cf2590d279e8bd0490eabb14a15f6522e2888ca0fded028653ce5551b12555ba857b01a3ff2e7018bb2d57ef1bf4
+TAG: 6f07ff30814614f5b1f219befc454873bbc48918d6c56f06661f257343f9d676
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874f9f4cec130550444d88e0d98859c29699cc7a64edca922fadb3b656febaae1188b8da167bee4b6517ba96f4b59908936ffaf5f982e03b14bef86d9afae8e1a6b5d5fd5d1798feccc0358b5321bdf3285a5c36206933736307198cf699e3180c29ffa7e8093e4c7b99e9ac06a3270fc24f1e461e0c72689127b50aa733c04ae7e
+TAG: 4b3fb1b3cf4a39bc6148a07e27ef683d7fda6aac6a4bd3f42151b71e6c122fb6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f7838748226605645b8144c88fe164b8198d31bfe4a64c709c69910ea9af8d922f2c827d4cee907d545374ecb2e457d8bb21b960c43cb94781ea6561d6d001cdc07c5cab039885a6db43f8c76ef4f355a0f3fe632cc54fc18cc3076719c0065720d0db97033b6d583dc571a24ace969d91b951ccb8f2674acdb7f742874cef41113eca4
+TAG: 5e726fa9da2390828f77993c136685bf0258d4087cba8869e7b6d3a3c37424e4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f7838748021add7a18115ea5dcc8825b758ddfd44b70c025792add5de8a8144a9ef73410ff3431a6b68a7aab8d894bd8d107fa035c598864ad9014bfe35e80e1dda82e5dbdef49f98e406605e89ae58f431d07fd9ee16640a87a62dfbfae3ffb6aa8c535cc1da9674c76da9ff8bf81ff15e84c2b587113d55d3fb281b51397db64f5b51
+TAG: 53a940406485b4fedb946fbedb50dc0f99e51db25dbda47abaff13a7578b63ce
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874571a2ca3fc257c297731783aaf44681357b79e98cc7d808ed018d9d353290eb399271350aad1b1fcde622eab1ecb4c4c2b5fcf583458b7f97ba5853c75b7e376bc7159384a16dcd5ee15c6fd6a8b80f98eb4f351ee25227f85d933a1fb615b10da18d133848c43310a0b50e9f2d23a99a87c8d0d35750565c10d7991ca9c1d87
+TAG: 71a89c0b210532e07a78052b215be085cc08220322191cab967afe020784b4a3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b0786f1a68f47eb02f29d103302247756f86f376b86740267589f2e9acdf440459d3e58aa8f0fabc1f9661c9289e24ce7e792c5d2429dbeff0a1030dde6887932a028fd2b90a1193aa5e5eab04e51e075e7a8bedfd2a7b0db072721d1062c053e05f1a938b9d3f80505cc379e858ba80f0244745ffe73c7576ab3e4d2d1d53b0
+TAG: 318db5c8ecf2c7f342176b4774cbe036cc357afc083ad8b22471de9b96307cd5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f7838749664a96f9042e2ad736797ecba27511805d412099db7d1a0de607122c8add4322beb6966618c2d071d80b514fc4e70125edffbac948acdc97253e529ba02b1a780e6cae491fe4513e85526e85a0d78c705d37e01777aaf3d83800f87117c48ecd04cb0f9c4c0510dc1758e8c7a5970f46947b202214b057ca8d26bfefdd58ec4
+TAG: 4f9d8b3c6fc9cc606fe0bce08ed8ab03b5edd0a7a62a72d0dcb56c5b74283014
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f7838746f5c62ada30aa05c100cb9840d60defb707c6ab438ab45e8d737ea5256a58edadecc8d06ed9989d74a2161e3771a6f28d6a6e747b0f83c796e05a6bb95048d509832d0eda49627eb771f566e95ffb5289e05059c9ba394f6f1ceae330de3848978efe9653e190426c2adfca287d4d201d1f00e1bb9a8f103a131abb6c5d2ad80
+TAG: a122baebbef61039a94267ad983269608b4f3479798916013f909b61de10ddf7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874643b6e116749de04f8ec203874f324ce05d77b20fb47c01d8c466a31bb1076002b20c8b102d7b932c6bab436eb8ae44a1e3bcdab8439767bf54d625bbefb033ec27ecbc70ccaebf7c2b6a4cccc73a691c701d3ae87fac03db6058458f54b8402c29d09429cd36836528dfaa304d963d66fdaf8c4f27ad271aae0f24dc300831e
+TAG: 9ef98d024d69cdeb4075070d44ca03824e1f074ad34ffa6cb45e7c03f1fd61dd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f7838741d3e7dfe52a87c189813e223e236a693adfae6ea7ffe453a44ea9544e980a88a4962dc587470e278c86ecbeaacda256e9a87bf7991d4dc6e3eac41e0fc091740529bd593020144cb0312393a3c18f25e6f9cf96bf95c06ff497b89391568e83ffd6bd365d7d2c7872bd2c1bb118121e133741580785662501224283bb0cc74de
+TAG: 1d17f84a2698f484fcc94cc19bb893f59fc140ad7def2e6af5eb9ff305d7db60
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f7838745fd5e8c9dca66e226d0752cd19b253b73fa221a859b3eeb90544e48dcb17b6e676ac6a0ae60e658a037757c53831b8ad4ed34dd4c7d4a2edd5108bcccc5e823fd6d0a4234f400540dc3a2aac4c66d2be290ff66ae796aed9fc60708df801ccc0bfaf7905132c4959569b32e6484616653e4fbde7c40aee84cf77cf3c2d7bd121
+TAG: ae28ca0b827891aef77b7e4ccf9b1d70a98a7e864b3d2ebb57ea32e559861544
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874ee2215b4c93f0228a22625330378d6f8ab6ffba291ac19fcebcc25b255dbf5c8a28f0f97475f89751cc1a14c84c832ca6958c850f91f65011b2b540083dc7eeff48cc567f0994c0909940f1e7b835371442e040ca401bfda4f89346f1e9d15d0b1cf6a9a3fae34897aff585f9a97acd79863836d4c4aa175810095db4bfc5dae
+TAG: 7ecbab01ccc77901016ed7c48460b60b040fdde08f16b36cb1993891918c3676
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874f23eff845229651612ceff22e2cde2faf80c26797981c7260be97b76e700aeb4d3c683c9952a0b2460e9133b30b1f752a71abf9165cf8fcaca28afe523607b3685b37fa7a22594c4727d69f37e8ca55a06f70df6e3c3e53c8b9c731b28c754132bbb944ba789f81785961c9ded649fe224d7cec0f8d4bd3e1f6971571f716580
+TAG: 0d3f1f2da7eb30581faeab131f75eaedb9ff92481b14b57c97df7f25c176bde3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874c6a17d3ad39c16b17957f1043445fa5eda672558db2cd9f5ebd135a96323ac4187efab366115a79639d77bdb317a0bcdc13e92a95c32c36fe9043ab589a72ff2339d5f1069feedd5927c932a673867482cf798678cbdc515fc92c42ca9c21a1bfdf0cdecc70a9ce77f7cc9b45ebb6d07e6876fff8abc3bce280ecea8f6f0e328
+TAG: 5e59e58c9babc8433008f57c8d684096ea79a73a28688245af47e6db67ab0c5d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f7838740f59a9ff8a658aace71126ef2353fe91bb811d085aec5596514c713687517d091a524daa7941cccc6329e9cbf5bd1d9e3d17f965305f2deee0b907fd12b86f094290c7afba8059e0bf8358c906741275e453fabb59d20011f03d336c9b5a4fe23056dc11367b9005fdab23d54854c8b9227450c65c90f504157f3e9b55c9fa96
+TAG: e162ac809152b503a60389390bd44b03669d87e712ce0e221354cab09304656a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874009af7e034d7615108cbc161e61f86b63636e53e1395635a2c1c8e18d81b44b68696774b413926a091e9923e41071f68096e2e56c19677f2574c5b5006892427a03d2e5fc9e59d9336ead21e88247e018c8343cc20e219b9b8ba511a76fcd33956efadb93ffc27a4bd0c3c29b95d4ca1559e4ab91a694ff8edeb6f33b72b98ee
+TAG: 37454d70105e7f79747dde35fcef0603604a7b450c760c8b45caf53c2da6ca8f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874cc62f7376a4112ff03001126e03ef20da60f27acadc044259812deea6165b3ec82f08b572d0cc9ac9b781b21ed95103c20228342d2d0fdee98e5b552f26a981683ed0cc19840b2b6c6745c0558a32756c4564318f5177c2a0183e338013a7c5986e7ba523d04b19f053041c9688675980f83ffb83b2837c6a0fa5d7ce6efa852
+TAG: befa46464641c24e25ebac8e14875ba8297035f037014b8003f8f1c3e214a343
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc9451077ace54f77019e61a54a0515f663207ff47503658ff4ffbb2544f8e9cb3148ea6f1dc8f49bae29a84f5bb4c27c38e3e43c154f2a0c4668b814c7a966e860bb321e409ef62067e7f8428874706a8f7972ebbc9efb5b8618e8734afad1e1f2771afc2e952015bca5d82d6a4f310120b5
+TAG: 21ee69b8cb3463458d156cf96a53e7b4976d9db31cf02ab01eb821560206034d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945cc6252bbba1b5a2ab5e555fa8933f5cfae5dc4c7ea2904a58f3e696124178496250bf6d48dae34e6b65d229489ce0beb6aed5c53db54753fa3cae6d2011d8a526f16f276d6c3291a787339a6b683435abfc7ca9d1175cf2f2ab750a50e88c9a2cf2fc78261989a2e8370e6d5a2e2a682
+TAG: e6edac29585f0638560590a569498308a7171225f537dc79517a7cd5b64715c8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945322f5604a70a6b629e12ee23c0047c5af5d275c813aa9ee8d168b693ffca3973762d976a331f3d252f4b072e832ae5f6919447e96c7688605c195aaeaaa04387095bf41e95d5587eb7455ecc028c550a75ed04f0291bfe34330c298f8eabeddb9bf37afc6db972ccff50784b1b7c22c4
+TAG: 96a140dcb49861f808da82ae7dbe498c0fc9b15e04aca6e9a3a80e0cd2f17f19
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc94558213c93a15696df5f8f71f0633fee092d22341ba2899709f7d203970a3345a635062e325d8bdb13117ee93d3af0e329c441de92ca31d511e57a88185f402a6c53fa4c196d627ab5ee102a114ce1239518b3f6050200434938bb811551bb1837ddf40431dc650c5d628ea257c8206800
+TAG: 16c2246aeb89c526f9faafbf6398508063d06e992aee8452430776bbf335d103
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e33ecc4282222ebaa271c82dfad00d527cb25160cd82fc91ae59b6ef59897aa54bbb823d3dbd68cbe02c736bec0e7305ac67bf76b236625f47062d816660516cdfbe65f61045da507bd3f7da3d52f0fe68ff090199bf89603a1431a3d2ecd74b3ee7b914dec3bc7577deaa1d1450c017
+TAG: a1b41f4fbbde3520ebd0784b258820471a95906db7e0059ca21c702a1ab7bc05
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc9456c9edcca35ac71efe776263990e443fb78ff360dbab83bb1ff5e7948a4fc0683c107f09789db44ca8938360ed96ec1bd4b65849235d7bde26bef727922d81cb9f41a94aa999625461d6247849e45099a877d8b316294a4f669b85b61ccf19126609ffb2e76cfdbda4621d927df1ee700
+TAG: 229c9905921f20b4334d651ad683d7a8a5f783f9c31d8b4f1cfb366ff8c7ae9f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc9451ed63d7740221764ad23fcde157ff3de77779f6fccb2a4afba860dce9aa5afb2dba513545a42ba897e14d3279b40bd057fb4e79cd753bd3704f110e0af90241039c69c11f0321caf9ea4256155e04380d92b916e9958a1a7d6469756c576111499a165896b5ae38272ef2d1756e1ac75
+TAG: ada379e2e742a8fdffaa5c5dfc68dd5da6ae68f18f300708685281bac66209bf
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945433d5001a540414f0e38bb6d2d2a1d358fc1bbc8189e4ac18f5888a7b31898afae92101750163e97da88df926b3634c2a18bc90bef0da058a85e2fcc55e6ec1c321a462ec3a641b133cfaf8cc282bdbda601824b117d3084c23030130334306ef5890f6254573a07d2ea7487cf943494
+TAG: ba1c903ccb8b2634a9f0c2600da902afc7d8841b7bee6f1d03e047092a290175
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945fda4375f71502837e669199f79ee645600ce9387673f995b5aeb309823db2908856737d252427d3f43e4a7af5debc0bfe52d62c0b2fb71b46ccc759f570ec7722bfb961b05284b6c980f04341119bd7139b2839721981ede6edc03ffb3dbf98579ed7007c871a314737c28a7f2de656d
+TAG: 0b0684ef8eee63b654688f60a277c4edf81518162651c29077404a48bfc3115b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc9459e2405eb01f8c4204ff1d1e11d3cae4d28d844b06467dbfd726d89caf30d99c45d7bf00140fcdbbf32ddc87ff4f52da8757b33d01fcf684e1732914117a762402f3e65f8838e5d359a41a36fd9cc399553a8344433dece4f993279ebf8b2f7dc00ed72327f8e83ccfadf8eefd6c67449
+TAG: b07f91fc44090951dab911273b2d4f34745be9482ac022e27504f684e5847fbf
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc9459d4abcd0c7c8eaa88fc57380f8234865279733b9a5547400d57af90809db20bcf6137fd8e28e58d95c2c03741f6d50f3b38a80c33627e81751faf97162eb163b62020ace2a890bf849c7279f4364e37cff79154eb93f6e0d5b07c8f6a7994d843f3ee581b0c55df3aa1c1b424b7f356c
+TAG: 62baf47179d54145dc72910df080aa5d71856d7651a07fe1e18c2a1a648b3069
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc9459f0058003505ba8951695a97eeb0de9f8a84b89d64a4b25d8ab6736344233951836179dc5546ac9135718a2432138219f49c47b294a747cf204718c6563c463d0b00dc6a8abf9414fa211a6de3ac5c931561e232ebc0627bf5c55920065c2e45d8e74a5bee4544b0134a5ca75d7241e8
+TAG: 499965a9690977eb501f5a570cf82e5442ce1308206fe3d0961256cbfb36c44f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc94573c07dd331b0fa9c971849451290049e472c2f816cd05269d832b4be600bba803d13b8bdac6a8fb56ce760f55d1cc8ff48c0d29734354b5fed619fa8a9e7c5dbb50875d047ef46d083cd642817ae43c981b43588030085726b02c81e69c77afb830cf7bdaabe52c67a318d3b308197fa
+TAG: 2cddd1443ea99739d7f75152e19af6c1847d8c0a8f021d608432d4c7c554fc02
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc9452397208bee229beadc7256aa058ca117ec964b3e7604f92e66c98e2f4264d1af20a71330e79a039046dec59c4373eaeb376a26d72aad43f31834bdf9a8ab0fa3c71f56d714768d794b40b3f5c2162e4037a87826f54d6554858b6c842efc6b49a0ef834f1dd3271a301fec5ee1837a77
+TAG: 3bba6ebe3b011860ddce933b8209fcbfedea882dc55b73db8a9bb9337cf157c3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945c3af14971e1b0c12c8de6d7a082643240dc126980598f9ab2b4ac09a563f0ad537209dac8ab063757300fea66a7a072f05115a6432b1bdcd58a06f5e2c254f04554ef43337a06c9d789dd25dc31469dbe81093632276bfb7d0f7ddeb6865670caf02f3f8d4221d569799f54729a56e78
+TAG: 55e5c75b41c0a4bb39838c4a39d623b0cb457b81e26fe66a0f5abfcb5d96e685
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc9450881e98c00a8f366d14b1e5434f7e6a6289c732d44c1c18cab0b834e9473e0385f2c3cbe6c40038d9288c6db240195305bda5053140038d3fd278b2cc3f15a12632afdb64b5d46853352eb74de04342bd83d756eacaad95e7224217ae2f5494e816186fa0c53e28a3e0ed9dfe6dcaba0
+TAG: b8eb7c14726579d10cc1fc16ac0e3c0e38a9d7a1a908e6610f58b020d0efc148
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab3971258b3acf7ef84a13430fb761d1d34cf8be388e2dbf790318018949492ca205da06493e16b2ae564fad96cdb3040d06c02e97a8b8f90262954f8b064fb6057f2c0d04a177e36584466b095e5eba825f40a445cfa9002872c0bfd8a368957f8db
+TAG: a044d95a7c7b4f7e053914b331187f9a1c011157a2d53d06e83fef9864de620d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab3979e11620336d4a28a7844da70bf9eef4df01037916d2c2b24c51f308c1db2e9ca8151a5538cac954c443cf068cf95447d959304a0bcaa7230d3bd63e004da7272244a99b729121ae42af8b55479fc2ea6b74d97cd7d571bc4df3a4fe1841eb9b1
+TAG: 57f68ebd58eb902503e84fa81804a9f77ddaf4004e811347546c78dd94223e9a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397e4b944564db4172057424baa6d23dcc412874c567daf7ac00a8bacb14688d3cdeb431621f0f8a42cf8055c20e8949ac9b03b021f84a30900d94d7b4401aa8cc36f93ee5f1a62093223d9a303cd0c4144fbd77a6f9a4e46bc2bd0fc8a4b4d0e10
+TAG: 5fe1bc30f02d239d03e597a5d0e373c129e3cdebce72cc2639a9495f6be966a1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab3975cf9190918b978983ba1cd6239c9e7e45a9bd53f54a561bffed98a503ec2fb95b63cc07afe991ff5873562b1332999f311929512f6304e09a1a248bc07cb08e068d2bcb5bccc9eb574155002e9882f952ef03e713f040cc10a630899f7bd52d4
+TAG: 2e0bef22b4e2b96f2339d68f45dcc6c892ec9b85a22e9b111eb3d0a04c9e7185
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c37707b262598bc68b20e6f5d80485870e90ec67cf1092e65aa765f87721750774b381a549f930f372c394b09c75c82ffd4140218784c93cf48b1db77ab25a7b240fc018d20567ae231eb15d007f3723a556c6951f60b65cfe72941e0cf4e297
+TAG: 4c4a7dbce149d678b31b26673b4f12bbf5ac508006ebf71a2535f3cb9e126ecb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397ed4bf596bed30adac7f9590881056848a8cae3d6a126bd5d6819db808b55fa623f23aa1ab0812a867e25cb9cdaa707eada28a6ee39b8a04525e2f41d23ff7b2789f7b467d472c697bc790ffa76e32a88be53a8bee4fc36ed31d42bad712fd0b8
+TAG: 18f6be2512e7e1f152fecd4e227bfa0b2bb178dabaf89a392f68ec2fdb32b971
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab3979667636741f49957f93ef027cd65e93e75e015e6547b37d6626f6e1042c1542e9b2780effd170c075538cbb44e852df46a585cd26261173a549b6927299b8c87269b7436b541d058373ef75a71a3dee9e505c745ad1bc833afae685e6ac91f4f
+TAG: 4fccf3cfb9bb82c8c6e8f1ed95a5cd1fb486edd3c8e9fbb5cbe3d4d5202ea9f6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab39783af7c5827165599741e4e7296a85d2c0b5b51bea8e90be43a9b6379b7c99b1f2e2df31d97f09e06bd8d33d202f260cb3c4c38eb13a5f5502c132e9a71a53df8dc24faa42935b472e2307aae961e43c5eddceaf7f070126aaaaefa96b11a5bb7
+TAG: 04333bdad0e990ab3f8bccecb87bc1940f784f85079ac25cec04a2450ea85216
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397642ab9eb04697b7dbeb68dbb38a3588f9833529e1d822a59a426e11de0e2473950f1bce0a0ef279405264e6556de585ca2f00604617a2d9a360f56e0fd369888190a45e1173329bc5392f8a8fabde88dd9f7f1a2bc6a9c2f414a77a2ed91a5de
+TAG: 5b55928e4c32ebc94b12d71c972ace7b62585cb6b4ddfc67ffd96c61d4d0647b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab3979fa4110200b0bf2b3712631cc9797ae9c87f3c484410cc0870d253552b2662a2e638b0b90f1f084f49f8b6b2d65c3a09e0a8f1e6b0c8c41e294de30ee1483e417cf19a52f62ae6b7d1ab39689d6aff6c63a39491804e80b25da4812020826393
+TAG: 25dff33eebbcbdb2b45d1fb9965190c1657fce510cf8edbc0de62abb2d3aa5cb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab3972b5c271fb1f5850fbbac3e53a34ad76c0313059cf730ab7c9d50e8c76b8dc49fcdf12324ac6261785af9ef882128b2e3472f703fa5fe9926f7ea4d0f183b1052e795c6be4de77e433e8c0d09103a3234df8d70eebe4fcec07eff78337e8a8cd7
+TAG: 4a1d9e15e5c8628f769cbd5b74d6154a75f3882aaf1d951faf39fe0b511cc3c9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397ad32fea30d8cad41d5d3421c1dc3d20b272b0f5c1d63e379863436589171d0cfd11a89aed63098b807485661e33c33f1eab9add5e835e154264cbd36a79e2858164bd6ca88478bdc563b4b9f29adce056b4217252c39474489a570aba785c907
+TAG: a9e5f8d85c573ad590ad8e69a99682908e1727c9da70eebe330596647ec589c4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab39737e498fd071681d5f00cced170acc64792139599c7e9f871653e9b69dea839c7d3f16d231b410e5ab106b360ca4692c110d2bef4c0e21ce15f9ed70a47d23afa205a1814734c6eaf02a7f70892bf34e82d6b6110968499a05a345d3c6ca3d1cb
+TAG: fe141912515adbb044a12e74e85e9074e8eb60af5fc90df7d22708299cdfb5f8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab3974a0a438d2bc15cdd4d1e6caba954421b5776966d441c09ad016f07291c675f35368e089f090031b904f8f9757113bfe1ee84a73e1626f31a71bdb056e5f1c0be4529f2fe797b9401c96f43ddea70db49e5ecd20b381a4b4b623f167141cd748a
+TAG: ac0c408caa69fcf7b89f012d817e1577a31252fd46786531d1c6a697631a106b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397b2092df220778468a0f0fbffc04101aab17b5c1a0fa737a420f43efe21333f722d93e3a48bcff3d87be923654830b3cabffad948973ae0265e2ed5bfca73c04b85f18d1eaa6e091166eec5b19504d98c6835077f79d1a4d0788aa61860cb384c
+TAG: 8d372fbd9103ed554a0359be9e91fa116b5f113c3bd963778b6bf2e868238896
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397cf073a75a8ca27f3f4c18395e65736f6dec2f046ee57b6b8ed800cfc19423dfc5e977f7e4347cbe7a9adbca67880c9fa41a65a4db422e5f2c1fcb1de960b82d460ad808b00c857b6e001688d40823284c8fc1339226a0cb6993c458ecfeacee7
+TAG: c5d8d39124904688504894f1879fbdd3cffbe84b6d03846a01daca7d47d8d638
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1dfad6d7e7be2b2476883502e8f4649fee0b0399ec734db8d17b3389c3f987ac190ebf8740c28ae1632231d9e83e062812f11f1c462557f223e4974d998571271f55a0a2a04da49541fb6a12215b59e5c7
+TAG: 62fba5a4e948560623b1363e329fe953f03c67df57149a7877c64841568a827c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1ddbd908f29a67bc048bb7869bea2587e04af1e09922caa0cf3af6563bb0c65f5b81082f83d5261df1dd513657b290b050a2584881dca5dd22d5c21d9e453ee15dcf6d4adfb2ab8ceac2e6b9f9b0cb2f83
+TAG: f4204f98699beb2f4fc620cd6d1d6ec04ce1845bd611842062f17a3a64c25a04
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d28219e7c7990949a751b49f4ae0b2772e738d603735be272b7eca25cf586d087c3dbb5c8e2838b3de38d20c875b397445bdd07e28c4735131175bc998389fa9bc11e043e552dc56e7c31dec28ba93537
+TAG: ec8a5b1d4e3308ad20964db08e4ae6926080074ff8fcebab524798ae00c10028
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d0b37c319d2beb07c0f46477fe5a80e57813c0123b712a99bcc06fd721989d8c376e0f6f9681225d5ca02de4695386a2caea4b2dfcb5442ed9714bc1ffc209901f3abe54db66b525cc90afce28e458f50
+TAG: 0fa79227b81a26a064ff310d1d70804ebd0844310c925d43bb417bcc72ab727a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d4f988d5bf678123dc0a1cb5ba116cde51777f2b80f7e7007d0ac363ea14ef1b4dc75ec59608265953bce439afd8e93a3186149bd1b4c798d76a0af3632d64c8b2b4b1d8bf8604ecab3f8259b5374086e
+TAG: 837e91b3869ecd042e4aa4470593c10078b41225f270606d7b6d018bbbfec292
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d9dbb23e0259826bb560d3e43b586d946997b856b59f46f360f9f80dd38c4caec6059ca7cac90e8665c9a551038d35947d406dbbbd5680f92bc0c8769075a96d1492bdf7af17f4ef72c768c93d8633bbd
+TAG: c20fb7f5e4cb72174391c5a4ac640b28e26ce66750e77b040959b6debb87a673
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d976c45750e9d9fcf878fb69dae0009811d604575124f525c806f2e5e0065ebbf01f4459e199f3c101754d329b054481e4587f020652823b6c8fbe23456d6da83869491cd98c1f8dfcb4da411489f5ca5
+TAG: 1dfb16f20d50fd375e39f523b7f7ae66ab0708342d1a043a623d68c056ddd11a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d0cd0db8c6462999ea02900db413405ebce540f821497ff138b2f44f31a7bced499556e4763b55661087a27f910fd438f6ba30d08d7d60a1757eb23bf5dea11159052e2ba3e3d1ae64f915b6d9dd7c3e8
+TAG: 277b3885e66e22995482c4994de69b4e789b6ed64144312fa4d3056a0a4223e7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1dce7e08138b81f3d8cc100826d2e83763701798ab40e7e40d5eb2431574d50c54fb130bc7b250fa24a5b7f1f766a3dfd26284d6e45c49ff91acc0f21a8b646b32a8511c7919ead444f2c3800ab52f0c05
+TAG: e732ed8e283c8525cfec8416b5402070ad0e79f37a9b146542b948dfc823830c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1df4a85051782cebe0ace187a8a211461ac98ba0ec31538ee4f50bd9877c022329d62a3f127e67262225aa5ce9daf0100980067a044ea97f328ad444537bd81f39e53864c80ba15a66becdbce8e7b24331
+TAG: 2bf68cc6f6bdf5048b1247f0c58f1b0d8ae738fc51fc692857217e34f0c6197e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d9dc53e59808ff4a96740c956bbb21410192c47b957fa5215f1e0d2d2b58aca70a020e8528fc7597bbe455db8b7f7aefb09a338dc70cb3626307b6d772718f3ec08af4e04f2391e8324594ee1cb830c67
+TAG: e08dc63e6aace0c7419549c4a594cfd93a2b81194f3bd462a0ef7cbd9c9d432b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d28d3f9f839913662f0f767b90509f2021347943afd7051301a65dd061d99da1e54cd99aa57958e5ccb37d23604a1a4fba176a6ab860cdc966c224ac27a679e6ede23098a7a15a288a73cae45151ea5ea
+TAG: 2dfd0b7084aab0b466546cdf5e369137782c6b3690e47446181d886698232906
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1dc9d362c96befa63d5f587e9245167a9d6ad41324d67606918d3c9af291431415961e2db78fb214a4ef6012dc7b2594f037fd01d2c41cce645ee1f2a95c31e249385cd8a052d78227135589ae37be7056
+TAG: 29cf021a08111be3993da5e054d7892c70c3b6f9e6bf3ae962a40c2ec2967677
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1da42a24210cdae03ccf51393d63aa90d875bb2811a081767284e4f69320b3536a30a2593b161644ee13eb6ec6e455e024c298e0f74afa533c734848f52d7f162a90eeb0570423d21b4833c27da71906fe
+TAG: 9eb4842223257929fac496064a1bfb620bb94153f4783295a9326ee09dd54220
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d6b7173e44fe6876516bb71e4d9199066ce215868b1fb62eabf64cdf292afbb848a72dbd2b324e3c5ffe3f8372d8334ee896eafa7c8448e43df0c9796ec885006df308f984140c028a4fb269c2bcf037f
+TAG: 37e197c6e47db1e44a754f670ab5faf90879daa694d507a93cce360135271713
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d3f541a821f67a0620483d9cd671255cb0fbce78df6f69832b1bd093e0adad0dc9510b6b68ee686fe31b3b62f48356da3e083420199e1a1f4a08c5590b4f07d0a824bb0b75f18a592c828f0d2e0202773
+TAG: f204976acc2c0350ac508c58a4251056bb193c7fa6594f82e85bc333b8968ee2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f881c8c2ec1c5f1877982414d4841215705f7fd6100b25df7d0a0b2b2d63b36429b68d99aa08a65e2637a06645eb20c7348175512c9541bc6258ad72d50862350
+TAG: 7be2d626aaf177c06cc59f47ef11932be340ea8543acd351841506a0a2bc6082
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f48dc5b447012aad1c6766e163960128a06ca32b389a0d5ca39e440d3f4bde8370be091fc515870a073d1df3e9ba9096d6c1f5d7af4b207bd0d5bed9851b0efbd
+TAG: 0f3cea72d5194734fe79827fa78b25fe6f8294d70680c9d5598a38e1e777aea6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15fcf34dbfc4275b3186beb9997adb283bb0052a5cc0995c4464012c1fe9366e40b9ad9a895796feb63ea71cc63f5115b7d11be39278971f101ddfadc0177fca4fa
+TAG: 1188bfdea1ae2f2f895cc5aa27fd95ba94201fd660ccdf49d644b2f86a362fa6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15fe0697d66e9abf64c4bc64080d84ee9b4495b49fddc6238ecd2c0f2b20c732749bbff1e17443aeb01bd1cba99236487ab6470e2b0d95c9e8fdcf6ef6f5117eb75
+TAG: 9f4c2e83af9d25221167b4f0e93fe027d4e380dd2a020083714df71c6b46456c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15ff284623537be69b22e7a541463093415685cfe47bf348df63dc695c7a55ce8393d2bb4deecbf1d0f0e7500998ca741ef4cbf6904d4d242807532fd98ced77d7b
+TAG: a4cf5c814746255589220453129e95670a8067ce38186111553b806925f58c47
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15ffad016970261c50562ea18bd7c319bc105b8b38e67c286a80a9e8d956859420428d284f03d118a9805c60e1409470959e2a838ef178d393afe01f113c89bd32c
+TAG: c23dbd74286834df5f68f6ce000dd3f56d5d84b74487d9aba979113b777c35ce
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f723893976d3947f23bdebd70d6d4e45e35a5ff8d54b7cc09018f6272373e64731fc3f8ea2cd302bca0a430b5ee0732e93677bfae12fdf83dcda9235ad1d4ea2a
+TAG: ffbebe1981f7079c1a8fedfac001c033f2a1a45c0a133f3164d1b6d456d6dfdd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f0f4dbcdfb226f6f0ebb61253d1373ced9489b2fbb5b082157fabfee7b6cf6988105c5aafeb13740522ebcf66b1b726e51159d87671340fdada037aeb85818c2a
+TAG: 71f761c0ffd1fa597f01d0140f569e513a9d292059f44620a392a5a33e77bf60
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15fd83dacdc3af1fec9b1d8c8d13238103473e4b1d26a000b76710707a40fd07bb6d5058d88384a9d7db6128dae1964d8dd1e63bb574414d525c816eac8b5bcb3b2
+TAG: bfa6bb7e47590141342c041bda64d45f453fda1d3658ca032f719583cd6e216c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15fe8489cf600b865044d3d1a887e3fb18750b357242d5a20fd7698d6feeba822b873eec0b11a3b24d12c222995fd59e84e1d47df504515ef19dee031bc020f2b18
+TAG: b4367546d9b2e30d30fc4f120f3d2d78111401f2454ce4a070b8f82d49e7a7fc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15ffdb2dcc884405cbd7ced5e317f2de24fb7a7c5c6e385cdf837cd3e3a8f6abb79c784aa7f181f9136b300c905b452f8f525ece53d8d223ae44d2ce33a36567bcd
+TAG: 8fb1a29654cb1512d5de6cc68e1af9baf7c94aefaad8ad570bbebb79d9a6c52f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f279be5950bbee9f9065d6a366745dadd204785b8af86d98a33c09ea300a59800151ddf173b19deeed9577454046653389121ac904b640099344c3f761f3e9656
+TAG: 34879c9f12ab3d280b34d099a687ab53ccc7bb2aed87d3ed650b2e1d23500055
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f190e7e450b669cd3804668dfcbd081a101daf5efcfa2c9017196bc0fd4ab2eadf561bf849cb7c485270a5d2e2cf85ea85dddc311a9cc0d21175063bb52b872e5
+TAG: 67cb73eb7f1a6ff36056d8399d30e26ab6c90fce8f076ff9f67dd2af2d6b600d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f0bfc253707af6ab773dc6fc8bca255c667f8b398a8556b0c3e8a98bb3d39d7bc50a13d26714bf40b926d048aea62a68e4506147e493358e1d4f04730a1b89aad
+TAG: f50bdeb932877069ad800d312c604dacb6e8f28342814208f331bc31dee52c23
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f1165f70b31fd67f54cf543cfb2c2488e35eca3945457f1d0845f54d758118590e96adb79c2208de677d542df7db509824171ae797bdf14a31d0ffd8f1e44c814
+TAG: 0c722fb9ae86989d096de4c2ee42167e9b8d139f8d8815c21e7d75f3520da713
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15fd8c3f502b1bdb9dd3711c4caee4241b885817cfebb0607cf383123629b5a1e04a0b940a0185d49cd72922d904e356307aee11f6938093612babf43b50a89a279
+TAG: 832d200206981853b81469499f1e6d2a67872a644d3437803451d948370443d0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f68a70ca0ec2093faeddc4f1741e520c5cb337b81d73b6f306ad60b5b6e2ed33e3d111cc174540ebb7c370357d4f481c0c
+TAG: 10f04bbd183d23e5fdbd919dc4f41c1b6e931ae9cdf8275cb6a5fa9ae527a29e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f6e23604465eb913c4e34a776a096c0cc7a95f901994aa4794eb0ee73bbcf3266774fa8eebc6c518326915026b0d70d916
+TAG: 48ad5070f88cf42731d5e6e3eb565d83367a37e2aa8a5ea95e10b562db2b004f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f6ee06d5d823842f232681b6a50487e57138226b16669c7967afb9ebf970cb04dbafaab1ba3f7bce568c43d6e9277f0a9e
+TAG: a9286a47837fe62f1e659b7fc34643c94e69ec44fe2cd80c1490dc8bd90c3338
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f68a2d05ef0a52d40a41191243ca112f3a06f6172fdc5ba86d14ec8de29212314b820ac39b5348118529ead5fb4a1cbd5c
+TAG: 0c6a7da61aabcc1171bb38cb543a7b2ca96d7127d057f749625a1db6428f02fb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f678a24d5d50432ee3626af12da381609dba12bbf8072ec40d8c03d6c7cf63b265311ce43ebff4aad38c3b6c7fd6161240
+TAG: ca5ce8d160b6b82c9ebf64dfccd25f5a451e02e826c625604e47eba7d74afa1a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f66b82c5ae574ab766fbacfddc41faedd61cd3e3b43e2e892967aabdb26588dce1a6be86d17a4f20bc264b4b0607491f88
+TAG: ae825366b692b5858357c6dca92d598b9080a412b62143c1d21ee2ad9c25b37e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f61c1e49b1a0c2ae8307f6d42b303506b9d4307490e886af8ec2211c50d5a0f6a62a029714811e423931a17db0e9cb04fd
+TAG: 4d5fd2b3dcc0bc08a0e381bc270b9ed8167b29bd7702382b0a4a3e622947f883
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f6f0deba7f0855cfd2439712812c7cb4aaf318938cb92f024b75df4a41036f9935f7fec6e661276baf1b5c744aeaa6b15e
+TAG: 98a77ff970bd16daf5e37e1021b0485180a639a1e6c2c6bc926ee62d1919640b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f634d54bd289738e6b366e2dfcb43fbeb71a5e9171fd6a88fd6b0e8f4768494fc8237ee7b3654974b09746e6638c6e43ed
+TAG: 29c9c336973bc465a1dcca3d303dbcd0eacdc0a99d9b6ce569e184792d6199a0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f6a30dd8d6edb66974959394784bceeb59acf70fcfa1ad8cf3963340499101be33001dc87beddf9f8b5cfc3ac40e7d4975
+TAG: a11c931615103728ce5dc9a68a3f7a78a6283981c3753601e4855fb66cf24fd9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f663ff6855f06a7e49dd3d7ceedb1f2ea02df534b32925be4da59f5a6596a11404e0a9e92009d6ff7d26372e9fc064ad67
+TAG: 002ba24d0ab565ac18f3e03e3ad2261fd5a8129662c0d75f85b04088c12613c7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f6a3a4f94a23826e39777ad056abf0e4dc9b136bc1d7257e2babdb83152cdea9a2ac7817386209d6add75fe5af6d75b3dd
+TAG: aefbdd2b890cfa41d0e6261ffc2099e7e8b4c3e7a8c280b068f53cb6d0930946
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f66f8ad67553ef348387b5ccae4cbe4770f8825c4d4c18fa56807f9e58ea66a7106036db7839ce112699bd584236e948dd
+TAG: 1d2e9212b527fb45caec8dcc3b1e679116af8f5f47d9e617811bfa882fabd31b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f6f2ccf62e869ab9558b10f9445b238db39421b5b331202c819112f7c68ca3597f346ed259fd239d8f2cf973f7181ec15d
+TAG: 3d17389e78fd3d6dfa909fd39b5f0b6847e75728790e6b3fdfa43ae637149f3e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f6b6ae46b70f5af53c3637c3937ac4415fa26ab8b3336055b5cdaf810abf65047065453e897ab192923d4fa15f8283d647
+TAG: 035e4b18b478bff21f576fce6197b3effefb7f9b2a8da1af1a98c5160e345e0d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f69095b0900f353d18f9b877b8df8c8f20e8b9495904d66f85d5f3a8e3510079deb48eec6912e0d0439bd4822a8da73fd7
+TAG: 06030265c03bed0072783484a116ad47e319b31b9df16b73ec3eee3c71c3536e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba58eae6fd685e50423d34e45d09fef772d510ce5ed725a552c5c363ec31bdac436c
+TAG: a197db7550fd9912dfa8df33c4a8d6caddb8e8b34e241525b65eb9f21bbb24a9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba585e635d5c5bb133842413ce9e48df0cdfd9a22dbac56e8cc292577a000f3c1599
+TAG: 589bf6df55af47d4503489247fbd62db84793a2d735fc41d91e2c1310c411cbb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba582c2795a3b1f11befee8391d7797531030bfe3ccd594ea97b135175de136fac08
+TAG: d0208953baea92fb6a366ccc05ef2723a4fe605c79b85e744d4a14f4d4a90fc7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba581eaff9cac19dbc6ddcf39e0de49a5bbd5fac378a3c4fff3e9c4c24391f18d527
+TAG: a534345b276087e7ea235bd9f798bfba2c11804f7a663b01473710e8814bdf4a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba589038c345d43b98288b6ff9f550299ab6ac4fa775cb14683ce50c02c798aab75d
+TAG: 57089025712268057de86e36f742c33711c53dc3eacb9548a830c490bc1f11ee
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba5832d6f819e71e197a3b2efbc01e4f8ae960ca53baab65490c98481e9d57fb888c
+TAG: 2b3c4ae569d93ffd65d06dd9c62486affe565396144a146452fcb0564ddf400f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba58e1a3d5a456e2263014f198c4c788b68f7b437e89cc48129491c67e8a644b1989
+TAG: b69618cec9d51fb2825fb2a4bf814f609ff17d99b6256b8e316db217e0061a40
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba5875ee38ff3e53656659c33c7729f8c1502a7bb2b6ec735464d8ee2d7f22c7fd2e
+TAG: 72fa074d32f9c5dbe7d39895adf807506cb79138385ecbc0a16736b69a3dadaf
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba5803ce67551d7df9057bd91526bd409636d45fa3639ae18c696104d44c77442496
+TAG: c5b39ddc6265914e4e5d2e92198f3170df8d7993886e47928df93b3b444b2d41
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba58a882ec07def2aa5c5485550d5cb897d1f1bb356af436a0c471c95c17720c92b1
+TAG: bb2c59ceef95130763b864262abd226c4f42b1a067162b7be43e25505ca97001
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba583c67126ce97cf1a00f88ab61e7cf1b5a6b53ab5a3b673ab2eee5ee1e6ce81517
+TAG: e20dc1287bcaa25379def7ad153cca10aa96a654e71d7b844a4565efa48df47b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba588fda507968881d5aaaaf06cd5775205827fd047a4913e8adb487022c179b4932
+TAG: fc46efb603cb9b0e7178df7f9405880f5038d7dbab26035527d36cfcaa7a5a8b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba5849c49752550d592cdf12ab514448fa81ba04aadbb0c03254dc42df227f5a1a17
+TAG: 89e4d37c723ecdcf0d3da66bc46fefa81867bb5cf5caf8e7ea99c849ad93dbdc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba584786c74d84b5a3c6bef4cdebc020b3c252ecb137eb1e6cccd953ae883b72b2be
+TAG: ada3c74c527a599ba59d64c56022d6c74734414ed4698c191377d882bb8c1860
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba583be5c5f76a4acc0a6d73101e65e110319bccf34677ba7e4ce0a22f0b0d5c4a8c
+TAG: 0957512519bce6537c4ddb1dd6e535c69e41c8e1f3147dfb197708b9519f63e4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba58fa23295f9bf62c4e09704c0377349341721a2184cb025654bfa90115bb4785f7
+TAG: 9777b96b0ed26d29691e1845e0b7b04b3cae8bc4f9b1bb8d73bb8399fec4116d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09e57027b939afce1009342fdd9a52f2d8
+TAG: 2239fb5cbe0cdb3dc52e7ceb111713ddfa522cf7f2cda79091dda2313aabba57
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d094872951413546dc893860d678cd9b6b3
+TAG: cb12cdc024c770fe56b699982ef69a59e1c8782fd1cf924637152fd42a4ea277
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d0996f222cb0e755ca94a450363c2137532
+TAG: bbd512e987da7b7594c4dfdd0f878bbe7f2bc1820ca2fcc83f4c2761e15b7840
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09f96ff8d57f9f6fb9cb39eefdc9be5788
+TAG: 67772c572d7a4cff58a8c6c465a27e773d43b81523e0906e1efdc606feade9fb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d099853669f540620996c323efd11e3ebff
+TAG: 0cccf57d95db93abd53cd5bded3e3b9ef00d589c3047fea3b744f753d1aea516
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d096c5736697bd969737bfeb172eb717f14
+TAG: 61c86005849426395f121e78e36856fe20f05c047c6880675031effb17a9cade
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09a1eeb04d13dd9e4319fb93d9ec737b59
+TAG: 23b355667f6a908f520a068fc8b1f7ac41fb0662b3b2160a027fcf4f7043ced1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d0988eebdb33895fcd6b923e1c90a73ec8d
+TAG: ce6c1bd673d9104df9660b2ed4dc92f1cb8eef5525db009aa2ecc8c81474b5f7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09ebd99b538be55e832e99c5eabf7fd89e
+TAG: 1c57eac802b7b38dc83993a500ab97ce0c1ba70edaed635a62d3d1a82e4e0566
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d098d76662e18803f0096b1aa43215cee5d
+TAG: c9b6fa8f66589b3655f9fe08041c0256aa3598914a45adb9678889919f18c963
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d0955f25e458889b169c79a68a4966cfb6e
+TAG: 70409ce6e3beeb27d771afd885ba388f679dafbd05efd5307870f319a23b3e6e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09807ad377423ca161832ae4e05a2ce155
+TAG: 7d51c2c9b0c34d3de6dbbb9b625b1278f341c385738464da4e7396c85368dd99
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09debb523a50cdecdf8d5bec003e0d542e
+TAG: b554bb9f431d446accedc454982d83346eaeae2260fbd59696ab09217a512585
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d093064893cfbd307cd6f7a1c7a311eb914
+TAG: 34bf334ada93f974705f1887551765f8fcaf0c9741b477d411ea736c78824e08
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d092449ff07b2e2d0985fff7a7b8be2bb0c
+TAG: 4c5a5167e8cfb7ebcae22a41556be3811a793d58886d2d8a5abf30ca812d638e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09da0c0f51899dbbdc34e614631f99e4eb
+TAG: a96d402a5e41073d14884866536024fc75c06650dd503fe6fa12ec7072c83792
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09c7cf88bcfe76c5ffb1512ae5db71c1cc
+TAG: 156de4abc0d8d24480162b31b7c66db3fcf6c296ac912b557d965c2836a917e2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09c7cf88bcfe76c5ffb1512ae5db71c1cc
+TAG: b40499e0a8a1468ba8569a708076c2366802fa48e40ca9dfde881026a74b2314
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09c7cf88bcfe76c5ffb1512ae5db71c1cc
+TAG: 222881504fccd3440b3386c45d91de1886691e225407bc6cc7d4df6efefa1135
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09c7cf88bcfe76c5ffb1512ae5db71c1cc
+TAG: f1d85776e0f9e028b0f72e00341624602ea63c84bcf7914b5569a432e693a2f1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09c7cf88bcfe76c5ffb1512ae5db71c1cc
+TAG: 6e464fb7aef4067fc8ee234276693971fd42fe3af602806ad628291d6e37c6ab
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09c7cf88bcfe76c5ffb1512ae5db71c1cc
+TAG: e1844782215fcb5dd79bd8851ca2d6769486ab51a13d43803100296e25df4ba0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09c7cf88bcfe76c5ffb1512ae5db71c1cc
+TAG: 5d5418614d765b36c5255281436ef681a8e66340649845fa5251eae4c15da097
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09c7cf88bcfe76c5ffb1512ae5db71c1cc
+TAG: c6866a5b8bf101bbeb46c728aff322fa94526db38f5e343c6c63fd0e5be115cb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09c7cf88bcfe76c5ffb1512ae5db71c1cc
+TAG: 02bbaac1643828c8959203694454d89bcb7528ebcbe4d59ee572ef8c1f0aa1a7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09c7cf88bcfe76c5ffb1512ae5db71c1cc
+TAG: 19b834f33a76def213392eead2498c867ae4f71aa31b1d86ee2d93667c1f711b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09c7cf88bcfe76c5ffb1512ae5db71c1cc
+TAG: 56e4598d6134f4c8211e48b650e4586cda84d55e4abae0c4e1cfa85adce67d1e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09c7cf88bcfe76c5ffb1512ae5db71c1cc
+TAG: fe52faf162e11ca45e150f870284f10604e8ed4017e148ed94a0f160dd93a62e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09c7cf88bcfe76c5ffb1512ae5db71c1cc
+TAG: b23293bda8116ff6683eb5ce2701755b38966d54423059a0f44febd699b12937
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09c7cf88bcfe76c5ffb1512ae5db71c1cc
+TAG: f2a6c774c64cec7a0e7c891f3852188e5b57fe71746ed252b2b6891abd18c331
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09c7cf88bcfe76c5ffb1512ae5db71c1cc
+TAG: c120bc872367e8e25293680ddff1cba41178c175f5a3258ec4a1e41a16373e93
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09c7cf88bcfe76c5ffb1512ae5db71c1cc
+TAG: 942d71a1b83594baf05389f36ed5294bee479d69ee2fe0d9bed433e0fbcf792a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09c7cf88bcfe76c5ffb1512ae5db71c1cc
+TAG: 42bfbc03e6f3dd17b160e4b5696b2741fe842e2dc771dbe5ce0f791616fe03c5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09c7cf88bcfe76c5ffb1512ae5db71c1cc
+TAG: 42bfbc03e6f3dd17b160e4b5696b2741c469a923f565399d744d43b32f0c7dec
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09c7cf88bcfe76c5ffb1512ae5db71c1cc
+TAG: 42bfbc03e6f3dd17b160e4b5696b2741fe9f1d0b6c138f724f23350a620cfeea
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09c7cf88bcfe76c5ffb1512ae5db71c1cc
+TAG: 42bfbc03e6f3dd17b160e4b5696b2741797a06537c43d7a528c34adc106cc510
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09c7cf88bcfe76c5ffb1512ae5db71c1cc
+TAG: 42bfbc03e6f3dd17b160e4b5696b274144e06c7bddd98ead471a92fe4e360bcd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09c7cf88bcfe76c5ffb1512ae5db71c1cc
+TAG: 42bfbc03e6f3dd17b160e4b5696b2741fd72b7c9241925795baa033acd8a91c4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09c7cf88bcfe76c5ffb1512ae5db71c1cc
+TAG: 42bfbc03e6f3dd17b160e4b5696b274146382752e7895b4d837309849a20753f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09c7cf88bcfe76c5ffb1512ae5db71c1cc
+TAG: 42bfbc03e6f3dd17b160e4b5696b2741f8adfb8cd2e6f626c6ab300d014ac548
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09c7cf88bcfe76c5ffb1512ae5db71c1cc
+TAG: 42bfbc03e6f3dd17b160e4b5696b2741a9844449369d3073e3390f6ba58b0449
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09c7cf88bcfe76c5ffb1512ae5db71c1cc
+TAG: 42bfbc03e6f3dd17b160e4b5696b2741105fa781fa2b6cf8eb1f3f89f4a0c4e8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09c7cf88bcfe76c5ffb1512ae5db71c1cc
+TAG: 42bfbc03e6f3dd17b160e4b5696b2741d13590e41375b2eed66a2b71a6fc338b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09c7cf88bcfe76c5ffb1512ae5db71c1cc
+TAG: 42bfbc03e6f3dd17b160e4b5696b2741a11ca8f9fdda3c8bdd4ac57a5ae837a4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09c7cf88bcfe76c5ffb1512ae5db71c1cc
+TAG: 42bfbc03e6f3dd17b160e4b5696b274168d3abaadde3f44b7ebe407ebe2a9ad0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09c7cf88bcfe76c5ffb1512ae5db71c1cc
+TAG: 42bfbc03e6f3dd17b160e4b5696b274196ece0c12f28795e95d1b4f67efca7a9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09c7cf88bcfe76c5ffb1512ae5db71c1cc
+TAG: 42bfbc03e6f3dd17b160e4b5696b2741f16bdd9f4ab0427b9a4d47dbf5b030d1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: 7265eea4b391d880c6bc72d3282f663e5551c0a71ca35898047362694ee8f271713c1f8817ca022f454f0c6c7d6efea46b86d79baaa4341843404a416f301640d175a628c7a80fdf1b37d1958b76888c69e42404a406005a31f52a59c308729063c6512864cf59608e45639630c5711ced56adf09840c4aa1d1c195b5f9fca08e6631ee9817a4792012dde00b4fb3bed7bfdd6dbdf6bfe82fab5f8406f783874b2a56607bffa361d773c9a7e5c0dc945e7a2dbfaaa5797551685a4700f6ab397c906630ac018704ad0e8697498fb9c1d5b843d808a5cf3c28015e5021dbea15f548745ed8c38ac250632efc66d0fe0f619b942fa90a41fefc779c8710c83ba586ed6ecbdb5b281003c93846299c86d09c7cf88bcfe76c5ffb1512ae5db71c1cc
+TAG: 42bfbc03e6f3dd17b160e4b5696b27417de2668646b93dcd07c45790b35cc7bb
+NO_SEAL: 01
+FAILS: 01
+
 # DIGEST: f1402641d69b3d67d63e5bd137ba006c70582fc0ac760c7cc005f22b69aead4b
 KEY: 7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b
 NONCE: 8ed1c8e9ba2fd6773e0d0c302a5f47e0
diff --git a/src/crypto/cipher/test/aes_128_gcm_siv_tests.txt b/src/crypto/cipher/test/aes_128_gcm_siv_tests.txt
new file mode 100644
index 0000000..b9e728a
--- /dev/null
+++ b/src/crypto/cipher/test/aes_128_gcm_siv_tests.txt
@@ -0,0 +1,133 @@
+# This is the example from
+# https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-04#section-8
+
+KEY: ee8e1ed9ff2540ae8f2ba9f50bc2f27c
+NONCE: 752abad3e0afb5f434dc4310
+IN: "Hello world"
+AD: "example"
+CT: 5d349ead175ef6b1def6fd
+TAG: 4fbcdeb7e4793f4a1d7e4faa70100af1
+
+# Test vectors from
+# https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-04#appendix-C
+
+KEY: 01000000000000000000000000000000
+NONCE: 030000000000000000000000
+IN: 
+AD: 
+CT: 
+TAG: dc20e2d83f25705bb49e439eca56de25
+
+KEY: 01000000000000000000000000000000
+NONCE: 030000000000000000000000
+IN: 0100000000000000
+AD: 
+CT: b5d839330ac7b786
+TAG: 578782fff6013b815b287c22493a364c
+
+KEY: 01000000000000000000000000000000
+NONCE: 030000000000000000000000
+IN: 010000000000000000000000
+AD: 
+CT: 7323ea61d05932260047d942
+TAG: a4978db357391a0bc4fdec8b0d106639
+
+KEY: 01000000000000000000000000000000
+NONCE: 030000000000000000000000
+IN: 01000000000000000000000000000000
+AD: 
+CT: 743f7c8077ab25f8624e2e948579cf77
+TAG: 303aaf90f6fe21199c6068577437a0c4
+
+KEY: 01000000000000000000000000000000
+NONCE: 030000000000000000000000
+IN: 0100000000000000000000000000000002000000000000000000000000000000
+AD: 
+CT: 84e07e62ba83a6585417245d7ec413a9fe427d6315c09b57ce45f2e3936a9445
+TAG: 1a8e45dcd4578c667cd86847bf6155ff
+
+KEY: 01000000000000000000000000000000
+NONCE: 030000000000000000000000
+IN: 010000000000000000000000000000000200000000000000000000000000000003000000000000000000000000000000
+AD: 
+CT: 3fd24ce1f5a67b75bf2351f181a475c7b800a5b4d3dcf70106b1eea82fa1d64df42bf7226122fa92e17a40eeaac1201b
+TAG: 5e6e311dbf395d35b0fe39c2714388f8
+
+KEY: 01000000000000000000000000000000
+NONCE: 030000000000000000000000
+IN: 01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
+AD: 
+CT: 2433668f1058190f6d43e360f4f35cd8e475127cfca7028ea8ab5c20f7ab2af02516a2bdcbc08d521be37ff28c152bba36697f25b4cd169c6590d1dd39566d3f
+TAG: 8a263dd317aa88d56bdf3936dba75bb8
+
+KEY: 01000000000000000000000000000000
+NONCE: 030000000000000000000000
+IN: 0200000000000000
+AD: 01
+CT: 1e6daba35669f427
+TAG: 3b0a1a2560969cdf790d99759abd1508
+
+KEY: 01000000000000000000000000000000
+NONCE: 030000000000000000000000
+IN: 020000000000000000000000
+AD: 01
+CT: 296c7889fd99f41917f44620
+TAG: 08299c5102745aaa3a0c469fad9e075a
+
+KEY: 01000000000000000000000000000000
+NONCE: 030000000000000000000000
+IN: 02000000000000000000000000000000
+AD: 01
+CT: e2b0c5da79a901c1745f700525cb335b
+TAG: 8f8936ec039e4e4bb97ebd8c4457441f
+
+KEY: 01000000000000000000000000000000
+NONCE: 030000000000000000000000
+IN: 0200000000000000000000000000000003000000000000000000000000000000
+AD: 01
+CT: 620048ef3c1e73e57e02bb8562c416a319e73e4caac8e96a1ecb2933145a1d71
+TAG: e6af6a7f87287da059a71684ed3498e1
+
+KEY: 01000000000000000000000000000000
+NONCE: 030000000000000000000000
+IN: 020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
+AD: 01
+CT: 50c8303ea93925d64090d07bd109dfd9515a5a33431019c17d93465999a8b0053201d723120a8562b838cdff25bf9d1e
+TAG: 6a8cc3865f76897c2e4b245cf31c51f2
+
+KEY: 01000000000000000000000000000000
+NONCE: 030000000000000000000000
+IN: 02000000000000000000000000000000030000000000000000000000000000000400000000000000000000000000000005000000000000000000000000000000
+AD: 01
+CT: 2f5c64059db55ee0fb847ed513003746aca4e61c711b5de2e7a77ffd02da42feec601910d3467bb8b36ebbaebce5fba30d36c95f48a3e7980f0e7ac299332a80
+TAG: cdc46ae475563de037001ef84ae21744
+
+KEY: 01000000000000000000000000000000
+NONCE: 030000000000000000000000
+IN: 02000000
+AD: 010000000000000000000000
+CT: a8fe3e87
+TAG: 07eb1f84fb28f8cb73de8e99e2f48a14
+
+KEY: 01000000000000000000000000000000
+NONCE: 030000000000000000000000
+IN: 0300000000000000000000000000000004000000
+AD: 010000000000000000000000000000000200
+CT: 6bb0fecf5ded9b77f902c7d5da236a4391dd0297
+TAG: 24afc9805e976f451e6d87f6fe106514
+
+KEY: 01000000000000000000000000000000
+NONCE: 030000000000000000000000
+IN: 030000000000000000000000000000000400
+AD: 0100000000000000000000000000000002000000
+CT: 44d0aaf6fb2f1f34add5e8064e83e12a2ada
+TAG: bff9b2ef00fb47920cc72a0c0f13b9fd
+
+# Sample large random test vector.
+
+KEY: d301238025c7ef4fe32fd20cc3ddb1dc
+NONCE: cab44881cefbcae419a122d6
+IN: 71356c78191cf4181cee0532d45d2d4fbbf62b9adf86b0643dd3735191283b1f9fd6a890029a4640294d0ffa9e18bf9da18cea164f87a01a376ec43163c5a612b125ca261e1eaedc03e3105b59e11bbbb8cc6c8247b3e5a0e55ad690c2a77b9f30e3b5202a187a6027097efa66ab0ba824dfc167ae51a581ca5e6c78d10a2e485c61404f0cf4bbb535e0b781ec1cf558e385d3f2d31334852015c402f77e7a4f69e45c88ca3b2950a0232971d80aec4b47c22d70ec2dfd058d5dad5ec4843df0173094053ccf265de85465d32dd36309798d88f7552e2b8a962d42e3744544e753516647fd0686860cdfa52c9a674a461df0a772f05cd814dcd80e8ebc871fa6994e045112178f98dea9f1fbcc3931bd5c3a6ba834ed083bdaad943e896c86c710ce59d49b36b882a24236e792e91351fc2b7a4385ed8d304b0c89e4785660822daecdf938fa237a97a95dec37d89cfc44c5964e31f4a257f996b628e8b0fded09d06e73b864200c7a8973dcc0e84f172940fa443c05dbe3a18e49b05c362adb57c7dcad2c31d3b2588e5931922c02f0eac0c3c7780213a978cd5a0ebcbaa4bdfb6873812e61c36b93d8f5d3b81db3f97f5a5207f274e4b1174f919defc2c63fe5cee5e9e2f3d91d7e726dfadb35bbb28ef01a625a97b502fe8a5ee56a5140668ca3429395440dc75dfb8212827ef9e5b7562f3f57dbf1a9d0e0fcbb2ceaddcbeea4cb2a8ef419cc12b767ed56712d19e431da3c6e48a21c3a5dba1b83f60e7a546000543946b24a8670684283736c230253873c39ed8d884967c2dacb365e55dc40c7f77787c1f050f16376c8220611ecec2887382b8fefa4b8627b0640038732f7ef0aad2877376b5256dd6f770a426749dd2f22f69684340e32548972be0feaab5dbbb0ae0b41460f6b483086b2d3d108e7f80a7cfa559dea483ea3c567cea8b16bb2f3eb29e9917be929e32571c7253b07d967a2c05d7f5b05c56f0dda6936a4d7d7b2e0ab877c99a9fedec49bc5058ffbaea034f7a5d493bf99cf3dea26d39076246e2a0f10d62b29799c04759b534a03b82e6cfff39872b07997a8de7d71ed87f0518581d15d34ccdbf66e6bbace42c56d7e4a7ef5e7e1462bd102fe104488bb4555676f04b4974ec436e6b05f7ea043641934bf02117079eb0323e213217662331d5dd310550a5db9a3a198770238e74da7d6667959956d736cd607c6c5c05eb279f077858101767a613024dfd31f50081ec482a2532276b2ccb272c1a5f00fc041dea0220ce8d51e5c73a7be649dfbaf1c4e75ab2e30cbfc61f3a83d866cc7e9318a4eca8ab9da2f4aea2c8a7e8b2f867adb134c3433f72edf471388fcd804ba316af409474197ade5a1f39d58a7378cd8bfca5a81588f43a05c09e4249a242cfb54a1c5ec70972dfabcbdccc61f305835dfa92a37d59148ad0b74d7
+AD: d1bbfb956faacbfd116bc473b3e0ae09feb224ec760f65b941d99a09eef82dcdd4f8111cfecf1ad4f02e0bdc3a137b9095f922dc3a80d98282827066c201779af4f4267364dcb3eee26a8c9e885b835e7836666dedce8dc912aa328c56bafa3f5746a5c7304cb6805e895885dc520edcea76739db2b426e93ef404b406ede2d57f0131ad6cb1049b18e0bff1bea181b57a3b942b55348a7d2afb056e90f421f5e281c9c3ada60c5891a2e518981704d92c5712991b31a620a3d53811b971469d4fa86e32de261a4679671cfd983c56fe037e9232f06a53aa1eeb2f61caa4f8c1079679ee9fa581ee5eb49842290152655c15bad483b96340a5f1fd67368fda29
+CT: 8dd19cbf232354e78032baaafd52903569381a29110fe1a6bdeeb539149d69e35f1d8efa09c029c21514ce1a040371714b317921228d8718bb979378cfbb53e60b16ba6ffbdedfa0283d9c48fdef183aa6000d05aa1bcf76f478a6de9356726f1645a681ec9cd84716403e354f38b5364f5ca290291c965b82fe4c0d3085d853ccb0588e4c815214e895b46fc2758747559920e0d137d105419e2856d0e0e5bcbb6f7d3d6055bbbcdd29c7a70fc80a00392bd27174c0bc806adfae08e32b308ce8128e4bbae574e96daea0d3676c7ee259bf2a1ee0af0f474401795794cb51d508db5ee02d346a5019a5dcda7532317a41a7147af946d56cb1dcbd53e28feadbd9af9cd3eb96c7bff0611c2f387d95f8caf8b3ca59d02020340630406e597d665b2d2193635f157c51f1b19a1cf4349d1ef227f62812d6cdb0c7dae87647f1ac28c79d643ac0d06781ccc24d626c44e0a3b7a55e3a81f30118703d489b93dd01f94ecae0ac42e1eb7e937f67a38dafe9ec0c5d2bf846acd1536011c02a63153c9e4c0bd4e467e5671e52507a34e3a8dc6de18eb967a54cf63bc049e0c7fe89988c394959ef80f8c23bd93aef9a150ae33a245fe8b6db955193632118e1adfea566620b6dd8ac46a16f86651a8d34719128a07c63123eda805602ce923eb0b945886bd73adfe08beb77b50cbc6fb023f41355d5f1e16f289b9ad86ae89e35c978dfe8b8356f80bb809fe9274553dc094e96d865ee1cad1de31e4c838e5b5564b581369e8ff719e1dd84c3465bff3981bbafc874bb206b5e9f58d175c292613ac4005bdfafd411acda8c94d64b58462d2612b2877c9284b1a88fd55631abe6fa17a7fecf3635256c3e09fe3b7aaf032a411e8b9645def45219de48d58aeec6e239ee211de18051a2a5175a265ce1bab462c7a35c46590f6e1fa543f0ffd3777c564dba9a1bd1124b96fc2d1e7e81e51ecc83f7c6f2ee02b09962bd5f2744e54d58592336515f39a4ccccbfaa8d829259abd0030da76648dab078574638c730bd9c32f8179592029faa9f19adde63fd7e2d671d1c22cbadd8d28d4dbe8d098fa5fbb593884830fe6bb4afd89bd1143f77d194938c71f01fa3323cc23f18bdd486bc7a468bfa6fc0e9bd198ac4fb572f1d94fc3ff7e4860621929d39967e1baf493132188d6978bba043b2264ded093709a224af7358d5aae09667a1b6533e714fd9ab5157e201d7d14e7f559c1e0709faadad5c18ec7144faea92b134f9ac48a97a13d98e4fe0b4c4a66daa0b6adb23d2d17be82da4f590caf6034b2f0c3a846a2740339ec24223e1c024a3955f54b87358b62247afeca011d4830b0e23174965aac60b7f5517f11b23dadc06e4e72e4d89d0f5764e804e840a495d8352dc0bf22ff454a118db981224b73632eeebe5496a2c5a43cf69af0a79e84e1d12398c8024
+TAG: ae3f5d2b7ff538343964febbcd9e919b
diff --git a/src/crypto/cipher/test/aes_128_gcm_tests.txt b/src/crypto/cipher/test/aes_128_gcm_tests.txt
index 0e33c91..eac9aa9 100644
--- a/src/crypto/cipher/test/aes_128_gcm_tests.txt
+++ b/src/crypto/cipher/test/aes_128_gcm_tests.txt
@@ -1,4 +1,4 @@
-# The AES-128-GCM test cases from cipher_test.txt have been merged into this
+# The AES-128-GCM test cases from cipher_tests.txt have been merged into this
 # file.
 
 KEY: d480429666d48b400633921c5407d1d1
diff --git a/src/crypto/cipher/test/aes_128_key_wrap_tests.txt b/src/crypto/cipher/test/aes_128_key_wrap_tests.txt
deleted file mode 100644
index 561ec90..0000000
--- a/src/crypto/cipher/test/aes_128_key_wrap_tests.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-# These test vectors have been taken from
-# http://csrc.nist.gov/groups/ST/toolkit/documents/kms/key-wrap.pdf
-
-KEY: 000102030405060708090A0B0C0D0E0F
-NONCE:
-IN: 00112233445566778899AABBCCDDEEFF
-AD:
-CT: 1FA68B0A8112B447AEF34BD8FB5A7B82
-TAG: 9D3E862371D2CFE5
diff --git a/src/crypto/cipher/test/aes_256_cbc_sha1_ssl3_tests.txt b/src/crypto/cipher/test/aes_256_cbc_sha1_ssl3_tests.txt
index a644168..9b921aa 100644
--- a/src/crypto/cipher/test/aes_256_cbc_sha1_ssl3_tests.txt
+++ b/src/crypto/cipher/test/aes_256_cbc_sha1_ssl3_tests.txt
@@ -24,7 +24,7 @@
 IN: 936a91d0b5
 AD: d2c0267218cb7090c6
 CT: c38859c09150f4c2dcbd409a
-TAG: 6ff0d4d77699ab8772483a69168bd80c869b5f30
+TAG: 6ff0d4d79db071e54d654ad6d2781978de4e88d0
 NO_SEAL: 01
 
 # Test with no padding.
@@ -38,6 +38,2589 @@
 NO_SEAL: 01
 FAILS: 01
 
+# Test with maximal padding.
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a4f8ad2cfceec3703d4cb0591df6964b496c6cf7d5499209352e513f6
+TAG: 4d5d3ece8d68423655f04792c0d0e9d10ecca8b7
+NO_SEAL: 01
+FAILS: 01
+
+# Test if the unpadded input is too short for a MAC, but not publicly so.
+# DIGEST: 095a8f557f75cba8e2452ddf97c053904b48827f
+KEY: 18cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e03744
+NONCE: 
+IN: 
+AD: 936a91d0b5d2c02672
+CT: 01cb4c7831eafe39321af304205409516797a424e14c144784645a6d67aea6e8185f5ef2f93fb6022900e885795e8af770cdd182fd5b56fff96f8b567575573a62f78c40d0553c2f00ea97bad8320813753365d10ee7fde79a7a99279acfcd974083cc8138ff704341f2fbdf1c3e5cfc81874e9e47ff457828fa0a399ea5eff04926eea2bb8f722bbf771189ac0aa317e1815abb63759eba9793151183ad599a89a08de1a2e2b8e679774f646270bd84122ac771b7261e3d9d60bc997c88a2afcc75c9abf697f1da0d71007214819d6d53e43b94e088729cdff13aa99da234cedbd107c1fdcf04c443740096
+TAG: 5e3d9bd635a180ca154797679253ae4586fb5c5c
+NO_SEAL: 01
+FAILS: 01
+
+# Test that each byte of incorrect padding is noticed.
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140c4261b78aba87b8de2f7b806c27b840dfdddd9d1b7bea5174b5e3d5d4d25fc03def5221839970193f31cfe2aaed4dac3ac776b884c0f777898826a60f457361d6f8278bc9ab0b1d7d78d657a21a56d7cf3bd585a35cda0aa69a6dd4d1b2a146cc285a3c91dbc768445ea52ec523ced412797adbef21c2332914d9034ae32e2861a915f7470f7b53a39be3402b1f52b51e591171180a4bb2ba86d5b3845e3871c82e0231ec2b663d8c6511cab50bb1e14f3611ba22b7e0315839fa6e69ca764c27d03ee5ccfd9ab7974c031af682a6805d477c9508922b1edd4f23824c96e17d520ed7f4d02aeb8b07ef72911d
+TAG: c83251be15086646c8b8091ed08feeec8ea62c64
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140c1aca8db430b065919ffd1c460420e20d2dc49a469e762c608ef318536414438d8ece5e6840ce3d0e3403a1f0d0a133a1b4a513a83fbb1a40977ce17609f9e87b3f272e1d91e0ae563a448c297734409c09190ca68e08104f35d3934b8da8eac4658bc0aa972784b821dc313c91d3d9d84936da3e3e38587617381e69c6440fb35285a673efc015cb408a2dde4da9c9c3530a8ac4731e70bbd0eea475bbcc609184e6d046c2d22c2df7a65c2234e6928babeb3e0872034617c4874be64870b2056350f2024d19e8c1c11355d937ff7f6eef244ec2c3cb945c2cdac31de38f6b401a66d978447daeefcaf720ab
+TAG: ec96c998ef148da5e9c95c3869347e52ab84866f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140c993303ba86787591db5a2c50f621b30bf214c922d24182ebca64b0c9498fa95e20b0148f9b95ca04c147e7d58607eeeba8487eb2871c2d75eb9179e79058a5fad294319ac2f59394bcf56d54a6c7630424e0449bccead5adaff2ec272f67e0c461101a76789a839d14d8dc2d3754a232b210a858f7b588b985df75f61f224347951dec2553018dab94fedff927ebec354fee5aa549f30b5057f987b7635e47ef87f6e24adf9ff1313c9f4b8829318623cd6a74d9e9ac2bdc8b1a183dfb2f66115b04d403dddde68bbde2877cc9cb83a35d950b1b4aa194f3d34b863a6b41d52cbfcf57eddad2a57bd10eda61
+TAG: 018c8e3ff575441c55725d3020073508df5f962a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140c3868d6d42a5b7662ab0fae8f412d5cf262737850ce1b9689bdac524f56af5d3a0840170a5e4e95a12edd6eeb36c94b0ac3b271cceaa11af8626af6241ec8fcdacc0505b148dfa83181b8fff2d99417008f3752d7b144543d4042c44612039f5c65c9646bd75f8007e5f867c0a28f74796591a47193ea7dcf885080f4a5c378b70ad9c86cabb24216f505d66cf4973d525ff535c40070a38df42935920e2a5c5b414cef6902046dff4f8a06a549286b59946673fe399a21f8760f18d2c08ed95b96552f81043412b2a5349a099bf7eba9846d888dcc044de910f92a4cbf8e02c7b3946d35b2821be41ff56ac7
+TAG: 0f0d5c3e91f94165353d4f3cd61491e468efc91d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140c3c5960ed36272494da48efd35b1656093e76bd156ea761a931355914ed6c0a390d97072ff71ae5d8c8a4f28a0c507f5332daab12b7a0ae0744ec71b53fd9c58c29f9452f15e1adc21b6af38f9ad7d87a79ac6b2823e6530691118af5ae0cf255db7d3c3b05bf9059419c09eb11692679adbc5beb000ef7af9dfc4c429dc052fe7df1d7c7d24aa520d783ee8bbe55b6314d1c8118818eeb97957d19d022e3d7b10c10af13c58ffbb5cf76fe6a2f198a73337954d90ccf7371021958addb62351bef2f733a410f0819246c32fd88d674cdfa994d144a2603a4a92cb1b6e0ff23d9ff067c02fd43f872fa80e232
+TAG: 377f6fb3471d6282cda5686076bc45fd8a62ce99
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140c4cc0f30647410a22b8830e1fb76c5167d215e8c2d411df537b743d482cc939413dffc60c720b373d4e16097a545b7b988b2182884b0f5ef963f67574be4dac8de88fa0686f484fede78f8b67c8bae64972f37c65bd40855387e0c5571efacd88b3bddb445302f6564afef4a31854418b75ca04146a53c2e2853d4849b3cb45ab2ea3bdccca6c307734753e168d57cef80ff85c994686b305abf582047ced51428f5e4645f2de1874f14cf0aac7050f9db71cbbf85f87440ce95a4027ee2095e5996fdbe9fed378ffcc1c1b60cadb7f330a612a13ac0267ece5888bf2aa346a338cce9560f8f224e2b2fc5e0d
+TAG: 17949d11cf58c2ed613d9421d4b34a312d92cee6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140c71e759906fbb3f487805c414abb50edd923cc7aaa494473e97643afbdc143ad968e0e4213654fa5952be0ed1dbc64fe2ae1d75e47f3e6824ab44b13dcf720b37b11e32226a5a15dd12e5b13fa0d9b8080eafb1543d8dc40fa5af0bd036606ace855bf08a6014fd9a28f936b08c6a19e6968fbb6ca9ccf69364da8b7a5bcf3e8366abb8ebccbf870dca228339cf4677683034ff73e87e4b8f35fe0a5f46d188378df4d93f635160328d008a16cf3316fb94bba76f15a3a84103a249311d1a80e4311935ee847d9dce3337b0778da2366167d12f7e750e886d7e95dedd6ab38f9f101411d853b75fe895af4001
+TAG: cb6db0ed6895e62fcdf3f31004563ce22a2bd02a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140c83983b0af789af16cfa705338595e83f924a4f02e233eb7b0dea0f4800604104bc5c76247f67fa513d112ae88699769269e7b4060b6566aa4493a754655c4d944c147b9ff139ae32159d80ff6c371b968f36d52e696c926a720ac12c3384e0fad91b2fceff69c290b2236e2de35964b38c9ac2c3c63d02e596a775c184a51340a99f326cf2fc64f9ab94081736aacf0e5311042c5bd8e2edc20bce0c8852b198928400da0939e556e59a00457e00f07a06023152a4cadb48af08949dd2a29e90de7356a4a53d88586899b9eba224553330eec05affbe4fb52c28bd2fd40593882c643e6eaa83265c8f2c9231
+TAG: 26945eeb7189e1c8205baff8b9a1c9dd6272b3b2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140ca0f7c239089bd9506395bd67c86840d32707980db6ec04de3c6dc23ce99f5561fe1fe404b85370f151cf740253fcf4c89ac3d7b62403dfda272ac83ed3f590aab6b1feda1a1a40440bbb705473420b015df8bc06cd2c45d6b02918bac2774428c9c53fe144cf84cabd0df25546b4bd6fba72eb5fab9705c6b34c3118555a001b20f1c273557e2515ec973730f2928693d542e54503e895892657966238e21aede773d45f2f0ee76827ba11b75979e36aac5bb47e9d473b247659405ee7410ff3fa0ede51128d62f398ce36c81372440e5d55d9c5ec3c6c6320ff276b8338e99422ea7a4e154867b9df014fc1
+TAG: 8c785098e411d1699b5870c034825bc0aa01dfcb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140c6df47061b17a3937c36e21118d48929eda865dd66ad5694644385289d90b1d53bff71af62473af8c8cb0d2f6ecbee14c881b54127e8d1bbb2ac72bb3d63f2fc1d3564e44eb2c7877eec6a917b2edc517380a402a7d37c737a3bfd5cf05d35e16730df821d283876e40c4b2839efb2f23a28e099755a98bf942d1ac2a2f2787a1cf3e1c585ff3bc2e0bf40f10b41f4cfa872b20a1b72ec749c3587dad0133f9d2ab8422d999adf086cb4d31b69849861f65eda2771522cea3876b8b8ba1ffa1f1872dda4a9d7a21cfa7381e05673445a6ecad072a66a1126e8d62899bfe59063762961c6a5f4c4ae3d029d3c0
+TAG: 5933785908efde6d9b6e2ee9449ca15ac434a238
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140c2bc0da1adba8ca306e8f6eed79e8910d79d2bd15e2f56d66354e7d238c9240f0a25618a976c374b8d443add76c3efaf1b8c6d3befced354fc46dc07ce2b1a4954615d904968fe9ba94589e10696a63ecdb90f06ec458c303dc6dd8d256a8f50d0261713eec1fa4a5e7e2846024a00d7ace23a38bbc9fb5ce127f86725dc1ff7ebb88b5222e919ec461c963d86ae3768a8dc9d62a69af51d4ea85ad378317b800e9532b9f6e8e6af1a21988f1e45a96e43bd387caece181a44f0a83f17535f016ebba301a0a78f4042713278e936f092028429779d47bd23fff9fbe38828c4e013da33d2efeaa91c8cc888866
+TAG: d721f287b4ddfcaa60da436f8eb677c2a6ae615d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140c424e200a6800c3020c9728eaf7483e31769360fb1f5c299e2473234bb9b4d4e2e63bfa39ac273fb3ef2cfd4fa8ff634b03c9948698e9c69c9d92e35c2dcb4282121809b0f9ac0a8a393603b77531c7fdc9d43a8c2747c36c2137ad59d44a4d515c176bca985c8b482e484a6d815935fa057faf144ae52e361f1e1e86a1b4ed997ba071a049f8dfc62fe55e98bcfb4beab27ba64f17a3ac80c7679fd6e156cbb28233f4439a96223c1ade6d1d31c69ec3da94f4c966fcde28d6520aebc4421c0be3ea263256c8ccbd1ea900ec3414ca2caa9388478db0317b18f1c2c5f4fd748f3b31d9dda7fa81a35f283301
+TAG: 2679621568a9f627685c1f19af05b733c9b08ae5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140c638ff6eea0408a9d7f7d7ee0faa4f730246b7b92869e13e40947a514ddc29c267732d1366aba12145718e70a07ea06e22e43e815c04c449b5313f3bb5ab0d1e2eca42ce029c34f69ebbcc4c3708cae4b2279f20225b816b3a891f4dec8d9d11fcefa71594b577be389589ca2f6e3414a4e5202c97ecc4b702a847c8d333cac376bc0509d9b3970249f42263726f2c36cf16c30c5850c08d79bdda35b504097b790d9141202f07f0aee1e26c8d36cb7ccd84b761e4c823a9800fe978b36d94b54afe911ccbfb178cf5394905e6c2bf02554eee0fb8d512dec96b5262c9671326b7e1010dca2048575b1496f60
+TAG: 16747463ebf264bfafb9662473d6a824003885c8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140c40c637eefee4a3dfe7e01aa2369987d6b5990c0388343b44f7135624dd92e5bb2e61be13ea2c1dd3c56b9c4cb8304092268a6c9913ad0d80ad7516f14548b32dbd64593a1899f8b9fe4309d71b1c163e249e43ac7cbe1414d289c9ff74516c6684e63e25030f9c0a60852f0864ef270d91491d834699e5e2892860df6a685089dd578463f7af0917ca2959803256027f166553707242d0eba0861bfca7d34003fe99e6d86b6755906f9e608bbf23086a4599fcf5062f693079e5ff2b8dc0558c8d744e479ec07a975c20fc6fad584579bece0089e10dc1cbf918def720d95ff94435a34d8eb14f1f162a2b18
+TAG: 19f13dd3bfa64d562a5685ff6909c1583068e076
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cc9903b53737d2c75fbe2e97eff446afd6af51acc48a56178e32115da223f52c5ed4e571945036a18d798e75e3d1679c5c646497fd685992db71cfc3ffdaead5e7debc370cd694f8e05501b7db4fe71804474323a93bbf75770c41d902688a4abc638c17f2de41c7e7bda7279e2cf20836b0b0767eb237a726be5c8b8f5d71918eee8e7810876c10346dd5f827048ff5294ccf329e8ec17b70f3453c4963586852458dfc7330ff38eddf188ee8135242fc767d898a6bd91874af2955ba41eed563047f4f9e740b04d6ef26e06c6aa0f375534359d3a1b8cc0ea0c1fe55a86d6f6c76bdeadb263edcd4e524bc7
+TAG: bfcf006b3e5364d18556e6ccbec833f8888f962f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140c5ee8d13d439b3b1d269e1d5879d1bd2fe19d8c15b54e5c910b5bc2cb9be4aa75e02c3648fd28fcfa87b698025e282902c3018b1743fdac8ca4c0b4fc359c717b47b7ead54880c603fe6973721036cc1844f96cdb7777a1890dfdda95aa5fa75868fb40aebebfa05def06bc52443cea0f02da1cb7f32fec6102b213488d84e4dd1e5f21d01b7de35cf768793bf807d725285d89d9522f534bffe3dfb545be8e2793e93b581ec5135c67f5f7254bf496d722a96f4747b6fcfb436fc98dfd7141f11b20856a7e01514c5a029239860dc358872f5d090f1cbf462f45e41aa93e333c3141c491232f2e59e41fc434
+TAG: 3ddec2c9a2473e6a696d782e436fa1a2484b12bb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa85abfededb19cb8c09a8498080c2d8d98d69bf38d7b4a9767bc20da14b0c95671f589a40170acfb26a0800b4e0b8bc507206a22ee505a8f4410c91a373e775f8fd1b6a5b7dca8900dabb653efaa8391166b436768cd79f9983962b3a76c94e0aff8f0b91408dd429b86668506e55c34dcf453027eb36d91655dce1a416ec340fc263381228edb7de4093b76e0ef6fb73a82919a93d7eaf6754fd0be54a7f164dcd208aeac9a39fdc5a1a61d5d36af83e84ae4764e2a1fcdd1aeaf267dcdee61964ccd74a8b537e8f6d0a428cb26d4be016ca2c3255b8e1972e66facb90
+TAG: aa9c24a714f329a1802bd3fa5adef23639f2b7f2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8539f062e12c26b23c954b3f013f9980358a953fb5abe2269b253a99a28597706713fc3917638a8ce20e9a167aa43f1464d04e8d44a27596f8fa98d7cef518b89122faf38d5ebed188bb69e9c3c05626a8a5f509ea8568b5c4b89bd7cf2ba9b55aec8bf68d1ce09359ed549e5969aa53f52b57aff688a87af913e692b104da9ab1c82719693a9bd75c8e0dfac6994d1d548ce946c9f584f552c5394d949f70ad46f94c0b3536cb471ea818ff7a929eb211319f261f967861cab37c51815f4f8df5e9137e84d63be04aaa02bf9a3515a731050ced79ab4b27d9d9f694fc
+TAG: e0daccfe144fa006545a0ad2fe145c6b09cb2260
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa853c74886a342a11f2af7833849a71f4b8e88487f8f8be7e0c0f2cb1ffc430146d8973240f22a44d49f24f669c59d19d1a3036dad4e346fbf3c85101476650c55c859bd6e9e3c76637f3038e36def46a1a1dbbea0649cc04a124c44625e6448d029f9da63f1c00501bda23b58742e914c6336beb3aca2383371e4a590fd040aac505cd64b06a6e786f6f5cb7a968d3011b5415f173777f80095e54b858e174432e35367d49a91dd319411090271d18ce5fa91f21a5e69315f006821796d0112030f21c79936b877dcf5183e825bcb1faef4359f09c6e7eb2c66ea3459a
+TAG: 668d94993176d39f3503d46e2a21a6be5db5b761
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa857749eafd062802585c441d226448c673d184ca45915ea1d4f0008f59b2ffbdcfaa215f481c178e9ab3514cc816cd6cbdb9c6d46c59ab5da9969d8f11f7bda6d8ad0bda48600f75bc6c8ccebf80be3ac92403bce6b11b448dbc9c2b92aac98104b3ca000c292a670a9b581912bed743cc7d451c506a7fae57b37b4cd1930e81b9d90cabcb4e6c90e92e753fe629f4f5a030a45ab8d3556f5f31ae5b18b6e91bce3c07e12f8168d62f096a29c940c87ced3fe8506c99e35c0d1f8e30278c719d30871fdc2b4bafc1041dd91351e06974b341925a7f9812d4274ba57e3c
+TAG: 140affad33fdbee1418eb783df61ce4c4ad62993
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa853a302896d8441516d105271da0c8c366cf56cd7d3f015c0bec4faef4e37bd2b99603f4a73c25a921cb53d8b922034e175802b3559a6669bb2bb65d0159e1c6e7ca32cdf3d1b3a6f0ee700240abbec6ee701c07cdc730185d1b93c8dfef1ede6c773fb6139674649f3d0e15dde76f63b067289cbcd12ad023ec0af959bbca308548602401ef3b477cb0dee2d29bfa5ad81d2e1dbe176a856feacc536234a664087c714ec8967f3836986f4e153fec38efbf40f03882720431df01d6ffecfd56bfe4c96bbca83c1e71a196c251c56e81b6b43e25b41c6799e77647f484
+TAG: 182bc2e781e4ccad158c53f4870d2a26de380bc5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa858816438c2fef1a90d6c9fcca13899ab4e248ab8e02ed488387bf7dfe60fc971dcc3974373800b73f1aacca3c1a11b465d874ce9653140ea869f6a767d6a22d677596ec374383298c8151fa7a2f2a0a4832b7a318d07ad52f55ac7e913487a1161a0e6f5faf2745b2e79032c581bd819ddf6c481b8c5ba8bfccfad5ef2d1703fab19ae08bba643cc1b92b0785396acbefcd0f09cdcbd544eb704dec67367ed2c8c7ec10c84db367f3ee08a1d5e2ea12e90e6f7146a1e11d2199168f1c81d02570d67a1771a13acc36a90532e8c2120e89c99115b15386d994954c2dd8
+TAG: 01391bfcb7f8a02e17f496a131a663c2d0a467cb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa854c387af5b7bb7495f001732fcb6af0ac13d56b53c2088ab51e440a0e49cfe0ecca059c61282abed5c12b857fa6930a655563ff1e38273867cb8f0210c9d775fe44306fddd6a1953e0a07e55087f7fa8a7e065b866e9eacde718883a223b7597392abe69089364d747249d89ce1acc13ed4fc49d1587a1b78b6ccfd88cb0eefe43d17160c23e02653a50d0eb3d536373fc9a807acd86afeb3c8937cb56c69e4748b561cf9e31991f82f4680c8b9fa4218cd9e72cfacc08b8ebf53f92b1cd97f64484b7f6a709362fa92f1e807794fcb8bf9e8ca65b914a2b7557cadc4
+TAG: 80afab30f23cd19bf542d9158116eb478f5da4ae
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa85721ab87ebac44a5e52aeac9a51248b572ceb65fcb6b1ab725d27bfd445c8eb80a4bdec280a5fc25593fa41bd2ed420912e2f24d151d8fe9c343c7ac91171ccabc8a1db53770bd494dd4949ccbdc83680eaef5f283ea9826a9e843bf08609f76ccfc4f0f98163dd37675257d4f54ad3a3229eea61e68f3d2c1127a3c01c54b6bfd452267a88c0b766a3ec93e30ecc7a33cd2ab8cb0a9cb76703745c6fd86a7b7b6f0e46ed85d3e4fe7be11e7ad9462f8daf031bfc8029f22ddcb0d6a3b7a7dd673ae6d6c44ee729601808bde47fa1b8ab6f26188d561682679b16d1ad
+TAG: a3ac2327487375d330c3558a39e3dc7367a21598
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa853968b8dc0a2416b7f679df807b644c790086ef88c01d47168815f31eedcbc5f226feabd20fff1c6c154a1d16ad07b5d38551579db3981eb22864d7c8ae819487552d3fd27020515c9b059a0a5fbeb1efe65761c7513c3a53019f68fdf8686e715d530f13840a729089af280d7c63fae70c4ca8c3be6f1b7af9290d0461411ec23e37b03ba58190055b160be1ee266d08f91a7cc7514cfd1a6dd50b6e616be98a7d673cbdeff66c43419a376f4279a350681649102edec536180cb77d3abd76a5305528f6b7a12837619f44fcbe874e44ca0c45195d26c7f94007f4e6
+TAG: 63148c3fd6c2d3c553f257fbbebc7619c7a50f85
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa85d73523e687e7b20240bab89fc7dd66dfbfda687ab2734b7e14834fb6dde1d8760739780c69657638a682e201a4707d929887188b67c0472a16a364ae3a6ed3fd4b6756ff1acabee88e003366ba020ec9740d6403ef6187f4339b02d824f160a87832887a9f09768b459ffde6d20e074dc06388a0d392bb996c6b72559bc1b26ce073cf6a71cfe4c5fe2d697b12a422b8aa844221661b4dc0180c145523237dbfef30cf141e8223e50e9a7e37f557b786b7b4c56f3cc70bc4e70ac542f74e9a90eda801cbc5e10577bce69a081c0d53cc97ff81efdf9d165aaef39cf2
+TAG: e7761ed9d220a214966afe93794991b7de1c3fb9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa85eac325c55e1e512c220b8e6e5934ff71e3ab251f65873f9d3d95de0bca3db2dd30dd92521d659889f943147a563a6f7a5be956bfb6dc96e849549373b81829e321045860a46d820a2d61019549b10d3d502b9df8cb1bfc91a25fb5700c335e90a530fcd9d011dcb55e2af7d2fccf593f6b4f968e072c2f31c9b748477c7751d5de64dbdc850a73f8b4ba7d5a50700ab84f6289c5ac8120c89043eeb29775d777f86ec8dd48e10c90c3f316eca853f54142d6e1bd3c5fcb58e5c442f589eb7da884a889d75efe6a6c68990c5a5c518d9dad74ad71adf46a6e18ebf1c9
+TAG: cc28321c82f286d44f8ad187b6ba363911e43871
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8580a2090dbe6dab99de0f7a5baab85b6e6f3869a20e537509786427ec14eb7ffb96ab7b4ebfcd6e2c91c509416f8eee0101336272949df659cac6566c17a56ec39f2dbacd0795cbf35d571d6f24e6c9f7e77a9e410806fa495cd10e55715e7eb3679930afe32f89caa836a4f2f4af9ab002e2eaf460419edf3ced91c2f305baf88e1cd3fc144c46c7b26cd60cd0e069bc0384bc96b3fb31733661a6cf16d742e07e9db373f4399233f6144f59dd153a1518dd70581ca9d4bbe6027ac040bf7e67655e03acbb104f2554b384ca2939161ae98e8848ccd0bc414149d457
+TAG: 37e0e96695354313145f0d8b7f9b595b886da85d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa85d12f8d0d7b1b3333c85fc1b74f1d7564fdf1073a2c038922ea27cc099f7a1ffdfe3f742c2a71fba35616ee59877b3d62704f7bc3f258a006f57d09181374dfa33a1ed677196a9e34fc17af5c5fe609624464df5442903861d0c5047e4811a6029e4b9d822e21809f5a4a96778f11bdecfc9a7abff83fe5649f004800bc3b2545173e8fed490e4e7eef490384615fe02e0bc4e1adddde3171ca4a02ba80eb52933471b0463b20249362c46e9d6b8aafedd9393b9e8f6cfcf902490d7bacc357aaa3d752e7ea4aa70033adefa6bfa7302786f3945096857093951db489
+TAG: 8f35ecc1677697d647a56874b098317c77892354
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa857bad5cbade98840a906cdd3e0638a6dcd6119c988da1bf2e1949e17bfe8369c3781600f11741aed3665e4d63211e2324b20fc7d765a82537505bda9c511cfdebb1000a485cdb022690029f32d51711377ae290b8cf453e5e19d32e56101f259c5266a168099e6e5b1f381e4a1077b927befd3654b82a5d3de88f84e0559d9fd85bc3cf4937378c9258f0bdc5c28c95c252ad27e62d2c79541ae522c773dedbc259fea124c958ed43982ee3f7ca8ee2e4de0c5932524a3eda187a8f4cd7797d2013e132c66358b667d9c47a5c1aeebd266ebf1646c8c2abe086bb06f4
+TAG: fd1e9d10b6e577146b8de8d476fab5e5b470a27e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa859a9a423e5303e54ae8ba4760ec5f8484a43af0e31d384c92c4e266c470c95e13711b2800320720b81cef2af3708daa270ff2fcc782d914e16574f8cf9a2d39e8880b94c18ef0e670837b639abef627020a04fdba87735c35a72af998cf90586a2f538a5ce720f3af8855aa438747ce9e0e9a82ff1f6fc5366aa3f2eff7735c59f380d32f4be67c5983fec7f406d174c1f75364f4521f0b7cd6e398f78e983ca9c42bda026b8b6cf2ec28fa2568be078d9b1dd162f5610c2964b2ab7c1f6bcb3482b0c0fd9e1e3fc3b0b67f661cb61835e6075c5ec532093d5f80634e
+TAG: b79238a5db2a562f0c6f14ea9053ac7c278bc306
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa851e62ca8230d38efc48b436ca46cf2eee3f6ed964fae6716fe2d8a6eb55907a024d68ea5645d7ef228d9feb88e67347d197da4c12efec718b9db26151f0b515a2b993442b448c13fc9593d8a40dcbaebb9c9941464e2405c5d55dae4711a83c5a0e82e4aa1d514f5909b025ea622f876d090dcff54c2282ca2b66a163ba7260d361c2f3e670422cf245a5f94f10a314dd8a9daf8327df73871be1cfed49c51240312b6ae6c371cc01400c191e15a71f39e44cf01a4a3b457e9111ed3cf4b9f767cb11779c39e03da88e512755508ac8086c89e3ae5e9f7440ae59586e
+TAG: 58aa008b354507950da17e984a5479eb1122f2b9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c91b676a3080e40d04492c10a4f52e09009b9ec418b0b0f0a4efa73177098b81a33eacacdef63c380e678abe57e781f02709c00d50cd3d04d0b11da9ecaad5ab7f873707531c352237c0ef1da248dcd80633b9d665cea86cb255b81bd9e5d83232fd3228a85d5ecd0c1c922e824d2bffe9587dda6235236f3debb748e1a08adfc21253e6e6ea98bbfafd27be0a25b9be140142e4710b9692819b69628eea7c5b13d3a37f1d333a0feb19b0b63e01d9df4bd0da5745b2dbc82a9bff573e18c5cd4a1b387fd0fd781dda61002976
+TAG: 409631c06cddc616de68fc119b0e3b6b44a302b0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c92854c96193e53b62eb2306a8f7444807d204a257bab8c38cac2e9ee2fd0a0e41e3e89af77a225715c5faff1057e01e5fa8be52a580d4faad9f52c4fcd2f133e4a03a3a44e33984da69b1dc07cf1d82a09a2702fb00d6237f2eb6ea95bdee12237880267462ab3173468d1b4211d75079fca42c89bfba4a9c47f47be0f6e18296fa6d85d203be7bcc2d5b1f567c3a174e71c814c48987c71a88492cfc65dced1a73b729945cbf1fbdc15edb064f9007cb94d6aa160945e4be277e2c77bb9735f2a41c2b5554cdc9a28e00cfab
+TAG: 612ac63beba48bea97a6423e5d6b8f55903b0727
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c90a746ed2fd69369109e17bf2243da269c124553a8da952d93eb0c675b0840f688f4701e20918183f60856488df88f6b8f9af8724de31fc6ff0f166cea285441bc7b41e294083e77ed24d63e20194eab8b74cac1d85e8f65def0988ba05d3ea2d2efe8234f0c6171b13e7e21d5542c199006f2193ae48112a90b27357ae3df1c33718dd9685ffb09660a2ecda941b8470b08515392e158e234721b66dce41dcb549dbec5ad4b8f4c896e76abb502cc2284a17e5f12b3b2eba6a029f7f86e5849329ace80cdf48f16aaca396d2
+TAG: a84b0d68f0ffda08a9544439c88df96807ecefdc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9a2fe524375e07c78d3c7b6648228c098172efc56d2a8069fc7982dffe9cf65f6c9c700e8d2b2b1b108c29aaadde78330f3f892413d1b7c13cb4b26b22ecb2bdaa97ab508217e70f9921cd5613bf9030bb0febbed1a7eacb462cc7c45e6bbf7587e4ac082321380f9375a2c4ecd4b5ddb4ca2009387c51f74fd1b217f739994d2cb38e6bfc57c547453a1367b0f8ad339bca03966f12399d2f6e51b9c72ecb55e3d6bcc68d7c9feff233923859576b9569e142f01c9a4b29bbdb242d618866d611be637bb409d5276f8570283
+TAG: d3b8321515a3fe49c0bc172de17d2f051c7dce4e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c960943899c9e58658fe715b5784109e9d27a52b64a318fa3e6ae46035fa9fc15461c8656702c4842076a96de00286c1ffdddd3e18bdec4df832289b92cde41a38c7760135765fbf72e3c484f5ef4fecccaac1a302aee7747d1b03954f0a3dfde2c7a7e167c66d5c01bd57cf46ec0d5163f4fc488cf1b80030587ac222ccf26f4afbe885c66c956959f33322933479347156629db78cf510d3c5bf63e1b39b9f44eb4a08a255b5f4901d52b845de0106c3bb01df0ce100532bdc65d3f210bc38544f439d292d1f7ac856d249f8
+TAG: 789a5061389c1c0670be7938627c6fb5636d07b1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c95217c937e45545533ce254b170ac37ddc5736913e8e32413e4ddcf51bdb26f2b95bff8b06be0f80a259557c9215321f245ab4d246b5b95cb52cc2cbc641ba9d3d7bd74d09e8ffe84c4c48c5ecd6eb1580a39da40aad445a3834e75f87a1b0f0e7c19af9202c61a242ea1d00000669e980da9d94f685fde386cab33bd08e761b87d8bb811ef53ec29ae4317c69bd2ed9e0fc12587ffbe996ac6a707b955a6095945968d1e38bb646f75fb7e9ba3318b7f0af83ff3818fab69a3f524ecfcc6a3656b291c06a39b8a4a23b3816a
+TAG: eafe5b511480c7888fe9f800da1e5364e5820164
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c93e9a9c0af49b367e0d1276a580b8f6e3790df471fcd9a2a8bf6d684259ba8bcf1e5d0f5779d780bb90be7d67f533f5b4dd5bc7823a8c9002b2cc2b42ceaa976bc694b924cf7f17daa7147268c13ef4f111c7cdee6ca21ac9cec21569ba65020b325b2006aa7a11e904f42d9954e6afa3785d26f84fc5227cddf878ad49a476d472730324b86af0b364e19948222af0d3e270e4d3adeccd1f9db0439e18d55197604a711f149610a3b6f11fe318eeef76a85ca6968499ebff42e0e5f4a99e28e0a12b24e5254c5fda4bced527
+TAG: 1ae5dc5b3175a177633ed6944f4955272a4cf9b6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c923ec1c43c668b209c68b769fced22c922be2f307d0eb0e9636ac3e3f08a7b0992b4897af050914511331289d19e5dd5fc6275a02fadb2f5b7d2698af07810b22081ca8d31b5f1fd9c18b058801d7f16b7240a66070f247b48e0f009b01b0872bdd2172710349b803d34fb5aaed7848dbf2575980cfa4d59a043516b672afe675ab1bf12943d7a67f1d47aaa22d97d1492ecac690c77f1dd7273edbda80b7906c142a91d00684a6166a3a697f81100e28f37040b0a724e8c70b2ca22afabe2c9a36678bfe9eb23ec5c9b5c41e
+TAG: 42b14b60ea88db00a3897b9a5c6443b4e4773bff
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c97813809bd8d70a21d928b8f88e651ec5a03b2839fbc12165223b10ca27d0c35cc6cd2d0a915634bf6e556e2d4cc4f5d3621831ed8ad012e5b07dfe232f63e750a97b4b1e31c09fd6221e451a23ae8cc1d91e39b6ef1c7b7af8f27a3fbdfd42fc498aac9a620a9dc6a10c262270a6c8c5e52f111b8a29be927d455a70d705f83f12c99d4111927bc3429c6ece7ae95fd5e8bacaa7a1f0bd2dbcb7748f146b8ba58eeb6ddc83f10c5d3b4d6724ce4ffb436ff55fc9b5f5ec949ccffc496a566a4f9ff5922974f739e2d384754c
+TAG: 66af2878c84d5d4b66b0d496d3a2830537331880
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9b157ea41710b6ef97b0244bd87857b51d3861a95a38fedfe948ec0f798398255ee1f9eb87cebd07c37a936a3dd8a7de72401797b5fa75c16fbd276eda97a1821977b68d8f713d66807417dc7e263073fef2de67166f4e47f0291f9d595bb1c5e3adc60d668a151f8f8596204ddb160b6ffb82a01c03d2b63857c820ac2cf0e82eb3ddea88c4746d7624ab80ca3baccdcd8b520f245e0251c005b5ab670e64174e7670f02d52ed632bf381f0afca19759647977c2deb731d2689be018af5c9acf5a284573d7b9e8513d6fbdbf
+TAG: 0c70f8e82910dfc8de3400a8924871601bd8903e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c930aa7606cf52ed72451e41890f387d4eabf75d75fa38bd9ba4d3cc132658383b7672472b1e4f0be83427b0f4d47a54e262ddc2abd5e9b8b9b2428ba9c6ae1bdae313896ee3e2f3417f104dc604a78bca29ed6af2e7cedc79e8f15db891afb14a78921b00a12cfc445adb733b91028e646a9b5302ea3e6e75393865a6ef9721a1330307179cd9f804017bba068f1c0dd5a12bbc307260ebf957f8ccf1a9d3aeb4f06943978a910ad62d8b7f0baa818e56eb138d1cbe80eb50f4cb2fcdf5113356321b62177f6fcf6f36b0f30a
+TAG: e68ee6600775ac3a5a72e2b38140062df94583f0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9e894708b06fabc5ab286f86b36d37f039643ca979c712bab7b08e7d6991c4effb5968864d584f20339733148cc737de4bbe61f14b8aceb03c219ca4d4fa3ba9ae4f81217ec2076388179080e002e0e8215ff21f033a80102eacc1e476104caa7fbac4fc889b9d374e97ac24ae84eaa39b3d6b26b87d883ccb7cc20294f83356a4939201fffb84679ca96a0e88a1aa514e217eb839c13345ce2962b92ff30479e8e9ce4715753bd58faebfde7f6c6afcacb10e021e14032765e21ed5f2c9b71251f8b480337eab30e029ba906
+TAG: 28015d180a1377052ba593dfaac272414458092e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9ab5c62a9c6437e19d166b3c55cbea67e706b22a1d21e19de378bf67f012e4242418b029fd28d67b4f1bfe4e6a3387540a17e9584137a0452ed2e8394297273e5da67bc1df04ff9031d224aeddb0f69352b99d29efcf4a2f562546837cb3bb15a1115bc6be6de388fdf1f4ecf53fa9624a15f0149d7c51c1940e1b069715501dad6fdc59e87eb27f844c34d224c1531df2a901825770a1e884cd8190c7f496c19a621f74e6d3c6b2e066a00f0e672718892a642aad13c0f673da9c0e1ebf7692242efa1bf2161fa4044a3018b
+TAG: 8e8b16f5a63801eb8dd3d41ece4f2a6a7eb661d7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9918bc1f9ba829372f537fc41ceec2e396ad753383ae3f4d94fe6d23f8e55efcf520b07ab3c36a11f12f0242e16d2a4a6ff93dea00be07693fad534ca613179743d6cffc588c3fe05248d60ec4f5a8c96d39b8f56eae0160d7617b5dc8916a712ee156a0474edde551911bd765dcafb48a4ac5e313fbdca1709bbc3e6dad27a47251250bd4636f7081e2103c7e79ea9bf60647393def6a4e6908a9d46282316417364c05ed6063085cfabdd1acf8b64db90b674b6671e8bfeeaad41378bb54bee5df111b54a759ceab1f2397d
+TAG: 4d89a5c69dfa7a6f16831f5855cf700c2a1c2078
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c95cc210c5c3e0ceeec395392b8d38e5c5bd2eeff45e424c74d8d5915c0cc1d8e4aa983501224ad9a6f5d2e0bc2d0216c4847b81a70b8b0eb43ef86dba274f5edf98b77fee5a16df67af64b774647957056195b37836685aa2889f0d480229bf9c20e6e40a4adcd396436ef686b95ff6318273fb60d313b4cf550326188b498ae695ff5fecf5e50c64c74a16de9fd9d4b52f87bc2b1d4502cc8e90be1a03f5aeb80c6f1ab39a4fef04dfbc0327eefa61959469cd7cc150bff1323a11d4560a82190c8ef8f09008b3fcc35afe34
+TAG: 6ba257dd6517bcb8e1e8c621856607669f7b50f1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9159fc257a4f571780c7e13b04977029c85fcc56f31acc56b25bda5ca6174b2aa34bafcd02789c730bb1208fcac2788ff2576876c1dad1ad428abac5c1b890293a4a624302cb55a7e3fded9b3ea6c6e00a2dce30dab6890588dea8d090155ecc260aa6a2e296e7ea22c6d11531723f591973f933f404e91809a57bbc50b1b48f152dd2f574f1cd4bf7327034e3f1ca136414449961f4acc2f48262b6df0aad0c9ba424bbd913aa3d07b341e8b89a6eb88d51d69baa9e3941fcefcb6b8817fe62260045e57e4c58b6224117015
+TAG: 48594fdd2125c7abfdd785f936a85cd8df97a561
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c5489632a12116f263c0c563813687bbb27d1baf7eada2e8d5a3bc764962c90ee07d8ed1be285f76a7b034d2f8ec88d5370592915a7e43d78ff9576652db80669dd3245f40e42e4fc8d9a59446e2f97cf3ead85f7e3dc14a103945afe6adc80bf74eaace640ed1895cb8a0d58be9c0e0c905f5ab66fa193e72e4286a22a55fb7b7984c8f43b44926be68f13de23c9cf15fdaa3466833b8f87a3a8696d60e2f6c2a387d295ddc7f3bcf5dedc4ff19d52b6e36fdf5aecc5979f968b8e94664e57
+TAG: b7eba0a13c635e35890aa9e23ac6d78880f7522f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963b14781675d8b0c27e4851bd4fa70903c6dd9afccfba82c43674a1e75249c31c840786b32bc6bac44c3c71e65dbd99721d4c578c51326a651ffd5fd906a9e936c0b678da8e219b0759160981735eed13f3608377785da4ad7cd8cb9d9ec733dfdbbff1af01d59998da340965302fead96a89dd7572df1fed4fc5eef4f94eb12a46b1b6ace394789574ea420dca299c50990db94447ac82f9720a532f70016d9aeb3f228f3ede7b5a8c1f16c8e0d1f05f8b6a9f34eed479a2e9c622aaf
+TAG: be9657423a6b5710ebdadaaea68250ad053c265f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c5489637d651f0001c2bb71e7ea56c8d762cc17930a2955c8bde0886895cb4c85de66e6a3cf4fdb59f901d9dc4605fde66012e0af1378dcb8eee0677864842a9d9ec406c150b8b8f80306e35a03f809561c16365befdb8f0c8f23909b17d4efc3dfc74580fd4f66eecc7c73bfb5efdafb4b409d0bf377866eb92a7561b44735db83949132a487c9e96e0a1fddb5d25674f92e47191d5873eb15b5888e10b7b9037bbc6b63874de68c185847ad9745bd81d234773d8c6e1c8be92cea1aea2e52
+TAG: 20df5a2f204b5aee58b501ec16cb0676f2975761
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963abe972130062cf09ee61afca0a6073cdef5e8b374e4bd69074a47dc3881887b865e51881b3a8298318c094e35ad7decd68a4e4780d3e530a7d7700c50c608be08a349c5c63ad166a95bb4005ffabfffde939ec49be8d0892b106d52ca2ae62e1bbbee12d73f65b8e110c9a706fab7f387341afc36fc81bb40cfcb0a3f34dd19d6c5a3d96a3e0f0c76a31d2a4cd3be2f3cdaa9269d791307169ff9ec7b55c9163bfde0e7cf741ec1c0fcc1e07345235e53cd05d55dda57124ded07cdc
+TAG: 6e7860de99b1d64fbf3c5954517034e27d02fc18
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c54896367c278b00b934ebacb02bdcb52ab9086b3ca119f651057cb285ec5e9d67ed1394d165848658c82fc11a2ee480fba765144fb2a03ebdaf2d6962491274d85eecc614e92fbd59a0d5283fbb22259ae376e4aaa7159bbd7689d54b719e7eddf88b2b50d37a6ea4644670ceaf9d84f2dc4f8860e05752ce501a0b2c76848276ae4ea576588ad40c1af538d1045d237391df21b330008ba7a128c4e21536e11d2892f8fcf5ac5b5f65194ef98ddf7ee43c797b0afc31a412bfbf71aa23f68
+TAG: 5e61f40546a40e1c09ea54297f60cef736766a03
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c54896330c39b66f91563a6de57487ba849fab12fc9bba942c2d238546db6413174ff946344ffaf85aab93e82f1fd2a641729bcffc4f8d352c0396ce9ba400eaf2d6b5f70f0bd7147ee5cb8ce3028febc3a6270e9e1ceaa9c1165498e59fe3d24177260a91b6ab9396b98d775dde1c25fd37495d89183f863b6c72be65e47fe9973250616410797fee6664fbf06f1d6e5170675218966d001b753b84208d7cd66e90cbca9ee5adf166b93743de65e32bf4095b9762a02b983cce42aff651e66
+TAG: d764502bb89cfa9bc39fc4c27ea0af1184b7aa5a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c54896361fb4f88b000b3c509576c6a6c660ed7078ea8301717ed6a9009364e71658cf71264706d93df504956ae936127823cc890260c2f0a6d77bb651db63304de13012586a095f0f09a0585e466b096fee8a055161739a040a8400bf2380efdada9bcf4cdcd1a0f15d5258db6e43fc343c991a196a87401093c435f4e1127c162d2ce4c4462d008f5ed8f29482609ee404d4c88d74a0976b221aa63d958ad3c43c140bd3c4d30437f15b2e49841583b9b92ceff74c77644adb9e4dc10562b
+TAG: bf76b7b747f9b8b829ef5e72bc932febfe4e7ebb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c5489630fabde139d1ba354cd00eafd629bb24f121e748bf60e7f2b99e95eb3ab76a6c5ba3177b2a93cfb24a1d04c7bf5f3545abfdd4a120e904493f78c0559f832dcf194f467226f69992505562e22b43b570df52dc83da00749b3ca5fdd3a7b3207808dde12c4e4937fa79163910e79681c39cf21ed3dc80947ea623d38dba8d2bdc998a771f75f02c1c77edd9d721e1d7a6d3312918fa65d67ae630789dfaa521049c4566077d0906240600ded0eac9e4cde369747d8c41b5c50d54377e9
+TAG: ecda2ba0af3a8a5ff3215f27fe530430fe6bb38c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963528153ac3359841d86944b0defa9659aaa95e28a3f78d4b62fe2bfdbcf0a7eb678c47cac292a60005af3d5e84f7c3cb93734baec9a20cfacfdca5c0d2396a875b1041d058eda11fa273c2f3bc6626ff3b44da0eca4c3268f129ee50a6987e942cc5f5af0a3af09c11d5377fa978ef97e39bc69506a55aef56ab7d138ad9d2b494c12d9d053c2c6c630afd417971ab41fc99902d8b8b485325f7c8763f631fa0439f2c91aee3b476063e9f80f604001ecc79732f413dac7498a06d128
+TAG: 84fe26e75d6fbbc6676e7bbbe214e7919b4b6d29
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c54896339a4dadd3abe19b8e450de0eb8275eb88a564c7462ee30d1512772f4718b1942e79d75a30a81b1a04cff1f0c999306aa5cff4b240e1da428585493dce925f4c103c6197e61e272aa8c23442f1300768198529f7af6dbe86d320bcdc18b6bb4827beff3aa50148400f677f487f5dc9f1c0e74eb1b395a9350bf3583a0211a00da04aa86f3201224aaf3ce86a0ee96160dc8688f76be5d32a97973c8ae89c09e9d108b40a331c1fee8fc16c889c86c2b142f78fa6afb97c6d9dc6930bb
+TAG: 3ec8d36243c03087753d39bc65e4012b4f725242
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c5489636f941442843a939812806ff51cc7eab6cce21e637f3631ba6102f801aaa58a2251852cabf777d58f493f0ad9d0a3ad4469e98277594c37f29c51b057dd11aff665a0d0633bff6c2e8401101603392783c0dbc3ed59a69ea3d27a4639a3318bdfea5cafb5306822db776c7523a23915a7f680ddc520f766e3f3e99b84bc8725fd3b91b801d971e016a4e4e47ca486f2b2b7e9aaf29746fcb39686da83bc65dcc861f9c76d3ce2b8819bf0eae5d5481b19612f949676da3f69c6f74056
+TAG: 90586b63dd36909c6ac86a3b7325b9364ca64111
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c5489632dd27e25b836a5b856a8332d163f57b70506e694ddcf36e393aca984d10a0c1d166edb26a75166281148a3c7523fa19ec87a67425fc0d89aec019fcfacf19a68aebeef192b202ed3c35ba0af47c6cf190a1c81ac3674e98341db0436391d98ff7d391a6911e0e8804e0dcf0a96a13fa6a746308f96c116295e657adab60ed8171ccaf048823c1702ba38e381ddab6994dae8d3516bcf39213e22283e5cc8aab69a980d98cf0302b7fcb44b8efb3760bbe9f9057f1e1f72ce9cc5aaf3
+TAG: 7345cfc3877055f51dac7c8e636202df9fb9530d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963607bbc82a83948616d1e4ecd53f7b661996c10926abc288a3531e15d83fb6e8a373850d0067c3d429daf707045c167c9fee1291df4f8f58aced7438407b0d0c294616afc69b6b0323b5e88328359c1aa5dc09c465c0bc42099167581ef5c83ee32971991f05b3f21b38f734f344fa653c7229fa11e1a7c719b20216c3e9afb1a27f802b365057ac5afda4313ee28539d55a29514d0eb054a16dde97ad802bbda96066781f42d8da9acc12500d9edf4f15637b314415779f042802763
+TAG: 5a69470d8f8db1251d855d89c3b1700bff0af3f6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c5489633681dbfc76e70755a80f1c28be2af683e9dc3ab724a4063101af49c7059956899bbdc7b7a6f993cb5f0f5c2a3e881a8b33d2e0ff9d992a790ade3c32d21f27002cfbed7b306a8ce19438b016e0e733db61e0f4833679f49edd7f2fc2171d5e9f07797273133b61482653c1128467cfe4e7a77246ab47cb35f1ca4155c4d4216ea6e83025681bb279669fca9aa57fd2a57884f6d0e06ef437e3e3cc2e45dd285df52bfb949da0e0b0afd3ef8934afd2c31679903b1ce1b7c122aa3d3a
+TAG: 20782b7dc4331bb019850900c837fefd7e73dfb5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963182cd07f857490b2188c0d383364b478f4f1b6571b52ed27127cbf1efe7d2c90b0ee765d1e86de7875ab28d185daea85d8dcd530c930d5af1ff862af4fa54a950b0e77761ecebfbf957224038244c477de7772b705b101b9bf79e1c6dc65c3dba8f07ecaff538a49480fbb3f871d4df971c68629f5880648785971e5b8b10dbe059e5f120a5001fcfe4590721e917563fbb13aba69d9996e025c41141e30807ca8deea1165ee1e813742118f2df739e318d1d5daaf508d909b080102
+TAG: 6f0456e81737faa6b3f4c3b8fc7ef9daf3873c79
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963b30ddf49356da0bcc4afc73bfc8e6a4efac4d70fcf0618fbbb6ef48de857812e9acee29ffdc24097c86f93937ed46fc1ba625a00f998276e840045312239317798a9a864d9ecdb7bbc60e7002fe9160eeb2fe2b4487b0bb20d6f7005d2b94508e57eeca1271b29e6683ea0d2f8906f3b7b1605dc0f332bcdb3fbaf6d16c596a0f83659f32456f4e3837b273d5b62c8c7fcdc063065bdaeb6e091fe8e2e4ea346bb0e5fca966c31c595b23a0a1a4369b44b07dd47f95f80d8b64ee0c3
+TAG: 40edba0d85c7134707de1d59b9146de37949d161
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4e119abdca7a7bd51438775a98bcb310fe747ec5f4d983e179a80cd4e2a14a849146fa3bb32b825a765a3109bbd29509d67842992e196be0b3a553b2536814fbf4da02ecd4172b00a2ab7f793a8a3505af4b52682da294b6f50da5fb02ea8b5b190779e082037d6866aecaf5534640bfe88e9228378b2cb0d79fb1dc6f0be3e7acaeba4f92c8ca9032394a1bb77108d62ba717e4a973f478c8931441f59af9e157ff99ebb60b28aec15165344
+TAG: e19011160d34bc441bee6f7b949a2b9354b4376f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e463121ba6074a158f93cccfd507abcf825826933ecd61c6052359e098cbb4de4f7fe1e97428dfde164d70b0cd6573a416796952283df5537dbc54ea2245ac583f90edcdefbab3d8ebdeebd2ad2b2aa54b4621ef792ccdc67aa99f25d1da316201e4a3918b3925dc516d392af321deeb9f956bef7ea97969116abbd4587211c9b62f4291094b744f61b5476e2cbc0c37532cdeea6e1e0233fdf8e6de959ce2769ef7fa7d41b5edbb3cab524e58
+TAG: 259734e55e9c22961a347a83f72c2382246264de
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4a05084057b22e5e30a1fbe2a7b43d6af776a7dafd441c12342766283e76fc801c887802ecff0c775ae8e34a19206e4fed9e30c70285e06188b0e92950f5450f89701a5d170c2e54a0e769b1b751287de99a84d8f00f5506e305dce0c13c70df1cba7cc94bb52bdb0560193eac58ce8578cf39661a8737073a94f76152610b0b10bf9c07af85d2604c094ef026ad3d7f1f1b88eed26181b9a1945061c3ab9db9acaab418ec4fad44108342299
+TAG: 095e943db3e349186a4eeef5e79b9beea5808f52
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4e4de8ec913880dba3b1c85b1858b732b1973d168918edb54cb2140caf4356ce9ddab9a00e5bb49de69fe3cf94bc8e4e63dfc87bdacf47122947ad70b6297b23efbcc5d3ffa5ef9b4c78f378379bb058c434c67f511feb82913534099fcc1b80e3497c24e76aa36dd125196bd314c1431f9fb12611e40342e54c7cff625cf110dda6adb5947322957fbf66b6d30518b4cee74e6e797cb71ce8cab3d7711e49628b9f92358efd09a84b3d30d34
+TAG: 375aa96fbf409d974d406c0aaa0f6a9000816cd6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e431bdf160139f20b7f63e106851b6e7c605c1ee2e0f7d9a25d56d119874a7289b68fd1819c95e0cf5bd85cfb96108dd5e788efc0291f2f8c9a9a06d3aadf0c54bacf8510906fe3e0c270a5bf254baa063f5fe38059e343a27a91b5155f7c5563c410fb55b9b0783887c384b6a170ff2787b85c98a6f92df598a3291acf5d8be4187c361e281a36d5e9541aabc0d0035053f267dff0bcf65ca45df5c8fd7fa1a495131cf470309c31c1c9dd5f4
+TAG: f3c8ef973071d03a36dabac93c1df7523c34a0f7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4f2b5798bf8244f97303907a33992e041aa6796b7c2d6d63aada8edb002d19de59fc971b7157256992784ad143d8fccd1c4c17e00063309f71791f2f3d42b0a4dbfbac9d75a06edd6bc435a0c8785ad6b90358a9b5cd13949f402f02bb0c597006e5120c900dda8ec3b3be94f4e221bec45777cb4b1d9db4dfeb234dd03ddbbe2f735be7e4af28a3b9cdaddce413f03886efaf11490aa95b3003f5f72dc362854a68cdb2c0f3998b63d32cd69
+TAG: 1852fa73336c0699ac21b57f3b50fc8aec156b26
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e415f85b22e2629fb7ba1ddadff4b91ba7f7dea2e0c0af747ce34e19e0d22a86ceba1841fb9cc1895fa4c29e0667afd0c3d56d1a0fec9f6ea0686b7bc1db25d7e71477108b781a6b8e92071b17db07928a1f75b806b78eee2bf245c408259ba0dc04536231dd8d589eabeb5000488f6b2e6663980a3038af322a372ba12bffe3c987b101a9bcc0812e044858cf591f941a6cf19538a00f07049140a3c956100d2d30eb876de87dee36985aaa14
+TAG: f09095f5d99757a70b2ffe2bf6ac1c654db49efb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e468cc8c5c286b78a498ae833217879cba5fc9b6d673b818c4be71bbbb67ef68aed5f1f35f7baeaea19db612ef46ac4603c1d2aa1020230760455b66fcf342bab964cf29213725785ca99b44f545130711c8b9d086c6521e45f551c5d202c2bc63795404afa7b7d051ce500ead1a6313f80b64ac43f5d29b255f64d7b35cfd87412100a318deb7c37e888dbf07563be59927b68a74b84988f077a9dbab3704e3bf5086c25bc148ea3866f6181d
+TAG: 3402c9b6af06e83747690051c9f89572cb3dc108
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4b56202856bcc92dc562664e5bf0a8dcd27688e1d3f35460d34b977dbbb874f41d662f004ddc7fab4c4ad06e443f33152f9b6552d68e70728e3eb245ca74488e7151d88993f2482667f392f8bf818b4b52ec38b25fe5f6eaa56b6d8f6faee764e0eb38fd9132bf5d869d499dce854c9dd8989b259da651d05076e35db87fefea1a71f9b1ae5836a78f58775696a2052e2287d0f7d805dd59aeab9de99bae97c2cc6e7245c7863e3ea997e1991
+TAG: eded55a4a1d1a32e8d913d0f4b31ea0997faf0e3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e45d64f1e5f3b3bbc18140282e9893b662dd6c760512bbd89dda05d2c40643c49363be8af47c5d0e9d366566c336dc324311e4b38cae6c754813ab8655262219f791551a42faf27a3321b2a534c3f030778f42a8e8319174f81d7a88786d1caec76c3a2858dbd423d53e9d709ebbd1e6cb90e629ca99150785e900fc3462123ea0547d59755647beb3eaabe8e8e0a0efc788da0bc33f1b8dc27c446cd2defb0734f4e12ea6fb7d76985ed82142
+TAG: a5c0fabf89c0875fa2edb66e4f87e792a321371c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4eeb0d20dbed3e60372e7db422edbe6d22cc5fcbdb8da8eee75e3b888a6f98516bdf545a439d67f1b300fb0bed75d468176b0acaf2e67be976c6def8b9a21c57dcf708a9a54b4082849cb0d49176bdae241a9e3eaf68660c21af5cfd7af84014a5b70dbfcd32699ea442e46f60026416fab44586872ce9ae30f7843bb3b6c17d4fc1856a27b41c00a015df9503f392688751a1bfa9e9c7d8e416801b6b40c33ba7c27eec776308680f49ee716
+TAG: aad0a5584c57679d2a5a6f8480d5064c1496aa59
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e464ce8e0d3a1a50d481b5dc8fff68fad1e5581d03d080f3c34d00804789e6e5ba009bf9e53c8b4076e18f8e130afb31df14a2662057b988ce13fbdec20d739183306cf6c3b042bb270614ac681c0e631780b1fb88605374ae396a080e7b94acd9673a1116cc9028f0b0de7d5650833ae3f91c9dd25f8604cf59d23f3e29374d1c4bb04564e2db4cb8a428bbf060652a519261c56520764b3f284f04ee35353e5e10288c6aa71f73d8d8923afb
+TAG: fa6a6c35d65ef04af2e463f90742fc20a71055a7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4298620046b22b9c84f2b3111350bfab4080258681f200a591d3a5e5da2efc666d24ef9a450327321c7361b41628cf4279abd5abc2a81500512d1512fe256464cacf662e917b73dfd0a0734f655f2078caf64ed1efd0ff832a5745ca5f1b30559b2388396585b8ef800092e27a2260c0ecd0e0196e5c403e8a4f2e55c4516b4b10ad7d06aa2d07337673b4d2056462550ec336d971a2c154b81508322cd48d8e5f6be0777e71d5cca4235be6b
+TAG: 2b2c6e645f53920a34900d0652b1ed54c64f015b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4dc6c6c4eb96969142fa89a051e48d11c729c21c5cae1f9d8e242e46c52b37ee3c94fb89d53d690269b115edf9ec470b37f66450e3bf2e291fa69b6e0cadeb03f1d620f5e41f4a48df7a48904fc793ebc78e2ecda39eeece32932001a1952d1644b6cbc7a83d4ee77b8a5bfb38bbe75e011e44171df802a4a9b13285bc2377528b30b4257e69fd53113a8807e7d7be39068f7cb6b2910a71c9e676a401cef14f80bb1bccc30e0e6e7856aeba4
+TAG: 34a6dfa9188d00dbd93683bd0b4e989a8eacf114
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4a51c30e9a4440a2c65de9db7818b9f77e754485b1ffa339e7ed7ef5ed98c990577f41143eb5f86d185e52f465bfc5cb06aa69e574acb4b59dc538f96c274980d40f040ade9da91ea156b890e4ea88835558395e056a99d300dbb8b938a66b80b9c87abf817682cd937936ebff429e991ced577087735a0b4faf1b63d4d1c97f447cc1f5b9c48ddea2a8905109fbe79166a26f754ad22ee063757bcdc49b95428fa70afb8e0fab60b6feb4637
+TAG: 7a359121230787c50853e3e54143e5f365546f96
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e438403e145103fbb6619c1520b079957c2530e55db74cf7520060343a43456eb56b43b76cdd1d089f3d1944316b086f5372ae987fb4c3d5a99bb113ddff9e5ab5f923ae44cc4c672675e6181d3c452066b0acff2aa9f4101e31b79714f370281050f47fc30d9751c1b9b936482c48b0e80ea36f085f18d454e3ff259be2eb72468f38d31c2fc518256318ba5919f4b20fedfb63385c8c29cc58fc37fa9ba6e9cdc5a73cf9ea2369964cb01f22
+TAG: 96f8e6bf7dd9e84463c1c366da8ede5cb208ca24
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0af662bd92a77b35fd569d20d07323a101ed5e393a428b2b584f714028aeaeae32b3a4e71222aa44d1539e23e3f2521c1b2f4859f1b13f619533324dd1a3207a12e8c193ed6608e6ae2491c04280515860f996bc300ac54a7a64a6fd9fce59d262c935ac602af7e450f09b608f96fa76f87e3feb7fae90a164a1a1de523d0d69e347f46958dc252d48cb64def33cc8b3852809dbffb866ea0d7ffc21c4
+TAG: 1b13fc9d1c0fbb515fc2d122974d5722139249be
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a9954d6953eab5e56b66996f703a47f201bf22b6f4e4f422f71be2cc4490da56d1d64f3fbac4dba3d56c977b34d656a3b28eecaac4bdcdc9061429a53fd4537aa690c6ef8f69df2f9005ce6a17b3426ad1013fc0c8534550ce001b74850f3731894f13fdd8ad1e7408e9b733d4c39d147e4a4bd74289f3bbf08232cfc4e75052c6076a76d7e2ee6c59da71b3f5dbd47fa980896fdf781dabb17cd745a
+TAG: 4ac6e9d609728d93ae26a1a94471bdc365351c8a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a4ce81a7e90a6594c11303604a2636a5c7c0e26300dffdc70d4717d41f650ca2c903b249db2d59fae8d114bef4675aa4af092cbd79205ea9b90303e00927130aef7a51e93491f6153a7d6b317c1b18da235d833e6b68e2f8c5271bfe038cddf799c49ce21472c2a25c3f1b6a15e6597d05dc15c45916a9bab8024b81ab3c9b69e68263c26102488e1420c3248e5394afcccb102f14e31ec7938ead94a
+TAG: 2bb2e02d1c9082bdd38785442e47ea57b1ed2395
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a1594d1994aff749b05658012655ef54d952f98dcb1137ada2034c74f55367c02cdb35941024fde808dd8cd75a28c1b185627a5255c84908ee068acc39eff08e4f730709be0b474f062456ef4e98e4a2dbb933253634420abbe993e14ad27c5bb61c883d2bce30575ff08b048fb4e71ba9736f2960a88d0c42554f249647b3abd14963feb0e54f1195a1e5c77b8669fa1a8d6d558a8d7e69057c3362d
+TAG: 46b3e7705923f5db8a74b966f7d66520807b20cb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0ae11a69289f1a407fa0a820402effae120e8489463e16b32f68488e20e0c55511900fb6252fea086aaaf9ecb9962a8f870e991b811dbf6689a7716f1e2123ba68b8ed5c3b30ff2419fcfa802d0c40d45cebe28c3240680f171befa41f4b9fea91bbab429f5f5ae78be085fbcfb6bdfc8775577bb21465776a20fffdc96b5e31a91635f5949da00cab35626a7b2634ca2ea98d83b9c988f7c302527f5c
+TAG: d502c9c234297f7e2225fd61b77d2edfc7bf5f74
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a402ba1d3b18ab0d2d769c879918568158e74a8c651a555dd8adcf8c20cca2b7cbc7f5dcebcf5c346489aec1c43a4639b2dca3e7bdfbdcc2a362008af5c6cf460b0f733e53d84aea0a820b5bad6540000aa9dff17b1c993bcf143768c4c4c5c20de23552de944b5e1802f9887a1baadbf280b241d1797da3ac16e774a194b00b40c609241b249ee9e57e2a61c4e8ba9634422f0fa512eaeac9e913543
+TAG: a2706746fe6492263c1c2f7885c83592f9d00ee4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0af31ad89025eb18595ab061bdea0477419360bcefa214db569541cd61de0f81b4fa2f7482b6a638af85a133cec473bcac57fc822a2a5156fc92f464e07bdd7e382a8e54ca005bd5351c597bdca71bfc15af21019b65720a607224dd13cc8d8fa58e77790906c4aecad52cdc75ca08add3c37f6ff53e29014defbedf67bfffbfe296781fd35c3c2910b5d6c0f32b3bfef7ec8d800b6b7efcface03232b
+TAG: 3cdfec7c24b2e1b212526573a0bd080da05e7977
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0aba110a877d72888def3d74191130a8928da8586bad3c5bf6407d85138df5fd88bc446ee3aa8f0737eeefa0058889031cafd1bcd1fb134a836024f8572fcc29932727af745cf2d964715decb649d83985c4530d260918fee4ba90a8d9c94074312f4716face5cb33f540ec50cc84ae463d2adec298307263688ac25ba5be06192342dc7682bb27510973816f7fb33a6fef10a4ab472969b411a3524b7
+TAG: 42712aa7ba35f9151c77793c9dd708ef8b19e2b6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0ad288df9bd6098a00a99d72878041c778c6f10cb2f8ec007492e8c4f7b84d2e2f809646609036b40e6fc178ff7927e12ab252070c2b6938b8300bd291f8061951173821ab2f5193f0ff5b8b9e0d4b41a566186db760d47995b2754287587f219956e800fb5a60f555922bcab99064def13e3d38a6dd1d40ed32b86cb3db3a7f9bdcf14f37eac0a43cd4cf396ce3947bfe93351c192170b7982964b0d2
+TAG: d696c64c59fbe9f53a383268f73679432bb66fcd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0ae7ea5038aa551f38ffbb5e9ef372184ac3fc5e09542ab989faeaaeabf7e855818b5ae802edd3065f9a87cdd9b34f88b8f2469af10978e08f46ff7052eb6b51e85734cbd152ab2664036b9277b9102bf569debd1cc468115280b150bdf21ed44bef32d50b4016848f4936bb7c85a140aa20a602acebf16bb63ffcbf6f34a30e8df4c7ec93142ae175b4640938616c8be1ba83a1f50444f666e3d406e8
+TAG: 6d9982396029119c858e0ff0efdc979b01e1d84d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0aadb6dbfea7523e7d458911f2c77d80ce2ad13091a6b3b2ce8dc1db835eaf9bc672200b445cc2ee395612c634a12f7b764feaf409574467998aa568a3504268c410296e382517912eef270cdebdbf1ce5f9b3f8a0ed0bdef2bf57094558e819dddeff123aca5681fe80d01e16fc18f334a560a3b6b87a00bcf429acd075a7f27016e630bcc063e9c45a1bed53e57ae4a9145738c05aa195795fa28037
+TAG: 259d961edb4a523eb8dc6f0ec0f5e01c47827461
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a8355981ea462d67fd310abd45bb0606d47b39132592c3e9eeca94e2d0e3047647331e79ef206e17bdf97bb64d6048d43f3a26eaa79a889b191dac49547e47c37e353f89d4beca2a511e4d4c017cfb7190310eee8d662db995a3bc6c72cd8a98ac7a6be87fe4858a9d332b7120e86502272918c9a713a7bb550e6fb2a447a81c21b0cc89ea907d5d0b923f0f6fe8d5daceb00a94c55d10e8a725d566a
+TAG: e4366441d9be3bf2aa4fa11cdc957e128b51d3e2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0ae534fddf9c1aec95aad7135765d6139d774b1461890751144ffe8601568546a679099775cf2632fc641fdf7725c2761b5c8035cad3cfa9b9726577f6d1be48252f9c943dc57998555e5ce93bec1b2753bfff8bc3b0df59016b760452954b58af4d189d1e3fc97318880b5aacd739149325b763a9aa11746c3bdfde9c29e00e7fa19d1bbab8d856d71eee741c31bbc3331e4db383090a2ce8173750ae
+TAG: 9774f8ee6c2180156f07a87eebfb5b61e0a7e09c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a63001589f7af872a92eb9951480be260f811d33b964f182999b21c6b55146ac3e2cdf364716fa756b69ec8496e66cfac995e72202f34cbf4d83dde510d5929437d89d30e8aad4e8e7a5d34fd2e2cebf0cdbe5d935a8f4f62be48bcb177bb929067a3f92e3ee05e3bcc5233fab936313d8acfeaac242721aea94860c8e220f0892935b74210375f15faa24cd220fe5e50accef6e8b1bd65449aa1498d
+TAG: a4aad48e950abe6ec65a716f8af3da7057371cc0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0addae09ecf6d97d902788bdf27a041d2914eca309ce34ae254c61fa4e5aed5aacdcf65ad765b701f3a36765464dac7ab21ab40937c9e64de9cb6775b9072e4552e853aa910d63f908339266fa438541b7532d3ec4f9fb1cb0f099766b70137776ebbec37fde13f9e354a2d2570c0e7337dbdc70be1ce392ffd99930ed5bacf9ad96729f272959268fd6418b0b4098d60737f68d38fdef9c02b0194abf
+TAG: 01c9fdc811454ee03bc9a1ba170906847341e9ca
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0ad7a35653225264b5f2b1645859d6b70dad7fe71eb6d580000f91c03d66b063e5704cff952de63bd6f246b8b5dad01a983be7d932593ed46422c0d89a4eea976de384019e002707b26d99b390b50c48c3835a654b35ae21bf7e25f4c9f3e4e7afa289e4060d8a9f32fd7431740154422a1f771352b456577eb98d3e43064f4a053b9e9ede192aff1440fb93cb55b49168cc149efcb1e328aba6b80bc5
+TAG: b874f7e873abd980f550d068bd89a9d6595b65f6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018d5a09eadb528dadc4298ff1ee5a646882c7343afbb860ff66116fbcc788f7b8f3285fa275198cff32529f2eeb4a850a10dc20d88524debf0e318e53e090027e30e583317a60a7682fe0ef7a6d54d82bb7391776d1ee7a0f409b70df1d772c15911fee0dd7a9a9b5f686c0ff88a35b532c1fa4914b5e4a2d91bd3adecaeb40dcb936f5ebfced6c5651bacf3d46
+TAG: b7b763a22b4f0fa868430b971ccf4f3ff576775d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018d2edc62ebf6315ff82df3b786e34bc4814f61bfa3d52621e3e95a7cc9e8468061abdfdc3ada1864d2f3984c5f44ad107901330ffcb9ef0497effd796818d6c1bf0e5822e0d01d0b042e03f433604000e14292b3aee94f53027a495d0b333f0ddbafdc78f0f35fc494fa9f1f7cef7dbc21c04a7abe04bdf0b771801c3739383782c22f35ca8b9b8e1cfc8850c2
+TAG: 9b344f0e5424bc45f93f7d33777c6e87f5ece23c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018db47876c04390dfc622c1cb11b46862eefa2102fdf867d890da985ba460766990815ed14568fda7918d4990f7d69c0c6fd73ec876f4cadffef445d16f1cecc972350fe00116106fe5a5f414ae6a8eb74f7614d114c33c593b07428de38eca06a36ed20395150812fbcb7e4a8ff9396325bdf7d7e9ae864b3eb9af6f8b804d68beb6d135058392191e76161c41
+TAG: 2ff0c5164b038e00bb55a3cbf8d52932d6e6c82c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018d5cd778129c0709e4a4c74cb5187d36e4bd33ae760ace18d1e725aa7fe286472b117cad8a6e49a0c51f2ea2b0511859a0d598fab1469491532c47797cbba7fb998a6acbad2a17ce2893054fb55ac691d0c3571d4060437f8dcac888dde640e5d07ad5ee25387962e43886e3f410e33d77d3aa9bc40efcc71ccdfc5b83ea9e26cd6e844a60ff354221da286407
+TAG: df757406a734e4f0ee2bf41603a55ae3d48891c1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018d99a9f555f533570a28a2864a8a0531fd2a4628143a2be54d7efcc2a6b2bd865d1ff8c0c841bb311a27bdd083a5e0b78e6302c0dfc2e887d4325a71dd504ffbcf2dc76d8fed75d6009acffb113054b0a06044177ed7269b849101aec25a4f3f6245475f4ec8efa38806e82a96aab75fbb67823923e3740d7989e7c28ca8be14ca804212ba4d7e0c1afe1e6928
+TAG: 5395447a6cd33cef96e44b5e695602567318abcb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018d6f65ed0caf127a65aacf0691238d86540eda944ca64cddc78fc02d53c49462abad85962172c73735696dc3aaae700ecd7f778518c3b62e9008aa642f8cc59a192dd0298abac21a57b24cc4c7908d80c3f85cb4e9a3f0b3fc8d7b5374cd89010c730d1684fc8538782c6d0d3b8b30342708f852c4f2a12def8cc799875f4409354710678551237cac40932ed3
+TAG: 49eb1c8451503a104f97ac3d2d2eb96ad5022e96
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018d526c0ce5ebdfa86812853a88a9ddc7b065b3ac1520e438eeeb8800231a8884e3726440d858f52d723678a1f31729aa090c0b54033853fc2cce530426af760d7e689d45ec2eecc6568b29f99d1b82a958c6468dabc314bcb6e99890e1fc51e97b696d7a6ff7001d335428b822d780ad91371d2e4f8e006c78e2fce5d3c54e3f2d3f48d96813b856944ac1630f
+TAG: c2a554038cf604a3d88504fac873fe34c47d2248
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018d97a4a1537b08bbaef601d45183f7b7f0e6fda6c544ee3661ac8809b36c29f358f7545e42c3f5649be50b6e2eaf03708ee45afa52d0869c44cf190c299c00a89a2e7d6aa0d3aa51c2a72c188b910f2f5ad684d34ded6c5ec6b0a366a1be1fb546fe06e1c05e19f94109b94bcdd034d32455710cc3578dae0f768aa3cad68b162f47c4d3b02dbb83145101489e
+TAG: 8c6f0014159e32e876b7296ea81adfdc2aacfd53
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018dff64ad1b4e92a70d8aba45c2a6454999a24b4a0def0858f9249124a11d849b1f97fe72525c9bea1c3a463f9bdeb09fdaf4c8efb5b189fa3ccbd65f0a6ec0d5ebbf9b064f8db2cba35c101858903a92cd6b1075065660eca0a8edc0a765080feaa8d3b33bf8bcd805d39d3b698712bd902821577246d055a14fedc06934c4b54e12d120060f6cf1279f4ce909
+TAG: ff3025cc4f38e896d07296875488e05551f18361
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018d647545d7e3cd7d492ce3fafc72a00e0d60a754d1fdbab87055d1dc3eb1e638a48480f2c19dc2cbed853d027e67fe4f1da74371a478f1f54d2a8e1be236f5d09b4b99edfb3e25dbf250827de2bc14817b5cfa8b0571841c9a1392c47279f5630e8593cffdb7f9c68a381066fb98855a946514673bff2380eae0e3c7f32d3c2a0ed3eea7855c12515f9494bbcb
+TAG: 84f58ce7d9fb12c2c7af0cbe038c581e05c221b8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018d4fef5c85a29382fcbcbebed0430eccffceb712ec5fe6b93a1ec913b60e66298e8a528c35170481c370b194991360ccffb82a0026abef6ee55aff13c8e77198291f0474c5c2df087d4bf81c4943a4a1286c4edbc07f6a1ead315217eda035a03aa7e8a9253cf9b6923eb4b0d6f817971b1d1cddce5866abe5cb6e08a1704f829c511ee276e739e38b00b07471
+TAG: 62c90438b6d7ff847d9fb36dd337665e1168bd1b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018d880c34acc6996096e79372bda07bbca3caf11fec4efe9d77b7894f3d5e79894d15bad9e21a6ee833a3f40169180ab8bfa14865aa4a209e8e6c328417ddeabe8d4f715102303afb3b7a932d3638c0ded9ddd2235ede4019b12e09e4403e2803254afbe30c666e6c677c885e301b886065e4099f6b83ed6a0d394962637e03200d825b063278eb60ededc38e1c
+TAG: 1fe5d5903daae3f85b63515cf26a502b804ebc5f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018dc13b8e4baefad6da34c3d6fff2b40a1ea643313aec7d122810ff6aa8834629fee56de1b51e300849fdc24f55431beb1670485246ad8326c6429bfb891b0a8b485d5d064e4eb9bb8c9052c7d256370628e53f9d17fff4f20c05062298c183171fa34cfff9f1013712be504c86b6d29d272e0aea008a2294379665fe8aab0056a4ccda88b97d71b6df5b29b921
+TAG: 9ea08794cb4ba03ceaf83b1591641b20c3f366f9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018d807b0f525098e98be1c81e582a2046bcf67d49d7664d428a3c6b6336205d7481acd43a4cb44b3ebeb29c593536cf54c22f69d05118a5c7851eb424eeffc4437b42182d9cef3c4fbfe2d66c0a956374506f2a9b54e747cfbc01db05ff5eec98ba1b2e6368df084460597454283ef26a83a61591cb59401c1892e21115e9a9a38e7c0e06f85c2214d983fe903b
+TAG: 739a3dafcdf4291eda6b91ba4f6b3384033492ba
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018d90f47dc292c9c6edf4972fbef499ce39b90260f404ad05ca87f6bf8f812394f1a1254fdb1d9dcfef9ac328b5b3cc8bad79118194ecd84c5d662770cf1f7840632c4e4cf46cee0cc2a31c22462af05e907263e4e103fbe82a07a7f64d765be13ff02325f40a126160365fbe76f36d81ea6e5d9e2e3702c5250844cf56728cebca8ee1c4cd4e3d472cae865a9b
+TAG: 11127ba8c52d52ad254dbdb46dddbbd4853cb2d3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018d29609c22eda2b1bb6856c6759073e1cc35052ee534032627252bb462dbbb0503b7e1fd710253dc216352397c1e060f744a3acff06ed7410a2ddf5906d52fd0be342c0565a000681e3215f9f9fa5d68720ef552a382d6d1585d2b0da37014f8dd218d841c500180fa471e7cca498d8bed7630ecabc691e8d1d89690e5af00d986a8652a938436cfe791be1f0a
+TAG: 5ef71b20b002921692d548fe0ce7080d7bed6b34
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d9647307557c9c6638d6c567ac2d872027c54f82c54560c72173724b34af0de98b414c99d07abf8344f7af6266357bb687bb6763cdb6010b479ce4fcd83cac6af3fde9d13a7e6211715296b781681f360d3b8a5c4294eda2a568fc59d02c733d84c313c80775cca868844725f6c13ecec235a95ee36d280cc2889e2d49bc0b40cb
+TAG: ac1b2ea645666792a5adb9c776c39982f2cb635d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d9647307557f4f602e4c4695b0e7986296d364f4501ba6c7f8e4a4d760e6574b8d215884155993ecc010ac30291e6a45298e696a33b79c66e19abc24c63bd1185df66ed1489fa3855b9721c9578859c2166cbc73347e4b188e3a94b0d535d43cc9d595e9feafde008b4b5a40f29951451b5186c081a7345b2ae06085ea95ec5fd5
+TAG: af0b623f99ae347e1a233e9ca5e6d1dae019c4cf
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755932347d8aaef781abe5a509239a9ff48d922e7268d9ed2792274f700b694cfe74774fcfb08e4cd93182b4f054c057a8afb174c1af04abb56918c2ffa4c2e3550aec0c9e1bc5e3c64ab2ee9418943c9fe7d88793f086f74b5183f16cf233092baa1513c42f915cb749f445557d5b909359d106965458e7c2cb2b5c8a4
+TAG: fd2b37a0df36b1d4510d8f4414c2c0b084c424c4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755077871c8457d7f39bf04302e8d0f1e450a96b06e9d559626bfad3cb46a577b9beddc115ed749ef26385147009a6e5ae8cb370c632991eb611867fe9b851bb82fdff12f70961fcba2dd662a1ffd195a536164130673c8dff3c0c69e043cb2dafd35faeba1d899d1b8c45683a11c23d4fea7da742cba4c9079ccbde810
+TAG: 183639850c84a0cb9d98a07a702b537288742811
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755d1d8f77541d0d90863b0c85de1c2a1c676366b7bd730314f1dfe990c5215912a2cab9deb16f89d927a117d3117fef54dd3e9204b7a61dabc2dafcda1826dd842978e24ca64ab4bbad7ae25dd0e20a818b3c8709b0dfa0d55b50ce71cb06222337c935b7cf3b55c09f5e505d24ac29f341da82ea23fbd5c7f0dcaa464
+TAG: 6ec97fa78453ecd465a04336ba2a3ab596e19c3e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755ab44044a94bb9b5a2b20b4d6f1a115eb1b99299a4b40adcf25f062c07568d344b60c404353711050c9ab66623a62753ec3a59fdb6d6d181391794ecc0ced2d269ad1c5c25ec9269271c47327cd702d459a031cde2ab3d68b128bf15fcf3e421e35074fb39c684fa79f62fd1040ca422abd59cde392da74093d106154
+TAG: c84ba16dc2a7ac45ea9340203a5fdfb4647cc786
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d96473075541b6006f92857562a9633a863e9e102c4d3365af973acfa166930654421c05a7865b59ed9d5d7d51ae5e235773ed44bc45e58a9780ec29589d0558dd3704287a6df684935a6692e0ca7de43ffb1dea9052062c0ae49998d1d8dda1e8f4a72ca0ebaa3cd75e70c32467beec28ef9d22525fd5361503a238bc06142b35
+TAG: ff0140d9befb5efe57b02f10c3cb907fcf22aa5f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755ff65d16b5afc87667c4954290e5816959e31718a0673f01ebdf41dc59181a6b1aff1a0244c51491dc13cde89b7ae04103b09f6e1b80c60f6c7e70a35fd482c8b4f392074a3ffc37a12b59056a507619c94419dbd6c606464ec07548a815ce21cda0064435d91622c766d6e4fc93244f220b6c3edcae8164c8991c969
+TAG: 35a2cb45ab6f16f5a03ae39958954ee92d86fd0f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755e556ecbc368b057bff5a2970402a0c1d89197caf2d640723f759aaf0b005093d3d218e8e680c9d64f02e0e699c8c4e94335ef602f32c29447c6451a037f597316ccf321767114aa74393d94546e5b22facdab76ab0a933d9368b16979492c7841bcf07a369fc2aed62d71dc6efa7c8d0760b8cd8522616ce5beb77c7
+TAG: a9a4e6994b11304ce80719d9e1cf41ed72006f21
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755c544a7e585e77901bc4a54b8ad310c407373a22e86e5d161ad3bcc4bfcd7a354897f2d2979a9b66bbd686e3ce4e7469356e52c38e3d0ef63127949146a611f76f902f4e7d84bcc67e3b2e0d3f0032c721b52f7d10a7a94ac33835d25b8c52193c45ca07c588257eb52b7fee1e72094c3a71396aa514ecceaec9970f0
+TAG: 9d336983dd96e9047b62dcf420873a594ae8588a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d96473075584c00ecd11ac0d712b7b153b81baa5711166518427888deb5c8d9cc3d897b1877d1e633a407b85616ac6b0acbc469dcc265f4dd69058db25b7297b5230f333793604f016ea7f70e6bfcfb1ee5dbdf46fe8216de7cd05f52895aa3d04f6f156db5ff2693038764da58bfe2a277699cdd94d353e3777eb90ea9c9e74e0
+TAG: f78dff2cd0ba7c9f53c9553330219689c218b138
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d96473075599b8c4fdb981ffc11d969686b6f21e8aac99c8f1b21741ef2c2c14d7486290fe987c3845522549f00d65659e395cc8614a65c94d3bc9c8efbe9fdae1446028c1eb4bffe1123d8b588573fa38b9fa5844b8b2c5d91d19b56c5c816f18f2b3e2eedff827c117c9ee491f47ad40b90394df755888bfbbce70043fd4c0c0
+TAG: 5dd165ad89a4d901538342b72f0f2a248a920d3b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755c85229a27773497380fcbf9753aa7e4b337f41127b86430a3466644ea969d5689022b4b84c3bccadbff1048d272bf483f4f1da8b8d51235a8ad3be36c7b27dd8281c665417a7b549ae807aaf735e23086a31d451cc3f813a1722470b3afbfc9669a74093c9f106f9efd04243c14bbf9d54259875eb06640e9957de53
+TAG: 2441d6671f18ce8ba4c6d71d61a157cb886593c1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d9647307557ff9c9e9714174086a090dc25c3670916060a709b8a3f36c81428424d22fab3b9023a34642122742f5b73d856b48b69f588e5e603ff0d20b55d5f5fe4400539bb246777c0968d4f3d0cb24b5e78ba7f3c353fe58dddf85fb9e4060a54b3b98e4a7ddd5a5bc11912d68c105053a6eebf5545cf2a5202cdd91c062c44a
+TAG: 072fa81d3a6f485e68247f222dd9edd0d2fa9aa8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d96473075575bf7772e7ffe02d8a18f2c9e48a3ce20663e1f6d4c4730b05ef54efaab08e756843a83da0f1a4851c4aae05f360fd8b6dec19bd7ce25e09250d7a9f530c84ca049bc57c74237e4ac04bd82df132f66ac1aad6e9d2a08366bc5d394342347d46e7640acf1117f0e84019ca4c80dbe052e81b8cf24df07a7ef5ab6e1e
+TAG: 009c73d7f96a109d20ca425b18fe734c44396539
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755b1479a16227373165e86d5091047280126f9271e60c33f9888acc28c94825a1f062c2d7826273694d0bea6c1ed0865721a721c8695866cd6523c559021f53327e2c3d33fa80442c0078c5f924ab13942cdf42e7be3d35e211da60e27eab9cbf5ac646699d58496c9a4718d4c06c2ffadfc779d4ab24b92e3d6cb9faf
+TAG: 3cde03621ff510bb724fdfb69880a7e2531a9418
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a29f1a0269f33784692328e48bb93153e08bc3fe5643aca3661b1c08f04b723d1ec1825d95462e2bbba5145fe6cd032d7abb62cb64766fceb12862f8f80565d6dc9b19b67d7b415e90556cdaa4fa1d960576765573da906f9387ee35673186b3c3a1ebd00d168073f6cfc883eb
+TAG: fe9aba81b71ae72d8d5ad8b88728eebc986b144a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a26ca6eeda85923ff8930ab9d246ebaedf2e1c6573eb5a655a3e3c23434d06ed3f56e35b583b271758278c9d2eff6366b4a21477d1f4938d66a2f1ef15f17cd0216b65731643c49a37f4496347c5890fdd224f1abfa97cb671ec5a8801d2cbf9c5a5b290611d8a6bd603fe62cf
+TAG: dbb786af8b10e46aaad69998576892d942d171ec
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a293fa0b5575fc4523685b5a41ce5cf96bd651bc24b10a94e5d13ac7636469487cbedb995d7cb66bf3515978b55445deb12403d9104a70b6aaee51aed2b4c4bafb5636eb2bca133bbe3f49b929633f031af88030047fcc111faf6e4844b1795f70b84f5c3c243d1171e0722d0a
+TAG: ffc9e36fac92f1d6e54ca738c2f8199670cf5125
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a2409dd1f8c1432a97d85d928d56cbdf535673f28255692df3569c2fde45ebc62311c9e0ce570db0a825198a9523ea266a3519de3f8abf3fe2fda2b06e1e7ef16d64c94ae2f61383d1e45ac581cb385ba8924af528da7cc765af0a01ab7a537edb069f388ff601641d0b1ea110
+TAG: fc992ed81a014b8e0e439557453cb87ac1640d40
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a2d3257dda63c1a13aa944a44405f46bca0744d9a80b90c1bdd04f59824c9f0d2a8d588f0ce6279609f526430820b04bb602788e966ae3f3a202845e452f7f4d13958a01252c054cb12ac6f37cbbfad5cc3975e4f52d7854b5902576758771a272de1188cbb3e023cfb23dfa52
+TAG: 3751661f20e3ef6f5feaa209a1e626ab114d0ece
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a2d07e56ce493c29e8a21a7d6a8201a2ea3b3503713a73969cc93a7a25dd1cfb78de450e616a5a0812070dcc96477ae0dabe5ef9d651c51b3ae4dd85f867284254997a47a25eae08cf74862b82d4411d30ef1f383c6c4a5533ef5171ff99c4f7b25bc67e6ed63f6fcb864d38d9
+TAG: a07e892eba3b2ba7e80bc6ce5d50871f400ab16d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a2d32b30086ccacd9127cd3bc7fb84e1863553cfd2c8b83103a5adb10a01934d6fc19a59998bbcecd01b40d0ec46991df747e231f3d3529b54bf86c5897e4044d4194547fd53a419fa607ad52f108c78cda91381c3163aa5454b29f7722c8009f844503d19df1320ab7cd541c1
+TAG: 7eb58d6e745a2b1dfdcc8b15f3938fd973308f8a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a27fdc021b5694a80a54e22e29cf78ba8b8fa74c05afd03d1fa8a8b5afbdca6d9822be6d0859cb63b6c11bc6718da88da8ab1bac2e37172188124206cf9444fb73b295e7e8b0cebe829034648ee8de583c3186622af9895ea0c3480dfeb07a1c9e3dff4fb78875708ccccac18c
+TAG: 05382b6cd7e7506a9b4ae62a438d33a5011377f5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a20c13a620736cda89d7f23ea1369e61250ad2022f4d52707d1eab38e0717ed8d764c8963c1831edc1ea1ab03b10db7bba6b2bc5a0970ac733308b392fb364f2398bce8a1ba5d5fea6393ddb9c9ab961712fdcf7618e1e06365cfc29ac4723e8beba93ffcd9092742ed6e93d6f
+TAG: b8fd1dd37a8ce48d0875a25efa02fb79d8a8a88d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a29755ab3556ab129653a8b1988336c299924fa59129ea043592c6b7dfd4a4a6e981d48531797148ab7442099c1bb107dc1074fe35b080d32f23216b0c93e99f942283fc684d98ba4311322410f5a97c77c5af380064288f6441fbdf9b242aa4a1f3a4be9afb1f54dd494bc590
+TAG: b030771b4b179760631c549c55a7787f91d0f5df
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a2926bfefee6599740193cc53b16199ee9938278a7cb7066708379ae8788ce795e3756677941b79b9d04ad9cceb2d70318df03594662248761a48f6c3c60f642073189d0aa12431eba81c56bdb4414abc37e33ec7272d964dcf9b263bee27f3a9371c148cf54e64c56dcdfbba8
+TAG: a0359d344d548b0f34e471004daa355a079b2805
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a257bcaffdd905a55bfad8f14b421000d436450f02100da3153229a5a5aa06cd72d23a79ba4a0ed3f882bd6475d9d79f746a31667a6d9abe30e32048e8cea52139f0cf6cd4571b22e16748d304b5f5ae3d5656b100b103874795f1d512f390f49b4a3988c64f26b7f19a8f03ee
+TAG: ff98d2094ecd5fb69fd7a07aaed79f26b4c1af4c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a2fcf45b5609280ab5289e83d1fc7b0e718d6e7576d0ca321fcf4d3e4ec5957ced6fba222cc007ded0a0ee6808a7ffaeefe7ae38a4333c146ea839b4957742b08ac84ebeb82a3ec9aff3b1bfdb6512f747dcdf3bba66fcc575ce05e0209257b9287a435135f3ee9f3e42b6bbd1
+TAG: 61f08901416752f7682d7e0c0974e77ae15e6ea5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a2c3056e523476e744c3c685c9e2490b1e9f9f875206a4f927058f276081f13a4866dea5dc61f280e4dfd1e74ac93745e2baac0167b5db2b053bc0604cd247e88adc2a7499cdabc95b3ce7ad2a6c1f15169c80fc4ef0b736c0918a752a26a3218521b12918cc748d4645e38309
+TAG: 8f63d9e94f098de766be5dbf4bd2ce31ae5a36f5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a2c3f87d634f3ae298542d4096f355007d305c09bbd6c8ad6140547ea5e6124493416ccc36c955ca44f5b0a1e68c694f3984341ea1331fbac70ea38879374b7cdba07fc8782e37beef5c2abbb72def986ba33dc1635cff6d7d69eec19d9b8327db7f1762cf7587d8a948e00231
+TAG: d7e1bbbc7c7d8eafc48039c69142615c1e2feefb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a24c06ff4e8eb6d2c150616a8997959343781988e25246afc84e474d3abbf6554d40d0a8d2a9bf5bb642f248ae89d2b4fbebc825561f220156837655e1e8b781c2fba9230e2f1565d0ef4614f43126776040ba4acf2d316a1a77a82a2d0148c0ad707274bbdaadd3d7dd336409
+TAG: 273525efa70c5c854297204a961731c28316a1b3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d822e65c7dabde1f8fa438db3f55fa40574ee38cdde0635b3f1be309171093735b7b66af17a72b1866a744ff175c119df15a636b7baae23ef835808b1ed57278628fd8c254de2c6a1f8c5aa873834bcc33fdf39d5ce995b9d554d07
+TAG: 30f93c69c5055ba30cde5571de0c182dc5c57f57
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e83727316a6760bf6d794d02a90807cd684a5fd1ac04eaeb5e5d84aaaa97a61ee38a1dd6f22a4505a599f49f0c62196198c6a9992cf6d84eb795663c432c710cf206160580ad003ab6a85f1a1b17d0ae4f28d109253727a5cabc5126e4c08e
+TAG: 7e2c1739c25b1610ee9a4c5f26f8090081423030
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837278ecc3cbfeed37a919e1dfd2a2c52158d5db7c8a238d5a977b9949f899755307c46f27f68ae0bfd772ad373823f0cc7803889bf4ee4ac9e44f9d652b7256894b12ab02a08017df99ca95846c70437557ac808f2365e5d88704ef3ba78
+TAG: 817ce8aa29c6cf5ec415294a2f6037fc304147b3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e83727b643f67a9889e20fdf70b340d52341e34b6119666bc1ebf48b47499eb1f203101fae598eb4f820703938a0b68b4c693c4435137fd8f182a27c754aa3f65eadb39591445eec852a004dfc50a25f5e56d1c5254ddda0d7c0fc0872f2e5
+TAG: 0c7a9ec57da633ff164adc5af4c5aa18386cf2e4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e83727905342ab22c46f8b90c2d62cff112e2b21a41a83073bf6091045465c3e35cbf831c862b133d580456625326c78c6845bc7b6d852aeabb094ad7abfe994d8c242d5309dac2388667e7535aacc0a62fc38fcb40080c2f1443692b48ade
+TAG: 25f4e5d7e8dc62649583b5abd53d606cc9c6864c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e8372738ccf95f0fa2da9c9f23e23743ad51a81e0345ce627b43b4551728805088a0067c26e92b71d6a6c1e62fe9b0ac6bfd1ed62058897611b78a5ee6b6b9640c58ff4bac4cf472c8d040fb9d5410efcdbd61e5aefc59bd95762bab0144c5
+TAG: a6cf90bf4a24816f5c7bf879f534def6ce116227
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837270413f83bca202386bce27feb2fc74e8c84bfd98472a989db99d1964a59c85e7e153d44e1450571b148ddbfcbb6c58568e08aff0f54529d8baff7b24ea2f7de08444b20455667154b3ef6597d71ab8cc8868cd4eb777133c6eea73843
+TAG: a93db5973b8e112f271bc261f3d7e5bb97e5dd09
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e83727c5d2129501e7e20ee49504cdd029f01a661999e733bb3ca0bb64e9db77809e84a1829df35b4be802e8a6107d3e2fc7b2a2acd9e132196b5a0f0c6d11850488f726e63d292320ce43e338f8263b621d2c945ff8d5672f6aa3dcbfb075
+TAG: 7cf583bd2885253e78d9d45dbf6990666d860e83
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837273f5ba538698801407903fda70224e2ac537ee5a997415a028d4eeccb00988309d80c19dbab527f523a72fc454c2978f79942eb5883e4ffb995940d011fcff4ea53f6fa1a00665716ebc08ccb20503e9e9b1fc6bd979c1bfaa788ab91
+TAG: dee87c0b8db2287576869dceeaef742a37c8d1d8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837270fbc23dd66f560b6ac542b68dd0c9f3751eb78ac147e59655ce241ecc8e5f65ced942e733e7f0a49007d2a88ec8f38247414d6b32d3bcd9f3b32663f907f2c068fe46a4695136af9678affab9f059bfaaba4b2469d6decf7b63fb1b8
+TAG: 490edfb09163500c4914b47604699ced055998d0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837270402ff5b657a6a85abf55282f29ef2722f829c12ea5c21a1798aea2d168cc494d618af5ae8e8a5bdaca25c750a13d70177044cb79b023368085df815f03f2e067f2a83485fd7e1ebd1b47537ccacf1f73157ad786b69ca7eb3bcd3b0
+TAG: 301b69a52342275476409dd950ba98304ca656e8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274c1338dfc80251359eb4a1a4a4cf985e41c1b094e35131b13faa311f562c3238b42a195c6f3bff7a1bd35f5ba44c98d1182763bcd14bb431ac8e1b549334267456cd968130c9b3d5503de01a70000066fa34e2b3a67ce93d6752aeb7
+TAG: badf7a66cb0dd3b69bd3aa5c406bd66a29dbfef5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e83727ef4c0e2a21463f63033bfa850e93f95a59e41be48fd92d6fe8253bdefb6fe9b50bbef60a4726bcf52b35939293deec2d3a7669fc55390282e8a038dc495ce186a3f6b4e72548caeec6cbefed1902ff9fa0b34e6e687ee4ca60c2dd8a
+TAG: 081b046e3a24323006feaae8961dda09bb245843
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e83727a9c57116f34138f974a770ee0b9ab2532af97e87114c8458faa15cb7470bb29dffcb4217ca79d52cd55acc62ae823e219c7e6e305c00454686fea301ff22da9c0a27ec11a81ebfcfd6a3996673206c908a490a1dfc4f174271da6863
+TAG: fedee8127961793602c14c5cc9e28ac4badc1585
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e83727b529a0acd69528ad14ef557e1ac030df5e522017b4d7d40f987d0c2aea1f9f5048ad2b74fecd7ff68c7ff99014971d7ae1c486e509f5dbb0762478910e33e4a4fced74f7a7941d7ade9296c9b7d64b663c492184a0a6a51538762be6
+TAG: edad53bc23bce1cd94f391b8e949e001e08c3452
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837275a9bed13a093eba15bc4487dec5c37921e137a38491e7418eb0c5fea4b033e5b0a5754deb6b2185c473276f3e6232c7c6890f897120b0802086b17e20566c7a56b4ab97d6ec9ab3bfe7d3be1e059f10b3c2cec338725e8bb8e9165c1
+TAG: 1cb902e012dccafdf8d312638ea0a8de17e263c1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f6258b44411c4d4c99b48107483600e090c7be3e0d58061947d0593ff05417313faf17b265a6b39f1d1483cacd7cd44654a49f6cba6545dd4369805640d858efe2b2d7c39cf71aaeeae85f755
+TAG: 93485b6d19b35d8544b559d4fedf346d398e1c85
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f9122e4ab9c56bcb885443f3dc949aea1ff7ffc9eb62fc90830736c1f4dbebf4b1867032d43bfe6a493a466a806940cf493a736f093c082bc35351eddfa593f057451dc956dc05f3cc7c1d52e
+TAG: 5d2b8a7f2fc38c6a4d77d5e8ea1650da7ee9f279
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418fe3448d214d5ccc09445ad032a568a3806e274d23e56889632b843de29f992cc0b294e9a9195bc279a1ef0e5ebc5789c6449a259d497331eca218245cf399592f3c727410f13b38b7eafdadad
+TAG: 952bcb58d2055790eee734d237e250873b77a889
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f79be095619fa69a5c187e75419439d5ffbc1a314d799bab6c3a2b270da623e971ad1892d212751600d31b181eb61784f1cfd500b6e71070d1478b61cdab7f6d80d6dae703a7c9214acb62faa
+TAG: e2610f59455021592d611c1f5ade028c24b70938
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f07488ccb5bde8bc7848df4fd64ac89366c4e1eb39f77fade5639bce857a283d733f3334bf271537e3f7b8dbefae9f4bb18eea3ed3ec9c6582cf835077bfd97fd4702f0737bdc86f3824690d1
+TAG: 87400b69d3483acd42c7ab3493737387cb4c8da2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f704a0712b3106622c1752ed984a52bced50373a2e65bed56b7f778389160bf7282fd87490692dc0ab17d93a426f709c5188883b383d7a2acd83b79d8086666b87c1f6bc942ed5fce6bb72205
+TAG: a9a3083af640305f2b6cfd02242ad78f989fde56
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418fd39789b82859a5acaba7f54c6ca7fba5171cb3ffe7a8fc9959dbe273c8cd22bd110b64f42c6b5106f41e4a45471a1348fb38e2bf33933804908416129677a986a2aba4aec6b707ba0a9298f5
+TAG: 5be8f8bf0f572a4e35f06dad2472769c233cb152
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418fc317ca838f2ba7440c425c42eca96cf8a448447aef35a60b294c3c900ee39818fb66946ccac474b4bf044d67ecbab66c50e95073bd3d4804c1b43efb1b4cfce2cc8f5c7f72aeb120be0a957b
+TAG: d5061bc98ac26f6b76be105779bea2e8fe7fdd02
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f570e0fe074a5770f7c5daa353c83cbefe0a1d502dd8927ea68eaf45454680f94e0760c5f4e14c3ceb2af92d4c982df14a44b7ff77fbe51bb8de90de4865adc46b93c0bd98440183141a96b8d
+TAG: 580d6f00162644c05101867a765fe29a5d0e3b0c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f501553557e1579028b4aa4f77030a8f808d7a58f16bc155eea9071b71a5a3473d332ab7851447786b39e9d5c5ae890c238674581750665a0254287838cb4040b7b65c21496a3a59011b422b1
+TAG: 26f9168936b0806e15a5887425826f381aca8bc5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418facd56a5ee504149d9694fba00bf6cbedc5bd2c49404962cd6f9096af195bdd92a048384c9f20e6920b46afb12bf031272cffc81fd3c57c3ff63cacdcee28577a247ddcaef7ef678b9ff0b0d5
+TAG: a44dacc256e4b025fdfcc58315e0d5f4e8a6bb0f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418facc46e59298d419199e0b1e78cb7612ef03935b4e6d09a42eff5ac61ad459e0868be76c6e58e9c2cdead64655a52e487652116053cc0e08bc861d8231eac23e8f21d62406f73e64bce75cd27
+TAG: 8cb2eba8a56a53524fd3da4e05744158b6aa197c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f7c85c01f0ec6700b475679a2bc7fafbacda61863191bb9c3e49d4a606d01ed292f46721f365e75c14da6cef55146c6b801bd0c61c600764eed76087e2eafacd87734bf73705a4827238d9033
+TAG: 47cd94a848084718741564e1705e09bcd6b20075
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418fb01065dc180d664c5ed57d91439d3d175660dd745a6a04381ddc3d71c593b5646b1df8bd55c4cce476072ef13062e89e2f920fd3314d1d856c181c53288fed39dc3e75b56d0b5895610b708d
+TAG: 86e5921a6098de8ac1516afc621d203211a471af
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f0f80023f1def876fcefac74e941e8eb4f5b22ec2efeb723935b22bfbfd6ea53ab1c3e7b32cbce53a9789fe36378e5261ae839901aca40455a14f6c585aeea6fdf52ec75aee3764e73a9e5a2c
+TAG: e636cb27df5b3b44739a2b59cf267a8adead91f5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f67186a7602d1ab0a831867c101cbe9de754aa2a8754922a66cddf24e96e8b87e124ca69bc96b3a61be005f899eac7dd75f36c30b8ac20582ca87f7bf40ab2a8f5535a625da404a2a5e91a855
+TAG: b54782ede41288332ea4d59a9ccf3a2cbff26df2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0fed80faf72aae6081dc990b2cbdf2173dc7dc6784ab808d4acc756161f1cfb16a0c2bd2032b405a37783449afee25312a028d92f23ed743e9522c20e108
+TAG: 833d799565c76abd0e28f5a3521e28cae36c0a04
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0fedb731763cf30c565b1f3aba51bb36aef3356be3760ddff0dd9dc4b3a7f473739ba241c38e6d3fb0b8c55e226a1cc028d29234f8472fad98d37f945cb1
+TAG: a5cd81bf3dd823b0d8e6183a74ee7f0b3d9a5f62
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0fed637118b49765712d85eac6a2c43128d639ded7003985c0b4f912744fc9e691800a7bf18e26a703b61d17aea20a0ec799e4a893ff359893414df06a4e
+TAG: 1c9eefce96c6ba58168ec0b2346e7d1933675fa2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0fedfd8f7659aed85b17eee4c6d620cb20fda28599871bebbab3e9750a281bce8e0c942df43e112c3c18c8835b447e4fd6e63188dae60738f74a94dcb438
+TAG: 16ae699f64bea0689695b797ba94838401f4529a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0fedfcf8198aa744a7726883480b14449517140f4e651eb870cf5122b762a86f4ea7372e70b96c6b181e40b68775b4f747d3124def42754a47acaee7cc34
+TAG: 45a14ea7e98755d183ef9f2ce18bcf0b54e850c4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0fed4ce8db8a268d302c582b0d6ad094e02b3e43dcbbd43fa674888d94151bd02a9c131e66d135bfa59536f5766ecdb63621a6047d66c1ad10bd515a9633
+TAG: 3575e6c61e37333eaca2bdc407a1e4fbfb86b076
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0fed671b32eb3c609eb963b7864f63fb1d4cbebee5c5310a38ba9e0f122631de9c45b9dd453191a1ed8afe3d89ddca7379d8e8b50a7672a521c1638647f3
+TAG: 47351cc02ff5f85754494f3ba144fa0fbc8b4ed0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0fed681d7b429b4bedf78b4ed01aed991bdd3f33a128e6465e51b3428eca6ec51ac33c487e92a579680d77f15135474da6410507c23c6197d5885a27116a
+TAG: f4a9a6d117a69232ab83b9b84dcc9c7e76ca492c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda6b0f2ab20ab93bbc2c44b961ea15e4391d98e9141bb4792ce5a3222c66e99c157efbd6fdb432ffb3756baebc84cc725b6c7eab736b1a363a013374f
+TAG: 28a3eec7a748418d56419014ae7dad17cafe198b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0fedb7958a9d1a5635587ed316fb43bc04e42c162115910d4c11f42dea1c6462176e018f6aab685c49e50654f94a4182c606c57f98534253b1d98ed1b702
+TAG: 0211cf5d19074a17f94c3ef0429ee3b3866863b7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0fed9ccb93abf2529cfac39b2b6af89b5c926e0631656dd0916bdffbb8486e0ce7c9bd96a5d1cb82d9f2e77988496fb42b7b4cc3a6ccdedf0975013eab1b
+TAG: 5de8c7ec225155faf858d32287af0c235a275852
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0fedc469c1fac1cdfce3701daff433bc0a211768f0d6946cefdcf878922077b9e6930624866f258ef4e6823e1c9d528def4d02bad56293b62d51a70b61b5
+TAG: 2203ec0eb855ddeda13fc282ef61af85e72415b2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0fed6c64e15b1f5c81edd49bff9c3076a5c0f7e0288a483214c6dc52e7b38027e69a2c70f1092def07a7601534baeb3f5107a6ff5e8420da5c5007efb3ae
+TAG: 7b665650cc7f16cd3c98b11a950fab8c52d009e9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0fed589e6695270bbb62b08a51779317aac9112f6b66bd586315ba779dbc0e8fe8e885839b2e1cd66f88c9e7f6c5bbd3a2008bdc1ad466d13c215c6349c6
+TAG: 346da741c44f361519ef97674b0ada039a53343b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0fede49e4688fd0e7b50ef8dc5580dee5dcb18399704a89717373a7197f6e55f87b0f0e9e249fb7aeae2fcca31505baf6eb721be0df399b9191325889bfa
+TAG: c5009972328a2f9113dbc3358f9c65da1a459cff
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0fed6680f94567cac4a030cd56ec0d6e8abf2f0a368314320c43a248f9380d5511ddb7df60ba994bcb0606109fad58a1e46ad077dfb1827ff6963614f9c2
+TAG: 10e0749fd8fd37d719cb1b554f88043e17b3f9d4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551d617dd2023ad03e1f8acaa4b7e820710adfd76d72df2e21f977edba61d1ed24c9d14d79337851cf0ef9de6f6
+TAG: 42fbd91d5acee688e08e8d2e7d95d3d8f3665cd9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce5514876c1f89ce84a07baccfa91871fdd44e21fe0f2ff8b45fa40d82413d5ff89c1312d518aadef8f57cc55d7ef
+TAG: 6c68dfd4dc48361b2964251aaa86c894a6d984c6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551c850f1caf6e8e5547743ab1499f46880b86b77751d28ebff6c96cb6d099320a8574ed3681d9f0bce4fd97282
+TAG: cd67dc104bb63a9c2e455d9dacf705d67a46ecc6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551c106a8d2dbc92fddacc74632f08531db377e3d4be4744cffe39f9f2070ffdc14aedd21c639bbaa5aced10c3a
+TAG: 6f6bdd98a4a4b295e13dd40bf0677013eebaaeec
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce5514be30a285b8cfeac3d9f7721e5bcd56aff40c88f79bd484514e1da9518fae24907da7c1b58df127c13cb9e61
+TAG: 9736aa4f2a9cc58651924d5b99441ee2068cbadb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551fceb5da3b0868911b8842406be94fc773187a868ca34be1d9207c37c856db3d18dcf9f777b8d057b674837da
+TAG: 04d21adcef2b1e8695ea244e6e335cad36247ae6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce55141ea4c270bdc979af52be4b9af5a3df386812ae777e776c5edeb9cf960bfd272ad0e597e9d323f5a24a39f92
+TAG: ba1326af7baac9517aab6e40d0f080fe510aaec2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce5519982a03ff99bc342b3d80bc4b7bfeeb8d4c698b7ec9a9e44f29389c90de2ede1aee49279b4e275c6b121341a
+TAG: 8209a0bcb4a17840fcab90db3b5b22f4fa971411
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551ec7b8f4b61ecab052044bfd1de1675bc69278741517f74e1f90e2d1bd3cbedd3abcfb4bb8e1e7783b4fc8dc0
+TAG: 523ec067ba2b8c49d93941ba7fcb86165d0e5915
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551de676a675ee1dd297eaaf79eba9675839e81a73592dac2814fe9c172ec53493bd7feb4ad6e700e2ceedaf506
+TAG: 454b8c86e6b3ded5b835783edb2f126f3bca74f7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce5516ab535e445b0b1bf1781db2ab8f0757f1b7c64f20bd51aaf89e9cdabaaf2dec6a40c006884ff763e0057fd1b
+TAG: 51296294a500d46b895da1eb8be6ee49f4758e0e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce5517cea5d8a2b339f3bea30af6120f87c08fa80b77b18d43e1b4e1d543ff8368419860563a6697581c4624e90b6
+TAG: 6efd53d2b51d2aa81ae45e24568abcee3a5e685a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce55155b026ca32b4b9df697f4b957a4fc5d0caad6e9eda722e783af0d19b61228ccd3c4e685e1b713cbfb01cb6ac
+TAG: da797a703b847c889d78af3b34ef4c9d1ba0b91e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551886ba9b3edff352890eead6f67130ef6f91086b0481d75dbed4bf57a769529dd3d1f4bbd47d7a46e8566957d
+TAG: 3e70fa078055e0d328208a4fa1c81fff363b6761
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551b828f14ca8485abab97c74dd2447cfe3a8d02ebcbcaefc5e260498678443a8d9ad33a0db7982bee87c3b5a44
+TAG: b0caa5b6679a6158a71e85a48eb7bb3679f233a7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce5513911fb3850cd6224bcdc2d1e2f741301d2751d50406613e85ac87cf6e403eaa607f3051f805c42d602f1ee2e
+TAG: d62f52706bf75ccbc2ca41993823b45faffb6974
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a0b0b9093c6ccbfb8131e7ac50b30774a0711cc3ce5877e6261886a70
+TAG: bdbe03aa3e7b6c7c44a2a3b19595d6c35b1392d6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a6b0044b2fea338a3b88d4692154b05a29a1c3b4849666201bd278ae1
+TAG: 9776a8ae5fa5d3d3f778341db564bf21d00db806
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411ad2a7322b17e2558050076e142cb18d5554d5503791d0316beae1068c
+TAG: a94cf13b16ba42f0e8d673a1a6eedee171e1fe3c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411af46e97955798691d35a91389b438fd00b7cd4970f588b7d1ea398086
+TAG: df1e5b2786e225c20eb14d4ec10c31b316d5079c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a332c56b325500e8649ebfeab3d5fddcc3c3c269bf0eb3e049650956b
+TAG: 1b80cef89fd7d97da002b21694374002c8433752
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a50223ab0ece0f8101931c3ab6a8fa1a768baf90fcedbe0fd143d1c0c
+TAG: aef7291680f17ce3b32223b7d779df978f94a887
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a062f581ab1cd9acec26f8ffb0559e3179c23fd2ddd5d38bd8509635d
+TAG: 9bada1a97dddc471d4e2d0ca2afc7dbf09202696
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a2141f11f47f712fdddc1b89efe106f7cee670a39e3044a734bbf685b
+TAG: cd24585c7303ae863d3c5051dacf0b4b56d7e93d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a0f072d0cccd76eddf65141dac78c54366bea2c89235b642ffe7f1c17
+TAG: 308d7d9248465ef50634f8a458fadbb9cfd73c32
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a600628367eb9eda5ee8ea20136e7d8c53fadf4da0cf49a56ab726ff8
+TAG: 6dbfa4bc7a870d9894651d3ed96a68ffeba1909d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a819c9e76e1a12c96829f220d7a57e4740dff6f2e908d204a24273beb
+TAG: ee430a1677366d1703dad09a9a7953d7dc5a55ab
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411adb2064385c88068a9790ba0dc0bc321ff94f4cb7dc45c7b53ec8d54d
+TAG: 987a535094ba8f3dcc519dda88888ee316f9a9f4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411ac3d92bc259a957f3465fe598bafcd5703e6c6da0c647f4ac6506497f
+TAG: ad4dceb1d591f692ab0c714c595efeeb90a59b5f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a6aa2db99e526ec3bbfd1491b63e89b845a4f1a43b4dcc093816766f4
+TAG: e7391790c34bde1a8fdc454064f2036a77fc73d2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411abcfd68b536800cdbd54a1ba6c3759cff8253e22b1f2792077f932543
+TAG: c181fedd18c26a4325733babfc8b646e3015ec95
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a0981378e7c6f7058fec887b37a5755f6c7d730b445aeb33d83ba8bd3
+TAG: da203d8e232c3771dcf8251e49406a73e24102ce
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a4f8ad2cfceec3703d4cb0591df6964b4c9bbc968dd1319a79c9de334
+TAG: ad43c506aeb3dc184b28be92ebf8f6bde7eae301
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a4f8ad2cfceec3703d4cb0591df6964b4043f2c27053a84f6a6d63a9b
+TAG: beb48c5b147349a1da6c8cfe90da8fe169e7187a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a4f8ad2cfceec3703d4cb0591df6964b4d684b965bf277a50bed907e5
+TAG: b385c99e11aef087ba2a9807eb5dcd3141a9d64c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a4f8ad2cfceec3703d4cb0591df6964b4904791a25a64e285276e282b
+TAG: 9b2386cb3406b9eed29480d3e3752fcb6f38b4c8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a4f8ad2cfceec3703d4cb0591df6964b494350db6e4d73e4ab2154ee5
+TAG: 06a3662f49a30641dd2549b764115bcbe4bc74ff
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a4f8ad2cfceec3703d4cb0591df6964b449393fddf7bf8c1909f9f9c2
+TAG: b1df7b4dea63a731adda91f22625240540e2a8a7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a4f8ad2cfceec3703d4cb0591df6964b4e13182507c76fb35b8e5e071
+TAG: 9055eb37ef7823b9dd6e9d32900527435ed66a07
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a4f8ad2cfceec3703d4cb0591df6964b450a8b42797b1aede6aeb73d2
+TAG: 1957d268b64088b90a14713237c9f7d66fdd6115
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a4f8ad2cfceec3703d4cb0591df6964b44587e02aed2e0051ec3491ad
+TAG: 5d92489a76e5060b20a6b6e26ad8d4e69c8997a6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a4f8ad2cfceec3703d4cb0591df6964b4248691932a4944764d99850b
+TAG: 3ee8ed8077fcb04c76f94f1fc499d39f45a56d34
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a4f8ad2cfceec3703d4cb0591df6964b4ac4d33527d16e38e9fe59463
+TAG: a8433cc1eac312e40d8196c25449104c66854ef4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a4f8ad2cfceec3703d4cb0591df6964b4eba0e9b2cd4783587b5bf1a9
+TAG: b468b727ab1e0248fd48b03d935f244aef9678d0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a4f8ad2cfceec3703d4cb0591df6964b4671d4d2d9f4d72d2bd29e72a
+TAG: 96524099856ff5f26c30d1daec616b6b5f3b93d6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a4f8ad2cfceec3703d4cb0591df6964b40682c6c78c9399c4028b5236
+TAG: e945d3714be4137a61e53f597edbecf17a6b1710
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a4f8ad2cfceec3703d4cb0591df6964b436360eba03a25e9aa88458b7
+TAG: 8dfbc7801690fabf029aeb03882214a5b00c7691
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a4f8ad2cfceec3703d4cb0591df6964b49eaccb002262d7468b401237
+TAG: a60548b61de5301882ffa8168b6d172a8ba0937c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a4f8ad2cfceec3703d4cb0591df6964b496c6cf7d5499209352e513f6
+TAG: 4d5d3ecea6d92547492f03d5e5ff50a4dc4711b3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a4f8ad2cfceec3703d4cb0591df6964b496c6cf7d5499209352e513f6
+TAG: 4d5d3ece9ac255e0b2b296319a5f65e8ed2cfe31
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a4f8ad2cfceec3703d4cb0591df6964b496c6cf7d5499209352e513f6
+TAG: 4d5d3ecee2f8690858a41d85e0f644f2674b9050
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a4f8ad2cfceec3703d4cb0591df6964b496c6cf7d5499209352e513f6
+TAG: 4d5d3eced639edf3d5ef8147431e28e3fa1364ba
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a4f8ad2cfceec3703d4cb0591df6964b496c6cf7d5499209352e513f6
+TAG: 4d5d3ece3a19bcfdb9bc6665ba78e78700118e07
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a4f8ad2cfceec3703d4cb0591df6964b496c6cf7d5499209352e513f6
+TAG: 4d5d3ece199bd309c295062fe0a9c116ec2aa55d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a4f8ad2cfceec3703d4cb0591df6964b496c6cf7d5499209352e513f6
+TAG: 4d5d3eced1be12596885a4482c372fbc999e8331
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a4f8ad2cfceec3703d4cb0591df6964b496c6cf7d5499209352e513f6
+TAG: 4d5d3ece17d505d0fce4b284a84fa2b020eeaea5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a4f8ad2cfceec3703d4cb0591df6964b496c6cf7d5499209352e513f6
+TAG: 4d5d3ece92a4ce0a653a1e6b18ed1f5f1d927b70
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a4f8ad2cfceec3703d4cb0591df6964b496c6cf7d5499209352e513f6
+TAG: 4d5d3ece61ca0c5c439a3921780a782b08e8cfd2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a4f8ad2cfceec3703d4cb0591df6964b496c6cf7d5499209352e513f6
+TAG: 4d5d3ece000c0dcc51787ffed877d2381caa4849
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a4f8ad2cfceec3703d4cb0591df6964b496c6cf7d5499209352e513f6
+TAG: 4d5d3ece87ced30c5463889552813fde794321df
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a4f8ad2cfceec3703d4cb0591df6964b496c6cf7d5499209352e513f6
+TAG: 4d5d3eceeccd29ddf40018eb10b2517511d0096f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a4f8ad2cfceec3703d4cb0591df6964b496c6cf7d5499209352e513f6
+TAG: 4d5d3ecebedc3c8ac1ba6d6e494f48a398f986c7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a4f8ad2cfceec3703d4cb0591df6964b496c6cf7d5499209352e513f6
+TAG: 4d5d3ece489362158d06c02bff6e9c8be4cd8e7b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: c24738f07b81998c80b1c66a0d4e9c4c2f6c80c13eb9e557e70768f86382a300724998cfc1b0850270e9b4c425ab146e770a444418e57b6ab4bbcb78b2f1140cf70cba3bd2fca99aea70d195e0beaa8526cab8e0c0974e8d740415efa40204c9dbaa299c612ffd92be07f0dd4c548963dd5744703dd47a8a30a7ef46297401e4bdfcd23c932635d9f51cb0cfa717bc0a991703d4c318af09a04c664126e4018daacd226a92252899615554d964730755cd267d679f17dd192be9cff2f59317a22e2cb22410db7c19a3d94bb941e837274d31fb35f602a123ee0e2ea0e4e5418f87ea165b4c53651156fcfe645e6f0feda51988c82d2ec5d145f7e378977ce551e32ad75dd81d22185a6818703841411a4f8ad2cfceec3703d4cb0591df6964b496c6cf7d5499209352e513f6
+TAG: 4d5d3ece57c5027481c12c5ad3905328424e9b0c
+NO_SEAL: 01
+FAILS: 01
+
 # DIGEST: 095a8f557f75cba8e2452ddf97c053904b48827f
 KEY: 18cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e03744
 NONCE: 
diff --git a/src/crypto/cipher/test/aes_256_cbc_sha1_tls_implicit_iv_tests.txt b/src/crypto/cipher/test/aes_256_cbc_sha1_tls_implicit_iv_tests.txt
index 06ce309..582e505 100644
--- a/src/crypto/cipher/test/aes_256_cbc_sha1_tls_implicit_iv_tests.txt
+++ b/src/crypto/cipher/test/aes_256_cbc_sha1_tls_implicit_iv_tests.txt
@@ -23,7 +23,7 @@
 IN: 936a91d0b5
 AD: d2c0267218cb7090c61713
 CT: d88861dcbb181ebd603365ed
-TAG: 262b8f2f50b02faefb172ea4c7478e6f7477abf5
+TAG: 262b8f2f9292c597b813c031f09b7a7144e557dd
 NO_SEAL: 01
 FAILS: 01
 
@@ -38,6 +38,2588 @@
 NO_SEAL: 01
 FAILS: 01
 
+# Test with maximal padding.
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6edd0dfb4867802d6992ce25efd8fe0dd0cb
+NO_SEAL: 01
+
+# Test if the unpadded input is too short for a MAC, but not publicly so.
+# DIGEST: f0f82752a691ef5866413f2b2e5c1d0ebb41ccc8
+KEY: 7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f58
+NONCE: 
+IN: 
+AD: 936a91d0b5d2c0267218cb
+CT: 49947d4111e2880431519d4eec862e01643017ee6ef66b6a13061d1098bfdfec397f13b9909128ab6199382f4fff85b6c67ff7ec8914dbe3ec72ef7265a11436e0536715bc446d514a6d79e21073f3308fd350650ab11a3b31f8b9fcd97e3bb57c9652d661167571417095ef938c82d7b5ec85d99e7cd579aaac8b13fd2f3cf42a1041df75d5108f3207e481e631b43121ad62e0baa5730333a3eaf05e736f61b68a7f6989990c06a05fd1d7bf553cf057caabe1f87a55a64fccaf2b2492c03acf077b017d0c9a383d9bf9544ac508a5ea683045ab08991a702cd5149c94923d7d1b5c93ab8ec965a4ff995d
+TAG: 13c793be2c114d497df5e65ad3a77e6e5f637ec5
+NO_SEAL: 01
+FAILS: 01
+
+# Test that each byte of incorrect padding is noticed.
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2376eeb9a7e692756e4db7e851b919f73133cfe5e1460fc1a8139978d37bc825f760428eb82978ee0f8a2fe8c7a0e1484ff83eab47a04eeceadbc061281baeff699d376d35a65b51d9f08d3c89b1640e78353d2b903e520b2dfbfa6dca4e789fc3432a678d84b0ed6c4d4db42c2840526e73eedb7f37bed9321afb88fe0c80c7d9d6a612e3b1e8d197af5c067e9749f07f329a14108cc285aa2221d33fd21d0aa0a1f9d135bf65147452a65f98158f180e9247f09453bb15ddb0feabe498acfa4c98c7ce197f929456594cbd2199a268998c846921eb5c5b4b10f74558204dc7330b1d3d06a0d21fdb1e38d27
+TAG: 3f8adcac196132811986ca577503420ee3ac141a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae214f5e3f4806bc1242583ade88f5547a46f5a0c3b49a6c4259bf02de4ae4528b40459fb12e815f8d56b75f60f2ad546cec10977556db9b1ad12b0d1a2b4c93a2c3508c6e20ee20cd84943af89fe5ae6232d1e927aeae422e14382d41eaeb6edd1b44f6eabf3b4d91210b405723e6296a7cfa013574cc5ceb9f047e528b98e3d9b6fb90366a778ef69ea1ba215cd1f144a9c269663209774e74c6bd43159ff11ed53b8e20f998508a9586e11b5d0661f9f3f2349132eecc9762e1c3667b16f178701b1e9e8d0bae95fbbac4b86bf8ca93cb610e7d47cd7243921b26dd1cb42c850b0193eb4e2eb6fa4c22a41e3
+TAG: 3759d040baf047a7585c26db9c098eae69f6f424
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2a91ff92427eed66c0a5eb6b2c01ace3cd408d93e0fd7749110477c2d1221ba303d8055123c57b24f0ee0f9a68d581da88953c37fb66f7f6d6bef0482566fe0c2309e4bf1204b907d6b5492d33e762a39fc2b19400f2b5d9e02af076026adb6d76885a07dc8caedc9a59e452b30b5d8b3ad745c27cdba3564982efe738f611d55053da28772417d8fd173e3da9e87eeb2f9eb8476b77456323e2dacc2142e13f1b0c09d97c67fe1ca90178fbed6f6fdbb1c6de9dec4079594d1a2efa1d5b2cb9e76da6cb75c1acd991d94c9308f24863afbf077cfd0fb997bf20c3b9584470d9f5a7fb52e96f3ac3895887144
+TAG: 1b120a56cf834446cb531404a041abf80b088448
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae28b1064ca19a9f583ba483aea3b29aea24f45cb20128ac8d2df8b7ca7dfe13821cb8c48e22aa1d555674e3ce9958cb1b4eb1b5564bb7d468cf155c1603557cd49c27d0d280b3f118ddcc5bffb775819b9a58e13c10da0b8c41e9aaf668167afc4e0f7480c313f0a9fd79b0522e9584e6084570c84f874e4ada88f051a80301099b29ea1793f2824acfcd42da0126b489f2da94daab9f303e5891cbda6356530b870fad3ab5b4b2c5bf0278ba829516af4a86829921281d5e51a5268533933750e2ab4b4270322ea2603034b187bb5de76d5d10ed269722144f944b6a990652ac29aaf52bb66c70b8747744bb8
+TAG: c6eb53e39d97c19fe5fb6f2da1f4320c439db1ed
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2c8cdc4a9d292616e92b4f348dbc0107f46720b8c31a186736c19a9d24c5f4d756bd001b2e61519eaecc1a2840aa5029d0a8ed36e08c0bcdddae378b49d965ccec9614bb02f97aeba637ab1a1c242cea7b9dc11a8957c4d2f48c934aacbe7443e3a9906bda33a1d9b6b830b6f58f5c6b180394b34da96f7fbfb780e1b2953570cf9c41b933f7a005e596891e69b736750149e61f39c744a69cf3de10919da7b6f4e04be0f8040636720a18f56cca83752d38d4a803eb1576e64ad8578ca022153b179714c42c213b78d77783327b650138928bca8ae60bccdd3b574c9d845c51faaf9cfb6057cc5cb9800c935
+TAG: 94471cb05c53252a6a3bfbd0d36f4417a993c640
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae21e5bfe40e2e6987661962d60bab52438a003fe0128d4c9fe2d787c3dde5451217b54ead7329eb06a0b6e953df8aed54322ef3aed9a1af4d995ca710f2119ef832e97705a82101a70aae63356c117df27ddb64fcd38581ef1b19360d0e3cc7316cb7c427ed0aa7af31416e1ff78570729eeb4535301b664d51c4e958b03ab2ad27e2999d0777f231b9908ba0a659a6cea7241971c7e1a2401c4814fb6d2c639092fe87cd492e30ba4d27bd2086bd7a8514b8796c6ce214ba0723f5994551f6008e1c7853568bc424512f3bca811f979c0d8c03b8ae38321a7b4e15b43b2391fe2c9160eadfe43e12a73c4cb9b
+TAG: ce5fe34546c31b71815b59f9175d937cc3fb49a8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2fbbc80805613c1d3130394c50781c841c3895cbe90d3b1436206cd46fa61bd4065b813de24338040f836e86108d042d304809f421a1ebe1ac4d1d14530fbdad1b28eabcabcc528c68846ab80c3cc7126346c7cbfe912c91dc21f47d3bd615a93bf7a94b76c705e68a0eb1ac428f0c33913529fed50cbed95d09781ef0a74158c5750a8a37cdd81dcddd66a58548636f4be8f06403655f2426e5770cc2d47662078d9b40a248df20db4daff789eaf58200d038c36f471e6875e4ad008dbe928a034ab4452fe2ff4e08d5b1e77e02e98c6620410c323a043317df9df806d16fb15f57dbd2b4dcef7fa46e3893c
+TAG: 4c2874ad3e03802f6c523247a588ba56ead49c55
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2bac2df31ecf9c3304318bd366d09f27d363e586dbb6e229dd5978d7978927fb6d3409efcd9906e6d6ba6d1b334820ce7e108d92f14a3776ef5b5a34e951d691f8709aacee46c852ad315afa7d30536623b750f4cbd278974da67004582f48e75bc943e76a09cb6869fbcad40b7a00ccb584349c5736b2047adbcfd13e31f8313660239aca3855fa658f6731ef37384e7517f3d38f1a48b9cc6bd698a27e8c71841b35ecbc45b8852cabcae8871a949726df96c0c3d2d13080972be12581e6cdcac172c7d46050e94965e662ed2ba9836a652fdbb116e2d0fff659b33a1003ee1f6337f4e4f31d7ef14ddd5b6
+TAG: cf6f2f81317bb2f4e37252ccd7786559e614f2b2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2cfe7d97bb82dd71abb553ba81854a2d274e4c028d0415ea635350d0dcd0f1e780435bc604d3b51995e27eb4062a2cec754d75302199021283979f5acc427fe753f3638553cadd4069127b2f3ca3009d46130cd095e9366dbbe455104f606b0566bd3b9e019edaecea4953700edcd88eefb7fdaa399eb87c6233b2e909579576da612a7ba2117b4436aef66a013046c8ec674ce8d136e48e1cf358d30a595445b946658b3ba41b05c669337e5ed06b2ed799c6760d24c3c59fb29a67e04244113e4617359957b53ae6cf4ec6a7a2867d87f03497a7baa9a11a5e1e2ac926843ffef8a8b146934089ac090252b
+TAG: 7d136e2ce3f533b8b42fdb44ccff4fb0f92c92a6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae29682687730a499a61db7ce9c741cde420cb7de33ac6fc67b8221368dd6b897d622423c083e7c7f9d0d34b8b67681186a14125f4a6254ff565f4fee00b9c64d6262ac8629ad8f4c47def6dfab3bf3fb2975652043afabd50aca77a62e48bf846f873a21539f616c80ace059f7aff1cee676a923bda797c9857ad419fb328a86583a2d787b00c263ce7e0908e0d9e2d7beaef8a665d0db8fc1eff43fd2a1428769335abead876304953627e12d21b53b85e7d26a622deec5e3240431d26e67c86fd992daadfcda046d57eb22e45eb11e050d6b804fba6c9ae6d061d47ae5aa4cb6789001838f9b22169ba807ec
+TAG: d5a84c6f80ae4a4df5907960f884594e8543f7dd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2b6e682a778dbfd9e22473c054d1f68ed3405ea5b855700af6359afcb9ca837a43d476de2915b8ac46f1fcc277cfcf1a727da061075ec8ab91f632b308019cf2fecec2378e84244f94753a957fd82c7780908256d4228b1bf8cef9cadadb539b953e1bb5c38bf3d7ad376985ea97ae61e45daeba548748dd1dc9a534f694cbd5098c168527f0fc7e108cadf8646eb01bd32114f8e1d9745d2b8b8070e075e2ad9d40840c57357b3054e9f6dd11ed35c4af4acf29e27e48b9c7747fcd622bafa7a9c43cc68db0a5c10c0400f612a6d80e0afd6c3e5077f7d4693944a93e705f7122379949f53761a9d785ce11d
+TAG: da57b697de5f69f896326dc2bef69f9de997f8b6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae27fd12bb6478344295e2e0196dd3f9b879086cf10d1abcc01dd7e5566a732248cff96cbabc8742801b1ecba1835b05d75e50294dd3b188324bd6cbb6e6470f7218b04afdd16fd82fc3df0279345c6249aabe62e3c30df33f927360a03e73a730cffdcbfa3670552fc6f93183899aa8d5065ba35cc390191d949d9f0f666c4588234f98e5c5d6b66da8717f501875eaeb08d8478fe6e09bc25a50be2ff2c774897b806e5293426aa81caa3740b75845d75dbbf21fb29e820cb53b6aa314e313c49901c0e93304569a1f9e5aa65a6419f9ae465193fd38abe0ddb80e89491e071b27fce54c76455357edab72d8b
+TAG: c4fbd3e2149482e72d2ddd6994be15d6f721c4d0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae28401792e4c2cfb8e4da9edabd685d2852fbefe3bb93f4b3db81abac0e245d40504afb7a84349d8003ecb3814e51fb254cc26827559db0f10738de25f74d05589deb56e15fb04cdef397dcbc6feba871cd5d6291f8d1e51f7b997f44b782e568badca0459cdc947c68e1b062430dd9a7f15728d7183d023505623694fab003f94fb928d9bbe8054a5681d932612b6b1658ce9627ee9293e4001724f609f30c8e56ff009240c2c540ae0846975b47c7de127ed47bc9e53be7b01824f98eca2cc5f8e87f3282446d01e9cf3534dc0d7f44b69f5644dc08365f5cc80cb5c3f8c6d859ec00b5a4192e12dc1e593d1
+TAG: b7c51eee6ce39172068f86ea8d566c49086e793a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae236ffdbfc1d0bf54bb3e0d435d7b5e683f4fe2f03c754ea8c71bbca6f992f63a671d0e54ea51168faa810cc079a20b30492cf93178a053811099876249590b22a7c8b475beee956d95a63ef9f61f670f813e63315bce63a525bdc886bb6aaf782313aa5c8086f1f245edf750b52749b913ccb0951e86257df5b54ef9d259f1caac8c9225c65473211d906a6931226e4c68d794067e5f0ae3e8e1202582d45e18e51ff85fbc955507f2d238d9b7a121a468c0166cb862aece6ce84907bd49412a92abc6b8904814f15f6b353dd0c0545a14c8c7b768bdd891be676b16c9263363eb096b49c0395483f9c3c3744
+TAG: df2b42339ac151efa615be74c0ec74ae559a1772
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2834e1e14f5d7b4a7276bfb4532523af1242288e7015e3ff00e38681a37df89b470da6a3385840e9336187bc02b7b9794400f7fe6a97b3b18eeca67027dbe1c8fde3d34fa6847d6f67b8e76100b7cf7cfffaccf90e44a3bd96607f08c7a31f172b7262ed7459a15a14fc010e277b9ab2c524c169af761acd2dd0ffff4b5c0f52f71e3f6ab485f612e6f68b2f809e0dd46b620dafd51d34e198540dc35fbc83ff746c03f138478cdec00f3e824959d4840665da8b3912f047e3debeba8f4dd60564fbc9c898223d19f27330a1799de5dca2abfb8ed1e799ff5cad571ddff16b58c83dc92a84504499666a5b4f2
+TAG: 56d377bdd1262bc50ea538d295f5afd99e73cd54
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae25b782c3dead0a771825c9e3ad7cbd6f3482922b065aa32015af98a2cfc1a06419988be03b298321c571eb7d56d909abd0a4a502dc229564beabe5571824239ab29c1e5b5b93eb53527a07a33fcda134c80c6faf590b7b13ee32ff055fa1aaf4d7b9dea4961a71ef11e47f393a4f34bdf32ceda7be8e88a907f4dd0ec2a043d0bfa38e60b9afeee8d9cd7b9d52bfa5e5d5df348855da608cbe6ee13990569701d7232ec2713a6281accbe2f9ce7dc0af2493ed3398dfda1eea0b221bd1bf8bc0a77350524ec0b9e37002a6a40b04d04a4cadb1f425a145b16aa2c201115dcb8bf74d3ba19dcebe6c84fdaa415
+TAG: 6b66eb9e74936880aa9ab1bfd5363dacd4b10b56
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908bdda0ed3efade2cd8be68fa064c9d465d0be925be6f8f9193ceb80db80354448e7c0029a68bdb91a33bc862e9750bf942b4dfd3f1532773e5c754e1046f81227b91f4cf0d707ef8fbfdcbbf1024e433f8c7b3a1b93012cb4cec8ce9a2f2014d035c858e27c776388500a67ec0bc5b82707ba64525f713efa9268418f508e65a3ef15cbbb377b6519b8dda6fa3fd6ae8a69f6f5d7e772be51fa650acb1d3dd2642dbd3854b1ab6dc611a3a2ad2446bef02842b843cf6248941d619a44cc10955848ded132400eca6a5bc0db7a316345f068ea051bda750523c288ee2b1
+TAG: e75ba0f6eb95a117696e9481eed36672fdc0e0e1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908b58088a040452d08093c6ccfea1f78c98be15bbeb3114d64ced884097bf0af26ab01c622ad7e9ad0bca71f992fce5e8246f0edb546dfeb83540ff0fa84f64c96c4ff65d7b732d896f7815b712d1954549fc05ec7b3cb7dbfb592205fab2d35df981fb2353ad5dc843e9263df5b607a6f58f45b6ab91ba4ebe50ca50b636bd43cb5189ac4f1e6e840d152169b8c4e22d31f36ed392bdd4ec5ac739adb584d12a140f4035863a0beaf41682959124d6a7b29d0a0280e88bc633f0c51aa82c15407e9e2a896c090c9ba62631a377f3c7c3450cc074764fbdbc8b57109035
+TAG: d57f29c8a43584218a5a87e6af3fce2bc4137024
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908b55b7a3e62365ca8e57c4b8fe8256a214632a24ac63cb4cb6d98c7ee6eaee5768ea4f24aa460912da168c25f7be031260a86c26396b4183352964bbc2cb285cd7e39278ec3bb9ab4da8ef8aab01f147656d875c4feb4e8059740b683d8340389286b5fdcb3a584d7fa363ade2dc5da7939547ccdc4f47879f2db940503b6c9ccf7c9b83ab25c67725d0f5d39c3d9dc335737cd55f77faaab9419090f5ace169d49cc1f1898bbc41b1c0d32e48760c9b89c8d775f95421715d922a8e6a8893ba763384f99a56d67be9b18c3638bff368b3d68c3a2a45e648e61a29ef1b
+TAG: ad0905ba94202f95769c526e4fad346e88ec795d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908b41d61629348d2aa49cd8391d114ff7795d591c7ed7d9505ea5a8a7991f1f92451acdef0ec6d5dccc98b9bd6b6456aa02ae57d2cbca60d76212a01c6ff854ee527e9ee78415b0d35f711f684fa5153f3ee4cf955150e9b0ab1f4076d3cf6b82e554950df41d6f731a242ca56bfe0a9034240d59d04b1428a5a69fea811af6706f586581f7959c0c709ad2734ad06e180ab20e1a3847ce01ec57ac4cc9d4c7a75f0b949cd5dbdeb18318652accad0bd9454065ea2e8f79000f803367f13d018765de45c5846611d2cc09e674a3d0fd63c7aa416cddf8083e744927b5e2
+TAG: e7c52ad607da437185dbcfcf0f0c9ea3f3a1071f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908b544360f3ffc9df7a6599bb35b4ff64ff5f5df3b00cb6062cc19afec69f3bdb3b784d8a5ca0ab88140fdf85d7c04f2aa732a13b11de5d6465450b571508248d266bec8772fd803cdd296cc3d41ae38aeb7f99d217c22564328c3cb74a2ecae1e265007ec83cda14f9e1a4b6c826db6c912445409894539a3d7095e89f19abad7ce1905f2f596884ee3fde007387f11ddae355630659e3bb010741ce8ba46f199416c232d3424a5ad74da60ac0d68b81ffc56bc45a48ee012e521978da52babcb6ea3419588510b110671a1e27b0496f7853fc0e37034128bf8cc62d6c
+TAG: 8ccd8535bae032aace63f4b2ededdead6d8f6542
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908b162626ee434491179df0f29cf80927058ea50e413d5d8e7f757713a0cf82178cc65c73e7870052bd183cbd92b0eb2a3b339f6264e63d42f24619778c171f752529ac16066e5060e25e7002684c8334e460cd3d9d18bc7a39fe14e90c5097c0147783bab95bb467a9987bced2579a941298583bad15c523e7eb086ecbc18e16eac9c5a05905b4ba8265b6ff6208e6fde68951baef2ccf8c0ad11de70a2a7a750b8b0002f737b3fe4f3ca5cb88a8771429fc4886685c512b764310e289b511146d01bbd1ff75c2f720de4e3357b5d00a4c886613dc086c9df1badc42b4
+TAG: cd6f73b262113604c8943c2c9368829f1d85bd2a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba273b7b4ebaf6ab6b1b5c8ef7a4b7c71ad88ed90ca899d7374de22598b990d0ea6035c8984c289426b9f603239894db794647764d922d3edabff23392866c91af2c9c61314a3ee419cb403287fd7ef2d81296f518ca6b06d2474c0f52cd437bb3b151abe4f5d2027c9cc3f8b55c7177a276e0793a64f3a7f6c42a04825abf4107c576e3b08859e48d757590cec7c325f8a64844b18bd635d36ed0c5894f880ccdb32614578092fcf6e1918e139547d275596176f4b8146977ca91782dd9acd08ad3549ece5b62baba56f5c73c8624541c1e1d236ec90d76026726814
+TAG: a15ca2c337c1b0d2490c41b8b8f3f50353543d29
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908bb08b0403802799606740cf759577c15c076099dc5d5869257b6791c177d0fdfdb4be36e615b986e25fb3f45ea71c409ca8f4d2701e1fa0fb7eea2f069ff3b8ee16597cfca23fbd25c713a48c9adb5b7c72f1f3f3be636aabfac61b585e3fe5694fbbe67c0d0f545b76a347ceed7692016519dc9df0b372bce3718af300b66eac760dbb8779228126d51286a04e5c50346715a0248a1425630b7e6f860412460f5b641a9012ce763c20c238eb4827e01d9c24f82be3e4ff6f9bd1b04d5d629f0d727ef1146c9d154e91e237e702b9de05b51dfb010c4a9eafa0b453ee
+TAG: 280d6e9e3d11102a6aed51fbffa7e5bfd2c6de90
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908b3fb17c538f0b1939f372a8f068a36d6934193e0232eb7ba4539e7920577805c074456d2bc9433f5a03a0b8dfddbe74db0112f775e5f0a8f0c432fa43d4e75632c1d1f043364aba6766d4b1c282f8bc1e6d50bceb9837b016274d0a9d8b44e7417d431224f0e889e752cb8cfd4a37ca25a02e177d1eb28132e83de078f825d702c0b599cee8360a77b1de37fc2355fc7ef7d4488f257b5121b3d2edc5343223efafdf8d2f674a7959744f6ea8fa15697e18a1d3964c8a72001302a05d0467fa3c18e260730866abd69262d5ff174bafee8e9ba258939273ac37c09f50
+TAG: 61bbb1730ceadc81d6feb4cff405b773d08f0475
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908b4ca1455044996445827ee2cd283d5d914f44cab359a7724f5359649e1664b294b749be48994a5daafe7cfc5d447232b3f9925d78929347bb845bb44dcf08e2d770fa88583a4447d26efb0755e5c0e89e2d09f3ecf915ad67f824cd3404eccf7e524136e39d6ff926c6d8f92ec417eb6b47acafb6c82289bd799fcec80260e4d83588cf7cd60431543993e28c61cd737f8c6326fabf88afaa68cb5d1f8ae5195b3134685f14603945ad44d5b66f5ed8355b769f136f246430cf66b99998771c0784549204ef64880c1a5108a06e7064b9b0183c8475f3ed6e93f841f2
+TAG: 0eb3c29c503c5c4363d5196b1ac88d3f35bb66c7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908b652e6ebf3b4068d2db241a11d81b6f8a91112cdcb2a203aba9f10f0b672c2797bb6a9dcdea19108ee48dcdb16222a95e728f62c7305344b7b56ec4c3f5645c63f30147ea591585958aeefcd9380a15f0738b89fd8715965cd1918d92f7c63e5425755e65c612ea1c7cf3a8dde7e80f4de506a85f3977e51a3bcbd42c97888604bd6d9b06e3e811c0b2d41ff1a8e7668630501a8e4991967ca84df2bc2adf3ce4f4288f0dfb04af64d9c2f6b8ceabdc5bf63d830e1200a673dcd0df8f42280e474e2c3b0cd51403adfa933d3b82de069ca137738072698fd33b07f370
+TAG: 9cd376a19156d9327bf32b8fd33adfeb314a067d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908b8fe0a91616969bda3ff244ae2c65236e812a1975188045b38a773cbc7a97f9b325925b58035630aa27995c01035fb6cdb58c195b215c03e84565825addcd3d2088005414c8ed8976f098e93bc38f77f99700adc078e766e45917320dcc80e07e8f9ebe995eb050bf534931ef890ae267987a7b4e98189fd9dfbb930a10d68725b434b1dadf11ae1d63028030d959685ff3b7ba626ee5a777de512a52f5c27d088decdd0c59126b7d27cf8de027e55be09341d1e4f1d61bd70c002fbee263c15cdf474bad7e895579c1cebd390bed6503d255db319ee8fedbe91c68bf
+TAG: eab5048ee71e29b6e241cab09dec2e4d1dbd5b53
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908b40213907c9509101861f7104d05db96685b0294894bf5f790365ac0e8b9615473707fe8cd650c41e9fe65e699fcc339a34bc80e929049c7bda2f2c807fd009f77ce52091249b5f56021a6252e280616b17785134d5b9e33e5b87055053fb7c8f78af6da9525d70f6fa9a9109dd70672e93d936d704121b000d515b86086d6bdc91968c7bf1127c6246d6dc1c5f04fa54f25592ae2a85cd127161ce9ca8280a20dbc3bc663a7175260a5dbbb8abb1e0dd364fed9908d9814ac873bf31ccd2df07f0617960726e4d6b03038949f884033ecee0eeec45576810c898c00e
+TAG: 1298872d988f88b60b0ac57920ead5bafc6a18b1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908bddee9d55387a8ec31a62a5570d7f63c779a231c95c41ff83ac20f42b8849c213aa3842b4268d5854e0c67385f2f8b1a71852f2959e13447bbea6959ae4c3a79d444deaa49907f2471859ceff27c9dcad67bd8ac592daf0f1208105fff320a3f2f8fcedadb98be384abc511f863950a50df5aa21728a461f940ae1b56a04ec54c2923cd99b122893d990f6257c239ccf5306c3bae1dfe79b0363cd90325ba61f981b13b391a44e61c7433db7b213863abdefdf394e0cfe46adcce53778608ad5387e0cd0f160dd5f9dcaff76ebf7d09f5945fa7e0bb9f1138d372c4dd
+TAG: d855a1877167dfccd47c86f05a4299b1c456ebb0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908b601548db018b39932fe0c5542c0c7901e1e6488bb626733ca99977ae7065f8aa77d90f337c795b591379b6ba9f3fbd4445c61c618a4c57e882275a53c0d2c718990a274436030fc592abd371de87e3a874490278e342f7e0d8e4f06d972908e791fa5da721b7a333da9a8753322a2f3e8791da5df179b6f351d2c7838921dd99f4863e9cfd29ad34286585a5c6690dff9b5120f787e331c673ba5e1806efe7105ec0ee8548d174d44b887e6cf55cfee47430c7df5e826848f6d7a6d97be14f85f3a1a9b55343c67f1eb729a3c6a2aededdc8561910435a70aba319b4
+TAG: 448d8be45378a56fecebab94422a9ff93bfe7995
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908bc1dd9236ca2124a932de57e29127af97451acec6169ed25d9cb9830dae9e87c24c8d8dc0c50c9bb9f1a4befccbe749710c2fbe6126fb882277fbf455d3d0f8c21288381a4ad987fcf2b32af8f10d561a17e9b0279497b86c65f8ba87a04b8392b7e724dd5e564b34356718fe2c23b997025010446fc57837257e47e71f5f8017c87a22381044574049fc6954c26761fcbf6c9acece47d067bd2d9101731b74c14c98fb249932ba2e53a969a29e13ecc734b62d84fe438eaf7c6bf3ffbc20f75784cc28b5289a5c5c958ae3e88cb12d9fbbe1bf29e9aadac29b76c0f9
+TAG: 7278488866a225aaa5243b543d43ad711f99b245
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fd406040842d68fc0c495ab7dfb5fdd23af72b7282a0edf30eb910bf8faf39f4968c17b0bc9d31d5d42a7f990a1dba17bc7231c8c46ad69290ff89e33de136164c7003e7dd70d830a9bf02387e1aaef4a5462e7441f7a61e487dc249db320282266bd2ed016b478908852e99c9118446d7eb7f1172ec6c17ca9021959eb6c1fde96d4830dcac2c9c49a671af161ad08dd674d8e02ee700b95d0164180705231dad2de7661dde9e18019e6672e73f173eedd460b9d1713f2c510b8134147d78b7786ceb36930a22d693001542f
+TAG: 093bfc686715eca8102e719dc1691e0371625d4f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85f75ca0a51fddcd731d9163a3a981dfce2f6fda727b63346d2b30827cb1e229e8a6f9fe245440bf5780cdcfc2372835cefd6cbc5e27e1deb63ddd0915d391596deb420a1c9239cf9bd3a31c3b0c1551c0ba6de530a6cdd1fd46f52a4ac19a334dded1066effd8cac3f53a872b9683b0d969f4b7983a68a88afec553a9e519ebd9b9d5f8969c671b8b2ebc0f1460a872b79ce03aaa6bf7d0a99f6ea178a9c0b6886c40d11abf099c2a2a6ddce061056cd30f79a21ec33620b9b2aa0eb040470340334b9e051c244254ba2e7f8dc
+TAG: ab31cc400eff38fcce5bafd0092a0a7b32f2e392
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85f8544b66c7878756661d9b6381f96082c976c672e765d6157300c0fd8d357ee148fdfafe00e6bd036e2f756dcea25d2e7030d060ed3b7b224e2df185870368fcce9c9604f0096c5b66176bca49772b514f4132d9c49c96365e71879ab8ed9e9ce74d4a7d1dd49c5f6f17fe41f9071c9dd34a33a03b481065ec2077e09037260f6f33772813b58589e9ad43c4679eb3d8ad918b9c5fd50b6d05bde13c33b966a8f92cc36944964abe10c0b35944087241963ffa8ea43aafb6135adf2168eefc021493e0fcbb8f7e8d5ccb7162b
+TAG: f227d302d2b2b47c12c62fbcf555d3d60760081f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85f116407cbc9c597e1dc4644d7e099b048867a86ac620138b820067a47c7161d284ea6b615631bfa7879abe80fa563b7b94c9c72ed33526ff5f1176c96bf4c5b069504bd7fda0e69c82fbecd06ef72e2a1ea3cba93adc740b60e1924b5311d6435a85f5c586f6bc8fedd95b666375726826e23813db09a54f85520d5cefaa2885500fd240ac2fda13bb18dd83474da6eb30ca2623295af2cd25e4e9dbe8ff10dd3a075d1888721dfa63f954812657933e8a4756e4ff629e90b176393c8c9a21acd36da6649b585a2fc44394190
+TAG: 8056b2c744efb988570794759852408e4b60a331
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fe7546a47f7b9a2c460844876d9101491eeaf523c0191ed24625d01306473e42a16be35cebe7411c1e52e60ea60a87d446f5f82acdca796f3ebc875296ed1a8420af54ec2e71e3fbed445bd123b514627a9bd02681f7f44bfb94ab158e8771ae658065e68249ac25b42de7604c28300653e44f04739f5254939c63075da1fb5438cd661a4bdd4817b52f7e8abcbf7082286aafc1c25581d234aa86544c4142e6a6fcf1abc008aacd6dfb4827f546443341531fd77e5a8afb0436bb9bdada92c649828e338c190b78cf58542f5
+TAG: 5b0b473f1d535c31951da991fa1527f3bc4f4233
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85f3017672a38adf2c9e1de0b79bbc52cda1574c975e553051622c6fb55fd5fd1971a0f5692e84f51ba6c4620363a6e2b16f89fa19226f92577971e362a6e9f1bafdcb99d312ce1dbde9b0420f088cbed70dd789604a47eee083b2759e59f71b75afb77830f216cb9c980a914fbec3194c4dfe9dc70d8c5983f0162048a3a041633887abe5a3558b1dd839be71c601c1cef0e71fe56ca6dc7ea21c915251bf8a98ed334c2402c27c9aabe433f3371d734d4356349ca04fb293a42d0856027fe76c14919705380f9c46084bd121a
+TAG: d40060475e0f1a942d3cafaa75b6f17972207e7a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85f203f006169bd572630d73d77afee66a41bec9aae220bd441fc0aab435616039b97ad7dd260e4e3007e4e51389e2bda48d77d208e6b4c072c3199219ce602199033ca1582c1060a98298371e33165b37d592a2490d1aa242dc1e4dc057ee6932f5d300150a4b8540430fd3ebe577cfce8674348b0377d09f520d0a89ff35b545c2bf0e76a2921ad6432e54e9be82e827dd44616f6f4c7e80b0292bba609e671f6af5fe4db2d7894a6bfdbdda82daa2f3b0323a8acba96e5b1834e9559b54f0d45274e66aba21653f0ffddf80c
+TAG: 620b4f2c95c4f070605ca26a22311a9eb6b62956
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85f724f6ec7aaddafddd79c161e4d629ce49394ae9e2d01fb24ee9f458cc2b9c0824a516569db3c70f6873a5c486458fa5d86698d0746d353231a22584aac9e17068b9b80fa32d969d2942ec5bf4a0749c04a3cc3083bc456ed47a2781a014c66a0596be7674b47ceaee0a97cd11be6a413be6b2f3e349d374e4808f0d3f8247701973b5628132fa90e95ddda56348cf2e68ce078916b0d0708ceb835bd31854fe78059267967f7e92df97c911130bad47e6f9f5f49356e45f1970a0ad30d4d88bfffb3ef4910401d01815db691
+TAG: c23f62f868456d84b50a840e802317f33f59b7e4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85f51c12f0372491840f524b5a4af58972ea93e5c97abc6eeeee22cce1ac67f6ca4e876866484b433d9db77180e95d4e4ce6c32081608b779447afe52f9714a84bab2fda45191997853aaae722a5b9f9a46ba8459592eba8edaba37a802b6f4e6d66b09d17126b5dede846cf663951a1bc6d1d5aeec1f7c23a8527930f9766b370b48ea6159ccc540befdf070ace70381893727c24dce2986e65b80a8c0901350cd0c14676ccd7115e294845746c47cef8c11ee4a97cb3db70d2a9a3c29d88557036c5426f5696cbf15ba74ac11
+TAG: 0a8dece576a251b67a1beb2136dedf7028755403
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85f8c85da9521ad538af1e2483f9c8e45af8b157aef7e8b76e5e30c8fb4025cbc40491e08ecfb6196fcb87d16cf01e14fa70df521cb7e779e0cae005d3540d5204b75de499b2f925d572bbbcc79b46610692b321d539982c780994ce6f7ba3f618c0b2d7b47122c7e3c1d07312c56a82a99f5c9007d0766f2dd74154cecc9a63574df29fa718bf5c9168a012c5b31a314419b7770adb8b6bd33bfcb78b7500628f2d506dd0cf2425fe86328d7ff1cf8c8dbb17c367db726c69efe281fccf0f643e0bc29a1982ba224ac6fd27e7a
+TAG: 7e5051402436db0cfaeba334ee529d9aad818f1d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fa3ccb2cfe61b3de2dd99a3e74149b4b32352032311e545054a9a135c21fdf40cd4c5fff57769c729e3fe303300e5869e3a892ef7e90d5d876e6b7d7d1a92dbbb12fd33948d9ecf0aa3ef02fa2070661a8bb47da737650c3a98ce5867f3c29dc27ec944fe096dafc4a266dfc4f3749b82e1288aa283334608e7627cd57a2285f01311d3764012fe99da0a80984be868635c82267fd510006da0409727ebf272a552b5e33aeb1c005ed449dd30367c71e7b614ad25f7fd877c0ed8b4b53a1c1d7c2851ec1deca6a8d62c4513f0
+TAG: 631d1837132ade9212c483f33a25a1f7190f03ee
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85f710dbd6f2d2ae828a92ac5b1ecd6649fc8977b0b30c1c725831b32531c15ea3f46f3bd291ba5d4315c6fd7ca11ca7b1b865cced2c3026f2920f381c1da540beb35332286f1bc359b2145e7c53dcb8fa979ed74caf11dc59a5b5de8b00774aa722dc9e3d234a403972b165059df3a5953566738428ecfead7e0b2afba09bc00588cffcd5cfed0be2fec5c93900ab0902d787dd9e7d9e67ff9612404ae1250ea61c0951a97ce1b2fce95e350b8f6c82039abe15027bc1344c5cee5b1ecf22505fb99df4ba57606232034fbcae1
+TAG: b0865dbad1ffb0a378801d3970bac3031ebc881e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fdcdd8c9f331b19a3df732f39bf74ae5fd1f434bed853337036f34b8fbad3787ee1c02343a969a920924ba4cb67117ab2256eac17f521a9beb4fe9f69a25cc7f56723ed8dc30e702f2077a4a0c9e5f90d39956e26c2934d9e37d534dffb8823c23504a2f1197ae4f8466d910c775f1217288393e6754e2f46c7297b88ccdcd81b2e46b57960a3eec609b5fd9afac6e1aafa03dcd114130370c5848b1959a89d01280a275125c7d3344138f40f9c5b1870075785384ebec91a87191661d17fe0fe4e6cdf400d7386c1e8aa07e8
+TAG: 54fdf1d044f6870ba117e105dab1fc878865495c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85f6625e266b0d7f045eebecf9e5154388c2850f3dd0db95acb2f16b6c6e65dec0072adb93c01d77840e7d58abec92311cba811192cb2a8f11fefa48a07cd730a7a278d55b644257602d7ee84dafaf49b12232044d3e91f1cfc8125f845b2095076e7d8b6741904063fb88bab84a25f0a854815b8539d25a14a792cfe09e55045dbf572dc9d990af1b7bc2a2cab30a11e5dc97a270139f32db2a27299a09c80ce136684e679b7f005dea699045fe61ef4bec4b3d71e84c3e5924c2da66dda7a2bffe76f74651cc01b296993b4a8
+TAG: 169188a9cd427268da37e56c7b844a8d961705bf
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85f3f94cee2b11cde2c49d4e554ac8d2c4293b4436e94dd1a6cc0363a9c832f4b9c2784da178175e128ea55b4033cc5e15205c24d8a9b05bd83e57a7e7ba9b74ada52af368f3b7d13c5c804a16c542cde185057d76ef27e6c850babd0fad1f68df6c05f77da9c4da9f16def806162d3fecd5f45ff66bb291b3e58dc2b85622ecdb378ef8ad68263afae88b8ef45444e7a1ad429c1a89e0e8d9b9844d5a31951adb61bdb595006c145cf6e9d4bb64a34f24c6af700a3a897171ac18dbd64aebbf8a1262ceaeccde34b6b1415e000
+TAG: f9845e29aa89aca30bf231c903167e10d85b8fc1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85f2444b7675d8cb6ed146f384341bcee305a4d92b855480709898515eda0af419aa54dd5d3ca4293fac1c015a0e2f5ded35ca480ed1c4a8af925338c96fb8706f0a3162a032113279535e9f984630ece548ea11f0dc0dad95c74ef32ce613992658c432defb1c78b8ad1aa053f54fba1c1ca502b89a0ed8a918b2515895d4730279fa2b3a95be914bc69ea1bff3362d9260d097d5108bcd96d5908369c7ebfa35a70e9e089d1438079987917e6fa7861a85fae218576ba9ea394a7690d8767d449fa231372b24d3f1f8d79eaab
+TAG: 0cd06df42d74bc7da43c378b3fc30a1b8c833f8a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff43f78ad9cb9a3fdaed607dba0542030ef4a8cb83d1ea7c5b07639079b490f85c50ca395d55158ac14caf544fe491d54346b2d2aa3b0e91eafe6daaeb394d83083d9c105b90382845103d5200f3447eefa8e1857f6ca0dc7c094b88da8a81166dd56450629efefc1ae6677641a89a4a61b3682937f2f687588912f63171df37806d71b809ac6eafd3ab5eaf2e1690a34ac4fde84326609372ff76a27522f29c3f276943caec9fc01585cad558d17ab308fad9af077d217e3fd2e7223e08
+TAG: 0e499d45ed18c37891cf1e224870e435f4b9e559
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435e6769d97112e7dcbc4eb09aea12c5e4366ec60d6d146576a57da315893104f9bcbf10a7c956742deb3f8fceb678af9378fabce72c7b492cf208e9b0afc2128c268db04e96873825a388058fef0ba0facf5303e378ae604d621d85b84e5e3b97696b7b741a6ea8d1a17421f7f6f78be34f6afb50999324dec8f2dbd4690ce871b81b7a49ca3080f6ec51817510c7c99a7071b612cc35d8edf4304ac9304fc5e18e39e9c92989b38f0f4b00236b6ff89e588d304f8afa0eb4070e710f
+TAG: e510c3531de778ff276a58fc900c1c1672859b28
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff437bc218f396ad080a4b28cb9f02c743bdcf57444aedaedd4f69bc3fed4dd20990aafa708b11a0a5169fffb93adb4a516298b7a436e6954270cd4e6ca9ef518b9852c059a6967d0314c65f6ab239439a56798066a2d1bd7880fb21421d60feaaade2828ec5779aee80eb4abc169f1c57b1f0276d7779dcfdad88b3fa3b675353abc956e9798a8e885ad54eeb8aca7f40b9e04d02d1b92f9597b36e1ec820387708720bf6e212754cf78cd305e59c2696c740013ba1d4812751b7e0d07c
+TAG: 4f7322916882854655a4965db445e8bc3c6c81f8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435c0d68b917cd27d076b2cc44d4af7f135a88735cb78e1543c0ddbd0741b8600ed477c579c7de2d7af859c587b4107bf25beaaec4ebaa4c05c97650e7570b12917ab8139c09bf200c58bf46a72f93e1375758700eddf89672f14c1cc8eff719d2df56bca1fa9ea9ad4b0e37769f82b52afd690654a29df1bc7b0b9d7ac69b4e4ac970077d655311cd9f609fd9cc67c6834fda790a6bc6085eb076405c1cc49bdf2bcaf86b99dff245a310de597b4c88368b39b0d26794465675556d93
+TAG: f21c5cf657e5526e00dadae857e10455631ce154
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff43f2a6fba1bc471ea11fd2664a66859e41e7f343e1e8ff3a1ab889f5acf4e4b65a7b5ac645209303d0066c9542192cdbf016dc51501d2d761566d5b13e3f20a562f98e73c3551eb5272c5af8332400256dde72a007f419b60d7692f0f1ce6a57db5fbcf68901330ef45cd1d6593b2e79fba7cf18a194e721683e21bc2134b8710a6db943a3bd15deff2e6186f179b4ba384c11ed2e31573e9aa79e5887f4e7310f51e8ff564e23bb71b41d4fa52b0ddb6b64e298de24a71b30ea1004f2
+TAG: 8961fd22f9cfba057c3459b0d5f97050b99e400f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff437fc0a30dd7e2e7d9804895c74f6926c23dd4bae48f041d972b2bc3f14a0a48d01c498a7269b3fe3057b69f87d0bcee89f6be7a9aacbda6f5b719d577daf8bc85a6f1ecd869970ddb003cdf2ca456b1c8e18ef57ca01afc6c7fbc467971802f9deaf5bd2bd0d39c481f3f0bfec372a5bf21c46b0f617ad5f8f3ca6c9cf3a422b7c2c999438d81e125d2ef3d3be24df1ebd372a96ed8eb7cb08466f9085b8f375c5e6273e7133e395ba4da85f3087da399e6fa413d1d584792978b895c
+TAG: d1955ceb748b559a4d527bd1d22e5927564c4bd4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff431dff06e5e5b6e0ef865a57ea620a068dca14479629b38aa9fc5b7d66da01aac3f240f3bac99c4742ca4b0dadb2cf77cc98a40311f1f23acf965865d902b306793f2b9989737bee3e77b181a999d7124d9dc3ff9286e9729f57f1d4b47b246044b971c905a840c9388ec51b14c954be9643d9cc1e9f96916c0af2c7cdad9d4489c32732ee2ccd2c32d8141398839f98f12e6b01e942e820c5900984a751d2bf5109a3893fae9eb047bd05ad6afa73aeb29eb3e3aa658cf9d2c917b5c1
+TAG: 8a6453ba37252f16cf3cfccee633c19396c3b8c2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435bc5cde48f127a596a81c953d7bc75bda6163b223228e6779b6228a55094d530d509750cfa41c0d1e78e74ffccd20e0c6486714e1d22eccd9adf44e47afa509302a58d29710e579515234ed665804fa44cf43db6612af9f096889ffff009e6baf8176edacf343a405cfd19990511f2433a579185c8facdbaf8e137c84fb2b06d4352ee495945e464154419f819c22abfe5b75107b3701f0fb44a1df3007916101409e069cc276d4dbc5ebae0bd889e939057ed6e0bfb3942e5b70efc
+TAG: 83cf1619fa8a0041feb62f128198cc595280b84c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff438430df5627641646184dfad041c1647edcfd1bfcf7b253f19fbfdf4fa74fb1d038a111e985bdb9fa615e3a8e3fe0f70579c657961d9699265c27022c96870886e229ec0909befe895890b215ca1e03aa677ad04811667b037eafbe3bf04e4a106463a512a9759f73184550ca1bde7903d21cb7078828fddf2b0a17a4c7cc90f211c0a969fd3f22890faa3a7d6e36d80fcb96030fadd8f498c93c6cf9bdb861bf450fdc6c56bb1d874d4200900308a32c49ea9227e0427e17ae29d026
+TAG: 6b185d1caffb103e004219df3e98e60a1ade61b7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff4377bd2cbd08c16ff0dc7d92e3fd5bb870ffe7ad217644860035b42df8fa7befe2a166fd0ddb0894664777333ea03fceae19ec5b4a441a6b310401625175ffc5bddf7bf33dc8594ca657a140099e4ea80af61e13f0029590098043e47268d7fbe2b813630ce25c6736df32739679c7a09063e09cf3a94cf0112e8fbd74b707d557a6ac66a742ecbc647fadb4386ef23bb451603eb0bce09af2ce72e4e56e344fdd0660b977e00b054762922f8d7f0bdc18b126fbc4f7b8d6b24016d753
+TAG: 40afb5a1e66617b2d1fcd69bee17d176b7d45dd7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff43a6f9ab9bbcdfd379d1c8ca0bf95d522f6540abc98bde29944bf5f1857e3a8bb8ed03fd41ee933046ef4fbbfba539cc04a047ae5ef5aeace96b278f27cc8d4de117ea5313f3b20808d450623494d43566bfc684511f14a6b894e62baf8a12bfb2386bb0620774936de6e8171d3dfa3e4091dd106539f6b8194d60137d6c487f1e73f5a536b27a7057a482471758e7b76a69657a73b5e9a8814205f08aebcd9aedf49ad44996f9c9eb77b7906c7bd229dffcc5187253bf133898ebeecc
+TAG: bc4437b88e0426e85e16e1b16b813295974bdd05
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff4330cbf44d387685aeeef62292512befcfe3e7f863eca7598268e7f1f286949c9c8cdc62854874b65c22d1547e63ddbbe3b933c36cb4ca7547fe3a7c094e3dd9b38bd9ea26c195442327995485cbfcfdc3550d1e564452463de6d052f2e065366ef6f9f9a6ea9785467e57894eead8e4b1532a9aa2f93ebac75696892915e4242521a6b9af67effcdc2f63d9aa65daafed44dd7602dc0d2300c9f72df06ab8e4619fdcc601a0524e738bdc5d2e7498cfaa91accb713d900f99522d8af8
+TAG: 0b2c67f90d73b2ae2e69525018dd4aa6e081361c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff436ee6907726df23be8b7f54eceb08427491f40e3172f4b497179952f8cb7f6faf7a6fc0929dd0c490fa1efc550462eb32c518c5d772376e06281a38ca1d6981c250697397a85529c11ca443deda01a710d6b7da0599fbddc4ad6ab072bb416ed4bfc40a13ce320b1a9590712194bbe8860bd6a60cb02bde8f20495956e247dcde8005de28baddebb310df08a857328cc1899c31ff89585afe40e68d37f81a85d9637d07426b044ae2dd84dac88284deaeb85e2bc6792367287c76016d
+TAG: 4d48006c8d4f81497bb89a39f6215b7e5cef839d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff4398fde8fa65dde0608cb273fc848f7367b1923aead0d0b6a0b83589a704461d0cd5872581ed0226b3e568f49e874101b8fa202175e90419da8781cbb34d2a1a6106e5a99eb6458a5a00d03c0092ed1a7694780f5580f1d332dc0959e537f6fb1ad7c732c53715deb0a96969cb7ab167a81eeb08e44af8d1e6c215689e8c762743ec643f5684943d70050b56cd3cfdf05af9c3930e7ccf8bc981b11449f85fccb4c2747165cacc937a184e83911809563195c38e72752fd167459d801a
+TAG: 57b4c25de97942256a8fc22fac5a56e49fa4c088
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff43fa161b93f05a00120c5c530d5fa4f57e25027a5b1a28ff60ae7c36be8e0c6c7e8c7f1482ad1cf60d616106f2769c8e70957d42156866e941065d856820e0a49c5c700d33866f98e7847116609d4919f95ee9c0a437a182e1f998ef1ac8ba372eaebd90f98c061d51f664d0ddc0189af963f5c8662382a245e76d4120a214615c33472f71b797b4890784d02763e33cab7467b383e866fc840483a0da8f395bbaa8de5e6a19a18360e556501be8bf385c959b7f774a39f45cb97de6ba
+TAG: a8f983eef4c6a0c104f39448a84a0b0d6d4b046e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff43b3fa4ff10208d33a48b77ab95757d5a1d6c5c7a29a39b18d68ef0ff2f7fce32ce34b60ac28a34401b97370676e2a0a0b9953fe3e1fe305d6c457aee6e45c5bf631ec414c1c898bebc975190cec9dfa28adfcf8222b871dbd7217880e5cc0374941926a637c7c998543fa46d151e45bc8abcda82dc35116fbac166e6744529759fcb1d60668a5b17604d69a20c04c1a4da93ac378111121edd72f070ffad040ed2e49d9bd8bd3b5b46f3e39055e652b63e9fddc2e05ae5e3179ef4b00
+TAG: 18974e55d696edc6c60a3e276a35bf261f8ae5ba
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bb2f85bdde6f6c7018f78af42970cc3173095179a4c4c23c103ca96a304efa3ccc8a7b845e5c50afbc066493fd25e941571ebb428e90ac8afc56eb28208da2d79aa49ef30f8f45cf5872f82d5a37bdbee3a2dafdabaa2bb914351e15dbabb6cf611e3efadfd5eb9100890948656b1905e23524564a8619820e647a323d2e89666d70626d3edbbf9b9bec22368523c2af6e52048b1ee1ffafc69a76ba036fe84c16f20db6b541efb31d2c8a28ac
+TAG: 99567073ad9d8f802783b1051e8e57dabfc929b0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbb3a0c81a9a9925e51ab832e0e0b0de15c0014c3dfb822161f90d1b4e07cb0bdba0cd8f468a4d35630700350c29e8ad563fd58a53d6e8606e25cb656a5d5364c5cc0a664d35df46302f086d7f556a5a2f3f3a1bde0aa0d1ae1f0e9969dc3a30c2bf63917c5be9c4a99c87d50ec623d4c071ed28120cbb0909a10268536fb4407c9303fd441a9f160e537adbb6cf7b3ee83939080f40951ed99597e1e4c5a7e7be3e2df8d120d916246104aa22
+TAG: b8a0ba59810630c98445c8b564a874f97f5d05c7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbaf67984daeb4685a80ec20cc2a65e3a09121793c1948e87abc19983eb3a6bc2164951282d18c36a91fe94c621e939570b56f746936000b06dc7e0a2baefe681a783ebc2306078133e45ba3eeef4b46c5996c91c4a3cd2cc899ba6e2e4a26fa71f7d28deaac45872c10afe9b08e1f07af54020917e9cca003de6574ec3cd28263742474909ef76a920c98b9e7155e7d4beba3fd4d67b174c169af45364e77978cdedf3ad7eb7a45d33d5baad4
+TAG: 7be9ec37503c4a3eebb529072ae32f80508e34ef
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bb6708d3b84b8a164d49a50edda91d0f14fb5dc35f4c2bcde43b3f5998ae18874d9e3be39021bf8aa9e585a6d39241ae1e9cc6b155907b9db864510b1dcf54e20644245571cfe9942892406b5d561f83113f460fe0f5b3e9588b8d8180ab06f1526b647c4834e7d3e3e77f1b70f0f1b37ce2c0754d45a55e016ddcdc57aa46965f456879f33e87c40da41dca80402b854d5f7503e65ca7b0026d7d4a961d978336bb568facd5f9c0f4c44f0a3f
+TAG: daa9d94366fefdaff7a1317bb307bbc2330aae5a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bb07fe4cc26399f338d3fc71c39ca9a604b8169467742b8dcb15678823895912d9a8dd3bae22c05e25b89c2ac5829dda15c3d2eae46ec731d008300f53056c0945d9f617daee87a316f415d554c6457493957765a6781f9448a6b39612da9ae31ede6edea154eac609eba05b0c722ed97f51000d7c8a2bdac57e56c29cf23cf4a6d0f70c74f57b89baf22dff87024cf9ad24f36a44125efc879ea53113dca6642f1f8189865c45486c806229c9
+TAG: 23393049acffcf8b494d5addac22299abb0ccee1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbefe7049db190c4f2412cec4d062aa5f462a688d490d8c0bffe69a6d42b78a3dc61983e0a9f6515207698fe0b0574722acaf3584ee3839f5760462584e06232694f5f0f8ffef56852de0c3bcc0d00f7af617e4b8328cdf52d8d4d18433ada519abb19b21b9ff30400f94715f9722d503863cdf5722a858358f602d6f2dffa7a56e5b9f2d0fb390bf8463a0a88cdd312883633945b3abf69e515da305722aece5816c8662696425d14b1f49b06
+TAG: 0dc95daf80c1aa4518f089b4ba8797ddb18f7c8d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bb0cc2a4ad50f08d29dfc6d456903d47a0bbe1c5eb2ee236648916f2823136ebd8adffbd25a42ace379f5479c9a4933802d7d4e5a037ed1451b2da581872d9d7d9e7247c8dc07545b62e0a21e50a4f776cfd3bf40038516e0cb40bd1ff8a6e8d86875de14306cd39ddf70ff1d360c8dfff8ffbfebfdf1a8a6d0dfb6d155594e70e44bf02f7b4788add0582a736eb600a998885f382fd79b563ee3f0885a93665ba18fe866a119a84cfbb206b15
+TAG: ff821d268e6a779e8644b64250d53dea8c765ede
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bb635064840cc6fa8cd38353a33295ead5e88e832eb3a9ba3f0cdb8f1226d27652ac9e20d6e87418191fdeb30ba89f09a0c70ac32bf0764e0efaa23165b119fa8eec65c17ca229ac6e8eeecffb07f9ae16b05a46c209404cd8439514bd7124d3311930f5a93e7de8d9b5b6e7cf9543ce483f6e56acf669d9652f5868c63244fa5d10d45e5aafdfdf3ea0eb1f7e75ae1466c5fe8280d01036ab9fffda0934d2b7bbe37b198fa6a498df70863eee
+TAG: 6c7381268853f4220fd5c17c793c77cb7ad83fd4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bb5be7e7e9051bd40b6a39c100e46c1be96031bb8c46680cf3814af9bfc9d90c0750652a32ace567fbf76181353e05be45f21e37b48c02df852ba8fe567a762503762075342e7d1155fb7b6c147e00b5e428f28f9857f938c48d0ca0984508681d34a78efa67939bf400c9aa18c75c2981f789e5088160c5fa96ba13d469bb22281aeb24320dda6e5c3825bf002313ddce455f60ab93f0a7d345e428ddc5a68a676a206d93554c71f6d1414b08
+TAG: 461e4b638bfb4f50bc83a500ef04f5639f7ef783
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbb2a9187895d863fe2dc2cad0be64315c6a87959b1a8bc0d9a9cc8d6905ba4679c6412018dbf200f1b8d6c6a47742575115b52f91e66e7e4ba15b8b2db5b5c02694ce9653082362ef1c7a88c737169a53e7d414342a6dc7c83d38ba8610419678fad8e8adc90c8b34381bf13084cabb892171dde674625192d5a95ec25b40a0eb1b5a14e411c9b96282fdb864e677ebf0b8ab5eae17e834c0eb44fe10ad7f9a7258bc5f7fa9801299be2ea715
+TAG: ea944eeefe00cd70b6c306e0cd5a770951cf1f50
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bba5547a86ca47bf031a766795ed101e6c20961047102a148cf12c5b80e9901f11a4d6532f258f1db8b2b5b1d28bbdf77e55ca074a978f46492160db8ec1858ab98fc46ff72f6bad75d80995e60dfcc491e0f854733d2f646b2fce9ee9717fa637d8bfe5f2ce48390daf7f6d3c7bd9d6af9d39ddbd581a4a92695b4aa1796ef05d828b69a099808b7f8f252172618f2e9f9d5f29eef6e0fdc03015cdd5248a89c256f44290a103027f1bcbc571
+TAG: 930213701b438cbe3db1ec1f2e4f3960b39eab69
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bb876ea734db86daade668a201ca933d9983737e66c411d233bc72be47aea608ccc47810e182d0ec5344bb562bd82d71b9c7e8548be3a1ea9e788b1b33d6584527d63955c9aee94a5bc99f705d32b634cb541f48e4744200fcc012cc1ae8a4ea17b3ebbb0a72f618545fcf724206f0ab6889041b0c58e753ca1fee7462a251017097327de03932306a7bcb17682328484777a455977b7b6246fd7a7ccfb8168e97e80c2e43540c1fe5f8918455
+TAG: 1c5ef1d5e8be01f85616e926561e79bf7a5c5123
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd4decb069712aa625ea3822291f52d80baae631d18a035bb2fc9cce34f8ab963794d358fd97a1887ec0c86521e3b083286fd2dc391a2164cc39cee99070dfbf74c663a9b13eebeb8a3081c989410c0f64837e633002b0a8da7ba990855fdbe5051d594c926df44a3d03bd78297742a6f66a47d21b82968a48a193f7b515940b874e71c6d74d5d475d23b844575260b517e99199fa28c851601cb0bf5371893357055d46336b9f15633e8c08d
+TAG: 5b830a0bff486119d1ac3395fd3273c4a510c920
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bb44eb8d4f7acae58ff9814da3968bf81fdcc2be3bde7498b110b69a20312dab699e00aad26760ed582d37952bd468514119b003319642ed656c66b20a904c32321862e8ba30ec284fdcf7a0e945b6401b4e0f189ace86730f2baaf35764d297c653d2b297f27d177b6524251ad85757c56e884ff108689e6781cf8fbe4aa6a3ea02cbb939bb0bfaf1877c91020aaf87109f6d5cbc60cedc19f5673feb74a6731627db6fbf6db129ba2e35041e
+TAG: 90098e10f9a011d827f2ebcf3642ff492575d5e6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bb55f77762afb276783bebfa00b96f452cb5c5801a682cdc155a287ff10950e284a83fdfbcf54391c8cf05bdbf11d7b31a323ca780328cae482212107ee24ac8622bdd5236b1948116f4189c0328f584b55bf0986ad016bfc374cba8ae08b89beb9870f5846272aa9102dde5e80134f0ba2157d401c859d764e4d10f56ae4a733b3bc170ad7a3a9cd2533f5f1f0763771acd63356b92bbd6748144f14e936881247397a42963bdbc9223981058
+TAG: 56253d0b0ff161e11a9befbee5774b855461737a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bb0f137ad00f0d0f84149ca102efd8a82143691be4417408fee38d1790975c594ea8db36ce6f9d7033161238e07fee66ab23046bd19f158a8789ca67ed5a8629d11b33c343d7c052c5268bd20da7b5a338f87f35f634ecbe76c23318d59e65670cda8a1f46acf5748d8880c47d96ce250ebd717890c065398e44832871d05af5aa23da07598ef1620988bdea3565bc463afb9d01213e2914eb92cb7d0b6dd2c6ca38142246204d473a62d17405
+TAG: bf3b027cbbfda323bbd5156efea8dd816e5eb67f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488fa32577394bcd29c475687262faa452ebaa8da8d152714cdba918851d95b52ae360f3fa894e1a1bb724c4b70430c121874a0342b25913c21ccc5e391f40c6245be186ef4985503f4b380df7fcbed071affda1d4cf993d01a17227511025c857e4fa04d5cacd8aa80ba08f7afffdcf23d5bd974b9bfd7bd5689daab20e4306fbfd15b21c70d689a751ee8b013b350ef6588f67e7dc70d106583a72c981
+TAG: 1ab0f9fec0277f3248f05bc6b82ebdd1b4aa1983
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f0cf0cfde9c52f8b9d7a91225e5aa07dc4dcb2c5bf2361b0b291dc4bc385f44154f541ea327aff441b75ad552a4aadfc14110a45c8dd674aee0d0814ec6e6d7839e4847612a2e36456b6299a7d96c8baccf7e9a19967307614860c9641bef19862e0eb6851994962650f8e562ec80b17940d099c486cc4099e15b6799b45a4484f4f7213b2e29a07d9a02f93b0b084a2025152ef0c8a6eaabd5fce167
+TAG: 4bd997f670a0e16bcd1fbe245f92ed453579d6c1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f0cd217c10d85e279877992cff7a333354f411e46705a899bca6890c381f3bb9d5a6bdd9b28159d41d7b74f5ffb8de71117caec853299c1504cf6ea282839ff7309435dc4d8b0484950cfbb52f87bc43f9bfe95f40fde599d531ecf6d8a87c49812ceb5dc85ad54d85f05c4f5c62af69bf1dddcd14eef35c46187d0e8d9e24bdd654f847fb61e4578c79dc25dab474dd821bce90ea0a55e8407989121
+TAG: b99e0d4475114b4970feecab3340711bf7141880
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488fc6e3e7a5fa0df69f9b7fafa5108e99fc910e7aa939fa4923dc573f4ae150062620620550f32d6adb13e9a0924d3df08a12c0002cf1e708b2a1b1a960a56ea73d3f271eb5a7cf5113ca472d18758da5b72aed666f6fa950b66e50ac7c8e3fa989040e4d6b372298d9ed8cba76d36888956fc895193bbd0f5ff49755bddcf0f6b30af53586a9d2ecd0a4d6aa2f7e82e4c1c9b9df6c50565d47c690562a
+TAG: 31ff25add0e4304832728d90aa86c61cc4fd00f6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f1f57d68a9ef71461d6b0489b48cdf0e44fc27305b5edfc936f76d11a1fcdf09284647f52adaa969481d30364582058b1d058395dd482a8070c5701e8065c164ecb304a49b852eef747125ac3dfc2810889d50bd2a75dedd2c75523c38f7e3a36810e78b0284bd0ddfca3ce0f6aab86135379f4baf9e52059c10d858037ff64d491b047a74224cc2f50537880427022afb8a6395931fd7c606e616d5d
+TAG: 17728a9bdcaa0e895415c2e2cc5c403caf934482
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f5c5de34e8d952532573d80c30501de0ac1c903e40157c800aa36af14be9d9dcc807c6e907a30dd4c46b93a197e1ea2ff8e1be85b1209f9e616c446c415bd3fcccfb5f7c2154cf3d366f5c1d256aee0d5cb1013e45f520ed2109f798e42a40b5260484f891300d103b1289e28bb88bbb26b5523fd4802c80cfd2dddfa06b09c00926a23df6c52d3307674a49df7613ae721dbf02918f964f634cb2f91
+TAG: cda441a331dd20f6bf30bbb9e79bdc0540315716
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f17c418f96477ec99fbad6745c5bcafd6fd71f9b89fe2a8f7cc0d8e9c683da165b0d5899186694d65c16a441357b0a6b02f0e71d1918c0a2acb2317e0de139ee0bcdd126f05b623e489915bd20820435eab7547f4e6a197c8e9c5d920bb0e64f0c4cae3304df968545d2b35fdffb3fd6c5012edf6ea628af395b3ce83eb83e3b33f567ed7363f68f080a3225d8f43ede7dbff690288c38e232941589a
+TAG: 1962e28864cba63ae2bd6fd94dedfd0701b52c74
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488ffda4ccfd56a3eef4485ae81a0054e6aaee05d1b8e8491a40452bb30394650fbb7e41f356edf94e33f0a38340c6cbc7caeaf093db42fa90bf074bda6f9b1131fc815eab89d26c6857207aed79b1fc2c397499daf680c38f57b6e8f1a15580323671524e8fdc8ca389f036f98b7b4a6d48af7e84f8d9044d41cee06cac482586743e51f0bdd95b708326a4b9df4cf8050cbfb1f2d4749d491646b59741
+TAG: e3e24d6f68b6eea5f7a88fd9f3654e28028f1750
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4d03c9baa6afd1c63c6e6ddd0dadc9411792948ecc9793e60622e979b8c87910428cfba0829c5a2e99b7642619551a4d1c22d1a844d1c7af5abe6e17554e1e2941090496a43ecec8d977513f9b170075364bb78cc010e9c76a9eb7e5880af0ee9e4948856d2ec2a987feecf17493070f73ed00640c3f507f4cd7d9566551c0cdbfa871199386088b8903eae949ab7f85efe68f32b9a8263d990803a5
+TAG: 955b948a9e5a194e96a2bd64bc2f8ce53b40d201
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f16f6aec2ba09da61eb87ed109de6470f2be8ca4e3d17fbfa52892d6035ca4ce899898ce8638af3703c377f7973536f7217ecb7a9ca63f5a01d7242220f886f974f52f91d731f7eb3c0cafd009a19507c03ebc21060635beea3a1b8018aeda2cc8953d34390d4a247ca42c506b7dd766b57543d4cb1908c78d7ba86208327d6fed7c74d97b4e18e83b7d302413eca8bd00723d499b055f75a210a13c7
+TAG: 14d8c2f246b49f15d6e80955eae0e5a8350c130e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488fb92923bbe64a81f80c5a4aa6c3b8225b3d04d9b0852f13cbcd8f1b6724c8cdd08f988c41c4f1d42bc9c6b148e1df917d33c34ab495c01c68cfeab90f673862d8dc42cab6ded823aa67533cbc1a138784ac5c0d50942398c30fff66ae22f96b12ef329142f2be53b39826141a7610528b959cbbf87c274dc26cbbdcdc5acc04c358cfb5eb4892c25ccc5a1b6543b73ae937034c6182a971ac1f3a143c
+TAG: 4467de304edc529dbc7af389ae72b40dc5178fd8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f274413b26a3ee6e6cc30891adf11118c5fbc23eaa223c98fd8275af201a178449d74cc4913f88a76067abbf5eeea001900989567f8ec011575859f22ae286bd63e7ec8edc0e265b477f6adc88f2ed90317db71a8749d3e1ae2b7332cf98a38208a2fe5e13323aee2ee4c87e015cee3c4a90d345807b5d0bfc6d3deb2b9562b74b95f884ad93bddd8245194ea71cad2dd5be7c26659d592f79491cdf4
+TAG: b894b69ee1589d885052eb4c5e8b6e61f1d66ab2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f6c18ff2439b4e2188c73db78b91911dabf40b860b97401937eacbedafc4ed050e8c012f9f6c5bf4057b9648a2d70d83231571d3d0afe7ed64fa0526cd0faabcb0cb74b342bc741cfc6e44b11090c302bb685458c8c5fb785a059d5a79cf2c79e22e4884acbb7076e8c1fc1314bf707f93f2c513dedcaf2e722cf1f519d935c5331b962aa17ae0da1ae61a91da6bbd9f2e284f53703f3f5f57c7fa8e6
+TAG: c111a2c91788695b3dccc824e4fb706b9b6feaf0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4f737306b2555503a3546307001777fd70e9243170604454c40c11b1b5589374c04e031089d7a676b2d2c30ed3afb21ef984676747570cbbacfaed4572348617434735e4fed886af396e697d244859ee09fa508ef767c9a3f65a7e021657c70fe117250cdae13f490621232e063326f0c1fb164d996847a95b39192f7417649b8caa5a080716cf955b1f0b40e868d1ef47fb3e3745f0d906c4526851
+TAG: 2a6f1105cd9d8c455688639770f72e619dca7396
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f064991d0fea7378bd14e579d40c4891ea87b2f8f33c90985f43475865a46a5e35d00022eb013ffd2921f2b5e04ea796f84ddf6190cdfa1987d960ebb6ae459aa7a4547d45fbce20e1a4213544d255ff229bc1a7321d09ac44b55b497edc3129b10c067b6094ed1d91729a89d63fae94ee5213a560f5a7b465abf95542e1a70e45c0314e832e9fbc83dae3e655b4309e9e5593c8bbab12e1b6668aa9f
+TAG: a2e6102a003e6f2e36793be87c1d2e488b3592ec
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f48cbb43e3ba8700f1eac099d1c1eb8f420eea0a0c7321453b0ddadc76b7b1d92428a3d5afbb781a09b1bd68646ea822636ff91ab41ac64d4d4fe810a6a6417cbd779a15a6564d326476e0237ba4336f61d85b1f17989a8230dd7fc6df022b20ee55436246bb0cac9ed79602e06642fc8d9f3061df3a512aa77974251120cfe2e2aefc1ca827fd0027eeda1346b4d3fdfa5a077d7510c2fdcbd0e622e
+TAG: 8a6db3531a7ae506e94af2d5fe03871c72f7e34d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc84f97afd5f60048cdfe28d552878157a1fd4ff8e118d13472ca47c2ed40a8a66eac8b129a9bb779755e3d34cacd096a948001feec47eac8866923ece17f84ac1e95a191bf90dadd637a8144106faa7e552b103d55b97927a9dbb4f2a307d0b8ecdf59d86f7641437bfd9592bf2b8e886bec442498386dfadd04890715bd5aff455adbfc9ff9cb9700c35cf12b5
+TAG: aba38481772ae68a3471b3abb2a4b321ac18847b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc84ce9c7ed23693a0b7e7d59554b847d42dbd33a6e64bcb8383b98a91394a56579662d26ad0bf29b80731472f83f5e49b633421f528abc6fe931c27ef1fe12e96855ba60f17e76c460f1a4e52a85d2ea30a03bbd47d9e0fb7aa8b4dd060a84333b62db31483faea64c7ba5af3e372c5a721f112c9cf03312167e32dfe9be7ca55a8ec9ac62ffe566c755667c55c
+TAG: 5a2bba3bfc77e40ede79c044a67e3eb9b607d38a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8452fb9f77a22d3b3f88b547968516dc80bbf165c6008c1744c402e40fd0f2412ac852b0bc0a714f2166361e3718b20127eec4e50ab9c1fbce7dbd0bbc87fc3d7ea92def78312f48550dd6ba670d877629cd6428473dacf2d48434ee8352322ece65b939dbb2df4893e0ec0d03120792e28a660e239544436335f00220a859b6422f3103a07e13074aa2a5bdb9
+TAG: c39d746c8b9438e648701b0533064638f58492ba
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc84928c3d211efd99b8d22f056ac94faf2b5df067d50cbbe144be02b542080e3f6d26af8aa33526c69820ac90f87180fc2621fbec8e6f1773b7d1e418ee268cd53567f33439b849dfb1d02293d083e0495ba1c91219e15b776877860ff67428a4bbfd79de8869943d58955a30d834e09040d5b4e8ca7ed7fdf3b0e0c7c90e9ba3c3af474f2e6f80ad89c90c322e
+TAG: 2db79115fd648e4692e0459b7ca9c8067f85d91e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8486fd8885616244b479d3349ec7a6478265ca49de45d65cce90cf4d0386e984c90dd4a0746e59c7ed62e7377b4971da5663f8afeaed76c2a295d9ee99c5939a79181915315ffd6cba2041573e0163e9acc344a5b9454664b8656da7ade87d088dea05d11568604284580c13e58e4b3cf42258f4ac445aa4a2d01bd3e4976dd24ceff2b091bb7b4cfcad92e59c
+TAG: 0346e2f91ab5b99acfb53da17a67f7f8b98ae676
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc846a47952b8c68e49b433eb4c997f279ea4c929cf395370be690a99896a747e8700aed720f853eb2b7442f84ad340bc13129c9a44821efc97b689f038cb9b24196fe26a67b8cb0000f52419c9d2cd7a7c4b1ab8b3646a85fb415bccd38afa038fb86a25cb2af016b4757a7acca07df735eab0f1f375cbbf529e9ad5c34319bc3ca54cb143b241066d129785f47
+TAG: a04fdd461eebb27ca4e4e92bd183c05f0d654f71
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc84714c1b170f0662d2811a676d66ec3bcd7f0bd133c42f2fab256909de4cbdeaa50fe21570262c30d9c10635fac3df6c64570e3ab790b4a996e4f6d78dbf1bf61fd14f93d6d598c23dacee0a86e61e09cdc442d73696221c07ce42ef7bf20e67a7b228d21b8ab136fc9eb84e828d25c90eff0c6b123cbba2c5c4c2cfea3866b19c32c841559524963c8b90a388
+TAG: 504ecd2a203bb335499d8708ec10dc7cd85d012e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc84060ca8254bbf3f380b1ee69c70af8a3b2e95cc049df667d8be98e527a1406c66744099c16bfdff4a9a6502d796a8f2b208c7d4945d774a1237970dd90435c3b40e96da0c35b18c6080b33726c72c190e8b8b65dbf9946a1a7d5c21bfc9bdc36e68df1283d5ad9d43cca363fae39d962196d82c733110f7b294b9e56e18096fd564b6f2e26b3b062d7985c7f9
+TAG: a6285b0d38236442375d78de78389de04a4402ea
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc84fe28d9791e692ad6a8d3af01f2a70c33f60ef0d5538531208951853d0b830e8ba148d3d12f3ef19fb1ad84917353e8a93b15325082e1ef0ef80089f413e649264a95f017d43125ddf2fe02cfc3c85004bc1e69cba3263e373200ba1436f70816388ac11d3d30704351f79a100d3022e3d316afd3c0be291ec6a4bfcaf20cb3adfbe65faf9b8d68674ef30f02
+TAG: 1f7bcaae1c38ce8755dc67f282204c8852d24572
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc84f01349ff716d9040447f001e6adb255aa550afba1658ff483a1294b2e81b72814f22273817abd1635bc935bd159bacd9280c45221ff969919d06b48fc9fdbe7a18213cd9d2b4b59336508750a22cc66f6329356405b710d685b69e63f39b035acc67199d7b50969bbbd3b211cf7ecafbaa18a9e4278b610627eea7b1e24f0822f7809f1c97c40053c792aa58
+TAG: c33923335366634b865a35a281b516c8170be943
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc849bf8bef4a180e100f051275c88c33b026feecbee0b32fd2c14d0fc053d2bee4eae7e179fd770e7a5ebfdcab94843c66d09bb135e68811ff4da14c72b4772b0ba1de387a8ccee2ead233ffc16a557fcab7ce549eb9367053b93aa2be20e395a88376d9d9520db3eefef91ff43ecc88873a0915ac61c12f6b57e7ed5f3793f6f6c007a6372ee19e86e31bf7e12
+TAG: 598cd9108bfe337ba732bf5622ae602f9a075f78
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc84528d069b450ac7fe577db2840c379353ea1a6b4c673e9ef4395ee16131b4976dfd8ef5e428274b2ebc6072f254ab9f9a4c845d7089dae6ba774f6f7a388fae34637299103bf97b82e5e7200d26c9afcf17872375a7f03e4628e314daedef20bd6778c7f3878b5ea42ecb9d5e3aceec133a81bad741453ac147b26ab398f0bb1124992f6acae91633e9bb7082
+TAG: 1f998d0364472449febf940eee6896b3171c0abd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8454dd3f45087b01718b2f09a318cf5f1f568319e8a76a2c8a97244ac3852fa4235dc938f64c4d78c8dcfe6b1da56b490be2cbd5b11731e61dd7416b4c171b5d3e32bb3e85369ef33bc61ef8f4fafba85ef253defaf1de4aa26927920a3dbb39d0c62d7eff74c785f083f6ef7c77dbd66e6aafaa01c4a04c968f236e53105985e07e7ec537d9d94354f30f35be
+TAG: c827a720abd7d349e947188e4560941fe5bc23a4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc840846383253b859f06a1a76545ca2d49d633724f6020a0474bd6f294f672e32e673bdc686435ede204ba1ca23de7c811a82ee8cacd0c2dac5ef0569e3e4f27f2f117d49c5752da962b1d1abd4fc952d3346f5435fda0ab2abe276442348a461928348b74e37dc80a4cb381897005a18bfda9ea6d32b65f5df821fcda3b224de9f49dbb05c28657a34776a5a5f
+TAG: 4df006dd82e8b2d1b33c910bc0b7eba32f6a978c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8468ac43aca5d1f4ca6421132b3c20b0d1e5edee3c875776657ba603a1aedcbfac667ebb2a8e1050a0fe4b76305d19b91d07e090bf26f5a6ea45133f10dc1d676bb27c56838a72de9297059a15060d1c28eb8ad17a53a3124250fe0cd7f2b277341e88162b524e0ff0d4ac25699eecc312b6806f5509495646f185cbce80a35a127117fa00cb2fb0558ab18ab6
+TAG: 7036a02627d40b6f8ca2b95e3df1393bfa075e48
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc84e926ee570ea92980f6511f2140c71fdbdcc5901f5e4af2d9de071e53de763e1ababf8dad4300ac429870bcf084b8928f2c953c4827cc17689a762efa09f484e95448185d0371f2be52cb8b18ee886e740c04917f1deec934eef1c96efea9c611918fdf1003c3d9c72d50e68f9d157deba81da57766817763035000d84cc036d4e147ddf570995a68f4353420
+TAG: f41a190c577426ed3bb505473e6c6e2c5603afda
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb7403e2d874e49d26d8f387995d18e7d0271895ed30f0c1cd3868c307ea21076e986f320572e7ab678c8ff008d344254baa8411c0d0eeecf75f28a1fbf1c3a25311db4f667c3c4e94fbfcdb2a52940aa49794c662cff0523606a0b39777f350ecdd3353d336b693bc3ada9d28712621c2b4f843a92bc161c6fc1d2b5d49e3
+TAG: e0ea5b9fe84496bb73a64a98cf2cef3187d21879
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb7403356ff97b73c0cac52da67270941e19134fe515cc9e2f8567a4101a29029063c4cffb612e7de79114c9904c6fa2c4bcb2991b177624c0033173e69c5bc25aea8b0a12ccf312dfa6ce3245b73ccd3d8811400025c1161f7bdee8af032d0d8cfe06176f9dc7f5b74b044c08835617de2b2e88fd5fd34a79777234a60d33
+TAG: 6000e6b1352da753c40931ad1c045b3bd3aeb649
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb7403e1521ba34cc810253d2c593ad47ea87bf7e1b4d523ba4d13022fa47f383ff66c3def79572c3224a80d2ba4657b549ad1a328bb8e9e067b1abeb1a3f3e61b76aef37420b208b2a5fd79344049222845c6c02d7450a92ab24a332c76dcad27afb23e5a9d84bc66db053fa56474b36f8b4eb4621227ebaf5568543d4e67
+TAG: 53177839d9d0ffbbbbadfd09442458a911fa661e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740328bd376223a41794f233270cd9b16a440a6daa7f98d8116d6bfc5b1af06143e37afddd42de2368fb14adea726fe7f315ac2708fe606cb3399380d37a56bae76e5c891fb3399484b1413a620bd70f941c09a6850b96bbbb08495f1437af98c693d1f5ff38bde67021d885205af5241b714c3ffaa1d9fcd853b47f8aa5
+TAG: 17b686e73b2c247f63de2a0b7ff249a186baac75
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb74032230e51a38bbb0cf37c5e3db9e188b1edf2905b35b7c284d4f84d7e8c09cc90bf9271ac3e563c63adaa88f7955e935b61de8ff3667b3bb769e78f2f7e9ddcfca21d9d0660d8799d89c9627f5c4da45480682cdff47f926ebafaabe3b15841938dde3bbca1131013d03753af833ab435a06fc5479f13344562f5fd86b
+TAG: fa9e08cbe2493518a70f31b5f9a9e622e285eb84
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740322c1ee109a737e76c441e061f6de3b4a930c46eea3d526c96cd07e4ea30683950d0d1ce7d7ed36097c8cede58e2f4b9a2542ff4d36871474b66f45c267f28e1eab3963b1d68d020298af3556d14461f3468e0670aed36b1e99c2c8ecb3817771fd69ee7490929719880049bf70d5710b0512fa286e3d56f02d6301e4
+TAG: 9d2ca2279ff4ecbed416acd28587bccf638841e7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb74030f6fb548d15cd916e9567aef75e06289561451596954dc4b82b3d85589ab1aea02aee175d3a36a25c1b11ad15cf6f26e2b921e55dec1bda7436fb99d299e492f60e8b8abfbeb77cee98c07b40700cd87d44deba910ccfffa62249f334da7a36ff2930d4625503286edb24692c562a1f0e9c6b5c54e0df2676ae58739
+TAG: b8e2ed387bd6eb724960a718d8234a1b7ef7c919
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb74031b8d8f8fe5a955e8c84dcbb8ddf5a40afbf4845a37de15fb0b47ceb1b2a326cfdb41e931ad937edaa805ef520fabbbcc24d7aed51daf7903054f2a1a1dad03fc334446445b70fedf9e39d23e88c914f82ac7dec6293572df0d79f3cf0882df834f9e4ff183e42ae86586f9e7311e98921c1688af09f15d240020911e
+TAG: bcfe8b0f6e5a4041f0602fc2b343b75b91bc0463
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb7403848d474c170e9229898e5679fec62200b557cda7ad9a8c06f638291a5f3d2f16ebd78cef7decb77fc67c43b009d0d49eea34f652d02efcac00ca303caf9fe7a792bd1cbb08d5054f70105c34b5ff040a0ce1e8fd2e682d67cfaed57eb6c5ac576113c66928952c3131207156f09ad750d09a13a7edbc93e3d587a25e
+TAG: 08e9b8afd25951e109f8f189ca7666aaa4b17381
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb7403c1e816d9549c9610271ce74a3c56b553db1c112b8b8486804328e7ff01b8db1b1403df99080f0e08ef39b9e71d4cf60880a1984bd1091e4786740bbbda4244ac921e68b0efde217c22f688cec6babbfef11f807189d88822e50286e5b7f94fce1f9aa7164709fd34a166c032aabb18b9027ef8a55eaede99d2b3c5f7
+TAG: d85d91987da611409fe07084c285a27fc47d1f6c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb74031bfca53fa1f5e36cd1dedd13f006e9e0055e101a749057c3a0f2d5a19546646a3089e7467cd45804dc15eda9377d78b43a49485ba5ba3128262e614c1768345733afef9bd3b2936e2bedcb8be2cad84c2df1a49ec28267ee0d3b3d8794788dba29e678c11187043daac2d9b17793bd5a3984adda80f09af9c49e0a64
+TAG: 3fb284b53a482fd3002eca5f14a8cfa8c2bd0758
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb74034a0bbee7973becae3632b43a815faaa32613ea6396b6eaee217b4e9380412f6396241b25727ea1f09c8dbfe4b566559a5c6de40c703afb0f6b52bba9cf22281d1cd047d2bec16424b64f3a2f180c319ca019e762dbfa13964e0f14bd6a7d2ca2400c95a754fa5def16e0a8e6f7c564a50c1b4c93435d80d875a554b8
+TAG: 34c9144f6bdb3123d9334da1f8def7755ae7e103
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740320894f1dd94c42bfbd32c094d43db932eec63372b5fff20253d255cb49d1a521f60aea26d15d4e59024621ebb644436736458006db8b1b174f0f0eba3957f4684b539089eb1e7ec171c2aecdd39443743e6313f041f31fc9301576a752c888545a2ba6096c3f3b3284527361e8fafdfdf1d82051d7aa44a4605ba393
+TAG: e739fb5ed2540fb1f55b4bdea668169024250aaa
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb74033d9c7b625f899489f4ef11718f6fa243ec50c3776023365a7a3abaa75a85decf74864db0c94bb1dcc6348430321d90fd1ab5bd2233bcdf326234d8f993b729409616bd1ed1c869040a987a280a14c5296410e7335359d96b2d5ef6d72afa2f5479ff327d3a3abdb2344bbffc44199c7408b23c894b3401963bbd14c3
+TAG: 55f5eca86283878597c281e68a269c79d651dacc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb7403cf7b6cd216560eb0a468dcc4b957be00b2fc49bb32f8c57bf1a1ff3add4368d78f379d49afaacb67696b2779ca988d0b363d02d00ec56d00e11208bb230c92dece5ce18065785bcff091561214ae0c8d78bce60fdc20b5b8dc47b5c0c473a2bb3f34cfe63f1f08cd10556220033fe3066f0f58e3d2ee7c264bfe30a1
+TAG: 5476a2103077c7918b53a9330abf3c1bb5074d46
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb7403e9bb05a8754b4e45ecdba91a1d0a12a4bad468bf9ea9e83a9ce2787c8fdc0214629e56dff1fcb4e49996a4695da84f6668331533085f9d3d9b328532e467882220b4b3f056e5d76e3894099a18bfd7a07c6a716c463b34f0fcdb52d2435141afb0cbd9ca2d064b227daf27ca659aaddda95e17a4afdcbb3606a87152
+TAG: 6c46bac39c517955f343d2280f016b706afe5dd5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c0677e7857c3686ff3079bc2c1bc3f75a0773e5e34b49b3a569c2b76df09eace9e867dfadae3019372fcc9c52e005bceb73198fe4ddb7c623d72c1062cf208a79064f3f7b6ba5e904530f34c1f3a50f83982c69c9c1d8f54d87fbcbc9cce936f56b176c0a4b37c0b4d41ad8cb3
+TAG: 269d732e768dd6ea274c363447f716abba8990e0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c0ac6a9c1bcfc5697a15b2a9cdd8eab1639ff85973e0e8592d1e8d689a04e1a81351469f5e93ecec47cd44d6db273fc16465a6de1a83c8c6b17b36ad9c6976a1928228a405955f31598de2ef75a00c2569730ddd7f0ca2741cd27156082c364c20bbc936851ad79bf9ebe691fb
+TAG: 734112f236212e2530460ea578f97a60e874d4e1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c0bcfcdb021f532936254dd955d21f65cda8521dfbd85430d147cec59c6a3021b0718aa35b27dd8d456605fc464e6a8086785d1d0783b6cd2915d868c32e476203661d15b54dcedbc7f1a1751b8ff0016284934b3a9531cb6930f9f8d0d4f86a93666c08dc03ed7e81189a990c
+TAG: 122a288aadb66d4868028386d866e4f0998fd77d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c0ce61c008ebfd8a7dcca74224cb9d7c1706ec617dbf7e15fb87e9e0248f57b37c744594ed9c81102f46a8b5f62a244538c25d6cf6c7cf121987a250d0c649e73073c77a00a6b2a374604e4159a19ccd6204741a52fdb0657845b0b08111b362dbd7522662a69b1864c3162d03
+TAG: d61483f39e2e27b3705acef3bf8ff3edd6589acd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c043df9e9fbac7808b3e0775e482cd55ea34df9f95bd91524412f388efd07c91f11c586e33e3f8bcc6fb3706d4f79429fb5df22269f79ee96dd9fb8a3dbc369a27f3269f13e2d621cbbe9f2398d49400fe51f0a2e1e913de9ad1a7ebe09db8baabb0d10f671a275e6890b49b58
+TAG: 3e6ee36ca6e990486842e0d14ee5ff7793dde62a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c08eb95ce18c226af6742290c82223399fa93c540cca8866bdd266921e94d73341d3c20604c139ba86c7d3db8b0e4250947f07039ae466da8f4f986be58ff864f5e7da985da6902ce333845b27df0d371602edebb9df93ebaf99bb9ed2e256309ccd0616ef95174e4dd3b7e266
+TAG: ab87bdd8e15df6d4cd88d881ee9a09c310debbeb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c0e420565f322cadd7e8bff7924d26d1d97b1df26752ef3494e3e050ebdfa1e00658caa01668e80a9ed01fa05efebc5e232b8fc8656eed3703ebaa40dc48ec0d8fe1eeeecd6a76d46923d913a0afb804c218e913b2d5b60f47f0b23cd710ab69a23e1c5079166a4f3aaae9f68d
+TAG: d3cb30324c6c4d6de0686854fc101668b5a9be5e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c0db4914f1e0817de607f55d51a2486368ad4ebe249388b1613a3080d87bf16b9619e8c09d8ee153560bf1fedf6e804990261f95e8a708bc11d2667dae365a8595c028c0d2acf16d5dc4d3fb19a5112c23811f12d67ca478205a588249ad51300c5e1fc763145d05deceb4564a
+TAG: 4ce30eafc103d2ed76fc2f04e5f75b6763eae244
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c097cbf5238d2f5024666c7609b6b0934663d81b9d92f5ab2d73753a0e7636aa9e39493ed95acbdb887100e0dbbe905d52d68bbd441bfa012a338a9f4f2d0d95fc7aa11af112fe892ed843a7a1e53c81e68ee58ce4514aab10248397e67eaf41491bb1a3231351d57a95a57a1a
+TAG: f4c35a677fa06299a57162e1a84d70770c2ecf47
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c0f1f12ffb18d72e72b3e4347bd561c3c37b2de69b6264d66153ecdb0d1b20395e5cd65fde155f2109a45798a0eb32c480a68a4f96a22f423a83db0752721b29001bfe4a66b84c997d8c4ab0150427587e88cfacdcb8285d47fc6cb6bc37c3165bde34c943c109317a3e9cc258
+TAG: 01fb3c63d6f18fe5430e4291cadc3ee3f55a03e8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c074c573952173dc1e077c2d94bf5891b2a26d5baf9e6cf2a6a8444b40581b8999372c98126cbdda6e5fb0d59cbbd738e57951b67abf3dbab991569fa4697cc0785b1dd63e181560404e06e8d9d017c7e11d93aad8a8a33cad51bcd07bf3bc449cd5832307ff812fb5337116e1
+TAG: c57e7ba694a25faa5d1b712002558d8c00931741
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c04f7cc59e2563313c1bb2ccc1aec10237c4cbbb9ba0aabd38acd94d8870cd4c92cef57cd5f325c1ea14692660d0765cb23f661832eb379819080a13efa28a90db7732cfba5c84bd716e5733036417b5090e0e2916be6b2a3f4b4c92dd508eb5aede9c4451821e640103a69348
+TAG: 0b7df9ccbcea1d7eb1dec58e168076a5580bbf19
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c0e764bd49eedbdced2d70e7a69237ceb68caaaf6855ca2da5fffe177c2aa12b087d212fe67010b7fefa2d12c9516291a19a72dde12bc4034ac334a59cda0931115df63e6e5555d42a36f5f7188815dc877140f07cd9c08a1d508129d973473c4b4b83d7c35bcd5a20db978f4c
+TAG: aee3f5862e45966e42d536f30f811643b2e8ff6d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c0745b15a09a81c9dc0de7d8b7a9740c056fc08e9a57b6a267a382dee1b4dfa7e783d4cb0ef18b33e534fdc7c8c471e876839fe0ad149ed9f73c0897548e89a6e739935737dd6bf3a31857033b849071c9defeb7598b26cc025ddb4b9f172cf5629eae9b51a4f791bac2441e8b
+TAG: fa67a0455f1dfb61d770ef2c3625a97902be505a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c019451d8e8e463ac8f162a99b6257d161199e8d847fbd5a3e85d2454d965c5efb8ae708fc4384eb22f23f0e0375ad528bd42aee7d06e4db4210f4b1b6e2118897ab5361781c66a9bd0f780465cf1371adf132f27f8b46336ce8d5c6f1054c5d3d975ab848bd38911fb06c9ae2
+TAG: e9bfca577f6ab16296e2916ba6377e02cda6e214
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c0d3465ad7201ce0d3d08079a9435c629a2237c13b01400756e37afeaa9615534fb44deaf5fcc49d6357867cd190e742f4f7691b5dc7cb160a8964490b062bb241d8e5938588809a25945048b95b01729e6721d39c2e2df7abb04f8737899ed34e92cf67e45a2ea423fde84f77
+TAG: 92b4ee022757c4ecdbd5bf023615a962c41bde01
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e9f37b18dfe19be8b8ed01e244a1c76187ed45226d7cc1207ea864a20178a3c46ca147355f7e4394951ec92bd694fbe82357dd786637872be27af588297d1103de7fd2b5b2d04626e4e5212b720656daa0c552709f3c3c220929980f74
+TAG: 79c941987cff3784c8863bda1199670d8b2bfab7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e9040a932d95b6989cf917b36d7c0c4530d000fcdf789e2f181c408794f8cbad0e246a395e6ef9218289561398486584e403d4e6a1b2bdb7b06768c5bc022003739d7f57b9bf103d434518e6242399b57714ff03a4de4f14e56f69d21c
+TAG: bcca26419ac07e3d25572c57a8452925552fc19e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e95c188047a209266abe082cbeac2379b2b90edf0d486e2b1b823d2f581238a478fc6bb7173d037b15566c1af687765bb130822ce988b5c0d812cbb877e9bddc3d7a05d17ad2026c4a0a03876592718c8de4b197883900ff585c6fd85d
+TAG: e74f327106037d8f020edf80527b18c814120e88
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e93018880d724cd554bc262d22939291fe5eff0de652a9c03dffe4fbdb212adccf4dc50f8b612948a170d14ff80636d1f0985768775c8da248ba9e737bd4d6634d61ab5e1bb8bdde505241ceb4f083544728ad676dda702fe8ebcff486
+TAG: 35b450c0a19429a8fb15e84cc840cc38fb1f2c6f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94a0abf4ca4048e7e37c6622feb3f1a2ebcd98cecb85f6baff5b47839a25627002020eff737941326e8a758416b6b35ce2695c97905dd80a2158ecd804ea9e7c1a22ef0b6d5f27238420d91280ffbee02632c1678806c739e62ed1e82
+TAG: 10cfec97bf6a2f9a4ed4c9590ae449517f6e23cd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e9a0c46416dc63006ec1d83c86a6dd1aaca4e347f5e00e14890e2f4653b994ae05e5c72f3591fc460b245f8331e34badbcb2f4ba97682acdeb14791cc9abece3261dd856eb4d2145709e13a31467555a577e05f0c0a476c6d6a666510f
+TAG: 0c02d8995012c2b37d49795a8034ee331a82ecd0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e9f5913a449137cc73384226818de14769598f54679b917bcb9445b8b66e97252386ee27d85a84236c47d06e53d1931bccbe20ffc6a1ea47f7d4312f5f38b7a6bb806ad548ffc48392a24a8f12316b2a6919e1b985e3884986b5561435
+TAG: f2b9d9a94047d95b1acf4ff7b60836418d017315
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e9ab617c2a16f75be02146e5f60b76ff153a5788a859a3aedb7c32b328012229502f00b7baf3ec3ae0a617af3aa3c04ad0bef67d8751476f91dad19c226c107891f0f36242ba2f5a9a9b9bcf303dbd2a0b7c417a282c08331d347fad38
+TAG: f6e4731e7072904617c093034ffa5fc1633d52d9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e9cff7a1d6e0a97e866a0e039f7e9b996b5f2f71eff33801fc743f1b389315a50efbc475c110782da1e94cc7236f7ef2b52b03e203f257ae652a41d8466a839295bfd150723d820487c1352156a52f1fb3b71354d9d437b212137c578a
+TAG: 4aa36750e8cff0a8734a4eed27797981ee204ab8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e951a649ba744732b4a902a3852269044e3757dea5ea41f050abcbcad8ee7b5fc0f4c50f217b257d054971d39204ce558774507d0ec3bce2a91d56ce699c21b9e658c3d5391a32a7033dc9a59aa0f0aada815c6d53aaf5fdf432b59968
+TAG: 4551a0a1c0412aa7b523a8f79b79e16ac41d187f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e96df5abd571c823a76e66ed5aa98bffcb58e1456ba1f0cf6f0dda6bf93ca8bfb39072b89f9be9cdf73f0021d7e525931581da12e446fc9e23c997e0adbad8f99d49b97e841f662637d1feeab1ad00ceb3742b20bc8cc85da8911497ba
+TAG: a79a5b34859a59ab49235969df04781e6ffa07a0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e9d8ac195ad35c77b6cb34df93557ded15cb3fdbfd1113dd59b3fdde366b98a6268bb3af112398cc67d0bb1cb34bd1b89309cbf3b4b5295b7cd976a937f01eb3d9839015f22367bef2ac226d27d2666a76c87681167a36a39184cb94dd
+TAG: a81ae012f9892b46d0699bac566a9c329d66d9a2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e90161319d851c96cf696e20a878a0752b80dfb6f1d382bbe577e4f7424454daa2f9a506ee1189f3e1b48b5fdeaca85b9566f7aed902dac407341ac74ff44b06caf1365e4ac5961888282ed7e14552557237d66282dd4bcc05d6cecd86
+TAG: 821990672ba3ae32ed2016b3f7d116a49506c198
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e9eb173edcf564a40c8c1935edaa951102ab3089779b3d9b52f7a58a05b82da6a7b7e473322c83c8816710ea3c45cf776d7d1f1fc2724d17344d84cf57e99ec9403a0e1b3282b49b34c40408ba810b68fa6faaa202816d72fdd80543fc
+TAG: 3cb39471a042ef44f5d7cf6392ea3f78b08edd57
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e9df6792e10f4b88501f6f6eba35bf66f281db86957618b0541bd23e8ed35341035e589d95764aad483c0b03b8faedf3ea32f0a9889b828281b6a4a8096c746034614ff1730d21530e751e22e78280eff9f8df93009ecd3a7437946ce4
+TAG: 6b5a259fc974172dca93edb1713a67eb8e68833d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e9a99906030ae6bdf7ad73392753dbd384a53c0b23372ed5309d06ec852303934adfa6858ae4b7cdefa498dda7d185dddbbde0579ac8ab45acc927a1e9da337b0d92fbe85e226a40c8247a9f8a3fe40de36240ef4ed2d50b3d3846cb8e
+TAG: 7eb25a4e64437c707147c7ec0d742c11b6b53be9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d03beef996f2ec45c8cd889b0b7273c6b3fb951eb1649f9109a256aba6b918aa2046c7da3005dd75ed15ee31222a45fc62e6a460cbec14dcdb5c50a551b7610d7982ba578356d911142c6d78f
+TAG: f0627e29463d5cd08d56154409bc932c17b48650
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d81ff48c35ce863babca14eb065156b7405c79b5d1df6021cf53b3791f0557dcc09b19e1493592c1272277b34bab7078732edb7a770cafe22511b1c86ea111f0be8124e4ec4c09cf6df1ab1d0
+TAG: 3fc48946f50c83db2ceb51c0fbbb66504eb755a2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d6259086fd1a64c3278750c5c83b759dd9516681c5529944f4ee1575bf16f53740f9722b92d50f30adb333613163e32fc264cbf24dd74a21aa9af9ff7b0160f109b52ff5d97d3c5d8cdbf9468
+TAG: db1f510b9046981d3e5859b317a930c979f81203
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d4a74fd10b37bad7f67c0ecbfd8d0fd7f217af48abd7a1b3e2e1a150563f2f26ca597201a668236e80f98e3154f912ae2fd08c95c4e6768e69f0ee5a129a2dd34a2fb493e36a949f3217eaa45
+TAG: f26c24e46a48dd837e356cd8ac6ab9414e7e74e4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454dcd9fefb389aecb262b3a446b8379f53bea3a39c0feca26cf9206f9ab96dd40a3363ff0d3dec00f81dc69f4ee55c602d9c0273a39d8ef95041feb8dabcc843b6f146c0ead43b4a0a0bc2dc4f6
+TAG: de1ac76f704ad777424acdbc57177fe83b1a19df
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d657eab760984ce70bc48f40aa1ef2e263944fff4fb1049ad69e4092f205d8562f7d2d39d2eb8b288d6b5b4e3abe172429707b96a70a336ba0e08eed31cf60806335d25cb526a5a8e37781aa9
+TAG: 06682d63b07bb6710553d81c9a69b1f5de5392f2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d4bdadca24452b43af231de93391efc668d114d49b3d33bb7dda6d483480ab3600621493b6f2882a8996082fed026abd7c084ec8751d5750336a6625aec5a9b24293d2e203efacc1aa0142abd
+TAG: fa56aa337e34f9397b35e6dcda7f3e7ada79f597
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d7b3aeb32cf778cfff5cd1205ed3acde214f942c561d5f077fc51950ac05fb544957418534b51236014dfc44abbfbf92e8845c99db2321e874a98934a658be36deee20f980d89fc5f3877a829
+TAG: 9fe1b8024f25ff628108ae1e1fdddc98c3c75b94
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454df56fd27c25067e63df17187d790bac7f5bdad1e47781114aaa6cf37678e7b0ac935ad1b03c3e1a9f15ed253ed1444e38fa1f9d2f19b8214226b5c4a9238b0e70b144c3433cd35713d5be085e
+TAG: 44b8f4da101296a594c65fe5487fac5c3aceb381
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d39731ef1f87b4d64f3562d2852a00a69d29424a64e7ed697a3fc153e2779385fbbc8446a6b725a92f047638f9782ec03b99cc7d0b38d61035ede402833591e5f1adce3509314ea5974b1f1fd
+TAG: 324d9e8b2a241ccf7caf3dd48fa792cd244104df
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d294444739215d6bfcf0b98b5ef7baf7ce38bf959c021b634c569951b5fa3cad65780086457602c3e280bce599012b9bbc845eefd009316c1840074156e4097cdd753ae126c012c36eafc0ba3
+TAG: c5dff4ef901c433d6818663efbd01f56fad0f373
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454dfdfeb54c189ba05e3f90e8fd3a246f1a5a60a93a66400988b5db00c20ed6d724f3f9a17fc1b3d82b2b792aca8b3da15b3332f8c90110be902ea1a04434e52cb0f5ec3f62d13f959bf4fca940
+TAG: 35911e87afd56fe1985a7c7b889e6743067cefb3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8dfa039def44435bd8691cd80d9b72a3c4fa25e50cebcfb59075bed286dba438c0a65dd06e1cf593b725a3e76aed54789260259df2d21971c1b4b3e34c8d57d1407f86165146a5397ecf01e3
+TAG: b3155081eebbc7ffe5ad4e0f928372ff9a17cf32
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454dca73b86926a506cb6f277157f441dae29b6be003fa703fb428ebb688c4317a699bef6572ccdfbad7fbed3df2f0870f7467b73b6c800a5be4c89b137c0b60d4e25546a7b6e86c72a3e9e66703
+TAG: 97773eaab8179dcc19178803280a2c432e8bf819
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454dbc6810107c13bd16e74e8b166b94267168abbf7d5630d18b928afaa146392a9995b8c4cdeede9c0c83fd0d4392354c895e4f7e6bf16fc26c5fc23d9316739a1e2dc3723dfd4f35027e018f40
+TAG: e1b28308c65384f618cfafa56d2f38c918798f49
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d17d4aa026909a01a6a9dff6443fd9a40aef2a637390683812e1a85dd1262a7a7fa757b77e4555058a47d737ba919867a2767abdefff24e0a5d5c8e6085cde399d345a06abb981d1179bb1a56
+TAG: 8b678ba76d9f38177d73204096a136acfa7f0a67
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b131870092deef728577f02ad44d1903f0fda05d3aeb088ae53382d286939abbb733b7c13db21a1811b7d04ac2610215d626c7a1ae44828409ed96a0024
+TAG: c31af953967cef920b9def46fbb4c2ddf5f8bee9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b1388850a973e1ae9bea6795ec8e4fc1d1d70d7cc6d512bf43e034ffae1ce6b198a16b9e682b450f144d99c95ae743f72da508a6551cdb31777170f0151
+TAG: 845690b3c5216e930cebb6079aee864b11acc856
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b1365ca49e2effb9127b848782379eed7e4767bbee3111a9bdf26d1b67469125bbc6fbb4f282fccf464666e7caa14c223bf883311eb843c5abce1ec62e5
+TAG: 8db6027e98ba42edd34ff989fe6a2bc9223bec87
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b138837a3f13616c4986742c52a99d2f64758773b031cff7b2a40d1659f21bc75dba2e499c2827180d386ca174af57aefe82ff9bc8d7bc268c79a6111a2
+TAG: 6945d3de62a30fc2e0d5a618ffdf1a1f6b6824f0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b13878b2d3d62a0a492dfa827e3553893fa9406f0d60138549913b4f73a50b85d1296b6a74f02b3e17f1eabcebaf52336990ea2130f2dcb955514fc8632
+TAG: 2547b8727c04a1edcd31a5c82118195ba769076e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b13d8a7b9be69ba0c268abf7c756dc640f9115aaaa01bb0a9d0843dec9b5f7dc6bd741a6ae8d2eab35cdda1825e7e6434a55219d212e59d081b27ca7c80
+TAG: acc633d14e72f44a0f0e5e294f64be3cbf3eb580
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b13b54363a0a3d90c90a085cf19cff7294b300e9736a06c29171b04a8f9b468b250191a518b2f0f29a50cf472bd2e3ba2374c6bfc7a67965b7b55c08ca2
+TAG: dcd2cb8dad937552cb882035e6ac94cf3bb1324c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b136d906d5a8b20d95d95342459fdd3ecb8a557969a5efca8494f3ade4a109888b273db2798eac812754a87e01c2236a6e4ce1faacb0243653c4fa25231
+TAG: 988c7a7b89a330ed8e845afcd74079faa9653fed
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b13bc466324406865edf8f2b36709e2bd969c65107a7f9f7b20162dbdcc78f473ff01e27e6d6d6fb93ff20cb0d0f239a5459d0bb35dd5f9545f2f62da44
+TAG: 60de94c03abb1074d8d9f91aea743337c9c35220
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b13ff602760d712a5d22694c5be296701caeed947ca5a56e1ec65688ad8db41ea06dd2aabd1cb73f9e1f4354baeedea2900b099a37bac75050bbb092f2c
+TAG: 00c3272a2550b08dfc46b2c7ab0fd2879433d69c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b13414ff3f17276ea15f2566b8575f6690701569deed74899ae5b0340a1d1c2a94f4556f361915699f7eace44fcd3a66466ab322e45b6c20edce85f0477
+TAG: 3ef65f38a7cf87f0b0580a6474a0158807f4dd96
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b13d6979ae1b5bf4b876ced1b8a18db01182b7681114282ce2abe4598a739a5b37c1c220c68c69704fe7cbd2cc5cb6891d55268fd19ca2decb67deca89f
+TAG: c6aed1e7146e8b471adcc54fa771fd0231ee4a24
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b1369cd340ea51927181dd670298745f2d4c66545886f510fea8780f042838dcb0de0ec02377247d81835210a416ecfd7f07fb9e0c2a67f11fb7c69f113
+TAG: d8c549476847173cb49b92afeb888ee971594d1f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b13c8f2ae94df0b279019be317b0a20277754ac6dbf4409a2a8b5e2f0a020287aeecd6ae760f0886dfc5bd6876b9a7f2ed97ec0352d46892a9cec32bcd5
+TAG: b67c7377f5ee8f47440955a14ed16c668d3ed470
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b13a8e8b78dac98bab202ee41ff1e5ec4b6405bf61698000fabf9ed14644705d55061abd6fd8543e3efd37262dcbd9f0d42aa6aa90671c14eaa7105b147
+TAG: ba0830de3b3a5105d1166b12174252525aaacc74
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b13e2f81713ad87af35a4e4fbc026122e0edbb9f4392d5c91d7b04fc6370cd7a7c3f6147591e8819622eb85dd701dee430de6958b12915288b17eec98e7
+TAG: d77d137946fd1db0e90dc3b444ab5ad06a68615c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cf372b278c5575d6a1e11ebfcf3a288b86afa8120d063393208f69efd64b876fbc6a4a27940e4d45f24336e04
+TAG: c215d684d411bc3636579bce0712fa045da26120
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515c68909d2c8b3c1ccff46a1c4cfd6ef43a03f7db5ed9972cf377ff571e3150e964b8caf28548a71c02aa6cf80a
+TAG: 9f8b0e73f45c2cffa8d1be939c20a625f65db447
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515c75ea67022038f52daa425ac1115b9387e96fb566c561c1a37cd1c7ca85de0df11e3bc1694e00ed341583faf5
+TAG: 2d309e9d9b92dccf17ef12711e6789aebb38b676
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cdba083beec828624c0a430977dfcf7ab15585b8bd361f1bb7f2a467c397f6dd854831be6c2c0dbe5f5ad97b3
+TAG: 41033200cf582cc4b913e7646f354aa2253bd90a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515c633c053a52fac4841f71f5d13ae145b42c62d5412545be8baddc77c0b7fc807cfa9b50295273370426541db4
+TAG: ffa967a8de6b78a60474e6b6d78f2befb9e74a54
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cf20fc55beb4b503cea984d72e4d1419ceb6b2e69a4923c64f470c9dd44c369407a0d7478ab3bf345b872ea7c
+TAG: 377ed14fa6ffda6004ba46fad4be12451b7c7b20
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515c16fad55a299ccbc3dbbff8419f2d488e75203f0af47300bd3fbd748af86ea87e396a3a2369db08a25b94033d
+TAG: c2b67faa4285063b4e4afdc8add092e9a9f2c91f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cfbc026a638bce89d8b1ce9d2bae084e66244c47dd58a65d8fd81279f203f7afee5eee0537bb3838114143862
+TAG: 628778fd2d7b3f1b95eb57ff080e1840dd086917
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cfb5467317f7ba4470858a12fd4a4fac36c2ab6d0c4b6037078e82887d94df8dcca100b7b58f9b46ad06ccd4d
+TAG: c94fba31c95182f847fe2b65f7d547dd4d14d7b3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515c796ae0cdf955d0542ad39e0e0e7ad55e092f3a06375893582530cfd9f218f1085f06c01bac415c7f5d3efb12
+TAG: 6c3ef5dc3b40adcd3718c20c21d89e67527498af
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515ce371d618872ce6dcceb7713f9dea6bed578c7a87ce9ca6a3dae9b3467e79c9a22b9754197df118eeb89cfc88
+TAG: ac4f85780fb259b60e7894088234515a75d76b95
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515c4f07c25cb1836e004b759488285f9e190f2e2abba558d3e5700d27106937cf42db9b1e68386a0e45bbc81c0e
+TAG: 90f6fd52e4a8946ee353f878d462bbea6399c699
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cf70e14d46a94688c8872d28b09096c43bf9f947c86471f7e9c621633ed80a3b018b32c06c2d6a598da505df5
+TAG: d9f7b44646076d9a745ae1b94fca8c72a5ec79f5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515c0352b473e6c5b65d375748200ac64270e01e0b1b2af99e356fd1653600245829c7f196ece7afc45c4cdfb287
+TAG: d206722726794eb71d936d4964129d60fb52e496
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515c1852066ab3d66883a846f2599c08e09281d8edb7ddf61a3a428d312349d22a9ab7b522ca90c9e8a47ba4ac3c
+TAG: 08f7d2cc2ec1e0b9aa9423281857891b427363f9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515c472d223ff7ac6453699de42c1363d2b7fb6c78240ac3713be7384ba8b188a9247a65f99c72c1623cb619b286
+TAG: 1ae629a7543e5fa5b493ff2bff11e6ec09e25b56
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92f07d4b82c55cd0dda3c9fac9dea496823bbd1e2342a27639a885843f
+TAG: 625ed73fd6ea8ea03a94a8d73cae06d9b9052c2a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db927ed98714d9640ef6386ed7f307b9d388c8cf956114b1e1d6de028724
+TAG: dfaa9c70b7ceec08d39de8a894e32401b7dcd048
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db924ed3364fe1109ec3b25dba3dbcf93914b130b137008a42d4693f8f1e
+TAG: ad953eda24e3c664e9a1884ec9db8899b1c98f69
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db920a4b8317329c4e337902ad86f9c54c9898d140bb805e2cb147f7d7c0
+TAG: aa2a44cd8b5a6a42033ad3a5ef7517d8b223aea7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db926bed3da3c1a89cd66b8a10833598fe5445ba243cd7479329e7bde29f
+TAG: 0368ef2411cf5c4d0e9864f37cda4f5ffd026303
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92024f8ebba092a54be441bc658604cada1d816655cec553adca419e3e
+TAG: c20b12c535ff7c73f8b6ae40f1969bbff02cf738
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92b167f85df5446515a40b2d3d820f3360c21b377a3879283783a3abf0
+TAG: c55eb045a36dc3c7fcfad77ca5290ed2e0bdff41
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db925076a7caf60445b8eebbf73ab2c611ebe88a31f558f5ffe45158a58b
+TAG: 23fdc118c364ddea3eaf051f52d4eec4e64c41d2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db923b2457f182d6ef467eddaaffce75ae081ff04d752e662f499fad72a4
+TAG: 1c9b7e22f5568a1f73bf0fffceeb96e989db6640
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92e514d139c9fd7b61fd5cbb4ad9f26874d6b1194e96f7f571dec62e41
+TAG: 1f8bee58d4581f2efdc7cf1fa6a886d62731b42d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92c18cdcb45866c1724821b16527465b9be46eb8beb4eb8d62853ccfce
+TAG: c82d1bcb8e8909b4627855090c69f893a7831513
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92b8ad58e0bbbd7e5597c465f7270d9af05ad36f5f76fd5061f08f34db
+TAG: e778b92bd5caaab5109c086deac8e15c0b868f18
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92a0f0195cd0f73b8f88946472773f155ae53b33034b6a2a0f108f5f1c
+TAG: 84d8f41a6c51864d3dea30c2d322628325c557cc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92a6eb0b880df4753ac6da5987e88a123a57226e9b090c7fc6220584d5
+TAG: bf51cec0b8c6177620f4c93dce042fc9bcdfee76
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92ab54fb95a50b74498b5db0b584755042ee981de9281a8d9f2be54941
+TAG: 63af479763cb00ba393684e22d1ef4add8995396
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db921221944be4f0ce28afbfb5848aab50fc23402f90cce4ee7fd28bbd9d
+TAG: a8144ac5e983802b585b7f9a5ca2d458dc6b9b75
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919fd629fbafb1d92f0aa82143a8
+TAG: 18dfecad0509f8cb1881bb6360ba07cd46e8e900
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919fa8d31d615cb4ae02981bd3ee
+TAG: a35e63847e014a27a140f8d1751b7e339ff79cff
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919fa192660b320e8f11ac1ce177
+TAG: 9bb0e77bb820a835aa92d385f13bb551fd3047c4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919fc6dc9120b4922ace3c191651
+TAG: d389df25088be5eb8a348b4c1beef169d65d43d3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f397e733836ffed7b66dc7f93
+TAG: af811ebee1c2ca697be9db97637bed1becceeb28
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919fdefc6f5ea938a77f81aa59da
+TAG: ae1791e3927a9d7688bb72bdac60a77e21ca68ff
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f48d68f55b982396148fbc91f
+TAG: 99c82ffdf60623654cb0f2517477a482609ee649
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f536734baf09c0695172b5f39
+TAG: fa03407b94a8380b92da027dd2599e48bba8d76c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f3b592a300d42d88eca46248a
+TAG: 058321a6005cd524144b314666680d055b251802
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f64a260576e70c596b4ad154d
+TAG: b9392bd3066e8851716b21d7eafa6958b53ed1bc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f5873f3356ad0ceb78f1988fb
+TAG: 7f5cc6e5e0cb8464766225aeb43f73825bc7abab
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f8074a8947beb206ebccd630e
+TAG: c3c63cc856aa7259849b4084123aee30cbc3f829
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919ffd81be722249485378cecdf9
+TAG: 19e540e70783ba69f9c0295dce0689d68c34afc1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f3927a690245b3f4e37cad5af
+TAG: 5457a28547d6bbb5ed1faef989e4cd2859e4004e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919fdf8aa5c4c253bbd5bd69d39d
+TAG: 65f9b90b46406184979599a283a392d1b7704b70
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919feeec7d7b95fa044f5305ef74
+TAG: 06ca47440e894022ea56b089ba8b660862a01232
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6edd634590c3af23946a2698491d94f4ee17
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6edd0b99008563c522f26a2cde729549e81e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6eddcdd8d754aaff441f1b291715c14957d7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6edd7d97517fde97e17c73f625597ce5edcd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6eddef4e9627da3d0ff6dea6c7a175b6caa6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6edd47b56afca50e38cbf2b57dcd59e29c3d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6eddd9e539461bc0ece73d86f57585193474
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6edda61b790380af1d0b28ed2b238c5fc9ef
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6edd39ede85453805deaa568276e05495ffb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6edd74a17c111ae8965eddbdaa103ab5e7f4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6eddf0a34a63a24b5874c16185afa9cf3b9e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6edd32adbc196416fc33299c7649949d57e9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6edda7fabbffe754ac1a0bd9a59bf9068280
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6edd06875c54d96f10b66ca38c25dd63dbe0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6edd854dd4a7c0795305078a9f408ee59690
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6edd6affbe256e0ee4c6446dd4748393b4b5
+NO_SEAL: 01
+FAILS: 01
+
 # DIGEST: f0f82752a691ef5866413f2b2e5c1d0ebb41ccc8
 KEY: 7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f58
 NONCE: 
diff --git a/src/crypto/cipher/test/aes_256_cbc_sha1_tls_tests.txt b/src/crypto/cipher/test/aes_256_cbc_sha1_tls_tests.txt
index 9cbeb39..5e2b18d 100644
--- a/src/crypto/cipher/test/aes_256_cbc_sha1_tls_tests.txt
+++ b/src/crypto/cipher/test/aes_256_cbc_sha1_tls_tests.txt
@@ -23,7 +23,7 @@
 IN: 936a91d0b5
 AD: d2c0267218cb7090c61713
 CT: d88861dcbb181ebd603365ed
-TAG: 262b8f2f50b02faefb172ea4c7478e6f7477abf5
+TAG: 262b8f2f9292c597b813c031f09b7a7144e557dd
 NO_SEAL: 01
 FAILS: 01
 
@@ -38,6 +38,2588 @@
 NO_SEAL: 01
 FAILS: 01
 
+# Test with maximal padding.
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6edd0dfb4867802d6992ce25efd8fe0dd0cb
+NO_SEAL: 01
+
+# Test if the unpadded input is too short for a MAC, but not publicly so.
+# DIGEST: f0f82752a691ef5866413f2b2e5c1d0ebb41ccc8
+KEY: 7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9
+NONCE: ba2fd6773e0d0c302a5f47e037446f58
+IN: 
+AD: 936a91d0b5d2c0267218cb
+CT: 49947d4111e2880431519d4eec862e01643017ee6ef66b6a13061d1098bfdfec397f13b9909128ab6199382f4fff85b6c67ff7ec8914dbe3ec72ef7265a11436e0536715bc446d514a6d79e21073f3308fd350650ab11a3b31f8b9fcd97e3bb57c9652d661167571417095ef938c82d7b5ec85d99e7cd579aaac8b13fd2f3cf42a1041df75d5108f3207e481e631b43121ad62e0baa5730333a3eaf05e736f61b68a7f6989990c06a05fd1d7bf553cf057caabe1f87a55a64fccaf2b2492c03acf077b017d0c9a383d9bf9544ac508a5ea683045ab08991a702cd5149c94923d7d1b5c93ab8ec965a4ff995d
+TAG: 13c793be2c114d497df5e65ad3a77e6e5f637ec5
+NO_SEAL: 01
+FAILS: 01
+
+# Test that each byte of incorrect padding is noticed.
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2376eeb9a7e692756e4db7e851b919f73133cfe5e1460fc1a8139978d37bc825f760428eb82978ee0f8a2fe8c7a0e1484ff83eab47a04eeceadbc061281baeff699d376d35a65b51d9f08d3c89b1640e78353d2b903e520b2dfbfa6dca4e789fc3432a678d84b0ed6c4d4db42c2840526e73eedb7f37bed9321afb88fe0c80c7d9d6a612e3b1e8d197af5c067e9749f07f329a14108cc285aa2221d33fd21d0aa0a1f9d135bf65147452a65f98158f180e9247f09453bb15ddb0feabe498acfa4c98c7ce197f929456594cbd2199a268998c846921eb5c5b4b10f74558204dc7330b1d3d06a0d21fdb1e38d27
+TAG: 3f8adcac196132811986ca577503420ee3ac141a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae214f5e3f4806bc1242583ade88f5547a46f5a0c3b49a6c4259bf02de4ae4528b40459fb12e815f8d56b75f60f2ad546cec10977556db9b1ad12b0d1a2b4c93a2c3508c6e20ee20cd84943af89fe5ae6232d1e927aeae422e14382d41eaeb6edd1b44f6eabf3b4d91210b405723e6296a7cfa013574cc5ceb9f047e528b98e3d9b6fb90366a778ef69ea1ba215cd1f144a9c269663209774e74c6bd43159ff11ed53b8e20f998508a9586e11b5d0661f9f3f2349132eecc9762e1c3667b16f178701b1e9e8d0bae95fbbac4b86bf8ca93cb610e7d47cd7243921b26dd1cb42c850b0193eb4e2eb6fa4c22a41e3
+TAG: 3759d040baf047a7585c26db9c098eae69f6f424
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2a91ff92427eed66c0a5eb6b2c01ace3cd408d93e0fd7749110477c2d1221ba303d8055123c57b24f0ee0f9a68d581da88953c37fb66f7f6d6bef0482566fe0c2309e4bf1204b907d6b5492d33e762a39fc2b19400f2b5d9e02af076026adb6d76885a07dc8caedc9a59e452b30b5d8b3ad745c27cdba3564982efe738f611d55053da28772417d8fd173e3da9e87eeb2f9eb8476b77456323e2dacc2142e13f1b0c09d97c67fe1ca90178fbed6f6fdbb1c6de9dec4079594d1a2efa1d5b2cb9e76da6cb75c1acd991d94c9308f24863afbf077cfd0fb997bf20c3b9584470d9f5a7fb52e96f3ac3895887144
+TAG: 1b120a56cf834446cb531404a041abf80b088448
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae28b1064ca19a9f583ba483aea3b29aea24f45cb20128ac8d2df8b7ca7dfe13821cb8c48e22aa1d555674e3ce9958cb1b4eb1b5564bb7d468cf155c1603557cd49c27d0d280b3f118ddcc5bffb775819b9a58e13c10da0b8c41e9aaf668167afc4e0f7480c313f0a9fd79b0522e9584e6084570c84f874e4ada88f051a80301099b29ea1793f2824acfcd42da0126b489f2da94daab9f303e5891cbda6356530b870fad3ab5b4b2c5bf0278ba829516af4a86829921281d5e51a5268533933750e2ab4b4270322ea2603034b187bb5de76d5d10ed269722144f944b6a990652ac29aaf52bb66c70b8747744bb8
+TAG: c6eb53e39d97c19fe5fb6f2da1f4320c439db1ed
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2c8cdc4a9d292616e92b4f348dbc0107f46720b8c31a186736c19a9d24c5f4d756bd001b2e61519eaecc1a2840aa5029d0a8ed36e08c0bcdddae378b49d965ccec9614bb02f97aeba637ab1a1c242cea7b9dc11a8957c4d2f48c934aacbe7443e3a9906bda33a1d9b6b830b6f58f5c6b180394b34da96f7fbfb780e1b2953570cf9c41b933f7a005e596891e69b736750149e61f39c744a69cf3de10919da7b6f4e04be0f8040636720a18f56cca83752d38d4a803eb1576e64ad8578ca022153b179714c42c213b78d77783327b650138928bca8ae60bccdd3b574c9d845c51faaf9cfb6057cc5cb9800c935
+TAG: 94471cb05c53252a6a3bfbd0d36f4417a993c640
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae21e5bfe40e2e6987661962d60bab52438a003fe0128d4c9fe2d787c3dde5451217b54ead7329eb06a0b6e953df8aed54322ef3aed9a1af4d995ca710f2119ef832e97705a82101a70aae63356c117df27ddb64fcd38581ef1b19360d0e3cc7316cb7c427ed0aa7af31416e1ff78570729eeb4535301b664d51c4e958b03ab2ad27e2999d0777f231b9908ba0a659a6cea7241971c7e1a2401c4814fb6d2c639092fe87cd492e30ba4d27bd2086bd7a8514b8796c6ce214ba0723f5994551f6008e1c7853568bc424512f3bca811f979c0d8c03b8ae38321a7b4e15b43b2391fe2c9160eadfe43e12a73c4cb9b
+TAG: ce5fe34546c31b71815b59f9175d937cc3fb49a8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2fbbc80805613c1d3130394c50781c841c3895cbe90d3b1436206cd46fa61bd4065b813de24338040f836e86108d042d304809f421a1ebe1ac4d1d14530fbdad1b28eabcabcc528c68846ab80c3cc7126346c7cbfe912c91dc21f47d3bd615a93bf7a94b76c705e68a0eb1ac428f0c33913529fed50cbed95d09781ef0a74158c5750a8a37cdd81dcddd66a58548636f4be8f06403655f2426e5770cc2d47662078d9b40a248df20db4daff789eaf58200d038c36f471e6875e4ad008dbe928a034ab4452fe2ff4e08d5b1e77e02e98c6620410c323a043317df9df806d16fb15f57dbd2b4dcef7fa46e3893c
+TAG: 4c2874ad3e03802f6c523247a588ba56ead49c55
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2bac2df31ecf9c3304318bd366d09f27d363e586dbb6e229dd5978d7978927fb6d3409efcd9906e6d6ba6d1b334820ce7e108d92f14a3776ef5b5a34e951d691f8709aacee46c852ad315afa7d30536623b750f4cbd278974da67004582f48e75bc943e76a09cb6869fbcad40b7a00ccb584349c5736b2047adbcfd13e31f8313660239aca3855fa658f6731ef37384e7517f3d38f1a48b9cc6bd698a27e8c71841b35ecbc45b8852cabcae8871a949726df96c0c3d2d13080972be12581e6cdcac172c7d46050e94965e662ed2ba9836a652fdbb116e2d0fff659b33a1003ee1f6337f4e4f31d7ef14ddd5b6
+TAG: cf6f2f81317bb2f4e37252ccd7786559e614f2b2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2cfe7d97bb82dd71abb553ba81854a2d274e4c028d0415ea635350d0dcd0f1e780435bc604d3b51995e27eb4062a2cec754d75302199021283979f5acc427fe753f3638553cadd4069127b2f3ca3009d46130cd095e9366dbbe455104f606b0566bd3b9e019edaecea4953700edcd88eefb7fdaa399eb87c6233b2e909579576da612a7ba2117b4436aef66a013046c8ec674ce8d136e48e1cf358d30a595445b946658b3ba41b05c669337e5ed06b2ed799c6760d24c3c59fb29a67e04244113e4617359957b53ae6cf4ec6a7a2867d87f03497a7baa9a11a5e1e2ac926843ffef8a8b146934089ac090252b
+TAG: 7d136e2ce3f533b8b42fdb44ccff4fb0f92c92a6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae29682687730a499a61db7ce9c741cde420cb7de33ac6fc67b8221368dd6b897d622423c083e7c7f9d0d34b8b67681186a14125f4a6254ff565f4fee00b9c64d6262ac8629ad8f4c47def6dfab3bf3fb2975652043afabd50aca77a62e48bf846f873a21539f616c80ace059f7aff1cee676a923bda797c9857ad419fb328a86583a2d787b00c263ce7e0908e0d9e2d7beaef8a665d0db8fc1eff43fd2a1428769335abead876304953627e12d21b53b85e7d26a622deec5e3240431d26e67c86fd992daadfcda046d57eb22e45eb11e050d6b804fba6c9ae6d061d47ae5aa4cb6789001838f9b22169ba807ec
+TAG: d5a84c6f80ae4a4df5907960f884594e8543f7dd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2b6e682a778dbfd9e22473c054d1f68ed3405ea5b855700af6359afcb9ca837a43d476de2915b8ac46f1fcc277cfcf1a727da061075ec8ab91f632b308019cf2fecec2378e84244f94753a957fd82c7780908256d4228b1bf8cef9cadadb539b953e1bb5c38bf3d7ad376985ea97ae61e45daeba548748dd1dc9a534f694cbd5098c168527f0fc7e108cadf8646eb01bd32114f8e1d9745d2b8b8070e075e2ad9d40840c57357b3054e9f6dd11ed35c4af4acf29e27e48b9c7747fcd622bafa7a9c43cc68db0a5c10c0400f612a6d80e0afd6c3e5077f7d4693944a93e705f7122379949f53761a9d785ce11d
+TAG: da57b697de5f69f896326dc2bef69f9de997f8b6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae27fd12bb6478344295e2e0196dd3f9b879086cf10d1abcc01dd7e5566a732248cff96cbabc8742801b1ecba1835b05d75e50294dd3b188324bd6cbb6e6470f7218b04afdd16fd82fc3df0279345c6249aabe62e3c30df33f927360a03e73a730cffdcbfa3670552fc6f93183899aa8d5065ba35cc390191d949d9f0f666c4588234f98e5c5d6b66da8717f501875eaeb08d8478fe6e09bc25a50be2ff2c774897b806e5293426aa81caa3740b75845d75dbbf21fb29e820cb53b6aa314e313c49901c0e93304569a1f9e5aa65a6419f9ae465193fd38abe0ddb80e89491e071b27fce54c76455357edab72d8b
+TAG: c4fbd3e2149482e72d2ddd6994be15d6f721c4d0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae28401792e4c2cfb8e4da9edabd685d2852fbefe3bb93f4b3db81abac0e245d40504afb7a84349d8003ecb3814e51fb254cc26827559db0f10738de25f74d05589deb56e15fb04cdef397dcbc6feba871cd5d6291f8d1e51f7b997f44b782e568badca0459cdc947c68e1b062430dd9a7f15728d7183d023505623694fab003f94fb928d9bbe8054a5681d932612b6b1658ce9627ee9293e4001724f609f30c8e56ff009240c2c540ae0846975b47c7de127ed47bc9e53be7b01824f98eca2cc5f8e87f3282446d01e9cf3534dc0d7f44b69f5644dc08365f5cc80cb5c3f8c6d859ec00b5a4192e12dc1e593d1
+TAG: b7c51eee6ce39172068f86ea8d566c49086e793a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae236ffdbfc1d0bf54bb3e0d435d7b5e683f4fe2f03c754ea8c71bbca6f992f63a671d0e54ea51168faa810cc079a20b30492cf93178a053811099876249590b22a7c8b475beee956d95a63ef9f61f670f813e63315bce63a525bdc886bb6aaf782313aa5c8086f1f245edf750b52749b913ccb0951e86257df5b54ef9d259f1caac8c9225c65473211d906a6931226e4c68d794067e5f0ae3e8e1202582d45e18e51ff85fbc955507f2d238d9b7a121a468c0166cb862aece6ce84907bd49412a92abc6b8904814f15f6b353dd0c0545a14c8c7b768bdd891be676b16c9263363eb096b49c0395483f9c3c3744
+TAG: df2b42339ac151efa615be74c0ec74ae559a1772
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2834e1e14f5d7b4a7276bfb4532523af1242288e7015e3ff00e38681a37df89b470da6a3385840e9336187bc02b7b9794400f7fe6a97b3b18eeca67027dbe1c8fde3d34fa6847d6f67b8e76100b7cf7cfffaccf90e44a3bd96607f08c7a31f172b7262ed7459a15a14fc010e277b9ab2c524c169af761acd2dd0ffff4b5c0f52f71e3f6ab485f612e6f68b2f809e0dd46b620dafd51d34e198540dc35fbc83ff746c03f138478cdec00f3e824959d4840665da8b3912f047e3debeba8f4dd60564fbc9c898223d19f27330a1799de5dca2abfb8ed1e799ff5cad571ddff16b58c83dc92a84504499666a5b4f2
+TAG: 56d377bdd1262bc50ea538d295f5afd99e73cd54
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae25b782c3dead0a771825c9e3ad7cbd6f3482922b065aa32015af98a2cfc1a06419988be03b298321c571eb7d56d909abd0a4a502dc229564beabe5571824239ab29c1e5b5b93eb53527a07a33fcda134c80c6faf590b7b13ee32ff055fa1aaf4d7b9dea4961a71ef11e47f393a4f34bdf32ceda7be8e88a907f4dd0ec2a043d0bfa38e60b9afeee8d9cd7b9d52bfa5e5d5df348855da608cbe6ee13990569701d7232ec2713a6281accbe2f9ce7dc0af2493ed3398dfda1eea0b221bd1bf8bc0a77350524ec0b9e37002a6a40b04d04a4cadb1f425a145b16aa2c201115dcb8bf74d3ba19dcebe6c84fdaa415
+TAG: 6b66eb9e74936880aa9ab1bfd5363dacd4b10b56
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908bdda0ed3efade2cd8be68fa064c9d465d0be925be6f8f9193ceb80db80354448e7c0029a68bdb91a33bc862e9750bf942b4dfd3f1532773e5c754e1046f81227b91f4cf0d707ef8fbfdcbbf1024e433f8c7b3a1b93012cb4cec8ce9a2f2014d035c858e27c776388500a67ec0bc5b82707ba64525f713efa9268418f508e65a3ef15cbbb377b6519b8dda6fa3fd6ae8a69f6f5d7e772be51fa650acb1d3dd2642dbd3854b1ab6dc611a3a2ad2446bef02842b843cf6248941d619a44cc10955848ded132400eca6a5bc0db7a316345f068ea051bda750523c288ee2b1
+TAG: e75ba0f6eb95a117696e9481eed36672fdc0e0e1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908b58088a040452d08093c6ccfea1f78c98be15bbeb3114d64ced884097bf0af26ab01c622ad7e9ad0bca71f992fce5e8246f0edb546dfeb83540ff0fa84f64c96c4ff65d7b732d896f7815b712d1954549fc05ec7b3cb7dbfb592205fab2d35df981fb2353ad5dc843e9263df5b607a6f58f45b6ab91ba4ebe50ca50b636bd43cb5189ac4f1e6e840d152169b8c4e22d31f36ed392bdd4ec5ac739adb584d12a140f4035863a0beaf41682959124d6a7b29d0a0280e88bc633f0c51aa82c15407e9e2a896c090c9ba62631a377f3c7c3450cc074764fbdbc8b57109035
+TAG: d57f29c8a43584218a5a87e6af3fce2bc4137024
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908b55b7a3e62365ca8e57c4b8fe8256a214632a24ac63cb4cb6d98c7ee6eaee5768ea4f24aa460912da168c25f7be031260a86c26396b4183352964bbc2cb285cd7e39278ec3bb9ab4da8ef8aab01f147656d875c4feb4e8059740b683d8340389286b5fdcb3a584d7fa363ade2dc5da7939547ccdc4f47879f2db940503b6c9ccf7c9b83ab25c67725d0f5d39c3d9dc335737cd55f77faaab9419090f5ace169d49cc1f1898bbc41b1c0d32e48760c9b89c8d775f95421715d922a8e6a8893ba763384f99a56d67be9b18c3638bff368b3d68c3a2a45e648e61a29ef1b
+TAG: ad0905ba94202f95769c526e4fad346e88ec795d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908b41d61629348d2aa49cd8391d114ff7795d591c7ed7d9505ea5a8a7991f1f92451acdef0ec6d5dccc98b9bd6b6456aa02ae57d2cbca60d76212a01c6ff854ee527e9ee78415b0d35f711f684fa5153f3ee4cf955150e9b0ab1f4076d3cf6b82e554950df41d6f731a242ca56bfe0a9034240d59d04b1428a5a69fea811af6706f586581f7959c0c709ad2734ad06e180ab20e1a3847ce01ec57ac4cc9d4c7a75f0b949cd5dbdeb18318652accad0bd9454065ea2e8f79000f803367f13d018765de45c5846611d2cc09e674a3d0fd63c7aa416cddf8083e744927b5e2
+TAG: e7c52ad607da437185dbcfcf0f0c9ea3f3a1071f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908b544360f3ffc9df7a6599bb35b4ff64ff5f5df3b00cb6062cc19afec69f3bdb3b784d8a5ca0ab88140fdf85d7c04f2aa732a13b11de5d6465450b571508248d266bec8772fd803cdd296cc3d41ae38aeb7f99d217c22564328c3cb74a2ecae1e265007ec83cda14f9e1a4b6c826db6c912445409894539a3d7095e89f19abad7ce1905f2f596884ee3fde007387f11ddae355630659e3bb010741ce8ba46f199416c232d3424a5ad74da60ac0d68b81ffc56bc45a48ee012e521978da52babcb6ea3419588510b110671a1e27b0496f7853fc0e37034128bf8cc62d6c
+TAG: 8ccd8535bae032aace63f4b2ededdead6d8f6542
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908b162626ee434491179df0f29cf80927058ea50e413d5d8e7f757713a0cf82178cc65c73e7870052bd183cbd92b0eb2a3b339f6264e63d42f24619778c171f752529ac16066e5060e25e7002684c8334e460cd3d9d18bc7a39fe14e90c5097c0147783bab95bb467a9987bced2579a941298583bad15c523e7eb086ecbc18e16eac9c5a05905b4ba8265b6ff6208e6fde68951baef2ccf8c0ad11de70a2a7a750b8b0002f737b3fe4f3ca5cb88a8771429fc4886685c512b764310e289b511146d01bbd1ff75c2f720de4e3357b5d00a4c886613dc086c9df1badc42b4
+TAG: cd6f73b262113604c8943c2c9368829f1d85bd2a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba273b7b4ebaf6ab6b1b5c8ef7a4b7c71ad88ed90ca899d7374de22598b990d0ea6035c8984c289426b9f603239894db794647764d922d3edabff23392866c91af2c9c61314a3ee419cb403287fd7ef2d81296f518ca6b06d2474c0f52cd437bb3b151abe4f5d2027c9cc3f8b55c7177a276e0793a64f3a7f6c42a04825abf4107c576e3b08859e48d757590cec7c325f8a64844b18bd635d36ed0c5894f880ccdb32614578092fcf6e1918e139547d275596176f4b8146977ca91782dd9acd08ad3549ece5b62baba56f5c73c8624541c1e1d236ec90d76026726814
+TAG: a15ca2c337c1b0d2490c41b8b8f3f50353543d29
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908bb08b0403802799606740cf759577c15c076099dc5d5869257b6791c177d0fdfdb4be36e615b986e25fb3f45ea71c409ca8f4d2701e1fa0fb7eea2f069ff3b8ee16597cfca23fbd25c713a48c9adb5b7c72f1f3f3be636aabfac61b585e3fe5694fbbe67c0d0f545b76a347ceed7692016519dc9df0b372bce3718af300b66eac760dbb8779228126d51286a04e5c50346715a0248a1425630b7e6f860412460f5b641a9012ce763c20c238eb4827e01d9c24f82be3e4ff6f9bd1b04d5d629f0d727ef1146c9d154e91e237e702b9de05b51dfb010c4a9eafa0b453ee
+TAG: 280d6e9e3d11102a6aed51fbffa7e5bfd2c6de90
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908b3fb17c538f0b1939f372a8f068a36d6934193e0232eb7ba4539e7920577805c074456d2bc9433f5a03a0b8dfddbe74db0112f775e5f0a8f0c432fa43d4e75632c1d1f043364aba6766d4b1c282f8bc1e6d50bceb9837b016274d0a9d8b44e7417d431224f0e889e752cb8cfd4a37ca25a02e177d1eb28132e83de078f825d702c0b599cee8360a77b1de37fc2355fc7ef7d4488f257b5121b3d2edc5343223efafdf8d2f674a7959744f6ea8fa15697e18a1d3964c8a72001302a05d0467fa3c18e260730866abd69262d5ff174bafee8e9ba258939273ac37c09f50
+TAG: 61bbb1730ceadc81d6feb4cff405b773d08f0475
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908b4ca1455044996445827ee2cd283d5d914f44cab359a7724f5359649e1664b294b749be48994a5daafe7cfc5d447232b3f9925d78929347bb845bb44dcf08e2d770fa88583a4447d26efb0755e5c0e89e2d09f3ecf915ad67f824cd3404eccf7e524136e39d6ff926c6d8f92ec417eb6b47acafb6c82289bd799fcec80260e4d83588cf7cd60431543993e28c61cd737f8c6326fabf88afaa68cb5d1f8ae5195b3134685f14603945ad44d5b66f5ed8355b769f136f246430cf66b99998771c0784549204ef64880c1a5108a06e7064b9b0183c8475f3ed6e93f841f2
+TAG: 0eb3c29c503c5c4363d5196b1ac88d3f35bb66c7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908b652e6ebf3b4068d2db241a11d81b6f8a91112cdcb2a203aba9f10f0b672c2797bb6a9dcdea19108ee48dcdb16222a95e728f62c7305344b7b56ec4c3f5645c63f30147ea591585958aeefcd9380a15f0738b89fd8715965cd1918d92f7c63e5425755e65c612ea1c7cf3a8dde7e80f4de506a85f3977e51a3bcbd42c97888604bd6d9b06e3e811c0b2d41ff1a8e7668630501a8e4991967ca84df2bc2adf3ce4f4288f0dfb04af64d9c2f6b8ceabdc5bf63d830e1200a673dcd0df8f42280e474e2c3b0cd51403adfa933d3b82de069ca137738072698fd33b07f370
+TAG: 9cd376a19156d9327bf32b8fd33adfeb314a067d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908b8fe0a91616969bda3ff244ae2c65236e812a1975188045b38a773cbc7a97f9b325925b58035630aa27995c01035fb6cdb58c195b215c03e84565825addcd3d2088005414c8ed8976f098e93bc38f77f99700adc078e766e45917320dcc80e07e8f9ebe995eb050bf534931ef890ae267987a7b4e98189fd9dfbb930a10d68725b434b1dadf11ae1d63028030d959685ff3b7ba626ee5a777de512a52f5c27d088decdd0c59126b7d27cf8de027e55be09341d1e4f1d61bd70c002fbee263c15cdf474bad7e895579c1cebd390bed6503d255db319ee8fedbe91c68bf
+TAG: eab5048ee71e29b6e241cab09dec2e4d1dbd5b53
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908b40213907c9509101861f7104d05db96685b0294894bf5f790365ac0e8b9615473707fe8cd650c41e9fe65e699fcc339a34bc80e929049c7bda2f2c807fd009f77ce52091249b5f56021a6252e280616b17785134d5b9e33e5b87055053fb7c8f78af6da9525d70f6fa9a9109dd70672e93d936d704121b000d515b86086d6bdc91968c7bf1127c6246d6dc1c5f04fa54f25592ae2a85cd127161ce9ca8280a20dbc3bc663a7175260a5dbbb8abb1e0dd364fed9908d9814ac873bf31ccd2df07f0617960726e4d6b03038949f884033ecee0eeec45576810c898c00e
+TAG: 1298872d988f88b60b0ac57920ead5bafc6a18b1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908bddee9d55387a8ec31a62a5570d7f63c779a231c95c41ff83ac20f42b8849c213aa3842b4268d5854e0c67385f2f8b1a71852f2959e13447bbea6959ae4c3a79d444deaa49907f2471859ceff27c9dcad67bd8ac592daf0f1208105fff320a3f2f8fcedadb98be384abc511f863950a50df5aa21728a461f940ae1b56a04ec54c2923cd99b122893d990f6257c239ccf5306c3bae1dfe79b0363cd90325ba61f981b13b391a44e61c7433db7b213863abdefdf394e0cfe46adcce53778608ad5387e0cd0f160dd5f9dcaff76ebf7d09f5945fa7e0bb9f1138d372c4dd
+TAG: d855a1877167dfccd47c86f05a4299b1c456ebb0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908b601548db018b39932fe0c5542c0c7901e1e6488bb626733ca99977ae7065f8aa77d90f337c795b591379b6ba9f3fbd4445c61c618a4c57e882275a53c0d2c718990a274436030fc592abd371de87e3a874490278e342f7e0d8e4f06d972908e791fa5da721b7a333da9a8753322a2f3e8791da5df179b6f351d2c7838921dd99f4863e9cfd29ad34286585a5c6690dff9b5120f787e331c673ba5e1806efe7105ec0ee8548d174d44b887e6cf55cfee47430c7df5e826848f6d7a6d97be14f85f3a1a9b55343c67f1eb729a3c6a2aededdc8561910435a70aba319b4
+TAG: 448d8be45378a56fecebab94422a9ff93bfe7995
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908bc1dd9236ca2124a932de57e29127af97451acec6169ed25d9cb9830dae9e87c24c8d8dc0c50c9bb9f1a4befccbe749710c2fbe6126fb882277fbf455d3d0f8c21288381a4ad987fcf2b32af8f10d561a17e9b0279497b86c65f8ba87a04b8392b7e724dd5e564b34356718fe2c23b997025010446fc57837257e47e71f5f8017c87a22381044574049fc6954c26761fcbf6c9acece47d067bd2d9101731b74c14c98fb249932ba2e53a969a29e13ecc734b62d84fe438eaf7c6bf3ffbc20f75784cc28b5289a5c5c958ae3e88cb12d9fbbe1bf29e9aadac29b76c0f9
+TAG: 7278488866a225aaa5243b543d43ad711f99b245
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fd406040842d68fc0c495ab7dfb5fdd23af72b7282a0edf30eb910bf8faf39f4968c17b0bc9d31d5d42a7f990a1dba17bc7231c8c46ad69290ff89e33de136164c7003e7dd70d830a9bf02387e1aaef4a5462e7441f7a61e487dc249db320282266bd2ed016b478908852e99c9118446d7eb7f1172ec6c17ca9021959eb6c1fde96d4830dcac2c9c49a671af161ad08dd674d8e02ee700b95d0164180705231dad2de7661dde9e18019e6672e73f173eedd460b9d1713f2c510b8134147d78b7786ceb36930a22d693001542f
+TAG: 093bfc686715eca8102e719dc1691e0371625d4f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85f75ca0a51fddcd731d9163a3a981dfce2f6fda727b63346d2b30827cb1e229e8a6f9fe245440bf5780cdcfc2372835cefd6cbc5e27e1deb63ddd0915d391596deb420a1c9239cf9bd3a31c3b0c1551c0ba6de530a6cdd1fd46f52a4ac19a334dded1066effd8cac3f53a872b9683b0d969f4b7983a68a88afec553a9e519ebd9b9d5f8969c671b8b2ebc0f1460a872b79ce03aaa6bf7d0a99f6ea178a9c0b6886c40d11abf099c2a2a6ddce061056cd30f79a21ec33620b9b2aa0eb040470340334b9e051c244254ba2e7f8dc
+TAG: ab31cc400eff38fcce5bafd0092a0a7b32f2e392
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85f8544b66c7878756661d9b6381f96082c976c672e765d6157300c0fd8d357ee148fdfafe00e6bd036e2f756dcea25d2e7030d060ed3b7b224e2df185870368fcce9c9604f0096c5b66176bca49772b514f4132d9c49c96365e71879ab8ed9e9ce74d4a7d1dd49c5f6f17fe41f9071c9dd34a33a03b481065ec2077e09037260f6f33772813b58589e9ad43c4679eb3d8ad918b9c5fd50b6d05bde13c33b966a8f92cc36944964abe10c0b35944087241963ffa8ea43aafb6135adf2168eefc021493e0fcbb8f7e8d5ccb7162b
+TAG: f227d302d2b2b47c12c62fbcf555d3d60760081f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85f116407cbc9c597e1dc4644d7e099b048867a86ac620138b820067a47c7161d284ea6b615631bfa7879abe80fa563b7b94c9c72ed33526ff5f1176c96bf4c5b069504bd7fda0e69c82fbecd06ef72e2a1ea3cba93adc740b60e1924b5311d6435a85f5c586f6bc8fedd95b666375726826e23813db09a54f85520d5cefaa2885500fd240ac2fda13bb18dd83474da6eb30ca2623295af2cd25e4e9dbe8ff10dd3a075d1888721dfa63f954812657933e8a4756e4ff629e90b176393c8c9a21acd36da6649b585a2fc44394190
+TAG: 8056b2c744efb988570794759852408e4b60a331
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fe7546a47f7b9a2c460844876d9101491eeaf523c0191ed24625d01306473e42a16be35cebe7411c1e52e60ea60a87d446f5f82acdca796f3ebc875296ed1a8420af54ec2e71e3fbed445bd123b514627a9bd02681f7f44bfb94ab158e8771ae658065e68249ac25b42de7604c28300653e44f04739f5254939c63075da1fb5438cd661a4bdd4817b52f7e8abcbf7082286aafc1c25581d234aa86544c4142e6a6fcf1abc008aacd6dfb4827f546443341531fd77e5a8afb0436bb9bdada92c649828e338c190b78cf58542f5
+TAG: 5b0b473f1d535c31951da991fa1527f3bc4f4233
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85f3017672a38adf2c9e1de0b79bbc52cda1574c975e553051622c6fb55fd5fd1971a0f5692e84f51ba6c4620363a6e2b16f89fa19226f92577971e362a6e9f1bafdcb99d312ce1dbde9b0420f088cbed70dd789604a47eee083b2759e59f71b75afb77830f216cb9c980a914fbec3194c4dfe9dc70d8c5983f0162048a3a041633887abe5a3558b1dd839be71c601c1cef0e71fe56ca6dc7ea21c915251bf8a98ed334c2402c27c9aabe433f3371d734d4356349ca04fb293a42d0856027fe76c14919705380f9c46084bd121a
+TAG: d40060475e0f1a942d3cafaa75b6f17972207e7a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85f203f006169bd572630d73d77afee66a41bec9aae220bd441fc0aab435616039b97ad7dd260e4e3007e4e51389e2bda48d77d208e6b4c072c3199219ce602199033ca1582c1060a98298371e33165b37d592a2490d1aa242dc1e4dc057ee6932f5d300150a4b8540430fd3ebe577cfce8674348b0377d09f520d0a89ff35b545c2bf0e76a2921ad6432e54e9be82e827dd44616f6f4c7e80b0292bba609e671f6af5fe4db2d7894a6bfdbdda82daa2f3b0323a8acba96e5b1834e9559b54f0d45274e66aba21653f0ffddf80c
+TAG: 620b4f2c95c4f070605ca26a22311a9eb6b62956
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85f724f6ec7aaddafddd79c161e4d629ce49394ae9e2d01fb24ee9f458cc2b9c0824a516569db3c70f6873a5c486458fa5d86698d0746d353231a22584aac9e17068b9b80fa32d969d2942ec5bf4a0749c04a3cc3083bc456ed47a2781a014c66a0596be7674b47ceaee0a97cd11be6a413be6b2f3e349d374e4808f0d3f8247701973b5628132fa90e95ddda56348cf2e68ce078916b0d0708ceb835bd31854fe78059267967f7e92df97c911130bad47e6f9f5f49356e45f1970a0ad30d4d88bfffb3ef4910401d01815db691
+TAG: c23f62f868456d84b50a840e802317f33f59b7e4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85f51c12f0372491840f524b5a4af58972ea93e5c97abc6eeeee22cce1ac67f6ca4e876866484b433d9db77180e95d4e4ce6c32081608b779447afe52f9714a84bab2fda45191997853aaae722a5b9f9a46ba8459592eba8edaba37a802b6f4e6d66b09d17126b5dede846cf663951a1bc6d1d5aeec1f7c23a8527930f9766b370b48ea6159ccc540befdf070ace70381893727c24dce2986e65b80a8c0901350cd0c14676ccd7115e294845746c47cef8c11ee4a97cb3db70d2a9a3c29d88557036c5426f5696cbf15ba74ac11
+TAG: 0a8dece576a251b67a1beb2136dedf7028755403
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85f8c85da9521ad538af1e2483f9c8e45af8b157aef7e8b76e5e30c8fb4025cbc40491e08ecfb6196fcb87d16cf01e14fa70df521cb7e779e0cae005d3540d5204b75de499b2f925d572bbbcc79b46610692b321d539982c780994ce6f7ba3f618c0b2d7b47122c7e3c1d07312c56a82a99f5c9007d0766f2dd74154cecc9a63574df29fa718bf5c9168a012c5b31a314419b7770adb8b6bd33bfcb78b7500628f2d506dd0cf2425fe86328d7ff1cf8c8dbb17c367db726c69efe281fccf0f643e0bc29a1982ba224ac6fd27e7a
+TAG: 7e5051402436db0cfaeba334ee529d9aad818f1d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fa3ccb2cfe61b3de2dd99a3e74149b4b32352032311e545054a9a135c21fdf40cd4c5fff57769c729e3fe303300e5869e3a892ef7e90d5d876e6b7d7d1a92dbbb12fd33948d9ecf0aa3ef02fa2070661a8bb47da737650c3a98ce5867f3c29dc27ec944fe096dafc4a266dfc4f3749b82e1288aa283334608e7627cd57a2285f01311d3764012fe99da0a80984be868635c82267fd510006da0409727ebf272a552b5e33aeb1c005ed449dd30367c71e7b614ad25f7fd877c0ed8b4b53a1c1d7c2851ec1deca6a8d62c4513f0
+TAG: 631d1837132ade9212c483f33a25a1f7190f03ee
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85f710dbd6f2d2ae828a92ac5b1ecd6649fc8977b0b30c1c725831b32531c15ea3f46f3bd291ba5d4315c6fd7ca11ca7b1b865cced2c3026f2920f381c1da540beb35332286f1bc359b2145e7c53dcb8fa979ed74caf11dc59a5b5de8b00774aa722dc9e3d234a403972b165059df3a5953566738428ecfead7e0b2afba09bc00588cffcd5cfed0be2fec5c93900ab0902d787dd9e7d9e67ff9612404ae1250ea61c0951a97ce1b2fce95e350b8f6c82039abe15027bc1344c5cee5b1ecf22505fb99df4ba57606232034fbcae1
+TAG: b0865dbad1ffb0a378801d3970bac3031ebc881e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fdcdd8c9f331b19a3df732f39bf74ae5fd1f434bed853337036f34b8fbad3787ee1c02343a969a920924ba4cb67117ab2256eac17f521a9beb4fe9f69a25cc7f56723ed8dc30e702f2077a4a0c9e5f90d39956e26c2934d9e37d534dffb8823c23504a2f1197ae4f8466d910c775f1217288393e6754e2f46c7297b88ccdcd81b2e46b57960a3eec609b5fd9afac6e1aafa03dcd114130370c5848b1959a89d01280a275125c7d3344138f40f9c5b1870075785384ebec91a87191661d17fe0fe4e6cdf400d7386c1e8aa07e8
+TAG: 54fdf1d044f6870ba117e105dab1fc878865495c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85f6625e266b0d7f045eebecf9e5154388c2850f3dd0db95acb2f16b6c6e65dec0072adb93c01d77840e7d58abec92311cba811192cb2a8f11fefa48a07cd730a7a278d55b644257602d7ee84dafaf49b12232044d3e91f1cfc8125f845b2095076e7d8b6741904063fb88bab84a25f0a854815b8539d25a14a792cfe09e55045dbf572dc9d990af1b7bc2a2cab30a11e5dc97a270139f32db2a27299a09c80ce136684e679b7f005dea699045fe61ef4bec4b3d71e84c3e5924c2da66dda7a2bffe76f74651cc01b296993b4a8
+TAG: 169188a9cd427268da37e56c7b844a8d961705bf
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85f3f94cee2b11cde2c49d4e554ac8d2c4293b4436e94dd1a6cc0363a9c832f4b9c2784da178175e128ea55b4033cc5e15205c24d8a9b05bd83e57a7e7ba9b74ada52af368f3b7d13c5c804a16c542cde185057d76ef27e6c850babd0fad1f68df6c05f77da9c4da9f16def806162d3fecd5f45ff66bb291b3e58dc2b85622ecdb378ef8ad68263afae88b8ef45444e7a1ad429c1a89e0e8d9b9844d5a31951adb61bdb595006c145cf6e9d4bb64a34f24c6af700a3a897171ac18dbd64aebbf8a1262ceaeccde34b6b1415e000
+TAG: f9845e29aa89aca30bf231c903167e10d85b8fc1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85f2444b7675d8cb6ed146f384341bcee305a4d92b855480709898515eda0af419aa54dd5d3ca4293fac1c015a0e2f5ded35ca480ed1c4a8af925338c96fb8706f0a3162a032113279535e9f984630ece548ea11f0dc0dad95c74ef32ce613992658c432defb1c78b8ad1aa053f54fba1c1ca502b89a0ed8a918b2515895d4730279fa2b3a95be914bc69ea1bff3362d9260d097d5108bcd96d5908369c7ebfa35a70e9e089d1438079987917e6fa7861a85fae218576ba9ea394a7690d8767d449fa231372b24d3f1f8d79eaab
+TAG: 0cd06df42d74bc7da43c378b3fc30a1b8c833f8a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff43f78ad9cb9a3fdaed607dba0542030ef4a8cb83d1ea7c5b07639079b490f85c50ca395d55158ac14caf544fe491d54346b2d2aa3b0e91eafe6daaeb394d83083d9c105b90382845103d5200f3447eefa8e1857f6ca0dc7c094b88da8a81166dd56450629efefc1ae6677641a89a4a61b3682937f2f687588912f63171df37806d71b809ac6eafd3ab5eaf2e1690a34ac4fde84326609372ff76a27522f29c3f276943caec9fc01585cad558d17ab308fad9af077d217e3fd2e7223e08
+TAG: 0e499d45ed18c37891cf1e224870e435f4b9e559
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435e6769d97112e7dcbc4eb09aea12c5e4366ec60d6d146576a57da315893104f9bcbf10a7c956742deb3f8fceb678af9378fabce72c7b492cf208e9b0afc2128c268db04e96873825a388058fef0ba0facf5303e378ae604d621d85b84e5e3b97696b7b741a6ea8d1a17421f7f6f78be34f6afb50999324dec8f2dbd4690ce871b81b7a49ca3080f6ec51817510c7c99a7071b612cc35d8edf4304ac9304fc5e18e39e9c92989b38f0f4b00236b6ff89e588d304f8afa0eb4070e710f
+TAG: e510c3531de778ff276a58fc900c1c1672859b28
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff437bc218f396ad080a4b28cb9f02c743bdcf57444aedaedd4f69bc3fed4dd20990aafa708b11a0a5169fffb93adb4a516298b7a436e6954270cd4e6ca9ef518b9852c059a6967d0314c65f6ab239439a56798066a2d1bd7880fb21421d60feaaade2828ec5779aee80eb4abc169f1c57b1f0276d7779dcfdad88b3fa3b675353abc956e9798a8e885ad54eeb8aca7f40b9e04d02d1b92f9597b36e1ec820387708720bf6e212754cf78cd305e59c2696c740013ba1d4812751b7e0d07c
+TAG: 4f7322916882854655a4965db445e8bc3c6c81f8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435c0d68b917cd27d076b2cc44d4af7f135a88735cb78e1543c0ddbd0741b8600ed477c579c7de2d7af859c587b4107bf25beaaec4ebaa4c05c97650e7570b12917ab8139c09bf200c58bf46a72f93e1375758700eddf89672f14c1cc8eff719d2df56bca1fa9ea9ad4b0e37769f82b52afd690654a29df1bc7b0b9d7ac69b4e4ac970077d655311cd9f609fd9cc67c6834fda790a6bc6085eb076405c1cc49bdf2bcaf86b99dff245a310de597b4c88368b39b0d26794465675556d93
+TAG: f21c5cf657e5526e00dadae857e10455631ce154
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff43f2a6fba1bc471ea11fd2664a66859e41e7f343e1e8ff3a1ab889f5acf4e4b65a7b5ac645209303d0066c9542192cdbf016dc51501d2d761566d5b13e3f20a562f98e73c3551eb5272c5af8332400256dde72a007f419b60d7692f0f1ce6a57db5fbcf68901330ef45cd1d6593b2e79fba7cf18a194e721683e21bc2134b8710a6db943a3bd15deff2e6186f179b4ba384c11ed2e31573e9aa79e5887f4e7310f51e8ff564e23bb71b41d4fa52b0ddb6b64e298de24a71b30ea1004f2
+TAG: 8961fd22f9cfba057c3459b0d5f97050b99e400f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff437fc0a30dd7e2e7d9804895c74f6926c23dd4bae48f041d972b2bc3f14a0a48d01c498a7269b3fe3057b69f87d0bcee89f6be7a9aacbda6f5b719d577daf8bc85a6f1ecd869970ddb003cdf2ca456b1c8e18ef57ca01afc6c7fbc467971802f9deaf5bd2bd0d39c481f3f0bfec372a5bf21c46b0f617ad5f8f3ca6c9cf3a422b7c2c999438d81e125d2ef3d3be24df1ebd372a96ed8eb7cb08466f9085b8f375c5e6273e7133e395ba4da85f3087da399e6fa413d1d584792978b895c
+TAG: d1955ceb748b559a4d527bd1d22e5927564c4bd4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff431dff06e5e5b6e0ef865a57ea620a068dca14479629b38aa9fc5b7d66da01aac3f240f3bac99c4742ca4b0dadb2cf77cc98a40311f1f23acf965865d902b306793f2b9989737bee3e77b181a999d7124d9dc3ff9286e9729f57f1d4b47b246044b971c905a840c9388ec51b14c954be9643d9cc1e9f96916c0af2c7cdad9d4489c32732ee2ccd2c32d8141398839f98f12e6b01e942e820c5900984a751d2bf5109a3893fae9eb047bd05ad6afa73aeb29eb3e3aa658cf9d2c917b5c1
+TAG: 8a6453ba37252f16cf3cfccee633c19396c3b8c2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435bc5cde48f127a596a81c953d7bc75bda6163b223228e6779b6228a55094d530d509750cfa41c0d1e78e74ffccd20e0c6486714e1d22eccd9adf44e47afa509302a58d29710e579515234ed665804fa44cf43db6612af9f096889ffff009e6baf8176edacf343a405cfd19990511f2433a579185c8facdbaf8e137c84fb2b06d4352ee495945e464154419f819c22abfe5b75107b3701f0fb44a1df3007916101409e069cc276d4dbc5ebae0bd889e939057ed6e0bfb3942e5b70efc
+TAG: 83cf1619fa8a0041feb62f128198cc595280b84c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff438430df5627641646184dfad041c1647edcfd1bfcf7b253f19fbfdf4fa74fb1d038a111e985bdb9fa615e3a8e3fe0f70579c657961d9699265c27022c96870886e229ec0909befe895890b215ca1e03aa677ad04811667b037eafbe3bf04e4a106463a512a9759f73184550ca1bde7903d21cb7078828fddf2b0a17a4c7cc90f211c0a969fd3f22890faa3a7d6e36d80fcb96030fadd8f498c93c6cf9bdb861bf450fdc6c56bb1d874d4200900308a32c49ea9227e0427e17ae29d026
+TAG: 6b185d1caffb103e004219df3e98e60a1ade61b7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff4377bd2cbd08c16ff0dc7d92e3fd5bb870ffe7ad217644860035b42df8fa7befe2a166fd0ddb0894664777333ea03fceae19ec5b4a441a6b310401625175ffc5bddf7bf33dc8594ca657a140099e4ea80af61e13f0029590098043e47268d7fbe2b813630ce25c6736df32739679c7a09063e09cf3a94cf0112e8fbd74b707d557a6ac66a742ecbc647fadb4386ef23bb451603eb0bce09af2ce72e4e56e344fdd0660b977e00b054762922f8d7f0bdc18b126fbc4f7b8d6b24016d753
+TAG: 40afb5a1e66617b2d1fcd69bee17d176b7d45dd7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff43a6f9ab9bbcdfd379d1c8ca0bf95d522f6540abc98bde29944bf5f1857e3a8bb8ed03fd41ee933046ef4fbbfba539cc04a047ae5ef5aeace96b278f27cc8d4de117ea5313f3b20808d450623494d43566bfc684511f14a6b894e62baf8a12bfb2386bb0620774936de6e8171d3dfa3e4091dd106539f6b8194d60137d6c487f1e73f5a536b27a7057a482471758e7b76a69657a73b5e9a8814205f08aebcd9aedf49ad44996f9c9eb77b7906c7bd229dffcc5187253bf133898ebeecc
+TAG: bc4437b88e0426e85e16e1b16b813295974bdd05
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff4330cbf44d387685aeeef62292512befcfe3e7f863eca7598268e7f1f286949c9c8cdc62854874b65c22d1547e63ddbbe3b933c36cb4ca7547fe3a7c094e3dd9b38bd9ea26c195442327995485cbfcfdc3550d1e564452463de6d052f2e065366ef6f9f9a6ea9785467e57894eead8e4b1532a9aa2f93ebac75696892915e4242521a6b9af67effcdc2f63d9aa65daafed44dd7602dc0d2300c9f72df06ab8e4619fdcc601a0524e738bdc5d2e7498cfaa91accb713d900f99522d8af8
+TAG: 0b2c67f90d73b2ae2e69525018dd4aa6e081361c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff436ee6907726df23be8b7f54eceb08427491f40e3172f4b497179952f8cb7f6faf7a6fc0929dd0c490fa1efc550462eb32c518c5d772376e06281a38ca1d6981c250697397a85529c11ca443deda01a710d6b7da0599fbddc4ad6ab072bb416ed4bfc40a13ce320b1a9590712194bbe8860bd6a60cb02bde8f20495956e247dcde8005de28baddebb310df08a857328cc1899c31ff89585afe40e68d37f81a85d9637d07426b044ae2dd84dac88284deaeb85e2bc6792367287c76016d
+TAG: 4d48006c8d4f81497bb89a39f6215b7e5cef839d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff4398fde8fa65dde0608cb273fc848f7367b1923aead0d0b6a0b83589a704461d0cd5872581ed0226b3e568f49e874101b8fa202175e90419da8781cbb34d2a1a6106e5a99eb6458a5a00d03c0092ed1a7694780f5580f1d332dc0959e537f6fb1ad7c732c53715deb0a96969cb7ab167a81eeb08e44af8d1e6c215689e8c762743ec643f5684943d70050b56cd3cfdf05af9c3930e7ccf8bc981b11449f85fccb4c2747165cacc937a184e83911809563195c38e72752fd167459d801a
+TAG: 57b4c25de97942256a8fc22fac5a56e49fa4c088
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff43fa161b93f05a00120c5c530d5fa4f57e25027a5b1a28ff60ae7c36be8e0c6c7e8c7f1482ad1cf60d616106f2769c8e70957d42156866e941065d856820e0a49c5c700d33866f98e7847116609d4919f95ee9c0a437a182e1f998ef1ac8ba372eaebd90f98c061d51f664d0ddc0189af963f5c8662382a245e76d4120a214615c33472f71b797b4890784d02763e33cab7467b383e866fc840483a0da8f395bbaa8de5e6a19a18360e556501be8bf385c959b7f774a39f45cb97de6ba
+TAG: a8f983eef4c6a0c104f39448a84a0b0d6d4b046e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff43b3fa4ff10208d33a48b77ab95757d5a1d6c5c7a29a39b18d68ef0ff2f7fce32ce34b60ac28a34401b97370676e2a0a0b9953fe3e1fe305d6c457aee6e45c5bf631ec414c1c898bebc975190cec9dfa28adfcf8222b871dbd7217880e5cc0374941926a637c7c998543fa46d151e45bc8abcda82dc35116fbac166e6744529759fcb1d60668a5b17604d69a20c04c1a4da93ac378111121edd72f070ffad040ed2e49d9bd8bd3b5b46f3e39055e652b63e9fddc2e05ae5e3179ef4b00
+TAG: 18974e55d696edc6c60a3e276a35bf261f8ae5ba
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bb2f85bdde6f6c7018f78af42970cc3173095179a4c4c23c103ca96a304efa3ccc8a7b845e5c50afbc066493fd25e941571ebb428e90ac8afc56eb28208da2d79aa49ef30f8f45cf5872f82d5a37bdbee3a2dafdabaa2bb914351e15dbabb6cf611e3efadfd5eb9100890948656b1905e23524564a8619820e647a323d2e89666d70626d3edbbf9b9bec22368523c2af6e52048b1ee1ffafc69a76ba036fe84c16f20db6b541efb31d2c8a28ac
+TAG: 99567073ad9d8f802783b1051e8e57dabfc929b0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbb3a0c81a9a9925e51ab832e0e0b0de15c0014c3dfb822161f90d1b4e07cb0bdba0cd8f468a4d35630700350c29e8ad563fd58a53d6e8606e25cb656a5d5364c5cc0a664d35df46302f086d7f556a5a2f3f3a1bde0aa0d1ae1f0e9969dc3a30c2bf63917c5be9c4a99c87d50ec623d4c071ed28120cbb0909a10268536fb4407c9303fd441a9f160e537adbb6cf7b3ee83939080f40951ed99597e1e4c5a7e7be3e2df8d120d916246104aa22
+TAG: b8a0ba59810630c98445c8b564a874f97f5d05c7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbaf67984daeb4685a80ec20cc2a65e3a09121793c1948e87abc19983eb3a6bc2164951282d18c36a91fe94c621e939570b56f746936000b06dc7e0a2baefe681a783ebc2306078133e45ba3eeef4b46c5996c91c4a3cd2cc899ba6e2e4a26fa71f7d28deaac45872c10afe9b08e1f07af54020917e9cca003de6574ec3cd28263742474909ef76a920c98b9e7155e7d4beba3fd4d67b174c169af45364e77978cdedf3ad7eb7a45d33d5baad4
+TAG: 7be9ec37503c4a3eebb529072ae32f80508e34ef
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bb6708d3b84b8a164d49a50edda91d0f14fb5dc35f4c2bcde43b3f5998ae18874d9e3be39021bf8aa9e585a6d39241ae1e9cc6b155907b9db864510b1dcf54e20644245571cfe9942892406b5d561f83113f460fe0f5b3e9588b8d8180ab06f1526b647c4834e7d3e3e77f1b70f0f1b37ce2c0754d45a55e016ddcdc57aa46965f456879f33e87c40da41dca80402b854d5f7503e65ca7b0026d7d4a961d978336bb568facd5f9c0f4c44f0a3f
+TAG: daa9d94366fefdaff7a1317bb307bbc2330aae5a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bb07fe4cc26399f338d3fc71c39ca9a604b8169467742b8dcb15678823895912d9a8dd3bae22c05e25b89c2ac5829dda15c3d2eae46ec731d008300f53056c0945d9f617daee87a316f415d554c6457493957765a6781f9448a6b39612da9ae31ede6edea154eac609eba05b0c722ed97f51000d7c8a2bdac57e56c29cf23cf4a6d0f70c74f57b89baf22dff87024cf9ad24f36a44125efc879ea53113dca6642f1f8189865c45486c806229c9
+TAG: 23393049acffcf8b494d5addac22299abb0ccee1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbefe7049db190c4f2412cec4d062aa5f462a688d490d8c0bffe69a6d42b78a3dc61983e0a9f6515207698fe0b0574722acaf3584ee3839f5760462584e06232694f5f0f8ffef56852de0c3bcc0d00f7af617e4b8328cdf52d8d4d18433ada519abb19b21b9ff30400f94715f9722d503863cdf5722a858358f602d6f2dffa7a56e5b9f2d0fb390bf8463a0a88cdd312883633945b3abf69e515da305722aece5816c8662696425d14b1f49b06
+TAG: 0dc95daf80c1aa4518f089b4ba8797ddb18f7c8d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bb0cc2a4ad50f08d29dfc6d456903d47a0bbe1c5eb2ee236648916f2823136ebd8adffbd25a42ace379f5479c9a4933802d7d4e5a037ed1451b2da581872d9d7d9e7247c8dc07545b62e0a21e50a4f776cfd3bf40038516e0cb40bd1ff8a6e8d86875de14306cd39ddf70ff1d360c8dfff8ffbfebfdf1a8a6d0dfb6d155594e70e44bf02f7b4788add0582a736eb600a998885f382fd79b563ee3f0885a93665ba18fe866a119a84cfbb206b15
+TAG: ff821d268e6a779e8644b64250d53dea8c765ede
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bb635064840cc6fa8cd38353a33295ead5e88e832eb3a9ba3f0cdb8f1226d27652ac9e20d6e87418191fdeb30ba89f09a0c70ac32bf0764e0efaa23165b119fa8eec65c17ca229ac6e8eeecffb07f9ae16b05a46c209404cd8439514bd7124d3311930f5a93e7de8d9b5b6e7cf9543ce483f6e56acf669d9652f5868c63244fa5d10d45e5aafdfdf3ea0eb1f7e75ae1466c5fe8280d01036ab9fffda0934d2b7bbe37b198fa6a498df70863eee
+TAG: 6c7381268853f4220fd5c17c793c77cb7ad83fd4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bb5be7e7e9051bd40b6a39c100e46c1be96031bb8c46680cf3814af9bfc9d90c0750652a32ace567fbf76181353e05be45f21e37b48c02df852ba8fe567a762503762075342e7d1155fb7b6c147e00b5e428f28f9857f938c48d0ca0984508681d34a78efa67939bf400c9aa18c75c2981f789e5088160c5fa96ba13d469bb22281aeb24320dda6e5c3825bf002313ddce455f60ab93f0a7d345e428ddc5a68a676a206d93554c71f6d1414b08
+TAG: 461e4b638bfb4f50bc83a500ef04f5639f7ef783
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbb2a9187895d863fe2dc2cad0be64315c6a87959b1a8bc0d9a9cc8d6905ba4679c6412018dbf200f1b8d6c6a47742575115b52f91e66e7e4ba15b8b2db5b5c02694ce9653082362ef1c7a88c737169a53e7d414342a6dc7c83d38ba8610419678fad8e8adc90c8b34381bf13084cabb892171dde674625192d5a95ec25b40a0eb1b5a14e411c9b96282fdb864e677ebf0b8ab5eae17e834c0eb44fe10ad7f9a7258bc5f7fa9801299be2ea715
+TAG: ea944eeefe00cd70b6c306e0cd5a770951cf1f50
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bba5547a86ca47bf031a766795ed101e6c20961047102a148cf12c5b80e9901f11a4d6532f258f1db8b2b5b1d28bbdf77e55ca074a978f46492160db8ec1858ab98fc46ff72f6bad75d80995e60dfcc491e0f854733d2f646b2fce9ee9717fa637d8bfe5f2ce48390daf7f6d3c7bd9d6af9d39ddbd581a4a92695b4aa1796ef05d828b69a099808b7f8f252172618f2e9f9d5f29eef6e0fdc03015cdd5248a89c256f44290a103027f1bcbc571
+TAG: 930213701b438cbe3db1ec1f2e4f3960b39eab69
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bb876ea734db86daade668a201ca933d9983737e66c411d233bc72be47aea608ccc47810e182d0ec5344bb562bd82d71b9c7e8548be3a1ea9e788b1b33d6584527d63955c9aee94a5bc99f705d32b634cb541f48e4744200fcc012cc1ae8a4ea17b3ebbb0a72f618545fcf724206f0ab6889041b0c58e753ca1fee7462a251017097327de03932306a7bcb17682328484777a455977b7b6246fd7a7ccfb8168e97e80c2e43540c1fe5f8918455
+TAG: 1c5ef1d5e8be01f85616e926561e79bf7a5c5123
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd4decb069712aa625ea3822291f52d80baae631d18a035bb2fc9cce34f8ab963794d358fd97a1887ec0c86521e3b083286fd2dc391a2164cc39cee99070dfbf74c663a9b13eebeb8a3081c989410c0f64837e633002b0a8da7ba990855fdbe5051d594c926df44a3d03bd78297742a6f66a47d21b82968a48a193f7b515940b874e71c6d74d5d475d23b844575260b517e99199fa28c851601cb0bf5371893357055d46336b9f15633e8c08d
+TAG: 5b830a0bff486119d1ac3395fd3273c4a510c920
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bb44eb8d4f7acae58ff9814da3968bf81fdcc2be3bde7498b110b69a20312dab699e00aad26760ed582d37952bd468514119b003319642ed656c66b20a904c32321862e8ba30ec284fdcf7a0e945b6401b4e0f189ace86730f2baaf35764d297c653d2b297f27d177b6524251ad85757c56e884ff108689e6781cf8fbe4aa6a3ea02cbb939bb0bfaf1877c91020aaf87109f6d5cbc60cedc19f5673feb74a6731627db6fbf6db129ba2e35041e
+TAG: 90098e10f9a011d827f2ebcf3642ff492575d5e6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bb55f77762afb276783bebfa00b96f452cb5c5801a682cdc155a287ff10950e284a83fdfbcf54391c8cf05bdbf11d7b31a323ca780328cae482212107ee24ac8622bdd5236b1948116f4189c0328f584b55bf0986ad016bfc374cba8ae08b89beb9870f5846272aa9102dde5e80134f0ba2157d401c859d764e4d10f56ae4a733b3bc170ad7a3a9cd2533f5f1f0763771acd63356b92bbd6748144f14e936881247397a42963bdbc9223981058
+TAG: 56253d0b0ff161e11a9befbee5774b855461737a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bb0f137ad00f0d0f84149ca102efd8a82143691be4417408fee38d1790975c594ea8db36ce6f9d7033161238e07fee66ab23046bd19f158a8789ca67ed5a8629d11b33c343d7c052c5268bd20da7b5a338f87f35f634ecbe76c23318d59e65670cda8a1f46acf5748d8880c47d96ce250ebd717890c065398e44832871d05af5aa23da07598ef1620988bdea3565bc463afb9d01213e2914eb92cb7d0b6dd2c6ca38142246204d473a62d17405
+TAG: bf3b027cbbfda323bbd5156efea8dd816e5eb67f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488fa32577394bcd29c475687262faa452ebaa8da8d152714cdba918851d95b52ae360f3fa894e1a1bb724c4b70430c121874a0342b25913c21ccc5e391f40c6245be186ef4985503f4b380df7fcbed071affda1d4cf993d01a17227511025c857e4fa04d5cacd8aa80ba08f7afffdcf23d5bd974b9bfd7bd5689daab20e4306fbfd15b21c70d689a751ee8b013b350ef6588f67e7dc70d106583a72c981
+TAG: 1ab0f9fec0277f3248f05bc6b82ebdd1b4aa1983
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f0cf0cfde9c52f8b9d7a91225e5aa07dc4dcb2c5bf2361b0b291dc4bc385f44154f541ea327aff441b75ad552a4aadfc14110a45c8dd674aee0d0814ec6e6d7839e4847612a2e36456b6299a7d96c8baccf7e9a19967307614860c9641bef19862e0eb6851994962650f8e562ec80b17940d099c486cc4099e15b6799b45a4484f4f7213b2e29a07d9a02f93b0b084a2025152ef0c8a6eaabd5fce167
+TAG: 4bd997f670a0e16bcd1fbe245f92ed453579d6c1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f0cd217c10d85e279877992cff7a333354f411e46705a899bca6890c381f3bb9d5a6bdd9b28159d41d7b74f5ffb8de71117caec853299c1504cf6ea282839ff7309435dc4d8b0484950cfbb52f87bc43f9bfe95f40fde599d531ecf6d8a87c49812ceb5dc85ad54d85f05c4f5c62af69bf1dddcd14eef35c46187d0e8d9e24bdd654f847fb61e4578c79dc25dab474dd821bce90ea0a55e8407989121
+TAG: b99e0d4475114b4970feecab3340711bf7141880
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488fc6e3e7a5fa0df69f9b7fafa5108e99fc910e7aa939fa4923dc573f4ae150062620620550f32d6adb13e9a0924d3df08a12c0002cf1e708b2a1b1a960a56ea73d3f271eb5a7cf5113ca472d18758da5b72aed666f6fa950b66e50ac7c8e3fa989040e4d6b372298d9ed8cba76d36888956fc895193bbd0f5ff49755bddcf0f6b30af53586a9d2ecd0a4d6aa2f7e82e4c1c9b9df6c50565d47c690562a
+TAG: 31ff25add0e4304832728d90aa86c61cc4fd00f6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f1f57d68a9ef71461d6b0489b48cdf0e44fc27305b5edfc936f76d11a1fcdf09284647f52adaa969481d30364582058b1d058395dd482a8070c5701e8065c164ecb304a49b852eef747125ac3dfc2810889d50bd2a75dedd2c75523c38f7e3a36810e78b0284bd0ddfca3ce0f6aab86135379f4baf9e52059c10d858037ff64d491b047a74224cc2f50537880427022afb8a6395931fd7c606e616d5d
+TAG: 17728a9bdcaa0e895415c2e2cc5c403caf934482
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f5c5de34e8d952532573d80c30501de0ac1c903e40157c800aa36af14be9d9dcc807c6e907a30dd4c46b93a197e1ea2ff8e1be85b1209f9e616c446c415bd3fcccfb5f7c2154cf3d366f5c1d256aee0d5cb1013e45f520ed2109f798e42a40b5260484f891300d103b1289e28bb88bbb26b5523fd4802c80cfd2dddfa06b09c00926a23df6c52d3307674a49df7613ae721dbf02918f964f634cb2f91
+TAG: cda441a331dd20f6bf30bbb9e79bdc0540315716
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f17c418f96477ec99fbad6745c5bcafd6fd71f9b89fe2a8f7cc0d8e9c683da165b0d5899186694d65c16a441357b0a6b02f0e71d1918c0a2acb2317e0de139ee0bcdd126f05b623e489915bd20820435eab7547f4e6a197c8e9c5d920bb0e64f0c4cae3304df968545d2b35fdffb3fd6c5012edf6ea628af395b3ce83eb83e3b33f567ed7363f68f080a3225d8f43ede7dbff690288c38e232941589a
+TAG: 1962e28864cba63ae2bd6fd94dedfd0701b52c74
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488ffda4ccfd56a3eef4485ae81a0054e6aaee05d1b8e8491a40452bb30394650fbb7e41f356edf94e33f0a38340c6cbc7caeaf093db42fa90bf074bda6f9b1131fc815eab89d26c6857207aed79b1fc2c397499daf680c38f57b6e8f1a15580323671524e8fdc8ca389f036f98b7b4a6d48af7e84f8d9044d41cee06cac482586743e51f0bdd95b708326a4b9df4cf8050cbfb1f2d4749d491646b59741
+TAG: e3e24d6f68b6eea5f7a88fd9f3654e28028f1750
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4d03c9baa6afd1c63c6e6ddd0dadc9411792948ecc9793e60622e979b8c87910428cfba0829c5a2e99b7642619551a4d1c22d1a844d1c7af5abe6e17554e1e2941090496a43ecec8d977513f9b170075364bb78cc010e9c76a9eb7e5880af0ee9e4948856d2ec2a987feecf17493070f73ed00640c3f507f4cd7d9566551c0cdbfa871199386088b8903eae949ab7f85efe68f32b9a8263d990803a5
+TAG: 955b948a9e5a194e96a2bd64bc2f8ce53b40d201
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f16f6aec2ba09da61eb87ed109de6470f2be8ca4e3d17fbfa52892d6035ca4ce899898ce8638af3703c377f7973536f7217ecb7a9ca63f5a01d7242220f886f974f52f91d731f7eb3c0cafd009a19507c03ebc21060635beea3a1b8018aeda2cc8953d34390d4a247ca42c506b7dd766b57543d4cb1908c78d7ba86208327d6fed7c74d97b4e18e83b7d302413eca8bd00723d499b055f75a210a13c7
+TAG: 14d8c2f246b49f15d6e80955eae0e5a8350c130e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488fb92923bbe64a81f80c5a4aa6c3b8225b3d04d9b0852f13cbcd8f1b6724c8cdd08f988c41c4f1d42bc9c6b148e1df917d33c34ab495c01c68cfeab90f673862d8dc42cab6ded823aa67533cbc1a138784ac5c0d50942398c30fff66ae22f96b12ef329142f2be53b39826141a7610528b959cbbf87c274dc26cbbdcdc5acc04c358cfb5eb4892c25ccc5a1b6543b73ae937034c6182a971ac1f3a143c
+TAG: 4467de304edc529dbc7af389ae72b40dc5178fd8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f274413b26a3ee6e6cc30891adf11118c5fbc23eaa223c98fd8275af201a178449d74cc4913f88a76067abbf5eeea001900989567f8ec011575859f22ae286bd63e7ec8edc0e265b477f6adc88f2ed90317db71a8749d3e1ae2b7332cf98a38208a2fe5e13323aee2ee4c87e015cee3c4a90d345807b5d0bfc6d3deb2b9562b74b95f884ad93bddd8245194ea71cad2dd5be7c26659d592f79491cdf4
+TAG: b894b69ee1589d885052eb4c5e8b6e61f1d66ab2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f6c18ff2439b4e2188c73db78b91911dabf40b860b97401937eacbedafc4ed050e8c012f9f6c5bf4057b9648a2d70d83231571d3d0afe7ed64fa0526cd0faabcb0cb74b342bc741cfc6e44b11090c302bb685458c8c5fb785a059d5a79cf2c79e22e4884acbb7076e8c1fc1314bf707f93f2c513dedcaf2e722cf1f519d935c5331b962aa17ae0da1ae61a91da6bbd9f2e284f53703f3f5f57c7fa8e6
+TAG: c111a2c91788695b3dccc824e4fb706b9b6feaf0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4f737306b2555503a3546307001777fd70e9243170604454c40c11b1b5589374c04e031089d7a676b2d2c30ed3afb21ef984676747570cbbacfaed4572348617434735e4fed886af396e697d244859ee09fa508ef767c9a3f65a7e021657c70fe117250cdae13f490621232e063326f0c1fb164d996847a95b39192f7417649b8caa5a080716cf955b1f0b40e868d1ef47fb3e3745f0d906c4526851
+TAG: 2a6f1105cd9d8c455688639770f72e619dca7396
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f064991d0fea7378bd14e579d40c4891ea87b2f8f33c90985f43475865a46a5e35d00022eb013ffd2921f2b5e04ea796f84ddf6190cdfa1987d960ebb6ae459aa7a4547d45fbce20e1a4213544d255ff229bc1a7321d09ac44b55b497edc3129b10c067b6094ed1d91729a89d63fae94ee5213a560f5a7b465abf95542e1a70e45c0314e832e9fbc83dae3e655b4309e9e5593c8bbab12e1b6668aa9f
+TAG: a2e6102a003e6f2e36793be87c1d2e488b3592ec
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f48cbb43e3ba8700f1eac099d1c1eb8f420eea0a0c7321453b0ddadc76b7b1d92428a3d5afbb781a09b1bd68646ea822636ff91ab41ac64d4d4fe810a6a6417cbd779a15a6564d326476e0237ba4336f61d85b1f17989a8230dd7fc6df022b20ee55436246bb0cac9ed79602e06642fc8d9f3061df3a512aa77974251120cfe2e2aefc1ca827fd0027eeda1346b4d3fdfa5a077d7510c2fdcbd0e622e
+TAG: 8a6db3531a7ae506e94af2d5fe03871c72f7e34d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc84f97afd5f60048cdfe28d552878157a1fd4ff8e118d13472ca47c2ed40a8a66eac8b129a9bb779755e3d34cacd096a948001feec47eac8866923ece17f84ac1e95a191bf90dadd637a8144106faa7e552b103d55b97927a9dbb4f2a307d0b8ecdf59d86f7641437bfd9592bf2b8e886bec442498386dfadd04890715bd5aff455adbfc9ff9cb9700c35cf12b5
+TAG: aba38481772ae68a3471b3abb2a4b321ac18847b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc84ce9c7ed23693a0b7e7d59554b847d42dbd33a6e64bcb8383b98a91394a56579662d26ad0bf29b80731472f83f5e49b633421f528abc6fe931c27ef1fe12e96855ba60f17e76c460f1a4e52a85d2ea30a03bbd47d9e0fb7aa8b4dd060a84333b62db31483faea64c7ba5af3e372c5a721f112c9cf03312167e32dfe9be7ca55a8ec9ac62ffe566c755667c55c
+TAG: 5a2bba3bfc77e40ede79c044a67e3eb9b607d38a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8452fb9f77a22d3b3f88b547968516dc80bbf165c6008c1744c402e40fd0f2412ac852b0bc0a714f2166361e3718b20127eec4e50ab9c1fbce7dbd0bbc87fc3d7ea92def78312f48550dd6ba670d877629cd6428473dacf2d48434ee8352322ece65b939dbb2df4893e0ec0d03120792e28a660e239544436335f00220a859b6422f3103a07e13074aa2a5bdb9
+TAG: c39d746c8b9438e648701b0533064638f58492ba
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc84928c3d211efd99b8d22f056ac94faf2b5df067d50cbbe144be02b542080e3f6d26af8aa33526c69820ac90f87180fc2621fbec8e6f1773b7d1e418ee268cd53567f33439b849dfb1d02293d083e0495ba1c91219e15b776877860ff67428a4bbfd79de8869943d58955a30d834e09040d5b4e8ca7ed7fdf3b0e0c7c90e9ba3c3af474f2e6f80ad89c90c322e
+TAG: 2db79115fd648e4692e0459b7ca9c8067f85d91e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8486fd8885616244b479d3349ec7a6478265ca49de45d65cce90cf4d0386e984c90dd4a0746e59c7ed62e7377b4971da5663f8afeaed76c2a295d9ee99c5939a79181915315ffd6cba2041573e0163e9acc344a5b9454664b8656da7ade87d088dea05d11568604284580c13e58e4b3cf42258f4ac445aa4a2d01bd3e4976dd24ceff2b091bb7b4cfcad92e59c
+TAG: 0346e2f91ab5b99acfb53da17a67f7f8b98ae676
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc846a47952b8c68e49b433eb4c997f279ea4c929cf395370be690a99896a747e8700aed720f853eb2b7442f84ad340bc13129c9a44821efc97b689f038cb9b24196fe26a67b8cb0000f52419c9d2cd7a7c4b1ab8b3646a85fb415bccd38afa038fb86a25cb2af016b4757a7acca07df735eab0f1f375cbbf529e9ad5c34319bc3ca54cb143b241066d129785f47
+TAG: a04fdd461eebb27ca4e4e92bd183c05f0d654f71
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc84714c1b170f0662d2811a676d66ec3bcd7f0bd133c42f2fab256909de4cbdeaa50fe21570262c30d9c10635fac3df6c64570e3ab790b4a996e4f6d78dbf1bf61fd14f93d6d598c23dacee0a86e61e09cdc442d73696221c07ce42ef7bf20e67a7b228d21b8ab136fc9eb84e828d25c90eff0c6b123cbba2c5c4c2cfea3866b19c32c841559524963c8b90a388
+TAG: 504ecd2a203bb335499d8708ec10dc7cd85d012e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc84060ca8254bbf3f380b1ee69c70af8a3b2e95cc049df667d8be98e527a1406c66744099c16bfdff4a9a6502d796a8f2b208c7d4945d774a1237970dd90435c3b40e96da0c35b18c6080b33726c72c190e8b8b65dbf9946a1a7d5c21bfc9bdc36e68df1283d5ad9d43cca363fae39d962196d82c733110f7b294b9e56e18096fd564b6f2e26b3b062d7985c7f9
+TAG: a6285b0d38236442375d78de78389de04a4402ea
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc84fe28d9791e692ad6a8d3af01f2a70c33f60ef0d5538531208951853d0b830e8ba148d3d12f3ef19fb1ad84917353e8a93b15325082e1ef0ef80089f413e649264a95f017d43125ddf2fe02cfc3c85004bc1e69cba3263e373200ba1436f70816388ac11d3d30704351f79a100d3022e3d316afd3c0be291ec6a4bfcaf20cb3adfbe65faf9b8d68674ef30f02
+TAG: 1f7bcaae1c38ce8755dc67f282204c8852d24572
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc84f01349ff716d9040447f001e6adb255aa550afba1658ff483a1294b2e81b72814f22273817abd1635bc935bd159bacd9280c45221ff969919d06b48fc9fdbe7a18213cd9d2b4b59336508750a22cc66f6329356405b710d685b69e63f39b035acc67199d7b50969bbbd3b211cf7ecafbaa18a9e4278b610627eea7b1e24f0822f7809f1c97c40053c792aa58
+TAG: c33923335366634b865a35a281b516c8170be943
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc849bf8bef4a180e100f051275c88c33b026feecbee0b32fd2c14d0fc053d2bee4eae7e179fd770e7a5ebfdcab94843c66d09bb135e68811ff4da14c72b4772b0ba1de387a8ccee2ead233ffc16a557fcab7ce549eb9367053b93aa2be20e395a88376d9d9520db3eefef91ff43ecc88873a0915ac61c12f6b57e7ed5f3793f6f6c007a6372ee19e86e31bf7e12
+TAG: 598cd9108bfe337ba732bf5622ae602f9a075f78
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc84528d069b450ac7fe577db2840c379353ea1a6b4c673e9ef4395ee16131b4976dfd8ef5e428274b2ebc6072f254ab9f9a4c845d7089dae6ba774f6f7a388fae34637299103bf97b82e5e7200d26c9afcf17872375a7f03e4628e314daedef20bd6778c7f3878b5ea42ecb9d5e3aceec133a81bad741453ac147b26ab398f0bb1124992f6acae91633e9bb7082
+TAG: 1f998d0364472449febf940eee6896b3171c0abd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8454dd3f45087b01718b2f09a318cf5f1f568319e8a76a2c8a97244ac3852fa4235dc938f64c4d78c8dcfe6b1da56b490be2cbd5b11731e61dd7416b4c171b5d3e32bb3e85369ef33bc61ef8f4fafba85ef253defaf1de4aa26927920a3dbb39d0c62d7eff74c785f083f6ef7c77dbd66e6aafaa01c4a04c968f236e53105985e07e7ec537d9d94354f30f35be
+TAG: c827a720abd7d349e947188e4560941fe5bc23a4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc840846383253b859f06a1a76545ca2d49d633724f6020a0474bd6f294f672e32e673bdc686435ede204ba1ca23de7c811a82ee8cacd0c2dac5ef0569e3e4f27f2f117d49c5752da962b1d1abd4fc952d3346f5435fda0ab2abe276442348a461928348b74e37dc80a4cb381897005a18bfda9ea6d32b65f5df821fcda3b224de9f49dbb05c28657a34776a5a5f
+TAG: 4df006dd82e8b2d1b33c910bc0b7eba32f6a978c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8468ac43aca5d1f4ca6421132b3c20b0d1e5edee3c875776657ba603a1aedcbfac667ebb2a8e1050a0fe4b76305d19b91d07e090bf26f5a6ea45133f10dc1d676bb27c56838a72de9297059a15060d1c28eb8ad17a53a3124250fe0cd7f2b277341e88162b524e0ff0d4ac25699eecc312b6806f5509495646f185cbce80a35a127117fa00cb2fb0558ab18ab6
+TAG: 7036a02627d40b6f8ca2b95e3df1393bfa075e48
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc84e926ee570ea92980f6511f2140c71fdbdcc5901f5e4af2d9de071e53de763e1ababf8dad4300ac429870bcf084b8928f2c953c4827cc17689a762efa09f484e95448185d0371f2be52cb8b18ee886e740c04917f1deec934eef1c96efea9c611918fdf1003c3d9c72d50e68f9d157deba81da57766817763035000d84cc036d4e147ddf570995a68f4353420
+TAG: f41a190c577426ed3bb505473e6c6e2c5603afda
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb7403e2d874e49d26d8f387995d18e7d0271895ed30f0c1cd3868c307ea21076e986f320572e7ab678c8ff008d344254baa8411c0d0eeecf75f28a1fbf1c3a25311db4f667c3c4e94fbfcdb2a52940aa49794c662cff0523606a0b39777f350ecdd3353d336b693bc3ada9d28712621c2b4f843a92bc161c6fc1d2b5d49e3
+TAG: e0ea5b9fe84496bb73a64a98cf2cef3187d21879
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb7403356ff97b73c0cac52da67270941e19134fe515cc9e2f8567a4101a29029063c4cffb612e7de79114c9904c6fa2c4bcb2991b177624c0033173e69c5bc25aea8b0a12ccf312dfa6ce3245b73ccd3d8811400025c1161f7bdee8af032d0d8cfe06176f9dc7f5b74b044c08835617de2b2e88fd5fd34a79777234a60d33
+TAG: 6000e6b1352da753c40931ad1c045b3bd3aeb649
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb7403e1521ba34cc810253d2c593ad47ea87bf7e1b4d523ba4d13022fa47f383ff66c3def79572c3224a80d2ba4657b549ad1a328bb8e9e067b1abeb1a3f3e61b76aef37420b208b2a5fd79344049222845c6c02d7450a92ab24a332c76dcad27afb23e5a9d84bc66db053fa56474b36f8b4eb4621227ebaf5568543d4e67
+TAG: 53177839d9d0ffbbbbadfd09442458a911fa661e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740328bd376223a41794f233270cd9b16a440a6daa7f98d8116d6bfc5b1af06143e37afddd42de2368fb14adea726fe7f315ac2708fe606cb3399380d37a56bae76e5c891fb3399484b1413a620bd70f941c09a6850b96bbbb08495f1437af98c693d1f5ff38bde67021d885205af5241b714c3ffaa1d9fcd853b47f8aa5
+TAG: 17b686e73b2c247f63de2a0b7ff249a186baac75
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb74032230e51a38bbb0cf37c5e3db9e188b1edf2905b35b7c284d4f84d7e8c09cc90bf9271ac3e563c63adaa88f7955e935b61de8ff3667b3bb769e78f2f7e9ddcfca21d9d0660d8799d89c9627f5c4da45480682cdff47f926ebafaabe3b15841938dde3bbca1131013d03753af833ab435a06fc5479f13344562f5fd86b
+TAG: fa9e08cbe2493518a70f31b5f9a9e622e285eb84
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740322c1ee109a737e76c441e061f6de3b4a930c46eea3d526c96cd07e4ea30683950d0d1ce7d7ed36097c8cede58e2f4b9a2542ff4d36871474b66f45c267f28e1eab3963b1d68d020298af3556d14461f3468e0670aed36b1e99c2c8ecb3817771fd69ee7490929719880049bf70d5710b0512fa286e3d56f02d6301e4
+TAG: 9d2ca2279ff4ecbed416acd28587bccf638841e7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb74030f6fb548d15cd916e9567aef75e06289561451596954dc4b82b3d85589ab1aea02aee175d3a36a25c1b11ad15cf6f26e2b921e55dec1bda7436fb99d299e492f60e8b8abfbeb77cee98c07b40700cd87d44deba910ccfffa62249f334da7a36ff2930d4625503286edb24692c562a1f0e9c6b5c54e0df2676ae58739
+TAG: b8e2ed387bd6eb724960a718d8234a1b7ef7c919
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb74031b8d8f8fe5a955e8c84dcbb8ddf5a40afbf4845a37de15fb0b47ceb1b2a326cfdb41e931ad937edaa805ef520fabbbcc24d7aed51daf7903054f2a1a1dad03fc334446445b70fedf9e39d23e88c914f82ac7dec6293572df0d79f3cf0882df834f9e4ff183e42ae86586f9e7311e98921c1688af09f15d240020911e
+TAG: bcfe8b0f6e5a4041f0602fc2b343b75b91bc0463
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb7403848d474c170e9229898e5679fec62200b557cda7ad9a8c06f638291a5f3d2f16ebd78cef7decb77fc67c43b009d0d49eea34f652d02efcac00ca303caf9fe7a792bd1cbb08d5054f70105c34b5ff040a0ce1e8fd2e682d67cfaed57eb6c5ac576113c66928952c3131207156f09ad750d09a13a7edbc93e3d587a25e
+TAG: 08e9b8afd25951e109f8f189ca7666aaa4b17381
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb7403c1e816d9549c9610271ce74a3c56b553db1c112b8b8486804328e7ff01b8db1b1403df99080f0e08ef39b9e71d4cf60880a1984bd1091e4786740bbbda4244ac921e68b0efde217c22f688cec6babbfef11f807189d88822e50286e5b7f94fce1f9aa7164709fd34a166c032aabb18b9027ef8a55eaede99d2b3c5f7
+TAG: d85d91987da611409fe07084c285a27fc47d1f6c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb74031bfca53fa1f5e36cd1dedd13f006e9e0055e101a749057c3a0f2d5a19546646a3089e7467cd45804dc15eda9377d78b43a49485ba5ba3128262e614c1768345733afef9bd3b2936e2bedcb8be2cad84c2df1a49ec28267ee0d3b3d8794788dba29e678c11187043daac2d9b17793bd5a3984adda80f09af9c49e0a64
+TAG: 3fb284b53a482fd3002eca5f14a8cfa8c2bd0758
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb74034a0bbee7973becae3632b43a815faaa32613ea6396b6eaee217b4e9380412f6396241b25727ea1f09c8dbfe4b566559a5c6de40c703afb0f6b52bba9cf22281d1cd047d2bec16424b64f3a2f180c319ca019e762dbfa13964e0f14bd6a7d2ca2400c95a754fa5def16e0a8e6f7c564a50c1b4c93435d80d875a554b8
+TAG: 34c9144f6bdb3123d9334da1f8def7755ae7e103
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740320894f1dd94c42bfbd32c094d43db932eec63372b5fff20253d255cb49d1a521f60aea26d15d4e59024621ebb644436736458006db8b1b174f0f0eba3957f4684b539089eb1e7ec171c2aecdd39443743e6313f041f31fc9301576a752c888545a2ba6096c3f3b3284527361e8fafdfdf1d82051d7aa44a4605ba393
+TAG: e739fb5ed2540fb1f55b4bdea668169024250aaa
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb74033d9c7b625f899489f4ef11718f6fa243ec50c3776023365a7a3abaa75a85decf74864db0c94bb1dcc6348430321d90fd1ab5bd2233bcdf326234d8f993b729409616bd1ed1c869040a987a280a14c5296410e7335359d96b2d5ef6d72afa2f5479ff327d3a3abdb2344bbffc44199c7408b23c894b3401963bbd14c3
+TAG: 55f5eca86283878597c281e68a269c79d651dacc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb7403cf7b6cd216560eb0a468dcc4b957be00b2fc49bb32f8c57bf1a1ff3add4368d78f379d49afaacb67696b2779ca988d0b363d02d00ec56d00e11208bb230c92dece5ce18065785bcff091561214ae0c8d78bce60fdc20b5b8dc47b5c0c473a2bb3f34cfe63f1f08cd10556220033fe3066f0f58e3d2ee7c264bfe30a1
+TAG: 5476a2103077c7918b53a9330abf3c1bb5074d46
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb7403e9bb05a8754b4e45ecdba91a1d0a12a4bad468bf9ea9e83a9ce2787c8fdc0214629e56dff1fcb4e49996a4695da84f6668331533085f9d3d9b328532e467882220b4b3f056e5d76e3894099a18bfd7a07c6a716c463b34f0fcdb52d2435141afb0cbd9ca2d064b227daf27ca659aaddda95e17a4afdcbb3606a87152
+TAG: 6c46bac39c517955f343d2280f016b706afe5dd5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c0677e7857c3686ff3079bc2c1bc3f75a0773e5e34b49b3a569c2b76df09eace9e867dfadae3019372fcc9c52e005bceb73198fe4ddb7c623d72c1062cf208a79064f3f7b6ba5e904530f34c1f3a50f83982c69c9c1d8f54d87fbcbc9cce936f56b176c0a4b37c0b4d41ad8cb3
+TAG: 269d732e768dd6ea274c363447f716abba8990e0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c0ac6a9c1bcfc5697a15b2a9cdd8eab1639ff85973e0e8592d1e8d689a04e1a81351469f5e93ecec47cd44d6db273fc16465a6de1a83c8c6b17b36ad9c6976a1928228a405955f31598de2ef75a00c2569730ddd7f0ca2741cd27156082c364c20bbc936851ad79bf9ebe691fb
+TAG: 734112f236212e2530460ea578f97a60e874d4e1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c0bcfcdb021f532936254dd955d21f65cda8521dfbd85430d147cec59c6a3021b0718aa35b27dd8d456605fc464e6a8086785d1d0783b6cd2915d868c32e476203661d15b54dcedbc7f1a1751b8ff0016284934b3a9531cb6930f9f8d0d4f86a93666c08dc03ed7e81189a990c
+TAG: 122a288aadb66d4868028386d866e4f0998fd77d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c0ce61c008ebfd8a7dcca74224cb9d7c1706ec617dbf7e15fb87e9e0248f57b37c744594ed9c81102f46a8b5f62a244538c25d6cf6c7cf121987a250d0c649e73073c77a00a6b2a374604e4159a19ccd6204741a52fdb0657845b0b08111b362dbd7522662a69b1864c3162d03
+TAG: d61483f39e2e27b3705acef3bf8ff3edd6589acd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c043df9e9fbac7808b3e0775e482cd55ea34df9f95bd91524412f388efd07c91f11c586e33e3f8bcc6fb3706d4f79429fb5df22269f79ee96dd9fb8a3dbc369a27f3269f13e2d621cbbe9f2398d49400fe51f0a2e1e913de9ad1a7ebe09db8baabb0d10f671a275e6890b49b58
+TAG: 3e6ee36ca6e990486842e0d14ee5ff7793dde62a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c08eb95ce18c226af6742290c82223399fa93c540cca8866bdd266921e94d73341d3c20604c139ba86c7d3db8b0e4250947f07039ae466da8f4f986be58ff864f5e7da985da6902ce333845b27df0d371602edebb9df93ebaf99bb9ed2e256309ccd0616ef95174e4dd3b7e266
+TAG: ab87bdd8e15df6d4cd88d881ee9a09c310debbeb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c0e420565f322cadd7e8bff7924d26d1d97b1df26752ef3494e3e050ebdfa1e00658caa01668e80a9ed01fa05efebc5e232b8fc8656eed3703ebaa40dc48ec0d8fe1eeeecd6a76d46923d913a0afb804c218e913b2d5b60f47f0b23cd710ab69a23e1c5079166a4f3aaae9f68d
+TAG: d3cb30324c6c4d6de0686854fc101668b5a9be5e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c0db4914f1e0817de607f55d51a2486368ad4ebe249388b1613a3080d87bf16b9619e8c09d8ee153560bf1fedf6e804990261f95e8a708bc11d2667dae365a8595c028c0d2acf16d5dc4d3fb19a5112c23811f12d67ca478205a588249ad51300c5e1fc763145d05deceb4564a
+TAG: 4ce30eafc103d2ed76fc2f04e5f75b6763eae244
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c097cbf5238d2f5024666c7609b6b0934663d81b9d92f5ab2d73753a0e7636aa9e39493ed95acbdb887100e0dbbe905d52d68bbd441bfa012a338a9f4f2d0d95fc7aa11af112fe892ed843a7a1e53c81e68ee58ce4514aab10248397e67eaf41491bb1a3231351d57a95a57a1a
+TAG: f4c35a677fa06299a57162e1a84d70770c2ecf47
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c0f1f12ffb18d72e72b3e4347bd561c3c37b2de69b6264d66153ecdb0d1b20395e5cd65fde155f2109a45798a0eb32c480a68a4f96a22f423a83db0752721b29001bfe4a66b84c997d8c4ab0150427587e88cfacdcb8285d47fc6cb6bc37c3165bde34c943c109317a3e9cc258
+TAG: 01fb3c63d6f18fe5430e4291cadc3ee3f55a03e8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c074c573952173dc1e077c2d94bf5891b2a26d5baf9e6cf2a6a8444b40581b8999372c98126cbdda6e5fb0d59cbbd738e57951b67abf3dbab991569fa4697cc0785b1dd63e181560404e06e8d9d017c7e11d93aad8a8a33cad51bcd07bf3bc449cd5832307ff812fb5337116e1
+TAG: c57e7ba694a25faa5d1b712002558d8c00931741
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c04f7cc59e2563313c1bb2ccc1aec10237c4cbbb9ba0aabd38acd94d8870cd4c92cef57cd5f325c1ea14692660d0765cb23f661832eb379819080a13efa28a90db7732cfba5c84bd716e5733036417b5090e0e2916be6b2a3f4b4c92dd508eb5aede9c4451821e640103a69348
+TAG: 0b7df9ccbcea1d7eb1dec58e168076a5580bbf19
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c0e764bd49eedbdced2d70e7a69237ceb68caaaf6855ca2da5fffe177c2aa12b087d212fe67010b7fefa2d12c9516291a19a72dde12bc4034ac334a59cda0931115df63e6e5555d42a36f5f7188815dc877140f07cd9c08a1d508129d973473c4b4b83d7c35bcd5a20db978f4c
+TAG: aee3f5862e45966e42d536f30f811643b2e8ff6d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c0745b15a09a81c9dc0de7d8b7a9740c056fc08e9a57b6a267a382dee1b4dfa7e783d4cb0ef18b33e534fdc7c8c471e876839fe0ad149ed9f73c0897548e89a6e739935737dd6bf3a31857033b849071c9defeb7598b26cc025ddb4b9f172cf5629eae9b51a4f791bac2441e8b
+TAG: fa67a0455f1dfb61d770ef2c3625a97902be505a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c019451d8e8e463ac8f162a99b6257d161199e8d847fbd5a3e85d2454d965c5efb8ae708fc4384eb22f23f0e0375ad528bd42aee7d06e4db4210f4b1b6e2118897ab5361781c66a9bd0f780465cf1371adf132f27f8b46336ce8d5c6f1054c5d3d975ab848bd38911fb06c9ae2
+TAG: e9bfca577f6ab16296e2916ba6377e02cda6e214
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c0d3465ad7201ce0d3d08079a9435c629a2237c13b01400756e37afeaa9615534fb44deaf5fcc49d6357867cd190e742f4f7691b5dc7cb160a8964490b062bb241d8e5938588809a25945048b95b01729e6721d39c2e2df7abb04f8737899ed34e92cf67e45a2ea423fde84f77
+TAG: 92b4ee022757c4ecdbd5bf023615a962c41bde01
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e9f37b18dfe19be8b8ed01e244a1c76187ed45226d7cc1207ea864a20178a3c46ca147355f7e4394951ec92bd694fbe82357dd786637872be27af588297d1103de7fd2b5b2d04626e4e5212b720656daa0c552709f3c3c220929980f74
+TAG: 79c941987cff3784c8863bda1199670d8b2bfab7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e9040a932d95b6989cf917b36d7c0c4530d000fcdf789e2f181c408794f8cbad0e246a395e6ef9218289561398486584e403d4e6a1b2bdb7b06768c5bc022003739d7f57b9bf103d434518e6242399b57714ff03a4de4f14e56f69d21c
+TAG: bcca26419ac07e3d25572c57a8452925552fc19e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e95c188047a209266abe082cbeac2379b2b90edf0d486e2b1b823d2f581238a478fc6bb7173d037b15566c1af687765bb130822ce988b5c0d812cbb877e9bddc3d7a05d17ad2026c4a0a03876592718c8de4b197883900ff585c6fd85d
+TAG: e74f327106037d8f020edf80527b18c814120e88
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e93018880d724cd554bc262d22939291fe5eff0de652a9c03dffe4fbdb212adccf4dc50f8b612948a170d14ff80636d1f0985768775c8da248ba9e737bd4d6634d61ab5e1bb8bdde505241ceb4f083544728ad676dda702fe8ebcff486
+TAG: 35b450c0a19429a8fb15e84cc840cc38fb1f2c6f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94a0abf4ca4048e7e37c6622feb3f1a2ebcd98cecb85f6baff5b47839a25627002020eff737941326e8a758416b6b35ce2695c97905dd80a2158ecd804ea9e7c1a22ef0b6d5f27238420d91280ffbee02632c1678806c739e62ed1e82
+TAG: 10cfec97bf6a2f9a4ed4c9590ae449517f6e23cd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e9a0c46416dc63006ec1d83c86a6dd1aaca4e347f5e00e14890e2f4653b994ae05e5c72f3591fc460b245f8331e34badbcb2f4ba97682acdeb14791cc9abece3261dd856eb4d2145709e13a31467555a577e05f0c0a476c6d6a666510f
+TAG: 0c02d8995012c2b37d49795a8034ee331a82ecd0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e9f5913a449137cc73384226818de14769598f54679b917bcb9445b8b66e97252386ee27d85a84236c47d06e53d1931bccbe20ffc6a1ea47f7d4312f5f38b7a6bb806ad548ffc48392a24a8f12316b2a6919e1b985e3884986b5561435
+TAG: f2b9d9a94047d95b1acf4ff7b60836418d017315
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e9ab617c2a16f75be02146e5f60b76ff153a5788a859a3aedb7c32b328012229502f00b7baf3ec3ae0a617af3aa3c04ad0bef67d8751476f91dad19c226c107891f0f36242ba2f5a9a9b9bcf303dbd2a0b7c417a282c08331d347fad38
+TAG: f6e4731e7072904617c093034ffa5fc1633d52d9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e9cff7a1d6e0a97e866a0e039f7e9b996b5f2f71eff33801fc743f1b389315a50efbc475c110782da1e94cc7236f7ef2b52b03e203f257ae652a41d8466a839295bfd150723d820487c1352156a52f1fb3b71354d9d437b212137c578a
+TAG: 4aa36750e8cff0a8734a4eed27797981ee204ab8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e951a649ba744732b4a902a3852269044e3757dea5ea41f050abcbcad8ee7b5fc0f4c50f217b257d054971d39204ce558774507d0ec3bce2a91d56ce699c21b9e658c3d5391a32a7033dc9a59aa0f0aada815c6d53aaf5fdf432b59968
+TAG: 4551a0a1c0412aa7b523a8f79b79e16ac41d187f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e96df5abd571c823a76e66ed5aa98bffcb58e1456ba1f0cf6f0dda6bf93ca8bfb39072b89f9be9cdf73f0021d7e525931581da12e446fc9e23c997e0adbad8f99d49b97e841f662637d1feeab1ad00ceb3742b20bc8cc85da8911497ba
+TAG: a79a5b34859a59ab49235969df04781e6ffa07a0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e9d8ac195ad35c77b6cb34df93557ded15cb3fdbfd1113dd59b3fdde366b98a6268bb3af112398cc67d0bb1cb34bd1b89309cbf3b4b5295b7cd976a937f01eb3d9839015f22367bef2ac226d27d2666a76c87681167a36a39184cb94dd
+TAG: a81ae012f9892b46d0699bac566a9c329d66d9a2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e90161319d851c96cf696e20a878a0752b80dfb6f1d382bbe577e4f7424454daa2f9a506ee1189f3e1b48b5fdeaca85b9566f7aed902dac407341ac74ff44b06caf1365e4ac5961888282ed7e14552557237d66282dd4bcc05d6cecd86
+TAG: 821990672ba3ae32ed2016b3f7d116a49506c198
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e9eb173edcf564a40c8c1935edaa951102ab3089779b3d9b52f7a58a05b82da6a7b7e473322c83c8816710ea3c45cf776d7d1f1fc2724d17344d84cf57e99ec9403a0e1b3282b49b34c40408ba810b68fa6faaa202816d72fdd80543fc
+TAG: 3cb39471a042ef44f5d7cf6392ea3f78b08edd57
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e9df6792e10f4b88501f6f6eba35bf66f281db86957618b0541bd23e8ed35341035e589d95764aad483c0b03b8faedf3ea32f0a9889b828281b6a4a8096c746034614ff1730d21530e751e22e78280eff9f8df93009ecd3a7437946ce4
+TAG: 6b5a259fc974172dca93edb1713a67eb8e68833d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e9a99906030ae6bdf7ad73392753dbd384a53c0b23372ed5309d06ec852303934adfa6858ae4b7cdefa498dda7d185dddbbde0579ac8ab45acc927a1e9da337b0d92fbe85e226a40c8247a9f8a3fe40de36240ef4ed2d50b3d3846cb8e
+TAG: 7eb25a4e64437c707147c7ec0d742c11b6b53be9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d03beef996f2ec45c8cd889b0b7273c6b3fb951eb1649f9109a256aba6b918aa2046c7da3005dd75ed15ee31222a45fc62e6a460cbec14dcdb5c50a551b7610d7982ba578356d911142c6d78f
+TAG: f0627e29463d5cd08d56154409bc932c17b48650
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d81ff48c35ce863babca14eb065156b7405c79b5d1df6021cf53b3791f0557dcc09b19e1493592c1272277b34bab7078732edb7a770cafe22511b1c86ea111f0be8124e4ec4c09cf6df1ab1d0
+TAG: 3fc48946f50c83db2ceb51c0fbbb66504eb755a2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d6259086fd1a64c3278750c5c83b759dd9516681c5529944f4ee1575bf16f53740f9722b92d50f30adb333613163e32fc264cbf24dd74a21aa9af9ff7b0160f109b52ff5d97d3c5d8cdbf9468
+TAG: db1f510b9046981d3e5859b317a930c979f81203
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d4a74fd10b37bad7f67c0ecbfd8d0fd7f217af48abd7a1b3e2e1a150563f2f26ca597201a668236e80f98e3154f912ae2fd08c95c4e6768e69f0ee5a129a2dd34a2fb493e36a949f3217eaa45
+TAG: f26c24e46a48dd837e356cd8ac6ab9414e7e74e4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454dcd9fefb389aecb262b3a446b8379f53bea3a39c0feca26cf9206f9ab96dd40a3363ff0d3dec00f81dc69f4ee55c602d9c0273a39d8ef95041feb8dabcc843b6f146c0ead43b4a0a0bc2dc4f6
+TAG: de1ac76f704ad777424acdbc57177fe83b1a19df
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d657eab760984ce70bc48f40aa1ef2e263944fff4fb1049ad69e4092f205d8562f7d2d39d2eb8b288d6b5b4e3abe172429707b96a70a336ba0e08eed31cf60806335d25cb526a5a8e37781aa9
+TAG: 06682d63b07bb6710553d81c9a69b1f5de5392f2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d4bdadca24452b43af231de93391efc668d114d49b3d33bb7dda6d483480ab3600621493b6f2882a8996082fed026abd7c084ec8751d5750336a6625aec5a9b24293d2e203efacc1aa0142abd
+TAG: fa56aa337e34f9397b35e6dcda7f3e7ada79f597
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d7b3aeb32cf778cfff5cd1205ed3acde214f942c561d5f077fc51950ac05fb544957418534b51236014dfc44abbfbf92e8845c99db2321e874a98934a658be36deee20f980d89fc5f3877a829
+TAG: 9fe1b8024f25ff628108ae1e1fdddc98c3c75b94
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454df56fd27c25067e63df17187d790bac7f5bdad1e47781114aaa6cf37678e7b0ac935ad1b03c3e1a9f15ed253ed1444e38fa1f9d2f19b8214226b5c4a9238b0e70b144c3433cd35713d5be085e
+TAG: 44b8f4da101296a594c65fe5487fac5c3aceb381
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d39731ef1f87b4d64f3562d2852a00a69d29424a64e7ed697a3fc153e2779385fbbc8446a6b725a92f047638f9782ec03b99cc7d0b38d61035ede402833591e5f1adce3509314ea5974b1f1fd
+TAG: 324d9e8b2a241ccf7caf3dd48fa792cd244104df
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d294444739215d6bfcf0b98b5ef7baf7ce38bf959c021b634c569951b5fa3cad65780086457602c3e280bce599012b9bbc845eefd009316c1840074156e4097cdd753ae126c012c36eafc0ba3
+TAG: c5dff4ef901c433d6818663efbd01f56fad0f373
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454dfdfeb54c189ba05e3f90e8fd3a246f1a5a60a93a66400988b5db00c20ed6d724f3f9a17fc1b3d82b2b792aca8b3da15b3332f8c90110be902ea1a04434e52cb0f5ec3f62d13f959bf4fca940
+TAG: 35911e87afd56fe1985a7c7b889e6743067cefb3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8dfa039def44435bd8691cd80d9b72a3c4fa25e50cebcfb59075bed286dba438c0a65dd06e1cf593b725a3e76aed54789260259df2d21971c1b4b3e34c8d57d1407f86165146a5397ecf01e3
+TAG: b3155081eebbc7ffe5ad4e0f928372ff9a17cf32
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454dca73b86926a506cb6f277157f441dae29b6be003fa703fb428ebb688c4317a699bef6572ccdfbad7fbed3df2f0870f7467b73b6c800a5be4c89b137c0b60d4e25546a7b6e86c72a3e9e66703
+TAG: 97773eaab8179dcc19178803280a2c432e8bf819
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454dbc6810107c13bd16e74e8b166b94267168abbf7d5630d18b928afaa146392a9995b8c4cdeede9c0c83fd0d4392354c895e4f7e6bf16fc26c5fc23d9316739a1e2dc3723dfd4f35027e018f40
+TAG: e1b28308c65384f618cfafa56d2f38c918798f49
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d17d4aa026909a01a6a9dff6443fd9a40aef2a637390683812e1a85dd1262a7a7fa757b77e4555058a47d737ba919867a2767abdefff24e0a5d5c8e6085cde399d345a06abb981d1179bb1a56
+TAG: 8b678ba76d9f38177d73204096a136acfa7f0a67
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b131870092deef728577f02ad44d1903f0fda05d3aeb088ae53382d286939abbb733b7c13db21a1811b7d04ac2610215d626c7a1ae44828409ed96a0024
+TAG: c31af953967cef920b9def46fbb4c2ddf5f8bee9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b1388850a973e1ae9bea6795ec8e4fc1d1d70d7cc6d512bf43e034ffae1ce6b198a16b9e682b450f144d99c95ae743f72da508a6551cdb31777170f0151
+TAG: 845690b3c5216e930cebb6079aee864b11acc856
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b1365ca49e2effb9127b848782379eed7e4767bbee3111a9bdf26d1b67469125bbc6fbb4f282fccf464666e7caa14c223bf883311eb843c5abce1ec62e5
+TAG: 8db6027e98ba42edd34ff989fe6a2bc9223bec87
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b138837a3f13616c4986742c52a99d2f64758773b031cff7b2a40d1659f21bc75dba2e499c2827180d386ca174af57aefe82ff9bc8d7bc268c79a6111a2
+TAG: 6945d3de62a30fc2e0d5a618ffdf1a1f6b6824f0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b13878b2d3d62a0a492dfa827e3553893fa9406f0d60138549913b4f73a50b85d1296b6a74f02b3e17f1eabcebaf52336990ea2130f2dcb955514fc8632
+TAG: 2547b8727c04a1edcd31a5c82118195ba769076e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b13d8a7b9be69ba0c268abf7c756dc640f9115aaaa01bb0a9d0843dec9b5f7dc6bd741a6ae8d2eab35cdda1825e7e6434a55219d212e59d081b27ca7c80
+TAG: acc633d14e72f44a0f0e5e294f64be3cbf3eb580
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b13b54363a0a3d90c90a085cf19cff7294b300e9736a06c29171b04a8f9b468b250191a518b2f0f29a50cf472bd2e3ba2374c6bfc7a67965b7b55c08ca2
+TAG: dcd2cb8dad937552cb882035e6ac94cf3bb1324c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b136d906d5a8b20d95d95342459fdd3ecb8a557969a5efca8494f3ade4a109888b273db2798eac812754a87e01c2236a6e4ce1faacb0243653c4fa25231
+TAG: 988c7a7b89a330ed8e845afcd74079faa9653fed
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b13bc466324406865edf8f2b36709e2bd969c65107a7f9f7b20162dbdcc78f473ff01e27e6d6d6fb93ff20cb0d0f239a5459d0bb35dd5f9545f2f62da44
+TAG: 60de94c03abb1074d8d9f91aea743337c9c35220
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b13ff602760d712a5d22694c5be296701caeed947ca5a56e1ec65688ad8db41ea06dd2aabd1cb73f9e1f4354baeedea2900b099a37bac75050bbb092f2c
+TAG: 00c3272a2550b08dfc46b2c7ab0fd2879433d69c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b13414ff3f17276ea15f2566b8575f6690701569deed74899ae5b0340a1d1c2a94f4556f361915699f7eace44fcd3a66466ab322e45b6c20edce85f0477
+TAG: 3ef65f38a7cf87f0b0580a6474a0158807f4dd96
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b13d6979ae1b5bf4b876ced1b8a18db01182b7681114282ce2abe4598a739a5b37c1c220c68c69704fe7cbd2cc5cb6891d55268fd19ca2decb67deca89f
+TAG: c6aed1e7146e8b471adcc54fa771fd0231ee4a24
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b1369cd340ea51927181dd670298745f2d4c66545886f510fea8780f042838dcb0de0ec02377247d81835210a416ecfd7f07fb9e0c2a67f11fb7c69f113
+TAG: d8c549476847173cb49b92afeb888ee971594d1f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b13c8f2ae94df0b279019be317b0a20277754ac6dbf4409a2a8b5e2f0a020287aeecd6ae760f0886dfc5bd6876b9a7f2ed97ec0352d46892a9cec32bcd5
+TAG: b67c7377f5ee8f47440955a14ed16c668d3ed470
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b13a8e8b78dac98bab202ee41ff1e5ec4b6405bf61698000fabf9ed14644705d55061abd6fd8543e3efd37262dcbd9f0d42aa6aa90671c14eaa7105b147
+TAG: ba0830de3b3a5105d1166b12174252525aaacc74
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b13e2f81713ad87af35a4e4fbc026122e0edbb9f4392d5c91d7b04fc6370cd7a7c3f6147591e8819622eb85dd701dee430de6958b12915288b17eec98e7
+TAG: d77d137946fd1db0e90dc3b444ab5ad06a68615c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cf372b278c5575d6a1e11ebfcf3a288b86afa8120d063393208f69efd64b876fbc6a4a27940e4d45f24336e04
+TAG: c215d684d411bc3636579bce0712fa045da26120
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515c68909d2c8b3c1ccff46a1c4cfd6ef43a03f7db5ed9972cf377ff571e3150e964b8caf28548a71c02aa6cf80a
+TAG: 9f8b0e73f45c2cffa8d1be939c20a625f65db447
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515c75ea67022038f52daa425ac1115b9387e96fb566c561c1a37cd1c7ca85de0df11e3bc1694e00ed341583faf5
+TAG: 2d309e9d9b92dccf17ef12711e6789aebb38b676
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cdba083beec828624c0a430977dfcf7ab15585b8bd361f1bb7f2a467c397f6dd854831be6c2c0dbe5f5ad97b3
+TAG: 41033200cf582cc4b913e7646f354aa2253bd90a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515c633c053a52fac4841f71f5d13ae145b42c62d5412545be8baddc77c0b7fc807cfa9b50295273370426541db4
+TAG: ffa967a8de6b78a60474e6b6d78f2befb9e74a54
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cf20fc55beb4b503cea984d72e4d1419ceb6b2e69a4923c64f470c9dd44c369407a0d7478ab3bf345b872ea7c
+TAG: 377ed14fa6ffda6004ba46fad4be12451b7c7b20
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515c16fad55a299ccbc3dbbff8419f2d488e75203f0af47300bd3fbd748af86ea87e396a3a2369db08a25b94033d
+TAG: c2b67faa4285063b4e4afdc8add092e9a9f2c91f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cfbc026a638bce89d8b1ce9d2bae084e66244c47dd58a65d8fd81279f203f7afee5eee0537bb3838114143862
+TAG: 628778fd2d7b3f1b95eb57ff080e1840dd086917
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cfb5467317f7ba4470858a12fd4a4fac36c2ab6d0c4b6037078e82887d94df8dcca100b7b58f9b46ad06ccd4d
+TAG: c94fba31c95182f847fe2b65f7d547dd4d14d7b3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515c796ae0cdf955d0542ad39e0e0e7ad55e092f3a06375893582530cfd9f218f1085f06c01bac415c7f5d3efb12
+TAG: 6c3ef5dc3b40adcd3718c20c21d89e67527498af
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515ce371d618872ce6dcceb7713f9dea6bed578c7a87ce9ca6a3dae9b3467e79c9a22b9754197df118eeb89cfc88
+TAG: ac4f85780fb259b60e7894088234515a75d76b95
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515c4f07c25cb1836e004b759488285f9e190f2e2abba558d3e5700d27106937cf42db9b1e68386a0e45bbc81c0e
+TAG: 90f6fd52e4a8946ee353f878d462bbea6399c699
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cf70e14d46a94688c8872d28b09096c43bf9f947c86471f7e9c621633ed80a3b018b32c06c2d6a598da505df5
+TAG: d9f7b44646076d9a745ae1b94fca8c72a5ec79f5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515c0352b473e6c5b65d375748200ac64270e01e0b1b2af99e356fd1653600245829c7f196ece7afc45c4cdfb287
+TAG: d206722726794eb71d936d4964129d60fb52e496
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515c1852066ab3d66883a846f2599c08e09281d8edb7ddf61a3a428d312349d22a9ab7b522ca90c9e8a47ba4ac3c
+TAG: 08f7d2cc2ec1e0b9aa9423281857891b427363f9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515c472d223ff7ac6453699de42c1363d2b7fb6c78240ac3713be7384ba8b188a9247a65f99c72c1623cb619b286
+TAG: 1ae629a7543e5fa5b493ff2bff11e6ec09e25b56
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92f07d4b82c55cd0dda3c9fac9dea496823bbd1e2342a27639a885843f
+TAG: 625ed73fd6ea8ea03a94a8d73cae06d9b9052c2a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db927ed98714d9640ef6386ed7f307b9d388c8cf956114b1e1d6de028724
+TAG: dfaa9c70b7ceec08d39de8a894e32401b7dcd048
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db924ed3364fe1109ec3b25dba3dbcf93914b130b137008a42d4693f8f1e
+TAG: ad953eda24e3c664e9a1884ec9db8899b1c98f69
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db920a4b8317329c4e337902ad86f9c54c9898d140bb805e2cb147f7d7c0
+TAG: aa2a44cd8b5a6a42033ad3a5ef7517d8b223aea7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db926bed3da3c1a89cd66b8a10833598fe5445ba243cd7479329e7bde29f
+TAG: 0368ef2411cf5c4d0e9864f37cda4f5ffd026303
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92024f8ebba092a54be441bc658604cada1d816655cec553adca419e3e
+TAG: c20b12c535ff7c73f8b6ae40f1969bbff02cf738
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92b167f85df5446515a40b2d3d820f3360c21b377a3879283783a3abf0
+TAG: c55eb045a36dc3c7fcfad77ca5290ed2e0bdff41
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db925076a7caf60445b8eebbf73ab2c611ebe88a31f558f5ffe45158a58b
+TAG: 23fdc118c364ddea3eaf051f52d4eec4e64c41d2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db923b2457f182d6ef467eddaaffce75ae081ff04d752e662f499fad72a4
+TAG: 1c9b7e22f5568a1f73bf0fffceeb96e989db6640
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92e514d139c9fd7b61fd5cbb4ad9f26874d6b1194e96f7f571dec62e41
+TAG: 1f8bee58d4581f2efdc7cf1fa6a886d62731b42d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92c18cdcb45866c1724821b16527465b9be46eb8beb4eb8d62853ccfce
+TAG: c82d1bcb8e8909b4627855090c69f893a7831513
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92b8ad58e0bbbd7e5597c465f7270d9af05ad36f5f76fd5061f08f34db
+TAG: e778b92bd5caaab5109c086deac8e15c0b868f18
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92a0f0195cd0f73b8f88946472773f155ae53b33034b6a2a0f108f5f1c
+TAG: 84d8f41a6c51864d3dea30c2d322628325c557cc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92a6eb0b880df4753ac6da5987e88a123a57226e9b090c7fc6220584d5
+TAG: bf51cec0b8c6177620f4c93dce042fc9bcdfee76
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92ab54fb95a50b74498b5db0b584755042ee981de9281a8d9f2be54941
+TAG: 63af479763cb00ba393684e22d1ef4add8995396
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db921221944be4f0ce28afbfb5848aab50fc23402f90cce4ee7fd28bbd9d
+TAG: a8144ac5e983802b585b7f9a5ca2d458dc6b9b75
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919fd629fbafb1d92f0aa82143a8
+TAG: 18dfecad0509f8cb1881bb6360ba07cd46e8e900
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919fa8d31d615cb4ae02981bd3ee
+TAG: a35e63847e014a27a140f8d1751b7e339ff79cff
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919fa192660b320e8f11ac1ce177
+TAG: 9bb0e77bb820a835aa92d385f13bb551fd3047c4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919fc6dc9120b4922ace3c191651
+TAG: d389df25088be5eb8a348b4c1beef169d65d43d3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f397e733836ffed7b66dc7f93
+TAG: af811ebee1c2ca697be9db97637bed1becceeb28
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919fdefc6f5ea938a77f81aa59da
+TAG: ae1791e3927a9d7688bb72bdac60a77e21ca68ff
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f48d68f55b982396148fbc91f
+TAG: 99c82ffdf60623654cb0f2517477a482609ee649
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f536734baf09c0695172b5f39
+TAG: fa03407b94a8380b92da027dd2599e48bba8d76c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f3b592a300d42d88eca46248a
+TAG: 058321a6005cd524144b314666680d055b251802
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f64a260576e70c596b4ad154d
+TAG: b9392bd3066e8851716b21d7eafa6958b53ed1bc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f5873f3356ad0ceb78f1988fb
+TAG: 7f5cc6e5e0cb8464766225aeb43f73825bc7abab
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f8074a8947beb206ebccd630e
+TAG: c3c63cc856aa7259849b4084123aee30cbc3f829
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919ffd81be722249485378cecdf9
+TAG: 19e540e70783ba69f9c0295dce0689d68c34afc1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f3927a690245b3f4e37cad5af
+TAG: 5457a28547d6bbb5ed1faef989e4cd2859e4004e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919fdf8aa5c4c253bbd5bd69d39d
+TAG: 65f9b90b46406184979599a283a392d1b7704b70
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919feeec7d7b95fa044f5305ef74
+TAG: 06ca47440e894022ea56b089ba8b660862a01232
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6edd634590c3af23946a2698491d94f4ee17
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6edd0b99008563c522f26a2cde729549e81e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6eddcdd8d754aaff441f1b291715c14957d7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6edd7d97517fde97e17c73f625597ce5edcd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6eddef4e9627da3d0ff6dea6c7a175b6caa6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6edd47b56afca50e38cbf2b57dcd59e29c3d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6eddd9e539461bc0ece73d86f57585193474
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6edda61b790380af1d0b28ed2b238c5fc9ef
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6edd39ede85453805deaa568276e05495ffb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6edd74a17c111ae8965eddbdaa103ab5e7f4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6eddf0a34a63a24b5874c16185afa9cf3b9e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6edd32adbc196416fc33299c7649949d57e9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6edda7fabbffe754ac1a0bd9a59bf9068280
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6edd06875c54d96f10b66ca38c25dd63dbe0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6edd854dd4a7c0795305078a9f408ee59690
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae14b500b94927f24ff6a4f7b07ec90d128ef465f4a3645fd0b2601fbe2b0bceae2f890f0700c7a15c82fcbee6ab492908ba5f2df0f04dd0635c047cbe52069d85fcfabe53ceb43dc71c46e51c0e3a9ff435840d62bdcb93341a1624b69397fa1bbd9229814a2788b91a107534b41ed488f4ce95fd2ab46963e4f1a3096c74acc8466d034eeaa7c0f1fe46a4eee7abb740367266cd36fba96dc74e520f64b9605c067bef516f517f99ec73c1104b43bf3e94eadd7dd6b9b7db847d6ff4c03dc454d8edbf8f694f09754f249fd1dc0bb4b130b2e43ddc1d24a0cc14edc8e7328515cc8498ae89beec66127508676fb04db92055abf2be22e0c2a7a3d9664e17d919f655ffaaaa7246a0ea29f9c42
+TAG: f72b6edd6affbe256e0ee4c6446dd4748393b4b5
+NO_SEAL: 01
+FAILS: 01
+
 # DIGEST: f0f82752a691ef5866413f2b2e5c1d0ebb41ccc8
 KEY: 7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9
 NONCE: ba2fd6773e0d0c302a5f47e037446f58
diff --git a/src/crypto/cipher/test/aes_256_cbc_sha256_tls_tests.txt b/src/crypto/cipher/test/aes_256_cbc_sha256_tls_tests.txt
index c614276..6aed23a 100644
--- a/src/crypto/cipher/test/aes_256_cbc_sha256_tls_tests.txt
+++ b/src/crypto/cipher/test/aes_256_cbc_sha256_tls_tests.txt
@@ -23,7 +23,7 @@
 IN: 936a91d0b5
 AD: d2c0267218cb7090c61713
 CT: 5485a389637bd49a1ea251ed03f34781
-TAG: 29a62964bc26d5d16c69be13c2e657f1b36726df0f322286f368847fecaa5977
+TAG: 29a62964bc26d5d16c69be13c2e657f1ae0fe30a3006727ffecf985f1a015f16
 NO_SEAL: 01
 FAILS: 01
 
@@ -38,6 +38,2588 @@
 NO_SEAL: 01
 FAILS: 01
 
+# Test with maximal padding.
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f80c9a62b7d1ab8a5f2b6707ea4efbefd
+TAG: 2bd04e535587a7e13ae0005e1e3401935f424c2eb7e27e4137135997e26957d6
+NO_SEAL: 01
+
+# Test if the unpadded input is too short for a MAC, but not publicly so.
+# DIGEST: f1402641d69b3d67d63e5bd137ba006c70582fc0ac760c7cc005f22b69aead4b
+KEY: 7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e0
+NONCE: 37446f5891d77df660ed82933f62be8d
+IN: 
+AD: 936a91d0b5d2c0267218cb
+CT: 38cfca742f83fb066e7dc876b8eabe3f00c490a64e481d2c27584581e60afe513de900d7f621c74d6bc2d9c1e7167cb059b92c23169af02cd28eec3a26e35dc2595b4f0730e7bbcbac320907dad9a365f274f2c8bb60069a5d7c88ff81a5f1c2d320160b639ec8c9140112a3b93da0bb9b0869457b9bedf603453cb27ccefd6b0a17ffdb4651ed2cc893f0eeb718ab91fe045d3a081d72ccb95993968cc216b5d6ca80408e96cbd6725b27bcddebf6d1a008dd8abf5ac82090d027dc1bc00b2da5448a031318a404d0abc2013da87388aeb8e9c574582dfbd791030d0259d087
+TAG: c6076469cad196ac83c588c9a2fe79a5144167e1960291e84589991522b2d93e
+NO_SEAL: 01
+FAILS: 01
+
+# Test that each byte of incorrect padding is noticed.
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc917a6180879a92fd56e6fe812fd87c8654297c65f3da5a76a75a36a053143ae08042eb2ab6b5b85f671d7393885e9524e09e2f9ce7593b6b7ab6887a7074e20d7c3466b038133777ad54c901031582066ed9868ad3f86fb3eb2708162e10c8551f50c00eb379daa47a904f3523c71e94cf7e0138cff860172c59e7520949a301fb732329fa6eaf6ef71c335c4b4f0437da8c5ab70e429c454debb3cc406f7c8880791b8793a154938ae47687424a6ecb1c23bac05d30192b6aeabdd69a8a7fe635e46187b2035b253b8fdf59c01cc2b88d1e166ac5f3aa417bf64e8d7a426d2c8
+TAG: 1cb725c9132b6518ed220383b41fd75851287c1241c0cf85908f1422c8dd4f83
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9323075edc5ff8b59b7a2a1f8edb3cbb76932e60429a0dd48f3bbd9b3bd554132b8fa5c52021e2143bb516f7d926f4664c4620522fb6d4d7347fa85dd57b441b4233ef363e602a04196ef78da6016d89e1d7fb55f825f6c7655d560269159b6aa5752367f4756899939f7892dc9cffe43e9dbd388478e5d3f53e5df97c9772e5366c4e389e7f89cbf651a76f82f5eaeaaaf68c0bb7543d3e9a478f0983000a3f0825777da874b545ec14a3565e101da9e7e0d18fbf4eb2282dc6a103535c2cee7178177d4448d516e7b120f9316549373421dd967b91b4566aed2655a767af304
+TAG: 9d88aa45fe31174536423d43401992c702ebd91b168864e6dd0e621f7ae94a2f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9ab3d5d0ac427251b020416b89634ea06a8a72ae283e5d44a7cfd1b93295222117d9d704d39e9989448094f0381ba0b61fff8f73a0d20b24202d7a0f63657109a13acbbf710187b61c4faace569153e84b8ae0c1f0d97755b69337866ba361f6970de6338fe30a3747a6b0f87eec609b7a601509474271ae14118eb52170c447e832119326df679e2041c8876702b0a941c5c6a72a0331ef5dc9fda6f05964f4c1ecef88b3a42d1a7f7f254bd26c08e464c42536bcbff248a21f89f5cbf4dc2b6c4ad5440914e3ff348d57961647d0f0784d4ecd8f9f1d37422f1b45ac9afa5f7
+TAG: f3559f12ae43f4bea013368bbd7e729c33916d81db8146560a296548a81736ed
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9882e3df031b128300de14ee15b44d5aca34eb42cc2dcccf8edceaa80eaca2a78e9e1c55f28dcd881e52e8c49d314b2264496426f3341deca30c4761a0264030acc18e2150054b294b84f22ea75bf07b48cbcfadddee7c8b0c44a9a8ab169b55f7980c420d3ff86ae81e26e50d32b6fbea1a62ee91c625eb3a4d35a1963391d4ac91bff58507e1adbaafba5ccc09c342c16fd6c222ca7d63d358b3e31fca2c86b274dc5362c20559bca62c921d6466703b82e4c98d018804f47660c40ea3eb2729e9e89a6df1e386a19be846f003bced63e85c6f6f2c6a807667909c383b16a2d
+TAG: 063b3718958f2e03fce950ef13eda7c67b9a5be2e5e5e1fc80fe97751eae9176
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9b769468968785c725181f201bae8cb30dcfe83e6a23d74223ab73614ee123aa027cfaa303f71b08191c37b2ee009a10b3ce6f88b5f9d3525d926261937501322a2d5a02ed1cbdf3af78b12cd42c72d2c4bfc56e9f6b5647c1366e7b10985c0c0abf14baa101c8998e0be1a0a79d48bf8eb66165a98a872b8297384c9c4c5cd5112d59b240bf3165e2514fc581713638dcc31ced7971199e3e06aa6885394b8f8bfe9fb8caaf32880b09153275b6ad9459ca63ece75b2e6443ab219208bd86f6cd7c7c99e4fea638f1940b698991e8c1debef816b89043f3a3b24d2a5e022f819
+TAG: bda3025ba41e7674934fbae362c558f64acadc94e8f4a253209c38d29f1c73b6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9b82054e6ea71a0de5405c3564aea7c2e9273fdb79606e8379e38ab4d75733185153fdffbf8a666dc47a6794d1f198ff1947f56f39d37e233eb69639f1656f25672e2177b6e583b3fb99146ceddbb02c0d33e273c0fccaff79c4bc0092a262401b96213cb8bdc2ee13ce0f69cee9f2ed76123fcd01e2f7a588daede98d3550b8ceaf2bd14edb1b407f3d54dad1a9827b82566ef52f2ef6d160b628fac6eb76236f102db9b77050ef951d4de4ed495a214416bb21672c842494ea6b1254471241a7d5547e921c2179b1b3a89219b76f8205a5eebc5f72d8c2821464b801fe4a38d
+TAG: a96efeadc06028a20e0c043ca15241d28c71fdfaa94f945ca1f8fea03f61c490
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9babc6452a7dee3cef67062c396538a9efec6789beb3f639a2d456392344e764f02328f3489687cc4f4959b1af011b1c0fa55bea01522874d9bec3fb4c1f42bf44e0c3239193fe54402e12a7cd11a1874857ccdd857c95701ea25a8961155f7452d7c494f229fb5a1d2f22404d668a1e7caad97c969b14c160d1fab50d6b35c4efc86eef948c2c7a89e8f8c31151081c1be7f76b804c34c9f9243c477fda43a4ea46ab375a19a85e3570885feebcb59f6d74d10338b8555095e9f8b70394ed84e0d26704bcfbe19c9943a0665293abab55ee5b7c9314d36c43ed2fc6e6c7b7036
+TAG: ded1e929fb49150b4c0c365f312b800083e9ea0f617196e11fd8e5f80349fd30
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc907e973f1e24f3b63904a6790ceb0052aa3a512b524003267bbcf625dea0b0efab26c2eb35ce583151299aed15eccfbf263cbce9b7f8d8c19cd4665010e8c2eea911d20cac99b9c869314560a03345c7b39577f15e3bb44bfcb45f1956c234dddf3aadc06befa8872dd7bc22bcd8fd1fb3416f2b83d585c78c3ebeca423b1e424be7ff77bf619a7e7c3866656f71056329cec17f918f5515853b626489d203581ca3ae673a8205e44d70e4f49f02a8d6d44b799be36fe473b5c6afacec88a94f17d0408cb41b94192ad48c634914249a5b1a8310679e3ecfc1d7a968536abdb75
+TAG: b42f9d873e66b0135b11d55a7b3ccbe9918e6ada2ef01e41503dc99e4f7e5a58
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9580a623d8c40bfb803943f7afaf2bc1c715e68ffa24c3cf7a3a0beccbbcd2a7ad3ed46caf1584862ff2725bc5c8d4a5adac4d277ccbcf22bea228b9d0a003913250764ee192c5cae96903c3eee5ec9168836222d91e855902408bdc9dad1d6519066cc3d1b1f7ff8366bb263357fd8917ab1cabb948285c765ba4717b2d5c8fce467ba5676203ac8d4bb0e7e0065a414d3b45e3e9a855940045d122f7bff770f538b5c7a739b3f28042a3fc5eb8570e0be08405a3b29f3b609d6bf27979e8658dc24de2096688b5688c63b1cd842d003150c29c0fa7e39ac6c4f2058a9346e53
+TAG: 68db5d841f59c16b38ffb5f77e91fa1eda42342d9e2392decf474056c8bbcda0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc91b97d0eb129bda9b69187ccb2d17c0604a9c7b2e23e4d10de0dd676485b16f8b371ea961e7ce029a25f596dec5171ccd7279feac323f8c753a895b5eac50521bb5aad180401e5047f005d23959db3a3d8cba3bf424b7a39835c694a0c8d59e8488e7f2b8c3b7ae53584420a92051f39b5deb36bc32a9bbab1ce796aea96e5c0ee6d7aeeb1cf49ab4d4f8b95e01624be498a9a29e8f7731056d2357787ed4f810627962e73381b788d9dd0c37fcfe70387138394356b5fbf96b3dd96b0bfc8d376fbe915a6764c5ccf0b07be67e59e0f4c07a7068187e6b72d5094c1b30eed280
+TAG: 1762500e5a03cf16fa875e1eabd755bc351ded0418a479bf09a313605cf1e7ed
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9de39494765a6219ce699571a186ec25e33c1e9678fc398a7225beded3d7e3edcfba218e3a5a5ecc2d00e4369af16f13b79c933d8221ee94240a542d64d29586d6ea07092399879238ca03ac9a0decd0e6b96ce6c1e40440d11aabdaa70b3b0b9e8357533d1e4bc996cd75b6e8530dd5ed17ade5b2563df7c032df529b420543af78f61cb27b75db0504106032bd570581daba567a6404c371ed921c5198130ce518d69081189250b9609e1b7cef30faac1065fbf939139c424cb61b06a3c091bb6bcdf9868183f318e13ae3686236dcd80e6f5664a337204da100ff1e5e09f4c
+TAG: 5ed18b1fb9e2145baab7b25f527ebc260ff5d3f2eeea9c80fec998517a6050db
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc910fc53d1c97a3fb1f1169dfc395923d794b681c0d7f40cc9887a9c06e39dbd51d7f38776036f2c67ad7edf44429dc32bd0222e43142417395b4fd0db73f8b684e4237b91f093302a457873bfb676cd377f35504a515e0b2477a4958e387100eca6816bbaff2400ed029dca27f90c4073a836c57f5a5fc0568882732a8773873681850cf5f39830a7dab9759844c4f623336f7724e1aa0c7b710dd88b2b3689b02aefd02ba94b89b60d1ac94186ed787cecadb39925ffe349d8665fc297f2d3a094a07db73c64b7edd2831ccd01fa041b0f004c48fee0c2a58058088babe13d05
+TAG: dc52ec31bf5030095e64326494f964f4a97c798112502d794d5d751a0eca2bb5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9d7ca2e9b03428f898c60a9ed0bead617baa7879af99cdbdf7c54bca1dee3241afe1037c090ab1c1c9cf4c760e30dc759147fc4683e23dc96a2fa183eba25811c635703782f878d7b534f089349435d270b72cab2fe481b45211e8e46f9f76c12e77029db6f44dd02eccefe07b174b57a5cac6cedfb80e2682489b3d8188af49548ceb084952acbc1ca15f425cddff6fcaebfee356f0280ebb36478531099fa155a39f0e8b1fd1be475490fe1989a15867ee31396a6750e71d26e379a0fa645a588fa50a166a4f73beb1ddc80303fc58a7d8412c711959dcc824c3d8dc2d499d1
+TAG: bd0e2c7cec0a6ae71edb20049e6c8e96c1148f027aa2e2f52a2068408af7c494
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc91389363709a5b80baf8dfed51a178ed2fd7f52ba7846aca85b262a2567a4b2a5a24a76b205ae432313b337f5a109f70ea786ae117f046e6bb0ab332f75d7c9d1aac795069e61522a54c5cec1500c8ab24c48f425d68e5398a076a4804581f87b0d043e67a3cc63b6ebd7e24248ca41863ed9d3e5e7492c43fc5b0f50d9f021c762073d5d1c9530722e29d31b4de04bcdf59bde104166901d13d75b43e392a5473b46325112ebec02d09f60cb89835f6db4683f49fa88385855f611a7df704236be932628c0004548ea3adbb08ff0bca61fbf291d0456b4c711c6bbbff2c61649
+TAG: 72ab77a3fe7fe6834fbcae26807f04254f6d184b5c33e606f2fe76100b9d2391
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9a0cd713e40f34e15aa6faf0eda672b65028545725295d6853558332f3aef86a914354b586f1590b4d935ae2f13325c8f25e50e1379cb5ffd10b641518e8b3f1f875122ca85fb7ac1fc21ca06a4c644e3175f32f5c5dae67951f0bb5aa2a925a48013d992a1961104e349e4fe75dcfc6d27ae7612e6bf04474154ca06c266f5cd5e5c36b005dd59fc2ba24e2f4125e32fbbeddbcabb9bfdd4e401a0e5d36a6c35e7a8ad6b3efc72a8621d5e8fa7531aebea41cacf14907ce38dfd11172d0fcbd8343fe0d11ec6ec0c8f332a6ba15aedd36fd7fb2ed890f8a72574efedd144f654
+TAG: 6780df6e68303aed0928627b2b8d78f3d46ff179cea462d79504c2c074f80169
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9ecba9d99960b326c04452e11cae5709b9d0b7a73045a2a0fecd2061507731e6ed390c75fad87347076788b7bc0220019696ec5d0a4ae4d54992cf770dcca4b4cb836dfa132dd35a7180e069e48d716eda490ac7c5b65aa282aff4bf58c7379ddd82be67f7d0cec543aea0df51a95da1923dad84a78f5a17f04fb4e69a3f90d5c0fc8fca2dbba3f38764df1a40c7bba8d6bf5ee550a042c3b6051d860a5ac84febeaabfdf8c53ebef3524de23e7e412abd9b3b7de1747b71ca90436bcd998436071e756ea63c117c873fe43c438c6e9085a08e4cf7acb8e06517e9d0da6fa4110
+TAG: aa728733b9bfdcab3a0417d9eb41ad114ad7f13c0328281414b980d866185e4f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fdbd8224c0c77c669258f34a280e3e2a4b65f456e81e7eefea5dfa4553d5fd5146e6584e6468d9e7212a2f56414ae939791f3c853d6003ed0dc85d2d494ee73253ffc1842950d38b9f27bc659ddd624a27c652edecc761f693be00bc4e3901c2d83ca25dfb50d735f21b629cd1292071eb792e4a27d639981a2806cbbad47b220abb41480ead0927dd6b7f3d2aa14cfffb4c9fef810f27308de44e82893e26f831f9e509cd2545ea79052ab4b640e974a8c7c771d31bfaf61fd587078b5c9220c70e10264646e02d9f54a270dbc9d9252d
+TAG: 37cc83231a20a9e40b257ca67de70a95f4083a62d4bad32a1f55967f9df1c80e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd0a266acfb5a43cbcea297e47e03151ed95797671df0d1a4e8d3c35d0875e7487052f19bd1d5af48a930d98474676304ed9276a18e5092a5fbd289be359a35caa43fcd5c6e53cdab3ce6ae808dc2f494d14adbb277aa1b2e801823c7f5ca0017e6fcae75dede4b34ef99570035f8d00befb3895a3e32505469d599f2b5cb7bd7b8710bf76e055416360204d54068216e0492d060d9a23768de6052cda77964b0428684ea19f6ddae78851043b975fc493f31e1f3efa540069af67a0a058147685064242cd84cdfb480ddb456ab7cb0e8f
+TAG: 77d3d283e8253621b177168ea383efcab5a2e98ed3dffd075fe332fe3a9dfb88
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd557a1ea12df9dee66f74163b4e01004bba8582d52623abee5cc6342c833b230081cf5e4fffec8d097f022e1f201bc28baa24e48f6d35e11951187c709605e32ffe8638c7c42fa759561a2df26bd12bcff6425ae819fcc6493ac1f0d85435cc655059aee4e1bdf1e588a2954afae3d7d15f0adf6b91d89b728bee01950e9c9d61c7833274777512246d05bf6bdce5e025f9ba0fb526c211fd6555c811d3b02ef47c4398f5eea1f6c0386c68134d895a7480cb95ffae0a5880fea57e2e6b85a0af56fa6336a8a24af6c4d13ab8f0d1a4d0
+TAG: 5162bebe83ed5119fd4fa65ecc6c35ed493661b5df6e6081455e047ef4f97df1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd0218af529843e9b2548ca2aee73f3e61cb8589d0c67096390c54833c19fec8452c8d6ae07e6248da358b7fd99884cc804a1079e5daee3f58a4df6ab0bd9214ed5f55b9a7410b8f44d3258e3b195a04e9c09d3ae288c7bb3f224fd0889a9a111cf0228d167163a7339e82e9df5d51feb13665cbcf8faa650b21218727d8f73173643f6af60e7f89b28d783dffed32f6d935f85010f472e4f09d4cc2f0a6886afd66704249f8c12bc4ab45aad9d3470483e85ca0140903aa2bcdffe2e29a0825c21baafcb42b4689e2406dc932b9d6b3ef
+TAG: ff27b9009c761b16c60878ca83bc5c26b36e23c562ae8db6c13cd5e45ccd35a5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd3769c9e65fa551d484bc9aa5b9e3dd93668d306438986efba0377b6ee7972814abf4b87b5541edd4ddac0b9098950a90d7bf35bd725d596119b78f6d14c67ca5e7afa91810e1fcea552baac2b51c8e46baeb9d95ad8a8097d7bec0d5a5b7213cf41d8d79f4f921194627b3105500ffbb1ca413956f7fa186e9a14e8a536ea48979f8488ac0b9a098dcc67e46dd0b9136845e9271d620c7dd3fa4d220981e6f61808bd4f847cfba09102f8ab3be5a2030595f6176d5692feed4cedeeb39985505caf3efd8d56f3d3f6db04ddcf3b02293
+TAG: 1b6317c6e65d0ed3f4555a9d7ccda105dfdedba648601c3c9852cad5add711f9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd7c6409435c82b69543df7f0ef686e69e93c2b6401124e005a6a92bf24b2f6cfd353ad806f35d5047806f423c5b8a8761802b8afb76bd1f5812dadee724ce66f2791f80bbc7c00e477deb4c1d70a999c0a16379080366b8211771eb665c0e7ee6771be668d726c5cd42a846b9e30adbccf3a72c30080b188cd02a92522b5cae7747a83c3bed509eef65420f9d54ded12b85a5d87cbd2e6094d8f4e82403e27a53d6161ea9b2b5cc10b3cf29a79999ea54476940ec02674617e17ed72c979f979fbe08bcc4bba1f871c7f726407ddfd1fd
+TAG: 52fcd834ccde00d4af4264c86f28f1574eba618cffe0d4b1b5ec4e584551ec3b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd7dcef6c378f4a75f34b14f6ebb82759ba40743265ba6d8be62475542cfbd8a71f68de977bf38db65da56a576566ee550f19214ed39c33b237fcc41af4fa3c59af4296c316cd505b92647b5725456542155a61ca86b5029d12efc24f6501308f86e23660e1efe6ad1b178f90886b9a8f74c67fe85ebe778537f0ae78e408eb9f9323552a6fba597f520da00a8be587b5ef98e1138aa1c4e432ef123d974db65d97f3c16b2351b44f4f78c09257e6b415ac6527d79f795276853db7e5cab4ff39f3523029772d5879baeb31287fb964980
+TAG: 69a9f54f5005f82afe650509d8289483e69d2cd4ec8319cb24ce17285848fe08
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd1101a1c790700e7902d3d2ffc090a27bf86e2c37926ed75abafa1e62ae95d13771657d1c7f16deb5b87f2bfb6bb8563c8b16b0a3773e125eae9b13b5dc87e99be42a9e9ac8701add69249ac537f11cfc4374dadde8de55256859ed4440ecc2a4342af8466714825c227ffce76ad0e29a9fc7b5798fd74627a89ba97b4251f8b202d974a00f1ce996cb0e8e760e02abd963c3be73059e1be80f5abddba1ce997fada620fffe9d9694b886f490a084a71977509514d63b606fffc38cb0b466008a5e2ad014d7829a0bbf3e6d7846bfd3a2
+TAG: bf34d7b2878687ffacd3fb28e5a6320f932ffdd4b5c1f370bdd97e169df068c9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fde8e00a26c29e40c0812cf99a3d6c2c4de1693a12bbbe6e969418e11902fffc82604df87daed66f0c74c505b8c178d179f6caf79e9811b2caa79c334dcc5fa2ee4cd38177470b645369aa6123dca5b826e1878b93b64d80a0bfb8b8f7a853b0fee46fed3c698a99fbce0d705636c777adba45501a587845d5cb317bc6ab928ba2527f521a15562f61700312234c1048b58f520fbfa1fbecc675f1efe8660eb2197c6a408877a8d54ab5d9b7eb0029cd85b330f8e9725c9f807f41727d0a3771399ce79663b6887952302d959d99284bb2
+TAG: 3cf91544f623ae3e166179d31015446ddc0dcb76ba77c63457272d4deff73014
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fdc083195c8abccf0fbc586b660b0acc2f637ada29bcd83395af50742283919d43883a58b30ed714d4678e965b6ec3e5283c0aa676bc8e59ba2141c783db1990eb0f5f2cee4fd9296e9bfe3d44e4e9d7532b073de81cc36cec2f592bf89dabc258770eb3925e8844fc26973b274c1c67dd75fa3c78a9e6d792fdd483b93932ac40d4caeca5beacf2eb7a67f7fd119df11958ed248c290927a2fe8bf8c9291ec4ce1ac67836d3658f832c9266a32c26e1e61764784ae3af301387e111efc6dbae574a57ef68107cb8103ec1c46dd89cc754
+TAG: 8ff6081fed62810a229633a94e9f9e9e1134909bec5335e2075f97fef85ee0ea
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd25c44bffcdf271e10b9f23a3cfcc198556552f1f723b1569b5f23ef85cd9dcca6be920ca7ae2c9f41f3f132659fb160556b07ace805215851b92029b2d6090bee02b7aa9169cfa10a466eae711cd1c92fa9c98ae25606b1422ce7a8a2bf06015852c12b93d61552f3829415c413a704861503c2bce62b4fb75442dc1ddce855505bed3e7433d61fa002be61c5293f13e263a3dff8698b8956200ea125dee8e675f53b422a3f58c9ff5edbf0a33384bf2c377f29b4a188eab06a8e349564cc9529352281c914a1877931417fbac47ca5c
+TAG: 47ae02a58b068c4a86ea7515c6d7bb4f70496fec0d40eb47dc9630dddd2659b0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fdb1cb88228b053edcd741afad8f292998db44f8dc1f9c074430a0f3dc41a1e7a226dee313b437c91d9138acb557084f808be6328510cedfa987a74926178d3709b0f37c33c79ea29b09078e0fb44a0aa990f538cb24888f9b280cd2dfb671b38753e1faebe7e5b60897eaeb904aa49b44e8a9a549e9ee8ccfeb3da4963fb7b6ecef09cd6d886e029e24b5b24156a8bd4f07b6bf1d66ccae1d47b642397c5a9e8c115d5f02dda769b25da3ca106c008e3ad8a92581c2cb47e1be89efa7b7a0a3486f5463cf2c0b03b2e2e3b3b453eb043d
+TAG: 7f6f03b026bbf5dc72144e9f6e2b40a3501401b0d787360987d670b2bbc3cace
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd87561f53faf41156a5abe89f092ec31e9a92d55f9c63b37657577853e0b11b469722ad588390ef1dff09892d1d2b93200efa1a1b89faff20d0a26d9174a679a497b62cf47ce4251a3ab5f97559f6b3c538af5ecad6d241cb8c67e704be1b5dd073e29880f0648aec48f7a37da1ffa848c73eff305b881c07ae94d768e4d7539a316366bc56e9e0044b95de1c1d5abe76aac77eb0562735af24adfa991cda5f73717c7e2c1a6ef5f74eef07b15ae2c2a38ff528c44c6626aac2baa090951172ece7ebaf949c82b251e64f8c8bb6efcefe
+TAG: e04ecd1994402fd81f7d818cfd67ac4ac4b3113d97c5594fc1beeb5e7d42305c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fdf205b34487e8a3f2d5de487a9175786fffce3d898896eac9e1b43cc4ab9c9847b26a3def48cc6d0e1acb1e48f9de05125f06e91b85d5739ca4844e946f9e26539f4d4ac665d7c42be19ab74d979604b1d444672265c6bd9e2875ea24e7bb8e7334740d159b7e50a57484e23258937399509e8b4f26955cadeab802ad188e4477ba1d84d603aee920676e7e3e3d12486f93a873b75cf75f80b3305a6f3435c9e2ab12d133a5f8231f96a8cd1a802168e2d6166aca2442805fc12710937def35a47987de293651e84dbb7d5aeba5de2462
+TAG: 748c1ce64459d51fdb958922fa265d0f057ae7756debba0e56b3fb7acfdbd926
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd34de5285af0eb3ea063af9e6f2779bb18a80f17512954ac8f2a440d18805714e2d4e40d46e876f2e90346755a7eb1ecc71359e5b0480039a2d5de763cdf4cbac0ef36618ca0b951084a21e6e23aab287a8de50455b7dc17b573d60d3a3d6ad723a9a773023f6be6a966434fbc4045fee2cb8c1dca920d095ba8cf263336f21c22d797a44680c6d5b3642b33ebb19bea60b212f610956e71048dd78b43a9479b0cbdcd34eee7e7dcf9489b9b59c9527355d78276d4a738420ca42ac38ff8a2643e19d223d7c43a837c952408929be28fe
+TAG: 0350885d12343613e2af983b4bec0dbd26314fb430755dd16172a86242c8dd40
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fdaf6f77b8cba31aefe77237f3a9c3189d13e0d1af5e2b8398406f5547700e89e0e8f3b8bf4b89f83934b26e46189365a175318c397d1f3a0ba3b2e84c2036b5e71ccb4c5ff1fc484a08c98df341169fb3b841bdd451bdb2727dbeba546a170a56bf2ee4e66ee4f3307c2c4a4dd97c9ac2a402d82e5cc915916bcff56616b8d34a11a4ef0693bb5dc7d0e68d09d5af1f701d8e22abfcda94c203447af6b1336686aa76c08e253ee812d50f36d3bd29291f53dc0461b507620729cb3395dae5563680b8d710f2bf0c734011bbbc7de357cb
+TAG: 65488cd66c49a4fb1eb7c11657bc6df961525b55731066a1d791607a6f9da587
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68acf2cf977551a77a71b2e2c7ef3016f3cdbf75e6bbf2470af052f469caf1e246c5a1f0515764fa078c78b8816ee1f9173edd30cce528340dca5dfb5042a916d1b93bf857cb60bfb627d45521486740f14222c05084af131594834e81e2a39f923f5547c1a89ac7ac93239370b6e589919a1a8be3b77c395fe698e8044e167496fc53bfcdc929d99c50e043381fa4a6f431123497259c5c97eb7d90ed6fca6f8bcd8b257c2a7315757de38a3d69bbde903d584650c9aaa471e5ef400bb15626701
+TAG: 99ac8c970c4d2fc3ee3474119edff129418f32e655844f831471005447f76544
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a65d7e6d7a26c3cb0e9f41d6ee36b4633b516e96dc66136bdbbe301878d25477a68303d07542bb30f261a21842131b09d9d85b0f29acb62261d79f3ffe9cdf372b70868aa730e2a87ca7f1bcdbd23082d4ec8bcf551ea8153d4da9a6cd15402c971b7ca2f8ce68b88279bcae68a463c071f5ae393c75e0812ff5a023fc01f1a9795593fdde874e3feee569a9bc50ac0ad5b1d3af05a8f41169bc76d5eac01db0dfc1c09168e09aa72ff2ed89c53100d6af5ab55f232c848f20db15dfa26564642
+TAG: 3db914e2cddcec92af05db68c0dd28eff8db9664c8de55a29647235c961b50f5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68af8035ea6ecab9d4d10a75018bb2b5588dc67fc222af0445ad0884c9938a6679acae7693e880d432033d98dee458e2829497c2e378fb2ac40e9ef5a7912c7a658b886fe92c497a08f42bd7ed1fe19b7967aafe4e2004ed03d0319c1e03754b6039b7ea7ce85df321d176159d570b4376a5fe709f5504f2aec8684b5e37e12820548b8d0d13466c4cecfd8b6ca4aff09cef13e40ad723c2b53374467091bdb6cf006afb20cf1ea5b474c25987d18020174c9c1a0377e7bc78470531c3bfc77b9f1
+TAG: 143b8643f7712d7125bd98ffa40b85df3ca2e83380eb5241a5e479d5f04f3062
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a816ad45b7c7917f7d2c2d6ad08ee402526c22c6dd938e6b48cd750c4a2755e890f95780b548a7da2eed9785ba90925fdc28cdbf0a5bb12575883e8e419a00ff07273d15f95a9c3d2a7ac6ac13d86865a49974ed3643a814b2e3e244397fb8a7ad3781ef80246cf08bffc4c9b09205e8f7dfcc541a8a4122be57a523c96397616a0738c5e587264c1dfc81af83a388eac19913e327983401ae75e060f932cb450f162fedddf243f6ecdf51e89d0942bf72f3e672e648126764e87c2fb3ad1f592
+TAG: 299771e1d2a30a7ae0a520f0382a5c0699fccd7a36b4653e75129a67bb46eac1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68ab0f8371f6f2002dcf476c274ba2e0ab3781d8dff5e546e5b36721f411a8f82c42fa00a7da5baf1071aa3d260084dfcce32a3d24a5615ffc7023093334e85fd3c1a5cc8fedf5a1ade5dc9ee8cd125ea1f5e12826bcc941c0741be0844071a8321a38f9296aede81b0df26599201ad787f737a58cb79194400ba1351e92c545c2e1637d1171653b723da491522bbe1c94a6ec55fcb5a59fc36d2d40d0298990aac98b8b2d9ebe7bd70393fc4cbec421047e59e28eb686ccf40e85dbfc90a8f434b
+TAG: 3de0a16e357ca3a02fac2a212ee2dc32339b344f288c485348f3d5062830b60f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68ade86510e6fa782f4ae9ff47f0bccad0de1a9660400d5465bc3fb035a8a90b71787888dbe51db0807a151b8c0b8dcfe2393c74a1d5b8d4844f4adf8e4fbd55314905de910123e1a2e30ae1e2af0d92b9b57d7d7a8a106c250610344856c3803876e2929981e339914a63bc4ae2104c9b0bb8ee0caf67b91c794a628d247e93c5e8ce75b7cdff2205772f588497137b05f6cd066275a09f0bf71aa513eb0808d239c88c2c159ada8bac7b7a93edfcc925d4fc79ef6858a0fae97a014a92efd1d83
+TAG: dec65145ede55b84119481eb116e93e3d6532c1949e8babaa665b6003e838671
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a8fad95e706016664902b5f5eed6b2c09073babd3c8b901214e67f533f4dad19e508db33f9b6bc3759e42bbe693332e2b1d45d3f35de64cfc18d8695ed3489c7bb63ed5302f4225cb432c7e52313e58057e0a5342f1bf1c02791c1890eef4cbdec0d656f27cd56be0e489808ac6a9c9fc5416f1a7f5d73a2fdceb960fac64e69d512ad626c09d694bdc86999738723e5d825ff878649afb05e3202deafc7522326de50790071f7e6a6aa578850a11e8fa1ab71c4ee18e31fb4f5d219d278c2e9a
+TAG: 64dc50e6357fe6fe128119ef3bb854a7dd4a836accba5aa641ee3b48c04c5782
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a086b81a161883efa39442de3d29e0fcbea7fbf858756f9577ebd9c05641a52dd2b58eda2bf3a7e6a07748975624a7e6d52a389c5e72b999a927fd1abc324c7cd578a22f0a8f63caff74bb21ef2c169b5fee826c0726a24b8d9b6bb5aa2c272e605ad6d77f6c3a45c60032b9778f1778e6ff791c87d823d0457de4ad34d384cf1a70430ca43a9b47d9f6af89d21326ce10311ab498511295b053d151bf31499d7eef496e6825af94c120a7f2af5d34be6dccfcaae3bc184d59b09ea632900c396
+TAG: e5dff476e2012bd8510b969f792f7ec2497f4204686ba584ca58f67b02a8ef20
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68abfbe919ea236d7c77dcf03057d69b37914e1329a3b793d2137fdd15ceba9586161c3d3ce7cc3a7ac6721d76a7d1087778f76bfd043548db2da8be615feaa88833444be6f9d271e41f2827545dd90aea0738256e766c25086d9eeb3d5683816763eb375e23390618c4f3b53c9d036c40f4f526c476211d4c1e98a8ee852e4196b4c12cb82bf299c1d683403ea11ead62a22694ee1f3b9c1a2e9c2f96ff5b18d1868096aa0183cca1b03665b7eb33e8ff534931e1e27f9b181ba6cfb94911fc6ae
+TAG: ce91aaf74e4de5d9485d9096056746042e9790c8bf0233e367745b47897ac33d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68ad7f10e7117f83007ff978fbea06de256f332b403c9c929f684271e6815e71d83c920736687122a8c6048379f720876f72e3a4f40508050b7ade8826e9ec48fbdff4a21fd3c6178921d2706e27eeaa61a79ac6de819ec579b22322197bfbe57cd12e7fabcbbdb65696a753d59d45fa1790f01e889982d75aece33eb21b0e02f16660b0a774bebe0de2d436b8440e5a631a35579fba6936d473bcdd58024866cbaf6cca756c1a1ea404723e9da81173f8e9cc127dc6341d5c5cf056c23f9097d25
+TAG: c0d71fb809e42848dcf16b674f058ff6f980d1f3f2a3f979a0c44e859dcb6913
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a8bb11f24386fd4ebc10936e149de18bea23dd66107e601250a8c8f10f520354b200c7ae6b1615766d19e83eb60c2346c0cb4b040202cda27d49946ce2cb03006e93fe0f6ce18fe910c300e18a0f541638fa52596e479f4a20d6c41df989106381884930e21a80b0ade34af5efdf819c67f005f640eba57f5132741ee111a4c467f57e68594cf69840869837ce5e6a12670d2e8840cb162c2c69538ff0ab7ccefedb83c72c444c7892caf6e235a545cbdf13aacecf6b0e3668bf1759e3ab869e2
+TAG: b8ff05a75ecbb674e6c668371e997837fdc53d3a008742531d8573cd29c961c6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a573dea87c7395074c2f302b57f9ab34eae349a561be990199c7e0369184eddb03d14e2ddb691dc3f7856618bd8748b9653f6dc4a32566f5651afb6ffa2c366cde29f3558503107196844691718136baa48cd7ea933c226d64696728352b2fdf277b59d92d9dd959da0295b401219773fdc43522a5e90b29e19172828e07f13fbbda2b169bf165f6fd0b884a071b3071b6ceb2a6ae64769de9c693f54db085cd8db22915fa08a208a8737ec4a08e58865cedf9e15d35db16ffbfc3aa1cba81727
+TAG: aab283e4ccd99469b7877190bbdb49448d40d62fe5f7e81645b443db19a97d1c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68afac890a9b29c6128258705a958ab895de2b736db70a799c284f8b1431b7d6646161ac1cb9a612725133eeff07a8e53dadad3deaca171b069cc6b98cb2e9f770b628eac151fd99fc53f9e304c98ccde6302cfc773fb30b253119f15613ac997cccb7b40a2f7905deff2947199cf69b5ab9c8df5b515323980cd73e1aa2b630a1f264449cfbd308d084f02cd37cea0269e0fba0eb361beaf607f84ed492e897fdc394708259ce7a90c240b534d1cb5879ab9f3c9ffa52ee1e4b72f72163f5fa33a
+TAG: 29151f5a90f827aea357c61f1b46fec4748f3539c7258ee824dcaec9a26f02f5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a97d797a6679e2679677138bf188d7223cae4e449f7f69704b11356d476d908567dff807a1ce465ca3f7a1429b21549d587df50ea8372c71817978c9f029f5e91ab8f76ff61277b120f6d8930ca2797cafe0a408b5314004021cb6be3326946a0f4390e792b97acb73a83fb8b4bdc9b4793615cfd97de375791a5b06152a8e78650a0f581ce4a9788e2a154717d499463921365b3167a2d8296ca744633e1afa0140c0441878f54d0fc345712ed30d1c3215a7daef6a7b6eb93ffff64dd75c1ea
+TAG: fef65ead8c194ec5c7b19ac93f148d7266955e193fe4724a19c7275cf2f730ac
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68ae54e9ac170784c5342808b6c23002cd2f356a9055c7f0e00e1c20572ac5034b3c4dd01118ea09fa9bb0c23e72935526a0fc053596b4d8ea2d7fbed60343de09587c8f601d89ebb5c381225318aeb46f918fba73c84faee6296bafbea7c06ce752e639b29ee9aba97f3478b0346e67fb53b3e0f929d162fb905831a5974a44314363096b677e56d3de6d8da1bb211af0f55159a35acfa998b0a3e07a624018914faa24bd925f4f83112a49d0a8f71bd39977a9a43b532f7c9fffc2030e485ce42
+TAG: f1580bea67c85fbc521cafed2afdab0e5cae84be033f7b85c3d42643cfe8f617
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68adef97093c57e218b0a6bc73a85f79a6b7a1c2a57d3033f483e433d4352043844db0009164d46f3d86e79d23d66cbbe237d794c3f709964b4a97ad43d25ae12a0658dec0fd1acc8fbcc8dae863405bb20e62920c0626338bcf2c75917666f484ebb83ffd6b536cf62557c25a9e54cf8fe1a30d5762873016bc9aef019633ceaff9677feb9a5f30feeef22aedfb3d08f4dd58311368344c417a644e318291fbdd6fb70bc01558a978008ba952df161534ee8736612315ec0d997e7009c1b5026c9
+TAG: e158f655200034ae2b77e3bbf72c16f10576755be84fd5a8fb1132a48fef5350
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37ac8fd56bf052d42baa44c2faa58b3a53e977169c6245dc67397846655755431cbd7b757545bd47d54f13214fa167be0c07fe6049a4d0a309751bd159040d151b9b33248cbf5027223c4056de2508821a22ee880accb7fae0612bc469d7c8427b7d60fe23d429ff874719287500618ea7f575af5c31cbcf17424c27bb5d6f8f148e3b0cdb0ef7b41c1eeb03944d6ceae159cd4e5bd922b97e72966414c12e3b4a0b2de4492d0c6d80abed14dbb80b7df98
+TAG: f6f5e6b0474a94f3b01190684c56d5e34e519c61ee1ce8ac512c21681001c9ce
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a1a309607358b4b44e7cfe5838e1a4d7d597f5feb991dbab6c5ebb0f5cee13ed112b745d79d2de3adc3b8d0b7586dabc9e5943c421186df5f9962d4c31685c2305ae333ff2f731e157d0123f95670edf1a559af0d8904e7782848cf26563ad2c9657caf9f984bec0790f3c0e9e9f26f419b8577ac364029f3f584211028c5fa303a3b22f1f2dbdeff74b9ea4797f252d027195327b21acc58532502913fd6bf4365a8fab5acc012a330416c401e40df0a
+TAG: 2529e9ee903dcb8afd6f04ee181c6763f939576c2f49b23f5acbdae18cb376aa
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a8355b1f19ba61b283a97bb63e0a00ebd1e180f88e14ae09ad0d351575d8bc7dc657903f1133711f4919a993857df78eec4b367bcecdffcd127e990297824459dc6bbf6b0e81e91678121bbc9a7897c3e713f9f780588be66fd8b020ba35feceb2b9930075a93e991b0211d348871885ca80f786f66cabe572489810bb9c15e71227c1e0654da4c5a686d9e06ed6acbc8f2403d7236aa7ca9b6c7be8bf0eb9eae86ce3e37858d730c0c743ebceb2b8e7d
+TAG: 93d1d3730a1a7cd15b39d378521d39a9106e3c7b9ba5de1968713fa670ecd901
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a9e69c091c8aa1eb95fc8c27ffd99e14ecf0cf752ff3cdd3c44557337d7f4667229c577974d05a66bd29d6465240f0a9a292c2fb96e0a5d3b1eead706a5bb7f11abdbb405ebe3c212270af5dd43b72aa341f7fbf1becb3aa98f7dee16218f0460c26639f708cff70ddfe9ae584a698d97f487da135018eb3234b2f878bbf0d7226978dac158718e42bf1f434439f145c56869c809bdf1c6fcb8cf89e10de216d2f42c46eded833be089a838a76f109d6e
+TAG: b9ef62a352bb6c59312e37f5f5accbeb8075185d3a12748bbad346509562d49d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a62465f190178fef5aa6a85636e4cd7fc1ac2d33593d4608ccc2d8ebcdd7dda2928d3c6277b13d5bf3d06f6e646e0518b1f6224a865fbd95b0893ae275e76e798086ddc8c9e5a3c4aa29b716f738380d6fc27ab5b30bfe41527c9348082f48ee5b770353b550c68155e29125563f919067d9f83381891ea8886fed5360bf2635c0d83542195bdc44ae959ae71e5fd2a5ab526674737166c3a1d3e3383f8394022bf662bda32474f5f6d7e866e96285490
+TAG: 953841d0986662c98cb7214ab3fb95f784bf44f1073caa0bb2f656c94a06888e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a89eb17f9bb5d6e3355801bed2708bead3d172a06b3d0d63c8bfd905d42d110ab1a1133fcbf0d4fd8d91b7edcae89252a8496062df9171f4451d2237b42a4708db490cfdc34a4712e88a0eee35937bdd969869a44f67474dd1ff804ff187e41cdb5941cf008c7c206d74e5cf9b6de23041cf91a87f8ca72770bf4cecb4496f0b8df1a5aa66faf2cb94c0bfb68ac007982a9f588cc18c9d3502481d10632fd60bab3386558a339a99e53f5409f179a2449
+TAG: ac4d4f070f40475a30901dd75c3339446d3080a01f2fdcc4e98b2fcbeba8ddc6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a44339d1aacebcbf6d4263487436170912e55879ae0718b4a42cdd0f162324921432434021fe235c7f76217ec8e6d9c2f5744e291589ffa0434102a38eb60b92f835334f0bf1dc1cefe9e1ea36f1b070924315658f2a8031d1390f8bb0f5bdbf518bf251439ac8f70fbf0bf450ef8b6bd32219b1aba9b9892ea32be13520cff6ec6cf7564af12736ac8915b333ba782f2433a20944079935c00951d2933d87b7fd1de119ac8a8c59562ad039ac02fedab
+TAG: db0ce7ccd2d197427b61ad6c3a12fc116c63e451c505ce0523414366157d1d6a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a6ea04219e54d03af9e68703709b33277b76ffa549a8229733cf7d9ec88dec6f6100bccbf3d4877f7590c786348eb10a00f74f239d8d53ae953a7ffba0392e3a85cd702ecab80d4ebc4f57a2da277eb310b4e6bfe66b2fd3401e335e7bf3f747b7e3a256068b56856c25acbab2d089c5e9086af411acfacff749a39e51a413c4f14dd1a13a076213f4446771d080acab5030c69198203b2410b6aa9ae7e16696843cab6d931739ee3c6a7b504ee9aeec3
+TAG: 7fda958f70aabf0c8547273336a2c6937d0db669cb7ba68a6c535d2657a9f9c9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a1cfe128dc7c7efd0b5365f3a0e6a91573067a0e6d4e9f917d58277065ebc7c0b66a299639fad36bbb1bdc64fd1901b6ab85eeaee4f3b7f2bf9f1592d0ee0f49e0f103528bb7ad496ba15c099b2083661d429ef40dbb4faae75cf5f23ceee8b75964815ac25296d7667955ed01ca0d9d6c7be8b4952b710722e0f5120688ac0ff81c3b68a7a1139e1e820ccf0e7d4394f6a9518c2f18a1f4c6916d865614e7ab323a051b89b1fb4cc6d0e54704697dcb1
+TAG: d85782ced862c242374b57ba151c8467ca8ddaef1d37c9a097e8dabdbd66b360
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a5572d03f47be1650aea53c85aafab8f3ba148a79153281ae687b00160f86cd3fee68c2f602111fe761a68226b42669d432c3f516fa8d4f1ed5c65fc18c4e7987dc343b13379745e97834bdef2d8537893eee010f9b5dfa8f659be8a1c1cfdfa0dcfe9410ace465e8b269376e0cca61a44621c16b4e3757e78070ef39219098013379de4e6ccc816f99fdd11f750f41b6897fb429f182b9227d2bb5a85909370b54226317e8da8166158a5132b92e0976
+TAG: cca2b0cd811cd74c58e86bbf7e1e94f66b54b5e272fa914311ba54d1267acfd0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a0566980e11cbdc7dac6bf2c31b986cf04e2a775be2be6b1329fb7357e1f32168078716c7f74f290217316fa154ddd5cc0d86bcb645f07143bc5cc8c88735879129e729b93bd897a7105db140f567ab7e6174eb1c6bb7f38740425762d159d3ba69051cd931bdd1f20eb83a0472561127db806717b6627a4f662889ac39bbb8b5e42f9c3ffe786b07724ac7959adf4b5d2d4e103c22df9a8a920591bde0210227ecd977d234aecda316e2baf8c7402be3
+TAG: df72d976eb0645fb7aa7074f3b7eb4541f702e1a2d89bb7fb49689124fa3e599
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37aaec42e413cae8e545efba9f39b8ba9fa732b9e1ea8f5c617d047f3a2df6a6d00de29541ad1301a28ee645d9479a1573d6bdd2e9df97088b7124118b9c7ab68b723f290f20fa46fb32848d486a42c8543d9c4e81020f1f8e66b2fbf88db7fcc107c49cf0d8239f108d71300531d57313f462e6ada238216d4babff7bc0fc9f5306f861070ee2ad71ea9a7de5aa723cab89aee6c83f6c14efceda1bb2d7b3d282d6610ebe5ea7bd13ff25cb7b48999a817
+TAG: 4ad0bcb1bc88867cf39b5a98646b9180426d39251fb4fdfd97fff33907b3e48e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a6ef4f6e2c778675dab23a38db09cb7fdb6b307050a60818ee22991a7d578edcc6e72705de020de8bf4d06b9bd530a42e24620d4f4c2a966b95010d41ef77db7639dd6f4b486cd9952c06b61331e5a523bc758495eac7f731d9e5c582a1ca25b0323b61b887ffaa61cc46fdb0d99bf7e3e0460414f985c91cd3f151fcc6ffd7bc485d3f8034c94a31013a1e734d45f3bd7039ee7148649ffc75159b43b77cf07f6c53082adad89b5935235851fd7525da
+TAG: d10c634654c8d3cf484ae9aba92bae98057935f49f0f5f607b11b2c6e1234da1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37ac424ef28dcb9d114f0e16b8a4821ac20b1ed603217c6f7deac417b45441574cda950d887df12a5b15d890a779ecc02ea043c3a968a9c9844811d9cccff3c781eb8c4c836652e868654cd4188702e4df9222e6fc9c465abbfd7b9e0abf9db6805d67eb984be5e80ba6c870af0c6375ec927b12c8326191e1c4e0f84d3406ff695529ba31b999fa78fb6f6c54970f1b15bed86f3b40edb044865627261adc86b644425740fa42c0555689b4d35d8ae41d6
+TAG: a0475537874f82a063dc0852ae355c8235e683017de572ecb1d51958e43b908b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a51e00c7f5af6e1b833e2422248484c9d22690ebc8cb8c1f877c4a36156ee01367b21f1388d5f1eb4a57410c92d83898e468d3046581da6fa907b41fd4da3ffa80d17ca354488db8a2016db675d262bd7e8ab6a7d3ac2987db06008dcd6940a0bd5eadbd64408269aae75f255f54b60bf1a0fa02d675c0a546708ba3651770a1959397fe19e2fb61bf86f2ceaa7e64d610cca1f7d0f27a0835e4092b13de3fbd5a851666bd0602e9994e908b5c6fe112e
+TAG: 232af1bec11bf54afbfbb6fce52bc62cac82287031eec9ef78003bac997b4e9e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a8f2dba3f50c935d5313e91df63964def146288d8fc987ddf90d70332f8ba09ce63dcab23bc21320edc4a1d52d70ba897ccd67f19ba05665a58e7ebe47f4ed1479ac0cb0048594be1e3d5cf0ae39a5af35a12f4befe4fb860c00fc045da126cf1031ac10b452aa15c649048f92f06f237640e13b097739827db55171bd8058a8789670db2cba9256b8654d05714eed7923d2b6e347ebac4330dd19a8ce98140e8923018edba345713ed37a6e7e7c1f2ae
+TAG: faf2e75c137861bf1ecc52333aa6542e14262c98f819db03e744bffa4bdfec0e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4ac9b47f95b8cddcfe748bd5e8d24b0d81be9924cb708e58d6a68668186a13c485a675118970eb29ba24e59eff0128c2c338c4931e00cea31db9f13b59ad7cc3df7be3e1b9344c663937af9d78750cf8bf7f6b300c80b2ec41dcbc6552e192f8227298c08dd1c0080f271123999dcf360862765f8bad86c24e2a6cf7745294b8fc87aa1f3ff86a54513bf69d8c54037c8a18f1937525983c107a2a69ca7d72acea9
+TAG: 7d0358b892be173325904121aaae32a8f186e1e1975f404952fe7ae2f62b0dd8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4ac0ab81b9f6ac62937d088ab23157a4167c4b4a4d72493247cedb047ea6dcd4f8bb2dd35ce73a2e7c2fe15d9a5c7e441ad7beeca8ee5345b6b1f27da3d8ebfaf1c1b3e7f4f46ba83d46dc0b3090ca8d3f514b6fc6f79a572a78d4f71564a65831efe24c3f027068500338c28c84d54a6404abc6b2c2c94f11068d61de63cd6a668528a2bddf4fb8a1629c5f062e6fac8a45166dfdcf5a5e7ef3a7cabffaf1c1ce6
+TAG: e39459a7f4e7177763484200707c1759acd3278b3eeaa3819123a646e5e3a32e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4ac1513553cc5892d75027e1d9024c9a829b2c32296f8374981b2cf36dd1061c94ca4e791d9a1c808db1cec5b7874604927608584ccade032afd72c9b9da947bd17809416d93b500e60092bd39fafc7be15ae55bd893c993a70f8060fcbf19506c52967b22b3f421ca217859253f6e393ffc28e94902d6b85c3172d1638e849bbe0c4453abda5f427742142a8e067778e16682eae12fbcdead5158fd6c04ad70fa6
+TAG: 995595c1b2606bc57e3733516b17aba9de40eb74417dfd190b70a3b8315f2340
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4ac25aa5362c0fa2d174851710a5adce83610375ecffd05e15e2494c2031f6308f55c20a40aa0b0df2aec85200cc5a3397e97627de6bc0f3e57d3d83cb5bfb8f1c6419c14ad7331dfa62529eee28dc387a3c331c56d0f80e4d500a17c4d2fded0908637719542c4bd149ae6bc30541f4b1a25e93389703fb120a0725c22a6af8aadc44d6f6a661617cd27f32d7c843fd1bd5b2630374f414ed6e7bf6a73e62465e8
+TAG: 8a817d14002fa10e7ec11b083e7acef674e406c17f7828ff51ccf526f530ea73
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4ac2ed47fdb4d0d6331a5cc3d1750e7d5b4410a62581ccf394cf9f8c0f670cf2e15725409b09739025fd91b5ef0adf50f5ccb3a161706343687e2d0e77f00cd47eb87fa35f493308283090d294da9b5f5e4f278d3020a8b937de2aa895a5a2af7716dd53ea23595a312cb51f4906cb33c34ba93f0fe6e19166015cf0345d86dd3f574d8aad14501df4fece5847605b959eaf812d114d4943e68d70c3ceeb2cc8737
+TAG: caf6002eba37606c5a4d742f28a883321190705c19706fa2e1586006683d8c1f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4ac35cb95437627b41e6f09cbfdd1605240a82850a955dd1501435bbae8082f2f778928f9c8649a8e1896dc30ac4d4eade1152c86343d228d2557ebffa35a08637c7169400f1136f17990f050a275be157d91987245559f7450dcc6f7ec2c2db2096b6bfaf7eb56ea800dcce3acfed550c9cab108f87fe3f6e1795f726ec53d1c2b086e6d6e60e605b39e2ba9a2b9090ba12d6e82524c61301192c20152f6ea05c3
+TAG: b76786a9fe37f90aefa5819fcc8ab4b4b2f9ca33fa912bb0eb5906505ed5e505
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4ac44a72867f44f52d2095cf4c3548e33b0fb35c7c146aafa1bcf0b1acde38bd4c776c66289dc16c0693d0d91d02a25f48d007410d45df459f38da0aa9253182fca99295f60a5f1028071ff7ce325a76e29281d8649d42fb898ce62187204b9e04fe70733937bce183cb354b0786d926345e245e6966f509a987911a6408145428b1003e7f73723b3fa49c9cd3502a4428d5fbe5b1c10c8dfff118a8052d3c0fe89
+TAG: 220eeab273d308740f8dca2aa20e6bebed16d35f2f4bac927483641c29297d28
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4aca478f5c24701b72cdea9768e338d9af60db7e6833679cbb1be49d1cd957874a0e3d14d5e182230b5c8c17db4c635eda23f059e09bb2e300bf894329c09be2a29da2c4f7b6dbe19c73e97c9bf32555d233b51eb0de1f3157c8d1f4847cc0c35152ebaf4f7af2cc48cb1e9f5068673137834acfd503a3dad2c27d87a4c573c4bd21fc1528305426682a7bb5c3291123337d4fd7f4d7eda390392c41685e6390016
+TAG: 3d2692e87153139c7d5b40c717bf805e9211e6ea17d486392f77ee3c538aa234
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4ac1587d3ec6cee937a07ac2e9d693194971a9f5dc16aa16b948878d5f50891ec0ec69817e0d3bb0c4009ce6fbc58c2a0e5236c44c60d2882122fd19c32a296c91d99c8f07ff974f4b615134121fb44777b29c3d441366c121e301955b10adb762538e8f6ba4f54024d3e5df964d6ba98ba2ddf33bdc792c32238a42881a110673709d5a5a748705ea77462eaa6846c975f597eb0f46043578821e07957db194bf8
+TAG: 4eb115b209b23eceef99b719f5583c40fe01e2e179be47f40c7347d01c77ad5a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4accea3e812f63b3cadd5293139b773d2833574bc20030c9f5fddcb0f507ac29538617490e59648aeae26b6ef762aedca9f41ad26ed3dec119fb25610078eb39701cc93e5a487ada90d408c485d1bdf219efaafbb1bb860e8564b03faa8db96fa567c494256320e8dffb0eabc9de13660d8cda523eda0a90ddab2ebee98bc6ec4f616131d1ccf3514cc8e31f5012d205eac7bf5b23315e578b6194407f0b301df4d
+TAG: de734f74a6d25eebdc42fb15823bf3c7d9fa463a4f70d2b3e3cb7f4430e62b29
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acbf045c0aed3d53bca76fda09ff3512fe5f0b2c3a70ec4c45654d08f2c3f5c5f511e05d812c6ff22993eebd7817da06812878d94c29d3fbfcab94db64170910a28fbda71e7da5c736207e3dd3831d7a0a9decd1090d5d5ebb2c2a743d9d0b09eea66b209f067e3c8d842b585cb91a56af096fbc3d79dc2676e1098ea6a66f5df9295e9ae6e97bc65ad2c49bad2aea5d1738cec3b4eb3e5efe333be18e77af9d6d
+TAG: 3cd641abc46844523859d705be5ca5018ac0566020742bc84cb3b731df8705f2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4ac1388648d516eadbf6cc27d388512527882b828cc47b8b4da3e79a7d10bd16aa5225f65133a84f73e683facb3d4156ee16ca2d3bf33d6a1b8315e7e00ff826a6d726554607598c9663e976a20529c17d901e3169c94f59b182d64ca81af1c378d0e152781ccc7dee03d867a844e22b91917f577067f801b274673e3cf273ce82f064d58ed594b91033b7f5e21c4009b8efc4b7a790beb74d410e13b00af390f43
+TAG: cf049ebd8266205de3c7ff631d03e96091e94f2ea8fa519285026245c180e6dd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4aca6b402fd38d4907a62cd3a4373040ed3411d012aca13120e2056a8cb151b5c37837ad86d9541fe58fa2ace3a2217f0d18777131685d20962820a980177f63fa71a6efdafe35b5652c01fb3c8b025f083967e20b8a97510434c299cbe2e84bbe35015b803aa23fd8f8f8a0c40ef5f06a1e0a4cc3b78d2ee9fa29ea8f21c97833fcdcb3d9413a55adde5fcfb528c7af92cf8276ec3930bba023a6837862b6b0993
+TAG: 984292d253c667cd83bd08c17ab7d78f09603a37873b0724f3fe9424fefe81f4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acb612c046c769b9c7a1bf6eb81cca0c18b4784bc79789d16a22122064b1dd716d3199748522e7b92d70c025a97256dd8662e495248407d7b24bcd7a82655464a2ba31cf38edeb2c05d52550a39dc07dfc800526251a4379a6f2dd5410c491595c074e9087a03a73387cd3aa28c04ac17da3684b42acbbf15da205cfe1ea233feffed6bba33350dbca1fa9b40656f9a9b82f3d058e83e3ba86d88636ab73d1f61c
+TAG: 73c86ada0f70a93e63ae559f7995165a80d39a7c6d4e47cc99ce4748e396418f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4ac5725a681e37138a09e96f5d800f6519b21e97d505eff4dcae4ea1939fa292449f572f9124e0bdaca4c462d8a4b28003fa23191b5768657cc7ecbe193e33a05f3eadf7980e8d56b3b52b1b246f4831ab657dc2092a6058decd2609c2c253cdeaec6322675cb4c0ff292dad8449217171c3a23c73dc207fdc9a831199b3740cccffb20a7eeb8139f1aff0fa3e3b729ceef2b9f61dd7dbfefc52cc252c4038ba8ec
+TAG: 9a6e70e37603de6c4a4935a10f9fb6e3e848ce662343b5586291f95377c5d88e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4ac496969d7e1a51b140169ab7bec3044796074b3b8224b0f5d6ac3012c7b65b458d2ad2bec99aa96c7d4f1e6eef535dcd74a80732988d2303a3db17d774179a0df737f472d53581ea06685f860c55148ae418dfc82d857dd8962ab7b715ba174bdcf569339dcf627397f0f20d8f86de53b90e9c643a1d0ae9c725af620d7f52cec01d43d3a8f5d952b0ea905573c352a910326874c0543c870c0808cb7a3e36690
+TAG: c4e63bdcc9066a9c5fe671f1236feedb41f1423d1f41ade97f0f68b1de618f27
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec55461ffb456b464d09831a3abd9aadd67bf1e86ff4f30465e3618b8f63243924ad345860855706da8ad428a074c0cda33c3e22f5ee194fd0c6ace4f19afbc4b8e863a6528787ccebb3aed5cdb63acf3883cf0f99432fbbb7a8a45fd279a512a909ea3a5c308b6cec9634beeed7e0d398c1508de1866067f6713b75d0beda05a65bd208d8fc4e93ff54299076acc050ad1
+TAG: b5643e8100c51b5310ab551ec42b44d1caa34b6b04d741de9623d2b1443c88ed
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec512b4796e8a85fbd885f1cdac48fd83f72fbb2035f7500d0d85992623399244a13f7a2a86661e59028fd16a140e450586cff7703e7da90ef38dedd25b027b63addcaec6b183f941eb6416fc0de8dd7401997fd873939af136b1d3f03a63bd28c1deb2f646f969156598c9f1b1b8139281ef08d10f6e716fd443c92fc82bf64aed7eff33dbaee03ce0ae2a97537d9c9165
+TAG: 2ff8681d81973706370f750eb9c49e73fcdcfa395c51a27656bda081a7388338
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec516cd3f34b0761308c91c78bdf31908f876916e66c8092ef8b0181ae3a79bb5041735e81a3fa19043ac614f59ff8755e62b6ea9003d51890444eb6c42a27116d04d30d3a5cbb7fcb7968a7caa8889efef304c5fc255e1a5aacd9b31587e073484c4b22d7252aafb0ac6742023c943a7a1822852fbb1f69e54b8df5130af5274fd671909e3e1f9c91d9ea5fa82cda0decf
+TAG: 950a3d3ba4695ec645768e27a8c452cde845420b30a440cd8a3b203c3885fe60
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec577fa5faf827834e09b39babe514f01f74993fd1c17ac9c42ff6f9a23c1f8db52caf60a27269056aaa799e1d3f055dfa515a021949e4c58d10dc9d60b8dedaca76ea24cccc0b2c3c383d0853db6c9e08fccbda15b8312fe9472b43f5949f075fa625179ccc136a3c21adf6f9df1695de2d01e147e0471fa08c13b33600efdd822f05d1f96033fc6470a11ea16162df8eb
+TAG: ec0f76709109d3ba11e5329353c97eacf58ac803bcd9cd59391d4611150d0dd0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec59e92021836cf74a3d82cf955bc926841045e1d6f7d1fc36eaa49ef51df74611c0ef9ee839c2f6e1645217496a2a4ff50f12a8092293db888fa0a0193b685b9238bc7b955c833b3592da3324570abaa597903d6c846077bec98a05173932b9d92251801c237cac731e495b658d9d285e391bfd48c7fdcc7d44957820ee1eab249274d0cb5df748d34cce2c8e65a55b6b1
+TAG: aff2b08d006271bec0ed98c544589c0c6919e372a28c34d70c553c615e4db0f9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec56acec5cc35f1612754c37a00ad2a0e23f5175e86133503ca4251eb2c6ee29cdec06d0d70678dcf9025cdce3c853dedccafaa7f156f46ac643029fe78d002a8f4389ec98be0474f1ba043668e6eb313e067b98a1fbce3f98aa83875e633538ac1d479601eb76636a0b574da9369e1dc324cb5a60f8a3e7314c3668627a96312ec497f0b3ab8bced1c8d6a9cf7d0250a98
+TAG: 769d5e7093b3aa3bd0284625185e68e2bea32bb85e2f97a18c8622304da389ed
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec59326fb7d16e9a8e578ad5d0d655fc984469eb35f502b3bd90809f980e877ef4fe7e439c29b49746f16a0c32f24767473166273b3a035133a7500169afff765f26934238ccb11cedd94777aafd7034cbc4d069cb912308c174564312630c0aa821893677c6e24ca389838179dba0a4309e461672958e566d9eab6b52953d29aa7bcfbf86495f24509a1cbcfd5922ec996
+TAG: fea817e4758e210bd008ad91a87d8f5a5be48e30b5468c2142dc4453cf2f0be8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec57a243b55481b6dfbd8c90ef8978d35a68944c4a71a1e3bdd9d2c3967c377c6c911d6efd3bc2120fc7012dd1c9b2e6e4ac1ba3d02f7c5233cbc5e740620c09adabf58ea8236269862aa4735b10d49fe762eb26545e93b699e1f6f6dc1e54d7fe1b8ae98de9c44579458c58ef37f9400b26cb0d744ae4bcc5f00f307f8542af11e2711bb82013aba72bca0561bd93fc0c4
+TAG: 2c28a82ae968428e3f43bad32bb8d0c0316147203e95de18529bf7cb63a5a3f8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5b8f5fdef995ed0930e9c2fe8f897e59ccac886e54b03a5733dbffa309ac49ca45b1d6a23e523c9391d41f39f1247bd3374e193866169bf5705664391ce025e786cc4dbdb2151dd2737915cc8c14217527fba340a1ba327a2af4f862eb1a7e442858610f4827d7304062e8b76aaae9f5dad64d8faf80c6c51a27eaed7a1305572ca08a2de586a9fe1939fdf7ef0c4f134
+TAG: 2c134c0ba6f7756984e2e98d1d6e25edc313e77fd636eca50c28403a6172d417
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5c6bd0b0efc2bec72fb491eb177246fedcbc8f8ede451e4aae7f42c71b254841be5f94599e8d9e772651d17c8e4feda72898810ede7e5c9a103f9ab337acbdd327ce4b737ed4c7a61e8c3df3a87c79fba69bee5504c05fe82ddca209d237f232e84f1884985f9115962616ce3dcfb6a103edfd6de4a5d9dca5352ae5ab816be34d3b5a082c69010e3ab2b68b5130de74c
+TAG: 75194d4f9bdc432019dc29e302460443c9741253e8f0d11c44e0680d890231ee
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec558f0ef291c9ef3152334a32fb3200d131f7a815a88ea70c267fab275b5db76dc5426daf16fa8eb75114fb4da1eb93bf0ecccf35fc47b73b8854dc92e1697fb5ce2d637bc8fb33c3a1ffebd816fd32c808b75943a95595c26e3a1a266b146b35d3fe5fd2ecaee1e1e1f1579266b3aeaf21b4047735e8db567ddbc127c47574644ee1f1ae81b467ac4f5df04d1bfc9d98c
+TAG: 1bb4a80db4305aef05770b2b4e045de95d158a2f61e6c5f71a220fdf8f5abb84
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec55e3578d50104794607b1265365bdb9e94523a2070bdb5f5731e01e49b0883991e4058c8136f5c29b55cb394ce6a3ddd729b3ad71d81bd978d5c2d738d7496564d5b1b65b8d76c481f3edf7d2bdcfb6ac3242d298d85127ace84cfc6794bc55ccdfa8619cedd297c70161df1aba1a769d602f91f0ccc1d808571eef7b8bb39d8464f1082807edf7d2b02aac3973726451
+TAG: de9ad91378d970e08fc8d37f4ba414e9da60e5ca275e1344ab5d4c146d3a1b73
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5f93d76881f3dbd954c5e28830c5df57748b364e9c3b0b8c540032070e2c7bc37a418449fd2edf6ab466f96c456eb6287c5c923bdd651e9b63b457ca4d6dbb8d12d3552ece9925e5e8351d92eb5dbbe6b45fd7bc11f6dbd5a92c59aea7f034ade8551b335423c7140ec5ed680ca2032c3ac18688bb926d4a5cba85f874cc89901f91ec6a63e98ed0e9d70e35f1fc97001
+TAG: 86fddc9daf4fd6a24089d10b99ee20b302fa9510faff99f9ae680877cf4fbf4c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5af41402c51c9cddc053c865ddfcfe7ea08f653572f3e592736e421e4b462983e0aac29a82df3e3d32b550c62794a87758cd9061785ba502edbfec27380da7a32efac5829bc4b7506636fdee3df1ac007f8e773d593fb7785568ec6ae136e14e4f49402d18584151f6643c12a00a9efef3385d460185c800ce18c4be4c45ad7e1213578d5852a894fadfc6369b8415ad9
+TAG: 41647bccc845f7b914d16ddad37626d7590044d561b731ee4b595a9669558289
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec541389e7c5caa6c45eb1cc18f693c40697f9427a09e6b09fad51400607e0978dd5c2b5c4c6781927b7059e9ead1498d50b942941961ed603b9c3ea18b64091b4f8246141587bd34573054bdff4b28d9f41dcc0b51824a6af3577bf6be2cdb45916d58cda19a20ec99ed627b35e4eac2180725fbdfed6e4b28339014939cfd8832625e9bce3123194cb9d3e992094c6fa2
+TAG: d659847e696bb703bdffe1c57b62dd876f8bea6f0238b4c7bfb0b2fb556b2124
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5c53313afb251a18e55824a48146f5a8a13539dacdfcc14cac52dcebdff77e8bc67e65e48595c06230851e41c32e48955721fc318cc3ac8b0330659b1a5896fa05bc7ee11b0baabace96da8ff1f7cdeb7abad168a0e96495c04c1169f38d8d4cb52a70df25579965001c38f0dc1b2a61c78054a980d7bd119c548e36311a980c70291ab1e1d514880a7f55b72a0600c80
+TAG: 27cb5f01dc474a2be089edc18690fa903d55e7091c37b823888087dda2adcff9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac725fbafb7eff4cb9213c57cc3c6258c22e2db351c56b4fbc98fb23cd6af4f1990254b2fc0825a176013d6912837ff464fe9077d1c61602ad4efb6b77a4b45ef776fc066fbc001e7858c1d2db6a48aa6a4f2e31093b10721e8b397adfd60bfd163c75982bb181985b8137a2983417af17bdb5611b3918bbbd59a133e698dc132dc27
+TAG: 88b04789835593e70159d20347f6427005c11a3e0f9ed8ff456085bdd2d84d5f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac725fcc37654d88fe8846f5eb2c672848865745dcc97b52f2590acb07105a93c0cbb25798e5e52d274e340cd2a6af2629445378cd8570752c07a9797788a7815f284fc05ba13d15773605fd3f7037aa85dd75b1b6c4cf9b05f77c7997557792383ff4e54514ab44e515cd92ae6789f314606b8eaa1ebe9a5770b60d92269f042745e
+TAG: f35146de5c1570ff274d936ccaae69c71ed500c3dfd53b11eca237f8ee072d7c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac725bb55b55ec87495dcb50fdeaa975460b3e847b86ec782014665dfa6b9a7a0392ccbe0666e17b5931ea213036d8179042cb6fb75084e6826a01614ba32ecd09e2438a328cfaf89832520055ea07e8b715f1c7f0cbde387889b581de449a1b5f2f44ba12e70d14f40d468abf6b60155c5a65e6fe524932492fd33e3687a1093b2f7
+TAG: d4f0770d57ae78935dbeb306b1efe481a4b599ed2d161fa6e42e931b91d74175
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b330ba3b6ba65f3a729ffa7b709111c5f8e8077fd06225939a682c72505533de8b229c24c3d641723aaed6d26d2d495965a129bdefd58f7cda61af842ba10059d746629ef88142ab27541b10dbeac72a48405cb4009a8cc8de8ea288d3a82582472e59459de99c466417e7c0abe8f6da055ef6360c927d4285944582aacecff
+TAG: 081ac406d74b9a31f4305f9da8775b2e716bcc92fe2562baef78f22e47f69bd5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac725bf65adb86c72e007680ccb6d8a564b05ff9701910edd582ca161b2c1391a0c9f97fe2392bd2d72f5eb0e651ea5ad9422b507a605e59905ac37f7a2bd6b005d4d43a9adc074f75ffb1552285f2a8840078e23c086729a7165be08518a1be73b265f1ab461f8d5dc01d15016c002f2b86d258ae49384fc0f3ca44ef85d96f8d876
+TAG: 4549467c39a9a101e13813f650764062b982f07d89ad35cd406954a23f858f7a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac72530a524533d15745289c5d0ce622a4cdd5c871d459a11607a42fbc2d258877b8e408e23101938f5d354e2b9891409513797d33c690400a9c49c3908967d8a3bdad1440a4d0806b0f1a13d8b3b745590141da3b4a3fbc66e95ed9ff879cabd99995eeb0bc2311a91a83d33fd9d75aabbe8be016c8d129db4bc108c1844443ca0f1
+TAG: 4be4fc3fb1e377e543d11b706e4c29b29e9cc2441e300d779eb163373768d1e5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac725fdfc7d82dc3f65fbfbd83931773f8b44af10c55944fa52b871cdc8531ad2d72c963c6e843fa381744eac300e873bc20c10a94485beb35b8a2cf25db3ccdf8ee06b7038241d7e7e511384a9d13efc43e137195f0e13370b51de46bc2d60a69c66fd63af21494a6bb11dd7c47cdf42f3dfc28911e53f567f9ee4b46ab2cf0dbeaf
+TAG: 89d8c66f16672eb202b0044e17179571a85ca27d37ab8a9c24323bff629c195c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac72506af24457aa4944b347ce60d81d69c9e207202c7e726cf56c6761f5462a444146120c224978254a6b7b76aed3d05beeeccc4b3cd880330f87e6762520d7952a19009745c4b39c22941047b955afa63b41c2e3d1bb923ae2b1e4521653f9cf05f35deb0d4fbb1e057cae9dbe10cbec98ffbfafe6e4aec94f7e111fa818e9372b1
+TAG: f594b792e7aed5dde384a0b0b91a55d24858c35bebb1cd298af20e6682b09b6c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7258cc17749d73dbb1f2dd664191529c4eb4dbe93bb6965ae22b2f4f5038e7671a813e4037408846f53f71e4ea7c8bb9f15467081d7537641c4e6326f500c1d359612221634c472189805fce506e96b4b1f539d329232ddf6e591c61cd86e118bb90944e2518e65875e8e77dbac1307a66eb929b278cd72657348fdaac2bc176fe9
+TAG: 8ca063ed58424a02a9b41b260bd93a61024e6e2d47ab9d5b2fadee387b59fcc8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac72566cae633dcb58524ec9dec82b31078fbfdda4bc079337a959f0faf6107b3bc889d9dc1f16b70d29b35c100e63106d1b5f635dc38129edc4f541a4ddec95a029f764f75c743df8927c56b183caa98125fd877ec32cbd3d3dbc265282f04628625cb3d6ef84f3ab8900e537ea57f71f0ce5d6f314b4ce4fce54948bd750ba4deca
+TAG: eac06cf71308465513f5066a94d0cb5e837a24362bb178914ab9714afd4d5230
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac725ee7ed6bf63b756182a5c2a0c0c309ac08cc8d467bd474b63992fe0813ce1355911edaa4da1c49228defd67ea8c8d85e5cfd881adef9c76bd1e1cfa0cccc63051d353e90fe2d94ac2214f18309c73c45e6b0db5250c3347b4543fb9b9883ceedf034ece8f3c6cd53d0c27585d2c40f17d2897664694f8545705f407a27dc32b5b
+TAG: 6c0203f6b6b0b605bbe09cfa0efd8a914cc9d7a5fb51513080b1af81a5b2d82a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7251ad9e2bd98add1c321112982502dde3b18c628d035517b7685712446c0d23fb6d2e9dee3e990c702667c91d4bb23950196011930043853a55acdd5fb5cd7081c58d1fde347632e957cb6d5155552823782cd6e63f2294cc4c0ba01bfc89e50f7a048c297fe8bb216de8c05d4f041220f1ef5c5fb3647bc793f5c8c7adaec5ad6
+TAG: abe19cf164da3e15682d9315e3da429e6c0f62bc2ca7052ed6c69bc73b6f7fad
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac725281d31a3f1712972990eea2f87ebe4b03d5978119b5697d55724ef3a3d632e9fd6869c2fbe266e5a03085050aec366b035c0d0fe6631b48571fe523f39444919d2fcfecbb102b1767826446f721a795e6c2e34fe229639dad34f26d0306f3b5b59aeb4a9a8f9064357a96139645dc38074467de00aa8e1830cad3d5e99489663
+TAG: 36a721f1e8fa181b5c6e954c1e138237255c4f270d7c62639a65496f081856bf
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac72562cd386768373a474e1b8d5bb0ed755337c2280b05b0c43f22203ee0bd70cabdbea59e2d53dd3611a7aa17bfbe49f146a4c67da95909e35ab8f0568ee59f97a886ce2487f86cdfc2c9ffff3c0e301ebd931fc3e9c5890ce51802482b8826ab1761efd6e71f44cadca7338e6dc7e307f0a58963aa50130dc0e7ba48bd8b123528
+TAG: 2712dbab890f8abf20eed73e3924ada6e73da2925fe0a4938059c660d8330fdd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7258b0811283742fd5df997e711fdf5078c97b6466302f9d55da838334ece3559ad4da4a637e374d32043a2e3a40a8590b999189bd224e1819b5af822f14bf03576181a3824475dffd59f42f0572fa5be1a77b940839bba03b66402bb5bd6cf8e625480c22a9e228c9974c0495f9db89b18645ce2a748a695b58deeff49496015b6
+TAG: 48a2668b32b4d4bc5c403b2ac7b3df3524dae2cfbe49907eaa1b751b47821d25
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac725e1daa9e94f13e412b8ae84dc0da9035e32ee1b2fb30c802f682320babdc99c46e5c0848e4a82b700ed09af2c482ac0e845d0f3a5056462aceac05b45c7fe76bb8f7ff81d918d8aec06a77f708e21d39ee4baab72e87044178da3c4e1a7fa1a332530a9fc740dbcecaf0bc6462a814618a4ac794d17565500916e02619ac44b28
+TAG: 37c22172e977ebdbc77980d4683b8eefd6880fef2ccdb0e427034f40412dad52
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6ab35b76687f1f8507527b9fe4b9e0c2a6f80f5af5cc234387adbc4e506ea78e185bfd9f559be539a3f7c24534b478ee255b36797aca6249a2b1580a0eedb95d320cc91383be6fe55cf59cd40a325d125bd2e4269f2dddb395a637a573221e8d158cd44e9aab7a3e3822d302372ddf0421
+TAG: f372c86a959d73afdb4ace31c3bffcd7368214771efcaa0ba12ad5feaf9094e8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6a7bb97cab194616f87ee06795cb115547a7a1c6b85406f9ba5650ad8f043f40adac6a0fb48477726720f4d5a488cb264d182bcadf71718a729db9b391fdd968caf4118679d61a83bbe7b856a0a4dc71197e75bba6be890a832cf1280b2657fb1de03c6b01a1e393c33cbb442f0002b97f
+TAG: 3a38e3663c3e5adc45ed0f5bded451067f4796c64174366e7ffa190ed0c406ef
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6a7178fd1ec941d7db1402b77b8475c65339448448be463e4d454b0671cf09754c2506e1ea3ac3e309f87a0d6531eaec58ebe72426bf87646403afe8f86e9ddb684a183e848bc8b1cafcaad6067d4d01cad20165266368ed181b255302a735980b0ab4ec8e33e84ccb3ae2f5888b765b17
+TAG: 683897f335843f343c0626d52bb62b31e2697b8d7ba6925b6a632ca4a85fa87a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aa08584a4e03ddc4cab8e2f8fe54fceb98644075dfbdfe6b7dab491c01d5af5d7f187a6324679860fbd6314ef51bb245dbdcbed298eb5a098169021cf87e7dfca8f0e6e7d23b39e6cf388b09a9e3a70e9de852b75f08e253d3bb1218e8db7795abc177cd4c14ce23f880fdb447ca99ca9
+TAG: 5fad4879050d0902e0550c1b0770948879f800772b3e0bd30f9c710601fc759e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6ab895a040a2269764d4506fccb8746dc66a0fc0793ecc8f42bb6ed4e80c77354df131012725727ba30196f5726c2f347a45c68eea09c6995fc2f391e5f21dec0303b76a1dca8eccf2358ababed6a1f48a7bb5db3e01ac143221b4dc43f876e2f982dc607b8ed2963988f80ed994f5f5f5
+TAG: c61481685757bbfb59afd0bff89972b137224ddc665ae0ab4bdccff68360ae6b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6a72705a53096a9bf72443925468d043bbc15988fa36f3f311b7bae87b74d5ec2cebacadc46069d9ea89c8e068d2b405dcb2c328018534531d8a1e5c3d5dc6082f6a5cd10783faf01ef9a606a29e5aa5eb1c8022f6b3da276bf4d9af013a52d7c620bc1ea26157b77ed4b9d61e416b2e7d
+TAG: 82ad23342cf1940e009bf3e5216b84751a41ceb20228b5d2e855876bdb9cf165
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6ab9066a5a3d89b05fbb8e77edc8137f62665a2fe937f9fe62d8e459245127a1d166d55df90dbaf303207a6103135e44a16737eb681f964ee535dd09008a595304148a6d1293294f0dce08f6deedff7bbe0bf92202d2146ba8d2c02c30173a876dcb4de19a19914aa9c2b5d39c11ed7f44
+TAG: d649e330fd0fff58d8673f1e53b83cf82344ca86422c8a5a660d4c5caa38beec
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aa6ddc930659dd4031f8478f5638e835147d3be78d0addd173b9f6825501cc6aa5515b53c745780b4716dae8514efed43c3b7c168f06db080ab507130ecfd451cb0c98d16d6d050c8421cbeb14290d34355e974fa5b34a3d72227333e8c47c786f0008a54b847268aa8c405135b1d64e8
+TAG: 606914b599ce0c6fd5875488715939999ff4181af80a40542ffe67d31044d606
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6a4748d20cc0349e651699bf55d6aba348371a54cc14aa68e767bad82e4cda8bf88eec313de4212b5b024e05021ba8259a30e643abeaa5b88a64969e988e2fb91482c3dfe734ee3462f2587105ee8b275ab8df25729e48e713e55da17840845e5a6c3b18fb2db863a00225bbe60a17330c
+TAG: 5c8f340bcb07fad82e897d8e31da87d61256f2d08f3e5140caa0009e112e6a98
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6a96ebd3bba080b8c97cf103f89d1844680902ca2207dab137a1ddec3e235c0246cdd70ccbc517a59970e9f95a8f9783bb5f80bd75cd248f958e150d693a4fc9709c3c3557b4136ab2acb6e1132727b0a9d1f94b64521a92490db0223581b0a902004bf71e1b03c5325c04bae81ff5349c
+TAG: 6957555ae2d934a6e958e05699cce915450c6e640f04fb53d199619be8daa468
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6a8fe0d411e2d1ce169f70e7aef888239811b85138b4855500992e8db59a8beb9b9a386496e94788d731558190885f2173d5b806cb012890ca11dce6a0685f5cbf0ec820c2a3dafd45dc6e839d544adeb54039b7b337b18cda4466ce341c93eb7a874bb10a1740736d11dd7b1cd950cc1c
+TAG: f7564ce8dee1b4c8687982a63683654bec647b1581fdb1fb20fce1c94d73bdbb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6adc448f9c0b24b0754366946a423a57620a299d0bcff0cf76b8f9d785ca61119d56d65d4d3ba0da74bf49df3c14657f9ae05f8763ee4349625aa9c4276cac2a0186bfa93174b0782a1731dbee703c37e29e2c1f21b5d98744fb59a98172a2cb00a85aaf5af104028440b687afe974914b
+TAG: 1239771f0569f22cb644e317c06fb725baa3ad0b24ea52e16b3133fc87b71f38
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6a116780074d450aa58a3e7c0f8de1d518914697d4535675decadd39157f3a7839015666450078170ef78194236a005b11c50e586bbccc5e803d7afecab795ae8f74b63f1915197bccb31b55c5363582a5d57618e8ac0c3bbff4be83f5bdd0c6851a6acacb7ffd0ab23f063e8fe80aca88
+TAG: f22422faa5169e2a0a477a96083ac438fea2c8436f5138ae57efc241c4210fb0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6a37a21826f66861d4250997942ab9d4115600811823dbb614dc1e9cf9fb157090516566c1e11dd93c435b2c83dba7fae01cff15b328adb3589eaf635ebd8885c0d6a0af85b69fc57ac6c0f2b795e1ebb4fbff538f2e1a6068bd3c412a9c1614614dd58c5f5097e9489eaa9cc0957c2cdf
+TAG: c33ced6b3879a7824e0ff80c55680e91fe13343ae6b71782db76c25f16812860
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6a13d830743dfff0f399527c39451734777ff3248c0095dca76fb76ce3bf76bdb2bd82f988d948e9a21d6e2ffe028fe12911313f9131005abfa200a1ba0459d655bfb3cf3ea526a150934e1c7d394b93d3a7df36f2155dfbd07efcb4fbc8b222cceb58107da3fa9a31059d6e84721f80e8
+TAG: 2491e23246266e37ced6839f141f53d8543db0882c6b559d04bfdfae1a23db20
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6a62a62f9f73a89b2d7cfbf62e209072ceae8339172c5fec4e9ac042da7e64623814176629fbdef658da190acd77b03ce951b1dfde6273a035615a3c3fcce6ef8634edf0abf2a4d13bf9d547b63bfc2e481793c32bb74fd0c6b2de8c47eb283c35bd6bcdc912856069323dc946fe0e6b16
+TAG: 84b67240928cbb99b2d9dc67c19f1622c0c0996fd05627020b75795dc5998143
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a00bb082e3210c34631fd219cb399d14d5cff17c4fca3098269c4486dd79ecc68d1d49c49efb91dd9d4ae36b3f2099ad67c3cb9ddcfec7b363555a7c823ba8eff88fde24303abf34ad332e709cc32b81af2089a48566d29dac23078ffb60cb553e0
+TAG: 13176f05c7471abf60ed07f70a7b07e88be7d39a3df85636c8acf379b95b76e6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a000f3b7a7162faf7a9472346341358b2c50eb218a1620524eab052b64bb44488329dd2ffe4d556b8cfaa79f8064e2238909007098ae0129853bcc07f65b2d67449c6c973f4fdb30553773f61081f34803bcefcb3f5a9593b64cc4d6ef88d9bfb76
+TAG: d3d6b62c406d5adb24e40df2ba464d6c53be0c95206c8d72ae2b368eb60130eb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a0092655e73a7bbf00a4670a200be548cc3d367b6b163a70925824c2b77ceb850292dd575534f8140b01ed04ce58b294cfadf780fcaa84448e696963b5e4026e195d70541e37e70d70801bc080704ad44932a7b8d9c55fbf843cfb32aed66f24f74
+TAG: 65ea1f21c070095d502d6cbe7b5693e8804f499ecb806c1be371bb273fc6d3a0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a00c5365484dd68f30756a2d5fd4afd50d44b8741829e04e9ca9529c57a8a5f8a4cce65a8c1a3788e113cfe51a31085ce7e8d5807e1f11dc173ba0f222f219e5fa05ac0446407396f737bd34ada19498648a0e81ec4317928fc207373fbb6b64cc3
+TAG: a9b6efa4821b1657f8225274c93091635fee80f40196103b40d64553677161a5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a007736ff8056037837f435c0f3240673a8196f8524ad012093824a5fd43dc2141de6eb78cae19f50916352561938790c4044c2b242e7bc4fefda1ab8f9cbc4895150c376b5ccf6e04ef89024ada2b070532b5c7c8f60506bf419fbbd6dd1b3ef17
+TAG: 4eb894222ff3faeda30451009a06c9330af4091c156ee4df8a3f1050d955a335
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a00649c360222d9d67c0a6b4c9a162f030f4a42d28b7c95108803dd3fe2f3f6555bd382684a8bdfa7683479ff290643f8fcdd0b56a1a8ae52c71907129ec65dbc4fd3aec9b1e1e18f059b9a1935bb996696df79318821ff7fefbf0778a71032bdc9
+TAG: ea177bd52269589d02e5580143d93bb7564384c3e58a862b425299f44ded707c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a007b70d34d10fd07a48c2839c3018256e2a25f2216eb48cef29020bd58a99a5ea4fb9da9cd0fc5f8d9f7e512ab7dee4616b0dc463467530e9c9918dac60c690c3f20b50d684e379cfa72cc23b91ad4b1cc43676baf9d559aef818046e4a340435b
+TAG: 0501f7fe8c7ed22ae4902bb0428ca7552d9c73bb6346b0e2458a2232a0315b61
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a00d08b09f3441e149b79830f8bf026b03fb52195117ea53a8464725193d8cda693281a2c3aa430ca0e50630be194e6569e76cc9cecc32564284222650d32dfea20d1ad2ff7d1ad17df65c444789ca8bb9825cd3b45387ba810e779d908f3e00e17
+TAG: 9dedfde672a0a98876cbf290616cad3103b286818f74fb01d18c63912841b02b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a00d3339dbe4489faefc33b58414abc9cec926c1a2ee2a604dd5f4111952b57ee672e5fe25c6fd811c0b1e9fa1f7b31edf31c9c9322ed53fa965d570ca32b062ce3910200d4272b096e5ed69aaea7a46e5773083855ae9efc35be2c1884311c854c
+TAG: 6ea0ae2f1ed642fda77e33e88e3ca609e46dfaac9d4d49d444655053d2ba0697
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a004e1375402e85f35561c11ebb82ba4593e17cc88093358c985ff5781120beaf30087bf4b0934cd690a0390b2a1c66a0ec963a7ac9f63ccd85e55c7a115c80f7f8cc3bc4a336c68bb363168c77741cd7485e7bf873d1b121ed6743f41c102dae52
+TAG: 510fe65168aaf4668ceb8c0a5af694b5ff7cbbf98e4c5961815ec97e42d298af
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a00d0a444ed7d46d56a67a0bee353551d4c1a3b1b85f24078a36dec3051205570901d2cd49dce0cd9cf67ec97d72bf95518a19bcf6cffd8c06b15734f1e7d6af240d097a75cf17a01721d1cebd9cc629d5309045fa923ea863305bab2e9476c99a6
+TAG: 5d790e4ce1157a84c8bb663f6ffbe7d93b977af509d3164769356636c858b8f6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a0060cbe79a9b635bf819922472e80e25ab8c60dfd3c551be72f6c7698191a39b990a94db84228909b24a681cf47f8c833acd46145ecbae60365f9501ef7b30154c62bc52dcfed8d970d197b6e91bd3669afe9f85ede4874f628244d607c208710e
+TAG: 639091ca5435541a7435e91cc40a3251b967b6d1454dd4ba47b131196da540b6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a009d7e30e3ac8967126323ea6303cf69c36b88b96e4501fbf76a32ed2b3b767b7be722c2a89d9bd750e0486488aed3f99ba560ee37ad0f332dc68cf1ce76be8f814d62aebefaea2e1bd5606c999b04bfe5476e88148425de4cdf68e0df137e952f
+TAG: 4c6e7b98742cc1c9c6804c634c971c214e22c496b1fbd9ec52cea1fd7ea7af0f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a00538a85c412d91ed43e1ce28dd3c6b4eda206aef0a34a85f1ceb0d1ed20ed30056d0ac9336c8bd92412e942580338fef0b4e4a7cdc1e88da49978eed64802eb34694b61a639fd9f65bfadab5e89b602f3420d015ad5c4f7e05425c148199e2900
+TAG: 17fdf5446bd3e436a08095268f484ebee40ed35fa3e89541cdc5b2c54fd36bc6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a0005b958e94f5ca9375abdbf56e963c5f1ee36fe6e6406a1e5948b9c10497aab811e8b7bc52ba8b3bdb9ee12b8569ad0f9d76d21dbfe960bcb6ca56c6a522cfdd342ff37328d57929fc03c04c07256e5a038546327ba4ff980d11cb3b74c7ec7d7
+TAG: 248ed6e7db4f9390c7657cc6d301622c6d317192c20bf4134856ff8e1734dd48
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a00d2674cadb53ed4c55fae9df44f676551a05ec3c1d17f8f518e08cc5f5bf33a1e66de0dc9d9a97464254371f0ade8f3eba04c1e0f57b259207a3efc89a8ca6b6af3dd0b46197369452b25d2c5264650d039803b17fd6e2794b2f3d3b10bbf225d
+TAG: fd2415dc9713abb7d3627b2a37cdc599cd48a52b735f61f2f6f5a01074cb0e41
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70aaa7857849ce279450cc984053f114c37603c9b0e370240458d045c16ce66d3d36da33f1b3959c4b39407aa8d6de3525850528092243f9d1041c16513370b0792fa3061f8111efdb5b457a0a4b75273
+TAG: 8e464b02fffa6d02609b3b97ddb23ffbe639bb38a9fbcf957d40e2d921404944
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec7038f0bf6fece903b0207d88fd83e21106479ca898a01a659871881ef921c2373afa8d20d5bf87ffc942ac8860c881e57debf915f1e2b3d45c4d184fb6de588ebfa7c9d3c5724229a7bb0112f6f711691
+TAG: c2b9483895c267b9ae1e63e5f05b58cad1e17852a7d78a3384ec18182473f9d6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec7bfa566b8ceaea2f11cdcf2eb2625325ebaa4cf617c07037848ab2d75683c5cc3644f4a0c423625cac882fa4eb7f457743918caf694efdcd227dd19cac6c97f007337d6507b3c6cd49aecf5763a3a27d3
+TAG: 05f2ceb2b282eb01194ee4b83f821bf2c5640de9ad459b0b481fc025d819a1e3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec7634f9c278cca812dd04d90a2b18e2b734826737eb0a48aa5a2efba97210f828e1988a1d1653a4e1e909df695a5edc93e2dfa40da1f278cff75ef9365ca91891c731bb1a64e60f80a73439127f52f139c
+TAG: 938260be3ba304cfe783bca022277f08325a6ededcaae6ec13346dab64a1c9f9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec7e734b729e47a6bbceff9255b53fc02890d933e482c07d0c0c5a18c9877b1625d6c48a00fd567756c732d5f9709c974f9d095ebb5fb629a41d97c38a59d79fab43d99a39cbed73564018133ae2656dcb3
+TAG: 17f65c87b378b88892b236cd0798a051750dee67560fe02e8a2b177e89a2281d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec7fe23daa52af185cdff261cd4710e2f77b492497f9b31098e1d48391963eaa348ce8b03ba8b1f2cf11f8c056772b4b1bfdef7b13f87c122f373e1c8037e81c47d948fef63ce1b7087fe5793a0e7c9411d
+TAG: 94e89e1e822d607326a64f9c2646b4bcfd893da47d6fa328f4d693aafed1217c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec7fb365750bb6fe2e301450ad4bf8f2335cb2adaed0d826a561eae2f75d92e906bac79ab0fefb4a725e8fda2cca77a9e9b8d34ec28d39dc374c019d3d31e8021c8c58ba5602946c25c2cfae2e6c870dc83
+TAG: 2aea8761f582c1225a3dd8ac0fb0e291da33596de0ba5b96745e9f7ade1ff3d7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec711ad07cc1411f3c91da70d6166e9ad82b459ddda56ed8cfc47fe729d9bbcd72efd07c24de72c13dcd64f477f07e067ad32287fb3e684ae717d1e2af444387029dda4b4d7717e2b3094c2450308f1a7a2
+TAG: ab62c27cc4af2c190b0a9f118e97015f2223ca97027622cf79cef4064507a152
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec7506b06ad0cb143c6bd91f7ed6d18cda59d18bed2638110e8c1757373cabbe405348f9e695166f77445ef05c129a8c769696fe1a2d6603a545d84a7a43fddca44678f670423864f107cf6ac2c417cf76b
+TAG: c37f6e065eb233c3ae05785b430362595f744f9c4888fa4f348b4d6f9939d6ca
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec7e50c9028c4c22435241f5fbcf7e3cc8fe68f82d15397cd0db0310482b64cbe7f3184aae4351a5164ae8e876d3e096aed938bd14f4ef17a13fd1a7afd9ed1b77007eae58eab90584b0c436e5be50f8144
+TAG: 20beb4af1b1cdd488e1b031b2ff48a277f2798e76b144fd22e7a22ea8545bcc1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec7b9a3e001d8f924a5a686d1f43570c24833dd465cac5045c62f8ded921d9c6a574433299000cdc08c890344742910ba62ca174a5e7f5bc2a4428582866b93323e45840d52d7d24ab9416797d996b237ef
+TAG: f60d031315413551a8123e48dcf1b6508fed04ecb70d0a1f42b3ebb25cff1991
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec74fb15d20d588fca252d1c6f36d0b45fc93f5f9b3b4209cfcf0c3bd90e10cbd3350c20ed527daad546dcaac4510fb4e1dd57e7c3b910efc6b80d97d71e2f0e58e5c420cc760f71c8507e24205327ef096
+TAG: cc91810c5937a7aeb0a5ff9fcf8afac3c74411d538a026480ad819ad4957e147
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec7918e47faae65e93c30ff8ce6cd5c13943597785a302213b2cbab77389b9ea7b5cda01aa73bd5bbc23fe51097aa48f9a8b1cfbf0071b95766acb80999d74fabb0950b174d6966cc5f829dd6df292fec89
+TAG: a2086370798d6ed8b61468d79894c9b01fe0fb551160e2a882ed3c19d6554765
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec75e678235a52baf76fd719e1b687f6399ebef2fa3ccabbbd397e20fb36ca29f8e4458c65cccb520ca296bf1bd9df0688a12d2093e4681bd655370b149eb5078c4ad3108693868ef934db417e0f131975e
+TAG: 00ce4ee0901e3d66f329b4a22644392180a63aac5afdfa0954ffd020fac3410b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec75781276b77e09fe5c8c7ae1f9baedf1173f7c62ed03323ff3da0891a24fea5c200e13d8a24d7b096443b1ab8c7bcf63b626ef7391006de62947726cfefadd7a40abbb4e5ea2f3680f568265908533cc8
+TAG: adc7cb6fbabc13b41d1c654fa485d7e6ac32a11d1fbf01c35c86e10bc25095ca
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec71a7967d34722c1a1c17e0f4a8fcf79560ce52a89c25d5e6101c959d60136d90b31bc6b7cdcd3c412c88193ed65fa080211d7878441cd43d79ca913bf63ab93438db9661d665b2c17715e4881400d205e
+TAG: 6cff6b2eedf3191c234a29df4f11e8d3788e7464de43041992ddbdc9d195180e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65cc3a9f4794d5f7466305ba8b565db4db6884e13834e59e80fffb311bc799a668f9a45c6cdf2cdba820ab38ce77f11001419a29be41eca7fe7fb5062ffca769d87
+TAG: 1b8dbc9d2f3469ac2776318e035e2a841f89f3843e4bb45739ff0f059ecf5ce7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65c2fc8560ead0b5f0c27cafd6de5f02512745b6eefc8f06e05f78100e02fb7c3d3fc7ba933f9ccbe74dc029a38eb38857a2ff31987cd7487e4e7d575aed1d3f4a4
+TAG: 53d3adab6d93887517ee94e003c99170646f245f96d3a3393d0fa2d7fbbdca28
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65c2e3058dc516fea6a4d2b7f6f78392feb89f50b4c31d547b87491637dfc76138fc2e05d9adf9e909222bd237bde1f5251691749be9722fca602de051aa912b5f6
+TAG: 4b1a19c14d6375d26d5fe13b6e7d0f6defff02347b2a30b7f1eb7559140ed784
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65c2d4a20fb86c6d8c179b9a3db7685aed8193b70f89fbb23cdf1a45eba1603ce4b56bd08902c1f2ccb71653771646f1ebed4e1447ee4a2a1f051345226803d9fb9
+TAG: 18e9766e0fd142f3df6d50d6105767af8469ea47d87f9d1d29e44064addff0e1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65cb486ab2fde1ede6b288fc2fdfef3059bce9a39b0b8c6329233483d5d09fcc8cc7072c282786b9e97468fc0658f399b96480ed5d962deffc286f9dda5d0ff09b5
+TAG: 06189cb89b88248668efbac9dbfca5f5aae3f944a0d9bc5d04984265ba0f98a8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65c81ea1eb344b8134dc04aba5544efb3919b660d07ab6fb51fd92d51571b6661fb423ccc940eec06dde0b3a1f84dcd281cda7d0704557ddc26d3dd4786c4f0abc2
+TAG: cde6cce07d37f8a7cea1036d81f1d7913b788d203024a641359016dc207b302c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65c1b72def705afde196bb1e9eee770b1d262684454c9ceb78d1aa675bbc284f4034686402f182b428932d0491e1383d6d40dd39adb1a8fbe569d41174b22789499
+TAG: d5b2eee6db4da8d39efdeb0296fffdeca9712aefdf27014a4f20df22e9fd80f4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65cb16fa75e58e3936b12f5a15be60361f6476197ae6035ca1dd02ab7828056c37602e83c7a001f962b6e47e918e76719caa47990d166f2644525a497c29c8e6520
+TAG: 5f1e5859fdacfcced1fae18e8743bcb51e6ddacc80565861ad265b4a842447ab
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65c18c9481984dae1e6598050cdfc3b519b7a3001851f48ae2cb7c4b6929d70349490cc87e415f413cb8f5a32f21f3f3a6f11642fd706329054f853970e322fa577
+TAG: 1fdc5e1ea310b693cb0db4669a7d20039fe79751ea71a0a5e50e7e9678b54e6e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65c4e5c7e8ad7229c6644691ed832c7fd8fc33f3b4406e485fd34fe13a47f704b8fe5feea2cf810842f439a388a91d6e3be37865eccd9b1c65422345abaa0e18b65
+TAG: 23a88c90d015625d9ffccba9bdb41a136e95a70ad0df1c7fc609fb734e44c40b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65c5291a5864e8c0ed12a265b82b29fb5220e3f6cfdce39c963e3f427e432f17675a2d6dd8aa0710e139133cef883dcf492e0e80a6cfb9c562d4cd52356b76d61eb
+TAG: a9fbbca12da8f59e58f43b11ae73f0ef0274926e7e212f5ddf69fcc4b9a112eb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65cd61b5249ea9b3b3c666f8678ecff5a82f2d4ec4ef2a9a5593a6819b3cf2289d9dfd495bb7205287b59b39c3c200778e48be9b8f7e182672d1e3eef344f995e86
+TAG: 083194cb75561f1ee4f255b6e1c13143938667449ba4f909313cf1dc5a99d7cc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ccede1c7ad2fd4c2dfe2bfbf633e91e498ba125c0c796275424a807fee73c2a0a88e7b77fba092c6a5fc789bf5f975b7ab69e1d77d47396f408263deef0274bf2
+TAG: cd5158ee26759b08ee31afc9933eec974465a0954371e472bc53ad5a4e43fd36
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65c53acac65fd199a57853e45fee47f2d63780d20c5f3d2031f58468d585d19103847b4c133befe86710ca052e538414f60b6aef087343c2d57bdf4b22f6897879a
+TAG: 1d5600ce43296177ed0db1d3bb82580f306b45e2bd8c562ed9687762eda0b0fa
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65c4b6e0719e96decba0ba788ca9d63aad16a70f45817484f42a16e3fd8d15ace3ac86679b2ebafa1d985b33dec842d10c2114975e48d754a3a1236386200cae512
+TAG: 6bfe3eb4ecc6cb799b21dfd144099deb6b6276744b834ac403b2ff3a1e37c719
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65c209bcb36a8a9ebd02bee9c86c44b26c1622eef05a11049a9a3b7e4f5d8e567b7136de775b1d58a75e17bda90d48b5af3e0bdb3972e5217defe6a915b1e2100e8
+TAG: 3262cec06826c69dee68d432b127ad95b739ff8af703effc6aa1587310543e05
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24cde36b3f4b0544c8fe91d053ae0ea43888d02ca84b7cc04d47627b2c121f9ee0abeb65adfa70109da1f3e5e4eced94d63
+TAG: c1a367093545c85e25d37d71b601e3ff5426f6b90564b87e655a5a9d306a1f89
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c4f4952a63596f2f190b5b71225b319d9de848c09bcd679c9c59c9e3c7280a45b9528460a993d2814d9500d8039ea695d
+TAG: 97b0acb492d9bc87539052774523126e2afdc66f98391542d350a6ee09358465
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c98443b42a4d11f9fdd8fe7e73a79092de4f76e5bc1895da177b313d28c9ecbfb66b267ad1e5f4163dc30b00dc7aaa2fb
+TAG: 71c74d88ca9057947b6ab17ab0d7b10d432b9231086561c2c47a680deac5b45f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24cc761a2d35ac39cda01c6603b44b449d1ba10219bda53c7e784c587c846bb942297e03c4581f7046dbec78a88355e6053
+TAG: b62779f93e1112dea7dd0394df55e3a5eb28a8965614e5f3e857d1ec152f996d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c1a4849aadcde908a5cef72de84a0b724f5ca382dd2a2ac408c60b2450ba160383a7d925e197f27cf02a4fd3ac047e31b
+TAG: 1bea6a5b4ff72a5ddb7d61c4a625c94c95a796bf4834f1cd2ac8994a6d61511e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c1871b5131cc235c3efe64f909dd565f1a967ae994b64925311df09346fd89978c31d9abffb920cd5ad69c8a341a37ddd
+TAG: 947a5028178d6c79bc87759c6deb47f317c6f71bd8a28f3489d338c687c3e645
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c16a7a6e2b55d6b358ad7f6f1dab91e5be23ad07133f17e19beea23fce1629248ef35e2f846c7cac61699a28f68f7fb48
+TAG: 49f15b878e8e585d89d692fca8028d1a9ae97d6d3180c5a6beab70e72af57bba
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24cf37c254a7ef310e46db2def6de90a9a4c5a7a435aa3f39410ecd40fa4c427e8fdcf1719efd3aa28874a2cc87dddbc347
+TAG: 3a64e4d5a2a6232570afa75448b55da7af9df0479087f4b549cee27349f21452
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c1a77036ddf9f410e99c4263221f369965767610d443aa4f97613ef8b920ad35e276f1fb661afd6504a854b538ac03a9e
+TAG: 984dd700f899d5c69f01ceffa0fe15f652732782e3337888f89ce52f0acac05d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c0ff30f0d0976b6dc539efad00db683fc4079795b207bccb5c47dc9c56f9206c079414611e5ddc86e91728ce2a899cc22
+TAG: da0be83eb571d4924d26f4fa852203cb52f90c889e3182a4a8f83f40ee614717
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c68d6bfd8d65f7fca0827d4a8e317a17bcbe243c1be513bfbfa3ad5d6902a73e9f6629bf6a97dd5fc3dc986e62b28a962
+TAG: 3f7820ef00f0359372cb177fee952807d99bfdbf297511708c3911279e7d7970
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c1ec36892c4aec7a141b2b705d6af99aa0012c96800ce74c83d46ef5ca174e11e1d2dd657479271ba5014982973c6fdcf
+TAG: 2975330609b65338054161e77d98a3c5d9d0a85468cd8665bc56615872685e25
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c2ea38df25d12380035c5497a5410a5c166d910e5ddba29c43991429c314963a13639cf5366d98126f8150310d4d0f661
+TAG: 33f6a7af9c8668e295cd65b740e130b8d839e85e54c100b9ba0cd091a96e8967
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c1b59a9704dcccb0ba4407407dc3a55234d5c4340f76e7d32145485aff600a6c7bb83a21942eab0ff5a08c697c2d95750
+TAG: 335f2d7f5a80a3af3eb7f580a68435f8f95971b8e8feca59a59cdfa02fe79525
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24ca7e1b906a14bf949debab4fbf3430e2586561f710def5abd1a2afa16e7c8a04b82f65318f2eb510b20f9b145f807cd98
+TAG: 295d24d9140f531710e82a604266a66fa59acaab3bdc5cb272e033e35e4a4109
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24ce93705df4ac5e2b1d94031736fcb21858808c6572659e1b2e7396e2ef4d0bb4e6e9a38d457ce308668f987489e65e355
+TAG: 2b230eaef9a1c9eb11b0e54fd694fafbe85490d335b070bb0fab6b3927bccb54
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3239260496d89b2ae2cf61e23716c9392c8df5595a4d9ff9b18c5c89011eedf0
+TAG: f9b2c17c1111199739a8118398e940d3c7809f650fc4f749f8a997b7828d0225
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd34ed73e1e38daf514f6794bea52891471d3cbd54b41852bd79c382092611cc23
+TAG: a9e0c5599b0a80b3fabb391ac8e5eb6241cb3b7eddb470b35823317d876aff48
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd5ad87c4b79cd127461c7c81e2a89df313f22e9df297945290eec382e3f5b847d
+TAG: 917335a93c6539c5478f9932e1212010af0fb3be53b4570b4279f435296afe53
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafdde4be6f0941524ea45d928d425b18aa21198b73a57fdf0eee72a09ed80ff9173
+TAG: f72dcc819f9270519382a46bb2c3d183cd6638df9b1328f1b77845a17d948393
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd22aa7d720b69f14d41ca4f1fd5b627cce3b96c43f7dbb158b8b7a687c639a55c
+TAG: 355104ff5be9b05f4c0ccce0895566ddeaae81a0b70354f36e54d782bd92a022
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafda8dc934193aa131cd28de9eba4d10671b5f6c791f348edd87d5660e05d0df954
+TAG: cb9c764541dad6f9abb36a184959231320edffc947de52d8dbb89fa7c3444bab
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd4ef436db63d8700c87ad9617b17cde7dfa2a54332dc6d48b606de01499b75097
+TAG: a7661889cee3bd8957512feb38ee04b7cf90a80e330458092367a170c9498ae6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd003d83b5979e4ff831a481c276ac978cc620c1393ac8ade396678fadb6d43505
+TAG: b031c691707b0458bf880e2ba6de5af37c294de01b19c27445d608176969b3b8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd7cf82d85d30368ea432977cebef56dc2380fbdeb9d6290a5511b4d0fa0e470b7
+TAG: aaa1f70b6e9002f1bc9043db6594f5d66bf2a782a8135b961dfce223ef061f41
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd0af06a8c384db06121076b6536344ece584ef5ff6fb271dd8cdcbab7d22f2dd4
+TAG: 7b705486d0b28cb54422e10a03bf91dbba101bcf9c3cc4dba4cbbcc83199abcb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd6806e9b125995d67fe2b5c75c1734adb206e13f2f213b2b5c7708f7ba137af62
+TAG: 0de56d99934209f009d7389e383f12d09ac07724f49275dd188d00425d2197e2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd590e1abae25a46e09cbba17996776fab13afe03915d2b02515090383cc35b911
+TAG: cc01228f96cc8580632cf818c3de230b6097f55a65f9a4e2550b1a5a39fd3cdb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafddc721890bce1ff4ab0bbf9255f50e2c8543b96bd5abf686999a89baa6fc0c51d
+TAG: ce011ee3476ee7787f01bea0de62662371360296d193afb8a96607d8be1262b7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd8d20aa2b67eeb89f1e31a15c0a855264bbf3124c0d52ffb5ff634b88ea72c0d6
+TAG: 8ae0c33ddc5509a53a24cbaaedd988d88438730d30f5327421bfe25b9b4617ae
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafdb65af1a48d566d028edc73b60b1dd701748fe8c7eebf301de57da0496c75ef66
+TAG: 893ac93d34997b313b17e4850e40eeed0478e59e2fb10435525775dea6d80615
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafdeb1f4ce5cf4a8e98153b8abe5d1f82d47b7a5bd7110d83e0008c3dafdf355ca0
+TAG: aa07b266e189c0d16315f46a6cff4489b88c1de69f9af19ad38a8ad59944b80d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26fb78222b83627ed842ee9adaa6d0b3e89
+TAG: 6be1b18f1fc7498875d6976cb034acd422796f9107cf51b1f208abb2c934659b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26ff76657565de790d0f518d4d5f3826ae2
+TAG: 1817814f45b874b2bca5cd3515c110133865007e48507e7926a7dbbe78399dde
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26fb9f156baa62dd6629b90293fd1e94217
+TAG: 6f1eaade9656cbff954c2227781b072b1e7480daa8713c98434d123f5e9c7f85
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f5bc91b96c2d069f32102db6183698c34
+TAG: 4de553a35bf0d79d3d7eab18c2753cb1193df3778a87c31e890665d70493b9c0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f0e96d56f9e6c9084bab8d363de07a4ca
+TAG: 121e437172b97da60fafb657b256f3b1234f19b7a5be55c520c625678428ae48
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f937956187337b8bbea2c771e28b67094
+TAG: d75ef51dcc7bd1e3cd5607a6cc5050a1099887d218f1e46fa16addec50e00279
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f2be718ad055cd6aa6d399f2b200b2ff6
+TAG: c11b68ca206595db5c053d42781976d01aaac4fc8949943851a44defa57308e6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f089df25c674a122d37b4c537fe9551db
+TAG: 9ad8169baa0cb8f253d5acdb61881e1a194ff2408b1d607b521aeb6ffaa1f1e6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26fd79d75b09d2bbdcb08ffa18b6acebded
+TAG: 5076a5036d3dac1074d115992368d7079b76f06880960f5846427cdd40aff862
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f74d8a37ddfd26d72696eeb4c9550d2a8
+TAG: 69ebbb8bd34ac38d76daa2628f4150c90462b39604f086c6db0908947ff9b3cc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26fe3d33c7b9fe7f8c34a04deadadc2c39e
+TAG: c3e73ce10d1a9b5db3629142937fbbf2f89a0dff5e40bc78205d19c5e923850e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f86be44f599458e4e20557be50dce8cea
+TAG: ce3441c2ed9f42796e6f02f4f32e895e4b1023b9e3fdcc9fa4fc5d1d8e3bd658
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f4d8f643745fcdb67847d36d33f809658
+TAG: 244dea720c1343f1607abd2d815cf8d852500293627c582375128663f5818ff6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26fc009e1ccf36f329c00dc4ddad841cf42
+TAG: cdd0baa94a8787f2187cc72aef9d1ab7588cd3078e9a6070b4879c646aec990d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26fb1996a1cfc834aaa27b46eadb95e60d3
+TAG: 1d5e8c65a40c8ce94f149759ce71f22849ca7f53a88bb4cac9b73666a6c38be5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f23bad46702e72b3e5312bb417e4d514e
+TAG: 970c912e1504dd788c1c1636ba556508036522ecbf56d03d291bbbc42bb760f8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f80c9a62b7d1ab8a5f2b6707ea4efbefd
+TAG: 0bfd0e4b9054e15eb2ac49623d250211a60dc0ec62e54257daa85d6232e02d7f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f80c9a62b7d1ab8a5f2b6707ea4efbefd
+TAG: 224a0420b6610462d0d8099b4f9fc1a5e447ba908880fbc07abb361d1982a9a0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f80c9a62b7d1ab8a5f2b6707ea4efbefd
+TAG: 9bb6e577563d9bee6d3dd27faa1237ef10aa5ac023febe79c76c3775814d3b47
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f80c9a62b7d1ab8a5f2b6707ea4efbefd
+TAG: 44d7a0901d8bdb562090620ddd9bb859d15f7e204ac002d67e92e7913c55d5fd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f80c9a62b7d1ab8a5f2b6707ea4efbefd
+TAG: 46afc97bd0729658c723ff59ee331769d17776377e8644c9697d353d1fc2346c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f80c9a62b7d1ab8a5f2b6707ea4efbefd
+TAG: 90c29b0775581dbad775b08e21055c92c4ccdfc5a0196fe69e28c512087a1031
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f80c9a62b7d1ab8a5f2b6707ea4efbefd
+TAG: d0ffc9d1a613960e32d69641720a3aeb974d862f8c261e4218c76acfcb9752db
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f80c9a62b7d1ab8a5f2b6707ea4efbefd
+TAG: 6e4174aa4ae8df6a48491bc3b933a0a62e0c0c3949c0d68eb0b0a961ea1bd9b3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f80c9a62b7d1ab8a5f2b6707ea4efbefd
+TAG: aec035b0fe1cc86ee58421d45478d23ed4754e723b97088ec633857d89dcae64
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f80c9a62b7d1ab8a5f2b6707ea4efbefd
+TAG: 3b1999f045e81dc20d4b6b862e1c8d8415a82ec1c8f31ad3048961cbc84a125d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f80c9a62b7d1ab8a5f2b6707ea4efbefd
+TAG: 1cc9cd75540b558385c25cf5e47c96250e6ea8848bfa392c9423dc627e16071f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f80c9a62b7d1ab8a5f2b6707ea4efbefd
+TAG: 642d928ca7dcd41bf99e95f4a16a5e553fe813e2a00ee006bb5f2ba1097aad60
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f80c9a62b7d1ab8a5f2b6707ea4efbefd
+TAG: a6eb3d7c58027e6bd99dad466f52089336e75b6a0cde6b9b275fc43b003b65aa
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f80c9a62b7d1ab8a5f2b6707ea4efbefd
+TAG: d9c85a0ec846b5d67d41db4bc7e633521a37c22d957cb2ff869c7dd164cb27c3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f80c9a62b7d1ab8a5f2b6707ea4efbefd
+TAG: 784d2e68dcd21f0fea8fea4cdf6701e3f6f5a18157917aab6bcc11683bea170e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f80c9a62b7d1ab8a5f2b6707ea4efbefd
+TAG: 57b6bea965dc3fb9d12c0b8ada2af98ddfa1bce5a52d68551d222235358d5df4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f80c9a62b7d1ab8a5f2b6707ea4efbefd
+TAG: 2bd04e535587a7e13ae0005e1e340193a83c5a26125c8f3027779e03d4d6aba7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f80c9a62b7d1ab8a5f2b6707ea4efbefd
+TAG: 2bd04e535587a7e13ae0005e1e340193f5512f6d989e9bb7fb5b2652487a8095
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f80c9a62b7d1ab8a5f2b6707ea4efbefd
+TAG: 2bd04e535587a7e13ae0005e1e3401935037c1abfc4cef0a117ce1a9cf01abbd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f80c9a62b7d1ab8a5f2b6707ea4efbefd
+TAG: 2bd04e535587a7e13ae0005e1e34019313ae94806c664bf091fbbcf5d4790b5d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f80c9a62b7d1ab8a5f2b6707ea4efbefd
+TAG: 2bd04e535587a7e13ae0005e1e340193e73c71288f70ddeb29431f00f224e6b4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f80c9a62b7d1ab8a5f2b6707ea4efbefd
+TAG: 2bd04e535587a7e13ae0005e1e3401931a102c999f21f07d75cd66fb1c016bb2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f80c9a62b7d1ab8a5f2b6707ea4efbefd
+TAG: 2bd04e535587a7e13ae0005e1e34019363231b79453640e860558c0bd2225db3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f80c9a62b7d1ab8a5f2b6707ea4efbefd
+TAG: 2bd04e535587a7e13ae0005e1e340193f826885340f9f759bd817d8e2bb749d5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f80c9a62b7d1ab8a5f2b6707ea4efbefd
+TAG: 2bd04e535587a7e13ae0005e1e340193ce3c714129124c90f3d5620783865a49
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f80c9a62b7d1ab8a5f2b6707ea4efbefd
+TAG: 2bd04e535587a7e13ae0005e1e34019327ce50ab80dffa309ce29050b8260cf3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f80c9a62b7d1ab8a5f2b6707ea4efbefd
+TAG: 2bd04e535587a7e13ae0005e1e34019349936dedc2eaf8a53240823dc5946cfc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f80c9a62b7d1ab8a5f2b6707ea4efbefd
+TAG: 2bd04e535587a7e13ae0005e1e340193bea35196ee1135b5bcaadef14c846e8a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f80c9a62b7d1ab8a5f2b6707ea4efbefd
+TAG: 2bd04e535587a7e13ae0005e1e3401938af4577fafd3e42485ef2a0a518e7bc3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f80c9a62b7d1ab8a5f2b6707ea4efbefd
+TAG: 2bd04e535587a7e13ae0005e1e340193562b52e327e2c2fe1694aefadb5430b7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f80c9a62b7d1ab8a5f2b6707ea4efbefd
+TAG: 2bd04e535587a7e13ae0005e1e3401931b2f384cbce7b01a9a0e8395b52df007
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 3519ab2b2943d2a50996628f6c26bea29f84c95af4c128cc3af012bb358ee9f7
+KEY: 481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8
+AD: afa22993a340b9b3c589c7
+CT: c90e0c2567341ea7e9d968dbde46ecb46ad78dc8be7d47672068de66d6e7eae1bc33ca235ae35aad13e540cc9f0714dab00678652cc476d57c543967c39dddc9eb9045fddd9fab64fd564959daf731fd95181a79f4e1d5e98ad446d8a625b68a1185d14f4d17a90a23e9f63e3470c37a367efe6765da9174fcdef198cc90d4acfe1ea34b2a38776fba7dfaca92b99ec5be216e7c196f1a615c787f8a11dac7259b3b6982d1415fe53c5e37c428099f6aef8a13b20d77e482c0900528b10b0a008e5ecd673762de36b1ad38fc33fc5ec70cfb963c62a8f3d8e471e2cc863fc65ce54dccdd3d95fa449378784f4e39a24c3cdfbe74fd352b74fccfde6dc777fafd3dca970e63f5b07e8c53d7ea0f77c26f80c9a62b7d1ab8a5f2b6707ea4efbefd
+TAG: 2bd04e535587a7e13ae0005e1e3401937a1fb0a32110095bcd909feb3207714b
+NO_SEAL: 01
+FAILS: 01
+
 # DIGEST: f1402641d69b3d67d63e5bd137ba006c70582fc0ac760c7cc005f22b69aead4b
 KEY: 7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e0
 NONCE: 37446f5891d77df660ed82933f62be8d
diff --git a/src/crypto/cipher/test/aes_256_cbc_sha384_tls_tests.txt b/src/crypto/cipher/test/aes_256_cbc_sha384_tls_tests.txt
index 9f38bb0..c2b40b8 100644
--- a/src/crypto/cipher/test/aes_256_cbc_sha384_tls_tests.txt
+++ b/src/crypto/cipher/test/aes_256_cbc_sha384_tls_tests.txt
@@ -23,7 +23,7 @@
 IN: 936a91d0b5
 AD: d2c0267218cb7090c61713
 CT: f6f8de8547cadb667c8c823a2ff44444
-TAG: bdc80dc7de80e5faffb40880dcf4d20f706109ef1d8fb6bed697545eeb0060e77a4c251b2e25daddee81248b6d121fa2
+TAG: bdc80dc7de80e5faffb40880dcf4d20f706109ef1d8fb6bed697545eeb0060e723a2dc7485b3546d50b6ba7fab863b28
 NO_SEAL: 01
 FAILS: 01
 
@@ -38,6 +38,2588 @@
 NO_SEAL: 01
 FAILS: 01
 
+# Test with maximal padding.
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 911d133cf637fd05357d538ebcc6081b8907e8e94e5ecec315d055c80f948a82f4c14e1295b7acaf2c74661cc41fef86
+NO_SEAL: 01
+
+# Test if the unpadded input is too short for a MAC, but not publicly so.
+# DIGEST: 2e6894abd3cfac4d4020094d02c6db6450cb7367b405443de9b5f2ab444b281848ef5da3aed9ebfc054ae89af094ddd6
+KEY: 7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
+NONCE: c55b436965aabe477e0cdd46be99371e
+IN: 
+AD: 936a91d0b5d2c0267218cb
+CT: 19c5729c83b0d6f8a120a33dfc5ea4872d2916a5c75fd2e16caf8b09b4674c40ccf5be816e9dca5768c126937051203ba63c6db5fd58d79ea8556dbc44da8da3fad14be20fb3eee5f150b85f2c738d9da8f128a00aef3157768fde594679c0b8ee998006fd5a88e535a95888011c60e63706441f6838d4e8ac252631f17d1211b917ac36957bda3d4937c463485e0eb4e94fd6afa67395c1baea194b494651ed88bdafcfda411fc15d0b03426fa2a15cd92ffc7bef9bb50b63420409a33a0e5fa494635f9ee36b7ad27bfe44c6470ce7
+TAG: 7216d0b493b0a0316502c09f60c040143dabc909747dd0916a8c74df15bab85a19152db1388d20a9710b0caa832e30fc
+NO_SEAL: 01
+FAILS: 01
+
+# Test that each byte of incorrect padding is noticed.
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21eb1103394d6c20f66e3ef30fd881b03cec92510c8007d91f913ab27cba90cf87fe2c0ff592985d29f2885bd434b14dbb5d79e5af098fb8a55cf582ae3b011c201e18be26428850e55b06141885c522172900b66f69ecfaf6aef1c4279e00bbb085ae590a67aaaea7ac9b250f7f1393a576678c3d6f18e4bfeaa38a1ddc3da051fcadfc7f7a625ca43987e4368eec351ffa8f1039424ca58e20bcf2d03a4f6ec65e2aacf6bd3eb27aa9e701a845f4d2786faa06bb86c05ba2b15e059402c11745e187b83d42d17eaa0a4fb85279ee629b5
+TAG: fb00c239911055142272c0498c475046b2e2cf715a233629e4bcf9a078397b76f87326b6d0fc07eb4f629d78e09f1492
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21e01fe17807178a0df51974663962208c1ba1270baaf992fd88c052dbdabfa44192374b683b098d400e37955844ab3908718977abc7fe8a65399742d29921a2dae2952e698253b2d669532c9b4bc4c59dc15f08a581b8fecf882a60897558f62ac2582e4d9526a0591083abff8c225859a5f0754a702094dc01e7584577c09275f58916194325df46a8343445bbbf1dd2311c750bfd97211ff5aa2d239dba05dc0863016050b317e40df5239a4baa79e11f2eba21d6467b89136e83338e99bc176009045248d3d791a16d68d9297d53560
+TAG: 8c4822f4d7eb6c2ee08e9588f365a78eaba1fdb94fc4d3c13a69bd8509881242b290be463ea82a4f93875d07a25e2519
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21eae4d4548797c0aa1a37c4bb53ce0814b8690fbc4705088db32992b5f7919c760d607f538c5619061f6d3e833080fbbbf99bcb217254497a3e45d2a3022b78e4e0fb8c97ec3aefbc9e57c401978d89d354dfd3b0ecadafccf9372231eab25f8e493fc30c8c15f345690becd5ed3a29980af216ab1d08f8466703b3aa073fb528e412b029ab9dce6c47860704da44b1bfd1c8fa6250d930653b134463e163728cecdb48a9fd4341cc546d5b9739766116f5a502cacdaf5f6940d227d7f5e2904cceb4ec82097100a129c2c9baf08bb5613
+TAG: 8765a1c2a337b214ac835711c74f1e3cb7716ab1826d0410ff77a0c765dd7b6fb45e6060bc4b914f2da3ff3a0dc62748
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21e998a6baa8e2913ede9326e76e26b60392521c48655be437422578479b6b8d752ffe38044900335543604055c131db58a4569b69a2e8cd51fdaa6e52c862fed8ca0245052ea5fcb0af1f161d70a9989c53185bf3b928b3b5a6881bc28a8c6b997999d83481546be05eb5e1c577039035a2f6dfc3fe8b222f451aeba7d0bafc6150efe9f5a2b8a30784e5b2162dcfe3a047e9c69b4da13dab893a12a13b18a1f630eed843510e1621d71e079331ff164e71971da32e12b93236d119d28bfad495b4cea68e94fa47a385cc258a6e0ac7580
+TAG: b60479028bb567dff9665ddd143bb5a5367354a9e7c86d3d85652820fc1e7fdf57d7ce73f5b9cb61872b59e1a4eb6719
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21e153f16574e19aa533db209d4d58aa70e0c2ce2b52d9f5eedcca3f63038cb1a1ce4580efb8bf2e7f6ab0cabacca83ec2adab9431ff530bc8e595b8c606e08da90c182000a84c1b1594e27f32d256495ec90e5dd88b0ebfa77b213925aa523f9a578ac242ba561529448d18310a0c6ed8fece89718a8c28421ca93e26c1f461d4ec34968cafe12032e8fd0cfdbdb44198a4e5f3a1809ab5daf3ffb144f61e6c9f8e70df160e671e50007569f5110785856bd0523bf2da54d5031a13a661e73248808e20bb85a14fe9a91d10b45c8dda373
+TAG: c9de0c1c231e7955f74d72b07a0d0831c1798d22b36fc570e15f011d9d487c9d87359761d0663be18451745b3ae89354
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21e9a27f99c2f905cb3adbb1dbfb2c93c98fe9239acd2a26d3d678af1fbd686f1d2a700143c401bff03868b5f6abc877f26ea0be72f5cec78fc1a963f8cd4b07b3a300a10d93cb9fc47f84d544b315ca63c092d51c9a9450ca16491ffec6bdcb25ee00d0505dd4a159bb02d0935d4b42d54cec9d987b9e20a3bdd2cf374d20ee991ed65ca77b1fec37b74084181b0ae6c61fad604002b1d9370addb1bfda0a660ccd1e6d99be3e11e5deea9221fd879670e8dd7b5f6d7d64742daafda3c83ad079a8723f42e0b67eb2ce7f5aa641239c0ef
+TAG: ed52de2984c80d90cb02a7bbfd307ba284e24fcc0d53516a110457eeed82fa9bf6d8d9a73ab1c1d392e5b6747ab3df4c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21e72d25bd0737c87458ad056c57bcdce99251e197b862a048080974a98fd4f3d1b7bcd403eba809709e9aa5572008f6da687a6fde624ce3ed7a1f314857a3e7039eb22a62cc8bc1a2c2a5bd7d5309a1ae1fb54cb536c9a6336e3c16d7ab555e0869fc76fa46f1042727640ad8cd5b16789321ea52f767c84dca21239c09f938e902ba4ace37a4f274b6835154d46fa54af05eb53a0b39384506948bff079551aeb4bbb5c4aa85982e02220eaa99cbd06fb09c4e20c25d74ae4ef184de14b627b1f28117064f71d1cf3cdc287051d1042c2
+TAG: 54f6eabef996d059014e08dbdcb603686fb1252cf18d4a276e7e9810b873b7324c1d8883b61372d408de973313888aa7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21e0baa8dc7ad61bfaa8ff40278e99200054dd3842f440cd98af9de08607293c9ce1294fc6e3e1a766ccab6cc44797760b42948838d78c2ecfbbf2f0b6d0e114c8bae14131b290bf530141412e609bbcaaa05fd629488ea02598c3ac9f28ff9a8c9e675bb04f210209a49789fcdd2603a6890f2376fc33fcef2bd3c238e7aee4d4690c74c482849549651aaee9469022da79b3144432b21d83f4cd137a2bf01e4ee25badb5fb03c7237abd8af82459e2d767f09862e0ce19f09e9d9740e38a564df15e741b5c8f972731cfdaf66ce59323b
+TAG: 76147fc56a0920c87407767f36f989b3de9e56c681376e221a4e8d50a89f63ba72b23b510480f35692770e1cc197a14f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ed3f275eb755496a78214b857ab6c9fdb71c61560bd3be5927c6c4a6dd110aea8176dfe91e22df5f0865ca1c0e95b7aec2d1df1c98dd5e7fc763e6e2a259d0eceec49c4b0c9d4122dc86d5eddeebb4fd8a7ec48fe80e17b95b83f21890373da5ba57e6d0fc06037e4d794e0f84c6c300cdb7ac342d9a94448050580d655de0e161810747702d5e5a999f519cb1065b627a15cf3beb1c8d9c30359bb4ddc96a99329bffb7ac2b56a9dca45204d5bbec0fd3ebf698c5cffce8b209785378b1d317e34449cb1ce406919cc59be5b27f6b0b3
+TAG: f5e47d0f303a5713b1322731d7cbe4a01355be0b1f20e4307163304786d63245996a463f3674518bb2c1c7895330fce4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21e076df49cd51c5b172f601f060b03a8bb61fc7deec13b0f821214ac4246d58f5e9c9049cd126bbbb9d3b11519db0e6465b424475338872e93dabfac2d188490662e72e49286ede26750999c4e4742e044c017ac81edcc40971fbe0cb2524818679e934eab3921484cce8c70e01fb56eace974494239bef8e7020709d6b78ed714661dcf70d9103ab61a291ed502e99cb23c607177f5961cec5838fdea2b37102f7c298bd1c137b47a1909b76162b04df4730c35c46ab8b32bbfe0c3f7aae32f8f1f08c653cd1fb505435ce4cf0d48828e
+TAG: e54d3eff517e9ebf8cdb044679849f3ab264bd0604a5b1013ed840df5c629b32bb181c59401f3a5baa8b7cb3cfe02c6d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21e784d93b4fcee8a8e0fed17f50e701b29d54f1ecc13d0ab6272acf73badfa4a554a49efe014644c6e4dfc59285abf6e56ccd6300817e1ce6fbddf6c7f68ccf14ff1f0fcbb5fed2452b61fe59a555efa6bc00586d365dd449f0d1682c0bc31271f16e154b309f5d24b0ccf227245aa5e2421a0a6d92dbe45f9ab9ae65e90d7bed4e8d1c1ab01be3117115971a496cf63b1e33f5650be634e6f3c89cfe49b981743eb31fb0de9b441608484a6f7ee7cda3337a77d25d96bc456a827926a4163ab02d6589fc0da7567825175b3220526e20b
+TAG: 263621f1ca35b5ea17f32b0d5ecacb8e0df6cb9533ed206ca568aff70e6e7a3c87369778d4045d4e2bd6267dd3f4af22
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ebd0f25a074e0154728d1df70275186f35d22d31b9948fe7c56e760cae151ccfa8d332c0269790c5351fe30589005500e36448faf01d3b664a61243618814b5d15c8b324435ec1d88737e34bd44a80d728c6c99823c666e8b474d94cd20df7d65e01b5b740243956973991d9e4cf55359b8effd5dacc87cf45c3e05122746e93771c8f62a294cfa90339ceaec83ec9b0cc5594161876d685fe5b6f4ee13ab9f023c3597557cbe2aae219328466b9c527d2c8d178d2cfe7c0dba5ea8bee27bb893e3199e1b3f0426c2bec57cc0c0780e67
+TAG: 5734c830aaf1ff9bef15e0005a759512d307499b439acb5209facde61e641bf6da386e91e173914f9b989d7c6f910913
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21e574843178c8cceffaada0e047155cb49866fc4d51e26a0a20dab8b78a02e2be901e0f10b0da38cc272c334c2f3dfd02d136adf200a93951d88149ac7f9aa593acdc18377599b3dcf6a33f7089b06f48899dd37016e0968d679b8aa8c3638cbd0c0f565c409b0ac30f962342d6cc780de8d047916ca4b38214e0cc1f1eff4f5cf9cf59c11d51db7c1bbe692251ef48570e0cb7f7fc8842b13a918c2fd681bf0ecfb90f267a6d40cc4a2b1322f613e9335f8455a153d435eeaccc9ed806509a6f34a773a2151c6352dc25999a0f12a7cd6
+TAG: e67ef58074f8778f7e931cc0876d29a427cbe2293c66a6ec6f2ea77d3f18e9b2bb8c61c1fc2a88ec47efb8f9eeb72856
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ea09920a6d82e0a6a39ce1f67633166ce032e4900c22940fd7eedc8756fa24ed0000dd4371e72138dbc6dabba6da21040aa05c5ab34285b10278cb8ff0362d5bd5a7ed17dfbe6c2671ac9deb97500dd135e2aedda0ff351748a0b31482786abe4b3f1f94b5a2ca3adfe1580dd9e55e9a261d18c235a69bff42e33a1d0506226e51fcac944ea4d7ed66482294c799a3b9f41f959219ebed1c509dbc4f7e3f6e9f089002e65ae96cfca63ea847b0f53549a5c98b2f728bcc48b797a776f71e321647393284de8990437ab55b24209e6f513
+TAG: e355ab66d9d99422b86207f072cd64e118faddae568b14bede5824f56bdc8a8e4ec4206e6668ecbbe12719f11e4309ca
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21eaa444155ac1e211767a48f14a17434003b25ca3b4729dac1ce285e079efba7d9db0bb5c5f9411dcd18ff952002950caf42ac599a56eab51813d662564d09fb1d2822dd01e1d048be5759b4bda1ed37e96d9489ac190e5bbf97b92c07f9d38cf517970bcaf15d4228c9e7b2379142fc1ded9e42551b94c904e49dfe06810150953e61510460ba331d8194db052d753685514a7a3f65c13dbfe8a9f8abdc55cbbd278bf5707b8bc855d01d37abea0e64a6dd9ceeedc48bb53ecfadd3d5825a1b374d2fa313c6430f08da29e792eeadd8f3
+TAG: 656edb97ce82abdd15ad0102f10274eed3fce7469d3d1ed9ad7bf79a4730d3c7cefb4caacd6c65e4ebc82eb8239b62fa
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21eb4be0ee08bd6895cf91f221cdf9c8c8b27bc8ec03b62e23f4bf3ab4ca2ff8445e1414edde5f6ec2da50062cb1104ffbb9964146050df7c2feb14c9b5da22593128b6ca9253a5e29b0608be0c24a23ecdcd7e80e27a2c23e0163125cb04c6c0bd4087fcd53daaec3f1980c2a09eb0448e91d08d50349a522eace7744af6cb928c0d587b2039d3f6af992c53777e9ca285ae7e193372a0bd6dec60a2b696debd4277842f83227abbddfd5679bc5ee658da889869b65831ddf3e753bca6249642673e2aeacfa3735578462b56a35e660dc4
+TAG: 8086a75abe177cc05cbb7ff204f9f4dbc7df5f0402594f8cac784a4e9a61dc6ff299501d09357b80d2e8d792e1f592d3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e1af19eab57980f65ff17f4766ce3e1a75d648c5b75a524ed3ddb78ce224dc9d1d25fcd3ab498bae9416b7383fb1749e2e17db9eae79278f5ad805b429dc2b776766e56e1b9fa54fe55f09656015aba067c6e21a10abaa873f8fc3711b7fb865b8b77266ef169178e64a0c31796ecdc8efe20ce6db011d86cecc86af63742c4101733f50bc6fa2cf32e74259320767a65077e2ea5a214c45becf92a0d76c92e33c786dddadf994af73e120f6b00a0a72705c32f0507ffad6181ffa2643e3269988
+TAG: 000f9e00e028321755bb68893ead2c389cffa93a683b7b06415404ff1042edf6b605d8388e51e02011f0e9f0fe8b4bed
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e1070e8a1123db78c488335fb25848eea3b59f54b2c3efb36ba411158063d661fc78ea24fe776550921a57504a30c1b4a6e1628ef3044f6ebf5901cf087cd438a3292af0fa5e0540f63c2f6a30e31b25ad016196c56d724356dae0ce84590169b78dd3f162eecfbe9f3e925d235e84ccfd8119b0370fa6590ba980e9ab7b0b0005cd17937a66b2bd357378bd4af24808e2a99957b58a88c4e42648a992202cb77ef5d6975b6f99a6a178e103155dac58c7fce159ccd49165095736f7e9f6f89158
+TAG: 320ed9f9ef34fcef41178328e1d8b7e5950e642bc96ccc2216fed8d2f79a9b67ffc7a8b15405a806844ef323952c80ef
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e1183e21c4c4b3a1949b25212a6e25ab444b51742e7252842c99066e5d40ff6cbd768ac1474faa57994cbd7573115bc1e32901db9c9ee221b44bee08a2e5bddcb2dc3b344ba11a20ffdf6e85436f8ea8a630bba4baecb3dd8becc13e43e1119f7506e486006b7d30c88e53c628ac4f5036d27e78a48d1569e17dc810653146f0935462c32839414960e386f14d6c2aba23b7c8cfb3ef552527290f761be91dbeb4ae334a7fc2172f0df6ea40add363d13fc0ae89a6adbdf8b5e572f0986b03fd6e
+TAG: 0c6c693ff80c742f25c15112c1f2d8ffb1ac59ebff6f62af439dcfcc0bc26fc2a1a0ebd1278f14dadc4c83a88d596a9d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e153487ceb48b337d92434c202fec23521729ad4fac5c3957564a624a05a990f397f7475ea9ac9dcbac9a7fc243d5ac159a2c096fa88230960efae444abbc5de07dda71efc594918e2f23e2027b3c3e373f7d0bb5a644443dc21dfe873a3d59a36c15273ab008ccab72d54b7cc268c888a23479087adcb5db44c8b8c642df233510fcad86fd49753c4c67b96ca4ab1fbb43240ff4bd4bffd0cd2e6248478e69521905bd3cffa14ec0171206f3aa820ab469c407e3e973ec68ea1b7b33db0b0f899
+TAG: d4d295d5d90e00adb733456a9dcf13ddf32be15dc98e3f935351de4fb25f5fd739e3ca14cdb93e32d4ec24bf963b6de9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e13386025f26fdbf49f9a8528d4edceb016b6dbc3917541447e571567c254e2812e4b1e73417ee70ddce8e1e9e548d04bc6a924fec21605fe165044c09ec1785697ecf5cff3f606cb3d165678532bba5296e5f9e5e78552218ff92205bb63328f5d94c400f5b29ea0c1087a291f257091868dc181a4f878de672189caee4a3a70fce0ea22fe5ba3fcddd6ea82145f1db756bcd9056ddddadd18dd86e4c8c5af84ada5d1033ebbab986fdd695369fa726cbe50ae5c1b279e675c828cf216567494f
+TAG: 420b5acba090fd0be46fd1c740e1c2db53ca7e82f1c7f77c8d4730550c60d1f907231e5c8ffd8c8ab6d3def84d0c3d64
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e1efaee3e5a6c2c7d1b1b6281a1e3b5cc98e3bbc718aa32e5bda1938908a4f5eb9ee6aee6fb0ceab66c997483d86b2a0f3584ed89f6964508c5e20e04a2843a39d4389cdeacbf10a3210c93bcd4e16913f096435d823fe16d3718202578fe8ac465b2562ad2b4f74ec8bcf9d226626d480637d0f874323084c113bcb799d92165d255a9aa3c0e47fd7fc3a4e35f9420e176a10d08079eae8f66c35d0c493d625cfb65c79a31d2745ce42960946756a8b9705aaa3988210e8b67d2fbce4dd6dca01
+TAG: faefcc5d2da932f83753da9b939356b8a03915ac1239b875e6bc60ce1f077445456fc8349c02253e9b09e32213114ff8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e1a820991691205aca46b381bf8f93233fe3bc2a2f4b6cec65011e0feacdbc9a0b66c1c16d8f876e6d4f4471e1e05d86068444974c0ccbd11147c7887d5ed8a603ca745b2ebecd63e46778b3c68182f0e988d16d8cfbbd73b9caddede554e7991899870cacc90c947c5a6a2ce8162dfc90844fe14db5fcba73c826075512df5d5e0b27fae1d2e5becadb52da348372fdfaed53ee70e08d9bd8676af8e227424a328cf2d291303b354986b9deecb4c4e214a26c5910df8eddfcfeb6474ad5a50cc0
+TAG: 1a8be24024655b1d9caa38a982c9fb4015a99bf73847b9268322b6a7a425ca3bcb566d30f87c19b7a11b4132246a0210
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e14cb353a5d55a4f4c5cfe1bf4aa16ee329fa638a23495b178e0cd9913679e2b3a536510d2120c9a2c92e01ca0497b0ef1499856f0b175a6b6b633378584687e63a93bf623ac284f7af23825888d93bc6ad2cba70c25165f8d5267d454983da642215e4c1301e17fcfb9017ed10def81d70d94569d16159b8c7dfce618ccf60598b6ae256947a4e13ddc3a2ad4763218b51f07655310127d75d34456f6279ef13dadbbe603d908b86ce0c81b329117d6e345a1c706fa944bd4b558deb8a149ad56
+TAG: 1bf55b6373de32b03c0bd545230308f90a2a9bfd2fe3652a98301a2fba5fabe73e8f085a8ac1388e0f6384741d79676d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e1bd980f2019a543f039c92628f812910625ac8f1ebf7f60a70df929c4272583f081e9f56ce767d664be4f70a9d27e2d09dc2508ac4fa49f0604d764ca45866d7e3963f6da413dd0a0fdcf16e53b67df90fa7b04573b4959d58c25ae7e260a0a180dc453c962b95778a31ed861479a6102c4f66a44c4f6d83711852945c3b79b259b9889967d40c98064a9a2a311ef412c8524b561cc22a604f3ec6031735595b3959dcb8683eeb7d66f514027f29499bfbcc54414fe995339f0bf1d614bc817e6
+TAG: 1e6c9fff1181ee8e7354d925fd90e32c5bc90dc5f6f726ea7c1700e279fe6bdb3815e96c5fe29650189e305849ee9acb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e1f1e22a43024eeec8c9ce8c452d4fb434838e6988f659a467a6bc580c07910cf0b03556268da3a4861372e4453433cec64e40c610cb206ddd68a72a1940dcebe59a25fa022e814d674cd902010af8a3368efb2e525d0a5892f8c1ac87e7a5792b6e83ee98561ade07344edc2d555f6be08c6b98aceab6d8779c2b25092addb6dbc0cc2fbc0ac9e1fb229e3cb563f7bc1058773acf1ecc74e8c13ac33133c86b6d5bd4be08f65018fa8fba0b80e07f6949204609b93928a584e1a57e88d9aa9cde
+TAG: 6671e6ffed32b40da24fa9c67d9f53decd5e69acf57f82cfc291295bd9a16af68d508c54ca681abb0e9b9182d27018a6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e1e79398cc2f553413ee1a4c593d3ce344e30eb9010cc845db813b22b78a30971497bcee8eb77a195a6e8ac9ec80f028e9d63edb28deafb837c0e90e75bbe28a227b4df1ccf400210eda7320831ee6604911f8f7d9a4727988e8a09777d94f50762980ff58b065da2b09489eba74101d1d5206b5662af09cabe6498b14284f807f867ec00298b2d26e2b2a54cc533f570ca7377dfd6057177cbbaa3ae2daeeabff3f07711b5f311c4fce43a5e0526ebb19623a102ef2602a43acd470b5989d0c4f
+TAG: 0696c71729e7d71d16797c7c18d0d30713d3ca8b71b5ae5125e245f7652e63137c8515c9386fb0a441f1341253ee2d3e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e1804cbe2123e3e0a3c7db983310fd859b4ddc83a7146071e0f2cb2b6a34a8c256b5bffcdf23c7e1daab0ec0e2c2f45532486a14820eaf1ddd5c437b019e63e3441bc525c9aa159620c7a6220638e843fc51ebaa2620df79bf15b305fa3b6f26c92e3a16a22ca770df4eb4d0591eca6bd32c6331411d7d83497ab22fa8337c74ea5d40e0f4df73064ff6bc464c88d7bae72fca94fbc95cb20326e9bc88788de4dfc975917d227ad0fb45f4d8ef267de610188aaa1168c25e83cda89531e3aeb3d2
+TAG: 0903db0a341d17ca69262e9ffe0251dcd669ccfdca3251d8985d849ea54a83b59a9db08ad782a871679c0179547ab7a8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e1637cba28eadedf489812e31953ebab676a3a875b142118263cb4b18ef2ed49a1bb459a41c03b123cb6aae0688425d3033ed568402a2ac98eefba03119634f4317f7cc0bec9003896b84c39f9581e16dd7b4a6c9afeaa27e8f4d68e06a31c8886bc5fd63c74c492b541d9d5945221e5a4e84bb7ed93f1fcc6f08e2979eca1c92c618c74945d8a12c7d5cea90f9e248953c7d2f0a1d5090802a271d4617861f4e3a8d9c83e265402b404679ae7658a0e9867c1ea551bfa57677eb0db57b3cdf162
+TAG: 771628ddc543f103512fcec6b243f3320e52aaf898f22ad2066138cdfef21e4750a8f4d7cba249c0ce95a7fb18f827dd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e10039dc755daa4459afb6a45b4fe0a72115fe853aba0c9cf25bc1597f085cd9b2357db3f77dd4eb1b806527e6784468a56e501a2a7e813eb06847f264a77121c815bf34d4d6d09426ae04f796e0f01e3504516283bec79af6001eb560df98ac9e8111a58c539223d8818ad331e4c099868da17a26e5d6be8ee2438c3f92079be10cd9cd70939307d0b78bfbac79c76945f083e1abdcc2c096bfa77efbd80d962ebe454688111f71bba834d4f5446861eef8003ef06af16ed9d4f86f9612c78193
+TAG: 8d4655b492a48858c2bcb49f03f83bca8f2907403a70ec685fc63030ea210f973c0a4d19fcfc1ac1e727ef20a7ef329c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e1f33ac65d2f104322c8ea546a0a7c7b7d1ae2aacf3da08f279e15e54039798f090b059da2925ad2995bd6ca7f595167f64058bf3668b0d817c5ac06d2d4983335ff600336b51282986c4ca13f745d6862bdbe921b7bace59265c54b39769e3f7b2dd515c04a860f18d1a4fcf6f94ecc4dc86b3e4196e8146d75067bc61e3e719c724829a57590a1481f1bf05bc76a5b545fc84b7097c85c13924429e750fab319e732b56ea5e66119e2ee501147acd1173eaaed451a8349dee82132f94f18832c
+TAG: e628ff16dafeee313de2b9087174bde4b8cc586e92d59e4ef8bfd171c69a1021f9ff5fdfe15b4500e408b009865d6dfb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e1fce6b516ff2926b312313044a4a32d2ad8bb4512885c86b4c2d7fec2817adc7779f459da6115c9ca617c6bb5580f72e697ac682b4919887197869b64b18dbec4a3baa43a5117ea9417263a6e6809731b99d3fa51d51e9fb7c210516036d1398c1904e88e475c7451988c1a2f7c7a1e9c46321753bced68e13ea0c5f0366826a2becef328fa9d5321a86b4d1de83bc44733c539896aa6907854724b5645d1d8212ccc870c2bbd352d5f88afa5fef763e186f8785cfc507eabe87c63a74f1ec88e
+TAG: b208b06ba3be8275836874c8c06a983f987e1e955080e785caf7548a46e262d230011d6132bc552d28ab860cec71ad6f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f76db2d9ce9ed212250daa3f32f2ff43a5a7f6b9022c0f215b8487013ae1819f6bd8d2c01849de1ad6c7209796f14c84b5387b4cd7dd70e03f1c062cded6b80376b23d1c2bc844c546c90053a21b3a47b7094f513e3202b96b6fb285f6bf68e57b9177c5039e13cf5f8d91cfa41c72c010f0cc8337d50fdaab1e47d3245a7224d93fbe42f0f478298c4c9d3baceda00f27b5ce9e72a4b09b17bbec425b3f50ce2c97901629df1b8674aefc5d8c3c4f8d1b
+TAG: a4a748cafb3e9c768744c34fd2eb9a3bea09f613e40f4ce705e690a33bf64847e61bb0536d179204ee1c0f1800f846c1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f75974702b8a42b1c862d538a2d48d84aecedfbb00c10ec7048701c2dda7a7cf4164f172b17ee9e457053e5f52bc5f94e252be6e7e3017f3c8d7aad661fafef55d53dc91f69748f2ddc76375534391ae57b4c3a04c17a7e06aa5081d7814daae565b18b1a5958ffff0db0d6c501048ca9a46d7180720776fe3a9bdf8b282580ca9e68d21cc803186c1f686182af9349e8991564257fcc8de70e780b9382f984975743ef77afddddf443b5081688927128f
+TAG: d54cfcaf28b137f72122477dba4b5ce353ff3bd0b535e32df622ebb6613bd77a9e64b2030dc74abd86e2b60ac3530fe7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d09152e077ac6e3979aadd1941984d266a6a7cc7f5b005b1a6e1f9b8f4f62232848160e4b91f7c0dc0be3ff69f8be424670e1b9494d227614fb1e74ee327d5a8dc975d5ed162e3586157b303ec101297912f633234148847d205f281661aa5b1c35d5510fcba6dca3d1b85bebaac3b19100e7847d85c58f34788531bad7dbaf6b8266ed7adcd7181838a671aad9c30429a1014669b06415c2ef1592768ef7309a2f1c098683083709cb5d9b208af2148
+TAG: d7270d30ab77637e1700b2b5e2b79c5e633455189998d18fcf113ee3cc1af33aa2dbeba6659e6cd2fb100fd72e9c039d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f73cf01523e4444e91f621309a087099388a1c16c3c69b1fbd47c9cb04b7671d72bd00f06bfe36cfe855df0bbea78c24136ff141e8d12393d882750e9ae37e5576b197effb7b2a7a079ac98218803e8de652ff6845e5fae13afaf31efd71f5545d5e48f969ab0c95d5e0a0295e4e7dd3ab10edb2ebedebe35c32c2abff305226e0994b6413af98238791b5b3902950f2a21024cd5c3ed7a185c96ed89252fe583d9ab69f4259aef93d4de56e6176fe367d
+TAG: bb777d6d4de95c24af00033f0303a485a49ac420396e82eec83d18332ae276259c48752196cb9a0fd927451a75dd7132
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7f7dd667d2783d238af7254ddc66d3f5fc1c5923330c141b044c61ef44c3a2fc72db3291ebe9a67707b97d9ee28a42908b223e25b48894deba2073efca496b86749704b282852a6dece05195cd5cc826188e7c809fe9079dc33f9c408dc34331fb132b030ee47a904920b0176022bc423f4109d4facbee82051e4a5b42c486aa1aea5f66c158529b8e3a05ae4b68acc076e84feb5591ae189005593ee26eb4f1d076bb14fa350186b13254c196200fce2
+TAG: 2ed7dc502d76693a118bf0a42cdbd175fe3d54cf9b0f28981090f9781e459ee81f06d7557edbab93c1b63722c1392f23
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f757d8089a3c1191571d27c05b5d242ea1729abcf4510ab0f62ff1d309cca99c88fb00c655ce3cd2670b1a635de6a9c887d91a13b8d35336908ccbe009a1815b94294d4d4245029728fef694d3bdb5f3476288f6e6f3055122730f85a1dd902650f5bb801df075647dc6d9f1d2b1e7738564e24d5c42225fef041609631224702b27837545694e469f206e7adda18ccf81fa9f550c04a49434d24b62f5a84619cbe12450fd2b8d8cd831f8a22bc6c3894f
+TAG: 03df1a93d7de73d51f0bf62795a9adfa83abf98569249e1bff2cb8d4652bb6a958cdfeb09c4023e3789b2219539ec5dc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f760fa613a0495176b681561e718637a3ea2444f5448ac84a50b515ddda2e06bc9249d519b31792a8336e179719aaaa16123059041863388e2bb6ded11bdb8af9b1abc389154fdc84e54649b1f00af9f14f055c15970e3d74d3f97a27e341ee7bac8689f4d608b60f18facdeff277309c71bd49ee7e3010c611e2e86a3785a20d4bdce55ed681070292e608580b34bda771621c758644ff5669e874a2309ca466108f803fe1ac6f1a9e71a72637d443dc6
+TAG: 3a914fdc21344648ccb176e449ee2c74699678f0891ce0da845306c9066a56de89bc46c151c03dced847bc37c63fb67b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f75782aa5956cb76065b8110d36a1a69171ee9ed5ab352752b0e66ae8a85b9fc0b1ac2f9c6a5b250c10abb46ff38544f525f3f13647b754d7ff40e4d811b8c9bd3ac5aa83bceb1284dd397226993cbfa6ac76577cfa800debfada945082c949ea706d64695c1b4ac6504595b098e255464474b8618bbc5d812ee9322a051ff2fbd616119f922353453983cade75791b7de07cf1b294d27ed15c9a4a68b3882e1a00557fd561ab5c6a2f8ffc30452fb79be
+TAG: b26f8bc45fd16833d88a97d6409fce75dcaf1d569b8b73aa29c2a75ab7508768aa0e31048313a65f131074ba0172c139
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7cff4be9d79b7c2298d7c13976a81234eed8fbf92aea15a36ffdb8794bec97a1e6e48c630756e442e4ba3388a130db1f15e294d10c0cf04df6687dc2ce47a26297e12302938a3f166a724f83ec24df7b45d10d88bd24bf309f33462c3751339a18b85c6ace816a3201d47b338f80be0d384985d464c6f828a0bc8e23a046a6488e2f14f7b70ccc018e2be3cb22747a6d57f0dcf1fcfc1b3a249f3b94652d537872aac3bf695ac5de2a9b19e4ad54a93c1
+TAG: d868d22b7d71954e2242d383ffb2107fdf883ecc20f5d005c730a861291697c395f1f28aa0fe088b7ce745236d7d5e8b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7f45781430d3ad0a855e4ecbca80caed4775cb19e90fbe5f8241ff1ca654c13e0c8912c25b56bea6a95062a8f4cec1b1e030307e7e0b0bd3dc9b60baf80c41d08e50427b128b0e6c940fee046b72ce6a62377891194d6d47f7b551dda6db4869fcbc8297f5a3808b1ad95c605594d0e560d75faf801eb4ab3c903998f840db1fbcc6e82f241fbbfbba7025b0deb6aec73b627a252abcaf7b9bbfdc8add4a0537fed1aadddfb7b14716451b7b63c23f0ed
+TAG: 6a7e678849f09ada6f232838439d83a030c35ddde49b7af18c62f43d5514e25d670eaf4d489a3e67c7aa4d8ba7853ca6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f78053bdbb9ba17288ad2b04ae9f179ba23ab619f4519ba55f7ce3c633b32ab136a2f826b81c379f648ae9021be17b0f4c21c330ae653e542bac15da0e69fb18f578760af70cdd3d0a62af088e2f28010b2798e421edde4d0b4814832dda41c9bf5542119b204e6d1c7d7d1f6a589ee168ddc45f13cd5746785fcd7d5d44a226909dface3264df61952476c99053d7807787fe53c8d91b2b44ef99f7a52f9afef8cfadce83f32e6f67e63e525b6f340643
+TAG: 95a82cb8c799af2f1f80f3bedbff00ae791e4e067c826bfbff471ca3f6cb95514bda3775306ef3e8fbd5ff5b2e4ed2e0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f78824a3638b72c62ca26d2cae0edaf61d0bf3b9ff4d1ed1b26de2cfc13989bdee5ba2e9d524fa2d508a1b908b210dbe11b63e8cff006d294d133088d499d954403fb05170ba9ac07a10650b308e541f7141893892cc46184708d6113bc8a2a103b625e964c73ca414415660c42249a150b0bc418e91ad60ce8c1e513aa269ffddbfbfec96e518f4435ad677f142f169d9dfb19444c1165025062f7fa400bbc6f0747f72f0e82b261808e62957fe59f56e
+TAG: f1dd1d4db280b3b96f6817b9eb6d0b67291268724f88cbff48c5a939927b8bf2f3a5ebc639a1977e8a5aafbb34e3ba96
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7f3c60640e02c55245042fd7bc2d1b00dcd9f5b5d11ba9030685db83ba0dd7c181d7ae00d8786ce144218928975ff6eefa2f32642da81e8552d121f5407098a7298e92c636157ac4733741f2a468f1c27f1725a58492d7c452a773606ac06ca5d22fa5379f95ae98680875f5279fb1194796422f21719b444b7747f14ab10e512af81acb79b3d23cad69379f2de5b46cbdf53beb5e532da89dcbf2f67b8c1f0bad58bdfad00b78bbf99919644edc73b94
+TAG: 7740e801aabfff5bdf8c6707d4b8f108e6d51656e058a0f855126f189ea3243f86a42c606b18e978aee39d4ac0e60e87
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f71105397e53076c3843909944b85e8ddcd3647a41f77fbaffc1ffda4172f894b55bba678166f6eb5a53f0bb6b9c5b6377bcdb8eddfd4e9b435488a464af962eb083cb50264c57d3cfa95db79fc5601a19c0461b64e065c2ae20f47b7d7e08d29380830cb7178f0994fed1ed49689b3e01c3f14e96f744905533ce5f732017be5a6089903e696bb79e0bfe543edffd1f0517810b3906deb900beb86fa18a2e0dbbe120f627b1a81756e6830d9706b6f20b
+TAG: 67aadfe39a62ef7a240fa725c494cfea6bdaed423ea9b03205d9564d7f9737399e31836d554643773b9b3fe9c7e80a09
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f76c5a8a3ab067c6afa27fa56fe61d20ff02caec5371e89f9d2468f87b9c66b7901a134cb8b983c4673dccb9333d8d4996d1482bb2a10aff70ac6f412523af83ee0ce668d3a2ac91ca866f37bc89950a5e827784637ccd43b53110ff7dd7cb905388392ff42b34f8ab8bfbef01b048398e311f0e5df7a5cdafdff7f7e6198d07b1562d96f149c0c72228dfeac7e3564386be064ef03134f666eaa9e6919e91e1957f939c9d3f7c26b3cce3757d686f063f
+TAG: f1397119aa1b90df907ba451003fd57fdf1413645fbd88e9b51a5d4809872b1e2675109f170485cb218646cac93b2584
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7c6605923120e6e4e77775f6bbc901a4172cc5901276216a42bebd38315ca280d65e88caa3e2478d0dbcae06ed262fb63f9607563448cc433dc9692603a53f86bb1014c1ac78803e9b21756fed9388cb96d18b8ce3f1f33d5965085c4900ad722d4def41fc489112a0639d4d52f1fd4ac0d960f562d795537b7cca84f89becb35cfd9633901d17cef24997831d598d87be0349f57ed6fa3fec35162e0a78e8336d3bf663e6dc5763c01f23977072b5251
+TAG: 9ede44f81ecf132f36e4f5b939956728de33fc898d481f4970263fbdc76f8996eada55f035e3e087c46ebe495a034093
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5d7bf3f60abe83f05aa0ceb3eb18107dc0d9033a24a127464b7987e6a7126b1d231e8a94e3ecb9cd2c37ab27252f863492562b78f0891d73cbf01955569d3e1714930298b94bb402b53e6fb8721f52fe21b81a2c2c0725038b5df6a812465ca39bd432d191864051d9981c9c3c79a65649db8398dadf7b813fd87bbc2ee692076a03fadeaa4cab27c7cff277097ed5f6b278a49b4852f5a2aa92fe228c8448a7a1
+TAG: d2eb65d05b8ebf0beca1c4a4202037f5bf85a0589be3a5fe7581af05cff018986bffa1a0edaa125b23a54f8aca15dec1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5d0c6f4d54519052570db1370aa09106226c6a705405685eaffc6f55545784be54c3e526c2ba92084a61ada912ba588cb0f58b259efe99f3db34b95e9f57e464fb7ea2d7d12abf5b24587ca30547491632e5a76f2049519aa137cca54dea6e116214f07773de714d05a7ed0ee7d293ef8b858e48237c3ccae85243a428a98b62cdfafb6cb4bda7ee0dfbbd2e094dfa6c133fdf6bd21c2737343da7117efb66e5fc
+TAG: 824fc9331fc6646878637e1e2f24cbb9c9edebc4423138fed44708fc040be13daadf9afdf5953c1d7af50a17199b5944
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5d6137cc8a76bca7ceb44c2b48a0b0f89f5fa80e9312929dd5fc81beebffe7374e12f41bb0f7ca2d9935135d798bd57d1f098a99fd22301646f42ac094d69d774074fb1350bccfefbaa1fb62f0d95b8a6bd7211fb59e9080642c185b468f8d979eaa9a2b1c857b240977d16f64197673072a51ba855cd201019e536540545c897ffdde15de4ea84b85226ead48d3a680829ece6ada052ac74a3e794cd500227fa4
+TAG: d1d30a43f729c6f65af9f35ea55bbb8bb553df4b1cd4bb46ea483ecb87afd3d5d1e8a070b445f0bd908f90abc7f76336
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dd1d8548009b6366086db52507208957dcf554afd87e1d891726ef71406f4ae7c890db6cfe0723445e2db99d0c9466a82b8e5171ec0068af3999201c700c278390e1bf555222156eafe1d5de6a979252b192cc5271571dec150a2d162f07e00d5c47fe76e0f3328e18b25d74ccdb8c3a5ec7521e3125bc13ad2fb669594c86cd01c0af628f9bd7078923189e88e97a5ed2736d69b41f376f6c6a9c9a057072ea6
+TAG: 73c48d441aacef7db31c46c035b13a23112f156ca11433497698669739c7215855817d78f1321fcbce5156311f0aa912
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5d72f6dac5680ac68ddcc0bdcf973d09b19058e25cb52db7c42a1d923e07aa2723998c927691a1a10c5bc8dad0a81b3131553d76b6b5205e00594842c6fce65c9045ce4df3d43c44272d7dd6be4acf29aac6629d98d070cfad878cc91de6096edb996678a04bb8b1b17f54bd043452245afc4082d7bd6f6f3a117ee47debb72f034f12ec53333b30f720af34cc968f063cb58559f0a4b3998f59e7d44ddda70d20
+TAG: c91db69ba0d23ba50ce5026a16a131fd981c0b1900650b0bd21acb1efeebaee8e8cc62beca2f88b55f23645b4799c202
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5d29bd515664fe3014be2b6540dca9abde264f6d69c6e40b0ebce66ff4dd5b3e5d3a0e9d44da4407d6b2e23dff554408969a82dee60cbb35636eee270706899d6c8daf3cba7fb51b878ac2ef9c36e578d5bc3ae1d1c934014f11ba52c02f7cd55e50b6d738c0d9b9ffd8f5eecb67d62b8b660f3f1a96c799de475386c626e6ed1f9cf8a4a37177448050811e80519c8593359eb4a8157b1abbadc2f9508dde8d82
+TAG: fd4cf430e355bdff585a33a9a1f6d42c871eb8424f09f23ab7a73e7049ae55fd42e9cdd50d85ab177664079836117851
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5db8c8dbaa759ce295b516b2ea6f39a0c23f8f9df72819bdf72c63e4e8f6f3e26970a5689c265496d4830e34d2a935b5ed1896c9ad4625f6e990888172af990d1d4825bd5b173525617ab229cc17ad1b774ce53a5170ae1cc64381f075ace215a53a06662751824063c2a5f13720d492a63623529c564c5f0f74ee99ad5df0207062a51b5c8b8ed2b85ff45a77f944aabb783befa280995ae93a1e4d0f51102f3a
+TAG: e407bf9fb73528b0007e2e7218e7fe4fb88f86e84b03d01e34d790bb51463207806c51b192c3e8eb8b1b26ee5cec6723
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5d5f10c0dec836a5de518cf71d393c74c4e09c4b6ebbf1e4aa2c90fce5904d11e3e8c513d3dbb7883bb342a8f65c4247d8ab1b523f24fb67525719f5843042e353344030b55417be12eaa5708dcfe29f3ae656fa9a6ce7427a9e826a4568318da2ab489b38dde998ac355c1856de1b48b254967cdbcdba6c610184665480b1224eff5e41ce39d286b38a282f0927a2044ad08cc075ba366f040884b4d890713449
+TAG: 371026c0354221ade29cc3e977ca201f7b842493d0f621bbefcebb2ab47af988af557d1ed3e56d7d8b340ec43ccdbdd3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5d779894542d5c46ddb00c11af05600ee1ffbb65afdb137103898bfde25b7d542a250e0dba0ac5800ea4bb9cc42dbd9e1670770d80bb23474504a50eefee0e55b41d648d7e07d703269f9860d205581ee97387aca803c5f4cf9b72308a21c220f2f1a94af72bd6684a224d6638ead0a8a92cc2c09653debe3575c2ac368c7841155904e762bb8f984559e3cb30f14602ab26f25e912a9702485a5f0c65b3ef7b48
+TAG: ac65311e538b80035a97a3ab242293d26d3a7f807e95b744801e9bf28b1360936cbdb43c5a384e6bae14142120906b00
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5da0c3efaeed619c611d905565ba2addd44c1f3f0d583fe98240828a229da92de5d409f918409b134a4777fc083a5358e4a2241fb3e4440cb8c3bc35482fb01ad543501d573bff7277563339364161a48b83daddd6a0d78229b67db520760ebef59377942375c2c8db6ae9bfdfc4f54f101fb0decca9d65164b040a3a8b7eb885157da934c98392e087ddb70cf29f27d2ffbf57db79969a73aebd08ef5bae80a4c
+TAG: 4eae95b9e6cb89faac11dc32666f15c06ba4e3f2092b8d0601b78e434e66ccaab2bd2340f08462e775feddd19e718e49
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5de05ce772cac32a76c6778a8ccb9677edf6a735197ab02f414867da52cf6b633ab2408a0229f14a91fbab20dab95bee526b0ab5f688727f0f397517d6f49f382913dc327da2cafc4b926b8b1e6ee45275b91658c473aff75b6e39f8c30c0056f1b2f542e779d20ea2937f7e759e865500a7d5b35140b61bdab8ebc464649774b48e8dd2787d124da28b8cda3b4a563887b2451cfab640398b0d6e993b8fcf9715
+TAG: 5e68d3cb9de3ad5d61ae494662181dcc76fdd409936d9bdef642b44bd632416e9a37290411192e7308f1b1a5243139d0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5d70924dec5d9fb01858f8b6a7e26fc92d6bab75d107e2fd4acfd1b0a540f7f68fa4804ef1fd8e9b0e7eecdd8c135273296c152ba68e7eab3abf1762ce89ed56db877593cdfd35de718759c642ba13be8ccd3dedf26baa46afb761e6318dd7950166da6bbcbf244258a4e962e0f4d60fbbe03be76016f6c8dfe88ce91529277a68ea3ff7d40a963cc375ddf47be936ff49bf5e142bbc63bd86fd8acdc4603e9eac
+TAG: 412b7c7d0f8c373d0e8a480108ddae5daac5d3b2de2d252278a59a4b3cebf281b3d0517737f8858915860e57ed19a624
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5d082ee4249d00afd2bbfa288f118d272a17b3f48257df7dd23d9e999389d7af2b94a3ab427ed5e3aae93cbb977d06580e8d006b81cd2c1407a6c42742a230430281b448470badc6a516e7f665abdabe2a95f35d65a323bce0da25156978c63f2f1eb3dd563678c60189b982c2ad4f0b33fff1ac95c0e04db180910883408b5ccd4da49fe7a8c228f4b0e02bbf2b3d7c6e9674fef843a85898f0c8e290422940b7
+TAG: be8376a52704aee68aad301406919715a28f1a14b91a8c9c14ef38e0b0187985ac3a7c8d8103546a016de5b3e55dc7d2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5df50060c0c52c59a47b69ae693cc9e09807cd5314bfa4f8c0f18ab55dede5bd86e16abdcc4884e1e69c3cac18458ea20f01bbc790f53fdd012283ff9c923c71081c41e3892171d79500dc40ad2707770fe0dc2b3584a04a23d15a8460d2c374dd0525ce3066f65f7e3732e862c7e8884dfb11ffa007ff61374f63390a05d43a59e755ee3071b5427a4d0be0d6709c2c2ab57813fb497939e7fd35970502fcf806
+TAG: 9373149f8c42bf19cda26f6cbf22dcc8aaf6ba53006ceb1a0509fc328a6751c1fc96369668009e12bdadfd016fe3cf43
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5d04efb1ed9d6e2a619f7ccf9358e20c521d608586c8fd77fab4c7d742f8ec62fb3e23d8da9364a2f90332f2b9177ea004490af3e07fb0d0687ff4eeb2cc8324854095be5b61e291b846cb49f6260e5046ec638617ff1346724f60a9d6e9329c19ff66d4dcf7f21498feaa534dc8e5c4eefaea1a56a53af633da68524486585bd7cf3c78db9170ce95742543000b8d5634c4d0f9ca5700222453fb1baa40aece36
+TAG: cea7d8f64d3b864ffe8a684a5670b5ed959b7e9f571ebefb25f6ed29528cba3dac2d5f1ba1fed0d758375413deddbb3a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5db6dc6aeab373e8abd24aa92825935b84b5714d136c89dfe15b11dfa875b0960ec43d14c89bee8ccde7b2a43297b68b906182e9308bb98728f59a3189a12a2ed554b17da545a36929593ebb8f1201b5b5d8fadfb28aeb2ab2f4524845c0e0ddcbfe96612d45e706f67c730dc5b71677b65328763b100144bcfe580c5403a687a8054e15e639d96e241384c0c3fb6138c771f290ed1f317d57b99bb940294f803f
+TAG: 4fd0cf7be0bf42ebd2740494f56c2bc9151fa00c6343be8079ff87c4f4667ef208934095353d008382641858c63e1494
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf647bee424a1746ef89e150d5a1e9225a8daa1810d8383a0be41fbd478bbbea0d7d02b7aebe3c7ed076ad27aed70bb3b109a16c3af6e4f66fe7295ab03242ee94b12a461a36bfdb8ee7958802aa536f42d49e9b4fa8ddbf320efa5fdbd41c59c4f9f6b4da6ae750d7e1d769baa09ab42e7056a56663d1ab76e0334b73422723b3e2be1dece19f17ffb77f8e084723c671
+TAG: 772dd2d8c3f094adf43e64aa4c78c5fbedfbdfba727b296d3845545be42c9c4e700c51a44634e93bc85e3578b136afde
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdfcef54e46350add63775309fd6671716dbb6846dcc6dd032c7475e637a595363fd38d268f28701cd7ae740894c7a0ab57df66fd1a98141ab045e089bde65ac720d5d7d4c5ed50370aefaa89a41e7758e3fcb77f41aa89f6f0b88539678d15ea02b25e6050981d65e22a0211107aa7540144e4311f05b203b8827a551d8385be59dc6ba06f6b57a7d7dcf5173f70d3e600
+TAG: f6a48008cdf32fe9e2732de0d473ae31380cccce7ae054b8ae0a8d238309d7722e018a29cc666121b145cb3b878f1baa
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf4bf78651adb6d2d0448a5871396c21dac5b701b4637772a4b2484803bddfd24bb281d4a7213d817e4b603617a6cf682bf1f519d883e3a4e6e603abe40b4f4c34bd236831d75f4691aeecbb43ce190ed6527d3e3054c01c1fa6dab9b5f8de08d2bb2342ea9cbd913bd3480a65afe98225cf950c9aef9731f5cffdb9ac605725606878ad13e2abffb9faebb275d437ee50
+TAG: 4a8ce59bca0c772a892c90d099efdcf70a8bde322c4526b304df446858155b9b5e2ffcc266f05330de707311b64f9a15
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdfdde3cbbc2b001c27c6425062963638fabdea804510dfc6b2f776db7ac10071741b57d500a6f37d183ede1e1ecde4e1ef64ef226101405ebd056c6c01c584fa46e41039946c5e0c44cc4cb75f642029b115b2050772479b3fa272d82f1ce15046f1476e025d2ac3aebf316e599cc25e269baf1d5ac63478d7beb5eae85c486ae0177f75d5b6d81dce6659d63a516c8b4b
+TAG: 9ae7e8a9c1b38fb55e3719942dc1adbd7bc7c14701181329312917021c289e26d4ece61f7e39715c0bc01fc9f5ff085e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf1abacc8e50492584c61082a51600e6d9ee669375f396908e13bc81ae9808d232a751b44c847e300d77df52d4ff991e4187962ab362013c74019800776a3ed4bdbf2480b887f10f8e41e7760ffddf408ce020fb4e92348a86f20b19aeabb292318772e21c6a17ad68237cff982dec557c6a49855010c6783a034f147b427cfc9845b6176bd34614db53b31bebdb9dd32f
+TAG: 8abd9206463c7f05969e356ade7327fa91bafcf44e645f7ef7d7667070a02e265a12e5a2c0c006dd9e2b26209c4c2dc8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf5889ec71d321d07ed87bc07ab76812c417e5c7692a772cdc66b2bbcc0d6f335ff3442e4e924825a0cb9791b0a2c86c77cd565d269245d0465380934c70d3166ac6e2c8fd3c67bb30d11709ebb17c501dc4b1e0d5b7444786336764ee0985c973d915502b3f349c4028a42ed0b30c0de55d5d6814f888141425bb57a58525b0efce994ffaad2bddd9c409ffc33a793f6f
+TAG: 7fc636cc4fb132eb16194f9b9bf3538e3be9cf20ecf98565f9695c166544c4a902635c7312f5dcb98b6239941aa6111e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdfede62a62cd88656a56bb69004c29ccb932c89dcd0d23f8801384ac714acf2151f82d1d52cf7c7b5161b9648767d704bf4b292003399951ef57789608494ae6690dd2e6c6f570bb3db6e2366c0b568190f7cd3f00752084e5bba9375f585826df69723ceb36a96bac9f39ca3bc893691f8882056c596c6eabb4ffe214ca32e18837032047ecbae661703c99aa8c9d2499
+TAG: fcaf5a82cfb9c68056285386bb07783b6fb2f8cdcb8ca7fcae9e4daffb41da0567bfeeff74cb1b0cf3a2e9573d404ebe
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdfde598715c62db7a7dc8fe2c61e3bfcfdeec41b6546ad1f60d85f753ecf7bd5150ce154f2d2b0ccaaf4e264c51219aaab7f7c4aa2c5ef83da75c8f269f9a84e12672499ce1048cebd7080088535100f0b391324f7aa5b06fd45bbbcf60fded9841dcee06c63a1e1e2752a13f4cd12dbc40f0e73df952a5176835963258b61332f65e09b8df38ff1a3202dc4fbfbc6e0af
+TAG: bf4938f37fdf663365da0bdb51f1d91489c6c3330538cb6449c597d0b7732040a296d566e9cd164047401ebfcbfc663c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf785be787708e481c84e670965a58826b687c22050825d0407ae39269f71bd023a9456673d80268a34e444fb141eaa3c7ac97ccd156104fc1817e6a0d9db90035e84dc735bbcf2b2668479f79af3da9c20a10875dc6cff8a19b4972fbbbe5a2ea5dcb2b8e22dfcc574da35eb96f28e841ff20f6281ecc9c022b49e987ee69ab50f5c53de82347fc2e32dac8e90496c0a7
+TAG: 136e796d020c486b9b8eab9a255128606dfa3e1232000d4cc9d9b167d133d4987ae614484746d00055162ba0875867df
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf43c0a423a1015af56a1bf5cf0ce454b14a26d4d171c5fe33f2c225660bf8c993050e8ed5a97260880295d9195533110c48bea48ad7c79bed154debe2a4e8fbaed4f0863060aaaa9b25b2c3eca8c4ce6b5a19f17524a49d75f3f263ab418391723f6f71a5cae5edd1d320f34e7e892597307c601eb59019ced069f5c4499ff3b045fe491723ce4b1522910cc6e7091ecd
+TAG: 1f6d1a6a58de3d5582cec21866aace3987e0b38e65474b23f897bb7c7e0f94a97e9b340d16306f8bfa49deb03f4ebcc8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf8b350c106a972b8ee8ab69da90c3c778f5caa2b5c8c4bcefc663a69f3d6625f814101a20a236a132eef6da09e3d246585b540a7ca617b55419d16c5f15c60672ef8d486ae09518e0feca9f387640645b3b5f7f3bde777deee04c78d3bdc92177258509ee48044507e74a3c0ac1a98e98a8d1997642e2377de9b9183c2181c6fe5b19cf3b0e94027ecbe0ea7f239bb2ff
+TAG: f9258cf4ebe44fb37f76f5153a1c75247369b225cf1ba851632650c19d14c2ec47861fedb740ad4f3fc3711466c16bd9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf6edc5e40fabeff526636488c78c63506ecdf0fde8fb67191459226df08843bd5ba6b8726e846c8c449ba9fd4e2edf8d95fabf8f11f2eea05155fdad31a18e887c474f465a18625931a8bf60372ae642722dcc623a8480f897f46e37cfc73d250e4db9a38eb775028690f6434e9e85f0aeee100214ce7252ea0d6c253e9743d575e03ae01d9347e91587090b355c03537
+TAG: cde5249d0ec103d6d4139edf31934747a9b4c0793cfc5ac2d1d7cb917053d38318e330d8abcbe48269252358435ed7e0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf6e472dc29f740ce4d6780f3f25c5022672e6c4f312ceb94c50573cbb4bdf488784a69c3f9090ae402d2162ae3e6f65725a0e34309c6295a6e90ce22fde745a1f92660fd8318cc1b43420e6336f3e34c1a7273be6e14fee420238be412c660b88541acdad1474bd005bb9b15e391359a93d75b79314f41b0ae4a88a1bc30562aa863ae2e07edb5289f7bb6546a1c25eb6
+TAG: 3acdffb23b2d132f2a0a909b2be52b6375806a0b2bd015c71d5b2d1fe04e9278dcd24f55886be36a7caa384414717684
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf82bb29fb59c11f517c1e6fe9cb9d44ab8ccce37cf9a49243b3543f1c7f0fb99a2b733772a11e6ae82cfe0865f05135b94d82e8c13b2939833e07581c2d302dbd0542a996e8c677c48cced5f25d21472cec8409bb2b9063900a821426a6e34df9b9ee6557c60e75ac5582bb551656fa77551cb79a7f5ad23fec2928420fdd85b66033ea640aadc2b3dbf65be39c3397d1
+TAG: f71ee5fa3efe4f1c24499665e9b5c8266dddfd8d800d3dd51e8e6c019d0a2c3cf2bafa601242b63523cadaa8f682a145
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf57a26b2db4df52e5a9c108c816473e1481908ebfd4630cc6f39549341375b51a0a7bfbe99c115c2d41b73e0b9cfadb76ba2e430c108057c777be80bae014d09be6bd6a5c2fe2753ebfc1fe51656069ee99d5cd648a78b38cfc86ebb58f653c8ccca479272d1a12685fb2953087d447692e03337d56e03701bec0aff3690a814e455fba626bbd32faa7a5dbe9656db3a3
+TAG: a8d1fca8b49d1985055966b4800e2a4459c9cdf76ea9aa0bd75deeaa205bca13e86cb545d3e4ae62255a3f24fb135e2e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdff356a3ae230642f87318d5173deecb8a31741767a5cff89aaa80a752fcf13fb765fc63949595e8a4c28a4d1f319667da98d9c33c6ac248acfa500823ad4c6061c8a622fde97461db5495d9ef475c8f0dfc39adf3395f7341f8d184f6c28865b841e6a2beb9f325db027c84431a476d1a0ab4fed618f527e73877dda2da09dd4f6e8b3add87d83442f5d64fc4f3f90d5d
+TAG: 96dc35dcae4158688d75ee1b053aae4d78cc36f56cae0ee7594402e3841bc4c141d297286d093000703453412a9eb7db
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e160d9fd55b65ffb16faea060a8620d7d1294390accb5457ad1af7607bd6ce3e3cccdbbbfa5e3bb70694627a8a60a0b99d8ced18f7654086704d6d96243e7e066dd069c26ad58bd4853f90428f5c67f0ea5f08156ab2ffd22086d0b6bc775a60fd99d42a779c8e6e3ec000b7dbc0c5a8be784207659fd28f219b63bd30c9254acd
+TAG: 0997a67134121b3cc1266a5108a331326fca63780f776a836108af8b896205b198198820c170432d3011a03081452a26
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1f04a35105f942a796437f1155a371adf7147b05b505e47a6d6723aa735b0493d0854baecc3d6507cd7a2ad04f959728ed3e096858ed1355ccfb4a00969ab30533e197ef1420fe70acc3875102617955c6b706fa0a6abae113f24a342deedd3ea01ded04cbcecfb1425d3f255910fbab4065c85f8394c604270ab7f3141122c4f
+TAG: 22d91ad13da7f605fb373ff6e2d46f515d50a13cf50235d7f519b1eb89307024ea84ba54c88f3faf1469dfd2827ec3ad
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e13cbd7444034495297b46607f39ff5b11e87cfd8a6b6edca4590d88c4af237245d586b73a71546001a8cd17b8b6a83166f590a0d296438a83334aea2e657245d9c2fd4255b3bc33f9c45678372a40748a4670606cb94ed41109e101addcc5d2342117b7db176108e02646b23ded30c7dff614c56d2574f4819bb69d415e7092c1
+TAG: 23015d63886b200127e73b281dd0b5d7f471edd9153c06b1355045d15b21147388cb6963edae855975e38b82d24a6120
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e10f9e624a7fcca469ae8f005b1c797424626a3ae4d879270e11eec95270c22eba0f084f63702a8a571b94704873962cc96be606fe5ea75b8c714fa69bdb3b6fa75823315bb0f1ec32c0131453dd1c77577a2912995809a32814d1f8376a7058d069ad1b608fb68bf50143f1105ab9eaa42aaa08e08870712efb542380c107035c
+TAG: 89f9f0ac3629de388e52ef793abf3a1b345bbbaa9162b540e7ccbe59aa37620d3895b7e75536294932e10e6e3a67db6a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1b76932c6aedb2eb5b55b02570ff53e0c0f67376862404ba07657796e3a83a765d8987c9706bb2e40b3e9390996ed2289d52d07dd150b6a014836abafa30f65f2b2f1270a9d58312c71e4442e87fa4ac15173718ced8fcdb1a3df90b4af68042a2717eb5205b9e740c38f3cec455360f2599fe8fe3ce8c26da0e3e10d36362644
+TAG: b116ef959713d4fd602c7cf8fbc1a0595559ba902c816ffb33ab0b807804cb542b540f30aedebe0503cb970e47f8505b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1a486df6eb6a75bfa8f5590c174b35e2b89cd11a83970a086977fd937874e49675044cb00aa0dba4f7405f5c97b232ec59182f56c4cc3d5093e8a9a6b332479982542e52b02ab83aa5e351dc40db3b638fd78a3bb90b4bcfa84176f3c70ec82375b917655996182c3b0b3347618e8378e48d33fe5b0326d61fe7ff5b55d5f1c96
+TAG: 39073bd3e69c59490ab59c51688335747bb7be2e9177799f9023614048030e99be56f67cf1f0e131b8a4c6cdc9e8d44e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e16ad836403901795113ee0f54bfd6c790a51542c075dd9082192a2780627f0717667565af43576aa28743b5f9c7ed93e5abcc61b2e4aa709edb0184948a518ff4d4223f220cd33c40679a30df3e8833ce72b5084e53b1b0036f03d1b1ebf9082ca41e0d9abf19bb5e633ed2443d6c97911f24215673b77f5328196174cf690795
+TAG: af2e9b3214311aa3cdda2c2395908333b65bb25c2e1563680e65bfeb59a0b60dcfa401ee96c4cb918f7e82cfa29e9df5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e11f763d9ab1d6bb6e966602161bb845d63208106858c75d01ebf493aa7348fd06e48b1ffea7f82b28740a8cb9ba39d3dee1f5abbfcb6e53de5403c7fa03395ba0a1b58b1d7ce0cd2ca9867ca7f59d15e61da922b7dfbed44b2e6f48dacf0f7ea0c0012e5e527bd04c22baff4ac8a1e3ab215182b12862fc8c2ed3736c21a5d818
+TAG: 06eeb24631ed76236718f9c4fef0f0d87d53527ee05b9513af63d6a8b08b60a545293258da177c8746c639a2751f7163
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e180a5f59dd8c4cd98fce57bcf473a2624c25fcd23b39d40871a4fdb589873324988cb4c74d185a216b0e15148e0e03d60be5da101c6366323bbcd64b29d0a4e3d7a861e10d3d21eaf7b2ad95d694bffcb2b60d476d9e4a5a4c92048ebbb38df4abae06bc9cbbb47b07f5e13429f3ab62110c427a69b21fb53a119c5fa1ff427b0
+TAG: 78d6119aefd7ecbb53ba891f103621e38de0d0c472ee1ac2db945f2b440040088190e8a982ea14b15780843f95589bf0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e16df24e65a17fb1e7a360bd7fc41e18d8b3dd0e2d58ac47a3a0878b27c421dcf5f8ad205be90424a13e908fa1062fae03a7a948d9da0fcaaeda3fe69c506ca00568009801fd4caaf79b318e266fda62d337824881f3bc9a474832dcc8fb8bd90ad64eb4dd015a7215e9a11530761efeaf49655bdfda86f780f58081f494c7a261
+TAG: bda67cf89668e70fd10a73b720ae5d77b641492d412b06a806e6cecacd9e7883813bf2946f5f670f6b036ccfbb62289c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1af9ae41785e9207443d0e960307dbe9126e3789c5d303887a3b3be10979bd7953da4ca4c0eaa1f479f18a80119ae2e031f91e42062018cda213d2c4c217c1bae2ea7bef393707e19e7c442ed8fcd2f388ed4d4069472bea3c22b28a6c364fd994aa8d3a87732b1b72556a6014b7d2563facd7fff7850316fb3bc73389d53e8ee
+TAG: 49df7c6003e443f3a5b96c7a6ca2337d89614e889b95392db696e094136b0239e2522d65bf57b25904724c23b5715fa9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e14ead23799c80c92334153d189a8b6beafb08501178f7b984320eb7f591b544546c76bec50cff3321543cf8e47aa9aa834c49b2f974d2cfd8934b5eb5ac4fe83946f063c55d0a3c1ad7bcf1e103de0b539be28f6e35f375c0fe3e501d6c350ea85ae7e4fb03d0d4aabde42d07ccb65fe8d37e44daff0e9e14994745c524e2741d
+TAG: 4481eb51d36974bc216c043c5c5cf4931e2980f78d4f34626d78aa94dbbd2065b4d86138cf7596b6d560648669e5af02
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e122e4541e245d1548e44556ec2750ee0108eab35310ee14140ce56a93c3c9d19a233520bd694244676ede94fdf386605111b941602ea069e7272feaeaff42bdc9dc394e0caac2430c44c154c7a20496a2613fae9caddf8df94cc45fe3f0fdd7941ac6fc230938ae49f41b32a39ddd9becf0032a0aefe5a5d24fe9e085e80dead2
+TAG: 444f44a4fcc6c2c702a82a07cbd9089f13917ff1d846a889d43819b11ba12c7570f9ffba6d0a733b9ac371fd43c44c0a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1803079babe085c48fdf40ea7d1f34cf88f3b03f67b6a7b07fef24b636d1c10ad820ce4706ec4c91592bc00cbfb16087ff90c81ef8d9dc890a39f27593732d5343eeb8e0deb75be989c01d2c030b9814107c17c5c3c511457cefffc7b3ac4492e0781b4a531d15dbbf9bc3ab00d6451b6902a712cf7c2a219e59558dbcdbd9981
+TAG: 867290407e459fa48088b7f7fd9027ef8271127c8e95817cbb074d80ae8fd9cca04303abf2b5d6f8074217713b955d2b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e15e40468eeabb5a5bed17407bacf7be619b45c10180ae09e8a146c295805f9c9653a91879c7e101327f00167d48db79cd9eb21198845b99f2dffd00831180ff7c585fde3be1a841c9d2bb938bcb52894df24d3a4c9f2c106bcf53b3dfa4b9691f9cc9f4978038aac378c7e40823c43c9e1bcffa2978b4feb60d37c0cacc4ed397
+TAG: fb28ba03c4c52f1438a57d1f855555423b858992caac24d65e20c2fe8b42d4637c370d4e6a3743baf71e19ecdf868caf
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e16928c4a031afa4373ae3d2faa13b0e4fab69418dba0465f316136d06de9cea9a0d00dd144eec91150c3513117cc8b5a6c37a62427986bc124e26535a8464a54be81beae8a907e81030e4e9b37e3002017716038ed2c6958ca24b797d8d47011c574f1a9d88e7f18bb565afb4fd9d7f35f5a6b3f2c5bd57a9ad4e09e11d95b1ff
+TAG: fe4a55647802ba497ff8a8c3612bf6a218de5f9b0c9f616705d1592b885067b8f50ac52e63a14c4155ef93566f95b1a1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae6d0eac64ae5938d72283283058a0acfd228a6560fab911320e301009f1cabb1f57a2d914bcdbd3fba3e4b5b81fcf5c8c4d144ea5eb00a4f150defd148c855ef3a4b158898013f165cebe6e1f73c49cfa61a142f6cf9f30ef2236a1c992860fe7eefba463c6acce1a4e69782bdc5a551cd
+TAG: 0de84252b82e39ade6c4b503e2b030d91686190613611a84352cb7bf140d70d925dd071e2ddba175143537bbd62894cb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae677426a768db8259d954183bd32be6097a0cc80b0c4563fc81480d49450aaa93577e1208cf86e47b5b6e407dae6dd4a5c516a786a12f538ad8e0b812bf220187dbfea648878825eccf867ae0bd24b0d6b4463dc2222171d63b2bcc04ca96168e46d867d675bcc3731022552d2b599395a
+TAG: b2e434d5bdc8877b0e7558521ad962c0265b75c26fb5eab144b86719036dc7c0ed41661202654e1d3a235fa7b6121067
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae65f5888a97c89766090fc786a923db6d5ad8ab5e204fc35acd150337d462b985a07702e96daa0cedfe138e706b1b2c71cab9bf2a91129146c064308ad70d35c4e39d7c47b9edea36da7007683fac1d4cbd7de1eb56d5ce706571e9b913b82715c921f11968e5b054f083c827e7492344b
+TAG: c53025dc115e1165edc5ffe295ebf123ecf9efd35560bdfdb53221b642191a9126b122a85267a1d3957de76961624a42
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae665a74a70307d193e9bce07974508276c225624daf78d47feee88959cb988de1e9fb57a6ce5e63352737a3c3a657697bbc9b7935f0b8ae767a18bbd6efff194c1a5c68eb9393f0c3bbdb89c20f9bfbfafd8cee640805cfc72cf038a3b81b8ff5a988091e5cea3739aaa8c1d4a06f97c86
+TAG: 6cc9bc372644d757e03ee41a4f0793d8a747e0a5f86a3bbf1e9739cf3c22303af0be9f909f9ce1d46ded5acd80e85358
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae688355eb17b7fc738ff3065249e73a073302378900708d0773be54132c7b7d6b12633110b9a1a6ee48e0ec6aabbf2c965abf6d458c95bc62d24424125fd6325e6375e757d10d18eb0cc33fc0ca1af968afeb987da1cbba55a9b6163c7d1db8a8ababd0ae8511d708dfa251b89981ca8dd
+TAG: 4c1f97682fe9ba52bb76cc7ab7faf3d26f4a891a35d2611bdce8ecf8332a1d3eb8ee94c77dc5e77301e784fdecf2e647
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae6444041b252dad5d9ce033eb8825c858d5540257660a97fd9a9d6c26c6a39c7b09be77886f2a0073b792116689fb815c0b687190b68c1b592b491356278a9b352260db6330721f34691efc040881e325a88a0a761b3ce5168a9a5a11c04ec4d5ccc6527108493e0a2d45c12d2c6c2cfa3
+TAG: 885f5fc15f844820e57bd783cbcbf97fd24312082b33c021ab8dab98073ae18535c478bb3b5bdcdb8d6aa461c991987f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69909697fa3ce7192492ca56f910076958122c03044c3decf07da1e051e798f7ec411a18476189d59c5593cde710144bf15885b717cc8b7f1013f052540b34f12884cf80bd4fb9e3c82a0afa3fcc498a7250da1d4fd4b6825c0cbdfdfa45110a0d8de71e796bb1fd3a296580462e779cf
+TAG: f85825b61a4d0f91396af7c840cc8268f38bc08ece1ba609f799479da79bc32087e68c9258f99a3c7308f2120dd3c8c4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae67e9ad7fef0072fd0f2fab36fe9ca92eb5a8435cdc11664e56e2e390b23ae1be7a2946f322ee4f3281e96953d78f6c1db05a87c1f40f3a55913559a5437ba387300edd15c8c79da8b80cfbebe7da91c2f270830fbb4666b7d7fe68971dffc0b28654a2c973a902a73aa743bb2ed5556aa
+TAG: fcf5d380054590edf0fa68e351d2a053eab9b2f3c6fbfe6257c36d1a7f2a1023ca0eb882978760e0c5ac314a5dd32e6f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae66e277fe9423b082ea6e6e51181fec9321da49f4e387c46e98b71c90010ac6f6fdf66b2a91e0d9053687479bc88cbdc38e833ab338323fce84196556656e5f6e1c54777143d75a67efe4dda640c23cdc936d465915c9ac722e567d253f3829a5d6eb6695c5cbc38b0759c4ec19b7a9a94
+TAG: b832b304a7dfe88c8fe6f9b4e37c6d054bbc84d423ad321275c59646281be38deefb816ba9165f7da1f1a19bdcea217a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae6035f61b74d568a34644b3d2cbabcc1aa245d99fe805f2f910e84d9dc4b9e12cea30fc9cb2cafbb6dd1ce6dac52794df98c27f2ff90a3fc378f8597a84a03be58a4b7fe8a78b4fd2d0feebc4c9849b29fb3219d86a4847bd8e20aed731c40e7227cddf2d4401318c4537d24c394372d76
+TAG: 864a9e7e88e53b03ecf7143e8b2199779c8080c53fe689333fb4a4569b6484a9fcd6bb8b20129844e6e7a5e0a85a8975
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae60510ce6a41d9349aaa6203a75ad88612e368e1ff0245e867e9a63cbaef460329de9dca2eef7ac3d0e50df4453e4fa0fe48a66555c81d74d0625d00ade08694311ea84dc62d253dbff55fc0dd189a568f3f24095782f89b3b0464af03242e2fc11c35939f3d051bdd4857b6d5ba7c834d
+TAG: 45918c08b187b8a37b6ad188db58d314df8bed3482ca373182ed6c8b2a24938bb4458d5559ed1d29444dce19b4628921
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae61208613539acf49757f1dbe273fbca75a0fc16acb124e4368bc2c849f8e9f14230c8e0352c49b3887d2e35ffd18897e35bcc8a37ee562758b36313f40d4111160a21a2b1e7d914608b48cd01ae0b0789716a493ac0127a60134f825815d5ae5285ca16ebefeb54a11a22999a5687a597
+TAG: f7bd4854427af6917922689f5a2422bfaecfb29c73cdb7b6cdaa23b851de784c9e40fe9ce5763a79d34c3fa8054f3b61
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae63e458b8373db7fb14aa9bdefe78a67181735728c978373984bd3c261a87a5d90e1826244c918e32b69a728cfee2c8ca45ab131a87c980b5d10b1fcf01fb9487fe04bbfd2b51f5e52810e9a8a7c52fb9be8acaa9f834d8024ad9a01219256655b67296581a8a60ec7fe8b44d70b8c5c1a
+TAG: 6e2f9e0211f7d017b81d186ce756d82819624453ecdece0393acf600f0b00ae1ee82e574fd5fd818f298b1ce098377e2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae6a24834712e502e2e50372f3b6e13d044b749e26bfbf060386c97259e3d125e9e540bde195fa1a58b4542dc80fdd1c87cd7abc70366d68031ac94a974cba0399b2b7a57f9a623e2ecc1e40028d14aa93ea2338d6da92ee57c17e865871df632376a45273950981895cbe43c43eb557205
+TAG: f7d2f54f2a191450f440a4c8ab0672f594a42c8a75c15f44b40a3ee8c49e1003ab064717020f5e47eba398084fe177f9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae6f25ce640eef54ad5e08b16cbf64780d9bae8c21440e95fdb92d1e4e62de3041f22f541016b4678e5177acfd30bd6f9bb059bc1c34d37a1c9d7c4b339e15570c4dc60fa9871a5ba6774569325bcfb983b8669979b7c1027f42f3867d9ae2341e0d47fd4527f032042ab83a33cce978016
+TAG: f8d77dae27a2b1ff4a4c118008ab01d339cce549a72a4865001570a397f9e4ce7ee46a1c781ef7fc373a8575adff0e34
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae6788b7842870122fe16fab38e7d66de7a188fac6102ce1846ece7e6baaf96dadb0d71984cf6d361bbad4ee15555951900aef31b4784494c1031c7c7476cdcdf878059f1b9d5f213cbca717ae3a92794e6679328460c6670499a67b27ea551849a63d0275f9db90052646e9d296706b5e9
+TAG: 4a361215de001b9420058df5908da9548af27f50d62f07725b20915a4a88e6170c32b0f588f6fe1df0cde6385f20b0a7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad9633be83832a842d6fbe71b5740055112386a47be63ace8b779e1b2fe95b677bfb6a06fd30f4edb8d8857dc753721914dbf60848faa40d1e67ac3868bd1d5c37fddd8f3e4f841e2446255f1b83d799f660d647bd5cc2cdf5855b7f3d92c5f182ab
+TAG: 3d00f18a85d11f3ce4a9cfa15b6eebefb85e9c3886e109f344e286627c3e949e4e849ef73e82a21a246a389243e4819e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96c00621653c4edef0d18e14c7786e2571d3e2290841a7b88c3f05d15da2ada301b92c95652d71d982a769084c2c5afdbb257516a027efff7c5c16988390dd013e9ce35898d962d6d43593bdda20d9a166cc07f6b6f092473f6199cc1b73fdfa3f
+TAG: 6a61ed22b56d10f8b20e645d5c84f80806ee548255dd9e7a8f5f10766f28a26c1bb9c55b2d9600c65501c029f7b26dfd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad960f2bbac617ccb2fcb0d4287f4d83bf458500861dac7c723c7ba13bfd640d6f84865ef707c99aa68b94b082d9b382cb1572601d59be93c32858734d9c06930b5d6eea894166f019911a5dc5702cd36a89ca9a8d072191765a37e0feed5a333253
+TAG: f9911b0650958750f1750d485af63bfae7926baab8e4cb9ca52e5764857861e7bec5a54f37b00bf72da48f0893aea1fb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96eca64f80293a5e053740f4f3eab95a2026dd6115a2187219e5ee21f586869b4091d25ff30ec1944bf48997f7b64cf71202c2e945e6ee78a98a31cb0f576748f0d03a22c6b65ba0ffaac51e08ec7a1db89b6e6d56d5e3b300bcb3798a2f43e354
+TAG: 2633605887cb45e18f8417f81a271c35d05a696036adaaa8ba77ab7fbbc5eb15f70cc401c036122db918451f6e59b0ed
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96881074c83ae83830d08ca1fdf5a70c0a8624ee9029f9d611a8db69ec1954ccf39640f5f326fe1dc3c006ff7c96471ba1b8b4edf65165d7fa78af56ac59e48de109c0b30a3dbca25c2f1dcd21b5e6086c32bab08e55d5471b6039fc44ccb7d7b3
+TAG: ec57e454b6cca5bf3a23495b9f7229b764717061662f4a69ee154db70117656b44becac52318e0f8b30b1d4b9746af61
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad9656fbbb6d788f850f71a95daf326fc9bce25026be8c2d63a76a2fa418621a97ce1cb5794bd95517b8e60abd018ffce8af264c6375b21b33a5430126240a4edda942636fd0ece3d3a69a835e6135c92824310a61f787e1f116c5639f95e3481455
+TAG: 85272b5a9874ebecd6d1b7a5473c83f26a0dd4e07ceacb38313d90f69b20a771f0f69d0dd7e7efc178afd45bea9f3427
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad9613630803e96da10d51be091b4aaaf723d001aedf063f152783f0b3411c935280cbe5339a9a4a03515fdf4d352a72dd09d2bee6f0332288a9cbcb44a8e103fb21228c0a02cd2fbeed03811b1c3df08f467a8b912467a16edc72bdea4618c78d28
+TAG: 5cc48ac4b11a067545b3134c756a74f614ced58f53b602ec40b9df6645020b213f0897a19d33ed06b1fc2ec66e7b264c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad962c3aa3ea7c347f8619e905614d41f38a8c464fe420f042e903ce5d96427150c7a59731ae40076e600a96c70963d49b7025d3728d2f68b363550a7eff84179cc585e161f06e7d1befca9dc4fe01826d0d2ed1f7ef94d3c68252332390226a5103
+TAG: 35a65deafc6fb366679494fedf43ce9549faaeb47704640a8187b0a16e2f2b08c30c4a54bc085ba04f187e01f5e02342
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96bdf7fc0a48cf705f5f44b2888815f0326fc245e2f97a64eedf31450c492ef4311f333b32f8a0946bee0547f4bdc90fb72500a167f6b3ebb6a91d0c1f3f6cf765bd3f4d10d46a655e7b73996fd38da18714fe8e0bd354e5bba03ef3a1beeba118
+TAG: 23365f265c2e79ea07cf1cd04518fe60dee098674cc0847a04b9d23ca4a8bea2e9ccdc347eacf5011307e3e3d0991dc9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad961e692fb571b638228f7b96619adb80013ff947451c4db238494a781c09bf2aa13a90cbfac2daaa49e1930301ca29ff0acf05eef1990a78add38ad4ce427f538ec71226120c51f877161ab24eead41533953d7b262c14308819b25270906770cb
+TAG: ceadb0455e812848cc1769129f061018ec7ecbd578125a759b99404a79396812b7add20fd6aefb00241bf68db12b2fc5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96e7a3d6628ce324da5c19beacc23adc13a51b714be90af8d031adfda59350242163d770ffdbce2ca5125aac699d8c2eb97b9961ed3a6c9f8b08df4e3f02dd4a21686f519829a112599d4b5723bfb4843e79d29a0c3c57ce3138797c35d54afafd
+TAG: 6a5385d0043530ca138e3a0dc4190befb16f6dcf77108857c15cfc03f21005cd4168f9ad8b30369f24ff22ec703483f8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad9666750192c21a0defb3d5398832a247edd6a67404c75618987486661c6fc0db17c2e9e90392056f3462571229ac638f543df6012df07c11f10476877e92ee95da3b328dad18f3c663b590c5758f55b3eb304a1ca9518d219e702c6bce122b0279
+TAG: d71c62edb1f3c2cc2a3585d98ce347f0d10d626d38f27f680222d0f5de29025b8f9da2cd7a1e4d00529746dbcbadc70b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96c9eac85878dd06639973b4d8421d5c69436d3319181a0d58d9a81a0752e0c834297eb9b33e420ea347ba786b4251cb78db114cb8d59993c26b7e6fc94b04b79f2f70631d6c4085a63ff78a8a0b5d84c1364e3d1bb534c34546f3d5a1e2db44ec
+TAG: 027894652f3ac555b80ee1708e06241a33ca3af35f05e48588f854bbb7a3d3c4e7b79bf87c8dc8abadf006e702b5a651
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad961e01b7b57f28fe5eb49a9f0ee95bfec8780edeacf8984a5281d46b49fabe042dc20814e51d09176f07cc2b0a45729f4861a0cfe872bb7887b585d032912e7820e9db3dccdfe8583160f4d3e7f9ce0541b78a62a60c1921415e8ca997e59cb76b
+TAG: 300972203e02855af7dc2dbf7b0375602fa84593f953ac18f4ca7889ced3ca460720bf91d001530e469bbc303e3a1bc7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad967c3075f59b76a546b6d39178a28c122c73194f34414e0a8b3063d79d97caf5360ece8243e8046ee4d0d2456d84f8e4bd7b0adbac4286835457483ffac83df760fb6545d2c04b86e1f49b2c7072efe274a4862b27dd3c207c86c7bb3b432caf16
+TAG: c7e4c66519934bec65f256482c8f8d696c40203ed0549544376a25c5a72e6c5153be83687155fc4eda67070ebf9f2d24
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96097f5edbf507d2fec7b6734e533c0b2a6fad607233c5d30b6580734f8fdea0ad23652d946e0d20dde48d9e073998691ebdd46580b57609a3980d1dcc7c2551cfd3d00a81a7b3a12c687bff6c9eb7ff491e47e90f1bdb4f4b0b3dd15b13d66057
+TAG: 3a86aa575f11a29637a57a60b3c6341ebd8cf377668391a6d8b36bca4c6d6814df5ca03eb6b44e84f9b2a17d7d671dc1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c0b770015a2459901452ae3c8eebeaf8186326ee047e1774ba90b36c4b0f4f21e6daa18659b1ce7791a0d46764449f7d73166b75352f5b3aecc34753bd3273db271be5477022e16d54ed80691dd7cc9db5
+TAG: 4c10f2e7209cf7385088d706503826742f83e06660e7d00c2198c9234d6ede5e84f5034fad5b6ab97c5fa77f9369dc6e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c0d54f554727d2d519f0a01b9f53a8c499f3cd6e1b04efb52384e17610328e35bd6829a4b85a3186c342c6129674f8c30664941c895a99d3a3a4c6d373a0ddf789547c9e67513c58cec1a82b07a3b1479f
+TAG: 61ee3f43e1e9991d9088a9d0f2c07b20e23ef3d32ae9db7b06c1abca513b5179a7152750b152fcda03416e2bda9f8116
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c0543034c84af442138cb140b2c3cc72449cfb613f04427292cc0aebc8cfeee91dda0a383e03f5c929724cba19e0dfdda740aa76fcadb341f38ddae690259c320d353d867ab486cf9942223c2496dfebe2
+TAG: 8a2919bcd8f55d3b8a4fe82984d8ffee504bdbbc46b9f9ae564ecc15d94e42ee1cb64c55dc753244ce8ba7002da41bbd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c0cf81e69220234eb7b12a586b1a1b3c7d48451e96fe6484c9fc9772a7ceb84c0e2a6941b6fdc348f995d822f3f65418469e018cba0f97e6c162da8c15cb4c5a20a79f1c524647a2e1b75e76222239b218
+TAG: 84df8ad3a9a8158929cf186061dc291a16a5831d8a40b135185179fe69197a6e662b086298c30ccd21603e378bccabf8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c04513b588c868ec6a17835bf209d366fa9eee670be15794134f43383452208a9e6e0f5cde2da543fcd827cb3a4df22be8f115ecb58a887e48bcf9fadf7519bb34c109eac732c6f92c795370602db99598
+TAG: a09282a3f3dec3427e58d8bb558e27a2e6d8660f505fc96d6ff27106ca418c1c892a49fb59f652ab4c6a56e8ca64f834
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c0083d3621e6ff760816809d75e58af16c217f2e91281c584655baa9d096c47e31bb54c22abca5204c6c5a2be206cf8fbe8e5d7b4bdf3b1864067f524720c8f878d8e053f43e6db8c9aea64ee79b52710b
+TAG: 48a4767eab5ccc8526285dd45bdbb1a5e753cf56b87938dc46bd1d4dda7fc8590442b166ae538dcb11898d1ef00b415c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c0432873d27a9b9e0163b7e51e4e2364714a844d03557e7a934b0ec10c80bafc4d958faf22804d02665469f433c0d5fdfa81fee4cb2cd599901ea691d7f62ba6e60dedfbece7695ba5049daf5ac0089b91
+TAG: 8d3dfd864fe800faff2f6aa70c46251c64656e1408109186c2402dba914a3ef4af8fff4f9d8b3756c39def8666c9ed62
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c0425f9f925214595e706b5483910a430639fc8697c69db73a355113b7946930fbdef0e0d53f503d92c6747bc34851c1b4159abde853a40875af142e7b0e55f2156b6da0da07635b66ae0149a46b901b8e
+TAG: da4ecb9361b8b63cd1f39b037ce67fd9006075c70577a4e11616c90a85afd2fa576a5fbffd1322b28ec2cc96be625ae2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c00d67bbc95b470f94a88b143c21504efd5b7d226506af7425591845ed151063e816a83e55cb12072cf3cebdff1da7602d913baa49405fb8378f4c7bbcc4f74b1944067ffff74ac3e308e449fe3c095518
+TAG: 6ea6bbc62bf2ca0dae647a8eb74c8703c8d1343885278dd963569d552c930a207753e039ed82ad8d34119b617cb0d0dd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c0a07fa041748bba73ad8a109ad63ac75a32d16619800442abb48b1fe3e37b4d67f984ccf63880404e79cebcec871275041b8adf41d0b1e469474994b60a1b65e834d870f56a261733f85b546766d95ced
+TAG: f23779eff1b15c1ce16f97dc490e79edb0db0d2bb19c21f2acd61bcc7759ac05480a4209ccf6335b83c3affa8e771e62
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c0adc6cd3ab15bc9d44bb0d29dcc62699597c6c65e759c487aeb91108548a82cdd0939634e0a82f81e98b7583e1ac0da014ddac002345398fcf2cf523e915f568e01a698d90a02dc14113b5660319217ff
+TAG: 82b8549f3b5b82a913ec1fd560a37221a1dfcd85e2b23b936b1b29477eb181b755690561b7bbfeb81cad1fea7af831cd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c0dc6a4d1c9c583c94cacaa1a45fff20e187a6678182aac630fccbb772cf6460bfbd20f85285a44f40cff34b83569b246316a7f9600cc67de4f64d52d53836624188491095ddf9d98084d70a943a33958f
+TAG: 28336187c9177b683086e947148dc8265a8ca54bff51104c32ea5d7e214b5498eba88d88ef5d04b11d137baa190dab02
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c03155aac28e579738c11dd11623ee9a0eb5fb52b95db008e37f76cad4fa59ace026d26facefdb2069b3c944f4038997e3667afc3cf20cf3887f238e7f4b23d7d5afcdc637c2b084fd28e0325bbeefb9cd
+TAG: 8e6854c1965ac093df9e55f87ae4ed775962708b7ba7a5012ee86e3dceb2ad1644dcc776a00b414152461bbe7f376b64
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c0e4305e5453cddfd1c83ffb5248e72a601cda42b0beaa0488973db9e7ceed88e12806719e5103a3915e2d86a9e541949580d9293a822712938393510860aedaac7a10a6e66263d9cd2c32f468d5f54cbd
+TAG: 340486f1c4b511ae94914f8ac95135cdc882a50175072845637bdec09319714e7dd03d4f6a31d8a408c26d817f847c3c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c0860816119470b56b42c35a158075b834686a52d571bfe3609c29c6b310d4efff2188c0552c174b2109f140c59deac16f65707dcc02cd9a8ab2ea2510b32ab871cf4bb5a8919d039c28d048cdf87689fc
+TAG: 6acfe3dcfe57142cbc2509d061531447b067937d20e1307801354fb60811ff0d5aadf5f9a1e1d54eca2ff1c7195c3ea3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c0613a57f0ca1238fe21df1c19c06ba4aef67544b1366a32e2d2886a4d777bd35bf7ced2f6d763d4d69a370e2454a0741490b508eb19fc4616f570a5a86e56c2c555f27d8df1d54d059bfda78e455f205b
+TAG: c688d5156d79f1a2043cb33c9d3fb889663665a675a355d779338089a52c22eebd681eacaedf7c5f2e5463915e9fe508
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f57887d055cffd63a4f3f2c440302cbc900737c19e24245c86154ae9d78ead2c5f3125660b501ccdc5fa04199fd5209bee7d7ba323988bb46e47a6b0b384fc2f208af
+TAG: 5701ad564a3745fb15edb8503d60b0faf5cc72f332c63cc58b061d25456b8ee9b866ca9256c474862507ee6a7cfeac1a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f5788e5cfe0f2f860798bf1dd513f5ff10db4eef943b91f09ecff2184135fc20ff5f18d99b4a256b0324e8d9449c639c17ba680cfa850a4b998f28071fe1a35c629d3
+TAG: 6047dcecf250e8e651b79377515137071eca5dcafb4a30e7a6c6fded6874a59d89da4743fe7e10c6dcf0b77968b2fe42
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f5788e5de532f5b7130ddcda380532762204ede4440a21142b2ba6f432c18ec7d8a8ad315e6cbf18b2108c577df073fd147a53f2a62ea0bcff6858e92a0f444f1a0a9
+TAG: 7448617f37a70bc00eff2d5290ecbf96be6168805d421acc2e48576c9c2ad5be632b2e723b7c869c66ee3213167f18d4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f57884f49eca5739cfab209af3bc9b5d32927b7b4905dcb1aa0ee3036e4a5387220cd906a08999e6918347d44cd878f720a008ee45b91588177659564224101419239
+TAG: 09e3dda0469ce51050538fd99d43454a748fd12a59da4a52fbebddfc2cce50639c1cfd1d44dbd1b2e016533b6c60e5a1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f5788c49e014fe7b13f61636f85c8d6d5059b96eb8c4628af134f94b02e4199b11dba82dffcaa6879102039e5d30b91ec69ced9c753c45db8d79c1f14741f2290e686
+TAG: 28fb0d4804edbc4fa435bec17cec7d3687c82e7ab0009d2bdcb8d32d1691da2370afda8919672f08f3c38ed8997d0e84
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f57886c0860e50617e506ac5c8750f323e804ec2b722ccbccf64dfc69b33a76771bd9c3346a782b1aaf38bcf249c60b837fb04b985246ba9ee1d5eaa97b9b8c2bbdd1
+TAG: fa7ec348ad18d18d3fd4a3307d9d23e871891a176c43794a2847504bead4238a88385b111ee6c3a48416514c08b0e93c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f57887b180ea02b3beb9a5fc38a9a3bc6b9b78d415501874dbc3a41df645071298ee82f40f93faf11d3330639731376cf102452dc39e6f3d9e9515525d956fc20602a
+TAG: ef2417eddf5fbbc1135fe3942d1a2018b2b793869d5cc57490f21555fe0c3e421b5dc77adfe35c6242cadcf6de9547eb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578834b66b61cbfc0a0683646cb7751442b66c2e4edefbb76a54d5b535b119e82c7190ca66e2859df1653fac2db4ffb3d4e65e435d55ea96fd94927aa05c9a8ad9f8
+TAG: 7d8d70ab15e5223e33736f7a68c23ae3a33ddc492fd7c02a9b62e1eae2d3344d8e6ccb4881eb0871ee7a198e71eb0434
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578838a59307ed182a474e0a43c70794862a0ebade906a4824f387a1c5041655e2ae6104d8a283350312ed977abc05224d59b9ee0f5bb2df659e58a5b6192ce7c68d
+TAG: 70b3c7c1799f070dfb9e6fccc6333b709d079f958b0be08ccb4aece46c3234acbcabbf5166b2a537fa09c059ef6f65dd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f57885b0fcf68fab4f79f6926ceeeb20625ff19be13585c50f650572f19a34628310126296115df798efbe63085b3707873489d613e11ea802c05b69e389d961497f8
+TAG: 899a08c658f28c89445f5fa2f4c33edc1b9600db4c938e24c1e07a8c841c02b1067fcd9bea977fbfe5ca2807da0b59ba
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f5788db86049d3a0042731bd4d4c8bef06411740073f925d2646a9653279cb224c5d16b0eb145910418c72955cefac86a96b49831694bb52f05006a05d34ba8495e1b
+TAG: b8b25944c56cf57049e81ccca1eb48160fc18a5179acd00329b910d575af47efeec714afaff470d1ad9e591804d7399b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f57884d295762d0e86d20b7696244c0622f25900f4556d5c3137ed4f23cdd92f1f960114c798bf4b1d390d38138958eee949d018bb65be35dd697dec2007dcea3a550
+TAG: 45a1364f7c9d8ba2fc8ce853b415ba9b438aa3c64050ed17a297481cd9d0a64ed50e75e69d9f432b514699813fae4781
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f57883142baff28759f87042f02da92b9c93a146fd7566bb7c1379d731a5739f825cc981e0561f39fb22c3b18d0df4624adfb4ba8071c9028256fc75e9e2950c7737a
+TAG: e4838b7ed205b9b6414c6d0d3aef04000665b5c93f3896839ba5ba87a626bba7b81edcd30dc306754326bfdde0f4616c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f5788760ed28f2298d5b077ca37f9366a3a2f6121035fc6840937fe1c8ca79ae8276d549d44c63e0e0b720ea0759a7e71e79327d70362347af8dc92212f26a6ba4bbd
+TAG: 4cea4401c74054d8562826f8fe49c6cc0eafeaa170b1cdf48a30401d2b1ee26dac21eb4d2b7106f8d65ba38d9f3f1439
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f5788c71586001e2dc88d0fe618d3909b064614fe585876cf1d1559556d229585f5c6f49543cff218a30dc5baacf3efafa5d1e5568d97ea625ace65356fe312cb4c41
+TAG: 5840d9bc5b417ce0aa43a2c689a3fa7eb255752a84cca2eb99370fc990ae5062b29cee1bf585ff299f3a94c5587a6d96
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f5788f9bb1c86f8bd8046da9a7459434c7318db56582c8950055c90dbd21b500fca7b9f7be6d3a4ee140c35d03822cce5c3ca3b108cecf6485623c916fe42e161c286
+TAG: e7d9029f8726336a3ca36d3f6d50ecfe79757de793db93c966825827f02a2ec67d2e3e979b5f4c844b955be638c44c3d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aace84fa0b047c74bb6875cc3d4af79f8914b50717af29cd80a4c13a64ac44fca43bd88a51cc6cad21e6dc7a582e01b501
+TAG: 86ac4689fb21cea5801cf74bb2a5592bde84cb02b845bd12fb7af140a5ace204238b1676fa41950ad1b57a5abe658059
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa3d388663ce5fba31721cd74ecd9ee36dfeee20a0b2aad0eb648d1746cab4b4d006cb6fa8f899f45b30d59ec3ec80d8e6
+TAG: 1cdd58c7c9a51315becc419b52e4311829ee59b3cef1cd6aac0559f674151895b183a3d18fca75582cf094b843bcdc0a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa1e0b9d61de6892a41808b8f1c2ea6ba583639e50fa8e61832223373ad843d7c5f40ded757248e286f43be98419add730
+TAG: 29c6fc03b323a5e5ca3a0dfbc86c672b253f62d9081a55a318718ff0555f56d2ed7a0c3d96c07255ecaf569625808f19
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa6b5f7d9425a2f8721e332490fb18339a1864ed298cbd096fd9f0a53439ea7cb5d87eee9bab8a74bec898973312700592
+TAG: 3f74341891d4aa139c61b2b8dbc61d29bb0f04a110fd172f752ba512b15dc4408b7910be6316167cf2e9b1e6de2e23f0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aabb813defedb6706605768d488fdcb3f1ff89103d398a7fadc9c0722b5651d3803644a85b30ca502ee090d76bd38571aa
+TAG: 35ef2e0ebdebdc8c58c938d720c56ef3c1e673194f3d8f45e0d9ed87788130cb5acbdcdbf7b56e0fffa15d8f12461c5f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa1620d6fa4c61c432064c6425c33a154f037cd82f087354e6827ae47043f8f0404f2c38628ca185442a08f2edaa402620
+TAG: 4ef5b6b1faa4a2a7c7401df0a9b0ee56bc2d2365261def948e464629c7b50f91b199e4d6b53d85120e85be90ffcb2b65
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa5f3eca164e17f12345b16ef6dae03e238ace0196a1c3552ceddbab612b6a6f8998107cc0695a3fd34eec7cc6c25d4d72
+TAG: eecea06099020ee74fb3d5e9cb4a52c490941a53368955c4d374da2003c96ef8c07c77875705d815b89f482beb396eab
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aaa44dcf055b8933c4d9041977f1c2db1b57bf8207b468bfa62f95c2e7541f67bad3bb2e3c15a31324417b910caf44b68e
+TAG: 5babc46d6993a6ed4b285a9edb535a59976efbc4994250841e0fead134272421eeb31ddb1f0bb9c3220b7ee682377a00
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aadc8f1060c7af5413daa0000692d35092460ccc4c6dd4e880c9995e0c9aa3460b3fcf53a37f963fb4eb064069058e3b69
+TAG: 1a0487b2f051efb1e96abfdf1efdf2ec8a4b75a8dbd216b9834c8db7b95050ce2613c3076a54d55cdd2cc4bad4b256fd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aafdaedd0bb56fa60d4413a53184e4e8b999690f098b3a3d11d60a0d53d47d6981898e3f007297c297334ae7dd241b0cda
+TAG: 67b6c13e2b04689ffe7da77ae37109e366a757c5b948e54ea3716711a507674dcf448fec4b4588d60ec8e47c8f6640d3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa927a3e860d1133eacfc6e2b4fb2f225f4bacbb01ffd6a4783030685c37fce7e6c01fe16172196f283b0fbd7c3ef9d987
+TAG: 7f2e62473e8e4dbff5afa0660c74f0acf06444d8474161333cd407c57418aa10e11d95972ae35175dd3ceb942bd89941
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa9662ce6cc4f1d21067c03128d53b6d74238ddeea2586e56a00978f0ccd7185f3e33112bcf83b627e2a39cb10325f3d01
+TAG: ffb41d678935a528d0e0daa603e132fd7c2c52a64a9415f3a864ffc195b86a79aa67dcd22387c839221564537cc730e2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa9c608bb10246cd2147d7e1ed9141fec654ab0f82bd721e0ed793b1045de4ddad9ca8d5f646474e8b8662dbc3d4445471
+TAG: 54883e25d4aa9390678001c5be852fda8bf8acc6e7eedce097f3fba03ff2a98c2a1916ec4ca743aa61e06bd78f5f4772
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa497767dc03b80952b047090da9fd28485139e2a1ab188b61802f69fd52cb9b61023a88afe8dc9943a95917a136b90184
+TAG: 7018101c6327d9293f7c0d331ebac2cb7630ab884965d732d0c97b6e400827f4d3968f6e8918fd131671be016b8ef28c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aada60a03de8677de9275f2b75b2b3599df51482f97c7d71e4c4855a7493403b0fe740c7f6944dfafe088168f1d418ab1f
+TAG: a6610cbadc870002584c6244e26cb9ef62bbffcf07ecae1d6a94f4faca36f00cfe9db260bcac525fc59bf896808e1c79
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aab4d848a8a0063a6774991c66b171e1871c17b03f9a5f97671aa0673cb81d90ad0afca8975a704b38e1a897fd65bc069a
+TAG: d23e0130e58f88943d9f0d075a8e595ff16f991d2c3f4064a0df43ceb9ccc7baf46331367e34ff6039d50d21036d56fa
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd00c5468b7503b83825069033d026a3c6231c41682675fe1e876111273a60fb80a
+TAG: f7cc7654f60b041010eeabb356ad5e220ec62aab80e5250c54e3ebd528958d42abb9285fe6875f3feef4500d8bde24a5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd08476190404d579711ce314b9399ad54636cb61e84a1544b23eace6ea5ebf9507
+TAG: ebf3d13fcb36b5bf00e0a860f6dc4fedb0dc2c7d5ba6fbd7d057991f9d7fd12ee0b539795c2914ebe8229e75d8082762
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd042095ca0c0284b72e8c7e188d41e3bfc47cee42a6dcd293a69893cc10d4df261
+TAG: 9106b30735318b5bb78b09d699e2d9fb32f4f28ec39ec15b4beb5d3ad0204a3690d8d0c39be3cabe6c6f3e1c61508c5c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0359ab1305f42f72ebe13cf8506311b382f4b31ee8d43692273365ebae74a41d2
+TAG: 5ce06fa1e755126e76e6ea0854d3530453e4a8f9f9b8ea34bc73808ceb0c650b36a13aee812e5c6e18da39dcd1453735
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd087e890a882e81a685699094fc4728116f56ea719b3c89725da899490d18cc7eb
+TAG: 67b7880cb6d8e60acab29cbfc9ec2d15691f4b52b808bd6b0944881a90969cf40e67caf0cb360f1a4535163e640711d9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0548ed0503157903a68bc004ea84b800a83b5b66c81353ec5b034359406a964a1
+TAG: 11ee19154c60b0e3c2611c368e73a42d2c19b78a5f664bdb578bc5a3748b3d77f7475f5c3f2a6941eccd2d1e55b9577e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0c2a6e4b0b9acf54c070209b0d0e7ca1e369bd9c7630eb1b5e917af508386ff7e
+TAG: 1c9a112460cd636205ed0a3bf995eb4e05098152acb786e1f3be3418d9a6305b66e743ff9c54563b84435350ec6f1698
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0f0fefd0bea663440974a084efdadfe98dffd1802d8801f0254fc6427e7f8cd8d
+TAG: 6498e2de22f5b4c20abb8a9c51da28a1e2402301303bd8b4b932f8e3381d4488214e23be89d3e0cbf393999d38299cf9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0b4eca9e0aca8088605e24ad19a9b8927c4d6d05233cff259df7aa938b9538bdd
+TAG: 20561d8a8c906c288075066f82ca01db7de6f3633b23f011b25b8300311dccc9a3a0ddf61d7b243c474f408f4f5c0f2a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0be87db1176c72ed73f7327d47e2bec503f40787b56162fda6304a0acee636aab
+TAG: 75e556efa2d96598ed0dfc6777ea3031fd88b649d430985fbdb655b91dfa2e03604638b06f4adec37b7223c096712db1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd04188694b8a7d360158ec1def25c3c327b9d2bb5e343b9168c9674f455c0dd99b
+TAG: c26d46b02ec9083e3a9ae5e4b7b7347a8ea45a68193c718eeebfaf4fbc8be91d24be4263b53abf559e48d387538e64d5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd076a523fc0a5512474b5106b175e653f8eb92cd1eaebf947a74dbbd0061dca070
+TAG: 4a62513d390f0f14998a2af3562b337f1dd655c3dcd4ccf4e46a5743c9bf5666bbb56e198838728c89a9a498ff884fc9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd07b561416154dfea4366fef06d42b14357c79ce5bae27bc04ffa60ebd17dbbd46
+TAG: 3cfd3c457dbc78f666c7d4f4c6a0b84e8fb7b3b0bac7a9c70ea1be583eb20517e1936574a1c54493e4f135071a7ad159
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0444a5add9b47c2bb4ff109bc296663c45d8939682d0379e8bb749d3bfc47bcea
+TAG: f3dc4caa43d934d383213ac6c90a3f3796bb1b0584cad3a487167047dbdc8a5e66b6ca348b2ba120224f5f66deb6bac9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd05ee85c48b2f45d62424809987d6b4c0dbff7f56b7f5f3420c907670d46f52303
+TAG: 382c52fbe36fe3853cdb9527df39e0d7c2511372c8fd4799c0514ad1aba45c0bec86637e7544767b1e6f30333d6d78ac
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0236fd1c9c572c15748f905eee0e9d5aa258b0a08a77fe70750145942d23ef305
+TAG: e3d609764a1bced419b44ca426789b77f4b144e444772454db15d7cfc471a16713a42a0cb6f74f04230bd68313ef2fb8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a78fb7cfdcd1cf58b9e6ee1979d2afbdd
+TAG: 1c24d4e4500bcb88e3607943740188c495bc185d51e57680a40d377f34a8f5988b3c14b69d05eda25ad6e8e54cbe6296
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a5ca7b2380f10b80a69b25837afabd345
+TAG: 928003358cd6df1e28c4ef14b0f83f754a86b6de9bccb0a8dfd6d20ace688ec3cb38fc728a6a8689c53527bd2869f76b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2ac0fb65f5affa33ce06a0efaf80e31a6a
+TAG: 85035b6c962029fb2349aa4a37be46e73a6a61c8d3a43703f4a1f3bebc9e66503d401bc3a096fb3889d5c6bef67aac30
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a818e5e1229d22073cf67a653254abb4b
+TAG: 48aa51f3be72689c88b7f98fc135c5f776e877f3707a47c7d1b683adff4ccea2c2598945e1bd99208963d662e1ce9e63
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a2caba4ca1cb816b6492167ff54f6ae78
+TAG: 2d94d2ddd10a950e7ead0e4918360b2a46cd68742c5ace83138166bb60f6511efce758ba8bb35875dfc18c5c198da3da
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a0fb33cd288849debd7df7fcd162b6c9e
+TAG: b655162aab915455f9a7dbe58d3231889625927e3577fedf8fabebe8fea113ee38c6cf119e8731582f89a20d5d27d2f5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a276311ab23770a1fd8a50a068fa168c1
+TAG: 58297c467e6e336016b8fca06f573906018813aae2cbfd9697fcb1b8d3db2cb46a47e99f6e7f22fe166b900e987b4e74
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a6e82769354f715792ca39bdbf8d987a3
+TAG: 74ca13b58436f524595fbea1d512d50829b97fd291a8c1b59373acaea1bfcab528f9c21cadea9d75ffd1ec6f93c731a9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a0c35f0fdb93a1219c55a875bbe5da813
+TAG: cdc2c52c0be8ba91f4937df929406ce7338f0fd5cec8cf13481d45deb8bd737231e4d2d2d3a2279a7d4bf9701b87b400
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2ac26a57132f5def6e5283cde5ba81eed0
+TAG: 98482bb47a0f04c49ff064ef37a543107fb2f909640b3bdf7d400735793d528f2a56dbaa2f3077056ccf5dc3aa7fe953
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2ad6f9a16590300ec8fbf8833db0c0d6c4
+TAG: f2ed065d8ea09287829a34038a520d23134470d8e4965958bdacb07395cb88bf9b122fa7caa600cb86be254b902128f2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2ad9572354dc5328cbfc20c54a91ea4dbb
+TAG: 80951740d2281af5377c983f181694295ac92b4a660ac946ebccab28b4ce156f29624da84f42de390e24032344c2b080
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2aa3bf040402cf3fd9812814bfdff32bd5
+TAG: 5038caa729f7f2e7da9dd3052148f32e2388ea552679bd5e4ca7f40691b2c5ea161208afaa571ca8930ae0d641b3c9d6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a9a9a588680a20041501bb976b8e5eb07
+TAG: 0e13cfdb806278e9b360de7be29d5677be25155ff407759db89a50af425951d5df9f5d0f8eaac215b9f7950c3ad7ffec
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a6b2018754b87a1cf27aeb72d6b988a44
+TAG: 7f3310cd91d50d785f6b30b364559fbfc359fa433a26a35b41a55c72db1cc379c34f03aac86a0dbb2523d5ed9d29e592
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a71f6ae6bdbfb1bc0d1000d0421598481
+TAG: b8f7281d9e01e40c467ff802031281275cad32796a368e3bc56b7b405b8e246570f9a8f6362ef40822b460b351b9b775
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 894c4394458d6ddd77ecb6a8e2bfb0ac5e287f4d69d138357b6e008c112f3bcbf9383d1f83f69c75f80c37d876f49b20
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: f262d086ce910d6b857f415717e42413fc82e140c54c4d9c5318b00a8cf95ca66750075b248576937d926519315d73c2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 377a6f1e37f5ab280c3a915767cd4219528746d662b6b9b46e2991d6ba8e43a18cd9390dc208795c0f7ad253d56660b7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: d754be10adddd67c06201af24f3be133c3d7f7ead5a784c0b034104834403987eee4b3891aabb9707e26ec5feaab39d7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 566974d2d44f6a89342e168ffa83890c7b4857c08a0825d139bdbb6135523c880ac56c5c75a3980f704691d3a150804d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 78d456a3688e6a35f95117e14e469ece31cb47c37d17a08c3360554fd34b96fab66439cc4885626dc08607d2e6cab26d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 0186f25e975b28d891d5ceeb5d7a23f6d1320829f18799276bea8824d71faa6ca68a8cc745c547c1684b962ce2890bb7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 55d473a0422b8a6e4dd3de9929e0a8b2860f6d2904c4c84c12c23697098bc7bd231ff8476c187fdc52cc39a8b6e80b78
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: ffc9ce666e563c48ab0119c6f933b90cff47f5c9ead009402fbbc35fc7b475ae0763d5b7fda2c5a3b7f891cb3118ef6f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: a06bebcec3460e2d639fc35bc4cb5926d532421c8d5ef2bb7a7e2333553d559a1f1f476d0831e7075dc47d7b4818c012
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: a9021ac8ba302b1ecf794518b541af0f11b245e97916b61c6c2d84b981320087fb34db779486e15311c6f4d6b1270c0e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: f31d1f0f5ce99c3a69aa054ce28768484e0e473eb85a70320eb0427d36466b2d8719b4d77e77d2e4baa294d7a95a0fb2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 686e575c4d91703662288b9616e734952362653f01d9fe1852951bc5ccbfe34453fb2d9cc1660890191cefd06ca16d3c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 78179779cc52d381e6b37bf6924f4d5ccff75d3235bca5fe936365656cd2bbe3491a7ffad2e8f566d85747c23b38b10a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: c04441f8f96e40b5958b9da21dc0858b2ddf308c38bce17dbf15de8416431ed075147591f82dc1003e4495ea9e73a538
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: f75bc7c4664b737273060ce2b219ae7ca7b09b76c4cb3a5992824250c119528fa4bd85bbe684a1f3cde280dcf766b6bc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 911d133cf637fd05357d538ebcc6081be2119870df44831c90a216fd602acc7165e4fb5b0aae984f3da7651ad99de721
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 911d133cf637fd05357d538ebcc6081b5f59353b376294363785b23cde30750487fe7d191f16f1eecefee03992ee2b9d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 911d133cf637fd05357d538ebcc6081b9cf1e14ff5d7e755ddf2b459fc071dcde4725d3f9d64922a18415d4a75954e34
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 911d133cf637fd05357d538ebcc6081b74f08ff3122556f9f540a4ccead7441d14dcf6a4d8e40f29d0692e2577534498
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 911d133cf637fd05357d538ebcc6081b08bc811a2973b2ec12ff3b8b4729e646f847f7d4f1417fdfd01539d56e4ba300
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 911d133cf637fd05357d538ebcc6081b816f87bbf646483147883a24bdf0146df220b13fc44e8cadfdbd37014b0f6042
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 911d133cf637fd05357d538ebcc6081b8148c9ce7b4148df30db2e4471194f12d48c3a9dd053ebf5e535976e6e2ec9eb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 911d133cf637fd05357d538ebcc6081ba74cae057b50b0bc3af9f2b705647e02c333823fabb9fc9b84e82c8a31dbb0dc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 911d133cf637fd05357d538ebcc6081bab4ddb79f04d7e53338038bfbb5bf55e34d1dc3b05fc17902592c2801d88370b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 911d133cf637fd05357d538ebcc6081b7470bf43467d9f91f3af9f91fdebc9e0d6dcedcf5313e45f46a06de78b2000e9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 911d133cf637fd05357d538ebcc6081b1678b59aa848d8973eabdb6bc85c6d6880567a93dd3717fc8778ff74a53644fd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 911d133cf637fd05357d538ebcc6081b390983f4f12a7cfb16eba31630d082768a66114c703808de311054458bbe45eb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 911d133cf637fd05357d538ebcc6081bea467fd5a07cd5c7d86da513a1bf2e7645dd93a5683ca1e9710743884260b550
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 911d133cf637fd05357d538ebcc6081b3f4d931cc6489fcd68258ca6ebfa654139f6d4ceeff401b2be1e19cb045be2bf
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 911d133cf637fd05357d538ebcc6081b787ad708dc9899295be04ac6230872b7e73b9f129c4b401a75a010577a005615
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 911d133cf637fd05357d538ebcc6081b059df93535accb6fb75dd799d8d7ae8ecc29873cfcb7b2f0b9dd2610643c50c9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 911d133cf637fd05357d538ebcc6081b8907e8e94e5ecec315d055c80f948a82f5492116a049571c95d575f2b5e9f50c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 911d133cf637fd05357d538ebcc6081b8907e8e94e5ecec315d055c80f948a8287a0679ace8765b5d9c503c25f114fcf
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 911d133cf637fd05357d538ebcc6081b8907e8e94e5ecec315d055c80f948a820e746c163831b3cf78c3c28232330f0a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 911d133cf637fd05357d538ebcc6081b8907e8e94e5ecec315d055c80f948a8240274f886f1361513c1658bffe5e1cc5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 911d133cf637fd05357d538ebcc6081b8907e8e94e5ecec315d055c80f948a82d8ddf86d5cf3b4fbd8096994c3ea65f4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 911d133cf637fd05357d538ebcc6081b8907e8e94e5ecec315d055c80f948a82c74c2967dd358d50e2c4861a5b9fb95a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 911d133cf637fd05357d538ebcc6081b8907e8e94e5ecec315d055c80f948a8260033a43dc4bea37922ed8d8333d603e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 911d133cf637fd05357d538ebcc6081b8907e8e94e5ecec315d055c80f948a8259c712147d94cd9318d0aea873d4540e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 911d133cf637fd05357d538ebcc6081b8907e8e94e5ecec315d055c80f948a82633dfe9ac57500f775ec2da108bcab13
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 911d133cf637fd05357d538ebcc6081b8907e8e94e5ecec315d055c80f948a82d144dd3800428dca60c6f8f08dee1d00
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 911d133cf637fd05357d538ebcc6081b8907e8e94e5ecec315d055c80f948a8217424ff5c1e67dad5fc42d54cc39972f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 911d133cf637fd05357d538ebcc6081b8907e8e94e5ecec315d055c80f948a82f0d93a7d7cce4f44e68f74b2a480a474
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 911d133cf637fd05357d538ebcc6081b8907e8e94e5ecec315d055c80f948a82fb8aa595973f79b3a18e3d145efb8898
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 911d133cf637fd05357d538ebcc6081b8907e8e94e5ecec315d055c80f948a822e949da57622e8ca5bd1ac8cc2104ef3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 911d133cf637fd05357d538ebcc6081b8907e8e94e5ecec315d055c80f948a8245f940d388f72f84eeccd9436c648925
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: 43a413967bf0fc76201e7b4427191338c74b86300fbb5a193e01a1a4c743a36168ec2f52433b8ad4075186e5c7fed1c0
+KEY: f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: b8da7dac997deafd64b1fc65de39f4f0
+IN: 936a91d0b5d2c0267218cb7090c61713
+AD: 86d641b87797b684e0fb56
+CT: c90e0c2567341ea7e9d968dbde46ecb48b4323f68c2cb1882cff4dd9ed10f49aa406481275509633d33028a0b510a77e780d4297ab8ad09b60445146ce85b21ecf5ecb1fbf535c5e6495a6d7682953e19eeeeb70b8258de6b5cdbc0b91ecc2f7d7a555da8ef2953161857f57e7d79a5dabd5d6faa78c72764fa8c6331d963fdf001721eadf3e94694cec40bb1458c9e1468d25a326f26d28732a9837f334eae69b35647b83d2c1daf303e4aa64f1ad96706199b4fa5cc40019b84ed5fd0b23c038d7d74d85eb0a2eaa81d0029b2f578890f488d502309a5c9ab1be818a98a8aa09c47dfeee07dd4ea879bc2101f7dcd0e9964761dff1e276f088ff8220f79c2a8633567a46f751e75665f0d843500696
+TAG: 911d133cf637fd05357d538ebcc6081b8907e8e94e5ecec315d055c80f948a82db56ef0a6ee3e27efd3c65436ba70ce8
+NO_SEAL: 01
+FAILS: 01
+
 # DIGEST: 2e6894abd3cfac4d4020094d02c6db6450cb7367b405443de9b5f2ab444b281848ef5da3aed9ebfc054ae89af094ddd6
 KEY: 7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
 NONCE: c55b436965aabe477e0cdd46be99371e
diff --git a/src/crypto/cipher/test/aes_256_gcm_siv_tests.txt b/src/crypto/cipher/test/aes_256_gcm_siv_tests.txt
new file mode 100644
index 0000000..b7cbdad
--- /dev/null
+++ b/src/crypto/cipher/test/aes_256_gcm_siv_tests.txt
@@ -0,0 +1,123 @@
+# Test vectors from
+# https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-04#appendix-C
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 030000000000000000000000
+IN: 
+AD: 
+CT: 
+TAG: 07f5f4169bbf55a8400cd47ea6fd400f
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 030000000000000000000000
+IN: 0100000000000000
+AD: 
+CT: c2ef328e5c71c83b
+TAG: 843122130f7364b761e0b97427e3df28
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 030000000000000000000000
+IN: 010000000000000000000000
+AD: 
+CT: 9aab2aeb3faa0a34aea8e2b1
+TAG: 8ca50da9ae6559e48fd10f6e5c9ca17e
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 030000000000000000000000
+IN: 01000000000000000000000000000000
+AD: 
+CT: 85a01b63025ba19b7fd3ddfc033b3e76
+TAG: c9eac6fa700942702e90862383c6c366
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 030000000000000000000000
+IN: 0100000000000000000000000000000002000000000000000000000000000000
+AD: 
+CT: 4a6a9db4c8c6549201b9edb53006cba821ec9cf850948a7c86c68ac7539d027f
+TAG: e819e63abcd020b006a976397632eb5d
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 030000000000000000000000
+IN: 010000000000000000000000000000000200000000000000000000000000000003000000000000000000000000000000
+AD: 
+CT: c00d121893a9fa603f48ccc1ca3c57ce7499245ea0046db16c53c7c66fe717e39cf6c748837b61f6ee3adcee17534ed5
+TAG: 790bc96880a99ba804bd12c0e6a22cc4
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 030000000000000000000000
+IN: 01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
+AD: 
+CT: c2d5160a1f8683834910acdafc41fbb1632d4a353e8b905ec9a5499ac34f96c7e1049eb080883891a4db8caaa1f99dd004d80487540735234e3744512c6f90ce
+TAG: 112864c269fc0d9d88c61fa47e39aa08
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 030000000000000000000000
+IN: 0200000000000000
+AD: 01
+CT: 1de22967237a8132
+TAG: 91213f267e3b452f02d01ae33e4ec854
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 030000000000000000000000
+IN: 020000000000000000000000
+AD: 01
+CT: 163d6f9cc1b346cd453a2e4c
+TAG: c1a4a19ae800941ccdc57cc8413c277f
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 030000000000000000000000
+IN: 02000000000000000000000000000000
+AD: 01
+CT: c91545823cc24f17dbb0e9e807d5ec17
+TAG: b292d28ff61189e8e49f3875ef91aff7
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 030000000000000000000000
+IN: 0200000000000000000000000000000003000000000000000000000000000000
+AD: 01
+CT: 07dad364bfc2b9da89116d7bef6daaaf6f255510aa654f920ac81b94e8bad365
+TAG: aea1bad12702e1965604374aab96dbbc
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 030000000000000000000000
+IN: 020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
+AD: 01
+CT: c67a1f0f567a5198aa1fcc8e3f21314336f7f51ca8b1af61feac35a86416fa47fbca3b5f749cdf564527f2314f42fe25
+TAG: 03332742b228c647173616cfd44c54eb
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 030000000000000000000000
+IN: 02000000000000000000000000000000030000000000000000000000000000000400000000000000000000000000000005000000000000000000000000000000
+AD: 01
+CT: 67fd45e126bfb9a79930c43aad2d36967d3f0e4d217c1e551f59727870beefc98cb933a8fce9de887b1e40799988db1fc3f91880ed405b2dd298318858467c89
+TAG: 5bde0285037c5de81e5b570a049b62a0
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 030000000000000000000000
+IN: 02000000
+AD: 010000000000000000000000
+CT: 22b3f4cd
+TAG: 1835e517741dfddccfa07fa4661b74cf
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 030000000000000000000000
+IN: 0300000000000000000000000000000004000000
+AD: 010000000000000000000000000000000200
+CT: 43dd0163cdb48f9fe3212bf61b201976067f342b
+TAG: b879ad976d8242acc188ab59cabfe307
+
+KEY: 0100000000000000000000000000000000000000000000000000000000000000
+NONCE: 030000000000000000000000
+IN: 030000000000000000000000000000000400
+AD: 0100000000000000000000000000000002000000
+CT: 462401724b5ce6588d5a54aae5375513a075
+TAG: cfcdf5042112aa29685c912fc2056543
+
+# Sample large random test vector.
+
+KEY: 9f646d6337565c689c9ec7627ad95c26a2df7d3a36fba9f1265c607458bbb1b6
+NONCE: 336bb4bb0c03e8c87efe3b5b
+IN: ec257ff779f7cb246a38462562e508b14adbd3ff33041b94aab6f10a3e8b7fe16738f12afa470c9100924b211a728f90ba6d2260b4d451d3f4701d72b8a8cd53921f65e8aa7b6bd3995fef3cf6db60d1e2927c9012ea2a62af3a50fdada2262f8f02d9651d542e3856210af36def3c6d1b712de4dd34c63a09a6d2928019c62a7253cb47a9ed056d7435d723809768192c7df2768aa4b9ab247e1a522fa58532c7d785d2236f92fc1f4ab621023f5e5af084fe41584d136cec5ce33472f85c4dc045e70bbd5b6781c394b4b2872b3734879de37454a5351d272a84301ef5df121c0ac70de6f375b7bb185730baaa7f9b4ab093d66e34e799e3abd94d03b6c344a82968a07ed8b6fea37e5c2275b8ad40faa040558ea8636af91f42be30af2c61c34c50459e04ed93998da10c2d7cb75f4b18fa027fbd7d5f0e0b830784fc530b0df84b253690649dba92671373e43773a324b81624298a5006c9083adf09ff35ab7b098b67e40c65888f6027eb741637afc646b6769c70b594c771fb94049d4f4e74e0c9967689716d8d37405687a7dea0527500df90dee256e496f251892023dc729d42cbfb4f2514cdc177cb427d6d46493770f91744b9c173ddae6b6baf7e2e95dc6dd268e2b89510deeb2fa5aaa108cf4b7da8a2af7a6cb18c32ceec6be8d2ec734bfeffe25464aa0cbcaaea9508c92ffbb1973d7cdc6118845df7d9386da2fac4e36bddb37d01bbd47d0bcb793850865a4ee08836a72281ff1bda146017145962bbbdd486e6e3a457d3f3c0e05a7cd3514e4aaec85730a39fc8ffe8904e1009d565d919b64e388988db05f90599649699a33f7620df75be25c0c45e1f3829ca38df1343f93dd1fe5b8f05584828f9bcc61c474737ddef2ad0b0436cf303ad2f404785a6db7314e9af2e0eaa68fffcd9dac3a905709d31a259c1e5b808c2fe036ffacb4ce0ca072835815e9f232e29c193e8519d0cb4cf4e8b1f9145c13211232d082229bd80efadd0e215e30873233f60a45441295396c03916d2c44cdc30e8c3650b4045b656d530372414723d1739fe353f4124b80d78d0a170925044b225139e75b4a774262656c72ad4cce99725d505871e3c7e01fb45e5f9f36b68f6ed7974f698967fbabe57b3143ed43d7e6c9cf253b16e8758267598f687e69c217194c5ea1bbbae73757d28d109582129dfc4777a27fafb3a8c3f64c5db209e4ce06099dd0ef3ab5c123a6435d2b0603b102e9b88398413373c53d2252620b8bd7293abe35e46be0b2f828ecfe573312dd85444d32fd5d18a39295865d367aec0d51193cfe8284670f3f1febdf64e34bb6f3ecb2efd0c43f66234ff01dee3465d2fb1d9ce87f3ef7f8f57674fb269bbe8f3e2001ef6b610eed4a2d0d2e2c1b696e4e32084fe4c340612aa13636e223dd758cd765e7864b96ba787d16432bd3c
+AD: 3d186bc3d38b19b41e8c039f5417be09358ad8743cb26b6fefe19a9752901a9bc18a6ed325ec307861bd0fa333a9b0d156dbf30a84f11b72d9b74000d1690f317c04598b1930ef6df873fd9c098abdb7e92eb82d9e5675518365af68a990477f2b70fa5514ec5f5010b5ac0d00fa6d848c40c49aed54b526cd8586bb783bcac299b8c0e96853c242d7c34479bca18aff6d55fbef52c735c41a363d68452304125bea529d235e09cc861198bd292ee63ea1387f859eda363f664c3952aa4fae135cbc0d37ae89f2f34cf1a5b6a685ebbfbac18209e0ea38aadd71a6c16163b5676e84b4bc539c4b1079553a6765726cc8064489c8cbfd3c0999021d70b4c0aea0
+CT: 17bb864ba0458a63fa51ec47259f0e22a9aa387bff7774f3badc55e13748c96f4d0463d73a29d70140f384aba50f9efcd5d0fcbfd1b0b4b16226993aa00260fc1f0a0a28b4a9a19acd9d966920a56a95cacee547a0b3b1d6a752e575a10101d3ba91d59a10ac9eac7367caa1e3a5ad7173d149bd69f97ee1e6782e05f14d9434716bd103ca2e48337bb1cc68d54f31d75244a53cf1d2e47f55da7fc2b80b8eea4110c1887b157530cafa2519bef54f7f4641a8bb5bf2a7f3ea50be71aa8def7d6244c49d2d11de0e08058d08e8619aa3cedcfed1850651585e38489b9b1c7a8aad5ccb3fd380ca2745c5b8b530e6c6ce4fdb7acc8de1543d0364a96d6dac08ffe4474a4f34a96a47c4a7d5db27997963546350e28150e34f81dc6d1d354e867d5e3850f285da5890906f76471f8133da4899ee9b6774da38860e7d8de09edb782eefbbcbebfc2b61aaaae92e0f576a789b8ae4c40359e2dc69e352dc1631a7b791b41788b13b228585301e035c134f3e3a51a7622aead20191445437a9283cd03c6fd9cf128006f96eaaebfa4d71476efafef719189aefdee20d14fb5fb2d0a783ec9894edf3e937b405b7eec3c51649bba3c73a2d94e1b3cb059b6d587d9ee2714c813345f5b29852bec2422490edaf8a7423f2481c8c65497db9711143cff07c0a9889b786ac3e4def8065c8417fd56a91b20a27fb6e5bf8a188039fd51ccfb8be365b1a9f4abbf05135c66928a449aeb6110a70894edbe7e00c2111ff7bf718781965f6e49b758397036b9df6ef77f5aa005d98ff9d61612dc70fe0794e6aa9d3e78a86a3d42f5048a0f6ece5d1264eeb88c94ae529c53933b977dceb41da1b0299fd89ef4b94f66cafb67d0165a9e4210b6958f1ee66d30f7be6643970ccd9df3b11ed29580c5352cbfa3bc8cdd11454282de0b43ad748366948871d4862167fa42d6ed8de023009c9944149227f88e135c53bd50f6ea0727e7cf30ec5bf68ec951d5713fa79175e6aa5ccfe634594497e82b57f7efac8e7293d40ca2af0b63be2aa09d8b97edb7002152220ff96c620f2ab9463f1a1f0517a5df03a47842480f06835377506dd50595946a1bbccb0ef299335fe8b442aca0f900f7068d3f4c06b1c7da8c59c22ab6d1489b474c3e346f67d4a4f0b895b6c45a432bca80f95d34fb2c12dd60c4fe0cc1ac1f4e826f353ddc1ec9072554ac2259c572072d309135d3fbf879288c4cebe756663ebab72fe2078c661f3feb5ed7ef398c2f9d69dd289a835e5251d916e733b3f981714dc3e28ef8fc17b230f7aaa8ed11a99d81a7238f9041704c66b1ae02ef7d4a14bf94b5713e6a5f16718e2b2152e4e8a5f9d673dbfb14ce0b032aa7fc9e264f9002a7f955f7644cf16deede930ec209171472f2cdbabc65632220928a64eb29bfaf411b63b58a30a98b1a47a54c007bbd6
+TAG: f2d188b9ec069b81793a841cfdcd1f88
diff --git a/src/crypto/cipher/test/aes_256_gcm_tests.txt b/src/crypto/cipher/test/aes_256_gcm_tests.txt
index dbcee81..30fd422 100644
--- a/src/crypto/cipher/test/aes_256_gcm_tests.txt
+++ b/src/crypto/cipher/test/aes_256_gcm_tests.txt
@@ -1,4 +1,4 @@
-# The AES-256-GCM test cases from cipher_test.txt have been merged into this
+# The AES-256-GCM test cases from cipher_tests.txt have been merged into this
 # file.
 
 KEY: e5ac4a32c67e425ac4b143c83c6f161312a97d88d634afdf9f4da5bd35223f01
diff --git a/src/crypto/cipher/test/aes_256_key_wrap_tests.txt b/src/crypto/cipher/test/aes_256_key_wrap_tests.txt
deleted file mode 100644
index 92d3a04..0000000
--- a/src/crypto/cipher/test/aes_256_key_wrap_tests.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-# These test vectors have been taken from
-# http://csrc.nist.gov/groups/ST/toolkit/documents/kms/key-wrap.pdf
-
-KEY: 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
-NONCE:
-IN: 00112233445566778899AABBCCDDEEFF
-AD:
-CT: 64E8C3F9CE0F5BA263E9777905818A2A
-TAG: 93C8191E7D6E8AE7
-
-KEY: 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
-NONCE:
-IN: 00112233445566778899AABBCCDDEEFF0001020304050607
-AD:
-CT: A8F9BC1612C68B3FF6E6F4FBE30E71E4769C8B80A32CB895
-TAG: 8CD5D17D6B254DA1
-
-KEY: 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
-NONCE:
-IN: 00112233445566778899AABBCCDDEEFF000102030405060708090A0B0C0D0E0F
-AD:
-CT: 28C9F404C4B810F4CBCCB35CFB87F8263F5786E2D80ED326CBC7F0E71A99F43B
-TAG: FB988B9B7A02DD21
diff --git a/src/crypto/cipher/test/chacha20_poly1305_tests.txt b/src/crypto/cipher/test/chacha20_poly1305_tests.txt
index 103c196..018eb56 100644
--- a/src/crypto/cipher/test/chacha20_poly1305_tests.txt
+++ b/src/crypto/cipher/test/chacha20_poly1305_tests.txt
@@ -47,9 +47,6 @@
 CT: e275aeb341e1fc9a70c4fd4496fc7cdb
 TAG: 41acd0560ea6843d3e5d4e5babf6e946
 
-# Test vectors from chacha20_poly1305_old_tests.txt, modified for the RFC 7539
-# AEAD construction.
-
 KEY: 9a97f65b9b4c721b960a672145fca8d4e32e67f9111ea979ce9c4826806aeee6
 NONCE: 000000003de9c0da2bd7f91e
 IN: ""
diff --git a/src/crypto/cipher/test/cipher_test.txt b/src/crypto/cipher/test/cipher_test.txt
deleted file mode 100644
index 21fffdb..0000000
--- a/src/crypto/cipher/test/cipher_test.txt
+++ /dev/null
@@ -1,597 +0,0 @@
-# RC4 tests (from rc4test)
-Cipher = RC4
-Key = 0123456789abcdef0123456789abcdef
-Plaintext = 0123456789abcdef
-Ciphertext = 75b7878099e0c596
-
-Cipher = RC4
-Key = 0123456789abcdef0123456789abcdef
-Plaintext = 0000000000000000
-Ciphertext = 7494c2e7104b0879
-
-Cipher = RC4
-Key = 00000000000000000000000000000000
-Plaintext = 0000000000000000
-Ciphertext = de188941a3375d3a
-
-Cipher = RC4
-Key = ef012345ef012345ef012345ef012345
-Plaintext = 0000000000000000000000000000000000000000
-Ciphertext = d6a141a7ec3c38dfbd615a1162e1c7ba36b67858
-
-Cipher = RC4
-Key = 0123456789abcdef0123456789abcdef
-Plaintext = 123456789ABCDEF0123456789ABCDEF0123456789ABCDEF012345678
-Ciphertext = 66a0949f8af7d6891f7f832ba833c00c892ebe30143ce28740011ecf
-
-Cipher = RC4
-Key = ef012345ef012345ef012345ef012345
-Plaintext = 00000000000000000000
-Ciphertext = d6a141a7ec3c38dfbd61
-
-
-# DES EDE3 CBC tests (from destest)
-Cipher = DES-EDE3-CBC
-Key = 0123456789abcdeff1e0d3c2b5a49786fedcba9876543210
-IV = fedcba9876543210
-Plaintext = 37363534333231204E6F77206973207468652074696D6520666F722000000000
-Ciphertext = 3FE301C962AC01D02213763C1CBD4CDC799657C064ECF5D41C673812CFDE9675
-
-
-# DES EDE CBC tests
-Cipher = DES-EDE-CBC
-Key = 0123456789abcdeff1e0d3c2b5a49786
-IV = fedcba9876543210
-Plaintext = 37363534333231204E6F77206973207468652074696D6520666F722000000000
-Ciphertext = 7948C0DA4FE91CD815DCA96DBC9B60A857EB954F4DEB08EB98722642AE69257B
-
-
-# DES EDE tests
-Cipher = DES-EDE
-Key = 0123456789abcdeff1e0d3c2b5a49786
-IV = fedcba9876543210
-Plaintext = 37363534333231204E6F77206973207468652074696D6520666F722000000000
-Ciphertext = 22E889402E28422F8167AD279D90A566DA75B734E12C671FC2669AECB3E4FE8F
-
-
-# AES 128 ECB tests (from FIPS-197 test vectors, encrypt)
-Cipher = AES-128-ECB
-Key = 000102030405060708090A0B0C0D0E0F
-Operation = ENCRYPT
-Plaintext = 00112233445566778899AABBCCDDEEFF
-Ciphertext = 69C4E0D86A7B0430D8CDB78070B4C55A
-
-
-# AES 256 ECB tests (from FIPS-197 test vectors, encrypt)
-Cipher = AES-256-ECB
-Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
-Operation = ENCRYPT
-Plaintext = 00112233445566778899AABBCCDDEEFF
-Ciphertext = 8EA2B7CA516745BFEAFC49904B496089
-
-
-# AES tests from NIST document SP800-38A
-# For all ECB encrypts and decrypts, the transformed sequence is
-#   AES-bits-ECB:key::plaintext:ciphertext:encdec
-# ECB-AES128.Encrypt and ECB-AES128.Decrypt
-Cipher = AES-128-ECB
-Key = 2B7E151628AED2A6ABF7158809CF4F3C
-Plaintext = 6BC1BEE22E409F96E93D7E117393172A
-Ciphertext = 3AD77BB40D7A3660A89ECAF32466EF97
-
-Cipher = AES-128-ECB
-Key = 2B7E151628AED2A6ABF7158809CF4F3C
-Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
-Ciphertext = F5D3D58503B9699DE785895A96FDBAAF
-
-Cipher = AES-128-ECB
-Key = 2B7E151628AED2A6ABF7158809CF4F3C
-Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
-Ciphertext = 43B1CD7F598ECE23881B00E3ED030688
-
-Cipher = AES-128-ECB
-Key = 2B7E151628AED2A6ABF7158809CF4F3C
-Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
-Ciphertext = 7B0C785E27E8AD3F8223207104725DD4
-
-
-# ECB-AES256.Encrypt and ECB-AES256.Decrypt
-Cipher = AES-256-ECB
-Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
-Plaintext = 6BC1BEE22E409F96E93D7E117393172A
-Ciphertext = F3EED1BDB5D2A03C064B5A7E3DB181F8
-
-Cipher = AES-256-ECB
-Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
-Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
-Ciphertext = 591CCB10D410ED26DC5BA74A31362870
-
-Cipher = AES-256-ECB
-Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
-Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
-Ciphertext = B6ED21B99CA6F4F9F153E7B1BEAFED1D
-
-Cipher = AES-256-ECB
-Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
-Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
-Ciphertext = 23304B7A39F9F3FF067D8D8F9E24ECC7
-
-
-# For all CBC encrypts and decrypts, the transformed sequence is
-#   AES-bits-CBC:key:IV/ciphertext':plaintext:ciphertext:encdec
-# CBC-AES128.Encrypt and CBC-AES128.Decrypt
-Cipher = AES-128-CBC
-Key = 2B7E151628AED2A6ABF7158809CF4F3C
-IV = 000102030405060708090A0B0C0D0E0F
-Plaintext = 6BC1BEE22E409F96E93D7E117393172A
-Ciphertext = 7649ABAC8119B246CEE98E9B12E9197D
-
-Cipher = AES-128-CBC
-Key = 2B7E151628AED2A6ABF7158809CF4F3C
-IV = 7649ABAC8119B246CEE98E9B12E9197D
-Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
-Ciphertext = 5086CB9B507219EE95DB113A917678B2
-
-Cipher = AES-128-CBC
-Key = 2B7E151628AED2A6ABF7158809CF4F3C
-IV = 5086CB9B507219EE95DB113A917678B2
-Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
-Ciphertext = 73BED6B8E3C1743B7116E69E22229516
-
-Cipher = AES-128-CBC
-Key = 2B7E151628AED2A6ABF7158809CF4F3C
-IV = 73BED6B8E3C1743B7116E69E22229516
-Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
-Ciphertext = 3FF1CAA1681FAC09120ECA307586E1A7
-
-
-# CBC-AES256.Encrypt and CBC-AES256.Decrypt
-Cipher = AES-256-CBC
-Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
-IV = 000102030405060708090A0B0C0D0E0F
-Plaintext = 6BC1BEE22E409F96E93D7E117393172A
-Ciphertext = F58C4C04D6E5F1BA779EABFB5F7BFBD6
-
-Cipher = AES-256-CBC
-Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
-IV = F58C4C04D6E5F1BA779EABFB5F7BFBD6
-Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
-Ciphertext = 9CFC4E967EDB808D679F777BC6702C7D
-
-Cipher = AES-256-CBC
-Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
-IV = 9CFC4E967EDB808D679F777BC6702C7D
-Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
-Ciphertext = 39F23369A9D9BACFA530E26304231461
-
-Cipher = AES-256-CBC
-Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
-IV = 39F23369A9D9BACFA530E26304231461
-Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
-Ciphertext = B2EB05E2C39BE9FCDA6C19078C6A9D1B
-
-
-# AES Counter test vectors from RFC3686
-Cipher = AES-128-CTR
-Key = AE6852F8121067CC4BF7A5765577F39E
-IV = 00000030000000000000000000000001
-Operation = ENCRYPT
-Plaintext = 53696E676C6520626C6F636B206D7367
-Ciphertext = E4095D4FB7A7B3792D6175A3261311B8
-
-Cipher = AES-128-CTR
-Key = 7E24067817FAE0D743D6CE1F32539163
-IV = 006CB6DBC0543B59DA48D90B00000001
-Operation = ENCRYPT
-Plaintext = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
-Ciphertext = 5104A106168A72D9790D41EE8EDAD388EB2E1EFC46DA57C8FCE630DF9141BE28
-
-Cipher = AES-128-CTR
-Key = 7691BE035E5020A8AC6E618529F9A0DC
-IV = 00E0017B27777F3F4A1786F000000001
-Operation = ENCRYPT
-Plaintext = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223
-Ciphertext = C1CF48A89F2FFDD9CF4652E9EFDB72D74540A42BDE6D7836D59A5CEAAEF3105325B2072F
-
-Cipher = AES-256-CTR
-Key = 776BEFF2851DB06F4C8A0542C8696F6C6A81AF1EEC96B4D37FC1D689E6C1C104
-IV = 00000060DB5672C97AA8F0B200000001
-Operation = ENCRYPT
-Plaintext = 53696E676C6520626C6F636B206D7367
-Ciphertext = 145AD01DBF824EC7560863DC71E3E0C0
-
-Cipher = AES-256-CTR
-Key = F6D66D6BD52D59BB0796365879EFF886C66DD51A5B6A99744B50590C87A23884
-IV = 00FAAC24C1585EF15A43D87500000001
-Operation = ENCRYPT
-Plaintext = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
-Ciphertext = F05E231B3894612C49EE000B804EB2A9B8306B508F839D6A5530831D9344AF1C
-
-Cipher = AES-256-CTR
-Key = FF7A617CE69148E4F1726E2F43581DE2AA62D9F805532EDFF1EED687FB54153D
-IV = 001CC5B751A51D70A1C1114800000001
-Operation = ENCRYPT
-Plaintext = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223
-Ciphertext = EB6C52821D0BBBF7CE7594462ACA4FAAB407DF866569FD07F48CC0B583D6071F1EC0E6B8
-
-
-# AES GCM test vectors from http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf
-Cipher = AES-128-GCM
-Key = 00000000000000000000000000000000
-IV = 000000000000000000000000
-Plaintext =
-Ciphertext =
-AAD =
-Tag = 58e2fccefa7e3061367f1d57a4e7455a
-
-Cipher = AES-128-GCM
-Key = 00000000000000000000000000000000
-IV = 000000000000000000000000
-Plaintext = 00000000000000000000000000000000
-Ciphertext = 0388dace60b6a392f328c2b971b2fe78
-AAD =
-Tag = ab6e47d42cec13bdf53a67b21257bddf
-
-Cipher = AES-128-GCM
-Key = feffe9928665731c6d6a8f9467308308
-IV = cafebabefacedbaddecaf888
-Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255
-Ciphertext = 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985
-AAD =
-Tag = 4d5c2af327cd64a62cf35abd2ba6fab4
-
-Cipher = AES-128-GCM
-Key = feffe9928665731c6d6a8f9467308308
-IV = cafebabefacedbaddecaf888
-Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
-Ciphertext = 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091
-AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2
-Tag = 5bc94fbc3221a5db94fae95ae7121a47
-
-Cipher = AES-128-GCM
-Key = feffe9928665731c6d6a8f9467308308
-IV = cafebabefacedbad
-Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
-Ciphertext = 61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c742373806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598
-AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2
-Tag = 3612d2e79e3b0785561be14aaca2fccb
-
-Cipher = AES-128-GCM
-Key = feffe9928665731c6d6a8f9467308308
-IV = 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b
-Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
-Ciphertext = 8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca701e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5
-AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2
-Tag = 619cc5aefffe0bfa462af43c1699d050
-
-Cipher = AES-256-GCM
-Key = 0000000000000000000000000000000000000000000000000000000000000000
-IV = 000000000000000000000000
-Plaintext =
-Ciphertext =
-AAD =
-Tag = 530f8afbc74536b9a963b4f1c4cb738b
-
-Cipher = AES-256-GCM
-Key = 0000000000000000000000000000000000000000000000000000000000000000
-IV = 000000000000000000000000
-Plaintext = 00000000000000000000000000000000
-Ciphertext = cea7403d4d606b6e074ec5d3baf39d18
-AAD =
-Tag = d0d1c8a799996bf0265b98b5d48ab919
-
-Cipher = AES-256-GCM
-Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
-IV = cafebabefacedbaddecaf888
-Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255
-Ciphertext = 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad
-AAD =
-Tag = b094dac5d93471bdec1a502270e3cc6c
-
-Cipher = AES-256-GCM
-Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
-IV = cafebabefacedbaddecaf888
-Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
-Ciphertext = 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662
-AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2
-Tag = 76fc6ece0f4e1768cddf8853bb2d551b
-
-Cipher = AES-256-GCM
-Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
-IV = cafebabefacedbad
-Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
-Ciphertext = c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f
-AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2
-Tag = 3a337dbf46a792c45e454913fe2ea8f2
-
-Cipher = AES-256-GCM
-Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
-IV = 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b
-Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
-Ciphertext = 5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f
-AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2
-Tag = a44a8266ee1c8eb0c8b5d4cf5ae9f19a
-
-# local add-ons, primarily streaming ghash tests
-# 128 bytes aad
-Cipher = AES-128-GCM
-Key = 00000000000000000000000000000000
-IV = 000000000000000000000000
-Plaintext =
-Ciphertext =
-AAD = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad
-Tag = 5fea793a2d6f974d37e68e0cb8ff9492
-
-# 48 bytes plaintext
-Cipher = AES-128-GCM
-Key = 00000000000000000000000000000000
-IV = 000000000000000000000000
-Plaintext = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-Ciphertext = 0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0
-AAD =
-Tag = 9dd0a376b08e40eb00c35f29f9ea61a4
-
-# 80 bytes plaintext
-Cipher = AES-128-GCM
-Key = 00000000000000000000000000000000
-IV = 000000000000000000000000
-Plaintext = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-Ciphertext = 0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85a8ee35616f7124a9d5270291
-AAD =
-Tag = 98885a3a22bd4742fe7b72172193b163
-
-# 128 bytes plaintext
-Cipher = AES-128-GCM
-Key = 00000000000000000000000000000000
-IV = 000000000000000000000000
-Plaintext = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-Ciphertext = 0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85a8ee35616f7124a9d527029195b84d1b96c690ff2f2de30bf2ec89e00253786e126504f0dab90c48a30321de3345e6b0461e7c9e6c6b7afedde83f40
-AAD =
-Tag = cac45f60e31efd3b5a43b98a22ce1aa1
-
-# 192 bytes plaintext, iv is chosen so that initial counter LSB is 0xFF
-Cipher = AES-128-GCM
-Key = 00000000000000000000000000000000
-IV = ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-Plaintext = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-Ciphertext = 56b3373ca9ef6e4a2b64fe1e9a17b61425f10d47a75a5fce13efc6bc784af24f4141bdd48cf7c770887afd573cca5418a9aeffcd7c5ceddfc6a78397b9a85b499da558257267caab2ad0b23ca476a53cb17fb41c4b8b475cb4f3f7165094c229c9e8c4dc0a2a5ff1903e501511221376a1cdb8364c5061a20cae74bc4acd76ceb0abc9fd3217ef9f8c90be402ddf6d8697f4f880dff15bfb7a6b28241ec8fe183c2d59e3f9dfff653c7126f0acb9e64211f42bae12af462b1070bef1ab5e3606
-AAD =
-Tag = 566f8ef683078bfdeeffa869d751a017
-
-# 288 bytes plaintext, iv is chosen so that initial counter LSB is 0xFF
-Cipher = AES-128-GCM
-Key = 00000000000000000000000000000000
-IV = ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-Plaintext = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-Ciphertext = 56b3373ca9ef6e4a2b64fe1e9a17b61425f10d47a75a5fce13efc6bc784af24f4141bdd48cf7c770887afd573cca5418a9aeffcd7c5ceddfc6a78397b9a85b499da558257267caab2ad0b23ca476a53cb17fb41c4b8b475cb4f3f7165094c229c9e8c4dc0a2a5ff1903e501511221376a1cdb8364c5061a20cae74bc4acd76ceb0abc9fd3217ef9f8c90be402ddf6d8697f4f880dff15bfb7a6b28241ec8fe183c2d59e3f9dfff653c7126f0acb9e64211f42bae12af462b1070bef1ab5e3606872ca10dee15b3249b1a1b958f23134c4bccb7d03200bce420a2f8eb66dcf3644d1423c1b5699003c13ecef4bf38a3b60eedc34033bac1902783dc6d89e2e774188a439c7ebcc0672dbda4ddcfb2794613b0be41315ef778708a70ee7d75165c
-AAD =
-Tag = 8b307f6b33286d0ab026a9ed3fe1e85f
-
-# 80 bytes plaintext, submitted by Intel
-Cipher = AES-128-GCM
-Key = 843ffcf5d2b72694d19ed01d01249412
-IV = dbcca32ebf9b804617c3aa9e
-Plaintext = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f
-Ciphertext = 6268c6fa2a80b2d137467f092f657ac04d89be2beaa623d61b5a868c8f03ff95d3dcee23ad2f1ab3a6c80eaf4b140eb05de3457f0fbc111a6b43d0763aa422a3013cf1dc37fe417d1fbfc449b75d4cc5
-AAD = 00000000000000000000000000000000101112131415161718191a1b1c1d1e1f
-Tag = 3b629ccfbc1119b7319e1dce2cd6fd6d
-
-Cipher = AES-128-GCM
-Key = 31323334353637383930313233343536
-IV = 31323334353637383930313233343536
-Plaintext = 48656c6c6f2c20576f726c64
-Ciphertext = cec189d0e8419b90fb16d555
-Tag = 32893832a8d609224d77c2e56a922282
-AAD =
-
-# OFB tests from OpenSSL upstream.
-
-# OFB-AES128.Encrypt
-Cipher = AES-128-OFB
-Key = 2B7E151628AED2A6ABF7158809CF4F3C
-IV = 000102030405060708090A0B0C0D0E0F
-Operation = ENCRYPT
-Plaintext = 6BC1BEE22E409F96E93D7E117393172A
-Ciphertext = 3B3FD92EB72DAD20333449F8E83CFB4A
-
-Cipher = AES-128-OFB
-Key = 2B7E151628AED2A6ABF7158809CF4F3C
-IV = 50FE67CC996D32B6DA0937E99BAFEC60
-Operation = ENCRYPT
-Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
-Ciphertext = 7789508D16918F03F53C52DAC54ED825
-
-Cipher = AES-128-OFB
-Key = 2B7E151628AED2A6ABF7158809CF4F3C
-IV = D9A4DADA0892239F6B8B3D7680E15674
-Operation = ENCRYPT
-Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
-Ciphertext = 9740051E9C5FECF64344F7A82260EDCC
-
-Cipher = AES-128-OFB
-Key = 2B7E151628AED2A6ABF7158809CF4F3C
-IV = A78819583F0308E7A6BF36B1386ABF23
-Operation = ENCRYPT
-Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
-Ciphertext = 304C6528F659C77866A510D9C1D6AE5E
-
-# OFB-AES128.Decrypt
-Cipher = AES-128-OFB
-Key = 2B7E151628AED2A6ABF7158809CF4F3C
-IV = 000102030405060708090A0B0C0D0E0F
-Operation = DECRYPT
-Plaintext = 6BC1BEE22E409F96E93D7E117393172A
-Ciphertext = 3B3FD92EB72DAD20333449F8E83CFB4A
-
-Cipher = AES-128-OFB
-Key = 2B7E151628AED2A6ABF7158809CF4F3C
-IV = 50FE67CC996D32B6DA0937E99BAFEC60
-Operation = DECRYPT
-Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
-Ciphertext = 7789508D16918F03F53C52DAC54ED825
-
-Cipher = AES-128-OFB
-Key = 2B7E151628AED2A6ABF7158809CF4F3C
-IV = D9A4DADA0892239F6B8B3D7680E15674
-Operation = DECRYPT
-Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
-Ciphertext = 9740051E9C5FECF64344F7A82260EDCC
-
-Cipher = AES-128-OFB
-Key = 2B7E151628AED2A6ABF7158809CF4F3C
-IV = A78819583F0308E7A6BF36B1386ABF23
-Operation = DECRYPT
-Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
-Ciphertext = 304C6528F659C77866A510D9C1D6AE5E
-
-# OFB-AES256.Encrypt
-Cipher = AES-256-OFB
-Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
-IV = 000102030405060708090A0B0C0D0E0F
-Operation = ENCRYPT
-Plaintext = 6BC1BEE22E409F96E93D7E117393172A
-Ciphertext = DC7E84BFDA79164B7ECD8486985D3860
-
-Cipher = AES-256-OFB
-Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
-IV = B7BF3A5DF43989DD97F0FA97EBCE2F4A
-Operation = ENCRYPT
-Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
-Ciphertext = 4FEBDC6740D20B3AC88F6AD82A4FB08D
-
-Cipher = AES-256-OFB
-Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
-IV = E1C656305ED1A7A6563805746FE03EDC
-Operation = ENCRYPT
-Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
-Ciphertext = 71AB47A086E86EEDF39D1C5BBA97C408
-
-Cipher = AES-256-OFB
-Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
-IV = 41635BE625B48AFC1666DD42A09D96E7
-Operation = ENCRYPT
-Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
-Ciphertext = 0126141D67F37BE8538F5A8BE740E484
-
-
-# OFB-AES256.Decrypt
-Cipher = AES-256-OFB
-Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
-IV = 000102030405060708090A0B0C0D0E0F
-Operation = DECRYPT
-Plaintext = 6BC1BEE22E409F96E93D7E117393172A
-Ciphertext = DC7E84BFDA79164B7ECD8486985D3860
-
-Cipher = AES-256-OFB
-Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
-IV = B7BF3A5DF43989DD97F0FA97EBCE2F4A
-Operation = DECRYPT
-Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
-Ciphertext = 4FEBDC6740D20B3AC88F6AD82A4FB08D
-
-Cipher = AES-256-OFB
-Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
-IV = E1C656305ED1A7A6563805746FE03EDC
-Operation = DECRYPT
-Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
-Ciphertext = 71AB47A086E86EEDF39D1C5BBA97C408
-
-Cipher = AES-256-OFB
-Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
-IV = 41635BE625B48AFC1666DD42A09D96E7
-Operation = DECRYPT
-Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
-Ciphertext = 0126141D67F37BE8538F5A8BE740E484
-
-
-# AES-192 CBC-mode test from upstream OpenSSL.
-Cipher = AES-192-CBC
-Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
-IV = 000102030405060708090A0B0C0D0E0F
-Plaintext = 6BC1BEE22E409F96E93D7E117393172A
-Ciphertext = 4F021DB243BC633D7178183A9FA071E8
-
-Cipher = AES-192-CBC
-Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
-IV = 4F021DB243BC633D7178183A9FA071E8
-Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
-Ciphertext = B4D9ADA9AD7DEDF4E5E738763F69145A
-
-Cipher = AES-192-CBC
-Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
-IV = B4D9ADA9AD7DEDF4E5E738763F69145A
-Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
-Ciphertext = 571B242012FB7AE07FA9BAAC3DF102E0
-
-Cipher = AES-192-CBC
-Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
-IV = 571B242012FB7AE07FA9BAAC3DF102E0
-Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
-Ciphertext = 08B0E27988598881D920A9E64F5615CD
-
-
-# AES-192-ECB tests from FIPS-197
-Cipher = AES-192-ECB
-Key = 000102030405060708090A0B0C0D0E0F1011121314151617
-Operation = ENCRYPT
-Plaintext = 00112233445566778899AABBCCDDEEFF
-Ciphertext = DDA97CA4864CDFE06EAF70A0EC0D7191
-
-
-# AES-192-ECB tests from NIST document SP800-38A
-Cipher = AES-192-ECB
-Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
-Plaintext = 6BC1BEE22E409F96E93D7E117393172A
-Ciphertext = BD334F1D6E45F25FF712A214571FA5CC
-
-Cipher = AES-192-ECB
-Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
-Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
-Ciphertext = 974104846D0AD3AD7734ECB3ECEE4EEF
-
-Cipher = AES-192-ECB
-Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
-Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
-Ciphertext = EF7AFD2270E2E60ADCE0BA2FACE6444E
-
-Cipher = AES-192-ECB
-Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
-Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
-Ciphertext = 9A4B41BA738D6C72FB16691603C18E0E
-
-# DES ECB tests
-
-Cipher = DES-ECB
-Key = 0000000000000000
-Plaintext = 0000000000000000
-Ciphertext = 8CA64DE9C1B123A7
-
-Cipher = DES-ECB
-Key = FFFFFFFFFFFFFFFF
-Plaintext = FFFFFFFFFFFFFFFF
-Ciphertext = 7359B2163E4EDC58
-
-Cipher = DES-ECB
-Key = 3000000000000000
-Plaintext = 1000000000000001
-Ciphertext = 958E6E627A05557B
-
-Cipher = DES-ECB
-Key = 1111111111111111
-Plaintext = 1111111111111111
-Ciphertext = F40379AB9E0EC533
-
-Cipher = DES-ECB
-Key = 0123456789ABCDEF
-Plaintext = 1111111111111111
-Ciphertext = 17668DFC7292532D
-
-Cipher = DES-ECB
-Key = 1111111111111111
-Plaintext = 0123456789ABCDEF
-Ciphertext = 8A5AE1F81AB8F2DD
-
-Cipher = DES-ECB
-Key = FEDCBA9876543210
-Plaintext = 0123456789ABCDEF
-Ciphertext = ED39D950FA74BCC4
diff --git a/src/crypto/cipher/test/cipher_tests.txt b/src/crypto/cipher/test/cipher_tests.txt
new file mode 100644
index 0000000..e75e664
--- /dev/null
+++ b/src/crypto/cipher/test/cipher_tests.txt
@@ -0,0 +1,621 @@
+# RC4 tests (from rc4test)
+Cipher = RC4
+Key = 0123456789abcdef0123456789abcdef
+Plaintext = 0123456789abcdef
+Ciphertext = 75b7878099e0c596
+
+Cipher = RC4
+Key = 0123456789abcdef0123456789abcdef
+Plaintext = 0000000000000000
+Ciphertext = 7494c2e7104b0879
+
+Cipher = RC4
+Key = 00000000000000000000000000000000
+Plaintext = 0000000000000000
+Ciphertext = de188941a3375d3a
+
+Cipher = RC4
+Key = ef012345ef012345ef012345ef012345
+Plaintext = 0000000000000000000000000000000000000000
+Ciphertext = d6a141a7ec3c38dfbd615a1162e1c7ba36b67858
+
+Cipher = RC4
+Key = 0123456789abcdef0123456789abcdef
+Plaintext = 123456789ABCDEF0123456789ABCDEF0123456789ABCDEF012345678
+Ciphertext = 66a0949f8af7d6891f7f832ba833c00c892ebe30143ce28740011ecf
+
+Cipher = RC4
+Key = ef012345ef012345ef012345ef012345
+Plaintext = 00000000000000000000
+Ciphertext = d6a141a7ec3c38dfbd61
+
+
+# DES EDE3 CBC tests (from destest)
+Cipher = DES-EDE3-CBC
+Key = 0123456789abcdeff1e0d3c2b5a49786fedcba9876543210
+IV = fedcba9876543210
+Plaintext = 37363534333231204E6F77206973207468652074696D6520666F722000000000
+Ciphertext = 3FE301C962AC01D02213763C1CBD4CDC799657C064ECF5D41C673812CFDE9675
+
+
+# DES EDE CBC tests
+Cipher = DES-EDE-CBC
+Key = 0123456789abcdeff1e0d3c2b5a49786
+IV = fedcba9876543210
+Plaintext = 37363534333231204E6F77206973207468652074696D6520666F722000000000
+Ciphertext = 7948C0DA4FE91CD815DCA96DBC9B60A857EB954F4DEB08EB98722642AE69257B
+
+
+# DES EDE tests
+Cipher = DES-EDE
+Key = 0123456789abcdeff1e0d3c2b5a49786
+IV = fedcba9876543210
+Plaintext = 37363534333231204E6F77206973207468652074696D6520666F722000000000
+Ciphertext = 22E889402E28422F8167AD279D90A566DA75B734E12C671FC2669AECB3E4FE8F
+
+
+# AES 128 ECB tests (from FIPS-197 test vectors, encrypt)
+Cipher = AES-128-ECB
+Key = 000102030405060708090A0B0C0D0E0F
+Operation = ENCRYPT
+Plaintext = 00112233445566778899AABBCCDDEEFF
+Ciphertext = 69C4E0D86A7B0430D8CDB78070B4C55A
+
+
+# AES 256 ECB tests (from FIPS-197 test vectors, encrypt)
+Cipher = AES-256-ECB
+Key = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
+Operation = ENCRYPT
+Plaintext = 00112233445566778899AABBCCDDEEFF
+Ciphertext = 8EA2B7CA516745BFEAFC49904B496089
+
+
+# AES tests from NIST document SP800-38A
+# For all ECB encrypts and decrypts, the transformed sequence is
+#   AES-bits-ECB:key::plaintext:ciphertext:encdec
+# ECB-AES128.Encrypt and ECB-AES128.Decrypt
+Cipher = AES-128-ECB
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+Plaintext = 6BC1BEE22E409F96E93D7E117393172A
+Ciphertext = 3AD77BB40D7A3660A89ECAF32466EF97
+
+Cipher = AES-128-ECB
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
+Ciphertext = F5D3D58503B9699DE785895A96FDBAAF
+
+Cipher = AES-128-ECB
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
+Ciphertext = 43B1CD7F598ECE23881B00E3ED030688
+
+Cipher = AES-128-ECB
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
+Ciphertext = 7B0C785E27E8AD3F8223207104725DD4
+
+
+# ECB-AES256.Encrypt and ECB-AES256.Decrypt
+Cipher = AES-256-ECB
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+Plaintext = 6BC1BEE22E409F96E93D7E117393172A
+Ciphertext = F3EED1BDB5D2A03C064B5A7E3DB181F8
+
+Cipher = AES-256-ECB
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
+Ciphertext = 591CCB10D410ED26DC5BA74A31362870
+
+Cipher = AES-256-ECB
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
+Ciphertext = B6ED21B99CA6F4F9F153E7B1BEAFED1D
+
+Cipher = AES-256-ECB
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
+Ciphertext = 23304B7A39F9F3FF067D8D8F9E24ECC7
+
+
+# For all CBC encrypts and decrypts, the transformed sequence is
+#   AES-bits-CBC:key:IV/ciphertext':plaintext:ciphertext:encdec
+# CBC-AES128.Encrypt and CBC-AES128.Decrypt
+Cipher = AES-128-CBC
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+IV = 000102030405060708090A0B0C0D0E0F
+Plaintext = 6BC1BEE22E409F96E93D7E117393172A
+Ciphertext = 7649ABAC8119B246CEE98E9B12E9197D
+
+Cipher = AES-128-CBC
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+IV = 7649ABAC8119B246CEE98E9B12E9197D
+Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
+Ciphertext = 5086CB9B507219EE95DB113A917678B2
+
+Cipher = AES-128-CBC
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+IV = 5086CB9B507219EE95DB113A917678B2
+Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
+Ciphertext = 73BED6B8E3C1743B7116E69E22229516
+
+Cipher = AES-128-CBC
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+IV = 73BED6B8E3C1743B7116E69E22229516
+Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
+Ciphertext = 3FF1CAA1681FAC09120ECA307586E1A7
+
+
+# CBC-AES256.Encrypt and CBC-AES256.Decrypt
+Cipher = AES-256-CBC
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+IV = 000102030405060708090A0B0C0D0E0F
+Plaintext = 6BC1BEE22E409F96E93D7E117393172A
+Ciphertext = F58C4C04D6E5F1BA779EABFB5F7BFBD6
+
+Cipher = AES-256-CBC
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+IV = F58C4C04D6E5F1BA779EABFB5F7BFBD6
+Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
+Ciphertext = 9CFC4E967EDB808D679F777BC6702C7D
+
+Cipher = AES-256-CBC
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+IV = 9CFC4E967EDB808D679F777BC6702C7D
+Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
+Ciphertext = 39F23369A9D9BACFA530E26304231461
+
+Cipher = AES-256-CBC
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+IV = 39F23369A9D9BACFA530E26304231461
+Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
+Ciphertext = B2EB05E2C39BE9FCDA6C19078C6A9D1B
+
+
+# AES Counter test vectors from RFC3686
+Cipher = AES-128-CTR
+Key = AE6852F8121067CC4BF7A5765577F39E
+IV = 00000030000000000000000000000001
+Operation = ENCRYPT
+Plaintext = 53696E676C6520626C6F636B206D7367
+Ciphertext = E4095D4FB7A7B3792D6175A3261311B8
+
+Cipher = AES-128-CTR
+Key = 7E24067817FAE0D743D6CE1F32539163
+IV = 006CB6DBC0543B59DA48D90B00000001
+Operation = ENCRYPT
+Plaintext = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
+Ciphertext = 5104A106168A72D9790D41EE8EDAD388EB2E1EFC46DA57C8FCE630DF9141BE28
+
+Cipher = AES-128-CTR
+Key = 7691BE035E5020A8AC6E618529F9A0DC
+IV = 00E0017B27777F3F4A1786F000000001
+Operation = ENCRYPT
+Plaintext = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223
+Ciphertext = C1CF48A89F2FFDD9CF4652E9EFDB72D74540A42BDE6D7836D59A5CEAAEF3105325B2072F
+
+Cipher = AES-256-CTR
+Key = 776BEFF2851DB06F4C8A0542C8696F6C6A81AF1EEC96B4D37FC1D689E6C1C104
+IV = 00000060DB5672C97AA8F0B200000001
+Operation = ENCRYPT
+Plaintext = 53696E676C6520626C6F636B206D7367
+Ciphertext = 145AD01DBF824EC7560863DC71E3E0C0
+
+Cipher = AES-256-CTR
+Key = F6D66D6BD52D59BB0796365879EFF886C66DD51A5B6A99744B50590C87A23884
+IV = 00FAAC24C1585EF15A43D87500000001
+Operation = ENCRYPT
+Plaintext = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
+Ciphertext = F05E231B3894612C49EE000B804EB2A9B8306B508F839D6A5530831D9344AF1C
+
+Cipher = AES-256-CTR
+Key = FF7A617CE69148E4F1726E2F43581DE2AA62D9F805532EDFF1EED687FB54153D
+IV = 001CC5B751A51D70A1C1114800000001
+Operation = ENCRYPT
+Plaintext = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223
+Ciphertext = EB6C52821D0BBBF7CE7594462ACA4FAAB407DF866569FD07F48CC0B583D6071F1EC0E6B8
+
+# Regression test for https://github.com/openssl/openssl/issues/1916.
+Cipher = AES-128-CTR
+Key = 7E24067817FAE0D743D6CE1F32539163
+IV = 00000000000000007FFFFFFFFFFFFFFF
+Operation = ENCRYPT
+Plaintext = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F
+Ciphertext = A2D459477E6432BD74184B1B5370D2243CDC202BC43583B2A55D288CDBBD1E03
+
+
+# AES GCM test vectors from http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-spec.pdf
+Cipher = AES-128-GCM
+Key = 00000000000000000000000000000000
+IV = 000000000000000000000000
+Plaintext =
+Ciphertext =
+AAD =
+Tag = 58e2fccefa7e3061367f1d57a4e7455a
+
+Cipher = AES-128-GCM
+Key = 00000000000000000000000000000000
+IV = 000000000000000000000000
+Plaintext = 00000000000000000000000000000000
+Ciphertext = 0388dace60b6a392f328c2b971b2fe78
+AAD =
+Tag = ab6e47d42cec13bdf53a67b21257bddf
+
+Cipher = AES-128-GCM
+Key = feffe9928665731c6d6a8f9467308308
+IV = cafebabefacedbaddecaf888
+Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255
+Ciphertext = 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091473f5985
+AAD =
+Tag = 4d5c2af327cd64a62cf35abd2ba6fab4
+
+Cipher = AES-128-GCM
+Key = feffe9928665731c6d6a8f9467308308
+IV = cafebabefacedbaddecaf888
+Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+Ciphertext = 42831ec2217774244b7221b784d0d49ce3aa212f2c02a4e035c17e2329aca12e21d514b25466931c7d8f6a5aac84aa051ba30b396a0aac973d58e091
+AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2
+Tag = 5bc94fbc3221a5db94fae95ae7121a47
+
+Cipher = AES-128-GCM
+Key = feffe9928665731c6d6a8f9467308308
+IV = cafebabefacedbad
+Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+Ciphertext = 61353b4c2806934a777ff51fa22a4755699b2a714fcdc6f83766e5f97b6c742373806900e49f24b22b097544d4896b424989b5e1ebac0f07c23f4598
+AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2
+Tag = 3612d2e79e3b0785561be14aaca2fccb
+
+Cipher = AES-128-GCM
+Key = feffe9928665731c6d6a8f9467308308
+IV = 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b
+Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+Ciphertext = 8ce24998625615b603a033aca13fb894be9112a5c3a211a8ba262a3cca7e2ca701e4a9a4fba43c90ccdcb281d48c7c6fd62875d2aca417034c34aee5
+AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2
+Tag = 619cc5aefffe0bfa462af43c1699d050
+
+Cipher = AES-128-GCM
+Key = 3de7b368783bd7287f2b9b731814c876
+IV = 90dedcfff100eb1f1db9d935
+Plaintext = 8d766795cadc0961c0f448c62df3827eef3a8664599b3adbaab0cfd63875bceb8f992b4f7447dca10ddd716aa0bc4fe925e1aa3e3fd1d5c430c650fe3546d6b9a24d576a857c5f04e8c0a3b149df277aa19cfa64ee235891d3b8ec0e840d268b1e70dd8a4bf97628a0c7aea38aa21eeb8fb1a8437f2abfee05e0d2c30659e312ec03d30da51b7c19073a2341c17df806e27e796d581143d39e4de8d3f8d46aa6d6fc1a98d94fa69b92dab751d930cc12de21fb1a7468af09e3c12ff6c3db3967d10cf140bc46f17a16e24b010b6cba5ebf777341c52042596ee53008389c48d9690ab9f5625795c3e588f72f7a1670b2b25a9f4eee1c8845ac90f1bf47ae4ea4b607a50aca88ed304cbb700d02d5486139b0bc81ec042e574abf986972fa008b83ef22dbfe720c2f2f6355c87c975932cec545ebed657e5e7570c503e9aa7f0b87d0b2648e421ed1d34749637c95d1e931af8925236387e50454f0ba2e22ed05f90450fad46f4eb7ddb08656511dd065c0f852a7e42f618a961a6c6bec42226c6b6043580b009ec9837cf99844cb74794a82c269ff648e0bae9ae50256a0ad98ad9f5a35057b3004ac96f469f9ee966dadc16dc47616586cf242706df96bb2f7ee43d3bd1c65d2eac7b82ef242e77ab509afb9639e5f3995380e926305729ca762c487f4411ec2a9c688b8347e5287216dbb38c3fe2281a89fcb47ee2ee7ddf79bfa3ab61cd56a00981019bbcea8aa0444eb75958e5fa56ea0036d2de4950a7db886f4a318b433bd41e00905ab158171e0ef13172293bdf70064b9dc7b243bf9dc927589bf9e99468d1cb330639dbff1850cc51929b8971b0b2ede9d06bc5f6ba39d4551b587f09bf6f8206e8f1524f55714612581d6aa45d8fb83425f84a736576deeecafdcbfbb8670d14cd2ab2a7f8b7f374c07881b7bac2605fd5ff7ff7cf43e30cf49910961a9079c0343b8601be8c3e9fe38f49fdab0b7e1a8c1536cf84e4d80d26ae5ec37570839b5cda02929221898d611525c3a88fc444167ffc532b256cdd0a8f31ff08097d75b629fab99c9e1062d1d9962b211e15ec8709934029c4934e64db8d7a2f32e23dc541be306e9a57a3419115994cbc3a8f8d5ea2a6f45b9ea9ac0e51ed0c6680fa029f4552a6c8665aab00ab77928342e7284c321e9500ad4774ef1fed0f596d5aea371fe1793271aef38cde55547f34701a525526e83a72673385a85f44db511bc87ce1f831fc6ccf8204ca4f4a20eac09897aae93684f14ede21bcaf40a09c08012b92600d6a839ebdf8bdca7b34192c6c50bad8796b3be3c375dbae6217815d2c75cc878d39b4e842d4eaa5f5df2242cf230e44a240e18e47827f089b18bf880fd41a2516eac8e6ba3fc2db64a4bc28789860d7b18d9edeae8b3059f4d945b15d0ee27b1f74842dd1df117fe83a8fdade23a47c93902eedc4d33f2dbfcd1996e6dc1458409fde2302830e8d44c58c5ae67486b9950dd938f14c38bc4c9484fdc4ded93a0f90875773453fc14d428cd6e7beb0c705d61229d2b3df09632ebb30b325fefe2aebbf2a7aa8e4ad46277ca4b8b078818b63d04e7652057f6cbbab7c43ac355537e0d3918b4a73c00dbe6b30a27ee7a6fa213d3347ae478e8edc323404b8322b9c7b0173ed61c38ed25f3576a675d527d22edd51d6dfa5767560d3a50a91226338e8c4e6436eedbcd3d2efe9dc1e686b15d2f57d553abcfda57dc316ca453a690f20148f0dfa20c1c4a58240aaf7195095fedfa56d839d0230d55ce9a8ca1b9d1acd6fe98d583148ba0f4a4e3413c76e6ec57ddb79428d3a90079f64d3321c791f60d501c3fd02c8403f0f5e6c6836bbc96430c1b48e83350c3a3cfd017f15bee3e4bb1295d821dc98b85ab3145555cce2c34a8142fe50f8db19918b514a165d12ff6301fb2296788760ac0b6d9e3a57770ad5111cde5d24b6321918cb0b0887a282b827a8749733171914b000e7d3c0edad1d42ca60da37f0698554bb2a1749f73b3120dbeaa32951f8217a781a200467d5b569d16f56fc9b7dff0ac524f03fee0617f4c692d94613b1e13b18075dc9f0d32811d4a8949a95f6b5fa46aeb83597adb409e68b2a0177c36dcc95dcb2e7dd4fb7337ff97c013364fe139e185014948fa698741d822044fa3f6978b16afd18138c845587c405ebf7a6cd1c28610ce67e992ed49e406658a0a202feed9709500d064b6f53eecfca57dd4b38363ce3aae9d59126d8ae7e140a373851188ae28c909181d0ac64770df70dd2475809350cb367825b59d521d5e457b4e36aea6dedd90a2266898b753b57fa359d43cd388e7d6c7ed90bc4c2af34ceafe88a3af6ac376fec35f1240f08af4f3eb30bc53dd68e5762e6d39e6b16f63003fbe0bee828d0d7adc58c41e857c2c44702215b202701fc696eae021af19c79e59c3e32627cd571f5db99b17f1772b5d746196befabb0b7446687827f3315b391d5dff069b1c39c00bb143218ef458e3b397e1c99640d57fc8db2e0083d3d22ed4111a8fc9e0e6f55fe6a56e946dbee43909bdd7d516fdf756ed8099ba80b1e17a5e279119345104379a36962ca9c8b2a53c414d79eb09fe79862ca749a9eabd9185ad1df57215945882f5894868a134bfc35c835e040e77ecf077d6a98a73ee022963d70b036be3fe5718280ae52c5d751211b22950c0597aaedd35af41f7dd5999e5f7ee34a37edcf97df54a46742b0252b196eaee454ff0c30685b15f8de087de208906be1d971f0fd89f7cdff2af0bdc96759d6889fba9ef092ad1c8deab0404562a7f3977d211c28dfd1573aebd5427a8773f03986101703fa19cd4ab96a381c76a747f63b63f7a9a3a08e251cdc593a024f63b443b76d17dd9e151809da3c582fbd334fa6dd0221b6d410c6a78ba95bb0154bb8999f619f2e084a6b9755ceee4ca3c7e0481a47776c8814f13054e627e37630d593bd09d5f10a049c66c9999f4b0b037e81ef70615d674c7c7975972994a053c069675fad3fae5ae3e779233b70254fb87f25d44c104afc3d5911b8b695173f9337130e39a02cf97356cb817f6cd23f55ef74dd06bd24ce5887a7001ef576262ffaa99f9bb5e3f55bda2aa0f199115909af48bb4d6b1a0a0847774515302cafebe75aad1f63362b1f38141e8721851c3ef1a247931b3b450581eb5d09027b9e3ba60ae9801d629b74991b7fd65520eac561d47115a85141d9a757bc75710bedff1630561ae05254ea541a7ff1846ed5e164834417556dd562c45543c88d8030bb56451fd5b3cbf10fb0164c5288789d2aac7e7a836e79bc3dd401a8e3e05aa6714ffb2dfddb3037c35fa1ebed62a073b2da42133f2620ae88de5e3f46cc69f2b9b3c9b88e39b8b108059ac6bd493be5f7a39f6b53ee825f4593b77ec9238f5ab804d533f48803e7d8187291ee25cfac4da5d8c9279517adfb09c422f6d704711726c73828a5082b4c7b3d85611b8f496d3e0f78c5c4f1dd1c722b1b11d55861f232beee6aaef8a00fd2eeeb45f182af191ca6de8eaa25ceda5451416fbf6d1abc0670b8c10e2815076f271044c690bdcb64856b91265bac202043a28f6bbeb807535aad4bd89e572a9427c826b170d3862f4cca70ddffb4769d6593a1cc6c42fd06cf68642835fe474a23e6f63df316f8361bab959b768d78e20c03c2a99913c162a9662bd9981eee55922f36792de0af68da04ab49dca72e3d9b0de79df828b433bcf6be073f851a36418c03a717d54d48c1014ccb793577c8393b7cb53cad6bc7060a54cc6363734f6ad388763519ca09b533078d3cfa61d7bdd4c4dd0ffe64d68d501b55903d3f4a1f310a3826ac2ca700de01d656188dcf577fd1b63e305614b8d13471f6f84a5d4b12c5e119870a63d1e3dbd39d3b5c26b09f9d80f8a59ce836b20bc933496923d278a022c00f3aac204d07d2e5075bbcef1e4820d633a3a2b35974f72a033484a91a1d6a9913239c93e5783b01833073c98f358e3465efd5087af37ad60b7285550e776d67ea7019e788776c5a456102358c32eb4e7c28096af88b9a20d8ce379ba3928a10ffd539c106f4927e7ac0f382c74017d6e4438fb128c660affd45e9bb68452de72b574eeffe3ce239d0718908c3800bc7e8ecd2fc7d9754171506017fd7868594c9373a96579fed475a28811649ce5dc8a3107bd0d8578748878ce4998684620931dc3981a2499568c2f61174c3b3fc46a7010468e8ff75c08cd43ac764d95e2ad1659f9db62e9554f811e0f43bb74779d923c8c243d12a5314d3c0c6ec84fe60e1d2b2e2b20d3e64054d62049ef9233ff55223a319c285e4e3f4c98dc95b2ca81230d7fed9bb99fd7d97430eb32c9c11647992bd85dcb47cfd58ea3e221d095bcf9374a6baa7c8333581f62b9e489282483023fdd18451f09bec764146b587209160b3d1d7a3d2e145fdb640c4bc382541e0d84255122d51a710887ebe1ccf29d41b4dd7fd7368d68ada250d3968d6f0971f0849c13c09abadb9db8b08960a18f84f0346ea0aa71227afa55b90cabc062d549b616400d36450b19adb67d7358e48c043fa1135abfca89374c906f8d1a6a845debf6b37f055d390b029c7f4524958bdf8d7e2755dde3b957f0926f9d3b8821ba96044d3cad2d637b973bfb657fcc06ff44c17965acf572ab7a0c87604c7dd1cfd136a0ad02b22e8ef320e101ea09772588e8c5b4d88f40fe1be18d27146a2b9559491949671700cebff9a709f297c2621ca9d5d1749623abc20a326ff5be55cb9435c03bf49b147b1e0a4a918bfdc3642df90b396a474f81d75c953d87b3f3b4e31fced630bd7c481c63acbb84dd31249101ac5277a36dcdfc80d8d9a2e928e9b2d65bb257bce97ccda83b187da8a7886dc96eab93d0864d88c358105f9cfe1ad0f0a8508b5b3985ff95de652e684da970b57669aa3fdfbe590a631522abe8246393639709a9a6cd549e78e3c2d1acf84643e9f554c5e076f75a5c1dce1be20a66722d0b896837b7036509ab8d473d5d2b7a8374d6a575f69d54afe3e7e18f4faf4e917be8a74e55c271b96d966e0c0b883f84b3ef2e4f278daeda2efd3ce770801d2c4bda5eb9b646deeab9fa55324e917e63e4eb6aeb4176cb4e43af3db61aea1546fbf16e76a12fcdbe726b565710e3f9866551023e5fbac0038678717e6ab4d3e92dcc53049e8cb65c00216d31a8869ff4d3539313fe2fd7ce0f53b255e3659e7dfc5f92b7627dd9ba42972f0ba72b888932d870ab97226040c4c0f4826be131fe1d2cdc21005ec2addd7796f0927501251ab26b0e5f3f9d2a1cb346a774e18bc233cc89aa69f5f70e3d5c17098eed350ec419c82837153b5c7f5813bf5918defc8df143063f3fe45125deded2b15892d5cebce589b60f2ada0f9d608983e8d107d8e6482b5f542c6650b014445e8c055aac142f16cfc59229fc9626f7aaa40cefacef777e494e13dfa93d27c201788ca9f60e572af8d65ffb513473dade5fe494cbf7377bd1ed03db2571d65af3be4b0bf27c1f069797bfb67ef0bd8a88c6286af6712c106df9c418d88054e3b46c88296a2e63894d6bee0dda8833c373d6a1b27637e1510fea3eb2fb34ae27354571369653a282a8d19f2c34f9e5ec34555b4ed24327dc5d246df13736bd41021697104f80c85bd0ae920e9aeb4e628fb8aec269d55858df149af298b06d61250b043c8a14a15f0646d0aaa18109d031c449e66dd7336044dbdec912b1bb615fae2a3df480bd64cbed74be65c8f1acac247e80bbaeb6f9dab38c6addf4f3b094d5934ef5c9749053b9159e280034e601731a12d6688ff27ee3581ae289de424d16676fb750d2ccd5b3f964dd77bdefc15bb204e2350632822384cc194cf9130f1ee81bfc3887d3366ec0b48cbbe0fe674281ae7445f03791887873659825680448f162452cef57d783821a73047078a8cf94c416850092ac772ef0b2e48517ef101ee0681b5259aa27fd56edf3c01e6dba6298ccc91b09bb304b637eccf8c673b816e74bd7f8ceffa6b17ab03df7ee9ca4098d24d044015a07df782a309cb6761528272632a6e1323c4e18284b463dfcabed708e4fc95cef133865cdbec8bfdde100621c65a92762cc3141ff37b66dea8fa6e3aad61dcbf3b512467c4773d36e58989e12a636389c1678c191137a5f7f59668c8a527dddcdd0c3fbb14cf48b8f3ea306850a5eda76c57aad06312d7bbfc18969d7b611f512358a7bdf959cc2f41de1c408133ef02b1fb2cdf8efe9973c27536434e56fc1bb4880db7fe901087b53ef3c0de18aafa47c25f1cd62c362f2e5da41c2dbff0e13adaba26c1e0829f027dc0320442e851eaed9507b70ac17180725349f6ea7b59bf39c095a9d10790e87221c7c2d24b8bca184ee95a3ef7449aad6c1d905f688498ae7a0cd1b01f76dabc342fb2be0295ca1484bece3c9b8a1b91e53de2d2587f3607a7f348f5cbefaa7a6dcf61bbbcae9444e2d25a77b016cbd1508c8cd319e9812b43b0bbca52df155d418dacb6ab1360a9e605fb53c6e20588a10bef42d884989e836b2ff16fbcdd2c1704f75dc8c1ac2cc6aeb92726f5d46e4784c70e1e249c102be6da506e5e3c2cef6a8bc4a60dac7adf3cacca8679f8f792ddc27613e44a70fd849b7617e042da46d65a3e6cf425f59b83cbae5b6e911142abd13a0a8cdf06d041435ee20e2ca417e905d2dc49c15b863ae5920ff7f9380a86bb0c86b69a000c157cd35245bf71f9dfdefbd1760af90ec3e554ebc511aebf650633221ca9157226f613f41406872765f8d7b916ff3877266f017b8d840dca0697ec3dffce7912ea9eafb62cc2f2d0a112c9bc0727444b47b62766bddf5b5f26d391f653b6894b069069979d0cf8cc7fc4143626a8420bc0a3866db3860096cc128d620ceff059d1614487004adbdf6b0c4428ac8897dcf16e6b11a692a6b465a92b40010f3480b444d4d2e24b0af8467666905c2a6233bdd6502521b621d3cdd4a5e1f268d65bf6a1879608ffd3abf635c5f0948f3cec7e087485c72b00258ba69783cfe7d611bc41c27814ef5674185791dbe626e1f276cf2c399a4eb264f19c77ee95d94252f546528f629188318e9ede65a927aafd2f2af56ff32c0ef39862d2f92268bc9400afa8ddeff591f3ef99681263a33b873bd9e01a59c8b281da30875245cbffee5268563c7f6f20b9e22d998934131dd219624d3cef6df2f3d2d6401833f72c619d6f763837141dbf93179d0f01375581ebe227185166aa7988eb9fd453d510ca6616cc013d551d23a33a4241e85aac3201284344977d496d768f5d920c5670b1d8bb608efc1b99abd261afb0a4ebe191605cc5c2e20523a13b3b94dd1fb24a27009d9a5b6329336f3516a327642386ba64c8769da1324a8a3d1f304cf0700df2b3e38215a954523e1d40ae96d0046e2929a815bf70785e94bc9b89246ab6aded60d65170eeb49b0ee0a57ee2e57db92409105c25f2d0c1a17b5556d06511bd0991a426258372c7f2b402dd533a75aa175524eb5d6b9575300b81fdb2258bd74429add8aa477bd1182db57107d411d16147defc3582861c68f5ce82e0a0316edd5d0f3cf36825a2c79a33e376cce2e63274b3b41bcbdd755845ad9ed2a3bdacb6fa3fa9484b7b60edeb1d9ef84772e78e39adca14c9fa0bb3ad1f1c17fb9449270e9b4c97b5b320839947fc73853fc58304ee9c9e86f3775f5469554d5006eb7ce9d02d5f900c771806c275ee7022e2b55d111338dd93ad51d14008df4c13d8c03fd9bb3689607e5cbdd499c3a372b487af74cb140f6300cd2dc2acda07277ea3dab57ecf09f1a8f2d6abf7c44fcdaa6dcb1f6e791164004b20b3b4c860f409c1483c7044b6fa445f7224606894e386ba08057a387b48920d4de203b1acc4dbe2b0b4cbdc3f7d7bbb097abbf81e01db09e120eab83def925a059cdb513efe6bc93f0579ebf75638df3c3d7f9eba3c36a169e9d88495c452888853640d93ee70f254f86e2d2d3fbb5e8883b36fbd2da105cf3a75cfe998068203186bb37f1d1ebead8ce1f9383b816f1da2fd0a9e01377b6ebfed4f05bec08b4ff9b90e385736fd13a3af7980c21b0dab58decea8e9545af5d0fb11bb51aeda2c8616960e8f6f84e6c2fc4f50d7e413afe030f75475509fbcf49cbe14445d267994fd3f38f41a1339f2895c0b2969a9bf9c59b85e629486c7bb5107c7a6b069793be7690f7a7c96c93b09a9d610594a156ab27a32d5557a5b1ec8920761cd2f559ad808dff3da64717ea5f10fba87b8ff2712ce322eb3c288939e0007f779a3920f45fdd533369f6f85a8cce21f91552fe03702ef81a926af0e402b418fbb25a6a3dad0ec18ec663126b3f48c341e2725abfeae865352d5ad275a9e3ca20393c64d118968023daac84bdc724a3c522d97a5878ed788cf8e44f80f8803d57584d8c8688cff24dd8c0e881b62d16ea30104d62007a4bec051da7fdc95d1df8556ebdf607383a0825ae503e24661ceb8ba773b793360c3f4ed3b761bd372570cb17e7c2030f07b0b45a7974e45ee6fcf5bd7ae9e9abde5421b42cff6af0c6eb7fc73f4deb67bb4e0b3dc9b4008da30c67071243cda649091a14b89bdacf2ae98dd230e932d9b277d6968c65e0006a8ff63f283f2cd9c21615dfd82e0b24af6ff559c97922a3d112ff0ef4af9d6583bec1f84d1aa8bbae705b9bcf458f5d93059b90fc2217ab27d0072a38aec3229d13266beb3015ac2389a06dec3120c6c04e540886091597919da293a4a8c0812d6cd336d5c5faeb64162ec0459e252d219bed78c4b6bb61c1213939bb3cca12a625ce5a45001d7408f6d40fa9466377caa43afe961b5c1602679220258fae72a8de2ac69c0dc97c90c270e306dbd8eb681ba9c092896b19a8d42665b94ff4d5b8b188f19f7c44abc8f88d4ad7b5df1cce3465de377072c70dd20dbd6779336f05ce328ad741d1e4606dce7065347df111c7d3282c8a3fa4a9458561c04d1056cd53ec5a8ddd6bd4434ac910c69cea0443fd09ee32d1256da44ab7896867a0c97fe4faa4a53b6db5cbfe3812a6667f04cd318f3da127a0dd46170cfbaadfcca863e0d4240ebec1cb2a5952881fe89804892d36dc5bd6484cc78db41bed868ed1b321a680a293bc29c420cffb5305d15fba05c76c2138b986f799b6a3d061658e498204c2b641f2f2ba73d633538eef6b5a01117951eedb7611742c120ff24261bea605e94d21e452ddb9ad27af08ed972b7d5e1eae010ec5d83e4505f6a2b7d9a0bb32a1fbba32a2a8c7823e736a69f516b781fb5354be4b0a67343c009a09b8f656c34ab895f9213531fdeee911d677d1cbc5e72c0fd1ad1f3b4b8bc735e14c3f75f1828ea28c90cda40e0cbdc40dec37031ff3d50305d5a8bba1d53d2f176895e53faa3067129a5c97505799967e55e4e9d87faf5920d71055009fd060ad06691b78583f63881b566d4a06b639c55796b23531ea79c6de24092c0e6fb4d3dc739f6d82ee3ee39f229de4c844aba36432d6119be0d2f02e5f72ef1d95fb2494522a7221e18e92cf22e00010ffd93b89fe60b6895a37fca91aa2fefa8debdae3147fe4f01a6adbfa0a59a5203516b2cc7de5faf821a2e72d43beafa30ac379791ad1e5da3286abecfc7a546b80191b7b892cdd01c25e95506471f5eb74568257439aea03300e80699909cc06db2fd607f3279651f7392f80bf4fc61d66f0dfed7b7db09744139d7374d3cdd18d153dede2a65f26130506acc51d5c721a7989485a145dac9565ef6d3cc938c5a51f31ccc88bb0739920ef8f0a01145f4ddccc74790a22a3099a4b57e31b3a01b4118c9e6c393c1304cc51ca1784db5633eb96ccdc88f8b732815b92c9072dbeb61a2cc1e6b2e7098d883e6174f5af7bd4f129389250926e041ba94d1ac543aab6525f151294060791fd26b668d09302c3482c78e5f3271c0150c437b4e78b1cff6f2b8660dc310965f2df14a1f2ad45cd2759433c4f3952402fefd79fff00dd309c3f09a58600223441c11693cdeeaf0a6100d38d612a759a8e01f753982803af30c7470f7bfd1ccf2c08aa0b187382d25868a9fdf729da10bb0aa0e1cd9c6e695eb2c80c6b6ce62737c3e655246edbce5b8f7ae21c473762db0969dc216a93d4db239f67dea74a1de21d50336793d1ae45e931d975bc706ea718a2ab10d66a59d9d23f76969d870ac279611246ed3aab0f79e11611b312624d78b88a9d1a49dc68d6968f7428c33f0a7a65675826422f7ac058101d2f85663de331345b3a25cf76b7c8fe0988a13278be9599b8e4708526b44a70bc31ac5c278ab739e3e6f0927b72507f34b0034e7fdf43364c466bb75b559e03d4d18c864714eb6061f83a6331b3f59dd62f39bfc2529d5cc68bb6ce63db1075105cbd7d7c4d4ab68c9e65a32092e34e76c3178382a965f49386bd4aae307128242a2ffe3022fd7dc1a824b330b9f032d55573c2f004a6905178a2479ba8a2d5b3140ed5f3e10d986265d8b4cf262295658f301b4d36281611d9c61624928da9abc51ff9a6eb481310511772fcb1c1786203d25295e4a319b9c6d65ccc966b4c5795e6e30b2b3ae8246c38b4a911d1904145de63dbd4470fac47f8ee3eeb3f58b5e665c26a316362382ccc6bf8db7699fa3334cb2ce61c746a7d3af24d8030df6759835f5890b7dd1de538cac1dfe843ad06eba2e887f08d9a49b39246fb26eff5cacc937d63c8d0136f7a8ed2af4cf473f3f0d9064f97fb4fe9938d631f7cea3c617c38771553eddd606ab80bf792f34b44111933796fe1fb8bb104223a4de9e16e17321ea7f8de3306e75a2bc79aa5e9c0ec8dde9b3dd1f2ae42a6a278410afa8fb62c16282f1e3dc1e2f8c28d4538a75b5da7645101253dd43aaa150b273f73e505d490490314606264c737bb344b616a80a4931825043a740ea4f75847e98cc99c6880d3085787903e54c63e90b60f03192234ab20cb41c70c6e82b00e0575a1bb0b0f435831c9ceb9dacd1fab8a7328eb3e28533d5bfbeace430e21758cac204631bf033752f947f78ac2bbd9423c2baf4dea22fcc65c96c332ece9abb20fed504643e82f3ba0fff213635910789a2fe1f2cedef68799fcf4a86d63ab0ccd395d6d4f393f7ee8905eb77df32d97592fb34ac86dcf20cbe5afbf9e9cff37bc34d75af046a09a1781cbf51ee2e0b0f40096d85413a30de974c4d1d16ec06c0fad00716c4e10f8dae46ef3cf27ccde74502b657d3dd26b5481d9787f5c6034083ff88807896da55fd2c951a28f15c8c9e6c86ab50c369e5ba4f6311de505c07c7b85573b5a539785820c672557cee4b58dcda948fb51c95674c23f1275b423ee5bf3a646df19bb5dfa22747857fb5c605669f334d116710bd9f1495e242bf47d6b607c1c9d9c706ee770808484ba552c978ef64daabb642a7caddf5a55facba474b8a63577ac817dc57e48ab072bc6a2cc5f5ae96edc45af41c896cecd8acfc36604db3b7fed9d2d17d429f94bd2542b194a3d3405f46c1021ecf6bb907fdfb4b53fe445d5adb18501aa772c9ba75619214384260306ab68a5ab59161b
+Ciphertext = 66c03198b3422cf3fd8291080f6fb3ebd9ad863e41cdff169becde726946a342ffa0ee547a27bae28cc782d95a90b0a618f717e3beb577354bd91e00a7a57485588265ad2dd0ab946926fea7c754c42751ec7247ee84c17262c0ed092186ec57d6044f0ac9deb21da6714ec7452e441e687e138ff144ea95636286263685419afd35f002830765d810b6f60e8dee0e6879995e9272c798b067d5f99f49e460b86d67c641f48240b61a16dc7cc27b048e8b8e8e80016470ecd2fc4225e29bb127ab48dfe7e7d5a65542176dd7ad40c07ac8b92891d595bbd7afb63fb6f9e1c2aa2fc659aa101f9b6a5c346625acec86fccf17f0d45809f3b9ee81572e5627f1afeed4ba96c6d3ed7e9232358dec01a1231ae7b94ad4675239f3b456adccec439b3cdd45504c5475bbc77dfd242e5e9671d103ba71a4601a7322e0e295357f335fa8d5651d528dda66575d106308338993e615b1c5bd7e95bf3f755ff726b4ac6dd5a43ef061ac9783f8f2804c68f66486f5844969103a36278ee0d10798bf8a802d3fee3a31294bf00ee74f087749ab3325c027d42b55b197469a5312bdc5c9b316b20093154e66605941d58f4db8d46a815c06f209c1dce2363771b5a794dd8d17e93a2fa7b194c6a0b79793c06f002638e5e3052365221232cc4b30adf161cc6e7865cf02911e2ac9b0a75f000e7ef3aa4f3c7438433513da7246d421f208b179763651f18e22a793961e5976a74744696912f22915244fcfbefdc472baee0be1e591d6503f2d9511ee1eededd9f5547c95eb94de134d0c2186109935207a23b2b8420a5858d831ed78202be855cc6b98d6663c1c52e1a0022ed7ebe0eea6b107da4cf50c1c7fced9744a914a66d4604a081587ce4b7e0f96ed408b8a9a2964314b1334a123d5184889958e6467a6d16e7615e5364e09aab75994e2758345511113321a3436db79351c63a282095ec6b99b6d775a5c09ea3f3225716e39e14df260bdefb2ecfe9a65c73ab4b3712ec842e43ccdfb535e3685fa39b4912719e67bbe195e5f0fe6c3aaada2d81b669c4565921f6c183d708b50c3f7172ba841815e9351fe5fbfe2fb1fabeb7cec9bd1dcf2d6332372f1b972b5144aa7ed6c5a985132f9a54469097e2e981b9e75a7df48fa79d0736c6f8a201c7c7d0ac8ac6512a7089514bf58442dbae0529135a7f2455e0ee5716c6610bd7600b3159197bcb20ca055695a36597bf7d3b18ecd08031b4ce3a643951e231c7ad15481e32ed7a3edd2b379c8e96d3288d5b93b562972a04f1b7e0abcc5090cb8655422cf5e9dac0b49678138faec81c78f113255eaa6110e95406a7e7417a6e221a8ec7fb9d55643bd589ace2da70fcb41722e66e0efce932cd7a34218375b6dfa3df1747953b24a41f94e50b84bad4d130d5dab4194665338e06f102f46badc5dad7aa06edb01f8a31244dceebe5e2006d6ab4a31582ff46731b19071c08ad1db79ba018687f3e6afbe703b1de26c11bc8b62fd6b2fa3219fa7190379504820abc97ff6c034f7850e2c7fd335462725db6748fe45920c213c539356b691f22eb490faca24e99f0a044a9f727d0786566ad00635983692ef324bbf1f80c42b269e9d5a8df3249873c51521c81400c729ed7a5e73995928abe94d189cddf2774f1735bc2060bb2240e558699c365dee45fa68801e6a1745e03736ced1b89fc2755565e3b36c2102594d43c451122d94f4a263664bd26b2fb5bc7700319f6b08796864f92d0fdb41710910bbc13aa9cc7baac3b48a24e4f3573f315448c317c149ddb433d9ddd2a2f0cfc81c22d3dab31f184975355b41e4b36fd8f22e8efa01d61a5cbb0e4fcdd273cdf68ac73fee745faff44d44d93c5a111aefe4a5ca8e8e7c075ffdb738cc5b6466dff78ddd837c72c54941707b04d60bc126a3a2fae9540ec2e4672ae13de0d927a7bd363f8abb5a56364d6d564df90a46df9fd59e2c54d5bcb8280415257a6976d8fb24c33330af32600cd1559e0eb05d55b34be456d434bca98252fa531486ce2a24c8bdea1d57d93a550ec586920903a39ca61cbfbce79b8f3a5b1653794872b2c614458177e748f8dfd43840e5bb0d608c26389347673fd0b005f60f52c56731ee5faec6c8d0617fb53d5f2415c2e7906ea0e6d0066354b213b3e94f4dfc311e4ec6afa7e8d1c69a63cccf8326741456a5e0bd0a359b7a37c117f7892969ad7b70cba9bea0a975ada7cf67e0d7255be8d2c6e7b8788b9ff14c5d1449d6173e07b5f9d94560d46f474ab2a67056fe9f4a9fd617a617d23143adb4e7ea35f2d5cc1398fb9ed43ddcd10f28debb27eb13533110005e6c78ca4a874db68c65081ecb8bff1b64eb1e2d7b76a1da3b375dce8a92d32a6277ed847879345717b9649f27e846a701549311c7e69a96d61df616157a114bdf1663ad93a26c28e1a62ee4a7c72bccb9785639eaf1e569decf777bb0548ad9ee36788cfa1150eee3ca3c96f09052ba2300cfb7526b9424b6f7418c27a1e9bc13e4d9868e5c330c051c3885e44714bddf7cb090fbd0f36b826aacbe191dc8c35c219e19fe736198c29dc4fa1a98b5fb1805dc29ecd02f74d4510a3928448b5ee61b5991e46644850a4885bb1ee272883faf27962430de1922d0883e7e80215cf5fe7e8f3fd0e2a49bd50727af793cb7e5b40860e80a1fbb9d5b5696bdf2f741909ab5a713de47716332df6c4f78288edcd6ea130d895fdb2f29f94635bbf2061de55f1801bd6a24294aa199d78021a1ba771c651de4bc08f032fe6ad7a5caf6a6afc6de649b901f783a0ee0fea9b803beeb0f431400d0707f159d7dc29c0c334a918fa08a653137a4a8bc86066c8800e1d171f1dbddf1fab8a3eff6b5023da96f002e7e217e826fa378b15dc8a376db30228f5d6b629f331a162d63e53e5b5bd7ff9ec098b4314285908281930ff0a8aa86a6d89411e6b5bc6b9c9e931623ccca6741fd6d36311e6a8e323a37ad40b7a2797b84694e736d9c135e52d149c760e727598726378cd674b0f4df1c361de0a12a2b8232e611d789bfbea699e8e77b99f3449609caff3d6ef7233df8cfc624376c905eea46c6f77c0b01d288868a19db77e227dbb5bfea5cc3f49d219c7477f7f2b3447b0b8efe08eab8f69579d727555e547c13ec7ae13b83386f2adf634140c311b6e2759cfb9c8aca1c32bb7c002d0f46ecc526916589a29e328ded9679c2163838f071b5b85b35e5e7d99c3c45d25bb9d37d7bafb8350ad4695a6e0cb7ea7d93868c30bb54e301e21147696b7dda156226a5ef8c62121e6b2cad0c4e192116192012468eaad46bea69a140aa3cb9056dec87c911636a1e55695b9e5a27c63cd8c03f31570d4b7507d13731ea31f082b33c6db8dd6e22282f9790be41350a96abfc4dc3de78e0a698930f540dbda3fee923a463a4c4a66bf00bb2cdd6d22b62a47af96b78b1f0f0a174e4ec5b785b3820f47d3c8cc1691d4751ce4e4ab78a4551956158a36717dc35488e890d0631241906db565603205e054815aaaaf17945c3372dfc7193369871e2e88fb84c15a2b9071101e1208177fc18397e6af17b5843e1fa75392d8d3ed214975d50f2b19c24e83f010f8c394ec1edbb1cb912e61627d2760b0e630b986bba2ae113b8f3b51ba00ddc495520274a85e6f6fa7573ac4ec6e2a86a1da9199ceb007aa6f132e5ab8ab8fdca7c829f452ff17524fec475b8f485b29fc6f0d972eea4ce98e242b5d58f6ddc1b3a71256de1c584c9914a3cf1e469f0033165d934fae68a7559011dac7a4e0c72e3b398fab8f8cc2fb67963b0f9220f410e5ba13026a27288a1d49edfaa51e8f220503fb5ec476147cbea975994fffde3ddc51bb189c470078978d238f5287fb2629d23989875d74b006a4122f6a342c996d4a244e8c5e4b804a44c301ac4d6054181a07964b279e0a44c158364395a2ead40053d2f3350ea0529a57552ed835513f533ee0c4b94ef674f31851616a4fa2d0302d13cd4aabf5f96ce28219c0b5bc0e5410fe0fa387ba1009a6f2280f9e7bbe20c33be5eb411a5f6327714b3443b4152cbc54c4012473237dd98b0490fc4228ded74afc81be2a58a22e03ca987faef5310e474f4f5a183f6b7ebede5a8df8a0f94a87a41852826b29466fd761f40b416ad0f263dd34e5497867766a361af1654c3fcd6ee7e6bb3f72d64cc980f04305b63bd574f116d1aa35b4bd642cab0cde6a29139aaa163805c6c40384313d4ec6027c891023083988c1b0d2edbdd9b1afe102fbda285a6f897efff72a0d7fc19a3cb6756cfaa2371e13be3cd167cddb90d525cba7da69608b9995cef92a6424a14df6b860ef0f09830fd7189497a432347680de0f463c0aff82df8098cc4f7753f7680c8c7374d01046b05c63be73f3a1623be778fdb0bdb90d4fb4b458af2890d15f108b0927304c91c8d62cb148c35cc93797db3ef9bba1014d89859a91da0c0a971f330600d71565d30e9c9ea8c07e7f629e1a6d578da04d37e597261cae8ab7d9a952bbf71573f1bf70e064f36c032cc624e3c980e5ea46d36232d61a57fa598347b7fb6b28401e34628b051d6ca3dea190d1d3c343fcc83175f70f77a8fc5e8791b9788989df1e37cc4881648f4fc673772003079adae55c83cf02a894b98561e4a6e4416bea3df18d6f702ad5c4f40faedec6b53cfdb5b3a52d7d43b97ee23ccfa2d30c7264ec555b15f1d9e7e19cd9890a7e8e01ff21d3b8b451e50932f189a420d18e7c7e2f103332c78c84600e5e8fdedd84f055a8b39be9a52782d47c6205c0de41644b09c0931f2da269a7e58e669f3b61ebda28ab8e3f9b83ff3d2bce37864af494860b2f01b000abeb737fbeaf8f9fa6378366606dcd0fc33031b94f9a7a0e562c08ea720a671ff92520047f69b138b4e032c3828874ec4c29e49aab302089956566372b20c0216b601c3958ed9691bbd89f1df45c6613d469e3b9758a70c860fddf768b10a6bf70237a454a2c0b70dd5d02da612a91fc5731513012a4a6fbc16d01550bdfdccaeca22bba104ccf6aeb19f21d4cdd3da231af8ec5bf2a726ee9cc7c85b8ed46d2f6fa4f1b010b2561fb69690d5a9df76d729450a6e139962bdaa2bec0254c5a252b97e7ce7eab1817f454c6121130952b8c40628065dc9b77b0f953552f5aa3ff983b6a51a51dd87c2b51a18e14adb8c80e002d0b47c61cb357babbbe3ed51d371941a8f111837ecf0e45020cb941de170c4a1b5e61bb928b1b11a8d902febd2ba016771f171b8a7ae825fcc4642d95649d53675d0027822e4ff79ffd302bfab1a0ff26f3648c7ab00c10f8d95f21e40ca2b40691bd4be79bb9ccc0bf760a05be4728bbc0a64e585207d1d09393a80d5f574442d6a933966777ab05f699c4e84aabbf753059287e7261d972745906a4fd8967bfc80ae9b6ec2ee1b22a81775f4f24999987365ae2dfb6739902ed51b9a4394fdf29f216c34567102d9db301661b09b728a79e377cf4bdfcf5c83b110a2e267abf6d40947e643ae2ff0c244af168c9f33e7685474ac30611ef95f218e0dd280899a92a41e7a759d03ce3709c2a140ebd35e199f1dbb96f7351cbe1f3de8da8c49758a49b9e724ebd3220ed6f51112944f70c0d1e9178f68a2c9476a913de00abbd1f5bcffa646f926da77a9e9fbdf81cdeaf7f9b13e843afefbca81c93614f8f1675325965b5836b8a77620a5ff162e25366718d8da7781e1a7e01fe2e9e56cf958c6273473abf5c2c8c7fb209307544e1c0726d5571e521621b18b6da3064b473423536b1b76ed75b21b4ee205d7ab5f081bada63062706bd155672dccf84614210d72660095437c6bc2213d9c904a4ba1bfda14d350fa3dce7141e817a50859b1a74aa64560b2ebc67add9f945b6e85577589817078c8ae54a9fc311593d2cbdb6692b089ee6264cebcc7719753f80e30dbe48b64fcfd1037fb9ddab69a5ff9e5898bd8aa947d9ad827c26df67c6786edcacb3478a20bded1ad8c48018ae0d439bb5afad5d39bb8fbaf22d72ffd759c4fa2e94a5a89f41358ebdc4c3aea5110f1965a049fdadff9cf703eabe9628e2680fa4e70320d304ecaed13f513f27220db1916ca1500f1c2e091671fb71329dec0bd6e310c83e67af61b8ab60ee1a8d559a508d174648b1bca451ef0ab0ee2ef74f4fcfaad1cc5ea6cadb8f1bffcb1f2c05122011ebbf6abc16838e452fc47653821589da4cb5bbac10deeea3ba0e0a6241338e64cc78d7a923d018e8b5b51c4442070e5b0e6f1e8c2b83791e930899c5897a602c401c1b85827962ff56d19c06f5af033059bc7fb1bd29b65f66aa5b4397834e846935e523b16438a42c1f990ebe4f83182163ca5fc60a4c6d77fc182e81fcda943a962e9e7f00f6399728b48bbe38d8178fae3582c8d9998e49df5f28e32d541636df3cdc8ac00df45db12da2e5e76f366c1ea8667ba5f3542d21f58ead7c55d06a4b35251b8f77dd34d3de262947379107a06d2f4891ffa0ad3a3e5bb2bbbb978af4953310d4cbe5525ab344ebb98ed24d003600de8f3af36ff3d0a7efeada963845d573685bec2221403b994f97b1e714fd7dccc300b62c2a516e9c6780983062eddde0178e93fcbb2ed4f06f60767356a11d22ca37078fda1ddb3cb907d1020f62ba85d09044574ba28aa3df36988eb8a41e4305e5b0687abe43a90e4f68f0374b6b05049aff5b065d7688cbbfb0e96ab03df38903bfa1c269f43a114085eb4596aec87ced88701b42f0b7426389727308bf10aee9d8f15ebdc411ce1e764a290a12faa2d7c1126dc7b5076f219b826ac8d380b69af7f95d69fc3929a97f5c7da1db6270e9ee1f2a5f7fa3a1b6bfcca00463655121f681d3a627d03efdf0b5fd045fb153bc4488a9a8b7264373c710ebfdb1c267fdca37723b21d5c3eaef48e784bd76e27c133cbc24d114f610c79f2a1f2c30d87ddba395887030b65097ca5566eb0361e70615b46d4b86c2759f1cc2efa3915b4cebdf51a745fb3c6cec69a1fda2ec5e884dce228e30af362815d2d8b59a14f89606bc77439042109369a9648db7d71024ed6df06c8ebd22e8623f48feea77f48b5e88827fafa84b0564151a5997b7f29c4d3d18068e34f2690a293d54003d0ea8f3bab9387ca72212cedb5f4602ad047dbffae2ab3a4cd2865bf896cd96f78b90e4017eb7e3c7092320c0a37f81dd65a5c4817a4e7053e6d2bcb23b11e09f681587f3a9361e974ad54b88c72c296629b1ab754d25be15e87c414cff975fafb3d7cb68167b21f1889685a48966705222b525fa47143b00041df94817c275d93c2550fdd82471cb3cc1b5644338060b767e807bca902c180b3e535c77be2651b3962287b6d1f6403033de4e0aa3a20615ab59d290f4b167325959c1524ef216dda2ffce86b50cb6b56b62a20a043d9d78c704479c22340151df5a1907670f8d4f8c90d93f7b5d94d04a4d383914867aa3c0e5ac85fc299a4d2801a3f80f4b0f046fb62c1c8c539a83b21c7549df0afe200537b52c80ebdbad8a438e430cf876cbbfee9ceb1bc5270577c27d53b40ac153cab377a565b1a9fbdee8bf8e94839c0fc04f7f664383bc90d56ccd1cc01b465c250b158b5e6f321c20db245602d10aab80c553d52f17282b095b5e2234c6c689a84b096112100359816cef7e92029fdfc048058f847cd2f2369ceec9fd171a0487bd7acfed6b0319832df6d59affbfd460ce8d12e4171da0f094e872a2888fe74925c5ef0621c4edad337f7006086748913b24d4d48ce36e662fefbe672b6d476456b1fbac6d80030ab93da93acb4a7e10f955547e7e20a0abcdbf909f05a2ee2e0b7485fa16be652b9d9fbfbf01f082488a81022bdb69af9e6fbe753e9eb92a1762afbb4df49f83ffc0cf03db563aa96fc5ba1af6d4d7eede6067749e8ecec79b63e09742e29e99e1c960dfb0688b0222c49ed919379ac66e3fa1c72645122d1664721e78fefdd1224c0b886f6e214e37d268ca9acab76ab3adc9f5549e5dcdbb3d31ac34ac472894d004eed71f88ca2377fcfa48d3ae43805dc612891dadd06c263ed8617194f890bcbb964f010d277ddce1f6682e661577ecd51a4d5421f00935a5b24fef0ea1809fa5c4fe9cf8c453046f61136ec8872915d2462157d73a205d56d77bb83cf16b88cadf6430c0e5397fae1f91a6a11b177bf04b065a2e55df81d5c086ec8dc8a0a660eed37d41fe4d8b3e3f22238e2a63b6e4feee1fe9a140ed37b2be4193f75c2d038aac7f6b7dad2a3b37e5b9b660615ec1db77a9b7ab416f43e66c872b71cb67c9245c757dc87723ab3b9544fdd8a16c9486e8ec3c4a44cefd98535d6e5683426c1cc8c888b8e0c2e7528bd7eb89b80d9e00969efd2f0a0fb09845426edf0d1d9a0809648e7e46ea0a8c9988bf9df475be12a72c7326c1f2bf01afafb190cf6f649133c7dc14ecf9b8c971135bd303c8894bac637e08257d45e1b68edf550d896c41682c002396e8f1eb7c1e2f4e0ed9b8b7010fc7847e6fb1c5907c17b2d2b7cd24c96f47406bd04cfcb2099d82dc2902d6f91e2f8f3a05bc62019af536309e7847fc06c10dbf7272a1509079fd16bb16a85ae2e078f97f9ce66bba66d6329c7ee70f9688f6d91aa38b25c7f4884658a72ad8cbf96d7d7a9652673273ee1b3d4d17780dfe9ca865416e318bdcbe9efd8e071fcb15ceb0743df5af4f7d598b31e38677e65af61c1109fdbb11fb11e3952e6c3ae8abc3f894ccdf205ae55dafce1dd05dca6b899877f57d712223dde4e7fdec7e0ed4f0a29ad359e318eb36ddb42fb205adca400f5b2615947c4f0ede95788093a1152d88acbbbb272750823151e245354e658452a95f21fef05bbfd98a10c1c975ad1a08c59fa3efa9fc73588407a83d0b26a53f1b4115f83780bc70ee2619d7374ca45b9e200055df1b93977e17aca89a009110a6e74caec7f86114f91975bc6e8bcdc7267ed2920cf12cd7137840628e1b8a0ea181dfef18dc5f74e752f842ea91bdce4b420ee709bca72c4514e92bcff55902e5529d77fd95f5837c8f4fffce80c813630550a0dde24092a25f65eba90790a06f4d4c3e739aaa8194a147fb32e81c71d3e8def79251c33637661b0a621a2a6b302dea00d34a9dbe9b621c1dabd0464e85241aa6712d90b4287cb23c17bf1e4d0e6dbed372e6b49c4a843305b3b0e5cab0b0964a93ad0bbc99ee711afa7f2d0a296a375fdb3176c65a957ddd9b88e9d57df736acdeb02a71b924cc2e972f51ba68a597215678573bede9ca5b3a0a2461b2d3b9ea57a5af8c91d40779bf917ded32f14a66d96e28e1415fea1e9306654c6b84d8a64243a5271c1f11590423c718961aecf5f659b49f67efa78e02ef2524d0966ebcc446d73d49ab7ec31f0c009069d14ccd63f926169291b83a3e37610054b0b964741e2ed8771d20bfa225eac0280b4d5af0c09d3218bd497a035536f5af0816884d606f1a872b8161a266466b56e0be8b80a7bde65ac706eea8cacf1749e5e71ff9fa3e69ce878427a0728d44e666eff977026abfe18cf3ad156a943b917e72ad65725a9a8d60b7b5740494fa63143a7f2a94fe6d8b319be55d6fe1a988244deb798f345f30dcafdb6af9e9cee9e35733274bdf3896750897371563ed2516c4ca6c3c3c994b48cc94b67e8129d234a0e19dabe39e500214c0ed5f0e5d61b2f58d7355d147102d93b2689bc5185dd4c0a18efd11a307b887d4d0fa84fd992731b3a80dbd027dd36cd6933766c537e8e9e27d35d5187e8276b0f59fbe7b6d629d3416b782e7981d85e1e890853c3aa94a93c1667a55044ae42badefab979fe7d525c6a180307c5ee3a9c3933038028c3e1d15d1e78fbf53b6ea61ac5e02db0161719398a31570c55f73cb47ddec8f99e3e14af5adb8d5cd179f4204d080331e75bd391b19d38eb81f148c36af3e8a3ebe76209bb75c9741a89b5d0708bb0fbb0945fc6fcd6ce142d19faf0947c338dbc8d976963281866b5216421c00cbd77c0907d1e16f5e925319cf6c62f8c6e8eff0c2f831c504e7a1c0df09a54e2af708ceef39ed7d0f63d83429e9b0920c03cf85c2244f2fbac3958847113bed577dbde8992cd91be5833c75faedd5e2005d4f7b66fab8fa9305927406f863d1795dfe04028940b765bd79de6972dc7094fe1c2503a73d7b50208835216c23aab3e47094587549fdd74bb50ae21cd1354daab632fd0907e63f4c2b2d39d7fdc4fc216bfa742b4608238623cb7fa01bd851c1e7ad5ef5215173a71f363fbb7dae8092486f4a1549e32ae53b14c1343ff7fb5e2b1487d9c594a1b56e22625d275e41535534d225b7b2c9deeb0d30dba7188cf75d680d4545ed05044a0661c690a37fa14a73ba8c68357e2c948e290b5d9a4b51822824614ef2938d19ea4b650041f59f3b548f0a305b86f55e69760f37f09dfdad62651aa5fd84eef28a4431136b34a49c9bf1f2891364f86b0aae70b0414e821e3db1533b0f1db5fd232308bf118f858aab5ae974c10583f61b283a3870eb82aaa8ea3c4e2ee3c3a3d7169aa8e975ddee7f620f6c5bcf3eaaef0101b62cd54495cb8809052c9e3151690cff7c1efcc4f63b22472111a7c5d9d7d2a2be951510f60dec8c426f14700c8630f8a14dfd359addf5d9b7ae031a745ecb4e17321b385799c90f924c4780287ac187530a40b064064b9036cc46e3f87c4d23aeeed1bc22a5411c7c503594d5d1261eb9fc4da242493beee9f671485a978a32e965faf9b0e2c13f78e31e1630b72d35b4be691e90b3798e18223c1b514b39a8e1eeb7897c22fdee1e33fc76e2b2f9298ad4fd89f44163aaab23d754d98c7890e58708b81b3832aee31aeca85e76416133710aeba0e5d9f17695e607d09ae3f94be191553bc39c6df03cefb4ee05516fc02d66c9866e4eb0d89a662e309379a347159db2e070abceee226f2b8b62847ef7c51d69c5f12eb567fa13af4b4f90b3f3d9d4b6a3f68bc4dd77075081e2e99833c18b154d0d6ac360141de2a25af61d551f10a34e03e1419a37409b4c177c51a8d248157b411868eb607c34d2daaa453a0954fade5eac45d5f21f50efba8bbc9c87ff0435c70f064b42cb2d158384fe0a4d9c90030ace7723af0a6c8faecd8f97f9850e2a489a94ebcc655301e2e14711de9eb08726638a9ddb57160c5545c152a26860a17dd18172bfac138a300f60431fc49eff18c93f71400e887f878f4dd637cf5df8c1e2b12c0f87e31ba2754ac1748479eda0c4184b528554106128320dcce349939e5e6cd3434f86dc7adfee28c008a21ddf9d0dbc87ceb14cc3afbef1e06fb3f9908a4b14f5e6c43b23ba783b75a6cbfa2ebac6533661b8c1143a34e8e2a9723389c4b7087dc07701c53b169894551084aedbb423bcce2f470881fdc7240c26b3b76fd6cfeebf8eb2828b4741e5e8698b19fa0a44703cb4e4c8ed6a7e4d6063f5fab724e08a159f4f04a2f351dcfb6335ae6697dbeca25c76b55e6ec9045eaaa8706902df492b8c8cfbf68c4cc1be5d1e5a173262e38bde051656ea85ffe35d97f1b25f6a47381bc327a946f7cbf6210adfd957b2921
+AAD = 85ddde4720659e80e25168585a354eb1e021c0b5d2ee289f2314dd5aae52bdf1fd44755bb56a6e659111a1d4b4da73315bde01c7d2c15a4f7114aefd68c141049fac27acfdca24e65c51fb1c27d307cd948e13af2963166bbc9411401d124f1ddf20f890db5611385257f52aa05c09b467e3ae886decf5744ec3749e5879f2a60017f601bbee11a66604d5f3d521d2c48cea1794f77366f29c7bd12a8aa51d34a4f3fb52809561b527016bc6badf9d136156c330e1d69d1aab98c7caa9cb46e782a898b4c66e4ee3e2445fbfacaadf9a8f73c4cbcb2a1ceb604ba5637b51337fcbe0fc366da98e805ceeb29feaf05420113b16e1005079c0e88af33f5970b3d7a8b51d0d9f5120a0795063db508171b75ed07705ac6d6bfe4ecc59243091d48865536515e036860affa880bfc91aae2fd1700de15994792aefc4a176e5d49d0f9135c7d670f3cb8798bfbe83fe73de7427e0f3e6a2df561cfa15ffe6ae80d5016096c8875b0beac8cee8fb530fb421b9a8ada4d551a528d0a0b521086f5a2db371a3bf12a2ef861f831fcb44cb2baede907a9306d3e5a3af796e0a50ba2c8dd61fb03727df5f0654d837dabee2fd90eecb7b2e8f303b0d57f97dc6a52d8281574d8457c89c6a9f5d80e0bd86c90ed39b1db4253affee614e8cf1ff05166c66e7d2a2aa2fe8a81c4741339683debe189c126e7f553a5f2dc16fc16672f74aebf94c7e3041c758fbc6d0c7f71c192cfd0fb2ec52d0a0705b05815d567f3d19f9b5d553a2adce9a79159b0e38980851bf64e97f896c028a6df8363cf1f13f4654265a7b0c0b24198efcf4418c32772bafd3980dbc689fab12e85b3ef4a491e2e5ffaa2fadaaf3deb392105a42380797d3b41ef61303a6016b269ec9a9f6e3f26070ff33cb467435ecb325dc7e18728a5c2e882e720c8f876fef10f5bffd5a925cdc9689d934272019e90e3a3bbf63a295f207faa5c014e1517c7d5c18c3ed70e92304d51944dcd3604c999d4aa8d8dbf2a4c69cbbc08635c968a20dcb80f438d43c57851c4cafec0b9568dd6c19932fd3f1294afd16f019f20e40ec87f6f5dffc7717470614b2de6e9000969e6b7e561cf91c06dd379a09c6c25c7841330dc78fc5be1d9b86581a81f55c0289531128638441fc98a1ad9472d74e2be2f874aff2fcf9c941502f59f716185a4c39289ca368c6dbf5257b5dc5e57a420792c26e602e4ecbc4f17c8787004eb88ea091d6b6ddc3c85dc110b5d1f46f6e1d872723176f4c73664ecb4219258fedce19ae22360354fa4894fe51d69434c2e58e1ec665b5cc33bb295053c591b474b6ae178c8834667bef971604279440170ebf3e739a4ff19704e5886767f81edce95a3dd93d1147995e7eb6c794b7be136658ed23cec7c374705ec0d8479dfb44cc7213076668e5fbe6a508537a9157815c6e5187b89f
+Tag = 469e3ef168a64945f76d7a2013f27b68
+
+Cipher = AES-256-GCM
+Key = 0000000000000000000000000000000000000000000000000000000000000000
+IV = 000000000000000000000000
+Plaintext =
+Ciphertext =
+AAD =
+Tag = 530f8afbc74536b9a963b4f1c4cb738b
+
+Cipher = AES-256-GCM
+Key = 0000000000000000000000000000000000000000000000000000000000000000
+IV = 000000000000000000000000
+Plaintext = 00000000000000000000000000000000
+Ciphertext = cea7403d4d606b6e074ec5d3baf39d18
+AAD =
+Tag = d0d1c8a799996bf0265b98b5d48ab919
+
+Cipher = AES-256-GCM
+Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+IV = cafebabefacedbaddecaf888
+Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255
+Ciphertext = 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad
+AAD =
+Tag = b094dac5d93471bdec1a502270e3cc6c
+
+Cipher = AES-256-GCM
+Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+IV = cafebabefacedbaddecaf888
+Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+Ciphertext = 522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662
+AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2
+Tag = 76fc6ece0f4e1768cddf8853bb2d551b
+
+Cipher = AES-256-GCM
+Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+IV = cafebabefacedbad
+Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+Ciphertext = c3762df1ca787d32ae47c13bf19844cbaf1ae14d0b976afac52ff7d79bba9de0feb582d33934a4f0954cc2363bc73f7862ac430e64abe499f47c9b1f
+AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2
+Tag = 3a337dbf46a792c45e454913fe2ea8f2
+
+Cipher = AES-256-GCM
+Key = feffe9928665731c6d6a8f9467308308feffe9928665731c6d6a8f9467308308
+IV = 9313225df88406e555909c5aff5269aa6a7a9538534f7da1e4c303d2a318a728c3c0c95156809539fcf0e2429a6b525416aedbf5a0de6a57a637b39b
+Plaintext = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b39
+Ciphertext = 5a8def2f0c9e53f1f75d7853659e2a20eeb2b22aafde6419a058ab4f6f746bf40fc0c3b780f244452da3ebf1c5d82cdea2418997200ef82e44ae7e3f
+AAD = feedfacedeadbeeffeedfacedeadbeefabaddad2
+Tag = a44a8266ee1c8eb0c8b5d4cf5ae9f19a
+
+# local add-ons, primarily streaming ghash tests
+# 128 bytes aad
+Cipher = AES-128-GCM
+Key = 00000000000000000000000000000000
+IV = 000000000000000000000000
+Plaintext =
+Ciphertext =
+AAD = d9313225f88406e5a55909c5aff5269a86a7a9531534f7da2e4c303d8a318a721c3c0c95956809532fcf0e2449a6b525b16aedf5aa0de657ba637b391aafd255522dc1f099567d07f47f37a32a84427d643a8cdcbfe5c0c97598a2bd2555d1aa8cb08e48590dbb3da7b08b1056828838c5f61e6393ba7a0abcc9f662898015ad
+Tag = 5fea793a2d6f974d37e68e0cb8ff9492
+
+# 48 bytes plaintext
+Cipher = AES-128-GCM
+Key = 00000000000000000000000000000000
+IV = 000000000000000000000000
+Plaintext = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+Ciphertext = 0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0
+AAD =
+Tag = 9dd0a376b08e40eb00c35f29f9ea61a4
+
+# 80 bytes plaintext
+Cipher = AES-128-GCM
+Key = 00000000000000000000000000000000
+IV = 000000000000000000000000
+Plaintext = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+Ciphertext = 0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85a8ee35616f7124a9d5270291
+AAD =
+Tag = 98885a3a22bd4742fe7b72172193b163
+
+# 128 bytes plaintext
+Cipher = AES-128-GCM
+Key = 00000000000000000000000000000000
+IV = 000000000000000000000000
+Plaintext = 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+Ciphertext = 0388dace60b6a392f328c2b971b2fe78f795aaab494b5923f7fd89ff948bc1e0200211214e7394da2089b6acd093abe0c94da219118e297d7b7ebcbcc9c388f28ade7d85a8ee35616f7124a9d527029195b84d1b96c690ff2f2de30bf2ec89e00253786e126504f0dab90c48a30321de3345e6b0461e7c9e6c6b7afedde83f40
+AAD =
+Tag = cac45f60e31efd3b5a43b98a22ce1aa1
+
+# 192 bytes plaintext, iv is chosen so that initial counter LSB is 0xFF
+Cipher = AES-128-GCM
+Key = 00000000000000000000000000000000
+IV = ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+Plaintext = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+Ciphertext = 56b3373ca9ef6e4a2b64fe1e9a17b61425f10d47a75a5fce13efc6bc784af24f4141bdd48cf7c770887afd573cca5418a9aeffcd7c5ceddfc6a78397b9a85b499da558257267caab2ad0b23ca476a53cb17fb41c4b8b475cb4f3f7165094c229c9e8c4dc0a2a5ff1903e501511221376a1cdb8364c5061a20cae74bc4acd76ceb0abc9fd3217ef9f8c90be402ddf6d8697f4f880dff15bfb7a6b28241ec8fe183c2d59e3f9dfff653c7126f0acb9e64211f42bae12af462b1070bef1ab5e3606
+AAD =
+Tag = 566f8ef683078bfdeeffa869d751a017
+
+# 288 bytes plaintext, iv is chosen so that initial counter LSB is 0xFF
+Cipher = AES-128-GCM
+Key = 00000000000000000000000000000000
+IV = ffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+Plaintext = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+Ciphertext = 56b3373ca9ef6e4a2b64fe1e9a17b61425f10d47a75a5fce13efc6bc784af24f4141bdd48cf7c770887afd573cca5418a9aeffcd7c5ceddfc6a78397b9a85b499da558257267caab2ad0b23ca476a53cb17fb41c4b8b475cb4f3f7165094c229c9e8c4dc0a2a5ff1903e501511221376a1cdb8364c5061a20cae74bc4acd76ceb0abc9fd3217ef9f8c90be402ddf6d8697f4f880dff15bfb7a6b28241ec8fe183c2d59e3f9dfff653c7126f0acb9e64211f42bae12af462b1070bef1ab5e3606872ca10dee15b3249b1a1b958f23134c4bccb7d03200bce420a2f8eb66dcf3644d1423c1b5699003c13ecef4bf38a3b60eedc34033bac1902783dc6d89e2e774188a439c7ebcc0672dbda4ddcfb2794613b0be41315ef778708a70ee7d75165c
+AAD =
+Tag = 8b307f6b33286d0ab026a9ed3fe1e85f
+
+# 80 bytes plaintext, submitted by Intel
+Cipher = AES-128-GCM
+Key = 843ffcf5d2b72694d19ed01d01249412
+IV = dbcca32ebf9b804617c3aa9e
+Plaintext = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f
+Ciphertext = 6268c6fa2a80b2d137467f092f657ac04d89be2beaa623d61b5a868c8f03ff95d3dcee23ad2f1ab3a6c80eaf4b140eb05de3457f0fbc111a6b43d0763aa422a3013cf1dc37fe417d1fbfc449b75d4cc5
+AAD = 00000000000000000000000000000000101112131415161718191a1b1c1d1e1f
+Tag = 3b629ccfbc1119b7319e1dce2cd6fd6d
+
+Cipher = AES-128-GCM
+Key = 31323334353637383930313233343536
+IV = 31323334353637383930313233343536
+Plaintext = 48656c6c6f2c20576f726c64
+Ciphertext = cec189d0e8419b90fb16d555
+Tag = 32893832a8d609224d77c2e56a922282
+AAD =
+
+Cipher = AES-256-GCM
+Key = 53a6f0d9b8a81818f2fd7525acd65acbaac82684cda4fd357b1ceb6146b31ee4
+IV = 05d8a92b5a510c3a3dacbbc0
+Plaintext = ac0ae17d3d0ee5935e18675c36d9e43967f6da38dddec14c7ec574ff8473e11ae5019e638232323c175b7672a7462df6709f5014bbe12a1370a1ffb570177927106f995dc8f35bd6e6228de7c16acb71e583c87477dcc7b17a908ce01543496c2cab8a14a21c43b18fab52d8a882dd1d999b4275db34c7f32bcba624d128580d7566a2da4bcfcc4136d58816c437d21e90456fc86381b946b8955f0448e83564165a629cb2edb978e5941010ee9153b054ee429b315058334ad7899aacedbc0bf423de69f57c633b56033c6531dde29258694045c46a797987471ae6af8fee8ad0c1be4149605064aaebafd1c5592e61beca9b5c7771410a276c3ae517490735ddd6af499ff705b9fa68d50650e60c19f5ae2c88dbb6d612afc7be28a5f55556a2163b6f66609f7d9ba7e97c074ea39a618727421fbfbb6453ffeefa643decf11404764515d28fce8ba66b8c85d077c47a54125a38bcb6b0adf6d248ba0a9ea129c887c66ef537c45e9fd3c17ce352e3936cf139e13a5946a7dc9dcb6423ca6a051bf560cfc572ef366940e71c81aa302cb9701f9a5206e9eacfe9835bdacb6425d058022a27fe73e5edeeba98c7a3edb761578ab2ad5a442c2dc1cb3c143c6f18dbe525fedd2a9cee0ada3b2c116465c5cca9a7e5d4374b29aa4ad8adaff8d6b0d1ac3990685240ce022faaa07241f9ff445566b9e0463350792cadcafd5fdf5c37706c0025b3c627185b356d39dcb2244b15566e6e3f8942f730fd6d855daa1456fe294f9156c4b5131e5bde7f2d938ceb6c7f5deb0f847a98b7fd11a3f5d0163eef9bbeb83cfc96dd8eedd447901ff4d3a35c0ea1f691b01385eb39fd265f756bbd77bb61b1741db0502947b4b985382a08a5916da809a8afd3fb1d78d9e16f8e37f51aba100d031d9da8613e9cd2cc621025b47150b3e76775ab23412d74334bcd79746cf601407481310a923047ac68a4e6a7f7b96bcd85bb6f24e38f03c80ad41a0a581b4246ea4715ee561cdc5384a51a6fc9ed8569ba6b12bcd95e6202ecf834dd9062ec539cc8cc4ed64ab9ff85998da0e63161e7391b14de47dfde41523b6c614618bf2fd1edd68a5de1c03c4181569b6c361d955c637abbf4efdb5dbf2f0dd2544329c44b77081a48f53231fa9d4cf6f2186427e469d0cfbcd698f7e7cf773240dd2b807a2fe699f0ceb4a2339e9cde01114b2aa5c3591a82a3a27b308e1e7f092af8ad97bbe7b28d78ecd80c0c0a28372193d66bdbadc0b58e4d5408acace53bd5e12101fcb25754f8c545340fbbd1328287044a29d18f40a24b4084febebe228b67cefd970df6d44ffdc033a50534e5977bda660c589c6e3c3a28b4c500b29ff4a1c3eaefb068784a29914ecab7868a43999833b0b37ae79afe58875a0425262e0ec7e10ee8a6bc1c97d332bc2a6195de239a166486a3c1ad8de3a026e5b1757f9a778a511024a260c9809ae3b22d78f18ac483281a796b1ccbfe7a9b9f357d12d340e20bdf2037e8bb91ef858cdf2eb9d7161a756d8c244c55524f8f5be2e4f18641bc4c2409c14816846c4655be716276d8356e516640da49e8412fcfc7ac0e084a079129b23e54952d8030e1f8ceaafcd322dfb4bd189bb5d940ac83231de0585783387d0642a245183f7a251779bdb12c63e9edbf3d0c94281140598fea9e73e951ce650c984cfb1398f8813abf8f8827af5eb64a65dfd1305bccc45086438ac439a9265790fb225c509ce3c9d39e25d2276d7f3c06d7cc28d33b2c21bb38b50dca5b10afc09da83ba12ee878e0f6054e8d3e78d731671de4f9d5a7b97298b01f37c7e78e5fcf5188554bcf5d42559d3b15153bb3cd5a0d1cc4a96d02ae8b1b115d1ff617b6ad894ce0585f46a2a5f4cc1b83065c1d7b5d2f25f3f4bf9966b4c7d7156931861d5edd199c126f1ee4ff6345023419d0a4c87f3388fcfbecbb6c1e2f4745922b88085d21d4551e4c127eb423db87a51c9f9a140f8a7415dbd70c4b0173e687a40f895404f2203e14ccd61e0e5b0d5aa3fbd1c8affb5807d787d840916ece24c56c50d3d9ed9f19d73f2c80c461b5b3c07dedcdb41402c3826a958d74be48382dc741dcf3e0eb8955397da33941fc47288147736d778914a57effbafccd4cf293e6ed1c7d19b55433bc0363e41546b3638a4c630eb35dc6a074f90185cb9daaa6eab54825a4daf76f49ad918e90e5777a826d6d5d52f32f7ceaf818f87251ab4d1b5406ae94e41cc97fe022b144f26335829d9c81725b3daead621a0df71313d18214ff8dc687a7ab86b8eec3070ee1ca9f62005a0cc15ca6e2f4fd893de8fd91f6210f6c96a576024678535c962a2dab06f56be377dfa74bca089adb7327abd05c3ad7646b5e9e6fc2f29916b34c8642f3c0caedb53b8f30c2a77d1757103b7ed156cdc703911366b02cde87ce7343886987f7a8c028921a7b87c5c0aca7ada34970a6d0d32eb1b177ed8e64c1fc6839b9d08acec19560bf4a815ca6187635f0cabb8bf062e8216d3b09b7abd99e956734129e16a7c4f3beb850fe2b1548729355f9015c9bba336d3e26a27b3d75d75722f7a8170d15ebf77f325c97778a5a9d7c76d3e101eeae354e54e6fa60b58cbdd900751854ede326b58fa5caca073c630f3719d6f52afe675f10d464e8b58e5fde75a4f225063ca48d76efd1b645e4bc89d98215beae765601f635a3bc8cfc08d74722f3d95ccb4cb4e3ea977d0c534a4abb866fb9a31771222cfd998231c30bd16b6844ef71038b67d72c910cca40db7260dff0b74162449a9e2cf15d7dfbfb3a685080e6c83ff4341c95819c0317502ed49af7ae688b52c9866518f74d69b4144500ab9d5a0829b9287d5fb67b78801119ddae7a76e80be8c4dbcec7866ffa7d081406e51cf617be061530b539cca7e1ef9118cc06e8eb2a01425b45947a1d2332e360acd0654bba8f1fa43ece68467690d36f6802a32f03f9ea056e57fd548dd4a3225ad5006c6c931aef1990639498dc88a23895ff1f75520a8009dbde4debc20ecc546e378eb7ed5ea3740d2244036588471d96e4751390b6b76b39816d853944cb5677b493b36de9736ba0fa404ad4b3a7d7c54d0c15072c040064b871401b25b88559d059a9519c7e2446b0d110a4aba9c12555e5f620680d1fea2359bc85cd15b5c0bfd6b3715d647514118cd60483dbc9c83e285192108f4ea6bcbee1f0935044610c68d052ccaba23258d09465d5521e2664d59358621ebbb8f28a4627362c8397f0a9852e5d8daf53a961d4ee66299e2b54d8adf5134ceedef57011f810aea76262422236c3e1a478a759584c7880fb3f32389c4bd4b637caad7b2bd6fd295aefb150754799434e99e0fd45c1cc4698ab14d1f63eeb06e53797cbdddd45e7f87e85b45a3dd0df6335c3b1addee87ba953bde29ed98042d745c1465a967ef922993798966e1c8b96ad6f68404136be0caa2264e24d8d93aa1b99da9316c7780904753d4e0b45cf282b43a0c91bc9ff83cb25cacea2ea72563b2e759b69cabbb6a50d6a0a5ba545622e5ce576cc301ba35afadbfd1e26668782e1d741feed8aae894b564a425141442fb8470b325cf7c8e1552973463bf4e67a2ad58d15417e418bb91d2df4b1310a0a70ac744bbb4245efd2ae642609079a44cbf6be19809a5ff7ad6847432368c9749cfb336ddcc0e6f52a699b910cd24671f38af5dc39268a3c87771f07d53bf220b7c2d5058cc7b0bcd492abfedf9bb295ec304107130f0e98dacaac6dab998b511f176d48daeb81db53643ad194690b6e28c5ed2927e09a1e959c494b90db401681f67bf1e23fe9ef4c903f666ef39332a91a25c63efe9bc518e9aff61842007dda72dcc0264aa47543c0a8b1f0d25749ddfbed487282241140d4c64def1831c4d75ca975fdb03258ddd013445e08bfb479a516b011fe3a12e4bfca439407c0022889e46914cd41a4d92a25eaa57a55bc7337e5fbbd11584dca34adb5643105c8171e53cf04b1412c3107e72330ebf1b52f524b4e72570cfdc0ab179991f3782d05091ea57b1a233048bf062e88939cfeefb61e8beaa90395faf61c4d974b23723a4a5cd39d70f92620f8f4f27bc99ca67bed7fb6e594913991ca3025480ad791bc94a0def36fca491a206440ec31e32bb85850c3606c875708309be63c2b4f5c477521aa08e1d059cedaafe4fbef5523b79f88b57d0c81bbdd09202095f10f13e2609e833ff41b862b2214c22e8f2b04a363b38d26bf95c07b184b9f909ad3a92122e158d3566d2204b22d4f2f3ce11a65544ccecb01a4a5ef62bc969fddcb648224a5c7bd94f8da9a7d4df393d880f537a377888874c19dad357a0564d303a5c1485c1451ea55d68779dc0c11c7c38025660684ba3f70cbbab00d15b34c0f2342207ad548eacb32ebad95292e85211a8669b586d05b0d0b9f278a35ea4d78e97fd5dafca6b72d8e1fbf3e704a60a8ec60befe2e3e4d3d37f9d33a0feb88add59f0171ddeba0b79a52feb9a1f4a7a6ee7c6927bd10968fba788a807409346a0fccd4f7daac3c8591fc689aed881829d479e8d360cdb5819d5eac718a6f860f2d9ef6a0d36ef6e10efbb37819bb7b03ab7649173447b2cd47f3433a2422b1611dff91cee0b10c6d060d4e84a9e3f4dc194514cb67f1e3985be05c845fc92b41955d0f61aeba6268789998bbf341a8b37af48f07b13a676a11d27330529cabcd52365842be559857cbc2a63a4ea1c77fa8619040e79705c5b51f473e13b73fc09c28598e070dbbb63ce884c2843ec365d4c5bebbf815ee3314dde0bab6b0a71a398e2d9ee8ba2f832863fae7eb0c18adcdd17f1dee0df29a8409acabf516c8e6dfea5a264c1c6657f774c86a14cf96eecac18a41b1650a9e652c6c9264b03aa2fd30e333a9f24cd6b0313358e3c00943a1de63ca970b7da2cb8a0fd1109cefbf12176f5dfb59457480428b194e88449bffd8b8d87d05d30f9ffe9ac3a7442b0df3418acf9165b14242489a54b6b47ea543fed5de74a00f61ab2af553b60d8d21c76c42052c72e4841bd94cf88185c39287c04d05f6336ae581cf7528a59b2874795caca79f5600ac64ad5820a91c711ae5a1c3762028242c5c8a9aae89177ec4db5785cd07402d45805a2e2e970059e4e6483074df1bcc01f57470fb66f45ab475ebb5343b727168e355a6c25d42384e39802d7b4a8c54ac94d82de12f8de13630ec8c19f008f98c505dbbfb21b363472e23d0147d1ac555f0981e2bfd07c62d097acf930094dcf239a40699421b207ac2575b7edf9b1d772ab066362820c182c2c5097a47d1dd25ca9e0dd9c3ae94e9a8f0dece74cdeeec3a17803d5e11f037820ea20364234079286a7c291f3424292b0eec3e956513cc6b078a76a3b8ab42c5fb5efdcea1d438f7ae08507275b48f9588a15be763ad094885269efa7330f6fc9d4746997c98d9f5feeb6dff2734d75afc6a11196b35bb9fd0c0af428cacef0df2c5ad4e5fb4559f0f93af2fafad6fb77f453238f409ec71a912350d7b62952e4858927f620d31569242615345265ff1cbbd7fdfaff35a45732628da663bfff3d3af3d7b537337754554458a2d1af0e16aa8ad9436096f42e243109cad32fac1adc58d714cd3d0d8483c783006991f3da263ef5ae1ff2ea06584e45849d64a07170675c29f0b2abcf1eedbb63b6f5d9dba600996c7d5edce9ac69448d05c0704fb9f84e831b60c376b8a5d33ea22030e2dd3dd421d8e0a810a77c085a3861fcba214a8baf592d624d673fb34f906581d923d80b06186db8ce5fbef2bb750166f7556adfe93d4951a825d55b0bf92c9f25776df784f6aec808ae221cc98d05ce988fe6a13ff96083dba15500e149409b54345274e3633fa8f6685d6fed40c20a5c5705f8b37099a5949846ca15def5a6a427eb4eec72747f116366adcb9b74d3de0b125bdee23ca98ee6312f41fa3d9bba43a8d343552c969c41f766ab4341a42ec4cd6f4d1d4c4b1f16979e5389fea36a150580418d95520506fe0cb1a1d861e09d21c57d88c46e10a3c5ad1aedc8f2743f5c06f10d6da9b2bb3ec783c6f5788ce9400795022cdcec197f9dd3ee4cd26531e7f057b6d9418a0c52ecdb35a24a2a079b3d396017feca8b31aa55e3d5ef79c9ea9ccc7e3d0b47f28f273276666fa1763b3a452672fedc94557d984c3353344a8bc9fc833dee685e33d63540d0801d8068cf66cc48ddcb0d42cec881eae36fc2614f96ad67fceb5c98ec33fbade0e3049178d503c13c2d5d71f32f4582d1cb0f47a2ace578b903796768a906998bed2995798251d7eb92faacc19255bf12c0024a94971c185841113faa288beb7e58d4a98289630fb3d230f936eb1b9d9c7b94b5ac9d3a211c0b454a26e29bdffb522548a65e8dde3730918fdf0575245e71ba013ce08f6e698342a61a81b1355d2483e97c06462cae1cdc7787f4bcee4396a08dac9c14981f2a8f4614a31b019c83782d5d8370acf9db467d9d95e8efbe44274fefde5860c2333cf81593a2ada9f5bb6c2362ba97fd7c3e5bc836c327c66b57c0f023efc0c0ff6feae0e625df2f4e21057060170c844c86412700d7d337b1f7835a0dafee5206cbd76104c5a36623c7783213f8dd457b5e69a86b74030a27b3c30074242b1d97e65a233885a681ec5a8532bce9dca1998dc32c6b40dd997b99a6ed6288e0b9b09447e356bc5345b2133571e65d47db2c736a391970879103d4137cab6c0724b8e67064167cd5521f32135fb6ca43c1e118adcded8227c9dbfdc18cdce154108eba5d8c60e5362e8fffc5c9ae6ac2572188617e4ce0f432e2476c74a4227af64b58e0ebafaf0b1ce01723ecd36a2a4167b7991e28b6a9e81992fcaf7b4b906d0361add02104db83914f28baea26b50561faa46293ba5247e8263ac0347509c36405747866d2fa2beef44f366108f6a4047e282a477c28654511075ddfaad9b9844e18e67320a831e647d923b2720d65ddd9ece165c222231d3c3e7f0001d15e3c690e9831ceb369a8edf183133814bfd20dd25d50973bda58ad03c4cbda8008556fc653ef401ff76ee858c1f79a0b09b4232768e72dd06e42078923d5647cb310bb644feb24d6b7e9d1167c3676cd96f79965a066aca314089db60bdc40c2be4b69c569ec76b3bb74a43fe731bc869c9222ab5404304a513d4f7d2ec5af278f7c3d664fcde579bba7bd472bdc00a1eb4c46ff69fb7e45e5712919e8656a8887afa28cadd66461fc57f53d574c92105818a89f210d7e8aee6de2e78228b2cb03b850a6e77627f70f51bb919bddf61837a978dd4cec2db138c657214ac07b67134bd53b071e2bffa3608a0b0bac88b0ddcfc1ba4dea17191c9ad76ab8de72118893256a7e13e15a3bf98bb5757a78c58328cc4b380f3786f22c6be81884d213ec3cc2784583a47a4003a59ebea08bd06e290a892c937448e664dac672942b068b839593c442f6e1d22875e01859cd24c17d108696a3196ea4794ddfdf25721d3dd3e754d1ea884e5086479819452991403a39014297fcc734e56f8daae4d49d5c47016fc3ead550783df895542229ff3b034b5b722ae2a2b04ba70e42c174e9ddb89ffa60024aa16f297ac9383b2ccad53de4bbe4ea2fa3fe3d059d16b4b4fe9959ba3c4e58922e7fa2673f50be5b636ee7c79b445471ddf5b851ec3ac505980bb184c8fe44c7776ae9aab4e66ce31fe1bc00efced390a82f96b4866e31ba3ff832a25b1e1d00ec44bf525ae523b7102ba60c1d3a2e2bed004524afc90a064b325a258eb36315b1496c748f5407e922914787acb8b47bdc495e521518e0637eac4b1b4fe1adede145181ec7ef038d48c473d6f296b349d7cf874d329c71f272883eb7e77ff303957e159fd417d5055d82687448950dd149e1074a1785518ebaf7ac167e07f1f559893a20d133b59aa294efebdae1e19a30ec9a3e257203eb9a854096395825ef4d1e4ecf1f8daeadfa049ea6c435c50d67fd21c6f6b11a8be46502f0dda1715f5349df5330454316498660b7996432e679c73f1af33e529ac669496bde538890cc093122842e3e2e4bff937708dd4b1b1d3fc066a63824266461e4af9245032d690aac0ea5636c29606473820ee57b112e2bd68c0ce1936b7e76a7873cad678b26b560d7bb10a7dcad3f69bbf226faf2f572c105741a121fa1c55ff30b2d0b7339ed9aa4c9a3671e6e4b572800afcbc8764b16f0a61c4c1ff24c3b64992cd84f39d1a4d5532a7dbd9f7bc847258a33c509a945e53236cbc46b61fc6fad662c523eef0c1eaa4bc0a49610c8d09659e7bdfa858d2494dc3da0a54fcce229951d366fd17f4120f27ac77e5e6b777693641a853eacec09cc4dc08ff6ba22295acec61c5e6215eaf2a3a012461eaade8faa9cba630c5ce2bee6f1a4676d54b4a38b7b5cfb6c98106a4882ed88153a4f0bad3e0f3d04dc1ae5318e3b8f4ab1d122a548eed47f70edad1a164a9c5c3eb10fdecb24b0b68005b2e958980481834c4f673478d3f47d07836d3c1c513dd920042381f70f1a68671acee2fdd453a7552eba497af27127999a13a33104f0086390e01635d1a0b79d92dd43211c74047804e82d9ab26f97ee88e664871dab52a2a79443e39f06a6e8ac9d5e986252529b389d9ed0b2f55fb16ca65f6e90cc9a149065f499630f973996c1e2b6c53f2ab391b7d78cc6926b1684d066a3a74b86b3b633baaf3730acd28deaf18fb926e1ec9c1f8a2345103cc4cbec05345db57c5adcf062412f289607f5fa41194f69bc2f426a30c7a6f8d1027ee8dc96c9957e90fbd9b16475b82dfd8698195159bd7b4860004beb1fa85e6843eca1acbbb0b8c7ec0b865ed108e297a2d5f915304167e18d01e51497e6e3ea76ae99bcb849f7595fa74c2a6263e2bef65f1063bce05483980ed51eac5289307117f17e99d761337e9b1fb625a1b900e6179f3b02de57a0b5f52352298c8a2d2c816182ec169d2b9c0490097ad98e2edc99c6df683a4b5b6eb73ccee0aaf07e8cf8f2f632381ac407c5c578bc1c5a8d0915dc231b01b92dbd25c2bfd412995780582793736572f1e23ef690bfe6872c2572285cd737a4be91f4dcafef09232de77b315d73f5beb23d03625e031d2438081222b063c343f52565ae314ac47a4fe518b45d0c12f2ceabc5e05c20f607b97035afbe0e29249e47961d9cf9b385c065966b0c7ea91cfa9ed1b55a58b9aaa9de080ca05c6405fdf15bcef74177226eb225a47d532bcbc82a5ffed7fd86c2609b146d86f566d0b84f638d46d6eb696bfbbc62c4fc981a94c1d6ccb9f3f7ed7976ea7e8ff1d2a2d79986fb27f1401f25d5a83f64844fa9e839fc8855007b417b261d325b6e7cb124b27ede8ad18d2b6da8bfc4d4f50c3960d5a1c82e4557b16d05471602d2a31462e4bac9535c9a57389ae0613a674815c2ec10c19f529c9274896dfe49ab06889da517d482145ed8f57ba4b7c0434ce24090ef2459682a4f6342ecc382b4cd3409c3415bcb7f1bbaadfb7ec308eea8b6cb2912469b707c99a55c1754db0650616754735b85a41433a30b28e3946754f90caeb03c7579fc9982e6ec5501d6f23e0f2b6392acc435907d79ea11eb6955723a81c4f02bfc78e2eeb1d0408f8f06b4d2f6d20d90f7698c4e58bcfa993884424f8fcb602ef35d23737fb6aff220927e28c19043ae708fd9755256a8a1660d9c5827bab1b836a10aa23aea9c92fa3b25428b3791c5d25f3f1b63befd5480ac4192c966350edceea8938ecc608e0f063d16d427049ad62625f5177470e7a0d811e8d4273aea8f7377d51db07fc34d9f18497a0c2b5c0bc5e8778e06bf7460f0487eed54d661d74346eeada9090957159b86f8b68183e33d0c3fc134d87e068badd8789d4c7adb829fe08e4558bada5ef3f526afb2c7b6184244af0d07aa5cb525c519ed32298bb6241d900ead0532b0b1fc77a6577963e7a44627ed326741af254ab957ca0298a74323d2ee4f1bca70e20ff796491424e108e03c20f2eed7374c0aa2474a91f3ced6f46165c886a510734d606ceaa08822bfced69def33cea3662512fb42ecefee341d1b499b826ad882542374b032e907a7e6a4dddc4620a5d1002b5aee25711fd2dd6e9d4e90ee350f2889d6c1f4328e4b711fc919ef3c655311637b83b4eff39c157e0510807ec61714b843bc9eb22a0f4dac7e5cc07b8e9ed587b701d9aca2a239e76ac9a16338b74d50578956e06b1ac35ee3b822ca779922d89de7d915afd7d80831e8534b8f8a2eaed252fd862abc99aadde62d4520d9a7c3c3da86081fc36927de60e3479096a2b5025b9a789da01da969cfb0ab2f252c82db9e6663dce3888146b365080f649cf94f991312817147d8f0d1774d8d44ba4afd846060df2de1d1043659c3b94b1eff51fff84e5a81a0c635aedcf677285e0d722e3335449fd0f49a41264fb963ea5bba31dae469c789047812071d8853291fd8003cc31a8968ce7acb68a6e0172ba6ee0e9dedbebeb62143047336c5a91c77085afb01fc075938b306d7e36383ecdfda55b9b5dfdab53aa34000289c398f617a146c4a06404737600484d8d4ea960061ec2cb575dc485f65f275540d0ce7550da08417632b6f0f7d044f6f719ff839aa3e5c9db94d45225a1cf0bdb0c5bffa781572ad605ad37aa988240858c9493dee9f00ed281e93532d89aba5e9e59ec430cdd5edfdfc2ef65e094eeab71cc40b59c997943a0e0dbbc80f1e11834bf3b53153ba1c1f0ccf63b3c802439b2ef1430be6994300d9b2efe4b84e25bd3bf8a566d4851e7fff57cada544d722438e8980a31563ef0558fdd8db9bdd6f1a3e34f06104b680f63c1f80a08ec6ed74bca69bb1023fe63d24c7e7a14ce85db6e21173f2ddf14f233f3787a37e4b347e4d64907fc0a23c3da017c81c27df9fafd4695886d0ddec8c47982912eceef886ab5680a130bfacbf3c67bb4f0cc118274bdfed43bbc2ba56f048d6a390e48932469b30ac84fdfc2e812f32d00a85349bb22f2d8091e64282fca1b40811db756059de5d03861d6a22cfc6289097d23c26c5e3f000f9b34a0e1b28a1269d8673d09107b29ccaa1adc8939bdca312c69ae4a238f45410d8f1b27392d594ceea2a6b42899ee5c5857965b29bea1bc413da618899b1894f2adff3b3a7b05a626e50e42379f5d0e0a148ded33d815f59d1401b197a85656466eaf88ed30d1ad4a87985570291efbb3a2c6f22c0b111e65c843ca3c6179e94335f0f91d4696e1a31107948a042f55f264c32a35e719668483957c9c8e13fd01e5f751870a509f5f06ba41ad63cbd5f706f25b1e598f6c9709ee6bab627211bc38494962e930779ed4ea2a8471d309c4c4f0603238959cb13476b673489696c87ad9da5fef0d6467145a77ae0b1089c8626988278a85be3292680d9d7e4c6866f19b78595d611f15f9a5e37b3d145d5aff4a5b58a3286bd25a862904817afe8e9b9105584af15f54554ca5e7dceaa0fbd1111aae126d74f68bb6f0ce98094dc9a59a31d9526729efa171beda9ac5b7db9118aa94b9b5ad58dc20ae1c328e31269244d636139
+Ciphertext = d248b9e47c303f735b0d29f6111a742d93509ae051466688d56b587104a74fab1b259da64475fc0d2c3e28d87ca4edfeaa5715c23dc0e5281eb0c0c14e22182bb02f9f7d3c24555cd6a3ff766c774e67730a920db5f85d47dc23bbbee460f0922cd7ddba81ccbe727b4b489e79a19db2d012dad2a732273dafabc0fbded3c47dbe5b6b585570c39eb62850dc47f4aa0c29bf5fadf334041fdd4658fa6cc29a81192a53dcf47c03ddca9d03b33b06e5b3808be77925b7e7d8cf51fa939e023161d969f92430917d73f3aa10b83d5b7402410280561a27c376ce0b5151a51be2ef4eb9057eed25a0715436233615dcad1559fdbd81042544441857cdf46d72f5f50ee552cfd3bf166c530e57fd97f34e2e71bff8a90b30b4c4cc3e843b0f06e4eb2ff82675e428f5303aa9141dbeb615cf6aca5540fd7cb756fe5f9b08a4abdc6eb90b2eaef51c21eb9ae79a0e44b0755b3ed48f5e6e57f3148ce02501528dd3dd2b0bbec2650710a183e38510990002ce6498dc5ce7bf33d699dd18b66c0f8031d958b11d678674c355a635f4b5e8d863785f5dc2f99eba9ce74595493c017697344b651dcc2a0b1d5386b73abd8bb2dc77a2d92173d3688d0d704da9e44a6385af9fb3a81db68822b1eac9ab284f0155c20f6bc34af85d8518d0dfd32fdaece1379abca339a00e1326b624b3e4050be5db8dced5e6c4b88b82b6ee2a48c373d236ea3565ecc072e953ffe01b624c6ecbf534678aad9c3f8a07d7dd7232134b6b397d0c96ab5f795f9e3af65b96e7a765283d8081dab9f953113abe06e8d150bf9a8416d8932fac17b032dc346be43736dbf066ed239328803510f6f62bc8abc92f6df9a82c02cbf85de91739bc8d7805d392341be99798079419540dc952fa0d3ceca4b806ab1db3b717f0d720038343465a8bc0da8e8964e58634e8a2d6c99230af2ac7c89acd3f86a22075dc40818028f3c632b36a39c0e064e3ca2a078c617a3e73aaea56ef11114f9efaac90a3ec8f8d9b18921a80d74b09ada83efee127f41179dc6c19c7965f3e7f43e22f636534b123e9246172f9920f253d2a2652a5e8c337ff93b2d479bef5e96e972a9b9cd8af057c750bd711010d59ce065ad50fdd487b5dde616301d0ae6373b6f9efae99d8972f242dd7a6bc61caee70201869be202fd384a992478dfc133b84171f013244c5d17585934aed3b43b818926246227d255bf832ff481f5f8d074ab159a11d6d17ed0ac50f727b870db966e0373bd3b1eecbf9ed66aa66caf33ac57cffe4ac6df3cf7b0e54ac54be4f3d50f61b33557c2990c908a710c85000ef6fa62716960daf918ae3d81ee60b3813e65673bd911ce468510bd230b9c2d215afe86ec12e49e0ae87e4235baf3df237188f5e0af2e61c22a4bf77190dd5dc804b4cc330b360c3dc093ef208c37d299ea0cd2ba906084011e16ac5f4fc9646538d5b538a99546d34a4599c8529c1524fc4b394d6a9cd762855905233ed92e72c8b538372ffe2f0df7085eb074616c7e695d7de40779e384d5fdb49fe02385424ea991dc05c6ae813f76c673eb45d6105bcdcfdbf04dcdd20caa6e30efcf3537bcf72947e1ac37d1e8c600ba9238569a4b3afa590d61acceb2572da85885146a142c8f8c60afe4d53ee4d61f33c47e5a99da9a346bcfbd013754ef39a4d7f16c4c5fbfa53d7f180c16e2b64f97dcfd65349939b5fc167c7a78926f638f1893fe9a81e897beea3258a4175d14f41dc123ddd846e45a87f35154db8a5ac27c7a0fc95d3b3113cfa9e7c828f83a1f0d91ab7789c33be5f55ecbb8eb0c81bcc0fccc880011b21000e2f10773388b198ce79c5d694472d3ef6b2e55c342b29c70e4f33fe59e2e0bd3f9ef617733dd3329a0e426338d9c007bcdd382522cb96e59b223825a39b01b52809f5e8518f64b81c99022d8215b5c435d87cc1a57bd440b31a19b197b277b2072968595ccd64c135ae1b218046e27a7f2685d013ce3173efd07586dc72a28ac4792e804d44f9efd785ef005213df928560a20daa4c24ab07f081479270a0dcee3c26331c48a164e4b9d79a7c30c77ab06b00e9b72c190d35fb873bc095d5e6231a89b52a0737a99532079bcc72ee221b48f0d0d9ba9105f981beb4225f6efc1230d6da10fd2b58a65112a98e4bbbe1accd6e8589eb6d9c771bb911cccf42aa6cbc68d1976f0da7eff1e70277e8c5f83734ec1efb2b00708fef08e986bd6519a0fa4b5772e585ac8e37fd2a2af07aa382579498b3b75863fe792461492b8e71c4a1a2f4421705696a96601317cfff1632784b5d75fc2036ed3fa650354620781b9fcfd53f1927223fa045edf4abe7b2144512f3e3aee99f7ac3e46028bc2427aeb18e9cb40db57b696ea884658abc9b7bae0d8117f93074a3ef903528f8b55c7687cf9f0119a1f246cc9e993219c6384359e7e5e639bb294b264048060224ae168d7b9f1f795c07eaafcddb10b61ac2be3ab3e1fddf75c1f47559f38d24f0c773d0e8bc5fa85d7d33e3aa8d0f15583b8c1e7aab6f5d0e085b7175678bf11cfee8eb069b78220377819e3f4d28eb833d3d21efff543d5c6357fffb4a8fdd6ce399fca42e2d71c53c50f6b20bcbaa1650b57ff483837c39a37d5e978393c332b43021508b8ef27773164d69d0af3c0dfdc125cf30a7c49a7d8e5320d68a35e80cdfd62a0b7ce6a412f08c8062e35265fad5d1f226d590e9b068d09e48772711d7dbd786a38c0325b3d5665c2ff45ad0a20c174dc5739896ac727b34f11c7af299d36d30c69bbdc35770138cf891cfdd8123489fdef2dfaffa9c2548ebd60b0f0bcedff44691979b4e92b364753120364dc2e3b895095da828e8659575a85cca587ba05ca625480f977a6fe10181ab6ce005defbcd8894f8c71811909cd6b56eb7ffe327f46793a9e98bd7fe8951400276bb9c7607f8ba1e633034b73d7f0d040197c3f346394eba68c8accccefe05f59cb7ea9ab1ae2e172d8f466ee21c6531cec2c9dfeebc477a6d98195c28bccc1d5e23ae50e3a1ddd7de189e36ffe0e387df7be43427b194b16e18b42eacd517bba78edc9f56a2c7e89e6f13513718869da7c8c529bc337217a69e14e35cf97ff7db2c23700347f0a33ad25a299fc52b35f63949735ad864aa127053797541864b07168f89ffb7ba5c9a8bfbcb4248383a95f45461a7aee9c658c5679205f47144ba4a06175e746037b8cb6556f06405e0d537d0f2bcd898dd5fb987d96dbce33001a50abff5b9cb0161dbfe30f5df5a161ddd8a750b0cb33898c110415881fc81239f2e25440bca41a5bc46fbd3787e6c8fe8a463415cd9a82be368a02566da740dca8e40e686e1213d9c15de2d3556a1e1180b298ba3074b4ab93e469dd9a39ac0c8a173b04a5ad913e72e4d7b5ff520f108e1a1747c11b6b2fcfaa89b3ef7e669f8ad9620364b4f4f0f9ab274e76bdd631df033357a24723653e427324d907a9eceb3c375c43ee36cdeb046a6374be19ab04922da93d4dc07c5914df06fee97dd813f5fd501ca75e3c5ad53574837f2e51ba6a257134e8ee0f4127c59840ba8b1bb13592dcbe47aea50e453c7837e91bb12ad1c74fd0f149479bc0334c511a822145690a3a408caa32671ed05c2dd219ea360c67727c1fe6a6cd842301761e94bedc73f93de7091b8b6d2783a788313b2fa12595904bf5d1167a5ddc4ee151b1522de60b7293b72a62c4d08b396ed682b6a6262a212ddc8c70dbec1a972cedc09f593e21d843279561884f9759a593da7b17a147db7559f19d5d6f43ea98012872f974306037dc0d344c55403b35a5903f766359341bee5bccb696fc0fd1c7aa8803e4c2f9e6e23d386d3a202027c5792e355592efab9330af330392a7c91e3cacc4e645359edafd78b77829374cd4b644817322b7650696fa763a0cc7143f9ec7e2f6ab3c9ec2443b0c0b0a31e9eeafb7bb8c375232357f08256959a10a6d4bc98d6cd9314a2ce7feaa8c0eb1eeb15047f715d6ae9ebd64238d648ed6bc50617a360d8ff9a01aa0ce0e29338d34bb9612751445372ac6d74837c7d2d67729760216ee33476cce1a154086ec31d986cc5a14e86561c6929554fb280646164bb03e8e52588a1b947960a77d61c2d2499212a742e1a5b78805b5b64fed141d3c4834301b8a8bef31ce65edb539fd9469b590a6980d0d1bd29e34a09f87438059a09b1ea234d1bb29882e67599fc1e417db9d86332077cfb05fe440ad1243e26a67a0ea30e63cdee8850a543d76e810140547412fb1400ac87a10e3bc77d3918750a5cc3e7a0efbd736c7ed4139cd5855ddba47143362bf40b91fcbf27222017c1552360466483e67ed125745724cc713c713dcf7ef6ea3081d65d8d78b903382717848bee7410431e1040ec92373f75a1bf229816f55dcfffb6e6da33ed8e1e8b05f9348cdcd6938f053eb9f93e0de639e922627bf61a6688f9649bb9cdfce6236a176db8b9b53ce4b5f9eb9c0680c92128bd327aa7f04a745025faaf117a18d5664027ab0e3f5898b834e1a75cd4b4087637733416f8bac1ccd67cb4457005945676d03f76fd0453fdb9968643fec98d28da7c8cd7070a803b14a2459f073ea075fd023a896d3306fdabc54416e95907103cd2fb642e301c71cc48e8eabedaae356582761a14e0b3b0ef1de06002c2acf594c85820ae3a094e5b4680566b592221543c1dc5192d6b208e86b5aca91d4e3454564eedb3b8208169ce97e1632b864f1d9d4c4c4c0fd4bcc5206e8f6d64c7cdf212d718cb5b7c7ee21593ada3f33f5952e12bba4f46cb99044978fe75349c6ca735db35891351d7e5f02a93354bc45a9ec756453f053cb87430b3e9211807f81ad99b6fceb8ef1b2d655910e1f5fd22f2ee90e42abab230f8f39a8345eed6ad294a0d32416a253f829093ecae209bc1dbfadae04a373080f9ea8394a28ddfe1134309bb53ae571d2019ff2bd4be94f8176d90987fcebad323f0b2921b85b2610852973f383a2ff4a5fa82a77b13cfd50a33f29164a9ff409422cc4cbd772132856cbd08470b220ace957a6b8e02c8003d750539a38a8df19a5b662907b72e3098d77c2fc3ece0693b47ff19ce911a93b6adce75653d48ace6af10b8f1141437f9206658707b16794e349db3f1a02606ea167d0213ce3644f64ced64de3799b1729210fc31ba1811b0c226306f2466b230ae35e6d8fa11c8f932e27da8cb1bd311919bf9178ef08bb7a2b4ca2d2e6e9585ee9f916991cfcd4862f5de9fbbc63bee6edbdcfcec9173a252eb59fc6d6e58258ca8b2a4475acfc1e09a0c9566d23d92e9ada97de51895bfb0867c42025c8d089c65bba67f4dd84d7c5155a930329345cdf3b1d6e910e730df273e183190beb900344bbce8c3bdb13a7e4ecbe967a61d47921aa55bac2bbb24e3e03d386ddbfafb3b32235b5ed922ed6ac2c89ded1316b69079b826507d708a6cca14ce2244a67be90fb91ddcb0c97432703729bceb432bc856f5eb9d2f169800a04283b080f0e053670a21468df9414fda9f4153eaf1669a19ede7925f832280800f0063ceee34b9d3b0f8da2012525fa7927e76bda71954714d5f51405b920391eca2ad71160acef4091878b907974573b4cf1b377baca0340ab0e4ec546fcaa6130603ad633c3ef980e88d8f44ec5de743cdc6cd9e0e4cbdb97a5c076be9ada8f26bc54d711facec16a2401292cc167bb98cdd320ec9321414bd97498f6d9b54dbb45ffe4b3e3f88260657ee23e19de48a93595c8e3a289a02d76a27ceead05d591633464709aca117c26aa49b64667f2a3b6371984f813d7098fae7a6ba1841775b52314a06c80b4c994ef8100e233ab3115ba2c39b97f2d5082a145720ad0b12b8a7cb275ba848b3fae14fc0c82bf0353195c056b302e508982f73a8519cca722892482b9d9e6a58bfb4d862fa393eabe6aedeae1be5ed772ea3c94a0df1d9684a131c35246c68b32e46aaf89f3649e58b2e99bd6bb3923d3ab43cbf73b6b3d19fe3b62bef178f46c79ba85e23ee4b25bc561e8fa97f51605bc0b210b02aa28242e81dae9489076d259f17d25b93b0e8a2010584d907314e3bd55482f0fa43d37ae9535629d28d6f837360bb35ec869d2a959789dc49b9c8c515942a1e03650566b736551a5180a60279bdb0ff9c387beebeb9e59ed930b3746464a010a6f7ef1de3c7d76fc6899b1e5ed98213813ffb333d969ad72fd8537ef4e12ca7b78d35c24f44ac82da4a7116492ca2efd86ee6a4474014e72a5cfeee7f729b77cfdd1a5d10a03f3cf28f1d314fca36d31ef2ecb3cfccecbcdfd22367b0a0e04435654286ae3d4fee13f56bb7cdab40b4e1dd01f9ef857f94a67c1e237e24819949935ff3bd73b0461ee9020fd0a2db2cc6312ace97e4a8a33c295271453a12822db8d1438f22ed0d466150990dcb39ed042424eef7a1210c83224c856923e3251484a81a15cddb4d7ada8bb7968dcc8f85e39ca99ece8ce2ed7753fcee6900cc9b7b5691f2d67ef9be13f70d195bbd0047908025df01b4f4d581fd59239836578627d9d585ebe9b053d807e9d3ba25405029a148938a746636decdade02b1afb5ccbf2f0e14a27c98a1e130d9208bbf7da4bb4e572927eb348568921d4a3309a2c24f367c935c2a8e1524c3024ff350ac7da8d2849586817bc9d46a08a21aef035a6151e608ed93b1556a484e455819f9ac2fb155020738962e7255a82a0854b31fe20cdd351c10a33eb693c9be1a51a932e04d0364ced41ee1bf800d0c12ab5eb37fe52563666e52827720e856d4f24eb06e0aba446910aabbe36513f2274362fedba4c19398433029495284ccb499bb559a9cdbc94a0d1b733136969a743945a04e1d2d4e77fed21550af35f22651c7de802eab7a3942d7ec55a3a5002bde8d5cccc1d4ac4bb7f4926615fcece543fe5d9092d2c4f50d94fd9868775a072f4a5bcf2e5fd10795f7f172a3341ce33505ba68e7ebedc9c1e9165864244ed31bbe5c308dceff858cc42010ad8c281a24689cf2dee8a549b1abab9981d70a912174944b403ce664d8608b2f723150f5c12164e4caf28676e7a25c3928ca2a4dbe96355ef8f282e57888d40715df07bd8b5895549ad957e758abf868def1c1f5e260d26498616e2ac962bcaa33b879874569f198a91ce4e50fc50da77fea1df9f9ea900c834dcdd462d338efcf8e612aedebf254fac596507d175d30a90543627cfcef6852c7cda8b430e255c4d6d417de31eb5dba123e3ce9e2269867d9a94fdcd8ccac40a9451953085109f5ae0c3e04daadb4a2a47b0e176917660eb3c9f1aae0ec6b00635fa387e056623947c0621f0a12e86fac1881ed1dc1b9f523388d6b6596a152b3e732c561972879dcd3f0232ef0773a4fb195a90c3186c4688ea58967ce7f18386b80bd38e90cfd4cb899337ab27cba8db6523e979b4c449645bb2f320ccd28578bc7ec38f47225273fa61a2e5df97c4d76c556fbe2b0fd30e615f5fc82c3de7194caed9f5946c151c22b7a0c48f4a7cf78aa153414f2913c5eb95e3dbcea7ca544272cd13a1c52fa87759aeb430aab144fab418c835344605df3a044825965ca15de6ba0e59b2080f5844b2d110d71587e19acf14264cec2de5b8c77d18893215d1c1da0a940e7c2ee429a99e2633c216aecb7675a2314a09044951ca5a8eac798f8878fb5ea65f4ddccac53ee0c786e597169079fb6e8ceb37a71580b0904a97450909ca454a690821e249aebb75449e582fe1b30f1fa9f6464bdef654daa5ede6d4f223f4589ea25a25f4672cfbe974d51008bce296628556f55d26646e40b59f40e3149273760b40806ace3b5171e0b79865c6adb53513da2f24c4115de243150cec76107b48ca8da19117f00b5870e67eb8357e43c1b7b593c9875795d46ede26a109e05406b69fda988947e49ab195f22454c3c743c2ec51b91370b4df8d38653b353e51bb83215d122bcfa591009c007bbb6124bc590fed3f9c5699180b3b1424ad02f7c90a149b77d22dea5c996aba675c2a1a20e206d9c25d9446247d495a26486c0d0bfb09d0b5a1a177a09fa749dc36cee73af0116a6b779c2b827512a04ff0f60b483edbcdb33d2a18339463c498ae67ffa9da0aa3f3beb6bc99212f9e6961afde89045520b1f3f2e2761666a333d76030f443f53322f099035584a60978ef8b49f46d7d4d8c5c758ea52a04b59c1a3a1c2f9df3f3b6f5c45cf4b3547043b18c1d615a2c965c3918d090cc72946e8fd0b938e60e03464f4bc71fb719a1d173b0931930e58bf7f6d4403971d36b40f83be6b57244a7029e1d41dc908764d57a5442557218b509faeda4e9fcf31debbc54ae671ef636871233f29e0013c0e33933543f4b59df1978ec89b109c3977b0cf938b7f6166d6c93be5e87684a703c8b7b5fe1a8bfe153a179b55575ff05e599b39e32ed10d958699a1ffe07136081f0719b18c69dc74f66f211103e9c544f3c81a88ba9f66a9bc7017d9ca9e2cd97634052694a598476b99daf1cdfb6122869375ca5873d32d5c1e07d9b5b380b4f09dbe04478cfb1a13853eafacfed70c8abcd444ed095f78d07c0e8b4093be95c3aa24b2e5b6bfe3a06e9d2d9fedfcfeac4cea2490627e6da6a5cca383351952f654ce2b0ad359c0f7f4ad3f8d1d4a030a947d4a2e417bb79102729115cc8b6558c3362b1d805fb48ce4858deff97677e60375ed13e150a12ee7dcc8ccc64d9710c7f516555c1f7a1a08f0d7c6fd21f864fcf28c8f748c40494e01fc32006f977a5100577f86a484d11b82c90cfe6b4d6b1902fef486cc6f3e033904e150e67283e49a5382961dabd244412ca9657b48796e476a82443167e277d5a65c0c563a6abca77d316e5d3ab639a1ecfb1110af2d29f146508bd9874486dbb56328d6f59479e2766692821660462aa60b6bc8a710707ceeb0ea6429e5113e03c9f41ce0d69c7589deb547527673e8a9f9a9a74e9e4bbcabf2e306b35504c1da99730ae86e94cd047b2e6ea5e97e63a492430d37ec446434fb3b066adde08b17d7d903ad194a4a863d6cfe181a45c8c97b5062bf7c4e44d69c0d1a7e1f5029b805b7c21d1b5e56e697999a32557870ebaae8d87dcb5ca5eea2c5547a16b3f30ef9df8df821028c106f86e091050ff8b6ea4171e59dc2592d405073bea53f8ea62edf112dfbc7ca69809db8005783d63557d3d90d123a944be395c1dc3b5e1476dff188346327769fea65f3cf9363e88ed67335870ec8ef13eb9d9ff5317c4e24dfce9d11699e5f47b4233cc8f9d1b915e716a5730a5898ee65d30b1628b484a5e82eda95a590964a8d8bc89dd3c5cf6c4f9137b8c6ee9d6a692e0c0d1d858dd5b3c12de48badade4d01bff312c56ce3ddb34b0fdde3b0c2706fc292b9fac7e1a0dcd0b6534c968117f7de15eba84d2754e4bcb8093a5440297605598659f686075e2b1b464b6b3ec68abb13cde263b1c607545c45746338b9b207b5c381da690f653b35e363e1249551ad938b9fd7b0a944151cda07127bf9ba76958e926472f4aa1de8512ce834cfcae5414b226f23acdb1fe5cf685d2201b78167ad35fc1da282744c2a43cc49d49242f968f7e06de14455e7ef5adedc5b33184346018114e2d1fc7a5349e378da9b2af5b328c213888652aca9f1145363809eca7c1fd8e64a5cc3255418736e048a731f3053db77971f67014e6121a8e464833e5dbd02ea6caf385e43e9f378bfba657986bf852b32adb55e35a2675bfc8d70d43a902032a61f59f57dad2dd7d7963322136233200cb9a90c952074e9ba0fc0654f1b6fd6f7f0eb77c0fa6d8143213ce6e8b0c178f73e17a7c64839f9bebca2fc955ea8ae406a13b80a9045fa8d129fd859faa46fd27c48bde7b890f98ee938c0d78889f84181ae2f5711304fe554d4251bbc6437ced59d577a2a1f26da736193c3674adb13cef9f4cb4aa6585c4d6874b0309ecde300493b1642c595746f09e03977c8902f3a4a877db1153b248f295a0ca2f1e437d15fcab8fd77c5f967304efb5c4920b990674ae61b954af40be17a8559dc377c591b68067fdcaf2d27bd9a22041b981a84be3de50d5962b58f8c4a22fa05192c5ac99a0a9423284fe62a3a59f085136cec72cda2a53af106a2eb5bda28b6e02c299118cd91714c2e7d045346c78d9ed1b41c73231a21e42c298949f70122277f4134ed5c56639edbf3c3e717310e3d1f03dc5a94e64c4ce148bc5c6bde64eb80b17d5979892786a31225eb89bf9f5a582bcf65b83ff7aa361ccd9238d144f6a22a3f77dd8a01382df4ee90a2057dd310a6b0c4b81dfc92a2cc0c606d3be8b18fbe64ddfdf2004eeabea892be2f914edd1edd8e8829dc7704d71bbaaf08c41824dd0f4b34c9eedead9e10e53bfc6fc0bd37417de0c5c71cff0754d672f29c262d8e27b524427e12bc4e4705ab311d3bedcb1ddd09a3ca0c268c05c64951b7d724a9dafe4d249aaabda91d68633aaab845bf78f9a22d467c7e0c5fc70fc9a318b01d7492efea7fffd329d70692e76647ae665c62b280da0d62f870a52e4dc4cd92c9150c96aab16f8c23475e3152d4debb41b6756f000c3d8aceef18b49e295be7a71da1eeadf4eb96509d45d7cc42af4b7013d8bb445f577e8d4cff92770b8ba0e451f3e24c6d981efdb68c7f2dfafee40b8a425955796e369f0d4da3e998c1626ae0fa583334475f1fdde68ca211c3f2e9afb003f553191702e11f8b731c89ea26059ea4466f2bd0a1a5601025ca9417006bca5c9a57dfdba44c603ef9ad38922623b40feda036d84425c47fa42973e348a180a7570e1215044c375313ab08d6f521052dda415707ebb74d6c4774e039bb04cadc2799224bde1802e2ee2a018032e3a341700c0fa2aa28bf93cc479231efe7da0e9f68e572415348c08cf648117e9b6d1267fef6617f5927252c86cc087775db3e30180feb5ce7e1ac9c3761161e07a4853aa6d97e525aa88302954cf9390fde81f8e11d97a11c79e3bad261364c18890dd1f8fc71127edefe3571518a42be611a46a0426a33221aa25a0ae6514daaf96038cb59aaba898de49e3b215a4464e0af614e638c2d9b6e676ec427fc906bc516331a18121f306a5246d179e2d3d0f38ab8393f7ea5a2d24585e7cca649637b9983924a15483c167e8780f8dd7aa1154cbf731745a8d8d54a8c4f8d854371bb8172303f9ba3c8c7cfe8c378ee56bc35c6376aafe907d3294ee9a8786281b7deff78ff125761f1a31d0e8fffe04a52a7574eeb8679670ca3bfb740167a559488d4337819613d32752d8a89013622f6a8d70f3c64b84a4215f4b7bb282a2d17c36a326167e3270757b8f1d9a0137bfc5ec278e8ca35a69e49779cfc25b95a89cc18732b5b9d1986b18878c57e118506909207207ad0b4edf32fb2b35b6e70546f45d0849bd139ffff9d8ae547787e7b51403b54f110e2ac65468cd0910d80a4e321deafd46e9af19609bee1efa41b762b8ace989dd681503539e7d9948664cf7a73ffac9ce2a34b514253c4f21bbccd38057a6d68732930dcdfc9a32219b53339d100db0037a8bbd101e71f5054f3
+AAD = 7b3b9c07148fcd897f657ecfcc87e530191536b8e77f9309e8d7323888b3b21477f2ab7c885c105d9c29ac96aed23b366f9fde4177401b7038c6770c7bd2ee8b4335105cc0eab9e367f0cea90d6f1ae3fa76cd21ceb9f3500ce7fb4b2a3f9e90f900a231ec693aeced7afb6821391d1f5b1b957895777aa7a2b71d9571c00336f26d54d756392cdb74bfb67d5a621d517db20441f74d0940180baf613b09452f64224f8af7bbc864ab4a8434ff624d0c0646ee07132fd376506951899bde975df8c836ab4ed9cc084f1f6d500ad56345d2f250a0d6991b9e458c62b6023191f341c8659e8a38c878cfac12b032674503df9c9bb01c4340c709eb6dd7c74907d769a317f4dd7317843c47bdb4c5e1f07f2380d464b0c47269389cc8a43a09adba86f6aa8f44c8fe514e73b5fe8d344769c1aa20a4538ecfbf47562ca79fa497b0f02f103f75522db9ead50d56dbe86997d6085f1b5aa7a4cab9e51a1247ce4f724a14983b6bafd17369fac973c6be268e20d800de870928e100990ebb0d3bedfceda36c64be3a729b603bce677a49e8caf282c9159b6e3e1e775129bd30dc3f5c9849535d86a27474be03bb5749b4c0115e2614f8feaa7405cc69b1de479b3b57e551f876a9c8c57ab9879cc68bb2ea110b2e77e59dd6a65eaa67cc4d4b2f4d6e646b2a298d3c80fb43969275d4414734e74726145dab06124c040656c39a94846e8fd58d326f4f9eafe5b95d85254765a21993f55070fcb9e85db5d42ab6b9464ce66de3f236dd2a0a26c4e5535dbdcd6eb350209a65aee785c6647ad4103d092a8ac932470880eb314f7c98cdff34fdf35ee2d36f09bd443b5defad7a5acb9df55965421fd043def6f4771e1bb27385b30ba22c0d8972aead6b654085a7dd3b60c4004a0dae22e25100e54e0badd0cadf909799329ddff699de8066dd6c3822d80c73c52d87e6fcbdb2dbbf852e37804b1256e23e76dbe43f30be4a577bc23c7941a3d708d1e1f579e9c6eebc219c74768168f6790a41f883790e08cd1e88ad09a544eb97b3d1d5af67eea666b9c027e5c7c976921189b955a9e605f6cc9c012c1c2e197c5b02504cb9ffbcb0f3ed778d540d5194fdf5d38dba6340c93da7c5501a082689616f337d8b59c2a92c25e777515726e1d7f6cc9552693cc7c30f1294b37f97d49814250d6c1e3eb335c5d214ef3641739d508b87106eaaf367902433a148ca962ec694409acb82d7749e1c88938ad382d0ca6e6cbe8255746832fe737c3e71dae8397f260c98d4a292a126ec21935c24096d2f91ae114194af659455d8a4206197495a28474dd2809debf5f550d77ffac2b0db521559910c352f23472d7aa9f4dbbdb158f40aa36912cbd918ae4c642e76d78d57ade1075c4fe1086ddee3d554353b4693bbcef1cfa87e49890838c36156af0edf384b0413d6d7aa
+Tag = 51cbcf4a2fd82f221de1bfebf86a8c24
+
+# OFB tests from OpenSSL upstream.
+
+# OFB-AES128.Encrypt
+Cipher = AES-128-OFB
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+IV = 000102030405060708090A0B0C0D0E0F
+Operation = ENCRYPT
+Plaintext = 6BC1BEE22E409F96E93D7E117393172A
+Ciphertext = 3B3FD92EB72DAD20333449F8E83CFB4A
+
+Cipher = AES-128-OFB
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+IV = 50FE67CC996D32B6DA0937E99BAFEC60
+Operation = ENCRYPT
+Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
+Ciphertext = 7789508D16918F03F53C52DAC54ED825
+
+Cipher = AES-128-OFB
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+IV = D9A4DADA0892239F6B8B3D7680E15674
+Operation = ENCRYPT
+Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
+Ciphertext = 9740051E9C5FECF64344F7A82260EDCC
+
+Cipher = AES-128-OFB
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+IV = A78819583F0308E7A6BF36B1386ABF23
+Operation = ENCRYPT
+Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
+Ciphertext = 304C6528F659C77866A510D9C1D6AE5E
+
+# OFB-AES128.Decrypt
+Cipher = AES-128-OFB
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+IV = 000102030405060708090A0B0C0D0E0F
+Operation = DECRYPT
+Plaintext = 6BC1BEE22E409F96E93D7E117393172A
+Ciphertext = 3B3FD92EB72DAD20333449F8E83CFB4A
+
+Cipher = AES-128-OFB
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+IV = 50FE67CC996D32B6DA0937E99BAFEC60
+Operation = DECRYPT
+Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
+Ciphertext = 7789508D16918F03F53C52DAC54ED825
+
+Cipher = AES-128-OFB
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+IV = D9A4DADA0892239F6B8B3D7680E15674
+Operation = DECRYPT
+Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
+Ciphertext = 9740051E9C5FECF64344F7A82260EDCC
+
+Cipher = AES-128-OFB
+Key = 2B7E151628AED2A6ABF7158809CF4F3C
+IV = A78819583F0308E7A6BF36B1386ABF23
+Operation = DECRYPT
+Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
+Ciphertext = 304C6528F659C77866A510D9C1D6AE5E
+
+# OFB-AES256.Encrypt
+Cipher = AES-256-OFB
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+IV = 000102030405060708090A0B0C0D0E0F
+Operation = ENCRYPT
+Plaintext = 6BC1BEE22E409F96E93D7E117393172A
+Ciphertext = DC7E84BFDA79164B7ECD8486985D3860
+
+Cipher = AES-256-OFB
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+IV = B7BF3A5DF43989DD97F0FA97EBCE2F4A
+Operation = ENCRYPT
+Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
+Ciphertext = 4FEBDC6740D20B3AC88F6AD82A4FB08D
+
+Cipher = AES-256-OFB
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+IV = E1C656305ED1A7A6563805746FE03EDC
+Operation = ENCRYPT
+Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
+Ciphertext = 71AB47A086E86EEDF39D1C5BBA97C408
+
+Cipher = AES-256-OFB
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+IV = 41635BE625B48AFC1666DD42A09D96E7
+Operation = ENCRYPT
+Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
+Ciphertext = 0126141D67F37BE8538F5A8BE740E484
+
+
+# OFB-AES256.Decrypt
+Cipher = AES-256-OFB
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+IV = 000102030405060708090A0B0C0D0E0F
+Operation = DECRYPT
+Plaintext = 6BC1BEE22E409F96E93D7E117393172A
+Ciphertext = DC7E84BFDA79164B7ECD8486985D3860
+
+Cipher = AES-256-OFB
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+IV = B7BF3A5DF43989DD97F0FA97EBCE2F4A
+Operation = DECRYPT
+Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
+Ciphertext = 4FEBDC6740D20B3AC88F6AD82A4FB08D
+
+Cipher = AES-256-OFB
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+IV = E1C656305ED1A7A6563805746FE03EDC
+Operation = DECRYPT
+Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
+Ciphertext = 71AB47A086E86EEDF39D1C5BBA97C408
+
+Cipher = AES-256-OFB
+Key = 603DEB1015CA71BE2B73AEF0857D77811F352C073B6108D72D9810A30914DFF4
+IV = 41635BE625B48AFC1666DD42A09D96E7
+Operation = DECRYPT
+Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
+Ciphertext = 0126141D67F37BE8538F5A8BE740E484
+
+
+# AES-192 CBC-mode test from upstream OpenSSL.
+Cipher = AES-192-CBC
+Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
+IV = 000102030405060708090A0B0C0D0E0F
+Plaintext = 6BC1BEE22E409F96E93D7E117393172A
+Ciphertext = 4F021DB243BC633D7178183A9FA071E8
+
+Cipher = AES-192-CBC
+Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
+IV = 4F021DB243BC633D7178183A9FA071E8
+Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
+Ciphertext = B4D9ADA9AD7DEDF4E5E738763F69145A
+
+Cipher = AES-192-CBC
+Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
+IV = B4D9ADA9AD7DEDF4E5E738763F69145A
+Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
+Ciphertext = 571B242012FB7AE07FA9BAAC3DF102E0
+
+Cipher = AES-192-CBC
+Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
+IV = 571B242012FB7AE07FA9BAAC3DF102E0
+Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
+Ciphertext = 08B0E27988598881D920A9E64F5615CD
+
+
+# AES-192-ECB tests from FIPS-197
+Cipher = AES-192-ECB
+Key = 000102030405060708090A0B0C0D0E0F1011121314151617
+Operation = ENCRYPT
+Plaintext = 00112233445566778899AABBCCDDEEFF
+Ciphertext = DDA97CA4864CDFE06EAF70A0EC0D7191
+
+
+# AES-192-ECB tests from NIST document SP800-38A
+Cipher = AES-192-ECB
+Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
+Plaintext = 6BC1BEE22E409F96E93D7E117393172A
+Ciphertext = BD334F1D6E45F25FF712A214571FA5CC
+
+Cipher = AES-192-ECB
+Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
+Plaintext = AE2D8A571E03AC9C9EB76FAC45AF8E51
+Ciphertext = 974104846D0AD3AD7734ECB3ECEE4EEF
+
+Cipher = AES-192-ECB
+Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
+Plaintext = 30C81C46A35CE411E5FBC1191A0A52EF
+Ciphertext = EF7AFD2270E2E60ADCE0BA2FACE6444E
+
+Cipher = AES-192-ECB
+Key = 8E73B0F7DA0E6452C810F32B809079E562F8EAD2522C6B7B
+Plaintext = F69F2445DF4F9B17AD2B417BE66C3710
+Ciphertext = 9A4B41BA738D6C72FB16691603C18E0E
+
+# DES ECB tests
+
+Cipher = DES-ECB
+Key = 0000000000000000
+Plaintext = 0000000000000000
+Ciphertext = 8CA64DE9C1B123A7
+
+Cipher = DES-ECB
+Key = FFFFFFFFFFFFFFFF
+Plaintext = FFFFFFFFFFFFFFFF
+Ciphertext = 7359B2163E4EDC58
+
+Cipher = DES-ECB
+Key = 3000000000000000
+Plaintext = 1000000000000001
+Ciphertext = 958E6E627A05557B
+
+Cipher = DES-ECB
+Key = 1111111111111111
+Plaintext = 1111111111111111
+Ciphertext = F40379AB9E0EC533
+
+Cipher = DES-ECB
+Key = 0123456789ABCDEF
+Plaintext = 1111111111111111
+Ciphertext = 17668DFC7292532D
+
+Cipher = DES-ECB
+Key = 1111111111111111
+Plaintext = 0123456789ABCDEF
+Ciphertext = 8A5AE1F81AB8F2DD
+
+Cipher = DES-ECB
+Key = FEDCBA9876543210
+Plaintext = 0123456789ABCDEF
+Ciphertext = ED39D950FA74BCC4
diff --git a/src/crypto/cipher/test/des_ede3_cbc_sha1_ssl3_tests.txt b/src/crypto/cipher/test/des_ede3_cbc_sha1_ssl3_tests.txt
index 2b57c8d..c33964b 100644
--- a/src/crypto/cipher/test/des_ede3_cbc_sha1_ssl3_tests.txt
+++ b/src/crypto/cipher/test/des_ede3_cbc_sha1_ssl3_tests.txt
@@ -24,7 +24,7 @@
 IN: 936a91d0b5
 AD: d2c0267218cb7090c6
 CT: 267abdc1b983e49bc0b90687
-TAG: 8f32d6a4c8181e7d5acf3fc5a3bf9078433cc5a8
+TAG: 8f32d6a4c8181e7d5acf3fc55a4d0a66772185f8
 NO_SEAL: 01
 
 # Test with no padding.
@@ -38,6 +38,2589 @@
 NO_SEAL: 01
 FAILS: 01
 
+# Test with maximal padding.
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebf919d04657440c33fd034626e8a417b9b97d8bd0
+TAG: 557791a3e8547c39955dab18f0144a62762fb196
+NO_SEAL: 01
+FAILS: 01
+
+# Test if the unpadded input is too short for a MAC, but not publicly so.
+# DIGEST: 095a8f557f75cba8e2452ddf97c053904b48827f
+KEY: 18cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1
+NONCE: 
+IN: 
+AD: 936a91d0b5d2c02672
+CT: a76d7e313217b0efa96b0958b078ec9883a0ab2bebb3d63ee7b6b7da7b0d8c0fade2a17aaf35b3aca88c3869da6c1ba966a216a60cec36f7e55a3daeef7d0ff5185f83c478647ce21bca0582224b72bf4eec23b467e0fdf087c2fbeee1c03361886d6d01b3c7b5e379b820b1a8e30dc1dc37c5906b28cb818a194edbb53b63d5d0724a92016783a5d66d1f53341d18be09e31c708ac3ac926daddcdfb1809a710a452c1dadc45ddcd6042c2860a1bee293ef51f63f25bff7ed5f9cced815f8a85faeca14f8f284ef8acac07095d52ec4bc1870cf1102265b7b8c772ae6c1f494f1866f97d906a7dae2ef65c3
+TAG: 722dcef381547f3b97ccfc6c5660438c3cc41216
+NO_SEAL: 01
+FAILS: 01
+
+# Test that each byte of incorrect padding is noticed.
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6aca9607ff5628c16d9c49e4f9753053120fa9a106fa7ecd7ffb008e61197598ef608b6e3e594e13fe041e3eca9686c355861b7e3d60920e4d260f7ae9c8d181de1bdbc20e6661bf7941f9ef612ccdcce8911429c2acf9dd0c199d631416695ccd7e1cbf116c2491833682e79ee30dead21c762dab1b4dd3e47303faf285a305ff2e871a5411e1be9716c1cf8a9d77d01a25032cf622a5bfe36132fea99403357fda3d66466c9c9a5b1b75f760b1f1964120590b9eb2ec3acf2ce826fa34cb07a1da83621d2b98e9f98b847f9034c59e2ae4847934aaffd2c2d0be99481fb4ec633a7109f045541ad62973cbe
+TAG: 30ce5a567d84bfc7428301e2ffbbff0227f1c34a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6903175199caca0041acec1efff1f08c32787a3c6a888f5e04dd8aec7316cf00dcad42b9216a2cc204696334ec8da3cef7c774ba743d272501e9cf598b5807ce676a7ad688f2ec4a398d469d873596ffc4a0954dfa1cdc99910a7d37d17180cb553e79a18efbb02bcd42a06832c129261235c777692f9facb983ff8f6c4f82b900904887060f7d4c82aa3bafde655b9a3b2356cbb43cd39cee164dbd2b612bbd4362b0202268193754121466629c108f274b0210760a0ffeb9fe0767a0341cb493593b5e22f9b1b6dc3d519036b1f093da0abfd73fa4813b58f4feb7369c1eb87ea772b1b9c26695f2bfe32ab
+TAG: 5758d075ed2f916300c1fcfffde81ad1197c9266
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6108410f4f75ecbc9d5eaa8bbcd94cf5cd402390207bf53b7221f78a53d39f3571153a43979a2f2da35bbe408e25ba43f069f5bb06677d81e15a6ebc24a9d0d711bff232488e2ee5fb8bd55514c550b85d024744dcdf179ebe9f73dac725bc0d27eaf158e2a7a61ddf3e9271511b24f4457d18c99c327a6182847683f2a68df44698dfa084e0110731408400769eaa1366c87c0bf21d3d8fc4c3558d9349de5a6deee7bcd3ea8afa336993b07f53765e777e4ae55ac9e612d32d942467f9090bbcf41d1703a30c990822558d6e37c07d8f95fecb2886a85361d0ca3f473ccef3ac4c43a250c1426081e999e75
+TAG: 840bba72000e4f61b5f99620ab3603a3bca328f9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6e8c71386f15c7afabdf4c13b6063bccb4ba67a9c8f15c88d1344ca76b2bc18154cbd22de30d2779dd483025604bce1c1188612a3055d3745d62d2246445b13fc7be0e02dd864964f50572bf631d1a37546d07399136e43635debe50a3e1d2d2d54730b7d32fb12d8c4b5056913eea61968de3b2dc66f78d567ef508d7fe8186ced053d444d63dc319c97b01d75b0a6e6843c3f2c3a65ba8a07256ff3b1b00e5e5ec30d5aeb01e0a3311477fdefaff5a963ee319bc53c1e80337e95136755d3afcec2a7ca23df27a08526c17b9489591e7f2cecb03f43722334e349950e642ea4f9af9ac41bb0df3d28575a3e
+TAG: 2acf3bc73acd5b1e0c6d5fa962b2b6243a41b798
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b62e8a8b25f1156777edeaefc99495a2ddbeac8ee78f3d59f6f3a6f80259dca201b1fc07b15160fa2f45ac75853b5e2c71b0125aaa9d6e4906d0a20e5824abdd7d3dbf6416877386786afecb2da23302dc086867bee4dc063e7f2b3f8a72e8564f4dc6072337d68d4b15f94af9dec3366c3ffc52a2e6e82407a1de715617ed535f8c9e94f491f6618cd2defca93ae876fb72079fdcf3f22adefd70759e21a79fdaabc4717a2de329a24dca7909b4b4fa69cdce8515325316bfa208fb6aa257b3a9c9f1cc92353dc48b3e4a4c56f02cd8345634abd0f2f8c030c2311029f0b5cbcaf363ee89a5fbe4f45fef9d0f
+TAG: 4f6c40e05a91abcf385a0f5b28fb3ed3c3180ff3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b69123f67bc17ef843b405b69cfa29847f22b4774a672b765bcedd0eb712d22bc222a1fe87f590e014d6824fa1527c8bdbd0386063f2b4a60b49f2f7c47ff2aa2bc1110eedc569e9e20866b7497303678bc88be8c1aa43c2b5f00004c941dfb7f89d5762802b82285495a0fb391ef1f31f29a20a6aedee47116384e44952d33144540489c763a91ac964e95b97e80f6918c5742d33b7ef897c06978753e6cb2e70a7f83d98ac2a0a9c002cb94d76f7c67a1a6c7fc1ec1699be9e5dd29f0eceb1d44fc30acdf8dd5e3311d3371303f89d6cc2117756a757df38e204cc964f890793f8ac18860102c837e4f4fb88
+TAG: 5e6b4e0bc5fe7b237453dbec9d1e2b47ceb042b9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6c2b7d0845cd1b597206a7a95b6c565c0c94bed1e0a6029f37e9e2083ad1bf123e996c141e412d13a8d419178348737ae1fd20ca4732bfeccd454fa124552fda20a2e28712176d9833263bc628734e11add37faab3733c492e77e10b58a243558c71423c1af3300eea55b3f0665a5930e996140455d8e951730e76354a467bab2475970c375d9980d9c0e5cfcab193d1b14c9a4ab0894f28df45c760ba6b64826d8c3495ae94b4a8eda583efabd8c18b1c15c8bae2bab52bcbf4b98db666e639349fdeae37ecfbee7e2583a82bb8f36b5370066fd8443a9b0db607d6293a3dadd1308f1a6b2c2a0f7d42dcf50
+TAG: b4e1a0d08cc632f2b8b43f6c4d91c34c8c00a428
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6170b60848358077a5e29c1e20aeff7428f6a6e1504c9607afb51e335a5d5c816e9c452cf7dab010fc44fc94cff4cbe6e2a1e1bad22f4db709bd4f9fbc2f91c8b6c350ef958796d48d353aef992383f02f54ccc8b56f96a2035302a89b7f3814128724121b54413e169be90078bee5047074c9c3011a01ac0ab9dc20206dac372957ecbebbb495959d35ddf469453f48d6d31a56a17e8f3ba233416c81cc5dd0539f22546efa94726b433f30d0a38b68bb3d2ecae9f46b70f8219768073bf91055554e06e6459314dfefcf136357989e9674fd1c5f3dc3fc60962160dda7587e150919343f01452a3f1402872
+TAG: eca060ca321c5b2eae7d2db60c49ec4d1cb615a0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb8983cb68ce7c10f95c5ce17358706f5c5775e3ec531934b7547578f7e8584a0f4251db3987a48aa81c4495ac3879ad93a310fb85411f331d79a77d16e62184b9b197ec5e85949f51453edeeba0355a383e3360f3e086598c660b254aaffdc11f65f7185b2cbdac73d388ff28e481b3b62307ef4f009cba26759aa22173db0391ef2faed096897798c7717e7dad9314268bac06d4f500d594da41fba4019a8c6a62914ee4404c48ad3663702604f5122683df00dd9a1ad1e0061e15ab99735521c1011a5389e6159aeddf370fac9d3d662397d3439257d5bded32061801468232f91ff9a507
+TAG: a6021060219e181ea622e0c78bf034b785b09a34
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb89587236559639661a312a094778344e802b0234294a854e938400c4381ef3be5dd023502e0a5e3b0c38a35c986ad6f43c7108532b0c4ae8fad66282fbe946ddff831b20f8a60e28a1f5f74a85dda8a4abb9264d38ac4580a28cbe9ae132139171ff86c6dca0ae5fe0721896333ea0c4582e2328f4427fc1063d6a82c20c9e41aebc17b67d7be22bbca11416fb580508c93ee3e3a18845eb42d3b0d60769c10208f32dec6315a2bc9562a00067db5d62deee9bb7db94c4b1bc82a955f2700c1cfd422c04cc4c3705fba43b749165101d32c7217b691505fcdf86d09abcbc02da7e007c5682
+TAG: 728968f4d796c946c1ad4eda79cc3951c937a5ea
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb894cec352f22d89c3a8305aacc073b089e0241259c688277dd37ef438a2de00810e9ae9ad3b9ab4f073ca36ff8921e0f0ea0b8db71dd3bcb0f81568b5c7d2ff5a84163a05a520a430a6dc1a92fdbda12fbc6ec66b22c593caa2292a15ae9c892433cacd007b506b7b205dffbc1b2a1cc6a9484bcff9873935989c2ed959dfecb17b166948cbcb5bc47470525b01b3863fa5c580f414da10936c8ec571a37a1218fdcd1c40ea3e3728bc80d48ce3cd4044d2c9dfe9e15970e30ee3088fcd11044b47a554cae0441ac814659a90bd0963722182763043b3816d4fefb7464003947fe4a0aa395
+TAG: 9cd1fd972818452ffbc041e5edfe62ffbad08cb5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb89131650e1dedc7243d27cafe32a586fe4be28f5c3943e4d1392bac6b5c26f074bd037cc0be9e5d9478f86266e4a79f1138168f9e4d17c7a7ebf7183ec4a7c2f14a7e84114ae94b76418e361da09fcba62d8750ad8096ce2452f2b34c18d3b67d2c1e2716efcbd71b2e3eb63e8dd46897dbc75f7f69b947d9e9fdc840d6a0754faa661e62cd178765b5f0023ebcc63633e90f0a2b135a9b0785fcefb34c297c6f74b30f51bd96c0b6a220b21afd32767907ddf9a2e801a6c0a5cfeb16e85b7433ea70908fc8620c8fb79004d2883aba90de16ab26eb30bf25e9b38ffd7413e2f7eb69ec1d9
+TAG: 3f828a500e6c502076a55d73acc0a85839fd872a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb8928128f29a5a2d553b2475f1c901a6c9a635b8e8e6b98b302b92d52f493993beaea11a804c941c44acc8c4658b1c832a2e4608fc2556a23dabfddccfc741e944967621a1fdc94784749259df170750e9770e81d59aed228ed2e3d1ef919d84848d8c9e36c1694d01a5df18e7155b63c7185da81782de3d6e4939ccf526103d298e090317b19252d8a81e22d26fae95422dab77a05d00a34310e01d6c11905928cec752235139f41163c4bcc1719889071b0974ae1007c93a30e7d9c45e91e05a90624559b4e69710aee8752e54b1a34eb4b56c71c63ca09d420603b34090f2977a472dcf8
+TAG: f4c170c430010e32dc0341efde2c6345e228d0f2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb892792154b79e8dc9f1c72a9e7240fce384ba3c9cb0715651187fa635fb2c9bf73c1b1e24604082ce6abe30aa86c6b9c0288518943dc5d60c7ee481dc899f69d71ebba31ec46d42969571b8f32e077aee3f238aa43c266ba71ec229b31547ae4cc2a238c8cf107f22a663c7ac803af29b693b6c942f2e09949c8091b9b4f139bde40ae6445277e8a4b90c24517ae87800e263ee36daebe615ab69e1f322d8d2eaca3757b4a3a4d2c756385584f46269cbc75fd9da36949dee27598a3e20ccc931057606d3c25eac14fa9b2c1c5d669a0803fd5bef216f8e008157443a11593f965a4ef0e53
+TAG: 0a972903789a84840418a012afb44bb7e0d607fd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb899c1bc5433112e40d12ab6f772a62700d7368c7ba6a42799390fc05896d42b475a777b00294f92c0064f5f988114ad591561b963840c540521630ab5141b18581b74a6a52dcde7e9ac2bc12e876eaeec39d05b56a3a3d5b240dd0dc81dcfdf9099bad8d7c0c699822a6a7dfc2f71f344c263e7920c4cf7f6f8057ab3e30f9db03b4f6504be2dbc41690d41f667557361fcd8f9ecff1c5db42f5f1ae582e4eb7254981b26d6536a77b654b2e9d3ffa8fd7d8a6955bd1ea691db927022ad64ff680230fd9eeb0791f70e7418639f87a098ecf6371405096a067c1d04cabb3de5b5c40108c4d
+TAG: ed020dbd749f08e1099e5c89bdfcb220db1d3560
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb89193acec78116fe3ce6707dc8b64f8b6ba67d81c6f0dca0f5f4ee5c57af8ef93dc7e88514be7cd906a7b8cec9419a625dbf1d5d43ce1be9e63a17c7fec802a13e0d77349f3a8c6245254b03f112b15a6323c61d54fe5212e8049ca9aff3402d99273a8f11fd7545ad32b7da3b8dcc69a49159a7b3ffbedcf49bab8a0d97ab95dafcb7142c85586407bdfd47031931d7a514e92e22f8294d39b72005a0dd211a188a1bdc760b000ffea4959b6bf1950483a3a3ceb20d9a24b6cfe41dd8382385b4f52a07ef0cdb07aa3e339e6e5f8e26d269c7e8aac0609a1a78a462f2f14c961d6a2fde03
+TAG: 2d4bdfe974e6dac134f11aee0846472daa609f56
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511807f4ed582183c36c08361389878e2f51a25ca3c845380970f7aba1e7b7993325502e388b6fcd9880b5a64b80cd271f874dcca5bb85b1f1ef0062416fbe6db73b6f9217b63de2097cb90a8e5a331a871781b34611542a533aa5f8c59fd14b8241ac2b19a08b94124be10e6ae7c2365904fb30fd74ed16858d5c06af820ff88ec6f2b5180d1992ad49f63de732607c08453f2cc70791f102de85a8a5f07651202270efe3e2030466f89db7f6757718654ba63a680d7f1f14e260a07fd31c23129eb0a44bc638d180fd0534a978ebc06523d9bfea887c38acea8dab92f
+TAG: 3ad40460160e380d7b93cb97a3e2cadc571a081d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511f87ea536db2b9a63b3e142075e482d69b39f327f500844d287164120f58b8fe5d9cf2c327cd62e0a327232b53c901661fafac972f9b599ff18cba6479edf20dbebca867c3b0e22b5399269c8bfc6f4cf2d3efb00fdf62f5b1c826d24fa2e29ee7488e8d990105aa9fbf2a1b80a98de99349b7a7c3db571f9a68a26032fafd36500a33dec19b0bae67d42a89f27122904f89403e5f0e3baf4718a98721b7108862bdc093a075d4372bf704384b545ded4fc7578e5f96b2074291364bd06e75b2d435d8df47eafd05326add43a5e68cb0e7df7acb547c37ff01dfaa7b2
+TAG: 9f37d2f1dcbf06e2388fd3209af262d9f4c09c6b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511aaaeb557cdc5f7e0f73dcad3c2248b82f9fc3923caa84e5f866d6f2cd9d1790a2914410622e1869dca3311e986d1e69e540d0def5cc608a7cab4f07efd454296e1428df7f2f95fe5f830e4e19cd8889c0e6f3b17b5939c2cc08442532b7dbf70f49c424443cd161ebe6e1fc3066b6e21d960e8e6c61eece9f84858298327ab35391891d392cd9681a881b85b5d85495a173b6dba7aee7bb1ce79b74d4cdb4c724de01b0794625858cc53deb2cd6a25192bf9326032f065c88728b8037d4fa8cd246da2a627419a24fc5442f5f4b76ce86197ec9863772476ff57643a
+TAG: 3df54a6e3ae9cf48f33fd97b97facaeace482b13
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c1c5be45c2ee1c11d5cfb5b6033bda50ef1013d244502c9765c92d38b02e910d089b366a09b3758a061b9e1a3f69a6b4627badc27bfc284ea23bc72758246d259e83eccb82e119d4ddc8c72afa3f9c8f0eb9ca318d0fb69f4fe0d61b84a901bc6f020691ce145314f428aef552fd29be185e7446b8e2cbfc8b47ac74403b9f7d4f1c860ded2358e4625edf77e7504158d47471ad1fa04ad3dc67c048476ddd75f21130c891fa08ea5a485d5a0a1c2a13a457474454f3d46af9b77c816468d04e576daf19b75f035ca81e4ba39d63a529408370ea68c7a72bc1e3cb06
+TAG: a741e71f2cc769073ed4ffabe34e8c59d9c7f56a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a480343385111b660e85761e5f2721ae4ebc26761218c5ff082cfea20298001801ee8ff3549028c94ca45b381ced0b123bef1f0f9120a6a5ca8d99c512cbc4baba29caf66c8ff22cf64c471d22fe94174ee6fb473636afba85870cfa5764e85c9c77e1b7ffa40c5e0860e13cc172f979beeea73bd842c8b6d1306810ef9adba6836d281594e3599bf628c08a4f0f4f2b95e07d1d6d290c55dbb91e2f72e93a05e13c4031e9a8b42189833070da54fc5e3929a36a685b05b4ded81ac5a1ceb05067f4656235c0df03476645b01fb62c28f5f8555161e494dd3acc6674a6c98059bf46
+TAG: c6c60d31b8ca3ea8cc1c1b2c13e3cca4cc591dd4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511f9a4ee6c6d9c1a2e8594e62bbc40d63d86168c0596bcb1544e8f7a280c290a2cf3d1d45cf357f316e6e8cc3969f0ba7aea1d5424bc49db02033dd88eb122ba88e922cd0c350990b371fb78b4d74a3ddf6ae5ec5999c79aa1dfe634a1018b115a9111772942e64fa7ca72eb542bbd839b0fbb9d9645da1b78490c156db2321c6864ebd946d11dd29b59ad202b100418bbfa77fe54d975633b1b0ea341e3457a1da1aa300e8defe99c1f701055a746303b0a4ba11cbc057022bfb273fed2df7b6135ead316bbccae9b8be0096ce20945394f3ca6a47235687f05f1db03
+TAG: 1980a85565d1f69cd7cd66e39e2114a4594cf626
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a4803433851183d43afa5a4213707cc9fa4ff4ed63a14febb2e9bf584f7dc79e7c515e216f29111a8c2f0375f7728bc5596c33c3cb175f56f52cf7086366b75a74d40799614190ec4f195f41569a2723e5be0d0ebcbc137b05f3c9fbc7045e59e02685b5e385569fbee99f597ab35bf8e9277b9174643b7fab7b7e37666e526b24234defde99c6ca997bbc42adeb6ebf880d50b490adb9830aa006f9c8887adf97f2d97b11e46bd05c8722d1181afd90ebc65b5a0ce07f5783e49e3215a19196536764a222842a9f124729037415e9e65883497a15beec2d799a40b685946633859f
+TAG: d88a5bd8413831ce90cfae318425be502e9f3b6c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a480343385117558d6ffc00f270da8cc39a5c5a711c92ee8b12d29c406f2bf7b3c9e415cfde3357eedb21d7dbfb0450aee9a0100d88fc58174dd57aa1d5cc4dc7a62fea1302f896c81eccc56bebf5a10658b0568b1ec010495f06c1c0a9ed810811b3431ace3ed0a787ce33b32b6c8ce3b21d0797e083bd18b58aaffa96a75e35f89be3048cb26ff903d33e34746949f72baa34cefbc8247ff40b3227d1eec5147572a1d2fa5ff34a9131380555f1db3dac8111960432bc870e38003398bce2d7ad5172c0b2e08005a02a0c4aa537587d6652c5a0738bc3dbcbe63a9008ac0e111fd
+TAG: c63d1f6a9986c117ea3451ed8c0023ffe7ad39c7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5fe1d02ea5d71cc0aad362106f6e92a3d8508e4577d8a90386e6252c4276617ad715671bd302383c12be3b3a9501cc70ae0fb2e710bb905863142c103f4d460e6deadfbb6c7e38dd38d23772ddf2c64357da40d1b2d1a4cf004b000ea2fdfbb96b2aa81a38296fcbf3f166ab74a09452756c648f3ea016569ca0946253f3807e7dec71f9cd844a8a008adb466ba626049a33707368bf0ada45d47dfec8d8d13faee4986c1f12071526f01455b5b4c863ba71bb35d14049db99f8390b593e5f7a377fb39795f9eb1947187f45d2ac5e62cd4f7e4f1f
+TAG: 70d2e83de209912417ef02c5dee16ecd9542d95a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f30d96267d1ffccf7bceff0e4aeb6c74b74c927f3e2c0d3472e96b33c24481969a9cb3fa02f090226baf94149d33ad8f0be0d43630b937c18d3a23fdca40998667f3578ad94487f0767c57c401eace46d7f403de9de69202f7701451a214bcea95f32a51d5676cb9ad6cc467fc07e234e043427dbf8e5e10e1f5768d7597dea461f47233e32e7301316818677d975bb98230b6eba20e562183be72ce4617cb3ebea640a7c130aa9d69a5b116636b1b1e9c4026451cb0937eb8d4e1ffaf61dd7c6cf3494a09ccc1d7bbe52d3d3adbb989bb68623dd
+TAG: fc7ab570f94fdbb1191e43e339ea4ef30f696225
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f69e0559d7064b7010e4e1f09fbf55dc7cf7a9f7b5a55abc9b5ef66695c140677452b78c90a3386653e490d15c028f81ab017931d2b3e8361899a819c9a3aa0ccf85c30394f4f9c676b24f31c2e0a4065e4de93f512215cabf49429ec4674c6728ac0e28cfbe997c555fc4f8c3449d2982e652ee38724bd40a51421fd61a335d443e80ed7d62e5ab3befe4847f341931cf17eb66a9c220437262188558327bb1242067d66eb1e98390325c87857c00742eda76d8b8a39435ef330b3f4724bd2f5b84b0aa7f5fc4ed6c9fb26413099f9206a3bcf07
+TAG: 42bcda0cf20804d1e66aead9f61b9d5f4b8b417f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f9e3865772ea2e959bc69811d31112a1e5be77860befb43fe660db7b42db01f0988e5d885461db91e8f24c4a51eaeeccd99e8d7d10d61c381f0a9a82b2550e8a6dc4b62afbbf3f91c60da137502a53f2dd50ce68b269fcc4314be450868f419f329dc8b9894d82f540aaef68df9eda9c3dcb699fd3f739073a854cd4ab78786d91f42d0ff35de25d08cec1da210a4a88414c83306f51d478b91c9c6804dc6cc58dcb040c521f1b640fb95638c24e0dbe9e79ffcf3663a842ce95feef84c61a35957ac3534035a89017a3a78c4a2a9d280f64d315a
+TAG: ccd8d0cf987aebf25b7d4ec1406ac0490e595eba
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f9b0455c8c6bfeb0ec2f7adaaf9cfe528da3eb24cc2ba17d1cc8d7d0973b97fd0e987771409a602b0696af7ab89e98ebc798839fcbd3576a98dc7830fde52e23b31203b93288d035bdf6e2feec01791d97cba322e514e87e66fc33d58e3a73a963c2289bd6efcb2c9f1778d1a529622677ba8b68b834ef8e27e3dbaa95b3369dccc185c49745f51679e7edaf516a75ab7f9f8f96a81d2d06bc9d3be3347cc8543a057583a1d4b04e7648aa077cdbead05fbbc39b90cca9d25d0e6f738816a1dd8f797e872988252cb67dcc8b079488cb50deaa160
+TAG: dd2909e86a80a80c26dcee8f1c5a312e6f66dd9a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f6240f86cecd5d165674338b8658267458aac104a8fbe1efe5f68067389dff4f20ebb131bbdb01e0e2f75b5b3bee095a544bcd0f02c798b2888428e7c5aabb337fca3107a305911002457849e307faea4c522b29e64b6b4e26915a7dbe0390dceaf107643980023af9de9753eea349b8c159e10a32095881ac278a5cbbf7859ab6f7ee483a4de7abcfbdadeb9196a2ba78090eb3bc84eaf2550defa8ce16985902bb7f816b588036c7d051cd1e6687c7197813d9645c1684ce4c0b61816d970d4a17c379e851dc4cddcb00763bf8d25ca9deb7950
+TAG: 040ba4f9653f80db9603bfbb24d4ad652a74e215
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5ff7eb02d792e224ee5be0cfce28eaf55b39729d2c0f9e024629e949258854014f4ddc7d59335c7571a56c7a55d07739344896963f013ace12bb2f964399bf1516d5674bf1f32662ed1ef5762cae53e8fb527b7be3c570d14cb3b4e04d8d27c3cf0bcbed4ff96b45489112051dee14cbbf68c28be202f17a91b471fababff363aad6240009ee2a632194e400dfd75d42a847e1693a3cf926347bce7cdd9bfe8050d804f01b0d945f3e20157c26c9085116d41b8c79368eea3e6599990867a3d66cfc0208749924ecbd94d63f02af19fe076b07f50f
+TAG: fac6cf9e7560873f6eac00ca57fb8725712ee795
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f99c9340e2ac24a340682721bb2a062b37bfc49b9c022fe64330da28fb693ab526d52538be2332e928233fe94e4faf05755d2dd803d3c39793b81d41afe2844e87641c73d7103f61103419796dbccc802dd3c4b20fb4a751dba82ce09df5efc0c78d153d9b4ce6cb3b271f09a9f791f60daf39ec33f1b281c55db6a24b5b4656008f95fb6462a0b5db253a2a736ef75b04826392c1c5acfeee15f8232dc3811b899f7ded950ad9155fe7bc6ac423fc957d90328c4cfc30420056808c67da425c6efce1133d5bb6882a24ee6bdb1cf1d7b2f25f255
+TAG: f4e45ab5f4f94b54a807cce677dafb1cf01d3cf8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a00a9597b80e5d0ca656c940b44234f86efb6719e6ee48ed06e26c7fe81e22faaede8c73efb53ea126b64841eca476a51ef9ecdec70d20a53507977a493b5ca89c7bf397b86662b69567997a8587d87a278eceedca10e8a14dff152f2854b3372ba1c4834838ca5559eb2d53dd076e48435268c5fa9ac5b6e6c4bf32915192c523a9eb1b4a622437677f1900ba8fe6621316062d248621c530787f3717579c00d331a9c8b1bf1db8f9ab01364b2e09d5f22abb620a0d03679d05147134027c13701388832713b42b1d6ef1cd2d
+TAG: 380138fd089a862cf978b2e030cb706aec4fc42a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f3992e5e591d575765d23aa1a4f1047767d782413e53b6f42ca1981b033f13cb77669bf5f5c58411e17078f1ad3fb6cf13c91369f9363f6559e6f45f6141d3598f4380e1fc644f01cf53bddbc3583b4909d742f7507f73defb3c70dd4c7046a798f458dfa27cc1a361cf2421f3aabda339e526e5af0f3c10479325ba11af6bb880daff0746c1395b9118bde76669aee897bb119ab604a0e2b6c95c3ca3fcdfa7e95af1c872b7897bafb915cf4a25fd90f9e0e6f0311d452d259f1e3cbd6b248241f4e918ebf7b60ad03d5f20
+TAG: 671b3ef5b743f19187cd37d7ffc5d0232a214f91
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0de8f2be46a54e396b9b54767da65bfef07fb52a41cea09177ded243eaa021a0f05ba852035897867bb0ca57812d934378407335fd909e7cdcf4c7f8836cbfcd18b5dedb8c58b51d154bf01170885dd1bb92f777bb2ce1c8cefde0a63900371db4b633718c9fc8100415945c6e29ede37e27c64d948bb0894bc57bb13973f2ea0acb604e7f613fc7a57f8669946e4704837d0971b72f4841e0e0964709c06f229414c028b8c607f74f63650dec606f2b50775348dddba152c7550beb99907f1776aa4a8a4bc4887dd307bd549
+TAG: 8c431a6e868d0d2e9520940b34a7a03df32b4bd6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a05c9c11539c8521f19879607feff32778cd94c22c99f9f7026baf35654a9e7c02959cd8eee18836255ebc60a62d21f6881be665b19ce3841b8f549ab3a1958028ab49369c500b818eee52b5124cc28b66dc0cc6c1b0c8563de99e98198000c033ba515a38b796d417896751df369afba9196422764ad1896a17c940db871103343144c34d750c87415ec59e5546a19e6f51619054da89e453b62a34feb715ab48230b248d6110da0d7b8ad187db2019d9cc974c1a6b961a252f8470fe6e2c9cccdc028c1559445a20840f6966
+TAG: 501dd1de8c301331fe54394e3dd5c7000135728d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f0124e795a8afd683243db01bdf042905b8c64c9a48942283edd0e66b2566570417dbf4e7cf3007630dcb70c44f75b861693599eba5ef5845032640ddaef5962994afd33161aa2bd5ca28a9dfc3521cc8795e0854835d0b0df6f79002963ff3034fc6651e6b0a0a8625b0331f65982a29e63a8d91a22bfd58ba9ba061c8c92633008df6b405e0881a5073a07ba23a2b99381f07f735b176841aa1d4421ce53eaecbb73809761852197ce292043062f03c657e8b23565c8eeb46b793f603733a4e96a81918754d6bdab70fc12
+TAG: 567d46999aa4cf585952d7d687e84d19a39d6009
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0ad76f9621dbf9c52084eafdfcec0f2f8214318159d474da8bb28bf54093a2bbf3a541c3998702271f697aa622b5a318b098e07e74ee4b4c1d02518322197538972c86c35f189bd3f6d20d116642eca96fe41f56eb8e3ae4c5dfa9f225285da46584c0d687908f2f3a3246c7786670b9713c4450bb71288b0cd0ea7680aba0a4b12f404eef567de4e6717f1f43f58f6ee2dba0d42905df07a1496164f391d806f4f766d89d802a38110c384f6f17f85886e7d922b0f77f790ecdcaeab48f4831f5298aa47c9e9b9f800b77e6a
+TAG: 6106bc4919e8c1d05b678f6d4466de8a949ce587
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0d6a4697868dd468b74ea078e394194ccbe91a277e167a37b725052d2f90f003e15cabe415171a765c77275057e354f2c9dd17066d4d8b620443679a44b77ce9a28fd6cf2b991825531780a2f0bd45adcc82ea884b9c6e1697241b50695d0840f56ef2b9fd97d54f78913679412b247d9962eaab6147f6da0aaa9549269d0efb0f654f7adb664776005ed94e56dac0c34c42ed157ef3fab33970b8c54fe485533546f3a52d5176e1f71e7c1a2bdb461fe0d3e01d03d632ec42248f928e042aa5a06a1b3cc264e76ef347a5eca
+TAG: 05144d2bbb835e38f78a0a334e4aa82064a1813a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a08332cfb2e4a484e02a92379ba02a5466accc3c2574879c2599c8c47ad8a984fef6df8612534d2430155233c7ff01cebce0cf7d1cbf6340a2c2c64d52878918f134af11b35e0c2c2dbf594c49a30c70536491524ce2f07474e3fc16bf5888ce3e99be18f5fb8b74baa92b554f7f6384a9ab67936ee8c7c0fb1265d5a4da71bbe301c795fbd7a1c7536e8d93801d4d6827e53cecae91dfb44c0438f243e08563ac695f65d78727cdc104998886b599f1c542dc6a82cad2a35bb50f95ff035054551c3b60596778638b56103322
+TAG: 66b0b1daacb41aa82ef781bed4ef37e08c5fd43a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2335c7ad8106d417fb576f620bab4fdd882fc231d09646d646516f65f9b00754f8999beaad999670676b7c903481b0d5d9f09867a4b9c4f03193faf1eb5d3af9403527f23c887f1792123fedb3940b9869ba9271f77b323693329e8d832a7853187da8506d8799e82c7e11d594c630fcce22dd0c06a107a5245209fc6148db7694014412561f5ec57e575fe68f4e5b0fd06b7179384e47a1cf8585f9da24991bed4c2bb84b2be5d55c63098f7684cb445871c8b42ab4e21c62724650705ab2640c5ed96cb
+TAG: 2cff11f2819923da85706570f076cbb185791719
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2fcff56e88c7a78427697a7561b0216cfffb73486c0203c66d56c598d58cb60d81c5ab1cba1f118212c70619434ddea8d298de3e91ad904b906377cc7df62a546e8577032b5d838689988f3afcd2a0cff3bd56726ffb9c25e5267550f67bbc1de3b9fa25e90e9c02779f6facf863ca459e80cfe9d3588922b7d25f524cf05dde0e1eac6ab190d4640c3fc09c77f6306f51d82b2db904403fc503f6c828cb1a18cab3f328ff0b34c958a56d1cb7593a473d978153837c3efe2cd148c58033fd41a6b4c6639
+TAG: 0c426f6c8b1f50364355379b91384f491cb4a3dd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2b868dd7fe995e693b5da1c0c420e80365f793c80208930bcc58557c5064c7539c7b6bdf9f182e602f8df269d0c314fdc09c857b3ca7ff365e1e0a2d9326f54204e5d0376bf8f9c9269e07b993997a323d98cfefa3a5978ba0e8a09e882227426a9f2f4b95c7ab4f3f53419a691bfe88006abdf6363a90e8661f88ac9363ad25e72ffa5a2ef41563bd4c92c542e550dc4b6fc288e302b7c531720b0306335940a36ec4496edbd1766d74471a1330a532eda0d2cca9aedf97439b8dcad8a0b3474eea8a92e
+TAG: 954e5ec6a5fc778461438c723c00877a86cd126c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2520c208c25b4817c56feb4328d57aa7c09f65f253f3c7bb4a955397911bd7068df38678c8fc95091599742ddc219025aa329b5de5396804555ef1835332ba057a04c84233f9fd9e89a4575071efbafef13fc5b87d0e76e96ed992a559e8172c0f1f9251d9bbd2d6eafaccb627ef2a9f799f580f30eafc183a23f31e92b6d9aac38db4eaedbc72c81ae4bd55a60ce964369d9e0e68b9ed7dbbfa1762bbe30de8d90d59cbcfe6f1d5ff78cf60a0bd12d1849c459d8e8b0d15b4d1f0aa7d47b7b8e51638e98
+TAG: 953ce43acef454811bafc4312a221fdfb893c2fe
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c28bc2b9d203773e12f9cdde56e0bf25bde8ec833f693f803ad998f7b097b4163aa3c830163f7fdc1930c3f277a147310ce7f180106bceb4d7b29dceac1a3c7c13e2f90777891a57234880e2f491817c205a5c8d1e3c447b06e95bcc0ccc0a07147d46176335d456f3b06ffc200d3ec50ce6377425d4e1b1942bb608cb47b743255e4b4ead1f7ac73e2f507866e5296413fa9af67138850ef0464a6d5bae05f9a6bdb65b0958e35a8274068b9751e31afc7ae278551027c5fd3f5bb4fc9930a86196200cb0
+TAG: 892884469c46ec5fdf11d78208b097dbd412c71c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2dffa2a0fb8e41d477c9e826dd58dc8132f4430cddf01aa00ed08890138d7dcf14aece6c883099bcc4dcf0a78cd535d563d9cc5ad7a4fad1160b2cf5e124762bd5811d5407820fb2c067bb119d08cbe9e940967e8546a2b2f52ebc5f147640cb24fcd53c7d52da1931a62bf80e4d24d51899a2658e98c51fd86950f4cc2dae05a67f17ee5058f832fa2fea3d7709f168bd67708f3b156df597b55f2832d1654417f7e08caba00b7d4c52f2ccc76126255f419d9ddb89e3921765aaa357523249bb5457589
+TAG: 01ff6b381eef5cbf9b63812e4485a692c95f3c64
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c239ea0a544fa6043fc935477fece39505eb42626433768eed2d851dc40243a4b80f657e0d16d936dc7157051ebc34cf1eb2e60b275a94d5755f2657d332f8e3f096bc7565fbb05e1144f96e97379afe3909d06627e01649310455f80c700947853b5e636e322f893ec6765dd1cc0fd501824be3a5c8b595317f89ec6429e4a182bfbedc37f560c91ff7b956223bce8628f6ad87135c7f787717d768b1be2f05c5e4797f52bdcb14aecaaab6eb5ea013348e2cf943b0342f695a84f4a2e40bf5ccb339e819
+TAG: 096df9197f3455358cda1ee879c6d1c1e987b9b3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c29921ad8849093ff37bfdc384baeb64307e563990bae6243111d71081a2473dde5bc6cf8eb45ea9c15f619d8387812928ea352548858cee31f04e9252ee800d69af681e7a33c902f4f25c630b6e702e0c05b27080297e588c24175bee66c9650f346b956ed98d25a33545a7b6962a70fc826fd78f27430eb3654dc11084aa1bcd1d7f6c3f1622d9630479b668a19f2069f426858262abe4c92def678755864cdd62ea20897c6b8b6725be336b8af3b31d9c2c0b659ac865c0cee5c62c902c9098cd1f9652
+TAG: 1737add98f8de58cd07947e212256e8a7850c35d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f1648c99978f93cb8cde6e2fdc76ba1f1ae88d252b6ab015f37688cc15537277f188fb344c8e1d48b0f7cada294f9154b14e85686ceffa39e9b4458678f34e8e4ea74518e48a1da4b9e90da3874102bd38074bde6fac88844d350c4059747a199a3416a457aa12156faeaa98cf39b30981f718674b9437432540cafa7f3696e0930939bba2c2eca8029a5ca90b1983586d199074391fe6e7a8bda4350e295f8a1487cfcc090bd55ca77e7ba957eabde606ed870e871d08f040515a9ce774
+TAG: 99d9f15a709d41f81382855e2ac9ecae46f89a30
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f16407bb1e67f26c24c5b76c9b0f8ceb80eb882f7fdefdc2c9b3cf9719d9e3328dca3db175a9d3d8eaaf09a46a787e73cbbb8d2e7a4077af73454518a1259916e50bbc950a91edcc5bce7852ac3e9c23c6180083e395741605ce3f9b918825dbd1cc4c34c0ed50b8da4442c44ec32cdd0308de70ca37f697160dc5de5f8fe8c505036f987ae0803d7f58b320619fb787853ca29f0d9c09c2f7fb025a67931048a235f0da042b2025d9aa6d641f73f4c1ea4306c2963be27dda0cda70e192
+TAG: c3a1299396a8f00bb9c0ee24514a51ac62e6ac81
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164dcf8c6bcce17ec704301adfe456af37c5de7743687450e63b7b980edb15838b594e77a987c5b8375770ccb153a1b472fe0ccba5cb1f988bcf589d29a925d01ac5d2402dec572f9d35bf2e0b50a49c1bae72e826d9daf36eef1cd6f867485fe4e4be3198f03a1994568aac4123c94663d7ff48bd455762233b2e73d9d81b8590d6f0d5be7a585c4aa6da67612c6453861c856f9f84ba6f00f594d2af2aa711732a48aaad84ad7c010473b2537cda95d1e7780228356a6fa9d5a7407a6
+TAG: 63138cb1e79d971c06fad598e407e6fbfb5dac64
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f1646ea57e625ab814a228936657806007d85b2f244ccacf61a2b789655a74c5679d7ef9a0e6865619c577a397882c7ce6ecc51a62c460b3814103f481d8ca4124256eb4973d7dce3252d0295f2572bbd7b46438889d9af6a8e9d0df0bc8bf17cc2dc25239b4fcd305cc0598f8e533485f0a8ad9e6f2b3b9613efd96bceb54ea01a2e55db881da573ef7ed57b9c4c46c9ba3c4309bfd5d380396b4c19f4d009d284cdec89a56a7498d4508cdfb3b5dd312f9403149bd4fc0871f2d9b83d3
+TAG: 1b2ffd8566db68d65d6d2b15f7a240900b46db34
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f16443c6b0a7c0762823d0eaaaf9f0d88d6afa581453e481c1c9ce394ea56673587842249ec32c20c469f2aaaa07234a1d33e7117d3bd9d83442daa37367a8d98da1fb6780c7e6ee1b03514faf01f44fef29e3da72a7ba20917639a58e2512f2b9e12531eca6c628f4aac0e4a70b681953499b35b4806f88236009f3f58e6d4dfa7f12d49ba138f1e536da02b1a70e0120a2d98bf0ad101660a9c67cde7947a21e41d1b429cee71362db19c1221bef0b40e929b9b8c3db78f67034bd1e97
+TAG: 7d3e6c38d4fd8658f2a3c020e239b7b61c4d0715
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164a8990e32e48d514dcb895568691e65b764ed29b649a645504d653244a5c93c3b312eaabd0faa8320f498507b18218e7fe06a182f38790bda2bd4664bf9c1e2ec2acd53ff99f87a8915dd1a137a8766ffb38afc692ce11bb5cce1f2c45ad2e1b19f6b2b8e876a5c595287c8b97bfc27a3ae27d3af7d0d87c9f5cb0020c9cf5b2ea6bc59d6cd5ad836099bb653d6c4290138f8657110061066f157c2b1d4ab248747811ab73e123f3a2f634438b6bcd25e03e27e19a89ae9d5f1daaa38
+TAG: 59c358557f7292e34da1bbba763203646b920feb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164eeb47662a229520239ad334f905248c416d0315267bd2a434289108fcc7184b6956cada441100449d53729395df3d67ee56ea63161e83974f901121e25f9c9de1c83c7b2c7f14087e043bd3d9e656f14bac1c8220d07b80420d5cfebc3b5a942b0c938feb1d2e5d12478c7ae74a4a82e571b4842e7b56fb9a1a908e622573d875a9da29384fd007ac1eeb0f9fe93eb5fa2084a8fd81bdcfada33e092105eea7fdf1449ad3c1966e4063e0e96629b761e063a679feffb3b0440160e6f
+TAG: f5bbc07b89e829025d0f717107f12e62a27d9fa5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164c1c4d0802194c641e678fd6b3ceb6b68b238424ba08389ed546cada5cb1c16e7a72fd6ff1d52aac73a5b85d1af82bcab75551bc840b4e0357083e02d2f529e794400ba7ea1f12b3ed3d3092837e256e12b771a1a5fa5f0c8fcb03032750baf3b398378ba3ba09d5ecb088dc48b3e00c3eaec0e0d294c9bd03ea5785b73b866e335ef546c94751625abe3bcbc4afc1e498c24915c352af9a3fef2a0edeaf4a036b8c94bf8a0ddd7e0fdb708cee4514ed9e737b10ed543c767604a8229
+TAG: 2f4e8eb3c30d30e92f2db712f7f06eafde8ca1f2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e59dd30828d6ae35c2a357ab6fa2211078008f4ecff5ae2d7708ff6ebfa2457eda478127859a81cdf686b260ae8d0082c57e1948bf5712a280517714fd4eaf50eec4ffc3da77fdd69a5f9676ead4f239cf2db528a16ecd9c42e69d7199e24440b93afb8af6fb8809c2769f4478f49237f0aba57a15546964b29a243d24c85fd3f48d21121f57dc2dc1c97d1ed4202a2b8beeddc22cfa2329c4f7b44a32d818172e0eb83fbbbd998fea45d569de508f20a5ef23e25
+TAG: 7a2eb9b88031f85c9306930a30b2c9ca930d0c13
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2ef4a87f9571a196e37c5c74051f44584dec24dcc7ebe152fcbdb7772199a8fd34d0b4e2a06e9a6966d8b17eae24ff8994bbf26c0c67204f462909cd137c383b21993466c0154f08454c546babf174dbfa9cc944fc52e296d42f135e562f18a9e7cbf1667b900f59f10cc2fa2437b09dc364103e074b9a3b9d12401f1faa33b7a76989dccdc920304986d55710a534f4d1e3941e6561b7c08516a32ab4b2f89886d5cd36e11983d64ef0e435f980ed66f64d76b511
+TAG: 6e70e5ce998a33687df442103feb026483183ffc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e44f9e05ffc01b8538488b0b6ebd53c543412b8327575c2cc84b6cd7b97954169fdcb907176e4033c8d2097ebaedd5d6fc48a2ffc1df6e0adb028b1a8b47696c1550c427a5014ba1e5826a14e7634a0dd48a6bd634ab805e7d89ebfd84ca3087ada391bb148073f0075e5fdd8f4fb21b5457cf7b4b162ef9b1d0d0697483a5dad0b31ec854bae517dd150187d1608c476237bdb7b100f93b6dad7e4ca10e2d62a01d3eff5e38f67b30b4aba71e592ce9c6e7363c5
+TAG: 457fbb867e1baede32ee100d52762d49a1db3cc6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e02d250cc708920bf9d576207f06bd5e4c03a5d955d560941659445ec1c9b32cc1291b48d0532cce1a9aef190a2fb19525362124f250c23e7ac3da61aec71b444b269da0393cebaa7d72837255e3f1b76b73830129ceb0ddffae04b19e29c16618b59169c4156eed67b88c98191c41d54abde55793dd595be00fd9447f7377e33d20a8d0adead844248f26f4d74087910a68d40418679c5736e865d23d1766ffc374ae0b74ba2e082409e7d9e693dc3a812b9eb13
+TAG: ceb26ad268873e23273ffdedaabee0f8c8cc1ef3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2ee7172e7387dcbd2baf8e2f4966172b09cb0cedcd5114329f3791ef4aa536baa956182020eb5f0fa6f9781b7b291d5c736b4c18909af76bb006476be24317cb355fe745ca1d7a5bad32ffea9eba91ecedea94c5287a119188a898fe65901769368808e8ccf664c85b7db25e0efb7e932db31b6d81e283c5dd967592a07c04a0ebea4c7598f8ba79e931ad211408001bf619828ab6694003e6b477cdd759a7459f6f23ad258d59b83c18a1a3db96549ebd4b093f56
+TAG: 62b6359e97be54c43b9fdac236c055b179afb12e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2ecb4de59f6e7fbff3e86f2fe7cb2207d786e6a3ea05dc4eb79d20901ae3cc9a68346f76b7a0d7a580cffd8a674ed7e938b841192b7673f4c9c5e1cf8c5607438c9a42d0afb4552c2d98301205e3312b6da74982e86ea3aefc56dac332944244fa862d884e1e32e82866f122d4db3d1cb20ace60bb5777b9c4a57905c916ded9101ebb7756762f86fd148ade51e30baf2b06a2b10259f1f5fa103442237ea8e9bb134165c6d8b243f07e26190d86c02863f1b55e32
+TAG: 69e30ec8100f3e1639f2303aa7b2ffa12f486251
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2ea62b4cf0aabf49f3017c4b8e639fd06aff435b16932e49f4ff0db08c34b4126f1515509eb999873d7eab8bc9dff31e26bc358e84b81bbef8fb074aaaf70d93b584b90964c515897096a58b5c778661d83acb9ecf569b71b7dfe0ffb45d3837b810b4124847da506efe326126c5dc65c892c61dd12a711562679890b4cf1a5706e98609db2d5b8e7889fd6de7230cb810b5923eb18cc0b0a21e8e4b8f92b11053f44d792d0e99a42ccade44456c9bf76b10dac5ed
+TAG: 8faf9d451f00d5a11f0a81a72094f745a8b0f2c5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2ed552370318c46f00578ae2d7678749b8b6ef257bc525b3bb3895af05838990810e69e42d6493a2f9adbd340f35d4a25a1ba752aebaa1a16161ea01fb98dc0de397ff976bf4bd2639dcc339efbe71cb33274df1f66dff0145d57b4f54b7d2a77f3ebcce9c5e1f47fd01c7de4827a3bbb19f1205371530d6f24ed8debfb7f71e926d621720901df8ae0a9f363ebfbfe48229b582599076ed426d8c260466f5937454aa3941f7c058e74366b3cec40151a59f4f60b8
+TAG: 48d98671d4950d16b3b011aed13f3e45f656d960
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759f2fb3be80646515856366126ef31e9c1211df9622509cf13b3bb4b15bb334c2f7ffc62feeb5225a546282083ce7da3673b2e532efc7e141b13594fb1622e750a65abc31ba43676f827def6ba9510c15e4eb078b78b8687c0db88a0bc9ab8f6a66e740f04696c4275df9027fd080d795384f04f7be8e3299ec422d226650279e0184c058ce005ca728c5ff6d726f2df3fde3008774b5231f07da2f392c3a37b70575fce63d3831d7901b60cf3
+TAG: 9e316d121c857d3b9f430aed2cab4b4f831596e1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cc7b85b7aa0a5e2da837160dff8badd305e8372ba179833a127462078597a90f8516bf1b0cce6052908fdcc8fcae98c620a27b7e18491a0a2f81c1f0b53cb4c3cd34a5683d4c7848d0ae116bab016192c35ff25c6b4330f0df83eaba2db28b0d4c919ada31855822559c2b321c1c1d9764c6f5223660e69f89b3e64a68299d5daf7100c1a869653b007fd8f729da5a702e018273dc642028bc3f83c7bc06c2f2067b255ebd31e9bf8f5d474a
+TAG: 81428b3d745db5d6a9467b9fe4f69f5ae7f433ae
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759c678bf5ab807d67e33788e20bd346ea19d3c4e16c4fc3da279f9c1907391ef83be435b8261962bd71fe084b2e676f798f8df800b371d0560cb8c2e2fa73c98a1361616da1ac93410411759ed6a36142308829381e35aa5824f949d136a57e5926791b37309a7a1c5122655074b54782fc295f83e9d8bc22169db88d8fa69b53175dce6db703f807b9f07fd9949ccb8aa14f0ae989da381aa890944e2d935eaa4acbd8dd595e90b15c49b70b4
+TAG: 1ebbc4eeab2447af95e8dad121d746a561d65f5f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759f7f28b0a68dae13c61053a069731d990348890a517b35692192fef0de54160d4e6c5abb7559db9ea71fd2516bf9cf68e98b1d43a8cfb4c0a778238481bfd5c225e671083dfb831d557fd9869d8d95911f0420e9b1cb77e982ddabf8f16e2dbdacad88c9c415dfa1b069e187c62978733dd66bd3a5e7ecc65719a9884e2ba04dc1c9287ea66df2464d5f33cd9f905a3bdc59d0389a415e1f4bda0dccdfd6993b4027d377f9b0d453561064b16
+TAG: 3d1254db49a0cea2edbbfa3107b5aa028173b1c7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be87599803fadf8a0be2aa35195c73bab74d925caaafeb2e3489c79e31e5b400b813fb0fd7ba28f8640f77e333bcc98d9575523b31e5490cec1eb7f041689bf1cbb9f8087ebcc3484971f0db30fc638e3bdc73a090a92b86d3de7a67895f968857a348d46cdb3ce2768ab74c63cf9f311f6dacae52257cc84113de3b4a02981a819b4f37beef06c04d8b9dbeaa0a39d76ee389e016b4b24e6c638c20fb5ee8237c6f9f97e03cd8f0b9a9f9270f22de
+TAG: 344423d92238944ea3da0c1187177dfa5230ca7a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be87593a4437579e64a0367a8e18f72a638baae46f50d0a969f7ae1a793ed1868b540ebd50e1396b88d6b79110a692ee7f72acb6b4afda4637a6a0a6e2cfe70d4b7e76a7e23f93d55ae44ae7bb2fe2d427ed99a0473e1e31295d918c3b08d37104b8b4393395e4cf29ce03c72d875acc678f898ac3474ec89bcd61ca1c93f28c80b2585b77c350c4debaa76dad64832538717daef47fbf2b3df9cdb9a9cd52ec99722fd3d9b5c561e229b99e177cab
+TAG: a11249662f44444582c99a795c641587bd640261
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759dbcce273d56fcdf00b9c939e26159a048849debe0d617523f339851dfdd17d5bbc13324124da6f9fe00ad4dc242a8d7faa4ef61242d8fff2cd0aea2cceacfc4a5b9cd9483ed9ce423c77fed37ac5c50ca497328067c458c3f496cc7ab67017a9828720386aedd23d7699cc49e50ba829cc151e8af2cdaeb989c8253b800854bdab04e711267ab4db82b37e7ad0b056315288ce666686a487338dbe044eb55f03d4e15bf554e96b5f7f3f8ed4
+TAG: 71761044f146b34325c6d844d4eab0acc8b2c88a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759a76029eb6e1f70a4e425f99244515a76465dfecc98be2f09cabf5d25b0b378586b4639737b36ee6241be25ef1a592f0945b7f51c6ca66ffa23073cfd6310bc9b1cd1666b6860b6ca186053cf105b99ac3998cf17cb7ba2a7067ab35e23322194b791d658f3dd384aea9d14a6b4d37b1c600db3f9fd45b9e12f35f6d35220e4a5083fc875b9c10ca04f00418ad19baa8efc139543e178f3738a5023e874ab3bd6d2554a4644c4a2124de6655e
+TAG: f10fd173bc485c8e6286ee169d8c991c2a274238
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4044671e07035988f0f4a2acf8a02cf35e2e27d81ef50be3e45410ec4abf35c695206beb697f8dc9454efed1dbc2f452a516c6bde9d940d9ac7483f8565c431d093a2a75dcd464384878394a90c6ff0e529f1a1473cfa7bd44be839b31617dfc9cd814c4ada4349c8f3a68a70a21392eafbb747a5248f35d00c1adb2bb8c9af13269cb770d943394073dd0b917141f4b2699345349b85604e57e2f939bd8f991790b4e15825
+TAG: fe1d96432e0669fbc9a4af77e16b1bc9cd56644c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c404cf9f4e459f964da6651f0e152d686b43be858dd6d8aac3b9db03084a607d446eb8baab07e97050fa5c96e96f19fd7b18a7cae7e3e1fbd8ff3f41f72ef67ddd727c26c4fa446a51b9b960cd1151287e89630403dca57e4f48e8f3d528c3f5f5f91eccef4b0207b9579264f9850acae61f0847cf8ee2616c0dd519019d41ad08c757352e2444566cbfa79d5539c17f85fa08db8947c641ab1f1411f4524035faf961e7c887
+TAG: 59fcc9505c1e54f8e7732d5eaf1ce865b1a666ca
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c404c64e55f99d3b5dd083a5cd6bff5fc262d1f001d44ac5d8d756ba59e1af6cacbd5c9094e57ad8cacab6ff7db4b24b247ac0592402a6eee688a5639b8f70360b51c9b04aa8ee72cf850c6ff6389b1cd15a8dfeae72a0ba5a2023a1a86a95f9f2c8e072f295a341751f3f6c0be71449a0a564d9bc244313742512a17bdb3a554a1587629d55f1fcbcdbdc7a28d9a30cd20444afe93eebac11bf8d3f7bcae79aecc7ba5a7b4a
+TAG: dc8a7cb848bdd84f9b0a4cf44895c3f115787ce5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4045d609a3c9763d658cf123566ed12075fb7028704b2cf01824756607dbcadf61361759d438ca3115852a19650152a21780eb23b4ea0dc613ff9d521cc0f4b3e967b06faa9fa2b715ba7d10c88cb1248b46c61eefd2782e349aade2830ffa430b5b379d74d0fad001b88d6fe673099fc510d81ad19234709e1d937ec0bcf3b3a09daea52acbce311e9f24a28e4db2e3f730acf4aaab37e8f0d0fba3399b77b71b56a9141f5
+TAG: 750300930eed8657d7d2841878c34f2766d9b95a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c40410425a2ef2b12bf8c41cb3d4ea53a4aa876121e271ed4ebbe82e129686bf973d20bbf624353fc6544a2cba5ef37e8361455535a85fadccad309201c36970900f46fb49eba70bfcce285888cfb430cb1b0d264de9ee99da45abaf5c700b7a75cf076d37fde09d9e0eb5316660099602364cbed4f38e36369399b135d61530539196c532d8c583d9a9a86dd2c63cfeacc5efece26a7ae5bc22bfa184983340c1a40ab04da2
+TAG: 617c879bf86426bd7148c31ab5b03b12682d0326
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c404e5e9db178786a17beedb60d9e5a53bbaaef2c7a3725f213f81d6a784ab7551ecd42ef477cad7411f49d5dd4ed0ad112a698aaeb3d647fba842ccc9192377df5e36f2908d3afe2cbc8bc6069d33fbd99f85cf829a3c4ea3335197f924318676037c8515e1a3c444490291b2d2131c5e3f8e0e225e889d9573d13a4e222e67d383aa88dabb02170589eb95338dbbffa584ce1c7f82087192e59c6fd3d16bb6e11b1d443412
+TAG: 366b19a9bf0d621a60c25326bb2764e1dae1ea1e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c404542975f1e267d7243125aae8d7aef3d1dec1049fe6657d7afd197bbd83e159342726c9e76f8635ff26a78d2b2a3d75be4ee992a3234cbc0bc8ae33fc0dca036d78878d39af8c0033564858c146e6bc06c35781dfcd238e14d02d7b9e01c6bbc0b08c93db9dcf92364e33074750cedbe5fd5d338103cbf069f6b4f039a419e99c74ab78ea26d20326bd06a39fdb613b6e17e79377b5eb10fdff779ce26e6b845b3b87767c
+TAG: c6d7bdf9dd6f050c6aee0d572e0c9e5113867495
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c40441451f11e2c0ba773194889bef70d3a67d2ad3630d3c28d1f74f5cef747dc92e0b0e5f9e31991830a871f00bb771eb7d0613b9bd26ee5045266421559ee9585f91cf5fd76afe7e8afc9b12af83d9afc0f1b7a1993a9e96d2e3c24d90d48cbbac8959b8999f3fd012cfd0d0cfe6c94bb3578b816472cc6cf9dcc0047e90495864a5ca328e85ca5eae3bb2c7811c1d15ad7ebaf6f360a2f41fbcea14e40ffadf23cc47c1b6
+TAG: 071197b871bf25aab6443ef40fb0514bc43a3a6e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3ff1f3b81c076fa740f6768b7e0291a8da39a631c74cba37b1c24777f9163b64478871be02bd1495ff9f228410a5634f95e80d93bbd007f009c47a8d421b48250202fb5d6a3d75f59918d8fa51c4b1db416d40f140a0255a717a89f8bbd996037f2b1a07bb5f3454ec5f3d8dd131f0befaf2a8d23e3114bcd8b4aba50909086895ae95d6aa0fe6024eb1cc7709c0bcd6bfbce6354ba0035018265ac518
+TAG: 34b9ab757f1f9b37f8893bcff52df559d9b29c19
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3f6dc7f25e05fbf7e889922574bcdfbabfdf05ea260ba9ef94890d9d4b4a5da8b37a50a5a24a46e95951e1de86e5590655fb073ff8575bf29a481322cbea58bf06ef746a57118db8a29994f97258ba9bd74739d8bc67fff635ff72506ba6381332189dcda5b0efc2f65bc2fb9d53508a29a1e825a73748200664ba6556b8c3d076c2f1132ba0341610d62f974e9771bda07d199ba4d4b236f51d1e4791
+TAG: aa84178a257b2d9d8898c430681545ad9dec95a1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3f0e1887829c895b516cfd348df6519c54a4d1070de1413a6a474baefae4fd0fe4478f2388ea74fa8c3df7883f1bc4b1f2cd39ae35739369e8608097a2d2c01c724cbd07e24c102e5eebe06c7abbbaeb3392db49484dc3f6f7ccc97c71b5e43174a57ef1e6b9a5eead26560054133c0560e231b4771e8c30b0c63f519752d6ee2cd01f077c7cf9e1d5a672439150f597d14dc8ef31c3eb6237a767300e
+TAG: fa48390a990cb9781a2467200013102faad9846e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3f80b4fc69133be8608fd585f0770b7b9b5f3905ba438f253705e779b45e46dee137c48b42ff08ced7011f439d0fc303163ff8340ae4d96a2c7ecf9e8a064a78c7d84f945de6d0a712a34bcdbfd92774a039d48c6c0eaa69447a615a359533e165623d71b40102a2468be2f667c9d51e905b70bb54d33c2a1a1591f1112ac2066478d6ca3eb9f688c9297102f80bca0b0cabbc3f07a26d57db59edf19e
+TAG: 95b86087e259740bf02493784a2bca08d411e699
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3f3423d3db5dbc9fd1472e8ff00781f18ca07ded16730cf8e6c937e1d5a8c75e7c0570450cff956f66f64ee6b55c3caeb1e3d2a86b5d913686e976aada69a7f02d3afbc67524448baa4d11a7b5db8d3fae6be309fec6ca7a4b90b46f49e4370349ff6e288084ef961030f07eba2328e686a4dc74f67b924d2b5bc98aa050fd4431aacd42cceea481d85b4b13bdd0677f87af59405819b7f9ce4be09683
+TAG: f406b88e2da3a29e10534ba2b7e8ffaf061206b9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3f0d797f2898b695fe1e00ad1c82691bf17e5020e578f89122c46757a8d7297ae0265a407cd8c75cc0e3e236e744b24bafe879802a1331d43dc9750f33961a2195463dd4ca2fb5129ca93a3e189dd5d0ec9123506ef1652d07ca23a8c45997985f69398198b65239ecf6da62b79b1fa23bc89470304848c9e73ed4ce6ffaded33285a17b1069b34df5c8819443ae56639784c64fb910b2f66894d3fac1
+TAG: f01384594f8d12e010209f2147df324791f2cdc7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3f61ef8b3e9d1ffc394f245dd44265bc5c526c712511dd5d500409985353080583158d0b31597cfeb9b95da16a97a25b707e04d9fbaf5b2f7c4a1669321896116d64e6c68c231c9d36227703b9e2c84e76da2a5407f4907054ede7fba98b8b8565aa9d4805b1218feaaa16498910c5deaee2e647ed0a4b8da3970573b94fbd3340edee02179b2abc334bbce9413f584676bfbd7039a7d850b13ea78f59
+TAG: 0ac56c101bc5e3302fedabdb1bb7a822e6ff4880
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3f86993a4d5c421fc35681c272719b78c6185bf159c75725f8e0af9177ee944a9842f09414c209bc2057f2b7e1d0db8d003c470ec290162545e54d6c78ce1b3a70ad9a508d05e04f4ec47fecaec8848e5378f736a579b4042bba567ce7dc9a6e940208a23a87fb6852c8d5e7df86ffd9242eb9f8abca28f9c7dd9bdd54ba597a193333816c9c916353a805c758bbd867408bb73cb364823cfa17dc3770
+TAG: 2b20f74e7b404083fe83a67d90ccce7526700fbe
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c76550d2afeb1ac3f9d0ba7c0cea98a89946c54dc78fb063e313394b6a0f50ecad1be9e5c5f31b5a60b68cb12090a5394577c96096a8f50e63e37f1177eafd303b94fe2bfd203fadbfd0b63a10a2cbdbcd247d7f4e47beddc56da42a1b03cafde36058f3f16e0ab9a4b2a300f806d70c73f0f1eda28eaf1e666f26729bf9fe45bb83679dab74fa5df5476cd1d1366abaddc58daa87
+TAG: c7cd9aabb79f974ce823bccabc598025e3338a30
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c7ea0fe34384588c8fbb91d8b4effc575d89c328de4e593d875f6162a46a0b593c9eb55e9942dc53ebd29ab0c6126334721487c61fe9e28e32d3f6e5365b9df7f9b187fe7d6d9e123cbc78104b89e4faf1732ff4e59db8fb0b7c8e98eff174cec07943bd7495bf77a31e256d1c18597568c0cf428ce2c380321a10cc4b904bff14a5b9e19b4106757c459af86f9b023cbf0579944f
+TAG: 9707d880e91802c7f89fb446b558b2caab66139c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c7a5fb5b94e75f4bf4451fae607af72373192435133de313c45fb7ad3efb5f63eebef93ddff8c321711de5065ce11507f5c48af94655547bf3c3f0f7a4f18443fe68578587e43c30206085bda9eb342c065933c7e6248ac26e1bb633baa4d46557793c4f6f151efea0ee436feb1d3aac02a8979087671db4d2497fb83a6a413c77f1bb56915b8d57c9f82ef61e88029f43346179f5
+TAG: 55f94ef32d4d67d1af4f710410f21e40d4a1dad2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c7745c2b4745354e6a551004ef12a2e5b72437885ca4da5c70208043ffc85529a6b910861b516028be39588b566c1f0b8069652f96651c3cf91363297ebceb15b5730eb864cd930c8b298c4f78e867e4b47ff4aa8e6f67c1cd07c96336c276f04a0d57f54d94e24a1116fb0d2e5216ed877917732b980b12506d639cb7407276cc2bb6d248860dd4b92fa9c539e13a0206780d2324
+TAG: 8ee380b14a31cfb7e1983eee4a0f052d29ed0769
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c722f3cf74df8db109dd013a6d334fa192175434a6b2ef8068e2b6f122960847dc829718cda13153f394f2dc58e3b35d9d12668fa3831fac909ad6ade0c5fa147b5d68f137cd26e758f37209e512a65547a2fd844ac1bf7c878bc706019f6215dfced716912fa48b55cb9b8ccb9c9836d3bfa2e54eb7fce7c123645ca5b0cba1da10f4519a87b0361fdf2019ec4e9dc1591cb4d1a1
+TAG: 8bc05706e3c03c4275d264a139bdba0afd06caeb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c77c39c3047b0e49acc35d4d9f44879a7d711101c2efcf7964d7dcc37c450a36abe888e049efc927ab91855f1513954200c43acb8f65ce8fe3cdeb096259a8a3038d3d6571a63eabb9dd8cf918a8376bef56e43cec79a3f05ff0759b2bb122e8426e61048368e35ba42bed149f0c6f409fe9063d8d36f159f1198bf431fb1089b1df6c0b10c54f1e1e0f34544215e5ad53bc2d429e
+TAG: a932769bfe2486f3ac19998bf9c6388d673cac93
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c75f3eb281954c197c6f3bb9fe8bfada7c08fab0b35333497e8d29eb825f08e614fdfa8a2aedb44c15a5f50c315e4c67a377e29e8b87d5785569965814f22eefea63fa36d4069225c734af9c24eab014760918f95222a597f39ef526b848a8ee7b3f9c0325c29cc4fdee78d180a7ba9431214fa1700d67699fbf8d3a941b6851604eee0c61303a0b856d7737a2b28db96994618c97
+TAG: 264ea24192e19e9e2e86384b16e2f40583a1e245
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c7ab20d9bcf56a857f2be5a146114dd0c4023241401c4524dc8409cd9421c54250ae8aff6922e88af4f571059842b02f0b45a0b2082a74964cfa24f5e8774f4ebb355c2152216e1e5e4eebd679462b60ffe629f1bc81a763195149dba64138ea7dfec28be64392488e4e9e4123a01073143de4b45eabba54c09bf867f48ca11d334db0d0250f29b6c25b2643285b4e9584cb7954f6
+TAG: 6cc10f33ab7d7a8d7ca78e4567123e8aae265576
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6cb7414b3540ef7e06a487f53c97db364d363350321e205317fb770af300f0dc278938caee518d31137aaf29acab189fd89bf4a5a813368006393f4178f8335b9a0f4f9b643be25ef4e164d40a5f5e2d54c2ba6b8c07857c59da85c780851a0bd77e79649137ba55cfd2c8e6ca8c8c44904adfd0c4d252df80d0f2a1b1d496f93bbc7b47133320eeb9fac2cc4
+TAG: c9dfd240c6d209d275802fd7ed28215b45b7e9fc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db69b3ff24ba43e9a85f8383c35308ed891d02acbaa76b4bbd80d2ff5c04caf5d8508c618828e0042020a7260f4114fa1454dad50847eac852e73e9f190649df392374b1c81c59a83ce0e9ff75e1435f01399fa8e3c5877c2feb6424929e517c5d5a232be1c519153bf54c4ed92ce89471444edd605b8f6704c7edbe758a036918acc50d2659d7440e9233209e1
+TAG: aaf73d4ab156b6fbaab69114f7ae659f5403ee76
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6dd86181de61f29afe31ec3966ae7a3e72d09ad23bc959246916233aaaf374b0a41a1a1bfa30402c57562bfd309395a172e65a684dd1330d5e40a21050a66be5ccc5f18c705c5444e932d4d059301595943b2f0f969f21b12f3e902e0c48bdf65e2c06a97cf95fd41ca37204c3b77287050cf54068d407c17f634f5db134be6661f043d35e5f0e81be0e4319b
+TAG: 8d3efc0f980393edf496f71ed53861ecd72362ab
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6263893f825bb7c763874d444b7ef57080c48eb72663f7c04bcf9e0449ae1c1ef08c1fe135775405e27f20c382f69402b99f86256998afb46af1fed921d2e14b6d46e37418ad5db3c2407d4c07511be6e9c38138231b75ddcfcc554c012e68f9df96f7a992641cb3b71ace16efb75b91b6c125d24f2216412118102d14e54c6c0524d16f2e0b3b059d09358c2
+TAG: 126e354d1a42eca007ed3827ae525c136ded078e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6af766ec0fa8f59eff1dc9dce40382f68b0a30594d73f99b92df9b708bf7545b9b4a6ceee4898f67d14913be2654282d9400d18ade7a5f9fa9c2fd86ad9e1e7710bf8da13daf026b95a23130e64e4b68b51d042c75ecd3f8547464f260ca0fbd47e8e7cc4eca25081dd4c5fedc4a520b3e9438f6b0714ad65ed66497ee8db4c59e4b8d57e75eb6503ddf98f17
+TAG: 6ae0856280899f4f0f7f6651457f3b01a58005d4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6741bc2cc1da912b2bb93c2e141eadfd65f6406bc0808b0cca18747ffcb3211b05144ec54efdd9472578b97547377d6a55516d24e37991d9cb0edaca2db9d39f6035c3b31fc5212ef9ba577c13b0a43c7f9b4ce5bad414d52cd562718796efaa64e245f9c577d473a7eba076527a5b8856dcdd4ce743246e8ae4688bb6f2df86e573388c48ef29b9f6730953e
+TAG: 3313e8c8ea212405a1bc63c3b7d1caa094506605
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db62c635ecb90cf540b86a46b659950b22a5d83329bb88a13062498cb17bd931eb8f19ab30a1abdd522c7c48bac21a9bc45065b12d493ff2570fcd7019d84613eb392177a8b063e7593cfde3cff867256a65e57d648f56fa1f26a4a222e0154ac31532b9001c9fa0cc14c552bad3ae3efbf91028be99f1834f1f57a34cec969d65b4bd8f87433d3367f95d67d9c
+TAG: 759296568af05b10725397d3d64367e95aa36c83
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6f256d8029e02d64db7b3185c904b41d8c3e72cbf189fee77aff8d475ed46fb03ddc02560a75b6f21fb7e661ba3a0ea61ef7a792d6b07a8035d00e8660f3052835b1457c5ffff42a620ece8f86b6c20a267350c24f4c3e03b085bd6949075a581348241bc71dd88de766e3325e392fba9b2bc78e9a038ec0d1e416f4840289a5ee820c75927447e9419ea6b56
+TAG: e8bc569cfa1d513288ffe3d727c14bfe8ac7be05
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66c9cbd6fecc63a8a8db092a2dc6080ec6cca1f02c1f4b935b2f65e6b7a4c73c49dcd725cafbeb88acd670f52ec81dc8f9380965c763ec293beefbaa1756088d7697a35de79a8e1cf9bf2db828876069594479df0d6ebea433d8428c6a99c84557aa084bf6918a2492d96f325cab950ccd22e3570d1dc7b02047465cf2102ab9f20849c2a96
+TAG: f1d0ff19d68a1b1424666373437c1e1e9c407440
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66c0e5c11dff0eafddc3a146f4090c7bd9722a4dd2d2bfce120ff1522ee13a9ab7a002d071841f7f6767a44fac31c37f3471b6ab043bcbb89c6ef15800c8c74a1f7bbc04f241e843397ae9218fb44724b128a866be4a35161cebf38a5dad19dfc2e2ee4641bae32d7d8627759466995ba4180722700362e7cdb9d31456063f0603ffbad8ada
+TAG: f36e473ec3b379750b8a5911630972e875af3cfd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66c15253ae1a3f8fa4100bea4be83663c5b3e97a8949515b7b56785a83e5c3b2b571b9cfa8e62e9c4c288875a26965b2bf1a56f25b08c74fbf618343015bc90b091634ed958b7297c77cfdfb56df089a200247ae3b229dc6152cbf7b25ac2094d6584d95890f6ba2a219308baec85a8c205bbb9950d14b06d6468025bb1629466afb28dd26d
+TAG: cf222e37bf8bdf75946ea246ab5671fba390f344
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66c3e564eebfb180a0897169430e402dceedcf5459579410a5323143d5d534f46c2a38bcf26d8c4f0862af8838d06e15b24e0acbe4251de033fbb7f73e7ed06faeade7edf14ea0e10bf44369476c928e5823885d1f1ce14d5273678878ceed8df66d96bba78e6013d0795b7067f972d44f2f24990e0ac5116ab41446a8243cabfefc355238e
+TAG: 1f3d4bbe22c901a85318ee5ec98d33a9a032a85a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66c38a390928a696813f9d03410a1bc3565523e7c054fb2d5826358e5b8909967a10957ee5edbe6512f4f8a7add1271483f71fa3212f5be01d197752dfeceba60f39978f50143f2e892d4857de9449b8e9aaf32aafb5000a0d995be86e8a49d5bf7cc8a712dc33ce31eee56862481c14ca1c2cffbb97d9bc72df2f9b0d4c2523f5330f46a38
+TAG: 5d7490c12d70bef0127044501ecd005b8f0a0d60
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66c36f2fe3f9c432996f5c8510c7abbcabfa8ea9ee41243b64e05af58f0874e7376b286279fc0cef3ccdeefbb7caba9b7dc87cfc8b5b4bc1ff05aede0516f64210df61b3fb8571abfc6dfe6d3f05c5ff2f16176b7f8328de36c983c900eb8fbd268ecb2c277a9b44a7a99c4a19efc227aeffe10bda4876e1fe99d5804114faa3a9fce590af8
+TAG: be37c53c2341744f735b170ae431a6554f8402af
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cb1d7b948e13fd573284334300c95e71ecdde5a9ffa71e771fb3ee37bc4d18ab3e57b73ecc83944e0bbac6f07bcb44d634e6abb732b8bdb1e983b08a02b8fd713cf81f5c1bb32333118a8fed93376752aa45cfdc1e0bbe45cbf8873eb5984f905b4e358eff1b495500a348b8172d15a548fa3fc6aca7980ac1d381dd34183fe561525c66b
+TAG: 75a1833c79a75bb8fc6abfde499f2ac8d43a7e5b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cbf6efc9e21cd4dcccd71cd81dccc9ce672f9cf5f665649df62bf786d1544b170524bbefc4db35dcbb789cbda3e55ded4860f9e31298674d7f99879f2990ff199c9c705d87e6d8568c449f2700fbe5620d81edec9fe682473bd99cd49106ffc344f3ef7594efe1185da26292dd90566f7a02c2fc13e7f6c95e5b4153b45951f71e1dec0cc
+TAG: 9c594948f1cae5371996a085a0f70f026f9bc479
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb89b80706199eb179ad941980b9d0080e120fc0080e8127d6b2350e41431335e6ed066e6dc29d9475b6ea1c8d963bbcec18c54dbca36612db4c72784bdbe0b44da3d506fab3d5bb910065e35b2dff2d0df90151961cabd17a5c016444614b2f392e0890ac66faaeb4f19696b506c175b9114a9b038f377bef98c8c73c4d
+TAG: 6fbbe8a06c515266af6596cfb6537e7e7db9d2d0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb8921913595dd472442014f9290b574185702692d38bf99c5cfa9734d24768f4b8409173695719b9ed8650fc3ed780e6b04cebf813c9486afc2cc2a2a3e82c357ec9fe0f6108fb5b6fed023fde1d70494cbdb8ef8a0f114bd4af3293a2b03ed7ecda8061f4618eda54d9cffb3b8068df243ef11fabd4f256d1fb8039aef
+TAG: 2a12e6630382f66385dc334106659ad21089dfdb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb89ace0d9e9e777fa412847f380217125ae01e5e83e08744ded96b45f798d1c0e93f82693f79079f5de14eaec4b1959b3a0f17dd4d8cd65cb1e6a87afdb5fb6b1c60ff18522e7864b0161b8a05ae551186010ce3d0b9ad6ad60a4533d4a42b75d3b37e3b82fa83672a87b43e648088f131012663984866f9d50213a97f6
+TAG: 09862c2b3fdea475dbc8bb725c128478468da083
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb89e7af8168cbc24a978023468c30615d6b8980e97837c0282d8646cc42704e9e2e30afb717a6a85e4b87843ea6e660b4cc5f2b93aba2d006f16a53afbb8be591a64be637f9b852f849feaaa48996c3b8ed08750ca37d7655164dbd23bc1e50c9e5d33605e7f94f3baa3698076908c951e5ca96f04d2097998a3e703e42
+TAG: 8e177568a6a9820bc786e199ef688fa0e73125ae
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb89a586ec3d27c0882b3c0d28a3511b762856b800da245ba1b454767c0082a98074f5929fae98208f888387396ff5760c1952fde36014ea8f4eb16c6f21f0468c5be89daa9865acfef726b78e5233c0b4bfb678312108b150cbf669b1d72e02eceb8f0bd8b8f94f3032ab67d61314ffdbda4b2dfe6607c751d56428daef
+TAG: ee14e75ade9c51b1937c7b3dedd03d20e9f3de84
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb8929908c7829f7418ecbfdbef01d3b633685129819db90e6af4e84901261f18c666a88066b15542eb8791f05b19c19300b1e8f7338331b0bfd2aa00f59373a311fa938e2b970bc6ec0767a2b1c122cb35cfdc4875f8194980dbdfb27d86ed1b43b583a0e32c32de16464013f9ab9b2aa60b53d08a82ee1bc47bf988449
+TAG: 8f1a85e68cf1610f2bc74e3394f5c6b3652caf42
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb8995f5922239b45be91275111575146a894313e879877c092609c1171fd297d69659275e543298de09a5a2b9fc23e9c9dc7852cb17b9a3983d91383c9e83faa59a34cfa74abd3a445d3e1e109ab3e3c31877d02ed94db53876a5052ddd87f4b7339bd2d74013a3d8974d893cba24f4ce7906c2a266c80d0ba1e4a986b2
+TAG: 430484340d2cb3a3cc79f01cbd1398e082401733
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb898e8e7524aadf962d87b0a07fd284adbe6c05100457ac89413f4f12e2a5fcd479c8d58dd0fcb6baf22c90cdff418a9281a97fa45a8d6ae345f6ae0909873067afaabb76f577b36d3c91f5f37f345cf36fa51eb2a2ee0cb270f7f266dbf619ccee98e964111ab604d20e8ac60d78493ac742a0298e04fc8727d5c9aae5
+TAG: a01947bb79730e169976248678b1dff925f30310
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e87400fbfe000ffbfca65235b60c77bc19cd6ac19fbc481467e3fdb0a7e3ae742115eff47723815fa541d1ce352858262d9c1a37c65cf8883a0bfcb90e93647a879be68cb3b91b600f095b1711906a98db6040f63c0ba32a82823f759f050005278e15e70002bcde210efab42ff9bf0e7c8935907e48b
+TAG: 3431ebd7f71cf2e3069809448532afb7e5a2729a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740499078400084d93c8154c2ec37615ee3933f23cd4dbc9038fbe488e5fc7864c1a48bfc02d4c072e6ef17149f3747261962be873a0771bc86505d03f3e460c8cc7a09e521f9a33243c142d772a01bf4e59ff8d70478c4624e20dbef9a76cd1759f1fe9ccbdd0aafbda000eaad6fa8c831c7725002
+TAG: 8b821834e8b1552083b85f61804e8e033008814c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740d1ff5c34160cdce001facfe7ea65aebeebcfe93e17e03f0e9f907b682448bfbbc25cd61bb4b9f4c21a9bd34907c7b28c48af467a975bca37b14fc747f4965eb1279f5b79f66fbb44f2bd85c27ce0014aabeccc3dd788343a5af4ba297f7a1008ddb189b80e82a1f8dc54ee6049086b454a31e935
+TAG: 252c109b69b927ed6537422eb8343b04e32dd345
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e08fbd5d8ca47c50af9df61420533f9765b0ca2a207c420014fea254952598f17f2d879a6db8ad0273339f55bd5c5ab75025bb5630a5a72b9db31821e67fb887117d80d1ece2e4531136fb98490f0ac5cb3c40f9b1ba989372bafb2903d6698782ae79488619b338a7537b66f3647dcc5f171483
+TAG: b0a8e932beac43e5659b6d3b73a4d34fc4fd0936
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e874035ad2884c91d8a43f952e2f29c11d4b39a01dd0452ddef6689ce6710f7a81e9600de5b0161a8ee75c21815cb2a734fff35e0d479cf83a247450e3043e99655d31150946391db60a61cbc233af74b0b42efd2185387f86bc011372a106e12dba2df6f1255d9a79e613a29b303f92f6e2f6fa68f81
+TAG: dc785a7360bd482612ef6bec5234c5a2ead2cd15
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740c0aa16383830c8d37a4e2764beef516326a13750b4da38ce12e124817675755e55db0348ff289e138ac182980c401d8819024db5e542338615588ef28f5860141ef628b0509a636aff77ef18fe03799e5128da5fb3ffe7424fccae6a5d4f2f3eaf8bc7dc9766b3618c7fe4dc2379739580fd8d27
+TAG: b63ee7ad5cebd0f3d0b9dbc32b83111a1cea47fc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740b81713008c69b53223709f2980a95f3b3ed2d1a51c1bfb9f9541bd5bd4972bb0e1fb3bd0384f505320fb9f1074bb195b77e80f1869d2510326246fbbfd57a0aeed6faca71a75c3350790d86c2fcb81d268b95ed86aa3f6d0b45f9695fed10147ec1c0e24069f114892d60aa6db1cf2ca3f353283
+TAG: d665ecd9c176979b73ccb62a1d9340d9bb7d1722
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e676a12ad3b14f3f3e231acd1d2acd214f9d272ad8b84e871ea66ee3bb57764e1e672f747a3813f1d271fcb30ba53aa900d8390133c9107a1386a76b5b4d5b937461107cc8fef9c24215cfb5d0389ddadc546d5ff4ef3fe0d34d77add5e48fc1a77609871d90c37d7edba6e64c5315f52d27f78a
+TAG: de93ca9825a8a2b88cb21bbb28d8bc56aeff2958
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1d167c2b2697e7c9402c0ac386944385e83b9d49274f13607757fdebba9d89c98bc7d7a00223be3659c5a7afd132034c399a565d864b99e306e73312efcc45a51656536e1071fccc6a9d5dc7b7d06019e341a84da1ee5679c58287174578d433ff86c334bb5bf0cee996348d1
+TAG: c2e0316703418b7b1d506fa382f2ae687283b36c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1bb12c225ff6568c4709590afb4ee9ee2e44220101dc5408d90f0809dc709ce3ac21713f77fbfcfa994e21443bfd610ddf942bc6442398986b5081ef631ca6c33bcac0f6aab1e519a45cfc9a42a65ab8a9ce81e2f10ece537aa2023aee5544e20da822d10b0ac2aa8075b7cca
+TAG: 61334b4d3ca084e1810486770dd740c8d7287854
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd190033c16b7ec1de874edfa318622967af4f038cfd6f9b385dff069c6e2a9029ce4c6b00cbd53b9e6fe4d446129f0b56dd56f47282e40f8271b1a8cfa75541c2131b6b219bcdb39f29e83e38a043ed372c240c730d96bbec6710836a66f4942e6ef967bbb47adbd434edcaf2a
+TAG: bd4bf9350c2c70c2b71000af111202bcadcddb16
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd18eed4bcbab9ea78de24f2a8059962340322e62232d54a9118de9d3dda7e021e1935f6dbaef5c15e20b36481b182bda0c48a26167d465debd72bf3619c7e51ae55fb2fce9a4651c57bc2c51b536038f73f7d2aa136084cd529f8a40365d16a480300cfbdcce056c740b0ffdb2
+TAG: b59a97beba6e4d0b80b3704d8850d91aa7907b82
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1c7c24c8640d29c06deafa63cc33d2594a642c70ed957c39269dd74837a47ca6492f5a30586666de743accd84f40621f6d46025fd53eb9194d4d6ed1784d6d547141c1d304d4eb0952c9cc03b32606404963de2c10775860fb7410041a9271c4c5542b0e22e758e7ad9627c8e
+TAG: 98c3e21a577e94dd6a02d3c5315a54da7a30a7e8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1c46dd4f8ddd9f3eca6dec563c42fdd59cabd34f1a08011a11e5e8b562ee0971c4bf8b18d34133d1591cee362f16f083256c6d9b094cfe47416da9d742c026d620c6358a802f95e18fdcef188950333bd8d0a9a4b307c8d331d9ccbdc3bd9aa94799cb8fe8a66560ba56bdcef
+TAG: 0e3c8ed61075c69db3578dd741f442d6e986813e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd178df3d5be8efc653ebef7a9ba0e941ef3cfddedab5e70bfd589403f4929d05d1b32d4deeaa206b11097788690a3ea65a8e1532f6e587ef1e9051852a520509cbd65beca0f263667eeb0a5093dab89c9e8bd3704f0d33b3284dee85f2ab97f2001eaa3c77e819fb0c50fa31e8
+TAG: d8303c91ba2c59d47d0b577af59cb43ad28df0b3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1e8e83c4511c05842cc93953a66f8846b332962179084166bdfba850fbd8cc4a9777dd01dd58dfcddce141dafb0abab95d324ba20b903c56cc6802576e8a1e45c1ae2738fe5cb7113e71ca47f32ce5fd68924fe2016321ebab69964bf787d35b33970d2383e407b844c5e3ae1
+TAG: da7b61443ac1db32444e559c8ef3ca60ca70524a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f1d990e7007c3157640181468a5d68ce1ca9669aa083e1d9a7e460a0c83780f0da64f8c6f15980a84548d45dcf193bcf0c7ee2416765322f55faa0cdb55492c4414dd9381409ae7eff3b8fa8d84f3333c74054bc4ca0c31fcdab665891507ce975d24b18a
+TAG: fe447a46f26f55e64c23977a60e936a941d3a1fc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f29c0fc2e2bc7a255f8f70f7e8b14a374fdafcfe0f0a46dcf0e82abe1483e296f453ce0d677f503e3ae565afefa68838b587e4e57297f80c2681fa119e1488b87d4a76c4123cb301ae831d305304e30fa1b381aca29e26ed2753f190420259208d1be4cd0
+TAG: 8ce255294782d71f5aac161db33df61a4ee1c71c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f14e3b0e651fcf8f99cfb5ddee26b5b0d62883711d26dcfad8820cf6cd8457f57258972a4b620212cc9cfe44b90486ccb608c996e5f274c57039e0018234ff72bec4cbcf5e44b77de68bb6813d0f25a68885a317c2fdf8c1bb90a51819adad2ac36d3d327
+TAG: dc75b705919c70c70ba89a124aaa8e2e35ba8189
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f1cdb9d762b7f4b6a196650075ec07cb789e0111009f833045e33f0a29f045befac25779c7b73be73b7d1330ec0d777815ca11bd5b490d1d3ef391ff8688cb48769140bc8effadb044a1c2bc505959c8a090abcea1e2fac1d64550ea0189aa9327ebe5834
+TAG: 0af15e76cf4996af951954b577cc2ddfcbb253b0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f91d193a30ae74ad92f38c43b0ea4ce8ecaaae68775c7332d17e22ccf2afa299e56b8b12a62fda6d7a5d5ff2cecbb1cfebc3c9aa6bb5cfb124b2871b428b03dae4b3bc367799835ce692f3e12627eb28fdd2abde5f26f7c5ca5a3c2773cecb18f7201b7e0
+TAG: 89008812e3780cdfb3fd362a6dba8d0beaef2cd1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673fe7c2381f6f273802f272632fae8892f524631936fc48e804bd2a0213ef0250917d2ba404266646802d8ff89e23b81b076376d6f2fe10bb75933383239a1fb0d89dc3a4f569e164a5f1d947175b47a9ea2cba0ed22a8844bd1aa1f42d4f48b2c97481b6bb
+TAG: 3ddd8a21b1dc07b89adacabb531f96005a4b69e8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f03a41885598863c3bb36789d798d7bee02882b18601442265de5db9109e07562d85f5b12fa1cb972b7bf5f2442952c927bb02e73e3075c065c3e6b59b82669d4fb796b452434bfc24082b6e4201eaf14fb27648fc9f1d5f3db80d9933e7190fdde26a10d
+TAG: 4e28fe216cf0f5819229a78a1626d387a10cd92a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f8caaf40f16989ef544944db13753aedb172275d372081529cbd09c578eeb6435cbb0c53814c52094c3540d87f50b689aca0297d168850a515ca803e7c45e67e91d4e2a0b44e7d33adf96376864714730790d31749d28365ac1804eb1d86f5510ae90cb65
+TAG: a4d9453bf9f024a3971ce8959be1929a95fd1ef9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f382244ebf45681d83de3dbb0e9f3cae71872e22f6151e727e7fdf4eacdd9e7b7b42542b7b37d814d76db2086cce7f4b515b6a3eff7a115d6397b02537322258b6ddab743248b54ccb15ceddb5a1a99ceeb9f07699098ddbe19aecd3c65
+TAG: 3aac2ac24e32318bdd4c0724cdcf853e4fe60b28
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38eaf350253307ed2e656dcf0030975db996fee7cb53909600d563aa29b416de273957d27ae7daba45a773e828e8fd2d8bdf275b20a4555a0d1332c448ca42ab394d0a3ff70ee0db0cd1da3bdd631b43c6d5acd891a11a03e9b09c6a86
+TAG: 66ef134d81307260082c8c362f961c08bcdfc645
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38cfd5d269fd1f52f641d3b27bff7ef06609c42478be1bbdb17921145f31e920483760d5a713b7fefb1a5d074d1f33d2443b8c59096b4bd4aded5bc20c7be1cd37d06f4f1860560824deba0b87d936df4e6f97c924a1f027e65ba69141
+TAG: e2e1d6822f0037e01308fe345ac1895a013d8d91
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38c2d1d5d2b4dc93922694b13eb48e1e8ef9b6e7ca174e58bd5dfc824470a18db11d85811674e7e6829910a295192ca947d3a902b39242dc94ec3622f5a2ce89458c3e14f03313545bcde7e224bc484ca2f2412572d492ab14b9662b70
+TAG: f4bff3b1da54569892449edd8fd119cb09fb7652
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38a0e504a931f393ff3caab0c0647ac690deb3f48752f7f6170ea036fdf645be31bc6524a39fc30011f72a3317144a4a85e60385f582d46e66ae772fe3cda9b9f3f40c6e34bcbc80b6c3fdc3d270ae2f12815bf9d93a2a2bfbb829f86e
+TAG: 04205d0690c4083225da12eb4613eb77e50d5035
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38ae3e6deb95a0cb899673080135bb8bd4176dd063b30c83011e206a502c64d6ac63a18344a35335cc0366a34975c6c9357c6f10a0dcdc65e7768f7b8c91e21b57fe07031c1dd97cd046549366c751745ba7bd0294d04642656b25827f
+TAG: 3e8154f456c822829aa960dde82381f5b6a6bc77
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f3899edb75ab97080c055bb4e528bf8845ff1437be0adbf7f2384134412ea8c16f51e7766db0a56a18fdc94d277f9d5fcd1eef4ffbb36b8d0e697d1980daa1f0c8921fa148c8672578f2fcd8408171a30a724ebc45770ac4e31729cabd2
+TAG: 3ec4023d03e719cbd8351044e4944b8240f82929
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f388dd7715c2ca50ef4beda4271e8381a6c8f070f07469a9dd66ad9e49a57182a7744c9b124eaeef4785ed9e4f588b85069a0971fa8d5ff00bf7edce79025f39c136c1e5c89430050a8fc4edf2214eeea06e7e4810ac90b63d4a9c1838b
+TAG: abfb1f930bbeb8a85b9b5562b3df81d8f835a801
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be3283303492b95aa08f793435d5d4cc6e76ba647b1e411fff714e64debb5936300a3d9f97575adf0b00405c980b238487b3935c75d36bd6462932495f834286e950dc7ec9bf8aff0ace5faf695ee1301a13cce06745aed
+TAG: 81db2f39b6183c649efe0778992de39d8237a0ee
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833fd6c063c66d321e2fef921bb3ba070b28338984bd0df97d06357bcb928004447f737bf91a907d9033137c4e9b94c32c7f52fb0c1315732adc4e9f2ad05ab0fb38507f01e7efe78503b3959a11813acf646123128
+TAG: 1741cd9de817680500847f60b99a5bad331474af
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be328337c6d3d790bff3801b6f70f4baa8426920bbb4d49f7b68fb95501a6d80a208420b226ba95f135f39ea2e01bcbae70b02cd96449219dbaf89b683e48bcb371589eca3d3703784cc2db7d4c687cc081b4b486cad9c2
+TAG: 641290d5487b6303f581e51980792591a2aaa58b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be3283306bad95bcb24c4f3a4068dbca6214ecef5d853fa70d32ba1777d79f05a50e30fbbaba6f1fbd889a2060e27e146cefc5e6027fc44582e92340449217e8d6b70e5ec840d34eb79833fd6d40171b348d49741143ab9
+TAG: 7148852f946c6bdee85947a7cc68e919d644f79e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833d31ddb2c2699419a6de6e4b7c03199ce8391c3b9e5139f84ae189a74ae2e8d1fc9045303310a8eb621d451ff028b2c487869eb3ee7a3db44a8a93851e903bd730a39bbffcf90bc8536591f1eaa510ae83b799232
+TAG: 7efdccae7327fbe7acd31c222275a1979738d880
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833802b697701f02f5d23392a1c11647a691eb487c520127a2f804b764c2bde17356c8de77876c616b437e0b6ef7b706163cded0a878dd055f6c1bb7c246866fb77ffb712750a666857c3111de4e1c2ae29aaa67e5f
+TAG: be0c4217b0abf4d66601e173c9bc33e85b0cfb58
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833b978df9f67bdb8fa2655572103b72b74a2a1b9101026d1d1d37e959cb7f603d01b917be0673593b62a81a8ab989c6c3ce64cbeecb28ff90f674f377cdb64c95ac41754af08dfd1511dc5ad644b1e86946cbe5c1c
+TAG: c3fa2ae24ad918d8f981c0345ffe368d0cebe96c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833a10652d4e444703e56a5f5a025ad3f4bd18d6fa2085480a178b6c702df12c34fc035d8350f9ba426d5f3d2a6b3e776f78003c3a1539c956a8cdadcf9906e84156998b7843782157eccaf9dfe241b3cb06e54db00
+TAG: bbee5b5c1fad63fd7953b493a6f7d60fe353c1ad
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258213ef013b0964a66a6f79de90f5e0c90b3440a31ab684543d39c786208134256a69e60555aef5313a2d1ac0557961a2eadc93183ff7ff36395f1e8d6c122c59854e489fb2fc013d80af2781fd1
+TAG: 194a3350246c15985e13b2b6e2be528810d9e240
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac25821df5a6edb91524d7a9a5986df40956c4db529b1b0b8bd9f6b163ad8a60b89287848cce0d776eef3705451ef38bb16970495ef7bcdeba47d73e84ec2e091271de26721976925e77d6840e8b334
+TAG: 80a1ccacb4a1a978c4ad8a515f5ee66d01f08d9f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258212db1295474e11d627f22ba59e30c51a7bcb7ba72ecd2cb3dfbdf0bbc9101ae13d136f7b5e44aed4e05d7f1881af00dc125e1b67650898f48eda744d2375354322882508b3a162e4583ca60ba
+TAG: c38bc7f8019f795acb906020d5be894d2a141175
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258213e4d7af96c6c76bc0a380cc23613e09756bc50fe246d8ffc7bf30269e966661c6f1d5e00c0e5f418166b7d1da74c95eef577519217177f3778f3e5f8463f7cab7e8132c8fab4fb6403a3824c
+TAG: 722079eab0c271a762e3c71a61d32ef70339ab13
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac25821a83bf5bc250e292a5e3611fccb57d3783e5608f58bd76ee231682dd7e6f99e86239ea03bcfa1b6b9fefca2ed06bf865a6b262f38153298f16d3c7753f6c44eda323f479a1c1a93b7b83ee9aa
+TAG: e550ff8e4ce7789503b559217e79de57d8ea6bc2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac25821284e7298b3a3e6ca9477808a4f0246edeccdc9d71a2ea9548d66be0099acff8349e8ccab19279586fb7e19b90c3055243753ca6a09db2fee2a40b3198c18c264c7e761e386f1c7ef341c3c7f
+TAG: 32b4c3fd8426fa78141e1b686b650f32b8e78e46
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac25821c6e2e4b626114ece6eb5b71f98a2b642749f4b7a243802463e366a1a1e2cb258fb6a7aa806ad5cbe7029315aff98b1004322b0562e7ab077c22473c7bb45ce111da3c3994af8e98208c6dc3a
+TAG: d3681ed8e639d75c4cb9ca76d9bd81bc04462118
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac25821311bd2abb580087555c533a220ea2286b082b60d082dd6423a2d733229330df364fad2e88a9909af8a85212d4d750a1a398389877cdd9ff20966acbbecde655c021083b7e8ae905d3314782b
+TAG: 1d623be551aa88256b69a5d8c918ee4d345dabb4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449090cefb5ae05905a2203683a10699c54293c8194f6e7c74c19c74f6e6c6254901c9c70fb0f43d4c4ea931c3dae3174e538ed22ba9ae33819be296d9136e556d73242a66dc
+TAG: e9bc33beb83345096f877917a08ce6e1abcf1516
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b4490d5eddfb7cd820df40c9d149e79e042b4848482939baee628a0c6a9399ae1766db3093246aca5acd2cfbe4bc7edd7385628246030b586ab3b59fcf6fb6bb5e518bc6ba9c4
+TAG: d36b941ff8f4addb61d0af96f48b19849340b77e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b4490e15595c727508ec1b5bc949b97988d9981633dee1259f997fd1e438391e56d7c71f493e00bee895d6786d2cae5320a1c57f9305dec2a1951a827fd8256e486749e35134d
+TAG: 542d15798bd1a0c346639f150da16af06923320f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b44907381da9156f2a5e81c5559fb5cbe6a0556506feaf3e8226e2b0c786b87df5aa6659cac3af97abfdf60a32795a22e0c3123ce9ce075ca65cdbcdad9d452a91a4bfdf47df9
+TAG: 8c13e0df9e4d8516cef1cc3ee500927fa2479130
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b4490dd3605a3b2cf2447ceb986afbcc27cf922636808f4757637b9153ff2930476ebd254617278b931c997e99cbd05735c4e418d1e19cdf0128da663a96441bfe477c0a0fd47
+TAG: ff9d2d533f69c56eb34f71826a07ece7e9b79673
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449007e6c54ed16e426441b73f52e35db27d45befd32d8baa1b3ed17819e3bc10b3dbf076fcf2eda16da06856efbd04a8f235d84e4a0352b15dfae3815c6d425f6321f82e2b1
+TAG: dda1b3da1a56d77f5f00aa6ba2d9189d7e205d88
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b4490577eaf61f80abfb032810ca89b31849d01e8d5c4a90445d9308aeb16a6fbe6026171e7bce3fb70fc7d334786743f5ea1f8c22d87b077fafd86df270cdc290c38bc23b48b
+TAG: 08376b67fa3e3cee063a8fddbaa17fb3e4c99cc5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b4490a75ea7c1bd6c975d2d69a01f15c7df8505ac54c781aa0a72269c4f3380329087e635762d9fcfebc3ae5951a8d6395e9196634cb720631bd6eafce29775eb04518e52693a
+TAG: 54045d4ae84892d0ce4bbb2c7137bfa2642fbc39
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea6c22b8275e72411093341069019346728ee47a767e5f845eecb6c5d9c84887df59aaeb9f2769bd879a1930746c130a149ada0e9e9ef2015ff2833ec51
+TAG: ed257d64b79736114c2eb925026bf5ebbd7d5fd1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea62c3c5a4b7302ce427c8e193a44d5225544f11aa972334fcbd529858bb78e84c2a7d8b2fe050c85a5211bda67de335c72a8f25e87bfa7ce689175d5cd
+TAG: 34668235c197be3837c010e24819c97d636580f5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea650f62febf1a91763eef02715e4ab4475a0122cc49d53d41f7cc89b7c3418fbb661ced3d90b7790ed3d55de685d7be9d6e0208cf7d112da862848865b
+TAG: 789c087ec4b7946744658708a4eb2192af1ccd00
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea64681a85614d73ea2b8e8ab173e256c651a7787757debb8aedd0282920f721c3775fd7c52bfb8224e8739198392f1fc47f8c410659fbb4b83af758e51
+TAG: 59d998a06298fe3b11d1260b21ede318e43fb4c4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea6a2cfac2fe34071d3342383a515b5d0701e7d131740d8bdf113fbdb63135aaa04fc0561fd4dde1a6b0625ba97e9bed21a4f0023b2c9e1dc132d68a4bd
+TAG: 07287c068a96492f0200025e72325e87893fbf51
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea68afc2a8f6e900f29d64abc3e85d4401238dd54fd6fd9b85f608225581971f67cce8011bba8cf502be7edb7953f6f50a1c425e7ded23c6a33507876bf
+TAG: ac5f1c9b34574858c29d015d4d3cf33c66227218
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea67ba27f3d9d3cc93dfdcf6a49b6cf620eecfcdd73ad64eeaad79d87b544127b33a8cbf8144385342af5e576d082d813cbf326918702c435b40389926d
+TAG: 5b2a00c28446c7d84cfeda9054add5c9264c8e84
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea665720fd89730f83f183eae6a9dceecfc4df2c2136e0b92534a03e60ff8619d192bd28f6d413294c2d33eee2edc23220e6d5437c4cd33d59d95421e74
+TAG: 9de9d55f80d752c8e9a57c736c60e581c5c635df
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d543bf3c951258f45db2c27d20c91cb473e2aaec6d96081ef0efbcc88c172ce62d4e4226be9e391d1e43147f97b3988dbf310a866cf9
+TAG: 87c480041f0d6064e39911e93288559a6804b263
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d543eeed529518623e86597472ed021271df9c17074e1972a08520fc406801d611c336fcf9c3dd8343cb2472e833d4f63d8cb491d127
+TAG: 75030bbd5e48bee657bfa71d4127179c7cb4bd41
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d543264363a8501e64720f713a68973c3a6b4f5ad7aca4fc1e68732cd455b877b2c210a5cb4834b09f621bca95c0d5262b86c863d428
+TAG: ae7ec7163105341da7ea46170cf820e49f4b2d8a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54382cce779ca151e875ba2784cf77f6a8fc57209b6ec10c50108acbe9e3933598fe4b8fc081da2cf4d181899b03ccb820b162aec9b
+TAG: b14b7f08f1ddd36549cc4c5a5fa3d5e5d492edbd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d543173c02369ea4f0d5957399f6ae75ef51e0b1529ff44455d623ad6f576313d90ee4fdb09a75c2876e894530df4899e7437392aa8f
+TAG: ce7f61ee6d48e3642e05b873dd7a28bbd75b40a6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d5433297b4b03d1eb43cbaf6731adddcbfcfd13316b0f8b549cc0d12f34e7dc76e9f7b52a712e4af595494febfad6a05caa3ec767505
+TAG: 0333e0903c10832b0440ca87cadebc5b3e0c870c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d543c59ecae6da2cb4c8377fb3317150d1fcd4272ba1c0ab18f8823c0996eb2dc4b866e09b2ba16e25c5729ce8899be96db79c5493a5
+TAG: 58abc0c0f5e082bb9941d528e866ebf85d2e0910
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d543ac4cf75b6a2cad95546500419ce5ecdac32e9ea018a91da9761ba62e21d05a3f3c91550b174c46258215680c5972fe01915bcd5e
+TAG: 4392ecf4cd4e2b6da332e97ace3148a6f31e9ff7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326e6df3b4cb51a357f5d0156c53e98ee47d671cf3604ef51c58f6a851da696538b92e7d5f89f6fa3ca2e3821b12
+TAG: baff600f974fc82b0793da302ccd9ee66d9e008a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326eae0a9201f5bf1136f93014691f2382dfb9f9a3a80dbfdd753cbbd8a9d83c80f7766802ab92c3645a8c9ab0ed
+TAG: 939391ddf26ffbf79b7a53be07a04c1ba348b3ba
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ea44b7df90d77d0e3ff9d78a52d4e5583a5b4e2b9de7367ba01d19f37aa92f212ea5e1009b86f691dd1bf5f0d
+TAG: c19b2fcc52d607b23c9b4b30b24eca8c4cea876f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ecf81b465424580e8e0bd1071a5767e9eb3646a6d4dca991d9d7b3f5b03335c42547150a36dd837dd702b0473
+TAG: 2c937ecffe38f649a06d39d9474e176bf38cfd94
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326e384b029c9654c354df3765c17897f967c89ac04d6e2c38d97cb17b53bec246a85b4dab5ef55a76d8fcda4144
+TAG: 8d6c10c06870fc2bb3d33e1604fb14530591da07
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ed3e5ef51543f6b294539dbdd606681a1c852b8ce8b4cd5d8c5fd9195d4908aa6e0c7a6e616732db82da59d97
+TAG: 8b4a57e5d054be3dc387b0a6dc4088b90f24c054
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec602d663ee9e8aff9223c9db8e1c40137be249fcbb8234b4d677b067d96fdd06eb0e1f6e2d3d92ad13a73c81
+TAG: e3ad0e90d357c65fa6fc3c21079e9852a3758f64
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326e01d3837d0f730b1c0c42b8016b59d0fed28e6ed0708578a640fc82e14f10ab7b77b1cfc6c265a09b537d90d8
+TAG: 136a477156133dc19c894d2cf9134f1bc4d590f8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d162662b9b3a8d78beb384118d82ff21d58cc60e6f86ad5df105da660fa1633aab0c08263
+TAG: ee8e37b2486aa58851553a334640cfac4261b804
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380df142e7ca82700e264d320d7daf18732e6c5b349bd00bb1b7c4f1dbf63630bd753fd325aa
+TAG: 13da4d49e36cc9f480e4bf04634ebd44fb86d167
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d3ac6c541bcae335643b52ddd37835e85c5cd6f8eed4479bfbfa671dbd3d0f71a14f14bda
+TAG: 0686119bc755d22249648555051defa90b92adb1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380dba0266219f165e6b99e7551bd77fe61f99f50c922d74e1825a86d933f53d17e32a2ca79e
+TAG: 0374aef4ff6c6d87647ad60e79ed92b4130cebde
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d7b1b4fe99f68d41771f6c66e446ac862a7e480e171082da235669e0a55a61fb5d286be0f
+TAG: bf3119405c944523ef285a23035a5a1b917701ac
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d7623642d365a936d5633eb610b2bd380258e22100a6bb81d052e6f87311a8269adc69577
+TAG: bea75bb1338258e650dc84a71d53a4ef9dd32427
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d2479ab0c4fb8b471f991af0b7f24b47e4b8e940ba0192eeedf727c7e945440ef80309445
+TAG: ed1f296e3960057826fe8449c9338a9881fd3273
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d5b9bf230258b100bb4bd4b5396667b48dd78351a5d68eae702ca0e537e312d05e50274b0
+TAG: f9fd62a5895beafb640e02b74b0256f8a224f2e1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec95e19fe0b0d9cf7bb01edd1be3e6de073bf3deaa88306964980b8a3f
+TAG: 1281c0587b04cc23945a64762b1f5c80789f0319
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec6bfac34e0c5d9260170f4e13f590bd601b21bedf100077ba961705dc
+TAG: 3c262eb7cc250293b10296533cf40b048f2445bf
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaecf24439519566b1d638f098ebe2678a4ab790d320e2db81d32003189d
+TAG: c30f32fd16a0452eae1d53ae16c95d2b0751f9c7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec4b0b8460367002bb76f96e274dee483137b94bca75a502e907dbd157
+TAG: be83d4e08187957202bdadbc61b05add097ff7e2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec95c1201466ce5f38861fe4ae91654c64113299e5f28519d5d5be3abb
+TAG: 8e17c6391c4504a383a9f0db1fa7d84e58b60420
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec7ef7cf360c36e19d46399eb5902bb229699c347f2abbb665fbdb5b93
+TAG: 4d365a2d5d20173e9e90586744a13f621fa757fa
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec3b09ec54628643fc79feb7bfce4b6d173660093c57ca41e81bdd9ea0
+TAG: cfe8fa124ed978fff079aa1e2eed8e81c390095a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaecb33c57dcbec05c6a736d1110e2dfa4cff1e4c2fa03a36830eb18ba3d
+TAG: f2b30ef171d97b4b9de2a5885b885c77e3b7aef1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80eb5508198216fd92c43235f4cad7c13f8a36910a2d
+TAG: 6febd266736ce281a8e45811e0a146e4049752ce
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80eb6f450ab8312eb8760c7a9065352f76fcdfde3179
+TAG: b9c910ceb3268ecdb8cfcefec051461655eaa44e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80eb02c2b34b4b2d1937e4c636d56685cd6b1528e9c6
+TAG: e18fdae0113295f951720ea6c2a2b331c4dfe47a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebd733b40ebdb80d2b677f24e1c7b69d32bf5694f3
+TAG: 393b7751b2cea3b7f4be3a23a1d7544986fae69b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebb04838ef92740b948e437aa676b81fbae1dfe7f7
+TAG: 0de89ac2201423da66a8d27f6f505ccf33a2b64a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80eb142643243e4cfe8e4829ab2fc21b220971b119fa
+TAG: 1d9d84f93296bbb8f1b8d63a57843633449c2489
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80eb6ffa4ecd0c57723be2f778610487c6011210ed8d
+TAG: ff9e150a3de9063455522ded1bf4aeb41e934ff9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80eb410c74d7bbacd64eab7ea80e0e05bf6246312e8c
+TAG: a8972bd06c2246e867f6bcba607fb87f6595518b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebf919d04657440c331817ad4896d27fd3286f13fe
+TAG: 98bca8135c4113f1a78830670aae230f168db8c7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebf919d04657440c3350a19bde96ef8abe04bde669
+TAG: b15d93f6b3d4f4b2bd9f207994730cfe8e6b760c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebf919d04657440c33150d0270de3785a2d951f33e
+TAG: dedcdff6c90a7ed6da859721cc3bb70aef7564c2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebf919d04657440c33bd7a036afb6ef1c488836ec0
+TAG: be31f5adf5eb77d2828c934aaf1fefbb2e2a4922
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebf919d04657440c3353dbc0ad8db25de134d52443
+TAG: 0b87be1916900b3ff614aecce7a809c417cc3f68
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebf919d04657440c3346580b6219c7bbf3003e2e4d
+TAG: b19429b8ff5ef8aa04151851ab09ad5919df2de1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebf919d04657440c333c8bfd3bc03747a4c8770b1e
+TAG: b0b96f109b6b43f204367f06cdae9deb43355df4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebf919d04657440c331d6bda922c761a5360c7302e
+TAG: c8d00b79d1e21e424a613c7153784e19258dc0bc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebf919d04657440c33fd034626e8a417b94ebb274a
+TAG: 38f544900f5b80f2abcd6702007fcde93e72d6b3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebf919d04657440c33fd034626e8a417b92a02b2f5
+TAG: 8ba6adf4d22c11ef5391903edf50805bedb4da8a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebf919d04657440c33fd034626e8a417b919ec5599
+TAG: 860c481241015fd89507627612fd1b4960f8ff6f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebf919d04657440c33fd034626e8a417b947689d06
+TAG: 53fb6027b10d6c367695fca9467ddcd1d36ac892
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebf919d04657440c33fd034626e8a417b992d190c4
+TAG: 1224b90625ef20b8f6a0adf7627d2ee1d4daefcc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebf919d04657440c33fd034626e8a417b90c483b84
+TAG: 1fa4af83d5e6a7baa6e3a5f72b0dc8c8f341c64a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebf919d04657440c33fd034626e8a417b946b27939
+TAG: d99a81cc5960ba7fc2393496e5cbaf93bef1f98e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebf919d04657440c33fd034626e8a417b95ea851e6
+TAG: e11886b4fb1f4e38ab242d4dd793e68eb50edc1e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebf919d04657440c33fd034626e8a417b9b97d8bd0
+TAG: 557791a3bfd6eec0771f41ef830da2fdc2745532
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebf919d04657440c33fd034626e8a417b9b97d8bd0
+TAG: 557791a3393167b9b8c93d652eaf4b3184f60de8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebf919d04657440c33fd034626e8a417b9b97d8bd0
+TAG: 557791a398964dd8fdf58002c58dd016b3077d97
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebf919d04657440c33fd034626e8a417b9b97d8bd0
+TAG: 557791a3f0feac37cab74ce971f51f6c8a5395c3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebf919d04657440c33fd034626e8a417b9b97d8bd0
+TAG: 557791a3196626981d984c469e58cd9dbdf56a3b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebf919d04657440c33fd034626e8a417b9b97d8bd0
+TAG: 557791a3957920cf4d13c355712f125c6ad083fa
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebf919d04657440c33fd034626e8a417b9b97d8bd0
+TAG: 557791a3959d977604d10778701d4a60aa8f289e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebf919d04657440c33fd034626e8a417b9b97d8bd0
+TAG: 557791a315be925bc0428f560559d670314fc393
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebf919d04657440c33fd034626e8a417b9b97d8bd0
+TAG: 557791a3e8547c39955dab18f3626a30d004593f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebf919d04657440c33fd034626e8a417b9b97d8bd0
+TAG: 557791a3e8547c39955dab18cba1bd4b124fa18f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebf919d04657440c33fd034626e8a417b9b97d8bd0
+TAG: 557791a3e8547c39955dab180fda9a52989fea5b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebf919d04657440c33fd034626e8a417b9b97d8bd0
+TAG: 557791a3e8547c39955dab186e5f2f2e46b77507
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebf919d04657440c33fd034626e8a417b9b97d8bd0
+TAG: 557791a3e8547c39955dab18cfce474c2e3b5cd6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebf919d04657440c33fd034626e8a417b9b97d8bd0
+TAG: 557791a3e8547c39955dab18b1397fb75da1dddd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebf919d04657440c33fd034626e8a417b9b97d8bd0
+TAG: 557791a3e8547c39955dab1842c05e5a24f3a6dd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: eef6209c94b929218349114d6ef8d5c1fb3f7107
+KEY: efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7
+CT: 66bbceb66b6010154b427f3a425cb4002071d7237093a9f29612e09cf241bcf9dbba5b5ef26c5f468763ee11997c66a777945bb051934aa50dc6b8e3e58cd0b6ecb92f3176eafb897922a48034338511c537e5fb5dc02e5f3c2926e3f62b16a0f496d76d169fd5c2faf3925842d2f164d8e8c2d576a44d2e63b651c1a7be8759cef481ca11a2c4048527c475a77e5d3fb56c6320007b24c784f03bd089f25db6d6b6259e353ed66cd93d7bbb5796cb890ad88fa6a74e8740e13337206910ecd1908939173997673f57dfe83baeb37f38715e7fe18be32833e8a464222ac258211a3044b2605b449098ff46177c989ea695184d189ba3d54379e5a3a2c92c326ec6c2b0cd67b1380d26afed782905eaec805ff1f340de80ebf919d04657440c33fd034626e8a417b9b97d8bd0
+TAG: 557791a3e8547c39955dab18f60a618ab7fa9498
+NO_SEAL: 01
+FAILS: 01
+
 # DIGEST: 095a8f557f75cba8e2452ddf97c053904b48827f
 KEY: 18cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1
 NONCE: 
diff --git a/src/crypto/cipher/test/des_ede3_cbc_sha1_tls_implicit_iv_tests.txt b/src/crypto/cipher/test/des_ede3_cbc_sha1_tls_implicit_iv_tests.txt
index ef97ddf..09a4642 100644
--- a/src/crypto/cipher/test/des_ede3_cbc_sha1_tls_implicit_iv_tests.txt
+++ b/src/crypto/cipher/test/des_ede3_cbc_sha1_tls_implicit_iv_tests.txt
@@ -23,7 +23,7 @@
 IN: 936a91d0b5
 AD: d2c0267218cb7090c61713
 CT: 144c98ca1f4a40ffe530b338
-TAG: e5173a8e62c8530b0c14b15088f70f550ab57e02
+TAG: e5173a8e62c8530b0c14b1508045d58f4bdae400
 NO_SEAL: 01
 FAILS: 01
 
@@ -38,6 +38,2588 @@
 NO_SEAL: 01
 FAILS: 01
 
+# Test with maximal padding.
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd5377f387bd914c1d64db1ee5f88627b59
+NO_SEAL: 01
+
+# Test if the unpadded input is too short for a MAC, but not publicly so.
+# DIGEST: f0f82752a691ef5866413f2b2e5c1d0ebb41ccc8
+KEY: 7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9
+NONCE: 
+IN: 
+AD: 936a91d0b5d2c0267218cb
+CT: ecd3c8f44675494e8815d0b2d8bcc125612d9ed52657c54c6c2cbbbfe3aa21a0ba23efb64cadbf6a81f0ad53d21bb5b536b10bd2173fe415b8623e24d4dea3db4305c847709b8c489a5d14ae35935e7143f4681798e30cec3dd97b304391d440a4d50f558cf9555faeff343612471935f5e4fbe25776739d7e36e36cd35bffe8c3b582a856cb9175b240338e4de9aa993add7c3d9c0f55aef162ede99acecd45dffa501cd44378f18c0bb9f21541ca639087a208f0a3926bf73766c2b77c50d8dba9ec0374688b733f0abe376387bf02e07089a9a58654fd1957b23758795b6ab9ae20e9ae45d032b99c200d
+TAG: fb9b92af0a7e8ca58fca1a0c2a964df39b1ca348
+NO_SEAL: 01
+FAILS: 01
+
+# Test that each byte of incorrect padding is noticed.
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82fffa4ca54c3a0ffd6e6fff942e7ec33d0d9e6ab8c9ae4b1ef0423b7f7ad15be0b8553a4bd66e7534a3f357071ec070341241592d5865585b277d2f60e220087b1d943a35cf2a72ea91ca1c57f481663cfb4608f23ab8a452a9b4a92b4f34010a7f74e607e2c0751404afd722fe989227915d260720cb3d80c02ea6ed190b832c1bd06037de68b55f9b0d2cc452378f1cd8d3c77665597441b4c0c38fb7f152ff1abacd61de5b25b494e752685e907f3e9112befbfdb722e7fa77b27bf9d8622d3545380938f9f0ab3a71bc3b97ba9033361d20605ebe1af42aabbf4c1dd0bd26e9cb9c21384ede090e23f41cb
+TAG: 340291c471efdf1a9d86f4a9443adeae2e1573f7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f97a5f38e6e3413efdef26233be485092b7a543065c741dc557d9fa7a796edda67a93bfe4edce2d1c525f19d5f3575e81a9b3900e4ba9c58d41e1ec10cd6ed617dd17d7b7a3c49164cd2b37b2d1df52f2b805b3f28dbb1f43adb8e1eb72b1d2b3ac51e96d60622657406dbc3fad9d34535a760fea0955811518b60cc164d46dfb7043e6faf4d29ace04fdbe5a7a559fa1e01e52e2b69009441c1efab68cdefd4eeb1695d882cde48f6c591fdb9ca4225b6d9beb90aba7725fcdf1ee118c1543549f1dbb2b165596bbbefb36b6b849d6495b8f59a22182f594ae273c3934d42d7c5ed300dd0cf5b25ba6d703d4
+TAG: 391d8381b2471d4a04685a1e8fefd934de35b001
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f5092a16f7df9a7114296b5902b1f07030cdf3da0211fd57971f07c765f0210c98ff2639bfd44292b2b7f7fd711a6d026965abbec67a9dd1632781a447de10432499d0c59e645b15be76ffffed3a434b5ea50512c15938f63a57fa0383b9158cb3151215b924a8cab60ee1ad486dd2fe4077e3bbd050c7df52e2e494618dafd5e0b4d7cefea7bae185615b72d51326e2cd4ac10405c1855a500750e4d3ce5591aeb5acce164474cfdecc97ead9562940f9729bfa1415c6b439d53bccd43acb54de78b4777418ff6cbfe8fae10d748b519f589b55bf7b472f3eeb1c576dbbcd17597806fbc6d996bfd0fa0d42a
+TAG: b021be068664a6e44095b51346609295efaad9ee
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82fcc48172be151a13a6999f4f5c476f40968887568c3201e8260d59e3a3b58643195c32c9d49ca9deeb40ecae4afd3b3464c7b175ca26ecae12cce7ffa3b9a2d5b4f73083d4d4c8188bbbd65d7e95aa269cd4ce4488fb136d115cba8f3fbd42122e848b26a8717d4da46854ad45d62700ade577503e790670b1aebf87afe9d1438fb3fdaa029f93f53422bc368b9344d0be16e67deb9cafde9492f39601a87199863277eb36aeaceca693549b23254fb80f7512ea36c896b70f41ec3a515b220cf0b053480182d5fc8e6ae7cee4f781186b9d8c50ca82e848dcce420a2b861b970a1915d6393e9e57479dc464f
+TAG: 1e3f3761c54fbfe087491adede031a2833229bc1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f5b571bf3981be2300d5412ed491b112dcc74e9dd8fe8558efe0d167efb1e9c5808b7de72db6c853b9845201707717795255de40f3bf8d5dab2b6be53b937f7bb67ec8b23205a166802a3641e0b2eea459baff12e6eda2b2d064d5d30c33e80ce6e467fad6d34eb89e2b996a9ef737b4e2067a583750497eb4b32285bf9fcb8590a629a9d186e9eb17265298a485dedc609a43bf1b0ec5f4ee55304164bd180625e518aa013763be1a94736b56844c9c31266e0e7217c324f13e7ce0950d5961ca40762e45f42e080eed79521c124e0d96dfc43964413622dc893a845e16bbb9a681397a42747a9085eca7cac
+TAG: 43778ab01acc71676991abbea0e7734ee6784e7d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f5a172605f496e4ffacb111b8b5482636b093d29285fed444069c9555cc3ef6c67441aad437c94e39f5d3a541de0418f207eadaffe0149ec779eabbb9ad3c35ead995603aeb18bfa1321363bfda10cf0922598d74a5a83be08e9142fb614d33cf8306ca6519c353370ec2c9a68d37f50e852afc190294f8d9af7918ecfce38616eb5ca70cf3710da6f8d224f9d961a59e444aa484ef3d79ce8d8f5d0f0fdf026527f5ef4df2767cc94b97ea442b5b5c4e6eef6d236488b5ba07801f6e425f580738722f065cf2a6e8f5534a0c2e7843ecc510b82955d83e5f4a2864638d0f42041cc16499f42321e05af94c7c
+TAG: b075eb0315f1c3cef99ee88e7388a22eff3a7a44
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82ff2d2004cca0722013e6808ed9bc99b0c4a80991525fea38db2b37fed5ed8632c969deb474122360b1ee810e47117cc1f8286aa8bdce347cbdade770f337deb84d2d0b55bf99a9d2b1bcb929e1391e1b601441145316e8e7663795b581b8807b2bc70a2709337e2480a5c6a3933e0634cb5d5c0376a8c7f05860f66a196ac71bf2b158c9a2f3e6635396de344c58d422a8ac86fab38f28eb908980a012532839e2af2b6984c59eea0c0f49dabf617988e6e8f96931bed6aa1519387bad1fe1a0e1a1b42351d6479aa96fbec4e3f6cddfca229b89b680c22e11869101df2095b24b5b33051a21125d6702fafc4
+TAG: e5d1196a9723a343946473a89ccd2e24b15b1d31
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f7300822f214448a904ccce467c43825a828a1f89dc9841aed04d06f22394a81a8250ed3080d52a096325a3e28f55c93b32296f7393905c99011154f7fcbd9d3b24108687e291eacb5f54e1edc9eb91305b6c3b97d5f4817a294979fd4d9bab2e9262fe59a464da24e8c7a4d5fdeaa4c01633d537f863f798a247f2682cf1066041c63f2490ac903118b54ed11d66071b0bb050296be27c96b0f07e64ef7154055b67ff0bc9c7fd6909e23e6cad9d2aaa57a7eee5b12dbd9d26de530f2d37dd0c1863568b1fac3bcea411d1464ca8a44172e7eb719930db001a0d9c1b2be3502986e635374fdb54d7a68f2135
+TAG: 99e057f6e1efa20d3d423db993d7a66bad349d90
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f129cc6cfd68eaef7096800257ec20a080188f2190804aa0c48221422ab3cc20f687b5945cf0b95de2b60411746cb20353911ba96934973b2ecbbe781fe91931b6521bd212b7bca681d261fc702adf8ac6eb81eed22dd1d76b71ef6fb91a82aebb6eafa0bed1207bf7f27d7864182c89aaf7de10045ce964ae7721df433698b3b0c957d5c65739375d699087bb26474fa50efc8455931513e040e04a49c6ce5b3cce36fc36ad9ffde2040c1e50602d39382d1ddbc10ef74b19022f96384d8e3f9963db95e5c75b4a5f050a658d25489e5ae51b1df7bdcb060eb49c9f7be73b15a54c7ffdcb77
+TAG: 99c4b999b4a9a80fd98b8f87572ee3607324ccfb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f129ec5f9e459a831e5fc0c8fc19c7da28f638f8cd35f59c6436707cd742818493dcba9576d26ef484e7a86309dce93127e795601aec1c2f445ad93e95a8b2e50b16b63cbf802288ac64d89df9612662a009b7fd563491d744f6483c2c683e02966c509a1d3ebec71014a4bcb705f1ee849d7e81bc0e003ef2052f61820787f3fd80467de1adb3511c15a2fc32f935c81bd3eb5e909ab875bf793ce7ab549ea5eabf31a90eb51a533790e2956437221bf8fda72c79ef0f9ff9d010adc0452a679f786ed06e8a76845ef1ad2a2ae74c0bad5c16b43013ad675b4b14879311f0be9cb5c376b40d
+TAG: 761cb73c6fcf0e98219efbdfabafdd81dd1b8def
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f129fbb04f98a0935e7ab3705d26e0eb67478a01e7d9f5b438130d4dacc02200fbd3daf1ead6cdcf635070bfd51adfc13e11b49928d1941cd040938676652e26cec8151d99b41a7b33b2e88bfb9f7df417527c36a374de95c9fe49e72342e6cd593e3d2a07473e1031fa370e0fc21e8e66fa2da83be78498a4ed80d7252b79419392ef9b7abffa81b3b262bffd33644aa1de8b4ceab86c43ead92b5ea47dc1925a08b0604fddc2afeb5bdc5cad76820e8162e65ce9eabd387a843c7023f8d48542845b26390a8de80086444712767e1ec94df27f1c79b04f3c1e266be29f983fbfe060168a21
+TAG: fef35dbbb49213d4836eaceaae02fb5ef74d133e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f1294d5a43724866710b205e90abf4c79e27b695b9bbf3e6448dfc7209a75acc30888ef1c476f1f3e58828690d7ed0edc79e009847d7c5b55359a3a614727c802116b63dff0f17b66815ff79bb6471f8adcbb47791f09c4a4d4cc217baa987506c4b209dc34e9e76218ce8be27982b3176f82642a4ae4fd652d56917366314b63d149827cb560403b9da9760389318a8ca0e3360aebbfb6d73416f9aec61cefc6027299d4babac671b6f1b14472cca56a2fb72a922418d9706a980c139b7291bf648189f0400247ad758a213e936f6a9589414018f83b53a045f19554e8d57e3577d09b2d48e
+TAG: 5e4b0f72792ae1030da5ba463e3e13f9bce65202
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f1299747276563ca0a14fc8039bfa3b8142a481e32af7ae8ad1b7996a12fc423ea9edb5b54169f944ae0be9670401d178700a880b13b025d903035fa1ff0d6aca681c3a0fb486816ded99b090a4e3e02fcc320834b9e3f48704c2eedf42e385db06b3a6cb4a917824c340e1d3f1f4e23445dbc159fad9a184b7692e42c011633f1ffc7d4a13fbc207d5a524321c9721e7323b9f3b44c11a170b88c09140cadb056247bf1194cbffe7f814ff4ed65e12fc495ff082b18ad695b110e5ffefb5babb14e6b67f3142d76178eb8fb1201d672457013c7a418c24d2a8a7a7468792c105387ba55a89a
+TAG: 57c4509dd98914e9370bb464c67aaf21039196b0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f129a0aa04aa6f5001c4b81ff6178b687b310a5839e5b785baa7c21ac7a0827a3ff5df6a145cc33ef346d59dca09674659833f4ffe2ff0611baf5361a781621db8e4df54740a6e2fee4f8058f54d2bde252b9d3b82509b6bb267cf1cc3aa588eb3a71a57843f980d6f72a794fd8c3a3f6f5073965d731222046613999f43e47d1144f4f81973af9196cfb21e27bdd33610d282a7b710e40fdb43014e2f2b4e7fc0c9312a09d41ff87d698e28ce1dc327290aa145f9e24c709fda55c144d418e5cd4e2198e8f6670cab5ce20b80cf9e1081faddc26e1254ea1ede940f819abd27f6df49de76e3
+TAG: 9cf918eb9ce5c18a2bb958082905cd379636b3b8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f129ecd39f87baf0961d75cbb7b862b9111b266712e129f5cc2320ef8f47603b30e67e323d6a93732994140fd5152f7621b75857ccab0c8f95c1562dc671abe69565871bdc42153745125b1c205dbcaeb535fb994608c8f998aec2e49b8c7953ed0adbe34dde0e7f8445f20bf20282ce03391b0f5bbca37d38ab8f93b1b32e92d6c30ab782a1437ac3e1e175216aae74595b98cfbec8ed0341c25370c86815d68e3d7692a75ed487e7dc9b3dde45dcf0d37cad8fbb8f0df52b0af97e028646bfb7c0a3e967a49d2d0f8412272b416da2d20643776aed03c2089c6a8a12263118caa701cb2fb7
+TAG: 1efdad18595b089e3dd9a8494df17ae2d5e90311
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f129c1d716c203b5fb64a76805a473c7ba4fc527e21bf4d049f898645f103dc6d0895fc383022d9474a6ffbc2404d5f4849fd6e1663f27ed114a2d696bd165af078a7319f748d16b433522a3248e474e88145331da4663dc665d6d82ae20ed0c57933d089efff5b42a01a7a96ae737ffcb6db4043392d16a0433a8a4ac59e2807bb47dcffe1173afe6ab1b51e9c0eebc2e5f4cb6a99fb03a450d75b514da9cd02847d0be55c448beaa359cbada849fc5618a3c93e471c228a84ea6d75d57975c555409a704c758388ec55e8e446046ca9cf90e0f89ef5891f9aba75db4e163d2e508ce098a9c
+TAG: 146d8b913759c8a4eaf63edca37345bb350768f6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421ef3b87ea1d7abc315fe960893a0fc8c64e748f976907f46ee28cddd349068ee906f1e227d4e61dab0e56ad2c77056ab7abea02ec4f272e691c393c13f8c84dd33dd9f0577c60ba60cafff4c0995a011b53a9db5e7a7253c4f52cf419ab211a7bb5848cc0d0214d7e04a650172a010abb378efc38576bc8417bdbf3b07d6bca17a81f70280c6c9e71a1cd4d32fc3f7239dff76b0d9dba8b35e5e928369b487bbd0ae71edcf7dae262693cd8bea5c17b298a16ad2156db535cca82ec767974dbc37af39eca5cd92deada63493d3a7db57b5431c91a88d89f3f82931d749a
+TAG: 8608eda1843f40ba0bfb5b5fb0c67df35c7bcae8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efb3364bec4d41a6981013ed7e07e776382d02a3f6f060d488b250ce580c60756e3c10df972122d33baa773ea1066622a9a3714ca8685bf796b11a46b8534cb2309f6fc0656544c3d7b4190e31a4258d5760560545b79cc8b0d5ee9e8bbe0deb15178c7d4c64b4f284dd70e254291e8e36aa2dc9f6deaeea13581259eede25c589fa8a19463fc22781543d33b45800359670ad825b05a82c2d683d00d93a027c0712f9edf2a36eaec7dc7fc12182f7a67aee50846429738d29f7aaf11d09a2bdd8363cd01bae9d15d949e27ce96c3a4f2b34296e1736fd67255a722486
+TAG: e02c9edf65ad422063715ca5c3fbb95409353124
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421ef2f4c94c53e857543dccb7859990090a1843caeac57cb755f7f92486eee4201a66818dbebc47a9e3135df4e0830a6c233eb1254e1d272c40057dfbfabfb07b838260bcce046d6faf71acf3a7e049bd7fea164b0cbc2809c3ad0752af027dc4f976d31c9aa05fc348f1c14a803b59c1c90856a2f32af78a89574badb056b16d856605ed0c217593b3cff969e6466b32c1119705e47085b6f9b2a76ce52831acccf3e9ea8651b3d520e6820a208e20a15c71427d29db3f0bf34066b53978c402a87d39dd972720fea895bc868247aeb90103098efdd27488ea83701a302
+TAG: b6afb8c97cce78b08d82c22343e403b89c2c14de
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421eff906afae2e433a5760fd55862cacc6d48a7dbafe28054dfb27dbdf143cc62c89d2f803aec795097fb15ef43eae56c292849499e401080ef1866345b3c4c9260d78a284bec85e7aa8e73d293009cbb204b119f2099b44eedb155dc269f0fac35a1b5c65ea0688bd4429bfe29907182070631d3f302b86520c02593b843d52dbdb2eb2504df4bc8d4ab4587c627604dc521c8538757ce8ab547ed509ca013f709bd99dc34a85808c4358465270c88c442079e8d0e38c745647b5a2efbde553662930f61bb6321124925f66d5263e1f7b1b2d995f7a0125775c0b11b40f
+TAG: 717afe257cadd23b5fa9d2dd130d252e91bb2798
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421eff24819532092ec210db7f3ff075244a61fe0f5b39f33985ae99f7439960e297c947466b65ef94302e32055e84fc3a4182568df26736173a19672b6ee47819a534e20e2d0c5736b32d57628b4a09770e28fd28941ab1a21b4b8ad1eb8411acee9bebd8fd5104f7b4d0a1358ad814ab742f4051c82ee82974ccf570d23f87cec9558de8276e18fd34d74a9032b950080fa0ca4da66519026a581cb0237bdbfee747e2389635de3f98d0a6faf2b350f1b20bdcb2e73134ff5ed63416b440f439b551964bd7df0df4f99345bac2414fcef7a836005c1d3c7a89d1f4ff870
+TAG: 22ddb81eafc3e09f8a3ff5107ae99398c2c4f014
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421ef71d70fb138ddc82dea24731c40c6753e55c14e36c580f0d0bbb83555db95eddb0c0f127463239f4e5295fffeabfd760be950750c5a840201bb0998bd61532248e31cc531490201d88867c31bd2a52f327aa5a5ceae341ee118c9cb6ee09e6f491e9e2bd989c98c939ad13acc123b5f246dcd30e277b299ce8974e015f39a60de5e04e329daec146fe4b4cbfe9a26ceb9baffbc9561dced8e7b2201493866310f09dacf6d4893845eb4a6c0f7465b266eccd76f0be5d39b8983450727cb0a6ea9454a76547aeeb4a36f3c224dcd11598d23f0d2f7942eba32ef4dd230
+TAG: 421fbd4b75d9a53192851e2525f498c592227c0f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421ef6f0a30389b6b479fe2b8012a6e61c4988480dd7d4b8bcedc9417402ecc5c5e8ae5bd0d7bbaf962c32faa6d7cb264cdf3217f5de534fcff95f78c46bd74e0a8c9d50fe6247a7461446f8199ada59ea6cdd106570331596234954b62245621be91a036fe397923eb97375ea6bb7b0a5f2829352c5c84dab9914e64675a52cb08d2ae5796b6a1d7bce48782f86f976310a6e15ddc4f8bbe0677bb5026e971a935bc0a997f040e6e731c54860e611f5bff6dac49e0d30c33b59091bb142d83a06fd9fbd6bacd0912e989611531cda1d9f07ff7e0b6dd5a781d52fe2d74a5
+TAG: 1294c87e2f022b6b322e0ae1bf5cedaee45afef5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421ef2d75f27ebed8052f412669a100e2be0d58c67dd73c799ee5166d36ac5e7e3f3a94d3a4ec11e2fbf93797167b61b7ebecaae7bab977f824efb24ac0cf5134ea48cfc12a610f3daa7c245490d7f3cd9b2e5925702b5629d90aa4a6bc07f89a309a9b5e1fc3998f5d7460516111b763a9c9e2bb5cebbe7954bc2bac4eea29efa1b68c943a831c7caff742646cb664b4c58ad25fdde1837cdf66aea582664539b474150276e446ae86aa23c575f8385a4fd4ad9307d82aa5b0967aaeb9a0e27c48433667650f7e2352ccd56bd9b44e96fbaed52dc50d499424f31d735024
+TAG: 36513ba6cd3fa1b0a01969bda4fc7d5e44371cd8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174143aa674f9a9d34ea4fd9b58eb6222c138d10e78864d0175645488d47270d953ca505af7d9efb72f6ab0c9e0200f2a7c61e23c483448efc4a106304d1644f261a023d6d52b9a9e8b1d42941eed96a8c16c48387a8f3b559ef23b82558682ac8427639b1aee6610e15e09c2d80d74087a8f18efd914d71df8f09eb76994eff14f975217604897b3bb2ab79ba3eace775fd86d1c16fb695318ad89aa1e00baeefc188439c49aeda0f543196bd80188b4bef946757e42268747fbf4b2b0d6c87c1ee0a9ac0390697a388ab629123c09eedecaf4d231
+TAG: 79b685adccddf7d36f4811e49bf42228b2a8eeb8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af61741501b81aef8ffbfd1563d47f0a8c2fb1f1d1e0523f8f34f7b0e8ef2787bb53b81b335ae63e8109ee8b3ff407ae36c16bf8696c67adab0e582def6789dbed3f74bd43413fcccfa113fba7562f7fee118e36e445e3a4fb3479f6022bf02170135bd4968ba1351f8df56e4de1344bedd402068709d1089a9abc71a45b2632210a74d6f500677e4da747db8c62c6b33265690b1d60f8a2b71f2a79b402c7fd014cdb14f9c5d4ba888c551351d709681b8b248a8cb535e0f1ac7792ba06246721d66e9cc5bc9e01b9d26a582b543e371cfb5fc0bac75e
+TAG: e60f5f43bce7dd98e56535afdece3c14fcc2f700
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af61747378a3a5d06148a3c44176381b30c927dfe85959135ac610266cefa23b9d34f3c49fc727732994e3194aaaabb88617319a1384166f797bddfbe9b89e9aa4c8a4a32a4b6805ba409cf3e54ffb35917da27ee29a099d91e1e60ed6c2dfd8796b952106e5ab79f2bc5e9c8fe5fe5ca1a4f5c4a6b23a819bb385f52d1f08468a3fb2d3be84e617b8e8974819d147e3e48db3b251cc4218fbdb5ba496c290cc7116f21e56d7f10beae592eaeb6e1ce6e6783f54790d5205d20954ad0b2982a7f57b5428e818509a266db322fc6eb06c598ef553028e63
+TAG: d4cd8b0e72025ea96dc9db64087bf81bbdd12e4a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af61743665f22dd52c9c1d27a4a82b5630906500b7e82d39540ab0f0e780279d6013b8102f4c206f4bef8aa7773ca1c3857cceddb49fbf32922e765c32cdd24ebad44c5404331fe5d2afb76f4a17c4afb1fb401380e250a7df1026df1ffd45ba512f498f13d3c44f5b94ba3860f5af5e1faabfea84ab9e8c2b8553b304eece0ffe41b727a040b2fb5809b2177dacbb8ce7102fd6470a11a6f012688e59a4730da5083ab748332aa5f81f90cb710903ef895763cded2653d988f37c8dabb44c7414f62ef1d738809288993f06f21fe06bc116d71cf651bb
+TAG: 0179e77ec1b15c5e93f6eaaad8ec1172f128cf85
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174ee55df8fdceae223fe451dd828a2afbbf92b7bfc9b77735f62fcaa15a7d1c45f5b1705f4453601efcc6afc8338bd5b9c4af66e305cbe5349bf7883f69420d88ad46aa4ce66482c6b042342b8d419e27883c2ba025b5be9ea5e4bc4f0006488b100120f626d8f88b0c6d5a05dc2e914558c41a262cef93b0ac33f9b81ec7346b2126a3ae1d8821a26c40d6afe89bc439a4e58b2d1b4b9d49b45f531fc94f83e7ab5e93f305fdab01be26bf5b111646d3fd9ff57157350a0c43156d9f83fb592a4c1dd84ed8616075068bf00821bd29572260d914c
+TAG: 59234921759384df9280510cce0b6c1d376f0c1a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af61743b3fd9b98e7d508fc0459f8d0fe938cc9406a1dad65a6359bfad069df70652f868ad249d53421adfe68ac08e1fde918c6318e08213b264c6a7b28b45369756a7df10ddc914c5ae82121f337c95b695c84bada5e90fc28a3612adc98eccaea39ecdbab64d1ce3bf2aafbf38842013f77a5f829ae6bc7dffb10c7feb5311217e1cdfed1e1f6618c1906bacd937f27bbb5b9d40d378856ea281944bd3336ace52b1b276d9cdcad59a1d986393752bc4b444eda018fb0134c171fc12b1b04706c0a0873f9575f62a6892ce765e5f1a7de952f2efd92a
+TAG: a75aba394d6d07c125e002092377452786612c2b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174246f8bdbd7b714a5fafa1f56351aa9b5819298c8dba432750e5bdc98f9e98d2ab3e3c2438912cec4b22522e051f6a9ed94a282e7e2eb76b51dccef203f7f86e7e44a8fab0e95468bf824bad2af0690d8f9e3e9647207d40ff3f1fc6661800d1daae1ba118fe5cba6edd2c3f0fd1152e4f21e96d662305285f71abb00ec874d8c290e38d7eaf0db9777512ff0b0522e9fdad685dbc662bd99882e20198013ce72e1247691558a35fb8e902f3532e06201f6ecd6a5f2c83b00e6995c0e4b98c9477caca5e9dc2da4ac90ed29268e16685627247fe4
+TAG: 579d1b2bb727bce33d468b22f3079aeb1583486d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af617408ed59b9fbe8101c419011e03572b1a0dd51213ad7c9293c2795a572d87c0bde407d128d65203a0718621722f59dfff1084309674bfc18c1d08f383be3868e1b79401752afcd39f1c36472891408e3f00c5c479237ff92ff9a40510b921d23e69ba6cfe9f545f491a96f10baa718387bcc13b0bfd9649cbf04341368ee4263b72082dd82c4a1d57ab50be52abacaf6502f2812589280bb26e3600f456de6933f2e08f2dcadbacb728e558816106afc59ee64a79eea30963a06f63f7ea8e9cc2a7a513587df072aac03d05401d5f0ed58d0208998
+TAG: 83854cbc63809e1083af8cc74a5fb950e5226318
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086ad618a45237d9c0a95ddef0b61d4fd1dc37c472ee3adca441085692f96b389d279da0989f58176bf9ceaf6f0ae012f91c35d4eebccb1c53346f71595aedb30d3fcdaa60083e42d6632c8078d1ec7d01b84a59d9c1f3ff206b130736795b61329431d936de4c326c7c499e47441939f34403fec2ba30185fca15e53bc1506535c580ed2a813558bf22b4fe4dfc32ceb492433d39f723352fdce0510d979700f7414cf3172ba524dc0bb56ac837f9f485722e41539622ce7b06d7903caa82e8e6e07afa97312bd6639037cc5666
+TAG: dafdbe7bbf9d775fc759877bc3ca50bdd5361dcd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086a28e661795e3d31ed0075b05b5dc3c943a4578838fbb8875fc102324695d783c8a4bbb464783d23f13145b7a09c20cdecd7f6c52909c5707b3b1fcf029a70529bfee875c0e555e0292d6f77b81490be978c09cd0762d7f714f07d083b7e5e349240392858176ee672b90427ddfa547ee3f6e8244f6b766f1d14cbc8c8d25efda5060778b3af4c43d7db953c607fd6d601b68a7b9d14db2147f6f45696cc3a56fc20a199eb42af954974d77cee8ea875830263c1925b6ea2095958bbe4d5e74446fc29b715b69cb89ffccc584d
+TAG: d1f6c86dab063f42495ccba85b2d7d88967fc9e1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aef3aa9e85ee3963708edd8430116e03d4b0b8bf3f899ad2291448454fffe135120e3573b8d88359377b37237f36f81d51f18295b9b7ac3186bb03cb507a1d9f0102738d7382dadbf3d0feaff7e97b618390e407b881012e7f5384edddc5da035fb3d165bd8febdf42d691b7275d3343e90b507e7b541478c43c07ed891e9647a547f19b35b89124f06c219b65367b081f7b887b1042f6125c7c673a4183de37529b805eaa0c664dd08f6fd3e0ee5ee92fdd34e6d3b0e3a3455862175af1c6d0350bb42d5590d7abb22e321df
+TAG: fd5dbc0237285658a151e88f5ace72b26b3350b9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086a4e848ebf02ae731972896df29a335c8e55c2208157ce0a42a4056660f6a40ec8c27f738fd068cecaebe43269d781c72c4a4d5fbcf527e0848cf0a8dc1f08e75f44ac7adb354bd6a8c215d5385badf314666b9982474c6c33f65344614d85a638e42b4c0bffb67385b7869763113c6ce6f5b2b379e23c001b274e8d25cd5f1badb71ae39690bd48c6801874f2cef87f0e1dc6aff6d4fb1c99f99ca3167bea53ea46714f35c2457c3b35307ef2b11999740b28697c0a3d18435b258ce45236953e56d6b06b539a53477cf00c80
+TAG: 96e1a0f1e6d9abac19c7963e3c805cfa3f05dcb2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086a044370470dfb72314a5806e0a83fb29a59a98d337981c6c5afca5348fef16c5ed938cefe9797d392a59cd07d94858f94ff0f4375c71b3688cdbb057a903e7773fd9e0f2645f03632830f70ed1507bfeb10248aad345420828bdf4d4b02f7dda82b49d6cab20d3a8068e7c41582cba64f71076912b13d98761d0f93abc68f58a73f6ab18123028e1adc52558bfd16687f5bc9ed11575258300999ee091c5f26876fe98fb1ca3d84189f3f05e0e1f7532b651d0458bac9a43a5c6ce26e76dc886828daedbb95f0f0864f9f5a7b
+TAG: 88384b195bef9ee399ab25faacd52baab5f70919
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086ab05d59920417fa42bf3fef5a6d2bb5c39d1abe3792bf64aeae2cbe98ee02359f1ced80535cf6fefab5ee95a178dad66d491331d25f5fae2ba189160e7c68d656355db48909f369d6a347c4ad0cb7d51c792ddd7ad681b39f153e3717d2f259f7af9af0b278f1c07a55f68d51e8be7836f21a83f6cde87534b820cb0eef8a372be01582976b74ead7afbc14526a019e11ba95b16d50d85530f0564fa92bcf7ae7eb6f0288a982929bbf7ab2c2fcef6d6226d466fe8940d4a32c5f558f8d0b52b59ef9e6e63cfc48c8e573dcd6
+TAG: 3989e038cfe8c8534e167b721990c4805ae4547f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086a896ed500a14188ebc9dd1339e7289e4ede7bd0a7cfdd40f05bb6790e63a0f3195521cd89db7a314249ea6293bda3d785ef34ff9866ecda01ba422d50f07f23a09109351919611cc01fe5e4c6dfdf4de21599934093d4a7e46b8dc624a966f28a018084d8f70b26bc23fad04b131b77dd9a2ee5565d34b07ddfb352e6bd53d0e13090eea31a16f2c9fb5473e76251a752bc1fd93f9958c826638f58c77a22e5e02e3a423f616b17270bb6ac3b2221a1a1a5a9f5ccb14617d6106ef85dbd8701299345b4c95526ee2f0ced4018
+TAG: 95929697b887e739f938a14662c611af134b983a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086a1178d6fa0773da2e31660c8886de71b954b47e69982742aab32850b095660fcf3262cdc64184ff8e3a1460dc9ac6acbbd2c957a3fe57c3d480abd44dadd3a6c63e60fa25d7084226f1b1214b0a5c57117ad975598c4a8a3a4464c6db8148cd736fbe887308b7abdeb5dcb49b7e618b00339f3e3be1d03210627b5b1d4e7fa70ddaf43f9965be79be0f34652992983a1390937900fcb2e44eb7dedb02307652000d0b3c3506d3145422e7fcb298dc6ed515e155686566bcb481a4cdda6ca8727d7f8037d9a6e0ea0265b95898
+TAG: 990e580e4963ac947ed6be52c7f6a958727d1f2b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa37316630e673ccc7cf6c2da5f28c2fb4fec9506f1a4042e808d5073db0fa7bfa6e7135f2da825e713eb5b9ccba40d123ac5b1a4a58dd2fbdf565f2ae6d6ed3dfe99bef9e29e6cbe2b70b87594d46dc71dc32e2da5a6e48eec50bcb5860fb9b367dfd44cfb6360eae83eb45c3a7e9bda612e8e0b0ec5e6a0a8c8f59839cc58d74104e8f22b261f84f36765d258ed1125597e39814cfba3af0cb1159f6bfc68ceb64784cb70c1786cf475c7c719a4a005baea284f7606840ec27d623eae5dde3285b802cf860
+TAG: 2c1592c6f68ecd194528fcb284b3e1319996db4f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3785299afc5368c9d58aa35e350c31a1c96a4cf04239cce817168ed5b823c05ddcf12207365fb74e73d5d2d22f0ae6998d7304f9f887fafcc83caaaf4bfb9f792b144fc6549511fbbe8032cb0d8187fe267c2f0da624e4ea204d865c9e9d4a0f8733ed3bb061102c2c35e044a1c70d6abb9f357fbd01d8c52f8ab544573fbcab8ac9f92b3eb00de1be5f50afdf90b7c83d60821618fc38594d9e440118660f3a84cec89e53b93582510acd8108121990a032365ab659178475a65fc8d9245b1f58ae1a34f9
+TAG: f9ec8f4b2bf14265cd795940cdf405d150b19c3d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3795597706c936d52b8363ff1db2434c2eb393c7c99854c0246a04c7ccaa7c87ec99dac909398e91f71f5d449c56a026a3e36da28daf3bdda8efb9ea4cbd1ea0c9bbf4225298b507f7463539276f6049b89e66d506ff1e4b0b8dc65b1a73954aa94fb66a31bced7173a5d1d0fb4af539bd20f68b79cf9ff79e597d184c0b2beb027f3b09d1f425038c29f8e88c7acda99e23a76080f304df3346950793613931471233cc2cbd6b239b67cb9c673ef0433c546f52f28c3e102865727add96dc02166faf4918
+TAG: 3cef777d7db821552b43864120c48a27d5b30146
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3751735b66d3369f28be6dafa382eeabddc542171bee3348f1eb8f89cf26d80420885615338ae05fa9fbf5231e33ef7525fec5248df06e1fdf353558a1817b0011bf27f31508826e21f2f074d47246975234484bad3dbff4c1fdc528c71f5e2c7681d501edf4682d6c3d2e1a3f2bec92d736f2d033d1cf53ac43e430c5a98a181e432bf6b43a3f1a6174d7129dd9a475cacb8572718e9e4e2018f90a35d516cab173f73d98e65d348f2f5f0b1563a6f77f5e174f85e091ba0df0189a1687d805b58ad6cdd7
+TAG: c907c393603cfdaed879ff70e93f9c187db5b4c0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa371e85c9153345e80e220265df29120df40294412855f58fbd4eee0ba9f158f72c9e1a5e5dc1cb5c633008ec790d3b8ce749604360f2a98b4ac99f4d272f58c55e553007aacbea5b95a416544b2f189f087a5cccb0899abe97bbbf69b753f81972fdd1e1dbe157f98f2fa23b290ecae71c5657c144285cafaaae027d129d332e42a8bb3fc15aa45c7371b51cea82e609a04a2e76f26bc2132de5ba4fbec67ce6b527cc598426afb0274693154401ad72ccafaa985579969d301984dc166f1253804da1d6b6
+TAG: 383ebd9d3f35aa17d76bec7ec29db344f62a0e8d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3719ab703bd54173f1ca7b93c7bc0ef607acd4c3f18f0bcea7907a90d0e0c33156dea40bbdc1e7f73c7c466770f2fde4ae1c5deb1db6905d38db94b5bba22eed2d1d8bcdb62baf54e73dca2a007063137732ea08d120aba594ac5336226683d151d0af5519f76d203da0c048d7c14973705d6207a0c68fbf5ae4c7f7f38c55f3ac52d2f9ff4891997b55de429a5a31fde46f5e35262e4a80c25e5645926e99441ae996da98d7acd58075eb2a9af88f24f9dc06b9502f29d3948e8545c90bd8e31d84856e7c
+TAG: db9cabd974846222fe1578714bdf7f5bbf99d020
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa37401a3dd7a2e9d4b10fe82a3e53ac33ca20e4ec04f05e4e3c8e4f75b50b6376af9ad7cf35d3aa61a1cf2f8c363976c8d1cf9be30392d1240db8997a34aac358810f375ded1ccc7a54d5ba3919364eb1e6da6f1e31ca5690a552356f878bb1d0e67f9a4c7a7453ba382b814c199a109edc528682248e9dee966ef7d2ab0393f34b5c0d12443c47214c0648033e323e21801d7bfef646533ff704bdf972e21556fedcb5cfb254142d4123588fd6d5ccbb62aabbba577939e66188e5313b942760babf1cb2b3
+TAG: 11855563687233ba0019182fcea2e1dd7ad9dcf5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa37fb5ab4cd88dfc04f36f7c0f513e03bd383262bd615f34511750050fc407cf45b918eb869cc70636f8dd58c887e27949a9ddf60d00afd6aca73cfdd2d197d396e8e887a390e0fdb7602eee59b974db932b2c026c34fd3439e8674160ae283dc2c912e230410d2b56bafa3f90db4a6a02512a3fbea3ac9b1040493feb981fd9d69e79756d0b69008923f93106136c64f8f83872538f5c5abd19907677d6ee0aa4cd1716a20ced6eccc8d21e1549a89be806d5fceb39b5a870707109677e1cb0fb701c6bb8b
+TAG: 9052fee68cfb46aacca8a29c776b554032d347dc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a7211c40817f7caef15641379958d61692e359706965f40965da5a59d31c5dafc30b8c425bd0696b6cdecb6a52f88df56b3d76428c489cdd4a9788dde394bcc9b848a750768bd76b4ebd935f5158da85ab62e8f20b4d83a1111f7240fc825ea4f6d5929b6db7c6002a4a98366bdb1d80f35a1d265d740e71896a5cad98d893831b078aaed80ca3363cd1e9490f5b0785bfa9c765585e0caff875b14264da3344a4e788c97b40f775e0f431b9d17f73419fad1ddca14163e12d68e6ea853
+TAG: 8fde1d84000cd10689db14e7d9942b9cf57035c4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a72b769fedd6e8a09b70d37418d3284521e46fb6f12a98f660b8bef17bd4c31fae53c9d3db310b9bddb8d66bf3bf2da2808e1491c5d822a09f5160296db2725e5f5305c15415746a89230e0708b50c360c5831c018d65a35daed69a5f4cd2647cd3f37806fe365be742ff6769b91e6d3274ad9f24b3a27668fa434397f164709bd08e53878b4d0021c953c92d1fd4cbcd94b2102fe6ebadf37fdd2ac854e8e38e7b7fb30cffc53e46dba4c4c2a2eb52dcc8f64cecc48d03454048d0f609
+TAG: 9f350a66ec0d6edb91230e06ba80cdd33ba1931d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a7204d3172870e0f763c223783586c033c8d650413887e1028ee9746ecc711c56bea218347480c048e0f7c76c9ca24a1793bda3f4d7bba1b50319fb8231e40259117acd68a13a4c8d29b0929af579c29bf10cd8f90493a4fa1b9c70d93b2d1f26e8a3eb460f4386a87518457e6cc14fd7419484b4246488dfe97b0dfedbc18e1d1bd0a5be6e4634028b37efb08462a9ad716eddba8e53def96d6240c9514af34edd35ae731671f5ed5e5d4cd99a1cf70737e5c1d58abd6d2eae339086f1
+TAG: 5745555c182090c7a07d01f0a05963a2e799c069
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a724c9bfc24ec7cb7cdd819c9239afc49414e91a62d9c0a81d4a64500b37484c87a12224532472056fa053ddaf12ebe4d2f94ec915125a2fe13a96adf4590a530361058d61025d9d76d63978ca3b1da2c90c20cd1ba4f23bf052d19afb074bf69965d19533dc55061eeac10fa1c58c131230535cca5bfec2605a000168dd913d06828428ddff1b152cdd3e8831988d407e989edd708b2b4a64bd1634e72b7e8300b8a1824b869b2579b65a78fad5f0da376f95ffec2a6072cf83c6254fa
+TAG: e56dba6cf3105cdf231d1ac45baebe4dc4838382
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a72bf7bc3fa52a5973b4ff104555a469033698076e50f3cb7c963989779c5ef11201476f101df4c9296cb1245322391e3e16cb63dfc9edd300f203a85aa7c6eb18c471fdfff897903b82231634737780ec7e0f86c6fc81600682ab88537a6cd569794db84b9a8ad7e5b17c042f14860635c2d9052735834ab9a4daa00060629ba1768078db350d1334692d046d7760408e051e40b78adf6a138db3e8f425b3e29011bc66c1a7b9657ddba20edc03d92339ece75ba90b018784e188cac36
+TAG: f25ca6fd782639b52862812445e825fc33571062
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725423f1d2583cfdfc30b7ad9be0bbe5b224131f9fc0b7d8b6164aa7e9a551e30cb7ba88ebe430f1890d09f5adb2110c300a4bab15ba82228e49f53272a4710a75aaac12b87873ac9de71f7330e60f860bea9c3c482f2542fcb1098dfc73fcba660dcce4bef6a24ee01ce1ddb4cf7d01c19256ded2d522d71f612f7c1a56fe287b2be4742ba6286bcc2171ec527e36991d5ac9cd890c80c2ff11d95b189685e675e7071af71daa90234b0f18c37ebfc93a59912e02a19cda9e2d4cb4b8
+TAG: 2249f2872dc4b1cc850917d4530393c19196e4a1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a7298e797694b9213d9130ad0bcfa073590d8ed313ea3eff439a813daf8eadc3b2c8a2b22d9ada036235f093155fbedb1537c1b75714fc9c9bd2fa47e3e53c43931c1ea5ceee9feb5f2bc09867797aa25da4496857df7d773bbce3c2e89ec2074be88b1b4affd39ce89f5976d131a087b9d0510ad71f2025d26066367156f9922cdda71dd56820a380e17e8676a1e57bd5860d23b2111a581194c9079d92d9c6e82a917cf0f440be115a7bfa52089b8837cffd8110a140c768add8bc082
+TAG: cd3cc4c5647165faba74dcce17bf17ae4b2747f1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a72b7bb632d872ba0d3c05c0371fbb29c7c87b1ed16146aa91743f0e00465c497baa4bc1598fba0518c5abcc81ce09c1a915a3cd48956975f20146479d0d51674cd81de8d82844d3dcc85828c0c9616b9139d506c28fa0b98af16a98c52d545174954ad7a099e31363f9804b5320ea120ee9a88ac476108c0259add9e50c2cf7732bbf2936588cfbebbd1dc8339c3afb6e10ed029ea749abb46f55bbb471f5ad7c229fea26d71ff30628ea56a45b14930847684204c6201859b7c5831ed
+TAG: 680cbdc5bb9d8bfab0bb52bae4d42e3178420740
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913e52851cb40127e51bf0467e69310a9ac8b9e2e380ec8c6e31c9eb2933db6c28571dc4c347a55909617ebb38450d5bf78b376b558bf7810a3688390899c48f8f80da6dc05901ba9ddd8515c9c9bb4e01f4ec003a2a9c3a08059f9019e26c4c9b969eb3492022bbca7d654b14e0daec72acd50debcbbb24f6b3d74c0ba05596fee737bde5a5bb8c61b43b2ef7fb125ca61e5921077d1f0c420c2bdbfb9b7a248274cf9ef89384cf9bb3808efe7843f0d8c9f3ff16e3
+TAG: 06e08a54dab05f9d15f301624eb149e0e63ceda6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913e438923afe9c42c10062a80920d1cfd44b278bbb0f416a6667e9c5a11c5fc6e074ab7feb896a2c9570cbf44982d2806d024d188006ac01b20a1ad5f08436de62366544a85421e8467fcb3daa07fc8bb3217c32ab5e9e1bd89c42500ad0414e5c6ccfa142edbb463448c8b5dde7f4986f930f1ab99c505d72f4a8427ab5758b0e2be38fbee29394893b7e7331235e702dea1b8295f35ec77129aa90ac630b61cd6a05ad84b0215502ce9dfa51c81e1bafb26f40b27
+TAG: 1fde2f047a09c3502c1cfb0037e60bb5409c6136
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913ea08fc603b133684831596f5ec7ccdee91e0926dae5c8c8c8c433c5b0381499c83fdaa716d70f31414fb54bc292907f8543d8a96baff4ddb2eadfa8240ac0cef02bd1f40cc0385d5d446484ea7a6d7e4bdb08e9190237e9be59318d32a02df2b75a980519ee35f109dc8c83e92511a7d71e84a361d3aa56168b3ab8c7660b97657853e42b0c03fa11ec1b153fae3a49e6bea8b73c2b98c5fd0f7fb0e58c9d37524f36ab440c987760a13afd2750f7cbb92ee1eefa
+TAG: 9e0f2e8ab120e41bda1619e9c5baa4ded6c77225
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913e4e5ddebda8ce0a8659a7f1eb31a02efe9fc39d217ad5f8ee1fd9a6e39cbdb806ebf4bf4eebb89fe682ebe4b5a425dc7b62a386a8ab4f2b4d3522d74c0d7f3dc2d1645b62289595f72af5bdd7381281fdbbd52184d57307632be8fd4c6c5569f1c012be075a53a17fa6a3500ccdc282fae036d3d90dc7912397c15fbfc55cbb83d338d48419b743a5b574378d863f3c0841f22bf101717e79394dbc4d3accfa8d949d2bd9445e40e0fc31e0db3c1b37898ccc9478
+TAG: b1e77bb7468f121a8f767278d302d179b5db02b3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913e4345e4450919855da468fe34933b0ca668f921378eb1b17ec3adfc487566db41ddc2d7de71c29078f162d3b6a1104bf9f3ed443653d96bb9c28af80b9da1ba9f056b92b2e336db6f4e05febc53ac4440e8483e40ee236d63a7fa0d4f09358a19f65c862c25b67ed0e4d646f7c1cf371778d82521a18b0d996695de9ec26b73302ca148ef626be919aea487e38109a47072cc10583564cbf3873f0321ed97d28f055a119daa83676bc287c6bf17b961e26df9508c
+TAG: 7fab4a7d9c050ac44a4918e22d069dbe6016e3c4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913e4a1c448012977826667b2a5b4497c5b0548ac15b4cca6804b5f400d58112af6f086e8a94dbf7eb8f6dc85ce2cc9933989de4887d13191ec7c4e28deedc37ab83950fcf76961c9b4c322b458565355bbe24579f5027927935cfefc9489ad26ae7e325f0e9680e66dbdff6e225bcb0d14833e02bd9ec23075f0bd2050f1e4eae171d59c3c08e330aa385d17ca4ee6ddea285d9bf35b0fed792b83c2a7508f1c0118f5cf1d84528f14806f80da36b3180a3a0fcbef7
+TAG: 9fd8860e193f06c470f135267dfbb3bd608a6dda
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913e9e109e220602aed717a3204339140524664ac4b24553772aae83cb0e3101f11b62397190bf4d7c145bb9142b1df96e4b983afdc0ca67266f8b203107851a02059e5e628bfe4778ba25505414f71d948a5d42388772b389388719bbb977232d463398d0a7b1bad8e0fbcb00101c97f158ce5091092440214248657c4aa933d591264f8058b5fa78c5bea642bcb2d90c20c36cc105c3d8cc3e5821e020b5afb7ab76821b044015f9856cc5f53e2973eacce9004575
+TAG: 4dfa451869851d157b3b3fe72e85a1cc5af01569
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913eb85cd0b8d2f2334af6a963c5f6fb6fe9699ca1da134f96971e29fab466c72acb7d75a019e1c40a6de3ac017fffd0f2ff74e8f52a4d62005c18b856994bbed05259e5ff5c3e4b058f38374903635ff6ea2b249edc99b58fa27c3b34ac337e0f80d62a97dcad50d14701ffc47ea25afff8e9479e174ff14bdb29c141e80cd9b88ec0e0c76a4002e902a084ad8a7791ac82d6d8d8e9598f3d7a8e0368f20e269799d46e165e8dd3992b1bc475485f2d06b21a9c2c6f
+TAG: 8e33b9cce62caf869be856b319cc537ce3692132
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c445856aa0831c9ff000cddad47c9a523ba5c55fd576d720428f81f042f1fc1fb261ee32fe9fa9fbd9d0e99f820ffa7e23d8c57ce360373c84c9262a9764b0053f90bfeaedac7db2c4d722f6b32aa789b2439c3b9099e6878171c7f4467f06ad2c8bfaf226df35c9fb7ac14f398488fc09e89065efd8af9a24f55cf0325381abdeb21ad80983cc52b335226f7ea3fc64e5ee67eb9ad95acced76c06b474a4e1977b290076c8d87e8d29d2c77569853
+TAG: b09d112a675a00032cce740dc3637dc09a8be2ee
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585620b8313e25f19a41d65b755184d4fdcdfeb6b00abe397d2de33a227ca04fa224160f0662758d2d1df1675f5007346861e117c55ee238171ec13661bbf773a72afd6ff591af5f676688ec54d2944630b3045fc5fed12ac61ce047549a08350f0e65b6425f9ffd77e56eed3a790ab176e31acaaac010f5aa3135eda9afe84e85246b4a855524e898fc3e7274efd006315e5efdde0a30e1f5fb79c2917d247cfa09bd1ace2ca5cb559d5373a28
+TAG: 59593f8aa8d8a92d10202ee1547366e2e1985089
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c445857e9adb562360c4328eb4234d420b33ea681db5af2f1c88f4c2fd5481d6257385ba2e70258f426db5710cbbb9aac13861048247606a9e321c3a8109197742b948db4d6b1a19fe1116fea89c1ef3d9e2635df46b895a3fdce78a7e8ca0d6154d735fc80c34a8fc65f83760502756ec09beff9a46f9092ce9f8be3a8beae07a4c95df84411a848ca45ecacee3f711c675f7b48f753d89168bc8843df3464d2bbf9e55c00ddae2533dd0245907ff
+TAG: 25609a2bd60548105a630be08f9926ea768f874b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c445850aed856bd18a7cfb582eb6ea865624c16b3c0ad9a1755211ee9d02e93f43c4bb0a6ea3db5ce6a9344bcd96c62800a2f3478c3524d140960c9a7ffdd8fd80c09594b3c9c4c2bf001a690097b1c0bd7f2f45730981de3ed074525f407265e32d3d012ec2950178decbc86f86bc6f905e5dfb86d59e481bd05a33e003ade74c231cce03b5b13854177a97bdc6e45578ac78a964661e3bbf5d952c5e69f23c10fd627cc93406d1ef3cd52e1cfddc
+TAG: f93a0157ddf0a5cb900039042094f8fdd4f29c51
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585a41ea1528cc5c1c4e88f74582c26bdb770348680d3ac3b7c07be1ccd7ce8d3c15637a9d4c5268b5287e72406194d7e36a1d62c5495cdd008e795db0ec9958ca416f947e9264c02a46f9f84a588ff2aeeb1b7f222e3f2505f00b61aaf60aa0f64a13574abdb7537b23f52978d49a61b0ed993b9d6964d0bb3350e0c7283b5725dd3c30a9f9831d9cf79a6746a1d73a5e73cc90c5486979ddb8760899e30660961cc2993909a704f8ad8cf2c51
+TAG: 25a2507fff7e365d9a3664888ddd3a284ed2a5bd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c4458551aa5c4cbf9f441451c32e98fa84b217d048bb36f60c21d26c82f4db37c9e606e10214fe5be6409f0de3d577c1dae8512ded253eb3fcfe472b614751e97cdcdc005fbf2924a26f96a3d6a89cb4e6881f101a80e0aad9bbfb24f810781c4e1cd3fd4a0c7848b95cd55c1660a4a3355b324b4399199b69c953cc54bef6a9b4814e5c890d38dbf675aad258cd9c1922415d2effe5bfaf2f14f2d69bdd372da3c37a80f71c0232c695f945ffb6f1
+TAG: c1ac085d7a60e5989f0f30798f50ca365b599357
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585b34e4a9a9c764a48528590338e0ab297c9dd42f6e2286f828d6784dc240af4f421ed8d8164c50cfc07a5343301a3add36e901b46f2fec18bd82e1af2db7982cbe9bb5bf00483a70483316fff2f754b28a00948871e979319ba7e4637ee4ea7e571835141e5153eb0062a77ba5562b238e3ce27971dcc11fe6189a7d10dbd77e6cbb61344c7ed1076e6b3653d0fd42d3c47008f0b69e41e15bfece8c49e085a8c003113194887afd3e2e20689
+TAG: 95af682caaaac9ef1b7c3b0f57f7dd79d9d311c3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c445859d8a18f105a9e0d9f7d8e00f300de60945c2ee6eb66e43f9b7864130d3f47594ccf987c2449528369184cf27ab156897040eaddf82a8b6e9a8865fea98a30dbd5c71f311d0b9fa8987bef00c0b3f80025fa98efa91bf5ba1e7e0bf6deb23561fdec2ee9ae541f9e664d9901608f732315000bb51cfa33837c040fe8fc45b3380eecc239628bf94cdad7832c106520de324ff9cd716f0f243aeb384b07b5ad2725b4d8018d53eb56fd9e6a762
+TAG: a2ab4c0b3b3354a064a6ffbb167be1ce4187352d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938cec00f0c79744146dc9fa2e82cd7b8566c61d8fc8f8c62f7aca8239864d841fd3f51b138cd605e0b20d75700c30fe4e14ea961b008914a11abd2e2739bf3106cd87996854241f6a93f3a434337f4892e7f756fca2451a6452ba169ddf38966007fff4366bcd5036ec5c7e7ac4da4a1823d1b8b7571a24471497cab74b5dc0c9e4fb992cd802981069fd047225862d5c2a5a0e0813b7e76a08658308b9ff757b5562602570
+TAG: 8486b0db021a6cff1dd1feeca9e13fb1827d143e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c116bd95e6c6a0fad2a617dce8492c02185724358402ee95d1c4cdb6d10da123fc8aeb016b5cdebc3862b0cb552b6032bf4e2565ce1f7ddc0c33badfc2d06b10d28614815d58bd9bd42c9111d53f6343548ccecd26971253a9bbff0cb52f7c0c85eb874399ab94eaf9f7084e7f01ba6ab97692a599a8d0259118c1ca085b3d354142d73a6185608fb090de794f5aaeaf382cce6ae8713cccd60b98ed036d8fdf3cf9c392a
+TAG: 650e268324d3c308627cd4a7c4a38169f0916998
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938cb65f2d35b5d110dc24695334000cc502bb5dc917b5b234234d58bb7404d29bb8cf6c7d2b45f27a235ad5560f77b6bdb2affe811e2291185a791a77e58573d076c37339a37eb1c2768c7af0a57d4ebe69923b6e982094550cc0e801bbcac98826fe5a89242ad42051c6b0a2c2651931248ab53f25462ec38389fc6ac5c46c0733c951b35b516534bc0256d77a9ca2d213022cb4c92777c329a3edb2542bd24e10b70510df
+TAG: 938e492e8fedef77b29fd799abef5f2dc38dee37
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c7c99f1cc12d420c47039873a70c6e54c6f012203129b970f64b7d67ecf08a155c3e1e23dce09ba83dfc4bdf3f13b66d9bc14abff333e3b35c0c2d08abd9156d7dc859a62dcea66545c8eeac550316992801fd7852a74c70f8799fc70af1a1089ace6c01c23ae7fa4cc814aee476c99ac307c4adf621f7bd9e5bde8f37fc89720ad95906c55c316d1f284fbf07d0b234b3b25d12d10fa81396d8f30888186fb2176bbb0e1
+TAG: fad9280402facc83889a904494d5ea8a8286c3d4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c93098fbf3be05648ef396bd06d6232ff4150a56b4a93115d5e03dc997e17d5049101e40b19ebe5a819d38914d1e173c525afb32c36bfa3696ee1a6587cf4f3c19b655c2f2d64a60e78ad6064bc87de308f0d879687869643328f7f429ed639be9a27403c74bf17bafb4b0c70ca5d3b9d14a4a20472454c421e8536fc7f17d4fe0fbab0250e904eea29be9d112eedd21b5d5755482bcab42f3729ba34b91f38e081176b88
+TAG: 9b88765e2d27c9ec67a454db15b8c8f11e2108f0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c2873dd092c18756e597ae4a764af2d1ba40f203a24035672cd94cea893791e9ac36912cd02f37e1da1566efaf654ec6c991c9a0371ac5028716a68a8ea32b371a0c45a970cbe5f245f09137137da0b9a8281a5bbbbacdee2a0eacc6c330940a6c636bf1b02c1eb941de2f628b4ace968f3bce3841cba885e57c5da959337d225dbeb710cc4f5f85606cbf89ddc0e373d4181c0c466ff3bf4d0e9481f0e138e0d96ab49d0
+TAG: 47f8bd6c7edb70204b8d1e0ba89835310affd686
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c7aac050706246a992121aa81b1b94bb5cc6ebcb030639fc6f64b89aa5a41fa28927998d979bff42e2e852d46427eb3697d716ad5096633293018630bd5b5400f0ebc7d4baadd526762b9efa6cc5ab9b8df0e0357b6fef90a66ad5cd7758c24d54c8c9dcbd1c7095653246d05faf752883f9aa3841970a73771df37dc2c1a605bb0347950489aacf8a340b4a6772fd11ecc82207ed07cee297c182e4d4f91d47bf0b06db0
+TAG: 4b46106bdf6e6d98d5d357d0d5c774126094825e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c1478ef6593d7763bb969693473ca19b14a134dc018bf821c11146de5741f9fdcb26ff0c73fd8e45f48d4832e2b382d033e87cff39a49df406ef1d2788670e28b60c5c989572948a367e41fbe9c451032f63bc5573fb8117239e02b8f75b4253f2f2ffd95eaedbc1479e46462638742cb920e6a564b82dec1231aa0e5540e20763863f1dc6c7a4dabf3a3327d59dbb1d77d952265ee275d6b5151bde2d78ed3fe20636f11
+TAG: f29ee37d0d1373d2708218fefc1384c648981594
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b47a32facddcd5eb3ede0103990bf2376a0ce506da4c12bba71de072334f9ea50f68e7eed59af75be91e8e02232086168e63b730a41ac4dd1358f5426d5d4067a0d57c1c50378e29fb50ed3f5b879b1aa5e704ec24bae9fe2b77011e2751cb370b9240cf1001392f02653be8448a3dcf33bd24524b356c77faf9a939050f55850d8c0c22aba256fc81a4524e65b1f82f42e0889a283356396bfe7b9141d
+TAG: 0a4da13b5ea31025cd355f8401d1c0c5386a2fc9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b47cd2ec5ef5132787e70c07e4308b839dae6bed6e4471a8e861d4bc1027dfbfd14142029c1cc2676febb804de4ca1dd2fd0bbf18da6d2abf811310270e3c989fbaa8775076a1b9f15a868963002c880884e25a7e745731efa2c9849d64db27668da53b02925b17b8ab4f202ffbb1b8f422da496af64e7d5518e2f05a2f0821007ed71de02e737f5effdc6bedeb5ca7bce863c869fd34f8f67923251f09
+TAG: d4cb7d00f45cae4354e9df558d80b22c00ed4b65
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b47d0bd9aded5e2d2d108457630a82eb5637227fa03b9e1351c1c437cd9aaf7e4d9d51f553144cb81099fcbd8187e4d437f5af794bff788d4b6af6375b63114bf36855cc33536bfde7b7f5b4a38817aa47031b294e5191dbbf126ba935a4a93904e177ec9b0193852c48f9dc122be4ffb0b1872609ebfcf9384f9ca9c1be36e2a17587b7b54fe3a6312d343d4e328c177609f6894e85c94f9a801c07bc6
+TAG: 821a86fd3d7eae805c113061527f3afc1d7ea019
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b4750977b9de6b9d16baddf1e161494802084393154114b3b8a32564a74b5aff9454ad4057c9af63eb4c3ccaeb87a9f7d986271f72f0c997040b6d294d193686aeface1ebefe26e3de4dfc85d7848bf59e58c1831fc1aa65b0fec7a2a6884a29fdb72089d3f366264f5e76d85b147d265ac2ebf4ba7751b270130ff077202008076b2af95f666cff3b1b482210a7b20d0f7a600ed32546060b614ec9ff1
+TAG: cc7cafbebdf199062055dd663d8cd7f61854aec6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b477538244c849eab7c2eceddf6ad019d01ffebfd70d23959317f608846e9508e052f12803d45f68e6dd781d190452f6e848d446f1052925ac80fa286f17811c1b9ae43a37c884a37ce6994ad0ae6485a2417fb3306184d2e525153e28851a14065a9376b7523c9560af9461058bb05ce41c6117d7bb0b6683913a9dd32f282ca7bedcf4e5eceedec1b78519a8e5135c7bb48e2a26021af8812d75cf82c
+TAG: 992b7451516ac213736b511e38b21776a7f11df0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b478466c0fa8050b432a693249eb60f8ec76129c6a3c58ede2aac7ebbc481d2414a6824acc4bc72e4bc243bf349e3730a22eafef0db89efa61115e7877ea8144dda902f339181f79ddea116ef959707838e2def59ffdccf0f8343b35df2ffe5972be18ecb1853e999b8b66d56d36763511ad12775249811a88ea31748b06ee38e58f1f2d43fcc4a0e89ee3b76b70b33b0277d6ba168dfe1d17dac8f0716
+TAG: a4531764731e3ca38f60f7bb890d43ab2db222ca
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b47bd50e9ed12008dae9612f49baa7d69e51a5045cd86d1fab39771b3e70815ec1b8ff983ef23e44215de3f5051a25460c095cb317f76e3e99ba4a0c6c8dac4b3b4f85a21460f78eb1f2fc2c75f54ea75d9e34fb4c0d477a294c85276abc46d1901993f0ea73480a1fc7dfd4ab46749591bcffcd6ff7acc728f0561ccfbc0166828db8a902f883f73a58520656baa628a3d899e868056c62a41e7c1c635
+TAG: a2ea6dff0de76b56289f04697fdd9fc2b185c422
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479a7548bb3fe247902edb9fb7133ade4c81ae41dfbe2ffc7f926f1b1c58c80114c015fbc933043df5f44ad8d188394370f22cc5a768aaabe6ae6ce6c5b7cc936db681bf2064658bc94827907ef9fcf4098ab4e7a7a0ba8be6fc057a944ea0aa979a0fc81c7476d117f5a46f0776e78780ef1bde734a31fa075f12677bfccd59c72fd8af8003ed7317922dfc7ce9d4420911237ee81f9c72cee9e16d7b
+TAG: d1e01f0e46b82ba8eb1c0664f236e7006cbbc2ea
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec74032012cab68cdd2eec2e7d0e308772b3bc089be8fbe713ccd086ccef3c6fcefca092a9a7dc0edaf55f99c055dc178d26bb82d26c99359f125215a7262a5703aed5dcd7a295ba0a7529941238f392a244551c9605841f23a1bb0a2c74aadff627c8dab516256e8568ff9d27b742f72b680c2980e89a3a7ba41591b37c016338b9f5acf58f6f872272ac8f867de5b1ae965e241a1
+TAG: f3f610ca427724564a215f8fb26bdda1fae0ef55
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec75f0fd6e69b4e65c7cac14e76bd9a1cdbd4a84cb04284ec565f36e465bc86025fa153de8c3d0367d623b1008307c2c359826f2824bd68777b4151829d29447cfd43cfaabf1037a82800d91dfb21410578fdd8a56e63926dfb60d646fd1d0fb3cf058442d193051f9d38b9a04b48c3deb390133e480cdde22cfbcb83ff6cb4f896fd273298a51c5c3372c27bb4ed2602c5d7ad521d
+TAG: c797726521e6dd84b49cb951864d9fa7f6bde1be
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec7be79a65af53eeba897f06643c3268841fed4624688e03a99d9413a43934f2ac10acccf7720dd8c7ace7ca5a8cdc77e6ce83a9235a136ad15543f036724c3d11ad9455ae6d0478815152be54282366240632846591f9490ae2e44ba4f3dc2cfeda6c1d10305927aa0e8122dd32b896842991f5c744687124e4a4a8f7427365769d7ff135b3d6f4c75ba54e421a3e8945b5967f1a1
+TAG: e531f26f3b192af0cfd23d0543403a9ac2871812
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec7c6212bc5c23d47170716a3b8fbb931bd7784b499f337afcfb3d5f8005cc1b26df6b6146545b60306734e825aaf29511cf843b58b8e9ef9926920c7d7908ae15dc864a1a6e08f6afda5a70a4a278574d521063a8d567558768fbb56c2b1ce2d00b6a3d98bd25412cf1b81791ff8ee0df4da8f59baf39b430131cf8de6decda76d9ec7bd9639d0670d1bc444829a042554e4bfa51e
+TAG: 56aa021a408928c4850cd37023feae3543d907aa
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec7f683557c207199bd75dab3e016ce73268f2e8b6405d6dc5f36c5fe407ed758ff20e3f87669ae6fcca6346fbd8aeea60f473f2930da4694c13edb8920512d0604398c0f53bea8a91da664a4f55ab2b28cd371d28872cb17987b58462e4584fc3022d66c12a8ffe2dbd0d2899f7027f4e84c419bf9eb661e129da4be93c841eae97fd8dff4145381c77bf2ecd88a462c6131642b45
+TAG: c2a4cd004b3d60e83c0ae15ae6605f382e3c2998
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec70093fa6ccb694f6337047beebdc26fd8ec49cb75022f03210e2d8d6eb2dcb66c3dd7ac2ea41d56aacf8e5a283b98bf7311861cf70c2e8113ea4e0010de1d12392bf889d9444e99054de6b21687472fb8dbb5fd7a384620ca7e0f24bb32e6398afda267ae70c4dcb1358f9379232aa635bd6a83e0e7689a22d3174f7fb634fcbbbc88cf8c6d242da905603634d9b251c969ad55b3
+TAG: 019f16fca4b435c0b9a623f90e6f4fd90a37c561
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec7fd9d84e73d11480cc29ccc4446dfa81276276f9f4cc35fcc8137d65590feab0fc5a990ec69969b6ed7ecaf3af2c4ac2f9e500da16aad00eae79e4dbecb174b8ec2906119c5069f5308d57c9b20a0e892c088880e25ba5059eb37957735b68e8485f1bc6c1b4dac3363648287ccab50fe33b70c2c9fdc55550106811738c93a761e4af9e983c63ef449a0562effad7ee28179a8f4
+TAG: 367acd479089f059c7ea29a20d208d5d39e3745d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec79fafaf6db9952f7ebd3e59d441f2a5a55acf4d90140f7f1fc2ebff3b7b4238033c5a35f1dddc16b611c2edafe9929df6161881e7790ea222aa487a60ddee389b946c3df65ce00f5305357048340743a2854fa4b78cf60c06d69de2e202ae3bdcaae3239b1b3922c889220ed70ee5fd9048a8d1540039575fec6fdaf69638e43b174ac393e322c20db062fd9cc7b55c88fc60c7fa
+TAG: 491d3adde3c372c9d3803396f397ae4ba06c80af
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180aecb83ea26a99ac11e393539261ebd0e38358023a16a8ada5fe1a488f81e884ba91ab59c0e0bcaf75dad35d6ea525b1155ca3235eaaefccf0028edd7d3361fdc57302886bfedc2455d7d737a3339640e1ea7cc0be93fbb17c28f945c7c5ba7d39df5b9087f3dfd82b206d2b8f9df9a3f8440b6a92cef205e8c9f546f6f978a95135c0aa886842e624d57d909d
+TAG: 43ec8b8fabe88e52607e3936132b7d86f72cb0b3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180a3b80cbaf5871bc0d189c5f84bb030c54b91361f1581418c65af37cbbd219726105928f52dbc490a23be453f3780b43104d32115cff1d9cb164eb61c7ce332eff4bf8da00a76b3a524d293039a7bd45492384baf3ff3bcec3291e93809c2a2059818b8041427fb6f738dcd1fdbc33dca23288dbc8662562b778f5007c6b0737370f78ff5dc83df59b3376fc9b
+TAG: dc71def387fdabdcd2e0dd67f37984ed8f5bd876
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180ae503d46bb0b05900806e4b7f37d94c2ce810de45ddd1d2318410342878e78a5a1f1f1020e70feec865ac901556291685982d5dce6ae1326c92126c6cab7907ed3cfc70ebb25796b4235448da5ed710021c35a22238706199b64ad40cb0b89a8c57cb57b506127a2dc2868235f91eedabc414b5f373901d7f78b7c2fe3b2911ca3346c864413b749ee23b5c9b
+TAG: d4e93178f1ad30bb91082429ea0712dc05568eba
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180a34d32cb6921c26ba9bc493216440f9f9a1c2d2c442a7be38a487933c52a7cb129917c9934a9ebc88892b6cbcdda13049823ce20c7167ea8795715928e8ffb1ad1ade8e0a91e39ad1eeac17604d65f873c1b630a3e3fdf28fda3f5328946aa73ee6615d6da0bc89eaef2d8d9235b2cf625d5257b5bd94b419418dfa702733fa3c229a727cd8f65473a30f5e63
+TAG: cdaa9bf52120f3d68422103a02c78d5674a87458
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180a34ce91c45c2297bbe6477d5cdf88c358017f59b966ac171527ddb394d975becef3128753b60c20d61e3711b26ac609b0f2e82379a4cef0470cf4035f367a729340d5d10106ad2ca7fb85988d28a0b073e9f1a1809a9ebec443b6872da8d664a11a5a760a89f9f178ba72f4484cfc9e632fbdce02b71126c5c1bd0e5f4b5dc0f27fb40d88ec256c29c8e4a88f
+TAG: b602262e02aa4be38ebb0472f1208cc9c2080cbd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180aa1af6a951b35d58732408bb4951921d599e5b847360d60e0e9bbbc5a1e35b9346c3e6248ec95bafdbdb114844cee049fcdee7b6a50bd4bf8c0d5d532fc88b98cf95eb26f739c40a8bde7c5e85eee7bfd355b0c61dce1edd5743ad2812c535e1fa870038026334727b5052b32bc8d5997494e3fc5da236babbe513980fe49318239cd79d3e2cf01d196a9a096
+TAG: 576544f705d75cf6fabc6d9707b5f52bcbe3a10e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180aa3b8107aadaf66f0b166ad34a15013b4047eb9ba7327ce2a7c66569add0955fdbf307c921347db107f0572e46c2e6f8ffe0ee8ad9cb02933d4cca7ab712aea08a0e8e094513062518e0b8bdd422f25c04656ee346ade3fe8c787272d71fcd85659d2f4e6adf2daa33fa202c5b20c3713d62e885ab349b6c501d004a1a31126ef1da5467dac94ed5ae6fe86aa
+TAG: 46ab364952f9a063131429dcf8161fb41a1e4780
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180a4f94a5948aac792f9caaef9d1f53e31294633e92c2bc54cd03ec0ae2406912254f1a7e9b1c936258be1c7e9a93f3bd6b88a5031c0906d608dbadb811c851d2e86b339c1f8aa0de57d986cf18a56137e464f27f898bb9ccb8a29b6ab8cb31a01e9550e1aa5d4636a3a92f2d2b4333be58e388814b79475c7ddb072192bae83f5157037c419b1177d6f62061e1
+TAG: e94ed4df10a8a2360428b67b56712a787f640466
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919017fd6ba2f539c0797f655ab74f994d9296050c004463095ea98387cf3685e19cef1bc05c30a6ab853b520b48dccfa88200197f0a27a3df91820c41cb1bfa623746ac350878d4c4089455dd596b1df7d5f4a837ec4ee625769fe1f89f9484938ff2b1e0183c18b0d02f1ef0bdc2dc992bad2dd6028b02aa93cf7c28f13629d1209e6e13691
+TAG: ba7e0853b2e6f9da5858998273fa4e3b5f2ab88c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c9190116259824214e5d7bfb8a3e03694a6a3dcea7355a9d19950dbc5b34d800285d03eacab504ccca6eeb3c1fcd71006c85afa69fa5db2f66da61cac6e749257008f42c8e24467da2a54bac69ff527f2b8c7d4d0bebc29c1e41289be330dc8166060c11cb94fa1511e6781efdb5efbc4889715a22a2b16890912411f88cfe6e3e1c4f8f974718
+TAG: a6dbac216c2996d1dc277a718f5fba34bd43454d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c91901434812cd93ac931e6428577403b174ad651c3c84b12fd3900026b1e79bcb15ca6aeaaa463c097d8e29823c4f91181c5f6a73452c88d08fe08533bc54e4b5daeb1e90e3f96afd7de70817296e3eac3fff056a2c622fd2a3dcb01d0c98c2bdd6471a12df0d45cf5f4edd88860e5a185b6509e85fa38ebbf28e0d0066123199bc50bb86511f
+TAG: aecf4e3e8e432c67852185831c9aa3acde797fb8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919019c6503f8ebf6a8befb074e7822ab9ca1ff13ba5eeec013cbbac22a3193ee3578d3647d6c1bce232a570d0bce0e9be4a2f1156d6ed35d657a596369e854feca0b2aa4eaff77f084771ab540bad073ed991790ee25ca6af630dc340108d0c503ed6175014253f12e223bd10b5fb923b0ea826cf6bbd5e24a23b7afa786e511e958d5fe3d74
+TAG: 577350808b22b0446fc3c4e9e2d4bf303addec02
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c91901542b83b074aa37a5ea88a36cc00a1b89f47225f19a7d9d23a4e993989c7f033a092fd1f519e3974a2bc6e3630f72e6262965de04d46498b715ec11b9b6e56c2fe03523c7cabe7397b4fe3cb1ca2198452a5276a3950c6719a6e67eed8a813a4e8bd93e70feafed6e63f61c8e2607aa8e8d791af7e7cda71cec6739b77c8e47f7f7fc3fa2
+TAG: 624ac2595384a115a8a1dbcdd0a97d1f2c4d9ef1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919018041ce28a84c721c8e834809fe95fc5b0cef6ddfd5d2f056b057cb96d322d1548c947a39a57994daeda2d2a3eae05bbf321c32970f369a8c69209778d71b6917d4cafcc3dff54dc640c834fa0641f193fad12c85fbacf6a34301e580893359624bc57555549911dcaa124b3ab57fc93e430e7e01ecca69184d5c4fda2bc8dd34db52e877
+TAG: c0a73e9253947c80b5d60aef728f046164939583
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c91901d1578c7d7dd120dd3b3be77d71e25a377a02dd95ab822ef307b020ea9585b2646e1a46d82c8d12672802246da16e16293e014d958692b310860d7998f4c6a1a48b8c10372e26dece36142c062ece0fddd7b0199c7bc72752f00d5dcaa8fe2300988639534a52ff6df26645a4133640fcbea4f979a67a83d1685ac2a8a3be8d27184fed08
+TAG: de44d0bb6fc5f1677051be4ee1607aed0addd426
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c91901d06104bdcbb391e3e84a19b0e5e5b0c547190e19e0ac5d092eabf3b3275530a89203b44e368f1f408eb14c1474cc3f09748196db4fd119b3f7fdb3f3486141739e0ca750071c10b4abd41c03e63a0a97639791c89aa0cae2f1ac4222ad5468e738ed364a75482973dd09046fd81dde9cc16869a763631963fb9fc6faf37228ceb4d944df
+TAG: fad7c315627e1b5c7bcd9146503fe1700733a986
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c40b963198cfff05dede3eab2d712abd9c228fe506902841df11ccf16d45036bf9848ef601d674f74775747a2d18850d88061edb208ae7a8d5478d8eb1d11950b1b83ec83cbd6598914d96aa8a7cdabdabddd281008cabcbcdd2281de53498877cfbca6d52ea3093c2b81348a9972654160855785c3f70129de83edf6
+TAG: 96fdf9cc14af813a1e4f93a1c3a3cb10428885a8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c450ac007372f3f9f867cbb17553dc05011126808e8aa48bc93661ea3deee29c532e502443668f20195a92e8df6462e2d04673f5e5228716e1fd407baa1b385c0c5bfcf41ccaf447d1621ff3cf2f3ea152579fac5293f53495f1960158e757788727b0d84b5bc8bcb8828f3656d553e590743b48a5ccf3a4b334c0e2f
+TAG: 8010c010417fd4d5d1445d532f534770eb2eaeab
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c4b7501b911ccf09c2c78a6209f6da6d98f2b7d76a47b91a0f11a248a02e6b65a3de0ec4c49d6ad3b3d4c75a5ac129222581de58760a74721533f2fc0f1bf176c149e7f715b626212cd70fe1e247c1b7d81175017a1398ac154f37cc35070468b22ddb8b36da8687c20f129218500d0ddd07b7398c4027d2f21d7efaa
+TAG: 526dffe70d4a7d1d122870bcf410a6258461046a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c46b9ecae3c502c643ff6b3b1c9a6780b3b9ff0b48815b0d33bbaf55219121028eb6c186a986088e0abd5f58a0691a75b7e1aeb554bab6c267b03383b9bc7fd48b84dfaede9dd85045bbbfbacc0922ff8ebe96895b49dbda424daf3e7d8425c5c34a806a49d772729ec5aba5c7740c401e72f2465e8104efdd9e655eb
+TAG: cbd2c7c18d83980c291abbc83008860971293adc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c01ac07f1c5de56a277774431960f60addae109efb4f83ca65e78b45efc815ee247af1ca7704e2118011bd7f65fd1351eb5bbcfee2bb2cace1c13edd6b11f48e8c7604912c54a81163b274b63eb837b0cb8ebb9ba663423910b357f876472dd54a57815be1359570e7cca915b00c5309a4adab12856a16e39ac6f27c1
+TAG: 2d0b56015faf101fd63ff321aa2531bed31de649
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c2fa89a9e4f3fdd8f3912c4b1c24bb99f23e07cc0fe9d52fdefbe12c23fb7e464af2308838a6a77cb745254ddddd1253ea15dc059099eace5b3ae7884e3a2e7a9179f568794d689a801a357cad5f1d7a2a91426e9496b93f18505f360541daeaa64b86ac4f34e11609fc9d782eb3caa2037f69a9e8643588999af6167
+TAG: 5c4d368a02d49e79db7aeaa3f783c98bde9bb3d4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05cde9c2bdf9c1669a0683b6b5aa68887b92765f253fa1774d965686edc9f4ec857a8a45db3ba7acac33655c281cc3cd5c24bc291839422a138704738d176f93f0c609bb3fc00246e2b92bc818a6340e6af4a2201d494a31874e906f1c9b3199ea05ebf64a1c995d077514d4065ca8dbba5443f6ed4c34254ca9ea0a42a
+TAG: 57b671a4f35ff9134d17d8575125fdc924a9becb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c086fd5b7d0bed1f170cde1628ba41b288209582f5d91457cbca58e23064e6028765e5506ddb5b26e5c3079f78fa642add10cc139e4b24963f20471073184f4458ae670e830220269fe8738745dda009cf79aa8e96fda39cc2f117b4e5536965d7e874f91ae5e89bcbf25b407fedf779c8ede47addf36352f5fdc0cf2
+TAG: 92c4e10800af961e944879aab7329c687b236e92
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb091e494da17f46b9a929c3a97c48ac4f156980aaf2530121d86efb61fb724a4429af24ec432e6158ace07fe61f55db793dc75332298bce91d22d5fca1c5c9a999374369d03ec4ae2deaf9f5e94eef2a99ae398a90f321485cbb9ff261d127c8dffbd321c5c6e01f3b0da6d29e33daecfd1a9bd9b94
+TAG: f02c5d7ca08ead8c2fc472d6df0ab3dc01055e6b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb0905e1d788fa672328848986a1e7770e27d6f7740c7fb91947b77b433d51d535d781dd0645aee2059f64ab4051e295a5673e5b73f4f412060b57e028088410f4797dfcc4dee4e24c2bd8a9a1a7669e3ef70715bdb661cf62a6c9493256bff1fa52fcb5cf4f8e337fe1e3b226a680bb9174968f72ca
+TAG: 8a5cdcc218d088fdaf27519f2c204fabb3813ad0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb094952d0d7aa11919dfbcb989a6e2a06c95d0bef90f70a99330aaec5b6aa4a572b4f45ddd0d3d64e966ae8c7431182bd3971b06439fb868cae31f9e768fa583b5413af1349d5342f1f987eb94f6bb48905d7350c93c6cc3659dd796dc8ceb2bdd05b3a171274a360051d87072f2983f39ecd949937
+TAG: 98745a29ee0f15bb9970c26d93101c9e44d7d0ab
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09cbec665e4393394486554915630d7a4e18d9117a2fae3398fe6dba552fb1e57e8228b5ed2c1606a9bacf1cbe65c70612ff5edd10b518a3b0bf5c0cb3c04b881af191b89998407214038203ef6d43cb5e03d7cd06fea8fc2ca219a16c60fb00f58af401c3e086315bce819994f085d7f9035175c9
+TAG: 19d8915331d86bc95dbad0df9399bc4c75996270
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09fad7cb3b8d2f471dbbabe2d8dcf36bc4c1970bd53f06a8fa3c15d908ecf28edc0e2bee081e9380262587f230baa1dd3ed1d5dfd36fbf776704f0c46231a1deaced2063561eae271f6b2ab25ae183d46a137d7a906dfcd808bad79869630ffcb100337db9a234bd47521c2a09f8627909d76355a3
+TAG: e40cc80e74a52c0c3ec7dc07ee1c326b31893b8b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09f71cd67140e636f18d7defa14f3bf5d593621bf6371f9f85dfde9d10bd283147e17cef183ebeb8fcca1e6ab3444a6e859759e984a8eaa1ca6c126335be6b3de6b1956760af19a09077e1ee0567b4e13d122575b3e3106729ca86b3a0c0e8c0d70d77b1ce6f75db3039046c1be02d271fd374d7fd
+TAG: eb04c7b2800086eeb31d7d1f2938a18479128d83
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09337ace4327c89faa59a0da9d3c0496d7a84f827edf2f53bcf15ef3e48c58027465a6b47770c4168eb44036b0f889a97d794d22e652c2013cb4f1c83a7df3a684acc8030c3539b96d82557412f4841ba8818b85a86a0b844d5302b0279a1e476eb65114cb6bc01208e7066a40188838a5a3b6576f
+TAG: a99ba70c03f4ab1722842c78e8060055760784d3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb090217ac4dbc1f4fe1edc603dba2a2a31bfe857ce0de2f56f88916337552f4f1f09b6df257bf855019d295c57d940f723df9b9f6cde4fe08fe0027c4734c7d5ed35a25026d9e4648382388de1477a893b5018172359abd836e6e09205aefd850a96ed7cf663a8625b47259e0a9c6f6c3b78d9aba10
+TAG: 393e329a728bd814e5568ab5a06ba90f04bd07d2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7c613dd38e9bb00d50876dd795f735e9be14613d681ea410725096cf777eaa57454508a0c29493d5456bcca7c011329249fb18d8574cdd5deb8bf528b7823731e8803145566200e93ec3730ddeb4e03cafbe989f18a65e514d34cad2646e0f08facd474b125807bececa2c7fb
+TAG: f00f13be9de4bd645cfb42bebd8d04ea3523c8a8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba716dcb0bcba1f7e62007248a0c61e236b01ff7551159e161f3228f5af331d291e8be1bb84d3e22ceff93cf257eeb59c0f0ac72a3d887cd42560d5a3cdf9cc56270963227ff0720db6450945bcff0eb0123ef4a4607516b66b38b30fdb2136814e56bdc034e472986f06bbb745
+TAG: 2fe7c697c48a841a976ddf8f28385574559e455b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba71c92c853700f414b2407cea1277f3dde8c4426020d1abde7c2f2678893aea16f4e85d66c7dcb5938cb65772cb7d7847c6c505ac229aaa04cde881cbcbb5aabab81ebc7227a0f934abbb4535e55144307b4485debc51702607e39be67f00fae1d55487705202419b12a1266eb
+TAG: 691dc7f35f7f5be24f6a371bd9f1010824d69cec
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba799b2348e998912a944b5bcd439f2ef67ef9368260a315a9c1a3a1bb41ce18a267fbc11a082cfa50768711a466f530a311a55f5612b9ef72c7e4fefc8f33596b9f0be5af82212a0a89810d7d06d83dbd13ca749be077ca4cf7440e6a4503d74012d926fa253323c9bb76797e8
+TAG: cd06f3559912700c848f2545ae4f85781c7cf4db
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7cd7cca124d1634defbeee882af29db098e4f3dcc84379b3654edc32289e1f2900ec54f0cc791392c9cf7e616ef7eb131a70aedb289165d8d0885955108004756fd25b4a43d568d6f074cab5e7d11b8afd67d0b92406c78c2d79fe2d8cc8d5ecaaa4367b1cbadecdd1227149d
+TAG: 7d67d2285708e34c8b798ddd3766b8830a3949fd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7082c6810cea5e7d0011011199160a648b8fc31c32da22eafcbb64f393a3d3d1e83b61f9436044572e09ba71d025e0e12bfb30b94a99e292ecc0a3e2157990bed2df91fc4d58a3b754b2a52e117735411d75d9ba83aff6a13a17fbab045cdff5dfd8c8602ecffd3fc59cec37d
+TAG: 4b25d74862eb3fe8a14b2570e8c0a87b2bf6fee6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba73bbbdb554b76a06ab01f3aa3812f01d89054acfd9d0bc249db78ac4fe8123f25348a678faaf626bb809354f0124ada14524df867010477f736e57233a795fc451e7fbceb0698ec56142c1c27a988cc785b29ce6db1c1de42c6ebb54361d55fc9e1343e891c3827b8a6ba1c20
+TAG: 1931759f02e16bf60a535cb2b505ebb955d2337c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7193b4589d7ac90435541e38a45fca7050b2d26700c4fa1cfdae074206de69b07c8f458e2fe93bdb3e277733eecc02c0d21c49c5be85e243a612cb55bee28db278a75e7e09b44f26130e3e01155c083aaaef279049800a9c36e9ab173dc69c4a6cd009d2b954cf76f937fc413
+TAG: 2fb8e30ff69bb07b831c967aaa19c6b237fc112b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d10757bef73a44c50743e368f71cbe97e91dda2ba020d6e51e9716bced7620b90de4fab77e64cf205eeaea46ceee168bd40b93c9f316b0be7c8aa693e98230d213cec2aada721c5079022980cfd28beebc35633d6e5778340ce8aacc5dbf4e77fd02c96f8c1688
+TAG: 21314968262352e1da60c356b63eb2f01a37632a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d10757f08e61fe8c56ba7d30b8fc6a7b15865cdc13c8c1f4831e8fd44cd74db4b4a04148904a8802704de56028b98a538cae48d03caabd3f8c9adae64279ad111c1a95620fe91789ce721aafa826c95d51be0d1b558037ee501f6f64d8f85b92bf936e260189f1
+TAG: 209d76f7920b9285d3c5a9bd67b400bc4c17c746
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d1075773138c9881e70e29f8e502e94ac9afe96e6fb5f8458e6f95bea7279ceea5c1fb548d04e81fb35b1405a04eb1fc84747d4dd85379c0f2691f1324ba2c6af90bd3a463a61128609674129fc4654beb9bcace940952d28597ecfc4c45d74596308c28b35077
+TAG: 2a2cdb1f79b0d7720ded3cb4506f86296b25267a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107570d2a513b25eb50300b4e15004e2f971df8f72aadf33a3b4fb695074ef585e6be8022d412467fcf066c404c0cbe3a9f5d552489721a8e3795e07fd66311d6e577e502defaca8481f65a25d5a4a2a318b93e03953fb35c93544af49f01586f4eeda20ca6aa
+TAG: 53814995f38cfed082023ef3454ca7d4a86f2039
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d10757a03e129aa98bdd6b16dd99c2ea673c56816d0e6a9b7ceb168c11a63ca53af7e0a36a08854098e6ef5ad72ba1f3550824e3787ca61c45b21d145a2f7aa9c72e11cfb0029b601e332e5aa656b901c953aff4e80c414ead808479d58733333680dd25506cc9
+TAG: 19004a1ae8b63e53003321434a271c35707fa9d6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d10757b486a4096a852f6960de114b95ac4db2dbd23ee5337374c9899c20c42abcbec838f76fe0338a310bf8384e5ceaa25b832a5ee018e443efb764ae41822bb5119859e735fc106ccc50eaa00958b4f0e3b6eb42ff4572f51c54b0d644fb1469ce1b48e14cba
+TAG: 50a5ce6b93a4b53c589f0cf2da03824cfb20c32b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107576c714493e6ba8c6a62f254b61191fdc2a82a8490e7f398590da7ccc6ddca87ddbb43291e28c0371d46b2960beca73b58a7523a6230fa19152ac0f241ba7b7a75918aae47ae87285302722c7e03e9c1263a9f1914196d83583ddedcf13d98c62de08aee7d
+TAG: a99951c3efc5be40196e9ddd22a3bed1ed1b877b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571af0a8b013e58c3de56a55a7d78b87c84650d2a6bf044bac9b90b25fdb4537c8e59f294b5a0dbced8258488c6c42532ed6d379d7dbb44740965e339b0f529e082bbed9b67e0d4b8b84818f80e0fc6ef10738ed2f6adbd26a92bf7454231a84f4047bc681
+TAG: 6a9fe912d8d27e98dba19dd16cbc62c1cdd46228
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009184639b1b381311bf9b1d0a08f68f41dece83232ea3bd1c6342b66fd8730f4ef1fd57161a82db74adaddb616d40f2a0daa59717aa2a74a8c017205750dc8a36c75d0d26fd7c846174abeac8c347dfaa73d54d52abe64ef0d928f72cca6
+TAG: 87ed543b2435940c0d400522e7acb2d8015d62a3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009183f0797304eadc54cfd3289ee9f9337dd1960e51c2970e10643da5b78c374779bf3a2efae15a7af97acec031b2f6951f91a3c4a64bc8560679a8968553372da498fd314b6cc7ba271a5d5c8b252d11fe9ba0156a37b7d93e8969651e1
+TAG: 1fa075da585a1c234027e514170caf1e4daafae5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb300918d4f261c1a3b27752678d844ab3347ec583677b7b56b811b74a34522964456b9663f78b3cde325ba6f6fcfa18b1c6019a93842e2969eba6ee20d9eed73d34001c06aed013e0d2ffea484c2154dd4b7a25332168143124c9b91e04bc24
+TAG: 620a1d103c3e418bfc83bf33e2828795a376d2f7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009184f41a010e281f758717545cca65f1d427de5c4a70097b6eccd59ea09a8063b1c2b354b8a61c18027c7d4ac3f19c37a554dc4823b5df2391e38712d1581f45ca6710f9268c6076a13d209664f3d6e195c613c365a8d4e3f4e02ed8c09
+TAG: ba38ba6938054ad20a3734191e1386b58ef09a6a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb300918366cd4fdb2813a474ca05a3a5f97eb38083fae761e023844640168736020be7a914a746e9c7512b45db4b9a16d65c9245ca30bb15baadfcc11c757ec4fabf30aea02dbbbd163f9158c39db02299404cf96726f8e7bab943508a2bbcb
+TAG: 37dcc207e86934638fbcdb9fd025d21d1aecb9bd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb30091819f62baed0cbaa863ad95fb4b6c98bef1e2b158add1de6f454a54544df1bc19c26896e7e5c7d1e2090cb8f0f9bc70f287cc09a2a3f2717d31d59d1e5a2a093d5cbef2bc402b5803525127de33b3ed4671627ea8a1e2852b0dd798bed
+TAG: a32a01cfe306aaad1a9a18d584c36dce041876f9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb300918629fd0c6f134f9648b4dfe01f037721fe1727d3027ddd8e93e5b68417eb8a14bdd5547c0c9c3151e27c2ed64c1340cd2374a1a26f67d356d6864ce493cfb7b42eccbc8f75620e13b896a2297a830b020fc3e5fd5b6f7547a6b07dc0f
+TAG: 54b7953c93516b73ada8d228a7af00fef50f26cc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009184a0589c81a17601ebc3d6468327739ce9d49d93d1f11eec96afe06453c60de507e0003da14f5d88bf8dfb7437aa0fcb6eb520ab9a1d0e2060f58a986a7a9c7e5f4db58c49a0b59db85fed76f3478b8662ab7810c5e6301eb07651c23
+TAG: 148f87d7ee56a5405cfe4dcc087701760c07149a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c611c9cd0620811aa4850906b9eb3393ec77a1c08cdfa18d286f7291a3ad8a74294ddf6d0b0b76189dd217644d632525d6fcdb5836143a14516e93dbe399c5d00b36221f543cd66304f94404ec51871d1c0b5bf4dc13
+TAG: 53f2390e488968f141945ca43c767e75905a13a0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c611a9febec72a6403f99fa660c741901525891bc7d12fb7e46b28d15e912f31b2c4f79c6b0b92c009eab2d50a6b5dfc48b723268b658642160a6aab79d6ff2242a6566eeecf853be0a64f1f3c25f366db6ff145d114
+TAG: 3ded125f5dc543a21bca99c370496701829f2214
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c611d6066228493f5ba630c23c01a64bbfee319bc8040cf6bd6c6c2d5c9c132fb905c85c87942b7326589d3560cae31e65ba7abab709a5f81cc7a613021cac7b830456f6655ae567f89118c99f7715a11fbe839b62f9
+TAG: c53743db3bc1e1d8facd09fc210153bc930cd5dd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6116326b1448f1731c476bbe2cac711412aa7179b1b1398c9350211c93ff3302842bf0b4855193451ab46728820f33ea412504c8f9c705d36521020227bc20b4cfe5b8b873f38c835405df6b49a6484e121892c82e6
+TAG: 0a89ab9279418ac764f4f5f1fa5be15c0ba43e27
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6119bc7dfd17657d2fdfc9eb5587a54b93d600118bb10d7e6ce7986eff89aa57df40907d36bef9a1798b4b44916dace26bee7b77d3da29fbcf65eda34c7a97c01879a6e6d9bbf93405c65590675a2ccb82c72d0c33d
+TAG: ad17ca3b338a29d2cd64ac3c41e60983430c2b13
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c61133476ae183d62dcfc356c35b8c037b57e33df0c5bdb86eb8992f6999be8e6aade716b75eee4cfd9d27fc67d6ba8383ca365233ec19b2a9850d0b201890eb6b70368dea0287b5d8348475a368a26895437bedbad9
+TAG: b1df25a8a015baf59e3e50d53ad528bf54ce5028
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c611450b9088ef27ea66511fa62518b8518cce0a0d05810059397d7377a918a08512d18e20679f542b4c37c4b65697526b33536095b9ddbe0ddec85094036b933ccd8d89fa8c2497534cabe31cfd452901329d778a7a
+TAG: fb9e5acf794bb8725e42af0ca4849ef2e1cfaec6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6113f6244ac0b131f197cfaed4523d3ec6dd4b7d78de7e7724a99d5659bc3045889f38fbb375111266322e1e288a3365633ef25f97e08bb534c5f472ec8208825551c9cc7870da2de8ff5f7a37cc2721959aa1b38a5
+TAG: 97397bbfa565db9eae18ad34ef8031853beb700f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da960595a1e5683179710af1f8efb7246a52b7397bcaa620f41674ed12845502dedafac4a946e003326c4e9769c290dea53a2fb74347d68c8aab643b92595a73f241f6a243359a7cba5a97246be45949
+TAG: e1b6771c4b1278559053516d88f8dcea5ade3658
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605959954047454ca1363a07e18a1c3cc56c38c8e8eef0b90f1d59c9e7c56da1e3c24dcc3c4ac1904ac3764e3c96065834c06d540fdbbd380b2cbfc1ac5cb836471b0af2d7b962b6978dac9f695bf
+TAG: 34c918d594309af05ef33f8239db90d290eec73d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da96059569b07682b8ac4a401c0029db537ada8120840964e34fcff177484265545f9db03a48479e3fb273001a27446aa490139b1b29d9b47a75727691931565a1ee2c2ab62025b31ac8ce1685d4e09a
+TAG: 8ab01c6ee68a7e7235fed3af3b8cd05c44b7a1e9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605950aa0c15f6c227263758328ec101ddc0365712f23e76669f2b2a571aff52c191358956eca0b5eaefe43b630af88ea6447bddaf69845e58c8cd0f58f440fddd1669742f8550cd9d2c775397f3f
+TAG: e419c2c2d2081f175f8a8adfedec63e349d1e2f0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da960595a3ae7d1e1f19c69401de1594ff90f7320cabd3ab18435980998abb724cf0b161f520acc86c1321720369329119c358b627d7518728de3da1ac5cb8ef20d721d4fabc92effe0cf2e3f31e2487
+TAG: 67f9939a7244da23332c6da1060e1b44db285db3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da960595b7765397599d414f505ae443a80e7e070ade45866134344d7751021efb213efe3d3326ca40232b9b26cad910260126bed25ead0b92cd3ad0db65916a4f8c7bd499c3bd4786b1ae461e462f7f
+TAG: d65f7c614dcfed968e76d791b4dd7b6797df4569
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da960595028b71e2f4feb1515f13b6a8beb6f12a1d2d41cb93b80c8041eb466ad00d5d1c406be5147489b15eefc417e71e8d5fc541e038bab21ac2e494a039dc89b01c6c4bcbd3044615df044f40279b
+TAG: 5c0a2daffbd38ba9fa041c38126e9b281f618e98
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da960595d91b8481abe552607c202f0249df0d35e4db34db36e7c32c145f88a16d099877d74977093f3b5efca7b702e16d3e3e9a1bed2fc91c870c30b00151bbcefea7119e9e9d5a4542df9f44cc7817
+TAG: 0347d6e0c338472041dd70100cdbc31ce11591af
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e6073bb49a05aab47e1261835509e92f13661aa9ea6a8991c4e15d36cef7853bfd5eab841298410977438139e2dd9eaa5cbf22f199e5449da6a6009f11df1d2875acd5498de
+TAG: fa2d6ba6f695a6623b380864a963000ae64886f8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60ff28e1047551166d68ff8f7d6b1662e888539d33746c6504abca4fc0029a7683cf1636c8a501e4239c4ffa51eed4ee66819d91ec37bd01175f7288e78b4d9a20168e2eb9
+TAG: 2ee689b05cf6b9a168b1ed3d3532594fd6ee660a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e6092eaafc31edafccff5eae7e9dd2e84d843b8b2930a48f8b890a45a5350ab0ed5aceacfb893bda6cdb02c96d21d95c14a9cd16bf23de9360e6b38d9f6eb87f9915445475a
+TAG: a9ac9b7c16da2fc7fa467c8d73bd74415bc067eb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60efae2e6454f9e2c8717e684c972d1c9ea5d60e06897e57e3b404c0ea1ca6958a11e0602b361c6f4c83d32dfca296439f2b9e7b79a95a2e651381d0f5b93b834d5466736f
+TAG: cd869f2ee684df377001307faccbe43196195736
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e604db5d3c0a0754204f0239298460fadae49403ee45691f3eac0caf19bfe777155523f5dc12049ceeb591ce631f60019f70abbca82227da9578922025b048d94a89e81f496
+TAG: 1d608d8565e9562baeca59122b03b20b1a61b157
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e606ecf0a84b2afef9db65d8909659d70df3be3c8e7c49866a6879c39c1c1c889f248db278439aca1c42fadf2e32a4438bbf3f0aeab224122d17188dfecdfb3d022c68be4b3
+TAG: ab322175f3d129ea64a67c70570cde6390b9f004
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e6051b7e3ef0ee9e0dc906158be4884d27c3af5f035dc4547089174a3d9d9f020f7b3e2b7292d78857f483e0ea47fe2cdfbe4e2cdef89beef2f3e2dac06b52dda6d59f31781
+TAG: 3cdff1e57ac02d935163fe05ce6bd709ac80035a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60b3673527c7a51a314f8d467bd861e1c592c5383bf2329ebb2dee8fac9c8edbbfc9987b241f745a7a9b6e5f976b1e45cbd644e5124f36a9e9df48ddb8d1cc4092a79e9c51
+TAG: c8daeb99ce9f82a1c183a2dfc21d71a8dcce845c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad37f1125a09b18d0145ed710349e1673d7f55f36c919273d7c9d6ecdacb9e29391660fb68c23ec224289ea0af2e445c8570870a3e55e01167b69b504fc
+TAG: 57b6a52e8f5659b85d80db41a4ebb6923a7cfdde
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad3496b2e9d6eebccd9ad0107b4ede77eda3ef9346267bc5dba242d0c1ca9abd38a54291f1b730fa7397af72d80daa541fe1d11a4dca0a4a3908983b13d
+TAG: 7dc6e676aaa082eebe8a5c7814681a0e67cd69fb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad3f964ce4d67fa886b109470360d3da9d58612db6fdc71a9951c54d15dec2b4daf4fded2e420004026563545984f9c6278c0f782ade33d8f49b2744290
+TAG: b5aa4dd455c1ba8624187bc0310dabf9a9039813
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad342a4ee8997c2cefc0bf1d016e0cd5f08ead145bc70b369b0a694efd5488fea4b3c7534d751ff6bec5961f8fe5555f26f6be2b0b9085bb8373c023ae2
+TAG: 10d1ccf9f7530b77b301f7f52e7a2e5fad0ec3c6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad3af641d7a383c89c2a9623f58267c6767dc85178fe6320388bfc8b86cffba826eeb97983e3eb66af22cdc772b78daca93384714a2238a05ded9a2db28
+TAG: 7897d59990b5530db90d341f699603954223a787
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad325c8f291d95c92b78f03eaff13c6d7791cd23a71faa55f50374ece8ae5153eef402930e7df035f90b9bcea749efc3b044029751f8bb684c290c3b69a
+TAG: 3180e56f152899a38d437540965e57beadd34542
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad3c1b8714e3b2b61ee5e9bfc8bd36cb2bc03aaaa040334eabd9f23fe934b390cd44149bd0ed2df82f05bc8f344461370a7c463165d79168ba51383b377
+TAG: 3b2065db38a12705fe10d59e9ee8f1787dfb7b29
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad31ee2ebe37b32fd611eab42af3423e388b06e6b893b0a5b5f57eb484fb0093c2a3ea0d8f0a0332bdfae24db5c9312156c572f9021279218d97c2e842b
+TAG: 8fcbf65c4556be8ec20239bd70063e42790db969
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b617e23eab77d45bf008c4944ba89bd39f73c53410059813812c60526d9946d227ba0ac2624c81229101db8da12b6fea44611cf0b2c
+TAG: 4f12ebd5984c0a91a17980880b3cc99da7320685
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b61e8414b359a9f315468271eafe4500b7e1068313115dfa2d2049bdf3cb380cce3c91ce0664fa1dcadcae609327eb004aed1e68240
+TAG: 99af181fbb09c63ce3d00220f859270c79379a4e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b613bba0bed31aa80fbd812e58b5ae6c8370d4a3ae5c673e3dca8a33386a29623c23d2cb8c496970facb1868d02929d22d6ab45f153
+TAG: 193ebe72c3be3f6f0524e36d07f17609c67f1c30
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b61743d8b05e4c17e60fe2d0ed78e1c70e5ebaf1776c5ee8ddaaec9ec56821e3f7bad362254d9a066f1f8b0faf1218c2b1f1cf84d47
+TAG: 72acbd2e99b7d2dddcfd5102057d9ec1e012ed29
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618c7ab2dd9e499a5ee8b43a9a1c2d19810e17a04999c2b0043d7c1adfe6cb136c92185d5eee636caee02900e406df972e3d5117c8
+TAG: 2f0a83135e52fa1a2fcf2998f30af10e9be30356
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b61d2cf53ffe9a58f9edd51ca98c4f497f3618fb30a5120927fb0870866d33e7dc36f0d881f46fd325d4c087a02311ed6b72efb3d55
+TAG: 49b57f5399ed16ecc7422f5506b2a5a82b26046c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b61f19584eaefbc443e38e35ffe199a4a75f91a71c165d8ae1e14856469e72a0adef4883d5cdba223a54312494db820012afabde779
+TAG: 2583e3170a78f39e332ad5b2ea05b43708d649ae
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b619f5be9cd8bc5347bbd8fe2965e40167712b881eeae1e98f06c5aa75396b3722fa2b8af315d913332e41fcc725de38460382a3c17
+TAG: b7f9945423c3f607425cbaeff60c13cca9211b16
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c460603176bc103b80d99c81c82232d8a02e1df2d8117d02a77136a0a0a7dbd3041801f733d2288a2d85340e034da66
+TAG: 0c44245dc4f01656d20d6c8ad2ee36b87362cca0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606034aed7751b43863a051960623326ba03fcadd00426a6f7e27c5470da037656494cf8d209425439b647873447a
+TAG: df2efbf7611483a141028ebf8aeea6b4b795d648
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606033b4313522a7da1adc218daa6e5c3168fa3ad0d369b277f61752c5f7d6449d55498d0fcb8b6300c91aeeefc24
+TAG: 545481566bc833d18e6af5f4928ffae02d209cb8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c460603aabb3f70353c35f0c5829ea178e1c7be9b2235feeb7d7bca476515e55249a472f27fc31c425ca339c9ac8f3d
+TAG: 7ea2f318b0432a9e7b00137b9f7ae11d7832d75d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030d8428434d8461b91295695d6a3d90e1a03bcab2d88ae05069fff28e8b9e50ae440996d67e2698480f14d0af
+TAG: d753dcfa7dffca41971e6f45de79971d29cffead
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c460603dfdbddc63e495155401400ba1528ce7387f39101538649b3489d7ff411181b41a2c7d4bca9b2fdae60685273
+TAG: 8bd10d3d761d530aeb5497196b8818dd2bdd7be3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c460603e5fbf71e904879e71195715df1a19538142200471124c618dc7968de10bd1d850b4f7258552b0640a621672a
+TAG: 48159568f951893d07a85f00915337febdd13c74
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c46060366153de87707c1e2ff5ebaac8b2a0fa39c856332d58d121cfdafa460b489fd1bf062cf6de4bef4b6f855af39
+TAG: 31caa9b9ede28e2afb984c26dfbda0f0cb852fc8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c492975d6d33cef2a9cc8d8035a2baf3d58143a82c7d2eb335da1b060f1277ff3756dd22a928f9
+TAG: d6b98cfea8ca1558c76e60455551dc79c30b2342
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c492977d1a169942fe78c97b101a9e5d4f86597070fe84d9b70615a1e0c985af1194ee5095314b
+TAG: 4bc18214e6cbae1a2d256e721c34c60022e9b41d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929701489e71c2ad19789059aad62516a4e6e07454140248966016bf71f707ff2593973979a8
+TAG: ef236845d789b4a071f1903c79f7d6576f92b45f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c492972346e9230c6872c0645062837eff7731d6732cc6993c48fa0a712845de1b3db5e657e778
+TAG: 9d6f91eaeeef2efc0f4ea9eb0249e9fe43ebf438
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929759c4468079cc1fe6091e711c52fb67803d4f3c33e792a8df8a1c8e1e299d89ae529d5997
+TAG: 8f4203d9e2127302bec77fda84cd385d0e94fe12
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929704768b6905e3a1fc76f98282646521f8787d79fbc4ba30e2d94b2d7efa847a7fce78c1db
+TAG: 3740bdb419938d8963338ef514ac37807f590e6e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c49297041084bedc6aa719fcc3b1c3b81eeadf8abf41f8815d2854896787231270af7812a91513
+TAG: 57dc8aa2392e0a850234e8b47a381fe6ac989b62
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c49297cb85bc06fc0be808b13899fad4b50aaba41b642d8e76dcf31d9b0a14e4f73693be6d44c4
+TAG: ede5ae1367b69c8cfef4cc94f832056543a65da0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b4a210376e6e15bbe3c711432297576a978c632fb3211b14828a14ada
+TAG: e48d20829be446044ae28179214303312aa0589e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b77f02f4a5c23bbe93cef6b80fedfeabdaac59fc359cdea0cfc1df50a
+TAG: b733ee53426574b78fcda289126b9a102e7e652c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b0e79bbf9779de02343404bbc4b375eb8faa8cd3796642009ac386e29
+TAG: 1fadaa07769a34ad2ab1f477911e22688b7d68a6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386be849b4c40de4201e761b9de0cc731e6a103ea451e0f480bb5c87b84e
+TAG: 9c59adc597b5f38bf949a8129abdf3b2ee6f7785
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386bcd293f34924a4faed7f64ef5ad598d7e1073860aedda95a46ea61385
+TAG: b1358a8a3f7650e8368f4d3b61bf1bcc6632afa2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b6d6ec1226b7a71d3e13014bd22154bd0820a6992e41004b402c960c0
+TAG: aa1a80e9aa352ab2d072837892d49af210bfa93e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386bf4605b87ed4c350f45c5b7d65f00d399e81506f410bba8af001964fb
+TAG: 372cc197aa260d9bd829c8c473a7bebaba9ed00d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386baf431c29c3d212de63cfda976fd6e330d74bdc2cbac31f7860e827f6
+TAG: a3a625c52245a06a914e3ec1e0eec4856e66da23
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f0680285b1e57953756b9cdb1901fbda4ea47b5ae
+TAG: ea17e950cd91298fcc38b52337467a2595342343
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f72ef52dc4da1235edc9476fe9f2240c47a049d3e
+TAG: 7e55eaa00e57dff0ed72e083c389bfdb5cbd6a32
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85fb2fa5a12bcb835d6c9b98873c85177ad92cbd015
+TAG: fa07fb691137a78d770f0c717bc0eb27ea342a55
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f081026e91d3b1f3da3782c9160ee467782541aa4
+TAG: 691da91b0413eabd629c7b77b8903623f65cf9f3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f97109d677c22f509281b9dd7a75aace5886fdbe6
+TAG: 84cb95e3837393636aba0fffd6c56ef79142075c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f7ba470aa5d263f6e1a29203a957d8424449efe8f
+TAG: f7e8fbefb4c2cf7ae37ee1a14e05cef8802bd474
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f46b361cda109d53840150009456cd7700b47aaf4
+TAG: 09bf7b11716d6851b050752068b8a31ec865aed7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85fcd2bcacccd35a6fed122c3046a55e8a71b13286e
+TAG: fc5e5b701928b5733152717ef232120eda146c56
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f065946d4f8abb184260eb85d101783
+TAG: df909b54a5fe227a4ac2d7e796ec043a1b2d3afc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f065946d2ac54ebb4b83b18e5fb5195
+TAG: b1d84f4bb0c7cb9cba0188ea773aa6607d3a2d03
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f065946ed477e35146cff380c3f6709
+TAG: aa8f95419724ce3b55f06c8b8095d38e43ae1de0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f065946488b5ebdef7ce05a8d75a216
+TAG: 8c74147617f67bd4aa51a73cc8262becf680a483
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f06594612d5009a9969f137a08bcea8
+TAG: 58ea6be5c04e7921ae923243203e1667e11bcee8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659467791a26dc54e946787e939f3
+TAG: d85f9f17c98cd33fcfda583c0f8ed7eac3ead237
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f065946838bd38e83eb0650fa798a32
+TAG: 3d73b2507d8e47635379378e212a8faacc1b7fc1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f065946330d5e8a53fa3e465f023c2a
+TAG: 502b8deea47260f008dfe1363b59f9b980149279
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a2b78e9b
+TAG: 78f537fbb7160e9181a825e49fa76a4f8be7bee8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6ea6d0822
+TAG: 1a10d1b6749439e60c7a0e58964b964ac151221f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c61f9f5534
+TAG: f7968deb0141d1c751dfca4acb860c6843ff916d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c668a8c582
+TAG: fe7b6e01c0e1cee2112461fdf4d9d5072fa691c7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c628816956
+TAG: 60b5a71171b40fdb046967fcee93d3328efe1b16
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c65a3dfb74
+TAG: 06dbc63f13cc4b700c451e6d9b5b5a5965fa4c9d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c62340443f
+TAG: 1fd305cf7db477158b2874d2af097835222543f5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c66eeefe53
+TAG: 8464fd0281b13bca3182cbadad791177b65fc24e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd54190906cfbf05b3a76bb959be491cabc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd5df43892eb9951ac0f294d959a8e19aad
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd52f3ae9838a864bdddea8e18f932fa70f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd5f5e62b70527c93c3653365d49d4470f4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd569cdaa3dc8d941cf02c2e6b611e45e8b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd50034e5a16962390e9e20dee3bc97537b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd518f2775706baafc8985117f62b24ebb7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd573f4c677bfbc7ca4e4f6dbb427139135
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd5377f387bd914c1d6390da2072b1b2348
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd5377f387bd914c1d6760693487f49b4de
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd5377f387bd914c1d67f9bace5204f1935
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd5377f387bd914c1d6b6f4511bbef9928d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd5377f387bd914c1d6738cf34d66735f4a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd5377f387bd914c1d69cc20ac54143c916
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd5377f387bd914c1d6c350de61f5990ec1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
+NONCE: 
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd5377f387bd914c1d694ac69cfe6bbfb48
+NO_SEAL: 01
+FAILS: 01
+
 # DIGEST: f0f82752a691ef5866413f2b2e5c1d0ebb41ccc8
 KEY: 7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9
 NONCE: 
diff --git a/src/crypto/cipher/test/des_ede3_cbc_sha1_tls_tests.txt b/src/crypto/cipher/test/des_ede3_cbc_sha1_tls_tests.txt
index 19fd026..fb37587 100644
--- a/src/crypto/cipher/test/des_ede3_cbc_sha1_tls_tests.txt
+++ b/src/crypto/cipher/test/des_ede3_cbc_sha1_tls_tests.txt
@@ -23,7 +23,7 @@
 IN: 936a91d0b5
 AD: d2c0267218cb7090c61713
 CT: 144c98ca1f4a40ffe530b338
-TAG: e5173a8e62c8530b0c14b15088f70f550ab57e02
+TAG: e5173a8e62c8530b0c14b1508045d58f4bdae400
 NO_SEAL: 01
 FAILS: 01
 
@@ -38,6 +38,2588 @@
 NO_SEAL: 01
 FAILS: 01
 
+# Test with maximal padding.
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd5377f387bd914c1d64db1ee5f88627b59
+NO_SEAL: 01
+
+# Test if the unpadded input is too short for a MAC, but not publicly so.
+# DIGEST: f0f82752a691ef5866413f2b2e5c1d0ebb41ccc8
+KEY: 7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd8
+NONCE: 8503f78b8ed1c8e9
+IN: 
+AD: 936a91d0b5d2c0267218cb
+CT: ecd3c8f44675494e8815d0b2d8bcc125612d9ed52657c54c6c2cbbbfe3aa21a0ba23efb64cadbf6a81f0ad53d21bb5b536b10bd2173fe415b8623e24d4dea3db4305c847709b8c489a5d14ae35935e7143f4681798e30cec3dd97b304391d440a4d50f558cf9555faeff343612471935f5e4fbe25776739d7e36e36cd35bffe8c3b582a856cb9175b240338e4de9aa993add7c3d9c0f55aef162ede99acecd45dffa501cd44378f18c0bb9f21541ca639087a208f0a3926bf73766c2b77c50d8dba9ec0374688b733f0abe376387bf02e07089a9a58654fd1957b23758795b6ab9ae20e9ae45d032b99c200d
+TAG: fb9b92af0a7e8ca58fca1a0c2a964df39b1ca348
+NO_SEAL: 01
+FAILS: 01
+
+# Test that each byte of incorrect padding is noticed.
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82fffa4ca54c3a0ffd6e6fff942e7ec33d0d9e6ab8c9ae4b1ef0423b7f7ad15be0b8553a4bd66e7534a3f357071ec070341241592d5865585b277d2f60e220087b1d943a35cf2a72ea91ca1c57f481663cfb4608f23ab8a452a9b4a92b4f34010a7f74e607e2c0751404afd722fe989227915d260720cb3d80c02ea6ed190b832c1bd06037de68b55f9b0d2cc452378f1cd8d3c77665597441b4c0c38fb7f152ff1abacd61de5b25b494e752685e907f3e9112befbfdb722e7fa77b27bf9d8622d3545380938f9f0ab3a71bc3b97ba9033361d20605ebe1af42aabbf4c1dd0bd26e9cb9c21384ede090e23f41cb
+TAG: 340291c471efdf1a9d86f4a9443adeae2e1573f7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f97a5f38e6e3413efdef26233be485092b7a543065c741dc557d9fa7a796edda67a93bfe4edce2d1c525f19d5f3575e81a9b3900e4ba9c58d41e1ec10cd6ed617dd17d7b7a3c49164cd2b37b2d1df52f2b805b3f28dbb1f43adb8e1eb72b1d2b3ac51e96d60622657406dbc3fad9d34535a760fea0955811518b60cc164d46dfb7043e6faf4d29ace04fdbe5a7a559fa1e01e52e2b69009441c1efab68cdefd4eeb1695d882cde48f6c591fdb9ca4225b6d9beb90aba7725fcdf1ee118c1543549f1dbb2b165596bbbefb36b6b849d6495b8f59a22182f594ae273c3934d42d7c5ed300dd0cf5b25ba6d703d4
+TAG: 391d8381b2471d4a04685a1e8fefd934de35b001
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f5092a16f7df9a7114296b5902b1f07030cdf3da0211fd57971f07c765f0210c98ff2639bfd44292b2b7f7fd711a6d026965abbec67a9dd1632781a447de10432499d0c59e645b15be76ffffed3a434b5ea50512c15938f63a57fa0383b9158cb3151215b924a8cab60ee1ad486dd2fe4077e3bbd050c7df52e2e494618dafd5e0b4d7cefea7bae185615b72d51326e2cd4ac10405c1855a500750e4d3ce5591aeb5acce164474cfdecc97ead9562940f9729bfa1415c6b439d53bccd43acb54de78b4777418ff6cbfe8fae10d748b519f589b55bf7b472f3eeb1c576dbbcd17597806fbc6d996bfd0fa0d42a
+TAG: b021be068664a6e44095b51346609295efaad9ee
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82fcc48172be151a13a6999f4f5c476f40968887568c3201e8260d59e3a3b58643195c32c9d49ca9deeb40ecae4afd3b3464c7b175ca26ecae12cce7ffa3b9a2d5b4f73083d4d4c8188bbbd65d7e95aa269cd4ce4488fb136d115cba8f3fbd42122e848b26a8717d4da46854ad45d62700ade577503e790670b1aebf87afe9d1438fb3fdaa029f93f53422bc368b9344d0be16e67deb9cafde9492f39601a87199863277eb36aeaceca693549b23254fb80f7512ea36c896b70f41ec3a515b220cf0b053480182d5fc8e6ae7cee4f781186b9d8c50ca82e848dcce420a2b861b970a1915d6393e9e57479dc464f
+TAG: 1e3f3761c54fbfe087491adede031a2833229bc1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f5b571bf3981be2300d5412ed491b112dcc74e9dd8fe8558efe0d167efb1e9c5808b7de72db6c853b9845201707717795255de40f3bf8d5dab2b6be53b937f7bb67ec8b23205a166802a3641e0b2eea459baff12e6eda2b2d064d5d30c33e80ce6e467fad6d34eb89e2b996a9ef737b4e2067a583750497eb4b32285bf9fcb8590a629a9d186e9eb17265298a485dedc609a43bf1b0ec5f4ee55304164bd180625e518aa013763be1a94736b56844c9c31266e0e7217c324f13e7ce0950d5961ca40762e45f42e080eed79521c124e0d96dfc43964413622dc893a845e16bbb9a681397a42747a9085eca7cac
+TAG: 43778ab01acc71676991abbea0e7734ee6784e7d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f5a172605f496e4ffacb111b8b5482636b093d29285fed444069c9555cc3ef6c67441aad437c94e39f5d3a541de0418f207eadaffe0149ec779eabbb9ad3c35ead995603aeb18bfa1321363bfda10cf0922598d74a5a83be08e9142fb614d33cf8306ca6519c353370ec2c9a68d37f50e852afc190294f8d9af7918ecfce38616eb5ca70cf3710da6f8d224f9d961a59e444aa484ef3d79ce8d8f5d0f0fdf026527f5ef4df2767cc94b97ea442b5b5c4e6eef6d236488b5ba07801f6e425f580738722f065cf2a6e8f5534a0c2e7843ecc510b82955d83e5f4a2864638d0f42041cc16499f42321e05af94c7c
+TAG: b075eb0315f1c3cef99ee88e7388a22eff3a7a44
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82ff2d2004cca0722013e6808ed9bc99b0c4a80991525fea38db2b37fed5ed8632c969deb474122360b1ee810e47117cc1f8286aa8bdce347cbdade770f337deb84d2d0b55bf99a9d2b1bcb929e1391e1b601441145316e8e7663795b581b8807b2bc70a2709337e2480a5c6a3933e0634cb5d5c0376a8c7f05860f66a196ac71bf2b158c9a2f3e6635396de344c58d422a8ac86fab38f28eb908980a012532839e2af2b6984c59eea0c0f49dabf617988e6e8f96931bed6aa1519387bad1fe1a0e1a1b42351d6479aa96fbec4e3f6cddfca229b89b680c22e11869101df2095b24b5b33051a21125d6702fafc4
+TAG: e5d1196a9723a343946473a89ccd2e24b15b1d31
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f7300822f214448a904ccce467c43825a828a1f89dc9841aed04d06f22394a81a8250ed3080d52a096325a3e28f55c93b32296f7393905c99011154f7fcbd9d3b24108687e291eacb5f54e1edc9eb91305b6c3b97d5f4817a294979fd4d9bab2e9262fe59a464da24e8c7a4d5fdeaa4c01633d537f863f798a247f2682cf1066041c63f2490ac903118b54ed11d66071b0bb050296be27c96b0f07e64ef7154055b67ff0bc9c7fd6909e23e6cad9d2aaa57a7eee5b12dbd9d26de530f2d37dd0c1863568b1fac3bcea411d1464ca8a44172e7eb719930db001a0d9c1b2be3502986e635374fdb54d7a68f2135
+TAG: 99e057f6e1efa20d3d423db993d7a66bad349d90
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f129cc6cfd68eaef7096800257ec20a080188f2190804aa0c48221422ab3cc20f687b5945cf0b95de2b60411746cb20353911ba96934973b2ecbbe781fe91931b6521bd212b7bca681d261fc702adf8ac6eb81eed22dd1d76b71ef6fb91a82aebb6eafa0bed1207bf7f27d7864182c89aaf7de10045ce964ae7721df433698b3b0c957d5c65739375d699087bb26474fa50efc8455931513e040e04a49c6ce5b3cce36fc36ad9ffde2040c1e50602d39382d1ddbc10ef74b19022f96384d8e3f9963db95e5c75b4a5f050a658d25489e5ae51b1df7bdcb060eb49c9f7be73b15a54c7ffdcb77
+TAG: 99c4b999b4a9a80fd98b8f87572ee3607324ccfb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f129ec5f9e459a831e5fc0c8fc19c7da28f638f8cd35f59c6436707cd742818493dcba9576d26ef484e7a86309dce93127e795601aec1c2f445ad93e95a8b2e50b16b63cbf802288ac64d89df9612662a009b7fd563491d744f6483c2c683e02966c509a1d3ebec71014a4bcb705f1ee849d7e81bc0e003ef2052f61820787f3fd80467de1adb3511c15a2fc32f935c81bd3eb5e909ab875bf793ce7ab549ea5eabf31a90eb51a533790e2956437221bf8fda72c79ef0f9ff9d010adc0452a679f786ed06e8a76845ef1ad2a2ae74c0bad5c16b43013ad675b4b14879311f0be9cb5c376b40d
+TAG: 761cb73c6fcf0e98219efbdfabafdd81dd1b8def
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f129fbb04f98a0935e7ab3705d26e0eb67478a01e7d9f5b438130d4dacc02200fbd3daf1ead6cdcf635070bfd51adfc13e11b49928d1941cd040938676652e26cec8151d99b41a7b33b2e88bfb9f7df417527c36a374de95c9fe49e72342e6cd593e3d2a07473e1031fa370e0fc21e8e66fa2da83be78498a4ed80d7252b79419392ef9b7abffa81b3b262bffd33644aa1de8b4ceab86c43ead92b5ea47dc1925a08b0604fddc2afeb5bdc5cad76820e8162e65ce9eabd387a843c7023f8d48542845b26390a8de80086444712767e1ec94df27f1c79b04f3c1e266be29f983fbfe060168a21
+TAG: fef35dbbb49213d4836eaceaae02fb5ef74d133e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f1294d5a43724866710b205e90abf4c79e27b695b9bbf3e6448dfc7209a75acc30888ef1c476f1f3e58828690d7ed0edc79e009847d7c5b55359a3a614727c802116b63dff0f17b66815ff79bb6471f8adcbb47791f09c4a4d4cc217baa987506c4b209dc34e9e76218ce8be27982b3176f82642a4ae4fd652d56917366314b63d149827cb560403b9da9760389318a8ca0e3360aebbfb6d73416f9aec61cefc6027299d4babac671b6f1b14472cca56a2fb72a922418d9706a980c139b7291bf648189f0400247ad758a213e936f6a9589414018f83b53a045f19554e8d57e3577d09b2d48e
+TAG: 5e4b0f72792ae1030da5ba463e3e13f9bce65202
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f1299747276563ca0a14fc8039bfa3b8142a481e32af7ae8ad1b7996a12fc423ea9edb5b54169f944ae0be9670401d178700a880b13b025d903035fa1ff0d6aca681c3a0fb486816ded99b090a4e3e02fcc320834b9e3f48704c2eedf42e385db06b3a6cb4a917824c340e1d3f1f4e23445dbc159fad9a184b7692e42c011633f1ffc7d4a13fbc207d5a524321c9721e7323b9f3b44c11a170b88c09140cadb056247bf1194cbffe7f814ff4ed65e12fc495ff082b18ad695b110e5ffefb5babb14e6b67f3142d76178eb8fb1201d672457013c7a418c24d2a8a7a7468792c105387ba55a89a
+TAG: 57c4509dd98914e9370bb464c67aaf21039196b0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f129a0aa04aa6f5001c4b81ff6178b687b310a5839e5b785baa7c21ac7a0827a3ff5df6a145cc33ef346d59dca09674659833f4ffe2ff0611baf5361a781621db8e4df54740a6e2fee4f8058f54d2bde252b9d3b82509b6bb267cf1cc3aa588eb3a71a57843f980d6f72a794fd8c3a3f6f5073965d731222046613999f43e47d1144f4f81973af9196cfb21e27bdd33610d282a7b710e40fdb43014e2f2b4e7fc0c9312a09d41ff87d698e28ce1dc327290aa145f9e24c709fda55c144d418e5cd4e2198e8f6670cab5ce20b80cf9e1081faddc26e1254ea1ede940f819abd27f6df49de76e3
+TAG: 9cf918eb9ce5c18a2bb958082905cd379636b3b8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f129ecd39f87baf0961d75cbb7b862b9111b266712e129f5cc2320ef8f47603b30e67e323d6a93732994140fd5152f7621b75857ccab0c8f95c1562dc671abe69565871bdc42153745125b1c205dbcaeb535fb994608c8f998aec2e49b8c7953ed0adbe34dde0e7f8445f20bf20282ce03391b0f5bbca37d38ab8f93b1b32e92d6c30ab782a1437ac3e1e175216aae74595b98cfbec8ed0341c25370c86815d68e3d7692a75ed487e7dc9b3dde45dcf0d37cad8fbb8f0df52b0af97e028646bfb7c0a3e967a49d2d0f8412272b416da2d20643776aed03c2089c6a8a12263118caa701cb2fb7
+TAG: 1efdad18595b089e3dd9a8494df17ae2d5e90311
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f129c1d716c203b5fb64a76805a473c7ba4fc527e21bf4d049f898645f103dc6d0895fc383022d9474a6ffbc2404d5f4849fd6e1663f27ed114a2d696bd165af078a7319f748d16b433522a3248e474e88145331da4663dc665d6d82ae20ed0c57933d089efff5b42a01a7a96ae737ffcb6db4043392d16a0433a8a4ac59e2807bb47dcffe1173afe6ab1b51e9c0eebc2e5f4cb6a99fb03a450d75b514da9cd02847d0be55c448beaa359cbada849fc5618a3c93e471c228a84ea6d75d57975c555409a704c758388ec55e8e446046ca9cf90e0f89ef5891f9aba75db4e163d2e508ce098a9c
+TAG: 146d8b913759c8a4eaf63edca37345bb350768f6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421ef3b87ea1d7abc315fe960893a0fc8c64e748f976907f46ee28cddd349068ee906f1e227d4e61dab0e56ad2c77056ab7abea02ec4f272e691c393c13f8c84dd33dd9f0577c60ba60cafff4c0995a011b53a9db5e7a7253c4f52cf419ab211a7bb5848cc0d0214d7e04a650172a010abb378efc38576bc8417bdbf3b07d6bca17a81f70280c6c9e71a1cd4d32fc3f7239dff76b0d9dba8b35e5e928369b487bbd0ae71edcf7dae262693cd8bea5c17b298a16ad2156db535cca82ec767974dbc37af39eca5cd92deada63493d3a7db57b5431c91a88d89f3f82931d749a
+TAG: 8608eda1843f40ba0bfb5b5fb0c67df35c7bcae8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efb3364bec4d41a6981013ed7e07e776382d02a3f6f060d488b250ce580c60756e3c10df972122d33baa773ea1066622a9a3714ca8685bf796b11a46b8534cb2309f6fc0656544c3d7b4190e31a4258d5760560545b79cc8b0d5ee9e8bbe0deb15178c7d4c64b4f284dd70e254291e8e36aa2dc9f6deaeea13581259eede25c589fa8a19463fc22781543d33b45800359670ad825b05a82c2d683d00d93a027c0712f9edf2a36eaec7dc7fc12182f7a67aee50846429738d29f7aaf11d09a2bdd8363cd01bae9d15d949e27ce96c3a4f2b34296e1736fd67255a722486
+TAG: e02c9edf65ad422063715ca5c3fbb95409353124
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421ef2f4c94c53e857543dccb7859990090a1843caeac57cb755f7f92486eee4201a66818dbebc47a9e3135df4e0830a6c233eb1254e1d272c40057dfbfabfb07b838260bcce046d6faf71acf3a7e049bd7fea164b0cbc2809c3ad0752af027dc4f976d31c9aa05fc348f1c14a803b59c1c90856a2f32af78a89574badb056b16d856605ed0c217593b3cff969e6466b32c1119705e47085b6f9b2a76ce52831acccf3e9ea8651b3d520e6820a208e20a15c71427d29db3f0bf34066b53978c402a87d39dd972720fea895bc868247aeb90103098efdd27488ea83701a302
+TAG: b6afb8c97cce78b08d82c22343e403b89c2c14de
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421eff906afae2e433a5760fd55862cacc6d48a7dbafe28054dfb27dbdf143cc62c89d2f803aec795097fb15ef43eae56c292849499e401080ef1866345b3c4c9260d78a284bec85e7aa8e73d293009cbb204b119f2099b44eedb155dc269f0fac35a1b5c65ea0688bd4429bfe29907182070631d3f302b86520c02593b843d52dbdb2eb2504df4bc8d4ab4587c627604dc521c8538757ce8ab547ed509ca013f709bd99dc34a85808c4358465270c88c442079e8d0e38c745647b5a2efbde553662930f61bb6321124925f66d5263e1f7b1b2d995f7a0125775c0b11b40f
+TAG: 717afe257cadd23b5fa9d2dd130d252e91bb2798
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421eff24819532092ec210db7f3ff075244a61fe0f5b39f33985ae99f7439960e297c947466b65ef94302e32055e84fc3a4182568df26736173a19672b6ee47819a534e20e2d0c5736b32d57628b4a09770e28fd28941ab1a21b4b8ad1eb8411acee9bebd8fd5104f7b4d0a1358ad814ab742f4051c82ee82974ccf570d23f87cec9558de8276e18fd34d74a9032b950080fa0ca4da66519026a581cb0237bdbfee747e2389635de3f98d0a6faf2b350f1b20bdcb2e73134ff5ed63416b440f439b551964bd7df0df4f99345bac2414fcef7a836005c1d3c7a89d1f4ff870
+TAG: 22ddb81eafc3e09f8a3ff5107ae99398c2c4f014
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421ef71d70fb138ddc82dea24731c40c6753e55c14e36c580f0d0bbb83555db95eddb0c0f127463239f4e5295fffeabfd760be950750c5a840201bb0998bd61532248e31cc531490201d88867c31bd2a52f327aa5a5ceae341ee118c9cb6ee09e6f491e9e2bd989c98c939ad13acc123b5f246dcd30e277b299ce8974e015f39a60de5e04e329daec146fe4b4cbfe9a26ceb9baffbc9561dced8e7b2201493866310f09dacf6d4893845eb4a6c0f7465b266eccd76f0be5d39b8983450727cb0a6ea9454a76547aeeb4a36f3c224dcd11598d23f0d2f7942eba32ef4dd230
+TAG: 421fbd4b75d9a53192851e2525f498c592227c0f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421ef6f0a30389b6b479fe2b8012a6e61c4988480dd7d4b8bcedc9417402ecc5c5e8ae5bd0d7bbaf962c32faa6d7cb264cdf3217f5de534fcff95f78c46bd74e0a8c9d50fe6247a7461446f8199ada59ea6cdd106570331596234954b62245621be91a036fe397923eb97375ea6bb7b0a5f2829352c5c84dab9914e64675a52cb08d2ae5796b6a1d7bce48782f86f976310a6e15ddc4f8bbe0677bb5026e971a935bc0a997f040e6e731c54860e611f5bff6dac49e0d30c33b59091bb142d83a06fd9fbd6bacd0912e989611531cda1d9f07ff7e0b6dd5a781d52fe2d74a5
+TAG: 1294c87e2f022b6b322e0ae1bf5cedaee45afef5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421ef2d75f27ebed8052f412669a100e2be0d58c67dd73c799ee5166d36ac5e7e3f3a94d3a4ec11e2fbf93797167b61b7ebecaae7bab977f824efb24ac0cf5134ea48cfc12a610f3daa7c245490d7f3cd9b2e5925702b5629d90aa4a6bc07f89a309a9b5e1fc3998f5d7460516111b763a9c9e2bb5cebbe7954bc2bac4eea29efa1b68c943a831c7caff742646cb664b4c58ad25fdde1837cdf66aea582664539b474150276e446ae86aa23c575f8385a4fd4ad9307d82aa5b0967aaeb9a0e27c48433667650f7e2352ccd56bd9b44e96fbaed52dc50d499424f31d735024
+TAG: 36513ba6cd3fa1b0a01969bda4fc7d5e44371cd8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174143aa674f9a9d34ea4fd9b58eb6222c138d10e78864d0175645488d47270d953ca505af7d9efb72f6ab0c9e0200f2a7c61e23c483448efc4a106304d1644f261a023d6d52b9a9e8b1d42941eed96a8c16c48387a8f3b559ef23b82558682ac8427639b1aee6610e15e09c2d80d74087a8f18efd914d71df8f09eb76994eff14f975217604897b3bb2ab79ba3eace775fd86d1c16fb695318ad89aa1e00baeefc188439c49aeda0f543196bd80188b4bef946757e42268747fbf4b2b0d6c87c1ee0a9ac0390697a388ab629123c09eedecaf4d231
+TAG: 79b685adccddf7d36f4811e49bf42228b2a8eeb8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af61741501b81aef8ffbfd1563d47f0a8c2fb1f1d1e0523f8f34f7b0e8ef2787bb53b81b335ae63e8109ee8b3ff407ae36c16bf8696c67adab0e582def6789dbed3f74bd43413fcccfa113fba7562f7fee118e36e445e3a4fb3479f6022bf02170135bd4968ba1351f8df56e4de1344bedd402068709d1089a9abc71a45b2632210a74d6f500677e4da747db8c62c6b33265690b1d60f8a2b71f2a79b402c7fd014cdb14f9c5d4ba888c551351d709681b8b248a8cb535e0f1ac7792ba06246721d66e9cc5bc9e01b9d26a582b543e371cfb5fc0bac75e
+TAG: e60f5f43bce7dd98e56535afdece3c14fcc2f700
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af61747378a3a5d06148a3c44176381b30c927dfe85959135ac610266cefa23b9d34f3c49fc727732994e3194aaaabb88617319a1384166f797bddfbe9b89e9aa4c8a4a32a4b6805ba409cf3e54ffb35917da27ee29a099d91e1e60ed6c2dfd8796b952106e5ab79f2bc5e9c8fe5fe5ca1a4f5c4a6b23a819bb385f52d1f08468a3fb2d3be84e617b8e8974819d147e3e48db3b251cc4218fbdb5ba496c290cc7116f21e56d7f10beae592eaeb6e1ce6e6783f54790d5205d20954ad0b2982a7f57b5428e818509a266db322fc6eb06c598ef553028e63
+TAG: d4cd8b0e72025ea96dc9db64087bf81bbdd12e4a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af61743665f22dd52c9c1d27a4a82b5630906500b7e82d39540ab0f0e780279d6013b8102f4c206f4bef8aa7773ca1c3857cceddb49fbf32922e765c32cdd24ebad44c5404331fe5d2afb76f4a17c4afb1fb401380e250a7df1026df1ffd45ba512f498f13d3c44f5b94ba3860f5af5e1faabfea84ab9e8c2b8553b304eece0ffe41b727a040b2fb5809b2177dacbb8ce7102fd6470a11a6f012688e59a4730da5083ab748332aa5f81f90cb710903ef895763cded2653d988f37c8dabb44c7414f62ef1d738809288993f06f21fe06bc116d71cf651bb
+TAG: 0179e77ec1b15c5e93f6eaaad8ec1172f128cf85
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174ee55df8fdceae223fe451dd828a2afbbf92b7bfc9b77735f62fcaa15a7d1c45f5b1705f4453601efcc6afc8338bd5b9c4af66e305cbe5349bf7883f69420d88ad46aa4ce66482c6b042342b8d419e27883c2ba025b5be9ea5e4bc4f0006488b100120f626d8f88b0c6d5a05dc2e914558c41a262cef93b0ac33f9b81ec7346b2126a3ae1d8821a26c40d6afe89bc439a4e58b2d1b4b9d49b45f531fc94f83e7ab5e93f305fdab01be26bf5b111646d3fd9ff57157350a0c43156d9f83fb592a4c1dd84ed8616075068bf00821bd29572260d914c
+TAG: 59234921759384df9280510cce0b6c1d376f0c1a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af61743b3fd9b98e7d508fc0459f8d0fe938cc9406a1dad65a6359bfad069df70652f868ad249d53421adfe68ac08e1fde918c6318e08213b264c6a7b28b45369756a7df10ddc914c5ae82121f337c95b695c84bada5e90fc28a3612adc98eccaea39ecdbab64d1ce3bf2aafbf38842013f77a5f829ae6bc7dffb10c7feb5311217e1cdfed1e1f6618c1906bacd937f27bbb5b9d40d378856ea281944bd3336ace52b1b276d9cdcad59a1d986393752bc4b444eda018fb0134c171fc12b1b04706c0a0873f9575f62a6892ce765e5f1a7de952f2efd92a
+TAG: a75aba394d6d07c125e002092377452786612c2b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174246f8bdbd7b714a5fafa1f56351aa9b5819298c8dba432750e5bdc98f9e98d2ab3e3c2438912cec4b22522e051f6a9ed94a282e7e2eb76b51dccef203f7f86e7e44a8fab0e95468bf824bad2af0690d8f9e3e9647207d40ff3f1fc6661800d1daae1ba118fe5cba6edd2c3f0fd1152e4f21e96d662305285f71abb00ec874d8c290e38d7eaf0db9777512ff0b0522e9fdad685dbc662bd99882e20198013ce72e1247691558a35fb8e902f3532e06201f6ecd6a5f2c83b00e6995c0e4b98c9477caca5e9dc2da4ac90ed29268e16685627247fe4
+TAG: 579d1b2bb727bce33d468b22f3079aeb1583486d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af617408ed59b9fbe8101c419011e03572b1a0dd51213ad7c9293c2795a572d87c0bde407d128d65203a0718621722f59dfff1084309674bfc18c1d08f383be3868e1b79401752afcd39f1c36472891408e3f00c5c479237ff92ff9a40510b921d23e69ba6cfe9f545f491a96f10baa718387bcc13b0bfd9649cbf04341368ee4263b72082dd82c4a1d57ab50be52abacaf6502f2812589280bb26e3600f456de6933f2e08f2dcadbacb728e558816106afc59ee64a79eea30963a06f63f7ea8e9cc2a7a513587df072aac03d05401d5f0ed58d0208998
+TAG: 83854cbc63809e1083af8cc74a5fb950e5226318
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086ad618a45237d9c0a95ddef0b61d4fd1dc37c472ee3adca441085692f96b389d279da0989f58176bf9ceaf6f0ae012f91c35d4eebccb1c53346f71595aedb30d3fcdaa60083e42d6632c8078d1ec7d01b84a59d9c1f3ff206b130736795b61329431d936de4c326c7c499e47441939f34403fec2ba30185fca15e53bc1506535c580ed2a813558bf22b4fe4dfc32ceb492433d39f723352fdce0510d979700f7414cf3172ba524dc0bb56ac837f9f485722e41539622ce7b06d7903caa82e8e6e07afa97312bd6639037cc5666
+TAG: dafdbe7bbf9d775fc759877bc3ca50bdd5361dcd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086a28e661795e3d31ed0075b05b5dc3c943a4578838fbb8875fc102324695d783c8a4bbb464783d23f13145b7a09c20cdecd7f6c52909c5707b3b1fcf029a70529bfee875c0e555e0292d6f77b81490be978c09cd0762d7f714f07d083b7e5e349240392858176ee672b90427ddfa547ee3f6e8244f6b766f1d14cbc8c8d25efda5060778b3af4c43d7db953c607fd6d601b68a7b9d14db2147f6f45696cc3a56fc20a199eb42af954974d77cee8ea875830263c1925b6ea2095958bbe4d5e74446fc29b715b69cb89ffccc584d
+TAG: d1f6c86dab063f42495ccba85b2d7d88967fc9e1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aef3aa9e85ee3963708edd8430116e03d4b0b8bf3f899ad2291448454fffe135120e3573b8d88359377b37237f36f81d51f18295b9b7ac3186bb03cb507a1d9f0102738d7382dadbf3d0feaff7e97b618390e407b881012e7f5384edddc5da035fb3d165bd8febdf42d691b7275d3343e90b507e7b541478c43c07ed891e9647a547f19b35b89124f06c219b65367b081f7b887b1042f6125c7c673a4183de37529b805eaa0c664dd08f6fd3e0ee5ee92fdd34e6d3b0e3a3455862175af1c6d0350bb42d5590d7abb22e321df
+TAG: fd5dbc0237285658a151e88f5ace72b26b3350b9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086a4e848ebf02ae731972896df29a335c8e55c2208157ce0a42a4056660f6a40ec8c27f738fd068cecaebe43269d781c72c4a4d5fbcf527e0848cf0a8dc1f08e75f44ac7adb354bd6a8c215d5385badf314666b9982474c6c33f65344614d85a638e42b4c0bffb67385b7869763113c6ce6f5b2b379e23c001b274e8d25cd5f1badb71ae39690bd48c6801874f2cef87f0e1dc6aff6d4fb1c99f99ca3167bea53ea46714f35c2457c3b35307ef2b11999740b28697c0a3d18435b258ce45236953e56d6b06b539a53477cf00c80
+TAG: 96e1a0f1e6d9abac19c7963e3c805cfa3f05dcb2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086a044370470dfb72314a5806e0a83fb29a59a98d337981c6c5afca5348fef16c5ed938cefe9797d392a59cd07d94858f94ff0f4375c71b3688cdbb057a903e7773fd9e0f2645f03632830f70ed1507bfeb10248aad345420828bdf4d4b02f7dda82b49d6cab20d3a8068e7c41582cba64f71076912b13d98761d0f93abc68f58a73f6ab18123028e1adc52558bfd16687f5bc9ed11575258300999ee091c5f26876fe98fb1ca3d84189f3f05e0e1f7532b651d0458bac9a43a5c6ce26e76dc886828daedbb95f0f0864f9f5a7b
+TAG: 88384b195bef9ee399ab25faacd52baab5f70919
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086ab05d59920417fa42bf3fef5a6d2bb5c39d1abe3792bf64aeae2cbe98ee02359f1ced80535cf6fefab5ee95a178dad66d491331d25f5fae2ba189160e7c68d656355db48909f369d6a347c4ad0cb7d51c792ddd7ad681b39f153e3717d2f259f7af9af0b278f1c07a55f68d51e8be7836f21a83f6cde87534b820cb0eef8a372be01582976b74ead7afbc14526a019e11ba95b16d50d85530f0564fa92bcf7ae7eb6f0288a982929bbf7ab2c2fcef6d6226d466fe8940d4a32c5f558f8d0b52b59ef9e6e63cfc48c8e573dcd6
+TAG: 3989e038cfe8c8534e167b721990c4805ae4547f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086a896ed500a14188ebc9dd1339e7289e4ede7bd0a7cfdd40f05bb6790e63a0f3195521cd89db7a314249ea6293bda3d785ef34ff9866ecda01ba422d50f07f23a09109351919611cc01fe5e4c6dfdf4de21599934093d4a7e46b8dc624a966f28a018084d8f70b26bc23fad04b131b77dd9a2ee5565d34b07ddfb352e6bd53d0e13090eea31a16f2c9fb5473e76251a752bc1fd93f9958c826638f58c77a22e5e02e3a423f616b17270bb6ac3b2221a1a1a5a9f5ccb14617d6106ef85dbd8701299345b4c95526ee2f0ced4018
+TAG: 95929697b887e739f938a14662c611af134b983a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086a1178d6fa0773da2e31660c8886de71b954b47e69982742aab32850b095660fcf3262cdc64184ff8e3a1460dc9ac6acbbd2c957a3fe57c3d480abd44dadd3a6c63e60fa25d7084226f1b1214b0a5c57117ad975598c4a8a3a4464c6db8148cd736fbe887308b7abdeb5dcb49b7e618b00339f3e3be1d03210627b5b1d4e7fa70ddaf43f9965be79be0f34652992983a1390937900fcb2e44eb7dedb02307652000d0b3c3506d3145422e7fcb298dc6ed515e155686566bcb481a4cdda6ca8727d7f8037d9a6e0ea0265b95898
+TAG: 990e580e4963ac947ed6be52c7f6a958727d1f2b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa37316630e673ccc7cf6c2da5f28c2fb4fec9506f1a4042e808d5073db0fa7bfa6e7135f2da825e713eb5b9ccba40d123ac5b1a4a58dd2fbdf565f2ae6d6ed3dfe99bef9e29e6cbe2b70b87594d46dc71dc32e2da5a6e48eec50bcb5860fb9b367dfd44cfb6360eae83eb45c3a7e9bda612e8e0b0ec5e6a0a8c8f59839cc58d74104e8f22b261f84f36765d258ed1125597e39814cfba3af0cb1159f6bfc68ceb64784cb70c1786cf475c7c719a4a005baea284f7606840ec27d623eae5dde3285b802cf860
+TAG: 2c1592c6f68ecd194528fcb284b3e1319996db4f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3785299afc5368c9d58aa35e350c31a1c96a4cf04239cce817168ed5b823c05ddcf12207365fb74e73d5d2d22f0ae6998d7304f9f887fafcc83caaaf4bfb9f792b144fc6549511fbbe8032cb0d8187fe267c2f0da624e4ea204d865c9e9d4a0f8733ed3bb061102c2c35e044a1c70d6abb9f357fbd01d8c52f8ab544573fbcab8ac9f92b3eb00de1be5f50afdf90b7c83d60821618fc38594d9e440118660f3a84cec89e53b93582510acd8108121990a032365ab659178475a65fc8d9245b1f58ae1a34f9
+TAG: f9ec8f4b2bf14265cd795940cdf405d150b19c3d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3795597706c936d52b8363ff1db2434c2eb393c7c99854c0246a04c7ccaa7c87ec99dac909398e91f71f5d449c56a026a3e36da28daf3bdda8efb9ea4cbd1ea0c9bbf4225298b507f7463539276f6049b89e66d506ff1e4b0b8dc65b1a73954aa94fb66a31bced7173a5d1d0fb4af539bd20f68b79cf9ff79e597d184c0b2beb027f3b09d1f425038c29f8e88c7acda99e23a76080f304df3346950793613931471233cc2cbd6b239b67cb9c673ef0433c546f52f28c3e102865727add96dc02166faf4918
+TAG: 3cef777d7db821552b43864120c48a27d5b30146
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3751735b66d3369f28be6dafa382eeabddc542171bee3348f1eb8f89cf26d80420885615338ae05fa9fbf5231e33ef7525fec5248df06e1fdf353558a1817b0011bf27f31508826e21f2f074d47246975234484bad3dbff4c1fdc528c71f5e2c7681d501edf4682d6c3d2e1a3f2bec92d736f2d033d1cf53ac43e430c5a98a181e432bf6b43a3f1a6174d7129dd9a475cacb8572718e9e4e2018f90a35d516cab173f73d98e65d348f2f5f0b1563a6f77f5e174f85e091ba0df0189a1687d805b58ad6cdd7
+TAG: c907c393603cfdaed879ff70e93f9c187db5b4c0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa371e85c9153345e80e220265df29120df40294412855f58fbd4eee0ba9f158f72c9e1a5e5dc1cb5c633008ec790d3b8ce749604360f2a98b4ac99f4d272f58c55e553007aacbea5b95a416544b2f189f087a5cccb0899abe97bbbf69b753f81972fdd1e1dbe157f98f2fa23b290ecae71c5657c144285cafaaae027d129d332e42a8bb3fc15aa45c7371b51cea82e609a04a2e76f26bc2132de5ba4fbec67ce6b527cc598426afb0274693154401ad72ccafaa985579969d301984dc166f1253804da1d6b6
+TAG: 383ebd9d3f35aa17d76bec7ec29db344f62a0e8d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3719ab703bd54173f1ca7b93c7bc0ef607acd4c3f18f0bcea7907a90d0e0c33156dea40bbdc1e7f73c7c466770f2fde4ae1c5deb1db6905d38db94b5bba22eed2d1d8bcdb62baf54e73dca2a007063137732ea08d120aba594ac5336226683d151d0af5519f76d203da0c048d7c14973705d6207a0c68fbf5ae4c7f7f38c55f3ac52d2f9ff4891997b55de429a5a31fde46f5e35262e4a80c25e5645926e99441ae996da98d7acd58075eb2a9af88f24f9dc06b9502f29d3948e8545c90bd8e31d84856e7c
+TAG: db9cabd974846222fe1578714bdf7f5bbf99d020
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa37401a3dd7a2e9d4b10fe82a3e53ac33ca20e4ec04f05e4e3c8e4f75b50b6376af9ad7cf35d3aa61a1cf2f8c363976c8d1cf9be30392d1240db8997a34aac358810f375ded1ccc7a54d5ba3919364eb1e6da6f1e31ca5690a552356f878bb1d0e67f9a4c7a7453ba382b814c199a109edc528682248e9dee966ef7d2ab0393f34b5c0d12443c47214c0648033e323e21801d7bfef646533ff704bdf972e21556fedcb5cfb254142d4123588fd6d5ccbb62aabbba577939e66188e5313b942760babf1cb2b3
+TAG: 11855563687233ba0019182fcea2e1dd7ad9dcf5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa37fb5ab4cd88dfc04f36f7c0f513e03bd383262bd615f34511750050fc407cf45b918eb869cc70636f8dd58c887e27949a9ddf60d00afd6aca73cfdd2d197d396e8e887a390e0fdb7602eee59b974db932b2c026c34fd3439e8674160ae283dc2c912e230410d2b56bafa3f90db4a6a02512a3fbea3ac9b1040493feb981fd9d69e79756d0b69008923f93106136c64f8f83872538f5c5abd19907677d6ee0aa4cd1716a20ced6eccc8d21e1549a89be806d5fceb39b5a870707109677e1cb0fb701c6bb8b
+TAG: 9052fee68cfb46aacca8a29c776b554032d347dc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a7211c40817f7caef15641379958d61692e359706965f40965da5a59d31c5dafc30b8c425bd0696b6cdecb6a52f88df56b3d76428c489cdd4a9788dde394bcc9b848a750768bd76b4ebd935f5158da85ab62e8f20b4d83a1111f7240fc825ea4f6d5929b6db7c6002a4a98366bdb1d80f35a1d265d740e71896a5cad98d893831b078aaed80ca3363cd1e9490f5b0785bfa9c765585e0caff875b14264da3344a4e788c97b40f775e0f431b9d17f73419fad1ddca14163e12d68e6ea853
+TAG: 8fde1d84000cd10689db14e7d9942b9cf57035c4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a72b769fedd6e8a09b70d37418d3284521e46fb6f12a98f660b8bef17bd4c31fae53c9d3db310b9bddb8d66bf3bf2da2808e1491c5d822a09f5160296db2725e5f5305c15415746a89230e0708b50c360c5831c018d65a35daed69a5f4cd2647cd3f37806fe365be742ff6769b91e6d3274ad9f24b3a27668fa434397f164709bd08e53878b4d0021c953c92d1fd4cbcd94b2102fe6ebadf37fdd2ac854e8e38e7b7fb30cffc53e46dba4c4c2a2eb52dcc8f64cecc48d03454048d0f609
+TAG: 9f350a66ec0d6edb91230e06ba80cdd33ba1931d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a7204d3172870e0f763c223783586c033c8d650413887e1028ee9746ecc711c56bea218347480c048e0f7c76c9ca24a1793bda3f4d7bba1b50319fb8231e40259117acd68a13a4c8d29b0929af579c29bf10cd8f90493a4fa1b9c70d93b2d1f26e8a3eb460f4386a87518457e6cc14fd7419484b4246488dfe97b0dfedbc18e1d1bd0a5be6e4634028b37efb08462a9ad716eddba8e53def96d6240c9514af34edd35ae731671f5ed5e5d4cd99a1cf70737e5c1d58abd6d2eae339086f1
+TAG: 5745555c182090c7a07d01f0a05963a2e799c069
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a724c9bfc24ec7cb7cdd819c9239afc49414e91a62d9c0a81d4a64500b37484c87a12224532472056fa053ddaf12ebe4d2f94ec915125a2fe13a96adf4590a530361058d61025d9d76d63978ca3b1da2c90c20cd1ba4f23bf052d19afb074bf69965d19533dc55061eeac10fa1c58c131230535cca5bfec2605a000168dd913d06828428ddff1b152cdd3e8831988d407e989edd708b2b4a64bd1634e72b7e8300b8a1824b869b2579b65a78fad5f0da376f95ffec2a6072cf83c6254fa
+TAG: e56dba6cf3105cdf231d1ac45baebe4dc4838382
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a72bf7bc3fa52a5973b4ff104555a469033698076e50f3cb7c963989779c5ef11201476f101df4c9296cb1245322391e3e16cb63dfc9edd300f203a85aa7c6eb18c471fdfff897903b82231634737780ec7e0f86c6fc81600682ab88537a6cd569794db84b9a8ad7e5b17c042f14860635c2d9052735834ab9a4daa00060629ba1768078db350d1334692d046d7760408e051e40b78adf6a138db3e8f425b3e29011bc66c1a7b9657ddba20edc03d92339ece75ba90b018784e188cac36
+TAG: f25ca6fd782639b52862812445e825fc33571062
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725423f1d2583cfdfc30b7ad9be0bbe5b224131f9fc0b7d8b6164aa7e9a551e30cb7ba88ebe430f1890d09f5adb2110c300a4bab15ba82228e49f53272a4710a75aaac12b87873ac9de71f7330e60f860bea9c3c482f2542fcb1098dfc73fcba660dcce4bef6a24ee01ce1ddb4cf7d01c19256ded2d522d71f612f7c1a56fe287b2be4742ba6286bcc2171ec527e36991d5ac9cd890c80c2ff11d95b189685e675e7071af71daa90234b0f18c37ebfc93a59912e02a19cda9e2d4cb4b8
+TAG: 2249f2872dc4b1cc850917d4530393c19196e4a1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a7298e797694b9213d9130ad0bcfa073590d8ed313ea3eff439a813daf8eadc3b2c8a2b22d9ada036235f093155fbedb1537c1b75714fc9c9bd2fa47e3e53c43931c1ea5ceee9feb5f2bc09867797aa25da4496857df7d773bbce3c2e89ec2074be88b1b4affd39ce89f5976d131a087b9d0510ad71f2025d26066367156f9922cdda71dd56820a380e17e8676a1e57bd5860d23b2111a581194c9079d92d9c6e82a917cf0f440be115a7bfa52089b8837cffd8110a140c768add8bc082
+TAG: cd3cc4c5647165faba74dcce17bf17ae4b2747f1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a72b7bb632d872ba0d3c05c0371fbb29c7c87b1ed16146aa91743f0e00465c497baa4bc1598fba0518c5abcc81ce09c1a915a3cd48956975f20146479d0d51674cd81de8d82844d3dcc85828c0c9616b9139d506c28fa0b98af16a98c52d545174954ad7a099e31363f9804b5320ea120ee9a88ac476108c0259add9e50c2cf7732bbf2936588cfbebbd1dc8339c3afb6e10ed029ea749abb46f55bbb471f5ad7c229fea26d71ff30628ea56a45b14930847684204c6201859b7c5831ed
+TAG: 680cbdc5bb9d8bfab0bb52bae4d42e3178420740
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913e52851cb40127e51bf0467e69310a9ac8b9e2e380ec8c6e31c9eb2933db6c28571dc4c347a55909617ebb38450d5bf78b376b558bf7810a3688390899c48f8f80da6dc05901ba9ddd8515c9c9bb4e01f4ec003a2a9c3a08059f9019e26c4c9b969eb3492022bbca7d654b14e0daec72acd50debcbbb24f6b3d74c0ba05596fee737bde5a5bb8c61b43b2ef7fb125ca61e5921077d1f0c420c2bdbfb9b7a248274cf9ef89384cf9bb3808efe7843f0d8c9f3ff16e3
+TAG: 06e08a54dab05f9d15f301624eb149e0e63ceda6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913e438923afe9c42c10062a80920d1cfd44b278bbb0f416a6667e9c5a11c5fc6e074ab7feb896a2c9570cbf44982d2806d024d188006ac01b20a1ad5f08436de62366544a85421e8467fcb3daa07fc8bb3217c32ab5e9e1bd89c42500ad0414e5c6ccfa142edbb463448c8b5dde7f4986f930f1ab99c505d72f4a8427ab5758b0e2be38fbee29394893b7e7331235e702dea1b8295f35ec77129aa90ac630b61cd6a05ad84b0215502ce9dfa51c81e1bafb26f40b27
+TAG: 1fde2f047a09c3502c1cfb0037e60bb5409c6136
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913ea08fc603b133684831596f5ec7ccdee91e0926dae5c8c8c8c433c5b0381499c83fdaa716d70f31414fb54bc292907f8543d8a96baff4ddb2eadfa8240ac0cef02bd1f40cc0385d5d446484ea7a6d7e4bdb08e9190237e9be59318d32a02df2b75a980519ee35f109dc8c83e92511a7d71e84a361d3aa56168b3ab8c7660b97657853e42b0c03fa11ec1b153fae3a49e6bea8b73c2b98c5fd0f7fb0e58c9d37524f36ab440c987760a13afd2750f7cbb92ee1eefa
+TAG: 9e0f2e8ab120e41bda1619e9c5baa4ded6c77225
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913e4e5ddebda8ce0a8659a7f1eb31a02efe9fc39d217ad5f8ee1fd9a6e39cbdb806ebf4bf4eebb89fe682ebe4b5a425dc7b62a386a8ab4f2b4d3522d74c0d7f3dc2d1645b62289595f72af5bdd7381281fdbbd52184d57307632be8fd4c6c5569f1c012be075a53a17fa6a3500ccdc282fae036d3d90dc7912397c15fbfc55cbb83d338d48419b743a5b574378d863f3c0841f22bf101717e79394dbc4d3accfa8d949d2bd9445e40e0fc31e0db3c1b37898ccc9478
+TAG: b1e77bb7468f121a8f767278d302d179b5db02b3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913e4345e4450919855da468fe34933b0ca668f921378eb1b17ec3adfc487566db41ddc2d7de71c29078f162d3b6a1104bf9f3ed443653d96bb9c28af80b9da1ba9f056b92b2e336db6f4e05febc53ac4440e8483e40ee236d63a7fa0d4f09358a19f65c862c25b67ed0e4d646f7c1cf371778d82521a18b0d996695de9ec26b73302ca148ef626be919aea487e38109a47072cc10583564cbf3873f0321ed97d28f055a119daa83676bc287c6bf17b961e26df9508c
+TAG: 7fab4a7d9c050ac44a4918e22d069dbe6016e3c4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913e4a1c448012977826667b2a5b4497c5b0548ac15b4cca6804b5f400d58112af6f086e8a94dbf7eb8f6dc85ce2cc9933989de4887d13191ec7c4e28deedc37ab83950fcf76961c9b4c322b458565355bbe24579f5027927935cfefc9489ad26ae7e325f0e9680e66dbdff6e225bcb0d14833e02bd9ec23075f0bd2050f1e4eae171d59c3c08e330aa385d17ca4ee6ddea285d9bf35b0fed792b83c2a7508f1c0118f5cf1d84528f14806f80da36b3180a3a0fcbef7
+TAG: 9fd8860e193f06c470f135267dfbb3bd608a6dda
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913e9e109e220602aed717a3204339140524664ac4b24553772aae83cb0e3101f11b62397190bf4d7c145bb9142b1df96e4b983afdc0ca67266f8b203107851a02059e5e628bfe4778ba25505414f71d948a5d42388772b389388719bbb977232d463398d0a7b1bad8e0fbcb00101c97f158ce5091092440214248657c4aa933d591264f8058b5fa78c5bea642bcb2d90c20c36cc105c3d8cc3e5821e020b5afb7ab76821b044015f9856cc5f53e2973eacce9004575
+TAG: 4dfa451869851d157b3b3fe72e85a1cc5af01569
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913eb85cd0b8d2f2334af6a963c5f6fb6fe9699ca1da134f96971e29fab466c72acb7d75a019e1c40a6de3ac017fffd0f2ff74e8f52a4d62005c18b856994bbed05259e5ff5c3e4b058f38374903635ff6ea2b249edc99b58fa27c3b34ac337e0f80d62a97dcad50d14701ffc47ea25afff8e9479e174ff14bdb29c141e80cd9b88ec0e0c76a4002e902a084ad8a7791ac82d6d8d8e9598f3d7a8e0368f20e269799d46e165e8dd3992b1bc475485f2d06b21a9c2c6f
+TAG: 8e33b9cce62caf869be856b319cc537ce3692132
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c445856aa0831c9ff000cddad47c9a523ba5c55fd576d720428f81f042f1fc1fb261ee32fe9fa9fbd9d0e99f820ffa7e23d8c57ce360373c84c9262a9764b0053f90bfeaedac7db2c4d722f6b32aa789b2439c3b9099e6878171c7f4467f06ad2c8bfaf226df35c9fb7ac14f398488fc09e89065efd8af9a24f55cf0325381abdeb21ad80983cc52b335226f7ea3fc64e5ee67eb9ad95acced76c06b474a4e1977b290076c8d87e8d29d2c77569853
+TAG: b09d112a675a00032cce740dc3637dc09a8be2ee
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585620b8313e25f19a41d65b755184d4fdcdfeb6b00abe397d2de33a227ca04fa224160f0662758d2d1df1675f5007346861e117c55ee238171ec13661bbf773a72afd6ff591af5f676688ec54d2944630b3045fc5fed12ac61ce047549a08350f0e65b6425f9ffd77e56eed3a790ab176e31acaaac010f5aa3135eda9afe84e85246b4a855524e898fc3e7274efd006315e5efdde0a30e1f5fb79c2917d247cfa09bd1ace2ca5cb559d5373a28
+TAG: 59593f8aa8d8a92d10202ee1547366e2e1985089
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c445857e9adb562360c4328eb4234d420b33ea681db5af2f1c88f4c2fd5481d6257385ba2e70258f426db5710cbbb9aac13861048247606a9e321c3a8109197742b948db4d6b1a19fe1116fea89c1ef3d9e2635df46b895a3fdce78a7e8ca0d6154d735fc80c34a8fc65f83760502756ec09beff9a46f9092ce9f8be3a8beae07a4c95df84411a848ca45ecacee3f711c675f7b48f753d89168bc8843df3464d2bbf9e55c00ddae2533dd0245907ff
+TAG: 25609a2bd60548105a630be08f9926ea768f874b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c445850aed856bd18a7cfb582eb6ea865624c16b3c0ad9a1755211ee9d02e93f43c4bb0a6ea3db5ce6a9344bcd96c62800a2f3478c3524d140960c9a7ffdd8fd80c09594b3c9c4c2bf001a690097b1c0bd7f2f45730981de3ed074525f407265e32d3d012ec2950178decbc86f86bc6f905e5dfb86d59e481bd05a33e003ade74c231cce03b5b13854177a97bdc6e45578ac78a964661e3bbf5d952c5e69f23c10fd627cc93406d1ef3cd52e1cfddc
+TAG: f93a0157ddf0a5cb900039042094f8fdd4f29c51
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585a41ea1528cc5c1c4e88f74582c26bdb770348680d3ac3b7c07be1ccd7ce8d3c15637a9d4c5268b5287e72406194d7e36a1d62c5495cdd008e795db0ec9958ca416f947e9264c02a46f9f84a588ff2aeeb1b7f222e3f2505f00b61aaf60aa0f64a13574abdb7537b23f52978d49a61b0ed993b9d6964d0bb3350e0c7283b5725dd3c30a9f9831d9cf79a6746a1d73a5e73cc90c5486979ddb8760899e30660961cc2993909a704f8ad8cf2c51
+TAG: 25a2507fff7e365d9a3664888ddd3a284ed2a5bd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c4458551aa5c4cbf9f441451c32e98fa84b217d048bb36f60c21d26c82f4db37c9e606e10214fe5be6409f0de3d577c1dae8512ded253eb3fcfe472b614751e97cdcdc005fbf2924a26f96a3d6a89cb4e6881f101a80e0aad9bbfb24f810781c4e1cd3fd4a0c7848b95cd55c1660a4a3355b324b4399199b69c953cc54bef6a9b4814e5c890d38dbf675aad258cd9c1922415d2effe5bfaf2f14f2d69bdd372da3c37a80f71c0232c695f945ffb6f1
+TAG: c1ac085d7a60e5989f0f30798f50ca365b599357
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585b34e4a9a9c764a48528590338e0ab297c9dd42f6e2286f828d6784dc240af4f421ed8d8164c50cfc07a5343301a3add36e901b46f2fec18bd82e1af2db7982cbe9bb5bf00483a70483316fff2f754b28a00948871e979319ba7e4637ee4ea7e571835141e5153eb0062a77ba5562b238e3ce27971dcc11fe6189a7d10dbd77e6cbb61344c7ed1076e6b3653d0fd42d3c47008f0b69e41e15bfece8c49e085a8c003113194887afd3e2e20689
+TAG: 95af682caaaac9ef1b7c3b0f57f7dd79d9d311c3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c445859d8a18f105a9e0d9f7d8e00f300de60945c2ee6eb66e43f9b7864130d3f47594ccf987c2449528369184cf27ab156897040eaddf82a8b6e9a8865fea98a30dbd5c71f311d0b9fa8987bef00c0b3f80025fa98efa91bf5ba1e7e0bf6deb23561fdec2ee9ae541f9e664d9901608f732315000bb51cfa33837c040fe8fc45b3380eecc239628bf94cdad7832c106520de324ff9cd716f0f243aeb384b07b5ad2725b4d8018d53eb56fd9e6a762
+TAG: a2ab4c0b3b3354a064a6ffbb167be1ce4187352d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938cec00f0c79744146dc9fa2e82cd7b8566c61d8fc8f8c62f7aca8239864d841fd3f51b138cd605e0b20d75700c30fe4e14ea961b008914a11abd2e2739bf3106cd87996854241f6a93f3a434337f4892e7f756fca2451a6452ba169ddf38966007fff4366bcd5036ec5c7e7ac4da4a1823d1b8b7571a24471497cab74b5dc0c9e4fb992cd802981069fd047225862d5c2a5a0e0813b7e76a08658308b9ff757b5562602570
+TAG: 8486b0db021a6cff1dd1feeca9e13fb1827d143e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c116bd95e6c6a0fad2a617dce8492c02185724358402ee95d1c4cdb6d10da123fc8aeb016b5cdebc3862b0cb552b6032bf4e2565ce1f7ddc0c33badfc2d06b10d28614815d58bd9bd42c9111d53f6343548ccecd26971253a9bbff0cb52f7c0c85eb874399ab94eaf9f7084e7f01ba6ab97692a599a8d0259118c1ca085b3d354142d73a6185608fb090de794f5aaeaf382cce6ae8713cccd60b98ed036d8fdf3cf9c392a
+TAG: 650e268324d3c308627cd4a7c4a38169f0916998
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938cb65f2d35b5d110dc24695334000cc502bb5dc917b5b234234d58bb7404d29bb8cf6c7d2b45f27a235ad5560f77b6bdb2affe811e2291185a791a77e58573d076c37339a37eb1c2768c7af0a57d4ebe69923b6e982094550cc0e801bbcac98826fe5a89242ad42051c6b0a2c2651931248ab53f25462ec38389fc6ac5c46c0733c951b35b516534bc0256d77a9ca2d213022cb4c92777c329a3edb2542bd24e10b70510df
+TAG: 938e492e8fedef77b29fd799abef5f2dc38dee37
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c7c99f1cc12d420c47039873a70c6e54c6f012203129b970f64b7d67ecf08a155c3e1e23dce09ba83dfc4bdf3f13b66d9bc14abff333e3b35c0c2d08abd9156d7dc859a62dcea66545c8eeac550316992801fd7852a74c70f8799fc70af1a1089ace6c01c23ae7fa4cc814aee476c99ac307c4adf621f7bd9e5bde8f37fc89720ad95906c55c316d1f284fbf07d0b234b3b25d12d10fa81396d8f30888186fb2176bbb0e1
+TAG: fad9280402facc83889a904494d5ea8a8286c3d4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c93098fbf3be05648ef396bd06d6232ff4150a56b4a93115d5e03dc997e17d5049101e40b19ebe5a819d38914d1e173c525afb32c36bfa3696ee1a6587cf4f3c19b655c2f2d64a60e78ad6064bc87de308f0d879687869643328f7f429ed639be9a27403c74bf17bafb4b0c70ca5d3b9d14a4a20472454c421e8536fc7f17d4fe0fbab0250e904eea29be9d112eedd21b5d5755482bcab42f3729ba34b91f38e081176b88
+TAG: 9b88765e2d27c9ec67a454db15b8c8f11e2108f0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c2873dd092c18756e597ae4a764af2d1ba40f203a24035672cd94cea893791e9ac36912cd02f37e1da1566efaf654ec6c991c9a0371ac5028716a68a8ea32b371a0c45a970cbe5f245f09137137da0b9a8281a5bbbbacdee2a0eacc6c330940a6c636bf1b02c1eb941de2f628b4ace968f3bce3841cba885e57c5da959337d225dbeb710cc4f5f85606cbf89ddc0e373d4181c0c466ff3bf4d0e9481f0e138e0d96ab49d0
+TAG: 47f8bd6c7edb70204b8d1e0ba89835310affd686
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c7aac050706246a992121aa81b1b94bb5cc6ebcb030639fc6f64b89aa5a41fa28927998d979bff42e2e852d46427eb3697d716ad5096633293018630bd5b5400f0ebc7d4baadd526762b9efa6cc5ab9b8df0e0357b6fef90a66ad5cd7758c24d54c8c9dcbd1c7095653246d05faf752883f9aa3841970a73771df37dc2c1a605bb0347950489aacf8a340b4a6772fd11ecc82207ed07cee297c182e4d4f91d47bf0b06db0
+TAG: 4b46106bdf6e6d98d5d357d0d5c774126094825e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c1478ef6593d7763bb969693473ca19b14a134dc018bf821c11146de5741f9fdcb26ff0c73fd8e45f48d4832e2b382d033e87cff39a49df406ef1d2788670e28b60c5c989572948a367e41fbe9c451032f63bc5573fb8117239e02b8f75b4253f2f2ffd95eaedbc1479e46462638742cb920e6a564b82dec1231aa0e5540e20763863f1dc6c7a4dabf3a3327d59dbb1d77d952265ee275d6b5151bde2d78ed3fe20636f11
+TAG: f29ee37d0d1373d2708218fefc1384c648981594
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b47a32facddcd5eb3ede0103990bf2376a0ce506da4c12bba71de072334f9ea50f68e7eed59af75be91e8e02232086168e63b730a41ac4dd1358f5426d5d4067a0d57c1c50378e29fb50ed3f5b879b1aa5e704ec24bae9fe2b77011e2751cb370b9240cf1001392f02653be8448a3dcf33bd24524b356c77faf9a939050f55850d8c0c22aba256fc81a4524e65b1f82f42e0889a283356396bfe7b9141d
+TAG: 0a4da13b5ea31025cd355f8401d1c0c5386a2fc9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b47cd2ec5ef5132787e70c07e4308b839dae6bed6e4471a8e861d4bc1027dfbfd14142029c1cc2676febb804de4ca1dd2fd0bbf18da6d2abf811310270e3c989fbaa8775076a1b9f15a868963002c880884e25a7e745731efa2c9849d64db27668da53b02925b17b8ab4f202ffbb1b8f422da496af64e7d5518e2f05a2f0821007ed71de02e737f5effdc6bedeb5ca7bce863c869fd34f8f67923251f09
+TAG: d4cb7d00f45cae4354e9df558d80b22c00ed4b65
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b47d0bd9aded5e2d2d108457630a82eb5637227fa03b9e1351c1c437cd9aaf7e4d9d51f553144cb81099fcbd8187e4d437f5af794bff788d4b6af6375b63114bf36855cc33536bfde7b7f5b4a38817aa47031b294e5191dbbf126ba935a4a93904e177ec9b0193852c48f9dc122be4ffb0b1872609ebfcf9384f9ca9c1be36e2a17587b7b54fe3a6312d343d4e328c177609f6894e85c94f9a801c07bc6
+TAG: 821a86fd3d7eae805c113061527f3afc1d7ea019
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b4750977b9de6b9d16baddf1e161494802084393154114b3b8a32564a74b5aff9454ad4057c9af63eb4c3ccaeb87a9f7d986271f72f0c997040b6d294d193686aeface1ebefe26e3de4dfc85d7848bf59e58c1831fc1aa65b0fec7a2a6884a29fdb72089d3f366264f5e76d85b147d265ac2ebf4ba7751b270130ff077202008076b2af95f666cff3b1b482210a7b20d0f7a600ed32546060b614ec9ff1
+TAG: cc7cafbebdf199062055dd663d8cd7f61854aec6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b477538244c849eab7c2eceddf6ad019d01ffebfd70d23959317f608846e9508e052f12803d45f68e6dd781d190452f6e848d446f1052925ac80fa286f17811c1b9ae43a37c884a37ce6994ad0ae6485a2417fb3306184d2e525153e28851a14065a9376b7523c9560af9461058bb05ce41c6117d7bb0b6683913a9dd32f282ca7bedcf4e5eceedec1b78519a8e5135c7bb48e2a26021af8812d75cf82c
+TAG: 992b7451516ac213736b511e38b21776a7f11df0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b478466c0fa8050b432a693249eb60f8ec76129c6a3c58ede2aac7ebbc481d2414a6824acc4bc72e4bc243bf349e3730a22eafef0db89efa61115e7877ea8144dda902f339181f79ddea116ef959707838e2def59ffdccf0f8343b35df2ffe5972be18ecb1853e999b8b66d56d36763511ad12775249811a88ea31748b06ee38e58f1f2d43fcc4a0e89ee3b76b70b33b0277d6ba168dfe1d17dac8f0716
+TAG: a4531764731e3ca38f60f7bb890d43ab2db222ca
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b47bd50e9ed12008dae9612f49baa7d69e51a5045cd86d1fab39771b3e70815ec1b8ff983ef23e44215de3f5051a25460c095cb317f76e3e99ba4a0c6c8dac4b3b4f85a21460f78eb1f2fc2c75f54ea75d9e34fb4c0d477a294c85276abc46d1901993f0ea73480a1fc7dfd4ab46749591bcffcd6ff7acc728f0561ccfbc0166828db8a902f883f73a58520656baa628a3d899e868056c62a41e7c1c635
+TAG: a2ea6dff0de76b56289f04697fdd9fc2b185c422
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479a7548bb3fe247902edb9fb7133ade4c81ae41dfbe2ffc7f926f1b1c58c80114c015fbc933043df5f44ad8d188394370f22cc5a768aaabe6ae6ce6c5b7cc936db681bf2064658bc94827907ef9fcf4098ab4e7a7a0ba8be6fc057a944ea0aa979a0fc81c7476d117f5a46f0776e78780ef1bde734a31fa075f12677bfccd59c72fd8af8003ed7317922dfc7ce9d4420911237ee81f9c72cee9e16d7b
+TAG: d1e01f0e46b82ba8eb1c0664f236e7006cbbc2ea
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec74032012cab68cdd2eec2e7d0e308772b3bc089be8fbe713ccd086ccef3c6fcefca092a9a7dc0edaf55f99c055dc178d26bb82d26c99359f125215a7262a5703aed5dcd7a295ba0a7529941238f392a244551c9605841f23a1bb0a2c74aadff627c8dab516256e8568ff9d27b742f72b680c2980e89a3a7ba41591b37c016338b9f5acf58f6f872272ac8f867de5b1ae965e241a1
+TAG: f3f610ca427724564a215f8fb26bdda1fae0ef55
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec75f0fd6e69b4e65c7cac14e76bd9a1cdbd4a84cb04284ec565f36e465bc86025fa153de8c3d0367d623b1008307c2c359826f2824bd68777b4151829d29447cfd43cfaabf1037a82800d91dfb21410578fdd8a56e63926dfb60d646fd1d0fb3cf058442d193051f9d38b9a04b48c3deb390133e480cdde22cfbcb83ff6cb4f896fd273298a51c5c3372c27bb4ed2602c5d7ad521d
+TAG: c797726521e6dd84b49cb951864d9fa7f6bde1be
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec7be79a65af53eeba897f06643c3268841fed4624688e03a99d9413a43934f2ac10acccf7720dd8c7ace7ca5a8cdc77e6ce83a9235a136ad15543f036724c3d11ad9455ae6d0478815152be54282366240632846591f9490ae2e44ba4f3dc2cfeda6c1d10305927aa0e8122dd32b896842991f5c744687124e4a4a8f7427365769d7ff135b3d6f4c75ba54e421a3e8945b5967f1a1
+TAG: e531f26f3b192af0cfd23d0543403a9ac2871812
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec7c6212bc5c23d47170716a3b8fbb931bd7784b499f337afcfb3d5f8005cc1b26df6b6146545b60306734e825aaf29511cf843b58b8e9ef9926920c7d7908ae15dc864a1a6e08f6afda5a70a4a278574d521063a8d567558768fbb56c2b1ce2d00b6a3d98bd25412cf1b81791ff8ee0df4da8f59baf39b430131cf8de6decda76d9ec7bd9639d0670d1bc444829a042554e4bfa51e
+TAG: 56aa021a408928c4850cd37023feae3543d907aa
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec7f683557c207199bd75dab3e016ce73268f2e8b6405d6dc5f36c5fe407ed758ff20e3f87669ae6fcca6346fbd8aeea60f473f2930da4694c13edb8920512d0604398c0f53bea8a91da664a4f55ab2b28cd371d28872cb17987b58462e4584fc3022d66c12a8ffe2dbd0d2899f7027f4e84c419bf9eb661e129da4be93c841eae97fd8dff4145381c77bf2ecd88a462c6131642b45
+TAG: c2a4cd004b3d60e83c0ae15ae6605f382e3c2998
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec70093fa6ccb694f6337047beebdc26fd8ec49cb75022f03210e2d8d6eb2dcb66c3dd7ac2ea41d56aacf8e5a283b98bf7311861cf70c2e8113ea4e0010de1d12392bf889d9444e99054de6b21687472fb8dbb5fd7a384620ca7e0f24bb32e6398afda267ae70c4dcb1358f9379232aa635bd6a83e0e7689a22d3174f7fb634fcbbbc88cf8c6d242da905603634d9b251c969ad55b3
+TAG: 019f16fca4b435c0b9a623f90e6f4fd90a37c561
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec7fd9d84e73d11480cc29ccc4446dfa81276276f9f4cc35fcc8137d65590feab0fc5a990ec69969b6ed7ecaf3af2c4ac2f9e500da16aad00eae79e4dbecb174b8ec2906119c5069f5308d57c9b20a0e892c088880e25ba5059eb37957735b68e8485f1bc6c1b4dac3363648287ccab50fe33b70c2c9fdc55550106811738c93a761e4af9e983c63ef449a0562effad7ee28179a8f4
+TAG: 367acd479089f059c7ea29a20d208d5d39e3745d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec79fafaf6db9952f7ebd3e59d441f2a5a55acf4d90140f7f1fc2ebff3b7b4238033c5a35f1dddc16b611c2edafe9929df6161881e7790ea222aa487a60ddee389b946c3df65ce00f5305357048340743a2854fa4b78cf60c06d69de2e202ae3bdcaae3239b1b3922c889220ed70ee5fd9048a8d1540039575fec6fdaf69638e43b174ac393e322c20db062fd9cc7b55c88fc60c7fa
+TAG: 491d3adde3c372c9d3803396f397ae4ba06c80af
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180aecb83ea26a99ac11e393539261ebd0e38358023a16a8ada5fe1a488f81e884ba91ab59c0e0bcaf75dad35d6ea525b1155ca3235eaaefccf0028edd7d3361fdc57302886bfedc2455d7d737a3339640e1ea7cc0be93fbb17c28f945c7c5ba7d39df5b9087f3dfd82b206d2b8f9df9a3f8440b6a92cef205e8c9f546f6f978a95135c0aa886842e624d57d909d
+TAG: 43ec8b8fabe88e52607e3936132b7d86f72cb0b3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180a3b80cbaf5871bc0d189c5f84bb030c54b91361f1581418c65af37cbbd219726105928f52dbc490a23be453f3780b43104d32115cff1d9cb164eb61c7ce332eff4bf8da00a76b3a524d293039a7bd45492384baf3ff3bcec3291e93809c2a2059818b8041427fb6f738dcd1fdbc33dca23288dbc8662562b778f5007c6b0737370f78ff5dc83df59b3376fc9b
+TAG: dc71def387fdabdcd2e0dd67f37984ed8f5bd876
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180ae503d46bb0b05900806e4b7f37d94c2ce810de45ddd1d2318410342878e78a5a1f1f1020e70feec865ac901556291685982d5dce6ae1326c92126c6cab7907ed3cfc70ebb25796b4235448da5ed710021c35a22238706199b64ad40cb0b89a8c57cb57b506127a2dc2868235f91eedabc414b5f373901d7f78b7c2fe3b2911ca3346c864413b749ee23b5c9b
+TAG: d4e93178f1ad30bb91082429ea0712dc05568eba
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180a34d32cb6921c26ba9bc493216440f9f9a1c2d2c442a7be38a487933c52a7cb129917c9934a9ebc88892b6cbcdda13049823ce20c7167ea8795715928e8ffb1ad1ade8e0a91e39ad1eeac17604d65f873c1b630a3e3fdf28fda3f5328946aa73ee6615d6da0bc89eaef2d8d9235b2cf625d5257b5bd94b419418dfa702733fa3c229a727cd8f65473a30f5e63
+TAG: cdaa9bf52120f3d68422103a02c78d5674a87458
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180a34ce91c45c2297bbe6477d5cdf88c358017f59b966ac171527ddb394d975becef3128753b60c20d61e3711b26ac609b0f2e82379a4cef0470cf4035f367a729340d5d10106ad2ca7fb85988d28a0b073e9f1a1809a9ebec443b6872da8d664a11a5a760a89f9f178ba72f4484cfc9e632fbdce02b71126c5c1bd0e5f4b5dc0f27fb40d88ec256c29c8e4a88f
+TAG: b602262e02aa4be38ebb0472f1208cc9c2080cbd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180aa1af6a951b35d58732408bb4951921d599e5b847360d60e0e9bbbc5a1e35b9346c3e6248ec95bafdbdb114844cee049fcdee7b6a50bd4bf8c0d5d532fc88b98cf95eb26f739c40a8bde7c5e85eee7bfd355b0c61dce1edd5743ad2812c535e1fa870038026334727b5052b32bc8d5997494e3fc5da236babbe513980fe49318239cd79d3e2cf01d196a9a096
+TAG: 576544f705d75cf6fabc6d9707b5f52bcbe3a10e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180aa3b8107aadaf66f0b166ad34a15013b4047eb9ba7327ce2a7c66569add0955fdbf307c921347db107f0572e46c2e6f8ffe0ee8ad9cb02933d4cca7ab712aea08a0e8e094513062518e0b8bdd422f25c04656ee346ade3fe8c787272d71fcd85659d2f4e6adf2daa33fa202c5b20c3713d62e885ab349b6c501d004a1a31126ef1da5467dac94ed5ae6fe86aa
+TAG: 46ab364952f9a063131429dcf8161fb41a1e4780
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180a4f94a5948aac792f9caaef9d1f53e31294633e92c2bc54cd03ec0ae2406912254f1a7e9b1c936258be1c7e9a93f3bd6b88a5031c0906d608dbadb811c851d2e86b339c1f8aa0de57d986cf18a56137e464f27f898bb9ccb8a29b6ab8cb31a01e9550e1aa5d4636a3a92f2d2b4333be58e388814b79475c7ddb072192bae83f5157037c419b1177d6f62061e1
+TAG: e94ed4df10a8a2360428b67b56712a787f640466
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919017fd6ba2f539c0797f655ab74f994d9296050c004463095ea98387cf3685e19cef1bc05c30a6ab853b520b48dccfa88200197f0a27a3df91820c41cb1bfa623746ac350878d4c4089455dd596b1df7d5f4a837ec4ee625769fe1f89f9484938ff2b1e0183c18b0d02f1ef0bdc2dc992bad2dd6028b02aa93cf7c28f13629d1209e6e13691
+TAG: ba7e0853b2e6f9da5858998273fa4e3b5f2ab88c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c9190116259824214e5d7bfb8a3e03694a6a3dcea7355a9d19950dbc5b34d800285d03eacab504ccca6eeb3c1fcd71006c85afa69fa5db2f66da61cac6e749257008f42c8e24467da2a54bac69ff527f2b8c7d4d0bebc29c1e41289be330dc8166060c11cb94fa1511e6781efdb5efbc4889715a22a2b16890912411f88cfe6e3e1c4f8f974718
+TAG: a6dbac216c2996d1dc277a718f5fba34bd43454d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c91901434812cd93ac931e6428577403b174ad651c3c84b12fd3900026b1e79bcb15ca6aeaaa463c097d8e29823c4f91181c5f6a73452c88d08fe08533bc54e4b5daeb1e90e3f96afd7de70817296e3eac3fff056a2c622fd2a3dcb01d0c98c2bdd6471a12df0d45cf5f4edd88860e5a185b6509e85fa38ebbf28e0d0066123199bc50bb86511f
+TAG: aecf4e3e8e432c67852185831c9aa3acde797fb8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919019c6503f8ebf6a8befb074e7822ab9ca1ff13ba5eeec013cbbac22a3193ee3578d3647d6c1bce232a570d0bce0e9be4a2f1156d6ed35d657a596369e854feca0b2aa4eaff77f084771ab540bad073ed991790ee25ca6af630dc340108d0c503ed6175014253f12e223bd10b5fb923b0ea826cf6bbd5e24a23b7afa786e511e958d5fe3d74
+TAG: 577350808b22b0446fc3c4e9e2d4bf303addec02
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c91901542b83b074aa37a5ea88a36cc00a1b89f47225f19a7d9d23a4e993989c7f033a092fd1f519e3974a2bc6e3630f72e6262965de04d46498b715ec11b9b6e56c2fe03523c7cabe7397b4fe3cb1ca2198452a5276a3950c6719a6e67eed8a813a4e8bd93e70feafed6e63f61c8e2607aa8e8d791af7e7cda71cec6739b77c8e47f7f7fc3fa2
+TAG: 624ac2595384a115a8a1dbcdd0a97d1f2c4d9ef1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919018041ce28a84c721c8e834809fe95fc5b0cef6ddfd5d2f056b057cb96d322d1548c947a39a57994daeda2d2a3eae05bbf321c32970f369a8c69209778d71b6917d4cafcc3dff54dc640c834fa0641f193fad12c85fbacf6a34301e580893359624bc57555549911dcaa124b3ab57fc93e430e7e01ecca69184d5c4fda2bc8dd34db52e877
+TAG: c0a73e9253947c80b5d60aef728f046164939583
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c91901d1578c7d7dd120dd3b3be77d71e25a377a02dd95ab822ef307b020ea9585b2646e1a46d82c8d12672802246da16e16293e014d958692b310860d7998f4c6a1a48b8c10372e26dece36142c062ece0fddd7b0199c7bc72752f00d5dcaa8fe2300988639534a52ff6df26645a4133640fcbea4f979a67a83d1685ac2a8a3be8d27184fed08
+TAG: de44d0bb6fc5f1677051be4ee1607aed0addd426
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c91901d06104bdcbb391e3e84a19b0e5e5b0c547190e19e0ac5d092eabf3b3275530a89203b44e368f1f408eb14c1474cc3f09748196db4fd119b3f7fdb3f3486141739e0ca750071c10b4abd41c03e63a0a97639791c89aa0cae2f1ac4222ad5468e738ed364a75482973dd09046fd81dde9cc16869a763631963fb9fc6faf37228ceb4d944df
+TAG: fad7c315627e1b5c7bcd9146503fe1700733a986
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c40b963198cfff05dede3eab2d712abd9c228fe506902841df11ccf16d45036bf9848ef601d674f74775747a2d18850d88061edb208ae7a8d5478d8eb1d11950b1b83ec83cbd6598914d96aa8a7cdabdabddd281008cabcbcdd2281de53498877cfbca6d52ea3093c2b81348a9972654160855785c3f70129de83edf6
+TAG: 96fdf9cc14af813a1e4f93a1c3a3cb10428885a8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c450ac007372f3f9f867cbb17553dc05011126808e8aa48bc93661ea3deee29c532e502443668f20195a92e8df6462e2d04673f5e5228716e1fd407baa1b385c0c5bfcf41ccaf447d1621ff3cf2f3ea152579fac5293f53495f1960158e757788727b0d84b5bc8bcb8828f3656d553e590743b48a5ccf3a4b334c0e2f
+TAG: 8010c010417fd4d5d1445d532f534770eb2eaeab
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c4b7501b911ccf09c2c78a6209f6da6d98f2b7d76a47b91a0f11a248a02e6b65a3de0ec4c49d6ad3b3d4c75a5ac129222581de58760a74721533f2fc0f1bf176c149e7f715b626212cd70fe1e247c1b7d81175017a1398ac154f37cc35070468b22ddb8b36da8687c20f129218500d0ddd07b7398c4027d2f21d7efaa
+TAG: 526dffe70d4a7d1d122870bcf410a6258461046a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c46b9ecae3c502c643ff6b3b1c9a6780b3b9ff0b48815b0d33bbaf55219121028eb6c186a986088e0abd5f58a0691a75b7e1aeb554bab6c267b03383b9bc7fd48b84dfaede9dd85045bbbfbacc0922ff8ebe96895b49dbda424daf3e7d8425c5c34a806a49d772729ec5aba5c7740c401e72f2465e8104efdd9e655eb
+TAG: cbd2c7c18d83980c291abbc83008860971293adc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c01ac07f1c5de56a277774431960f60addae109efb4f83ca65e78b45efc815ee247af1ca7704e2118011bd7f65fd1351eb5bbcfee2bb2cace1c13edd6b11f48e8c7604912c54a81163b274b63eb837b0cb8ebb9ba663423910b357f876472dd54a57815be1359570e7cca915b00c5309a4adab12856a16e39ac6f27c1
+TAG: 2d0b56015faf101fd63ff321aa2531bed31de649
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c2fa89a9e4f3fdd8f3912c4b1c24bb99f23e07cc0fe9d52fdefbe12c23fb7e464af2308838a6a77cb745254ddddd1253ea15dc059099eace5b3ae7884e3a2e7a9179f568794d689a801a357cad5f1d7a2a91426e9496b93f18505f360541daeaa64b86ac4f34e11609fc9d782eb3caa2037f69a9e8643588999af6167
+TAG: 5c4d368a02d49e79db7aeaa3f783c98bde9bb3d4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05cde9c2bdf9c1669a0683b6b5aa68887b92765f253fa1774d965686edc9f4ec857a8a45db3ba7acac33655c281cc3cd5c24bc291839422a138704738d176f93f0c609bb3fc00246e2b92bc818a6340e6af4a2201d494a31874e906f1c9b3199ea05ebf64a1c995d077514d4065ca8dbba5443f6ed4c34254ca9ea0a42a
+TAG: 57b671a4f35ff9134d17d8575125fdc924a9becb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c086fd5b7d0bed1f170cde1628ba41b288209582f5d91457cbca58e23064e6028765e5506ddb5b26e5c3079f78fa642add10cc139e4b24963f20471073184f4458ae670e830220269fe8738745dda009cf79aa8e96fda39cc2f117b4e5536965d7e874f91ae5e89bcbf25b407fedf779c8ede47addf36352f5fdc0cf2
+TAG: 92c4e10800af961e944879aab7329c687b236e92
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb091e494da17f46b9a929c3a97c48ac4f156980aaf2530121d86efb61fb724a4429af24ec432e6158ace07fe61f55db793dc75332298bce91d22d5fca1c5c9a999374369d03ec4ae2deaf9f5e94eef2a99ae398a90f321485cbb9ff261d127c8dffbd321c5c6e01f3b0da6d29e33daecfd1a9bd9b94
+TAG: f02c5d7ca08ead8c2fc472d6df0ab3dc01055e6b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb0905e1d788fa672328848986a1e7770e27d6f7740c7fb91947b77b433d51d535d781dd0645aee2059f64ab4051e295a5673e5b73f4f412060b57e028088410f4797dfcc4dee4e24c2bd8a9a1a7669e3ef70715bdb661cf62a6c9493256bff1fa52fcb5cf4f8e337fe1e3b226a680bb9174968f72ca
+TAG: 8a5cdcc218d088fdaf27519f2c204fabb3813ad0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb094952d0d7aa11919dfbcb989a6e2a06c95d0bef90f70a99330aaec5b6aa4a572b4f45ddd0d3d64e966ae8c7431182bd3971b06439fb868cae31f9e768fa583b5413af1349d5342f1f987eb94f6bb48905d7350c93c6cc3659dd796dc8ceb2bdd05b3a171274a360051d87072f2983f39ecd949937
+TAG: 98745a29ee0f15bb9970c26d93101c9e44d7d0ab
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09cbec665e4393394486554915630d7a4e18d9117a2fae3398fe6dba552fb1e57e8228b5ed2c1606a9bacf1cbe65c70612ff5edd10b518a3b0bf5c0cb3c04b881af191b89998407214038203ef6d43cb5e03d7cd06fea8fc2ca219a16c60fb00f58af401c3e086315bce819994f085d7f9035175c9
+TAG: 19d8915331d86bc95dbad0df9399bc4c75996270
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09fad7cb3b8d2f471dbbabe2d8dcf36bc4c1970bd53f06a8fa3c15d908ecf28edc0e2bee081e9380262587f230baa1dd3ed1d5dfd36fbf776704f0c46231a1deaced2063561eae271f6b2ab25ae183d46a137d7a906dfcd808bad79869630ffcb100337db9a234bd47521c2a09f8627909d76355a3
+TAG: e40cc80e74a52c0c3ec7dc07ee1c326b31893b8b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09f71cd67140e636f18d7defa14f3bf5d593621bf6371f9f85dfde9d10bd283147e17cef183ebeb8fcca1e6ab3444a6e859759e984a8eaa1ca6c126335be6b3de6b1956760af19a09077e1ee0567b4e13d122575b3e3106729ca86b3a0c0e8c0d70d77b1ce6f75db3039046c1be02d271fd374d7fd
+TAG: eb04c7b2800086eeb31d7d1f2938a18479128d83
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09337ace4327c89faa59a0da9d3c0496d7a84f827edf2f53bcf15ef3e48c58027465a6b47770c4168eb44036b0f889a97d794d22e652c2013cb4f1c83a7df3a684acc8030c3539b96d82557412f4841ba8818b85a86a0b844d5302b0279a1e476eb65114cb6bc01208e7066a40188838a5a3b6576f
+TAG: a99ba70c03f4ab1722842c78e8060055760784d3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb090217ac4dbc1f4fe1edc603dba2a2a31bfe857ce0de2f56f88916337552f4f1f09b6df257bf855019d295c57d940f723df9b9f6cde4fe08fe0027c4734c7d5ed35a25026d9e4648382388de1477a893b5018172359abd836e6e09205aefd850a96ed7cf663a8625b47259e0a9c6f6c3b78d9aba10
+TAG: 393e329a728bd814e5568ab5a06ba90f04bd07d2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7c613dd38e9bb00d50876dd795f735e9be14613d681ea410725096cf777eaa57454508a0c29493d5456bcca7c011329249fb18d8574cdd5deb8bf528b7823731e8803145566200e93ec3730ddeb4e03cafbe989f18a65e514d34cad2646e0f08facd474b125807bececa2c7fb
+TAG: f00f13be9de4bd645cfb42bebd8d04ea3523c8a8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba716dcb0bcba1f7e62007248a0c61e236b01ff7551159e161f3228f5af331d291e8be1bb84d3e22ceff93cf257eeb59c0f0ac72a3d887cd42560d5a3cdf9cc56270963227ff0720db6450945bcff0eb0123ef4a4607516b66b38b30fdb2136814e56bdc034e472986f06bbb745
+TAG: 2fe7c697c48a841a976ddf8f28385574559e455b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba71c92c853700f414b2407cea1277f3dde8c4426020d1abde7c2f2678893aea16f4e85d66c7dcb5938cb65772cb7d7847c6c505ac229aaa04cde881cbcbb5aabab81ebc7227a0f934abbb4535e55144307b4485debc51702607e39be67f00fae1d55487705202419b12a1266eb
+TAG: 691dc7f35f7f5be24f6a371bd9f1010824d69cec
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba799b2348e998912a944b5bcd439f2ef67ef9368260a315a9c1a3a1bb41ce18a267fbc11a082cfa50768711a466f530a311a55f5612b9ef72c7e4fefc8f33596b9f0be5af82212a0a89810d7d06d83dbd13ca749be077ca4cf7440e6a4503d74012d926fa253323c9bb76797e8
+TAG: cd06f3559912700c848f2545ae4f85781c7cf4db
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7cd7cca124d1634defbeee882af29db098e4f3dcc84379b3654edc32289e1f2900ec54f0cc791392c9cf7e616ef7eb131a70aedb289165d8d0885955108004756fd25b4a43d568d6f074cab5e7d11b8afd67d0b92406c78c2d79fe2d8cc8d5ecaaa4367b1cbadecdd1227149d
+TAG: 7d67d2285708e34c8b798ddd3766b8830a3949fd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7082c6810cea5e7d0011011199160a648b8fc31c32da22eafcbb64f393a3d3d1e83b61f9436044572e09ba71d025e0e12bfb30b94a99e292ecc0a3e2157990bed2df91fc4d58a3b754b2a52e117735411d75d9ba83aff6a13a17fbab045cdff5dfd8c8602ecffd3fc59cec37d
+TAG: 4b25d74862eb3fe8a14b2570e8c0a87b2bf6fee6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba73bbbdb554b76a06ab01f3aa3812f01d89054acfd9d0bc249db78ac4fe8123f25348a678faaf626bb809354f0124ada14524df867010477f736e57233a795fc451e7fbceb0698ec56142c1c27a988cc785b29ce6db1c1de42c6ebb54361d55fc9e1343e891c3827b8a6ba1c20
+TAG: 1931759f02e16bf60a535cb2b505ebb955d2337c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7193b4589d7ac90435541e38a45fca7050b2d26700c4fa1cfdae074206de69b07c8f458e2fe93bdb3e277733eecc02c0d21c49c5be85e243a612cb55bee28db278a75e7e09b44f26130e3e01155c083aaaef279049800a9c36e9ab173dc69c4a6cd009d2b954cf76f937fc413
+TAG: 2fb8e30ff69bb07b831c967aaa19c6b237fc112b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d10757bef73a44c50743e368f71cbe97e91dda2ba020d6e51e9716bced7620b90de4fab77e64cf205eeaea46ceee168bd40b93c9f316b0be7c8aa693e98230d213cec2aada721c5079022980cfd28beebc35633d6e5778340ce8aacc5dbf4e77fd02c96f8c1688
+TAG: 21314968262352e1da60c356b63eb2f01a37632a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d10757f08e61fe8c56ba7d30b8fc6a7b15865cdc13c8c1f4831e8fd44cd74db4b4a04148904a8802704de56028b98a538cae48d03caabd3f8c9adae64279ad111c1a95620fe91789ce721aafa826c95d51be0d1b558037ee501f6f64d8f85b92bf936e260189f1
+TAG: 209d76f7920b9285d3c5a9bd67b400bc4c17c746
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d1075773138c9881e70e29f8e502e94ac9afe96e6fb5f8458e6f95bea7279ceea5c1fb548d04e81fb35b1405a04eb1fc84747d4dd85379c0f2691f1324ba2c6af90bd3a463a61128609674129fc4654beb9bcace940952d28597ecfc4c45d74596308c28b35077
+TAG: 2a2cdb1f79b0d7720ded3cb4506f86296b25267a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107570d2a513b25eb50300b4e15004e2f971df8f72aadf33a3b4fb695074ef585e6be8022d412467fcf066c404c0cbe3a9f5d552489721a8e3795e07fd66311d6e577e502defaca8481f65a25d5a4a2a318b93e03953fb35c93544af49f01586f4eeda20ca6aa
+TAG: 53814995f38cfed082023ef3454ca7d4a86f2039
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d10757a03e129aa98bdd6b16dd99c2ea673c56816d0e6a9b7ceb168c11a63ca53af7e0a36a08854098e6ef5ad72ba1f3550824e3787ca61c45b21d145a2f7aa9c72e11cfb0029b601e332e5aa656b901c953aff4e80c414ead808479d58733333680dd25506cc9
+TAG: 19004a1ae8b63e53003321434a271c35707fa9d6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d10757b486a4096a852f6960de114b95ac4db2dbd23ee5337374c9899c20c42abcbec838f76fe0338a310bf8384e5ceaa25b832a5ee018e443efb764ae41822bb5119859e735fc106ccc50eaa00958b4f0e3b6eb42ff4572f51c54b0d644fb1469ce1b48e14cba
+TAG: 50a5ce6b93a4b53c589f0cf2da03824cfb20c32b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107576c714493e6ba8c6a62f254b61191fdc2a82a8490e7f398590da7ccc6ddca87ddbb43291e28c0371d46b2960beca73b58a7523a6230fa19152ac0f241ba7b7a75918aae47ae87285302722c7e03e9c1263a9f1914196d83583ddedcf13d98c62de08aee7d
+TAG: a99951c3efc5be40196e9ddd22a3bed1ed1b877b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571af0a8b013e58c3de56a55a7d78b87c84650d2a6bf044bac9b90b25fdb4537c8e59f294b5a0dbced8258488c6c42532ed6d379d7dbb44740965e339b0f529e082bbed9b67e0d4b8b84818f80e0fc6ef10738ed2f6adbd26a92bf7454231a84f4047bc681
+TAG: 6a9fe912d8d27e98dba19dd16cbc62c1cdd46228
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009184639b1b381311bf9b1d0a08f68f41dece83232ea3bd1c6342b66fd8730f4ef1fd57161a82db74adaddb616d40f2a0daa59717aa2a74a8c017205750dc8a36c75d0d26fd7c846174abeac8c347dfaa73d54d52abe64ef0d928f72cca6
+TAG: 87ed543b2435940c0d400522e7acb2d8015d62a3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009183f0797304eadc54cfd3289ee9f9337dd1960e51c2970e10643da5b78c374779bf3a2efae15a7af97acec031b2f6951f91a3c4a64bc8560679a8968553372da498fd314b6cc7ba271a5d5c8b252d11fe9ba0156a37b7d93e8969651e1
+TAG: 1fa075da585a1c234027e514170caf1e4daafae5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb300918d4f261c1a3b27752678d844ab3347ec583677b7b56b811b74a34522964456b9663f78b3cde325ba6f6fcfa18b1c6019a93842e2969eba6ee20d9eed73d34001c06aed013e0d2ffea484c2154dd4b7a25332168143124c9b91e04bc24
+TAG: 620a1d103c3e418bfc83bf33e2828795a376d2f7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009184f41a010e281f758717545cca65f1d427de5c4a70097b6eccd59ea09a8063b1c2b354b8a61c18027c7d4ac3f19c37a554dc4823b5df2391e38712d1581f45ca6710f9268c6076a13d209664f3d6e195c613c365a8d4e3f4e02ed8c09
+TAG: ba38ba6938054ad20a3734191e1386b58ef09a6a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb300918366cd4fdb2813a474ca05a3a5f97eb38083fae761e023844640168736020be7a914a746e9c7512b45db4b9a16d65c9245ca30bb15baadfcc11c757ec4fabf30aea02dbbbd163f9158c39db02299404cf96726f8e7bab943508a2bbcb
+TAG: 37dcc207e86934638fbcdb9fd025d21d1aecb9bd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb30091819f62baed0cbaa863ad95fb4b6c98bef1e2b158add1de6f454a54544df1bc19c26896e7e5c7d1e2090cb8f0f9bc70f287cc09a2a3f2717d31d59d1e5a2a093d5cbef2bc402b5803525127de33b3ed4671627ea8a1e2852b0dd798bed
+TAG: a32a01cfe306aaad1a9a18d584c36dce041876f9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb300918629fd0c6f134f9648b4dfe01f037721fe1727d3027ddd8e93e5b68417eb8a14bdd5547c0c9c3151e27c2ed64c1340cd2374a1a26f67d356d6864ce493cfb7b42eccbc8f75620e13b896a2297a830b020fc3e5fd5b6f7547a6b07dc0f
+TAG: 54b7953c93516b73ada8d228a7af00fef50f26cc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009184a0589c81a17601ebc3d6468327739ce9d49d93d1f11eec96afe06453c60de507e0003da14f5d88bf8dfb7437aa0fcb6eb520ab9a1d0e2060f58a986a7a9c7e5f4db58c49a0b59db85fed76f3478b8662ab7810c5e6301eb07651c23
+TAG: 148f87d7ee56a5405cfe4dcc087701760c07149a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c611c9cd0620811aa4850906b9eb3393ec77a1c08cdfa18d286f7291a3ad8a74294ddf6d0b0b76189dd217644d632525d6fcdb5836143a14516e93dbe399c5d00b36221f543cd66304f94404ec51871d1c0b5bf4dc13
+TAG: 53f2390e488968f141945ca43c767e75905a13a0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c611a9febec72a6403f99fa660c741901525891bc7d12fb7e46b28d15e912f31b2c4f79c6b0b92c009eab2d50a6b5dfc48b723268b658642160a6aab79d6ff2242a6566eeecf853be0a64f1f3c25f366db6ff145d114
+TAG: 3ded125f5dc543a21bca99c370496701829f2214
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c611d6066228493f5ba630c23c01a64bbfee319bc8040cf6bd6c6c2d5c9c132fb905c85c87942b7326589d3560cae31e65ba7abab709a5f81cc7a613021cac7b830456f6655ae567f89118c99f7715a11fbe839b62f9
+TAG: c53743db3bc1e1d8facd09fc210153bc930cd5dd
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6116326b1448f1731c476bbe2cac711412aa7179b1b1398c9350211c93ff3302842bf0b4855193451ab46728820f33ea412504c8f9c705d36521020227bc20b4cfe5b8b873f38c835405df6b49a6484e121892c82e6
+TAG: 0a89ab9279418ac764f4f5f1fa5be15c0ba43e27
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6119bc7dfd17657d2fdfc9eb5587a54b93d600118bb10d7e6ce7986eff89aa57df40907d36bef9a1798b4b44916dace26bee7b77d3da29fbcf65eda34c7a97c01879a6e6d9bbf93405c65590675a2ccb82c72d0c33d
+TAG: ad17ca3b338a29d2cd64ac3c41e60983430c2b13
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c61133476ae183d62dcfc356c35b8c037b57e33df0c5bdb86eb8992f6999be8e6aade716b75eee4cfd9d27fc67d6ba8383ca365233ec19b2a9850d0b201890eb6b70368dea0287b5d8348475a368a26895437bedbad9
+TAG: b1df25a8a015baf59e3e50d53ad528bf54ce5028
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c611450b9088ef27ea66511fa62518b8518cce0a0d05810059397d7377a918a08512d18e20679f542b4c37c4b65697526b33536095b9ddbe0ddec85094036b933ccd8d89fa8c2497534cabe31cfd452901329d778a7a
+TAG: fb9e5acf794bb8725e42af0ca4849ef2e1cfaec6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6113f6244ac0b131f197cfaed4523d3ec6dd4b7d78de7e7724a99d5659bc3045889f38fbb375111266322e1e288a3365633ef25f97e08bb534c5f472ec8208825551c9cc7870da2de8ff5f7a37cc2721959aa1b38a5
+TAG: 97397bbfa565db9eae18ad34ef8031853beb700f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da960595a1e5683179710af1f8efb7246a52b7397bcaa620f41674ed12845502dedafac4a946e003326c4e9769c290dea53a2fb74347d68c8aab643b92595a73f241f6a243359a7cba5a97246be45949
+TAG: e1b6771c4b1278559053516d88f8dcea5ade3658
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605959954047454ca1363a07e18a1c3cc56c38c8e8eef0b90f1d59c9e7c56da1e3c24dcc3c4ac1904ac3764e3c96065834c06d540fdbbd380b2cbfc1ac5cb836471b0af2d7b962b6978dac9f695bf
+TAG: 34c918d594309af05ef33f8239db90d290eec73d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da96059569b07682b8ac4a401c0029db537ada8120840964e34fcff177484265545f9db03a48479e3fb273001a27446aa490139b1b29d9b47a75727691931565a1ee2c2ab62025b31ac8ce1685d4e09a
+TAG: 8ab01c6ee68a7e7235fed3af3b8cd05c44b7a1e9
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605950aa0c15f6c227263758328ec101ddc0365712f23e76669f2b2a571aff52c191358956eca0b5eaefe43b630af88ea6447bddaf69845e58c8cd0f58f440fddd1669742f8550cd9d2c775397f3f
+TAG: e419c2c2d2081f175f8a8adfedec63e349d1e2f0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da960595a3ae7d1e1f19c69401de1594ff90f7320cabd3ab18435980998abb724cf0b161f520acc86c1321720369329119c358b627d7518728de3da1ac5cb8ef20d721d4fabc92effe0cf2e3f31e2487
+TAG: 67f9939a7244da23332c6da1060e1b44db285db3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da960595b7765397599d414f505ae443a80e7e070ade45866134344d7751021efb213efe3d3326ca40232b9b26cad910260126bed25ead0b92cd3ad0db65916a4f8c7bd499c3bd4786b1ae461e462f7f
+TAG: d65f7c614dcfed968e76d791b4dd7b6797df4569
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da960595028b71e2f4feb1515f13b6a8beb6f12a1d2d41cb93b80c8041eb466ad00d5d1c406be5147489b15eefc417e71e8d5fc541e038bab21ac2e494a039dc89b01c6c4bcbd3044615df044f40279b
+TAG: 5c0a2daffbd38ba9fa041c38126e9b281f618e98
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da960595d91b8481abe552607c202f0249df0d35e4db34db36e7c32c145f88a16d099877d74977093f3b5efca7b702e16d3e3e9a1bed2fc91c870c30b00151bbcefea7119e9e9d5a4542df9f44cc7817
+TAG: 0347d6e0c338472041dd70100cdbc31ce11591af
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e6073bb49a05aab47e1261835509e92f13661aa9ea6a8991c4e15d36cef7853bfd5eab841298410977438139e2dd9eaa5cbf22f199e5449da6a6009f11df1d2875acd5498de
+TAG: fa2d6ba6f695a6623b380864a963000ae64886f8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60ff28e1047551166d68ff8f7d6b1662e888539d33746c6504abca4fc0029a7683cf1636c8a501e4239c4ffa51eed4ee66819d91ec37bd01175f7288e78b4d9a20168e2eb9
+TAG: 2ee689b05cf6b9a168b1ed3d3532594fd6ee660a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e6092eaafc31edafccff5eae7e9dd2e84d843b8b2930a48f8b890a45a5350ab0ed5aceacfb893bda6cdb02c96d21d95c14a9cd16bf23de9360e6b38d9f6eb87f9915445475a
+TAG: a9ac9b7c16da2fc7fa467c8d73bd74415bc067eb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60efae2e6454f9e2c8717e684c972d1c9ea5d60e06897e57e3b404c0ea1ca6958a11e0602b361c6f4c83d32dfca296439f2b9e7b79a95a2e651381d0f5b93b834d5466736f
+TAG: cd869f2ee684df377001307faccbe43196195736
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e604db5d3c0a0754204f0239298460fadae49403ee45691f3eac0caf19bfe777155523f5dc12049ceeb591ce631f60019f70abbca82227da9578922025b048d94a89e81f496
+TAG: 1d608d8565e9562baeca59122b03b20b1a61b157
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e606ecf0a84b2afef9db65d8909659d70df3be3c8e7c49866a6879c39c1c1c889f248db278439aca1c42fadf2e32a4438bbf3f0aeab224122d17188dfecdfb3d022c68be4b3
+TAG: ab322175f3d129ea64a67c70570cde6390b9f004
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e6051b7e3ef0ee9e0dc906158be4884d27c3af5f035dc4547089174a3d9d9f020f7b3e2b7292d78857f483e0ea47fe2cdfbe4e2cdef89beef2f3e2dac06b52dda6d59f31781
+TAG: 3cdff1e57ac02d935163fe05ce6bd709ac80035a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60b3673527c7a51a314f8d467bd861e1c592c5383bf2329ebb2dee8fac9c8edbbfc9987b241f745a7a9b6e5f976b1e45cbd644e5124f36a9e9df48ddb8d1cc4092a79e9c51
+TAG: c8daeb99ce9f82a1c183a2dfc21d71a8dcce845c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad37f1125a09b18d0145ed710349e1673d7f55f36c919273d7c9d6ecdacb9e29391660fb68c23ec224289ea0af2e445c8570870a3e55e01167b69b504fc
+TAG: 57b6a52e8f5659b85d80db41a4ebb6923a7cfdde
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad3496b2e9d6eebccd9ad0107b4ede77eda3ef9346267bc5dba242d0c1ca9abd38a54291f1b730fa7397af72d80daa541fe1d11a4dca0a4a3908983b13d
+TAG: 7dc6e676aaa082eebe8a5c7814681a0e67cd69fb
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad3f964ce4d67fa886b109470360d3da9d58612db6fdc71a9951c54d15dec2b4daf4fded2e420004026563545984f9c6278c0f782ade33d8f49b2744290
+TAG: b5aa4dd455c1ba8624187bc0310dabf9a9039813
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad342a4ee8997c2cefc0bf1d016e0cd5f08ead145bc70b369b0a694efd5488fea4b3c7534d751ff6bec5961f8fe5555f26f6be2b0b9085bb8373c023ae2
+TAG: 10d1ccf9f7530b77b301f7f52e7a2e5fad0ec3c6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad3af641d7a383c89c2a9623f58267c6767dc85178fe6320388bfc8b86cffba826eeb97983e3eb66af22cdc772b78daca93384714a2238a05ded9a2db28
+TAG: 7897d59990b5530db90d341f699603954223a787
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad325c8f291d95c92b78f03eaff13c6d7791cd23a71faa55f50374ece8ae5153eef402930e7df035f90b9bcea749efc3b044029751f8bb684c290c3b69a
+TAG: 3180e56f152899a38d437540965e57beadd34542
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad3c1b8714e3b2b61ee5e9bfc8bd36cb2bc03aaaa040334eabd9f23fe934b390cd44149bd0ed2df82f05bc8f344461370a7c463165d79168ba51383b377
+TAG: 3b2065db38a12705fe10d59e9ee8f1787dfb7b29
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad31ee2ebe37b32fd611eab42af3423e388b06e6b893b0a5b5f57eb484fb0093c2a3ea0d8f0a0332bdfae24db5c9312156c572f9021279218d97c2e842b
+TAG: 8fcbf65c4556be8ec20239bd70063e42790db969
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b617e23eab77d45bf008c4944ba89bd39f73c53410059813812c60526d9946d227ba0ac2624c81229101db8da12b6fea44611cf0b2c
+TAG: 4f12ebd5984c0a91a17980880b3cc99da7320685
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b61e8414b359a9f315468271eafe4500b7e1068313115dfa2d2049bdf3cb380cce3c91ce0664fa1dcadcae609327eb004aed1e68240
+TAG: 99af181fbb09c63ce3d00220f859270c79379a4e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b613bba0bed31aa80fbd812e58b5ae6c8370d4a3ae5c673e3dca8a33386a29623c23d2cb8c496970facb1868d02929d22d6ab45f153
+TAG: 193ebe72c3be3f6f0524e36d07f17609c67f1c30
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b61743d8b05e4c17e60fe2d0ed78e1c70e5ebaf1776c5ee8ddaaec9ec56821e3f7bad362254d9a066f1f8b0faf1218c2b1f1cf84d47
+TAG: 72acbd2e99b7d2dddcfd5102057d9ec1e012ed29
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618c7ab2dd9e499a5ee8b43a9a1c2d19810e17a04999c2b0043d7c1adfe6cb136c92185d5eee636caee02900e406df972e3d5117c8
+TAG: 2f0a83135e52fa1a2fcf2998f30af10e9be30356
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b61d2cf53ffe9a58f9edd51ca98c4f497f3618fb30a5120927fb0870866d33e7dc36f0d881f46fd325d4c087a02311ed6b72efb3d55
+TAG: 49b57f5399ed16ecc7422f5506b2a5a82b26046c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b61f19584eaefbc443e38e35ffe199a4a75f91a71c165d8ae1e14856469e72a0adef4883d5cdba223a54312494db820012afabde779
+TAG: 2583e3170a78f39e332ad5b2ea05b43708d649ae
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b619f5be9cd8bc5347bbd8fe2965e40167712b881eeae1e98f06c5aa75396b3722fa2b8af315d913332e41fcc725de38460382a3c17
+TAG: b7f9945423c3f607425cbaeff60c13cca9211b16
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c460603176bc103b80d99c81c82232d8a02e1df2d8117d02a77136a0a0a7dbd3041801f733d2288a2d85340e034da66
+TAG: 0c44245dc4f01656d20d6c8ad2ee36b87362cca0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606034aed7751b43863a051960623326ba03fcadd00426a6f7e27c5470da037656494cf8d209425439b647873447a
+TAG: df2efbf7611483a141028ebf8aeea6b4b795d648
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606033b4313522a7da1adc218daa6e5c3168fa3ad0d369b277f61752c5f7d6449d55498d0fcb8b6300c91aeeefc24
+TAG: 545481566bc833d18e6af5f4928ffae02d209cb8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c460603aabb3f70353c35f0c5829ea178e1c7be9b2235feeb7d7bca476515e55249a472f27fc31c425ca339c9ac8f3d
+TAG: 7ea2f318b0432a9e7b00137b9f7ae11d7832d75d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030d8428434d8461b91295695d6a3d90e1a03bcab2d88ae05069fff28e8b9e50ae440996d67e2698480f14d0af
+TAG: d753dcfa7dffca41971e6f45de79971d29cffead
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c460603dfdbddc63e495155401400ba1528ce7387f39101538649b3489d7ff411181b41a2c7d4bca9b2fdae60685273
+TAG: 8bd10d3d761d530aeb5497196b8818dd2bdd7be3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c460603e5fbf71e904879e71195715df1a19538142200471124c618dc7968de10bd1d850b4f7258552b0640a621672a
+TAG: 48159568f951893d07a85f00915337febdd13c74
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c46060366153de87707c1e2ff5ebaac8b2a0fa39c856332d58d121cfdafa460b489fd1bf062cf6de4bef4b6f855af39
+TAG: 31caa9b9ede28e2afb984c26dfbda0f0cb852fc8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c492975d6d33cef2a9cc8d8035a2baf3d58143a82c7d2eb335da1b060f1277ff3756dd22a928f9
+TAG: d6b98cfea8ca1558c76e60455551dc79c30b2342
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c492977d1a169942fe78c97b101a9e5d4f86597070fe84d9b70615a1e0c985af1194ee5095314b
+TAG: 4bc18214e6cbae1a2d256e721c34c60022e9b41d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929701489e71c2ad19789059aad62516a4e6e07454140248966016bf71f707ff2593973979a8
+TAG: ef236845d789b4a071f1903c79f7d6576f92b45f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c492972346e9230c6872c0645062837eff7731d6732cc6993c48fa0a712845de1b3db5e657e778
+TAG: 9d6f91eaeeef2efc0f4ea9eb0249e9fe43ebf438
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929759c4468079cc1fe6091e711c52fb67803d4f3c33e792a8df8a1c8e1e299d89ae529d5997
+TAG: 8f4203d9e2127302bec77fda84cd385d0e94fe12
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929704768b6905e3a1fc76f98282646521f8787d79fbc4ba30e2d94b2d7efa847a7fce78c1db
+TAG: 3740bdb419938d8963338ef514ac37807f590e6e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c49297041084bedc6aa719fcc3b1c3b81eeadf8abf41f8815d2854896787231270af7812a91513
+TAG: 57dc8aa2392e0a850234e8b47a381fe6ac989b62
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c49297cb85bc06fc0be808b13899fad4b50aaba41b642d8e76dcf31d9b0a14e4f73693be6d44c4
+TAG: ede5ae1367b69c8cfef4cc94f832056543a65da0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b4a210376e6e15bbe3c711432297576a978c632fb3211b14828a14ada
+TAG: e48d20829be446044ae28179214303312aa0589e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b77f02f4a5c23bbe93cef6b80fedfeabdaac59fc359cdea0cfc1df50a
+TAG: b733ee53426574b78fcda289126b9a102e7e652c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b0e79bbf9779de02343404bbc4b375eb8faa8cd3796642009ac386e29
+TAG: 1fadaa07769a34ad2ab1f477911e22688b7d68a6
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386be849b4c40de4201e761b9de0cc731e6a103ea451e0f480bb5c87b84e
+TAG: 9c59adc597b5f38bf949a8129abdf3b2ee6f7785
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386bcd293f34924a4faed7f64ef5ad598d7e1073860aedda95a46ea61385
+TAG: b1358a8a3f7650e8368f4d3b61bf1bcc6632afa2
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b6d6ec1226b7a71d3e13014bd22154bd0820a6992e41004b402c960c0
+TAG: aa1a80e9aa352ab2d072837892d49af210bfa93e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386bf4605b87ed4c350f45c5b7d65f00d399e81506f410bba8af001964fb
+TAG: 372cc197aa260d9bd829c8c473a7bebaba9ed00d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386baf431c29c3d212de63cfda976fd6e330d74bdc2cbac31f7860e827f6
+TAG: a3a625c52245a06a914e3ec1e0eec4856e66da23
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f0680285b1e57953756b9cdb1901fbda4ea47b5ae
+TAG: ea17e950cd91298fcc38b52337467a2595342343
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f72ef52dc4da1235edc9476fe9f2240c47a049d3e
+TAG: 7e55eaa00e57dff0ed72e083c389bfdb5cbd6a32
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85fb2fa5a12bcb835d6c9b98873c85177ad92cbd015
+TAG: fa07fb691137a78d770f0c717bc0eb27ea342a55
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f081026e91d3b1f3da3782c9160ee467782541aa4
+TAG: 691da91b0413eabd629c7b77b8903623f65cf9f3
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f97109d677c22f509281b9dd7a75aace5886fdbe6
+TAG: 84cb95e3837393636aba0fffd6c56ef79142075c
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f7ba470aa5d263f6e1a29203a957d8424449efe8f
+TAG: f7e8fbefb4c2cf7ae37ee1a14e05cef8802bd474
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f46b361cda109d53840150009456cd7700b47aaf4
+TAG: 09bf7b11716d6851b050752068b8a31ec865aed7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85fcd2bcacccd35a6fed122c3046a55e8a71b13286e
+TAG: fc5e5b701928b5733152717ef232120eda146c56
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f065946d4f8abb184260eb85d101783
+TAG: df909b54a5fe227a4ac2d7e796ec043a1b2d3afc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f065946d2ac54ebb4b83b18e5fb5195
+TAG: b1d84f4bb0c7cb9cba0188ea773aa6607d3a2d03
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f065946ed477e35146cff380c3f6709
+TAG: aa8f95419724ce3b55f06c8b8095d38e43ae1de0
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f065946488b5ebdef7ce05a8d75a216
+TAG: 8c74147617f67bd4aa51a73cc8262becf680a483
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f06594612d5009a9969f137a08bcea8
+TAG: 58ea6be5c04e7921ae923243203e1667e11bcee8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659467791a26dc54e946787e939f3
+TAG: d85f9f17c98cd33fcfda583c0f8ed7eac3ead237
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f065946838bd38e83eb0650fa798a32
+TAG: 3d73b2507d8e47635379378e212a8faacc1b7fc1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f065946330d5e8a53fa3e465f023c2a
+TAG: 502b8deea47260f008dfe1363b59f9b980149279
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a2b78e9b
+TAG: 78f537fbb7160e9181a825e49fa76a4f8be7bee8
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6ea6d0822
+TAG: 1a10d1b6749439e60c7a0e58964b964ac151221f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c61f9f5534
+TAG: f7968deb0141d1c751dfca4acb860c6843ff916d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c668a8c582
+TAG: fe7b6e01c0e1cee2112461fdf4d9d5072fa691c7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c628816956
+TAG: 60b5a71171b40fdb046967fcee93d3328efe1b16
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c65a3dfb74
+TAG: 06dbc63f13cc4b700c451e6d9b5b5a5965fa4c9d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c62340443f
+TAG: 1fd305cf7db477158b2874d2af097835222543f5
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c66eeefe53
+TAG: 8464fd0281b13bca3182cbadad791177b65fc24e
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd54190906cfbf05b3a76bb959be491cabc
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd5df43892eb9951ac0f294d959a8e19aad
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd52f3ae9838a864bdddea8e18f932fa70f
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd5f5e62b70527c93c3653365d49d4470f4
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd569cdaa3dc8d941cf02c2e6b611e45e8b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd50034e5a16962390e9e20dee3bc97537b
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd518f2775706baafc8985117f62b24ebb7
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd573f4c677bfbc7ca4e4f6dbb427139135
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd5377f387bd914c1d6390da2072b1b2348
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd5377f387bd914c1d6760693487f49b4de
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd5377f387bd914c1d67f9bace5204f1935
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd5377f387bd914c1d6b6f4511bbef9928d
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd5377f387bd914c1d6738cf34d66735f4a
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd5377f387bd914c1d69cc20ac54143c916
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd5377f387bd914c1d6c350de61f5990ec1
+NO_SEAL: 01
+FAILS: 01
+
+# DIGEST: c6105cc86e18eb8376c16ea37693db5c07b77137
+KEY: 8503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe47
+NONCE: 7e0cdd46be99371e
+IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c748
+AD: 1df3f4183aa23fd8d7efd8
+CT: 17944422f667bf1356c234189f9c6cf7af52b2832b2fbaa990ccef4e7f9bc3841e59e25c00e3686d5bd5c29f3ebd1b0bee840e8a6e992421c62de5a8fda3a82f0af0de2c6be5f12937267befe9b421efafca4455b5af6174cb0e6f929031086aa7b85a073705fa3718a2a9b595e32a725ccb0b3328ea913edf6a42dad4c44585fbbb9a500b0c938c78d4fa17b2e52b479aba6921b376bec72ff6d66a5854180afedb8edb06c919016d19f252ab39d05c3c4f297038badb09ad7f23c88d5cdba7e793f1e4f2d107571eb9807efb3009187e1415e5d0d3c6110ff77f26da9605955843b9cc60875e60c3181ed0da4e5ad390e1d3c0fb942b618d1015716c4606030a40f0a554c4929764da415d773d386b3bb018a4ce72e85f28cfa3e08f0659464c0e0cf3215996c6a7698940
+TAG: 23e4fbd5377f387bd914c1d694ac69cfe6bbfb48
+NO_SEAL: 01
+FAILS: 01
+
 # DIGEST: f0f82752a691ef5866413f2b2e5c1d0ebb41ccc8
 KEY: 7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd8
 NONCE: 8503f78b8ed1c8e9
diff --git a/src/crypto/cipher/test/make_all_legacy_aead_tests.sh b/src/crypto/cipher/test/make_all_legacy_aead_tests.sh
index 12f8853..0ee7a51 100755
--- a/src/crypto/cipher/test/make_all_legacy_aead_tests.sh
+++ b/src/crypto/cipher/test/make_all_legacy_aead_tests.sh
@@ -2,9 +2,6 @@
 
 set -xe
 
-go run make_legacy_aead_tests.go -cipher rc4 -mac md5 > rc4_md5_tls_tests.txt
-go run make_legacy_aead_tests.go -cipher rc4 -mac sha1 > rc4_sha1_tls_tests.txt
-
 go run make_legacy_aead_tests.go -cipher aes128 -mac sha1 > aes_128_cbc_sha1_tls_tests.txt
 go run make_legacy_aead_tests.go -cipher aes128 -mac sha1 -implicit-iv > aes_128_cbc_sha1_tls_implicit_iv_tests.txt
 go run make_legacy_aead_tests.go -cipher aes128 -mac sha256 > aes_128_cbc_sha256_tls_tests.txt
@@ -17,8 +14,6 @@
 go run make_legacy_aead_tests.go -cipher 3des -mac sha1 > des_ede3_cbc_sha1_tls_tests.txt
 go run make_legacy_aead_tests.go -cipher 3des -mac sha1 -implicit-iv > des_ede3_cbc_sha1_tls_implicit_iv_tests.txt
 
-go run make_legacy_aead_tests.go -cipher rc4 -mac md5 -ssl3 > rc4_md5_ssl3_tests.txt
-go run make_legacy_aead_tests.go -cipher rc4 -mac sha1 -ssl3 > rc4_sha1_ssl3_tests.txt
 go run make_legacy_aead_tests.go -cipher aes128 -mac sha1 -ssl3 > aes_128_cbc_sha1_ssl3_tests.txt
 go run make_legacy_aead_tests.go -cipher aes256 -mac sha1 -ssl3 > aes_256_cbc_sha1_ssl3_tests.txt
 go run make_legacy_aead_tests.go -cipher 3des -mac sha1 -ssl3 > des_ede3_cbc_sha1_ssl3_tests.txt
diff --git a/src/crypto/cipher/test/make_legacy_aead_tests.go b/src/crypto/cipher/test/make_legacy_aead_tests.go
index 40b8a01..66c8b0d 100644
--- a/src/crypto/cipher/test/make_legacy_aead_tests.go
+++ b/src/crypto/cipher/test/make_legacy_aead_tests.go
@@ -60,8 +60,6 @@
 
 func getKeySize(name string) int {
 	switch name {
-	case "rc4":
-		return 16
 	case "aes128":
 		return 16
 	case "aes256":
@@ -126,11 +124,18 @@
 type options struct {
 	// extraPadding causes an extra block of padding to be added.
 	extraPadding bool
+	// maximalPadding causes 256 bytes of padding to be added.
+	maximalPadding bool
 	// wrongPadding causes one of the padding bytes to be wrong.
 	wrongPadding bool
+	// wrongPaddingOffset specifies the byte offset of the incorrect padding
+	// byte.
+	wrongPaddingOffset int
 	// noPadding causes padding is to be omitted. The plaintext + MAC must
 	// be a multiple of the block size.
 	noPadding bool
+	// omitMAC causes the MAC to be omitted.
+	omitMAC bool
 }
 
 func makeTestCase(length int, options options) (*testCase, error) {
@@ -185,76 +190,75 @@
 	var nonce []byte
 	var sealed []byte
 	var noSeal, fails bool
-	if *bulkCipher == "rc4" {
-		if *implicitIV {
-			return nil, fmt.Errorf("implicit IV enabled on a stream cipher")
-		}
+	block, err := newBlockCipher(*bulkCipher, encKey)
+	if err != nil {
+		return nil, err
+	}
 
-		stream, err := rc4.NewCipher(encKey)
-		if err != nil {
-			return nil, err
-		}
-
-		sealed = make([]byte, 0, len(input)+len(digest))
-		sealed = append(sealed, input...)
-		sealed = append(sealed, digest...)
-		stream.XORKeyStream(sealed, sealed)
+	iv := make([]byte, block.BlockSize())
+	rand.fillBytes(iv)
+	if *implicitIV || *ssl3 {
+		fixedIV = iv
 	} else {
-		block, err := newBlockCipher(*bulkCipher, encKey)
-		if err != nil {
-			return nil, err
-		}
+		nonce = iv
+	}
 
-		iv := make([]byte, block.BlockSize())
-		rand.fillBytes(iv)
-		if *implicitIV || *ssl3 {
-			fixedIV = iv
-		} else {
-			nonce = iv
-		}
+	cbc := cipher.NewCBCEncrypter(block, iv)
 
-		cbc := cipher.NewCBCEncrypter(block, iv)
-
-		sealed = make([]byte, 0, len(input)+len(digest)+cbc.BlockSize())
-		sealed = append(sealed, input...)
+	sealed = make([]byte, 0, len(input)+len(digest)+cbc.BlockSize())
+	sealed = append(sealed, input...)
+	if options.omitMAC {
+		noSeal = true
+		fails = true
+	} else {
 		sealed = append(sealed, digest...)
-		paddingLen := cbc.BlockSize() - (len(sealed) % cbc.BlockSize())
-		if options.noPadding {
-			if paddingLen != cbc.BlockSize() {
-				return nil, fmt.Errorf("invalid length for noPadding")
-			}
-			noSeal = true
-			fails = true
-		} else {
+	}
+	paddingLen := cbc.BlockSize() - (len(sealed) % cbc.BlockSize())
+	if options.noPadding {
+		if paddingLen != cbc.BlockSize() {
+			return nil, fmt.Errorf("invalid length for noPadding")
+		}
+		noSeal = true
+		fails = true
+	} else {
+		if options.extraPadding || options.maximalPadding {
 			if options.extraPadding {
 				paddingLen += cbc.BlockSize()
-				noSeal = true
-				if *ssl3 {
-					// SSLv3 padding must be minimal.
-					fails = true
-				}
-			}
-			if *ssl3 {
-				sealed = append(sealed, make([]byte, paddingLen-1)...)
-				sealed = append(sealed, byte(paddingLen-1))
 			} else {
-				pad := make([]byte, paddingLen)
-				for i := range pad {
-					pad[i] = byte(paddingLen - 1)
+				if paddingLen != cbc.BlockSize() {
+					return nil, fmt.Errorf("invalid length for maximalPadding")
 				}
-				sealed = append(sealed, pad...)
+				paddingLen = 256
 			}
-			if options.wrongPadding && paddingLen > 1 {
-				sealed[len(sealed)-2]++
-				noSeal = true
-				if !*ssl3 {
-					// TLS specifies the all the padding bytes.
-					fails = true
-				}
+			noSeal = true
+			if *ssl3 {
+				// SSLv3 padding must be minimal.
+				fails = true
 			}
 		}
-		cbc.CryptBlocks(sealed, sealed)
+		if *ssl3 {
+			sealed = append(sealed, make([]byte, paddingLen-1)...)
+			sealed = append(sealed, byte(paddingLen-1))
+		} else {
+			pad := make([]byte, paddingLen)
+			for i := range pad {
+				pad[i] = byte(paddingLen - 1)
+			}
+			sealed = append(sealed, pad...)
+		}
+		if options.wrongPadding {
+			if options.wrongPaddingOffset >= paddingLen {
+				return nil, fmt.Errorf("invalid wrongPaddingOffset")
+			}
+			sealed[len(sealed)-paddingLen+options.wrongPaddingOffset]++
+			noSeal = true
+			if !*ssl3 {
+				// TLS specifies the all the padding bytes.
+				fails = true
+			}
+		}
 	}
+	cbc.CryptBlocks(sealed, sealed)
 
 	key := make([]byte, 0, len(macKey)+len(encKey)+len(fixedIV))
 	key = append(key, macKey...)
@@ -290,6 +294,16 @@
 	}
 }
 
+func addTestCase(length int, options options) {
+	t, err := makeTestCase(length, options)
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "%s\n", err)
+		os.Exit(1)
+	}
+	printTestCase(t)
+	fmt.Printf("\n")
+}
+
 func main() {
 	flag.Parse()
 
@@ -310,48 +324,38 @@
 	fmt.Printf("\n")
 
 	// For CBC-mode ciphers, emit tests for padding flexibility.
-	if *bulkCipher != "rc4" {
-		fmt.Printf("# Test with non-minimal padding.\n")
-		t, err := makeTestCase(5, options{extraPadding: true})
-		if err != nil {
-			fmt.Fprintf(os.Stderr, "%s\n", err)
-			os.Exit(1)
-		}
-		printTestCase(t)
-		fmt.Printf("\n")
+	fmt.Printf("# Test with non-minimal padding.\n")
+	addTestCase(5, options{extraPadding: true})
 
-		fmt.Printf("# Test with bad padding values.\n")
-		t, err = makeTestCase(5, options{wrongPadding: true})
-		if err != nil {
-			fmt.Fprintf(os.Stderr, "%s\n", err)
-			os.Exit(1)
-		}
-		printTestCase(t)
-		fmt.Printf("\n")
+	fmt.Printf("# Test with bad padding values.\n")
+	addTestCase(5, options{wrongPadding: true})
 
-		fmt.Printf("# Test with no padding.\n")
-		hash, ok := getHash(*mac)
-		if !ok {
-			panic("unknown hash")
-		}
-		t, err = makeTestCase(64-hash.Size(), options{noPadding: true})
-		if err != nil {
-			fmt.Fprintf(os.Stderr, "%s\n", err)
-			os.Exit(1)
-		}
-		printTestCase(t)
-		fmt.Printf("\n")
+	hash, ok := getHash(*mac)
+	if !ok {
+		panic("unknown hash")
+	}
+
+	fmt.Printf("# Test with no padding.\n")
+	addTestCase(64-hash.Size(), options{noPadding: true})
+
+	fmt.Printf("# Test with maximal padding.\n")
+	addTestCase(64-hash.Size(), options{maximalPadding: true})
+
+	fmt.Printf("# Test if the unpadded input is too short for a MAC, but not publicly so.\n")
+	addTestCase(0, options{omitMAC: true, maximalPadding: true})
+
+	fmt.Printf("# Test that each byte of incorrect padding is noticed.\n")
+	for i := 0; i < 256; i++ {
+		addTestCase(64-hash.Size(), options{
+			maximalPadding:     true,
+			wrongPadding:       true,
+			wrongPaddingOffset: i,
+		})
 	}
 
 	// Generate long enough of input to cover a non-zero num_starting_blocks
 	// value in the constant-time CBC logic.
 	for l := 0; l < 500; l += 5 {
-		t, err := makeTestCase(l, options{})
-		if err != nil {
-			fmt.Fprintf(os.Stderr, "%s\n", err)
-			os.Exit(1)
-		}
-		printTestCase(t)
-		fmt.Printf("\n")
+		addTestCase(l, options{})
 	}
 }
diff --git a/src/crypto/cipher/test/rc4_md5_ssl3_tests.txt b/src/crypto/cipher/test/rc4_md5_ssl3_tests.txt
deleted file mode 100644
index 329569a..0000000
--- a/src/crypto/cipher/test/rc4_md5_ssl3_tests.txt
+++ /dev/null
@@ -1,808 +0,0 @@
-# Generated by
-#   go run make_legacy_aead_tests.go -cipher rc4 -mac md5 -ssl3
-#
-# Note: aead_test's input format splits the ciphertext and tag positions of the sealed
-# input. But these legacy AEADs are MAC-then-encrypt and may include padding, so this
-# split isn't meaningful. The unencrypted MAC is included in the 'DIGEST' tag above
-# each test case.
-
-# DIGEST: 426e94f7c3d22cdfa51d7ead530d93d7
-KEY: 18cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c5
-NONCE: 
-IN: 
-AD: 936a91d0b5d2c02672
-CT: 
-TAG: 05846be413003a0eb64a245a28775d8f
-
-# DIGEST: a7bdf0184f0c1374fc84aaaccf0d8309
-KEY: 171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3
-NONCE: 
-IN: 936a91d0b5
-AD: d2c0267218cb7090c6
-CT: 2593351dfe
-TAG: 863de43649bf546a1bd0ff1125b8e350
-
-# DIGEST: 1b3c97629ae3b60a1116b48bc7366361
-KEY: b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23f
-NONCE: 
-IN: 936a91d0b5d2c0267218
-AD: cb7090c6171386d641
-CT: 51e5dff21e15c9c107b2
-TAG: 503b5f8096b7b5f95f94caa4bd64f05a
-
-# DIGEST: 506e7defec74b711d424bfedc1a9d9f7
-KEY: e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd885
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c617
-AD: 1386d641b87797b684
-CT: e1b2d8a4bc5a63d9305d8f5aa266cf
-TAG: 5723497026a15e318b5417b7a3300a47
-
-# DIGEST: c2668e1af0461bb975611ee291d951de
-KEY: 3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b8
-AD: 7797b684e0fb56f97c
-CT: 22de3dcf23720f48512ec7e47a6dbb71daeb6f81
-TAG: e7d301f88b1400714b59eb3a1f81eab1
-
-# DIGEST: bd92ee8df8f0d9bc61f917fa8c60b435
-KEY: 2993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0
-AD: fb56f97c3961d8afa2
-CT: 48b521762a7555332bc0d4074a63c2381db05a9c2406c1351c
-TAG: 5255a7661e8f1e2c1764daa0b47eec0f
-
-# DIGEST: 842173c8929556ff8b2ac55fe427f5e7
-KEY: b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c30
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c39
-AD: 61d8afa22993a340b9
-CT: 4bccbd6af7761500dc4113802632ebe1dad33581177b03b51fb095e4fd05
-TAG: 333c9a1413a6d2ce961a5f3447f5d0a1
-
-# DIGEST: 6823af156b7baae6f74ddfc4f0d911cf
-KEY: 1df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa229
-AD: 93a340b9b3c589c748
-CT: d5437e9a3618f0d4a3c4bcc6393c603be961ec485bae84b4d0baf0f50419e7d35224b1
-TAG: 5982a70a52b2d960ca4c118aeb73bc4e
-
-# DIGEST: 39ddff59a03ce56ccb306bf69c687d16
-KEY: a23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d7
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3
-AD: c589c7481df3f4183a
-CT: d9774257767cf640e68e706cfa861bfd00f992df627d1ab8557433d98c6ff11d92c74d634340c193
-TAG: 1313f466a4acf36eecd52bfb76535072
-
-# DIGEST: b735db1f1bde92e0b5655d14a378ef28
-KEY: d88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481d
-AD: f3f4183aa23fd8d7ef
-CT: 4fea0cb8faec38c3cf3b3562ee80273f65f18a42fbb43e38804bae51a3fbb16074cc4ea40464a950a9106c5ad4
-TAG: c2da66e07900cf676356fb011c1a7476
-
-# DIGEST: 6d89920b67eecc3e93b7cbf90e37d872
-KEY: 8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8d
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa2
-AD: 3fd8d7efd88503f78b
-CT: 6e658a27ffd7aeb5906dc743361b19f62aea56f41b043c82b2a2caf1eb75e8f28dc73ddb7d72d4d333e9e57e5f9b746d2167
-TAG: f2ee67308d0f5677a079387c90f30dae
-
-# DIGEST: 274d4d9ee741be5e72cea431cf75c7ab
-KEY: 2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd8
-AD: 8503f78b8ed1c8e9ba
-CT: 835cb09e59158c13c28ad651482d75c39cbe91cf8d224fce0413770d56191f74bbbec9641588408fe69791a3cba4bb1d54b6d605595ab9
-TAG: 4e721990c5ff5c878405d1a1d6699581
-
-# DIGEST: 5e63a64af3e67492f7e4fd2237f2ab67
-KEY: 0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0c
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8e
-AD: d1c8e9ba2fd6773e0d
-CT: 62905dc07cd5df22402b2eb148f4ad3a740612f647fc8c03ea6a9f28c7913734317c609d97eabdd133840845a67dba69b2732f05ac562fbaacde227e
-TAG: a19603ad15f278fd377fb5ff358efeca
-
-# DIGEST: 2fca578631a06e8cafa565fd09c30e09
-KEY: e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be9937
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2f
-AD: d6773e0d0c302a5f47
-CT: 70d3805fba2f613b689edf9a61f03888240085734701035bced726440ae0d9955193849ca6133ce8c3c22a54337617376f8d4d3bc09f4910130ecdefb8abb366ca
-TAG: beb41bfe3e73105e706ca7169206c585
-
-# DIGEST: aa192f3b031cb9a30af41b8fa3f4e369
-KEY: 91d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c
-AD: 302a5f47e037446f58
-CT: b1317208f660f563bd62f005ee65796d293a2eeb2e59f7705c997a491d01b23e39fe266b3f6450a3ee6a1a17dded8259334f7aaf1efceb7e2b53eabd371aa4ab86a008cbecc2
-TAG: bc77d0ac024768b105d4be4bc343f40e
-
-# DIGEST: 393c853840160ddd9e7cbb51e3377f57
-KEY: ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e0
-AD: 37446f5891d77df660
-CT: 1d99057efaf87afb2a5be17f3b5226d4fb76db90dd274af26ad858360701ee8119d1e927ec1c93ecfc81b70bcdc54f74361300593d53145acc58a65e8f1c5d8db80828abdfa25e107e4ecd
-TAG: a86e86c0457e2ad6f567408e6b12f53f
-
-# DIGEST: d02f0f475895a6643bf54f91026671dc
-KEY: be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891
-AD: d77df660ed82933f62
-CT: 2d0c0b403b1320346deb4fe08c3c8c6b0a2087aa12b21df1f5fa06ae3113589b329107c852cd436e4a5a160a1f8745e8fdba76e9cd66d09dd21ec5135899eea5b218a7ac6992e03582d0eab07da34cd0
-TAG: 861cc010424b3168d94cd5e0c413b661
-
-# DIGEST: c99f7c9d68495a74eaf7b380cf8ebb5d
-KEY: 6965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a1
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed
-AD: 82933f62be8dc55b43
-CT: a994e7600252b8fbef23be6c01eb38234c10a49b963dc0b1a13b7213579b7254ee4954de0044d31127dd6bb49c89072b1baf049db9a987b742a9e042ffe5425e280b546a7e1842b689fd0fbf418ff7d18672f49f92
-TAG: 3f08b1086962d1eac317bddee31c1b34
-
-# DIGEST: 184dcb254997993937d338a762208d0f
-KEY: 7e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a729
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be
-AD: 8dc55b436965aabe47
-CT: d558213621e14f40231438002d0dc5b1e96bce531a1c118e478b59001210ff8478e54ed24032328858c0e6e2204566c4e98e0a90a7ca2f856b67e50e01b0d6ebcf4cab4494d394cd642a98fefa1343a6a5e88b1f778ad94be2fd
-TAG: 43804328531f04ade72e44c9bf657eff
-
-# DIGEST: 5edc848f24cad2efa22f6fdda710b027
-KEY: 99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b4369
-AD: 65aabe477e0cdd46be
-CT: c1ed7d7615c5575817fa2b5353c1ed6e16b4c18fa57789b88030d9ec80447037729f82f7c5fc34d90c93969607348df0754c5549a9fea1cb94ad9f63cd5cd063d60a3af47e1ebd80c3dda604a30bb099f27557ae918961262a57999086296a
-TAG: 2a098f3f6669360001a661ab3be820d6
-
-# DIGEST: d24e0f5685b3b90ca1669656dcbad20b
-KEY: 7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e
-AD: 0cdd46be99371eb8da
-CT: e4a22be70ba7642ed6f02f1b76ec2143c161b03fe406e19f043e23a6be3a575c11721824c7c796ca3cf96b835830ea369b83b05a751e481b77446751e3fe0cdb27eb9682ed8cd71e48f8699e743be7e70cc80deacde5c9381a59c7aa908d417192a3dd12
-TAG: 32c89817f1ee09295c9d7108e606ec70
-
-# DIGEST: fea6f3c6b5b442c42392aef4b8327654
-KEY: fd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
-AD: 371eb8da7dac997dea
-CT: a27d73f11b119fd94ef071131585a759f82a5028c2c56bb31baffe9746281636ae0f691e411ed8954a959ee7a6ab49cc5581a58ee4d734d9a013758bec7ca07c5763eb95eaa577e05dcd5d7cf361821f5ad118566c7ca5b8f3d05fff984f8875cffad97df5f5a64f43
-TAG: c783535f032ad4c2905fbc44fc9d05ef
-
-# DIGEST: fb6e2c79ce3f425b011f1a1291c68b84
-KEY: de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2ea
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7d
-AD: ac997deafd64b1fc65
-CT: 3c4ae6b1a39df8586882981e6998eba21a339e0f7208acd91364c09ce26593d320f27c290e4fce80b790900b2e50f848130ed76411def57687c5047326925596e248bb62c7bf8179f6cad60e70b484a0b83529ed7b2c62c03a9c101b26508c7cc95d85e783728dc6c9e5609910ec
-TAG: b364e72448df5e15fb56469665cfc331
-
-# DIGEST: c2afdc008657b539a6611ea992bbc482
-KEY: 41a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae021
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd
-AD: 64b1fc65de39f4f035
-CT: 022fb12a967311e357f7f9634e1ad598d94d4bae2d70daa6136b6be1c06cc4c5f2af7a02903992393a63c2f037b4534cbd720e75501930b081145e9fea8e640941df62fd5f36dc15195c2b55172c052779d9400d30936478b346450fb947f66cd0de9bf0fa832bdb9ad2fe5b3e5724b2acf644
-TAG: 49736dd0605e62bf24043d5c96057d48
-
-# DIGEST: 6f8e417699313a90b5aded715dcaa643
-KEY: a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0c
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de
-AD: 39f4f03541a11be112
-CT: 85eb73b69ad10ed561d27cf2cc28154fa02a2b366ae40a206674b7c5e539cc05cdf19dca5a5db49154b1805b75661cc78be9d5dde3eaedc9fec040b24c05703beb8457b43f3e808459257fe98273f13b9c5127f5c211e43d7e84201104231df4091ec9d2bfc1ba3b68422593215d834433fa48af743811b1
-TAG: 2f81076852caa12dbb640037fa468d8f
-
-# DIGEST: 8aceb91b52859608724b4a48b922d43e
-KEY: 4ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541
-AD: a11be112a72933c7b5
-CT: 4b7276030a7874c9a0ff4c581605eb8c73c70d0eeaba862ba50568d193b5c04c739df087b3e1f797d0afac61a19603ed3506d25ea30d8c1275827ae383efc0e1e14c96263dbddabd48bf73269b4057791cb162885ea1b26f755c040337d79113021c2b920537f35361fdd3c44619dcf73bbd0a8b4d57235d6bd8f1d249
-TAG: 0407850fc0180fae942efa19393a8798
-
-# DIGEST: fad9e8eb1af2dbcdacfa0b8717c23924
-KEY: 905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f2
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a7
-AD: 2933c7b54ed4fad0be
-CT: 57e0ececf205a7ded9c530952bff2329cbb54d2ae077e741078f2734d516217567864b500fc66987f4382f45c31091bf2146a2a28b6f7327edec01b5261d9f0ba216c32ec1f8131998c6d06e411f1b77912bb4d5a6eaca54fc02b143da2ed6f0d5c85bc205dc2807e981ff98e08f12e45879aa4bbd16377ef4fb9e6b7e1759e64ccc
-TAG: f1f60690a3c488f146d36641928cec5f
-
-# DIGEST: 92ea0c97694e315909b540f2a6c6371c
-KEY: 5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d03
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54e
-AD: d4fad0be905d41203f
-CT: ac58dc34b2abc4a6905ac7c4a788835e00f335e8c5c88ecce9e1b18a9fda971e1319440935913cf171074595b77d064c558fbee528996413436441dedc503fa251c83e4c5428a30f52b098f4ed355c8d598cd5d5fdfc2fa4802d9212f07bb1a147c9d1442865df7774b9fed2d50deea09667b920968af475c7aaa0ceafa9eebdf3e22efbe24be8
-TAG: dc1c2b005b805744a09da9dd508355b4
-
-# DIGEST: 3077366019f1e67eb8eec875922863ef
-KEY: b2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be90
-AD: 5d41203f5dce998f8f
-CT: 5c998d85a3c0eb59f5ac78756cf3b2db5c20bf0657d0339e66c5a6e204e72fac3fd21690915445fb55fb7405685efc47ea98154004d6a3373dcc1014d8f59b3d711ac32f4056fe4b9a1259c62bd9a5291c282b7e8e6abc5cff0f414f782149a92ba8717ea9fb9d5cd6d6347f4ab7d06de15afbab9cc7c524783e22619b61afc217f83bb6911b1b055c12ae1c
-TAG: 1fa679f8407f206bad94fddc1d629ec2
-
-# DIGEST: 5252d79fb797526525742fa0368f13d1
-KEY: e02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5d
-AD: ce998f8fb2eaad409a
-CT: 02707c7e05411a77bfadcca90c8994191ec79edbada45b95ff0add0f1cea0d0f35e7e208a493d80ef2c2c114a563e87329429ff36608fc0a0e1115a44b47d47c5e5095b2c0662c523814954c57d4ac5038c362b574e1b35543b5a04335ac4a5e6054a2f541688fa54b6e0d3da3a1e22c22b3b9baaa523e5ff08236219f37aba267ade84f6af352319f3c5304b1dff09a96
-TAG: 7b1bf69149efc480b0b5ec2d74063bb2
-
-# DIGEST: 404ec1474e5cc319401cb6917841930d
-KEY: ae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2
-AD: eaad409ae02116417d
-CT: 6757d23ea24d7c45cb11705a98dd9f24be0b9d1c3120bc140d8c216ba831aaceeb9bc5f102e420a4e141706f812d793059259bcc2882d7155452e93ff4cc8e1b006b0523024de24988681f14f8b7c4399c586d72c5a1124c4b5b4e7583d04c9bd82b2b04ddf1b81caa2e8392b5d06d58be3b21ab7001cf8de02915ff3e83cfa8bec1dd0ef8141147de698c3c35f98f81cbc314a203ea
-TAG: 3e61331729f00c9201d4120813fd5017
-
-# DIGEST: 3bda811f1a0bde14458d547ba2c7928b
-KEY: 9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a74
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae0
-AD: 2116417dae0cef457b
-CT: 6b08b8a7e877438ac9af36ecfb1a577c59c6697d5949b527f00e3cbcefc01983f8ca58c93489e903bc2fb2df14470848440dfa7a58d3ec24abced8d729be4f414b3645d99241fb8b26eded8ba4c4e78909d85a5b4af4af02ada1f6a483262fe57ca2fb8459d52175dd32df021b56aa7eb6c5fb3117723b75a16812c3a1713f5d82b894c800137be6afe1dcf3ddaed439997ec308870ce3bbded570
-TAG: fa52ae48b96197cf3d01284155e5ff51
-
-# DIGEST: 23adf4ac47183c50429f7f288d1f2e72
-KEY: b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae
-AD: 0cef457b9e5e16dcc5
-CT: 6e5de1b6e56f82df47dfbe44dfcbe79fff2b160ca96b867662660e0ab675f8af700c62bfb81b8a71b723bfa76b0d6b0e31e2bc2ac3e84ea5d18048d6004a72df6d79f097960891651cae15bf750053d87c4bbb39948089bc3687088af8329bd5a308f2e19411a5ce326f0411f89d883ed3e01f1885910940a1371059e7ea8552d8f379e0563d2a8de0a5197d33b33335fa27ab5d1c00dba8640701af250b3c4b
-TAG: 2299b6be430023a1e1264bfac3480da7
-
-# DIGEST: b9e89fdbac6bc398838ff244071b8a9e
-KEY: 0d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b144476
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e
-AD: 5e16dcc5b6f25607f0
-CT: 7eda958efdfec21f278c9f0fb915e173a97aa37cc266c6ccbcd0000be5d0879815635464c04a688bc46b1d8f99d018112a899a718a8f941c1ccdd1ebdd0df8349bbe543c620c7f649cc4af84b459810c7361f19995d4e8dfa253523a2d55ece9f7996a610b38b4e0fbef9afea548f7174fef8a50b2b5923d11106ee588a0e696bc811c98acdd9b3aa896cdcc9a5b96e3977971f6decdb1af8dfc9437427bdce62640d87226
-TAG: 50e24daa826873b682c0d8158a3f970c
-
-# DIGEST: 014ed695a644f2b8e9a45b9d38ed202f
-KEY: b09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6
-AD: f25607f00d033fb95f
-CT: feeccf5b760db1668de88fdb368caaa443fbae3c6064d0cf681cd785f79f06c3ebb20b429ddd68e0a1dbac2b76dae39d8c84f078fe8177020b406eedf19d4fd89bbda2247a298f4914d3fb2c856d4ef57c76e9fc4a0b6ae69dc13d5fda02468b71337c5d508adcba33c9f586049dbf4fc743776ac6dd3169feba07afd70e9e03d2f10da49b79882691b45f0531781a80b5bf4b8120803336fedcf6d53a7c0ecddab8dbd140d325906f11
-TAG: dbed8077c0ad861018f2f6f57dd7da6e
-
-# DIGEST: e5d8d3b66ac9c11de3e3ab6d0f88e17d
-KEY: 172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d
-AD: 033fb95fb09e4d00d6
-CT: e10dd7b0e0c7fc02e7df875921ed537437fe5723fbed68e24b96d84e6475d7558f773b6d765016b7b8e57368567ce4fa9de9a4923d13d30217b4202721fa7c8c2650ff5a3edae11f112797a2ccf10afc07c94c01783ece6a509efbd64d220f22c0454c219a1b120efeb68ae96e251d9a4a7fd4a51af10e96e9ea6b3e190dc06be571992ece0c9c727b949870a8331cc72985f6fae694511ead3ad7ddd3a7f36a3502d3f56581cb0eec53f6a9ed2356
-TAG: c3b4b0c50c4cbcd133a995f5eea4cb7e
-
-# DIGEST: 4ce3eefb916480816f66176f39ca1f83
-KEY: b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3a
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb0
-AD: 9e4d00d6172e780ab8
-CT: 1bb00f63b102b576f7dfc114de44219be1ab8bcf2ed1b9133bcb8711f9d0aa88eb4c8540d2c9b653b740d55783d7cbc05f9cd8bde224fa4a601cdeeddf193536f625ca9f7292d974f9cd2db5e018c075f3f66ff0d649f13d60499727c6836b16d340fa9e0ff0699b26920be3c273172bbfa8ba8b55de378299e14d8dfa7f5acecb8edc907a93840264ec6c535c180bceac0761dd16bee00badb777530f8b8ccfde928a1e4eb73aed4fdfdea8e026ff0518e2b7f5
-TAG: a1f60746e414f0a2e6c6ae5794453a22
-
-# DIGEST: 3a9a63597a0f95983a9cfda265eac176
-KEY: 7a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b18
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d617
-AD: 2e780ab8b700433a95
-CT: 72a283919ae3d279d7594683dc7680ae93298ab3ca887bca22c6db5def3570c270fc47f973873192b410d695d547d9909b65cec57f68528db8d1a1a05aeaa29f5d1e923e4f7132391ab3939be05d2cda1118f58ec556e57956e096b7c11bfb7b39ad1238cab04afbf789208245837aa2d709ca1f0cfbb3c805bef5e3562ee9b5ad18b8705e3a8a477ab06d4368f3e43d70920659a0cc761dbbcf5fda59f07f699b7016f97bbfc72e40a62b7d3341204be4491209d981248f49
-TAG: da7670699256f86330480ed45f1e171b
-
-# DIGEST: 4c4516dbad34a518693559604d55d34b
-KEY: 0f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b7
-AD: 00433a957a741c9eb8
-CT: a898b0660d1f528b18d544b5e5f95d1a20e9298efd0441dbfe599a537e00b129a46fb19f7ad0b297653aeb401759b58ce61b8e32632825e96bf0e8a66cb95ab2f49afc5707416369b47fca12336f7f212dc25cb6da620ef5d63b8b69678d2d2f3e5bdf887a29c6adc77bab3f0331f5aaccc2b7355c72e2387f2708f4be00376146b8c7e690e34d4a05aacd9bc4392b273f86e2953300eb9eedf855d25030c8004f04aa111954c093dfad15e63becee6a44ec679b69658c674ecdbcbf5aac
-TAG: 42e267ac23fd1f20b53a4c4be206bce3
-
-# DIGEST: 2db68c551c43ebd1b18da8518f4abe7e
-KEY: 44769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a
-AD: 741c9eb80f2b021b14
-CT: 78ccd36c0cea3981ba2b7a9413d7f96a137862ada5b03a28661e0824e5a425fd9d34a861969f84be8d9d59e356e0fb5fe42de6528b43103c65f7ae893b21f1a68328eee0c5dbbeded165621f96f59eaa6c20eee20b5a49586867e1e019fe146917b3bbc29d8627e33c409c9eaad1e4fae0c5bec59d946daa4cae02db5eae991de078771f005b82c74692273af45a18df344c6b9637308c83d4be35c67e3c22d83f6dfefc238cf0b6e1ee04de4ae02f8ac92139d31b2f2211e6513a9704e5d9c3c4873e
-TAG: e0271c7e00c771b0f93c08af17cc0808
-
-# DIGEST: 113aef22861952d452c541d5c230765b
-KEY: cfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f
-AD: 2b021b1444769da00f
-CT: 87516a2d342a6d11ed739731b8e965a8acf9cf7b1e0dcc535b7b354e4ef208511f1c999f03546e24d0252c8063c722459b878605f596b1ee7bd0395963ce43282355a7564cf28479959d587f48f34d2c5705a6b14401da25bbab15d3db8d074473cd6ff55299333c6be6d832ea71ef1738d449fa835ce589cb179495d36bc537d841d6ec4421bb4743c404bca6a6a5631a977cc6fc85c0a8b7dc710971be01298a2f554fb3d3db4e764a55075da446ad0247c4a9292ff6b52526227a6c7360dd4f42190592d14719
-TAG: fa9e556c2d930286faf2d68226b34176
-
-# DIGEST: dd36b5a92d416e3d2dc4c15407556748
-KEY: b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444
-AD: 769da00fcfab0f5f93
-CT: 0fe4c705744b0d3c2603148393f33cea2a2603fd018496fa8a4527bd4037c17103ed2601ce721d5289b317658d21809fdedeaf5c1dcbfa758a19befa03ab930158b252c5d3a8eba82bda3f6655029e0dcfa4ce20da1e4e9a7d3a90af67a0fd96654982e4e75e009b94dc7dddcac2a766cb380e40026b0ae7bf25c5acc943b486c4abec847c12068a26e467b5de96860e82a4f1393bf16f1f24db7fef420c327f8af4140e3b273c12d6391dd273feccbee1ca0ade55b84961e57dfe6f33407db86c240c16a866c16d289a93afaf
-TAG: 4f14190e07bed1a0e3bc236948b025e6
-
-# DIGEST: 3d94d12c5dc8424a058de2a998ba7a6a
-KEY: 5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249c
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcf
-AD: ab0f5f93b511060c9c
-CT: 116a50e2eb4d1562c49d484597a53f68ed17200aa036dd8926728cdd25156f94e94c0207f97e37b1f3f8d3a57c3d92f3c6d056bcf63b25eea79fe4e35a40bc566070dd0dc3cd3fb017e0354160146f46716c5d8242ae6c60a7e89ac0a8f5e3ee278e4e10f3f2d19c4c1682d7b810ec8a8e7e7e2bf9a11604ef294f8571a7d8998be0afe8326397dcba7d68284366dc2b82fc47ebe9abfe33a5af263fb54a96c8d0b8609098110af9702c3be43c0a58951fbd56170d59a1c04cb02861b12c30f087508d4f37690c3fe60c0e2f76ca53808765
-TAG: 52df5d8f215f382225368a29ff204701
-
-# DIGEST: 1dfe99b6df485647f7d88e08cf56163d
-KEY: 1b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b5
-AD: 11060c9c5f3aacefe6
-CT: bb514ace66239002b23fd0643673d9e5f601a021d9cc444dbec91c11e9e79a4a71b84d2b514b98ecf62c8164df84d0fc10b9149c3ca88c1575287121608ef7b8f94681384f705e9c5fb59604378791ac2d8057bd9ee3175ace3355c0cc77440db0e31d7d5f88567e887ce5b115815ad7321c025e6d176c4f7bba4686e223053eca2417a78ac81f2a67b522593b72060a7c0339597b06a6505c19c00cfad5dd76ceda73a46eeeec6fa7218acd9479ea032147ac4f59079943dc31212b6ca8bce30f66d2ae28106825bc6c4c1a5df272e279d9f8adad9652
-TAG: 371ce3d96af1fa0514b0b0ae7cd1ad40
-
-# DIGEST: 501f8a4a621c5fa25f3d835b00526ff6
-KEY: 3939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f
-AD: 3aacefe61b184ad246
-CT: fa6b8e1532c01196bb220bd64f4f9b66a69f50377cffa4733673028acc5bd4ddfa195f9a0b37a61b67d0a24ec30cafac97203df5c7e5d8dc3271cc97242a4c8030b7100667c135a54a53f5cd4af9340c0726850dec7f1a6d48851777b2dd6992e1b2502837dd84c996b1ac41f0cbd2c69d8fb6c6a3550d9cb3f3b6a8e1809733c97f7c1bda88c691420b956b5c81a59bc5bba327b35c302ad3d2d7d6223fba9a5b176af7f904b6a8f300104006bb3c9a9ad9912740643da61c022508ce243171e314394d958fd2c012b70b965b82114c6c0fa879e661a3c5ee24161b
-TAG: 75af38ed899b1456ee12924925e8152a
-
-# DIGEST: ac835d341bfe7039645ca14c05d29b3b
-KEY: e97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e7
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b
-AD: 184ad2463939ed518c
-CT: 66cc280967790c374494a45d93a5119d8368598402f98dcf2288cb988d1e62641728d3380cbfdddb5400aed37322ac8a2ca4018a3e708f7b54cc39b2a0c50cc5ff2da5efa31f1908f417d966eedac8ebee9a6ebc30039aaa3526f8364f68d97ab0ab917035a933cc75cb856efd7ec5a9d2eef4e73f1ee39f185bdfb01aaefedbab39a1e57fcc90cc18ea721d62f7273dedd0feb2ec72556a2a8412ae446dd1bca94848779db9ab8ee4ffdf663a6469327c8434ff1612303dde92c9e1c78d64d99555b3b5cf6adea1e170f17fc8d369f59c4b4babcb3ae3b4820c7a4a41905e3945
-TAG: 84a43ae2f0537f0ae458f8a84eb51fff
-
-# DIGEST: 4bcc5b6312a793e6874c8ceabd086182
-KEY: 3d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025c
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad24639
-AD: 39ed518ce97c3fdd29
-CT: 487e47b1486bc32e33aef14bf56fdf578a33be5e09849198ed2f91a7c6905917106434ee1bd7b5c95c266ae371c075aba5f5aae9c5a7ae3e39e3a25a1cda682db4295e473be862de1ebf9db7244e3139eec37e6e4e4231de7dce06e5253ebb429bd4b22fc7cc98bc897caad630adbee281081e772dfd29f69cae620d89c2cb0f78a2b1980f8d83d9c47b8f43ef9a73775ff8188cbc7abdb1759383f53158897aec10ff1c98ce469fe67551345b10d7307e1b1b6a5481034b0c6b2e1d541ed1647b9a217d3790d237ca37cf47c4d96b0abbcc78670795f9d6c57a059efb1d0edbfae33490b33b
-TAG: cf4324536fa10c0510bfa6a26b6190f2
-
-# DIGEST: 80b0cf21fcb7ed153a787592150af7cd
-KEY: fdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d29
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce9
-AD: 7c3fdd293d72afc09f
-CT: 9fead102515d95f86e178070c162f71189e7ad1dde31dad503c33a5e7c702918abe2b9d2dce5886aff412ca2a6f027d719edbf837949906d80e5545f29ace27a2804a149577e03d0181971bb7bfd64d82d4da1c9073a617fe7c265ba3e4fac3d1bcb96b5930f46b609ed7abd001bd80d6993976af60873436c2db169861db6aee7de0d59454461ce5dc90299a3a80a6eb0f27fbf6d071941d95c7fd962ccfbd8c60f0c0227ad3650458ed794f42160edca41cb805b7c83eb626b8ae625615657bdc240234b613fe8551a93080b17e3854bb98c166661616137e507fb293fbca437174b366f4f1fefca7448
-TAG: 38146f2b814ff4cd6d9833a7e792a611
-
-# DIGEST: 23bfd9d6c946dcf8d47e6ba743c3781b
-KEY: 249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d
-AD: 72afc09ffdd4f41963
-CT: 0b03085e0f32b9d882b46bb9b5245a44cebe9647a0f06a5d7fb48b5b6af8c875b1cd524a66f4b08df03e32c612ba82ce609a3fb97c256c312088acd5c635d44c52319254a88889f2ade388200107cf42330824552ef0784a8a4578462b383bae5a77dac532a0b169dcda545c8af78627e12cbedadf2039626787066a1f7cf420cfd8e68abc9bb6ae5aa7d86a10cccf96d64b0ce6178c87de22b214a041ba5d5c9fd947d65e4d1d1b5b2eb23fc48367286a179782b3fe148101f3c844c5b95ca3fc7f0b8d0d36e06b1cfe9735ea43055ce1568a8b1aadfe9ad775bee4eaf34321e4b6d164f0dd70c7888d8187f25763f1
-TAG: 77da84c5c44516fed499667df0368553
-
-# DIGEST: e9fbf8746d61a8f52f259ed2e38aba0c
-KEY: 2e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be5
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffd
-AD: d4f41963249cd299b9
-CT: efa252251de3aa0c11c023d881d9728ec8715722661ec3e531596d4c1609dfab2684b4ed484f290a83b4a2d6763f597c6ccb6237f4c1a96e78ca4cfb2f5fec2a4e7741aa32fbe935672792a14aa1b07a8f9d32b94af0679654e2fa05d36dd31b37c65f4158a5e389f96672fe896fca21dc5df5a8abe1a43d49003dbc060e65e3c7ca5ff79489f3e7d2ecf86788a6655a369e517eb1109aae205e6e8ddb6ade98ca7aef3934d6254a3be8a221e635b16e96d33298bf0340998c7e0fcc0c3664f4306fa0d20244186f4fae97b97e2d6aa3787b91c597da21659b64cf962bdbfe858151547186f30fbcbff3a694a5d11d1bd99d76e376
-TAG: a4a83bbc54016275b2b65aaa1a544b05
-
-# DIGEST: 8c09a0bd0fbeee7211c138c837bb1f09
-KEY: c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af1
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f4196324
-AD: 9cd299b92e55ca24d8
-CT: 07419c48687a9de15a007d5521253b76bca15be276bd7cb0c56ecb74b30f17b9d697bb189a3bbc82f0f944b84239fcc177fb64c41c42789082192457bba0460acc58263f2912b2c6935cd67336ec8ff501aef40cd35e6f4f66ded303824580615347bdd8d4511303ae5f47b20c932c0ea2270de1f33822eb7e7bfb733375c3869ae092ddbfe792d205b91ee79e2142a210c8fd00a4b25b1de796bad9fb686e3335339c56e4925bf04490cef35fa000dc6a78815e8a58b02800483b9264e3a12b88cf8a57864b164573d732a2de1cd2094b6c8d8c9db0f7a3a3854db93bec6410b9c743a4c312de36218efa1db0da76579be3d83a93bc68d11af2
-TAG: df8b9c147798aedd893fb07badda3af5
-
-# DIGEST: 737fc724a7ee589b475d3a46333b6528
-KEY: c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e10
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e
-AD: 55ca24d8c078c49f78
-CT: 167408f770548d8c8b471c0c04033359d67f36176ccb701d859c7b80ce24bde453c93eee3908801b967a9dbd6e8646600cb97ec519cfef8a2eb2522f440f4cc3eb4d0a4f6a00af6053482bba54f4a7ddef2eb35f585ec46381750969ae131146b789b87fa429d1a2492ac40495c8efa9818c2cc33a79e75793b3b4b94ba491a7bafe6361b48b224725e9cf8c551f0277524600048969f19521bc3b9181f3ef4cda0849e5ba72cf7d28cb8bfdceaca11aecdf1f3595ebd443bdf6b357ea4b58790af3a280d2b19d4cfd1e216e35dbf0a9c7f455dfc0b64da16f655795a594501fe02ad96c1c4f4856a16305cf5cb0432d4e7be0a9ca3682089ca1e09a7531ba
-TAG: 43a3e7f67b609aa4516173aeb2690848
-
-# DIGEST: 642be488fac458617b8590f7281e9dc8
-KEY: 025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e8
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c0
-AD: 78c49f78c7e713710a
-CT: 22b6404c5cf46935f582ec36056a58e5c6aceecec038962f61305f2247c0e20aaf59f5a9cff44bc20ae2d3a49fccce618911609ebd01686740da90fce75eb01bb08dea952a4b19e18b3e124c9a10bb4a190f2b6c469787b1d8a5cc32e11ae99f26d238888a0a6ffe8f605ab63ff8304c8f2467dca93fe840370a0898febb3dfeada3c91086b4705a97c60b30d96ddc2d9cbc17a132ad28db7d0e936f53346242c1e8101b8adb9bfb177785d9b6d547b411c01f3cf0d387af911b82fce97d248d72a092c994df7d93024b9c346c9e8525b0f9719a64a7b0aa258a976c69bdc7a3fc630200dee58170e640b2b28d6e75f79aedebaea4d7aff2e4bfaf9e2e2f057e711af60d
-TAG: fea411cfdce04491a361893b86286c1b
-
-# DIGEST: 1c7c31cd062040c8db4f188c45170e3c
-KEY: 1d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7
-AD: e713710a025cb8b9d7
-CT: 0e8fd3257650c5a9255224a494cee1c709f3f7a2aa467da6308f735ec4a07cba9cf25d49a78ad6219c197bc1deee3cf188230248172b0a33fee5e7d0d7d20dd010fb1fffbf723554d3ed8c9d630feae088ba4af2b58755d3380be95120060e1b6a69dc795540e0880566f149085bc6326176684d563dcdc87ab29a8d73ea7959dc2d10a089f160a6a3f9067cf669c79021317434e3f599b668b153b6a3f448ba6f391e4e089f7223903a4b974d655d2f9b5ca5f8d6d4fb84061510105e9bfca0d1aba01403d2acbd027446c46c787c767efb408fd646c8db0381c38748e6ca0966e725e08f207edff25fea6ef469f2ac7c08ba21ec8a796f205e0c4ef8eec3bb71b9152c48bebf3bd0
-TAG: 43ee003b1fd38dc56e23bd81a515eedc
-
-# DIGEST: e1e6201d23f24095643c6977d56205a3
-KEY: e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a02
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a02
-AD: 5cb8b9d71d2989ab33
-CT: 1908c9f4b0038e568f15e46af6ccbd5d798dbb08c1275c7f757df28a403e147f1a90cd69a3462e7f4a1681922478720f62508f7259f75948431cdbd8ec73dafbe666688ad18302dd17ea7fb41e0aaf5043aeaf041aaac4c389ce4a4ffeae208bfb08f525d05f4dc0376651e999cab33c0106dd21fd75532ebd64ac942a6375f74a559543b981fd20c8f71085b38ece0d39b79bd8115cc5fa52bf4a074e1c72885573a6aed0fbf85fb1367dab0cb4e9f61c97674bca43633ac0f7cadaa6ea5a06700750c103df4164467f6e3a4677aff0e68da74fbe37c1d6fc8b97b5f19b195a6f782865ef6000017b4b29b1002d144ebf1cc07a96c6cbf339601d9d2a7f524671639191f7e81ceff4e8420fe68a
-TAG: 01ecadfc181fb3bb47d4d5b907054f16
-
-# DIGEST: 57210154c6292e0847d231ad76eb6168
-KEY: 3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d
-AD: 2989ab33e978c4451e
-CT: e0da199b8bbaba1e440abcd66e03d85e8d5bf78375507af506ba5015877c01d0f19115341ebfa1f69fd05c5d999aff0979c101d82651b90925cb4b929f51d33fb1756d6ea16e445910a09ee8ad261042becf5e54d56bbcca2bf071445826dcf539374da414628ff4e39177d5cde20f1dd0e38db05ba1503820ed6cbfc663835634b902434b8eb650ba9056fbdcbb441a071234bef49f58ca7ae621075a773e0b7d92447a98d629c8d8ff092d7feec70ba50cf61bb55c1755f9f975e7b16f1abb12939ce0f1f75060421cb16a5b6201f86339ccb8bcea1c88bca929d0f5f9d5433b12cc07de858981ce34e94e1b71802b558b82148facc5e03d337fbfbbd63a01a3a349a38f3aa35d6232edeeeba90e107d972b
-TAG: 48374614d65c500cc3c5e2784be89c05
-
-# DIGEST: 6f6d56cca5d872205a57571fc564cf72
-KEY: 2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a7
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e9
-AD: 78c4451e3be585a29a
-CT: a1304672e5950c3c4805bd1556a87debd1da675b727d0e3ea29ab7cbddd523d20a0bdfb39edb2ea7da3d82ce489defe5516ea8e08b627944ddc648f77eca01c1b9b6e848c60dbbacc6bfc16ad82aaca568d646407be98710fd8d16785c4845acfb9e583493b8cbb170ebba677a160099954aa496aa9cbe5dcffca907096b9b57da293eb86622b4b6656241fd47e486ab541b9dd4035ced25a5e3c40c781b4b2a9702f96d567d116ab0b26777d01772a0f86bb4393fe09fb7251bf0e722fe27de3a31e4b8bde14bcdbef78d0c0611f7f8fd992d6699603d0fe267577e559ac4fd533b53a4de901b7dce10ddd4b672f46c8e9e7b461453a7572e20baa7f48be990aca2616917da40571b6037d056ab955f811d5250e5aaabea
-TAG: 9e783043a55aa2f2252436d1474bab8d
-
-# DIGEST: ac37709ba1b8654c0765c9bd4ab92c3f
-KEY: 1e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b38
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3b
-AD: e585a29a2af12feef7
-CT: 3cca2772b518cd7418a047eea4df2a4f98447658301d64c0c83cb7a2dc2b83cabe50f52aaee0db53d97a65c61eb0976a0172ee9d2cd3cac94d83dc3e302d9ad6a55170e3bc0bc32da50beb7f3502d464ce763008c10dd80edffa49207bbb0949874f5082da43591f78017b1f522b8683c02b1b62c738033e8ae2d9854d271e667275cc52dd40cc4b13b8a51249421c361acc7ab1c802e6cb3ef1e1a41344d75721a886c43fd2b81ed688172bdf393a83d986f5026fd296a3a789417904aea5c796df1bf7c7ba61409639aa0c244d2150c94469f7bab5ee15c93fdbb78dda98023ca752209cfe91c5748358d5c882139c6087d6e2a4cd5fca929a6f28d69896eccc60e4ea191db090c25b3a283085ae2950e79a5721ea9f42fa7696984e
-TAG: c29132dbf866d880af4bf0301f936369
-
-# DIGEST: 4c53d119a5f99d33bbde7e15e076f5f4
-KEY: e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2a
-AD: f12feef71e1063b0b4
-CT: 9ce6bb2a8165fc84815d512cb79b5e6bf95eed0033d982af640b1a48c3a6c898e5c11b016f08f824acba3da4cf9b4775a47d0ae4e53f7fe0bdfa6adf0240882cda625a387823e20dadd940b8d9e84456ced027f7844e3ac9c72f150eb5a422793128827b88843c76101bd0c8319ce6cb760e4205b5833b34f643de024a7872c4a76574d19adeaad0555c4e39416b4d1ce15c9bb26235ed8e705a1ba13052ac366094abbb0c441e508a26c1ccc276cf6c43738b786572ac43782a9493ad47fa82639dc9337553e73ae0587ab01b6f5e928dae0a1ae4393b780b8277cfd5cc9f358bf69ac21f4367a2a3711e2361927b7b25469e65e8e2c29250c2239ef358e2fb41e90a556d7f81c22086fbc2e16e23fad45c0781b9464fc39de6ce3821f3c64dec57
-TAG: 70f696d5c28e546c2df1ab518414bafa
-
-# DIGEST: 33c72019b806d647531a2df1517d13ad
-KEY: 04bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e
-AD: 1063b0b4e6e8992003
-CT: b2b6753787cb50b8209ffd5529da02b64594159264f69ce7ca0b2e5f42d9eb6795e95c3e6baf57a3b7f5f7c260a428b0d47b3a4fe2d5323e1d2554014ee79b2867d6f954e1dd11b6b8b0d8d9a6088a313672f6e5c0699c8b9dd013cad4530a37fdcf7a813d3a71b7bb87ce2bdc3e6fce237e26e0899eeae031d808a6bf37cd4ab88466e20dc9081484c1938829626893367888adf5fe7ea66e6a46457a0d6980a2bd96b2dd2c8386620c93ad6a30e904bd11c3515651ec78346fdb6c4a3d61ad696741d55da980027668c016f5a9f0c991a1d57dd37900e51502f42b1f3d7eb865fb3836a644ca0ff6de2d147d89146d710cc7eb01c025950261db300b49e7607ff8a0d6c5bbb245f82b684ea1e678f20ece4e05eb2fafddd8bd71edde6f3289d36354550340e9
-TAG: 1e2fe20c38aa8a9f9226b0b8d41d8102
-
-# DIGEST: 32f25db0edef93b50a9104b5fbebe0e6
-KEY: 2a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6
-AD: e899200304bd350813
-CT: 9fed83de5dda9e0679e98790bcc6226976dac10414751299af304c91e40c91bd239991e02a3ad6d3b14c84d32ea2c39def6f8820050c3fe9a21bf4e82d58086330361d5423c3203815d5208dc0f8d3e774e8875a70fe3c4ef09341f9963c078844a67ef69bbf66bfe939da4ac57f9d5f53b06a5c9d4d3defb306966f15be2a6d431dc521a5994070546cdc35d552a5e9f582110c39f79d77fb4b1ced4fcf243fcf79c55cef9fb0c3a0a66cb36dc822a68f6b0fbaeac859acdda1c9744e690c7248f93358c989265a3b45718bb654c08f1267c57a7014927fc29032041143d102861226ede06f705c19da6d2baa142996380b46c0aca0e9f103bed84c04e3f56cf2f6f983672f8daaf4222513cddd2a2064829f71a5163150a5e40d38acf7a3db30b4da0f3efdb835c43d10f3
-TAG: 7881e996e03efe69d69d6c3da908a4c6
-
-# DIGEST: 2a36a608b469ed2cfcd987016e487b06
-KEY: c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304
-AD: bd3508132a027d1ff4
-CT: aedd430e100b7355b832d0b9db0bfa7a541527654f19f5cde4689787f3c705596bd61b5406df8c78dc833270543a4000866dd9896e22879cfcba25e7aec57492c2ca2f6dac77eb3facf66ae1bf12b65671f97e4a6c7064509699bec7adbce0e0e3f6175539fd35a9963aedca5756af0daacdc604a6e9e4d3f7f537ae8f42ec5d42168225741f309d3b0d8e912d77207be843799ca2d80cccdf68963ed0941241d6e306aa4b682c27302d054fffac44889f04e851c772697e3ae7f06305c92c229905d6b8dd9d7b46287dcaa0a32ebed120dbf58ec533ec4bd6c360eff8ead7b6dc38e53c3d4c7582e0b71415c5fcbfe170beb7259ceaf09ae450cafbe7609921c46cc2e44368f6026be8cc0aae797dbd8766712e5b5da85f83ee55c715883cdb9c508a3eb36453ff51571e8d7a63a71091
-TAG: 044b46de9c993cdc81788fba305f9eaa
-
-# DIGEST: 16f650bcfc7127fcabbdff3f344a0c0d
-KEY: 57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a4172
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a
-AD: 027d1ff4c047b3ef4f
-CT: 3f27ddce45f3b828b3a212053c97da0f14face2f622d440a99596f900f519c59d95b5161a9f98648a58356634bcea4f3295af03cc4e947ed63b676a3e9c148851fe96d805b65552225a9570ee56e60d22fd8f39f39070bf7f6d666fb538fed96b255d022413b8252c414a17ebe49b6e01e8afec0cded8942f52ea7ce814aeb5bed9e883799e3951e809a92c3280b24036bb08f72201e41f1c0e6080f10d3b71e26e29e0209e18769475a2a52bca05a66735d8e49bd96f7e2507dd33bd597e24449aab01496cc924850ae4b6958bbd4e4db3810933585016910cc9f290487626acd19c33ae70c7eed3477790959ac8117cec940490b586258a59bc389a4e03772e821d84a36579057f1d9648ba4529d7ce35b4a189c69ada0e152f32bf9e0a197d651ab805831322ec52c56bf7d6fabdb6a758ad1956d
-TAG: 163b19ed66856084833dc222f2c3c925
-
-# DIGEST: c792c5b1c4fbb54909c5a4d205194c57
-KEY: 4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c0
-AD: 47b3ef4f57a74706de
-CT: cdc1da3548980c176fcc489d4bae72ea36db636caf6e6201c2eb8af5968d6aa2bc8863450514caf27112c9ed4c08148c75b6b258d4c0dcb55b6358305fbe15ff6ec435947ec1f567fa8f680d0f75a31a7b4a96013b6b0ceef3a5ce95a7799e50434f3d702ad886313ff3e8b9445efe59372e10d8911ce6f0d2e0c1cb3de3340912def094a55c0970d48fcfd728d6ba66ab1b38018cb56507b0c3e462921043ba15069e9553ec04db8e8a329f09d52508328496d8d30d0f82eb85fa8cc7d63119eaa3f17107a05834c3903e2f61804a7d89542231868d943f1d73502badf240d3de7cd400950469a62a242406ec125cfd92805243ce434194a104e8788f4a1410c93bdd68762b0720f9b0ed3bbf559c720cbaf66dc90fa26a4f1c86edf4d23e573908fd2f8b465cb4e30fd19af5755c5376e60876d17a31251583f6
-TAG: 62e47276e4b8c8ab74ef98b6e6253462
-
-# DIGEST: 08f2d340d16d63548c1d29e52ee8cc09
-KEY: f164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57
-AD: a74706de4b381c692e
-CT: de4706e5eafa9f448642f34fc322388b4d6f69cdd0ce20a87655e6e6343f0fa830e9517628571f218cd9cb06a5501577901ba940be24884170f789da2b38ba7f9cb8d42372b445297f47d34e759d4bfa2fc843fc52059c1ca170da3f00a9c241ee87eec4c95d52591d373fdb73f96ec4a86df3afc4c6705b8aa92cf287a94ebab80168a5b5c0a96766b709ad7da2b365c78ac6c99d44c76127a86ed4d3dabef7e3a744adb7368913cb0b4cb626735ff5e9eab51d285d5aa72c78c3ef45a5359d51177b4c009f071a50e53584c450a0aaf8de3b65fc915c797feb48c0c533152a9d93cf3a60d99e5bc02bb7e2b461b92500cc2632ba60ef2c31d2aed8654302063fc2cde4706d9988a9539c28ac1195c0d30b1c9c132e797fc1caf19e62bc3f9b4ea25a0b1cae86caa6477f808d1e9ac648bd44971268d9a9e534b6719606ff3f
-TAG: fa8e48c16ed080eebb362665a9e807d7
-
-# DIGEST: 71ac80721f38fd7d54a644765bd1f48a
-KEY: b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a0
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b
-AD: 381c692ef164101b89
-CT: b68f2908c386fe241571edb4766ff64ddddef9ae511740ba949b8adcee91c5468d4b87eb27cf639ea43fb56668a732a6bce74cfb2645dbed1c5f39016b82e9f471bddeddaf60f5cc11ad66d56b586466f88eececf17477cd86fe71603e20c486615d4ec960da3860a2db4d2a33c815b5cd4db00d666d1e2a59a09a139a5f94f9d152b658d0b7c3dd67f799fc0e907489d70d293ea16294740c9efedbeb33f0b2f821f2ffb5777bd888eef29463c625482b733539cc0d0691de6b59daa9720998f04ac6477f80db62479d92f2970b4bca34aca11d0ea1dde560b0609c50460ed0e3c9ce9bd0dd893d84c47345b0704cdef9832fe720b0c054dcf9a0a6a33b6d69d3fc4b398d71c2d4dac4e480a73df21c9235aaf82a5c5985abec1a008795f24894bb326048b91b0184e1a02cc8e23358949f860ba425daba75d5494e096972a10312a36dfe
-TAG: aaef46b0180e51cbc0d9b73145601c67
-
-# DIGEST: 3f37e16dda400dcce23bf4e476f6a97c
-KEY: f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab6997
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef1
-AD: 64101b89b476f72b27
-CT: dd955f6ce7c833fbfd6859ab34e563dd685520b4ca4a2b21ce0f462e44738a5090d26b5e71e450015f5b0e08902f2513b9306d33bbd4b25a9b5a00e66935e8ba6a1cbd01fab93846163170f07297485cbee2a4fd1cbb99cd864fc281f9e35626d9f936e57b8376225b656ae7280e2efbf1b01085e5f94c22733ed5db9dc061efeea59fbde8bb764fbb6230ef6133208b3128c1a402bf385113ce9a1288d4791cae37833270af8e83ee5d70adfdfbac1033c4642750d67091d4bb4c222771bf66215273ecf68767aeb5d8d7fddeab6d73140aee4ceced826ee05f55b5279ec647d4691c4719b49d1d7f8afa4e7acdf888ef3ad9846b21e2a4705cea9f3c7038b91872373f7db2310fbfab4707d067977d79233e8c8d6a8eb113003907397f6d4602675eaf5065be12ddf486b20cdb014bb07e7b390d41fa699086c7d3edbd6e1cbf2e705fbcf099bbdffc
-TAG: 3ab8f56f918b102691e8193a51d58683
-
-# DIGEST: 658412ac7dd60a93ccbe73c9d88e0ecf
-KEY: 67cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b4
-AD: 76f72b27f06f520c92
-CT: 25b8ac08fd2ea4e9cf3dbd84245f007e32024c8b257e1274abb9dd144a6ec3999514c07a389152c603efd9e2bf8d742c5c523d15047135f0b0677ae9c14fb2bd60a7757cfc6818291c72e5479aebbd7133ec2f0e31c39e9405ee6aa1b60835db9f9221768dd4446fdcacbefc6a2696f87afe8ed0cf5b09825a07570edc2f7b3a1fc1342704b62590347145977d0837003a5d9c19fa2888eb0ab211d7dfaad32fed7cb51e4ac9f029e650e863ca165f4cce99c8b28df78ae73d22c7e4d0d6fc75f2ece50d8893f3a73bc92fa69e5c9576eb13f34da976e1d44f9fa1814224c20e057e9c57ae5fefcd5366ba8176ad4d468a4131541c9b8a3b20f2207dadbcca8cbf4872c99a11c4ed949d0f05d90087050d01182a94364a845b5a23ab3efaa51589cbb158df534299d12af5654002f1dd92a19e6958c40bd7e2a00cb213c75050fdc017190d17c7b077bcfba80f6014
-TAG: a4f7c2bd8805e03b38679d1fb86810b0
-
-# DIGEST: d58f377d8ad6c3f53f39f38c0b2b0685
-KEY: 41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f0
-AD: 6f520c9267cf71408a
-CT: bdccd6103753ee7dffa21d7254291239015da3532076b11bc8ddfdf94408feec7b92cb135ccb8da8bbcf1a1937d942d9d9f9acb009ba63e3bfc957e518d3ae36bf839c073d9883549cc7c826b91066155f798a30d1fe2fc5f8904af160e359dbba7de774e3ec468d6924b3774b3ab753bf2363ccbfb01416d7f918f16b4195853c19647027b617250766d730fc3e50d0b3710e965c829d5366809d91c1fe35ecd35c17110744b842ba6ef81b2db7e9bd992ce8909da1ee57d54abe64bb50d6265611655ac5fcc574180072afebe0a60da3fdee42af02552499d8592acafd8ab0fe63a0235d297b01fb4bdeb9fd94ad52ffe1e1e51fa6564b4c6f082f0819f2da718d6bab23ba710ed16fed50d8366ed950758ce04ad8b927e07cc4f24fe03ae21676d6d29a9f70daa29bb163d9f4926683447ec19f58fb81204312a3554d017478a10c618e1da3316288fe084d70eb7496d0696e
-TAG: a2b7ba032f834f83c7bedd1659ebfc85
-
-# DIGEST: dfd840fe0d59eb9b05884455fc8f2644
-KEY: 877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870d
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267
-AD: cf71408a41729bacb5
-CT: 34afbe79f3d6c66af1401d9ee8206716888d447afe33ec0dcd672a10fd2b85d7226653268172d35e4ef236ab3026e95e96063825e4e3751bc05dad84ecd9991912ffc95b6000baf02882629c144dfe38cecb8280f93b571dfd182b9ccd0fb2bc6cae64aecd8d9a2469fa710ebb400296e3202ab1290957edbadac45cf5cd37c86ab7f76df262ce4f2e0b8a8a16c9e7f220055ee6ec108f43e3e908f4ccd1f783a452910afae90c14ee3173a0c8252a2007a192a431a7d38d981d16c88ba6b1db2aace490acd7e63ef4f8795b6b0f449d44865ed2fd243f3f55e7ec1c5233686db081a44ca428ccd96238a33324d62f0aff7c45d954ea778176b68123afc18ef32a76d77f5267e54d6ba06472ef82864011a022a9da2c567ca32c5ea3718a93d2fe747351a452edfe610e552d0bb949861e6c615f34d1b5642833bd94b4dd1e38385dff917f8868565ca5446d6b09a2641b6dcc145bdee50b7c
-TAG: 48d515f164f18b80a3fc7890381452b4
-
-# DIGEST: 026c86d0f2cf51fafddc6623fa7acfb2
-KEY: fa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bd
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41
-AD: 729bacb5877e72cdfc
-CT: 6bcd3e1875adf1a8e5e1273c7e887347b7aed9b028efb64e7863ce92b0fc21a8e150fcc5f35863279be9e3455eeb3812dc2453ddac241b9dad1cb419e38a62e7ce48363c01d05f85cdeae37a4dd4e7baf32a8f8ee14822f0e4ed7e8c54f6dc93aa281cb63a54f6bf7e54c3d59e29d6d4cc838c663cf9e260e1063b080ba4b68581e022f32fcfafd6f85d16ed52ace3bbd8d946215e325104ca73c53dcede023c0c56a86741e02624ae6f1cae6bc7e40409a2043e629c5bcbc07fcf5f68fd720f51e80f1fd69c2602bfc7e6714b2b1f268744acdc52920987a9db30c9fce1ad47e9490a304fdd7aee4caae1f4eb2a68a2d7b481df7c5065a96d321d5eb4eeff673cedff0d31ca9052130991a57fcb471cc463718f8aaba373ce2335f51696191828a98b9abe27fe9700bc41939a49b7a478f88f488baa19cb4c33a212fd6b30fd9c227f0577aba83b67b0fd0257f60c07bfde1cd71cec6d24be3125896e8c
-TAG: 164b98e0627ce973fc196ed1ddd97c50
-
-# DIGEST: 85b63faf53d1a1caaea723f2d0f4d9b0
-KEY: 07a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb105
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb587
-AD: 7e72cdfcfa76aed067
-CT: cdbb9d06cb5973d699ef8418b113f9c5bbeafc427b287ec3a475fd64eccf233a678dfb850b157e18e95309967eedc381637569ce5cdc68c0b89c4dc352840c55511cf8a4291838680a10e9f1aace56a6be46856f0d43b9961c2d5acef06586b72c0cc05f1902caa846a94e9206ad6ea203c56b56f70b487cd68232e78a762720032ccb98954b32aceb26f3d4a8487a20eb4fa47b67f7887d3a7c79f87143aa14900a4579fb2fb28868621172aced46a3aebacc77c2964d0c227a3f4b9151250bbba35c0961e8f025b00b055749ea5914706ece5573f96fdcff359d2124663f859d69a5f63a4ffd853a8aa7d2e728a618c7b86d0b9f770cdd084913f7228249d09d885a7375fa36cc1157188ae9eded71f0ceb2b414bfff03ce20fa57d939fc922461e265d98563d2d345edd785335da838dca068d7cbbf40ec5881eee6a9bb560b5989ed35d6136c3b8c891f6c19e5ecf0af1b49425f48eb7a7c631adbee3733f33009
-TAG: d33fd21c1dc33ee95ed519c091271f0c
-
-# DIGEST: f5f396b0a28d97d9c5f9880475d2b313
-KEY: 699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a1
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa
-AD: 76aed06707a07c3dab
-CT: 69cffa7ec4f11dfdf2cfef639774701c542ca22d52ab53555382b42678c4ede8dbf1e8c376de99c4f75e426dcbef76b96c29698308d80239bd60c804adf846bee81cddc48f8f004f05145c4cddcb00cce08ba90bb0342f733fc661b6497d082898c49c359bf67dba8f1634ac16ea7c1de60bac806c2eb36ab4a25d47c9f66a3da1608e562b0c1030d0174f79a211ad442aa50f12e91071f7b1ecb7db05d13c4acd9037b62dc0d7c0a9753302be298c7d8b71fe9952c60d88d5a46474c69e4f75000bf871fd4c2bc4dee09fb917b06526a599a53a616f3134b64cd0dc0b52dc8d7d1d6a4f7bc703b18e710fe4cc8ca7013abc1426b8061c23dc595ab94f5acd0ead423daa1245dc6febd5d4b569fe55c211bdf4bc28bd803a4b6cddfae3fb2603704276334d3e5ebe3480d1a44e5abc40935d2b0c6a985bd7f42ea35e99abf943de78779b766a59b40f1621c31b9d927234837d77c934559f7f5c5eb862395540a275a969b1cf20b3
-TAG: cd28598489165f20a382a4edf219e12b
-
-# DIGEST: eda1d27c78e3cf18826d72aaa9d3360f
-KEY: 2eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095d
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707
-AD: a07c3dab699719fe88
-CT: 44917b7da50b0d57ac61aa582ef21912243eec101da9773e0c82a279c2d778d42583684e1f9bbc2bb7d58b2c64d4226e11dafb002f80335b930924e3cb3baffeb55af42d9ac4b7a8838bb7e64587a90d6c263511e5d139b8d1ed0ea08ece969bf581eac03eb34bd2302c606708bc1522e7e728790a6083315a08290323658a85562437a61dba7fbe473568fb601021c9ce82c6d5f5260a2d3e2705c59b048d3a269f1bcc348931e11c3c05f43b5b5a91a07b32647fc7b5849697333f5c1609a9ecede15703657ef83ea7cc9cc8074399ec1c4744fdb29c298458db34b283a8285b513c29275506d866150ac39e69ef08b56207f69b4c963690416ee2920e441e4001cfcb820d27b67e246dbdebb642bcdbe1a060360f06c2cd8e98cf496920a252fd895fd8d6e316eaa2081d65e2eb01bb44facf8c76c4bda543c1d3587b40e077a4da20c364d402262fd729de7c11afbf44846f0372b012ef376eb6a5ac0cf0b8ed4695d22ab53a6f48b0441a
-TAG: 0427e13275e8c1436eca3da08984a503
-
-# DIGEST: 4b1448f2ee1aa8511c3e24274530637d
-KEY: ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab69
-AD: 9719fe882eee2fee55
-CT: 4e585ce43cc157dbeba9c21455712dd9ef50f9fc4c9567d8ced08f1fa8a1712fc839d2331e658c88d30de97ef6225bb6f9c0eaa71e35bb10de9b73c3666948a328bd1da06a62ade92f29f336f9affcf481dc0b0a246671aea223c2b937b93f2ffbb0ea1f17bebbb6a6964c54894aa7f2671ce4eda1b361ebd64d7268cb8994f683877e24765487821907b3e88544de6094e732ce01fb226eaa1f74aba6f8471135dd944a9a6fc22f2a957712735060ac0aadf1cf469fc9a4fe1306d9c22d671c1c7e42c0a3dbe2016b3b535869f5ec438e644bbd3f08c4f35de10d72314717328a6e60fdecb604fff90ebbfc3a6118641ee71b2beaea672532f75f0fad6a0d14dbd75f9e0038f39c91eb55c9a3b022e910cd8ad002b83499727b7f9eaef2a7214176b856171ea9757fc54dbf3ae455d1f7ddff2003981c56e1d9c53b4ef3617ba103b77bbec226833a55fbeaa587b4cc1b2abe70023262fb73bcd3b97fc762d39e1cffc225c190d7eb8497c6016ee88f6479
-TAG: 1907b80efe6d13c65dab5694dda97cfc
-
-# DIGEST: 2483a9a1fb3c7b3b399ef062a7b3b7ea
-KEY: 870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d50
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882e
-AD: ee2fee55ed8b11534c
-CT: ab9da4a38f81737ff05edc442ad046f6324ab9f6ef0b70702438e7e2b4e8e9c893c8b7af8a49fe54c3d8dae8b3983b5c625dc101de20e3e1d33efddcb9932f2d88769bf950fc26850fd41be4c13f6092ddd3e611992baa4bd526ef66f44c80daea8e3eda5d1d9f680b0403419be5e30424749714e9792f3c7a434a94cddee59e8680510eb5f78684fb35913d5592a4721b649f2ec0bd7383bd0366fc07ee3c823a2e21fb116444f0ffc63e9a83be3fc07a7ddc371ed532d7f35fc58b2abe0042290544d5f0f4a07a3accf1fede69c10917eb626c63756338e9fd498659868b021b02d223101a02a8ad05ce734426cf6a12a7e1ed5d469dc8a6b88aca88a725e35267a246828234c4dcc0fa7b62b61bfe7526babedd6af7f4c877f74c7abed25eb88fcdc1ff1eaaae5738b2ea03928f304696683398cccbcacabec855c6e1cf18a42fe4511da75dab80a364755fde1966d9b9002f335fd5aec82f1461a9d61f2138c31f7c5513c7ea16cd008f6f81f7da273c5287f18eba
-TAG: 878e67f8fbc86d4b7f721a68398a3103
-
-# DIGEST: 35a6ea4f54f8cc735b35c8f71c48d325
-KEY: 14bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed
-AD: 8b11534c870dc695b8
-CT: 30999422519fbb295b92b377e03294feb061eb57cd97156cd81518fc66f75b4662df89ad3b99fa0afb3a26b1f40d1ef1b591a4892ea10ddcfdb985a84e19affbb3a4c61f06e473ead4cd193426ae632d4ae2c419eafef1ec43b7780feb6bc0e6e17b6fa91c7eeee967648cafdfda6afbca6b6822e71dd563ebdf6b6f6d49f98d9748320692466865fdbfc2bd9f047feaf213bfac7bcd4502300539133353df343253034712cc236c74bbf0bcccc8abbe7cf44e445de4dd24be54bdb251764c36632f1446339e58904a26929085db0182b43beadbaf3c7086d9831ae59789953f59428fc399490c101378c952dd6ac24c3de1e1ebd6c284cd367388f39d208a2b5196b3fc737c588abf770260dabf9dbdbd36670d07dff4540ce2e67bb9173a8d9a038daf1b59705a4f5d5ff51510646ce283047671bb7fc18ebb6013ee1b47741a31ce49302da399ff0e28eef4d5b325f67f8809f0ac19279372cde0f8bcf9141f2bc0ee9ce892e5427d31a016be7878fdda80fde1ce691df23cc52b
-TAG: 40910f0ad89adf7cd1e624a1325545ce
-
-# DIGEST: a351ccd3cea941c35f1fa776f09e43da
-KEY: b1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c87
-AD: 0dc695b814bdf1a87b
-CT: 81d6805a8d4764e52521cf995311fd2979146862e9effdbc3311c127be3b311b6bc325b494b1db8a5474f3bdd2b5bfab0e5fee38868af4f1410a8bcdee3aa752306d72059c35eca63e19ff817bf6e4cb6d5b716194b34203e84407ee27e7d42fafeafb9260273f92b7636b5cce9c454f524205b642e83640483cf9cc9f47e78857c18465fa2f576cfd95541cce0f2752328f44c3a9f257dabb8d3a66eadeaff668f302265920febb8f0775bf5a3133c9d47b92fad347bc26ee582b671865dc8ca59f3a4e8200da3278ee58b95e5774d2303607da64ca32c31035002281474da87d3c9885eb8c61a1296231ea1d3f0cb4fd91c723f374373d2efb8ae23f3e8054c4da9ba517d8d2657093e5cf3c8c43c6ce41e0047118428f4af04c6cfbf9224e8dcc429431e045b05aa5f8b12639f2595e48c2585d9d1d1a602ced3102fc3b744d83ed9ca5cf0b28db7743d3f47362245f996e57d29328321cd84a73687ed700cc202ea52c64bdf6775344b1f1a9257d7319cb6785fa593b042d4453ea17d2cee2
-TAG: 2d21e78705f349ce058a412408becfd4
-
-# DIGEST: e52e4a1db3ffc409a9af5b65882789d8
-KEY: a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814
-AD: bdf1a87bb1052c6755
-CT: 53a86af84ebde5059dec18b9867755ab994e897b9512655c489ec2ef4291df74bfd63ecc880c694b0124ffda1f96e51bfb06df2e527d071509e2ae5c51d75b89139eacac9e61a614e2b4033633df5a998a38f146cb8d1d6b69421d024a4dec07f84b9da531e6c23ee5d8bb62b1829cd851471acb971adf23595ef041b682f1085b799adf3dfc0f2795a774ee135fe6db065e0dd642e39642af71e312637ac993bf94d9900f2dffa7a54e51407eba3617667aaa602e1c61621f0dbd4cd1a27a73395d02b5849304bb023a7f4b02bc0675a985c1f2aec2cde3bc226f73634b972f2fa6d1e21523a05a53c7aae524246831397968a5ad634664c5fec0a57c8ee51a2a3e123cab0aa8169cc7d51b2f3e4ee1bd6454930c660cd7df41090243cf542b0f49ad85030d950d6ccf27f8d8e9de6d172cbdebfbac59ae86309adb5b54ab5e25231e6d1526b9db7992d4e82f1366ef2be0c0c4126545e51666c11a6682b227087d1cda373da408d8fd00ac3f099538f9e15357e6d100fb6ec2e5668192190e48f835746a5f
-TAG: dde4bfa752ae99b2c8de2d813b6d65da
-
-# DIGEST: 7a624215d180b523862d2b0c9d9ce0bc
-KEY: 095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1
-AD: 052c6755a7a116bfc9
-CT: 513e03d3bf6c4e3676d295a69d1d09bdb1f5fdf067d02c87eaa2caa2de9e1edd2fb594f0bdcb40eb31779d9699a6ed7e406e2fcbc672297ea75d4cd90fa7481bcec936ed44c6832c28a4f57813fea389db096200cef14e60277495799a45083a65b1baf60595ce7b671208c15795598ee7aea2961c42896eabc76551158407b4696640003ab5e13f9fa3502fe5361c131ef20b12168bada932e10bbe9bbd0c2e78dabdc8c7427f006412dc526a72cbe7afb90c844429e0364dd698824b8260221719b1a8c13edd4aeffa7a482c76e23e3fd06073e9acbad2e1cf55d7280adc73d211efa5dfeee2b8b8e42d717d19ed96faf603a9c4c3c36b63b1f56a5369a9c017e8735415b79c6eda27da311ebffe0b1729e2e040f2b185bf6bc99efce660545d72b63c2a192f462540e8b8c54db85df4cbfc70e5cfcdc1123224d5b6a4b7fcaf9b5bdd567336f8906eaab4c566047c76b7930e838bf0d590f256d9c57fb07d7d850d020b10bb3d5aa52e1a1e64152f272025655eb2ac7b54b3b08bb8c56b7c7308532bf5f8e6dfb5309c
-TAG: 13182fa2d35344b231aa43eefb25ea67
-
-# DIGEST: b894330fad8850d3a33918ca2ed73090
-KEY: d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee585777
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7
-AD: a116bfc9095da49db3
-CT: afd9a2313252e9a333c3d5c1c2825294d09787ce728bfcd08c46726bfdf190863d2d6f0f0bef6a112de2a31c7a76c876feadbfb55c2da3ae056943f8d7385373bda6bc2f34c6dc4b32839d53d0948d2e250cb4a9c7ff38ca5cf6c23b4c2af5b9fcfcfe95f6ebeb8c37439c0aa6ec8b3c3588ea0a69c256283ec42b0e7f3cff7f8aa94b7651c539bd0a2ffe3ab4501075187b1b604d460d8b061d1ec052c04ba14afd8c05be9559b5d12ffb400330f9adf5550a0332a3de83396b1048591245af112c691365bc62c8d339477e34af6ea36b63ec4936bc9328bacb60b054b9bc711b6c7ee2ce405bd3761c79b79b7dca9dd46f13341b7087b58abf465e016bdce12d746a66daf9d52c4a18f0ab2eff69adac3970a42cb44670c5df3c12e1f60bcb14b94a7f72cd7491aabc670d37e2152b078cf6db76435bd2927471c3e88fb1680c9e7d55003dee904def37e492b423d0000c4ab4adc3844183a12326c298fc8fa2b3605d5a6549c392a84eaf7760ca5d7648bbf5549ece14571655967639f9e9e9166eb95a6eb16ce7913524bfa1524e
-TAG: a26398461026c59af3201a767e89e65b
-
-# DIGEST: 92b916267f27859c14cbb07dcd9c05a9
-KEY: 5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b5
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc909
-AD: 5da49db3d71f4b975c
-CT: 38634ca794878081ecf598b272e06d83fe17a3defac2bf8302cd9e6d9ab33eb47befc1ffdf5ca33d607585b54bc9786b8ed1e1414158edb7e120e6567e20bdd30ae6b3a9db076324e4aacb6b0762d4939479b0e79817315c243e987021416593f75ac58c4f65f7910ed07148f1884bd196a5b4e7ffd0f078c753aa0a89b501cd7ef8157243413c54201d5e1f232da8b3ab9fe1480e97f2034cf3a5e8c57e760d99eaafab9b5c2574f079d94e9b77a60a47406e956f995a3fddfbf11eae8aa3584d76bc9bf497d6962791f9e0c9ebe9178317489e1664f3465c66a21bd4fa1d55e683f76bd01b5ec3427d9b52b071b4d7f5324a4f74fbb3f99a20a9844c6c9c5e442740deda2acbb379d323661cb9930331ca47d4d7a0f6abd9e577736cb455ebda5efad8e65a4cbdc4a6e1cef26952670874ef887beaf085cd494a6ebf566555b42eb720321bad0e011fea0a0da6f2356c6bdc5b84c92e62b4bbb7d4e48de3bf6c665dcb4dd07ba6cf4e5acd5c0293719357da9219a1809bf839dfde87e893e520ba0ea8edc172b91b8e606c7584845131db13c3db
-TAG: 71bae6db6429cdfb67022b967f283aa5
-
-# DIGEST: 4465e341e0ebe2ea59175751f9bc0be8
-KEY: 22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d7
-AD: 1f4b975c5d503f478b
-CT: d69442c7e022f4d2c69854e07ed099b6dce18432b1cb232a3d7c9b0a5188864d848c17bde687aa35198085029eec6bfc8abd0e86cee73347c6f6f0fc090f462c4a617f839d047ab31da668f69df66ca38a586fc893d74967f23bdf0c96c0abf8006744c71690e361ace444bbe01ee443588d0d9bbb5aef7566b5ea0b27fe1a4ba2d6c545737ce0968062bf4dfc2de6f498a0b55b2d5bf9e86405ef307eab013540355030e4e7f85fc9d59f90a94894b68d61bcbc5defcaf6bd39368cd5924474bb7f20df0045764d2639b5c0cbef916dcb49d4958af758c0c36b76fe58289929cd83538779f65f1a7aa7486e0d1ceab396a34d6ce7c7d4194f7f1ab8f7a6aa295570e118dc3db999c4b76c9a3222fbbf9855de1ef5a61e8517f74634947e120b55b2a7d2c562b24d92023f6a5d14545d778adbf3b85ac969270b578cdce574a57e86efef202bc89f041122a4c429cff087733ad3d04327e62477f937e6ae13912328782d5ee248fd486fbd4f03d6548fca41dc8a2e543e86aa1d75cf39b0a02a55ab3bce92ea4e7278bfd021756b19e5bcd54da002f7a3a5f0d3
-TAG: ba423b074120d15bcfc99d8a7920db23
-
-# DIGEST: 16b14d50d657a4dcb5f745e2de66b2cd
-KEY: e6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d
-AD: 503f478b22dc8253be
-CT: fad86b42e107ec8d0bdbc63561fd1d83ef5ff9943f044b1ec1c1ce554043f7a763fbb68fd910fe53beadc4d570ec7e671abea1a99be3b368a77df28664c9e8c143b28f8753324c89261055409070f6940693ea1d3708c6465219064135cb85d79bca4317e159fbc5b624c2fcbed3f339de5a6bd4fa2b927481b3b852db57d9fb7bc205384faf53fb604a9b5cdeaab3df48998c61ad280a58f10e9ca9cda1976e461e8d1b9b0ab5f32078c00132ff68cc20435b441163dfdd3c8041208e4d11e0ef0652eaaae4d4fb8ec5662ea60eb78e188b9dd1165382a5226c2d070a3cfb94cb6765730de2715b298d92c6c95a5ba8b9082634287266b90c7498ab30b9516f9edc35ad89ad55c4c62e60e4751aadb61373c12de1cce4ffc12311e0b33209e138c411f959b8522c221171acce55802633544dded45bf783a50911008f199db1cf3fe65581eca4379187ecf14432338725bb6123ad4664f5d9f91337e1d0a8a2b3562fa83ec0bf949453e714228455bef0efa8f5d7c1a652c49167634b1990dc1126efcbb8bce1c3650a69112ef5774f5e46f3bf69b1edfab4035df916fc69
-TAG: 41ca785151f835b99bda574eb5448068
-
-# DIGEST: 9b69e954dcd34c3a5251ee13e4c8179e
-KEY: 307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf78
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22
-AD: dc8253bee6fd1b174c
-CT: cbc02c5923d5f56eee4010969f486bc4538f38185159a23d751e339f90565b2e8f6ea977c2acc892e05159e772bb2d8a6da0e0ea2e8d314fc85d4e4cb63e3710ad827a0a260d5b4eaec0dbbef254480a97e2008975af36de1ca301d69d6a360325380a68565e9a8701530506ee759656e5cba2cac1ecd5182c2b70950b9afdad6cf0888fcf7e6f519434efc31ba87bbf138fa6f6883fb764214740f4356c15ef907960ca8901304739ae30681c7e3d91dcccabf22a2bad5b33f1ace436a3e423ebcf69f9d7f61e0bbdf125e6be29a85a0c18c6c6da1c448d71588e18ca180fa697ac56eb6e24d3cb4d3d35367fbf800dacc305048fad71e4376aa0416bf7647e24b707f4e65b40555577256a277a882b9a5d64f27e1e56426236ef951650d082a5b8c04c6ab3818a02d39c0e9a1b78da109284c941d42e5d7350ff89da8d83e7e61536648f4afcc84a895f50234ffa9c3262848bacef0161021b06756d8c2e13fd55602e92d3a3bc79f9a7d3bbca56885826da10063f2a14b3f04a3ea3228575416f77e3797951070e01b20199e4067c01021ec6cd2c86a6986da094b9a0377a4bc8b1ad
-TAG: 8a271ca3c9fde6a6152d4f624c7c49fa
-
-# DIGEST: 5d9d41fee2178bd7f431f60b30771912
-KEY: abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6
-AD: fd1b174c307f01be95
-CT: 4de1b987a419e38d54fbc93d7abf0dba4a9b6961eba02fa37035d3a2c29ae1edd8c92d19cfb4efdd99fcc164db9049001dfccd13617faaef9617ff2f3dd2cd567546f7f63820bb330350d88a8bb6d7758e1050f53bc4c0c9f570b02193c1a41ae9290d3a61aa67e6c1a300ad48f0ac42e408726c453b79509ff08aa46fc6ccc0648485c6a1b70c92c759149bbce74778e7ce5b1f9ad3eb524b95730d088c284b616c0be8b44f27730711bbf8f710c38fe21100c303453d2708e6152ed08d99d971d4d20ba1468db0bc05ccc56202746dbc249bcc76e83ec31c7623984f0cbdf58521f798966bd3c2d8f8b5f9423a6c8d1aad475934739b7f44ced5aec0e70e4a581cbcd84bca5106bbff1fda80dd4e8c7671609d95d4b10b92d84d0fd01a5e7ada7aa2b2c8d71ff33a0971b3404add5bf0e0ab5abef373db2fc3408ec63c6f462c7bce3861ccfb32e37c4dc413ccfd9c44e3184ac3307097feb9accb7e39a46e047dbad88928f876417da4bb436cfa434088fa5aa13563cd7cba0ed36cdc97cff0e262dc400d472fa2e2f01f12589a551574b3362840e46faed9a120abcec01e275c013494d8f112e2
-TAG: a9ac5e4d19c1e72d0b8e712886ae71b4
-
-# DIGEST: df2b853313aeb7796dd6b91b45710b2e
-KEY: 57772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6d
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c30
-AD: 7f01be95abaa9bee58
-CT: 0b9025f707950937ebc0d835836bd33ee943fdf1bd77125f065f2e2ce96c23643c8a7b48d6832cd07c0aa42c820a50bda0495a7ccebfdb37ad5a95b3d438fb1ef1450e7a6d7159f0c020b45d2fa361cb1b19915404181b098cb2aecf06b62425939fad6b4e0137844c5bf5c4d1f912eb47acd6d4afe6dac1937397056fcc82b4cb4da13bba3d81905733d85996f3881f3fc9a56cc112b5357b6857eb474188ede98c16e6786a1739232b0b9cd7fc7d255138f15bea73f257ca7284835e26c0e97a814720500ac2079eb92d35bf409d408cce330d892f54a21f208848521f728fc77fe2845ce0d51cc991a5b017a399edddcf530c5f9b5025cd66e1274dcdd27d57ef72d6b82585dcc2d9e4537854814c5d009f99710df74a60ab9615f6ed0c5690d488899b12c969bd121da9f67f9a973830867ad088ad2c5d90ebce3c7296072efbe4d6145bd7fd93b3751befd8322c5a8a0f69ceb9c2c33825434e4aebaa5040bef331fdd05909ba09d6f5d199bd88b11c3ee9c12b3c7b252c9726c3b611b93e78da1d4336a05795acd2f928a77ef424ca64021d4802cb9b42d3f639c61def102e76be7efa75972dac3698b73d
-TAG: 2e052714cb1b6d77009074fc7ed23810
-
-# DIGEST: 539203e4c1494bf84e16a2bc953ee485
-KEY: a4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95ab
-AD: aa9bee5857772305da
-CT: 708d7501d07b03e65484bdaff1b0992a3b547685be63ce0b187fc5e359337cb4de113a667f1cb933aaf2e4da0cc91436fd42acfa99a381aa1a8eac87f470ad8e52be9cdd624e46bb1eb04079f5ee38b7d35aa8f4e1f57254c2dda1741e4ae79963ca691f01333e9c25ec9b78485c474ee08dae1523d3f5114ff0413b8d295393b656238fea984b4419f6a8b1185089b8c6a611b2d477d10c4d856504db1dbf1535f269e9bf02f6ff3ee4717a4a903439bb697133a7dd1e49830ba8cd1297e7958e508fd62c1db3c9491d47d21d9471f0edfced7d7626395c48276bbdcea2366593fad2e985623559da742691475c39f8374ceed2748252780e58f80fcfa55e8eeb2fdd1ab9f5fe0b54d56039a901fefb263a4dcf56921b229541315ad25128089c6d42b3b9aefed0d88006b240273d969e6871e2d37d3c1cfe879fe29804732bd0dce6ab8422cce5f52d5342430d79baa81601b90dd904baf1e95111d55801778e163f9d6826904d4068bc8565480658a6767ea2374b383bd7f4acc52874b39e51cbcd1bbef41465e7522cad1f2ac0b322bd91134e0572608f4aeb281604ffdd51247966f719ef0b22d4f423c64da79848a398
-TAG: 9aa7ada3a0949b97e114ba529a806105
-
-# DIGEST: 7abdbff8fe6003f19eeaaedc5dd97cdd
-KEY: 05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857
-AD: 772305daa4b550d75f
-CT: 269e3f3d008c4b37746f57e166082197bbe6f848bbe9e6731ddc73ec999da162bd6772931b8a1b5f8aab3cb5e9e341b2184a1ac848dfb98bb62ac6313a50e98091a8b830e81a614e5010b22c85ce96d717cc80a137455e274e2e432d57e89719df4aac62a3e72ed40c9ebc30b048493174af5563459779a4d9ca18fb7338066f876c901c88bc111a88b2749c96d073565c5b06344eef2deba1730dc9b8cf0e2dd6379a95b49e3595466d6fec8e902eb3caa5eb6040fc739e3f1ab9ee962119299e2d4db637d97203ae0bdfe677d5bd016e3107a77ac95adb760dcb1e954f2ac959ca0708a879e341ab4f5c08ee4fefe55c73eb08358476c352846fb40c01facb589a0e825939abe1751442f4ee49ac6034ed22933f412dd971c2625faf15563fc79d8ce522e4255a890d339d849a1ed9f989e1c627252e4694911be9a11a7c7f2dba4f8a18e8daae6d27e420cb4e1354d996078530eca3cda25fc33dbca151829086037bd3dbf44b56f79e279ca18887d35f64c97c3bfe55b6c41ea2d3af2867fc52a82d258de031dd17227bf260addbce2c2311df31b1b57ec213288460d8d70c19054e7e847eb7f23c174b28eb01264ae17ed69012af59
-TAG: 954dd539b5e5b82da2f991ecad2a1d85
-
-# DIGEST: b5ba41f3768b7212013eac67a613e17a
-KEY: fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41d
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4
-AD: b550d75f05d8089850
-CT: 73bbefc2c66981c17b1db7033972c697a69a0281413f60ae001274b7dbc4d615653e394a8efcbc4100e98a6aba7629fc05f0cd033eaf75156e1267f7cbd163e016c92cb5ad8933f7d3fc91693ea82e4532ed4229a9eb506f543765d704cdbc86cf149d99c3eb92b3c35e5c5e67b632b467415a8d6bdce7eeb5cba287cebb04e9c007a6dfe4032b1c6236a6f1369ea492cc3e321080869656b4d088c9a3db6072cf1242222cc5152743c3bd86aa2e2cd9aa47b079b2ccfe091dfb72dd85d50dea46b0492db7d51012137ce2f7ac960f6a32e87f19138622a7bd7a278195834084d386c9522cf72252f612bfd7241c8331ba9fea380e648c4981692713120594afbd1a4fe46c151ecc557ea9fa05941bdfb8de8d6e8738d32783d0563a7629cfc1a2ac8fc40e2637413aa96a36f863c9e6d02cbe8e92020c3bcc15ff4e05fc312a54c8b297dc07b2d95b33cbe5d727dd0fb45a91a171d5e6b1e867132abd417d84243ebec01211a236ca3ca5936d7fb6a2cc2e2d33ca2ab11a04c23685aba49e65dce7b0e5caa5e66e85987dab4081c9b6174643ce31851bcfc57c6cc9d20abe5a1527028356ee5372cec94a8990147291d800c20a0dbdb718748a86666c
-TAG: 7f0ecbf514cf0af99185b15b23284c1a
-
-# DIGEST: d0267fe533b8d89563e8d7046121b9c2
-KEY: bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f9823
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05
-AD: d8089850fea3711265
-CT: b595bd4d603d6c22819ce1bbc96e5db951b3326a07e46a85b36d2deffd7badad310d2611360027ced4739400e6a7aeba9bc3b4ff1232f1cb2946bc8962c5a1b139db8f9e75166f00249245bc5628b593feed578150a449904e9c640cd2f6a8c96ffb5a6b6d018d18dad48693f165411411ecfdc9d6d91ffd95c9e65c31c22e1107d657c385b1a1fad0ddf404151960162e2dbc379db8c2d7ec9191a78e4bd278a11499b4f61d094d633287bb6698d91da4acdeaa098179e2a33228d56a5fc012e252660252cc5b60a6418e2a39303cfb675d7684f48fe0724927d1b51abecdfc2cd38b2e210eacb3ad9d712a7dca0970e3bfab0ce2be1afec30a88d2a5e45e56428b9acdbeb5b20c8a657c30c8bcd5e97db74a00e8c3e616c37ccb84ab1367e935c4f1891c75b9d657c3a57bf7c2a9e3bcb0933e652934c8d9c4de1bcb772721dcc3850042ad52358376929cd33e288cd6e03bd6db1a80a0fe4b8c2be46f5cb54c9c64af86e2e50e5aea327af276002d8ca4473da13a6a2caec0edca89d06a256f2625b5bcd52b280b68ed17f5fe72fad3cb3771df5fc64f19eb3a44462a36fc3dc2b8956909eb9400035b3cca0c5ecf7cabd66c2e2ea1a65563f8749a29ba0c213c
-TAG: 85bb6da24a0b79726458da81751bc0ee
-
-# DIGEST: 1df657796024b3f5303ea6b7c93f75cf
-KEY: 0bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a5
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fe
-AD: a3711265bf78261046
-CT: 501c36a4048690953e838daa3b21ed3bc99ec6db3c3034f6572b3f19b6ed2ecf3af1f93649ec362592c9537b34907aa8e053236f8c06c7ce9f258203976b81bfc12723807fe3558ad12b74ad3e29585e05486836e537c9b369c54c387e970b514399769d59cbd6f1d43e3420087ad70ac145273d6373b0d013b05cd704e0df4b15da5be3ff51fea41c1f207e3dae111264bd949c7c5650d7b5e07e735c064f9157ce0ca74967103d646888b65f12871d56483238f1006a43dbe3c7f4a0ca1295f7846ba1e6136349d753fd61cb44510149a8b986f530c5a3326e1b6e6b50ff07a3f32738ba93c70a309f47f05793a8f96ffd7f1d18d6ef1811489ef7e37c9fe9b55a9427ff6e3efc420b7012676e649935e85cb3702cf4780a1260eeeb188469ff0631a7d632fa9c25cc23c8d05c440483aefe3692b439114de65b33412ad503b91c75683e5611b2e14b196ff601ad4eca50b49dcf7922d7cc8af687a9239b372d9a85347c225a5bfa03675aeb479fec43a65be1193edefbf767cbb07043914d203867b249907da10c1714b5bdd54b016c9e07e1aa69568681671244de4ee423dc36d80b9195d70b1d7801f75374743c909a3ed9a5f6d2613a4fe55c7fddceb1436d1fbff360aa
-TAG: 9dbf8881204d58c1ee7ce48f1f802d94
-
-# DIGEST: 34af4afa9bc312dfce81a335f10effdc
-KEY: 2e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f31
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf
-AD: 782610460bfd24ba02
-CT: 790c4275fe98628f10b22ba14be7cbb9c12da9237d2a000ffa08048a86602b41966078a3128fcc17dc42ca08880c196229353c69cb1c4a5e999cf73ba05f7d2a5cb830c5110554e9b4c878bdc89ec803c588adfa7403d5227c681496618d6e84116eba323bd88a7b63ef37e426659fda576d26e5ded2c76035af3272d0e54178f340f9247f0fe9f63e30ac1d85b7b03635c01975a90dba95de74d40c3e8a6436450830b830132dbaa5405d391802336f9eb55f1fc00831df6eb9f3b5b79cee5a6fa05f79c2ba7a9667dbd3973c5307c524c4e39c9aafdb7c43322719506314782d461d1b66a57eece5c4c537c18ad579f568f741bb907999156d1958a72b56320bf123f7e1e2fc871fe0aec12e3bd8acbe4aaa19b54ebc6be3f332d4dd2490e54643db9baefe498b2b0f6ce27d3e9dfae7a5ccfcf7bb8058efa42ae2d6e6cf973777d6175e8bacb0494ecd72e880bb000b9445aff09ba6fd842df9c612b596df46f9cb1f83526e3c768d8578655886cf44df89c3e279bbf30d713504c948c8a0f5cc22b38f251ce0136f871f45ad11b519ab298203e1df07df2bd12e98b28d3c5b37d823768eebea444d50f99af18106e421f7221abd6dff05787d94030fe2a7a4bf80c3a544d89439474312
-TAG: de69a2de94edc0b8d6ed8c808845e0e3
-
-# DIGEST: e62b14eaadc8c64f883ca44ee9650e21
-KEY: c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6e
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460b
-AD: fd24ba022e6da12dd4
-CT: a21c3d02b781230bfea4f226e7f5771b2204d12ba69aa73de505f1372cd673837bb27e98503bd342c3d9cfc02de3a3aadf067edc719b03a1e819b7a383fa0a088bc0bf29ac68f81f0f22695902200b6767ccd20e4fe34fa67542e3272575f0c49cdbaf7b34db4deddcf25053d4f61f716f01707afe3f2e04e330563322daaa00fb2384f083be7bead9e354fd15d721f32e4a1fa103c41462f1c24298602f9b81e794ad59717a5e3e1a61a2b6cd7e134efe45632b08ba98ceb5001734d6fe1f4254660dcf2f0c648dd66cb948d093e20bd94a735fd2653806b86ffb3b415fe30a09ebd1e10593dbb1b1eddc64ff30671290e7ef01b980317b8fddfaa38daf1b5ce3c19a749557c7dd2c770684022ef8e839653dcf6ca442ef6907875c6b948dd229b038d8e107d64c3666e5efe2169bdf30e9d453fc59bc4981c887c5675da0698a5e8be0c1ea153f8e073597b4784ec0df791926ff9db525649c5fe7d38493c9103bb00a09dd46b226a471719c7d9e5b2c8ef28b33d6a2eea37939aab607c663afece3f0713213d665791c9df3566d5ffae58b438f1eb498f38cd01311c546a6ba6b5ec4a6d0ddbdbcbb10b988ce6d29b037906a2d9dca0e2d2c530864e6f525dd714ef0ada397c4b620f71603e04a48af
-TAG: d79c4a13834a9d31864a9abba3c3bd15
-
-# DIGEST: dae9f48f286ce7b3355bc3a645157647
-KEY: 0974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799e
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e
-AD: 6da12dd4c27f437248
-CT: 01012e24c420ccef50d9764bbd08f08f615eaf7760928af57330908f95036804eeb747b442cdb78bda535479c21fc034ef4688deea1605a147b19b8ec90be0a11aef2a03bf4d2883cf5884c4882892810bc56c324572bb03404c54f810daae9705659a4d3aa4dd34d41093950a0b9fe3c6067573d9d85b4a601dd423f7dc0e56186dc3d88f258596e52eb3b029343901979d403cee76a4bfb10f54fcaec418e030991d8216480e5b335d3ea061ef93ac5fdd38b35ebd109043761344a21c7acbb03c9046e20eadb86ca539263703481eb109e7682b241066b18ff22ff6c35fea7731aa26fb3d6634620d9ba0ec06624cf5f534713146a34fe8ab6479470a66e017a60d946fb588f7ecbafb754f159a6a2e597446b3ce231bbe2cf7dccffd9429157abe4643e29db8d654f5022abdc1f723a55e75aba3a10f83f4220f453aa6cacd6d019002f576c91964b8ff7ec1d474983d0a9cf6591c9502eb2f7cbafd754bf13b0f48e8687c00d7a4faa339160f27a5d8193596e44b99393ce9aac93f302fec64e0f7fdcbb7cc319da71fdfd294c929a64fc7b4e248d8e601af93fc511db891a43d0fb6ca8a4eb9f7224de8f98551f294bd9e464e734ea468326c44bf82831ea0810b27b0b8268fbeb974b3599744652f2a607928
-TAG: cf211e739999c0a884a201d24e1defae
-
-# DIGEST: de6f2d0a9b2e678bdde49c463719942a
-KEY: c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c2
-AD: 7f4372480974454879
-CT: 48e2287435bfbe67587ab7d4a101e217a565040663659fc0d73a952dd6fd9c29ec29263960d84c1c0295c4ee2149eff2ec60a17871741b0419fb612288d6e6db6bb5abe321006878b8802ae62e19c5f0abfd81582539aa06e14af05f9015e60cc906c2716665400b87f6995c77ad1f4394b16e4e5f4ecf1e7a69928c18d786c94d6169ad6846ff8de1fd0bff2332bebc0b23de70bdd2b0e4b305f4dc3a85b34571ae351d7bbf394a2e51196c3073515d57ad14341653f1cbe54c50862586d8e0e1824f9bd9f38a5d51dd1ac7470d06b4283739906d4aa431870ea38e003f7a0d9ede50064694d761b4ac908179f3b244958ac05f1981b5cda5c7f67f18bc87f3bd09e1eb5bdcd9f74c4ad8d4b2b166f6039e40c144562b6d90298ab797af1220f5aa48c2baea819b30c2cae54311b2c8b44cd163c034023411af6133ef2cd14d5448b08ee6cdf60661a19d3114aa4fab03df07d0ee30dabf36940d6ed2171705e0f7d2064a01ef56e69d6a135f0c13e94c9c57391b5e862e687aabb82ebb2551160fb90aa142edbff48938e288bcf9f32e47dec4e89d6c1aeeefdd4737dbab412ae3407aa47c76847021824739c385723068e68c443c8a8b51d37f1085b3f599d1e7aa6b7070db8d2e907cbccf2326c377365347f2ea010552bcf7
-TAG: 13a03ce033c494c9ba60a66aa3c07ed8
-
-# DIGEST: db6eddb69a41cd0d4ca9679040a199c4
-KEY: 98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e93
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f43724809
-AD: 74454879c41de9ac9f
-CT: fcdb2d0070295ace472381de9ad1fedad4c21f6f9bd6549111b080a0ee78901e977b7d4d4c5153359e6a3201a2fa8f9ecfec1abe4a7826f6260cd107d7b4d74f5904472881e25ed8faa85d8db5d36e83c59387c2efe711a7f247747b5fbfe6c9c779f63b632b78cf6a4a55f19e62dce27676d3aadde0536deced39dc4cc3b360eab3851d99bbeed9b28b88e39484a27c7fbd37d6523ee0e50903ca89beb8fbcc6f73368ed4790696bfeeae81ab5a3a5294390c6bfd1d576f3896ad923db0fafc50fe5b23a6324a0a1881d2581381ff8aaadcda315a9aced39fe9c4782936b33553a897c3cd599b26903e114ac8cd8334c2e98542864b94e8d1711bb505797498770e8be9ef4ca0d7a94e53d62825459dedb5abe4acaa9a44192076daaf9b9773f99f7502c8ed38f0e675f41c685b85db681fc5994a206fe8454be3e3590785b07b9ad074cc164e9675fdfdc5c57d825ca2d9b2fc1c9f7e4af8b2716d21b8666c198c6175482d44946b83507c5ee5f41a0b438c55c185f7b0ce85e2ea01ed0f20cd4000dbe9755b4e59b36624751141c86b44e196f9522e7c0f0ba892787ce5735ae82e5c6d151fb8c431b5b5a4b1aab959cc8c55b21ad60dfbc4936156ff3ca97995ef221f987c240e7e6bc62201cfbb55c7e70693e854002ac991a3928522b6
-TAG: 552d84f30344bbc5017b510637fb2f18
-
-# DIGEST: e4e06593a0603f3860c86d1fbe2aa43a
-KEY: 79a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a694
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c4
-AD: 1de9ac9f98233b5a73
-CT: 8006a4fdcd449f2b7da0ac9bacd94ad887e5a10542d36a7886c4bd81fad228ac66f95a0a66c2415003b7d2fdcd08c2c2f201358b31266b046ecb7d1d253963d0e790270fdd89e57212268eee2626cd33cfda90776b86992ef182151aa130f3c437602d1fb908c396e31a7acebc479f2d4b45c318e1373a7b8f65a759d6bc3d7781e73eb430eba1f3e5598273a3ffb805314f176dee7352163fb172d0eff516316d345e6dc4a7d0be7d035b9feec2a419b3fc90dff8c801e9784a270b86f863759e5f06e4a8d5934474d10a0d16224a374a6555882cb0834ab84c1e1f1853b3514afa2e6ffb4add6d0a32660f6e305c921ddc2aad880462ade745f30a87b0ccfe5c15197a833cc517396875b1a3e8ecaa7cd745b1c53d3b2be00258adca82c158b32714175449a9b6aea7c6f9136348a738834e7788a2acd94b21bafc903bef5f71efe0f116002e377c92a8800880dafa613d7ca3e7479ea5cc1f3e76b87d9567ce81cb48c41bd4874c3cbd0394345a9a993a9056aedec499cde39a31e6270dcbbbdeb325cd2179f471b29ac4054a37a0e0c51e3ad25f91fe1718eb1b2b9f1d19763d08a2be6114e6ea50e75887a6c2d18a8ccfa5de41a6da15c921afe368c39dd6bc411128cf9aeff7d48125126f2d8d12864ca260f655fd5953be5c3de63b2def94a177f3
-TAG: b69f65870400bb2326b9dd8749dec331
-
-# DIGEST: a7a194379c1d265d2b77990f70c46ac7
-KEY: 0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d72227
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98
-AD: 233b5a7379a561792c
-CT: 8f46a3c72904cdf63c692fa0e2ac3b0282251606b720ac79232365b3a817ab00b8efab53e93d712fb1c4f7f60bd023669d50d4008ab8aa42291d972f5b5d39a4fdf859d12efc9d0c4ec3550f4743794b12c2c3dfe9ce3a1aa1e5960b4212b26d572aea1cf458f6ac193e34d6508f655971ad32c5d249d56d48573ce52c0e066c245e71ce0a6bd84b2fed90c84f8253baff77cb3cac8a2c785c4271d4b080a342af297bb3ecd54c03f45564c6d84af9b4b315a99fc75814b198942eaa4890ee10e67efdf2aa1e9608d5553bef569a085a767dea732324edc485c5e3c9f412902116695d7b74262d93e1469f5721e1f5ff9113fe7653103ec6d16891e0841616641aef5bc1e3d2fed2cf74179fcf488a9833c1e886bbf224fc6bf059707ae1030f51bdfce71843cdbbe0b53c773ac12db44af5d5acc62508db1bb4f6753c018c32004178dd418fc6ef0d5255deb4b4999dd94b59cd11c9843da7f76cbbfcd4b9c7b99283305432bc3bf9473032efe923bc265ab130ba3733872ddbf402d8e295a8ee09ef689dc41f46df40d941227f1614a6d2895b2e7e01052516ff67d9ea17bf864a08f9df3fd035da8046599b2819b40d5b290584bbbfe138bdfd52c043cee630b7cfb4fbdda4a9b38b54b76cee95c6c9029a0466216894b4d8627104a22b6d95bcdd96e9bd904634b6
-TAG: 828e852f1d956f6e53daa6a78b016932
-
-# DIGEST: 024206042fa9f1c70cb75952ed076e53
-KEY: 8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a82526
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379
-AD: a561792c0f3116430e
-CT: bd7f7811be613d6c6dc47be7c208c381b084443b78e124338c514532a96e329519d6553d51bae587cafd4f3b1acae6d20a34172b46fc2cffad3b979f16b6e4c1ecfee56b085eba9eb4a33ed2a9a02515e8d3700346a0d0c5f4dc4a3a1a3784d58fdd207726aab66126b23c725562e4ae44d3677c8577ba2a83f48faa28151929f7c33ef22ee42e4cfa9a27abd3fe8a27d8376f68233744c4c04aad2169976b9eed261ec82ed131033b4268e498a4a35bdcb757e0ec92715397d1804c7789f3870a84de4d3a9a92875f5624bd6cd7ba55e24dcb01044b5409ceac99f254697fac04c1a1bdd1682119653a0bd693f2bc00372d044da72308dcff6ac360bad8c048a6eb5b52515598970b2e48ed25105b751ab6fc084a239a561513f3cb5e56d75301160b56ae1da7ede989f6a08d30b77f5516764f8b9f7128d55d7726095fbb441d3da8aafa0842e283762d0f5ebbc0d6aee45e9df7fd41b63431adb16f6c5325e376c26e536f848c2a01251111e022e5adfc88d1ad977c67e9abac0d3749cfcf1d0e6b61c7be0432c5ce56187c48c84c8b3ddb71bf373e6ce818b579e13eae2987cf407cbc844c4ac176d3bde3851446908eb61969154f8d058e645dfc05ce4cc6722062e5ec1a790952f504fde390a438c8aa19eb25566ac9313f44aa2de4e438926583ef9592e55abd39149e226a
-TAG: d711bed86f6fd7adce31ae3879c36093
-
diff --git a/src/crypto/cipher/test/rc4_md5_tls_tests.txt b/src/crypto/cipher/test/rc4_md5_tls_tests.txt
deleted file mode 100644
index 26a2824..0000000
--- a/src/crypto/cipher/test/rc4_md5_tls_tests.txt
+++ /dev/null
@@ -1,808 +0,0 @@
-# Generated by
-#   go run make_legacy_aead_tests.go -cipher rc4 -mac md5
-#
-# Note: aead_test's input format splits the ciphertext and tag positions of the sealed
-# input. But these legacy AEADs are MAC-then-encrypt and may include padding, so this
-# split isn't meaningful. The unencrypted MAC is included in the 'DIGEST' tag above
-# each test case.
-
-# DIGEST: c881255084e0f1a659712ab2e82d5b37
-KEY: 7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7
-NONCE: 
-IN: 
-AD: 936a91d0b5d2c0267218cb
-CT: 
-TAG: 117ed9d774a7e0a103b3b44b92c5fcbb
-
-# DIGEST: e1bc6efc59bcc11ba263459176decf67
-KEY: 86d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f418
-NONCE: 
-IN: 936a91d0b5
-AD: d2c0267218cb7090c61713
-CT: 0d937a13df
-TAG: 5db90b62cec3d5595fba8daa1031969e
-
-# DIGEST: 923c031c891fd8fbcad833524727cfe8
-KEY: 97b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7
-NONCE: 
-IN: 936a91d0b5d2c0267218
-AD: cb7090c6171386d641b877
-CT: 06f8afaa7e40a1b8b939
-TAG: 689671bec189ad4d4d8f953e21aad538
-
-# DIGEST: 1578901a05412789af66de2fb376476b
-KEY: 56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f7
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c617
-AD: 1386d641b87797b684e0fb
-CT: b52360ca180a83cb0a431967b760df
-TAG: 5d0ccb30a6c3fe4f576e8787c6009912
-
-# DIGEST: 97520ecf77d226d7993e3e063f0d870e
-KEY: d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b8
-AD: 7797b684e0fb56f97c3961
-CT: 942a728b2c1d93ba16f09b4feddcbb22852605e0
-TAG: 0d7a7542e69787501b6cf9a4befad516
-
-# DIGEST: 31204840e4d9d7fd65f77c44393c0133
-KEY: a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0
-AD: fb56f97c3961d8afa22993
-CT: aa054be3aa6ef1f88a1b5acffccdfd71a37c8272feeb8d6e30
-TAG: 04d7407aa53d3a29be5d3d0de321331a
-
-# DIGEST: 91344b9a4ee429eea6177a09060c7553
-KEY: 89c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c39
-AD: 61d8afa22993a340b9b3c5
-CT: 36ed08ac78f36243b070eb6bc795990509bdb894cd32b0f23bac425c1ac6
-TAG: 7fb1ca79203d5376424cd888017d1d49
-
-# DIGEST: 1c49c045e7a9aaf5b7189a8eaa5d204c
-KEY: f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa229
-AD: 93a340b9b3c589c7481df3
-CT: 8a30756248324405b50c158821ff2b8c0507c0892c5f7f7bce7cc22ea88654b3595615
-TAG: 41349883fec502362155d75e5990e46d
-
-# DIGEST: a973b16287ea82511d9ccd1fbf5facad
-KEY: d8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df6
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3
-AD: c589c7481df3f4183aa23f
-CT: 550a94ccedaea25649df6d1ed3be681cddab569d49ee8607684c5ae99edb671711910d6cdb28420f
-TAG: a535f655fab88529ede7b07433853b63
-
-# DIGEST: 94a0f3b460e5fb5ff96907d8f42be0f0
-KEY: 03f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481d
-AD: f3f4183aa23fd8d7efd885
-CT: 00802d26b7cea1aa8bb7714ccea2d4fd0d9f5c792128eb80a358821113c455b364966b616ffc901ddaefb14ee9
-TAG: 04721a25d6f8bfe7107595d883ef64bb
-
-# DIGEST: 2f3c28d24f433ded58cea125f64c427c
-KEY: c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa2
-AD: 3fd8d7efd88503f78b8ed1
-CT: ca6a68b922f07e746d14403fcd4dadce0b24cfd9515ab41a623b57d0820d78998b446dc31d97ca1b47f2c2616394d245998e
-TAG: 4d87d13ad88796e1d566e2371b6e3ee2
-
-# DIGEST: 0984364e7d640e8f8cec231240851d14
-KEY: 773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd8
-AD: 8503f78b8ed1c8e9ba2fd6
-CT: 671bddabb2cd1dc74a075fc76e2ffd49472d575e80850cf497fadcfba5694d76121eee0a849b1ec2f101cc4056cb448efdd85eb36df353
-TAG: 465c0c7667586c0925489ba09cc7fb7b
-
-# DIGEST: e36590350b24e2d10cf69e9c56a51497
-KEY: 2a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8e
-AD: d1c8e9ba2fd6773e0d0c30
-CT: 42bc538d9a88cc277b0835afefa82d170d161fcd04212125c8d6d8d15f8c69e08669f9b3b29f526df59ed023faa32f0cadc9bfb2e5a78be318385c99
-TAG: cdbaaeeb162cda49bcd0a43fb16738b5
-
-# DIGEST: 0812b6041cd64a720b59143b1c796475
-KEY: 446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2f
-AD: d6773e0d0c302a5f47e037
-CT: 2a4bd55394612fc929ce1e5096ff495a73ababbb3e1f4f6e61293fb8d1b1b1350b2bcfd99bb7a34a340faee87fc79834c099c2c765dc6548c0d55ec85483e4a21f
-TAG: 1caf411949af0d5f58d63e2b0b9eefeb
-
-# DIGEST: 45105e6cfe50e6f19f4d69028a13c501
-KEY: 7df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997d
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c
-AD: 302a5f47e037446f5891d7
-CT: 4dcb418b40c6a1e4117419907646b2901aa1168c17666d954d2bf9b6915dc16c9fde7ea9372dc3169a66a44aa8d01672956a82043e74253b1f42fe9123a2f4cc7776c5d4f38f
-TAG: f8ced6476bfc8e0cadf0f4085612b616
-
-# DIGEST: 39a4171290f03c5d9c3af26d710cbd4f
-KEY: 933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e0
-AD: 37446f5891d77df660ed82
-CT: 06b513c1123d12c19911f3a6e41ce4a1ddfd58b017b6bbe2f1cbc5898e272cf39c0d19900cec6bd14475e0a27aaddea6ce1da3a34333f0e07ac134c9a6001da5474936a35330a862b60440
-TAG: b7d83d712aef8486ebc39d07b03001c4
-
-# DIGEST: 39cdf1512b10e8283c255f78254af3fe
-KEY: c55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f0
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891
-AD: d77df660ed82933f62be8d
-CT: 662533ab59e17ea202bf74a7f465b6a3f7c3b89c21f91916e3d0543066d676ef31b97184eede519d6ac5300046b8d3a89e47928aa3b348cd6097ea2bf6e7c87ade499b084f908eb822ed06f574f19673
-TAG: ce07ac0ba6808cfd68f2a5c7f7485b2f
-
-# DIGEST: 6a5dfcb98da598e243b85c0146c3d9f1
-KEY: aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be1
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed
-AD: 82933f62be8dc55b436965
-CT: 958bde313ef29f25b0a771a907be16993fd00f6f7161377e9296a85d4f1675d6959afd14cbbcf20a4ba0ddff2a8a2259cbb14bd0f5ceb2079b81ead41574d86eb0bc82d2cf4eae8e3238c7451682b17c4a4577fe15
-TAG: 207c12bfd69288206bee7aa70d022e87
-
-# DIGEST: 4d08a93e37bc6970c32f90107dccdb58
-KEY: dd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be
-AD: 8dc55b436965aabe477e0c
-CT: d844cdb9d93c02399bb61ffb280a9146b79b9faa03c7acfe7abd7ba99496e40bc2f34b8547a549ba264ee9767d67c9c94809ed9354b53d26438515ce039082a097310cebd832b30072d98e29beba3cff02bf43494017b98ff216
-TAG: a627fb233fc8cb3c0d0a3d46257dbb41
-
-# DIGEST: 070ed30ad273236ef1199928261c2db1
-KEY: 1eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b4369
-AD: 65aabe477e0cdd46be9937
-CT: 86cf00c8dc9af8d231ca9186aab46f96b6ae0fe311302546b66411baf9a688da106a5d3d332360252174d694461cfc3ee771117fd825c63e8c791d0b3988340f3d87f47219ec0c56fe1cfee6aae4cc938c8658963dbea6ed2138ea050b3ddc
-TAG: 66d99a289d5f809aecf5ca2990d39fd1
-
-# DIGEST: fe0e658cd29c28d6156a83076c559093
-KEY: 997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d4120
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e
-AD: 0cdd46be99371eb8da7dac
-CT: c4d7b8599da07fb144dac7bbea62f8b4a7668be305604ed8eb17617ab1f88fc61d8b2d9b0024fb0f7e21cdb09e65a266da7cc7c3d4e56f7c8ebeed3ba962bbf24289cfb17411ebad274ccf2891114995c02d3c6b47f993a9569dedf26346e9192180edbb
-TAG: d6bc2491a7e8e50a7a1bd991e83c5044
-
-# DIGEST: 79afdb81989e28e11f59a5ee381674c2
-KEY: b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
-AD: 371eb8da7dac997deafd64
-CT: a480e47f24600c16f181fb217581eebfebc38c5be494e707407b3cb4c88424726a43225f2f8c98c54c886753c851d42d64d7f9c68c28d2ae34bd853603944e98f944f353352e9084897d8e64867cd54790dafa93db2e108d9301388e4c24d929efdce020bf0782f2f9
-TAG: 71d359da0e121aaffe0621017a931db0
-
-# DIGEST: 9c6487750d3b409d80625a11b8be3bcc
-KEY: f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad40
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7d
-AD: ac997deafd64b1fc65de39
-CT: 11fb2fd41f0ab4ddde1cd9b9b24821483c5ce33922fb883acf240f1f964ebef5364193763c1daafdc495bfa11445a3f32ba0c5fd409ea23ed99b02db460ce37c61a5c9a9e3c8165eba3f0183b1645d65816ca1da55f0bccb7ab9333a59650119be40b0e5245c3a751f2f82a07d9e
-TAG: 59ca22b8a22a2c5c8c46f262b863bf98
-
-# DIGEST: e939eed2d601b8398f93bc64bd346fe6
-KEY: 1be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae0211641
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd
-AD: 64b1fc65de39f4f03541a1
-CT: 89eb6968532a4a4a9aaaadc6532e2894f233b414bb7178f42c0276824f04a045822324892fe345d3c97b83b281107074906950d8a085b7adcad611417568da0ca7a759c868a6d76c0d77df2005aa3b8ee239d411744df96d9053fa97c847b198c594ba84ed94553a8b640a4094cd05c30dc714
-TAG: 89e1cc53dc3666fa17b9f90f3491be93
-
-# DIGEST: a3c81ede6b6a0ca240d924abc57fdb48
-KEY: 33c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef45
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de
-AD: 39f4f03541a11be112a729
-CT: 4949bc8e8e50849e4e475b91510d2ae45684c4c9f6a500de6cf8c0ebf0750e03ea371bc942f3d3ca28073701f6b0fe6df6654c4083a9b885580a6b9c2074994ab2bee5f9f8c0e0d2e26e84d2cdfee51396706aa8c70c7fe5e1859a4a99a0fc113f67a0203fb96b55ab19af91d89f325e1e4b3d2fd42162dd
-TAG: 50f1dac70c1f6ceff709da6a9fcdf1b1
-
-# DIGEST: 3851887695c9f64a3b97ee8c33005485
-KEY: fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dc
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541
-AD: a11be112a72933c7b54ed4
-CT: e7240af13d68162ff7fc0c25fc0f1cf785ade49bd39f49c1c222e7ba44b3a4e379a92caff00daa0e0d2d668e9aed5a80951fe4207089dda7188ac052176e790f2a7df0853558df8221f346f53a8f06227d70387fc5b6e42815e9b2de851c5013eed5d6e031cdbe73d43abad20fd573cd108d8494a8b17806aa19b56f7d
-TAG: 8211d9fd9f47675218f42fa69e0d8dc0
-
-# DIGEST: b623cc1e5e2115b94b7f47dabcc31735
-KEY: 41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a7
-AD: 2933c7b54ed4fad0be905d
-CT: e2b6a06df1fc7178e88e01aa009dab626c7a8e46778405ce2790681d26ab8f8fd69d2894639e6d4a7fd3ee2b2149ab4e5a254059f830c8b4d32a69453babe706924e706a8b12ac3d56317fde62b60d3694846f50e09737503c34c960df10d43a0d624f2ef0ea3e7423d2ec1e7c5974434093f53943468dcdaa29a7cd6e8c706b1ad5
-TAG: 6ad8e00edc98ac0d69e6e16aef1e6783
-
-# DIGEST: 4a59cec9f8626ae914c5a94a27f5de3d
-KEY: 998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb9
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54e
-AD: d4fad0be905d41203f5dce
-CT: 3dd231facfc7c84e8c95bd2a937cb2fbcebc4978a3de06c5b00218301b01d5b398499bb7b48ebfddf76517539adfe5e84e278994db2ce3d86ea0818d8c50e19f2a2990e8a2f4059036286ff72772d15fe762e79e0621175561483beb29644a403b3df3c14b883e454f10debc6655c69287482a40377563ad0765fa9e4da061bd365a7eea29cfa5
-TAG: b1d00f1e703d0088bbe07d23d86b2c3d
-
-# DIGEST: ec5c15d3292d8c1df0784c36bce45163
-KEY: ad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be90
-AD: 5d41203f5dce998f8fb2ea
-CT: edcd1007678e8aabdb6faa3bd8308488f765aa3b304931dcbc44d3ac67cb88854ad72206c0c98e57fc7d10d5c6f7858442978492d000a31f145fb26ce2d4b9d55f2663047e618b6d0cf0657e8ff3b4859d6b0eda600def393f5d61ade0658ed0c7060ee01a1b895a90cb66c13896ea835cb2a64d1bc4b0a580b4c5d153b6cfd78a005cd8e0d440efd1085dc2
-TAG: 79ac4fb117472ca2503d56a86706e730
-
-# DIGEST: 349ed7114f2b4112ef858eddeac2db91
-KEY: 16417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780a
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5d
-AD: ce998f8fb2eaad409ae021
-CT: ccef052add7ceca004b35aca8771cd96e94672e53bd0440cf0d28461aed73707e77983a3fd06404cfe4245c2e50701a81ba739bee051640a41d4365b8f85bc3c2acad087023a26affb19e320bccd3cfbe699925c2469d30b5b9f022fe24530baa2f60134291a25f3e49804dba23cfdf9143457cd4e92013fb052cfc3bb3c6539fec14f160c7d71559ba6427f86a28df509
-TAG: e547d7e814bcc9dcfc9bdd3163c6b6b8
-
-# DIGEST: c58bf920dfa2158876cc83afaaa6932f
-KEY: ef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2
-AD: eaad409ae02116417dae0c
-CT: 14222b0b8172d5f0cc1a77f86f645cf576ef788208d5ed00723504ae5390556821c2ec474b4a693ec9001dd86fa2c26b4a332a4dc76da9c5ade0a4178b8567e4e464cd42a3c2ccaba4422a98773099843a4a47a19d929a4ae96d624fc090027cddb90f150796a4587f2b741f0b86c74d6417c144679996677e8579d6fb015d4067ef66d8ff09c9144a35af79a08da8cf08909aa68897
-TAG: 0daeffcb4b3a84137cf7b975d26bc024
-
-# DIGEST: 0248862f0735e29caa6cd6da11560ae8
-KEY: 16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9e
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae0
-AD: 2116417dae0cef457b9e5e
-CT: 26e00daa0e6e9086cca053c90e176b3a4374771b657a7a56aa3c40a810bb8722a2b0ea45fccc78c13428e8ef6f915bf4c10bc92ea4cb2485c98819d00588bccd503bad4ca147ea7930bcf8cfa852371efb46184edec6f651a8701df8c98ec785d6bb9eaa71b66f4589a1fd5d0a85194b18796fe0ceca856b0225f735aa9713308c31424fb9f5a2447aaeddbe7441cce17b1df8d98958b7e2810a3b
-TAG: df15278d770f4d1a4c5e48b6c195b476
-
-# DIGEST: 6c619bd671699123ca99baa4916261a6
-KEY: 5607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae
-AD: 0cef457b9e5e16dcc5b6f2
-CT: e8441767ac75ff93e0c0380b37edda310f98164085ef1ca02c8b901d03bf3ee439f6974a4a0e8dbf6fc48e262b3092fe48aa80f0984976b1151d53d8a900d72858853db6dd85ab2f87b0aab7f479e571f6688a1e2ea489203f29b9852cb64832761cb834a7c7b2e728faaf96282689b8f1431acbbf79e280141aaeb00c5ed5448cc9ce6a4dba7a6719a18236b5f357c7a03e55b28371ae830fc45a291d3f5ffd
-TAG: 97cd2547d69142a2b0bc0c5ba03bc202
-
-# DIGEST: 38adb3334cddc37d1907abfdf00a7ea3
-KEY: 3fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da0
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e
-AD: 5e16dcc5b6f25607f00d03
-CT: 1488ffd99f7eb677fbe3c88076473b76790968b7fff3ffa7d62caa8c3d91bd7577ffa00bfb4b3e5227bcd56f5d63fff133aaa9c4b16a0122f9a6ad322811b5acd251e66b8c0279921a25ed944e2d2767f4f5e5a42cda1c4985e655d57dbbdbfd17eb275cafdb8696d0c9db89f5167e866aea1b5c7aa70a1a9703d8098ce246c841f36165dfd54f0b910d1d60fedce500e75367d95bb9039e2047355c21118abbf84fcef924
-TAG: 09ee3924170ed1f7c3509bb0f1ba078c
-
-# DIGEST: c48077c3bb077f089100c8f40cf071e4
-KEY: 4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6
-AD: f25607f00d033fb95fb09e
-CT: 6a6bfc3a6b9db5d0f174b9e57549d8d1769899ab1f6536fe3c603af64de4f4d747f87550a96a508855e5df3253d0000f22e321bc55efa7af25dfcef9de702c192e47cf8f3bbade2217adb593a4f3dba66f3281eaa77c2b8b6e2ab43740f19f14512963f9ec31130e78326bdd5dbeab3af04e255d22b774b82c864f7c0a4e4e0ace0384419071710473ae4c7b9d071f7e9168a0a3e6ad51730ca679fbff2d652e9795aebd71b6ebd32ce0
-TAG: 435d1c6df44fb99d57a25671d4d09b11
-
-# DIGEST: 9fbe01afa60a2107ed82643fead3d8d0
-KEY: 780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d
-AD: 033fb95fb09e4d00d6172e
-CT: 3a5706fdc8ed4805ab824161ccd51b59319350ca7c2c00b2cefc574de2a5c3f7be5762d4d837af0ee9efb9fa1c6227a1dd232900032d7f2a09658912df403e4546ff45f20e76e0c774e3aae6c3292cbce65529d451a7069f036a1b500331437b4399445056392797807ffd89867222536f8f0949542edc1219944faf78af3f068a0c4791096f33d1e66e4f067520a21fb77359b194b7a3dc894c9b5174737f394788bc4216c134aac6941467185a05
-TAG: c35c3642ad41abdcfb73a51280095f75
-
-# DIGEST: ef32a4f8c3e5520e52f3c802f8ad3701
-KEY: 433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacef
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb0
-AD: 9e4d00d6172e780ab8b700
-CT: f9d5ded5389ce96eae5adaeca4c35caccc187a1cd662bb454e82656f600f44f82155a69288ea6925d39ec26f065127736c952dda8e9c13fde73a1c10465b1780a16466cf277ff8862f7216751da2cc0effd853ba201e619ce83fe64d08b63a73f4fb040b7f52990b0133ef02f9db4bcb7f05e31e22dbacf7a7baee9b5400fec5ba9355cdcd876ddbe9c2599bd647a0f528300bd78834e7d3460dc1067fab7e04e1ab903ac78ba36dfd480c4f73aff1b6d2b8ceee
-TAG: fd54b7e5091b277efe5106e735927a7e
-
-# DIGEST: ead895f7821c38ea7b9f7f4d312447ed
-KEY: 1c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d617
-AD: 2e780ab8b700433a957a74
-CT: c0b8a6bf492f1f2acd22131c003cd86dedbb1be12bf9603fc03adb3ebbd23ff0145afb864a4ad95ed0d3c34a30449eeb1c877abc516de0a9f70094b07ed8978c34686959b50b29918bf593269e960ef42b9d6e4dcae05773439e6cec210d2f9152fb0ee52dfed56e660d7e87c8d47ef673378197777c2d79ece9949ae89896d659368231ab310c2092dbfc1dcbe183380471a01c13c07766dcca93f36e40aac6bd0cfa8a43636f32946deade797afef3b5c2063dc5da8fa2c1
-TAG: 66d5575db7d2e8d10e74138c77e7c1f4
-
-# DIGEST: 292bb2ae5f49dbc20efa5fb626870933
-KEY: 021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed51
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b7
-AD: 00433a957a741c9eb80f2b
-CT: ca0322ec1fb06356879ac0b90cab48d3ceb9a7d97b361db8fd001c69ed9845bbee656542cf3c5d1491c555ee3f05322dbe62e5a3490131d19289150245db71480c50038bccae48a3e6a220cdb4de508c185ae845f6fd1a654554ec49f0b4c70c32a1e0f600920f1496b71b0d57d26ca10b01d033351d79e53117d9208c3c9078ee7880b006f8c4595739ab1abffc45391176bf2b21696a56d20ab4ad23570488563c7a030db690f1f0fa2838663a4a4aa249c2a841e2c867088be1996799
-TAG: 6aa00271869c23ed636b2a91b4692e42
-
-# DIGEST: 6e3475400d823789c3d6a07156fe3a72
-KEY: 9da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a
-AD: 741c9eb80f2b021b144476
-CT: 13f77fa81d702b8e69b2e7bda40c425c962f3d3336ebc730685bfd11676628ecff52b339cdf074277b8def6d212076c9dc4f0ca08845c984270fa51dfd64420690461bb334456eacdbff3c7dbf564ab6479fbec6315800f67f4b50afc9924c0f662c354ea75a0ec1ccaf5d75778974a739dfd94d4ecc5bdd5390cfc2fb5dab18edf2cc7873bb046655f2605e2cd0a0a51b1c3a65aba43c7ea94d147100715c2611bfad854e86d084b79c0e4dd7f75ff9db0c4010615ff615cc9643eed2af89a3a45c8f
-TAG: a521939d20fcbddd1e8dd0d01009fe2d
-
-# DIGEST: 060d2f03ce54ba0af18f2371fbcb252b
-KEY: 0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc0
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f
-AD: 2b021b1444769da00fcfab
-CT: d303d8a5b165a4b316a6da94e8deb5b9cc8226b0695301423ab5ec868e1cd91af247550591fee72a0b07c2a8a34a1a5108d82b088aee2da8a22d3b4122178546a221f50a88f60eb28c070d0b8a355cbd7b7538a64ace31d4cd5a202460f5550ea3cfdf8ee6e58d09830da378cf9fc03c884ec9a72f969e4cd616a9519e76351bc465cbe40ab4c36b9b9857d1e849c6c4fb25c54e466276164f98d8ee27c9bae8966f7449adc8b34fde978ed3431f604597d96efe976b804c93ee06a618909638239c2637e78097e5
-TAG: 046fc6699e7e1baec230a254137da537
-
-# DIGEST: 9445f97d8d4e9f1299f03f9b495b46a9
-KEY: 060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f419
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444
-AD: 769da00fcfab0f5f93b511
-CT: d690ca4467e757a6efe9dd152fdd17db2d14f40466278ac5c6297e3b6f846050ecdbc56a2dec572de24db1f14c0a189e586d36d89173313859adbad6af6a049d5a6ad0b744a167e065767f6e20168b2d71c89ebaae08bd959ab31af1d5cc69cc40f330a0e8e41452de54a48532cd97120a0f10103ae036d10accaa4793a6ce2507b88a97e194c2c1b47850de60c0cbf5b56a04fe9f5fcbc2607770af9ba3b35c983247502993d7a1dab275e75d00e19fb420728f7de040bf9cb6a1dc8a9816ade7a98c4e5f7337b48639c9fb9d
-TAG: 13375da440b06089667d093a06528a5b
-
-# DIGEST: 71272ad29dc9b9b5eebff317e216a951
-KEY: acefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcf
-AD: ab0f5f93b511060c9c5f3a
-CT: 44f63d519806997b360731071ba43b308a4ae13f99956e807925b04d996aca984aadf8dc4bf7fc43e8d57874587853efff2855b20a5dbb8244dfbabced742c984064ba3e3b71946eab1680d74c3c61d2eaf9d2bb91207d6a7642668eb4e32b40ae3ac268b370b85204c6f0231a249cc4844f51aeb0ee469fde6b4cf9125b4af380fa9dc38f6cfccc6c5cf7172616539f794c9d116b7897973c202dfdb67c73b25e8fc092d1cf1da6ba2e3cb611d6a924b0ef073badf62d3cc11a76f75813d9cc403dde6b6b9f9fa275baa360d45c4aef2a60
-TAG: b07139311dfc7ba40c4e215823b69d0d
-
-# DIGEST: f4953fac03f0f9f2149c7c632c30a75e
-KEY: 4ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b5
-AD: 11060c9c5f3aacefe61b18
-CT: 0875a5163df500749e1d718fe9d5cd8c1a12162a3e71bd48abe3d79b0b1c521f7b41bc4c41ff4e5f70f29ade666be85a9467174e8a92d43b82e747e2c03415a87a7937a414fcfcb2829a5d755a756b3b84993e06e710156a7bf2ffb272c2652d831c1364d8d96b99944c0180ca337a95d3297f044748f6c955645cd5e961968139bb2f218486f3b600e7fe22922984fa25f4c6c604c734552285ef8a32df4ba257026d8d4c994a0b903eb9885b8b6bca0c1354f0dea5323a8b064ddf8edd3e8eda41a4afe47180781c37430dbcee634dcc253e06ad0e92
-TAG: a08d0eef96f0ac624536581d6244d7ce
-
-# DIGEST: 94bf58bf8ddd100bf3c8915ce172cf2b
-KEY: ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f
-AD: 3aacefe61b184ad2463939
-CT: 6b311960e7513f9faeddc8f9ccdc969255595790e5dead365320f84c1219a4af74917f818c69fff6f91e1b1ac612a70cf4a67478a8fa16b8113cae8511e2daa50534cc90d6da2e2220863f1cf2e1ab540c8f898d1a596af09359184a04926364988567e3691e4dcc319e249e2c32cc030a60aa2178cc495ef8f18a31bdb5ddc7dc75c1d070d40fdfb85b61af41b6b65abdfe8ed4c9c883a9f1e42f74839b635a01e92f644af28ed4cfff385a8ffcfc71c458675a558a1375356140c0abb20adf577f7ffa07d322d172ad175365bfcad5a769a0a752763b069277ceef
-TAG: c293157dcc4d380c86f51703f8c918a4
-
-# DIGEST: 5f97b2a1f54987466fc533e0affc380c
-KEY: 3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e71371
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b
-AD: 184ad2463939ed518ce97c
-CT: 4c93fe1917866c88b8db07086e942e0f734e2eb043f140c7894708f08a677e6b2f47499214ae65a1e76d473d2b4295e6e1fdd5795f00a60e17e1d2e733a798726f47dac4ab301b11990a39fd18a0def0916752538eb5df17da9d834a4ed367747d9d97c33270734b39c31ee51cee92f8c4ee14597a4e1ac0ef367931bb5ae4956fa6bd1412aab69b54f0ccea0b8e735ed60bee4f5e4e93a8803cdf9e19c56e340256923704b6b5816865578e5bef1f0531b012af93288ee649146243205771586ac16faec5af4934c2aa7bdbff3a08856b011b56d2febc4b967ca317f181ea218b
-TAG: 5c54c7ac4501e0f90b605a80723b6efa
-
-# DIGEST: 00cdf989b87c8882b1667c29c9c17b31
-KEY: afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad24639
-AD: 39ed518ce97c3fdd293d72
-CT: 235bbcf2e0c2383f6417e7fa668fd0e535d1e4522929a239367e4e5c5dabaf3d2aaad00f7f43f8412e2c7c6404a3fc4df3a0aae8592d2922c4386cc9740ffe849eb919c43fb1dface523fa5ddae3b8d8f6f8685c1601b9450e0c1e10acffce1287ddb342355ef9ec56efbd6f61858ce811da932b1052d15c531b466afe4f4164ccf5bc1f651b8de07620472bd882c8cea78f0fc65872a26291e6954e11a76ac0f410a97cd28c6133894bcfb09325b239fc0e23ad14725da4548f0de3e473c0d4dba7daab98e8114b0fd3d20ba0ae8e9789dbfa0ba956d5d7a173e8f0d0d8bc8bf6106831fa78
-TAG: 03769fd54a3093afb3f67d4a41a67a23
-
-# DIGEST: 3f1a4c94e27706d322a7516b327338b0
-KEY: f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce9
-AD: 7c3fdd293d72afc09ffdd4
-CT: a6b57f220baf8d8df8603dd925250b9ea06e1d01b0d3ae94eaea6e15db770061f63f7aa099c93012414f456bcf1e6ffe02bcd3129a713490071bdbba861cf9a73f9e4f1ad2e7f5836eb9c2703fa7a33589b2f699de73a0026fbe6468205bd8d3fe2dbd6de79672e7f07219351038ce12fc3d7edeb84651f56c1d1fb2a886b10d9c0008399443ad7def6f19754fbd71624d97aebbc3ae88038569d67c9e31597a33c8fb448a1619b0504fd1b06545ef93d7ede5a3819616e7611540355cfca12c98d9cea5b0979240ac24f901fea0500ffbf5fe5b8a9aea88ab88a9a9d2f82327ef88c12016dffeefd61cc5
-TAG: 60c0e6fa8730e6ec53224cd5a45b220e
-
-# DIGEST: e2010b79883f042a87640fd21222c9c1
-KEY: d299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c445
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d
-AD: 72afc09ffdd4f41963249c
-CT: 0fa4a993458f526143c2b22dd78163aa2d0edda724bb8340ce382fba3a810aeae3f79d97bd726f1279f81f0d43842699890dfcd8036d5c90c0ff70cf237abfe56e2d623bd8ed5c1e3e676de728d0f5d997e24c6eb13e90be67074aaa59924f42c6c700448dc9475a2f791349f1383d26687b242764ac0b850c250aeefadd0886a5e638b44db97e4c71a602e0e6e6ce411c79bf7b6ff7c6902a571f18b2f1718856beede0326ce573f0846167f3e3e8f51bc6d613d990c0ef00a8b6357dec0d46d3616ef8160e7964b25eb4c62c6ca75f81526b41f298265937a2a340810011c5b3157fd417daa36ce394d85910cd08a8
-TAG: ce1dbfcf7ffdca361c26d7b4e9d24f3b
-
-# DIGEST: df20c534f7431f87d8e9338f4e3db67a
-KEY: ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a2
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffd
-AD: d4f41963249cd299b92e55
-CT: bf267a0a42c3a885e5164c14b50d7931801ad8a551a1c4c123bb568857dd7212b5d83c20e90ad1c2d3419261f86c11ec5d1b29e90d6bcc421d53f3f11815759c0c8cae5516dffcf82e152cdb98d984600b721b00c4d98ae41b966e7eb21ce3862f24d980745e2a4489b5eeba0b9e05cec076d1016a4b96ba7e1850d6a92fc63feb9e22a0d8e8ab3a58ff23a0146b18dd9100a1a888f8129086c3ab1744f2be38014498368b70e6e32565947353f3df24d2b16b9b89a2d7c25ed861cdedc1247cd1ffb3c285937e2cbca34521b3d550a1747e0bda19e8d7d661458fce4a5ba9c933833c7b784ce8a4fd042d7570493a4521c1791bf8
-TAG: 76c8cca275f2a28c771965574c1b5a77
-
-# DIGEST: f45b6ffab0dfe7902aaecf0ea33bb831
-KEY: c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12fee
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f4196324
-AD: 9cd299b92e55ca24d8c078
-CT: c2ee4814a9011455acae6d09fac7c070f85b93537031dee21a84f7dfca4c0944770832b0bad986c7adfeff01ee87443290a6b1259e4f75123a31f2fb434ce513fbeb16f55935de36614c2bed16130a15e8ab7333658efd2b35230c1993e15da675e158fe814000cb0276298a492944b8b18761a57e70d32e00122dccdfceacdd1105238620fa12efadf5b29aaedc0d63170f86fbf73ded508e538d769270f92ce3f63a0707199709dbc3b341162e94b62373b0ebd3141af017f36865a9d5679a2d43217359db155c343a303a1db0e8c474066023559a5aaee8159d6b21040ecf72a07174ce16792d6dcc59b5ba846e6680cddde32ddfe2348fa1
-TAG: 56dec4941ab6bd602b2b0d00320aeee1
-
-# DIGEST: 193a29b7078ca1e6adf3019c6adfc919
-KEY: 13710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e
-AD: 55ca24d8c078c49f78c7e7
-CT: dd5ea738801b27f7c8af9bfc1749580ec36186f8c84d576355b5118febfa34829c93c08132701fcce8d4d7dcc3f20053baeb732418af132aea0c6b23d8d63e7302b969d909d2b03289278228ce7095192d0263298cdcab83ed49bb89d2bb71f9bd705224411bc28e24140e204b27fe9c00b44018ff42537a94521872ba4fb3b3c0c72304b88c0964aea91c145e68477c8dcb2c8efe8fdfdd7014e0e3c743b884da00deb8ba5cbc6fb49774e386325c8c2ce02b0ca00586c4e0c721b652ec579a14e18230dfca22b38244457580c923a6f02b2427ccc511842a38aae92eda616839157de5fa90a694ccaa3e2c592ef1534f71f66cded862a423511b3ab9aed0
-TAG: e95feb17ef3de46163615e1e27eb83d9
-
-# DIGEST: 354b5f9bc9ec7a622e1615b9276cc9b5
-KEY: b8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e89920
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c0
-AD: 78c49f78c7e713710a025c
-CT: 5f3b4233452e0a54e418a4549ee3f561f2cf89135ff234067a7ba193113f9b059859bcdac782bfc6c22b14344e11d845cb367efc513f3201858f3f350e28f18972bb25f8a1d05f3fb80257e19b5dade29734e747dd674129c9add36b0e5785094e7fab5d0cd5c87c191b03dc44e2583c4279650352bb6734cb25ffbb3e1a366560aa0576f4b6dee50e5f8073c0a5b177583c0a1c04946dda024829cceb8335d754bbd64183e28b67dbf882788e7be8cbfbdf80e29630643ddd1b8f51304e0dd05ce045526cfc3bc71070e0994f55260e947b4fbb2c0046097d41df9ecf603d4eaf731e81acbdbe4ef529006f210653861feb5e4023ef5cdfe648665c9365a9fe0e76ed1d
-TAG: fcd801777cd76bfdfbaa32b87cbed954
-
-# DIGEST: b96789ad37e04beaa93bf5ffa86fab7a
-KEY: 89ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7
-AD: e713710a025cb8b9d71d29
-CT: 39450296b89e1802b61767c6e72bf5bfe70f89d56b9e879cbf5854f4a2d7d263b21d231726aa3cdab3ad5a2e57e4b99b98e04153224c4cc7f47eac87b5414333613e2b91ab7bfccdd7658ad2f8cd9c806241a029a752e811bdf78f760ffeb69046afbefe2655563e60041d57bfa747105e8e37c2dd26eb1454797eaaf6a94fe3f5c10f9126a75f0ff0da8e689892c723bdadadc1e96abd921a9c4ac1ec71b5e24b833a44d69bd3e6fe6f8b74bac2d31faa51f6ec26fbe4eeae855d8afa0a1142a7b94be1155e602350eaa37fffa7ec70e6809ce0aff298a2ed57712e605202693bd65a408252f5ab15b457f2514b13d30bcd5a8965c53eb0b31dbc9469f465c0f7b28baf765e52bad2
-TAG: acc8473f464b94b35c40cb0029b7d225
-
-# DIGEST: 4bac3f2c8e06db31e888e86fdb0e9109
-KEY: c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1f
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a02
-AD: 5cb8b9d71d2989ab33e978
-CT: f79d7ec76ee4aef607dc89cef7ca620a6eabaccec78182dcc4e0649bdc917856e2c4747045900d40ea88a6b4a711c46b205d7bf82f2b3b47bd1d7886d14d77b27b1e3cdffd9bb4f1840498fc4a44fe2bbe9a7a07e10af037e07bfde75429e5c6b0a0789ab54c0f36f7be55612b7f144a054b1c63f4352ac61afd274acaa9c0de3be721a3e8f791756f624bae656b9671cac5aedda12e29069c9aebd0215c214f0efc4dfdb70a6b6ce3e55c6e9777399833594f15af9da45f96bbcb51b1bb6770fac0953d8d28db9ccb69db7474b110eb66d3a223c4e00fefc6abcda02cbf782f1fb4e49de6f6904ad2247e2e0ca98d14f9cbee03a818207c617f240eabbd489712c8e81598e6ab4f7cf8e11ac7ad
-TAG: ee072123f03d4bd4c5d2a795ed0bfa1c
-
-# DIGEST: 21c8985b6544843da17ddbc929dc8635
-KEY: 85a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d
-AD: 2989ab33e978c4451e3be5
-CT: a1f0b82e614b48e9161590be5ea456cb1a7f359fcee65baa3c4722db30a6f71695b2655d068961c0e7d85bfe9f7debea517a1e1f6ca29f92c8459ec690c1c8f2d2418f7580af3c1ea9ae4bec66385647fa5b5bd086da66a9922ad5f748684616a561c14cccf6cf84617c310e7efb265fb821ac40bc8f4207bf1659f03572298b4831348b25449e28dabe3c7bc03efbf4aa46a5c89250d1b998510956f2aedb8884af966392cb1d93aea023d437f0eda920f737dd9b0eefb322b796ea518bc5ce1623a8ed6b7583c775f67576a5af84be4af8d407f3bd2c7e1daab23aad10c3cb2d687dd357be60f1a5b10842495a589181ceddd8dfa830fb0e32b4ed0f4c5719cec8d2e448461d04d787bc0991c8d6b540c492
-TAG: 5c88b7fd810b7abbd5778822ab1ec00b
-
-# DIGEST: 84e1ca3e134c38a2c55ca250c5d4e712
-KEY: 2feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e9
-AD: 78c4451e3be585a29a2af1
-CT: e136fc48bbd599988a05651edb20b3a8c6ee5a0a867704fc0556beb424c5cea45ba88d7786d88ee42e1a53fbfdb3c6fd93f5d3f3fd3f63b38020d05c20e734c3b5381d5206d11f0cd1e1d34242889285eeba189f03d3e61a891fdfc86a2c064f074b894379690f37af0f4c0f057b2dbe1ee7a1587c933a9f162cbed45bde8226343ac96556ace1d8291c21a09c4dec032b0475505a6e5c93aa2295d332783cab15bae1172eea1d87a0617c950524f08c7b4d262a6ef90b76d25e82a88c29306c04db034c3d490886eb5f32572a004ee3e2d9cc060da61ccd8e5abd4d66b928a85ef8377550577c68d688fb4ad5a2cf55351e970d1921d237eeb591e63fc5eb91991570e0f9ef0589aadfd3a7d2e8a8155dcadf900daa4470
-TAG: 0502ebe6f59008fb5ee04b01c7a3363f
-
-# DIGEST: 5093568ec95e8396c164aa3030fcae39
-KEY: 63b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c69
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3b
-AD: e585a29a2af12feef71e10
-CT: 459f9d14cd8f13b022eebc4f8c4d285e572614284cd9c1d7d027e5454bcbb02fc3f442359cc92b50d896fbac5190ac447434517be69f8a0e208754aeaf84edcdb3650e6f468603085d9388ac83e2763bd816fa4f854ba6c8aeea93542de8976dde2478ff3645bd8404d9e65f4cb7f85c036f6198c61446d9bc3300387110e503c08a97d469142286a37a9800c5602c41b56e3f6240c5b93b2d73f61a6e922c102afbe4e3935910c5c2b077e2d3a995de6459b2e949adafaabc8abdd48a6d186c60247db4943e2ef9c190d15510c5e8a45f2e49ec9a4f1a215b536adfd76fc269c8130ec63af4d47c9f6cfa03e4b1247b3c4af4da652be0347aa7dc870285b57addc01259d2e8e6ec63a23e578ed421f3b28b71a01470c1641db18b9ab1
-TAG: d399cbef21bf65decca41c3f8119b316
-
-# DIGEST: 246725d6fb787ad7c0173b080b35b378
-KEY: 99200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2a
-AD: f12feef71e1063b0b4e6e8
-CT: a2fd3237069fdbcda3be5f0e85896c727073a84cd9e89ac8334943356ca6d24cf4201987bc79e019531bd3ffdf480324e793d2fdee56a4750e6ad5efd19926f9e27ad42718d07635217c7ce1694e9fc46fe01c9524846115a6c1d388fbfc452b1a39b58cc790be461965e805fe365a4be4daeaff319d4ee29c193a530a3b32ad8088c443fb0a13883f6b701dc23121e2a4eddc039811e672232f23b1e43b5b45142797db8abbba3ec3e8c5ffdbac7ebe7c08d75a101d306475cd4313b5d984acceb37f1cbdfff8eccd1657d8dbde90b3fa81787ab4f1aafee1bc8915144632abe207e40e21dec830c623b3f6eee9dfe9cd2b20c94896631bb13942d91f379ff1e3ae5e25b7d675dfefb03b9381bf38597e0dbc49bafb7e89e49141f8f745bbd9aa14
-TAG: 0e5e9961ae44d700a04fce952e85afcd
-
-# DIGEST: d4de2d03937bcffe13fddfd19515bacf
-KEY: 3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e
-AD: 1063b0b4e6e899200304bd
-CT: a679a86894007d51968a6888cfb5de5f6bc2bb7b08cd4efe96fe3461ca2c25017a41301265afa33576e26afdda11123eccb52a3d6a23a8ad1e801884b904e7ce355a021e67db52646d8101e8aee43c4268fd6bddc4510c5f609006c29108f77e0b4ae86eafefa12297bb755c53f1da2dab8daae08dc835de9af62bcd86f5a5efabd951352bd192a79128286bd3c565d37d7bf6ec661b47f881273c79cf6d842e1d0ce8aa28e1802204a56ef2e96ed2ce222cebc15ebd55a7347d8daf5207c0252fbf996c02b4df8f8aa2df4b61ac99f4e5e8761a2af3aeaf4dcc5d13a3fcce9d879cf26052e2956245693577e3461aa6d1bfc8ef75215e654a54871fbc8820095ca359cb69dc1ac787ba3d970602b99c2b0930d83a2bd9454bbfbd284b247627478f4be0d37415
-TAG: 949d1a29247bcd1db77841efb6f99f95
-
-# DIGEST: e05e927c56f95359635700a1da271149
-KEY: 7d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6
-AD: e899200304bd3508132a02
-CT: d16283ead5f35b89f9858a70377cdcdf6294e940af92cea417ce4e5068dfad75ae6df2ed06c9f8f0cedb6f1157b91f4fa4f642de980ac313c6ddeb67d8ebac67d6bb19cde1e4ca8a61d67154d2fdf09b81547dda42286c95b30106c2ac650c0f34a81ac13ec1b0cd861fa57475b594746047576eec5d761d195dfc3efa6af36d0bb78e7aa9601bc5ecdf7b1649ab28c780d5783addc3fb9f0f431cfb02be8f17dd4d723ceaeb9f7255d50371623bade2281ea7ffe38f54caeaaac690021750011a467ef1149149d3833a3f01d685a44c4a887a971d4cc7603442ddd71d853ac6b0d2f123a84e9cbc1af1584b83fed2dea21129480bb28aca6da05e0ab34b6b9264c541bf19fbff5c8e27058e5dee9740c5b2a37536c3c21e892d169422ccbaf7678155127f73e9568ce8e2ec
-TAG: 4fb29de227ab7186aaa3c85d04f66b8f
-
-# DIGEST: ae1092c2239a594a279f35e189cb7eb6
-KEY: b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf7140
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304
-AD: bd3508132a027d1ff4c047
-CT: 3f680d90bdc1c9f6d2f059a095c1e65a301f9d2797a5f8b9ae00d5e4336ac04563eecefe3b0f11c3686d2aa6210dd26dc5ad293c259f27879b3c50eea7e28d3a1256678927cd3e2547d4071cba797337908c8ca7c63c6939a859f00ea931c17ef0933a86cdd5b314293dab83c704bf7af282b9ea2d3f01d07e4b4826309d4bfc5b38136bc361dcee664d60a696aa6ec5faf85c464093bb68a559538583977bb8b1c25fd1f3bfab680b15858892cd7b9b728c5a531fb9f87da8d5d9914f481e2d7ef41c340498e732abadb41ec3633082ca9af06021ba6b85fb20ae6bf6cdc31dac12c86c2d594fd58047cabe0f2907efc48023c12a56722fdd27bc8922dfb503d83accdd4439c638a845933f8a0957bf1f1c4a5ed40f42019756c2937148624282185dc2543bafc2d15a36c0d7f5aeae21
-TAG: 516bfe38c7198500cef83c6c7f9f7492
-
-# DIGEST: 9ece0c0e545ae7387fdd4fb638cf1c97
-KEY: 4706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bac
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a
-AD: 027d1ff4c047b3ef4f57a7
-CT: 4b19ac559a3197b7dec47def0d9f3b9c3056a4686c1eff225b6fbc86ce98e26d40bdd899794d70c43f96a9ea7f01b5fa41fd23cdb0310d86567e90086f84ba87a14158e974edd46350cdd2e8509f1a7de45402ef3948e779ff8455c411b060d9215a0ee4c2d3a7dfadb68abc228382d3a9902dff2c42a80ceeb29a9e2a116e2532d9d926659aa1be2abedab32b7832af8cbe890b352b60615a1613a30f63634c1a7b0954d5c5293705543d7cde4071f07dda1ec304aa97038012cdfc42e387ab1897b1163bc7dfcc81d1dbedcc4f2d76956414d288738d09a4aad3cd419fdc076db2b43835a6aaf48108aadbbd7b3bb1fac080bace769bea9bb410a08a1ec9bc54f4d905fa12b5e4407ead0ab18d939e7fc89ef3b8ce8a631fc7dec90c1501e5a2867a0f02841255cccfcf036001415b3f2a68bb76cc
-TAG: b7495b69aff721937e53b67e79fe9903
-
-# DIGEST: 36c515cb7b0a278e07c0a7ed582091ee
-KEY: 1c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cd
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c0
-AD: 47b3ef4f57a74706de4b38
-CT: f73d7dfe80a222047884d5a239db14910f3adb64eabd0c0dfcaaae8f36205d62bc9f187f6bd6d3a1264ac874621a1bd1bfdf64cd921cee7e5267ca285b885d89181ee6efb49ab72b5d8bbaebd4355ec1113979e0af50c8232b73bec6c9d7bf07b357a23278934c548353c4fbb10f18da7f2c98798b6e6a33ce111265eb12b43062f2cd32e9907da455bbae284bd50e4f825c5a9443bc568e463bf705896c2f810946248a196173379ed69d2dd725e3ff36c2555fb135fa91bb81eb3ba21f2c283481acf0b42195e8987842cd8a78236772a50c2dbeb20a5cf668c07445eca42f88b1194d65892c9a681a6992df5cea766249b9a81ac476282bc1e91cf79d20a201316073b944f1cdee02b34881af4f0ead3e40aefa82d4ceb43ca0db5fb862e6aa7af4e7c1bc99d637b8fda3db52d959a35b49ada10addfd70f4a5
-TAG: ce97f86f02b0b1afe560706bb2210d3b
-
-# DIGEST: dd3a8764b876462d81cbebf4ad39c062
-KEY: 101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed0
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57
-AD: a74706de4b381c692ef164
-CT: eb33a04c1729ade767e620bcfcdb1a2d0fa2a6b61b9cf904acc7fa71d77fca4e7356d5b3b9807ee6649e50fc806190e400e928c15efc1df7bce97a18329ef9ac8cf95bdce146213a2633a8991afedd50cbfc54e449477b413713b82afe6a6ca48eaf72e2b59bca771c29c6b637787cd39acf67775e83a140da427b6ad424f52d7fa880fc0232ad5c6ce3506f25b130b7d62b524c25162bc876ef639b211eda8100ba1297e9491aa98081551a1c97f8a12a9bd3763c6a5c25b62fabcb9bbf826faab0799a4513fdcab7fe97f66ce42240b24017a848711c21d2989d2ce5ec122e280b4e5f3f0199fe31f0df1e4bf5b142b82a34baddec8103c7ab5a448087c5196e3873c8544b3500c12a090d55c4001f79be432ef727df68cb784cdd5a2aef15708e016e50328c988d483758f418b300b0848272f4e1ba272ff6241fe9cdb237
-TAG: a47c8af974512cfa3b6c6fd236a87cd2
-
-# DIGEST: eba2de7ecd86ff37ff4d61f3e1e3d72f
-KEY: f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3d
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b
-AD: 381c692ef164101b89b476
-CT: 0d2192253fc05f72d4d62247cc195ea9b458c843cdb9a1393599ddef07140a5fa81a2856a95e7a3ae730ef6c5a45723be1d0414a2fcf3e3eba5474ad4777c811a6123ac31f554b7bace41fb459063bb9e6b9bfb2e7e4547adbc2505ac639d88d90d40774773ea3fad2278299bd15fedc8df67a6ac12d9fe41d352668f6a8bb61690f4729cb9ca062dc95efdf50672a9cc223b4511ceefb9a2bad8aed8695aa3b917df075f779367a3e810eb2f3ad2c6acc863e1cfb920e3ebedaa36b369c0842a01cfed8eefa5c0c346d2ee29ac87ec69e19e3a7a04082de9544e2613abb3e8396ab1d45ef968b3b046b0e40f6643558f8442fe99db6772da2e4bbdc7e56ee0d510bb8cf073d2f3b17138aac1bc615d6c3d6ef73973b8f3cde408ff39972dda05cb00715191b2cb3eef6b65b9e65d2895625d917aa93f4f5b036971946bfdc97b0b382c982
-TAG: 4a6226f65e03e00a10af75ef1bf60931
-
-# DIGEST: 80bd1368959e19759220940500549997
-KEY: 520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef1
-AD: 64101b89b476f72b27f06f
-CT: 6abe2dfbde9951d744772997056157f7b2e8e3a6b25f071533dda8d0b27359fc47f342b50a472393ce6e5ae9d2121cfc5ba5d3da6df14732b5de01f8ebdc879c2e771d246d63b73d294ce60e770828948cb079fcd99e60b7746bd4b7e0fb168e53923e75f4d4c34efd8ed885aecb530a179efb52b14894df0a2cead731504d7a38b746b1e4e7d67dd8cbfbb07efcd7dfdd172af5c211939d2cd9216cf43443236348a66dabe1a513900244e35f5d7547ebafcfbda780f14da527b960aa6b60ba966c1ca5001fab69d03bd0c041aa99983261d9096f5e0544374966ae118dc7992d2c31fe010f5a62cc8634ed367f662f68a5def3e63215ac265457821c037c1096e786d15d53f182744ea5257a772cee1874d9d51c496780545a862ab00936665c95f4aed673c617ae73604037dbecc968abdf51ab4bc27d26d902ffc540b256f0ba22a260ba979d42e7
-TAG: e1b4e1c6bbf04bd458426f3876d22097
-
-# DIGEST: a0b9f45ca992ed9b963ad071bf5a663b
-KEY: 71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b4
-AD: 76f72b27f06f520c9267cf
-CT: 194c831a05be6d418493dda7aaa6a9d07372a5963af2a984ee3cd737e59e112c64f4d9718e853ae175ba99ae410c494aa6f42c8ef119651fe43bb7f996e1b49c0172b698d353e8733009647030761506ea07d1f3fad5762f78c17e77a4917b88889f5f0df0e6357a794c88395500eba9a2c0a0bdeeafc7d21e002555c8c8fbdb6938da2c4b7c86dbb670dd00d652ef0c85858133f6705b4176e8402a15fc89b178d52a23250ed20e0846554462bbcbabaf2353245fa790c1f2af272a3942d8c1af05d1a51d8fb8c5fa0382431843290fcc57b2a18c680ddf477b1b1ab33dcde5b7bbb590394c53d385ca7ded3577d6194579a2119230b32508426e410a1d25c226822e0df8b7e0863a17626e9a5635803e6944833a4f7ad2beccf62e867246f9369611b82c73a0ef86b7a8251784c062126dce9fa18349a64e3dd0cf0991ae4f03ff6147ffe0ac2eb165c9793ac02d
-TAG: f3ea0d8e769fd49101a4154059a283e3
-
-# DIGEST: a5930aa76a853a73f5dd763a2572f0a2
-KEY: 9bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b1153
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f0
-AD: 6f520c9267cf71408a4172
-CT: 1c5bc7800a13f2468acad45aaa810fe4da2a81439138ae78e6a5388dca296bc5225b53b94c2281b853f7f43bfe20b3190e98a7249af1031bb82895964bda30be1778468ad6d368f89753f19eac5e0c664c4ceef98d256067252f0c673af00cbfbfde412a363f72cb6e46aac0f18d757d5fa1ecf39501535c533a445eb94aee4445ad7515935b7768472ac850baff6a5e4014e1a8207dcb099b9f2f7b0b49fc9d535eecf088493f0dccccc0ed5048f6cc1344c7f2e0fc753b4fc060192ec4a32c92e883ac3c685fb1bd1b988388543f55f645e6d7771163bd1ac6b56eaee7f98326e39ae81bb85a709ccdcd1aac47d1c00b0a390872b410a9ddf5721fe7020120d557a4e1691eb9a15a1d77a3d79690b9054dd728f0720242b22b6447d4858785b4f90c82205cca3b478186aa4bcfa85bb6cba4938ab4201c67a5e7bf38ac2cee50d7bbd4cb79e3c878e89b980b50e5bdfc10d865
-TAG: e6a8da9c91074fb0324ff09d2b48d81e
-
-# DIGEST: 315afd11af4c2e349f72fa47a311f7a1
-KEY: 72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267
-AD: cf71408a41729bacb5877e
-CT: f7d2481624397f43bb5c981d9a820e2d3fb6bf30736f609fdfbf2740567b6affa3e27afbde7029951d73de2a72ac9f62ed30998aa5ef6bd6c29a8c969e4758b9dcc57b8fe35a0395fc693132a03facd2b331bd0f206d6c589505063fc6af0904420f3c95bdedcfa18a876d69aec2b2fa80deee6f7ad75ebdd32b998a5ea384cd2c34c1b9dafe221bbe1265f1e5c18562daf53622bdbcd392adfa4abb7be550d25e7c3a0d3e018739297ca63f301b511c05295a664a022ff165059a1c3b076f4fe432c848c567d75d939b129d4ff8fa4d556c07c9804ea9d43c1e84ac83943d661db620509b054e9b6d0a93d224f517afe457d5de28fec444e1d7f0cd22325f810eb7e1d4150398a4fb6af454c0cdcf8eb0ad9e69003f61c67c607765cca1605dedbf6269a7a7002e11c34082377c3f9cad2f00c8db5e7b4b5bbc0c63dc9350070388c4a5adbfcdde52a72005315f253c265540cfdb8486130b
-TAG: 6aea228edb0f4372bf903098693b24f8
-
-# DIGEST: d483a58882a065609a9d5450370d7777
-KEY: aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a8
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41
-AD: 729bacb5877e72cdfcfa76
-CT: 3de34ecd09f2aae12e97d600a345a04f319a680d6428d5571c308608ef71355ef9ca2a05c26e053f2b8beb66ba1184ef0d231f9fd6d110632c85d5d1044b60479a2d565eb103753cefefb76492444757dc0edd889eb75802eb596b79b9b52f208949195af45c58070821d38a6895723645b2d3647c99ddcdac610a3c9b6a625ecc4a3ee62671583978a4a6620e6a7b7346593cf5226b242d13a0a41febc01de7cf86c5c2ed73700be6f4e9c088b1c0b3552085bdde8e8046ad3fa0f9e489affe4a7aa598208a5c31772968b5a7303990335bd5d2dccc73825a1e3538e8604adad49b1a56292b8f603b28341969b59d562449d7fb44115975bb935b3773a813be249942c296b6e7af8bfd523df72d584d5c595267dc9dbee88955fee403ea1b3ba4513f2c2459f8999df5ddaf250dba7dec60436a25d654b773bab6f29909d99b8116eb3c84b86334273332c6df2b4b046bc9bef04bcd28f7e70620fc578c
-TAG: ae4d17e81b38d7c428518df347624951
-
-# DIGEST: b1baa9d812ae3a18f6d8d136e37e87cc
-KEY: 7c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c67
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb587
-AD: 7e72cdfcfa76aed06707a0
-CT: 7225717afb77db2d64ea87c29e94dd5fe18c1e025aee5ea854374eb38c4e43eafdd25316ca8b9a1dcde09c7e466a3239e38802d6b8f9eb2705fef5e087ced360c21cfc0d829d7fcc30a1aa39db54709fdab4ea1316c27b089c408ac38cc25f46e12bedcaaf9a41401c960e50ff33c7a4495f8a7302fe162f9dca1e84d1e1072da54b208d809954adea892597cdd2317564ed916a5ef610fd7de114dd1908d85a296b930c1c214750ce1054f7efabf9322ed3bff62da0cf1ab7ab1e298e2bbd114497a9c28fa69eb56cd1da070b1ba0baf8fe2f8c17840b0ba0ca835f41461bd3d1ff24ccab828d95bec0ca78753f4e52de047cf9401e0bc6082fdb5241ed48ed8c128037d83b48eab5a62f744510c204fd9bd1c79c68599414ce4d8a47bfccbd8916994df710b67d76ead650ce9079a5e8f2eee07bfcd7788f50fcee862b449c0b4b14722be305bf4a6aa87b7f22c0ec57614ed8675fe13987967abc3c8a7457435076
-TAG: cf99dd535f78aa458de539eb64b6041b
-
-# DIGEST: 68c0be56c31757f80c17a0532ed15886
-KEY: 19fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bf
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa
-AD: 76aed06707a07c3dab6997
-CT: 4f7449235ca434029ccd8af844ee893341b9128005cba959dfc49aad362580fe45eaea25ecd5fc979118358a845acace1ed0bd4c22cbe87bd02db947059d90c8993f2db02a23b3a8508fe7d9b63cc4adcce8b6a2d11b2da2f50a70112824dcd574c4a7f3f1a5d59f1858aaefc1eab938cbb730049fada7d04d212e32aa5bd64879ce460aea7f50da89a68e6708c32a1ef919078d3078f97c726e5516dc6d261cedc1fc3ee622cc57c4d23fe13e2cd862a57d662e29bb47f7a7d2d3fc58221809614dcb222cda362741e19304212df3ebb4eee2979f97e4f1442c36373b65a894a7711015886dd9475f86101775b46510132c2c6a5127b1cc8375c0baa31832a3ae292c5f39f86f5c07fd49e8c84e5b4d6d92a513c39e290a1d61ec38f6342a2c504aba4202aa776ff145a23fc324c3d2ddbd75261c3a1ec205b87f9559c2fb55a79a17ef8be69d81ad67668794e70d032fdbbd131524911d7e680fc873fa0627240ca02e539aa63d
-TAG: 9984fe499f6a098eee40c020eb8ed388
-
-# DIGEST: 50adef6da405084eefe2918284d8a2d7
-KEY: 2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49d
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707
-AD: a07c3dab699719fe882eee
-CT: 0ae257c9c7173aac789aa20057588a6cdaefd34ef91f9e50f2c8040de3b8d8aea82317bf6bb4f4cdebb4d9340e5ba99a598d520f23660eeaa7b946dd6d2597b40d665117514a0a68309f976e2355892a38e061438ec9a67e2ea938e38b7e58658dccb67296bd8073f8cd885b6ce363ac62282586dc78a2a53a0e218c1039f028973831c1bd11d384a34cbc051a07fc0a1786b7e92c99308b063a61ad07716377b5da64e516bfb412dc138718d3c255a04ec3d307b9f2ba90fe30b51a7506c48e0c25481d8e41da097bea7c97c41308d486c7936c4571ff539c09f09172817a92a0b1dff415c9eec36a6e8309c18e50c2d232d9d257f48cccceef0768cb1403a2cbf93b50a7a75fdb2de73df640c9471c646b6494062abb198f31793cd1b60f5893fc662b9350c8f74404023306d1cb4205f6a4bd131d39a29cb605269836526fad6e465e11f7c7921bcfb44996bcee249ed4fc2fef8ac7e8cca4f15a5b1b8f5f29c281de89a438897f2a890e9a
-TAG: d2e2b9bbe88d10e89bc8d8aca69d56db
-
-# DIGEST: e0e99653835661c7becbd9ba0c48107c
-KEY: 11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b97
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab69
-AD: 9719fe882eee2fee55ed8b
-CT: 3010e2287e92a1a526eae166a6b09341cdd17e0c96b017c534dabd4e197a7c7ebce5217819bcb253e62c6873ef97aad7e6eddd92ce5ff41346b92671af2a8d76ae0442b47ec241dc20c38f1d0e34c556eb820ed17ab67196cdc9c6b226b151a729ca0d7acf3263973761ad32dc1a81cd8c942626f4d4ba67e3ea73041ee107896bd62e714f147176802b013054f0ac8eb7daf750eebbb585b4fedc67972977a22364028c445ddb6441a2378f8f17c307742615f9b6489591d8ca2325c699d38e4dec8c7aa65eea7bab6d720802729b3dcf7a3c3ea48e4e57620d51fbf34e73df0df27158a815177195f08d02f0ae65485b9713a3b313cf7b042085ea7c3064d4e5d307efa1dafd83e05ce672cc8bbcb59a196d967eea3674d272827c210f8efb3377d627d1393d7478fa6a240dea0eea7e251cf2624cb6a679ecf6f5009a91b8b97f868f60b40c5afc36edf970682a15c9d8460aa669fd9931edd9d4752cf7d6446efbba62da525be96039ed9c24bfe283c4
-TAG: 50667fdc0f53c729370589abbbd7bb16
-
-# DIGEST: d48b900f00c5ee1a629c2a0d3d778c0c
-KEY: c695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f47
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882e
-AD: ee2fee55ed8b11534c870d
-CT: 20e3e0f8f68b311c8a8c97338cb819d8283ecd8f7f7f743bdf66d8f2b7e9bde6de26f2c6277932cd444b69b2e3b2dac804a30d10777d52d70136a8177d4712b271b5c736b123b5912bba0ac479a31b8b50fdda2ca0b79c1b95b7e7bbd7f3f87401499fac1db5854def863c53a88923a135303897f23679a46e954f24bea2ae06f7a51cc5a7bce74715abacd29de4523e3dae5c8477b8ccc65dac351d289efd8813e454981686e1572b2d86119cf3c91f04234c7af6d4ceaab3a74e79021c2d2c6918343e05f624b938f12e0330586cecc4084969a9b02cd74181634a21dbb8192492ada41740d4f20078a3c6e378d2143ba97945c714edb72e758c0fd1a157cdc0e5f35a0435c055916360e6231e84f1cd08c4d9683053c6f29269cb3fb46bbc2136dceb4d98305f856a46103c764545ef40847e9c12e417c987f2eea838dbf6ea75043144ade176b5b3b896f8b8e6cbafc218bd326604b180da71471867c352fd1f414f63c8de94e103bc1166a78d82a207cee234b93a
-TAG: 2fb9bc483ed2925eddc2cf1a541390bd
-
-# DIGEST: abb7c6092e4f729be74a8c66291a73c3
-KEY: f1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed
-AD: 8b11534c870dc695b814bd
-CT: 6b19aa9bc626b77e79f44b1315002722a9a8486ea24c060de42d1b929c04a1832cf62970834cfff3ea251d234896cf164ce850d4da613c01e5a00fdc364bc3eb07fd20d7dd9f48f48bdb171504c7f9fa593f9d559be02c913a8aa8703433e024f6cf6116e056b529a32d2bd8c7800cdfe69279da869c5aa1acea7ad7f90605d0cf6eca2d2a8b5c14fe249d7ebd51e87fd7884ee88291bd0ed8987b8acf19d35cc73e3946d56a52ca40552b33f50fb5fcdf1b0f167830e5bbea3b75742ddf0a3d615d258ce30743ea4bae4e4aad54dd197acd69cdcd992f15eed07767b473ea814f602bf43009174d8b56d430346e9eb27ebb1b62f3f442cf61b4370668f6f751a722b894e0431280261d2965bb52073fc22464ed6656f7100282decd12c116c731b54f020ef3a8acdc1a3d01b2d2e40451b515d0cb6505fe8a1e82feb109728a7c2ad6c422fbc9f1aec572fb0ab451694e0d521e2b3450db76446de4955c6e4d20a6854710b37a2e3a68e6a8f2cf43187414c105222a9a81887134d9
-TAG: 2808cb399950b4982c73a643999e3650
-
-# DIGEST: 8ded156a3f7c636a322f664810431782
-KEY: 2c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b17
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c87
-AD: 0dc695b814bdf1a87bb105
-CT: 09a18c4010560393b7dde422fb4437adcd75286d03838886b527650a29943c7d40c9f07efc53fb350191626feb8f6e2cfd37e1acc95b39b06d7458acb0d28b31894fe4b69a7c0beac050c4341a2e95106c41ff079164be6aef79b5ef8056d129f49085658a917ee9be071ebf3af499e6f7958092a3390be36c4495c73303f40582b92d3913c36a38d5f13892e7de420969647cffecdef25b99cab3ac8a2061ca1ea9373728ed1f9f6437db8482b9b6436f5f8c23f69b367de29e83edcbe246b0506c87881bfe09a22aa4fb525d6c115b7f9a171569494394775f80aad34aed1d8dd7d06a0cf64f1a40c91b006185c7d3944a7a4f33dd57a22fa25e077b7fe3b760ba3f5601892488a07ff07f57286438a5cec0db30945bb93ddb17f550c34a8b61466bfff81800b962ab1b36ec856bb6e9222c317420e217d76cfa0308a0dd8340631f7ea020ec796ab49e6897d9381e3aad1dfb54b55e4ed1892d36f3b46fff4400231619ae1d4bcbf59ef44309eb2e08732960ee6dd0cc9c8f122214a0ed8eef
-TAG: def243ec5a6a1b19bc054b1ff73d450a
-
-# DIGEST: 476f4c73eff8ef9dc0cb5a98ad24fac0
-KEY: 16bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814
-AD: bdf1a87bb1052c6755a7a1
-CT: 3c491ee5eb64f423375d864e1b7467ea216cde75a87a9a2876e275de3e50e1f53a412ff0a3168ccf1b36b96c5ce3f9dd52037941ec435f83eca175ebc80bb9496bec3b5239853a4ada2397fd9bb38299c7ba43f410310685bb95650272578a96b6e79be51cb8aaf1854f1a5522c830b9e3c13eed3c6da05e1447e856e3606113398a571d131efb9e86f3036919232a65dfc109c175239fe0f8f0c8b6f8766edbd1eb1204bc999ee45cf241b8f54d1f2e6e7f10ce8f8d4234146f42ac2537795b55254ce7775a66e79080bcd746d846a9aae61edb42595ab0cce3b89520b7a621118f4271c804bff9e97285856e153c21ed6c3a87b5bb1b25bef13cae57d657a51595669e36fc650a578a2431c761d477d659496a99890dc9c1af5ade6f5ea53587868df0a9e9de538472acf44baacb22ad2a6c61df427de3cb5cff939a1333d3745ca58a60b7a4002f38d4002fc60ed6f46c00620192b7af86921e66b585907e94bd02f0fdfc009d942b875dada16c20a142ee9284930d8ee5de0cf6c6a29153e89bb38caef5
-TAG: 3d2dc3732f579d8b8b13954acbc085aa
-
-# DIGEST: ee209d295d7f9be542fe42c2df64af23
-KEY: a49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1
-AD: 052c6755a7a116bfc9095d
-CT: e4675723aa350dc1a687aa917e6783558cc44914038fb94b8632b7c6dbe65b415eea890a95c94113291c93eb00a335db45b06ae6cbd9774aeb1f9ec2c4a81bcd12807274081239b2702dcfc939f8bdbe15e9fb84106a70137572a941ee0cdde004779351f619c841bf74abc57ad38e9297896bf32368520004008cbef2b046afeb1ee3918208907d5605eda0991e289ba3cac2fff5fc4afbe11e8cf62a53be0a9789e87165e856c4a9a3276d560dbe108b9346fe549c80890d05673b26576aa7309441a2eb0527a24e79de926ea5dafd55a2707bfa1f98ea32862d2763298450117eeccc0566b9abd88fe8e6cc687aa26e3962a242fee58b2d09aa4f7e9e04c77f330eafe3c9da765bc373ef1bf81eb033c235a3181cd4fddb811796b8a6fd45455c80ed4059609cc6d29f5a012ebcc321d80550abf577fe797433e82a8bba1d7e5a5fdc02c6a6aba9f91e713452dea5f5996d211cfbf6bd271497b915fa0996f0773783ab790d889966aa5ee878e2c3b046a8f8b75e0240d97039b64dff59cc3b5c32ae9146a3235b06cc
-TAG: d326b0325b79b6b48e698664b5e80174
-
-# DIGEST: edc76d971fd21d71ef1a5cebb4ae9ad2
-KEY: 4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7
-AD: a116bfc9095da49db3d71f
-CT: db50a51a5d6b71e57175e1611e6f808aa0d6b4edd19ecb7a7e1ebfd1e9532255885a4e81d94ce19c7a0168611305ef0acfaaba9bb5d0d1968ad09e9de3b2d3115a716a9b9250e49a75fdac55f51257bfeef4308108ac90b79b47374b7cb392171be9f6519ca0e7c83de0af351727501915f8baa117c811b1d74de65be00bd77185b083fad42de80acc31bf1c6b5b0b63e38169af7ea33faccd0de72ce1db117135bdf814acb4e9f15d25325f8dd00bd31e2387ccfafbb35951871c77875f22abd4caa01cd23edde2196191c5f04c41723c5a098638d17ad470522405f11457989fd367906d3cbb48894507cd353a8063c579ebfb115f9dbe0efbdb44eb8b6e8441eb8b5578986dc9277f28c36f1de32d990b29171db34a7749227d242e35b44909ab3cbf6ca78503968e8ee94eae6d47ee9c816a9fd479e12b6467b8eccba6d29aab1ee8df8155d60682a10589728401b9d51a70205b1d3b71f7cf7273921c4a3997e279180b0bc55d3bc73836cf995c126a42d76eaaa4b22d2daacd4821171d64905fabde6aad322d78b3ed09fd6f4f
-TAG: 65d126603707ec327bfba6fab9c4db49
-
-# DIGEST: 5b721a3d03aaf095d1cf78db00485987
-KEY: 3f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d7
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc909
-AD: 5da49db3d71f4b975c5d50
-CT: 1406ce3dc7845267d8445864db73229ca135f07fb4f5638a523b759e8fbc0066b3b6dd9cfab8818d0286a394c69b681b0f254637968b159cedda768841e66f83901ae8fabfc437df490213c5300b4afd6aa1e5c6b1e4abfc09c813bac1be874d07cabbfd5afdfaa12bfe49d2a57ea39441f318aa15a8f75e7a9fd2d4f9506fcbadb2b0252881e07b3c5a7143811d449473b83d975dabc76034427eb1ed078c7262d9e3429cb985db0bb160d5521658fb90c27194c8a763b0e9b3888d55f818c881624bb33ca7724041b3a6f5dd07480570ab1648633f770a6c3f47235d8c1b195b8e96e2fe4a714ed50a47b497e931492d1de3e467d2e1aac15ffca1ee7b0430e7e006452389fdb7ef605533fd411e0385da74ed14418ad85297b8fff50309326f3132eaf69da33ba88f34aad1c7c4692ce3fbe96268432a8efc4455c3614a1955db30dc29ff4c98257be16621d9da209211764e81b8724fec777a8073a7590a119cb1b7b5c14cd5e037597b14ead415299cd74e1274d6cca8d9de5dd3ca8687310db8eafb084e35c6e7a037c39017fab0c21379aa
-TAG: 8eccfc25e4921cc0eaae3fa31090482b
-
-# DIGEST: 5c230f3abc8c28493462086a8a988b25
-KEY: 8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d80898
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d7
-AD: 1f4b975c5d503f478b22dc
-CT: c0ad4239b406ac1dc560887de06d6ae3e4fe987e8aaf443c676d38af0745f4ca88625cb69233af7311836c55b8570dc4a2a9f1169e31857e095848560a04b1a7b4c61bd3e3db137a1f82f966dec88656d5b389bf3f0b50be88797e58df6f01e9d9481e70809e8f46a85cd85add45c9305398e5aabecef48defad6f2cccb5c21313b14a3e63107bac9b4243ea125d5d836260680b07adb55158d38362f1356a5699bcbb88b256f3fd0a66f56c47a6d2df819cb70d0e0541c30c3305d8952813dd3fff8b6cb6bb40f2e7234f400949676aff8cf2e739e7cdf5dc67fd2427421a7a4fb03564efa7e52e5ddaf796ace63caad1c78a9f3e20b1136f0cf8d91bad0397d5f40df198903e60dd83c301aa40af1070dcce46d53a357e94e2ae6c4036819e19506a80cb3611e9a21a4741e81f5be4ff49ca39e3040487bbc506133317d950de4e63e3e3efe4466e144c0faed616281f63e65d9f161c25baef639b4d9e41aa6293c627d8228bd246e467a2ae01451acf4134f5739f0331a06ba8de782fe7108a4028e14c909853954b74ba7eb15e08185d564fb90ce105c349
-TAG: f605cc66de00f490bcda9e3bcbf5683b
-
-# DIGEST: d001d4aed1501085c3016f25dc21e03d
-KEY: 1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea37112
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d
-AD: 503f478b22dc8253bee6fd
-CT: 6ba5329a5e4c1046465f82d79e7f52383709be8f495acac7c2fcbfa27f58c59be0c972e035b7ef2bf6ebbc2e040ef2a89d883f5470a6388090c4713bcf366da0cc1e733dac332dbbb4c230e127ec8354980b568a4f8154eddde1bfc1eeb475d13c211569eb4ee25a7dbbc8b433bc007490bd9b3eb003382dfd4bac4a0779e7bb6525f643af6ace411c9054293f8f37ecb7e3fed821d4a4bb34240b8781f0dd78aace6b9861e794e8b9ed17c5ff24b976514dd09ca54a78262dc99dfbdac0e7b93743054fa4a49220d82dc4b4319284c216bca05bfe2e1abfa44e0f8ad94e6250f22b7caf17fb0ad5617cb9b754b28f151197f68ae3a514a738bdb3f4ad6876723a9fd92be504e36bc1581f7e388b4ed98ab01af79d7d1746d437eaf16d7e9bb0d8556ecf9e7f94ed2f769d7821cf01ed8b23da3b2fcbbc27e644748bbdb1c8bdfd35c89176a11a73cc205ec7fb7ccde0ca450120a20ce1c0d4d80d35e88bd435608a9400683f97909b0b9c8439b731ab1daddcc17f6f19e1e57938acca374616d5ef23d3504b9e94c7aa89957669ee3e5710b239facbae874fa63f75ff9b04
-TAG: 0d460ffb50fcd449c699c58151fff8e4
-
-# DIGEST: e48e5f6e6f73c0625e79057e18f2ed29
-KEY: 01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22
-AD: dc8253bee6fd1b174c307f
-CT: c50ce9a6ba84423a28c6390115bd9767c1202ee4b3c6851fab1007b0f23d07f016bab18a8efebe0f09c0796b0725add60ee521823fda248b809eb317e40149374d95e9aea5cbde33ecea576e91a650e4be741f13fca2cd45cbfc967ece9ba219d5e4695d57032417165f2d29b67a9fbf6bddc0389c9c649a4de23b361cee86c3c86daf507b5a012ce2171cf94ef1019507265c0cc35d06acd936a5dd05a16a8ae8fd5a73939f68634347d35d4b6ad2b508a48e871cb51b583e8e628a24d68b63dd4a50fd9b907a67247109627faead59cdf0eaf3610bd74d7b45bc801b8e9e3780911b5017846035b5a54061f98a10b91cee3ceeb301503913ffdd4b0cba1e3f7f406ec30a7e7207adb27f3b0ec80605ff65ecddc01239838deec3d0abde5b36d743ffd5973b21e467e940fe3ee3b887230708f61d1e4417fcf756af1a9fb469d91ef360c8a1c2861481f61a137b308a913c15b469d6c3ab7b71f8bf27b2fd40e9e276f07d10bfe72626965b500752cc4eef16adbeb65ad98de604c2df8d20b5b69384e69a432688ec6b9225b3f473ff7b32816d5a28f6623706c1e411f04a531ff5bb46
-TAG: 30451363e2e03ce4f9a432d28d2dd44b
-
-# DIGEST: 1910b5dc71aab1b2a978c487f5f76df5
-KEY: 9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6
-AD: fd1b174c307f01be95abaa
-CT: ebd8b1e9abcef8eedef579b2bf37174ed8b6bc46cdb8392b4668318bf7afe149a98b3d3f9015285373adab1af0551f317eea7cbb56aa27161cbb165b6385689aa7ca1481ae2dccefb5721290da2044fe8d3de8854b1cd3822617356bb84cbf8fae2a865d9e8777b6833cfae5eec85de81c1b9b72b3c092758e59c10b719734c83633c9198f6f1e1ede2455defccbbe3bc9746af7e8526599a9b5de1057956ec88f7f970018c942be60e14e09b48b9dd0fa6276950cc4a4a73c3087d6d25243e5a95ce5c5cc610897a5e21ad281cf692e3ad7a4432d61d98560cf16234fbae0b1245424fe86ca94396629ad39a9722756b24fe764584eaa337aad79e823ee367c5254cc0421e40cdb2ceff496cf20e69bee39edd2eb38dccab18a3ac312fc672c2a3d252f0bcc1d1b25c85be83233601c29b89fb6a998ac36bbf0c572c184f94b402c3f9c507848751d5fe56e33919773cbc337b272cd8d9c78f54a431a78cba31b989b1db3ad1f1214522268ea9580160b21adf01cc9650253d8d22ad6e6877b525d411c688770898fca77c91e5545caa4999c839b26eec634c886808c793e37d9ff19f3e14bb1499b
-TAG: bf0653da28fbe42053746aaba0510492
-
-# DIGEST: e5b79a4a9a785ae0a9818bd752d81130
-KEY: 2305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12d
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c30
-AD: 7f01be95abaa9bee585777
-CT: bd52047b9c992ba4b657931ce78872bae84cabcea091e32e0e011dac1c372cad88c18b0fcc117a33dc800144b7418d5be64f69b38f174f663b8d980f5d1c38e75c0ca39014a2b641cf1f0101d6d3a3ff4e6fa5fb3de8a88086104b729e1a9675487820c026835be7ff6600cd541819f9c4fef670bce214c4f105f1e4155963b13f350d55f146125b937ec144d73b01386754ad073f941a3b45a8b934a74c2f554be441ac118faaaa97174999a28b569582698039f94c2eade7486713ac0847fc21ccacf9dc99a8e846a53ff5ccb8f2fc211e735ee176b834d598dc849ac59af9228323ae33721cca53505936261ac31b71160877b1fec885e5ad68257096511b4c95894476260a10db66003ec07cf3cd9e9c2d75bfe951ae4cdab5bb7e5fe74f462eb4651fc55d243c5fe04cfa2c4742652c9c62b7966b97d7c509899b64a642a9cbbc2ef723b3d0857cda68498d970b5892f2d273d5118a8ccdb0e431d7ed0874463fcf4454aa308c91bea7b89cccf8a06edb405f3065360540da3f52ff5821b85d7fe6944b5778c99d49f2612b65467a43960168ac8bc4fff7d27f9bdc59194513a3ba39a6c9968ceea8075aa9
-TAG: 7eb4040f290c97bbbb7dfbeb9a73f2e6
-
-# DIGEST: 165cfc8f22f98aba035cbb44802b73f3
-KEY: 50d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95ab
-AD: aa9bee5857772305daa4b5
-CT: 30877f875cb8277391ce1ee6a4d6d8236597b4b6ff92f99ff6a0936f5f69ca7b4ed6e665bd0a839a9308d6b19ff0759d4ea8a3debc68a56f29320a8d5b7a72b0fbc6c3db1bf4f84bbdfd2dc9d9ff1f7b88e5ac2e4faed3910e2c828599299e43527ed75d250f2821f5e52019474e2daff474621552e504072a7c6b29076ebcd53d6b7194303e92df1f728a868f4c836ffd0eb0f05782a8f737b4f799983c6965ac8c44f0821f1be485bca48b545cc8a0f7e61bc7e987a9b183ad3dc03c41a98fc2fed643fbf8fa10938ffa37bb79175177331006b5acdca04996fa3739963991765a308ceb8ac35c46c8ac4548add3ee3ef77f42c9b49093a7907a2f2b8195c53377654fea51ad55fcf58ca6ed333674f9cc2d9bec1e509513a250b595163848eeb5df23ea8305ccc1413c9a97ef94e19d3986d584134cc985e98d398790aaefbf44e447e8707b7effd52b6af3abb6ed2d1db57e016026e962b7048e00027eaa1a11910a2f54af54170bd8ad9b17ff55302da6ab19144167531098f977e1ecf1e374a956d49595b326c9c805040e511dc5c8ce0a56f5078a7c12324aa55da1125b82c4ae433337de48f017d059039b8425eb75
-TAG: 27006fa7a39b64eabae70ccbf884b2ca
-
-# DIGEST: 4ea4edf4c7d390a9465fd5ea4ab7d4f4
-KEY: 089850fea3711265bf782610460bfd24ba022e6da12dd4c27f43724809744548
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857
-AD: 772305daa4b550d75f05d8
-CT: 90151815e2c6af6753c265657ddd9205447a49eaab8d6b258d2aea66cec6ca3c9302e73a6e08b9b63679fe0f3b026cafd03e664d6aa7e0d7171aba17e3ceb2d11c63851becdab399f71081d6fd3f5c5cdc387b77d919a5f717f352efa4ca87a753aa81693b5ff00785b7e8228acca636fcf6163157362756e46d29ffb69d9308af60452c821989c1b3b2f1eb4fd6ca7e555102a052098cae1aadb4578f45067492a6ddfb435d4b976dc223cc643c9ff86e47626837b8f48a8bce5647340aa7aecf049c510a65d957041dc3525ad2a16936194bbb2deeaa53d5147ad15ac9ad2a1ad852a92e44b067e54a1a3bb48a9ca6e249018e10361d3d76cfe6a25cbe2961e70db44dc9fc35886501ba957e8568161d09c51805e2b09dca668151b56d2cc24bac15f21ef7c81b5edc8dd683c328099e41d91d9ad09d7b9195bc7823c97379322bf9487da0b700c625dd5a2481b609885f3133ce78de3a303afac64e980c9dc15a0fb1559603f2eff1192060a9297d33811c43c59f4e0bff1e4f56d3d86298fab884d133c3743c9fa86cfe424cf4e8278ccfa0e5948dc005fcef7784ea91a91fd9dba729e5ea0f10a1c419fb9f1f764070de745c86750d
-TAG: 6cdf4165f444005b25d384167d7c5fcf
-
-# DIGEST: 838a2cdb1f507acd485870460bc595c0
-KEY: 711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4
-AD: b550d75f05d8089850fea3
-CT: 6cd01c4259d58fd4781811a67322755aa7b9c9f01f3ff7117fa0c30618b7f8cb6140502f2b850d486ec4cfa1192a4b01644438d86a4c2dc0a94968ef7da5660d7e66c9b6d4c51ffc9bc939d5564a25fa67459652fc6d0f20f43d2e97a4d11139c0817d320f6ccd92fc4ab4c986bcfd29b0b8fef0b7d3c3668b31d14a38840980fb7a078daea8b4e42a26bb4b23755cffb5c5309c62b9debbed40dc3ecb9bad09592a254b59a17bf80371d7abc1cf83a6ea44da238be638a46d6d9e369f0311f5f9ec7a63861668082c7ee390ac2d822a2555c0d09695df6c838bcc2583b868bdbec76e050c1a36a5fd3720f277e2cb5d5d067c61649ba66c316ebaf237f02aaca44be9bdefe16c51c6007755158673441654aea29f5bca6fd2b27227c9d029006036d77c8cfe8bc6dcaca259dd87e0a5982fcb631c28660f0d02515e9b702314985b504cbdbc2568ee04b8b80a2efc9121cd6c2e9b72d9e4c53a939a28280c618d428326f95e64680a299b31150dfb6b2007302d0e50ca0ad90c8094258acc8689f0b44d405bf4457ddd284aaee75b27ee7d64b55b0f0606d76d773580a3c0214981325f4ddde19fb30716f01b76197b217ae650fd7a71b337e7a34e05
-TAG: 287b728e0f1c5bfc11427720bfadf646
-
-# DIGEST: 7c4d663f385b10207fa977d19d9234f7
-KEY: 2610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05
-AD: d8089850fea3711265bf78
-CT: 9b019ddfcab4c84ad95b017a7a121320a8c1824f110e45e4fb184718a034b289542fd9799b98645c64d045b185b1fc9f48544d99ea5f3e76771556dc018353fad7b26bb7734b576c64ebe9b45fae3bfd3afd9155af81fb5e96ee1d918c84cdedb853bd0b609fef7d7276802ffe7860f5faf59cd197da7ba0795105df1f47862764daa944128fb34c473e2ebe5e296841c0c705dc2831155c591a60af6000b8abcf63dc831e9a593107d366af4053fefdfbf532c03f4ee3b710ed678b436fe07cc2561773aa8ca2a065f5624ec157806c94d0813465f5a2a2dacf50c5f47d8357b14f977221b6bd291cf4f0be3a692d0664235529f0cdda9e4cb2a09ef7af816eff499fb6dfb9f8ea20a731036de9db7ab03307f2b762ca811f36fdbd67f09e4afb4345e64ef57b72e133da61cb8eb612e327ad79864fd8bb9c37461ddff66e6d5b8bdf6980d9ac9acdf03a76089da0173a79bb50c04c2bcfca0029b398705d71a64169bd58bbf392ac72d43ec445cc3c7aec3a99126be0733b1804b79ece6c6a6230940e25443b1ebf7ebbeeb3d9c13ce3de970bfd399bb0964a5179d34e292d19039b911d421d3fd74bbdb7cf21bbf2643b4410a9fa8fe565b821a94725c8667d9c
-TAG: 4526d0a45c3aa8447603075a765b73d3
-
-# DIGEST: e52cf395415d5134e78d8a6897f91291
-KEY: 24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a56179
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fe
-AD: a3711265bf782610460bfd
-CT: cf705822d1da98141709c1edb5e4947aac4e08869870133d1bd840ff14c839ccf59e5d788af01678e3b2db0b63be17bf9b01513f8dec4a45a685a7d50b9c959d5b9df8998a1532966ed6245b394c83e849d7fd9c78168d0309ba9571405566db6bf31212b1f63b5b1412a11c6cfebfef14d35189685795bf988d3f51c79e409e3c7334d6398f76b68b363bb300c82bbbbd9ea9a9ce9e31a5c4888d7b08a98f594e073803d5ea60a95c4a7fb6a143902ffe173a2939fc6ea9cb21cbac15147a6439fc2cc06c9386f1293e2fe5efd5bae24e218d86f1b6735951ba0f672d64fa1e8dd410def77ad2a6f10f85a3048c31c4e64c588c96c2cab2060a515f3e7d68d67185c235cba8c3f257f8d37e753974f1e95c29540a847afa4786eed15c34f7db0f1c722810f4ae328916bdb076533f0b357d4b3497081c9ab68e98cf26e453479a0fd5312d2871e6cfb2f8ef375aa0a294462bb73da14949c287c0fa716be37f11ddb6f7e493aedd94718f35bcfceb68717585e0ae63d13e1d767326f54e8b2eb38b3ceeb409f020d02bde0fbbc4e06d14d2ae99ca304fa32f5653ed44939749e5f972b0fb8a6fc05cf826dd4025a808b61e9412a8b1a8f27e64de18a35893262a79a8cb0cec20
-TAG: 617310796152e91bd763bf1162849795
-
-# DIGEST: c4161bfb8895268565ed0e2563b26c96
-KEY: a12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f311643
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf
-AD: 782610460bfd24ba022e6d
-CT: 57b0c0e28fa66b9736971aef22d7d86137d548a0ac1b644aab306a2f979d8542156ad2741a384625b6ff579919eee7323da113589a2a342597d11917a9fc2fdcfea1fed6cbdeb55de2e809c1fdad26bdbfee428d361644ca21f55727101a597e664cc7211ad639f3f765f4cb51035d6a522c140fa92c92dae39dba4535b52b3562520c647fb23ca569f634f0bf430936a7348f6bb063a683eca09745de2e7c842d20cc0eb06448d2ba52b08fb54e6fac2d05a57bb7f092f616c13df49e4e54cbbf94ce7a3ddc95bc4b49327cf5d1a4fb19cbbf78faff09e19ed143029989d505a8e7832815b9ce25b44f169c7c3ec1c15afb6b74e4c0b92ee8c2d2e61d47391d0687b5a0172c382623e18d7f1071b8c529dafdeee003b4cbba129ddc8e5e785246f6917c1074f29d915af8f4728d180c18919b753a0b056fc71a15a0e09e5ab555c62c6d02214c539eba966fda05dc8dea5fb4738131df72a53b83e6ef539d75282b8ff99a761cc885afeb6d849b886ab59888933db6b91362053f9552f626dfc8c3621c25603c2c257e7c1fc17d206a3f76253f88c468e5b73dfb8b107ed6960832c9955c8bcbdd0ddcf77d0c510029bc761accc41e9b344f753fd6db881a9ac2758b6f2c6b1f5787b7aa47
-TAG: 1465528b2efccadb4dca099468029ffa
-
-# DIGEST: 5316b9140451c44cd67cd9a2c9b3b668
-KEY: 4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460b
-AD: fd24ba022e6da12dd4c27f
-CT: b874f7a7bbb22e888130456cb93c867242b0a44e4d2497116092221e9fbee54545108f25e342c8e06c2a7e8d3541088b7bf6766a92769a39a1bf37b2edf90ba1a14aacab0649c518529880379f483b99a9c98e13b4baa47e79e1df049c843d100a8635614692514effe098f38659df69543cd27504feaf436d1f04b85b4775991855da050fa21808871cd30f433d0718aa141876355be2ede583a2b4ca17332ab7beea63134e65908999ece8f4985aced7a9f3b89cbf099115f92a343d2feb2f2b39968069918c62cbec80ca760c93de92518d6f4b855906752f909b0064bbfdee8b6d5eeed10b1e58627d96a660d87339c2647ee287c3efa7c80124876bd462eb18158007a5dac108e9c5f9295bff5de87b528a8db33fd60a52f394ccbace73e4711b3552087ce1d38955abb3ebca24fa4e5541ceb4bd162583170eaa3043b2b258e7c595816313177790b7b684f480802dfab03e41fa90d25f01d746c5fba48ed62dafb61b2bad3d66d908df7963d0ed230e9f1d6c08cfd5b3707221a5f828df6b3ac28b1e48651a4d89578724cc6e66b45e47e15c2206ddda622aef8ac4b3d9d9c9708ebe1605a5174f79ccb2c1d001d12ddbf9823350d554d9135fee7de3899394dc24d12b46e779f38d59403d6cbe
-TAG: ac394c05f2af8ec027b66f5b6a64f464
-
-# DIGEST: 580e929216166bc239b3b9137b2f00b7
-KEY: 454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e
-AD: 6da12dd4c27f4372480974
-CT: 4736410243526a37d14024099da6f50e51953a2194d38399e935642e9a1c71b6e7bfb404d0678dff844aa96eb64a133ba004421da9ebb01acdb2621ec45e617bb3d5b9a27224d275023b37ad49ff53003415e97f38b01ceb149daf49124fc7c5272e12ce83b51d3b4904bc088c8c59a207a6a24e86f1cee5682d32e9b2ce821a105c91896e226d0f286205b0b8106bd31ce0d7a56cc546f294a144cba741805ea4633918c3256ff68fb76720ccde1fd3ad05aacc299ae87b6a9da1aa5706fa2d05f84fc094a470c08af578bd633faa99ef018cef78bec1bb646e7ba06acb884b3a20b94dbaf5a7290d0eef866fee38971aa2df880aa8c83e1a3967a1e7044d8e6d528eb31d9421ba227138e48db766a20364c0f5044d02916ae3b569998cb2b52e4b6765d148834900a4e96398e6266fccd038ca3ca881c91f40e4b383df67640057559e3981bf468e5ded9831f3dd2205b97296d0e7ada6ef10516225b9d53cf44967d22fd85105bbad8de666dab38314ddc89ef4ce7547e5b29176963bbe09390f642a527615573c38e4c7d4bc698cd0d94fb3ef694de8965a5fb4412de97aac0b5e8efc2158490730397756f770ff52a4eeb40f8e6e464fab9cac94026ea76b1884ec18f2195747222a52f1e62c07902240ce3e5e
-TAG: ea46512c8a7332c4d63c7d8faad019ae
-
-# DIGEST: aba7a79c9107933b5d5c01965fb21d02
-KEY: e9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1d
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c2
-AD: 7f4372480974454879c41d
-CT: 5c1937c3e5142700a00d89fc8cd56b32d91e0182dcbee99c56a268dace00490bbe5f243560719df76bc492e53b21de57d7ac8803ec00afa463e04302d8ec23c8a4b12129d6d924c0ef49302f19f24cc3e4869b40937a11a01c6198f7e710ca8bfdd142f25cda23558b639c108908aadb1f83a8402f0b5755e5e9b8650a9c6c0568ea30361fd9334935239d89b2ab242e8f83ab60f1f4c21ca86625129d892939e3f18ba7b44a3cd788c316e3eece720ff5cb077dc08bcaef31069a8c62493cb27f9706d2879cff2e06342b7b9828afc929e226c72e8f012f32d17c77aeaadbdd435e602fe9981f78550e38afd0631be5b197827740b6f9e3a71daf93d705098b2d7c5c3e8bc79274ca021504c682b868f986568039ddfade902a8e364298a46af4cda4a104badb965f5a2600a30813aa4d8c251e31a1d36803c42323083c3fae69b91bbf52687458c7cc7e15b9a066c5cd349ff45cae43a9443979a56fd88dba64f924a11deacd36b069193e3aa532c76b216a2f2a883d02fdbe82c98ecc09dbd3eff7ea6411e398d3555b9a8cc851be4dd04442595b9aaaae415167c4685953fe1c7009b099f408502f6a121f90ba6c57880c3782aab1a123bb946b9e6de6fdbaebb3c78fd326cd23ac78ec251d5fb8a1df74b47c308eead8c2ce
-TAG: 8da32407e0897e2b00aebe576619713e
-
-# DIGEST: 93866d980c6f5a13693a5d350f2d3c72
-KEY: 3b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f43724809
-AD: 74454879c41de9ac9f9823
-CT: f559d2830b720d70336ac550a13d6a686dda1087ec5b517eccbb5c8580277852b7a05f0bc90ca417c8de69ec15d0493d2e4829666102226453c84333a6240e151090228d2872c89dcd6bc805d32cdf83b03ad6b28afeb6be972b9b5844739bd9fc11e38869860ec4dc0dcaaccf5274a8aceb95c2f2b4c5c82b63a178edd2eb7d41affbe93c92ad8153a77157d742edb53926d1192b5f8dbe1e58d1974013f8bf676d52f0a096ca756d389a7ea774cd4ba16aeb33356279e706038338c7ba932054aa93bc75d9d49d0e9a62ad58a8d5b28178286fc2f205608133992259c4f140148ee2bb431e73132af3dd23b8df5406c5f4a65da38f65e5d630b193a6e4a62c86a98034cc4789e8376cd16fd9a9ee56480ef96232955fdab68a8aea07736757a7c5e28637a18f255ab044bee7ee991bf8d403ca3d7c35392d64307527b04683cfbef1e0a7cb005fcead5d8cf1f3afd2a0bf428814ae93b10d34b04158768b4b3873ba83c9e20172776f73866890d38f6f253c64c89288ddec376d01857e9698c561ab020ca33b63f843946d97824983d5999d8bb565b1517655c9ee8600e0480d95a5c7b33390b8172ee1a13e09f1e377daf86dbc220c5585a6859e798b44f61c5463d1e2cfde28a2f043d0cc8e83cebd087b6cf34e048f3f4fe902d1c7c089
-TAG: b2ff32dd9823d1f90db9078ca471d4c9
-
-# DIGEST: 15ed29142440dd8af534d2c2b33dd98c
-KEY: 61792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c4
-AD: 1de9ac9f98233b5a7379a5
-CT: 466e361159ffdd7ac6e88bcdbe85cffae4b6a813321538a317accc1a36e6924011e446557a6f47786d99ab8102386bac937ffecda7c9eff4ce567eac6939fdc77c6db11437f959beb340d58414ee1969182c978fe7c739ccb95b620a0f0b19be2d6e8dec31e79a52b527fda1a046b2cc3bacb3677385b2a8bc96e40b784944452667958393c0e78af716415e93b87d4942d0e0cfacb967c26c2b81f3857c85d5a734043581f2131d2a584139eb41b110a2c8c535d265f5ffabd52c7c3a6c291ad4fa924435e4bb6e891afc6d86365329e856d6424e0fd31afe0c469fecc6453d15b63347f3486879447c3208485fd92ae3fb71ffc2347a79df4fd8f03fa452598e48e4689aad73bb5021d98a403c17a3177051b3e189c955ce1afe96e4be38a484687c5b0b7e0b1edf38e66d54eadbd80ee56528c1c00f8e3c0dd9d6737da7ac955de557d68ad5a6c6e0d85d8fa115640a6f4a19e734abe06ecdb653b66e38acf4778f8604225a3e8a17f81e58196211a73c9ebc2548baa04bb68e7d91584e563575983b7ebcb0dd7a83e565e89f7df2fb5ca616ad3a1a4bc2a728acab951975e77c56610ba8f9edd445f74ec442d679dcd260564d2e8882313982c9a622a1a42157faf82479a866fda1c74d21482e2cf629278b6f932ae1857008fe0c9e44b542c942591a
-TAG: 188fa26c452a97f68e0f27d47625133d
-
-# DIGEST: 22a2ee718c69582499aa0ac787cca9a1
-KEY: 16430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98
-AD: 233b5a7379a561792c0f31
-CT: 67109c38272a3ea6a8940d9f7003dd7962ceb088b1f975f74f555e115a869f5a7c4844112dc652236b84faf71533af8ba01828c3a63f7aaa6fb8cc06ce68fe65f60e715c991fa2c089e52529fbb2c14c95b3a9b8461cd2ffcc3a46e54606ab86043c0b019c8539b4a1967e1223b80dfb76c3da941a0632e9255401271c2ef0caacc14c754bb067337b11496940a70b64ebd5749f37dff625bc9b1928a077d81777e24ad3b6b58bcd9ccb145c1ae566bcfa0c55e958922ed3c38037e301a83d6aaef98027de167b8fb5593e7518e7b8688e9542af9df9f92d0666823b5ff7f2d4482cd546216be57e72e8ef6bbcfe32b7d37c7d23a47ddbf7af99a0a46a5c017050234d5a5214e171a28c7c08052c4221cdce240eb0c3df9f9205f63905ab63a99233cd74b57268050f1a04569c96553e3043db88569e065ab9211259ae175dd535c2ad225d5f70de6ce4682a56d8c679ee2dc5f63ec2d305cb3a9a1e25a90b4d148e840ff270e0049642986ec8c04a09ccf54a2848374a84d1c5a1ce4af7b5f4c844947ff3e913e86fb2d668af3eeecadc36df490532b15cd0d65ae99bc23e20c58a826094be1f3acc6c1661b58211bad36d6a9a5c3c28704694e28553f85756407c5990ecc4b0842812e6e29b167d9260fc9df88a6414456e0e9d2d4f83cce1f23b3170cef4c44f883b
-TAG: 0d4ad1e138a35ebc3d530eb0d8968e80
-
-# DIGEST: a64b2e7861a3b81599e28f7927498221
-KEY: a058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e97
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379
-AD: a561792c0f3116430e8b6e
-CT: aebcdb47d8f5565894e4be47dbe8914631c5de410be171358941e7e39b9a930d1d43c8472b33101cf8edbfee477ed19f39f391032d1a2786871781bcc9f08632251579c196b3993162c7a0db8291e5b06454f45cec378d36f5b5b6c342c6bd936eb286201fedaa8129e6cf6befbdea84b01fb653b10c6d36445429fd0e29878479a911b488a03bae8b30a9eb1c933f482fd066a33a46e0c0ae1a593064c0ef568994cb3d16085e3a49731e039ea37e400667576f1a06b6954052eff50abe59ff90d172c5eff6e04ef5fd185aa7830a3d819cd4d57031dc491815ebc2e18f306988e21f8707791c3448fecac276f89c89821dfb1983ab3087095ccd42b9ab114f64d613accadaacccfca4b57afa2a3e4a21fb2b4231936ebf6746e4805c555a6c6041cef8d90c3d5f6f12fd4585fe1bc5745ad5c29a395918c9e52f0c1ec55d41e76a947871b85f4f0dd769b12f9eebbb073b2842636b944bd7414b114957c00b615311921f511295a5fb334a77cb7f8768946faa6c00e98c1dea65ec9d7aac487ef917f4cf5cf785ee7dace6bbacb7484957cad1982d7c230ad1be62c2ef3ced8c994a704063348815fb54daac5ec9cab57963e8dc29f5054cc0c1626df56fc22400029b58239147a85d171562ab8780f64d1858870ce28b6060d6104a8c26d4fd78700ae11638236bce92ecdbd7e9
-TAG: f5fd3668d52f4c82278d94e9728c45e0
-
diff --git a/src/crypto/cipher/test/rc4_sha1_ssl3_tests.txt b/src/crypto/cipher/test/rc4_sha1_ssl3_tests.txt
deleted file mode 100644
index 721cef9..0000000
--- a/src/crypto/cipher/test/rc4_sha1_ssl3_tests.txt
+++ /dev/null
@@ -1,808 +0,0 @@
-# Generated by
-#   go run make_legacy_aead_tests.go -cipher rc4 -mac sha1 -ssl3
-#
-# Note: aead_test's input format splits the ciphertext and tag positions of the sealed
-# input. But these legacy AEADs are MAC-then-encrypt and may include padding, so this
-# split isn't meaningful. The unencrypted MAC is included in the 'DIGEST' tag above
-# each test case.
-
-# DIGEST: 095a8f557f75cba8e2452ddf97c053904b48827f
-KEY: 18cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481d
-NONCE: 
-IN: 
-AD: 936a91d0b5d2c02672
-CT: 
-TAG: 42fbfab0ff2cf9938a29b79c5bf289aac6db2da7
-
-# DIGEST: 4a7464217ea94d95668d31736693ae851eb0e39a
-KEY: 171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa2
-NONCE: 
-IN: 936a91d0b5
-AD: d2c0267218cb7090c6
-CT: ed6c876469
-TAG: 3d3149ef83ac555271dce4ce450cc31d3bb32de4
-
-# DIGEST: f1efd4c11318f4558eb4a50d5a5b9b1e540f6dfc
-KEY: b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd8
-NONCE: 
-IN: 936a91d0b5d2c0267218
-AD: cb7090c6171386d641
-CT: afadafe409fde84f8901
-TAG: ec20aef4350ebea1cbcf910e74a0e0e62ab419ce
-
-# DIGEST: 995341bee01fb91132d1af8394401144a35bd965
-KEY: e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8e
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c617
-AD: 1386d641b87797b684
-CT: 8358512e9cc1143dcdd908479e4129
-TAG: d765825aa1e1f1430046369c64831742ba458a5c
-
-# DIGEST: 73dc06657c34ffcc71e6662ec0a52aa7168c22e0
-KEY: 3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2f
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b8
-AD: 7797b684e0fb56f97c
-CT: 2c53873f0e02a70437eeff275623bdcc0d0d4533
-TAG: 4a0a14ce7b5ea1305637f7691d988aae655ebe01
-
-# DIGEST: 6a5e3024f92e29f8f3e294f87fb25572c0390dd1
-KEY: 2993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0
-AD: fb56f97c3961d8afa2
-CT: 33b31a7663a04d4819138b9afc9e8bbd3e8d9651489da70383
-TAG: 3c0fd00f8a839c739a168b90d21f16671819d3b6
-
-# DIGEST: 6f192a6acc2fed00007506adeb1dd454e2e92809
-KEY: b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e0
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c39
-AD: 61d8afa22993a340b9
-CT: 67df387e73f7050286e6f7fede0ff98880d03cf0348a0b09b0f392f3f4bb
-TAG: 65a63d2f42a842cc6387c149339d8034b78eb7d8
-
-# DIGEST: 7faa4d4ec92841e45297553097f2ac2ca53d2592
-KEY: 1df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa229
-AD: 93a340b9b3c589c748
-CT: 14a1af0b3ca2bbbfe6b61d0d13352e422cbc46a616542047b9562c5edd0d20b8ef4993
-TAG: 5ba5731267366f041998a50a635b3b7062f416fa
-
-# DIGEST: d6cf3a4fe57328e885cb10cc7088e0562c7f91b3
-KEY: a23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3
-AD: c589c7481df3f4183a
-CT: b791f1701e00cf2ab51cc341c3b142194cc15a67ba1bfdc09e0e6963bbc1eee11d47170810dd7a21
-TAG: cb883e2debf80c04e09af2c6e2576398ccfdbba5
-
-# DIGEST: a2ba1bff3a6dc3ffa8c405fb8f69c41ce7c1a1f5
-KEY: d88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481d
-AD: f3f4183aa23fd8d7ef
-CT: 1240c27d9d132ebd3f6ecd644edf5c2b9385bee1099d3ecb5e33ef7a10cbac2ea8c05537180371f2378d38fa5a
-TAG: 4813fb143d05567bcc75cbbb5551fd944bdfceac
-
-# DIGEST: e2825275a794df011a9dd0c6061de3a9eb2efd48
-KEY: 8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b4369
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa2
-AD: 3fd8d7efd88503f78b
-CT: a5873808917d9b452bf13878e1c8fbe06ad063206b8b75a4754032a7d2e9e8c97571f5eee1bdae8550fecc97cb5e85ec3e70
-TAG: 4e38aaba4320b6ad874c24616414428bad95c56e
-
-# DIGEST: ab656533e45e90a45a508392ce59ab9bbcac27c2
-KEY: 2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd8
-AD: 8503f78b8ed1c8e9ba
-CT: aa5d4eb24a28527149552be0864fced97736994382efa76742c1bc1df8af3c571c27b65f01a742d8e93f14584645f66414cfc4a2a8f54d
-TAG: 980e3e5a6f8e4fc370990d813a4d1d3cb40b8c42
-
-# DIGEST: 0614460f6ee128d42ae79b1dda518a0f0e4d0d16
-KEY: 0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8e
-AD: d1c8e9ba2fd6773e0d
-CT: 963b25bc57f4ff2161ebe8e13250e1b19500eb467300cbd7d7d240a31746436c5a64ab1874f57cf9205582a364f1486b17e4420112a3a9adbf6824e6
-TAG: 9f7c325e93edde164eb3acf739b9097ad5f9b495
-
-# DIGEST: 629525ee366d420f18c6a88fa3a8cfecaa1331f9
-KEY: e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7d
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2f
-AD: d6773e0d0c302a5f47
-CT: d2f611885eef206fc73f346611e61a9c38b9f67dbecb14799ce7c2395ae6e89d1a2debb319b68ee7006c884b9b98ad3af15709b9d1b2e176b308f399f74107fcaf
-TAG: 96604f07b8ccea9a830db6845f887197bcc9a471
-
-# DIGEST: 79b26abc71e1670444167ecf48e093d505678371
-KEY: 91d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c
-AD: 302a5f47e037446f58
-CT: f526da150e339a1527a325b217f86afc12e34936aa98f487fd754b27dd2997b208bdef456ab2f8029c47dadd0e0c565043db169c632aa166551bf8475aac497578efaa493b21
-TAG: c06d88653796f1965b07d0ac8d17ba0fdd3d3483
-
-# DIGEST: 6cd5a6f762364b9814deb6e1cfba1eae5b0f31d3
-KEY: ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e0
-AD: 37446f5891d77df660
-CT: eaa157a1a45054c9496d70ea9429071763e65fec4e03808041f569affc6fa6a818a857135e80d67cec5ece259fc33535db2106b2b16f75880f39b9326d4d1419d8eb1e7b3c9b0c620830e2
-TAG: 4951455ca46f1d3c2f9b6e6fe70adffa9a77c8f8
-
-# DIGEST: 2d3f449046b625672e740920da76e6cb0b297236
-KEY: be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891
-AD: d77df660ed82933f62
-CT: 7112394937353fb4362b8d974895296c596eaffd68d4702a280273a01c0fd8218a58556d1afc8ef9baf09c2e257c4194b13335d2bd6edf5ff52c8113ab663532b987f51de94372efdf55c2eef73c6716
-TAG: 169a37f0d0fcb9ab7211adfce3e06884fa925147
-
-# DIGEST: f321845e9752dd4bbc414648274459099c9e5574
-KEY: 6965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a7
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed
-AD: 82933f62be8dc55b43
-CT: 7a38a3cec5b13fb9918f69a4ae4656ab16da1c5f23d7e89540f7eac98103d616c19da4b6c37a012dc4ae0f84292b1c1e017fef186547c618d4705be66f054acabe0ac48d6e836ce899374e3d68f49df31e11efa466
-TAG: 5cb7b3345741a8473477735b6ba91a519081a163
-
-# DIGEST: da9868a42a40dc263e0a0fe4247ee859569d7f63
-KEY: 7e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54e
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be
-AD: 8dc55b436965aabe47
-CT: d996a7ceefe76cbdf83bf2bf707067eb22579d7aee99464184e78a9eeb10c9d47b76de9621a8f728ef4f90beefec0be8a36cf2c1c679d158a484d43902b543e31920359aafd51bc47b622c01a98463ec0471c5bda7040d654f2a
-TAG: 8939720762240273631ac9dcd7a2227ec5ba1c98
-
-# DIGEST: a17d268f79216e57050079ed4a85ce137f83cf5e
-KEY: 99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be90
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b4369
-AD: 65aabe477e0cdd46be
-CT: b8058f25f9fd11c1ebdf5570d5e18cf96d768abdd979250fcb87c97f30f508ae2115f99ef088328bed753ec571a3158f4e83d50639b340af020d5d9fe9a913dccb3e9818d497470cb51e6dd696506ae350b89fc023d9fddcf2fa9860f1f703
-TAG: 1de8ddec0c43310fdb052e7884b94da86a5f3404
-
-# DIGEST: 44ba8d9c06c6788865a1dd76287a443eb0c22aa0
-KEY: 7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5d
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e
-AD: 0cdd46be99371eb8da
-CT: 90cae6bf042b86fe5a3762e829532395c884c5410b02cf4237cae91cbb460ab4e85ea3acde6b0ca76c878d950510b78d36b8fa4a7ac2b018b8be08e3145694667e966a3b4b18109a62f8c8a35fa922a52c1b14d72f23693fbe4777b435587240eba5ad52
-TAG: 7e520549bb7d8515ea5e6b9b30e4ef3337d6afdc
-
-# DIGEST: 5b0d95d9ca1dc4d0ccd940d38881b8864757c9d2
-KEY: fd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
-AD: 371eb8da7dac997dea
-CT: 79c97c6bd427bcf073edbe6d522fe077ad8a7bcb44f4767f6d4d84ec057ad21f30e7abb6a600907905c57a405bdc68627a2cc2dc4a0f942c3f83bc59fe0320587b211f3831c1207949ae295a350e8166c433579b8b794b039ba60ea8194532fe742dd89555cefea263
-TAG: be903f4aa6afcdc0e05ee39e160c8723de43684a
-
-# DIGEST: 310801f266e960f886f9a02cc9e8adaead89dd29
-KEY: de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae0
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7d
-AD: ac997deafd64b1fc65
-CT: d97f0b75e910efb5a9fe90bff3d1986e7fcc4a620ad8dc9a811ce6148ea1f10a427a9280a8bc4fda4580c5a045b8df85f2da6668af09386692e1e721645890c328f718bba7a00c78b3ab9ffac115df353dc00e0e7892d736e8f152ea2ecdd80350e01161a2c14ff713066088775d
-TAG: 799ed401e99d3ab54616dc8f2e0affa8109c3e27
-
-# DIGEST: f6998ed9b090ceb8422100ff91e5e2671a49d980
-KEY: 41a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd
-AD: 64b1fc65de39f4f035
-CT: f59fcaab6e1c62614e12ccac2430bcf5ab87954b4c678940cf64f442cb4e56126fe39bf25769b5622c3da73b44e57d977e9826500a33c5f48598cf4a264381954ec94a94ff2e1b1585e07f1bde18c5062be474cbd09966d14ff8c27a56b85b489fc4240614152ddbca10dc28afe154b8c7c5b8
-TAG: a2612eb4ca3f51b7d4ea2e1c63ba0e4a133642a0
-
-# DIGEST: af2873f1a7fcd4930f1c8a554ff271c5ee9185ce
-KEY: a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de
-AD: 39f4f03541a11be112
-CT: bb149d8dfc97403a5c1be9655adb17cfd8fe9458a5f7c296fcbba583f6dead58f135138d5965c9ec489481544b8c42ad5f8fa10fc129e6f49a1fb9be75fdac724f65a489e26a5adac60e073cafff429900aab079d83e417760349970c86ab37da5547b5f3f22a3a620207b3cc9f255a79767a5e22971d8a5
-TAG: 4e97b22ac0ccca468463616230a8b54cba66eb47
-
-# DIGEST: c4eaa1d6c4d2d5a8d2f4d96890bd0299f1d699d8
-KEY: 4ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541
-AD: a11be112a72933c7b5
-CT: c2bf3eb1f2d87005fab2a16ec21c0678b66b57c28ca20d413aed6c50a26ac1af6272c80983d1e9348573af84a38de9f47cc8358df2f70d4fbda7ece428b07e8ebf94cffd6e82923bce263cbc3d6a44090894922a565a7401189677a3da7b359658bd24e20d7199a1822a527a5e916b7ec85eb5aa3b368b63108eccc4ff
-TAG: 25d775b8c7063c627e4e4b540c48d250d7029f5d
-
-# DIGEST: e9bb0964e1cb09fde5e8f852937c4d8e1605b714
-KEY: 905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a7
-AD: 2933c7b54ed4fad0be
-CT: 6457026b23b8d31afba224c866688051a8132973e4cb97e017fe4ffcbce63acc177e3f2100c33adaec1d09b96a3c6ae96c8c90df697d322f3301b01fdfc2703b59a25944b9bbd2cce2a56ab1dc120e2fb2c906a986d306636564c5eee7f7f06dc74f4b45c208018cedb9a9643d85506d2f35781fbadf3dc1dfe17ab3126a062ddf81
-TAG: 4920fc1354c9cf60ca78d39e55041b8b5e5ac58a
-
-# DIGEST: 659746de28fff60cf3bcaa07eb7a95c5b7d3200a
-KEY: 5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb0
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54e
-AD: d4fad0be905d41203f
-CT: 2cbfe55d182b1e32997a9bc15756076fce0d74074fe3d6de95465010710fb6e48f272093d989c1b382a2d1457817b905269e4158b65a824dfde9d5142849367231611eebd767b09d2edd87db86c9eec8f6e4be7f271708553faf9b8ee8b8edd8b669690e93415e78e3227922d041e4a9cbb19f2db23cc5bf5e444daa8ac99bbc238dfeee3f0eea
-TAG: f4ce57f86096bf2aa2e904666213669050e8eaf2
-
-# DIGEST: 170202dac332954785ff6f866f165ca62510d9bb
-KEY: b2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d617
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be90
-AD: 5d41203f5dce998f8f
-CT: 15ecdbdf769134ff174f8473a8fc1f8119c0a7499c7d5adf339f8a2f23c54ff2f07e8002344fc9867bd5345d83f148a8a3693a7217232a98de92b7ce2a6702893bd1ef9d3efa734d501253e8af0cd20251fbad552b4b1f59e52b4b1a138ac89d2e6027dcbd004ed8e2b23629fc5de4ae1894987fc35693a300244aee525d3ae0b68fa40f1178f82b9c08ecfd
-TAG: ec4889ddbf5879bc74cd40989dfb8b68143b7b9e
-
-# DIGEST: 767d4f588b55b2593cfbdc46acc6064616f75c2a
-KEY: e02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b7
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5d
-AD: ce998f8fb2eaad409a
-CT: e0eb36831cc90b2739671bc583b7bb0dabf12de5d45b478d4eab1ff25b158c52bfa83a79d0f1581b2a7c7628405255d678a721c6db44ce8f053eac595b3ad3d0658fd93f7775ad2f02d532e0fb9ad7498746e3e105d165b22fd776e93f2738fea93e82bc3e456488b07b683f59ded5e0b4c4e3c6382c31c215598ba1464c8d6254071a0c0faadea8c248480a5340bf0166
-TAG: f9a4cd990a3998752d06f9193521a04bea771798
-
-# DIGEST: 27937a84ae455678a2f3c73b523d600135e6dcdf
-KEY: ae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2
-AD: eaad409ae02116417d
-CT: f47fe2f0ab38d33a0be222fc035d8e0271af0945cd8d7b2075a645ce9b0e10dd32a7b35a320e904f28086300f6c63b9984064cdd3a1e945e4b09e521f8a7addc781c8c206698902e6c30e202b7045d3a2233b8981aa16ec36bc568ab4688b08e5b0402f9781b4e843b40361b79db0064e141566f6df0301a2fdab3efcb32aae0aba0bf7d1317ab061e37118f59f46377c9ea521d3e10
-TAG: 40da6a2b16aa3a61ea5c56ac229692a754342883
-
-# DIGEST: b1c534558a6ecb0ea225369be47ddfe669190d41
-KEY: 9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae0
-AD: 2116417dae0cef457b
-CT: 073434fd77c0f06a1ce257d9988a28da439c05efe00c28e89c45a5cb0606334c7a34bef33687dbb559d33cf2cc60c23cd217ce1a56ad5ac995141b5ef5d7308ebb30634e74d37bd9fb1bff082a1c718b7e811ff5c0dbee2acfa35a26899cf4749e1d4e2d7e04f795ac4c73b5f00c09e06f098725dfbeea62385deea4096d27e4f5806810742dac6c73906ad454640c574e9b63ed2d810add0f34b0
-TAG: 827ea5384c132bba74c199b40af774aecb95263a
-
-# DIGEST: 774dbbcae39eaf44fc300eb00977f4e56e4dc0d6
-KEY: b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae
-AD: 0cef457b9e5e16dcc5
-CT: 28a3dfcd210589857c4d4040ff61e2d0f50a944a9ffc7443ce5721ca5416b84c90aa4c05ecdacd746021b711ce44a256713ffdaf31e33baec23e9d88bdbba99ac83ecacdcad09f482a6ea3a6ba75f7ae65ba8e0d429bb03c4394194c51e55e66966db37d0347d0a5b7aee2e1dc23ec90775e32193a739335106074fb3ad65a6154047cbd4341933e6954f0b7d0392198bc46faf0d66c5e270d165909573646d3
-TAG: 710469ca411535dad3c7d49e507a0ea46a7e9afb
-
-# DIGEST: 5c6b13d8f7e9f764136921bf62cf406b9dcc8615
-KEY: 0d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcf
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e
-AD: 5e16dcc5b6f25607f0
-CT: 5b447b16aa964e8abe9f6087d40a746019ca109e99ec78b7166484a497d8e829faed1bfbd9c08f6acab94f86d565c5845174a4634901da38aab27151752320c6b81e71e68092d49619b4b99427823868429f00d2fcd93105a4f151011457a7c8dd82f90a3002994e131b3dec06d0e4c84b0f24f3ee5769830ab949dbb6b6cbf1df468369c1f0614bbe0593135a3d3762bedf0367bd7990104cb9c171534bc00d92750eeb25
-TAG: 51cdcd24acafbddcdcc4bcf30eff1dbf4151d2ac
-
-# DIGEST: b72799f51e711da0ea2528a5125a994e33078898
-KEY: b09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b5
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6
-AD: f25607f00d033fb95f
-CT: 18d86aa0539057971974e72a1b6f06f43e45cb7a5ac20d59cb88e3b952002ecfa4593a2787ff68a38fb386d4dd06da29cad8f5e9c7f1fab4878f2e92becc45a58b3948b7f5c0d0245f957bcfc393b07a16f9180e109e4e3e2090a7b2078e29d54c59ddd718b76cab59584864c8dc2c840e90b0a5909d230cf44cf18ebd72c70eabffa0ecc1bf6c73ddafee3f55ba13cecacba7663b08fcf5f149eb5fe359a197b495722d8b2737f48ad9
-TAG: 7089cd9d3ca5bf31ec1c3dd5d50f26c14323c3c8
-
-# DIGEST: c2c932a2159da6861262e601fe835e4feb139fc6
-KEY: 172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d
-AD: 033fb95fb09e4d00d6
-CT: 5aabc651eca00fb77235fb54818c06a7f4fd19e4bb00844b3ca3f705dd22fcace922f2ac4509af9c72ff2ed068556962f936759d56d726db65e149e7e4e362d771512ad9d3bde7388f53e69d813a8afd4e5accb77d9024b4fefd86b6a32d8c455d7edafe8f897aa08069d7345371bd46bece90dd9f82da5233a3cea5bad59a8b8859290f786223e83b57136a3de0c2da7fbc4483634ef9b0e7b026d07ad86f3184520ca49b04f38f170006a7e35805
-TAG: 4b5088aa10d6c4bde1165ae11b0b5c17bfa050a1
-
-# DIGEST: 25b40da26cc2da8afe980d0287004507d92a426d
-KEY: b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb0
-AD: 9e4d00d6172e780ab8
-CT: 68b82ca866d62315e0870a3e86dfa8357e704b0d53243cc058f31281622dc63e304032135fa43c4973f183c7d7999b496cb6ff4fdf8370ed45e82b6ff897f32b7abfe80e9193ddb74916103085e18fd6d84981714299fda6a6d8851e7af73921b02f71eae96c45497525636b6b093705db1e614b1ff594d6e28ba0a239fbb1078fe0dd76777669f780f0f4d79bd13aa3b0cd1b1da66e05112349413f03219ac50759f4186b2f20ce9831914d8d0ecd851777b7e3
-TAG: 2d963c2535e0c3ed74cf97d26a039fdddb78c1e8
-
-# DIGEST: 2b6449832e28e0f08469119a61c6119ecaf747be
-KEY: 7a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad24639
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d617
-AD: 2e780ab8b700433a95
-CT: bf0ad57d9488771a3325336c8fadb2c7d07f659408a72368385d8324c39c25d26af60252fa83ffc831934d6eb6107fba199352fb7f308abaff306b1e2e77e9b8ca8b7138a481a703e6289f1b3c1045f012749ad5692706d6f6c1a8c086062bf728a0277c79d5a14b7d36fdd2d26e7761b82a57319c93c6df34b93a216065fa5cb79273826503be96ad60f7799c02995e2227d26b5f2c93e5897a8adf4b4ead6504389a9ff18c0b42b8684b98ba7e9fed8a6a01afaed53f3d96
-TAG: 9ad5ed93f2e952f0b1462348a84e2ddf00f6d76d
-
-# DIGEST: 4e2f1dae39e30675c6b32f427ca47ce502a02191
-KEY: 0f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce9
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b7
-AD: 00433a957a741c9eb8
-CT: af7a08349525d2d24d992f3c0fe725bfe8fe896e0c7acc5ad581a7976995588745714ac772e7afc9ab916f86eb189ec68d9b2c492be6fbb7378cdb8b226d09d5e2ab7e59ef063c99c8684217928254db72050aadcfc5883acdc566fbfb69b248b4c5e5425dab7521dc30ab220751d31d1165cf81059e6ec5aeb8d0c74c712e33d895148fc120669b26ba00b00044d4d6db7177ad44a62c893826c5d654cb710d4bd3fedca0523e3f42f290babd110d9706aab3495827952e3f0836ea7aff
-TAG: da1b91d5d06e1475b86b48b439a5157e8d80c722
-
-# DIGEST: 4b779331c327101cda11bbea17702561aa8a410d
-KEY: 44769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a
-AD: 741c9eb80f2b021b14
-CT: 80a9f55c17c62102d6823fcd318277941ae57469811e2bdd5949b705960917a4bcc5915821a49a1da23cc5fbc1b047d414d0dffadfdd820ed280d92e9fa22d38e5134d1a2f8e3b5ed3a3a37219ffe0b1dc4de0d57607fdff522765a1c23c480a904bfa425379ff7383b38c8cda62ced5ebba17db593c6e69bda0a9c8b6dd72e38b4b4c98e4984082162cbd7718150ccc8edfed0486777f1dcac67bd7ea4cf3d44e40b450976378c4d04b7f36ac3410368cd4bf530c32f1900a732a71d9ff8685aa9992
-TAG: 8d78b133054797ccbfa8c04f2d98627e1bce622e
-
-# DIGEST: 708364fadfaaf52792bc2fe5bdaabcf986af7aa9
-KEY: cfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffd
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f
-AD: 2b021b1444769da00f
-CT: d9dd3e151f466b7969f73801eea0fae7cd8427c7b39587ebaa22ea80c5c40ed42fd9d189a6c7c55f9ef3129739a728c0af7e0b37f891af7cbe7ad83526b6be3dd1dc9efb30656e5298638a6baf3719f78a0b4274c9d8ecec4326055ebd33054e504c73bc0e68fde6dc64f69576a04ff87971b520d905d2df6bdc2a2eb54642c301a88d305a30d7d0d42e731aa67c06da64180f9b6206ec0c7ef7cca074ebcf22f0ec4fc1f722a425e8a08d57dcc007cdfd9164de3a5c4a99e2285327e6a0b0bc84cbd2e3549a39f4
-TAG: 06f1a5f262325ef0465342fea679747930bfdf27
-
-# DIGEST: 335c241743268f08b03aa63abf9642360d22a112
-KEY: b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f4196324
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444
-AD: 769da00fcfab0f5f93
-CT: f448369ddf6afc246731ec01667b19ecf0534392c76e7848385f51d187253ba1acd2b3ccf8cba66f2ba90e25a2b999748dbcc4a6e0575f565d38a4ca6326276a7f5dc51c6007c3491b017d7e127a31633d00ca3f01909b607d74f27dffd4c67c5860f3b18754211b5bc719f4780841d224203c3de44104b65deaae2559e6ee3d5ed6c6657be351ef2a1791d28a149af7061c4d9c7ff991f0c35b87681208d8763f6158142c7c50e50a0c516c74a00f94bfb0663f8cb85e62ad9e4748f45f2fb14f12ba58e45082b1a487655ed2
-TAG: 14427e3d291b4eb36a87c0a5b3b6e61e18ece0d7
-
-# DIGEST: ae61ce3c2b1475f8afdfb1be68addaaeb6489356
-KEY: 5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcf
-AD: ab0f5f93b511060c9c
-CT: 20c99f6edec4a13ff93b43fa6e52daff5f6b83cd295cd6bc560c70def9b8eb7ab27f17e4ebf28479a786fdac80ceb057f45737548998ebbf9bb2917da086bf29a4178c49654d73d0ca98091b4dc618a7903d7771f6bee7a81d7f63894afacabd8af32a5dbf748a51960a33c6c8ba8378e4a76054228d5a639eebd60283d9aae75c531e48c7c2518b788b3440ce72d99bb8e86a92c802d6ec00002fa0b5e7fbb7c22809362bfa7027134e7ab0f978d7b5f1ed4bca13bae97ed24a76a4216e59cc72af58d1ff27a0ba3b68548ac6d44948b42e
-TAG: 5562283769aad26a812585074b329a403444fd65
-
-# DIGEST: dc6621d897775dba7bacf8b7f82bac003e984b00
-KEY: 1b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c0
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b5
-AD: 11060c9c5f3aacefe6
-CT: 21629876afb14f4694e49898c5af7fbdaaf96c2b7871094d1f3d55d8d903d2205422e7514662d15020366c41b5422110a0f84a8d2577c79df4e664e68d79f19c71c63d2190b7b8756a8bb05cada3f7f5925a67906b6f93f3349eb1502005fd9d123e07df3f423d5e5ac97a52ddccab3fe8191a7a1896356d49eafe67c18a2fb32745a3e0f6776bcfcb51e0027812c222eb2da4451bb9f218fda14b5d078e89873b1a09866814ba4a0adf542d0a0e578e6a39d5dd783626b5d1795581f4b11b46271eae7e1c5b02fd4f21d6238ee417c75a35735358c324
-TAG: ad3eb8bde9d6af53dc3803b3f40511fce6a4be5a
-
-# DIGEST: d2e6d3eeb6b5565d9a407fb96c74b8b3be42e64e
-KEY: 3939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f
-AD: 3aacefe61b184ad246
-CT: de8061ea3b9408e5ba06c5919388b3525f9e9b11021d2554006246765a977e5bb90a9e89c4cb32b3ad2d03e47b34a36189c2aacb0dfa0746e1eab2d806eed3310887d60e12f7c8de5cd5501e6564cb0bada4e6ccbcdc16fbfce9aeff7c41c02d9ab333cc811f0295b87df0714129799a7de0ab4727a19e145fa6afac3eae1740a8f877bc3ba69f4cd212d6cb028d7aa869ee22572b65fc76bb0a64d32ccb63ad238abd6387fd4af1a9c770b460bd3cdacab4e6b98330daeab2f852a898211a13a2550ea041c1a1b9b00675616281a0275c1f9faa4ef23aac2bef19aa
-TAG: 20dc918aa66561341910b033a15505b94128b0a7
-
-# DIGEST: 238d50a0695b1f255d5b3944c623876919f9cc6f
-KEY: e97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a02
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b
-AD: 184ad2463939ed518c
-CT: aab52e8bee8a90959cc84dd9477751f0725be7adb366f321f415552458918b40a96d39c3a43ebc64fe0d6bd3efdc4ec8654a6fddec81208ab57cf3d29cb563c743cbd9e110d8151016a27e5eb86285231ee4c79c5a15fbbc2d05daa96f6b06d542e05b9fcaf164b822e10b311013ef038399e09b696a1697a14069c30d9b6db4bbdd866431d912f2b84a231ca84cdb4e7d8160268425412eac641a92afb9d47231fd802a663bc8a42031564086615388ad2794d30b4c16c6370a75e7488d00234d1da69d64a740b3f0f682e95ab99a0271a448a240d11d80c6953dfddedd2e3563
-TAG: 676d003572059bada08be97c20260f7afb1da0bb
-
-# DIGEST: 562090fcf982854158b6068786792d26d2af3cb4
-KEY: 3d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad24639
-AD: 39ed518ce97c3fdd29
-CT: 59b348edd30bfa86e0f4662ffe5351727e98a1942877a1079edb5cec4fa811a06f871f023b7249bee23b2e8708acc776c5c88b449946bc1f4d17f31f0f78598e3b2de5a667555313b9ce4494b53eb2b2938c0533c49498a8455281769c84d94fffb69f5a7061a095705f1f767b649be854168f8e058d17699b5798007f0f92e36a2aff459591b93c4d712364e7fdf32c080a212783c09ba2a6ac6b68b818e08b2c6012f7234af899dcf1958cae498ee42b6e9107bfc702b190d04fb3db4611eb9602ea88a33efab569228e7cdc883a91bc695739754ea69013e6316b75a7695835a6fd4cb6f9
-TAG: 1c78c2dff285189eb60609d74a4fe9dc951c2738
-
-# DIGEST: 0c2eff5f73e4ec6371200ea4e3ed600ca22116cf
-KEY: fdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e9
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce9
-AD: 7c3fdd293d72afc09f
-CT: 380373d3a8dd1460b75f7b809ebf51d0d1fa55c0d434fc23af1898d13539fb8abb17dfaefb892b7efc7c005738599138da7f2501d6ad4591647b655add97c2af2384a633ba6dfad3b7b1d2e072df58db461ed5e147d3b456591f0c0a344c7d3b557e074208eca098da866f42244fd18823da188cbbbb42f935d11b5d3f7d6ab0f32bd35c8a6ecb816c98e7dd00c55960ec258756c478e501688200970728340517f59c8e5ca0b77ac6e054be4647a923eff729a149732ea3e875017ba945613b5e956646105739851f67c829fe8dffb850b29ff9313e9368805b3c8ef5a6d62acfa58032351608882caeb6
-TAG: f681b209cc7fbc6b902145d750dbd08d8a07c273
-
-# DIGEST: 7e81f0c3bb2f9c2073120134be9d0b1d0521989a
-KEY: 249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3b
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d
-AD: 72afc09ffdd4f41963
-CT: d22a45b6b6dff4c4a9b362d7c1e3b21d4d3364cd65d17ff37241ee0f2d89333964da9357f5f4228df3b7778f8fc64b8c5b2ed2c7f60e1fd67cc58843e3aac3f80052ade2a901315b56260e7b18004d2cc4c730d7d7a0b128b87e2fd0e910211e3f8ecfa97488344f1bfcad735c32b52dcabb3d9fd821a329a6515b1241002e61fa1400b672d76139cc56c0660af0de5179056b52286a1237ffaddd51be34e2cbffc4307f07682b10e8fa109cc87b5ced99a97fdb633279d609bb9c11b5f96039208eca672eb7bab4c54e66db69d8e0ce558c9a0e83a53da005131a53765e771b0c1bdd0121f5c5e4aadb9edadca2329b
-TAG: da8484093b25e78f7090d8a4298404cfd5858b2b
-
-# DIGEST: 28a454911a3ce17c0248d2f535f4073b6b092f6e
-KEY: 2e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2a
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffd
-AD: d4f41963249cd299b9
-CT: 943b5845b33812ba7610e75aeaf5ea38268324cd6fac2e9275795fdaa1a6df50d6acb3dc4c9dcbf6625865859697a27fd6b1ad418e4f184f074692f6faa13e795701d33a3b8f5fe8bd6fb36e4c852fafdeee63122e0150468cb37680670f5b8b3c9a86f4eafbb106857d527708d1f20b6114ce19feba607dab8755ef7707b8bdc9e9f71e40e6c099c6790a5cc5c30b0a45c94de1743cb5da7ef11d0a180042dbfb1595d144f28e3b1f431ebad15af77b325d8944e5e61a58c6f6234a7ad2be1cf18a1e7453f6e348adf330447205b3bf8d148c63441d681bf7bae17755a3d797ac03dc81df899548ead0ea413a6a99c7ec07021312
-TAG: 2b7b6000232312ed6bfbc04983d32d46e67a1dc3
-
-# DIGEST: 179d0ff2661ea9bbc7a42df1b3368bd48c176a91
-KEY: c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f4196324
-AD: 9cd299b92e55ca24d8
-CT: 8ff112e1de1d8baac5be35dd75ed7099f5ae24ab0b01984daaf7c69c0b35b1038316adb4a6029af6363ccf4232875f2712fa9d91012a0e9b37606cb2051815697f3e020836f46cab240a27472561ef14fb0a85924802d1e991e80aacd149d8f93aba358d5024e412f7ee6b30fd67cc17dfa3e9219097768ca438b150cf83d28b25bf53795a8d519c0e43dc9ae7b732a25e6391236770897085e9e10c4278fcde2c3958b89438c0dc085fed9159f17ad74fee72d6e0c5a43818fdf2c246ba781b7a47b13cca182869a6daed98eea4e1b868b9f0f4a7a482d5066cd6165c769369b2261529bb97424e3a3a75208d5dab9bb38ca5d9eb1deef6af24
-TAG: 0e5bd44a1df7664162d7e2c696e52cbe1aa58fe6
-
-# DIGEST: 35f3568ac38767bbb0464106b32622a101523d0f
-KEY: c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e
-AD: 55ca24d8c078c49f78
-CT: d13d3a49ff50b3755d46a272e3819f68b98d4c668648301c5ab4d0fe1f477940c3318bde05090f14ca3832af2a6ca4a60221751d2555715184c8df8d67c5d17a052b8b375dbe5b63e68cbcb230fd36b0d9321d72c61377567a47d7d65064b4826bd130f949544edad567b6f12314fb7b807d9d7fe109607b40928aa798bbbba9ff19ae362ed6faaf42cd6b7df0bdb8cc0e39b650a78bdf13b378e641ba4c86f8a52d6e4cde61b337e5112f64a57b5020962689ca4c8173f17f8e8c627476d1fb3118d5be44abe7247eaa0b2fe4b1494c43231a2ae87f14271e6b956f0da89aafad9f008d0d25f174ef82b96afc4f1ada9694c033101bcc5e62e8d3f6b41450
-TAG: eeee908d29c6ec4293c0d6bc61447a21c2f21447
-
-# DIGEST: 720ba4f4eaf71a85873c01a80fcbcea419d22ce5
-KEY: 025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c0
-AD: 78c49f78c7e713710a
-CT: c6aab34bf5ff64abb221ce84bf690040486c03321d898f228b34cc3fda44e6df1486f06284fe53eafa3f9b16a0d07db924ce911381903bd941f5b1e3b7069f3648cd44d6275919493eb36a9ce960e208f7d2464275fc7ab0fcc45d4528b9487bb22326741b9ab517a7aa412cd6cd4ad5bcb217d39cce252449c9a59121cba8c714bd3f16c3228b563f3a5a588da12364cb5c1db0821763a04309e97e243fe869c836897794bb67af25c86e2546e63a28fc3b90c3af5eedb41c6785e8318ef82b429369d088e9328bfdaba0621c4247e181cb44ee5001a540ccee570e47deaa6563add91ce9bdb3fcf8e409bda66ee5b545d9b767a7913255c188a2cf038619e4d197f942
-TAG: 2b3704e284c3a0fad20b6d2654e7cc2fc6bbd951
-
-# DIGEST: e531dc2be28c8985a08dc53ed098457cca032116
-KEY: 1d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7
-AD: e713710a025cb8b9d7
-CT: d4c81d32d0dd6fd40a7892442921d27b98bdb7a6cf32101b0d062c31877074c73880d932404000e83c8f65a1a027f21409353bdef852f8acb87713f2effc0cab743831dc011e2c82826c3177af759a0027f57d1b0bb3ab487ffa4ea9763d1db5a7d41ce249ef878b54af845fc63a83497c102b87f21ec8b589864ce758f53127af36e4d006eedb9fa76da0a7c23c8056e2832dc41e73580f10f5c1b57b5bff2ca23e22c5c193014a885c36d5535b1d4e7215e5568a1c0cb4dd9f982c6c1847d0bececa0d19567d0319878d2925f88d1b965cd016707e55ab27b54532a7360d4112f472a7ccdde4892aba35e42caa523fb88aa2f5a33ba0502360ac5d52f615b3533b1e4ab6ceb66372
-TAG: 21b3c2757288507ea67239422287f67675273011
-
-# DIGEST: 87828be40716e1acb0ce876660045cef3bbbda49
-KEY: e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c0
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a02
-AD: 5cb8b9d71d2989ab33
-CT: 680f456751cca408e19342cac26668b49b89e0d8311b95309f4377bb45cdfa8c9268f9cfea547f114c7c6626a3de37fa75a80b3ca1bb1edfecc1f628432dfb459cb6a7cadce0f90e402185f28b328587c13ef3d1992eba37cb46252fb424cbea94a766a906017ff49bd0d360e30e25247b912b70b81964d1347a1de0bbdeda7a76866201ed728f369e0866a84fb9fa8956d31ee5cfeac115ea6ccc587120599ee7bccaadf5217b09d14deb6406e234bbdd9d294dd71df01db3a7762d44eacc9c0c1218398cfc68c45146a8d8d3416d55bb5628c83427d8dcd0252739247d147efcc737c725a11363b1e29acd13677dec3ff27e6406e3978db82bc11e232163d047ea0556a84cba9bf194002b5794
-TAG: 8977b63942a59e8d7f1279973c9f202e7f50d061
-
-# DIGEST: c413683815bcbf3858fbb654590434d5b9f1eaae
-KEY: 3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d
-AD: 2989ab33e978c4451e
-CT: 6aa6371c08b82ab3a11fcc3606096a2b9badd5065727b534ec484120d0e8c5604813503cd2efb737df2eaa001bd309738a2393146c7187a9e659af964bf7e386a95a2a94498c59610f0dea18e15ac8eb4af5057feb08146e17ac935b3816d7f1aa6fd48157e0773249a8d8d4c6ca8908cbf28567fad3eda42d349cbe630c865ed942abeb24b136a95341da4dc9353711e033f4dec49c0c8d41ce766df14c516704a80606f83e3907984702ef5f520f5b2f54513fc9961045e95bd925181fbe84b563223f857ed2f57c3aa2c365e09208a22bf0a66fa4acad282b960d4fc5f94364505a39d62d7b7b0b087f441463476ee09b781ca0da0c0db77c9135c07de04f3dc796360c3f40f123540c2ca083a3a2a2eb80
-TAG: 1b897a78c5444f951c2e540bb8ca62d177994c15
-
-# DIGEST: e55813b42aa337183d3c091b9f88f8e37832692a
-KEY: 2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e9
-AD: 78c4451e3be585a29a
-CT: 0fded719e9447da01727f2f0e09c5accfa6ca4a37be56c0328d615a5c3bde41e6eb09b8013d5ddb2231812ec1becf9ef7340f61a74aad14175b4f3a06b32554afeaa549940a61950e0541d9d299b4c0c6a2cd9a6d56546ddff208f466355ed5787462375dc54b32fc7a6680aca9579386e11292463adef01c3379d9099134a7e00efdfe477d7ed5dcaeaa5cc444bbfc9891bf2a192094c6496d2b25cc45858ad5124886245c3a1ecd6c515464b70ea0d739278a86a7d1b6bc369fcb29f8cc6ecd60524646fd36dad09017797f5d01f44ae00f2744d61c69f8b29f26a7b7f9f37d85c208cd89c323a80f0d99c689811e6db3365356671dc3887e016fefc8835461bab75ca3ecf52e6fa56d89dcf9338455bbb55cff1e9f10e
-TAG: 1570afb016707550615f02da6f4824048db1d802
-
-# DIGEST: 013c5a98871203f5494bc2d6927d15ace1e719ea
-KEY: 1e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef1
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3b
-AD: e585a29a2af12feef7
-CT: 7239290c44cce5a0a7b22180b5fc6fcee4b1a5b55b1c9475db16e246aa12a4e4d8ba6ca1b4c68b289f8fd18d1442b46f0f1f14c584a1128f3fe456e15dbb3eb2b15d9d11fd86e19af236b2d4e29884dd98a0b89d4f86663f672c2e3ff4e7c57caffa8b09564ceeb7557c0c0a1f97136f06c2b00b12c64fb5d13ebeb3384fabf5a9f35ee700efcddb79aab49e25e7b0e296d2b8e625a970bf1888b844c74608b703a59a57f669745ba3ee89bc5d6bbf19fb3e8acca322fd93f6cd5e0a792c29c47fcecda29c1e2842056fbd94e25a0442f2a68409bff680b76b3e9d5902189098bdfd00e982a4bb0932b272229e1d795c0fb9464db31d9a918eba62eccbbbc29aa0bf6d2d029eeaab97b1395c8f4cc92f8cbf9746e0471399421edd83ea
-TAG: 037e1fd817bede51eb47755c071f6f11d1e21f43
-
-# DIGEST: 7f9e8085dff06dec7a2250bcc60532aedf162762
-KEY: e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b4
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2a
-AD: f12feef71e1063b0b4
-CT: 921a159f066f91275f36cd54486376bf627fa8d342e9816dee093a1f9ce5fc4d866cb1ae146ccf500b558ef543682ce03178dd9c7dc019e47e189bd06d47b708ddca50fbd57cfc4b8bcba7921b66cab1ce0a5ddb8716e015e0ba1b9a47e6d0b417c6c177f56b5dcbee24a27dabc0cd97a08074655e367168f84293ab5306f310b9f13eaa976fab886017c3c94bd0bd04a8602265cfdd4aabb8539332d875aabef8abf53574b17b4dfd4f05a46d2d5755e69e09200fbd88510a8dfa9c44d1577d18e34f9b04b8969d6867c92ae0899bf94d27db85da27dba2f5ca1c8105f219daca5cafd6394f764103a319a3c3d7bcd0058effa72294ed3813b8d977e8cdb49d4e24321a8f9b68136efd2cb926363e0a7ec233e09433a26ca6451910242433928417
-TAG: 499815f05270dc4823696553f505de10b24bc475
-
-# DIGEST: 0254594a43b8c9b638cb456593750b3f8f9ada22
-KEY: 04bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f0
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e
-AD: 1063b0b4e6e8992003
-CT: 5996d5bc8057de4e7db15436983978338d8dd9b3134a029e937fb9b7ec53a87c7685c24a8de6a024af2b6413a5beed842ba376e6b2c9a6e9b1e5dd7ca3d5fc2fc914d8db008bafdb39f632f306a905d98c1be2c71ed53e6c16371fb593792546c3d91e2c067d755f659df39b1b5b8768772e2625268e653d3fe88a742f666da99eee4ef8dce23c87a7e46309d4039cb49968ec13256083b695a9352364a354150e41fb34b18be7702d72df83872d6627a18861c9854e44fa17fb6e2443c97c2ff2ee307adb5fed315a91c5060a36770467782cc5340594f4b393e74a1c848eca1b2280a2e568de697564934a6d4ef14f8d1eb844ae2f2dfe0f4ff0462483e5b0d8d21b5ec8ea2aaad58fc84e51251560d93e58076afa29f2b6f58ff8f533ca13ad84a991ab3a24
-TAG: 17480f644c4351fbed6f21a7624a15ed864db9be
-
-# DIGEST: 15059d32a3357610e64a48c19dec95d256455404
-KEY: 2a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6
-AD: e899200304bd350813
-CT: 73b136d64df2b3fa8e39c2df09322509764ac6b8e9db523ceb94dd654ccd9e1f37bfb6a6128c4da55432de0fba06a6934d162a905b9b9931fa030006f8f50ac8e64ad64d1ae09336f95f541e7114507e03ffed6b5a4c73df41787da70306a765f484987b3102db46cb3dac5aa1d3b617f4c1f2938d384a8628eafc9ec3e5313b96b6cddbb4da34bf3d7467703317c11f3662790cee0110ad6202f6a9cb6d9e155aba11292cad2fef459762efd68514fefc820fdf8016a9991a06af074fcf1bb37cd52c8d491303f1ed721f8f33d53756247f3010ad9b20aca36bea8d3b5c71d4b5202052b4c2ad0d07894afcafa84a125f9bd8c2c3805e562516076c54ffe638b12ad6c79a23ca1875c5fe53879d97927a9936d4fc42e6e20f6882ac0259f718e33edb5375897d80448bb442
-TAG: b3eb0253705c434f7d1e6c36f31347f9ec7e79a5
-
-# DIGEST: df289e1d102b25ad07e98f430cdd24eef513f8d4
-KEY: c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304
-AD: bd3508132a027d1ff4
-CT: 9634f9a5936150cd81dfb92a8eb20be560197da9f2cb0c9d80ea21b30c61ad03588d1281881d4d5b5dd98f22660ab88ab21d58fee675ea122f88464982bed5711c2e8d4d7177dbe7109fa3173bde9d58d9ad06c8809bf47bd0415ff6352be9ed579bed26496fc85a4f28ef8178aa0c9dbec3f0faefac33a8d172a6fd37b853c1da0457229c0e43d8d089ce2dae8fe944e62ef4473e6be0f0fa7d4a3fa7db7a7bff27f542dd34c7e2022b117b45be1a03f769ed1617dc5976f667a3b7529896b200f5d0346b036273b7cf22e02d49026f068d05df84625021efb49039fefbfd9010075bafea9d97ed5000e56e962c64a414347baee525e910ba6cd75222e2570266f9713ef1fa78194e89a60f32b8a176f7e01377f2327eb16c688b0645dc42ec42b2b14c9b6277fc07ef032484ee77dc10
-TAG: cbdf5f13e04d40a5cf18b3f4be7fc81af8d6239b
-
-# DIGEST: 3faf5b20ff66fd6583a2b62901c1ccd798c0e9eb
-KEY: 57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb587
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a
-AD: 027d1ff4c047b3ef4f
-CT: 5caaec626058391de248e4690345da79206ca1583b9eb07fe92e8a4ed451ec8d0fb2363000dadd05225ea0e36fb327b083c7aca517b99fd3553a604a528ac3cf474c9be6f0e2da0b184c8eba60cffaee4ee2ab23d1acb8b4d371ab3e4dd64c9d10da80a789c627645dc1dc99f7febcc82d0d594b06ccab9b2563f398cb24f5778903337c336cc1ecefae2569487c41e498246d36307f174f345314ea8c68ffe37903046308b361382212c8c617e2e7413b5a4783f6e0249fc306298d2b96c802aeff2f57eb124feaeb335352496ef159f22fe45324c2c125153051f7b956a3c39c4c4260287a93674cb32c15c66eb4053c19e6075b1065ab6d11a4fbb1188a30d48e0071d6db0c15ac523ff882a79faf419754a90330b2d87b08a94dc8b6edd42a769b19212674bc9aff4af2f9cec47c6b0f486f8e5e
-TAG: d733762bb04080e15537cc840efaa0209a07b8ac
-
-# DIGEST: 2a1f12db7c66ef374e510b2fee81431a4902fd8d
-KEY: 4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c0
-AD: 47b3ef4f57a74706de
-CT: 96e184f7d0a88b1b00c45117ead492b2407e75f83bcbc2602a9cf660371e3bed40898133b8d706a347f68375102d843b0512522501c455cffe8260e589832219cde28993ebe608459b5a3db9b8d4bc1c20b23077743fe65918972fcc9b2de1310a20e5554476cfdf34b9377769cece4428b7fc437ce113655cb92f670aaadbfe6b83574c4f57313d41a21fb2731e16a2659e440cf91177856a0ab13b7fc0664ce2706ca44f96cf17e29fd9a4754a0b0455c434c2b1095b72b5b9782a91e2437a3bf65ba3f716e6e7596ab6fd6e8980368a45edcd4c222bc03301f0a450e93a43a1d4ce5efdc36676068dcce5fefdae8a590289621855f02619e8bed0f82acfe85045d613029e5db9b07e99578f71d9f6cd1024f3e031de2540ee99c834c55bc56aa4dd95b496797e4599fe8a3c00cabfe518a9a457ca5f3258b37f
-TAG: 9b6d21c19fe123f5b8c2c6e1aa00bfc5525fdd4a
-
-# DIGEST: 524f8d38ff527d6ba89c51265f6a55211a443a04
-KEY: f164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57
-AD: a74706de4b381c692e
-CT: c35644580aec8535204a1d98f4aebc8f70dd659b9bd6810080197755062b975c269c2228d33149ff3ab1a2ffb554561fee4c06500017d0f3e3d9845fdab84bd311bb38995c04d8f801c6d7f7341695921cb0ea3947f7cdbbb4787d032c1fead5ae913bcf7c748805d0d9833bc6a73b43ef026c8a2c77f031cd9f2cb05ae5ac4cf639f93b50a8775c3adbd06f212ea14de34ac7afa93ff9b2e60f82407a8cdd49e971a1a938ac30611fcaca913a509eb6fdf8dd859e0ee3ae4178b1fe01f6a8e2285fdbcdc73f36f9fdf04eeaa98861b068abb69acffc765efe68df97206a8738f6555e0d6c94686f09598567a222b754863144daf2b14a1723103914e8f37010c86861f8f510d32c47952cb548a8977023bcfc5768fc89bc03c0bf2dba1f036f576fde363c35f0d5381998bc5e9e65d1dc5efa52b8810f96d4c1351d9e7462a4
-TAG: c93f523bcadb7db1d2fa8fecc9ea7b63a4f5e4c2
-
-# DIGEST: b50c58268b989fac3ad8f6d25a401211ddc5cef4
-KEY: b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab69
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b
-AD: 381c692ef164101b89
-CT: 19aed26d8f680371ed40554248306faeb951ccfc880a1303d394e2948e55a214b056e8db8ca57ddbf5007fba9d77c2429e64cd417b10de6478d8b9f48e79de8ad434d489bf2d18eac4933419d7c971d1304a8bc605a89238b9e440271aeb18a86d8e17523ebbacd86dc29ca4e1cfb396e8e79b717a0188d094923d90f69e2d382e57fdad06b21019c0f61c504b76546b43a4211a7a235186ff236638599efaa025a2703ad6f54f6c31fab2405a26fbbd1f2229860c76255c4f1f113c775d3df0fe37e29e617731d93b30e71cfb06fa9ba2cc143492b3758151e19304ab27be2a5775aeef539a10a51fc94d1a37a65f5d64b6b3b0fbf0ecee2061663188c288a668d66573f479b12675be7b3d563feb532afe6177431b8cc1da1b7786c2e2992809638f9f00cb6d8464786227c9fe0e957e3f549bc5aadeb185c0b9f52d8c676c893b25fd10
-TAG: 2c444107e0c938d5bca33f5e18c91a3291e6c060
-
-# DIGEST: 7337152aba55f41574aac9d678dedcf895a1fd7c
-KEY: f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882e
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef1
-AD: 64101b89b476f72b27
-CT: cc4663885845e8360fe110fedeedb93552d33ffa03f4edde71b69fab5a55835a3327e0fb1b01141bae77e9faf534c97bacb044ea9744059a1bca2c9fd5cd61ee097eae00a206af9f3fadd82c7aea17968c128548e99495da6047bb8b2059afab4bc4731f5d2c9de2ab43386def08ebf0d981721abe5b2108996bc604096a3e5e7b2030b1a63af3000ff0d5c96c7f9073e52d7a9e895e642cda8bfb692a220b699ac3cee3c557c80e1d56993aa47cf96a3494cfc27fb515f111eebe5f0bade366183477ce44e1c614dcc884cd192e2dae6e5193fd9435fb897deb2c11b76413dc33534a4dc9027a88d73c4d151251c0511726aba86905ccf135833c4c77f0bb4091921beb549fe04c1909a4f0930848c5d1cac51c44f7cdb060c0e370d2578584fe7170b95d225609648057478e362a33d7a566ee27eb71a8831bc276e685f92236d1c6129e8fb436af8c
-TAG: bc75c7995b34a15355b0b8e51fbbbe2b57e84971
-
-# DIGEST: 6578de87f977f4cd4c5d6dd6f6f99daa338ceef4
-KEY: 67cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b4
-AD: 76f72b27f06f520c92
-CT: ff3e4153e46cd056e3c73aaa60416f7eeb126e59f47b9462c27e23d2dc2e7f9f4babbddbb205620bf89cad24879308a99f16c404fce4b7351868fa3b081c6ed14e824a41ead8db109f537784724f4a25e4e7c8960a563151223dcf893e1b09bfe6e23d5408388d975b158af6961f92ffc70738822324055f502500b3855c3d4898fe2838ffba75e0bb6099f07cefa4877611a33f4f819cf13bde64e4d5dea2f780d5936a4f3b5e8abd5842b82ff9bc97c8287565a33f3038d31c4016fdd78bdd05f38b3420d6708ea93c69b5aec08461a39bf37e718c3b2dd797f847ea8d5448d82ba7f5595dc9a3036b8cda497176e2f3f952e1b37dea55ebf10ba60298c6d12c2968e9dc09df92fe75a814b61c1b20c7dda8cbbe8897f086335cbce0a5b00370312d3fd737c14e0bdf46ede18d051e82e013af5cdd45749b5c496a16247a874e7c48e0d1ebd8343072fa403ae7fa
-TAG: 1122473ff26ea7f621e3ccd8e0a7bd417794a02d
-
-# DIGEST: 38dda49f961e8d18556e2f4cc30812a7e17d827a
-KEY: 41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c87
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f0
-AD: 6f520c9267cf71408a
-CT: 3fce7f036bd0fc52bbf4d25cb7f9fd88c78a157b7cb2fa349eab415316db90c987874920e6e4fdba26e4ffe81adb0eca3bb315e2c3e20c446f18c27cc7ab7686bc59fab8e085b6de1c9310023f4a33ad867dfdf5c7271cdd1872ea76e705f712a412c4d31cc1ee6fae2a63d7c44a71b2232202ef2cb6a9496809c97fbf2621f0e39ff765a99d4ac4410f0b9c744638d602e1cecbddc5358aa2faa06c82d0dd628f7eff73e2b010262a735d885254bf1168c123931e14a8a5bc4bd817078724766fb07a6279a4b8ec3fcbae311df29b2d7a7213a4b66032db3e5206b297872954447ddd32960ec4ffe07dacf5a106ebc455f9e30a0a4150c88aaf34354a7fd0c050419e8cc6db9e12b2d4116386fe1550888779c7fbed6b1d56b23731d0fe3eae14e9b993e49e965db60577d13f6fbb03d937e0c09cd10b1b15133798717f74201116c3da2c08430bf40263b591047cf909c665dc
-TAG: 3a0efdac8ee75abdd79c3f93028fda0bdfa37078
-
-# DIGEST: 9a4462e5c302d0657a599d31a78f3581e4b1684b
-KEY: 877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267
-AD: cf71408a41729bacb5
-CT: be03b780b4698313866ea0174471b6c54dc7aaedb5b438ba944202cf763f0f1d906599d23506599a11d5de0cefd144929142a94c82af2b61f908895af4e679676a0ad9657e6739c617e1e52182386a8db0f6922e387111672c1fa0cb0fbc4b4e42a9f2ad137224e91b21895bd958e702a1665d83c807aeb15977642d18afd931f50926ab27a0436cff6b04f6c1ff93e58ed2f4d4cb6f5048fddcb5ef135c3eda8cc96a8e1aa8250411592c43e7aeccf1c814dd3f3a8fec60ec5613296fdd1edc0d9a76d4d252cb8b28cb9697204d0140d51f6eaf0fceb8db7269030abe7dd1dbb9fd4162a59c2790987c4e204931dd64c06f5041428870d8119601a21a88824d1f2e5d2c56bd34073e05ac234f64f73aac7d67c754506f62341c240e7731c506438ff836814705c6f48fbe7056b408fd083296e9157dd53c4a6065e1be27956e6494c724064e58e69833ce871199ee92c8dab57f6e3bed6137
-TAG: 8c63c41924400f386144121b91411fcdf4dfe91d
-
-# DIGEST: c96066fba6ca75beaddcbf7b6bf1b43b2a7b6353
-KEY: fa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41
-AD: 729bacb5877e72cdfc
-CT: 80153a7bef8ab89d04214ec93045cf4c471b225ea04e569f2e394b755ea7bc6378ac1cc7b9b6f407d21d82004ef7faa37624936d5efe9b5f04d3bdaf31e96afd2eee7441c09de6413ffed0323a15bb6ba02a7e9775c3e71a32553a48537ae94a8d7de4a53cf3bf1c9ac47ef9178ad480deebd7cb02977008987dfeec4a8ae0160f5e3c726ae89230027bdab41ef703831d6b85775321cbd64362e2a6590036fea8f0a86752800fd44dde7f934b7cfd8892a1e3de873cd162de316d3610f7ba522aefe82196f459572ceb000498faa8b383208add721a9450d4586745115ec11b82bd39c1b3b016de0f7307ed2cdff9fbd9e4981c1ff42d5a8b4307133a0821540bfa1c94a100f6225b0f37bce482895dc0f3254e136f5ba8dc622843516e4aacadbca070e70c775be978e72fa6f9dcf695b07b42848dec50d325f7e80679299d7a39ff07c33f95e29f4fc8a19140c3e25034521043fca8ebc8dc01f55b92
-TAG: 75b49f356afd4752dcac3abf1525625e7edf3811
-
-# DIGEST: 0cd3dccc73f4bbfcc3c62b4638bcca5a633a2b37
-KEY: 07a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb587
-AD: 7e72cdfcfa76aed067
-CT: 92b56e0f8e04cd31a8496097c3a4d188e3f7dfa36577a0896d9ea81a2f0b92eb6d55148ab375e7e9cb7398ab8f74916735159553b26ddeb3143d6ad8934b50f6fd59559e5d768092e1a1dec220ba9c0b30a76582050b5abac8bf9b576c39c9d93375b4bdc383e9145722335f5a458da78af2f94d35bcc421f695584148ca0aa63305370df473d17771eeab64db928a96d60270e73a30e8d44c3c92e261d14f4f029b1816fbedc238262179f0ea101003dc27cd9018f1e64408c5fbf6b81226a801769c23e05d85b74ec8a51e3fb58662033ca4f4900791fec90e212af7c8681b1aedeb5738e6253ba4f150f9b2d86051b4071c778f8e020efe350c1e81818e0822972a4f5e387c81f60b460f4f865b71ff29471c76da0a6245b7a0cec8e882d0c3767e12ba4c550393266f137807276f37e99ce59a8a1033b878b8960aa0d0554082a9bb2994f48385d98aeb09a28557a8138ebba93b7ecb4db4d3e0e995ed6707d6b2
-TAG: 99aa6de07804065fb4d36a3e0ec18a954cb98135
-
-# DIGEST: 61f7a437ed58c4d0c66997aeed34757d4f36926f
-KEY: 699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc909
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa
-AD: 76aed06707a07c3dab
-CT: 239b6400b1fb4c9dac96b84401c419931efdeb6af9473975979c2315a96a103a0cc5a3d89e44c5f18cd42e218af662ef0cc43a7d9fb1b24b238a28d18e4afcc7f2a87ed59de04775af7390444fff68af519416ab0727ddac1b6c46fef5085871575481382e9f244aaaafb0dd004654e0d76d3eae36db7c1480adab3fffce2bf40ec172ed00b72266bd7049b3ea0d18806b86776dc4b43e60e4ed856811ebf7ef7a51853300d80d713353938d6c05d6e79ffc2a59642a7042805fd1482917c0c1808677f977738a4436568d3ada913285be30999a9c806c74d22b1a7e65bf80cefe158d785bd86229c3ad7a8e2129262f4cfc0a86b0587d1cb5f62179de15acbddd7f984972e627554448697cec457a798e1b0f1cba6deb1c795432f5964a02618a88dea906be61d09bbef6bcabc2cded3867b08b023d77ff114b32a40748dc9417eac9cfb2eef67405a28c024bd82e2dc8fbde615c3a2caae48eae1fd72a33f0cc3956b1f6cbfff7
-TAG: 965b16a7dc6895db026b69f287f37701c21ed2be
-
-# DIGEST: 9b062a7f63d081bc4fbb8cf13db57ffdb7d113bc
-KEY: 2eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d7
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707
-AD: a07c3dab699719fe88
-CT: c9eb33f74f30722568f1fb10c74285184125a317c23502a53fb683dba4f27f1fda501aca6b5beff101711ab65301d5323a2d4f665e9609495cb3eacb0363cd7e664a9aff6a7816d01969877b18e0e114e9a03b86ea4be8f3bba0c0d207e6b052a624d0d04d6c69249d71ee6e7dbc8ae57c6d47d34ebe655da38e5b97aa19fcd2d0307d9de6a0f61c9735e71c3edf9867e1ed8684bb41b0d547a8aa9e3fe8d6dda64078df499d0ea49fcc2c212950c65ef107c12cefdd1fc1edf9d8637192ba127e7e3fbd07bc6c662d8315ca2e531e374b1363470b890c0bef830768d22548d814c92b0c5945971271d3443a72ca7e317356de9e4cec5caa2f47f2904ed1aa88c88ebc386413049f552a481a7de29afa7ea62874e7085f76a4bd716e0556ddbf2188ebc8b9d68ce388ac5efdd251c47d0bba7fe5c5d73171fd382433990fbf92ebb7a612b20c9b040f10caa5f90ad4faf3ac053dd469b43d99aeec5418d13e1d7959fa7aa01907e72a0a5eb0a8
-TAG: e921b1bb121d0a629c08755bef6fc3f1e4c5c3f5
-
-# DIGEST: ee4812a7dc3e037844fd9c35770734168c4ce2ce
-KEY: ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab69
-AD: 9719fe882eee2fee55
-CT: b420c2d484ef8284447a0d14ea73dc43c79080c4560a0ecb6937a920bae8ec975e14c58a200f933b24e472f544b0b12539caa91f8cc5450a5d9f13344008e303e6770a057737ce04d1507d320c0e82c8356041b92d21d8211dd802cd47d05a7b529832843ec03f74d58f75f2eac4e43596c1ba8e6539f7200bb1eb491e975a7dcde78088d042a6ac7731c904ed17675b7265ced940fecd4ec61e6653fc12a9766ecd167e7d33ccfd501dabfa72ddf9fd5ceaff2e81fc8d821142337efc768acff4c01c245e36161e4226444bfa42cccc586e041bb9aad429cf3a57f3ea674587ef49ae09e4845c52becedc76e79e58a00d80d0b350f89e9042a74a7a3f02d7a8e3f99f9431738416d5b761078295bf6d2be8d05a59a72f8699923fea5f61dedbb481993fe19d6deb50d39ac37cccc875d84246303a9a52770758986ffb1331b4d7aff7b8cfb3a03befc9ce156a5f5fe4d42f40e0511a5dfe8f1d6babbfe65ce85f1b1eb1f6de30acf52a8593d763f10d1871
-TAG: b052776332bb81c991f6f70e79270add7f0bf6f0
-
-# DIGEST: 4209b9f203b29926176f7d54ae89ce7e903009cf
-KEY: 870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882e
-AD: ee2fee55ed8b11534c
-CT: 6f751cb6179b55339051a1d2060f68e0d73e5d5eee4f3a6dfa5555dfcb613a8993dc473f4fbb0f5e2ccdf2041743a7a436ee8582ccecbc2e2aaa9865cb2de735513f882b826bf240f217808e5dfa9a1f88851f1c8a7e4a81235c371a0918033859eea12b41a8d46eca874d3247837be056e441a82e5eef44f550bd3e079249641a2677dd3a46939eaae2fb61cfd8bf27567b4e4391644cfea7fa04186e67b9c347bc7bb331117a81daa53821822db4f3a1acd888d9286d4898c2e3fc5b7b8b1c829c09ae7ad556509d6c284a9dc2c88fc6db5a928999d15c7720d6ad0697e2dacd643cff49eaa3b05c64ec8d7f8e6da47978dd5ac256513e2b8fe3f52625c5f77f35a64ee264d9090e1dfb8453565d8df618c242b1b48474b02ac71ab72e4ed88080a47b7a9a2f450d30ea021cba5ffdc432ffed92e01a659017c184ea9d0669aff47160af476b00a712631fed290bea7c4763c80b34ff2cf911bd3623f49b3b27e7e17e47197b93ab08e2907773c6164cf3fb90c4e16b
-TAG: f9435a042895ce53916e1e14ce1df9ced677962d
-
-# DIGEST: ef5c6927cf43e0994fe5d8e87aeee052b6828289
-KEY: 14bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed
-AD: 8b11534c870dc695b8
-CT: adf307571ca077ce893883f70f60276c36d601bf49ee23adaf81c6b84bc3bf46e9c13c921556f86075688d9fd3ed5f678442c09a6d3f81f52dbb32224d878f644046a9318de7fe5a8520735f8e71a66ecf176af38aab83a0c2c07b21b574f067544c03b9beb50e04c85df9b557d143b30bd5c75f63813b51cbfe2bf4b077c708cbe770c83ca0bea9b5b73255b04906fac466b1b07d4ac48e0b2f318e8a212b09010e262db38881ab8e82b61c4b370c4378022225e597c9b0081618c02604ea0f3c5cd0faf3da44bde5c4e916061380a95678113e8b16d66d2a416dc713fc7ed921049af96c97cd827d781f6c3e8a89447738dc77ab3b73ae1cbd2a5b6c42f9b9237b8fe0d9bf496fc20bbb3818c77153b99cbbaacdd63bae384756d83da79963c5754d28fb9cf72e45a6f5f3dd064ad23402004d6b102edbb3eb112f80983f92fcefd35c1bcc876b6d98c7650d1485aa2152add4e11999ba66e7627d216992ba23590f660ac289d96cba43e534b03433f917540fb4730290112a377b
-TAG: aa5bde606f1143263549c9ef1fe4ebfc8cb6fae6
-
-# DIGEST: f239c330cddd57a5e88e777c848cd66e508bbac0
-KEY: b1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c30
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c87
-AD: 0dc695b814bdf1a87b
-CT: 578f5fb9e465d5170e4213421298803b81153140a69c8867d143affe182970729b58af0aa00c280619b0bd9aab23c988e5ea60be4100b8b000911b96f8c7345fb590b478c95b1d7ef9deb9a770f59a433f44aa11cbb4f9d1ea2f9acc861c8e44c932af277022a2f7fa1adb333f1728c7c3219cf616ac6d90f7dee497470d5d50bedeea6771e83be2a42ac9e9c54d27ba3fc1a8f77ae6591079c945111dbd0631e80024e2dd62d2487fa6291fdbc11001d7d8fe6aafa069da4a6c084c328b7850d681fc4943bbae999ebb5950057d22fad12707df8b02d1b85ae01a4f97747a0b58c6cad19846edd76847d64f9ef8855b5679e6ed78734b53b014e7fdb04c436c64ab8dc96a380cf0e69e98dd6cb302caedd2a2922f38fee381a6ec63ef507a3c657e3f875edee806c2a801c72461174de3cae1c73daf1aedfa75543a46fa51f254b20c53bca20c79f036c2b39d8d5861aca40be01382e6eda1ccfa159c517bc4bac0507e14f16323b812ccee4f70ede598ac37bfc01a7ae9285fe90ed88bcf7124
-TAG: b40c2e6bf817514ff9bd363a6e06d648be0c261f
-
-# DIGEST: 7384b8e3650297f0e51d9a8f76de34eaa4bc9fcd
-KEY: a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95ab
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814
-AD: bdf1a87bb1052c6755
-CT: 29cbbe2cf50c291bd2f525173786d8fb20f45edbf0fb52825e415a644a6396bed1346abe0ccdf3e20f602951be4ca8e2c5fca8f6d79ec56f51d1667615e72b475b8f7cef71a97992f167808b45ad6e450a3ee25eaa976a87827a676d2534fd604b3765a9e2844af2dc276fc8bcb76c861403f822e900db914c9591a3dc1c5e05129c57aad7d3ca1e58f713eab94de4edbf418c50ec073b616e10bcf7228076598c4cc89431413a66935ea2ccf98e87b365087316e362406d02146a3a3e80d0b6c2b38b48d69530f48295ae305b7a177308e28d17b0b1f4f7fe218354c4857963abaf6eea625b44b2f764357121a2bc4d5cd7eb75d52509c48878956a1598ad4979f5b1d05a311263a306fd2ba36f3468528c150b77863c01bc8a6f8b502b4d4d75a138bb4d34445570ac7bd9ee5ad33a1a67365e0a7096f206c1d401e4dda563f61fa826f091186e2d60edef486cdae4108388c5d6d131bd82119c3710c9c017e3107b328c840e79691773a6551287ff7b7245854ce555587368e8a2ea741383a29eee1b7e34
-TAG: fc08fb09951de4a6bc3e8cd483248279650f1c45
-
-# DIGEST: dab0914dde7a8845203fb78f9b0af41ce550adf8
-KEY: 095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1
-AD: 052c6755a7a116bfc9
-CT: 2b5aa6105c526639bef306b1b4ed377c51ffe3389c70767ff4b11f5573bf128b1a1d745419c2756e7356cd1c7402969891ba10ea6b6d336222e5f6a9902dd23a0447e2dec8a24ca99abebb3d04954f6102caedf6a22dae5a2f5bf01c6b316d77524aa86245c89f6c6bebce5791dd7ce65e7239356361d09bf35c6c07eb6141abf5e8a7382a86ba32c4e1e3382f3599b4e398cfd08eb6b8dfc86fc5e6f5da1ad252ec57e4f550ab2887ab8cc7a30c06b9cb9e22180846150538b1567525f86c0363765a287962965966179be154f2406be74da366df58d4095a1f179046c02c538e30b70561ac03fcac7e1844ba1900473cdfe7b0824fd26c623cc9e87fef340adbe136dc0e06b64ed0f0f5b1ff56e094dfe3894021082b9f9b10ff46d76b0ca9829a2832e0c67e99679aff2a022bade3743dea259aaf1b964a7ea84f202986fa9ce9c1d98ff77ccdd08103ba0926fb8bf972b9861d537621136aed49b33d4cb4e574a485fbb1469c8bc97e8e23300fc970a9d9e3c81580703c12632f1221a37ab45db367ed31a56fb1945c
-TAG: fd6d4d5bd750a7631434ae3c1102db751997e965
-
-# DIGEST: b139e0011fe2e768284091a4f838f86fea1e4a7a
-KEY: d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7
-AD: a116bfc9095da49db3
-CT: 9a878b40eb8c755bf7fde51fd406d7ac496a467f36e833586f6f1f60e7fd6c52ce96ff9049055af08aeb99e28ead97d83669df6f868a62fb4193a38e65570e30c1ac39279f107c250e976f2b396fd94f0584b41ff02b6bd1075d7af8d580386398531ef5b5868153f3668966a23c72bd02d9e01af231a7ce327694ea81a6165326f098f3fd3db8b0a235db22571bc3b2511b2874797a4bd1812f79cdc7462e44d204995c65a6e0c0789cabc344132bfba06b7cb493713c184078cb64a13e9e72b91896cdb5586155173755b819389ec1e4dc853f44ddc414c3ed7516f342885d7cb40a426b1ae7a5422b6ea77fd8bcc7e921ef6862ba1ef0d8f625709017e207e874f7858a89e4e2d73bb8612fd32c5e57074a4d4dd2f3d97cbfb11913361be39bfcffbb5ec9fce19810a4357a030adfd070f4924dc82338441f61d9a9bf0fc94c1c68ff609923b6b95fe4146403c0009082296e4ed94c52f8e5481c017405dcc870223f0fd6efd3243a385b2e70771931e8bba676b1b02a215205f710e1e76cb123a9722757d22d3ad49f1625078347
-TAG: 9d47b2d5666bafaa77edee57f26a6953db96fa23
-
-# DIGEST: b338ffac4bbf3a2e41fd1b3b6d9d224d4263b547
-KEY: 5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc909
-AD: 5da49db3d71f4b975c
-CT: 05ab919931edf88f6c7d68a883f4928d31e31d6bd8e223ede06a1b05e17bca5726cc7334be24a5b8937857f4d0adfa3da7ccdecf18ea73b4b0af199f9f39ae47f8b805ad5375d50d3638faea53e1073e8c79929a3e2bf753154bd5980d347c2d12c7f3d0ceae0a6b5f7e58413cd321597873d13d440ffa5936e892cfcde8239a5108421f0f86357ee1855ede66acffea05bf8b6963d4e465acc84f3f97f74466be9109dcb7b24041f32a017fb6629fceae5f5045f7db743442d79b3a38e9b14891a80334dc80e72c94a0c534df3d8e6877a05a55c7cf0f14cdb4bcdff24ce8e76e25fad1ecfa1e6e4b39b387a1d0165bddb2224750e7d3971bbebc8d78da5f25387bf3e1dbc31c10118107cc65fe040f7d37cd778da5125c619138236d082bdfdb56f08670a20e859a48e71103e7dc417ef9d78ca7308b081a6b96120bbda291d3790f1c516f3fef5189c2ce34f6eacef331672b1dfddb6273535ea3806b470afab24f8217126df8821fd3c8248753b45cde8276242328bbdd2d16564262c874209566495d6d846b858b2baf100b596cd9fb99fc70
-TAG: 129a576af57cc5e9e26957085296cc83d8ac9789
-
-# DIGEST: c9dc1fbf134470bd3ac0d9855918516e5b8d8778
-KEY: 22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fe
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d7
-AD: 1f4b975c5d503f478b
-CT: ac26c716fe110ffe65fdf821b8afc4aa217b2dfbc40c4cfe8e014321d62145d652c55256bdfc50da8dd5e05253bcf3118eb4deb03e802c7b3c9fb2b5675829d5d58972bdc806b8dee5dd394e5dd2f2c0624d99cc5092ce9e893c0cb3c582c63f25f3eadc2feb5f3a55acd013c1ebac8992c4282ae15a72e5a2a07fed6b8272bb6b739a077290321c3acef763c290700e32ee4ebcd8739eb70251ffe2ae0bd0c8177365c67464947eb8b0863bf3d155c289f7378f6cadc3033f2a4ebd7db180f9b8855af9aead52067cf707167453eb1dd4ccec0ef9a5d6d4275417b5ad5be6fc4dbcbb66d34bd5160fd5acd98e5d0e7a89990a0bd7b920eeabeb059ccc1d7ff3480ad3190c4b54275ae2ff64e9766a7639d0403e827b234ad18dc298d2d651bf0aba550f3ad23a13420f181d997984ffb62d623c1db9fefe77ba0db48de7c17311065153aa4bde5e17865e2af2a037fc3005333cb856ecb0baf6a05aeb6ea983099e85ed8e2a5dab283d389fd5966e3025eb431a37edee0ae2e9de6573a93a78bfe973bcd135275b9ab5b698fdd40fa2bcc226b83c010caede1b
-TAG: 07987dc6133e2050817d4c9f650d2dd63820c982
-
-# DIGEST: a551ad393bcdeb8c1bb1a4a70e367b069ec549c7
-KEY: e6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d
-AD: 503f478b22dc8253be
-CT: d5a7518fc6accd03686279ccda810b8a15d6a75d6a3de1a0f7d8b2beaad418cd45a6a3aaab1f10ba101728549e64ead8d6ec865943e02013a1c49f3c1ef254c7b80a60fba71ef4d24ed89a776c066b86878ede6fcb6cc01b9fefb28581ccc5784c574f6188df057d2483358fd159497a74f8c2761545a522c2ae2fb7ac43abc655e3bce5a3e970172b3ee8e310b0055d8f263d4e4cf08c066b6305903f04d5a8a7b8d2fe0bf06e1b88b6e6d0383302cd82705437903219574f17a0f5707ec9318dfd93401f629773c79cdb7b07978e16ad7d53e4cf3b6786f85364d80c747c75e5926d06b689f124873fdc47a646b3994e2e1e63bc1f2942a7c74b4942440ed4c6bfad7f39e951b1ed739ed9f5e6332623acc3f67e1586c6dedb2471f2886a6e83263ea04b623df4ebc591b651dd030bf05c4ab4f2dbf5c0f1d120919f9233ae37d5e49f865343d9858f5dfc6d140d29da4e62f8d4317b39535b2bac1f43b6ff60db448f8b7f4f1ca69d6ffaaa8b4c1e7729aa1740509506abee3cb8d2cfdd7b3cb7c719ce83381296da1d17259f0887963202cbc806db70138880b03457f1
-TAG: bef2ba9751a26349c2b0a0ca06b900d510a77c56
-
-# DIGEST: 45b1d26c62717ec46530a565c9e11c18206bab29
-KEY: 307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460b
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22
-AD: dc8253bee6fd1b174c
-CT: b6fc258bb64e8ca059c30c0c6c3818efb8a3566058e3fc30f5bd555535568071c255d434cbcef333e02820f0b3d824d45811d575fef8a883de07016cd7b9546cccb238d42ba5e384f82b2aca128fc12ae4334cd5a74397cd9b418c711068167dbd2b51967eba5ee6bbbb3bf54aa46f49d523eb74710c993e5cbf86cb859f19e4b6b0082b9f724683fb45880f3802493d3d61f8a826ff073d635955fc73a833194afda9043b347b6294529185b3cb827b85269f7cf5a457de4170db0194a84ce96400371a98b76c7b8a65d948f0f34c803abe65df001f5fa80e0b63d237fe20bf6a1233686d16a37d6e244ea59e07c135050a2045e1c3305ad284f0d0981f683c91a64097fbc4219d9f9e415d90fd59e6fec3aa07d00fe27209658a5a446ab8982e49553ae24e70f4deaeb4ff662ec05ab7b4bca774a35e0037658f4ae2e59d8174e41592887652ad4ea44b081c08d698ce47d722ad29f834b4132ac0675a0f20decee4a4d946c06d25c1c905533be55e471182ae1f445dd2deea3637ed985e22efe4e4f9f4634a4de27e13082a9f7f4e0e0366fad88ca86c63dd9dbb33bf61968e989103
-TAG: 94f0ca862e7d8e1f764df9b738378d3fece90842
-
-# DIGEST: aa7cb8f1b995ca51405931f1d021ef30a5b0eb3d
-KEY: abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6
-AD: fd1b174c307f01be95
-CT: 9085c339ae7bb43ddc1ceaad9ba3317c1e1a6dd5e391beb5fcfccaf258c4d9c78bc8e4d4728d6b7381917e4b7aeea7759ba21f67a00e31f0b6e22a4695285a359e4a8114ff8d94163ceec0640c5f040b0a7869065d68603ee209b10632cacfc81ac6fe82138d0faa750fb04d582f06ea5ee009529b74ca203fae65e4ac47b81cf46d3d6a95f43f701ab2d80d02e31ebefb6d47a0662aecf76e3bfe501fb10261eb0b483069f7b6309fd04ed4fcda950863a3a32a2a027fa220f262029a05e2544bc490f30363a26dd9c809c10ddf48f10805922908c1d40d99a8529f153e085608920021b316533954eb3f8dba79dd4c5d1c16d32859d221c63892c9138c2e01aa44351f5d20040a61173e6f4a672a3d9fd6265fbd2ea78048379f8c1f164c2b0421dc7f248fea856e3060cb340c71d913db8eb6739fc18d0232a2ffa54edb0853e40c71761523b7929c8b7e315066a5637bd0171b4489a201e21b21e2bb8898a57317405812fa41b4f5ecfbcb4c8222edc338e056c5a85e1c55491ee9850347086b137a3517d39c16db5f7b0a5282219e5b15e8dded5d174b8e609d954e7f8c55ece0beb13f5a6652
-TAG: a80dd559dbad93f2f7e0c488e7a1b64bb50e2fcf
-
-# DIGEST: bdbd450e5d302436cffcae83ca3a444c0253a85c
-KEY: 57772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c2
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c30
-AD: 7f01be95abaa9bee58
-CT: 006a885cb2b3968ce150b4e89591cd0b5baf7056f1d82bf5fbe4f994be75e2323ba28c7ad84a146a45a9c0192daf25c113f164f4813d88879bfa21e583e2cd16ea9232be370b00f174b9d04af4877f0dd9d5695c5b65f5710165f9c9806ed08170c9a968ff24065e11297147d3575a1173e752472c31cf7e6f11888f55eade9a86e4c8d61ef0d3a4d70d9e469b0cdfcc95d66d116a093a5c7a392510643905b73eb816b981c8eb2f07eac0e61966eeed596d35f3efac268af78fdf655e981db0069a76df72af523ad88d313f8c6001dfdd6bc2417b5bf25b1e97d380e84a6b9c8716704f1fe8c0ecc79362e29a4bdcc7f97f331adaa2cddc81c9bc75fd45b9ebce682cd72cadbb8aea74553e47aa0f7fe046853bbba6aa93b797d0362ecf8061d4be3525b9b71c990cf62e8ed7364989114c1023e6443fcb22340d599f59188ee00c28ea9ae17555e44b7a001f6064ea0c3776e19b5318d0c0710e6b5be0695b86b9df2e60a640946129a83582eb0bf613c05b1b3156bb6bbf8735c9790b6906d8ed2f87b2edcce33117124464e24950b2ecb07319c4892a8d6b1be71b5ab21607b5eea8e1649d3a389a7ef0ce75
-TAG: fa6c2e0a8bc4fe87333ff0f450005063700e4a9d
-
-# DIGEST: af3f40d07667dc7e32a1fa664c6f5503c3e2c8f1
-KEY: a4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f43724809
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95ab
-AD: aa9bee5857772305da
-CT: 7ba590996ccf9cc27aa3ca835494fe22c04cfd6653c6a130fcaf6362950a592226d64d6300957701c0bc7322054ed7a5da0710646357976393997ca1d9900687e8b9687d8e0ab4b52f570e59fd24d57d5b6039efdc89b1ae1112b039f4a5326d5bf96bd4eb9f4786d29738c23a411c268bf97b51052c1df7f852ccbd5d73d132aefcd63e7fd424b229f44c273c3291379e13f55cc177cd5b9b641d888f3a8c331f753fcd10200f727f7e72e5ac983ae908a30e4f3d1f7cc7b6c4b1a5ba3829e08eacbd0b0b902a11650bdb1e66eac4aa1cf9fbbfe982c3cf1cdf6e08a1af5e40a76736b63e418ccd2c90a9d5bd9e0e6033ee3edf68f220b7b6ae78c155656b3fe80512c90b2a26a5f89dc0159a0707f2619f2f76c18c3c2d82dda661cdbe817fe2df1c4ce139016597cac1ef4e8ec30413624d4cc6e5285aed49643db2d70abfb36e97ba3fc9e88c17abe5f82d855b09b303a748d0812db5bc07bd59211f292aeb0b8ef001259b7a12cd7e409d7396ea5f620fb9054ecb506c7d548ca77a62761c92a8484870255f3feb878e6715f711b608af234235e55ba834373f5223c630a061276875f598010e0567ee72a211c32f61eb
-TAG: 6d8145aceb01e000d3463cc6fd07246076e2f1c4
-
-# DIGEST: c6830aca35b85932f7c5df33907ca59bcc489a85
-KEY: 05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c4
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857
-AD: 772305daa4b550d75f
-CT: ba7f2c4b3acc7aa855b862e9bc6a6e9e4b673e9d6c3e5c3a756e0017a68be0912dad490c7a42dd095e459e3a5696e6291ff98d412f866d1ed177ac311920b60b062b108a36c80507d4a41b20cd14a9f6a7ae142382d88e7619376e223c0ed4fdd1d9c7409a0827104a42bce85e075fdd3fccb5635b0d82abd75507ad4139ed03dc49f39ec6c7b3ce05f2fe0fff53da5d7316908061bfb3de630c40efdff3ef612a9352d527dd2f505664558f99b0a7e908738ee6fe833824a2240058edd8c2bd9e77e51a3828b6a382cadf9c5fa2b7f70aab14959d19c485e94593da45dec7362398c2396461b5d1dbf77d3e954f7e2d08dafe24dacef38500183a17ed92c8fb8e9974c21fe8b597004a087c633f42a67d7d8f0e8623d70819100f5033c392bd159afc5c39f6b81d30d8e94e9a2f13ccd5428dca2513178eab91180d2226d3293707873ef69d0163d3c8fa18e879cb0d51ae6e289ed7825cd46df859e70ac97c5ac17ceaa4da73739d97750cd000675910decb20d5941c2372d46ce69d934edecb5e26e02926ae4bb6819e4ed8aa3c307c5ade9330b36d4de79453a1b294293ca9bb7e6454c7ef31760eaa10303f52c4f9a5be9a2c83832c
-TAG: 5f836b39e8138627594b0529ea382608be0e58e1
-
-# DIGEST: ccbdb85e0a5bae6416136d8d64ef0fc8ef3bd52c
-KEY: fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4
-AD: b550d75f05d8089850
-CT: e0a855b6d3584bb5793097867ddf2fdc65d509a493675085df912b8d9d45f65dd3f18f4fbc3780ea2d134107f4685ed9f6d40dd52c76b1cb3ae5b4f74d3110f223c1db893c40df84cba33b8398742382c723c91de8f7de22138ba150c6909147a81d236a65806655881e7b77e115e589ba78f0665839668d84e9bfed25f0e3328be98a66176e9d73c5aedba453f241c4cc056e54642bfba8e3bc60165f4f2abc50b99b1985501d2cb08a735ab5cabf8d83020a12f94050518276703f0ef5c9767139bbd9f4a7ed0dbe431bc29500e715df723b0a89f9a26638fe7664f32dcdc52a3ea76ea605e01f06cc734140e2bff8bbd589b015dc043518f90c1fe4a9fc6a9e42fca91ee4efdba6bc4fee897e3a35989945378bfce25368b2acee1ac82adcdedcdacd2a9ed487914f249c8a72ccd93e2afd43c42386d7e35e2568c0c812f110c42b1c666b73bfd200534a2dc275352ff46f74c327431d834c24c82214045d7d4efa6297361fc1c2e4eb1ab3a8dfaa417c4a9f2bafb26f934bcf16cf6aa29a264d8100c8669a44692a88a26ff5705e6196bff8f80cf22a1bda8fe85b68660f10bf33c4b566d0285dd6fb03c116c1483ba7adc82b98c6d2168b1d8d85
-TAG: 8cef2e943614fdebdd3b88374925fe725a21e4e4
-
-# DIGEST: 9bc71f6083d602ea43a5be27534283d8953578aa
-KEY: bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05
-AD: d8089850fea3711265
-CT: 974e2616553cc63db47fae22b0f0c8abf9ed4074aaac7eea99edc717df468fd648f78add94df01178a742bdaceeac4e72887ae5161db5bc1fbf192b24f79942425096be91cc3dca81f139cedbbfd97d56f429830ae2e5a6a3c9f563e3e0af5204859c4db7beca03f2b1e958c81de8233b5a96e32483b63a0c0dd62b9381b2436479cdcbd67192f0e670f00b11d78adc333b5a25d165c563b6c1630e93212ef4cfd86d7cdf0ef66df65406dd0229b6281c0b0f6f622f0d99010cc5217c37dd11405788fbb6ab468df3cfef4fbd9f34b77030b1a851ebd1c0550f2aff2434985e9c0b400025ed9862e25b00d0b37e6f1180edf35169b9e0a4c29eb76eebbddd745e019665a0f59a95dd8ac9d31cff2f1e89dfbaf283a31265b881b51eb8f0d044fdcc58152487cbde662e658cd1fa7db0a5b77a2669db089a760f6c1fd22af5168c83fa088b4dd67566caa38189f7d966797c17ab8e03220f16a9f2e3fd0d445c4431bd088f2a2f611d8746705bc68e9b22718677e51e0c855965b59e2eea24b2c08a4bf553f73096a3e716ce96498af8b53e3928e1646e87b2e0eb4ade54da82919d22e5a479592321752524b556dafd165b3760cfddde22e92f578045b76c0b8bb72
-TAG: a51897e4134937cade90d95a443ff1814823c7ea
-
-# DIGEST: c39bd34f093d3b18f254e8a94d2afd8f70eb4d75
-KEY: 0bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fe
-AD: a3711265bf78261046
-CT: a71a8c31a0b21b0e3d9c498527a08781e0003ed488bd067cafc7629f3d33ebf703bd4988404d650fca6af15d3639d1e0c4c6bbc3f2b1de89615b0ad4f5b2825080ff8a65e742870e25ad5e91e7f73e4aa6df970c3752b8c83c0c7f348719ac2423b699a921687d8ee53ffdc54dfb87c37e0d52f97593407f9ba590118a6f260515807633d24b3ac2843e9dede15eca8cc42a4c2fd52f6c6651cfe27feb66b1eaa843a6c955cc302bb85a4d1cfb4de9bc9e95a978cdd0170fb7eff65cfefef919bb5ed6788b1841d7e84df1e612e98d5b20ff69e0cd33e15d41802d69169cf50b71989071101b17ce865aa810fcc2f59307b54c3eb908107549551522da4f9f3966b4060822d5df9dbd30d3520308f6a11d6b9b2c6765894c76122ac5d1aebc11e077938a577e5c315d6a88230d17e74329d8a96007982f09882837e502d2c22420878b0ebcb8116330f906d03e471606221b44717dc3c721257171375c1fa24d7d90675870fceb227e558f025c9d4afd057ce5d0b3def8131d7bd5294713211b827f5bf2f6649ed279767a2ef75a9815775e47a49cb2f7f3006da71990995436cdd5dd5791184c35f77296f5dd36b495cec211ff2663791900ac1ba25e66249bf0f41600ffd991
-TAG: 67e16c8889d79079dbfdc1085c93fbaea962af2a
-
-# DIGEST: 630e1d99053b3cb7dc8c5c78dcb39fa7b0b53e74
-KEY: 2e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf
-AD: 782610460bfd24ba02
-CT: 1d4924289812fe49f47e1830f5c883ed2dccb9dbfa24c408544cadb79311a893ed1bdbfcd3c89dad26e831935afa86c60eabc909b108b1dc35f47fcfa59bca36a877fdf8c00a37171cd727b66a717f94417135255aac047b7a424bd94e265e503446f1ce8d8a540755a283ef9cd1146073e741c8d36d5541f788f7d016b3d8a7d413b072b99adf3301394a7859f3ae3ca94ae03fe13981f0917997916c0fd7e7c24793d97ff7b25ec3588ade4487980daa0064d6e95b49513fb5a9d2b02bfb894d6f7cb3b07382348b9ffbd525553af3af9c9fdbfa3ec3b7a82a3fc290a6a262381f29f32dbbcdbcf8de8d7ad8d7329babb40d4daf2e63a87b79c37c1da0afe81dcca690076e6794ccef06a6e4fd7e6749f3ee5ff3f5a93b7d7814049a9a12f3732e5f77765552d5b0fb9b9308f0628cb22ad88af88416c3e9a09e153d8f4dad78cb5de99d20e186537d9ccc49eacaf5d8e466e9093094fae310e7fae9ede277f0051fd105ca7781707dba15fb6be3bbeea419ac82cec825785031dbc09318883d8df0e330de6193fe1b93bf322fb499ff3fbf1210a08cf435747d4646572b3d83ca5ebe5b368f2bbbb2e391f702f049ab7991de28928496772e671fa232e1db5a68dbd768d25a348d7a96d4
-TAG: f84e2ea463e5b1889b8b4028200deb97fb7af5b3
-
-# DIGEST: 083d60536c78fbe909d2b35cd5b891be34f2a60a
-KEY: c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c479
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460b
-AD: fd24ba022e6da12dd4
-CT: d6c48de6968aa867c440f9a5a1c5a4938a9cca58350c72fc5f79787b1de75cb024da9c86d920b41f4972fde0001ddd45ad4b630dafba8ee91320d462c52e8f4223aa845c5498428673fa0b63e648561622022b2cef22fdfc04bd4db2e33c536179b4ffefe97302be847487104684e3012d4294b133d317b12405e36564108037f8f5682080c6dcb1280b21ac554fc84f3f4eeb1fb88e1b9b99f443b57f6f5aa712f2bb77e5e3232dc5252e376b0be57d5a82117c022b765bf92a533d362404e9b3a54d347adbfb75012097e4dfcd00d84ea40f8490dc90c01dde5595efe64e556fdabdd4359d13d95442012b828498fff1fbc100f8ab23e6c4fa4ac38e5c2b509f1ae04ca922e76d3aab5fcc1812331618e9484b19a7b6f849cfe4fa02f8b5ed47e74f99f9d14b4911013459ad353eb3b540da6d079d937745dceb6466865be2f0815d8bc45ce9c96b1dc6d892a8f1a76d37649283f72f25a5eea83e37bcc499b1a36a3f92a85f41ee8303a9798d2e83f80e929594370c679ec47beafe6a8be3a37b26bd572686bef6341f11515fd0aba7c149e918f564ec36a85975108ce4c7eb436456d07a2d01aa28462ec771be5ab3b98bd01cf661de1321a163870bdcdcd17bb532a4923a816e9b057cedf061374a
-TAG: 658be7b2bc87f3eb23b220e9534a67a79cb1738c
-
-# DIGEST: ba36e689ce5c9e3dbeba5ed1cb00b265c7b30d79
-KEY: 0974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e
-AD: 6da12dd4c27f437248
-CT: f32043386610dafbbd6264e61982044a071a0da0fbb1f62ecf56c9e61b126948c5821a79e288b6087caec4e5275ba85a13a1b16f409e8063d6cd871a6dc08bcfe7ecc6e4348dfb93d84a78d0e470199f135bee40495a8f1133856e9c003d8eb0024261b28415f7688cbbb156c2a8ecfb6fa95c1d5938f14f07b930accc67d689aa6a26c0ac6bb1af26ddbd7a62db89c0a04e895eee446a0c628468f1e9089b0f7b3bfa7c0d1ee83321be25159bf910a17f6a71854b7bdfe75a3fbec68dc2e3d9f245dc0380a0b3500a9811b34973bcd06cde0cc7ecee4e13e3195a936b5fdba5dc5c97937846d50462808f130f2b650f422ad4a387c2ce227e3017a02ea15579a8a0ce0780d37e1f2066a23c949b308263b48c1a19d488ad044a442bbc9b93ef9df3ed4d9917ff18a7a406f4178a2e9e678aaa9eb50a25fca1fc5c8e378b4325b2c679ca21a3c6914c8a34ef4b385cfd7c8856aadf01bac7bc8028cd0498cb1d3eb530b1c850d54209fa966f2f9c6034d74245e5cdc418c1eb3d033bcb50a5e6e1e70f6f7851f4e1f318f415f0c88978d0e3804599c313cd265c5a78862646f60230e2299063d05bd5c1876ea1cea6003f4076a44bea1802d809aa46cf06ed1589a2b8895164fae541028540f58eeeeb6c576dd17ae5
-TAG: 844f42a38aa2349436a963585d1f3ceda5e292fc
-
-# DIGEST: 2f9b29467c1e54888b4d4db41fe3a943887e305e
-KEY: c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c2
-AD: 7f4372480974454879
-CT: 5cfcf1ccbcb43cc75978cf33529d2a5f19b4989627689d76cdf25566794b9350ce781fdeb5fb73f74b368d95ef63c86a389d2be3da73ad211c5367fe0e2424fd3a3ee9ccd2b41ef9c0fe3f9ddfef362d8b8bb38a5017089a84a0374e223eff98a3731f5f80b65758abcee2ec0a1ca548b005dc3f46a466c3c5baa98b74b01bdd5b7cc8931d86966460643b00ac449b546b0e8b839db61bd14c84ed0c6f903f9b2f2fd2c12465a40f4f644ac5782660b7340426721091e0d381442f22c244ba2d40908b354d073df6e9538a091f913086abd37a96c0126801160dff8f07355b9694fefb607e61047c759987f6193927db881b148c12bc85edc15ce7fd18c2a014210f7111b189119191f77f9295b9196d916f2c69da24f663758c862b7aa30cba62dafdd552d2f52b2b93abd3d286d60aff3c25ac1daf64c3442702b8b90db1a885a61daa70aca37024a18a8ad96da2ed5da3e1eb5b646ed3cb944d013dedecabdafda61e6dd3c8489281b6cae0cbb4b55e07f313e042da0a85c8cf6b36a2846ef64ad78db421d8e13f2a6f7b9a147b90365a8c3e6c45daafeef365d7bc3025607805cfe23238984dd4f39cf62c94d96294aeed613df8dd37bf9177be07fb06eb970dca0af147340c1c91f3cf4843f88a05bc623fda579ae60f2410
-TAG: 39ffe4d34319d26a148016a265e1f986af7c1c70
-
-# DIGEST: 070f23e02cb53f55b0127fd3fddbab83e5682275
-KEY: 98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f43724809
-AD: 74454879c41de9ac9f
-CT: 4f225391be3a9d473c4352a23d0030f42ac43c43d645f265404a3b53735135a5e2164a47a483be3d24a5ee51d2c0d216e7d816cf7f8fe094efbf4b4966de2395c645c70191273a57bfde17277173573af90d60fbc8b6161be2a9af5d5a99042c7f15cd00c93f6b9b79521aacfc16ee2b28f05427d23ea82cc1cf9bdc3914e3c140c926275cb339f7d5f53c8528dfc4e7bbcddf4c2c82b97f1503454bb2e18f1249bdf4f4d8d42aa07f8c9fe037f1c8ab7c0ba3dbb3c6d007ff3ac04c6fae18afdd81660f5f2aeb5975527f88063cf4838f7d8b14589982af68fa03f1b8631a7b36c7d20e24f9757071ad1acd43042af10ebbec26c755014b7aa5c5d8c90e7da1afed24a88ed1c2e1c6bbc4ed1e4ebd57d504785b0d9a651ef03b7760b6966f9029cfbd534810b31bfa5ee93b046d2c25c76e2a4c4ce4cda06c267e8662fb53aaf70cb86f551f08c06df577038144213afe38cf30878eb9f783f902e2776abe8e1e5ea1edcf193dce8521896e010cc715f8e3693e3ba1d5e6828b1f4ddbed6901c288b6ad25c8f34c030a03dd09dbde9d14c24b86a7686d8064d9ca0ec85390b70247a006501c2676a7a1eebf77111a401e0c15fc6b4aff8c4ce07c3a57326f4bf86dc553a4cb7383920e1a5ded368a310ff539945a6df6f821437781cc28057f
-TAG: c57eab12df6e5913fb17bce528343ad3641ce02f
-
-# DIGEST: a09f0450fec556fbb3a1f869c9780c3d12547311
-KEY: 79a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c4
-AD: 1de9ac9f98233b5a73
-CT: 7af1b83f0f7b4da19cec10c42cedab801abf8fa47ff79ff89fd5c0221e13a6c3f0f9e8d9102cc7a60fa3c623610fa3d1431d0fe1290ace2834df15d06826910aa9683687d199f12dd0980aef4f071d850836ff35f0e21416185fc30be28bb4bc8f51a269b3eedfb8d1b326308cfbb1a302076ca973d99427aaf1908d1d722fe30c4f1f700f05312af5d7637bc711f0581a7946303606907f72993e070024f28ff1339dc35116434e4cd03f2f240c15da8743807c26aa6058aade9c9e745ce33bbe2d062304a6637b81594a5b3266042c702342c6f157e1e0fad1262b9ad54db5ddcc00e5feba6828de39cb4b62f018a98ec52896f048a67bb6c89a8e08949b403447b96e344e852024248e13518db2a0bb3694f2821d4c50c6133032fe09143918f027f3ac0e327dbcd8b295e47167d778892040739e5f146a6ac9a33fd9c473b0ff0aeb2ac0d0b6dba6e76616cb59cb4f6ade7e49f3eb6aa5a16b5c0dd239085bdbc508abbbe9869d3a294b39bc751a00a16a8e51d2dce28f6f79e6db8a495d599c0998e28e6a4d9023d55721c5caedf347eaf3427df44af986cd2f084a493cc3663f8e198e69e6d8406e1dfb09d773538368e6b9a7d25521f093dd26899b506b3b4f3b0733767a0c8b837c775eff70d898c9a375cf4926969b71fde64650bb49904af371
-TAG: 53bc310ad159b5e75d0d2f2ecd9ad39c6c80d339
-
-# DIGEST: 32559b69ebdbf4f1fe7c6e5ada9a4117836eaf4e
-KEY: 0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98
-AD: 233b5a7379a561792c
-CT: 26f98bd16beca4414e16786a03d9c4fdcd3a12be33e3c9c65c71ac98e0cf47a8cb1c3e121be3821e79afbdb0c5751650a7aab90dd75d817628201bfec19c093977d00f5796248c6417fc81f72a2c967a6f3a8201907729997d962483a99642f7b01b5c3cea1fc3384e60224308bad9418bb1f1533451fbecb40031023628a7f1212eac41bbbf065f84af902d02938d0734d91bb2ecd638672c87f06a6a80f51cec5dd3ffd7ebf7ed134b2aad2afa6d3c3a99cf8be4072115cf56b60e664c166590f0a5623f405a4ad54f713a9da2dbdef5b6e3e4ad077f88f20272f0a33a3b74b447d7fd9a1c3fb76b302da10338f8f013804082ce50a31a092683cda694435731aa7f7085f6917a02bf1f18414539bc5c76a4a3ccf96bb385f76f4e739e1b3d7de83d6447821c4a456fb6864d2daae77481363b44cddb3e302b8ee6f508b0ac64b7b5b1dd6a1b937e4c2d0e69a6299b3ad7b1cf05b66a6ee60f4c5c097ec252dd01a0f41f2e3fda2f443b38f19926d6a66a3c270bbe39206cf734c04a69f600ef7ac92be34c337ae65ce8e23fa5784a85f051a7b54ec2231f002e5a38542490331d093f4a2a73c3f493b5626b0ea801bcea5a128c9f4da1150e55bb54f59e28d8ab07e7b2d12d4aca84f8c87594524e66e12c8e4760ac0647ff3ded86cdf75931208a0e3710acd89d14
-TAG: e0f3c733d714646b10f7500ee599efc28cd8d12a
-
-# DIGEST: bcdc01526c7b0248abf3a41ac893bb72adf422eb
-KEY: 8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379
-AD: a561792c0f3116430e
-CT: 0b3dbb6131ff771ed17b16770b0ca1bd24eb73b1a9dc26ea85e65dd02a6a5182887b58eeacc427c458fa990977fa6aa43e1739e026df75b59422f52281aa105951525f162050b530b9e1f24f61cd408858df473a7624fa2f1732b5c209d0a8973e7c95a6e9df40843a1a9d7f660636610bc84eb884990dffe7e6c5ce7e736f2af55d52c4b5a1475ad4b041a367c7c2ae2b4c9f4014ce4d16d7d0d3f28b5a7159dd7171122af72b14a520611e93e1ad6594c91626a8626bdd2bce1a85a5f314cd0d00f52aac6ea496e146b0e710952e1af5bfe61529b6c8a28f98f36445e3a74fab40f86c11f0507b9aaac6672a86fe709e155341a9f020c14ae6e68b5303dd48c6a82ddbb8937efc4e3dacba99f404b9851d3e8dfede32c2bc866ce0f1381f9448b12b4867b0ea1359f0e9daad9b79dc52eff5aa7e7d3cc383db74121520677cf4f9ac213daf5fa739b3c362cda1ecaf102646b247585b034fb10e8b650af63243f8210c559daeea3c3afb9ba153c257104ea88c0d1561adf58c717bc8bed2a11c4d6617e66315cf4c5c13a7cd6ee01347f1a7ba587e00c48bba6d58acee96429f28d29306f73d03bc540145dfbc2815658a13e3db5432fe4f451c89e3c1096f946b13ec62c5c1a3dc7537c0b320c70315070147d7f249514f2b4566681e3154bbb56e0fbb86910e7837bf6063a6e0
-TAG: 4c24b2c14225f725cdf3c966d6dc18ac9ade0ee0
-
diff --git a/src/crypto/cipher/test/rc4_sha1_tls_tests.txt b/src/crypto/cipher/test/rc4_sha1_tls_tests.txt
deleted file mode 100644
index fd80f2b..0000000
--- a/src/crypto/cipher/test/rc4_sha1_tls_tests.txt
+++ /dev/null
@@ -1,808 +0,0 @@
-# Generated by
-#   go run make_legacy_aead_tests.go -cipher rc4 -mac sha1
-#
-# Note: aead_test's input format splits the ciphertext and tag positions of the sealed
-# input. But these legacy AEADs are MAC-then-encrypt and may include padding, so this
-# split isn't meaningful. The unencrypted MAC is included in the 'DIGEST' tag above
-# each test case.
-
-# DIGEST: f0f82752a691ef5866413f2b2e5c1d0ebb41ccc8
-KEY: 7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4
-NONCE: 
-IN: 
-AD: 936a91d0b5d2c0267218cb
-CT: 
-TAG: 4a25572381795f1cfd98dc51990437b4a7bad2d3
-
-# DIGEST: 7f3a0e20bde700d3c5596909282e5c3e764c99e7
-KEY: 86d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8
-NONCE: 
-IN: 936a91d0b5
-AD: d2c0267218cb7090c61713
-CT: 7a81a0da3c
-TAG: 4f919beb63c93776b9b7bc50854e199a6ef44c46
-
-# DIGEST: 5b32faa93c18842b5cb7b075270438756d5f7dd2
-KEY: 97b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503
-NONCE: 
-IN: 936a91d0b5d2c0267218
-AD: cb7090c6171386d641b877
-CT: b9b803f120257091144b
-TAG: 1d38f5c6bc60f8029e3c0de2bf26f75a1f043fca
-
-# DIGEST: 995a0f9b029aba3e0a3205364628bb76baccbf45
-KEY: 56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c617
-AD: 1386d641b87797b684e0fb
-CT: f9bcc75773ebeb7c04ee92e6ea5bd3
-TAG: b65aae98856e1ae9532ec51a74da99c8ed3bc305
-
-# DIGEST: 023d08d5e5af3e0b016103c7c3cfd1d02577888e
-KEY: d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd677
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b8
-AD: 7797b684e0fb56f97c3961
-CT: c287f1b6c5df7eccaa8784dd13261a80c32a498c
-TAG: c935f5958dabeceb4a7c5b938c96e8e9e092fcd6
-
-# DIGEST: ad4b11a43bb47aec3e91209f98f99839dfa1d6f6
-KEY: a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0
-AD: fb56f97c3961d8afa22993
-CT: b4ebc7ceace83ce72af3ae7bacd7aa244cef66ee260e67e19d
-TAG: 3831e1c2bfc15719a10fa549bb71b878d14b6f25
-
-# DIGEST: 580641286aa43bcef85be190e1967f627713bc64
-KEY: 89c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e03744
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c39
-AD: 61d8afa22993a340b9b3c5
-CT: 205e1cb68ac5405308020d4ffd33f8fb64feadddc41ded3f004f8d95ac1a
-TAG: 21c3f69b9e0047ece616d7514545f83e4a2b296f
-
-# DIGEST: abb06965675631a07f380e80a05cff36c2d42ecb
-KEY: f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77d
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa229
-AD: 93a340b9b3c589c7481df3
-CT: 5aa602faea775f241e8fa18773fc5ffdd33bbd948e1dbdcb3f11dfe140594e0c997aa4
-TAG: 169eaa5183d8b27ca529503deb4c53b5a0ce0d8b
-
-# DIGEST: c6a1ebefd827cde32df1d38379ee4bb6a7f81267
-KEY: d8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed8293
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3
-AD: c589c7481df3f4183aa23f
-CT: 81eaefd64602a8b482fc03a21c96c64f682d9d28206daa9af4e7f2a53f4835ce733467f38b79be66
-TAG: 6aeae471674201d6c951b519ee6119f85d6b6db9
-
-# DIGEST: 77fcb5875838a28d24c4b6bd0916ebd827968073
-KEY: 03f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc5
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481d
-AD: f3f4183aa23fd8d7efd885
-CT: 3fd49ccc28eeddd198569a5e4a00c33d09edae39f5fe4924fe5b5c248ee2b02e874934db9bc3324e6ee8982423
-TAG: e48dc9b4d7f7a8a941db23c9d958cd94bd237560
-
-# DIGEST: ff3c91da880d2942bbc51adafaebcf4c6fd50603
-KEY: c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aa
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa2
-AD: 3fd8d7efd88503f78b8ed1
-CT: bbdb54a6b0665c5e116298b84cc79436b99d968d9431f658cb56835b1e4b5e486a196c3937f1d0f51cd3ddd482e2db8361c8
-TAG: f3a15e61df207b75caf6f0d49cc6642a7dbe399e
-
-# DIGEST: 8c439bfcfb896bd106f94676b5626f2bc624c313
-KEY: 773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd8
-AD: 8503f78b8ed1c8e9ba2fd6
-CT: 8cacec10e7af223a3d90227d763a548b54f6848293815d8e7fead6fbbd6fe6fb5afd5f2e8b4fb553001c4e17378dc3b50f61b85c25a4e7
-TAG: 1480dc16dc2ee806cf1cb7c585712e8d23ca8421
-
-# DIGEST: 35d9dfb89c1883210f03050da3166b6d13f5b8db
-KEY: 2a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371e
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8e
-AD: d1c8e9ba2fd6773e0d0c30
-CT: b40d09b38f18061f9ddfa062df4e077d4cb9fa04e837cfc214a38d771c1a2385c5dc08820cd006b4da7168dab11af2c41ad67d87ba16c8f2a65a4057
-TAG: 3e6f3d1f13d37a1bcf2106a0b72484ad3b1b4cd8
-
-# DIGEST: a07054c760cc66fc704edf950201005031f3faac
-KEY: 446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac99
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2f
-AD: d6773e0d0c302a5f47e037
-CT: 07cdbc2ee6594752bcf8f66fd4a1e0e8f04a9117264787f8a4f7ad27055c78956975bc572fcdccc190ae4429b7638f0f2719026197af13699df20019251116b84c
-TAG: 773725bc58bdc2b6c10669f65731e378993212d5
-
-# DIGEST: 63efe7af502231420ed5aecce9a28446b257828d
-KEY: 7df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c
-AD: 302a5f47e037446f5891d7
-CT: 22cd54d388c7d34cde365709dc2f357c76f131c41ad36a0fac1ea6f4d30f4bf6c556ca7bd98677c245cc7a636d43827c2676ebeaff0606e7757e8419328f70b813fb7d76fd23
-TAG: 43b833799237d4006bc4a03e05117e6f449bf8cf
-
-# DIGEST: e8e41988fad6c8b44c56544964cfe0a347b35b1e
-KEY: 933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e0
-AD: 37446f5891d77df660ed82
-CT: d7e4ff3604a61c3f8a22c6a3223c18ddb5caace28aa0bdcfaee64595dce7d3d7e41d2eb150c732115aa8845cd252b57ff86ec20b651723bba7ba235837a884357f9de26643c9f273652018
-TAG: cdc49592235a3783efea4125d8fc17e2ca4beee0
-
-# DIGEST: 172f4992e692a88f49628e5d3937959be01aed2e
-KEY: c55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11b
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891
-AD: d77df660ed82933f62be8d
-CT: 1e7776c5ebe458c070344e94ba4e4fd476a00b3c9361691df365b280b6f1143fdc8e80794696c3ca1cc53152c5d1c58b4253b8c5cf4b0d2a8cb5016e7d99333321c4938257a8452a2ae5ed56aac4b6ff
-TAG: e0dd54ff80a71a27b972466826474bee791f13b9
-
-# DIGEST: a35fc7d25f90dd9cbd35910d5532aca8aba88b29
-KEY: aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed
-AD: 82933f62be8dc55b436965
-CT: 25330f9bda1ec06eba08deff82afe69247ebceae24130a7f4c900b365d064d195726feba02dac16fe3450e346ed21201fcd824bb1c4ec7f6845d48d8c6c138e912b5b30a7a1ff7640229909d6b4df939366d3ee516
-TAG: 3e71a5168d3cc7b29a96d87791c1afb2ab1cef4e
-
-# DIGEST: 4abaa8453e8cfdefd918571a961d8351754ad5b4
-KEY: dd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fa
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be
-AD: 8dc55b436965aabe477e0c
-CT: 747485302cade88f45098a5bcba428d7b9ce893f72194d2b8738d5ffa8397626a08cf9ea8542cba682cd5cdcb32022d7ab622f807fedd3fe16e852ec7f081cd3f14f364fd869e2bf556a25e0f7e205832d9c2996fa9ca8220f54
-TAG: cc65b494fca8f21cfa2aa7d1232a9f412920efc1
-
-# DIGEST: b51001b6ff9d27bccf3103a4961280e0a1406257
-KEY: 1eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b4369
-AD: 65aabe477e0cdd46be9937
-CT: 571d8eda38bee06d5217a01d64ae1b8d4a7cf03e95b66cc79e0923c6f8f14964666b63f8683cf381957dfa923c666e1a72e54123280b063d90365973184d7397ee343e24ba80ac6efc30eb9f118e6abef7cd5cc22effaf869ef2f660d26762
-TAG: e756093d90e2871ea7c208ad5b16b479bed23894
-
-# DIGEST: ad2b43eee27e6267d8c5c1c3d558a07dcd6b1f5f
-KEY: 997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce99
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e
-AD: 0cdd46be99371eb8da7dac
-CT: 89f3ea9a3a62ef92d33a9567d371233414e8102d6e9bfc8b2c1cab922290de1d3f28e0fa8c34058b73be3ea25c4846a1f2406473fac7f7207e838fe98055afa10dd1b379f50eba19f9886935d25dfcc221f9d08385c4ac19a7306363c246eecda1be94da
-TAG: af2d6a54de4a9aa05defb56dffbebc9ca1f6094d
-
-# DIGEST: 7b17b7cb19107af8fc4671420e461060e2ef3e61
-KEY: b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99
-AD: 371eb8da7dac997deafd64
-CT: e2c3cddae16d8113917edf7a26ad79a70c08878fa1e6df5799c062ba7f00f8d2e7fe393da949e85406ae5631ca4386f5a338b71035eab1145a545eae88e7731dcf5f1549a22dc976605253f4166615d97e330f776b4a226e6ddbc2f61b7c0908226c2d3b5a5b9de3fc
-TAG: 6894925d22dc099b341a42d40f624bd48eb0c228
-
-# DIGEST: a27799fc2e00e7abec4c5939451a834c4606cf7a
-KEY: f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7d
-AD: ac997deafd64b1fc65de39
-CT: 6cc34fabc39283fed27a10a55e1f803bebcb733a74e6cf2b20e9e48124db96d98b1a85afa02f8f83533f98ee9f50f7a8c71233c82d0835c1384b757f3f60eb89806b72f614baed813a08f7812f953ce5c71cd28ef8d2ef0d0b01444742071005fe8cd0e1fb2264acfd30c2c63620
-TAG: f51769be1a133d7a9b9dc38e1f9932bebd15ed8e
-
-# DIGEST: 7c52593d1d37b0dc380297231c6cb7b64e04c493
-KEY: 1be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd
-AD: 64b1fc65de39f4f03541a1
-CT: 63d9e6661c65dc695188835467546d4cabb554d463367ef93ee405e6b8cb8c011ead72dcbc82459ad29e599143a6956cffe752b6dd54ae1cd713f415af600ae5e0ac1d1104aad7d25f369e1c85772b1cbde454c4913604b085fdfee187484bf01efd2077913c05ea12acd1d5c0981df00d9b4d
-TAG: 4a5ba0aefdcc619d8a503695d4c8d37d9c862553
-
-# DIGEST: ac6871d354eac507556770d8b6bf10b5240273ed
-KEY: 33c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de
-AD: 39f4f03541a11be112a729
-CT: 88c4f7db02287ba3a42cc28daf6761029bb10269c7a044a3131413f086a5341171785bdd59fc8aa3d27792e41d8085e6b3ad0423c0e8e9dc00399e3bf9040d1752e43d779da4920630107c49aca16db509a1521c5ec4e8dc6d73770dbe9954fe92a5b1901cc5753d7a422db6a1f894d16bcb160b3c33a7bf
-TAG: 48547e6b59f847dafab7e038db21ecaf2c3f5400
-
-# DIGEST: 4f498d0aa9205160827626ef80c163275eca1f78
-KEY: fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f256
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541
-AD: a11be112a72933c7b54ed4
-CT: ce154bb6481d413b39e440540e5e5ba2b98d839ef6469054f9a60b33feb95acdb9a5573d6348e3f0f9eb765b005fd5625dab15a8d34c0fe8d51ec3e160ee1e71ec21b2f463add443234f0a786f0cfd60a67a8ce81a6a2ac608f70260598c636190269b5bb95ffd6f499069e9eb23153db27c0882389ae7ae4f4f85a178
-TAG: 193ce6c16238c5049df7811386f80427e49c2c75
-
-# DIGEST: f0901e8b8083c39222fc940384eb73cb96b22892
-KEY: 41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033f
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a7
-AD: 2933c7b54ed4fad0be905d
-CT: 740d1f16d5ea65f0222ee191a77b0b12b6468631d4e2283115dcbbbce2a31ee113d751c3b02197e35a0f8a208e067cc7b5d7f1859fd6fe1d1466d3ac6044fcfad074722ca08df66cdff5b26b716a724ba76e9c948ff47258ed6e80ae68689334c4205e7ee8f0aaff136b457889d0a64fa32a7f90a3c8e40d7d2060c2c0b484328a2c
-TAG: f41e458ac8ae3ea367deecad504f102365a1b82a
-
-# DIGEST: 7af193cdcc8d7f17b55447a81eef3dfdf345bba8
-KEY: 998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54e
-AD: d4fad0be905d41203f5dce
-CT: cc0b4d97e3e121915bf753affb1fba6bd629cddbd4bbafa274ff033dc9a7af54cf891a5a57b7624c440b4361efc88fe8f3d1e5d32eaeccfcd37bd51c33c99e490399fe27790c1a72d75e15b584d2c529b5ed4a6f9763895433d2230acd9fa3f7d911d6b411fba49887a5cb519cab9ba77e0e94c5f4ef69ca52e22a13273c103ed7d71703310d37
-TAG: 46b5e4512f710809f32fffccb2945cba5cf2c24d
-
-# DIGEST: 4ecf44faa266de0904b093653c4d623a543d12d8
-KEY: ad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e78
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be90
-AD: 5d41203f5dce998f8fb2ea
-CT: c7bc10d0960fa1ccca680829527650427431f4d44d22eba3346cc9e42e6f6707d0fde032ca156095289270da8ae0c2eee27d9f3533a54d2338c57689d78eacaac2349f00b240de54e29120b3e6c1c0832cc8f93eeecacae3e23a2a0732cbbccdf466b1067017890b48a5f2bf14be75f86544ddcce0e85c8a8a5b2648709f016a20ea2a8751b2fdfa8c9e73f7
-TAG: 43ccdebc5977c71f203099bef5a4c3f9b4f0d1d6
-
-# DIGEST: 92a938017497e0762115325c40b5f7c138d5c6f6
-KEY: 16417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b70043
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5d
-AD: ce998f8fb2eaad409ae021
-CT: 8fb543fefa444fd4d3a1e45f8ad7b53c3e2ba0173472726eb51beaca6b9e999d36b1c8ee9f371f171f8a30a660a7e6b56e71a1a2ad3e435eda139d3ccb423ea9eeaa43a4e410c544c400083b414c870429d5828095374e4537a498a4c0f3337147254704342b7498f617c65e334c752ac74a1fdd24673bd7475395b680ff7d98074da33deb89d2e0ea3246be69be50abc9
-TAG: 37c95a199572bc7041baf730f254e59ca3d6c81a
-
-# DIGEST: 6b126413a7bac1069cbb5b338c158463a242d607
-KEY: ef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2
-AD: eaad409ae02116417dae0c
-CT: bb11378d80cae9b1e88be6a20c1a447209fe307972c2cfcd615fd277617ee2bd75b3bfc06e792ed584abc3d220a13f91db258a8b86a2622975888170648bc511465e4844e75792cb617a850d61b913a355d7d487cc3b64dff39e8cad19bda78e3179428fd87f88575b3676e452e00a497546fc56560fe4e91ae5eb366cd9798ab583bf9f6d0237340f114dcf602284f8c5050a15c571
-TAG: 07d3bcf76f73402f7f33d098fc47bb1ed7a19645
-
-# DIGEST: c72d214b42ed66ae0822fa9f3bda306c7d58cf80
-KEY: 16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b02
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae0
-AD: 2116417dae0cef457b9e5e
-CT: 453c1a83249343b90d28b8b69bd1e63e94a01863ab0fb68fd8a63bea261088477edad3c9eda06e1d2b9b5149027fd9345d1e77079d1f95cac60eb3563ef4849dbf7012eb1617ad5bcc284dfd3fcec2927b3c07cfdf406a8109746e01fe23a2ceafb70bee955e9aa8a567e81be3c954840cedc4aca07a530cbc7a87757aac5c0e273f4ec1ecad124ae0402336c7e2b45a36be9195398e59bac0dae4
-TAG: 74594c333141277f04fcaf83687e1fa0cd753ffa
-
-# DIGEST: 9faaa58dd34a192550c3519f8c0aeb2ff48dd388
-KEY: 5607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769d
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae
-AD: 0cef457b9e5e16dcc5b6f2
-CT: a770211790010d9c8ac978027a81a1764b96acc7593a0bd8af8a9cb820e7f54176ba5737836858bfcbd72937a6f0956c58126b44ac7e15f22a5cd8ce890b07d7b6cd60e9ec897fe3d3730f4c94b5d952651f2cf69b00133167a8fe808c72587d3ac024bc8dfc238cda08fc2ccc5043f9b4265dc6092626bae91485f6c0c39598c0fe4c42e05b6985f48e00c390efb02fa30cf5ca24b04e1102d51869d05af8f0
-TAG: e35e82e27da42c6d002771274fd83bf434e3515f
-
-# DIGEST: dd5e6be3644dcc888cc50c0b2ad0d55eb0407fdc
-KEY: 3fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e
-AD: 5e16dcc5b6f25607f00d03
-CT: 88ffd8e1134afc00f36c06288548ffa40a63a5484094527d8bc390422385ccc1455b6bec72741c1de0d9c9ce3f7100114b4a6f3eeb55efb70d88dbd8976d85774099f5447c03cb8adfce723274211f6877c23d2da345cdbc6cb113fc89b1aab4cc8f3a71713acf4d6cd95d924bfee73caec80c51e99fd30e33068a9985d9ee5ba0359e3537a366d3dfd7d6f76dc770e42dcb429a503a48ae359326286b9f6bca252e23a0d4
-TAG: 10c3c2f10e79c92c0e2b5a7f68127b867309439a
-
-# DIGEST: 1b8b627e1020d71318511d4c2078eed315ee0b04
-KEY: 4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b51106
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6
-AD: f25607f00d033fb95fb09e
-CT: 005bbe3c706831c234edb017b22399e158be7cf84689a9650f2cfa6415109fe37817e2a65332846f115c6be8b6d34d9950b254b31921182d084a602850db9d93d0102acda99504fc832a2dde26406e1876c242df7d01fa54a197dee3e933aeb5006e597f198bbd81bacd91abd90dcedbc878f713c3a833b3ecf296261a71eba43b3919bfdfa0e621a0346a8ac6e9045b60481c66fec83b08d277b9966011720625dbe7a635dc407e0903
-TAG: 0bdabe2a3b1c9c1d1e486e11efa1eb07c541e22d
-
-# DIGEST: b7370237d402dbf76f1a431cdfbb37f41ef2ad4e
-KEY: 780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aac
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d
-AD: 033fb95fb09e4d00d6172e
-CT: a709eb37f13d3c77d0142da173f630f40f7d35363d4078af8e7a2d7599e6aeca8906fdbab714794b6096f039a4a123d27e229035f7e2d9877b0f06228f9fb13d3a3b0bc2370da097e34a1beef075c8656b2b0d3c9ff8ec6749ae97551a9e2ad686cbf00ccbf26463f393c74f4f942872e0888da4463fa4a6764925279d508b5cb5ea86774141ae75b54f06713d8b16f26064b9927756c421587e7b63c5a2c3343eaceb38bbf4a9daced65d0954f1b2
-TAG: 3256993e68c56e09d5c816768c0056232ce5699f
-
-# DIGEST: 0ad0e709e40cb2fd662020d420d97ae50a14adc2
-KEY: 433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184a
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb0
-AD: 9e4d00d6172e780ab8b700
-CT: b7a9ce07a6743b7ea2b09702c0b78865bdcb94b5407e0406791207885d65beee4d9cd319f02cc3649ebdf2917e009e628dcb5621adecaa0f5fcdfc3465ab4de9084eeec19e05d99f6e1f1d44ab68fc08c23d4856c53053a814c6ab59d06b99a34db9bdef3d447a705dc76168969f729b9339302c7a20286dfd55e0f9c9521bfdea22d179ae54ec9a8e9bd5a254519739b5165c817720fd80a4ede9d5b8a28ad05f7802b26dea2faf3346dddec09a3cf37bf5d54e
-TAG: 89c08dc0a31bb9762b75a6b8434bddf8f86b6def
-
-# DIGEST: 5f9967a8fba7184dd97dc7d5da22ea785e0ffbbf
-KEY: 1c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d617
-AD: 2e780ab8b700433a957a74
-CT: 1f24dd87a8fa17c78ced7190f7036b9ee09768840407787ee90bb1536a2bb51b55f7400484eaadd49b69263052986eb53786688241e0bf22f13b035bac824d3a9de4193d96ff40bc2b78f798a65e55aa0fd757687b1c665195ce7c1eba0b6f3fe3c446651eb8129f665241d1d94dbc5ba0972634ccb39a90c67a9b75acc23e640bdd2719045b9679430b05a3fa1e5d02e92110caa1d20e27ce9d4674f3bbd668de04f3747bf62b4d009f5c68f48ab0fca0d9c8f21e9d2ea773
-TAG: bde3deff0fc4f4fa7fae10062e04ddd52b5e6d1a
-
-# DIGEST: b5aedaae523d9d396ad1d9bb175bf4c7c0b03eb5
-KEY: 021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3f
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b7
-AD: 00433a957a741c9eb80f2b
-CT: 996f7e35ad967735a3f98a0032c77b9f9fbc36bfadbf4892fa77833eff98cdbfefe731522a08e9d2d5ffa8771da675c1b257b5d839e4aa8cdce6276c598cc1684b8e76f354477db5ff07ab9076dc32e1ab94a12a7a8adff47474e4186f10d57e167de8e56bd5a853cc764561ea276d12566a59994eed04f79db48524f92e1656754a2c145c5582874746dd8d14855676b3eff902d2dcadfdd79bfc84f9c6bb628d524ae818c2bb73e4101d1d0f33b65d997c68fd250571e7b52fe94dd5fa
-TAG: 03ed20e94c7fc6a0a6af3406870e65806b4e5ba3
-
-# DIGEST: 52bf12f5594b0cdefcf977c07626e8748cec5425
-KEY: 9da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72af
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a
-AD: 741c9eb80f2b021b144476
-CT: 0e066967cc5b14dabe619a6ff8aec1be75722c0ec656b9b22d3d6b0bfc861a2e3378df61038299f921681632f3a462b2bffc450f4b17906f790294f0b49cbca03d4ac9aa17bf25d97f3210d0c400067240cd2c703012ecda314864d6446582c505972eb872c362856d063ca224fd9108ce1fdb3a0570559ec802a221f4235bf5d42579089cee35cb79155f51856a4e2a12bf445183a558ce7a7325c6651b7defe486f066360f6e5c08fbaf8920c29279c86a9adb306ba4b21170d9c52e7d1d58ba5a89
-TAG: 15dd6051ac156b8b6bce69175764f5ab1b74b934
-
-# DIGEST: 900a1792a921b6a253c47013c9eaf01fc5c880c2
-KEY: 0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f4
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f
-AD: 2b021b1444769da00fcfab
-CT: 3b7a1cc6516105379e4dfd5b38f1e7481457ed388ba53e292ff3e24a6b5ce9a64a9505aab5c16d01083e30bff215375e1482ddb22bf0a7fd7bb8d62f4670cb514bf7efcdadc2a321f20d80aefc423a28942e928b7dc54ac997b960cbfc1182c9c085b36130b890d698dc49af682670ffb5faa34552ad85f7d646bee0a6937f2f3cbac3cee6ec55f0844fb7a9b66567b8e6d9df48133ca78150834f04d5b30df84591a5d26816d6c9d0e49b54403cb7bc6a7a5f2543df640ee3b1198aab9862d7b6aa51704da63cc3
-TAG: 059814e20636ac39bef8900e19e07fd6b0468309
-
-# DIGEST: 88d7ec35d88ff113703702955e931e802fb0d8b8
-KEY: 060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd2
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444
-AD: 769da00fcfab0f5f93b511
-CT: caf2c8350ecbe6b476bfbc4141c741106394965adbeaa09317502511d0512b20fdff8a160134a6987449bdea666bed33a068d4e1c75df4aa61d03f3231190a1196b27d81b37d0518326e75051f160d730ea3e957e93282cb9c351cee80c0bc842eeb8843114bf887f0747525c3adfc7020263e2bdefa56e6232de719647afeb61dee81ad76d00f59561213766d34fc4f6ae3946cf9f422aee42f9d7fa819b1f5a599824fa6bf230675dca2d95933de11ed7b8e20679faed82de39064cca50c542c269d6e94442ea3e2dd7c3299
-TAG: 52b86cf0afdc4611dac15b57334a5192e7db5f9c
-
-# DIGEST: 8d8493b55d9b74892e77d3b730588c087ca9b1e8
-KEY: acefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcf
-AD: ab0f5f93b511060c9c5f3a
-CT: 0896c2cf79cd8199adf4f91644cd96a1770d7ca3b0a92277816df280c6ec0522e04899c62758fef4f84d843c183f100506b69d0360ae054749b0b862bec23ef212dae0e8c17d2dfddf0a009ab6bf91539f1b0d0579ba8a53620b578dd6315fbc159f3249f1074a4a8a7203ed3238dc88ed8b6ac6d296edf422e2d9a2353de9671fba487129d8dd15ce39baa9c24040967a183cf61a6fd74b5f7f4852b3e3ab1e04c04692f16d0b035e0c999feab906e8600962a389e1a43136799a66d30c16e211d19582a62a941e8bf3acf80b291efee818
-TAG: 361201f6e711ac9a62f21dcabd1cf1be9f9c01a4
-
-# DIGEST: 4cd92ac16a807d2ff180df75c47d848749c7ef46
-KEY: 4ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c4
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b5
-AD: 11060c9c5f3aacefe61b18
-CT: 93f684f357e4763edb21343c7a9e17433653a1d6c2f2b5392b0a17408d3d1787cffede7d90bd4e3266c4797d90930ccd3f96077ddda39a32789eebe717e02133d44298b83bfee7f879292ab46b67cd8ecd24b25432d668a226c0f7f46ec07aef7e3fe5127610a6e5370b32fa8bf4949733ed0d920463c488684e4b76f4b015e7a7284ec8ffd52027e967dfe0fefd94345488880d5f8a606ed159b0124a6db32f34709876234fcac6b352d735522d03407cb93c2f878dfbcd543731b9a40703c23c065f5f1f39e776f32ce97fb1b4eba1e5cbc8364a5084
-TAG: b5139d51e5fd191c8ce3749401e730197cf435e6
-
-# DIGEST: 64ee218c0c96ca8e2d2e50cd809d61ee109baca6
-KEY: ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f
-AD: 3aacefe61b184ad2463939
-CT: 65ec3ab04f748c6b68ea0cedb1dced536de2f2b90103884299622ced112d15c52ee677fcf9fb364895b60546f408e4d95261a8cd9d08eefac283b62e118f2ade876a6c7864f9e9f3669b200e4a5a9bafea645302db3d8b5e280847b29ec9135a2a01ab607a694739fc47192eac87638156684c62e573da262b09db180ff8620746ea8679a33a10ab8863f89c31edf60dc5c35c14ab439bfc58ffe5731b596f87a80fa1982450428205983d9993639f34a40a08e7876f43eb8d3d2803dbb3a3dff8e92556bca311b9e6e80eda56e1f9ba9e4a8f3a7e14e3b1827d8426
-TAG: f8816855dcf65d14bc51da1771cbb76697587eca
-
-# DIGEST: eef8eae201ae4e5af32ee74bc724e13ae5ed3978
-KEY: 3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b
-AD: 184ad2463939ed518ce97c
-CT: c54f730fb867af4149390dc03d0ab5452e1bcb2c4ffd32cac435758f17ce8ac989e0b78f8018b96440e31d6de691d00e61ba3597a4a16b1bf0b5bcfd9fd03c005a4a6e3396f3f97bdbe9f5363a9a0657094da45729568334758ecccc045a33d0bdab9fea940b86079e58969234523c8a8612922ce7effac0d9a8c80835cd08bc420d9ffb166396f7438a98f2b93ce0bde77ba0666ae913ab0378df364147161f5d45709b8dacf469367fd737121908ba25f75e9877b9e1d31f6c5a766ccb39ae326822b984639367d07e46aa05ab23da9d06c2be11c789bcfdfba452453a6bd842
-TAG: 10e33999b4d7cca2ccacb6d4f114d8b5a4c9ce3a
-
-# DIGEST: 2fe67a81b41b094a708ae515e28bcbde3bed724c
-KEY: afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad24639
-AD: 39ed518ce97c3fdd293d72
-CT: 4290d591ab106835007456629b59e99bfca0ad0169f530fed727f65e6f25794ba8224a747aa5d6c94259e3cb803ce6e28d7c7ed79241fc76ed3e89d97e6344d84f437e30beb59fd6d5e1c3747b9ae83dc3d6493d46e10f8f6293f3e271268e55adaa74b7c00c5fd2d90c2e442181fa283923923f65a8a6e17172dacfc271a3cbae736b0202ce041b31647834ac1b0820d2d6ceebd800f3d6931fb5327d8141f319b07238ac9f186643b52a6cc7ad8a744f63b47fcd0f548417dd17b87423dc55d35be65a44a2525785e59e63266222bcf2695b4a04620f2452818085648aaa5526bb767af956
-TAG: 8a319ad6486ba6180e0c5cef4f0d7d81a5a401da
-
-# DIGEST: 33d10d6cb5dc80751d0f8e370925d7c86cda331c
-KEY: f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce9
-AD: 7c3fdd293d72afc09ffdd4
-CT: 9036f2648c270734fd19bc1c2fbfff99bb8321c3f125e0aca45c8315a9edc31ea1ec1ceb2b588e383f83de84a3ef9982b04a5b1640d3ee0948d93af822a478ecfb86b84abe1d91d8a134012e3aa750ee27b688aa689b818b775d99b2690d0165eb9213147618a925842f7261f336e49bb21eaf52644318296e64f864c981d4d817cda98d4bc0ac4b36f8f156ebbb162d963bceadb91cb02f300a2e34fca5dc41d80c9fe3c4afb980ec69bd00200bea8d666b430205366e0cf9649f125254a9b74b373ee11a4ce000052e4519c563636b32a1e4e65f5a68490633b4eab3ae221cf40d1f288163b9bfa3a40a
-TAG: a6b46380f845b752962b6f21f1713ef71c6c911b
-
-# DIGEST: a29f128842a48debb60699ae0df0da9a9b5e5dad
-KEY: d299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d
-AD: 72afc09ffdd4f41963249c
-CT: 677611097062667de3646779b59140faf94475426fe6a96f953facf6708433330a31aa35f95daf2539510b44a7660634233ebdb15699ddcd9c2c044c4bb2b636c356583111db64d2ce378e74558ac7fedd495b562b79f99052ea515826fdb0ea662d81e5297fce2a8695a2318c0e5b82049ba944f2ca733075fa5d985eb6634a25505acb4ba18965be92ec6366332b90607b9e1e2a30be112391b29ed0b54b61d8237b968ed070aa04a0dbc2e97c2581112e568da22a3f0f64c52267ea22f11fd8cedbfaf49e038224482f36aa6b19d872cc19ac1b90a820f1c72a1295bd551407a6cba1ad582c867bad6137d2ffb12a
-TAG: 2c229ff0bfe0bc88a7c831d99a30011ab9e7d686
-
-# DIGEST: b5048d1efa7564966b6cf1579cfb4ad8e9460660
-KEY: ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12f
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffd
-AD: d4f41963249cd299b92e55
-CT: 8a770020b63a9f2d220ccceed5562047763e86eb4047638515aed53940f46209f2ba84eae5d8f9081d4839dba2f01312f80496f8d6d4007e1656653a40c06e611b97fb4548fd9d623f926cbde44391ddd772a957c2815fe3d114ad092d535904f2a87811b8ed3a42e6667239b83e2c2f492a0eb8723e06e93bbdeed4ad5fde2e7da46d50b583a1f2dc35fac4cd40ec55f6dd38ee71051595599bb688eb3243c40da79789ea0fdbe82067cabc56fec3b812b0835aea441b9457024cf51035192c78e7cc391b565d5b837afd621c5b92a249a4dae614f09f15a87f59a35a7f67abc2e0aac6175f4f00e4d3cd9404a6655358f525053f
-TAG: 5eb88f26603397fa0c0af9806e441c219394665a
-
-# DIGEST: b6e68f5f0dfd8ceab56ebb657728c9bc5129fdf4
-KEY: c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f4196324
-AD: 9cd299b92e55ca24d8c078
-CT: e0c6e12e33364ee2a4ba0067af2c57fde404efb1753a0e47efec8eafe611cb56d8c535404bd334a48399b83f1c23931068cb3378ae1e8b435a535d1238704d8bef3d7a73f05090b88fdb028506e11b5c996d891a505ad173f1b8b761e19622420232a2a0ba983bb96c054d4f960f517e9526fcd7e67b395cd0eed2dd34e67ba69d821c6069d671dd352f089cb4bd3b604eb7868643bcfb5a065be1aa2800dde814ec5f9473fed6cf724a323326a7515f491788fe57ad08e6c3b2e207c555b6659c90925d4483f01d3ac8dc09d6da78f0e2f665c8b9bae0918578e1ec4479d4d9a4670e356a69290cea97254a91b9871e9c7996668f347a43f96a
-TAG: 8f89b656d406819c405dd8b8387a61bc3ba76c97
-
-# DIGEST: 853bc7b9fbd640cc0654fa5533ae302e398bab35
-KEY: 13710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e
-AD: 55ca24d8c078c49f78c7e7
-CT: 6a2e464c9d5b3e4053ee0deff66d8971e99d1d3cb02ed5d50c8fa5cb52f695b3a26b1dfb40ccbc881bc471958e8e68ad7a5576e1e4befd884ec6a3ca0f6510bf8db2e011ab53a8cb7d022d13755c11bc77b4c7f9f1fcadf2ff30054b72566f79316144f1fb1388848bae0637f5aa8c0e53751d9fc850cf78c280da0d65b468804fcc93c5837f00281bc40c3ce3d303d11fa2c0ceaa3a544553a9112cf5928cfbd82e96f3268e861a6ef8baf6f8e6a050f83a9e84c77f954069800e31e3aeebca1192b33f2c1fe380c1aff70a716059f12dba2ba4d780ad60c7f92f8d566625c2cc33550d92ec7e01130f887b8c78dea334c438a597df7f9bc98c0919749f97
-TAG: 6d1d94322ddab6739f34a05f10acfac396f15c2d
-
-# DIGEST: 286a92c480192206a2153df1b6d0eb26e6507da3
-KEY: b8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd35
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c0
-AD: 78c49f78c7e713710a025c
-CT: 3a57ab69b1db616a47f0dd7d0e8b9cc6ad0bffe66f32b49bc1a22970efef75f365fbadd4b6cb18dcef56e411ecb43b01e798fd233242531b89e7c393904c657fa4f665a6730ea34cc7b55355634284c95d27485a4dd71fa2e7e46d0f8b34373649b5d029b2fefdcbc19b6c4eab1b4c02ef993fbc2770368c3d53ab1bab44bd3f79cf418780fb6b158f9a9872c973ea7a4c2c75bdc6aae7924cc5c7f5f41b451fd8aa48fa88b5321ce3f65f599b50a17dbf7100bcb1faf4ba8319847119755cfed0e073d07f0f81884f816f3fec7cb75dee4005869da30b3875cc586e4525df3d9e33f3f41a66b6121d09c9bd4838e2df42e38eeee17af11e648a969f827e955d1f935e79
-TAG: b1c96886a636cec39ac6317e826fda1e8d4c0983
-
-# DIGEST: c2acb0c126af5282abe14058066631fd0c658571
-KEY: 89ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7
-AD: e713710a025cb8b9d71d29
-CT: 34c7ed85d85618f73c4af5e1b596966ad8bf5b4eb169363f5abdd788ee69a9a426cd3acd16610f2f291d3dfbfa487e56925d94043c8393c7ab0dd6105b4f0ce342d36a11be29687da84a64410d834a9c4de3367d9c5c68ba5dfad4774cfc0e54a0b8e1c666ea502b575264967115e5ce04899605745a1887f19f663cd83cdb09d43fc84c386c2714b63cf609c758188ad4f47765d5e98811ae3aa6e948d4bd79c7365370d5bd08dbb4bc56a7b779b321508d8e848a637040c44afff96b30b6ed16425a214360590ea02f32b01b710bbab9540e72d454a528980542c01b0afdcec168b6c51ee5c11cfeebf7563bcbfaeb02f95a5905d44e8a16b1c37225a56986bb1e3ca379655e8f85
-TAG: d53b9e3d13e0e5bd65683e82d22377bebd672bfc
-
-# DIGEST: 500e5f2a56bfafb2d93e26224c9c2df562589f23
-KEY: c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a02
-AD: 5cb8b9d71d2989ab33e978
-CT: 50b1b403b14560fe110cd027656bf3caa819dfc2716c55530d865e286ecccfa1af3074bac96d855eea05bcf031f20abb4237ba58dfa54adcb1060c1e736381855d225d95f2e50fe2eff0dcb5fa95cdd622cfd38ff26ca79e47c5434528cea3625268e88389339328b0480eb45b9d65e5cdefaa157530b74049edc75e21b7e25165abb7dd4dbc649be52fc685a0ee2fb5ff43850b441cbf181f7fca3702d5ae95dc0e1a620701b64a90a1202331020c547d4d4385327c05f019fd619ea0648059a7322cd25fbabbc06c17c402fa5efd9010651ef67af24e99b4bfd45971cc7a45ff415f30f61c7278c08dc3b9a4ec466b4c2769d119c6307312ed2f91edc433f73a75eba87f51d66d74b842d86976
-TAG: 35a58c0b953a4cd830903c7a72bf895118d68fa6
-
-# DIGEST: cfa6a42a2cc0ddf1c7b20031c95e331696bb9ece
-KEY: 85a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a747
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d
-AD: 2989ab33e978c4451e3be5
-CT: 6d6b66c1e66ceaa39d661c54b65d5fbca2bd1b03d9011e84a54bb60f205674e01ce1aee2aafd8073cceaf6dd5931ff4ee969f15224b328c100045ce9d964c169b14877154b202372e469df384ce3ebf777ea4fb808207566971d89f98d48605e8c510210db572fbd961e917e8d37f22617dfad556a5245756488014bc3fde63c3fa49b535f03ea5c9f7f717d29a53f9156f1f263e80382e18cc350579a1ae81a144047ad9f67f0556225c66af0fdb6908202c043b54aefbdb4bb17fe4b9fcac388e30c459e0905c9873656b3d0d79c4e836422bda6d9ba55009bbbafe6f9f8023a1a8d716d049c6c948fd9dea9900583c6f13ea5963715ea4fb6b6c0f979a2816b8046e152cd93bfd80981c24ac3d75d060da0
-TAG: 3bc2ccf3d7e14c316d6037d9505043b98ba20521
-
-# DIGEST: 2d1b27948de83e32a0fa5be7040d896824ac1fe9
-KEY: 2feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e9
-AD: 78c4451e3be585a29a2af1
-CT: 743450a5ca75c9170afde7b7dd6e56a64d945993175e929edcf2e8cae677953d9c663e96230c3ba6b507c93274d6b7ac37d96d9083f08c629a12be5b450764a34ecf4a6f84fa0cd4f63b121a8027bded2f9acd176c022e8340a98baacfa198af22f9b223887aa2eba03097e4168e1a4e3e90f25f4b90dc89429d3f5f6c853f456d8336b669a7b4e49e9b9ce63c082593aced7678b496d3fc907c3af703fdd4c0215a91f2cf16ae81fb4f045c6ff3dc856bd06dd833d4e824310400e45cd59eb6327261ee3fc694c3db79838d0232e2b9432e90ea0bde8a39a14c36d240128308ffe58471ae90f156928b6f3acffc83496304217de9093a34ddd22aa0cef94f0713151079bf41c12e43101108b55e8166460375af4dad155b
-TAG: abce5498e41fb9ad6ec25bcadffd93fe307e7a15
-
-# DIGEST: d35ac8b9ece76d43f1497ac8681c5077398bf2ac
-KEY: 63b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef16410
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3b
-AD: e585a29a2af12feef71e10
-CT: 718d77763ef30a884de7722f839c774904d9a82b4eae23412c877b69811af2129b9ab2858804f417600434709c1ee27442e56abb569eb546eb7df3df63e6a0839014a40c1773ef24e552bf96d9d85a67857a73b74996ede90121218cf221dc3d338ccbaa71102c36c1df7d4987ab27759724022d64b0891e87cb60c6ffbfd597b2112a0a24c7c9e235797b7ea636671d3523edb6714f1788c8d71e938226b7b1f2e1baec2e07d1d24895ee01f434cceaa63db35ae3c393ba78757b73b006d82fd4c78ff90795e18d6e78e24c2473a8421d7e3ad2b07057f31ce53e196f3f02d407f723dc855c72e15949c27184feccbc3bda47e4f50b7ee9f36a7e65f024cb5e0b975a493b9aedb9acfecf7ab60569c16675480dad2bdfb6107e0daeb3
-TAG: 659d537861e30a18f9f1214417e973afab90baaa
-
-# DIGEST: a3b33fa67f5c471a60a63dea915333550bf3af04
-KEY: 99200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f7
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2a
-AD: f12feef71e1063b0b4e6e8
-CT: ed8da42ea6b09c913196f5757c28f749ddd7a9e1404ae6caded36f3e093b107e01cf3b8fff8714dc2e780e6c33d0f07995d99f6eb70c8e36e08598fd0c11ad9992e5738c23a8825aafe57b3dc33a9bba2d2e7a9f563a773cd5a4888a8432902da2ea39cf3b4b1170032f78daec21e82413c55e8b0e660bb6cb5e4d23349249cc51d8620bf77936f72f7596674d1c2e1bf4faf5a2eb6055c981fa441cf8c982c50bc8c71b1339f9b1da8036fc794457fbdf6c410343135e02504be9d9e7674cdd925d0ad8f19b269af2f0d1f9e3a8c6d16df6c7d02874632fc56800659a1c82b2ff2f2a8a31ce81060864d6ffa94587fd10802dca0d4b355255dd357f04abb29cb7e351c781247fda8fcf878ea7323728b47987e3d193e1f1c08272cb569700a148b8
-TAG: b0d46e23a76083decd6cbcaae22db5657626e6ad
-
-# DIGEST: fc45f684acf19a1dcbf767f671396e793430d7fc
-KEY: 3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f52
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e
-AD: 1063b0b4e6e899200304bd
-CT: db65b42cf3242f4a7a40a335c790d85c8adb2a102fdda1939599f109c80c36403ca06cf4343dded58d1ba3b054a982414ebd2e22e3338c511227b3ee7113502aedb91befead70d9e6a3c9d0dad6b38197083d9828dddd8c6789c06ea44482d30eca889654d73bd2a20f0fb926961135058ea831d4662d677af227d404458b1b65bc328eaad4f60cb64e2ba4bd9032413be2fc5a993bdd35385b08b0077969d3949acac73b824756cfda03257cea0deb428cea88f7d63435674c16cb3da4f6a64a6ae1e98996a852e9e5815707ee6c375dd4dd7391242b9d32f144e754fc49487bd13d9b3cc1747006c24dccf344250da9a4a6d3f9b865d6c04ba17af89f47bc01aba92e266317e8433b13b759c2c9ab6f18a05a045e7c8d52632cf3f64d3f12b1adf5487fa36fd
-TAG: fccb6252f6f517e13de29c6bf7e8c32bd0cdb2b5
-
-# DIGEST: bea3f11679bacd98ddd996236dd603d319aafc6a
-KEY: 7d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6
-AD: e899200304bd3508132a02
-CT: 61b16df94f975683ecb519d3a8c2ce14b9d73a17ecf16fd46352278c34e4bd6aa0ca4199fa896de693dd866b259e244ae70e68911e94102e1d8488cb6f14acb6a35bbf3667813f3b050af05f2701bc372973111cfcffeb79e96eacd878e8e57363bb834e65e583a800431f6c29b823ca720626d2a33f6f19e936b5d1479349735e072cfdd57129bdb0d676ecf12596b3b196f169b268b747ee66222a0d452f070edd7563fdd398a0a83610117d130b01262d86162055eab3cf0afa187484669804137e84ee21d253fd6ee672ce685ff607d928c59a70c787fe0f30bc574ad30dbc88a354b7a6e828903820d60068fb3b062b054a6bb0dedb738bb7dc5a69e51a1d36d6e0eeb43c035397a44bfaf5c53b7fd90722f75c55020346ba56f73c973f4d3ef24b2d746482e4ab0620
-TAG: ce319534af63b9e965e214aba9a6ebf602c7653f
-
-# DIGEST: b0ccc9b5ae13a7f8a01100af61a34be7ef6ccf6d
-KEY: b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729b
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304
-AD: bd3508132a027d1ff4c047
-CT: 4473f6dbf2e39c927374ae7009c3aa0abaf855a2b78236afa2e033dfa40338035ca76f64960999e983dae0969ab02a6cf7e6dd0afcd5f9db596973d24e3a37f5bd6f685a06c10d2d681d7f4113e4b26f62df87b97cfa6861f7f28986c4f372c39e536ec219fbd96a0484a7c02c3895274c97b81e3330ab1a41d2046f828145468bc787e88a561840a00720a36a666181310282ff7e9c84ab39549b777f278a484d51aa92a69aebfbf3151ee89c480817f7442ab2e64f5ddf41ad36ede584babc7804c9da1b51257ab4a87613ae1edaabb9a82883dd9e4677b3e5d2c276911e23f79c1b3a300438eddddcfdf1af496caf50b4e92c37ca2f6d4968831bed614078bf53d28ef73fcf8869f23b16ecc55335dd1adf2f40a39ebe4933369b65169f13a3995e3e39348cf12fd965efe2e75fcb5e
-TAG: eeeab95ce23e78854bd1cf7338a915d7596f990d
-
-# DIGEST: e2b953c833076a52442a7afab46150176c47b730
-KEY: 4706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a
-AD: 027d1ff4c047b3ef4f57a7
-CT: 964febfd22378418945efde794a84f6b4ad1500fe0255d785a4dfb7436cd2c0431fdd7dddff43badf4de88d74107fad8e44bf605f4805d343b20d27ad3e3d46060e0e2e4642af74f249deb26b7175fd0568a47ed36b71aa363c8267bcb5321e6f0615ec2e60dab5e8e5b77e365bb53cd2df91937332e693db4ff09bf3be3900cb757466be7f76bb0e55a58adc134f51958872535b410ea87e876801c664e09cf263d4f4e99c1fccd41c0c990abcf49900859efdac3d472247f212628c704cf27fda26a89ca5e984a10335290a950e8b0489ef67fbc2d675523774a2df4c8325172b9d578a1f73ba230a22b85e154d013d0f04ee8148a7056806249342130522b735ecc17ed9fdae4b0a88a5e7f769a13b12bd6f3011c7e5671893b0698786b0f59c4e455a043eeea5582a97bbbb4d3af5c7660773fc2
-TAG: d6339db6207b064fb810591f32f23a1f1609fbe3
-
-# DIGEST: 8e84935ed1bb79dd38ae38924952e1105101533b
-KEY: 1c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76ae
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c0
-AD: 47b3ef4f57a74706de4b38
-CT: 01092dc4f294a74d082d61f47029e2015f3d43e7094c07e88d7407fbf27502e919d80d9a0389ed9cee571cd2decc43257bf58c393e492e6616b4ba0d65a8dfa04b91c8cf4f864cd7878928a4277b1fb51b730def9cf711061cea8c64ed06132e5f0a4a738d194295009eae1716a26dc7976ba139a87bbfab681d04baa7753455cb749c1cd0b4c7df77fb6e4aa124ba9338a3cfd63d4ece35e062404ffb0c0c123e7ed8732dffc8a0739b69c31b078e38bafa0593ab8a9aef485b663d302aed927be0850378cdaeb82ec8860daeb9f8845a2c77be5759331c0896e314f322d25a0d8d6e4b9d970d73db705508c64fe26215cb9bd602920b5fe1769f3ff1538528c8bd1cdeef1039d7a94e014cc568d3f495c49888c0f18ee0607e2f276e2fcaab2746a3811555a8476ada570da5ddbf15c78014efaeb55193409f2a
-TAG: a969b4a56862275eca92c3a74f225b64fb76060a
-
-# DIGEST: 99ec6b669dbedbe99548117f37189e669fc5d8a2
-KEY: 101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57
-AD: a74706de4b381c692ef164
-CT: f5fc7aba347a577477f1082edaf7c46ed81d71c06262acb5ba1e893525ae6419ad1536a1ee5e22fb60492c8265c15fb612cd65dd492432163a17d98fed2110fa160ed8cc51ec0b3c165fd19421ab5209f5b29b94dec85d5cf9c0621fb46f0602910200e32e28cf5ab5e4ed45ef913e1b4f589e8a7927275729d6f885c67e706eb37594b224f7d78aa61e046569b5e94fb1f93d6dd973651b9d4579c9f6c9ff72a96b2ac5e80491a89a884839a162e38c73bbf3edfbeb66ff2af303c0eaf51d7660e02dbcad616891651947811c4f83ef229f978118815dfcb54dd926e8ebee7938c566c9360d35f608ed64ff985aa9e85828c204ab2338b4b77020aabbc628a3b683fb00e3193c961573cde0b31c2f9daaffa8bf417a6f84c6599fc61692a3df71cd51679111b4a07c2bef3157df168b608d81ccc6aeb13c1365095044d1c99e
-TAG: 63284acc9960ca0632087c68af42958eced06a39
-
-# DIGEST: b55f018cb06f74f0a9f76e65a23c1744ce7535e0
-KEY: f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b
-AD: 381c692ef164101b89b476
-CT: b4e3965ea00f0a6cda49d5586b74e93a8ac4cce1498cfc4cfcba2570ae509b07c8600f04b05042eb7612062c56bd155ea8577dcefcaed2cb91b3a4e2230aeab8ff825639cb20eaee4c8d0cc7b3445a3e5e339ce698898e6009fbc228c37ff8833d06aaf51048a5424be4b40b82aaa61dc7ae130fa83abfe72f6341c78eb3348a9e06aaeba457e06f08f88f3dc1a419238e115f053a456cba344b7e292eeb0d7c2281f3129235f741920f24e9214c24172e19fad28dc7bc50d759ce163321ffbd3e4e6975d4be5ef6d07a33585324d215ed6740062b7fb5a03e008ccfb1c99c24f0732756c115211ce1e8ca6bf8376dfaacad1a4184da6f9944a14c723e4da5deeb202709c59cbb4132bb17f404d127e3e95292a7a2f6335a52f31aebd3685162ea9c5ebd16b45bdcef385dea9daf4fb02d0257d05f81793619689bfea1f18ea37506d4b4d6
-TAG: 1d7172f30033409663a733a01f6d9dc9d7afb7fd
-
-# DIGEST: ac3202e483c67fbcdd751950e1497feb3ebacf52
-KEY: 520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2f
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef1
-AD: 64101b89b476f72b27f06f
-CT: 12925d23d5518dfe5649c89b1b5f4a7cf0034128c714437cdfc1e7aa049425a09f11b4ef0d9a72126b0b4ac637de3a3519eb742f6134673fb521e2b556e5f6e42ac8f41f4371f55c18e318af2c48e3d92945e13eda9b1e4c6229702cee2c7539b328faa056e7f7aa5d0f1c1b7ca9abdb34709573b8359609003ea681d9814cfdc9cb1d043797f32c4bad4a36c53bca5a176f7c1a81fd94cda5992530c7675b49d27f20d16958e63723e52c43149166b2589712e3d5cf07949836e5fd471038c9acaa968673f13c00d85be51cf95360c672f88b95bdfec7869325623ed778d67d00bf41fb3f1abd681ba26e9ae18f82e58b12d80676f98a2a39f0e2f55c4ef39aec1e09b090aaeb98d024c94ae71c2c360dc358bb57ff458627eb25612ca4d4fd7c300a4a01e81c2157cd5d496c234574b556154327bd70ca81d1dfa8b13519235d3586140aecfd5157b4
-TAG: 7616b97262344239b231267986d3c3c72bfb5d28
-
-# DIGEST: db82ae5d79573da2bd7215485a92063861879c3c
-KEY: 71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b4
-AD: 76f72b27f06f520c9267cf
-CT: 281277e794af0eb7df69df600a96a5b07cf28f89ad6398c58330aaa30ece2b30014897d7aeb2a2273c06d223b8c97ac3d5d521e68a0cdaf38ff028939600b6d194fdf6ca2609e412e594497977f3a268a0ceed502f534c0d36e9b39c72a218f862454d55d184c73c2a65ab3deff2fd8ceaab9a810294d19e416a7d79a262d6f9d0f6aacff9b3f30765d35a6f0c57f6133372ba02828b71112e6586ae1efce0b5d909d9b018f17a720dcee4ed73a3953e5080598a0ea290533e71d18789fd8e5392287172230b6993abe6924a4271b003cc3c0d9cfa3c4e483896d7085749b5a07a7395fb909890fe259632a73b974f06a6d02a9b4c62f314b682ab80fffbf535374fb2b6dbca32f084eca0964d54344ebf15b489208ef54fe5b9b3b98dd4e577d868a6837d26f75b8084d77a3cceb5a91b5d3cee8abf5e30e1a30b670bfdaca8b278e8697e0a0fa806b50ae69faf10
-TAG: 07fceb24c68f8a5aaf79ad890c1727bac98a59de
-
-# DIGEST: 902d703861f9872e7b6482f854709a214aa98731
-KEY: 9bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc6
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f0
-AD: 6f520c9267cf71408a4172
-CT: 3fc7262c7b9f5a2515cd2d994a95172821c7a7d78ce103a54e10778c8f6e2e0ae4fb83cb71d6b75d1bf99ad201e3c8b5cdd14ab91a1ecbbf2570e5e37b4a77a7f7228fd0169809b3fe57bb088153a9b932c9e263931c88a173650d237ed46d0e91b859c758311ecb245d85c0447182a7159576b8227ffcd3d7198ffad4320b72e563382daa72c165866f9f76fbdb39bd2d361556b4c8172f5eb1bfe0337d4097b76b5742615954a6e1c089392c90dbc488b1bf4621e6e2d7b7e3529e27ca9260d1d53fa70d442c93c29991a8d907ab7a3564851083a57d21b89d4064861e52e8fd953f03c8cd034718a03cddccbe7b8c8eff552374ac650e988875d7b4110bbb0c37c87f2b6cb0b88cee2a494528edb5a0d9c3a8fa02000fcb5f668533eff65dddf9ab91b7f35ba6a53ef31ab08808d53a7f52b0ca5ec5e183f83cec21499171785afbebdcee06a7a95be6611344628e91ea9552
-TAG: 40f2b4c52d16bfb75db7c9e766be1571b35cbbe7
-
-# DIGEST: 4becd26b9b5c7bf831523f44cb72c8e50ff8033e
-KEY: 72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267
-AD: cf71408a41729bacb5877e
-CT: dacf6f256ac1d4b3e2f7971aa129681852898cf9a6941b1509174f85bb78dae6bd2202e6c7e422a36e16322fa3348a93ff193f2927aff6a61c265638e99ea86f02210da863068a646bcc6c0f73167ef3b9e22ac2336773ce65dd4632816f77f70e17744028e75630a756a0ad250e88a267fa572c69eb75377fc32b2b374850943adc08c05339862382e7aeef6e909ee67820b39784c9e1851c61b0a2cb66f9c40c5599169c6c1d5a008685222b3704c9a5cdee26041957bd0fe11749a2443f4c75a15d3c236ca53ee1838a7b6deea90fd3dea3b73445a70f4ecbb074ca1f9c3ea962c8a7af55a3d8eaabfa5d25c6fccdbf7068ec04052aeb15f1c4e2d577266eee16d2761231eb1f1c16bd632a26d1bfe05731161896e7b883017f488da07a8c6a9ea6b328d6db18423cb8aa20ee68a4e9b40715298a2fae3c1613d02d217d29e10a745f96d2aa60e289701d4efb22a85f3d5b688ae39ecf75
-TAG: 14df58551290cbf36433af1d5c4800a95f8059a7
-
-# DIGEST: bcf4785d0e3b34c55cb2505b559fdbd525deaac6
-KEY: aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41
-AD: 729bacb5877e72cdfcfa76
-CT: 4da071822155fd88fe886af96fba4c78220f9759d5c65b97f6bc2fac0c727004625577844286870477f36b8b07625588e2177cf568703f8b7fed2f5f2d0765b320038f450704521b842bdc69e2c9aeed028490fcc6085b6a63bc1d14111bdda123518c2bde2d145d0c965fa99538fd5e602528a46f4ea97ed4b5b5b014de7ed449af06bb1b4ca62cec5b91097747b7a5318b08d98c369ec4ddd3ccc5919b22faed23b8cce94ee1026c56fe5b6514b0e7de0054623a3e025528ca80c371c29d2bcdc0514a25085edf11f82bf12d66ba29edf4483814a3ad2689eeb39265a82a20db2002c7d39de05ba1835a13fa792d8e4c4ededb578eb734f13c66e1e54ad07de1a6de06c229a9632affd97d27eaec4492dd24426c0f26b56cb2089ac46a572df484b42cecf8c930ed8909bc6ba75edcb131dd917035248ce3ed31a33593f9636d56a0b519757f7d39496570973448b15b48c9543fab9d2a438d5bdeb15e
-TAG: 485e275d11392681f03049a38e4d3a21b5942494
-
-# DIGEST: 13bff121568d7c32b2546132cb4ad490cea9303d
-KEY: 7c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb587
-AD: 7e72cdfcfa76aed06707a0
-CT: f11e4f245836de61fba3cd50d3dab04d5dfe951045fb5d4692b20d7c64c5d4338c89355c859a7a19be779cb4edf7bb5af6f12cd9530ae438b6e3ac39a136e7604fa952aa2761c96c9422279d7cd91ba5800a82975561770e6a5fec1b4980aa24847666c838e2b20cc9b36ccf99eed7b4f179c5d5a8504a8a624f1e8d8a6a3ba8f8473900cf830ce740f8aa7714fc2e0ee1899440e3a93097248b986550e7203e173ad9a2ba4ec68902ebc2b32954290354a4b4999be077db2205c1315d9014cca579d44a162358804b7b1ad276b79d71dcf8b2ba489de860d0c015b6df096f8195a3042e37e68c0c2399e7a860476c94b534c650e15db3ffc5a706fe89673de6ecc7ae6e05fd1f85c092b02fc578bf6dbf6a394e8a005148dfe7a186616ee54d26162242d9eee14c218e7882ed6077a4977a02804885460b8023243533536b932a57b7724092191e7b4d1531b58c43e0383a0ae134fd29544d5bc33b466f167d25af69
-TAG: 027ac5addc74f1e1e372837dbef5d44d48fb14ff
-
-# DIGEST: e0ec91f0baa3c5fd0c50f135517909e26c204af3
-KEY: 19fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da4
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa
-AD: 76aed06707a07c3dab6997
-CT: 2baabe5ace1588f81b158baef541304556baac57fe7a1ced41cf27994ee77e6252c2fb7164c67350eb181acea36ba7d3a2c0e916d74de6c7204a24670b023933de10be2871aa631cb1bf51ba3e514b828ed501150165b90d32102a17b532e7579e02f83953af57fab4c884b72f375e94a95fd7fb775dd8a8c60c13c77e0f0c0e2a425f633b1f5eca906a6e9079fbe80a9838e41d89371eeb0283eaf102691df5bc25b104a35ae0727c2d4b1a342377a7e9f5f59c55da856b5b8de96be8ff20d1c7e3d87bca0646f0ff188838d38075c82fb156c8a80b8f5fc4d9dba12a8e5e0b9155f0d0619fbea43ffcd358127d10d73dd8cb84b147e13a3646c04f68631dd3cdf8eedc8f36aced5beb23d6b0ac247c272fd1d8057e1775cc2c9da988bdda7918ff4190bd4720cb90d6b26b1d5fa91a72f3bce2e7359d242cd05ff927840126aaaf4c731ecf0e17ed095ac30d49b9bed6677e13dea1021c70e074bccba68cbbeba2831cc0eeff68
-TAG: 6276304cbb4102c51393621d4f76ff3b135afb2b
-
-# DIGEST: ee7d6f651db434a281b5cc57c2c418db731c65df
-KEY: 2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707
-AD: a07c3dab699719fe882eee
-CT: d5e77afedfb02589cf443cccb4c6fd586c7aab72581af4f5966a5b05bde89bc0db6214f73ac4eda01edf99fbe7f2d09356b475fde75c5aecdd38747bc2bf4004e1a443d765e5c20be178231b3d0f2e50a646436d221e15eb1a27982190154b5abcf892424714f5b3280e4895d79ba49f4e6ee22612b8a181c08a7a7147e6af2c42194bb7e201a16f67d49dc3beb5b1d5cf731a0889ef24fc28946247f273134ff1b93d868f019667b4b01a0a37266a65590a9ad81fc40d43b126ae602280ca5d8b96441d59d3ee619e9181668efae6739ade593db6fd7f87f83f7cb4a164ec5e23400c2dbb85f8f2fb8172e67176f7e9fe66e6e31ddb5e6935058a1ec0945c2535977bfd717936d7eb46f9e3cae26e2021f6f5cfc062dbd64e0b72540802f1b56b30e61d400fa481601e83b8e0ecc8551e9e2ada8eaa278cd13b235e0cdb62992c4e7fc407b78695e18105092011dea3b2eb1f73922a5df5b74e98a2d0a5e74c44f8ce8aca4ab878abb78fac7e
-TAG: 4f54fdbcd07f1d7ae4d66dd32d084ce4c116fcaf
-
-# DIGEST: 810e1f01bfcf6bc13ebae7861454ac133b2d6cd2
-KEY: 11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab69
-AD: 9719fe882eee2fee55ed8b
-CT: f8265e8f3ab952867e0954a72231823503fe0165b9642a2b1facc2ef5c1dea8e063315eb0c6cc66234000abb030dce35273dcb1face27c68be91fab8109d64b9fd0572412d548fc57e4aec883c0222a93a604f58d8ffeda6481bf430aa487bb253f56d0811f5fdc1547ebeb9aff478f3ed0e6daeea55c0b70147748c9604c3ee738c14363f54435c92c05ac60ad92db861d250fa1e6fbde6718a94bba7eafa5ace400439c245db0f60ca52453ed9867340a9544e53fd6c9709736499afcdca771cc33139ee14386c953dff7d09b3cf79f6db3b3e862e86c564c4379c8bce7e28ab0f91f284fb66f6bf148440e3a971c9e6ec312b294eba8f681d565facb3475166a3282c7a8ab3d364f4df4ab69354f7b9248e700340659a19856b302f57808575c4e70a49ab56789172a666a41d814be589104dd67a48c9f8fa8afe98390ac23eedc82b6ed0d7e8f938d4bd30ab70f0c11aa527f5ace3a72405497d83f01a66fc9fea2f64d764dba2db8c235b491b06c183
-TAG: 88ea977a77a18aa4020c9a5461ca02e7f8d94a4a
-
-# DIGEST: 881551d50a849b7e81f0cc0d722f631e32a4c97f
-KEY: c695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc82
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882e
-AD: ee2fee55ed8b11534c870d
-CT: 89e5f9ee792b89e51663abbfc31786b7df872f3666cf0e7366c0500e6ef36a4339e71fb6b3382a32b936643e7849cc9fa1f6758cb53f7f9140d825ffc45ae3bb4a2626c9b518a77393fe3f96d7a8b3f7e2115f99b5c6da70b0cff31aa4814390242ec7fd9b1f9129a49d906ab343a402f6871f582e60514b3faab9340d961135d4c96738b38d5b62813c79169cb124818ee1c412d8768fc4d5b6088c2d61e0da33ac55165c09df47dc0ed798da978b88a324222fb4b8b60bd0cb340329538e5127c06080f0952b079c0b78d13b012d3d0307f8076b8d9ff79b94525b958212b7a2a4ca28464e02063928f26fe076e57365bc7746717efa4ed86641e0f122291e53dc32edb57afe632db70ef3fc4030c34a05b3558f745d2b4a168bf290770569eab01f4dad9ad3d9a4949eff800b7bbb7024ab5ba8772e72cf53a6e316f57491ce13d2ad63a178afa51747b513e710c2eaf94d2189a225ac770e541e7b406f109694e313be3c98668fe64074836643fa961f2beb88b6d0
-TAG: 1b809da43a0a6dd439889b6a6958dd504e94e8eb
-
-# DIGEST: d525f72dbdbf54db80ddeb9c2a84aca41451353e
-KEY: f1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed
-AD: 8b11534c870dc695b814bd
-CT: c8dbf609b350a63957dff770a6c143cec61f885fd23efce164f9de00f68cfd38a1a22569938f4aa5b34b099dd1243e6fa8fa8018641ddb4c32dd532144b939db8756a197a0a6f13507bdb3f8aba1a20eee94df74fd341cc78001eda37e4464f442b3905e1b163d5f7eaa51145fc72b10a85925136e66abb3a17e787db2aa54b666b8330a96c9e1bccebd596b4222cd42daf547fbc7c4630980457f3936e318c51f5bdd6b04bda5f733a7c57580e428d9e163240c47313815bfe20adb2f89e0646bf725d54a2e497c2a838a3f1f90bbdb2429fd2842258d363c841f4a5500e6252fbe396bed20c3c8f633f38a145422b4af4541821926b4d0d96e7743ba226f67c7a4b1a4c32c9494146be4a531b1fa0bb24f9ee44f99e4217fb61a87645b5a5efe3bceb5558391dc367354e64ff2a90eb5bd9ad925a2a4a7104bab7246644dbefdee6d93df7028429ab1ce03ac80623c502286da0ff5868b934a673dd431acd47985d3750c295c087551aad4332031b7d103d590203422a10f46a792
-TAG: 3054546598b67d893cd56d7e439b8e3c170999e4
-
-# DIGEST: b25882426b4730205533cfccc0da1de1f6f2c459
-KEY: 2c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c87
-AD: 0dc695b814bdf1a87bb105
-CT: 80b0591059c545a1e8b4692880c1425bbc08a4d159f4310504d931c02ed21d2fdc9256ac6a151dd8bf1825acb65d43b203631894539bff0bca9a74e732d08f4ea1bd44e6fedab499284fe6b20dc91b6c71517ad9f9436cacf0d6f014eaff418d64269efc62a7363091ed9b7648af113b9453bc1a66bd041ba370c4e654642abfe44099f78cf70bbcdc43ddf39bcb61b01cef9dc54e5d87fe2b95a85f3cf23f8e494a98dafa5bab420237f01b2d14ea6766ed9ae79630e77e8abf99ec62d2835338346bac866bac29adaecbfada8407a96048c5d135c90bdebad291476ed4b25bb7d8f05bfcc43468f2f8d922948faa159fe75cfe322e8936d8c536a7dfb1a040443e6bf8bf33e9dcdb0c3e87c80daeabb09aa14833c18e90a632571f714794f7a70fff7e69bc8b824243a757038ba74d79b38757639e2318fb1c99a6303a3d33de621104afd30a421865ed9712927cc17c684c0417b59b85fc3d05bc93713154e7e75111ce2b9c282e4bcce2d3c38416a6f77bf9405a71691815003dc9c555c3da
-TAG: 16074e9ebdb9bdde598d953f6a50cbea0c488567
-
-# DIGEST: 939442486c730c2cbd8df213d81310e50534f06c
-KEY: 16bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9b
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814
-AD: bdf1a87bb1052c6755a7a1
-CT: 295fedfde61b2d00b6c1d85f0ef6e34748a9d975fd4c3bcb139955054274af93dbea9a9fa3c28cdff4284b4ef20bc07e1beedc505a847abe0c9510a736b589628fac18bd5546664597b53ddd8d4a9cd7f97129e3eb618a76fe9f9386a97424c2e2193bfbcc6c10529ccb6bc16ed9109f75936760b219cffa47425a8c66c3f0312566b502278797ea1441e383cdb5618636bf1f7faea7c83d504c244553cd88fb853059e77067661c3906bd8b29aec5d066d9dcc735f590fc8362b567e8237d2c9fe9b30c9d872cfa02f4b1c7bea5afa527b29182c517484ec01f2abd89eced89518b10ae33385827357f7dbf6e28b0a7d825cce15076e1c94629f0e5f950a8fe9a8f6da65723a14071fa34237f9d99a482672e12c0c99c3af418da0fcfd9d9f8d828f6f1ada4a5918810549395097096ed521f83210292053bbec97fa3201282ce5ca509cf644749e57da9c8648519a1902272646bad4e822c94273e09b17cf8bf307c9c225cc441addf7f62e4b091fdb7e5591a0e27fbb57ee53b4eed111854e47450279db3
-TAG: 55c82c13578d0dc8863d2d0a96d26c3d6dd11f5d
-
-# DIGEST: a7b522c0de411517839342925e8acf703ea12e8c
-KEY: a49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee58577723
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1
-AD: 052c6755a7a116bfc9095d
-CT: 16c05767af25ec96be58cb10c75ea2e10b72d3e8f8243b329127b5b78dcd2aafd19faead8108dcc5ca3010b4655fdb3815b0edad5d3265338481b26848735a3b6c58f8f2ea08e3f671cb46047859bba4886d9df89adde5fde5e34272df93f86c27ee69b6f9822d502aaaf18beb153f235a620aeaefa43f7a11340f329f45b8a141cab854e31c05600b4a84fe246f5633bb2b6525fef5aa71834bea19cccca9352393e5cba73cdfc2c7a04183cac16da16a3be09d292ef9edff7a216fd708857f65be99dd696ae0ac5ba74cc33fa4b95bbfd2fad8b84202377692b4e8d2bd9901e4f5c2458cccc207cf41b2f27d91a31014e610d1fd033cd52d9706d2834c7817a78a9441f02d95f8177fc58dcfded105310c577840f49eafe0408d0d387225e8cb080daebb5677abd3b02afb699985ba434892e59e19a8baaff0356c131235499f9fb341edb12741fc574c46a1ab35501c51925e741eaea59452f5f76dd7d39ea721b341d2715f7425fd1e5f5b05e397b7ff312201a3575909143a6a22a88f3490b85e97243222020714b5
-TAG: 7129fef93fcd67556fae5414c9936256b57930d4
-
-# DIGEST: f61096694be30b85b6571dfc8b5bfc4d364bd225
-KEY: 4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7
-AD: a116bfc9095da49db3d71f
-CT: cab46036ec877a6a1797192905fe5ec3bbe5c6ad8318bcfd47b8d28c892ab2e7cea9b1b01aa78308a1868633fb77972e436860641d20e07ced22ad9c558f0a9fe3698d1ec10ff73627bf7480630f2ee9ca6e6887551b440fb36da68f84b809dd78e0b3a780727466a4deddaef43f00e4bf31adc49ae5216877c437b23f5a384353df2fdae1d9839423b1dbaeeda2d5e873f9a0a0d1a9b6f031c698bf44ff2658b788c42576efdc8cd78fb12db95a1b0e6ded6fc7838f0529849e05718e14a50fecc1f4de20233ebed7905c8ae7ac7ee8d9b6b7d9e549bd57bea0e1a68688bdaf73d497170028af527007a67f3a165dac2f0fbc54683686da7343f8deaff9b538bc9e3f50cf13851f6c5958c9b0807313aa985f3730908e00f70b9108fab8dc50e208e3e1f0d1ca9fd0c174811ff87bbc9cf1b17b072499e7861458ec8ac4d8b5654a9cc3b1082097cb1a7ee1698c30658e20dc91d07feec0fb685011cd590095f109c318394ee39a09f9f8696fec9d964053a142df939dd481407b0c984d715bf73a1a5bcaaef44fd490cbde9f970055
-TAG: 482684a4f897baee64af8632c3d6fdae9cd187f2
-
-# DIGEST: acd9a5179a0ec782a63bc824188d838776bc1b81
-KEY: 3f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d808
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc909
-AD: 5da49db3d71f4b975c5d50
-CT: c13d301ef5dd85a539af93aeea45dd6022dadb0e834c2a115c594ed6a31a1aa522c7944348f7de64bd694b994625bc08d5f3d974b6cba8060ec719d78e4ac5992668a7a0d8c911be5867dabb2df3a4d71baf9d82c878b0b5e449c8712ee300bc5bc31347d09df05e06875ddfbb6b69bd4337908c5bc8cdeb81517c91fe025ecc21c6b91a9de42ccfb946215908966aad616ff72e23770e8e24ec75592959b728133577ce0695334184ad3c0070a6a0a0cd4464db13f32a265e5b030a3c742fc2e3a65d2a3844945ff0f9b572c676b78e6bbc61b8ef6e61377209425dcf77a8ce678957632c0b344f636f339c54827a4b62b0698888539cf01898fd35cf43def6f3a6e949e8ecf4010493481fdc3dea629adf86cab60d2df0cb9592b2b1103057895cdb31dd9bfcd476c2ae9be5961f6eb664a5a533817ab12f4522fb976a0331d4d6f91ba89fc4d83270bb3be53a2094ec0aa3075ced8b7ef2afb94fb62e2c843403ccd834fd85080670a4f47e623d14b0599fc3d24e7ea459e155a27741b77126a75de4d09d713404ab352fdd936965acdc5fce80
-TAG: e140a0352368d50684c284754796f3636f398de8
-
-# DIGEST: 152118d780c866c5eed3a08d2d9960cdc5acaabf
-KEY: 8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea371
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d7
-AD: 1f4b975c5d503f478b22dc
-CT: 7bd84f18e5dca11f90d045c8c5ef6db4a5e66a6412e49393abce42b147d9d301669563c4c85526e537a54e03158d947efd9089fac862b773a79051bf50c35b26f98b0d4988295e5355ddd49ed1a2a21623e6546675516a1eb5442bc2aaea887e0ca0498346a1cc37dde8d82eaa8fcc67ba43d3bca7aa107e9d2ac70d5a526e9107dd8ca08aabbe7aa9f653db1da194b3701cc7c0d117dec905c2cb4cb02a5c9d48bcc4de6a114a17f83b2f7f926bbf3220ce3ae209caa3551ccb53339829f52a2068b161042d9b48172fdbd7be527b4cd3abf1b0e17931edcb20c55f245b3d8745bcc5a77941829561ff5e82c17ce7413bb858d87d97c9e9c362f09d5ad244417e1afee0b64c18fbecb4e4b6ea64e2ba87c1dfba250d092eaf51de94c60299c5c4a06c578c89b3cc59ae454c06902df22db0b35777b39e473e72945fe3f84182a094506c286a68fa3072ac46091d33fb5fc0d89b86b8f03dac299362665d09c95a5d21f2a5f5e8ced683d45f84a4fc1e3284d99a48fc24c6325162937e6a936f684481735aab30f6fd47cd3a712a866e13ca40fe4a1176c22205
-TAG: 42766e9cf0ec3c2535b67b7e44c309b5bbd1e553
-
-# DIGEST: ca91b15125e07b81debf75ff84e7eed4da5808a0
-KEY: 1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf7826
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d
-AD: 503f478b22dc8253bee6fd
-CT: d38a66c515a4e30c1a341c952bc8344fbcd221f2a59ac415358764d459adcbe620c76dbbbf71fe44e34d2cdb287599748e89e0a91bad4a5053bb72c23afb58eb39d468af969210146918ce17e6c399550c26213ccf964de8face807ca5011a5fb12b2c9b8db6ba11bb725ea77264fb1aec8b164f3ca3284e331f0bf2ce8ab2aff928532b3878d915bb052970559d7b540464cf493a793385f56f6149228e9573621e8c67756158d33029145fb5af82ef7fb5ce885866e578c6833d5378cd89e626879deedc60ffb910e403d5018f42840202285f846daf15f7907d6f1df0eb5a8b60f484bedf44cee6a4da6229c8ec9e11ded1f8e2d5a519adf1cfea40a838195c322f7517610beb0331e8484d20f22fa6a873fb1a520ff31357fb2fef8429ff54a9b1160232a2b2a73e8c45de6be95458f26b7a4e04efdee2b33a8e599ede760249f0261d7ce3d23528326ea55901bfe35ad1401322a9a954cfee52a376c664a5a99c03e0b9b033defa54005eaed64fccd87eb1e655448a66ff017e79320ece47105ec6e99051af737ae73241d3c1eea5c78949a3f32c351974ad273f66cd
-TAG: 24a3e638be17c2e810f8bf49a3d18b7a2d7452ea
-
-# DIGEST: 93d06638fe1e836ecdf5d30db3e4fd0660d9d701
-KEY: 01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22
-AD: dc8253bee6fd1b174c307f
-CT: 35d29afd4110acca674c73c693fe71ca34a7119b60594a8df52c24e6765ad9bd30d8b65728cb42f3227a9048677647135a385894cd057c494b6f52af8f5c099135ac8e344dbea7a152154ecee4ccddc164713b3b2d5da21108ec7f6654861b5b0dfd60865f75ac73f433eca1ab83326924fe8a9adf8fab10db48b5ccd27ad51af9cf60138683c75b9c49cbb1dc3c6be9bce77baaf927f7b8da4ae66ae6dfad02862f0ee83bf4d76c22cc3cb421bd38dabb9c42cfdf59efa757a61befb17a36c76ab07a152bc09df293b8e3b31baedc851279eaaf5a6a25f8629642c7a754139da770f54cbbb18daab5b5da916e40c1c0ca48bbe30ca4ae4fc89866a935c73110da8cf938f1ff88011bb951c0a041198d809365c46d0e06d4aaab806a46da697f2eac0887d7744d63a550c9192f1dfc2e6f3f55e9867b0e22e9550d61b9d6624f4ac2808f4381fb71d41cccd203acf24648e3f5f92d415647cfa454dbb0b5e23e6dc40926814330c6f01387435ee1f4d4a5eb95cfdf992736823dd666b35f79ad88dd317fc0bd82bc98fbb1315bb2184e00f3d1f74c751138c28a985a1eccedaea57940e1
-TAG: 9b0585dd97d9a97d592556d393f782d794c32be4
-
-# DIGEST: a12c8aa71387379d0e43afa0321979e018d56547
-KEY: 9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da1
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6
-AD: fd1b174c307f01be95abaa
-CT: bae3dfd4e46015aff8cff38c11e0342e5fbc237d241d2d328b960e3341d49af01d3c364ea92c091b3fddbcdf7cdb8110f1ff0b266e9c09c2877e2750405e15c8fd75301f590ad3a3c30b3f48d2b6d0d47bf652e59497a00c5efed6268a4d2d896516082500f191c8ea6e22ab6bd5abf6e9b053ca6b36c80e583abd9dcac3ab009284b9f2920e498984f3324110aab151a10724ec5599c6a2a40b282d20969dfc956b724655873215939751151b84af6082807f58f612ac2f331430633e09c24f381dc30b8fe3a1a3f248d10c6194ed602d7a1268a6f02d2a465e4bbd4de36b0d89ad4cc48bb341bdad7a42f31e86234c1a46984f4b5262f5e2e298cfc9e59bf79782f3b08c77c16f6652eb48a34272fa5714981503edb0929c8ea3c8e24a43fe63271ffef1891d989915ca222ca6c4ffa2df3adcb413f22c14a039a874a578108502cf7ac990774ae34f266ac3a606b14a971d82b0d3e063eff4eaf6a1ffde96794f73ecf5915c6a559471d879d4d71b6f705025b057650ec70cb1ea9d77e24e688a068efefe11db9cb5681fb5ae28616e5ceb29ef047565865847b557baeb99ca04d77c74d73bf6e0
-TAG: dc405467227388fe499925a32262985337280920
-
-# DIGEST: 8a524c3ce814e3059b4c7a6ac748783ce1385c68
-KEY: 2305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f43
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c30
-AD: 7f01be95abaa9bee585777
-CT: 675e75c4be936f4f01cb55818a5051e73c7ba82dad6b3f5c135308d69aa74476af6e45043369a7250c71fa48aab0560fece0b258f7a8546a468857a58389acb15b06c2f98fa641e9a5fb6effe75048c36a4eaec331ecd075ca3a6c3c1d254a1ba62e0556eb15a73808c4a6ff4eb94a4594dd7cfe88fa958b87ea45d5fb6c9f211e426ac075033438648faf57c513da828753a388e36ab4e4e6a9f1449d7568035ca499b7e3a7054f7c8158b186ab28aa4e6456cb31345e6c4ef34422ff3bbf46651e56a7c82520cf7e9cc354c5bd79d23d07e04dfe7a58285b196e6e7c247c318851f23b35b71af46b529c501af7cc588894d17fa1fba6f3debab63cf9e214194b10a8694453c7f6e806e6966e6b1455a7550d98c628cf8f86b1b76479fe45ab599047a9966847b5bb3b334a753204757b916b1cd755f7554898de0278505140c8afccd9a5514a8cda06c32ad50022d87f02a197acd2db289590d2c2ddcd4a0f1ba29ce1f3fb3e400e7b0cfd1dd1ff49e07e626b2e05e4e649396f92d7ce7849e5c78cfe91d27a3519dca3903228be9fb97bff4ef2cbd1c9d33bdccd94b3e9275e0086dbf2f3972da7d99a337e72
-TAG: 122b6197b4cd640a8389f52203e25a8d823fb490
-
-# DIGEST: c31dae836928083019ab6902865d9f14c88fe27b
-KEY: 50d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f437248097445
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95ab
-AD: aa9bee5857772305daa4b5
-CT: 50522331acf0b054ffc13847011df9a6a993277b66470fb312fabc84d6af6579f976b071144ab5edf17a0d3cc2c6d0a12ea5de0e7e17e1bf46492db32ff247795a51be91a06169bbcdbad98a80ab1bfe658299d8f266c147291c5e59bcc8ca72f3ea3576a94c2a58eeea2bd2c9087368dac4c7099b8fb3b1d3ae179557ada654d8ce459363e70f2a6eb51c27a93bad5d24dadd581130308b9783e85321a2c8b13e641b734850b66b842e68a3a1dfed65400816117d8ee2fd282db9563a4d3ea352eb346417e59101384744dd8357c84fa83cdd006935521a2b6fb5a2f154da6d5276cbca9a5cc55c33f155e0369982df6955092170426ff2e7edc0a7dc7c2e45d15b799643123f732511918a1595ca341c347efb0a1d5e403a7e79661f99b4d44431480697b580eebf5789daf4307cb92058291c9e05724b8026949d32e0a17b6e6a8b61e2c2ca1d0c8a43989d0bf30f7f1661bc320679a589641705132284cb24b29ab393357e6ed8d37e76ae057aa10267d7bcda84c3ac91c941d65c7e8271dbf7f0df5df8a6e8e1431c7759831c3469f9937e704ed2112889068319bdc952059c43fe714007d4e3ee21b751da5ecfed8e17
-TAG: a9d85c3a90e25a670f586c0c5eff165883fdd620
-
-# DIGEST: 4b2db052fc8a09f7a0c26afc66dbcd8ae5c9bf62
-KEY: 089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857
-AD: 772305daa4b550d75f05d8
-CT: bd1e3ae0ec8c5fc3fd73fef807ee5638c602699dc1f2fea52696533055258b673ff5e03603fa0421c0b0addbf1c37fd2210139abe9defc7751005dc20d538ebf6caa7116a9cee2137a2418b972793efdba624775ef06b8e9293969536ef03afc8c4c52579635cf11e6baf696564c085cc47040779c5c596da51f7d27946c495f3d09e95f3d8e2a9220fcd03a104a635da896e913825228653fab7a14108b6ba9281afd5cb1f0f936e978c250ac32e5a57bcd6d1e5eb32ebd0b60c14323f4c89f7a4380bb11fd71cdeab5a5d3e95b02727a5acffb79c8020415782b915011307465ec200ffa0f924a6a0c5ef1157b70139d21f451aa17819c579a12ff309ba43dbad70b3079432f5f153c5ce3b38994c113f25c3162834b6840a5076afbb54f163a28309ac641b11d9ff8aa92aba8d3ca68d9518e916a9f26a09f58a9a8862c788f638276cb7c1f267a23d50e6741688d948f72646c1b1f586439fa98109bb47c2b82aa6d6f6064310e3fb57f4f77cfac651e7882a8549f91c262de025de63e6196db82d68ec8d3d203c96098a2f7da707b57a97c46981981fd7e3c119bf4f48d62b5c236a8be8afbcd3e124f391495a0726e64462b0cc00c
-TAG: 3de5372136ff9f77b1273b64d4056e62ae51dabb
-
-# DIGEST: 881926d37fae9095362fff56efadd9fa3c455ebd
-KEY: 711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4
-AD: b550d75f05d8089850fea3
-CT: 8c750a834c7ad3b280e4a92eb17f4f7d5200b9d38f54334089c361a6bf88654046b7b4c48995f31d509f86945558287eaad74c4310c17d9aa3064a365950b3d64766f84a1daa11050a309053101392ec25e476a832ed785bf683af1febf6f58d4c50e28657c8838d59553ab006f6a9c6ec0be4c49fa01751a382b5e592291a24c4e6d71e3de9233529d79515e3d10214c274fedbefe203eceeadec92abe9923d34aebdff33ef3ba3e112caa1e60c552f7b9d1eaa0584b05a812b2ec363dd582b63fc1c08eb2f17fa96517f3c7c1306bb96fedffd01c384b54692166fb4f6f5d1ab90f67e2589ca5ccf76cf9ec2ac13e220ef8e83f8f3fa1cbd409b7df0bd1c848d9e1cb84952a560ae0a63aa0e4f8566a3cf90d7a9d5dc67d12a2f7127f824a84a5f32509bbb90b846e305c520cdc274b185794eab24a6429870eca7459d06a6b8f00b9bdf15bde4cc52a95a26ff583e7ddf5d0d7e6090eb2b41b1b6c09210ed9c998d6de660ca4babd148e7de977198f95275f0a32bc4fbd976cc37058e09b87ed46dd501bd61d492a5fa189d0e2369cc8811c3a444d38e56830fd3c50b712fd1bb17064312440b4971dbc5e9f386c0311eb537f00283d6053d0c0f32
-TAG: 35e6d1d76d51d5b3e898d88363c33fa0399bf28a
-
-# DIGEST: 92d143942e6ef5b44ad7a4b8e71c22f1ecaafffb
-KEY: 2610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05
-AD: d8089850fea3711265bf78
-CT: 5ae10feabb2c08a9487c8be5197f6b024a72434647c1ade111b2c4cca72fbb59865eda4f36b526af000a3081d5db3fa24e7c45c79f530a9db4ae533f8f6f62d1941ce180740b725947c077b81ffa70efdd5067c9d1bdd9153d55c6ccc74195622da51266ad71b5f5879597138309202bdb4da6e7e243ff2414e0cd7e3008e958fe8ccfcb381cea993ffb4615547bbb3f752ede12a0826a93350c02771bc814769c6070fe0d9e0bb70ae1b2c75cb20fd28289af44671fb2949ec72216e139c1eed55dd9f3971b4d7e177e349dd8d7fc3c8b2f0b0fd0b9146e9d35597d206219be5ef4c0fdda4b23a3c3587dcea1f89be91a5952fb024aa7df99c0f800acf58b9c0211eaed6e4c049f3ab2c29491bc3c8a662a3719b895cdf3a35b714952eb581222064f2667e578cd0e13deb1bea33fb2f4c65ad3620a1292b4d7eaf238b7269434e15a3add43393cfbb2425ec167fda249e8379283079f95fdc3ad3ea0d6a35aa0198bb1f7c55ba1b9d79ff467ed6b9b8fe56b19727616ae12d5ee8316a0849df30a5275ebd6933cb2707666b22d4950859935c47509808441caa306ca1b3f44917f1cabfa7e117d8e325527b7d0aa780821947c01a98383b1e7b61e6fc1a73b4475
-TAG: 89b1495e5916a3fc37fa6e57116c803c8237d01b
-
-# DIGEST: 7fcec4927096421498e91df912cfe43b2e971d4a
-KEY: 24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fe
-AD: a3711265bf782610460bfd
-CT: 68c46881b52106a455e0d408eefc9089b78e874e6184ab99732a9066c7c56d5c251ea64fa3e11ad64effc24ddba17a3604f91cdd77f1560733c49d07a14c270cb79c25eb89ae9119977628ec3a6f2d8771cbc7e654c8b23ea97ec3376c78d459762091642170211f06f23a6a3832d4ed0cf7da3e70f26fa99f866cedcf82b7f2f1cc25967ef0978975c38010e14854be7fbb2395307b14b1f02c3e1a4b10e90dc12933e59a7939abc7902e84f85f551aeaaa3d3b685dc81b76060b159414f8329ea4d6f1fe522f77c802646232aeca7cd1d0674410d26fa6b4694cf368f5f414e4db5cf8a03fd772ef2b2ceae57f84939b208fb49cdb718a2bf3a945f82104a958c8dd860ac9c690717666e97f689f200bfa960bc2d8ad0cbb5d57f6affbb24133bab8b20cb6bc7cdffdcf6944e030ab1bf003283bfd623d84f74a1774f9af8e102a044d5ed5e2581b881e91e18ca2f126473fe1bfcd067d3d3525478a50aa7d051d7d55de9674674c226430826d3b0c6383ca175c684279ae074aa4b6e402750c734792352565184b64fdfd6a063860aba717b746bd863ae1206d6881b14b7cac01b1959747b7cc7845808d99a1c0f2105548a726fa6f18fd5bb7a118ee4709c95dc4af9865d8
-TAG: f60291408cfa2b74d36fe999e41dcb2ae0110712
-
-# DIGEST: c1c6273ce723df9f2033c7150d466c011bb457da
-KEY: a12dd4c27f4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea0
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf
-AD: 782610460bfd24ba022e6d
-CT: 2a2f09d464391d1f07356a3d8420d24b0194514a58c1c7913b3a926e4621d9c196079cf319570c1a7c5a4d816f822643ea9c79624b7ff3597d0f5e3e797b95f665b80aa7161f6697f71e8cbf6a436ea0f691b27b52c5fdbfa8a9fc2d17964a161a69cadfe0d3a8ee3772018bbb0a7c35bf7a5939d40f0b32c0b2e1d5414cfece1763775995c1bb4e3cce287d68a33f5a1d647473b1c4287890ce5e9c088803c3eb281163e327fa91544c24fcc62008c26384efa60cd6372fc9a33f530b2d75f2176cadaefd19cc1ab23119a9bc540772f7b1d256e6f770cb7751981b1a5b78cdfe18a6c745460d1f7ea8128de06fa45d93031dc585ead31e9c64858525b9c30ff38015ee62ba35bb3262574d9d7cdb6223815e8acc1db04130961b68fef19ae0a5eb2f3f08f62b2174873c3257370537daef8fbc47a4af0a8e125015ab9ebe077cf8fec0eb29c07565830f89f4336813e76dd0c9795c93be82d4c723119ca18ff06aacf4595b3931e158eb30c3e8956a0b8a3d1bb3456b29c9395046c1065b7295ac676dfcb8b9a81abe5a50661164032b19122d933b73425d5cbb5a08200ed31eab258a9b9c05acaac85795b78bd228ea292e9f8c14b5d08d5cc43c6147a79e42bf5c452938e5f30a00e972
-TAG: 00a1f7f9abb343d0e00c44af21c0808d2292fe0a
-
-# DIGEST: 11424a64d5ce78fd71b30a8070aea071d873afea
-KEY: 4372480974454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460b
-AD: fd24ba022e6da12dd4c27f
-CT: c07f865db109af913772076704f17a2f5e3c40c1a4353c72af3e606cc79b92f5d88ba5245a9babfde9e1ff8936a285bcdc5c81e67054c012bcd9c2b874c09e3e52960f5860f55c8264245d5c4ddd69584b7fb5bf9f79384e7017a1fc3ce1b24420f57656435fa987862deca85b0f57681e32e29fd4c6f7ff80dcbe78e2ee319ddc63e0ee680b1ccddd0fc7a26901adcd6f5f632162d672b99c09aca2e4ae63f608b2e37202c6c04515ef3f4cc6691facd70a39cd044f4115ad4fc16554a473ca994f3ce92a49021453e889508a447373cd06995f0557915009d5801144750bbb83309695726025164be2bec822936c1382fe09acabedd571b95890fd260cb907945dbd657779d35621fbae61bc7ee893708019ba13742031119ebda3e29cfe843bbe0a927b21b4a26cfb92545da5ea4beccd09b4b3eb3cb743f5956e55144da9d98acf2035cc8e9e76b7cc7ced6928d7f4a4b1f5642a3b5aa85b6042c94aa1a82111169b98a7bd3458d429b3fad0d16d6ef681df776fc0edef6c6a26d023ca504b5641325ec32baea721b0aabb9dd67c5bf822ac432676d75230e299747924be2841343ddf7275f235c013aeb5fc079adf288f4017fc40a5a8027f4dbf4e14c1822941b5561b1b78d262e34e055b88ce2b
-TAG: 045620f6e9e16322f17f29f580af6c7117157f3e
-
-# DIGEST: 6b7295febce7fba8d79d1e7ab8fdfc452191e2ba
-KEY: 454879c41de9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e
-AD: 6da12dd4c27f4372480974
-CT: 537f28e6e0ff15fe2cd3e8711006bd471e69f2e465f49f4386fdff00af7c24608dbc4e4b49553c508a70e8ea9d21b8c3702016b0a36a9b2ee15e9f820f1ea16d4be04a489561db04c9dcfa10944b4fe1720a370517ab2d26bfdd8e1439d62f6595b8ce48cb64ce3495edd2be45215a348b6909bfb95c4989af058dff20a5c21a1d6c203c75b2bae4bb9a19c40098a8be1ad4c82309f1fedb312492c73a4da856c838919cf2eb58a02318bd6135554c5dc6f92439a7cf7b9ac6bab9fdb35b2e576f861963ebe43ace3c4e1c4d2ce4aff504880c5a8c2e5e9f8cff0a68139fbafbb3897bf0c4b75f9331d0935526c2d9f9b87e58d9c6ade378fb59be0f43d3caffb25f3751f2f31978a20903934a52db485d68eddca362416eac7df57be9d626c7606173befe02bebcd6d29f1b19c3a5eb0f5d1bd3eedcb8b216cd0e3ff35701291c36e190ad023409058738a5fb9d49a9ed49d1e021ced5a41b25dd765112a3890697f22b97b188ff05a7f02938f79712dc2848802d0d43af15390e77fcc4762dc8e31de811d0072c171197df4a71399aef67adaec999336254badb8ba5d3a1068eaaaa8fea82d09669cd896242294d62fb244faa54bbf50f987c7818c31b3047bbfef41afd7d00c82b8205179e527319a631466e59bd
-TAG: 0a4578985f26088be83b3627ecd37e37b1ae8bc9
-
-# DIGEST: 1dadffba439570155af2509a548764a93042d23a
-KEY: e9ac9f98233b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937a
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c2
-AD: 7f4372480974454879c41d
-CT: 7ff3917c6a5ef9aac95b6d9a837100c7f587c5c9446051f9022fc9178b0d651bad58c884665a04e92af456ff173ea9745d8cf67eec8506b638e4dd26b3ea96e42c5992f3d94b64c0c310a0f0d60b8004ca8eeb5ead6dac3b4e8594281e3672f4d2bf9526c5645caa3d6937c43714f030432ac594391cc491c6464c128975537e8973f11d8254c8d4ff5a1591e5adea25ef60161623bfccbda8c6eed70600a532421808a1f017b8db5c09498a3cfe992046175a0c74a9485b52741d7d7cd665a0e1c73380364bc914986efe4ac1e14676b238095a22f4ff2552f2ad19f072a749bdfb81d16124f8fef856d2cc8b878805d641eac3dfb173afff38307feb4b67ba1d295464fab9dd9e45e23fc2ca49e03434c3a02424832759b1d018ef38b7ca4905974dab11f7fe2885b2ea517bfd0b22390b5e7f652bb33078bc23ace1f68045300ab713db8309dd413459d54217891cdcb350b4a3cdef008c34ccbacd338f8033d72d32a52b0ee79fcb6688d7ba76d514c35012b51cc3f4892c823189eec28195708973ff93f28b41ac282981fa20cfc930f4d13e8dbdc02feb5f3d487cf90a929fe5a29bb881a1c13c36c2dd318c5840c4d66cc89d10cb375f7c565767268a9298e7bbf479b5fecce53d6d9eb335d06fe64cc606ac39f2d8d51c
-TAG: a2cc699d78e3f6248e75a4420692f87961157d3c
-
-# DIGEST: e654b4c78e1c0061eea2996fc126c9bfd41eb6d9
-KEY: 3b5a7379a561792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f43724809
-AD: 74454879c41de9ac9f9823
-CT: f208264960162592a3e9d56b4fc83c00269780269a93e7dadfce93f54af792c65aeef71f5db7e33f3fdec65f7a064da9826237d77a1ae03739c2a8476901f6fa4523d63dd3eb7e505408ead7fe450f0f3cb7974503603dc1d0c1c25e394349024ccc64e82bd6c6b0497da627899c61eb0accdcb776bd0516c5ef8d1c0b138f5fb59ff883df3a274cd5699cf7e400904ed7a50efaa808ff15419362b8d987caf9f57dcf542f78fdc9a8378739e1c724358264678964892d65c488cdbd1009c395d000669b26a42ec49aa91c9e73a9dc6e57fcfcee6ca1ac696975f81e45d9b2a7312ee8d5db77fa4d87f21037a949a26b8fe82655cd2078793ff30bb37db081e110615dcdfec09ebf51b98530bdf13ed457fbfb7a423019cc1056ec0ebfd5d54086f06965d98720c54e1d625db697806c44381ad35e851f4d923405173dacee2665e1f97401612f961d842276a3e8c8758f43ddafb56941dd3143de8d43c52767f598898c5182f2ab22441795719344eaa07c7145e629b31d9ab3a80ad75e2b1d23d964c32d4d9dfcd8b5909cd6e56d47b141b6da4d1292a4c438d7540659f795ccd4f7f6886ec366baa1f72a9c15fed3c0836f740416513800462903999d7e09d3bae22769c911a57b099e15a1d7d776362f25ed16ef0b3dbd2ced9632460dfb
-TAG: 1dd4b30129fda67fa16c30d192048d8305af09ab
-
-# DIGEST: 654b8591c7f0506261713e9ce7a6fd24a6b9357e
-KEY: 61792c0f3116430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d7222712
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c4
-AD: 1de9ac9f98233b5a7379a5
-CT: 9ed81dde78d093b3c45934a2045684bc9dd735c9898f95d70c2aa42d025ce3ff6cd55078054db439b980b94fc89f516a682c10f0f1f960f859f080378844786f59f1719ab14ae63ad047237b9aa9df84ed92bb96acab14a95516124ca465f5a1394485b7ba6eae1db874e395b89a4f6fbd72402f1f4c0514af8465a7a1e78e3d4bf68c1411227471c91b1e4ddb1c5d3394280b59fccfe1a809400248c75723832347e5d52a25c3db1e98f5b72c2c92bd02a4936db492f9f02d799f464aa1190d5caa65c28185217cd3ad072e38ec98a53c87f9ab869483075a10debcdb09025eb03b17decb80722279282be69325b1b8d9e63d0d587023e9deadb8b54e1dcd9681a78540755c70540d1bd7fadc54586d24b75d511952acc69e69ae3f1bfe34830b9306de0a26a2e045bf4670830d7f6ff254283298ccd82eef5ee773587852a3b3925b4a7b1ba55d512b0559f2a62fabbfa0169e0f3608ea457fbb9437cfe8f38f87e35b7306fb8aac50eed94b44bacb9423bfd1514a74591185f34fde204f3dd1bece5a2b9e07b533913b2b69ff6197e49686ff144b35152a1d5471b5500f439b7cae8c17ed15001a3f48a1899305a161e4b093cdd40b98d5b34f868a4b4ee2e38a939ee33226b882afd258f94a795026bfaada68681aa39c2759301812756f87e6563d17
-TAG: d8f6a119a6ac8a68deebfc6ac1a635dde51d4fd4
-
-# DIGEST: 1eaad32c8d0cefaa5e2c503bb2185a73e6387fac
-KEY: 16430e8b6ea058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98
-AD: 233b5a7379a561792c0f31
-CT: 2248180bf6a9405dbac464126f2bbeceb4f8e0fb6ee0400be9481515936550b766e23c343c60982b7984b8de37b661705b06aad6a446834a29160f999f1c9fd22dbb01f8b28b9ae0bbc0e9939a149621ae3bd001aaa52eda0a450c1355db18324f2cf66df77f887aa8b36c550191b3458f23c17d7acb21c02c53abb7227708fc27b308486597bb07999fbf2cfed0fe4f4195d102866bcacdc2ec5c17e1b13cb506e7db53c4bf76cd027a54724752b791afe845b43c0e9109f7982a552bd6ce74851c8146ee2418787ce871d1bad80679d50d60e45d0f4a8ef5f9718a065e195986090ebb0795314d2045ee8c1c02b882887dac53d3078d7e678f1934044e7ae7860df10c928bf474b9dcd05f206f7226aec6f005c296b56910401e42a3cfb49fce993c09e156b91183f1b41cb813057eedcc07e10c62b7f695550e3c6856b2290d262f326ef9d944114b63ee5dc7ed1b83c1286e072d0a7ddb844de616e8b47cb5aa95eff840536c732dbc06e46c01f61cb8ea3e3ce1d57c6f200fb7b10b6751872a65c96c8d3679d8290f0381c22ffb30be641aeef4e28a50410826861514199259ef46294c5353a402acdc6e0969b5aaacc5657f14bfc8c0600982c3874443fc41e92ec1052fe1c790e3546f5b9b1b9e67764924959789277027aaedd127c1a9542d9a263bedf74576
-TAG: 99e98eb154afbf6cc5de5cc0074227ee2ddca81c
-
-# DIGEST: 862c0517b3658e9b9cd27db608d49e24e9b4667d
-KEY: a058c4799eea80abde04ee1de13e937af8f1a6944f44d722271233a825264e977045318c
-NONCE: 
-IN: 936a91d0b5d2c0267218cb7090c6171386d641b87797b684e0fb56f97c3961d8afa22993a340b9b3c589c7481df3f4183aa23fd8d7efd88503f78b8ed1c8e9ba2fd6773e0d0c302a5f47e037446f5891d77df660ed82933f62be8dc55b436965aabe477e0cdd46be99371eb8da7dac997deafd64b1fc65de39f4f03541a11be112a72933c7b54ed4fad0be905d41203f5dce998f8fb2eaad409ae02116417dae0cef457b9e5e16dcc5b6f25607f00d033fb95fb09e4d00d6172e780ab8b700433a957a741c9eb80f2b021b1444769da00fcfab0f5f93b511060c9c5f3aacefe61b184ad2463939ed518ce97c3fdd293d72afc09ffdd4f41963249cd299b92e55ca24d8c078c49f78c7e713710a025cb8b9d71d2989ab33e978c4451e3be585a29a2af12feef71e1063b0b4e6e899200304bd3508132a027d1ff4c047b3ef4f57a74706de4b381c692ef164101b89b476f72b27f06f520c9267cf71408a41729bacb5877e72cdfcfa76aed06707a07c3dab699719fe882eee2fee55ed8b11534c870dc695b814bdf1a87bb1052c6755a7a116bfc9095da49db3d71f4b975c5d503f478b22dc8253bee6fd1b174c307f01be95abaa9bee5857772305daa4b550d75f05d8089850fea3711265bf782610460bfd24ba022e6da12dd4c27f4372480974454879c41de9ac9f98233b5a7379
-AD: a561792c0f3116430e8b6e
-CT: 95a4e848170959bb9367293c8c6779aa4757bf58f03fa60e3e144bbb88a47dfd349db915647ea3a44fe96786543f8d09f6305f8369146b79571a9f449643c8b067896679c163e615bb64be7e459d0517e6ba420aa56e6d1faa2f936156136eb1db758fab08dbd0dd1006e8ec6407ea24b201c9244791e67ec7f2308db459f0f2f7b44078bd1a968b96a707d40a1e5a3d47cb5009222d36fcaa92bd41fad9b56b9915b42e7ab1081f0eeeeae7317d04a9e870a4033343b4dc6bf8b6d8c384d3848eefd01bf583b9a10e6bf11b92ebf1e62f3ef04c942a3ef654ceba77f3f39263a1a9cd7f2a51f1aaf01230e53370af89956615b2c370a827e56af083474ab91821dd46b6af1627d2de448942267eda09e699806be60183f208b8a83ee557ad81fe9c6d89180439423a4a1466b89bc57f19816c6c28ef0520685333d7ceebc7904d27f3fb01e25b30c00107c1e2f9477c3929354bd5bb33091555b8de268ddce72c29a80f5dd5a8d72830c072c34f95a3cfb64214233ceb304b4f96760ea762552ba0dc775ccbea2ce02ee9806daa5155287f2f741ccf700f5e5b0de7ffc6a673f00b941a2dd0f45bb8300bc8d000615db3e88381551e119296939585c810b0719d8880b0a8837bea1052a60544b3bd6c60ff8c825ff6a202d803e593873e9f7aca33aac57780f0bb71c14256512c69
-TAG: 208d87d0a27f909a4d73f03565b6442ae20bd55d
-
diff --git a/src/crypto/cipher/tls_cbc.c b/src/crypto/cipher/tls_cbc.c
index c541db3..52880b0 100644
--- a/src/crypto/cipher/tls_cbc.c
+++ b/src/crypto/cipher/tls_cbc.c
@@ -54,10 +54,11 @@
 #include <string.h>
 
 #include <openssl/digest.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
 #include <openssl/sha.h>
 
 #include "../internal.h"
+#include "internal.h"
 
 
 /* TODO(davidben): unsigned should be size_t. The various constant_time
@@ -72,7 +73,7 @@
  * supported by TLS.) */
 #define MAX_HASH_BLOCK_SIZE 128
 
-int EVP_tls_cbc_remove_padding(unsigned *out_len,
+int EVP_tls_cbc_remove_padding(unsigned *out_padding_ok, unsigned *out_len,
                                const uint8_t *in, unsigned in_len,
                                unsigned block_size, unsigned mac_size) {
   unsigned padding_length, good, to_check, i;
@@ -118,111 +119,97 @@
    * bad padding would give POODLE's padding oracle. */
   padding_length = good & (padding_length + 1);
   *out_len = in_len - padding_length;
-
-  return constant_time_select_int(good, 1, -1);
+  *out_padding_ok = good;
+  return 1;
 }
 
-/* If CBC_MAC_ROTATE_IN_PLACE is defined then EVP_tls_cbc_copy_mac is performed
- * with variable accesses in a 64-byte-aligned buffer. Assuming that this fits
- * into a single or pair of cache-lines, then the variable memory accesses don't
- * actually affect the timing. CPUs with smaller cache-lines [if any] are not
- * multi-core and are not considered vulnerable to cache-timing attacks. */
-#define CBC_MAC_ROTATE_IN_PLACE
-
 void EVP_tls_cbc_copy_mac(uint8_t *out, unsigned md_size,
                           const uint8_t *in, unsigned in_len,
                           unsigned orig_len) {
-#if defined(CBC_MAC_ROTATE_IN_PLACE)
-  uint8_t rotated_mac_buf[64 + EVP_MAX_MD_SIZE];
-  uint8_t *rotated_mac;
-#else
-  uint8_t rotated_mac[EVP_MAX_MD_SIZE];
-#endif
+  uint8_t rotated_mac1[EVP_MAX_MD_SIZE], rotated_mac2[EVP_MAX_MD_SIZE];
+  uint8_t *rotated_mac = rotated_mac1;
+  uint8_t *rotated_mac_tmp = rotated_mac2;
 
   /* mac_end is the index of |in| just after the end of the MAC. */
   unsigned mac_end = in_len;
   unsigned mac_start = mac_end - md_size;
-  /* scan_start contains the number of bytes that we can ignore because
-   * the MAC's position can only vary by 255 bytes. */
-  unsigned scan_start = 0;
-  unsigned i, j;
-  unsigned div_spoiler;
-  unsigned rotate_offset;
 
   assert(orig_len >= in_len);
   assert(in_len >= md_size);
   assert(md_size <= EVP_MAX_MD_SIZE);
 
-#if defined(CBC_MAC_ROTATE_IN_PLACE)
-  rotated_mac = rotated_mac_buf + ((0 - (size_t)rotated_mac_buf) & 63);
-#endif
-
+  /* scan_start contains the number of bytes that we can ignore because
+   * the MAC's position can only vary by 255 bytes. */
+  unsigned scan_start = 0;
   /* This information is public so it's safe to branch based on it. */
   if (orig_len > md_size + 255 + 1) {
     scan_start = orig_len - (md_size + 255 + 1);
   }
-  /* div_spoiler contains a multiple of md_size that is used to cause the
-   * modulo operation to be constant time. Without this, the time varies
-   * based on the amount of padding when running on Intel chips at least.
-   *
-   * The aim of right-shifting md_size is so that the compiler doesn't
-   * figure out that it can remove div_spoiler as that would require it
-   * to prove that md_size is always even, which I hope is beyond it. */
-  div_spoiler = md_size >> 1;
-  div_spoiler <<= (sizeof(div_spoiler) - 1) * 8;
-  rotate_offset = (div_spoiler + mac_start - scan_start) % md_size;
 
-  memset(rotated_mac, 0, md_size);
-  for (i = scan_start, j = 0; i < orig_len; i++) {
-    uint8_t mac_started = constant_time_ge_8(i, mac_start);
-    uint8_t mac_ended = constant_time_ge_8(i, mac_end);
-    uint8_t b = in[i];
-    rotated_mac[j++] |= b & mac_started & ~mac_ended;
-    j &= constant_time_lt(j, md_size);
-  }
-
-/* Now rotate the MAC */
-#if defined(CBC_MAC_ROTATE_IN_PLACE)
-  j = 0;
-  for (i = 0; i < md_size; i++) {
-    /* in case cache-line is 32 bytes, touch second line */
-    ((volatile uint8_t *)rotated_mac)[rotate_offset ^ 32];
-    out[j++] = rotated_mac[rotate_offset++];
-    rotate_offset &= constant_time_lt(rotate_offset, md_size);
-  }
-#else
-  memset(out, 0, md_size);
-  rotate_offset = md_size - rotate_offset;
-  rotate_offset &= constant_time_lt(rotate_offset, md_size);
-  for (i = 0; i < md_size; i++) {
-    for (j = 0; j < md_size; j++) {
-      out[j] |= rotated_mac[i] & constant_time_eq_8(j, rotate_offset);
+  unsigned rotate_offset = 0;
+  uint8_t mac_started = 0;
+  OPENSSL_memset(rotated_mac, 0, md_size);
+  for (unsigned i = scan_start, j = 0; i < orig_len; i++, j++) {
+    if (j >= md_size) {
+      j -= md_size;
     }
-    rotate_offset++;
-    rotate_offset &= constant_time_lt(rotate_offset, md_size);
+    unsigned is_mac_start = constant_time_eq(i, mac_start);
+    mac_started |= is_mac_start;
+    uint8_t mac_ended = constant_time_ge_8(i, mac_end);
+    rotated_mac[j] |= in[i] & mac_started & ~mac_ended;
+    /* Save the offset that |mac_start| is mapped to. */
+    rotate_offset |= j & is_mac_start;
   }
-#endif
+
+  /* Now rotate the MAC. We rotate in log(md_size) steps, one for each bit
+   * position. */
+  for (unsigned offset = 1; offset < md_size;
+       offset <<= 1, rotate_offset >>= 1) {
+    /* Rotate by |offset| iff the corresponding bit is set in
+     * |rotate_offset|, placing the result in |rotated_mac_tmp|. */
+    const uint8_t skip_rotate = (rotate_offset & 1) - 1;
+    for (unsigned i = 0, j = offset; i < md_size; i++, j++) {
+      if (j >= md_size) {
+        j -= md_size;
+      }
+      rotated_mac_tmp[i] =
+          constant_time_select_8(skip_rotate, rotated_mac[i], rotated_mac[j]);
+    }
+
+    /* Swap pointers so |rotated_mac| contains the (possibly) rotated value.
+     * Note the number of iterations and thus the identity of these pointers is
+     * public information. */
+    uint8_t *tmp = rotated_mac;
+    rotated_mac = rotated_mac_tmp;
+    rotated_mac_tmp = tmp;
+  }
+
+  OPENSSL_memcpy(out, rotated_mac, md_size);
 }
 
 /* u32toBE serialises an unsigned, 32-bit number (n) as four bytes at (p) in
  * big-endian order. The value of p is advanced by four. */
-#define u32toBE(n, p) \
-  (*((p)++)=(uint8_t)(n>>24), \
-   *((p)++)=(uint8_t)(n>>16), \
-   *((p)++)=(uint8_t)(n>>8), \
-   *((p)++)=(uint8_t)(n))
+#define u32toBE(n, p)                \
+  do {                               \
+    *((p)++) = (uint8_t)((n) >> 24); \
+    *((p)++) = (uint8_t)((n) >> 16); \
+    *((p)++) = (uint8_t)((n) >> 8);  \
+    *((p)++) = (uint8_t)((n));       \
+  } while (0)
 
 /* u64toBE serialises an unsigned, 64-bit number (n) as eight bytes at (p) in
  * big-endian order. The value of p is advanced by eight. */
-#define u64toBE(n, p) \
-  (*((p)++)=(uint8_t)(n>>56), \
-   *((p)++)=(uint8_t)(n>>48), \
-   *((p)++)=(uint8_t)(n>>40), \
-   *((p)++)=(uint8_t)(n>>32), \
-   *((p)++)=(uint8_t)(n>>24), \
-   *((p)++)=(uint8_t)(n>>16), \
-   *((p)++)=(uint8_t)(n>>8), \
-   *((p)++)=(uint8_t)(n))
+#define u64toBE(n, p)                \
+  do {                               \
+    *((p)++) = (uint8_t)((n) >> 56); \
+    *((p)++) = (uint8_t)((n) >> 48); \
+    *((p)++) = (uint8_t)((n) >> 40); \
+    *((p)++) = (uint8_t)((n) >> 32); \
+    *((p)++) = (uint8_t)((n) >> 24); \
+    *((p)++) = (uint8_t)((n) >> 16); \
+    *((p)++) = (uint8_t)((n) >> 8);  \
+    *((p)++) = (uint8_t)((n));       \
+  } while (0)
 
 /* These functions serialize the state of a hash and thus perform the standard
  * "final" operation without adding the padding and length that such a function
@@ -395,16 +382,16 @@
 
   /* Compute the initial HMAC block. */
   bits += 8 * md_block_size;
-  memset(hmac_pad, 0, md_block_size);
+  OPENSSL_memset(hmac_pad, 0, md_block_size);
   assert(mac_secret_length <= sizeof(hmac_pad));
-  memcpy(hmac_pad, mac_secret, mac_secret_length);
+  OPENSSL_memcpy(hmac_pad, mac_secret, mac_secret_length);
   for (i = 0; i < md_block_size; i++) {
     hmac_pad[i] ^= 0x36;
   }
 
   md_transform(md_state.c, hmac_pad);
 
-  memset(length_bytes, 0, md_length_size - 4);
+  OPENSSL_memset(length_bytes, 0, md_length_size - 4);
   length_bytes[md_length_size - 4] = (uint8_t)(bits >> 24);
   length_bytes[md_length_size - 3] = (uint8_t)(bits >> 16);
   length_bytes[md_length_size - 2] = (uint8_t)(bits >> 8);
@@ -412,15 +399,15 @@
 
   if (k > 0) {
     /* k is a multiple of md_block_size. */
-    memcpy(first_block, header, 13);
-    memcpy(first_block + 13, data, md_block_size - 13);
+    OPENSSL_memcpy(first_block, header, 13);
+    OPENSSL_memcpy(first_block + 13, data, md_block_size - 13);
     md_transform(md_state.c, first_block);
     for (i = 1; i < k / md_block_size; i++) {
       md_transform(md_state.c, data + md_block_size * i - 13);
     }
   }
 
-  memset(mac_out, 0, sizeof(mac_out));
+  OPENSSL_memset(mac_out, 0, sizeof(mac_out));
 
   /* We now process the final hash blocks. For each block, we construct
    * it in constant time. If the |i==index_a| then we'll include the 0x80
diff --git a/src/crypto/cmac/cmac.c b/src/crypto/cmac/cmac.c
index fa4c3c4..a9a527d 100644
--- a/src/crypto/cmac/cmac.c
+++ b/src/crypto/cmac/cmac.c
@@ -55,6 +55,8 @@
 #include <openssl/cipher.h>
 #include <openssl/mem.h>
 
+#include "../internal.h"
+
 
 struct cmac_ctx_st {
   EVP_CIPHER_CTX cipher_ctx;
@@ -176,7 +178,7 @@
       todo = in_len;
     }
 
-    memcpy(ctx->block + ctx->block_used, in, todo);
+    OPENSSL_memcpy(ctx->block + ctx->block_used, in, todo);
     in += todo;
     in_len -= todo;
     ctx->block_used += todo;
@@ -206,7 +208,7 @@
     in_len -= AES_BLOCK_SIZE;
   }
 
-  memcpy(ctx->block, in, in_len);
+  OPENSSL_memcpy(ctx->block, in, in_len);
   ctx->block_used = in_len;
 
   return 1;
@@ -224,8 +226,8 @@
     /* If the last block is incomplete, terminate it with a single 'one' bit
      * followed by zeros. */
     ctx->block[ctx->block_used] = 0x80;
-    memset(ctx->block + ctx->block_used + 1, 0,
-           AES_BLOCK_SIZE - (ctx->block_used + 1));
+    OPENSSL_memset(ctx->block + ctx->block_used + 1, 0,
+                   AES_BLOCK_SIZE - (ctx->block_used + 1));
 
     mask = ctx->k2;
   }
diff --git a/src/crypto/cmac/cmac_test.cc b/src/crypto/cmac/cmac_test.cc
index 53f45d1..7cb1df5 100644
--- a/src/crypto/cmac/cmac_test.cc
+++ b/src/crypto/cmac/cmac_test.cc
@@ -16,9 +16,10 @@
 
 #include <algorithm>
 
+#include <openssl/cipher.h>
 #include <openssl/cmac.h>
+#include <openssl/mem.h>
 
-#include "../test/scoped_types.h"
 #include "../test/test_util.h"
 
 
@@ -43,8 +44,8 @@
     return 0;
   }
 
-  ScopedCMAC_CTX ctx(CMAC_CTX_new());
-  if (!CMAC_Init(ctx.get(), key, key_len, EVP_aes_128_cbc(), NULL)) {
+  bssl::UniquePtr<CMAC_CTX> ctx(CMAC_CTX_new());
+  if (!ctx || !CMAC_Init(ctx.get(), key, key_len, EVP_aes_128_cbc(), NULL)) {
     fprintf(stderr, "%s: CMAC_Init failed.\n", name);
     return 0;
   }
diff --git a/src/crypto/conf/conf.c b/src/crypto/conf/conf.c
index 7512dd0..00172f5 100644
--- a/src/crypto/conf/conf.c
+++ b/src/crypto/conf/conf.c
@@ -65,8 +65,14 @@
 #include <openssl/mem.h>
 
 #include "conf_def.h"
+#include "internal.h"
+#include "../internal.h"
 
 
+/* The maximum length we can grow a value to after variable expansion. 64k
+ * should be more than enough for all reasonable uses. */
+#define MAX_CONF_VALUE_LENGTH 65536
+
 static uint32_t conf_value_hash(const CONF_VALUE *v) {
   return (lh_strhash(v->section) << 2) ^ lh_strhash(v->name);
 }
@@ -117,7 +123,7 @@
     OPENSSL_PUT_ERROR(CONF, ERR_R_MALLOC_FAILURE);
     return NULL;
   }
-  memset(v, 0, sizeof(CONF_VALUE));
+  OPENSSL_memset(v, 0, sizeof(CONF_VALUE));
   return v;
 }
 
@@ -152,7 +158,7 @@
   OPENSSL_free(conf);
 }
 
-CONF_VALUE *NCONF_new_section(const CONF *conf, const char *section) {
+static CONF_VALUE *NCONF_new_section(const CONF *conf, const char *section) {
   STACK_OF(CONF_VALUE) *sk = NULL;
   int ok = 0;
   CONF_VALUE *v = NULL, *old_value;
@@ -314,7 +320,15 @@
         OPENSSL_PUT_ERROR(CONF, CONF_R_VARIABLE_HAS_NO_VALUE);
         goto err;
       }
-      BUF_MEM_grow_clean(buf, (strlen(p) + buf->length - (e - from)));
+      size_t newsize = strlen(p) + buf->length - (e - from);
+      if (newsize > MAX_CONF_VALUE_LENGTH) {
+        OPENSSL_PUT_ERROR(CONF, CONF_R_VARIABLE_EXPANSION_TOO_LONG);
+        goto err;
+      }
+      if (!BUF_MEM_grow_clean(buf, newsize)) {
+        OPENSSL_PUT_ERROR(CONF, ERR_R_MALLOC_FAILURE);
+        goto err;
+      }
       while (*p) {
         buf->data[to++] = *(p++);
       }
@@ -352,7 +366,7 @@
 static CONF_VALUE *get_section(const CONF *conf, const char *section) {
   CONF_VALUE template;
 
-  memset(&template, 0, sizeof(template));
+  OPENSSL_memset(&template, 0, sizeof(template));
   template.section = (char *) section;
   return lh_CONF_VALUE_retrieve(conf->data, &template);
 }
@@ -369,7 +383,7 @@
                              const char *name) {
   CONF_VALUE template, *value;
 
-  memset(&template, 0, sizeof(template));
+  OPENSSL_memset(&template, 0, sizeof(template));
   template.section = (char *) section;
   template.name = (char *) name;
   value = lh_CONF_VALUE_retrieve(conf->data, &template);
@@ -783,3 +797,7 @@
 }
 
 void CONF_modules_free(void) {}
+
+void OPENSSL_config(CONF_MUST_BE_NULL *config_name) {}
+
+void OPENSSL_no_config(void) {}
diff --git a/src/crypto/constant_time_test.c b/src/crypto/constant_time_test.c
deleted file mode 100644
index bc127c1..0000000
--- a/src/crypto/constant_time_test.c
+++ /dev/null
@@ -1,307 +0,0 @@
-/*
- * Utilities for constant-time cryptography.
- *
- * Author: Emilia Kasper (emilia@openssl.org)
- * Based on previous work by Bodo Moeller, Emilia Kasper, Adam Langley
- * (Google).
- * ====================================================================
- * Copyright (c) 2014 The OpenSSL Project.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *    "This product includes cryptographic software written by
- *     Eric Young (eay@cryptsoft.com)"
- *    The word 'cryptographic' can be left out if the rouines from the library
- *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- *    the apps directory (application code) you must include an acknowledgement:
- *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed.  i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- */
-
-#include "internal.h"
-
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-
-static const unsigned int CONSTTIME_TRUE = (unsigned)(~0);
-static const unsigned int CONSTTIME_FALSE = 0;
-static const uint8_t CONSTTIME_TRUE_8 = 0xff;
-static const uint8_t CONSTTIME_FALSE_8 = 0;
-
-static int test_binary_op(unsigned int (*op)(unsigned int a, unsigned int b),
-                          const char* op_name, unsigned int a, unsigned int b,
-                          int is_true) {
-  unsigned c = op(a, b);
-  if (is_true && c != CONSTTIME_TRUE) {
-    fprintf(stderr,
-            "Test failed for %s(%du, %du): expected %du (TRUE), got %du\n",
-            op_name, a, b, CONSTTIME_TRUE, c);
-    return 1;
-  } else if (!is_true && c != CONSTTIME_FALSE) {
-    fprintf(stderr,
-            "Test failed for  %s(%du, %du): expected %du (FALSE), got %du\n",
-            op_name, a, b, CONSTTIME_FALSE, c);
-    return 1;
-  }
-  return 0;
-}
-
-static int test_binary_op_8(uint8_t (*op)(unsigned int a, unsigned int b),
-                            const char* op_name, unsigned int a, unsigned int b,
-                            int is_true) {
-  uint8_t c = op(a, b);
-  if (is_true && c != CONSTTIME_TRUE_8) {
-    fprintf(stderr,
-            "Test failed for %s(%du, %du): expected %u (TRUE), got %u\n",
-            op_name, a, b, CONSTTIME_TRUE_8, c);
-    return 1;
-  } else if (!is_true && c != CONSTTIME_FALSE_8) {
-    fprintf(stderr,
-            "Test failed for  %s(%du, %du): expected %u (FALSE), got %u\n",
-            op_name, a, b, CONSTTIME_FALSE_8, c);
-    return 1;
-  }
-  return 0;
-}
-
-static int test_is_zero(unsigned int a) {
-  unsigned int c = constant_time_is_zero(a);
-  if (a == 0 && c != CONSTTIME_TRUE) {
-    fprintf(stderr,
-            "Test failed for constant_time_is_zero(%du): expected %du (TRUE), "
-            "got %du\n",
-            a, CONSTTIME_TRUE, c);
-    return 1;
-  } else if (a != 0 && c != CONSTTIME_FALSE) {
-    fprintf(stderr,
-            "Test failed for constant_time_is_zero(%du): expected %du (FALSE), "
-            "got %du\n",
-            a, CONSTTIME_FALSE, c);
-    return 1;
-  }
-  return 0;
-}
-
-static int test_is_zero_8(unsigned int a) {
-  uint8_t c = constant_time_is_zero_8(a);
-  if (a == 0 && c != CONSTTIME_TRUE_8) {
-    fprintf(stderr,
-            "Test failed for constant_time_is_zero(%du): expected %u (TRUE), "
-            "got %u\n",
-            a, CONSTTIME_TRUE_8, c);
-    return 1;
-  } else if (a != 0 && c != CONSTTIME_FALSE) {
-    fprintf(stderr,
-            "Test failed for constant_time_is_zero(%du): expected %u (FALSE), "
-            "got %u\n",
-            a, CONSTTIME_FALSE_8, c);
-    return 1;
-  }
-  return 0;
-}
-
-static int test_select(unsigned int a, unsigned int b) {
-  unsigned int selected = constant_time_select(CONSTTIME_TRUE, a, b);
-  if (selected != a) {
-    fprintf(stderr,
-            "Test failed for constant_time_select(%du, %du,"
-            "%du): expected %du(first value), got %du\n",
-            CONSTTIME_TRUE, a, b, a, selected);
-    return 1;
-  }
-  selected = constant_time_select(CONSTTIME_FALSE, a, b);
-  if (selected != b) {
-    fprintf(stderr,
-            "Test failed for constant_time_select(%du, %du,"
-            "%du): expected %du(second value), got %du\n",
-            CONSTTIME_FALSE, a, b, b, selected);
-    return 1;
-  }
-  return 0;
-}
-
-static int test_select_8(uint8_t a, uint8_t b) {
-  uint8_t selected = constant_time_select_8(CONSTTIME_TRUE_8, a, b);
-  if (selected != a) {
-    fprintf(stderr,
-            "Test failed for constant_time_select(%u, %u,"
-            "%u): expected %u(first value), got %u\n",
-            CONSTTIME_TRUE, a, b, a, selected);
-    return 1;
-  }
-  selected = constant_time_select_8(CONSTTIME_FALSE_8, a, b);
-  if (selected != b) {
-    fprintf(stderr,
-            "Test failed for constant_time_select(%u, %u,"
-            "%u): expected %u(second value), got %u\n",
-            CONSTTIME_FALSE, a, b, b, selected);
-    return 1;
-  }
-  return 0;
-}
-
-static int test_select_int(int a, int b) {
-  int selected = constant_time_select_int(CONSTTIME_TRUE, a, b);
-  if (selected != a) {
-    fprintf(stderr,
-            "Test failed for constant_time_select(%du, %d,"
-            "%d): expected %d(first value), got %d\n",
-            CONSTTIME_TRUE, a, b, a, selected);
-    return 1;
-  }
-  selected = constant_time_select_int(CONSTTIME_FALSE, a, b);
-  if (selected != b) {
-    fprintf(stderr,
-            "Test failed for constant_time_select(%du, %d,"
-            "%d): expected %d(second value), got %d\n",
-            CONSTTIME_FALSE, a, b, b, selected);
-    return 1;
-  }
-  return 0;
-}
-
-static int test_eq_int(int a, int b) {
-  unsigned int equal = constant_time_eq_int(a, b);
-  if (a == b && equal != CONSTTIME_TRUE) {
-    fprintf(stderr,
-            "Test failed for constant_time_eq_int(%d, %d): expected %du(TRUE), "
-            "got %du\n",
-            a, b, CONSTTIME_TRUE, equal);
-    return 1;
-  } else if (a != b && equal != CONSTTIME_FALSE) {
-    fprintf(stderr,
-            "Test failed for constant_time_eq_int(%d, %d): expected "
-            "%du(FALSE), got %du\n",
-            a, b, CONSTTIME_FALSE, equal);
-    return 1;
-  }
-  return 0;
-}
-
-static int test_eq_int_8(int a, int b) {
-  uint8_t equal = constant_time_eq_int_8(a, b);
-  if (a == b && equal != CONSTTIME_TRUE_8) {
-    fprintf(stderr,
-            "Test failed for constant_time_eq_int_8(%d, %d): expected "
-            "%u(TRUE), got %u\n",
-            a, b, CONSTTIME_TRUE_8, equal);
-    return 1;
-  } else if (a != b && equal != CONSTTIME_FALSE_8) {
-    fprintf(stderr,
-            "Test failed for constant_time_eq_int_8(%d, %d): expected "
-            "%u(FALSE), got %u\n",
-            a, b, CONSTTIME_FALSE_8, equal);
-    return 1;
-  }
-  return 0;
-}
-
-static unsigned int test_values[] = {0, 1, 1024, 12345, 32000, UINT_MAX / 2 - 1,
-                                     UINT_MAX / 2, UINT_MAX / 2 + 1,
-                                     UINT_MAX - 1, UINT_MAX};
-
-static uint8_t test_values_8[] = {0, 1, 2, 20, 32, 127, 128, 129, 255};
-
-static int signed_test_values[] = {
-    0,     1,      -1,      1024,    -1024,       12345,      -12345,
-    32000, -32000, INT_MAX, INT_MIN, INT_MAX - 1, INT_MIN + 1};
-
-int main(int argc, char* argv[]) {
-  unsigned int a, b, i, j;
-  int c, d;
-  uint8_t e, f;
-  int num_failed = 0, num_all = 0;
-  fprintf(stdout, "Testing constant time operations...\n");
-
-  for (i = 0; i < sizeof(test_values) / sizeof(int); ++i) {
-    a = test_values[i];
-    num_failed += test_is_zero(a);
-    num_failed += test_is_zero_8(a);
-    num_all += 2;
-    for (j = 0; j < sizeof(test_values) / sizeof(int); ++j) {
-      b = test_values[j];
-      num_failed +=
-          test_binary_op(&constant_time_lt, "constant_time_lt", a, b, a < b);
-      num_failed += test_binary_op_8(&constant_time_lt_8, "constant_time_lt_8",
-                                     a, b, a < b);
-      num_failed +=
-          test_binary_op(&constant_time_lt, "constant_time_lt_8", b, a, b < a);
-      num_failed += test_binary_op_8(&constant_time_lt_8, "constant_time_lt_8",
-                                     b, a, b < a);
-      num_failed +=
-          test_binary_op(&constant_time_ge, "constant_time_ge", a, b, a >= b);
-      num_failed += test_binary_op_8(&constant_time_ge_8, "constant_time_ge_8",
-                                     a, b, a >= b);
-      num_failed +=
-          test_binary_op(&constant_time_ge, "constant_time_ge", b, a, b >= a);
-      num_failed += test_binary_op_8(&constant_time_ge_8, "constant_time_ge_8",
-                                     b, a, b >= a);
-      num_failed +=
-          test_binary_op(&constant_time_eq, "constant_time_eq", a, b, a == b);
-      num_failed += test_binary_op_8(&constant_time_eq_8, "constant_time_eq_8",
-                                     a, b, a == b);
-      num_failed +=
-          test_binary_op(&constant_time_eq, "constant_time_eq", b, a, b == a);
-      num_failed += test_binary_op_8(&constant_time_eq_8, "constant_time_eq_8",
-                                     b, a, b == a);
-      num_failed += test_select(a, b);
-      num_all += 13;
-    }
-  }
-
-  for (i = 0; i < sizeof(signed_test_values) / sizeof(int); ++i) {
-    c = signed_test_values[i];
-    for (j = 0; j < sizeof(signed_test_values) / sizeof(int); ++j) {
-      d = signed_test_values[j];
-      num_failed += test_select_int(c, d);
-      num_failed += test_eq_int(c, d);
-      num_failed += test_eq_int_8(c, d);
-      num_all += 3;
-    }
-  }
-
-  for (i = 0; i < sizeof(test_values_8); ++i) {
-    e = test_values_8[i];
-    for (j = 0; j < sizeof(test_values_8); ++j) {
-      f = test_values_8[j];
-      num_failed += test_select_8(e, f);
-      num_all += 1;
-    }
-  }
-
-  if (!num_failed) {
-    fprintf(stdout, "ok (ran %d tests)\n", num_all);
-    fprintf(stdout, "PASS\n");
-    return EXIT_SUCCESS;
-  } else {
-    fprintf(stdout, "%d of %d tests failed!\n", num_failed, num_all);
-    return EXIT_FAILURE;
-  }
-}
diff --git a/src/crypto/constant_time_test.cc b/src/crypto/constant_time_test.cc
new file mode 100644
index 0000000..adfe272
--- /dev/null
+++ b/src/crypto/constant_time_test.cc
@@ -0,0 +1,132 @@
+/*
+ * Utilities for constant-time cryptography.
+ *
+ * Author: Emilia Kasper (emilia@openssl.org)
+ * Based on previous work by Bodo Moeller, Emilia Kasper, Adam Langley
+ * (Google).
+ * ====================================================================
+ * Copyright (c) 2014 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
+#include "internal.h"
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <gtest/gtest.h>
+
+
+static const unsigned CONSTTIME_TRUE = (unsigned)(~0);
+static const unsigned CONSTTIME_FALSE = 0;
+static const uint8_t CONSTTIME_TRUE_8 = 0xff;
+static const uint8_t CONSTTIME_FALSE_8 = 0;
+
+static unsigned FromBool(bool b) {
+  return b ? CONSTTIME_TRUE : CONSTTIME_FALSE;
+}
+
+static uint8_t FromBool8(bool b) {
+  return b ? CONSTTIME_TRUE_8 : CONSTTIME_FALSE_8;
+}
+
+static unsigned test_values[] = {
+    0,
+    1,
+    1024,
+    12345,
+    32000,
+    UINT_MAX / 2 - 1,
+    UINT_MAX / 2,
+    UINT_MAX / 2 + 1,
+    UINT_MAX - 1,
+    UINT_MAX,
+};
+
+static uint8_t test_values_8[] = {0, 1, 2, 20, 32, 127, 128, 129, 255};
+
+static int signed_test_values[] = {
+    0,     1,      -1,      1024,    -1024,       12345,      -12345,
+    32000, -32000, INT_MAX, INT_MIN, INT_MAX - 1, INT_MIN + 1};
+
+TEST(ConstantTimeTest, Test) {
+  for (unsigned a : test_values) {
+    SCOPED_TRACE(a);
+
+    EXPECT_EQ(FromBool(a == 0), constant_time_is_zero(a));
+    EXPECT_EQ(FromBool8(a == 0), constant_time_is_zero_8(a));
+
+    for (unsigned b : test_values) {
+      SCOPED_TRACE(b);
+
+      EXPECT_EQ(FromBool(a < b), constant_time_lt(a, b));
+      EXPECT_EQ(FromBool8(a < b), constant_time_lt_8(a, b));
+
+      EXPECT_EQ(FromBool(a >= b), constant_time_ge(a, b));
+      EXPECT_EQ(FromBool8(a >= b), constant_time_ge_8(a, b));
+
+      EXPECT_EQ(FromBool(a == b), constant_time_eq(a, b));
+      EXPECT_EQ(FromBool8(a == b), constant_time_eq_8(a, b));
+
+      EXPECT_EQ(a, constant_time_select(CONSTTIME_TRUE, a, b));
+      EXPECT_EQ(b, constant_time_select(CONSTTIME_FALSE, a, b));
+    }
+  }
+
+  for (int a : signed_test_values) {
+    SCOPED_TRACE(a);
+    for (int b : signed_test_values) {
+      SCOPED_TRACE(b);
+
+      EXPECT_EQ(a, constant_time_select_int(CONSTTIME_TRUE, a, b));
+      EXPECT_EQ(b, constant_time_select_int(CONSTTIME_FALSE, a, b));
+
+      EXPECT_EQ(FromBool(a == b), constant_time_eq_int(a, b));
+      EXPECT_EQ(FromBool8(a == b), constant_time_eq_int_8(a, b));
+    }
+  }
+
+  for (uint8_t a : test_values_8) {
+    SCOPED_TRACE(static_cast<int>(a));
+    for (uint8_t b : test_values_8) {
+      SCOPED_TRACE(static_cast<int>(b));
+      EXPECT_EQ(a, constant_time_select_8(CONSTTIME_TRUE_8, a, b));
+      EXPECT_EQ(b, constant_time_select_8(CONSTTIME_FALSE_8, a, b));
+    }
+  }
+}
diff --git a/src/crypto/cpu-aarch64-linux.c b/src/crypto/cpu-aarch64-linux.c
new file mode 100644
index 0000000..1b0f395
--- /dev/null
+++ b/src/crypto/cpu-aarch64-linux.c
@@ -0,0 +1,61 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/cpu.h>
+
+#if defined(OPENSSL_AARCH64) && !defined(OPENSSL_STATIC_ARMCAP)
+
+#include <sys/auxv.h>
+
+#include <openssl/arm_arch.h>
+
+#include "internal.h"
+
+
+extern uint32_t OPENSSL_armcap_P;
+
+void OPENSSL_cpuid_setup(void) {
+  unsigned long hwcap = getauxval(AT_HWCAP);
+
+  /* See /usr/include/asm/hwcap.h on an aarch64 installation for the source of
+   * these values. */
+  static const unsigned long kNEON = 1 << 1;
+  static const unsigned long kAES = 1 << 3;
+  static const unsigned long kPMULL = 1 << 4;
+  static const unsigned long kSHA1 = 1 << 5;
+  static const unsigned long kSHA256 = 1 << 6;
+
+  if ((hwcap & kNEON) == 0) {
+    /* Matching OpenSSL, if NEON is missing, don't report other features
+     * either. */
+    return;
+  }
+
+  OPENSSL_armcap_P |= ARMV7_NEON;
+
+  if (hwcap & kAES) {
+    OPENSSL_armcap_P |= ARMV8_AES;
+  }
+  if (hwcap & kPMULL) {
+    OPENSSL_armcap_P |= ARMV8_PMULL;
+  }
+  if (hwcap & kSHA1) {
+    OPENSSL_armcap_P |= ARMV8_SHA1;
+  }
+  if (hwcap & kSHA256) {
+    OPENSSL_armcap_P |= ARMV8_SHA256;
+  }
+}
+
+#endif /* OPENSSL_AARCH64 && !OPENSSL_STATIC_ARMCAP */
diff --git a/src/crypto/cpu-arm-asm.S b/src/crypto/cpu-arm-asm.S
deleted file mode 100644
index faf3ad8..0000000
--- a/src/crypto/cpu-arm-asm.S
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (c) 2014, Google Inc.
-#
-# Permission to use, copy, modify, and/or distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
-# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-#if !defined(OPENSSL_NO_ASM) && defined(__arm__)
-
-.syntax unified
-.cpu cortex-a8
-.fpu neon
-.text
-.thumb
-.align 2
-.global CRYPTO_arm_neon_probe
-.hidden CRYPTO_arm_neon_probe
-.type CRYPTO_arm_neon_probe, %function
-.thumb_func
-CRYPTO_arm_neon_probe:
-  vorr q1, q1, q1
-  bx lr
-.section .note.GNU-stack,"",%progbits
-
-#endif  /* !OPENSSL_NO_ASM && __arm__ */
diff --git a/src/crypto/cpu-arm-linux.c b/src/crypto/cpu-arm-linux.c
new file mode 100644
index 0000000..95bb5ee
--- /dev/null
+++ b/src/crypto/cpu-arm-linux.c
@@ -0,0 +1,360 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/cpu.h>
+
+#if defined(OPENSSL_ARM) && !defined(OPENSSL_STATIC_ARMCAP)
+
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <openssl/arm_arch.h>
+#include <openssl/buf.h>
+#include <openssl/mem.h>
+
+#include "internal.h"
+
+
+#define AT_HWCAP 16
+#define AT_HWCAP2 26
+
+#define HWCAP_NEON (1 << 12)
+
+/* See /usr/include/asm/hwcap.h on an ARM installation for the source of
+ * these values. */
+#define HWCAP2_AES (1 << 0)
+#define HWCAP2_PMULL (1 << 1)
+#define HWCAP2_SHA1 (1 << 2)
+#define HWCAP2_SHA2 (1 << 3)
+
+/* |getauxval| is not available on Android until API level 20. Link it as a weak
+ * symbol and use other methods as fallback. */
+unsigned long getauxval(unsigned long type) __attribute__((weak));
+
+static int open_eintr(const char *path, int flags) {
+  int ret;
+  do {
+    ret = open(path, flags);
+  } while (ret < 0 && errno == EINTR);
+  return ret;
+}
+
+static ssize_t read_eintr(int fd, void *out, size_t len) {
+  ssize_t ret;
+  do {
+    ret = read(fd, out, len);
+  } while (ret < 0 && errno == EINTR);
+  return ret;
+}
+
+/* read_full reads exactly |len| bytes from |fd| to |out|. On error or end of
+ * file, it returns zero. */
+static int read_full(int fd, void *out, size_t len) {
+  char *outp = out;
+  while (len > 0) {
+    ssize_t ret = read_eintr(fd, outp, len);
+    if (ret <= 0) {
+      return 0;
+    }
+    outp += ret;
+    len -= ret;
+  }
+  return 1;
+}
+
+/* read_file opens |path| and reads until end-of-file. On success, it returns
+ * one and sets |*out_ptr| and |*out_len| to a newly-allocated buffer with the
+ * contents. Otherwise, it returns zero. */
+static int read_file(char **out_ptr, size_t *out_len, const char *path) {
+  int fd = open_eintr(path, O_RDONLY);
+  if (fd < 0) {
+    return 0;
+  }
+
+  static const size_t kReadSize = 1024;
+  int ret = 0;
+  size_t cap = kReadSize, len = 0;
+  char *buf = OPENSSL_malloc(cap);
+  if (buf == NULL) {
+    goto err;
+  }
+
+  for (;;) {
+    if (cap - len < kReadSize) {
+      size_t new_cap = cap * 2;
+      if (new_cap < cap) {
+        goto err;
+      }
+      char *new_buf = OPENSSL_realloc(buf, new_cap);
+      if (new_buf == NULL) {
+        goto err;
+      }
+      buf = new_buf;
+      cap = new_cap;
+    }
+
+    ssize_t bytes_read = read_eintr(fd, buf + len, kReadSize);
+    if (bytes_read < 0) {
+      goto err;
+    }
+    if (bytes_read == 0) {
+      break;
+    }
+    len += bytes_read;
+  }
+
+  *out_ptr = buf;
+  *out_len = len;
+  ret = 1;
+  buf = NULL;
+
+err:
+  OPENSSL_free(buf);
+  close(fd);
+  return ret;
+}
+
+/* getauxval_proc behaves like |getauxval| but reads from /proc/self/auxv. */
+static unsigned long getauxval_proc(unsigned long type) {
+  int fd = open_eintr("/proc/self/auxv", O_RDONLY);
+  if (fd < 0) {
+    return 0;
+  }
+
+  struct {
+    unsigned long tag;
+    unsigned long value;
+  } entry;
+
+  for (;;) {
+    if (!read_full(fd, &entry, sizeof(entry)) ||
+        (entry.tag == 0 && entry.value == 0)) {
+      break;
+    }
+    if (entry.tag == type) {
+      close(fd);
+      return entry.value;
+    }
+  }
+  close(fd);
+  return 0;
+}
+
+typedef struct {
+  const char *data;
+  size_t len;
+} STRING_PIECE;
+
+static int STRING_PIECE_equals(const STRING_PIECE *a, const char *b) {
+  size_t b_len = strlen(b);
+  return a->len == b_len && OPENSSL_memcmp(a->data, b, b_len) == 0;
+}
+
+/* STRING_PIECE_split finds the first occurence of |sep| in |in| and, if found,
+ * sets |*out_left| and |*out_right| to |in| split before and after it. It
+ * returns one if |sep| was found and zero otherwise. */
+static int STRING_PIECE_split(STRING_PIECE *out_left, STRING_PIECE *out_right,
+                              const STRING_PIECE *in, char sep) {
+  const char *p = OPENSSL_memchr(in->data, sep, in->len);
+  if (p == NULL) {
+    return 0;
+  }
+  /* |out_left| or |out_right| may alias |in|, so make a copy. */
+  STRING_PIECE in_copy = *in;
+  out_left->data = in_copy.data;
+  out_left->len = p - in_copy.data;
+  out_right->data = in_copy.data + out_left->len + 1;
+  out_right->len = in_copy.len - out_left->len - 1;
+  return 1;
+}
+
+/* STRING_PIECE_trim removes leading and trailing whitespace from |s|. */
+static void STRING_PIECE_trim(STRING_PIECE *s) {
+  while (s->len != 0 && (s->data[0] == ' ' || s->data[0] == '\t')) {
+    s->data++;
+    s->len--;
+  }
+  while (s->len != 0 &&
+         (s->data[s->len - 1] == ' ' || s->data[s->len - 1] == '\t')) {
+    s->len--;
+  }
+}
+
+/* extract_cpuinfo_field extracts a /proc/cpuinfo field named |field| from
+ * |in|.  If found, it sets |*out| to the value and returns one. Otherwise, it
+ * returns zero. */
+static int extract_cpuinfo_field(STRING_PIECE *out, const STRING_PIECE *in,
+                                 const char *field) {
+  /* Process |in| one line at a time. */
+  STRING_PIECE remaining = *in, line;
+  while (STRING_PIECE_split(&line, &remaining, &remaining, '\n')) {
+    STRING_PIECE key, value;
+    if (!STRING_PIECE_split(&key, &value, &line, ':')) {
+      continue;
+    }
+    STRING_PIECE_trim(&key);
+    if (STRING_PIECE_equals(&key, field)) {
+      STRING_PIECE_trim(&value);
+      *out = value;
+      return 1;
+    }
+  }
+
+  return 0;
+}
+
+static int cpuinfo_field_equals(const STRING_PIECE *cpuinfo, const char *field,
+                                const char *value) {
+  STRING_PIECE extracted;
+  return extract_cpuinfo_field(&extracted, cpuinfo, field) &&
+         STRING_PIECE_equals(&extracted, value);
+}
+
+/* has_list_item treats |list| as a space-separated list of items and returns
+ * one if |item| is contained in |list| and zero otherwise. */
+static int has_list_item(const STRING_PIECE *list, const char *item) {
+  STRING_PIECE remaining = *list, feature;
+  while (STRING_PIECE_split(&feature, &remaining, &remaining, ' ')) {
+    if (STRING_PIECE_equals(&feature, item)) {
+      return 1;
+    }
+  }
+  return 0;
+}
+
+static unsigned long get_hwcap_cpuinfo(const STRING_PIECE *cpuinfo) {
+  if (cpuinfo_field_equals(cpuinfo, "CPU architecture", "8")) {
+    /* This is a 32-bit ARM binary running on a 64-bit kernel. NEON is always
+     * available on ARMv8. Linux omits required features, so reading the
+     * "Features" line does not work. (For simplicity, use strict equality. We
+     * assume everything running on future ARM architectures will have a
+     * working |getauxval|.) */
+    return HWCAP_NEON;
+  }
+
+  STRING_PIECE features;
+  if (extract_cpuinfo_field(&features, cpuinfo, "Features") &&
+      has_list_item(&features, "neon")) {
+    return HWCAP_NEON;
+  }
+  return 0;
+}
+
+static unsigned long get_hwcap2_cpuinfo(const STRING_PIECE *cpuinfo) {
+  STRING_PIECE features;
+  if (!extract_cpuinfo_field(&features, cpuinfo, "Features")) {
+    return 0;
+  }
+
+  unsigned long ret = 0;
+  if (has_list_item(&features, "aes")) {
+    ret |= HWCAP2_AES;
+  }
+  if (has_list_item(&features, "pmull")) {
+    ret |= HWCAP2_PMULL;
+  }
+  if (has_list_item(&features, "sha1")) {
+    ret |= HWCAP2_SHA1;
+  }
+  if (has_list_item(&features, "sha2")) {
+    ret |= HWCAP2_SHA2;
+  }
+  return ret;
+}
+
+/* has_broken_neon returns one if |in| matches a CPU known to have a broken
+ * NEON unit. See https://crbug.com/341598. */
+static int has_broken_neon(const STRING_PIECE *cpuinfo) {
+  return cpuinfo_field_equals(cpuinfo, "CPU implementer", "0x51") &&
+         cpuinfo_field_equals(cpuinfo, "CPU architecture", "7") &&
+         cpuinfo_field_equals(cpuinfo, "CPU variant", "0x1") &&
+         cpuinfo_field_equals(cpuinfo, "CPU part", "0x04d") &&
+         cpuinfo_field_equals(cpuinfo, "CPU revision", "0");
+}
+
+extern uint32_t OPENSSL_armcap_P;
+
+static int g_has_broken_neon;
+
+void OPENSSL_cpuid_setup(void) {
+  char *cpuinfo_data;
+  size_t cpuinfo_len;
+  if (!read_file(&cpuinfo_data, &cpuinfo_len, "/proc/cpuinfo")) {
+    return;
+  }
+  STRING_PIECE cpuinfo;
+  cpuinfo.data = cpuinfo_data;
+  cpuinfo.len = cpuinfo_len;
+
+  /* |getauxval| is not available on Android until API level 20. If it is
+   * unavailable, read from /proc/self/auxv as a fallback. This is unreadable
+   * on some versions of Android, so further fall back to /proc/cpuinfo.
+   *
+   * See
+   * https://android.googlesource.com/platform/ndk/+/882ac8f3392858991a0e1af33b4b7387ec856bd2
+   * and b/13679666 (Google-internal) for details. */
+  unsigned long hwcap = 0;
+  if (getauxval != NULL) {
+    hwcap = getauxval(AT_HWCAP);
+  }
+  if (hwcap == 0) {
+    hwcap = getauxval_proc(AT_HWCAP);
+  }
+  if (hwcap == 0) {
+    hwcap = get_hwcap_cpuinfo(&cpuinfo);
+  }
+
+  /* Clear NEON support if known broken. */
+  g_has_broken_neon = has_broken_neon(&cpuinfo);
+  if (g_has_broken_neon) {
+    hwcap &= ~HWCAP_NEON;
+  }
+
+  /* Matching OpenSSL, only report other features if NEON is present. */
+  if (hwcap & HWCAP_NEON) {
+    OPENSSL_armcap_P |= ARMV7_NEON;
+
+    /* Some ARMv8 Android devices don't expose AT_HWCAP2. Fall back to
+     * /proc/cpuinfo. See https://crbug.com/596156. */
+    unsigned long hwcap2 = 0;
+    if (getauxval != NULL) {
+      hwcap2 = getauxval(AT_HWCAP2);
+    }
+    if (hwcap2 == 0) {
+      hwcap2 = get_hwcap2_cpuinfo(&cpuinfo);
+    }
+
+    if (hwcap2 & HWCAP2_AES) {
+      OPENSSL_armcap_P |= ARMV8_AES;
+    }
+    if (hwcap2 & HWCAP2_PMULL) {
+      OPENSSL_armcap_P |= ARMV8_PMULL;
+    }
+    if (hwcap2 & HWCAP2_SHA1) {
+      OPENSSL_armcap_P |= ARMV8_SHA1;
+    }
+    if (hwcap2 & HWCAP2_SHA2) {
+      OPENSSL_armcap_P |= ARMV8_SHA256;
+    }
+  }
+
+  OPENSSL_free(cpuinfo_data);
+}
+
+int CRYPTO_has_broken_NEON(void) { return g_has_broken_neon; }
+
+#endif /* OPENSSL_ARM && !OPENSSL_STATIC_ARMCAP */
diff --git a/src/crypto/cpu-arm.c b/src/crypto/cpu-arm.c
index 675d174..ef395ea 100644
--- a/src/crypto/cpu-arm.c
+++ b/src/crypto/cpu-arm.c
@@ -17,52 +17,15 @@
 #if (defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)) && \
     !defined(OPENSSL_STATIC_ARMCAP)
 
-#include <inttypes.h>
-#include <string.h>
-
-#include <setjmp.h>
-#include <signal.h>
-
 #include <openssl/arm_arch.h>
 
 
-/* We can't include <sys/auxv.h> because the Android SDK version against which
- * Chromium builds is too old to have it. Instead we define all the constants
- * that we need and have a weak pointer to getauxval. */
-
-unsigned long getauxval(unsigned long type) __attribute__((weak));
-
 extern uint32_t OPENSSL_armcap_P;
 
 char CRYPTO_is_NEON_capable_at_runtime(void) {
   return (OPENSSL_armcap_P & ARMV7_NEON) != 0;
 }
 
-static char g_set_neon_called = 0;
-
-void CRYPTO_set_NEON_capable(char neon_capable) {
-  g_set_neon_called = 1;
-
-  if (neon_capable) {
-    OPENSSL_armcap_P |= ARMV7_NEON;
-  } else {
-    OPENSSL_armcap_P &= ~ARMV7_NEON;
-  }
-}
-
-char CRYPTO_is_NEON_functional(void) {
-  static const uint32_t kWantFlags = ARMV7_NEON | ARMV7_NEON_FUNCTIONAL;
-  return (OPENSSL_armcap_P & kWantFlags) == kWantFlags;
-}
-
-void CRYPTO_set_NEON_functional(char neon_functional) {
-  if (neon_functional) {
-    OPENSSL_armcap_P |= ARMV7_NEON_FUNCTIONAL;
-  } else {
-    OPENSSL_armcap_P &= ~ARMV7_NEON_FUNCTIONAL;
-  }
-}
-
 int CRYPTO_is_ARMv8_AES_capable(void) {
   return (OPENSSL_armcap_P & ARMV8_AES) != 0;
 }
@@ -71,129 +34,5 @@
   return (OPENSSL_armcap_P & ARMV8_PMULL) != 0;
 }
 
-#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_ARM)
-
-static sigjmp_buf sigill_jmp;
-
-static void sigill_handler(int signal) {
-  siglongjmp(sigill_jmp, signal);
-}
-
-void CRYPTO_arm_neon_probe(void);
-
-// probe_for_NEON returns 1 if a NEON instruction runs successfully. Because
-// getauxval doesn't exist on Android until Jelly Bean, supporting NEON on
-// older devices requires this.
-static int probe_for_NEON(void) {
-  int supported = 0;
-
-  sigset_t sigmask;
-  sigfillset(&sigmask);
-  sigdelset(&sigmask, SIGILL);
-  sigdelset(&sigmask, SIGTRAP);
-  sigdelset(&sigmask, SIGFPE);
-  sigdelset(&sigmask, SIGBUS);
-  sigdelset(&sigmask, SIGSEGV);
-
-  struct sigaction sigill_original_action, sigill_action;
-  memset(&sigill_action, 0, sizeof(sigill_action));
-  sigill_action.sa_handler = sigill_handler;
-  sigill_action.sa_mask = sigmask;
-
-  sigset_t original_sigmask;
-  sigprocmask(SIG_SETMASK, &sigmask, &original_sigmask);
-
-  if (sigsetjmp(sigill_jmp, 1 /* save signals */) == 0) {
-    sigaction(SIGILL, &sigill_action, &sigill_original_action);
-
-    // This function cannot be inline asm because GCC will refuse to compile
-    // inline NEON instructions unless building with -mfpu=neon, which would
-    // defeat the point of probing for support at runtime.
-    CRYPTO_arm_neon_probe();
-    supported = 1;
-  }
-  // Note that Android up to and including Lollipop doesn't restore the signal
-  // mask correctly after returning from a sigsetjmp. So that would need to be
-  // set again here if more probes were added.
-  // See https://android-review.googlesource.com/#/c/127624/
-
-  sigaction(SIGILL, &sigill_original_action, NULL);
-  sigprocmask(SIG_SETMASK, &original_sigmask, NULL);
-
-  return supported;
-}
-
-#else
-
-static int probe_for_NEON(void) {
-  return 0;
-}
-
-#endif  /* !OPENSSL_NO_ASM && OPENSSL_ARM */
-
-void OPENSSL_cpuid_setup(void) {
-  if (getauxval == NULL) {
-    // On ARM, but not AArch64, try a NEON instruction and see whether it works
-    // in order to probe for NEON support.
-    //
-    // Note that |CRYPTO_is_NEON_capable| can be true even if
-    // |CRYPTO_set_NEON_capable| has never been called if the code was compiled
-    // with NEON support enabled (e.g. -mfpu=neon).
-    if (!g_set_neon_called && !CRYPTO_is_NEON_capable() && probe_for_NEON()) {
-      OPENSSL_armcap_P |= ARMV7_NEON;
-    }
-    return;
-  }
-
-  static const unsigned long AT_HWCAP = 16;
-  unsigned long hwcap = getauxval(AT_HWCAP);
-
-#if defined(OPENSSL_ARM)
-  static const unsigned long kNEON = 1 << 12;
-  if ((hwcap & kNEON) == 0) {
-    return;
-  }
-
-  /* In 32-bit mode, the ARMv8 feature bits are in a different aux vector
-   * value. */
-  static const unsigned long AT_HWCAP2 = 26;
-  hwcap = getauxval(AT_HWCAP2);
-
-  /* See /usr/include/asm/hwcap.h on an ARM installation for the source of
-   * these values. */
-  static const unsigned long kAES = 1 << 0;
-  static const unsigned long kPMULL = 1 << 1;
-  static const unsigned long kSHA1 = 1 << 2;
-  static const unsigned long kSHA256 = 1 << 3;
-#elif defined(OPENSSL_AARCH64)
-  /* See /usr/include/asm/hwcap.h on an aarch64 installation for the source of
-   * these values. */
-  static const unsigned long kNEON = 1 << 1;
-  static const unsigned long kAES = 1 << 3;
-  static const unsigned long kPMULL = 1 << 4;
-  static const unsigned long kSHA1 = 1 << 5;
-  static const unsigned long kSHA256 = 1 << 6;
-
-  if ((hwcap & kNEON) == 0) {
-    return;
-  }
-#endif
-
-  OPENSSL_armcap_P |= ARMV7_NEON;
-
-  if (hwcap & kAES) {
-    OPENSSL_armcap_P |= ARMV8_AES;
-  }
-  if (hwcap & kPMULL) {
-    OPENSSL_armcap_P |= ARMV8_PMULL;
-  }
-  if (hwcap & kSHA1) {
-    OPENSSL_armcap_P |= ARMV8_SHA1;
-  }
-  if (hwcap & kSHA256) {
-    OPENSSL_armcap_P |= ARMV8_SHA256;
-  }
-}
-
 #endif  /* (defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)) &&
            !defined(OPENSSL_STATIC_ARMCAP) */
diff --git a/src/crypto/cpu-intel.c b/src/crypto/cpu-intel.c
index 924bab0..f2e0c4c 100644
--- a/src/crypto/cpu-intel.c
+++ b/src/crypto/cpu-intel.c
@@ -64,17 +64,19 @@
 #if !defined(OPENSSL_NO_ASM) && (defined(OPENSSL_X86) || defined(OPENSSL_X86_64))
 
 #include <inttypes.h>
-#include <stdlib.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 
 #if defined(OPENSSL_WINDOWS)
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <immintrin.h>
 #include <intrin.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
 #endif
 
+#include "internal.h"
+
 
 /* OPENSSL_cpuid runs the cpuid instruction. |leaf| is passed in as EAX and ECX
  * is set to zero. It writes EAX, EBX, ECX, and EDX to |*out_eax| through
@@ -127,7 +129,7 @@
   const int invert = in[0] == '~';
   uint64_t v;
 
-  if (!sscanf(in + invert, "%" PRIi64, &v)) {
+  if (!sscanf(in + invert, "%" PRIu64, &v)) {
     return;
   }
 
diff --git a/src/crypto/cpu-ppc64le.c b/src/crypto/cpu-ppc64le.c
new file mode 100644
index 0000000..c431c81
--- /dev/null
+++ b/src/crypto/cpu-ppc64le.c
@@ -0,0 +1,40 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/cpu.h>
+
+#if defined(OPENSSL_PPC64LE)
+
+#include <sys/auxv.h>
+
+#include "internal.h"
+
+
+#if !defined(PPC_FEATURE2_HAS_VCRYPTO)
+/* PPC_FEATURE2_HAS_VCRYPTO was taken from section 4.1.2.3 of the “OpenPOWER
+ * ABI for Linux Supplement”. */
+#define PPC_FEATURE2_HAS_VCRYPTO 0x02000000
+#endif
+
+static unsigned long g_ppc64le_hwcap2 = 0;
+
+void OPENSSL_cpuid_setup(void) {
+  g_ppc64le_hwcap2 = getauxval(AT_HWCAP2);
+}
+
+int CRYPTO_is_PPC64LE_vcrypto_capable(void) {
+  return (g_ppc64le_hwcap2 & PPC_FEATURE2_HAS_VCRYPTO) != 0;
+}
+
+#endif  /* OPENSSL_PPC64LE */
diff --git a/src/crypto/crypto.c b/src/crypto/crypto.c
index da8807d..c32f514 100644
--- a/src/crypto/crypto.c
+++ b/src/crypto/crypto.c
@@ -21,9 +21,11 @@
 
 #if !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_STATIC_ARMCAP) && \
     (defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \
-     defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64))
-/* x86, x86_64 and the ARMs need to record the result of a cpuid call for the
- * asm to work correctly, unless compiled without asm code. */
+     defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64) || \
+     defined(OPENSSL_PPC64LE))
+/* x86, x86_64, the ARMs and ppc64le need to record the result of a
+ * cpuid/getauxval call for the asm to work correctly, unless compiled without
+ * asm code. */
 #define NEED_CPUID
 
 #else
@@ -63,7 +65,7 @@
 
 uint32_t OPENSSL_armcap_P =
 #if defined(OPENSSL_STATIC_ARMCAP_NEON) || defined(__ARM_NEON__)
-    ARMV7_NEON | ARMV7_NEON_FUNCTIONAL |
+    ARMV7_NEON |
 #endif
 #if defined(OPENSSL_STATIC_ARMCAP_AES)
     ARMV8_AES |
@@ -79,10 +81,8 @@
 #endif
     0;
 
-#elif defined(__ARM_NEON__)
-uint32_t OPENSSL_armcap_P = ARMV7_NEON | ARMV7_NEON_FUNCTIONAL;
 #else
-uint32_t OPENSSL_armcap_P = ARMV7_NEON_FUNCTIONAL;
+uint32_t OPENSSL_armcap_P = 0;
 #endif
 
 #endif
@@ -125,6 +125,22 @@
 #endif
 }
 
+int CRYPTO_is_confidential_build(void) {
+#if defined(BORINGSSL_CONFIDENTIAL)
+  return 1;
+#else
+  return 0;
+#endif
+}
+
+int CRYPTO_has_asm(void) {
+#if defined(OPENSSL_NO_ASM)
+  return 0;
+#else
+  return 1;
+#endif
+}
+
 const char *SSLeay_version(int unused) {
   return "BoringSSL";
 }
@@ -139,4 +155,10 @@
 
 void ENGINE_load_builtin_engines(void) {}
 
+int ENGINE_register_all_complete(void) {
+  return 1;
+}
+
 void OPENSSL_load_builtin_modules(void) {}
+
+int FIPS_mode(void) { return 0; }
diff --git a/src/crypto/curve25519/CMakeLists.txt b/src/crypto/curve25519/CMakeLists.txt
index a2ef3bb..198d6af 100644
--- a/src/crypto/curve25519/CMakeLists.txt
+++ b/src/crypto/curve25519/CMakeLists.txt
@@ -22,6 +22,7 @@
   OBJECT
 
   curve25519.c
+  spake25519.c
   x25519-x86_64.c
 
   ${CURVE25519_ARCH_SOURCES}
@@ -38,10 +39,10 @@
 add_dependencies(all_tests ed25519_test)
 
 add_executable(
-  x25519_test
+  spake25519_test
 
-  x25519_test.cc
+  spake25519_test.cc
 )
 
-target_link_libraries(x25519_test crypto)
-add_dependencies(all_tests x25519_test)
+target_link_libraries(spake25519_test crypto)
+add_dependencies(all_tests spake25519_test)
diff --git a/src/crypto/curve25519/asm/x25519-asm-arm.S b/src/crypto/curve25519/asm/x25519-asm-arm.S
index 60d08dd..3af1dba 100644
--- a/src/crypto/curve25519/asm/x25519-asm-arm.S
+++ b/src/crypto/curve25519/asm/x25519-asm-arm.S
@@ -17,6 +17,9 @@
  * domain licensed but the standard ISC license is included above to keep
  * licensing simple. */
 
+#if !defined(OPENSSL_NO_ASM)
+#if defined(__arm__)
+
 .fpu neon
 .text
 .align 4
@@ -2116,3 +2119,6 @@
 mov sp,r12
 vpop {q4,q5,q6,q7}
 bx lr
+
+#endif  /* __arm__ */
+#endif  /* !OPENSSL_NO_ASM */
diff --git a/src/crypto/curve25519/asm/x25519-asm-x86_64.S b/src/crypto/curve25519/asm/x25519-asm-x86_64.S
index 7e86a23..18041d0 100644
--- a/src/crypto/curve25519/asm/x25519-asm-x86_64.S
+++ b/src/crypto/curve25519/asm/x25519-asm-x86_64.S
@@ -17,6 +17,9 @@
  * domain licensed but the standard ISC license is included above to keep
  * licensing simple. */
 
+#if !defined(OPENSSL_NO_ASM)
+#if defined(__x86_64__)
+
 .data
 .p2align 4
 
@@ -57,17 +60,10 @@
 .globl C_ABI(x25519_x86_64_freeze)
 HIDDEN C_ABI(x25519_x86_64_freeze)
 C_ABI(x25519_x86_64_freeze):
-mov %rsp,%r11
-and $31,%r11
-add $64,%r11
-sub %r11,%rsp
-movq %r11,0(%rsp)
-movq %r12,8(%rsp)
-movq %r13,16(%rsp)
-movq %r14,24(%rsp)
-movq %r15,32(%rsp)
-movq %rbx,40(%rsp)
-movq %rbp,48(%rsp)
+.cfi_startproc
+/* This is a leaf function and uses the redzone for saving registers. */
+movq %r12,-8(%rsp)
+.cfi_rel_offset r12, -8
 movq   0(%rdi),%rsi
 movq   8(%rdi),%rdx
 movq   16(%rdi),%rcx
@@ -125,44 +121,38 @@
 movq   %rcx,16(%rdi)
 movq   %r8,24(%rdi)
 movq   %r9,32(%rdi)
-movq 0(%rsp),%r11
-movq 8(%rsp),%r12
-movq 16(%rsp),%r13
-movq 24(%rsp),%r14
-movq 32(%rsp),%r15
-movq 40(%rsp),%rbx
-movq 48(%rsp),%rbp
-add %r11,%rsp
-mov %rdi,%rax
-mov %rsi,%rdx
+movq -8(%rsp),%r12
 ret
+.cfi_endproc
 
 .p2align 5
 .globl C_ABI(x25519_x86_64_mul)
 HIDDEN C_ABI(x25519_x86_64_mul)
 C_ABI(x25519_x86_64_mul):
-mov %rsp,%r11
-and $31,%r11
-add $96,%r11
-sub %r11,%rsp
-movq %r11,0(%rsp)
-movq %r12,8(%rsp)
-movq %r13,16(%rsp)
-movq %r14,24(%rsp)
-movq %r15,32(%rsp)
-movq %rbx,40(%rsp)
-movq %rbp,48(%rsp)
-movq %rdi,56(%rsp)
+.cfi_startproc
+/* This is a leaf function and uses the redzone for saving registers. */
+movq %r12,-8(%rsp)
+.cfi_rel_offset r12, -8
+movq %r13,-16(%rsp)
+.cfi_rel_offset r13, -16
+movq %r14,-24(%rsp)
+.cfi_rel_offset r14, -24
+movq %r15,-32(%rsp)
+.cfi_rel_offset r15, -32
+movq %rbx,-40(%rsp)
+.cfi_rel_offset rbx, -40
+movq %rbp,-48(%rsp)
+.cfi_rel_offset rbp, -48
 mov  %rdx,%rcx
 movq   24(%rsi),%rdx
 imulq  $19,%rdx,%rax
-movq %rax,64(%rsp)
+movq %rax,-64(%rsp)
 mulq  16(%rcx)
 mov  %rax,%r8
 mov  %rdx,%r9
 movq   32(%rsi),%rdx
 imulq  $19,%rdx,%rax
-movq %rax,72(%rsp)
+movq %rax,-72(%rsp)
 mulq  8(%rcx)
 add  %rax,%r8
 adc %rdx,%r9
@@ -237,11 +227,11 @@
 mulq  8(%rcx)
 add  %rax,%rbx
 adc %rdx,%rbp
-movq 64(%rsp),%rax
+movq -64(%rsp),%rax
 mulq  24(%rcx)
 add  %rax,%r10
 adc %rdx,%r11
-movq 64(%rsp),%rax
+movq -64(%rsp),%rax
 mulq  32(%rcx)
 add  %rax,%r12
 adc %rdx,%r13
@@ -249,15 +239,15 @@
 mulq  0(%rcx)
 add  %rax,%rbx
 adc %rdx,%rbp
-movq 72(%rsp),%rax
+movq -72(%rsp),%rax
 mulq  16(%rcx)
 add  %rax,%r10
 adc %rdx,%r11
-movq 72(%rsp),%rax
+movq -72(%rsp),%rax
 mulq  24(%rcx)
 add  %rax,%r12
 adc %rdx,%r13
-movq 72(%rsp),%rax
+movq -72(%rsp),%rax
 mulq  32(%rcx)
 add  %rax,%r14
 adc %rdx,%r15
@@ -304,33 +294,31 @@
 movq   %r9,16(%rdi)
 movq   %rax,24(%rdi)
 movq   %r10,32(%rdi)
-movq 0(%rsp),%r11
-movq 8(%rsp),%r12
-movq 16(%rsp),%r13
-movq 24(%rsp),%r14
-movq 32(%rsp),%r15
-movq 40(%rsp),%rbx
-movq 48(%rsp),%rbp
-add %r11,%rsp
-mov %rdi,%rax
-mov %rsi,%rdx
+movq -8(%rsp),%r12
+movq -16(%rsp),%r13
+movq -24(%rsp),%r14
+movq -32(%rsp),%r15
+movq -40(%rsp),%rbx
+movq -48(%rsp),%rbp
 ret
+.cfi_endproc
 
 .p2align 5
 .globl C_ABI(x25519_x86_64_square)
 HIDDEN C_ABI(x25519_x86_64_square)
 C_ABI(x25519_x86_64_square):
-mov %rsp,%r11
-and $31,%r11
-add $64,%r11
-sub %r11,%rsp
-movq %r11,0(%rsp)
-movq %r12,8(%rsp)
-movq %r13,16(%rsp)
-movq %r14,24(%rsp)
-movq %r15,32(%rsp)
-movq %rbx,40(%rsp)
-movq %rbp,48(%rsp)
+.cfi_startproc
+/* This is a leaf function and uses the redzone for saving registers. */
+movq %r12,-8(%rsp)
+.cfi_rel_offset r12, -8
+movq %r13,-16(%rsp)
+.cfi_rel_offset r13, -16
+movq %r14,-24(%rsp)
+.cfi_rel_offset r14, -24
+movq %r15,-32(%rsp)
+.cfi_rel_offset r15, -32
+movq %rbx,-40(%rsp)
+.cfi_rel_offset rbx, -40
 movq   0(%rsi),%rax
 mulq  0(%rsi)
 mov  %rax,%rcx
@@ -446,33 +434,33 @@
 movq   %r9,16(%rdi)
 movq   %rax,24(%rdi)
 movq   %r10,32(%rdi)
-movq 0(%rsp),%r11
-movq 8(%rsp),%r12
-movq 16(%rsp),%r13
-movq 24(%rsp),%r14
-movq 32(%rsp),%r15
-movq 40(%rsp),%rbx
-movq 48(%rsp),%rbp
-add %r11,%rsp
-mov %rdi,%rax
-mov %rsi,%rdx
+movq -8(%rsp),%r12
+movq -16(%rsp),%r13
+movq -24(%rsp),%r14
+movq -32(%rsp),%r15
+movq -40(%rsp),%rbx
 ret
+.cfi_endproc
 
 .p2align 5
 .globl C_ABI(x25519_x86_64_ladderstep)
 HIDDEN C_ABI(x25519_x86_64_ladderstep)
 C_ABI(x25519_x86_64_ladderstep):
-mov %rsp,%r11
-and $31,%r11
-add $352,%r11
-sub %r11,%rsp
-movq %r11,0(%rsp)
-movq %r12,8(%rsp)
-movq %r13,16(%rsp)
-movq %r14,24(%rsp)
-movq %r15,32(%rsp)
-movq %rbx,40(%rsp)
-movq %rbp,48(%rsp)
+.cfi_startproc
+sub $344,%rsp
+.cfi_adjust_cfa_offset 344
+movq %r12,296(%rsp)
+.cfi_rel_offset r12, 296
+movq %r13,304(%rsp)
+.cfi_rel_offset r13, 304
+movq %r14,312(%rsp)
+.cfi_rel_offset r14, 312
+movq %r15,320(%rsp)
+.cfi_rel_offset r15, 320
+movq %rbx,328(%rsp)
+.cfi_rel_offset rbx, 328
+movq %rbp,336(%rsp)
+.cfi_rel_offset rbp, 336
 movq   40(%rdi),%rsi
 movq   48(%rdi),%rdx
 movq   56(%rdi),%rcx
@@ -498,201 +486,86 @@
 subq 96(%rdi),%r11
 subq 104(%rdi),%r12
 subq 112(%rdi),%r13
-movq %rsi,56(%rsp)
-movq %rdx,64(%rsp)
-movq %rcx,72(%rsp)
-movq %r8,80(%rsp)
-movq %r9,88(%rsp)
-movq %rax,96(%rsp)
-movq %r10,104(%rsp)
-movq %r11,112(%rsp)
-movq %r12,120(%rsp)
-movq %r13,128(%rsp)
-movq 96(%rsp),%rax
-mulq  96(%rsp)
+movq %rsi,0(%rsp)
+movq %rdx,8(%rsp)
+movq %rcx,16(%rsp)
+movq %r8,24(%rsp)
+movq %r9,32(%rsp)
+movq %rax,40(%rsp)
+movq %r10,48(%rsp)
+movq %r11,56(%rsp)
+movq %r12,64(%rsp)
+movq %r13,72(%rsp)
+movq 40(%rsp),%rax
+mulq  40(%rsp)
 mov  %rax,%rsi
 mov  %rdx,%rcx
-movq 96(%rsp),%rax
+movq 40(%rsp),%rax
 shl  $1,%rax
-mulq  104(%rsp)
+mulq  48(%rsp)
 mov  %rax,%r8
 mov  %rdx,%r9
-movq 96(%rsp),%rax
+movq 40(%rsp),%rax
 shl  $1,%rax
-mulq  112(%rsp)
+mulq  56(%rsp)
 mov  %rax,%r10
 mov  %rdx,%r11
-movq 96(%rsp),%rax
+movq 40(%rsp),%rax
 shl  $1,%rax
-mulq  120(%rsp)
+mulq  64(%rsp)
 mov  %rax,%r12
 mov  %rdx,%r13
-movq 96(%rsp),%rax
+movq 40(%rsp),%rax
 shl  $1,%rax
-mulq  128(%rsp)
+mulq  72(%rsp)
 mov  %rax,%r14
 mov  %rdx,%r15
-movq 104(%rsp),%rax
-mulq  104(%rsp)
+movq 48(%rsp),%rax
+mulq  48(%rsp)
 add  %rax,%r10
 adc %rdx,%r11
-movq 104(%rsp),%rax
+movq 48(%rsp),%rax
 shl  $1,%rax
-mulq  112(%rsp)
+mulq  56(%rsp)
 add  %rax,%r12
 adc %rdx,%r13
-movq 104(%rsp),%rax
+movq 48(%rsp),%rax
 shl  $1,%rax
-mulq  120(%rsp)
+mulq  64(%rsp)
 add  %rax,%r14
 adc %rdx,%r15
-movq 104(%rsp),%rdx
+movq 48(%rsp),%rdx
 imulq  $38,%rdx,%rax
-mulq  128(%rsp)
+mulq  72(%rsp)
 add  %rax,%rsi
 adc %rdx,%rcx
-movq 112(%rsp),%rax
-mulq  112(%rsp)
-add  %rax,%r14
-adc %rdx,%r15
-movq 112(%rsp),%rdx
-imulq  $38,%rdx,%rax
-mulq  120(%rsp)
-add  %rax,%rsi
-adc %rdx,%rcx
-movq 112(%rsp),%rdx
-imulq  $38,%rdx,%rax
-mulq  128(%rsp)
-add  %rax,%r8
-adc %rdx,%r9
-movq 120(%rsp),%rdx
-imulq  $19,%rdx,%rax
-mulq  120(%rsp)
-add  %rax,%r8
-adc %rdx,%r9
-movq 120(%rsp),%rdx
-imulq  $38,%rdx,%rax
-mulq  128(%rsp)
-add  %rax,%r10
-adc %rdx,%r11
-movq 128(%rsp),%rdx
-imulq  $19,%rdx,%rax
-mulq  128(%rsp)
-add  %rax,%r12
-adc %rdx,%r13
-movq x25519_x86_64_REDMASK51(%rip),%rdx
-shld $13,%rsi,%rcx
-and  %rdx,%rsi
-shld $13,%r8,%r9
-and  %rdx,%r8
-add  %rcx,%r8
-shld $13,%r10,%r11
-and  %rdx,%r10
-add  %r9,%r10
-shld $13,%r12,%r13
-and  %rdx,%r12
-add  %r11,%r12
-shld $13,%r14,%r15
-and  %rdx,%r14
-add  %r13,%r14
-imulq  $19,%r15,%rcx
-add  %rcx,%rsi
-mov  %rsi,%rcx
-shr  $51,%rcx
-add  %r8,%rcx
-and  %rdx,%rsi
-mov  %rcx,%r8
-shr  $51,%rcx
-add  %r10,%rcx
-and  %rdx,%r8
-mov  %rcx,%r9
-shr  $51,%rcx
-add  %r12,%rcx
-and  %rdx,%r9
-mov  %rcx,%rax
-shr  $51,%rcx
-add  %r14,%rcx
-and  %rdx,%rax
-mov  %rcx,%r10
-shr  $51,%rcx
-imulq  $19,%rcx,%rcx
-add  %rcx,%rsi
-and  %rdx,%r10
-movq %rsi,136(%rsp)
-movq %r8,144(%rsp)
-movq %r9,152(%rsp)
-movq %rax,160(%rsp)
-movq %r10,168(%rsp)
 movq 56(%rsp),%rax
 mulq  56(%rsp)
-mov  %rax,%rsi
-mov  %rdx,%rcx
-movq 56(%rsp),%rax
-shl  $1,%rax
-mulq  64(%rsp)
-mov  %rax,%r8
-mov  %rdx,%r9
-movq 56(%rsp),%rax
-shl  $1,%rax
-mulq  72(%rsp)
-mov  %rax,%r10
-mov  %rdx,%r11
-movq 56(%rsp),%rax
-shl  $1,%rax
-mulq  80(%rsp)
-mov  %rax,%r12
-mov  %rdx,%r13
-movq 56(%rsp),%rax
-shl  $1,%rax
-mulq  88(%rsp)
-mov  %rax,%r14
-mov  %rdx,%r15
-movq 64(%rsp),%rax
-mulq  64(%rsp)
-add  %rax,%r10
-adc %rdx,%r11
-movq 64(%rsp),%rax
-shl  $1,%rax
-mulq  72(%rsp)
-add  %rax,%r12
-adc %rdx,%r13
-movq 64(%rsp),%rax
-shl  $1,%rax
-mulq  80(%rsp)
 add  %rax,%r14
 adc %rdx,%r15
+movq 56(%rsp),%rdx
+imulq  $38,%rdx,%rax
+mulq  64(%rsp)
+add  %rax,%rsi
+adc %rdx,%rcx
+movq 56(%rsp),%rdx
+imulq  $38,%rdx,%rax
+mulq  72(%rsp)
+add  %rax,%r8
+adc %rdx,%r9
+movq 64(%rsp),%rdx
+imulq  $19,%rdx,%rax
+mulq  64(%rsp)
+add  %rax,%r8
+adc %rdx,%r9
 movq 64(%rsp),%rdx
 imulq  $38,%rdx,%rax
-mulq  88(%rsp)
-add  %rax,%rsi
-adc %rdx,%rcx
-movq 72(%rsp),%rax
 mulq  72(%rsp)
-add  %rax,%r14
-adc %rdx,%r15
-movq 72(%rsp),%rdx
-imulq  $38,%rdx,%rax
-mulq  80(%rsp)
-add  %rax,%rsi
-adc %rdx,%rcx
-movq 72(%rsp),%rdx
-imulq  $38,%rdx,%rax
-mulq  88(%rsp)
-add  %rax,%r8
-adc %rdx,%r9
-movq 80(%rsp),%rdx
-imulq  $19,%rdx,%rax
-mulq  80(%rsp)
-add  %rax,%r8
-adc %rdx,%r9
-movq 80(%rsp),%rdx
-imulq  $38,%rdx,%rax
-mulq  88(%rsp)
 add  %rax,%r10
 adc %rdx,%r11
-movq 88(%rsp),%rdx
+movq 72(%rsp),%rdx
 imulq  $19,%rdx,%rax
-mulq  88(%rsp)
+mulq  72(%rsp)
 add  %rax,%r12
 adc %rdx,%r13
 movq x25519_x86_64_REDMASK51(%rip),%rdx
@@ -733,11 +606,126 @@
 imulq  $19,%rcx,%rcx
 add  %rcx,%rsi
 and  %rdx,%r10
-movq %rsi,176(%rsp)
-movq %r8,184(%rsp)
-movq %r9,192(%rsp)
-movq %rax,200(%rsp)
-movq %r10,208(%rsp)
+movq %rsi,80(%rsp)
+movq %r8,88(%rsp)
+movq %r9,96(%rsp)
+movq %rax,104(%rsp)
+movq %r10,112(%rsp)
+movq 0(%rsp),%rax
+mulq  0(%rsp)
+mov  %rax,%rsi
+mov  %rdx,%rcx
+movq 0(%rsp),%rax
+shl  $1,%rax
+mulq  8(%rsp)
+mov  %rax,%r8
+mov  %rdx,%r9
+movq 0(%rsp),%rax
+shl  $1,%rax
+mulq  16(%rsp)
+mov  %rax,%r10
+mov  %rdx,%r11
+movq 0(%rsp),%rax
+shl  $1,%rax
+mulq  24(%rsp)
+mov  %rax,%r12
+mov  %rdx,%r13
+movq 0(%rsp),%rax
+shl  $1,%rax
+mulq  32(%rsp)
+mov  %rax,%r14
+mov  %rdx,%r15
+movq 8(%rsp),%rax
+mulq  8(%rsp)
+add  %rax,%r10
+adc %rdx,%r11
+movq 8(%rsp),%rax
+shl  $1,%rax
+mulq  16(%rsp)
+add  %rax,%r12
+adc %rdx,%r13
+movq 8(%rsp),%rax
+shl  $1,%rax
+mulq  24(%rsp)
+add  %rax,%r14
+adc %rdx,%r15
+movq 8(%rsp),%rdx
+imulq  $38,%rdx,%rax
+mulq  32(%rsp)
+add  %rax,%rsi
+adc %rdx,%rcx
+movq 16(%rsp),%rax
+mulq  16(%rsp)
+add  %rax,%r14
+adc %rdx,%r15
+movq 16(%rsp),%rdx
+imulq  $38,%rdx,%rax
+mulq  24(%rsp)
+add  %rax,%rsi
+adc %rdx,%rcx
+movq 16(%rsp),%rdx
+imulq  $38,%rdx,%rax
+mulq  32(%rsp)
+add  %rax,%r8
+adc %rdx,%r9
+movq 24(%rsp),%rdx
+imulq  $19,%rdx,%rax
+mulq  24(%rsp)
+add  %rax,%r8
+adc %rdx,%r9
+movq 24(%rsp),%rdx
+imulq  $38,%rdx,%rax
+mulq  32(%rsp)
+add  %rax,%r10
+adc %rdx,%r11
+movq 32(%rsp),%rdx
+imulq  $19,%rdx,%rax
+mulq  32(%rsp)
+add  %rax,%r12
+adc %rdx,%r13
+movq x25519_x86_64_REDMASK51(%rip),%rdx
+shld $13,%rsi,%rcx
+and  %rdx,%rsi
+shld $13,%r8,%r9
+and  %rdx,%r8
+add  %rcx,%r8
+shld $13,%r10,%r11
+and  %rdx,%r10
+add  %r9,%r10
+shld $13,%r12,%r13
+and  %rdx,%r12
+add  %r11,%r12
+shld $13,%r14,%r15
+and  %rdx,%r14
+add  %r13,%r14
+imulq  $19,%r15,%rcx
+add  %rcx,%rsi
+mov  %rsi,%rcx
+shr  $51,%rcx
+add  %r8,%rcx
+and  %rdx,%rsi
+mov  %rcx,%r8
+shr  $51,%rcx
+add  %r10,%rcx
+and  %rdx,%r8
+mov  %rcx,%r9
+shr  $51,%rcx
+add  %r12,%rcx
+and  %rdx,%r9
+mov  %rcx,%rax
+shr  $51,%rcx
+add  %r14,%rcx
+and  %rdx,%rax
+mov  %rcx,%r10
+shr  $51,%rcx
+imulq  $19,%rcx,%rcx
+add  %rcx,%rsi
+and  %rdx,%r10
+movq %rsi,120(%rsp)
+movq %r8,128(%rsp)
+movq %r9,136(%rsp)
+movq %rax,144(%rsp)
+movq %r10,152(%rsp)
 mov  %rsi,%rsi
 mov  %r8,%rdx
 mov  %r9,%rcx
@@ -748,16 +736,16 @@
 add  x25519_x86_64_2P1234(%rip),%rcx
 add  x25519_x86_64_2P1234(%rip),%r8
 add  x25519_x86_64_2P1234(%rip),%r9
-subq 136(%rsp),%rsi
-subq 144(%rsp),%rdx
-subq 152(%rsp),%rcx
-subq 160(%rsp),%r8
-subq 168(%rsp),%r9
-movq %rsi,216(%rsp)
-movq %rdx,224(%rsp)
-movq %rcx,232(%rsp)
-movq %r8,240(%rsp)
-movq %r9,248(%rsp)
+subq 80(%rsp),%rsi
+subq 88(%rsp),%rdx
+subq 96(%rsp),%rcx
+subq 104(%rsp),%r8
+subq 112(%rsp),%r9
+movq %rsi,160(%rsp)
+movq %rdx,168(%rsp)
+movq %rcx,176(%rsp)
+movq %r8,184(%rsp)
+movq %r9,192(%rsp)
 movq   120(%rdi),%rsi
 movq   128(%rdi),%rdx
 movq   136(%rdi),%rcx
@@ -783,121 +771,121 @@
 subq 176(%rdi),%r11
 subq 184(%rdi),%r12
 subq 192(%rdi),%r13
-movq %rsi,256(%rsp)
-movq %rdx,264(%rsp)
-movq %rcx,272(%rsp)
-movq %r8,280(%rsp)
-movq %r9,288(%rsp)
-movq %rax,296(%rsp)
-movq %r10,304(%rsp)
-movq %r11,312(%rsp)
-movq %r12,320(%rsp)
-movq %r13,328(%rsp)
-movq 280(%rsp),%rsi
+movq %rsi,200(%rsp)
+movq %rdx,208(%rsp)
+movq %rcx,216(%rsp)
+movq %r8,224(%rsp)
+movq %r9,232(%rsp)
+movq %rax,240(%rsp)
+movq %r10,248(%rsp)
+movq %r11,256(%rsp)
+movq %r12,264(%rsp)
+movq %r13,272(%rsp)
+movq 224(%rsp),%rsi
 imulq  $19,%rsi,%rax
-movq %rax,336(%rsp)
-mulq  112(%rsp)
+movq %rax,280(%rsp)
+mulq  56(%rsp)
 mov  %rax,%rsi
 mov  %rdx,%rcx
-movq 288(%rsp),%rdx
+movq 232(%rsp),%rdx
 imulq  $19,%rdx,%rax
-movq %rax,344(%rsp)
-mulq  104(%rsp)
+movq %rax,288(%rsp)
+mulq  48(%rsp)
 add  %rax,%rsi
 adc %rdx,%rcx
-movq 256(%rsp),%rax
-mulq  96(%rsp)
+movq 200(%rsp),%rax
+mulq  40(%rsp)
 add  %rax,%rsi
 adc %rdx,%rcx
-movq 256(%rsp),%rax
-mulq  104(%rsp)
+movq 200(%rsp),%rax
+mulq  48(%rsp)
 mov  %rax,%r8
 mov  %rdx,%r9
-movq 256(%rsp),%rax
-mulq  112(%rsp)
+movq 200(%rsp),%rax
+mulq  56(%rsp)
 mov  %rax,%r10
 mov  %rdx,%r11
-movq 256(%rsp),%rax
-mulq  120(%rsp)
+movq 200(%rsp),%rax
+mulq  64(%rsp)
 mov  %rax,%r12
 mov  %rdx,%r13
-movq 256(%rsp),%rax
-mulq  128(%rsp)
+movq 200(%rsp),%rax
+mulq  72(%rsp)
 mov  %rax,%r14
 mov  %rdx,%r15
-movq 264(%rsp),%rax
-mulq  96(%rsp)
+movq 208(%rsp),%rax
+mulq  40(%rsp)
 add  %rax,%r8
 adc %rdx,%r9
-movq 264(%rsp),%rax
-mulq  104(%rsp)
+movq 208(%rsp),%rax
+mulq  48(%rsp)
 add  %rax,%r10
 adc %rdx,%r11
-movq 264(%rsp),%rax
-mulq  112(%rsp)
+movq 208(%rsp),%rax
+mulq  56(%rsp)
 add  %rax,%r12
 adc %rdx,%r13
-movq 264(%rsp),%rax
-mulq  120(%rsp)
+movq 208(%rsp),%rax
+mulq  64(%rsp)
 add  %rax,%r14
 adc %rdx,%r15
-movq 264(%rsp),%rdx
+movq 208(%rsp),%rdx
 imulq  $19,%rdx,%rax
-mulq  128(%rsp)
+mulq  72(%rsp)
 add  %rax,%rsi
 adc %rdx,%rcx
-movq 272(%rsp),%rax
-mulq  96(%rsp)
+movq 216(%rsp),%rax
+mulq  40(%rsp)
 add  %rax,%r10
 adc %rdx,%r11
-movq 272(%rsp),%rax
-mulq  104(%rsp)
+movq 216(%rsp),%rax
+mulq  48(%rsp)
 add  %rax,%r12
 adc %rdx,%r13
-movq 272(%rsp),%rax
-mulq  112(%rsp)
+movq 216(%rsp),%rax
+mulq  56(%rsp)
 add  %rax,%r14
 adc %rdx,%r15
-movq 272(%rsp),%rdx
+movq 216(%rsp),%rdx
 imulq  $19,%rdx,%rax
-mulq  120(%rsp)
+mulq  64(%rsp)
 add  %rax,%rsi
 adc %rdx,%rcx
-movq 272(%rsp),%rdx
+movq 216(%rsp),%rdx
 imulq  $19,%rdx,%rax
-mulq  128(%rsp)
+mulq  72(%rsp)
+add  %rax,%r8
+adc %rdx,%r9
+movq 224(%rsp),%rax
+mulq  40(%rsp)
+add  %rax,%r12
+adc %rdx,%r13
+movq 224(%rsp),%rax
+mulq  48(%rsp)
+add  %rax,%r14
+adc %rdx,%r15
+movq 280(%rsp),%rax
+mulq  64(%rsp)
 add  %rax,%r8
 adc %rdx,%r9
 movq 280(%rsp),%rax
-mulq  96(%rsp)
-add  %rax,%r12
-adc %rdx,%r13
-movq 280(%rsp),%rax
-mulq  104(%rsp)
+mulq  72(%rsp)
+add  %rax,%r10
+adc %rdx,%r11
+movq 232(%rsp),%rax
+mulq  40(%rsp)
 add  %rax,%r14
 adc %rdx,%r15
-movq 336(%rsp),%rax
-mulq  120(%rsp)
+movq 288(%rsp),%rax
+mulq  56(%rsp)
 add  %rax,%r8
 adc %rdx,%r9
-movq 336(%rsp),%rax
-mulq  128(%rsp)
+movq 288(%rsp),%rax
+mulq  64(%rsp)
 add  %rax,%r10
 adc %rdx,%r11
 movq 288(%rsp),%rax
-mulq  96(%rsp)
-add  %rax,%r14
-adc %rdx,%r15
-movq 344(%rsp),%rax
-mulq  112(%rsp)
-add  %rax,%r8
-adc %rdx,%r9
-movq 344(%rsp),%rax
-mulq  120(%rsp)
-add  %rax,%r10
-adc %rdx,%r11
-movq 344(%rsp),%rax
-mulq  128(%rsp)
+mulq  72(%rsp)
 add  %rax,%r12
 adc %rdx,%r13
 movq x25519_x86_64_REDMASK51(%rip),%rdx
@@ -938,116 +926,116 @@
 imulq  $19,%rcx,%rcx
 add  %rcx,%rsi
 and  %rdx,%r10
-movq %rsi,96(%rsp)
-movq %r8,104(%rsp)
-movq %r9,112(%rsp)
-movq %rax,120(%rsp)
-movq %r10,128(%rsp)
-movq 320(%rsp),%rsi
+movq %rsi,40(%rsp)
+movq %r8,48(%rsp)
+movq %r9,56(%rsp)
+movq %rax,64(%rsp)
+movq %r10,72(%rsp)
+movq 264(%rsp),%rsi
 imulq  $19,%rsi,%rax
-movq %rax,256(%rsp)
-mulq  72(%rsp)
+movq %rax,200(%rsp)
+mulq  16(%rsp)
 mov  %rax,%rsi
 mov  %rdx,%rcx
-movq 328(%rsp),%rdx
+movq 272(%rsp),%rdx
 imulq  $19,%rdx,%rax
-movq %rax,264(%rsp)
-mulq  64(%rsp)
+movq %rax,208(%rsp)
+mulq  8(%rsp)
 add  %rax,%rsi
 adc %rdx,%rcx
-movq 296(%rsp),%rax
-mulq  56(%rsp)
+movq 240(%rsp),%rax
+mulq  0(%rsp)
 add  %rax,%rsi
 adc %rdx,%rcx
-movq 296(%rsp),%rax
-mulq  64(%rsp)
+movq 240(%rsp),%rax
+mulq  8(%rsp)
 mov  %rax,%r8
 mov  %rdx,%r9
-movq 296(%rsp),%rax
-mulq  72(%rsp)
+movq 240(%rsp),%rax
+mulq  16(%rsp)
 mov  %rax,%r10
 mov  %rdx,%r11
-movq 296(%rsp),%rax
-mulq  80(%rsp)
+movq 240(%rsp),%rax
+mulq  24(%rsp)
 mov  %rax,%r12
 mov  %rdx,%r13
-movq 296(%rsp),%rax
-mulq  88(%rsp)
+movq 240(%rsp),%rax
+mulq  32(%rsp)
 mov  %rax,%r14
 mov  %rdx,%r15
-movq 304(%rsp),%rax
-mulq  56(%rsp)
+movq 248(%rsp),%rax
+mulq  0(%rsp)
 add  %rax,%r8
 adc %rdx,%r9
-movq 304(%rsp),%rax
-mulq  64(%rsp)
+movq 248(%rsp),%rax
+mulq  8(%rsp)
 add  %rax,%r10
 adc %rdx,%r11
-movq 304(%rsp),%rax
-mulq  72(%rsp)
+movq 248(%rsp),%rax
+mulq  16(%rsp)
 add  %rax,%r12
 adc %rdx,%r13
-movq 304(%rsp),%rax
-mulq  80(%rsp)
+movq 248(%rsp),%rax
+mulq  24(%rsp)
 add  %rax,%r14
 adc %rdx,%r15
-movq 304(%rsp),%rdx
+movq 248(%rsp),%rdx
 imulq  $19,%rdx,%rax
-mulq  88(%rsp)
+mulq  32(%rsp)
 add  %rax,%rsi
 adc %rdx,%rcx
-movq 312(%rsp),%rax
-mulq  56(%rsp)
+movq 256(%rsp),%rax
+mulq  0(%rsp)
 add  %rax,%r10
 adc %rdx,%r11
-movq 312(%rsp),%rax
-mulq  64(%rsp)
+movq 256(%rsp),%rax
+mulq  8(%rsp)
 add  %rax,%r12
 adc %rdx,%r13
-movq 312(%rsp),%rax
-mulq  72(%rsp)
+movq 256(%rsp),%rax
+mulq  16(%rsp)
 add  %rax,%r14
 adc %rdx,%r15
-movq 312(%rsp),%rdx
+movq 256(%rsp),%rdx
 imulq  $19,%rdx,%rax
-mulq  80(%rsp)
+mulq  24(%rsp)
 add  %rax,%rsi
 adc %rdx,%rcx
-movq 312(%rsp),%rdx
+movq 256(%rsp),%rdx
 imulq  $19,%rdx,%rax
-mulq  88(%rsp)
+mulq  32(%rsp)
 add  %rax,%r8
 adc %rdx,%r9
-movq 320(%rsp),%rax
-mulq  56(%rsp)
+movq 264(%rsp),%rax
+mulq  0(%rsp)
 add  %rax,%r12
 adc %rdx,%r13
-movq 320(%rsp),%rax
-mulq  64(%rsp)
+movq 264(%rsp),%rax
+mulq  8(%rsp)
 add  %rax,%r14
 adc %rdx,%r15
-movq 256(%rsp),%rax
-mulq  80(%rsp)
+movq 200(%rsp),%rax
+mulq  24(%rsp)
 add  %rax,%r8
 adc %rdx,%r9
-movq 256(%rsp),%rax
-mulq  88(%rsp)
+movq 200(%rsp),%rax
+mulq  32(%rsp)
 add  %rax,%r10
 adc %rdx,%r11
-movq 328(%rsp),%rax
-mulq  56(%rsp)
+movq 272(%rsp),%rax
+mulq  0(%rsp)
 add  %rax,%r14
 adc %rdx,%r15
-movq 264(%rsp),%rax
-mulq  72(%rsp)
+movq 208(%rsp),%rax
+mulq  16(%rsp)
 add  %rax,%r8
 adc %rdx,%r9
-movq 264(%rsp),%rax
-mulq  80(%rsp)
+movq 208(%rsp),%rax
+mulq  24(%rsp)
 add  %rax,%r10
 adc %rdx,%r11
-movq 264(%rsp),%rax
-mulq  88(%rsp)
+movq 208(%rsp),%rax
+mulq  32(%rsp)
 add  %rax,%r12
 adc %rdx,%r13
 movq x25519_x86_64_REDMASK51(%rip),%rdx
@@ -1098,16 +1086,16 @@
 add  x25519_x86_64_2P1234(%rip),%r11
 add  x25519_x86_64_2P1234(%rip),%r12
 add  x25519_x86_64_2P1234(%rip),%r13
-addq 96(%rsp),%rsi
-addq 104(%rsp),%r8
-addq 112(%rsp),%r9
-addq 120(%rsp),%rax
-addq 128(%rsp),%r10
-subq 96(%rsp),%rdx
-subq 104(%rsp),%rcx
-subq 112(%rsp),%r11
-subq 120(%rsp),%r12
-subq 128(%rsp),%r13
+addq 40(%rsp),%rsi
+addq 48(%rsp),%r8
+addq 56(%rsp),%r9
+addq 64(%rsp),%rax
+addq 72(%rsp),%r10
+subq 40(%rsp),%rdx
+subq 48(%rsp),%rcx
+subq 56(%rsp),%r11
+subq 64(%rsp),%r12
+subq 72(%rsp),%r13
 movq   %rsi,120(%rdi)
 movq   %r8,128(%rdi)
 movq   %r9,136(%rdi)
@@ -1350,13 +1338,13 @@
 movq   %r10,192(%rdi)
 movq   184(%rdi),%rsi
 imulq  $19,%rsi,%rax
-movq %rax,56(%rsp)
+movq %rax,0(%rsp)
 mulq  16(%rdi)
 mov  %rax,%rsi
 mov  %rdx,%rcx
 movq   192(%rdi),%rdx
 imulq  $19,%rdx,%rax
-movq %rax,64(%rsp)
+movq %rax,8(%rsp)
 mulq  8(%rdi)
 add  %rax,%rsi
 adc %rdx,%rcx
@@ -1431,11 +1419,11 @@
 mulq  8(%rdi)
 add  %rax,%r14
 adc %rdx,%r15
-movq 56(%rsp),%rax
+movq 0(%rsp),%rax
 mulq  24(%rdi)
 add  %rax,%r8
 adc %rdx,%r9
-movq 56(%rsp),%rax
+movq 0(%rsp),%rax
 mulq  32(%rdi)
 add  %rax,%r10
 adc %rdx,%r11
@@ -1443,15 +1431,15 @@
 mulq  0(%rdi)
 add  %rax,%r14
 adc %rdx,%r15
-movq 64(%rsp),%rax
+movq 8(%rsp),%rax
 mulq  16(%rdi)
 add  %rax,%r8
 adc %rdx,%r9
-movq 64(%rsp),%rax
+movq 8(%rsp),%rax
 mulq  24(%rdi)
 add  %rax,%r10
 adc %rdx,%r11
-movq 64(%rsp),%rax
+movq 8(%rsp),%rax
 mulq  32(%rdi)
 add  %rax,%r12
 adc %rdx,%r13
@@ -1498,111 +1486,111 @@
 movq   %r9,176(%rdi)
 movq   %rax,184(%rdi)
 movq   %r10,192(%rdi)
-movq 200(%rsp),%rsi
+movq 144(%rsp),%rsi
 imulq  $19,%rsi,%rax
-movq %rax,56(%rsp)
-mulq  152(%rsp)
+movq %rax,0(%rsp)
+mulq  96(%rsp)
 mov  %rax,%rsi
 mov  %rdx,%rcx
-movq 208(%rsp),%rdx
+movq 152(%rsp),%rdx
 imulq  $19,%rdx,%rax
-movq %rax,64(%rsp)
-mulq  144(%rsp)
+movq %rax,8(%rsp)
+mulq  88(%rsp)
 add  %rax,%rsi
 adc %rdx,%rcx
-movq 176(%rsp),%rax
-mulq  136(%rsp)
+movq 120(%rsp),%rax
+mulq  80(%rsp)
 add  %rax,%rsi
 adc %rdx,%rcx
-movq 176(%rsp),%rax
-mulq  144(%rsp)
+movq 120(%rsp),%rax
+mulq  88(%rsp)
 mov  %rax,%r8
 mov  %rdx,%r9
-movq 176(%rsp),%rax
-mulq  152(%rsp)
+movq 120(%rsp),%rax
+mulq  96(%rsp)
 mov  %rax,%r10
 mov  %rdx,%r11
-movq 176(%rsp),%rax
-mulq  160(%rsp)
+movq 120(%rsp),%rax
+mulq  104(%rsp)
 mov  %rax,%r12
 mov  %rdx,%r13
-movq 176(%rsp),%rax
-mulq  168(%rsp)
+movq 120(%rsp),%rax
+mulq  112(%rsp)
 mov  %rax,%r14
 mov  %rdx,%r15
-movq 184(%rsp),%rax
-mulq  136(%rsp)
+movq 128(%rsp),%rax
+mulq  80(%rsp)
 add  %rax,%r8
 adc %rdx,%r9
-movq 184(%rsp),%rax
-mulq  144(%rsp)
+movq 128(%rsp),%rax
+mulq  88(%rsp)
 add  %rax,%r10
 adc %rdx,%r11
-movq 184(%rsp),%rax
-mulq  152(%rsp)
+movq 128(%rsp),%rax
+mulq  96(%rsp)
 add  %rax,%r12
 adc %rdx,%r13
-movq 184(%rsp),%rax
-mulq  160(%rsp)
+movq 128(%rsp),%rax
+mulq  104(%rsp)
 add  %rax,%r14
 adc %rdx,%r15
-movq 184(%rsp),%rdx
+movq 128(%rsp),%rdx
 imulq  $19,%rdx,%rax
-mulq  168(%rsp)
+mulq  112(%rsp)
 add  %rax,%rsi
 adc %rdx,%rcx
-movq 192(%rsp),%rax
-mulq  136(%rsp)
+movq 136(%rsp),%rax
+mulq  80(%rsp)
 add  %rax,%r10
 adc %rdx,%r11
-movq 192(%rsp),%rax
-mulq  144(%rsp)
+movq 136(%rsp),%rax
+mulq  88(%rsp)
 add  %rax,%r12
 adc %rdx,%r13
-movq 192(%rsp),%rax
-mulq  152(%rsp)
+movq 136(%rsp),%rax
+mulq  96(%rsp)
 add  %rax,%r14
 adc %rdx,%r15
-movq 192(%rsp),%rdx
+movq 136(%rsp),%rdx
 imulq  $19,%rdx,%rax
-mulq  160(%rsp)
+mulq  104(%rsp)
 add  %rax,%rsi
 adc %rdx,%rcx
-movq 192(%rsp),%rdx
+movq 136(%rsp),%rdx
 imulq  $19,%rdx,%rax
-mulq  168(%rsp)
+mulq  112(%rsp)
 add  %rax,%r8
 adc %rdx,%r9
-movq 200(%rsp),%rax
-mulq  136(%rsp)
+movq 144(%rsp),%rax
+mulq  80(%rsp)
 add  %rax,%r12
 adc %rdx,%r13
-movq 200(%rsp),%rax
-mulq  144(%rsp)
+movq 144(%rsp),%rax
+mulq  88(%rsp)
 add  %rax,%r14
 adc %rdx,%r15
-movq 56(%rsp),%rax
-mulq  160(%rsp)
+movq 0(%rsp),%rax
+mulq  104(%rsp)
 add  %rax,%r8
 adc %rdx,%r9
-movq 56(%rsp),%rax
-mulq  168(%rsp)
+movq 0(%rsp),%rax
+mulq  112(%rsp)
 add  %rax,%r10
 adc %rdx,%r11
-movq 208(%rsp),%rax
-mulq  136(%rsp)
+movq 152(%rsp),%rax
+mulq  80(%rsp)
 add  %rax,%r14
 adc %rdx,%r15
-movq 64(%rsp),%rax
-mulq  152(%rsp)
+movq 8(%rsp),%rax
+mulq  96(%rsp)
 add  %rax,%r8
 adc %rdx,%r9
-movq 64(%rsp),%rax
-mulq  160(%rsp)
+movq 8(%rsp),%rax
+mulq  104(%rsp)
 add  %rax,%r10
 adc %rdx,%r11
-movq 64(%rsp),%rax
-mulq  168(%rsp)
+movq 8(%rsp),%rax
+mulq  112(%rsp)
 add  %rax,%r12
 adc %rdx,%r13
 movq x25519_x86_64_REDMASK51(%rip),%rdx
@@ -1648,37 +1636,37 @@
 movq   %r9,56(%rdi)
 movq   %rax,64(%rdi)
 movq   %r10,72(%rdi)
-movq 216(%rsp),%rax
+movq 160(%rsp),%rax
 mulq  x25519_x86_64_121666_213(%rip)
 shr  $13,%rax
 mov  %rax,%rsi
 mov  %rdx,%rcx
-movq 224(%rsp),%rax
+movq 168(%rsp),%rax
 mulq  x25519_x86_64_121666_213(%rip)
 shr  $13,%rax
 add  %rax,%rcx
 mov  %rdx,%r8
-movq 232(%rsp),%rax
+movq 176(%rsp),%rax
 mulq  x25519_x86_64_121666_213(%rip)
 shr  $13,%rax
 add  %rax,%r8
 mov  %rdx,%r9
-movq 240(%rsp),%rax
+movq 184(%rsp),%rax
 mulq  x25519_x86_64_121666_213(%rip)
 shr  $13,%rax
 add  %rax,%r9
 mov  %rdx,%r10
-movq 248(%rsp),%rax
+movq 192(%rsp),%rax
 mulq  x25519_x86_64_121666_213(%rip)
 shr  $13,%rax
 add  %rax,%r10
 imulq  $19,%rdx,%rdx
 add  %rdx,%rsi
-addq 136(%rsp),%rsi
-addq 144(%rsp),%rcx
-addq 152(%rsp),%r8
-addq 160(%rsp),%r9
-addq 168(%rsp),%r10
+addq 80(%rsp),%rsi
+addq 88(%rsp),%rcx
+addq 96(%rsp),%r8
+addq 104(%rsp),%r9
+addq 112(%rsp),%r10
 movq   %rsi,80(%rdi)
 movq   %rcx,88(%rdi)
 movq   %r8,96(%rdi)
@@ -1686,109 +1674,109 @@
 movq   %r10,112(%rdi)
 movq   104(%rdi),%rsi
 imulq  $19,%rsi,%rax
-movq %rax,56(%rsp)
-mulq  232(%rsp)
+movq %rax,0(%rsp)
+mulq  176(%rsp)
 mov  %rax,%rsi
 mov  %rdx,%rcx
 movq   112(%rdi),%rdx
 imulq  $19,%rdx,%rax
-movq %rax,64(%rsp)
-mulq  224(%rsp)
+movq %rax,8(%rsp)
+mulq  168(%rsp)
 add  %rax,%rsi
 adc %rdx,%rcx
 movq   80(%rdi),%rax
-mulq  216(%rsp)
+mulq  160(%rsp)
 add  %rax,%rsi
 adc %rdx,%rcx
 movq   80(%rdi),%rax
-mulq  224(%rsp)
+mulq  168(%rsp)
 mov  %rax,%r8
 mov  %rdx,%r9
 movq   80(%rdi),%rax
-mulq  232(%rsp)
+mulq  176(%rsp)
 mov  %rax,%r10
 mov  %rdx,%r11
 movq   80(%rdi),%rax
-mulq  240(%rsp)
+mulq  184(%rsp)
 mov  %rax,%r12
 mov  %rdx,%r13
 movq   80(%rdi),%rax
-mulq  248(%rsp)
+mulq  192(%rsp)
 mov  %rax,%r14
 mov  %rdx,%r15
 movq   88(%rdi),%rax
-mulq  216(%rsp)
+mulq  160(%rsp)
 add  %rax,%r8
 adc %rdx,%r9
 movq   88(%rdi),%rax
-mulq  224(%rsp)
+mulq  168(%rsp)
 add  %rax,%r10
 adc %rdx,%r11
 movq   88(%rdi),%rax
-mulq  232(%rsp)
+mulq  176(%rsp)
 add  %rax,%r12
 adc %rdx,%r13
 movq   88(%rdi),%rax
-mulq  240(%rsp)
+mulq  184(%rsp)
 add  %rax,%r14
 adc %rdx,%r15
 movq   88(%rdi),%rdx
 imulq  $19,%rdx,%rax
-mulq  248(%rsp)
+mulq  192(%rsp)
 add  %rax,%rsi
 adc %rdx,%rcx
 movq   96(%rdi),%rax
-mulq  216(%rsp)
+mulq  160(%rsp)
 add  %rax,%r10
 adc %rdx,%r11
 movq   96(%rdi),%rax
-mulq  224(%rsp)
+mulq  168(%rsp)
 add  %rax,%r12
 adc %rdx,%r13
 movq   96(%rdi),%rax
-mulq  232(%rsp)
+mulq  176(%rsp)
 add  %rax,%r14
 adc %rdx,%r15
 movq   96(%rdi),%rdx
 imulq  $19,%rdx,%rax
-mulq  240(%rsp)
+mulq  184(%rsp)
 add  %rax,%rsi
 adc %rdx,%rcx
 movq   96(%rdi),%rdx
 imulq  $19,%rdx,%rax
-mulq  248(%rsp)
+mulq  192(%rsp)
 add  %rax,%r8
 adc %rdx,%r9
 movq   104(%rdi),%rax
-mulq  216(%rsp)
+mulq  160(%rsp)
 add  %rax,%r12
 adc %rdx,%r13
 movq   104(%rdi),%rax
-mulq  224(%rsp)
+mulq  168(%rsp)
 add  %rax,%r14
 adc %rdx,%r15
-movq 56(%rsp),%rax
-mulq  240(%rsp)
+movq 0(%rsp),%rax
+mulq  184(%rsp)
 add  %rax,%r8
 adc %rdx,%r9
-movq 56(%rsp),%rax
-mulq  248(%rsp)
+movq 0(%rsp),%rax
+mulq  192(%rsp)
 add  %rax,%r10
 adc %rdx,%r11
 movq   112(%rdi),%rax
-mulq  216(%rsp)
+mulq  160(%rsp)
 add  %rax,%r14
 adc %rdx,%r15
-movq 64(%rsp),%rax
-mulq  232(%rsp)
+movq 8(%rsp),%rax
+mulq  176(%rsp)
 add  %rax,%r8
 adc %rdx,%r9
-movq 64(%rsp),%rax
-mulq  240(%rsp)
+movq 8(%rsp),%rax
+mulq  184(%rsp)
 add  %rax,%r10
 adc %rdx,%r11
-movq 64(%rsp),%rax
-mulq  248(%rsp)
+movq 8(%rsp),%rax
+mulq  192(%rsp)
 add  %rax,%r12
 adc %rdx,%r13
 movq x25519_x86_64_REDMASK51(%rip),%rdx
@@ -1834,26 +1822,22 @@
 movq   %r9,96(%rdi)
 movq   %rax,104(%rdi)
 movq   %r10,112(%rdi)
-movq 0(%rsp),%r11
-movq 8(%rsp),%r12
-movq 16(%rsp),%r13
-movq 24(%rsp),%r14
-movq 32(%rsp),%r15
-movq 40(%rsp),%rbx
-movq 48(%rsp),%rbp
-add %r11,%rsp
-mov %rdi,%rax
-mov %rsi,%rdx
+movq 296(%rsp),%r12
+movq 304(%rsp),%r13
+movq 312(%rsp),%r14
+movq 320(%rsp),%r15
+movq 328(%rsp),%rbx
+movq 336(%rsp),%rbp
+add $344,%rsp
+.cfi_adjust_cfa_offset -344
 ret
+.cfi_endproc
 
 .p2align 5
 .globl C_ABI(x25519_x86_64_work_cswap)
 HIDDEN C_ABI(x25519_x86_64_work_cswap)
 C_ABI(x25519_x86_64_work_cswap):
-mov %rsp,%r11
-and $31,%r11
-add $0,%r11
-sub %r11,%rsp
+.cfi_startproc
 cmp  $1,%rsi
 movq   0(%rdi),%rsi
 movq   80(%rdi),%rdx
@@ -1925,7 +1909,10 @@
 movq   %rdx,144(%rdi)
 movq   %rcx,72(%rdi)
 movq   %r8,152(%rdi)
-add %r11,%rsp
 mov %rdi,%rax
 mov %rsi,%rdx
 ret
+.cfi_endproc
+
+#endif  /* __x86_64__ */
+#endif  /* !OPENSSL_NO_ASM */
diff --git a/src/crypto/curve25519/curve25519.c b/src/crypto/curve25519/curve25519.c
index 272db6c..c91e78e 100644
--- a/src/crypto/curve25519/curve25519.c
+++ b/src/crypto/curve25519/curve25519.c
@@ -29,13 +29,13 @@
 #include <openssl/sha.h>
 
 #include "internal.h"
+#include "../internal.h"
 
 
-/* fe means field element. Here the field is \Z/(2^255-19). An element t,
- * entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77
- * t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on
- * context.  */
-typedef int32_t fe[10];
+static const int64_t kBottom25Bits = INT64_C(0x1ffffff);
+static const int64_t kBottom26Bits = INT64_C(0x3ffffff);
+static const int64_t kTop39Bits = INT64_C(0xfffffffffe000000);
+static const int64_t kTop38Bits = INT64_C(0xfffffffffc000000);
 
 static uint64_t load_3(const uint8_t *in) {
   uint64_t result;
@@ -77,17 +77,17 @@
   int64_t carry8;
   int64_t carry9;
 
-  carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
-  carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
-  carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
-  carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
-  carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
+  carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits;
+  carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits;
+  carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits;
+  carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits;
+  carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits;
 
-  carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
-  carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
-  carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
-  carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
-  carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
+  carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
+  carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits;
+  carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
+  carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits;
+  carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits;
 
   h[0] = h0;
   h[1] = h1;
@@ -135,16 +135,6 @@
   int32_t h8 = h[8];
   int32_t h9 = h[9];
   int32_t q;
-  int32_t carry0;
-  int32_t carry1;
-  int32_t carry2;
-  int32_t carry3;
-  int32_t carry4;
-  int32_t carry5;
-  int32_t carry6;
-  int32_t carry7;
-  int32_t carry8;
-  int32_t carry9;
 
   q = (19 * h9 + (((int32_t) 1) << 24)) >> 25;
   q = (h0 + q) >> 26;
@@ -162,16 +152,16 @@
   h0 += 19 * q;
   /* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */
 
-  carry0 = h0 >> 26; h1 += carry0; h0 -= carry0 << 26;
-  carry1 = h1 >> 25; h2 += carry1; h1 -= carry1 << 25;
-  carry2 = h2 >> 26; h3 += carry2; h2 -= carry2 << 26;
-  carry3 = h3 >> 25; h4 += carry3; h3 -= carry3 << 25;
-  carry4 = h4 >> 26; h5 += carry4; h4 -= carry4 << 26;
-  carry5 = h5 >> 25; h6 += carry5; h5 -= carry5 << 25;
-  carry6 = h6 >> 26; h7 += carry6; h6 -= carry6 << 26;
-  carry7 = h7 >> 25; h8 += carry7; h7 -= carry7 << 25;
-  carry8 = h8 >> 26; h9 += carry8; h8 -= carry8 << 26;
-  carry9 = h9 >> 25;               h9 -= carry9 << 25;
+  h1 += h0 >> 26; h0 &= kBottom26Bits;
+  h2 += h1 >> 25; h1 &= kBottom25Bits;
+  h3 += h2 >> 26; h2 &= kBottom26Bits;
+  h4 += h3 >> 25; h3 &= kBottom25Bits;
+  h5 += h4 >> 26; h4 &= kBottom26Bits;
+  h6 += h5 >> 25; h5 &= kBottom25Bits;
+  h7 += h6 >> 26; h6 &= kBottom26Bits;
+  h8 += h7 >> 25; h7 &= kBottom25Bits;
+  h9 += h8 >> 26; h8 &= kBottom26Bits;
+                  h9 &= kBottom25Bits;
                   /* h10 = carry9 */
 
   /* Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
@@ -182,32 +172,32 @@
   s[0] = h0 >> 0;
   s[1] = h0 >> 8;
   s[2] = h0 >> 16;
-  s[3] = (h0 >> 24) | (h1 << 2);
+  s[3] = (h0 >> 24) | ((uint32_t)(h1) << 2);
   s[4] = h1 >> 6;
   s[5] = h1 >> 14;
-  s[6] = (h1 >> 22) | (h2 << 3);
+  s[6] = (h1 >> 22) | ((uint32_t)(h2) << 3);
   s[7] = h2 >> 5;
   s[8] = h2 >> 13;
-  s[9] = (h2 >> 21) | (h3 << 5);
+  s[9] = (h2 >> 21) | ((uint32_t)(h3) << 5);
   s[10] = h3 >> 3;
   s[11] = h3 >> 11;
-  s[12] = (h3 >> 19) | (h4 << 6);
+  s[12] = (h3 >> 19) | ((uint32_t)(h4) << 6);
   s[13] = h4 >> 2;
   s[14] = h4 >> 10;
   s[15] = h4 >> 18;
   s[16] = h5 >> 0;
   s[17] = h5 >> 8;
   s[18] = h5 >> 16;
-  s[19] = (h5 >> 24) | (h6 << 1);
+  s[19] = (h5 >> 24) | ((uint32_t)(h6) << 1);
   s[20] = h6 >> 7;
   s[21] = h6 >> 15;
-  s[22] = (h6 >> 23) | (h7 << 3);
+  s[22] = (h6 >> 23) | ((uint32_t)(h7) << 3);
   s[23] = h7 >> 5;
   s[24] = h7 >> 13;
-  s[25] = (h7 >> 21) | (h8 << 4);
+  s[25] = (h7 >> 21) | ((uint32_t)(h8) << 4);
   s[26] = h8 >> 4;
   s[27] = h8 >> 12;
-  s[28] = (h8 >> 20) | (h9 << 6);
+  s[28] = (h8 >> 20) | ((uint32_t)(h9) << 6);
   s[29] = h9 >> 2;
   s[30] = h9 >> 10;
   s[31] = h9 >> 18;
@@ -215,15 +205,15 @@
 
 /* h = f */
 static void fe_copy(fe h, const fe f) {
-  memmove(h, f, sizeof(int32_t) * 10);
+  OPENSSL_memmove(h, f, sizeof(int32_t) * 10);
 }
 
 /* h = 0 */
-static void fe_0(fe h) { memset(h, 0, sizeof(int32_t) * 10); }
+static void fe_0(fe h) { OPENSSL_memset(h, 0, sizeof(int32_t) * 10); }
 
 /* h = 1 */
 static void fe_1(fe h) {
-  memset(h, 0, sizeof(int32_t) * 10);
+  OPENSSL_memset(h, 0, sizeof(int32_t) * 10);
   h[0] = 1;
 }
 
@@ -447,46 +437,46 @@
    * |h1| <= (1.65*1.65*2^51*(1+1+19+19+19+19+19+19+19+19))
    *   i.e. |h1| <= 1.7*2^59; narrower ranges for h3, h5, h7, h9 */
 
-  carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
-  carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
+  carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
+  carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
   /* |h0| <= 2^25 */
   /* |h4| <= 2^25 */
   /* |h1| <= 1.71*2^59 */
   /* |h5| <= 1.71*2^59 */
 
-  carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
-  carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
+  carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits;
+  carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits;
   /* |h1| <= 2^24; from now on fits into int32 */
   /* |h5| <= 2^24; from now on fits into int32 */
   /* |h2| <= 1.41*2^60 */
   /* |h6| <= 1.41*2^60 */
 
-  carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
-  carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
+  carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits;
+  carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits;
   /* |h2| <= 2^25; from now on fits into int32 unchanged */
   /* |h6| <= 2^25; from now on fits into int32 unchanged */
   /* |h3| <= 1.71*2^59 */
   /* |h7| <= 1.71*2^59 */
 
-  carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
-  carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
+  carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits;
+  carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits;
   /* |h3| <= 2^24; from now on fits into int32 unchanged */
   /* |h7| <= 2^24; from now on fits into int32 unchanged */
   /* |h4| <= 1.72*2^34 */
   /* |h8| <= 1.41*2^60 */
 
-  carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
-  carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
+  carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
+  carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits;
   /* |h4| <= 2^25; from now on fits into int32 unchanged */
   /* |h8| <= 2^25; from now on fits into int32 unchanged */
   /* |h5| <= 1.01*2^24 */
   /* |h9| <= 1.71*2^59 */
 
-  carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
+  carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits;
   /* |h9| <= 2^24; from now on fits into int32 unchanged */
   /* |h0| <= 1.1*2^39 */
 
-  carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
+  carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
   /* |h0| <= 2^25; from now on fits into int32 unchanged */
   /* |h1| <= 1.01*2^24 */
 
@@ -612,24 +602,24 @@
   int64_t carry8;
   int64_t carry9;
 
-  carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
-  carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
+  carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
+  carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
 
-  carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
-  carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
+  carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits;
+  carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits;
 
-  carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
-  carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
+  carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits;
+  carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits;
 
-  carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
-  carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
+  carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits;
+  carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits;
 
-  carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
-  carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
+  carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
+  carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits;
 
-  carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
+  carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits;
 
-  carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
+  carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
 
   h[0] = h0;
   h[1] = h1;
@@ -651,9 +641,6 @@
   int i;
 
   fe_sq(t0, z);
-  for (i = 1; i < 1; ++i) {
-    fe_sq(t0, t0);
-  }
   fe_sq(t1, t0);
   for (i = 1; i < 2; ++i) {
     fe_sq(t1, t1);
@@ -661,9 +648,6 @@
   fe_mul(t1, z, t1);
   fe_mul(t0, t0, t1);
   fe_sq(t2, t0);
-  for (i = 1; i < 1; ++i) {
-    fe_sq(t2, t2);
-  }
   fe_mul(t1, t1, t2);
   fe_sq(t2, t1);
   for (i = 1; i < 5; ++i) {
@@ -880,24 +864,24 @@
   h8 += h8;
   h9 += h9;
 
-  carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
-  carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
+  carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
+  carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
 
-  carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
-  carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
+  carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits;
+  carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits;
 
-  carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
-  carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
+  carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits;
+  carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits;
 
-  carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
-  carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
+  carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits;
+  carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits;
 
-  carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
-  carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
+  carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
+  carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits;
 
-  carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
+  carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits;
 
-  carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
+  carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
 
   h[0] = h0;
   h[1] = h1;
@@ -918,9 +902,6 @@
   int i;
 
   fe_sq(t0, z);
-  for (i = 1; i < 1; ++i) {
-    fe_sq(t0, t0);
-  }
   fe_sq(t1, t0);
   for (i = 1; i < 2; ++i) {
     fe_sq(t1, t1);
@@ -928,9 +909,6 @@
   fe_mul(t1, z, t1);
   fe_mul(t0, t0, t1);
   fe_sq(t0, t0);
-  for (i = 1; i < 1; ++i) {
-    fe_sq(t0, t0);
-  }
   fe_mul(t0, t1, t0);
   fe_sq(t1, t0);
   for (i = 1; i < 5; ++i) {
@@ -974,52 +952,7 @@
   fe_mul(out, t0, z);
 }
 
-/* ge means group element.
-
- * Here the group is the set of pairs (x,y) of field elements (see fe.h)
- * satisfying -x^2 + y^2 = 1 + d x^2y^2
- * where d = -121665/121666.
- *
- * Representations:
- *   ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z
- *   ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT
- *   ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T
- *   ge_precomp (Duif): (y+x,y-x,2dxy) */
-
-typedef struct {
-  fe X;
-  fe Y;
-  fe Z;
-} ge_p2;
-
-typedef struct {
-  fe X;
-  fe Y;
-  fe Z;
-  fe T;
-} ge_p3;
-
-typedef struct {
-  fe X;
-  fe Y;
-  fe Z;
-  fe T;
-} ge_p1p1;
-
-typedef struct {
-  fe yplusx;
-  fe yminusx;
-  fe xy2d;
-} ge_precomp;
-
-typedef struct {
-  fe YplusX;
-  fe YminusX;
-  fe Z;
-  fe T2d;
-} ge_cached;
-
-static void ge_tobytes(uint8_t *s, const ge_p2 *h) {
+void x25519_ge_tobytes(uint8_t *s, const ge_p2 *h) {
   fe recip;
   fe x;
   fe y;
@@ -1049,7 +982,7 @@
 static const fe sqrtm1 = {-32595792, -7943725,  9377950,  3500415, 12389472,
                           -272473,   -25146209, -2005654, 326686,  11406482};
 
-static int ge_frombytes_negate_vartime(ge_p3 *h, const uint8_t *s) {
+int x25519_ge_frombytes_vartime(ge_p3 *h, const uint8_t *s) {
   fe u;
   fe v;
   fe v3;
@@ -1084,7 +1017,7 @@
     fe_mul(h->X, h->X, sqrtm1);
   }
 
-  if (fe_isnegative(h->X) == (s[31] >> 7)) {
+  if (fe_isnegative(h->X) != (s[31] >> 7)) {
     fe_neg(h->X, h->X);
   }
 
@@ -1105,6 +1038,13 @@
   fe_0(h->T);
 }
 
+static void ge_cached_0(ge_cached *h) {
+  fe_1(h->YplusX);
+  fe_1(h->YminusX);
+  fe_1(h->Z);
+  fe_0(h->T2d);
+}
+
 static void ge_precomp_0(ge_precomp *h) {
   fe_1(h->yplusx);
   fe_1(h->yminusx);
@@ -1122,7 +1062,7 @@
                       15978800,  -12551817, -6495438,  29715968, 9444199};
 
 /* r = p */
-static void ge_p3_to_cached(ge_cached *r, const ge_p3 *p) {
+void x25519_ge_p3_to_cached(ge_cached *r, const ge_p3 *p) {
   fe_add(r->YplusX, p->Y, p->X);
   fe_sub(r->YminusX, p->Y, p->X);
   fe_copy(r->Z, p->Z);
@@ -1130,20 +1070,27 @@
 }
 
 /* r = p */
-static void ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p) {
+void x25519_ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p) {
   fe_mul(r->X, p->X, p->T);
   fe_mul(r->Y, p->Y, p->Z);
   fe_mul(r->Z, p->Z, p->T);
 }
 
 /* r = p */
-static void ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p) {
+void x25519_ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p) {
   fe_mul(r->X, p->X, p->T);
   fe_mul(r->Y, p->Y, p->Z);
   fe_mul(r->Z, p->Z, p->T);
   fe_mul(r->T, p->X, p->Y);
 }
 
+/* r = p */
+static void ge_p1p1_to_cached(ge_cached *r, const ge_p1p1 *p) {
+  ge_p3 t;
+  x25519_ge_p1p1_to_p3(&t, p);
+  x25519_ge_p3_to_cached(r, &t);
+}
+
 /* r = 2 * p */
 static void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p) {
   fe t0;
@@ -1199,7 +1146,7 @@
 }
 
 /* r = p + q */
-static void ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {
+void x25519_ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {
   fe t0;
 
   fe_add(r->X, p->Y, p->X);
@@ -1216,7 +1163,7 @@
 }
 
 /* r = p - q */
-static void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {
+void x25519_ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {
   fe t0;
 
   fe_add(r->X, p->Y, p->X);
@@ -1242,12 +1189,64 @@
   return y;
 }
 
-static void cmov(ge_precomp *t, ge_precomp *u, uint8_t b) {
+static void cmov(ge_precomp *t, const ge_precomp *u, uint8_t b) {
   fe_cmov(t->yplusx, u->yplusx, b);
   fe_cmov(t->yminusx, u->yminusx, b);
   fe_cmov(t->xy2d, u->xy2d, b);
 }
 
+void x25519_ge_scalarmult_small_precomp(
+    ge_p3 *h, const uint8_t a[32], const uint8_t precomp_table[15 * 2 * 32]) {
+  /* precomp_table is first expanded into matching |ge_precomp|
+   * elements. */
+  ge_precomp multiples[15];
+
+  unsigned i;
+  for (i = 0; i < 15; i++) {
+    const uint8_t *bytes = &precomp_table[i*(2 * 32)];
+    fe x, y;
+    fe_frombytes(x, bytes);
+    fe_frombytes(y, bytes + 32);
+
+    ge_precomp *out = &multiples[i];
+    fe_add(out->yplusx, y, x);
+    fe_sub(out->yminusx, y, x);
+    fe_mul(out->xy2d, x, y);
+    fe_mul(out->xy2d, out->xy2d, d2);
+  }
+
+  /* See the comment above |k25519SmallPrecomp| about the structure of the
+   * precomputed elements. This loop does 64 additions and 64 doublings to
+   * calculate the result. */
+  ge_p3_0(h);
+
+  for (i = 63; i < 64; i--) {
+    unsigned j;
+    signed char index = 0;
+
+    for (j = 0; j < 4; j++) {
+      const uint8_t bit = 1 & (a[(8 * j) + (i / 8)] >> (i & 7));
+      index |= (bit << j);
+    }
+
+    ge_precomp e;
+    ge_precomp_0(&e);
+
+    for (j = 1; j < 16; j++) {
+      cmov(&e, &multiples[j-1], equal(index, j));
+    }
+
+    ge_cached cached;
+    ge_p1p1 r;
+    x25519_ge_p3_to_cached(&cached, h);
+    x25519_ge_add(&r, h, &cached);
+    x25519_ge_p1p1_to_p3(h, &r);
+
+    ge_madd(&r, h, &e);
+    x25519_ge_p1p1_to_p3(h, &r);
+  }
+}
+
 #if defined(OPENSSL_SMALL)
 
 /* This block of code replaces the standard base-point table with a much smaller
@@ -1258,7 +1257,7 @@
  * element then consider i+1 as a four-bit number: (i₀, i₁, i₂, i₃) (where i₀
  * is the most significant bit). The value of the group element is then:
  * (i₀×2^192 + i₁×2^128 + i₂×2^64 + i₃)G, where G is the generator. */
-static const uint8_t kSmallPrecomp[15 * 2 * 32] = {
+static const uint8_t k25519SmallPrecomp[15 * 2 * 32] = {
     0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
     0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
     0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21, 0x58, 0x66, 0x66, 0x66,
@@ -1341,60 +1340,14 @@
     0x45, 0xc9, 0x8b, 0x17, 0x79, 0xe7, 0xc7, 0x90, 0x99, 0x3a, 0x18, 0x25,
 };
 
-static void ge_scalarmult_base(ge_p3 *h, const uint8_t a[32]) {
-  /* kSmallPrecomp is first expanded into matching |ge_precomp| elements. */
-  ge_precomp multiples[15];
-
-  unsigned i;
-  for (i = 0; i < 15; i++) {
-    const uint8_t *bytes = &kSmallPrecomp[i*(2 * 32)];
-    fe x, y;
-    fe_frombytes(x, bytes);
-    fe_frombytes(y, bytes + 32);
-
-    ge_precomp *out = &multiples[i];
-    fe_add(out->yplusx, y, x);
-    fe_sub(out->yminusx, y, x);
-    fe_mul(out->xy2d, x, y);
-    fe_mul(out->xy2d, out->xy2d, d2);
-  }
-
-  /* See the comment above |kSmallPrecomp| about the structure of the
-   * precomputed elements. This loop does 64 additions and 64 doublings to
-   * calculate the result. */
-  ge_p3_0(h);
-
-  for (i = 63; i < 64; i--) {
-    unsigned j;
-    signed char index = 0;
-
-    for (j = 0; j < 4; j++) {
-      const uint8_t bit = 1 & (a[(8 * j) + (i / 8)] >> (i & 7));
-      index |= (bit << j);
-    }
-
-    ge_precomp e;
-    ge_precomp_0(&e);
-
-    for (j = 1; j < 16; j++) {
-      cmov(&e, &multiples[j-1], equal(index, j));
-    }
-
-    ge_cached cached;
-    ge_p1p1 r;
-    ge_p3_to_cached(&cached, h);
-    ge_add(&r, h, &cached);
-    ge_p1p1_to_p3(h, &r);
-
-    ge_madd(&r, h, &e);
-    ge_p1p1_to_p3(h, &r);
-  }
+void x25519_ge_scalarmult_base(ge_p3 *h, const uint8_t a[32]) {
+  x25519_ge_scalarmult_small_precomp(h, a, k25519SmallPrecomp);
 }
 
 #else
 
-/* base[i][j] = (j+1)*256^i*B */
-static ge_precomp base[32][8] = {
+/* k25519Precomp[i][j] = (j+1)*256^i*B */
+static const ge_precomp k25519Precomp[32][8] = {
     {
         {
             {25967493, -14356035, 29566456, 3660896, -12694345, 4014787,
@@ -3518,17 +3471,17 @@
 static void table_select(ge_precomp *t, int pos, signed char b) {
   ge_precomp minust;
   uint8_t bnegative = negative(b);
-  uint8_t babs = b - (((-bnegative) & b) << 1);
+  uint8_t babs = b - ((uint8_t)((-bnegative) & b) << 1);
 
   ge_precomp_0(t);
-  cmov(t, &base[pos][0], equal(babs, 1));
-  cmov(t, &base[pos][1], equal(babs, 2));
-  cmov(t, &base[pos][2], equal(babs, 3));
-  cmov(t, &base[pos][3], equal(babs, 4));
-  cmov(t, &base[pos][4], equal(babs, 5));
-  cmov(t, &base[pos][5], equal(babs, 6));
-  cmov(t, &base[pos][6], equal(babs, 7));
-  cmov(t, &base[pos][7], equal(babs, 8));
+  cmov(t, &k25519Precomp[pos][0], equal(babs, 1));
+  cmov(t, &k25519Precomp[pos][1], equal(babs, 2));
+  cmov(t, &k25519Precomp[pos][2], equal(babs, 3));
+  cmov(t, &k25519Precomp[pos][3], equal(babs, 4));
+  cmov(t, &k25519Precomp[pos][4], equal(babs, 5));
+  cmov(t, &k25519Precomp[pos][5], equal(babs, 6));
+  cmov(t, &k25519Precomp[pos][6], equal(babs, 7));
+  cmov(t, &k25519Precomp[pos][7], equal(babs, 8));
   fe_copy(minust.yplusx, t->yminusx);
   fe_copy(minust.yminusx, t->yplusx);
   fe_neg(minust.xy2d, t->xy2d);
@@ -3541,7 +3494,7 @@
  *
  * Preconditions:
  *   a[31] <= 127 */
-static void ge_scalarmult_base(ge_p3 *h, const uint8_t *a) {
+void x25519_ge_scalarmult_base(ge_p3 *h, const uint8_t *a) {
   signed char e[64];
   signed char carry;
   ge_p1p1 r;
@@ -3570,27 +3523,88 @@
   for (i = 1; i < 64; i += 2) {
     table_select(&t, i / 2, e[i]);
     ge_madd(&r, h, &t);
-    ge_p1p1_to_p3(h, &r);
+    x25519_ge_p1p1_to_p3(h, &r);
   }
 
   ge_p3_dbl(&r, h);
-  ge_p1p1_to_p2(&s, &r);
+  x25519_ge_p1p1_to_p2(&s, &r);
   ge_p2_dbl(&r, &s);
-  ge_p1p1_to_p2(&s, &r);
+  x25519_ge_p1p1_to_p2(&s, &r);
   ge_p2_dbl(&r, &s);
-  ge_p1p1_to_p2(&s, &r);
+  x25519_ge_p1p1_to_p2(&s, &r);
   ge_p2_dbl(&r, &s);
-  ge_p1p1_to_p3(h, &r);
+  x25519_ge_p1p1_to_p3(h, &r);
 
   for (i = 0; i < 64; i += 2) {
     table_select(&t, i / 2, e[i]);
     ge_madd(&r, h, &t);
-    ge_p1p1_to_p3(h, &r);
+    x25519_ge_p1p1_to_p3(h, &r);
   }
 }
 
 #endif
 
+static void cmov_cached(ge_cached *t, ge_cached *u, uint8_t b) {
+  fe_cmov(t->YplusX, u->YplusX, b);
+  fe_cmov(t->YminusX, u->YminusX, b);
+  fe_cmov(t->Z, u->Z, b);
+  fe_cmov(t->T2d, u->T2d, b);
+}
+
+/* r = scalar * A.
+ * where a = a[0]+256*a[1]+...+256^31 a[31]. */
+void x25519_ge_scalarmult(ge_p2 *r, const uint8_t *scalar, const ge_p3 *A) {
+  ge_p2 Ai_p2[8];
+  ge_cached Ai[16];
+  ge_p1p1 t;
+
+  ge_cached_0(&Ai[0]);
+  x25519_ge_p3_to_cached(&Ai[1], A);
+  ge_p3_to_p2(&Ai_p2[1], A);
+
+  unsigned i;
+  for (i = 2; i < 16; i += 2) {
+    ge_p2_dbl(&t, &Ai_p2[i / 2]);
+    ge_p1p1_to_cached(&Ai[i], &t);
+    if (i < 8) {
+      x25519_ge_p1p1_to_p2(&Ai_p2[i], &t);
+    }
+    x25519_ge_add(&t, A, &Ai[i]);
+    ge_p1p1_to_cached(&Ai[i + 1], &t);
+    if (i < 7) {
+      x25519_ge_p1p1_to_p2(&Ai_p2[i + 1], &t);
+    }
+  }
+
+  ge_p2_0(r);
+  ge_p3 u;
+
+  for (i = 0; i < 256; i += 4) {
+    ge_p2_dbl(&t, r);
+    x25519_ge_p1p1_to_p2(r, &t);
+    ge_p2_dbl(&t, r);
+    x25519_ge_p1p1_to_p2(r, &t);
+    ge_p2_dbl(&t, r);
+    x25519_ge_p1p1_to_p2(r, &t);
+    ge_p2_dbl(&t, r);
+    x25519_ge_p1p1_to_p3(&u, &t);
+
+    uint8_t index = scalar[31 - i/8];
+    index >>= 4 - (i & 4);
+    index &= 0xf;
+
+    unsigned j;
+    ge_cached selected;
+    ge_cached_0(&selected);
+    for (j = 0; j < 16; j++) {
+      cmov_cached(&selected, &Ai[j], equal(j, index));
+    }
+
+    x25519_ge_add(&t, &u, &selected);
+    x25519_ge_p1p1_to_p2(r, &t);
+  }
+}
+
 static void slide(signed char *r, const uint8_t *a) {
   int i;
   int b;
@@ -3625,7 +3639,7 @@
   }
 }
 
-static ge_precomp Bi[8] = {
+static const ge_precomp Bi[8] = {
     {
         {25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626,
          -11754271, -6079156, 2047605},
@@ -3696,8 +3710,8 @@
  * where a = a[0]+256*a[1]+...+256^31 a[31].
  * and b = b[0]+256*b[1]+...+256^31 b[31].
  * B is the Ed25519 base point (x,4/5) with x positive. */
-void ge_double_scalarmult_vartime(ge_p2 *r, const uint8_t *a,
-                                  const ge_p3 *A, const uint8_t *b) {
+static void ge_double_scalarmult_vartime(ge_p2 *r, const uint8_t *a,
+                                         const ge_p3 *A, const uint8_t *b) {
   signed char aslide[256];
   signed char bslide[256];
   ge_cached Ai[8]; /* A,3A,5A,7A,9A,11A,13A,15A */
@@ -3709,30 +3723,30 @@
   slide(aslide, a);
   slide(bslide, b);
 
-  ge_p3_to_cached(&Ai[0], A);
+  x25519_ge_p3_to_cached(&Ai[0], A);
   ge_p3_dbl(&t, A);
-  ge_p1p1_to_p3(&A2, &t);
-  ge_add(&t, &A2, &Ai[0]);
-  ge_p1p1_to_p3(&u, &t);
-  ge_p3_to_cached(&Ai[1], &u);
-  ge_add(&t, &A2, &Ai[1]);
-  ge_p1p1_to_p3(&u, &t);
-  ge_p3_to_cached(&Ai[2], &u);
-  ge_add(&t, &A2, &Ai[2]);
-  ge_p1p1_to_p3(&u, &t);
-  ge_p3_to_cached(&Ai[3], &u);
-  ge_add(&t, &A2, &Ai[3]);
-  ge_p1p1_to_p3(&u, &t);
-  ge_p3_to_cached(&Ai[4], &u);
-  ge_add(&t, &A2, &Ai[4]);
-  ge_p1p1_to_p3(&u, &t);
-  ge_p3_to_cached(&Ai[5], &u);
-  ge_add(&t, &A2, &Ai[5]);
-  ge_p1p1_to_p3(&u, &t);
-  ge_p3_to_cached(&Ai[6], &u);
-  ge_add(&t, &A2, &Ai[6]);
-  ge_p1p1_to_p3(&u, &t);
-  ge_p3_to_cached(&Ai[7], &u);
+  x25519_ge_p1p1_to_p3(&A2, &t);
+  x25519_ge_add(&t, &A2, &Ai[0]);
+  x25519_ge_p1p1_to_p3(&u, &t);
+  x25519_ge_p3_to_cached(&Ai[1], &u);
+  x25519_ge_add(&t, &A2, &Ai[1]);
+  x25519_ge_p1p1_to_p3(&u, &t);
+  x25519_ge_p3_to_cached(&Ai[2], &u);
+  x25519_ge_add(&t, &A2, &Ai[2]);
+  x25519_ge_p1p1_to_p3(&u, &t);
+  x25519_ge_p3_to_cached(&Ai[3], &u);
+  x25519_ge_add(&t, &A2, &Ai[3]);
+  x25519_ge_p1p1_to_p3(&u, &t);
+  x25519_ge_p3_to_cached(&Ai[4], &u);
+  x25519_ge_add(&t, &A2, &Ai[4]);
+  x25519_ge_p1p1_to_p3(&u, &t);
+  x25519_ge_p3_to_cached(&Ai[5], &u);
+  x25519_ge_add(&t, &A2, &Ai[5]);
+  x25519_ge_p1p1_to_p3(&u, &t);
+  x25519_ge_p3_to_cached(&Ai[6], &u);
+  x25519_ge_add(&t, &A2, &Ai[6]);
+  x25519_ge_p1p1_to_p3(&u, &t);
+  x25519_ge_p3_to_cached(&Ai[7], &u);
 
   ge_p2_0(r);
 
@@ -3746,22 +3760,22 @@
     ge_p2_dbl(&t, r);
 
     if (aslide[i] > 0) {
-      ge_p1p1_to_p3(&u, &t);
-      ge_add(&t, &u, &Ai[aslide[i] / 2]);
+      x25519_ge_p1p1_to_p3(&u, &t);
+      x25519_ge_add(&t, &u, &Ai[aslide[i] / 2]);
     } else if (aslide[i] < 0) {
-      ge_p1p1_to_p3(&u, &t);
-      ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]);
+      x25519_ge_p1p1_to_p3(&u, &t);
+      x25519_ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]);
     }
 
     if (bslide[i] > 0) {
-      ge_p1p1_to_p3(&u, &t);
+      x25519_ge_p1p1_to_p3(&u, &t);
       ge_madd(&t, &u, &Bi[bslide[i] / 2]);
     } else if (bslide[i] < 0) {
-      ge_p1p1_to_p3(&u, &t);
+      x25519_ge_p1p1_to_p3(&u, &t);
       ge_msub(&t, &u, &Bi[(-bslide[i]) / 2]);
     }
 
-    ge_p1p1_to_p2(r, &t);
+    x25519_ge_p1p1_to_p2(r, &t);
   }
 }
 
@@ -3775,7 +3789,7 @@
  *   s[0]+256*s[1]+...+256^31*s[31] = s mod l
  *   where l = 2^252 + 27742317777372353535851937790883648493.
  *   Overwrites s in place. */
-static void sc_reduce(uint8_t *s) {
+void x25519_sc_reduce(uint8_t *s) {
   int64_t s0 = 2097151 & load_3(s);
   int64_t s1 = 2097151 & (load_4(s + 2) >> 5);
   int64_t s2 = 2097151 & (load_3(s + 5) >> 2);
@@ -4600,20 +4614,7 @@
 void ED25519_keypair(uint8_t out_public_key[32], uint8_t out_private_key[64]) {
   uint8_t seed[32];
   RAND_bytes(seed, 32);
-
-  uint8_t az[SHA512_DIGEST_LENGTH];
-  SHA512(seed, 32, az);
-
-  az[0] &= 248;
-  az[31] &= 63;
-  az[31] |= 64;
-
-  ge_p3 A;
-  ge_scalarmult_base(&A, az);
-  ge_p3_tobytes(out_public_key, &A);
-
-  memcpy(out_private_key, seed, 32);
-  memmove(out_private_key + 32, out_public_key, 32);
+  ED25519_keypair_from_seed(out_public_key, out_private_key, seed);
 }
 
 int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len,
@@ -4632,9 +4633,9 @@
   uint8_t nonce[SHA512_DIGEST_LENGTH];
   SHA512_Final(nonce, &hash_ctx);
 
-  sc_reduce(nonce);
+  x25519_sc_reduce(nonce);
   ge_p3 R;
-  ge_scalarmult_base(&R, nonce);
+  x25519_ge_scalarmult_base(&R, nonce);
   ge_p3_tobytes(out_sig, &R);
 
   SHA512_Init(&hash_ctx);
@@ -4644,7 +4645,7 @@
   uint8_t hram[SHA512_DIGEST_LENGTH];
   SHA512_Final(hram, &hash_ctx);
 
-  sc_reduce(hram);
+  x25519_sc_reduce(hram);
   sc_muladd(out_sig + 32, hram, az, nonce);
 
   return 1;
@@ -4654,16 +4655,19 @@
                    const uint8_t signature[64], const uint8_t public_key[32]) {
   ge_p3 A;
   if ((signature[63] & 224) != 0 ||
-      ge_frombytes_negate_vartime(&A, public_key) != 0) {
+      x25519_ge_frombytes_vartime(&A, public_key) != 0) {
     return 0;
   }
 
+  fe_neg(A.X, A.X);
+  fe_neg(A.T, A.T);
+
   uint8_t pkcopy[32];
-  memcpy(pkcopy, public_key, 32);
+  OPENSSL_memcpy(pkcopy, public_key, 32);
   uint8_t rcopy[32];
-  memcpy(rcopy, signature, 32);
+  OPENSSL_memcpy(rcopy, signature, 32);
   uint8_t scopy[32];
-  memcpy(scopy, signature + 32, 32);
+  OPENSSL_memcpy(scopy, signature + 32, 32);
 
   SHA512_CTX hash_ctx;
   SHA512_Init(&hash_ctx);
@@ -4673,17 +4677,35 @@
   uint8_t h[SHA512_DIGEST_LENGTH];
   SHA512_Final(h, &hash_ctx);
 
-  sc_reduce(h);
+  x25519_sc_reduce(h);
 
   ge_p2 R;
   ge_double_scalarmult_vartime(&R, h, &A, scopy);
 
   uint8_t rcheck[32];
-  ge_tobytes(rcheck, &R);
+  x25519_ge_tobytes(rcheck, &R);
 
   return CRYPTO_memcmp(rcheck, rcopy, sizeof(rcheck)) == 0;
 }
 
+void ED25519_keypair_from_seed(uint8_t out_public_key[32],
+                               uint8_t out_private_key[64],
+                               const uint8_t seed[32]) {
+  uint8_t az[SHA512_DIGEST_LENGTH];
+  SHA512(seed, 32, az);
+
+  az[0] &= 248;
+  az[31] &= 63;
+  az[31] |= 64;
+
+  ge_p3 A;
+  x25519_ge_scalarmult_base(&A, az);
+  ge_p3_tobytes(out_public_key, &A);
+
+  OPENSSL_memcpy(out_private_key, seed, 32);
+  OPENSSL_memcpy(out_private_key + 32, out_public_key, 32);
+}
+
 
 #if defined(BORINGSSL_X25519_X86_64)
 
@@ -4749,17 +4771,17 @@
   int64_t carry8;
   int64_t carry9;
 
-  carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25;
-  carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25;
-  carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25;
-  carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25;
-  carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25;
+  carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits;
+  carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits;
+  carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits;
+  carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits;
+  carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits;
 
-  carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26;
-  carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26;
-  carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26;
-  carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26;
-  carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26;
+  carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
+  carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits;
+  carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
+  carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits;
+  carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits;
 
   h[0] = h0;
   h[1] = h1;
@@ -4779,7 +4801,7 @@
   fe x1, x2, z2, x3, z3, tmp0, tmp1;
 
   uint8_t e[32];
-  memcpy(e, scalar, 32);
+  OPENSSL_memcpy(e, scalar, 32);
   e[0] &= 248;
   e[31] &= 127;
   e[31] |= 64;
@@ -4841,6 +4863,24 @@
 
 void X25519_keypair(uint8_t out_public_value[32], uint8_t out_private_key[32]) {
   RAND_bytes(out_private_key, 32);
+
+  /* All X25519 implementations should decode scalars correctly (see
+   * https://tools.ietf.org/html/rfc7748#section-5). However, if an
+   * implementation doesn't then it might interoperate with random keys a
+   * fraction of the time because they'll, randomly, happen to be correctly
+   * formed.
+   *
+   * Thus we do the opposite of the masking here to make sure that our private
+   * keys are never correctly masked and so, hopefully, any incorrect
+   * implementations are deterministically broken.
+   *
+   * This does not affect security because, although we're throwing away
+   * entropy, a valid implementation of scalarmult should throw away the exact
+   * same bits anyway. */
+  out_private_key[0] |= 7;
+  out_private_key[31] &= 63;
+  out_private_key[31] |= 128;
+
   X25519_public_from_private(out_public_value, out_private_key);
 }
 
@@ -4877,13 +4917,13 @@
 #endif
 
   uint8_t e[32];
-  memcpy(e, private_key, 32);
+  OPENSSL_memcpy(e, private_key, 32);
   e[0] &= 248;
   e[31] &= 127;
   e[31] |= 64;
 
   ge_p3 A;
-  ge_scalarmult_base(&A, e);
+  x25519_ge_scalarmult_base(&A, e);
 
   /* We only need the u-coordinate of the curve25519 point. The map is
    * u=(y+1)/(1-y). Since y=Y/Z, this gives u=(Z+Y)/(Z-Y). */
diff --git a/src/crypto/curve25519/ed25519_test.cc b/src/crypto/curve25519/ed25519_test.cc
index 1b6a0b6..7581730 100644
--- a/src/crypto/curve25519/ed25519_test.cc
+++ b/src/crypto/curve25519/ed25519_test.cc
@@ -17,6 +17,7 @@
 
 #include <openssl/curve25519.h>
 
+#include "../internal.h"
 #include "../test/file_test.h"
 
 
@@ -53,11 +54,30 @@
   return true;
 }
 
+static bool TestKeypairFromSeed() {
+  uint8_t public_key1[32], private_key1[64];
+  ED25519_keypair(public_key1, private_key1);
+
+  uint8_t seed[32];
+  OPENSSL_memcpy(seed, private_key1, sizeof(seed));
+
+  uint8_t public_key2[32], private_key2[64];
+  ED25519_keypair_from_seed(public_key2, private_key2, seed);
+
+  if (OPENSSL_memcmp(public_key1, public_key2, sizeof(public_key1)) != 0 ||
+      OPENSSL_memcmp(private_key1, private_key2, sizeof(private_key1)) != 0) {
+    fprintf(stderr, "TestKeypairFromSeed: resulting keypairs did not match.\n");
+    return false;
+  }
+
+  return true;
+}
+
 int main(int argc, char **argv) {
   if (argc != 2) {
     fprintf(stderr, "%s <test input.txt>\n", argv[0]);
     return 1;
   }
 
-  return FileTestMain(TestSignature, nullptr, argv[1]);
+  return TestKeypairFromSeed() && FileTestMain(TestSignature, nullptr, argv[1]);
 }
diff --git a/src/crypto/curve25519/internal.h b/src/crypto/curve25519/internal.h
index 27994b7..ea206a3 100644
--- a/src/crypto/curve25519/internal.h
+++ b/src/crypto/curve25519/internal.h
@@ -37,6 +37,70 @@
                  const uint8_t point[32]);
 #endif
 
+/* fe means field element. Here the field is \Z/(2^255-19). An element t,
+ * entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77
+ * t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on
+ * context.  */
+typedef int32_t fe[10];
+
+/* ge means group element.
+
+ * Here the group is the set of pairs (x,y) of field elements (see fe.h)
+ * satisfying -x^2 + y^2 = 1 + d x^2y^2
+ * where d = -121665/121666.
+ *
+ * Representations:
+ *   ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z
+ *   ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT
+ *   ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T
+ *   ge_precomp (Duif): (y+x,y-x,2dxy) */
+
+typedef struct {
+  fe X;
+  fe Y;
+  fe Z;
+} ge_p2;
+
+typedef struct {
+  fe X;
+  fe Y;
+  fe Z;
+  fe T;
+} ge_p3;
+
+typedef struct {
+  fe X;
+  fe Y;
+  fe Z;
+  fe T;
+} ge_p1p1;
+
+typedef struct {
+  fe yplusx;
+  fe yminusx;
+  fe xy2d;
+} ge_precomp;
+
+typedef struct {
+  fe YplusX;
+  fe YminusX;
+  fe Z;
+  fe T2d;
+} ge_cached;
+
+void x25519_ge_tobytes(uint8_t *s, const ge_p2 *h);
+int x25519_ge_frombytes_vartime(ge_p3 *h, const uint8_t *s);
+void x25519_ge_p3_to_cached(ge_cached *r, const ge_p3 *p);
+void x25519_ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p);
+void x25519_ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p);
+void x25519_ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q);
+void x25519_ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q);
+void x25519_ge_scalarmult_small_precomp(
+    ge_p3 *h, const uint8_t a[32], const uint8_t precomp_table[15 * 2 * 32]);
+void x25519_ge_scalarmult_base(ge_p3 *h, const uint8_t a[32]);
+void x25519_ge_scalarmult(ge_p2 *r, const uint8_t *scalar, const ge_p3 *A);
+void x25519_sc_reduce(uint8_t *s);
+
 
 #if defined(__cplusplus)
 }  /* extern C */
diff --git a/src/crypto/curve25519/spake25519.c b/src/crypto/curve25519/spake25519.c
new file mode 100644
index 0000000..5b794b3
--- /dev/null
+++ b/src/crypto/curve25519/spake25519.c
@@ -0,0 +1,465 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/curve25519.h>
+
+#include <string.h>
+
+#include <openssl/bytestring.h>
+#include <openssl/mem.h>
+#include <openssl/rand.h>
+#include <openssl/sha.h>
+
+#include "internal.h"
+#include "../internal.h"
+
+
+/* The following precomputation tables are for the following
+ * points used in the SPAKE2 protocol.
+ *
+ * N:
+ *   x: 49918732221787544735331783592030787422991506689877079631459872391322455579424
+ *   y: 54629554431565467720832445949441049581317094546788069926228343916274969994000
+ *   encoded: 10e3df0ae37d8e7a99b5fe74b44672103dbddcbd06af680d71329a11693bc778
+ *
+ * M:
+ *   x: 31406539342727633121250288103050113562375374900226415211311216773867585644232
+ *   y: 21177308356423958466833845032658859666296341766942662650232962324899758529114
+ *   encoded: 5ada7e4bf6ddd9adb6626d32131c6b5c51a1e347a3478f53cfcf441b88eed12e
+ *
+ * These points and their precomputation tables are generated with the
+ * following Python code. For a description of the precomputation table,
+ * see curve25519.c in this directory.
+ *
+ * Exact copies of the source code are kept in bug 27296743.
+ *
+ * import hashlib
+ * import ed25519 as E  # http://ed25519.cr.yp.to/python/ed25519.py
+ *
+ * SEED_N = 'edwards25519 point generation seed (N)'
+ * SEED_M = 'edwards25519 point generation seed (M)'
+ *
+ * def genpoint(seed):
+ *     v = hashlib.sha256(seed).digest()
+ *     it = 1
+ *     while True:
+ *         try:
+ *             x,y = E.decodepoint(v)
+ *         except Exception, e:
+ *             print e
+ *             it += 1
+ *             v = hashlib.sha256(v).digest()
+ *             continue
+ *         print "Found in %d iterations:" % it
+ *         print "  x = %d" % x
+ *         print "  y = %d" % y
+ *         print " Encoded (hex)"
+ *         print E.encodepoint((x,y)).encode('hex')
+ *         return (x,y)
+ *
+ * def gentable(P):
+ *     t = []
+ *     for i in range(1,16):
+ *         k = (i >> 3 & 1) * (1 << 192) + \
+ *             (i >> 2 & 1) * (1 << 128) + \
+ *             (i >> 1 & 1) * (1 <<  64) + \
+ *             (i      & 1)
+ *         t.append(E.scalarmult(P, k))
+ *     return ''.join(E.encodeint(x) + E.encodeint(y) for (x,y) in t)
+ *
+ * def printtable(table, name):
+ *     print "static const uint8_t %s[15 * 2 * 32] = {" % name,
+ *     for i in range(15 * 2 * 32):
+ *         if i % 12 == 0:
+ *             print "\n   ",
+ *         print " 0x%02x," % ord(table[i]),
+ *     print "\n};"
+ *
+ * if __name__ == "__main__":
+ *     print "Searching for N"
+ *     N = genpoint(SEED_N)
+ *     print "Generating precomputation table for N"
+ *     Ntable = gentable(N)
+ *     printtable(Ntable, "kSpakeNSmallPrecomp")
+ *
+ *     print "Searching for M"
+ *     M = genpoint(SEED_M)
+ *     print "Generating precomputation table for M"
+ *     Mtable = gentable(M)
+ *     printtable(Mtable, "kSpakeMSmallPrecomp")
+ */
+static const uint8_t kSpakeNSmallPrecomp[15 * 2 * 32] = {
+    0x20, 0x1b, 0xc5, 0xb3, 0x43, 0x17, 0x71, 0x10, 0x44, 0x1e, 0x73, 0xb3,
+    0xae, 0x3f, 0xbf, 0x9f, 0xf5, 0x44, 0xc8, 0x13, 0x8f, 0xd1, 0x01, 0xc2,
+    0x8a, 0x1a, 0x6d, 0xea, 0x4d, 0x00, 0x5d, 0x6e, 0x10, 0xe3, 0xdf, 0x0a,
+    0xe3, 0x7d, 0x8e, 0x7a, 0x99, 0xb5, 0xfe, 0x74, 0xb4, 0x46, 0x72, 0x10,
+    0x3d, 0xbd, 0xdc, 0xbd, 0x06, 0xaf, 0x68, 0x0d, 0x71, 0x32, 0x9a, 0x11,
+    0x69, 0x3b, 0xc7, 0x78, 0x93, 0xf1, 0x57, 0x97, 0x6e, 0xf0, 0x6e, 0x45,
+    0x37, 0x4a, 0xf4, 0x0b, 0x18, 0x51, 0xf5, 0x4f, 0x67, 0x3c, 0xdc, 0xec,
+    0x84, 0xed, 0xd0, 0xeb, 0xca, 0xfb, 0xdb, 0xff, 0x7f, 0xeb, 0xa8, 0x23,
+    0x68, 0x87, 0x13, 0x64, 0x6a, 0x10, 0xf7, 0x45, 0xe0, 0x0f, 0x32, 0x21,
+    0x59, 0x7c, 0x0e, 0x50, 0xad, 0x56, 0xd7, 0x12, 0x69, 0x7b, 0x58, 0xf8,
+    0xb9, 0x3b, 0xa5, 0xbb, 0x4d, 0x1b, 0x87, 0x1c, 0x46, 0xa7, 0x17, 0x9d,
+    0x6d, 0x84, 0x45, 0xbe, 0x7f, 0x95, 0xd2, 0x34, 0xcd, 0x89, 0x95, 0xc0,
+    0xf0, 0xd3, 0xdf, 0x6e, 0x10, 0x4a, 0xe3, 0x7b, 0xce, 0x7f, 0x40, 0x27,
+    0xc7, 0x2b, 0xab, 0x66, 0x03, 0x59, 0xb4, 0x7b, 0xc7, 0xc7, 0xf0, 0x39,
+    0x9a, 0x33, 0x35, 0xbf, 0xcc, 0x2f, 0xf3, 0x2e, 0x68, 0x9d, 0x53, 0x5c,
+    0x88, 0x52, 0xe3, 0x77, 0x90, 0xa1, 0x27, 0x85, 0xc5, 0x74, 0x7f, 0x23,
+    0x0e, 0x93, 0x01, 0x3e, 0xe7, 0x2e, 0x2e, 0x95, 0xf3, 0x0d, 0xc2, 0x25,
+    0x25, 0x39, 0x39, 0x3d, 0x6e, 0x8e, 0x89, 0xbd, 0xe8, 0xbb, 0x67, 0x5e,
+    0x8c, 0x66, 0x8b, 0x63, 0x28, 0x1e, 0x4e, 0x74, 0x85, 0xa8, 0xaf, 0x0f,
+    0x12, 0x5d, 0xb6, 0x8a, 0x83, 0x1a, 0x77, 0x76, 0x5e, 0x62, 0x8a, 0xa7,
+    0x3c, 0xb8, 0x05, 0x57, 0x2b, 0xaf, 0x36, 0x2e, 0x10, 0x90, 0xb2, 0x39,
+    0xb4, 0x3e, 0x75, 0x6d, 0x3a, 0xa8, 0x31, 0x35, 0xc2, 0x1e, 0x8f, 0xc2,
+    0x79, 0x89, 0x35, 0x16, 0x26, 0xd1, 0xc7, 0x0b, 0x04, 0x1f, 0x1d, 0xf9,
+    0x9c, 0x05, 0xa6, 0x6b, 0xb5, 0x19, 0x5a, 0x24, 0x6d, 0x91, 0xc5, 0x31,
+    0xfd, 0xc5, 0xfa, 0xe7, 0xa6, 0xcb, 0x0e, 0x4b, 0x18, 0x0d, 0x94, 0xc7,
+    0xee, 0x1d, 0x46, 0x1f, 0x92, 0xb1, 0xb2, 0x4a, 0x2b, 0x43, 0x37, 0xfe,
+    0xc2, 0x15, 0x11, 0x89, 0xef, 0x59, 0x73, 0x3c, 0x06, 0x76, 0x78, 0xcb,
+    0xa6, 0x0d, 0x79, 0x5f, 0x28, 0x0b, 0x5b, 0x8c, 0x9e, 0xe4, 0xaa, 0x51,
+    0x9a, 0x42, 0x6f, 0x11, 0x50, 0x3d, 0x01, 0xd6, 0x21, 0xc0, 0x99, 0x5e,
+    0x1a, 0xe8, 0x81, 0x25, 0x80, 0xeb, 0xed, 0x5d, 0x37, 0x47, 0x30, 0x70,
+    0xa0, 0x4e, 0x0b, 0x43, 0x17, 0xbe, 0xb6, 0x47, 0xe7, 0x2a, 0x62, 0x9d,
+    0x5d, 0xa6, 0xc5, 0x33, 0x62, 0x9d, 0x56, 0x24, 0x9d, 0x1d, 0xb2, 0x13,
+    0xbc, 0x17, 0x66, 0x43, 0xd1, 0x68, 0xd5, 0x3b, 0x17, 0x69, 0x17, 0xa6,
+    0x06, 0x9e, 0x12, 0xb8, 0x7c, 0xd5, 0xaf, 0x3e, 0x21, 0x1b, 0x31, 0xeb,
+    0x0b, 0xa4, 0x98, 0x1c, 0xf2, 0x6a, 0x5e, 0x7c, 0x9b, 0x45, 0x8f, 0xb2,
+    0x12, 0x06, 0xd5, 0x8c, 0x1d, 0xb2, 0xa7, 0x57, 0x5f, 0x2f, 0x4f, 0xdb,
+    0x52, 0x99, 0x7c, 0x58, 0x01, 0x5f, 0xf2, 0xa5, 0xf6, 0x51, 0x86, 0x21,
+    0x2f, 0x5b, 0x8d, 0x6a, 0xae, 0x83, 0x34, 0x6d, 0x58, 0x4b, 0xef, 0xfe,
+    0xbf, 0x73, 0x5d, 0xdb, 0xc4, 0x97, 0x2a, 0x85, 0xf3, 0x6c, 0x46, 0x42,
+    0xb3, 0x90, 0xc1, 0x57, 0x97, 0x50, 0x35, 0xb1, 0x9d, 0xb7, 0xc7, 0x3c,
+    0x85, 0x6d, 0x6c, 0xfd, 0xce, 0xb0, 0xc9, 0xa2, 0x77, 0xee, 0xc3, 0x6b,
+    0x0c, 0x37, 0xfa, 0x30, 0x91, 0xd1, 0x2c, 0xb8, 0x5e, 0x7f, 0x81, 0x5f,
+    0x87, 0xfd, 0x18, 0x02, 0x5a, 0x30, 0x4e, 0x62, 0xbc, 0x65, 0xc6, 0xce,
+    0x1a, 0xcf, 0x2b, 0xaa, 0x56, 0x3e, 0x4d, 0xcf, 0xba, 0x62, 0x5f, 0x9a,
+    0xd0, 0x72, 0xff, 0xef, 0x28, 0xbd, 0xbe, 0xd8, 0x57, 0x3d, 0xf5, 0x57,
+    0x7d, 0xe9, 0x71, 0x31, 0xec, 0x98, 0x90, 0x94, 0xd9, 0x54, 0xbf, 0x84,
+    0x0b, 0xe3, 0x06, 0x47, 0x19, 0x9a, 0x13, 0x1d, 0xef, 0x9d, 0x13, 0xf3,
+    0xdb, 0xc3, 0x5c, 0x72, 0x9e, 0xed, 0x24, 0xaa, 0x64, 0xed, 0xe7, 0x0d,
+    0xa0, 0x7c, 0x73, 0xba, 0x9b, 0x86, 0xa7, 0x3b, 0x55, 0xab, 0x58, 0x30,
+    0xf1, 0x15, 0x81, 0x83, 0x2f, 0xf9, 0x62, 0x84, 0x98, 0x66, 0xf6, 0x55,
+    0x21, 0xd8, 0xf2, 0x25, 0x64, 0x71, 0x4b, 0x12, 0x76, 0x59, 0xc5, 0xaa,
+    0x93, 0x67, 0xc3, 0x86, 0x25, 0xab, 0x4e, 0x4b, 0xf6, 0xd8, 0x3f, 0x44,
+    0x2e, 0x11, 0xe0, 0xbd, 0x6a, 0xf2, 0x5d, 0xf5, 0xf9, 0x53, 0xea, 0xa4,
+    0xc8, 0xd9, 0x50, 0x33, 0x81, 0xd9, 0xa8, 0x2d, 0x91, 0x7d, 0x13, 0x2a,
+    0x11, 0xcf, 0xde, 0x3f, 0x0a, 0xd2, 0xbc, 0x33, 0xb2, 0x62, 0x53, 0xea,
+    0x77, 0x88, 0x43, 0x66, 0x27, 0x43, 0x85, 0xe9, 0x5f, 0x55, 0xf5, 0x2a,
+    0x8a, 0xac, 0xdf, 0xff, 0x9b, 0x4c, 0x96, 0x9c, 0xa5, 0x7a, 0xce, 0xd5,
+    0x79, 0x18, 0xf1, 0x0b, 0x58, 0x95, 0x7a, 0xe7, 0xd3, 0x74, 0x65, 0x0b,
+    0xa4, 0x64, 0x30, 0xe8, 0x5c, 0xfc, 0x55, 0x56, 0xee, 0x14, 0x14, 0xd3,
+    0x45, 0x3b, 0xf8, 0xde, 0x05, 0x3e, 0xb9, 0x3c, 0xd7, 0x6a, 0x52, 0x72,
+    0x5b, 0x39, 0x09, 0xbe, 0x82, 0x23, 0x10, 0x4a, 0xb7, 0xc3, 0xdc, 0x4c,
+    0x5d, 0xc9, 0xf1, 0x14, 0x83, 0xf9, 0x0b, 0x9b, 0xe9, 0x23, 0x84, 0x6a,
+    0xc4, 0x08, 0x3d, 0xda, 0x3d, 0x12, 0x95, 0x87, 0x18, 0xa4, 0x7d, 0x3f,
+    0x23, 0xde, 0xd4, 0x1e, 0xa8, 0x47, 0xc3, 0x71, 0xdb, 0xf5, 0x03, 0x6c,
+    0x57, 0xe7, 0xa4, 0x43, 0x82, 0x33, 0x7b, 0x62, 0x46, 0x7d, 0xf7, 0x10,
+    0x69, 0x18, 0x38, 0x27, 0x9a, 0x6f, 0x38, 0xac, 0xfa, 0x92, 0xc5, 0xae,
+    0x66, 0xa6, 0x73, 0x95, 0x15, 0x0e, 0x4c, 0x04, 0xb6, 0xfc, 0xf5, 0xc7,
+    0x21, 0x3a, 0x99, 0xdb, 0x0e, 0x36, 0xf0, 0x56, 0xbc, 0x75, 0xf9, 0x87,
+    0x9b, 0x11, 0x18, 0x92, 0x64, 0x1a, 0xe7, 0xc7, 0xab, 0x5a, 0xc7, 0x26,
+    0x7f, 0x13, 0x98, 0x42, 0x52, 0x43, 0xdb, 0xc8, 0x6d, 0x0b, 0xb7, 0x31,
+    0x93, 0x24, 0xd6, 0xe8, 0x24, 0x1f, 0x6f, 0x21, 0xa7, 0x8c, 0xeb, 0xdb,
+    0x83, 0xb8, 0x89, 0xe3, 0xc1, 0xd7, 0x69, 0x3b, 0x02, 0x6b, 0x54, 0x0f,
+    0x84, 0x2f, 0xb5, 0x5c, 0x17, 0x77, 0xbe, 0xe5, 0x61, 0x0d, 0xc5, 0xdf,
+    0x3b, 0xcf, 0x3e, 0x93, 0x4f, 0xf5, 0x89, 0xb9, 0x5a, 0xc5, 0x29, 0x31,
+    0xc0, 0xc2, 0xff, 0xe5, 0x3f, 0xa6, 0xac, 0x03, 0xca, 0xf5, 0xff, 0xe0,
+    0x36, 0xce, 0xf3, 0xe2, 0xb7, 0x9c, 0x02, 0xe9, 0x9e, 0xd2, 0xbc, 0x87,
+    0x2f, 0x3d, 0x9a, 0x1d, 0x8f, 0xc5, 0x72, 0xb8, 0xa2, 0x01, 0xd4, 0x68,
+    0xb1, 0x84, 0x16, 0x10, 0xf6, 0xf3, 0x52, 0x25, 0xd9, 0xdc, 0x4c, 0xdd,
+    0x0f, 0xd6, 0x4a, 0xcf, 0x60, 0x96, 0x7e, 0xcc, 0x42, 0x0f, 0x64, 0x9d,
+    0x72, 0x46, 0x04, 0x07, 0xf2, 0x5b, 0xf4, 0x07, 0xd1, 0xf4, 0x59, 0x71,
+};
+
+static const uint8_t kSpakeMSmallPrecomp[15 * 2 * 32] = {
+    0xc8, 0xa6, 0x63, 0xc5, 0x97, 0xf1, 0xee, 0x40, 0xab, 0x62, 0x42, 0xee,
+    0x25, 0x6f, 0x32, 0x6c, 0x75, 0x2c, 0xa7, 0xd3, 0xbd, 0x32, 0x3b, 0x1e,
+    0x11, 0x9c, 0xbd, 0x04, 0xa9, 0x78, 0x6f, 0x45, 0x5a, 0xda, 0x7e, 0x4b,
+    0xf6, 0xdd, 0xd9, 0xad, 0xb6, 0x62, 0x6d, 0x32, 0x13, 0x1c, 0x6b, 0x5c,
+    0x51, 0xa1, 0xe3, 0x47, 0xa3, 0x47, 0x8f, 0x53, 0xcf, 0xcf, 0x44, 0x1b,
+    0x88, 0xee, 0xd1, 0x2e, 0x03, 0x89, 0xaf, 0xc0, 0x61, 0x2d, 0x9e, 0x35,
+    0xeb, 0x0e, 0x03, 0xe0, 0xb7, 0xfb, 0xa5, 0xbc, 0x44, 0xbe, 0x0c, 0x89,
+    0x0a, 0x0f, 0xd6, 0x59, 0x47, 0x9e, 0xe6, 0x3d, 0x36, 0x9d, 0xff, 0x44,
+    0x5e, 0xac, 0xab, 0xe5, 0x3a, 0xd5, 0xb0, 0x35, 0x9f, 0x6d, 0x7f, 0xba,
+    0xc0, 0x85, 0x0e, 0xf4, 0x70, 0x3f, 0x13, 0x90, 0x4c, 0x50, 0x1a, 0xee,
+    0xc5, 0xeb, 0x69, 0xfe, 0x98, 0x42, 0x87, 0x1d, 0xce, 0x6c, 0x29, 0xaa,
+    0x2b, 0x31, 0xc2, 0x38, 0x7b, 0x6b, 0xee, 0x88, 0x0b, 0xba, 0xce, 0xa8,
+    0xca, 0x19, 0x60, 0x1b, 0x16, 0xf1, 0x25, 0x1e, 0xcf, 0x63, 0x66, 0x1e,
+    0xbb, 0x63, 0xeb, 0x7d, 0xca, 0xd2, 0xb4, 0x23, 0x5a, 0x01, 0x6f, 0x05,
+    0xd1, 0xdc, 0x41, 0x73, 0x75, 0xc0, 0xfd, 0x30, 0x91, 0x52, 0x68, 0x96,
+    0x45, 0xb3, 0x66, 0x01, 0x3b, 0x53, 0x89, 0x3c, 0x69, 0xbc, 0x6c, 0x69,
+    0xe3, 0x51, 0x8f, 0xe3, 0xd2, 0x84, 0xd5, 0x28, 0x66, 0xb5, 0xe6, 0x06,
+    0x09, 0xfe, 0x6d, 0xb0, 0x72, 0x16, 0xe0, 0x8a, 0xce, 0x61, 0x65, 0xa9,
+    0x21, 0x32, 0x48, 0xdc, 0x7a, 0x1d, 0xe1, 0x38, 0x7f, 0x8c, 0x75, 0x88,
+    0x3d, 0x08, 0xa9, 0x4a, 0x6f, 0x3d, 0x9f, 0x7f, 0x3f, 0xbd, 0x57, 0x6b,
+    0x19, 0xce, 0x3f, 0x4a, 0xc9, 0xd3, 0xf9, 0x6e, 0x72, 0x7b, 0x5b, 0x74,
+    0xea, 0xbe, 0x9c, 0x7a, 0x6d, 0x9c, 0x40, 0x49, 0xe6, 0xfb, 0x2a, 0x1a,
+    0x75, 0x70, 0xe5, 0x4e, 0xed, 0x74, 0xe0, 0x75, 0xac, 0xc0, 0xb1, 0x11,
+    0x3e, 0xf2, 0xaf, 0x88, 0x4d, 0x66, 0xb6, 0xf6, 0x15, 0x4f, 0x3c, 0x6c,
+    0x77, 0xae, 0x47, 0x51, 0x63, 0x9a, 0xfe, 0xe1, 0xb4, 0x1a, 0x12, 0xdf,
+    0xe9, 0x54, 0x8d, 0x3b, 0x30, 0x2a, 0x75, 0xe3, 0xe5, 0x29, 0xb1, 0x4c,
+    0xb0, 0x7c, 0x6d, 0xb5, 0xae, 0x85, 0xdb, 0x1e, 0x38, 0x55, 0x96, 0xa5,
+    0x5b, 0x9f, 0x15, 0x23, 0x28, 0x36, 0xb8, 0xa2, 0x41, 0xb4, 0xd7, 0x19,
+    0x91, 0x8d, 0x26, 0x3e, 0xca, 0x9c, 0x05, 0x7a, 0x2b, 0x60, 0x45, 0x86,
+    0x8b, 0xee, 0x64, 0x6f, 0x5c, 0x09, 0x4d, 0x4b, 0x5a, 0x7f, 0xb0, 0xc3,
+    0x26, 0x9d, 0x8b, 0xb8, 0x83, 0x69, 0xcf, 0x16, 0x72, 0x62, 0x3e, 0x5e,
+    0x53, 0x4f, 0x9c, 0x73, 0x76, 0xfc, 0x19, 0xef, 0xa0, 0x74, 0x3a, 0x11,
+    0x1e, 0xd0, 0x4d, 0xb7, 0x87, 0xa1, 0xd6, 0x87, 0x6c, 0x0e, 0x6c, 0x8c,
+    0xe9, 0xa0, 0x44, 0xc4, 0x72, 0x3e, 0x73, 0x17, 0x13, 0xd1, 0x4e, 0x3d,
+    0x8e, 0x1d, 0x5a, 0x8b, 0x75, 0xcb, 0x59, 0x2c, 0x47, 0x87, 0x15, 0x41,
+    0xfe, 0x08, 0xe9, 0xa6, 0x97, 0x17, 0x08, 0x26, 0x6a, 0xb5, 0xbb, 0x73,
+    0xaa, 0xb8, 0x5b, 0x65, 0x65, 0x5b, 0x30, 0x9e, 0x62, 0x59, 0x02, 0xf8,
+    0xb8, 0x0f, 0x32, 0x10, 0xc1, 0x36, 0x08, 0x52, 0x98, 0x4a, 0x1e, 0xf0,
+    0xab, 0x21, 0x5e, 0xde, 0x16, 0x0c, 0xda, 0x09, 0x99, 0x6b, 0x9e, 0xc0,
+    0x90, 0xa5, 0x5a, 0xcc, 0xb0, 0xb7, 0xbb, 0xd2, 0x8b, 0x5f, 0xd3, 0x3b,
+    0x3e, 0x8c, 0xa5, 0x71, 0x66, 0x06, 0xe3, 0x28, 0xd4, 0xf8, 0x3f, 0xe5,
+    0x27, 0xdf, 0xfe, 0x0f, 0x09, 0xb2, 0x8a, 0x09, 0x5a, 0x23, 0x61, 0x0d,
+    0x2d, 0xf5, 0x44, 0xf1, 0x5c, 0xf8, 0x82, 0x4e, 0xdc, 0x78, 0x7a, 0xab,
+    0xc3, 0x57, 0x91, 0xaf, 0x65, 0x6e, 0x71, 0xf1, 0x44, 0xbf, 0xed, 0x43,
+    0x50, 0xb4, 0x67, 0x48, 0xef, 0x5a, 0x10, 0x46, 0x81, 0xb4, 0x0c, 0xc8,
+    0x48, 0xed, 0x99, 0x7a, 0x45, 0xa5, 0x92, 0xc3, 0x69, 0xd6, 0xd7, 0x8a,
+    0x20, 0x1b, 0xeb, 0x8f, 0xb2, 0xff, 0xec, 0x6d, 0x76, 0x04, 0xf8, 0xc2,
+    0x58, 0x9b, 0xf2, 0x20, 0x53, 0xc4, 0x74, 0x91, 0x19, 0xdd, 0x2d, 0x12,
+    0x53, 0xc7, 0x6e, 0xd0, 0x02, 0x51, 0x3c, 0xa6, 0x7d, 0x80, 0x75, 0x6b,
+    0x1d, 0xdf, 0xf8, 0x6a, 0x52, 0xbb, 0x81, 0xf8, 0x30, 0x45, 0xef, 0x51,
+    0x85, 0x36, 0xbe, 0x8e, 0xcf, 0x0b, 0x9a, 0x46, 0xe8, 0x3f, 0x99, 0xfd,
+    0xf7, 0xd9, 0x3e, 0x84, 0xe5, 0xe3, 0x37, 0xcf, 0x98, 0x7f, 0xeb, 0x5e,
+    0x5a, 0x53, 0x77, 0x1c, 0x20, 0xdc, 0xf1, 0x20, 0x99, 0xec, 0x60, 0x40,
+    0x93, 0xef, 0x5c, 0x1c, 0x81, 0xe2, 0xa5, 0xad, 0x2a, 0xc2, 0xdb, 0x6b,
+    0xc1, 0x7e, 0x8f, 0xa9, 0x23, 0x5b, 0xd9, 0x0d, 0xfe, 0xa0, 0xac, 0x11,
+    0x28, 0xba, 0x8e, 0x92, 0x07, 0x2d, 0x07, 0x40, 0x83, 0x14, 0x4c, 0x35,
+    0x8d, 0xd0, 0x11, 0xff, 0x98, 0xdb, 0x00, 0x30, 0x6f, 0x65, 0xb6, 0xa0,
+    0x7f, 0x9c, 0x08, 0xb8, 0xce, 0xb3, 0xa8, 0x42, 0xd3, 0x84, 0x45, 0xe1,
+    0xe3, 0x8f, 0xa6, 0x89, 0x21, 0xd7, 0x74, 0x02, 0x4d, 0x64, 0xdf, 0x54,
+    0x15, 0x9e, 0xba, 0x12, 0x49, 0x09, 0x41, 0xf6, 0x10, 0x24, 0xa1, 0x84,
+    0x15, 0xfd, 0x68, 0x6a, 0x57, 0x66, 0xb3, 0x6d, 0x4c, 0xea, 0xbf, 0xbc,
+    0x60, 0x3f, 0x52, 0x1c, 0x44, 0x1b, 0xc0, 0x4a, 0x25, 0xe3, 0xd9, 0x4c,
+    0x9a, 0x74, 0xad, 0xfc, 0x9e, 0x8d, 0x0b, 0x18, 0x66, 0x24, 0xd1, 0x06,
+    0xac, 0x68, 0xc1, 0xae, 0x14, 0xce, 0xb1, 0xf3, 0x86, 0x9f, 0x87, 0x11,
+    0xd7, 0x9f, 0x30, 0x92, 0xdb, 0xec, 0x0b, 0x4a, 0xe8, 0xf6, 0x53, 0x36,
+    0x68, 0x12, 0x11, 0x5e, 0xe0, 0x34, 0xa4, 0xff, 0x00, 0x0a, 0x26, 0xb8,
+    0x62, 0x79, 0x9c, 0x0c, 0xd5, 0xe5, 0xf5, 0x1c, 0x1a, 0x16, 0x84, 0x4d,
+    0x8e, 0x5d, 0x31, 0x7e, 0xf7, 0xe2, 0xd3, 0xa1, 0x41, 0x90, 0x61, 0x5d,
+    0x04, 0xb2, 0x9a, 0x18, 0x9e, 0x54, 0xfb, 0xd1, 0x61, 0x95, 0x1b, 0x08,
+    0xca, 0x7c, 0x49, 0x44, 0x74, 0x1d, 0x2f, 0xca, 0xc4, 0x7a, 0xe1, 0x8b,
+    0x2f, 0xbb, 0x96, 0xee, 0x19, 0x8a, 0x5d, 0xfb, 0x3e, 0x82, 0xe7, 0x15,
+    0xdb, 0x29, 0x14, 0xee, 0xc9, 0x4d, 0x9a, 0xfb, 0x9f, 0x8a, 0xbb, 0x17,
+    0x37, 0x1b, 0x6e, 0x28, 0x6c, 0xf9, 0xff, 0xb5, 0xb5, 0x8b, 0x9d, 0x88,
+    0x20, 0x08, 0x10, 0xd7, 0xca, 0x58, 0xf6, 0xe1, 0x32, 0x91, 0x6f, 0x36,
+    0xc0, 0xad, 0xc1, 0x57, 0x5d, 0x76, 0x31, 0x43, 0xf3, 0xdd, 0xec, 0xf1,
+    0xa9, 0x79, 0xe9, 0xe9, 0x85, 0xd7, 0x91, 0xc7, 0x31, 0x62, 0x3c, 0xd2,
+    0x90, 0x2c, 0x9c, 0xa4, 0x56, 0x37, 0x7b, 0xbe, 0x40, 0x58, 0xc0, 0x81,
+    0x83, 0x22, 0xe8, 0x13, 0x79, 0x18, 0xdb, 0x3a, 0x1b, 0x31, 0x0d, 0x00,
+    0x6c, 0x22, 0x62, 0x75, 0x70, 0xd8, 0x96, 0x59, 0x99, 0x44, 0x79, 0x71,
+    0xa6, 0x76, 0x81, 0x28, 0xb2, 0x65, 0xe8, 0x47, 0x14, 0xc6, 0x39, 0x06,
+};
+
+enum spake2_state_t {
+  spake2_state_init = 0,
+  spake2_state_msg_generated,
+  spake2_state_key_generated,
+};
+
+struct spake2_ctx_st {
+  uint8_t private_key[32];
+  uint8_t my_msg[32];
+  uint8_t password_scalar[32];
+  uint8_t password_hash[SHA512_DIGEST_LENGTH];
+  uint8_t *my_name;
+  size_t my_name_len;
+  uint8_t *their_name;
+  size_t their_name_len;
+  enum spake2_role_t my_role;
+  enum spake2_state_t state;
+};
+
+SPAKE2_CTX *SPAKE2_CTX_new(enum spake2_role_t my_role,
+                           const uint8_t *my_name, size_t my_name_len,
+                           const uint8_t *their_name, size_t their_name_len) {
+  SPAKE2_CTX *ctx = OPENSSL_malloc(sizeof(SPAKE2_CTX));
+  if (ctx == NULL) {
+    return NULL;
+  }
+
+  OPENSSL_memset(ctx, 0, sizeof(SPAKE2_CTX));
+  ctx->my_role = my_role;
+
+  CBS my_name_cbs, their_name_cbs;
+  CBS_init(&my_name_cbs, my_name, my_name_len);
+  CBS_init(&their_name_cbs, their_name, their_name_len);
+  if (!CBS_stow(&my_name_cbs, &ctx->my_name, &ctx->my_name_len) ||
+      !CBS_stow(&their_name_cbs, &ctx->their_name, &ctx->their_name_len)) {
+    SPAKE2_CTX_free(ctx);
+    return NULL;
+  }
+
+  return ctx;
+}
+
+void SPAKE2_CTX_free(SPAKE2_CTX *ctx) {
+  if (ctx == NULL) {
+    return;
+  }
+
+  OPENSSL_free(ctx->my_name);
+  OPENSSL_free(ctx->their_name);
+  OPENSSL_free(ctx);
+}
+
+/* left_shift_3 sets |n| to |n|*8, where |n| is represented in little-endian
+ * order. */
+static void left_shift_3(uint8_t n[32]) {
+  uint8_t carry = 0;
+  unsigned i;
+
+  for (i = 0; i < 32; i++) {
+    const uint8_t next_carry = n[i] >> 5;
+    n[i] = (n[i] << 3) | carry;
+    carry = next_carry;
+  }
+}
+
+int SPAKE2_generate_msg(SPAKE2_CTX *ctx, uint8_t *out, size_t *out_len,
+                         size_t max_out_len, const uint8_t *password,
+                         size_t password_len) {
+  if (ctx->state != spake2_state_init) {
+    return 0;
+  }
+
+  if (max_out_len < sizeof(ctx->my_msg)) {
+    return 0;
+  }
+
+  uint8_t private_tmp[64];
+  RAND_bytes(private_tmp, sizeof(private_tmp));
+  x25519_sc_reduce(private_tmp);
+  /* Multiply by the cofactor (eight) so that we'll clear it when operating on
+   * the peer's point later in the protocol. */
+  left_shift_3(private_tmp);
+  OPENSSL_memcpy(ctx->private_key, private_tmp, sizeof(ctx->private_key));
+
+  ge_p3 P;
+  x25519_ge_scalarmult_base(&P, ctx->private_key);
+
+  /* mask = h(password) * <N or M>. */
+  uint8_t password_tmp[SHA512_DIGEST_LENGTH];
+  SHA512(password, password_len, password_tmp);
+  OPENSSL_memcpy(ctx->password_hash, password_tmp, sizeof(ctx->password_hash));
+  x25519_sc_reduce(password_tmp);
+  OPENSSL_memcpy(ctx->password_scalar, password_tmp, sizeof(ctx->password_scalar));
+
+  ge_p3 mask;
+  x25519_ge_scalarmult_small_precomp(&mask, ctx->password_scalar,
+                              ctx->my_role == spake2_role_alice
+                                  ? kSpakeMSmallPrecomp
+                                  : kSpakeNSmallPrecomp);
+
+  /* P* = P + mask. */
+  ge_cached mask_cached;
+  x25519_ge_p3_to_cached(&mask_cached, &mask);
+  ge_p1p1 Pstar;
+  x25519_ge_add(&Pstar, &P, &mask_cached);
+
+  /* Encode P* */
+  ge_p2 Pstar_proj;
+  x25519_ge_p1p1_to_p2(&Pstar_proj, &Pstar);
+  x25519_ge_tobytes(ctx->my_msg, &Pstar_proj);
+
+  OPENSSL_memcpy(out, ctx->my_msg, sizeof(ctx->my_msg));
+  *out_len = sizeof(ctx->my_msg);
+  ctx->state = spake2_state_msg_generated;
+
+  return 1;
+}
+
+static void update_with_length_prefix(SHA512_CTX *sha, const uint8_t *data,
+                                      const size_t len) {
+  uint8_t len_le[8];
+  size_t l = len;
+  unsigned i;
+
+  for (i = 0; i < 8; i++) {
+    len_le[i] = l & 0xff;
+    l >>= 8;
+  }
+
+  SHA512_Update(sha, len_le, sizeof(len_le));
+  SHA512_Update(sha, data, len);
+}
+
+int SPAKE2_process_msg(SPAKE2_CTX *ctx, uint8_t *out_key, size_t *out_key_len,
+                       size_t max_out_key_len, const uint8_t *their_msg,
+                       size_t their_msg_len) {
+  if (ctx->state != spake2_state_msg_generated ||
+      their_msg_len != 32) {
+    return 0;
+  }
+
+  ge_p3 Qstar;
+  if (0 != x25519_ge_frombytes_vartime(&Qstar, their_msg)) {
+    /* Point received from peer was not on the curve. */
+    return 0;
+  }
+
+  /* Unmask peer's value. */
+  ge_p3 peers_mask;
+  x25519_ge_scalarmult_small_precomp(&peers_mask, ctx->password_scalar,
+                                    ctx->my_role == spake2_role_alice
+                                        ? kSpakeNSmallPrecomp
+                                        : kSpakeMSmallPrecomp);
+
+  ge_cached peers_mask_cached;
+  x25519_ge_p3_to_cached(&peers_mask_cached, &peers_mask);
+
+  ge_p1p1 Q_compl;
+  ge_p3 Q_ext;
+  x25519_ge_sub(&Q_compl, &Qstar, &peers_mask_cached);
+  x25519_ge_p1p1_to_p3(&Q_ext, &Q_compl);
+
+  ge_p2 dh_shared;
+  x25519_ge_scalarmult(&dh_shared, ctx->private_key, &Q_ext);
+
+  uint8_t dh_shared_encoded[32];
+  x25519_ge_tobytes(dh_shared_encoded, &dh_shared);
+
+  SHA512_CTX sha;
+  SHA512_Init(&sha);
+  if (ctx->my_role == spake2_role_alice) {
+    update_with_length_prefix(&sha, ctx->my_name, ctx->my_name_len);
+    update_with_length_prefix(&sha, ctx->their_name, ctx->their_name_len);
+    update_with_length_prefix(&sha, ctx->my_msg, sizeof(ctx->my_msg));
+    update_with_length_prefix(&sha, their_msg, 32);
+  } else {
+    update_with_length_prefix(&sha, ctx->their_name, ctx->their_name_len);
+    update_with_length_prefix(&sha, ctx->my_name, ctx->my_name_len);
+    update_with_length_prefix(&sha, their_msg, 32);
+    update_with_length_prefix(&sha, ctx->my_msg, sizeof(ctx->my_msg));
+  }
+  update_with_length_prefix(&sha, dh_shared_encoded, sizeof(dh_shared_encoded));
+  update_with_length_prefix(&sha, ctx->password_hash,
+                            sizeof(ctx->password_hash));
+
+  uint8_t key[SHA512_DIGEST_LENGTH];
+  SHA512_Final(key, &sha);
+
+  size_t to_copy = max_out_key_len;
+  if (to_copy > sizeof(key)) {
+    to_copy = sizeof(key);
+  }
+  OPENSSL_memcpy(out_key, key, to_copy);
+  *out_key_len = to_copy;
+  ctx->state = spake2_state_key_generated;
+
+  return 1;
+}
diff --git a/src/crypto/curve25519/spake25519_test.cc b/src/crypto/curve25519/spake25519_test.cc
new file mode 100644
index 0000000..3af073d
--- /dev/null
+++ b/src/crypto/curve25519/spake25519_test.cc
@@ -0,0 +1,170 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <string>
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/curve25519.h>
+
+#include "../internal.h"
+
+
+struct SPAKE2Run {
+  bool Run() {
+    bssl::UniquePtr<SPAKE2_CTX> alice(SPAKE2_CTX_new(
+        spake2_role_alice,
+        reinterpret_cast<const uint8_t *>(alice_names.first.data()),
+        alice_names.first.size(),
+        reinterpret_cast<const uint8_t *>(alice_names.second.data()),
+        alice_names.second.size()));
+    bssl::UniquePtr<SPAKE2_CTX> bob(SPAKE2_CTX_new(
+        spake2_role_bob,
+        reinterpret_cast<const uint8_t *>(bob_names.first.data()),
+        bob_names.first.size(),
+        reinterpret_cast<const uint8_t *>(bob_names.second.data()),
+        bob_names.second.size()));
+
+    if (!alice || !bob) {
+      return false;
+    }
+
+    uint8_t alice_msg[SPAKE2_MAX_MSG_SIZE];
+    uint8_t bob_msg[SPAKE2_MAX_MSG_SIZE];
+    size_t alice_msg_len, bob_msg_len;
+
+    if (!SPAKE2_generate_msg(
+            alice.get(), alice_msg, &alice_msg_len, sizeof(alice_msg),
+            reinterpret_cast<const uint8_t *>(alice_password.data()),
+            alice_password.size()) ||
+        !SPAKE2_generate_msg(
+            bob.get(), bob_msg, &bob_msg_len, sizeof(bob_msg),
+            reinterpret_cast<const uint8_t *>(bob_password.data()),
+            bob_password.size())) {
+      return false;
+    }
+
+    if (alice_corrupt_msg_bit >= 0 &&
+        static_cast<size_t>(alice_corrupt_msg_bit) < 8 * alice_msg_len) {
+      alice_msg[alice_corrupt_msg_bit/8] ^= 1 << (alice_corrupt_msg_bit & 7);
+    }
+
+    uint8_t alice_key[64], bob_key[64];
+    size_t alice_key_len, bob_key_len;
+
+    if (!SPAKE2_process_msg(alice.get(), alice_key, &alice_key_len,
+                            sizeof(alice_key), bob_msg, bob_msg_len) ||
+        !SPAKE2_process_msg(bob.get(), bob_key, &bob_key_len, sizeof(bob_key),
+                            alice_msg, alice_msg_len)) {
+      return false;
+    }
+
+    key_matches_ = (alice_key_len == bob_key_len &&
+                    OPENSSL_memcmp(alice_key, bob_key, alice_key_len) == 0);
+
+    return true;
+  }
+
+  bool key_matches() const {
+    return key_matches_;
+  }
+
+  std::string alice_password = "password";
+  std::string bob_password = "password";
+  std::pair<std::string, std::string> alice_names = {"alice", "bob"};
+  std::pair<std::string, std::string> bob_names = {"bob", "alice"};
+  int alice_corrupt_msg_bit = -1;
+
+ private:
+  bool key_matches_ = false;
+};
+
+static bool TestSPAKE2() {
+  for (unsigned i = 0; i < 20; i++) {
+    SPAKE2Run spake2;
+    if (!spake2.Run()) {
+      fprintf(stderr, "TestSPAKE2: SPAKE2 failed.\n");
+      return false;
+    }
+
+    if (!spake2.key_matches()) {
+      fprintf(stderr, "Key didn't match for equal passwords.\n");
+      return false;
+    }
+  }
+
+  return true;
+}
+
+static bool TestWrongPassword() {
+  SPAKE2Run spake2;
+  spake2.bob_password = "wrong password";
+  if (!spake2.Run()) {
+    fprintf(stderr, "TestSPAKE2: SPAKE2 failed.\n");
+    return false;
+  }
+
+  if (spake2.key_matches()) {
+    fprintf(stderr, "Key matched for unequal passwords.\n");
+    return false;
+  }
+
+  return true;
+}
+
+static bool TestWrongNames() {
+  SPAKE2Run spake2;
+  spake2.alice_names.second = "charlie";
+  spake2.bob_names.second = "charlie";
+  if (!spake2.Run()) {
+    fprintf(stderr, "TestSPAKE2: SPAKE2 failed.\n");
+    return false;
+  }
+
+  if (spake2.key_matches()) {
+    fprintf(stderr, "Key matched for unequal names.\n");
+    return false;
+  }
+
+  return true;
+}
+
+static bool TestCorruptMessages() {
+  for (int i = 0; i < 8 * SPAKE2_MAX_MSG_SIZE; i++) {
+    SPAKE2Run spake2;
+    spake2.alice_corrupt_msg_bit = i;
+    if (spake2.Run() && spake2.key_matches()) {
+      fprintf(stderr, "Passed after corrupting Alice's message, bit %d\n", i);
+      return false;
+    }
+  }
+
+  return true;
+}
+
+/* TODO(agl): add tests with fixed vectors once SPAKE2 is nailed down. */
+
+int main(int argc, char **argv) {
+  if (!TestSPAKE2() ||
+      !TestWrongPassword() ||
+      !TestWrongNames() ||
+      !TestCorruptMessages()) {
+    return 1;
+  }
+
+  printf("PASS\n");
+  return 0;
+}
diff --git a/src/crypto/curve25519/x25519-x86_64.c b/src/crypto/curve25519/x25519-x86_64.c
index 9776c75..9c3d414 100644
--- a/src/crypto/curve25519/x25519-x86_64.c
+++ b/src/crypto/curve25519/x25519-x86_64.c
@@ -1,7 +1,29 @@
+/* Copyright (c) 2015, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+/* This code is mostly taken from the ref10 version of Ed25519 in SUPERCOP
+ * 20141124 (http://bench.cr.yp.to/supercop.html). That code is released as
+ * public domain but this file has the ISC license just to keep licencing
+ * simple.
+ *
+ * The field functions are shared by Ed25519 and X25519 where possible. */
+
 #include <openssl/curve25519.h>
 
 #include <string.h>
 
+#include "../internal.h"
 #include "internal.h"
 
 
@@ -207,7 +229,7 @@
 void x25519_x86_64(uint8_t out[32], const uint8_t scalar[32],
                   const uint8_t point[32]) {
   uint8_t e[32];
-  memcpy(e, scalar, sizeof(e));
+  OPENSSL_memcpy(e, scalar, sizeof(e));
 
   e[0] &= 248;
   e[31] &= 127;
diff --git a/src/crypto/curve25519/x25519_test.cc b/src/crypto/curve25519/x25519_test.cc
index 85ee4a2..903892f 100644
--- a/src/crypto/curve25519/x25519_test.cc
+++ b/src/crypto/curve25519/x25519_test.cc
@@ -16,12 +16,16 @@
 #include <stdio.h>
 #include <string.h>
 
+#include <gtest/gtest.h>
+
 #include <openssl/curve25519.h>
 
+#include "../internal.h"
+#include "../test/test_util.h"
 
-static bool TestX25519() {
-  /* Taken from
-   * https://tools.ietf.org/html/draft-irtf-cfrg-curves-11#section-5.2 */
+
+TEST(X25519Test, TestVector) {
+  // Taken from https://tools.ietf.org/html/rfc7748#section-5.2
   static const uint8_t kScalar1[32] = {
       0xa5, 0x46, 0xe3, 0x6b, 0xf0, 0x52, 0x7c, 0x9d, 0x3b, 0x16, 0x15,
       0x4b, 0x82, 0x46, 0x5e, 0xdd, 0x62, 0x14, 0x4c, 0x0a, 0xc1, 0xfc,
@@ -34,17 +38,14 @@
   };
 
   uint8_t out[32];
-  X25519(out, kScalar1, kPoint1);
+  EXPECT_TRUE(X25519(out, kScalar1, kPoint1));
 
   static const uint8_t kExpected1[32] = {
       0xc3, 0xda, 0x55, 0x37, 0x9d, 0xe9, 0xc6, 0x90, 0x8e, 0x94, 0xea,
       0x4d, 0xf2, 0x8d, 0x08, 0x4f, 0x32, 0xec, 0xcf, 0x03, 0x49, 0x1c,
       0x71, 0xf7, 0x54, 0xb4, 0x07, 0x55, 0x77, 0xa2, 0x85, 0x52,
   };
-  if (memcmp(kExpected1, out, sizeof(out)) != 0) {
-    fprintf(stderr, "X25519 test one failed.\n");
-    return false;
-  }
+  EXPECT_EQ(Bytes(kExpected1), Bytes(out));
 
   static const uint8_t kScalar2[32] = {
       0x4b, 0x66, 0xe9, 0xd4, 0xd1, 0xb4, 0x67, 0x3c, 0x5a, 0xd2, 0x26,
@@ -57,22 +58,17 @@
       0x3c, 0x3e, 0xfc, 0x4c, 0xd5, 0x49, 0xc7, 0x15, 0xa4, 0x93,
   };
 
-  X25519(out, kScalar2, kPoint2);
+  EXPECT_TRUE(X25519(out, kScalar2, kPoint2));
 
   static const uint8_t kExpected2[32] = {
       0x95, 0xcb, 0xde, 0x94, 0x76, 0xe8, 0x90, 0x7d, 0x7a, 0xad, 0xe4,
       0x5c, 0xb4, 0xb8, 0x73, 0xf8, 0x8b, 0x59, 0x5a, 0x68, 0x79, 0x9f,
       0xa1, 0x52, 0xe6, 0xf8, 0xf7, 0x64, 0x7a, 0xac, 0x79, 0x57,
   };
-  if (memcmp(kExpected2, out, sizeof(out)) != 0) {
-    fprintf(stderr, "X25519 test two failed.\n");
-    return false;
-  }
-
-  return true;
+  EXPECT_EQ(Bytes(kExpected2), Bytes(out));
 }
 
-static bool TestX25519SmallOrder() {
+TEST(X25519Test, SmallOrder) {
   static const uint8_t kSmallOrderPoint[32] = {
       0xe0, 0xeb, 0x7a, 0x7c, 0x3b, 0x41, 0xb8, 0xae, 0x16, 0x56, 0xe3,
       0xfa, 0xf1, 0x9f, 0xc4, 0x6a, 0xda, 0x09, 0x8d, 0xeb, 0x9c, 0x32,
@@ -80,26 +76,25 @@
   };
 
   uint8_t out[32], private_key[32];
-  memset(private_key, 0x11, sizeof(private_key));
+  OPENSSL_memset(private_key, 0x11, sizeof(private_key));
 
-  if (X25519(out, private_key, kSmallOrderPoint)) {
-    fprintf(stderr, "X25519 returned success with a small-order input.\n");
-    return false;
-  }
+  OPENSSL_memset(out, 0xff, sizeof(out));
+  EXPECT_FALSE(X25519(out, private_key, kSmallOrderPoint))
+      << "X25519 returned success with a small-order input.";
 
-  return true;
+  // For callers which don't check, |out| should still be filled with zeros.
+  static const uint8_t kZeros[32] = {0};
+  EXPECT_EQ(Bytes(kZeros), Bytes(out));
 }
 
-static bool TestX25519Iterated() {
-  /* Taken from
-   * https://tools.ietf.org/html/draft-irtf-cfrg-curves-11#section-5.2 */
+TEST(X25519Test, Iterated) {
+  // Taken from https://tools.ietf.org/html/rfc7748#section-5.2.
   uint8_t scalar[32] = {9}, point[32] = {9}, out[32];
 
-  unsigned i;
-  for (i = 0; i < 1000; i++) {
-    X25519(out, scalar, point);
-    memcpy(point, scalar, sizeof(point));
-    memcpy(scalar, out, sizeof(scalar));
+  for (unsigned i = 0; i < 1000; i++) {
+    EXPECT_TRUE(X25519(out, scalar, point));
+    OPENSSL_memcpy(point, scalar, sizeof(point));
+    OPENSSL_memcpy(scalar, out, sizeof(scalar));
   }
 
   static const uint8_t kExpected[32] = {
@@ -108,21 +103,5 @@
       0xe3, 0x87, 0x5f, 0x2e, 0xb9, 0x4d, 0x99, 0x53, 0x2c, 0x51,
   };
 
-  if (memcmp(kExpected, scalar, sizeof(kExpected)) != 0) {
-    fprintf(stderr, "Iterated X25519 test failed\n");
-    return false;
-  }
-
-  return true;
-}
-
-int main(int argc, char **argv) {
-  if (!TestX25519() ||
-      !TestX25519Iterated() ||
-      !TestX25519SmallOrder()) {
-    return 1;
-  }
-
-  printf("PASS\n");
-  return 0;
+  EXPECT_EQ(Bytes(kExpected), Bytes(scalar));
 }
diff --git a/src/crypto/des/des.c b/src/crypto/des/des.c
index 1d27ebe..cada7d1 100644
--- a/src/crypto/des/des.c
+++ b/src/crypto/des/des.c
@@ -291,7 +291,7 @@
 
 #define HPERM_OP(a, t, n, m)                  \
   ((t) = ((((a) << (16 - (n))) ^ (a)) & (m)), \
-   (a) = (a) ^ (t) ^ (t >> (16 - (n))))
+   (a) = (a) ^ (t) ^ ((t) >> (16 - (n))))
 
 void DES_set_key(const DES_cblock *key, DES_key_schedule *schedule) {
   static const int shifts2[16] = {0, 0, 1, 1, 1, 1, 1, 1,
diff --git a/src/crypto/des/internal.h b/src/crypto/des/internal.h
index 00b4558..21eb933 100644
--- a/src/crypto/des/internal.h
+++ b/src/crypto/des/internal.h
@@ -64,45 +64,51 @@
 #endif
 
 
-#define c2l(c, l)                                                 \
-  (l = ((uint32_t)(*((c)++))), l |= ((uint32_t)(*((c)++))) << 8L, \
-   l |= ((uint32_t)(*((c)++))) << 16L, l |= ((uint32_t)(*((c)++))) << 24L)
+#define c2l(c, l)                         \
+  do {                                    \
+    (l) = ((uint32_t)(*((c)++)));         \
+    (l) |= ((uint32_t)(*((c)++))) << 8L;  \
+    (l) |= ((uint32_t)(*((c)++))) << 16L; \
+    (l) |= ((uint32_t)(*((c)++))) << 24L; \
+  } while (0)
 
-#define l2c(l, c)                                   \
-  (*((c)++) = (unsigned char)(((l)) & 0xff),        \
-   *((c)++) = (unsigned char)(((l) >> 8L) & 0xff),  \
-   *((c)++) = (unsigned char)(((l) >> 16L) & 0xff), \
-   *((c)++) = (unsigned char)(((l) >> 24L) & 0xff))
+#define l2c(l, c)                                    \
+  do {                                               \
+    *((c)++) = (unsigned char)(((l)) & 0xff);        \
+    *((c)++) = (unsigned char)(((l) >> 8L) & 0xff);  \
+    *((c)++) = (unsigned char)(((l) >> 16L) & 0xff); \
+    *((c)++) = (unsigned char)(((l) >> 24L) & 0xff); \
+  } while (0)
 
 /* NOTE - c is not incremented as per c2l */
-#define c2ln(c, l1, l2, n)                   \
-  {                                          \
-    c += n;                                  \
-    l1 = l2 = 0;                             \
-    switch (n) {                             \
-      case 8:                                \
-        l2 = ((uint32_t)(*(--(c)))) << 24L;  \
-      case 7:                                \
-        l2 |= ((uint32_t)(*(--(c)))) << 16L; \
-      case 6:                                \
-        l2 |= ((uint32_t)(*(--(c)))) << 8L;  \
-      case 5:                                \
-        l2 |= ((uint32_t)(*(--(c))));        \
-      case 4:                                \
-        l1 = ((uint32_t)(*(--(c)))) << 24L;  \
-      case 3:                                \
-        l1 |= ((uint32_t)(*(--(c)))) << 16L; \
-      case 2:                                \
-        l1 |= ((uint32_t)(*(--(c)))) << 8L;  \
-      case 1:                                \
-        l1 |= ((uint32_t)(*(--(c))));        \
-    }                                        \
-  }
+#define c2ln(c, l1, l2, n)                     \
+  do {                                         \
+    (c) += (n);                                \
+    (l1) = (l2) = 0;                           \
+    switch (n) {                               \
+      case 8:                                  \
+        (l2) = ((uint32_t)(*(--(c)))) << 24L;  \
+      case 7:                                  \
+        (l2) |= ((uint32_t)(*(--(c)))) << 16L; \
+      case 6:                                  \
+        (l2) |= ((uint32_t)(*(--(c)))) << 8L;  \
+      case 5:                                  \
+        (l2) |= ((uint32_t)(*(--(c))));        \
+      case 4:                                  \
+        (l1) = ((uint32_t)(*(--(c)))) << 24L;  \
+      case 3:                                  \
+        (l1) |= ((uint32_t)(*(--(c)))) << 16L; \
+      case 2:                                  \
+        (l1) |= ((uint32_t)(*(--(c)))) << 8L;  \
+      case 1:                                  \
+        (l1) |= ((uint32_t)(*(--(c))));        \
+    }                                          \
+  } while (0)
 
 /* NOTE - c is not incremented as per l2c */
 #define l2cn(l1, l2, c, n)                                \
-  {                                                       \
-    c += n;                                               \
+  do {                                                    \
+    (c) += (n);                                           \
     switch (n) {                                          \
       case 8:                                             \
         *(--(c)) = (unsigned char)(((l2) >> 24L) & 0xff); \
@@ -121,7 +127,7 @@
       case 1:                                             \
         *(--(c)) = (unsigned char)(((l1)) & 0xff);        \
     }                                                     \
-  }
+  } while (0)
 
 /* IP and FP
  * The problem is more of a geometric problem that random bit fiddling.
@@ -160,44 +166,50 @@
 I first got ~42 operations without xors.  When I remembered
 how to use xors :-) I got it to its final state.
 */
-#define PERM_OP(a, b, t, n, m) \
-  ((t) = ((((a) >> (n)) ^ (b)) & (m)), (b) ^= (t), (a) ^= ((t) << (n)))
+#define PERM_OP(a, b, t, n, m)          \
+  do {                                  \
+    (t) = ((((a) >> (n)) ^ (b)) & (m)); \
+    (b) ^= (t);                         \
+    (a) ^= ((t) << (n));                \
+  } while (0)
 
 #define IP(l, r)                        \
-  {                                     \
+  do {                                  \
     uint32_t tt;                        \
     PERM_OP(r, l, tt, 4, 0x0f0f0f0fL);  \
     PERM_OP(l, r, tt, 16, 0x0000ffffL); \
     PERM_OP(r, l, tt, 2, 0x33333333L);  \
     PERM_OP(l, r, tt, 8, 0x00ff00ffL);  \
     PERM_OP(r, l, tt, 1, 0x55555555L);  \
-  }
+  } while (0)
 
 #define FP(l, r)                        \
-  {                                     \
+  do {                                  \
     uint32_t tt;                        \
     PERM_OP(l, r, tt, 1, 0x55555555L);  \
     PERM_OP(r, l, tt, 8, 0x00ff00ffL);  \
     PERM_OP(l, r, tt, 2, 0x33333333L);  \
     PERM_OP(r, l, tt, 16, 0x0000ffffL); \
     PERM_OP(l, r, tt, 4, 0x0f0f0f0fL);  \
-  }
+  } while (0)
 
 #define LOAD_DATA(ks, R, S, u, t, E0, E1) \
-  u = R ^ ks->subkeys[S][0];              \
-  t = R ^ ks->subkeys[S][1]
+  do {                                    \
+    (u) = (R) ^ (ks)->subkeys[S][0];      \
+    (t) = (R) ^ (ks)->subkeys[S][1];      \
+  } while (0)
 
 #define D_ENCRYPT(ks, LL, R, S)                                                \
-  {                                                                            \
+  do {                                                                         \
     LOAD_DATA(ks, R, S, u, t, E0, E1);                                         \
     t = ROTATE(t, 4);                                                          \
-    LL ^=                                                                      \
+    (LL) ^=                                                                    \
         DES_SPtrans[0][(u >> 2L) & 0x3f] ^ DES_SPtrans[2][(u >> 10L) & 0x3f] ^ \
         DES_SPtrans[4][(u >> 18L) & 0x3f] ^                                    \
         DES_SPtrans[6][(u >> 26L) & 0x3f] ^ DES_SPtrans[1][(t >> 2L) & 0x3f] ^ \
         DES_SPtrans[3][(t >> 10L) & 0x3f] ^                                    \
         DES_SPtrans[5][(t >> 18L) & 0x3f] ^ DES_SPtrans[7][(t >> 26L) & 0x3f]; \
-  }
+  } while (0)
 
 #define ITERATIONS 16
 #define HALF_ITERATIONS 8
diff --git a/src/crypto/dh/CMakeLists.txt b/src/crypto/dh/CMakeLists.txt
index f1e8616..83ae6d4 100644
--- a/src/crypto/dh/CMakeLists.txt
+++ b/src/crypto/dh/CMakeLists.txt
@@ -10,14 +10,3 @@
   check.c
   dh_asn1.c
 )
-
-add_executable(
-  dh_test
-
-  dh_test.cc
-
-  $<TARGET_OBJECTS:test_support>
-)
-
-target_link_libraries(dh_test crypto)
-add_dependencies(all_tests dh_test)
diff --git a/src/crypto/dh/check.c b/src/crypto/dh/check.c
index 06af6f2..e3c111b 100644
--- a/src/crypto/dh/check.c
+++ b/src/crypto/dh/check.c
@@ -58,34 +58,54 @@
 
 #include <openssl/bn.h>
 
-#include "internal.h"
-
 
 int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret) {
-  int ok = 0;
-  BIGNUM q;
-
   *ret = 0;
-  BN_init(&q);
-  if (!BN_set_word(&q, 1)) {
+
+  BN_CTX *ctx = BN_CTX_new();
+  if (ctx == NULL) {
+    return 0;
+  }
+  BN_CTX_start(ctx);
+
+  int ok = 0;
+
+  /* Check |pub_key| is greater than 1. */
+  BIGNUM *tmp = BN_CTX_get(ctx);
+  if (tmp == NULL ||
+      !BN_set_word(tmp, 1)) {
     goto err;
   }
-
-  if (BN_cmp(pub_key, &q) <= 0) {
+  if (BN_cmp(pub_key, tmp) <= 0) {
     *ret |= DH_CHECK_PUBKEY_TOO_SMALL;
   }
-  if (!BN_copy(&q, dh->p) ||
-      !BN_sub_word(&q, 1)) {
+
+  /* Check |pub_key| is less than |dh->p| - 1. */
+  if (!BN_copy(tmp, dh->p) ||
+      !BN_sub_word(tmp, 1)) {
     goto err;
   }
-  if (BN_cmp(pub_key, &q) >= 0) {
+  if (BN_cmp(pub_key, tmp) >= 0) {
     *ret |= DH_CHECK_PUBKEY_TOO_LARGE;
   }
 
+  if (dh->q != NULL) {
+    /* Check |pub_key|^|dh->q| is 1 mod |dh->p|. This is necessary for RFC 5114
+     * groups which are not safe primes but pick a generator on a prime-order
+     * subgroup of size |dh->q|. */
+    if (!BN_mod_exp_mont(tmp, pub_key, dh->q, dh->p, ctx, NULL)) {
+      goto err;
+    }
+    if (!BN_is_one(tmp)) {
+      *ret |= DH_CHECK_PUBKEY_INVALID;
+    }
+  }
+
   ok = 1;
 
 err:
-  BN_free(&q);
+  BN_CTX_end(ctx);
+  BN_CTX_free(ctx);
   return ok;
 }
 
@@ -98,7 +118,7 @@
    *   for 5, p mod 10 == 3 or 7
    * should hold.
    */
-  int ok = 0;
+  int ok = 0, r;
   BN_CTX *ctx = NULL;
   BN_ULONG l;
   BIGNUM *t1 = NULL, *t2 = NULL;
@@ -125,14 +145,18 @@
       *ret |= DH_CHECK_NOT_SUITABLE_GENERATOR;
     } else {
       /* Check g^q == 1 mod p */
-      if (!BN_mod_exp(t1, dh->g, dh->q, dh->p, ctx)) {
+      if (!BN_mod_exp_mont(t1, dh->g, dh->q, dh->p, ctx, NULL)) {
         goto err;
       }
       if (!BN_is_one(t1)) {
         *ret |= DH_CHECK_NOT_SUITABLE_GENERATOR;
       }
     }
-    if (!BN_is_prime_ex(dh->q, BN_prime_checks, ctx, NULL)) {
+    r = BN_is_prime_ex(dh->q, BN_prime_checks, ctx, NULL);
+    if (r < 0) {
+      goto err;
+    }
+    if (!r) {
       *ret |= DH_CHECK_Q_NOT_PRIME;
     }
     /* Check p == 1 mod q  i.e. q divides p - 1 */
@@ -147,11 +171,17 @@
     }
   } else if (BN_is_word(dh->g, DH_GENERATOR_2)) {
     l = BN_mod_word(dh->p, 24);
+    if (l == (BN_ULONG)-1) {
+      goto err;
+    }
     if (l != 11) {
       *ret |= DH_CHECK_NOT_SUITABLE_GENERATOR;
     }
   } else if (BN_is_word(dh->g, DH_GENERATOR_5)) {
     l = BN_mod_word(dh->p, 10);
+    if (l == (BN_ULONG)-1) {
+      goto err;
+    }
     if (l != 3 && l != 7) {
       *ret |= DH_CHECK_NOT_SUITABLE_GENERATOR;
     }
@@ -159,13 +189,21 @@
     *ret |= DH_CHECK_UNABLE_TO_CHECK_GENERATOR;
   }
 
-  if (!BN_is_prime_ex(dh->p, BN_prime_checks, ctx, NULL)) {
+  r = BN_is_prime_ex(dh->p, BN_prime_checks, ctx, NULL);
+  if (r < 0) {
+    goto err;
+  }
+  if (!r) {
     *ret |= DH_CHECK_P_NOT_PRIME;
   } else if (!dh->q) {
     if (!BN_rshift1(t1, dh->p)) {
       goto err;
     }
-    if (!BN_is_prime_ex(t1, BN_prime_checks, ctx, NULL)) {
+    r = BN_is_prime_ex(t1, BN_prime_checks, ctx, NULL);
+    if (r < 0) {
+      goto err;
+    }
+    if (!r) {
       *ret |= DH_CHECK_P_NOT_SAFE_PRIME;
     }
   }
diff --git a/src/crypto/dh/dh.c b/src/crypto/dh/dh.c
index bf6196c..33c36f3 100644
--- a/src/crypto/dh/dh.c
+++ b/src/crypto/dh/dh.c
@@ -65,7 +65,6 @@
 #include <openssl/mem.h>
 #include <openssl/thread.h>
 
-#include "internal.h"
 #include "../internal.h"
 
 
@@ -74,13 +73,13 @@
 static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT;
 
 DH *DH_new(void) {
-  DH *dh = (DH *)OPENSSL_malloc(sizeof(DH));
+  DH *dh = OPENSSL_malloc(sizeof(DH));
   if (dh == NULL) {
     OPENSSL_PUT_ERROR(DH, ERR_R_MALLOC_FAILURE);
     return NULL;
   }
 
-  memset(dh, 0, sizeof(DH));
+  OPENSSL_memset(dh, 0, sizeof(DH));
 
   CRYPTO_MUTEX_init(&dh->method_mont_p_lock);
 
@@ -115,6 +114,29 @@
   OPENSSL_free(dh);
 }
 
+void DH_get0_key(const DH *dh, const BIGNUM **out_pub_key,
+                 const BIGNUM **out_priv_key) {
+  if (out_pub_key != NULL) {
+    *out_pub_key = dh->pub_key;
+  }
+  if (out_priv_key != NULL) {
+    *out_priv_key = dh->priv_key;
+  }
+}
+
+void DH_get0_pqg(const DH *dh, const BIGNUM **out_p, const BIGNUM **out_q,
+                 const BIGNUM **out_g) {
+  if (out_p != NULL) {
+    *out_p = dh->p;
+  }
+  if (out_q != NULL) {
+    *out_q = dh->q;
+  }
+  if (out_g != NULL) {
+    *out_g = dh->g;
+  }
+}
+
 int DH_generate_parameters_ex(DH *dh, int prime_bits, int generator, BN_GENCB *cb) {
   /* We generate DH parameters as follows
    * find a prime q which is prime_bits/2 bits long.
@@ -234,11 +256,8 @@
 int DH_generate_key(DH *dh) {
   int ok = 0;
   int generate_new_key = 0;
-  unsigned l;
   BN_CTX *ctx = NULL;
-  BN_MONT_CTX *mont = NULL;
   BIGNUM *pub_key = NULL, *priv_key = NULL;
-  BIGNUM local_priv;
 
   if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) {
     OPENSSL_PUT_ERROR(DH, DH_R_MODULUS_TOO_LARGE);
@@ -269,31 +288,36 @@
     pub_key = dh->pub_key;
   }
 
-  mont = BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock,
-                                dh->p, ctx);
-  if (!mont) {
+  if (!BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock,
+                              dh->p, ctx)) {
     goto err;
   }
 
   if (generate_new_key) {
     if (dh->q) {
-      do {
-        if (!BN_rand_range(priv_key, dh->q)) {
-          goto err;
-        }
-      } while (BN_is_zero(priv_key) || BN_is_one(priv_key));
+      if (!BN_rand_range_ex(priv_key, 2, dh->q)) {
+        goto err;
+      }
     } else {
       /* secret exponent length */
-      DH_check_standard_parameters(dh);
-      l = dh->priv_length ? dh->priv_length : BN_num_bits(dh->p) - 1;
-      if (!BN_rand(priv_key, l, 0, 0)) {
+      unsigned priv_bits = dh->priv_length;
+      if (priv_bits == 0) {
+        const unsigned p_bits = BN_num_bits(dh->p);
+        if (p_bits == 0) {
+          goto err;
+        }
+
+        priv_bits = p_bits - 1;
+      }
+
+      if (!BN_rand(priv_key, priv_bits, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY)) {
         goto err;
       }
     }
   }
 
-  BN_with_flags(&local_priv, priv_key, BN_FLG_CONSTTIME);
-  if (!BN_mod_exp_mont(pub_key, dh->g, &local_priv, dh->p, ctx, mont)) {
+  if (!BN_mod_exp_mont_consttime(pub_key, dh->g, priv_key, dh->p, ctx,
+                                 dh->method_mont_p)) {
     goto err;
   }
 
@@ -318,11 +342,9 @@
 
 int DH_compute_key(unsigned char *out, const BIGNUM *peers_key, DH *dh) {
   BN_CTX *ctx = NULL;
-  BN_MONT_CTX *mont = NULL;
   BIGNUM *shared_key;
   int ret = -1;
   int check_result;
-  BIGNUM local_priv;
 
   if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) {
     OPENSSL_PUT_ERROR(DH, DH_R_MODULUS_TOO_LARGE);
@@ -344,9 +366,8 @@
     goto err;
   }
 
-  mont = BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock,
-                                dh->p, ctx);
-  if (!mont) {
+  if (!BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock,
+                              dh->p, ctx)) {
     goto err;
   }
 
@@ -355,9 +376,8 @@
     goto err;
   }
 
-  BN_with_flags(&local_priv, dh->priv_key, BN_FLG_CONSTTIME);
-  if (!BN_mod_exp_mont(shared_key, peers_key, &local_priv, dh->p, ctx,
-                       mont)) {
+  if (!BN_mod_exp_mont_consttime(shared_key, peers_key, dh->priv_key, dh->p,
+                                 ctx, dh->method_mont_p)) {
     OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB);
     goto err;
   }
diff --git a/src/crypto/dh/dh_asn1.c b/src/crypto/dh/dh_asn1.c
index 73cd4df..1a147ee 100644
--- a/src/crypto/dh/dh_asn1.c
+++ b/src/crypto/dh/dh_asn1.c
@@ -55,30 +55,106 @@
 
 #include <openssl/dh.h>
 
-#include <openssl/asn1.h>
-#include <openssl/asn1t.h>
+#include <assert.h>
+#include <limits.h>
 
-#include "internal.h"
+#include <openssl/bn.h>
+#include <openssl/bytestring.h>
+#include <openssl/err.h>
 
-/* Override the default free and new methods */
-static int dh_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
-                 void *exarg) {
-  if (operation == ASN1_OP_NEW_PRE) {
-    *pval = (ASN1_VALUE *)DH_new();
-    if (*pval) {
-      return 2;
-    }
+#include "../bytestring/internal.h"
+
+
+static int parse_integer(CBS *cbs, BIGNUM **out) {
+  assert(*out == NULL);
+  *out = BN_new();
+  if (*out == NULL) {
     return 0;
-  } else if (operation == ASN1_OP_FREE_PRE) {
-    DH_free((DH *)*pval);
-    *pval = NULL;
-    return 2;
+  }
+  return BN_parse_asn1_unsigned(cbs, *out);
+}
+
+static int marshal_integer(CBB *cbb, BIGNUM *bn) {
+  if (bn == NULL) {
+    /* A DH object may be missing some components. */
+    OPENSSL_PUT_ERROR(DH, ERR_R_PASSED_NULL_PARAMETER);
+    return 0;
+  }
+  return BN_marshal_asn1(cbb, bn);
+}
+
+DH *DH_parse_parameters(CBS *cbs) {
+  DH *ret = DH_new();
+  if (ret == NULL) {
+    return NULL;
+  }
+
+  CBS child;
+  if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
+      !parse_integer(&child, &ret->p) ||
+      !parse_integer(&child, &ret->g)) {
+    goto err;
+  }
+
+  uint64_t priv_length;
+  if (CBS_len(&child) != 0) {
+    if (!CBS_get_asn1_uint64(&child, &priv_length) ||
+        priv_length > UINT_MAX) {
+      goto err;
+    }
+    ret->priv_length = (unsigned)priv_length;
+  }
+
+  if (CBS_len(&child) != 0) {
+    goto err;
+  }
+
+  return ret;
+
+err:
+  OPENSSL_PUT_ERROR(DH, DH_R_DECODE_ERROR);
+  DH_free(ret);
+  return NULL;
+}
+
+int DH_marshal_parameters(CBB *cbb, const DH *dh) {
+  CBB child;
+  if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) ||
+      !marshal_integer(&child, dh->p) ||
+      !marshal_integer(&child, dh->g) ||
+      (dh->priv_length != 0 &&
+       !CBB_add_asn1_uint64(&child, dh->priv_length)) ||
+      !CBB_flush(cbb)) {
+    OPENSSL_PUT_ERROR(DH, DH_R_ENCODE_ERROR);
+    return 0;
   }
   return 1;
 }
 
-ASN1_SEQUENCE_cb(DHparams, dh_cb) = {
-    ASN1_SIMPLE(DH, p, BIGNUM), ASN1_SIMPLE(DH, g, BIGNUM),
-    ASN1_OPT(DH, priv_length, ZLONG)} ASN1_SEQUENCE_END_cb(DH, DHparams);
+DH *d2i_DHparams(DH **out, const uint8_t **inp, long len) {
+  if (len < 0) {
+    return NULL;
+  }
+  CBS cbs;
+  CBS_init(&cbs, *inp, (size_t)len);
+  DH *ret = DH_parse_parameters(&cbs);
+  if (ret == NULL) {
+    return NULL;
+  }
+  if (out != NULL) {
+    DH_free(*out);
+    *out = ret;
+  }
+  *inp = CBS_data(&cbs);
+  return ret;
+}
 
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DH, DHparams, DHparams)
+int i2d_DHparams(const DH *in, uint8_t **outp) {
+  CBB cbb;
+  if (!CBB_init(&cbb, 0) ||
+      !DH_marshal_parameters(&cbb, in)) {
+    CBB_cleanup(&cbb);
+    return -1;
+  }
+  return CBB_finish_i2d(&cbb, outp);
+}
diff --git a/src/crypto/dh/dh_test.cc b/src/crypto/dh/dh_test.cc
index c117bd4..e08664f 100644
--- a/src/crypto/dh/dh_test.cc
+++ b/src/crypto/dh/dh_test.cc
@@ -61,29 +61,33 @@
 
 #include <vector>
 
+#include <gtest/gtest.h>
+
 #include <openssl/bn.h>
+#include <openssl/bytestring.h>
 #include <openssl/crypto.h>
+#include <openssl/dh.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
-#include "internal.h"
-#include "../test/scoped_types.h"
+#include "../internal.h"
 
 
 static bool RunBasicTests();
 static bool RunRFC5114Tests();
+static bool TestBadY();
+static bool TestASN1();
+static bool TestRFC3526();
 
-int main(int argc, char *argv[]) {
-  CRYPTO_library_init();
-
+// TODO(davidben): Convert this file to GTest properly.
+TEST(DHTest, AllTests) {
   if (!RunBasicTests() ||
-      !RunRFC5114Tests()) {
-    ERR_print_errors_fp(stderr);
-    return 1;
+      !RunRFC5114Tests() ||
+      !TestBadY() ||
+      !TestASN1() ||
+      !TestRFC3526()) {
+    ADD_FAILURE() << "Tests failed.";
   }
-
-  printf("PASS\n");
-  return 0;
 }
 
 static int GenerateCallback(int p, int n, BN_GENCB *arg) {
@@ -108,7 +112,7 @@
 static bool RunBasicTests() {
   BN_GENCB cb;
   BN_GENCB_set(&cb, &GenerateCallback, stdout);
-  ScopedDH a(DH_new());
+  bssl::UniquePtr<DH> a(DH_new());
   if (!a || !DH_generate_parameters_ex(a.get(), 64, DH_GENERATOR_5, &cb)) {
     return false;
   }
@@ -136,7 +140,7 @@
   BN_print_fp(stdout, a->g);
   printf("\n");
 
-  ScopedDH b(DH_new());
+  bssl::UniquePtr<DH> b(DH_new());
   if (!b) {
     return false;
   }
@@ -430,8 +434,8 @@
   for (unsigned i = 0; i < sizeof(kRFCTestData) / sizeof(RFC5114TestData); i++) {
     const RFC5114TestData *td = kRFCTestData + i;
     /* Set up DH structures setting key components */
-    ScopedDH dhA(td->get_param(nullptr));
-    ScopedDH dhB(td->get_param(nullptr));
+    bssl::UniquePtr<DH> dhA(td->get_param(nullptr));
+    bssl::UniquePtr<DH> dhB(td->get_param(nullptr));
     if (!dhA || !dhB) {
       fprintf(stderr, "Initialisation error RFC5114 set %u\n", i + 1);
       return false;
@@ -465,9 +469,9 @@
     }
 
     if (static_cast<size_t>(ret1) != td->Z_len ||
-        memcmp(Z1.data(), td->Z, td->Z_len) != 0 ||
+        OPENSSL_memcmp(Z1.data(), td->Z, td->Z_len) != 0 ||
         static_cast<size_t>(ret2) != td->Z_len ||
-        memcmp(Z2.data(), td->Z, td->Z_len) != 0) {
+        OPENSSL_memcmp(Z2.data(), td->Z, td->Z_len) != 0) {
       fprintf(stderr, "Test failed RFC5114 set %u\n", i + 1);
       return false;
     }
@@ -477,3 +481,183 @@
 
   return 1;
 }
+
+// kRFC5114_2048_224BadY is a bad y-coordinate for RFC 5114's 2048-bit MODP
+// Group with 224-bit Prime Order Subgroup (section 2.2).
+static const uint8_t kRFC5114_2048_224BadY[] = {
+    0x45, 0x32, 0x5f, 0x51, 0x07, 0xe5, 0xdf, 0x1c, 0xd6, 0x02, 0x82, 0xb3,
+    0x32, 0x8f, 0xa4, 0x0f, 0x87, 0xb8, 0x41, 0xfe, 0xb9, 0x35, 0xde, 0xad,
+    0xc6, 0x26, 0x85, 0xb4, 0xff, 0x94, 0x8c, 0x12, 0x4c, 0xbf, 0x5b, 0x20,
+    0xc4, 0x46, 0xa3, 0x26, 0xeb, 0xa4, 0x25, 0xb7, 0x68, 0x8e, 0xcc, 0x67,
+    0xba, 0xea, 0x58, 0xd0, 0xf2, 0xe9, 0xd2, 0x24, 0x72, 0x60, 0xda, 0x88,
+    0x18, 0x9c, 0xe0, 0x31, 0x6a, 0xad, 0x50, 0x6d, 0x94, 0x35, 0x8b, 0x83,
+    0x4a, 0x6e, 0xfa, 0x48, 0x73, 0x0f, 0x83, 0x87, 0xff, 0x6b, 0x66, 0x1f,
+    0xa8, 0x82, 0xc6, 0x01, 0xe5, 0x80, 0xb5, 0xb0, 0x52, 0xd0, 0xe9, 0xd8,
+    0x72, 0xf9, 0x7d, 0x5b, 0x8b, 0xa5, 0x4c, 0xa5, 0x25, 0x95, 0x74, 0xe2,
+    0x7a, 0x61, 0x4e, 0xa7, 0x8f, 0x12, 0xe2, 0xd2, 0x9d, 0x8c, 0x02, 0x70,
+    0x34, 0x44, 0x32, 0xc7, 0xb2, 0xf3, 0xb9, 0xfe, 0x17, 0x2b, 0xd6, 0x1f,
+    0x8b, 0x7e, 0x4a, 0xfa, 0xa3, 0xb5, 0x3e, 0x7a, 0x81, 0x9a, 0x33, 0x66,
+    0x62, 0xa4, 0x50, 0x18, 0x3e, 0xa2, 0x5f, 0x00, 0x07, 0xd8, 0x9b, 0x22,
+    0xe4, 0xec, 0x84, 0xd5, 0xeb, 0x5a, 0xf3, 0x2a, 0x31, 0x23, 0xd8, 0x44,
+    0x22, 0x2a, 0x8b, 0x37, 0x44, 0xcc, 0xc6, 0x87, 0x4b, 0xbe, 0x50, 0x9d,
+    0x4a, 0xc4, 0x8e, 0x45, 0xcf, 0x72, 0x4d, 0xc0, 0x89, 0xb3, 0x72, 0xed,
+    0x33, 0x2c, 0xbc, 0x7f, 0x16, 0x39, 0x3b, 0xeb, 0xd2, 0xdd, 0xa8, 0x01,
+    0x73, 0x84, 0x62, 0xb9, 0x29, 0xd2, 0xc9, 0x51, 0x32, 0x9e, 0x7a, 0x6a,
+    0xcf, 0xc1, 0x0a, 0xdb, 0x0e, 0xe0, 0x62, 0x77, 0x6f, 0x59, 0x62, 0x72,
+    0x5a, 0x69, 0xa6, 0x5b, 0x70, 0xca, 0x65, 0xc4, 0x95, 0x6f, 0x9a, 0xc2,
+    0xdf, 0x72, 0x6d, 0xb1, 0x1e, 0x54, 0x7b, 0x51, 0xb4, 0xef, 0x7f, 0x89,
+    0x93, 0x74, 0x89, 0x59,
+};
+
+static bool TestBadY() {
+  bssl::UniquePtr<DH> dh(DH_get_2048_224(nullptr));
+  bssl::UniquePtr<BIGNUM> pub_key(
+      BN_bin2bn(kRFC5114_2048_224BadY, sizeof(kRFC5114_2048_224BadY), nullptr));
+  if (!dh || !pub_key || !DH_generate_key(dh.get())) {
+    return false;
+  }
+
+  int flags;
+  if (!DH_check_pub_key(dh.get(), pub_key.get(), &flags)) {
+    return false;
+  }
+  if (!(flags & DH_CHECK_PUBKEY_INVALID)) {
+    fprintf(stderr, "DH_check_pub_key did not reject the key.\n");
+    return false;
+  }
+
+  std::vector<uint8_t> result(DH_size(dh.get()));
+  if (DH_compute_key(result.data(), pub_key.get(), dh.get()) >= 0) {
+    fprintf(stderr, "DH_compute_key unexpectedly succeeded.\n");
+    return false;
+  }
+  ERR_clear_error();
+
+  return true;
+}
+
+static bool BIGNUMEqualsHex(const BIGNUM *bn, const char *hex) {
+  BIGNUM *hex_bn = NULL;
+  if (!BN_hex2bn(&hex_bn, hex)) {
+    return false;
+  }
+  bssl::UniquePtr<BIGNUM> free_hex_bn(hex_bn);
+  return BN_cmp(bn, hex_bn) == 0;
+}
+
+static bool TestASN1() {
+  // kParams are a set of Diffie-Hellman parameters generated with
+  // openssl dhparam 256
+  static const uint8_t kParams[] = {
+      0x30, 0x26, 0x02, 0x21, 0x00, 0xd7, 0x20, 0x34, 0xa3, 0x27,
+      0x4f, 0xdf, 0xbf, 0x04, 0xfd, 0x24, 0x68, 0x25, 0xb6, 0x56,
+      0xd8, 0xab, 0x2a, 0x41, 0x2d, 0x74, 0x0a, 0x52, 0x08, 0x7c,
+      0x40, 0x71, 0x4e, 0xd2, 0x57, 0x93, 0x13, 0x02, 0x01, 0x02,
+  };
+
+  CBS cbs;
+  CBS_init(&cbs, kParams, sizeof(kParams));
+  bssl::UniquePtr<DH> dh(DH_parse_parameters(&cbs));
+  if (!dh || CBS_len(&cbs) != 0 ||
+      !BIGNUMEqualsHex(
+          dh->p,
+          "d72034a3274fdfbf04fd246825b656d8ab2a412d740a52087c40714ed2579313") ||
+      !BIGNUMEqualsHex(dh->g, "2") || dh->priv_length != 0) {
+    return false;
+  }
+
+  bssl::ScopedCBB cbb;
+  uint8_t *der;
+  size_t der_len;
+  if (!CBB_init(cbb.get(), 0) ||
+      !DH_marshal_parameters(cbb.get(), dh.get()) ||
+      !CBB_finish(cbb.get(), &der, &der_len)) {
+    return false;
+  }
+  bssl::UniquePtr<uint8_t> free_der(der);
+  if (der_len != sizeof(kParams) ||
+      OPENSSL_memcmp(der, kParams, der_len) != 0) {
+    return false;
+  }
+
+  // kParamsDSA are a set of Diffie-Hellman parameters generated with
+  // openssl dhparam 256 -dsaparam
+  static const uint8_t kParamsDSA[] = {
+      0x30, 0x81, 0x89, 0x02, 0x41, 0x00, 0x93, 0xf3, 0xc1, 0x18, 0x01, 0xe6,
+      0x62, 0xb6, 0xd1, 0x46, 0x9a, 0x2c, 0x72, 0xea, 0x31, 0xd9, 0x18, 0x10,
+      0x30, 0x28, 0x63, 0xe2, 0x34, 0x7d, 0x80, 0xca, 0xee, 0x82, 0x2b, 0x19,
+      0x3c, 0x19, 0xbb, 0x42, 0x83, 0x02, 0x70, 0xdd, 0xdb, 0x8c, 0x03, 0xab,
+      0xe9, 0x9c, 0xc4, 0x00, 0x4d, 0x70, 0x5f, 0x52, 0x03, 0x31, 0x2c, 0xa4,
+      0x67, 0x34, 0x51, 0x95, 0x2a, 0xac, 0x11, 0xe2, 0x6a, 0x55, 0x02, 0x40,
+      0x44, 0xc8, 0x10, 0x53, 0x44, 0x32, 0x31, 0x63, 0xd8, 0xd1, 0x8c, 0x75,
+      0xc8, 0x98, 0x53, 0x3b, 0x5b, 0x4a, 0x2a, 0x0a, 0x09, 0xe7, 0xd0, 0x3c,
+      0x53, 0x72, 0xa8, 0x6b, 0x70, 0x41, 0x9c, 0x26, 0x71, 0x44, 0xfc, 0x7f,
+      0x08, 0x75, 0xe1, 0x02, 0xab, 0x74, 0x41, 0xe8, 0x2a, 0x3d, 0x3c, 0x26,
+      0x33, 0x09, 0xe4, 0x8b, 0xb4, 0x41, 0xec, 0xa6, 0xa8, 0xba, 0x1a, 0x07,
+      0x8a, 0x77, 0xf5, 0x5f, 0x02, 0x02, 0x00, 0xa0,
+  };
+
+  CBS_init(&cbs, kParamsDSA, sizeof(kParamsDSA));
+  dh.reset(DH_parse_parameters(&cbs));
+  if (!dh || CBS_len(&cbs) != 0 ||
+      !BIGNUMEqualsHex(dh->p,
+                       "93f3c11801e662b6d1469a2c72ea31d91810302863e2347d80caee8"
+                       "22b193c19bb42830270dddb8c03abe99cc4004d705f5203312ca467"
+                       "3451952aac11e26a55") ||
+      !BIGNUMEqualsHex(dh->g,
+                       "44c8105344323163d8d18c75c898533b5b4a2a0a09e7d03c5372a86"
+                       "b70419c267144fc7f0875e102ab7441e82a3d3c263309e48bb441ec"
+                       "a6a8ba1a078a77f55f") ||
+      dh->priv_length != 160) {
+    return false;
+  }
+
+  if (!CBB_init(cbb.get(), 0) ||
+      !DH_marshal_parameters(cbb.get(), dh.get()) ||
+      !CBB_finish(cbb.get(), &der, &der_len)) {
+    return false;
+  }
+  bssl::UniquePtr<uint8_t> free_der2(der);
+  if (der_len != sizeof(kParamsDSA) ||
+      OPENSSL_memcmp(der, kParamsDSA, der_len) != 0) {
+    return false;
+  }
+
+  return true;
+}
+
+static bool TestRFC3526() {
+  bssl::UniquePtr<BIGNUM> bn(BN_get_rfc3526_prime_1536(nullptr));
+  if (!bn) {
+    return false;
+  }
+
+  static const uint8_t kPrime1536[] = {
+      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc9, 0x0f, 0xda, 0xa2,
+      0x21, 0x68, 0xc2, 0x34, 0xc4, 0xc6, 0x62, 0x8b, 0x80, 0xdc, 0x1c, 0xd1,
+      0x29, 0x02, 0x4e, 0x08, 0x8a, 0x67, 0xcc, 0x74, 0x02, 0x0b, 0xbe, 0xa6,
+      0x3b, 0x13, 0x9b, 0x22, 0x51, 0x4a, 0x08, 0x79, 0x8e, 0x34, 0x04, 0xdd,
+      0xef, 0x95, 0x19, 0xb3, 0xcd, 0x3a, 0x43, 0x1b, 0x30, 0x2b, 0x0a, 0x6d,
+      0xf2, 0x5f, 0x14, 0x37, 0x4f, 0xe1, 0x35, 0x6d, 0x6d, 0x51, 0xc2, 0x45,
+      0xe4, 0x85, 0xb5, 0x76, 0x62, 0x5e, 0x7e, 0xc6, 0xf4, 0x4c, 0x42, 0xe9,
+      0xa6, 0x37, 0xed, 0x6b, 0x0b, 0xff, 0x5c, 0xb6, 0xf4, 0x06, 0xb7, 0xed,
+      0xee, 0x38, 0x6b, 0xfb, 0x5a, 0x89, 0x9f, 0xa5, 0xae, 0x9f, 0x24, 0x11,
+      0x7c, 0x4b, 0x1f, 0xe6, 0x49, 0x28, 0x66, 0x51, 0xec, 0xe4, 0x5b, 0x3d,
+      0xc2, 0x00, 0x7c, 0xb8, 0xa1, 0x63, 0xbf, 0x05, 0x98, 0xda, 0x48, 0x36,
+      0x1c, 0x55, 0xd3, 0x9a, 0x69, 0x16, 0x3f, 0xa8, 0xfd, 0x24, 0xcf, 0x5f,
+      0x83, 0x65, 0x5d, 0x23, 0xdc, 0xa3, 0xad, 0x96, 0x1c, 0x62, 0xf3, 0x56,
+      0x20, 0x85, 0x52, 0xbb, 0x9e, 0xd5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6d,
+      0x67, 0x0c, 0x35, 0x4e, 0x4a, 0xbc, 0x98, 0x04, 0xf1, 0x74, 0x6c, 0x08,
+      0xca, 0x23, 0x73, 0x27, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  };
+
+  uint8_t buffer[sizeof(kPrime1536)];
+  if (BN_num_bytes(bn.get()) != sizeof(kPrime1536) ||
+      BN_bn2bin(bn.get(), buffer) != sizeof(kPrime1536) ||
+      OPENSSL_memcmp(buffer, kPrime1536, sizeof(kPrime1536)) != 0) {
+    fprintf(stderr, "1536-bit MODP prime did not match.\n");
+    return false;
+  }
+
+  return true;
+}
diff --git a/src/crypto/dh/params.c b/src/crypto/dh/params.c
index 7e8102a..4cec700 100644
--- a/src/crypto/dh/params.c
+++ b/src/crypto/dh/params.c
@@ -54,7 +54,6 @@
 
 #include <openssl/bn.h>
 
-#include "internal.h"
 #include "../bn/internal.h"
 
 
@@ -166,58 +165,6 @@
     TOBN(0xB4479976, 0x40129DA2), TOBN(0x8CF83642, 0xA709A097),
 };
 
-/* dh1024_safe_prime_1 is hard-coded in Apache httpd 2.2,
- * modules/ssl/ssl_engine_dh.c. */
-static const BN_ULONG dh1024_safe_prime_1[] = {
-    TOBN(0xE7393E0F, 0x24218EB3), TOBN(0x7DE0F4D6, 0xE2BD68B0),
-    TOBN(0x07DD62DB, 0x88AEAA74), TOBN(0x10EA9FCC, 0x9DDD3305),
-    TOBN(0xA7DBCA78, 0x74087D15), TOBN(0xDAE88600, 0x78045B07),
-    TOBN(0x33168A46, 0x1AAD3B72), TOBN(0xFF590137, 0x7BEDDCFD),
-    TOBN(0xFE324A46, 0x7A635E81), TOBN(0x5AC179BA, 0x420B2A29),
-    TOBN(0x13B4B4D7, 0x177E16D5), TOBN(0x849F912E, 0x639C72FB),
-    TOBN(0xB88174CB, 0x98BCE951), TOBN(0x0C84D239, 0xA45F520B),
-    TOBN(0x36D693D3, 0x4AFD0AD5), TOBN(0xD67DE440, 0xCBBBDC19),
-};
-
-/* dh1024_safe_prime_2 is hard-coded in nginx,
- * src/event/ngx_event_openssl.c. */
-static const BN_ULONG dh1024_safe_prime_2[] = {
-    TOBN(0x071DF045, 0xCFE16B9B), TOBN(0x88D0F65D, 0x146757DA),
-    TOBN(0x4A63AB1E, 0x58FAFD49), TOBN(0x35D8CECE, 0xEF9EA027),
-    TOBN(0x25ECE662, 0x70CC9A50), TOBN(0xF29BA5DF, 0x81DC2CA7),
-    TOBN(0x8F68B076, 0xF7D36CC8), TOBN(0x60E91A92, 0xA757E304),
-    TOBN(0x87A2BC04, 0x9BE67780), TOBN(0xBEECA565, 0xA5FDF1D2),
-    TOBN(0x5CCBBAA8, 0x922614C5), TOBN(0x6C030276, 0xE710800C),
-    TOBN(0x08EED4EB, 0x0FB3504C), TOBN(0xD958A3F5, 0x68B42D4B),
-    TOBN(0x7C43FCF5, 0x80E9CFDB), TOBN(0xBBBC2DCA, 0xD8467490),
-};
-
-/* dh1024_safe_prime_3 is offered as a parameter by several high-traffic sites,
- * including mozilla.org, as of Jan 2015. */
-static const BN_ULONG dh1024_safe_prime_3[] = {
-    TOBN(0x671746AE, 0x349E721B), TOBN(0x258A0655, 0xD75E93B2),
-    TOBN(0xD425E6FB, 0x25592EB6), TOBN(0x0C46AB04, 0xBF7CDD9A),
-    TOBN(0x0AD0BC99, 0x28968680), TOBN(0xF53907FB, 0xD0B7EB49),
-    TOBN(0x202EABB3, 0xEBC85C1D), TOBN(0x3129C693, 0x364D8C71),
-    TOBN(0x53728351, 0x2D46F195), TOBN(0xDF326DD6, 0x8C76CC85),
-    TOBN(0xF898B3F9, 0x9188E24E), TOBN(0x95EFB13C, 0x2855DFD2),
-    TOBN(0x1F5DAC48, 0x7B2241FE), TOBN(0x117B6BF7, 0x99A13D9F),
-    TOBN(0x0F97CDDA, 0x3A3468C7), TOBN(0xC9BBF5F7, 0x74A8297B)};
-
-/* dh1024_safe_prime_4 is hard-coded in Apache httpd 2.0,
- * modules/ssl/ssl_engine_dh.c. */
-static const BN_ULONG dh1024_safe_prime_4[] = {
-    TOBN(0x5085E21F, 0x0DD5C86B), TOBN(0x871538DF, 0xD823C650),
-    TOBN(0x125136F7, 0x262E56A8), TOBN(0x974E9EF1, 0x839EB5DB),
-    TOBN(0xEA9BAD99, 0x1B13A63C), TOBN(0x6044CF02, 0x3D76E05E),
-    TOBN(0x611EBBBE, 0x1BAC9B5C), TOBN(0x3E371D79, 0x4E5327DF),
-    TOBN(0x000E6EDD, 0x061CBC05), TOBN(0x2F971F3C, 0x20129B48),
-    TOBN(0xA6EF09C4, 0x3048D5A2), TOBN(0xFA15A259, 0xCBD523A6),
-    TOBN(0x2A206490, 0x4A79A770), TOBN(0x91B78182, 0x51BB055E),
-    TOBN(0x7CF180C3, 0xBDD4798E), TOBN(0xE6969D3D, 0x495BE32C)};
-
-static const BN_ULONG bn_two_data[] = {2};
-
 struct standard_parameters {
   BIGNUM p, q, g;
 };
@@ -240,15 +187,6 @@
   STATIC_BIGNUM(dh2048_256_g),
 };
 
-static const BIGNUM dh1024_safe_prime[] = {
-  STATIC_BIGNUM(dh1024_safe_prime_1),
-  STATIC_BIGNUM(dh1024_safe_prime_2),
-  STATIC_BIGNUM(dh1024_safe_prime_3),
-  STATIC_BIGNUM(dh1024_safe_prime_4)
-};
-
-static BIGNUM bn_two = STATIC_BIGNUM(bn_two_data);
-
 static DH *get_standard_parameters(const struct standard_parameters *params,
                                    const ENGINE *engine) {
   DH *dh = DH_new();
@@ -279,23 +217,37 @@
   return get_standard_parameters(&dh2048_256, engine);
 }
 
-void DH_check_standard_parameters(DH *dh) {
-  unsigned i;
+BIGNUM *BN_get_rfc3526_prime_1536(BIGNUM *ret) {
+  static const BN_ULONG kPrime1536Data[] = {
+      TOBN(0xffffffff, 0xffffffff), TOBN(0xf1746c08, 0xca237327),
+      TOBN(0x670c354e, 0x4abc9804), TOBN(0x9ed52907, 0x7096966d),
+      TOBN(0x1c62f356, 0x208552bb), TOBN(0x83655d23, 0xdca3ad96),
+      TOBN(0x69163fa8, 0xfd24cf5f), TOBN(0x98da4836, 0x1c55d39a),
+      TOBN(0xc2007cb8, 0xa163bf05), TOBN(0x49286651, 0xece45b3d),
+      TOBN(0xae9f2411, 0x7c4b1fe6), TOBN(0xee386bfb, 0x5a899fa5),
+      TOBN(0x0bff5cb6, 0xf406b7ed), TOBN(0xf44c42e9, 0xa637ed6b),
+      TOBN(0xe485b576, 0x625e7ec6), TOBN(0x4fe1356d, 0x6d51c245),
+      TOBN(0x302b0a6d, 0xf25f1437), TOBN(0xef9519b3, 0xcd3a431b),
+      TOBN(0x514a0879, 0x8e3404dd), TOBN(0x020bbea6, 0x3b139b22),
+      TOBN(0x29024e08, 0x8a67cc74), TOBN(0xc4c6628b, 0x80dc1cd1),
+      TOBN(0xc90fdaa2, 0x2168c234), TOBN(0xffffffff, 0xffffffff),
+  };
 
-  if (dh->p == NULL ||
-      dh->g == NULL ||
-      BN_num_bytes(dh->p) != (1024 / 8) ||
-      BN_cmp(dh->g, &bn_two) != 0) {
-    return;
-  }
+  static const BIGNUM kPrime1536BN = STATIC_BIGNUM(kPrime1536Data);
 
-  for (i = 0; i < sizeof(dh1024_safe_prime) / sizeof(dh1024_safe_prime[0]);
-       i++) {
-    if (BN_cmp(dh->p, &dh1024_safe_prime[i]) == 0) {
-      /* The well-known DH groups are known to have safe primes. In this case
-       * we can safely reduce the size of the private key. */
-      dh->priv_length = 161;
-      break;
+  BIGNUM *alloc = NULL;
+  if (ret == NULL) {
+    alloc = BN_new();
+    if (alloc == NULL) {
+      return NULL;
     }
+    ret = alloc;
   }
+
+  if (!BN_copy(ret, &kPrime1536BN)) {
+    BN_free(alloc);
+    return NULL;
+  }
+
+  return ret;
 }
diff --git a/src/crypto/digest/digest.c b/src/crypto/digest/digest.c
index eb71b07..9c9962b 100644
--- a/src/crypto/digest/digest.c
+++ b/src/crypto/digest/digest.c
@@ -60,10 +60,10 @@
 #include <string.h>
 
 #include <openssl/err.h>
-#include <openssl/obj.h>
 #include <openssl/mem.h>
 
 #include "internal.h"
+#include "../internal.h"
 
 
 int EVP_MD_type(const EVP_MD *md) { return md->type; }
@@ -75,7 +75,9 @@
 size_t EVP_MD_block_size(const EVP_MD *md) { return md->block_size; }
 
 
-void EVP_MD_CTX_init(EVP_MD_CTX *ctx) { memset(ctx, 0, sizeof(EVP_MD_CTX)); }
+void EVP_MD_CTX_init(EVP_MD_CTX *ctx) {
+  OPENSSL_memset(ctx, 0, sizeof(EVP_MD_CTX));
+}
 
 EVP_MD_CTX *EVP_MD_CTX_create(void) {
   EVP_MD_CTX *ctx = OPENSSL_malloc(sizeof(EVP_MD_CTX));
@@ -141,7 +143,7 @@
         return 0;
       }
     }
-    memcpy(out->md_data, in->md_data, in->digest->ctx_size);
+    OPENSSL_memcpy(out->md_data, in->md_data, in->digest->ctx_size);
   }
 
   assert(in->pctx == NULL || in->pctx_ops != NULL);
@@ -166,6 +168,7 @@
   if (ctx->digest != type) {
     if (ctx->digest && ctx->digest->ctx_size > 0) {
       OPENSSL_free(ctx->md_data);
+      ctx->md_data = NULL;
     }
     ctx->digest = type;
     if (type->ctx_size > 0) {
@@ -231,11 +234,11 @@
   return ctx->digest;
 }
 
-unsigned EVP_MD_CTX_size(const EVP_MD_CTX *ctx) {
+size_t EVP_MD_CTX_size(const EVP_MD_CTX *ctx) {
   return EVP_MD_size(EVP_MD_CTX_md(ctx));
 }
 
-unsigned EVP_MD_CTX_block_size(const EVP_MD_CTX *ctx) {
+size_t EVP_MD_CTX_block_size(const EVP_MD_CTX *ctx) {
   return EVP_MD_block_size(EVP_MD_CTX_md(ctx));
 }
 
diff --git a/src/crypto/digest/digest_test.cc b/src/crypto/digest/digest_test.cc
index 6a6113d..36a62ab 100644
--- a/src/crypto/digest/digest_test.cc
+++ b/src/crypto/digest/digest_test.cc
@@ -16,14 +16,19 @@
 #include <stdio.h>
 #include <string.h>
 
+#include <memory>
+
+#include <openssl/asn1.h>
 #include <openssl/crypto.h>
 #include <openssl/digest.h>
 #include <openssl/err.h>
 #include <openssl/md4.h>
 #include <openssl/md5.h>
+#include <openssl/nid.h>
+#include <openssl/obj.h>
 #include <openssl/sha.h>
 
-#include "../test/scoped_types.h"
+#include "../internal.h"
 
 
 struct MD {
@@ -138,10 +143,9 @@
                           const uint8_t *digest,
                           size_t digest_len) {
   static const char kHexTable[] = "0123456789abcdef";
-  size_t i;
   char digest_hex[2*EVP_MAX_MD_SIZE + 1];
 
-  for (i = 0; i < digest_len; i++) {
+  for (size_t i = 0; i < digest_len; i++) {
     digest_hex[2*i] = kHexTable[digest[i] >> 4];
     digest_hex[2*i + 1] = kHexTable[digest[i] & 0xf];
   }
@@ -158,7 +162,7 @@
 }
 
 static int TestDigest(const TestVector *test) {
-  ScopedEVP_MD_CTX ctx;
+  bssl::ScopedEVP_MD_CTX ctx;
 
   // Test the input provided.
   if (!EVP_DigestInit_ex(ctx.get(), test->md.func(), NULL)) {
@@ -171,13 +175,13 @@
       return false;
     }
   }
-  uint8_t digest[EVP_MAX_MD_SIZE];
+  std::unique_ptr<uint8_t[]> digest(new uint8_t[EVP_MD_size(test->md.func())]);
   unsigned digest_len;
-  if (!EVP_DigestFinal_ex(ctx.get(), digest, &digest_len)) {
+  if (!EVP_DigestFinal_ex(ctx.get(), digest.get(), &digest_len)) {
     fprintf(stderr, "EVP_DigestFinal_ex failed\n");
     return false;
   }
-  if (!CompareDigest(test, digest, digest_len)) {
+  if (!CompareDigest(test, digest.get(), digest_len)) {
     return false;
   }
 
@@ -198,7 +202,7 @@
       }
     }
   }
-  if (!EVP_DigestFinal_ex(ctx.get(), digest, &digest_len)) {
+  if (!EVP_DigestFinal_ex(ctx.get(), digest.get(), &digest_len)) {
     fprintf(stderr, "EVP_DigestFinal_ex failed\n");
     return false;
   }
@@ -206,19 +210,19 @@
     fprintf(stderr, "EVP_MD_size output incorrect\n");
     return false;
   }
-  if (!CompareDigest(test, digest, digest_len)) {
+  if (!CompareDigest(test, digest.get(), digest_len)) {
     return false;
   }
 
   // Test the one-shot function.
   if (test->md.one_shot_func && test->repeat == 1) {
     uint8_t *out = test->md.one_shot_func((const uint8_t *)test->input,
-                                          strlen(test->input), digest);
-    if (out != digest) {
+                                          strlen(test->input), digest.get());
+    if (out != digest.get()) {
       fprintf(stderr, "one_shot_func gave incorrect return\n");
       return false;
     }
-    if (!CompareDigest(test, digest, EVP_MD_size(test->md.func()))) {
+    if (!CompareDigest(test, digest.get(), EVP_MD_size(test->md.func()))) {
       return false;
     }
 
@@ -234,20 +238,35 @@
 }
 
 static int TestGetters() {
-  if (EVP_get_digestbyname("RSA-SHA512") == NULL ||
-      EVP_get_digestbyname("sha512WithRSAEncryption") == NULL ||
-      EVP_get_digestbyname("nonsense") != NULL) {
+  if (EVP_get_digestbyname("RSA-SHA512") != EVP_sha512() ||
+      EVP_get_digestbyname("sha512WithRSAEncryption") != EVP_sha512() ||
+      EVP_get_digestbyname("nonsense") != NULL ||
+      EVP_get_digestbyname("SHA512") != EVP_sha512() ||
+      EVP_get_digestbyname("sha512") != EVP_sha512()) {
+    return false;
+  }
+
+  if (EVP_get_digestbynid(NID_sha512) != EVP_sha512() ||
+      EVP_get_digestbynid(NID_sha512WithRSAEncryption) != NULL ||
+      EVP_get_digestbynid(NID_undef) != NULL) {
+    return false;
+  }
+
+  bssl::UniquePtr<ASN1_OBJECT> obj(OBJ_txt2obj("1.3.14.3.2.26", 0));
+  if (!obj ||
+      EVP_get_digestbyobj(obj.get()) != EVP_sha1() ||
+      EVP_get_digestbyobj(OBJ_nid2obj(NID_md5_sha1)) != EVP_md5_sha1() ||
+      EVP_get_digestbyobj(OBJ_nid2obj(NID_sha1)) != EVP_sha1()) {
     return false;
   }
 
   return true;
 }
 
-int main(void) {
+int main() {
   CRYPTO_library_init();
-  ERR_load_crypto_strings();
 
-  for (size_t i = 0; i < sizeof(kTestVectors) / sizeof(kTestVectors[0]); i++) {
+  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kTestVectors); i++) {
     if (!TestDigest(&kTestVectors[i])) {
       fprintf(stderr, "Test %d failed\n", (int)i);
       return 1;
diff --git a/src/crypto/digest/digests.c b/src/crypto/digest/digests.c
index 3307f26..9ad2d49 100644
--- a/src/crypto/digest/digests.c
+++ b/src/crypto/digest/digests.c
@@ -59,12 +59,15 @@
 #include <assert.h>
 #include <string.h>
 
+#include <openssl/asn1.h>
+#include <openssl/bytestring.h>
 #include <openssl/md4.h>
 #include <openssl/md5.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
 #include <openssl/sha.h>
 
 #include "internal.h"
+#include "../internal.h"
 
 #if defined(NDEBUG)
 #define CHECK(x) (void) (x)
@@ -262,36 +265,41 @@
 };
 
 static const struct nid_to_digest nid_to_digest_mapping[] = {
-  { NID_md4, EVP_md4, SN_md4, LN_md4 },
-  { NID_md5, EVP_md5, SN_md5, LN_md5 },
-  { NID_sha1, EVP_sha1, SN_sha1, LN_sha1 },
-  { NID_sha224, EVP_sha224, SN_sha224, LN_sha224 },
-  { NID_sha256, EVP_sha256, SN_sha256, LN_sha256 },
-  { NID_sha384, EVP_sha384, SN_sha384, LN_sha384 },
-  { NID_sha512, EVP_sha512, SN_sha512, LN_sha512 },
-  { NID_md5_sha1, EVP_md5_sha1, SN_md5_sha1, LN_md5_sha1 },
-  { NID_dsaWithSHA, EVP_sha1, SN_dsaWithSHA, LN_dsaWithSHA },
-  { NID_dsaWithSHA1, EVP_sha1, SN_dsaWithSHA1, LN_dsaWithSHA1 },
-  { NID_ecdsa_with_SHA1, EVP_sha1, SN_ecdsa_with_SHA1, NULL },
-  { NID_md5WithRSAEncryption, EVP_md5, SN_md5WithRSAEncryption,
-    LN_md5WithRSAEncryption },
-  { NID_sha1WithRSAEncryption, EVP_sha1, SN_sha1WithRSAEncryption,
-    LN_sha1WithRSAEncryption },
-  { NID_sha224WithRSAEncryption, EVP_sha224, SN_sha224WithRSAEncryption,
-    LN_sha224WithRSAEncryption },
-  { NID_sha256WithRSAEncryption, EVP_sha256, SN_sha256WithRSAEncryption,
-    LN_sha256WithRSAEncryption },
-  { NID_sha384WithRSAEncryption, EVP_sha384, SN_sha384WithRSAEncryption,
-    LN_sha384WithRSAEncryption },
-  { NID_sha512WithRSAEncryption, EVP_sha512, SN_sha512WithRSAEncryption,
-    LN_sha512WithRSAEncryption },
+    {NID_md4, EVP_md4, SN_md4, LN_md4},
+    {NID_md5, EVP_md5, SN_md5, LN_md5},
+    {NID_sha1, EVP_sha1, SN_sha1, LN_sha1},
+    {NID_sha224, EVP_sha224, SN_sha224, LN_sha224},
+    {NID_sha256, EVP_sha256, SN_sha256, LN_sha256},
+    {NID_sha384, EVP_sha384, SN_sha384, LN_sha384},
+    {NID_sha512, EVP_sha512, SN_sha512, LN_sha512},
+    {NID_md5_sha1, EVP_md5_sha1, SN_md5_sha1, LN_md5_sha1},
+    /* As a remnant of signing |EVP_MD|s, OpenSSL returned the corresponding
+     * hash function when given a signature OID. To avoid unintended lax parsing
+     * of hash OIDs, this is no longer supported for lookup by OID or NID.
+     * Node.js, however, exposes |EVP_get_digestbyname|'s full behavior to
+     * consumers so we retain it there. */
+    {NID_undef, EVP_sha1, SN_dsaWithSHA, LN_dsaWithSHA},
+    {NID_undef, EVP_sha1, SN_dsaWithSHA1, LN_dsaWithSHA1},
+    {NID_undef, EVP_sha1, SN_ecdsa_with_SHA1, NULL},
+    {NID_undef, EVP_md5, SN_md5WithRSAEncryption, LN_md5WithRSAEncryption},
+    {NID_undef, EVP_sha1, SN_sha1WithRSAEncryption, LN_sha1WithRSAEncryption},
+    {NID_undef, EVP_sha224, SN_sha224WithRSAEncryption,
+     LN_sha224WithRSAEncryption},
+    {NID_undef, EVP_sha256, SN_sha256WithRSAEncryption,
+     LN_sha256WithRSAEncryption},
+    {NID_undef, EVP_sha384, SN_sha384WithRSAEncryption,
+     LN_sha384WithRSAEncryption},
+    {NID_undef, EVP_sha512, SN_sha512WithRSAEncryption,
+     LN_sha512WithRSAEncryption},
 };
 
 const EVP_MD* EVP_get_digestbynid(int nid) {
-  unsigned i;
+  if (nid == NID_undef) {
+    /* Skip the |NID_undef| entries in |nid_to_digest_mapping|. */
+    return NULL;
+  }
 
-  for (i = 0; i < sizeof(nid_to_digest_mapping) / sizeof(struct nid_to_digest);
-       i++) {
+  for (unsigned i = 0; i < OPENSSL_ARRAY_SIZE(nid_to_digest_mapping); i++) {
     if (nid_to_digest_mapping[i].nid == nid) {
       return nid_to_digest_mapping[i].md_func();
     }
@@ -300,15 +308,83 @@
   return NULL;
 }
 
-const EVP_MD* EVP_get_digestbyobj(const ASN1_OBJECT *obj) {
-  return EVP_get_digestbynid(OBJ_obj2nid(obj));
+static const struct {
+  uint8_t oid[9];
+  uint8_t oid_len;
+  const EVP_MD *(*md_func) (void);
+} kMDOIDs[] = {
+  /* 1.2.840.113549.2.4 */
+  { {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x04}, 8, EVP_md4 },
+  /* 1.2.840.113549.2.5 */
+  { {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05}, 8, EVP_md5 },
+  /* 1.3.14.3.2.26 */
+  { {0x2b, 0x0e, 0x03, 0x02, 0x1a}, 5, EVP_sha1 },
+  /* 2.16.840.1.101.3.4.2.1 */
+  { {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01}, 9, EVP_sha256 },
+  /* 2.16.840.1.101.3.4.2.2 */
+  { {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02}, 9, EVP_sha384 },
+  /* 2.16.840.1.101.3.4.2.3 */
+  { {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03}, 9, EVP_sha512 },
+  /* 2.16.840.1.101.3.4.2.4 */
+  { {0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04}, 9, EVP_sha224 },
+};
+
+static const EVP_MD *cbs_to_md(const CBS *cbs) {
+  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kMDOIDs); i++) {
+    if (CBS_len(cbs) == kMDOIDs[i].oid_len &&
+        OPENSSL_memcmp(CBS_data(cbs), kMDOIDs[i].oid, kMDOIDs[i].oid_len) ==
+            0) {
+      return kMDOIDs[i].md_func();
+    }
+  }
+
+  return NULL;
+}
+
+const EVP_MD *EVP_get_digestbyobj(const ASN1_OBJECT *obj) {
+  /* Handle objects with no corresponding OID. */
+  if (obj->nid != NID_undef) {
+    return EVP_get_digestbynid(obj->nid);
+  }
+
+  CBS cbs;
+  CBS_init(&cbs, obj->data, obj->length);
+  return cbs_to_md(&cbs);
+}
+
+const EVP_MD *EVP_parse_digest_algorithm(CBS *cbs) {
+  CBS algorithm, oid;
+  if (!CBS_get_asn1(cbs, &algorithm, CBS_ASN1_SEQUENCE) ||
+      !CBS_get_asn1(&algorithm, &oid, CBS_ASN1_OBJECT)) {
+    OPENSSL_PUT_ERROR(DIGEST, DIGEST_R_DECODE_ERROR);
+    return NULL;
+  }
+
+  const EVP_MD *ret = cbs_to_md(&oid);
+  if (ret == NULL) {
+    OPENSSL_PUT_ERROR(DIGEST, DIGEST_R_UNKNOWN_HASH);
+    return NULL;
+  }
+
+  /* The parameters, if present, must be NULL. Historically, whether the NULL
+   * was included or omitted was not well-specified. When parsing an
+   * AlgorithmIdentifier, we allow both. (Note this code is not used when
+   * verifying RSASSA-PKCS1-v1_5 signatures.) */
+  if (CBS_len(&algorithm) > 0) {
+    CBS param;
+    if (!CBS_get_asn1(&algorithm, &param, CBS_ASN1_NULL) ||
+        CBS_len(&param) != 0 ||
+        CBS_len(&algorithm) != 0) {
+      OPENSSL_PUT_ERROR(DIGEST, DIGEST_R_DECODE_ERROR);
+      return NULL;
+    }
+  }
+
+  return ret;
 }
 
 const EVP_MD *EVP_get_digestbyname(const char *name) {
-  unsigned i;
-
-  for (i = 0; i < sizeof(nid_to_digest_mapping) / sizeof(struct nid_to_digest);
-       i++) {
+  for (unsigned i = 0; i < OPENSSL_ARRAY_SIZE(nid_to_digest_mapping); i++) {
     const char *short_name = nid_to_digest_mapping[i].short_name;
     const char *long_name = nid_to_digest_mapping[i].long_name;
     if ((short_name && strcmp(short_name, name) == 0) ||
diff --git a/src/crypto/digest/internal.h b/src/crypto/digest/internal.h
index e3d812a..9f83bcb 100644
--- a/src/crypto/digest/internal.h
+++ b/src/crypto/digest/internal.h
@@ -104,6 +104,8 @@
   EVP_PKEY_CTX* (*dup) (EVP_PKEY_CTX *pctx);
 };
 
+const EVP_MD *EVP_parse_digest_algorithm(CBS *cbs);
+
 
 #if defined(__cplusplus)
 }  /* extern C */
diff --git a/src/crypto/digest/md32_common.h b/src/crypto/digest/md32_common.h
index 9db8c54..45fe939 100644
--- a/src/crypto/digest/md32_common.h
+++ b/src/crypto/digest/md32_common.h
@@ -53,6 +53,8 @@
 
 #include <assert.h>
 
+#include "../internal.h"
+
 #if defined(__cplusplus)
 extern "C" {
 #endif
@@ -140,89 +142,39 @@
 
 #if defined(DATA_ORDER_IS_BIG_ENDIAN)
 
-#if !defined(PEDANTIC) && defined(__GNUC__) && __GNUC__ >= 2 && \
-    !defined(OPENSSL_NO_ASM)
-#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
-/* The first macro gives a ~30-40% performance improvement in SHA-256 compiled
- * with gcc on P4. This can only be done on x86, where unaligned data fetches
- * are possible. */
-#define HOST_c2l(c, l)                       \
-  (void)({                                   \
-    uint32_t r = *((const uint32_t *)(c));   \
-    __asm__("bswapl %0" : "=r"(r) : "0"(r)); \
-    (c) += 4;                                \
-    (l) = r;                                 \
-  })
-#define HOST_l2c(l, c)                       \
-  (void)({                                   \
-    uint32_t r = (l);                        \
-    __asm__("bswapl %0" : "=r"(r) : "0"(r)); \
-    *((uint32_t *)(c)) = r;                  \
-    (c) += 4;                                \
-    r;                                       \
-  })
-#elif defined(__aarch64__) && defined(__BYTE_ORDER__)
-#if defined(__ORDER_LITTLE_ENDIAN__) && \
-    __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
-#define HOST_c2l(c, l)                                                 \
-  (void)({                                                             \
-    uint32_t r;                                                        \
-    __asm__("rev %w0, %w1" : "=r"(r) : "r"(*((const uint32_t *)(c)))); \
-    (c) += 4;                                                          \
-    (l) = r;                                                           \
-  })
-#define HOST_l2c(l, c)                                      \
-  (void)({                                                  \
-    uint32_t r;                                             \
-    __asm__("rev %w0, %w1" : "=r"(r) : "r"((uint32_t)(l))); \
-    *((uint32_t *)(c)) = r;                                 \
-    (c) += 4;                                               \
-    r;                                                      \
-  })
-#elif defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
-#define HOST_c2l(c, l) (void)((l) = *((const uint32_t *)(c)), (c) += 4)
-#define HOST_l2c(l, c) (*((uint32_t *)(c)) = (l), (c) += 4, (l))
-#endif /* __aarch64__ && __BYTE_ORDER__ */
-#endif /* ARCH */
-#endif /* !PEDANTIC && GNUC && !NO_ASM */
+#define HOST_c2l(c, l)                     \
+  do {                                     \
+    (l) = (((uint32_t)(*((c)++))) << 24);  \
+    (l) |= (((uint32_t)(*((c)++))) << 16); \
+    (l) |= (((uint32_t)(*((c)++))) << 8);  \
+    (l) |= (((uint32_t)(*((c)++))));       \
+  } while (0)
 
-#ifndef HOST_c2l
-#define HOST_c2l(c, l)                        \
-  (void)(l = (((uint32_t)(*((c)++))) << 24),  \
-         l |= (((uint32_t)(*((c)++))) << 16), \
-         l |= (((uint32_t)(*((c)++))) << 8), l |= (((uint32_t)(*((c)++)))))
-#endif
-
-#ifndef HOST_l2c
-#define HOST_l2c(l, c)                             \
-  (void)(*((c)++) = (uint8_t)(((l) >> 24) & 0xff), \
-         *((c)++) = (uint8_t)(((l) >> 16) & 0xff), \
-         *((c)++) = (uint8_t)(((l) >> 8) & 0xff),  \
-         *((c)++) = (uint8_t)(((l)) & 0xff))
-#endif
+#define HOST_l2c(l, c)                        \
+  do {                                        \
+    *((c)++) = (uint8_t)(((l) >> 24) & 0xff); \
+    *((c)++) = (uint8_t)(((l) >> 16) & 0xff); \
+    *((c)++) = (uint8_t)(((l) >> 8) & 0xff);  \
+    *((c)++) = (uint8_t)(((l)) & 0xff);       \
+  } while (0)
 
 #elif defined(DATA_ORDER_IS_LITTLE_ENDIAN)
 
-#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
-/* See comment in DATA_ORDER_IS_BIG_ENDIAN section. */
-#define HOST_c2l(c, l) (void)((l) = *((const uint32_t *)(c)), (c) += 4)
-#define HOST_l2c(l, c) (void)(*((uint32_t *)(c)) = (l), (c) += 4, l)
-#endif /* OPENSSL_X86 || OPENSSL_X86_64 */
+#define HOST_c2l(c, l)                     \
+  do {                                     \
+    (l) = (((uint32_t)(*((c)++))));        \
+    (l) |= (((uint32_t)(*((c)++))) << 8);  \
+    (l) |= (((uint32_t)(*((c)++))) << 16); \
+    (l) |= (((uint32_t)(*((c)++))) << 24); \
+  } while (0)
 
-#ifndef HOST_c2l
-#define HOST_c2l(c, l)                                                     \
-  (void)(l = (((uint32_t)(*((c)++)))), l |= (((uint32_t)(*((c)++))) << 8), \
-         l |= (((uint32_t)(*((c)++))) << 16),                              \
-         l |= (((uint32_t)(*((c)++))) << 24))
-#endif
-
-#ifndef HOST_l2c
-#define HOST_l2c(l, c)                             \
-  (void)(*((c)++) = (uint8_t)(((l)) & 0xff),       \
-         *((c)++) = (uint8_t)(((l) >> 8) & 0xff),  \
-         *((c)++) = (uint8_t)(((l) >> 16) & 0xff), \
-         *((c)++) = (uint8_t)(((l) >> 24) & 0xff))
-#endif
+#define HOST_l2c(l, c)                        \
+  do {                                        \
+    *((c)++) = (uint8_t)(((l)) & 0xff);       \
+    *((c)++) = (uint8_t)(((l) >> 8) & 0xff);  \
+    *((c)++) = (uint8_t)(((l) >> 16) & 0xff); \
+    *((c)++) = (uint8_t)(((l) >> 24) & 0xff); \
+  } while (0)
 
 #endif /* DATA_ORDER */
 
@@ -244,16 +196,16 @@
   size_t n = c->num;
   if (n != 0) {
     if (len >= HASH_CBLOCK || len + n >= HASH_CBLOCK) {
-      memcpy(c->data + n, data, HASH_CBLOCK - n);
+      OPENSSL_memcpy(c->data + n, data, HASH_CBLOCK - n);
       HASH_BLOCK_DATA_ORDER(c->h, c->data, 1);
       n = HASH_CBLOCK - n;
       data += n;
       len -= n;
       c->num = 0;
       /* Keep |c->data| zeroed when unused. */
-      memset(c->data, 0, HASH_CBLOCK);
+      OPENSSL_memset(c->data, 0, HASH_CBLOCK);
     } else {
-      memcpy(c->data + n, data, len);
+      OPENSSL_memcpy(c->data + n, data, len);
       c->num += (unsigned)len;
       return 1;
     }
@@ -269,7 +221,7 @@
 
   if (len != 0) {
     c->num = (unsigned)len;
-    memcpy(c->data, data, len);
+    OPENSSL_memcpy(c->data, data, len);
   }
   return 1;
 }
@@ -290,11 +242,11 @@
 
   /* Fill the block with zeros if there isn't room for a 64-bit length. */
   if (n > (HASH_CBLOCK - 8)) {
-    memset(c->data + n, 0, HASH_CBLOCK - n);
+    OPENSSL_memset(c->data + n, 0, HASH_CBLOCK - n);
     n = 0;
     HASH_BLOCK_DATA_ORDER(c->h, c->data, 1);
   }
-  memset(c->data + n, 0, HASH_CBLOCK - 8 - n);
+  OPENSSL_memset(c->data + n, 0, HASH_CBLOCK - 8 - n);
 
   /* Append a 64-bit length to the block and process it. */
   uint8_t *p = c->data + HASH_CBLOCK - 8;
@@ -308,7 +260,7 @@
   assert(p == c->data + HASH_CBLOCK);
   HASH_BLOCK_DATA_ORDER(c->h, c->data, 1);
   c->num = 0;
-  memset(c->data, 0, HASH_CBLOCK);
+  OPENSSL_memset(c->data, 0, HASH_CBLOCK);
 
   HASH_MAKE_STRING(c, md);
   return 1;
diff --git a/src/crypto/directory.h b/src/crypto/directory.h
deleted file mode 100644
index 29123ea..0000000
--- a/src/crypto/directory.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/* Copied from Richard Levitte's (richard@levitte.org) LP library.  All
- * symbol names have been changed, with permission from the author. */
-
-/* $LP: LPlib/source/LPdir.h,v 1.1 2004/06/14 08:56:04 _cvs_levitte Exp $ */
-/*
- * Copyright (c) 2004, Richard Levitte <richard@levitte.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef OPENSSL_HEADER_DIRECTORY_H
-#define OPENSSL_HEADER_DIRECTORY_H
-
-#include <openssl/base.h>
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-
-/* Directory functions abstract the O/S specific operations for opening and
- * reading directories in the filesystem. */
-
-
-/* OPENSSL_dir_context_st is an opaque structure that represents an open
- * directory and a position in that directory. */
-typedef struct OPENSSL_dir_context_st OPENSSL_DIR_CTX;
-
-/* OPENSSL_DIR_read reads a single filename from |ctx|. On the first call,
- * |directory| must be given and |*ctx| must be NULL. Subsequent calls with the
- * same |*ctx| will return subsequent file names until it returns NULL to
- * indicate EOF. The strings returned reference a buffer internal to the
- * |OPENSSL_DIR_CTX| and will be overridden by subsequent calls. */
-OPENSSL_EXPORT const char *OPENSSL_DIR_read(OPENSSL_DIR_CTX **ctx,
-                                            const char *directory);
-
-/* OPENSSL_DIR_end closes |*ctx|. It returns one on success and zero on
- * error. */
-OPENSSL_EXPORT int OPENSSL_DIR_end(OPENSSL_DIR_CTX **ctx);
-
-
-#if defined(__cplusplus)
-}  /* extern C */
-#endif
-
-#endif  /* OPENSSL_HEADER_DIRECTORY_H */
diff --git a/src/crypto/directory_posix.c b/src/crypto/directory_posix.c
deleted file mode 100644
index b944b69..0000000
--- a/src/crypto/directory_posix.c
+++ /dev/null
@@ -1,108 +0,0 @@
-/* $LP: LPlib/source/LPdir_unix.c,v 1.11 2004/09/23 22:07:22 _cvs_levitte Exp $ */
-/*
- * Copyright (c) 2004, Richard Levitte <richard@levitte.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
-
-#if !defined(_POSIX_C_SOURCE)
-#define _POSIX_C_SOURCE 201409  /* for readdir_r */
-#endif
-
-#include "directory.h"
-
-
-#if !defined(OPENSSL_WINDOWS)
-
-#include <dirent.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-
-#if defined(OPENSSL_PNACL)
-/* pnacl doesn't include readdir_r! So we do the best we can. */
-int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) {
-  errno = 0;
-  *result = readdir(dirp);
-  if (*result != NULL) {
-    return 0;
-  }
-  if (errno) {
-    return 1;
-  }
-  return 0;
-}
-#endif
-
-struct OPENSSL_dir_context_st {
-  DIR *dir;
-  struct dirent dirent;
-};
-
-const char *OPENSSL_DIR_read(OPENSSL_DIR_CTX **ctx, const char *directory) {
-  struct dirent *dirent;
-
-  if (ctx == NULL || directory == NULL) {
-    errno = EINVAL;
-    return NULL;
-  }
-
-  errno = 0;
-  if (*ctx == NULL) {
-    *ctx = malloc(sizeof(OPENSSL_DIR_CTX));
-    if (*ctx == NULL) {
-      errno = ENOMEM;
-      return 0;
-    }
-    memset(*ctx, 0, sizeof(OPENSSL_DIR_CTX));
-
-    (*ctx)->dir = opendir(directory);
-    if ((*ctx)->dir == NULL) {
-      int save_errno = errno; /* Probably not needed, but I'm paranoid */
-      free(*ctx);
-      *ctx = NULL;
-      errno = save_errno;
-      return 0;
-    }
-  }
-
-  if (readdir_r((*ctx)->dir, &(*ctx)->dirent, &dirent) != 0 ||
-      dirent == NULL) {
-    return 0;
-  }
-
-  return (*ctx)->dirent.d_name;
-}
-
-int OPENSSL_DIR_end(OPENSSL_DIR_CTX **ctx) {
-  if (ctx != NULL && *ctx != NULL) {
-    int r = closedir((*ctx)->dir);
-    free(*ctx);
-    *ctx = NULL;
-    return r == 0;
-  }
-
-  errno = EINVAL;
-  return 0;
-}
-
-#endif  /* !OPENSSL_WINDOWS */
diff --git a/src/crypto/directory_win.c b/src/crypto/directory_win.c
deleted file mode 100644
index 4ebacf2..0000000
--- a/src/crypto/directory_win.c
+++ /dev/null
@@ -1,144 +0,0 @@
-/* $LP: LPlib/source/LPdir_win.c,v 1.10 2004/08/26 13:36:05 _cvs_levitte Exp $ */
-/*
- * Copyright (c) 2004, Richard Levitte <richard@levitte.org>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "directory.h"
-
-
-#if defined(OPENSSL_WINDOWS)
-
-#pragma warning(push, 3)
-#include <windows.h>
-#pragma warning(pop)
-#include <errno.h>
-#include <string.h>
-#include <tchar.h>
-
-#ifndef NAME_MAX
-#define NAME_MAX 255
-#endif
-
-#include <openssl/mem.h>
-
-
-struct OPENSSL_dir_context_st {
-  WIN32_FIND_DATA ctx;
-  HANDLE handle;
-  char entry_name[NAME_MAX + 1];
-};
-
-const char *OPENSSL_DIR_read(OPENSSL_DIR_CTX **ctx, const char *directory) {
-  if (ctx == NULL || directory == NULL) {
-    errno = EINVAL;
-    return 0;
-  }
-
-  errno = 0;
-  if (*ctx == NULL) {
-    *ctx = malloc(sizeof(OPENSSL_DIR_CTX));
-    if (*ctx == NULL) {
-      errno = ENOMEM;
-      return 0;
-    }
-    memset(*ctx, 0, sizeof(OPENSSL_DIR_CTX));
-
-    if (sizeof(TCHAR) != sizeof(char)) {
-      TCHAR *wdir = NULL;
-      /* len_0 denotes string length *with* trailing 0 */
-      size_t index = 0, len_0 = strlen(directory) + 1;
-
-      wdir = (TCHAR *)malloc(len_0 * sizeof(TCHAR));
-      if (wdir == NULL) {
-        free(*ctx);
-        *ctx = NULL;
-        errno = ENOMEM;
-        return 0;
-      }
-
-      if (!MultiByteToWideChar(CP_ACP, 0, directory, len_0, (WCHAR *)wdir,
-                               len_0)) {
-        for (index = 0; index < len_0; index++) {
-          wdir[index] = (TCHAR)directory[index];
-        }
-      }
-
-      (*ctx)->handle = FindFirstFile(wdir, &(*ctx)->ctx);
-
-      free(wdir);
-    } else {
-      (*ctx)->handle = FindFirstFile((TCHAR *)directory, &(*ctx)->ctx);
-    }
-
-    if ((*ctx)->handle == INVALID_HANDLE_VALUE) {
-      free(*ctx);
-      *ctx = NULL;
-      errno = EINVAL;
-      return 0;
-    }
-  } else {
-    if (FindNextFile((*ctx)->handle, &(*ctx)->ctx) == FALSE) {
-      return 0;
-    }
-  }
-
-  if (sizeof(TCHAR) != sizeof(char)) {
-    TCHAR *wdir = (*ctx)->ctx.cFileName;
-    size_t index, len_0 = 0;
-
-    while (wdir[len_0] && len_0 < (sizeof((*ctx)->entry_name) - 1)) {
-      len_0++;
-    }
-    len_0++;
-
-    if (!WideCharToMultiByte(CP_ACP, 0, (WCHAR *)wdir, len_0,
-                             (*ctx)->entry_name, sizeof((*ctx)->entry_name),
-                             NULL, 0)) {
-      for (index = 0; index < len_0; index++) {
-        (*ctx)->entry_name[index] = (char)wdir[index];
-      }
-    }
-  } else {
-    strncpy((*ctx)->entry_name, (const char *)(*ctx)->ctx.cFileName,
-            sizeof((*ctx)->entry_name) - 1);
-  }
-
-  (*ctx)->entry_name[sizeof((*ctx)->entry_name) - 1] = '\0';
-
-  return (*ctx)->entry_name;
-}
-
-int OPENSSL_DIR_end(OPENSSL_DIR_CTX **ctx) {
-  if (ctx != NULL && *ctx != NULL) {
-    FindClose((*ctx)->handle);
-    free(*ctx);
-    *ctx = NULL;
-    return 1;
-  }
-  errno = EINVAL;
-  return 0;
-}
-
-#endif  /* OPENSSL_WINDOWS */
diff --git a/src/crypto/dsa/CMakeLists.txt b/src/crypto/dsa/CMakeLists.txt
index de36565..d3c12f5 100644
--- a/src/crypto/dsa/CMakeLists.txt
+++ b/src/crypto/dsa/CMakeLists.txt
@@ -8,14 +8,3 @@
   dsa.c
   dsa_asn1.c
 )
-
-add_executable(
-  dsa_test
-
-  dsa_test.c
-
-  $<TARGET_OBJECTS:test_support>
-)
-
-target_link_libraries(dsa_test crypto)
-add_dependencies(all_tests dsa_test)
diff --git a/src/crypto/dsa/dsa.c b/src/crypto/dsa/dsa.c
index ebe55e8..e2b6695 100644
--- a/src/crypto/dsa/dsa.c
+++ b/src/crypto/dsa/dsa.c
@@ -61,7 +61,6 @@
 
 #include <string.h>
 
-#include <openssl/asn1.h>
 #include <openssl/bn.h>
 #include <openssl/dh.h>
 #include <openssl/digest.h>
@@ -73,7 +72,7 @@
 #include <openssl/sha.h>
 #include <openssl/thread.h>
 
-#include "internal.h"
+#include "../bn/internal.h"
 #include "../internal.h"
 
 
@@ -86,18 +85,17 @@
 static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT;
 
 DSA *DSA_new(void) {
-  DSA *dsa = (DSA *)OPENSSL_malloc(sizeof(DSA));
+  DSA *dsa = OPENSSL_malloc(sizeof(DSA));
   if (dsa == NULL) {
     OPENSSL_PUT_ERROR(DSA, ERR_R_MALLOC_FAILURE);
     return NULL;
   }
 
-  memset(dsa, 0, sizeof(DSA));
+  OPENSSL_memset(dsa, 0, sizeof(DSA));
 
-  dsa->write_params = 1;
   dsa->references = 1;
 
-  CRYPTO_MUTEX_init(&dsa->method_mont_p_lock);
+  CRYPTO_MUTEX_init(&dsa->method_mont_lock);
   CRYPTO_new_ex_data(&dsa->ex_data);
 
   return dsa;
@@ -122,7 +120,8 @@
   BN_clear_free(dsa->kinv);
   BN_clear_free(dsa->r);
   BN_MONT_CTX_free(dsa->method_mont_p);
-  CRYPTO_MUTEX_cleanup(&dsa->method_mont_p_lock);
+  BN_MONT_CTX_free(dsa->method_mont_q);
+  CRYPTO_MUTEX_cleanup(&dsa->method_mont_lock);
   OPENSSL_free(dsa);
 }
 
@@ -131,6 +130,29 @@
   return 1;
 }
 
+void DSA_get0_key(const DSA *dsa, const BIGNUM **out_pub_key,
+                  const BIGNUM **out_priv_key) {
+  if (out_pub_key != NULL) {
+    *out_pub_key = dsa->pub_key;
+  }
+  if (out_priv_key != NULL) {
+    *out_priv_key = dsa->priv_key;
+  }
+}
+
+void DSA_get0_pqg(const DSA *dsa, const BIGNUM **out_p, const BIGNUM **out_q,
+                  const BIGNUM **out_g) {
+  if (out_p != NULL) {
+    *out_p = dsa->p;
+  }
+  if (out_q != NULL) {
+    *out_q = dsa->q;
+  }
+  if (out_g != NULL) {
+    *out_g = dsa->g;
+  }
+}
+
 int DSA_generate_parameters_ex(DSA *dsa, unsigned bits, const uint8_t *seed_in,
                                size_t seed_len, int *out_counter,
                                unsigned long *out_h, BN_GENCB *cb) {
@@ -167,7 +189,7 @@
       /* Only consume as much seed as is expected. */
       seed_len = qsize;
     }
-    memcpy(seed, seed_in, seed_len);
+    OPENSSL_memcpy(seed, seed_in, seed_len);
   }
 
   ctx = BN_CTX_new();
@@ -211,8 +233,8 @@
         /* If we come back through, use random seed next time. */
         seed_in = NULL;
       }
-      memcpy(buf, seed, qsize);
-      memcpy(buf2, seed, qsize);
+      OPENSSL_memcpy(buf, seed, qsize);
+      OPENSSL_memcpy(buf2, seed, qsize);
       /* precompute "SEED + 1" for step 7: */
       for (i = qsize - 1; i < qsize; i--) {
         buf[i]++;
@@ -393,11 +415,25 @@
   return ok;
 }
 
+DSA *DSAparams_dup(const DSA *dsa) {
+  DSA *ret = DSA_new();
+  if (ret == NULL) {
+    return NULL;
+  }
+  ret->p = BN_dup(dsa->p);
+  ret->q = BN_dup(dsa->q);
+  ret->g = BN_dup(dsa->g);
+  if (ret->p == NULL || ret->q == NULL || ret->g == NULL) {
+    DSA_free(ret);
+    return NULL;
+  }
+  return ret;
+}
+
 int DSA_generate_key(DSA *dsa) {
   int ok = 0;
   BN_CTX *ctx = NULL;
   BIGNUM *pub_key = NULL, *priv_key = NULL;
-  BIGNUM prk;
 
   ctx = BN_CTX_new();
   if (ctx == NULL) {
@@ -412,11 +448,9 @@
     }
   }
 
-  do {
-    if (!BN_rand_range(priv_key, dsa->q)) {
-      goto err;
-    }
-  } while (BN_is_zero(priv_key));
+  if (!BN_rand_range_ex(priv_key, 1, dsa->q)) {
+    goto err;
+  }
 
   pub_key = dsa->pub_key;
   if (pub_key == NULL) {
@@ -426,10 +460,10 @@
     }
   }
 
-  BN_init(&prk);
-  BN_with_flags(&prk, priv_key, BN_FLG_CONSTTIME);
-
-  if (!BN_mod_exp(pub_key, dsa->g, &prk, dsa->p, ctx)) {
+  if (!BN_MONT_CTX_set_locked(&dsa->method_mont_p, &dsa->method_mont_lock,
+                              dsa->p, ctx) ||
+      !BN_mod_exp_mont_consttime(pub_key, dsa->g, priv_key, dsa->p, ctx,
+                                 dsa->method_mont_p)) {
     goto err;
   }
 
@@ -579,7 +613,6 @@
                            size_t digest_len, DSA_SIG *sig, const DSA *dsa) {
   BN_CTX *ctx;
   BIGNUM u1, u2, t1;
-  BN_MONT_CTX *mont = NULL;
   int ret = 0;
   unsigned i;
 
@@ -650,15 +683,14 @@
     goto err;
   }
 
-  mont = BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p,
-                                (CRYPTO_MUTEX *)&dsa->method_mont_p_lock,
-                                dsa->p, ctx);
-  if (!mont) {
+  if (!BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p,
+                              (CRYPTO_MUTEX *)&dsa->method_mont_lock, dsa->p,
+                              ctx)) {
     goto err;
   }
 
   if (!BN_mod_exp2_mont(&t1, dsa->g, &u1, dsa->pub_key, &u2, dsa->p, ctx,
-                        mont)) {
+                        dsa->method_mont_p)) {
     goto err;
   }
 
@@ -728,7 +760,8 @@
 
   /* Ensure that the signature uses DER and doesn't have trailing garbage. */
   int der_len = i2d_DSA_SIG(s, &der);
-  if (der_len < 0 || (size_t)der_len != sig_len || memcmp(sig, der, sig_len)) {
+  if (der_len < 0 || (size_t)der_len != sig_len ||
+      OPENSSL_memcmp(sig, der, sig_len)) {
     goto err;
   }
 
@@ -740,31 +773,45 @@
   return ret;
 }
 
+/* der_len_len returns the number of bytes needed to represent a length of |len|
+ * in DER. */
+static size_t der_len_len(size_t len) {
+  if (len < 0x80) {
+    return 1;
+  }
+  size_t ret = 1;
+  while (len > 0) {
+    ret++;
+    len >>= 8;
+  }
+  return ret;
+}
+
 int DSA_size(const DSA *dsa) {
-  int ret, i;
-  ASN1_INTEGER bs;
-  unsigned char buf[4]; /* 4 bytes looks really small.
-                           However, i2d_ASN1_INTEGER() will not look
-                           beyond the first byte, as long as the second
-                           parameter is NULL. */
-
-  i = BN_num_bits(dsa->q);
-  bs.length = (i + 7) / 8;
-  bs.data = buf;
-  bs.type = V_ASN1_INTEGER;
-  /* If the top bit is set the asn1 encoding is 1 larger. */
-  buf[0] = 0xff;
-
-  i = i2d_ASN1_INTEGER(&bs, NULL);
-  i += i; /* r and s */
-  ret = ASN1_object_size(1, i, V_ASN1_SEQUENCE);
+  size_t order_len = BN_num_bytes(dsa->q);
+  /* Compute the maximum length of an |order_len| byte integer. Defensively
+   * assume that the leading 0x00 is included. */
+  size_t integer_len = 1 /* tag */ + der_len_len(order_len + 1) + 1 + order_len;
+  if (integer_len < order_len) {
+    return 0;
+  }
+  /* A DSA signature is two INTEGERs. */
+  size_t value_len = 2 * integer_len;
+  if (value_len < integer_len) {
+    return 0;
+  }
+  /* Add the header. */
+  size_t ret = 1 /* tag */ + der_len_len(value_len) + value_len;
+  if (ret < value_len) {
+    return 0;
+  }
   return ret;
 }
 
 int DSA_sign_setup(const DSA *dsa, BN_CTX *ctx_in, BIGNUM **out_kinv,
                    BIGNUM **out_r) {
   BN_CTX *ctx;
-  BIGNUM k, kq, *K, *kinv = NULL, *r = NULL;
+  BIGNUM k, kq, *kinv = NULL, *r = NULL;
   int ret = 0;
 
   if (!dsa->p || !dsa->q || !dsa->g) {
@@ -789,17 +836,16 @@
   }
 
   /* Get random k */
-  do {
-    if (!BN_rand_range(&k, dsa->q)) {
-      goto err;
-    }
-  } while (BN_is_zero(&k));
+  if (!BN_rand_range_ex(&k, 1, dsa->q)) {
+    goto err;
+  }
 
-  BN_set_flags(&k, BN_FLG_CONSTTIME);
-
-  if (BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p,
-                             (CRYPTO_MUTEX *)&dsa->method_mont_p_lock, dsa->p,
-                             ctx) == NULL) {
+  if (!BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_p,
+                              (CRYPTO_MUTEX *)&dsa->method_mont_lock, dsa->p,
+                              ctx) ||
+      !BN_MONT_CTX_set_locked((BN_MONT_CTX **)&dsa->method_mont_q,
+                              (CRYPTO_MUTEX *)&dsa->method_mont_lock, dsa->q,
+                              ctx)) {
     goto err;
   }
 
@@ -821,18 +867,19 @@
     goto err;
   }
 
-  K = &kq;
-
-  if (!BN_mod_exp_mont(r, dsa->g, K, dsa->p, ctx, dsa->method_mont_p)) {
+  if (!BN_mod_exp_mont_consttime(r, dsa->g, &kq, dsa->p, ctx,
+                                 dsa->method_mont_p)) {
     goto err;
   }
   if (!BN_mod(r, r, dsa->q, ctx)) {
     goto err;
   }
 
-  /* Compute  part of 's = inv(k) (m + xr) mod q' */
-  kinv = BN_mod_inverse(NULL, &k, dsa->q, ctx);
-  if (kinv == NULL) {
+  /* Compute part of 's = inv(k) (m + xr) mod q' using Fermat's Little
+   * Theorem. */
+  kinv = BN_new();
+  if (kinv == NULL ||
+      !bn_mod_inverse_prime(kinv, &k, dsa->q, ctx, dsa->method_mont_q)) {
     goto err;
   }
 
@@ -856,6 +903,7 @@
   }
   BN_clear_free(&k);
   BN_clear_free(&kq);
+  BN_clear_free(kinv);
   return ret;
 }
 
diff --git a/src/crypto/dsa/dsa_asn1.c b/src/crypto/dsa/dsa_asn1.c
index b6b3fa4..ff5ee00 100644
--- a/src/crypto/dsa/dsa_asn1.c
+++ b/src/crypto/dsa/dsa_asn1.c
@@ -54,97 +54,286 @@
 
 #include <openssl/dsa.h>
 
-#include <string.h>
+#include <assert.h>
 
-#include <openssl/asn1.h>
-#include <openssl/asn1t.h>
+#include <openssl/bn.h>
+#include <openssl/bytestring.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
-#include "internal.h"
+#include "../bytestring/internal.h"
 
 
-static int dsa_sig_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
-                      void *exarg) {
-  if (operation != ASN1_OP_NEW_PRE) {
-    return 1;
-  }
-
-  DSA_SIG *sig;
-  sig = OPENSSL_malloc(sizeof(DSA_SIG));
-  if (!sig) {
-    OPENSSL_PUT_ERROR(DSA, ERR_R_MALLOC_FAILURE);
+static int parse_integer(CBS *cbs, BIGNUM **out) {
+  assert(*out == NULL);
+  *out = BN_new();
+  if (*out == NULL) {
     return 0;
   }
-
-  memset(sig, 0, sizeof(DSA_SIG));
-  *pval = (ASN1_VALUE *)sig;
-  return 2;
+  return BN_parse_asn1_unsigned(cbs, *out);
 }
 
-ASN1_SEQUENCE_cb(DSA_SIG, dsa_sig_cb) = {
-    ASN1_SIMPLE(DSA_SIG, r, CBIGNUM),
-    ASN1_SIMPLE(DSA_SIG, s, CBIGNUM)} ASN1_SEQUENCE_END_cb(DSA_SIG, DSA_SIG);
-
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA_SIG, DSA_SIG, DSA_SIG);
-
-
-static int dsa_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
-                  void *exarg) {
-  switch (operation) {
-    case ASN1_OP_NEW_PRE:
-      *pval = (ASN1_VALUE *)DSA_new();
-      if (*pval) {
-        return 2;
-      }
-      return 0;
-
-    case ASN1_OP_FREE_PRE:
-      DSA_free((DSA *)*pval);
-      *pval = NULL;
-      return 2;
-
-    default:
-      return 1;
+static int marshal_integer(CBB *cbb, BIGNUM *bn) {
+  if (bn == NULL) {
+    /* A DSA object may be missing some components. */
+    OPENSSL_PUT_ERROR(DSA, ERR_R_PASSED_NULL_PARAMETER);
+    return 0;
   }
+  return BN_marshal_asn1(cbb, bn);
 }
 
-ASN1_SEQUENCE_cb(DSAPrivateKey, dsa_cb) = {
-    ASN1_SIMPLE(DSA, version, LONG),
-    ASN1_SIMPLE(DSA, p, BIGNUM),
-    ASN1_SIMPLE(DSA, q, BIGNUM),
-    ASN1_SIMPLE(DSA, g, BIGNUM),
-    ASN1_SIMPLE(DSA, pub_key, BIGNUM),
-    ASN1_SIMPLE(DSA, priv_key, BIGNUM)} ASN1_SEQUENCE_END_cb(DSA,
-                                                             DSAPrivateKey);
+DSA_SIG *DSA_SIG_parse(CBS *cbs) {
+  DSA_SIG *ret = DSA_SIG_new();
+  if (ret == NULL) {
+    return NULL;
+  }
+  CBS child;
+  if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
+      !parse_integer(&child, &ret->r) ||
+      !parse_integer(&child, &ret->s) ||
+      CBS_len(&child) != 0) {
+    OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
+    DSA_SIG_free(ret);
+    return NULL;
+  }
+  return ret;
+}
 
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA, DSAPrivateKey, DSAPrivateKey);
+int DSA_SIG_marshal(CBB *cbb, const DSA_SIG *sig) {
+  CBB child;
+  if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) ||
+      !marshal_integer(&child, sig->r) ||
+      !marshal_integer(&child, sig->s) ||
+      !CBB_flush(cbb)) {
+    OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR);
+    return 0;
+  }
+  return 1;
+}
 
-ASN1_SEQUENCE_cb(DSAparams, dsa_cb) = {
-    ASN1_SIMPLE(DSA, p, BIGNUM), ASN1_SIMPLE(DSA, q, BIGNUM),
-    ASN1_SIMPLE(DSA, g, BIGNUM), } ASN1_SEQUENCE_END_cb(DSA, DSAparams);
+DSA *DSA_parse_public_key(CBS *cbs) {
+  DSA *ret = DSA_new();
+  if (ret == NULL) {
+    return NULL;
+  }
+  CBS child;
+  if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
+      !parse_integer(&child, &ret->pub_key) ||
+      !parse_integer(&child, &ret->p) ||
+      !parse_integer(&child, &ret->q) ||
+      !parse_integer(&child, &ret->g) ||
+      CBS_len(&child) != 0) {
+    OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
+    DSA_free(ret);
+    return NULL;
+  }
+  return ret;
+}
 
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA, DSAparams, DSAparams);
+int DSA_marshal_public_key(CBB *cbb, const DSA *dsa) {
+  CBB child;
+  if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) ||
+      !marshal_integer(&child, dsa->pub_key) ||
+      !marshal_integer(&child, dsa->p) ||
+      !marshal_integer(&child, dsa->q) ||
+      !marshal_integer(&child, dsa->g) ||
+      !CBB_flush(cbb)) {
+    OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR);
+    return 0;
+  }
+  return 1;
+}
 
+DSA *DSA_parse_parameters(CBS *cbs) {
+  DSA *ret = DSA_new();
+  if (ret == NULL) {
+    return NULL;
+  }
+  CBS child;
+  if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
+      !parse_integer(&child, &ret->p) ||
+      !parse_integer(&child, &ret->q) ||
+      !parse_integer(&child, &ret->g) ||
+      CBS_len(&child) != 0) {
+    OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
+    DSA_free(ret);
+    return NULL;
+  }
+  return ret;
+}
 
-/* DSA public key is a bit trickier... its effectively a CHOICE type decided by
- * a field called write_params which can either write out just the public key
- * as an INTEGER or the parameters and public key in a SEQUENCE. */
+int DSA_marshal_parameters(CBB *cbb, const DSA *dsa) {
+  CBB child;
+  if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) ||
+      !marshal_integer(&child, dsa->p) ||
+      !marshal_integer(&child, dsa->q) ||
+      !marshal_integer(&child, dsa->g) ||
+      !CBB_flush(cbb)) {
+    OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR);
+    return 0;
+  }
+  return 1;
+}
 
-ASN1_SEQUENCE(dsa_pub_internal) = {
-	ASN1_SIMPLE(DSA, pub_key, BIGNUM),
-	ASN1_SIMPLE(DSA, p, BIGNUM),
-	ASN1_SIMPLE(DSA, q, BIGNUM),
-	ASN1_SIMPLE(DSA, g, BIGNUM)
-} ASN1_SEQUENCE_END_name(DSA, dsa_pub_internal);
+DSA *DSA_parse_private_key(CBS *cbs) {
+  DSA *ret = DSA_new();
+  if (ret == NULL) {
+    return NULL;
+  }
 
-ASN1_CHOICE_cb(DSAPublicKey, dsa_cb) = {
-	ASN1_SIMPLE(DSA, pub_key, BIGNUM),
-	ASN1_EX_COMBINE(0, 0, dsa_pub_internal)
-} ASN1_CHOICE_END_cb(DSA, DSAPublicKey, write_params);
+  CBS child;
+  uint64_t version;
+  if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
+      !CBS_get_asn1_uint64(&child, &version)) {
+    OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
+    goto err;
+  }
 
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_const_fname(DSA, DSAPublicKey, DSAPublicKey);
+  if (version != 0) {
+    OPENSSL_PUT_ERROR(DSA, DSA_R_BAD_VERSION);
+    goto err;
+  }
 
-DSA *DSAparams_dup(const DSA *dsa) {
-  return ASN1_item_dup(ASN1_ITEM_rptr(DSAparams), (DSA*) dsa);
+  if (!parse_integer(&child, &ret->p) ||
+      !parse_integer(&child, &ret->q) ||
+      !parse_integer(&child, &ret->g) ||
+      !parse_integer(&child, &ret->pub_key) ||
+      !parse_integer(&child, &ret->priv_key) ||
+      CBS_len(&child) != 0) {
+    OPENSSL_PUT_ERROR(DSA, DSA_R_DECODE_ERROR);
+    goto err;
+  }
+  return ret;
+
+err:
+  DSA_free(ret);
+  return NULL;
+}
+
+int DSA_marshal_private_key(CBB *cbb, const DSA *dsa) {
+  CBB child;
+  if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) ||
+      !CBB_add_asn1_uint64(&child, 0 /* version */) ||
+      !marshal_integer(&child, dsa->p) ||
+      !marshal_integer(&child, dsa->q) ||
+      !marshal_integer(&child, dsa->g) ||
+      !marshal_integer(&child, dsa->pub_key) ||
+      !marshal_integer(&child, dsa->priv_key) ||
+      !CBB_flush(cbb)) {
+    OPENSSL_PUT_ERROR(DSA, DSA_R_ENCODE_ERROR);
+    return 0;
+  }
+  return 1;
+}
+
+DSA_SIG *d2i_DSA_SIG(DSA_SIG **out_sig, const uint8_t **inp, long len) {
+  if (len < 0) {
+    return NULL;
+  }
+  CBS cbs;
+  CBS_init(&cbs, *inp, (size_t)len);
+  DSA_SIG *ret = DSA_SIG_parse(&cbs);
+  if (ret == NULL) {
+    return NULL;
+  }
+  if (out_sig != NULL) {
+    DSA_SIG_free(*out_sig);
+    *out_sig = ret;
+  }
+  *inp = CBS_data(&cbs);
+  return ret;
+}
+
+int i2d_DSA_SIG(const DSA_SIG *in, uint8_t **outp) {
+  CBB cbb;
+  if (!CBB_init(&cbb, 0) ||
+      !DSA_SIG_marshal(&cbb, in)) {
+    CBB_cleanup(&cbb);
+    return -1;
+  }
+  return CBB_finish_i2d(&cbb, outp);
+}
+
+DSA *d2i_DSAPublicKey(DSA **out, const uint8_t **inp, long len) {
+  if (len < 0) {
+    return NULL;
+  }
+  CBS cbs;
+  CBS_init(&cbs, *inp, (size_t)len);
+  DSA *ret = DSA_parse_public_key(&cbs);
+  if (ret == NULL) {
+    return NULL;
+  }
+  if (out != NULL) {
+    DSA_free(*out);
+    *out = ret;
+  }
+  *inp = CBS_data(&cbs);
+  return ret;
+}
+
+int i2d_DSAPublicKey(const DSA *in, uint8_t **outp) {
+  CBB cbb;
+  if (!CBB_init(&cbb, 0) ||
+      !DSA_marshal_public_key(&cbb, in)) {
+    CBB_cleanup(&cbb);
+    return -1;
+  }
+  return CBB_finish_i2d(&cbb, outp);
+}
+
+DSA *d2i_DSAPrivateKey(DSA **out, const uint8_t **inp, long len) {
+  if (len < 0) {
+    return NULL;
+  }
+  CBS cbs;
+  CBS_init(&cbs, *inp, (size_t)len);
+  DSA *ret = DSA_parse_private_key(&cbs);
+  if (ret == NULL) {
+    return NULL;
+  }
+  if (out != NULL) {
+    DSA_free(*out);
+    *out = ret;
+  }
+  *inp = CBS_data(&cbs);
+  return ret;
+}
+
+int i2d_DSAPrivateKey(const DSA *in, uint8_t **outp) {
+  CBB cbb;
+  if (!CBB_init(&cbb, 0) ||
+      !DSA_marshal_private_key(&cbb, in)) {
+    CBB_cleanup(&cbb);
+    return -1;
+  }
+  return CBB_finish_i2d(&cbb, outp);
+}
+
+DSA *d2i_DSAparams(DSA **out, const uint8_t **inp, long len) {
+  if (len < 0) {
+    return NULL;
+  }
+  CBS cbs;
+  CBS_init(&cbs, *inp, (size_t)len);
+  DSA *ret = DSA_parse_parameters(&cbs);
+  if (ret == NULL) {
+    return NULL;
+  }
+  if (out != NULL) {
+    DSA_free(*out);
+    *out = ret;
+  }
+  *inp = CBS_data(&cbs);
+  return ret;
+}
+
+int i2d_DSAparams(const DSA *in, uint8_t **outp) {
+  CBB cbb;
+  if (!CBB_init(&cbb, 0) ||
+      !DSA_marshal_parameters(&cbb, in)) {
+    CBB_cleanup(&cbb);
+    return -1;
+  }
+  return CBB_finish_i2d(&cbb, outp);
 }
diff --git a/src/crypto/dsa/dsa_test.c b/src/crypto/dsa/dsa_test.cc
similarity index 77%
rename from src/crypto/dsa/dsa_test.c
rename to src/crypto/dsa/dsa_test.cc
index 8bdaaf4..63b7803 100644
--- a/src/crypto/dsa/dsa_test.c
+++ b/src/crypto/dsa/dsa_test.cc
@@ -59,17 +59,18 @@
 
 #include <openssl/dsa.h>
 
+#include <stdio.h>
 #include <string.h>
 
+#include <gtest/gtest.h>
+
 #include <openssl/bn.h>
 #include <openssl/crypto.h>
 #include <openssl/err.h>
 
-#include "internal.h"
+#include "../internal.h"
 
 
-static int dsa_cb(int p, int n, BN_GENCB *arg);
-
 /* The following values are taken from the updated Appendix 5 to FIPS PUB 186
  * and also appear in Appendix 5 to FIPS PUB 186-1. */
 
@@ -165,28 +166,59 @@
     0xdc, 0xd8, 0xc8,
 };
 
-static DSA *get_fips_dsa(void) {
-  DSA *dsa = DSA_new();
+static bssl::UniquePtr<DSA> GetFIPSDSA(void) {
+  bssl::UniquePtr<DSA>  dsa(DSA_new());
   if (!dsa) {
-    return NULL;
+    return nullptr;
   }
-  dsa->p = BN_bin2bn(fips_p, sizeof(fips_p), NULL);
-  dsa->q = BN_bin2bn(fips_q, sizeof(fips_q), NULL);
-  dsa->g = BN_bin2bn(fips_g, sizeof(fips_g), NULL);
-  dsa->pub_key = BN_bin2bn(fips_y, sizeof(fips_y), NULL);
-  dsa->priv_key = BN_bin2bn(fips_x, sizeof(fips_x), NULL);
-  if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL ||
-      dsa->pub_key == NULL || dsa->priv_key == NULL) {
-    DSA_free(dsa);
-    return NULL;
+  dsa->p = BN_bin2bn(fips_p, sizeof(fips_p), nullptr);
+  dsa->q = BN_bin2bn(fips_q, sizeof(fips_q), nullptr);
+  dsa->g = BN_bin2bn(fips_g, sizeof(fips_g), nullptr);
+  dsa->pub_key = BN_bin2bn(fips_y, sizeof(fips_y), nullptr);
+  dsa->priv_key = BN_bin2bn(fips_x, sizeof(fips_x), nullptr);
+  if (dsa->p == nullptr || dsa->q == nullptr || dsa->g == nullptr ||
+      dsa->pub_key == nullptr || dsa->priv_key == nullptr) {
+    return nullptr;
   }
   return dsa;
 }
 
-static int test_generate(FILE *out) {
+struct GenerateContext {
+  FILE *out = nullptr;
+  int ok = 0;
+  int num = 0;
+};
+
+static int GenerateCallback(int p, int n, BN_GENCB *arg) {
+  GenerateContext *ctx = reinterpret_cast<GenerateContext *>(arg->arg);
+  char c = '*';
+  switch (p) {
+    case 0:
+      c = '.';
+      ctx->num++;
+      break;
+    case 1:
+      c = '+';
+      break;
+    case 2:
+      c = '*';
+      ctx->ok++;
+      break;
+    case 3:
+      c = '\n';
+  }
+  fputc(c, ctx->out);
+  fflush(ctx->out);
+  if (!ctx->ok && p == 0 && ctx->num > 1) {
+    fprintf(stderr, "error in dsatest\n");
+    return 0;
+  }
+  return 1;
+}
+
+static int TestGenerate(FILE *out) {
   BN_GENCB cb;
-  DSA *dsa = NULL;
-  int counter, ok = 0, i, j;
+  int counter, i, j;
   uint8_t buf[256];
   unsigned long h;
   uint8_t sig[256];
@@ -194,11 +226,14 @@
 
   fprintf(out, "test generation of DSA parameters\n");
 
-  BN_GENCB_set(&cb, dsa_cb, out);
-  dsa = DSA_new();
-  if (dsa == NULL ||
-      !DSA_generate_parameters_ex(dsa, 512, seed, 20, &counter, &h, &cb)) {
-    goto end;
+  GenerateContext ctx;
+  ctx.out = out;
+  BN_GENCB_set(&cb, GenerateCallback, &ctx);
+  bssl::UniquePtr<DSA> dsa(DSA_new());
+  if (!dsa ||
+      !DSA_generate_parameters_ex(dsa.get(), 512, seed, 20, &counter, &h,
+                                  &cb)) {
+    return false;
   }
 
   fprintf(out, "seed\n");
@@ -210,116 +245,73 @@
 
   if (counter != 105) {
     fprintf(stderr, "counter should be 105\n");
-    goto end;
+    return false;
   }
   if (h != 2) {
     fprintf(stderr, "h should be 2\n");
-    goto end;
+    return false;
   }
 
   i = BN_bn2bin(dsa->q, buf);
   j = sizeof(fips_q);
-  if (i != j || memcmp(buf, fips_q, i) != 0) {
+  if (i != j || OPENSSL_memcmp(buf, fips_q, i) != 0) {
     fprintf(stderr, "q value is wrong\n");
-    goto end;
+    return false;
   }
 
   i = BN_bn2bin(dsa->p, buf);
   j = sizeof(fips_p);
-  if (i != j || memcmp(buf, fips_p, i) != 0) {
+  if (i != j || OPENSSL_memcmp(buf, fips_p, i) != 0) {
     fprintf(stderr, "p value is wrong\n");
-    goto end;
+    return false;
   }
 
   i = BN_bn2bin(dsa->g, buf);
   j = sizeof(fips_g);
-  if (i != j || memcmp(buf, fips_g, i) != 0) {
+  if (i != j || OPENSSL_memcmp(buf, fips_g, i) != 0) {
     fprintf(stderr, "g value is wrong\n");
-    goto end;
+    return false;
   }
 
-  if (!DSA_generate_key(dsa) ||
-      !DSA_sign(0, fips_digest, sizeof(fips_digest), sig, &siglen, dsa)) {
-    goto end;
+  if (!DSA_generate_key(dsa.get()) ||
+      !DSA_sign(0, fips_digest, sizeof(fips_digest), sig, &siglen, dsa.get())) {
+    return false;
   }
-  if (DSA_verify(0, fips_digest, sizeof(fips_digest), sig, siglen, dsa) == 1) {
-    ok = 1;
-  } else {
+  if (DSA_verify(0, fips_digest, sizeof(fips_digest), sig, siglen, dsa.get()) !=
+      1) {
     fprintf(stderr, "verification failure\n");
+    return false;
   }
 
-end:
-  DSA_free(dsa);
-
-  return ok;
+  return true;
 }
 
-static int test_verify(const uint8_t *sig, size_t sig_len, int expect) {
-  int ok = 0;
-  DSA *dsa = get_fips_dsa();
-  if (dsa == NULL) {
-    goto end;
+static bool TestVerify(const uint8_t *sig, size_t sig_len, int expect) {
+  bssl::UniquePtr<DSA> dsa = GetFIPSDSA();
+  if (!dsa) {
+    return false;
   }
 
-  int ret = DSA_verify(0, fips_digest, sizeof(fips_digest), sig, sig_len, dsa);
+  int ret =
+      DSA_verify(0, fips_digest, sizeof(fips_digest), sig, sig_len, dsa.get());
   if (ret != expect) {
     fprintf(stderr, "DSA_verify returned %d, want %d\n", ret, expect);
-    goto end;
+    return false;
   }
-  ok = 1;
-  /* Clear any errorrs from a test with expected failure. */
+
+  /* Clear any errors from a test with expected failure. */
   ERR_clear_error();
-
-end:
-  DSA_free(dsa);
-
-  return ok;
+  return true;
 }
 
-int main(int argc, char **argv) {
-  CRYPTO_library_init();
-
-  if (!test_generate(stdout) ||
-      !test_verify(fips_sig, sizeof(fips_sig), 1) ||
-      !test_verify(fips_sig_negative, sizeof(fips_sig_negative), -1) ||
-      !test_verify(fips_sig_extra, sizeof(fips_sig_extra), -1) ||
-      !test_verify(fips_sig_bad_length, sizeof(fips_sig_bad_length), -1) ||
-      !test_verify(fips_sig_bad_r, sizeof(fips_sig_bad_r), 0)) {
-    ERR_print_errors_fp(stderr);
-    return 1;
+// TODO(davidben): Convert this file to GTest properly.
+TEST(DSATest, AllTests) {
+  if (!TestGenerate(stdout) ||
+      !TestVerify(fips_sig, sizeof(fips_sig), 1) ||
+      !TestVerify(fips_sig_negative, sizeof(fips_sig_negative), -1) ||
+      !TestVerify(fips_sig_extra, sizeof(fips_sig_extra), -1) ||
+      !TestVerify(fips_sig_bad_length, sizeof(fips_sig_bad_length), -1) ||
+      !TestVerify(fips_sig_bad_r, sizeof(fips_sig_bad_r), 0)) {
+    ADD_FAILURE() << "Tests failed";
   }
-
-  printf("PASS\n");
-  return 0;
-}
-
-static int dsa_cb(int p, int n, BN_GENCB *arg) {
-  char c = '*';
-  static int ok = 0, num = 0;
-
-  switch (p) {
-  case 0:
-    c = '.';
-    num++;
-    break;
-  case 1:
-    c = '+';
-    break;
-  case 2:
-    c = '*';
-    ok++;
-    break;
-  case 3:
-    c = '\n';
-  }
-
-  fputc(c, arg->arg);
-  fflush(arg->arg);
-
-  if (!ok && p == 0 && num > 1) {
-    fprintf(stderr, "error in dsatest\n");
-    return 0;
-  }
-
-  return 1;
 }
diff --git a/src/crypto/ec/CMakeLists.txt b/src/crypto/ec/CMakeLists.txt
index 4749484..75dccec 100644
--- a/src/crypto/ec/CMakeLists.txt
+++ b/src/crypto/ec/CMakeLists.txt
@@ -39,13 +39,13 @@
 )
 
 add_executable(
-  ec_test
+  p256-x86_64_test
 
-  ec_test.cc
+  p256-x86_64_test.cc
 
   $<TARGET_OBJECTS:test_support>
 )
 
 target_link_libraries(example_mul crypto)
-target_link_libraries(ec_test crypto)
-add_dependencies(all_tests example_mul ec_test)
+target_link_libraries(p256-x86_64_test crypto)
+add_dependencies(all_tests example_mul p256-x86_64_test)
diff --git a/src/crypto/ec/asm/p256-x86_64-asm.pl b/src/crypto/ec/asm/p256-x86_64-asm.pl
old mode 100644
new mode 100755
index 361a84b..517c506
--- a/src/crypto/ec/asm/p256-x86_64-asm.pl
+++ b/src/crypto/ec/asm/p256-x86_64-asm.pl
@@ -51,7 +51,7 @@
 ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
 die "can't locate x86_64-xlate.pl";
 
-open OUT,"| \"$^X\" $xlate $flavour $output";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
 *STDOUT=*OUT;
 
 # TODO: enable these after testing. $avx goes to two and $addx to one.
@@ -78,56 +78,12 @@
 ___
 
 {
-################################################################################
-# void ecp_nistz256_mul_by_2(uint64_t res[4], uint64_t a[4]);
-
 my ($a0,$a1,$a2,$a3)=map("%r$_",(8..11));
 my ($t0,$t1,$t2,$t3,$t4)=("%rax","%rdx","%rcx","%r12","%r13");
 my ($r_ptr,$a_ptr,$b_ptr)=("%rdi","%rsi","%rdx");
 
 $code.=<<___;
 
-.type	ecp_nistz256_mul_by_2,\@function,2
-.align	64
-ecp_nistz256_mul_by_2:
-	push	%r12
-	push	%r13
-
-	mov	8*0($a_ptr), $a0
-	mov	8*1($a_ptr), $a1
-	add	$a0, $a0		# a0:a3+a0:a3
-	mov	8*2($a_ptr), $a2
-	adc	$a1, $a1
-	mov	8*3($a_ptr), $a3
-	lea	.Lpoly(%rip), $a_ptr
-	 mov	$a0, $t0
-	adc	$a2, $a2
-	adc	$a3, $a3
-	 mov	$a1, $t1
-	sbb	$t4, $t4
-
-	sub	8*0($a_ptr), $a0
-	 mov	$a2, $t2
-	sbb	8*1($a_ptr), $a1
-	sbb	8*2($a_ptr), $a2
-	 mov	$a3, $t3
-	sbb	8*3($a_ptr), $a3
-	test	$t4, $t4
-
-	cmovz	$t0, $a0
-	cmovz	$t1, $a1
-	mov	$a0, 8*0($r_ptr)
-	cmovz	$t2, $a2
-	mov	$a1, 8*1($r_ptr)
-	cmovz	$t3, $a3
-	mov	$a2, 8*2($r_ptr)
-	mov	$a3, 8*3($r_ptr)
-
-	pop	%r13
-	pop	%r12
-	ret
-.size	ecp_nistz256_mul_by_2,.-ecp_nistz256_mul_by_2
-
 ################################################################################
 # void ecp_nistz256_neg(uint64_t res[4], uint64_t a[4]);
 .globl	ecp_nistz256_neg
@@ -989,108 +945,6 @@
 }
 }
 {
-my ($r_ptr,$in_ptr)=("%rdi","%rsi");
-my ($acc0,$acc1,$acc2,$acc3)=map("%r$_",(8..11));
-my ($t0,$t1,$t2)=("%rcx","%r12","%r13");
-
-$code.=<<___;
-################################################################################
-# void ecp_nistz256_from_mont(
-#   uint64_t res[4],
-#   uint64_t in[4]);
-# This one performs Montgomery multiplication by 1, so we only need the reduction
-
-.globl	ecp_nistz256_from_mont
-.type	ecp_nistz256_from_mont,\@function,2
-.align	32
-ecp_nistz256_from_mont:
-	push	%r12
-	push	%r13
-
-	mov	8*0($in_ptr), %rax
-	mov	.Lpoly+8*3(%rip), $t2
-	mov	8*1($in_ptr), $acc1
-	mov	8*2($in_ptr), $acc2
-	mov	8*3($in_ptr), $acc3
-	mov	%rax, $acc0
-	mov	.Lpoly+8*1(%rip), $t1
-
-	#########################################
-	# First iteration
-	mov	%rax, $t0
-	shl	\$32, $acc0
-	mulq	$t2
-	shr	\$32, $t0
-	add	$acc0, $acc1
-	adc	$t0, $acc2
-	adc	%rax, $acc3
-	 mov	$acc1, %rax
-	adc	\$0, %rdx
-
-	#########################################
-	# Second iteration
-	mov	$acc1, $t0
-	shl	\$32, $acc1
-	mov	%rdx, $acc0
-	mulq	$t2
-	shr	\$32, $t0
-	add	$acc1, $acc2
-	adc	$t0, $acc3
-	adc	%rax, $acc0
-	 mov	$acc2, %rax
-	adc	\$0, %rdx
-
-	##########################################
-	# Third iteration
-	mov	$acc2, $t0
-	shl	\$32, $acc2
-	mov	%rdx, $acc1
-	mulq	$t2
-	shr	\$32, $t0
-	add	$acc2, $acc3
-	adc	$t0, $acc0
-	adc	%rax, $acc1
-	 mov	$acc3, %rax
-	adc	\$0, %rdx
-
-	###########################################
-	# Last iteration
-	mov	$acc3, $t0
-	shl	\$32, $acc3
-	mov	%rdx, $acc2
-	mulq	$t2
-	shr	\$32, $t0
-	add	$acc3, $acc0
-	adc	$t0, $acc1
-	 mov	$acc0, $t0
-	adc	%rax, $acc2
-	 mov	$acc1, $in_ptr
-	adc	\$0, %rdx
-
-	sub	\$-1, $acc0
-	 mov	$acc2, %rax
-	sbb	$t1, $acc1
-	sbb	\$0, $acc2
-	 mov	%rdx, $acc3
-	sbb	$t2, %rdx
-	sbb	$t2, $t2
-
-	cmovnz	$t0, $acc0
-	cmovnz	$in_ptr, $acc1
-	mov	$acc0, 8*0($r_ptr)
-	cmovnz	%rax, $acc2
-	mov	$acc1, 8*1($r_ptr)
-	cmovz	%rdx, $acc3
-	mov	$acc2, 8*2($r_ptr)
-	mov	$acc3, 8*3($r_ptr)
-
-	pop	%r13
-	pop	%r12
-	ret
-.size	ecp_nistz256_from_mont,.-ecp_nistz256_from_mont
-___
-}
-{
 my ($val,$in_t,$index)=$win64?("%rcx","%rdx","%r8d"):("%rdi","%rsi","%edx");
 my ($ONE,$INDEX,$Ra,$Rb,$Rc,$Rd,$Re,$Rf)=map("%xmm$_",(0..7));
 my ($M0,$T0a,$T0b,$T0c,$T0d,$T0e,$T0f,$TMP0)=map("%xmm$_",(8..15));
@@ -1568,13 +1422,14 @@
 .type	__ecp_nistz256_add_toq,\@abi-omnipotent
 .align	32
 __ecp_nistz256_add_toq:
+	xor	$t4,$t4
 	add	8*0($b_ptr), $a0
 	adc	8*1($b_ptr), $a1
 	 mov	$a0, $t0
 	adc	8*2($b_ptr), $a2
 	adc	8*3($b_ptr), $a3
 	 mov	$a1, $t1
-	sbb	$t4, $t4
+	adc	\$0, $t4
 
 	sub	\$-1, $a0
 	 mov	$a2, $t2
@@ -1582,14 +1437,14 @@
 	sbb	\$0, $a2
 	 mov	$a3, $t3
 	sbb	$poly3, $a3
-	test	$t4, $t4
+	sbb	\$0, $t4
 
-	cmovz	$t0, $a0
-	cmovz	$t1, $a1
+	cmovc	$t0, $a0
+	cmovc	$t1, $a1
 	mov	$a0, 8*0($r_ptr)
-	cmovz	$t2, $a2
+	cmovc	$t2, $a2
 	mov	$a1, 8*1($r_ptr)
-	cmovz	$t3, $a3
+	cmovc	$t3, $a3
 	mov	$a2, 8*2($r_ptr)
 	mov	$a3, 8*3($r_ptr)
 
@@ -1657,13 +1512,14 @@
 .type	__ecp_nistz256_mul_by_2q,\@abi-omnipotent
 .align	32
 __ecp_nistz256_mul_by_2q:
+	xor	$t4, $t4
 	add	$a0, $a0		# a0:a3+a0:a3
 	adc	$a1, $a1
 	 mov	$a0, $t0
 	adc	$a2, $a2
 	adc	$a3, $a3
 	 mov	$a1, $t1
-	sbb	$t4, $t4
+	adc	\$0, $t4
 
 	sub	\$-1, $a0
 	 mov	$a2, $t2
@@ -1671,14 +1527,14 @@
 	sbb	\$0, $a2
 	 mov	$a3, $t3
 	sbb	$poly3, $a3
-	test	$t4, $t4
+	sbb	\$0, $t4
 
-	cmovz	$t0, $a0
-	cmovz	$t1, $a1
+	cmovc	$t0, $a0
+	cmovc	$t1, $a1
 	mov	$a0, 8*0($r_ptr)
-	cmovz	$t2, $a2
+	cmovc	$t2, $a2
 	mov	$a1, 8*1($r_ptr)
-	cmovz	$t3, $a3
+	cmovc	$t3, $a3
 	mov	$a2, 8*2($r_ptr)
 	mov	$a3, 8*3($r_ptr)
 
@@ -1729,6 +1585,7 @@
 	push	%r15
 	sub	\$32*5+8, %rsp
 
+.Lpoint_double_shortcut$x:
 	movdqu	0x00($a_ptr), %xmm0		# copy	*(P256_POINT *)$a_ptr.x
 	mov	$a_ptr, $b_ptr			# backup copy
 	movdqu	0x10($a_ptr), %xmm1
@@ -1968,16 +1825,14 @@
 	mov	$b_org, $a_ptr			# reassign
 	movdqa	%xmm0, $in1_x(%rsp)
 	movdqa	%xmm1, $in1_x+0x10(%rsp)
-	por	%xmm0, %xmm1
 	movdqa	%xmm2, $in1_y(%rsp)
 	movdqa	%xmm3, $in1_y+0x10(%rsp)
-	por	%xmm2, %xmm3
 	movdqa	%xmm4, $in1_z(%rsp)
 	movdqa	%xmm5, $in1_z+0x10(%rsp)
-	por	%xmm1, %xmm3
+	por	%xmm4, %xmm5
 
 	movdqu	0x00($a_ptr), %xmm0		# copy	*(P256_POINT *)$b_ptr
-	 pshufd	\$0xb1, %xmm3, %xmm5
+	 pshufd	\$0xb1, %xmm5, %xmm3
 	movdqu	0x10($a_ptr), %xmm1
 	movdqu	0x20($a_ptr), %xmm2
 	 por	%xmm3, %xmm5
@@ -1989,14 +1844,14 @@
 	movdqa	%xmm0, $in2_x(%rsp)
 	 pshufd	\$0x1e, %xmm5, %xmm4
 	movdqa	%xmm1, $in2_x+0x10(%rsp)
-	por	%xmm0, %xmm1
-	 movq	$r_ptr, %xmm0			# save $r_ptr
+	movdqu	0x40($a_ptr),%xmm0		# in2_z again
+	movdqu	0x50($a_ptr),%xmm1
 	movdqa	%xmm2, $in2_y(%rsp)
 	movdqa	%xmm3, $in2_y+0x10(%rsp)
-	por	%xmm2, %xmm3
 	 por	%xmm4, %xmm5
 	 pxor	%xmm4, %xmm4
-	por	%xmm1, %xmm3
+	por	%xmm0, %xmm1
+	 movq	$r_ptr, %xmm0			# save $r_ptr
 
 	lea	0x40-$bias($a_ptr), $a_ptr	# $a_ptr is still valid
 	 mov	$src0, $in2_z+8*0(%rsp)		# make in2_z copy
@@ -2007,8 +1862,8 @@
 	call	__ecp_nistz256_sqr_mont$x	# p256_sqr_mont(Z2sqr, in2_z);
 
 	pcmpeqd	%xmm4, %xmm5
-	pshufd	\$0xb1, %xmm3, %xmm4
-	por	%xmm3, %xmm4
+	pshufd	\$0xb1, %xmm1, %xmm4
+	por	%xmm1, %xmm4
 	pshufd	\$0, %xmm5, %xmm5		# in1infty
 	pshufd	\$0x1e, %xmm4, %xmm3
 	por	%xmm3, %xmm4
@@ -2019,6 +1874,7 @@
 	 mov	0x40+8*1($b_ptr), $acc6
 	 mov	0x40+8*2($b_ptr), $acc7
 	 mov	0x40+8*3($b_ptr), $acc0
+	movq	$b_ptr, %xmm1
 
 	lea	0x40-$bias($b_ptr), $a_ptr
 	lea	$Z1sqr(%rsp), $r_ptr		# Z1^2
@@ -2074,7 +1930,7 @@
 	test	$acc0, $acc0
 	jnz	.Ladd_proceed$x			# (in1infty || in2infty)?
 	test	$acc1, $acc1
-	jz	.Ladd_proceed$x			# is_equal(S1,S2)?
+	jz	.Ladd_double$x			# is_equal(S1,S2)?
 
 	movq	%xmm0, $r_ptr			# restore $r_ptr
 	pxor	%xmm0, %xmm0
@@ -2087,6 +1943,13 @@
 	jmp	.Ladd_done$x
 
 .align	32
+.Ladd_double$x:
+	movq	%xmm1, $a_ptr			# restore $a_ptr
+	movq	%xmm0, $r_ptr			# restore $r_ptr
+	add	\$`32*(18-5)`, %rsp		# difference in frame sizes
+	jmp	.Lpoint_double_shortcut$x
+
+.align	32
 .Ladd_proceed$x:
 	`&load_for_sqr("$R(%rsp)", "$src0")`
 	lea	$Rsqr(%rsp), $r_ptr		# R^2
@@ -2124,6 +1987,7 @@
 	#lea	$Hsqr(%rsp), $r_ptr	# 2*U1*H^2
 	#call	__ecp_nistz256_mul_by_2	# ecp_nistz256_mul_by_2(Hsqr, U2);
 
+	xor	$t4, $t4
 	add	$acc0, $acc0		# a0:a3+a0:a3
 	lea	$Rsqr(%rsp), $a_ptr
 	adc	$acc1, $acc1
@@ -2131,7 +1995,7 @@
 	adc	$acc2, $acc2
 	adc	$acc3, $acc3
 	 mov	$acc1, $t1
-	sbb	$t4, $t4
+	adc	\$0, $t4
 
 	sub	\$-1, $acc0
 	 mov	$acc2, $t2
@@ -2139,15 +2003,15 @@
 	sbb	\$0, $acc2
 	 mov	$acc3, $t3
 	sbb	$poly3, $acc3
-	test	$t4, $t4
+	sbb	\$0, $t4
 
-	cmovz	$t0, $acc0
+	cmovc	$t0, $acc0
 	mov	8*0($a_ptr), $t0
-	cmovz	$t1, $acc1
+	cmovc	$t1, $acc1
 	mov	8*1($a_ptr), $t1
-	cmovz	$t2, $acc2
+	cmovc	$t2, $acc2
 	mov	8*2($a_ptr), $t2
-	cmovz	$t3, $acc3
+	cmovc	$t3, $acc3
 	mov	8*3($a_ptr), $t3
 
 	call	__ecp_nistz256_sub$x		# p256_sub(res_x, Rsqr, Hsqr);
@@ -2331,16 +2195,14 @@
 	 mov	0x40+8*3($a_ptr), $acc0
 	movdqa	%xmm0, $in1_x(%rsp)
 	movdqa	%xmm1, $in1_x+0x10(%rsp)
-	por	%xmm0, %xmm1
 	movdqa	%xmm2, $in1_y(%rsp)
 	movdqa	%xmm3, $in1_y+0x10(%rsp)
-	por	%xmm2, %xmm3
 	movdqa	%xmm4, $in1_z(%rsp)
 	movdqa	%xmm5, $in1_z+0x10(%rsp)
-	por	%xmm1, %xmm3
+	por	%xmm4, %xmm5
 
 	movdqu	0x00($b_ptr), %xmm0	# copy	*(P256_POINT_AFFINE *)$b_ptr
-	 pshufd	\$0xb1, %xmm3, %xmm5
+	 pshufd	\$0xb1, %xmm5, %xmm3
 	movdqu	0x10($b_ptr), %xmm1
 	movdqu	0x20($b_ptr), %xmm2
 	 por	%xmm3, %xmm5
@@ -2429,6 +2291,7 @@
 	#lea	$Hsqr(%rsp), $r_ptr	# 2*U1*H^2
 	#call	__ecp_nistz256_mul_by_2	# ecp_nistz256_mul_by_2(Hsqr, U2);
 
+	xor	$t4, $t4
 	add	$acc0, $acc0		# a0:a3+a0:a3
 	lea	$Rsqr(%rsp), $a_ptr
 	adc	$acc1, $acc1
@@ -2436,7 +2299,7 @@
 	adc	$acc2, $acc2
 	adc	$acc3, $acc3
 	 mov	$acc1, $t1
-	sbb	$t4, $t4
+	adc	\$0, $t4
 
 	sub	\$-1, $acc0
 	 mov	$acc2, $t2
@@ -2444,15 +2307,15 @@
 	sbb	\$0, $acc2
 	 mov	$acc3, $t3
 	sbb	$poly3, $acc3
-	test	$t4, $t4
+	sbb	\$0, $t4
 
-	cmovz	$t0, $acc0
+	cmovc	$t0, $acc0
 	mov	8*0($a_ptr), $t0
-	cmovz	$t1, $acc1
+	cmovc	$t1, $acc1
 	mov	8*1($a_ptr), $t1
-	cmovz	$t2, $acc2
+	cmovc	$t2, $acc2
 	mov	8*2($a_ptr), $t2
-	cmovz	$t3, $acc3
+	cmovc	$t3, $acc3
 	mov	8*3($a_ptr), $t3
 
 	call	__ecp_nistz256_sub$x		# p256_sub(res_x, Rsqr, Hsqr);
@@ -2604,14 +2467,14 @@
 	sbb	\$0, $a2
 	 mov	$a3, $t3
 	sbb	$poly3, $a3
+	sbb	\$0, $t4
 
-	bt	\$0, $t4
-	cmovnc	$t0, $a0
-	cmovnc	$t1, $a1
+	cmovc	$t0, $a0
+	cmovc	$t1, $a1
 	mov	$a0, 8*0($r_ptr)
-	cmovnc	$t2, $a2
+	cmovc	$t2, $a2
 	mov	$a1, 8*1($r_ptr)
-	cmovnc	$t3, $a3
+	cmovc	$t3, $a3
 	mov	$a2, 8*2($r_ptr)
 	mov	$a3, 8*3($r_ptr)
 
@@ -2699,14 +2562,14 @@
 	sbb	\$0, $a2
 	 mov	$a3, $t3
 	sbb	$poly3, $a3
+	sbb	\$0, $t4
 
-	bt	\$0, $t4
-	cmovnc	$t0, $a0
-	cmovnc	$t1, $a1
+	cmovc	$t0, $a0
+	cmovc	$t1, $a1
 	mov	$a0, 8*0($r_ptr)
-	cmovnc	$t2, $a2
+	cmovc	$t2, $a2
 	mov	$a1, 8*1($r_ptr)
-	cmovnc	$t3, $a3
+	cmovc	$t3, $a3
 	mov	$a2, 8*2($r_ptr)
 	mov	$a3, 8*3($r_ptr)
 
diff --git a/src/crypto/ec/ec.c b/src/crypto/ec/ec.c
index a7097f2..96bb703 100644
--- a/src/crypto/ec/ec.c
+++ b/src/crypto/ec/ec.c
@@ -73,7 +73,7 @@
 #include <openssl/bn.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
 
 #include "internal.h"
 #include "../internal.h"
@@ -82,7 +82,6 @@
 static const struct curve_data P224 = {
     "NIST P-224",
     28,
-    1,
     {/* p */
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -112,7 +111,6 @@
 static const struct curve_data P256 = {
     "NIST P-256",
     32,
-    1,
     {/* p */
      0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
@@ -141,7 +139,6 @@
 static const struct curve_data P384 = {
     "NIST P-384",
     48,
-    1,
     {/* p */
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
@@ -176,7 +173,6 @@
 static const struct curve_data P521 = {
     "NIST P-521",
     66,
-    1,
     {/* p */
      0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
      0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
@@ -228,30 +224,48 @@
 #endif
 
 const struct built_in_curve OPENSSL_built_in_curves[] = {
-    {NID_secp521r1, &P521, 0},
-    {NID_secp384r1, &P384, 0},
     {
-        NID_X9_62_prime256v1, &P256,
+        NID_secp521r1,
+        /* 1.3.132.0.35 */
+        {0x2b, 0x81, 0x04, 0x00, 0x23}, 5,
+        &P521,
+        &EC_GFp_mont_method,
+      },
+    {
+        NID_secp384r1,
+        /* 1.3.132.0.34 */
+        {0x2b, 0x81, 0x04, 0x00, 0x22}, 5,
+        &P384,
+        &EC_GFp_mont_method,
+    },
+    {
+        NID_X9_62_prime256v1,
+        /* 1.2.840.10045.3.1.7 */
+        {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07}, 8,
+        &P256,
 #if defined(BORINGSSL_USE_INT128_CODE)
 #if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && \
     !defined(OPENSSL_SMALL)
-        EC_GFp_nistz256_method,
+        &EC_GFp_nistz256_method,
 #else
-        EC_GFp_nistp256_method,
+        &EC_GFp_nistp256_method,
 #endif
 #else
-        0,
+        &EC_GFp_mont_method,
 #endif
     },
     {
-        NID_secp224r1, &P224,
+        NID_secp224r1,
+        /* 1.3.132.0.33 */
+        {0x2b, 0x81, 0x04, 0x00, 0x21}, 5,
+        &P224,
 #if defined(BORINGSSL_USE_INT128_CODE) && !defined(OPENSSL_SMALL)
-        EC_GFp_nistp224_method,
+        &EC_GFp_nistp224_method,
 #else
-        0,
+        &EC_GFp_mont_method,
 #endif
     },
-    {NID_undef, 0, 0},
+    {NID_undef, {0}, 0, NULL, NULL},
 };
 
 /* built_in_curve_scalar_field_monts contains Montgomery contexts for
@@ -336,11 +350,10 @@
     OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
     return NULL;
   }
-  memset(ret, 0, sizeof(EC_GROUP));
+  OPENSSL_memset(ret, 0, sizeof(EC_GROUP));
 
   ret->meth = meth;
   BN_init(&ret->order);
-  BN_init(&ret->cofactor);
 
   if (!meth->group_init(ret)) {
     OPENSSL_free(ret);
@@ -352,10 +365,7 @@
 
 EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p, const BIGNUM *a,
                                  const BIGNUM *b, BN_CTX *ctx) {
-  const EC_METHOD *meth = EC_GFp_mont_method();
-  EC_GROUP *ret;
-
-  ret = ec_group_new(meth);
+  EC_GROUP *ret = ec_group_new(&EC_GFp_mont_method);
   if (ret == NULL) {
     return NULL;
   }
@@ -373,46 +383,22 @@
 
 int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
                            const BIGNUM *order, const BIGNUM *cofactor) {
-  if (group->curve_name != NID_undef) {
-    /* |EC_GROUP_set_generator| should only be used with |EC_GROUP|s returned
-     * by |EC_GROUP_new_curve_GFp|. */
+  if (group->curve_name != NID_undef || group->generator != NULL) {
+    /* |EC_GROUP_set_generator| may only be used with |EC_GROUP|s returned by
+     * |EC_GROUP_new_curve_GFp| and may only used once on each group. */
     return 0;
   }
 
   /* Require a cofactor of one for custom curves, which implies prime order. */
   if (!BN_is_one(cofactor)) {
-    OPENSSL_PUT_ERROR(EC, EC_R_WRONG_CURVE_PARAMETERS);
+    OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COFACTOR);
     return 0;
   }
 
-  if (group->generator == NULL) {
-    group->generator = EC_POINT_new(group);
-    if (group->generator == NULL) {
-      return 0;
-    }
-  }
-
-  if (!EC_POINT_copy(group->generator, generator)) {
-    return 0;
-  }
-
-  if (order != NULL) {
-    if (!BN_copy(&group->order, order)) {
-      return 0;
-    }
-  } else {
-    BN_zero(&group->order);
-  }
-
-  if (cofactor != NULL) {
-    if (!BN_copy(&group->cofactor, cofactor)) {
-      return 0;
-    }
-  } else {
-    BN_zero(&group->cofactor);
-  }
-
-  return 1;
+  group->generator = EC_POINT_new(group);
+  return group->generator != NULL &&
+         EC_POINT_copy(group->generator, generator) &&
+         BN_copy(&group->order, order);
 }
 
 static EC_GROUP *ec_group_new_from_data(unsigned built_in_index) {
@@ -420,7 +406,6 @@
   EC_GROUP *group = NULL;
   EC_POINT *P = NULL;
   BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL;
-  const EC_METHOD *meth;
   int ok = 0;
 
   BN_CTX *ctx = BN_CTX_new();
@@ -440,18 +425,11 @@
     goto err;
   }
 
-  if (curve->method != 0) {
-    meth = curve->method();
-    if (((group = ec_group_new(meth)) == NULL) ||
-        (!(group->meth->group_set_curve(group, p, a, b, ctx)))) {
-      OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
-      goto err;
-    }
-  } else {
-    if ((group = EC_GROUP_new_curve_GFp(p, a, b, ctx)) == NULL) {
-      OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
-      goto err;
-    }
+  group = ec_group_new(curve->method);
+  if (group == NULL ||
+      !group->meth->group_set_curve(group, p, a, b, ctx)) {
+    OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
+    goto err;
   }
 
   if ((P = EC_POINT_new(group)) == NULL) {
@@ -469,8 +447,7 @@
     OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
     goto err;
   }
-  if (!BN_bin2bn(params + 5 * param_len, param_len, &group->order) ||
-      !BN_set_word(&group->cofactor, (BN_ULONG)data->cofactor)) {
+  if (!BN_bin2bn(params + 5 * param_len, param_len, &group->order)) {
     OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
     goto err;
   }
@@ -533,80 +510,49 @@
 
   EC_POINT_free(group->generator);
   BN_free(&group->order);
-  BN_free(&group->cofactor);
 
   OPENSSL_free(group);
 }
 
-int ec_group_copy(EC_GROUP *dest, const EC_GROUP *src) {
-  if (dest->meth->group_copy == 0) {
-    OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
-    return 0;
-  }
-  if (dest->meth != src->meth) {
-    OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
-    return 0;
-  }
-  if (dest == src) {
-    return 1;
-  }
-
-  dest->mont_data = src->mont_data;
-
-  if (src->generator != NULL) {
-    if (dest->generator == NULL) {
-      dest->generator = EC_POINT_new(dest);
-      if (dest->generator == NULL) {
-        return 0;
-      }
-    }
-    if (!EC_POINT_copy(dest->generator, src->generator)) {
-      return 0;
-    }
-  } else {
-    EC_POINT_clear_free(dest->generator);
-    dest->generator = NULL;
-  }
-
-  if (!BN_copy(&dest->order, &src->order) ||
-      !BN_copy(&dest->cofactor, &src->cofactor)) {
-    return 0;
-  }
-
-  dest->curve_name = src->curve_name;
-
-  return dest->meth->group_copy(dest, src);
-}
-
 const BN_MONT_CTX *ec_group_get_mont_data(const EC_GROUP *group) {
   return group->mont_data;
 }
 
 EC_GROUP *EC_GROUP_dup(const EC_GROUP *a) {
-  EC_GROUP *t = NULL;
-  int ok = 0;
-
   if (a == NULL) {
     return NULL;
   }
 
-  t = ec_group_new(a->meth);
-  if (t == NULL) {
+  if (a->meth->group_copy == NULL) {
+    OPENSSL_PUT_ERROR(EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
     return NULL;
   }
-  if (!ec_group_copy(t, a)) {
+
+  EC_GROUP *ret = ec_group_new(a->meth);
+  if (ret == NULL) {
+    return NULL;
+  }
+
+  ret->mont_data = a->mont_data;
+  ret->curve_name = a->curve_name;
+
+  if (a->generator != NULL) {
+    ret->generator = EC_POINT_dup(a->generator, ret);
+    if (ret->generator == NULL) {
+      goto err;
+    }
+  }
+
+  if (!BN_copy(&ret->order, &a->order) ||
+      !ret->meth->group_copy(ret, a)) {
     goto err;
   }
 
-  ok = 1;
+  return ret;
 
 err:
-  if (!ok) {
-    EC_GROUP_free(t);
-    return NULL;
-  } else {
-    return t;
-  }
+  EC_GROUP_free(ret);
+  return NULL;
 }
 
 int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ignored) {
@@ -633,11 +579,8 @@
 
 int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor,
                           BN_CTX *ctx) {
-  if (!BN_copy(cofactor, &group->cofactor)) {
-    return 0;
-  }
-
-  return !BN_is_zero(&group->cofactor);
+  /* All |EC_GROUP|s have cofactor 1. */
+  return BN_set_word(cofactor, 1);
 }
 
 int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *out_p, BIGNUM *out_a,
@@ -708,25 +651,18 @@
 }
 
 EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group) {
-  EC_POINT *t;
-  int r;
-
   if (a == NULL) {
     return NULL;
   }
 
-  t = EC_POINT_new(group);
-  if (t == NULL) {
-    OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
+  EC_POINT *ret = EC_POINT_new(group);
+  if (ret == NULL ||
+      !EC_POINT_copy(ret, a)) {
+    EC_POINT_free(ret);
     return NULL;
   }
-  r = EC_POINT_copy(t, a);
-  if (!r) {
-    EC_POINT_free(t);
-    return NULL;
-  } else {
-    return t;
-  }
+
+  return ret;
 }
 
 int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point) {
@@ -773,9 +709,7 @@
 
 int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[],
                           BN_CTX *ctx) {
-  size_t i;
-
-  for (i = 0; i < num; i++) {
+  for (size_t i = 0; i < num; i++) {
     if (group->meth != points[i]->meth) {
       OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
       return 0;
@@ -893,3 +827,21 @@
     abort();
   }
 }
+
+size_t EC_get_builtin_curves(EC_builtin_curve *out_curves,
+                             size_t max_num_curves) {
+  unsigned num_built_in_curves;
+  for (num_built_in_curves = 0;; num_built_in_curves++) {
+    if (OPENSSL_built_in_curves[num_built_in_curves].nid == NID_undef) {
+      break;
+    }
+  }
+
+  unsigned i;
+  for (i = 0; i < max_num_curves && i < num_built_in_curves; i++) {
+    out_curves[i].comment = OPENSSL_built_in_curves[i].data->comment;
+    out_curves[i].nid = OPENSSL_built_in_curves[i].nid;
+  }
+
+  return num_built_in_curves;
+}
diff --git a/src/crypto/ec/ec_asn1.c b/src/crypto/ec/ec_asn1.c
index a085be5..35c8f27 100644
--- a/src/crypto/ec/ec_asn1.c
+++ b/src/crypto/ec/ec_asn1.c
@@ -53,472 +53,436 @@
 
 #include <openssl/ec.h>
 
+#include <limits.h>
 #include <string.h>
 
-#include <openssl/asn1.h>
-#include <openssl/asn1t.h>
+#include <openssl/bytestring.h>
 #include <openssl/bn.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
 
 #include "internal.h"
+#include "../bytestring/internal.h"
+#include "../internal.h"
 
 
-typedef struct x9_62_fieldid_st {
-  ASN1_OBJECT *fieldType;
-  union {
-    char *ptr;
-    /* NID_X9_62_prime_field */
-    ASN1_INTEGER *prime;
-    /* anything else */
-    ASN1_TYPE *other;
-  } p;
-} X9_62_FIELDID;
+static const uint8_t kParametersTag =
+    CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0;
+static const uint8_t kPublicKeyTag =
+    CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 1;
 
-ASN1_ADB_TEMPLATE(fieldID_def) = ASN1_SIMPLE(X9_62_FIELDID, p.other, ASN1_ANY);
-
-ASN1_ADB(X9_62_FIELDID) = {
-  ADB_ENTRY(NID_X9_62_prime_field, ASN1_SIMPLE(X9_62_FIELDID, p.prime, ASN1_INTEGER)),
-} ASN1_ADB_END(X9_62_FIELDID, 0, fieldType, 0, &fieldID_def_tt, NULL);
-
-ASN1_SEQUENCE(X9_62_FIELDID) = {
-  ASN1_SIMPLE(X9_62_FIELDID, fieldType, ASN1_OBJECT),
-  ASN1_ADB_OBJECT(X9_62_FIELDID)
-} ASN1_SEQUENCE_END(X9_62_FIELDID);
-
-typedef struct x9_62_curve_st {
-  ASN1_OCTET_STRING *a;
-  ASN1_OCTET_STRING *b;
-  ASN1_BIT_STRING *seed;
-} X9_62_CURVE;
-
-ASN1_SEQUENCE(X9_62_CURVE) = {
-  ASN1_SIMPLE(X9_62_CURVE, a, ASN1_OCTET_STRING),
-  ASN1_SIMPLE(X9_62_CURVE, b, ASN1_OCTET_STRING),
-  ASN1_OPT(X9_62_CURVE, seed, ASN1_BIT_STRING)
-} ASN1_SEQUENCE_END(X9_62_CURVE);
-
-typedef struct ec_parameters_st {
-  long version;
-  X9_62_FIELDID *fieldID;
-  X9_62_CURVE *curve;
-  ASN1_OCTET_STRING *base;
-  ASN1_INTEGER *order;
-  ASN1_INTEGER *cofactor;
-} ECPARAMETERS;
-
-DECLARE_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS);
-
-ASN1_SEQUENCE(ECPARAMETERS) = {
-    ASN1_SIMPLE(ECPARAMETERS, version, LONG),
-    ASN1_SIMPLE(ECPARAMETERS, fieldID, X9_62_FIELDID),
-    ASN1_SIMPLE(ECPARAMETERS, curve, X9_62_CURVE),
-    ASN1_SIMPLE(ECPARAMETERS, base, ASN1_OCTET_STRING),
-    ASN1_SIMPLE(ECPARAMETERS, order, ASN1_INTEGER),
-    ASN1_OPT(ECPARAMETERS, cofactor, ASN1_INTEGER)
-} ASN1_SEQUENCE_END(ECPARAMETERS);
-
-IMPLEMENT_ASN1_ALLOC_FUNCTIONS(ECPARAMETERS);
-
-typedef struct ecpk_parameters_st {
-  int type;
-  union {
-    ASN1_OBJECT *named_curve;
-    ECPARAMETERS *parameters;
-  } value;
-} ECPKPARAMETERS;
-
-/* SEC1 ECPrivateKey */
-typedef struct ec_privatekey_st {
-  long version;
-  ASN1_OCTET_STRING *privateKey;
-  ECPKPARAMETERS *parameters;
-  ASN1_BIT_STRING *publicKey;
-} EC_PRIVATEKEY;
-
-DECLARE_ASN1_FUNCTIONS_const(ECPKPARAMETERS);
-DECLARE_ASN1_ENCODE_FUNCTIONS_const(ECPKPARAMETERS, ECPKPARAMETERS);
-
-ASN1_CHOICE(ECPKPARAMETERS) = {
-    ASN1_SIMPLE(ECPKPARAMETERS, value.named_curve, ASN1_OBJECT),
-    ASN1_SIMPLE(ECPKPARAMETERS, value.parameters, ECPARAMETERS),
-} ASN1_CHOICE_END(ECPKPARAMETERS);
-
-IMPLEMENT_ASN1_FUNCTIONS_const(ECPKPARAMETERS);
-
-DECLARE_ASN1_FUNCTIONS_const(EC_PRIVATEKEY);
-DECLARE_ASN1_ENCODE_FUNCTIONS_const(EC_PRIVATEKEY, EC_PRIVATEKEY);
-
-ASN1_SEQUENCE(EC_PRIVATEKEY) = {
-    ASN1_SIMPLE(EC_PRIVATEKEY, version, LONG),
-    ASN1_SIMPLE(EC_PRIVATEKEY, privateKey, ASN1_OCTET_STRING),
-    ASN1_EXP_OPT(EC_PRIVATEKEY, parameters, ECPKPARAMETERS, 0),
-    ASN1_EXP_OPT(EC_PRIVATEKEY, publicKey, ASN1_BIT_STRING, 1),
-} ASN1_SEQUENCE_END(EC_PRIVATEKEY);
-
-IMPLEMENT_ASN1_FUNCTIONS_const(EC_PRIVATEKEY);
-
-
-ECPKPARAMETERS *ec_asn1_group2pkparameters(const EC_GROUP *group,
-                                           ECPKPARAMETERS *params) {
-  int ok = 0, nid;
-  ECPKPARAMETERS *ret = params;
-
-  if (ret == NULL) {
-    ret = ECPKPARAMETERS_new();
-    if (ret == NULL) {
-      OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
-      return NULL;
-    }
-  } else {
-    ASN1_OBJECT_free(ret->value.named_curve);
-  }
-
-  /* use the ASN.1 OID to describe the the elliptic curve parameters. */
-  nid = EC_GROUP_get_curve_name(group);
-  if (nid) {
-    ret->type = 0;
-    ret->value.named_curve = (ASN1_OBJECT*) OBJ_nid2obj(nid);
-    ok = ret->value.named_curve != NULL;
-  }
-
-  if (!ok) {
-    ECPKPARAMETERS_free(ret);
+EC_KEY *EC_KEY_parse_private_key(CBS *cbs, const EC_GROUP *group) {
+  CBS ec_private_key, private_key;
+  uint64_t version;
+  if (!CBS_get_asn1(cbs, &ec_private_key, CBS_ASN1_SEQUENCE) ||
+      !CBS_get_asn1_uint64(&ec_private_key, &version) ||
+      version != 1 ||
+      !CBS_get_asn1(&ec_private_key, &private_key, CBS_ASN1_OCTETSTRING)) {
+    OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
     return NULL;
   }
 
-  return ret;
-}
-
-EC_GROUP *ec_asn1_pkparameters2group(const ECPKPARAMETERS *params) {
-  EC_GROUP *ret = NULL;
-  int nid = NID_undef;
-
-  if (params == NULL) {
-    OPENSSL_PUT_ERROR(EC, EC_R_MISSING_PARAMETERS);
-    return NULL;
-  }
-
-  if (params->type == 0) {
-    nid = OBJ_obj2nid(params->value.named_curve);
-  } else if (params->type == 1) {
-    /* We don't support arbitary curves so we attempt to recognise it from the
-     * group order. */
-    const ECPARAMETERS *ecparams = params->value.parameters;
-    unsigned i;
-    const struct built_in_curve *curve;
-
-    for (i = 0; OPENSSL_built_in_curves[i].nid != NID_undef; i++) {
-      curve = &OPENSSL_built_in_curves[i];
-      const unsigned param_len = curve->data->param_len;
-      if ((unsigned) ecparams->order->length == param_len &&
-          memcmp(ecparams->order->data, &curve->data->data[param_len * 5],
-                 param_len) == 0) {
-        nid = curve->nid;
-        break;
-      }
-    }
-  }
-
-  if (nid == NID_undef) {
-    OPENSSL_PUT_ERROR(EC, EC_R_NON_NAMED_CURVE);
-    return NULL;
-  }
-
-  ret = EC_GROUP_new_by_curve_name(nid);
-  if (ret == NULL) {
-    OPENSSL_PUT_ERROR(EC, EC_R_EC_GROUP_NEW_BY_NAME_FAILURE);
-    return NULL;
-  }
-
-  return ret;
-}
-
-static EC_GROUP *d2i_ECPKParameters(EC_GROUP **groupp, const uint8_t **inp,
-                                    long len) {
-  EC_GROUP *group = NULL;
-  ECPKPARAMETERS *params = NULL;
-  const uint8_t *in = *inp;
-
-  params = d2i_ECPKPARAMETERS(NULL, &in, len);
-  if (params == NULL) {
-    OPENSSL_PUT_ERROR(EC, EC_R_D2I_ECPKPARAMETERS_FAILURE);
-    ECPKPARAMETERS_free(params);
-    return NULL;
-  }
-
-  group = ec_asn1_pkparameters2group(params);
-  if (group == NULL) {
-    OPENSSL_PUT_ERROR(EC, EC_R_PKPARAMETERS2GROUP_FAILURE);
-    ECPKPARAMETERS_free(params);
-    return NULL;
-  }
-
-  if (groupp) {
-    EC_GROUP_free(*groupp);
-    *groupp = group;
-  }
-
-  ECPKPARAMETERS_free(params);
-  *inp = in;
-  return group;
-}
-
-static int i2d_ECPKParameters(const EC_GROUP *group, uint8_t **outp) {
-  int ret = 0;
-  ECPKPARAMETERS *tmp = ec_asn1_group2pkparameters(group, NULL);
-  if (tmp == NULL) {
-    OPENSSL_PUT_ERROR(EC, EC_R_GROUP2PKPARAMETERS_FAILURE);
-    return 0;
-  }
-  ret = i2d_ECPKPARAMETERS(tmp, outp);
-  if (ret == 0) {
-    OPENSSL_PUT_ERROR(EC, EC_R_I2D_ECPKPARAMETERS_FAILURE);
-    ECPKPARAMETERS_free(tmp);
-    return 0;
-  }
-  ECPKPARAMETERS_free(tmp);
-  return ret;
-}
-
-EC_KEY *d2i_ECPrivateKey(EC_KEY **a, const uint8_t **inp, long len) {
-  int ok = 0;
+  /* Parse the optional parameters field. */
+  EC_GROUP *inner_group = NULL;
   EC_KEY *ret = NULL;
-  EC_PRIVATEKEY *priv_key = NULL;
-
-  const uint8_t *in = *inp;
-  priv_key = d2i_EC_PRIVATEKEY(NULL, &in, len);
-  if (priv_key == NULL) {
-    OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
-    return NULL;
-  }
-
-  if (a == NULL || *a == NULL) {
-    ret = EC_KEY_new();
-    if (ret == NULL) {
-      OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
+  if (CBS_peek_asn1_tag(&ec_private_key, kParametersTag)) {
+    /* Per SEC 1, as an alternative to omitting it, one is allowed to specify
+     * this field and put in a NULL to mean inheriting this value. This was
+     * omitted in a previous version of this logic without problems, so leave it
+     * unimplemented. */
+    CBS child;
+    if (!CBS_get_asn1(&ec_private_key, &child, kParametersTag)) {
+      OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
       goto err;
     }
-  } else {
-    ret = *a;
+    inner_group = EC_KEY_parse_parameters(&child);
+    if (inner_group == NULL) {
+      goto err;
+    }
+    if (group == NULL) {
+      group = inner_group;
+    } else if (EC_GROUP_cmp(group, inner_group, NULL) != 0) {
+      /* If a group was supplied externally, it must match. */
+      OPENSSL_PUT_ERROR(EC, EC_R_GROUP_MISMATCH);
+      goto err;
+    }
+    if (CBS_len(&child) != 0) {
+      OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
+      goto err;
+    }
   }
 
-  if (priv_key->parameters) {
-    EC_GROUP_free(ret->group);
-    ret->group = ec_asn1_pkparameters2group(priv_key->parameters);
-  }
-
-  if (ret->group == NULL) {
-    OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
+  if (group == NULL) {
+    OPENSSL_PUT_ERROR(EC, EC_R_MISSING_PARAMETERS);
     goto err;
   }
 
-  ret->version = priv_key->version;
-
-  if (priv_key->privateKey) {
-    ret->priv_key =
-        BN_bin2bn(M_ASN1_STRING_data(priv_key->privateKey),
-                  M_ASN1_STRING_length(priv_key->privateKey), ret->priv_key);
-    if (ret->priv_key == NULL) {
-      OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
-      goto err;
-    }
-  } else {
-    OPENSSL_PUT_ERROR(EC, EC_R_MISSING_PRIVATE_KEY);
+  ret = EC_KEY_new();
+  if (ret == NULL || !EC_KEY_set_group(ret, group)) {
     goto err;
   }
 
-  if (BN_cmp(ret->priv_key, EC_GROUP_get0_order(ret->group)) >= 0) {
+  /* Although RFC 5915 specifies the length of the key, OpenSSL historically
+   * got this wrong, so accept any length. See upstream's
+   * 30cd4ff294252c4b6a4b69cbef6a5b4117705d22. */
+  ret->priv_key =
+      BN_bin2bn(CBS_data(&private_key), CBS_len(&private_key), NULL);
+  ret->pub_key = EC_POINT_new(group);
+  if (ret->priv_key == NULL || ret->pub_key == NULL) {
+    goto err;
+  }
+
+  if (BN_cmp(ret->priv_key, EC_GROUP_get0_order(group)) >= 0) {
     OPENSSL_PUT_ERROR(EC, EC_R_WRONG_ORDER);
     goto err;
   }
 
-  EC_POINT_free(ret->pub_key);
-  ret->pub_key = EC_POINT_new(ret->group);
-  if (ret->pub_key == NULL) {
-    OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
-    goto err;
-  }
-
-  if (priv_key->publicKey) {
-    const uint8_t *pub_oct;
-    int pub_oct_len;
-
-    pub_oct = M_ASN1_STRING_data(priv_key->publicKey);
-    pub_oct_len = M_ASN1_STRING_length(priv_key->publicKey);
-    /* The first byte (the point conversion form) must be present. */
-    if (pub_oct_len <= 0) {
-      OPENSSL_PUT_ERROR(EC, EC_R_BUFFER_TOO_SMALL);
+  if (CBS_peek_asn1_tag(&ec_private_key, kPublicKeyTag)) {
+    CBS child, public_key;
+    uint8_t padding;
+    if (!CBS_get_asn1(&ec_private_key, &child, kPublicKeyTag) ||
+        !CBS_get_asn1(&child, &public_key, CBS_ASN1_BITSTRING) ||
+        /* As in a SubjectPublicKeyInfo, the byte-encoded public key is then
+         * encoded as a BIT STRING with bits ordered as in the DER encoding. */
+        !CBS_get_u8(&public_key, &padding) ||
+        padding != 0 ||
+        /* Explicitly check |public_key| is non-empty to save the conversion
+         * form later. */
+        CBS_len(&public_key) == 0 ||
+        !EC_POINT_oct2point(group, ret->pub_key, CBS_data(&public_key),
+                            CBS_len(&public_key), NULL) ||
+        CBS_len(&child) != 0) {
+      OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
       goto err;
     }
-    /* Save the point conversion form. */
-    ret->conv_form = (point_conversion_form_t)(pub_oct[0] & ~0x01);
-    if (!EC_POINT_oct2point(ret->group, ret->pub_key, pub_oct, pub_oct_len,
-                            NULL)) {
-      OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
-      goto err;
-    }
+
+    /* Save the point conversion form.
+     * TODO(davidben): Consider removing this. */
+    ret->conv_form = (point_conversion_form_t)(CBS_data(&public_key)[0] & ~0x01);
   } else {
-    if (!EC_POINT_mul(ret->group, ret->pub_key, ret->priv_key, NULL, NULL,
-                      NULL)) {
-      OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
+    /* Compute the public key instead. */
+    if (!EC_POINT_mul(group, ret->pub_key, ret->priv_key, NULL, NULL, NULL)) {
       goto err;
     }
-    /* Remember the original private-key-only encoding. */
+    /* Remember the original private-key-only encoding.
+     * TODO(davidben): Consider removing this. */
     ret->enc_flag |= EC_PKEY_NO_PUBKEY;
   }
 
-  if (a) {
-    *a = ret;
+  if (CBS_len(&ec_private_key) != 0) {
+    OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
+    goto err;
   }
-  *inp = in;
-  ok = 1;
+
+  /* Ensure the resulting key is valid. */
+  if (!EC_KEY_check_key(ret)) {
+    goto err;
+  }
+
+  EC_GROUP_free(inner_group);
+  return ret;
 
 err:
-  if (!ok) {
-    if (a == NULL || *a != ret) {
-      EC_KEY_free(ret);
-    }
-    ret = NULL;
+  EC_KEY_free(ret);
+  EC_GROUP_free(inner_group);
+  return NULL;
+}
+
+int EC_KEY_marshal_private_key(CBB *cbb, const EC_KEY *key,
+                               unsigned enc_flags) {
+  if (key == NULL || key->group == NULL || key->priv_key == NULL) {
+    OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
+    return 0;
   }
 
-  EC_PRIVATEKEY_free(priv_key);
+  CBB ec_private_key, private_key;
+  if (!CBB_add_asn1(cbb, &ec_private_key, CBS_ASN1_SEQUENCE) ||
+      !CBB_add_asn1_uint64(&ec_private_key, 1 /* version */) ||
+      !CBB_add_asn1(&ec_private_key, &private_key, CBS_ASN1_OCTETSTRING) ||
+      !BN_bn2cbb_padded(&private_key,
+                        BN_num_bytes(EC_GROUP_get0_order(key->group)),
+                        key->priv_key)) {
+    OPENSSL_PUT_ERROR(EC, EC_R_ENCODE_ERROR);
+    return 0;
+  }
 
+  if (!(enc_flags & EC_PKEY_NO_PARAMETERS)) {
+    CBB child;
+    if (!CBB_add_asn1(&ec_private_key, &child, kParametersTag) ||
+        !EC_KEY_marshal_curve_name(&child, key->group) ||
+        !CBB_flush(&ec_private_key)) {
+      OPENSSL_PUT_ERROR(EC, EC_R_ENCODE_ERROR);
+      return 0;
+    }
+  }
+
+  /* TODO(fork): replace this flexibility with sensible default? */
+  if (!(enc_flags & EC_PKEY_NO_PUBKEY) && key->pub_key != NULL) {
+    CBB child, public_key;
+    if (!CBB_add_asn1(&ec_private_key, &child, kPublicKeyTag) ||
+        !CBB_add_asn1(&child, &public_key, CBS_ASN1_BITSTRING) ||
+        /* As in a SubjectPublicKeyInfo, the byte-encoded public key is then
+         * encoded as a BIT STRING with bits ordered as in the DER encoding. */
+        !CBB_add_u8(&public_key, 0 /* padding */) ||
+        !EC_POINT_point2cbb(&public_key, key->group, key->pub_key,
+                            key->conv_form, NULL) ||
+        !CBB_flush(&ec_private_key)) {
+      OPENSSL_PUT_ERROR(EC, EC_R_ENCODE_ERROR);
+      return 0;
+    }
+  }
+
+  if (!CBB_flush(cbb)) {
+    OPENSSL_PUT_ERROR(EC, EC_R_ENCODE_ERROR);
+    return 0;
+  }
+
+  return 1;
+}
+
+/* is_unsigned_integer returns one if |cbs| is a valid unsigned DER INTEGER and
+ * zero otherwise. */
+static int is_unsigned_integer(const CBS *cbs) {
+  if (CBS_len(cbs) == 0) {
+    return 0;
+  }
+  uint8_t byte = CBS_data(cbs)[0];
+  if ((byte & 0x80) ||
+      (byte == 0 && CBS_len(cbs) > 1 && (CBS_data(cbs)[1] & 0x80) == 0)) {
+    /* Negative or not minimally-encoded. */
+    return 0;
+  }
+  return 1;
+}
+
+/* kPrimeFieldOID is the encoding of 1.2.840.10045.1.1. */
+static const uint8_t kPrimeField[] = {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, 0x01};
+
+static int parse_explicit_prime_curve(CBS *in, CBS *out_prime, CBS *out_a,
+                                      CBS *out_b, CBS *out_base_x,
+                                      CBS *out_base_y, CBS *out_order) {
+  /* See RFC 3279, section 2.3.5. Note that RFC 3279 calls this structure an
+   * ECParameters while RFC 5480 calls it a SpecifiedECDomain. */
+  CBS params, field_id, field_type, curve, base;
+  uint64_t version;
+  if (!CBS_get_asn1(in, &params, CBS_ASN1_SEQUENCE) ||
+      !CBS_get_asn1_uint64(&params, &version) ||
+      version != 1 ||
+      !CBS_get_asn1(&params, &field_id, CBS_ASN1_SEQUENCE) ||
+      !CBS_get_asn1(&field_id, &field_type, CBS_ASN1_OBJECT) ||
+      CBS_len(&field_type) != sizeof(kPrimeField) ||
+      OPENSSL_memcmp(CBS_data(&field_type), kPrimeField, sizeof(kPrimeField)) != 0 ||
+      !CBS_get_asn1(&field_id, out_prime, CBS_ASN1_INTEGER) ||
+      !is_unsigned_integer(out_prime) ||
+      CBS_len(&field_id) != 0 ||
+      !CBS_get_asn1(&params, &curve, CBS_ASN1_SEQUENCE) ||
+      !CBS_get_asn1(&curve, out_a, CBS_ASN1_OCTETSTRING) ||
+      !CBS_get_asn1(&curve, out_b, CBS_ASN1_OCTETSTRING) ||
+      /* |curve| has an optional BIT STRING seed which we ignore. */
+      !CBS_get_asn1(&params, &base, CBS_ASN1_OCTETSTRING) ||
+      !CBS_get_asn1(&params, out_order, CBS_ASN1_INTEGER) ||
+      !is_unsigned_integer(out_order)) {
+    OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
+    return 0;
+  }
+
+  /* |params| has an optional cofactor which we ignore. With the optional seed
+   * in |curve|, a group already has arbitrarily many encodings. Parse enough to
+   * uniquely determine the curve. */
+
+  /* Require that the base point use uncompressed form. */
+  uint8_t form;
+  if (!CBS_get_u8(&base, &form) || form != POINT_CONVERSION_UNCOMPRESSED) {
+    OPENSSL_PUT_ERROR(EC, EC_R_INVALID_FORM);
+    return 0;
+  }
+
+  if (CBS_len(&base) % 2 != 0) {
+    OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
+    return 0;
+  }
+  size_t field_len = CBS_len(&base) / 2;
+  CBS_init(out_base_x, CBS_data(&base), field_len);
+  CBS_init(out_base_y, CBS_data(&base) + field_len, field_len);
+
+  return 1;
+}
+
+/* integers_equal returns one if |a| and |b| are equal, up to leading zeros, and
+ * zero otherwise. */
+static int integers_equal(const CBS *a, const uint8_t *b, size_t b_len) {
+  /* Remove leading zeros from |a| and |b|. */
+  CBS a_copy = *a;
+  while (CBS_len(&a_copy) > 0 && CBS_data(&a_copy)[0] == 0) {
+    CBS_skip(&a_copy, 1);
+  }
+  while (b_len > 0 && b[0] == 0) {
+    b++;
+    b_len--;
+  }
+  return CBS_mem_equal(&a_copy, b, b_len);
+}
+
+EC_GROUP *EC_KEY_parse_curve_name(CBS *cbs) {
+  CBS named_curve;
+  if (!CBS_get_asn1(cbs, &named_curve, CBS_ASN1_OBJECT)) {
+    OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
+    return NULL;
+  }
+
+  /* Look for a matching curve. */
+  unsigned i;
+  for (i = 0; OPENSSL_built_in_curves[i].nid != NID_undef; i++) {
+    const struct built_in_curve *curve = &OPENSSL_built_in_curves[i];
+    if (CBS_len(&named_curve) == curve->oid_len &&
+        OPENSSL_memcmp(CBS_data(&named_curve), curve->oid, curve->oid_len) == 0) {
+      return EC_GROUP_new_by_curve_name(curve->nid);
+    }
+  }
+
+  OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
+  return NULL;
+}
+
+int EC_KEY_marshal_curve_name(CBB *cbb, const EC_GROUP *group) {
+  int nid = EC_GROUP_get_curve_name(group);
+  if (nid == NID_undef) {
+    OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
+    return 0;
+  }
+
+  unsigned i;
+  for (i = 0; OPENSSL_built_in_curves[i].nid != NID_undef; i++) {
+    const struct built_in_curve *curve = &OPENSSL_built_in_curves[i];
+    if (curve->nid == nid) {
+      CBB child;
+      return CBB_add_asn1(cbb, &child, CBS_ASN1_OBJECT) &&
+             CBB_add_bytes(&child, curve->oid, curve->oid_len) &&
+             CBB_flush(cbb);
+    }
+  }
+
+  OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
+  return 0;
+}
+
+EC_GROUP *EC_KEY_parse_parameters(CBS *cbs) {
+  if (!CBS_peek_asn1_tag(cbs, CBS_ASN1_SEQUENCE)) {
+    return EC_KEY_parse_curve_name(cbs);
+  }
+
+  /* OpenSSL sometimes produces ECPrivateKeys with explicitly-encoded versions
+   * of named curves.
+   *
+   * TODO(davidben): Remove support for this. */
+  CBS prime, a, b, base_x, base_y, order;
+  if (!parse_explicit_prime_curve(cbs, &prime, &a, &b, &base_x, &base_y,
+                                  &order)) {
+    return NULL;
+  }
+
+  /* Look for a matching prime curve. */
+  unsigned i;
+  for (i = 0; OPENSSL_built_in_curves[i].nid != NID_undef; i++) {
+    const struct built_in_curve *curve = &OPENSSL_built_in_curves[i];
+    const unsigned param_len = curve->data->param_len;
+    /* |curve->data->data| is ordered p, a, b, x, y, order, each component
+     * zero-padded up to the field length. Although SEC 1 states that the
+     * Field-Element-to-Octet-String conversion also pads, OpenSSL mis-encodes
+     * |a| and |b|, so this comparison must allow omitting leading zeros. (This
+     * is relevant for P-521 whose |b| has a leading 0.) */
+    if (integers_equal(&prime, curve->data->data, param_len) &&
+        integers_equal(&a, curve->data->data + param_len, param_len) &&
+        integers_equal(&b, curve->data->data + param_len * 2, param_len) &&
+        integers_equal(&base_x, curve->data->data + param_len * 3, param_len) &&
+        integers_equal(&base_y, curve->data->data + param_len * 4, param_len) &&
+        integers_equal(&order, curve->data->data + param_len * 5, param_len)) {
+      return EC_GROUP_new_by_curve_name(curve->nid);
+    }
+  }
+
+  OPENSSL_PUT_ERROR(EC, EC_R_UNKNOWN_GROUP);
+  return NULL;
+}
+
+EC_KEY *d2i_ECPrivateKey(EC_KEY **out, const uint8_t **inp, long len) {
+  /* This function treats its |out| parameter differently from other |d2i|
+   * functions. If supplied, take the group from |*out|. */
+  const EC_GROUP *group = NULL;
+  if (out != NULL && *out != NULL) {
+    group = EC_KEY_get0_group(*out);
+  }
+
+  if (len < 0) {
+    OPENSSL_PUT_ERROR(EC, EC_R_DECODE_ERROR);
+    return NULL;
+  }
+  CBS cbs;
+  CBS_init(&cbs, *inp, (size_t)len);
+  EC_KEY *ret = EC_KEY_parse_private_key(&cbs, group);
+  if (ret == NULL) {
+    return NULL;
+  }
+  if (out != NULL) {
+    EC_KEY_free(*out);
+    *out = ret;
+  }
+  *inp = CBS_data(&cbs);
   return ret;
 }
 
 int i2d_ECPrivateKey(const EC_KEY *key, uint8_t **outp) {
-  int ret = 0, ok = 0;
-  uint8_t *buffer = NULL;
-  size_t buf_len = 0, tmp_len;
-  EC_PRIVATEKEY *priv_key = NULL;
+  CBB cbb;
+  if (!CBB_init(&cbb, 0) ||
+      !EC_KEY_marshal_private_key(&cbb, key, EC_KEY_get_enc_flags(key))) {
+    CBB_cleanup(&cbb);
+    return -1;
+  }
+  return CBB_finish_i2d(&cbb, outp);
+}
 
-  if (key == NULL || key->group == NULL || key->priv_key == NULL) {
-    OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
-    goto err;
+EC_KEY *d2i_ECParameters(EC_KEY **out_key, const uint8_t **inp, long len) {
+  if (len < 0) {
+    return NULL;
   }
 
-  priv_key = EC_PRIVATEKEY_new();
-  if (priv_key == NULL) {
-    OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
-    goto err;
+  CBS cbs;
+  CBS_init(&cbs, *inp, (size_t)len);
+  EC_GROUP *group = EC_KEY_parse_parameters(&cbs);
+  if (group == NULL) {
+    return NULL;
   }
 
-  priv_key->version = key->version;
-
-  buf_len = BN_num_bytes(&key->group->order);
-  buffer = OPENSSL_malloc(buf_len);
-  if (buffer == NULL) {
-    OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
-    goto err;
+  EC_KEY *ret = EC_KEY_new();
+  if (ret == NULL || !EC_KEY_set_group(ret, group)) {
+    EC_GROUP_free(group);
+    EC_KEY_free(ret);
+    return NULL;
   }
+  EC_GROUP_free(group);
 
-  if (!BN_bn2bin_padded(buffer, buf_len, key->priv_key)) {
-    OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
-    goto err;
+  if (out_key != NULL) {
+    EC_KEY_free(*out_key);
+    *out_key = ret;
   }
-
-  if (!M_ASN1_OCTET_STRING_set(priv_key->privateKey, buffer, buf_len)) {
-    OPENSSL_PUT_ERROR(EC, ERR_R_ASN1_LIB);
-    goto err;
-  }
-
-  /* TODO(fork): replace this flexibility with key sensible default? */
-  if (!(key->enc_flag & EC_PKEY_NO_PARAMETERS)) {
-    if ((priv_key->parameters = ec_asn1_group2pkparameters(
-             key->group, priv_key->parameters)) == NULL) {
-      OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
-      goto err;
-    }
-  }
-
-  /* TODO(fork): replace this flexibility with key sensible default? */
-  if (!(key->enc_flag & EC_PKEY_NO_PUBKEY) && key->pub_key != NULL) {
-    priv_key->publicKey = M_ASN1_BIT_STRING_new();
-    if (priv_key->publicKey == NULL) {
-      OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
-      goto err;
-    }
-
-    tmp_len = EC_POINT_point2oct(key->group, key->pub_key, key->conv_form, NULL,
-                                 0, NULL);
-
-    if (tmp_len > buf_len) {
-      uint8_t *tmp_buffer = OPENSSL_realloc(buffer, tmp_len);
-      if (!tmp_buffer) {
-        OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
-        goto err;
-      }
-      buffer = tmp_buffer;
-      buf_len = tmp_len;
-    }
-
-    if (!EC_POINT_point2oct(key->group, key->pub_key, key->conv_form, buffer,
-                            buf_len, NULL)) {
-      OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
-      goto err;
-    }
-
-    priv_key->publicKey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
-    priv_key->publicKey->flags |= ASN1_STRING_FLAG_BITS_LEFT;
-    if (!M_ASN1_BIT_STRING_set(priv_key->publicKey, buffer, buf_len)) {
-      OPENSSL_PUT_ERROR(EC, ERR_R_ASN1_LIB);
-      goto err;
-    }
-  }
-
-  ret = i2d_EC_PRIVATEKEY(priv_key, outp);
-  if (ret == 0) {
-    OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
-    goto err;
-  }
-  ok = 1;
-
-err:
-  OPENSSL_free(buffer);
-  EC_PRIVATEKEY_free(priv_key);
-  return (ok ? ret : 0);
+  *inp = CBS_data(&cbs);
+  return ret;
 }
 
 int i2d_ECParameters(const EC_KEY *key, uint8_t **outp) {
-  if (key == NULL) {
+  if (key == NULL || key->group == NULL) {
     OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
-    return 0;
-  }
-  return i2d_ECPKParameters(key->group, outp);
-}
-
-EC_KEY *d2i_ECParameters(EC_KEY **key, const uint8_t **inp, long len) {
-  EC_KEY *ret;
-
-  if (inp == NULL || *inp == NULL) {
-    OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
-    return NULL;
+    return -1;
   }
 
-  if (key == NULL || *key == NULL) {
-    ret = EC_KEY_new();
-    if (ret == NULL) {
-      OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
-      return NULL;
-    }
-  } else {
-    ret = *key;
+  CBB cbb;
+  if (!CBB_init(&cbb, 0) ||
+      !EC_KEY_marshal_curve_name(&cbb, key->group)) {
+    CBB_cleanup(&cbb);
+    return -1;
   }
-
-  if (!d2i_ECPKParameters(&ret->group, inp, len)) {
-    OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
-    if (key == NULL || *key == NULL) {
-      EC_KEY_free(ret);
-    }
-    return NULL;
-  }
-
-  if (key) {
-    *key = ret;
-  }
-  return ret;
+  return CBB_finish_i2d(&cbb, outp);
 }
 
 EC_KEY *o2i_ECPublicKey(EC_KEY **keyp, const uint8_t **inp, long len) {
@@ -526,17 +490,17 @@
 
   if (keyp == NULL || *keyp == NULL || (*keyp)->group == NULL) {
     OPENSSL_PUT_ERROR(EC, ERR_R_PASSED_NULL_PARAMETER);
-    return 0;
+    return NULL;
   }
   ret = *keyp;
   if (ret->pub_key == NULL &&
       (ret->pub_key = EC_POINT_new(ret->group)) == NULL) {
     OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
-    return 0;
+    return NULL;
   }
   if (!EC_POINT_oct2point(ret->group, ret->pub_key, *inp, len, NULL)) {
     OPENSSL_PUT_ERROR(EC, ERR_R_EC_LIB);
-    return 0;
+    return NULL;
   }
   /* save the point conversion form */
   ret->conv_form = (point_conversion_form_t)(*inp[0] & ~0x01);
diff --git a/src/crypto/ec/ec_key.c b/src/crypto/ec/ec_key.c
index d3bf4c6..1a93346 100644
--- a/src/crypto/ec/ec_key.c
+++ b/src/crypto/ec/ec_key.c
@@ -85,13 +85,13 @@
 EC_KEY *EC_KEY_new(void) { return EC_KEY_new_method(NULL); }
 
 EC_KEY *EC_KEY_new_method(const ENGINE *engine) {
-  EC_KEY *ret = (EC_KEY *)OPENSSL_malloc(sizeof(EC_KEY));
+  EC_KEY *ret = OPENSSL_malloc(sizeof(EC_KEY));
   if (ret == NULL) {
     OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
     return NULL;
   }
 
-  memset(ret, 0, sizeof(EC_KEY));
+  OPENSSL_memset(ret, 0, sizeof(EC_KEY));
 
   if (engine) {
     ret->ecdsa_meth = ENGINE_get_ECDSA_method(engine);
@@ -100,7 +100,6 @@
     METHOD_ref(ret->ecdsa_meth);
   }
 
-  ret->version = 1;
   ret->conv_form = POINT_CONVERSION_UNCOMPRESSED;
   ret->references = 1;
 
@@ -209,8 +208,6 @@
   /* copy the rest */
   dest->enc_flag = src->enc_flag;
   dest->conv_form = src->conv_form;
-  dest->version = src->version;
-  dest->flags = src->flags;
 
   return dest;
 }
@@ -320,14 +317,6 @@
     OPENSSL_PUT_ERROR(EC, EC_R_POINT_IS_NOT_ON_CURVE);
     goto err;
   }
-  /* TODO(fork): can this be skipped if the cofactor is one or if we're about
-   * to check the private key, below? */
-  if (eckey->group->meth->check_pub_key_order != NULL &&
-      !eckey->group->meth->check_pub_key_order(eckey->group, eckey->pub_key,
-                                               ctx)) {
-    OPENSSL_PUT_ERROR(EC, EC_R_WRONG_ORDER);
-    goto err;
-  }
   /* in case the priv_key is present :
    * check if generator * priv_key == pub_key
    */
@@ -368,15 +357,24 @@
     return 0;
   }
   ctx = BN_CTX_new();
+
+  if (ctx == NULL) {
+    return 0;
+  }
+
+  BN_CTX_start(ctx);
   point = EC_POINT_new(key->group);
 
-  if (ctx == NULL ||
-      point == NULL) {
+  if (point == NULL) {
     goto err;
   }
 
   tx = BN_CTX_get(ctx);
   ty = BN_CTX_get(ctx);
+  if (tx == NULL ||
+      ty == NULL) {
+    goto err;
+  }
 
   if (!EC_POINT_set_affine_coordinates_GFp(key->group, point, x, y, ctx) ||
       !EC_POINT_get_affine_coordinates_GFp(key->group, point, tx, ty, ctx)) {
@@ -401,6 +399,7 @@
   ok = 1;
 
 err:
+  BN_CTX_end(ctx);
   BN_CTX_free(ctx);
   EC_POINT_free(point);
   return ok;
@@ -426,11 +425,9 @@
   }
 
   const BIGNUM *order = EC_GROUP_get0_order(eckey->group);
-  do {
-    if (!BN_rand_range(priv_key, order)) {
-      goto err;
-    }
-  } while (BN_is_zero(priv_key));
+  if (!BN_rand_range_ex(priv_key, 1, order)) {
+    goto err;
+  }
 
   if (eckey->pub_key == NULL) {
     pub_key = EC_POINT_new(eckey->group);
diff --git a/src/crypto/ec/ec_montgomery.c b/src/crypto/ec/ec_montgomery.c
index 1d4113d..4643fd2 100644
--- a/src/crypto/ec/ec_montgomery.c
+++ b/src/crypto/ec/ec_montgomery.c
@@ -71,6 +71,7 @@
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
+#include "../bn/internal.h"
 #include "internal.h"
 
 
@@ -79,31 +80,18 @@
 
   ok = ec_GFp_simple_group_init(group);
   group->mont = NULL;
-  group->one = NULL;
   return ok;
 }
 
 void ec_GFp_mont_group_finish(EC_GROUP *group) {
   BN_MONT_CTX_free(group->mont);
   group->mont = NULL;
-  BN_free(group->one);
-  group->one = NULL;
   ec_GFp_simple_group_finish(group);
 }
 
-void ec_GFp_mont_group_clear_finish(EC_GROUP *group) {
-  BN_MONT_CTX_free(group->mont);
-  group->mont = NULL;
-  BN_clear_free(group->one);
-  group->one = NULL;
-  ec_GFp_simple_group_clear_finish(group);
-}
-
 int ec_GFp_mont_group_copy(EC_GROUP *dest, const EC_GROUP *src) {
   BN_MONT_CTX_free(dest->mont);
   dest->mont = NULL;
-  BN_clear_free(dest->one);
-  dest->one = NULL;
 
   if (!ec_GFp_simple_group_copy(dest, src)) {
     return 0;
@@ -118,12 +106,6 @@
       goto err;
     }
   }
-  if (src->one != NULL) {
-    dest->one = BN_dup(src->one);
-    if (dest->one == NULL) {
-      goto err;
-    }
-  }
 
   return 1;
 
@@ -137,13 +119,10 @@
                                 const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) {
   BN_CTX *new_ctx = NULL;
   BN_MONT_CTX *mont = NULL;
-  BIGNUM *one = NULL;
   int ret = 0;
 
   BN_MONT_CTX_free(group->mont);
   group->mont = NULL;
-  BN_free(group->one);
-  group->one = NULL;
 
   if (ctx == NULL) {
     ctx = new_ctx = BN_CTX_new();
@@ -160,29 +139,20 @@
     OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
     goto err;
   }
-  one = BN_new();
-  if (one == NULL || !BN_to_montgomery(one, BN_value_one(), mont, ctx)) {
-    goto err;
-  }
 
   group->mont = mont;
   mont = NULL;
-  group->one = one;
-  one = NULL;
 
   ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
 
   if (!ret) {
     BN_MONT_CTX_free(group->mont);
     group->mont = NULL;
-    BN_free(group->one);
-    group->one = NULL;
   }
 
 err:
   BN_CTX_free(new_ctx);
   BN_MONT_CTX_free(mont);
-  BN_free(one);
   return ret;
 }
 
@@ -226,55 +196,108 @@
   return BN_from_montgomery(r, a, group->mont, ctx);
 }
 
-int ec_GFp_mont_field_set_to_one(const EC_GROUP *group, BIGNUM *r,
-                                 BN_CTX *ctx) {
-  if (group->one == NULL) {
-    OPENSSL_PUT_ERROR(EC, EC_R_NOT_INITIALIZED);
+static int ec_GFp_mont_point_get_affine_coordinates(const EC_GROUP *group,
+                                                    const EC_POINT *point,
+                                                    BIGNUM *x, BIGNUM *y,
+                                                    BN_CTX *ctx) {
+  if (EC_POINT_is_at_infinity(group, point)) {
+    OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY);
     return 0;
   }
 
-  if (!BN_copy(r, group->one)) {
-    return 0;
+  BN_CTX *new_ctx = NULL;
+  if (ctx == NULL) {
+    ctx = new_ctx = BN_CTX_new();
+    if (ctx == NULL) {
+      return 0;
+    }
   }
-  return 1;
-}
 
-static int ec_GFp_mont_check_pub_key_order(const EC_GROUP *group,
-                                           const EC_POINT* pub_key,
-                                           BN_CTX *ctx) {
-  EC_POINT *point = EC_POINT_new(group);
   int ret = 0;
 
-  if (point == NULL ||
-      !ec_wNAF_mul(group, point, NULL, pub_key, EC_GROUP_get0_order(group),
-                   ctx) ||
-      !EC_POINT_is_at_infinity(group, point)) {
-    goto err;
+  BN_CTX_start(ctx);
+
+  if (BN_cmp(&point->Z, &group->one) == 0) {
+    /* |point| is already affine. */
+    if (x != NULL && !BN_from_montgomery(x, &point->X, group->mont, ctx)) {
+      goto err;
+    }
+    if (y != NULL && !BN_from_montgomery(y, &point->Y, group->mont, ctx)) {
+      goto err;
+    }
+  } else {
+    /* transform  (X, Y, Z)  into  (x, y) := (X/Z^2, Y/Z^3) */
+
+    BIGNUM *Z_1 = BN_CTX_get(ctx);
+    BIGNUM *Z_2 = BN_CTX_get(ctx);
+    BIGNUM *Z_3 = BN_CTX_get(ctx);
+    if (Z_1 == NULL ||
+        Z_2 == NULL ||
+        Z_3 == NULL) {
+      goto err;
+    }
+
+    /* The straightforward way to calculate the inverse of a Montgomery-encoded
+     * value where the result is Montgomery-encoded is:
+     *
+     *    |BN_from_montgomery| + invert + |BN_to_montgomery|.
+     *
+     * This is equivalent, but more efficient, because |BN_from_montgomery|
+     * is more efficient (at least in theory) than |BN_to_montgomery|, since it
+     * doesn't have to do the multiplication before the reduction.
+     *
+     * Use Fermat's Little Theorem instead of |BN_mod_inverse_odd| since this
+     * inversion may be done as the final step of private key operations.
+     * Unfortunately, this is suboptimal for ECDSA verification. */
+    if (!BN_from_montgomery(Z_1, &point->Z, group->mont, ctx) ||
+        !BN_from_montgomery(Z_1, Z_1, group->mont, ctx) ||
+        !bn_mod_inverse_prime(Z_1, Z_1, &group->field, ctx, group->mont)) {
+      goto err;
+    }
+
+    if (!BN_mod_mul_montgomery(Z_2, Z_1, Z_1, group->mont, ctx)) {
+      goto err;
+    }
+
+    /* Instead of using |BN_from_montgomery| to convert the |x| coordinate
+     * and then calling |BN_from_montgomery| again to convert the |y|
+     * coordinate below, convert the common factor |Z_2| once now, saving one
+     * reduction. */
+    if (!BN_from_montgomery(Z_2, Z_2, group->mont, ctx)) {
+      goto err;
+    }
+
+    if (x != NULL) {
+      if (!BN_mod_mul_montgomery(x, &point->X, Z_2, group->mont, ctx)) {
+        goto err;
+      }
+    }
+
+    if (y != NULL) {
+      if (!BN_mod_mul_montgomery(Z_3, Z_2, Z_1, group->mont, ctx) ||
+          !BN_mod_mul_montgomery(y, &point->Y, Z_3, group->mont, ctx)) {
+        goto err;
+      }
+    }
   }
 
   ret = 1;
 
 err:
-  EC_POINT_free(point);
+  BN_CTX_end(ctx);
+  BN_CTX_free(new_ctx);
   return ret;
 }
 
-const EC_METHOD *EC_GFp_mont_method(void) {
-  static const EC_METHOD ret = {
+const EC_METHOD EC_GFp_mont_method = {
     ec_GFp_mont_group_init,
     ec_GFp_mont_group_finish,
-    ec_GFp_mont_group_clear_finish,
     ec_GFp_mont_group_copy,
     ec_GFp_mont_group_set_curve,
-    ec_GFp_simple_point_get_affine_coordinates,
+    ec_GFp_mont_point_get_affine_coordinates,
     ec_wNAF_mul /* XXX: Not constant time. */,
-    ec_GFp_mont_check_pub_key_order,
     ec_GFp_mont_field_mul,
     ec_GFp_mont_field_sqr,
     ec_GFp_mont_field_encode,
     ec_GFp_mont_field_decode,
-    ec_GFp_mont_field_set_to_one,
-  };
-
-  return &ret;
-}
+};
diff --git a/src/crypto/ec/ec_test.cc b/src/crypto/ec/ec_test.cc
index 2088e72..02b9ef2 100644
--- a/src/crypto/ec/ec_test.cc
+++ b/src/crypto/ec/ec_test.cc
@@ -17,12 +17,18 @@
 
 #include <vector>
 
+#include <gtest/gtest.h>
+
+#include <openssl/bn.h>
+#include <openssl/bytestring.h>
 #include <openssl/crypto.h>
 #include <openssl/ec_key.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
+#include <openssl/nid.h>
+#include <openssl/obj.h>
 
-#include "../test/scoped_types.h"
+#include "../test/test_util.h"
 
 
 // kECKeyWithoutPublic is an ECPrivateKey with the optional publicKey field
@@ -34,6 +40,36 @@
   0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07,
 };
 
+// kECKeySpecifiedCurve is the above key with P-256's parameters explicitly
+// spelled out rather than using a named curve.
+static const uint8_t kECKeySpecifiedCurve[] = {
+    0x30, 0x82, 0x01, 0x22, 0x02, 0x01, 0x01, 0x04, 0x20, 0xc6, 0xc1, 0xaa,
+    0xda, 0x15, 0xb0, 0x76, 0x61, 0xf8, 0x14, 0x2c, 0x6c, 0xaf, 0x0f, 0xdb,
+    0x24, 0x1a, 0xff, 0x2e, 0xfe, 0x46, 0xc0, 0x93, 0x8b, 0x74, 0xf2, 0xbc,
+    0xc5, 0x30, 0x52, 0xb0, 0x77, 0xa0, 0x81, 0xfa, 0x30, 0x81, 0xf7, 0x02,
+    0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01,
+    0x01, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0x30, 0x5b, 0x04, 0x20, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
+    0x04, 0x20, 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb,
+    0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53,
+    0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b, 0x03, 0x15,
+    0x00, 0xc4, 0x9d, 0x36, 0x08, 0x86, 0xe7, 0x04, 0x93, 0x6a, 0x66, 0x78,
+    0xe1, 0x13, 0x9d, 0x26, 0xb7, 0x81, 0x9f, 0x7e, 0x90, 0x04, 0x41, 0x04,
+    0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5,
+    0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0,
+    0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2,
+    0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16,
+    0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68,
+    0x37, 0xbf, 0x51, 0xf5, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
+    0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc,
+    0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc,
+    0x63, 0x25, 0x51, 0x02, 0x01, 0x01,
+};
+
 // kECKeyMissingZeros is an ECPrivateKey containing a degenerate P-256 key where
 // the private key is one. The private key is incorrectly encoded without zero
 // padding.
@@ -65,10 +101,12 @@
 
 // DecodeECPrivateKey decodes |in| as an ECPrivateKey structure and returns the
 // result or nullptr on error.
-static ScopedEC_KEY DecodeECPrivateKey(const uint8_t *in, size_t in_len) {
-  const uint8_t *inp = in;
-  ScopedEC_KEY ret(d2i_ECPrivateKey(NULL, &inp, in_len));
-  if (!ret || inp != in + in_len) {
+static bssl::UniquePtr<EC_KEY> DecodeECPrivateKey(const uint8_t *in,
+                                                  size_t in_len) {
+  CBS cbs;
+  CBS_init(&cbs, in, in_len);
+  bssl::UniquePtr<EC_KEY> ret(EC_KEY_parse_private_key(&cbs, NULL));
+  if (!ret || CBS_len(&cbs) != 0) {
     return nullptr;
   }
   return ret;
@@ -76,184 +114,277 @@
 
 // EncodeECPrivateKey encodes |key| as an ECPrivateKey structure into |*out|. It
 // returns true on success or false on error.
-static bool EncodeECPrivateKey(std::vector<uint8_t> *out, EC_KEY *key) {
-  int len = i2d_ECPrivateKey(key, NULL);
-  out->resize(len);
-  uint8_t *outp = out->data();
-  return i2d_ECPrivateKey(key, &outp) == len;
-}
-
-bool Testd2i_ECPrivateKey() {
-  ScopedEC_KEY key = DecodeECPrivateKey(kECKeyWithoutPublic,
-                                        sizeof(kECKeyWithoutPublic));
-  if (!key) {
-    fprintf(stderr, "Failed to parse private key.\n");
-    ERR_print_errors_fp(stderr);
+static bool EncodeECPrivateKey(std::vector<uint8_t> *out, const EC_KEY *key) {
+  bssl::ScopedCBB cbb;
+  uint8_t *der;
+  size_t der_len;
+  if (!CBB_init(cbb.get(), 0) ||
+      !EC_KEY_marshal_private_key(cbb.get(), key, EC_KEY_get_enc_flags(key)) ||
+      !CBB_finish(cbb.get(), &der, &der_len)) {
     return false;
   }
-
-  std::vector<uint8_t> out;
-  if (!EncodeECPrivateKey(&out, key.get())) {
-    fprintf(stderr, "Failed to serialize private key.\n");
-    ERR_print_errors_fp(stderr);
-    return false;
-  }
-
-  if (std::vector<uint8_t>(kECKeyWithoutPublic,
-                           kECKeyWithoutPublic + sizeof(kECKeyWithoutPublic)) !=
-      out) {
-    fprintf(stderr, "Serialisation of key doesn't match original.\n");
-    return false;
-  }
-
-  const EC_POINT *pub_key = EC_KEY_get0_public_key(key.get());
-  if (pub_key == NULL) {
-    fprintf(stderr, "Public key missing.\n");
-    return false;
-  }
-
-  ScopedBIGNUM x(BN_new());
-  ScopedBIGNUM y(BN_new());
-  if (!x || !y) {
-    return false;
-  }
-  if (!EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(key.get()),
-                                           pub_key, x.get(), y.get(), NULL)) {
-    fprintf(stderr, "Failed to get public key in affine coordinates.\n");
-    return false;
-  }
-  ScopedOpenSSLString x_hex(BN_bn2hex(x.get()));
-  ScopedOpenSSLString y_hex(BN_bn2hex(y.get()));
-  if (!x_hex || !y_hex) {
-    return false;
-  }
-  if (0 != strcmp(
-          x_hex.get(),
-          "c81561ecf2e54edefe6617db1c7a34a70744ddb261f269b83dacfcd2ade5a681") ||
-      0 != strcmp(
-          y_hex.get(),
-          "e0e2afa3f9b6abe4c698ef6495f1be49a3196c5056acb3763fe4507eec596e88")) {
-    fprintf(stderr, "Incorrect public key: %s %s\n", x_hex.get(), y_hex.get());
-    return false;
-  }
-
+  out->assign(der, der + der_len);
+  OPENSSL_free(der);
   return true;
 }
 
-static bool TestZeroPadding() {
-  // Check that the correct encoding round-trips.
-  ScopedEC_KEY key = DecodeECPrivateKey(kECKeyWithZeros,
-                                        sizeof(kECKeyWithZeros));
-  std::vector<uint8_t> out;
-  if (!key || !EncodeECPrivateKey(&out, key.get())) {
-    ERR_print_errors_fp(stderr);
-    return false;
-  }
+TEST(ECTest, Encoding) {
+  bssl::UniquePtr<EC_KEY> key =
+      DecodeECPrivateKey(kECKeyWithoutPublic, sizeof(kECKeyWithoutPublic));
+  ASSERT_TRUE(key);
 
-  if (std::vector<uint8_t>(kECKeyWithZeros,
-                           kECKeyWithZeros + sizeof(kECKeyWithZeros)) != out) {
-    fprintf(stderr, "Serialisation of key was incorrect.\n");
-    return false;
-  }
+  // Test that the encoding round-trips.
+  std::vector<uint8_t> out;
+  ASSERT_TRUE(EncodeECPrivateKey(&out, key.get()));
+  EXPECT_EQ(Bytes(kECKeyWithoutPublic), Bytes(out.data(), out.size()));
+
+  const EC_POINT *pub_key = EC_KEY_get0_public_key(key.get());
+  ASSERT_TRUE(pub_key) << "Public key missing";
+
+  bssl::UniquePtr<BIGNUM> x(BN_new());
+  bssl::UniquePtr<BIGNUM> y(BN_new());
+  ASSERT_TRUE(x);
+  ASSERT_TRUE(y);
+  ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp(
+      EC_KEY_get0_group(key.get()), pub_key, x.get(), y.get(), NULL));
+  bssl::UniquePtr<char> x_hex(BN_bn2hex(x.get()));
+  bssl::UniquePtr<char> y_hex(BN_bn2hex(y.get()));
+  ASSERT_TRUE(x_hex);
+  ASSERT_TRUE(y_hex);
+
+  EXPECT_STREQ(
+      "c81561ecf2e54edefe6617db1c7a34a70744ddb261f269b83dacfcd2ade5a681",
+      x_hex.get());
+  EXPECT_STREQ(
+      "e0e2afa3f9b6abe4c698ef6495f1be49a3196c5056acb3763fe4507eec596e88",
+      y_hex.get());
+}
+
+TEST(ECTest, ZeroPadding) {
+  // Check that the correct encoding round-trips.
+  bssl::UniquePtr<EC_KEY> key =
+      DecodeECPrivateKey(kECKeyWithZeros, sizeof(kECKeyWithZeros));
+  ASSERT_TRUE(key);
+  std::vector<uint8_t> out;
+  EXPECT_TRUE(EncodeECPrivateKey(&out, key.get()));
+  EXPECT_EQ(Bytes(kECKeyWithZeros), Bytes(out.data(), out.size()));
 
   // Keys without leading zeros also parse, but they encode correctly.
   key = DecodeECPrivateKey(kECKeyMissingZeros, sizeof(kECKeyMissingZeros));
-  if (!key || !EncodeECPrivateKey(&out, key.get())) {
-    ERR_print_errors_fp(stderr);
-    return false;
-  }
-
-  if (std::vector<uint8_t>(kECKeyWithZeros,
-                           kECKeyWithZeros + sizeof(kECKeyWithZeros)) != out) {
-    fprintf(stderr, "Serialisation of key was incorrect.\n");
-    return false;
-  }
-
-  return true;
+  ASSERT_TRUE(key);
+  EXPECT_TRUE(EncodeECPrivateKey(&out, key.get()));
+  EXPECT_EQ(Bytes(kECKeyWithZeros), Bytes(out.data(), out.size()));
 }
 
-bool TestSetAffine(const int nid) {
-  ScopedEC_KEY key(EC_KEY_new_by_curve_name(nid));
-  if (!key) {
-    return false;
-  }
+TEST(ECTest, SpecifiedCurve) {
+  // Test keys with specified curves may be decoded.
+  bssl::UniquePtr<EC_KEY> key =
+      DecodeECPrivateKey(kECKeySpecifiedCurve, sizeof(kECKeySpecifiedCurve));
+  ASSERT_TRUE(key);
+
+  // The group should have been interpreted as P-256.
+  EXPECT_EQ(NID_X9_62_prime256v1,
+            EC_GROUP_get_curve_name(EC_KEY_get0_group(key.get())));
+
+  // Encoding the key should still use named form.
+  std::vector<uint8_t> out;
+  EXPECT_TRUE(EncodeECPrivateKey(&out, key.get()));
+  EXPECT_EQ(Bytes(kECKeyWithoutPublic), Bytes(out.data(), out.size()));
+}
+
+TEST(ECTest, ArbitraryCurve) {
+  // Make a P-256 key and extract the affine coordinates.
+  bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
+  ASSERT_TRUE(key);
+  ASSERT_TRUE(EC_KEY_generate_key(key.get()));
+
+  // Make an arbitrary curve which is identical to P-256.
+  static const uint8_t kP[] = {
+      0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
+      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  };
+  static const uint8_t kA[] = {
+      0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
+      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
+  };
+  static const uint8_t kB[] = {
+      0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd,
+      0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53,
+      0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b,
+  };
+  static const uint8_t kX[] = {
+      0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6,
+      0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb,
+      0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96,
+  };
+  static const uint8_t kY[] = {
+      0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb,
+      0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31,
+      0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5,
+  };
+  static const uint8_t kOrder[] = {
+      0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+      0xff, 0xff, 0xff, 0xff, 0xff, 0xbc, 0xe6, 0xfa, 0xad, 0xa7, 0x17,
+      0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc, 0x63, 0x25, 0x51,
+  };
+  bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
+  ASSERT_TRUE(ctx);
+  bssl::UniquePtr<BIGNUM> p(BN_bin2bn(kP, sizeof(kP), nullptr));
+  ASSERT_TRUE(p);
+  bssl::UniquePtr<BIGNUM> a(BN_bin2bn(kA, sizeof(kA), nullptr));
+  ASSERT_TRUE(a);
+  bssl::UniquePtr<BIGNUM> b(BN_bin2bn(kB, sizeof(kB), nullptr));
+  ASSERT_TRUE(b);
+  bssl::UniquePtr<BIGNUM> gx(BN_bin2bn(kX, sizeof(kX), nullptr));
+  ASSERT_TRUE(gx);
+  bssl::UniquePtr<BIGNUM> gy(BN_bin2bn(kY, sizeof(kY), nullptr));
+  ASSERT_TRUE(gy);
+  bssl::UniquePtr<BIGNUM> order(BN_bin2bn(kOrder, sizeof(kOrder), nullptr));
+  ASSERT_TRUE(order);
+
+  bssl::UniquePtr<EC_GROUP> group(
+      EC_GROUP_new_curve_GFp(p.get(), a.get(), b.get(), ctx.get()));
+  ASSERT_TRUE(group);
+  bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group.get()));
+  ASSERT_TRUE(generator);
+  ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(
+      group.get(), generator.get(), gx.get(), gy.get(), ctx.get()));
+  ASSERT_TRUE(EC_GROUP_set_generator(group.get(), generator.get(), order.get(),
+                                     BN_value_one()));
+
+  // |group| should not have a curve name.
+  EXPECT_EQ(NID_undef, EC_GROUP_get_curve_name(group.get()));
+
+  // Copy |key| to |key2| using |group|.
+  bssl::UniquePtr<EC_KEY> key2(EC_KEY_new());
+  ASSERT_TRUE(key2);
+  bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group.get()));
+  ASSERT_TRUE(point);
+  bssl::UniquePtr<BIGNUM> x(BN_new()), y(BN_new());
+  ASSERT_TRUE(x);
+  ASSERT_TRUE(EC_KEY_set_group(key2.get(), group.get()));
+  ASSERT_TRUE(
+      EC_KEY_set_private_key(key2.get(), EC_KEY_get0_private_key(key.get())));
+  ASSERT_TRUE(EC_POINT_get_affine_coordinates_GFp(
+      EC_KEY_get0_group(key.get()), EC_KEY_get0_public_key(key.get()), x.get(),
+      y.get(), nullptr));
+  ASSERT_TRUE(EC_POINT_set_affine_coordinates_GFp(group.get(), point.get(),
+                                                  x.get(), y.get(), nullptr));
+  ASSERT_TRUE(EC_KEY_set_public_key(key2.get(), point.get()));
+
+  // The key must be valid according to the new group too.
+  EXPECT_TRUE(EC_KEY_check_key(key2.get()));
+}
+
+class ECCurveTest : public testing::TestWithParam<EC_builtin_curve> {};
+
+TEST_P(ECCurveTest, SetAffine) {
+  // Generate an EC_KEY.
+  bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
+  ASSERT_TRUE(key);
+  ASSERT_TRUE(EC_KEY_generate_key(key.get()));
+
+  const EC_GROUP *const group = EC_KEY_get0_group(key.get());
+  EXPECT_TRUE(
+      EC_POINT_is_on_curve(group, EC_KEY_get0_public_key(key.get()), nullptr));
+
+  // Get the public key's coordinates.
+  bssl::UniquePtr<BIGNUM> x(BN_new());
+  ASSERT_TRUE(x);
+  bssl::UniquePtr<BIGNUM> y(BN_new());
+  ASSERT_TRUE(y);
+  EXPECT_TRUE(EC_POINT_get_affine_coordinates_GFp(
+      group, EC_KEY_get0_public_key(key.get()), x.get(), y.get(), nullptr));
+
+  // Points on the curve should be accepted.
+  auto point = bssl::UniquePtr<EC_POINT>(EC_POINT_new(group));
+  ASSERT_TRUE(point);
+  EXPECT_TRUE(EC_POINT_set_affine_coordinates_GFp(group, point.get(), x.get(),
+                                                  y.get(), nullptr));
+
+  // Subtract one from |y| to make the point no longer on the curve.
+  EXPECT_TRUE(BN_sub(y.get(), y.get(), BN_value_one()));
+
+  // Points not on the curve should be rejected.
+  bssl::UniquePtr<EC_POINT> invalid_point(EC_POINT_new(group));
+  ASSERT_TRUE(invalid_point);
+  EXPECT_FALSE(EC_POINT_set_affine_coordinates_GFp(group, invalid_point.get(),
+                                                   x.get(), y.get(), nullptr));
+}
+
+TEST_P(ECCurveTest, AddingEqualPoints) {
+  bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(GetParam().nid));
+  ASSERT_TRUE(key);
+  ASSERT_TRUE(EC_KEY_generate_key(key.get()));
 
   const EC_GROUP *const group = EC_KEY_get0_group(key.get());
 
-  if (!EC_KEY_generate_key(key.get())) {
-    fprintf(stderr, "EC_KEY_generate_key failed with nid %d\n", nid);
-    ERR_print_errors_fp(stderr);
-    return false;
-  }
+  bssl::UniquePtr<EC_POINT> p1(EC_POINT_new(group));
+  ASSERT_TRUE(p1);
+  ASSERT_TRUE(EC_POINT_copy(p1.get(), EC_KEY_get0_public_key(key.get())));
 
-  if (!EC_POINT_is_on_curve(group, EC_KEY_get0_public_key(key.get()),
-                            nullptr)) {
-    fprintf(stderr, "generated point is not on curve with nid %d", nid);
-    ERR_print_errors_fp(stderr);
-    return false;
-  }
+  bssl::UniquePtr<EC_POINT> p2(EC_POINT_new(group));
+  ASSERT_TRUE(p2);
+  ASSERT_TRUE(EC_POINT_copy(p2.get(), EC_KEY_get0_public_key(key.get())));
 
-  ScopedBIGNUM x(BN_new());
-  ScopedBIGNUM y(BN_new());
-  if (!EC_POINT_get_affine_coordinates_GFp(group,
-                                           EC_KEY_get0_public_key(key.get()),
-                                           x.get(), y.get(), nullptr)) {
-    fprintf(stderr, "EC_POINT_get_affine_coordinates_GFp failed with nid %d\n",
-            nid);
-    ERR_print_errors_fp(stderr);
-    return false;
-  }
+  bssl::UniquePtr<EC_POINT> double_p1(EC_POINT_new(group));
+  ASSERT_TRUE(double_p1);
+  bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
+  ASSERT_TRUE(ctx);
+  ASSERT_TRUE(EC_POINT_dbl(group, double_p1.get(), p1.get(), ctx.get()));
 
-  ScopedEC_POINT point(EC_POINT_new(group));
-  if (!point) {
-    return false;
-  }
+  bssl::UniquePtr<EC_POINT> p1_plus_p2(EC_POINT_new(group));
+  ASSERT_TRUE(p1_plus_p2);
+  ASSERT_TRUE(
+      EC_POINT_add(group, p1_plus_p2.get(), p1.get(), p2.get(), ctx.get()));
 
-  if (!EC_POINT_set_affine_coordinates_GFp(group, point.get(), x.get(), y.get(),
-                                           nullptr)) {
-    fprintf(stderr, "EC_POINT_set_affine_coordinates_GFp failed with nid %d\n",
-            nid);
-    ERR_print_errors_fp(stderr);
-    return false;
-  }
-
-  // Subtract one from |y| to make the point no longer on the curve.
-  if (!BN_sub(y.get(), y.get(), BN_value_one())) {
-    return false;
-  }
-
-  ScopedEC_POINT invalid_point(EC_POINT_new(group));
-  if (!invalid_point) {
-    return false;
-  }
-
-  if (EC_POINT_set_affine_coordinates_GFp(group, invalid_point.get(), x.get(),
-                                          y.get(), nullptr)) {
-    fprintf(stderr,
-            "EC_POINT_set_affine_coordinates_GFp succeeded with invalid "
-            "coordinates with nid %d\n",
-            nid);
-    ERR_print_errors_fp(stderr);
-    return false;
-  }
-
-  return true;
+  EXPECT_EQ(0,
+            EC_POINT_cmp(group, double_p1.get(), p1_plus_p2.get(), ctx.get()))
+      << "A+A != 2A";
 }
 
-int main(void) {
-  CRYPTO_library_init();
-  ERR_load_crypto_strings();
+TEST_P(ECCurveTest, MulZero) {
+  bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(GetParam().nid));
+  ASSERT_TRUE(group);
 
-  if (!Testd2i_ECPrivateKey() ||
-      !TestZeroPadding() ||
-      !TestSetAffine(NID_secp224r1) ||
-      !TestSetAffine(NID_X9_62_prime256v1) ||
-      !TestSetAffine(NID_secp384r1) ||
-      !TestSetAffine(NID_secp521r1)) {
-    fprintf(stderr, "failed\n");
-    return 1;
-  }
+  bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group.get()));
+  ASSERT_TRUE(point);
+  bssl::UniquePtr<BIGNUM> zero(BN_new());
+  ASSERT_TRUE(zero);
+  BN_zero(zero.get());
+  ASSERT_TRUE(EC_POINT_mul(group.get(), point.get(), zero.get(), nullptr,
+                           nullptr, nullptr));
 
-  printf("PASS\n");
-  return 0;
+  EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), point.get()))
+      << "g * 0 did not return point at infinity.";
+
+  // Test that zero times an arbitrary point is also infinity. The generator is
+  // used as the arbitrary point.
+  bssl::UniquePtr<EC_POINT> generator(EC_POINT_new(group.get()));
+  ASSERT_TRUE(generator);
+  ASSERT_TRUE(EC_POINT_mul(group.get(), generator.get(), BN_value_one(),
+                           nullptr, nullptr, nullptr));
+  ASSERT_TRUE(EC_POINT_mul(group.get(), point.get(), nullptr, generator.get(),
+                           zero.get(), nullptr));
+
+  EXPECT_TRUE(EC_POINT_is_at_infinity(group.get(), point.get()))
+      << "p * 0 did not return point at infinity.";
 }
+
+static std::vector<EC_builtin_curve> AllCurves() {
+  const size_t num_curves = EC_get_builtin_curves(nullptr, 0);
+  std::vector<EC_builtin_curve> curves(num_curves);
+  EC_get_builtin_curves(curves.data(), num_curves);
+  return curves;
+}
+
+static std::string CurveToString(
+    const testing::TestParamInfo<EC_builtin_curve> &params) {
+  // The comment field contains characters GTest rejects, so use the OBJ name.
+  return OBJ_nid2sn(params.param.nid);
+}
+
+INSTANTIATE_TEST_CASE_P(, ECCurveTest, testing::ValuesIn(AllCurves()),
+                        CurveToString);
diff --git a/src/crypto/ec/example_mul.c b/src/crypto/ec/example_mul.c
index ebb724f..a2bdd52 100644
--- a/src/crypto/ec/example_mul.c
+++ b/src/crypto/ec/example_mul.c
@@ -70,10 +70,10 @@
 #include <openssl/bn.h>
 #include <openssl/crypto.h>
 #include <openssl/ec.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
 
 
-int example_EC_POINT_mul(void) {
+static int example_EC_POINT_mul(void) {
   /* This example ensures that 10×∞ + G = G, in P-256. */
   EC_GROUP *group = NULL;
   EC_POINT *p = NULL, *result = NULL;
diff --git a/src/crypto/ec/internal.h b/src/crypto/ec/internal.h
index bcc0e37..b3c2a71 100644
--- a/src/crypto/ec/internal.h
+++ b/src/crypto/ec/internal.h
@@ -80,18 +80,11 @@
 
 
 struct ec_method_st {
-  /* used by EC_GROUP_new, EC_GROUP_free, EC_GROUP_clear_free, EC_GROUP_copy: */
   int (*group_init)(EC_GROUP *);
   void (*group_finish)(EC_GROUP *);
-  void (*group_clear_finish)(EC_GROUP *);
   int (*group_copy)(EC_GROUP *, const EC_GROUP *);
-
-  /* used by EC_GROUP_set_curve_GFp, EC_GROUP_get_curve_GFp, */
-  /* EC_GROUP_set_curve_GF2m, and EC_GROUP_get_curve_GF2m: */
   int (*group_set_curve)(EC_GROUP *, const BIGNUM *p, const BIGNUM *a,
                          const BIGNUM *b, BN_CTX *);
-
-  /* used by EC_POINT_get_affine_coordinates_GFp: */
   int (*point_get_affine_coordinates)(const EC_GROUP *, const EC_POINT *,
                                       BIGNUM *x, BIGNUM *y, BN_CTX *);
 
@@ -103,17 +96,6 @@
   int (*mul)(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
              const EC_POINT *p, const BIGNUM *p_scalar, BN_CTX *ctx);
 
-  /* |check_pub_key_order| checks that the public key is in the proper subgroup
-   * by checking that |pub_key*group->order| is the point at infinity. This may
-   * be NULL for |EC_METHOD|s specialized for prime-order curves (i.e. with
-   * cofactor one), as this check is not necessary for such curves (See section
-   * A.3 of the NSA's "Suite B Implementer's Guide to FIPS 186-3
-   * (ECDSA)"). */
-  int (*check_pub_key_order)(const EC_GROUP *group, const EC_POINT *pub_key,
-                             BN_CTX *ctx);
-
-  /* internal functions */
-
   /* 'field_mul' and 'field_sqr' can be used by 'add' and 'dbl' so that the
    * same implementations of point operations can be used with different
    * optimized implementations of expensive field operations: */
@@ -125,16 +107,15 @@
                       BN_CTX *); /* e.g. to Montgomery */
   int (*field_decode)(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
                       BN_CTX *); /* e.g. from Montgomery */
-  int (*field_set_to_one)(const EC_GROUP *, BIGNUM *r, BN_CTX *);
 } /* EC_METHOD */;
 
-const EC_METHOD* EC_GFp_mont_method(void);
+extern const EC_METHOD EC_GFp_mont_method;
 
 struct ec_group_st {
   const EC_METHOD *meth;
 
-  EC_POINT *generator; /* optional */
-  BIGNUM order, cofactor;
+  EC_POINT *generator;
+  BIGNUM order;
 
   int curve_name; /* optional NID for named curve */
 
@@ -150,20 +131,17 @@
   int a_is_minus3; /* enable optimized point arithmetics for special case */
 
   BN_MONT_CTX *mont; /* Montgomery structure. */
-  BIGNUM *one; /* The value one */
+
+  BIGNUM one; /* The value one. */
 } /* EC_GROUP */;
 
 struct ec_point_st {
   const EC_METHOD *meth;
 
-  /* All members except 'meth' are handled by the method functions,
-   * even if they appear generic */
-
   BIGNUM X;
   BIGNUM Y;
   BIGNUM Z; /* Jacobian projective coordinates:
              * (X, Y, Z)  represents  (X/Z^2, Y/Z^3)  if  Z != 0 */
-  int Z_is_one; /* enable optimized point arithmetics for special case */
 } /* EC_POINT */;
 
 EC_GROUP *ec_group_new(const EC_METHOD *meth);
@@ -180,14 +158,12 @@
 /* method functions in simple.c */
 int ec_GFp_simple_group_init(EC_GROUP *);
 void ec_GFp_simple_group_finish(EC_GROUP *);
-void ec_GFp_simple_group_clear_finish(EC_GROUP *);
 int ec_GFp_simple_group_copy(EC_GROUP *, const EC_GROUP *);
 int ec_GFp_simple_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a,
                                   const BIGNUM *b, BN_CTX *);
 int ec_GFp_simple_group_get_curve(const EC_GROUP *, BIGNUM *p, BIGNUM *a,
                                   BIGNUM *b, BN_CTX *);
 unsigned ec_GFp_simple_group_get_degree(const EC_GROUP *);
-int ec_GFp_simple_group_check_discriminant(const EC_GROUP *, BN_CTX *);
 int ec_GFp_simple_point_init(EC_POINT *);
 void ec_GFp_simple_point_finish(EC_POINT *);
 void ec_GFp_simple_point_clear_finish(EC_POINT *);
@@ -204,9 +180,6 @@
 int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *, EC_POINT *,
                                                const BIGNUM *x, const BIGNUM *y,
                                                BN_CTX *);
-int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *,
-                                               const EC_POINT *, BIGNUM *x,
-                                               BIGNUM *y, BN_CTX *);
 int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *, EC_POINT *,
                                              const BIGNUM *x, int y_bit,
                                              BN_CTX *);
@@ -232,7 +205,6 @@
 int ec_GFp_mont_group_set_curve(EC_GROUP *, const BIGNUM *p, const BIGNUM *a,
                                 const BIGNUM *b, BN_CTX *);
 void ec_GFp_mont_group_finish(EC_GROUP *);
-void ec_GFp_mont_group_clear_finish(EC_GROUP *);
 int ec_GFp_mont_group_copy(EC_GROUP *, const EC_GROUP *);
 int ec_GFp_mont_field_mul(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
                           const BIGNUM *b, BN_CTX *);
@@ -242,34 +214,22 @@
                              BN_CTX *);
 int ec_GFp_mont_field_decode(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
                              BN_CTX *);
-int ec_GFp_mont_field_set_to_one(const EC_GROUP *, BIGNUM *r, BN_CTX *);
 
 int ec_point_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
                                              EC_POINT *point, const BIGNUM *x,
                                              const BIGNUM *y, const BIGNUM *z,
                                              BN_CTX *ctx);
 
-void ec_GFp_nistp_points_make_affine_internal(
-    size_t num, void *point_array, size_t felem_size, void *tmp_felems,
-    void (*felem_one)(void *out), int (*felem_is_zero)(const void *in),
-    void (*felem_assign)(void *out, const void *in),
-    void (*felem_square)(void *out, const void *in),
-    void (*felem_mul)(void *out, const void *in1, const void *in2),
-    void (*felem_inv)(void *out, const void *in),
-    void (*felem_contract)(void *out, const void *in));
-
 void ec_GFp_nistp_recode_scalar_bits(uint8_t *sign, uint8_t *digit, uint8_t in);
 
-const EC_METHOD *EC_GFp_nistp224_method(void);
-const EC_METHOD *EC_GFp_nistp256_method(void);
+extern const EC_METHOD EC_GFp_nistp224_method;
+extern const EC_METHOD EC_GFp_nistp256_method;
 
-/* Returns GFp methods using montgomery multiplication, with x86-64
- * optimized P256. See http://eprint.iacr.org/2013/816. */
-const EC_METHOD *EC_GFp_nistz256_method(void);
+/* EC_GFp_nistz256_method is a GFp method using montgomery multiplication, with
+ * x86-64 optimized P256. See http://eprint.iacr.org/2013/816. */
+extern const EC_METHOD EC_GFp_nistz256_method;
 
 struct ec_key_st {
-  int version;
-
   EC_GROUP *group;
 
   EC_POINT *pub_key;
@@ -279,7 +239,6 @@
   point_conversion_form_t conv_form;
 
   CRYPTO_refcount_t references;
-  int flags;
 
   ECDSA_METHOD *ecdsa_meth;
 
@@ -292,9 +251,6 @@
   const char *comment;
   /* param_len is the number of bytes needed to store a field element. */
   uint8_t param_len;
-  /* cofactor is the cofactor of the group (i.e. the number of elements in the
-   * group divided by the size of the main subgroup. */
-  uint8_t cofactor; /* promoted to BN_ULONG */
   /* data points to an array of 6*|param_len| bytes which hold the field
    * elements of the following (in big-endian order): prime, a, b, generator x,
    * generator y, order. */
@@ -303,8 +259,10 @@
 
 struct built_in_curve {
   int nid;
+  uint8_t oid[8];
+  uint8_t oid_len;
   const struct curve_data *data;
-  const EC_METHOD *(*method)(void);
+  const EC_METHOD *method;
 };
 
 /* OPENSSL_built_in_curves is terminated with an entry where |nid| is
diff --git a/src/crypto/ec/oct.c b/src/crypto/ec/oct.c
index e39337d..4e8272d 100644
--- a/src/crypto/ec/oct.c
+++ b/src/crypto/ec/oct.c
@@ -68,6 +68,7 @@
 #include <openssl/ec.h>
 
 #include <openssl/bn.h>
+#include <openssl/bytestring.h>
 #include <openssl/err.h>
 
 #include "internal.h"
@@ -268,11 +269,27 @@
   return ec_GFp_simple_point2oct(group, point, form, buf, len, ctx);
 }
 
+int EC_POINT_point2cbb(CBB *out, const EC_GROUP *group, const EC_POINT *point,
+                       point_conversion_form_t form, BN_CTX *ctx) {
+  size_t len = EC_POINT_point2oct(group, point, form, NULL, 0, ctx);
+  if (len == 0) {
+    return 0;
+  }
+  uint8_t *p;
+  return CBB_add_space(out, &p, len) &&
+         EC_POINT_point2oct(group, point, form, p, len, ctx) == len;
+}
+
 int ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group,
-                                             EC_POINT *point, const BIGNUM *x_,
+                                             EC_POINT *point, const BIGNUM *x,
                                              int y_bit, BN_CTX *ctx) {
+  if (BN_is_negative(x) || BN_cmp(x, &group->field) >= 0) {
+    OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COMPRESSED_POINT);
+    return 0;
+  }
+
   BN_CTX *new_ctx = NULL;
-  BIGNUM *tmp1, *tmp2, *x, *y;
+  BIGNUM *tmp1, *tmp2, *y;
   int ret = 0;
 
   ERR_clear_error();
@@ -289,7 +306,6 @@
   BN_CTX_start(ctx);
   tmp1 = BN_CTX_get(ctx);
   tmp2 = BN_CTX_get(ctx);
-  x = BN_CTX_get(ctx);
   y = BN_CTX_get(ctx);
   if (y == NULL) {
     goto err;
@@ -300,19 +316,15 @@
    * so  y  is one of the square roots of  x^3 + a*x + b. */
 
   /* tmp1 := x^3 */
-  if (!BN_nnmod(x, x_, &group->field, ctx)) {
-    goto err;
-  }
-
   if (group->meth->field_decode == 0) {
     /* field_{sqr,mul} work on standard representation */
-    if (!group->meth->field_sqr(group, tmp2, x_, ctx) ||
-        !group->meth->field_mul(group, tmp1, tmp2, x_, ctx)) {
+    if (!group->meth->field_sqr(group, tmp2, x, ctx) ||
+        !group->meth->field_mul(group, tmp1, tmp2, x, ctx)) {
       goto err;
     }
   } else {
-    if (!BN_mod_sqr(tmp2, x_, &group->field, ctx) ||
-        !BN_mod_mul(tmp1, tmp2, x_, &group->field, ctx)) {
+    if (!BN_mod_sqr(tmp2, x, &group->field, ctx) ||
+        !BN_mod_mul(tmp1, tmp2, x, &group->field, ctx)) {
       goto err;
     }
   }
@@ -369,19 +381,7 @@
 
   if (y_bit != BN_is_odd(y)) {
     if (BN_is_zero(y)) {
-      int kron;
-
-      kron = BN_kronecker(x, &group->field, ctx);
-      if (kron == -2) {
-        goto err;
-      }
-
-      if (kron == 1) {
-        OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COMPRESSION_BIT);
-      } else {
-        /* BN_mod_sqrt() should have cought this error (not a square) */
-        OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COMPRESSED_POINT);
-      }
+      OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COMPRESSION_BIT);
       goto err;
     }
     if (!BN_usub(y, &group->field, y)) {
diff --git a/src/crypto/ec/p224-64.c b/src/crypto/ec/p224-64.c
index e026fc4..7b2ae68 100644
--- a/src/crypto/ec/p224-64.c
+++ b/src/crypto/ec/p224-64.c
@@ -26,11 +26,11 @@
 #include <openssl/ec.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
-#include <openssl/obj.h>
 
 #include <string.h>
 
 #include "internal.h"
+#include "../internal.h"
 
 
 typedef uint8_t u8;
@@ -50,7 +50,7 @@
  * to the unique minimal representation at the end of the computation. */
 
 typedef uint64_t limb;
-typedef __uint128_t widelimb;
+typedef uint128_t widelimb;
 
 typedef limb felem[4];
 typedef widelimb widefelem[7];
@@ -60,23 +60,6 @@
  * scalars for point multiplication. */
 typedef u8 felem_bytearray[28];
 
-static const felem_bytearray nistp224_curve_params[5] = {
-    {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* p */
-     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-     0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
-    {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, /* a */
-     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE},
-    {0xB4, 0x05, 0x0A, 0x85, 0x0C, 0x04, 0xB3, 0xAB, 0xF5, 0x41, /* b */
-     0x32, 0x56, 0x50, 0x44, 0xB0, 0xB7, 0xD7, 0xBF, 0xD8, 0xBA, 0x27, 0x0B,
-     0x39, 0x43, 0x23, 0x55, 0xFF, 0xB4},
-    {0xB7, 0x0E, 0x0C, 0xBD, 0x6B, 0xB4, 0xBF, 0x7F, 0x32, 0x13, /* x */
-     0x90, 0xB9, 0x4A, 0x03, 0xC1, 0xD3, 0x56, 0xC2, 0x11, 0x22, 0x34, 0x32,
-     0x80, 0xD6, 0x11, 0x5C, 0x1D, 0x21},
-    {0xbd, 0x37, 0x63, 0x88, 0xb5, 0xf7, 0x23, 0xfb, 0x4c, 0x22, /* y */
-     0xdf, 0xe6, 0xcd, 0x43, 0x75, 0xa0, 0x5a, 0x07, 0x47, 0x64, 0x44, 0xd5,
-     0x81, 0x99, 0x85, 0x00, 0x7e, 0x34}};
-
 /* Precomputed multiples of the standard generator
  * Points are given in coordinates (X, Y, Z) where Z normally is 1
  * (0 for the point at infinity).
@@ -209,8 +192,7 @@
 }
 
 static void felem_to_bin28(u8 out[28], const felem in) {
-  unsigned i;
-  for (i = 0; i < 7; ++i) {
+  for (size_t i = 0; i < 7; ++i) {
     out[i] = in[0] >> (8 * i);
     out[i + 7] = in[1] >> (8 * i);
     out[i + 14] = in[2] >> (8 * i);
@@ -219,9 +201,8 @@
 }
 
 /* To preserve endianness when using BN_bn2bin and BN_bin2bn */
-static void flip_endian(u8 *out, const u8 *in, unsigned len) {
-  unsigned i;
-  for (i = 0; i < len; ++i) {
+static void flip_endian(u8 *out, const u8 *in, size_t len) {
+  for (size_t i = 0; i < len; ++i) {
     out[i] = in[len - 1 - i];
   }
 }
@@ -230,8 +211,8 @@
 static int BN_to_felem(felem out, const BIGNUM *bn) {
   /* BN_bn2bin eats leading zeroes */
   felem_bytearray b_out;
-  memset(b_out, 0, sizeof(b_out));
-  unsigned num_bytes = BN_num_bytes(bn);
+  OPENSSL_memset(b_out, 0, sizeof(b_out));
+  size_t num_bytes = BN_num_bytes(bn);
   if (num_bytes > sizeof(b_out) ||
       BN_is_negative(bn)) {
     OPENSSL_PUT_ERROR(EC, EC_R_BIGNUM_OUT_OF_RANGE);
@@ -258,13 +239,6 @@
  * expected to be correct in general - e.g., multiplication with a large scalar
  * will cause an overflow. */
 
-static void felem_one(felem out) {
-  out[0] = 1;
-  out[1] = 0;
-  out[2] = 0;
-  out[3] = 0;
-}
-
 static void felem_assign(felem out, const felem in) {
   out[0] = in[0];
   out[1] = in[1];
@@ -476,18 +450,6 @@
   out[3] = output[3];
 }
 
-static void felem_square_reduce(felem out, const felem in) {
-  widefelem tmp;
-  felem_square(tmp, in);
-  felem_reduce(out, tmp);
-}
-
-static void felem_mul_reduce(felem out, const felem in1, const felem in2) {
-  widefelem tmp;
-  felem_mul(tmp, in1, in2);
-  felem_reduce(out, tmp);
-}
-
 /* Reduce to unique minimal representation.
  * Requires 0 <= in < 2*p (always call felem_reduce first) */
 static void felem_contract(felem out, const felem in) {
@@ -555,16 +517,11 @@
   return (zero | two224m96p1 | two225m97p2);
 }
 
-static limb felem_is_zero_int(const felem in) {
-  return (int)(felem_is_zero(in) & ((limb)1));
-}
-
 /* Invert a field element */
 /* Computation chain copied from djb's code */
 static void felem_inv(felem out, const felem in) {
   felem ftmp, ftmp2, ftmp3, ftmp4;
   widefelem tmp;
-  unsigned i;
 
   felem_square(tmp, in);
   felem_reduce(ftmp, tmp); /* 2 */
@@ -584,7 +541,7 @@
   felem_reduce(ftmp, tmp); /* 2^6 - 1 */
   felem_square(tmp, ftmp);
   felem_reduce(ftmp2, tmp); /* 2^7 - 2 */
-  for (i = 0; i < 5; ++i) { /* 2^12 - 2^6 */
+  for (size_t i = 0; i < 5; ++i) { /* 2^12 - 2^6 */
     felem_square(tmp, ftmp2);
     felem_reduce(ftmp2, tmp);
   }
@@ -592,7 +549,7 @@
   felem_reduce(ftmp2, tmp); /* 2^12 - 1 */
   felem_square(tmp, ftmp2);
   felem_reduce(ftmp3, tmp); /* 2^13 - 2 */
-  for (i = 0; i < 11; ++i) {/* 2^24 - 2^12 */
+  for (size_t i = 0; i < 11; ++i) {/* 2^24 - 2^12 */
     felem_square(tmp, ftmp3);
     felem_reduce(ftmp3, tmp);
   }
@@ -600,7 +557,7 @@
   felem_reduce(ftmp2, tmp); /* 2^24 - 1 */
   felem_square(tmp, ftmp2);
   felem_reduce(ftmp3, tmp); /* 2^25 - 2 */
-  for (i = 0; i < 23; ++i) {/* 2^48 - 2^24 */
+  for (size_t i = 0; i < 23; ++i) {/* 2^48 - 2^24 */
     felem_square(tmp, ftmp3);
     felem_reduce(ftmp3, tmp);
   }
@@ -608,7 +565,7 @@
   felem_reduce(ftmp3, tmp); /* 2^48 - 1 */
   felem_square(tmp, ftmp3);
   felem_reduce(ftmp4, tmp); /* 2^49 - 2 */
-  for (i = 0; i < 47; ++i) {/* 2^96 - 2^48 */
+  for (size_t i = 0; i < 47; ++i) {/* 2^96 - 2^48 */
     felem_square(tmp, ftmp4);
     felem_reduce(ftmp4, tmp);
   }
@@ -616,13 +573,13 @@
   felem_reduce(ftmp3, tmp); /* 2^96 - 1 */
   felem_square(tmp, ftmp3);
   felem_reduce(ftmp4, tmp); /* 2^97 - 2 */
-  for (i = 0; i < 23; ++i) {/* 2^120 - 2^24 */
+  for (size_t i = 0; i < 23; ++i) {/* 2^120 - 2^24 */
     felem_square(tmp, ftmp4);
     felem_reduce(ftmp4, tmp);
   }
   felem_mul(tmp, ftmp2, ftmp4);
   felem_reduce(ftmp2, tmp); /* 2^120 - 1 */
-  for (i = 0; i < 6; ++i) { /* 2^126 - 2^6 */
+  for (size_t i = 0; i < 6; ++i) { /* 2^126 - 2^6 */
     felem_square(tmp, ftmp2);
     felem_reduce(ftmp2, tmp);
   }
@@ -632,7 +589,7 @@
   felem_reduce(ftmp, tmp); /* 2^127 - 2 */
   felem_mul(tmp, ftmp, in);
   felem_reduce(ftmp, tmp); /* 2^127 - 1 */
-  for (i = 0; i < 97; ++i) {/* 2^224 - 2^97 */
+  for (size_t i = 0; i < 97; ++i) {/* 2^224 - 2^97 */
     felem_square(tmp, ftmp);
     felem_reduce(ftmp, tmp);
   }
@@ -644,10 +601,9 @@
  * if icopy == 1, copy in to out,
  * if icopy == 0, copy out to itself. */
 static void copy_conditional(felem out, const felem in, limb icopy) {
-  unsigned i;
   /* icopy is a (64-bit) 0 or 1, so copy is either all-zero or all-one */
   const limb copy = -icopy;
-  for (i = 0; i < 4; ++i) {
+  for (size_t i = 0; i < 4; ++i) {
     const limb tmp = copy & (in[i] ^ out[i]);
     out[i] ^= tmp;
   }
@@ -901,13 +857,12 @@
 
 /* select_point selects the |idx|th point from a precomputation table and
  * copies it to out. */
-static void select_point(const u64 idx, unsigned int size,
+static void select_point(const u64 idx, size_t size,
                          const felem pre_comp[/*size*/][3], felem out[3]) {
-  unsigned i, j;
   limb *outlimbs = &out[0][0];
-  memset(outlimbs, 0, 3 * sizeof(felem));
+  OPENSSL_memset(outlimbs, 0, 3 * sizeof(felem));
 
-  for (i = 0; i < size; i++) {
+  for (size_t i = 0; i < size; i++) {
     const limb *inlimbs = &pre_comp[i][0][0];
     u64 mask = i ^ idx;
     mask |= mask >> 4;
@@ -915,14 +870,14 @@
     mask |= mask >> 1;
     mask &= 1;
     mask--;
-    for (j = 0; j < 4 * 3; j++) {
+    for (size_t j = 0; j < 4 * 3; j++) {
       outlimbs[j] |= inlimbs[j] & mask;
     }
   }
 }
 
 /* get_bit returns the |i|th bit in |in| */
-static char get_bit(const felem_bytearray in, unsigned i) {
+static char get_bit(const felem_bytearray in, size_t i) {
   if (i >= 224) {
     return 0;
   }
@@ -930,36 +885,32 @@
 }
 
 /* Interleaved point multiplication using precomputed point multiples:
- * The small point multiples 0*P, 1*P, ..., 16*P are in pre_comp[],
- * the scalars in scalars[]. If g_scalar is non-NULL, we also add this multiple
+ * The small point multiples 0*P, 1*P, ..., 16*P are in p_pre_comp, the scalars
+ * in p_scalar, if non-NULL. If g_scalar is non-NULL, we also add this multiple
  * of the generator, using certain (large) precomputed multiples in g_pre_comp.
  * Output point (X, Y, Z) is stored in x_out, y_out, z_out */
-static void batch_mul(felem x_out, felem y_out, felem z_out,
-                      const felem_bytearray scalars[],
-                      const unsigned num_points, const u8 *g_scalar,
-                      const int mixed, const felem pre_comp[][17][3]) {
-  int i, skip;
-  unsigned num;
-  unsigned gen_mul = (g_scalar != NULL);
+static void batch_mul(felem x_out, felem y_out, felem z_out, const u8 *p_scalar,
+                      const u8 *g_scalar, const felem p_pre_comp[17][3]) {
   felem nq[3], tmp[4];
   u64 bits;
   u8 sign, digit;
 
   /* set nq to the point at infinity */
-  memset(nq, 0, 3 * sizeof(felem));
+  OPENSSL_memset(nq, 0, 3 * sizeof(felem));
 
-  /* Loop over all scalars msb-to-lsb, interleaving additions
-   * of multiples of the generator (two in each of the last 28 rounds)
-   * and additions of other points multiples (every 5th round). */
-  skip = 1; /* save two point operations in the first round */
-  for (i = (num_points ? 220 : 27); i >= 0; --i) {
+  /* Loop over both scalars msb-to-lsb, interleaving additions of multiples of
+   * the generator (two in each of the last 28 rounds) and additions of p (every
+   * 5th round). */
+  int skip = 1; /* save two point operations in the first round */
+  size_t i = p_scalar != NULL ? 220 : 27;
+  for (;;) {
     /* double */
     if (!skip) {
       point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]);
     }
 
     /* add multiples of the generator */
-    if (gen_mul && (i <= 27)) {
+    if (g_scalar != NULL && i <= 27) {
       /* first, look 28 bits upwards */
       bits = get_bit(g_scalar, i + 196) << 3;
       bits |= get_bit(g_scalar, i + 140) << 2;
@@ -972,7 +923,7 @@
         point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1 /* mixed */,
                   tmp[0], tmp[1], tmp[2]);
       } else {
-        memcpy(nq, tmp, 3 * sizeof(felem));
+        OPENSSL_memcpy(nq, tmp, 3 * sizeof(felem));
         skip = 0;
       }
 
@@ -988,87 +939,45 @@
     }
 
     /* do other additions every 5 doublings */
-    if (num_points && (i % 5 == 0)) {
-      /* loop over all scalars */
-      for (num = 0; num < num_points; ++num) {
-        bits = get_bit(scalars[num], i + 4) << 5;
-        bits |= get_bit(scalars[num], i + 3) << 4;
-        bits |= get_bit(scalars[num], i + 2) << 3;
-        bits |= get_bit(scalars[num], i + 1) << 2;
-        bits |= get_bit(scalars[num], i) << 1;
-        bits |= get_bit(scalars[num], i - 1);
-        ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits);
+    if (p_scalar != NULL && i % 5 == 0) {
+      bits = get_bit(p_scalar, i + 4) << 5;
+      bits |= get_bit(p_scalar, i + 3) << 4;
+      bits |= get_bit(p_scalar, i + 2) << 3;
+      bits |= get_bit(p_scalar, i + 1) << 2;
+      bits |= get_bit(p_scalar, i) << 1;
+      bits |= get_bit(p_scalar, i - 1);
+      ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits);
 
-        /* select the point to add or subtract */
-        select_point(digit, 17, pre_comp[num], tmp);
-        felem_neg(tmp[3], tmp[1]); /* (X, -Y, Z) is the negative point */
-        copy_conditional(tmp[1], tmp[3], sign);
+      /* select the point to add or subtract */
+      select_point(digit, 17, p_pre_comp, tmp);
+      felem_neg(tmp[3], tmp[1]); /* (X, -Y, Z) is the negative point */
+      copy_conditional(tmp[1], tmp[3], sign);
 
-        if (!skip) {
-          point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], mixed, tmp[0],
-                    tmp[1], tmp[2]);
-        } else {
-          memcpy(nq, tmp, 3 * sizeof(felem));
-          skip = 0;
-        }
+      if (!skip) {
+        point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 0 /* mixed */,
+                  tmp[0], tmp[1], tmp[2]);
+      } else {
+        OPENSSL_memcpy(nq, tmp, 3 * sizeof(felem));
+        skip = 0;
       }
     }
+
+    if (i == 0) {
+      break;
+    }
+    --i;
   }
   felem_assign(x_out, nq[0]);
   felem_assign(y_out, nq[1]);
   felem_assign(z_out, nq[2]);
 }
 
-int ec_GFp_nistp224_group_init(EC_GROUP *group) {
-  int ret;
-  ret = ec_GFp_simple_group_init(group);
-  group->a_is_minus3 = 1;
-  return ret;
-}
-
-int ec_GFp_nistp224_group_set_curve(EC_GROUP *group, const BIGNUM *p,
-                                    const BIGNUM *a, const BIGNUM *b,
-                                    BN_CTX *ctx) {
-  int ret = 0;
-  BN_CTX *new_ctx = NULL;
-  BIGNUM *curve_p, *curve_a, *curve_b;
-
-  if (ctx == NULL) {
-    ctx = BN_CTX_new();
-    new_ctx = ctx;
-    if (ctx == NULL) {
-      return 0;
-    }
-  }
-  BN_CTX_start(ctx);
-  if (((curve_p = BN_CTX_get(ctx)) == NULL) ||
-      ((curve_a = BN_CTX_get(ctx)) == NULL) ||
-      ((curve_b = BN_CTX_get(ctx)) == NULL)) {
-    goto err;
-  }
-  BN_bin2bn(nistp224_curve_params[0], sizeof(felem_bytearray), curve_p);
-  BN_bin2bn(nistp224_curve_params[1], sizeof(felem_bytearray), curve_a);
-  BN_bin2bn(nistp224_curve_params[2], sizeof(felem_bytearray), curve_b);
-  if (BN_cmp(curve_p, p) ||
-      BN_cmp(curve_a, a) ||
-      BN_cmp(curve_b, b)) {
-    OPENSSL_PUT_ERROR(EC, EC_R_WRONG_CURVE_PARAMETERS);
-    goto err;
-  }
-  ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
-
-err:
-  BN_CTX_end(ctx);
-  BN_CTX_free(new_ctx);
-  return ret;
-}
-
 /* Takes the Jacobian coordinates (X, Y, Z) of a point and returns
  * (X', Y') = (X/Z^2, Y/Z^3) */
-int ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group,
-                                                 const EC_POINT *point,
-                                                 BIGNUM *x, BIGNUM *y,
-                                                 BN_CTX *ctx) {
+static int ec_GFp_nistp224_point_get_affine_coordinates(const EC_GROUP *group,
+                                                        const EC_POINT *point,
+                                                        BIGNUM *x, BIGNUM *y,
+                                                        BN_CTX *ctx) {
   felem z1, z2, x_in, y_in, x_out, y_out;
   widefelem tmp;
 
@@ -1107,46 +1016,16 @@
   return 1;
 }
 
-static void make_points_affine(size_t num, felem points[/*num*/][3],
-                               felem tmp_felems[/*num+1*/]) {
-  /* Runs in constant time, unless an input is the point at infinity
-   * (which normally shouldn't happen). */
-  ec_GFp_nistp_points_make_affine_internal(
-      num, points, sizeof(felem), tmp_felems, (void (*)(void *))felem_one,
-      (int (*)(const void *))felem_is_zero_int,
-      (void (*)(void *, const void *))felem_assign,
-      (void (*)(void *, const void *))felem_square_reduce,
-      (void (*)(void *, const void *, const void *))felem_mul_reduce,
-      (void (*)(void *, const void *))felem_inv,
-      (void (*)(void *, const void *))felem_contract);
-}
-
-int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
-                               const BIGNUM *g_scalar, const EC_POINT *p_,
-                               const BIGNUM *p_scalar_, BN_CTX *ctx) {
-  /* TODO: This function used to take |points| and |scalars| as arrays of
-   * |num| elements. The code below should be simplified to work in terms of
-   * |p_| and |p_scalar_|. */
-  size_t num = p_ != NULL ? 1 : 0;
-  const EC_POINT **points = p_ != NULL ? &p_ : NULL;
-  BIGNUM const *const *scalars = p_ != NULL ? &p_scalar_ : NULL;
-
+static int ec_GFp_nistp224_points_mul(const EC_GROUP *group, EC_POINT *r,
+                                      const BIGNUM *g_scalar, const EC_POINT *p,
+                                      const BIGNUM *p_scalar, BN_CTX *ctx) {
   int ret = 0;
-  int j;
-  unsigned i;
-  int mixed = 0;
   BN_CTX *new_ctx = NULL;
   BIGNUM *x, *y, *z, *tmp_scalar;
-  felem_bytearray g_secret;
-  felem_bytearray *secrets = NULL;
-  felem(*pre_comp)[17][3] = NULL;
-  felem *tmp_felems = NULL;
+  felem_bytearray g_secret, p_secret;
+  felem p_pre_comp[17][3];
   felem_bytearray tmp;
-  unsigned num_bytes;
-  size_t num_points = num;
   felem x_in, y_in, z_in, x_out, y_out, z_out;
-  const EC_POINT *p = NULL;
-  const BIGNUM *p_scalar = NULL;
 
   if (ctx == NULL) {
     ctx = BN_CTX_new();
@@ -1164,87 +1043,54 @@
     goto err;
   }
 
-  if (num_points > 0) {
-    if (num_points >= 3) {
-      /* unless we precompute multiples for just one or two points,
-       * converting those into affine form is time well spent  */
-      mixed = 1;
+  if (p != NULL && p_scalar != NULL) {
+    /* We treat NULL scalars as 0, and NULL points as points at infinity, i.e.,
+     * they contribute nothing to the linear combination. */
+    OPENSSL_memset(&p_secret, 0, sizeof(p_secret));
+    OPENSSL_memset(&p_pre_comp, 0, sizeof(p_pre_comp));
+    size_t num_bytes;
+    /* reduce g_scalar to 0 <= g_scalar < 2^224 */
+    if (BN_num_bits(p_scalar) > 224 || BN_is_negative(p_scalar)) {
+      /* this is an unusual input, and we don't guarantee
+       * constant-timeness */
+      if (!BN_nnmod(tmp_scalar, p_scalar, &group->order, ctx)) {
+        OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
+        goto err;
+      }
+      num_bytes = BN_bn2bin(tmp_scalar, tmp);
+    } else {
+      num_bytes = BN_bn2bin(p_scalar, tmp);
     }
-    secrets = OPENSSL_malloc(num_points * sizeof(felem_bytearray));
-    pre_comp = OPENSSL_malloc(num_points * sizeof(felem[17][3]));
-    if (mixed) {
-      tmp_felems = OPENSSL_malloc((num_points * 17 + 1) * sizeof(felem));
-    }
-    if (secrets == NULL ||
-        pre_comp == NULL ||
-        (mixed && tmp_felems == NULL)) {
-      OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
+
+    flip_endian(p_secret, tmp, num_bytes);
+    /* precompute multiples */
+    if (!BN_to_felem(x_out, &p->X) ||
+        !BN_to_felem(y_out, &p->Y) ||
+        !BN_to_felem(z_out, &p->Z)) {
       goto err;
     }
 
-    /* we treat NULL scalars as 0, and NULL points as points at infinity,
-     * i.e., they contribute nothing to the linear combination */
-    memset(secrets, 0, num_points * sizeof(felem_bytearray));
-    memset(pre_comp, 0, num_points * 17 * 3 * sizeof(felem));
-    for (i = 0; i < num_points; ++i) {
-      if (i == num) {
-        /* the generator */
-        p = EC_GROUP_get0_generator(group);
-        p_scalar = g_scalar;
+    felem_assign(p_pre_comp[1][0], x_out);
+    felem_assign(p_pre_comp[1][1], y_out);
+    felem_assign(p_pre_comp[1][2], z_out);
+
+    for (size_t j = 2; j <= 16; ++j) {
+      if (j & 1) {
+        point_add(p_pre_comp[j][0], p_pre_comp[j][1], p_pre_comp[j][2],
+                  p_pre_comp[1][0], p_pre_comp[1][1], p_pre_comp[1][2],
+                  0, p_pre_comp[j - 1][0], p_pre_comp[j - 1][1],
+                  p_pre_comp[j - 1][2]);
       } else {
-        /* the i^th point */
-        p = points[i];
-        p_scalar = scalars[i];
+        point_double(p_pre_comp[j][0], p_pre_comp[j][1],
+                     p_pre_comp[j][2], p_pre_comp[j / 2][0],
+                     p_pre_comp[j / 2][1], p_pre_comp[j / 2][2]);
       }
-
-      if (p_scalar != NULL && p != NULL) {
-        /* reduce g_scalar to 0 <= g_scalar < 2^224 */
-        if (BN_num_bits(p_scalar) > 224 || BN_is_negative(p_scalar)) {
-          /* this is an unusual input, and we don't guarantee
-           * constant-timeness */
-          if (!BN_nnmod(tmp_scalar, p_scalar, &group->order, ctx)) {
-            OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
-            goto err;
-          }
-          num_bytes = BN_bn2bin(tmp_scalar, tmp);
-        } else {
-          num_bytes = BN_bn2bin(p_scalar, tmp);
-        }
-
-        flip_endian(secrets[i], tmp, num_bytes);
-        /* precompute multiples */
-        if (!BN_to_felem(x_out, &p->X) ||
-            !BN_to_felem(y_out, &p->Y) ||
-            !BN_to_felem(z_out, &p->Z)) {
-          goto err;
-        }
-
-        felem_assign(pre_comp[i][1][0], x_out);
-        felem_assign(pre_comp[i][1][1], y_out);
-        felem_assign(pre_comp[i][1][2], z_out);
-
-        for (j = 2; j <= 16; ++j) {
-          if (j & 1) {
-            point_add(pre_comp[i][j][0], pre_comp[i][j][1], pre_comp[i][j][2],
-                      pre_comp[i][1][0], pre_comp[i][1][1], pre_comp[i][1][2],
-                      0, pre_comp[i][j - 1][0], pre_comp[i][j - 1][1],
-                      pre_comp[i][j - 1][2]);
-          } else {
-            point_double(pre_comp[i][j][0], pre_comp[i][j][1],
-                         pre_comp[i][j][2], pre_comp[i][j / 2][0],
-                         pre_comp[i][j / 2][1], pre_comp[i][j / 2][2]);
-          }
-        }
-      }
-    }
-
-    if (mixed) {
-      make_points_affine(num_points * 17, pre_comp[0], tmp_felems);
     }
   }
 
   if (g_scalar != NULL) {
-    memset(g_secret, 0, sizeof(g_secret));
+    OPENSSL_memset(g_secret, 0, sizeof(g_secret));
+    size_t num_bytes;
     /* reduce g_scalar to 0 <= g_scalar < 2^224 */
     if (BN_num_bits(g_scalar) > 224 || BN_is_negative(g_scalar)) {
       /* this is an unusual input, and we don't guarantee constant-timeness */
@@ -1259,9 +1105,9 @@
 
     flip_endian(g_secret, tmp, num_bytes);
   }
-  batch_mul(x_out, y_out, z_out, (const felem_bytearray(*))secrets,
-            num_points, g_scalar != NULL ? g_secret : NULL, mixed,
-            (const felem(*)[17][3])pre_comp);
+  batch_mul(x_out, y_out, z_out,
+            (p != NULL && p_scalar != NULL) ? p_secret : NULL,
+            g_scalar != NULL ? g_secret : NULL, (const felem(*)[3])p_pre_comp);
 
   /* reduce the output to its unique minimal representation */
   felem_contract(x_in, x_out);
@@ -1278,28 +1124,20 @@
 err:
   BN_CTX_end(ctx);
   BN_CTX_free(new_ctx);
-  OPENSSL_free(secrets);
-  OPENSSL_free(pre_comp);
-  OPENSSL_free(tmp_felems);
   return ret;
 }
 
-const EC_METHOD *EC_GFp_nistp224_method(void) {
-  static const EC_METHOD ret = {ec_GFp_nistp224_group_init,
-                                ec_GFp_simple_group_finish,
-                                ec_GFp_simple_group_clear_finish,
-                                ec_GFp_simple_group_copy,
-                                ec_GFp_nistp224_group_set_curve,
-                                ec_GFp_nistp224_point_get_affine_coordinates,
-                                ec_GFp_nistp224_points_mul,
-                                0 /* check_pub_key_order */,
-                                ec_GFp_simple_field_mul,
-                                ec_GFp_simple_field_sqr,
-                                0 /* field_encode */,
-                                0 /* field_decode */,
-                                0 /* field_set_to_one */};
-
-  return &ret;
-}
+const EC_METHOD EC_GFp_nistp224_method = {
+    ec_GFp_simple_group_init,
+    ec_GFp_simple_group_finish,
+    ec_GFp_simple_group_copy,
+    ec_GFp_simple_group_set_curve,
+    ec_GFp_nistp224_point_get_affine_coordinates,
+    ec_GFp_nistp224_points_mul,
+    ec_GFp_simple_field_mul,
+    ec_GFp_simple_field_sqr,
+    NULL /* field_encode */,
+    NULL /* field_decode */,
+};
 
 #endif  /* 64_BIT && !WINDOWS && !SMALL */
diff --git a/src/crypto/ec/p256-64.c b/src/crypto/ec/p256-64.c
index 32852dd..0f32c2e 100644
--- a/src/crypto/ec/p256-64.c
+++ b/src/crypto/ec/p256-64.c
@@ -27,44 +27,22 @@
 #include <openssl/ec.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
-#include <openssl/obj.h>
 
 #include <string.h>
 
 #include "internal.h"
+#include "../internal.h"
 
 
 typedef uint8_t u8;
 typedef uint64_t u64;
 typedef int64_t s64;
-typedef __uint128_t uint128_t;
-typedef __int128_t int128_t;
 
 /* The underlying field. P256 operates over GF(2^256-2^224+2^192+2^96-1). We
  * can serialise an element of this field into 32 bytes. We call this an
  * felem_bytearray. */
 typedef u8 felem_bytearray[32];
 
-/* These are the parameters of P256, taken from FIPS 186-3, page 86. These
- * values are big-endian. */
-static const felem_bytearray nistp256_curve_params[5] = {
-    {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, /* p */
-     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
-    {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, /* a = -3 */
-     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-     0xfc}, /* b */
-    {0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb, 0xbd, 0x55,
-     0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53, 0xb0, 0xf6,
-     0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b},
-    {0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, /* x */
-     0xf8, 0xbc, 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81,
-     0x2d, 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96},
-    {0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, /* y */
-     0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57,
-     0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5}};
-
 /* The representation of field elements.
  * ------------------------------------
  *
@@ -99,10 +77,10 @@
 /* bin32_to_felem takes a little-endian byte array and converts it into felem
  * form. This assumes that the CPU is little-endian. */
 static void bin32_to_felem(felem out, const u8 in[32]) {
-  out[0] = *((u64 *)&in[0]);
-  out[1] = *((u64 *)&in[8]);
-  out[2] = *((u64 *)&in[16]);
-  out[3] = *((u64 *)&in[24]);
+  out[0] = *((const u64 *)&in[0]);
+  out[1] = *((const u64 *)&in[8]);
+  out[2] = *((const u64 *)&in[16]);
+  out[3] = *((const u64 *)&in[24]);
 }
 
 /* smallfelem_to_bin32 takes a smallfelem and serialises into a little endian,
@@ -115,9 +93,8 @@
 }
 
 /* To preserve endianness when using BN_bn2bin and BN_bin2bn. */
-static void flip_endian(u8 *out, const u8 *in, unsigned len) {
-  unsigned i;
-  for (i = 0; i < len; ++i) {
+static void flip_endian(u8 *out, const u8 *in, size_t len) {
+  for (size_t i = 0; i < len; ++i) {
     out[i] = in[len - 1 - i];
   }
 }
@@ -131,8 +108,8 @@
 
   felem_bytearray b_out;
   /* BN_bn2bin eats leading zeroes */
-  memset(b_out, 0, sizeof(b_out));
-  unsigned num_bytes = BN_num_bytes(bn);
+  OPENSSL_memset(b_out, 0, sizeof(b_out));
+  size_t num_bytes = BN_num_bytes(bn);
   if (num_bytes > sizeof(b_out)) {
     OPENSSL_PUT_ERROR(EC, EC_R_BIGNUM_OUT_OF_RANGE);
     return 0;
@@ -155,20 +132,6 @@
 
 /* Field operations. */
 
-static void smallfelem_one(smallfelem out) {
-  out[0] = 1;
-  out[1] = 0;
-  out[2] = 0;
-  out[3] = 0;
-}
-
-static void smallfelem_assign(smallfelem out, const smallfelem in) {
-  out[0] = in[0];
-  out[1] = in[1];
-  out[2] = in[2];
-  out[3] = in[3];
-}
-
 static void felem_assign(felem out, const felem in) {
   out[0] = in[0];
   out[1] = in[1];
@@ -212,9 +175,9 @@
   out[7] *= scalar;
 }
 
-#define two105m41m9 (((limb)1) << 105) - (((limb)1) << 41) - (((limb)1) << 9)
+#define two105m41m9 ((((limb)1) << 105) - (((limb)1) << 41) - (((limb)1) << 9))
 #define two105 (((limb)1) << 105)
-#define two105m41p9 (((limb)1) << 105) - (((limb)1) << 41) + (((limb)1) << 9)
+#define two105m41p9 ((((limb)1) << 105) - (((limb)1) << 41) + (((limb)1) << 9))
 
 /* zero105 is 0 mod p */
 static const felem zero105 = {two105m41m9, two105, two105m41p9, two105m41p9};
@@ -248,9 +211,11 @@
   out[3] -= in[3];
 }
 
-#define two107m43m11 (((limb)1) << 107) - (((limb)1) << 43) - (((limb)1) << 11)
+#define two107m43m11 \
+  ((((limb)1) << 107) - (((limb)1) << 43) - (((limb)1) << 11))
 #define two107 (((limb)1) << 107)
-#define two107m43p11 (((limb)1) << 107) - (((limb)1) << 43) + (((limb)1) << 11)
+#define two107m43p11 \
+  ((((limb)1) << 107) - (((limb)1) << 43) + (((limb)1) << 11))
 
 /* zero107 is 0 mod p */
 static const felem zero107 = {two107m43m11, two107, two107m43p11, two107m43p11};
@@ -309,10 +274,10 @@
   out[7] -= in[7];
 }
 
-#define two64m0 (((limb)1) << 64) - 1
-#define two110p32m0 (((limb)1) << 110) + (((limb)1) << 32) - 1
-#define two64m46 (((limb)1) << 64) - (((limb)1) << 46)
-#define two64m32 (((limb)1) << 64) - (((limb)1) << 32)
+#define two64m0 ((((limb)1) << 64) - 1)
+#define two110p32m0 ((((limb)1) << 110) + (((limb)1) << 32) - 1)
+#define two64m46 ((((limb)1) << 64) - (((limb)1) << 46))
+#define two64m32 ((((limb)1) << 64) - (((limb)1) << 32))
 
 /* zero110 is 0 mod p. */
 static const felem zero110 = {two64m0, two110p32m0, two64m46, two64m32};
@@ -364,8 +329,7 @@
    * conditionally subtract kPrime if tmp[3] is large enough. */
   high = tmp[3] >> 64;
   /* As tmp[3] < 2^65, high is either 1 or 0 */
-  high <<= 63;
-  high >>= 63;
+  high = ~(high - 1);
   /* high is:
    *   all ones   if the high word of tmp[3] is 1
    *   all zeros  if the high word of tmp[3] if 0 */
@@ -632,9 +596,9 @@
   smallfelem_mul(out, small1, small2);
 }
 
-#define two100m36m4 (((limb)1) << 100) - (((limb)1) << 36) - (((limb)1) << 4)
+#define two100m36m4 ((((limb)1) << 100) - (((limb)1) << 36) - (((limb)1) << 4))
 #define two100 (((limb)1) << 100)
-#define two100m36p4 (((limb)1) << 100) - (((limb)1) << 36) + (((limb)1) << 4)
+#define two100m36p4 ((((limb)1) << 100) - (((limb)1) << 36) + (((limb)1) << 4))
 
 /* zero100 is 0 mod p */
 static const felem zero100 = {two100m36m4, two100, two100m36p4, two100m36p4};
@@ -756,8 +720,7 @@
    * each u64, from most-significant to least significant. For each one, if
    * all words so far have been equal (m is all ones) then a non-equal
    * result is the answer. Otherwise we continue. */
-  unsigned i;
-  for (i = 3; i < 4; i--) {
+  for (size_t i = 3; i < 4; i--) {
     u64 equal;
     uint128_t a = ((uint128_t)kPrime[i]) - out[i];
     /* if out[i] > kPrime[i] then a will underflow and the high 64-bits
@@ -800,25 +763,6 @@
   subtract_u64(&out[3], &carry, result & kPrime[3]);
 }
 
-static void smallfelem_square_contract(smallfelem out, const smallfelem in) {
-  longfelem longtmp;
-  felem tmp;
-
-  smallfelem_square(longtmp, in);
-  felem_reduce(tmp, longtmp);
-  felem_contract(out, tmp);
-}
-
-static void smallfelem_mul_contract(smallfelem out, const smallfelem in1,
-                                    const smallfelem in2) {
-  longfelem longtmp;
-  felem tmp;
-
-  smallfelem_mul(longtmp, in1, in2);
-  felem_reduce(tmp, longtmp);
-  felem_contract(out, tmp);
-}
-
 /* felem_is_zero returns a limb with all bits set if |in| == 0 (mod p) and 0
  * otherwise.
  * On entry:
@@ -855,10 +799,6 @@
   return result;
 }
 
-static int smallfelem_is_zero_int(const smallfelem small) {
-  return (int)(smallfelem_is_zero(small) & ((limb)1));
-}
-
 /* felem_inv calculates |out| = |in|^{-1}
  *
  * Based on Fermat's Little Theorem:
@@ -870,7 +810,6 @@
   /* each e_I will hold |in|^{2^I - 1} */
   felem e2, e4, e8, e16, e32, e64;
   longfelem tmp;
-  unsigned i;
 
   felem_square(tmp, in);
   felem_reduce(ftmp, tmp); /* 2^1 */
@@ -895,47 +834,47 @@
   felem_mul(tmp, ftmp, e4);
   felem_reduce(ftmp, tmp); /* 2^8 - 2^0 */
   felem_assign(e8, ftmp);
-  for (i = 0; i < 8; i++) {
+  for (size_t i = 0; i < 8; i++) {
     felem_square(tmp, ftmp);
     felem_reduce(ftmp, tmp);
   } /* 2^16 - 2^8 */
   felem_mul(tmp, ftmp, e8);
   felem_reduce(ftmp, tmp); /* 2^16 - 2^0 */
   felem_assign(e16, ftmp);
-  for (i = 0; i < 16; i++) {
+  for (size_t i = 0; i < 16; i++) {
     felem_square(tmp, ftmp);
     felem_reduce(ftmp, tmp);
   } /* 2^32 - 2^16 */
   felem_mul(tmp, ftmp, e16);
   felem_reduce(ftmp, tmp); /* 2^32 - 2^0 */
   felem_assign(e32, ftmp);
-  for (i = 0; i < 32; i++) {
+  for (size_t i = 0; i < 32; i++) {
     felem_square(tmp, ftmp);
     felem_reduce(ftmp, tmp);
   } /* 2^64 - 2^32 */
   felem_assign(e64, ftmp);
   felem_mul(tmp, ftmp, in);
   felem_reduce(ftmp, tmp); /* 2^64 - 2^32 + 2^0 */
-  for (i = 0; i < 192; i++) {
+  for (size_t i = 0; i < 192; i++) {
     felem_square(tmp, ftmp);
     felem_reduce(ftmp, tmp);
   } /* 2^256 - 2^224 + 2^192 */
 
   felem_mul(tmp, e64, e32);
   felem_reduce(ftmp2, tmp); /* 2^64 - 2^0 */
-  for (i = 0; i < 16; i++) {
+  for (size_t i = 0; i < 16; i++) {
     felem_square(tmp, ftmp2);
     felem_reduce(ftmp2, tmp);
   } /* 2^80 - 2^16 */
   felem_mul(tmp, ftmp2, e16);
   felem_reduce(ftmp2, tmp); /* 2^80 - 2^0 */
-  for (i = 0; i < 8; i++) {
+  for (size_t i = 0; i < 8; i++) {
     felem_square(tmp, ftmp2);
     felem_reduce(ftmp2, tmp);
   } /* 2^88 - 2^8 */
   felem_mul(tmp, ftmp2, e8);
   felem_reduce(ftmp2, tmp); /* 2^88 - 2^0 */
-  for (i = 0; i < 4; i++) {
+  for (size_t i = 0; i < 4; i++) {
     felem_square(tmp, ftmp2);
     felem_reduce(ftmp2, tmp);
   } /* 2^92 - 2^4 */
@@ -958,14 +897,6 @@
   felem_reduce(out, tmp); /* 2^256 - 2^224 + 2^192 + 2^96 - 3 */
 }
 
-static void smallfelem_inv_contract(smallfelem out, const smallfelem in) {
-  felem tmp;
-
-  smallfelem_expand(tmp, in);
-  felem_inv(tmp, tmp);
-  felem_contract(out, tmp);
-}
-
 /* Group operations
  * ----------------
  *
@@ -1076,8 +1007,7 @@
 
 /* copy_conditional copies in to out iff mask is all ones. */
 static void copy_conditional(felem out, const felem in, limb mask) {
-  unsigned i;
-  for (i = 0; i < NLIMBS; ++i) {
+  for (size_t i = 0; i < NLIMBS; ++i) {
     const limb tmp = mask & (in[i] ^ out[i]);
     out[i] ^= tmp;
   }
@@ -1085,9 +1015,8 @@
 
 /* copy_small_conditional copies in to out iff mask is all ones. */
 static void copy_small_conditional(felem out, const smallfelem in, limb mask) {
-  unsigned i;
   const u64 mask64 = mask;
-  for (i = 0; i < NLIMBS; ++i) {
+  for (size_t i = 0; i < NLIMBS; ++i) {
     out[i] = ((limb)(in[i] & mask64)) | (out[i] & ~mask);
   }
 }
@@ -1469,21 +1398,21 @@
 
 /* select_point selects the |idx|th point from a precomputation table and
  * copies it to out. */
-static void select_point(const u64 idx, unsigned int size,
-                         const smallfelem pre_comp[16][3], smallfelem out[3]) {
-  unsigned i, j;
+static void select_point(const u64 idx, size_t size,
+                         const smallfelem pre_comp[/*size*/][3],
+                         smallfelem out[3]) {
   u64 *outlimbs = &out[0][0];
-  memset(outlimbs, 0, 3 * sizeof(smallfelem));
+  OPENSSL_memset(outlimbs, 0, 3 * sizeof(smallfelem));
 
-  for (i = 0; i < size; i++) {
-    const u64 *inlimbs = (u64 *)&pre_comp[i][0][0];
+  for (size_t i = 0; i < size; i++) {
+    const u64 *inlimbs = (const u64 *)&pre_comp[i][0][0];
     u64 mask = i ^ idx;
     mask |= mask >> 4;
     mask |= mask >> 2;
     mask |= mask >> 1;
     mask &= 1;
     mask--;
-    for (j = 0; j < NLIMBS * 3; j++) {
+    for (size_t j = 0; j < NLIMBS * 3; j++) {
       outlimbs[j] |= inlimbs[j] & mask;
     }
   }
@@ -1498,38 +1427,34 @@
 }
 
 /* Interleaved point multiplication using precomputed point multiples: The
- * small point multiples 0*P, 1*P, ..., 17*P are in pre_comp[], the scalars
- * in scalars[]. If g_scalar is non-NULL, we also add this multiple of the
- * generator, using certain (large) precomputed multiples in g_pre_comp.
+ * small point multiples 0*P, 1*P, ..., 17*P are in p_pre_comp, the scalar
+ * in p_scalar, if non-NULL. If g_scalar is non-NULL, we also add this multiple
+ * of the generator, using certain (large) precomputed multiples in g_pre_comp.
  * Output point (X, Y, Z) is stored in x_out, y_out, z_out. */
-static void batch_mul(felem x_out, felem y_out, felem z_out,
-                      const felem_bytearray scalars[],
-                      const unsigned num_points, const u8 *g_scalar,
-                      const int mixed, const smallfelem pre_comp[][17][3]) {
-  int i, skip;
-  unsigned num, gen_mul = (g_scalar != NULL);
+static void batch_mul(felem x_out, felem y_out, felem z_out, const u8 *p_scalar,
+                      const u8 *g_scalar, const smallfelem p_pre_comp[17][3]) {
   felem nq[3], ftmp;
   smallfelem tmp[3];
   u64 bits;
   u8 sign, digit;
 
   /* set nq to the point at infinity */
-  memset(nq, 0, 3 * sizeof(felem));
+  OPENSSL_memset(nq, 0, 3 * sizeof(felem));
 
-  /* Loop over all scalars msb-to-lsb, interleaving additions of multiples
-   * of the generator (two in each of the last 32 rounds) and additions of
-   * other points multiples (every 5th round). */
+  /* Loop over both scalars msb-to-lsb, interleaving additions of multiples
+   * of the generator (two in each of the last 32 rounds) and additions of p
+   * (every 5th round). */
 
-  skip = 1; /* save two point operations in the first
-             * round */
-  for (i = (num_points ? 255 : 31); i >= 0; --i) {
+  int skip = 1; /* save two point operations in the first round */
+  size_t i = p_scalar != NULL ? 255 : 31;
+  for (;;) {
     /* double */
     if (!skip) {
       point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]);
     }
 
     /* add multiples of the generator */
-    if (gen_mul && i <= 31) {
+    if (g_scalar != NULL && i <= 31) {
       /* first, look 32 bits upwards */
       bits = get_bit(g_scalar, i + 224) << 3;
       bits |= get_bit(g_scalar, i + 160) << 2;
@@ -1539,9 +1464,8 @@
       select_point(bits, 16, g_pre_comp[1], tmp);
 
       if (!skip) {
-        /* Arg 1 below is for "mixed" */
-        point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1, tmp[0], tmp[1],
-                  tmp[2]);
+        point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1 /* mixed */,
+                  tmp[0], tmp[1], tmp[2]);
       } else {
         smallfelem_expand(nq[0], tmp[0]);
         smallfelem_expand(nq[1], tmp[1]);
@@ -1556,41 +1480,42 @@
       bits |= get_bit(g_scalar, i);
       /* select the point to add, in constant time */
       select_point(bits, 16, g_pre_comp[0], tmp);
-      /* Arg 1 below is for "mixed" */
-      point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1, tmp[0], tmp[1],
-                tmp[2]);
+      point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 1 /* mixed */, tmp[0],
+                tmp[1], tmp[2]);
     }
 
     /* do other additions every 5 doublings */
-    if (num_points && (i % 5 == 0)) {
-      /* loop over all scalars */
-      for (num = 0; num < num_points; ++num) {
-        bits = get_bit(scalars[num], i + 4) << 5;
-        bits |= get_bit(scalars[num], i + 3) << 4;
-        bits |= get_bit(scalars[num], i + 2) << 3;
-        bits |= get_bit(scalars[num], i + 1) << 2;
-        bits |= get_bit(scalars[num], i) << 1;
-        bits |= get_bit(scalars[num], i - 1);
-        ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits);
+    if (p_scalar != NULL && i % 5 == 0) {
+      bits = get_bit(p_scalar, i + 4) << 5;
+      bits |= get_bit(p_scalar, i + 3) << 4;
+      bits |= get_bit(p_scalar, i + 2) << 3;
+      bits |= get_bit(p_scalar, i + 1) << 2;
+      bits |= get_bit(p_scalar, i) << 1;
+      bits |= get_bit(p_scalar, i - 1);
+      ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits);
 
-        /* select the point to add or subtract, in constant time. */
-        select_point(digit, 17, pre_comp[num], tmp);
-        smallfelem_neg(ftmp, tmp[1]); /* (X, -Y, Z) is the negative
-                                       * point */
-        copy_small_conditional(ftmp, tmp[1], (((limb)sign) - 1));
-        felem_contract(tmp[1], ftmp);
+      /* select the point to add or subtract, in constant time. */
+      select_point(digit, 17, p_pre_comp, tmp);
+      smallfelem_neg(ftmp, tmp[1]); /* (X, -Y, Z) is the negative
+                                     * point */
+      copy_small_conditional(ftmp, tmp[1], (((limb)sign) - 1));
+      felem_contract(tmp[1], ftmp);
 
-        if (!skip) {
-          point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], mixed, tmp[0],
-                    tmp[1], tmp[2]);
-        } else {
-          smallfelem_expand(nq[0], tmp[0]);
-          smallfelem_expand(nq[1], tmp[1]);
-          smallfelem_expand(nq[2], tmp[2]);
-          skip = 0;
-        }
+      if (!skip) {
+        point_add(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2], 0 /* mixed */,
+                  tmp[0], tmp[1], tmp[2]);
+      } else {
+        smallfelem_expand(nq[0], tmp[0]);
+        smallfelem_expand(nq[1], tmp[1]);
+        smallfelem_expand(nq[2], tmp[2]);
+        skip = 0;
       }
     }
+
+    if (i == 0) {
+      break;
+    }
+    --i;
   }
   felem_assign(x_out, nq[0]);
   felem_assign(y_out, nq[1]);
@@ -1602,53 +1527,12 @@
  * OPENSSL EC_METHOD FUNCTIONS
  */
 
-int ec_GFp_nistp256_group_init(EC_GROUP *group) {
-  int ret = ec_GFp_simple_group_init(group);
-  group->a_is_minus3 = 1;
-  return ret;
-}
-
-int ec_GFp_nistp256_group_set_curve(EC_GROUP *group, const BIGNUM *p,
-                                    const BIGNUM *a, const BIGNUM *b,
-                                    BN_CTX *ctx) {
-  int ret = 0;
-  BN_CTX *new_ctx = NULL;
-  BIGNUM *curve_p, *curve_a, *curve_b;
-
-  if (ctx == NULL) {
-    if ((ctx = new_ctx = BN_CTX_new()) == NULL) {
-      return 0;
-    }
-  }
-  BN_CTX_start(ctx);
-  if (((curve_p = BN_CTX_get(ctx)) == NULL) ||
-      ((curve_a = BN_CTX_get(ctx)) == NULL) ||
-      ((curve_b = BN_CTX_get(ctx)) == NULL)) {
-    goto err;
-  }
-  BN_bin2bn(nistp256_curve_params[0], sizeof(felem_bytearray), curve_p);
-  BN_bin2bn(nistp256_curve_params[1], sizeof(felem_bytearray), curve_a);
-  BN_bin2bn(nistp256_curve_params[2], sizeof(felem_bytearray), curve_b);
-  if (BN_cmp(curve_p, p) ||
-      BN_cmp(curve_a, a) ||
-      BN_cmp(curve_b, b)) {
-    OPENSSL_PUT_ERROR(EC, EC_R_WRONG_CURVE_PARAMETERS);
-    goto err;
-  }
-  ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
-
-err:
-  BN_CTX_end(ctx);
-  BN_CTX_free(new_ctx);
-  return ret;
-}
-
 /* Takes the Jacobian coordinates (X, Y, Z) of a point and returns (X', Y') =
  * (X/Z^2, Y/Z^3). */
-int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group,
-                                                 const EC_POINT *point,
-                                                 BIGNUM *x, BIGNUM *y,
-                                                 BN_CTX *ctx) {
+static int ec_GFp_nistp256_point_get_affine_coordinates(const EC_GROUP *group,
+                                                        const EC_POINT *point,
+                                                        BIGNUM *x, BIGNUM *y,
+                                                        BN_CTX *ctx) {
   felem z1, z2, x_in, y_in;
   smallfelem x_out, y_out;
   longfelem tmp;
@@ -1665,68 +1549,43 @@
   felem_inv(z2, z1);
   felem_square(tmp, z2);
   felem_reduce(z1, tmp);
-  felem_mul(tmp, x_in, z1);
-  felem_reduce(x_in, tmp);
-  felem_contract(x_out, x_in);
-  if (x != NULL && !smallfelem_to_BN(x, x_out)) {
-    OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
-    return 0;
+
+  if (x != NULL) {
+    felem_mul(tmp, x_in, z1);
+    felem_reduce(x_in, tmp);
+    felem_contract(x_out, x_in);
+    if (!smallfelem_to_BN(x, x_out)) {
+      OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
+      return 0;
+    }
   }
-  felem_mul(tmp, z1, z2);
-  felem_reduce(z1, tmp);
-  felem_mul(tmp, y_in, z1);
-  felem_reduce(y_in, tmp);
-  felem_contract(y_out, y_in);
-  if (y != NULL && !smallfelem_to_BN(y, y_out)) {
-    OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
-    return 0;
+
+  if (y != NULL) {
+    felem_mul(tmp, z1, z2);
+    felem_reduce(z1, tmp);
+    felem_mul(tmp, y_in, z1);
+    felem_reduce(y_in, tmp);
+    felem_contract(y_out, y_in);
+    if (!smallfelem_to_BN(y, y_out)) {
+      OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
+      return 0;
+    }
   }
+
   return 1;
 }
 
-/* points below is of size |num|, and tmp_smallfelems is of size |num+1| */
-static void make_points_affine(size_t num, smallfelem points[][3],
-                               smallfelem tmp_smallfelems[]) {
-  /* Runs in constant time, unless an input is the point at infinity (which
-   * normally shouldn't happen). */
-  ec_GFp_nistp_points_make_affine_internal(
-      num, points, sizeof(smallfelem), tmp_smallfelems,
-      (void (*)(void *))smallfelem_one,
-      (int (*)(const void *))smallfelem_is_zero_int,
-      (void (*)(void *, const void *))smallfelem_assign,
-      (void (*)(void *, const void *))smallfelem_square_contract,
-      (void (*)(void *, const void *, const void *))smallfelem_mul_contract,
-      (void (*)(void *, const void *))smallfelem_inv_contract,
-      /* nothing to contract */
-      (void (*)(void *, const void *))smallfelem_assign);
-}
-
-int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
-                               const BIGNUM *g_scalar, const EC_POINT *p_,
-                               const BIGNUM *p_scalar_, BN_CTX *ctx) {
-  /* TODO: This function used to take |points| and |scalars| as arrays of
-   * |num| elements. The code below should be simplified to work in terms of |p|
-   * and |p_scalar|. */
-  size_t num = p_ != NULL ? 1 : 0;
-  const EC_POINT **points = p_ != NULL ? &p_ : NULL;
-  BIGNUM const *const *scalars = p_ != NULL ? &p_scalar_ : NULL;
-
+static int ec_GFp_nistp256_points_mul(const EC_GROUP *group, EC_POINT *r,
+                                      const BIGNUM *g_scalar, const EC_POINT *p,
+                                      const BIGNUM *p_scalar, BN_CTX *ctx) {
   int ret = 0;
-  int j;
-  int mixed = 0;
   BN_CTX *new_ctx = NULL;
   BIGNUM *x, *y, *z, *tmp_scalar;
-  felem_bytearray g_secret;
-  felem_bytearray *secrets = NULL;
-  smallfelem(*pre_comp)[17][3] = NULL;
-  smallfelem *tmp_smallfelems = NULL;
+  felem_bytearray g_secret, p_secret;
+  smallfelem p_pre_comp[17][3];
   felem_bytearray tmp;
-  unsigned i, num_bytes;
-  size_t num_points = num;
   smallfelem x_in, y_in, z_in;
   felem x_out, y_out, z_out;
-  const EC_POINT *p = NULL;
-  const BIGNUM *p_scalar = NULL;
 
   if (ctx == NULL) {
     ctx = new_ctx = BN_CTX_new();
@@ -1743,83 +1602,52 @@
     goto err;
   }
 
-  if (num_points > 0) {
-    if (num_points >= 3) {
-      /* unless we precompute multiples for just one or two points,
-       * converting those into affine form is time well spent */
-      mixed = 1;
+  if (p != NULL && p_scalar != NULL) {
+    /* We treat NULL scalars as 0, and NULL points as points at infinity, i.e.,
+     * they contribute nothing to the linear combination. */
+    OPENSSL_memset(&p_secret, 0, sizeof(p_secret));
+    OPENSSL_memset(&p_pre_comp, 0, sizeof(p_pre_comp));
+    size_t num_bytes;
+    /* Reduce g_scalar to 0 <= g_scalar < 2^256. */
+    if (BN_num_bits(p_scalar) > 256 || BN_is_negative(p_scalar)) {
+      /* This is an unusual input, and we don't guarantee constant-timeness. */
+      if (!BN_nnmod(tmp_scalar, p_scalar, &group->order, ctx)) {
+        OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
+        goto err;
+      }
+      num_bytes = BN_bn2bin(tmp_scalar, tmp);
+    } else {
+      num_bytes = BN_bn2bin(p_scalar, tmp);
     }
-    secrets = OPENSSL_malloc(num_points * sizeof(felem_bytearray));
-    pre_comp = OPENSSL_malloc(num_points * sizeof(smallfelem[17][3]));
-    if (mixed) {
-      tmp_smallfelems =
-          OPENSSL_malloc((num_points * 17 + 1) * sizeof(smallfelem));
-    }
-    if (secrets == NULL || pre_comp == NULL ||
-        (mixed && tmp_smallfelems == NULL)) {
-      OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
+    flip_endian(p_secret, tmp, num_bytes);
+    /* Precompute multiples. */
+    if (!BN_to_felem(x_out, &p->X) ||
+        !BN_to_felem(y_out, &p->Y) ||
+        !BN_to_felem(z_out, &p->Z)) {
       goto err;
     }
-
-    /* we treat NULL scalars as 0, and NULL points as points at infinity,
-     * i.e., they contribute nothing to the linear combination. */
-    memset(secrets, 0, num_points * sizeof(felem_bytearray));
-    memset(pre_comp, 0, num_points * 17 * 3 * sizeof(smallfelem));
-    for (i = 0; i < num_points; ++i) {
-      if (i == num) {
-        /* we didn't have a valid precomputation, so we pick the generator. */
-        p = EC_GROUP_get0_generator(group);
-        p_scalar = g_scalar;
+    felem_shrink(p_pre_comp[1][0], x_out);
+    felem_shrink(p_pre_comp[1][1], y_out);
+    felem_shrink(p_pre_comp[1][2], z_out);
+    for (size_t j = 2; j <= 16; ++j) {
+      if (j & 1) {
+        point_add_small(p_pre_comp[j][0], p_pre_comp[j][1],
+                        p_pre_comp[j][2], p_pre_comp[1][0],
+                        p_pre_comp[1][1], p_pre_comp[1][2],
+                        p_pre_comp[j - 1][0], p_pre_comp[j - 1][1],
+                        p_pre_comp[j - 1][2]);
       } else {
-        /* the i^th point */
-        p = points[i];
-        p_scalar = scalars[i];
+        point_double_small(p_pre_comp[j][0], p_pre_comp[j][1],
+                           p_pre_comp[j][2], p_pre_comp[j / 2][0],
+                           p_pre_comp[j / 2][1], p_pre_comp[j / 2][2]);
       }
-      if (p_scalar != NULL && p != NULL) {
-        /* reduce g_scalar to 0 <= g_scalar < 2^256 */
-        if (BN_num_bits(p_scalar) > 256 || BN_is_negative(p_scalar)) {
-          /* this is an unusual input, and we don't guarantee
-           * constant-timeness. */
-          if (!BN_nnmod(tmp_scalar, p_scalar, &group->order, ctx)) {
-            OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
-            goto err;
-          }
-          num_bytes = BN_bn2bin(tmp_scalar, tmp);
-        } else {
-          num_bytes = BN_bn2bin(p_scalar, tmp);
-        }
-        flip_endian(secrets[i], tmp, num_bytes);
-        /* precompute multiples */
-        if (!BN_to_felem(x_out, &p->X) ||
-            !BN_to_felem(y_out, &p->Y) ||
-            !BN_to_felem(z_out, &p->Z)) {
-          goto err;
-        }
-        felem_shrink(pre_comp[i][1][0], x_out);
-        felem_shrink(pre_comp[i][1][1], y_out);
-        felem_shrink(pre_comp[i][1][2], z_out);
-        for (j = 2; j <= 16; ++j) {
-          if (j & 1) {
-            point_add_small(pre_comp[i][j][0], pre_comp[i][j][1],
-                            pre_comp[i][j][2], pre_comp[i][1][0],
-                            pre_comp[i][1][1], pre_comp[i][1][2],
-                            pre_comp[i][j - 1][0], pre_comp[i][j - 1][1],
-                            pre_comp[i][j - 1][2]);
-          } else {
-            point_double_small(pre_comp[i][j][0], pre_comp[i][j][1],
-                               pre_comp[i][j][2], pre_comp[i][j / 2][0],
-                               pre_comp[i][j / 2][1], pre_comp[i][j / 2][2]);
-          }
-        }
-      }
-    }
-    if (mixed) {
-      make_points_affine(num_points * 17, pre_comp[0], tmp_smallfelems);
     }
   }
 
   if (g_scalar != NULL) {
-    memset(g_secret, 0, sizeof(g_secret));
+    size_t num_bytes;
+
+    OPENSSL_memset(g_secret, 0, sizeof(g_secret));
     /* reduce g_scalar to 0 <= g_scalar < 2^256 */
     if (BN_num_bits(g_scalar) > 256 || BN_is_negative(g_scalar)) {
       /* this is an unusual input, and we don't guarantee
@@ -1834,9 +1662,10 @@
     }
     flip_endian(g_secret, tmp, num_bytes);
   }
-  batch_mul(x_out, y_out, z_out, (const felem_bytearray(*))secrets,
-            num_points, g_scalar != NULL ? g_secret : NULL, mixed,
-            (const smallfelem(*)[17][3])pre_comp);
+  batch_mul(x_out, y_out, z_out,
+            (p != NULL && p_scalar != NULL) ? p_secret : NULL,
+            g_scalar != NULL ? g_secret : NULL,
+            (const smallfelem(*)[3]) &p_pre_comp);
 
   /* reduce the output to its unique minimal representation */
   felem_contract(x_in, x_out);
@@ -1853,26 +1682,20 @@
 err:
   BN_CTX_end(ctx);
   BN_CTX_free(new_ctx);
-  OPENSSL_free(secrets);
-  OPENSSL_free(pre_comp);
-  OPENSSL_free(tmp_smallfelems);
   return ret;
 }
 
-const EC_METHOD *EC_GFp_nistp256_method(void) {
-  static const EC_METHOD ret = {
-      ec_GFp_nistp256_group_init,
-      ec_GFp_simple_group_finish,
-      ec_GFp_simple_group_clear_finish,
-      ec_GFp_simple_group_copy, ec_GFp_nistp256_group_set_curve,
-      ec_GFp_nistp256_point_get_affine_coordinates,
-      ec_GFp_nistp256_points_mul,
-      0 /* check_pub_key_order */,
-      ec_GFp_simple_field_mul, ec_GFp_simple_field_sqr,
-      0 /* field_encode */, 0 /* field_decode */, 0 /* field_set_to_one */
-  };
-
-  return &ret;
-}
+const EC_METHOD EC_GFp_nistp256_method = {
+    ec_GFp_simple_group_init,
+    ec_GFp_simple_group_finish,
+    ec_GFp_simple_group_copy,
+    ec_GFp_simple_group_set_curve,
+    ec_GFp_nistp256_point_get_affine_coordinates,
+    ec_GFp_nistp256_points_mul,
+    ec_GFp_simple_field_mul,
+    ec_GFp_simple_field_sqr,
+    NULL /* field_encode */,
+    NULL /* field_decode */,
+};
 
 #endif  /* 64_BIT && !WINDOWS */
diff --git a/src/crypto/ec/p256-x86_64-table.h b/src/crypto/ec/p256-x86_64-table.h
index 5b3254c..e4705f8 100644
--- a/src/crypto/ec/p256-x86_64-table.h
+++ b/src/crypto/ec/p256-x86_64-table.h
@@ -24,12 +24,7 @@
  * in order to increase the chances of using a large page but that appears to
  * lead to invalid ELF files being produced. */
 
-#if defined(__GNUC__)
-__attribute((aligned(4096)))
-#elif defined(_MSC_VER)
-__declspec(align(4096))
-#endif
-static const BN_ULONG
+static const alignas(4096) BN_ULONG
     ecp_nistz256_precomputed[37][64 * sizeof(P256_POINT_AFFINE) /
                                  sizeof(BN_ULONG)] = {
         {TOBN(0x79e730d4, 0x18a9143c), TOBN(0x75ba95fc, 0x5fedb601),
diff --git a/src/crypto/ec/p256-x86_64.c b/src/crypto/ec/p256-x86_64.c
index 2f7023d..652d10c 100644
--- a/src/crypto/ec/p256-x86_64.c
+++ b/src/crypto/ec/p256-x86_64.c
@@ -31,57 +31,16 @@
 #include <openssl/err.h>
 
 #include "../bn/internal.h"
-#include "../ec/internal.h"
 #include "../internal.h"
+#include "internal.h"
+#include "p256-x86_64.h"
 
 
 #if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && \
     !defined(OPENSSL_SMALL)
 
-
-#if defined(__GNUC__)
-#define ALIGN(x) __attribute((aligned(x)))
-#elif defined(_MSC_VER)
-#define ALIGN(x) __declspec(align(x))
-#else
-#define ALIGN(x)
-#endif
-
-#define ALIGNPTR(p, N) ((uint8_t *)p + N - (size_t)p % N)
-#define P256_LIMBS (256 / BN_BITS2)
-
-typedef struct {
-  BN_ULONG X[P256_LIMBS];
-  BN_ULONG Y[P256_LIMBS];
-  BN_ULONG Z[P256_LIMBS];
-} P256_POINT;
-
-typedef struct {
-  BN_ULONG X[P256_LIMBS];
-  BN_ULONG Y[P256_LIMBS];
-} P256_POINT_AFFINE;
-
 typedef P256_POINT_AFFINE PRECOMP256_ROW[64];
 
-/* Functions implemented in assembly */
-
-/* Modular neg: res = -a mod P */
-void ecp_nistz256_neg(BN_ULONG res[P256_LIMBS], const BN_ULONG a[P256_LIMBS]);
-/* Montgomery mul: res = a*b*2^-256 mod P */
-void ecp_nistz256_mul_mont(BN_ULONG res[P256_LIMBS],
-                           const BN_ULONG a[P256_LIMBS],
-                           const BN_ULONG b[P256_LIMBS]);
-/* Montgomery sqr: res = a*a*2^-256 mod P */
-void ecp_nistz256_sqr_mont(BN_ULONG res[P256_LIMBS],
-                           const BN_ULONG a[P256_LIMBS]);
-/* Convert a number from Montgomery domain, by multiplying with 1 */
-void ecp_nistz256_from_mont(BN_ULONG res[P256_LIMBS],
-                            const BN_ULONG in[P256_LIMBS]);
-/* Functions that perform constant time access to the precomputed tables */
-void ecp_nistz256_select_w5(P256_POINT *val, const P256_POINT *in_t, int index);
-void ecp_nistz256_select_w7(P256_POINT_AFFINE *val,
-                            const P256_POINT_AFFINE *in_t, int index);
-
 /* One converted into the Montgomery domain */
 static const BN_ULONG ONE[P256_LIMBS] = {
     TOBN(0x00000000, 0x00000001), TOBN(0xffffffff, 0x00000000),
@@ -91,7 +50,7 @@
 /* Precomputed tables for the default generator */
 #include "p256-x86_64-table.h"
 
-/* Recode window to a signed digit, see ecp_nistputil.c for details */
+/* Recode window to a signed digit, see util-64.c for details */
 static unsigned booth_recode_w5(unsigned in) {
   unsigned s, d;
 
@@ -114,6 +73,11 @@
   return (d << 1) + (s & 1);
 }
 
+/* copy_conditional copies |src| to |dst| if |move| is one and leaves it as-is
+ * if |move| is zero.
+ *
+ * WARNING: this breaks the usual convention of constant-time functions
+ * returning masks. */
 static void copy_conditional(BN_ULONG dst[P256_LIMBS],
                              const BN_ULONG src[P256_LIMBS], BN_ULONG move) {
   BN_ULONG mask1 = ((BN_ULONG)0) - move;
@@ -131,15 +95,34 @@
   }
 }
 
-void ecp_nistz256_point_double(P256_POINT *r, const P256_POINT *a);
-void ecp_nistz256_point_add(P256_POINT *r, const P256_POINT *a,
-                            const P256_POINT *b);
-void ecp_nistz256_point_add_affine(P256_POINT *r, const P256_POINT *a,
-                                   const P256_POINT_AFFINE *b);
+/* is_not_zero returns one iff in != 0 and zero otherwise.
+ *
+ * WARNING: this breaks the usual convention of constant-time functions
+ * returning masks.
+ *
+ * (define-fun is_not_zero ((in (_ BitVec 64))) (_ BitVec 64)
+ *   (bvlshr (bvor in (bvsub #x0000000000000000 in)) #x000000000000003f)
+ * )
+ *
+ * (declare-fun x () (_ BitVec 64))
+ *
+ * (assert (and (= x #x0000000000000000) (= (is_not_zero x) #x0000000000000001)))
+ * (check-sat)
+ *
+ * (assert (and (not (= x #x0000000000000000)) (= (is_not_zero x) #x0000000000000000)))
+ * (check-sat)
+ * */
+static BN_ULONG is_not_zero(BN_ULONG in) {
+  in |= (0 - in);
+  in >>= BN_BITS2 - 1;
+  return in;
+}
 
-/* r = in^-1 mod p */
-static void ecp_nistz256_mod_inverse(BN_ULONG r[P256_LIMBS],
-                                     const BN_ULONG in[P256_LIMBS]) {
+/* ecp_nistz256_mod_inverse_mont sets |r| to (|in| * 2^-256)^-1 * 2^256 mod p.
+ * That is, |r| is the modular inverse of |in| for input and output in the
+ * Montgomery domain. */
+static void ecp_nistz256_mod_inverse_mont(BN_ULONG r[P256_LIMBS],
+                                          const BN_ULONG in[P256_LIMBS]) {
   /* The poly is ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff
      ffffffff
      We use FLT and used poly-2 as exponent */
@@ -214,9 +197,7 @@
 
   ecp_nistz256_sqr_mont(res, res);
   ecp_nistz256_sqr_mont(res, res);
-  ecp_nistz256_mul_mont(res, res, in);
-
-  memcpy(r, res, sizeof(res));
+  ecp_nistz256_mul_mont(r, res, in);
 }
 
 /* ecp_nistz256_bignum_to_field_elem copies the contents of |in| to |out| and
@@ -227,8 +208,8 @@
     return 0;
   }
 
-  memset(out, 0, sizeof(BN_ULONG) * P256_LIMBS);
-  memcpy(out, in->d, sizeof(BN_ULONG) * in->top);
+  OPENSSL_memset(out, 0, sizeof(BN_ULONG) * P256_LIMBS);
+  OPENSSL_memcpy(out, in->d, sizeof(BN_ULONG) * in->top);
   return 1;
 }
 
@@ -245,7 +226,7 @@
   /* A |P256_POINT| is (3 * 32) = 96 bytes, and the 64-byte alignment should
    * add no more than 63 bytes of overhead. Thus, |table| should require
    * ~1599 ((96 * 16) + 63) bytes of stack space. */
-  ALIGN(64) P256_POINT table[16];
+  alignas(64) P256_POINT table[16];
   uint8_t p_str[33];
 
 
@@ -323,10 +304,10 @@
   ecp_nistz256_point_double(&row[10 - 1], &row[5 - 1]);
   ecp_nistz256_point_add(&row[15 - 1], &row[14 - 1], &row[1 - 1]);
   ecp_nistz256_point_add(&row[11 - 1], &row[10 - 1], &row[1 - 1]);
-  ecp_nistz256_point_add(&row[16 - 1], &row[15 - 1], &row[1 - 1]);
+  ecp_nistz256_point_double(&row[16 - 1], &row[8 - 1]);
 
   BN_ULONG tmp[P256_LIMBS];
-  ALIGN(32) P256_POINT h;
+  alignas(32) P256_POINT h;
   unsigned index = 255;
   unsigned wvalue = p_str[(index - 1) / 8];
   wvalue = (wvalue >> ((index - 1) % 8)) & kMask;
@@ -390,7 +371,7 @@
   static const unsigned kWindowSize = 7;
   static const unsigned kMask = (1 << (7 /* kWindowSize */ + 1)) - 1;
 
-  ALIGN(32) union {
+  alignas(32) union {
     P256_POINT p;
     P256_POINT_AFFINE a;
   } t, p;
@@ -399,17 +380,6 @@
   BN_CTX *new_ctx = NULL;
   int ctx_started = 0;
 
-  /* Need 256 bits for space for all coordinates. */
-  if (bn_wexpand(&r->X, P256_LIMBS) == NULL ||
-      bn_wexpand(&r->Y, P256_LIMBS) == NULL ||
-      bn_wexpand(&r->Z, P256_LIMBS) == NULL) {
-    OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
-    goto err;
-  }
-  r->X.top = P256_LIMBS;
-  r->Y.top = P256_LIMBS;
-  r->Z.top = P256_LIMBS;
-
   if (g_scalar != NULL) {
     if (BN_num_bits(g_scalar) > 256 || BN_is_negative(g_scalar)) {
       if (ctx == NULL) {
@@ -468,7 +438,11 @@
     ecp_nistz256_neg(p.p.Z, p.p.Y);
     copy_conditional(p.p.Y, p.p.Z, wvalue & 1);
 
-    memcpy(p.p.Z, ONE, sizeof(ONE));
+    /* Convert |p| from affine to Jacobian coordinates. We set Z to zero if |p|
+     * is infinity and |ONE| otherwise. |p| was computed from the table, so it
+     * is infinity iff |wvalue >> 1| is zero.  */
+    OPENSSL_memset(p.p.Z, 0, sizeof(p.p.Z));
+    copy_conditional(p.p.Z, ONE, is_not_zero(wvalue >> 1));
 
     for (i = 1; i < 37; i++) {
       unsigned off = (index - 1) / 8;
@@ -503,15 +477,12 @@
     }
   }
 
-  memcpy(r->X.d, p.p.X, sizeof(p.p.X));
-  memcpy(r->Y.d, p.p.Y, sizeof(p.p.Y));
-  memcpy(r->Z.d, p.p.Z, sizeof(p.p.Z));
-
   /* Not constant-time, but we're only operating on the public output. */
-  bn_correct_top(&r->X);
-  bn_correct_top(&r->Y);
-  bn_correct_top(&r->Z);
-  r->Z_is_one = BN_is_one(&r->Z);
+  if (!bn_set_words(&r->X, p.p.X, P256_LIMBS) ||
+      !bn_set_words(&r->Y, p.p.Y, P256_LIMBS) ||
+      !bn_set_words(&r->Z, p.p.Z, P256_LIMBS)) {
+    return 0;
+  }
 
   ret = 1;
 
@@ -527,8 +498,6 @@
                                    BIGNUM *x, BIGNUM *y, BN_CTX *ctx) {
   BN_ULONG z_inv2[P256_LIMBS];
   BN_ULONG z_inv3[P256_LIMBS];
-  BN_ULONG x_aff[P256_LIMBS];
-  BN_ULONG y_aff[P256_LIMBS];
   BN_ULONG point_x[P256_LIMBS], point_y[P256_LIMBS], point_z[P256_LIMBS];
 
   if (EC_POINT_is_at_infinity(group, point)) {
@@ -543,54 +512,50 @@
     return 0;
   }
 
-  ecp_nistz256_mod_inverse(z_inv3, point_z);
+  ecp_nistz256_mod_inverse_mont(z_inv3, point_z);
   ecp_nistz256_sqr_mont(z_inv2, z_inv3);
-  ecp_nistz256_mul_mont(x_aff, z_inv2, point_x);
+
+  /* Instead of using |ecp_nistz256_from_mont| to convert the |x| coordinate
+   * and then calling |ecp_nistz256_from_mont| again to convert the |y|
+   * coordinate below, convert the common factor |z_inv2| once now, saving one
+   * reduction. */
+  ecp_nistz256_from_mont(z_inv2, z_inv2);
 
   if (x != NULL) {
-    if (bn_wexpand(x, P256_LIMBS) == NULL) {
+    BN_ULONG x_aff[P256_LIMBS];
+    ecp_nistz256_mul_mont(x_aff, z_inv2, point_x);
+    if (!bn_set_words(x, x_aff, P256_LIMBS)) {
       OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
       return 0;
     }
-    x->top = P256_LIMBS;
-    ecp_nistz256_from_mont(x->d, x_aff);
-    bn_correct_top(x);
   }
 
   if (y != NULL) {
+    BN_ULONG y_aff[P256_LIMBS];
     ecp_nistz256_mul_mont(z_inv3, z_inv3, z_inv2);
     ecp_nistz256_mul_mont(y_aff, z_inv3, point_y);
-    if (bn_wexpand(y, P256_LIMBS) == NULL) {
+    if (!bn_set_words(y, y_aff, P256_LIMBS)) {
       OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
       return 0;
     }
-    y->top = P256_LIMBS;
-    ecp_nistz256_from_mont(y->d, y_aff);
-    bn_correct_top(y);
   }
 
   return 1;
 }
 
-const EC_METHOD *EC_GFp_nistz256_method(void) {
-  static const EC_METHOD ret = {
-      ec_GFp_mont_group_init,
-      ec_GFp_mont_group_finish,
-      ec_GFp_mont_group_clear_finish,
-      ec_GFp_mont_group_copy,
-      ec_GFp_mont_group_set_curve,
-      ecp_nistz256_get_affine,
-      ecp_nistz256_points_mul,
-      0 /* check_pub_key_order */,
-      ec_GFp_mont_field_mul,
-      ec_GFp_mont_field_sqr,
-      ec_GFp_mont_field_encode,
-      ec_GFp_mont_field_decode,
-      ec_GFp_mont_field_set_to_one,
-  };
 
-  return &ret;
-}
+const EC_METHOD EC_GFp_nistz256_method = {
+    ec_GFp_mont_group_init,
+    ec_GFp_mont_group_finish,
+    ec_GFp_mont_group_copy,
+    ec_GFp_mont_group_set_curve,
+    ecp_nistz256_get_affine,
+    ecp_nistz256_points_mul,
+    ec_GFp_mont_field_mul,
+    ec_GFp_mont_field_sqr,
+    ec_GFp_mont_field_encode,
+    ec_GFp_mont_field_decode,
+};
 
 #endif /* !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && \
           !defined(OPENSSL_SMALL) */
diff --git a/src/crypto/ec/p256-x86_64.h b/src/crypto/ec/p256-x86_64.h
new file mode 100644
index 0000000..0132348
--- /dev/null
+++ b/src/crypto/ec/p256-x86_64.h
@@ -0,0 +1,113 @@
+/* Copyright (c) 2014, Intel Corporation.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#ifndef OPENSSL_HEADER_EC_P256_X86_64_H
+#define OPENSSL_HEADER_EC_P256_X86_64_H
+
+#include <openssl/base.h>
+
+#include <openssl/bn.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && \
+    !defined(OPENSSL_SMALL)
+
+/* P-256 field operations.
+ *
+ * An element mod P in P-256 is represented as a little-endian array of
+ * |P256_LIMBS| |BN_ULONG|s, spanning the full range of values.
+ *
+ * The following functions take fully-reduced inputs mod P and give
+ * fully-reduced outputs. They may be used in-place. */
+
+#define P256_LIMBS (256 / BN_BITS2)
+
+/* ecp_nistz256_neg sets |res| to -|a| mod P. */
+void ecp_nistz256_neg(BN_ULONG res[P256_LIMBS], const BN_ULONG a[P256_LIMBS]);
+
+/* ecp_nistz256_mul_mont sets |res| to |a| * |b| * 2^-256 mod P. */
+void ecp_nistz256_mul_mont(BN_ULONG res[P256_LIMBS],
+                           const BN_ULONG a[P256_LIMBS],
+                           const BN_ULONG b[P256_LIMBS]);
+
+/* ecp_nistz256_sqr_mont sets |res| to |a| * |a| * 2^-256 mod P. */
+void ecp_nistz256_sqr_mont(BN_ULONG res[P256_LIMBS],
+                           const BN_ULONG a[P256_LIMBS]);
+
+/* ecp_nistz256_from_mont sets |res| to |in|, converted from Montgomery domain
+ * by multiplying with 1. */
+static inline void ecp_nistz256_from_mont(BN_ULONG res[P256_LIMBS],
+                                          const BN_ULONG in[P256_LIMBS]) {
+  static const BN_ULONG ONE[P256_LIMBS] = { 1 };
+  ecp_nistz256_mul_mont(res, in, ONE);
+}
+
+
+/* P-256 point operations.
+ *
+ * The following functions may be used in-place. All coordinates are in the
+ * Montgomery domain. */
+
+/* A P256_POINT represents a P-256 point in Jacobian coordinates. */
+typedef struct {
+  BN_ULONG X[P256_LIMBS];
+  BN_ULONG Y[P256_LIMBS];
+  BN_ULONG Z[P256_LIMBS];
+} P256_POINT;
+
+/* A P256_POINT_AFFINE represents a P-256 point in affine coordinates. Infinity
+ * is encoded as (0, 0). */
+typedef struct {
+  BN_ULONG X[P256_LIMBS];
+  BN_ULONG Y[P256_LIMBS];
+} P256_POINT_AFFINE;
+
+/* ecp_nistz256_select_w5 sets |*val| to |in_t[index-1]| if 1 <= |index| <= 16
+ * and all zeros (the point at infinity) if |index| is 0. This is done in
+ * constant time. */
+void ecp_nistz256_select_w5(P256_POINT *val, const P256_POINT in_t[16],
+                            int index);
+
+/* ecp_nistz256_select_w7 sets |*val| to |in_t[index-1]| if 1 <= |index| <= 64
+ * and all zeros (the point at infinity) if |index| is 0. This is done in
+ * constant time. */
+void ecp_nistz256_select_w7(P256_POINT_AFFINE *val,
+                            const P256_POINT_AFFINE in_t[64], int index);
+
+/* ecp_nistz256_point_double sets |r| to |a| doubled. */
+void ecp_nistz256_point_double(P256_POINT *r, const P256_POINT *a);
+
+/* ecp_nistz256_point_add adds |a| to |b| and places the result in |r|. */
+void ecp_nistz256_point_add(P256_POINT *r, const P256_POINT *a,
+                            const P256_POINT *b);
+
+/* ecp_nistz256_point_add_affine adds |a| to |b| and places the result in
+ * |r|. |a| and |b| must not represent the same point unless they are both
+ * infinity. */
+void ecp_nistz256_point_add_affine(P256_POINT *r, const P256_POINT *a,
+                                   const P256_POINT_AFFINE *b);
+
+#endif /* !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && \
+           !defined(OPENSSL_SMALL) */
+
+
+#if defined(__cplusplus)
+}  /* extern C++ */
+#endif
+
+#endif  /* OPENSSL_HEADER_EC_P256_X86_64_H */
diff --git a/src/crypto/ec/p256-x86_64_test.cc b/src/crypto/ec/p256-x86_64_test.cc
new file mode 100644
index 0000000..afc3b54
--- /dev/null
+++ b/src/crypto/ec/p256-x86_64_test.cc
@@ -0,0 +1,508 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#if !defined(__STDC_FORMAT_MACROS)
+#define __STDC_FORMAT_MACROS
+#endif
+
+#include <openssl/base.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/bn.h>
+#include <openssl/mem.h>
+
+#include "../bn/internal.h"
+#include "../test/file_test.h"
+#include "p256-x86_64.h"
+
+
+// Disable tests if BORINGSSL_SHARED_LIBRARY is defined. These tests need access
+// to internal functions.
+#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && \
+    !defined(OPENSSL_SMALL) && !defined(BORINGSSL_SHARED_LIBRARY)
+
+static bool TestSelectW5() {
+  // Fill a table with some garbage input.
+  P256_POINT table[16];
+  for (size_t i = 0; i < 16; i++) {
+    OPENSSL_memset(table[i].X, 3 * i, sizeof(table[i].X));
+    OPENSSL_memset(table[i].Y, 3 * i + 1, sizeof(table[i].Y));
+    OPENSSL_memset(table[i].Z, 3 * i + 2, sizeof(table[i].Z));
+  }
+
+  for (int i = 0; i <= 16; i++) {
+    P256_POINT val;
+    ecp_nistz256_select_w5(&val, table, i);
+
+    P256_POINT expected;
+    if (i == 0) {
+      OPENSSL_memset(&expected, 0, sizeof(expected));
+    } else {
+      expected = table[i-1];
+    }
+
+    if (OPENSSL_memcmp(&val, &expected, sizeof(P256_POINT)) != 0) {
+      fprintf(stderr, "ecp_nistz256_select_w5(%d) gave the wrong value.\n", i);
+      return false;
+    }
+  }
+
+  return true;
+}
+
+static bool TestSelectW7() {
+  // Fill a table with some garbage input.
+  P256_POINT_AFFINE table[64];
+  for (size_t i = 0; i < 64; i++) {
+    OPENSSL_memset(table[i].X, 2 * i, sizeof(table[i].X));
+    OPENSSL_memset(table[i].Y, 2 * i + 1, sizeof(table[i].Y));
+  }
+
+  for (int i = 0; i <= 64; i++) {
+    P256_POINT_AFFINE val;
+    ecp_nistz256_select_w7(&val, table, i);
+
+    P256_POINT_AFFINE expected;
+    if (i == 0) {
+      OPENSSL_memset(&expected, 0, sizeof(expected));
+    } else {
+      expected = table[i-1];
+    }
+
+    if (OPENSSL_memcmp(&val, &expected, sizeof(P256_POINT_AFFINE)) != 0) {
+      fprintf(stderr, "ecp_nistz256_select_w7(%d) gave the wrong value.\n", i);
+      return false;
+    }
+  }
+
+  return true;
+}
+
+static bool GetFieldElement(FileTest *t, BN_ULONG out[P256_LIMBS],
+                            const char *name) {
+  std::vector<uint8_t> bytes;
+  if (!t->GetBytes(&bytes, name)) {
+    return false;
+  }
+
+  if (bytes.size() != BN_BYTES * P256_LIMBS) {
+    t->PrintLine("Invalid length: %s", name);
+    return false;
+  }
+
+  // |byte| contains bytes in big-endian while |out| should contain |BN_ULONG|s
+  // in little-endian.
+  OPENSSL_memset(out, 0, P256_LIMBS * sizeof(BN_ULONG));
+  for (size_t i = 0; i < bytes.size(); i++) {
+    out[P256_LIMBS - 1 - (i / BN_BYTES)] <<= 8;
+    out[P256_LIMBS - 1 - (i / BN_BYTES)] |= bytes[i];
+  }
+
+  return true;
+}
+
+static std::string FieldElementToString(const BN_ULONG a[P256_LIMBS]) {
+  std::string ret;
+  for (size_t i = P256_LIMBS-1; i < P256_LIMBS; i--) {
+    char buf[2 * BN_BYTES + 1];
+    BIO_snprintf(buf, sizeof(buf), BN_HEX_FMT2, a[i]);
+    ret += buf;
+  }
+  return ret;
+}
+
+static bool ExpectFieldElementsEqual(FileTest *t, const char *message,
+                                     const BN_ULONG expected[P256_LIMBS],
+                                     const BN_ULONG actual[P256_LIMBS]) {
+  if (OPENSSL_memcmp(expected, actual, sizeof(BN_ULONG) * P256_LIMBS) == 0) {
+    return true;
+  }
+
+  t->PrintLine("%s", message);
+  t->PrintLine("Expected: %s", FieldElementToString(expected).c_str());
+  t->PrintLine("Actual:   %s", FieldElementToString(actual).c_str());
+  return false;
+}
+
+static bool PointToAffine(P256_POINT_AFFINE *out, const P256_POINT *in) {
+  static const uint8_t kP[] = {
+      0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
+      0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  };
+
+  bssl::UniquePtr<BIGNUM> x(BN_new()), y(BN_new()), z(BN_new());
+  bssl::UniquePtr<BIGNUM> p(BN_bin2bn(kP, sizeof(kP), nullptr));
+  if (!x || !y || !z || !p ||
+      !bn_set_words(x.get(), in->X, P256_LIMBS) ||
+      !bn_set_words(y.get(), in->Y, P256_LIMBS) ||
+      !bn_set_words(z.get(), in->Z, P256_LIMBS)) {
+    return false;
+  }
+
+  // Coordinates must be fully-reduced.
+  if (BN_cmp(x.get(), p.get()) >= 0 ||
+      BN_cmp(y.get(), p.get()) >= 0 ||
+      BN_cmp(z.get(), p.get()) >= 0) {
+    return false;
+  }
+
+  OPENSSL_memset(out, 0, sizeof(P256_POINT_AFFINE));
+
+  if (BN_is_zero(z.get())) {
+    // The point at infinity is represented as (0, 0).
+    return true;
+  }
+
+  bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
+  bssl::UniquePtr<BN_MONT_CTX> mont(BN_MONT_CTX_new());
+  if (!ctx || !mont ||
+      !BN_MONT_CTX_set(mont.get(), p.get(), ctx.get()) ||
+      // Invert Z.
+      !BN_from_montgomery(z.get(), z.get(), mont.get(), ctx.get()) ||
+      !BN_mod_inverse(z.get(), z.get(), p.get(), ctx.get()) ||
+      !BN_to_montgomery(z.get(), z.get(), mont.get(), ctx.get()) ||
+      // Convert (X, Y, Z) to (X/Z^2, Y/Z^3).
+      !BN_mod_mul_montgomery(x.get(), x.get(), z.get(), mont.get(),
+                             ctx.get()) ||
+      !BN_mod_mul_montgomery(x.get(), x.get(), z.get(), mont.get(),
+                             ctx.get()) ||
+      !BN_mod_mul_montgomery(y.get(), y.get(), z.get(), mont.get(),
+                             ctx.get()) ||
+      !BN_mod_mul_montgomery(y.get(), y.get(), z.get(), mont.get(),
+                             ctx.get()) ||
+      !BN_mod_mul_montgomery(y.get(), y.get(), z.get(), mont.get(),
+                             ctx.get())) {
+    return false;
+  }
+
+  OPENSSL_memcpy(out->X, x->d, sizeof(BN_ULONG) * x->top);
+  OPENSSL_memcpy(out->Y, y->d, sizeof(BN_ULONG) * y->top);
+  return true;
+}
+
+static bool ExpectPointsEqual(FileTest *t, const char *message,
+                              const P256_POINT_AFFINE *expected,
+                              const P256_POINT *point) {
+  // There are multiple representations of the same |P256_POINT|, so convert to
+  // |P256_POINT_AFFINE| and compare.
+  P256_POINT_AFFINE affine;
+  if (!PointToAffine(&affine, point)) {
+    t->PrintLine("%s", message);
+    t->PrintLine("Could not convert to affine: (%s, %s, %s)",
+                 FieldElementToString(point->X).c_str(),
+                 FieldElementToString(point->Y).c_str(),
+                 FieldElementToString(point->Z).c_str());
+    return false;
+  }
+
+  if (OPENSSL_memcmp(expected, &affine, sizeof(P256_POINT_AFFINE)) != 0) {
+    t->PrintLine("%s", message);
+    t->PrintLine("Expected: (%s, %s)",
+                 FieldElementToString(expected->X).c_str(),
+                 FieldElementToString(expected->Y).c_str());
+    t->PrintLine("Actual:   (%s, %s)", FieldElementToString(affine.X).c_str(),
+                 FieldElementToString(affine.Y).c_str());
+    return false;
+  }
+
+  return true;
+}
+
+static bool TestNegate(FileTest *t) {
+  BN_ULONG a[P256_LIMBS], b[P256_LIMBS];
+  if (!GetFieldElement(t, a, "A") ||
+      !GetFieldElement(t, b, "B")) {
+    return false;
+  }
+
+  // Test that -A = B.
+  BN_ULONG ret[P256_LIMBS];
+  ecp_nistz256_neg(ret, a);
+  if (!ExpectFieldElementsEqual(t, "ecp_nistz256_neg(A) was incorrect.", b,
+                                ret)) {
+    return false;
+  }
+
+  OPENSSL_memcpy(ret, a, sizeof(ret));
+  ecp_nistz256_neg(ret, ret);
+  if (!ExpectFieldElementsEqual(
+          t, "In-place ecp_nistz256_neg(A) was incorrect.", b, ret)) {
+    return false;
+  }
+
+  // Test that -B = A.
+  ecp_nistz256_neg(ret, b);
+  if (!ExpectFieldElementsEqual(t, "ecp_nistz256_neg(B) was incorrect.", a,
+                                ret)) {
+    return false;
+  }
+
+  OPENSSL_memcpy(ret, b, sizeof(ret));
+  ecp_nistz256_neg(ret, ret);
+  if (!ExpectFieldElementsEqual(
+          t, "In-place ecp_nistz256_neg(B) was incorrect.", a, ret)) {
+    return false;
+  }
+
+  return true;
+}
+
+static bool TestMulMont(FileTest *t) {
+  BN_ULONG a[P256_LIMBS], b[P256_LIMBS], result[P256_LIMBS];
+  if (!GetFieldElement(t, a, "A") ||
+      !GetFieldElement(t, b, "B") ||
+      !GetFieldElement(t, result, "Result")) {
+    return false;
+  }
+
+  BN_ULONG ret[P256_LIMBS];
+  ecp_nistz256_mul_mont(ret, a, b);
+  if (!ExpectFieldElementsEqual(t, "ecp_nistz256_mul_mont(A, B) was incorrect.",
+                                result, ret)) {
+    return false;
+  }
+
+  ecp_nistz256_mul_mont(ret, b, a);
+  if (!ExpectFieldElementsEqual(t, "ecp_nistz256_mul_mont(B, A) was incorrect.",
+                                result, ret)) {
+    return false;
+  }
+
+  OPENSSL_memcpy(ret, a, sizeof(ret));
+  ecp_nistz256_mul_mont(ret, ret, b);
+  if (!ExpectFieldElementsEqual(
+          t, "ecp_nistz256_mul_mont(ret = A, B) was incorrect.", result, ret)) {
+    return false;
+  }
+
+  OPENSSL_memcpy(ret, a, sizeof(ret));
+  ecp_nistz256_mul_mont(ret, b, ret);
+  if (!ExpectFieldElementsEqual(
+          t, "ecp_nistz256_mul_mont(B, ret = A) was incorrect.", result, ret)) {
+    return false;
+  }
+
+  OPENSSL_memcpy(ret, b, sizeof(ret));
+  ecp_nistz256_mul_mont(ret, a, ret);
+  if (!ExpectFieldElementsEqual(
+          t, "ecp_nistz256_mul_mont(A, ret = B) was incorrect.", result, ret)) {
+    return false;
+  }
+
+  OPENSSL_memcpy(ret, b, sizeof(ret));
+  ecp_nistz256_mul_mont(ret, ret, a);
+  if (!ExpectFieldElementsEqual(
+          t, "ecp_nistz256_mul_mont(ret = B, A) was incorrect.", result, ret)) {
+    return false;
+  }
+
+  if (OPENSSL_memcmp(a, b, sizeof(a)) == 0) {
+    ecp_nistz256_sqr_mont(ret, a);
+    if (!ExpectFieldElementsEqual(t, "ecp_nistz256_sqr_mont(A) was incorrect.",
+                                  result, ret)) {
+      return false;
+    }
+
+    OPENSSL_memcpy(ret, a, sizeof(ret));
+    ecp_nistz256_sqr_mont(ret, ret);
+    if (!ExpectFieldElementsEqual(
+            t, "ecp_nistz256_sqr_mont(ret = A) was incorrect.", result, ret)) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+static bool TestFromMont(FileTest *t) {
+  BN_ULONG a[P256_LIMBS], result[P256_LIMBS];
+  if (!GetFieldElement(t, a, "A") ||
+      !GetFieldElement(t, result, "Result")) {
+    return false;
+  }
+
+  BN_ULONG ret[P256_LIMBS];
+  ecp_nistz256_from_mont(ret, a);
+  if (!ExpectFieldElementsEqual(t, "ecp_nistz256_from_mont(A) was incorrect.",
+                                result, ret)) {
+    return false;
+  }
+
+  OPENSSL_memcpy(ret, a, sizeof(ret));
+  ecp_nistz256_from_mont(ret, ret);
+  if (!ExpectFieldElementsEqual(
+          t, "ecp_nistz256_from_mont(ret = A) was incorrect.", result, ret)) {
+    return false;
+  }
+
+  return true;
+}
+
+static bool TestPointAdd(FileTest *t) {
+  P256_POINT a, b;
+  P256_POINT_AFFINE result;
+  if (!GetFieldElement(t, a.X, "A.X") ||
+      !GetFieldElement(t, a.Y, "A.Y") ||
+      !GetFieldElement(t, a.Z, "A.Z") ||
+      !GetFieldElement(t, b.X, "B.X") ||
+      !GetFieldElement(t, b.Y, "B.Y") ||
+      !GetFieldElement(t, b.Z, "B.Z") ||
+      !GetFieldElement(t, result.X, "Result.X") ||
+      !GetFieldElement(t, result.Y, "Result.Y")) {
+    return false;
+  }
+
+  P256_POINT ret;
+  ecp_nistz256_point_add(&ret, &a, &b);
+  if (!ExpectPointsEqual(t, "ecp_nistz256_point_add(A, B) was incorrect.",
+                         &result, &ret)) {
+    return false;
+  }
+
+  ecp_nistz256_point_add(&ret, &b, &a);
+  if (!ExpectPointsEqual(t, "ecp_nistz256_point_add(B, A) was incorrect.",
+                         &result, &ret)) {
+    return false;
+  }
+
+  OPENSSL_memcpy(&ret, &a, sizeof(ret));
+  ecp_nistz256_point_add(&ret, &ret, &b);
+  if (!ExpectPointsEqual(t, "ecp_nistz256_point_add(ret = A, B) was incorrect.",
+                         &result, &ret)) {
+    return false;
+  }
+
+  OPENSSL_memcpy(&ret, &a, sizeof(ret));
+  ecp_nistz256_point_add(&ret, &b, &ret);
+  if (!ExpectPointsEqual(t, "ecp_nistz256_point_add(B, ret = A) was incorrect.",
+                         &result, &ret)) {
+    return false;
+  }
+
+  OPENSSL_memcpy(&ret, &b, sizeof(ret));
+  ecp_nistz256_point_add(&ret, &a, &ret);
+  if (!ExpectPointsEqual(t, "ecp_nistz256_point_add(ret = A, B) was incorrect.",
+                         &result, &ret)) {
+    return false;
+  }
+
+  OPENSSL_memcpy(&ret, &b, sizeof(ret));
+  ecp_nistz256_point_add(&ret, &ret, &a);
+  if (!ExpectPointsEqual(t, "ecp_nistz256_point_add(ret = B, A) was incorrect.",
+                         &result, &ret)) {
+    return false;
+  }
+
+  P256_POINT_AFFINE a_affine, b_affine, infinity;
+  OPENSSL_memset(&infinity, 0, sizeof(infinity));
+  if (!PointToAffine(&a_affine, &a) ||
+      !PointToAffine(&b_affine, &b)) {
+    return false;
+  }
+
+  // ecp_nistz256_point_add_affine does not work when a == b unless doubling the
+  // point at infinity.
+  if (OPENSSL_memcmp(&a_affine, &b_affine, sizeof(a_affine)) != 0 ||
+      OPENSSL_memcmp(&a_affine, &infinity, sizeof(a_affine)) == 0) {
+    ecp_nistz256_point_add_affine(&ret, &a, &b_affine);
+    if (!ExpectPointsEqual(t,
+                           "ecp_nistz256_point_add_affine(A, B) was incorrect.",
+                           &result, &ret)) {
+      return false;
+    }
+
+    OPENSSL_memcpy(&ret, &a, sizeof(ret));
+    ecp_nistz256_point_add_affine(&ret, &ret, &b_affine);
+    if (!ExpectPointsEqual(
+            t, "ecp_nistz256_point_add_affine(ret = A, B) was incorrect.",
+            &result, &ret)) {
+      return false;
+    }
+
+    ecp_nistz256_point_add_affine(&ret, &b, &a_affine);
+    if (!ExpectPointsEqual(t,
+                           "ecp_nistz256_point_add_affine(B, A) was incorrect.",
+                           &result, &ret)) {
+      return false;
+    }
+
+    OPENSSL_memcpy(&ret, &b, sizeof(ret));
+    ecp_nistz256_point_add_affine(&ret, &ret, &a_affine);
+    if (!ExpectPointsEqual(
+            t, "ecp_nistz256_point_add_affine(ret = B, A) was incorrect.",
+            &result, &ret)) {
+      return false;
+    }
+  }
+
+  if (OPENSSL_memcmp(&a, &b, sizeof(a)) == 0) {
+    ecp_nistz256_point_double(&ret, &a);
+    if (!ExpectPointsEqual(t, "ecp_nistz256_point_double(A) was incorrect.",
+                           &result, &ret)) {
+      return false;
+    }
+
+    ret = a;
+    ecp_nistz256_point_double(&ret, &ret);
+    if (!ExpectPointsEqual(
+            t, "In-place ecp_nistz256_point_double(A) was incorrect.", &result,
+            &ret)) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+int main(int argc, char **argv) {
+  if (argc != 2) {
+    fprintf(stderr, "%s TEST_FILE\n", argv[0]);
+    return 1;
+  }
+
+  if (!TestSelectW5() ||
+      !TestSelectW7()) {
+    return 1;
+  }
+
+  return FileTestMain([](FileTest *t, void *) -> bool {
+    if (t->GetParameter() == "Negate") {
+      return TestNegate(t);
+    }
+    if (t->GetParameter() == "MulMont") {
+      return TestMulMont(t);
+    }
+    if (t->GetParameter() == "FromMont") {
+      return TestFromMont(t);
+    }
+    if (t->GetParameter() == "PointAdd") {
+      return TestPointAdd(t);
+    }
+
+    t->PrintLine("Unknown test type: %s", t->GetParameter().c_str());
+    return false;
+  }, nullptr, argv[1]);
+}
+
+#else
+
+int main() {
+  printf("PASS\n");
+  return 0;
+}
+
+#endif
diff --git a/src/crypto/ec/p256-x86_64_tests.txt b/src/crypto/ec/p256-x86_64_tests.txt
new file mode 100644
index 0000000..a680850
--- /dev/null
+++ b/src/crypto/ec/p256-x86_64_tests.txt
@@ -0,0 +1,1405 @@
+# Negation tests.
+#
+# The following tests satisfy A = -B (mod P).
+
+Test = Negate
+A = 0000000000000000000000000000000000000000000000000000000000000000
+B = 0000000000000000000000000000000000000000000000000000000000000000
+
+Test = Negate
+A = 0000000000000000000000000000000000000000000000000000000000000001
+B = ffffffff00000001000000000000000000000000fffffffffffffffffffffffe
+
+Test = Negate
+A = 0000000000000000000000000000000000000000000000000000000000000003
+B = ffffffff00000001000000000000000000000000fffffffffffffffffffffffc
+
+Test = Negate
+A = 0000000000000000000000000000000000000000000000000000000000000007
+B = ffffffff00000001000000000000000000000000fffffffffffffffffffffff8
+
+Test = Negate
+A = 000000000000000000000000000000000000000000000000000000000000000f
+B = ffffffff00000001000000000000000000000000fffffffffffffffffffffff0
+
+Test = Negate
+A = 000000000000000000000000000000000000000000000000000000000000001f
+B = ffffffff00000001000000000000000000000000ffffffffffffffffffffffe0
+
+Test = Negate
+A = 000000000000000000000000000000000000000000000000000000000000003f
+B = ffffffff00000001000000000000000000000000ffffffffffffffffffffffc0
+
+Test = Negate
+A = 000000000000000000000000000000000000000000000000000000000000007f
+B = ffffffff00000001000000000000000000000000ffffffffffffffffffffff80
+
+Test = Negate
+A = 00000000000000000000000000000000000000000000000000000000000000ff
+B = ffffffff00000001000000000000000000000000ffffffffffffffffffffff00
+
+Test = Negate
+A = 00000000000000000000000000000000000000000000000000000000000001ff
+B = ffffffff00000001000000000000000000000000fffffffffffffffffffffe00
+
+Test = Negate
+A = 00000000000000000000000000000000000000000000000000000000000003ff
+B = ffffffff00000001000000000000000000000000fffffffffffffffffffffc00
+
+Test = Negate
+A = 00000000000000000000000000000000000000000000000000000000000007ff
+B = ffffffff00000001000000000000000000000000fffffffffffffffffffff800
+
+Test = Negate
+A = 0000000000000000000000000000000000000000000000000000000000000fff
+B = ffffffff00000001000000000000000000000000fffffffffffffffffffff000
+
+Test = Negate
+A = 0000000000000000000000000000000000000000000000000000000000001fff
+B = ffffffff00000001000000000000000000000000ffffffffffffffffffffe000
+
+Test = Negate
+A = 0000000000000000000000000000000000000000000000000000000000003fff
+B = ffffffff00000001000000000000000000000000ffffffffffffffffffffc000
+
+Test = Negate
+A = 0000000000000000000000000000000000000000000000000000000000007fff
+B = ffffffff00000001000000000000000000000000ffffffffffffffffffff8000
+
+Test = Negate
+A = 000000000000000000000000000000000000000000000000000000000000ffff
+B = ffffffff00000001000000000000000000000000ffffffffffffffffffff0000
+
+Test = Negate
+A = 000000000000000000000000000000000000000000000000000000000001ffff
+B = ffffffff00000001000000000000000000000000fffffffffffffffffffe0000
+
+Test = Negate
+A = 000000000000000000000000000000000000000000000000000000000003ffff
+B = ffffffff00000001000000000000000000000000fffffffffffffffffffc0000
+
+Test = Negate
+A = 000000000000000000000000000000000000000000000000000000000007ffff
+B = ffffffff00000001000000000000000000000000fffffffffffffffffff80000
+
+Test = Negate
+A = 00000000000000000000000000000000000000000000000000000000000fffff
+B = ffffffff00000001000000000000000000000000fffffffffffffffffff00000
+
+Test = Negate
+A = 00000000000000000000000000000000000000000000000000000000001fffff
+B = ffffffff00000001000000000000000000000000ffffffffffffffffffe00000
+
+Test = Negate
+A = 00000000000000000000000000000000000000000000000000000000003fffff
+B = ffffffff00000001000000000000000000000000ffffffffffffffffffc00000
+
+Test = Negate
+A = 00000000000000000000000000000000000000000000000000000000007fffff
+B = ffffffff00000001000000000000000000000000ffffffffffffffffff800000
+
+Test = Negate
+A = 0000000000000000000000000000000000000000000000000000000000ffffff
+B = ffffffff00000001000000000000000000000000ffffffffffffffffff000000
+
+Test = Negate
+A = 0000000000000000000000000000000000000000000000000000000001ffffff
+B = ffffffff00000001000000000000000000000000fffffffffffffffffe000000
+
+Test = Negate
+A = 0000000000000000000000000000000000000000000000000000000003ffffff
+B = ffffffff00000001000000000000000000000000fffffffffffffffffc000000
+
+Test = Negate
+A = 0000000000000000000000000000000000000000000000000000000007ffffff
+B = ffffffff00000001000000000000000000000000fffffffffffffffff8000000
+
+Test = Negate
+A = 000000000000000000000000000000000000000000000000000000000fffffff
+B = ffffffff00000001000000000000000000000000fffffffffffffffff0000000
+
+Test = Negate
+A = 000000000000000000000000000000000000000000000000000000001fffffff
+B = ffffffff00000001000000000000000000000000ffffffffffffffffe0000000
+
+Test = Negate
+A = 000000000000000000000000000000000000000000000000000000003fffffff
+B = ffffffff00000001000000000000000000000000ffffffffffffffffc0000000
+
+Test = Negate
+A = 000000000000000000000000000000000000000000000000000000007fffffff
+B = ffffffff00000001000000000000000000000000ffffffffffffffff80000000
+
+Test = Negate
+A = 00000000000000000000000000000000000000000000000000000000ffffffff
+B = ffffffff00000001000000000000000000000000ffffffffffffffff00000000
+
+Test = Negate
+A = 00000000000000000000000000000000000000000000000000000001ffffffff
+B = ffffffff00000001000000000000000000000000fffffffffffffffe00000000
+
+Test = Negate
+A = 00000000000000000000000000000000000000000000000000000003ffffffff
+B = ffffffff00000001000000000000000000000000fffffffffffffffc00000000
+
+Test = Negate
+A = 00000000000000000000000000000000000000000000000000000007ffffffff
+B = ffffffff00000001000000000000000000000000fffffffffffffff800000000
+
+Test = Negate
+A = 0000000000000000000000000000000000000000000000000000000fffffffff
+B = ffffffff00000001000000000000000000000000fffffffffffffff000000000
+
+Test = Negate
+A = 0000000000000000000000000000000000000000000000000000001fffffffff
+B = ffffffff00000001000000000000000000000000ffffffffffffffe000000000
+
+Test = Negate
+A = 0000000000000000000000000000000000000000000000000000003fffffffff
+B = ffffffff00000001000000000000000000000000ffffffffffffffc000000000
+
+Test = Negate
+A = 0000000000000000000000000000000000000000000000000000007fffffffff
+B = ffffffff00000001000000000000000000000000ffffffffffffff8000000000
+
+Test = Negate
+A = 000000000000000000000000000000000000000000000000000000ffffffffff
+B = ffffffff00000001000000000000000000000000ffffffffffffff0000000000
+
+Test = Negate
+A = 000000000000000000000000000000000000000000000000000001ffffffffff
+B = ffffffff00000001000000000000000000000000fffffffffffffe0000000000
+
+Test = Negate
+A = 000000000000000000000000000000000000000000000000000003ffffffffff
+B = ffffffff00000001000000000000000000000000fffffffffffffc0000000000
+
+Test = Negate
+A = 000000000000000000000000000000000000000000000000000007ffffffffff
+B = ffffffff00000001000000000000000000000000fffffffffffff80000000000
+
+Test = Negate
+A = 00000000000000000000000000000000000000000000000000000fffffffffff
+B = ffffffff00000001000000000000000000000000fffffffffffff00000000000
+
+Test = Negate
+A = 00000000000000000000000000000000000000000000000000001fffffffffff
+B = ffffffff00000001000000000000000000000000ffffffffffffe00000000000
+
+Test = Negate
+A = 00000000000000000000000000000000000000000000000000003fffffffffff
+B = ffffffff00000001000000000000000000000000ffffffffffffc00000000000
+
+Test = Negate
+A = 00000000000000000000000000000000000000000000000000007fffffffffff
+B = ffffffff00000001000000000000000000000000ffffffffffff800000000000
+
+Test = Negate
+A = 0000000000000000000000000000000000000000000000000000ffffffffffff
+B = ffffffff00000001000000000000000000000000ffffffffffff000000000000
+
+Test = Negate
+A = 0000000000000000000000000000000000000000000000000001ffffffffffff
+B = ffffffff00000001000000000000000000000000fffffffffffe000000000000
+
+Test = Negate
+A = 0000000000000000000000000000000000000000000000000003ffffffffffff
+B = ffffffff00000001000000000000000000000000fffffffffffc000000000000
+
+Test = Negate
+A = 0000000000000000000000000000000000000000000000000007ffffffffffff
+B = ffffffff00000001000000000000000000000000fffffffffff8000000000000
+
+Test = Negate
+A = 000000000000000000000000000000000000000000000000000fffffffffffff
+B = ffffffff00000001000000000000000000000000fffffffffff0000000000000
+
+Test = Negate
+A = 000000000000000000000000000000000000000000000000001fffffffffffff
+B = ffffffff00000001000000000000000000000000ffffffffffe0000000000000
+
+Test = Negate
+A = 000000000000000000000000000000000000000000000000003fffffffffffff
+B = ffffffff00000001000000000000000000000000ffffffffffc0000000000000
+
+Test = Negate
+A = 000000000000000000000000000000000000000000000000007fffffffffffff
+B = ffffffff00000001000000000000000000000000ffffffffff80000000000000
+
+Test = Negate
+A = 00000000000000000000000000000000000000000000000000ffffffffffffff
+B = ffffffff00000001000000000000000000000000ffffffffff00000000000000
+
+Test = Negate
+A = 00000000000000000000000000000000000000000000000001ffffffffffffff
+B = ffffffff00000001000000000000000000000000fffffffffe00000000000000
+
+Test = Negate
+A = 00000000000000000000000000000000000000000000000003ffffffffffffff
+B = ffffffff00000001000000000000000000000000fffffffffc00000000000000
+
+Test = Negate
+A = 00000000000000000000000000000000000000000000000007ffffffffffffff
+B = ffffffff00000001000000000000000000000000fffffffff800000000000000
+
+Test = Negate
+A = 0000000000000000000000000000000000000000000000000fffffffffffffff
+B = ffffffff00000001000000000000000000000000fffffffff000000000000000
+
+Test = Negate
+A = 0000000000000000000000000000000000000000000000001fffffffffffffff
+B = ffffffff00000001000000000000000000000000ffffffffe000000000000000
+
+Test = Negate
+A = 0000000000000000000000000000000000000000000000003fffffffffffffff
+B = ffffffff00000001000000000000000000000000ffffffffc000000000000000
+
+Test = Negate
+A = 0000000000000000000000000000000000000000000000007fffffffffffffff
+B = ffffffff00000001000000000000000000000000ffffffff8000000000000000
+
+Test = Negate
+A = 000000000000000000000000000000000000000000000000ffffffffffffffff
+B = ffffffff00000001000000000000000000000000ffffffff0000000000000000
+
+Test = Negate
+A = 000000000000000000000000000000000000000000000001ffffffffffffffff
+B = ffffffff00000001000000000000000000000000fffffffe0000000000000000
+
+Test = Negate
+A = 000000000000000000000000000000000000000000000003ffffffffffffffff
+B = ffffffff00000001000000000000000000000000fffffffc0000000000000000
+
+Test = Negate
+A = 000000000000000000000000000000000000000000000007ffffffffffffffff
+B = ffffffff00000001000000000000000000000000fffffff80000000000000000
+
+Test = Negate
+A = 00000000000000000000000000000000000000000000000fffffffffffffffff
+B = ffffffff00000001000000000000000000000000fffffff00000000000000000
+
+Test = Negate
+A = 00000000000000000000000000000000000000000000001fffffffffffffffff
+B = ffffffff00000001000000000000000000000000ffffffe00000000000000000
+
+Test = Negate
+A = 00000000000000000000000000000000000000000000003fffffffffffffffff
+B = ffffffff00000001000000000000000000000000ffffffc00000000000000000
+
+Test = Negate
+A = 00000000000000000000000000000000000000000000007fffffffffffffffff
+B = ffffffff00000001000000000000000000000000ffffff800000000000000000
+
+Test = Negate
+A = 0000000000000000000000000000000000000000000000ffffffffffffffffff
+B = ffffffff00000001000000000000000000000000ffffff000000000000000000
+
+Test = Negate
+A = 0000000000000000000000000000000000000000000001ffffffffffffffffff
+B = ffffffff00000001000000000000000000000000fffffe000000000000000000
+
+Test = Negate
+A = 0000000000000000000000000000000000000000000003ffffffffffffffffff
+B = ffffffff00000001000000000000000000000000fffffc000000000000000000
+
+Test = Negate
+A = 0000000000000000000000000000000000000000000007ffffffffffffffffff
+B = ffffffff00000001000000000000000000000000fffff8000000000000000000
+
+Test = Negate
+A = 000000000000000000000000000000000000000000000fffffffffffffffffff
+B = ffffffff00000001000000000000000000000000fffff0000000000000000000
+
+Test = Negate
+A = 000000000000000000000000000000000000000000001fffffffffffffffffff
+B = ffffffff00000001000000000000000000000000ffffe0000000000000000000
+
+Test = Negate
+A = 000000000000000000000000000000000000000000003fffffffffffffffffff
+B = ffffffff00000001000000000000000000000000ffffc0000000000000000000
+
+Test = Negate
+A = 000000000000000000000000000000000000000000007fffffffffffffffffff
+B = ffffffff00000001000000000000000000000000ffff80000000000000000000
+
+Test = Negate
+A = 00000000000000000000000000000000000000000000ffffffffffffffffffff
+B = ffffffff00000001000000000000000000000000ffff00000000000000000000
+
+Test = Negate
+A = 00000000000000000000000000000000000000000001ffffffffffffffffffff
+B = ffffffff00000001000000000000000000000000fffe00000000000000000000
+
+Test = Negate
+A = 00000000000000000000000000000000000000000003ffffffffffffffffffff
+B = ffffffff00000001000000000000000000000000fffc00000000000000000000
+
+Test = Negate
+A = 00000000000000000000000000000000000000000007ffffffffffffffffffff
+B = ffffffff00000001000000000000000000000000fff800000000000000000000
+
+Test = Negate
+A = 0000000000000000000000000000000000000000000fffffffffffffffffffff
+B = ffffffff00000001000000000000000000000000fff000000000000000000000
+
+Test = Negate
+A = 0000000000000000000000000000000000000000001fffffffffffffffffffff
+B = ffffffff00000001000000000000000000000000ffe000000000000000000000
+
+Test = Negate
+A = 0000000000000000000000000000000000000000003fffffffffffffffffffff
+B = ffffffff00000001000000000000000000000000ffc000000000000000000000
+
+Test = Negate
+A = 0000000000000000000000000000000000000000007fffffffffffffffffffff
+B = ffffffff00000001000000000000000000000000ff8000000000000000000000
+
+Test = Negate
+A = 000000000000000000000000000000000000000000ffffffffffffffffffffff
+B = ffffffff00000001000000000000000000000000ff0000000000000000000000
+
+Test = Negate
+A = 000000000000000000000000000000000000000001ffffffffffffffffffffff
+B = ffffffff00000001000000000000000000000000fe0000000000000000000000
+
+Test = Negate
+A = 000000000000000000000000000000000000000003ffffffffffffffffffffff
+B = ffffffff00000001000000000000000000000000fc0000000000000000000000
+
+Test = Negate
+A = 000000000000000000000000000000000000000007ffffffffffffffffffffff
+B = ffffffff00000001000000000000000000000000f80000000000000000000000
+
+Test = Negate
+A = 00000000000000000000000000000000000000000fffffffffffffffffffffff
+B = ffffffff00000001000000000000000000000000f00000000000000000000000
+
+Test = Negate
+A = 00000000000000000000000000000000000000001fffffffffffffffffffffff
+B = ffffffff00000001000000000000000000000000e00000000000000000000000
+
+Test = Negate
+A = 00000000000000000000000000000000000000003fffffffffffffffffffffff
+B = ffffffff00000001000000000000000000000000c00000000000000000000000
+
+Test = Negate
+A = 00000000000000000000000000000000000000007fffffffffffffffffffffff
+B = ffffffff00000001000000000000000000000000800000000000000000000000
+
+Test = Negate
+A = 0000000000000000000000000000000000000000ffffffffffffffffffffffff
+B = ffffffff00000001000000000000000000000000000000000000000000000000
+
+Test = Negate
+A = 0000000000000000000000000000000000000001ffffffffffffffffffffffff
+B = ffffffff00000000ffffffffffffffffffffffff000000000000000000000000
+
+Test = Negate
+A = 0000000000000000000000000000000000000003ffffffffffffffffffffffff
+B = ffffffff00000000fffffffffffffffffffffffd000000000000000000000000
+
+Test = Negate
+A = 0000000000000000000000000000000000000007ffffffffffffffffffffffff
+B = ffffffff00000000fffffffffffffffffffffff9000000000000000000000000
+
+Test = Negate
+A = 000000000000000000000000000000000000000fffffffffffffffffffffffff
+B = ffffffff00000000fffffffffffffffffffffff1000000000000000000000000
+
+Test = Negate
+A = 000000000000000000000000000000000000001fffffffffffffffffffffffff
+B = ffffffff00000000ffffffffffffffffffffffe1000000000000000000000000
+
+Test = Negate
+A = 000000000000000000000000000000000000003fffffffffffffffffffffffff
+B = ffffffff00000000ffffffffffffffffffffffc1000000000000000000000000
+
+Test = Negate
+A = 000000000000000000000000000000000000007fffffffffffffffffffffffff
+B = ffffffff00000000ffffffffffffffffffffff81000000000000000000000000
+
+Test = Negate
+A = 00000000000000000000000000000000000000ffffffffffffffffffffffffff
+B = ffffffff00000000ffffffffffffffffffffff01000000000000000000000000
+
+Test = Negate
+A = 00000000000000000000000000000000000001ffffffffffffffffffffffffff
+B = ffffffff00000000fffffffffffffffffffffe01000000000000000000000000
+
+Test = Negate
+A = 00000000000000000000000000000000000003ffffffffffffffffffffffffff
+B = ffffffff00000000fffffffffffffffffffffc01000000000000000000000000
+
+Test = Negate
+A = 00000000000000000000000000000000000007ffffffffffffffffffffffffff
+B = ffffffff00000000fffffffffffffffffffff801000000000000000000000000
+
+Test = Negate
+A = 0000000000000000000000000000000000000fffffffffffffffffffffffffff
+B = ffffffff00000000fffffffffffffffffffff001000000000000000000000000
+
+Test = Negate
+A = 0000000000000000000000000000000000001fffffffffffffffffffffffffff
+B = ffffffff00000000ffffffffffffffffffffe001000000000000000000000000
+
+Test = Negate
+A = 0000000000000000000000000000000000003fffffffffffffffffffffffffff
+B = ffffffff00000000ffffffffffffffffffffc001000000000000000000000000
+
+Test = Negate
+A = 0000000000000000000000000000000000007fffffffffffffffffffffffffff
+B = ffffffff00000000ffffffffffffffffffff8001000000000000000000000000
+
+Test = Negate
+A = 000000000000000000000000000000000000ffffffffffffffffffffffffffff
+B = ffffffff00000000ffffffffffffffffffff0001000000000000000000000000
+
+Test = Negate
+A = 000000000000000000000000000000000001ffffffffffffffffffffffffffff
+B = ffffffff00000000fffffffffffffffffffe0001000000000000000000000000
+
+Test = Negate
+A = 000000000000000000000000000000000003ffffffffffffffffffffffffffff
+B = ffffffff00000000fffffffffffffffffffc0001000000000000000000000000
+
+Test = Negate
+A = 000000000000000000000000000000000007ffffffffffffffffffffffffffff
+B = ffffffff00000000fffffffffffffffffff80001000000000000000000000000
+
+Test = Negate
+A = 00000000000000000000000000000000000fffffffffffffffffffffffffffff
+B = ffffffff00000000fffffffffffffffffff00001000000000000000000000000
+
+Test = Negate
+A = 00000000000000000000000000000000001fffffffffffffffffffffffffffff
+B = ffffffff00000000ffffffffffffffffffe00001000000000000000000000000
+
+Test = Negate
+A = 00000000000000000000000000000000003fffffffffffffffffffffffffffff
+B = ffffffff00000000ffffffffffffffffffc00001000000000000000000000000
+
+Test = Negate
+A = 00000000000000000000000000000000007fffffffffffffffffffffffffffff
+B = ffffffff00000000ffffffffffffffffff800001000000000000000000000000
+
+Test = Negate
+A = 0000000000000000000000000000000000ffffffffffffffffffffffffffffff
+B = ffffffff00000000ffffffffffffffffff000001000000000000000000000000
+
+Test = Negate
+A = 0000000000000000000000000000000001ffffffffffffffffffffffffffffff
+B = ffffffff00000000fffffffffffffffffe000001000000000000000000000000
+
+Test = Negate
+A = 0000000000000000000000000000000003ffffffffffffffffffffffffffffff
+B = ffffffff00000000fffffffffffffffffc000001000000000000000000000000
+
+Test = Negate
+A = 0000000000000000000000000000000007ffffffffffffffffffffffffffffff
+B = ffffffff00000000fffffffffffffffff8000001000000000000000000000000
+
+Test = Negate
+A = 000000000000000000000000000000000fffffffffffffffffffffffffffffff
+B = ffffffff00000000fffffffffffffffff0000001000000000000000000000000
+
+Test = Negate
+A = 000000000000000000000000000000001fffffffffffffffffffffffffffffff
+B = ffffffff00000000ffffffffffffffffe0000001000000000000000000000000
+
+Test = Negate
+A = 000000000000000000000000000000003fffffffffffffffffffffffffffffff
+B = ffffffff00000000ffffffffffffffffc0000001000000000000000000000000
+
+Test = Negate
+A = 000000000000000000000000000000007fffffffffffffffffffffffffffffff
+B = ffffffff00000000ffffffffffffffff80000001000000000000000000000000
+
+Test = Negate
+A = 00000000000000000000000000000000ffffffffffffffffffffffffffffffff
+B = ffffffff00000000ffffffffffffffff00000001000000000000000000000000
+
+Test = Negate
+A = 00000000000000000000000000000001ffffffffffffffffffffffffffffffff
+B = ffffffff00000000fffffffffffffffe00000001000000000000000000000000
+
+Test = Negate
+A = 00000000000000000000000000000003ffffffffffffffffffffffffffffffff
+B = ffffffff00000000fffffffffffffffc00000001000000000000000000000000
+
+Test = Negate
+A = 00000000000000000000000000000007ffffffffffffffffffffffffffffffff
+B = ffffffff00000000fffffffffffffff800000001000000000000000000000000
+
+Test = Negate
+A = 0000000000000000000000000000000fffffffffffffffffffffffffffffffff
+B = ffffffff00000000fffffffffffffff000000001000000000000000000000000
+
+Test = Negate
+A = 0000000000000000000000000000001fffffffffffffffffffffffffffffffff
+B = ffffffff00000000ffffffffffffffe000000001000000000000000000000000
+
+Test = Negate
+A = 0000000000000000000000000000003fffffffffffffffffffffffffffffffff
+B = ffffffff00000000ffffffffffffffc000000001000000000000000000000000
+
+Test = Negate
+A = 0000000000000000000000000000007fffffffffffffffffffffffffffffffff
+B = ffffffff00000000ffffffffffffff8000000001000000000000000000000000
+
+Test = Negate
+A = 000000000000000000000000000000ffffffffffffffffffffffffffffffffff
+B = ffffffff00000000ffffffffffffff0000000001000000000000000000000000
+
+Test = Negate
+A = 000000000000000000000000000001ffffffffffffffffffffffffffffffffff
+B = ffffffff00000000fffffffffffffe0000000001000000000000000000000000
+
+Test = Negate
+A = 000000000000000000000000000003ffffffffffffffffffffffffffffffffff
+B = ffffffff00000000fffffffffffffc0000000001000000000000000000000000
+
+Test = Negate
+A = 000000000000000000000000000007ffffffffffffffffffffffffffffffffff
+B = ffffffff00000000fffffffffffff80000000001000000000000000000000000
+
+Test = Negate
+A = 00000000000000000000000000000fffffffffffffffffffffffffffffffffff
+B = ffffffff00000000fffffffffffff00000000001000000000000000000000000
+
+Test = Negate
+A = 00000000000000000000000000001fffffffffffffffffffffffffffffffffff
+B = ffffffff00000000ffffffffffffe00000000001000000000000000000000000
+
+Test = Negate
+A = 00000000000000000000000000003fffffffffffffffffffffffffffffffffff
+B = ffffffff00000000ffffffffffffc00000000001000000000000000000000000
+
+Test = Negate
+A = 00000000000000000000000000007fffffffffffffffffffffffffffffffffff
+B = ffffffff00000000ffffffffffff800000000001000000000000000000000000
+
+Test = Negate
+A = 0000000000000000000000000000ffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000ffffffffffff000000000001000000000000000000000000
+
+Test = Negate
+A = 0000000000000000000000000001ffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000fffffffffffe000000000001000000000000000000000000
+
+Test = Negate
+A = 0000000000000000000000000003ffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000fffffffffffc000000000001000000000000000000000000
+
+Test = Negate
+A = 0000000000000000000000000007ffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000fffffffffff8000000000001000000000000000000000000
+
+Test = Negate
+A = 000000000000000000000000000fffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000fffffffffff0000000000001000000000000000000000000
+
+Test = Negate
+A = 000000000000000000000000001fffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000ffffffffffe0000000000001000000000000000000000000
+
+Test = Negate
+A = 000000000000000000000000003fffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000ffffffffffc0000000000001000000000000000000000000
+
+Test = Negate
+A = 000000000000000000000000007fffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000ffffffffff80000000000001000000000000000000000000
+
+Test = Negate
+A = 00000000000000000000000000ffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000ffffffffff00000000000001000000000000000000000000
+
+Test = Negate
+A = 00000000000000000000000001ffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000fffffffffe00000000000001000000000000000000000000
+
+Test = Negate
+A = 00000000000000000000000003ffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000fffffffffc00000000000001000000000000000000000000
+
+Test = Negate
+A = 00000000000000000000000007ffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000fffffffff800000000000001000000000000000000000000
+
+Test = Negate
+A = 0000000000000000000000000fffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000fffffffff000000000000001000000000000000000000000
+
+Test = Negate
+A = 0000000000000000000000001fffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000ffffffffe000000000000001000000000000000000000000
+
+Test = Negate
+A = 0000000000000000000000003fffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000ffffffffc000000000000001000000000000000000000000
+
+Test = Negate
+A = 0000000000000000000000007fffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000ffffffff8000000000000001000000000000000000000000
+
+Test = Negate
+A = 000000000000000000000000ffffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000ffffffff0000000000000001000000000000000000000000
+
+Test = Negate
+A = 000000000000000000000001ffffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000fffffffe0000000000000001000000000000000000000000
+
+Test = Negate
+A = 000000000000000000000003ffffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000fffffffc0000000000000001000000000000000000000000
+
+Test = Negate
+A = 000000000000000000000007ffffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000fffffff80000000000000001000000000000000000000000
+
+Test = Negate
+A = 00000000000000000000000fffffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000fffffff00000000000000001000000000000000000000000
+
+Test = Negate
+A = 00000000000000000000001fffffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000ffffffe00000000000000001000000000000000000000000
+
+Test = Negate
+A = 00000000000000000000003fffffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000ffffffc00000000000000001000000000000000000000000
+
+Test = Negate
+A = 00000000000000000000007fffffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000ffffff800000000000000001000000000000000000000000
+
+Test = Negate
+A = 0000000000000000000000ffffffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000ffffff000000000000000001000000000000000000000000
+
+Test = Negate
+A = 0000000000000000000001ffffffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000fffffe000000000000000001000000000000000000000000
+
+Test = Negate
+A = 0000000000000000000003ffffffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000fffffc000000000000000001000000000000000000000000
+
+Test = Negate
+A = 0000000000000000000007ffffffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000fffff8000000000000000001000000000000000000000000
+
+Test = Negate
+A = 000000000000000000000fffffffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000fffff0000000000000000001000000000000000000000000
+
+Test = Negate
+A = 000000000000000000001fffffffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000ffffe0000000000000000001000000000000000000000000
+
+Test = Negate
+A = 000000000000000000003fffffffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000ffffc0000000000000000001000000000000000000000000
+
+Test = Negate
+A = 000000000000000000007fffffffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000ffff80000000000000000001000000000000000000000000
+
+Test = Negate
+A = 00000000000000000000ffffffffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000ffff00000000000000000001000000000000000000000000
+
+Test = Negate
+A = 00000000000000000001ffffffffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000fffe00000000000000000001000000000000000000000000
+
+Test = Negate
+A = 00000000000000000003ffffffffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000fffc00000000000000000001000000000000000000000000
+
+Test = Negate
+A = 00000000000000000007ffffffffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000fff800000000000000000001000000000000000000000000
+
+Test = Negate
+A = 0000000000000000000fffffffffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000fff000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 0000000000000000001fffffffffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000ffe000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 0000000000000000003fffffffffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000ffc000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 0000000000000000007fffffffffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000ff8000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 000000000000000000ffffffffffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000ff0000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 000000000000000001ffffffffffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000fe0000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 000000000000000003ffffffffffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000fc0000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 000000000000000007ffffffffffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000f80000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 00000000000000000fffffffffffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000f00000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 00000000000000001fffffffffffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000e00000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 00000000000000003fffffffffffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000c00000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 00000000000000007fffffffffffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000800000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffff
+B = ffffffff00000000000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 0000000000000001ffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffeffffffff000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 0000000000000003ffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffefffffffd000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 0000000000000007ffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffefffffff9000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 000000000000000fffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffefffffff1000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 000000000000001fffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffeffffffe1000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 000000000000003fffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffeffffffc1000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 000000000000007fffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffeffffff81000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 00000000000000ffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffeffffff01000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 00000000000001ffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffefffffe01000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 00000000000003ffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffefffffc01000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 00000000000007ffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffefffff801000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 0000000000000fffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffefffff001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 0000000000001fffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffeffffe001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 0000000000003fffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffeffffc001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 0000000000007fffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffeffff8001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffeffff0001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 000000000001ffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffefffe0001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 000000000003ffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffefffc0001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 000000000007ffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffefff80001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 00000000000fffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffefff00001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 00000000001fffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffeffe00001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 00000000003fffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffeffc00001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 00000000007fffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffeff800001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 0000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffeff000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 0000000001ffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffefe000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 0000000003ffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffefc000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 0000000007ffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffef8000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffef0000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 000000001fffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffee0000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 000000003fffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffec0000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffe80000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffe00000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 00000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffd00000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 00000003ffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffffb00000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 00000007ffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffff700000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 0000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = ffffffef00000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 0000001fffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = ffffffdf00000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 0000003fffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = ffffffbf00000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 0000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = ffffff7f00000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffeff00000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffdff00000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 000003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffffbff00000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 000007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffff7ff00000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = ffffefff00000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 00001fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = ffffdfff00000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 00003fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = ffffbfff00000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 00007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = ffff7fff00000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 0000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffeffff00000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 0001ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffdffff00000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 0003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fffbffff00000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 0007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fff7ffff00000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = ffefffff00000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 001fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = ffdfffff00000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 003fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = ffbfffff00000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = ff7fffff00000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = feffffff00000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 01ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fdffffff00000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = fbffffff00000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = f7ffffff00000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = efffffff00000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = dfffffff00000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = bfffffff00000001000000000000000000000001000000000000000000000000
+
+Test = Negate
+A = 7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
+B = 7fffffff00000001000000000000000000000001000000000000000000000000
+
+
+# Montgomery multiplication tests.
+#
+# The following tests satisfy A * B * 2^-256 = Result (mod P).
+
+Test = MulMont
+A = e762f095431b732ce33c4f4a6f41068ff7f78e37aad940166667d193bfc58039
+B = a43df383dd5df14d7c16737b781261473f9ffb76ee29562fbb5e5d390b882fb5
+Result = cf637a47dc5fb82aed80ed4c66b682a94bf0b76a2878acf483aad86c0db7cc19
+
+Test = MulMont
+A = 2e519e860cb3f8f32fc351861b022e9fc7bb073ca8767efb3d1027dd32a38bcb
+B = 466d035e4238d6a30613dd227b0daeacd6a8634fa60f5150d42dd20601794be4
+Result = 486e1abe0f79e107f8beca6e4653872f63a24dedb005def6aae75a2a51e73c76
+
+Test = MulMont
+A = 1763859541b5e2edee019c66699d0e12e349e6ee586d618ac20c679d2fa8cadd
+B = 56125872de888c5656dec17fbf9678d915ff9815da897df81f03fd9aa4f93654
+Result = 71ce584135a0aba8222ca0021bcefac5811d19100627f96726cf195ff2ac4aad
+
+Test = MulMont
+A = ea3be6295098e4995b93267dbd58f24fd9c18f7e89e9e5aeafdc34ca54e8ec4e
+B = 2735658978d620a4f76bffe94d9cd7d683b3bfd533aa6bb2b94f52122e83f7fc
+Result = 362f7ab3a12effe9bad069b84a7df5f108503c2457f83ddb05b57f19e6457989
+
+Test = MulMont
+A = f607f087ec5015b533df8802771dc60ef1487d86ce405e5bb18f8f06ca483f13
+B = 73ac532eb3f2356a96e668f167a1626a0f7b1fd2cd84ba6deeebd01af1d3897d
+Result = ce7045e69da157e62fb42508880f5734531c36948c704aedec42afa75cb9c2eb
+
+Test = MulMont
+A = 80ce8eb07601fd8e19ba08a9d21081b0324fd459f9c489ac7c871d406133c813
+B = 7ad28cef45b137ecc5426a44b6bce6d4329f5bd2b5e55d46edd5fbb295678a1b
+Result = 04068f8461d17b34c8d9c3eecf61dbaef9cd5a952bbcd9f84bb2044f2439da60
+
+Test = MulMont
+A = 17429caf63689e143c8ca77df69a11cbc02c272daadd75a66f3fa5f88828367e
+B = 5725bedc56a4b16e0f0ae55fa0beb1fdf3ff132ccb9803bab678d4ac7915d88c
+Result = a1da0fa68947e906287ea164b213bc7e80649b2ac3f97f203549d3b270de05a1
+
+Test = MulMont
+A = e7da43c0e0fa7adeb972901bef3160c848e9651bfc810968afdb0cd598830370
+B = 08f03060cac1d3c15eea69623d5fb01da465b209e3e5e90fbb51053a1c5700eb
+Result = cda4ffaf8b1c3ac0d44bae6ea5154de11e14931747a65396531302c0cb1ed537
+
+Test = MulMont
+A = c7375c2b6666713cb33cfb741268fd3ccf703bcaa0b9b27f84a8cb970655da9c
+B = b0796ee4bb88b9bad895d9c25c34f43a3941e9585bda8e86ff4fa0bbb391ac61
+Result = fd1d557a9fb0031e462121bf7ca31804acfcfce822bb6ee6631b54c575380617
+
+Test = MulMont
+A = 72a87b13eb4a2e248214aa591c586df65790f9f750a1641b47581a4ee09be7e9
+B = 38e602844b9aaf737e8b1261110b86ba22806ccbbbfdc5305075429d7ce4f002
+Result = cb2d63ee829de8801759f0229d4c07139bacd804f0c815d35004747c65bffdf2
+
+# Test cases where A == B to test squaring.
+
+Test = MulMont
+A = 0000000000000000000000000000000000000000000000000000000000000000
+B = 0000000000000000000000000000000000000000000000000000000000000000
+Result = 0000000000000000000000000000000000000000000000000000000000000000
+
+Test = MulMont
+A = 579e9ce1ad00639b8b64d49546ff4f9c30ad12eaebe9e2ed91e97d55c3c5d847
+B = 579e9ce1ad00639b8b64d49546ff4f9c30ad12eaebe9e2ed91e97d55c3c5d847
+Result = 10c5e60c2d480d5d53f50c24fb771fd2dec208db04624dfd05d2847ca173a9aa
+
+Test = MulMont
+A = 501947209b121bcdedce8c895ee2ba310f2e561e97998eb8f3b99d1f924f36c1
+B = 501947209b121bcdedce8c895ee2ba310f2e561e97998eb8f3b99d1f924f36c1
+Result = 54d6d64566619b215910f1b9e467b22ef205ca3aaad37a00fcbd906357f9c179
+
+Test = MulMont
+A = e84ab9202722498baa2c9158f40d47b1f03df4d13976b0aec916a937e99f3a89
+B = e84ab9202722498baa2c9158f40d47b1f03df4d13976b0aec916a937e99f3a89
+Result = 9af01fa6947a60679b6f87efe9b6fba97baf5d55a19d5e91dd5da1da10caeebf
+
+Test = MulMont
+A = add67c61d8479570f45a59e9b04974f970b0c4c6c046056fea1bdf3f0e7d3152
+B = add67c61d8479570f45a59e9b04974f970b0c4c6c046056fea1bdf3f0e7d3152
+Result = c0c68b4327e3fe7e0522167a54b25aaa6f76085ce4f6550479c89f3f1c39dd18
+
+Test = MulMont
+A = 434ef0db5640a3ea63125f815bc3cb3c92d06dbc3b5cb484e01b5247b3b4bfe5
+B = 434ef0db5640a3ea63125f815bc3cb3c92d06dbc3b5cb484e01b5247b3b4bfe5
+Result = b5105d16b858279247ed31362a90260978d64e0492e84bffa7a0e13ee1541544
+
+Test = MulMont
+A = b1db42aa4b259d9c6104599aff622114f10c327d02c5640b74cf1742adff332d
+B = b1db42aa4b259d9c6104599aff622114f10c327d02c5640b74cf1742adff332d
+Result = 0c175e7f96fc62059864c561d99a8d90978c72757ba305cd8862ed6a5fadad59
+
+Test = MulMont
+A = 7610271796be25416b652badd3119938974b20d4fc92244aea76d23b80d178f0
+B = 7610271796be25416b652badd3119938974b20d4fc92244aea76d23b80d178f0
+Result = 67d76e4a7c8355bb362481a76a63b365ad79767cc672b174130e833d41ca5709
+
+Test = MulMont
+A = 3480d60b0ccafca89c86f22f78380cead81310241f27a815e6fd21c2060caed8
+B = 3480d60b0ccafca89c86f22f78380cead81310241f27a815e6fd21c2060caed8
+Result = 68bfb2652d3bf03d17b20b2c52c68e847b0006047ba4ea81d4b85af2e0a21f72
+
+Test = MulMont
+A = 8ad6fa8bf3fe56ece1d0970636c1429ed5dfc2441c3194928a6348b69490b537
+B = 8ad6fa8bf3fe56ece1d0970636c1429ed5dfc2441c3194928a6348b69490b537
+Result = f5cdccf29e09928722137fb5a5ec035d7f39580838e19b892a7a972866330318
+
+Test = MulMont
+A = 71c328ce472ae74b5028b21f9d1997e0f7dbcee979a8f9fdecfa5d37d359c835
+B = 71c328ce472ae74b5028b21f9d1997e0f7dbcee979a8f9fdecfa5d37d359c835
+Result = c3472fafd01fc3ed93a91ab65411cb852bd5839603a02ca6cdfbadcb9ac474a0
+
+
+# Montgomery conversion tests.
+#
+# The following tests satisfy A * 2^-256 = Result (mod P).
+
+Test = FromMont
+A = 0585a3dada9bb283fd8db4fc46c106d28f95b8cf159a405891196dbb9ce0b5cf
+Result = d198d054d25a069c40cdeeb968a5562a67c3ef659297169e4be872f234897dc0
+
+Test = FromMont
+A = 9ff49a4a3f810fd34ca6f37fb1b3c40e61bc0492227e91e41cbe06bd58ba65b8
+Result = 326a061b2047d9ba4eddaba9b1fe253d5b2a24e268e3f8810767bef8cda07643
+
+Test = FromMont
+A = 05a69f8f646494be65affbd44d0536ca098d6f3640e80b5e48764ab78928cf58
+Result = 5a6f9c7025d4063480c400fe6f271cf3a3d2c43f9e1ceac21a88208c28329731
+
+Test = FromMont
+A = 256481a9e52d692719330a6f1208d9eca4ddd919aee06e234cbbde77d245501b
+Result = fe9fc86a2ff61a0c981d5e86c5472248e071e9639521c5be43947bfffc7d5858
+
+Test = FromMont
+A = 2062ef333cadefc36ced52a2ea7e4215b1fca29283baa1e3be76e321f1b213f0
+Result = 961ce39c3bf1d699b4b61ded8a5beae6eb6185d21f1df435b079b1f6a79dc738
+
+Test = FromMont
+A = 97241c3651a8f9d2fc02730f15c3e09e48d2e645cfe927385cb81d3f454414fb
+Result = 2114225803efe7b6c7fbb290cb946da4e78697aad5624c2d3fe9fb568460b93c
+
+Test = FromMont
+A = 1aae0ad2c8ac988e11beda32ca7257f4d4de41f4b74452fa46f0a3bafb39262a
+Result = 77c884131c34a2c3acce8a69dc5cf55987b7999c70586a9ef3c0dfb634900296
+
+Test = FromMont
+A = 034de033e2d38cf8bec8a994414b64a2fce7c83c5d81efc3d21448225071e85d
+Result = 984fecbde84f393133fb602777b4395c56449d2cbbd7d8ae428b2ee6f82a2956
+
+Test = FromMont
+A = d2b296c2004b2761b6781311c924cbf5ff56dcc0900ed5cd24f5dd2e07f32633
+Result = ddcff6e031b859a814ce8f37b71c10cd5fb642af54af72deabb95adcb99307b1
+
+Test = FromMont
+A = 8f525e6af50a62fc176dec75bdf48f70ba8ab97323ba78c643ef07f6457ba070
+Result = 8fa95d57aae2fff79045654501478f7a394b27b8b54113a25ac74662606f767c
+
+
+# Point adding tests.
+#
+# The following tests satisfy Result = A + B, where Result is in affine
+# coordinates and A and B are in Jacobian coordinates in the Montgomery domain.
+
+# ∞ + ∞ = ∞.
+Test = PointAdd
+A.X = 0000000000000000000000000000000000000000000000000000000000000000
+A.Y = 0000000000000000000000000000000000000000000000000000000000000000
+A.Z = 0000000000000000000000000000000000000000000000000000000000000000
+B.X = 0000000000000000000000000000000000000000000000000000000000000000
+B.Y = 0000000000000000000000000000000000000000000000000000000000000000
+B.Z = 0000000000000000000000000000000000000000000000000000000000000000
+Result.X = 0000000000000000000000000000000000000000000000000000000000000000
+Result.Y = 0000000000000000000000000000000000000000000000000000000000000000
+
+# ∞ + ∞ = ∞, with an alternate representation of ∞.
+Test = PointAdd
+A.X = 2b11cb945c8cf152ffa4c9c2b1c965b019b35d0b7626919ef0ae6cb9d232f8af
+A.Y = 6d333da42e30f7011245b6281015ded14e0f100968e758a1b6c3c083afc14ea0
+A.Z = 0000000000000000000000000000000000000000000000000000000000000000
+B.X = 2b11cb945c8cf152ffa4c9c2b1c965b019b35d0b7626919ef0ae6cb9d232f8af
+B.Y = 6d333da42e30f7011245b6281015ded14e0f100968e758a1b6c3c083afc14ea0
+B.Z = 0000000000000000000000000000000000000000000000000000000000000000
+Result.X = 0000000000000000000000000000000000000000000000000000000000000000
+Result.Y = 0000000000000000000000000000000000000000000000000000000000000000
+
+# g + ∞ = g.
+Test = PointAdd
+A.X = 18905f76a53755c679fb732b7762251075ba95fc5fedb60179e730d418a9143c
+A.Y = 8571ff1825885d85d2e88688dd21f3258b4ab8e4ba19e45cddf25357ce95560a
+A.Z = 00000000fffffffeffffffffffffffffffffffff000000000000000000000001
+B.X = 0000000000000000000000000000000000000000000000000000000000000000
+B.Y = 0000000000000000000000000000000000000000000000000000000000000000
+B.Z = 0000000000000000000000000000000000000000000000000000000000000000
+Result.X = 18905f76a53755c679fb732b7762251075ba95fc5fedb60179e730d418a9143c
+Result.Y = 8571ff1825885d85d2e88688dd21f3258b4ab8e4ba19e45cddf25357ce95560a
+
+# g + ∞ = g, with an alternate representation of ∞.
+Test = PointAdd
+A.X = 18905f76a53755c679fb732b7762251075ba95fc5fedb60179e730d418a9143c
+A.Y = 8571ff1825885d85d2e88688dd21f3258b4ab8e4ba19e45cddf25357ce95560a
+A.Z = 00000000fffffffeffffffffffffffffffffffff000000000000000000000001
+B.X = 2b11cb945c8cf152ffa4c9c2b1c965b019b35d0b7626919ef0ae6cb9d232f8af
+B.Y = 6d333da42e30f7011245b6281015ded14e0f100968e758a1b6c3c083afc14ea0
+B.Z = 0000000000000000000000000000000000000000000000000000000000000000
+Result.X = 18905f76a53755c679fb732b7762251075ba95fc5fedb60179e730d418a9143c
+Result.Y = 8571ff1825885d85d2e88688dd21f3258b4ab8e4ba19e45cddf25357ce95560a
+
+# g + -g = ∞.
+Test = PointAdd
+A.X = 18905f76a53755c679fb732b7762251075ba95fc5fedb60179e730d418a9143c
+A.Y = 8571ff1825885d85d2e88688dd21f3258b4ab8e4ba19e45cddf25357ce95560a
+A.Z = 00000000fffffffeffffffffffffffffffffffff000000000000000000000001
+B.X = 18905f76a53755c679fb732b7762251075ba95fc5fedb60179e730d418a9143c
+B.Y = 7a8e00e6da77a27b2d17797722de0cda74b5471c45e61ba3220daca8316aa9f5
+B.Z = 00000000fffffffeffffffffffffffffffffffff000000000000000000000001
+Result.X = 0000000000000000000000000000000000000000000000000000000000000000
+Result.Y = 0000000000000000000000000000000000000000000000000000000000000000
+
+Test = PointAdd
+A.X = bcba3eebf2b0af1174a4b874b155b4dc74bd5fb57c70214561aaabb105635580
+A.Y = 1dc33ce74f651305dd89263c1d314edd2773ef6dd043742a6f47f29542b9eb07
+A.Z = 00000000fffffffeffffffffffffffffffffffff000000000000000000000001
+B.X = f9e0b98b1a87b6c49c4cc5fc47efd157e5f12cf5543d71cfa38187a3793d6791
+B.Y = 3b2de94df438554381037c9f9d2c21991c6975d83c0acd42ef1a8419a040436f
+B.Z = 00000000fffffffeffffffffffffffffffffffff000000000000000000000001
+Result.X = 6bd7b4e06d7862f749901a398417e941618c11c48dffcce719e4026220b77477
+Result.Y = 1e2ffd71e8c206acc19032d26a53ea275fefea51a2c90e4dd3c8b7c6acc51ab6
+
+Test = PointAdd
+A.X = d71c6da129f6e867bf525563e1d8bdbd2f90a9bac7de867a6ea2317a5d6cb507
+A.Y = 125e0cc1ba0c93caa19edb419a764f88d955289c4c6e77d02d90e4e31d47c9a2
+A.Z = 00000000fffffffeffffffffffffffffffffffff000000000000000000000001
+B.X = 334c2200ec08896808ab12a76820ff674fcdccff6d85afa2e586b31fc944de33
+B.Y = b5ee8cfa25896d4075588c60926a2582a099c7a5acbcfec78fba457c4886301c
+B.Z = 00000000fffffffeffffffffffffffffffffffff000000000000000000000001
+Result.X = 93e9d4e6f7736f80da1b00d221024ccfd17f2927d6b505a5bcefe0801fe6f0a9
+Result.Y = 4824eeb2d5da27d57e1d50c2dae000acdcddcbaf534d8b7e7d97854ed3dc939e
+
+Test = PointAdd
+A.X = 0daba41be2b418e7d160a363e6cbdcbff5d433f96b0d5be3812c0a7adfab8ed4
+A.Y = 3ae4dd97c4d2987a63df16c5fb8c494164e14b93eeebd5585d74bd26e2201499
+A.Z = 00000000fffffffeffffffffffffffffffffffff000000000000000000000001
+B.X = 87135fb06383ec8b282fdc028eb38fd447ac1ecc76922e37f0cc454febb11aee
+B.Y = 98ab966087531eb3eea1e5e36189271a02f7ee8e381f9c78d6f346a301f96f81
+B.Z = 00000000fffffffeffffffffffffffffffffffff000000000000000000000001
+Result.X = 2e096c2fabf06a5b838c7e07fda436d068dd1c4e3ff4f5704f89ab9df6b4be5b
+Result.Y = 59ca6304321ae1e41bfa30f52e7ef27fceeade8507f20837654383d70e8a41df
+
+Test = PointAdd
+A.X = 356db98c21c2169899b9b296edcacb7d531524f2572913b75edb7b73196f5682
+A.Y = 47a26c52b1b2f229109e8aca7f5b4af768baf053a15ff8f58051c7e4e1b7f818
+A.Z = 00000000fffffffeffffffffffffffffffffffff000000000000000000000001
+B.X = 56956f6d3bbbd4aece299f29bb4c537355f312f391c207c6ec6efe646362b288
+B.Y = a69fc73c0636c9928764cc9d6e1482577b6ca06f277c098f571108356a858cab
+B.Z = 00000000fffffffeffffffffffffffffffffffff000000000000000000000001
+Result.X = ca0ddd995a77173a1438473bf82734cb3a09fafe7050bda9bd592a1cf078fa38
+Result.Y = 379da87952d36c5396b934a2ce8b003ee8fc4155b3b488f2f550734e2a82ce7d
+
+Test = PointAdd
+A.X = 13764cccab4addf5cf4ef5fb4af60a93e08fa3a0a72653abf013e3427abbf82c
+A.Y = c3dc524745368a0dc4948f897402f4b5a280acbf74f5ea9180d038a483d4090a
+A.Z = 2903a04d6615ec23cd63ba46287be2e7a8eeee030bed49e7a94769386a46f209
+B.X = a5c5921f9a8c569f661693bfae1b167937987c2fe951956ef0e34c426965c648
+B.Y = f8a299605e690a78e583371e59cf2b848d475afc35bb1448981c53ad8c0a6581
+B.Z = 9c3fde73f1899a76eb40f055fce02ab9c1b1ce7d43b54c54f93ffe56830e3f83
+Result.X = 4073318e85bc2d7637fd0129fa8eb86b6ca20334542795f3bb1de54b90a16b69
+Result.Y = 9a1b1e7435d98287b244d2337f8bf0e9c87b40677bf1ea2a9dedbd07c5241ee0
+
+Test = PointAdd
+A.X = f72706b81fca2b1530238bdc2c0c454b5116ee54fdf156bc62bffea73f0645af
+A.Y = c6e66d9ae8fc5e164e6a985f866aae41f3c4e4281a0eea9173e4e77cb29e4bc7
+A.Z = 6a84f9c37634b8aefdae477e9efec66f20d2f6159575f40c7b21a1e0732e8c49
+B.X = bcf21b020cb8fb4b2ef7f639240d221dd96fc08d7fa575c2e7037fc84d8f03b2
+B.Y = abc500f82f06f0d69a920c8d80eef9dd2310cd09e0d89d80fc7397aa4e361dd1
+B.Z = 5031c46be15f9d4fa9a347be998c07f9cc7f754999fe0f9c3c8b38e0d85dda9f
+Result.X = 401b010df4dd21ed96f7c8babb401db74b3b6ee7f55c498803203855b5911de9
+Result.Y = 05e585cca569bc22855f7df32b20a4a45315a1ca5d98d2b94792eb748ec8744b
+
+Test = PointAdd
+A.X = 7b44b52e9fb1bc58c81a2adc9bfedcc42bba3cb34ec666e51cba8050d48fdb37
+A.Y = 2b7e629fef7b4e175f5eb30c421e60f26fefdf5f9fed743cad4a8e638c18696a
+A.Z = 68f31acd92bed56a4556e954b0c51f9f8f3b797bc853d1b2b01b228657bd317f
+B.X = 3d293c36fd065d1f054eb218932d60feb00d1bd4bee0236cb9788d9723df9571
+B.Y = c8b893b8e9ff935f2e060227334e32ba144f4046b1bd4961f4479ad3fef1c7d2
+B.Z = 9c072deacfe5c025c763efebb4feab79e954c47d3e86ef4abfbd1901f50d8495
+Result.X = 245582d32415c77a2e3abbf844cf1a40c31466c1418cd279747e5394744509be
+Result.Y = 5c2f80f947d2df7fb1f829d05c6175f6fce7cd2d7f79fd7aa865f930e910e9fd
+
+Test = PointAdd
+A.X = 75ab91b8a46a5a1abf827cb209373b28cbb8f83a06adf6a9b10ac76e22493ecc
+A.Y = abd989a78d1bcee7e63920d7e637f9763901da408a9d8c731e4e65a6fc52e1a1
+A.Z = 188a24145243ca066c35870e5a8835532ad512fbdcf5f5ae4033b262fa9aa6b8
+B.X = 5d6e885ec19069b2aa51a2723c98da1f03e8dbc344fe1de0bdb42910ba8bfe96
+B.Y = a1f86e66eacc38db7e47154a324a16031705b4803addf074037d3320b50dbef8
+B.Z = 5cff900a783687049a7d497b1f8cd837c479a61f3fef4b7ced180ea82770bc75
+Result.X = a4029333b9b9db434eea002bd6d4e0d9f3e5317c685511a30ecae351fc60d164
+Result.Y = 8e9302c77bc6f560c9bec473ef1ffb76b357c0d4794192696bda8e99651798ee
+
+Test = PointAdd
+A.X = 8d1867f890abaa26b634d5d5cdeb0f4abc7ebd16d807479f837fcece592dc0eb
+A.Y = fc68c801999c12070eddeb3169219c491f9e8fe29cdc4e3cb698ee8471934076
+A.Z = 00000000fffffffeffffffffffffffffffffffff000000000000000000000001
+B.X = 8d1867f890abaa26b634d5d5cdeb0f4abc7ebd16d807479f837fcece592dc0eb
+B.Y = fc68c801999c12070eddeb3169219c491f9e8fe29cdc4e3cb698ee8471934076
+B.Z = 00000000fffffffeffffffffffffffffffffffff000000000000000000000001
+Result.X = 8da53dc540c1450c73082ad3b799d0d18a69a747fcd81f847e9e60484dcf579a
+Result.Y = c20c398e99e0513a452b5e9b6331863d1ac3eee6fcf73021f505a0b62daf6f80
+
+Test = PointAdd
+A.X = 328b983f6490312e37e8eeb2121cd622cf85dbcf78af93df74fbca961ce3bfa2
+A.Y = 1c8a0aea2f2e540770644f48c41810bf7f9e1a782b2f6397712b17c88109fbce
+A.Z = 00000000fffffffeffffffffffffffffffffffff000000000000000000000001
+B.X = 328b983f6490312e37e8eeb2121cd622cf85dbcf78af93df74fbca961ce3bfa2
+B.Y = 1c8a0aea2f2e540770644f48c41810bf7f9e1a782b2f6397712b17c88109fbce
+B.Z = 00000000fffffffeffffffffffffffffffffffff000000000000000000000001
+Result.X = b6f3c548944862dfdea2314ca6d6a88780b08da41becf58384af80544aca4966
+Result.Y = 95afecb4ad3195485a2aad3cd14008c9a7c1e0c02656c3c2b7cd5f2e7f3a4474
+
+Test = PointAdd
+A.X = 3ae6b24cadd6a14612d24a1c094a35c6be56db8f53a6d526e0ede03923918443
+A.Y = de8a23105c5f5c88b77dbde74e30a56f8865d78a5ce9060cff9f2927dbd196b6
+A.Z = 00000000fffffffeffffffffffffffffffffffff000000000000000000000001
+B.X = 3ae6b24cadd6a14612d24a1c094a35c6be56db8f53a6d526e0ede03923918443
+B.Y = de8a23105c5f5c88b77dbde74e30a56f8865d78a5ce9060cff9f2927dbd196b6
+B.Z = 00000000fffffffeffffffffffffffffffffffff000000000000000000000001
+Result.X = 6f125b512c3c736f39781fcd89adb653e515b4ce1e1204505f08d0a8480052ef
+Result.Y = e1acfccf1b9950067adf0f06e0d9703a8b1ac1bbdbb35b08df28cd56c24ae5a0
+
+Test = PointAdd
+A.X = f317c6c02d9a6ff0799b3b4a22f83c95324831baad336ecd0c631ea04a5e11c8
+A.Y = b624e8057d411031f41b30cd02f56c24e89262e885007b7a1ed1861feb7ffcda
+A.Z = 00000000fffffffeffffffffffffffffffffffff000000000000000000000001
+B.X = f317c6c02d9a6ff0799b3b4a22f83c95324831baad336ecd0c631ea04a5e11c8
+B.Y = b624e8057d411031f41b30cd02f56c24e89262e885007b7a1ed1861feb7ffcda
+B.Z = 00000000fffffffeffffffffffffffffffffffff000000000000000000000001
+Result.X = e805208c74602e54482d113f16fcf6e4600436f8af49705cdd05ecfb0e6d45fd
+Result.Y = baded898bfead1b4eb3ab3bbd0129837efc85823dabe82718a975bd603f96d9e
+
+Test = PointAdd
+A.X = 3a6802aeaebc67046a1e75152822fa8bab04c11ae2b816f42c073daee3f13274
+A.Y = d6522c882d18e32bc5ea1fa59efbce8ce2369f2154dcc00e6fb17500f50f8ebf
+A.Z = bea747d5bb1c6ee865249d7a22378f3c760916e163497f4b6ef4da8adcb5dfab
+B.X = 3a6802aeaebc67046a1e75152822fa8bab04c11ae2b816f42c073daee3f13274
+B.Y = d6522c882d18e32bc5ea1fa59efbce8ce2369f2154dcc00e6fb17500f50f8ebf
+B.Z = bea747d5bb1c6ee865249d7a22378f3c760916e163497f4b6ef4da8adcb5dfab
+Result.X = 5a2891dca746889d413d8dc1a69b715954baf692689fc32d9aa10b7431a5c149
+Result.Y = 91db7288536b4f6d78e5a787ecbb5094f6834515038cb070a7fa4870af8045f0
+
+Test = PointAdd
+A.X = c76ddbcb15bc63f82807804536a0d25fd7a639c71adf953ad6cc8f68d915f485
+A.Y = e3a4f830809f5e91b68699c05fa9faa7c3d1f9d1b1c982c282508fa18d695537
+A.Z = eb372f19c7b9466a116363ad9114a89ad287523da318d915f59ed5e558bd824e
+B.X = c76ddbcb15bc63f82807804536a0d25fd7a639c71adf953ad6cc8f68d915f485
+B.Y = e3a4f830809f5e91b68699c05fa9faa7c3d1f9d1b1c982c282508fa18d695537
+B.Z = eb372f19c7b9466a116363ad9114a89ad287523da318d915f59ed5e558bd824e
+Result.X = c5485a3509f55c7cc33d098fb0bfe1b198a9f26ce0ebc29bec5baa29ef6f74a2
+Result.Y = 60e949a551aa94afc9a3efe411a3c63ecb851ef1738ed24c88f86cf85ec01020
+
+Test = PointAdd
+A.X = ca72936509631f09d2a3ac14fb786daabb15520ef01de4298c7fd71653e89194
+A.Y = 02aeb6b6f04cd8125887baa18e6e79ba2b0acfa9a2443e9eea36ca7715eb8eb3
+A.Z = 8b4ef1a52fa42c711445e0463003f2ed38ace6583bf08198e9a0b938b4589479
+B.X = ca72936509631f09d2a3ac14fb786daabb15520ef01de4298c7fd71653e89194
+B.Y = 02aeb6b6f04cd8125887baa18e6e79ba2b0acfa9a2443e9eea36ca7715eb8eb3
+B.Z = 8b4ef1a52fa42c711445e0463003f2ed38ace6583bf08198e9a0b938b4589479
+Result.X = 8d3b35c5661faafa83510ab9b3f1642bb121e7686ed4ae61323ddee2c7247f93
+Result.Y = 1a22ef5df156ca80235fe3cd1ca3152e21a3e17b2a34dd93b2003e3274a8a2fb
+
+Test = PointAdd
+A.X = db7b023fbe056819027fa09c5a2a0d777a53fb78c00bf4f31f46b63a7494bbfe
+A.Y = 59affcbf4628d572ee56b95087d30e765bb518b123e879b25df9960dab706a32
+A.Z = 1f7c7226d78e51478c683bbb6afe01abc2225dbfc773d0806d30ff5f827b76c8
+B.X = db7b023fbe056819027fa09c5a2a0d777a53fb78c00bf4f31f46b63a7494bbfe
+B.Y = 59affcbf4628d572ee56b95087d30e765bb518b123e879b25df9960dab706a32
+B.Z = 1f7c7226d78e51478c683bbb6afe01abc2225dbfc773d0806d30ff5f827b76c8
+Result.X = fba400ae656ec3103c5c5f531d2a0f7368031e01a48a91f1a4f3138d294b13be
+Result.Y = 160e358ad1f059eb62722df01a7440048a1db21ecaea8698efa9677db6e9ff97
diff --git a/src/crypto/ec/simple.c b/src/crypto/ec/simple.c
index cef0e94..880b717 100644
--- a/src/crypto/ec/simple.c
+++ b/src/crypto/ec/simple.c
@@ -74,6 +74,7 @@
 #include <openssl/mem.h>
 
 #include "internal.h"
+#include "../internal.h"
 
 
 /* Most method functions in this file are designed to work with non-trivial
@@ -82,16 +83,16 @@
  * field_sqr methods will be used for multiplication, and field_encode and
  * field_decode (if defined) will be used for converting between
  * representations.
-
- * Functions ec_GFp_simple_points_make_affine() and
- * ec_GFp_simple_point_get_affine_coordinates() specifically assume that if a
- * non-trivial representation is used, it is a Montgomery representation (i.e.
- * 'encoding' means multiplying by some factor R). */
+ *
+ * Functions here specifically assume that if a non-trivial representation is
+ * used, it is a Montgomery representation (i.e. 'encoding' means multiplying
+ * by some factor R). */
 
 int ec_GFp_simple_group_init(EC_GROUP *group) {
   BN_init(&group->field);
   BN_init(&group->a);
   BN_init(&group->b);
+  BN_init(&group->one);
   group->a_is_minus3 = 0;
   return 1;
 }
@@ -100,18 +101,14 @@
   BN_free(&group->field);
   BN_free(&group->a);
   BN_free(&group->b);
-}
-
-void ec_GFp_simple_group_clear_finish(EC_GROUP *group) {
-  BN_clear_free(&group->field);
-  BN_clear_free(&group->a);
-  BN_clear_free(&group->b);
+  BN_free(&group->one);
 }
 
 int ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src) {
   if (!BN_copy(&dest->field, &src->field) ||
       !BN_copy(&dest->a, &src->a) ||
-      !BN_copy(&dest->b, &src->b)) {
+      !BN_copy(&dest->b, &src->b) ||
+      !BN_copy(&dest->one, &src->one)) {
     return 0;
   }
 
@@ -178,6 +175,14 @@
   }
   group->a_is_minus3 = (0 == BN_cmp(tmp_a, &group->field));
 
+  if (group->meth->field_encode != NULL) {
+    if (!group->meth->field_encode(group, &group->one, BN_value_one(), ctx)) {
+      goto err;
+    }
+  } else if (!BN_copy(&group->one, BN_value_one())) {
+    goto err;
+  }
+
   ret = 1;
 
 err:
@@ -230,81 +235,10 @@
   return BN_num_bits(&group->field);
 }
 
-int ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx) {
-  int ret = 0;
-  BIGNUM *a, *b, *order, *tmp_1, *tmp_2;
-  const BIGNUM *p = &group->field;
-  BN_CTX *new_ctx = NULL;
-
-  if (ctx == NULL) {
-    ctx = new_ctx = BN_CTX_new();
-    if (ctx == NULL) {
-      OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
-      goto err;
-    }
-  }
-  BN_CTX_start(ctx);
-  a = BN_CTX_get(ctx);
-  b = BN_CTX_get(ctx);
-  tmp_1 = BN_CTX_get(ctx);
-  tmp_2 = BN_CTX_get(ctx);
-  order = BN_CTX_get(ctx);
-  if (order == NULL) {
-    goto err;
-  }
-
-  if (group->meth->field_decode) {
-    if (!group->meth->field_decode(group, a, &group->a, ctx) ||
-        !group->meth->field_decode(group, b, &group->b, ctx)) {
-      goto err;
-    }
-  } else {
-    if (!BN_copy(a, &group->a) || !BN_copy(b, &group->b)) {
-      goto err;
-    }
-  }
-
-  /* check the discriminant:
-   * y^2 = x^3 + a*x + b is an elliptic curve <=> 4*a^3 + 27*b^2 != 0 (mod p)
-   * 0 =< a, b < p */
-  if (BN_is_zero(a)) {
-    if (BN_is_zero(b)) {
-      goto err;
-    }
-  } else if (!BN_is_zero(b)) {
-    if (!BN_mod_sqr(tmp_1, a, p, ctx) ||
-        !BN_mod_mul(tmp_2, tmp_1, a, p, ctx) ||
-        !BN_lshift(tmp_1, tmp_2, 2)) {
-      goto err;
-    }
-    /* tmp_1 = 4*a^3 */
-
-    if (!BN_mod_sqr(tmp_2, b, p, ctx) ||
-        !BN_mul_word(tmp_2, 27)) {
-      goto err;
-    }
-    /* tmp_2 = 27*b^2 */
-
-    if (!BN_mod_add(a, tmp_1, tmp_2, p, ctx) ||
-        BN_is_zero(a)) {
-      goto err;
-    }
-  }
-  ret = 1;
-
-err:
-  if (ctx != NULL) {
-    BN_CTX_end(ctx);
-  }
-  BN_CTX_free(new_ctx);
-  return ret;
-}
-
 int ec_GFp_simple_point_init(EC_POINT *point) {
   BN_init(&point->X);
   BN_init(&point->Y);
   BN_init(&point->Z);
-  point->Z_is_one = 0;
 
   return 1;
 }
@@ -319,7 +253,6 @@
   BN_clear_free(&point->X);
   BN_clear_free(&point->Y);
   BN_clear_free(&point->Z);
-  point->Z_is_one = 0;
 }
 
 int ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src) {
@@ -328,18 +261,32 @@
       !BN_copy(&dest->Z, &src->Z)) {
     return 0;
   }
-  dest->Z_is_one = src->Z_is_one;
 
   return 1;
 }
 
 int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group,
                                         EC_POINT *point) {
-  point->Z_is_one = 0;
   BN_zero(&point->Z);
   return 1;
 }
 
+static int set_Jprojective_coordinate_GFp(const EC_GROUP *group, BIGNUM *out,
+                                          const BIGNUM *in, BN_CTX *ctx) {
+  if (in == NULL) {
+    return 1;
+  }
+  if (BN_is_negative(in) ||
+      BN_cmp(in, &group->field) >= 0) {
+    OPENSSL_PUT_ERROR(EC, EC_R_COORDINATES_OUT_OF_RANGE);
+    return 0;
+  }
+  if (group->meth->field_encode) {
+    return group->meth->field_encode(group, out, in, ctx);
+  }
+  return BN_copy(out, in) != NULL;
+}
+
 int ec_GFp_simple_set_Jprojective_coordinates_GFp(
     const EC_GROUP *group, EC_POINT *point, const BIGNUM *x, const BIGNUM *y,
     const BIGNUM *z, BN_CTX *ctx) {
@@ -353,43 +300,10 @@
     }
   }
 
-  if (x != NULL) {
-    if (!BN_nnmod(&point->X, x, &group->field, ctx)) {
-      goto err;
-    }
-    if (group->meth->field_encode &&
-        !group->meth->field_encode(group, &point->X, &point->X, ctx)) {
-      goto err;
-    }
-  }
-
-  if (y != NULL) {
-    if (!BN_nnmod(&point->Y, y, &group->field, ctx)) {
-      goto err;
-    }
-    if (group->meth->field_encode &&
-        !group->meth->field_encode(group, &point->Y, &point->Y, ctx)) {
-      goto err;
-    }
-  }
-
-  if (z != NULL) {
-    int Z_is_one;
-
-    if (!BN_nnmod(&point->Z, z, &group->field, ctx)) {
-      goto err;
-    }
-    Z_is_one = BN_is_one(&point->Z);
-    if (group->meth->field_encode) {
-      if (Z_is_one && (group->meth->field_set_to_one != 0)) {
-        if (!group->meth->field_set_to_one(group, &point->Z, ctx)) {
-          goto err;
-        }
-      } else if (!group->meth->field_encode(group, &point->Z, &point->Z, ctx)) {
-        goto err;
-      }
-    }
-    point->Z_is_one = Z_is_one;
+  if (!set_Jprojective_coordinate_GFp(group, &point->X, x, ctx) ||
+      !set_Jprojective_coordinate_GFp(group, &point->Y, y, ctx) ||
+      !set_Jprojective_coordinate_GFp(group, &point->Z, z, ctx)) {
+    goto err;
   }
 
   ret = 1;
@@ -455,109 +369,6 @@
                                                   BN_value_one(), ctx);
 }
 
-int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group,
-                                               const EC_POINT *point, BIGNUM *x,
-                                               BIGNUM *y, BN_CTX *ctx) {
-  BN_CTX *new_ctx = NULL;
-  BIGNUM *Z, *Z_1, *Z_2, *Z_3;
-  const BIGNUM *Z_;
-  int ret = 0;
-
-  if (EC_POINT_is_at_infinity(group, point)) {
-    OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY);
-    return 0;
-  }
-
-  if (ctx == NULL) {
-    ctx = new_ctx = BN_CTX_new();
-    if (ctx == NULL) {
-      return 0;
-    }
-  }
-
-  BN_CTX_start(ctx);
-  Z = BN_CTX_get(ctx);
-  Z_1 = BN_CTX_get(ctx);
-  Z_2 = BN_CTX_get(ctx);
-  Z_3 = BN_CTX_get(ctx);
-  if (Z == NULL || Z_1 == NULL || Z_2 == NULL || Z_3 == NULL) {
-    goto err;
-  }
-
-  /* transform  (X, Y, Z)  into  (x, y) := (X/Z^2, Y/Z^3) */
-
-  if (group->meth->field_decode) {
-    if (!group->meth->field_decode(group, Z, &point->Z, ctx)) {
-      goto err;
-    }
-    Z_ = Z;
-  } else {
-    Z_ = &point->Z;
-  }
-
-  if (BN_is_one(Z_)) {
-    if (group->meth->field_decode) {
-      if (x != NULL && !group->meth->field_decode(group, x, &point->X, ctx)) {
-        goto err;
-      }
-      if (y != NULL && !group->meth->field_decode(group, y, &point->Y, ctx)) {
-        goto err;
-      }
-    } else {
-      if (x != NULL && !BN_copy(x, &point->X)) {
-        goto err;
-      }
-      if (y != NULL && !BN_copy(y, &point->Y)) {
-        goto err;
-      }
-    }
-  } else {
-    if (!BN_mod_inverse(Z_1, Z_, &group->field, ctx)) {
-      OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
-      goto err;
-    }
-
-    if (group->meth->field_encode == 0) {
-      /* field_sqr works on standard representation */
-      if (!group->meth->field_sqr(group, Z_2, Z_1, ctx)) {
-        goto err;
-      }
-    } else if (!BN_mod_sqr(Z_2, Z_1, &group->field, ctx)) {
-      goto err;
-    }
-
-    /* in the Montgomery case, field_mul will cancel out Montgomery factor in
-     * X: */
-    if (x != NULL && !group->meth->field_mul(group, x, &point->X, Z_2, ctx)) {
-      goto err;
-    }
-
-    if (y != NULL) {
-      if (group->meth->field_encode == 0) {
-        /* field_mul works on standard representation */
-        if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx)) {
-          goto err;
-        }
-      } else if (!BN_mod_mul(Z_3, Z_2, Z_1, &group->field, ctx)) {
-        goto err;
-      }
-
-      /* in the Montgomery case, field_mul will cancel out Montgomery factor in
-       * Y: */
-      if (!group->meth->field_mul(group, y, &point->Y, Z_3, ctx)) {
-        goto err;
-      }
-    }
-  }
-
-  ret = 1;
-
-err:
-  BN_CTX_end(ctx);
-  BN_CTX_free(new_ctx);
-  return ret;
-}
-
 int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
                       const EC_POINT *b, BN_CTX *ctx) {
   int (*field_mul)(const EC_GROUP *, BIGNUM *, const BIGNUM *, const BIGNUM *,
@@ -607,7 +418,9 @@
    */
 
   /* n1, n2 */
-  if (b->Z_is_one) {
+  int b_Z_is_one = BN_cmp(&b->Z, &group->one) == 0;
+
+  if (b_Z_is_one) {
     if (!BN_copy(n1, &a->X) || !BN_copy(n2, &a->Y)) {
       goto end;
     }
@@ -628,7 +441,8 @@
   }
 
   /* n3, n4 */
-  if (a->Z_is_one) {
+  int a_Z_is_one = BN_cmp(&a->Z, &group->one) == 0;
+  if (a_Z_is_one) {
     if (!BN_copy(n3, &b->X) || !BN_copy(n4, &b->Y)) {
       goto end;
     }
@@ -666,7 +480,6 @@
     } else {
       /* a is the inverse of b */
       BN_zero(&r->Z);
-      r->Z_is_one = 0;
       ret = 1;
       goto end;
     }
@@ -681,16 +494,16 @@
   /* 'n8' = n2 + n4 */
 
   /* Z_r */
-  if (a->Z_is_one && b->Z_is_one) {
+  if (a_Z_is_one && b_Z_is_one) {
     if (!BN_copy(&r->Z, n5)) {
       goto end;
     }
   } else {
-    if (a->Z_is_one) {
+    if (a_Z_is_one) {
       if (!BN_copy(n0, &b->Z)) {
         goto end;
       }
-    } else if (b->Z_is_one) {
+    } else if (b_Z_is_one) {
       if (!BN_copy(n0, &a->Z)) {
         goto end;
       }
@@ -701,7 +514,7 @@
       goto end;
     }
   }
-  r->Z_is_one = 0;
+
   /* Z_r = Z_a * Z_b * n5 */
 
   /* X_r */
@@ -761,7 +574,6 @@
 
   if (EC_POINT_is_at_infinity(group, a)) {
     BN_zero(&r->Z);
-    r->Z_is_one = 0;
     return 1;
   }
 
@@ -791,7 +603,7 @@
    */
 
   /* n1 */
-  if (a->Z_is_one) {
+  if (BN_cmp(&a->Z, &group->one) == 0) {
     if (!field_sqr(group, n0, &a->X, ctx) ||
         !BN_mod_lshift1_quick(n1, n0, p) ||
         !BN_mod_add_quick(n0, n0, n1, p) ||
@@ -824,7 +636,7 @@
   }
 
   /* Z_r */
-  if (a->Z_is_one) {
+  if (BN_cmp(&a->Z, &group->one) == 0) {
     if (!BN_copy(n0, &a->Y)) {
       goto err;
     }
@@ -834,7 +646,6 @@
   if (!BN_mod_lshift1_quick(&r->Z, n0, p)) {
     goto err;
   }
-  r->Z_is_one = 0;
   /* Z_r = 2 * Y_a * Z_a */
 
   /* n2 */
@@ -886,7 +697,7 @@
 }
 
 int ec_GFp_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point) {
-  return !point->Z_is_one && BN_is_zero(&point->Z);
+  return BN_is_zero(&point->Z);
 }
 
 int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
@@ -897,7 +708,7 @@
   const BIGNUM *p;
   BN_CTX *new_ctx = NULL;
   BIGNUM *rh, *tmp, *Z4, *Z6;
-  int ret = -1;
+  int ret = 0;
 
   if (EC_POINT_is_at_infinity(group, point)) {
     return 1;
@@ -910,7 +721,7 @@
   if (ctx == NULL) {
     ctx = new_ctx = BN_CTX_new();
     if (ctx == NULL) {
-      return -1;
+      return 0;
     }
   }
 
@@ -938,7 +749,7 @@
     goto err;
   }
 
-  if (!point->Z_is_one) {
+  if (BN_cmp(&point->Z, &group->one) != 0) {
     if (!field_sqr(group, tmp, &point->Z, ctx) ||
         !field_sqr(group, Z4, tmp, ctx) ||
         !field_mul(group, Z6, Z4, tmp, ctx)) {
@@ -967,8 +778,6 @@
       goto err;
     }
   } else {
-    /* point->Z_is_one */
-
     /* rh := (rh + a)*X */
     if (!BN_mod_add_quick(rh, rh, &group->a, p) ||
         !field_mul(group, rh, rh, &point->X, ctx)) {
@@ -1017,7 +826,10 @@
     return 1;
   }
 
-  if (a->Z_is_one && b->Z_is_one) {
+  int a_Z_is_one = BN_cmp(&a->Z, &group->one) == 0;
+  int b_Z_is_one = BN_cmp(&b->Z, &group->one) == 0;
+
+  if (a_Z_is_one && b_Z_is_one) {
     return ((BN_cmp(&a->X, &b->X) == 0) && BN_cmp(&a->Y, &b->Y) == 0) ? 0 : 1;
   }
 
@@ -1046,7 +858,7 @@
    *     (X_a*Z_b^2, Y_a*Z_b^3) = (X_b*Z_a^2, Y_b*Z_a^3).
    */
 
-  if (!b->Z_is_one) {
+  if (!b_Z_is_one) {
     if (!field_sqr(group, Zb23, &b->Z, ctx) ||
         !field_mul(group, tmp1, &a->X, Zb23, ctx)) {
       goto end;
@@ -1055,7 +867,7 @@
   } else {
     tmp1_ = &a->X;
   }
-  if (!a->Z_is_one) {
+  if (!a_Z_is_one) {
     if (!field_sqr(group, Za23, &a->Z, ctx) ||
         !field_mul(group, tmp2, &b->X, Za23, ctx)) {
       goto end;
@@ -1072,7 +884,7 @@
   }
 
 
-  if (!b->Z_is_one) {
+  if (!b_Z_is_one) {
     if (!field_mul(group, Zb23, Zb23, &b->Z, ctx) ||
         !field_mul(group, tmp1, &a->Y, Zb23, ctx)) {
       goto end;
@@ -1081,7 +893,7 @@
   } else {
     tmp1_ = &a->Y;
   }
-  if (!a->Z_is_one) {
+  if (!a_Z_is_one) {
     if (!field_mul(group, Za23, Za23, &a->Z, ctx) ||
         !field_mul(group, tmp2, &b->Y, Za23, ctx)) {
       goto end;
@@ -1112,7 +924,8 @@
   BIGNUM *x, *y;
   int ret = 0;
 
-  if (point->Z_is_one || EC_POINT_is_at_infinity(group, point)) {
+  if (BN_cmp(&point->Z, &group->one) == 0 ||
+      EC_POINT_is_at_infinity(group, point)) {
     return 1;
   }
 
@@ -1134,7 +947,7 @@
       !EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) {
     goto err;
   }
-  if (!point->Z_is_one) {
+  if (BN_cmp(&point->Z, &group->one) != 0) {
     OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
     goto err;
   }
@@ -1152,7 +965,6 @@
   BN_CTX *new_ctx = NULL;
   BIGNUM *tmp, *tmp_Z;
   BIGNUM **prod_Z = NULL;
-  size_t i;
   int ret = 0;
 
   if (num == 0) {
@@ -1177,8 +989,8 @@
   if (prod_Z == NULL) {
     goto err;
   }
-  memset(prod_Z, 0, num * sizeof(prod_Z[0]));
-  for (i = 0; i < num; i++) {
+  OPENSSL_memset(prod_Z, 0, num * sizeof(prod_Z[0]));
+  for (size_t i = 0; i < num; i++) {
     prod_Z[i] = BN_new();
     if (prod_Z[i] == NULL) {
       goto err;
@@ -1193,18 +1005,12 @@
       goto err;
     }
   } else {
-    if (group->meth->field_set_to_one != 0) {
-      if (!group->meth->field_set_to_one(group, prod_Z[0], ctx)) {
-        goto err;
-      }
-    } else {
-      if (!BN_one(prod_Z[0])) {
-        goto err;
-      }
+    if (BN_copy(prod_Z[0], &group->one) == NULL) {
+      goto err;
     }
   }
 
-  for (i = 1; i < num; i++) {
+  for (size_t i = 1; i < num; i++) {
     if (!BN_is_zero(&points[i]->Z)) {
       if (!group->meth->field_mul(group, prod_Z[i], prod_Z[i - 1],
                                   &points[i]->Z, ctx)) {
@@ -1217,10 +1023,16 @@
     }
   }
 
-  /* Now use a single explicit inversion to replace every
-   * non-zero points[i]->Z by its inverse. */
-
-  if (!BN_mod_inverse(tmp, prod_Z[num - 1], &group->field, ctx)) {
+  /* Now use a single explicit inversion to replace every non-zero points[i]->Z
+   * by its inverse. We use |BN_mod_inverse_odd| instead of doing a constant-
+   * time inversion using Fermat's Little Theorem because this function is
+   * usually only used for converting multiples of a public key point to
+   * affine, and a public key point isn't secret. If we were to use Fermat's
+   * Little Theorem then the cost of the inversion would usually be so high
+   * that converting the multiples to affine would be counterproductive. */
+  int no_inverse;
+  if (!BN_mod_inverse_odd(tmp, &no_inverse, prod_Z[num - 1], &group->field,
+                          ctx)) {
     OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB);
     goto err;
   }
@@ -1235,7 +1047,7 @@
     }
   }
 
-  for (i = num - 1; i > 0; --i) {
+  for (size_t i = num - 1; i > 0; --i) {
     /* Loop invariant: tmp is the product of the inverses of
      * points[0]->Z .. points[i]->Z (zero-valued inputs skipped). */
     if (BN_is_zero(&points[i]->Z)) {
@@ -1259,7 +1071,7 @@
   }
 
   /* Finally, fix up the X and Y coordinates for all points. */
-  for (i = 0; i < num; i++) {
+  for (size_t i = 0; i < num; i++) {
     EC_POINT *p = points[i];
 
     if (!BN_is_zero(&p->Z)) {
@@ -1271,16 +1083,9 @@
         goto err;
       }
 
-      if (group->meth->field_set_to_one != NULL) {
-        if (!group->meth->field_set_to_one(group, &p->Z, ctx)) {
-          goto err;
-        }
-      } else {
-        if (!BN_one(&p->Z)) {
-          goto err;
-        }
+      if (BN_copy(&p->Z, &group->one) == NULL) {
+        goto err;
       }
-      p->Z_is_one = 1;
     }
   }
 
@@ -1290,7 +1095,7 @@
   BN_CTX_end(ctx);
   BN_CTX_free(new_ctx);
   if (prod_Z != NULL) {
-    for (i = 0; i < num; i++) {
+    for (size_t i = 0; i < num; i++) {
       if (prod_Z[i] == NULL) {
         break;
       }
diff --git a/src/crypto/ec/util-64.c b/src/crypto/ec/util-64.c
index 171b063..4006271 100644
--- a/src/crypto/ec/util-64.c
+++ b/src/crypto/ec/util-64.c
@@ -21,80 +21,6 @@
 
 #include "internal.h"
 
-/* Convert an array of points into affine coordinates. (If the point at
- * infinity is found (Z = 0), it remains unchanged.) This function is
- * essentially an equivalent to EC_POINTs_make_affine(), but works with the
- * internal representation of points as used by ecp_nistp###.c rather than
- * with (BIGNUM-based) EC_POINT data structures. point_array is the
- * input/output buffer ('num' points in projective form, i.e. three
- * coordinates each), based on an internal representation of field elements
- * of size 'felem_size'. tmp_felems needs to point to a temporary array of
- * 'num'+1 field elements for storage of intermediate values. */
-void ec_GFp_nistp_points_make_affine_internal(
-    size_t num, void *point_array, size_t felem_size, void *tmp_felems,
-    void (*felem_one)(void *out), int (*felem_is_zero)(const void *in),
-    void (*felem_assign)(void *out, const void *in),
-    void (*felem_square)(void *out, const void *in),
-    void (*felem_mul)(void *out, const void *in1, const void *in2),
-    void (*felem_inv)(void *out, const void *in),
-    void (*felem_contract)(void *out, const void *in)) {
-  int i = 0;
-
-#define tmp_felem(I) (&((char *)tmp_felems)[(I)*felem_size])
-#define X(I) (&((char *)point_array)[3 * (I)*felem_size])
-#define Y(I) (&((char *)point_array)[(3 * (I) + 1) * felem_size])
-#define Z(I) (&((char *)point_array)[(3 * (I) + 2) * felem_size])
-
-  if (!felem_is_zero(Z(0))) {
-    felem_assign(tmp_felem(0), Z(0));
-  } else {
-    felem_one(tmp_felem(0));
-  }
-
-  for (i = 1; i < (int)num; i++) {
-    if (!felem_is_zero(Z(i))) {
-      felem_mul(tmp_felem(i), tmp_felem(i - 1), Z(i));
-    } else {
-      felem_assign(tmp_felem(i), tmp_felem(i - 1));
-    }
-  }
-  /* Now each tmp_felem(i) is the product of Z(0) .. Z(i), skipping any
-   * zero-valued factors: if Z(i) = 0, we essentially pretend that Z(i) = 1. */
-
-  felem_inv(tmp_felem(num - 1), tmp_felem(num - 1));
-  for (i = num - 1; i >= 0; i--) {
-    if (i > 0) {
-      /* tmp_felem(i-1) is the product of Z(0) .. Z(i-1), tmp_felem(i)
-       * is the inverse of the product of Z(0) .. Z(i). */
-      /* 1/Z(i) */
-      felem_mul(tmp_felem(num), tmp_felem(i - 1), tmp_felem(i));
-    } else {
-      felem_assign(tmp_felem(num), tmp_felem(0)); /* 1/Z(0) */
-    }
-
-    if (!felem_is_zero(Z(i))) {
-      if (i > 0) {
-        /* For next iteration, replace tmp_felem(i-1) by its inverse. */
-        felem_mul(tmp_felem(i - 1), tmp_felem(i), Z(i));
-      }
-
-      /* Convert point (X, Y, Z) into affine form (X/(Z^2), Y/(Z^3), 1). */
-      felem_square(Z(i), tmp_felem(num));    /* 1/(Z^2) */
-      felem_mul(X(i), X(i), Z(i));           /* X/(Z^2) */
-      felem_mul(Z(i), Z(i), tmp_felem(num)); /* 1/(Z^3) */
-      felem_mul(Y(i), Y(i), Z(i));           /* Y/(Z^3) */
-      felem_contract(X(i), X(i));
-      felem_contract(Y(i), Y(i));
-      felem_one(Z(i));
-    } else {
-      if (i > 0) {
-        /* For next iteration, replace tmp_felem(i-1) by its inverse. */
-        felem_assign(tmp_felem(i - 1), tmp_felem(i));
-      }
-    }
-  }
-}
-
 /* This function looks at 5+1 scalar bits (5 current, 1 adjacent less
  * significant bit), and recodes them into a signed digit for use in fast point
  * multiplication: the use of signed rather than unsigned digits means that
diff --git a/src/crypto/ec/wnaf.c b/src/crypto/ec/wnaf.c
index ba2257c..67b7f34 100644
--- a/src/crypto/ec/wnaf.c
+++ b/src/crypto/ec/wnaf.c
@@ -90,10 +90,10 @@
  * with the exception that the most significant digit may be only
  * w-1 zeros away from that next non-zero digit.
  */
-static signed char *compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len) {
+static int8_t *compute_wNAF(const BIGNUM *scalar, int w, size_t *ret_len) {
   int window_val;
   int ok = 0;
-  signed char *r = NULL;
+  int8_t *r = NULL;
   int sign = 1;
   int bit, next_bit, mask;
   size_t len = 0, j;
@@ -109,9 +109,8 @@
     return r;
   }
 
-  if (w <= 0 || w > 7) /* 'signed char' can represent integers with absolute
-                          values less than 2^7 */
-  {
+  /* 'int8_t' can represent integers with absolute values less than 2^7. */
+  if (w <= 0 || w > 7) {
     OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
     goto err;
   }
@@ -129,20 +128,18 @@
   }
 
   len = BN_num_bits(scalar);
-  r = OPENSSL_malloc(
-      len +
-      1); /* modified wNAF may be one digit longer than binary representation
-           * (*ret_len will be set to the actual length, i.e. at most
-           * BN_num_bits(scalar) + 1) */
+  /* The modified wNAF may be one digit longer than binary representation
+   * (*ret_len will be set to the actual length, i.e. at most
+   * BN_num_bits(scalar) + 1). */
+  r = OPENSSL_malloc(len + 1);
   if (r == NULL) {
     OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
     goto err;
   }
   window_val = scalar->d[0] & mask;
   j = 0;
-  while ((window_val != 0) ||
-         (j + w + 1 < len)) /* if j+w+1 >= len, window_val will not increase */
-  {
+  /* If j+w+1 >= len, window_val will not increase. */
+  while (window_val != 0 || j + w + 1 < len) {
     int digit = 0;
 
     /* 0 <= window_val <= 2^(w+1) */
@@ -174,9 +171,8 @@
 
       window_val -= digit;
 
-      /* now window_val is 0 or 2^(w+1) in standard wNAF generation;
-       * for modified window NAFs, it may also be 2^w
-       */
+      /* Now window_val is 0 or 2^(w+1) in standard wNAF generation;
+       * for modified window NAFs, it may also be 2^w. */
       if (window_val != 0 && window_val != next_bit && window_val != bit) {
         OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR);
         goto err;
@@ -217,28 +213,45 @@
  *       sometimes smaller windows will give better performance
  *       (thus the boundaries should be increased)
  */
-#define EC_window_bits_for_scalar_size(b)                                      \
-  ((size_t)((b) >= 2000 ? 6 : (b) >= 800 ? 5 : (b) >= 300                      \
-                                                   ? 4                         \
-                                                   : (b) >= 70 ? 3 : (b) >= 20 \
-                                                                         ? 2   \
-                                                                         : 1))
+static size_t window_bits_for_scalar_size(size_t b) {
+  if (b >= 2000) {
+    return 6;
+  }
+
+  if (b >= 800) {
+    return 5;
+  }
+
+  if (b >= 300) {
+    return 4;
+  }
+
+  if (b >= 70) {
+    return 3;
+  }
+
+  if (b >= 20) {
+    return 2;
+  }
+
+  return 1;
+}
 
 int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
                 const EC_POINT *p, const BIGNUM *p_scalar, BN_CTX *ctx) {
   BN_CTX *new_ctx = NULL;
   const EC_POINT *generator = NULL;
   EC_POINT *tmp = NULL;
-  size_t total_num;
+  size_t total_num = 0;
   size_t i, j;
   int k;
   int r_is_inverted = 0;
   int r_is_at_infinity = 1;
   size_t *wsize = NULL;      /* individual window sizes */
-  signed char **wNAF = NULL; /* individual wNAFs */
+  int8_t **wNAF = NULL; /* individual wNAFs */
   size_t *wNAF_len = NULL;
   size_t max_len = 0;
-  size_t num_val;
+  size_t num_val = 0;
   EC_POINT **val = NULL; /* precomputation */
   EC_POINT **v;
   EC_POINT ***val_sub = NULL; /* pointers to sub-arrays of 'val' */
@@ -271,15 +284,14 @@
   }
 
 
-  wsize = OPENSSL_malloc(total_num * sizeof wsize[0]);
-  wNAF_len = OPENSSL_malloc(total_num * sizeof wNAF_len[0]);
-  wNAF = OPENSSL_malloc((total_num + 1) *
-                        sizeof wNAF[0]); /* includes space for pivot */
-  val_sub = OPENSSL_malloc(total_num * sizeof val_sub[0]);
+  wsize = OPENSSL_malloc(total_num * sizeof(wsize[0]));
+  wNAF_len = OPENSSL_malloc(total_num * sizeof(wNAF_len[0]));
+  wNAF = OPENSSL_malloc(total_num * sizeof(wNAF[0]));
+  val_sub = OPENSSL_malloc(total_num * sizeof(val_sub[0]));
 
   /* Ensure wNAF is initialised in case we end up going to err. */
-  if (wNAF) {
-    wNAF[0] = NULL; /* preliminary pivot */
+  if (wNAF != NULL) {
+    OPENSSL_memset(wNAF, 0, total_num * sizeof(wNAF[0]));
   }
 
   if (!wsize || !wNAF_len || !wNAF || !val_sub) {
@@ -294,9 +306,8 @@
     size_t bits;
 
     bits = i < num ? BN_num_bits(scalars[i]) : BN_num_bits(g_scalar);
-    wsize[i] = EC_window_bits_for_scalar_size(bits);
+    wsize[i] = window_bits_for_scalar_size(bits);
     num_val += (size_t)1 << (wsize[i] - 1);
-    wNAF[i + 1] = NULL; /* make sure we always have a pivot */
     wNAF[i] =
         compute_wNAF((i < num ? scalars[i] : g_scalar), wsize[i], &wNAF_len[i]);
     if (wNAF[i] == NULL) {
@@ -309,12 +320,12 @@
 
   /* All points we precompute now go into a single array 'val'. 'val_sub[i]' is
    * a pointer to the subarray for the i-th point. */
-  val = OPENSSL_malloc((num_val + 1) * sizeof val[0]);
+  val = OPENSSL_malloc(num_val * sizeof(val[0]));
   if (val == NULL) {
     OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE);
     goto err;
   }
-  val[num_val] = NULL; /* pivot element */
+  OPENSSL_memset(val, 0, num_val * sizeof(val[0]));
 
   /* allocate points for precomputation */
   v = val;
@@ -364,7 +375,7 @@
     }
   }
 
-#if 1 /* optional; EC_window_bits_for_scalar_size assumes we do this step */
+#if 1 /* optional; window_bits_for_scalar_size assumes we do this step */
   if (!EC_POINTs_make_affine(group, num_val, val, ctx)) {
     goto err;
   }
@@ -429,17 +440,15 @@
   OPENSSL_free(wsize);
   OPENSSL_free(wNAF_len);
   if (wNAF != NULL) {
-    signed char **w;
-
-    for (w = wNAF; *w != NULL; w++) {
-      OPENSSL_free(*w);
+    for (i = 0; i < total_num; i++) {
+      OPENSSL_free(wNAF[i]);
     }
 
     OPENSSL_free(wNAF);
   }
   if (val != NULL) {
-    for (v = val; *v != NULL; v++) {
-      EC_POINT_clear_free(*v);
+    for (i = 0; i < num_val; i++) {
+      EC_POINT_clear_free(val[i]);
     }
 
     OPENSSL_free(val);
diff --git a/src/crypto/ecdh/CMakeLists.txt b/src/crypto/ecdh/CMakeLists.txt
index 8eaeae5..3d95180 100644
--- a/src/crypto/ecdh/CMakeLists.txt
+++ b/src/crypto/ecdh/CMakeLists.txt
@@ -7,3 +7,14 @@
 
   ecdh.c
 )
+
+add_executable(
+  ecdh_test
+
+  ecdh_test.cc
+
+  $<TARGET_OBJECTS:test_support>
+)
+
+target_link_libraries(ecdh_test crypto)
+add_dependencies(all_tests ecdh_test)
diff --git a/src/crypto/ecdh/ecdh.c b/src/crypto/ecdh/ecdh.c
index 4a1964a..22b216e 100644
--- a/src/crypto/ecdh/ecdh.c
+++ b/src/crypto/ecdh/ecdh.c
@@ -66,6 +66,7 @@
 
 #include <openssl/ecdh.h>
 
+#include <limits.h>
 #include <string.h>
 
 #include <openssl/bn.h>
@@ -73,9 +74,11 @@
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
+#include "../internal.h"
+
 
 int ECDH_compute_key(void *out, size_t outlen, const EC_POINT *pub_key,
-                     EC_KEY *priv_key,
+                     const EC_KEY *priv_key,
                      void *(*kdf)(const void *in, size_t inlen, void *out,
                                   size_t *outlen)) {
   const BIGNUM *const priv = EC_KEY_get0_private_key(priv_key);
@@ -139,10 +142,15 @@
     if (buflen < outlen) {
       outlen = buflen;
     }
-    memcpy(out, buf, outlen);
+    OPENSSL_memcpy(out, buf, outlen);
   }
 
-  ret = outlen;
+  if (outlen > INT_MAX) {
+    OPENSSL_PUT_ERROR(ECDH, ERR_R_OVERFLOW);
+    goto err;
+  }
+
+  ret = (int)outlen;
 
 err:
   OPENSSL_free(buf);
diff --git a/src/crypto/ecdh/ecdh_test.cc b/src/crypto/ecdh/ecdh_test.cc
new file mode 100644
index 0000000..a02fd22
--- /dev/null
+++ b/src/crypto/ecdh/ecdh_test.cc
@@ -0,0 +1,125 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <stdio.h>
+
+#include <vector>
+
+#include <openssl/bn.h>
+#include <openssl/crypto.h>
+#include <openssl/ec.h>
+#include <openssl/ec_key.h>
+#include <openssl/ecdh.h>
+#include <openssl/nid.h>
+
+#include "../test/file_test.h"
+
+
+static bssl::UniquePtr<EC_GROUP> GetCurve(FileTest *t, const char *key) {
+  std::string curve_name;
+  if (!t->GetAttribute(&curve_name, key)) {
+    return nullptr;
+  }
+
+  if (curve_name == "P-224") {
+    return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(NID_secp224r1));
+  }
+  if (curve_name == "P-256") {
+    return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(
+        NID_X9_62_prime256v1));
+  }
+  if (curve_name == "P-384") {
+    return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(NID_secp384r1));
+  }
+  if (curve_name == "P-521") {
+    return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(NID_secp521r1));
+  }
+
+  t->PrintLine("Unknown curve '%s'", curve_name.c_str());
+  return nullptr;
+}
+
+static bssl::UniquePtr<BIGNUM> GetBIGNUM(FileTest *t, const char *key) {
+  std::vector<uint8_t> bytes;
+  if (!t->GetBytes(&bytes, key)) {
+    return nullptr;
+  }
+
+  return bssl::UniquePtr<BIGNUM>(BN_bin2bn(bytes.data(), bytes.size(), nullptr));
+}
+
+static bool TestECDH(FileTest *t, void *arg) {
+  bssl::UniquePtr<EC_GROUP> group = GetCurve(t, "Curve");
+  bssl::UniquePtr<BIGNUM> priv_key = GetBIGNUM(t, "Private");
+  bssl::UniquePtr<BIGNUM> x = GetBIGNUM(t, "X");
+  bssl::UniquePtr<BIGNUM> y = GetBIGNUM(t, "Y");
+  bssl::UniquePtr<BIGNUM> peer_x = GetBIGNUM(t, "PeerX");
+  bssl::UniquePtr<BIGNUM> peer_y = GetBIGNUM(t, "PeerY");
+  std::vector<uint8_t> z;
+  if (!group || !priv_key || !x || !y || !peer_x || !peer_y ||
+      !t->GetBytes(&z, "Z")) {
+    return false;
+  }
+
+  bssl::UniquePtr<EC_KEY> key(EC_KEY_new());
+  bssl::UniquePtr<EC_POINT> pub_key(EC_POINT_new(group.get()));
+  bssl::UniquePtr<EC_POINT> peer_pub_key(EC_POINT_new(group.get()));
+  if (!key || !pub_key || !peer_pub_key ||
+      !EC_KEY_set_group(key.get(), group.get()) ||
+      !EC_KEY_set_private_key(key.get(), priv_key.get()) ||
+      !EC_POINT_set_affine_coordinates_GFp(group.get(), pub_key.get(), x.get(),
+                                           y.get(), nullptr) ||
+      !EC_POINT_set_affine_coordinates_GFp(group.get(), peer_pub_key.get(),
+                                           peer_x.get(), peer_y.get(),
+                                           nullptr) ||
+      !EC_KEY_set_public_key(key.get(), pub_key.get()) ||
+      !EC_KEY_check_key(key.get())) {
+    return false;
+  }
+
+  std::vector<uint8_t> actual_z;
+  // Make |actual_z| larger than expected to ensure |ECDH_compute_key| returns
+  // the right amount of data.
+  actual_z.resize(z.size() + 1);
+  int ret = ECDH_compute_key(actual_z.data(), actual_z.size(),
+                             peer_pub_key.get(), key.get(), nullptr);
+  if (ret < 0 ||
+      !t->ExpectBytesEqual(z.data(), z.size(), actual_z.data(),
+                           static_cast<size_t>(ret))) {
+    return false;
+  }
+
+  // Test |ECDH_compute_key| truncates.
+  actual_z.resize(z.size() - 1);
+  ret = ECDH_compute_key(actual_z.data(), actual_z.size(), peer_pub_key.get(),
+                         key.get(), nullptr);
+  if (ret < 0 ||
+      !t->ExpectBytesEqual(z.data(), z.size() - 1, actual_z.data(),
+                           static_cast<size_t>(ret))) {
+    return false;
+  }
+
+  return true;
+}
+
+int main(int argc, char *argv[]) {
+  CRYPTO_library_init();
+
+  if (argc != 2) {
+    fprintf(stderr, "%s <test file.txt>\n", argv[0]);
+    return 1;
+  }
+
+  return FileTestMain(TestECDH, nullptr, argv[1]);
+}
diff --git a/src/crypto/ecdh/ecdh_tests.txt b/src/crypto/ecdh/ecdh_tests.txt
new file mode 100644
index 0000000..58dc3d9
--- /dev/null
+++ b/src/crypto/ecdh/ecdh_tests.txt
@@ -0,0 +1,804 @@
+# Tests from NIST CAVP SP 800-56A ECCCDH Primitive Test Vectors.
+# http://csrc.nist.gov/groups/STM/cavp/documents/components/ecccdhtestvectors.zip
+#
+# P-521 test vectors were fixed to have the right length.
+
+Curve = P-224
+Private = 8346a60fc6f293ca5a0d2af68ba71d1dd389e5e40837942df3e43cbd
+X = 8de2e26adf72c582d6568ef638c4fd59b18da171bdf501f1d929e048
+Y = 4a68a1c2b0fb22930d120555c1ece50ea98dea8407f71be36efac0de
+PeerX = af33cd0629bc7e996320a3f40368f74de8704fa37b8fab69abaae280
+PeerY = 882092ccbba7930f419a8a4f9bb16978bbc3838729992559a6f2e2d7
+Z = 7d96f9a3bd3c05cf5cc37feb8b9d5209d5c2597464dec3e9983743e8
+
+Curve = P-224
+Private = 043cb216f4b72cdf7629d63720a54aee0c99eb32d74477dac0c2f73d
+X = 2f90f5c8eac9c7decdbb97b6c2f715ab725e4fe40fe6d746efbf4e1b
+Y = 66897351454f927a309b269c5a6d31338be4c19a5acfc32cf656f45c
+PeerX = 13bfcd4f8e9442393cab8fb46b9f0566c226b22b37076976f0617a46
+PeerY = eeb2427529b288c63c2f8963c1e473df2fca6caa90d52e2f8db56dd4
+Z = ee93ce06b89ff72009e858c68eb708e7bc79ee0300f73bed69bbca09
+
+Curve = P-224
+Private = 5ad0dd6dbabb4f3c2ea5fe32e561b2ca55081486df2c7c15c9622b08
+X = 005bca45d793e7fe99a843704ed838315ab14a5f6277507e9bc37531
+Y = 43e9d421e1486ae5893bfd23c210e5c140d7c6b1ada59d842c9a98de
+PeerX = 756dd806b9d9c34d899691ecb45b771af468ec004486a0fdd283411e
+PeerY = 4d02c2ca617bb2c5d9613f25dd72413d229fd2901513aa29504eeefb
+Z = 3fcc01e34d4449da2a974b23fc36f9566754259d39149790cfa1ebd3
+
+Curve = P-224
+Private = 0aa6ff55a5d820efcb4e7d10b845ea3c9f9bc5dff86106db85318e22
+X = 2f96754131e0968198aa78fbe8c201dc5f3581c792de487340d32448
+Y = 61e8a5cd79615203b6d89e9496f9e236fe3b6be8731e743d615519c6
+PeerX = 0f537bf1c1122c55656d25e8aa8417e0b44b1526ae0523144f9921c4
+PeerY = f79b26d30e491a773696cc2c79b4f0596bc5b9eebaf394d162fb8684
+Z = 49129628b23afcef48139a3f6f59ff5e9811aa746aa4ff33c24bb940
+
+Curve = P-224
+Private = efe6e6e25affaf54c98d002abbc6328da159405a1b752e32dc23950a
+X = 355e962920bde043695f6bffb4b355c63da6f5de665ed46f2ec817e2
+Y = 748e095368f62e1d364edd461719793b404adbdaacbcadd88922ff37
+PeerX = 2b3631d2b06179b3174a100f7f57131eeea8947be0786c3dc64b2239
+PeerY = 83de29ae3dad31adc0236c6de7f14561ca2ea083c5270c78a2e6cbc0
+Z = fcdc69a40501d308a6839653a8f04309ec00233949522902ffa5eac6
+
+Curve = P-224
+Private = 61cb2932524001e5e9eeed6df7d9c8935ee3322029edd7aa8acbfd51
+X = d50e4adabfd989d7dbc7cf4052546cc7c447a97630436997ad4b9536
+Y = 5bea503473c5eaef9552d42c40b1f2f7ca292733b255b9bbe1b12337
+PeerX = 4511403de29059f69a475c5a6a5f6cabed5d9f014436a8cb70a02338
+PeerY = 7d2d1b62aa046df9340f9c37a087a06b32cf7f08a223f992812a828b
+Z = 827e9025cb62e0e837c596063f3b9b5a0f7afd8d8783200086d61ec1
+
+Curve = P-224
+Private = 8c7ace347171f92def98d845475fc82e1d1496da81ee58f505b985fa
+X = b1a8dcac89aca2799320b451df1c7ff4d97567abb68141c0d95fc2aa
+Y = 3524950902b1510bdc987d860afc27ad871ceaea66935abd3c0a99a8
+PeerX = 314a0b26dd31c248845d7cc17b61cad4608259bed85a58d1f1ffd378
+PeerY = 66e4b350352e119eecada382907f3619fd748ea73ae4899dfd496302
+Z = 335ba51228d94acbed851ca7821c801d5cb1c7975d7aa90a7159f8fa
+
+Curve = P-224
+Private = 382feb9b9ba10f189d99e71a89cdfe44cb554cec13a212840977fb68
+X = abb6f1e3773ff8fc73aea2a0b107809ce70adcefed6e41fc5cb43045
+Y = a963897ae906c10a055eeadb97ffdd6f748d3e5621e5fff304e48ba7
+PeerX = abe6843beec2fd9e5fb64730d0be4d165438ce922ed75dd80b4603e5
+PeerY = 6afe8673a96c4ba9900ad85995e631e436c6cc88a2c2b47b7c4886b8
+Z = 8c2e627594206b34f7356d3426eb3d79f518ef843fbe94014cceace3
+
+Curve = P-224
+Private = e0d62035101ef487c485c60fb4500eebe6a32ec64dbe97dbe0232c46
+X = 88537735e9b23e3e0e076f135a82d33f9bffb465f3abce8322a62a62
+Y = b4c8c123673197875c0bd14ed097606d330fba2b9200ef65a44764d3
+PeerX = 13cf9d6d2c9aae8274c27d446afd0c888ffdd52ae299a35984d4f527
+PeerY = dcbee75b515751f8ee2ae355e8afd5de21c62a939a6507b538cbc4af
+Z = 632abb662728dbc994508873d5c527ca5ef923c0d31fa6c47ef4c825
+
+Curve = P-224
+Private = b96ade5b73ba72aa8b6e4d74d7bf9c58e962ff78eb542287c7b44ba2
+X = 37682926a54f70a4c1748f54d50d5b00138a055f924f2c65e5b0bbe4
+Y = 596afefcdd640d29635015b89bdddd1f8c2723686d332e7a06ca8799
+PeerX = 965b637c0dfbc0cf954035686d70f7ec30929e664e521dbaa2280659
+PeerY = 82a58ff61bc90019bbcbb5875d3863db0bc2a1fa34b0ad4de1a83f99
+Z = 34641141aab05ef58bd376d609345901fb8f63477c6be9097f037f1f
+
+Curve = P-224
+Private = a40d7e12049c71e6522c7ff2384224061c3a457058b310557655b854
+X = 399801243bfe0c2da9b0a53c8ca57f2eee87aaa94a8e4d5e029f42ca
+Y = aa49e6d4b47cee7a5c4ab71d5a67da84e0b9b425ce3e70da68c889e7
+PeerX = 73cc645372ca2e71637cda943d8148f3382ab6dd0f2e1a49da94e134
+PeerY = df5c355c23e6e232ebc3bee2ab1873ee0d83e3382f8e6fe613f6343c
+Z = 4f74ac8507501a32bfc5a78d8271c200e835966e187e8d00011a8c75
+
+Curve = P-224
+Private = ad2519bc724d484e02a69f05149bb047714bf0f5986fac2e222cd946
+X = df9c1e0ef15e53b9f626e2be1cbe893639c06f3e0439ee95d7d4b1e3
+Y = 7a52a7386adda243efdf8941085c84e31239cab92b8017336748965e
+PeerX = 546578216250354e449e21546dd11cd1c5174236739acad9ce0f4512
+PeerY = d2a22fcd66d1abedc767668327c5cb9c599043276239cf3c8516af24
+Z = ad09c9ae4d2324ea81bb555b200d3c003e22a6870ee03b52df49e4de
+
+Curve = P-224
+Private = 3d312a9b9d8ed09140900bbac1e095527ebc9e3c6493bcf3666e3a29
+X = b4a0198dc8810e884425b750928b0c960c31f7a99663400b01a179df
+Y = 812b601bfc0738242c6f86f830f27acd632ca618a0b5280c9d5769f7
+PeerX = 1d46b1dc3a28123cb51346e67baec56404868678faf7d0e8b2afa22a
+PeerY = 0ec9e65ec97e218373e7fc115c2274d5b829a60d93f71e01d58136c3
+Z = ef029c28c68064b8abd2965a38c404fb5e944ace57e8638daba9d3cd
+
+Curve = P-224
+Private = 8ce0822dc24c153995755ac350737ef506641c7d752b4f9300c612ed
+X = 00dfc7ec137690cd6d12fdb2fd0b8c5314582108769c2b722ffb3958
+Y = 5eef3da4ba458127346bb64023868bddb7558a2ecfc813645f4ce9fe
+PeerX = 266d038cc7a4fe21f6c976318e827b82bb5b8f7443a55298136506e0
+PeerY = df123d98a7a20bbdf3943df2e3563422f8c0cf74d53aaabdd7c973ba
+Z = f83c16661dfcbad021cc3b5a5af51d9a18db4653866b3ff90787ce3e
+
+Curve = P-224
+Private = 0ff9b485325ab77f29e7bc379fed74bfac859482da0dee7528c19db2
+X = 7e603e6976db83c36011508fa695d1b515249e2e54b48fcbcfb90247
+Y = 0179a600ce86adfca9b1b931fa5173d618da09e841803d19b0264286
+PeerX = eb0a09f7a1c236a61f595809ec5670efd92e4598d5e613e092cdfdca
+PeerY = 50787ae2f2f15b88bc10f7b5f0aee1418373f16153aebd1fba54288d
+Z = f51258c63f232e55a66aa25ebd597b2018d1052c02eeb63866758005
+
+Curve = P-224
+Private = 19cf5ff6306467f28b9fe0675a43c0582552c8c12e59ce7c38f292b1
+X = fc20e906e609c112cfc2e0fea6303882c5db94e87e022373ab2c082a
+Y = aecdf1daa71782bc5a26bbbd8d7e8a76490e26abc17dffc774bd7341
+PeerX = 6b2f6b18a587f562ffc61bd9b0047322286986a78f1fd139b84f7c24
+PeerY = 7096908e4615266be59a53cd655515056ff92370a6271a5d3823d704
+Z = 7fdc969a186ff18429f2a276dac43beea21182d82ce2e5a0876552b1
+
+Curve = P-224
+Private = 90a15368e3532c0b1e51e55d139447c2c89bc160719d697291ea7c14
+X = c6837d506e976da7db3ad1267c359dff2ea6fb0b7f7f8e77024c59e9
+Y = 67eb491d2fc8a530c46525d2a8b2d7c1df5fba1ae740a4649c683ee6
+PeerX = 328101ba826acd75ff9f34d5574ce0dbc92f709bad8d7a33c47940c1
+PeerY = df39f1ea88488c55d5538160878b9ced18a887ea261dd712d14024ff
+Z = 3d60ab6db2b3ffe2d29ccff46d056e54230cf34982e241556ed2920c
+
+Curve = P-224
+Private = 8e0838e05e1721491067e1cabc2e8051b290e2616eec427b7121897d
+X = e9150f770075626019e18f95473b71e6828041791d3f08d3faeeaa2b
+Y = 475f70735eaae52308a3b763dc88efe18ab590ebafa035f6e08b001c
+PeerX = 0081e34270871e2ebbd94183f617b4ae15f0416dd634fe6e934cf3c0
+PeerY = 3a1e9f38a7b90b7317d26b9f6311063ab58b268cf489b2e50386d5d6
+Z = 9116d72786f4db5df7a8b43078c6ab9160d423513d35ea5e2559306d
+
+Curve = P-224
+Private = 38106e93f16a381adb1d72cee3da66ae462ad4bbfea9ecdf35d0814e
+X = 7be6c4c917829ab657dd79e8637d7aefd2f81f0de7654d957e97658d
+Y = 430d22d9e8438310f61e0d43f25fa3e34585f432baad27db3021bf0d
+PeerX = 2623632fdf0bd856805a69aa186d4133ef5904e1f655a972d66cce07
+PeerY = 2cef9728dd06fb8b50150f529b695076d4507983912585c89bd0682e
+Z = 207c53dcefac789aaa0276d9200b3a940ce5f2296f4cb2e81a185d3d
+
+Curve = P-224
+Private = e5d1718431cf50f6cbd1bc8019fa16762dfa12c989e5999977fb4ea2
+X = 2ea4966e7f92ed7f5cc61fde792045f63b731d6e7d0de2577f2d8ece
+Y = 1c4a7b1ede6f839162292df424be78e8176fb6f942a3c02391700f31
+PeerX = 8ee4d1dcc31dee4bf6fe21ca8a587721d910acfb122c16c2a77a8152
+PeerY = 4ebf323fff04eb477069a0ac68b345f6b1ae134efc31940e513cb99f
+Z = 10e467da34f48ad7072005bccd6da1b2ba3f71eafa1c393842f91d74
+
+Curve = P-224
+Private = 3d635691b62a9a927c633951c9369c8862bd2119d30970c2644727d6
+X = 438bbb980517afb20be1d674e3ac2b31cef07a9b23fb8f6e38e0d6c0
+Y = 0be5f1c47d58d21b6ed28423b32f5a94750da47edcef33ea79942afd
+PeerX = 97dcbe6d28335882a6d193cc54a1063dd0775dc328565300bb99e691
+PeerY = dad11dd5ece8cfd9f97c9a526e4a1506e6355969ee87826fc38bcd24
+Z = 82fd2f9c60c4f999ac00bbe64bfc11da8ff8cda2e499fced65230bb1
+
+Curve = P-224
+Private = acf3c85bbdc379f02f5ea36e7f0f53095a9e7046a28685a8659bf798
+X = ff7511215c71d796bd646e8474be4416b91684ce0d269ef6f422013b
+Y = b7bf5e79b5a9393bb9ea42c0bdb2d3c2dc806e1a7306aa58e4fdbea5
+PeerX = ce9126dd53972dea1de1d11efef900de34b661859c4648c5c0e534f7
+PeerY = e113b6f2c1659d07f2716e64a83c18bbce344dd2121fe85168eae085
+Z = 530f7e7fc932613b29c981f261cb036cba3f1df3864e0e1cba2685a2
+
+Curve = P-224
+Private = cffd62cb00a0e3163fbf2c397fadc9618210f86b4f54a675287305f0
+X = 04bf4d948f4430d18b4ed6c96dbaf981fa11a403ed16887f06754981
+Y = 7c1326a9cef51f79d4e78303d6064b459f612584ac2fdf593d7d5d84
+PeerX = 84419967d6cfad41e75a02b6da605a97949a183a97c306c4b46e66a5
+PeerY = 5cc9b259718b1bc8b144fde633a894616ffd59a3a6d5d8e942c7cbb7
+Z = 49f6fd0139248ef4df2db05d1319bd5b1489e249827a45a8a5f12427
+
+Curve = P-224
+Private = 85f903e43943d13c68932e710e80de52cbc0b8f1a1418ea4da079299
+X = 970a4a7e01d4188497ceb46955eb1b842d9085819a9b925c84529d3d
+Y = dfa2526480f833ea0edbd204e4e365fef3472888fe7d9691c3ebc09f
+PeerX = 7c9cac35768063c2827f60a7f51388f2a8f4b7f8cd736bd6bc337477
+PeerY = 29ee6b849c6025d577dbcc55fbd17018f4edbc2ef105b004d6257bcd
+Z = 8f7e34e597ae8093b98270a74a8dfcdbed457f42f43df487c5487161
+
+Curve = P-224
+Private = cce64891a3d0129fee0d4a96cfbe7ac470b85e967529057cfa31a1d9
+X = a6b29632db94da2125dc1cf80e03702687b2acc1122022fa2174765a
+Y = 61723edd73e10daed73775278f1958ba56f1fc9d085ebc2b64c84fe5
+PeerX = 085a7642ad8e59b1a3e8726a7547afbecffdac1dab7e57230c6a9df4
+PeerY = f91c36d881fe9b8047a3530713554a1af4c25c5a8e654dcdcf689f2e
+Z = 71954e2261e8510be1a060733671d2e9d0a2d012eb4e09556d697d2a
+
+Curve = P-256
+Private = 7d7dc5f71eb29ddaf80d6214632eeae03d9058af1fb6d22ed80badb62bc1a534
+X = ead218590119e8876b29146ff89ca61770c4edbbf97d38ce385ed281d8a6b230
+Y = 28af61281fd35e2fa7002523acc85a429cb06ee6648325389f59edfce1405141
+PeerX = 700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287
+PeerY = db71e509e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ac
+Z = 46fc62106420ff012e54a434fbdd2d25ccc5852060561e68040dd7778997bd7b
+
+Curve = P-256
+Private = 38f65d6dce47676044d58ce5139582d568f64bb16098d179dbab07741dd5caf5
+X = 119f2f047902782ab0c9e27a54aff5eb9b964829ca99c06b02ddba95b0a3f6d0
+Y = 8f52b726664cac366fc98ac7a012b2682cbd962e5acb544671d41b9445704d1d
+PeerX = 809f04289c64348c01515eb03d5ce7ac1a8cb9498f5caa50197e58d43a86a7ae
+PeerY = b29d84e811197f25eba8f5194092cb6ff440e26d4421011372461f579271cda3
+Z = 057d636096cb80b67a8c038c890e887d1adfa4195e9b3ce241c8a778c59cda67
+
+Curve = P-256
+Private = 1accfaf1b97712b85a6f54b148985a1bdc4c9bec0bd258cad4b3d603f49f32c8
+X = d9f2b79c172845bfdb560bbb01447ca5ecc0470a09513b6126902c6b4f8d1051
+Y = f815ef5ec32128d3487834764678702e64e164ff7315185e23aff5facd96d7bc
+PeerX = a2339c12d4a03c33546de533268b4ad667debf458b464d77443636440ee7fec3
+PeerY = ef48a3ab26e20220bcda2c1851076839dae88eae962869a497bf73cb66faf536
+Z = 2d457b78b4614132477618a5b077965ec90730a8c81a1c75d6d4ec68005d67ec
+
+Curve = P-256
+Private = 207c43a79bfee03db6f4b944f53d2fb76cc49ef1c9c4d34d51b6c65c4db6932d
+X = 24277c33f450462dcb3d4801d57b9ced05188f16c28eda873258048cd1607e0d
+Y = c4789753e2b1f63b32ff014ec42cd6a69fac81dfe6d0d6fd4af372ae27c46f88
+PeerX = df3989b9fa55495719b3cf46dccd28b5153f7808191dd518eff0c3cff2b705ed
+PeerY = 422294ff46003429d739a33206c8752552c8ba54a270defc06e221e0feaf6ac4
+Z = 96441259534b80f6aee3d287a6bb17b5094dd4277d9e294f8fe73e48bf2a0024
+
+Curve = P-256
+Private = 59137e38152350b195c9718d39673d519838055ad908dd4757152fd8255c09bf
+X = a8c5fdce8b62c5ada598f141adb3b26cf254c280b2857a63d2ad783a73115f6b
+Y = 806e1aafec4af80a0d786b3de45375b517a7e5b51ffb2c356537c9e6ef227d4a
+PeerX = 41192d2813e79561e6a1d6f53c8bc1a433a199c835e141b05a74a97b0faeb922
+PeerY = 1af98cc45e98a7e041b01cf35f462b7562281351c8ebf3ffa02e33a0722a1328
+Z = 19d44c8d63e8e8dd12c22a87b8cd4ece27acdde04dbf47f7f27537a6999a8e62
+
+Curve = P-256
+Private = f5f8e0174610a661277979b58ce5c90fee6c9b3bb346a90a7196255e40b132ef
+X = 7b861dcd2844a5a8363f6b8ef8d493640f55879217189d80326aad9480dfc149
+Y = c4675b45eeb306405f6c33c38bc69eb2bdec9b75ad5af4706aab84543b9cc63a
+PeerX = 33e82092a0f1fb38f5649d5867fba28b503172b7035574bf8e5b7100a3052792
+PeerY = f2cf6b601e0a05945e335550bf648d782f46186c772c0f20d3cd0d6b8ca14b2f
+Z = 664e45d5bba4ac931cd65d52017e4be9b19a515f669bea4703542a2c525cd3d3
+
+Curve = P-256
+Private = 3b589af7db03459c23068b64f63f28d3c3c6bc25b5bf76ac05f35482888b5190
+X = 9fb38e2d58ea1baf7622e96720101cae3cde4ba6c1e9fa26d9b1de0899102863
+Y = d5561b900406edf50802dd7d73e89395f8aed72fba0e1d1b61fe1d22302260f0
+PeerX = 6a9e0c3f916e4e315c91147be571686d90464e8bf981d34a90b6353bca6eeba7
+PeerY = 40f9bead39c2f2bcc2602f75b8a73ec7bdffcbcead159d0174c6c4d3c5357f05
+Z = ca342daa50dc09d61be7c196c85e60a80c5cb04931746820be548cdde055679d
+
+Curve = P-256
+Private = d8bf929a20ea7436b2461b541a11c80e61d826c0a4c9d322b31dd54e7f58b9c8
+X = 20f07631e4a6512a89ad487c4e9d63039e579cb0d7a556cb9e661cd59c1e7fa4
+Y = 6de91846b3eee8a5ec09c2ab1f41e21bd83620ccdd1bdce3ab7ea6e02dd274f5
+PeerX = a9c0acade55c2a73ead1a86fb0a9713223c82475791cd0e210b046412ce224bb
+PeerY = f6de0afa20e93e078467c053d241903edad734c6b403ba758c2b5ff04c9d4229
+Z = 35aa9b52536a461bfde4e85fc756be928c7de97923f0416c7a3ac8f88b3d4489
+
+Curve = P-256
+Private = 0f9883ba0ef32ee75ded0d8bda39a5146a29f1f2507b3bd458dbea0b2bb05b4d
+X = abb61b423be5d6c26e21c605832c9142dc1dfe5a5fff28726737936e6fbf516d
+Y = 733d2513ef58beab202090586fac91bf0fee31e80ab33473ab23a2d89e58fad6
+PeerX = 94e94f16a98255fff2b9ac0c9598aac35487b3232d3231bd93b7db7df36f9eb9
+PeerY = d8049a43579cfa90b8093a94416cbefbf93386f15b3f6e190b6e3455fedfe69a
+Z = 605c16178a9bc875dcbff54d63fe00df699c03e8a888e9e94dfbab90b25f39b4
+
+Curve = P-256
+Private = 2beedb04b05c6988f6a67500bb813faf2cae0d580c9253b6339e4a3337bb6c08
+X = 3d63e429cb5fa895a9247129bf4e48e89f35d7b11de8158efeb3e106a2a87395
+Y = 0cae9e477ef41e7c8c1064379bb7b554ddcbcae79f9814281f1e50f0403c61f3
+PeerX = e099bf2a4d557460b5544430bbf6da11004d127cb5d67f64ab07c94fcdf5274f
+PeerY = d9c50dbe70d714edb5e221f4e020610eeb6270517e688ca64fb0e98c7ef8c1c5
+Z = f96e40a1b72840854bb62bc13c40cc2795e373d4e715980b261476835a092e0b
+
+Curve = P-256
+Private = 77c15dcf44610e41696bab758943eff1409333e4d5a11bbe72c8f6c395e9f848
+X = ad5d13c3db508ddcd38457e5991434a251bed49cf5ddcb59cdee73865f138c9f
+Y = 62cec1e70588aa4fdfc7b9a09daa678081c04e1208b9d662b8a2214bf8e81a21
+PeerX = f75a5fe56bda34f3c1396296626ef012dc07e4825838778a645c8248cff01658
+PeerY = 33bbdf1b1772d8059df568b061f3f1122f28a8d819167c97be448e3dc3fb0c3c
+Z = 8388fa79c4babdca02a8e8a34f9e43554976e420a4ad273c81b26e4228e9d3a3
+
+Curve = P-256
+Private = 42a83b985011d12303db1a800f2610f74aa71cdf19c67d54ce6c9ed951e9093e
+X = ab48caa61ea35f13f8ed07ffa6a13e8db224dfecfae1a7df8b1bb6ebaf0cb97d
+Y = 1274530ca2c385a3218bddfbcbf0b4024c9badd5243bff834ebff24a8618dccb
+PeerX = 2db4540d50230756158abf61d9835712b6486c74312183ccefcaef2797b7674d
+PeerY = 62f57f314e3f3495dc4e099012f5e0ba71770f9660a1eada54104cdfde77243e
+Z = 72877cea33ccc4715038d4bcbdfe0e43f42a9e2c0c3b017fc2370f4b9acbda4a
+
+Curve = P-256
+Private = ceed35507b5c93ead5989119b9ba342cfe38e6e638ba6eea343a55475de2800b
+X = 9a8cd9bd72e71752df91440f77c547509a84df98114e7de4f26cdb39234a625d
+Y = d07cfc84c8e144fab2839f5189bb1d7c88631d579bbc58012ed9a2327da52f62
+PeerX = cd94fc9497e8990750309e9a8534fd114b0a6e54da89c4796101897041d14ecb
+PeerY = c3def4b5fe04faee0a11932229fff563637bfdee0e79c6deeaf449f85401c5c4
+Z = e4e7408d85ff0e0e9c838003f28cdbd5247cdce31f32f62494b70e5f1bc36307
+
+Curve = P-256
+Private = 43e0e9d95af4dc36483cdd1968d2b7eeb8611fcce77f3a4e7d059ae43e509604
+X = f989cf8ee956a82e7ebd9881cdbfb2fd946189b08db53559bc8cfdd48071eb14
+Y = 5eff28f1a18a616b04b7d337868679f6dd84f9a7b3d7b6f8af276c19611a541d
+PeerX = 15b9e467af4d290c417402e040426fe4cf236bae72baa392ed89780dfccdb471
+PeerY = cdf4e9170fb904302b8fd93a820ba8cc7ed4efd3a6f2d6b05b80b2ff2aee4e77
+Z = ed56bcf695b734142c24ecb1fc1bb64d08f175eb243a31f37b3d9bb4407f3b96
+
+Curve = P-256
+Private = b2f3600df3368ef8a0bb85ab22f41fc0e5f4fdd54be8167a5c3cd4b08db04903
+X = 69c627625b36a429c398b45c38677cb35d8beb1cf78a571e40e99fe4eac1cd4e
+Y = 81690112b0a88f20f7136b28d7d47e5fbc2ada3c8edd87589bc19ec9590637bd
+PeerX = 49c503ba6c4fa605182e186b5e81113f075bc11dcfd51c932fb21e951eee2fa1
+PeerY = 8af706ff0922d87b3f0c5e4e31d8b259aeb260a9269643ed520a13bb25da5924
+Z = bc5c7055089fc9d6c89f83c1ea1ada879d9934b2ea28fcf4e4a7e984b28ad2cf
+
+Curve = P-256
+Private = 4002534307f8b62a9bf67ff641ddc60fef593b17c3341239e95bdb3e579bfdc8
+X = 5fe964671315a18aa68a2a6e3dd1fde7e23b8ce7181471cfac43c99e1ae80262
+Y = d5827be282e62c84de531b963884ba832db5d6b2c3a256f0e604fe7e6b8a7f72
+PeerX = 19b38de39fdd2f70f7091631a4f75d1993740ba9429162c2a45312401636b29c
+PeerY = 09aed7232b28e060941741b6828bcdfa2bc49cc844f3773611504f82a390a5ae
+Z = 9a4e8e657f6b0e097f47954a63c75d74fcba71a30d83651e3e5a91aa7ccd8343
+
+Curve = P-256
+Private = 4dfa12defc60319021b681b3ff84a10a511958c850939ed45635934ba4979147
+X = c9b2b8496f1440bd4a2d1e52752fd372835b364885e154a7dac49295f281ec7c
+Y = fbe6b926a8a4de26ccc83b802b1212400754be25d9f3eeaf008b09870ae76321
+PeerX = 2c91c61f33adfe9311c942fdbff6ba47020feff416b7bb63cec13faf9b099954
+PeerY = 6cab31b06419e5221fca014fb84ec870622a1b12bab5ae43682aa7ea73ea08d0
+Z = 3ca1fc7ad858fb1a6aba232542f3e2a749ffc7203a2374a3f3d3267f1fc97b78
+
+Curve = P-256
+Private = 1331f6d874a4ed3bc4a2c6e9c74331d3039796314beee3b7152fcdba5556304e
+X = 59e1e101521046ad9cf1d082e9d2ec7dd22530cce064991f1e55c5bcf5fcb591
+Y = 482f4f673176c8fdaa0bb6e59b15a3e47454e3a04297d3863c9338d98add1f37
+PeerX = a28a2edf58025668f724aaf83a50956b7ac1cfbbff79b08c3bf87dfd2828d767
+PeerY = dfa7bfffd4c766b86abeaf5c99b6e50cb9ccc9d9d00b7ffc7804b0491b67bc03
+Z = 1aaabe7ee6e4a6fa732291202433a237df1b49bc53866bfbe00db96a0f58224f
+
+Curve = P-256
+Private = dd5e9f70ae740073ca0204df60763fb6036c45709bf4a7bb4e671412fad65da3
+X = 30b9db2e2e977bcdc98cb87dd736cbd8e78552121925cf16e1933657c2fb2314
+Y = 6a45028800b81291bce5c2e1fed7ded650620ebbe6050c6f3a7f0dfb4673ab5c
+PeerX = a2ef857a081f9d6eb206a81c4cf78a802bdf598ae380c8886ecd85fdc1ed7644
+PeerY = 563c4c20419f07bc17d0539fade1855e34839515b892c0f5d26561f97fa04d1a
+Z = 430e6a4fba4449d700d2733e557f66a3bf3d50517c1271b1ddae1161b7ac798c
+
+Curve = P-256
+Private = 5ae026cfc060d55600717e55b8a12e116d1d0df34af831979057607c2d9c2f76
+X = 46c9ebd1a4a3c8c0b6d572b5dcfba12467603208a9cb5d2acfbb733c40cf6391
+Y = 46c913a27d044185d38b467ace011e04d4d9bbbb8cb9ae25fa92aaf15a595e86
+PeerX = ccd8a2d86bc92f2e01bce4d6922cf7fe1626aed044685e95e2eebd464505f01f
+PeerY = e9ddd583a9635a667777d5b8a8f31b0f79eba12c75023410b54b8567dddc0f38
+Z = 1ce9e6740529499f98d1f1d71329147a33df1d05e4765b539b11cf615d6974d3
+
+Curve = P-256
+Private = b601ac425d5dbf9e1735c5e2d5bdb79ca98b3d5be4a2cfd6f2273f150e064d9d
+X = 7c9e950841d26c8dde8994398b8f5d475a022bc63de7773fcf8d552e01f1ba0a
+Y = cc42b9885c9b3bee0f8d8c57d3a8f6355016c019c4062fa22cff2f209b5cc2e1
+PeerX = c188ffc8947f7301fb7b53e36746097c2134bf9cc981ba74b4e9c4361f595e4e
+PeerY = bf7d2f2056e72421ef393f0c0f2b0e00130e3cac4abbcc00286168e85ec55051
+Z = 4690e3743c07d643f1bc183636ab2a9cb936a60a802113c49bb1b3f2d0661660
+
+Curve = P-256
+Private = fefb1dda1845312b5fce6b81b2be205af2f3a274f5a212f66c0d9fc33d7ae535
+X = 38b54db85500cb20c61056edd3d88b6a9dc26780a047f213a6e1b900f76596eb
+Y = 6387e4e5781571e4eb8ae62991a33b5dc33301c5bc7e125d53794a39160d8fd0
+PeerX = 317e1020ff53fccef18bf47bb7f2dd7707fb7b7a7578e04f35b3beed222a0eb6
+PeerY = 09420ce5a19d77c6fe1ee587e6a49fbaf8f280e8df033d75403302e5a27db2ae
+Z = 30c2261bd0004e61feda2c16aa5e21ffa8d7e7f7dbf6ec379a43b48e4b36aeb0
+
+Curve = P-256
+Private = 334ae0c4693d23935a7e8e043ebbde21e168a7cba3fa507c9be41d7681e049ce
+X = 3f2bf1589abf3047bf3e54ac9a95379bff95f8f55405f64eca36a7eebe8ffca7
+Y = 5212a94e66c5ae9a8991872f66a72723d80ec5b2e925745c456f5371943b3a06
+PeerX = 45fb02b2ceb9d7c79d9c2fa93e9c7967c2fa4df5789f9640b24264b1e524fcb1
+PeerY = 5c6e8ecf1f7d3023893b7b1ca1e4d178972ee2a230757ddc564ffe37f5c5a321
+Z = 2adae4a138a239dcd93c243a3803c3e4cf96e37fe14e6a9b717be9599959b11c
+
+Curve = P-256
+Private = 2c4bde40214fcc3bfc47d4cf434b629acbe9157f8fd0282540331de7942cf09d
+X = 29c0807f10cbc42fb45c9989da50681eead716daa7b9e91fd32e062f5eb92ca0
+Y = ff1d6d1955d7376b2da24fe1163a271659136341bc2eb1195fc706dc62e7f34d
+PeerX = a19ef7bff98ada781842fbfc51a47aff39b5935a1c7d9625c8d323d511c92de6
+PeerY = e9c184df75c955e02e02e400ffe45f78f339e1afe6d056fb3245f4700ce606ef
+Z = 2e277ec30f5ea07d6ce513149b9479b96e07f4b6913b1b5c11305c1444a1bc0b
+
+Curve = P-256
+Private = 85a268f9d7772f990c36b42b0a331adc92b5941de0b862d5d89a347cbf8faab0
+X = 9cf4b98581ca1779453cc816ff28b4100af56cf1bf2e5bc312d83b6b1b21d333
+Y = 7a5504fcac5231a0d12d658218284868229c844a04a3450d6c7381abe080bf3b
+PeerX = 356c5a444c049a52fee0adeb7e5d82ae5aa83030bfff31bbf8ce2096cf161c4b
+PeerY = 57d128de8b2a57a094d1a001e572173f96e8866ae352bf29cddaf92fc85b2f92
+Z = 1e51373bd2c6044c129c436e742a55be2a668a85ae08441b6756445df5493857
+
+Curve = P-384
+Private = 3cc3122a68f0d95027ad38c067916ba0eb8c38894d22e1b15618b6818a661774ad463b205da88cf699ab4d43c9cf98a1
+X = 9803807f2f6d2fd966cdd0290bd410c0190352fbec7ff6247de1302df86f25d34fe4a97bef60cff548355c015dbb3e5f
+Y = ba26ca69ec2f5b5d9dad20cc9da711383a9dbe34ea3fa5a2af75b46502629ad54dd8b7d73a8abb06a3a3be47d650cc99
+PeerX = a7c76b970c3b5fe8b05d2838ae04ab47697b9eaf52e764592efda27fe7513272734466b400091adbf2d68c58e0c50066
+PeerY = ac68f19f2e1cb879aed43a9969b91a0839c4c38a49749b661efedf243451915ed0905a32b060992b468c64766fc8437a
+Z = 5f9d29dc5e31a163060356213669c8ce132e22f57c9a04f40ba7fcead493b457e5621e766c40a2e3d4d6a04b25e533f1
+
+Curve = P-384
+Private = 92860c21bde06165f8e900c687f8ef0a05d14f290b3f07d8b3a8cc6404366e5d5119cd6d03fb12dc58e89f13df9cd783
+X = ea4018f5a307c379180bf6a62fd2ceceebeeb7d4df063a66fb838aa35243419791f7e2c9d4803c9319aa0eb03c416b66
+Y = 68835a91484f05ef028284df6436fb88ffebabcdd69ab0133e6735a1bcfb37203d10d340a8328a7b68770ca75878a1a6
+PeerX = 30f43fcf2b6b00de53f624f1543090681839717d53c7c955d1d69efaf0349b7363acb447240101cbb3af6641ce4b88e0
+PeerY = 25e46c0c54f0162a77efcc27b6ea792002ae2ba82714299c860857a68153ab62e525ec0530d81b5aa15897981e858757
+Z = a23742a2c267d7425fda94b93f93bbcc24791ac51cd8fd501a238d40812f4cbfc59aac9520d758cf789c76300c69d2ff
+
+Curve = P-384
+Private = 12cf6a223a72352543830f3f18530d5cb37f26880a0b294482c8a8ef8afad09aa78b7dc2f2789a78c66af5d1cc553853
+X = fcfcea085e8cf74d0dced1620ba8423694f903a219bbf901b0b59d6ac81baad316a242ba32bde85cb248119b852fab66
+Y = 972e3c68c7ab402c5836f2a16ed451a33120a7750a6039f3ff15388ee622b7065f7122bf6d51aefbc29b37b03404581b
+PeerX = 1aefbfa2c6c8c855a1a216774550b79a24cda37607bb1f7cc906650ee4b3816d68f6a9c75da6e4242cebfb6652f65180
+PeerY = 419d28b723ebadb7658fcebb9ad9b7adea674f1da3dc6b6397b55da0f61a3eddacb4acdb14441cb214b04a0844c02fa3
+Z = 3d2e640f350805eed1ff43b40a72b2abed0a518bcebe8f2d15b111b6773223da3c3489121db173d414b5bd5ad7153435
+
+Curve = P-384
+Private = 8dd48063a3a058c334b5cc7a4ce07d02e5ee6d8f1f3c51a1600962cbab462690ae3cd974fb39e40b0e843daa0fd32de1
+X = e38c9846248123c3421861ea4d32669a7b5c3c08376ad28104399494c84ff5efa3894adb2c6cbe8c3c913ef2eec5bd3c
+Y = 9fa84024a1028796df84021f7b6c9d02f0f4bd1a612a03cbf75a0beea43fef8ae84b48c60172aadf09c1ad016d0bf3ce
+PeerX = 8bc089326ec55b9cf59b34f0eb754d93596ca290fcb3444c83d4de3a5607037ec397683f8cef07eab2fe357eae36c449
+PeerY = d9d16ce8ac85b3f1e94568521aae534e67139e310ec72693526aa2e927b5b322c95a1a033c229cb6770c957cd3148dd7
+Z = 6a42cfc392aba0bfd3d17b7ccf062b91fc09bbf3417612d02a90bdde62ae40c54bb2e56e167d6b70db670097eb8db854
+
+Curve = P-384
+Private = 84ece6cc3429309bd5b23e959793ed2b111ec5cb43b6c18085fcaea9efa0685d98a6262ee0d330ee250bc8a67d0e733f
+X = 3222063a2997b302ee60ee1961108ff4c7acf1c0ef1d5fb0d164b84bce71c431705cb9aea9a45f5d73806655a058bee3
+Y = e61fa9e7fbe7cd43abf99596a3d3a039e99fa9dc93b0bdd9cad81966d17eeaf557068afa7c78466bb5b22032d1100fa6
+PeerX = eb952e2d9ac0c20c6cc48fb225c2ad154f53c8750b003fd3b4ed8ed1dc0defac61bcdde02a2bcfee7067d75d342ed2b0
+PeerY = f1828205baece82d1b267d0d7ff2f9c9e15b69a72df47058a97f3891005d1fb38858f5603de840e591dfa4f6e7d489e1
+Z = ce7ba454d4412729a32bb833a2d1fd2ae612d4667c3a900e069214818613447df8c611de66da200db7c375cf913e4405
+
+Curve = P-384
+Private = 68fce2121dc3a1e37b10f1dde309f9e2e18fac47cd1770951451c3484cdb77cb136d00e731260597cc2859601c01a25b
+X = 868be0e694841830e424d913d8e7d86b84ee1021d82b0ecf523f09fe89a76c0c95c49f2dfbcf829c1e39709d55efbb3b
+Y = 9195eb183675b40fd92f51f37713317e4a9b4f715c8ab22e0773b1bc71d3a219f05b8116074658ee86b52e36f3897116
+PeerX = 441d029e244eb7168d647d4df50db5f4e4974ab3fdaf022aff058b3695d0b8c814cc88da6285dc6df1ac55c553885003
+PeerY = e8025ac23a41d4b1ea2aa46c50c6e479946b59b6d76497cd9249977e0bfe4a6262622f13d42a3c43d66bdbb30403c345
+Z = ba69f0acdf3e1ca95caaac4ecaf475bbe51b54777efce01ca381f45370e486fe87f9f419b150c61e329a286d1aa265ec
+
+Curve = P-384
+Private = b1764c54897e7aae6de9e7751f2f37de849291f88f0f91093155b858d1cc32a3a87980f706b86cc83f927bdfdbeae0bd
+X = c371222feaa6770c6f3ea3e0dac9740def4fcf821378b7f91ff937c21e0470f70f3a31d5c6b2912195f10926942b48ae
+Y = 047d6b4d765123563f81116bc665b7b8cc6207830d805fd84da7cb805a65baa7c12fd592d1b5b5e3e65d9672a9ef7662
+PeerX = 3d4e6bf08a73404accc1629873468e4269e82d90d832e58ad72142639b5a056ad8d35c66c60e8149fac0c797bceb7c2f
+PeerY = 9b0308dc7f0e6d29f8c277acbc65a21e5adb83d11e6873bc0a07fda0997f482504602f59e10bc5cb476b83d0a4f75e71
+Z = 1a6688ee1d6e59865d8e3ada37781d36bb0c2717eef92e61964d3927cb765c2965ea80f7f63e58c322ba0397faeaf62b
+
+Curve = P-384
+Private = f0f7a96e70d98fd5a30ad6406cf56eb5b72a510e9f192f50e1f84524dbf3d2439f7287bb36f5aa912a79deaab4adea82
+X = 99c8c41cb1ab5e0854a346e4b08a537c1706a61553387c8d94943ab15196d40dbaa55b8210a77a5d00915f2c4ea69eab
+Y = 5531065bdcf17bfb3cb55a02e41a57c7f694c383ad289f900fbd656c2233a93c92e933e7a26f54cbb56f0ad875c51bb0
+PeerX = f5f6bef1d110da03be0017eac760cc34b24d092f736f237bc7054b3865312a813bcb62d297fb10a4f7abf54708fe2d3d
+PeerY = 06fdf8d7dc032f4e10010bf19cbf6159321252ff415fb91920d438f24e67e60c2eb0463204679fa356af44cea9c9ebf5
+Z = d06a568bf2336b90cbac325161be7695eacb2295f599500d787f072612aca313ee5d874f807ddef6c1f023fe2b6e7cd0
+
+Curve = P-384
+Private = 9efb87ddc61d43c482ba66e1b143aef678fbd0d1bebc2000941fabe677fe5b706bf78fce36d100b17cc787ead74bbca2
+X = 4c34efee8f0c95565d2065d1bbac2a2dd25ae964320eb6bccedc5f3a9b42a881a1afca1bb6b880584fa27b01c193cd92
+Y = d8fb01dbf7cd0a3868c26b951f393c3c56c2858cee901f7793ff5d271925d13a41f8e52409f4eba1990f33acb0bac669
+PeerX = 7cdec77e0737ea37c67b89b7137fe38818010f4464438ee4d1d35a0c488cad3fde2f37d00885d36d3b795b9f93d23a67
+PeerY = 28c42ee8d6027c56cf979ba4c229fdb01d234944f8ac433650112c3cf0f02844e888a3569dfef7828a8a884589aa055e
+Z = bb3b1eda9c6560d82ff5bee403339f1e80342338a991344853b56b24f109a4d94b92f654f0425edd4c205903d7586104
+
+Curve = P-384
+Private = d787a57fde22ec656a0a525cf3c738b30d73af61e743ea90893ecb2d7b622add2f94ee25c2171467afb093f3f84d0018
+X = 171546923b87b2cbbad664f01ce932bf09d6a6118168678446bfa9f0938608cb4667a98f4ec8ac1462285c2508f74862
+Y = fa41cb4db68ae71f1f8a3e8939dc52c2dec61a83c983beb2a02baf29ec49278088882ed0cf56c74b5c173b552ccf63cf
+PeerX = 8eeea3a319c8df99fbc29cb55f243a720d95509515ee5cc587a5c5ae22fbbd009e626db3e911def0b99a4f7ae304b1ba
+PeerY = 73877dc94db9adddc0d9a4b24e8976c22d73c844370e1ee857f8d1b129a3bd5f63f40caf3bd0533e38a5f5777074ff9e
+Z = 1e97b60add7cb35c7403dd884c0a75795b7683fff8b49f9d8672a8206bfdcf0a106b8768f983258c74167422e44e4d14
+
+Curve = P-384
+Private = 83d70f7b164d9f4c227c767046b20eb34dfc778f5387e32e834b1e6daec20edb8ca5bb4192093f543b68e6aeb7ce788b
+X = 57cd770f3bbcbe0c78c770eab0b169bc45e139f86378ffae1c2b16966727c2f2eb724572b8f3eb228d130db4ff862c63
+Y = 7ec5c8813b685558d83e924f14bc719f6eb7ae0cbb2c474227c5bda88637a4f26c64817929af999592da6f787490332f
+PeerX = a721f6a2d4527411834b13d4d3a33c29beb83ab7682465c6cbaf6624aca6ea58c30eb0f29dd842886695400d7254f20f
+PeerY = 14ba6e26355109ad35129366d5e3a640ae798505a7fa55a96a36b5dad33de00474f6670f522214dd7952140ab0a7eb68
+Z = 1023478840e54775bfc69293a3cf97f5bc914726455c66538eb5623e218feef7df4befa23e09d77145ad577db32b41f9
+
+Curve = P-384
+Private = 8f558e05818b88ed383d5fca962e53413db1a0e4637eda194f761944cbea114ab9d5da175a7d57882550b0e432f395a9
+X = 9a2f57f4867ce753d72b0d95195df6f96c1fae934f602efd7b6a54582f556cfa539d89005ca2edac08ad9b72dd1f60ba
+Y = d9b94ee82da9cc601f346044998ba387aee56404dc6ecc8ab2b590443319d0b2b6176f9d0eac2d44678ed561607d09a9
+PeerX = d882a8505c2d5cb9b8851fc676677bb0087681ad53faceba1738286b45827561e7da37b880276c656cfc38b32ade847e
+PeerY = 34b314bdc134575654573cffaf40445da2e6aaf987f7e913cd4c3091523058984a25d8f21da8326192456c6a0fa5f60c
+Z = 6ad6b9dc8a6cf0d3691c501cbb967867f6e4bbb764b60dbff8fcff3ed42dbba39d63cf325b4b4078858495ddee75f954
+
+Curve = P-384
+Private = 0f5dee0affa7bbf239d5dff32987ebb7cf84fcceed643e1d3c62d0b3352aec23b6e5ac7fa4105c8cb26126ad2d1892cb
+X = 23346bdfbc9d7c7c736e02bdf607671ff6082fdd27334a8bc75f3b23681ebe614d0597dd614fae58677c835a9f0b273b
+Y = 82ba36290d2f94db41479eb45ab4eaf67928a2315138d59eecc9b5285dfddd6714f77557216ea44cc6fc119d8243efaf
+PeerX = 815c9d773dbf5fb6a1b86799966247f4006a23c92e68c55e9eaa998b17d8832dd4d84d927d831d4f68dac67c6488219f
+PeerY = e79269948b2611484560fd490feec887cb55ef99a4b524880fa7499d6a07283aae2afa33feab97deca40bc606c4d8764
+Z = cc9e063566d46b357b3fcae21827377331e5e290a36e60cd7c39102b828ae0b918dc5a02216b07fe6f1958d834e42437
+
+Curve = P-384
+Private = 037b633b5b8ba857c0fc85656868232e2febf59578718391b81da8541a00bfe53c30ae04151847f27499f8d7abad8cf4
+X = 8878ac8a947f7d5cb2b47aad24fbb8210d86126585399a2871f84aa9c5fde3074ae540c6bf82275ca822d0feb862bc74
+Y = 632f5cd2f900c2711c32f8930728eb647d31edd8d650f9654e7d33e5ed1b475489d08daa30d8cbcba6bfc3b60d9b5a37
+PeerX = 1c0eeda7a2be000c5bdcda0478aed4db733d2a9e341224379123ad847030f29e3b168fa18e89a3c0fba2a6ce1c28fc3b
+PeerY = ec8c1c83c118c4dbea94271869f2d868eb65e8b44e21e6f14b0f4d9b38c068daefa27114255b9a41d084cc4a1ad85456
+Z = deff7f03bd09865baf945e73edff6d5122c03fb561db87dec8662e09bed4340b28a9efe118337bb7d3d4f7f568635ff9
+
+Curve = P-384
+Private = e3d07106bedcc096e7d91630ffd3094df2c7859db8d7edbb2e37b4ac47f429a637d06a67d2fba33838764ef203464991
+X = e74a1a2b85f1cbf8dbbdf050cf1aff8acb02fda2fb6591f9d3cfe4e79d0ae938a9c1483e7b75f8db24505d65065cdb18
+Y = 1773ee591822f7abaa856a1a60bc0a5203548dbd1cb5025466eff8481bd07614eaa04a16c3db76905913e972a5b6b59d
+PeerX = c95c185e256bf997f30b311548ae7f768a38dee43eeeef43083f3077be70e2bf39ac1d4daf360c514c8c6be623443d1a
+PeerY = 3e63a663eaf75d8a765ab2b9a35513d7933fa5e26420a5244550ec6c3b6f033b96db2aca3d6ac6aab052ce929595aea5
+Z = c8b1038f735ad3bb3e4637c3e47eab487637911a6b7950a4e461948329d3923b969e5db663675623611a457fcda35a71
+
+Curve = P-384
+Private = f3f9b0c65a49a506632c8a45b10f66b5316f9eeb06fae218f2da62333f99905117b141c760e8974efc4af10570635791
+X = a4ad77aa7d86e5361118a6b921710c820721210712f4c347985fdee58aa4effa1e28be80a17b120b139f96300f89b49b
+Y = 1ddf22e07e03f1560d8f45a480094560dba9fae7f9531130c1b57ebb95982496524f31d3797793396fa823f22bdb4328
+PeerX = 3497238a7e6ad166df2dac039aa4dac8d17aa925e7c7631eb3b56e3aaa1c545fcd54d2e5985807910fb202b1fc191d2a
+PeerY = a49e5c487dcc7aa40a8f234c979446040d9174e3ad357d404d7765183195aed3f913641b90c81a306ebf0d8913861316
+Z = d337eaa32b9f716b8747b005b97a553c59dab0c51df41a2d49039cdae705aa75c7b9e7bc0b6a0e8c578c902bc4fff23e
+
+Curve = P-384
+Private = 59fce7fad7de28bac0230690c95710c720e528f9a4e54d3a6a8cd5fc5c5f21637031ce1c5b4e3d39647d8dcb9b794664
+X = 9c43bf971edf09402876ee742095381f78b1bd3aa39b5132af75dbfe7e98bd78bde10fe2e903c2b6379e1deee175a1b0
+Y = a6c58ecea5a477bb01bd543b339f1cc49f1371a2cda4d46eb4e53e250597942351a99665a122ffea9bde0636c375daf2
+PeerX = 90a34737d45b1aa65f74e0bd0659bc118f8e4b774b761944ffa6573c6df4f41dec0d11b697abd934d390871d4b453240
+PeerY = 9b590719bb3307c149a7817be355d684893a307764b512eeffe07cb699edb5a6ffbf8d6032e6c79d5e93e94212c2aa4e
+Z = 32d292b695a4488e42a7b7922e1ae537d76a3d21a0b2e36875f60e9f6d3e8779c2afb3a413b9dd79ae18e70b47d337c1
+
+Curve = P-384
+Private = 3e49fbf950a424c5d80228dc4bc35e9f6c6c0c1d04440998da0a609a877575dbe437d6a5cedaa2ddd2a1a17fd112aded
+X = 5a949594228b1a3d6f599eb3db0d06070fbc551c657b58234ba164ce3fe415fa5f3eb823c08dc29b8c341219c77b6b3d
+Y = 2baad447c8c290cfed25edd9031c41d0b76921457327f42db31122b81f337bbf0b1039ec830ce9061a3761953c75e4a8
+PeerX = dda546acfc8f903d11e2e3920669636d44b2068aeb66ff07aa266f0030e1535b0ed0203cb8a460ac990f1394faf22f1d
+PeerY = 15bbb2597913035faadf413476f4c70f7279769a40c986f470c427b4ee4962abdf8173bbad81874772925fd32f0b159f
+Z = 1220e7e6cad7b25df98e5bbdcc6c0b65ca6c2a50c5ff6c41dca71e475646fd489615979ca92fb4389aeadefde79a24f1
+
+Curve = P-384
+Private = 50ccc1f7076e92f4638e85f2db98e0b483e6e2204c92bdd440a6deea04e37a07c6e72791c190ad4e4e86e01efba84269
+X = 756c07df0ce32c839dac9fb4733c9c28b70113a676a7057c38d223f22a3a9095a8d564653af528e04c7e1824be4a6512
+Y = 17c2ce6962cbd2a2e066297b39d57dd9bb4680f0191d390f70b4e461419b2972ce68ad46127fdda6c39195774ea86df3
+PeerX = 788be2336c52f4454d63ee944b1e49bfb619a08371048e6da92e584eae70bde1f171c4df378bd1f3c0ab03048a237802
+PeerY = 4673ebd8db604eaf41711748bab2968a23ca4476ce144e728247f08af752929157b5830f1e26067466bdfa8b65145a33
+Z = 793bb9cd22a93cf468faf804a38d12b78cb12189ec679ddd2e9aa21fa9a5a0b049ab16a23574fe04c1c3c02343b91beb
+
+Curve = P-384
+Private = 06f132b71f74d87bf99857e1e4350a594e5fe35533b888552ceccbc0d8923c902e36141d7691e28631b8bc9bafe5e064
+X = 2a3cc6b8ff5cde926e7e3a189a1bd029c9b586351af8838f4f201cb8f4b70ef3b0da06d352c80fc26baf8f42b784459e
+Y = bf9985960176da6d23c7452a2954ffcbbcb24249b43019a2a023e0b3dabd461f19ad3e775c364f3f11ad49f3099400d3
+PeerX = d09bb822eb99e38060954747c82bb3278cf96bbf36fece3400f4c873838a40c135eb3babb9293bd1001bf3ecdee7bf26
+PeerY = d416db6e1b87bbb7427788a3b6c7a7ab2c165b1e366f9608df512037584f213a648d47f16ac326e19aae972f63fd76c9
+Z = 012d191cf7404a523678c6fc075de8285b243720a903047708bb33e501e0dbee5bcc40d7c3ef6c6da39ea24d830da1e8
+
+Curve = P-384
+Private = 12048ebb4331ec19a1e23f1a2c773b664ccfe90a28bfb846fc12f81dff44b7443c77647164bf1e9e67fd2c07a6766241
+X = bc18836bc7a9fdf54b5352f37d7528ab8fa8ec544a8c6180511cbfdd49cce377c39e34c031b5240dc9980503ed2f262c
+Y = 8086cbe338191080f0b7a16c7afc4c7b0326f9ac66f58552ef4bb9d24de3429ed5d3277ed58fcf48f2b5f61326bec6c6
+PeerX = 13741262ede5861dad71063dfd204b91ea1d3b7c631df68eb949969527d79a1dc59295ef7d2bca6743e8cd77b04d1b58
+PeerY = 0baaeadc7e19d74a8a04451a135f1be1b02fe299f9dc00bfdf201e83d995c6950bcc1cb89d6f7b30bf54656b9a4da586
+Z = ad0fd3ddffe8884b9263f3c15fe1f07f2a5a22ffdc7e967085eea45f0cd959f20f18f522763e28bcc925e496a52dda98
+
+Curve = P-384
+Private = 34d61a699ca576169fcdc0cc7e44e4e1221db0fe63d16850c8104029f7d48449714b9884328cae189978754ab460b486
+X = 867f81104ccd6b163a7902b670ef406042cb0cce7dcdc63d1dfc91b2c40e3cdf7595834bf9eceb79849f1636fc8462fc
+Y = 9d4bde8e875ec49697d258d1d59465f8431c6f5531e1c59e9f9ebe3cf164a8d9ce10a12f1979283a959bad244dd83863
+PeerX = 9e22cbc18657f516a864b37b783348b66f1aa9626cd631f4fa1bd32ad88cf11db52057c660860d39d11fbf024fabd444
+PeerY = 6b0d53c79681c28116df71e9cee74fd56c8b7f04b39f1198cc72284e98be9562e35926fb4f48a9fbecafe729309e8b6f
+Z = dc4ca392dc15e20185f2c6a8ea5ec31dfc96f56153a47394b3072b13d0015f5d4ae13beb3bed54d65848f9b8383e6c95
+
+Curve = P-384
+Private = dc60fa8736d702135ff16aab992bb88eac397f5972456c72ec447374d0d8ce61153831bfc86ad5a6eb5b60bfb96a862c
+X = b69beede85d0f829fec1b893ccb9c3e052ff692e13b974537bc5b0f9feaf7b22e84f03231629b24866bdb4b8cf908914
+Y = 66f85e2bfcaba2843285b0e14ebc07ef7dafff8b424416fee647b59897b619f20eed95a632e6a4206bf7da429c04c560
+PeerX = 2db5da5f940eaa884f4db5ec2139b0469f38e4e6fbbcc52df15c0f7cf7fcb1808c749764b6be85d2fdc5b16f58ad5dc0
+PeerY = 22e8b02dcf33e1b5a083849545f84ad5e43f77cb71546dbbac0d11bdb2ee202e9d3872e8d028c08990746c5e1dde9989
+Z = d765b208112d2b9ed5ad10c4046e2e3b0dbf57c469329519e239ac28b25c7d852bf757d5de0ee271cadd021d86cfd347
+
+Curve = P-384
+Private = 6fa6a1c704730987aa634b0516a826aba8c6d6411d3a4c89772d7a62610256a2e2f289f5c3440b0ec1e70fa339e251ce
+X = 53de1fc1328e8de14aecab29ad8a40d6b13768f86f7d298433d20fec791f86f8bc73f358098b256a298bb488de257bf4
+Y = ac28944fd27f17b82946c04c66c41f0053d3692f275da55cd8739a95bd8cd3af2f96e4de959ea8344d8945375905858b
+PeerX = 329647baa354224eb4414829c5368c82d7893b39804e08cbb2180f459befc4b347a389a70c91a23bd9d30c83be5295d3
+PeerY = cc8f61923fad2aa8e505d6cfa126b9fabd5af9dce290b75660ef06d1caa73681d06089c33bc4246b3aa30dbcd2435b12
+Z = d3778850aeb58804fbe9dfe6f38b9fa8e20c2ca4e0dec335aafceca0333e3f2490b53c0c1a14a831ba37c4b9d74be0f2
+
+Curve = P-384
+Private = 74ad8386c1cb2ca0fcdeb31e0869bb3f48c036afe2ef110ca302bc8b910f621c9fcc54cec32bb89ec7caa84c7b8e54a8
+X = 27a3e83cfb9d5122e73129d801615857da7cc089cccc9c54ab3032a19e0a0a9f677346e37f08a0b3ed8da6e5dd691063
+Y = 8d60e44aa5e0fd30c918456796af37f0e41957901645e5c596c6d989f5859b03a0bd7d1f4e77936fff3c74d204e5388e
+PeerX = 29d8a36d22200a75b7aea1bb47cdfcb1b7fd66de967041434728ab5d533a060df732130600fe6f75852a871fb2938e39
+PeerY = e19b53db528395de897a45108967715eb8cb55c3fcbf23379372c0873a058d57544b102ecce722b2ccabb1a603774fd5
+Z = 81e1e71575bb4505498de097350186430a6242fa6c57b85a5f984a23371123d2d1424eefbf804258392bc723e4ef1e35
+
+Curve = P-521
+Private = 017eecc07ab4b329068fba65e56a1f8890aa935e57134ae0ffcce802735151f4eac6564f6ee9974c5e6887a1fefee5743ae2241bfeb95d5ce31ddcb6f9edb4d6fc47
+X = 00602f9d0cf9e526b29e22381c203c48a886c2b0673033366314f1ffbcba240ba42f4ef38a76174635f91e6b4ed34275eb01c8467d05ca80315bf1a7bbd945f550a5
+Y = 01b7c85f26f5d4b2d7355cf6b02117659943762b6d1db5ab4f1dbc44ce7b2946eb6c7de342962893fd387d1b73d7a8672d1f236961170b7eb3579953ee5cdc88cd2d
+PeerX = 00685a48e86c79f0f0875f7bc18d25eb5fc8c0b07e5da4f4370f3a9490340854334b1e1b87fa395464c60626124a4e70d0f785601d37c09870ebf176666877a2046d
+PeerY = 01ba52c56fc8776d9e8f5db4f0cc27636d0b741bbe05400697942e80b739884a83bde99e0f6716939e632bc8986fa18dccd443a348b6c3e522497955a4f3c302f676
+Z = 005fc70477c3e63bc3954bd0df3ea0d1f41ee21746ed95fc5e1fdf90930d5e136672d72cc770742d1711c3c3a4c334a0ad9759436a4d3c5bf6e74b9578fac148c831
+
+Curve = P-521
+Private = 00816f19c1fb10ef94d4a1d81c156ec3d1de08b66761f03f06ee4bb9dcebbbfe1eaa1ed49a6a990838d8ed318c14d74cc872f95d05d07ad50f621ceb620cd905cfb8
+X = 00d45615ed5d37fde699610a62cd43ba76bedd8f85ed31005fe00d6450fbbd101291abd96d4945a8b57bc73b3fe9f4671105309ec9b6879d0551d930dac8ba45d255
+Y = 01425332844e592b440c0027972ad1526431c06732df19cd46a242172d4dd67c2c8c99dfc22e49949a56cf90c6473635ce82f25b33682fb19bc33bd910ed8ce3a7fa
+PeerX = 01df277c152108349bc34d539ee0cf06b24f5d3500677b4445453ccc21409453aafb8a72a0be9ebe54d12270aa51b3ab7f316aa5e74a951c5e53f74cd95fc29aee7a
+PeerY = 013d52f33a9f3c14384d1587fa8abe7aed74bc33749ad9c570b471776422c7d4505d9b0a96b3bfac041e4c6a6990ae7f700e5b4a6640229112deafa0cd8bb0d089b0
+Z = 000b3920ac830ade812c8f96805da2236e002acbbf13596a9ab254d44d0e91b6255ebf1229f366fb5a05c5884ef46032c26d42189273ca4efa4c3db6bd12a6853759
+
+Curve = P-521
+Private = 012f2e0c6d9e9d117ceb9723bced02eb3d4eebf5feeaf8ee0113ccd8057b13ddd416e0b74280c2d0ba8ed291c443bc1b141caf8afb3a71f97f57c225c03e1e4d42b0
+X = 00717fcb3d4a40d103871ede044dc803db508aaa4ae74b70b9fb8d8dfd84bfecfad17871879698c292d2fd5e17b4f9343636c531a4fac68a35a93665546b9a878679
+Y = 00f3d96a8637036993ab5d244500fff9d2772112826f6436603d3eb234a44d5c4e5c577234679c4f9df725ee5b9118f23d8a58d0cc01096daf70e8dfec0128bdc2e8
+PeerX = 0092db3142564d27a5f0006f819908fba1b85038a5bc2509906a497daac67fd7aee0fc2daba4e4334eeaef0e0019204b471cd88024f82115d8149cc0cf4f7ce1a4d5
+PeerY = 016bad0623f517b158d9881841d2571efbad63f85cbe2e581960c5d670601a6760272675a548996217e4ab2b8ebce31d71fca63fcc3c08e91c1d8edd91cf6fe845f8
+Z = 006b380a6e95679277cfee4e8353bf96ef2a1ebdd060749f2f046fe571053740bbcc9a0b55790bc9ab56c3208aa05ddf746a10a3ad694daae00d980d944aabc6a08f
+
+Curve = P-521
+Private = 00e548a79d8b05f923b9825d11b656f222e8cb98b0f89de1d317184dc5a698f7c71161ee7dc11cd31f4f4f8ae3a981e1a3e78bdebb97d7c204b9261b4ef92e0918e0
+X = 000ce800217ed243dd10a79ad73df578aa8a3f9194af528cd1094bbfee27a3b5481ad5862c8876c0c3f91294c0ab3aa806d9020cbaa2ed72b7fecdc5a09a6dad6f32
+Y = 01543c9ab45b12469232918e21d5a351f9a4b9cbf9efb2afcc402fa9b31650bec2d641a05c440d35331c0893d11fb13151335988b303341301a73dc5f61d574e67d9
+PeerX = 00fdd40d9e9d974027cb3bae682162eac1328ad61bc4353c45bf5afe76bf607d2894c8cce23695d920f2464fda4773d4693be4b3773584691bdb0329b7f4c86cc299
+PeerY = 0034ceac6a3fef1c3e1c494bfe8d872b183832219a7e14da414d4e3474573671ec19b033be831b915435905925b44947c592959945b4eb7c951c3b9c8cf52530ba23
+Z = 00fbbcd0b8d05331fef6086f22a6cce4d35724ab7a2f49dd8458d0bfd57a0b8b70f246c17c4468c076874b0dff7a0336823b19e98bf1cec05e4beffb0591f97713c6
+
+Curve = P-521
+Private = 01c8aae94bb10b8ca4f7be577b4fb32bb2381032c4942c24fc2d753e7cc5e47b483389d9f3b956d20ee9001b1eef9f23545f72c5602140046839e963313c3decc864
+X = 0106a14e2ee8ff970aa8ab0c79b97a33bba2958e070b75b94736b77bbe3f777324fa52872771aa88a63a9e8490c3378df4dc760cd14d62be700779dd1a4377943656
+Y = 002366ce3941e0b284b1aa81215d0d3b9778fce23c8cd1e4ed6fa0abf62156c91d4b3eb55999c3471bed275e9e60e5aa9d690d310bfb15c9c5bbd6f5e9eb39682b74
+PeerX = 0098d99dee0816550e84dbfced7e88137fddcf581a725a455021115fe49f8dc3cf233cd9ea0e6f039dc7919da973cdceaca205da39e0bd98c8062536c47f258f44b5
+PeerY = 00cd225c8797371be0c4297d2b457740100c774141d8f214c23b61aa2b6cd4806b9b70722aa4965fb622f42b7391e27e5ec21c5679c5b06b59127372997d421adc1e
+Z = 0145cfa38f25943516c96a5fd4bfebb2f645d10520117aa51971eff442808a23b4e23c187e639ff928c3725fbd1c0c2ad0d4aeb207bc1a6fb6cb6d467888dc044b3c
+
+Curve = P-521
+Private = 009b0af137c9696c75b7e6df7b73156bb2d45f482e5a4217324f478b10ceb76af09724cf86afa316e7f89918d31d54824a5c33107a483c15c15b96edc661340b1c0e
+X = 00748cdbb875d35f4bccb62abe20e82d32e4c14dc2feb5b87da2d0ccb11c9b6d4b7737b6c46f0dfb4d896e2db92fcf53cdbbae2a404c0babd564ad7adeac6273efa3
+Y = 01984acab8d8f173323de0bb60274b228871609373bb22a17287e9dec7495873abc09a8915b54c8455c8e02f654f602e23a2bbd7a9ebb74f3009bd65ecc650814cc0
+PeerX = 007ae115adaaf041691ab6b7fb8c921f99d8ed32d283d67084e80b9ad9c40c56cd98389fb0a849d9ecf7268c297b6f93406119f40e32b5773ed25a28a9a85c4a7588
+PeerY = 01a28e004e37eeaefe1f4dbb71f1878696141af3a10a9691c4ed93487214643b761fa4b0fbeeb247cf6d3fba7a60697536ad03f49b80a9d1cb079673654977c5fa94
+Z = 005c5721e96c273319fd60ecc46b5962f698e974b429f28fe6962f4ac656be2eb8674c4aafc037eab48ece612953b1e8d861016b6ad0c79805784c67f73ada96f351
+
+Curve = P-521
+Private = 01e48faacee6dec83ffcde944cf6bdf4ce4bae72747888ebafee455b1e91584971efb49127976a52f4142952f7c207ec0265f2b718cf3ead96ea4f62c752e4f7acd3
+X = 010eb1b4d9172bcc23f4f20cc9560fc54928c3f34ea61c00391dc766c76ed9fa608449377d1e4fadd1236025417330b4b91086704ace3e4e6484c606e2a943478c86
+Y = 0149413864069825ee1d0828da9f4a97713005e9bd1adbc3b38c5b946900721a960fe96ad2c1b3a44fe3de9156136d44cb17cbc2415729bb782e16bfe2deb3069e43
+PeerX = 012588115e6f7f7bdcfdf57f03b169b479758baafdaf569d04135987b2ce6164c02a57685eb5276b5dae6295d3fe90620f38b5535c6d2260c173e61eb888ca920203
+PeerY = 01542c169cf97c2596fe2ddd848a222e367c5f7e6267ebc1bcd9ab5dcf49158f1a48e4af29a897b7e6a82091c2db874d8e7abf0f58064691344154f396dbaed188b6
+Z = 01736d9717429b4f412e903febe2f9e0fffd81355d6ce2c06ff3f66a3be15ceec6e65e308347593f00d7f33591da4043c30763d72749f72cdceebe825e4b34ecd570
+
+Curve = P-521
+Private = 00c29aa223ea8d64b4a1eda27f39d3bc98ea0148dd98c1cbe595f8fd2bfbde119c9e017a50f5d1fc121c08c1cef31b758859556eb3e0e042d8dd6aaac57a05ca61e3
+X = 001511c848ef60d5419a98d10204db0fe58224124370061bcfa4e9249d50618c56bf3722471b259f38263bb7b280d23caf2a1ee8737f9371cdb2732cdc958369930c
+Y = 01d461681ae6d8c49b4c5f4d6016143fb1bd7491573e3ed0e6c48b82e821644f87f82f0e5f08fd16f1f98fa17586200ab02ed8c627b35c3f27617ec5fd92f456203f
+PeerX = 0169491d55bd09049fdf4c2a53a660480fee4c03a0538675d1cd09b5bba78dac48543ef118a1173b3fbf8b20e39ce0e6b890a163c50f9645b3d21d1cbb3b60a6fff4
+PeerY = 0083494b2eba76910fed33c761804515011fab50e3b377abd8a8a045d886d2238d2c268ac1b6ec88bd71b7ba78e2c33c152e4bf7da5d565e4acbecf5e92c7ad662bb
+Z = 018f2ae9476c771726a77780208dedfefa205488996b18fecc50bfd4c132753f5766b2cd744afa9918606de2e016effc63622e9029e76dc6e3f0c69f7aeced565c2c
+
+Curve = P-521
+Private = 0028692be2bf5c4b48939846fb3d5bce74654bb2646e15f8389e23708a1afadf561511ea0d9957d0b53453819d60fba8f65a18f7b29df021b1bb01cd163293acc3cc
+X = 01cfdc10c799f5c79cb6930a65fba351748e07567993e5e410ef4cacc4cd8a25784991eb4674e41050f930c7190ac812b9245f48a7973b658daf408822fe5b85f668
+Y = 0180d9ddfc9af77b9c4a6f02a834db15e535e0b3845b2cce30388301b51cecbe3276307ef439b5c9e6a72dc2d94d879bc395052dbb4a5787d06efb280210fb8be037
+PeerX = 008415f5bbd0eee387d6c09d0ef8acaf29c66db45d6ba101860ae45d3c60e1e0e3f7247a4626a60fdd404965c3566c79f6449e856ce0bf94619f97da8da24bd2cfb6
+PeerY = 00fdd7c59c58c361bc50a7a5d0d36f723b17c4f2ad2b03c24d42dc50f74a8c465a0afc4683f10fab84652dfe9e928c2626b5456453e1573ff60be1507467d431fbb2
+Z = 0105a346988b92ed8c7a25ce4d79d21bc86cfcc7f99c6cd19dbb4a39f48ab943b79e4f0647348da0b80bd864b85c6b8d92536d6aa544dc7537a00c858f8b66319e25
+
+Curve = P-521
+Private = 01194d1ee613f5366cbc44b504d21a0cf6715e209cd358f2dd5f3e71cc0d67d0e964168c42a084ebda746f9863a86bacffc819f1edf1b8c727ccfb3047240a57c435
+X = 016bd15c8a58d366f7f2b2f298cc87b7485e9ee70d11d12448b8377c0a82c7626f67aff7f97be7a3546bf417eeeddf75a93c130191c84108042ea2fca17fd3f80d14
+Y = 01560502d04b74fce1743aab477a9d1eac93e5226981fdb97a7478ce4ce566ff7243931284fad850b0c2bcae0ddd2d97790160c1a2e77c3ed6c95ecc44b89e2637fc
+PeerX = 01c721eea805a5cba29f34ba5758775be0cf6160e6c08723f5ab17bf96a1ff2bd9427961a4f34b07fc0b14ca4b2bf6845debd5a869f124ebfa7aa72fe565050b7f18
+PeerY = 00b6e89eb0e1dcf181236f7c548fd1a8c16b258b52c1a9bfd3fe8f22841b26763265f074c4ccf2d634ae97b701956f67a11006c52d97197d92f585f5748bc2672eeb
+Z = 004531b3d2c6cd12f21604c8610e6723dbf4daf80b5a459d6ba5814397d1c1f7a21d7c114be964e27376aaebe3a7bc3d6af7a7f8c7befb611afe487ff032921f750f
+
+Curve = P-521
+Private = 01fd90e3e416e98aa3f2b6afa7f3bf368e451ad9ca5bd54b5b14aee2ed6723dde5181f5085b68169b09fbec721372ccf6b284713f9a6356b8d560a8ff78ca3737c88
+X = 01ebea1b10d3e3b971b7efb69fc878de11c7f472e4e4d384c31b8d6288d8071517acade9b39796c7af5163bcf71aeda777533f382c6cf0a4d9bbb938c85f44b78037
+Y = 016b0e3e19c2996b2cbd1ff64730e7ca90edca1984f9b2951333535e5748baa34a99f61ff4d5f812079e0f01e87789f34efdad8098015ee74a4f846dd190d16dc6e1
+PeerX = 01c35823e440a9363ab98d9fc7a7bc0c0532dc7977a79165599bf1a9cc64c00fb387b42cca365286e8430360bfad3643bc31354eda50dc936c329ecdb60905c40fcb
+PeerY = 00d9e7f433531e44df4f6d514201cbaabb06badd6783e01111726d815531d233c5cdb722893ffbb2027259d594de77438809738120c6f783934f926c3fb69b40c409
+Z = 0100c8935969077bae0ba89ef0df8161d975ec5870ac811ae7e65ca5394efba4f0633d41bf79ea5e5b9496bbd7aae000b0594baa82ef8f244e6984ae87ae1ed124b7
+
+Curve = P-521
+Private = 009012ecfdadc85ced630afea534cdc8e9d1ab8be5f3753dcf5f2b09b40eda66fc6858549bc36e6f8df55998cfa9a0703aecf6c42799c245011064f530c09db98369
+X = 00234e32be0a907131d2d128a6477e0caceb86f02479745e0fe245cb332de631c078871160482eeef584e274df7fa412cea3e1e91f71ecba8781d9205d48386341ad
+Y = 01cf86455b09b1c005cffba8d76289a3759628c874beea462f51f30bd581e3803134307dedbb771b3334ee15be2e242cd79c3407d2f58935456c6941dd9b6d155a46
+PeerX = 00093057fb862f2ad2e82e581baeb3324e7b32946f2ba845a9beeed87d6995f54918ec6619b9931955d5a89d4d74adf1046bb362192f2ef6bd3e3d2d04dd1f87054a
+PeerY = 00aa3fb2448335f694e3cda4ae0cc71b1b2f2a206fa802d7262f19983c44674fe15327acaac1fa40424c395a6556cb8167312527fae5865ecffc14bbdc17da78cdcf
+Z = 017f36af19303841d13a389d95ec0b801c7f9a679a823146c75c17bc44256e9ad422a4f8b31f14647b2c7d317b933f7c2946c4b8abd1d56d620fab1b5ff1a3adc71f
+
+Curve = P-521
+Private = 01b5ff847f8eff20b88cfad42c06e58c3742f2f8f1fdfd64b539ba48c25926926bd5e332b45649c0b184f77255e9d58fe8afa1a6d968e2cb1d4637777120c765c128
+X = 01de3dc9263bc8c4969dc684be0eec54befd9a9f3dba194d8658a789341bf0d78d84da6735227cafaf09351951691197573c8c360a11e5285712b8bbdf5ac91b977c
+Y = 00812de58cd095ec2e5a9b247eb3ed41d8bef6aeace194a7a05b65aa5d289fbc9b1770ec84bb6be0c2c64cc37c1d54a7f5d71377a9adbe20f26f6f2b544a821ea831
+PeerX = 0083192ed0b1cb31f75817794937f66ad91cf74552cd510cedb9fd641310422af5d09f221cad249ee814d16dd7ac84ded9eacdc28340fcfc9c0c06abe30a2fc28cd8
+PeerY = 002212ed868c9ba0fb2c91e2c39ba93996a3e4ebf45f2852d0928c48930e875cc7b428d0e7f3f4d503e5d60c68cb49b13c2480cd486bed9200caddaddfe4ff8e3562
+Z = 00062f9fc29ae1a68b2ee0dcf956cbd38c88ae5f645eaa546b00ebe87a7260bf724be20d34b9d02076655c933d056b21e304c24ddb1dedf1dd76de611fc4a2340336
+
+Curve = P-521
+Private = 011a6347d4e801c91923488354cc533e7e35fddf81ff0fb7f56bb0726e0c29ee5dcdc5f394ba54cf57269048aab6e055895c8da24b8b0639a742314390cc04190ed6
+X = 00fe30267f33ba5cdefc25cbb3c9320dad9ccb1d7d376644620ca4fadee5626a3cede25ad254624def727a7048f7145f76162aa98042f9b123b2076f8e8cf59b3fdf
+Y = 001145dc6631953b6e2945e94301d6cbb098fe4b04f7ee9b09411df104dc82d7d79ec46a01ed0f2d3e7db6eb680694bdeb107c1078aec6cabd9ebee3d342fe7e54df
+PeerX = 01a89b636a93e5d2ba6c2292bf23033a84f06a3ac1220ea71e806afbe097a804cc67e9baa514cfb6c12c9194be30212bf7aae7fdf6d376c212f0554e656463ffab7e
+PeerY = 0182efcaf70fc412d336602e014da47256a0b606f2addcce8053bf817ac8656bb4e42f14c8cbf2a68f488ab35dcdf64056271dee1f606a440ba4bd4e5a11b8b8e54f
+Z = 0128ab09bfec5406799e610f772ba17e892249fa8e0e7b18a04b9197034b250b48294f1867fb9641518f92766066a07a8b917b0e76879e1011e51ccbd9f540c54d4f
+
+Curve = P-521
+Private = 0022b6d2a22d71dfaa811d2d9f9f31fbed27f2e1f3d239538ddf3e4cc8c39a330266db25b7bc0a9704f17bde7f3592bf5f1f2d4b56013aacc3d8d1bc02f00d3146cc
+X = 00ba38cfbf9fd2518a3f61d43549e7a6a6d28b2be57ffd3e0faceb636b34ed17e044a9f249dae8fc132e937e2d9349cd2ed77bb1049ceb692a2ec5b17ad61502a64c
+Y = 001ec91d3058573fa6c0564a02a1a010160c313bc7c73510dc983e5461682b5be00dbce7e2c682ad73f29ca822cdc111f68fabe33a7b384a648342c3cdb9f050bcdb
+PeerX = 017200b3f16a68cbaed2bf78ba8cddfb6cffac262bba00fbc25f9dc72a07ce59372904899f364c44cb264c097b647d4412bee3e519892d534d9129f8a28f7500fee7
+PeerY = 00baba8d672a4f4a3b63de48b96f56e18df5d68f7d70d5109833f43770d6732e06b39ad60d93e5b43db8789f1ec0aba47286a39ea584235acea757dbf13d53b58364
+Z = 0101e462e9d9159968f6440e956f11dcf2227ae4aea81667122b6af9239a291eb5d6cf5a4087f358525fcacfa46bb2db01a75af1ba519b2d31da33eda87a9d565748
+
+Curve = P-521
+Private = 005bacfff268acf6553c3c583b464ea36a1d35e2b257a5d49eb3419d5a095087c2fb4d15cf5bf5af816d0f3ff7586490ccd3ddc1a98b39ce63749c6288ce0dbdac7d
+X = 0036e488da7581472a9d8e628c58d6ad727311b7e6a3f6ae33a8544f34b09280249020be7196916fafd90e2ec54b66b5468d2361b99b56fa00d7ac37abb8c6f16653
+Y = 011edb9fb8adb6a43f4f5f5fdc1421c9fe04fc8ba46c9b66334e3af927c8befb4307104f299acec4e30f812d9345c9720d19869dbfffd4ca3e7d2713eb5fc3f42615
+PeerX = 004efd5dbd2f979e3831ce98f82355d6ca14a5757842875882990ab85ab9b7352dd6b9b2f4ea9a1e95c3880d65d1f3602f9ca653dc346fac858658d75626f4d4fb08
+PeerY = 0061cf15dbdaa7f31589c98400373da284506d70c89f074ed262a9e28140796b7236c2eef99016085e71552ff488c72b7339fefb7915c38459cb20ab85aec4e45052
+Z = 0141d6a4b719ab67eaf04a92c0a41e2dda78f4354fb90bdc35202cc7699b9b04d49616f82255debf7bbec045ae58f982a66905fcfae69d689785e38c868eb4a27e7b
+
+Curve = P-521
+Private = 008e2c93c5423876223a637cad367c8589da69a2d0fc68612f31923ae50219df2452e7cc92615b67f17b57ffd2f52b19154bb40d7715336420fde2e89fee244f59dc
+X = 00fa3b35118d6c422570f724a26f90b2833b19239174cea081c53133f64db60d6940ea1261299c04c1f4587cdb0c4c39616479c1bb0c146799a118032dcf98f899c0
+Y = 0069f040229006151fa32b51f679c8816f7c17506b403809dc77cd58a2aec430d94d13b6c916de99f355aa45fcfbc6853d686c71be496a067d24bfaea4818fc51f75
+PeerX = 0129891de0cf3cf82e8c2cf1bf90bb296fe00ab08ca45bb7892e0e227a504fdd05d2381a4448b68adff9c4153c87eacb78330d8bd52515f9f9a0b58e85f446bb4e10
+PeerY = 009edd679696d3d1d0ef327f200383253f6413683d9e4fcc87bb35f112c2f110098d15e5701d7ceee416291ff5fed85e687f727388b9afe26a4f6feed560b218e6bb
+Z = 00345e26e0abb1aac12b75f3a9cf41efe1c336396dffa4a067a4c2cfeb878c68b2b045faa4e5b4e6fa4678f5b603c351903b14bf9a6a70c439257199a640890b61d1
+
+Curve = P-521
+Private = 0004d49d39d40d8111bf16d28c5936554326b197353eebbcf47545393bc8d3aaf98f14f5be7074bfb38e6cc97b989754074daddb3045f4e4ce745669fdb3ec0d5fa8
+X = 012ec226d050ce07c79b3df4d0f0891f9f7adf462e8c98dbc1a2a14f5e53a3f5ad894433587cc429a8be9ea1d84fa33b1803690dae04da7218d30026157fc995cf52
+Y = 004837dfbf3426f57b5c793269130abb9a38f618532211931154db4eeb9aede88e57290f842ea0f2ea9a5f74c6203a3920fe4e305f6118f676b154e1d75b9cb5eb88
+PeerX = 01a3c20240e59f5b7a3e17c275d2314ba1741210ad58b71036f8c83cc1f6b0f409dfdd9113e94b67ec39c3291426c23ffcc447054670d2908ff8fe67dc2306034c5c
+PeerY = 01d2825bfd3af8b1e13205780c137fe938f84fde40188e61ea02cead81badfdb425c29f7d7fb0324debadc10bbb93de68f62c35069268283f5265865db57a79f7bf7
+Z = 006fe9de6fb8e672e7fd150fdc5e617fabb0d43906354ccfd224757c7276f7a1010091b17ed072074f8d10a5ec971eb35a5cb7076603b7bc38d432cbc059f80f9488
+
+Curve = P-521
+Private = 011a5d1cc79cd2bf73ea106f0e60a5ace220813b53e27b739864334a07c03367efda7a4619fa6eef3a9746492283b3c445610a023a9cc49bf4591140384fca5c8bb5
+X = 00eb07c7332eedb7d3036059d35f7d2288d4377d5f42337ad3964079fb120ccd4c8bd384b585621055217023acd9a94fcb3b965bfb394675e788ade41a1de73e620c
+Y = 00491a835de2e6e7deb7e090f4a11f2c460c0b1f3d5e94ee8d751014dc720784fd3b54500c86ebaef18429f09e8e876d5d1538968a030d7715dde99f0d8f06e29d59
+PeerX = 007e2d138f2832e345ae8ff65957e40e5ec7163f016bdf6d24a2243daa631d878a4a16783990c722382130f9e51f0c1bd6ff5ac96780e48b68f5dec95f42e6144bb5
+PeerY = 00b0de5c896791f52886b0f09913e26e78dd0b69798fc4df6d95e3ca708ecbcbcce1c1895f5561bbabaae372e9e67e6e1a3be60e19b470cdf673ec1fc393d3426e20
+Z = 01e4e759ecedce1013baf73e6fcc0b92451d03bdd50489b78871c333114990c9ba6a9b2fc7b1a2d9a1794c1b60d9279af6f146f0bbfb0683140403bfa4ccdb524a29
+
+Curve = P-521
+Private = 010c908caf1be74c616b625fc8c1f514446a6aec83b5937141d6afbb0a8c7666a7746fa1f7a6664a2123e8cdf6cd8bf836c56d3c0ebdcc980e43a186f938f3a78ae7
+X = 0031890f4c7abec3f723362285d77d2636f876817db3bbc88b01e773597b969ff6f013ea470c854ab4a7739004eb8cbea69b82ddf36acadd406871798ecb2ac3aa7f
+Y = 00d8b429ae3250266b9643c0c765a60dc10155bc2531cf8627296f4978b6640a9e600e19d0037d58503fa80799546a814d7478a550aa90e5ebeb052527faaeae5d08
+PeerX = 00118c36022209b1af8ebad1a12b566fc48744576e1199fe80de1cdf851cdf03e5b9091a8f7e079e83b7f827259b691d0c22ee29d6bdf73ec7bbfd746f2cd97a357d
+PeerY = 00da5ff4904548a342e2e7ba6a1f4ee5f840411a96cf63e6fe622f22c13e614e0a847c11a1ab3f1d12cc850c32e095614ca8f7e2721477b486e9ff40372977c3f65c
+Z = 0163c9191d651039a5fe985a0eea1eba018a40ab1937fcd2b61220820ee8f2302e9799f6edfc3f5174f369d672d377ea8954a8d0c8b851e81a56fda95212a6578f0e
+
+Curve = P-521
+Private = 01b37d6b7288de671360425d3e5ac1ccb21815079d8d73431e9b74a6f0e7ae004a357575b11ad66642ce8b775593eba9d98bf25c75ef0b4d3a2098bbc641f59a2b77
+X = 00189a5ee34de7e35aefeaeef9220c18071b4c29a4c3bd9d954458bd3e82a7a34da34cff5579b8101c065b1f2f527cf4581501e28ef5671873e65267733d003520af
+Y = 01eb4bc50a7b4d4599d7e3fa773ddb9eb252c9b3422872e544bdf75c7bf60f5166ddc11eb08fa7c30822dabaee373ab468eb2d922e484e2a527fff2ebb804b7d9a37
+PeerX = 01780edff1ca1c03cfbe593edc6c049bcb2860294a92c355489d9afb2e702075ade1c953895a456230a0cde905de4a3f38573dbfcccd67ad6e7e93f0b5581e926a5d
+PeerY = 00a5481962c9162962e7f0ebdec936935d0eaa813e8226d40d7f6119bfd940602380c86721e61db1830f51e139f210000bcec0d8edd39e54d73a9a129f95cd5fa979
+Z = 015d613e267a36342e0d125cdad643d80d97ed0600afb9e6b9545c9e64a98cc6da7c5aaa3a8da0bdd9dd3b97e9788218a80abafc106ef065c8f1c4e1119ef58d298b
+
+Curve = P-521
+Private = 00f2661ac762f60c5fff23be5d969ccd4ec6f98e4e72618d12bdcdb9b4102162333788c0bae59f91cdfc172c7a1681ee44d96ab2135a6e5f3415ebbcd55165b1afb0
+X = 00a8e25a6902d687b4787cdc94c364ac7cecc5c495483ed363dc0aa95ee2bd739c4c4d46b17006c728b076350d7d7e54c6822f52f47162a25109aaaba690cab696ec
+Y = 0168d2f08fe19e4dc9ee7a195b03c9f7fe6676f9f520b6270557504e72ca4394a2c6918625e15ac0c51b8f95cd560123653fb8e8ee6db961e2c4c62cc54e92e2a2a9
+PeerX = 016dacffa183e5303083a334f765de724ec5ec9402026d4797884a9828a0d321a8cfac74ab737fe20a7d6befcfc73b6a35c1c7b01d373e31abc192d48a4241a35803
+PeerY = 011e5327cac22d305e7156e559176e19bee7e4f2f59e86f1a9d0b6603b6a7df1069bde6387feb71587b8ffce5b266e1bae86de29378a34e5c74b6724c4d40a719923
+Z = 014d6082a3b5ced1ab8ca265a8106f302146c4acb8c30bb14a4c991e3c82a9731288bdb91e0e85bda313912d06384fc44f2153fb13506fa9cf43c9aab5750988c943
+
+Curve = P-521
+Private = 00f430ca1261f09681a9282e9e970a9234227b1d5e58d558c3cc6eff44d1bdf53de16ad5ee2b18b92d62fc79586116b0efc15f79340fb7eaf5ce6c44341dcf8dde27
+X = 006c1d9b5eca87de1fb871a0a32f807c725adccde9b3967453a71347d608f0c030cd09e338cdecbf4a02015bc8a6e8d3e2595fe773ffc2fc4e4a55d0b1a2cc00323b
+Y = 01141b2109e7f4981c952aa818a2b9f6f5c41feccdb7a7a45b9b4b672937771b008cae5f934dfe3fed10d383ab1f38769c92ce88d9be5414817ecb073a31ab368ccb
+PeerX = 00a091421d3703e3b341e9f1e7d58f8cf7bdbd1798d001967b801d1cec27e605c580b2387c1cb464f55ce7ac80334102ab03cfb86d88af76c9f4129c01bedd3bbfc4
+PeerY = 008c9c577a8e6fc446815e9d40baa66025f15dae285f19eb668ee60ae9c98e7ecdbf2b2a68e22928059f67db188007161d3ecf397e0883f0c4eb7eaf7827a62205cc
+Z = 0020c00747cb8d492fd497e0fec54644bf027d418ab686381f109712a99cabe328b9743d2225836f9ad66e5d7fed1de247e0da92f60d5b31f9e47672e57f710598f4
+
+Curve = P-521
+Private = 005dc33aeda03c2eb233014ee468dff753b72f73b00991043ea353828ae69d4cd0fadeda7bb278b535d7c57406ff2e6e473a5a4ff98e90f90d6dadd25100e8d85666
+X = 00c825ba307373cec8dd2498eef82e21fd9862168dbfeb83593980ca9f82875333899fe94f137daf1c4189eb502937c3a367ea7951ed8b0f3377fcdf2922021d46a5
+Y = 016b8a2540d5e65493888bc337249e67c0a68774f3e8d81e3b4574a0125165f0bd58b8af9de74b35832539f95c3cd9f1b759408560aa6851ae3ac7555347b0d3b13b
+PeerX = 004f38816681771289ce0cb83a5e29a1ab06fc91f786994b23708ff08a08a0f675b809ae99e9f9967eb1a49f196057d69e50d6dedb4dd2d9a81c02bdcc8f7f518460
+PeerY = 009efb244c8b91087de1eed766500f0e81530752d469256ef79f6b965d8a2232a0c2dbc4e8e1d09214bab38485be6e357c4200d073b52f04e4a16fc6f5247187aecb
+Z = 00c2bfafcd7fbd3e2fd1c750fdea61e70bd4787a7e68468c574ee99ebc47eedef064e8944a73bcb7913dbab5d93dca660d216c553622362794f7a2acc71022bdb16f
+
+Curve = P-521
+Private = 00df14b1f1432a7b0fb053965fd8643afee26b2451ecb6a8a53a655d5fbe16e4c64ce8647225eb11e7fdcb23627471dffc5c2523bd2ae89957cba3a57a23933e5a78
+X = 004e8583bbbb2ecd93f0714c332dff5ab3bc6396e62f3c560229664329baa5138c3bb1c36428abd4e23d17fcb7a2cfcc224b2e734c8941f6f121722d7b6b94154576
+Y = 01cf0874f204b0363f020864672fadbf87c8811eb147758b254b74b14fae742159f0f671a018212bbf25b8519e126d4cad778cfff50d288fd39ceb0cac635b175ec0
+PeerX = 01a32099b02c0bd85371f60b0dd20890e6c7af048c8179890fda308b359dbbc2b7a832bb8c6526c4af99a7ea3f0b3cb96ae1eb7684132795c478ad6f962e4a6f446d
+PeerY = 017627357b39e9d7632a1370b3e93c1afb5c851b910eb4ead0c9d387df67cde85003e0e427552f1cd09059aad0262e235cce5fba8cedc4fdc1463da76dcd4b6d1a46
+Z = 01aaf24e5d47e4080c18c55ea35581cd8da30f1a079565045d2008d51b12d0abb4411cda7a0785b15d149ed301a3697062f42da237aa7f07e0af3fd00eb1800d9c41
diff --git a/src/crypto/ecdsa/CMakeLists.txt b/src/crypto/ecdsa/CMakeLists.txt
index 0cc672e..c0ab6d6 100644
--- a/src/crypto/ecdsa/CMakeLists.txt
+++ b/src/crypto/ecdsa/CMakeLists.txt
@@ -18,5 +18,23 @@
   $<TARGET_OBJECTS:test_support>
 )
 
+add_executable(
+  ecdsa_sign_test
+
+  ecdsa_sign_test.cc
+
+  $<TARGET_OBJECTS:test_support>
+)
+
+add_executable(
+  ecdsa_verify_test
+
+  ecdsa_verify_test.cc
+
+  $<TARGET_OBJECTS:test_support>
+)
+
 target_link_libraries(ecdsa_test crypto)
-add_dependencies(all_tests ecdsa_test)
+target_link_libraries(ecdsa_sign_test crypto)
+target_link_libraries(ecdsa_verify_test crypto)
+add_dependencies(all_tests ecdsa_test ecdsa_sign_test ecdsa_verify_test)
diff --git a/src/crypto/ecdsa/ecdsa.c b/src/crypto/ecdsa/ecdsa.c
index 2a655b6..e1a0525 100644
--- a/src/crypto/ecdsa/ecdsa.c
+++ b/src/crypto/ecdsa/ecdsa.c
@@ -60,13 +60,16 @@
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
+#include "../bn/internal.h"
 #include "../ec/internal.h"
+#include "../internal.h"
 
 
 int ECDSA_sign(int type, const uint8_t *digest, size_t digest_len, uint8_t *sig,
-               unsigned int *sig_len, EC_KEY *eckey) {
+               unsigned int *sig_len, const EC_KEY *eckey) {
   if (eckey->ecdsa_meth && eckey->ecdsa_meth->sign) {
-    return eckey->ecdsa_meth->sign(digest, digest_len, sig, sig_len, eckey);
+    return eckey->ecdsa_meth->sign(digest, digest_len, sig, sig_len,
+                                   (EC_KEY*) eckey /* cast away const */);
   }
 
   return ECDSA_sign_ex(type, digest, digest_len, sig, sig_len, NULL, NULL,
@@ -74,15 +77,11 @@
 }
 
 int ECDSA_verify(int type, const uint8_t *digest, size_t digest_len,
-                 const uint8_t *sig, size_t sig_len, EC_KEY *eckey) {
+                 const uint8_t *sig, size_t sig_len, const EC_KEY *eckey) {
   ECDSA_SIG *s;
   int ret = 0;
   uint8_t *der = NULL;
 
-  if (eckey->ecdsa_meth && eckey->ecdsa_meth->verify) {
-    return eckey->ecdsa_meth->verify(digest, digest_len, sig, sig_len, eckey);
-  }
-
   /* Decode the ECDSA signature. */
   s = ECDSA_SIG_from_bytes(sig, sig_len);
   if (s == NULL) {
@@ -92,7 +91,7 @@
   /* Defend against potential laxness in the DER parser. */
   size_t der_len;
   if (!ECDSA_SIG_to_bytes(&der, &der_len, s) ||
-      der_len != sig_len || memcmp(sig, der, sig_len) != 0) {
+      der_len != sig_len || OPENSSL_memcmp(sig, der, sig_len) != 0) {
     /* This should never happen. crypto/bytestring is strictly DER. */
     OPENSSL_PUT_ERROR(ECDSA, ERR_R_INTERNAL_ERROR);
     goto err;
@@ -135,12 +134,12 @@
 }
 
 ECDSA_SIG *ECDSA_do_sign(const uint8_t *digest, size_t digest_len,
-                         EC_KEY *key) {
+                         const EC_KEY *key) {
   return ECDSA_do_sign_ex(digest, digest_len, NULL, NULL, key);
 }
 
 int ECDSA_do_verify(const uint8_t *digest, size_t digest_len,
-                    const ECDSA_SIG *sig, EC_KEY *eckey) {
+                    const ECDSA_SIG *sig, const EC_KEY *eckey) {
   int ret = 0;
   BN_CTX *ctx;
   BIGNUM *u1, *u2, *m, *X;
@@ -148,11 +147,6 @@
   const EC_GROUP *group;
   const EC_POINT *pub_key;
 
-  if (eckey->ecdsa_meth && eckey->ecdsa_meth->verify) {
-    OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_NOT_IMPLEMENTED);
-    return 0;
-  }
-
   /* check input values */
   if ((group = EC_KEY_get0_group(eckey)) == NULL ||
       (pub_key = EC_KEY_get0_public_key(eckey)) == NULL ||
@@ -185,7 +179,8 @@
     goto err;
   }
   /* calculate tmp1 = inv(S) mod order */
-  if (!BN_mod_inverse(u2, sig->s, order, ctx)) {
+  int no_inverse;
+  if (!BN_mod_inverse_odd(u2, &no_inverse, sig->s, order, ctx)) {
     OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
     goto err;
   }
@@ -224,13 +219,13 @@
   ret = (BN_ucmp(u1, sig->r) == 0);
 
 err:
-  BN_CTX_end(ctx);

+  BN_CTX_end(ctx);
   BN_CTX_free(ctx);
   EC_POINT_free(point);
   return ret;
 }
 
-static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
+static int ecdsa_sign_setup(const EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
                             BIGNUM **rp, const uint8_t *digest,
                             size_t digest_len) {
   BN_CTX *ctx = NULL;
@@ -272,20 +267,18 @@
     /* If possible, we'll include the private key and message digest in the k
      * generation. The |digest| argument is only empty if |ECDSA_sign_setup| is
      * being used. */
-    do {
-      int ok;
-
-      if (digest_len > 0) {
-        ok = BN_generate_dsa_nonce(k, order, EC_KEY_get0_private_key(eckey),
-                                   digest, digest_len, ctx);
-      } else {
-        ok = BN_rand_range(k, order);
-      }
-      if (!ok) {
-        OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED);
-        goto err;
-      }
-    } while (BN_is_zero(k));
+    if (digest_len > 0) {
+      do {
+        if (!BN_generate_dsa_nonce(k, order, EC_KEY_get0_private_key(eckey),
+                                   digest, digest_len, ctx)) {
+          OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED);
+          goto err;
+        }
+      } while (BN_is_zero(k));
+    } else if (!BN_rand_range_ex(k, 1, order)) {
+      OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED);
+      goto err;
+    }
 
     /* We do not want timing information to leak the length of k,
      * so we compute G*k using an equivalent scalar of fixed
@@ -318,12 +311,9 @@
   } while (BN_is_zero(r));
 
   /* Compute the inverse of k. The order is a prime, so use Fermat's Little
-   * Theorem. */
-  if (!BN_set_word(tmp, 2) ||
-      !BN_sub(tmp, order, tmp) ||
-      /* Note |ec_group_get_mont_data| may return NULL but |BN_mod_exp_mont|
-       * allows it to be. */
-      !BN_mod_exp_mont(k, k, tmp, order, ctx, ec_group_get_mont_data(group))) {
+   * Theorem. Note |ec_group_get_mont_data| may return NULL but
+   * |bn_mod_inverse_prime| allows this. */
+  if (!bn_mod_inverse_prime(k, k, order, ctx, ec_group_get_mont_data(group))) {
     OPENSSL_PUT_ERROR(ECDSA, ERR_R_BN_LIB);
     goto err;
   }
@@ -349,13 +339,14 @@
   return ret;
 }
 
-int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, BIGNUM **rp) {
+int ECDSA_sign_setup(const EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv,
+                     BIGNUM **rp) {
   return ecdsa_sign_setup(eckey, ctx, kinv, rp, NULL, 0);
 }
 
 ECDSA_SIG *ECDSA_do_sign_ex(const uint8_t *digest, size_t digest_len,
                             const BIGNUM *in_kinv, const BIGNUM *in_r,
-                            EC_KEY *eckey) {
+                            const EC_KEY *eckey) {
   int ok = 0;
   BIGNUM *kinv = NULL, *s, *m = NULL, *tmp = NULL;
   const BIGNUM *ckinv;
@@ -452,7 +443,7 @@
 
 int ECDSA_sign_ex(int type, const uint8_t *digest, size_t digest_len,
                   uint8_t *sig, unsigned int *sig_len, const BIGNUM *kinv,
-                  const BIGNUM *r, EC_KEY *eckey) {
+                  const BIGNUM *r, const EC_KEY *eckey) {
   int ret = 0;
   ECDSA_SIG *s = NULL;
 
diff --git a/src/crypto/ecdsa/ecdsa_asn1.c b/src/crypto/ecdsa/ecdsa_asn1.c
index 3fee191..d41a536 100644
--- a/src/crypto/ecdsa/ecdsa_asn1.c
+++ b/src/crypto/ecdsa/ecdsa_asn1.c
@@ -61,6 +61,7 @@
 #include <openssl/ec_key.h>
 #include <openssl/mem.h>
 
+#include "../bytestring/internal.h"
 #include "../ec/internal.h"
 
 
@@ -115,8 +116,8 @@
   }
   CBS child;
   if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
-      !BN_cbs2unsigned(&child, ret->r) ||
-      !BN_cbs2unsigned(&child, ret->s) ||
+      !BN_parse_asn1_unsigned(&child, ret->r) ||
+      !BN_parse_asn1_unsigned(&child, ret->s) ||
       CBS_len(&child) != 0) {
     OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_BAD_SIGNATURE);
     ECDSA_SIG_free(ret);
@@ -140,8 +141,8 @@
 int ECDSA_SIG_marshal(CBB *cbb, const ECDSA_SIG *sig) {
   CBB child;
   if (!CBB_add_asn1(cbb, &child, CBS_ASN1_SEQUENCE) ||
-      !BN_bn2cbb(&child, sig->r) ||
-      !BN_bn2cbb(&child, sig->s) ||
+      !BN_marshal_asn1(&child, sig->r) ||
+      !BN_marshal_asn1(&child, sig->s) ||
       !CBB_flush(cbb)) {
     OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_ENCODE_ERROR);
     return 0;
@@ -211,30 +212,16 @@
     ECDSA_SIG_free(*out);
     *out = ret;
   }
-  *inp += (size_t)len - CBS_len(&cbs);
+  *inp = CBS_data(&cbs);
   return ret;
 }
 
 int i2d_ECDSA_SIG(const ECDSA_SIG *sig, uint8_t **outp) {
-  uint8_t *der;
-  size_t der_len;
-  if (!ECDSA_SIG_to_bytes(&der, &der_len, sig)) {
+  CBB cbb;
+  if (!CBB_init(&cbb, 0) ||
+      !ECDSA_SIG_marshal(&cbb, sig)) {
+    CBB_cleanup(&cbb);
     return -1;
   }
-  if (der_len > INT_MAX) {
-    OPENSSL_PUT_ERROR(ECDSA, ERR_R_OVERFLOW);
-    OPENSSL_free(der);
-    return -1;
-  }
-  if (outp != NULL) {
-    if (*outp == NULL) {
-      *outp = der;
-      der = NULL;
-    } else {
-      memcpy(*outp, der, der_len);
-      *outp += der_len;
-    }
-  }
-  OPENSSL_free(der);
-  return (int)der_len;
+  return CBB_finish_i2d(&cbb, outp);
 }
diff --git a/src/crypto/ecdsa/ecdsa_sign_test.cc b/src/crypto/ecdsa/ecdsa_sign_test.cc
new file mode 100644
index 0000000..ee95773
--- /dev/null
+++ b/src/crypto/ecdsa/ecdsa_sign_test.cc
@@ -0,0 +1,120 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <stdio.h>
+
+#include <vector>
+
+#include <openssl/bn.h>
+#include <openssl/crypto.h>
+#include <openssl/ec.h>
+#include <openssl/ec_key.h>
+#include <openssl/ecdsa.h>
+#include <openssl/nid.h>
+
+#include "../test/file_test.h"
+
+
+static bssl::UniquePtr<EC_GROUP> GetCurve(FileTest *t, const char *key) {
+  std::string curve_name;
+  if (!t->GetAttribute(&curve_name, key)) {
+    return nullptr;
+  }
+
+  if (curve_name == "P-224") {
+    return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(NID_secp224r1));
+  }
+  if (curve_name == "P-256") {
+    return bssl::UniquePtr<EC_GROUP>(
+        EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+  }
+  if (curve_name == "P-384") {
+    return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(NID_secp384r1));
+  }
+  if (curve_name == "P-521") {
+    return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(NID_secp521r1));
+  }
+
+  t->PrintLine("Unknown curve '%s'", curve_name.c_str());
+  return nullptr;
+}
+
+static bssl::UniquePtr<BIGNUM> GetBIGNUM(FileTest *t, const char *key) {
+  std::vector<uint8_t> bytes;
+  if (!t->GetBytes(&bytes, key)) {
+    return nullptr;
+  }
+
+  return bssl::UniquePtr<BIGNUM>(BN_bin2bn(bytes.data(), bytes.size(), nullptr));
+}
+
+static bool TestECDSASign(FileTest *t, void *arg) {
+  bssl::UniquePtr<EC_GROUP> group = GetCurve(t, "Curve");
+  bssl::UniquePtr<BIGNUM> priv_key = GetBIGNUM(t, "Private");
+  bssl::UniquePtr<BIGNUM> x = GetBIGNUM(t, "X");
+  bssl::UniquePtr<BIGNUM> y = GetBIGNUM(t, "Y");
+  bssl::UniquePtr<BIGNUM> k = GetBIGNUM(t, "K");
+  bssl::UniquePtr<BIGNUM> r = GetBIGNUM(t, "R");
+  bssl::UniquePtr<BIGNUM> s = GetBIGNUM(t, "S");
+  std::vector<uint8_t> digest;
+  if (!group || !priv_key || !x || !y || !k || !r || !s ||
+      !t->GetBytes(&digest, "Digest")) {
+    return false;
+  }
+
+  bssl::UniquePtr<EC_KEY> key(EC_KEY_new());
+  bssl::UniquePtr<EC_POINT> pub_key(EC_POINT_new(group.get()));
+  if (!key || !pub_key ||
+      !EC_KEY_set_group(key.get(), group.get()) ||
+      !EC_KEY_set_private_key(key.get(), priv_key.get()) ||
+      !EC_POINT_set_affine_coordinates_GFp(group.get(), pub_key.get(), x.get(),
+                                           y.get(), nullptr) ||
+      !EC_KEY_set_public_key(key.get(), pub_key.get()) ||
+      !EC_KEY_check_key(key.get())) {
+    return false;
+  }
+
+  // |ECDSA_do_sign_ex| expects |k| to already be inverted.
+  bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
+  if (!ctx ||
+      !BN_mod_inverse(k.get(), k.get(), EC_GROUP_get0_order(group.get()),
+                      ctx.get())) {
+    return false;
+  }
+
+  bssl::UniquePtr<ECDSA_SIG> sig(ECDSA_do_sign_ex(digest.data(), digest.size(), k.get(),
+                                 r.get(), key.get()));
+  if (!sig) {
+    return false;
+  }
+
+  if (BN_cmp(r.get(), sig->r) != 0 ||
+      BN_cmp(s.get(), sig->s) != 0) {
+    t->PrintLine("Signature mismatch.");
+    return false;
+  }
+
+  return true;
+}
+
+int main(int argc, char *argv[]) {
+  CRYPTO_library_init();
+
+  if (argc != 2) {
+    fprintf(stderr, "%s <test file.txt>\n", argv[0]);
+    return 1;
+  }
+
+  return FileTestMain(TestECDSASign, nullptr, argv[1]);
+}
diff --git a/src/crypto/ecdsa/ecdsa_sign_tests.txt b/src/crypto/ecdsa/ecdsa_sign_tests.txt
new file mode 100644
index 0000000..513c582
--- /dev/null
+++ b/src/crypto/ecdsa/ecdsa_sign_tests.txt
@@ -0,0 +1,2166 @@
+# Tests from NIST CAVP 186-4 ECDSA2VS Test Vectors, Signature Generation Test
+# http://csrc.nist.gov/groups/STM/cavp/documents/dss/186-3ecdsatestvectors.zip
+#
+# NIST's files provide message and digest pairs. Since this is a low-level test,
+# the digests have been extracted. P-521 test vectors were fixed to have the
+# right number of leading zeros.
+
+Curve = P-224
+Private = 16797b5c0c7ed5461e2ff1b88e6eafa03c0f46bf072000dfc830d615
+X = 605495756e6e88f1d07ae5f98787af9b4da8a641d1a9492a12174eab
+Y = f5cc733b17decc806ef1df861a42505d0af9ef7c3df3959b8dfc6669
+Digest = 07eb2a50bf70eee87467600614a490e7600437d077ec651a27e65e67
+K = d9a5a7328117f48b4b8dd8c17dae722e756b3ff64bd29a527137eec0
+R = 2fc2cff8cdd4866b1d74e45b07d333af46b7af0888049d0fdbc7b0d6
+S = 8d9cc4c8ea93e0fd9d6431b9a1fd99b88f281793396321b11dac41eb
+
+Curve = P-224
+Private = cf020a1ff36c28511191482ed1e5259c60d383606c581948c3fbe2c5
+X = fa21f85b99d3dc18c6d53351fbcb1e2d029c00fa7d1663a3dd94695e
+Y = e9e79578f8988b168edff1a8b34a5ed9598cc20acd1f0aed36715d88
+Digest = bde0fbb390fb05d0b75df5bd0d0a4ea29516125f19830e3b0c93b641
+K = c780d047454824af98677cf310117e5f9e99627d02414f136aed8e83
+R = 45145f06b566ec9fd0fee1b6c6551a4535c7a3bbfc0fede45f4f5038
+S = 7302dff12545b069cf27df49b26e4781270585463656f2834917c3ca
+
+Curve = P-224
+Private = dde6f173fa9f307d206ce46b4f02851ebce9638a989330249fd30b73
+X = fc21a99b060afb0d9dbf3250ea3c4da10be94ce627a65874d8e4a630
+Y = e8373ab7190890326aac4aacca3eba89e15d1086a05434dd033fd3f3
+Digest = c2c03fe07e10538f6a38d5831b5dda9ce7478b3ed31323d60617dc95
+K = 6629366a156840477df4875cfba4f8faa809e394893e1f5525326d07
+R = 41f8e2b1ae5add7c24da8725a067585a3ad6d5a9ed9580beb226f23a
+S = a5d71bff02dce997305dd337128046f36714398f4ef6647599712fae
+
+Curve = P-224
+Private = aeee9071248f077590ac647794b678ad371f8e0f1e14e9fbff49671e
+X = fad0a34991bbf89982ad9cf89337b4bd2565f84d5bdd004289fc1cc3
+Y = 5d8b6764f28c8163a12855a5c266efeb9388df4994b85a8b4f1bd3bc
+Digest = 5d52747226f37a5afcd94d1b95867c0111bcb34402dad12bee76c1b7
+K = 1d35d027cd5a569e25c5768c48ed0c2b127c0f99cb4e52ea094fe689
+R = 2258184ef9f0fa698735379972ce9adf034af76017668bfcdab978de
+S = 866fb8e505dea6c909c2c9143ec869d1bac2282cf12366130ff2146c
+
+Curve = P-224
+Private = 29c204b2954e1406a015020f9d6b3d7c00658298feb2d17440b2c1a4
+X = 0e0fc15e775a75d45f872e5021b554cc0579da19125e1a49299c7630
+Y = cb64fe462d025ae2a1394746bdbf8251f7ca5a1d6bb13e0edf6b7b09
+Digest = a1ab56bd011b7e6c7e066f25333d08cf81ac0d9c1abfa09f004ab52f
+K = 39547c10bb947d69f6c3af701f2528e011a1e80a6d04cc5a37466c02
+R = 86622c376d326cdf679bcabf8eb034bf49f0c188f3fc3afd0006325d
+S = 26613d3b33c70e635d7a998f254a5b15d2a3642bf321e8cff08f1e84
+
+Curve = P-224
+Private = 8986a97b24be042a1547642f19678de4e281a68f1e794e343dabb131
+X = 2c070e68e8478341938f3d5026a1fe01e778cdffbebbdd7a4cd29209
+Y = cde21c9c7c6590ba300715a7adac278385a5175b6b4ea749c4b6a681
+Digest = 8ef4d8a368fad480bac518d625e97206adcafa87c52aef3d179cbfa9
+K = 509712f9c0f3370f6a09154159975945f0107dd1cee7327c68eaa90b
+R = 57afda5139b180de96373c3d649700682e37efd56ae182335f081013
+S = eb6cd58650cfb26dfdf21de32fa17464a6efc46830eedc16977342e6
+
+Curve = P-224
+Private = d9aa95e14cb34980cfddadddfa92bde1310acaff249f73ff5b09a974
+X = 3a0d4b8e5fad1ea1abb8d3fb742cd45cd0b76d136e5bbb33206ad120
+Y = c90ac83276b2fa3757b0f226cd7360a313bc96fd8329c76a7306cc7d
+Digest = 28fabbac167f3d6a20c2f5a4bcee527c96be04bdd2c596f09d8fbab7
+K = 1f1739af68a3cee7c5f09e9e09d6485d9cd64cc4085bc2bc89795aaf
+R = 09bbdd003532d025d7c3204c00747cd52ecdfbc7ce3dde8ffbea23e1
+S = 1e745e80948779a5cc8dc5cb193beebb550ec9c2647f4948bf58ba7d
+
+Curve = P-224
+Private = 380fb6154ad3d2e755a17df1f047f84712d4ec9e47d34d4054ea29a8
+X = 4772c27cca3348b1801ae87b01cb564c8cf9b81c23cc74468a907927
+Y = de9d253935b09617a1655c42d385bf48504e06fa386f5fa533a21dcb
+Digest = 50dd74b5af40978e809cee3eb41195402ebb5056e4437f753f9a9d0d
+K = 14dbdffa326ba2f3d64f79ff966d9ee6c1aba0d51e9a8e59f5686dc1
+R = ff6d52a09ca4c3b82da0440864d6717e1be0b50b6dcf5e1d74c0ff56
+S = 09490be77bc834c1efaa23410dcbf800e6fae40d62a737214c5a4418
+
+Curve = P-224
+Private = 6b98ec50d6b7f7ebc3a2183ff9388f75e924243827ddded8721186e2
+X = 1f249911b125348e6e0a473479105cc4b8cfb4fa32d897810fc69ffe
+Y = a17db03b9877d1b6328329061ea67aec5a38a884362e9e5b7d7642dc
+Digest = 9fee01807ab6c43a794abf6dcd6118915252ca7d3a31a1ff96b88a8d
+K = ab3a41fedc77d1f96f3103cc7dce215bf45054a755cf101735fef503
+R = 70ccc0824542e296d17a79320d422f1edcf9253840dafe4427033f40
+S = e3823699c355b61ab1894be3371765fae2b720405a7ce5e790ca8c00
+
+Curve = P-224
+Private = 8dda0ef4170bf73077d685e7709f6f747ced08eb4cde98ef06ab7bd7
+X = 7df67b960ee7a2cb62b22932457360ab1e046c1ec84b91ae65642003
+Y = c764ca9fc1b0cc2233fa57bdcfedaab0131fb7b5f557d6ca57f4afe0
+Digest = c349032f84384b913bd5d19b9211ddce221d66a45e8a051878254117
+K = 9ef6ebd178a76402968bc8ec8b257174a04fb5e2d65c1ab34ab039b9
+R = eef9e8428105704133e0f19636c89e570485e577786df2b09f99602a
+S = 8c01f0162891e4b9536243cb86a6e5c177323cca09777366caf2693c
+
+Curve = P-224
+Private = 3dbe18cd88fa49febfcb60f0369a67b2379a466d906ac46a8b8d522b
+X = b10150fd797eb870d377f1dbfa197f7d0f0ad29965af573ec13cc42a
+Y = 17b63ccefbe27fb2a1139e5757b1082aeaa564f478c23a8f631eed5c
+Digest = 63fe0d82cf5edf972e97316666a0914432e420f80b4f78ceb92afd1d
+K = 385803b262ee2ee875838b3a645a745d2e199ae112ef73a25d68d15f
+R = 1d293b697f297af77872582eb7f543dc250ec79ad453300d264a3b70
+S = 517a91b89c4859fcc10834242e710c5f0fed90ac938aa5ccdb7c66de
+
+Curve = P-224
+Private = c906b667f38c5135ea96c95722c713dbd125d61156a546f49ddaadc6
+X = 3c9b4ef1748a1925578658d3af51995b989ad760790157b25fe09826
+Y = 55648f4ff4edfb899e9a13bd8d20f5c24b35dc6a6a4e42ed5983b4a0
+Digest = 9b44ee16e576c50c0b6b37ac1437bf8f013a745615012451e54a12f2
+K = b04d78d8ac40fefadb99f389a06d93f6b5b72198c1be02dbff6195f0
+R = 4bdd3c84647bad93dcaffd1b54eb87fc61a5704b19d7e6d756d11ad0
+S = fdd81e5dca54158514f44ba2330271eff4c618330328451e2d93b9fb
+
+Curve = P-224
+Private = 3456745fbd51eac9b8095cd687b112f93d1b58352dbe02c66bb9b0cc
+X = f0acdfbc75a748a4a0ac55281754b5c4a364b7d61c5390b334daae10
+Y = 86587a6768f235bf523fbfc6e062c7401ac2b0242cfe4e5fb34f4057
+Digest = 3c89c15dee194b3223e7b53a8a5845d4873a12a2f1581d5413359828
+K = 854b20c61bcdf7a89959dbf0985880bb14b628f01c65ef4f6446f1c1
+R = a2601fbb9fe89f39814735febb349143baa934170ffb91c6448a7823
+S = bf90f9305616020a0e34ef30803fc15fa97dffc0948452bbf6cb5f66
+
+Curve = P-224
+Private = 2c522af64baaca7b7a08044312f5e265ec6e09b2272f462cc705e4c3
+X = 5fad3c047074b5de1960247d0cc216b4e3fb7f3b9cd960575c8479fc
+Y = e4fc9c7f05ff0b040eb171fdd2a1dfe2572c564c2003a08c3179a422
+Digest = 2b7faf36fdf0e393ddeb9fc875dd99f670e3d538fd0462395ea06c8f
+K = 9267763383f8db55eed5b1ca8f4937dc2e0ca6175066dc3d4a4586af
+R = 422e2e9fe535eb62f11f5f8ce87cf2e9ec65e61c06737cf6a0019ae6
+S = 116cfcf0965b7bc63aecade71d189d7e98a0434b124f2afbe3ccf0a9
+
+Curve = P-224
+Private = 3eff7d07edda14e8beba397accfee060dbe2a41587a703bbe0a0b912
+X = 6dd84f4d66f362844e41a7913c40b4aad5fa9ba56bb44c2d2ed9efac
+Y = 15f65ebcdf2fd9f8035385a330bdabec0f1cd9cc7bc31d2fadbe7cda
+Digest = 5b24b6157c0d1edf3a40c22a0745d23bdb59379e5e5e776ed040288d
+K = 7bb48839d7717bab1fdde89bf4f7b4509d1c2c12510925e13655dead
+R = 127051d85326049115f307af2bc426f6c2d08f4774a0b496fb6982b1
+S = 6857e84418c1d1179333b4e5307e92abade0b74f7521ad78044bf597
+
+Curve = P-224
+Private = 888fc992893bdd8aa02c80768832605d020b81ae0b25474154ec89aa
+X = 4c741e4d20103670b7161ae72271082155838418084335338ac38fa4
+Y = db7919151ac28587b72bad7ab180ec8e95ab9e2c8d81d9b9d7e2e383
+Digest = 00c6fc53c1986d19a8a8b580ee553dc1240745d760647d1c0adf442c133c7f56
+K = 06f7a56007825433c4c61153df1a135eee2f38ec687b492ed40d9c90
+R = 0909c9b9cae8d2790e29db6afdb45c04f5b072c4c20410c7dc9b6772
+S = 298f4fcae1fe271da1e0345d11d07a1fca43f58af4c113b909eedea0
+
+Curve = P-224
+Private = 5b5a3e186e7d5b9b0fbdfc74a05e0a3d85dc4be4c87269190c839972
+X = 897089f4ef05b943eeac06589f0e09ccc571a6add3eb1610a2fc830f
+Y = 62ba3f6b3e6f0f062058b93e6f25b6041246c5be13584a41cae7e244
+Digest = fb5dd3b8d280fe7c4838f01b2a5c28493ed3084f46b40642600ba39e43fbff7b
+K = 5b6f7eca2bcc5899fce41b8169d48cd57cf0c4a1b66a30a150072676
+R = f12c9985d454ffbc899ebbbb6cf43e3debcac7f19029f8f2f35cce31
+S = 12fcb848adbd8b1b4c72b2b54a04d936e4a5f480ae2a3ea2e3c1baae
+
+Curve = P-224
+Private = f60b3a4d4e31c7005a3d2d0f91cb096d016a8ddb5ab10ecb2a549170
+X = 40a4ab1e6a9f84b4dedb81795e6a7124d1cfdfd7ec64c5d4b9e32666
+Y = 83aa32a3c2fc068e62626f2dafce5d7f050e826e5c145cd2d13d1b27
+Digest = f4083aebe08c9bdb8c08ff844ffc207f80fa4406fb73bdbc1c6020f71281bdae
+K = c31150420dfb38ba8347e29add189ec3e38c14b0c541497fb90bf395
+R = bf6c6daa89b21211ea2c9f45192d91603378d46b1a5057962dafaf12
+S = cb6b237950e0f0369323055cd1f643528c7a64616f75b11c4ddd63c7
+
+Curve = P-224
+Private = c8fc474d3b1cba5981348de5aef0839e376f9f18e7588f1eed7c8c85
+X = 66f49457ed15f67ed4042195856f052fe774077f61cebcb9efddc365
+Y = 3a6e3f3423eec7308a69eb1b0416d67cc3b84d24f251d7cbdb45c079
+Digest = cb017b280093879c4b114b52ea670f14e97b661074abccc8539a23280fe136b4
+K = 5e5405ae9ab6164bb476c1bb021ec78480e0488736e4f8222920fbd9
+R = 7b7beaf9f696ca1a8051527478c4c075ab45aa4768937886dbf38618
+S = 93d4cf110a37c5a6f15c4e6024822118539e860dee2f60b8c3f462f6
+
+Curve = P-224
+Private = 04ef5d2a45341e2ace9af8a6ebd25f6cde45453f55b7a724eb6c21f6
+X = 8d642868e4d0f55ee62a2052e6b806b566d2ac79dbde7939fe725773
+Y = 79505a57cd56904d2523b3e1281e9021167657d38aeb7d42fc8ec849
+Digest = 5f1d77f456d7ed30acad33795b50733d54226e57df4281a43d3821d0762f12fe
+K = ec60ea6f3d6b74d102e5574182566b7e79a69699a307fee70a2d0d22
+R = 2fd7fcbb7832c97ce325301dd338b279a9e28b8933284d49c6eabcf6
+S = 550b2f1efc312805a6ed8f252e692d8ee19eaa5bcd5d0cda63a1a3f0
+
+Curve = P-224
+Private = 35d4bbe77d149812339e85c79483cb270bdac56bbf30b5ef3d1f4d39
+X = 7924b1d7f5920cce98e25094e40f2eb3eb80d70b17e14b3d36c3671c
+Y = 26c5af35f71e61858582b7cc2b41790597c53ee514ffdf7a289d108c
+Digest = cce0671ca07521fdaa81eced1dc37282bd9a6dbbaeb8cd00d13d4cf75cef044c
+K = 751869c1d0e79eb30aae8fbfb6d97bfa332123fd6b6c72c9cd3c1796
+R = 26bb1b92b0f01e94eba5fa429271371db527ce857abba13bd1103f64
+S = 836aba9c63e1252c2b2d72a21e6a41b82241ebe32647e7f814652bcb
+
+Curve = P-224
+Private = 2c291a393281b75264c9b8817af684fa86a1cdc900822f74039dc5d6
+X = 18cb5826ad60e6696bf07655032a3749f6577ca36da3ccd6e66a137c
+Y = 194e14820fe02d784fd1363ff7a30399518309765bd3f4412d646da2
+Digest = 4ee903b828f54f35adab0bfec06eb064abde530d8ed0384730aa23e8e9664801
+K = e2a860416229dfd3f5a5cc92344ca015093a543943a0d8f73bf2b2fd
+R = 00e300c1ef4a8c4ca5da6413856f8981db49de29bdf03f32ffc3ceab
+S = f250f18a51ba5f63e1584097841099fa6ae4e98ee458c061d1d5aed7
+
+Curve = P-224
+Private = 831ea25dbeda33d272a1382c5def0e83929170ab06a629eed6ee244b
+X = 076518e393940d42dfd09819409d66966d8c9189c83d554a9cc8a082
+Y = 44d0ceaf4c0f50e46bea4a52e30423ce3ada19edd363ac5694c65cb8
+Digest = 215e9817eccaa125e0c053fed373f4605de292d27a692bd4f744e63215fd8705
+K = 6be6dd9f6a083915ccba54626caf12d246d3aece0a7eda7d8d85599c
+R = ff1460946e06fb6f5d35e8d2625ca70ffb9b45308e3fabf6ad8351b1
+S = 6029aa3990918e8cb8a388d53b0772e5cdfff49c3405fe0d3a95933a
+
+Curve = P-224
+Private = 70f74c7324ef137318b610ead8ddc5b964e0eed3750b20612fc2e67b
+X = 279649e2a2918e683520cde3fc98b0ae58a7100e8de35e7c9cc797b6
+Y = aa4de6be34be61f02880139787b9038f4554a8ef1c994b887c2974b5
+Digest = 6571a344765c0512d3911a7724509b649a6ce4106823be76726f117f109ec0fa
+K = 8e984864f86f7a2a73f3edda17dbccd13fac8fa4b872814abf223b1b
+R = 3b18736fa11d04e27e2614cda03a63ec11a180f357b0b3192920d09c
+S = 2f0f3dbd570727b14fbb29155538e62c930dd51c4035275c1365dc60
+
+Curve = P-224
+Private = 026be5789886d25039c11d7d58a11a6e1d52cb1d5657561f2165b8a8
+X = 3fa617c50b177da1a2bdb98b780ad21ad1195c4bd24465f6187de3c9
+Y = e3fd8d8876dfd03a4a4e31a1acad3a08d983826d286c250c4e5620c1
+Digest = 95914b17ff0362e12305d71657bbc9d919ae4aa746bf4ebe95b2d2fe7ca3f022
+K = 0128b8e3f50731eb5fcc223517fc0cf6b96cd1d2807eb4524bc46f77
+R = 3a6b633f96f3d0b6d54f7fb29ac33709e4f0dd8fa0e51606ed9765ca
+S = 63e8c119dfa51784decd864f6911f2210a80f8f02d472d88df10d119
+
+Curve = P-224
+Private = e79c18d935c2839644762867aa793201f96a3cde080c5968412ce784
+X = b7ae1e992b1c7fde1141f40bd913358538ca0f07f62b729f13cea327
+Y = 811252d12120e04805fc171a439d382c43b68a21e1a0bdf5e4ec1da4
+Digest = 2dd97b10b2ac90709062989f57873e30696bf8376957e68f7de95aa333a67685
+K = 7abedab1d36f4f0959a03d968b27dd5708223b66e0fc48594d827361
+R = d35047d74e1e7305bb8c1a94e8ae47cb1591c3437a3e185e00afe710
+S = d9c425c9d5feb776ac8952e6c4eee0ecd68aef2f0e7bff2e49c9185e
+
+Curve = P-224
+Private = 0d087f9d1f8ae29c9cf791490efc4a5789a9d52038c4b1d22494ad8c
+X = cd95cf8fb1cd21690f40d647f2353672a1076cc6c46bddaad2d0fc56
+Y = 934262f74d9ee0f8a2754f64cb7415923d64bf00c94a39b52803f577
+Digest = 7c74a2e71f7bb3101787517394a67d03f977c95519526b47854e417b95bf8d1b
+K = 557d0e3995dc6377b3911546dd7aeaeec62a6d8f2af6a274382fc37f
+R = 56df0ea6afdcc232ceb41729eec00cf906b69b6e28423a36d3c92cc5
+S = f4f70fd948c9a147f55317fdea7b8a84c33e721014552d5800d63edc
+
+Curve = P-224
+Private = 0830aebb6577d3a3be3ba54a4501c987b0e0bb593267b9bbadb66583
+X = b88652020e083ccc1c43dc83d1881884dd4c7e3b4e3460b344b1ea64
+Y = 22b69b517f86d7c26dc37c0f8feb4bb07fe876149fbcc3334fd2805b
+Digest = ccc04666744685c57d2256f21cee0f53857a0528a96d59bb13cdeb92fd786d4f
+K = e4f4a3280574c704c2fde47ca81ec883d27f2c5a961a294db7cda9d2
+R = b30b8a0079d9a134b5e1618c2ac63e3fbe0e95866b9dbc5f423f2707
+S = 3dc36746610271ef66e0aa52cc2ccadc5c9b08dc769e4dc4f6538c11
+
+Curve = P-224
+Private = 2acc9b97e625263e8e4cd164302c7d1e078bfcdd706111a13ccda5b2
+X = ce1a06f82df874dded37cca03b56c0648e4e8917ecd40ee73ee61588
+Y = ceb6177b8f1ac7c5c6e6e1f7737cc3026952ee392badd2cd7af32f9d
+Digest = 9e7d5f30677692b669e21cf5461fa7f2e887dfcbbeb2db88d666bd591a944e00
+K = e401fa80f96480d437ed4f61a783888062ec33d530b188fd48016a6d
+R = 28674f447c4742e4087bbccfb522fbad4e18b56031d2ce8f532b078a
+S = a5a7a13d15b423dd17771f73cea98d89dbffa846cc209b45c0e29b76
+
+Curve = P-224
+Private = f4e873d4fb944fb52323406f933815092b7672221de4d1c45917f3fc
+X = 0dc2cdddb990341adb1de73f02d87fc3822485a659a15145f4251d5f
+Y = cf78b2a83c7352eda1af2c74e1804ea04b35f76c04e89d90281dc2bb
+Digest = d8978f697bef71b062d4b3211e8ab5b993c09920af803614dbb9437f6e261b70
+K = 5d1476c682a64162fd2fdc82696fc8cab1469a86f707ea2757416e40
+R = 82982b38ed465138df4018d7cfb835edcb591cb57446ca49d163782b
+S = 8ef1d7b326cabee7f7ab95b7b98d3c27a069c0fd95a1599c0ccb422b
+
+Curve = P-224
+Private = 62c572ee0d6f81b27e591d788bfc2f42b5105d2663078dfb58069ebd
+X = bd6ba605639b98fa8113a16a3bb004ddfaec901c98a931206165f4a5
+Y = a3190b10ef39e88abd60b2293b4707512b45c6c5ed5794cc11454427
+Digest = 1a9fc0195bf0f53cebba8aa7ccc8567c680d75187392d6d8201854ec4a6e6abd349037d831809e9f3add2fc09d27e4a4
+K = 0f0bb1e428bcdebf4dc62a5278068efc0f8ce75f89e89b3630f102b2
+R = aac0ea27e129f544abcc77f110e70bbdd5aa3e425dc39d5e8887025d
+S = 10e5dd06aee6b8419a04aa33d9d5678b0039c3acc3c4b61fe106bfdc
+
+Curve = P-224
+Private = e2f86bf73ba9336fa023343060f038e9ad41e5fe868e9f80574619a3
+X = f5d5346f17898ea6bbdfff19c216a8757a5dc37b95315f5481628381
+Y = ae61fd172ac8b7a4f13870a932dece465834cbd4f50bbcfb802c824e
+Digest = 0f236d9a43edd55dacf5ff9f93ee805395e130ca2c8ad2eaea0fdd68e2ee2fadae9f41aa46f881485db208bd9cdc463b
+K = 35724ac043e3b44b73b5a7919cf675190306d26aa67c27c28c873534
+R = 535147c265af138eec50c7fb570bcc8d2e6f675597b0fcc034e536bc
+S = 743812c188a1dddf9fb34b90738f8b2e58760d6cd20ccceb1bb9c516
+
+Curve = P-224
+Private = b0a203438e2586d7575bc417a4a798e47abc22aa3955b58fc2789f17
+X = dc5d217862a1e5b00c95affa9d8b925a72b9beaeb7a86dc397e788d8
+Y = 5f05f8e976ae1eb1036eca6d683a82850795bf9127dee5f8b2859445
+Digest = 525b6241eb2a6dd00b55b172708aafd0775e959b7c601903f44ffcfc17ee979f34f204680f8a71044a6d7e3679a50576
+K = 408e9c8b1f33136d6ddb93ff3a498bc09d4eee99bf69cdd5af0aa5a2
+R = 1b5a964c8b1fc634c6e2b82322499df1d7f0c12a4d2a77723c816ab8
+S = cf54599a36ca064fae0aa936de5266f87704409d22a15d28c01b7f2a
+
+Curve = P-224
+Private = efcfa50fad6fb2065f9a55f28c0c42fa24c809ccb19b6fc6d8ffb085
+X = 61521a0cfb72be77ba33cb3b8e022743cd9130ff49e97093b71aa178
+Y = ce0819aedaf6fce639d0e593f8ab0147eeb6058f5f2b448231584ea9
+Digest = 88c4b7ca396f17e82c92596c301e41d7f01810bfeb33173cc0d1fedf3fd5ace6892ba9a788de13417f0ef00ff87344fb
+K = d1eea821f286eae6ebc1f61b08f9ad4323a3787e94af4c32cd31351b
+R = b37caaa71103752ac559f9eb4943324409ebfa8b585f684dcaa5c411
+S = 7c28e7619e2944ab4b7be022878c8052ebdf2cae5dff4f976c49686a
+
+Curve = P-224
+Private = 61a17816937987764cdc064dc7b5b4f5b16db1023acdfe25902957dd
+X = a7e975c0a8f87c683bb8e31bc160843a7b69c945f4850bd60e1c08c0
+Y = 8930a454dcc2aa13bed7ea89368b2c9d689d816b2acf4e52585ee9c4
+Digest = 3babfaba30f3300171e6adcf4f62a12287031ac40078c96b2c2c063849e9a42ef3be953dc11fb319c18bf22fe511bf37
+K = 44b1fdec2629f9075f89c134ac28ff19bfddaa9db02a5d7f853582b4
+R = b0f5635d8bc9c53a1d54a3ec63de59ed66e6b2358d4ab79755414326
+S = 67c68fe265c7e5aba4232deeafb88545a2aa266fb9f2c2bb3f3ae8d2
+
+Curve = P-224
+Private = 79d5367314ec664aa0f6ca36f95549502a05bf8400bf532d669fab8d
+X = 3191f0237102dac159032ab2dde53cf56c9ec827b5caddfe9e83c02a
+Y = b496b1bdcca4434ac0d0d91ea38ff3bc33f9f54095bfe17796d5a9e2
+Digest = 9f36da1a5653469a52f85e7e3b2a21ac3497cc00ff37e03235bbdf951695f182312ad5c8fb8a5fbd0295dc8c5acda068
+K = da529c52f5cc1f435d873109cd991d6cd7e1631d9ff1dd9521dd5db6
+R = 8e0ac63903f4921755430572c3f08bc272790639bdf1009fe2a9a714
+S = 6278c841a2d0a270791fe54b36c49d426d67907aa4e4f59c8638ad97
+
+Curve = P-224
+Private = 1320eedad4745121793a7eaf732b0b4498f7cb456cac8cf45a1f66f0
+X = 9fdd99906ab77fd29e9021bde947d05a7a9eb153612269bfb0899bc9
+Y = 681b65b9ac8e4c2899bb622dafb253b7bf5a6e38e5f6595f997c291a
+Digest = 12532cbcfd4e80373bc235ac0bfa2a70b1044786d29f9384d555030f5df3cb5ab9f973df638b6835cb756792d1fe1a4e
+K = 66ed8d8934633f4125f593cf1b1d3745c4db1f15dde60cf46ca1c7f2
+R = 80199485a3a96447b39f7679cd47412a78675ba17dcbd10465dc5b48
+S = a251fd9f136a3cb0dd0bc80659ae032e4a761ba7045da0034553fb8c
+
+Curve = P-224
+Private = e18821329447d3f65ba7279e96bd4624ffa1b32b90f6e8331b1e876d
+X = 46c9ed837232c47022df2f1a1578fbe65ac9f2e81c98a74cc22ea31a
+Y = 6fc5e9568ae62b31412a0b0b367242e9fd7e518c83aa06a069e1d90d
+Digest = 89030408e06cc06d3dbfb51f6725c710a2bc9db9e07ff1ec8a32a827d93d2dc951834cdb01a7afa1fe4cf4e9186ee424
+K = a4c1eb402a2fb3af26e0e14a3d2fc8ed3bc1a8b2475270356a79fdd3
+R = d478b68733d8ad44be46766e7b66af782fbdc7ff7ed0b191176da98a
+S = 5eae9160ccf71fd1d359d89cecce72ef8afaeee2365f6ba828aa450a
+
+Curve = P-224
+Private = f73e030d5a696b358986d3efaca121cf71f775f8835a21e6135145d7
+X = 9ca2c6ea87ac8dd3a23a5b4010841a7c8af309038882ae44634bcf55
+Y = b0a347dbd5ded3b8702ac5a457e8b32bd4de06fd315095fa1b7d5fe1
+Digest = eda24262a9e64be110a6c96763e8a4b5edb38af2a084695e294593583b462c56b0db50bc014eb19278e3f3d675eb5f22
+K = e3cc786c1288ea567836c51d6d69dd0cab5c015987d936ccc3a4beb3
+R = f1234da71761b7a0f49e661a419d2a739bdc4544bf87690e3d2f96db
+S = 096d16bf8020c3d3c233894ad8eb81206010e62c6e692a215e088fd4
+
+Curve = P-224
+Private = 7a0789323f8741c157a1753ae165ecaf8e8b03a60561f8b80cee467c
+X = 101271a9addd4bd1f19d00bf116c8524f52cefd598e85dc381597acb
+Y = 2f17d14f4d8ccb28b216553718152ba7c104646d8eca986dd9ddea39
+Digest = 983a5d16b009cc65bdf3c3badc2f21280e04f44244b70a583c2e9732534497373f51b226c3ab7bd69c6940e46bc41fa1
+K = d169f04f05b60c625cda864d187938863964dab7bb3b9dfc04b05519
+R = e4a51be686a764b709da23ab48b1985e153c6ee238d945e743907afc
+S = 118a8f1ffe3cd556ce6345bd1a398dd9cc3729b7fd6d8af9bfd82f40
+
+Curve = P-224
+Private = 78e795d0edb11fd9e28dc26b21e751aa89bea0d87932ef11c95c0e18
+X = 9edd544107977134bf6360d43ccabb3c94d627c03963c0a04b439627
+Y = ece4c61d319a0e41f3de7863e7c355bac94395aaa74cdb5f74a87a5b
+Digest = ae7b5fde427af9c450368b11f66f49bf8c3b6e1f5abed6bb25683001924dfb005738637e1c1b7855566330d202ecc763
+K = 36f7c0f76808b826a0a974a1fd6e155e00a73f1d34674a8f88be405a
+R = 3e319444438bc2cc92f323ea842cb402b3c3c2448c89869ef7998edb
+S = 3420cc38f058f41c31e71f4b1ad488f801111c73541de69fcee60695
+
+Curve = P-224
+Private = bee02d8bc5bffb3fd3b4c9d6f686409f02662d10150d1e58d689966a
+X = 8848f964c847fe9dddc774618d4588c9cd56bbe588d7b1fb369c8bfa
+Y = ebbb699fbd0dc08859fe9132285fe20dff3b9d561c0640b6e0717607
+Digest = 63ef787f467ff0cd6e5012b09414c00ef56dba959c4b62bf7e76a4205078d436c45591752c8d55abe728a2d28b5b0643
+K = 59f1450d857b40e5552a4b8cd4ab0df2f01716635d172c1106840f21
+R = a206d8398a16a991bc217f77f23c6f648384f254f255a8a876404444
+S = eb1169cb5b1423dc0bfaffe565ae57f986e00de06405e3e7b605862e
+
+Curve = P-224
+Private = dc0ddf6e501418bb8eafc5d7ccc143369e2aa441df8fc57d5f94a738
+X = 063a5d632f4144376e14cfb03ad8ccf1489b613acd184d20dff66545
+Y = e77727f057b043d8a0f7458196b72e92d11f85b0891c6aaa9d915f58
+Digest = 11f0d587e82e7490af4737c272877d9d37c1e7ae7f2fd3b00d8fa0d4f2bcb3a41d5185e65604b8c411a407eb6c558954
+K = ff0e5cae2671db7a1b90e22c63e7570bdd27352d45bac31e338debe0
+R = 5bc0b4998481ecbd3b6609184a84ca41d69b08c37138097f559259f8
+S = 0df8828eb1ca85e46405b94e1a2972c34c5e620a54e2f640f04aecc5
+
+Curve = P-224
+Private = 229d89b2fcf8441ffc95ebb2ac2ef156e25825782044b2b8bd6a3e01
+X = de616848d8044a44789ef1ba3a6dd66fe9257ddc57f7534e59a701be
+Y = 26cbf74a6d25e5b34b96d30f327abd574cff7f7dbe6686573a7d6c5c
+Digest = 537d6d3d4be3e3beaf31014dae59ca7186c1c1a32c88068ff343180a138ceb6d7c38e0ae1e9b51003b71c1a2f3a3741b
+K = 3b18ca6ec8e8e255ac88f64302745ca0b73ff94b2b2d48be95b4aaee
+R = fa94fd8b827c06115c1eefd50afc02ce5926ee0e789667783c01c34b
+S = edf766a66973cfc33e4159966c07321a7f6549c3c60e8586ef41402b
+
+Curve = P-224
+Private = 97d747068147c0393a0bb5c159e2c9f1bd538f6204823294883abe28
+X = 3858a576eef2ce24d01766997fb81b3f3f78b6104cd188610be221d7
+Y = 95ffc677ac7bfe3e0bb4cffb17355a964c8356a807151b3cba5d1f4e
+Digest = 7e16034a71ebf52a7a6cd00fe469c6edc121b2882462176298c9443aca2a0ad6ebe2eb9e145097409873170f40d503dd
+K = c1a2ec1ef16cfd5107c892790daefbed061be78bd8576696b60f64d5
+R = 18c908541843fcdac99b9ff6bb397f3f8094d16b42670216e4eaa2d7
+S = c107a8a508ff57c5d4f78f86cc37e129c864d1c44ed5e73909613b74
+
+Curve = P-224
+Private = ba5374541c13597bded6880849184a593d69d3d4f0b1cb4d0919cbd6
+X = ac635fe00e8b7a3c8ef5655bdfb7f83e8532e59c0cc0b6534d810ffa
+Y = 1d067aebeba66e79b28ecfe59ac6fdf5e1970dc3a84499c9d90cd8e2
+Digest = 3edbb59a32b2464291d0a96023a798c1fc6cb5ff4fcecfadcfac2be00c26fa27181aef76c96d8269aeaf2275eeacbb777abbd9571de9279edc5695a3345cad9b
+K = 187ed1f45c466cbafcd4b9577fb222408c011225dcccfd20f08b8d89
+R = f83d54945997584c923c09662c34cf9ad1e987da8bfd9be600e7a098
+S = 4ff2dba9dba992c98a095b1144a539310e1a570e20c88b7d0aa1955c
+
+Curve = P-224
+Private = 1e27187134d0a63542adf4665fba22f00cfc7b0a1e02effe913ceedc
+X = ecaea8ceea55c3bd418fd34a4ff2499e25e66a104eed846bc00c31d2
+Y = 3933a356ab1f2dabc303ff0a5d076131e77032e6f502336883bf78a7
+Digest = 825ab979af5c263d9f074a2d771d1d1cdfa435e7938245a3c9ee30cb77ee8c1475051d2f09d7d11d920a6c754bfd253903131c491994679cafdb8cfbf32b763d
+K = 34cb597deae9a3b1cada937abcd247161b19b2b336b20e2e42ae01f1
+R = 58177ba46fb291490b39368774accf72736412c1fb5ee0f27b9b1e02
+S = 58337d78b95a080bfcabb5809bee012501b4da84b8ef310a4628f11c
+
+Curve = P-224
+Private = 0905b40e6c29bfcbf55e04266f68f10ca8d3905001d68bb61a27749b
+X = d656b73b131aa4c6336a57849ce0d3682b6ab2113d013711e8c29762
+Y = 6328335ffc2029afbfe2a15cc5636978778c3f9dab84840b05f2e705
+Digest = d0db7c20c201cd8c63ca777293543750d7f6a9e375b056e74cfe9fb2c95b2cc9807d8a9607a5b0fad6eeda86e4f73ace139e77a5356181b8cbef3f88173253b6
+K = dc82840d147f893497a82f023d7d2cbf0a3a5b2ac6cc1b9b23e504be
+R = 583af080e0ec7c1ba5a491a84889b7b7b11ccfe18927c7c219b11757
+S = b23700035349df25d839f0973bef78a7515287de6c83707907074fa6
+
+Curve = P-224
+Private = afbaede5d75e4f241dd5b53220f3f5b9c1aa1d5d298e2d43236452dc
+X = fe83e59fc8ea8b939355d3258fe53a64d45f63031a0716b7cc416173
+Y = f151d23060f1c856eb7f1f58be72a7228c3af89e43b56e9695b558c7
+Digest = 37d9091eddc6fc34b45cf97140e956a42ab659f6bd442e81b57c4ecfbdab45f7380a7efdbac5400ceb1bf683194232cd086c1b4e09fc9313f1bc38af731f1a98
+K = 0fbbe7b40136c81a8fb894498d5502157a1cf5a89d0643de92cd38f6
+R = 24f3f457c7b72b7e759d5a8afbf330e31c5d8d2e36f92c0e79c5d87d
+S = 36fd1193def34f12a960740fd79fb38bf2b480726ccad540eb42cdf8
+
+Curve = P-224
+Private = 950b07b0c2b7539a21b5135bfede214733f2e009647d38d8b21d760c
+X = f43d13bbfcee3b724063b3910fea49fd591b81e86fdb813b1a492d0c
+Y = 6b4c8d6fa5dc661889e3cf5ec64997a78222837885f85d2fe9b684fb
+Digest = 8ddf64c9c67289a76c2f5b44a30b8365f4adf487b4edadada5749cad9e5765c57a348a750817a53e5c2ff551e003747ca1e3438b2aa1952c6876fda8fd8f4de2
+K = 83e110d0d1e700d2f36543028737d2a2f1474aa3b4b28998a39e4793
+R = 2685265bc878e85d10ab13293dec190881a57c4a467f8fc2170432ea
+S = 80a347bb49036522369339bd6485a967cdda818915d8eb947302fcf9
+
+Curve = P-224
+Private = 015bd9f5dfef393b431c3c7fced24385d861ccb563542574a5d2a9bc
+X = e868690641e2cda13b289a6c5d2fb175940396044d9cf27b4f2240af
+Y = 4c78c9abdf2b7fc67ed4497001d7bcf1daca1739dc14a661f91d7c40
+Digest = 7c22f34d5897ccdf7d807f68a7f16e3093a4413625e7853401a4e0384d26893f1997c84557515f2ea66afe7629f62415e6b98e18e97dcb4fb2dec97cf2dd68d9
+K = e2374350f47c08f3c1359d4edf87e61d1ba4e7dd1540d8d9062efa79
+R = e12dc088d2bc032bb214c77d0e0fb749fc8e61ebe1ed72996f1084b6
+S = 0ab58aa31e0bba5fbc76855e6549f1036fba0a589aeab978ab01b8fb
+
+Curve = P-224
+Private = 0a3c259df933247445acffb6d8265b601d597fb9997dc2a1eb4deef4
+X = e67f4385a9da54253cc371ee9bc6739ae6385a4b87669c7baf0c460d
+Y = 2bb00b6ddd7b67d9ac5653ec04ca8529fbf16f815c04da3c2e58e82d
+Digest = 016d26cbcf55236c053ece58651183e4c81edd8f07749a5ba28d8d22a5d6a9c6b33810c9618bd9cf472006cfeb62842927d3fb677d82e09bb5134e470d481812
+K = 8bf5859665b6a23e6b05a311580f60187ba1c4ae89e44877fb48af66
+R = 653675fb993c3fa9e57b32e33029ec230b966e8077c72c1ec90ddefc
+S = 792723bf87e315147cd4303de7f1dfe95cd7658ebb95c38c1a196140
+
+Curve = P-224
+Private = a1c8ef463f9e7e3dd63e677412f87cf9ea4ac9a6a2dae629da5b9916
+X = 400e5cd4b315ceb309545cd3277acb70bdae2073fda6ad896ea14b27
+Y = fbe1d2466cd2e116f38248bd5cabaa6cbe6c4a2694d998abd7b0c991
+Digest = 47e43ab8ebe14f0394c46b55856104211b12d8f2b075f6efa1510fed823dc121cfd9198e060839ebbdf2eb994194875c342be861bf0975665aae881f28cefbc0
+K = 82f55a25d3ed6e47c22a6eed0fa52ed0818b87d6ea7950281dfefc09
+R = 16305a46a3f6f9e216ef8f6a6f5f0760d064a885657c864e1c1ea035
+S = 58fd97050bfbca6f87e64e1458c4ad80bae26e280356da344ad3b25d
+
+Curve = P-224
+Private = fa511dbf6fef7e5e9c73e4555eb75d435f7884322d9faf5d78cacc0b
+X = e8dccd706c31f895f2f261ab979cbab51b8ae28196bcc12a42046380
+Y = ec246be8e71ea3859cb717a59990fe22e4b76858ff49becd70739a01
+Digest = d86bfb4fc2ae431617d8800e44b37a5b549775c78e90eaec58b42aebafed731b3123a82fab13254783e24c28db715c53f6538a2961cc888638eab768ee6b66c0
+K = a37d665fe4314aa4cd03eb8e6a1f366b43e11fdb419c96b48f787b62
+R = 05e4909bcc172ab4140be291aad4660e375032bce2d762b6269ba764
+S = e347a1c9d3670690e1d8d1d4cd9579848f442199c10526488da5cebf
+
+Curve = P-224
+Private = a58bd53646400a646f0e4208320dc679a9664d1c6bfb27fdc8eac7ea
+X = e22e0dc4ecd96eb0071b72ba4b4988bf784f3fe73cb81bfb93d9ac4f
+Y = b3e213e518bee1367a4fb3703b9008bac9d95a1fc4aa61225fff9f3c
+Digest = e537383a08a421bf1f29e07554387bd32d685c2a5830b157df1e83c0f3c78cd11e5a5cc62830a45d7eb71920a2d13ca9cc1eec020c9db49a07d1c91433b31e2c
+K = 42c5b6f87d3bb1ed74f5ee8398d8f8c61e9e50ffa7a1da12d39893f9
+R = 5c0e5c6f057de1e99ef5d237a60d7a07fa9a42b120a82f573d9fb7b2
+S = 2fffc0bf550bd2f650fed085a84501cacfa6a1bb984df1f9237eaa59
+
+Curve = P-224
+Private = 64bd4452b572cc95510ac2e572f41136299ff17f6e8448f4ffb571d0
+X = 92521fa25c2e034d127e0921efdb167f0b2ff8b20504487ed87fa264
+Y = e72c770e37375ad7dc2c4e63e5701826f6606f6ffb9461ee61b4e872
+Digest = e7a2242c4409f1eefabffc48014a00424ae3b38c39651227d033b464c2ed4a365841499048b8e491506657e40548a104b4d9d08dc86b6d6dd43af27730788639
+K = eaf76ee4d7e00d13d8a6d03dffd07ad9a8bb6dc8176c9f93059b1b7f
+R = cf5058e2a6cf5e61a138b013eb292f38a1b9f07239ae5941dbce8919
+S = d14198621650d985d270bc997da6e78588fd0ef843b874c66a3de3c3
+
+Curve = P-224
+Private = 7f3edb710df9d982f486233d0c176aa88f5a0ee81efa9b8145020294
+X = e7611e013e7b43ff5b8b57ad83333bffcc9e469ad23070b5791dc594
+Y = 7784da0a11dbe16208c6e0b6d5029e71fbec4dffc9fa046d3eeb71c9
+Digest = 8b751b00d1bb15cc16f6ea2e67b3235c9a50e8cb602eb20dd846c92375ef8446bf1ff1c77fdbc93cfb7d4e845774a27983aaf3fad289ba8495183d03e8b3bbe0
+K = 94db7ef9a232593091eb9a74f289529c7e0d7fef21f80b3c8556b75e
+R = a971f45bab10b1d16d7234ca8e4ec987da20d9e867f28aa063296e23
+S = e38c538d65a7e1a28fd3ec53f015a7e5beb60e9d309f1e3ba4b2c3d2
+
+Curve = P-224
+Private = b569f8296ff1d9cc01fffd9919016e5730c1858bdb7b99527153751a
+X = 242f34959516a4706172f7dede23110efa314bff22eb320ab88feeff
+Y = 45e3227710900a8acfc9bcce728119d042f64ca40876c2b380ee46e0
+Digest = 89670327dfc4c3a20cd71c6943d3404c34c4b2267b892ae69dee792107ea19e90cc792c3ab886e6c1247e37c3eae8d81cff87b24e06f476e32dae64303349a23
+K = ae61523866a8f43e6cdd42ba27a34ed06527e8a5842901a64c393f76
+R = c2732a4e0815f9f785500e80147e9486994446beccf8a6a352b97585
+S = 6ecaece6487d7920e398f7f951ab7c7aba5832dabf03704106ad1244
+
+Curve = P-224
+Private = 41a4dd8eee39232b728516e2f21e66011e7426a6b25986c3ffa237e4
+X = c32988171caab178bf50dc7310bc7f604df5a9d19a8e602519c72d8a
+Y = f8985d112ad9de05969e5364d943c1cc5cd198359f4c62b19da0e117
+Digest = e94800f0b0272d7e59c7e2614318df5652261e89c47fbd0c01b016e569825a4a1b0631e0749dca72b47a4edaac6e6463c7b1c8c3038b20d06d160fc0e1c217e3
+K = 827d4999da81fa920c8492ccc1e2d5cdafed9754cf7382a859952071
+R = 89c61da7422ccd676baec07e2185c12e947a2374eede87847304be6c
+S = 2685379624717ea28422e8d001c090405a130b4ef9f1ac726c3ca502
+
+Curve = P-224
+Private = 67fa50569257c8cc89ac0325db4902003a62f30b917f53e4035a7e04
+X = 6773a0436a9c42635730413b19aa4166f08c69c0e5002953da42253b
+Y = 555138290b093bf2fe79acda9131d920cd1e7ac43fb8775776cd713c
+Digest = 0bc258cd68474b7df93d2b3209048f571fb0fad76e4c1a5d6e0fc83c2aaff5e50fc978c36a47fb2c0163ad47333b78ed08e07fc21ba2230356a54885a8df2fe5
+K = 557cb45fd3a30b3bdbf08c56eabbd4478736024aaa52bf8448096453
+R = 8e92cf7a674aa5f7542dd95c695589a05747431692edd04804299b8f
+S = af4908b41f8180b71a6ff10fd51f3d143147af6ddddf7534d3284ed9
+
+Curve = P-256
+Private = 708309a7449e156b0db70e5b52e606c7e094ed676ce8953bf6c14757c826f590
+X = 29578c7ab6ce0d11493c95d5ea05d299d536801ca9cbd50e9924e43b733b83ab
+Y = 08c8049879c6278b2273348474158515accaa38344106ef96803c5a05adc4800
+Digest = 5e53611194b517b0ef4f704684850dfa387f99997d586d43c9e41530
+K = 58f741771620bdc428e91a32d86d230873e9140336fcfb1e122892ee1d501bdc
+R = 4a19274429e40522234b8785dc25fc524f179dcc95ff09b3c9770fc71f54ca0d
+S = 58982b79a65b7320f5b92d13bdaecdd1259e760f0f718ba933fd098f6f75d4b7
+
+Curve = P-256
+Private = 90c5386100b137a75b0bb495002b28697a451add2f1f22cb65f735e8aaeace98
+X = 4a92396ff7930b1da9a873a479a28a9896af6cc3d39345b949b726dc3cd978b5
+Y = 475abb18eaed948879b9c1453e3ef2755dd90f77519ec7b6a30297aad08e4931
+Digest = 50be7b4f0e1fa36f06eb430ad4afe8f0cea2b97e060230f91ed1922b
+K = 36f853b5c54b1ec61588c9c6137eb56e7a708f09c57513093e4ecf6d739900e5
+R = 38b29558511061cfabdc8e5bb65ac2976d1aa2ba9a5deab8074097b2172bb9ad
+S = 0de2cde610502b6e03c0b23602eafbcd3faf886c81d111d156b7aa550f5bcd51
+
+Curve = P-256
+Private = a3a43cece9c1abeff81099fb344d01f7d8df66447b95a667ee368f924bccf870
+X = 5775174deb0248112e069cb86f1546ac7a78bc2127d0cb953bad46384dd6be5b
+Y = a27020952971cc0b0c3abd06e9ca3e141a4943f560564eba31e5288928bc7ce7
+Digest = f51177ab6c34bf80ea72d687a670e4102987d1378bd9a4d973af4dad
+K = a0d9a7a245bd9b9aa86cecb89341c9de2e4f9b5d095a8150826c7ba7fb3e7df7
+R = b02a440add66a9ff9c3c0e9acf1be678f6bd48a10cbdec2ad6d186ffe05f3f2a
+S = a98bea42aec56a1fcecec00a1cc69b01fcbcf5de7ac1b2f2dcc09b6db064f92b
+
+Curve = P-256
+Private = 7bbc8ff13f6f921f21e949b224c16b7176c5984d312b671cf6c2e4841135fc7f
+X = f888e913ec6f3cd8b31eb89e4f8aaa8887d30ae5348ed7118696949d5b8cc7c1
+Y = 08895d09620500d244e5035e262dea3f2867cd8967b226324d5c05220d8b410c
+Digest = 03bf686dab49196f887f3a8083f1a39e26085127a9d9e6a78f22f652
+K = 21c942f3b487accbf7fadc1c4b7a6c7567ce876c195022459fa1ebf6d04ffbaa
+R = 2e6cc883b8acc904ee9691ef4a9f1f5a9e5fbfde847cda3be833f949fb9c7182
+S = 2ac48f7a930912131a8b4e3ab495307817c465d638c2a9ea5ae9e2808806e20a
+
+Curve = P-256
+Private = daf5ec7a4eebc20d9485796c355b4a65ad254fe19b998d0507e91ea24135f45d
+X = 137c465085c1b1b8cccbe9fccbe9d0295a331aaf332f3ed2e285d16e574b943b
+Y = d3e8d5a24cd218c19760b0e85b35a8569945aa857cbf0fd6a3ce127581b217b6
+Digest = 40a7ece19f7f6a6473b209a7ac9441d59b00fc94ae0ded3423427c12
+K = 343251dffa56e6a612fec7b078f9c3819eab402a72686b894a47a08fd97e6c23
+R = 775e25a296bd259510ae9375f548997bec8a744900022945281dc8c4d94f2b5b
+S = d87592ceab773ae103daebbb56a04144aaccb1e14efc1024dc36c0e382df1f70
+
+Curve = P-256
+Private = 8729a8396f262dabd991aa404cc1753581cea405f0d19222a0b3f210de8ee3c5
+X = 82b1f1a7af9b48ca8452613d7032beb0e4f28fe710306aeccc959e4d03662a35
+Y = 5e39f33574097b8d32b471a591972496f5d44db344c037d13f06fafc75f016fd
+Digest = f6c083325d6316e337c102b16bb96faa478a43b2dc0d56d51a4affed
+K = 6de9e21f0b2cacc1762b3558fd44d3cf156b85dbef430dd28d59713bfb9cfa0b
+R = a754b42720e71925d51fcef76151405a3696cc8f9fc9ca7b46d0b16edd7fb699
+S = 603924780439cc16ac4cf97c2c3065bc95353aa9179d0ab5f0322ca82f851cf2
+
+Curve = P-256
+Private = f1b62413935fc589ad2280f6892599ad994dae8ca3655ed4f7318cc89b61aa96
+X = e0bbfe4016eea93e6f509518cbffc25d492de6ebbf80465a461caa5bdc018159
+Y = 3231ee7a119d84fa56e3034d50fea85929aec2eb437abc7646821e1bf805fb50
+Digest = 6890736262386d60424be27b3f95996ab696e1ddffdc4a03c256a7c0
+K = 7a33eeb9f469afd55de2fb786847a1d3e7797929305c0f90d953b6f143bb8fc6
+R = 96d1c9399948254ea381631fc0f43ea808110506db8aacf081df5535ac5eb8ad
+S = 73bf3691260dddd9997c97313f2a70783eacf8d15bdfb34bb13025cdfae72f70
+
+Curve = P-256
+Private = 4caaa26f93f009682bbba6db6b265aec17b7ec1542bda458e8550b9e68eed18d
+X = e3c58c1c254d11c7e781ad133e4c36dd1b5de362120d336a58e7b68813f3fbee
+Y = 59760db66120afe0d962c81a8e5586588fd19de2f40556371611c73af22c8a68
+Digest = e8ed2e73fe9e3c6bb087c5179bb357be4cd147bc66e70dc1fecc10fd
+K = c0d37142dc8b0d614fad20c4d35af6eb819e259e513ddeac1e1c273e7e1dc1bb
+R = 25dd8e4086c62a40d2a310e2f90f6af5cb7e677b4dfdb4dc4e99e23ea2f0e6dc
+S = 90ad62c179b0c9d61f521dde1cd762bfd224b5525c39c3706f2549313ddb4f39
+
+Curve = P-256
+Private = 7af4b150bb7167cb68037f280d0823ce5320c01a92b1b56ee1b88547481b1de9
+X = cb3634ec4f0cbb99986be788f889e586026d5a851e80d15382f1bdb1bda2bc75
+Y = 51e4e43bc16fb114896b18198a1aebe6054ba20ed0c0317c1b8776158c0e6bfb
+Digest = ca7e8c8c873346c85db9ac648509c8ccc9ab5651d91e35a248b951fb
+K = 98edd59fafbcaee5f64e84eb5ed59fff45d14aabada47cee2fa674377173627a
+R = 261a1cdb0fd93c0fb06ea6068b6b03c330a12f621a7eba76682a1d152c0e8d08
+S = 7ca049bad54feee101d6db807635ffb8bdb05a38e445c8c3d65d60df143514c5
+
+Curve = P-256
+Private = 52ad53e849e30bec0e6345c3e9d98ebc808b19496c1ef16d72ab4a00bbb8c634
+X = 7cca1334bfc2a78728c50b370399be3f9690d445aa03c701da643eeb0b0f7fa8
+Y = 3f7522238668e615405e49b2f63faee58286000a30cdb4b564ac0df99bc8950f
+Digest = 3367c395a9ad7b8214c48658f2a4b377b6b0288ba272a4fbfeaa48df
+K = 8650c30712fc253610884fbba4a332a4574d4b7822f7776cab1df8f5fa05442a
+R = a18194c7ac5829afc408d78dde19542837e7be82706c3941b2d9c5e036bb51e0
+S = 188ead1cdf7c1d21114ff56d0421ffd501ab978ef58337462c0fa736d86299af
+
+Curve = P-256
+Private = 80754962a864be1803bc441fa331e126005bfc6d8b09ed38b7e69d9a030a5d27
+X = 0aaeed6dd1ae020d6eefc98ec4241ac93cbd3c8afed05bb28007e7da5727571b
+Y = 2dda1d5b7872eb94dfffb456115037ff8d3e72f8ebdd8fcfc42391f96809be69
+Digest = a36a7d6424763633320ca799667f1b79955f079fb1b6dc264058af41
+K = 738e050aeefe54ecba5be5f93a97bbcb7557d701f9da2d7e88483454b97b55a8
+R = 8cb9f41dfdcb9604e0725ac9b78fc0db916dc071186ee982f6dba3da36f02efa
+S = 5c87fe868fd4282fb114f5d70e9590a10a5d35cedf3ff6402ba5c4344738a32e
+
+Curve = P-256
+Private = cfa8c8bd810eb0d73585f36280ecdd296ee098511be8ad5eac68984eca8eb19d
+X = c227a2af15dfa8734e11c0c50f77e24e77ed58dd8cccf1b0e9fa06bee1c64766
+Y = b686592ce3745eb300d2704083db55e1fa8274e4cb7e256889ccc0bb34a60570
+Digest = 864f18aa83fd3af6cdf6ac7f8526062d0c48a8d3c341cc23d53be864
+K = 2d6b449bb38b543d6b6d34ff8cb053f5e5b337f949b069b21f421995ebb28823
+R = 5e89d3c9b103c2fa3cb8cebeec23640acda0257d63ffbe2d509bfc49fab1dca6
+S = d70c5b1eeb29e016af9925798d24e166c23d58fedd2f1a3bbdb1ef78cdbfb63a
+
+Curve = P-256
+Private = b2021e2665ce543b7feadd0cd5a4bd57ffcc5b32deb860b4d736d9880855da3c
+X = 722e0abad4504b7832a148746153777694714eca220eced2b2156ca64cfed3dd
+Y = f0351b357b3081e859c46cad5328c5afa10546e92bc6c3fd541796ac30397a75
+Digest = 916924fcced069bf6956eeb4e8f09dc9bf928e8a690111b699e39eab
+K = b15bbce4b382145de7ecd670d947e77555ef7cd1693bd53c694e2b52b04d10e1
+R = 9d086dcd22da165a43091991bede9c1c14515e656633cb759ec2c17f51c35253
+S = 23595ad1cb714559faaecaf946beb9a71e584616030ceaed8a8470f4bf62768f
+
+Curve = P-256
+Private = 0c9bce6a568ca239395fc3552755575cbcdddb1d89f6f5ab354517a057b17b48
+X = 4814d454495df7103e2da383aba55f7842fd84f1750ee5801ad32c10d0be6c7d
+Y = a0bd039d5097c8f0770477f6b18d247876e88e528bf0453eab515ffab8a9eda3
+Digest = ec2fb907b92865e501ce97f703cf6214a6de2303df472ba58145af16
+K = d414f1525cdcc41eba1652de017c034ebcc7946cb2efe4713d09f67c85b83153
+R = 84db02c678f9a21208cec8564d145a35ba8c6f26b4eb7e19522e439720dae44c
+S = 537c564da0d2dc5ac4376c5f0ca3b628d01d48df47a83d842c927e4d6db1e16d
+
+Curve = P-256
+Private = 1daa385ec7c7f8a09adfcaea42801a4de4c889fb5c6eb4e92bc611d596d68e3f
+X = f04e9f2831d9697ae146c7d4552e5f91085cc46778400b75b76f00205252941d
+Y = bd267148174cd0c2b019cd0a5256e2f3f889d1e597160372b5a1339c8d787f10
+Digest = b047a2a715335a1cc255beb983355e7d1363c610bf56df45d4503e69
+K = 7707db348ee6f60365b43a2a994e9b40ed56fe03c2c31c7e781bc4ffadcba760
+R = 5d95c385eeba0f15db0b80ae151912409128c9c80e554246067b8f6a36d85ea5
+S = db5d8a1e345f883e4fcb3871276f170b783c1a1e9da6b6615913368a8526f1c3
+
+Curve = P-256
+Private = 519b423d715f8b581f4fa8ee59f4771a5b44c8130b4e3eacca54a56dda72b464
+X = 1ccbe91c075fc7f4f033bfa248db8fccd3565de94bbfb12f3c59ff46c271bf83
+Y = ce4014c68811f9a21a1fdb2c0e6113e06db7ca93b7404e78dc7ccd5ca89a4ca9
+Digest = 44acf6b7e36c1342c2c5897204fe09504e1e2efb1a900377dbc4e7a6a133ec56
+K = 94a1bbb14b906a61a280f245f9e93c7f3b4a6247824f5d33b9670787642a68de
+R = f3ac8061b514795b8843e3d6629527ed2afd6b1f6a555a7acabb5e6f79c8c2ac
+S = 8bf77819ca05a6b2786c76262bf7371cef97b218e96f175a3ccdda2acc058903
+
+Curve = P-256
+Private = 0f56db78ca460b055c500064824bed999a25aaf48ebb519ac201537b85479813
+X = e266ddfdc12668db30d4ca3e8f7749432c416044f2d2b8c10bf3d4012aeffa8a
+Y = bfa86404a2e9ffe67d47c587ef7a97a7f456b863b4d02cfc6928973ab5b1cb39
+Digest = 9b2db89cb0e8fa3cc7608b4d6cc1dec0114e0b9ff4080bea12b134f489ab2bbc
+K = 6d3e71882c3b83b156bb14e0ab184aa9fb728068d3ae9fac421187ae0b2f34c6
+R = 976d3a4e9d23326dc0baa9fa560b7c4e53f42864f508483a6473b6a11079b2db
+S = 1b766e9ceb71ba6c01dcd46e0af462cd4cfa652ae5017d4555b8eeefe36e1932
+
+Curve = P-256
+Private = e283871239837e13b95f789e6e1af63bf61c918c992e62bca040d64cad1fc2ef
+X = 74ccd8a62fba0e667c50929a53f78c21b8ff0c3c737b0b40b1750b2302b0bde8
+Y = 29074e21f3a0ef88b9efdf10d06aa4c295cc1671f758ca0e4cd108803d0f2614
+Digest = b804cf88af0c2eff8bbbfb3660ebb3294138e9d3ebd458884e19818061dacff0
+K = ad5e887eb2b380b8d8280ad6e5ff8a60f4d26243e0124c2f31a297b5d0835de2
+R = 35fb60f5ca0f3ca08542fb3cc641c8263a2cab7a90ee6a5e1583fac2bb6f6bd1
+S = ee59d81bc9db1055cc0ed97b159d8784af04e98511d0a9a407b99bb292572e96
+
+Curve = P-256
+Private = a3d2d3b7596f6592ce98b4bfe10d41837f10027a90d7bb75349490018cf72d07
+X = 322f80371bf6e044bc49391d97c1714ab87f990b949bc178cb7c43b7c22d89e1
+Y = 3c15d54a5cc6b9f09de8457e873eb3deb1fceb54b0b295da6050294fae7fd999
+Digest = 85b957d92766235e7c880ac5447cfbe97f3cb499f486d1e43bcb5c2ff9608a1a
+K = 24fc90e1da13f17ef9fe84cc96b9471ed1aaac17e3a4bae33a115df4e5834f18
+R = d7c562370af617b581c84a2468cc8bd50bb1cbf322de41b7887ce07c0e5884ca
+S = b46d9f2d8c4bf83546ff178f1d78937c008d64e8ecc5cbb825cb21d94d670d89
+
+Curve = P-256
+Private = 53a0e8a8fe93db01e7ae94e1a9882a102ebd079b3a535827d583626c272d280d
+X = 1bcec4570e1ec2436596b8ded58f60c3b1ebc6a403bc5543040ba82963057244
+Y = 8af62a4c683f096b28558320737bf83b9959a46ad2521004ef74cf85e67494e1
+Digest = 3360d699222f21840827cf698d7cb635bee57dc80cd7733b682d41b55b666e22
+K = 5d833e8d24cc7a402d7ee7ec852a3587cddeb48358cea71b0bedb8fabe84e0c4
+R = 18caaf7b663507a8bcd992b836dec9dc5703c080af5e51dfa3a9a7c387182604
+S = 77c68928ac3b88d985fb43fb615fb7ff45c18ba5c81af796c613dfa98352d29c
+
+Curve = P-256
+Private = 4af107e8e2194c830ffb712a65511bc9186a133007855b49ab4b3833aefc4a1d
+X = a32e50be3dae2c8ba3f5e4bdae14cf7645420d425ead94036c22dd6c4fc59e00
+Y = d623bf641160c289d6742c6257ae6ba574446dd1d0e74db3aaa80900b78d4ae9
+Digest = c413c4908cd0bc6d8e32001aa103043b2cf5be7fcbd61a5cec9488c3a577ca57
+K = e18f96f84dfa2fd3cdfaec9159d4c338cd54ad314134f0b31e20591fc238d0ab
+R = 8524c5024e2d9a73bde8c72d9129f57873bbad0ed05215a372a84fdbc78f2e68
+S = d18c2caf3b1072f87064ec5e8953f51301cada03469c640244760328eb5a05cb
+
+Curve = P-256
+Private = 78dfaa09f1076850b3e206e477494cddcfb822aaa0128475053592c48ebaf4ab
+X = 8bcfe2a721ca6d753968f564ec4315be4857e28bef1908f61a366b1f03c97479
+Y = 0f67576a30b8e20d4232d8530b52fb4c89cbc589ede291e499ddd15fe870ab96
+Digest = 88fc1e7d849794fc51b135fa135deec0db02b86c3cd8cebdaa79e8689e5b2898
+K = 295544dbb2da3da170741c9b2c6551d40af7ed4e891445f11a02b66a5c258a77
+R = c5a186d72df452015480f7f338970bfe825087f05c0088d95305f87aacc9b254
+S = 84a58f9e9d9e735344b316b1aa1ab5185665b85147dc82d92e969d7bee31ca30
+
+Curve = P-256
+Private = 80e692e3eb9fcd8c7d44e7de9f7a5952686407f90025a1d87e52c7096a62618a
+X = a88bc8430279c8c0400a77d751f26c0abc93e5de4ad9a4166357952fe041e767
+Y = 2d365a1eef25ead579cc9a069b6abc1b16b81c35f18785ce26a10ba6d1381185
+Digest = 41fa8d8b4cd0a5fdf021f4e4829d6d1e996bab6b4a19dcb85585fe76c582d2bc
+K = 7c80fd66d62cc076cef2d030c17c0a69c99611549cb32c4ff662475adbe84b22
+R = 9d0c6afb6df3bced455b459cc21387e14929392664bb8741a3693a1795ca6902
+S = d7f9ddd191f1f412869429209ee3814c75c72fa46a9cccf804a2f5cc0b7e739f
+
+Curve = P-256
+Private = 5e666c0db0214c3b627a8e48541cc84a8b6fd15f300da4dff5d18aec6c55b881
+X = 1bc487570f040dc94196c9befe8ab2b6de77208b1f38bdaae28f9645c4d2bc3a
+Y = ec81602abd8345e71867c8210313737865b8aa186851e1b48eaca140320f5d8f
+Digest = 2d72947c1731543b3d62490866a893952736757746d9bae13e719079299ae192
+K = 2e7625a48874d86c9e467f890aaa7cd6ebdf71c0102bfdcfa24565d6af3fdce9
+R = 2f9e2b4e9f747c657f705bffd124ee178bbc5391c86d056717b140c153570fd9
+S = f5413bfd85949da8d83de83ab0d19b2986613e224d1901d76919de23ccd03199
+
+Curve = P-256
+Private = f73f455271c877c4d5334627e37c278f68d143014b0a05aa62f308b2101c5308
+X = b8188bd68701fc396dab53125d4d28ea33a91daf6d21485f4770f6ea8c565dde
+Y = 423f058810f277f8fe076f6db56e9285a1bf2c2a1dae145095edd9c04970bc4a
+Digest = e138bd577c3729d0e24a98a82478bcc7482499c4cdf734a874f7208ddbc3c116
+K = 62f8665fd6e26b3fa069e85281777a9b1f0dfd2c0b9f54a086d0c109ff9fd615
+R = 1cc628533d0004b2b20e7f4baad0b8bb5e0673db159bbccf92491aef61fc9620
+S = 880e0bbf82a8cf818ed46ba03cf0fc6c898e36fca36cc7fdb1d2db7503634430
+
+Curve = P-256
+Private = b20d705d9bd7c2b8dc60393a5357f632990e599a0975573ac67fd89b49187906
+X = 51f99d2d52d4a6e734484a018b7ca2f895c2929b6754a3a03224d07ae61166ce
+Y = 4737da963c6ef7247fb88d19f9b0c667cac7fe12837fdab88c66f10d3c14cad1
+Digest = 17b03f9f00f6692ccdde485fc63c4530751ef35da6f71336610944b0894fcfb8
+K = 72b656f6b35b9ccbc712c9f1f3b1a14cbbebaec41c4bca8da18f492a062d6f6f
+R = 9886ae46c1415c3bc959e82b760ad760aab66885a84e620aa339fdf102465c42
+S = 2bf3a80bc04faa35ebecc0f4864ac02d349f6f126e0f988501b8d3075409a26c
+
+Curve = P-256
+Private = d4234bebfbc821050341a37e1240efe5e33763cbbb2ef76a1c79e24724e5a5e7
+X = 8fb287f0202ad57ae841aea35f29b2e1d53e196d0ddd9aec24813d64c0922fb7
+Y = 1f6daff1aa2dd2d6d3741623eecb5e7b612997a1039aab2e5cf2de969cfea573
+Digest = c25beae638ff8dcd370e03a6f89c594c55bed1277ee14d83bbb0ef783a0517c7
+K = d926fe10f1bfd9855610f4f5a3d666b1a149344057e35537373372ead8b1a778
+R = 490efd106be11fc365c7467eb89b8d39e15d65175356775deab211163c2504cb
+S = 644300fc0da4d40fb8c6ead510d14f0bd4e1321a469e9c0a581464c7186b7aa7
+
+Curve = P-256
+Private = b58f5211dff440626bb56d0ad483193d606cf21f36d9830543327292f4d25d8c
+X = 68229b48c2fe19d3db034e4c15077eb7471a66031f28a980821873915298ba76
+Y = 303e8ee3742a893f78b810991da697083dd8f11128c47651c27a56740a80c24c
+Digest = 5eb28029ebf3c7025ff2fc2f6de6f62aecf6a72139e1cba5f20d11bbef036a7f
+K = e158bf4a2d19a99149d9cdb879294ccb7aaeae03d75ddd616ef8ae51a6dc1071
+R = e67a9717ccf96841489d6541f4f6adb12d17b59a6bef847b6183b8fcf16a32eb
+S = 9ae6ba6d637706849a6a9fc388cf0232d85c26ea0d1fe7437adb48de58364333
+
+Curve = P-256
+Private = 54c066711cdb061eda07e5275f7e95a9962c6764b84f6f1f3ab5a588e0a2afb1
+X = 0a7dbb8bf50cb605eb2268b081f26d6b08e012f952c4b70a5a1e6e7d46af98bb
+Y = f26dd7d799930062480849962ccf5004edcfd307c044f4e8f667c9baa834eeae
+Digest = 12135386c09e0bf6fd5c454a95bcfe9b3edb25c71e455c73a212405694b29002
+K = 646fe933e96c3b8f9f507498e907fdd201f08478d0202c752a7c2cfebf4d061a
+R = b53ce4da1aa7c0dc77a1896ab716b921499aed78df725b1504aba1597ba0c64b
+S = d7c246dc7ad0e67700c373edcfdd1c0a0495fc954549ad579df6ed1438840851
+
+Curve = P-256
+Private = 34fa4682bf6cb5b16783adcd18f0e6879b92185f76d7c920409f904f522db4b1
+X = 105d22d9c626520faca13e7ced382dcbe93498315f00cc0ac39c4821d0d73737
+Y = 6c47f3cbbfa97dfcebe16270b8c7d5d3a5900b888c42520d751e8faf3b401ef4
+Digest = aea3e069e03c0ff4d6b3fa2235e0053bbedc4c7e40efbc686d4dfb5efba4cfed
+K = a6f463ee72c9492bc792fe98163112837aebd07bab7a84aaed05be64db3086f4
+R = 542c40a18140a6266d6f0286e24e9a7bad7650e72ef0e2131e629c076d962663
+S = 4f7f65305e24a6bbb5cff714ba8f5a2cee5bdc89ba8d75dcbf21966ce38eb66f
+
+Curve = P-256
+Private = b6faf2c8922235c589c27368a3b3e6e2f42eb6073bf9507f19eed0746c79dced
+X = e0e7b99bc62d8dd67883e39ed9fa0657789c5ff556cc1fd8dd1e2a55e9e3f243
+Y = 63fbfd0232b95578075c903a4dbf85ad58f8350516e1ec89b0ee1f5e1362da69
+Digest = d9c83b92fa0979f4a5ddbd8dd22ab9377801c3c31bf50f932ace0d2146e2574da0d5552dbed4b18836280e9f94558ea6
+K = 9980b9cdfcef3ab8e219b9827ed6afdd4dbf20bd927e9cd01f15762703487007
+R = f5087878e212b703578f5c66f434883f3ef414dc23e2e8d8ab6a8d159ed5ad83
+S = 306b4c6c20213707982dffbb30fba99b96e792163dd59dbe606e734328dd7c8a
+
+Curve = P-256
+Private = 118958fd0ff0f0b0ed11d3cf8fa664bc17cdb5fed1f4a8fc52d0b1ae30412181
+X = afda82260c9f42122a3f11c6058839488f6d7977f6f2a263c67d06e27ea2c355
+Y = 0ae2bbdd2207c590332c5bfeb4c8b5b16622134bd4dc55382ae806435468058b
+Digest = 76c8df4563375d34656f2d1dd3445c9d9f0c8da59dc015fa6122237e1a02039998c16b3935e281160923c6e21115d0a9
+K = 23129a99eeda3d99a44a5778a46e8e7568b91c31fb7a8628c5d9820d4bed4a6b
+R = e446600cab1286ebc3bb332012a2f5cc33b0a5ef7291d5a62a84de5969d77946
+S = cf89b12793ee1792eb26283b48fa0bdcb45ae6f6ad4b02564bf786bb97057d5a
+
+Curve = P-256
+Private = 3e647357cd5b754fad0fdb876eaf9b1abd7b60536f383c81ce5745ec80826431
+X = 702b2c94d039e590dd5c8f9736e753cf5824aacf33ee3de74fe1f5f7c858d5ed
+Y = 0c28894e907af99fb0d18c9e98f19ac80dd77abfa4bebe45055c0857b82a0f4d
+Digest = bad1b2c4c35c54eede5d9dee6f6821bb0254395ae6a689ae7289790448ff787ea4e495ea418c0759c51144a74eba3ac9
+K = 9beab7722f0bcb468e5f234e074170a60225255de494108459abdf603c6e8b35
+R = c4021fb7185a07096547af1fb06932e37cf8bd90cf593dea48d48614fa237e5e
+S = 7fb45d09e2172bec8d3e330aa06c43fbb5f625525485234e7714b7f6e92ba8f1
+
+Curve = P-256
+Private = 76c17c2efc99891f3697ba4d71850e5816a1b65562cc39a13da4b6da9051b0fd
+X = d12512e934c367e4c4384dbd010e93416840288a0ba00b299b4e7c0d91578b57
+Y = ebf8835661d9b578f18d14ae4acf9c357c0dc8b7112fc32824a685ed72754e23
+Digest = c248cc5eb23ed0f6f03de308fffed1e5fdd918aef379946d7b66b8924dc38306feb28e85cc5ab5d7a3a0e55087ddecde
+K = 77cffa6f9a73904306f9fcd3f6bbb37f52d71e39931bb4aec28f9b076e436ccf
+R = 4d5a9d95b0f09ce8704b0f457b39059ee606092310df65d3f8ae7a2a424cf232
+S = 7d3c014ca470a73cef1d1da86f2a541148ad542fbccaf9149d1b0b030441a7eb
+
+Curve = P-256
+Private = 67b9dea6a575b5103999efffce29cca688c781782a41129fdecbce76608174de
+X = b4238b029fc0b7d9a5286d8c29b6f3d5a569e9108d44d889cd795c4a385905be
+Y = 8cb3fff8f6cca7187c6a9ad0a2b1d9f40ae01b32a7e8f8c4ca75d71a1fffb309
+Digest = b05d944f6752bfe003526499bb4d8721c0d25a7901999f67519b17665e907cd148b2ff1b451248d292866bcc81b506d9
+K = d02617f26ede3584f0afcfc89554cdfb2ae188c192092fdde3436335fafe43f1
+R = 26fd9147d0c86440689ff2d75569795650140506970791c90ace0924b44f1586
+S = 00a34b00c20a8099df4b0a757cbef8fea1cb3ea7ced5fbf7e987f70b25ee6d4f
+
+Curve = P-256
+Private = ecf644ea9b6c3a04fdfe2de4fdcb55fdcdfcf738c0b3176575fa91515194b566
+X = c3bdc7c795ec94620a2cfff614c13a3390a5e86c892e53a24d3ed22228bc85bf
+Y = 70480fc5cf4aacd73e24618b61b5c56c1ced8c4f1b869580ea538e68c7a61ca3
+Digest = 847325a13b72de5a15cd899ced0920b8543ab26f9d3877fde99c5018efc78ddf14c00f88b06af7971181923aa46624d4
+K = 53291d51f68d9a12d1dcdc58892b2f786cc15f631f16997d2a49bace513557d4
+R = a860c8b286edf973ce4ce4cf6e70dc9bbf3818c36c023a845677a9963705df8b
+S = 5630f986b1c45e36e127dd7932221c4272a8cc6e255e89f0f0ca4ec3a9f76494
+
+Curve = P-256
+Private = 4961485cbc978f8456ec5ac7cfc9f7d9298f99415ecae69c8491b258c029bfee
+X = 8d40bf2299e05d758d421972e81cfb0cce68b949240dc30f315836acc70bef03
+Y = 5674e6f77f8b46f46cca937d83b128dffbe9bd7e0d3d08aa2cbbfdfb16f72c9a
+Digest = fd30608cf408dac5886ca156bdce7f75067e18172af79ca84f8d60d011b8a6b5ea33a92554d1ea34b105d5bd09062d47
+K = 373a825b5a74b7b9e02f8d4d876b577b4c3984168d704ba9f95b19c05ed590af
+R = ef6fb386ad044b63feb7445fa16b10319018e9cea9ef42bca83bdad01992234a
+S = ac1f42f652eb1786e57be01d847c81f7efa072ba566d4583af4f1551a3f76c65
+
+Curve = P-256
+Private = 587907e7f215cf0d2cb2c9e6963d45b6e535ed426c828a6ea2fb637cca4c5cbd
+X = 660da45c413cc9c9526202c16b402af602d30daaa7c342f1e722f15199407f31
+Y = e6f8cbb06913cc718f2d69ba2fb3137f04a41c27c676d1a80fbf30ea3ca46439
+Digest = 9d21e70e88c43cbab056c5fdeb63baa2660ebc44e0d1ef781f8f6bf58b28e3a2c9d5db051c8da3ba34796d8bcc7ba5cb
+K = 6b8eb7c0d8af9456b95dd70561a0e902863e6dfa1c28d0fd4a0509f1c2a647b2
+R = 08fabf9b57de81875bfa7a4118e3e44cfb38ec6a9b2014940207ba3b1c583038
+S = a58d199b1deba7350616230d867b2747a3459421811c291836abee715b8f67b4
+
+Curve = P-256
+Private = 24b1e5676d1a9d6b645a984141a157c124531feeb92d915110aef474b1e27666
+X = b4909a5bdf25f7659f4ef35e4b811429fb2c59126e3dad09100b46aea6ebe7a6
+Y = 760ae015fa6af5c9749c4030fdb5de6e58c6b5b1944829105cf7edf7d3a22cfb
+Digest = 0bc6a254fa0016a5aa608309f9a97cf0c879370bae0b7b460da17c2694e8414db39ec8b5f943167372610fc146dd8b28
+K = 88794923d8943b5dbcc7a7a76503880ff7da632b0883aaa60a9fcc71bf880fd6
+R = 6ec9a340b77fae3c7827fa96d997e92722ff2a928217b6dd3c628f3d49ae4ce6
+S = 637b54bbcfb7e7d8a41ea317fcfca8ad74eb3bb6b778bc7ef9dec009281976f7
+
+Curve = P-256
+Private = bce49c7b03dcdc72393b0a67cf5aa5df870f5aaa6137ada1edc7862e0981ec67
+X = c786d9421d67b72b922cf3def2a25eeb5e73f34543eb50b152e738a98afb0ca5
+Y = 6796271e79e2496f9e74b126b1123a3d067de56b5605d6f51c8f6e1d5bb93aba
+Digest = 12520a7ef4f05f91b9f9a0fba73eddc813413c4d4764dc1c4b773c4afd5cd77b0e7f09d56e5931aec2958407c02774c0
+K = 89e690d78a5e0d2b8ce9f7fcbf34e2605fd9584760fa7729043397612dd21f94
+R = 07e5054c384839584624e8d730454dc27e673c4a90cbf129d88b91250341854d
+S = f7e665b88614d0c5cbb3007cafe713763d81831525971f1747d92e4d1ca263a7
+
+Curve = P-256
+Private = 73188a923bc0b289e81c3db48d826917910f1b957700f8925425c1fb27cabab9
+X = 86662c014ab666ee770723be8da38c5cd299efc6480fc6f8c3603438fa8397b9
+Y = f26b3307a650c3863faaa5f642f3ba1384c3d3a02edd3d48c657c269609cc3fc
+Digest = 4b3a6ea660aac1e87dae5a252ab5588b5292d713f8c146f1a92d7b72f64bc91663c46e2beb33832e92ec0dccdf033f87
+K = ec90584ab3b383b590626f36ed4f5110e49888aec7ae7a9c5ea62dd2dc378666
+R = 13e9ad59112fde3af4163eb5c2400b5e9a602576d5869ac1c569075f08c90ff6
+S = 708ac65ff2b0baaccc6dd954e2a93df46016bd04457636de06798fcc17f02be5
+
+Curve = P-256
+Private = f637d55763fe819541588e0c603f288a693cc66823c6bb7b8e003bd38580ebce
+X = 74a4620c578601475fc169a9b84be613b4a16cb6acab8fd98848a6ec9fbd133d
+Y = 42b9e35d347c107e63bd55f525f915bcf1e3d2b81d002d3c39acf10fc30645a1
+Digest = a357e9fa283e8699373cb7c027e4c86084259f08662fd0fc064e7b2f6a33562fb2a9e938962eda99f43e5e2b012822b8
+K = 4d578f5099636234d9c1d566f1215d5d887ae5d47022be17dbf32a11a03f053b
+R = 113a933ebc4d94ce1cef781e4829df0c493b0685d39fb2048ce01b21c398dbba
+S = 3005bd4ec63dbd04ce9ff0c6246ad65d27fcf62edb2b7e461589f9f0e7446ffd
+
+Curve = P-256
+Private = 2e357d51517ff93b821f895932fddded8347f32596b812308e6f1baf7dd8a47f
+X = 7e4078a1d50c669fb2996dd9bacb0c3ac7ede4f58fa0fa1222e78dbf5d1f4186
+Y = 0014e46e90cc171fbb83ea34c6b78202ea8137a7d926f0169147ed5ae3d6596f
+Digest = 347d91b8295d9321c84ce2a5e1c5257c4ffaf0006d884ff7337d386c63f532db444a873b8047ba373bb3538b5664ab31
+K = be522b0940b9a40d84bf790fe6abdc252877e671f2efa63a33a65a512fc2aa5c
+R = a26b9ad775ac37ff4c7f042cdc4872c5e4e5e800485f488ddfaaed379f468090
+S = f88eae2019bebbba62b453b8ee3472ca5c67c267964cffe0cf2d2933c1723dff
+
+Curve = P-256
+Private = 77d60cacbbac86ab89009403c97289b5900466856887d3e6112af427f7f0f50b
+X = a62032dfdb87e25ed0c70cad20d927c7effeb2638e6c88ddd670f74df16090e5
+Y = 44c5ee2cf740ded468f5d2efe13daa7c5234645a37c073af35330d03a4fed976
+Digest = 46252c7ed042d8b1f691a46b4f6ca5395106871bd413e277a3812beb1757d9fb056a9805aa31376fd60e0ac567265cdd
+K = 06c1e692b045f425a21347ecf72833d0242906c7c1094f805566cdcb1256e394
+R = eb173b51fb0aec318950d097e7fda5c34e529519631c3e2c9b4550b903da417d
+S = ca2c13574bf1b7d56e9dc18315036a31b8bceddf3e2c2902dcb40f0cc9e31b45
+
+Curve = P-256
+Private = 486854e77962117f49e09378de6c9e3b3522fa752b10b2c810bf48db584d7388
+X = 760b5624bd64d19c866e54ccd74ad7f98851afdbc3ddeae3ec2c52a135be9cfa
+Y = feca15ce9350877102eee0f5af18b2fed89dc86b7df0bf7bc2963c1638e36fe8
+Digest = 1ec1470e867e27ab4800998382f623e27fc2a897a497e6a9cb7c3584b42080c65dbe1270dc479a454566653abd402f02
+K = e4f77c6442eca239b01b0254e11a4182782d96f48ab521cc3d1d68df12b5a41a
+R = bdff14e4600309c2c77f79a25963a955b5b500a7b2d34cb172cd6acd52905c7b
+S = b0479cdb3df79923ec36a104a129534c5d59f622be7d613aa04530ad2507d3a2
+
+Curve = P-256
+Private = 9dd0d3a3d514c2a8adb162b81e3adfba3299309f7d2018f607bdb15b1a25f499
+X = 6b738de3398b6ac57b9591f9d7985dd4f32137ad3460dcf8970c1390cb9eaf8d
+Y = 83bc61e26d2bbbd3cf2d2ab445a2bc4ab5dde41f4a13078fd1d3cc36ab596d57
+Digest = a59ca4dd2b0347f4f2702a8962878a206775fd91047040be60463119f02aa829b7360b940b2785395406c280375c5d90ee655e51d4120df256b9a6287161c7fc
+K = 9106192170ccb3c64684d48287bb81bbed51b40d503462c900e5c7aae43e380a
+R = 275fa760878b4dc05e9d157fedfd8e9b1c9c861222a712748cb4b7754c043fb1
+S = 699d906bb8435a05345af3b37e3b357786939e94caae257852f0503adb1e0f7e
+
+Curve = P-256
+Private = f9bf909b7973bf0e3dad0e43dcb2d7fa8bda49dbe6e5357f8f0e2bd119be30e6
+X = f2a6674d4e86152a527199bed293fa63acde1b4d8a92b62e552210ba45c38792
+Y = c72565c24f0eee6a094af341ddd8579747b865f91c8ed5b44cda8a19cc93776f
+Digest = 9e359350e87e7573ad9894cd4aad6c6202a58e9938d098dbf65650fc6f04fce3664b9adb234bfa0821788223a306daaa3e62bd46b19d7eb7a725bc5bce8998f3
+K = e547791f7185850f03d0c58419648f65b9d29cdc22ed1de2a64280220cfcafba
+R = 4782903d2aaf8b190dab5cae2223388d2d8bd845b3875d37485c54e1ded1d3d8
+S = dfb40e406bfa074f0bf832771b2b9f186e2211f0bca279644a0ca8559acf39da
+
+Curve = P-256
+Private = 724567d21ef682dfc6dc4d46853880cfa86fe6fea0efd51fac456f03c3d36ead
+X = 70b877b5e365fcf08140b1eca119baba662879f38e059d074a2cb60b03ea5d39
+Y = 5f56f94d591df40b9f3b8763ac4b3dbe622c956d5bd0c55658b6f46fa3deb201
+Digest = ff5e80ccbb51b75742a1f0e632b4c6cd119692f2aca337378f7eb2f3b17fc3d912828b7e1655d2263d8757715eea31493aa89dfe1db143a8fa13f89a00379938
+K = 79d6c967ed23c763ece9ca4b026218004c84dc2d4ccc86cf05c5d0f791f6279b
+R = 2ba2ea2d316f8937f184ad3028e364574d20a202e4e7513d7af57ac2456804d1
+S = 64fe94968d18c5967c799e0349041b9e40e6c6c92ebb475e80dd82f51cf07320
+
+Curve = P-256
+Private = 29c5d54d7d1f099d50f949bfce8d6073dae059c5a19cc70834722f18a7199edd
+X = 3088d4f45d274cc5f418c8ecc4cbcf96be87491f420250f8cbc01cdf2503ec47
+Y = 634db48198129237ed068c88ff5809f6211921a6258f548f4b64dd125921b78b
+Digest = e9518ad1c62d686b9df1f5ae1f6797d8c5944a65fcf2244b763f47b9bc5db8ec360cbd17180e6d24678bc36a1535276733bab7817610399ef6257ca43361dfa0
+K = 0508ad7774908b5705895fda5c3b7a3032bf85dab7232bf981177019f3d76460
+R = acd9f3b63626c5f32103e90e1dd1695907b1904aa9b14f2132caef331321971b
+S = 15c04a8bd6c13ed5e9961814b2f406f064670153e4d5465dcef63c1d9dd52a87
+
+Curve = P-256
+Private = 0d8095da1abba06b0d349c226511f642dabbf1043ad41baa4e14297afe8a3117
+X = 75a45758ced45ecf55f755cb56ca2601d794ebeaeb2e6107fe2fc443f580e23c
+Y = 5303d47d5a75ec821d51a2ee7548448208c699eca0cd89810ffc1aa4faf81ead
+Digest = 9fd9a5f9b73f6d01894ceaf8a1e0327a0cac0dbc30153201bcccf09b6756e2f89198781e80a7ff5119cc2bb4402c731379f5ab5eda9264e3fe88b4b528e16598
+K = 5165c54def4026ab648f7768c4f1488bcb183f6db7ffe02c7022a529a116482a
+R = ebc85fc4176b446b3384ccc62fc2526b45665561a0e7e9404ac376c90e450b59
+S = 8b2c09428e62c5109d17ed0cf8f9fd7c370d018a2a73f701effc9b17d04852c6
+
+Curve = P-256
+Private = 52fe57da3427b1a75cb816f61c4e8e0e0551b94c01382b1a80837940ed579e61
+X = 2177e20a2092a46667debdcc21e7e45d6da72f124adecbc5ada6a7bcc7b401d5
+Y = 550e468f2626070a080afeeb98edd75a721eb773c8e62149f3e903cf9c4d7b61
+Digest = bfc07b9a8a8941b99ac47d607356e5b68d7534fb3faccfbe97751397af359d31fe239179a1d856ffac49a9738e888f599123ee96ae202fb93b897e26bc83202e
+K = 0464fe9674b01ff5bd8be21af3399fad66f90ad30f4e8ee6e2eb9bcccfd5185c
+R = f8250f073f34034c1cde58f69a85e2f5a030703ebdd4dbfb98d3b3690db7d114
+S = a9e83e05f1d6e0fef782f186bedf43684c825ac480174d48b0e4d31505e27498
+
+Curve = P-256
+Private = 003d91611445919f59bfe3ca71fe0bfdeb0e39a7195e83ac03a37c7eceef0df2
+X = 7b9c592f61aae0555855d0b9ebb6fd00fb6746e8842e2523565c858630b9ba00
+Y = d35b2e168b1875bbc563bea5e8d63c4e38957c774a65e762959a349eaf263ba0
+Digest = a051dcee66f456d9786785444cee2a3a342a8e27a5ebdf0e91553a0d257eea11af3a7df7e9310b46d95021a1880cd3f064c73447d92a31bacdb889f1e1390f49
+K = ef9df291ea27a4b45708f7608723c27d7d56b7df0599a54bc2c2fabbff373b40
+R = 66d057fd39958b0e4932bacd70a1769bbadcb62e4470937b45497a3d4500fabb
+S = 6c853b889e18b5a49ee54b54dd1aaedfdd642e30eba171c5cab677f0df9e7318
+
+Curve = P-256
+Private = 48f13d393899cd835c4193670ec62f28e4c4903e0bbe5817bf0996831a720bb7
+X = 82a1a96f4648393c5e42633ecdeb1d8245c78c5ea236b5bab460dedcc8924bc0
+Y = e8cbf03c34b5154f876de19f3bb6fd43cd2eabf6e7c95467bcfa8c8fc42d76fd
+Digest = e1a00e6e38599d7eba1f1a8a6c7337e4dcbdd4f436f47c57d17ef85829f7e266b6bff67a001598db6b9ac032ad160d6f928f8724d2f10928cf953bc76c3fd2fb
+K = efed736e627899fea944007eea39a4a63c0c2e26491cd12adb546be3e5c68f7d
+R = cf7fc24bdaa09ac0cca8497e13298b961380668613c7493954048c06385a7044
+S = f38b1c8306cf82ab76ee3a772b14416b49993fe11f986e9b0f0593c52ec91525
+
+Curve = P-256
+Private = 95c99cf9ec26480275f23de419e41bb779590f0eab5cf9095d37dd70cb75e870
+X = 42c292b0fbcc9f457ae361d940a9d45ad9427431a105a6e5cd90a345fe3507f7
+Y = 313b08fd2fa351908b3178051ee782cc62b9954ad95d4119aa564900f8ade70c
+Digest = bdcf1926e90c980373954c67d3c3c06ccb1a5076957673f12ddf23fa0cce7b3dc3ec2aec143a1ba58094e3da45e2b160092e1d943cf8f22fad35f8348575a0cf
+K = 4c08dd0f8b72ae9c674e1e448d4e2afe3a1ee69927fa23bbff3716f0b99553b7
+R = f2bc35eb1b8488b9e8d4a1dbb200e1abcb855458e1557dc1bf988278a174eb3b
+S = ed9a2ec043a1d578e8eba6f57217976310e8674385ad2da08d6146c629de1cd9
+
+Curve = P-256
+Private = e15e835d0e2217bc7c6f05a498f20af1cd56f2f165c23d225eb3360aa2c5cbcf
+X = 89dd22052ec3ab4840206a62f2270c21e7836d1a9109a3407dd0974c7802b9ae
+Y = e91609ba35c7008b080c77a9068d97a14ca77b97299e74945217672b2fd5faf0
+Digest = da606bb1d0d25dd18a9c29096042e65e6b73086b30509962ea1aa75f25b74653c03a66620cba446f442765f28d7c55a5ff4f9693a6c7ce18e1196c25c12da48d
+K = c9f621441c235fc47ec34eef4c08625df1ec74918e1f86075b753f2589f4c60b
+R = a70d1a2d555d599bfb8c9b1f0d43725341151d17a8d0845fa56f3563703528a7
+S = 4e05c45adf41783e394a5312f86e66871c4be4896948c85966879d5c66d54b37
+
+Curve = P-256
+Private = 808c08c0d77423a6feaaffc8f98a2948f17726e67c15eeae4e672edbe388f98c
+X = b0c0ad5e1f6001d8e9018ec611b2e3b91923e69fa6c98690ab644d650f640c42
+Y = 610539c0b9ed21ac0a2f27527c1a61d9b47cbf033187b1a6ada006eb5b2662ed
+Digest = efdb1d2143ecf0447a68e8156a7443897a56b31b4c0cfe499511a4a3ff6f32ba25515b3a20296a10d23378a24fb7de8c2ce606a7d93a9bd72aef3a34d1ff6401
+K = 1f6d4a905c761a53d54c362976717d0d7fc94d222bb5489e4830080a1a67535d
+R = 83404dcf8320baf206381800071e6a75160342d19743b4f176960d669dd03d07
+S = 3f75dcf102008b2989f81683ae45e9f1d4b67a6ef6fd5c8af44828af80e1cfb5
+
+Curve = P-256
+Private = f7c6315f0081acd8f09c7a2c3ec1b7ece20180b0a6365a27dcd8f71b729558f9
+X = 250f7112d381c1751860045d9bcaf20dbeb25a001431f96ac6f19109362ffebb
+Y = 49fba9efe73546135a5a31ab3753e247034741ce839d3d94bd73936c4a17e4aa
+Digest = eeb09b1f4a74744909774bfe707977e5234db27026873fc7b5496e37d363ff82d5a1dd6fa6c97717aa0828a6f6325a2b7970e5d836ddfb63bf47b09f136eb9da
+K = 68c299be2c0c6d52d208d5d1a9e0ffa2af19b4833271404e5876e0aa93987866
+R = 7b195e92d2ba95911cda7570607e112d02a1c847ddaa33924734b51f5d81adab
+S = 10d9f206755cef70ab5143ac43f3f8d38aea2644f31d52eaf3b472ee816e11e5
+
+Curve = P-256
+Private = f547735a9409386dbff719ce2dae03c50cb437d6b30cc7fa3ea20d9aec17e5a5
+X = 4ca87c5845fb04c2f76ae3273073b0523e356a445e4e95737260eba9e2d021db
+Y = 0f86475d07f82655320fdf2cd8db23b21905b1b1f2f9c48e2df87e24119c4880
+Digest = 8cd8e7876555a7393128336880c8002136e1008814a691528111220fd14158b7ff822226c67390739db56b368cf69cecc4cc147220be3d3ce587c8ad75b0f55a
+K = 91bd7d97f7ed3253cedefc144771bb8acbbda6eb24f9d752bbe1dd018e1384c7
+R = 008c1755d3df81e64e25270dbaa9396641556df7ffc7ac9add6739c382705397
+S = 77df443c729b039aded5b516b1077fecdd9986402d2c4b01734ba91e055e87fc
+
+Curve = P-256
+Private = 26a1aa4b927a516b661986895aff58f40b78cc5d0c767eda7eaa3dbb835b5628
+X = 28afa3b0f81a0e95ad302f487a9b679fcdef8d3f40236ec4d4dbf4bb0cbba8b2
+Y = bb4ac1be8405cbae8a553fbc28e29e2e689fabe7def26d653a1dafc023f3cecf
+Digest = 7a951d7de2e3552d16912a1d4381f047577f9fd7a8f55dc8ebfb5eac9c859ab8771e222bf56d3330201b82751d0aa5b6c21f42ada05db9955d46f62d530723e1
+K = f98e1933c7fad4acbe94d95c1b013e1d6931fa8f67e6dbb677b564ef7c3e56ce
+R = 15a9a5412d6a03edd71b84c121ce9a94cdd166e40da9ce4d79f1afff6a395a53
+S = 86bbc2b6c63bad706ec0b093578e3f064736ec69c0dba59b9e3e7f73762a4dc3
+
+Curve = P-256
+Private = 6a5ca39aae2d45aa331f18a8598a3f2db32781f7c92efd4f64ee3bbe0c4c4e49
+X = c62cc4a39ace01006ad48cf49a3e71466955bbeeca5d318d672695df926b3aa4
+Y = c85ccf517bf2ebd9ad6a9e99254def0d74d1d2fd611e328b4a3988d4f045fe6f
+Digest = 4cb0debbdb572d89e2e46dcc6c2c63ef032792683032ce965b3e7fa79e3282039a705acbcc7bd07057a88b1e65852707934f10a67710ebefaa865201dfa6d4ff
+K = dac00c462bc85bf39c31b5e01df33e2ec1569e6efcb334bf18f0951992ac6160
+R = 6e7ff8ec7a5c48e0877224a9fa8481283de45fcbee23b4c252b0c622442c26ad
+S = 3dfac320b9c873318117da6bd856000a392b815659e5aa2a6a1852ccb2501df3
+
+Curve = P-384
+Private = 0af857beff08046f23b03c4299eda86490393bde88e4f74348886b200555276b93b37d4f6fdec17c0ea581a30c59c727
+X = 00ea9d109dbaa3900461a9236453952b1f1c2a5aa12f6d500ac774acdff84ab7cb71a0f91bcd55aaa57cb8b4fbb3087d
+Y = 0fc0e3116c9e94be583b02b21b1eb168d8facf3955279360cbcd86e04ee50751054cfaebcf542538ac113d56ccc38b3e
+Digest = 5e3b235f5a8037f7556331ed6e9b503fd9f4d6e7d5851d8716780e00
+K = e2f0ce83c5bbef3a6eccd1744f893bb52952475d2531a2854a88ff0aa9b12c65961e2e517fb334ef40e0c0d7a31ed5f5
+R = c36e5f0d3de71411e6e519f63e0f56cff432330a04fefef2993fdb56343e49f2f7db5fcab7728acc1e33d4692553c02e
+S = 0d4064399d58cd771ab9420d438757f5936c3808e97081e457bc862a0c905295dca60ee94f4537591c6c7d217453909b
+
+Curve = P-384
+Private = 047dd5baab23f439ec23b58b7e6ff4cc37813cccb4ea73bb2308e6b82b3170edfe0e131eca50841bf1b686e651c57246
+X = de92ff09af2950854a70f2178d2ed50cc7042a7188301a1ea81d9629ad3c29795cb7f0d56630a401e4d6e5bed0068d1e
+Y = 6135adbd8624130735e64e65ecbd43770dcc12b28e737b5ed033666f34c918eb5589508e4a13b9243374a118a628dd0b
+Digest = 871afe65a30654d09a9bd33767cb4c581a8c5a534c9cdc5801821e89
+K = f3922351d14f1e5af84faab12fe57ded30f185afe5547aeb3061104740ecc42a8df0c27f3877b4d855642b78938c4e05
+R = 38e181870cb797c1f4e6598cfd032add1cb60447d33473038d06df73919f844eddd16f40f911075f8a4bacc0d924e684
+S = a58dd1ca18aa31277de66c30c3bb7a14b53705ce6c547ed2cb0e336f63c42809422efffcc722d1155f2254330a02b278
+
+Curve = P-384
+Private = 54ba9c740535574cebc41ca5dc950629674ee94730353ac521aafd1c342d3f8ac52046ed804264e1440d7fe409c45c83
+X = 3db95ded500b2506b627270bac75688dd7d44f47029adeff99397ab4b6329a38dbb278a0fc58fe4914e6ae31721a6875
+Y = 049288341553a9ac3dc2d9e18e7a92c43dd3c25ca866f0cb4c68127bef6b0e4ba85713d27d45c7d0dc57e5782a6bf733
+Digest = 31113fbe2375b059be766f538b09bf18ca8ec6c38442847e809fe25a
+K = 04324bd078807f6b18507a93ee60da02031717217ee5ce569750737be912be72da087ac00f50e13fdf7249a6ae33f73e
+R = b2752aa7abc1e5a29421c9c76620bcc3049ecc97e6bc39fcca126f505a9a1bfae3bde89fb751a1aa7b66fa8db3891ef0
+S = f1c69e6d818ca7ae3a477049b46420cebd910c0a9a477fd1a67a38d628d6edaac123aebfca67c53a5c80fe454dba7a9d
+
+Curve = P-384
+Private = dabe87bbe95499bac23bc83c8b7307fe04be198f00059e2bf67c9611feaffb2c8f274f6aa50eb99c3074186d8067d659
+X = c2aa0a695125279705917e02a4f258cade4c3ff9140a071414babf87764f426f7f36ffda9d5f3394375d24864235476f
+Y = 8f9808da0ce0227cf453f9e456f557db9752e23b45cce4baad5fee3844ddd7e1112bcec01ea9d67c7a76f3535bd0cb58
+Digest = 279d65e738a347fd9aa6890e497077ad9e90043868bdcb5ab09e90cd
+K = 65a0305854033cbc6fe3ca139c40ca354d45801ecb59f4a923c251dc6b25d12d452d99b5d6711fdb5efac812aa464cc4
+R = c7fc32997d17ac79baf5789e4503f5f1a8863872bc350a91f12dd3ef8cf78c254e829217809e8e00b6b8d4d85be3f1fd
+S = 1422e1838a22496df93486bce1142961dbd8478ae844b8dda54e210afdae0d9e930d587c91bb600b0bde7237186d94e6
+
+Curve = P-384
+Private = df43107a1deb24d02e31d479087bd669e2bc3e50f1f44b7db9484a7143cdca6a3391bddfea72dc940dbce8ec5efbd718
+X = 76bd4be5d520471162cb5c36f80038301b325f845d9642204a84d78b3e721098932827bf872bde0a9f86383953667d29
+Y = 415116b8b878f896a5aa4dbbdc21076f27135d8bbcaaca02489ef639d742bd63f377da0c8e8ab36ff19b4a7cc5d4ceb4
+Digest = 21cd3764d8b28d8c70eea318bba06a8cc2b359e59a0782d7f1c659a2
+K = 798abad5a30d1805794540057388ee05e2422901c6335f985b9d4447b3ef75524751abfeab6409ad6bf77d4ae3014558
+R = 98744e5c6742fa5118a74a70db4957647a3cc12add4e876b45974a6a8707809f871daadbfc0b865e01624f706b65f10c
+S = 9e256e8da8eff5a0c83baaa1ef4f7be798eba9543bf97adb0fff8719f5406ea1207a0cf703d99aa8f02169724b492273
+
+Curve = P-384
+Private = ea7a563ba2a7f5ab69973dca1f1a0d1572f0c59817cd3b62ad356c2099e2cdca1c553323563f9dfbb333b126d84abc7f
+X = cf4717c5f5de668b785f06bdc9845df5a09e4edd83f4669756407cbb60807305c632bc49f818f4a84b194369aa07736f
+Y = 7391e4982af8a2218f704f627d01f0508bfc8304992a2d598a420bf2eb519f33bd7caf79380793733b3dba0cc5e2b9d8
+Digest = dae4b61e1cbc5c2846b3b698656ca1acbd262a0fbe492f810fac6b39
+K = 7b9606b3df7b2a340dbc68d9754de0734e1faeb5a0135578a97628d948702235c60b20c8002c8fcf906783e1b389e754
+R = 0d680010bed373287f9767955b5d2850e150b6713b49e453eb280148e45230c853d99ea2d2f8fcbd3ddcba19aeec0af1
+S = 64329763a930ab5452afdb0557fef16ff71810d6343dfc9c6ae18905c3d274db6554cdc69d6078a1ca03284474a94f30
+
+Curve = P-384
+Private = 4cc70cb35b3ddeb0df53a6bd7bd05f8ff4392a2db7344f2d443761484b3a468a4ee3d1a8b27113d57283fd18b05f7829
+X = 40e1fe21df34bb85a642a0abe819ebd128f7e39b84d8dcc4a9a599b372fb9588da1484600ec28b1297bb685f9ae77831
+Y = f3aa69ada57879fdcbe8df19cefabc308add7d03b17b1fac2f7783fece6a8dfe20bc36f518692677d96e3f730a67a671
+Digest = 1e7ca1523ce2b48143a9665843b602d617441d1b43142631de2088cf
+K = 8eda401d98f5688c34d8dbebcd3991c87c0442b0379154eaa2e5287dabe9a9e34cfc1305d11ff68781df25d5611b331d
+R = ff2d772786e159448bba26afd8c3281941a4cb0c56fec6f5cccb4c292c4ee0f7af9bd39bbe2d88148732585e104fdb30
+S = 07a1d890770daa949a17797dca7af3e8163da981ec330c03d63d1a8312c152be6a718163205ffa08da7dcc163ba261f4
+
+Curve = P-384
+Private = 366d15e4cd7605c71560a418bd0f382fd7cd7ad3090ff1b2dfbed74336166a905e1b760cf0bccee7a0e66c5ebfb831f1
+X = a143f277ab36a10b645ff6c58241ea67ffdc8acf12d60973068390f06b4d8f4d773b10c1ebf6889b1cfa73ebb90f6ca1
+Y = 7a17cad29bb507b309021f6f92cb5c10ba535f4a3e317fcc68cfd02d3ccd269f465169c73d30ff308f5350d881b08aec
+Digest = 505dff744fd26f08990ef6c68e80b5c1f1bfb328203a8a6efd444e02
+K = dbe545f920bc3d704c43d834bab21e40df12ec9e16a619a3e6b3f08760c26aae6e4fd91fad00f745194794b74bb1baee
+R = cdc39b12bba30da66fe9554713c05880ddc27afa4d2d151440f124c351fb9496dc95046516b0921083347d64369846ac
+S = 797d0344e49f9ba87a187c50f664e5015d449e346b1a7bd9427c5be559fc58173651880d5aadf053f81899d3368d6181
+
+Curve = P-384
+Private = e357d869857a52a06e1ece5593d16407022354780eb9a7cb8575cef327f877d22322c006b3c8c11e3d7d296a708bdb6d
+X = ce9a2185a68d6094aa5849a6efe78b349946f7380f0c79aa9664246cfcc71a879e90ad78a0474f58644c6a208168150e
+Y = 8354fa47673cb3e07d446521345706c5515584b2602f921c3b9c44dded9e2c3f90ce47adb36d7e5f9f95a8c5ad8af397
+Digest = b972526301f2c5d689205193c9fc73fb0cddc24ed6ff32e7b5fd6f6e
+K = 1e77367ac4e10924854d135ad2f2507f39e2bafdbce33ff256bcbe9a7329b8d27185218bcc3550aafbe3390e84c77292
+R = df3182d49ad70959fb0c95bc7312750ce70fc87f1a328d39d9b29ac05d31305ce7209d6c24d13225d9567b489f7a187b
+S = d812b05abab0e96de13291e1f0da6479444ed5cd9d959b76f6cb43d394769035364f7c831a104dc7b5bd9b4a8e64df64
+
+Curve = P-384
+Private = 745a18db47324a3710b993d115b2834339315e84e7006eafd889fb49bd3cc5a8b50c90526e65e6c53bddd2916d14bead
+X = f692578c6f77531210aef55c9e004ce3b66cf268c6900dde31a8bbb76e7562e3fb76242de34ca330d2501030aa119466
+Y = 40965833b28de926c46de060aa25beaeda98f8415a6b1e3564aa77870cf4c89bd4fde92c8f5d9bf0eb41721586859d8e
+Digest = 0659e2e64a794837b070ce3a664836d0157880e496f1e9b8c51fc7e0
+K = 11b9b36720abcac084efdb44c9f5b7d039e3250cb1e9c47850189ba3cfc1489d858b2a44df357772b61d919c7e729c0f
+R = 02b252c99820cf50e6ce060ab55bd4f682276e29b4ae4197417432e6a7bfb8cf0bac89dfe105456af805d822cee77696
+S = 8e248bbf7d7028d63177e565c9d1666ee5be4d1ffbfffc9c7814b0cd38f74b98f3f2cd59be42b9f132bfe5ee789cd96c
+
+Curve = P-384
+Private = 93f20963ea5011ff4f26481e359309e634195f6289134087bd2e83eee008c962780a679784ee7ac6acda03d663ed27e0
+X = 0edcde3533ea019e18f1a3cd97b7962e8823dda36c389f8f9287549f796d11376392b8a01c7a80f127a8f75795e04f54
+Y = 63d7c458dccfc02f5148d755d59f9bbc8e3c3ea34908777928440747795955741296abcdd5386676419ed8049fedb489
+Digest = 6a29c05caf892d0b0d339eea5c58ec54f59a66da25051bfc01fef680
+K = 3ad308faf04c42ee5ac69d36bc0aa9a96aacf55ea0f27dac4f52e088f023d206340a6324874ffad169ff80624de24c96
+R = 209b72f9aae72c4339813573c3a8408a9e0be641ca863d81d9d14c48d0bf4cd44a1a7985cff07b5d68f3f9478475645b
+S = f6292e599b22a76eda95393cf59f4745fa6c472effd1f781879ad9a4437a98080b0b07dadad0c249631c682d2836a977
+
+Curve = P-384
+Private = f175e6ac42fd48ec9d652c10707c039c67c4cc61d8c45a373dcda6e4ca6c53e947e49c24e01b48e7cdf92edfe6d316a1
+X = a40c64f595491ce15790a5a87fbe64c1800247b42acd08fe5257700719f46afc8acce0e4ede0517a312092d5e3d089cd
+Y = d565df9dc2f381cc0c5d84f382a43a98018524c0b4708a44b3e2817f9719f29fbf9c15803591ed9b4790c5adaba9f433
+Digest = 3978516bf80bf5bcd4acd93497d3f56d699f089207b1715b9733421b
+K = 812dcaa6d4f9a43ccc553288065d13761581485aa903a500a690ccafbd330ba4818c977b98c4bb57f8a182a1afacfae9
+R = d000f18d3e4c162ff0d16f662e6703e7a6f5bff7a333ed266fa4f44c752415946c34945c342c20f739677186b1d80ab3
+S = ae7f1271c89e0aaa238710d039ea73a69110cc28fcf426f2fe6754b63a59e417fa84f903cf7dccb5468b43ff083bbfd5
+
+Curve = P-384
+Private = 46c4f0b228b28aaa0ec8cfdf1d0ed3408b7ae049312fb9eaf5f3892720e68684cc8ad29844a3dc9d110edf6916dfb8bb
+X = 13ddec844731b7e30c467451df08ca11d6c581cb64abd8a257671cffd26f5ccad4df7b9ee8924047a88a5d2d7567609c
+Y = d74ca94f590fd1d13e190cc1e03c3da6c3faab15c7dda034af3deefee8aeec3628fa8b1978c54cfcd071baa319a46ec0
+Digest = 6833365d547d47628755680dbe3a946feca5bb0a07929d88ca894923
+K = 2a9dd520207c40a379cd4036adef9ee60fa8bc8c0d39b3ad91850ac93fd543f218b1688581f23481a090b0e4c73792ac
+R = 94e08cca20fe3866f643f53ec65faf3f2b4d80cd9bcc8ff8f88bb28da9eada324fc2d048908dd3d08a9e0ebb547731bc
+S = 8e6f82c4d3069b14f4c844b4ca133a9503493265c9f77a7d4775eda67de76798a23dd7ea48e0ac3c337dd62bf058319d
+
+Curve = P-384
+Private = 1d7b71ef01d0d33a8513a3aed3cabb83829589c8021087a740ca65b570777089be721a61172b874a22a1f81aef3f8bb6
+X = 8d2721370df8f097d5a69396249a315f6037dc7045b3da11eacae6d43036f779d5de7053d101768b42cc2b1283a3aaea
+Y = a046039ae662141f9954d278183eaa2e03917fe58583e32d344074d59d60caa5b0949c53066525d5cca923e2f201502e
+Digest = b3b149ce5ceb3df24bcc080484fea7170b5a91e3c36dfb86a5ccb6f8
+K = d1b25ad25581cad17e96f1d302251681fee5b2efbb71c3c15ff035b2145d015d18e0e52dc3187ab5a560277b3a3929b0
+R = d836f52b14c7391744868daa2d5cf27eb9380b9b6176195573d5b04842e9f2fc3794d6cf877feafee63d11b05f6a6bee
+S = 8b89042fef2c04d4bd6c9d66a06a010514321d623a5f8d57ba5ac3686872eaabca9e0ba2d058ae7028e870acf03ca32d
+
+Curve = P-384
+Private = cf53bdd4c91fe5aa4d82f116bd68153c907963fa3c9d478c9462bb03c79039493a8eaeb855773f2df37e4e551d509dcd
+X = 3a65b26c08102b44838f8c2327ea080daf1e4fc45bb279ce03af13a2f9575f0fff9e2e4423a58594ce95d1e710b590ce
+Y = fe9dcbcb2ec6e8bd8ed3af3ff0aa619e900cc8bab3f50f6e5f79fac09164fb6a2077cc4f1fed3e9ec6899e91db329bf3
+Digest = 0baa03848341fbe4df9caa8b4d52a47a174cf485659ea7044b9265f3
+K = df31908c9289d1fe25e055df199591b23e266433ab8657cc82cb3bca96b88720e229f8dfd42d8b78af7db69342430bca
+R = 6770eea9369d6718e60dd0b91aee845ff7ed7e0fcc91675f56d32e5227fd3a4612bbcb1556fe94a989b9e3bcc25bb20e
+S = c43072f706c98126d06a82b04251e3ecb0ba66c4bb6cd7c025919b9cc6019cdc635256d2a7fa017b806b1e88649d2c0d
+
+Curve = P-384
+Private = c602bc74a34592c311a6569661e0832c84f7207274676cc42a89f058162630184b52f0d99b855a7783c987476d7f9e6b
+X = 0400193b21f07cd059826e9453d3e96dd145041c97d49ff6b7047f86bb0b0439e909274cb9c282bfab88674c0765bc75
+Y = f70d89c52acbc70468d2c5ae75c76d7f69b76af62dcf95e99eba5dd11adf8f42ec9a425b0c5ec98e2f234a926b82a147
+Digest = bbbd0a5f645d3fda10e288d172b299455f9dff00e0fbc2833e18cd017d7f3ed1
+K = c10b5c25c4683d0b7827d0d88697cdc0932496b5299b798c0dd1e7af6cc757ccb30fcd3d36ead4a804877e24f3a32443
+R = b11db00cdaf53286d4483f38cd02785948477ed7ebc2ad609054551da0ab0359978c61851788aa2ec3267946d440e878
+S = 16007873c5b0604ce68112a8fee973e8e2b6e3319c683a762ff5065a076512d7c98b27e74b7887671048ac027df8cbf2
+
+Curve = P-384
+Private = 0287f62a5aa8432ff5e95618ec8f9ccaa870dde99c30b51b7673378efe4ccac598f4bbebbfd8993f9abb747b6ad638b9
+X = b36418a3014074ec9bbcc6a4b2367a4fb464cca7ec0a324cb68670d5c5e03e7a7eb07da117c5ea50b665ab62bd02a491
+Y = 4ea299c30e7d76e2c5905babada2d3bb4ee5eb35a5a23605cdb0d5133471a53eb9e6758e49105a4eaf29d2267ba84ef2
+Digest = e4cb4f2f94793f4a471a1e1de49b2c6ceb5825c5d02c69a7fe122eebda7b28b9
+K = 935eeab3edeb281fbd4eead0d9c0babd4b10ff18a31663ee9de3bfa9ae8f9d266441158ea31c889ded9b3c592da77fd7
+R = 738f9cb28f3b991335ef17b62559255faf75cad370a222464a492e27bb173c7f16b22100ada6b695875c7e4b1a28f158
+S = bc998c30e1491cd5d60dc7d1c38333165efe036b2a78db9b8f0e85ee68619cfba654e11ae5ca5ee5a87099c27cf22442
+
+Curve = P-384
+Private = d44d3108873977036c9b97e03f914cba2f5775b68c425d550995574081191da764acc50196f6d2508082a150af5cd41f
+X = c703835d723c85c643260379d8445b0c816fe9534351921e14a8e147fe140ec7b0c4d704f8dc66a232b2333b28f03dee
+Y = c5d0bb054053fd86c26f147c4966757aa04b00513a02d427b8d06c16055c607955efdc518d338abfe7927c195dc28588
+Digest = a22a3d3da784a68d37ae5aaca8ef28dc1ceefc8e530431e455dd2bb2ed969684
+K = c80f63e080650c8a21e4f63a62ec909adfb7d877f365d11ee1cb260baf112eb4730c161c1d99dba98fc0d5bbd00dc97d
+R = 81de2810cde421997013513951a3d537c51a013110d6dbb29251410bcb5ba001a9686b8490f1e581e282fd2ed0974b22
+S = 9cab0bbaffe91c7677ec3dd1f17060211a3cc0be574cbca064aa8c4b66ba6e64f3d80e83da895042ca32d311c388d950
+
+Curve = P-384
+Private = d5b72cbb6ec68aca46b9c27ad992afd8ffa02cb3067b234fcfa6e272e3b31be760695ff7df988b57663057ab19dd65e3
+X = 135a6542612f1468d8a4d01ff1914e532b1dd64d3627db9d403dc325651d3f82b0f6f0fd1dbdeca2be967c4fb3793b5f
+Y = cbbd40f6d3a38d0dfb64582ff4789d7b268241bc0c36de2884bccfaeeff3b7b2b46a30bb35719804e0d11124b4e7f480
+Digest = 1241e0219c19b1fe70919f4f5738edf7cdf4bd51905273b030c2f522abf11823
+K = 9da6de7c87c101b68db64fea40d97f8ad974ceb88224c6796c690cbf61b8bd8eede8470b3caf6e6106b66cf3f0eebd55
+R = 17840911ecdf6ae0428b2634f442163c2c11b8dbf0cc7a5596fbe4d33e3e52f9d99e99ad169867b1f39e89c9180cedc2
+S = dd7ed67e480866d0474379ea4afff72870746f4feef2153be42f13bf472b1613d7faa5c0abb7f7464070f94d7cf3f234
+
+Curve = P-384
+Private = 218ee54a71ef2ccf012aca231fee28a2c665fc395ff5cd20bde9b8df598c282664abf9159c5b3923132983f945056d93
+X = 01989ff07a7a452d8084937448be946bfedac4049cea34b3db6f7c91d07d69e926cce0af3d6e88855a28120cf3dba8df
+Y = eb064e029d7539d4b301aabafe8de8870162deffe6383bc63cc005add6ee1d5ced4a5761219c60cd58ad5b2a7c74aaa9
+Digest = e2e52fe49dd358e95fdaf1fc6f7f4bdc638ee8f65a410890eb290342ca53f6de
+K = c5d39b436d851d94691f5f4aa9ef447f7989d984f279ae8b091aef5449ac062bcc0567740f914624ad5b99fc32f9af0b
+R = 07d5b1b12877e8cb5e0aa5e71eeeb17bf0aa203064c7e98b3a1798a74dc9717252dc47c7f06aaf1d5fe15b868323bbb9
+S = 69428cf101a7af5d08161a9fd7af212e02e33b6062aebdce4c96bf3a0684b5394cb902ca7c2dec6e2f01f40c4576009d
+
+Curve = P-384
+Private = e6ab171f6937c000e144950801ad91023ae8e8476856c2592d9f7d5bb7180fd729211803d39a412ead6c0be761cfa5d1
+X = 38bc42b8c9d8866d09b214398d584b1b24a488dfacc3420d1e9506aa825b19fdf1ba74e7b8f547f47b571467fe8c4d1f
+Y = 5179d62668d3f6a7ab5c8e3761a685e12008fb87d0529a97645f65cfb5364376c1b6682e0ffcddd0bcd995c41d013ad3
+Digest = 57f030024cde572f1e3368cf23aaa686e59d645455ef5f01e3b9c14067dd0eb3
+K = 05e9718aea9669c9e434f73866da5f252dec6d24c47a1c4ee3233450b6ec626de9746ebe095b285558dfc89fc1b622fe
+R = df9bab9dd1f22ec6f27116f38831cb2089aa78aa8c073024a0faddd9a48e810a5e8e2cadd80fbf8dbd6088c71fe30b5b
+S = 1e0e8718567d12d18558c57f9e87a755c309e4ffb497335a3adfc8d7475ce8fd882d5dc33a8f5a16274b7ad74bb7862a
+
+Curve = P-384
+Private = 14acd516c7198798fd42ab0684d18df1cd1c99e304312752b3035bed6535a8975dff8acfc2ba1675787c817b5bff6960
+X = 29909d143cf7ee9c74b11d52f1a8f3ebd4a720c135612ca5618d3f432f03a95602ee75a2057e1d7aab51d0648ac0b334
+Y = 404b6c5adffbadfa1b0380ae89fed96ec1ca16cc28661e623d0f1c8b130fbaa96dd7257eae2bf03c2d3dcbc3dbc82c58
+Digest = b3533ac348a241e255a62e7bc787a44394fd80328621f62f39df170298cc6a1b
+K = 7f623c103eaa9099a0462e55f80519c565adaeffcb57a29993f3a8a92e63a560be8f0fb9d23dc80bff1064bb41abad79
+R = 932ab291950c16b2b19a8036cd2e905714c6229cb190a73b3ea49c48dd8e76063a453c7c3267a57597d2973678216296
+S = d17d4c5ddbb9c27beebf526f113b416c8abfad53d11c4224813c7f351ba41a77dd4e77d6e4a65bef2c9f62cc37a469a5
+
+Curve = P-384
+Private = 2e780550984f3a00cb1e412429b33493c6eb6cd86d12f9d80588c247dcf567bd04296d2d4b24b889d9c54954b7f38f57
+X = 37dac42ef04663238443ef33e8addee2e78c40d50a1751913a7f5c37d1f23a26c7f86e16055c788b8ca9554f06b2f2ef
+Y = bbed1549652904e3d00c39b01cc0460dbaf3185e6190c2705677a9701de1fe56dff4f4d8418ee15059ff8fc36800982d
+Digest = 8f8009afc17d98d009d1bc84afb81d07e128c941e3312cf807223fc4f33ebb53
+K = b788ca82811b0d4e4841765c71eafaa1e575378beedcd3860d8b92db3d070ac5aef7c425067860fbee6c50cf0c642bbb
+R = 7292b3851870daeb2555a8a2fb198ead78739fcfb75327e5c32a82c6b77d58983e5ad548ccb75dcf9411039c9576d9b9
+S = a378c61802d9f1dd062b6e18f16416a954018f77df4df95ad1b983570377d5cfce4cc7861759e802c52f81abc4f49aac
+
+Curve = P-384
+Private = a24d0fe90808aecc5d90626d7e6da7c9be5dfd4e1233c7f0f71f1b7c1c6fd318fafe18559c94718f044cf02ed5107cb1
+X = ec8ae1fb9bb88589d27d6f27d790392853396f37bc0c381631d85800fc668eea0886bf1c6cff801147df19778d5b1604
+Y = 1e1a8336c1e2506f8ee388b55cc648ae73b9295ea78467979d2affb364536fad28120f51ec62a67cbb6ce7784780389f
+Digest = 9611180f5a8b0d8320759910bf653e92accbf1f968d40dec5d8e0350a989b09b
+K = 755d025509b73cf1ea8817beb772ad150b4c17a52378be187daffe3db0158921e5e552d1ca3c85df28519939f3cb794d
+R = 23ff2ffa62bbd427d49995d9c9950116e0d5a06ef076a4553448bc109e6482c5e87d4c833bc88de0bc722bc98cae2e61
+S = 9aea13d487c3ea6917e16374caafcf0321c12a80d28902dd8cd81909bb04b8c439e2491e504756742d0d0bfb15a9c34c
+
+Curve = P-384
+Private = 1c172e25732555afee7ded67a496f3f11babc0875898619f4519c29321e201e8ba1149f2c20b48e5efba235d58fea7c3
+X = 13e9e2c8bbcfe26e8f5f43c86268c5980ee693236a6b8777f3a7323718baa21005b482d08aafc6fa6e3667d91353544c
+Y = 9ba181b3ee505be030f87ecd249b00670a791489b42af04976013483ff95b630c91c01e95757e906129f2f9b4ce719a8
+Digest = 45607fd85aa1a246e8910dd3164b7c62c23ae515a3b464128a69c78f172138cc
+K = 08aec9a9e58bdc028805eb5dc86073d05fff1f5fb3fd17f510fc08f9272d84ba7aa66b6f77d84fe6360bd538192bf01a
+R = 2b4337c3dfbc886ffad7858ae2480cb62227e12205a70361c42f1a5ca9e658ee30fc3cf4030d85bd065edad83b99821f
+S = 2550cef8574bf17fb3d6b0c9d04ab266962bac3621bac233ff2e4989712d2a4a07171c0aebd3040cd6a32c3bd3efb8b5
+
+Curve = P-384
+Private = 5b96555dbd602e71d4d5d3aee19fd1ea084ee23d4f55c10937056762bc2015cbded2e898a487f5482ab7e1e971245907
+X = 6e14c17bb831b0112d7f3543c5fd17c78379a516c9e0539b03b8b4bfdead2820343fc84b0382807573ded6c4d97b7003
+Y = 7f60021d2de77546db666721c9aec84c3e2ba8de0ba77443600dc77e6839bbf9316271adb22d4cb47d08f745ecb1dafd
+Digest = 5a3b963da0a115759db0cee686ee34441e35ca3a3d5dd8ccb9d85b1f001ae63f
+K = 7ad6f4ffd2b429ba10c6f112f800cacf1ad508cf8eba880893bb9659c1ddaaec57dcdc093a114500460d457bdde324f2
+R = faea950ca513806bc59028c638d6302ffc86978c3ff1f06db015dd7c4777050186cb8dd871f5e926e1416539c1939c2f
+S = 2c592240eabb8a1f9878e1b5c9d5d3ced7b3a7ae571f5a86494ed2ca567a36eb72e7bea8934bded29594bccf67ca84bd
+
+Curve = P-384
+Private = 8df9c3c710a25192f3dea970910bb3784e3509874cccf4334823eb9f7a8d05b067f2d812d61e878e24b093089a0b8245
+X = 92c9e32b20cbe6d4ed0727c6c942cf804a72031d6dfd69078b5e78ebce2d192268f1f5e2abce5aaf1f8d6a35f136837f
+Y = d5167905fa7689e03b9fb1487c566f62b36f2bc1c4a2bfb6a836113b5c8d46f7c1ca51b628b14397fbc06ec9a07f4849
+Digest = 3863fc5414aef6de36c69b2a38307f9b429fefb2fb029d7dbf80483950316a8d
+K = 258dd05919735cd48627c9fe9fac5c252604aa7c2ae0460d7c1149cd96b7bd2ba195ad393bf392a2499f06aead5ba050
+R = 413793bcce52eda0f5b675a8d687cce86d5c9e1659b38a89e96246b5e05f8b0934d17dbba3b2ea44c838aa5fd87125d1
+S = ce7309fc2d6e3438818a1a29a997410b025b0403de20795b97c86c46034a6b02afeed279aeb06522d4de941bfdf50469
+
+Curve = P-384
+Private = 6002cb01ad2ce6e7101665d47729c863b6435c3875de57a93f99da834f73e3e6e2b3880e06de3e6bd1d51ea1807ab0d7
+X = e4216e1a20af8e8e3e74653ac016545001066e53e64af679ad1c85841bb475aed3e00ead052ae9955f48d675ff4ace56
+Y = 8804c17641be21d4c6386902c9c5c888af25d97ca383703ea4a85cf93bbab360c0bbd2993374da499a303778650270b9
+Digest = 9ef131664cee116ba88d3c362e694c2a56772c19f4356d9e576c96285bc52275
+K = 6b9507fd2844df0949f8b67b6fde986e50173713ac03df2edf65cb339859321cd3a2b9aab8356f95dec62460ab19c822
+R = 018891f6381ed358b422f79a299cf0789cee783ba388af4d82cbbe17f3709751b7fd9400e9702820c28b9afc62fdf489
+S = aef73bd590802b2fd2a65c4f7fec89f9b24ecc199a69254785925f334cd1977c5e1f858bd9830d7d7d243ea707b1af0b
+
+Curve = P-384
+Private = d8559c3543afc6f7b3dc037a687bad2630283757ba7862fd23ed14e2151a4cf5fed3d249268f780e0b96b6b46274a2d5
+X = 5f94223918f2ec9f0a08342cb99e724881c92453957c59672860f69daac01b660331a0f5845e50f1f27766b219c89e7e
+Y = d76d83396130d10d1168d76c7fc83742ffffbe66d9f4da4ca3f95f5ad6dac8cc7bb65d16d317d37aa99fdbf30ec7439c
+Digest = 2d0f59dc1c0698c75de8744e75c8bca110f125fc67bd75833c2b5aaf9d99da26
+K = 4ad5a92b5b8e170b71c8a7ed419dc624c7680004562b8d16a37b6e639f581ce81d5f0d98cce44d54c4e7136229148340
+R = f7baa6a5488ab462ea59aa31a36402b15880c68110b6069f51ede0c3b52a7b1e5bf926fdbe95768931b7d5f87058835c
+S = 28b1c4ef448a432f7c91b98b0c6471691e888211b6af907369a8930859b8cdb2e94f466a44f4e52f46df9b0d65e35de6
+
+Curve = P-384
+Private = b9208cbfd186ddfa3efd5b71342ae1efb01a13ebc4c2a992a2cbee7254b7846a4252ece1104b89d13d835911f8511224
+X = 166e6d96cb60d916fd19888a2dd945a3306ff0d7b0a5e30729f47d3dac3de2be3fd5cd7437e9a80d6c48cf960d2d36f8
+Y = e6b2b70f131092ae210f29cc6bad701318bddb31bddf921695855c6208941100d0cee5d10799f8b835afe3ea510e8229
+Digest = c92cd2d52c9bfbd5c1bc55c6894cbaeae5aef12bd76a4d39d63e526aaf25760f
+K = da706ab5f61531f2378b3c0a2b342108cd119eadaa88b859df64923bccfb0ec2393fd312826f65c15a6587d1d460015b
+R = d9124c42858080c62400e4d4d8136304e03d910cbe9b9b3487f4d27c7e0540a314d34bef8c850045c8746ca631c11c42
+S = bbf6424a3b70166fa799f49e918439d515327039258ef9bd88435a59c9c19659f8ec3c8660720b0c08354ff60e0f5a76
+
+Curve = P-384
+Private = 201b432d8df14324182d6261db3e4b3f46a8284482d52e370da41e6cbdf45ec2952f5db7ccbce3bc29449f4fb080ac97
+X = c2b47944fb5de342d03285880177ca5f7d0f2fcad7678cce4229d6e1932fcac11bfc3c3e97d942a3c56bf34123013dbf
+Y = 37257906a8223866eda0743c519616a76a758ae58aee81c5fd35fbf3a855b7754a36d4a0672df95d6c44a81cf7620c2d
+Digest = 31a452d6164d904bb5724c878280231eae705c29ce9d4bc7d58e020e1085f17eebcc1a38f0ed0bf2b344d81fbd896825
+K = dcedabf85978e090f733c6e16646fa34df9ded6e5ce28c6676a00f58a25283db8885e16ce5bf97f917c81e1f25c9c771
+R = 50835a9251bad008106177ef004b091a1e4235cd0da84fff54542b0ed755c1d6f251609d14ecf18f9e1ddfe69b946e32
+S = 0475f3d30c6463b646e8d3bf2455830314611cbde404be518b14464fdb195fdcc92eb222e61f426a4a592c00a6a89721
+
+Curve = P-384
+Private = 23d9f4ea6d87b7d6163d64256e3449255db14786401a51daa7847161bf56d494325ad2ac8ba928394e01061d882c3528
+X = 5d42d6301c54a438f65970bae2a098cbc567e98840006e356221966c86d82e8eca515bca850eaa3cd41f175f03a0cbfd
+Y = 4aef5a0ceece95d382bd70ab5ce1cb77408bae42b51a08816d5e5e1d3da8c18fcc95564a752730b0aabea983ccea4e2e
+Digest = a92784916a40feaebfeab16ea28c0c65e45c5e81eb634052944865708072e20110bd669a9838d7e722e94ac75245cdd3
+K = 67ba379366049008593eac124f59ab017358892ee0c063d38f3758bb849fd25d867c3561563cac1532a323b228dc0890
+R = fb318f4cb1276282bb43f733a7fb7c567ce94f4d02924fc758635ab2d1107108bf159b85db080cdc3b30fbb5400016f3
+S = 588e3d7af5da03eae255ecb1813100d95edc243476b724b22db8e85377660d7645ddc1c2c2ee4eaea8b683dbe22f86ca
+
+Curve = P-384
+Private = b5f670e98d8befc46f6f51fb2997069550c2a52ebfb4e5e25dd905352d9ef89eed5c2ecd16521853aadb1b52b8c42ae6
+X = 44ffb2a3a95e12d87c72b5ea0a8a7cb89f56b3bd46342b2303608d7216301c21b5d2921d80b6628dc512ccb84e2fc278
+Y = e4c1002f1828abaec768cadcb7cf42fbf93b1709ccae6df5b134c41fae2b9a188bfbe1eccff0bd348517d7227f2071a6
+Digest = b2acf6b4ae1ba9985c1e657313d59157939c21868302f6f5c5dbf037867035ae7c2009bad9fce472579923f7b4b87795
+K = 229e67638f712f57bea4c2b02279d5ccad1e7c9e201c77f6f01aeb81ea90e62b44b2d2107fd66d35e56608fff65e28e4
+R = b11db592e4ebc75b6472b879b1d8ce57452c615aef20f67a280f8bca9b11a30ad4ac9d69541258c7dd5d0b4ab8dd7d49
+S = 4eb51db8004e46d438359abf060a9444616cb46b4f99c9a05b53ba6df02e914c9c0b6cc3a9791d804d2e4c0984dab1cc
+
+Curve = P-384
+Private = de5975d8932533f092e76295ed6b23f10fc5fba48bfb82c6cc714826baf0126813247f8bd51d5738503654ab22459976
+X = f1fabafc01fec7e96d982528d9ef3a2a18b7fe8ae0fa0673977341c7ae4ae8d8d3d67420343d013a984f5f61da29ae38
+Y = 1a31cf902c46343d01b2ebb614bc789c313b5f91f9302ad9418e9c797563e2fa3d44500f47b4e26ad8fdec1a816d1dcf
+Digest = ec21c9d03a7270ea9ce7e9ff83211bac2fb104d078217c370248a3aba81f6c586852f19ced56dc71f83f5251d7381c8a
+K = fc5940e661542436f9265c34bce407eff6364bd471aa79b90c906d923e15c9ed96eea4e86f3238ea86161d13b7d9359d
+R = c2fbdd6a56789024082173725d797ef9fd6accb6ae664b7260f9e83cb8ab2490428c8b9c52e153612295432fec4d59cd
+S = 8056c5bb57f41f73082888b234fcda320a33250b5da012ba1fdb4924355ae679012d81d2c08fc0f8634c708a4833232f
+
+Curve = P-384
+Private = 11e0d470dc31fab0f5722f87b74a6c8d7414115e58ceb38bfcdced367beac3adbf1fe9ba5a04f72e978b1eb54597eabc
+X = 1950166989164cbfd97968c7e8adb6fbca1873ebef811ea259eb48b7d584627f0e6d6c64defe23cbc95236505a252aa1
+Y = 41ef424b5cb076d4e32accd9250ea75fcf4ffd81814040c050d58c0a29b06be11edf67c911b403e418b7277417e52906
+Digest = f0272d0a51ee61f86d0875ca7800e12744ef6ffbac72bdda7c54ba24e5a5a6bd69ebe6f429cc20ac12b926d392efc4ce
+K = e56904028226eb04f8d071e3f9cefec91075a81ca0fa87b44cae148fe1ce9827b5d1910db2336d0eb9813ddba3e4d7b5
+R = c38ef30f55624e8935680c29f8c24824877cf48ffc0ef015e62de1068893353030d1193bf9d34237d7ce6ba92c98b0fe
+S = 651b8c3d5c9d5b936d300802a06d82ad54f7b1ba4327b2f031c0c5b0cb215ad4354edc7f932d934e877dfa1cf51b13fe
+
+Curve = P-384
+Private = 5c6bbf9fbcbb7b97c9535f57b431ed1ccae1945b7e8a4f1b032016b07810bd24a9e20055c0e9306650df59ef7e2cd8c2
+X = 2e01c5b59e619e00b79060a1e8ef695472e23bf9a511fc3d5ed77a334a242557098e40972713732c5291c97adf9cf2cf
+Y = 563e3fe4ad807e803b9e961b08da4dde4cea8925649da0d93221ce4cdceabc6a1db7612180a8c6bef3579c65539b97e9
+Digest = e114c6204bee5bf0bbdf9ffc139bb99f09e7ea2186da3ee1e011dd059185d57c4953a130d34ff0df3fc6782dda199ee8
+K = 03d23f1277b949cb6380211ad9d338e6f76c3eedac95989b91d0243cfb734a54b19bca45a5d13d6a4b9f815d919eea77
+R = abab65308f0b79c4f3a9ff28dd490acb0c320434094cef93e75adfe17e5820dc1f77544cfaaacdc8cf9ac8b38e174bef
+S = 11b783d879a6de054b316af7d56e526c3dce96c85289122e3ad927cfa77bfc50b4a96c97f85b1b8221be2df083ff58fb
+
+Curve = P-384
+Private = ffc7dedeff8343721f72046bc3c126626c177b0e48e247f44fd61f8469d4d5f0a74147fabaa334495cc1f986ebc5f0b1
+X = 51c78c979452edd53b563f63eb3e854a5b23e87f1b2103942b65f77d024471f75c8ce1cc0dfef83292b368112aa5126e
+Y = 313e6aaf09caa3ba30f13072b2134878f14a4a01ee86326cccbff3d079b4df097dc57985e8c8c834a10cb9d766169366
+Digest = f11e38f4037ae3ffd0fde97c08e2e5acbc26e3ac5828a86c182232be90ef6fc0f5d21a9b1a7b93472d78c103b4136019
+K = c3de91dbe4f777698773da70dd610ef1a7efe4dc00d734399c7dd100728006a502822a5a7ff9129ffd8adf6c1fc1211a
+R = f4f477855819ad8b1763f53691b76afbc4a31a638b1e08c293f9bcd55decf797f9913ca128d4b45b2e2ea3e82c6cf565
+S = 7c26be29569ef95480a6d0c1af49dc10a51a0a8931345e48c0c39498bfb94d62962980b56143a7b41a2fddc8794c1b7f
+
+Curve = P-384
+Private = adca364ef144a21df64b163615e8349cf74ee9dbf728104215c532073a7f74e2f67385779f7f74ab344cc3c7da061cf6
+X = ef948daae68242330a7358ef73f23b56c07e37126266db3fa6eea233a04a9b3e4915233dd6754427cd4b71b75854077d
+Y = 009453ef1828eaff9e17c856d4fc1895ab60051312c3e1db1e3766566438b2990cbf9945c2545619e3e0145bc6a79004
+Digest = f8d0170479b2d1a8f50c80556e67ff345592c8b7dcda4e4f6099f993c1a71bff6d3b60190715ae1215a8a759a8eb13df
+K = a2da3fae2e6da3cf11b49861afb34fba357fea89f54b35ce5ed7434ae09103fe53e2be75b93fc579fedf919f6d5e407e
+R = dda994b9c428b57e9f8bbaebba0d682e3aac6ed828e3a1e99a7fc4c804bff8df151137f539c7389d80e23d9f3ee497bf
+S = a0d6b10ceffd0e1b29cf784476f9173ba6ecd2cfc7929725f2d6e24e0db5a4721683640eaa2bbe151fb57560f9ce594b
+
+Curve = P-384
+Private = 39bea008ec8a217866dcbdb1b93da34d1d3e851d011df9ef44b7828b3453a54aa70f1df9932170804eacd207e4f7e91d
+X = 5709ec4305a9c3271c304face6c148142490b827a73a4c17affcfd01fffd7eaa65d2fdedfa2419fc64ed910823513faf
+Y = b083cda1cf3be6371b6c06e729ea6299213428db57119347247ec1fcd44204386cc0bca3f452d9d864b39efbfc89d6b2
+Digest = 86bc7536faf2de20028159ce93e293d0a7f5721fb6680b5b070c3f70aba845de2eaed9245144babc38c49cce59f3eac7
+K = 3c90cc7b6984056f570542a51cbe497ce4c11aeae8fc35e8fd6a0d9adeb650e8644f9d1d5e4341b5adc81e27f284c08f
+R = d13646895afb1bfd1953551bb922809c95ad65d6abe94eb3719c899aa1f6dba6b01222c7f283900fe98628b7597b6ea6
+S = 4a9a38afda04c0a6b0058943b679bd02205b14d0f3d49b8f31aac289129780cdb1c555def8c3f9106b478729e0c7efaa
+
+Curve = P-384
+Private = e849cf948b241362e3e20c458b52df044f2a72deb0f41c1bb0673e7c04cdd70811215059032b5ca3cc69c345dcce4cf7
+X = 06c037a0cbf43fdf335dff33de06d34348405353f9fdf2ce1361efba30fb204aea9dbd2e30da0a10fd2d876188371be6
+Y = 360d38f3940e34679204b98fbf70b8a4d97f25443e46d0807ab634ed5891ad864dd7703557aa933cd380e26eea662a43
+Digest = 1128c8b09573a993adaa0a68f3ca965db30870db46de70d29e3b9a7d110ba0cd57633f1713173c62331b36fb925fa874
+K = 32386b2593c85e877b70e5e5495936f65dc49553caef1aa6cc14d9cd370c442a0ccfab4c0da9ec311b67913b1b575a9d
+R = 5886078d3495767e330c7507b7ca0fa07a50e59912a416d89f0ab1aa4e88153d6eaf00882d1b4aa64153153352d853b5
+S = 2cc10023bf1bf8ccfd14b06b82cc2114449a352389c8ff9f6f78cdc4e32bde69f3869da0e17f691b329682ae7a36e1aa
+
+Curve = P-384
+Private = d89607475d509ef23dc9f476eae4280c986de741b63560670fa2bd605f5049f1972792c0413a5b3b4b34e7a38b70b7ca
+X = 49a1c631f31cf5c45b2676b1f130cbf9be683d0a50dffae0d147c1e9913ab1090c6529a84f47ddc7cf025921b771355a
+Y = 1e207eece62f2bcc6bdabc1113158145170be97469a2904eaaa93aad85b86a19719207f3e423051f5b9cbbe2754eefcb
+Digest = ab9a6d22c8d7675bc8e99e3cafed8318f33051ba5398ce0e9d8e8d3d537a6a908d4c2ace3e6d8204d0236d863eee3c28
+K = 78613c570c8d33b7dd1bd1561d87e36282e8cf4843e7c344a2b2bb6a0da94756d670eeaffe434f7ae7c780f7cf05ca08
+R = 66f92b39aa3f4aeb9e2dc03ac3855406fa3ebbab0a6c88a78d7a03482f0c9868d7b78bc081ede0947c7f37bf193074ba
+S = e5c64ed98d7f3701193f25dd237d59c91c0da6e26215e0889d82e6d3e416693f8d58843cf30ab10ab8d0edd9170b53ad
+
+Curve = P-384
+Private = 083e7152734adf342520ae377087a223688de2899b10cfcb34a0b36bca500a4dfa530e2343e6a39da7ae1eb0862b4a0d
+X = 70a0f16b6c61172659b027ed19b18fd8f57bd28dc0501f207bd6b0bb065b5671cf3dd1ed13d388dcf6ccc766597aa604
+Y = 4f845bf01c3c3f6126a7368c3454f51425801ee0b72e63fb6799b4420bfdebe3e37c7246db627cc82c09654979c700bb
+Digest = 68f858243fe465eb91dc2481333cbb1958883ef25099d45cf02721d17d2846d2cec4689884ae7c0412332e035a1fa3fc
+K = 28096ababe29a075fbdf894709a20d0fdedb01ed3eeacb642a33a0da6aed726e13caf6cf206792ec359f0c9f9b567552
+R = ee2923f9b9999ea05b5e57f505bed5c6ba0420def42c6fa90eef7a6ef770786525546de27cdeb2f8586f8f29fb4ee67c
+S = 50ef923fb217c4cf65a48b94412fda430fac685f0da7bd574557c6c50f5b22e0c8354d99f2c2f2c2691f252f93c7d84a
+
+Curve = P-384
+Private = 63578d416215aff2cc78f9b926d4c7740a77c142944e104aa7422b19a616898262d46a8a942d5e8d5db135ee8b09a368
+X = cadbacef4406099316db2ce3206adc636c2bb0a835847ed7941efb02862472f3150338f13f4860d47f39b7e098f0a390
+Y = 752ad0f22c9c264336cde11bbc95d1816ed4d1b1500db6b8dce259a42832e613c31178c2c7995206a62e201ba108f570
+Digest = dca5ebfebeac1696eff4a89162469c6937b80f8f8cf17299856de2e13d8f8a199bff3085cee59366886164bcc03f7e90
+K = 7b69c5d5b4d05c9950dc94c27d58403b4c52c004b80a80418ad3a89aabc5d34f21926729e76afd280cc8ee88c9805a2a
+R = db054addb6161ee49c6ce2e4d646d7670754747b6737ca8516e9d1e87859937c3ef9b1d2663e10d7e4bd00ec85b7a97a
+S = fcc504e0f00ef29587e4bc22faada4db30e2cb1ac552680a65785ae87beb666c792513f2be7a3180fc544296841a0e27
+
+Curve = P-384
+Private = ed4df19971658b74868800b3b81bc877807743b25c65740f1d6377542afe2c6427612c840ada31a8eb794718f37c7283
+X = 33093a0568757e8b58df5b72ea5fe5bf26e6f7aeb541b4c6a8c189c93721749bcaceccf2982a2f0702586a9f812fc66f
+Y = ebe320d09e1f0662189d50b85a20403b821ac0d000afdbf66a0a33f304726c69e354d81c50b94ba3a5250efc31319cd1
+Digest = f9b152150f7dc99d5262c9da04dde148009730fb2af9ac753b9c64488d27c817f68c17ae1ff61e50ebb6749230c59a71
+K = d9b4cd1bdfa83e608289634dbfcee643f07315baf743fc91922880b55a2feda3b38ddf6040d3ba10985cd1285fc690d5
+R = 009c74063e206a4259b53decff5445683a03f44fa67252b76bd3581081c714f882f882df915e97dbeab061fa8b3cc4e7
+S = d40e09d3468b46699948007e8f59845766dbf694b9c62066890dd055c0cb9a0caf0aa611fb9f466ad0bbb00dbe29d7eb
+
+Curve = P-384
+Private = e9c7e9a79618d6ff3274da1abd0ff3ed0ec1ae3b54c3a4fd8d68d98fb04326b7633fc637e0b195228d0edba6bb1468fb
+X = a39ac353ca787982c577aff1e8601ce192aa90fd0de4c0ed627f66a8b6f02ae51315543f72ffc1c48a7269b25e7c289a
+Y = 9064a507b66b340b6e0e0d5ffaa67dd20e6dafc0ea6a6faee1635177af256f9108a22e9edf736ab4ae8e96dc207b1fa9
+Digest = 14f785ebb5a3b1bdff516a6b580e245b3c81aff37e1035e354b084a6691e973e0de30bb2a0490fca2d757f8191d7560a
+K = b094cb3a5c1440cfab9dc56d0ec2eff00f2110dea203654c70757254aa5912a7e73972e607459b1f4861e0b08a5cc763
+R = ee82c0f90501136eb0dc0e459ad17bf3be1b1c8b8d05c60068a9306a346326ff7344776a95f1f7e2e2cf9477130e735c
+S = af10b90f203af23b7500e070536e64629ba19245d6ef39aab57fcdb1b73c4c6bf7070c6263544633d3d358c12a178138
+
+Curve = P-384
+Private = 217afba406d8ab32ee07b0f27eef789fc201d121ffab76c8fbe3c2d352c594909abe591c6f86233992362c9d631baf7c
+X = fb937e4a303617b71b6c1a25f2ac786087328a3e26bdef55e52d46ab5e69e5411bf9fc55f5df9994d2bf82e8f39a153e
+Y = a97d9075e92fa5bfe67e6ec18e21cc4d11fde59a68aef72c0e46a28f31a9d60385f41f39da468f4e6c3d3fbac9046765
+Digest = f863cf3749ae5256da0ceb2e6d391fcce939b1490b024527687b1a2908da35c48b44255d82956c76d70672c41c6456d78c57342e932490083f73016b560a0245
+K = 90338a7f6ffce541366ca2987c3b3ca527992d1efcf1dd2723fbd241a24cff19990f2af5fd6419ed2104b4a59b5ae631
+R = c269d9c4619aafdf5f4b3100211dddb14693abe25551e04f9499c91152a296d7449c08b36f87d1e16e8e15fee4a7f5c8
+S = 77ffed5c61665152d52161dc13ac3fbae5786928a3d736f42d34a9e4d6d4a70a02d5af90fa37a23a318902ae2656c071
+
+Curve = P-384
+Private = 0a3f45a28a355381a919372f60320d6610cfb69c3e318eb1607db3cadfc42b728b77a6a9e9e333de9183c58933daf60f
+X = 832cbb7061a719a316e73dbad348fa67cd17c33f40b9000a3d3b691a2a2cd821052566717c3ead01089b56086af1366f
+Y = 1e15a048d1dce642d9ebcbfac7f92b1bcee90fd0240cc79abd29e32e0e655c4ee1fd34fb88178bba92aca100e7794ed0
+Digest = 68944ca920620e1d42184d264c4ffe295882f00079f9daaaa0efc305fe10cc7bbc667985c148eacb51ee1c05a6d8a861e98371a045e11e18e200ad52d5b4cb13
+K = 2a78e651623ba604c42cf094fc7d046629306f508853427ba091448800d1092c041bb2323035fc9d19a8d44950f7dcc3
+R = 0db0cc9a2bda8dd7e565ad36f91b1c5756d78164dc8a72a5bee4b6bc45ea38c7a16b01d05b1893d4e06b62db24c30385
+S = abd383edaeda7d0b8de1b54fcd3c28874fed62ab266f1f84c8ba796a7b54e5e0695fdb43ce7fe90ed00fa468d87bca64
+
+Curve = P-384
+Private = 2e408c57921939f0e0fe2e80ce74a4fa4a1b4fa7ab070206298fe894d655be50e2583af9e45544b5d69c73dce8a2c8e7
+X = a2b24a5ad4a2e91f12199ed7699e3f297e27bf8b8ea8fbe7ed28366f3544cd8e680c238450f8a6422b40829d6647b25c
+Y = 2732be0075536e6519f6a099b975a40f8e0de337fa4d48bd0762b43f41cab8deafdef9cfbb9973e457801e3bf9c93304
+Digest = 8876ecd423fd0e903364fac777897b80b31c03f0f1ef1678372a6cb240ab701e49b51b798fd8e588ab39db7d3c77879901916babdd0ef0632cc16d5ccb9d1535
+K = b10b6258afdde81f9c971cc1526d942e20cafac02f59fee10f98e99b8674636bff1d84a6eaa49c0de8d8cfdc90d8ce84
+R = be428a8de89a364a134719141ee8d776a3a8338f1132b07e01b28573d8eaf3b9008b63304c48821e53638b6141f9660b
+S = 866181dbef5c147d391bed6adcee408c339982c307adc718c2b9ab9e5642d8dedc36dd6402559a3ab614c99c1e56b529
+
+Curve = P-384
+Private = 1c285da72a8eb1c3c38faab8d3bb4e68dc95c797082b9a3991a21c1de54759071ecf2265fb1eff504ab24174bc6710cf
+X = 11acb1b5cc59a4f1df1913a8d6e91cbdafb8206dc44aff7d9da45906b664fc33194d9935a82aa4d62f39618897c86025
+Y = 832ed0b9575fff52a3603bfe89f312751b4c396da98324117a61b3f525d27b2266f6cfb22be07e50b6874435e380ed62
+Digest = 2a1a866fe1596c484c38ef78bdda2e9783dd9f8df86e93e56f86cfb467e9f457d27e02d36e0c23d63401d82765e5e1a8065ad8f3a67bb0db356a6a1c5a63df27
+K = 2513075e02cc7fb3cff7b7adde46da31c5493749b5cf02758bd5b098a838bfd4d5e4c7fb8268bdc37e219c30efebe878
+R = b3d638b3be45f14f170da5bdc22d2114deac93ab340a25b3af2b5c18584bb9147e00dc6c67a2274f79aa4838793eb63f
+S = 876112bdca2c725eb2f6dbd76d07710a31f0c16d38430cb0817f320a25a9ecfec8a66137d0304612ae29a6a484fd3319
+
+Curve = P-384
+Private = 9da37e104938019fbdcf247e3df879a282c45f8fb57e6655e36b47723af42bec3b820f660436deb3de123a21de0ca37b
+X = 722d0ea6891d509b18b85ca56f74deb5c3030d2a30433824123d430d03c99279572c3b28ecf01e747b9db8acc55d0ba3
+Y = 7e2605ea7092214f366f3639037bffd89fe103c646e990839d3a1ced8d78edb5b9bc60d834fd8e2a3c17e920bdae023a
+Digest = 96768f5d5edae35aaabf1e32158525b0cfb28a74059a48e053208e4a655f51a8fabb63e3a7e7c70be9945b1954f9bc48247d9f19c98328b8d65030d37a71b84b
+K = c8c18e53a9aa5915288c33132bd09323638f7995cd89162073984ed84e72e07a37e18c4c023933eace92c35d10e6b1b6
+R = 6512a8a2be731e301dcf4803764297862bbfa0ac8daed64d8e98b34618ecb20520fc5d3cf890b7783edf86e7ea407541
+S = 4ff10301f7b4168fae066361376007c1d7aa89a75c87719d0b54711ffef5ef3726f3eef84f7ebc025c110bde511b17f6
+
+Curve = P-384
+Private = 0661ab3bf9f7bef51bec7dff758de289154557beb9ce18cc4b8cc09a871e8322af259cf188b593dc62f03a19e75f7f69
+X = b4f100558043858efa728082d9b99ad5192b59b0947434f5ba7ff2514508a6d71ba54e7221c31cb0712103272b3f6fa4
+Y = 34f6df4eeb2da11498044635067c2715ed15ae251c78ffb9030d87909ea8539b66394e93109ca54c0406cf99960c3e93
+Digest = c2a0f9cd8fe7d7a951f19d373ad97dc7f95219cd2b8498552a3352f1a4b0e4ee25c7a7a51b1e47b66640c320e503a53dc76af6c08141c8936ec8cbdc038cb7a8
+K = 84a87137edb6894f96c5a8e94a3765162034feb84dfea94e1c71411170c285a80321ec7999e25861844143209804882c
+R = 4dc9d1b949b36e3c3847ac1c7ed114e1bc9cbe76119cf6fcd3f1b69ee6ee54e3255f1bb288fe2f8bd6d4049a21793c27
+S = 56a561d647b62ccae1e6df818b1a6fbde66c82ef0ff69ee415f183e7daf76be22630c7e02cd3fd729dfa490f26824584
+
+Curve = P-384
+Private = 66e7cfdeb7f264cf786e35210f458c32223c3a12a3bc4b63d53a5776bc9b069928452484f6241caa3781fd1a4109d4db
+X = 3c7682de540ab231daf21bf9fc80bda6abf7e17dcc79d476c7b7c3bd4d42d386877fd8ba495c1b0333e04fb5fd2a1505
+Y = 0a1582e4f4d72abea9d3476aff8369c41261f0c5dddf2ca82e10f7a163f73df09473d9e5e2552187104e4cc7c6d83611
+Digest = cc04e32af9b8c178039eb9b1cece8bd89079ea400e35bb912e5efec06eeb02f9a12905383acbb5551b949f225998169818e3e9e6bd2cb0c08e10895f022f3be8
+K = 2fa266f5cce190eb77614933ca6a55121ad8bae168ff7a9043d96d13b5ca2fe70101ff9fe1e2b2cd7413e6aa8f49abde
+R = e7ecda9da0c52d0474a9f70094dc8f061d7d6a22210d3b69a7be8f389aa666f256322099b87d16ad35357ea856574dba
+S = ba348eb40a2830ec5a1130264ac0a8675420b1ae243e808a778135809ece21f42c0c881166321102b4f02df4c5c7ed9d
+
+Curve = P-384
+Private = 92c2f7ee64af86d003ab484e12b82fcf245fc330761057fec5b7af8f7e0a2d85b468c21d171460fcb829cae7b986316d
+X = ca43a306479bf8fb537d4b9ff9d635bbb2a0d60d9e854d5b7e269d09d91f78c6b90b616e4c931629453645a2bb371e14
+Y = 356c4d7f10e690614eaf7f82ba0f9dc1aad98130c0ad9fe353deec565cc04bef789a0a4242322e0058b46cd02f2de77d
+Digest = cf638b5ae7d04e6edc97be83aa2598afce555f9f85893208b7a5192ea84b08cbd10b54d0f5ee6e11e86a31252d766dfd927f724f276a52eb43c98fc16c4f7333
+K = 6ec81fb74f8725ba225f317264460ee300cfd2f02092000989acbdad4799cf55c244a65c557113328fe20282e6badb55
+R = cd7a4309bcebc25a8e10899fe2eda5f8b2dbcf329cd2f3d65befd67393e83fba2f8a67a15c01a6ac8314f9f5e87a9dca
+S = 6dcfc0426bc148e67e91d4784e3d7e9bc3b7ce3676be62daa7f3f55dfdff6d9dc735b5e3e0bbd0785db1f76f7ac065f3
+
+Curve = P-384
+Private = 15347caaad1067f1848a676bd0a8c52021ae604b79d02775a0459226e0391a3acd26653c916fcfe86149fb0ee0904476
+X = e5a0463163964d984f5bad0072d45bc2059939e60a826ccca36c151460ae360f5d6679f60fe43e999b6da5841c96e48a
+Y = 30f2dd425a3fa2c95d34124217250b39e3b4a14f3e6e415ae8e5b0409eb72f43f78b64d0ce6f2d49980d6f04cd1391db
+Digest = 4f381df1ba39833f9f10e4b88314290ed04b56a8cdc4eab26d7b8b2bb03b5add622d8323b9fce5c794027b91578fdbd17208cb238cb1c8bfab7485c81bf45a90
+K = 1a2d224db4bb9c241ca5cab18920fad615fa25c1db0de0f024cb3ace0d11ef72b056885446659f67650fdff692517b1c
+R = 87b4de0fb21df38dfc9a4b1e350da67547e307f55b5b9dd6615e408afe7c3553a6e02722847367439e636074faa2182b
+S = 375d965753b9ed6c6c08576726f8308c2f8dbd2737824464e71265d47907e26f615bbeb8203ec617520d4ecd1851dc44
+
+Curve = P-384
+Private = ac1cb5e59bda2eff3413a3bab80308f9fb32c595283c795de4c17fdae8d4647b5f108fd0801aee22adb7db129283b5aa
+X = bc6b1a718284803553c173089c397870aaaecca579bb8e81a8cfa12473cd2057567fa8726a19ed427cc035baeec2c551
+Y = 14f82997d1129b669f0015350e47ad561b1b13441af4fb44656f15ed0c5706984d66655accc52f2e943eef39cb1cdc21
+Digest = d1a787cdf3c1c6c807731083e28a75a1df39f43d19a16ff121ca10b33111b5c71c561542cb61c2cca85a1632ab5535596c659d8b257df95be175843d246e6232
+K = 8053a46e875f446056b06d4318fa3e8977622de7207cbf0996bf35b0e9b19aaa507f642bcf0be9f048f1af09806f6946
+R = a994eb15b64114ce8a9342d18b5edda96a6d76314a5ac03da723699177d352a4a9f3b7121b11a91e43a6af4025da51d6
+S = 8183ae33a888e99aa76882da0a6705ad102f2bbd9572fad0d2e4d6d70151970469e00c5220e59c14724d771c1384b302
+
+Curve = P-384
+Private = 205f1eb3dfacff2bdd8590e43e613b92512d6a415c5951bda7a6c37db3aae39b9b7ec6edd256609e75373419087fa71f
+X = c9f1f63a18c761b077a1ec35fbb2de635db9b8592c36194a01769b57728c7755d4c79b3d5b97a1a4631e30c86d03f13c
+Y = f8c4a38770054d5cc9bb9182e6d4638242c4fd16e869ac22e44c4b9402d594e0c6f5df6a9a7de32a4893d9f6588f1950
+Digest = f1c6287f6a2164c20b246bcc8500b03a7cee404caa6b571ed32ee7cff17eb1979d07e8ef1c2856ca83d987bf8301d7f3a8384c22f209c831f8b12f2b11cd8154
+K = ecd395c5d8b7d6e6b2b19644e0d2e6086c912c6a0f5b8ed4b94b7290b65852c9741ce8eeb08d8751ead8a183e17d76c6
+R = e81331d78b438b0b8d98c1be03385ba5d614af182f1677f259126cc3de7eaac6c19b02be955d936b6bf9c27c6796e6f0
+S = 17c2b7a8e0fc93909762aa9f86f9561e759ecb88f02337b2018363be6095d9e4324a6d3296046686624b5efad6b52878
+
+Curve = P-384
+Private = e21e3a739e7ded418df5d3e7bc2c4ae8da76266a1fc4c89e5b09923db80a72217f1e96158031be42914cf3ee725748c1
+X = 0f753171922b5334f3dd2778a64ce2da8295121939beae71ad85e5344e893be0fd03cf14e1f031adec098e0c4409449c
+Y = 45c10a0ffc0eb2f1cec5c89b698061108313ee7d449ad580efad344f0e7cf35be8a18fca620f112e57bdc746abdace55
+Digest = 44d0ad691730209dbfde2083c68111a0f59af96d8de255875b55654055c5b6f7a48537d461ebea4df1709e196fc5d9fab1466a53f24a63c749fde05f62daf7b8
+K = d06bea06b25e6c30e866b1eb0657b45673e37b709013fb28fd7373afc8277cbc861354f821d0bd1927e52ec083a0f41f
+R = e8d4a31dd0e7d2522be62a32608e744c3775ceb606dc897899f0c73f1a40ce9a8be854cd506e65cd81fd7fa2c616cb7b
+S = 8151b681b6b6046d3c36f332d06d9ba7751e740631cdb759f88c50a25a8e950d5023df8a15c77243743733c4feaf21d5
+
+Curve = P-384
+Private = 93434d3c03ec1da8510b74902c3b3e0cb9e8d7dccad37594d28b93e065b468d9af4892a03763a63eae060c769119c23c
+X = a52c25f2af70e5bc6a992ecef4ea54e831ed5b9453747d28aec5cffb2fcfee05be80c5cbab21606b5507aa23878adee1
+Y = 2cf2a9afeff83f3041dc8a05f016ccae58aa1a0e0dc6be9d928e97f2598c9ba5e9718d5eb74c9cfb516fd8c09f55f5b9
+Digest = 61c5ed5d5e7d742dce869379a4322dd5b3d773c0c07575d69fca1e9fe2e7a90ea013094dd474ef1e682f30ca0fca50d8835e84f1e5e62b8a3f6140fbe5c75a44
+K = 13d047708ae5228d6e3bbada0e385afdb3b735b31123454fdf40afe3c36efed563fd2cce84dcc45c553b0993d9ca9ec3
+R = a0203f6f2c456baac03538ed506a182e57a25151802cf4b2557613b2fb615ebd4c50ddc505f87c048a45bad3b2fc371c
+S = 0eab56457c4080400fa3af124761d5a01fef35f9649edba8b97d22116386f3b8b363e97ef3f82616d5d825df1cf865ef
+
+Curve = P-384
+Private = e36339ddbe8787062a9bc4e1540690915dd2a2f11b3fe9ee946e281a0a2cbed426df405ed9cb0eca42f85443efd09e0c
+X = a1ffb4b790d1593e907369b69de10b93cddbb02c6131f787422364d9d692768ef8097970306cce16c97f2b10c538efa7
+Y = d0692028601ea794d2563ffe9facc7273938fab47dd00b8960be15549a9c2b3f8552583eb4c6cd212fe486c159c79153
+Digest = 5e7b908015b39fe97a2e84d30cae3c3b309103ff446e3ea2b2eafb8c004ceee6589d31a83c9904f4f4caec4cc0cec7641f62dd228a40a7696bd2b4583a016ace
+K = 2226f7329378cecd697f36ae151546643d67760856854661e31d424fae662da910e2157da9bb6dfbe3622296e0b5710c
+R = 20dcc25b67dd997621f437f65d78347fb57f8295b1b14453b1128203cda892bcfe726a2f107d30975d63172e56f11d76
+S = 51cff592cbef75ef8321c8fa1e4229c4298b8180e427bee4e91d1e24fc28a729cf296beb728960d2a58cf26773d8e2e2
+
+Curve = P-384
+Private = 5da87be7af63fdaf40662bd2ba87597f54d7d52fae4b298308956cddbe5664f1e3c48cc6fd3c99291b0ce7a62a99a855
+X = 54c79da7f8faeeee6f3a1fdc664e405d5c0fb3b904715f3a9d89d6fda7eabe6cee86ef82c19fca0d1a29e09c1acfcf18
+Y = 926c17d68778eb066c2078cdb688b17399e54bde5a79ef1852352a58967dff02c17a792d39f95c76d146fdc086fe26b0
+Digest = 6f39c6187b6dbdfb17c7267aba7804f6087742d56647e74692afc69e1430bed1535cd71c7cef015f9647e2ade3e19f4f9574807a4c5fc5b2b219d1b6fe803bb0
+K = 1b686b45a31b31f6de9ed5362e18a3f8c8feded3d3b251b134835843b7ae8ede57c61dc61a30993123ac7699de4b6eac
+R = 9dbfa147375767dde81b014f1e3bf579c44dd22486998a9b6f9e0920e53faa11eed29a4e2356e393afd1f5c1b060a958
+S = e4d318391f7cbfe70da78908d42db85225c85f4f2ff413ecad50aad5833abe91bdd5f6d64b0cd281398eab19452087dd
+
+Curve = P-521
+Private = 01d7bb864c5b5ecae019296cf9b5c63a166f5f1113942819b1933d889a96d12245777a99428f93de4fc9a18d709bf91889d7f8dddd522b4c364aeae13c983e9fae46
+X = 01a7596d38aac7868327ddc1ef5e8178cf052b7ebc512828e8a45955d85bef49494d15278198bbcc5454358c12a2af9a3874e7002e1a2f02fcb36ff3e3b4bc0c69e7
+Y = 0184902e515982bb225b8c84f245e61b327c08e94d41c07d0b4101a963e02fe52f6a9f33e8b1de2394e0cb74c40790b4e489b5500e6804cabed0fe8c192443d4027b
+Digest = 84358f87f45970a080efcb8b1d9284c8e61e06edbf5209b1a9db9cbc
+K = 0141f679033b27ec29219afd8aa123d5e535c227badbe2c86ff6eafa5116e9778000f538579a80ca4739b1675b8ff8b6245347852aa524fe9aad781f9b672e0bb3ff
+R = 006b973a638bde22d8c1c0d804d94e40538526093705f92c0c4dac2c72e7db013a9c89ffc5b12a396886305ddf0cbaa7f10cdd4cd8866334c8abfc800e5cca365391
+S = 00b0a01eca07a3964dd27d9ba6f3750615ea36434979dc73e153cd8ed1dbcde2885ead5757ebcabba117a64fcff9b5085d848f107f0c9ecc83dfa2fa09ada3503028
+
+Curve = P-521
+Private = 017e49b8ea8f9d1b7c0378e378a7a42e68e12cf78779ed41dcd29a090ae7e0f883b0d0f2cbc8f0473c0ad6732bea40d371a7f363bc6537d075bd1a4c23e558b0bc73
+X = 00156cd2c485012ea5d5aadad724fb87558637de37b34485c4cf7c8cbc3e4f106cb1efd3e64f0adf99ddb51e3ac991bdd90785172386cdaf2c582cc46d6c99b0fed1
+Y = 01edeeda717554252b9f1e13553d4af028ec9e158dbe12332684fc1676dc731f39138a5d301376505a9ab04d562cc1659b0be9cb2b5e03bad8b412f2699c245b0ba2
+Digest = 962bade1e8227c9f2a069177fb89dab45c4f7e8e2f81fdd206b0b99e
+K = 01dc3e60a788caa5f62cb079f332d7e5c918974643dca3ab3566a599642cd84964fbef43ce94290041fe3d2c8c26104d9c73a57a7d4724613242531083b49e255f33
+R = 012592c0be6cce18efb2b972cd193d036dcb850f2390fa8b9b86b2f876548bc424fb3bc13c1e5c415fa09d0ecfcae5bf76fb23e8322d7eecb264a2ae6d20ef50d405
+S = 011bc9713be88e3b9912a3e5f5d7b56f20573e979b1a75d04ce339f724bddffa4665d25995fe24d32507d8a07c5e10169f5338ef2827737f7b0291752b21237217e3
+
+Curve = P-521
+Private = 0135ea346852f837d10c1b2dfb8012ae8215801a7e85d4446dadd993c68d1e9206e1d8651b7ed763b95f707a52410eeef4f21ae9429828289eaea1fd9caadf826ace
+X = 018d40cc4573892b3e467d314c39c95615ee0510e3e4dbc9fa28f6cd1f73e7acde15ad7c8c5339df9a7774f8155130e7d1f8de9139ddd6dfe1841c1e64c38ea98243
+Y = 017021782d33dc513716c83afe7ba5e7abef9cb25b31f483661115b8d6b5ae469aaf6f3d54baa3b658a9af9b6249fd4d5ea7a07cb8b600f1df72b81dac614cfc384a
+Digest = 3ab194db447f5dc738e1452bf7958b346c071b84d6ca2edd9ea3b870
+K = 00c24acc1edb3777212e5b0bac744eadf4eda11fa150753b355bf96b189e6f57fc02284bb22d8b3cd8bba7a09aae9f4ea955b382063425a6f8da2f99b9647b147172
+R = 0183da7b8a9f9d5f08903359c1a2435b085fcf26a2ed09ab71357bb7634054acc569535e6fe81d28233e4703005fc4bf83ce794d9463d575795aa0f03398e854cefd
+S = 00b3621145b9866ab7809139795cc30cd0404127a7f0fafa793660491009f6c53724fdb0b1ffbf0fd51c131180b8a957fe66e76d2970247c024261c768dee9abbfb9
+
+Curve = P-521
+Private = 01393cb1ee9bfd7f7b9c057ecc66b43e807e12515f66ed7e9c9210ba1514693965988e567fbad7c3f17231aacee0e9b9a4b1940504b1cd4fd5edfaa62ba4e3e476fc
+X = 01e855c935139c8092092cfa733db1292530506eeb2bbb1687f9602c36d97a6714e998892d5d3b842d1896a6ece9d549e9792881a256256137b3dff180c96cc5d07b
+Y = 018d83b6e93cd287311f7bf7c1d7f9eeabcf0b69c12f2d8f40e333e81e956d968532a37a4c04d761874df293b484cd7053b03fdbc2fdcd3b4c412d6f272fb7c93fe6
+Digest = 7c72d5606cbc1610e101aa50d4793f96339eab9eba88342e87ff2642
+K = 01d98619bdc04735d30c222fc67da82c069aea5f449af5e8c4db10c1786c0cb9e6f2cc0bb66fa6be18c485570d648dafcd0a973c43d5c94e9a9dacbd3170e53fa2a0
+R = 00bf47fabe107ce0ec03e2ad60a79b058e1bebb18568b6a8cdbe86032e71aa30c15766105b2ea952cfa79bcab046df601159f96e179bbcf252dc68ac73d31481fdae
+S = 01f918fec69cd07d90f9d892b7117e7519c3224947f4262f1fd97077dd5386a6c78aeddff3ee97e59ea353f06029f1336f0d6ef5c0f4b17ca59343a55319b7bfc3db
+
+Curve = P-521
+Private = 0179fa164e051c5851e8a37d82c181e809a05fea9a3f083299b22684f59aa27e40dc5a33b3f7949338764d46bfe1f355134750518b856d98d9167ef07aac3092c549
+X = 01857cc7bbed20e87b3fd9a104956aa20c6502192910e0e7598410526ebfe1c99397b85189612a60c51fb8f4dd5cb08a8cd2e702563062dcb043410715c5323a0046
+Y = 01fce8d135284310d2f38c216030634b32cd223222f0d9d8d2b7c55477c4b8b74fc6c96a6092f34b05ca44d3633a5037c2166c479a032bb4f949f89fc1ba5236d07d
+Digest = b2d36a3bfc82c960eb05f4993b9bd596a25920145d4267f74481a070
+K = 016d9704c0cee791f2938bb2a8a595752a3635c2f557efeecefd719414b5f2aaf846080f582c76eae7a8fddf81859b49d0131c212524d55defa67dca1a9a28ca400f
+R = 01c9a4e51774384e8362876a87c572e6463a54413c7c6252c552ebb182f83e45ace436ade4ca373d8a7216e83efb62c8b41c4d5132a0afa65078f16d189baca39187
+S = 01e92a7dd5fea29a666398e1df5775cbb5664fe6943fe4c1d2bba516b7543c84df584458e53919c4ffab579a26fb3c892a5d1a77b0a07428c89350f8b559e627b014
+
+Curve = P-521
+Private = 013dabca37130ba278eae2b3d106b5407711b0d3b437fbf1c952f0773571570764d2c7cb8896a8815f3f1975b21adc6697898e5c0a4242092fc1b80db819a4702df4
+X = 00bc2aebf40cd435bc37d73c09d05f2fd71321111a767c2b0d446f90dd4a186839c694ceb734e027e7ee948f0f63e4d3f1656d3d543df23c342a599306909b347109
+Y = 01f4c98ac03f0718e58d5d1762c920445b11dbdd60ec7f60095809204e14965a4ecb0be6fea06adbac8ba431d6f144c75c199225df2a619a34be99897125b3a10af8
+Digest = 06d4fd20efb2a725626550c8097bd7b38dcadf64ee36350ce8e47a24
+K = 00401187c8b89945a1e48cda9ee52167789f4121e67482a7ac797899f5d3d2e623aed31e4adae08a8d43e69028fa074d2650317cbc765f6ed191cf0317b4bae57881
+R = 01e572afed754016fba43fc33e352932c4db65efcb84e2bd159b40fc5925893b161effc40240be28d8c07154d2615f605c6f0451b976522d95afd37f46602df7a12a
+S = 0030370c1c5352c2b663ac1858b42f69545b2f58ed5b2c007f303726977d3c756b5d644ec6788f94c886f78269aa190a3d8d1ae10e4fd24d937c4556fb9e1953fd6d
+
+Curve = P-521
+Private = 0198681adbde7840d7ccd9cf1fb82056433fb4dd26bddf909af7b3b99da1ca2c05c8d4560ecd80ba68f376f8b487897e374e99a9288ed7e3645cc0d00a478aae8d16
+X = 0057ce3777af7032f1f82308682e71fe09f88bf29dacd5018a725e1caa4b1e2bfdd894fe618f9266f31ba089856dc9c1b70e4a2faa08b4b744d1aafcd5ae99e2c736
+Y = 0199bcfef2021bc5890d7d39ec5dc0c26956801e84cae742cf6c50386eb289b6e97754dd25a94abf81f1cb1b36935b5eb29f4b32a6516d2ff6a7d23064a0daec94b3
+Digest = 8c7db2e1a2ba5f8bd0a4f7e7f67a20918a87bc6c6462c326406e6c4e
+K = 019d2d74ad8ee2d85048f386998a71899ef6c960b4ab324e5fd1c0a076c5a632fd0009500076522e052c5c9806eef7056da48df6b16eb71cdf0f1838b0e21715fce0
+R = 018ecacbcffd5414bbb96728e5f2d4c90178e27733d13617e134ec788022db124374bbaa11e2c77fe3f38d1af6e998e1b0266b77380984c423e80ffa6ff2bcafd57a
+S = 01c727f34b6a378f3087721a54e9796499b597ecf6666b8f18312d67e1190a8a66e878efc2367b551267494e0245979ef4deed6d2cbf2c3711af6d82ccfeb101a377
+
+Curve = P-521
+Private = 008c4c0fd9696d86e99a6c1c32349a89a0b0c8384f2829d1281730d4e9af1df1ad5a0bcfccc6a03a703b210defd5d49a6fb82536f88b885776f0f7861c6fc010ef37
+X = 0164ac88ed9afe137f648dd89cdd9956682830cac5f7c1a06d19a1b19f82bb1d22dfeefea30d35c11202fed93fd5ce64835d27c6564d6e181287fa04a2d20994986b
+Y = 005cb83669265f5380ccefe6b4f85fdf0049e6703f6f378a0b2e52ed0fbbcf300afebb722f4ed48e3819cb976c1d60e2ba05646b478f6dfecfbae730e9644c297f00
+Digest = 4ff99d232c8fef39fecfe8af79d274e03beb4502fb833d8af4181d7b
+K = 0189801432cba9bf8c0763d43b6ec3b8636e62324587a4e27905b09a58e4aa66d07d096dbce87824e837be1c243dd741f983c535a5dd2f077aac8beee9918258d3cb
+R = 00917723f7241e8dc7cd746b699ab621d068dd3a90e906aaf0a4862744b96fd4e5ccdb9c7796c27f7196e693d06ec209464c3ea60ad6313e9b77cceaa14767e6651c
+S = 00957b0ecdc3668f6efa5d0957615bcfffd6419c5e57579b74f960f65ae3fb9e8284322ff710b066f7e0959ac926d3cf9a594bdb70bbec756c96910b26a2486dee9e
+
+Curve = P-521
+Private = 01466d14f8fbe25544b209c5e6a000b771ef107867e28ed489a42015119d1aa64bff51d6b7a0ac88673bbc3618c917561cff4a41cdb7c2833dab5ebb9d0ddf2ca256
+X = 01dc8b71d55700573a26af6698b92b66180cf43e153edadb720780321dbb4e71d28e0a488e4201d207fc4848fe9dd10dcabec44492656a3ff7a665fe932445c82d0b
+Y = 01920b16331b7abeb3db883a31288ef66f80b7728b008b3cc33e03a68f68d9e653a86e3177bbc00014fa5ea4c1608c0d455c2e2ac7bd8ab8519ebf19955edf1baf8d
+Digest = c1120fe21c2c40b47a97c9815c619a223c2f11fb2ebb5e87cb175280
+K = 0160d04420e0d31b0df476f83393b1f9aff68389cc3299e42ef348d97646f7531a722b66ddfb9501bbb5c4a41d84c78be7233b11489bceb817d23060e6017433fab8
+R = 008077aabd0a342f03f912007c586cfedfc63f93d1118f720d5b62b3ce141a60f86f111dfd8fc2e31a6778981f1a5e28f29a7369bd7897bb41240c8d3a9c170e0ee0
+S = 000abc75fc154b93840579457820957e89d1260fee0a4b9bb1946f61ca1e71afd76bb5e1077b3e38ceb39d1fac5ef8b217c4110617b3ad118e02b3fcc2a39ef38613
+
+Curve = P-521
+Private = 001a99fcf54c9b85010f20dc4e48199266c70767e18b2c618044542cd0e23733817776a1a45dbd74a8e8244a313d96c779f723013cd88886cb7a08ef7ee8fdd862e7
+X = 01912d33b01d51e2f777bdbd1ada23f2b1a9faf2be2f2a3b152547db9b149b697dd71824ca96547462e347bc4ef9530e7466318c25338c7e04323b1ba5fd25ea7162
+Y = 00bbe9b1e3a84accd69b76b253f556c63e3f374e3de0d1f5e3600fc19215533b2e40d6b32c3af33314d223ea2366a51d1a337af858f69326389276f91be5c466e649
+Digest = 08a10ee8d56db0cbc4bd68611f39f23d2ef379fe730eae170d84b388
+K = 014fafd60cb026f50c23481867772411bb426ec6b97054e025b35db74fe8ea8f74faa2d36e7d40b4652d1f61794878510b49b7b4fe4349afccd24fc45fec2fd9e9e7
+R = 018b1df1b6d7030a23a154cacce4a2e3761cc6251ff8bf6c9f6c89d0a15123baef9b338ada59728349ce685c03109fcde512ed01a40afd2ca34e1bc02ecf2871d45c
+S = 00a399f9b9e21aeddf450429fec2dc5749e4a4c7e4f94cee736004dcc089c47635da22845992cd076a4f0a01d2cc1b0af6e17b81a802361699b862157ad6cad8bd1d
+
+Curve = P-521
+Private = 01b6015d898611fbaf0b66a344fa18d1d488564352bf1c2da40f52cd997952f8ccb436b693851f9ccb69c519d8a033cf27035c27233324f10e9969a3b384e1c1dc73
+X = 0110c6177ceb44b0aec814063f297c0c890671220413dbd900e4f037a67d87583eaf4b6a9a1d2092472c17641362313c6a96f19829bb982e76e3a993932b848c7a97
+Y = 00f6e566c4e49b2ee70a900dc53295640f3a4a66732df80b29f497f4ae2fa61d0949f7f4b12556967bb92201a4f5d1384d741120c95b617b99c47a61e11c93a482d6
+Digest = bdcae2456898841b7d4dfe7309457bbcd51de792ef4942d5ea419926
+K = 01a88667b9bdfe72fb87a6999a59b8b139e18ef9273261549bc394d884db5aa64a0bc7c7d38a8ef17333478d2119d826e2540560d65f52b9a6dc91be1340cfd8f8f8
+R = 0015f73def52ea47ddb03e0a5d154999642202e06e6734ac930c1dc84756c67bbb1cca9f21f92d61bfdb2052c5dd2833349610f68139393d77250a7662ef7bd17cbe
+S = 0155c744a729f83b27d1f325a91e63a0d564fe96ff91eaa1bad3bff17d2abffa065d14a1d20a04dd993f6ed3260b60bcc6401e31f6bc75aaafe03e8c1a9cd14d2708
+
+Curve = P-521
+Private = 005e0d47bf37f83bcc9cd834245c42420b68751ac552f8a4aae8c24b6064ae3d33508ecd2c17ec391558ec79c8440117ad80e5e22770dac7f2017b755255000c853c
+X = 01a6effc96a7f23a44bf9988f64e5cfafdae23fa14e4bee530af35d7a4ddf6b80dcd0d937be9dd2db3adcda2f5216fecbce867ee67e7e3773082f255156e31358c2f
+Y = 01e7760190dfbe07ec2df87067597087de262c1e0a12355456faba91b2e7277050d73b924e14c0e93b8457a8b3e1f4207ce6e754274f88ad75c000d1b2977edc9c1a
+Digest = c7d69612a965f318f419e9e1c6fdbcce011e42bbbffc2ed4b3458036
+K = 018afea9a6a408db1e7a7bb1437a3d276f231eacfc57678bfa229d78681cbe4e800e6065332a3128db65d3aa446bb35b517dca26b02e106e1311881a95b0302d15e8
+R = 001c49b3c1d21f1678bdbe1ac12167e95e06617190bdee1a729c1c649210da19e2e210f6689e1310513bfe2ac6c0f4ee5f324f344b31b18df341eaadb826d07adc9b
+S = 0129d4931ba457443012f6ffecd002f2abc3a4b65a58fee8457917ebcf24b29a1d3055b7fc62939a74ebb0c3582172ee7c3c75e0b2fa2367c6e04df63a7a91d593ad
+
+Curve = P-521
+Private = 01804ab8f90ff518b58019a0b30c9ed8e00326d42671b71b067e6f815ac6752fa35016bd33455ab51ad4550424034419db8314a91362c28e29a80fbd193670f56ace
+X = 00a79529d23a832412825c3c2ad5f121c436af0f29990347ecfa586ce2e57fd3c7e0624d8db1f099c53473dbc2578f85416ad2ac958a162051014fb96bf07f9e1d17
+Y = 017c0750f26df0c621d2d243c6c99f195f0086947b1bf0f43731555f5d677e2d4a082fb5fe8da87e1592a5fa31777da3299cede5a6f756edf81c85b77853388bb3ab
+Digest = 7131ff8c846ed0de577806cc5e57f3bc896865a1994a17101fc1d254
+K = 0042d7c36fec0415bc875deb0fab0c64548554062e618aee3aa6670ffd68ab579fe620d3a9316357267fd3111c0ed567dca663acd94b646d2ba0771953cd9690ef42
+R = 00d01dfbef126febbdfa03ef43603fd73bc7d2296dce052216e965fed7bb8cbbc24142bfcddb60c2e0bef185833a225daa0c91a2d9665176d4ad9986da785f4bfcf0
+S = 016627e2614dbcd371693c10bbf579c90c31a46c8d88adf59912c0c529047b053a7c7715142f64dcf5945dbc69ff5b706c4b0f5448d04dd1f0b5a4c3765148bf253d
+
+Curve = P-521
+Private = 00159bff3a4e42b133e20148950452d99681de6649a56b904ee3358d6dd01fb6c76ea05345cb9ea216e5f5db9ecec201880bdff0ed02ac28a6891c164036c538b8a8
+X = 012d7f260e570cf548743d0557077139d65245c7b854ca58c85920ac2b290f2abfeccd3bb4217ee4a29b92513ddce3b5cbf7488fb65180bb74aeb7575f8682337ef5
+Y = 017560186230c7e8bff0bffce1272afcd37534f317b453b40716436a44e4731a3ec90a8f17c53357bc54e6ff22fc5b4ca892321aa7891252d140ece88e25258b63d5
+Digest = 3bd7a8f543e3bc2a56be31f437e5917cf18abc84da11bded6c352921
+K = 014b8a30f988cefdc0edec59537264edb0b697d8c4f9e8507cf72bc01c761304bd2019da1d67e577b84c1c43dd034b7569f16635a771542b0399737025b8d817e1c3
+R = 00fc50939ebca4f4daa83e7eaf6907cb08f330c01d6ea497b86becda43dfcad47cb5c48f5eb2cc924228628070bcd144088c449a7873242ba86badf796097dbecd6d
+S = 00ccb6463c4301ba5c043e47ed508d57dd908fd0d533af89fd3b11e76343a1cf2954ce90b0eb18cbc36acd6d76b3906612d8a0feec6ebed13d88650ed9c708b28a11
+
+Curve = P-521
+Private = 017418dfc0fc3d38f02aa06b7df6afa9e0d08540fc40da2b459c727cff052eb0827bdb3d53f61eb3033eb083c224086e48e3eea7e85e31428ffe517328e253f166ad
+X = 000188366b9419a900ab0ed9633426d51e25e8dc03f4f0e7549904243981ec469c8d6d938f6714ee620e63bb0ec536376a73d24d40e58ad9eb44d1e6063f2eb4c51d
+Y = 009889b9203d52b9243fd515294a674afd6b81df4637ffdddc43a7414741eda78d8aa862c9cbbb618acec55bb9a29aac59616fc804a52a97a9fc4d03254f4469effe
+Digest = 83fd2803e0faa52a4bc5ff9549ed9f68531da5acf81a5bb6e23016a4
+K = 01211c8824dcbfa0e1e15a04779c9068aed2431daeac298260795e6a80401f11f6d52d36bcee3cfa36627989c49d11475163aa201d2cd4c5394144a6bb500bbaf02b
+R = 01d59401b8ac438855d545a699991142685077a409de2418c7ccfe01a4771b3870e76287a9654c209b58a12b0f51e8dc568e33140a6b630324f7ef17caa64bf4c139
+S = 0143af360b7971095b3b50679a13cd49217189eaee4713f4201720175216573c68f7ac6f688bfe6eb940a2d971809bf36c0a77decc553b025ed41935a3898685183b
+
+Curve = P-521
+Private = 01e8c05996b85e6f3f875712a09c1b40672b5e7a78d5852de01585c5fb990bf3812c3245534a714389ae9014d677a449efd658254e610da8e6cad33414b9d33e0d7a
+X = 007d042ca19408524e68b981f1419351e3b84736c77fe58fee7d11317df2e850d960c7dd10d10ba714c8a609d163502b79d682e8bbecd4f52591d2748533e45a867a
+Y = 0197ac6416111ccf987d290459ebc8ad9ec56e49059c992155539a36a626631f4a2d89164b985154f2dddc0281ee5b5178271f3a76a0914c3fcd1f97be8e8376efb3
+Digest = 53e6537cb6ea68ae47a81611c22756d770d7a37e336c3af0b0814b04fa39434b
+K = 00dc8daaacddb8fd2ff5c34a5ce183a42261ad3c64dbfc095e58924364dc47ea1c05e2599aae917c2c95f47d6bb37da008af9f55730ddbe4d8ded24f9e8daa46db6a
+R = 009dd1f2a716843eedec7a6645ac834d4336e7b18e35701f06cae9d6b290d41491424735f3b57e829ad5de055eaeef1778f051c1ee152bf2131a081e53df2a567a8a
+S = 002148e8428d70a72bc9fa986c38c2c97deda0420f222f9dc99d32c0acba699dc7ba0a2b79ce5999ff61bd0b233c744a893bc105bca5c235423e531612da65d72e62
+
+Curve = P-521
+Private = 00b65bf33b2f27d52cbfabcadce741e691bf4762089afd37964de1a0deda98331bf8c74020a14b52d44d26e2f6fa7bcddbe83be7db17a0c8a1b376469cf92c6da27c
+X = 010038bb9a7aea626de68c14c64243150e72c69e2f8a1ab922bfbdaa6f33d24fb4542c0324357b0dd640bbcd07632ecd253f64ca2bfbfbf3de9b24fffd0568ab82da
+Y = 00faf867d95308cc36d6f46844a0f535dc70f9768eed011a2464d2f308fa1d8e72c3616aec7e70516908183ffce7fdd36984a15f73efaa3858c2edf16a784d40e6c2
+Digest = 40aef13bb7192a564d72ba58f7efad15635248eca49619b4182bf6f979842d6f
+K = 014aeb96c57d99677a1f5e4588064215e7e9af4027bfb8f31ff6126dbf341b8e6f719465e4273e91ba32670feca802549808322b7ee108bb20653cf20f93284d365f
+R = 0075ead62edf7d86c5d1bc2443d1aeb5dc034fd999e6ea012cef7499d9d050cd97d262095884e9fc89a42e15bd3dee80fe3c1ba10f4caabc4aabb86347023028b663
+S = 0129a992a6ff66d41948d11fa680f732b1a74315b804c982805190ed9d2fae223f2b149980b9241998cdea0c5672595a8a49d5186a0ef7a46c0a376f925bdda81726
+
+Curve = P-521
+Private = 002c4e660609e99becd61c14d043e8b419a663010cc1d8f9469897d7d0a4f076a619a7214a2a9d07957b028f7d8539ba7430d0b9a7de08beeeae8452d7bb0eac669d
+X = 00fb3868238ca840dbb36ecc6cf04f5f773ea0ab8e8b0fdcf779dc4039a8d7146a417504e953c0cb5e7f4e599cc2c168deda8b7f16084b5582f89f2ece4cae5167f7
+Y = 01f90b5c15eeda48e747cf3ee8183166a49dbfac6161cbd09d29d40a6854f4c495e88a435892a920cdaad20d41985890b648badd4f0a858ffcbd9afdfc23134ede18
+Digest = 6fd829bd5fc68d7a36436284c1282e3fae76ba44c5babcee423142c1cf2b52c4
+K = 01f875bbf882cd6dd034a87916c7b3ba54b41b2ea2ce84ebaf4e393fcf7291fee09dec2b5bb8b6490997c9e62f077c34f0947fe14cec99b906dd6bf0b5d301e75ca1
+R = 007aa70425697736b298233249f5d0cf25c99e640c9ff88035ef1804820e1bfe7d043755f02d7a079494f7fa6dc26740c4e6b7b430c63f29c67bbd3a5c88d2f0e8d1
+S = 00e0d42e4ff11cf5be37a9fda348514d5097a662f214687cbfb28ff42d635b13029871ca4f464bb1fbce02d5da4d5fb61b2a071844259fc863d136197bec3a61e7c7
+
+Curve = P-521
+Private = 017c3522007a90357ff0bda7d3a36e66df88ca9721fb80e8f63f50255d47ee819068d018f14c6dd7c6ad176f69a4500e6f63caf5cf780531004f85009c69b9c1230c
+X = 013a4bea0eed80c66ea973a9d3d4a90b6abbb5dee57d8affaf93390a8783a20982eba644d2e2809f66530adeeee7f9a1da7515447e9ba118999f76f170c375f621f7
+Y = 012f9dfaee40a75d8442b39b37a5c19ea124b464236e9b9a31bae6780cfd50f7ea4a700154b5ea0feeb64e9b35a1b0e33e46900cca1f34d13bb17e5017769841af27
+Digest = 902b55b79c29c0de27386e4fadb3469fc124f1225ad0fac06bd4a3a1e351c09e
+K = 018388a49caeda35859ef02702c1fd45ff26991998bd9d5e189c12c36cdae3f642ddd4a79561bd1d3e1cd9359de8f5c9e1604a312d207a27b08a6033f2741794ced5
+R = 015c6264795837dfea19f91876455f564f073c5c84a3c9d76e67872ae0447ba0d4850d8721302b25bec7ebfedd2721de140b2f3dead547042b24b0876117e7093cc1
+S = 0060eb74236c189a28ed20bd0822eb22d75f7d97c9043a3c8e3f6d4c90bc8ca02ac4d37c1171c799a1c7dfd2fcbf83406b5e48c051e0fbf0fd937bfe6c3db4e18154
+
+Curve = P-521
+Private = 00c4dad55871d3bd65b016d143ddd7a195cc868b3048c8bbcb1435622036bdb5e0dec7178ca0138c610238e0365968f6ddd191bbfacc91948088044d9966f652ff25
+X = 0014858a3b9bd426b678fdcf93fc53d17e7a9e8fe022442aaaba65399d12fd3a6a381958fb0f07ac6088f4e490506ec0f1ab4d0dbd461126f7eb46ff69cfa8bd88af
+Y = 018c18ce29ecc6d79d26a2de0cd31c4b32e84b5e90f6ba748f86c5afbd89618aceb9079460cbd1a8261ed5476973e61bf1d17ea78b022387443800c9247d21dde550
+Digest = 99a83d5d6471963d9e18b105e51662dce360f34f23b8d64be47d50e9f8afa4d9
+K = 005577108f4187a173e5c29e927a8fc8f5ffd37e184254a6e381ff1018955aec91a35f30085e8cee6a7555c10f9efdce26d62f2b4b52dfdbaeafc3a30983e2d50d5b
+R = 00344375ae7c804cbe32ced7a20976efae5d9c19eb88b6e24514d1d0cfb728b0f4601098b18b2e98f42b5222dd5237d4d87767007bf5acb185c5526d72047e2cb1a1
+S = 002de4cfa908c73c1102d6fb7062baf54a056a9517701e036c9c51e09899d60051612d59348945f845dffebec5aa395b2fac7229929033615788777306ccad96d0a3
+
+Curve = P-521
+Private = 003d4749fadcc2008f098de70545a669133c548ce0e32eec1276ff531bcff53533144555728ad8906d17f091cc0514571691107350b6561858e90dbe19633aaf31bf
+X = 010fe5986b65f6e65d13c88c4d2aed781a91026904f82129d46779bdadaf6b733c845a934e941ab4a285efdea9c96ecc9dc784d87e4d937b42c337b3a9cb111a9600
+Y = 0077853768a2a4d6f596f57414e57ec60b76d3cd5ece8351cd1f335ebcb8801a3d91fb82c65caaeb5c31eea9918367bb5906863ff3ccaf7a6cee415e0d75c15ac2e0
+Digest = 2c92465f323f6355ff408e42196e2de9a47807877ec02c9a7686917d3aa166a4
+K = 01fbb4de337b09e935a6dc6215ffcfcb85d236cc490585e73251a8b8bac37cfa36c5d1df5f4536d33659be1e7a442529a783452f7efda74a4f661b6a127f9248aaf7
+R = 009d8f10eeff6178594c89d6e8184f9502117384813243ddf9ccf3c8eac5dc6502c472dfc1487a5caffc569f7dedd14a8ebcb310e9bacdb79fb6655aba026cdf87f2
+S = 00f74236c7915d638708d17c9f10e39dda358faf9bbb821d8dcda0d151aac143bfb165ad0a23a65cd3de532e32cad928728f5ae1c16f58fc16577f3ca8e36f9e708b
+
+Curve = P-521
+Private = 0096a77b591bba65023ba92f8a51029725b555caf6eff129879d28f6400e760439d6e69ce662f6f1aecf3869f7b6057b530a3c6ff8ed9e86d5944f583ee0b3fbb570
+X = 00fdf6aed933dba73913142ef8bdcd4b760db8500831cd11d7707ab852a6372c05d112a1e7fbc7b514c42142c7370d9f4129493cd75cc6f2daf83747078f15229db6
+Y = 00ef91dffb3c43080a59534b95ca585ee87f6145f6a0199b2b82c89f456d8bd8e6ac71c78039c08177184484eb2ebd372f189db3a58fab961a75a18afec1ee32764a
+Digest = 17baaa5a7f97f2d17545c4baa468f36ef22b1945ea889b63b027806f5b1b7f90
+K = 013aa7b0471317a2a139c2f90df1c40d75e5a8a830fbaf87030fffdb2ef6f2c93d1310c9ed7fe9d7bcd4fe46537ff2495bc9c4f0aaff11461f5e4bebbfbce9a8740a
+R = 01c7a21800962c91d4651553633b18612d931bb88bff8b743ed595b4e869437e50f8e84fbf334c99061db123a1c40b73b07e203790561a37df65a660355ba2017d78
+S = 01301e1782559a38f1ca0eebe9bed0f5c7c33103d506a24f8a688f500ee1fe37f97b6685319279e82e6fe43cfd823ccbc123309974cffa76c4f8d41ec02a3cbc45f1
+
+Curve = P-521
+Private = 0015152382bfd4f7932a8668026e705e9e73daa8bade21e80ea62cf91bd2448ebc4487b508ca2bdaaf072e3706ba87252d64761c6885a65dcafa64c5573c224ae9e6
+X = 000b8c7c0186a77dc6e9addd2018188a6a40c3e2ba396f30bbd9293dba2841d57d60866b37f587432719b544d8bf7eb06d90a8c0dc9c93b0c53d53b2f667077228ca
+Y = 01dd2e5c73ab908ae34f701689f1cd3cf5186d3a2bc941e208bf3ef970e5e429ee9b154d73286b2e5da423e75b7c7b78c7bdf915da92279db43265a0cdefca51f86a
+Digest = b8f56952078ffcf04cd9815c6b06b63812eee9d682495d7172fd3677abe1c2db
+K = 00d03506999f5cc9ec3304072984a20a9c64a22ad9b418495ca904f4bbddc96e76d34672cb52763339d3f3bc5b1701c00a675b972797e3a086314da1a8d338436566
+R = 0085406c0ff5ec91f598bb579ad8714ad718c3e133d5dcc2e67c5d2339c146b69919cac07f3bc2bda218f4c7c8be04855e2ca6fff7fbdc4fc0fda87c8c3081cad4f5
+S = 01b45f2066e583636215ae135afc202b8bf3f301eccff2e1c0198b9aeddf695fa8179488e7b622fc307f601e2f6551815117cc836bb09ef888f8e64a45d9c84ad30c
+
+Curve = P-521
+Private = 01750ff0ca0c166560b2034bc5760fe0b3915340bc43216e9de0c1d4a76550e8b2036e8b874230f8d29354aed43e183610f24fd4abd4b0be2f111dae942bd7a121f7
+X = 01b4b8947192a7c0166c0e0b2791e217370836283e805f3ee11cfb78445aba3c5bc39fe594e01916617ad59e7c8e740d8f2d07d88905d3f33bd5e51aafd4943c5dc6
+Y = 01175d117232836c28e717ce2a55e59f4ec550effde30d18e3d99e42c6aa2283c7b3e7f2f6ff1fca605dde78c3a5bffa689347b4c93f51ba59a1787bb7d5e43861dc
+Digest = 9477d884384f80b528aa4c3408b7f7d0dc59bd3f678466b122d48a42c01fc3bd
+K = 0023645023d6bdf20652cdce1185c4ef225c66d54f18632d99ccf743bf554d04c214c88ce52a4f71ec75c899ad1b3c07c34112ca20b55c217ff1d72c9528e2774ce8
+R = 01e933f68ce0f8403cb16822b8e0564b1d39a35f27b53e4ae0bcdff3e051759464afbc34998ba7c8a7ee34ef6c1aaa722cffe48356fd0b738058358d4c768b3186c1
+S = 00a67368a305508ce6d25d29c84f552a4a513998990fef4936244f891a2909c30d5fdc9e8a267ecbf3c597138f4a08f7e92bee57d5420eadd700fee864bf78b2614b
+
+Curve = P-521
+Private = 0023048bc16e00e58c4a4c7cc62ee80ea57f745bda35715510ed0fc29f62359ff60b0cf85b673383b87a6e1a792d93ab8549281515850fa24d6a2d93a20a2fff3d6e
+X = 00ba3dc98326a15999351a2ec6c59e221d7d9e7ee7152a6f71686c9797f3f330d3150123620d547813ba9d7cc6c6d35cc9a087d07dff780e4821e74ad05f3762efd6
+Y = 018b051af9824b5f614d23ecadd591e38edbfe910ad6cbebc3e8a6bec11ea90691c17deb3bc5f34a4a3acd90b7b10f521f6ee7b3cfbfdc03b72d5a8783a4a77c3e4c
+Digest = e995003b47e16fcdc7487e2fe3b715b707e5c8d1246de04172a3002b140dddac
+K = 006099d2667f06c58798757632d07d8b3efbe9c1323efb0c244be6b12b3b163ba1b7cf5246c98dcc0771665a66696d687af5f28ed664fd87d5093df6427523d4db84
+R = 010dc80ea853064a2ba5a781f108aca3785c5ec0aa45aa05ba31d4de671170797589e863d54a3a986aadf6f670277f50355713dfb27d4ec7e348f787910b3cd668cd
+S = 0018572bfad4f62e3694d1f2e6ffd432faed2e2b9d7e3611a07138212f1e79e6c394839f7cfae96bc368422630016fb9346681eadc5f9699e7331c3b5fde6d65e4c6
+
+Curve = P-521
+Private = 002b8b866ce4503bb40ffc2c3c990465c72473f901d6ebe6a119ca49fcec8221b3b4fa7ec4e8e9a10dbd90c739065ad6a3a0dd98d1d6f6dcb0720f25a99357a40938
+X = 01b8c7a169d5455f16bfe5df1ba5d6ec9c76e4bad9968d4f5f96be5878a7b6f71d74bfac0076dd278bc4630629f3294646f17d6b6c712b0087e2c4d576039cfdc8b9
+Y = 018faffd5422dfd1b61432fa77b9a288b2b7d546656c0dcca3032179e6f45ee3cf61d6a447fc51731cb54457343a41569fcf78cef42895f4da5efcb14ea1fc065f8d
+Digest = ce977a38b4c4db0c74fb5d0bfda5818719fb4bec00412f235c48c99995510c55
+K = 00ac89e813f94042292aa1e77c73773c85cf881a9343b3f50711f13fa17b50f4e5cb04ac5f6fc3106a6ef4c9732016c4e08e301eefac19199459129a41a7589e0628
+R = 005bc7a253a028ee8b7253979b8d689d41d8df6fae7736341f22e28b6faf0cbbdebbd2ef4d73e56d2021af2c646dc15539a7c1e1c4dc9c7674808bd7968d8a66f947
+S = 00fd71575837a43a4cf1c47d0485cfd503c2cf36ebcea0fdef946ad29acb7fb2e7c6daf6b4eb741eb211081aed6207d02569f1518988f275ad94c7fd4735cb18a92e
+
+Curve = P-521
+Private = 00a43b32ad7327ec92c0a67279f417c8ada6f40d6282fe79d6dc23b8702147a31162e646291e8df460d39d7cdbdd7b2e7c6c89509b7ed3071b68d4a518ba48e63662
+X = 0172fb25a3e22c2a88975d7a814f3e02d5bb74cfb0aaa082c5af580019b429fddd8c7f9e09b6938f62e8c31019b25571aaceef3c0d479079db9a9b533ee8e1670abd
+Y = 00ff5516223b6cc7c711705f15b91db559014e96d3839249c5c849f2aced228a8998177a1e91177abbb24b57a8ea84d944e0c95da860ae0925f1b40c0e1b7c9e0a46
+Digest = 35156a6da83777e4bb100c48cd11dafc0e2e0bbe5c985faa57a6da61fcf31236
+K = 00383eda042e06c0297fbd279a2ad40559c5c12ad458f73458eebcc92b308d3c4fcec20a5b59f698e16fa6ea02dba8661b6955f67c052f67b0a56460869f24cfdf7d
+R = 01b9c35356b9d068f33aa22a61370dae44a6cb030497a34fb52af23c6b684677370268f06bb4433be6795a71de570088aec17ce0c9933d2f76c7edce7f406f62fedd
+S = 006f07ea453cfa20ad604ba855332f62834657b0b795684d50c1562a675456e37f4dae45f0df47d8e27e47bc9ce9c9cbba1554c5b94b0b17401b73c8d0c0902c6cc4
+
+Curve = P-521
+Private = 003c08fdccb089faee91dac3f56f556654a153cebb32f238488d925afd4c7027707118a372f2a2db132516e12ec25f1664953f123ac2ac8f12e0dcbbb61ff40fb721
+X = 0193301fc0791996ca29e2350723bd9aa0991ddbb4a78348ee72bdcd9ed63ce110ba3496f2ce0331b5c00d4d674c1b70114e17ce44a73c3e16bab14ed1ee924202e4
+Y = 00aea9b288cfb2933ec0a40efa8e2108774e09b3863b3193d0dac6cc16ccaa5bd5f9ce133aec5cd3b62cbaeec04703e4b61b19572705db38cfaa1907c3d7c785b0cd
+Digest = afe33dce77cc747ec0a7f4835740be3bbe3faa1c3b02b10afdfc40a28dae61aa
+K = 00d0e90d5ee7b5036655ad5c8f6a112c4b21c9449ca91c5c78421e364a2160bbac4428303657bc11ea69f59fb0fe85a41b8f155a362343094456fd2a39f2a79e4804
+R = 01a8c23a2965d365a4c2ffd0802ae8b3a69c6b84a1ba77fd8a5f2f61e8ec3a1dcb336f136e2a997252eaa94caf9b5ad6c9ecff5bf33abf547ca84985bb89908a11d7
+S = 01cc42a2dd97aa42b9df5ea430e0d4cb13106dd6da6e8c9315c96ed7b052db365bbde6960c9a965954a4398c18ea7db9593bbfc3c3b6b3466ff806fccac3de6424ab
+
+Curve = P-521
+Private = 00969b515f356f8bb605ee131e80e8831e340902f3c6257270f7dedb2ba9d876a2ae55b4a17f5d9acd46c1b26366c7e4e4e90a0ee5cff69ed9b278e5b1156a435f7e
+X = 00fc7ae62b05ed6c34077cbcbb869629528a1656e2e6d403884e79a21f5f612e91fc83c3a8ac1478d58852f0e8ba120d5855983afd1a719949afa8a21aec407516c3
+Y = 00aa705da6459a90eaa2c057f2e6614fb72fc730d6fdebe70e968c93dbc9858534768ea2666553cd01db132331441823950a17e8d2345a3cab039c22b21bfe7bd3b9
+Digest = ff76d5393d73d021b9dce99b394b6a6b4d9c34ff74d68a2406319c48bbe6743d
+K = 019029260f88e19360b70c11107a92f06faa64524cfbd9f70fecf02bd5a94f390582a7f4c92c5313bb91dc881596768d86f75a0d6f452094adbe11d6643d1a0b2135
+R = 007f2158e9b9fa995199608263969498923cf918fdc736427c72ce27ce4a3540dce2e8e5e63a8fc7ba46f7fa42480efbf79c6ed39521f6e6ec056079e453e80a89d9
+S = 008e349eed6f1e28b0dbf0a8aeb1d67e59a95b54a699f083db885f50d702f3c6a4069591afaa5b80b3c75efb1674ebd32c7ead0040d115945f9a52ee3a51806cad45
+
+Curve = P-521
+Private = 0013be0bf0cb060dbba02e90e43c6ba6022f201de35160192d33574a67f3f79df969d3ae87850071aac346b5f386fc645ed1977bea2e8446e0c5890784e369124418
+X = 0167d8b8308259c730931db828a5f69697ec0773a79bdedbaaf15114a4937011c5ae36ab0503957373fee6b1c4650f91a3b0c92c2d604a3559dd2e856a9a84f551d9
+Y = 019d2c1346aadaa3090b5981f5353243300a4ff0ab961c4ee530f4133fe85e6aab5bad42e747eee0298c2b8051c8be7049109ad3e1b572dda1cac4a03010f99f206e
+Digest = e40ae6e430f07950c186100e20048cc62bf56be6a818ad660785bdaf3bcc0c25
+K = 01a363a344996aac9a3ac040066a65856edfb36f10bb687d4821a2e0299b329c6b60e3547dde03bdbd1afa98b0b75d79cf5aac0ef7a3116266cadf3dfbd46f8a4bfc
+R = 01ff097485faf32ce9e0c557ee064587c12c4834e7f0988cf181d07ba9ee15ae85a8208b61850080fc4bbedbd82536181d43973459f0d696ac5e6b8f2330b179d180
+S = 00306dc3c382af13c99d44db7a84ed813c8719c6ed3bbe751ead0d487b5a4aa018129862b7d282cce0bc2059a56d7722f4b226f9deb85da12d5b40648bf6ec568128
+
+Curve = P-521
+Private = 0095976d387d814e68aeb09abecdbf4228db7232cd3229569ade537f33e07ed0da0abdee84ab057c9a00049f45250e2719d1ecaccf91c0e6fcdd4016b75bdd98a950
+X = 013b4ab7bc1ddf7fd74ca6f75ac560c94169f435361e74eba1f8e759ac70ab3af138d8807aca3d8e73b5c2eb787f6dcca2718122bd94f08943a686b115d869d3f406
+Y = 00f293c1d627b44e7954d0546270665888144a94d437679d074787959d0d944d8223b9d4b5d068b4fbbd1176a004b476810475cd2a200b83eccd226d08b444a71e71
+Digest = 9832832c49754bdeba2d3799cbf6437af28ad9f942d3f313abd320fad0897be6b446aa24f1b23a86ea54aef12b1f5c0b
+K = 00a8d90686bd1104627836afe698effe22c51aa3b651737a940f2b0f9cd72c594575e550adb142e467a3f631f4429514df8296d8f5144df86faa9e3a8f13939ad5b3
+R = 002128f77df66d16a604ffcd1a515e039d49bf6b91a215b814b2a1c88d32039521fbd142f717817b838450229025670d99c1fd5ab18bd965f093cae7accff0675aae
+S = 0008dc65a243700a84619dce14e44ea8557e36631db1a55de15865497dbfd66e76a7471f78e510c04e613ced332aa563432a1017da8b81c146059ccc7930153103a6
+
+Curve = P-521
+Private = 004ceb9896da32f2df630580de979515d698fbf1dd96bea889b98fc0efd0751ed35e6bcf75bc5d99172b0960ffd3d8b683fbffd4174b379fbdecd7b138bb9025574b
+X = 00e7a3d30d5bd443549d50e9b297aaa87bc80b5c9e94169602d9d43d6d0c490c0bed8cc2170288b106bdbf4c9f1ce53fd699af0b4c64b494b08520e57dc01ab9a8b0
+Y = 01d81056d37aec8a75d588f6d05977416e6f24ad0117a7f4450036d695612e7bc2771caed80e580314eebc88c8fc51c453f066e752481f212b57165d67f8a44f375a
+Digest = cca0c216abf3baaff0b0d8597bcfc7183835b4e3d025749a741a0e75d00845a341fe094214b1c39e13e8932a062c1ecf
+K = 0046639c5a3ec15afae5e4a7a418ac760846512d880c359bc2c751b199ce43b10887e861b14127809754dbea47f6cc0140d2817e3f5b9a80ce01abd81f81b748433a
+R = 00f913de91e19bd8f943d542ae357bacc942a0967abc9be6c06239a379db8cc733fa50013e0b0f088bce9d630262feaa33b30d84f91bcf5ce9976e4e740fcb112f84
+S = 008a73a5c9c24235e0d9cecaac653f68ce5a6fb186ce67fa058d6ddbbd4d0a8c4d194e571148e8ad6c8882b4e33d2f60fb23dd7d07a1ae60864e8277918f592b3dc6
+
+Curve = P-521
+Private = 000a8db566bd771a9689ea5188c63d586b9c8b576dbe74c06d618576f61365e90b843d00347fdd084fec4ba229fe671ccdd5d9a3afee821a84af9560cd455ed72e8f
+X = 004f5b790cbe2984b71d41af5efed6c6893d15e13f31816d55a9c2926a104eee66f1ada83115d1388551218773b8b9d1138e3e3f027bb4392c90c14fd232580b4a11
+Y = 00660eb160e9bfc8c5619e70e948e238c6fd37739bc1bb657b8e8436e63628f91992be7e63d9a7359623a1340642777b22026feb51116a6c50c54c3589b9bd39b6cb
+Digest = 0af6f685cb6c1219cb1627dd2b9099b70b1622d32b2342cbef6c0b9604d3f22360d595198af65579062dddccb66a56ce
+K = 01e7b5e53571a24bd102dd7ad44a4b8d8a4e60e5957bc3c4e5d3c73109f55233f072e572c7892f425ba5e64d3cb7966096bb34a47e26cd5b3e3b44108b310d9f681b
+R = 01a88bcd7e2bdff6e497d943dde432fb3f855a7177c466319cb53b701230c299db030276269685857d1e3f28110e690f2f529c8d18115eb381f313bc891d92ad278e
+S = 0146f1984ea879274dfd5e86ad92e564a4de081523ddbb1c397b8f9595911ef2e6501bc081584d5340f7aa47e1af036234ac6f27a5ac31f78dd3b0ff1a62693c630d
+
+Curve = P-521
+Private = 01a300b8bf028449344d0e736145d9dd7c4075a783cb749e1ec7988d60440a07021a25a3de74ea5e3d7bd4ab774d8ad6163adae31877ef0b2bd50e26e9e4be8a7b66
+X = 005055b9ad726ba8a48219b0ecbfffb89f8428de895b231f676705b7de9f2022d9ff4e0114ebb52dea342f9bf76b2fb060c020e29d92074ebb1fbfe5290a58c8bc10
+Y = 00415af7f20a6e945315adbf757316bb486c80780a0a3a15b4b9609f126d7341053a2b726ab63cb46feee527b0bf532b32b477e5671aea23d9b3c3e604b9029954b5
+Digest = b5008011397235faff9eda7ac9838dd1199eb52b2921d28407e5c356dcca7611184d29d268c16bfb489481a294bd7a43
+K = 005a2e92717bb4dab3ee76724d4d9c2d58a32b873e491e36127985f0c9960c610962ca1c4510dba75c98d83beebdc58b1d8678e054640951d11db1bd2d8a4ab8476b
+R = 0104a78ce94f878822daaf00ee527fbdbf6cceb3cbb23a2caa485e4109466de8910252f92379ab292cac8d1eda164f880c0067696e733fc8588a27703a3e1f5b8f1f
+S = 01ffe23e8ab5a31668a81161a234ea14879771fe9866f8872eb6edb672e0fe91d2bb75c9767a2dfbac7c15c802211236b22ea41ecd055a0b8b311ffc4255f86d5c67
+
+Curve = P-521
+Private = 006a253acd79912a74270fc0703ed6507ab20a970f2bc2277f782062092cf0e60ae1ca1bb44dec003169bc25ef6e7123dd04692f77b181a6d7e692e66b09d35a540c
+X = 01f15c6b1df156fdd8381cd7446e039435e445f8f36f0247475058da0e371bf72753f6e39f98066bc79370b038c39687ba18e16cb118fe6538b7568c5403c251f6b7
+Y = 012d2b4f46b854eeae75f1c63f55b76bf0c604d47f870c28a50ecdeb52bba1dd9a0ff12e680804ff864111207652da7dd10b49edf66bb86be00bc06672de91982457
+Digest = 64c05e43191b0313abd6514eb5a44dbf25befb232b8e928f92801f75a968d9a96801facc86b2174e0a5f247d9b5e7587
+K = 0165faf3727e42fd61345cfa7b93e55fb4bf583b24bdc14ce635b6c99dbd788012f14da9a210b677c44acdd851e672f1a48188d6b8946c0efeebfe8a597ba0090a2c
+R = 01ad9463d2759abd568626548578deefdcd8b2d050ce6d9c7ed05feca20167484b86e89bdcc936fd647e0f8aedd7b6add2b8cf13ff6ff013c2b5540c6c56fda97a0c
+S = 01645a7d0e11015256cfb034adca198695eea6aedd44d9fbf496850ccfed950f43fffd8dbf41e113f2d3837d8a5dd62b2ed580112ff05800b1f73196e5576810e15b
+
+Curve = P-521
+Private = 00d5a5d3ddfd2170f9d2653b91967efc8a5157f8720d740dd974e272aab000cc1a4e6c630348754ab923cafb5056fc584b3706628051c557fce67744ee58ba7a56d0
+X = 0128a4da5fc995678e457ceb3929adee93c280f851abe900fa21f4f809dafad4e33b381e0cd49ce8dd50e2e281cea162bfd60a1d6a1c0ee2228e6a011e171b559ab8
+Y = 006eb0917cd72256992c49ea527f6bb0315f13d8047794a0f1da1e93737703b1c2a74a00441ef3b47b6a2ff789c49ae32d91cabe7b29247aeec44f6c40a76597a2ca
+Digest = 9e4bf8293245611cb31caf0b0125117a4ef286ca3730f1519f3c95e65a5db326ead01b08e6b219281a26f2a41bda1e98
+K = 003269983a5c2bcc98e9476f5abf82424566b1f08b17204d29e310ece88f99eb677a537f86fe2529e409cfef2c12929644100099e0de2f27c0f0ac11105a4dca935b
+R = 01a5257ae1e8187ba954f535b86ff9b8d6a181a3b95c250d090cb4e9c3bfbd03aa64696a76c569728ef67780d6338d70ce46da40b87a3e49bfe154b93930890dfa93
+S = 005b6ccdfd5c63c7db76d3a0478064a2a376e0e050cb093be795a72a549247c2e4adba9183145c63d46479dbbdcf09986a6f64c09c7e16abc4853f6376c9558b014a
+
+Curve = P-521
+Private = 01bcedf920fa148361671b43c64e3186e1937eb1bd4b28cbd84c421472394552889bc05509aa732ef69d732b21b750523fdfd811f36467690fe94e01e64c9d5cbbe9
+X = 00d33c151d202a5d4d831348e940b027ee32e4b0b9b48d823a05c67ff3bdaee0189fc6680565f352c062e99968afc643208b4f9c7af185b861658a88c4ad0fcc8ba2
+Y = 00e4441ddb546468ad8ffa6074f137edfbb81e82e0e7d8f05c4c54598aa996a9cde54cb371f642bfdd4ae7eca5b769696030027129a4183da93567ad142a2dff5183
+Digest = 417e8611fe90382b134add3b3df5a963d95c4de28a5a5b215b7f96731db9350d4646c1efe7455d48a1a2de6b4fcbd9c3
+K = 0046e619b83aac868b26d0b3cbfab55e630e0b55c461985b5d00f94ff3a5ce90ff412cebf46bbd84550d2031d573ca27d924624428360708c8d8491c29eb01d30f2e
+R = 008427c0f0ac0263472cd423c0fb554bf3c851b9c775c566ab0f6878717bd57665830767b05b7789c5c0b078195bd943dc737325552d32877ecb04a7c41bd07cd80c
+S = 010bb6652d6a624c40a7dd06828f15774130d02369ceb1a7d03b553e16e17b7fa5b5401f15885d5e4fc2e55c0c7a1b97871ab02f76386b93a16aa6e7eb65debac6dd
+
+Curve = P-521
+Private = 003789e04b3a2a0254ade3380172c150d2fad033885e02ea8bea5b92db3f4adbab190ae423080a1154dfedec694c25eab46ce638be3db4e4cba67bc39f62d6e7db2d
+X = 01dbc2cf19627bdccf02432b1761f296275230c150cdde823ce3141ec315d7d05e16b2c29e2a67491078d5316883e933d85b4b10d4f64c477d3c4e0442dc928983a2
+Y = 007562e720807dd118d3d8b265b3abc61a71fce43e3dce0e7b5ae18b7a4cb01ecc00d39c1f22e150a9a8728997e502144f5b3f6fa9b4cb8a4136212b082ca394e3f6
+Digest = 297eed020ddcd03aeeafc77469caa105469205595ef22f64860126135e2596ae99ccaeb679d073cd9364b1e4ee2c4b60
+K = 00fbccd8d7804bdd1d1d721b5ec74d4ba37603bc306f9fce2ec241853d8e07334e6b4b12c4ecca0c54bd71193dd7146507933a20737c5f3e15085830fab9b30ca57b
+R = 0181915a3998d8fa214f9715f4ca928d09c36de168dc15c6970a8a062b5cea2dc969b2437ca17b684f78a1fd583aad8e6c762c8f4ab0c91b86a497145e3ca440d307
+S = 015a6c18c5c77f5470b27d061eafdc26b78561941a3b2ab0f5c81d40899fc053c3d9ed12d7d61e298abbae470009c7b2157731c58d7b16a66fa5abaf5e8a1b8ed394
+
+Curve = P-521
+Private = 0124700aa9186353e298edefc57bec0c7d0201cca10c1d80dd408d5d71040592b0ac59facdadfa8712445f5977ef8d4854022720c3f02d60e0732dbb2f171fcf1490
+X = 00c80fc4cecae5d53348524ddba6a160b735c75b22fdb39af17e2a613d09246e3bb0fd3f2978577f6db5d2118e05c7898024808f8eb8e021d7969cdcf7fc981200bb
+Y = 01a880c93943fd446d4b3923b574d2221c1bb7b645fb5534dda60e827b497666ff586b77921f7e7f605147947194cffd2fef0678880b89cc0bc7fb74fa96d4b112d7
+Digest = 39884fd5e7c8b6cb67836e257957cc11f6bd342f540bde745e0e4e55d3ead2ea080d8b2b2e96664056c50de0d7822f25
+K = 001a05238d595ded5c61d3bf6fde257dbf13095af8a5cb3a2e579e8e4c550fe31d12b71cc2dbcb295e6c4fd0fb8c22d1b741c097cc59d826ced1a8771f09983143c4
+R = 0132762bc81e9922a8d642e3a9d0218affa21fa2331cfcb9e452545c5981c64a8f7e4cc8e68056023b2aa78bead59061d19c7f646c931163a91e544b106b3be8de9e
+S = 00c3a1b0b000c3169984132add51d611e2cb7069a262a6983d2ae72b459c36e6469509bdb0f473600b8686700b08910779dee9ba83f82e755d4a4ef5f124eb09397f
+
+Curve = P-521
+Private = 01f532d01af885cb4ad5c329ca5d421c5c021883bd5404c798d617679bb8b094cbb7e15c832fb436325c5302313ce5e496f9513455e7021ffad75777a19b226acfa1
+X = 00c0bd76b0027b85bdd879052220da1494d503f6a4bb972105a48ae98e7dda8c2d9fd9336f5646385b961ef68e8464e3a95b00f96614b1a408ceaa2c87b077b6a8fb
+Y = 017eb7eb5c78db7819af92e8537d110d9f05a5e24f954f4dde21c224d4040f059ec99e051702f390413d2708d18f84d82998c61847475250fb844b20082cbe651a6b
+Digest = ac6b375afaad4c5c1b8e8aa5ac94e2aa1553e8f8603d16a86d573d53a4e6c5731f6d6c18ac732cfd3ae8aed75046c1f1
+K = 014e66853e0f7cd3300ebcae06048532e19cbb95bee140edc1c867ce7310637651445b6dfeb1d99d2e32f2ffb787ebe3fe35032277f185d3dad84f95806924550abe
+R = 00c5b3a57161098e2e8e16e0a5ae8ecf4a14df14927eea18ed4925d11dc429dda145159323ba970174b194b9b4608a8fa2373b7a825c5e8bd80574e49698285c2c82
+S = 01a0c038a51796158b42eb5b0dac37aff9ab93b903a47e06ebbdd15946e4bcc9a3b3875b18cf6294c33fc6c3693cef04ed1a43d08951e664c760e2cf3fb4e47490d2
+
+Curve = P-521
+Private = 011abf508bca68a85a54bc0659e77efad3c86112c9db04db2883e76144aa446918bb4bb0784b0b6a0e9aa47399fe3de5aaecfd8894a0d130bb0c366c40d9d5050745
+X = 005c0ea363a3a12633ea39d564587ebdd3a22a175ef32b9ebfc7311304b19cb3a62b5adc36f6afb6a6f7fabbf810ee89fdb72854fefd613e7798e9b9ff5938ea54c6
+Y = 00bd06a85e47b885c08124b55a3fcc07ca61647cda6efbfdbd21b24d1ea7a4c7300d46cd798e76063aa979adef6f0698b15e5b7ae8a2ab39ab4f50b2d20614db6317
+Digest = d59d1ff62ae0c4e41b3b8bfcb14f8d40b1774be1d9c6b44a60cb546a21e9f2ae5f4427d45f7fdd67e238ead3afa59c8d
+K = 019cadb8c7eb10565aa4567e0709873918720f0e4b42b4817afb0b0547c70cd1100229deae97a276b9c98ea58b01d4839fee86336d749d123b03e8b1a31166acc110
+R = 00667448a8bbef1c810d40646977dc22f3dfb52a4d80928ded5e976e199cbed02fbd5a08546756ece14548d721a6eb380d0e1a71ad0660dbcac6163c776eedd3e249
+S = 00ae7f0a238daaddb7fb4a1707fe5132daf653f8e19f732347134c96f1dd798f867c479a4a4609a568a15b61afed70790adbde13ac5f68c468d0230852c1a2c22581
+
+Curve = P-521
+Private = 018dbf520d58177e4b7a0627674d220137983f486dd2fd3639f19751804e80df0655db6afd829cdf75238de525e1a7a9f048049b593dd64b4b96cc013f970c05ea1f
+X = 018b872690c37995be324ddb5c2bd5462841bb062f8e63da248a853de79c3d6bb9a2eb1e6933afda0998ca43491cc807b08ace2d5336a43d0ab50563a2d3d98755f0
+Y = 0002ff31221aa32aa6546f35e8fe5b9361f938362a5e89e77ae130ba8bce3729e912dfac35a2fd21efe84b45b8be2a340850e4b574e1885b35c2afbe196b57c6cf4c
+Digest = 6985cfbbd8dbf28558ee181006d07193feb1225ac9dd46e5da122759daa9ced6fafdb95cc407c217d9f163d7c04aaa8d
+K = 0098faeb73054639cb2e4442cd68e7b3a13f4b3f397a7b26f303afa40789f8ddd3d918f1ce4f0be53c8cb69c380744e2297d7fc01e2b3daef4ce64dd3a2644234753
+R = 009c0e7649f814f70a8416cb78bc4601472a363fe97f5c587305778169677860dd97f87b5ab07c3a953bc4615fc34634509d6a25621bdded33ed42446d059509c190
+S = 0120b90e1cfb8a1b5e530df7b17d1128bc051ca4f1a65dd9c9d9d3c59d2f00c7c1e994c52b8671d40294b4d574d2c04475d5bebeacd3a0d3870a54dc7a4805614f40
+
+Curve = P-521
+Private = 0002764f5696aa813cd55d30948585f86288ae05aeb264ca157cd09e1d09a10515a849b0791b755ccc656a34707be9e52f5762d290a7d2bcd6de52c600ff862eaf4e
+X = 0127279c88719dc614db387f102e55104ea1c704ac7f57f3bca936f728439b76556730dd7cde2ac1ad0a4c2c2f036ab6f00cf34cb87ea36113571f300713044106d2
+Y = 0134a0786c31f5f2291b83c50fb579ae4c620b95e5a8bdc0c7e1ee6b996c89d764f1b20403e7faa203f397425ada297045dd8ba0e4b155d4900da249e934faab7991
+Digest = 67d285cfc8eaaedab30be810129fcf06da8b091fa7f4bc49752fd707fbf2a9cf8bc5c187db6f6191b838873fb55c9784
+K = 008bffb0778cbb06466cecc114b9e89ca243a2b2b5e2597db920bc73a8bbcbe3f57144ad33409ef7faaab430e13f4c42d304d11347360c84972ca20b1539cce3a288
+R = 01f8f504e64a502e51e7c129517931c3b71f0d8a63b19cfe01ff7c951c6525249608b3ef5d00061d77eb6b3d69581adeaa3732c773bbb9b919c3e7c71fdc09f44d06
+S = 0058044fc64b340604ffd02a5b2918d76fd6fb59ea895feab7aa218e6f1e8c8f226eb9ee345ef8140183a69272582005077b008006aab11597e808d7ff1e8382c924
+
+Curve = P-521
+Private = 01b0c9acd3eeb618b4b0de4db402206f0f29adc69d7ad324b6db6601b351f723ac8fe949eeacd34228649bf0126276e5aceb0137d00c30dd858aef2d6b6449de2e89
+X = 01811c8884486aaa083ddee1c51cb6e861cb830bd5eaa929f72efadbbd1286566ae7e7ba7fde7e02529900d35ee64591652d28798bfc1bed0d192602a9cf5a7d22e3
+Y = 006d7fc9dd494816cfd29613d4689af67f7d0a2e6fbad5d4d6e0130189172a1ab601c5ca71deaa8bfcb5a190d49da191672ff6fc048e146cb902acec5eae6d87e60a
+Digest = 10bb638f2f48a8696dca63275a35428adfd6ae154923c8a33f06d23e4fe4c42edff1f382ef09fc3970611d0806abd630
+K = 01fdc4f108070af3c66c9ba7b6c1f2603a19ceb4760399df81228cfc7eafde1082b5a0716a3ff82fbe84726f14dd0db3376ca184a78c3c60679bab6cd45f77f9b9ce
+R = 01ec310339ff056faeb341c4499c43782078b04be1725ae9a6cdcb6011c46d1a4eb3d75c358225e4ec142fd1cd344186f5eb597f7ba559ddfa954824365d5b6edaec
+S = 0005b679a33fdb7e04834f071cd0ac514c04add9f2614ab9bbd9b407b1420fed3f3e02a108e7e279899e43dcf64ae4083c289a87cd7d2103bdc036a95d36800ac7c6
+
+Curve = P-521
+Private = 0181e1037bbec7ca2f271343e5f6e9125162c8a8a46ae8baa7ca7296602ae9d56c994b3b94d359f2b3b3a01deb7a123f07d9e0c2e729d37cc5abdec0f5281931308a
+X = 00cfa5a8a3f15eb8c419095673f1d0bd63b396ff9813c18dfe5aa31f40b50b82481f9ed2edd47ae5ea6a48ea01f7e0ad0000edf7b66f8909ee94f141d5a07efe315c
+Y = 018af728f7318b96d57f19c1104415c8d5989565465e429bc30cf65ced12a1c5856ac86fca02388bc151cf89959a4f048597a9e728f3034aa39259b59870946187bf
+Digest = a02db3dbf881cbe8a90a27e6513d67bbf7b33a9d3d2a422ba1f4c42b7e21e0885dd86cb9a920f7c3571e8fbcd047ba23
+K = 009078beaba465ba7a8b3624e644ac1e97c654533a58ac755e90bd606e2214f11a48cb51f9007865a0f569d967ea0370801421846a89f3d09eb0a481289270919f14
+R = 019cf91a38cc20b9269e7467857b1fc7eabb8cea915a3135f727d471e5bfcfb66d321fabe283a2cf38d4c5a6ecb6e8cbee1030474373bb87fcdfcc95cf857a8d25d0
+S = 01cf9acd9449c57589c950f287842f9e2487c5610955b2b5035f6aacfd2402f511998a1a942b39c307fc2bcab2c8d0dae94b5547ddccfb1012ca985b3edf42bbba8b
+
+Curve = P-521
+Private = 00f749d32704bc533ca82cef0acf103d8f4fba67f08d2678e515ed7db886267ffaf02fab0080dca2359b72f574ccc29a0f218c8655c0cccf9fee6c5e567aa14cb926
+X = 0061387fd6b95914e885f912edfbb5fb274655027f216c4091ca83e19336740fd81aedfe047f51b42bdf68161121013e0d55b117a14e4303f926c8debb77a7fdaad1
+Y = 00e7d0c75c38626e895ca21526b9f9fdf84dcecb93f2b233390550d2b1463b7ee3f58df7346435ff0434199583c97c665a97f12f706f2357da4b40288def888e59e6
+Digest = 65f83408092261bda599389df03382c5be01a81fe00a36f3f4bb6541263f801627c440e50809712b0cace7c217e6e5051af81de9bfec3204dcd63c4f9a741047
+K = 003af5ab6caa29a6de86a5bab9aa83c3b16a17ffcd52b5c60c769be3053cdddeac60812d12fecf46cfe1f3db9ac9dcf881fcec3f0aa733d4ecbb83c7593e864c6df1
+R = 004de826ea704ad10bc0f7538af8a3843f284f55c8b946af9235af5af74f2b76e099e4bc72fd79d28a380f8d4b4c919ac290d248c37983ba05aea42e2dd79fdd33e8
+S = 0087488c859a96fea266ea13bf6d114c429b163be97a57559086edb64aed4a18594b46fb9efc7fd25d8b2de8f09ca0587f54bd287299f47b2ff124aac566e8ee3b43
+
+Curve = P-521
+Private = 01a4d2623a7d59c55f408331ba8d1523b94d6bf8ac83375ceb57a2b395a5bcf977cfc16234d4a97d6f6ee25a99aa5bff15ff535891bcb7ae849a583e01ac49e0e9b6
+X = 004d5c8afee038984d2ea96681ec0dccb6b52dfa4ee2e2a77a23c8cf43ef19905a34d6f5d8c5cf0981ed804d89d175b17d1a63522ceb1e785c0f5a1d2f3d15e51352
+Y = 0014368b8e746807b2b68f3615cd78d761a464ddd7918fc8df51d225962fdf1e3dc243e265100ff0ec133359e332e44dd49afd8e5f38fe86133573432d33c02fa0a3
+Digest = a6200971c6a289e2fcb80f78ec08a5079ea2675efd68bcab479552aa5bcb8edf3c993c79d7cebcc23c20e5af41723052b871134cc71d5c57206182a7068cc39b
+K = 00bc2c0f37155859303de6fa539a39714e195c37c6ea826e224c8218584ae09cd0d1cc14d94d93f2d83c96e4ef68517fdb3f383da5404e5a426bfc5d424e253c181b
+R = 01a3c4a6386c4fb614fba2cb9e74201e1aaa0001aa931a2a939c92e04b8344535a20f53c6e3c69c75c2e5d2fe3549ed27e6713cb0f4a9a94f6189eb33bff7d453fce
+S = 016a997f81aa0bea2e1469c8c1dab7df02a8b2086ba482c43af04f2174831f2b1761658795adfbdd44190a9b06fe10e578987369f3a2eced147cff89d8c2818f7471
+
+Curve = P-521
+Private = 014787f95fb1057a2f3867b8407e54abb91740c097dac5024be92d5d65666bb16e4879f3d3904d6eab269cf5e7b632ab3c5f342108d1d4230c30165fba3a1bf1c66f
+X = 00c2d540a7557f4530de35bbd94da8a6defbff783f54a65292f8f76341c996cea38795805a1b97174a9147a8644282e0d7040a6f83423ef2a0453248156393a1782e
+Y = 0119f746c5df8cec24e4849ac1870d0d8594c799d2ceb6c3bdf891dfbd2242e7ea24d6aec3166214734acc4cbf4da8f71e2429c5c187b2b3a048527c861f58a9b97f
+Digest = 46ff533622cc90321a3aeb077ec4db4fbf372c7a9db48b59de7c5d59e6314110676ba5491bd20d0f02774eef96fc2e88ca99857d21ef255184c93fb1ff4f01d3
+K = 0186cd803e6e0c9925022e41cb68671adba3ead5548c2b1cd09348ab19612b7af3820fd14da5fe1d7b550ed1a3c8d2f30592cd7745a3c09ee7b5dcfa9ed31bdd0f1f
+R = 010ed3ab6d07a15dc3376494501c27ce5f78c8a2b30cc809d3f9c3bf1aef437e590ef66abae4e49065ead1af5f752ec145acfa98329f17bca9991a199579c41f9229
+S = 008c3457fe1f93d635bb52df9218bf3b49a7a345b8a8a988ac0a254340546752cddf02e6ce47eee58ea398fdc9130e55a4c09f5ae548c715f5bcd539f07a34034d78
+
+Curve = P-521
+Private = 015807c101099c8d1d3f24b212af2c0ce525432d7779262eed0709275de9a1d8a8eeeadf2f909cf08b4720815bc1205a23ad1f825618cb78bde747acad8049ca9742
+X = 0160d7ea2e128ab3fabd1a3ad5455cb45e2f977c2354a1345d4ae0c7ce4e492fb9ff958eddc2aa61735e5c1971fa6c99beda0f424a20c3ce969380aaa52ef5f5daa8
+Y = 014e4c83f90d196945fb4fe1e41913488aa53e24c1d2142d35a1eed69fed784c0ef44d71bc21afe0a0065b3b87069217a5abab4355cf8f4ceae5657cd4b9c8008f1f
+Digest = 6b514f8d85145e30ced23b4b22c85d79ed2bfcfed5b6b2b03f7c730f1981d46d4dadd6699c28627d41c8684bac305b59eb1d9c966de184ae3d7470a801c99fd4
+K = 0096731f8c52e72ffcc095dd2ee4eec3da13c628f570dba169b4a7460ab471149abdede0b63e4f96faf57eab809c7d2f203fd5ab406c7bd79869b7fae9c62f97c794
+R = 01e2bf98d1186d7bd3509f517c220de51c9200981e9b344b9fb0d36f34d969026c80311e7e73bb13789a99e0d59e82ebe0e9595d9747204c5f5550c30d934aa30c05
+S = 012fed45cc874dc3ed3a11dd70f7d5c61451fbea497dd63e226e10364e0718d3722c27c7b4e5027051d54b8f2a57fc58bc070a55b1a5877b0f388d768837ef2e9cec
+
+Curve = P-521
+Private = 018692def0b516edcdd362f42669999cf27a65482f9358fcab312c6869e22ac469b82ca9036fe123935b8b9ed064acb347227a6e377fb156ec833dab9f170c2ac697
+X = 01ceee0be3293d8c0fc3e38a78df55e85e6b4bbce0b9995251f0ac55234140f82ae0a434b2bb41dc0aa5ecf950d4628f82c7f4f67651b804d55d844a02c1da6606f7
+Y = 01f775eb6b3c5e43fc754052d1f7fc5b99137afc15d231a0199a702fc065c917e628a54e038cbfebe05c90988b65183b368a2061e5b5c1b025bbf2b748fae00ba297
+Digest = 53c86e0b08b28e22131324f6bfad52984879ab09363d6b6c051aac78bf3568be3faeade6a2dda57dece4527abaa148326d3adbd2d725374bdac9ccb8ac39e51e
+K = 0161cf5d37953e09e12dc0091dc35d5fb3754c5c874e474d2b4a4f1a90b870dff6d99fb156498516e25b9a6a0763170702bb8507fdba4a6131c7258f6ffc3add81fd
+R = 014dfa43046302b81fd9a34a454dea25ccb594ace8df4f9d98556ca5076bcd44b2a9775dfaca50282b2c8988868e5a31d9eb08e794016996942088d43ad3379eb9a1
+S = 0120be63bd97691f6258b5e78817f2dd6bf5a7bf79d01b8b1c3382860c4b00f89894c72f93a69f3119cb74c90b03e9ede27bd298b357b9616a7282d176f3899aaa24
+
+Curve = P-521
+Private = 00a63f9cdefbccdd0d5c9630b309027fa139c31e39ca26686d76c22d4093a2a5e5ec4e2308ce43eb8e563187b5bd811cc6b626eace4063047ac0420c3fdcff5bdc04
+X = 014cab9759d4487987b8a00afd16d7199585b730fb0bfe63796272dde9135e7cb9e27cec51207c876d9214214b8c76f82e7363f5086902a577e1c50b4fbf35ce9966
+Y = 01a83f0caa01ca2166e1206292342f47f358009e8b891d3cb817aec290e0cf2f47e7fc637e39dca03949391839684f76b94d34e5abc7bb750cb44486cce525eb0093
+Digest = a9e9a9cb1febc380a22c03bacd18f8c46761180badd2e58b94703bd82d5987c52baec418388bc3f1e6831a130c400b3c865c51b73514f5b0a9026d9e8da2e342
+K = 001e51fd877dbbcd2ab138fd215d508879298d10c7fcbdcc918802407088eb6ca0f18976a13f2c0a57867b0298512fc85515b209c4435e9ef30ab01ba649838bc7a0
+R = 011a1323f6132d85482d9b0f73be838d8f9e78647934f2570fededca7c234cc46aa1b97da5ac1b27b714f7a171dc4209cbb0d90e4f793c4c192dc039c31310d6d99b
+S = 00386a5a0fc55d36ca7231a9537fee6b9e51c2255363d9c9e7cb7185669b302660e23133eb21eb56d305d36e69a79f5b6fa25b46ec61b7f699e1e9e927fb0bceca06
+
+Curve = P-521
+Private = 0024f7d67dfc0d43a26cc7c19cb511d30a097a1e27e5efe29e9e76e43849af170fd9ad57d5b22b1c8840b59ebf562371871e12d2c1baefc1abaedc872ed5d2666ad6
+X = 009da1536154b46e3169265ccba2b4da9b4b06a7462a067c6909f6c0dd8e19a7bc2ac1a47763ec4be06c1bec57d28c55ee936cb19588cc1398fe4ea3bd07e6676b7f
+Y = 014150cdf25da0925926422e1fd4dcfcffb05bdf8682c54d67a9bd438d21de5af43a15d979b320a847683b6d12ac1383a7183095e9da491c3b4a7c28874625e70f87
+Digest = 7e324819033de8f2bffded5472853c3e68f4872ed25db79636249aecc24242cc3ca229ce7bd6d74eac8ba32f779e7002095f5d452d0bf24b30e1ce2eb56bb413
+K = 01c1308f31716d85294b3b5f1dc87d616093b7654907f55289499b419f38ceeb906d2c9fe4cc3d80c5a38c53f9739311b0b198111fede72ebde3b0d2bc4c2ef090d2
+R = 000dbf787ce07c453c6c6a67b0bf6850c8d6ca693a3e9818d7453487844c9048a7a2e48ff982b64eb9712461b26b5127c4dc57f9a6ad1e15d8cd56d4fd6da7186429
+S = 00c6f1c7774caf198fc189beb7e21ca92ceccc3f9875f0e2d07dc1d15bcc8f210b6dd376bf65bb6a454bf563d7f563c1041d62d6078828a57538b25ba54723170665
+
+Curve = P-521
+Private = 00349471460c205d836aa37dcd6c7322809e4e8ef81501e5da87284b267d843897746b33016f50a7b702964910361ed51d0afd9d8559a47f0b7c25b2bc952ce8ed9e
+X = 000bbd4e8a016b0c254e754f68f0f4ed081320d529ecdc7899cfb5a67dd04bc85b3aa6891a3ed2c9861ae76c3847d81780c23ad84153ea2042d7fd5d517a26ff3ce4
+Y = 00645953afc3c1b3b74fdf503e7d3f982d7ee17611d60f8eb42a4bddbec2b67db1f09b54440c30b44e8071d404658285cb571462001218fc8c5e5b98b9fae28272e6
+Digest = 4541f9a04b289cd3b13d31d2f513d9243b7e8c3a0cbd3e0c790892235a4d4569ef8aef62444ecc64608509e6ad082bf7cd060d172550faa158b2fd396aa1e37b
+K = 000eb2bd8bb56b9d2e97c51247baf734cc655c39e0bfda35375f0ac2fe82fad699bf1989577e24afb33c3868f91111e24fefe7dec802f3323ac013bec6c048fe5568
+R = 014bf63bdbc014aa352544bd1e83ede484807ed760619fa6bc38c4f8640840195e1f2f149b29903ca4b6934404fb1f7de5e39b1ea04dba42819c75dbef6a93ebe269
+S = 005d1bcf2295240ce4415042306abd494b4bda7cf36f2ee2931518d2454faa01c606be120b057062f2f3a174cb09c14f57ab6ef41cb3802140da22074d0e46f908d4
+
+Curve = P-521
+Private = 007788d34758b20efc330c67483be3999d1d1a16fd0da81ed28895ebb35ee21093d37ea1ac808946c275c44454a216195eb3eb3aea1b53a329eca4eb82dd48c784f5
+X = 00157d80bd426f6c3cee903c24b73faa02e758607c3e102d6e643b7269c299684fdaba1acddb83ee686a60acca53cddb2fe976149205c8b8ab6ad1458bc00993cc43
+Y = 016e33cbed05721b284dacc8c8fbe2d118c347fc2e2670e691d5d53daf6ef2dfec464a5fbf46f8efce81ac226915e11d43c11c8229fca2327815e1f8da5fe95021fc
+Digest = 7ec0906f9fbe0e001460852c0b6111b1cd01c9306c0c57a5e746d43f48f50ebb111551d04a90255b22690d79ea60e58bed88220d485daaf9b6431740bb499e39
+K = 00a73477264a9cc69d359464abb1ac098a18c0fb3ea35e4f2e6e1b060dab05bef1255d9f9c9b9fbb89712e5afe13745ae6fd5917a9aedb0f2860d03a0d8f113ea10c
+R = 007e315d8d958b8ce27eaf4f3782294341d2a46fb1457a60eb9fe93a9ae86f3764716c4f5f124bd6b114781ed59c3f24e18aa35c903211b2f2039d85862932987d68
+S = 01bcc1d211ebc120a97d465b603a1bb1e470109e0a55d2f1b5c597803931bd6d7718f010d7d289b31533e9fcef3d141974e5955bc7f0ee342b9cad05e29a3dded30e
+
+Curve = P-521
+Private = 01f98696772221e6cccd5569ed8aed3c435ee86a04689c7a64d20c30f6fe1c59cc10c6d2910261d30c3b96117a669e19cfe5b696b68feeacf61f6a3dea55e6e5837a
+X = 007002872c200e16d57e8e53f7bce6e9a7832c387f6f9c29c6b75526262c57bc2b56d63e9558c5761c1d62708357f586d3aab41c6a7ca3bf6c32d9c3ca40f9a2796a
+Y = 01fe3e52472ef224fb38d5a0a14875b52c2f50b82b99eea98d826c77e6a9ccf798de5ffa92a0d65965f740c702a3027be66b9c844f1b2e96c134eb3fdf3edddcf11c
+Digest = 7230642b79eed2fd50f19f79f943d67d6ef609ec06c9adbb4b0a62126926080ecd474922d1af6c01f4c354affde016b284b13dbb3122555dea2a2e6ca2a357dc
+K = 01a277cf0414c6adb621d1cc0311ec908401ce040c6687ed45a0cdf2910c42c9f1954a4572d8e659733d5e26cbd35e3260be40017b2f5d38ec42315f5c0b056c596d
+R = 00d732ba8b3e9c9e0a495249e152e5bee69d94e9ff012d001b140d4b5d082aa9df77e10b65f115a594a50114722db42fa5fbe457c5bd05e7ac7ee510aa68fe7b1e7f
+S = 0134ac5e1ee339727df80c35ff5b2891596dd14d6cfd137bafd50ab98e2c1ab4008a0bd03552618d217912a9ec502a902f2353e757c3b5776309f7f2cfebf913e9cd
+
+Curve = P-521
+Private = 013c3852a6bc8825b45fd7da1754078913d77f4e586216a6eb08b6f03adce7464f5dbc2bea0eb7b12d103870ef045f53d67e3600d7eba07aac5db03f71b64db1cceb
+X = 00c97a4ebcbbe701c9f7be127e87079edf479b76d3c14bfbee693e1638e5bff8d4705ac0c14597529dbe13356ca85eb03a418edfe144ce6cbf3533016d4efc29dbd4
+Y = 011c75b7a8894ef64109ac2dea972e7fd5f79b75dab1bf9441a5b8b86f1dc1324426fa6cf4e7b973b44e3d0576c52e5c9edf8ce2fc18cb3c28742d44419f044667f8
+Digest = d209f43006e29ada2b9fe840afdf5fe6b0abeeef5662acf3fbca7e6d1bf4538f7e860332ef6122020e70104b541c30c3c0581e2b1daa0d767271769d0f073133
+K = 01e25b86db041f21c2503d547e2b1b655f0b99d5b6c0e1cf2bdbd8a8c6a053f5d79d78c55b4ef75bff764a74edc920b35536e3c470b6f6b8fd53898f3bbc467539ef
+R = 01dce45ea592b34d016497882c48dc0c7afb1c8e0f81a051800d7ab8da9d237efd892207bc9401f1d30650f66af8d5349fc5b19727756270722d5a8adb0a49b72d0a
+S = 00b79ffcdc33e028b1ab894cb751ec792a69e3011b201a76f3b878655bc31efd1c0bf3b98aea2b14f262c19d142e008b98e890ebbf464d3b025764dd2f73c4251b1a
+
+Curve = P-521
+Private = 01654eaa1f6eec7159ee2d36fb24d15d6d33a128f36c52e2437f7d1b5a44ea4fa965c0a26d0066f92c8b82bd136491e929686c8bde61b7c704daab54ed1e1bdf6b77
+X = 01f269692c47a55242bb08731ff920f4915bfcecf4d4431a8b487c90d08565272c52ca90c47397f7604bc643982e34d05178e979c2cff7ea1b9eaec18d69ca7382de
+Y = 00750bdd866fba3e92c29599c002ac6f9e2bf39af8521b7b133f70510e9918a94d3c279edec97ab75ecda95e3dd7861af84c543371c055dc74eeeff7061726818327
+Digest = c992314e8d282d10554b2e6e8769e8b10f85686cccafb30e7db62beaad080e0da6b5cf7cd1fc5614df56705fb1a841987cb950101e2f66d55f3a285fc75829ff
+K = 01b7519becd00d750459d63a72f13318b6ac61b8c8e7077cf9415c9b4b924f35514c9c28a0fae43d06e31c670a873716156aa7bc744577d62476e038b116576a9e53
+R = 0183bddb46c249e868ef231a1ebd85d0773bf8105a092ab7d884d677a1e9b7d6014d6358c09538a99d9dca8f36f163ac1827df420c3f9360cc66900a9737a7f756f3
+S = 00d05ee3e64bac4e56d9d8bd511c8a43941e953cba4e5d83c0553acb87091ff54f3aad4d69d9f15e520a2551cc14f2c86bb45513fef0295e381a7635486bd3917b50
+
+Curve = P-521
+Private = 01cba5d561bf18656991eba9a1dde8bde547885ea1f0abe7f2837e569ca52f53df5e64e4a547c4f26458b5d9626ed6d702e5ab1dd585cf36a0c84f768fac946cfd4c
+X = 012857c2244fa04db3b73db4847927db63cce2fa6cb22724466d3e20bc950a9250a15eafd99f236a801e5271e8f90d9e8a97f37c12f7da65bce8a2c93bcd25526205
+Y = 00f394e37c17d5b8e35b488fa05a607dbc74264965043a1fb60e92edc212296ae72d7d6fe2e3457e67be853664e1da64f57e44bd259076b3bb2b06a2c604fea1be9d
+Digest = 6e14c91db5309a075fe69f6fe8ecd663a5ba7fab14770f96b05c22e1f631cde9e086c44335a25f63d5a43ddf57da899fcedbc4a3a4350ad2edd6f70c01bb051e
+K = 00e790238796fee7b5885dc0784c7041a4cc7ca4ba757d9f7906ad1fcbab5667e3734bc2309a48047442535ff89144b518f730ff55c0c67eeb4c880c2dfd2fb60d69
+R = 01d7ce382295a2a109064ea03f0ad8761dd60eefb9c207a20e3c5551e82ac6d2ee5922b3e9655a65ba6c359dcbf8fa843fbe87239a5c3e3eaecec0407d2fcdb687c2
+S = 0161963a6237b8955a8a756d8df5dbd303140bb90143b1da5f07b32f9cb64733dc6316080924733f1e2c81ade9d0be71b5b95b55666026a035a93ab3004d0bc0b19f
+
+Curve = P-521
+Private = 00972e7ff25adf8a032535e5b19463cfe306b90803bf27fabc6046ae0807d2312fbab85d1da61b80b2d5d48f4e5886f27fca050b84563aee1926ae6b2564cd756d63
+X = 01d7f1e9e610619daa9d2efa563610a371677fe8b58048fdc55a98a49970f6afa6649c516f9c72085ca3722aa595f45f2803402b01c832d28aac63d9941f1a25dfea
+Y = 01571facce3fcfe733a8eef4e8305dfe99103a370f82b3f8d75085414f2592ad44969a2ef8196c8b9809f0eca2f7ddc71c47879e3f37a40b9fecf97992b97af29721
+Digest = 26b4f562053f7aed8b7268e95eff336ac80a448fae52329d2771b138c9c7f70de936ef54158446afa72b0a27c2a73ca45dfa38a2ba2bf323d31aba499651128f
+K = 00517f6e4002479dc89e8cbb55b7c426d128776ca82cf81be8c1da9557178783f40e3d047db7e77867f1af030a51de470ee3128c22e9c2d642d71e4904ab5a76edfa
+R = 01c3262a3a3fb74fa5124b71a6c7f7b7e6d56738eabaf7666b372b299b0c99ee8a16be3df88dd955de093fc8c049f76ee83a4138cee41e5fe94755d27a52ee44032f
+S = 0072fd88bb1684c4ca9531748dfce4c161037fcd6ae5c2803b7117fb60d3db5df7df380591aaf3073a3031306b76f062dcc547ded23f6690293c34a710e7e9a226c3
+
+Curve = P-521
+Private = 01f0ec8da29295394f2f072672db014861be33bfd9f91349dad5566ff396bea055e53b1d61c8c4e5c9f6e129ed75a49f91cce1d5530ad4e78c2b793a63195eb9f0da
+X = 009ec1a3761fe3958073b9647f34202c5e8ca2428d056facc4f3fedc7077fa87f1d1eb30cc74f6e3ff3d3f82df2641cea1eb3ff1529e8a3866ae2055aacec0bf68c4
+Y = 00bed0261b91f664c3ff53e337d8321cb988c3edc03b46754680097e5a8585245d80d0b7045c75a9c5be7f599d3b5eea08d828acb6294ae515a3df57a37f903ef62e
+Digest = ea13b25b80ec89ffa649a00ce85a494892f9fb7389df56eed084d670efb020c05508ac3f04872843c92a67ee5ea02e0445dad8495cd823ca16f5510d5863002b
+K = 00ac3b6d61ebda99e23301fa198d686a13c0832af594b289c9a55669ce6d62011384769013748b68465527a597ed6858a06a99d50493562b3a7dbcee975ad34657d8
+R = 00cef3f4babe6f9875e5db28c27d6a197d607c3641a90f10c2cc2cb302ba658aa151dc76c507488b99f4b3c8bb404fb5c852f959273f412cbdd5e713c5e3f0e67f94
+S = 00097ed9e005416fc944e26bcc3661a09b35c128fcccdc2742739c8a301a338dd77d9d13571612a3b9524a6164b09fe73643bbc31447ee31ef44a490843e4e7db23f
diff --git a/src/crypto/ecdsa/ecdsa_test.cc b/src/crypto/ecdsa/ecdsa_test.cc
index a0c8fbd..7c68de4 100644
--- a/src/crypto/ecdsa/ecdsa_test.cc
+++ b/src/crypto/ecdsa/ecdsa_test.cc
@@ -59,11 +59,9 @@
 #include <openssl/ec.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
 #include <openssl/rand.h>
 
-#include "../test/scoped_types.h"
-
 enum Api {
   kEncodedApi,
   kRawApi,
@@ -82,7 +80,7 @@
       if (!ECDSA_SIG_to_bytes(&der, &der_len, ecdsa_sig)) {
         return false;
       }
-      ScopedOpenSSLBytes delete_der(der);
+      bssl::UniquePtr<uint8_t> delete_der(der);
       actual_result = ECDSA_verify(0, digest, digest_len, der, der_len, eckey);
       break;
     }
@@ -171,7 +169,7 @@
     fprintf(out, "%s: ", kCurves[n].name);
 
     int nid = kCurves[n].nid;
-    ScopedEC_GROUP group(EC_GROUP_new_by_curve_name(nid));
+    bssl::UniquePtr<EC_GROUP> group(EC_GROUP_new_by_curve_name(nid));
     if (!group) {
       fprintf(out, " failed\n");
       return false;
@@ -184,14 +182,14 @@
     }
 
     // Create a new ECDSA key.
-    ScopedEC_KEY eckey(EC_KEY_new());
+    bssl::UniquePtr<EC_KEY> eckey(EC_KEY_new());
     if (!eckey || !EC_KEY_set_group(eckey.get(), group.get()) ||
         !EC_KEY_generate_key(eckey.get())) {
       fprintf(out, " failed\n");
       return false;
     }
     // Create a second key.
-    ScopedEC_KEY wrong_eckey(EC_KEY_new());
+    bssl::UniquePtr<EC_KEY> wrong_eckey(EC_KEY_new());
     if (!wrong_eckey || !EC_KEY_set_group(wrong_eckey.get(), group.get()) ||
         !EC_KEY_generate_key(wrong_eckey.get())) {
       fprintf(out, " failed\n");
@@ -253,7 +251,7 @@
     fprintf(out, ".");
     fflush(out);
     // Verify a tampered signature.
-    ScopedECDSA_SIG ecdsa_sig(ECDSA_SIG_from_bytes(
+    bssl::UniquePtr<ECDSA_SIG> ecdsa_sig(ECDSA_SIG_from_bytes(
         signature.data(), signature.size()));
     if (!ecdsa_sig ||
         !TestTamperedSig(out, kEncodedApi, digest, 20, ecdsa_sig.get(),
@@ -313,7 +311,7 @@
 
 static bool TestECDSA_SIG_max_len(size_t order_len) {
   /* Create the largest possible |ECDSA_SIG| of the given constraints. */
-  ScopedECDSA_SIG sig(ECDSA_SIG_new());
+  bssl::UniquePtr<ECDSA_SIG> sig(ECDSA_SIG_new());
   if (!sig) {
     return false;
   }
@@ -328,7 +326,7 @@
   if (!ECDSA_SIG_to_bytes(&der, &der_len, sig.get())) {
     return false;
   }
-  ScopedOpenSSLBytes delete_der(der);
+  bssl::UniquePtr<uint8_t> delete_der(der);
 
   size_t max_len = ECDSA_SIG_max_len(order_len);
   if (max_len != der_len) {
@@ -340,16 +338,19 @@
   return true;
 }
 
+static size_t BitsToBytes(size_t bits) {
+  return (bits / 8) + (7 + (bits % 8)) / 8;
+}
+
 int main(void) {
   CRYPTO_library_init();
-  ERR_load_crypto_strings();
 
   if (!TestBuiltin(stdout) ||
-      !TestECDSA_SIG_max_len(224/8) ||
-      !TestECDSA_SIG_max_len(256/8) ||
-      !TestECDSA_SIG_max_len(384/8) ||
-      !TestECDSA_SIG_max_len(512/8) ||
-      !TestECDSA_SIG_max_len(10000)) {
+      !TestECDSA_SIG_max_len(BitsToBytes(224)) ||
+      !TestECDSA_SIG_max_len(BitsToBytes(256)) ||
+      !TestECDSA_SIG_max_len(BitsToBytes(384)) ||
+      !TestECDSA_SIG_max_len(BitsToBytes(521)) ||
+      !TestECDSA_SIG_max_len(BitsToBytes(10000))) {
     printf("\nECDSA test failed\n");
     ERR_print_errors_fp(stdout);
     return 1;
diff --git a/src/crypto/ecdsa/ecdsa_verify_test.cc b/src/crypto/ecdsa/ecdsa_verify_test.cc
new file mode 100644
index 0000000..18340e2
--- /dev/null
+++ b/src/crypto/ecdsa/ecdsa_verify_test.cc
@@ -0,0 +1,110 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <stdio.h>
+
+#include <vector>
+
+#include <openssl/bn.h>
+#include <openssl/crypto.h>
+#include <openssl/ec.h>
+#include <openssl/ec_key.h>
+#include <openssl/ecdsa.h>
+#include <openssl/nid.h>
+
+#include "../test/file_test.h"
+
+
+static bssl::UniquePtr<EC_GROUP> GetCurve(FileTest *t, const char *key) {
+  std::string curve_name;
+  if (!t->GetAttribute(&curve_name, key)) {
+    return nullptr;
+  }
+
+  if (curve_name == "P-224") {
+    return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(NID_secp224r1));
+  }
+  if (curve_name == "P-256") {
+    return bssl::UniquePtr<EC_GROUP>(
+        EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+  }
+  if (curve_name == "P-384") {
+    return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(NID_secp384r1));
+  }
+  if (curve_name == "P-521") {
+    return bssl::UniquePtr<EC_GROUP>(EC_GROUP_new_by_curve_name(NID_secp521r1));
+  }
+
+  t->PrintLine("Unknown curve '%s'", curve_name.c_str());
+  return nullptr;
+}
+
+static bssl::UniquePtr<BIGNUM> GetBIGNUM(FileTest *t, const char *key) {
+  std::vector<uint8_t> bytes;
+  if (!t->GetBytes(&bytes, key)) {
+    return nullptr;
+  }
+
+  return bssl::UniquePtr<BIGNUM>(BN_bin2bn(bytes.data(), bytes.size(), nullptr));
+}
+
+static bool TestECDSASign(FileTest *t, void *arg) {
+  bssl::UniquePtr<EC_GROUP> group = GetCurve(t, "Curve");
+  bssl::UniquePtr<BIGNUM> x = GetBIGNUM(t, "X");
+  bssl::UniquePtr<BIGNUM> y = GetBIGNUM(t, "Y");
+  bssl::UniquePtr<BIGNUM> r = GetBIGNUM(t, "R");
+  bssl::UniquePtr<BIGNUM> s = GetBIGNUM(t, "S");
+  std::vector<uint8_t> digest;
+  if (!group || !x || !y || !r || !s ||
+      !t->GetBytes(&digest, "Digest")) {
+    return false;
+  }
+
+  bssl::UniquePtr<EC_KEY> key(EC_KEY_new());
+  bssl::UniquePtr<EC_POINT> pub_key(EC_POINT_new(group.get()));
+  bssl::UniquePtr<ECDSA_SIG> sig(ECDSA_SIG_new());
+  if (!key || !pub_key || !sig ||
+      !EC_KEY_set_group(key.get(), group.get()) ||
+      !EC_POINT_set_affine_coordinates_GFp(group.get(), pub_key.get(), x.get(),
+                                           y.get(), nullptr) ||
+      !EC_KEY_set_public_key(key.get(), pub_key.get()) ||
+      !BN_copy(sig->r, r.get()) ||
+      !BN_copy(sig->s, s.get())) {
+    return false;
+  }
+
+  int ok = ECDSA_do_verify(digest.data(), digest.size(), sig.get(), key.get());
+  if (t->HasAttribute("Invalid")) {
+    if (ok) {
+      t->PrintLine("Signature was incorrectly accepted.");
+      return false;
+    }
+  } else if (!ok) {
+    t->PrintLine("Signature was incorrectly rejected.");
+    return false;
+  }
+
+  return true;
+}
+
+int main(int argc, char *argv[]) {
+  CRYPTO_library_init();
+
+  if (argc != 2) {
+    fprintf(stderr, "%s <test file.txt>\n", argv[0]);
+    return 1;
+  }
+
+  return FileTestMain(TestECDSASign, nullptr, argv[1]);
+}
diff --git a/src/crypto/ecdsa/ecdsa_verify_tests.txt b/src/crypto/ecdsa/ecdsa_verify_tests.txt
new file mode 100644
index 0000000..a1b4cb2
--- /dev/null
+++ b/src/crypto/ecdsa/ecdsa_verify_tests.txt
@@ -0,0 +1,2346 @@
+# Tests from NIST CAVP 186-4 ECDSA2VS Test Vectors, Signature Verification Test
+# http://csrc.nist.gov/groups/STM/cavp/documents/dss/186-3ecdsatestvectors.zip
+#
+# NIST's files provide message and digest pairs. Since this is a low-level test,
+# the digests have been extracted. P-521 test vectors were fixed to have the
+# right number of leading zeros.
+
+Curve = P-224
+X = a100d410ce497e991070285c439cd361a1a9c6c973fd6f5e1ba9ec66
+Y = 0a8c3a2f909f212c84441b8c0030529cbd731304d86f771d89d7cc29
+Digest = 6a02c84186eb132d8e91ab6fea2e066f6f8de1a5
+R = 1bfcaab01e47addd4733369320364ad208169ffb15e6aac33c2d7c06
+S = 07fb33465e7b7b373feda2ea35ab7cc9477156a1335ecad942f99627
+
+Curve = P-224
+X = a6cd3d14cd5eb188a9f59d9c32e93d890558de382f6fba5ff5c6e395
+Y = 7a76734a0afead9e5e4aba65f1ae353d6445b1689b5ea402de5f9af9
+Digest = ab1205b7f9f591a013c70cb645435b38689644c1
+R = f0f670963c3d2a3281d639f850f3781c6402d99a1bf07cd9f35b2975
+S = 758e84920c1b744502cd787cdd64ec58364ccc6917258a2580097492
+Invalid =
+
+Curve = P-224
+X = f5fe7875a517207f1336ec2bb4fe5cc7eb80ee2b0f8ebeff4c56e620
+Y = 0b7ac24ea9092d03b28904d89714b517be023235abc9cffa297cf4ad
+Digest = d62c7a42fcf3738276a6e0d27160328e9f27e5aa
+R = 88617e694e361d2cfef6b0658d444607fba030ad31fe8dead14db22e
+S = 5b0bf37c4a583dd75d99aec20943ea02617cecdbcd295d35ed01cc32
+Invalid =
+
+Curve = P-224
+X = 8a6a77179ffc0ff5d412cf859cc82aa19cd18e5224ab997e9c2e46b0
+Y = 3d67c177ca7cc12c7b05a3bf55fb78549ef5400a566efe8ae3580c9f
+Digest = 0b5a025a4038b6f9f995001c0b8d7a660e6766c2
+R = 107b7442e6569ddde54b5da55a9dac9bd348079358047a19a3de0b91
+S = 92359be39353cb263946294fb728eecf1880f50a43637f391d3e7824
+
+Curve = P-224
+X = f9f23388d573562f29e7e7c9a98f27e7a1ff02d2d66e177c6506466f
+Y = 4545937caf1878fbacc34ca38a0e5e1f6ad2b25ddd796d06c8d12351
+Digest = cf670c7589b91dac6a131fe2e863e86ee790ca75
+R = bc1db32e437c67439c27db1dc607e3c505210c984bf707a8e87abb70
+S = b760f4943a2397311e54e888a1ad379ad9c45d1fd09b5389ce1a00ee
+Invalid =
+
+Curve = P-224
+X = 8781e5a98950092570d685964e9ed27760fb7dcff8d3b6f3c8f77151
+Y = 9207cef64b7c2ed181c57337001f45f1e800e0d1bc8adac296e454b5
+Digest = e5e5e8c8b3f7146c72ef86ca1b75f422181b5729
+R = 79826ae5b0297b9404829df0f02bbb7b8acb35459e13a4045c40f242
+S = 2a629dab19c9e5cd0a551a43851fe6d8409469f86cbcf6204b41e5b5
+Invalid =
+
+Curve = P-224
+X = 03c78c532b8767784fd45e75027abce3371181f8f54914811588cbb2
+Y = 166c7b70e98fa11ac361d827557676ec07e553370a462b4fe502dedb
+Digest = 270606c9c9b136ffada9588f15f9786455369422
+R = ff18b493b166d832c9c25ee491525e4c188ff2b804e38b5964941c48
+S = bbf4291db484b4e4143c01a284c03543bbdaa2db1f1c571f1e5a5e2e
+Invalid =
+
+Curve = P-224
+X = 99fab11464484cee96d72dfcf0327d671787a2f6ee32f9b184c48fec
+Y = fe8ec3d660cfa3f3e09e5cfc2c3298d4de2f464416deb5b4a27ac062
+Digest = 9c77c796ba619aedef68b2d30b4ba00c4972488b
+R = 714c48c143cb259408c04f77a38d6484e788cb268fc9789d5e871491
+S = 542793d5dbcabcebc83a809cca02b8e95189c93fa4e330d66d5a62ef
+Invalid =
+
+Curve = P-224
+X = 014e8e57388eba32ebdce80df60c481e5c7758374f90a92e0a82f1b9
+Y = d1aa8418f992283c5b6bb0461f05dc9103050dc55e0265e1c99b935d
+Digest = 82b45d1fb3bb502c7c20ee1e2d63f2aaa9f492ab
+R = a159b83e80e656f54f614e8437821bd87f6f13264ac8eca1b3ddde29
+S = b77b7bc8cf374f012ee15f9f9224a46a560a5b689cfc92ca4fa03459
+Invalid =
+
+Curve = P-224
+X = e0b9e3cadca81311923d6d6adcfc326b62fac9c4b8d61c5f960c88fa
+Y = be505338108f8d3f0ee80aefa304d51dd4a4035477934a98a6111403
+Digest = f4da99fee346e572906e6dc8083a3d0c2e09b773
+R = 8dba585dc3312056a7be61161c7af8ba8b538f0c125c80cf9af2682e
+S = 1b5b1adac4d66c7045f3f79c3aa154a0274c4a994ac7a093e2482eeb
+Invalid =
+
+Curve = P-224
+X = 29197e94a3617e62d9999c859640871a4537a073ca4f12a4c324dcad
+Y = fe198969ac7cbe49df2c61c4cc6fa502c2207a7da10acdccec7b1cad
+Digest = 58fab970cb7c1f0dac21b7c7fd67d0ad169688a1
+R = 261670b09afaeee71c590c5658e3f57d859b18a887f70fdeb90e57ea
+S = d1d12c11cf7f4a9dd015ead4bd245793cb37ffee1f4cf109b7b68394
+Invalid =
+
+Curve = P-224
+X = 0fac352c1c444435e6aeb1d60f28ac773b0170ae902afb0944ef0a12
+Y = ac3ca693a7c5347a074808b43edea94059e2b1d0571d935fde3f5841
+Digest = 4b69dbfac12f1b974566d8170d1672d0f5fc0506
+R = c33c7a4de313ff856d2f51cd9e3d173bd10668c296f0e6b208c036ef
+S = e562d30822b5cc69713a57ce8c70f83827add85a06c88109505ebf7a
+Invalid =
+
+Curve = P-224
+X = b0d4298e998b7d9d4509322a1ac974c6180956533debafd3d9e7f2fc
+Y = 185a64ca840d4b6a2800e72433f26dd523f97daadc18d6d01533f0ad
+Digest = b84805c37e76e530729ddcb59a68ad69d40c82f9
+R = a5155ce53050cbfe84b67d62ce118c6004564087f2fe1cdf44e9c945
+S = b6894b050d77a3ff4d191ddc0c9fc7009a7472e31739949193d7cceb
+Invalid =
+
+Curve = P-224
+X = 59996a4a06658e553fc2993f0f55e3fc8ca2cb52d30f882a37729be4
+Y = a5f68f26ea6608fd1f350d8da7c187c7e70f23363177a5aa41508fce
+Digest = ef0a69578d8a1dc930803a7ad2a92c3c19ab6513
+R = 704ef49e0a43c61ef5b325899acb9d12287883a849976c8b9c950634
+S = 73da6e3a26d5c512405fc09fcfdf650dd8da748e6c3dfc05032d7a9f
+
+Curve = P-224
+X = a0cfdfc5a096b0b23ba6748ebaad17e60228b204aebdc01057a7154b
+Y = 9f6bd5369d21d88d7b5c3ce221af530fb9a8fb91e751cdb855ff32a6
+Digest = b05f0232e6d44151e249e7b75c7c9ab05c14d44b
+R = d68aa9048e84b8653b8ff3ab31bc73884c6ac7df1fd1bd3c38c16b0d
+S = 38ce58afe5fbc6af892e06a4ddd978c745d5ec700cab825c11dd8fd1
+Invalid =
+
+Curve = P-224
+X = f1eb36b3e1c96a18d87878d5fa8b79d77afce9d2ce40d26199f33482
+Y = ae819af474f3efbd62401a407036505c5a2d60449274593865de3374
+Digest = 1dd27c95dd6fb3f080afebdf5a1ad906502e12ab8f64e5f38f67c386
+R = 003122e976bac378c06ec95fd73290b067e7ff022d23493c40663ec9
+S = b99eb4220146a282c7a34f98a9a4fa38ed3f48ca2c7983cde2d3235f
+
+Curve = P-224
+X = 3bdcc7c6112cde3c0522f1a4863f1d7b6727c5bff67598ba2f1bafc1
+Y = 47acb6b254e0e8747e0039de471d0dda443cb09a592c678717d83200
+Digest = 19b39292f4e862ed3ee90c35e709587231191632dc8b35611dd24abe
+R = a5aab7768f549f8fe3c7e650154c865b71ea5089bd6303bfdfd19316
+S = ee4989c4b96bcc802464fe44b2adeb1b3506755a3f4fb3f9252bf21b
+Invalid =
+
+Curve = P-224
+X = 6d5bacf458cee3ded627d0ff14fd2aeb54fe1455d6daaf7bb43faeea
+Y = caecc8d3967ca1c8889607e9ed975b8a335a17c0acbcfbfed721ee1c
+Digest = 328ab7d2a7c56d09cb72cedaacc23a6da46d5cf984dfdfd16af60964
+R = 80e7024bf30ecddf7a658785ae51cd6e5a23963c89ee96a82346d889
+S = 561252dc8d9280fc54da0046da494fa5e4b7aed213923e8b894a1ae3
+Invalid =
+
+Curve = P-224
+X = 7f9789c729355516588a5c75cb2cbcf85a14c35e14a5d03b4ef920d7
+Y = 49e95c49e62dd20f02ed16594f35ebf3415ed50e6efdc0c548101a9d
+Digest = c5bb2d7ca9b37af1f4bb572ae6b6e69e8fcab9ac1cc5a6e1b6d1f8de
+R = 3c7b664413c2a0e4682a9d1c88243a96196fbd03f72cb873b9bee8b9
+S = 8f7f81ee9d3a2660ab1d666bac6cc434143ca9b04ff638ca7b4aa1ea
+
+Curve = P-224
+X = fd3efc7108edbe155adcd8686d8605e811fa79756c7e2dc8c1c04212
+Y = 59edea73a4e5f91541fb4cabce539afffa85b6b0113289f049ce60a0
+Digest = 562d1a8fa642dd8bbb4f4801f2d9fc8cf3452be916c0ecd6c8ddc4fc
+R = 4907884b8b7d0eb9a7b24420f69c58e3a17314e101da0280c0ceb130
+S = f7629bed92e5c40f35d7731912fb45a3cee06eab3d409a62997f2282
+Invalid =
+
+Curve = P-224
+X = 8b3f3e31d9c8408a39997455ffe0240fe128a5f1be9b3a33a97b0910
+Y = d74ac6ad8de2407887c335bd66f684454dee175a2af713bb334cb3fe
+Digest = b57ffce01c72221c6714e4a38c76746c45a8cc685f37c55a69f6773f
+R = d28ae763c22f50ae9ee9fbe5bab682fd8d820b99ab70677cc46624f7
+S = d9fa54d0300a6ac74936e7a47fbacadcbb4b25ae3a5b550aaf53991f
+Invalid =
+
+Curve = P-224
+X = f4fd02f3d224727e156a2cd7543483f3e35eb65219e32c7923f93ecf
+Y = e7aa734828ef326259f98e0e8c3f30b62bd3295c6d1af2c429a087f6
+Digest = 8e70efc206d69d1bd1dce263a29a56030ad5602046bc61848899474d
+R = 9f57e28f69d2ebd96f6d98903156a4e795730e09fb67963771b0a851
+S = 8cfe716488479e04500c8eccdc86fdd54ff00258639f7177169e2030
+Invalid =
+
+Curve = P-224
+X = 0fdb8faf52d8f46229cca1e0f22e869a91bd56eb6dccc547151f9c68
+Y = 96c8d1946528bdd2c14c3a0a9c17a088d3f0599752d095ba9de9ffa6
+Digest = db452771046d4b64ba673771b49df905881df9c4b6a1292a11f87515
+R = c53c0ce7d408278552a5fe5854c05641cbe93b1dc18eff1c68af53c1
+S = be7453a12693ce7812fe58746323882bc14eff972480b49431cb10b3
+Invalid =
+
+Curve = P-224
+X = 240431da69703b32ba2ae501d2458b355b66170725806b45996db195
+Y = 13beb5198ee00abdcfb2cc5454416d4f7c795e97a14bd93cec3f0a56
+Digest = 3598d7d7b2cd9e482fd3bbebb9ae4549a4b452c81b89f3da6f6f2e85
+R = ad03bdf64e3450407a2a977e1985853d6ea41568c3a394d696de6739
+S = 7b55db9abf2045e2dc7ccfa2e8fb501883c494662d400590c74d100f
+Invalid =
+
+Curve = P-224
+X = 8c80c86f91b1e330f86f5177fdba839e625a27e8531f232efb10a484
+Y = a24deab8978dfe7398f7a1da0633ff7cf5aa7b7365ce2d840ce81c80
+Digest = 44603667b2251cf051cd67b927714d67a25295679d884c4b79099a80
+R = 0c422b292308f31af78b1261d12765cced1cf96a83a6bc3bd90330fc
+S = db34f4462d0bb1927cc99273dc92d3fe654c85a3b53c6d74ed900621
+Invalid =
+
+Curve = P-224
+X = 3a5d1b7ee6749630c9619789b256f6bad5bc4b09950cd53b78d5ef30
+Y = e85c7ee707df680eeb5fd78451f7302ae653f96721443826096f62a3
+Digest = 2ed9e7077df2ca2f8a96dfea2127b1b34147fcf963f9d73e8aff9df6
+R = 671ad280609364b0e26c92b13891f677db7c83499d0a3d7b6d80affa
+S = 7c4b9c5a3937d540ed8bd59e340c13f02313445e06b2bf7525f5726a
+Invalid =
+
+Curve = P-224
+X = 350f59509abc9f7f9b35a8b80065258727a8ffc27e6dac635ed68900
+Y = 634fceae493b200cc7680297fd940dd86a5111da14bed68c797ef254
+Digest = 012a6edb0064f2b734b0297ab924efcb0e653be9e6ae97c371d59680
+R = 13a302b200555a0e80584e6ede32c0f9c5a199125b219c3e8d0fbf96
+S = 13f1d7b0c87acea6290cd9d36f1820f546f83dd8d7d9abe9da5812a9
+Invalid =
+
+Curve = P-224
+X = 1fdb820003a2fe61deef2b68b92ac711abc76200c534ec3abc99a187
+Y = 32f87d0554b6b5e389311fd3c86825fcd42654a0b6f5d4d5ba73031b
+Digest = 2afe40d5042eb4020b14053e9ead6774d566e0b536912b7de4450090
+R = c03e551abcb12eadbc291b2d5fdd53bf725b785933e0766969f0355e
+S = 94826a8753cb949e0199be3220b4f90318f1c835cdd67efc50df7fbd
+
+Curve = P-224
+X = 208dcc6c87e7c38bd914bc9b350602ff62ac62fa4fd633c1af5b8cd7
+Y = 0263587c7692c8be1f78de88ed6dc99ce1198ecc53a77ae6cf98a323
+Digest = 3f95e73294defecfc125a2dbbf322d31f323c030adf244c07a7c8746
+R = c12d3b396e1a894dfe4a28971ce4983547596879956504e1a3aed75c
+S = 067b729ca23be6cd520fbe9b972b9bb3d00c9ee96832a5c35e20e0e0
+Invalid =
+
+Curve = P-224
+X = a66a652fa36413dccd72c83febedda051182dc5758a1466366197f5f
+Y = dc813a79e0fc647d8892dcf4f2132c90914a520cbbad65f458ee0fae
+Digest = 8a8942761ccd4ac7c88c4afcb6bc69d431cc3d10e6ad7a2b8610892f
+R = 809d1b4557eaf36b6eab3449dad56e61d572bd8b63d51b63af1b0bc6
+S = 8bf88226a463606ab57c27ed78f1b71ccd61732fa58b62ee845fd3dd
+Invalid =
+
+Curve = P-224
+X = 8856fb8b81a4eacd971a954560018f33cbb71cc1fc243d03f63cabcb
+Y = 28afa26baf31b4d89de1dadd2289006f836f23a11383817ec7e4e799
+Digest = d8454640ad1f4632cc667823418ae56c62028825d727adfc84afdb0842b0c9a4
+R = efccef331805e71bbf876cbbc2342a6bc4508aea7c691029c8396aef
+S = bed544d09e28dbf01a30b2cfb61b98ad6201a9818f22b4f543f3e7f5
+Invalid =
+
+Curve = P-224
+X = 34c5ff3de565b85bfdd9f0a8b3fb0d46f924c57b276bcc830a1ed580
+Y = 609d22200ef38b410da77f7a8ff2f58448188042978fd9ae1b2b4477
+Digest = 831979405db4eb9dadf01249fa15f68d4846e0ece70a320d3022f75f3dc281cc
+R = f0138024fe0516738f3bd0e0fec10defaca8c3b89c161a77489cf2b7
+S = 4ae0934266d9e3d64c2a12f546b132ba0f33ef50abc90e7ef5974805
+
+Curve = P-224
+X = 465afb14f4bf85022ac1f635f46c0b2f6548bace9352d32f74eab012
+Y = 036371a3246dbf1069d2d268ca431553d1f2bf0181225145881b7be0
+Digest = 489cd3c10d94f7f284bc4ea472634a5d7f0d280d5abbf139c110ef80c8bf463f
+R = 9bcd57a2fec2518903e4b13dc0a7b84bafed5c4908546e94ffae87ed
+S = a337e06582f6b3973df38b93a0fb2a63f7774b62db50dba557e5cfcc
+Invalid =
+
+Curve = P-224
+X = b8b7f923c05ec95ebd484db7c58d219cfd26ee6b66149631f25ffe4c
+Y = 6bda5f4f988784555a80b5494eca51ad2c7f88ce94d2090ee0c76fba
+Digest = b100feed0121d9d0471e5bd94a659510c2f84e313f476431deac17ca6d87bd79
+R = ce4d86bf5a7543d1cba8e4470a297e9a48d0096d7788c6284b1c0af3
+S = 229eb0636ee62508ce3719396d7577ed892cec70a66857fdee0d1fa0
+Invalid =
+
+Curve = P-224
+X = 13e84ec2eb993818d7d78330855ee2fbe8ddb548a5e4198e2087b3b2
+Y = c95dff249e10c506fb547a92ade53c61ddbb667c760e4127a1a7f806
+Digest = 21a9f65d4cdcc287e0bf330e4f76f1168d16d0cea796dd6c0e13cd2837decaf1
+R = ed26f00ed696e114305c546ed04db5fc35efa43059c0d8bbcd418d0c
+S = 6e16efbe9501e3055d74966a49232cd76b5d1241468788b4cc7378b4
+Invalid =
+
+Curve = P-224
+X = 16c23c93699cf665a5da8b2d4baa72c36158d3433b1b945e47204b0d
+Y = 12023703e1b59ec9054ff22d15567b9f74058b47cc13f2ca08ab77c1
+Digest = d62496d0ee0453e7f13f8d9c57adcd33442a5365f626381ed665f95f528aa198
+R = ada849b673a1bd2949a8b4d8fdfc239ec53524a356d37da3c9d17ae2
+S = 698de3a3d8697c2e8e5b2c85fceb8796750c5b44154f01ce86d99e24
+Invalid =
+
+Curve = P-224
+X = a580f9a0cd15abff8e1e712f16b0fd4142d0d773af3c657abc06c2a6
+Y = 22c6286340dc072e64274209eda60503047700571caee64b4a2306c2
+Digest = 25ef291dd6a2047ea193f8aedd3f4692f2c135cb519922a17cba3e969423b030
+R = c6fae06274dc052e482102520b49d4ccc4cb7eb8a3ea41bd3680ddad
+S = 50d66b75a2bbd0468be1f9e61bfda85b6329505b0134d60846cbe4b7
+
+Curve = P-224
+X = 0b4fb6fe5f6cf6adc7d28683628d4b9c569d21d2397533f5bd121a23
+Y = b44d60a3414b9b7b6e4ad735ce2f9cb05593b0874ada5e65acdead4c
+Digest = 7d53ebba0424c4b6731806407f97af4af863a5a87c759626830c9e8753ca50fe
+R = ab5ac2039b49690c6436793decb1a6a58ac34833a8091005312a93a7
+S = 98fe955cd836501cef78c7a05fa27edf2fb3afea80990028ff64e984
+Invalid =
+
+Curve = P-224
+X = bae2b3634c7854c932551ece8dced2139a51705059503881a9239c78
+Y = 094d5e455bc9296202618d7022512b0f9ce53d796c7294e6eb076a29
+Digest = bb5c0917ec5376b2c685f3a530a9f8ef1ef1c1b398ab66f479d936cd662efc1b
+R = 2fbdc7e9e98aed5dbbcc5b034e17a95209e2fe1b01515426b8b372c3
+S = f2b19226528f10be6ef0d27ec3703db690261206b7e42f93a691192e
+Invalid =
+
+Curve = P-224
+X = 49d9ff4f4bbd4320b6806a7fbaaedd962283c766a6c130e4b62139dc
+Y = 06dbe8e7fb8fccf9758101ae46939c6fd4d3afc526ba6c8156c6b013
+Digest = 9a113d3d73543e17faba847981e0b7fbc5647e547bfc989921ddc987133692d1
+R = 2d83aa59bcfc8a0237884826e08dbd78a56733598e379f2a9d51e9e2
+S = 485036c74618d0e665775fbe2d614a313c550f9826b955d3e5636fd1
+Invalid =
+
+Curve = P-224
+X = 78451cca49655978b65d8ddd45ff367c47f321f5d55ddac7969ab82b
+Y = 25b77f820aa9ec93ec89d7fc84285f3f3deed496e0cd3fb9ee4a5c99
+Digest = 352afd36279bee1ef5727c55c7428bb79db949a9f1953eb98cfd38c4a4a458af
+R = 998789490e008ed11febdfe2981a55c733eb9739d7f37fd5c2a7ec96
+S = c3ec8afade81860ff23cc1e7d759d32d9a5775886ef17bfb719df4aa
+Invalid =
+
+Curve = P-224
+X = 18ced60b7fd9ebf76c3aa5976dcbdef40bd3e36033c013553043dd84
+Y = 30398582dbd2004064f8055e7fe0fe8df11b2c9d9e2931ad12d09628
+Digest = a1e3668af6307f6a2b7414079e73308ee0836b588b92a48bd5baa9a62f45b0f8
+R = f880143960e812464810c175001b5d39592fe63aab544deb9ca301a0
+S = 1e0657df071a25dd791264b411c8964688f4fe17ce024e659836ebe1
+Invalid =
+
+Curve = P-224
+X = 5d67c1fca848ba7f3d9de5b1894d3993ac4ebe68cdb0b49553b3b0e9
+Y = 07c219a8323273c81f5694306d0dd1d133a49efce5003bc90f05578f
+Digest = e8f714f901cd2390c66f9fa9cb81ecc5f17a82bd934cf19c5ce2bcbd3a985de9
+R = 767cb6b2efa7a40739830659b0cc24fe3de771d00104b3dcc0f640bc
+S = f2e7268bc011d79d33f3551d2edd3c95f324955479b8e29e8aba629b
+
+Curve = P-224
+X = eac72b399cb791b3ed25cb0a49eb157e69603197e0327eac5448680d
+Y = bdab3a2270066e74e8210eed7b5d43fba1e26845b6c037a8a7e2a13b
+Digest = 74aa7c8f25644514582fa904cea1ea88a0b262ffca43cdf6536ad97d8550616e
+R = 55485947e9e3c194a29c8ecaddb18eefd16fb6919aeb0bbbd8c12369
+S = 6309a2cc7fdd9eccb32b86d5577aa54ada79899a9645f2e299630d31
+Invalid =
+
+Curve = P-224
+X = 17f741267bf3e8143046707d41eafc9555953fe5f57d6c035452b232
+Y = c667554d9a55fc8ab1062203dcbcd2bf9769c696a295350cb28aa01a
+Digest = 3b997a1c220593cab4301e07886db745436911b8abfd9d1b03cc12e1c7fa4510
+R = 57408bfcc68e60ad000eddbfe6eccbe5f87b98c95de0e0a2e065da92
+S = 51249bddc149f0942be001b2f3d6f6d17a0cc36fefce147058944667
+Invalid =
+
+Curve = P-224
+X = 3297edac34cb802df263f8d366f62a8b746c316adfb1c84a1c79c58c
+Y = 79fe82e87ef5879c12eda6adda198a662fd77afa6a1fb5696cb7da9d
+Digest = e71dc3ab7ce73995d053bc6361bbb3f20e39ec2f295d97fa2bd229ed31a56dde6bf2c9cf6b0a9cc7e65962c57f3662a3
+R = 9993defdcf83965723c03e04ce6c33b3972cef3c449cdf1bc69990db
+S = 553b22a4164549f16aa1a928eee74548fc141fd3c16f213318965974
+
+Curve = P-224
+X = 2bc010527ea7427cedd213aeccf0c62dc513785888c6373740139d8b
+Y = 2e9eb7ddf027ff7678ca880511be147098b34d8e77acb4389fbc6e50
+Digest = 781195b6396344146fe8b73a2526b4b1c981d26b9adcce0123176be1239f798c847495fd714661d1ba8e41f2ccfd052b
+R = 70a7cb04295a53b4a3a695ccb5d87856fe9152fce11987d4c43207bd
+S = 49f4094368f2de9327ca2913ef940e17c5801e8f589413838831083f
+Invalid =
+
+Curve = P-224
+X = 55c6217adbefff6e21bfb5d1b75213ce7b20c900d514ee094f27ad0d
+Y = a68ae9f86eb9c10de3e7d9b03868518f33f571f85c3529d2902575d3
+Digest = a318b24bbb5ba46e6656f8ad68201c024e7b3b3849d6a70f3abce8c20f5b98ae43a326f5f48994045f0ff27098837b5b
+R = c073fba87267b45853e693910c1de791908ca7a25c1716ec2d3cec71
+S = 6138c86daf1021ae4af0faaf0abd5958f93944d5b0d82c40214bacca
+Invalid =
+
+Curve = P-224
+X = 4d0cab0dae88fa0cf53a2a6562934e0cf0271cc7fe54a30109a232be
+Y = 70835833cf9e1f989a18d419e7bee9eb5cef1fd145cf62c4411c372c
+Digest = 6abbf2557f2e9b4e020126f4a87fb0262a1ec59bd3b569581048c5692f8a1cd381ee9c3cf195fa1a362a87ab604d79b3
+R = 3b8548eab4dc123e236133d826f2badbde96f92249f456e33ccc9739
+S = c82b2e41b9e2b21594cc03b1c0de216f183403c6025e18bb29bff421
+
+Curve = P-224
+X = f55a53b818b3ec4b4402a2c63429c1d78f2cd0d8d202e33812878a03
+Y = 5a2b1a00615c56b4313828bd70526b12f402df1d40fa4900c994af8b
+Digest = da8d2571bea9840494a41f03c6c357410de030a7b5c023a0487020bb5b7c45fb6c5ed0e3dc66e4c0ab8460d9bda68c94
+R = fa934f9fdb765fabb5693ccb1de4177f172a8de108805a48f4bb989c
+S = 12994f2a26252742667044a01b509b0f315e8141629f760267b850e1
+Invalid =
+
+Curve = P-224
+X = 40a5c52dda7de858a2c17d12856c552ab820023336b9b4fc196bcd67
+Y = 301e5368f59c00f15e6f3a91510444fb75a4ead8efb0778b4419e7db
+Digest = 0f88ea2d9dd40c19cd31c7a7cff71379431c9dc0a3092041a5fcbd2c20a05a8cb6e5a8aa143f1dfa169d2eaf87d01e26
+R = 0fd8773fac425a2761b954c946020615336d3e350ae40743641917fe
+S = d59f2b806ccecc444f9387f511c7f9926fe7f045c0ea633a51b7db47
+Invalid =
+
+Curve = P-224
+X = 372a134eec0dae3322de8836b89dde11a69e0379a60b10343abd478c
+Y = 65921970ca8cf5a75f044db0e29802afe1726d18b3e07b61c768c242
+Digest = 1547d49d33566f8c05f68b9a980e113f919bbdef8d6d53046456a2c2ebe27ad86eaa52d05677fadd5ccc3e84b04c0f94
+R = be6474845a42fd4e85b91238f1e3ba11cc88e216d295c1b07d855987
+S = 2724242ffb5775f614ee06eaa4c985358f64869ce4ae4bfb16b5271d
+Invalid =
+
+Curve = P-224
+X = 9ad2cee0d92b00b11157a18fcd752f43e772ede7a46475a50e7ad8d2
+Y = a6edfae6c5589dc0db6353b8655fe3b0f7dab2aa8400cbbd72d1a572
+Digest = 60942be3ff8d2370481b04fa07743482e08a61d3724010d7edd49bcf12e1463ae059696c825ac0505f079625b95310a1
+R = c31a40b6c245572457a19efac0da0db22b2a0818de716b6fdc5bdb32
+S = ed8204de94f1d92ae3fa6e10c727eea38d0e12b58133fda1a15559bb
+Invalid =
+
+Curve = P-224
+X = ed071a20d76f81c776875f8d3307841d33b70523ea40abd691d55d21
+Y = 34ca47d8ba0a984d0d728c4d8c6b9aacdded03c6070616680aac162c
+Digest = e0776a80c616b8e596bacb0391a19956b2f0e2c566c50dd2ba99f9e59ff3dfa6197622c2a64cb4d02780a39c68d249e0
+R = c7a5dce4733a81bd738e0a6e0667dc1fade86db119e7f3cde57d6dc6
+S = dfb7f43343941cce331be27047b131617910f68393630fa53d137df4
+Invalid =
+
+Curve = P-224
+X = f51097e1e4b4f3b32e92fded0b4c8b7240a62731292e615a4cae0dcf
+Y = 0549003f18e67076bc68110a75252072fc29b6d4a336d152dac2c3d1
+Digest = 48803bce00fe101650dcc83b290c49a524b21422f1f6a3aaa6e2f201863ffc355346d167dcb0ac552007a46cf8d6e4ad
+R = 6875a118dbf586a51af2212d5f32908c9f31110e9e9a7e4cdf7494c5
+S = 1542ab4260459e82070bbad405193a1894ce717af158daf1d096bc01
+Invalid =
+
+Curve = P-224
+X = 5255e4fdc816044389e9c6f5e09b85aedbe1c85b1cf9b7190ef7c2cc
+Y = 683c8cb6f31e4cc1e2a5361eb47e305d5d8bfeaf94e261a341aedde6
+Digest = 995229c018cd0ea061672c46ec30c99693fff1cad491b13b4093df0154872adf946644dee6192657b436931c30b7af9d
+R = f1b0f8a3fbf7d4de19cc1d3b4c525c31bd97c2e2a94eb8a27c7c197d
+S = 936d3f49a9aa58935cfe227b22db83314ffadcc4751c8e26853d8cd0
+Invalid =
+
+Curve = P-224
+X = 7cdaf519f6b1254cb8da4668a2dd2015857ceec17f838c15d7d34b27
+Y = e29f80fa4f830af7737126d4454b6498905e2c633fa61ad6acb30823
+Digest = c7d8d1f060287ec402092be54ca6e06895e91f9d0c29010124c0d9bd54007d8039b7328ec7b3a29e1d5d4d8fb78807e4
+R = e640f3e676a11007e73efd00b23087adefc9b9407ae8b79b47c397f3
+S = 66b7860a0ca35c2f1c65d50f99def9f2bfc0a6cad2008dcc38d6b3d7
+Invalid =
+
+Curve = P-224
+X = ca1a04f08708ae714b7dfb3db509970d30b7e01be7fd6181613894a7
+Y = 1d90a2fcda7dd6ce8b207eef48340e58cd439a3ce17658f6f82be778
+Digest = 1f710f925826bc33c0da91798cb7d7d0700883da685a1fb9503179f0a06b589bf92eb4b67496faf21cd74c8e3d560d77
+R = 9e810ec2a0bc205df6a75bd6410e0c8ea1c738e71af060e2eb271aa6
+S = 9d05eeb46258c468b0398cb6e421149bbea5ed936be3fde3380111cb
+Invalid =
+
+Curve = P-224
+X = 558c323d8259e055a025fbbe6ba8b525b02f32caddfd31e5b08219d4
+Y = e1d6398b1c47132632cd3f3fae14fc3ee3092faa619074fd951a5870
+Digest = 4b662138833a976051b20ddfb02e67339715b77046bedeb1e30b9dccbcd84204e76da722bb3bd020fbbe33a182792e0f
+R = 05d8b0bcedf287a4740bfc548570b1c1fff71058e0a9d88476bbb6a1
+S = 769321d50e34939e622a727855501e25a7ad44ec979985e7389aa3f9
+Invalid =
+
+Curve = P-224
+X = 9237e61ad9ffafc61cc1c72b6d2f96d69b588c8feee4074359f694f7
+Y = db25a18f1eee72734c640313f5c6c0441358611406cc62619113b4ba
+Digest = 4e7bbf78843a767536977b240e9d1516c73c0fa19bc91448280fd85361b06fdd11ee413f956ca4ea3d67c0e325a1d53a
+R = a58225b10080dab26644f10d8a817ffc4ed4535011729491b6ad5d00
+S = ddbc010e295882e0731ff240f15ed82fa3e81b7552c690cc5b40be03
+
+Curve = P-224
+X = ea7efb9a7e7bf693dc0249504ead70dd422ec86806cd649ed57a7ffe
+Y = 33dfb17b1cb244279990019286ab477a2aff2b55c08959deed0b1a28
+Digest = 330f78db9f217f95d99cbcb5414a32523025b85c87ed5aaa3a5e6b006c53cecbbd446166bb9b98e944626332c3266e82356e72110bdbf7df2431b8e7faf59e45
+R = deab574de1f971419b7ba9e169866c3a6233fc627c13dc6a8cb88bdc
+S = 8d4c542bb0046da1b3912652a2c84542668cd89920808785d04e4352
+Invalid =
+
+Curve = P-224
+X = 6fce4d789b1240f2ab1c23051aa03e219da99943a18864e7876d4d11
+Y = 3e84a6bddea4a28cf8151ae73aa7b1964c37e654241353a9fa723f67
+Digest = 0088e4cbf3eddb6eaf108fd3937c439684ff8fe5595f2032948423a2a15811b34b0def245bed3b4b4ca90d3f497f3aaa2577a7154d22d7254dfc4755eb9b7b17
+R = 2d1b4f1ccaebc0a929598b650ee364abfd6091a542ba426886d75f38
+S = 44f3d7afe84ae33ab5f9426dfc85248ebc7e0df434d35980ddec75e0
+Invalid =
+
+Curve = P-224
+X = 72013dd6f5b1eb709b3b7da234987f9a36c6f0b095620b8c31f02381
+Y = 319d54c719b59d91900b3c20d963ddf1a10d80d6601ac155094b075a
+Digest = 3cba2980faf5579c7ddbeb31c3318a162a882129a1efe1fc9acc3219a617c460701f22fd7a5c46b017bd9ec9c40587127319ea14b148d2be4df9875d5bef6e4e
+R = eb38db9b757b3cf04020f09188c789bf0258cd0467cf7d67368e8703
+S = 7664e85f01e67881712b24083f89e838c8b818de4d665494e7016833
+Invalid =
+
+Curve = P-224
+X = c6a65011926eb64e02bf472d5ba37841d49cfb7f17a20fb9f59355de
+Y = 386ccb33d944fd7be6b8531863d2b6200cd602d300d7e7681537e53f
+Digest = eaa81b1236121db12f2036611eb6d3e5386f5733125fb26844cb4188109aae402525fc63bcd73494c36c170d1934b108739d79b0c4f184bd85ffce93b1beecde
+R = 9e7c637a699dd52512faea847079f0ad41b20cd7a5461c36d01e857e
+S = dec6e9ef361de3f6ec7d87de3129eaac5fd0b43b5f7f58ce46c29173
+
+Curve = P-224
+X = 5bcdbaeb2f6c57e8a9dffe94804e74daaf9db8452d13c6a8bc2a4966
+Y = a564072356c5d86200e979291a19d5e73d8bcb701cf84d9012824bf6
+Digest = 4a5de84f304f0c83365ae4213fee71c0944d8580f9d8e7455fc961e9f98bf3d51b7fc20aa44e36c0bdaa09e365767742e9bd8bc868d5c6cd8e1cd2ce2968e3dc
+R = c58436fb77aaa4468dee284e1220141ce9ff4426f75daadf5a898a6f
+S = 87aeee1229a50921d8e77e7e3478061f5c051097defb104a0455ed81
+Invalid =
+
+Curve = P-224
+X = 6c6a7deef8b3dee2eaa98d8ec877dddb460365968e63ffe5c249a421
+Y = 1ad1715797b5e47c4be24d7ecb8141f1772344a2f643cc66fbcf3f9d
+Digest = f59946dd73887a1fb945ae3e5b44b574512e36dd7d35925b0bdc3a3f69a88e50dc6ebaaac86092679961a99d7ba5724363c5886e7c2cd566433c5a9d59e2515d
+R = f778faa2dc2cee7de2af0bbc4339239dc240907e59ac034464ce986b
+S = 2ac929588a8dc8785808c9d4366bd7b1a81e0fc5be0c63e62344c251
+Invalid =
+
+Curve = P-224
+X = 0ee33a134feae6ee1488bf10edf7cf7c318a2d709080a24818619b91
+Y = d7d39536e42652baf55159847f475ded075385a3c1af5c3dcb17ee6a
+Digest = 00fc4992514c1053eee7facc5199161a2b0f69dad2770326371ba42c2c12ffdb4ff6bd86fc440dc8dc1354dad42ff0c2a055b61137532a62521b0f3508ebe611
+R = 34bd0407f80cb6fc759036e6d4522eb6da94874c92ce0f02d8f5f2ad
+S = 3a2dd970050ff990162e5702b06905d03e3c7bb2771050de6d84eece
+Invalid =
+
+Curve = P-224
+X = 31d3c62a4305c37a15e9102072e287a8e0ac027f9189cb9d87ecbea2
+Y = 26449ca391af6a2a9f8daaa036f2c9044b336773ee48bcbd9cad59f0
+Digest = dfafbf96b70ead7e91dbf48b8efd062bf2bc0aac6d3e90a7fdf61aac13a74b304bcd0d0c23c88df269d45bdd31d50f0fccfc0324698af4dbcffef04ca05a119e
+R = dc33e8f7b52f584aa3f091aba10c2a9a23be6835e1551092652e1bbc
+S = ae84a6d19f6bad3f9886930c0a1406016fae813673db1516b31b638c
+Invalid =
+
+Curve = P-224
+X = a6e4470712df583d0c795237ff46c9df5718ba2aa24139a2d99721b4
+Y = 9edb403a8c10807e8736af665dbcf6052bd4b43bcdc8b9eb8d4394fd
+Digest = 36cd6716cbb8b7f96df4617143be7b74f42bc94e468e79e6658d00b092e24d6de82f207693427fb439dd13bcf49665cac343ea35a79b5963cb21273094ce28fd
+R = 4e9ba5bc4f4fc4e507c1e5cbd0d688da4237385b16ff06601436d8ab
+S = 4e0450a57d802d0ea7b0fb57eb162267195bc4248a831a0ee8b0380d
+Invalid =
+
+Curve = P-224
+X = 350fa782e1cf7254b18cde30683e54edf2c1b4782525fd081bed5920
+Y = a77de5b4139ff63e108b6fbd3a7e6c09c3d2ea8720860a7db1c1b5c8
+Digest = 0589be3481da7becf046cc9fd84e9a68db8086c730374e8ee8542de45e1e17dbacba6ecbaa99886f4daaaf32be01bae96b1e2a04cd76f699a1a74a3d97b73019
+R = fb7073865646bd92f882f8224503ac1f340cb7a5d6319102c31fb544
+S = aed3ca77d23c78ec76f748e84483c536d447b0f8e186dbd0774b1214
+Invalid =
+
+Curve = P-224
+X = f10652c3c2c30a765564f5e393c6c202d436c81fc7d71b88857bd458
+Y = 42979ba5e6c8cd044e262c73e6aa918d8c3e0e08e4bf98ec2d5c6f57
+Digest = 680aaa97b939a5031737a40b9e34e5fb8047b8a6e495c7c90653458072cb423fb098e6ecef15c9d62d4443337f61cde237c66c1683753e65f8bced5298375bf5
+R = 072e0b130267d8e124dda2d0604f4c575ef4007628fa61f66bcd8f07
+S = 6276475fccda3bee2af7816c7b3ec222e408cec36d0409e672af23b5
+
+Curve = P-224
+X = 89cef29515f1d30fdd283625eb59e682023bdf2eb0497288ff700b27
+Y = ca0a3f7ee4853ae8454fff6e926c7a85dc7852fb4d01cc3de861c53d
+Digest = bb7394f9b30617419daa71573f5ed9d72732930b6d24141ea2bfb6bcdd67f4fd7a7e6caed8fcac76f50bad0616c291ff875d866b4085f2a0201289a0895a319a
+R = 0ff5dba589454d0ee5bb391a4dc8446b1ffd1cf8d66c9fc0f05a8a89
+S = 987c32258cd12b6b9cdcc5915eea5eb79a30ead442179a126b97fa9e
+Invalid =
+
+Curve = P-224
+X = 086d892340057368ca47a3762735519a4316f005ed8a18a9edce3b4c
+Y = e15f4c9a0d240fb94e05192ce4296c532b549af577c26de861dd3452
+Digest = dd84be132129accb134697c8b86a47bc3479eb3db37f128965c5638e210b416580ad52d8f63033b032f1897dbc4732fdddd8202479ee6b32fa12b1ee529242bc
+R = 8d1e13fdf36eeea06a837cb22d17601081df6ed2815ea9da79894a75
+S = c19713a132a562bf2abf8c2d8cae95ef3272824db63edb0776ffc1ce
+Invalid =
+
+Curve = P-224
+X = 6c8aea044d4f0b9699eaf398dbb030db4d6c68e0786068fbc2094974
+Y = 426e743008febd8597594e7247ed1cbd40561bbabe1031963591ec6b
+Digest = c5e3ff45af230a7a97d1ab13f95641d1a47953d43be0427c1f30de1b7a431d22972fcdbe748911e05aa0c8047f9211af2234ddad4c30f34abee15d421c9333d6
+R = 3041c36b8456d65f4564597c65aa880fa8bc455f2c35de0fa2298cc1
+S = b87a516d1e2dcd862c6e5fcfc363e9f36bb06ff2c0333e95221e7f36
+Invalid =
+
+Curve = P-224
+X = dc85f6701bc95a60ea52f1c476dcb211e5e3eeba5b35dc3a3786113f
+Y = a52b364fb7c4b4c9155e4ee2d8841386b8a96cbeed1e5c9957214a50
+Digest = d4e0bcf58e2083383ef94b28cfb2710a4e898b2c2a0cf30bebb99c3f2dc93403dd165e1a0c3773ed05adedf967fc92f0a158e5086965a29dab3a4aaa5e9f9911
+R = bdc7b4d3266e54a19f030f3055f83460ccf30fe8f5368be013076081
+S = 82a0e3a21a8d5e9cfcc5a673385cc2d4159498b6c1ef5791b2b02f9f
+
+Curve = P-256
+X = 1198b3c409a8b47edb1347e0982d533cb1813e5cb2a92c824b2881b3cd2f3f4a
+Y = 0bdbac5fa02e41e775f8d602446d58ecb2209b5a3d79ae69eef399016e992e87
+Digest = 01ed0c41d650479c47057f61433d7e8b24492649
+R = 9206d435f148f88c15b2effbf3c506e41b2c620102022b801e371d0767b54bea
+S = cbc4e1674ae1af69873946ccf6275946e59e0107278749b2d0010795833d80fa
+Invalid =
+
+Curve = P-256
+X = f7c6280aecd6b936513b0ca84e63346333dc41437a15442e605d46bba93ae101
+Y = 3c834cecc16167b07866a9478f9f2d882de7ef937da447cd837e60cb5ed65d81
+Digest = f91b4dfddd5eb33a875d2e50d1e949211ac819da
+R = f615af212ab030c4bbf9362d9815a1462312df4beb4358a7ce80d820355420bf
+S = d12ed715ef65cfe6fe6bf348364088a0e7f70927bbafe4c12fc4cb65c0cc51bc
+Invalid =
+
+Curve = P-256
+X = 0e7632dbc4db879e10d1d80f2789d9fa414c1fe77a6c1e56d6667af43e36e610
+Y = 6f0dd2a5840e5a6f6ff7e23f656f5c945b7a493fbb0cfd5b9b531bf04435b1ef
+Digest = 3905696f8bad8205fa1445df0e91ade3dbc413e6
+R = 2b0b9ab4a575732a168f28494b66a855fc1a757fb1177864bf3e4f0a000c4a86
+S = 54901ce2f92f55ac112afa0f8b62bc00b44c8c10fe0c863675bfd305d6dc0cd8
+Invalid =
+
+Curve = P-256
+X = 1613f12bae8e98d09b4bba53f5229596a0d417d2c625f41bb15f923b3c1e4b57
+Y = 411319fa85227997a4cf3b1756161485124d2cedc38c9c30d82f42dc2647d545
+Digest = 580d31ce22700a20c2db81bcdac37330b491c86f
+R = ed058d476a77be99c1b0fc8502abe545541b4c0ff3eed3f558133ae2f02042b0
+S = c571b4895712a4f64f7220b0694cab767379b09f1824fe7874acd127deb2371e
+Invalid =
+
+Curve = P-256
+X = 88bb041dcb1733a676a7f4ae8d3e407d72d5396547f07db77078485c1d5db077
+Y = 72cf2b55e596cd140c58228f1b0a19c34fca26ffac043528a417c5abb6fca9c9
+Digest = 7900a02f768b0718a13525c33adace583de15c50
+R = 87208734deb125dca68f0d33f9d369cf1b79cf5a021391b9c6c1727d2efe663a
+S = b984f722de18f1ce407104342948f03f2b55413a096c4b5fca1e032a2c814a4a
+Invalid =
+
+Curve = P-256
+X = 811eb5180def7fb60d632f8cb2cba831b88cee778aa2a82ec3a5fc3d80ff7fb6
+Y = db88d65b0fc35d9ba1f1ced0400434979ae895d371d1441d7c7a441a9fb1709b
+Digest = 17b7451ea903125ccb293ffaa9d1a4ca1141a2c5
+R = c329fa28dac0018276c5af0cd770e60be50bc14e2562d5556991971edc7d4916
+S = 2d111d13837a02fa279fe835a7dc59a521864d92b26649ca4e24b36ae93878e8
+Invalid =
+
+Curve = P-256
+X = 4a6f1e7f7268174d23993b8b58aa60c2a87b18de79b36a750ec86dd6f9e12227
+Y = 572df22bd6487a863a51ca544b8c5de2b47f801372a881cb996a97d9a98aa825
+Digest = 54e9a048559f370425e9c8e54a460ec91bcc930a
+R = 4a800e24de65e5c57d4cab4dd1ef7b6c38a2f0aa5cfd3a571a4b552fb1993e69
+S = d9c89fb983640a7e65edf632cacd1de0823b7efbc798fc1f7bbfacdda7398955
+Invalid =
+
+Curve = P-256
+X = f3033d1e548d245b5e45ff1147db8cd44db8a1f2823c3c164125be88f9a982c2
+Y = 3c078f6cee2f50e95e8916aa9c4e93de3fdf9b045abac6f707cfcb22d065638e
+Digest = e8d38e4c6a905a814b04c2841d898ed6da023c34
+R = d4255db86a416a5a688de4e238071ef16e5f2a20e31b9490c03dee9ae6164c34
+S = 4e0ac1e1a6725bf7c6bd207439b2d370c5f2dea1ff4decf1650ab84c7769efc0
+
+Curve = P-256
+X = 0ea0a6bb6c70966fad1a2307479c12de2322795bdecb70e4b286bd6200ba9c1a
+Y = c40eda3947021348db691ac4086fb6c06b587ce37c155bb0a7d912b93226de81
+Digest = 3b08bf1b67abc03c1cd69b0e24743b5c2d49e506
+R = f5509deff7bfda3f3759800fa4033af6a84466b114ecb48eac37eff48d2ae1b3
+S = 8c4b62dce2082f80caf220cdbb1d02567bbdfab40564b90ef31d86e3e10ce80a
+Invalid =
+
+Curve = P-256
+X = e7a57e0f6ec0fa9c7c34978034cf82f039f8fd62804070ad943573fc8efa5775
+Y = 87b2cc85dfff2dae5620fbe3e6256bd728de28fc9dc1b5eb6b5d7bd5d29186ad
+Digest = a8c5dc0344b1442dfdb5f8836251893d6c4ecbe9
+R = 97642038932fdddbe2021ec1af53ae6b9af00ef9c8b9f26aea582892e80e6285
+S = 9cb14918359338041cf795cf6781e4905837fa5ce3b3e50ffafb5f13c73b5bc8
+Invalid =
+
+Curve = P-256
+X = be7a651be0c87278569987cf62d7fa1dd1b3d6e1b868d8f4dfb56135a9960eec
+Y = b7a62c588a987760b915edbd7f95506870c60f042471de1d8b2d4cd9d6563391
+Digest = 2f93ee45db133a14c26d418c2ffd3470ae63bf50
+R = aa889fb608b6939f6eeacf2f64c3b2e3a6061f2834058c7e724321720b737a63
+S = 6cd6d0ef2b93a760daa914e11b9b414bd4d72457405f00a62ab63f36d76efb73
+Invalid =
+
+Curve = P-256
+X = 76ddc46d8db8d7ce2ce837f60cdabcee92b7c7817ee41c8f066f1ae65f85c318
+Y = bea47191f1c584c87250370ce337a1de1583bcfc20ccc23b7a82e83f19adaa88
+Digest = 2136a5470ff9d45214a0b2c300042efea8ff7266
+R = 84a42efbf7ec04166ad144d19cd98c120aa2e79d483b5eea6fbdfa7f1222e07b
+S = e41531205e691e65668f69f518abc7b60f32c373434872a043b7358462babf83
+Invalid =
+
+Curve = P-256
+X = 2f71b932f770ba9daf7c1dd47444ab6cb8881f71a1c597e719845b15cb84ca35
+Y = ab928625b40ec0738d0fc8dbc4df4a1f65d20bc0447b69cfa13bb20b95bb41d4
+Digest = ae6093bb37c1264ca3ead439e4f678721912c8c4
+R = 63fca172bbca6197cd2802a9cb61d74c2b47cf35f6d35203e67ffbaa838be775
+S = e70ec283cd212df6ba3723e26b697501f112d7cf64e4f45185dae76055e09f1e
+
+Curve = P-256
+X = ce775648b928db82ac5edb3b009d32959a73b86c45e96d4b8d5b6e640b7c2790
+Y = 52455caf08ee94d86f0984e9ec9268d74823f2102dd97fced59638055f6af18e
+Digest = 60054807acb29e3091a023c42b9885c4945249e1
+R = 2a64b29146588f3153fee1029a0131ac0a8a25ba2ecc494f697c166c7c91fc08
+S = 7b429bc12a72ca3d76c119eea9f4098633cc31c87831e54d5d93afd6e8d20f4f
+Invalid =
+
+Curve = P-256
+X = cd2f29a53f0ce57e0e4a542c3256e65ebbdc30415f4de771d5d706d3aeacc852
+Y = dbbf2c129f30d11fe77d7816a24187764eae3fb2ff70c1ec745e876e26f5232f
+Digest = 5f50e35b134942295c16d003742fd6bce5bdab45
+R = 2454c5ee84e4f77b554acd368dd412389db8c78429590a092f24db2da43cb761
+S = 63e870ce2fa4085d4ff1e360f7a5c101a1f8b288abe71cca56887e613ad034b7
+
+Curve = P-256
+X = 843f6d83d777aac75b758d58c670f417c8deea8d339a440bb626114318c34f29
+Y = 83e0c70008521c8509044b724420463e3478e3c91874d424be44413d1ce555f3
+Digest = cda2c7ad9abb2a858c4981550f78974c69e41cc31fa33509e3e83dc2
+R = d08e9a5db411019d826b20ac889227ed245503a6d839494db1e8d7995a6b245b
+S = 8d46a204054125d0dc776ab1055302ec4eb0f20b90bca6d205f21d3cefd29097
+
+Curve = P-256
+X = f08b56f73f7a0e098444f6f0a02ad81ce0b914a11cafa15893d1c84704e1c564
+Y = bbee9aeb91cdc2d1d1437b4168df73acfd64e8b02962b14c85e67187e1ef80a4
+Digest = 5453c2656550e9b3dc6c40a3f1362a73522396bc35d383dd6451128f
+R = 71b3ec982725a007ac18a5cf60587e1fd1beb57685a1f9df3cddd9df25dcbc18
+S = 407e41217325f92f8a031cfcc4eb64c1a4b17b0a7459c254af754a7ea9eac997
+Invalid =
+
+Curve = P-256
+X = 0b688e761e1ddda2305e002809da65bf5916dfe1356a5b99b61f5576a9b90efa
+Y = 90ec958e2e3a676e7bbf8e9394f72742875836125a317b0ae38374953f746a91
+Digest = 7289573d6bb7486e428e086bec9da9d7ff3c5f8bd0db2ec209fed6ae
+R = ef89df3bbf079fb250f7e882c4f85c0023fc3804e862d9ef4d9530a15f1013f0
+S = 4ba985e900e6737b8e07eac638f7b38277ead4faee6d2076a2eee90fd2a6bf0f
+Invalid =
+
+Curve = P-256
+X = 0b64480783e260e1e9caef37b4cc9c650d2d57e2c594b1106314843d8d7ab74e
+Y = 29d373d8522deffe40055aef539f53f38937eb799b44f05a8d8c0b381f12907f
+Digest = 497656e780360ec3b4bd1be97570615e4a32467982cd9330bc6aa224
+R = c5c26b0b21eef0f7a0f1cff38d0079d890376759369b01d8d8e959c1c785e203
+S = fecc400bf0deab99d87da168b9d0dd31d2dfa3435b0fe9d38b5fb8efd45195a4
+Invalid =
+
+Curve = P-256
+X = 7f78a8fd880c509940e2b83de67c9ab553ab91489bae75cdc1d5b523b06ab7f5
+Y = 7786aee7032c373cdfad7d9ddb6fa09a026f6da30fd477ab014d30a289d542a1
+Digest = 6d88da9e83ae9457e233d7977172c062dfbdd17d365694515251e031
+R = c93ada69db326f76b1362d610cb8bcc6e7ef1dc03d3d11367e153c0e39d5dc86
+S = d0c02c71b14ef7a4af4e23bd207ce98449f5d6e7e5b3ec8cbbca9549e97d379d
+
+Curve = P-256
+X = e58cdc207c56f62e0bb7c0b55b7f7236a6b308f8fc4de3e61cdb3bf20ad2f62c
+Y = 6056c0ee827e85ba284838954d0c6cc096df03b4611b1e0f7f9002bac86856d4
+Digest = 3f9a97b8ea807edc88788df8956c296b1daaed8dd12d50c712344091
+R = 2df3906527ad322000285bccdd11dd09130d633cf43534f5802604639eb847e0
+S = adaaad19b7c66836ef0f4afeff8ac5e898cd2523246a74a1a291a3a1ff583322
+
+Curve = P-256
+X = 70b4bba10b7bbc6d4175ada8d485f3685b13916d0c992301f47e45b629c63d0e
+Y = 257a93be31b09ff4cd22e3375e30b5a79f3bf3c74c80dde93e5d65e88c07c1c4
+Digest = cc3a0d3a5d4f28dc9144a3cdb276eb92265f1157a8d8192cf628673c
+R = 6e714a737b07a4784d26bde0399d8eee81998a13363785e2e4fb527e6a5c9e4e
+S = 94c0220f0f3fa66ff24f96717f464b66ae3a7b0f228ab6a0b5775038da13768a
+Invalid =
+
+Curve = P-256
+X = 8b11b48d2397355000a5289d816b9892ae64dffc842abec02a2fb2db2bb34310
+Y = fc1a42528a0473cfc2c2e184b8bc5055096350fe1549d24b526d6536681026e8
+Digest = f340e491fa935be8945b8caa485d0699c66331e0e17c7407da1b018e
+R = 61a91dd1c80049e70dc4aea84bda0efc6ec9c7b9dd16ecbccf687244c51184ce
+S = e381e7b32bab49578c7e7ce7784ce19263e4a7dab4b614df411d20eaebfc391c
+Invalid =
+
+Curve = P-256
+X = 7bad1b3d8bad4355a44511d2eb50daeae793af99418ada118327359936aa0e1d
+Y = e7eff40334b7a5455f6b0d0ecdcdc513702857bb5bbb73c910c86746092bcd7d
+Digest = 9cf84546c046b370c372c167ebba39af6aadd60463626453787bb058
+R = fd961b60b21be32b47abafa77e22197dc99af6825dcca46e0e3b1991a90aa202
+S = a0477f97b94a1c26a3b2d186791d7fc9dfa8130bbae79c28fa11ec93a3aeac0b
+Invalid =
+
+Curve = P-256
+X = 407d92c9b28723602bf09f20f0de002afdf90e22cb709a8d38e3c51e82cba96c
+Y = 4530659432e1dd74237768133e1f9808e62d0fbe5d1d979d1571baf645dcb84c
+Digest = 0cf5cd48c93f45472d254196bebea4bddb272a2adff23bab8c3adf99
+R = a7dc65293ee3deb0008ae3e2d7ef9e9a4ebb8bf7b10d165f80ab8bed58d6fdef
+S = 3e8300a3ee603a8d8234fe265c628e705015bf1903eb74c943323050626f701f
+Invalid =
+
+Curve = P-256
+X = 26aea3dd5c53f984dbdaf415c7f26e1e73048658a548eb3b59dd5f721899919a
+Y = dff15f57bd9b08644d49cbb214403647195725cd4d4511bc8a48b0770466ae9f
+Digest = 75d6b6b575d0a2c89528b83c94ef864c825b66253ab662b36bb0e716
+R = 726af92afe53e8125b0b9f3659745be401a37ae658b7b1aa88c3cb97e9de22c3
+S = 794484c5837a419efe11a4e4293341a6fa36d21230925a0e5e135887302acca9
+Invalid =
+
+Curve = P-256
+X = e73418677ce044b331a6d60773cbae199221699d31e1bec4b68b9bc0b87e4cd0
+Y = 37215db4e3d9161f3351b385a61ddb2fcf1cec469d1659e7574610ed27fe879f
+Digest = dcbb92e3be3951d37e37852d508f78da29c8183c5dbe59d6549f78ed
+R = ac469290a8f61a2a8c6adc7533dd5cfe804e2e7bf101cc74e5f624f301bccd23
+S = 4c328c3bc259316641fff44753743afebe89b8627f904df7245e42adcff2dc76
+Invalid =
+
+Curve = P-256
+X = b0892b19c508b3543a5ae864ba9194084c8f7ae544760759550cc160972e87ff
+Y = 9208e9b0c86ad6bc833e53026f233db9a42298cdb35d906326008377520b7d98
+Digest = 90333facb4f5068c1d05d1a478fb46d02f367e271a000474c06a5fec
+R = a62dd0d1518c6b9c60de766b952312a8d8c6eaa36a68196d2a30a46fb17dc067
+S = b9ded660e978129277f74c1d436003d1e6d556dc8eed9d505bbaf4c67cb13d21
+Invalid =
+
+Curve = P-256
+X = 8c5c41cb07d828a6a86be4533aef791d3a70a95cb285aa2956b21feeac2f8c49
+Y = 84101581cad7a48b7d0596df7ffed47085d22e8a4af685cddbeeb32ea69ae190
+Digest = 8bb52bd045c985167f673c07b613a3402f435a54c122877bc0c5fe34
+R = 9812449df0a51f7a2a8f78aa9a589ca9644dce285f1e69658daaea759fa5bd7e
+S = beb4c27c748a7944e37afe861576f76b5a749a8ccbbd7dec00838ba250ddfe1a
+Invalid =
+
+Curve = P-256
+X = 788d7e54ab03020e4954f41259052ee5af68361492b180da31fbbe68d868aa95
+Y = 982a3ababa6d351649e56da3faeb7160b9de74e22fe93a06ead1bd9a8dffdf7e
+Digest = 9870ae25b0f0403eff1079b94669cf95fb250fb098eeb885ff08f117
+R = 3ddea06bf8aa4a1b0c68674a2c4796def0bfb52236f4efb3332204a41fd8ea89
+S = 871237039431a41aeefcdd08f67848b2b09067e3a1344c8ed9b372d1b1c754a6
+Invalid =
+
+Curve = P-256
+X = 87f8f2b218f49845f6f10eec3877136269f5c1a54736dbdf69f89940cad41555
+Y = e15f369036f49842fac7a86c8a2b0557609776814448b8f5e84aa9f4395205e9
+Digest = a82c31412f537135d1c418bd7136fb5fde9426e70c70e7c2fb11f02f30fdeae2
+R = d19ff48b324915576416097d2544f7cbdf8768b1454ad20e0baac50e211f23b0
+S = a3e81e59311cdfff2d4784949f7a2cb50ba6c3a91fa54710568e61aca3e847c6
+Invalid =
+
+Curve = P-256
+X = 5cf02a00d205bdfee2016f7421807fc38ae69e6b7ccd064ee689fc1a94a9f7d2
+Y = ec530ce3cc5c9d1af463f264d685afe2b4db4b5828d7e61b748930f3ce622a85
+Digest = 5984eab8854d0a9aa5f0c70f96deeb510e5f9ff8c51befcdc3c41bac53577f22
+R = dc23d130c6117fb5751201455e99f36f59aba1a6a21cf2d0e7481a97451d6693
+S = d6ce7708c18dbf35d4f8aa7240922dc6823f2e7058cbc1484fcad1599db5018c
+Invalid =
+
+Curve = P-256
+X = 2ddfd145767883ffbb0ac003ab4a44346d08fa2570b3120dcce94562422244cb
+Y = 5f70c7d11ac2b7a435ccfbbae02c3df1ea6b532cc0e9db74f93fffca7c6f9a64
+Digest = 44b02ad3088076f997220a68ff0b27a58ecfa528b604427097cce5ca956274c5
+R = 9913111cff6f20c5bf453a99cd2c2019a4e749a49724a08774d14e4c113edda8
+S = 9467cd4cd21ecb56b0cab0a9a453b43386845459127a952421f5c6382866c5cc
+Invalid =
+
+Curve = P-256
+X = e424dc61d4bb3cb7ef4344a7f8957a0c5134e16f7a67c074f82e6e12f49abf3c
+Y = 970eed7aa2bc48651545949de1dddaf0127e5965ac85d1243d6f60e7dfaee927
+Digest = d1b8ef21eb4182ee270638061063a3f3c16c114e33937f69fb232cc833965a94
+R = bf96b99aa49c705c910be33142017c642ff540c76349b9dab72f981fd9347f4f
+S = 17c55095819089c2e03b9cd415abdf12444e323075d98f31920b9e0f57ec871c
+
+Curve = P-256
+X = e0fc6a6f50e1c57475673ee54e3a57f9a49f3328e743bf52f335e3eeaa3d2864
+Y = 7f59d689c91e463607d9194d99faf316e25432870816dde63f5d4b373f12f22a
+Digest = b9336a8d1f3e8ede001d19f41320bc7672d772a3d2cb0e435fff3c27d6804a2c
+R = 1d75830cd36f4c9aa181b2c4221e87f176b7f05b7c87824e82e396c88315c407
+S = cb2acb01dac96efc53a32d4a0d85d0c2e48955214783ecf50a4f0414a319c05a
+
+Curve = P-256
+X = a849bef575cac3c6920fbce675c3b787136209f855de19ffe2e8d29b31a5ad86
+Y = bf5fe4f7858f9b805bd8dcc05ad5e7fb889de2f822f3d8b41694e6c55c16b471
+Digest = 640c13e290147a48c83e0ea75a0f92723cda125ee21a747e34c8d1b36f16cf2d
+R = 25acc3aa9d9e84c7abf08f73fa4195acc506491d6fc37cb9074528a7db87b9d6
+S = 9b21d5b5259ed3f2ef07dfec6cc90d3a37855d1ce122a85ba6a333f307d31537
+Invalid =
+
+Curve = P-256
+X = 3dfb6f40f2471b29b77fdccba72d37c21bba019efa40c1c8f91ec405d7dcc5df
+Y = f22f953f1e395a52ead7f3ae3fc47451b438117b1e04d613bc8555b7d6e6d1bb
+Digest = 8a3e7ad7b9b1b0cdc48e58d1e651fe6d710fef1420addeb61582bdd982d2b44c
+R = 548886278e5ec26bed811dbb72db1e154b6f17be70deb1b210107decb1ec2a5a
+S = e93bfebd2f14f3d827ca32b464be6e69187f5edbd52def4f96599c37d58eee75
+Invalid =
+
+Curve = P-256
+X = 69b7667056e1e11d6caf6e45643f8b21e7a4bebda463c7fdbc13bc98efbd0214
+Y = d3f9b12eb46c7c6fda0da3fc85bc1fd831557f9abc902a3be3cb3e8be7d1aa2f
+Digest = d80e9933e86769731ec16ff31e6821531bcf07fcbad9e2ac16ec9e6cb343a870
+R = 288f7a1cd391842cce21f00e6f15471c04dc182fe4b14d92dc18910879799790
+S = 247b3c4e89a3bcadfea73c7bfd361def43715fa382b8c3edf4ae15d6e55e9979
+Invalid =
+
+Curve = P-256
+X = bf02cbcf6d8cc26e91766d8af0b164fc5968535e84c158eb3bc4e2d79c3cc682
+Y = 069ba6cb06b49d60812066afa16ecf7b51352f2c03bd93ec220822b1f3dfba03
+Digest = 7c1048884558961c7e178b3a9b22583fca0d17f355a9887e2f96d363d2a776a3
+R = f5acb06c59c2b4927fb852faa07faf4b1852bbb5d06840935e849c4d293d1bad
+S = 049dab79c89cc02f1484c437f523e080a75f134917fda752f2d5ca397addfe5d
+Invalid =
+
+Curve = P-256
+X = 224a4d65b958f6d6afb2904863efd2a734b31798884801fcab5a590f4d6da9de
+Y = 178d51fddada62806f097aa615d33b8f2404e6b1479f5fd4859d595734d6d2b9
+Digest = 4c8d1afb724ad0c2ec458d866ac1dbb4497e273bbf05f88153102987e376fa75
+R = 87b93ee2fecfda54deb8dff8e426f3c72c8864991f8ec2b3205bb3b416de93d2
+S = 4044a24df85be0cc76f21a4430b75b8e77b932a87f51e4eccbc45c263ebf8f66
+Invalid =
+
+Curve = P-256
+X = 43691c7795a57ead8c5c68536fe934538d46f12889680a9cb6d055a066228369
+Y = f8790110b3c3b281aa1eae037d4f1234aff587d903d93ba3af225c27ddc9ccac
+Digest = 8581034ec7d7a6b163d71820923f616b362748f2846042c9896d8e4bf7577960
+R = 8acd62e8c262fa50dd9840480969f4ef70f218ebf8ef9584f199031132c6b1ce
+S = cfca7ed3d4347fb2a29e526b43c348ae1ce6c60d44f3191b6d8ea3a2d9c92154
+Invalid =
+
+Curve = P-256
+X = 9157dbfcf8cf385f5bb1568ad5c6e2a8652ba6dfc63bc1753edf5268cb7eb596
+Y = 972570f4313d47fc96f7c02d5594d77d46f91e949808825b3d31f029e8296405
+Digest = e5b30e0041a33281210644938d9aaa15ef2c1247b4178f7ca1ee935ce23daabc
+R = dfaea6f297fa320b707866125c2a7d5d515b51a503bee817de9faa343cc48eeb
+S = 8f780ad713f9c3e5a4f7fa4c519833dfefc6a7432389b1e4af463961f09764f2
+Invalid =
+
+Curve = P-256
+X = 072b10c081a4c1713a294f248aef850e297991aca47fa96a7470abe3b8acfdda
+Y = 9581145cca04a0fb94cedce752c8f0370861916d2a94e7c647c5373ce6a4c8f5
+Digest = edd72dc0aa91649e09e2489c37ec27efab3b61953762c6b4532a9b1cd08a500d
+R = 09f5483eccec80f9d104815a1be9cc1a8e5b12b6eb482a65c6907b7480cf4f19
+S = a4f90e560c5e4eb8696cb276e5165b6a9d486345dedfb094a76e8442d026378d
+Invalid =
+
+Curve = P-256
+X = 09308ea5bfad6e5adf408634b3d5ce9240d35442f7fe116452aaec0d25be8c24
+Y = f40c93e023ef494b1c3079b2d10ef67f3170740495ce2cc57f8ee4b0618b8ee5
+Digest = 0d06ba42d256062e16b319a0f3099109518a765f26bac3b9f56930d965617726
+R = 5cc8aa7c35743ec0c23dde88dabd5e4fcd0192d2116f6926fef788cddb754e73
+S = 9c9c045ebaa1b828c32f82ace0d18daebf5e156eb7cbfdc1eff4399a8a900ae7
+Invalid =
+
+Curve = P-256
+X = 2d98ea01f754d34bbc3003df5050200abf445ec728556d7ed7d5c54c55552b6d
+Y = 9b52672742d637a32add056dfd6d8792f2a33c2e69dafabea09b960bc61e230a
+Digest = 41007876926a20f821d72d9c6f2c9dae6c03954123ea6e6939d7e6e669438891
+R = 06108e525f845d0155bf60193222b3219c98e3d49424c2fb2a0987f825c17959
+S = 62b5cdd591e5b507e560167ba8f6f7cda74673eb315680cb89ccbc4eec477dce
+
+Curve = P-256
+X = 40ded13dbbe72c629c38f07f7f95cf75a50e2a524897604c84fafde5e4cafb9f
+Y = a17202e92d7d6a37c438779349fd79567d75a40ef22b7d09ca21ccf4aec9a66c
+Digest = 5aa8e8a6f0622b841416e1a70d79a54641d2c699a075b6960fe5dcf96301da8ca6f15b0948d4ededac30a42e00d3b310
+R = be34730c31730b4e412e6c52c23edbd36583ace2102b39afa11d24b6848cb77f
+S = 03655202d5fd8c9e3ae971b6f080640c406112fd95e7015874e9b6ee77752b10
+Invalid =
+
+Curve = P-256
+X = 1f80e19ffeb51dd74f1c397ac3dfd3415ab16ebd0847ed119e6c3b15a1a884b8
+Y = 9b395787371dbfb55d1347d7bed1c261d2908121fb78de1d1bf2d00666a62aed
+Digest = 244656186c11c2e67be88099d55e60f4b68e61fba0b214aac3399dc559cfccc02f9884e85623426dbdc3243f2b5374f7
+R = 249ca2c3eb6e04ac57334c2f75dc5e658bbb485bf187100774f5099dd13ef707
+S = 97363a05202b602d13166346694e38135bbce025be94950e9233f4c8013bf5bf
+Invalid =
+
+Curve = P-256
+X = ce4dcfa7384c83443ace0fb82c4ac1adfa100a9b2c7bf09f093f8b6d084e50c2
+Y = d98ae7b91abee648d0bfde192703741ac21daad7262af418b50e406d825eb0d6
+Digest = adaeadda3f0e941fba1d3e206a84e6d7530d800e0f215b3ddd82022f27c5be44fed27bc73084c6f7ca55555532be2e3b
+R = 597e1e04d93a6b444ccc447a48651f17657ff43fb65fe94461d2bf816b01af40
+S = 359fe3817963548e676d6da34c2d0866aa42499237b682002889eaf8893814d2
+
+Curve = P-256
+X = 1b677f535ac69d1acd4592c0d12fac13c9131e5a6f8ab4f9d0afdcb3a3f327e0
+Y = 5dca2c73ec89e58ef8267cba2bb5eb0f551f412f9dc087c1a6944f0ce475277a
+Digest = e34a541f87ff0eaa0c640f555caec6bf11a1320c74c47a8ff172c4e2ec902e48d499732b12a86189e750bbf4c0424c72
+R = df0b0cd76d2555d4c38b3d70bfdf964884d0beeb9f74385f0893e87d20c9642d
+S = 128299aabf1f5496112be1fe04365f5f8215b08a040abdfeca4626f4d15c005b
+Invalid =
+
+Curve = P-256
+X = 7ffc2853f3e17887dda13b0eb43f183ce50a5ac0f8bba75fb1921172484f9b94
+Y = 4cc523d14192f80bd5b27d30b3b41e064da87bfbae15572dd382b9a176c123a2
+Digest = 0689927a38486cccf28fe9454e08e0d74843424b89be4cdee8e48f39a69addec730184da72f914cea67231c765ee2574
+R = 3156176d52eb26f9391229de4251993a41b8172f78970bb70e32a245be4bb653
+S = 62827a29e12d2f29b00fb2d02dd5f2d5412e17a4455f4431a5c996881fdfc0ee
+Invalid =
+
+Curve = P-256
+X = 5569f76dc94243cde819fb6fc85144ec67e2b5d49539f62e24d406d1b68f0058
+Y = 1208c38dbe25870deab53c486f793a1e250c9d1b8e7c147ea68b71196c440730
+Digest = 97f8f8cea435282ac746730ac744bf97d85d4e249c0b1d9c7b83c7e59aed172ffc3724d7e6fab7d6ab55ffb3a39c0775
+R = 706f2ba4025e7c06b66d6369a3f93b2fec46c51eceff42a158f7431919506cfb
+S = b4e75ac34a96393237fc4337789e37168d79382705b248051c9c72bcbac5f516
+Invalid =
+
+Curve = P-256
+X = e4b470c65b2c04db060d7105ec6911589863d3c7f7ce48726ba3f369ea3467e8
+Y = 44c38d3ae098de05f5915a5868c17fee296a6e150beb1f000df5f3bec8fc4532
+Digest = 5b937a2af46dbf18b4a6fb042ea353a6878e0d4beac016002b3d91a42bcba52856c07a3f35c08dfecb4f03e1c0b9948e
+R = c9c347ee5717e4c759ddaf09e86f4e1db2c8658593177cfda4e6514b5e3ecb87
+S = baae01e9e44a7b04d69c8eaaed77c9e3a36ce8962f95cc50a0db146b4e49eb40
+Invalid =
+
+Curve = P-256
+X = 96050c5fa2ddd1b2e5451d89ee74a0b7b54347364ddc0231715a6ef1146fe8dc
+Y = e0888a9e78aeea87f6e1e9002b2651169f36c4ee53013cfc8c9912b7fd504858
+Digest = b123e07744f05ad523790ea5bfa3f848869a3bfdbf936a496c8606b577ed8427eb7ee888e0fe18d4e3cfac73baad883f
+R = 2353d6cd3c21b8ea7dbc1cd940519812dbe365a3b15cd6aebba9d11cf269867a
+S = 85f560273cd9e82e6801e4cb1c8cd29cdac34a020da211d77453756b604b8fa7
+
+Curve = P-256
+X = 0c07bb79f44012299fbfd5a0f31397aaf7d757f8a38437407c1b09271c6551a0
+Y = 84fe7846d5d403dc92c0091fbd39f3c5cbca3f94c10b5cae44e2e96562131b13
+Digest = fb8d12652de59e63ef5297641dfbce084808de146720e9069c2ef814bcd80b6187f7422a6cd9c706f8d64ccf80e8bc54
+R = 49e9425f82d0a8c503009cead24e12adc9d48a08594094ca4f6d13ad1e3c571d
+S = 1f1b70aaa30a8ff639aa0935944e9b88326a213ab8fce5194c1a9dec070eb433
+Invalid =
+
+Curve = P-256
+X = 71db1de1a1f38f356c91feaff5cfe395d1a5b9d23cf6aa19f38ae0bcc90a486d
+Y = ecdd6ffb174a50f1cc792985c2f9608c399c98b8a64a69d2b5b7cdd9241f67e2
+Digest = 2d8c6585a3b6319a556e27b53d434f455f73e771c8fc6a115f5c92a8e9a81ce2b4336a5c3edf98910689d11f4c93632a
+R = b0443b33a6f249470d2f943675009d21b9ccbead1525ae57815df86bb20470bf
+S = 316dbee27d998e09128539c269e297ac8f34b9ef8249a0619168c3495c5c1198
+Invalid =
+
+Curve = P-256
+X = 8219b225aa15472262c648cac8de9aad4173d17a231ba24352a5a1c4eea70fad
+Y = 0fee2b08ad39fbf0db0016ef2896ca99adc07efc8c415f640f3720498be26037
+Digest = a4cc3b23f54d9d48ba6b0ad3da3b2e3a0806f41348bd7844e9c9b8648753bdeef8a039e1fa4f5172c89148d65b14056f
+R = 134fb689101aaad3954de2819d9fbd12072fe2bc36f496bbf0d13fa72114ab96
+S = e65c232bd915b59e087e7fd5ec90bf636cfa80526345c79a0adfd75003045d6f
+Invalid =
+
+Curve = P-256
+X = c934195de33b60cf00461fc3c45dad068e9f5f7af5c7fa78591e95aeb04e2617
+Y = b588dd5f9965fdaa523b475c2812c251bc6973e2df21d9beaace976abf5728cb
+Digest = b962b63a7743ad77f9072f2f08d277f6dda8cc3420ddd37d873746008895902bcce218fbfed1a8cb28406978dd8e5134
+R = 71f302440eb4ed2a939b69e33e905e6fdc545c743458d38f7e1a1d456e35f389
+S = 54eaa0eb9cd7503b19a9658f0a04955d9f0ab20ebc8a0877e33c89ee88ad068f
+Invalid =
+
+Curve = P-256
+X = 9e1adcd48e2e3f0e4c213501808228e587c40558f52bb54ddbb6102d4048ea92
+Y = 34eff98704790938e7e0bdf87ae39807a6b77dfdc9ecdfe6dd0f241abae1aeb2
+Digest = 21b883fae159867731b123a2606e9b3320fb53a00e4a5dfe3bc3429dd53b8068197be3c7288c1e0bf28a4fc7b13bd70f
+R = ce4f0d7480522c8dd1b02dd0eb382f22406642f038c1ede9411883d72b3e7ed0
+S = 8546e1ee3b77f9927cdaccbc2f1cf19d6b5576b0f738bb1b86a0c66b39ca56fb
+Invalid =
+
+Curve = P-256
+X = 93edbecb0b019c2cc03060f54cb4904b920fdb34eb83badd752be9443036ae13
+Y = b494e9295e080a9080fe7e73249b3a5904aa84e1c028121eecd3e2cf1a55f598
+Digest = fcc17b88077570c053650e1de42ae6bb1522900b38996decc87704aab6a87ab01d52f83f6442875f378a262c22d23ab2
+R = eec2986d47b71995892b0915d3d5becc4dcb2ab55206d772e0189541b2184ddf
+S = 8a6c1edeb6452627ad27c8319599c54ac44cdd831ea66f13f49d90affe6ad45b
+
+Curve = P-256
+X = 3205bae876f9bd50b0713959e72457165e826cbbe3895d67320909daa48b0ebc
+Y = d1592562273e5e0f57bbfb92cedd9af7f133255684ee050af9b6f02019bbcafa
+Digest = 299a6070d32a5557010753d7559dbd8d2bde8a8feae5417616ceb5b167997fd2fac0c2bd44264106d3a9720d5e805a04
+R = 0124f3f1c61ec458561a4eaa6c155bd29e59703d14556324924683db3a4cf43b
+S = 688a5c5fc0c7ba92210c50cce5b512a468a880e05acc21ca56571d89f45f603a
+Invalid =
+
+Curve = P-256
+X = 484e31e69ef70bb8527853c22c6b6b4cd2a51311dde66c7b63f097dbb6ab27bf
+Y = e1ff8177f4061d4fbbacbbc70519f0fc8c8b6053d72af0fe4f048d615004f74e
+Digest = f1e9cda2e096ece9a1fc57e55eeeb56b1c635380c0f9a1800a4a1a5f105d1fc0c60e776234daaa8a6f7c0f5286bb420b3f607e7cc0a7d840ad5dcbab26c797b0
+R = 91a303d8fe3ab4176070f6406267f6b79bfe5eb5f62ae6aeb374d90667858518
+S = e152119cefa26826ea07ec40a428869132d70812c5578c5a260e48d6800e046a
+Invalid =
+
+Curve = P-256
+X = 8b75fc0129c9a78f8395c63ae9694b05cd6950665cf5da7d66118de451422624
+Y = b394171981d4896d6e1b4ef2336d9befe7d27e1eb87f1c14b8ddda622af379dc
+Digest = 0527199fadea30f9e5e66166a3ebcdf6aedf906984535f48165e591eff36f1c0de6b0fa69aefb6399e8a213cc2ce53268fbe18c3471b7708bc27c426aaa769a4
+R = 17e298e67ad2af76f6892fdcead00a88256573868f79dc74431b55103058f0b0
+S = 881328cd91e43d30133f6e471e0b9b04353b17893fb7614fd7333d812a3df6b4
+Invalid =
+
+Curve = P-256
+X = 76e51086e078b2b116fd1e9c6fa3d53f675ae40252fb9f0cc62817bd9ce8831d
+Y = ca7e609a0b1d14b7c9249b53da0b2050450e2a25cb6c8f81c5311974a7efb576
+Digest = c926a5026d8f83ffa2092caf863f2d8a886af391462969b13a11d3c6c5fa66bb4281bc6e60a1e99a2e1ae95d689a66282096a0f27aacc048f32d39297649a014
+R = 23b653faaa7d4552388771931803ce939dd5ee62d3fa72b019be1b2272c85592
+S = a03c6f5c54a10861d6b8922821708e9306fd6d5d10d566845a106539cbf4fadd
+Invalid =
+
+Curve = P-256
+X = bc7c8e09bd093468f706740a4130c544374fdc924a535ef02e9d3be6c6d3bbfa
+Y = af3f813ae6646f5b6dbfb0f261fd42537705c800bb1647386343428a9f2e10fc
+Digest = 4d74631eb67fd1a6fa93ecb6e6112b6699e78c1d4c24ae81d0d5842efe5d93c2fd7a7863f8d45d1b2fafecbe41b7dc19c4b2bc208e014ffdc216e7eda0392a70
+R = 6bd7ce95af25abfbf14aef4b17392f1da877ab562eca38d785fe39682e9c9324
+S = 6688bea20c87bab34d420642da9bdd4c69456bdec50835887367bb4fb7cd8650
+Invalid =
+
+Curve = P-256
+X = 9cb0cf69303dafc761d4e4687b4ecf039e6d34ab964af80810d8d558a4a8d6f7
+Y = 2d51233a1788920a86ee08a1962c79efa317fb7879e297dad2146db995fa1c78
+Digest = 0250f93e6932887df519921f9a8dcff110be0768dc351ef73a940a579fae2d20061759e892e289c3e4ba5f7fe17d6ebb15c5931d48db55ebc81549f6637292fe
+R = 4b9f91e4285287261a1d1c923cf619cd52c175cfe7f1be60a5258c610348ba3d
+S = 28c45f901d71c41b298638ec0d6a85d7fcb0c33bbfec5a9c810846b639289a84
+
+Curve = P-256
+X = e31096c2d512fbf84f81e9bdb16f33121702897605b43a3db546f8fb695b5f6f
+Y = 6fbec6a04a8c59d61c900a851d8bf8522187d3ec2637b10fa8f377689e086bba
+Digest = f91b09107d10904d3968ec29f85e456ac4e828f32e8da3db6a13f5566bfa625e2ad03f8dad5425a073c0d61d25de63dcafa9f4fcd206f29e9cb6b0fecd74aa57
+R = 1b244c21c08c0c0a10477fb7a21382d405b95c755088292859ca0e71bab68361
+S = 852f4cbfd346e90f404e1dd5c4b2c1debca3ea1abefe8400685d703aea6c5c7f
+Invalid =
+
+Curve = P-256
+X = 633c2ee5630b62c9ce839efd4d485a6d35e8b9430d264ffe501d28dbace79123
+Y = 4b668a1a6d1a25b089f75c2bd8d8c6a9a14fe7b729f45a82565da2e866e2c490
+Digest = 575c64df58c8dc517ce65b388fa3ed69470163afecbabc3fa94b497ff7f3fe36ff12fabe2b84cebbf667744195091e4e2335a71d36414e0af0d0260fc8e8ea44
+R = bf2111c93ec055a7eda90c106fce494fd866045634fd2aa28d6e018f9106994e
+S = 86b0341208a0aa55edecfd272f49cb34408ce54b7febc1d0a1c2ce77ab6988f8
+Invalid =
+
+Curve = P-256
+X = f78dce40d1cb8c4af2749bf22c6f8a9a470b1e41112796215dd017e57df1b38a
+Y = 61b29b0bc03dff7fa00613b4de1e2317cfbf2badd50dee3376c032a887c5b865
+Digest = 4c097f2f5b2489c94258b34d529675bb5d77d4be083b51b01188dd42b4b5473982728763ee6fbad479375c5eacb5edaaec0b6583a10b19aad81ec88dde2d0e7f
+R = 4a96169a5dea36a2594011537ee0dc19e8f9f74e82c07434079447155a830152
+S = a204eaa4e97d7553a1521d9f6baadc0b6d6183ba0f385d8593d6ca83607c4d82
+Invalid =
+
+Curve = P-256
+X = 3fcc3b3e1b103fe435ac214c756bdaad309389e1c803e6d84bbbc27039fcf900
+Y = 7f09edd1ec87a6d36dc81c1528d52a62776e666c274415a9f441d6a8df6b9237
+Digest = 1a3dd21cb6ac1fa7fc196319cf534b7608afb93805420fcb5250dff453564a5b22e22971a3ce6dd222405fea018cd0508d86c561eca15e1ac7d79c14e916b86a
+R = 1cac13f277354456ae67ab09b09e07eb1af2a2bf45108da70f5c8c6a4cbcd538
+S = 5d83752e540525602ba7e6fee4d4263f3eda59e67df20aac79ca67e8899fed0d
+Invalid =
+
+Curve = P-256
+X = 5ec702d43a67ada86efbfc136cf16d96078906954a3f1f9e440674cd907e4676
+Y = 05a62044fed8470dd4fca38d89d583ce36d50d28b66ab0b51922b21da92c56d9
+Digest = c5c016f6c9b525987dd835131def77cc72d8360d364eeccdd7af8b95712b6cd487c0b846201f3b64466fd140833514ae8d765da395fbd9d3c03ca410effa9a69
+R = 75f3037298f1457dba55743999976a1c2636b2b8ab2ed3df4736a6d2934acc83
+S = 19d43ad168dda1bb8ac423f8f08876515234b3d841e57faef1b5ab27359b27ef
+Invalid =
+
+Curve = P-256
+X = f63afe99e1b5fc652782f86b59926af22e6072be93390fe41f541204f9c935d1
+Y = f6e19ce5935e336183c21becf66596b8f559d2d02ee282aa87a7d6f936f7260c
+Digest = 9eb2f9fa96a1f3ffcef9600522730e86d26d328ec0c1bf2fbfe55a38754610341fda1b894fdcf10c9bc4f48819010fdcf0d24f27ff539e40c6855cafbd306386
+R = cef4831e4515c77ca062282614b54a11b7dc4057e6997685c2fbfa95b392bf72
+S = f20dc01bf38e1344ba675a22239d9893b3a3e33d9a403329a3d21650e9125b75
+
+Curve = P-256
+X = 6d11b09d2767cf8d275faee746c203486259f66dd2bfa3a65c39371a66b23385
+Y = 4eb05c73e05261e979182833f20311e5366f72f4b949665ff294f959375534c6
+Digest = 0e71b28b0a1eac7aa881c09daec616c93d9a9286b5f5fdf2642d211021b125fa884b2595b73c7c3e649e61cd7157ef6660076a3b87ddf830db46533f3aa30afa
+R = 15a697cdb614e11c0810e1e764cd501fcabc70874c957587bc4883d9438e177f
+S = 7bf6244f92bc768063cecb5336c8eaacd23db930b28703560f241c7d93950dfd
+Invalid =
+
+Curve = P-256
+X = f3899caba038efb534c4cea0bd276814ffd80194473c903b81af11c8c05cb6e6
+Y = 6ea6b17402fcf2e8e737d11ffc7c2ed3b2d0bc3b8f271a381f4294cff62682c3
+Digest = 104ace16689d785df09a81c5cf47a496db30fbd696aa4df080219487575a23641436e70329dd1c13290582c0d03aae200e51189d43666c86f38a5203c16cd7e4
+R = 57b99380452e1d37b133c49b9ba493dee8630940477ca3351a43d90b99871e6a
+S = df599c3a37105af3ecc159b3b685ccb3e151b7d5cf2d97147974ae71f466b615
+Invalid =
+
+Curve = P-256
+X = 1fd6f4b98d0755291e7a230e9f81ecf909e6350aadb08e42a3262ff19200fbd2
+Y = 5578fef79bc477acfb8ed0dc10c4f5809c14dc5492405b3792a7940650b305d7
+Digest = 761a54f3718985b6d7bcfdd57d6c4823f854831bd29305fcb07e34e3f825d451fca28a62ce9582e3957d89ea7c1bc1afe3aa58fd2fa18566974600fc394cf2a8
+R = 97a99e96e407b3ada2c2dcf9ceeeb984d9a4d0aa66ddf0a74ca23cabfb1566cc
+S = 0ecac315dc199cfea3c15348c130924a1f787019fe4cd3ae47ca8b111268754a
+Invalid =
+
+Curve = P-256
+X = 2dcbd8790cee552e9f18f2b3149a2252dcd58b99ca7dc9680b92c8c43aa33874
+Y = 5dbc8bb8813c8e019d80e19acdb0792f537980fecde93db621aaf1f6d0e6ee34
+Digest = 45b082e804443b53a82229cdf13e4c5f8f31fe93170cc8a23f63eef506cb7748388e1a971a2f81e3daa324cf2bb69118f7418f40df66a24f50c34a55e1416c3a
+R = 2bdbd8b0d759595662cc10b10236136ef6ce429641f68cf6480f472fcc77bc9f
+S = 7e7df0c8b86f7db06caf1610166f7b9c4c75447f991d5aaf4dea720c25985c8c
+
+Curve = P-384
+X = 6881154cfe3f09affbee04cd387b27b7854326faf8906c4b9c9e6ac2c632e0d59717b3f33f6d747d7b7cbb4e4dc01fb8
+Y = ba295ae0966f06ad9d84b3bb4da7f99b56044c99f88d71082cfea6964ea3c63bb79806a6a41fcc314b55b3f64f82b68a
+Digest = 8a6429d55885146f7aab582a1aa9360fa9591b0a
+R = 2112385a75d4edda89ae2bc3c74524dc792544a3a52fdb588da3f0feaee6a11623db275e2ab8abdd998cc42a29c60856
+S = 8d308a3987b81c595f8cec19898b1a42da8eda97496af280033b0f915283f171fed7e2a221fa9c78927962189333f437
+Invalid =
+
+Curve = P-384
+X = 2f2f43f244ae027c3d2ec5c900393f80a8ad0e9b9a12a047195d29a39f2b7026b071688dd9a6764379d02a5ed8035ec1
+Y = e43d45851bc76c37d34dbed996a65ffcfbbaf0e2cbfbc9f62d2116bdf3b330bbef5acdbcd0aa6d949f771daa17cda1e3
+Digest = 5f41322db1a276042ae807f0f0d6f1e04cb5cd26
+R = c011c52e9cb02048957a233704ff9a2c1d4c56e08ebb083aa8ba351f041a23a7d0da19088ac6c60ea2ca117531c7cf35
+S = a66ca9bf06c35d129a8253a0f793acf681e482d9994868b275a230b215286e03a66a0de77c7a53174375137fd4688556
+Invalid =
+
+Curve = P-384
+X = 9a5e1932d318bfa7986f0dac4489c6f55775427bb60fb24bac7646b9994bbc3a9b5cd15e818cc4e832afc1c3fca9abae
+Y = 64c89e7c3399c136b2718ab675944207157f0bf23d9e2a807ae7ac3bef81da7ec3c56c2d2c08afc53301af2a3cc71861
+Digest = d36ef9ee70a3b61ba31cdfcd0cac6e49331a407f
+R = 4cf6c63fea6c80efc105cd99afe2b53da05ae16566ddb20b9d40a076575ffac419b6807fa336fc6e7c7416c59775ef09
+S = aec2d96054b4b23c49faaf9903ccf63bc96281fb7c1b9d14daa54bba51bb2b2f4d3a901f3b0b9cb2b62976459219350c
+Invalid =
+
+Curve = P-384
+X = b3aeff27b65540c6da10a88008404b1d49239c87fbf47932518fb87a9bb132403d1f310f531d086340bb4a68c3e64b9b
+Y = 567e75f442fcd81017b8adc4cce634f5ffa3cd497d38221d34dc1f43aef99133131ff1b197f7b9f37beecae5c438849a
+Digest = dd0f9c326fb50593fd0a0df31abeeb00a22eb956
+R = 3b94a2514eb915b71e18c867ad7f508a35375c5bcd4b797b86054798569870b2477e2ac14406628017d829400efc63b2
+S = 179a10441a0beea3b375248e697e0d19e24bb68184c373fe4302839b97dd7353a5a25929c2733796b0c0d8211bd67c51
+Invalid =
+
+Curve = P-384
+X = 0874a2e0b8ff448f0e54321e27f4f1e64d064cdeb7d26f458c32e930120f4e57dc85c2693f977eed4a8ecc8db981b4d9
+Y = 1f69446df4f4c6f5de19003f45f891d0ebcd2fffdb5c81c040e8d6994c43c7feedb98a4a31edfb35e89a30013c3b9267
+Digest = a871caf9fff9856031a79a55b96753c1a34ccb73
+R = 8d9d3e3d0b2b2871ea2f03f27ba8699f214be8d875c0d770b0fff1c4ce341f0c834ac11f9ec12bfdb8320b1724c8c220
+S = 62150dfba8e65c0c7be7ef81c87241d2c37a83c27eb31ccc2b3c3957670a744c81be6d741340b5189cc0c547df81b0d2
+
+Curve = P-384
+X = b4b92211edbd41c5468d2ba70810bc37b5e7c954c7bd0db80c4fa89ccba10bf07cdab953828a068bc0104d28e4040c14
+Y = 93ed318efce3dff98fc782b788d78658ea5ecde4f716e2d5d0ec2d87a2e761daa1f1658cfb857762caa567baaccf9924
+Digest = 765343d50541bc2c0e20193648048016a95e7588
+R = aa3978eabd196ddf9cab2815cc9cbab0b61cd639deaf70e093a10a58ddf9f410ee1ab965ff8fbb98efbe812421a613d3
+S = 02761a2947e1855806b8a25b9ebb0762be9f5517461a371e5783f34b184f32c4ea684b362119b1a2d8a3ff439f10291f
+
+Curve = P-384
+X = 63b4cc14f9efd3b8f29e65806591d1e9c54f34a3f5231339bcdbfa4109c42d946a59cdd7bbd2591fd1b2383a0819772f
+Y = 55ab3d208109da6ef039c23cddd52a5af619266d8fe066dcabb1af885ad5501401a78c44ed3b5fff2892fdcb2a3ac8b2
+Digest = 4535ef8d7396b4f2af65660ebbb56f356cacefd9
+R = a3f9b840fd7201356f35b5dde39027410aad26ac61919c14fe7b0535bb74e7218cb3312bfa60aac63f14166f32ceff26
+S = 1b1bcbcb0237fad4e406c8d4e3e39b55642d8535afa9ccbc9c601cb4e01891df79f1bc792687cb3a5ee7703565c4a13b
+Invalid =
+
+Curve = P-384
+X = f82f82f8f7454ce7a94a040ec0bbb52d49e3b9f8ddd095704973c760ee6067a5c28369656f22d70d8bb1cd70ef9bfea0
+Y = 0e36e256d02870ee5646a17aac4b280c9d1d2e1d4803eb3cb32e7f754cc889522120efd7c4d8a82e509a4d8f266d3ce4
+Digest = 26302c41e6da59e2df2e26c12382738880be94cc
+R = 27a2332f3c59464f5dfe7bb1201a3936248d375bde603724c048eb8f7c0c2be3ed4b56c14b51d7d68bd2554526b36d9e
+S = e1f90367b0cc530c545f95163d9ffb1208c943685d5ae221052b83ee40953397be581e5979c9855b20246e9d26d57acc
+Invalid =
+
+Curve = P-384
+X = 7d40b51127cb1642dd8538d4124138a2f49c41b4d12f702c1b0cec8deba50c3712e01c2e1e693e00438af0e86025da33
+Y = e734b5939b673c45dd32baf20d234f01b7124b391d14beea231e9c604e813fc83b3a77b0cb1f2ce4873a69b0165e369d
+Digest = 0b30b209147432207a72177997d28d6f1d03330f
+R = abf16821b6657e0005071f78c679cbbb130bee6e7ca63526eef0f747fb721feefe6258dae1aa02064a700e963bd9dedf
+S = 3f7e61c34a30cc5ff7a8be375fcc9c38a76dbc0c30a4356843421ca37a7bcf24edcd41d8235903bb522fb6e5a8033885
+Invalid =
+
+Curve = P-384
+X = a5b59d59599c105e39f61354da99c7c9135c749cf996cc2252eb83b008299cdafbcb44227d2d2c4a5ffa44823922893b
+Y = 0399fb0edcbfd0b76b524f22b7b87ddbb4fa02f510661615312a4492eb3f2001e0fc0e479f77c33a88f9a7e20757373c
+Digest = 44aa3083d111bbce7feb412af74a782cd320becd
+R = a4c9cac2409a9bfea1ebe28fec4e19545f08cd18fdd31048f52a3f2d32b2ed859dcae4dc12fb2fecabe542c4f03191ba
+S = b4d83f927ad1980d96cbb0ccc36aa640f786293b8b19e4dd97a797d192b420f630a5e42ac42d8736e7d42008f445dbc1
+Invalid =
+
+Curve = P-384
+X = 29178ce9127e1048ea70c7d435439e9ff9915387e51b7e5ca10bfdafe53565978eb3784d9a4226f443d4834f4d451685
+Y = 5cc2970589a453488649711bdf3cdac9a200519aae65b1c6bd54fed0d965755b36b74d978d674275bd71a03e8f054b0e
+Digest = c679b4a0e61406c4869d721192bd314d77e1cb39
+R = 5d6f5e9a94d9c92a0890c558bc0408b3405cd04e33f663df16701e80520e4394f1c54d3c8225d36f4753a799aaf6ff90
+S = d895b1cc522ceec6a7867867b8f603245c6e4d48945dfc43af721ebae4683d40a3c21b905ca3bd4b974d36806825b2cd
+Invalid =
+
+Curve = P-384
+X = 9f03569f8c6ca2c16d707f0ca36a8a8cf214a9d5c14034829d709e283cd675eb4e3090c6b973429efdf476c0782e0a7c
+Y = e1b842536731e91596782787d57af17db85dc92fd2fb95ac65339174aee66775ce0a4721d1faeb29da968ea5eb705e59
+Digest = ae1a63f88a59c7da5d9f512d11bbd5d75dd1f583
+R = 31ccbe22a360b1786dac89394c6ef4ed6604943e50837395f96052821f6182914840096e90f2ad650917bd91d7bd4cfd
+S = d97199a6b952dcaefb1defe23def92bf2ee236ad18046a2ccf8924d42ee10a62e70ffe7f3c909b11112278f160d98b7a
+
+Curve = P-384
+X = b85e78a935d169dd5ba8f558f964b21c07804464816f9231233184675f557463a8b00470ac0ca8278cd008f4642e7962
+Y = 8edf7be8584c5f207939d479e65173e2e69673090a8538fa93efb4432127895d92b4e4cf13b7632a830e9a33b37f75e1
+Digest = 811685f7ff2701e692f6830a33d8712d0432cd5a
+R = fd2876b250a94ced71734aa7a0d32423b2c6f039c926c557e748f38e23bbdb46e17d1204832c6f76c3ea854e1da23979
+S = 76409e381799502c81194ba87540aec0b89fc4680dd683780d49f82a46a7191b40f5f06ccb02e45e704c31fcd59382b9
+Invalid =
+
+Curve = P-384
+X = 0c74aaa0527524cb6171ab741896b405a6ac4615e474cdc09c9457b18bed33c6383e1b92f2fa1306e8e5dcd1667e45fe
+Y = 7b00d934dfd876f6e07dc0582b20ed650be104fa603a5a1255c62b6059d2685aa9773f1ba31254d213c815d0efc8ed93
+Digest = 328029316d73d1b8d2b8927d12332036e5671384
+R = 832c62b0f34986eda9d1ace5068a0c5318051b0d0166d3dacf137ac072cc359f109ad6e17059e700bb1958bcf4101246
+S = 6bb56f4eb550688ea66e5dd09aebe7e0b39e2716b4697ebb68f113e080f0ff26fd0fc947a34f3c5a8a2f10e07dc1405e
+Invalid =
+
+Curve = P-384
+X = 4104de08b4108ee26ee239e0a5d340c1b1aa48b1b3b40717debd6ed3ff0d777923c106f857a3830ce7f3d08d0d6d7908
+Y = 00498c38393e6393edcf254804558f86e461df1f5a6557bc5144f8d2f3806413d372b6ce417d531c08a52d1e38e8b949
+Digest = a13ebaf4431c43b684d1e18e610a75fd7527200e
+R = 9924a3273248db20db007309560a0e616572ac799d773529a5215786cf4a6e03cc73bea81d4810c1eee4b5e975652eee
+S = 6cc8ea4c4c56da87c25946a198e86917227bcb90da7be1dcde7b6547bc45a98e8175dd54af15bb6ef955b4cb48b7bb0a
+Invalid =
+
+Curve = P-384
+X = b6bc9418f3da0cce38a65f1b52bb3a9d22a0368e02f5f12fa1f1303ac67df1cffa55d049a782bf5bddb5e841b125aed6
+Y = 3b578a0560280a2958a14286e10faa7f5dec77fd8d90123aff5780efa8a636cee833fc9f10d7a164f1254a483b613746
+Digest = 7b44de2e448107197558cb071bb5bec9a5849467827d29b2c6625708
+R = 6602090aec001c16e5f6e7e3e488bed5d1702d36b258b6a8a2d8392a5ff30a6af12fbf4308d67eed6aaa8b7be8b831c5
+S = 65d0c3bb1910ba0b7cc108ae1ccaae63405ff01a8df91021e17cd46aa6f8ca8f4eaeac6d6fc26fc816a3ea537fd9576b
+Invalid =
+
+Curve = P-384
+X = b4ab83a4ded7d76aa15eaecb1bafe59427d3cfc38564af9123cb707da2405184acd40a6c093ba29e321ba0f67c1e0c6a
+Y = 26e2902499495f8550e798617a44ac9990c4c1cc3527dc0dd003a15aee3cbd3955151f7863de1692a94aafd3730e7665
+Digest = 8f902a34f36d7cd36748d5ddcc8fba6040be223a462842d506f185d1
+R = 61e48d5a100049578e820768ea57f30f27ffd1a1f839fabc55e8f4816c9b95d042619cd3bcc7180fd99834e344f53e7f
+S = 977b81d43216f31d8bedc3ffe873047817de3441df8b80a321aa0a80931f25a15c6628f43cf8e48d5c6aeca7626b0a18
+
+Curve = P-384
+X = f886f36fcf34e8df2a7e09220051b9981a3a6f693ec5999f28864e012c13896d633c9564f0118a95631cea8355b25b20
+Y = 746f9a77835325f18338dee5dc88a9b086b858ce15b4e4462a98844bb01811195f4fae0bee8f457c32823e142210dbb8
+Digest = 6a80377d3c7f0e6a50f6dc1656cef5a0d33cf7934441244f69f0062a
+R = 665390653ed280b8f6bd3718d8423f26cb38d2d7faa10fc0f094295677d9dafad45fc64cfc22ded56afdd86a77cf3c33
+S = 864f0eb3a8d93c388d987cfcb60bba76098039d46bf4ff4be083961f70a29e724c25cf56685802b7b5be048107ad52e3
+Invalid =
+
+Curve = P-384
+X = 5fc835a2f5429adb719ed22f11dfcb02731da6759a8ea75c21d1af9631187626c31e191f4dcdc183df01c48e13dbbce6
+Y = 9ed2d03df1cbeaefd4478b8106e90f92e0b6e958145cb81b9648aef0b96b71d1d55918564694b1987d68cc8e7cbd7dd1
+Digest = 807f609592e2ededa12792a7006a6db641904e86a1df3cec477dfd3c
+R = 94d9dedd27f2d014ba84ea58d2e88d68f3e86ba88b93750e50255211effe88b0a0e2f62017f22965726cdc77c55bca4f
+S = 14814bd09d9b7ba81b2485777cc588b5c0a4064df95c63f18a8bfd57494cd0f40c5bda9dc6c01ea72540f57a354360ef
+Invalid =
+
+Curve = P-384
+X = 0b86851d7c19f0f04a16e5e2903a36d09bf1863e152d87936fb2d74cf916bcf6dedf3c066d242f7dd327df0fcb42270a
+Y = b0c93480740bb635e6c25fb61630fdfcc462a1418366a51b1265656f721e18ba89ebf754c7dfdad865a252c884a6c4fc
+Digest = c34e896a31fc4de7596679e12bb2416a51e58e8942eabd5cb01f0737
+R = 33fa5fe3e495076e90f4b62753d3cdc7603aa7f5b407dbf89a854b9521d15e6c381d3cf28f103035dc4291ae318c5f82
+S = 30919a2a3fae71e1afe8378aedcaa08fadfab6c6bf954031452d4fe514969ede2acf0347a2f1e81abf1bfb9d8bd55a36
+Invalid =
+
+Curve = P-384
+X = 6f8f2fc40d1db28309c8850bf94d77c01c5449b4fc556e6bf50e5ee805209c4489d8ff9bd781699eb0e42f6a962d56fe
+Y = a4c7c77271dbbe7e00d1c6e4287dddc5463c6803a577a18f89a5eea01c6addc12404353abbc128cb9cf2496732312d65
+Digest = c19cabc6141b2adf67fe4bd0a3fead50473dea8cb0276de1fdc467c5
+R = 327c4642019a635d80dab82f7dc22e3102a3c1ba684c2b6de67d3d3009a17d39ae3d58ca2caec9f6f03f5ba3b406178c
+S = 6b1af807cc7265cc6d3049959cd7779ae0de819036647f9510b0e9f7e4c0e3fece5fc3741b68881145a2c944dc5c54d1
+
+Curve = P-384
+X = e98ba8016a976dcc3c50127d2af792969835b1096b1644b37c004d1786f4fb1026233f33ad56cd9444ba0a332c92efb8
+Y = 54bbcb78ffa3c855dd24bf182376ff5d28dd7b7551e4b05a19549c9f59c83dcc12a43092d63c5967fc0256612475b7d4
+Digest = d8d9319d3f705d03dfc992e8e7596586200fb1574f2a918350deb268
+R = 3b76a0c0ece2348085f3554fc92b9e5b0fe84801ab2adf1d239d7c81c9697b62285e8e5667774559d1bbc6e86f2ade64
+S = 91d929e42f8223ccc74d4cb09ee7eb619d3a348886c21091ec55d36164ad3cc04e1da6edd88ad89710a908ca4bc00333
+Invalid =
+
+Curve = P-384
+X = b8d7a836715635a8b095d3712817aa9e6ffdd98d24be2db751bb0c1fad42b082542500ea255cde17525ec159afca7002
+Y = 1a526c876d4771157b4f66e3056485c95066d4bd1e73e991ce6d5d3642807efe80015c52ef3cf8c86e57ab9a510ec86a
+Digest = fe23e8ab9dc934144247930a48babb0d8ba57703c2bef60e0e9a1e2b
+R = 9e36f47ec1b7ffdc6e3472f3cbec913494c0bbaa0c073f597e01845b5a3107c0e23a4575de4f2b582e1c2fe3067ec048
+S = b013cf51008a89b379a2a6b519b8d229ff0374401eae21a8da350fe35756b94168e7fafbd81f0f681f21c056941a82eb
+Invalid =
+
+Curve = P-384
+X = 4ffdecf5d5f7c1164297a93742c8a685bb425b97fdfe85f630dab2064ab29e52a0df34629c2531048c288216723fc9bf
+Y = 84fcff3e7e478a6932ace6f6b0ab70e61d8a5137b76886c59e721d938e0e252e2f7e57c2ab7dab90493446ad85c3fe4c
+Digest = 28d44c363bfb2e36bc59bb68c56e8b5d2587f149839fd3b8c05d9eb3
+R = 7d909d9aacf064c32d070c3149ace8b8f5d83b2006e8460b84c4bce664fc20e91c61ac8b415965b6155eddbe9238fe3d
+S = 19d909e358e71985179dab9113941ecad21e4f3608cb3a32dd065868af1657df8e06aa86855ac7ad757a7f8fb568a953
+Invalid =
+
+Curve = P-384
+X = e805e0733fc156bd582faaf794e58d4630ce73fc383cdc964dd337728f774e4989a697d79665a3282ee6e0ee343d6c7b
+Y = 43821b7b9a6ce1ddf0c59ada552668a0cfc85a87a610b5c36b7a691947116b49a4099340306e53494fc6b496cb8d12b0
+Digest = fd1bb27d666e3d40f5bd19d8c026a3614404b9edc11e582eb80b044c
+R = 3d4fa4ec95b55feac607fddc618d6f4eed71da65dc49d732e64460e5c80c57dc4421c64bacf3ef1e22995fd19c2a3cf5
+S = b11898ba475f2b28402d038afc15f171b99aab93437b35a2f8a3b89f42fdb7f93a0469d9da7652882000dd5bb1e8b9a8
+Invalid =
+
+Curve = P-384
+X = e15c7ef9791b9392c3e97389f2597ee161545c267e584b94262870ef25fda348f72349f396c27ac884fa8d776387fdd8
+Y = 107b4a7da8be564a14f9c45e4df5cc9b62f0671b3f2c0573c33fa37f985fefd1ae3ff2640947ebb12dffda72757db6af
+Digest = 3d9611421379fc93226fff23f5fe472a33f6bdc759d5705f7e9a2be3
+R = 9d715fd1a3668283fa83c407242e8d2a4f3fa1bf41919ca4101114bd0e0ac1b16c4379edb11de5210eee8618d42e9ed1
+S = 2dc37f453c8cfe01ea80c56d1865daf0f28847b12970132a1853c3ed80da6693e0da47a2476207947f29da34d68d604a
+Invalid =
+
+Curve = P-384
+X = efcb97dd73106b0a2be4f665c496352f6938da9d0fa97690dc0e8d018b06dce2ba8d19b93ddfe889d549a33e64497c31
+Y = 66a0cb7e64f40470b6d09b9e12f217b59e9e6615af52fbdc4ddcb379e77809361eca2093a3e24c7103e971567018400f
+Digest = 5598b06acf834ffbb2e50784fe2bc493fa51967f7ffadf1ece63f9b2
+R = 4ea5d4faf8ee52540db2f4c6283cea5302a3540a56e14c8a7533441c248465be99e10f23bba85be9634efaba7a8b172e
+S = 4c98a2142ecaba7db44c78658efffc1175f810a147306ba2e6498553526adb1507d7a99a372e0f84c8dbd160ef7fd5bf
+
+Curve = P-384
+X = 4e916a3cf2561580b49ecc52321db7103292fd2fcce8dd4d6f86be6035808e0df51c3c4ac1894f0b08ef6ebf953e0d18
+Y = 4e6f28895d024b4c71220b27052ddd4bf6115a260825acade48c043b3e06d2b6b8e4ebdf465980f3b013cb575d475bbb
+Digest = 1668ee6ae19c2d6f23b9184b6895ede8f55549b23095d53ef89487f6
+R = efce00544ebe0d98ba6015c07e3e9d09af808d49a0820c22ef572a3ef9c8a684b377bef1f8b3bbddb734b9b0bd0b1cd4
+S = e80d0e183b3f00098308e20e5b4ae393a07f1d1a8defda9a9d10f19b3e5236e42f593b1dc57f6718dd8d4583f0175ff7
+Invalid =
+
+Curve = P-384
+X = 3c6528c82d9d5e8dddf41a211c70f78604d81f49853bdc746270f1340a2a645dca3bc7844c3680268fa5973cd1758313
+Y = 4b9e697f1caf83d3224486bb0a8cd6a7c56e47c91043d8cba3aba51b6e504441d37abcc9b7b2d49b9126463703e514a0
+Digest = 1b39217bcc5dc841b32ddf00245623c581f19cac8a4ecd03eb2c07f0
+R = 848814c01c3d18534f39bcd53a8736db16f0f77a015a0e578cbb2f831739723e83b29cb6d4eee7822c76ff056d0f467d
+S = 05beb19f766bd1d4ec5e65786042258298a2dc617e3f13d8e2f0f4b50d934565f3162c737fa791a81897397f29305943
+Invalid =
+
+Curve = P-384
+X = 80c3f6488dcd76f33cdb75e30f8452ab9a3bd6110f14e25179b0aefe4c19c60a07b4af10844b130b0b75a7024e341298
+Y = 6c85a17ad4bbefb33910250e05ac02a17c892c3380712d06dd070843dff0d040e219dae78679b774cd5eff0adb67189a
+Digest = 23cd0066d1d88702c5d4461deff89aa5662b517806a04c4da30e0d82
+R = bc444deb0c7dd9f96f20a7ffd3ddb35a1189316655531860c39b5f87f09992106985e5562e083ee9f538c8e2d5363c52
+S = 91adde5d47eae80a98661f4347fd6e4778478c3d4aff3cff8aa92e2345a8e03cd4ab64adfd38e461bb98b496516439e7
+Invalid =
+
+Curve = P-384
+X = 97c3f446803a61a7014f61cb7f8b3f36486c7ea96d90ee1767f5c7e1d896dd5114255abb36c74be218c1f0a4e7ebba3d
+Y = 553ed1fed72c62851e042f0171454f120029adba4ee26855ab881d9470355f1947aa1d2e806a7ff2583660fedbd037a0
+Digest = 647eb206a8477440b4bd048d00f37dca8635b15c2a8e79e2a9d74fb9a5553211
+R = 7b06d6c2b63f1cc3bfdaa897d07dc15a83bdf35d979f70c34578332b3f4920422bb24867c51bde10831324df424e04ec
+S = 4bef715161f400dc98d4b63bd13ff4ad4a6c981ead44bfc662fe9bca4b56cd790698e4deddf9a4bd69327f26bfe801e6
+Invalid =
+
+Curve = P-384
+X = 08bd5c6cdc1f8c611df96485090e20e9188df6abb766bff3c1ba341ed209ad5dfd78b628ec60998ddfdd0dd029352fbd
+Y = d9831d75dec760e9f405d1aa5e23aac506dc019fb64d44bd57f6c570d017e6609f8fdbb2dc7b28ca9e00e37cd32a3b73
+Digest = 9a4985f744dd6f2774cb6f20ad6b6969e212abf4ac035b72ad3f8b1955ae1862
+R = 8b372c86ed1eec2163d6f7152e53696b4a10958948d863eb622873b471702ac5b2e75ff852149a499e61510905f98e4c
+S = b2ed728e8b30787a28f2a6d3740872e47348686c7cb426411379411310241d25f08a026b853789b1157f1fc1a7f6ff49
+Invalid =
+
+Curve = P-384
+X = 10a784abb3c549444a62c28df1c926b8aabb20c8d9aa4b1f7ca830258857cbe9718dbc9845fa9cbb78587a373baee80d
+Y = a1ad0c10b5ab6780cad49c8cd3eebd27de8f1b382ddd7a604458cef8e76ca632a7e44e1c63141a742426cec598029e2e
+Digest = f5b47101b4ff9baf64aca830b6afbc4f9620035d88a1d84a12cefa6f7f99faf2
+R = d9e52be2a3f7f566899cf6daaa38116d092473066f3a1bf91f3df44d81bca1deb438d9d25ce1632599c1d3576a30f128
+S = 0cad30bce4b3d7f40b3eef762a21bb1a3bad77439838b13024b7b2c70316875a99e80723a74a9e7a404715ca06a5d673
+Invalid =
+
+Curve = P-384
+X = 8760182393132d69011edfa127e36f92eeac8272641c27f52f3337ef8af7451e6d14f4e4590c7eb9fafb76e8c92865cf
+Y = ebc2b123ed871ca570ead40ae8f6f32335393c569b21b38f626d09c064a3c8668e9fb10a4667e0f0c68bf25ca98fd6dc
+Digest = 979131ca1d07e0b4ac6f27b20a978e0a230159eec4906db5dbd22b10ec71af87
+R = 1db957e5c2d294035d7f476a0cbc28a4aac2614d8212de5017076cd836bf04ffe237dce8fec91f2fb5ef82449ff1c65d
+S = 3e3b9058d0a9c5b417f9c6f86557b9d50e7a902694a7012a1be6bb70708497e4d39fc1f6d6bc60dfa52d23cab173385f
+Invalid =
+
+Curve = P-384
+X = 2b1f98d2acdda8347b9a68c75174408eae7de3d6b9c08c26e73ce9ed2ac147b8d90cd82e30ab43909d63f6b457de2071
+Y = 33f5e6f5f5793201991e014cce0045d04adc352298e32f45f4e374450111c8456b5c2efaec43d157949b5c191b2bc934
+Digest = a1daaf888d93a2a7e52bcd2a66cca3ff2e02916616d1919adefdd7257490e5b8
+R = 23d046402cbce807d232bcf0dc96d53c72992e0ba1ffce0d79050c0f4c5ad9bfbbdc1c96c730d67ff3aa3edaa3845da9
+S = 2cd46a4fe5d120b3af3a6d9ea63cc78f4079e8b5520a8fa96828334a4f182ff4d5e3d79470019e4eb8afc4f598b6becb
+Invalid =
+
+Curve = P-384
+X = 86ac12dd0a7fe5b81fdae86b12435d316ef9392a3f50b307ab65d9c6079dd0d2d819dc09e22861459c2ed99fbab66fae
+Y = ac8444077aaed6d6ccacbe67a4caacee0b5a094a3575ca12ea4b4774c030fe1c870c9249023f5dc4d9ad6e333668cc38
+Digest = e3bcded61cbb0bf6ec20d59f91e8e73e532f15b082b89c984c1b51fb0d1db8a9
+R = 798065f1d1cbd3a1897794f4a025ed47565df773843f4fa74c85fe4d30e3a394783ec5723b530fc5f57906f946ce15e8
+S = b57166044c57c7d9582066805b5885abc06e0bfc02433850c2b74973205ca357a2da94a65172086f5a1580baa697400b
+
+Curve = P-384
+X = 9e7553eab8cc7e2e7396128f42ab260c6dbb5457cbff2070ea7c0db21def1537939e3f02699e5dd460eca3798d08bd6d
+Y = 892c0c8e47dddf858e89099a8fc1026e8b8333532b22f561f7647f63f9c79dbf5e8dd18fbfe6ff34902233119c5d5aa3
+Digest = 0f2a9b447ea5cfcfb9e67d661d7f0752befd3b4e3454fe40b9ae1eca47806025
+R = 2452da6a48c3749b66e576e0f1f768d51728be17aea149164c4e1654c5ce27f625a4610c4a2eeddb3a0626d3abc6c37c
+S = 499504fb58c9db24a7ff5f7921e1312f8aa583c08a308e080f5ef1acf5cdae7927c4101573db069ab0b6de7f4f1cab38
+Invalid =
+
+Curve = P-384
+X = 0cf4dc51e71185a29c0c6fa3c075d9da5bd7ede085053344dce5dbbe8329e8ac9045f7246c9d0efed393b8e113c71429
+Y = fdb7917b73974b355cf9f3bef6a0a460c2d39fdf1fe32a7744be0a54ddd1cfa8d03914cff4b5ca536b40707ff2629aa4
+Digest = 331aefe2369b9c5ee6dd9f850259b3b8512f5934434e61573f97fe2c1cd2b147
+R = 3812c2dc2881d7ef7f621993b161672329b261ff100bbd19fb5826c9face09aec2017b6843d69336b813b673c5402527
+S = 5dc102fab9d6325131c556ec00309c2959d1031a63fbc1e2d5d04996d3234ed33875c0ab98e5878e9bc72742519ed398
+Invalid =
+
+Curve = P-384
+X = 6c590434988155236b43147389c6dbfdd27dcd3387e9b4c2587ece670753a542a13a736579887791cf53d31e5ce99994
+Y = 35a20194ff3f1b55f7ffb2758ddd4b98dd0d9e0cc213e10ed25e8e0430fe861066c1d4423c67f0c93f7ebd87fd3c561e
+Digest = 153475076a003545d3ca3d4a772866f12cc85f6e69f8c486a91a80fd709206b1
+R = 89ff866889245e797926509e563b1746920b78c9370a6cdae52663730d131e558e327d1f5fef8faf9e6c802fa29504ed
+S = 8dd68e2de2f788e598b3e5a60c18d81849a0cc14b3b0e3c931910639f3125e5d6045f00330b1fa989252a80f95419b04
+Invalid =
+
+Curve = P-384
+X = 499cbdf18ec4e69b88051543c7da80845fa2de8be2b9d9045fee7f104a8b5b7d04e69142de9955c5ab18c5a34ebff075
+Y = a29cb8d28836b201a389922b6f8f93870f09c80a00242d00d32656a43ac1440fc55bcb123551a73290f603c3469be9ed
+Digest = 5f00b3b48c1ee8287abe6f3fbc3438b91f4268f318ae2aa1e7810369d6716020
+R = 25d4d243da6fd9b439a9242c3656fade7acb7a306e8cf23ea89e3ff4f9330be19c61aaa42d7b426d12c8e0f96b80dae5
+S = e7a99cf4b269bb4a6210d185e9654602523b5cfa1cddc94b1db92018aa557ecb6adda44c816975f5ec1756b6df3c44fd
+Invalid =
+
+Curve = P-384
+X = 9a74ea00203c571bd91ae873ce0ed517f8f0a929c1854d68abd3b83a5051c0b686bb37d12958a54940cfa2de23902da7
+Y = 6f20ccf8fa360a9ec03d7bb79ff17ad885f714757ef62995f824908561dc0c3dffc49d873627936a2fff018b82879ced
+Digest = 45c3a1b29a18780234f12f5e4b64e7af9de2acf0029ce55b706cc79a7e4df994
+R = acc1fcac98c593fb0a0765fce35a601c2e9570d63ea1e612fff8bc99ac2d4d877750bb44cfb1014e52e00b9235e350af
+S = 7f53de3afa4146b1447e829ebac8f5645e948cc99e871c07280cc631613cfdaf52ccaeccbe93588a3fd12170a7ec79fa
+
+Curve = P-384
+X = e22f221809fb7a054ac799a70b3d24744eb7c5096c8671770399527c88ccf9ddaea0257a0ae9430d927ff5d9f109c533
+Y = af4101d60df9b306ae92da7592f4faf3df422a3e33f1c2ed2973b2b900eefc346b4cf024de650abf537cecd12ac77618
+Digest = ef1057d83a6e6481be7caf2c12c15f085ff971f02f0db8544352558e2b9fd61c
+R = c39a8e79f0560b9f26504469a470c7b2230c0d25de07c206e87dfbde9aff0a5d85322f56dfb50d4c1fc67c67d615dad7
+S = 2ad94dd13a39cf4f4cb24c2c81d4c1181652363addd856dc9ba7455458e40ed047cd113129bc87f43949d5a98a0d5205
+Invalid =
+
+Curve = P-384
+X = fa8ebc3682d90ac7356f0b75b9e3376e76518676e0bedd176cfa7fa57fea4b3a399dbb2bf735ec90b9c1705cf9fa6f57
+Y = 18c3fbca0150ec10696b3851f31fb3ba62c0b6be509d249e0d4b374c7a08e49338e0922e2a8a9319999e6569ab8d292e
+Digest = 0c7152ec620fe9b783625196b41192dd5d49df184ad26965c970ac5e28bb1c4b
+R = fb58ab09b8a7ef7a6ec05b854eae11af9b713f7c7540e25115f609846e636ad4f88dcf4dd61e311273df23ccda474f03
+S = 485be4c21b7c3a9c6b39ffc9f0c39f4050f76d2a6b3fae203d016318c541c1b4ad6cfc0d0950636ff6883895dd49e4e9
+
+Curve = P-384
+X = e5f331536a2940cd67234bedf813c12e15aefa9a1a68429f8754bf2769a47c9c2efb5c42135e7b01a110d7302e097eac
+Y = 63b2398612c863febd482184e834d3acb51408c49aacbbd35d8719746f37cb13e013c9505ce034cd815aacd10d2f7a0d
+Digest = d925955406f6b6dd4df05270a2539a5924830dfbcbf6a5a34f21354db246244b
+R = 96c35f22d036785a392dc6abf9b3cfb0ad37b5c59caefcc0b5212e94e86739a2674020ff79258094d90d7d59f09d47a1
+S = 373cbc865384734c56952f7a35a1fdecd88e8b343ee3aa073d30f5f25b73506f1e5f5857f668b0080dec6edeb5e1be96
+Invalid =
+
+Curve = P-384
+X = c53ad865beb1e2b92764065f1a6bb465ee94aacabe43426a93c277d02e00fe36be1c859ba08a031fc518a0d007668979
+Y = 6728d42bae9bc097151748ffa0982964bdd16076fa0e7cc15837c1f773b08d02c3dbc57339091ccc34105b84781150b4
+Digest = 6d5fa5b492406a1e93df6bb6364d7b17a24ef43807a1159acc77486dd7b49b60
+R = d4f0dd94fc3b657dbd234767949207624082ff946de9ce0aeb0d9993b8c7d7935760e1bf9d8b233bc7d6cd34928f5218
+S = 0941df05062aa8849610f4b37d184db77ed1bc19ad2bb42f9a12c123017592bf4086bf424b3caad9a404b260a0f69efb
+Invalid =
+
+Curve = P-384
+X = 1f94eb6f439a3806f8054dd79124847d138d14d4f52bac93b042f2ee3cdb7dc9e09925c2a5fee70d4ce08c61e3b19160
+Y = 1c4fd111f6e33303069421deb31e873126be35eeb436fe2034856a3ed1e897f26c846ee3233cd16240989a7990c19d8c
+Digest = 8cf5e81c6858b8395421d8c913f1ac887e282b5818eab525fb79feb9bc64bca7eb98f94b9e48b705e6c28311bb0ca672
+R = 3c15c3cedf2a6fbff2f906e661f5932f2542f0ce68e2a8182e5ed3858f33bd3c5666f17ac39e52cb004b80a0d4ba73cd
+S = 9de879083cbb0a97973c94f1963d84f581e4c6541b7d000f9850deb25154b23a37dd72267bdd72665cc7027f88164fab
+Invalid =
+
+Curve = P-384
+X = cb908b1fd516a57b8ee1e14383579b33cb154fece20c5035e2b3765195d1951d75bd78fb23e00fef37d7d064fd9af144
+Y = cd99c46b5857401ddcff2cf7cf822121faf1cbad9a011bed8c551f6f59b2c360f79bfbe32adbcaa09583bdfdf7c374bb
+Digest = 965b83f5d34f7443eb88e78fcc23479156c9cb0080dd68334dac0ad33ba8c774100e440063db28b40b51ac37705d4d70
+R = 33f64fb65cd6a8918523f23aea0bbcf56bba1daca7aff817c8791dc92428d605ac629de2e847d43cee55ba9e4a0e83ba
+S = 4428bb478a43ac73ecd6de51ddf7c28ff3c2441625a081714337dd44fea8011bae71959a10947b6ea33f77e128d3c6ae
+
+Curve = P-384
+X = 9b3c48d924194146eca4172b6d7d618423682686f43e1dbc54ed909053d075ca53b68ae12f0f16a1633d5d9cb17011ec
+Y = 695039f837b68e59330ee95d11d5315a8fb5602a7b60c15142dbba6e93b5e4aba8ae4469eac39fa6436323eccc60dcb6
+Digest = c68382d0641ffad850c41365a8ec68e3d55acba376d1bb941e7dcdf7b71f37b8288b023b942373a40be1dfaaf4aea633
+R = 202da4e4e9632bcb6bf0f6dafb7e348528d0b469d77e46b9f939e2fa946a608dd1f166bcbcde96cfad551701da69f6c2
+S = db595b49983882c48df8a396884cd98893a469c4d590e56c6a59b6150d9a0acdf142cf92151052644702ed857a5b7981
+Invalid =
+
+Curve = P-384
+X = 5140108b93b52d9ad572d6129ed6564766f8df3755e49fa53eba41a5a0d6c1d24a483c90070583a66e3cfa52b6fb1f31
+Y = ff52498446a40c61e60c97554256472625633eda0c1a8b4061481fecfbe9c4503e99dfc69e86c9e85c8cc53dca6b8dc4
+Digest = 4b945020c329a61221060e924ec682eceb842c09537fe26265ad084753b89f7650cee4e8df30b38126984d80fd25d246
+R = b2726b2ba9da02de35e9953fc283d1e78700860d4c33dce8db04dd41499d904866c1b8debb377f6c0dfcb0704252174f
+S = 0775b027068d7ad55121a278a819f52099ace750d5e996eaec9dee7be72758736cf769650148fbd5c411beb9b88f979e
+Invalid =
+
+Curve = P-384
+X = 31f4fc2fac3a163a5796f5e414af6f8107ab5e4a98c755d81efa9d5a83c10128c16c863190112fc29d3d5f3057a2edf1
+Y = fe208743f3e96c3a34b5fff78c9716c074a1ce3dc01c3f0e471ddfae91cd88e7dda38dd0e5e1f91b00b8539da3cc10bc
+Digest = 2d6affdf541609f649dbe9fd5829059bf42021fcfefee42d8c9cd5c127015c06b4c3c13ef56d08767788955887752e44
+R = 706911812ec9e7370234efd57b2855975eab81e9c2fe783aa8e442dc6e7d681dab2dc0dfc6765f87ab67001108e3facf
+S = 42c89efa22d853d32f619c9fe13e9852889ac98a9fed5d4fa47fed238e1cbe70d7970af9f7bdf84e51176af4885f2490
+Invalid =
+
+Curve = P-384
+X = 1f7911dcfe63a6f270cf75b8584d9b1b4a00afc1fa43543c945945b8a821ebeb37fbc705a000f9cc7c35f7d27027b7bb
+Y = f11835ec80c4ac06d99247e73bf72522109ac255e6109262de4dfbf9619244f74fb6c9ee57694537d7e79c248db34dc4
+Digest = f4b0a912331e7fc59a7071e5f47c9dafa6dc09b32c5c3d05301b3833bbe0b9168e2b63f12248849572a322b2f5423b8d
+R = 3587c9c6885adf3be1086825f9a41ccd2edfa0bd95e7fc4dba5a9710f41d539132de7772f14c18e318f8992b66d2a86c
+S = 73a844d729599d4e3e3c1b63e9c4bf5a73d1f69e0160857fe63a56c381c051f5c37ea6b4cc4caacb6ff26ef9699efe30
+Invalid =
+
+Curve = P-384
+X = 2039661db813d494a9ecb2c4e0cdd7b54068aae8a5d0597009f67f4f36f32c8ee939abe03716e94970bba69f595fead6
+Y = e2d5236e7e357744514e66a3fb111073336de929598eb79fb4368c5bf80814e7584a3b94118faac9321df37452a846fc
+Digest = cae50a424395e38bde9ba31fa5ea0c107ccceaff06663719162aac2c3e15f2b2cfd376f90d371326e1d29e0392a756ee
+R = 164b8ac2b34c4c499b9d6727e130b5ef37c296bd22c306d1396c6aa54ca661f729aa6353b55d7cf1793b80b5a485115f
+S = 4e7187f8f735b7272f2c0985315b5602bb9b1a09f32233aa10570c82d1ccedef6e725800336511e47f88ddbbbdc08f54
+Invalid =
+
+Curve = P-384
+X = 46dcf8ee848c6459fa66d1cae91ccd471401a5782cb2d3b9b9264189f0e9ddf7197b05c694931bde3306240cf9d24b7e
+Y = 79d9508f82c5ead05c3f9392f3b1458f6d6c02f44420b9021d656e59402e2645bf3ba1a6b244ddb12edbb69516d5873b
+Digest = 039fe89dfc54e7f2162545af700a8c49a1216b08854643656b07d74e7032516fd0c9368c5e5ce54655e4d08baa29b6f0
+R = 5ffba3b5bd7c3a89ec40b47884b0b3464e8abb78608c6d61e1e62c2ca98d44fcdf61825d69dffee8408d0849d0623bac
+S = 0d2597b5fc3842ffce1957172253a8c9c0e4dbe770ce54f70f139e0545dc34ec639d609e14175bdb2b812ccfda00c9d4
+Invalid =
+
+Curve = P-384
+X = 097cea75f685cf4d54324ad2124ce3f77b1e490bbaa1ffacde40dd988f7591e1c5d158e6f232500d958762831914af7f
+Y = 716d8bc056daf69ca2edd21b89a6ae9923cfcae87bfda5f9a6e514dd4b9d28d164fcc613ca2afb9660adfece59f09b66
+Digest = 02afb35f1df33b3d83df3391ca4184121ca52f520dd12ffc891aee77eab6503f232a5b1231bd997239751f46c4133edb
+R = 1c5d4561d2a3af8835839b543098c101c715c545eb7d00300c5cb05bb08dac29e732ffdc31c50915e691999ad505104c
+S = c3442f2fb1498fd47c2f959edff37a19783e3ccee80dc6955ca64db087fd188e67358e7b9223535bbb858d21ba6a978c
+Invalid =
+
+Curve = P-384
+X = d2e2b3d262bb1105d914c32c007ea23d15a98197f0ed90b46a17f3d403e406a76c8f752be1a8cd01a94fd45157f6511a
+Y = e585fba180017b9983b4c853ad3a5dd52e079c5f0ef792d1a0213b6085e390b073de1a4b01749ceab27806e5604980fe
+Digest = e66b11b84f87c38526438e5e3c5b4521248c358eaab80e40526906a05fb29d14d4e5686681f03bc3f0025d45dfb83b5f
+R = 49c001c47bbcee10c81c0cdfdb84c86e5b388510801e9c9dc7f81bf667e43f74b6a6769c4ac0a38863dc4f21c558f286
+S = 1fb4ff67340cc44f212404ba60f39a2cb8dcd3f354c81b7219289d32e849d4915e9d2f91969ba71e3dd4414f1e8f18f7
+Invalid =
+
+Curve = P-384
+X = cd887c65c01a1f0880bf58611bf360a8435573bc6704bfb249f1192793f6d3283637cd50f3911e5134b0d6130a1db60e
+Y = f2b3cbf4fe475fd15a7897561e5c898f10caa6d9d73fef10d4345917b527ce30caeaef138e21ac6d0a49ef2fef14bee6
+Digest = f6325d6bcaaaf1aba1197a290b33974f2fe8af200d5d726e78705904e9894ec31988e35dc76b9976834b7cd1c4c67146
+R = addfa475b998f391144156c418561d323bdfd0c4f416a2f71a946712c349bb79ba1334c3de5b86c2567b8657fe4ca1f1
+S = 1c314b1339f73545ff457323470695e0474c4b6860b35d703784fbf66e9c665de6ca3acb60283df61413e0740906f19e
+Invalid =
+
+Curve = P-384
+X = a370cdbef95d1df5bf68ec487122514a107db87df3f8852068fd4694abcadb9b14302c72491a76a64442fc07bd99f02c
+Y = d397c25dc1a5781573d039f2520cf329bf65120fdbe964b6b80101160e533d5570e62125b9f3276c49244b8d0f3e44ec
+Digest = 709d1bf45b5817f5a67b859651eb47133ebed2622fda09ab66d3467b5e95da50ecc2c74d8f4d289feebec29729a4bfa3
+R = c6c7bb516cc3f37a304328d136b2f44bb89d3dac78f1f5bcd36b412a8b4d879f6cdb75175292c696b58bfa9c91fe6391
+S = 6b711425e1b14f7224cd4b96717a84d65a60ec9951a30152ea1dd3b6ea66a0088d1fd3e9a1ef069804b7d969148c37a0
+
+Curve = P-384
+X = d1cf635ca04f09b58879d29012f2025479a002bda590020e6a238bccc764478131cac7e6980c67027d92ece947fea5a6
+Y = 21f7675c2be60c0a5b7d6df2bcc89b56212a2849ec0210c59316200c59864fd86b9a19e1641d206fd8b29af7768b61d3
+Digest = 5d54d236db6ab4691b3d50dc81471c5d388e5735ebdd435e9742a5a8a0ad0e841bab57326c8535a680ada57d2b3a70fa
+R = 6101d26e76690634b7294b6b162dcc1a5e6233813ba09edf8567fb57a8f707e024abe0eb3ce948675cd518bb3bfd4383
+S = 4e2a30f71c8f18b74184837f981a90485cd5943c7a184aba9ac787d179f170114a96ddbb8720860a213cc289ae340f1f
+Invalid =
+
+Curve = P-384
+X = d15ca4b2d944d5539658a19be8ef85874f0c363b870f1cd1f2dc9cb68b2a43a10d37064697c84543e60982ab62bb32c8
+Y = 062fb7dfc379fc6465302ac5d8d11d3b957b594c9ef445cfe856765dd59e6f10f11809e115ac64969baa23543f2e5661
+Digest = 67cf9e6f9e9558a379ef7361771323a4f3925f2c7a5d94d9156bf2d9d45f9f8fc4d47322da622fbce92fc764a2ccc327
+R = e2cf123ce15ca4edad5f087778d483d9536e4a37d2d55599541c06f878e60354aa31df250b2fc4ed252b80219552c958
+S = 696707a7e3f9a4b918e7c994e7332103d8e816bbe6d0d1cf72877318e087ed0e230b0d1269902f369acb432b9e97a389
+
+Curve = P-384
+X = c83d30de9c4e18167cb41c990781b34b9fceb52793b4627e696796c5803515dbc4d142977d914bc04c153261cc5b537f
+Y = 42318e5c15d65c3f545189781619267d899250d80acc611fe7ed0943a0f5bfc9d4328ff7ccf675ae0aac069ccb4b4d6e
+Digest = e8d6b550271b486e79f6975cff753d49519ed9393b207af7039b4c070cbc2fe7d49dd1bb87f7021e442fadd80ce8a5b0
+R = b567c37f7c84107ef72639e52065486c2e5bf4125b861d37ea3b44fc0b75bcd96dcea3e4dbb9e8f4f45923240b2b9e44
+S = d06266e0f27cfe4be1c6210734a8fa689a6cd1d63240cb19127961365e35890a5f1b464dcb4305f3e8295c6f842ef344
+Invalid =
+
+Curve = P-384
+X = d4e93c4bafb54c06814011309e9f3d8e68b76a5452e364ef05ccc3b44b271e576c9028106b1584f09271c886d467f41d
+Y = db730ccfdeb6644362f4fb510d5254bfe6f23e891e936132f90f1913e93baa8b1f8c0613a0f0c61a760ce659f22babc6
+Digest = d5c82ff11f555ce21c3f20a9ecfa6047cb6895e32fa0fb379f49085a59f61b7c8fa05058ef144cf47db5738fa40f4890cb59695998a2358162bbbf6d7f53517b
+R = 8d0fd14a59c24b0c2a34b438e162f1f536fe09a698cacfe0760d026d1593265d02f2668d2a5e49ac0b21e93807aa9c18
+S = 3162ffd2adc9dd5ec1bb1d97d2b0c27b8ae234235ffb374878d0b76382002ea505e885c178d56a2d7809bd1d83117ef1
+Invalid =
+
+Curve = P-384
+X = c665feccf51e6bca31593087df60f65b9fe14a12022814615deb892eedb99d86069a82aa91319310b66588185282dad6
+Y = 1e6e25bb8ae7714415b94f89def0f75dcb81d4af6b78d61f277b74b990c11aff51bd12fc88d691c99f2afde7fbd13e51
+Digest = ea056beb112fa9aad69c8dfe51ea947b772bf1c11287edcede43a98089d21492ed581edcb6d1823e2873aabba213b84291db3bffa6eac3ae43a92fc2da276a24
+R = 0e18c4063137468fe864fdc405ad4e120176eb91b4538b28ce43a22ae1a310cc22a2f7a2b3a0f3d15e0f82038b4a4301
+S = 5a1620e42041ce4357daf824befbb2ed65596bcd8214e88726149b26b1f416b9472a8877413f1c3705fc2edf4731943b
+
+Curve = P-384
+X = a6bbf85e8068151482ce855ccf0ed22988fcf4b162c4b811cb7243b849299e3390a083147fbd68683203ba33588b13ae
+Y = 5c837ec9f2eda225c83ab2d5f10b1aa5bfb56387deebf27ecda779f6254a17968260247c75dd813ea0e1926887d46f86
+Digest = 81b1303e10f25d37877b09f9d82dbd894e40264992d86cc74656ebeef505b46fdf9dec312a7f0a26e3f56a7195d5b01d198c378fff9d049e00cbad9586da20c9
+R = 9c11879e59659848274fc1ef5a6a181af813d23708b09a24dc06c089b93b918828dd938a75a34d5a681b0af362dc19a0
+S = 9c362231962ba7579c4a874e87bdc60dc15cb2e0677149c8ea31162963e05a6614616f67a5269616071cf095be7ff44b
+Invalid =
+
+Curve = P-384
+X = 9c1eb5cdb1a873e4c275b7ded8712b9058ee0d9ded06c96a2a8d7c652b82e894e2f918dd8e18138e5c34821744b97952
+Y = dd474c93619f02b5d4fe30ea7805c1a13fb80008a81bb5f3eeb95cd11f38841b8e34d64f2c6cc2d6cc2587365eed6b6e
+Digest = c0f9ae90fe8aaf54962e7d47a832e4ca6e60355e4066cd2b08bff78650d4e4a5d1eb1de296f9f0ef92887e09f82e0db4411aa9c3c6b109159bd39feed40419a3
+R = f17b2f2fa3b5c8e9c62a633e5d417139ddf3dafba75b464fa156c99b3948a0aca532c7fd3e14a266eb17e7fa80881da2
+S = 01c246866983fa74d6dff38b1ea091f8afd218b5a42467761b147c19a3bb20cd24be8ed1f95f1e61863a709d2d0148e2
+Invalid =
+
+Curve = P-384
+X = 20622a293edc96d83fee77cf1ee8077c61d6f8ed0073d53cfb5ee9c68e764c553fa4fc35fe42dade3a7307179d6fc9c2
+Y = 710fa24383f78cc4568fe0f4ecbbe6b11f0dce5434f4483712a6d2befae975a2efb554907aa46356f29bf7c6c2707c65
+Digest = 5cb8ed471a4001e280a0927faf25183c857b9b2de21c8566e8a1bf04ee085c36db7fab9d8f627898b3bb23c10225305938b56a732659f2cab3fa857d80dfde19
+R = 45a6cf5cef06256139caa709292d1e0f963d176add188572e9c7be29af21a95853a98e23aef0a0850e58d44d60b6d780
+S = df8d71cd5ab22fc718070078103483e5258734872ab935435f21ea199018e49a69c064a63801beb0759fde6e2c4a85b8
+Invalid =
+
+Curve = P-384
+X = 83a4fecc0bf0a353b0acf6f54094b822f2b12564e172b296f3461cafa7315d7d31d0089b1b4c18ad3c86bd18f539774a
+Y = e4fd57c5b2937e6fba1e7d72fc3f02352bd79c13611931935f4dfd073b9379f862f2277585137e996e212b5b6533dcba
+Digest = cd7c623c3c3b52f46be0ebb2b353ff97db3cd7dfc1a059a57668fc50101aeeb37b8aee9ddda8ab611546999a120cc9acb0e2c3df48dee66d5c31a46a7be94bc7
+R = fb02804010a570d702ebfbcf3d6cc9d55ddac2bd4b4de56d325e9790571b1737f91d3fa1d4caeec6eea806195aed3187
+S = 1fd20fe383e907e77639c05594642798619b2742090919bedeefb672c5700881baf0df19b9529d64bc7bb02683226103
+
+Curve = P-384
+X = 208a8c5a6b59458160c5b680116c8b23799c54a7ee8954a4869425a717739facfe4fe24540505cdc133fde8c74bfca78
+Y = 22aa7aba797bde1e8389c3c3f8d8d9aa2a914f4d2d7aaf7187ebed9b2761975718ef97660ba0b8a71dee17f2b982e2cf
+Digest = 007b907b90fa60835d45d2f0201a4486d9782fea4f0a235d97d4968336c5369c6c2e82bded56288a10fd6741f4c15d1633bc92e0196308d9f0490fc2077d3b6c
+R = 0b4e835ed83151d2bde96e201c54544ba5f301aca853957d3c538c9858fcce796b60fc50f5600a48dcdf13e5bc029827
+S = 0270adf02d31d5428d523e13d7d315c1929a1d89bbd0f61eec0b1186abe1c307cbba6b1067a68bc3947e6196d49719a0
+Invalid =
+
+Curve = P-384
+X = 80ae47e99107d6148b1088c6694df5c1273ff336b66e45b68a7c65fed735129dadcaf2b900e9f8ec50eff70a5ba89ea3
+Y = 47450efb5669bfacd7cbff1f801aafa0812ff88a6ae7b5a1f85e88e19129ed995f509fbf8dec15ce42bbbbd33814c09e
+Digest = 1cacc8f609080e7b8339529f944850a700977ef9107f40956fb35645e15fdd54ef01755f07a2582d0bf2ca0cb84ee8ab154fe0914dfc9ad7ad5fe54b857d0f4e
+R = bae6fba7b1485ecdca48219ead3c39295fa9c196b1f0941445b1ac768e33962f68d37f1f1749eaad7200064aa202fb41
+S = b411a38d02deb42d1015a7837b033c89d2f37d92c70fa8bb1f592223f7750520b950f30277abfb4155a3ab194b3beca0
+Invalid =
+
+Curve = P-384
+X = 45cb6dcca8d2e80ac04536a22f9d68ea2313245550108ddcd32799d154c0a55492e49463e826275bd9bf0d5e380205c1
+Y = 6fd124f5a6c745751ccfb3ba4dd9144ea8fd41a4d9a4b34820434da66aa7385e73ffe71e6c11ed1beb6c7af22ce00edf
+Digest = dd7947a5b9a1c988dd7dff537e15335aacafd3e602adc8373765013f338334dd58aed4fb7144de0007c3410d79f5e78bcd4cf0dd63cc33ed3dd564882e299c7b
+R = 2c782c4263eeee63657fbf20fa287a1a81fcd14b1d3bae333928ba4fc31abb20edebc130714380608e38ea74309eca9d
+S = 716113d95bc9dba532bfb470112b0d43d9cd6560ad15e0de2e514994801ff339bcf19ad4ee2b8af573f57c038fbd70f0
+
+Curve = P-384
+X = 36c1459d9e9f7b6c1598778c784cbf94661a2b11370c02ee092f6ea0ca20acf81f1ed5048a28a1466a91689df26bc291
+Y = d1367418c7b216bd32c6dafc8b2be99d02cab68df990758b2ddd543b7eb6ff6e285b649ffe588b1811b549cfb5f0289b
+Digest = 242ff2713c03e3d5277652f8e7fb1e5a1f0422b6652e1bdd696e46c03cdd3aaac329b1d88e7aa345ff7224ce6dc6df05c7e9d7dc2665282c817d15a15b8288fd
+R = 40c338adeb504193444bdb95336177362031aaadc5b7e151e42030df9dd8687f3cb8fe2292fd4f9206989c089d966dae
+S = be4b2ba251094c24de006c89af2b5c77e6937f36d7bb703b4f8edcfe65d45f4b2fd2486222163ae0ed9e215c0a96f488
+Invalid =
+
+Curve = P-384
+X = b5eb6670bb0b0d3aef10e533d3660756b7372a2a081d9d920130034f48202cd43b9e2d1e5893d0cfb322db65ab839716
+Y = e28444770396041b489b302786a57fca9a98f19685cb4b455d219151e64645ad30dd3149ec96f3bc90879834b65e58aa
+Digest = 8d2e653807e87962883956ee3705b2167c50370c3af12eb8f6c26f0f15ede56dddc7d0c9642a1c1c2444b06571fa1a4d47e7884acc7ea3884daaa50940f782e2
+R = 0887a13df940907864b425ec0d8f91ac719abcc62b276fa08c5122b38831c8930abd3c8454e98182bb588fc72843717a
+S = a380284eacaa36a34e35f04fbf6e28ffb59176f41ea52d9c9bc1362eccd8e0d699c2e08111d93e9dc2785637b1f4f09e
+Invalid =
+
+Curve = P-384
+X = 700e8f65e052e918a63a96fa57f4eda849f9f9faca3302d6ead66ebf85838f8145a6d6718a681b7bef73170d7254958f
+Y = 9e9e10357658913007803859165926cd1e5e92c3a644d834098cb1cbfab466349bf4238a5154cf50ed77c77a78263e81
+Digest = cf885fa7a96db595f825a0ccc56b70b60e0e1c30d0a15af636d1f4957328aecb7eeb734d5874bd72ddaf15c357ca36bd42abf387f7b771ea6160e2e23a08652e
+R = 59be870e0fd684b000cce95c616d9f34674354e9d20db15d204b8a6285ff55258e4eeb49da1573ef1030cd6b2626dcfb
+S = c0bbbf71d87479d82575458be9f4d686921db7ea458d620271f51ec3f4d1afe3bf25ef9c0c400eb7b92cd7058fb17346
+Invalid =
+
+Curve = P-384
+X = a9de6f029445fffcf16349b44095cc83b11e3d0d9f08654b158014803b1cc31b8dfe00b1a8167c6f704d69cdd62c6512
+Y = 27336a503a669ba1d1f3619f51dc8aa2a44b2075c682a36f071be486e7dafba9adfac2ce74be0442b7251e99304ffc05
+Digest = b7e73f38767f253790e7fff019b4e0e61562aeb97b2b749afec2a61c87ab0e15916d4286c0a13989912f6bafdf3efc6f64ddc3b944f9041266e5abd4480c1606
+R = f93a4d2eb94d087f28572847e0099ae2ee944efacdad392ec268c9c1e632e6ccd670c36584e58aba52a4c2b07127d55a
+S = 941ee89cea6e7ed20213a95482fae134707ddf4d292ab1952ed5464f1f1138669dedbfc9998b696eaf469be5fb240c80
+Invalid =
+
+Curve = P-384
+X = e63500d6d13069c01fafc4518f1d429661c5bb6ad1ff0383037ca6a469a5c20c453dce03bf6e4164f7e26f849016b3d0
+Y = 83b7b731c2531c3ac61b194cf3db6dc02ccdfa16d9eb49f97bc4ec3fe6c8bd865ea27f1538531ad07dc44fc5107af8e6
+Digest = afc0ed355377d0ab0c4f79d420dcf67ad4920c013d5c8afde2287525da4596672927540418a61568b21ae7799d7659f16b85f611bd6e8d2066a55903da0c48b9
+R = eb78733e73fd64a6a1f23eba5311af23d26816fb8847671e01fdbd8dc7d5fce1a0823b080ee99e8d75edb3f100e16077
+S = bcaedfe599f98b51542c0f94ae1010611c6767ac3abb2bd887399d62fd0f1b3a0e97deb24c95a76de44521bf24c8645e
+Invalid =
+
+Curve = P-384
+X = 3ebd869be687f82d844416e6816d698d82e1e22a1f451d50b6c146134deb07f05204c0b04e7dc07ebdcfd916531dc7c3
+Y = 6e4d7bde063edb7254a82b9d9249d2a2b9ad8988c37a84ac9f7c09daed42b1fd28f7cca1ea8b4f91a66e878224800bdc
+Digest = 56a61339a35750e95770f28846930e3f594e8d759e07423718734a82b2a80430b0fb3378e40bdcf5c12be135be9a9bec32916b4988a763091a6da7b44631414e
+R = 575f87a8a7980555a198cfdec279cbb2f89551b5271d242397c29f6bc4bf413dc30312a7e626ef7fc77a9124a79bf9be
+S = f0b7d759246ad36ba8240c537b1eeb5d148c38d324f48028c598eaef6e49d79ff3f6cfe3a32fbbf6f3ed3aaaec31d572
+Invalid =
+
+Curve = P-521
+X = 01939b25d13ee8e04203643ba3709526a92912b0e98f06962fb217ed18d1ba52bff192640f980d3f7f92c116b5d94dfd48c25a26b72acb9425e316b3d2ac130a6943
+Y = 0122d0809c5de123c6e5373c1680a4d566c565408b6750d942c024d56c0d6761807adf9dab454b84254671dc68f6917f09a442643e6db1bb35e6796816dd3e5c6a7a
+Digest = 6f89ccb8daf6d4ee583b04786812da9e2960a6e5
+R = 0144c1a1e075aced5e10f50ab7ab0f795bac07439c953ca0c749dc12d50a7e4dce21850dac1fd773e46576335a555f20d266842a8bb47fb464fe3fe297e9ee356e48
+S = 0125f3b6f1cf7eb704bd37391a43034df9260c4d5fdccd583bf65dd5ab4b007c8f837a31a0b7c5a0be3743a187b2569841fc4c69f816c8234d8ae845b92fb9263242
+Invalid =
+
+Curve = P-521
+X = 00882e2cfed1286668e62699ab20c6c40068b460917b306e51ce7f72a4d760e19b3f6cb5897de599cfd84ae70c26d1a39144772b90f8ba1ec2d0f09395265f0308cf
+Y = 0020b80b99778dcdd3dc47da42b279cc289eaae369b9e2c4b0322d2eee9b1a76eed6b5b70d03d83f1db81a67ad6bea98ce71b120e9f83f0178cd6fa3f109a87b1fa9
+Digest = 838b0206f0df827b5aa38abedc972a8ed59611fa
+R = 013ec7124331d896832b77440854c043cb605ae9cc7d20cb358513a5bab26371903c6abc6e4860a0b4940bc5429755341a10251195e5f8af42494c002340ccc57bc9
+S = 01460bda2fd76ef05dcbe1cd17b9c5663b03551cce586c56e103179069fbef6ecae47f6555db755860f0b06eb1bf247312ae0f9d64c5cf13fbc42b923d6bee151b5f
+Invalid =
+
+Curve = P-521
+X = 011a5a6f7166fe435c5cc4238daf92a2d1af483543b7f505785ec4e2d93b2ca1d1eed3bccc31761aa60f7dadc97629475d2712998c2eccb82a78d6da7b0524662e9f
+Y = 00c66d54768f5daf947cd414a1296a54c90e2b65a14cb94aecf0ba51c280676c160c39539955f2a8194357a983a1311845f8cac51cdca1e209bbac32cc809f0e4e10
+Digest = b14bfba79b3a36303dd4c5c7e6bb6981cf37bcc8
+R = 010f45ccf0b4de7d2af890d65395c715043dc5ca1489c79b820347d51848f599ebd4aa558c62ce8769c5d5a294679f9aa74414ca6a1b82f183f23558b0a8dc6cce68
+S = 01adaf876dc35310ac592d1e3ba89f148c3b76417799f43aa1b24c1d2e3f544c018f066ed7baef480f7488820593bcbb25ce08183fc14c6c12fce0c118743f04e281
+Invalid =
+
+Curve = P-521
+X = 00f3bd2590cbf620991d990b84efee86073f6c789deb07b89a1f278e6cc9ea573d8586ac395958ce4e1b09bda73af1b1e6f2a8c09ecc697c021974c024564ed87165
+Y = 00514871935c187e57d1aac376aeb018acf57c4d005d85cc939a6c83256f38b2c9ecb1a0ec8d132e0f5169843faca4ae664459124bf5f30309fa86f87a2604058150
+Digest = d9cba47d31015f5fe70b1bf0c2a7ce40676bd1e8
+R = 0083e6155dd97bf9ba7c60dbcdcba7824b125a73df1433fcb46f57c51f63ae161ce67393d327d174aec7f0b552decb8131a192ae940deb84acc3b45be61917fc580c
+S = 001fbfe61d75dc3fd814eeabdececf361a0a066b8c06c40f0e057faf8e4e7b206dfbbd3a99ef55df67234a29fb1a618620d2e27636d35bb98eb7535d1749c4b7e7d2
+Invalid =
+
+Curve = P-521
+X = 013136c4e5dee983f761955bce7c196a000cb26863a1dea762884bb041e45363a1ab1665c0ca69d1167e555bd63bceba08f6ee14571acd06eea3e1e5d9c11a036984
+Y = 011c830e1fd29ee4e10d7c6db7e90d6c1319c9858f87a944542c28679d83680747eaf71a29362ea2c22a89d78e2ce020dfbba74448d2f46b3f84b99f22604075b22e
+Digest = eb4d89e3ce396c525fdbb67e4620ca99d9585d31
+R = 0124b3bcdae17413de84721e6ebe64409d80ac07a3b6c9a603ef19c5162566076108d30ec79426d24c72ac12af6fa1caa4830d55b4e6fcee900b0e4b20cdae0eaf70
+S = 003e0724d156c3fe5cb799a17972fbb891f0e11cfb650a1c524f6f2aab134c70fb114084a7821e0e12054fe071c516cbfb393fe9d98c840e1cc9e8475d3add81e0c7
+Invalid =
+
+Curve = P-521
+X = 019eb73393f070160d871cc396cd8d6973d828d6f3c17bcec7168843f0342c1b54f3c02a1b11348da1035833df6fa469d75692ecaa2feddce9210a813bdb0e1f9936
+Y = 00e030c5a11e2317ba10a20ec373cf69c96660b434445235efff0a9d23904c5d3ef49efdf0897222e51624f047b567ed61814f3f9e8c62f16ac27160897d5a09f476
+Digest = 43a5c6621edef91f6938507b2dc2092c6b17fc9e
+R = 00ca41bcf9e80780687ba70d7f5ffec7da25542dc22144d9f6843889e941cad2fd8d8771755f38c0ef77909416371726b066464d1d41f888efa39456dee859f0ce98
+S = 01770961a369ca70f9d73b61aec34662735cf228299a7c668aa24afbc9d7f621cb3acff79cee19d107361614c1e71ff1f32ae4f02b7bf94486f0fcd61b6f76f304e4
+Invalid =
+
+Curve = P-521
+X = 000c12d47011ed272aaabcb0fb6c12d8627f33bda02b2b3c3ec7b5ed60eaa577add4205d222b8ba0485b1d98ade9df18ee1e1ad9e0a9e78242322201e3c664bf8c9f
+Y = 00d1b86d4a1171bc80822e0e1094a96bdf7e031201ec212ab7d0e7b55394cad8335050701327a0a1a17181b586b89ff24a658e4b0ee16b8418dfcac122f2457f67b1
+Digest = 35802e4fd349e7cdff4b85c76a417977c3e40b65
+R = 00e4678311d0c068eab2118fc0a59014ec32c89cfd1e0273b966634b87783011b58a99204d266014d0236bd6f276f49c693a4d62b0601c307c936252cf718e239dfc
+S = 0149f5cc02a6aaa126a99a59b83ae34f405f8076b597540625fa76e27dd29a85b6a4b0fc3e73a245a91d64a8f2b13ac345553b7a40835af76a9528cb48ac8d0be364
+Invalid =
+
+Curve = P-521
+X = 00f50a08703250c15f043c8c46e99783435245cf98f4f2694b0e2f8d029a514dd6f0b086d4ed892000cd5590107aae69c4c0a7a95f7cf74e5770a07d5db55bce4ab4
+Y = 00f2c770bab8b9be4cdb6ecd3dc26c698da0d2599cebf3d904f7f9ca3a55e64731810d73cd317264e50baba4bc2860857e16d6cbb79501bc9e3a32bd172ea8a71dee
+Digest = ca6b94a2773e9b7392b2a6b2863efb113fea8bba
+R = 001e7cbb20c9a66abf149c79d11859051d35cfddd04f420dd23bd3206c82b29e782453cabfefe792e4e3e68c9bf6bf50d5a00ba5dd73b41378fb46e91ca797dbb250
+S = 00f1e9252573c003cb77f22c8c6d56f2149f7e8d88d699983da9250c8edfd4b9f864a46c48819524651886e3fd56492f4b6c75fb50a1d59e8bfc25f9fd42dc4e1d37
+
+Curve = P-521
+X = 00fc6486a5cc9a366b2c25d57f3f1caadf93659223c7eb38c310916cd44bc49d3ecf1cfbd429b57e329e1eab5f552abaf828ad9cfbc2f7534dc8c87f54d252e7b69b
+Y = 01c0010af6c5cdfe26b068990cf44b1bcf324d0940bce1e953f7366c757aadaf25ff7dee4947879f305d3deb1e9a849db3cffb83bc1c7e5e82777be140931d58d177
+Digest = adb7456d405053624755076f2654f24f2bb521d6
+R = 00a58843085162864b2246c619d6cd38626657eb8f13ed5921b73071b6bddd56640ec9a55e7f2190481ef5e356425749e626a4b988b811cc12dd21c61cea89640095
+S = 019fbd1f9b108aad0208d1a27735ead4685f04d01882ed18c217d8e0e0fc71d8a98d3c45c471327e4dfa631cf4b826ead3bd5fd4bc0426fcc95b58bd354d012cfcd2
+Invalid =
+
+Curve = P-521
+X = 000933ee70d1470acaea66626394023020ed521d5b9a52e068b827d23af283bdbbbf3999b0c2ced0abf607b467fa86ef89bee3852d4e993df3c2c73a49488740cabf
+Y = 010231bba67cba896274e7af7f9c65403e48c56356fba772120aa8781611239d0f50b8958ec8709a301078379b59123b47c5edb87bc2327cf607f876154904b93e92
+Digest = 40d6902c8bdedd45f6f6789f8657e8716c66d6d3
+R = 016f79df89a498ac65bb39d62e1ce82e5578eaf778084ec5926a638d50ee5943c87955c8255340a90f800fd43d4dca125b68dfe957d148533126d5761d711412bcb9
+S = 0175198228ce2eb0222d64eeaa403c0571989046e638419ef96612a90094a26fb819ff1addd823f8912e07ff32ac72790c38c601505b45dbb9cafd1b46f352aaea0e
+Invalid =
+
+Curve = P-521
+X = 0007a5694d537eea406d753532b307c5b86e8823d31e81f6e7371e6def61f31c8f706c1b89f8655e54f68e6821096e6b96a7c3752e47d8d3ef5da135f881927ed92a
+Y = 005810620b7d83d3e7e48f7338b18e03c2e97dde5dacdd5d54e4c7e75d736f159dc45431d5d3c07153a334fa60567307271bfb85cb0fcae142cbd7baaddcbdfdc018
+Digest = 6067b9f7fd22c43c4a91550c461201318220cd1d
+R = 002cba23e78a1f9c6c18bd26321cec0c26db4f1100b986d37a0f24fc42c75ce4731a2876e8865ae21700289734ad5bae3611418ea37a13fae67db2d1a58a86f85422
+S = 00c438e76249b5016e0b83ddef5447420fd13aee6f099a0b9ffafcba4e7227f70cc5dd5abba03532ebc50424fefdd4f6d258ffe044573aa51b8a5d1d5c6e5dbf318a
+
+Curve = P-521
+X = 00a00f34f4572450d93607d3ffb1fffe7c86334426ad60fda27aa647e67c34b2cb1f0a12f4707336f1f708b3ba1f3cdd599ae92a2be92f9ae5526eba9d4adc052fa4
+Y = 0166808273466ec1ef2865e92b263b897131c5ea97fce1adb1ef88c8ac2e63eab97567d82db9c0825510812db1b2e4cba705ba64d33ffdce676b7f3aa2e343f7834e
+Digest = 3d0012d4148fc6bf2e703ddfec9293c27a9fc4fd
+R = 018ada7d95f4d05350ae95494b7c81e233168ec88c5ebffa2d2a3ac74cf90b6d9f80407276f92bd9b3ca949e5d5cd51166e29678aae58a284b9e6ceda3a550b08c15
+S = 01ff12f5e9b12efd941e8a445ac036d735e7bf64237972002568e8eeb0dbb887709b53cfa67186f4df215e2a9f7b9feb045270c72196e19335a9c554a19cee0a8397
+Invalid =
+
+Curve = P-521
+X = 0013a5c825a9ffe6179cd106b4a2343fd3318d83cf3be58d971704d0328486738f7536041cc69e6f9548851cf591ba080c4a1c4b4f5d95d216138d72bc56eb63779d
+Y = 00e79075f5acb9f52b67f8411f310c02aac5a98dcce0275438e59f8a2a3754ebe57815247a00d3506fd342d3d43607ba67d4cb608da3a9296d57619223c02e0c4f8e
+Digest = 4ee72ed3337db64795f3b859021c9b6b405bfaef
+R = 01ad988418099c6483e6a8d62fc16a9fe571ad35c8cf111c3f35e680541a2f5ed96896715efa4943f8b46d20a0abb228852bdd5cfce1787c150d01231abc065718e3
+S = 0095c1e7dcd09375d1760700c5351ab23618b1fdf1b2b02e918c0ec341e5156300b602f7960e0eee2c027aa0076b194080e63155dc56a81699e8aea36ddfe703b94f
+Invalid =
+
+Curve = P-521
+X = 0092bf4245f0ece3a8c3a723de152c6413526c333a64f4f2455e7b45396c1614c473460246f49c65e957dcf779af0b675eaf5ed7800539d3619a6fb131f1bc610968
+Y = 0047689692e52baa835ee9c49793bca7b01ed3bc4d4c396a54eaefe0520840a31fa3c35cc0d2317ce367881a15a3c06e7c26b192e90fe16c10e84c92233910d7df7d
+Digest = 8f0ab491cf25b8526f8da76e329bf886a84c279a
+R = 0141f936c6a5ca580e5a18caeb85fc13e9ff57d50d89b8447c8645ff66202e71eff4303d57c28ee6b68915de6767a124f3652c22940656f4227d61ff30b17c2b9aeb
+S = 01c7bb4c22e68920bc6b9df0626b09ac79e5b76ba29d0b632c0b892c8661087461c4131771a2b3a9834ea4b3d3bddac9910331774643ae22b613bd0b2464a12cfabb
+Invalid =
+
+Curve = P-521
+X = 0194cc7f51d9caff692137190541f5aea160977bedb0d3b67c3deed6669bff160696a96550934b3dba4129e204f068901c84c821523bec91ec40336dce0d2673e794
+Y = 00709279f85ef54164fd7347afcdbfe42d8d14e6808002b3e0b59bcbed80ce0c16e2db1b320c1d98ccdd75efc50fcd6ce91df6baaa99ecbee6df41da9c142a74386c
+Digest = 4eab87203ae54fe6b3c0913cb865266d7be8bda4
+R = 00d2542223b0a5322249e8f1af6d559a87c39aa5c3c7e595b07fb7be4d3bd0184a419651f96811f3e8c9c578a4be68188a8a3a1ff0ccba4af5429ef95c64f34d645b
+S = 01ee3123fd300cceabe2ad99bd1975c4594005ac9ec31d44ee4b9fe325d39049a5a83b4ac2a7f0b603c82dd88d136507bca2d383c7e8375c36eda82a169b3e4b4034
+
+Curve = P-521
+X = 0145896c96ede10f5b049edc0475870c0c6a09ab9cc47667146deca1729d98c124bbe009e5e161b88c7ff61e79d6f85b9c4673c0664e039dab852e8f99fb0ae70a64
+Y = 005afb810a0a9c7f008850e8ecc67d907a74ff9e58f6d60ed14b3ed31e4751077a60de444a43d4d9a9b944905b79ff0c0ab431b21e0fb160cce8f08784677fb58bbf
+Digest = 7cbce9271d00009eab429db9025bb4edc9ff7151ec964873f74a5277
+R = 012f63284068bb815ba935833f382ee2a8a5f64e2dbc9869be281ec7d3a28e2d7d2a84e214d79598213f82217d95ba9868da4dc3a3ec7fcfd7c8c457a053e8b0ce5e
+S = 012b62183c893455324b94b7cea2fa2e1c912362f99e5159e229ce67a80f45c7c0d27340e57b4a8f40b80a4d572345df083061d311b578a73c8faaba4e6a194b4726
+Invalid =
+
+Curve = P-521
+X = 0113a72cee148a7428065d8f8e89dce2dc7e1bffad46a130af8f6fc8d0fabf26ad76bb64ee078ee66fbf0212987e363e176f0106369eb1e43297851ff409e935e216
+Y = 01a723ee3f44aa68e1b43185a50bfca99f349ad47d848dba8f9dfbd773f9f53bc0298bf43130e19ccb8021be39ed70c7b1f7295cfd034e713878f47d7508059a4f81
+Digest = 0068909a03ecb0947b2d585eea1f5496a6b3e50861089cdeb75b516f
+R = 0010b883cb3b76612b6cd8f9288459d373d58c2e0366f300623ff6b28224036ad1df47d1d9df8037a18e774e0bcb42910e96dc7d7fee0b53686d5d3af13485453c66
+S = 00a29c87d9be8e91da4333089043693425892f50333c7f93ab27dabfa5cf89697f366573621a86d523e850caf31a4c26051e76b91ad3e20a391ba724d4e58641cc00
+Invalid =
+
+Curve = P-521
+X = 005766da7e6d9ebbe7cbb5b9bcdd657edf36fc4a7d4a173b99bd1caa804e35e937289e05cec2cedf86f0f7a8de42958e6052500c8a63b496ebea88252cf1b44ee5da
+Y = 00ad35038ce07b53148cd7d0b4ee8c8ad6d89a2c68c0458d0d694036120893ba24a52792e0c8097f86591dce015151659908829f323a5dfaecfc51470779f8e5a5fb
+Digest = f743f4bafec75012878f74c39b30bcdfe1a0d0e4da1ba84ba8320796
+R = 011c5357042c1d98133e76f0a696e27a22738c78ff17c903d8a5190b3c5fb186374fce58fe47d9933c2b361cb20546d730bb5602fab6c8d14e0114a64f9d2b1d892c
+S = 0115ece7d8ab1b578b0e870faa8139d009f6cc3cdacf3172c047bffc1a31e2c66b198ac1ab8c90e826af291de58990e32b18e71b26fe01b6bcbaf86db6b1a726f51b
+Invalid =
+
+Curve = P-521
+X = 00ea4254c3111118d3d859c704474251fa951b0cfbfd2f249bd32f70cecd80526e8fb72c1258c994d8067539e478890d5637ad925ef43e2caf297fd1eb49d9acac77
+Y = 01ed78a277869d8bf7f2d5eb9c2753aedd89197fbfcaf36a633a4f3b2bdb5e706983641156f0aa6e13d38e907546a2603bb1cec785bc334fb03033600a77fed391f2
+Digest = e2a441ca0e946139960943cb42fd6a1d6b6d6fbfb9739d8fba72ead7
+R = 0127570a0c0141bb4c2ababef5fa879e55c1637407686b49535fd17b3b911452650e302e9186d539782cde4d48ee43c258572ec299ee63d961def2333a4f1f8d2af9
+S = 012ed61b0b4c889bb36ff9ba648318a2b11604be6fcff858adbba8e59fa49fa30e2e20df5f2d26a8b9e6d989ab4e50586732adfdd4ca49ddee11cd889f0176a59ca9
+
+Curve = P-521
+X = 00549a23bf1b24fba2e921c5c2ba78809d6b0623fb1b92a506690b668c946daa393ec42ddb113f10a34f1b11475ac1250f119e83149d5211791dbf6cfe4f591b6f44
+Y = 01ecdd45de1ee27f6abc1270fe11f770d4e26d5dd12d0a7baae6f3fc9c7f074541bb05ff0137c3923e1f858d643ec63f7c50f776f45009f2998a0b4f37c192210ce3
+Digest = c063ab8a65966f0b7d6c4127d45ad56f57e5922f5bb0537f71ec51d3
+R = 012bf2daa304f162454686f98330f526a21d066b430969547ccb0ace347cadb4af7bf62b473e33aa1f62b5959b7c431451913d5b1ad297b4c1f6bc5f3afc9e052794
+S = 008c7c58e4703f46fe0885f353f97bfefbecf5f10b95a02d4ac7764a0a713919004a153ff443ce417d24db60d325357408b59dbe7ad043e7fc7c1c23cda14a867d83
+Invalid =
+
+Curve = P-521
+X = 0087784b171cb62451eec46449a2a1ab769225288a092d833aeb823c99de8542ebef8c290f96636a45e2a9cab678a2c55e10283ceea6780c8d61d341952643903f51
+Y = 014a9315a888dc2f774633ed1c5ba95e09b6898764dc5a9d568d727b56fb50d3b288eb77c9db3b1cd31aa204ebf0f2402fa513b782527ce5c5652a97df6bb05e35c8
+Digest = 4a06dfd0dc3fe089a1081066ae40a7297c9bf929dca9a6b6f2a41a49
+R = 0137a47e2f3e1c2916a4a590adea04e93b4d18f2d548a3cf832401bcc42b1b35ad820e88a7efbc15d1462f518342cf81d41a40abd68651bef73816f58d1ace55e338
+S = 0101e3233d8da91e092a6ed4db279c594494f73bd8d6d7bf5f6a8437146a29b1ba78fe3694502ca987cf108af9f461b6341735b8c2a21653d1b52010bf2ee02e02b6
+Invalid =
+
+Curve = P-521
+X = 00b97948459489a548f94459fdbcff544e87f5b93c3ffd8baaa997f616eba75187f7a8fb13d848ddf427aaefc3cd001553c213bd1b1c5d892847eaff2d2663d90637
+Y = 000eb07b08b69af1f15260ab6a8eb84f9337d9d3f99148e61f5ee06c5a031f1eb467e897b65c0d14773018929d9da129d3cd66b8f9c11ddede32bf9f339e3de57b13
+Digest = ab236a98d4f9487b888cfd01d52f7d3746ffc189207b6eb31d4eac5e
+R = 01a31ea52171394839ce630bb1c2912b42b045c5143c3bb1c04a5b97a738887f8367c9607971b00964d5d9fc5d921877cd6b099a84e19024cd77249d263e729e7f7e
+S = 007600944031efbf27face352b6267349f3cb72eca5679d74d4a0d47fa6e84b391f4743cf2f4704afcbb9dcf7b522d812d268a1ff393d0ff1b44b11b6d75fb84d750
+Invalid =
+
+Curve = P-521
+X = 00edc8ee8d40918ab15122d92522bd862e9d46bbb6550ef22a52de0e4fbb6e4a4635be48406bf54bfb24dc385f506086c0a6e1297cea60ec847007e798a632867cab
+Y = 003e92534bf025440635fcd4d40e4b97c5396f33eb16fb1e3390830f24737b6b1645262b0336fe74284afdb99ed6b8551f82a449d80911b0c0f02592c7d210958b94
+Digest = d8704904fd8939d7a1017495a039883a8b07f371eba096b2a54d3057
+R = 00a1f835da9b892687201294cf15769d7390e62e46efe1f61ce7ddc80fc47dc83c86db35a5096cee41289d66d7803f7e8e11fb9c9ca867123027af343fddf2b1b89d
+S = 000b5b9653b2533da8e52292f37b86aaef201743c6d12352470656ca165092d74a8f97ab1772299c62b93d61ec097c957ae231d3c80ef1b9dad1f40b06e0c92ece2d
+Invalid =
+
+Curve = P-521
+X = 01f1464035dcc9c6dbc5e32c318b6b3e9def33cd2feb02b7d4b7249155078915034ef823a4d55fcefecfe6a10603891a4a9c3e6ccc1a05809bc510032d5fd30030e5
+Y = 00ec160b9da57cd8e55630ab9524301ae7f0f53be5d55f7e7b99270272f6e6a33d6fa5fba73195d242e7ababa5cb69f6bfe9165ae3fcc1645df5ca4b6254460029b7
+Digest = a824681278f1dcdd937c6d7d97e5c028106277a07c3926150c7bfd39
+R = 013489e2917236dce23e929f8c1ed0057b0d70c68762073c7b1787bd3cbdd084174f24aef0af10d09c77530c3f76099ce53b63598c0d8f8ce53df83a9af11b7e173d
+S = 0111e1868e71f5e83eb5e38f97fbc466a9e729e19165169ad81cfd214a1ad1e56fa47bc97ef47a93511397c849e9da3f7cee68bccfca4c5c60762d99b8c41393b879
+Invalid =
+
+Curve = P-521
+X = 001248e0953894616aa4b5573644bf4c0b1f45a5c0a47a193c3ebd2215b29dcd387d76ac98183894bed359f06c6de7bb94e975c3e6f9c1be3fbe3b763e2501b524cb
+Y = 01971e69438e24b67baa6203ac5904159763202c16d6afa91298fb43eafc867bead0e61be1601a3fd70219af962f7140cd0a29cc26ebf765c22b895ad0f91aca7500
+Digest = 4d9ded4947fe2a964a6d54f6262292162a14b054b5d8606342d32523
+R = 00215d8b547b0fcb9d18eeb5acf277f90d97ab6371aaa6e8a3c1dfe66d2c6ba5fef45260028d25cf600bb24560e599238b285a823a0dec5e014db4cddfb89ce64aaa
+S = 00bc5c4dba8bea55b73866c0b4bf739c764ba67121b9b1fb261b282fc1882f22eeaecb5c89edbedf90318ae8537554dd8604930bb893d21ba36ea445d0cfeaa28664
+
+Curve = P-521
+X = 00bb34185d844a096f7f673f86b317c27e84fbd6938c1e22e4afb1120489c38508dc643a92ecc963b694dd6f2c7d0958966d49b20883daad4b00a8d0107f2b8ea2ed
+Y = 01e5d3adceda7ed7c7177040b1845fa8064e187a16b9336294c1402ea2eb89e6c14bdd392bbdd2ab516aa7ff3987bc44f6dda8109452db403b39cba9536a39f1ddeb
+Digest = 2f2a916d2c907ab764986fb1ee972907379a8b66a281ff6996e1d158
+R = 00d1f2dd7534f9f093a281fb538660324fef9cec2dbabd3527b1482f980dc08cc84de25f83b062ee5cfe1d3372555b7bcf618c71fc464caeef5a8bb141f39531f15c
+S = 01a1be81c9379abd578ae9663cad8fdc892ff46144f77da469b832fec4e5eee8a6465be3f211f26e3b72de5a9e45aafa064e24d501fc1963733388af20c7b9c9959f
+Invalid =
+
+Curve = P-521
+X = 012918b48baedcb53edc782cef70d772232d1d9e1f5e995f70c76b510f3effcd5c239625e3ec5e37d202b37e4e6047a28d70b489b44bf5bfc2b2cf03c8abaabcc4fa
+Y = 015ada9031e346257778a7b6a7d8285b9d66cbb27b1686ce3de3490c08a3d0a64495906f0ed6e1e4b7edf1ff657091f97bcc383e16f2ddb3c723c53d559fa0c5ffac
+Digest = b1e5176dee3fe3678e36e8471f4e5769b366271eaee73858e53d22fc
+R = 0074cc58e3fdbee1b3b09fd82621bd593118fd4fb372adfedf8895f1775add9bb38fceefb42298c16cacff33af75e38443388b448ae251ff8c049a09fc7af3cf6ad6
+S = 00c51622876dadca150cb6be19dd5de70446cffd2bcaacfb8dfae4e1c7d58c41defa4589668b45958cb5f164bec71353ee57817e0a882c8643fa7bc6339dd88480ac
+Invalid =
+
+Curve = P-521
+X = 015f8a3371c14a76d932a83f242c56097843ca370385db632fd91e05939ce0f87a94028f9f197c435e89525da4624db332ab1b36a1a59cca8c1ebba281ef5ea48bd0
+Y = 01bdd578714cab38b3d07f28f286a55659cb4de6bdbf13ffc149f0cdf71be6be2d11ef800614a1ab97731886179f50360bb98a8c74ec5a222dbc9b6762a4f56734e7
+Digest = 3f9668946bb66d9f63774aa4bd7f15c9dc94da241867b13570e7e4aa
+R = 00c15e0d1c06abac899b90c86ba6e37c8b8cc982780262e303c94a0c9a1ac52554423257dfaedb70760e6ecd66f9b74913a283a2e44d05dc8eb85e5aaee5a4323015
+S = 0014783e744895c7b6084d536a58e9d05a1a53a4ab96321d09cc4c89a908f75f01515c45df3c471ea02cca0bf9f07d1873bb3404d3ba5b51dcccf30e9a5ea0bb151f
+Invalid =
+
+Curve = P-521
+X = 00af896543430ecf3b22534a1a3c1c84fa0ae28f1cc659432417426fcfa814faef9397801f16da3bd610206c2ad62f775ca01ebaf380fe64e928cfcb48213a268cdd
+Y = 01bf669b84b415f99e8e997b4e67d0b9f359823e0df92688c760ca99c08350f0375b301c404eee80d86af5de31e95d64ca95d9494e2d8622edda97282732e7e2757d
+Digest = 5d90c46baf8cfe5541ab3ee8f3aa02e881db1d12692dc16b0d013420
+R = 0191e914f1520532b8b3ccc536b103e4eaf2aceda838117b7090de8b3c2ea03fbfc1f54d15d6fe8e6d2cbb794d0206ae3387e808661518bf5c6dd608b5a40756e24b
+S = 0152e95ec2ba49b5e4d65a3f50a29d140b144f10d2eeba729e439f34ecd7b97dbe672dcc25647446a49e43f5710280d79fe01c0a7b7956fd80bf35cb6d7e560cc983
+Invalid =
+
+Curve = P-521
+X = 01ccee36646013645ac83b532106a9d78828cb387819bdec3f7d982ad2744292281a00d59cd4c1290365d5b821cfeccdbaa8ebd5f10aa1b4b1342bbca27e7619023e
+Y = 0171cfb6c2a95aae42458b6bb582d8efbeaf7219594dca5904b2b3c22a203eac193068e603acf1afd10125306595d0056e2bdee05aeef2d4b774498619cd5f1a3664
+Digest = e201f8ff4c18ef73b7ee6ea2ab3cc482e785bc77b71badf828d9ef29
+R = 004347e5389a6b4a3de2e543d7474c28e5fa284f5268e474f8998395a7dd154fd0c09253b8160f9bae840189161bc3c85db268d500d6aa82a3c383aa025553fc25c9
+S = 010623dda9d2c39d5e6d463d96dc1ae91f0c3f34df698dec0de2e1840467aa54a5bdbe7815426b175f6c19d1a5f09cec6f5270658a80ccbfcf58a30e10cb342e9e01
+
+Curve = P-521
+X = 015bd9bf7a35cc60147b32b64e0e4e54bf9ac2173cc6784b3d4ebd076aa5d45c1e3d0846b20b61d6342341a8801a2f63028c991831318245c2fe31f8acde6bf2003e
+Y = 01afb67c9c700ed332b47a2d148e6ddd3571e138f02a81c3cfe6d4dee0f512d92e76574fe5797c5566c05b3239fabb212c735615e719e718fb40fa6783c964357f72
+Digest = 3dfb0c771418d4f1ffd092de8aae7a563af2c9e559ad0b53a5b61090ea77eacd
+R = 01a341d0e8906239faace79554b90d1445bd28f703d7c7cc8eb163337ad3d4bfb3725cb06e618991491534d399866df5c5bdef897c889947b21148d89c657e64124d
+S = 005c5b728837d44b7b6935efb2b721b4f45c1675d803d87f70158e451434176d9682034c9b356b5f9181e07599bdcb55e5bc808fdd36fef9c19ddb6342c975262024
+Invalid =
+
+Curve = P-521
+X = 009f21a6e7295b183656709089b3c647140c81f71b0b3812e6de22c52245335599ade6a3116cb70277dc2485f91c7b1f46d62afb60fc17a110358c9a02e02e010960
+Y = 01e914284cea47dd6836e7ce899d0c9a88d67fc9d039ffa9fa5bee58d247e0d0dc9251be8b82afd3add327f98c5570bdcd8ad8827820032774d19db09232aeba190a
+Digest = 6b7b1a121d5e8f4d3d0294abbb62ae16561f37b6fbdd6d519209c6663669323b
+R = 00ce4b2ac68afd071531027b90d4b92d9b0e1044b824ccebb2c9ab241d5b909ead1ffa2dc3d330f57187efbea7374bc77c4f7ce7ee689aa5a1e27aa78abc3cc1e751
+S = 00aa85d84f9c7fecd25064dbae69c16d6fcff38040027bf476c7f913746272b5d4b9bd34d2482e27730522df724895b99253aed86011139928fa9a272892f8c99d8f
+Invalid =
+
+Curve = P-521
+X = 01098be00de7b2ee7390f26eff82ba5b6de8f04d7f11909193923866d2feefad9b01c5d78b699ce0a6900dc2a3073a03505ae946aa6f384ab0573ec9d17fa775dacd
+Y = 0106e122e7148b547a0314da646b6f834e66c2ff7f64f39da9dc7983e80e84063e23c8ce12994e8495b7786c2b3180d7f22bd2d2becf1e1ba2029cbbe8d4801b65b1
+Digest = a1aa4766ee9db4cb7bcc31a333214b096fa608623acf5a246ba0de66067d61de
+R = 01092e5ccfc4f966c3281a3924cd527606ce8e64cfd78f57373cfd702f528368beb71eb1a2cd64005bb172cb35b4ea61af88cb06bc8f1a38e2d75b235d23947dc209
+S = 01aff29a28d935d0e10bf8015f38ec128e0ec047f04020d1474366807b140e4d4a6d069aefc8dce723fcb4fc803df30b3880cc6d0dfc75c291d848d89e06ab7e24d1
+Invalid =
+
+Curve = P-521
+X = 001ec67de63455605b31a460d4faa664697cc505885577c0844472842dee78fa6d522e4b942d3c7e2de684e6399f6a44a328ccaab5e678cd99d49f015e35a934cdd9
+Y = 019b41da41e7506cbcb7c31d39751669cda166fd045c86e1fac68d39d2ebb0f1ed50b8a923511e1306952888e068092b19130181c2de5f25c5e1fc4fd9ea202258d6
+Digest = f00b9327fbfba5a3fdd7bd9331582822b7bf8bd8f2fc97f0af5ba207fcc92b71
+R = 01e1882a3d98c236189a35ffddc9fecdb7cb5fc5e3d0784eabb69d9c37862dbb38eed6c5567a0abc4f74099329681b9a0921515f1df83ba8948b51d3871866a8f7ce
+S = 0025ff707889678f7cd05665c941a2bbe13622a1e75ab986cc86778658c62e527f55804ab27d0643f6bb8adaab0614eac47f33f0e1fba109c63b28fa6732a5afbe49
+Invalid =
+
+Curve = P-521
+X = 00defff5ef7cc5de0e1ac32261e7a74e8c434c0b51f76df7566b612cc5b8201e7b38c51aa6118b6307f436394bf452a72224c977e37e410eae9525df2ee00a8123bf
+Y = 00263b7db73558ddc783824f0b19776802aaf5e46ccb1b1d1dda07d2d6c5843f5036ae8d381b235ccd2ed04eb90c5d51e32cbd7acdc7031cae63c06797556fb66fe3
+Digest = 63c7b65f78581fc15992ac54b1221f16545a6e50a0c740e3f3a1685f09f358a8
+R = 0089bd129a537840a52ef434d5a8ba4add952f72f22a84ac4523ea0bc02cbfa8b681ab0ed3fa2bca24ae575f23fce7efbb9bfd28e465174158a5ad2b08fd9e0b7132
+S = 0004ed533337791e05f8d097eabdf4be96b3fcc9f876d47fb8c5c7a05cbddba398cded2edf5ec9b7dbb4e32c1374b46953d66a193c211ef12de4b9d73adc369d5e95
+Invalid =
+
+Curve = P-521
+X = 0180f1e933054473e81ac82aa458094b7cb95d4b8d399600420cfb082e37980414909a133d5e42ebb7d2defddb34a9fb51fe4ab72e88526fc28608e152aaaba3ee5b
+Y = 01c5cee9fd322d1c3af1726366e8a1e3f22099d9246d4bb02708eed89ecef1fc73926dc97a5c263afa235edb39a9e63d9690608846abc482397a2d8673c5d472c970
+Digest = 1f2f2957156270593c0998ba0d12c6d2adfe8728ccacf3332f9e6c936c33c805
+R = 017f1fd4df519ef432f68b5f426ff23a8f36b5729fdf7c8363d73f4e707d9800c7b50174fc3d66d89813a5265f8734602e5c998c2d7b51bdef6e90ee5a527e1357e0
+S = 010560ed68f152d649493c02c1e32bf4138aacb5f2d7f449e7685336edde24e5ce1cfaa2c54530f1419593614971896f1a877dda7bc5d56ccdbab18e770647287979
+Invalid =
+
+Curve = P-521
+X = 006d8c16536b17cab6ff41f5df4038fe416c05ccb601710909708dc561b02ceed9cf020441d9daa075e8fd604531ff58084035b1c19a498b82582f5b20f9cedf61f9
+Y = 00e89d71c66e55c4f5bf245413388bfe9de83944b11d1abdb4692db7da8a086442965ee512f7089f89464dda5d7786e52cc26a8a30bc8824cc56a289fefcd42bdfd2
+Digest = 2e139493b5db177dd536c562e0c90445b59a686eeb27e0a7b7cd93d72fa4ab7d
+R = 0087f86cf4bd36e8253097ac1bc8500dedafdbccbe5767ec25e53c73c4f053f3b37acd1d5ea4c16e4058919b61d2a67393220ffefe07535d53923ace6815463c4c31
+S = 01def2582fd0df89fa28c9ce882f5c3846135f51bdf7f4b2497b190136ef04618eaa22a8c5a117b0adfc6425eac3111b6558df145a8b14ad39524b98659e01d51c21
+Invalid =
+
+Curve = P-521
+X = 01c7fb4747a409a3723177c38c9943b81b2d0aee867b8f424e227f3a664f1877c560d37953e7cc09390e05599292bde1ea345073ec365834d99ac59332f6e5bd29d7
+Y = 01b7485b454d5ed5d581c7897a7e68f425d8c23cd89b934747d90765a5fda1cfc3d997af61728f328cc8bdfca8a3ae1b3b90be13cf164c343d199b8e16b0400f3e33
+Digest = 8ba31656449e19607c84d9a8d689193f30a6111aa87b8f978b9cff5abac9f827
+R = 01552ac2dfbe67c6abad8d3325713c1e28537eae620d805a73dbaa4e5e04acff6ae0498346d6e41df1cbdb20b70d8e548564da8fa239fe6c6f28b6c2a6ef57973097
+S = 00cc9e60b694d792f36cbe9adff8dc79f0f75b3ec11ff2d54419227c7566e0bd441655eb30b558c78a55ac613c1bf3c3058ea7a4bb70adbf5b49fcae15e54defd6db
+Invalid =
+
+Curve = P-521
+X = 016c0e1d1fc81e5069e9c02794fdfe1f5a8ac5008305d9ac2234eb0117e565203acc6777c570f41661c5db1adb26097d7f5f2a1762c4f8039f1b68caad75915baab8
+Y = 000b3690995d6d881dc1564f792ab174cdc1a0fc6f12d69a21088d5e82de4a7d56947a2dad0ce64d9ad0675e72b6da755e3ef82c9cc6d532378c23112210236889d6
+Digest = 4d3c537785e9dc1d434091ddd3be8a48b86a02df7e6ffa269642d44cf8f32c25
+R = 01316e9a934cad1aa0f7dbade1c9ad942d61bbe1bf41b7b95e3b25b761b9899f6125790369277aa09fa57340a2b8c3c609a08ae7be5a3c09dd4d081e6cb54d9f3061
+S = 00d6b285f91c3c8d6192af624336caf793ad5300d96262f5e25228dfb60896c4e28e61be22e92ca7d6e11a02f36655441032bf291f895aaa117f6bfdfb422286f255
+Invalid =
+
+Curve = P-521
+X = 006194b1780a2416dde8c9402e3ddbf310c51ed87fc40530ad5c97931b99336c00098337fcca7b01c634e56a7874309177364e6d4c24c2ab33d6a1a09a84689ad0b5
+Y = 00c5bfcdf640c0a7573ecf4a9dc1aa75db298ddf1a679609e0669182a594b9b9a8186ee961b902d84fe998e3b380c304a0be98974514966965bfef9971f05a57c162
+Digest = 23e932281d4fb08520bb7c563808e6b9ff43e83fc59977df1ff2c00ab5a0f7b5
+R = 018051118c2d8b841c6d78e2e5068c7305039cbae1f8b5a479b9bba559ebc45d8c8ac18d1f6033713871e656fa4eba9c1c0892e7263bb22c46ec3c72aae92afe2c79
+S = 00de0db6a6ba5e6a953a126be3b87d6c895f4bc2db27be223109dc67cf115bbc8c566e1c9a1bdf1a87e632f8a0e4b31331a086caeb60793e87f03b404140aba206ae
+Invalid =
+
+Curve = P-521
+X = 00397714abcc503eaa0c18abd1fd26586d28ec1b1035d37ac710f2823911ec9afa429b41ea89cec13d5bcae9d6d7147794407e409f3b267cf4dd27e8c77e7ccf4d36
+Y = 00a3a4b749d19b84708e42b59e9faa5a99ac0f0a01121655fab87785fca38c8cd4277c8c2c9a0024ff608c3cce954596315dfe0e3b133aeab08bb5389eb2a4f1fb42
+Digest = 61bcad3941eeb4005c391745635dbca42b451c3222b6123af2cd1279f89f3b2d
+R = 019da96a866db12948e0aec7231f797061f345739d439bdaaba63e4d03e0bb52c3fea2fb593347d983f24a3afa6a77f476e6bb49a5de843b4c4755cddce97b8b909e
+S = 001bb442f428b2ca445a75ad88ed49d965d6659d748d02cebf78faa1ecc187b606f284d11d47791d585dc371c2d91848a55ca7b092f06d561efcf64e0de0814e1db4
+
+Curve = P-521
+X = 01af06b10d357fc3c807854b4be235f81d5036da4df1af6a054a03ff800c1aa2d59c2ad5c0e25ed25c002057cae4b4adb92b95c36cf422a46c8833fd8968e0f32441
+Y = 018432172be0e535a3f3a5f6d6927dfbf6a00051cc1983ba25410ee3598a60dd1f7c38526de7ee23f8e9ee973ffddff49eb3edb28adc7d094cd95b63d52ba45ecb58
+Digest = 006e84c19a348fd59fd011cfc5c189d0bbb68bdd2ad30448e13ce2e01f2cdde0
+R = 01396b4f044919d0ba5ad43004cd37b8bb0626ea5549d57c532339358ee1794988a7c9eab91a9340dc2aa0f18e89b236a6c20d03a6e98f35c011430fc4213cd65dbd
+S = 0101e5a788a867d9b5a4444554c9651173f9f8e15c0f39f9adb66c18ef8075243f23b95d5229ccf5f56b87f5c50920b01b22ab7476ecf4c865a3d6d8f2242d422d8d
+Invalid =
+
+Curve = P-521
+X = 0176f1276918fed24a098d6d03077f3c33ae543316df1b6b06ce877e74b69b2cd4131fdf797e77e5f6391b0b32411120d03c0c59ba1721a7187d18708121d6f3a86f
+Y = 010f9d38b30a2da1a745840de7c9994578e32bb10f9334b46f533b6eab550aa55048e4ac601889564ac8314e01b61613fc7b8e2bd3f1a188c5c5e869af16a8d61d9b
+Digest = c11b8b03fcd4f2ae25f60af2ec2ccc9afcbf760f61782fad21a02d69b1024cdb
+R = 019cb5639a321e95214c90a612d29c9ffd5ae5aaa2a814ee2d66ac1ce1d2ab3229009129ec9d472061444cbfbf50c7e4cba09aab65299a42740bce7af3fddf2a1f46
+S = 00082ce6bf1d809d3bb4f9f09a95590bb64b0c41bcee5fcdd332947a9b59618da5da897fff44968d92635e7833dec1e91d8d99bd8b527609393b446c83d109a32243
+
+Curve = P-521
+X = 0089565cf5838658fd36b70cf5246cbe999a394562c46e9d8057928e0aa9e04ade6002cfb83f315e06790e58ea833b3bd64fba8e93c5fdba8319c5d38be7cf25a21a
+Y = 008faeff531e683d28d817045a03b2dd22e50e6168f1e5fda5b5abc71859effc5e5c45b88705b62ca090e3362a8313dc472ec2ed970bbb5029200318e7582643d613
+Digest = ae3204e3df3b8aa0265cfeec6b0facd4b3025af6af26fab931ee5f2188fb4864
+R = 006b5237ad17da6037aef116532b3aaa70172d0ca0eebdc478c35e6f8bd0f9a6472d052c5a18a23dcced7be6e5e7b6d0bcb5b3cea707000e7d114b6f41084d6f5620
+S = 005e2556425b35e6495b137f7dab522c7e7b812004c87a002f6ce4f4b6cc5f967b8f5b7d3786a17d5f717d3ac467b73e176e90cdd8c5151a6e62fc4604cbeab7e717
+Invalid =
+
+Curve = P-521
+X = 00aa42473f80d9d81f6d41ed05c8ba35c005f90e2690f71dfdb12555b7590c7a8e95b618368c39f4e84d6cba25f522c9bdd256c60d3f8c8425ad313701225a9cc9c4
+Y = 01992b7966b925f42c91f810eb05d602b804301849ea278466a68e5b616e3a0bce110fc9250db14f9c8f5929347e1bb8727bcf8072c6aebc26958954fe96df04e139
+Digest = b7e0d79517efe3d961ca5bbdc0916bab7a32743f5150d53cd60300b3edceff49
+R = 00cbb35513420f206bd26b568712503b66e159a54e154c8d4e9c661aa954e0bf425871275fff5e8f368c8ccc77ffe6adf84ba88a84483d8ba5cc862bd408f6a192c1
+S = 002ffb4e461e3161c801ad217a0483045181013deed29eec29cca94776139ddf5fe9d7771e5ac7b637a4bf7e5276940489bd8ae36f41ef6be93cff4b96bd0e1f3e59
+
+Curve = P-521
+X = 00984cf3de2bbaf1b37ad4e9121a1294a0128d8a031ddfac7a8c5d7c9db83699de26c50012d42223d902cbd4be7e6fb611f4502ce8444d43d3eb0685aee07349d0c5
+Y = 017165e8feaada26cc599ee394dfb5de7e2201004f755ebecb92ffda0a24be55aba88ab9b3c7a575884ffa7b78b631806f54e01ef875c5819fd2d52dd6369d649615
+Digest = a0f94fba76704fb2749e4cd454312e47f7606ece0b2013748096de2ff30626c3c7c7aaa855f33908ed60fc8943101625
+R = 0036c8554602661d9d8f4bfecbb099f01e9e314136e50c6d026de2297bbaf66213ea72fce13b73bb07e6e333523f19d3910983ea5842a1b634b3e3ec8157d270b496
+S = 0129b439d3ba2d66c89c34be2a674013128dccfcef33f5d3844c4465381453c361ce80e1b52b6a611749bc70933655caa56da2c5dd6b04defcd8baeb2d9be06f3caf
+Invalid =
+
+Curve = P-521
+X = 00f976d58a015d3015a14997fa3f59ca8d762a6541861be923d6110c9e742a0a2a77d59a6a9335c67f13a626d9545b27c072349c3d20b80c35b0a9490f3e6c5c1b3c
+Y = 00425c22ac0755c58fe3497c1f1a9f537d5e26127d9b031359c2378fd4b13f83691a854444eac3fa346bb5a63bb9567c122945ce99d2aeb0bb1b956ad348f7c9c461
+Digest = dd84b1706091da5e5e27099894e439027b9f45c56e0f31ea0cc528dd587f13a45b9dc87aeb90bb2003e16f56c60b8ad8
+R = 01ca7346a2efe39e03e627ee9480a9b7c925a6677dc80932ffd67ca52b7e46acd2063402545d678d218ac579a64cf1fa4eff4f32f92d3fa4510eea22472dbd3daa72
+S = 00893d86a6502d5973f6c766413e7c7ecbc4583577c58672ef36a76c83755a0ab65af0e0af0ad0f3e6cb8f9ef67669132ce7e996d6122cbbe1dec710a7ba9c9d1ff9
+Invalid =
+
+Curve = P-521
+X = 0066ad5c073425bbbe3a1d97ce6e1a9f2c298392c5afb95c60eee1393f7cd5c9a12c283258b1a53f2ed4abd13ba1287f3a1b051a09cb0f337cb6cf616dffd16aacc2
+Y = 009d2b2afc181bd82043b13b8222cd206b9264d73b229c71d9abcf74a478a7f7088bc8c7bb1e54882fee693340a3cf1aa56ccc2fb81d2675b19bba754dae0c2f00c3
+Digest = 89990b6ae2d21961eba4f7c9efd2e910ecf1c7809e1171d219236f2a8a38bceaefb553bbef7083114af5ea891fe44e89
+R = 004e6f08380c43f225169acb0e9f3ff61cdd2e9b713d149f63b5b6a4510d381409648fc1d442fa1bbbce2a8fe1ff7d1de0597f72d7681c79d3a876db6d3ef89ed192
+S = 011745ab4dec3542cbf37d10090d6038bd1ef9cce8216a4069b21e4a08075e7e8502ec97b99d3b18fd314d6ab6826bbbfaa2343ada1abc7c3b551c0b854dc45ffa75
+Invalid =
+
+Curve = P-521
+X = 0068801cdbb1e07f4b72218c52aa24bda872f1b2ab4e0c13b686cb8b10096ff88018e82196769359227192752a1c4c884f08cfa7f947ac428651f528bd41d1034073
+Y = 01aeb335cb89ecae3cbc05681e2170870dcf40d486db4011c4d7bd84c58c6b3204161d9ca3516760b0c42466605077c96c0540939c635bf5d7d11e1407b6da30c094
+Digest = ad6637c97ce73a8476c08eab09a8e98f42ae6253517f9abed3b3527942075dac7132122d96978a68324ca4dc11193d47
+R = 01ce67a3509d59f8a0f171b86559f1d84589ff2693ff7d3ad3ae64b0e5af85db2fd99bfd7eda6e8f984a87f16767231cbd9026bed0a9a49d74ea5047201227c98f41
+S = 0032b0e4c043df8e81ff22c9bead36f704c992ec160d6be7764640200e1307002421b5d73154eccde012b463aeefd11138c5b9b705623c2c849736da23c122df06f9
+
+Curve = P-521
+X = 001dd34056fd2ff3009bca2d0bbfa70ea0fb678597d41dc545358263ce2cef9a2efc016622c12099c2a50257609d6a14f3c5ffac8a52661e4a34689a3aebdbe86163
+Y = 017926740659acf72f7c7a147a3a320d501efadef8519bb289ebc33e348d6b9efd65fa516048101678548898619d311b8ef2a0d4a6f59f86810e9e6534176a24faf9
+Digest = 1cd3273e0dd337d53131614aaab0b6ffaba8d4c17863a1ddf1e7cf4965bc548628e7230f7331e1ae72b1ed9d1d2f8ae8
+R = 019043db42f44b957784a0e1f09d2e0a0dd548b865947f93b516f249ef1757402544ce5dc402cf8c1f180e9a3be01657258a1dfc14b25ef564805651763d6f609d43
+S = 01e0b45e00bde9c4e8dfe094f9bcd7af5a19b631db850a69bf0b6291fd3df6e26f4c712e3b5d4b7b8572f637874057d5652fa2bcd1977065a695d26a80669a23f0e9
+Invalid =
+
+Curve = P-521
+X = 016e5b4f4ff81c1b1e7956103c5cde951c56b37259fb8bf735b386e4d8b3d44063ef062d6e179f618a506ec8ad9773cfe99044748e2c8ae229a51bca6262aaefe2f5
+Y = 000069bfdb9123885d8ce4ce67c63311055aa9a1a5150197717a853d0549bd17d2683e427fc90a0b78af5dc96465ea3f2862cf98e8f3ee2a07089e8837aa8d09d97f
+Digest = 9949e2a22eee8ae6aa35dae08f3c81a11e0e2c546ccc11428133c65c43d36686c40b17bfb6ecdb47f3279c01defec943
+R = 011550cb365daec01901b5a5cabe7930c10d79128c5e510d58b7593c88647eee811e6fa736b26351558cbe7f17d7c882bfd1ffa72ca3bf4bc1cf1c05f31f5e8bc057
+S = 00d6fc97ad14639a5157c92b39cfd1315d7e940a454f1289c8e95c8cbbce8731ad37180554e7a91565d86cffb3f5caf4ef883184d717e03eb776af714a32234e3f5f
+Invalid =
+
+Curve = P-521
+X = 00202896ccf6710cf780bef8908a2783b3c8d5b8356f1546a1b6b909b0d65ffd7999a16112d8d68c837597656e520a56c2f6578e322df6dd794d2c08bc5d8f9f4c37
+Y = 00576152d30218c941e83080a502cdfbf9de7ca2c394969e779b76c359ffcb84902ff89e37125dea7dcdea0ba928ce2305c619b1906955e6be5ce40d087c5245eb45
+Digest = 90de70a32a54280bcf6acec4f4d2ff996855de0a224f538e2002106c06b695c8d9d143cfe0c90a1679a2fca7a15bf3ed
+R = 00bc6a7f5d77cb6ebb36a261e80d739f42b67ddc7a6496acc0ba7804d14b4850cf3fe4d8b56cdd8c019ef9f0d33aa26746018fbb4c69f4587b6da1adcf2feee2b438
+S = 00f09c6a94a8550a2781e70b4542096407fc07617f537cd27f1a1ddd15c599d5a9e3fa41da57094456277b44b89d40b26f2cc054fbe657788fa9d71659008d0d698c
+
+Curve = P-521
+X = 006ee95783b768c895e2af569bb84b0b1b00c8b72eec022df255892527987ffecdd81bd8afe267408a8912cce80982bad79c30610571a37d2a0e027e73ad23923b8d
+Y = 01ca3f60a37b18bd8b08529da1e39f93d518ae3feead5d00e07150d80d641b20e887c62e8e910ca1c2f64cdcfa678c89b2e3012e3d9b96088ae31dd660dfe6369cb6
+Digest = 8a27d78796a750bf11f75bbed9fa9807633adb4d907125004f69d29b881ec79d14feac2f0e0ed5f113932563eb38c63f
+R = 006823e8f6514e42e79d50a112f0f320ecd53963729038ef0d66d5fb59e1c664fda493027678a02b139fcf290657fffd7a529f4f38ac73542f316e1b0b25b3b88cfd
+S = 01b3bf9e54b0f48bfcc7289d187e831d94d165949db3c660cb63106be1b933e10614e3673bb8078bd8b80ba052c63d566899e618ea31e2a37e0c9c10da111ad11560
+Invalid =
+
+Curve = P-521
+X = 01ba73e2af308df78d4f2a9e552c3b9fd35d35bf20126fdf751d8ad9917cc58d734fb9de27553cd07c02eabc077f16ad4532871a8aeb59bbec82e46ef1581e4abac0
+Y = 00cf888c75582fb50bd0de724a9f4834ea127a1eea437b9a05935d1ec06815bace3464c230314b7f796423ba9fa983b2e6d1eb0260a32cf2f163a5ff46a9623ff149
+Digest = c9a34291213a5edc7474aee794f9de901be35159890bb660f9596efaf8ae7b02118457dfc3d8d2649cfd0bf5c7eea0eb
+R = 01df7e724658f1666aee8d5d75609e3f5215228ac32b978ea53434b7d154dd4edf661c688083d0937e43836c3611526c75f6f26b08f7844a95113ea4a6f1ab824a0b
+S = 019d40a7e03bd69ca568f70a066a4a57c0e6ab82dc8c2c8aa52b00c3ee4c327a87eeb7d837b0c4de68e25f7ac7cf6c0d8bbe0393b98dd61ac4961c7f8c70b40082e0
+Invalid =
+
+Curve = P-521
+X = 01419bc65174998ac21026f81e6807d8b42f0477396e7ff8a330e17c1d84bdc9b39b2a310767b46c41711f3f2fe503504350c86bf3d2b39473b64822ee32dec526e4
+Y = 0184c968f6ad79bf0da00520e5339751cd9c50e41e7cd21ef37756bd0e36e23a8071e5f0240988b73acb3bb2b6002002e09bc7ef70ffcfc7cf42d6b7c65110f54ae0
+Digest = c1c0b91842d461d466e94b411c673069d3737c898435972eda2f6ba1118ce9db013d57d3970b137071446a1fa2477930
+R = 00d785b38c5283466f796988242aba08398ed2493aaabf959ed0e8b7b915cbb711d7694f94206db74641a518642d43c843ea7f43b8354a956a3695764021cc5d2774
+S = 012c20c6ab988ae911c7cdea0549de2e40e3e68c47cfe58fb777ebc204641bbb44f2c8b6a0196d330ea2ffa1d8cdc1dd9be353f1c657e43f7fe3c094898a569c45b6
+Invalid =
+
+Curve = P-521
+X = 010f3bb1c96a753d278ddf6435e7a79a53bc2855d26d9f8d5c1337b0fd7d70bccf204377a02a1cbe95cb63e21a9e8a3ce8ee7c8d4ade16ff4083dcacbc6c4b2a350e
+Y = 01f98a0273c48fa78a91c0f8c1a43f59c7bccb74780fa38b08989d334f2ba0353a3619e6d4a1072e4e052720ed10e4f2c07e12d0c81a062fe912708dc51d4cdba97c
+Digest = 38688d539ee5c3792c29a505d8f8c01ad86efeb2fa3292e49cb921a76eca20dc536ae3feddf2e473dbe798926eb73fa9
+R = 014c4b9e23f51df21b4e02ed7611a8530466d1ed799b50b34b5fcac3bd1d63fa345925122414119cca76d22c167c18ad0fa8e1b47b53ab0f201bd4ca7ea25e011965
+S = 00ce91a050938119f80b5f584a9d9515c998212f6e122780f1607cebdb9b538dceb2d4039ab5e1b13736f4166e73d86c720516f20ad8f24e4b9fadd459c2988534ed
+Invalid =
+
+Curve = P-521
+X = 00819178ace7bf1e6e942fd6ed69193386f6c90cf65b42e9204d34ec96a0ce8fb92552ca57a7ba658422dc8b53bee150170362e6e74bdda24fb458271602aaa9b832
+Y = 014af772624921f61b3d1275591ec2d68702fbf348382e9e552a9b6c110eebf6e93f20c8bff287d504fa08ae3628e611fc1262736916fa9edd87db1c78ed2426cab2
+Digest = dda4a591219b9762f682a9c9a626f172b9cb78ce191cf8acacf137ebbd3e28857e768a9e4f2407c990b192f07c5cf5ed
+R = 012c45d6ac0b5dbd9647211f770c3cca4411666aa39b6988a968bab345129237597b6c9b3bd788c5f9f39a38463a8afb159ad72f19e7e33e7f9ce8d67d611c3d9b46
+S = 01684000b3d7381aded85b18576832c4a89b4faeea0515454677e29e3f072097e786fef11f72f229b63defa1c2fd3c07090b34f9147647035854cf2950c12a8b16d8
+Invalid =
+
+Curve = P-521
+X = 011f8e50ed6905b029ce4b16c8acb8ed9136b1c5adf6f11bfb5f3dd8bb1e208ca8329a0aff9bf286e3be90e4d61d5147bcaf2293f934862cca6aead51d6e0a083093
+Y = 01963e84a2f06a9cb273a424ee5fa1ae5900fef348371cc91c99323f58bbcd8742a4495a4f7ef52677501a4d5d663658c1f6c8f6edef8b7880e6894ff9e52bb617da
+Digest = c55e6d3091b6eb8f48794749ae0c7e9394ca3cb7b083ad65177f8f8db938a76ed6d3c1286a3d51b333c74d1c0f8032b7
+R = 012fc3e0c18c4edbcda4f82b5136c893a6307c3f60affa15d0d99fc0e4a3576b7daefa363b3a362014d14f631c35619f6861bdff9a7b503825bf9f027fcb9a31fd8a
+S = 01a138d6b02fd2a7ba45f7f952b2f329ba6a8e25697379330dddd91d1d6e865d3df1541bc4717d3e09b10a57cf38dcef587ac31b4a8abedef43e4f6cdf6ec3f49eea
+Invalid =
+
+Curve = P-521
+X = 01efc81c1efc7a9bc36ed49a5ef6fa1ba641360fa5c0f96cc1e4a3f4d973c95e86935d979fc2101370777637ab210a56fc4173a50a758725d60e9f925f2066d2bc00
+Y = 0108225fc94ab33c74aff785dcc68c45cfc3cbbdfa3481fd2a3f97308be671fb32fc8d268c129d97f140210def188dceecc9d712ac397793dbc39c5cac332671ec54
+Digest = 5fe56235e4684bd7419e321db508565d30cd351086ef67d943aa5b932f93efdce875be295920ce5210b7d3f092f401e6
+R = 00480c48a24e7a7ef832547d107769254fcdb4e7982d0e6abd16822837fd4f3b66d81e1d4a018606881abebd220ed8ca865d7e00499ac9651a98c65502baebf34a98
+S = 00ccd22d1b44a1701c99f662535aea9abff7e27f73628101f42708737db8b07effdc2b0b05d4ef233c5910b6261ae9d9c540115f27d2af766c0494c33d31bd56b3db
+Invalid =
+
+Curve = P-521
+X = 00a15c8040f94235b8b444f7a74ca293ed1b718449911eefbdb74332687850a644395394c690aa98e8064f6eca600fc3f659208c0f8a21a1e7113bed0c6e00e3176e
+Y = 004bebea7037b731d175043dec3630b2ee85c680a81256921a89407c14507c10ac043deb5d474602211ad58cb569a8b805686bdac3ef7ff62a4d25b27200706b603d
+Digest = d27a626bc9154bfc85b03724329b8a06454d5dc005997bd565f64a80134c865e73a2e123d2b433927efcbdfa3eafa827
+R = 00c1a70919025aceb29dbabdfc2a43715192cc60fc3d1ceababb40f91e3110b2cdd8f6e9c1bafe7415a26fa4179f8fc261b143ddb094fe61117afb13adae9db8943d
+S = 00197d7f87aea8d6ccd2178614b147b290ec780c8075f8439137803c0e9a589e415d84fa23f5f31d61c1674f87142d4ba4f8473fc92d7715c281dcf3f1ee5c2f1390
+
+Curve = P-521
+X = 012a593f568ca2571e543e00066ecd3a3272a57e1c94fe311e5df96afc1b792e5862720fc730e62052bbf3e118d3a078f0144fc00c9d8baaaa8298ff63981d09d911
+Y = 017cea5ae75a74100ee03cdf2468393eef55ddabfe8fd5718e88903eb9fd241e8cbf9c68ae16f4a1db26c6352afcb1894a9812da6d32cb862021c86cd8aa483afc26
+Digest = 7679eaaf0495725fa99c51a2dd0c35c8882b840e1c2340ba793013b1e2567471cba35c0dd6247cc2c2ca14f6556912a5687023fb2f0ee02114393bed4c598742
+R = 01aac7692baf3aa94a97907307010895efc1337cdd686f9ef2fd8404796a74701e55b03ceef41f3e6f50a0eeea11869c4789a3e8ab5b77324961d081e1a3377ccc91
+S = 0009c1e7d93d056b5a97759458d58c49134a45071854b8a6b8272f9fe7e78e1f3d8097e8a6e731f7ab4851eb26d5aa4fdadba6296dc7af835fe3d1b6dba4b031d5f3
+Invalid =
+
+Curve = P-521
+X = 01d6aef44370325a8a5882f4667c21172cdc8fa41d712562883ececff53883ac8ee276124e825088c79d6c9d96323cb7b8c0b7ea44d3f0026e2538f4b62d785bb1af
+Y = 0027203959a6e944b91fe6306debe74dc5dde9831fd0ec27e8be2d0b56807d63151b15f6495b8632e919e1e6b015f5ae5f2b6fb8cf75b5f848f00cf4ee457cebed3a
+Digest = b99c410653ce928e365d3613331b5df067020e92f634696279d5cee80f1f4a82f7d976a059e318b36eb25314b56f8765a81070d0944f4c86e8407d9c3e2aa7da
+R = 004417ff74889dde6bb1820b5d13da5c81dcf9b0723ee89bb1ff0d3faa90d497685709f315b2cbe55481dee43ebb6d25b1501ae69494dd69e7bffb72f987d1573b93
+S = 00fd7aa027c665458c7ac11d54d4f32cb4a1e727b499ce27b08d3d647c636cc3222a4f0a6057732249ddc22574d7cb80c3769c3ea9de3d33db3edd8ea90cb3f8dc8a
+Invalid =
+
+Curve = P-521
+X = 0153eb2be05438e5c1effb41b413efc2843b927cbf19f0bc9cc14b693eee26394a0d8880dc946a06656bcd09871544a5f15c7a1fa68e00cdc728c7cfb9c448034867
+Y = 0143ae8eecbce8fcf6b16e6159b2970a9ceb32c17c1d878c09317311b7519ed5ece3374e7929f338ddd0ec0522d81f2fa4fa47033ef0c0872dc049bb89233eef9bc1
+Digest = 97ff5a81fc88f7ddd3bc58154ffd2695912fe50ce7c63b62bd798fb673c6aa49f54bc7301fb7bddc6edc51b7e0d0b4dec9f80851fff02a33671ad9a406bbabe5
+R = 00dd633947446d0d51a96a0173c01125858abb2bece670af922a92dedcec067136c1fa92e5fa73d7116ac9c1a42b9cb642e4ac19310b049e48c53011ffc6e7461c36
+S = 00efbdc6a414bb8d663bb5cdb7c586bccfe7589049076f98cee82cdb5d203fddb2e0ffb77954959dfa5ed0de850e42a86f5a63c5a6592e9b9b8bd1b40557b9cd0cc0
+
+Curve = P-521
+X = 01184b27a48e223891cbd1f4a0255747d078f82768157e5adcc8e78355a2ff17d8363dfa39bcdb48e2fae759ea3bd6a8909ce1b2e7c20653915b7cd7b94d8f110349
+Y = 003bd6e273ee4278743f1bb71ff7aefe1f2c52954d674c96f268f3985e69727f22adbe31e0dbe01da91e3e6d19baf8efa4dcb4d1cacd06a8efe1b617bd681839e6b9
+Digest = ee21776d7174103b7fb65f03fd5d78744d2706c6726ece81e3943cf90f60fad6d8978af6cae9bc059aee2412ef86d0600694447a10b9d21079b9ca77500634a9
+R = 004c1d88d03878f967133eb56714945d3c89c3200fad08bd2d3b930190246bf8d43e453643c94fdab9c646c5a11271c800d5df25c11927c000263e785251d62acd59
+S = 012e31766af5c605a1a67834702052e7e56bbd9e2381163a9bf16b579912a98bebabb70587da58bec621c1e779a8a21c193dda0785018fd58034f9a6ac3e297e3790
+Invalid =
+
+Curve = P-521
+X = 01d9020b8e6717254eebe619d46dd5a9dda7ba5491a7d1b6820fba888e236fafd71179200437f4d61284fb5a3dfbada66bac3e6909ccbeee03c2b93a8bebe41a73f4
+Y = 0048a5f09174fda12704acdd8ed560695dec42864b6300a030768a0be7f09d25f82d7b126125e41417a145641937807ed8d1af7a53f5bc3fc3c57427d755dcce3e25
+Digest = cc4e8efb1e9061500bd2dcc5233c2bfa3d3bd89067c26cfee4fff4a5a7c9c9b15151aec1fa91e78b67cfe3efd966ce65681dd3daf36b887d844033a473be592d
+R = 0092df2dcb457fc7578eaacc98ffd73ade07d764e9553506f3dc958cdb3f65d37665528cb2f5f8bded0db0a57e6fa73bfad1aaf94718379d1655db4f32d4c505a785
+S = 010e0c31479c2b29dc2726fe9f75b397d9e37a17619e96bc631c62e9ece71f05b199804cc803940d43ddee41171dd7787668c7db05049dd5b63e4f63562aa700ca81
+Invalid =
+
+Curve = P-521
+X = 0007067d2cf7b7619b9fcff2c898246ae0950439b8bab92d809624970eda18456cb99953ce1ae45ee5d36ef02fcd5caa4d951de8581f0c21e572caad56d6dce60da3
+Y = 01913c59007a309005f226b6a30122828d60b4d0390359e1977f88b5347dacf2056dd362648e8b1d6fc038a3bd3fde6f1140c740efa9075ab8b4a64b334c5cd43f09
+Digest = 996010910456dee59309f1631f30e3dbf7ac2da7d5d7f69223c8a18f491cb18f7e11d0ca09352b715354a071e6d392a8c1dc0751569bdfcf36c158c8b07a5ba6
+R = 012aa4a532c108aa3cfb1753f95ca626bb72bd96a423d727656d4ebdc3f406d6cc6c44d3718f9abae8a0b46be9b57f8fd3a540326b63d0d4a8a93165715920437787
+S = 001badaf38e16efd75915f4806f054d40abd2d11e402039bd48c832f66cbfd145e4dac93357d476b7e608d7b75a017374ae76eee86c505f2cc16eaa19075827ccd60
+Invalid =
+
+Curve = P-521
+X = 00365388d9589c18ae608124b4cf746ff488183a912e07d26b6e867c5defb552a5a0df5a16b6342014dd1b0b6760072bcd60045d6a9a514fc74d16047c2e8765636d
+Y = 01a5319b26fd555f2a12e557418f6aa65a3461aeaea5c0c6d8698ceaa5495eed7a7d2fed0b76e77b5be11834f36e413d5288e47231c0eb0e9007d4b042bb7a1b6014
+Digest = f8e150be2f657c8266fadc9bdb04648fc5a51f3c3f7521022aaf58d24165f8af4ad66319d8aa2dab48fe8a2f773c8d0e6c8c4f732e0fdfbae4b91918530c1f91
+R = 01d9ef377063a592cf81e27815a2c20789ff9b60f7f125e618b52d90b35abdd41cd7f437cfad337953ab0314fe8e79a2f2d27fa08597d4b28313358f714a737321fb
+S = 00f01d4f150e0a174674a6a61a58a4ba781406024f6dd1b5252e04807b8a807a4ff8d52883eaa258286e506ef4b04ca890e6f81a79ed9a0cd5ed585094fea0bc5c43
+
+Curve = P-521
+X = 00fd0cac24aeb75ca50c50a72340256b43649050e0fa155f72342877bf49c3d57ac2b51b828385ee6aea94bae38587e63390f5ef4ac5540a9e6fc6f1c1e79b524693
+Y = 0107b227bdd307efd7a8d4034f733d150c41601215e76eea2bac62ad2427dff52f75f46da3d5fe31bfaedf071d2a8bb5e3c82bf6c84ecdf89ca233c92d599d376309
+Digest = d0d8c24bc5b6f34bf35b08f25dc2d6ebcd36b565f96bee9c1b47030428f10c3ad2904de19247b29650690c08517404e8ca55f366ab176e5089a4c9c661f90eb2
+R = 01c00196aa5dcbc4c4404fa76504a5eacbc96aa66c3ba531a3a679f3fb675ce58f863e08b0d2bdeae74d96ad93a39a78ed4bb3749e26567d0ca5c48a71079925b617
+S = 00f1188eba4f0943f4003ddad6a54606c13af26014db2eb8e60534fad3dae8f07c021cea0990987f1e02dce03fe53360472c3dee3c305bb3ef4b0b53ea6625bf152a
+Invalid =
+
+Curve = P-521
+X = 0104a96beea09d88ea6789a9925880c8a9ece8d764be931675640c1bf847ac8e7a8b14f408ba6722c2bf6295db9132d6ad2fe287fa6e6855f7c58ed238148a896944
+Y = 01b5e8e643fae552261427ea7d521f380adf605579462315c75e9203203ebdc9ee33dd7ba885b6cccccbd2327462988223c4b31485311c935a341ee87ba1ee820ce0
+Digest = e9ea3c8aeae3133be537da09b98c096b9a9eb287a02b3542efd30f0026ea9cb3f242b842b2cedbf02e70b44ff8a0b1bcf6f31956eaf6c0dd9a023bea36440068
+R = 00ba2c57827baae684d2c637590275c782a6db263a5358c8e1a08b5460ca3cf0f5ff8d4119a6b0d55fc68a75c793098e0a5622a0b4e2fcb0f17943440138d751797b
+S = 01594beb73b2ebb7c573ff07b5c43e722dc05979df0eef53587e9fe06a920f61d2efcc7671e6cb875df4e4d92cd4d37cc3eadcb9b6aee8f2097790ce24d6dcda8706
+Invalid =
+
+Curve = P-521
+X = 010d587aa82a4d8e690672c00e3fd71826d892862d14dc4fbad4935aaab86924dc7ee6f7fd3e2bbe86a8652589448494dab83d363d1d623cbae59f6c2670706a0576
+Y = 01a9734c99b6ff21267050738937c30971d0f6fe07e29794748a5017ea1036c975c9a52e6d3739ca0e8d70e784529cc1a7437aac5d75c69121b69020a95356137f1d
+Digest = 8814a9dbef9e6d9b8322bdf8d471b207388bb7bf831d9fba8ad29da52d528d5d5108c01e4459f5ca13e26bf5da3c848195558828d7a00f53abb9fce47ef35091
+R = 0188dcb840dfc573a97117009226d58dbb930ba8ec848931786abc770611f3519c8ba73cceb5b489170805bcf04974672fe66c908ba379aca99fa67fec81a994c2d1
+S = 000b1a185512dc6a65e454ea2bdb8049ef8f012a53ae87b759fb5d9edba51ea32e254e80545a99eb4b7c58af96b7c433535fa3f009cc644b1c97666d88355af9fc19
+
+Curve = P-521
+X = 0182c957a62e2e27aa28acee2e2f7b1ed6aef81c68001d2648da47d2b621e8b8bd18d991cd1e3fb9afb84f639fbed1050584428cd2a1d50f877532ffdefdd4e6f7ba
+Y = 005fadeef58cc0d79362b599e94636f9c70e3e5580c085b7ea52a5fd24fe4a892120b8f28ba53ec249c42d6d3b36268b8ca8464e54b72d37327d7504d9b7ce534d95
+Digest = e1838cf6ab5daf5ed28dc1b3365eb03466e01cc30f6fec9756c966cc7b89ef5ddb32754302a33b5aa309c871f98de082a21cf734ba8a368794d89b0cde1cfcf7
+R = 01e3a78e973fef6b6de8a0356401e89f435ae5f49c0173f073c4dbb9c91463e420f5265eade8305f11d30fa8d97e5b4c5ab33975f73385aea81fbdde2f7ddf7fdf16
+S = 00efeca10b5362e05a8f2e3df6661d0d536b32ca1e0a62515df2d94eb314aadb5eb40468483e24b16efe85c503d6c231ef860aabe674b72ed1ddd93853338e5e4e50
+Invalid =
+
+Curve = P-521
+X = 009911b41f9af525c874e05bfdf050331bf830296911bcb18eec16275027d63fa106c8989b07921c7e58b02711b5b5880cc4e6d9174e0d31060548cf643bf7ed4f0c
+Y = 0184fc0fac3c2c80c69c1c0293f4e5e22fa08c267b1f36ac5ad6dfdf4da1754f7942f48cb56f56cba05e22b91508fe4db3703066e8f697aca56f974f3fe530c9640c
+Digest = 365868aac67d82cc0510bcfb012f9035f99b5841329344f1b45f0489463cfe22c2f3641f7d6c59a3703aa2804323db8fec4fb3804f521149e5f7d38c9e1e94f2
+R = 017b8a22fd8f73112310867909f234fad6aa82999c28ea5a2e74b4b4bc79b2f89008b4d361ef7e797c7656f7d9317eff3e5a4982799b8cc0db82618bd2aa3959f617
+S = 01edacc6d1c0004b2090d2025d615de1fd53a96e826a3930c7cafaf3c87f34b2583997534cfa127485600a7ae04e6af4a2e98c77fd04507195e520e80014aa982a3c
+Invalid =
+
+Curve = P-521
+X = 006da3b694e3123ef96b3fd2ab964f85a36110590720dc1724a5d50d3050498957211c6a1535032cf1f31240bfab967cc0cf3b442c35a1bfa3e72470df1863d2593a
+Y = 017d0a5dc460c85d0365c7bdc2e9300e276b8aa97368af9972744f4422442afc601ecfe7903a33b0354c901c7b61f29d2d3c5610192cd188291c5651754b385b87a8
+Digest = 4e992e9e5403eb9822958f2737b70fa8096474a845a0f37244af744a6009e3b6e6e008faa7192fc01755bb785e03e4e3d2caef03eeadfe32a7fbc7e3bda49f5e
+R = 01f9cb1f4e2e65282a929acd8b685ab34da176f5c73bcb374fd1b09bc995385ce3902d6c5496b02916fd5a28f6f8bb662828a76aa0ad14b01bc24a63b328c7bb949b
+S = 001d6b3a2f34e3b7bf63d06b11ace172ca61ac5a911a4b408d766eb586c9ab820d42f555e546d892643e12a6752465427c213e3839e4f8cb3a7e4fd83642843e8544
+Invalid =
+
+Curve = P-521
+X = 00b7e03f0d623a0998add5360dfb0bfe836fcb0a46b0d6f697ba6b3766bd8698ac8c7af62f50511c6aa5e613f4a99fa28f70b220ba1cddb22482be74c969953ae6e5
+Y = 00d4ee40ee4441dc85356760f87ba32e2e7c269a2e53a2e8425d5ff02f5e4fe8d65cefe20e162c3915d2eb9ad1354bd28595a86dbdc94a5d40c5b44b1e3aa3965455
+Digest = 8ebb37c7b60ba4622070391864a70b5e797dc2464151304b1d9614b77f0bcb92fce230f42cf98f9b2612f481c21f70564f5cbfc4e81e48e08ae27b466f717e02
+R = 01fcba4781de6506f7c3f26521f0e036b5225f651e69e115d6784b2176a666edf69d759627468400a73a136f599fb8db4643fcc16bdeeef6384a1875e1c81c36b962
+S = 00a21cfaa7e1ee0eff7efc3d7e936378500283b00687363070974483ad474c58c6b55b77f678d78e7cb44d9745f79394659bdd26b72663608384b5ae9cac1c888d13
+Invalid =
+
+Curve = P-521
+X = 001bb7c623fde41beec7ddfb96f65848c2f52b50b39576bf06de6ccf157b8ec49889528728480928236300447da7171f58c8f0e0ba8fd3e2cf378b88619aa6c1e0bc
+Y = 01f8b20a1a7df319bf78c2cee03581a1ffe8ca5107fbfd40760fbd5ef5247e2df1092d5caf504a9ee653ded2995f0cdd841d6af29c9f720770056ebbc128705f68e6
+Digest = c18be2e3f935561d1ad1cacf6ae06e733a463c7e5063cbb0cfaf162a579522786755dff879d2bb0b63d4eea9120a2ed648d601a5cb2dee936dbada679bcc134b
+R = 0000db4c31f316912295c5b9506aabc24b0b2dc2b2358e6b023148889d9200bcf44762e88575e359b4868b2d93ba7bdb24800b09fc22eade0744b9832b71ee784e9c
+S = 018c84437fac7cd82099a2a4230084ac27ec7ea9c92e1c9d9a71290df9b37dc881f9ba59ed331c22dca4b2cbb837cd916e0a78398d2b7aaf8e88f113a942beac48c0
+Invalid =
diff --git a/src/crypto/engine/engine.c b/src/crypto/engine/engine.c
index 25ea98d..141ed23 100644
--- a/src/crypto/engine/engine.c
+++ b/src/crypto/engine/engine.c
@@ -23,6 +23,8 @@
 #include <openssl/rsa.h>
 #include <openssl/thread.h>
 
+#include "../internal.h"
+
 
 struct engine_st {
   RSA_METHOD *rsa_method;
@@ -35,7 +37,7 @@
     return NULL;
   }
 
-  memset(engine, 0, sizeof(ENGINE));
+  OPENSSL_memset(engine, 0, sizeof(ENGINE));
   return engine;
 }
 
@@ -93,4 +95,4 @@
   assert(method->is_static);
 }
 
-OPENSSL_DECLARE_ERROR_REASON(ENGINE, OPERATION_NOT_SUPPORTED);
+OPENSSL_DECLARE_ERROR_REASON(ENGINE, OPERATION_NOT_SUPPORTED)
diff --git a/src/crypto/err/CMakeLists.txt b/src/crypto/err/CMakeLists.txt
index a095b54..579a35b 100644
--- a/src/crypto/err/CMakeLists.txt
+++ b/src/crypto/err/CMakeLists.txt
@@ -37,14 +37,3 @@
   err.c
   err_data.c
 )
-
-add_executable(
-  err_test
-
-  err_test.cc
-
-  $<TARGET_OBJECTS:test_support>
-)
-
-target_link_libraries(err_test crypto)
-add_dependencies(all_tests err_test)
diff --git a/src/crypto/err/asn1.errordata b/src/crypto/err/asn1.errordata
index b1b0437..c304b2c 100644
--- a/src/crypto/err/asn1.errordata
+++ b/src/crypto/err/asn1.errordata
@@ -6,82 +6,87 @@
 ASN1,105,BN_LIB
 ASN1,106,BOOLEAN_IS_WRONG_LENGTH
 ASN1,107,BUFFER_TOO_SMALL
-ASN1,108,DECODE_ERROR
-ASN1,109,DEPTH_EXCEEDED
-ASN1,110,ENCODE_ERROR
-ASN1,111,ERROR_GETTING_TIME
-ASN1,112,EXPECTING_AN_ASN1_SEQUENCE
-ASN1,113,EXPECTING_AN_INTEGER
-ASN1,114,EXPECTING_AN_OBJECT
-ASN1,115,EXPECTING_A_BOOLEAN
-ASN1,116,EXPECTING_A_TIME
-ASN1,117,EXPLICIT_LENGTH_MISMATCH
-ASN1,118,EXPLICIT_TAG_NOT_CONSTRUCTED
-ASN1,119,FIELD_MISSING
-ASN1,120,FIRST_NUM_TOO_LARGE
-ASN1,121,HEADER_TOO_LONG
-ASN1,122,ILLEGAL_BITSTRING_FORMAT
-ASN1,123,ILLEGAL_BOOLEAN
-ASN1,124,ILLEGAL_CHARACTERS
-ASN1,125,ILLEGAL_FORMAT
-ASN1,126,ILLEGAL_HEX
-ASN1,127,ILLEGAL_IMPLICIT_TAG
-ASN1,128,ILLEGAL_INTEGER
-ASN1,129,ILLEGAL_NESTED_TAGGING
-ASN1,130,ILLEGAL_NULL
-ASN1,131,ILLEGAL_NULL_VALUE
-ASN1,132,ILLEGAL_OBJECT
-ASN1,133,ILLEGAL_OPTIONAL_ANY
-ASN1,134,ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE
-ASN1,135,ILLEGAL_TAGGED_ANY
-ASN1,136,ILLEGAL_TIME_VALUE
-ASN1,137,INTEGER_NOT_ASCII_FORMAT
-ASN1,138,INTEGER_TOO_LARGE_FOR_LONG
-ASN1,139,INVALID_BIT_STRING_BITS_LEFT
-ASN1,140,INVALID_BMPSTRING_LENGTH
-ASN1,141,INVALID_DIGIT
-ASN1,142,INVALID_MODIFIER
-ASN1,143,INVALID_NUMBER
-ASN1,144,INVALID_OBJECT_ENCODING
-ASN1,145,INVALID_SEPARATOR
-ASN1,146,INVALID_TIME_FORMAT
-ASN1,147,INVALID_UNIVERSALSTRING_LENGTH
-ASN1,148,INVALID_UTF8STRING
-ASN1,149,LIST_ERROR
-ASN1,150,MISSING_ASN1_EOS
-ASN1,151,MISSING_EOC
-ASN1,152,MISSING_SECOND_NUMBER
-ASN1,153,MISSING_VALUE
-ASN1,154,MSTRING_NOT_UNIVERSAL
-ASN1,155,MSTRING_WRONG_TAG
-ASN1,156,NESTED_ASN1_ERROR
-ASN1,157,NESTED_ASN1_STRING
-ASN1,158,NON_HEX_CHARACTERS
-ASN1,159,NOT_ASCII_FORMAT
-ASN1,160,NOT_ENOUGH_DATA
-ASN1,161,NO_MATCHING_CHOICE_TYPE
-ASN1,162,NULL_IS_WRONG_LENGTH
-ASN1,163,OBJECT_NOT_ASCII_FORMAT
-ASN1,164,ODD_NUMBER_OF_CHARS
-ASN1,165,SECOND_NUMBER_TOO_LARGE
-ASN1,166,SEQUENCE_LENGTH_MISMATCH
-ASN1,167,SEQUENCE_NOT_CONSTRUCTED
-ASN1,168,SEQUENCE_OR_SET_NEEDS_CONFIG
-ASN1,169,SHORT_LINE
-ASN1,170,STREAMING_NOT_SUPPORTED
-ASN1,171,STRING_TOO_LONG
-ASN1,172,STRING_TOO_SHORT
-ASN1,173,TAG_VALUE_TOO_HIGH
-ASN1,174,TIME_NOT_ASCII_FORMAT
-ASN1,175,TOO_LONG
-ASN1,176,TYPE_NOT_CONSTRUCTED
-ASN1,177,TYPE_NOT_PRIMITIVE
-ASN1,178,UNEXPECTED_EOC
-ASN1,179,UNIVERSALSTRING_IS_WRONG_LENGTH
-ASN1,180,UNKNOWN_FORMAT
-ASN1,181,UNKNOWN_TAG
-ASN1,182,UNSUPPORTED_ANY_DEFINED_BY_TYPE
-ASN1,183,UNSUPPORTED_PUBLIC_KEY_TYPE
-ASN1,184,UNSUPPORTED_TYPE
-ASN1,185,WRONG_TAG
-ASN1,186,WRONG_TYPE
+ASN1,108,CONTEXT_NOT_INITIALISED
+ASN1,109,DECODE_ERROR
+ASN1,110,DEPTH_EXCEEDED
+ASN1,111,DIGEST_AND_KEY_TYPE_NOT_SUPPORTED
+ASN1,112,ENCODE_ERROR
+ASN1,113,ERROR_GETTING_TIME
+ASN1,114,EXPECTING_AN_ASN1_SEQUENCE
+ASN1,115,EXPECTING_AN_INTEGER
+ASN1,116,EXPECTING_AN_OBJECT
+ASN1,117,EXPECTING_A_BOOLEAN
+ASN1,118,EXPECTING_A_TIME
+ASN1,119,EXPLICIT_LENGTH_MISMATCH
+ASN1,120,EXPLICIT_TAG_NOT_CONSTRUCTED
+ASN1,121,FIELD_MISSING
+ASN1,122,FIRST_NUM_TOO_LARGE
+ASN1,123,HEADER_TOO_LONG
+ASN1,124,ILLEGAL_BITSTRING_FORMAT
+ASN1,125,ILLEGAL_BOOLEAN
+ASN1,126,ILLEGAL_CHARACTERS
+ASN1,127,ILLEGAL_FORMAT
+ASN1,128,ILLEGAL_HEX
+ASN1,129,ILLEGAL_IMPLICIT_TAG
+ASN1,130,ILLEGAL_INTEGER
+ASN1,131,ILLEGAL_NESTED_TAGGING
+ASN1,132,ILLEGAL_NULL
+ASN1,133,ILLEGAL_NULL_VALUE
+ASN1,134,ILLEGAL_OBJECT
+ASN1,135,ILLEGAL_OPTIONAL_ANY
+ASN1,136,ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE
+ASN1,137,ILLEGAL_TAGGED_ANY
+ASN1,138,ILLEGAL_TIME_VALUE
+ASN1,139,INTEGER_NOT_ASCII_FORMAT
+ASN1,140,INTEGER_TOO_LARGE_FOR_LONG
+ASN1,141,INVALID_BIT_STRING_BITS_LEFT
+ASN1,142,INVALID_BMPSTRING_LENGTH
+ASN1,143,INVALID_DIGIT
+ASN1,144,INVALID_MODIFIER
+ASN1,145,INVALID_NUMBER
+ASN1,146,INVALID_OBJECT_ENCODING
+ASN1,147,INVALID_SEPARATOR
+ASN1,148,INVALID_TIME_FORMAT
+ASN1,149,INVALID_UNIVERSALSTRING_LENGTH
+ASN1,150,INVALID_UTF8STRING
+ASN1,151,LIST_ERROR
+ASN1,152,MISSING_ASN1_EOS
+ASN1,153,MISSING_EOC
+ASN1,154,MISSING_SECOND_NUMBER
+ASN1,155,MISSING_VALUE
+ASN1,156,MSTRING_NOT_UNIVERSAL
+ASN1,157,MSTRING_WRONG_TAG
+ASN1,158,NESTED_ASN1_ERROR
+ASN1,159,NESTED_ASN1_STRING
+ASN1,160,NON_HEX_CHARACTERS
+ASN1,161,NOT_ASCII_FORMAT
+ASN1,162,NOT_ENOUGH_DATA
+ASN1,163,NO_MATCHING_CHOICE_TYPE
+ASN1,164,NULL_IS_WRONG_LENGTH
+ASN1,165,OBJECT_NOT_ASCII_FORMAT
+ASN1,166,ODD_NUMBER_OF_CHARS
+ASN1,167,SECOND_NUMBER_TOO_LARGE
+ASN1,168,SEQUENCE_LENGTH_MISMATCH
+ASN1,169,SEQUENCE_NOT_CONSTRUCTED
+ASN1,170,SEQUENCE_OR_SET_NEEDS_CONFIG
+ASN1,171,SHORT_LINE
+ASN1,172,STREAMING_NOT_SUPPORTED
+ASN1,173,STRING_TOO_LONG
+ASN1,174,STRING_TOO_SHORT
+ASN1,175,TAG_VALUE_TOO_HIGH
+ASN1,176,TIME_NOT_ASCII_FORMAT
+ASN1,177,TOO_LONG
+ASN1,178,TYPE_NOT_CONSTRUCTED
+ASN1,179,TYPE_NOT_PRIMITIVE
+ASN1,180,UNEXPECTED_EOC
+ASN1,181,UNIVERSALSTRING_IS_WRONG_LENGTH
+ASN1,182,UNKNOWN_FORMAT
+ASN1,183,UNKNOWN_MESSAGE_DIGEST_ALGORITHM
+ASN1,184,UNKNOWN_SIGNATURE_ALGORITHM
+ASN1,185,UNKNOWN_TAG
+ASN1,186,UNSUPPORTED_ANY_DEFINED_BY_TYPE
+ASN1,187,UNSUPPORTED_PUBLIC_KEY_TYPE
+ASN1,188,UNSUPPORTED_TYPE
+ASN1,189,WRONG_PUBLIC_KEY_TYPE
+ASN1,190,WRONG_TAG
+ASN1,191,WRONG_TYPE
diff --git a/src/crypto/err/conf.errordata b/src/crypto/err/conf.errordata
index 651fabe..e6226e4 100644
--- a/src/crypto/err/conf.errordata
+++ b/src/crypto/err/conf.errordata
@@ -3,4 +3,5 @@
 CONF,102,MISSING_EQUAL_SIGN
 CONF,103,NO_CLOSE_BRACE
 CONF,104,UNABLE_TO_CREATE_NEW_SECTION
+CONF,106,VARIABLE_EXPANSION_TOO_LONG
 CONF,105,VARIABLE_HAS_NO_VALUE
diff --git a/src/crypto/err/dh.errordata b/src/crypto/err/dh.errordata
index 571e218..9e1b87d 100644
--- a/src/crypto/err/dh.errordata
+++ b/src/crypto/err/dh.errordata
@@ -1,4 +1,6 @@
 DH,100,BAD_GENERATOR
+DH,104,DECODE_ERROR
+DH,105,ENCODE_ERROR
 DH,101,INVALID_PUBKEY
 DH,102,MODULUS_TOO_LARGE
 DH,103,NO_PRIVATE_VALUE
diff --git a/src/crypto/err/digest.errordata b/src/crypto/err/digest.errordata
index 411e778..bbcd9cd 100644
--- a/src/crypto/err/digest.errordata
+++ b/src/crypto/err/digest.errordata
@@ -1 +1,3 @@
+DIGEST,101,DECODE_ERROR
 DIGEST,100,INPUT_NOT_INITIALIZED
+DIGEST,102,UNKNOWN_HASH
diff --git a/src/crypto/err/dsa.errordata b/src/crypto/err/dsa.errordata
index 3c5764a..6f4bc13 100644
--- a/src/crypto/err/dsa.errordata
+++ b/src/crypto/err/dsa.errordata
@@ -1,4 +1,7 @@
 DSA,100,BAD_Q_VALUE
+DSA,104,BAD_VERSION
+DSA,105,DECODE_ERROR
+DSA,106,ENCODE_ERROR
 DSA,101,MISSING_PARAMETERS
 DSA,102,MODULUS_TOO_LARGE
 DSA,103,NEED_NEW_SETUP_VALUES
diff --git a/src/crypto/err/ec.errordata b/src/crypto/err/ec.errordata
index e7b4175..aada76e 100644
--- a/src/crypto/err/ec.errordata
+++ b/src/crypto/err/ec.errordata
@@ -2,10 +2,14 @@
 EC,100,BUFFER_TOO_SMALL
 EC,101,COORDINATES_OUT_OF_RANGE
 EC,102,D2I_ECPKPARAMETERS_FAILURE
+EC,128,DECODE_ERROR
 EC,103,EC_GROUP_NEW_BY_NAME_FAILURE
+EC,129,ENCODE_ERROR
 EC,104,GROUP2PKPARAMETERS_FAILURE
+EC,130,GROUP_MISMATCH
 EC,105,I2D_ECPKPARAMETERS_FAILURE
 EC,106,INCOMPATIBLE_OBJECTS
+EC,131,INVALID_COFACTOR
 EC,107,INVALID_COMPRESSED_POINT
 EC,108,INVALID_COMPRESSION_BIT
 EC,109,INVALID_ENCODING
diff --git a/src/crypto/err/err.c b/src/crypto/err/err.c
index 9221bf1..cbb1260 100644
--- a/src/crypto/err/err.c
+++ b/src/crypto/err/err.c
@@ -114,9 +114,9 @@
 #include <string.h>
 
 #if defined(OPENSSL_WINDOWS)
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <windows.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
 #endif
 
 #include <openssl/mem.h>
@@ -141,7 +141,7 @@
 /* err_clear clears the given queued error. */
 static void err_clear(struct err_error_st *error) {
   err_clear_data(error);
-  memset(error, 0, sizeof(struct err_error_st));
+  OPENSSL_memset(error, 0, sizeof(struct err_error_st));
 }
 
 /* global_next_library contains the next custom library value to return. */
@@ -175,7 +175,7 @@
     if (state == NULL) {
       return NULL;
     }
-    memset(state, 0, sizeof(ERR_STATE));
+    OPENSSL_memset(state, 0, sizeof(ERR_STATE));
     if (!CRYPTO_set_thread_local(OPENSSL_THREAD_LOCAL_ERR, state,
                                  err_state_free)) {
       return NULL;
@@ -325,7 +325,7 @@
 
   CRYPTO_STATIC_MUTEX_lock_write(&global_next_library_mutex);
   ret = global_next_library++;
-  CRYPTO_STATIC_MUTEX_unlock(&global_next_library_mutex);
+  CRYPTO_STATIC_MUTEX_unlock_write(&global_next_library_mutex);
 
   return ret;
 }
@@ -349,7 +349,7 @@
 #if !defined(NDEBUG)
   /* This is aimed to help catch callers who don't provide
    * |ERR_ERROR_STRING_BUF_LEN| bytes of space. */
-  memset(ret, 0, ERR_ERROR_STRING_BUF_LEN);
+  OPENSSL_memset(ret, 0, ERR_ERROR_STRING_BUF_LEN);
 #endif
 
   ERR_error_string_n(packed_error, ret, ERR_ERROR_STRING_BUF_LEN);
@@ -407,7 +407,7 @@
          * terminating 0). If we're setting this colon, then all whole of the
          * rest of the string must be colons in order to have the correct
          * number. */
-        memset(last_pos, ':', num_colons - i);
+        OPENSSL_memset(last_pos, ':', num_colons - i);
         break;
       }
 
@@ -675,7 +675,7 @@
       buf = new_buf;
     }
 
-    memcpy(buf + len, substr, substr_len);
+    OPENSSL_memcpy(buf + len, substr, substr_len);
     len = new_len;
   }
 
diff --git a/src/crypto/err/err_data_generate.go b/src/crypto/err/err_data_generate.go
index 24e0d66..893ebff 100644
--- a/src/crypto/err/err_data_generate.go
+++ b/src/crypto/err/err_data_generate.go
@@ -18,6 +18,7 @@
 	"bufio"
 	"bytes"
 	"errors"
+	"flag"
 	"fmt"
 	"io"
 	"os"
@@ -26,6 +27,8 @@
 	"strings"
 )
 
+var verbose = flag.Bool("verbose", false, "If true, prints a status message at the end.")
+
 // libraryNames must be kept in sync with the enum in err.h. The generated code
 // will contain static assertions to enforce this.
 var libraryNames = []string{
@@ -138,7 +141,9 @@
 
 func (st *stringList) WriteTo(out stringWriter, name string) {
 	list := st.buildList()
-	fmt.Fprintf(os.Stderr, "%s: %d bytes of list and %d bytes of string data.\n", name, 4*len(list), len(st.stringData))
+	if *verbose {
+		fmt.Fprintf(os.Stderr, "%s: %d bytes of list and %d bytes of string data.\n", name, 4*len(list), len(st.stringData))
+	}
 
 	values := "kOpenSSL" + name + "Values"
 	out.WriteString("const uint32_t " + values + "[] = {\n")
@@ -215,6 +220,8 @@
 }
 
 func main() {
+	flag.Parse()
+
 	e := &errorData{
 		reasons:    newStringList(),
 		libraryMap: make(map[string]uint32),
diff --git a/src/crypto/err/err_test.cc b/src/crypto/err/err_test.cc
index d691355..8e820b8 100644
--- a/src/crypto/err/err_test.cc
+++ b/src/crypto/err/err_test.cc
@@ -15,40 +15,34 @@
 #include <stdio.h>
 #include <string.h>
 
+#include <gtest/gtest.h>
+
 #include <openssl/crypto.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
 
-static bool TestOverflow() {
+TEST(ErrTest, Overflow) {
   for (unsigned i = 0; i < ERR_NUM_ERRORS*2; i++) {
     ERR_put_error(1, 0 /* unused */, i+1, "test", 1);
   }
 
   for (unsigned i = 0; i < ERR_NUM_ERRORS - 1; i++) {
+    SCOPED_TRACE(i);
     uint32_t err = ERR_get_error();
     /* Errors are returned in order they were pushed, with the least recent ones
      * removed, up to |ERR_NUM_ERRORS - 1| errors. So the errors returned are
      * |ERR_NUM_ERRORS + 2| through |ERR_NUM_ERRORS * 2|, inclusive. */
-    if (err == 0 || ((unsigned)ERR_GET_REASON(err)) != i + ERR_NUM_ERRORS + 2) {
-      fprintf(stderr, "ERR_get_error failed at %u\n", i);
-      return false;
-    }
+    EXPECT_NE(0u, err);
+    EXPECT_EQ(static_cast<int>(i + ERR_NUM_ERRORS + 2), ERR_GET_REASON(err));
   }
 
-  if (ERR_get_error() != 0) {
-    fprintf(stderr, "ERR_get_error more than the expected number of values.\n");
-    return false;
-  }
-
-  return true;
+  EXPECT_EQ(0u, ERR_get_error());
 }
 
-static bool TestPutError() {
-  if (ERR_get_error() != 0) {
-    fprintf(stderr, "ERR_get_error returned value before an error was added.\n");
-    return false;
-  }
+TEST(ErrTest, PutError) {
+  ASSERT_EQ(0u, ERR_get_error())
+      << "ERR_get_error returned value before an error was added.";
 
   ERR_put_error(1, 0 /* unused */, 2, "test", 4);
   ERR_add_error_data(1, "testing");
@@ -60,45 +54,31 @@
                                &peeked_flags);
   uint32_t packed_error = ERR_get_error_line_data(&file, &line, &data, &flags);
 
-  if (peeked_packed_error != packed_error ||
-      peeked_file != file ||
-      peeked_data != data ||
-      peeked_flags != flags) {
-    fprintf(stderr, "Bad peeked error data returned.\n");
-    return false;
-  }
+  EXPECT_EQ(peeked_packed_error, packed_error);
+  EXPECT_EQ(peeked_file, file);
+  EXPECT_EQ(peeked_data, data);
+  EXPECT_EQ(peeked_flags, flags);
 
-  if (strcmp(file, "test") != 0 ||
-      line != 4 ||
-      (flags & ERR_FLAG_STRING) == 0 ||
-      ERR_GET_LIB(packed_error) != 1 ||
-      ERR_GET_REASON(packed_error) != 2 ||
-      strcmp(data, "testing") != 0) {
-    fprintf(stderr, "Bad error data returned.\n");
-    return false;
-  }
-
-  return true;
+  EXPECT_STREQ("test", file);
+  EXPECT_EQ(4, line);
+  EXPECT_TRUE(flags & ERR_FLAG_STRING);
+  EXPECT_EQ(1, ERR_GET_LIB(packed_error));
+  EXPECT_EQ(2, ERR_GET_REASON(packed_error));
+  EXPECT_STREQ("testing", data);
 }
 
-static bool TestClearError() {
-  if (ERR_get_error() != 0) {
-    fprintf(stderr, "ERR_get_error returned value before an error was added.\n");
-    return false;
-  }
+TEST(ErrTest, ClearError) {
+  ASSERT_EQ(0u, ERR_get_error())
+      << "ERR_get_error returned value before an error was added.";
 
   ERR_put_error(1, 0 /* unused */, 2, "test", 4);
   ERR_clear_error();
 
-  if (ERR_get_error() != 0) {
-    fprintf(stderr, "Error remained after clearing.\n");
-    return false;
-  }
-
-  return true;
+  // The error queue should be cleared.
+  EXPECT_EQ(0u, ERR_get_error());
 }
 
-static bool TestPrint() {
+TEST(ErrTest, Print) {
   ERR_put_error(1, 0 /* unused */, 2, "test", 4);
   ERR_add_error_data(1, "testing");
   uint32_t packed_error = ERR_get_error();
@@ -107,14 +87,14 @@
   for (size_t i = 0; i <= sizeof(buf); i++) {
     ERR_error_string_n(packed_error, buf, i);
   }
-
-  return true;
 }
 
-static bool TestRelease() {
+TEST(ErrTest, Release) {
   ERR_put_error(1, 0 /* unused */, 2, "test", 4);
   ERR_remove_thread_state(NULL);
-  return true;
+
+  // The error queue should be cleared.
+  EXPECT_EQ(0u, ERR_get_error());
 }
 
 static bool HasSuffix(const char *str, const char *suffix) {
@@ -126,7 +106,7 @@
   return strcmp(str + str_len - suffix_len, suffix) == 0;
 }
 
-static bool TestPutMacro() {
+TEST(ErrTest, PutMacro) {
   int expected_line = __LINE__ + 1;
   OPENSSL_PUT_ERROR(USER, ERR_R_INTERNAL_ERROR);
 
@@ -134,29 +114,8 @@
   const char *file;
   uint32_t error = ERR_get_error_line(&file, &line);
 
-  if (!HasSuffix(file, "err_test.cc") ||
-      line != expected_line ||
-      ERR_GET_LIB(error) != ERR_LIB_USER ||
-      ERR_GET_REASON(error) != ERR_R_INTERNAL_ERROR) {
-    fprintf(stderr, "Bad error data returned.\n");
-    return false;
-  }
-
-  return true;
-}
-
-int main() {
-  CRYPTO_library_init();
-
-  if (!TestOverflow() ||
-      !TestPutError() ||
-      !TestClearError() ||
-      !TestPrint() ||
-      !TestRelease() ||
-      !TestPutMacro()) {
-    return 1;
-  }
-
-  printf("PASS\n");
-  return 0;
+  EXPECT_PRED2(HasSuffix, file, "err_test.cc");
+  EXPECT_EQ(expected_line, line);
+  EXPECT_EQ(ERR_LIB_USER, ERR_GET_LIB(error));
+  EXPECT_EQ(ERR_R_INTERNAL_ERROR, ERR_GET_REASON(error));
 }
diff --git a/src/crypto/err/evp.errordata b/src/crypto/err/evp.errordata
index 8f8dd48..a482f76 100644
--- a/src/crypto/err/evp.errordata
+++ b/src/crypto/err/evp.errordata
@@ -1,46 +1,30 @@
-EVP,151,BN_DECODE_ERROR
 EVP,100,BUFFER_TOO_SMALL
 EVP,101,COMMAND_NOT_SUPPORTED
-EVP,146,CONTEXT_NOT_INITIALISED
-EVP,143,DECODE_ERROR
-EVP,104,DIFFERENT_KEY_TYPES
-EVP,105,DIFFERENT_PARAMETERS
-EVP,147,DIGEST_AND_KEY_TYPE_NOT_SUPPORTED
-EVP,107,EXPECTING_AN_EC_KEY_KEY
-EVP,141,EXPECTING_AN_RSA_KEY
-EVP,109,EXPECTING_A_DH_KEY
-EVP,110,EXPECTING_A_DSA_KEY
-EVP,111,ILLEGAL_OR_UNSUPPORTED_PADDING_MODE
-EVP,112,INVALID_CURVE
-EVP,113,INVALID_DIGEST_LENGTH
-EVP,114,INVALID_DIGEST_TYPE
-EVP,115,INVALID_KEYBITS
-EVP,116,INVALID_MGF1_MD
-EVP,142,INVALID_OPERATION
-EVP,118,INVALID_PADDING_MODE
-EVP,119,INVALID_PSS_PARAMETERS
-EVP,144,INVALID_PSS_SALTLEN
-EVP,121,INVALID_SALT_LENGTH
-EVP,122,INVALID_TRAILER
-EVP,123,KEYS_NOT_SET
-EVP,124,MISSING_PARAMETERS
-EVP,125,NO_DEFAULT_DIGEST
-EVP,126,NO_KEY_SET
-EVP,127,NO_MDC2_SUPPORT
-EVP,128,NO_NID_FOR_CURVE
-EVP,129,NO_OPERATION_SET
-EVP,130,NO_PARAMETERS_SET
-EVP,131,OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE
-EVP,132,OPERATON_NOT_INITIALIZED
-EVP,152,PARAMETER_ENCODING_ERROR
-EVP,133,UNKNOWN_DIGEST
-EVP,134,UNKNOWN_MASK_DIGEST
-EVP,150,UNKNOWN_MESSAGE_DIGEST_ALGORITHM
-EVP,145,UNKNOWN_PUBLIC_KEY_TYPE
-EVP,149,UNKNOWN_SIGNATURE_ALGORITHM
-EVP,138,UNSUPPORTED_ALGORITHM
-EVP,139,UNSUPPORTED_MASK_ALGORITHM
-EVP,140,UNSUPPORTED_MASK_PARAMETER
-EVP,153,UNSUPPORTED_PUBLIC_KEY_TYPE
-EVP,154,UNSUPPORTED_SIGNATURE_TYPE
-EVP,148,WRONG_PUBLIC_KEY_TYPE
+EVP,102,DECODE_ERROR
+EVP,103,DIFFERENT_KEY_TYPES
+EVP,104,DIFFERENT_PARAMETERS
+EVP,105,ENCODE_ERROR
+EVP,106,EXPECTING_AN_EC_KEY_KEY
+EVP,107,EXPECTING_AN_RSA_KEY
+EVP,108,EXPECTING_A_DSA_KEY
+EVP,109,ILLEGAL_OR_UNSUPPORTED_PADDING_MODE
+EVP,110,INVALID_DIGEST_LENGTH
+EVP,111,INVALID_DIGEST_TYPE
+EVP,112,INVALID_KEYBITS
+EVP,113,INVALID_MGF1_MD
+EVP,114,INVALID_OPERATION
+EVP,115,INVALID_PADDING_MODE
+EVP,116,INVALID_PSS_SALTLEN
+EVP,117,KEYS_NOT_SET
+EVP,118,MISSING_PARAMETERS
+EVP,119,NO_DEFAULT_DIGEST
+EVP,120,NO_KEY_SET
+EVP,121,NO_MDC2_SUPPORT
+EVP,122,NO_NID_FOR_CURVE
+EVP,123,NO_OPERATION_SET
+EVP,124,NO_PARAMETERS_SET
+EVP,125,OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE
+EVP,126,OPERATON_NOT_INITIALIZED
+EVP,127,UNKNOWN_PUBLIC_KEY_TYPE
+EVP,128,UNSUPPORTED_ALGORITHM
+EVP,129,UNSUPPORTED_PUBLIC_KEY_TYPE
diff --git a/src/crypto/err/pkcs8.errordata b/src/crypto/err/pkcs8.errordata
index 0eb5083..8b51274 100644
--- a/src/crypto/err/pkcs8.errordata
+++ b/src/crypto/err/pkcs8.errordata
@@ -1,3 +1,4 @@
+PKCS8,129,BAD_ITERATION_COUNT
 PKCS8,100,BAD_PKCS12_DATA
 PKCS8,101,BAD_PKCS12_VERSION
 PKCS8,102,CIPHER_HAS_NO_OBJECT_IDENTIFIER
@@ -22,4 +23,9 @@
 PKCS8,121,UNKNOWN_CIPHER_ALGORITHM
 PKCS8,122,UNKNOWN_DIGEST
 PKCS8,123,UNKNOWN_HASH
+PKCS8,127,UNSUPPORTED_CIPHER
+PKCS8,125,UNSUPPORTED_KEYLENGTH
+PKCS8,128,UNSUPPORTED_KEY_DERIVATION_FUNCTION
+PKCS8,130,UNSUPPORTED_PRF
 PKCS8,124,UNSUPPORTED_PRIVATE_KEY_ALGORITHM
+PKCS8,126,UNSUPPORTED_SALT_TYPE
diff --git a/src/crypto/err/rsa.errordata b/src/crypto/err/rsa.errordata
index c19f73c..62d286c 100644
--- a/src/crypto/err/rsa.errordata
+++ b/src/crypto/err/rsa.errordata
@@ -1,46 +1,46 @@
-RSA,143,BAD_ENCODING
-RSA,100,BAD_E_VALUE
-RSA,101,BAD_FIXED_HEADER_DECRYPT
-RSA,102,BAD_PAD_BYTE_COUNT
-RSA,103,BAD_RSA_PARAMETERS
-RSA,104,BAD_SIGNATURE
-RSA,145,BAD_VERSION
-RSA,105,BLOCK_TYPE_IS_NOT_01
-RSA,106,BN_NOT_INITIALIZED
-RSA,142,CANNOT_RECOVER_MULTI_PRIME_KEY
-RSA,107,CRT_PARAMS_ALREADY_GIVEN
-RSA,108,CRT_VALUES_INCORRECT
-RSA,109,DATA_LEN_NOT_EQUAL_TO_MOD_LEN
-RSA,110,DATA_TOO_LARGE
-RSA,111,DATA_TOO_LARGE_FOR_KEY_SIZE
-RSA,112,DATA_TOO_LARGE_FOR_MODULUS
-RSA,113,DATA_TOO_SMALL
-RSA,114,DATA_TOO_SMALL_FOR_KEY_SIZE
-RSA,115,DIGEST_TOO_BIG_FOR_RSA_KEY
-RSA,116,D_E_NOT_CONGRUENT_TO_1
-RSA,117,EMPTY_PUBLIC_KEY
-RSA,144,ENCODE_ERROR
-RSA,118,FIRST_OCTET_INVALID
-RSA,119,INCONSISTENT_SET_OF_CRT_VALUES
-RSA,120,INTERNAL_ERROR
-RSA,121,INVALID_MESSAGE_LENGTH
-RSA,122,KEY_SIZE_TOO_SMALL
-RSA,123,LAST_OCTET_INVALID
-RSA,124,MODULUS_TOO_LARGE
-RSA,141,MUST_HAVE_AT_LEAST_TWO_PRIMES
-RSA,125,NO_PUBLIC_EXPONENT
-RSA,126,NULL_BEFORE_BLOCK_MISSING
-RSA,127,N_NOT_EQUAL_P_Q
-RSA,128,OAEP_DECODING_ERROR
-RSA,129,ONLY_ONE_OF_P_Q_GIVEN
-RSA,130,OUTPUT_BUFFER_TOO_SMALL
-RSA,131,PADDING_CHECK_FAILED
-RSA,132,PKCS_DECODING_ERROR
-RSA,133,SLEN_CHECK_FAILED
-RSA,134,SLEN_RECOVERY_FAILED
-RSA,135,TOO_LONG
-RSA,136,TOO_MANY_ITERATIONS
-RSA,137,UNKNOWN_ALGORITHM_TYPE
-RSA,138,UNKNOWN_PADDING_TYPE
-RSA,139,VALUE_MISSING
-RSA,140,WRONG_SIGNATURE_LENGTH
+RSA,100,BAD_ENCODING
+RSA,101,BAD_E_VALUE
+RSA,102,BAD_FIXED_HEADER_DECRYPT
+RSA,103,BAD_PAD_BYTE_COUNT
+RSA,104,BAD_RSA_PARAMETERS
+RSA,105,BAD_SIGNATURE
+RSA,106,BAD_VERSION
+RSA,107,BLOCK_TYPE_IS_NOT_01
+RSA,108,BN_NOT_INITIALIZED
+RSA,109,CANNOT_RECOVER_MULTI_PRIME_KEY
+RSA,110,CRT_PARAMS_ALREADY_GIVEN
+RSA,111,CRT_VALUES_INCORRECT
+RSA,112,DATA_LEN_NOT_EQUAL_TO_MOD_LEN
+RSA,113,DATA_TOO_LARGE
+RSA,114,DATA_TOO_LARGE_FOR_KEY_SIZE
+RSA,115,DATA_TOO_LARGE_FOR_MODULUS
+RSA,116,DATA_TOO_SMALL
+RSA,117,DATA_TOO_SMALL_FOR_KEY_SIZE
+RSA,118,DIGEST_TOO_BIG_FOR_RSA_KEY
+RSA,119,D_E_NOT_CONGRUENT_TO_1
+RSA,120,EMPTY_PUBLIC_KEY
+RSA,121,ENCODE_ERROR
+RSA,122,FIRST_OCTET_INVALID
+RSA,123,INCONSISTENT_SET_OF_CRT_VALUES
+RSA,124,INTERNAL_ERROR
+RSA,125,INVALID_MESSAGE_LENGTH
+RSA,126,KEY_SIZE_TOO_SMALL
+RSA,127,LAST_OCTET_INVALID
+RSA,128,MODULUS_TOO_LARGE
+RSA,129,MUST_HAVE_AT_LEAST_TWO_PRIMES
+RSA,130,NO_PUBLIC_EXPONENT
+RSA,131,NULL_BEFORE_BLOCK_MISSING
+RSA,132,N_NOT_EQUAL_P_Q
+RSA,133,OAEP_DECODING_ERROR
+RSA,134,ONLY_ONE_OF_P_Q_GIVEN
+RSA,135,OUTPUT_BUFFER_TOO_SMALL
+RSA,136,PADDING_CHECK_FAILED
+RSA,137,PKCS_DECODING_ERROR
+RSA,138,SLEN_CHECK_FAILED
+RSA,139,SLEN_RECOVERY_FAILED
+RSA,140,TOO_LONG
+RSA,141,TOO_MANY_ITERATIONS
+RSA,142,UNKNOWN_ALGORITHM_TYPE
+RSA,143,UNKNOWN_PADDING_TYPE
+RSA,144,VALUE_MISSING
+RSA,145,WRONG_SIGNATURE_LENGTH
diff --git a/src/crypto/err/ssl.errordata b/src/crypto/err/ssl.errordata
index 3766bb9..5e38b30 100644
--- a/src/crypto/err/ssl.errordata
+++ b/src/crypto/err/ssl.errordata
@@ -1,3 +1,4 @@
+SSL,277,ALPN_MISMATCH_ON_EARLY_DATA
 SSL,100,APP_DATA_IN_HANDSHAKE
 SSL,101,ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT
 SSL,102,BAD_ALERT
@@ -18,15 +19,21 @@
 SSL,117,BAD_SSL_FILETYPE
 SSL,118,BAD_WRITE_RETRY
 SSL,119,BIO_NOT_SET
+SSL,261,BLOCK_CIPHER_PAD_IS_WRONG
 SSL,120,BN_LIB
+SSL,255,BUFFERED_MESSAGES_ON_CIPHER_CHANGE
 SSL,121,BUFFER_TOO_SMALL
+SSL,275,CANNOT_HAVE_BOTH_PRIVKEY_AND_METHOD
+SSL,272,CANNOT_PARSE_LEAF_CERT
 SSL,122,CA_DN_LENGTH_MISMATCH
 SSL,123,CA_DN_TOO_LONG
 SSL,124,CCS_RECEIVED_EARLY
+SSL,274,CERTIFICATE_AND_PRIVATE_KEY_MISMATCH
 SSL,125,CERTIFICATE_VERIFY_FAILED
 SSL,126,CERT_CB_ERROR
 SSL,127,CERT_LENGTH_MISMATCH
 SSL,128,CHANNEL_ID_NOT_P256
+SSL,279,CHANNEL_ID_ON_EARLY_DATA
 SSL,129,CHANNEL_ID_SIGNATURE_INVALID
 SSL,130,CIPHER_OR_HASH_UNAVAILABLE
 SSL,131,CLIENTHELLO_PARSE_FAILED
@@ -41,7 +48,10 @@
 SSL,140,DH_PUBLIC_VALUE_LENGTH_IS_WRONG
 SSL,141,DH_P_TOO_LONG
 SSL,142,DIGEST_CHECK_FAILED
+SSL,254,DOWNGRADE_DETECTED
 SSL,143,DTLS_MESSAGE_TOO_BIG
+SSL,257,DUPLICATE_EXTENSION
+SSL,264,DUPLICATE_KEY_SHARE
 SSL,144,ECC_CERT_NOT_FOR_SIGNING
 SSL,145,EMS_STATE_INCONSISTENT
 SSL,146,ENCRYPTED_LENGTH_TOO_LONG
@@ -56,13 +66,17 @@
 SSL,155,HTTPS_PROXY_REQUEST
 SSL,156,HTTP_REQUEST
 SSL,157,INAPPROPRIATE_FALLBACK
+SSL,259,INVALID_ALPN_PROTOCOL
 SSL,158,INVALID_COMMAND
+SSL,256,INVALID_COMPRESSION_LIST
 SSL,159,INVALID_MESSAGE
+SSL,251,INVALID_OUTER_RECORD_TYPE
+SSL,269,INVALID_SCT_LIST
 SSL,160,INVALID_SSL_SESSION
 SSL,161,INVALID_TICKET_KEYS_LENGTH
 SSL,162,LENGTH_MISMATCH
-SSL,163,LIBRARY_HAS_NO_CIPHERS
 SSL,164,MISSING_EXTENSION
+SSL,258,MISSING_KEY_SHARE
 SSL,165,MISSING_RSA_CERTIFICATE
 SSL,166,MISSING_TMP_DH_KEY
 SSL,167,MISSING_TMP_ECDH_KEY
@@ -75,30 +89,38 @@
 SSL,174,NO_CERTIFICATE_SET
 SSL,175,NO_CIPHERS_AVAILABLE
 SSL,176,NO_CIPHERS_PASSED
+SSL,262,NO_CIPHERS_SPECIFIED
 SSL,177,NO_CIPHER_MATCH
+SSL,253,NO_COMMON_SIGNATURE_ALGORITHMS
 SSL,178,NO_COMPRESSION_SPECIFIED
+SSL,265,NO_GROUPS_SPECIFIED
 SSL,179,NO_METHOD_SPECIFIED
 SSL,180,NO_P256_SUPPORT
 SSL,181,NO_PRIVATE_KEY_ASSIGNED
 SSL,182,NO_RENEGOTIATION
 SSL,183,NO_REQUIRED_DIGEST
 SSL,184,NO_SHARED_CIPHER
+SSL,266,NO_SHARED_GROUP
 SSL,185,NULL_SSL_CTX
 SSL,186,NULL_SSL_METHOD_PASSED
 SSL,187,OLD_SESSION_CIPHER_NOT_RETURNED
+SSL,268,OLD_SESSION_PRF_HASH_MISMATCH
 SSL,188,OLD_SESSION_VERSION_NOT_RETURNED
 SSL,189,OUTPUT_ALIASES_INPUT
 SSL,190,PARSE_TLSEXT
 SSL,191,PATH_TOO_LONG
 SSL,192,PEER_DID_NOT_RETURN_A_CERTIFICATE
 SSL,193,PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE
+SSL,267,PRE_SHARED_KEY_MUST_BE_LAST
 SSL,194,PROTOCOL_IS_SHUTDOWN
+SSL,271,PSK_IDENTITY_BINDER_COUNT_MISMATCH
 SSL,195,PSK_IDENTITY_NOT_FOUND
 SSL,196,PSK_NO_CLIENT_CB
 SSL,197,PSK_NO_SERVER_CB
 SSL,198,READ_TIMEOUT_EXPIRED
 SSL,199,RECORD_LENGTH_MISMATCH
 SSL,200,RECORD_TOO_LARGE
+SSL,263,RENEGOTIATION_EMS_MISMATCH
 SSL,201,RENEGOTIATION_ENCODING_ERR
 SSL,202,RENEGOTIATION_MISMATCH
 SSL,203,REQUIRED_CIPHER_MISSING
@@ -106,8 +128,10 @@
 SSL,205,RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION
 SSL,206,SCSV_RECEIVED_WHEN_RENEGOTIATING
 SSL,207,SERVERHELLO_TLSEXT
+SSL,273,SERVER_CERT_CHANGED
 SSL,208,SESSION_ID_CONTEXT_UNINITIALIZED
 SSL,209,SESSION_MAY_NOT_BE_CREATED
+SSL,250,SHUTDOWN_WHILE_IN_INIT
 SSL,210,SIGNATURE_ALGORITHMS_EXTENSION_SENT_BY_SERVER
 SSL,211,SRTP_COULD_NOT_ALLOCATE_PROFILES
 SSL,212,SRTP_UNKNOWN_PROTECTION_PROFILE
@@ -127,6 +151,7 @@
 SSL,214,SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION
 SSL,215,SSL_HANDSHAKE_FAILURE
 SSL,216,SSL_SESSION_ID_CONTEXT_TOO_LONG
+SSL,276,TICKET_ENCRYPTION_FAILED
 SSL,1049,TLSV1_ALERT_ACCESS_DENIED
 SSL,1050,TLSV1_ALERT_DECODE_ERROR
 SSL,1021,TLSV1_ALERT_DECRYPTION_FAILED
@@ -142,13 +167,17 @@
 SSL,1090,TLSV1_ALERT_USER_CANCELLED
 SSL,1114,TLSV1_BAD_CERTIFICATE_HASH_VALUE
 SSL,1113,TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE
+SSL,1116,TLSV1_CERTIFICATE_REQUIRED
 SSL,1111,TLSV1_CERTIFICATE_UNOBTAINABLE
+SSL,1115,TLSV1_UNKNOWN_PSK_IDENTITY
 SSL,1112,TLSV1_UNRECOGNIZED_NAME
 SSL,1110,TLSV1_UNSUPPORTED_EXTENSION
 SSL,217,TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST
 SSL,218,TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG
 SSL,219,TOO_MANY_EMPTY_FRAGMENTS
+SSL,260,TOO_MANY_KEY_UPDATES
 SSL,220,TOO_MANY_WARNING_ALERTS
+SSL,270,TOO_MUCH_SKIPPED_EARLY_DATA
 SSL,221,UNABLE_TO_FIND_ECDH_PARAMETERS
 SSL,222,UNEXPECTED_EXTENSION
 SSL,223,UNEXPECTED_MESSAGE
@@ -169,6 +198,7 @@
 SSL,238,UNSUPPORTED_COMPRESSION_ALGORITHM
 SSL,239,UNSUPPORTED_ELLIPTIC_CURVE
 SSL,240,UNSUPPORTED_PROTOCOL
+SSL,252,UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY
 SSL,241,WRONG_CERTIFICATE_TYPE
 SSL,242,WRONG_CIPHER_RETURNED
 SSL,243,WRONG_CURVE
@@ -176,5 +206,6 @@
 SSL,245,WRONG_SIGNATURE_TYPE
 SSL,246,WRONG_SSL_VERSION
 SSL,247,WRONG_VERSION_NUMBER
+SSL,278,WRONG_VERSION_ON_EARLY_DATA
 SSL,248,X509_LIB
 SSL,249,X509_VERIFICATION_SETUP_PROBLEMS
diff --git a/src/crypto/err/x509.errordata b/src/crypto/err/x509.errordata
index f4828ce..5687c30 100644
--- a/src/crypto/err/x509.errordata
+++ b/src/crypto/err/x509.errordata
@@ -10,28 +10,27 @@
 X509,109,INVALID_BIT_STRING_BITS_LEFT
 X509,110,INVALID_DIRECTORY
 X509,111,INVALID_FIELD_NAME
-X509,112,INVALID_TRUST
-X509,113,ISSUER_MISMATCH
-X509,114,KEY_TYPE_MISMATCH
-X509,115,KEY_VALUES_MISMATCH
-X509,116,LOADING_CERT_DIR
-X509,117,LOADING_DEFAULTS
-X509,118,METHOD_NOT_SUPPORTED
+X509,112,INVALID_PSS_PARAMETERS
+X509,113,INVALID_TRUST
+X509,114,ISSUER_MISMATCH
+X509,115,KEY_TYPE_MISMATCH
+X509,116,KEY_VALUES_MISMATCH
+X509,117,LOADING_CERT_DIR
+X509,118,LOADING_DEFAULTS
+X509,135,NAME_TOO_LONG
 X509,119,NEWER_CRL_NOT_NEWER
 X509,120,NOT_PKCS7_SIGNED_DATA
 X509,121,NO_CERTIFICATES_INCLUDED
 X509,122,NO_CERT_SET_FOR_US_TO_VERIFY
-X509,136,NO_CRLS_INCLUDED
-X509,123,NO_CRL_NUMBER
-X509,124,PUBLIC_KEY_DECODE_ERROR
-X509,125,PUBLIC_KEY_ENCODE_ERROR
-X509,126,SHOULD_RETRY
-X509,127,UNABLE_TO_FIND_PARAMETERS_IN_CHAIN
-X509,128,UNABLE_TO_GET_CERTS_PUBLIC_KEY
-X509,129,UNKNOWN_KEY_TYPE
-X509,130,UNKNOWN_NID
-X509,131,UNKNOWN_PURPOSE_ID
-X509,132,UNKNOWN_TRUST_ID
-X509,133,UNSUPPORTED_ALGORITHM
-X509,134,WRONG_LOOKUP_TYPE
-X509,135,WRONG_TYPE
+X509,123,NO_CRLS_INCLUDED
+X509,124,NO_CRL_NUMBER
+X509,125,PUBLIC_KEY_DECODE_ERROR
+X509,126,PUBLIC_KEY_ENCODE_ERROR
+X509,127,SHOULD_RETRY
+X509,128,UNKNOWN_KEY_TYPE
+X509,129,UNKNOWN_NID
+X509,130,UNKNOWN_PURPOSE_ID
+X509,131,UNKNOWN_TRUST_ID
+X509,132,UNSUPPORTED_ALGORITHM
+X509,133,WRONG_LOOKUP_TYPE
+X509,134,WRONG_TYPE
diff --git a/src/crypto/evp/CMakeLists.txt b/src/crypto/evp/CMakeLists.txt
index 000f076..188c580 100644
--- a/src/crypto/evp/CMakeLists.txt
+++ b/src/crypto/evp/CMakeLists.txt
@@ -5,7 +5,6 @@
 
   OBJECT
 
-  algorithm.c
   digestsign.c
   evp.c
   evp_asn1.c
@@ -16,19 +15,12 @@
   p_rsa.c
   p_rsa_asn1.c
   pbkdf.c
+  print.c
   sign.c
 )
 
 
 add_executable(
-  evp_extra_test
-
-  evp_extra_test.cc
-
-  $<TARGET_OBJECTS:test_support>
-)
-
-add_executable(
   evp_test
 
   evp_test.cc
@@ -44,7 +36,6 @@
   $<TARGET_OBJECTS:test_support>
 )
 
-target_link_libraries(evp_extra_test crypto)
 target_link_libraries(evp_test crypto)
 target_link_libraries(pbkdf_test crypto)
-add_dependencies(all_tests evp_extra_test evp_test pbkdf_test)
+add_dependencies(all_tests evp_test pbkdf_test)
diff --git a/src/crypto/evp/evp.c b/src/crypto/evp/evp.c
index afe5c38..f083879 100644
--- a/src/crypto/evp/evp.c
+++ b/src/crypto/evp/evp.c
@@ -59,12 +59,11 @@
 #include <assert.h>
 #include <string.h>
 
-#include <openssl/bio.h>
 #include <openssl/dsa.h>
 #include <openssl/ec.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
 #include <openssl/rsa.h>
 #include <openssl/thread.h>
 
@@ -81,7 +80,7 @@
     return NULL;
   }
 
-  memset(ret, 0, sizeof(EVP_PKEY));
+  OPENSSL_memset(ret, 0, sizeof(EVP_PKEY));
   ret->type = EVP_PKEY_NONE;
   ret->references = 1;
 
@@ -109,9 +108,9 @@
   OPENSSL_free(pkey);
 }
 
-EVP_PKEY *EVP_PKEY_up_ref(EVP_PKEY *pkey) {
+int EVP_PKEY_up_ref(EVP_PKEY *pkey) {
   CRYPTO_refcount_inc(&pkey->references);
-  return pkey;
+  return 1;
 }
 
 int EVP_PKEY_is_opaque(const EVP_PKEY *pkey) {
@@ -195,11 +194,12 @@
   return pkey->type;
 }
 
-/* TODO(fork): remove the first argument. */
-const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pengine, int nid) {
+/* evp_pkey_asn1_find returns the ASN.1 method table for the given |nid|, which
+ * should be one of the |EVP_PKEY_*| values. It returns NULL if |nid| is
+ * unknown. */
+static const EVP_PKEY_ASN1_METHOD *evp_pkey_asn1_find(int nid) {
   switch (nid) {
     case EVP_PKEY_RSA:
-    case EVP_PKEY_RSA2:
       return &rsa_asn1_meth;
     case EVP_PKEY_EC:
       return &ec_asn1_meth;
@@ -211,7 +211,7 @@
 }
 
 int EVP_PKEY_type(int nid) {
-  const EVP_PKEY_ASN1_METHOD *meth = EVP_PKEY_asn1_find(NULL, nid);
+  const EVP_PKEY_ASN1_METHOD *meth = evp_pkey_asn1_find(nid);
   if (meth == NULL) {
     return NID_undef;
   }
@@ -302,6 +302,8 @@
   return ec_key;
 }
 
+DH *EVP_PKEY_get0_DH(EVP_PKEY *pkey) { return NULL; }
+
 int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key) {
   if (!EVP_PKEY_set_type(pkey, type)) {
     return 0;
@@ -310,19 +312,6 @@
   return key != NULL;
 }
 
-const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pengine,
-                                                   const char *name,
-                                                   size_t len) {
-  if (len == 3 && memcmp(name, "RSA", 3) == 0) {
-    return &rsa_asn1_meth;
-  } if (len == 2 && memcmp(name, "EC", 2) == 0) {
-    return &ec_asn1_meth;
-  } else if (len == 3 && memcmp(name, "DSA", 3) == 0) {
-    return &dsa_asn1_meth;
-  }
-  return NULL;
-}
-
 int EVP_PKEY_set_type(EVP_PKEY *pkey, int type) {
   const EVP_PKEY_ASN1_METHOD *ameth;
 
@@ -330,10 +319,10 @@
     free_it(pkey);
   }
 
-  ameth = EVP_PKEY_asn1_find(NULL, type);
+  ameth = evp_pkey_asn1_find(type);
   if (ameth == NULL) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
-    ERR_add_error_dataf("algorithm %d (%s)", type, OBJ_nid2sn(type));
+    ERR_add_error_dataf("algorithm %d", type);
     return 0;
   }
 
@@ -357,41 +346,6 @@
   return -2;
 }
 
-static int print_unsupported(BIO *out, const EVP_PKEY *pkey, int indent,
-                             const char *kstr) {
-  BIO_indent(out, indent, 128);
-  BIO_printf(out, "%s algorithm \"%s\" unsupported\n", kstr,
-             OBJ_nid2ln(pkey->type));
-  return 1;
-}
-
-int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey, int indent,
-                          ASN1_PCTX *pctx) {
-  if (pkey->ameth && pkey->ameth->pub_print) {
-    return pkey->ameth->pub_print(out, pkey, indent, pctx);
-  }
-
-  return print_unsupported(out, pkey, indent, "Public Key");
-}
-
-int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey, int indent,
-                           ASN1_PCTX *pctx) {
-  if (pkey->ameth && pkey->ameth->priv_print) {
-    return pkey->ameth->priv_print(out, pkey, indent, pctx);
-  }
-
-  return print_unsupported(out, pkey, indent, "Private Key");
-}
-
-int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey, int indent,
-                          ASN1_PCTX *pctx) {
-  if (pkey->ameth && pkey->ameth->param_print) {
-    return pkey->ameth->param_print(out, pkey, indent, pctx);
-  }
-
-  return print_unsupported(out, pkey, indent, "Parameters");
-}
-
 int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) {
   return EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, EVP_PKEY_CTRL_MD, 0,
                            (void *)md);
@@ -404,6 +358,8 @@
 
 void OpenSSL_add_all_algorithms(void) {}
 
+void OPENSSL_add_all_algorithms_conf(void) {}
+
 void OpenSSL_add_all_ciphers(void) {}
 
 void OpenSSL_add_all_digests(void) {}
diff --git a/src/crypto/evp/evp_asn1.c b/src/crypto/evp/evp_asn1.c
index c57f411..6c90571 100644
--- a/src/crypto/evp/evp_asn1.c
+++ b/src/crypto/evp/evp_asn1.c
@@ -56,112 +56,270 @@
 
 #include <openssl/evp.h>
 
-#include <openssl/asn1.h>
+#include <string.h>
+
+#include <openssl/bytestring.h>
+#include <openssl/dsa.h>
+#include <openssl/ec_key.h>
 #include <openssl/err.h>
-#include <openssl/obj.h>
-#include <openssl/x509.h>
+#include <openssl/rsa.h>
 
 #include "internal.h"
+#include "../internal.h"
 
 
-EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **out, const uint8_t **inp,
-                         long len) {
-  EVP_PKEY *ret;
+static const EVP_PKEY_ASN1_METHOD *const kASN1Methods[] = {
+    &rsa_asn1_meth,
+    &ec_asn1_meth,
+    &dsa_asn1_meth,
+};
 
-  if (out == NULL || *out == NULL) {
-    ret = EVP_PKEY_new();
-    if (ret == NULL) {
-      OPENSSL_PUT_ERROR(EVP, ERR_R_EVP_LIB);
-      return NULL;
-    }
-  } else {
-    ret = *out;
+static int parse_key_type(CBS *cbs, int *out_type) {
+  CBS oid;
+  if (!CBS_get_asn1(cbs, &oid, CBS_ASN1_OBJECT)) {
+    return 0;
   }
 
-  if (!EVP_PKEY_set_type(ret, type)) {
-    OPENSSL_PUT_ERROR(EVP, EVP_R_UNKNOWN_PUBLIC_KEY_TYPE);
+  unsigned i;
+  for (i = 0; i < OPENSSL_ARRAY_SIZE(kASN1Methods); i++) {
+    const EVP_PKEY_ASN1_METHOD *method = kASN1Methods[i];
+    if (CBS_len(&oid) == method->oid_len &&
+        OPENSSL_memcmp(CBS_data(&oid), method->oid, method->oid_len) == 0) {
+      *out_type = method->pkey_id;
+      return 1;
+    }
+  }
+
+  return 0;
+}
+
+EVP_PKEY *EVP_parse_public_key(CBS *cbs) {
+  /* Parse the SubjectPublicKeyInfo. */
+  CBS spki, algorithm, key;
+  int type;
+  uint8_t padding;
+  if (!CBS_get_asn1(cbs, &spki, CBS_ASN1_SEQUENCE) ||
+      !CBS_get_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) ||
+      !parse_key_type(&algorithm, &type) ||
+      !CBS_get_asn1(&spki, &key, CBS_ASN1_BITSTRING) ||
+      CBS_len(&spki) != 0 ||
+      /* Every key type defined encodes the key as a byte string with the same
+       * conversion to BIT STRING. */
+      !CBS_get_u8(&key, &padding) ||
+      padding != 0) {
+    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
+    return NULL;
+  }
+
+  /* Set up an |EVP_PKEY| of the appropriate type. */
+  EVP_PKEY *ret = EVP_PKEY_new();
+  if (ret == NULL ||
+      !EVP_PKEY_set_type(ret, type)) {
     goto err;
   }
 
-  const uint8_t *in = *inp;
-  if (!ret->ameth->old_priv_decode ||
-      !ret->ameth->old_priv_decode(ret, &in, len)) {
-    if (ret->ameth->priv_decode) {
-      /* Reset |in| in case |old_priv_decode| advanced it on error. */
-      in = *inp;
-      PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &in, len);
-      if (!p8) {
+  /* Call into the type-specific SPKI decoding function. */
+  if (ret->ameth->pub_decode == NULL) {
+    OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
+    goto err;
+  }
+  if (!ret->ameth->pub_decode(ret, &algorithm, &key)) {
+    goto err;
+  }
+
+  return ret;
+
+err:
+  EVP_PKEY_free(ret);
+  return NULL;
+}
+
+int EVP_marshal_public_key(CBB *cbb, const EVP_PKEY *key) {
+  if (key->ameth == NULL || key->ameth->pub_encode == NULL) {
+    OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
+    return 0;
+  }
+
+  return key->ameth->pub_encode(cbb, key);
+}
+
+EVP_PKEY *EVP_parse_private_key(CBS *cbs) {
+  /* Parse the PrivateKeyInfo. */
+  CBS pkcs8, algorithm, key;
+  uint64_t version;
+  int type;
+  if (!CBS_get_asn1(cbs, &pkcs8, CBS_ASN1_SEQUENCE) ||
+      !CBS_get_asn1_uint64(&pkcs8, &version) ||
+      version != 0 ||
+      !CBS_get_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
+      !parse_key_type(&algorithm, &type) ||
+      !CBS_get_asn1(&pkcs8, &key, CBS_ASN1_OCTETSTRING)) {
+    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
+    return NULL;
+  }
+
+  /* A PrivateKeyInfo ends with a SET of Attributes which we ignore. */
+
+  /* Set up an |EVP_PKEY| of the appropriate type. */
+  EVP_PKEY *ret = EVP_PKEY_new();
+  if (ret == NULL ||
+      !EVP_PKEY_set_type(ret, type)) {
+    goto err;
+  }
+
+  /* Call into the type-specific PrivateKeyInfo decoding function. */
+  if (ret->ameth->priv_decode == NULL) {
+    OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
+    goto err;
+  }
+  if (!ret->ameth->priv_decode(ret, &algorithm, &key)) {
+    goto err;
+  }
+
+  return ret;
+
+err:
+  EVP_PKEY_free(ret);
+  return NULL;
+}
+
+int EVP_marshal_private_key(CBB *cbb, const EVP_PKEY *key) {
+  if (key->ameth == NULL || key->ameth->priv_encode == NULL) {
+    OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
+    return 0;
+  }
+
+  return key->ameth->priv_encode(cbb, key);
+}
+
+static EVP_PKEY *old_priv_decode(CBS *cbs, int type) {
+  EVP_PKEY *ret = EVP_PKEY_new();
+  if (ret == NULL) {
+    return NULL;
+  }
+
+  switch (type) {
+    case EVP_PKEY_EC: {
+      EC_KEY *ec_key = EC_KEY_parse_private_key(cbs, NULL);
+      if (ec_key == NULL || !EVP_PKEY_assign_EC_KEY(ret, ec_key)) {
+        EC_KEY_free(ec_key);
         goto err;
       }
-      EVP_PKEY_free(ret);
-      ret = EVP_PKCS82PKEY(p8);
-      PKCS8_PRIV_KEY_INFO_free(p8);
-      if (ret == NULL) {
+      return ret;
+    }
+    case EVP_PKEY_DSA: {
+      DSA *dsa = DSA_parse_private_key(cbs);
+      if (dsa == NULL || !EVP_PKEY_assign_DSA(ret, dsa)) {
+        DSA_free(dsa);
         goto err;
       }
-    } else {
-      OPENSSL_PUT_ERROR(EVP, ERR_R_ASN1_LIB);
+      return ret;
+    }
+    case EVP_PKEY_RSA: {
+      RSA *rsa = RSA_parse_private_key(cbs);
+      if (rsa == NULL || !EVP_PKEY_assign_RSA(ret, rsa)) {
+        RSA_free(rsa);
+        goto err;
+      }
+      return ret;
+    }
+    default:
+      OPENSSL_PUT_ERROR(EVP, EVP_R_UNKNOWN_PUBLIC_KEY_TYPE);
       goto err;
+  }
+
+err:
+  EVP_PKEY_free(ret);
+  return NULL;
+}
+
+EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **out, const uint8_t **inp,
+                         long len) {
+  if (len < 0) {
+    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
+    return NULL;
+  }
+
+  /* Parse with the legacy format. */
+  CBS cbs;
+  CBS_init(&cbs, *inp, (size_t)len);
+  EVP_PKEY *ret = old_priv_decode(&cbs, type);
+  if (ret == NULL) {
+    /* Try again with PKCS#8. */
+    ERR_clear_error();
+    CBS_init(&cbs, *inp, (size_t)len);
+    ret = EVP_parse_private_key(&cbs);
+    if (ret == NULL) {
+      return NULL;
+    }
+    if (ret->type != type) {
+      OPENSSL_PUT_ERROR(EVP, EVP_R_DIFFERENT_KEY_TYPES);
+      EVP_PKEY_free(ret);
+      return NULL;
     }
   }
 
   if (out != NULL) {
+    EVP_PKEY_free(*out);
     *out = ret;
   }
-  *inp = in;
+  *inp = CBS_data(&cbs);
   return ret;
+}
 
-err:
-  if (out == NULL || *out != ret) {
-    EVP_PKEY_free(ret);
+/* num_elements parses one SEQUENCE from |in| and returns the number of elements
+ * in it. On parse error, it returns zero. */
+static size_t num_elements(const uint8_t *in, size_t in_len) {
+  CBS cbs, sequence;
+  CBS_init(&cbs, in, (size_t)in_len);
+
+  if (!CBS_get_asn1(&cbs, &sequence, CBS_ASN1_SEQUENCE)) {
+    return 0;
   }
-  return NULL;
+
+  size_t count = 0;
+  while (CBS_len(&sequence) > 0) {
+    if (!CBS_get_any_asn1_element(&sequence, NULL, NULL, NULL)) {
+      return 0;
+    }
+
+    count++;
+  }
+
+  return count;
 }
 
 EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **out, const uint8_t **inp, long len) {
-  STACK_OF(ASN1_TYPE) *inkey;
-  const uint8_t *p;
-  int keytype;
-  p = *inp;
-
-  /* Dirty trick: read in the ASN1 data into out STACK_OF(ASN1_TYPE):
-   * by analyzing it we can determine the passed structure: this
-   * assumes the input is surrounded by an ASN1 SEQUENCE. */
-  inkey = d2i_ASN1_SEQUENCE_ANY(NULL, &p, len);
-  /* Since we only need to discern "traditional format" RSA and DSA
-   * keys we can just count the elements. */
-  if (sk_ASN1_TYPE_num(inkey) == 6) {
-    keytype = EVP_PKEY_DSA;
-  } else if (sk_ASN1_TYPE_num(inkey) == 4) {
-    keytype = EVP_PKEY_EC;
-  } else if (sk_ASN1_TYPE_num(inkey) == 3) {
-    /* This seems to be PKCS8, not traditional format */
-    p = *inp;
-    PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len);
-    EVP_PKEY *ret;
-
-    sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free);
-    if (!p8) {
-      OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
-      return NULL;
-    }
-    ret = EVP_PKCS82PKEY(p8);
-    PKCS8_PRIV_KEY_INFO_free(p8);
-    if (ret == NULL) {
-      return NULL;
-    }
-
-    *inp = p;
-    if (out) {
-      *out = ret;
-    }
-    return ret;
-  } else {
-    keytype = EVP_PKEY_RSA;
+  if (len < 0) {
+    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
+    return NULL;
   }
 
-  sk_ASN1_TYPE_pop_free(inkey, ASN1_TYPE_free);
-  return d2i_PrivateKey(keytype, out, inp, len);
+  /* Parse the input as a PKCS#8 PrivateKeyInfo. */
+  CBS cbs;
+  CBS_init(&cbs, *inp, (size_t)len);
+  EVP_PKEY *ret = EVP_parse_private_key(&cbs);
+  if (ret != NULL) {
+    if (out != NULL) {
+      EVP_PKEY_free(*out);
+      *out = ret;
+    }
+    *inp = CBS_data(&cbs);
+    return ret;
+  }
+  ERR_clear_error();
+
+  /* Count the elements to determine the legacy key format. */
+  switch (num_elements(*inp, (size_t)len)) {
+    case 4:
+      return d2i_PrivateKey(EVP_PKEY_EC, out, inp, len);
+
+    case 6:
+      return d2i_PrivateKey(EVP_PKEY_DSA, out, inp, len);
+
+    default:
+      return d2i_PrivateKey(EVP_PKEY_RSA, out, inp, len);
+  }
 }
 
 int i2d_PublicKey(EVP_PKEY *key, uint8_t **outp) {
diff --git a/src/crypto/evp/evp_ctx.c b/src/crypto/evp/evp_ctx.c
index 9e038cd..a17a8cc 100644
--- a/src/crypto/evp/evp_ctx.c
+++ b/src/crypto/evp/evp_ctx.c
@@ -56,13 +56,12 @@
 
 #include <openssl/evp.h>
 
-#include <stdio.h>
 #include <string.h>
 
 #include <openssl/err.h>
 #include <openssl/mem.h>
-#include <openssl/obj.h>
 
+#include "../internal.h"
 #include "internal.h"
 
 
@@ -98,8 +97,7 @@
 
   if (pmeth == NULL) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_ALGORITHM);
-    const char *name = OBJ_nid2sn(id);
-    ERR_add_error_dataf("algorithm %d (%s)", id, name);
+    ERR_add_error_dataf("algorithm %d", id);
     return NULL;
   }
 
@@ -108,14 +106,15 @@
     OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
     return NULL;
   }
-  memset(ret, 0, sizeof(EVP_PKEY_CTX));
+  OPENSSL_memset(ret, 0, sizeof(EVP_PKEY_CTX));
 
   ret->engine = e;
   ret->pmeth = pmeth;
   ret->operation = EVP_PKEY_OP_UNDEFINED;
 
   if (pkey) {
-    ret->pkey = EVP_PKEY_up_ref(pkey);
+    EVP_PKEY_up_ref(pkey);
+    ret->pkey = pkey;
   }
 
   if (pmeth->init) {
@@ -149,56 +148,44 @@
   OPENSSL_free(ctx);
 }
 
-EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *pctx) {
-  EVP_PKEY_CTX *rctx;
-
-  if (!pctx->pmeth || !pctx->pmeth->copy) {
+EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *ctx) {
+  if (!ctx->pmeth || !ctx->pmeth->copy) {
     return NULL;
   }
 
-  rctx = OPENSSL_malloc(sizeof(EVP_PKEY_CTX));
-  if (!rctx) {
+  EVP_PKEY_CTX *ret = OPENSSL_malloc(sizeof(EVP_PKEY_CTX));
+  if (!ret) {
     return NULL;
   }
 
-  memset(rctx, 0, sizeof(EVP_PKEY_CTX));
+  OPENSSL_memset(ret, 0, sizeof(EVP_PKEY_CTX));
 
-  rctx->pmeth = pctx->pmeth;
-  rctx->engine = pctx->engine;
-  rctx->operation = pctx->operation;
+  ret->pmeth = ctx->pmeth;
+  ret->engine = ctx->engine;
+  ret->operation = ctx->operation;
 
-  if (pctx->pkey) {
-    rctx->pkey = EVP_PKEY_up_ref(pctx->pkey);
-    if (rctx->pkey == NULL) {
-      goto err;
-    }
+  if (ctx->pkey != NULL) {
+    EVP_PKEY_up_ref(ctx->pkey);
+    ret->pkey = ctx->pkey;
   }
 
-  if (pctx->peerkey) {
-    rctx->peerkey = EVP_PKEY_up_ref(pctx->peerkey);
-    if (rctx->peerkey == NULL) {
-      goto err;
-    }
+  if (ctx->peerkey != NULL) {
+    EVP_PKEY_up_ref(ctx->peerkey);
+    ret->peerkey = ctx->peerkey;
   }
 
-  if (pctx->pmeth->copy(rctx, pctx) > 0) {
-    return rctx;
+  if (ctx->pmeth->copy(ret, ctx) <= 0) {
+    ret->pmeth = NULL;
+    EVP_PKEY_CTX_free(ret);
+    OPENSSL_PUT_ERROR(EVP, ERR_LIB_EVP);
+    return NULL;
   }
 
-err:
-  EVP_PKEY_CTX_free(rctx);
-  OPENSSL_PUT_ERROR(EVP, ERR_LIB_EVP);
-  return NULL;
+  return ret;
 }
 
 EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx) { return ctx->pkey; }
 
-void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data) {
-  ctx->app_data = data;
-}
-
-void *EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx) { return ctx->app_data; }
-
 int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype, int cmd,
                       int p1, void *p2) {
   if (!ctx || !ctx->pmeth || !ctx->pmeth->ctrl) {
@@ -206,6 +193,7 @@
     return 0;
   }
   if (keytype != -1 && ctx->pmeth->pkey_id != keytype) {
+    OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
     return 0;
   }
 
@@ -229,15 +217,6 @@
   }
 
   ctx->operation = EVP_PKEY_OP_SIGN;
-  if (!ctx->pmeth->sign_init) {
-    return 1;
-  }
-
-  if (!ctx->pmeth->sign_init(ctx)) {
-    ctx->operation = EVP_PKEY_OP_UNDEFINED;
-    return 0;
-  }
-
   return 1;
 }
 
@@ -260,14 +239,6 @@
     return 0;
   }
   ctx->operation = EVP_PKEY_OP_VERIFY;
-  if (!ctx->pmeth->verify_init) {
-    return 1;
-  }
-  if (!ctx->pmeth->verify_init(ctx)) {
-    ctx->operation = EVP_PKEY_OP_UNDEFINED;
-    return 0;
-  }
-
   return 1;
 }
 
@@ -290,13 +261,6 @@
     return 0;
   }
   ctx->operation = EVP_PKEY_OP_ENCRYPT;
-  if (!ctx->pmeth->encrypt_init) {
-    return 1;
-  }
-  if (!ctx->pmeth->encrypt_init(ctx)) {
-    ctx->operation = EVP_PKEY_OP_UNDEFINED;
-    return 0;
-  }
   return 1;
 }
 
@@ -319,13 +283,6 @@
     return 0;
   }
   ctx->operation = EVP_PKEY_OP_DECRYPT;
-  if (!ctx->pmeth->decrypt_init) {
-    return 1;
-  }
-  if (!ctx->pmeth->decrypt_init(ctx)) {
-    ctx->operation = EVP_PKEY_OP_UNDEFINED;
-    return 0;
-  }
   return 1;
 }
 
@@ -342,19 +299,34 @@
   return ctx->pmeth->decrypt(ctx, out, outlen, in, inlen);
 }
 
+int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx) {
+  if (!ctx || !ctx->pmeth || !ctx->pmeth->verify_recover) {
+    OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+    return 0;
+  }
+  ctx->operation = EVP_PKEY_OP_VERIFYRECOVER;
+  return 1;
+}
+
+int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *out_len,
+                            const uint8_t *sig, size_t sig_len) {
+  if (!ctx || !ctx->pmeth || !ctx->pmeth->verify_recover) {
+    OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
+    return 0;
+  }
+  if (ctx->operation != EVP_PKEY_OP_VERIFYRECOVER) {
+    OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATON_NOT_INITIALIZED);
+    return 0;
+  }
+  return ctx->pmeth->verify_recover(ctx, out, out_len, sig, sig_len);
+}
+
 int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx) {
   if (!ctx || !ctx->pmeth || !ctx->pmeth->derive) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
     return 0;
   }
   ctx->operation = EVP_PKEY_OP_DERIVE;
-  if (!ctx->pmeth->derive_init) {
-    return 1;
-  }
-  if (!ctx->pmeth->derive_init(ctx)) {
-    ctx->operation = EVP_PKEY_OP_UNDEFINED;
-    return 0;
-  }
   return 1;
 }
 
@@ -436,13 +408,6 @@
     return 0;
   }
   ctx->operation = EVP_PKEY_OP_KEYGEN;
-  if (!ctx->pmeth->keygen_init) {
-    return 1;
-  }
-  if (!ctx->pmeth->keygen_init(ctx)) {
-    ctx->operation = EVP_PKEY_OP_UNDEFINED;
-    return 0;
-  }
   return 1;
 }
 
diff --git a/src/crypto/evp/evp_extra_test.cc b/src/crypto/evp/evp_extra_test.cc
index fe7a002..0f8bb3b 100644
--- a/src/crypto/evp/evp_extra_test.cc
+++ b/src/crypto/evp/evp_extra_test.cc
@@ -15,19 +15,22 @@
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 
 #include <utility>
 #include <vector>
 
+#include <gtest/gtest.h>
+
 #include <openssl/bytestring.h>
 #include <openssl/crypto.h>
 #include <openssl/digest.h>
 #include <openssl/err.h>
-#include <openssl/evp.h>
+#include <openssl/pkcs8.h>
 #include <openssl/rsa.h>
-#include <openssl/x509.h>
 
-#include "../test/scoped_types.h"
+#include "../internal.h"
+#include "../test/test_util.h"
 
 
 // kExampleRSAKeyDER is an RSA private key in ASN.1, DER format. Of course, you
@@ -177,142 +180,6 @@
     0x55, 0xa7, 0xab, 0x45, 0x02, 0x97, 0x60, 0x42,
 };
 
-// kExamplePSSCert is an example self-signed certificate, signed with
-// kExampleRSAKeyDER using RSA-PSS with default hash functions.
-static const uint8_t kExamplePSSCert[] = {
-    0x30, 0x82, 0x02, 0x62, 0x30, 0x82, 0x01, 0xc6, 0xa0, 0x03, 0x02, 0x01,
-    0x02, 0x02, 0x09, 0x00, 0x8d, 0xea, 0x53, 0x24, 0xfa, 0x48, 0x87, 0xf3,
-    0x30, 0x12, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
-    0x0a, 0x30, 0x05, 0xa2, 0x03, 0x02, 0x01, 0x6a, 0x30, 0x45, 0x31, 0x0b,
-    0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31,
-    0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f,
-    0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f,
-    0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72,
-    0x6e, 0x65, 0x74, 0x20, 0x57, 0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20,
-    0x50, 0x74, 0x79, 0x20, 0x4c, 0x74, 0x64, 0x30, 0x1e, 0x17, 0x0d, 0x31,
-    0x34, 0x31, 0x30, 0x30, 0x39, 0x31, 0x39, 0x30, 0x39, 0x35, 0x35, 0x5a,
-    0x17, 0x0d, 0x31, 0x35, 0x31, 0x30, 0x30, 0x39, 0x31, 0x39, 0x30, 0x39,
-    0x35, 0x35, 0x5a, 0x30, 0x45, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55,
-    0x04, 0x06, 0x13, 0x02, 0x41, 0x55, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03,
-    0x55, 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74,
-    0x61, 0x74, 0x65, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a,
-    0x0c, 0x18, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x20, 0x57,
-    0x69, 0x64, 0x67, 0x69, 0x74, 0x73, 0x20, 0x50, 0x74, 0x79, 0x20, 0x4c,
-    0x74, 0x64, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48,
-    0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00,
-    0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xf8, 0xb8, 0x6c, 0x83, 0xb4,
-    0xbc, 0xd9, 0xa8, 0x57, 0xc0, 0xa5, 0xb4, 0x59, 0x76, 0x8c, 0x54, 0x1d,
-    0x79, 0xeb, 0x22, 0x52, 0x04, 0x7e, 0xd3, 0x37, 0xeb, 0x41, 0xfd, 0x83,
-    0xf9, 0xf0, 0xa6, 0x85, 0x15, 0x34, 0x75, 0x71, 0x5a, 0x84, 0xa8, 0x3c,
-    0xd2, 0xef, 0x5a, 0x4e, 0xd3, 0xde, 0x97, 0x8a, 0xdd, 0xff, 0xbb, 0xcf,
-    0x0a, 0xaa, 0x86, 0x92, 0xbe, 0xb8, 0x50, 0xe4, 0xcd, 0x6f, 0x80, 0x33,
-    0x30, 0x76, 0x13, 0x8f, 0xca, 0x7b, 0xdc, 0xec, 0x5a, 0xca, 0x63, 0xc7,
-    0x03, 0x25, 0xef, 0xa8, 0x8a, 0x83, 0x58, 0x76, 0x20, 0xfa, 0x16, 0x77,
-    0xd7, 0x79, 0x92, 0x63, 0x01, 0x48, 0x1a, 0xd8, 0x7b, 0x67, 0xf1, 0x52,
-    0x55, 0x49, 0x4e, 0xd6, 0x6e, 0x4a, 0x5c, 0xd7, 0x7a, 0x37, 0x36, 0x0c,
-    0xde, 0xdd, 0x8f, 0x44, 0xe8, 0xc2, 0xa7, 0x2c, 0x2b, 0xb5, 0xaf, 0x64,
-    0x4b, 0x61, 0x07, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x50, 0x30, 0x4e,
-    0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xd0,
-    0x41, 0xfb, 0x89, 0x41, 0x1e, 0xa7, 0xad, 0x5a, 0xec, 0x34, 0x5d, 0x49,
-    0x11, 0xf9, 0x55, 0x81, 0x78, 0x1f, 0x13, 0x30, 0x1f, 0x06, 0x03, 0x55,
-    0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xd0, 0x41, 0xfb, 0x89,
-    0x41, 0x1e, 0xa7, 0xad, 0x5a, 0xec, 0x34, 0x5d, 0x49, 0x11, 0xf9, 0x55,
-    0x81, 0x78, 0x1f, 0x13, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04,
-    0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x12, 0x06, 0x09, 0x2a, 0x86,
-    0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0a, 0x30, 0x05, 0xa2, 0x03, 0x02,
-    0x01, 0x6a, 0x03, 0x81, 0x81, 0x00, 0x49, 0x4c, 0xb6, 0x45, 0x97, 0x20,
-    0x35, 0xb3, 0x50, 0x64, 0x0d, 0x3f, 0xec, 0x5f, 0x95, 0xd5, 0x84, 0xcb,
-    0x11, 0x7c, 0x03, 0xd7, 0xa6, 0xe6, 0xfa, 0x24, 0x95, 0x9f, 0x31, 0xb0,
-    0xb5, 0xec, 0x66, 0x41, 0x51, 0x18, 0x21, 0x91, 0xbb, 0xe0, 0xaf, 0xf0,
-    0xc5, 0xb7, 0x59, 0x41, 0xd4, 0xdb, 0xa4, 0xd2, 0x64, 0xa7, 0x54, 0x0f,
-    0x8c, 0xf7, 0xe1, 0xd3, 0x3b, 0x1a, 0xb7, 0x0e, 0x9d, 0x9a, 0xde, 0x50,
-    0xa1, 0x9f, 0x0a, 0xf0, 0xda, 0x34, 0x0e, 0x34, 0x7d, 0x76, 0x07, 0xfe,
-    0x5a, 0xfb, 0xf9, 0x58, 0x9b, 0xc9, 0x50, 0x84, 0x01, 0xa0, 0x05, 0x4d,
-    0x67, 0x42, 0x0b, 0xf8, 0xe4, 0x05, 0xcf, 0xaf, 0x8b, 0x71, 0x31, 0xf1,
-    0x0f, 0x6e, 0xc9, 0x24, 0x27, 0x9b, 0xac, 0x04, 0xd7, 0x64, 0x0d, 0x30,
-    0x4e, 0x11, 0x93, 0x40, 0x39, 0xbb, 0x72, 0xb2, 0xfe, 0x6b, 0xe4, 0xae,
-    0x8c, 0x16,
-};
-
-// kBadPSSCert is an example RSA-PSS certificate with bad parameters.
-static const uint8_t kBadPSSCert[] = {
-    0x30, 0x82, 0x03, 0x76, 0x30, 0x82, 0x02, 0x3a, 0xa0, 0x03, 0x02, 0x01,
-    0x02, 0x02, 0x09, 0x00, 0xd7, 0x30, 0x64, 0xbc, 0x9f, 0x12, 0xfe, 0xc3,
-    0x30, 0x3e, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
-    0x0a, 0x30, 0x31, 0xa0, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48,
-    0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0xa1, 0x1a, 0x30, 0x18, 0x06, 0x09,
-    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0x30, 0x0b, 0x06,
-    0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0xa2, 0x04,
-    0x02, 0x02, 0x00, 0xde, 0x30, 0x27, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03,
-    0x55, 0x04, 0x03, 0x0c, 0x1c, 0x54, 0x65, 0x73, 0x74, 0x20, 0x49, 0x6e,
-    0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x50, 0x53, 0x53, 0x20, 0x63, 0x65,
-    0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x30, 0x1e, 0x17,
-    0x0d, 0x31, 0x35, 0x31, 0x31, 0x30, 0x34, 0x31, 0x36, 0x30, 0x32, 0x33,
-    0x35, 0x5a, 0x17, 0x0d, 0x31, 0x35, 0x31, 0x32, 0x30, 0x34, 0x31, 0x36,
-    0x30, 0x32, 0x33, 0x35, 0x5a, 0x30, 0x27, 0x31, 0x25, 0x30, 0x23, 0x06,
-    0x03, 0x55, 0x04, 0x03, 0x0c, 0x1c, 0x54, 0x65, 0x73, 0x74, 0x20, 0x49,
-    0x6e, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x20, 0x50, 0x53, 0x53, 0x20, 0x63,
-    0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x30, 0x82,
-    0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
-    0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82,
-    0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc4, 0xda, 0x33, 0xb5, 0x87,
-    0xa9, 0x50, 0x80, 0x18, 0x02, 0x00, 0xfb, 0x32, 0xf5, 0x29, 0x6b, 0xef,
-    0x01, 0x24, 0xeb, 0x86, 0x5a, 0xbe, 0xd5, 0xe3, 0xdd, 0x3b, 0xbc, 0x2c,
-    0xad, 0x65, 0xf6, 0x2a, 0x26, 0x28, 0x4d, 0x8a, 0xc9, 0x61, 0x39, 0xf1,
-    0x84, 0xb9, 0xe7, 0xd3, 0x0a, 0xc7, 0xa8, 0x0a, 0x6d, 0xef, 0xd9, 0xcb,
-    0x20, 0x11, 0xbb, 0x71, 0xf4, 0xa1, 0xc9, 0x9a, 0x85, 0x1c, 0xe6, 0x3f,
-    0x23, 0x39, 0x58, 0x3c, 0xc5, 0x6d, 0xfa, 0x03, 0xe8, 0xdb, 0xdd, 0xe0,
-    0xc3, 0xde, 0x85, 0x76, 0xce, 0x49, 0x06, 0xc8, 0xe1, 0x8e, 0x4c, 0x86,
-    0x9c, 0xec, 0xab, 0xf4, 0xe5, 0x27, 0xb4, 0x5a, 0xaf, 0xc4, 0x36, 0xd3,
-    0x20, 0x81, 0x54, 0xee, 0x8f, 0x48, 0x77, 0x10, 0xf8, 0x79, 0xd6, 0xaa,
-    0x8d, 0x1b, 0xfe, 0x7d, 0xe8, 0x15, 0x13, 0xe0, 0x7b, 0xf6, 0x90, 0xe4,
-    0xe2, 0xcd, 0x2e, 0x8e, 0xc9, 0x3a, 0x75, 0x42, 0xed, 0x0a, 0x0f, 0x51,
-    0xb2, 0xdd, 0x2e, 0x70, 0x61, 0x68, 0xd7, 0xd9, 0xab, 0xf9, 0xbe, 0xe4,
-    0x75, 0xb7, 0xe7, 0xf2, 0x96, 0x7b, 0xd9, 0x93, 0x43, 0x24, 0xfb, 0x9e,
-    0x55, 0xda, 0xd4, 0x01, 0x6c, 0x3d, 0xa2, 0x59, 0x7a, 0xd5, 0x47, 0x18,
-    0x7e, 0x4e, 0xf9, 0x5d, 0xda, 0xcb, 0x93, 0xa2, 0x65, 0x2f, 0x8d, 0x46,
-    0xad, 0x81, 0xdc, 0xf0, 0xa9, 0x5f, 0x5d, 0xfe, 0x37, 0x80, 0x64, 0x2a,
-    0x41, 0xfa, 0xe9, 0x1e, 0x48, 0x38, 0x22, 0x1d, 0x9c, 0x23, 0xa5, 0xad,
-    0xda, 0x78, 0x45, 0x18, 0x0c, 0xeb, 0x95, 0xca, 0x2b, 0xcc, 0xb9, 0x62,
-    0x40, 0x85, 0x09, 0x44, 0x88, 0x4c, 0xf2, 0x1e, 0x08, 0x80, 0x37, 0xe9,
-    0x06, 0x96, 0x8f, 0x75, 0x54, 0x0b, 0xa9, 0x2d, 0xa9, 0x15, 0xb5, 0xda,
-    0xe5, 0xe4, 0x23, 0xaa, 0x2c, 0x89, 0xc1, 0xa9, 0x36, 0xbc, 0x9f, 0x02,
-    0x03, 0x01, 0x00, 0x01, 0xa3, 0x50, 0x30, 0x4e, 0x30, 0x1d, 0x06, 0x03,
-    0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x2b, 0x75, 0xf3, 0x43, 0x78,
-    0xa0, 0x65, 0x2d, 0xe4, 0xb6, 0xf3, 0x07, 0x04, 0x38, 0x21, 0xaf, 0xb6,
-    0xe1, 0x5f, 0x7b, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18,
-    0x30, 0x16, 0x80, 0x14, 0x2b, 0x75, 0xf3, 0x43, 0x78, 0xa0, 0x65, 0x2d,
-    0xe4, 0xb6, 0xf3, 0x07, 0x04, 0x38, 0x21, 0xaf, 0xb6, 0xe1, 0x5f, 0x7b,
-    0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01,
-    0x01, 0xff, 0x30, 0x31, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
-    0x01, 0x01, 0x0a, 0x30, 0x24, 0xa0, 0x0d, 0x30, 0x0b, 0x06, 0x09, 0x60,
-    0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0xa1, 0x0d, 0x30, 0x0b,
-    0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08, 0xa2,
-    0x04, 0x02, 0x02, 0x00, 0xde, 0x03, 0x82, 0x01, 0x01, 0x00, 0x08, 0xc1,
-    0xb6, 0x6f, 0x74, 0x94, 0x6c, 0x60, 0x75, 0xd8, 0xdc, 0xe1, 0x7b, 0xbf,
-    0x9d, 0xb5, 0xd7, 0x14, 0x75, 0x6c, 0xdb, 0x35, 0x5c, 0x1e, 0xff, 0xe6,
-    0xa8, 0xe6, 0x68, 0x42, 0x41, 0x81, 0xf6, 0xbf, 0xc1, 0x56, 0x02, 0xdb,
-    0xc6, 0x11, 0xeb, 0x15, 0x9d, 0xa9, 0x1c, 0x61, 0x25, 0x6d, 0x46, 0x0f,
-    0x7e, 0x27, 0xdd, 0x4b, 0xdc, 0xed, 0x07, 0xbd, 0xde, 0xd5, 0xde, 0x09,
-    0xf8, 0xfd, 0xbd, 0xa3, 0x4c, 0x81, 0xa9, 0xf7, 0x78, 0xff, 0x01, 0x80,
-    0x73, 0xf2, 0x40, 0xf2, 0xa8, 0x27, 0xe8, 0x00, 0x04, 0x3b, 0xf5, 0xe7,
-    0xa6, 0x58, 0x45, 0x79, 0x34, 0x49, 0x42, 0xd2, 0xd9, 0x56, 0x5e, 0xf9,
-    0x0a, 0x41, 0xd7, 0x81, 0x41, 0x94, 0x77, 0x78, 0x7e, 0x00, 0x3b, 0xca,
-    0xb5, 0xc0, 0x6e, 0x5b, 0xd7, 0x52, 0x52, 0x77, 0x1a, 0x52, 0xb8, 0x0d,
-    0x29, 0x1f, 0x2e, 0xfe, 0x1f, 0xf6, 0xb0, 0xc1, 0xb7, 0xf1, 0x15, 0x98,
-    0x0f, 0x30, 0x5d, 0x74, 0x2f, 0xfa, 0xe9, 0x84, 0xda, 0xde, 0xbe, 0xca,
-    0x91, 0x55, 0x1f, 0x5b, 0xbc, 0xaa, 0x45, 0x07, 0xc4, 0x2e, 0x21, 0x8a,
-    0x75, 0xc9, 0xbe, 0x6e, 0x39, 0x53, 0x10, 0xcb, 0x2f, 0x4b, 0xe1, 0x21,
-    0x1e, 0xea, 0x7d, 0x0b, 0x36, 0xe9, 0xa0, 0x2c, 0x76, 0x17, 0x1f, 0x69,
-    0x34, 0xfb, 0x45, 0x63, 0x7c, 0x84, 0x39, 0xb4, 0x21, 0x98, 0xbd, 0x49,
-    0xca, 0x80, 0x91, 0x5a, 0xa0, 0x44, 0xef, 0x91, 0xb3, 0x14, 0xf6, 0xd1,
-    0x6a, 0x2b, 0xb1, 0xe5, 0x4a, 0x44, 0x92, 0x7b, 0x3e, 0x8b, 0x7b, 0x6b,
-    0x90, 0x6b, 0x2c, 0x67, 0x3b, 0x0e, 0xb9, 0x5a, 0x87, 0x35, 0x33, 0x59,
-    0x94, 0x2f, 0x7e, 0xf6, 0x13, 0xc7, 0x22, 0x87, 0x3d, 0x50, 0xc9, 0x80,
-    0x40, 0xda, 0x35, 0xbc, 0x62, 0x16, 0xdc, 0xd5, 0x95, 0xa1, 0xe1, 0x9b,
-    0x68, 0x9f,
-};
-
 // kExampleRSAKeyPKCS8 is kExampleRSAKeyDER encoded in a PKCS #8
 // PrivateKeyInfo.
 static const uint8_t kExampleRSAKeyPKCS8[] = {
@@ -387,6 +254,61 @@
     0xc1,
 };
 
+// kExampleECKeyPKCS8 is a sample EC private key encoded as a PKCS#8
+// PrivateKeyInfo.
+static const uint8_t kExampleECKeyPKCS8[] = {
+    0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
+    0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
+    0x03, 0x01, 0x07, 0x04, 0x6d, 0x30, 0x6b, 0x02, 0x01, 0x01, 0x04, 0x20,
+    0x43, 0x09, 0xc0, 0x67, 0x75, 0x21, 0x47, 0x9d, 0xa8, 0xfa, 0x16, 0xdf,
+    0x15, 0x73, 0x61, 0x34, 0x68, 0x6f, 0xe3, 0x8e, 0x47, 0x91, 0x95, 0xab,
+    0x79, 0x4a, 0x72, 0x14, 0xcb, 0xe2, 0x49, 0x4f, 0xa1, 0x44, 0x03, 0x42,
+    0x00, 0x04, 0xde, 0x09, 0x08, 0x07, 0x03, 0x2e, 0x8f, 0x37, 0x9a, 0xd5,
+    0xad, 0xe5, 0xc6, 0x9d, 0xd4, 0x63, 0xc7, 0x4a, 0xe7, 0x20, 0xcb, 0x90,
+    0xa0, 0x1f, 0x18, 0x18, 0x72, 0xb5, 0x21, 0x88, 0x38, 0xc0, 0xdb, 0xba,
+    0xf6, 0x99, 0xd8, 0xa5, 0x3b, 0x83, 0xe9, 0xe3, 0xd5, 0x61, 0x99, 0x73,
+    0x42, 0xc6, 0x6c, 0xe8, 0x0a, 0x95, 0x40, 0x41, 0x3b, 0x0d, 0x10, 0xa7,
+    0x4a, 0x93, 0xdb, 0x5a, 0xe7, 0xec,
+};
+
+// kExampleECKeySpecifiedCurvePKCS8 is a sample EC private key encoded as a
+// PKCS#8 PrivateKeyInfo with P-256's parameters spelled out rather than using
+// the curve OID.
+static const uint8_t kExampleECKeySpecifiedCurvePKCS8[] = {
+    0x30, 0x82, 0x01, 0x79, 0x02, 0x01, 0x00, 0x30, 0x82, 0x01, 0x03, 0x06,
+    0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x30, 0x81, 0xf7, 0x02,
+    0x01, 0x01, 0x30, 0x2c, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01,
+    0x01, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0x30, 0x5b, 0x04, 0x20, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x01,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
+    0x04, 0x20, 0x5a, 0xc6, 0x35, 0xd8, 0xaa, 0x3a, 0x93, 0xe7, 0xb3, 0xeb,
+    0xbd, 0x55, 0x76, 0x98, 0x86, 0xbc, 0x65, 0x1d, 0x06, 0xb0, 0xcc, 0x53,
+    0xb0, 0xf6, 0x3b, 0xce, 0x3c, 0x3e, 0x27, 0xd2, 0x60, 0x4b, 0x03, 0x15,
+    0x00, 0xc4, 0x9d, 0x36, 0x08, 0x86, 0xe7, 0x04, 0x93, 0x6a, 0x66, 0x78,
+    0xe1, 0x13, 0x9d, 0x26, 0xb7, 0x81, 0x9f, 0x7e, 0x90, 0x04, 0x41, 0x04,
+    0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, 0xe6, 0xe5,
+    0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, 0xeb, 0x33, 0xa0,
+    0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, 0x4f, 0xe3, 0x42, 0xe2,
+    0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, 0x4a, 0x7c, 0x0f, 0x9e, 0x16,
+    0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68,
+    0x37, 0xbf, 0x51, 0xf5, 0x02, 0x21, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00,
+    0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbc,
+    0xe6, 0xfa, 0xad, 0xa7, 0x17, 0x9e, 0x84, 0xf3, 0xb9, 0xca, 0xc2, 0xfc,
+    0x63, 0x25, 0x51, 0x02, 0x01, 0x01, 0x04, 0x6d, 0x30, 0x6b, 0x02, 0x01,
+    0x01, 0x04, 0x20, 0x43, 0x09, 0xc0, 0x67, 0x75, 0x21, 0x47, 0x9d, 0xa8,
+    0xfa, 0x16, 0xdf, 0x15, 0x73, 0x61, 0x34, 0x68, 0x6f, 0xe3, 0x8e, 0x47,
+    0x91, 0x95, 0xab, 0x79, 0x4a, 0x72, 0x14, 0xcb, 0xe2, 0x49, 0x4f, 0xa1,
+    0x44, 0x03, 0x42, 0x00, 0x04, 0xde, 0x09, 0x08, 0x07, 0x03, 0x2e, 0x8f,
+    0x37, 0x9a, 0xd5, 0xad, 0xe5, 0xc6, 0x9d, 0xd4, 0x63, 0xc7, 0x4a, 0xe7,
+    0x20, 0xcb, 0x90, 0xa0, 0x1f, 0x18, 0x18, 0x72, 0xb5, 0x21, 0x88, 0x38,
+    0xc0, 0xdb, 0xba, 0xf6, 0x99, 0xd8, 0xa5, 0x3b, 0x83, 0xe9, 0xe3, 0xd5,
+    0x61, 0x99, 0x73, 0x42, 0xc6, 0x6c, 0xe8, 0x0a, 0x95, 0x40, 0x41, 0x3b,
+    0x0d, 0x10, 0xa7, 0x4a, 0x93, 0xdb, 0x5a, 0xe7, 0xec,
+};
+
 // kExampleBadECKeyDER is a sample EC private key encoded as an ECPrivateKey
 // structure. The private key is equal to the order and will fail to import.
 static const uint8_t kExampleBadECKeyDER[] = {
@@ -438,428 +360,183 @@
     0x48, 0x30, 0x01, 0xaa, 0x02, 0x86, 0xc0, 0x30, 0xdf, 0xe9, 0x80,
 };
 
-static ScopedEVP_PKEY LoadExampleRSAKey() {
-  ScopedRSA rsa(RSA_private_key_from_bytes(kExampleRSAKeyDER,
+static bssl::UniquePtr<EVP_PKEY> LoadExampleRSAKey() {
+  bssl::UniquePtr<RSA> rsa(RSA_private_key_from_bytes(kExampleRSAKeyDER,
                                            sizeof(kExampleRSAKeyDER)));
   if (!rsa) {
     return nullptr;
   }
-  ScopedEVP_PKEY pkey(EVP_PKEY_new());
+  bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
   if (!pkey || !EVP_PKEY_set1_RSA(pkey.get(), rsa.get())) {
     return nullptr;
   }
   return pkey;
 }
 
-static bool TestEVP_DigestSignInit(void) {
-  ScopedEVP_PKEY pkey = LoadExampleRSAKey();
-  ScopedEVP_MD_CTX md_ctx;
-  if (!pkey ||
-      !EVP_DigestSignInit(md_ctx.get(), NULL, EVP_sha256(), NULL, pkey.get()) ||
-      !EVP_DigestSignUpdate(md_ctx.get(), kMsg, sizeof(kMsg))) {
-    return false;
-  }
+TEST(EVPExtraTest, DigestSignInit) {
+  bssl::UniquePtr<EVP_PKEY> pkey = LoadExampleRSAKey();
+  ASSERT_TRUE(pkey);
+  bssl::ScopedEVP_MD_CTX md_ctx;
+  ASSERT_TRUE(
+      EVP_DigestSignInit(md_ctx.get(), NULL, EVP_sha256(), NULL, pkey.get()));
+  ASSERT_TRUE(EVP_DigestSignUpdate(md_ctx.get(), kMsg, sizeof(kMsg)));
+
   // Determine the size of the signature.
   size_t sig_len = 0;
-  if (!EVP_DigestSignFinal(md_ctx.get(), NULL, &sig_len)) {
-    return false;
-  }
+  ASSERT_TRUE(EVP_DigestSignFinal(md_ctx.get(), NULL, &sig_len));
+
   // Sanity check for testing.
-  if (sig_len != (size_t)EVP_PKEY_size(pkey.get())) {
-    fprintf(stderr, "sig_len mismatch\n");
-    return false;
-  }
+  EXPECT_EQ(static_cast<size_t>(EVP_PKEY_size(pkey.get())), sig_len);
 
   std::vector<uint8_t> sig;
   sig.resize(sig_len);
-  if (!EVP_DigestSignFinal(md_ctx.get(), sig.data(), &sig_len)) {
-    return false;
-  }
+  ASSERT_TRUE(EVP_DigestSignFinal(md_ctx.get(), sig.data(), &sig_len));
   sig.resize(sig_len);
 
   // Ensure that the signature round-trips.
   md_ctx.Reset();
-  if (!EVP_DigestVerifyInit(md_ctx.get(), NULL, EVP_sha256(), NULL,
-                            pkey.get()) ||
-      !EVP_DigestVerifyUpdate(md_ctx.get(), kMsg, sizeof(kMsg)) ||
-      !EVP_DigestVerifyFinal(md_ctx.get(), sig.data(), sig_len)) {
-    return false;
-  }
-
-  return true;
+  ASSERT_TRUE(
+      EVP_DigestVerifyInit(md_ctx.get(), NULL, EVP_sha256(), NULL, pkey.get()));
+  ASSERT_TRUE(EVP_DigestVerifyUpdate(md_ctx.get(), kMsg, sizeof(kMsg)));
+  ASSERT_TRUE(EVP_DigestVerifyFinal(md_ctx.get(), sig.data(), sig_len));
 }
 
-static bool TestEVP_DigestVerifyInit(void) {
-  ScopedEVP_PKEY pkey = LoadExampleRSAKey();
-  ScopedEVP_MD_CTX md_ctx;
-  if (!pkey ||
-      !EVP_DigestVerifyInit(md_ctx.get(), NULL, EVP_sha256(), NULL,
-                            pkey.get()) ||
-      !EVP_DigestVerifyUpdate(md_ctx.get(), kMsg, sizeof(kMsg)) ||
-      !EVP_DigestVerifyFinal(md_ctx.get(), kSignature, sizeof(kSignature))) {
-    return false;
-  }
-  return true;
+TEST(EVPExtraTest, DigestVerifyInit) {
+  bssl::UniquePtr<EVP_PKEY> pkey = LoadExampleRSAKey();
+  bssl::ScopedEVP_MD_CTX md_ctx;
+  ASSERT_TRUE(pkey);
+  ASSERT_TRUE(
+      EVP_DigestVerifyInit(md_ctx.get(), NULL, EVP_sha256(), NULL, pkey.get()));
+  ASSERT_TRUE(EVP_DigestVerifyUpdate(md_ctx.get(), kMsg, sizeof(kMsg)));
+  ASSERT_TRUE(
+      EVP_DigestVerifyFinal(md_ctx.get(), kSignature, sizeof(kSignature)));
 }
 
-// TestAlgorithmRoundtrip signs a message using an already-initialized
-// |md_ctx|, sampling the AlgorithmIdentifier. It then uses |pkey| and the
-// AlgorithmIdentifier to verify the signature.
-static bool TestAlgorithmRoundtrip(EVP_MD_CTX *md_ctx, EVP_PKEY *pkey) {
-  if (!EVP_DigestSignUpdate(md_ctx, kMsg, sizeof(kMsg))) {
-    return false;
-  }
+TEST(EVPExtraTest, VerifyRecover) {
+  bssl::UniquePtr<EVP_PKEY> pkey = LoadExampleRSAKey();
+  ASSERT_TRUE(pkey);
+  bssl::UniquePtr<RSA> rsa(EVP_PKEY_get1_RSA(pkey.get()));
+  ASSERT_TRUE(rsa);
 
-  // Save the algorithm.
-  ScopedX509_ALGOR algor(X509_ALGOR_new());
-  if (!algor || !EVP_DigestSignAlgorithm(md_ctx, algor.get())) {
-    return false;
-  }
+  const uint8_t kDummyHash[32] = {0};
+  uint8_t sig[2048/8];
+  unsigned sig_len = sizeof(sig);
+  ASSERT_TRUE(RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash), sig,
+                       &sig_len, rsa.get()));
 
-  // Determine the size of the signature.
-  size_t sig_len = 0;
-  if (!EVP_DigestSignFinal(md_ctx, NULL, &sig_len)) {
-    return false;
-  }
-  // Sanity check for testing.
-  if (sig_len != (size_t)EVP_PKEY_size(pkey)) {
-    fprintf(stderr, "sig_len mismatch\n");
-    return false;
-  }
+  size_t out_len;
+  bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new(pkey.get(), nullptr));
+  ASSERT_TRUE(EVP_PKEY_verify_recover_init(ctx.get()));
+  ASSERT_TRUE(EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_PADDING));
+  ASSERT_TRUE(EVP_PKEY_CTX_set_signature_md(ctx.get(), EVP_sha256()));
+  ASSERT_TRUE(
+      EVP_PKEY_verify_recover(ctx.get(), nullptr, &out_len, sig, sig_len));
 
-  std::vector<uint8_t> sig;
-  sig.resize(sig_len);
-  if (!EVP_DigestSignFinal(md_ctx, sig.data(), &sig_len)) {
-    return false;
-  }
-  sig.resize(sig_len);
+  std::vector<uint8_t> recovered;
+  recovered.resize(out_len);
 
-  // Ensure that the signature round-trips.
-  ScopedEVP_MD_CTX md_ctx_verify;
-  if (!EVP_DigestVerifyInitFromAlgorithm(md_ctx_verify.get(), algor.get(),
-                                         pkey) ||
-      !EVP_DigestVerifyUpdate(md_ctx_verify.get(), kMsg, sizeof(kMsg)) ||
-      !EVP_DigestVerifyFinal(md_ctx_verify.get(), sig.data(), sig_len)) {
-    return false;
-  }
+  ASSERT_TRUE(EVP_PKEY_verify_recover(ctx.get(), recovered.data(), &out_len,
+                                      sig, sig_len));
+  EXPECT_EQ(Bytes(kDummyHash), Bytes(recovered.data(), out_len));
 
-  return true;
+  out_len = recovered.size();
+  ASSERT_TRUE(EVP_PKEY_CTX_set_signature_md(ctx.get(), nullptr));
+  ASSERT_TRUE(EVP_PKEY_verify_recover(ctx.get(), recovered.data(), &out_len,
+                                      sig, sig_len));
+
+  // The size of a SHA-256 hash plus PKCS#1 v1.5 ASN.1 stuff happens to be 51
+  // bytes.
+  EXPECT_EQ(51u, out_len);
 }
 
-static bool TestEVP_DigestSignAlgorithm(void) {
-  ScopedEVP_PKEY pkey = LoadExampleRSAKey();
-
-  // Test a simple AlgorithmIdentifier.
-  ScopedEVP_MD_CTX md_ctx;
-  if (!pkey ||
-      !EVP_DigestSignInit(md_ctx.get(), NULL, EVP_sha256(), NULL, pkey.get()) ||
-      !TestAlgorithmRoundtrip(md_ctx.get(), pkey.get())) {
-    fprintf(stderr, "RSA with SHA-256 failed\n");
-    return false;
-  }
-
-  // Test RSA-PSS with custom parameters.
-  md_ctx.Reset();
-  EVP_PKEY_CTX *pkey_ctx;
-  if (!EVP_DigestSignInit(md_ctx.get(), &pkey_ctx, EVP_sha256(), NULL,
-                          pkey.get()) ||
-      !EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) ||
-      !EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, EVP_sha512()) ||
-      !TestAlgorithmRoundtrip(md_ctx.get(), pkey.get())) {
-    fprintf(stderr, "RSA-PSS failed\n");
-    return false;
-  }
-
-  return true;
-}
-
-static bool ParseCertificate(CBS *out_tbs_cert,
-                             ScopedEVP_PKEY *out_pubkey,
-                             ScopedX509_ALGOR *out_algor,
-                             CBS *out_signature,
-                             const CBS *in_) {
-  CBS in = *in_;
-  CBS cert_body, tbs_cert, algorithm, signature;
-  if (!CBS_get_asn1(&in, &cert_body, CBS_ASN1_SEQUENCE) ||
-      CBS_len(&in) != 0 ||
-      !CBS_get_any_asn1_element(&cert_body, &tbs_cert, NULL, NULL) ||
-      !CBS_get_asn1_element(&cert_body, &algorithm, CBS_ASN1_SEQUENCE) ||
-      !CBS_get_asn1(&cert_body, &signature, CBS_ASN1_BITSTRING) ||
-      CBS_len(&cert_body) != 0) {
-    return false;
-  }
-
-  CBS tbs_cert_copy = tbs_cert;
-  CBS tbs_cert_body, discard, spki;
-  if (!CBS_get_asn1(&tbs_cert_copy, &tbs_cert_body, CBS_ASN1_SEQUENCE) ||
-      CBS_len(&tbs_cert_copy) != 0 ||
-      !CBS_get_optional_asn1(
-          &tbs_cert_body, &discard, NULL,
-          CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0) ||
-      !CBS_get_asn1(&tbs_cert_body, &discard /* serialNumber */,
-                    CBS_ASN1_INTEGER) ||
-      !CBS_get_asn1(&tbs_cert_body, &discard /* signature */,
-                    CBS_ASN1_SEQUENCE) ||
-      !CBS_get_any_asn1_element(&tbs_cert_body, &discard /* issuer */,
-                                NULL, NULL) ||
-      !CBS_get_asn1(&tbs_cert_body, &discard /* validity */,
-                    CBS_ASN1_SEQUENCE) ||
-      !CBS_get_any_asn1_element(&tbs_cert_body, &discard /* subject */,
-                                NULL, NULL) ||
-      !CBS_get_asn1_element(&tbs_cert_body, &spki, CBS_ASN1_SEQUENCE)) {
-    return false;
-  }
-
-  const uint8_t *derp = CBS_data(&spki);
-  ScopedEVP_PKEY pubkey(d2i_PUBKEY(NULL, &derp, CBS_len(&spki)));
-  if (!pubkey || derp != CBS_data(&spki) + CBS_len(&spki)) {
-    return false;
-  }
-
-  derp = CBS_data(&algorithm);
-  ScopedX509_ALGOR algor(d2i_X509_ALGOR(NULL, &derp, CBS_len(&algorithm)));
-  if (!algor || derp != CBS_data(&algorithm) + CBS_len(&algorithm)) {
-    return false;
-  }
-
-  // Signatures are BIT STRINGs, but they have are multiple of 8 bytes, so the
-  // leading phase byte is just a zero.
-  uint8_t padding;
-  if (!CBS_get_u8(&signature, &padding) || padding != 0) {
-    return false;
-  }
-
-  *out_tbs_cert = tbs_cert;
-  *out_pubkey = std::move(pubkey);
-  *out_algor = std::move(algor);
-  *out_signature = signature;
-  return true;
-}
-
-static bool TestEVP_DigestVerifyInitFromAlgorithm(void) {
-  CBS in, tbs_cert, signature;
-  ScopedEVP_PKEY pkey;
-  ScopedX509_ALGOR algor;
-  CBS_init(&in, kExamplePSSCert, sizeof(kExamplePSSCert));
-  if (!ParseCertificate(&tbs_cert, &pkey, &algor, &signature, &in)) {
-    fprintf(stderr, "Failed to parse certificate\n");
-    return false;
-  }
-
-  ScopedEVP_MD_CTX md_ctx;
-  if (!EVP_DigestVerifyInitFromAlgorithm(md_ctx.get(), algor.get(),
-                                         pkey.get()) ||
-      !EVP_DigestVerifyUpdate(md_ctx.get(), CBS_data(&tbs_cert),
-                              CBS_len(&tbs_cert)) ||
-      !EVP_DigestVerifyFinal(md_ctx.get(), CBS_data(&signature),
-                             CBS_len(&signature))) {
-    return false;
-  }
-  return true;
-}
-
-static bool TestBadPSSParameters(void) {
-  CBS in, tbs_cert, signature;
-  ScopedEVP_PKEY pkey;
-  ScopedX509_ALGOR algor;
-  CBS_init(&in, kBadPSSCert, sizeof(kBadPSSCert));
-  if (!ParseCertificate(&tbs_cert, &pkey, &algor, &signature, &in)) {
-    fprintf(stderr, "Failed to parse certificate\n");
-    return false;
-  }
-
-  ScopedEVP_MD_CTX md_ctx;
-  if (EVP_DigestVerifyInitFromAlgorithm(md_ctx.get(), algor.get(),
-                                        pkey.get())) {
-    fprintf(stderr, "Unexpectedly processed bad signature parameters\n");
-    return false;
-  }
-  ERR_clear_error();
-  return true;
-}
-
-static bool TestValidPrivateKey(const uint8_t *input, size_t input_len,
+static void TestValidPrivateKey(const uint8_t *input, size_t input_len,
                                 int expected_id) {
   const uint8_t *p = input;
-  ScopedEVP_PKEY pkey(d2i_AutoPrivateKey(NULL, &p, input_len));
-  if (!pkey || p != input + input_len) {
-    fprintf(stderr, "d2i_AutoPrivateKey failed\n");
-    return false;
-  }
-
-  if (EVP_PKEY_id(pkey.get()) != expected_id) {
-    fprintf(stderr, "Did not decode expected type\n");
-    return false;
-  }
-
-  return true;
+  bssl::UniquePtr<EVP_PKEY> pkey(d2i_AutoPrivateKey(NULL, &p, input_len));
+  ASSERT_TRUE(pkey);
+  EXPECT_EQ(input + input_len, p);
+  EXPECT_EQ(expected_id, EVP_PKEY_id(pkey.get()));
 }
 
-static bool Testd2i_AutoPrivateKey() {
-  if (!TestValidPrivateKey(kExampleRSAKeyDER, sizeof(kExampleRSAKeyDER),
-                           EVP_PKEY_RSA)) {
-    fprintf(stderr, "d2i_AutoPrivateKey(kExampleRSAKeyDER) failed\n");
-    return false;
-  }
-
-  if (!TestValidPrivateKey(kExampleRSAKeyPKCS8, sizeof(kExampleRSAKeyPKCS8),
-                           EVP_PKEY_RSA)) {
-    fprintf(stderr, "d2i_AutoPrivateKey(kExampleRSAKeyPKCS8) failed\n");
-    return false;
-  }
-
-  if (!TestValidPrivateKey(kExampleECKeyDER, sizeof(kExampleECKeyDER),
-                           EVP_PKEY_EC)) {
-    fprintf(stderr, "d2i_AutoPrivateKey(kExampleECKeyDER) failed\n");
-    return false;
-  }
-
-  if (!TestValidPrivateKey(kExampleDSAKeyDER, sizeof(kExampleDSAKeyDER),
-                           EVP_PKEY_DSA)) {
-    fprintf(stderr, "d2i_AutoPrivateKey(kExampleDSAKeyDER) failed\n");
-    return false;
-  }
+TEST(EVPExtraTest, d2i_AutoPrivateKey) {
+  TestValidPrivateKey(kExampleRSAKeyDER, sizeof(kExampleRSAKeyDER),
+                      EVP_PKEY_RSA);
+  TestValidPrivateKey(kExampleRSAKeyPKCS8, sizeof(kExampleRSAKeyPKCS8),
+                      EVP_PKEY_RSA);
+  TestValidPrivateKey(kExampleECKeyDER, sizeof(kExampleECKeyDER), EVP_PKEY_EC);
+  TestValidPrivateKey(kExampleECKeyPKCS8, sizeof(kExampleECKeyPKCS8),
+                      EVP_PKEY_EC);
+  TestValidPrivateKey(kExampleECKeySpecifiedCurvePKCS8,
+                      sizeof(kExampleECKeySpecifiedCurvePKCS8), EVP_PKEY_EC);
+  TestValidPrivateKey(kExampleDSAKeyDER, sizeof(kExampleDSAKeyDER),
+                      EVP_PKEY_DSA);
 
   const uint8_t *p = kInvalidPrivateKey;
-  ScopedEVP_PKEY pkey(d2i_AutoPrivateKey(NULL, &p, sizeof(kInvalidPrivateKey)));
-  if (pkey) {
-    fprintf(stderr, "Parsed invalid private key\n");
-    return false;
-  }
+  bssl::UniquePtr<EVP_PKEY> pkey(
+      d2i_AutoPrivateKey(NULL, &p, sizeof(kInvalidPrivateKey)));
+  EXPECT_FALSE(pkey) << "Parsed invalid private key";
   ERR_clear_error();
-
-  return true;
 }
 
-// TestEVP_PKCS82PKEY tests loading a bad key in PKCS8 format.
-static bool TestEVP_PKCS82PKEY(void) {
+// Tests loading a bad key in PKCS8 format.
+TEST(EVPExtraTest, BadECKey) {
   const uint8_t *derp = kExampleBadECKeyDER;
-  ScopedPKCS8_PRIV_KEY_INFO p8inf(
+  bssl::UniquePtr<PKCS8_PRIV_KEY_INFO> p8inf(
       d2i_PKCS8_PRIV_KEY_INFO(NULL, &derp, sizeof(kExampleBadECKeyDER)));
-  if (!p8inf || derp != kExampleBadECKeyDER + sizeof(kExampleBadECKeyDER)) {
-    fprintf(stderr, "Failed to parse key\n");
-    return false;
-  }
+  ASSERT_TRUE(p8inf);
+  EXPECT_EQ(kExampleBadECKeyDER + sizeof(kExampleBadECKeyDER), derp);
 
-  ScopedEVP_PKEY pkey(EVP_PKCS82PKEY(p8inf.get()));
-  if (pkey) {
-    fprintf(stderr, "Imported invalid EC key\n");
-    return false;
-  }
+  bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKCS82PKEY(p8inf.get()));
+  ASSERT_FALSE(pkey) << "Imported invalid EC key";
   ERR_clear_error();
-
-  return true;
 }
 
-// Testd2i_PrivateKey tests |d2i_PrivateKey|.
-static bool Testd2i_PrivateKey(void) {
-  const uint8_t *derp = kExampleRSAKeyDER;
-  ScopedEVP_PKEY pkey(d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &derp,
-                                     sizeof(kExampleRSAKeyDER)));
-  if (!pkey || derp != kExampleRSAKeyDER + sizeof(kExampleRSAKeyDER)) {
-    fprintf(stderr, "Failed to import raw RSA key.\n");
-    return false;
+// Tests |EVP_marshal_public_key| on an empty key.
+TEST(EVPExtraTest, MarshalEmptyPublicKey) {
+  bssl::UniquePtr<EVP_PKEY> empty(EVP_PKEY_new());
+  ASSERT_TRUE(empty);
+
+  bssl::ScopedCBB cbb;
+  EXPECT_FALSE(EVP_marshal_public_key(cbb.get(), empty.get()))
+      << "Marshalled empty public key.";
+  EXPECT_EQ(EVP_R_UNSUPPORTED_ALGORITHM, ERR_GET_REASON(ERR_peek_last_error()));
+}
+
+static bssl::UniquePtr<EVP_PKEY> ParsePrivateKey(int type, const uint8_t *in,
+                                                 size_t len) {
+  const uint8_t *ptr = in;
+  bssl::UniquePtr<EVP_PKEY> pkey(d2i_PrivateKey(type, nullptr, &ptr, len));
+  if (!pkey) {
+    return nullptr;
   }
 
-  derp = kExampleDSAKeyDER;
-  pkey.reset(d2i_PrivateKey(EVP_PKEY_DSA, nullptr, &derp,
-             sizeof(kExampleDSAKeyDER)));
-  if (!pkey || derp != kExampleDSAKeyDER + sizeof(kExampleDSAKeyDER)) {
-    fprintf(stderr, "Failed to import raw DSA key.\n");
-    return false;
-  }
+  EXPECT_EQ(in + len, ptr);
+  return pkey;
+}
 
-  derp = kExampleRSAKeyPKCS8;
-  pkey.reset(d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &derp,
-             sizeof(kExampleRSAKeyPKCS8)));
-  if (!pkey || derp != kExampleRSAKeyPKCS8 + sizeof(kExampleRSAKeyPKCS8)) {
-    fprintf(stderr, "Failed to import PKCS#8 RSA key.\n");
-    return false;
-  }
+TEST(EVPExtraTest, d2i_PrivateKey) {
+  EXPECT_TRUE(ParsePrivateKey(EVP_PKEY_RSA, kExampleRSAKeyDER,
+                              sizeof(kExampleRSAKeyDER)));
+  EXPECT_TRUE(ParsePrivateKey(EVP_PKEY_DSA, kExampleDSAKeyDER,
+                              sizeof(kExampleDSAKeyDER)));
+  EXPECT_TRUE(ParsePrivateKey(EVP_PKEY_RSA, kExampleRSAKeyPKCS8,
+                              sizeof(kExampleRSAKeyPKCS8)));
+  EXPECT_TRUE(
+      ParsePrivateKey(EVP_PKEY_EC, kExampleECKeyDER, sizeof(kExampleECKeyDER)));
 
-  derp = kExampleECKeyDER;
-  pkey.reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &derp,
-             sizeof(kExampleECKeyDER)));
-  if (!pkey || derp != kExampleECKeyDER + sizeof(kExampleECKeyDER)) {
-    fprintf(stderr, "Failed to import raw EC key.\n");
-    return false;
-  }
-
-  derp = kExampleBadECKeyDER;
-  pkey.reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &derp,
-             sizeof(kExampleBadECKeyDER)));
-  if (pkey) {
-    fprintf(stderr, "Imported invalid EC key.\n");
-    return false;
-  }
+  EXPECT_FALSE(ParsePrivateKey(EVP_PKEY_EC, kExampleBadECKeyDER,
+                               sizeof(kExampleBadECKeyDER)));
   ERR_clear_error();
 
   // Copy the input into a |malloc|'d vector to flag memory errors.
-  std::vector<uint8_t> copy(kExampleBadECKeyDER2, kExampleBadECKeyDER2 +
-                                                  sizeof(kExampleBadECKeyDER2));
-  derp = copy.data();
-  pkey.reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &derp, copy.size()));
-  if (pkey) {
-    fprintf(stderr, "Imported invalid EC key #2.\n");
-    return false;
-  }
+  std::vector<uint8_t> copy(
+      kExampleBadECKeyDER2,
+      kExampleBadECKeyDER2 + sizeof(kExampleBadECKeyDER2));
+  EXPECT_FALSE(ParsePrivateKey(EVP_PKEY_EC, copy.data(), copy.size()));
   ERR_clear_error();
 
-  return true;
-}
-
-int main(void) {
-  CRYPTO_library_init();
-  ERR_load_crypto_strings();
-
-  if (!TestEVP_DigestSignInit()) {
-    fprintf(stderr, "EVP_DigestSignInit failed\n");
-    ERR_print_errors_fp(stderr);
-    return 1;
-  }
-
-  if (!TestEVP_DigestVerifyInit()) {
-    fprintf(stderr, "EVP_DigestVerifyInit failed\n");
-    ERR_print_errors_fp(stderr);
-    return 1;
-  }
-
-  if (!TestEVP_DigestSignAlgorithm()) {
-    fprintf(stderr, "EVP_DigestSignInit failed\n");
-    ERR_print_errors_fp(stderr);
-    return 1;
-  }
-
-  if (!TestEVP_DigestVerifyInitFromAlgorithm()) {
-    fprintf(stderr, "EVP_DigestVerifyInitFromAlgorithm failed\n");
-    ERR_print_errors_fp(stderr);
-    return 1;
-  }
-
-  if (!TestBadPSSParameters()) {
-    fprintf(stderr, "TestBadPSSParameters failed\n");
-    ERR_print_errors_fp(stderr);
-    return 1;
-  }
-
-  if (!Testd2i_AutoPrivateKey()) {
-    fprintf(stderr, "Testd2i_AutoPrivateKey failed\n");
-    ERR_print_errors_fp(stderr);
-    return 1;
-  }
-
-  if (!TestEVP_PKCS82PKEY()) {
-    fprintf(stderr, "TestEVP_PKCS82PKEY failed\n");
-    ERR_print_errors_fp(stderr);
-    return 1;
-  }
-
-  if (!Testd2i_PrivateKey()) {
-    fprintf(stderr, "Testd2i_PrivateKey failed\n");
-    ERR_print_errors_fp(stderr);
-    return 1;
-  }
-
-  printf("PASS\n");
-  return 0;
+  // Test that an RSA key may not be imported as an EC key.
+  EXPECT_FALSE(ParsePrivateKey(EVP_PKEY_EC, kExampleRSAKeyPKCS8,
+                               sizeof(kExampleRSAKeyPKCS8)));
+  ERR_clear_error();
 }
diff --git a/src/crypto/evp/evp_test.cc b/src/crypto/evp/evp_test.cc
index 7fedc15..6ca250e 100644
--- a/src/crypto/evp/evp_test.cc
+++ b/src/crypto/evp/evp_test.cc
@@ -51,33 +51,30 @@
  * ====================================================================
  */
 
+#include <openssl/evp.h>
+
 #include <stdio.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
 
-#if defined(_MSC_VER)
-#pragma warning(push)
-#pragma warning(disable: 4702)
-#endif
+OPENSSL_MSVC_PRAGMA(warning(push))
+OPENSSL_MSVC_PRAGMA(warning(disable: 4702))
 
 #include <map>
 #include <string>
+#include <utility>
 #include <vector>
 
-#if defined(_MSC_VER)
-#pragma warning(pop)
-#endif
+OPENSSL_MSVC_PRAGMA(warning(pop))
 
-#include <openssl/bio.h>
+#include <openssl/bytestring.h>
 #include <openssl/crypto.h>
 #include <openssl/digest.h>
 #include <openssl/err.h>
-#include <openssl/evp.h>
-#include <openssl/pem.h>
+#include <openssl/rsa.h>
 
 #include "../test/file_test.h"
-#include "../test/scoped_types.h"
 
 
 // evp_test dispatches between multiple test types. PrivateKey tests take a key
@@ -103,34 +100,103 @@
   return nullptr;
 }
 
-using KeyMap = std::map<std::string, EVP_PKEY*>;
+static int GetKeyType(FileTest *t, const std::string &name) {
+  if (name == "RSA") {
+    return EVP_PKEY_RSA;
+  }
+  if (name == "EC") {
+    return EVP_PKEY_EC;
+  }
+  if (name == "DSA") {
+    return EVP_PKEY_DSA;
+  }
+  t->PrintLine("Unknown key type: '%s'", name.c_str());
+  return EVP_PKEY_NONE;
+}
 
-// ImportPrivateKey evaluates a PrivateKey test in |t| and writes the resulting
-// private key to |key_map|.
-static bool ImportPrivateKey(FileTest *t, KeyMap *key_map) {
+static int GetRSAPadding(FileTest *t, int *out, const std::string &name) {
+  if (name == "PKCS1") {
+    *out = RSA_PKCS1_PADDING;
+    return true;
+  }
+  if (name == "PSS") {
+    *out = RSA_PKCS1_PSS_PADDING;
+    return true;
+  }
+  if (name == "OAEP") {
+    *out = RSA_PKCS1_OAEP_PADDING;
+    return true;
+  }
+  t->PrintLine("Unknown RSA padding mode: '%s'", name.c_str());
+  return false;
+}
+
+using KeyMap = std::map<std::string, bssl::UniquePtr<EVP_PKEY>>;
+
+static bool ImportKey(FileTest *t, KeyMap *key_map,
+                      EVP_PKEY *(*parse_func)(CBS *cbs),
+                      int (*marshal_func)(CBB *cbb, const EVP_PKEY *key)) {
+  std::vector<uint8_t> input;
+  if (!t->GetBytes(&input, "Input")) {
+    return false;
+  }
+
+  CBS cbs;
+  CBS_init(&cbs, input.data(), input.size());
+  bssl::UniquePtr<EVP_PKEY> pkey(parse_func(&cbs));
+  if (!pkey) {
+    return false;
+  }
+
+  std::string key_type;
+  if (!t->GetAttribute(&key_type, "Type")) {
+    return false;
+  }
+  if (EVP_PKEY_id(pkey.get()) != GetKeyType(t, key_type)) {
+    t->PrintLine("Bad key type.");
+    return false;
+  }
+
+  // The key must re-encode correctly.
+  bssl::ScopedCBB cbb;
+  uint8_t *der;
+  size_t der_len;
+  if (!CBB_init(cbb.get(), 0) ||
+      !marshal_func(cbb.get(), pkey.get()) ||
+      !CBB_finish(cbb.get(), &der, &der_len)) {
+    return false;
+  }
+  bssl::UniquePtr<uint8_t> free_der(der);
+
+  std::vector<uint8_t> output = input;
+  if (t->HasAttribute("Output") &&
+      !t->GetBytes(&output, "Output")) {
+    return false;
+  }
+  if (!t->ExpectBytesEqual(output.data(), output.size(), der, der_len)) {
+    t->PrintLine("Re-encoding the key did not match.");
+    return false;
+  }
+
+  // Save the key for future tests.
   const std::string &key_name = t->GetParameter();
   if (key_map->count(key_name) > 0) {
     t->PrintLine("Duplicate key '%s'.", key_name.c_str());
     return false;
   }
-  const std::string &block = t->GetBlock();
-  ScopedBIO bio(BIO_new_mem_buf(const_cast<char*>(block.data()), block.size()));
-  if (!bio) {
-    return false;
-  }
-  ScopedEVP_PKEY pkey(PEM_read_bio_PrivateKey(bio.get(), nullptr, 0, nullptr));
-  if (!pkey) {
-    t->PrintLine("Error reading private key.");
-    return false;
-  }
-  (*key_map)[key_name] = pkey.release();
+  (*key_map)[key_name] = std::move(pkey);
   return true;
 }
 
 static bool TestEVP(FileTest *t, void *arg) {
   KeyMap *key_map = reinterpret_cast<KeyMap*>(arg);
   if (t->GetType() == "PrivateKey") {
-    return ImportPrivateKey(t, key_map);
+    return ImportKey(t, key_map, EVP_parse_private_key,
+                     EVP_marshal_private_key);
+  }
+
+  if (t->GetType() == "PublicKey") {
+    return ImportKey(t, key_map, EVP_parse_public_key, EVP_marshal_public_key);
   }
 
   int (*key_op_init)(EVP_PKEY_CTX *ctx);
@@ -156,16 +222,15 @@
     t->PrintLine("Could not find key '%s'.", key_name.c_str());
     return false;
   }
-  EVP_PKEY *key = (*key_map)[key_name];
+  EVP_PKEY *key = (*key_map)[key_name].get();
 
-  std::vector<uint8_t> input, output;
-  if (!t->GetBytes(&input, "Input") ||
-      !t->GetBytes(&output, "Output")) {
+  std::vector<uint8_t> input;
+  if (!t->GetBytes(&input, "Input")) {
     return false;
   }
 
   // Set up the EVP_PKEY_CTX.
-  ScopedEVP_PKEY_CTX ctx(EVP_PKEY_CTX_new(key, nullptr));
+  bssl::UniquePtr<EVP_PKEY_CTX> ctx(EVP_PKEY_CTX_new(key, nullptr));
   if (!ctx || !key_op_init(ctx.get())) {
     return false;
   }
@@ -176,9 +241,30 @@
       return false;
     }
   }
+  if (t->HasAttribute("RSAPadding")) {
+    int padding;
+    if (!GetRSAPadding(t, &padding, t->GetAttributeOrDie("RSAPadding")) ||
+        !EVP_PKEY_CTX_set_rsa_padding(ctx.get(), padding)) {
+      return false;
+    }
+  }
+  if (t->HasAttribute("PSSSaltLength") &&
+      !EVP_PKEY_CTX_set_rsa_pss_saltlen(
+          ctx.get(), atoi(t->GetAttributeOrDie("PSSSaltLength").c_str()))) {
+    return false;
+  }
+  if (t->HasAttribute("MGF1Digest")) {
+    const EVP_MD *digest = GetDigest(t, t->GetAttributeOrDie("MGF1Digest"));
+    if (digest == nullptr ||
+        !EVP_PKEY_CTX_set_rsa_mgf1_md(ctx.get(), digest)) {
+      return false;
+    }
+  }
 
   if (t->GetType() == "Verify") {
-    if (!EVP_PKEY_verify(ctx.get(), output.data(), output.size(), input.data(),
+    std::vector<uint8_t> output;
+    if (!t->GetBytes(&output, "Output") ||
+        !EVP_PKEY_verify(ctx.get(), output.data(), output.size(), input.data(),
                          input.size())) {
       // ECDSA sometimes doesn't push an error code. Push one on the error queue
       // so it's distinguishable from other errors.
@@ -189,7 +275,7 @@
   }
 
   size_t len;
-  std::vector<uint8_t> actual;
+  std::vector<uint8_t> actual, output;
   if (!key_op(ctx.get(), nullptr, &len, input.data(), input.size())) {
     return false;
   }
@@ -198,13 +284,14 @@
     return false;
   }
   actual.resize(len);
-  if (!t->ExpectBytesEqual(output.data(), output.size(), actual.data(), len)) {
+  if (!t->GetBytes(&output, "Output") ||
+      !t->ExpectBytesEqual(output.data(), output.size(), actual.data(), len)) {
     return false;
   }
   return true;
 }
 
-int main(int argc, char **argv) {
+int main(int argc, char *argv[]) {
   CRYPTO_library_init();
   if (argc != 2) {
     fprintf(stderr, "%s <test file.txt>\n", argv[0]);
@@ -212,11 +299,5 @@
   }
 
   KeyMap map;
-  int ret = FileTestMain(TestEVP, &map, argv[1]);
-  // TODO(davidben): When we can rely on a move-aware std::map, make KeyMap a
-  // map of ScopedEVP_PKEY instead.
-  for (const auto &pair : map) {
-    EVP_PKEY_free(pair.second);
-  }
-  return ret;
+  return FileTestMain(TestEVP, &map, argv[1]);
 }
diff --git a/src/crypto/evp/evp_tests.txt b/src/crypto/evp/evp_tests.txt
index 97ddaa0..e70ebbc 100644
--- a/src/crypto/evp/evp_tests.txt
+++ b/src/crypto/evp/evp_tests.txt
@@ -1,47 +1,89 @@
 # Public key algorithm tests
 
-# Private keys used for PKEY operations.
+# Keys used for PKEY operations.
 
 # RSA 2048 bit key.
-
 PrivateKey = RSA-2048
------BEGIN PRIVATE KEY-----
-MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDNAIHqeyrh6gbV
-n3xz2f+5SglhXC5Lp8Y2zvCN01M+wxhVJbAVx2m5mnfWclv5w1Mqm25fZifV+4UW
-B2jT3anL01l0URcX3D0wnS/EfuQfl+Mq23+d2GShxHZ6Zm7NcbwarPXnUX9LOFlP
-6psF5C1a2pkSAIAT5FMWpNm7jtCGuI0odYusr5ItRqhotIXSOcm66w4rZFknEPQr
-LR6gpLSALAvsqzKPimiwBzvbVG/uqYCdKEmRKzkMFTK8finHZY+BdfrkbzQzL/h7
-yrPkBkm5hXeGnaDqcYNT8HInVIhpE2SHYNEivmduD8SD3SD/wxvalqMZZsmqLnWt
-A95H4cRPAgMBAAECggEAYCl6x5kbFnoG1rJHWLjL4gi+ubLZ7Jc4vYD5Ci41AF3X
-ziktnim6iFvTFv7x8gkTvArJDWsICLJBTYIQREHYYkozzgIzyPeApIs3Wv8C12cS
-IopwJITbP56+zM+77hcJ26GCgA2Unp5CFuC/81WDiPi9kNo3Oh2CdD7D+90UJ/0W
-glplejFpEuhpU2URfKL4RckJQF/KxV+JX8FdIDhsJu54yemQdQKaF4psHkzwwgDo
-qc+yfp0Vb4bmwq3CKxqEoc1cpbJ5CHXXlAfISzUjlcuBzD/tW7BDtp7eDAcgRVAC
-XO6MX0QBcLYSC7SOD3R7zY9SIRCFDfBDxCjf0YcFMQKBgQD2+WG0fLwDXTrt68fe
-hQqVa2Xs25z2B2QGPxWqSFU8WNly/mZ1BW413f3De/O58vYi7icTNyVoScm+8hdv
-6PfD+LuRujdN1TuvPeyBTSvewQwf3IjN0Wh28mse36PwlBl+301C/x+ylxEDuJjK
-hZxCcocIaoQqtBC7ac8tNa9r4wKBgQDUfnJKf/QQSLJwwlJKQQGHi3MVm7c9PbwY
-eyIOY1s1NPluJDoYTZP4YLa/u2txwe2aHh9FhYMCPDAelqaSwaCLU9DsnKkQEA2A
-RR47fcagG6xK7O+N95iEa8I1oIy7os9MBoBMwRIZ6VYIxxTj8UMNSR+tu6MqV1Gg
-T5d0WDTJpQKBgCHyRSu5uV39AoyRS/eZ8cp36JqV1Q08FtOE+EVfi9evnrPfo9WR
-2YQt7yNfdjCo5IwIj/ZkLhAXlFNakz4el2+oUJ/HKLLaDEoaCNf883q6rh/zABrK
-HcG7sF2d/7qhoJ9/se7zgjfZ68zHIrkzhDbd5xGREnmMJoCcGo3sQyBhAoGAH3UQ
-qmLC2N5KPFMoJ4H0HgLQ6LQCrnhDLkScSBEBYaEUA/AtAYgKjcyTgVLXlyGkcRpg
-esRHHr+WSBD5W+R6ReYEmeKfTJdzyDdzQE9gZjdyjC0DUbsDwybIu3OnIef6VEDq
-IXK7oUZfzDDcsNn4mTDoFaoff5cpqFfgDgM43VkCgYBNHw11b+d+AQmaZS9QqIt7
-aF3FvwCYHV0jdv0Mb+Kc1bY4c0R5MFpzrTwVmdOerjuuA1+9b+0Hwo3nBZM4eaBu
-SOamA2hu2OJWCl9q8fLCT69KqWDjghhvFe7c6aJJGucwaA3Uz3eLcPqoaCarMiNH
-fMkTd7GabVourqIZdgvu1Q==
------END PRIVATE KEY-----
+Type = RSA
+Input = 308204bc020100300d06092a864886f70d0101010500048204a6308204a20201000282010100cd0081ea7b2ae1ea06d59f7c73d9ffb94a09615c2e4ba7c636cef08dd3533ec3185525b015c769b99a77d6725bf9c3532a9b6e5f6627d5fb85160768d3dda9cbd35974511717dc3d309d2fc47ee41f97e32adb7f9dd864a1c4767a666ecd71bc1aacf5e7517f4b38594fea9b05e42d5ada9912008013e45316a4d9bb8ed086b88d28758bacaf922d46a868b485d239c9baeb0e2b64592710f42b2d1ea0a4b4802c0becab328f8a68b0073bdb546feea9809d2849912b390c1532bc7e29c7658f8175fae46f34332ff87bcab3e40649b98577869da0ea718353f0722754886913648760d122be676e0fc483dd20ffc31bda96a31966c9aa2e75ad03de47e1c44f02030100010282010060297ac7991b167a06d6b24758b8cbe208beb9b2d9ec9738bd80f90a2e35005dd7ce292d9e29ba885bd316fef1f20913bc0ac90d6b0808b2414d82104441d8624a33ce0233c8f780a48b375aff02d76712228a702484db3f9ebecccfbbee1709dba182800d949e9e4216e0bff3558388f8bd90da373a1d82743ec3fbdd1427fd16825a657a316912e8695365117ca2f845c909405fcac55f895fc15d20386c26ee78c9e99075029a178a6c1e4cf0c200e8a9cfb27e9d156f86e6c2adc22b1a84a1cd5ca5b2790875d79407c84b352395cb81cc3fed5bb043b69ede0c07204550025cee8c5f440170b6120bb48e0f747bcd8f522110850df043c428dfd187053102818100f6f961b47cbc035d3aedebc7de850a956b65ecdb9cf60764063f15aa48553c58d972fe6675056e35ddfdc37bf3b9f2f622ee271337256849c9bef2176fe8f7c3f8bb91ba374dd53baf3dec814d2bdec10c1fdc88cdd16876f26b1edfa3f094197edf4d42ff1fb2971103b898ca859c427287086a842ab410bb69cf2d35af6be302818100d47e724a7ff41048b270c2524a4101878b73159bb73d3dbc187b220e635b3534f96e243a184d93f860b6bfbb6b71c1ed9a1e1f458583023c301e96a692c1a08b53d0ec9ca910100d80451e3b7dc6a01bac4aecef8df798846bc235a08cbba2cf4c06804cc11219e95608c714e3f1430d491fadbba32a5751a04f97745834c9a502818021f2452bb9b95dfd028c914bf799f1ca77e89a95d50d3c16d384f8455f8bd7af9eb3dfa3d591d9842def235f7630a8e48c088ff6642e101794535a933e1e976fa8509fc728b2da0c4a1a08d7fcf37abaae1ff3001aca1dc1bbb05d9dffbaa1a09f7fb1eef38237d9ebccc722b9338436dde7119112798c26809c1a8dec4320610281801f7510aa62c2d8de4a3c53282781f41e02d0e8b402ae78432e449c48110161a11403f02d01880a8dcc938152d79721a4711a607ac4471ebf964810f95be47a45e60499e29f4c9773c83773404f606637728c2d0351bb03c326c8bb73a721e7fa5440ea2172bba1465fcc30dcb0d9f89930e815aa1f7f9729a857e00e0338dd590281804d1f0d756fe77e01099a652f50a88b7b685dc5bf00981d5d2376fd0c6fe29cd5b638734479305a73ad3c1599d39eae3bae035fbd6fed07c28de705933879a06e48e6a603686ed8e2560a5f6af1f2c24faf4aa960e382186f15eedce9a2491ae730680dd4cf778b70faa86826ab3223477cc91377b19a6d5a2eaea219760beed5
+
+# The public half of the same key encoded as a SubjectPublicKeyInfo.
+PublicKey = RSA-2048-SPKI
+Type = RSA
+Input = 30820122300d06092a864886f70d01010105000382010f003082010a0282010100cd0081ea7b2ae1ea06d59f7c73d9ffb94a09615c2e4ba7c636cef08dd3533ec3185525b015c769b99a77d6725bf9c3532a9b6e5f6627d5fb85160768d3dda9cbd35974511717dc3d309d2fc47ee41f97e32adb7f9dd864a1c4767a666ecd71bc1aacf5e7517f4b38594fea9b05e42d5ada9912008013e45316a4d9bb8ed086b88d28758bacaf922d46a868b485d239c9baeb0e2b64592710f42b2d1ea0a4b4802c0becab328f8a68b0073bdb546feea9809d2849912b390c1532bc7e29c7658f8175fae46f34332ff87bcab3e40649b98577869da0ea718353f0722754886913648760d122be676e0fc483dd20ffc31bda96a31966c9aa2e75ad03de47e1c44f0203010001
+
+# The same key but with missing parameters rather than a NULL.
+PublicKey = RSA-2048-SPKI-Invalid
+Input = 30820120300b06092a864886f70d0101010382010f003082010a0282010100cd0081ea7b2ae1ea06d59f7c73d9ffb94a09615c2e4ba7c636cef08dd3533ec3185525b015c769b99a77d6725bf9c3532a9b6e5f6627d5fb85160768d3dda9cbd35974511717dc3d309d2fc47ee41f97e32adb7f9dd864a1c4767a666ecd71bc1aacf5e7517f4b38594fea9b05e42d5ada9912008013e45316a4d9bb8ed086b88d28758bacaf922d46a868b485d239c9baeb0e2b64592710f42b2d1ea0a4b4802c0becab328f8a68b0073bdb546feea9809d2849912b390c1532bc7e29c7658f8175fae46f34332ff87bcab3e40649b98577869da0ea718353f0722754886913648760d122be676e0fc483dd20ffc31bda96a31966c9aa2e75ad03de47e1c44f0203010001
+Error = DECODE_ERROR
+
+# The same key but with an incorrectly-encoded length prefix.
+PublicKey = RSA-2048-SPKI-Invalid2
+Input = 3083000122300d06092a864886f70d01010105000382010f003082010a0282010100cd0081ea7b2ae1ea06d59f7c73d9ffb94a09615c2e4ba7c636cef08dd3533ec3185525b015c769b99a77d6725bf9c3532a9b6e5f6627d5fb85160768d3dda9cbd35974511717dc3d309d2fc47ee41f97e32adb7f9dd864a1c4767a666ecd71bc1aacf5e7517f4b38594fea9b05e42d5ada9912008013e45316a4d9bb8ed086b88d28758bacaf922d46a868b485d239c9baeb0e2b64592710f42b2d1ea0a4b4802c0becab328f8a68b0073bdb546feea9809d2849912b390c1532bc7e29c7658f8175fae46f34332ff87bcab3e40649b98577869da0ea718353f0722754886913648760d122be676e0fc483dd20ffc31bda96a31966c9aa2e75ad03de47e1c44f0203010001
+Error = DECODE_ERROR
+
+# RSA 512 bit key.
+PrivateKey = RSA-512
+Type = RSA
+Input = 30820154020100300d06092a864886f70d01010105000482013e3082013a020100024100dd20403d976a38c9d79152d87b5c8e9f05033eadd7b7de709bf5b0c4a5182a97d18483526b02362b992e154a9f37faa396ca2685cdab8fec09877ebe705f4dd70203010001024055bebcca655d7e39de8a6eaa9d636db682161907064039544755c53eeb99ec618c03a210dbc61471eaba10c5c365c9726d6b7a96f54d455f7d168d49367270e1022100f21a05d9fd6817301ce49ce10448f9bdd44f5ef5b7557cd7d83155db46382ae7022100e9d1f7157783db2feab1936954ddc4e83aa365695868144cda1be6813b61d791022100d6001eb0040920860ce41fafdf23ca6dfbdf74e6e9f98cf3164cf5c16f9e727d02206f6f73f4b52b10517be6f9bc5f87fa0a3bb817e2e711636b651f9af1c85d4f21022063eff2e57f5b4ca20342cfe793e25526624e3692f192461f9e1ce7f13f2d72c8
+
+# RSA 515 bit key.
+PrivateKey = RSA-515
+Type = RSA
+Input = 30820157020100300d06092a864886f70d0101010500048201413082013d0201000241054fa166e205e658bbe8a2dc35311c0c2b75b7e4569fd9642c8bae809279271fc824f26baa1166ea46298ca63379ea76adbada2b61e5066820a35beaec1aca227f020301000102410266c972be0d30e53ac2acb1aa13b4bd0401cccf212452a66b4615f7e943831f67b4ca48560582d0ca886044aaaaf87945252a848c1947944186e6eb83969bf91102210309e631761842cc8a2ccfd372c20a9cba21de1a199c30ab440bc6b51079f4e825022101bf715c1db432627ca7c29a293b9210f2eff1e92d12f306ebaa5334f8ee03dcd30221018ac58a765f2b8f37d434081fe5ff92b81735ead2f263f4968ccf63d61fbe3d0d0221015b247a1159a2d5a25d0db049593c6405f77f3a278c521d066e290c2a2d8fb59d0221026224aa31fd95c14d24fd03b8a195bba4cc88df7c37f5370a5ab19f882f1404d6
 
 # EC P-256 key
-
 PrivateKey = P-256
------BEGIN PRIVATE KEY-----
-MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgiocvtiiTxNH/xbnw
-+RdYBp+DUuCPoFpJ+NuSbLVyhyWhRANCAAQsFQ9CnOcPIWwlLPXgYs4fY5zV0WXH
-+JQkBywnGX14szuSDpXNtmTpkNzwz+oNlOKo5q+dDlgFbmUxBJJbn+bJ
------END PRIVATE KEY-----
+Type = EC
+Input = 308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b02010104208a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725a144034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9
+
+# The same key as above with the optional public key omitted.
+PrivateKey = P-256-MissingPublic
+Type = EC
+Input = 3041020100301306072a8648ce3d020106082a8648ce3d0301070427302502010104208a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725
+
+# The same key as above with redundant parameters.
+PrivateKey = P-256-ExtraParameters
+Type = EC
+Input = 308193020100301306072a8648ce3d020106082a8648ce3d0301070479307702010104208a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725a00a06082a8648ce3d030107a144034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9
+# The key re-encodes with the parameters removed.
+Output = 308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b02010104208a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725a144034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9
+
+# The same key, but with the redundant parameters in the ECPrivateKey mismatched.
+PrivateKey = P-256-BadInnerParameters
+Input = 308190020100301306072a8648ce3d020106082a8648ce3d0301070476307402010104208a872fb62893c4d1ffc5b9f0f91758069f8352e08fa05a49f8db926cb5728725a00706052b81040022a144034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9
+Error = GROUP_MISMATCH
+
+# The public half of the same key encoded as a PublicKey.
+PublicKey = P-256-SPKI
+Type = EC
+Input = 3059301306072a8648ce3d020106082a8648ce3d030107034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9
+
+# The same as above, but with the curve explicitly spelled out.
+PublicKey = P-256-SPKI
+Input = 3082014b3082010306072a8648ce3d02013081f7020101302c06072a8648ce3d0101022100ffffffff00000001000000000000000000000000ffffffffffffffffffffffff305b0420ffffffff00000001000000000000000000000000fffffffffffffffffffffffc04205ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b031500c49d360886e704936a6678e1139d26b7819f7e900441046b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c2964fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5022100ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551020101034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9
+Error = DECODE_ERROR
+
+# The same as above, but with trailing data after the curve name.
+PublicKey = P-256-SPKI
+Input = 305b301506072a8648ce3d020106082a8648ce3d0301070500034200042c150f429ce70f216c252cf5e062ce1f639cd5d165c7f89424072c27197d78b33b920e95cdb664e990dcf0cfea0d94e2a8e6af9d0e58056e653104925b9fe6c9
+Error = DECODE_ERROR
+
+# A DSA private key.
+PrivateKey = DSA-1024
+Type = DSA
+Input = 308202650201003082023906072a8648ce3804013082022c02820101009e12fab3de12213501dd82aa10ca2d101d2d4ebfef4d2a3f8daa0fe0cedad8d6af85616aa2f3252c0a2b5a6db09e6f14900e0ddb8311876dd8f9669525f99ed65949e184d5064793271169a228680b95ec12f59a8e20b21f2b58eb2a2012d35bde2ee351822fe8f32d0a330565dcce5c672b7259c14b2433d0b5b2ca2b2db0ab626e8f13f47fe0345d904e7294bb038e9ce21a9e580b83356278706cfe768436c69de149ccff98b4aab8cb4f6385c9f102ce59346eaeef27e0ad222d53d6e89cc8cde5776dd00057b03f2d88ab3cedbafd7b585f0b7f7835e17a3728bbf25ea62572f245dc111f3ce39cb6ffacc31b0a2790e7bde90224ea9b09315362af3d2b022100f381dcf53ebf724f8b2e5ca82c010fb4b5eda9358d0fd88ed278589488b54fc3028201000c402a725dcc3a62e02bf4cf43cd17f4a493591220223669cf4193edab423ad08dfb552e308a6a57a5ffbc7cd0fb2087f81f8df0cb08ab2133287d2b6968714a94f633c940845a48a3e16708dde761cc6a8eab2d84db21b6ea5b07681493cc9c31fbc368b243f6ddf8c932a8b4038f44e7b15ca876344a147859f2b43b39458668ad5e0a1a9a669546dd2812e3b3617a0aef99d58e3bb4cc87fd94225e01d2dcc469a77268146c51918f18e8b4d70aa1f0c7623bcc52cf3731d38641b2d2830b7eecb2f09552ff137d046e494e7f33c3590002b16d1b97d936fda28f90c3ed3ca35338168ac16f77c3c57adc2e8f7c6c2256e41a5f65450590dbb5bcf06d66610423022100b0c768702743bc51242993a971a52889795444f7c6452203d0ce84fe6117d46e
+
+# A DSA public key.
+PublicKey = DSA-1024-SPKI
+Type = DSA
+Input = 308201b73082012c06072a8648ce3804013082011f02818100b3429b8b128c9079f9b72e86857e98d265e5d91661ed8b5f4cc56e5eed1e571da30186983a9dd76297eab73ee13a1db841f8800d04a7cab478af6cde2ea4a2868531af169a24858c6268efa39ceb7ed0d4227eb5bbb01124a2a5a26038c7bcfb8cc827f68f5202345166e4718596799b65c9def82828ce44e62e38e41a0d24b1021500c5a56c81ddd87f47e676546c56d05706421624cf0281810094de40d27314fe929e47ff9b1ac65cfc73ef38c4d381c890be6217b15039ae18190e6b421af8c0bda35a5cfd050f58ae2644adce83e68c8e5ba11729df56bbb21e227a60b816cc033fa799a38fe1ba5b4aa1801b6f841ce3df99feb3b4fb96950c960af13fa2ce920aabc12dd24ad2044a35063ea0e25f67f560f4cfbdc5598303818400028180258c30ebbb7f34fdc873ce679f6cea373c7886d75d4421b90920db034daedd292c64d8edd8cdbdd7f3ad23d74cfa2135247d0cef6ecf2e14f99e19d22a8c1266bd8fb8719c0e5667c716c45c7adbdabe548085bdad2dfee636f8d52fd6adb2193df6c4f0520fbd171b91882e0e4f321f8250ffecf4dbea00e114427d3ef96c1a
+
+# The same key as above, but without the parameters.
+PublicKey = DSA-1024-SPKI-No-Params
+Type = DSA
+Input = 308192300906072a8648ce38040103818400028180258c30ebbb7f34fdc873ce679f6cea373c7886d75d4421b90920db034daedd292c64d8edd8cdbdd7f3ad23d74cfa2135247d0cef6ecf2e14f99e19d22a8c1266bd8fb8719c0e5667c716c45c7adbdabe548085bdad2dfee636f8d52fd6adb2193df6c4f0520fbd171b91882e0e4f321f8250ffecf4dbea00e114427d3ef96c1a
+
 
 # RSA tests
 
@@ -55,18 +97,21 @@
 Input = "0123456789ABCDEF1234"
 Output = c09d402423cbf233d26cae21f954547bc43fe80fd41360a0336cfdbe9aedad05bef6fd2eaee6cd60089a52482d4809a238149520df3bdde4cb9e23d9307b05c0a6f327052325a29adf2cc95b66523be7024e2a585c3d4db15dfbe146efe0ecdc0402e33fe5d40324ee96c5c3edd374a15cdc0f5d84aa243c0f07e188c6518fbfceae158a9943be398e31097da81b62074f626eff738be6160741d5a26957a482b3251fd85d8df78b98148459de10aa93305dbb4a5230aa1da291a9b0e481918f99b7638d72bb687f97661d304ae145d64a474437a4ef39d7b8059332ddeb07e92bf6e0e3acaf8afedc93795e4511737ec1e7aab6d5bc9466afc950c1c17b48ad
 
+Verify = RSA-2048-SPKI
+Digest = SHA1
+Input = "0123456789ABCDEF1234"
+Output = c09d402423cbf233d26cae21f954547bc43fe80fd41360a0336cfdbe9aedad05bef6fd2eaee6cd60089a52482d4809a238149520df3bdde4cb9e23d9307b05c0a6f327052325a29adf2cc95b66523be7024e2a585c3d4db15dfbe146efe0ecdc0402e33fe5d40324ee96c5c3edd374a15cdc0f5d84aa243c0f07e188c6518fbfceae158a9943be398e31097da81b62074f626eff738be6160741d5a26957a482b3251fd85d8df78b98148459de10aa93305dbb4a5230aa1da291a9b0e481918f99b7638d72bb687f97661d304ae145d64a474437a4ef39d7b8059332ddeb07e92bf6e0e3acaf8afedc93795e4511737ec1e7aab6d5bc9466afc950c1c17b48ad
+
 # Digest too long
 Sign = RSA-2048
 Digest = SHA1
 Input = "0123456789ABCDEF12345"
-Output =
 Error = INVALID_DIGEST_LENGTH
 
 # Digest too short
 Sign = RSA-2048
 Digest = SHA1
 Input = "0123456789ABCDEF12345"
-Output =
 Error = INVALID_DIGEST_LENGTH
 
 # Mismatched digest
@@ -118,6 +163,253 @@
 Output = 49525db4d44c755e560cba980b1d85ea604b0e077fcadd4ba44072a3487bbddb835016200a7d8739cce2dc3223d9c20cbdd25059ab02277f1f21318efd18e21038ec89aa9d40680987129e8b41ba33bceb86518bdf47268b921cce2037acabca6575d832499538d6f40cdba0d40bd7f4d8ea6ca6e2eec87f294efc971407857f5d7db09f6a7b31e301f571c6d82a5e3d08d2bb3a36e673d28b910f5bec57f0fcc4d968fd7c94d0b9226dec17f5192ad8b42bcab6f26e1bea1fdc3b958199acb00f14ebcb2a352f3afcedd4c09000128a603bbeb9696dea13040445253972d46237a25c7845e3b464e6984c2348ea1f1210a9ff0b00d2d72b50db00c009bb39f9
 Error = BAD_SIGNATURE
 
+
+# RSA-PSS tests.
+
+# Zero salt length makes the output deterministic
+Sign = RSA-2048
+RSAPadding = PSS
+PSSSaltLength = 0
+Digest = SHA256
+Input = "0123456789ABCDEF0123456789ABCDEF"
+Output = 4de433d5844043ef08d354da03cb29068780d52706d7d1e4d50efb7d58c9d547d83a747ddd0635a96b28f854e50145518482cb49e963054621b53c60c498d07c16e9c2789c893cf38d4d86900de71bde463bd2761d1271e358c7480a1ac0bab930ddf39602ad1bc165b5d7436b516b7a7858e8eb7ab1c420eeb482f4d207f0e462b1724959320a084e13848d11d10fb593e66bf680bf6d3f345fc3e9c3de60abbac37e1c6ec80a268c8d9fc49626c679097aa690bc1aa662b95eb8db70390861aa0898229f9349b4b5fdd030d4928c47084708a933144be23bd3c6e661b85b2c0ef9ed36d498d5b7320e8194d363d4ad478c059bae804181965e0b81b663158a
+
+# Verify of above signature
+Verify = RSA-2048-SPKI
+RSAPadding = PSS
+PSSSaltLength = 0
+Digest = SHA256
+Input = "0123456789ABCDEF0123456789ABCDEF"
+Output = 4de433d5844043ef08d354da03cb29068780d52706d7d1e4d50efb7d58c9d547d83a747ddd0635a96b28f854e50145518482cb49e963054621b53c60c498d07c16e9c2789c893cf38d4d86900de71bde463bd2761d1271e358c7480a1ac0bab930ddf39602ad1bc165b5d7436b516b7a7858e8eb7ab1c420eeb482f4d207f0e462b1724959320a084e13848d11d10fb593e66bf680bf6d3f345fc3e9c3de60abbac37e1c6ec80a268c8d9fc49626c679097aa690bc1aa662b95eb8db70390861aa0898229f9349b4b5fdd030d4928c47084708a933144be23bd3c6e661b85b2c0ef9ed36d498d5b7320e8194d363d4ad478c059bae804181965e0b81b663158a
+
+# Auto-detected salt length
+Verify = RSA-2048-SPKI
+RSAPadding = PSS
+PSSSaltLength = -2
+Digest = SHA256
+Input = "0123456789ABCDEF0123456789ABCDEF"
+Output = 4de433d5844043ef08d354da03cb29068780d52706d7d1e4d50efb7d58c9d547d83a747ddd0635a96b28f854e50145518482cb49e963054621b53c60c498d07c16e9c2789c893cf38d4d86900de71bde463bd2761d1271e358c7480a1ac0bab930ddf39602ad1bc165b5d7436b516b7a7858e8eb7ab1c420eeb482f4d207f0e462b1724959320a084e13848d11d10fb593e66bf680bf6d3f345fc3e9c3de60abbac37e1c6ec80a268c8d9fc49626c679097aa690bc1aa662b95eb8db70390861aa0898229f9349b4b5fdd030d4928c47084708a933144be23bd3c6e661b85b2c0ef9ed36d498d5b7320e8194d363d4ad478c059bae804181965e0b81b663158a
+
+# Wrong digest
+Verify = RSA-2048-SPKI
+RSAPadding = PSS
+PSSSaltLength = 0
+Digest = SHA256
+Input = "00000000000000000000000000000000"
+Output = 4de433d5844043ef08d354da03cb29068780d52706d7d1e4d50efb7d58c9d547d83a747ddd0635a96b28f854e50145518482cb49e963054621b53c60c498d07c16e9c2789c893cf38d4d86900de71bde463bd2761d1271e358c7480a1ac0bab930ddf39602ad1bc165b5d7436b516b7a7858e8eb7ab1c420eeb482f4d207f0e462b1724959320a084e13848d11d10fb593e66bf680bf6d3f345fc3e9c3de60abbac37e1c6ec80a268c8d9fc49626c679097aa690bc1aa662b95eb8db70390861aa0898229f9349b4b5fdd030d4928c47084708a933144be23bd3c6e661b85b2c0ef9ed36d498d5b7320e8194d363d4ad478c059bae804181965e0b81b663158a
+Error = BAD_SIGNATURE
+
+# Digest too short
+Verify = RSA-2048-SPKI
+RSAPadding = PSS
+PSSSaltLength = 0
+Digest = SHA256
+Input = "0123456789ABCDEF0123456789ABCDE"
+Output = 4de433d5844043ef08d354da03cb29068780d52706d7d1e4d50efb7d58c9d547d83a747ddd0635a96b28f854e50145518482cb49e963054621b53c60c498d07c16e9c2789c893cf38d4d86900de71bde463bd2761d1271e358c7480a1ac0bab930ddf39602ad1bc165b5d7436b516b7a7858e8eb7ab1c420eeb482f4d207f0e462b1724959320a084e13848d11d10fb593e66bf680bf6d3f345fc3e9c3de60abbac37e1c6ec80a268c8d9fc49626c679097aa690bc1aa662b95eb8db70390861aa0898229f9349b4b5fdd030d4928c47084708a933144be23bd3c6e661b85b2c0ef9ed36d498d5b7320e8194d363d4ad478c059bae804181965e0b81b663158a
+Error = INVALID_DIGEST_LENGTH
+
+# Digest too long
+Verify = RSA-2048-SPKI
+RSAPadding = PSS
+PSSSaltLength = 0
+Digest = SHA256
+Input = "0123456789ABCDEF0123456789ABCDEF0"
+Output = 4de433d5844043ef08d354da03cb29068780d52706d7d1e4d50efb7d58c9d547d83a747ddd0635a96b28f854e50145518482cb49e963054621b53c60c498d07c16e9c2789c893cf38d4d86900de71bde463bd2761d1271e358c7480a1ac0bab930ddf39602ad1bc165b5d7436b516b7a7858e8eb7ab1c420eeb482f4d207f0e462b1724959320a084e13848d11d10fb593e66bf680bf6d3f345fc3e9c3de60abbac37e1c6ec80a268c8d9fc49626c679097aa690bc1aa662b95eb8db70390861aa0898229f9349b4b5fdd030d4928c47084708a933144be23bd3c6e661b85b2c0ef9ed36d498d5b7320e8194d363d4ad478c059bae804181965e0b81b663158a
+Error = INVALID_DIGEST_LENGTH
+
+# Wrong salt length
+Verify = RSA-2048
+RSAPadding = PSS
+PSSSaltLength = 2
+Digest = SHA256
+Input = "0123456789ABCDEF0123456789ABCDEF"
+Output = 4de433d5844043ef08d354da03cb29068780d52706d7d1e4d50efb7d58c9d547d83a747ddd0635a96b28f854e50145518482cb49e963054621b53c60c498d07c16e9c2789c893cf38d4d86900de71bde463bd2761d1271e358c7480a1ac0bab930ddf39602ad1bc165b5d7436b516b7a7858e8eb7ab1c420eeb482f4d207f0e462b1724959320a084e13848d11d10fb593e66bf680bf6d3f345fc3e9c3de60abbac37e1c6ec80a268c8d9fc49626c679097aa690bc1aa662b95eb8db70390861aa0898229f9349b4b5fdd030d4928c47084708a933144be23bd3c6e661b85b2c0ef9ed36d498d5b7320e8194d363d4ad478c059bae804181965e0b81b663158a
+Error = SLEN_CHECK_FAILED
+
+# Wrong salt length using implicit hash length
+Verify = RSA-2048
+RSAPadding = PSS
+PSSSaltLength = -1
+Digest = SHA256
+Input = "0123456789ABCDEF0123456789ABCDEF"
+Output = 4de433d5844043ef08d354da03cb29068780d52706d7d1e4d50efb7d58c9d547d83a747ddd0635a96b28f854e50145518482cb49e963054621b53c60c498d07c16e9c2789c893cf38d4d86900de71bde463bd2761d1271e358c7480a1ac0bab930ddf39602ad1bc165b5d7436b516b7a7858e8eb7ab1c420eeb482f4d207f0e462b1724959320a084e13848d11d10fb593e66bf680bf6d3f345fc3e9c3de60abbac37e1c6ec80a268c8d9fc49626c679097aa690bc1aa662b95eb8db70390861aa0898229f9349b4b5fdd030d4928c47084708a933144be23bd3c6e661b85b2c0ef9ed36d498d5b7320e8194d363d4ad478c059bae804181965e0b81b663158a
+Error = SLEN_CHECK_FAILED
+
+# Wrong MGF1 digest, SHA-1
+Verify = RSA-2048
+RSAPadding = PSS
+PSSSaltLength = 0
+Digest = SHA256
+MGF1Digest = SHA1
+Input = "0123456789ABCDEF0123456789ABCDEF"
+Output = 4de433d5844043ef08d354da03cb29068780d52706d7d1e4d50efb7d58c9d547d83a747ddd0635a96b28f854e50145518482cb49e963054621b53c60c498d07c16e9c2789c893cf38d4d86900de71bde463bd2761d1271e358c7480a1ac0bab930ddf39602ad1bc165b5d7436b516b7a7858e8eb7ab1c420eeb482f4d207f0e462b1724959320a084e13848d11d10fb593e66bf680bf6d3f345fc3e9c3de60abbac37e1c6ec80a268c8d9fc49626c679097aa690bc1aa662b95eb8db70390861aa0898229f9349b4b5fdd030d4928c47084708a933144be23bd3c6e661b85b2c0ef9ed36d498d5b7320e8194d363d4ad478c059bae804181965e0b81b663158a
+# If SHA-1, this input happens to succeed recovering a salt length, but it does
+# not match.
+Error = SLEN_CHECK_FAILED
+
+# Wrong MGF1 digest, SHA-384
+Verify = RSA-2048
+RSAPadding = PSS
+PSSSaltLength = 0
+Digest = SHA256
+MGF1Digest = SHA384
+Input = "0123456789ABCDEF0123456789ABCDEF"
+Output = 4de433d5844043ef08d354da03cb29068780d52706d7d1e4d50efb7d58c9d547d83a747ddd0635a96b28f854e50145518482cb49e963054621b53c60c498d07c16e9c2789c893cf38d4d86900de71bde463bd2761d1271e358c7480a1ac0bab930ddf39602ad1bc165b5d7436b516b7a7858e8eb7ab1c420eeb482f4d207f0e462b1724959320a084e13848d11d10fb593e66bf680bf6d3f345fc3e9c3de60abbac37e1c6ec80a268c8d9fc49626c679097aa690bc1aa662b95eb8db70390861aa0898229f9349b4b5fdd030d4928c47084708a933144be23bd3c6e661b85b2c0ef9ed36d498d5b7320e8194d363d4ad478c059bae804181965e0b81b663158a
+# If SHA-384, this input happens fail to recover the salt length altogether.
+Error = SLEN_RECOVERY_FAILED
+
+# The salt length is too large for the modulus (signing).
+Sign = RSA-2048
+RSAPadding = PSS
+PSSSaltLength = 223
+Digest = SHA256
+Input = "0123456789ABCDEF0123456789ABCDEF"
+Error = DATA_TOO_LARGE_FOR_KEY_SIZE
+
+# The salt length is too large for the modulus (verifying).
+Verify = RSA-2048
+RSAPadding = PSS
+PSSSaltLength = 223
+Digest = SHA256
+Input = "0123456789ABCDEF0123456789ABCDEF"
+Output = 4de433d5844043ef08d354da03cb29068780d52706d7d1e4d50efb7d58c9d547d83a747ddd0635a96b28f854e50145518482cb49e963054621b53c60c498d07c16e9c2789c893cf38d4d86900de71bde463bd2761d1271e358c7480a1ac0bab930ddf39602ad1bc165b5d7436b516b7a7858e8eb7ab1c420eeb482f4d207f0e462b1724959320a084e13848d11d10fb593e66bf680bf6d3f345fc3e9c3de60abbac37e1c6ec80a268c8d9fc49626c679097aa690bc1aa662b95eb8db70390861aa0898229f9349b4b5fdd030d4928c47084708a933144be23bd3c6e661b85b2c0ef9ed36d498d5b7320e8194d363d4ad478c059bae804181965e0b81b663158a
+Error = DATA_TOO_LARGE
+
+# The hash is too large for the modulus (signing).
+Sign = RSA-512
+RSAPadding = PSS
+PSSSaltLength = 0
+Digest = SHA512
+Input = "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"
+Error = DATA_TOO_LARGE_FOR_KEY_SIZE
+
+Sign = RSA-512
+RSAPadding = PSS
+PSSSaltLength = -2
+Digest = SHA512
+Input = "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"
+Error = DATA_TOO_LARGE_FOR_KEY_SIZE
+
+# The hash is too large for the modulus (verifying).
+Verify = RSA-512
+RSAPadding = PSS
+PSSSaltLength = 0
+Digest = SHA512
+Input = "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"
+Output = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+Error = DATA_TOO_LARGE
+
+Verify = RSA-512
+RSAPadding = PSS
+PSSSaltLength = -2
+Digest = SHA512
+Input = "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF"
+Output = 457001d9ca50a93385fc5ec721c9dbbe7a0f2e9e4a2f846a30a8811dde66347b83901c7492039243537c7a667fafffd69049bcbd36afd0010d9b425e2d8785c1
+Error = DATA_TOO_LARGE
+
+# Sample RSA-515 signature.
+Verify = RSA-515
+RSAPadding = PSS
+PSSSaltLength = 0
+Digest = SHA256
+Input = "0123456789ABCDEF0123456789ABCDEF"
+Output = 00c5926600f160f85e7fe950cfe123908384211cd8fe25c90cb8e8cc0593308e9aa2efe3acbf100ec1658ded8f72f506525fc2c44f06251b08d896e7bb3f05b135
+
+# The above, but with too few leading zeros.
+Verify = RSA-515
+RSAPadding = PSS
+PSSSaltLength = 0
+Digest = SHA256
+Input = "0123456789ABCDEF0123456789ABCDEF"
+Output = c5926600f160f85e7fe950cfe123908384211cd8fe25c90cb8e8cc0593308e9aa2efe3acbf100ec1658ded8f72f506525fc2c44f06251b08d896e7bb3f05b135
+Error = DATA_LEN_NOT_EQUAL_TO_MOD_LEN
+
+# The above, but with too many leading zeros.
+Verify = RSA-515
+RSAPadding = PSS
+PSSSaltLength = 0
+Digest = SHA256
+Input = "0123456789ABCDEF0123456789ABCDEF"
+Output = 0000c5926600f160f85e7fe950cfe123908384211cd8fe25c90cb8e8cc0593308e9aa2efe3acbf100ec1658ded8f72f506525fc2c44f06251b08d896e7bb3f05b135
+Error = DATA_LEN_NOT_EQUAL_TO_MOD_LEN
+
+# The above with an invalid leading byte. The top few bits of EM are required to
+# be cleared.
+Verify = RSA-515
+RSAPadding = PSS
+PSSSaltLength = 0
+Digest = SHA256
+Input = "0123456789ABCDEF0123456789ABCDEF"
+Output = 007f803c832a2090aea04013d9fa9c1630732a1625232826d235f0950f7050d3fb0eb06ef9ea8b260fad68e1165a2d770a8c7fc7a8aaa68620b021fc19c97e0041
+Error = FIRST_OCTET_INVALID
+
+# The above with an invalid trailing byte.
+Verify = RSA-515
+RSAPadding = PSS
+PSSSaltLength = 0
+Digest = SHA256
+Input = "0123456789ABCDEF0123456789ABCDEF"
+Output = 03e68555035891eb08d96c0967db22328cd892ad2856d88516ecb946bfdba732bb029b5c0dfa2119ed7349897d2324e95e86d91d0c4afc82700a36db8933abbf58
+Error = LAST_OCTET_INVALID
+
+# Non-zero salt length.
+Verify = RSA-2048-SPKI
+RSAPadding = PSS
+PSSSaltLength = 32
+Digest = SHA256
+Input = "0123456789ABCDEF0123456789ABCDEF"
+Output = 4065b284b0a6e98d4c41a8427007f878d8dd61599c87764fa79b8bf03f030c48127a4b1a5af5a6e0cf9055e57a1f47e5b0c0d8c600e78369cf1c39374899fac91a812692aa2216ba10900ce85a5cf7fddcafb726e4b83479c5bb7b3b84b08ffe183b4c2973aa3193ec7b7d4ea73bf1b579c6657b78ad7800e1975a4838c28ffe353fafef96be27b5c69677760a71b6f4df65ba6fe6b3565580a536f966928294c6e9ece807a90c1477779bcbfa3a250e98d685097c162c1c8c56ab02bd2e16eec7a019b51c067bdba7fa8cd5460796e22c607a8b6d12e1deb9be51c6943c46590f416800c48bb4cbb8c409d316573e59eadf7d3b9e6e5c2d0e570692e511e139
+
+# Non-zero salt length, wrong salt length.
+Verify = RSA-2048-SPKI
+RSAPadding = PSS
+PSSSaltLength = 31
+Digest = SHA256
+Input = "0123456789ABCDEF0123456789ABCDEF"
+Output = 4065b284b0a6e98d4c41a8427007f878d8dd61599c87764fa79b8bf03f030c48127a4b1a5af5a6e0cf9055e57a1f47e5b0c0d8c600e78369cf1c39374899fac91a812692aa2216ba10900ce85a5cf7fddcafb726e4b83479c5bb7b3b84b08ffe183b4c2973aa3193ec7b7d4ea73bf1b579c6657b78ad7800e1975a4838c28ffe353fafef96be27b5c69677760a71b6f4df65ba6fe6b3565580a536f966928294c6e9ece807a90c1477779bcbfa3a250e98d685097c162c1c8c56ab02bd2e16eec7a019b51c067bdba7fa8cd5460796e22c607a8b6d12e1deb9be51c6943c46590f416800c48bb4cbb8c409d316573e59eadf7d3b9e6e5c2d0e570692e511e139
+Error = SLEN_CHECK_FAILED
+
+# Non-zero salt length, match hash length.
+Verify = RSA-2048-SPKI
+RSAPadding = PSS
+PSSSaltLength = -1
+Digest = SHA256
+Input = "0123456789ABCDEF0123456789ABCDEF"
+Output = 4065b284b0a6e98d4c41a8427007f878d8dd61599c87764fa79b8bf03f030c48127a4b1a5af5a6e0cf9055e57a1f47e5b0c0d8c600e78369cf1c39374899fac91a812692aa2216ba10900ce85a5cf7fddcafb726e4b83479c5bb7b3b84b08ffe183b4c2973aa3193ec7b7d4ea73bf1b579c6657b78ad7800e1975a4838c28ffe353fafef96be27b5c69677760a71b6f4df65ba6fe6b3565580a536f966928294c6e9ece807a90c1477779bcbfa3a250e98d685097c162c1c8c56ab02bd2e16eec7a019b51c067bdba7fa8cd5460796e22c607a8b6d12e1deb9be51c6943c46590f416800c48bb4cbb8c409d316573e59eadf7d3b9e6e5c2d0e570692e511e139
+
+# Non-zero salt length, auto-detected.
+Verify = RSA-2048-SPKI
+RSAPadding = PSS
+PSSSaltLength = -2
+Digest = SHA256
+Input = "0123456789ABCDEF0123456789ABCDEF"
+Output = 4065b284b0a6e98d4c41a8427007f878d8dd61599c87764fa79b8bf03f030c48127a4b1a5af5a6e0cf9055e57a1f47e5b0c0d8c600e78369cf1c39374899fac91a812692aa2216ba10900ce85a5cf7fddcafb726e4b83479c5bb7b3b84b08ffe183b4c2973aa3193ec7b7d4ea73bf1b579c6657b78ad7800e1975a4838c28ffe353fafef96be27b5c69677760a71b6f4df65ba6fe6b3565580a536f966928294c6e9ece807a90c1477779bcbfa3a250e98d685097c162c1c8c56ab02bd2e16eec7a019b51c067bdba7fa8cd5460796e22c607a8b6d12e1deb9be51c6943c46590f416800c48bb4cbb8c409d316573e59eadf7d3b9e6e5c2d0e570692e511e139
+
+
+# RSA decrypt
+
+Decrypt = RSA-2048
+Input = 550af55a2904e7b9762352f8fb7fa235a9cb053aacb2d5fcb8ca48453cb2ee3619746c701abf2d4cc67003471a187900b05aa812bd25ed05c675dfc8c97a24a7bf49bd6214992cad766d05a9a2b57b74f26a737e0237b8b76c45f1f226a836d7cfbc75ba999bdbe48dbc09227aa46c88f21dccba7840141ad5a5d71fd122e6bd6ac3e564780dfe623fc1ca9b995a6037bf0bbd43b205a84ac5444f34202c05ce9113087176432476576de6ffff9a52ea57c08be3ec2f49676cb8e12f762ac71fa3c321e00ac988910c85ff52f93825666ce0d40ffaa0592078919d4493f46d95ccf76364c6d57760dd0b64805f9afc76a2365a5575ca301d5103f0ea76cb9a78
+Output = "Hello World"
+
+# Corrupted ciphertext
+Decrypt = RSA-2048
+Input = 550af55a2904e7b9762352f8fb7fa235a9cb053aacb2d5fcb8ca48453cb2ee3619746c701abf2d4cc67003471a187900b05aa812bd25ed05c675dfc8c97a24a7bf49bd6214992cad766d05a9a2b57b74f26a737e0237b8b76c45f1f226a836d7cfbc75ba999bdbe48dbc09227aa46c88f21dccba7840141ad5a5d71fd122e6bd6ac3e564780dfe623fc1ca9b995a6037bf0bbd43b205a84ac5444f34202c05ce9113087176432476576de6ffff9a52ea57c08be3ec2f49676cb8e12f762ac71fa3c321e00ac988910c85ff52f93825666ce0d40ffaa0592078919d4493f46d95ccf76364c6d57760dd0b64805f9afc76a2365a5575ca301d5103f0ea76cb9a79
+Error = PKCS_DECODING_ERROR
+
+# OAEP padding
+Decrypt = RSA-2048
+RSAPadding = OAEP
+Input = 458708dfbd42a1297ce7a9c86c7087ab80b1754810929b89c5107ca55368587686986fce94d86cc1595b3fb736223a656ec0f34d18ba1cc5665593610f56c58e26b272d584f3d983a5c91085700755aebd921fb280bba3eda7046ec07b43e7298e52d59edc92be4639a8ce08b2f85976ecf6d98cc469eeb9d5d8e2a32ea8a6626edafe1038b3df455668a9f3c77cad8b92fb872e00058c3d2a7ede1a1f03fc5622084ae04d9d24f6bf0995c58d35b93b699b9763595e123f2ab0863cc9229eb290e2ede7715c7a8f39e0b9a3e2e1b56ebb62f1cbfbb5986fb212ebd785b83d01d968b11d1756c7337f70c1f1a63bff03608e24f3a2fd44e67f832a8701c5d5af
+Output = "Hello World"
+
+# OAEP padding, corrupted ciphertext
+Decrypt = RSA-2048
+RSAPadding = OAEP
+Input = 458708dfbd42a1297ce7a9c86c7087ab80b1754810929b89c5107ca55368587686986fce94d86cc1595b3fb736223a656ec0f34d18ba1cc5665593610f56c58e26b272d584f3d983a5c91085700755aebd921fb280bba3eda7046ec07b43e7298e52d59edc92be4639a8ce08b2f85976ecf6d98cc469eeb9d5d8e2a32ea8a6626edafe1038b3df455668a9f3c77cad8b92fb872e00058c3d2a7ede1a1f03fc5622084ae04d9d24f6bf0995c58d35b93b699b9763595e123f2ab0863cc9229eb290e2ede7715c7a8f39e0b9a3e2e1b56ebb62f1cbfbb5986fb212ebd785b83d01d968b11d1756c7337f70c1f1a63bff03608e24f3a2fd44e67f832a8701c5d5ac
+Error = OAEP_DECODING_ERROR
+
+
 # EC tests
 
 Verify = P-256
@@ -125,6 +417,11 @@
 Input = "0123456789ABCDEF1234"
 Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec8
 
+Verify = P-256-SPKI
+Digest = SHA1
+Input = "0123456789ABCDEF1234"
+Output = 3045022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec8
+
 # Digest too long
 Verify = P-256
 Digest = SHA1
@@ -171,3 +468,807 @@
 Input = "0123456789ABCDEF1234"
 Output = 3080022100b1d1cb1a577035bccdd5a86c6148c2cc7c633cd42b7234139b593076d041e15202201898cdd52b41ca502098184b409cf83a21bc945006746e3b7cea52234e043ec80000
 Error = BAD_SIGNATURE
+
+
+# Additional RSA-PSS and RSA-OAEP tests converted from
+# ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip
+
+PublicKey = RSA-PSS-1
+Type = RSA
+Input = 30819f300d06092a864886f70d010101050003818d0030818902818100a56e4a0e701017589a5187dc7ea841d156f2ec0e36ad52a44dfeb1e61f7ad991d8c51056ffedb162b4c0f283a12a88a394dff526ab7291cbb307ceabfce0b1dfd5cd9508096d5b2b8b6df5d671ef6377c0921cb23c270a70e2598e6ff89d19f105acc2d3f0cb35f29280e1386b6f64c4ef22e1e1f20d0ce8cffb2249bd9a21370203010001
+
+Verify = RSA-PSS-1
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = cd8b6538cb8e8de566b68bd067569dbf1ee2718e
+Output = 9074308fb598e9701b2294388e52f971faac2b60a5145af185df5287b5ed2887e57ce7fd44dc8634e407c8e0e4360bc226f3ec227f9d9e54638e8d31f5051215df6ebb9c2f9579aa77598a38f914b5b9c1bd83c4e2f9f382a0d0aa3542ffee65984a601bc69eb28deb27dca12c82c2d4c3f66cd500f1ff2b994d8a4e30cbb33c
+
+Verify = RSA-PSS-1
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = e35befc17a1d160b9ce35fbd8eb16e7ee491d3fd
+Output = 3ef7f46e831bf92b32274142a585ffcefbdca7b32ae90d10fb0f0c729984f04ef29a9df0780775ce43739b97838390db0a5505e63de927028d9d29b219ca2c4517832558a55d694a6d25b9dab66003c4cccd907802193be5170d26147d37b93590241be51c25055f47ef62752cfbe21418fafe98c22c4d4d47724fdb5669e843
+
+Verify = RSA-PSS-1
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 0652ec67bcee30f9d2699122b91c19abdba89f91
+Output = 666026fba71bd3e7cf13157cc2c51a8e4aa684af9778f91849f34335d141c00154c4197621f9624a675b5abc22ee7d5baaffaae1c9baca2cc373b3f33e78e6143c395a91aa7faca664eb733afd14d8827259d99a7550faca501ef2b04e33c23aa51f4b9e8282efdb728cc0ab09405a91607c6369961bc8270d2d4f39fce612b1
+
+Verify = RSA-PSS-1
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 39c21c4cceda9c1adf839c744e1212a6437575ec
+Output = 4609793b23e9d09362dc21bb47da0b4f3a7622649a47d464019b9aeafe53359c178c91cd58ba6bcb78be0346a7bc637f4b873d4bab38ee661f199634c547a1ad8442e03da015b136e543f7ab07c0c13e4225b8de8cce25d4f6eb8400f81f7e1833b7ee6e334d370964ca79fdb872b4d75223b5eeb08101591fb532d155a6de87
+
+Verify = RSA-PSS-1
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 36dae913b77bd17cae6e7b09453d24544cebb33c
+Output = 1d2aad221ca4d31ddf13509239019398e3d14b32dc34dc5af4aeaea3c095af73479cf0a45e5629635a53a018377615b16cb9b13b3e09d671eb71e387b8545c5960da5a64776e768e82b2c93583bf104c3fdb23512b7b4e89f633dd0063a530db4524b01c3f384c09310e315a79dcd3d684022a7f31c865a664e316978b759fad
+
+Verify = RSA-PSS-1
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 45eef191f4f79c31fe5d2ede7e5098994e929d2d
+Output = 2a34f6125e1f6b0bf971e84fbd41c632be8f2c2ace7de8b6926e31ff93e9af987fbc06e51e9be14f5198f91f3f953bd67da60a9df59764c3dc0fe08e1cbef0b75f868d10ad3fba749fef59fb6dac46a0d6e504369331586f58e4628f39aa278982543bc0eeb537dc61958019b394fb273f215858a0a01ac4d650b955c67f4c58
+
+PublicKey = RSA-PSS-2
+Type = RSA
+Input = 30819f300d06092a864886f70d010101050003818d0030818902818101d40c1bcf97a68ae7cdbd8a7bf3e34fa19dcca4ef75a47454375f94514d88fed006fb829f8419ff87d6315da68a1ff3a0938e9abb3464011c303ad99199cf0c7c7a8b477dce829e8844f625b115e5e9c4a59cf8f8113b6834336a2fd2689b472cbb5e5cabe674350c59b6c17e176874fb42f8fc3d176a017edc61fd326c4b33c90203010001
+
+Verify = RSA-PSS-2
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 5c81a3e2a658246628cd0ee8b00bb4c012bc9739
+Output = 014c5ba5338328ccc6e7a90bf1c0ab3fd606ff4796d3c12e4b639ed9136a5fec6c16d8884bdd99cfdc521456b0742b736868cf90de099adb8d5ffd1deff39ba4007ab746cefdb22d7df0e225f54627dc65466131721b90af445363a8358b9f607642f78fab0ab0f43b7168d64bae70d8827848d8ef1e421c5754ddf42c2589b5b3
+
+Verify = RSA-PSS-2
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 27f71611446aa6eabf037f7dedeede3203244991
+Output = 010991656cca182b7f29d2dbc007e7ae0fec158eb6759cb9c45c5ff87c7635dd46d150882f4de1e9ae65e7f7d9018f6836954a47c0a81a8a6b6f83f2944d6081b1aa7c759b254b2c34b691da67cc0226e20b2f18b42212761dcd4b908a62b371b5918c5742af4b537e296917674fb914194761621cc19a41f6fb953fbcbb649dea
+
+Verify = RSA-PSS-2
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 03ecc2c33e93f05fc7224fcc0d461356cb897217
+Output = 007f0030018f53cdc71f23d03659fde54d4241f758a750b42f185f87578520c30742afd84359b6e6e8d3ed959dc6fe486bedc8e2cf001f63a7abe16256a1b84df0d249fc05d3194ce5f0912742dbbf80dd174f6c51f6bad7f16cf3364eba095a06267dc3793803ac7526aebe0a475d38b8c2247ab51c4898df7047dc6adf52c6c4
+
+Verify = RSA-PSS-2
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 246c727b4b9494849dddb068d582e179ac20999c
+Output = 009cd2f4edbe23e12346ae8c76dd9ad3230a62076141f16c152ba18513a48ef6f010e0e37fd3df10a1ec629a0cb5a3b5d2893007298c30936a95903b6ba85555d9ec3673a06108fd62a2fda56d1ce2e85c4db6b24a81ca3b496c36d4fd06eb7c9166d8e94877c42bea622b3bfe9251fdc21d8d5371badad78a488214796335b40b
+
+Verify = RSA-PSS-2
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = e8617ca3ea66ce6a58ede2d11af8c3ba8a6ba912
+Output = 00ec430824931ebd3baa43034dae98ba646b8c36013d1671c3cf1cf8260c374b19f8e1cc8d965012405e7e9bf7378612dfcc85fce12cda11f950bd0ba8876740436c1d2595a64a1b32efcfb74a21c873b3cc33aaf4e3dc3953de67f0674c0453b4fd9f604406d441b816098cb106fe3472bc251f815f59db2e4378a3addc181ecf
+
+Verify = RSA-PSS-2
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 7a6fdc1a4e434ecbc35d657ad49a2f4fafd43bc8
+Output = 00475b1648f814a8dc0abdc37b5527f543b666bb6e39d30e5b49d3b876dccc58eac14e32a2d55c2616014456ad2f246fc8e3d560da3ddf379a1c0bd200f10221df078c219a151bc8d4ec9d2fc2564467811014ef15d8ea01c2ebbff8c2c8efab38096e55fcbe3285c7aa558851254faffa92c1c72b78758663ef4582843139d7a6
+
+PublicKey = RSA-PSS-3
+Type = RSA
+Input = 30819f300d06092a864886f70d010101050003818d0030818902818102f246ef451ed3eebb9a310200cc25859c048e4be798302991112eb68ce6db674e280da21feded1ae74880ca522b18db249385012827c515f0e466a1ffa691d98170574e9d0eadb087586ca48933da3cc953d95bd0ed50de10ddcb6736107d6c831c7f663e833ca4c097e700ce0fb945f88fb85fe8e5a773172565b914a471a4430203010001
+
+Verify = RSA-PSS-3
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 3552be69dd74bdc56d2cf8c38ef7bafe269040fe
+Output = 0088b135fb1794b6b96c4a3e678197f8cac52b64b2fe907d6f27de761124964a99a01a882740ecfaed6c01a47464bb05182313c01338a8cd097214cd68ca103bd57d3bc9e816213e61d784f182467abf8a01cf253e99a156eaa8e3e1f90e3c6e4e3aa2d83ed0345b89fafc9c26077c14b6ac51454fa26e446e3a2f153b2b16797f
+
+Verify = RSA-PSS-3
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 609143ff7240e55c062aba8b9e4426a781919bc9
+Output = 02a5f0a858a0864a4f65017a7d69454f3f973a2999839b7bbc48bf78641169179556f595fa41f6ff18e286c2783079bc0910ee9cc34f49ba681124f923dfa88f426141a368a5f5a930c628c2c3c200e18a7644721a0cbec6dd3f6279bde3e8f2be5e2d4ee56f97e7ceaf33054be7042bd91a63bb09f897bd41e81197dee99b11af
+
+Verify = RSA-PSS-3
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 0afd22f879a9cda7c584f4135f8f1c961db114c0
+Output = 0244bcd1c8c16955736c803be401272e18cb990811b14f72db964124d5fa760649cbb57afb8755dbb62bf51f466cf23a0a1607576e983d778fceffa92df7548aea8ea4ecad2c29dd9f95bc07fe91ecf8bee255bfe8762fd7690aa9bfa4fa0849ef728c2c42c4532364522df2ab7f9f8a03b63f7a499175828668f5ef5a29e3802c
+
+Verify = RSA-PSS-3
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 405dd56d395ef0f01b555c48f748cc32b210650b
+Output = 0196f12a005b98129c8df13c4cb16f8aa887d3c40d96df3a88e7532ef39cd992f273abc370bc1be6f097cfebbf0118fd9ef4b927155f3df22b904d90702d1f7ba7a52bed8b8942f412cd7bd676c9d18e170391dcd345c06a730964b3f30bcce0bb20ba106f9ab0eeb39cf8a6607f75c0347f0af79f16afa081d2c92d1ee6f836b8
+
+Verify = RSA-PSS-3
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = a2c313b0440c8a0c47233b87f0a160c61af3eae7
+Output = 021eca3ab4892264ec22411a752d92221076d4e01c0e6f0dde9afd26ba5acf6d739ef987545d16683e5674c9e70f1de649d7e61d48d0caeb4fb4d8b24fba84a6e3108fee7d0705973266ac524b4ad280f7ae17dc59d96d3351586b5a3bdb895d1e1f7820ac6135d8753480998382ba32b7349559608c38745290a85ef4e9f9bd83
+
+Verify = RSA-PSS-3
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = f1bf6ca7b4bbdbb6bf20a4bf55728725d177154a
+Output = 012fafec862f56e9e92f60ab0c77824f4299a0ca734ed26e0644d5d222c7f0bde03964f8e70a5cb65ed44e44d56ae0edf1ff86ca032cc5dd4404dbb76ab854586c44eed8336d08d457ce6c03693b45c0f1efef93624b95b8ec169c616d20e5538ebc0b6737a6f82b4bc0570924fc6b35759a3348426279f8b3d7744e2d222426ce
+
+PublicKey = RSA-PSS-4
+Type = RSA
+Input = 30819f300d06092a864886f70d010101050003818d00308189028181054adb7886447efe6f57e0368f06cf52b0a3370760d161cef126b91be7f89c421b62a6ec1da3c311d75ed50e0ab5fff3fd338acc3aa8a4e77ee26369acb81ba900fa83f5300cf9bb6c53ad1dc8a178b815db4235a9a9da0c06de4e615ea1277ce559e9c108de58c14a81aa77f5a6f8d1335494498848c8b95940740be7bf7c37050203010001
+
+Verify = RSA-PSS-4
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = f8b0abf70fec0bca74f0accbc24f75e6e90d3bfd
+Output = 0323d5b7bf20ba4539289ae452ae4297080feff4518423ff4811a817837e7d82f1836cdfab54514ff0887bddeebf40bf99b047abc3ecfa6a37a3ef00f4a0c4a88aae0904b745c846c4107e8797723e8ac810d9e3d95dfa30ff4966f4d75d13768d20857f2b1406f264cfe75e27d7652f4b5ed3575f28a702f8c4ed9cf9b2d44948
+
+Verify = RSA-PSS-4
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 04a10944bfe11ab801e77889f3fd3d7f4ff0b629
+Output = 049d0185845a264d28feb1e69edaec090609e8e46d93abb38371ce51f4aa65a599bdaaa81d24fba66a08a116cb644f3f1e653d95c89db8bbd5daac2709c8984000178410a7c6aa8667ddc38c741f710ec8665aa9052be929d4e3b16782c1662114c5414bb0353455c392fc28f3db59054b5f365c49e1d156f876ee10cb4fd70598
+
+Verify = RSA-PSS-4
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = ba01243db223eb97fb86d746c3148adaaa0ca344
+Output = 03fbc410a2ced59500fb99f9e2af2781ada74e13145624602782e2994813eefca0519ecd253b855fb626a90d771eae028b0c47a199cbd9f8e3269734af4163599090713a3fa910fa0960652721432b971036a7181a2bc0cab43b0b598bc6217461d7db305ff7e954c5b5bb231c39e791af6bcfa76b147b081321f72641482a2aad
+
+Verify = RSA-PSS-4
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 934bb0d38d6836daec9de82a9648d4593da67cd2
+Output = 0486644bc66bf75d28335a6179b10851f43f09bded9fac1af33252bb9953ba4298cd6466b27539a70adaa3f89b3db3c74ab635d122f4ee7ce557a61e59b82ffb786630e5f9db53c77d9a0c12fab5958d4c2ce7daa807cd89ba2cc7fcd02ff470ca67b229fcce814c852c73cc93bea35be68459ce478e9d4655d121c8472f371d4f
+
+Verify = RSA-PSS-4
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = ec35d81abd1cceac425a935758b683465c8bd879
+Output = 022a80045353904cb30cbb542d7d4990421a6eec16a8029a8422adfd22d6aff8c4cc0294af110a0c067ec86a7d364134459bb1ae8ff836d5a8a2579840996b320b19f13a13fad378d931a65625dae2739f0c53670b35d9d3cbac08e733e4ec2b83af4b9196d63e7c4ff1ddeae2a122791a125bfea8deb0de8ccf1f4ffaf6e6fb0a
+
+Verify = RSA-PSS-4
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 72ce251d17b04dd3970d6ff1fbe3624899e9e941
+Output = 00938dcb6d583046065f69c78da7a1f1757066a7fa75125a9d2929f0b79a60b627b082f11f5b196f28eb9daa6f21c05e5140f6aef1737d2023075c05ecf04a028c686a2ab3e7d5a0664f295ce12995e890908b6ad21f0839eb65b70393a7b5afd9871de0caa0cedec5b819626756209d13ab1e7bb9546a26ff37e9a51af9fd562e
+
+PublicKey = RSA-PSS-5
+Type = RSA
+Input = 30819f300d06092a864886f70d010101050003818d003081890281810d10f661f29940f5ed39aa260966deb47843679d2b6fb25b3de370f3ac7c19916391fd25fb527ebfa6a4b4df45a1759d996c4bb4ebd18828c44fc52d0191871740525f47a4b0cc8da325ed8aa676b0d0f626e0a77f07692170acac8082f42faa7dc7cd123e730e31a87985204cabcbe6670d43a2dd2b2ddef5e05392fc213bc5070203010001
+
+Verify = RSA-PSS-5
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = d98b7061943510bc3dd9162f7169aabdbdcd0222
+Output = 0ba373f76e0921b70a8fbfe622f0bf77b28a3db98e361051c3d7cb92ad0452915a4de9c01722f6823eeb6adf7e0ca8290f5de3e549890ac2a3c5950ab217ba58590894952de96f8df111b2575215da6c161590c745be612476ee578ed384ab33e3ece97481a252f5c79a98b5532ae00cdd62f2ecc0cd1baefe80d80b962193ec1d
+
+Verify = RSA-PSS-5
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 7ae8e699f754988f4fd645e463302e49a2552072
+Output = 08180de825e4b8b014a32da8ba761555921204f2f90d5f24b712908ff84f3e220ad17997c0dd6e706630ba3e84add4d5e7ab004e58074b549709565d43ad9e97b5a7a1a29e85b9f90f4aafcdf58321de8c5974ef9abf2d526f33c0f2f82e95d158ea6b81f1736db8d1af3d6ac6a83b32d18bae0ff1b2fe27de4c76ed8c7980a34e
+
+Verify = RSA-PSS-5
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 8d46c7c05534c1ba2cc7624500d48a4531604bff
+Output = 05e0fdbdf6f756ef733185ccfa8ced2eb6d029d9d56e35561b5db8e70257ee6fd019d2f0bbf669fe9b9821e78df6d41e31608d58280f318ee34f559941c8df13287574bac000b7e58dc4f414ba49fb127f9d0f8936638c76e85356c994f79750f7fa3cf4fd482df75e3fb9978cd061f7abb17572e6e63e0bde12cbdcf18c68b979
+
+Verify = RSA-PSS-5
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = ee3de96783fd0a157c8b20bf5566124124dcfe65
+Output = 0bc989853bc2ea86873271ce183a923ab65e8a53100e6df5d87a24c4194eb797813ee2a187c097dd872d591da60c568605dd7e742d5af4e33b11678ccb63903204a3d080b0902c89aba8868f009c0f1c0cb85810bbdd29121abb8471ff2d39e49fd92d56c655c8e037ad18fafbdc92c95863f7f61ea9efa28fea401369d19daea1
+
+Verify = RSA-PSS-5
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 1204df0b03c2724e2709c23fc71789a21b00ae4c
+Output = 0aefa943b698b9609edf898ad22744ac28dc239497cea369cbbd84f65c95c0ad776b594740164b59a739c6ff7c2f07c7c077a86d95238fe51e1fcf33574a4ae0684b42a3f6bf677d91820ca89874467b2c23add77969c80717430d0efc1d3695892ce855cb7f7011630f4df26def8ddf36fc23905f57fa6243a485c770d5681fcd
+
+Verify = RSA-PSS-5
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 29926bc3280c841f601acd0d6f17ea38023eddbc
+Output = 02802dccfa8dfaf5279bf0b4a29ba1b157611faeaaf419b8919d15941900c1339e7e92e6fae562c53e6cc8e84104b110bce03ad18525e3c49a0eadad5d3f28f244a8ed89edbafbb686277cfa8ae909714d6b28f4bf8e293aa04c41efe7c0a81266d5c061e2575be032aa464674ff71626219bd74cc45f0e7ed4e3ff96eee758e8f
+
+PublicKey = RSA-PSS-6
+Type = RSA
+Input = 30819f300d06092a864886f70d010101050003818d00308189028181164ca31cff609f3a0e7101b039f2e4fe6dd37519ab98598d179e174996598071f47d3a04559158d7be373cf1aa53f0aa6ef09039e5678c2a4c63900514c8c4f8aaed5de12a5f10b09c311af8c0ffb5b7a297f2efc63b8d6b0510931f0b98e48bf5fc6ec4e7b8db1ffaeb08c38e02adb8f03a48229c99e969431f61cb8c4dc698d10203010001
+
+Verify = RSA-PSS-6
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = ab464e8cb65ae5fdea47a53fa84b234d6bfd52f6
+Output = 04c0cfacec04e5badbece159a5a1103f69b3f32ba593cb4cc4b1b7ab455916a96a27cd2678ea0f46ba37f7fc9c86325f29733b389f1d97f43e7201c0f348fc45fe42892335362eee018b5b161f2f9393031225c713012a576bc88e23052489868d9010cbf033ecc568e8bc152bdc59d560e41291915d28565208e22aeec9ef85d1
+
+Verify = RSA-PSS-6
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 92d0bcae82b641f578f040f5151be8eda6d42299
+Output = 0a2314250cf52b6e4e908de5b35646bcaa24361da8160fb0f9257590ab3ace42b0dc3e77ad2db7c203a20bd952fbb56b1567046ecfaa933d7b1000c3de9ff05b7d989ba46fd43bc4c2d0a3986b7ffa13471d37eb5b47d64707bd290cfd6a9f393ad08ec1e3bd71bb5792615035cdaf2d8929aed3be098379377e777ce79aaa4773
+
+Verify = RSA-PSS-6
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 3569bd8fd2e28f2443375efa94f186f6911ffc2b
+Output = 086df6b500098c120f24ff8423f727d9c61a5c9007d3b6a31ce7cf8f3cbec1a26bb20e2bd4a046793299e03e37a21b40194fb045f90b18bf20a47992ccd799cf9c059c299c0526854954aade8a6ad9d97ec91a1145383f42468b231f4d72f23706d9853c3fa43ce8ace8bfe7484987a1ec6a16c8daf81f7c8bf42774707a9df456
+
+Verify = RSA-PSS-6
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 7abbb7b42de335730a0b641f1e314b6950b84f98
+Output = 0b5b11ad549863ffa9c51a14a1106c2a72cc8b646e5c7262509786105a984776534ca9b54c1cc64bf2d5a44fd7e8a69db699d5ea52087a4748fd2abc1afed1e5d6f7c89025530bdaa2213d7e030fa55df6f34bcf1ce46d2edf4e3ae4f3b01891a068c9e3a44bbc43133edad6ecb9f35400c4252a5762d65744b99cb9f4c559329f
+
+Verify = RSA-PSS-6
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 55b7eb27be7a787a59eb7e5fac468db8917a7725
+Output = 02d71fa9b53e4654fefb7f08385cf6b0ae3a817942ebf66c35ac67f0b069952a3ce9c7e1f1b02e480a9500836de5d64cdb7ecde04542f7a79988787e24c2ba05f5fd482c023ed5c30e04839dc44bed2a3a3a4fee01113c891a47d32eb8025c28cb050b5cdb576c70fe76ef523405c08417faf350b037a43c379339fcb18d3a356b
+
+Verify = RSA-PSS-6
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = de2fa0367ef49083ff89b9905d3fd646fcc12c38
+Output = 0a40a16e2fe2b38d1df90546167cf9469c9e3c3681a3442b4b2c2f581deb385ce99fc6188bb02a841d56e76d301891e24560550fcc2a26b55f4ccb26d837d350a154bcaca8392d98fa67959e9727b78cad03269f56968fc56b68bd679926d83cc9cb215550645ccda31c760ff35888943d2d8a1d351e81e5d07b86182e751081ef
+
+PublicKey = RSA-PSS-7
+Type = RSA
+Input = 30819f300d06092a864886f70d010101050003818d0030818902818137c9da4a66c8c408b8da27d0c9d79f8ccb1eafc1d2fe48746d940b7c4ef5dee18ad12647cefaa0c4b3188b221c515386759b93f02024b25ab9242f8357d8f3fd49640ee5e643eaf6c64deefa7089727c8ff03993333915c6ef21bf5975b6e50d118b51008ec33e9f01a0a545a10a836a43ddbca9d8b5c5d3548022d7064ea29ab30203010001
+
+Verify = RSA-PSS-7
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 8be4afbdd76bd8d142c5f4f46dba771ee5d6d29d
+Output = 187f390723c8902591f0154bae6d4ecbffe067f0e8b795476ea4f4d51ccc810520bb3ca9bca7d0b1f2ea8a17d873fa27570acd642e3808561cb9e975ccfd80b23dc5771cdb3306a5f23159dacbd3aa2db93d46d766e09ed15d900ad897a8d274dc26b47e994a27e97e2268a766533ae4b5e42a2fcaf755c1c4794b294c60555823
+
+Verify = RSA-PSS-7
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 402140dc605b2f5c5ec0d15bce9f9ba8857fe117
+Output = 10fd89768a60a67788abb5856a787c8561f3edcf9a83e898f7dc87ab8cce79429b43e56906941a886194f137e591fe7c339555361fbbe1f24feb2d4bcdb80601f3096bc9132deea60ae13082f44f9ad41cd628936a4d51176e42fc59cb76db815ce5ab4db99a104aafea68f5d330329ebf258d4ede16064bd1d00393d5e1570eb8
+
+Verify = RSA-PSS-7
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 3e885205892ff2b6b37c2c4eb486c4bf2f9e7f20
+Output = 2b31fde99859b977aa09586d8e274662b25a2a640640b457f594051cb1e7f7a911865455242926cf88fe80dfa3a75ba9689844a11e634a82b075afbd69c12a0df9d25f84ad4945df3dc8fe90c3cefdf26e95f0534304b5bdba20d3e5640a2ebfb898aac35ae40f26fce5563c2f9f24f3042af76f3c7072d687bbfb959a88460af1
+
+Verify = RSA-PSS-7
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 1fc2201d0c442a4736cd8b2cd00c959c47a3bf42
+Output = 32c7ca38ff26949a15000c4ba04b2b13b35a3810e568184d7ecabaa166b7ffabddf2b6cf4ba07124923790f2e5b1a5be040aea36fe132ec130e1f10567982d17ac3e89b8d26c3094034e762d2e031264f01170beecb3d1439e05846f25458367a7d9c02060444672671e64e877864559ca19b2074d588a281b5804d23772fbbe19
+
+Verify = RSA-PSS-7
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = e4351b66819e5a31501f89acc7faf57030e9aac5
+Output = 07eb651d75f1b52bc263b2e198336e99fbebc4f332049a922a10815607ee2d989db3a4495b7dccd38f58a211fb7e193171a3d891132437ebca44f318b280509e52b5fa98fcce8205d9697c8ee4b7ff59d4c59c79038a1970bd2a0d451ecdc5ef11d9979c9d35f8c70a6163717607890d586a7c6dc01c79f86a8f28e85235f8c2f1
+
+Verify = RSA-PSS-7
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 49f6cc58365e514e1a3f301f4de16f9fb5347ff2
+Output = 18da3cdcfe79bfb77fd9c32f377ad399146f0a8e810620233271a6e3ed3248903f5cdc92dc79b55d3e11615aa056a795853792a3998c349ca5c457e8ca7d29d796aa24f83491709befcfb1510ea513c92829a3f00b104f655634f320752e130ec0ccf6754ff893db302932bb025eb60e87822598fc619e0e981737a9a4c4152d33
+
+PublicKey = RSA-PSS-8
+Type = RSA
+Input = 30819f300d06092a864886f70d010101050003818d00308189028181495370a1fb18543c16d3631e3163255df62be6eee890d5f25509e4f778a8ea6fbbbcdf85dff64e0d972003ab3681fbba6dd41fd541829b2e582de9f2a4a4e0a2d0900bef4753db3cee0ee06c7dfae8b1d53b5953218f9cceea695b08668edeaadced9463b1d790d5ebf27e9115b46cad4d9a2b8efab0561b0810344739ada0733f0203010001
+
+Verify = RSA-PSS-8
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = a1dd230d8ead860199b6277c2ecfe3d95f6d9160
+Output = 0262ac254bfa77f3c1aca22c5179f8f040422b3c5bafd40a8f21cf0fa5a667ccd5993d42dbafb409c520e25fce2b1ee1e716577f1efa17f3da28052f40f0419b23106d7845aaf01125b698e7a4dfe92d3967bb00c4d0d35ba3552ab9a8b3eef07c7fecdbc5424ac4db1e20cb37d0b2744769940ea907e17fbbca673b20522380c5
+
+Verify = RSA-PSS-8
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = f6e68e53c602c5c65fa67b5aa6d786e5524b12ab
+Output = 2707b9ad5115c58c94e932e8ec0a280f56339e44a1b58d4ddcff2f312e5f34dcfe39e89c6a94dcee86dbbdae5b79ba4e0819a9e7bfd9d982e7ee6c86ee68396e8b3a14c9c8f34b178eb741f9d3f121109bf5c8172fada2e768f9ea1433032c004a8aa07eb990000a48dc94c8bac8aabe2b09b1aa46c0a2aa0e12f63fbba775ba7e
+
+Verify = RSA-PSS-8
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = d6f9fcd3ae27f32bb2c7c93536782eba52af1f76
+Output = 2ad20509d78cf26d1b6c406146086e4b0c91a91c2bd164c87b966b8faa42aa0ca446022323ba4b1a1b89706d7f4c3be57d7b69702d168ab5955ee290356b8c4a29ed467d547ec23cbadf286ccb5863c6679da467fc9324a151c7ec55aac6db4084f82726825cfe1aa421bc64049fb42f23148f9c25b2dc300437c38d428aa75f96
+
+Verify = RSA-PSS-8
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 7ff2a53ce2e2d900d468e498f230a5f5dd0020de
+Output = 1e24e6e58628e5175044a9eb6d837d48af1260b0520e87327de7897ee4d5b9f0df0be3e09ed4dea8c1454ff3423bb08e1793245a9df8bf6ab3968c8eddc3b5328571c77f091cc578576912dfebd164b9de5454fe0be1c1f6385b328360ce67ec7a05f6e30eb45c17c48ac70041d2cab67f0a2ae7aafdcc8d245ea3442a6300ccc7
+
+Verify = RSA-PSS-8
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 4eb309f7022ba0b03bb78601b12931ec7c1be8d3
+Output = 33341ba3576a130a50e2a5cf8679224388d5693f5accc235ac95add68e5eb1eec31666d0ca7a1cda6f70a1aa762c05752a51950cdb8af3c5379f18cfe6b5bc55a4648226a15e912ef19ad77adeea911d67cfefd69ba43fa4119135ff642117ba985a7e0100325e9519f1ca6a9216bda055b5785015291125e90dcd07a2ca9673ee
+
+Verify = RSA-PSS-8
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 65033bc2f67d6aba7d526acb873b8d9241e5e4d9
+Output = 1ed1d848fb1edb44129bd9b354795af97a069a7a00d0151048593e0c72c3517ff9ff2a41d0cb5a0ac860d736a199704f7cb6a53986a88bbd8abcc0076a2ce847880031525d449da2ac78356374c536e343faa7cba42a5aaa6506087791c06a8e989335aed19bfab2d5e67e27fb0c2875af896c21b6e8e7309d04e4f6727e69463e
+
+PublicKey = RSA-PSS-9
+Type = RSA
+Input = 3081df300d06092a864886f70d01010105000381cd003081c90281c100e6bd692ac96645790403fdd0f5beb8b9bf92ed10007fc365046419dd06c05c5b5b2f48ecf989e4ce269109979cbb40b4a0ad24d22483d1ee315ad4ccb1534268352691c524f6dd8e6c29d224cf246973aec86c5bf6b1401a850d1b9ad1bb8cbcec47b06f0f8c7f45d3fc8f319299c5433ddbc2b3053b47ded2ecd4a4caefd614833dc8bb622f317ed076b8057fe8de3f84480ad5e83e4a61904a4f248fb397027357e1d30e463139815c6fd4fd5ac5b8172a45230ecb6318a04f1455d84e5a8b0203010001
+
+Verify = RSA-PSS-9
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 2715a49b8b0012cd7aee84c116446e6dfe3faec0
+Output = 586107226c3ce013a7c8f04d1a6a2959bb4b8e205ba43a27b50f124111bc35ef589b039f5932187cb696d7d9a32c0c38300a5cdda4834b62d2eb240af33f79d13dfbf095bf599e0d9686948c1964747b67e89c9aba5cd85016236f566cc5802cb13ead51bc7ca6bef3b94dcbdbb1d570469771df0e00b1a8a06777472d2316279edae86474668d4e1efff95f1de61c6020da32ae92bbf16520fef3cf4d88f61121f24bbd9fe91b59caf1235b2a93ff81fc403addf4ebdea84934a9cdaf8e1a9e
+
+Verify = RSA-PSS-9
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 2dac956d53964748ac364d06595827c6b4f143cd
+Output = 80b6d643255209f0a456763897ac9ed259d459b49c2887e5882ecb4434cfd66dd7e1699375381e51cd7f554f2c271704b399d42b4be2540a0eca61951f55267f7c2878c122842dadb28b01bd5f8c025f7e228418a673c03d6bc0c736d0a29546bd67f786d9d692ccea778d71d98c2063b7a71092187a4d35af108111d83e83eae46c46aa34277e06044589903788f1d5e7cee25fb485e92949118814d6f2c3ee361489016f327fb5bc517eb50470bffa1afa5f4ce9aa0ce5b8ee19bf5501b958
+
+Verify = RSA-PSS-9
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 28d98c46cccafbd3bc04e72f967a54bd3ea12298
+Output = 484408f3898cd5f53483f80819efbf2708c34d27a8b2a6fae8b322f9240237f981817aca1846f1084daa6d7c0795f6e5bf1af59c38e1858437ce1f7ec419b98c8736adf6dd9a00b1806d2bd3ad0a73775e05f52dfef3a59ab4b08143f0df05cd1ad9d04bececa6daa4a2129803e200cbc77787caf4c1d0663a6c5987b605952019782caf2ec1426d68fb94ed1d4be816a7ed081b77e6ab330b3ffc073820fecde3727fcbe295ee61a050a343658637c3fd659cfb63736de32d9f90d3c2f63eca
+
+Verify = RSA-PSS-9
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 0866d2ff5a79f25ef668cd6f31b42dee421e4c0e
+Output = 84ebeb481be59845b46468bafb471c0112e02b235d84b5d911cbd1926ee5074ae0424495cb20e82308b8ebb65f419a03fb40e72b78981d88aad143053685172c97b29c8b7bf0ae73b5b2263c403da0ed2f80ff7450af7828eb8b86f0028bd2a8b176a4d228cccea18394f238b09ff758cc00bc04301152355742f282b54e663a919e709d8da24ade5500a7b9aa50226e0ca52923e6c2d860ec50ff480fa57477e82b0565f4379f79c772d5c2da80af9fbf325ece6fc20b00961614bee89a183e
+
+Verify = RSA-PSS-9
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 6a5b4be4cd36cc97dfde9995efbf8f097a4a991a
+Output = 82102df8cb91e7179919a04d26d335d64fbc2f872c44833943241de8454810274cdf3db5f42d423db152af7135f701420e39b494a67cbfd19f9119da233a23da5c6439b5ba0d2bc373eee3507001378d4a4073856b7fe2aba0b5ee93b27f4afec7d4d120921c83f606765b02c19e4d6a1a3b95fa4c422951be4f52131077ef17179729cddfbdb56950dbaceefe78cb16640a099ea56d24389eef10f8fecb31ba3ea3b227c0a86698bb89e3e9363905bf22777b2a3aa521b65b4cef76d83bde4c
+
+Verify = RSA-PSS-9
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = b9dfd1df76a461c51e6576c6c8ed0a923d1c50e7
+Output = a7fdb0d259165ca2c88d00bbf1028a867d337699d061193b17a9648e14ccbbaadeacaacdec815e7571294ebb8a117af205fa078b47b0712c199e3ad05135c504c24b81705115740802487992ffd511d4afc6b854491eb3f0dd523139542ff15c3101ee85543517c6a3c79417c67e2dd9aa741e9a29b06dcb593c2336b3670ae3afbac7c3e76e215473e866e338ca244de00b62624d6b9426822ceae9f8cc460895f41250073fd45c5a1e7b425c204a423a699159f6903e710b37a7bb2bc8049f
+
+PublicKey = RSA-PSS-10
+Type = RSA
+Input = 30820122300d06092a864886f70d01010105000382010f003082010a0282010100a5dd867ac4cb02f90b9457d48c14a770ef991c56c39c0ec65fd11afa8937cea57b9be7ac73b45c0017615b82d622e318753b6027c0fd157be12f8090fee2a7adcd0eef759f88ba4997c7a42d58c9aa12cb99ae001fe521c13bb5431445a8d5ae4f5e4c7e948ac227d3604071f20e577e905fbeb15dfaf06d1de5ae6253d63a6a2120b31a5da5dabc9550600e20f27d3739e2627925fea3cc509f21dff04e6eea4549c540d6809ff9307eede91fff58733d8385a237d6d3705a33e391900992070df7adf1357cf7e3700ce3667de83f17b8df1778db381dce09cb4ad058a511001a738198ee27cf55a13b754539906582ec8b174bd58d5d1f3d767c613721ae050203010001
+
+Verify = RSA-PSS-10
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 9596bb630cf6a8d4ea4600422b9eba8b13675dd4
+Output = 82c2b160093b8aa3c0f7522b19f87354066c77847abf2a9fce542d0e84e920c5afb49ffdfdace16560ee94a1369601148ebad7a0e151cf16331791a5727d05f21e74e7eb811440206935d744765a15e79f015cb66c532c87a6a05961c8bfad741a9a6657022894393e7223739796c02a77455d0f555b0ec01ddf259b6207fd0fd57614cef1a5573baaff4ec00069951659b85f24300a25160ca8522dc6e6727e57d019d7e63629b8fe5e89e25cc15beb3a647577559299280b9b28f79b0409000be25bbd96408ba3b43cc486184dd1c8e62553fa1af4040f60663de7f5e49c04388e257f1ce89c95dab48a315d9b66b1b7628233876ff2385230d070d07e1666
+
+Verify = RSA-PSS-10
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = b503319399277fd6c1c8f1033cbf04199ea21716
+Output = 14ae35d9dd06ba92f7f3b897978aed7cd4bf5ff0b585a40bd46ce1b42cd2703053bb9044d64e813d8f96db2dd7007d10118f6f8f8496097ad75e1ff692341b2892ad55a633a1c55e7f0a0ad59a0e203a5b8278aec54dd8622e2831d87174f8caff43ee6c46445345d84a59659bfb92ecd4c818668695f34706f66828a89959637f2bf3e3251c24bdba4d4b7649da0022218b119c84e79a6527ec5b8a5f861c159952e23ec05e1e717346faefe8b1686825bd2b262fb2531066c0de09acde2e4231690728b5d85e115a2f6b92b79c25abc9bd9399ff8bcf825a52ea1f56ea76dd26f43baafa18bfa92a504cbd35699e26d1dcc5a2887385f3c63232f06f3244c3
+
+Verify = RSA-PSS-10
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 50aaede8536b2c307208b275a67ae2df196c7628
+Output = 6e3e4d7b6b15d2fb46013b8900aa5bbb3939cf2c095717987042026ee62c74c54cffd5d7d57efbbf950a0f5c574fa09d3fc1c9f513b05b4ff50dd8df7edfa20102854c35e592180119a70ce5b085182aa02d9ea2aa90d1df03f2daae885ba2f5d05afdac97476f06b93b5bc94a1a80aa9116c4d615f333b098892b25fface266f5db5a5a3bcc10a824ed55aad35b727834fb8c07da28fcf416a5d9b2224f1f8b442b36f91e456fdea2d7cfe3367268de0307a4c74e924159ed33393d5e0655531c77327b89821bdedf880161c78cd4196b5419f7acc3f13e5ebf161b6e7c6724716ca33b85c2e25640192ac2859651d50bde7eb976e51cec828b98b6563b86bb
+
+Verify = RSA-PSS-10
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = aa0b72b8b371ddd10c8ae474425ccccf8842a294
+Output = 34047ff96c4dc0dc90b2d4ff59a1a361a4754b255d2ee0af7d8bf87c9bc9e7ddeede33934c63ca1c0e3d262cb145ef932a1f2c0a997aa6a34f8eaee7477d82ccf09095a6b8acad38d4eec9fb7eab7ad02da1d11d8e54c1825e55bf58c2a23234b902be124f9e9038a8f68fa45dab72f66e0945bf1d8bacc9044c6f07098c9fcec58a3aab100c805178155f030a124c450e5acbda47d0e4f10b80a23f803e774d023b0015c20b9f9bbe7c91296338d5ecb471cafb032007b67a60be5f69504a9f01abb3cb467b260e2bce860be8d95bf92c0c8e1496ed1e528593a4abb6df462dde8a0968dffe4683116857a232f5ebf6c85be238745ad0f38f767a5fdbf486fb
+
+Verify = RSA-PSS-10
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = fad3902c9750622a2bc672622c48270cc57d3ea8
+Output = 7e0935ea18f4d6c1d17ce82eb2b3836c55b384589ce19dfe743363ac9948d1f346b7bfddfe92efd78adb21faefc89ade42b10f374003fe122e67429a1cb8cbd1f8d9014564c44d120116f4990f1a6e38774c194bd1b8213286b077b0499d2e7b3f434ab12289c556684deed78131934bb3dd6537236f7c6f3dcb09d476be07721e37e1ceed9b2f7b406887bd53157305e1c8b4f84d733bc1e186fe06cc59b6edb8f4bd7ffefdf4f7ba9cfb9d570689b5a1a4109a746a690893db3799255a0cb9215d2d1cd490590e952e8c8786aa0011265252470c041dfbc3eec7c3cbf71c24869d115c0cb4a956f56d530b80ab589acfefc690751ddf36e8d383f83cedd2cc
+
+Verify = RSA-PSS-10
+RSAPadding = PSS
+MGF1Digest = SHA1
+Input = 122196deb5d122bd8c6fc781ff6924d7c695aade
+Output = 6d3b5b87f67ea657af21f75441977d2180f91b2c5f692de82955696a686730d9b9778d970758ccb26071c2209ffbd6125be2e96ea81b67cb9b9308239fda17f7b2b64ecda096b6b935640a5a1cb42a9155b1c9ef7a633a02c59f0d6ee59b852c43b35029e73c940ff0410e8f114eed46bbd0fae165e42be2528a401c3b28fd818ef3232dca9f4d2a0f5166ec59c42396d6c11dbc1215a56fa17169db9575343ef34f9de32a49cdc3174922f229c23e18e45df9353119ec4319cedce7a17c64088c1f6f52be29634100b3919d38f3d1ed94e6891e66a73b8fb849f5874df59459e298c7bbce2eee782a195aa66fe2d0732b25e595f57d3e061b1fc3e4063bf98f
+
+PrivateKey = RSA-OAEP-1
+Type = RSA
+Input = 30820276020100300d06092a864886f70d0101010500048202603082025c02010002818100a8b3b284af8eb50b387034a860f146c4919f318763cd6c5598c8ae4811a1e0abc4c7e0b082d693a5e7fced675cf4668512772c0cbc64a742c6c630f533c8cc72f62ae833c40bf25842e984bb78bdbf97c0107d55bdb662f5c4e0fab9845cb5148ef7392dd3aaff93ae1e6b667bb3d4247616d4f5ba10d4cfd226de88d39f16fb020301000102818053339cfdb79fc8466a655c7316aca85c55fd8f6dd898fdaf119517ef4f52e8fd8e258df93fee180fa0e4ab29693cd83b152a553d4ac4d1812b8b9fa5af0e7f55fe7304df41570926f3311f15c4d65a732c483116ee3d3d2d0af3549ad9bf7cbfb78ad884f84d5beb04724dc7369b31def37d0cf539e9cfcdd3de653729ead5d1024100d32737e7267ffe1341b2d5c0d150a81b586fb3132bed2f8d5262864a9cb9f30af38be448598d413a172efb802c21acf1c11c520c2f26a471dcad212eac7ca39d024100cc8853d1d54da630fac004f471f281c7b8982d8224a490edbeb33d3e3d5cc93c4765703d1dd791642f1f116a0dd852be2419b2af72bfe9a030e860b0288b5d7702400e12bf1718e9cef5599ba1c3882fe8046a90874eefce8f2ccc20e4f2741fb0a33a3848aec9c9305fbecbd2d76819967d4671acc6431e4037968db37878e695c102410095297b0f95a2fa67d00707d609dfd4fc05c89dafc2ef6d6ea55bec771ea333734d9251e79082ecda866efef13c459e1a631386b7e354c899f5f112ca85d7158302404f456c502493bdc0ed2ab756a3a6ed4d67352a697d4216e93212b127a63d5411ce6fa98d5dbefd73263e3728142743818166ed7dd63687dd2a8ca1d2f4fbd8e1
+
+Decrypt = RSA-OAEP-1
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 354fe67b4a126d5d35fe36c777791a3f7ba13def484e2d3908aff722fad468fb21696de95d0be911c2d3174f8afcc201035f7b6d8e69402de5451618c21a535fa9d7bfc5b8dd9fc243f8cf927db31322d6e881eaa91a996170e657a05a266426d98c88003f8477c1227094a0d9fa1e8c4024309ce1ecccb5210035d47ac72e8a
+Output = 6628194e12073db03ba94cda9ef9532397d50dba79b987004afefe34
+
+Decrypt = RSA-OAEP-1
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 640db1acc58e0568fe5407e5f9b701dff8c3c91e716c536fc7fcec6cb5b71c1165988d4a279e1577d730fc7a29932e3f00c81515236d8d8e31017a7a09df4352d904cdeb79aa583adcc31ea698a4c05283daba9089be5491f67c1a4ee48dc74bbbe6643aef846679b4cb395a352d5ed115912df696ffe0702932946d71492b44
+Output = 750c4047f547e8e41411856523298ac9bae245efaf1397fbe56f9dd5
+
+Decrypt = RSA-OAEP-1
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 423736ed035f6026af276c35c0b3741b365e5f76ca091b4e8c29e2f0befee603595aa8322d602d2e625e95eb81b2f1c9724e822eca76db8618cf09c5343503a4360835b5903bc637e3879fb05e0ef32685d5aec5067cd7cc96fe4b2670b6eac3066b1fcf5686b68589aafb7d629b02d8f8625ca3833624d4800fb081b1cf94eb
+Output = d94ae0832e6445ce42331cb06d531a82b1db4baad30f746dc916df24d4e3c2451fff59a6423eb0e1d02d4fe646cf699dfd818c6e97b051
+
+Decrypt = RSA-OAEP-1
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 45ead4ca551e662c9800f1aca8283b0525e6abae30be4b4aba762fa40fd3d38e22abefc69794f6ebbbc05ddbb11216247d2f412fd0fba87c6e3acd888813646fd0e48e785204f9c3f73d6d8239562722dddd8771fec48b83a31ee6f592c4cfd4bc88174f3b13a112aae3b9f7b80e0fc6f7255ba880dc7d8021e22ad6a85f0755
+Output = 52e650d98e7f2a048b4f86852153b97e01dd316f346a19f67a85
+
+Decrypt = RSA-OAEP-1
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 36f6e34d94a8d34daacba33a2139d00ad85a9345a86051e73071620056b920e219005855a213a0f23897cdcd731b45257c777fe908202befdd0b58386b1244ea0cf539a05d5d10329da44e13030fd760dcd644cfef2094d1910d3f433e1c7c6dd18bc1f2df7f643d662fb9dd37ead9059190f4fa66ca39e869c4eb449cbdc439
+Output = 8da89fd9e5f974a29feffb462b49180f6cf9e802
+
+Decrypt = RSA-OAEP-1
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 42cee2617b1ecea4db3f4829386fbd61dafbf038e180d837c96366df24c097b4ab0fac6bdf590d821c9f10642e681ad05b8d78b378c0f46ce2fad63f74e0ad3df06b075d7eb5f5636f8d403b9059ca761b5c62bb52aa45002ea70baace08ded243b9d8cbd62a68ade265832b56564e43a6fa42ed199a099769742df1539e8255
+Output = 26521050844271
+
+PrivateKey = RSA-OAEP-2
+Type = RSA
+Input = 30820276020100300d06092a864886f70d0101010500048202603082025c02010002818101947c7fce90425f47279e70851f25d5e62316fe8a1df19371e3e628e260543e4901ef6081f68c0b8141190d2ae8daba7d1250ec6db636e944ec3722877c7c1d0a67f14b1694c5f0379451a43e49a32dde83670b73da91a1c99bc23b436a60055c610f0baf99c1a079565b95a3f1526632d1d4da60f20eda25e653c4f002766f4502030100010281800823f20fadb5da89088a9d00893e21fa4a1b11fbc93c64a3be0baaea97fb3b93c3ff713704c19c963c1d107aae99054739f79e02e186de86f87a6ddefea6d8ccd1d3c81a47bfa7255be20601a4a4b2f08a167b5e279d715b1b455bdd7eab245941d9768b9acefb3ccda5952da3cee72525b4501663a8ee15c9e992d92462fe3902410159dbde04a33ef06fb608b80b190f4d3e22bcc13ac8e4a081033abfa416edb0b338aa08b57309ea5a5240e7dc6e54378c69414c31d97ddb1f406db3769cc41a430241012b652f30403b38b40995fd6ff41a1acc8ada70373236b7202d39b2ee30cfb46db09511f6f307cc61cc21606c18a75b8a62f822df031ba0df0dafd5506f568bd70240436ef508de736519c2da4c580d98c82cb7452a3fb5efadc3b9c7789a1bc6584f795addbbd32439c74686552ecb6c2c307a4d3af7f539eec157248c7b31f1a2550241012b15a89f3dfb2b39073e73f02bdd0c1a7b379dd435f05cdde2eff9e462948b7cec62ee9050d5e0816e0785a856b49108dcb75f3683874d1ca6329a19013066ff02400270db17d5914b018d76118b24389a7350ec836b0063a21721236fd8edb6d89b51e7eeb87b611b7132cb7ea7356c23151c1e7751507c786d9ee1794170a8c8e8
+
+Decrypt = RSA-OAEP-2
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 0181af8922b9fcb4d79d92ebe19815992fc0c1439d8bcd491398a0f4ad3a329a5bd9385560db532683c8b7da04e4b12aed6aacdf471c34c9cda891addcc2df3456653aa6382e9ae59b54455257eb099d562bbe10453f2b6d13c59c02e10f1f8abb5da0d0570932dacf2d0901db729d0fefcc054e70968ea540c81b04bcaefe720e
+Output = 8ff00caa605c702830634d9a6c3d42c652b58cf1d92fec570beee7
+
+Decrypt = RSA-OAEP-2
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 018759ff1df63b2792410562314416a8aeaf2ac634b46f940ab82d64dbf165eee33011da749d4bab6e2fcd18129c9e49277d8453112b429a222a8471b070993998e758861c4d3f6d749d91c4290d332c7a4ab3f7ea35ff3a07d497c955ff0ffc95006b62c6d296810d9bfab024196c7934012c2df978ef299aba239940cba10245
+Output = 2d
+
+Decrypt = RSA-OAEP-2
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 018802bab04c60325e81c4962311f2be7c2adce93041a00719c88f957575f2c79f1b7bc8ced115c706b311c08a2d986ca3b6a9336b147c29c6f229409ddec651bd1fdd5a0b7f610c9937fdb4a3a762364b8b3206b4ea485fd098d08f63d4aa8bb2697d027b750c32d7f74eaf5180d2e9b66b17cb2fa55523bc280da10d14be2053
+Output = 74fc88c51bc90f77af9d5e9a4a70133d4b4e0b34da3c37c7ef8e
+
+Decrypt = RSA-OAEP-2
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 00a4578cbc176318a638fba7d01df15746af44d4f6cd96d7e7c495cbf425b09c649d32bf886da48fbaf989a2117187cafb1fb580317690e3ccd446920b7af82b31db5804d87d01514acbfa9156e782f867f6bed9449e0e9a2c09bcecc6aa087636965e34b3ec766f2fe2e43018a2fddeb140616a0e9d82e5331024ee0652fc7641
+Output = a7eb2a5036931d27d4e891326d99692ffadda9bf7efd3e34e622c4adc085f721dfe885072c78a203b151739be540fa8c153a10f00a
+
+Decrypt = RSA-OAEP-2
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 00ebc5f5fda77cfdad3c83641a9025e77d72d8a6fb33a810f5950f8d74c73e8d931e8634d86ab1246256ae07b6005b71b7f2fb98351218331ce69b8ffbdc9da08bbc9c704f876deb9df9fc2ec065cad87f9090b07acc17aa7f997b27aca48806e897f771d95141fe4526d8a5301b678627efab707fd40fbebd6e792a25613e7aec
+Output = 2ef2b066f854c33f3bdcbb5994a435e73d6c6c
+
+Decrypt = RSA-OAEP-2
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 010839ec20c27b9052e55befb9b77e6fc26e9075d7a54378c646abdf51e445bd5715de81789f56f1803d9170764a9e93cb78798694023ee7393ce04bc5d8f8c5a52c171d43837e3aca62f609eb0aa5ffb0960ef04198dd754f57f7fbe6abf765cf118b4ca443b23b5aab266f952326ac4581100644325f8b721acd5d04ff14ef3a
+Output = 8a7fb344c8b6cb2cf2ef1f643f9a3218f6e19bba89c0
+
+PrivateKey = RSA-OAEP-3
+Type = RSA
+Input = 30820277020100300d06092a864886f70d0101010500048202613082025d02010002818102b58fec039a860700a4d7b6462f93e6cdd491161ddd74f4e810b40e3c1652006a5c277b2774c11305a4cbab5a78efa57e17a86df7a3fa36fc4b1d2249f22ec7c2dd6a463232accea906d66ebe80b5704b10729da6f833234abb5efdd4a292cbfad33b4d33fa7a14b8c397b56e3acd21203428b77cdfa33a6da706b3d8b0fc43e9020301000102818015b48a5b5683a94670e23b5718f814fa0e13f85038f50711182cba61510581f3d22c7e232ef937e22e551d68b86e2f8cb1aad8be2e488f5df7efd279e3f568d4eaf36f80cf7141ace60fcc9113fb6c4a841fd50bbc7c512ffcbeff21487aa811eb3ca8c62005346a86de86bfa1d8a948fd3f348c22eaadf333c3ce6ce13208fd024101bf01d216d73595cf0270c2beb78d40a0d8447d31da919a983f7eea781b77d85fe371b3e9373e7b69217d3150a02d8958de7fad9d555160958b4454127e0e7eaf0241018d3399658166db3829816d7b295416759e9c91987f5b2d8aecd63b04b48bd7b2fcf229bb7f8a6dc88ba13dd2e39ad55b6d1a06160708f9700be80b8fd3744ce7024006c0a249d20a6f2ee75c88b494d53f6aae99aa427c88c28b163a769445e5f390cf40c274fd6ea6329a5ce7c7ce03a2158396ee2a7845786e09e2885a9728e4e5024100d1d27c29fedd92d86c348edd0ccbfac14f746e051ce1d1811df35d61f2ee1c97d4bf2804802f6427187ba8e90a8af44243b4079b03445e602e29fa5193e64fe90241008cb2f756bd8941b1d3b770e5ad31ee373b28acda69ff9b6f40fe578b9f1afb85836f9627d37acff73c2779e634bb26011c2c8f7f3361ae2a9ea65ed689e3639a
+
+Decrypt = RSA-OAEP-3
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 026a0485d96aebd96b4382085099b962e6a2bdec3d90c8db625e14372de85e2d5b7baab65c8faf91bb5504fb495afce5c988b3f6a52e20e1d6cbd3566c5cd1f2b8318bb542cc0ea25c4aab9932afa20760eaddec784396a07ea0ef24d4e6f4d37e5052a7a31e146aa480a111bbe926401307e00f410033842b6d82fe5ce4dfae80
+Output = 087820b569e8fa8d
+
+Decrypt = RSA-OAEP-3
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 024db89c7802989be0783847863084941bf209d761987e38f97cb5f6f1bc88da72a50b73ebaf11c879c4f95df37b850b8f65d7622e25b1b889e80fe80baca2069d6e0e1d829953fc459069de98ea9798b451e557e99abf8fe3d9ccf9096ebbf3e5255d3b4e1c6d2ecadf067a359eea86405acd47d5e165517ccafd47d6dbee4bf5
+Output = 4653acaf171960b01f52a7be63a3ab21dc368ec43b50d82ec3781e04
+
+Decrypt = RSA-OAEP-3
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 0239bce681032441528877d6d1c8bb28aa3bc97f1df584563618995797683844ca86664732f4bed7a0aab083aaabfb7238f582e30958c2024e44e57043b97950fd543da977c90cdde5337d618442f99e60d7783ab59ce6dd9d69c47ad1e962bec22d05895cff8d3f64ed5261d92b2678510393484990ba3f7f06818ae6ffce8a3a
+Output = d94cd0e08fa404ed89
+
+Decrypt = RSA-OAEP-3
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 02994c62afd76f498ba1fd2cf642857fca81f4373cb08f1cbaee6f025c3b512b42c3e8779113476648039dbe0493f9246292fac28950600e7c0f32edf9c81b9dec45c3bde0cc8d8847590169907b7dc5991ceb29bb0714d613d96df0f12ec5d8d3507c8ee7ae78dd83f216fa61de100363aca48a7e914ae9f42ddfbe943b09d9a0
+Output = 6cc641b6b61e6f963974dad23a9013284ef1
+
+Decrypt = RSA-OAEP-3
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 0162042ff6969592a6167031811a239834ce638abf54fec8b99478122afe2ee67f8c5b18b0339805bfdbc5a4e6720b37c59cfba942464c597ff532a119821545fd2e59b114e61daf71820529f5029cf524954327c34ec5e6f5ba7efcc4de943ab8ad4ed787b1454329f70db798a3a8f4d92f8274e2b2948ade627ce8ee33e43c60
+Output = df5151832b61f4f25891fb4172f328d2eddf8371ffcfdbe997939295f30eca6918017cfda1153bf7a6af87593223
+
+Decrypt = RSA-OAEP-3
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 00112051e75d064943bc4478075e43482fd59cee0679de6893eec3a943daa490b9691c93dfc0464b6623b9f3dbd3e70083264f034b374f74164e1a00763725e574744ba0b9db83434f31df96f6e2a26f6d8eba348bd4686c2238ac07c37aac3785d1c7eea2f819fd91491798ed8e9cef5e43b781b0e0276e37c43ff9492d005730
+Output = 3c3bad893c544a6d520ab022319188c8d504b7a788b850903b85972eaa18552e1134a7ad6098826254ff7ab672b3d8eb3158fac6d4cbaef1
+
+PrivateKey = RSA-OAEP-4
+Type = RSA
+Input = 30820277020100300d06092a864886f70d0101010500048202613082025d020100028181051240b6cc0004fa48d0134671c078c7c8dec3b3e2f25bc2564467339db38853d06b85eea5b2de353bff42ac2e46bc97fae6ac9618da9537a5c8f553c1e357625991d6108dcd7885fb3a25413f53efcad948cb35cd9b9ae9c1c67626d113d57dde4c5bea76bb5bb7de96c00d07372e9685a6d75cf9d239fa148d70931b5f3fb03902030100010281800411ffca3b7ca5e9e9be7fe38a85105e353896db05c5796aecd2a725161eb3651c8629a9b862b904d7b0c7b37f8cb5a1c2b54001018a00a1eb2cafe4ee4e9492c348bc2bedab4b9ebbf064e8eff322b9009f8eec653905f40df88a3cdc49d4567f75627d41aca624129b46a0b7c698e5e65f2b7ba102c749a10135b6540d04010241027458c19ec1636919e736c9af25d609a51b8f561d19c6bf6943dd1ee1ab8a4a3f232100bd40b88decc6ba235548b6ef792a11c9de823d0a7922c7095b6eba570102410210ee9b33ab61716e27d251bd465f4b35a1a232e2da00901c294bf22350ce490d099f642b5375612db63ba1f20386492bf04d34b3c22bceb909d13441b53b5139024039fa028b826e88c1121b750a8b242fa9a35c5b66bdfd1fa637d3cc48a84a4f457a194e7727e49f7bcc6e5a5a412657fc470c7322ebc37416ef458c307a8c09010241015d99a84195943979fa9e1be2c3c1b69f432f46fd03e47d5befbbbfd6b1d1371d83efb330a3e020942b2fed115e5d02be24fd92c9019d1cecd6dd4cf1e54cc899024101f0b7015170b3f5e42223ba30301c41a6d87cbb70e30cb7d3c67d25473db1f6cbf03e3f9126e3e97968279a865b2c2b426524cfc52a683d31ed30eb984be412ba
+
+Decrypt = RSA-OAEP-4
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 04cce19614845e094152a3fe18e54e3330c44e5efbc64ae16886cb1869014cc5781b1f8f9e045384d0112a135ca0d12e9c88a8e4063416deaae3844f60d6e96fe155145f4525b9a34431ca3766180f70e15a5e5d8e8b1a516ff870609f13f896935ced188279a58ed13d07114277d75c6568607e0ab092fd803a223e4a8ee0b1a8
+Output = 4a86609534ee434a6cbca3f7e962e76d455e3264c19f605f6e5ff6137c65c56d7fb344cd52bc93374f3d166c9f0c6f9c506bad19330972d2
+
+Decrypt = RSA-OAEP-4
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 0097b698c6165645b303486fbf5a2a4479c0ee85889b541a6f0b858d6b6597b13b854eb4f839af03399a80d79bda6578c841f90d645715b280d37143992dd186c80b949b775cae97370e4ec97443136c6da484e970ffdb1323a20847821d3b18381de13bb49aaea66530c4a4b8271f3eae172cd366e07e6636f1019d2a28aed15e
+Output = b0adc4f3fe11da59ce992773d9059943c03046497ee9d9f9a06df1166db46d98f58d27ec074c02eee6cbe2449c8b9fc5080c5c3f4433092512ec46aa793743c8
+
+Decrypt = RSA-OAEP-4
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 0301f935e9c47abcb48acbbe09895d9f5971af14839da4ff95417ee453d1fd77319072bb7297e1b55d7561cd9d1bb24c1a9a37c619864308242804879d86ebd001dce5183975e1506989b70e5a83434154d5cbfd6a24787e60eb0c658d2ac193302d1192c6e622d4a12ad4b53923bca246df31c6395e37702c6a78ae081fb9d065
+Output = bf6d42e701707b1d0206b0c8b45a1c72641ff12889219a82bdea965b5e79a96b0d0163ed9d578ec9ada20f2fbcf1ea3c4089d83419ba81b0c60f3606da99
+
+Decrypt = RSA-OAEP-4
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 02d110ad30afb727beb691dd0cf17d0af1a1e7fa0cc040ec1a4ba26a42c59d0a796a2e22c8f357ccc98b6519aceb682e945e62cb734614a529407cd452bee3e44fece8423cc19e55548b8b994b849c7ecde4933e76037e1d0ce44275b08710c68e430130b929730ed77e09b015642c5593f04e4ffb9410798102a8e96ffdfe11e4
+Output = fb2ef112f5e766eb94019297934794f7be2f6fc1c58e
+
+Decrypt = RSA-OAEP-4
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 00dbb8a7439d90efd919a377c54fae8fe11ec58c3b858362e23ad1b8a44310799066b99347aa525691d2adc58d9b06e34f288c170390c5f0e11c0aa3645959f18ee79e8f2be8d7ac5c23d061f18dd74b8c5f2a58fcb5eb0c54f99f01a83247568292536583340948d7a8c97c4acd1e98d1e29dc320e97a260532a8aa7a758a1ec2
+Output = 28ccd447bb9e85166dabb9e5b7d1adadc4b9d39f204e96d5e440ce9ad928bc1c2284
+
+Decrypt = RSA-OAEP-4
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 00a5ffa4768c8bbecaee2db77e8f2eec99595933545520835e5ba7db9493d3e17cddefe6a5f567624471908db4e2d83a0fbee60608fc84049503b2234a07dc83b27b22847ad8920ff42f674ef79b76280b00233d2b51b8cb2703a9d42bfbc8250c96ec32c051e57f1b4ba528db89c37e4c54e27e6e64ac69635ae887d9541619a9
+Output = f22242751ec6b1
+
+PrivateKey = RSA-OAEP-5
+Type = RSA
+Input = 30820279020100300d06092a864886f70d0101010500048202633082025f0201000281810aadf3f9c125e5d891f31ac448e993defe580f802b45f9d7f22ba5021e9c47576b5a1e68031ba9db4e6dabe4d96a1d6f3d267268cff408005f118efcadb99888d1c234467166b2a2b849a05a889c060ac0da0c5fae8b55f309ba62e703742fa0326f2d10b011021489ff497770190d895fd39f52293c39efd73a698bdab9f10ed902030100010281810256eb4cba7067f2d2be540dcdff4582a36b7d31d1c9099bb214b79848466a268f80f58a49ac04c0e3648934a0206c04537c19b236643a6082732144df75fa217588f794682be89168276dc726c5c0cbdb84d31bbf26d0a43af495717f7d528acfee341561f6ff3cae05c578f8470d9682f9c0d072f9f6068b56d5880f682be2c5024103b0d3962f6d17549cbfca11294348dcf0e7e39f8c2bc6824f2164b606d687860dae1e632393cfedf513228229069e2f60e4acd7e633a436063f82385f48993707024102e4c32e2f517269b7072309f00c0e31365f7ce28b236b82912df239abf39572cf0ed604b02982e53564c52d6a05397de5c052a2fddc141ef7189836346aeb331f024101e84b119d25161fa67b00256a5bd9b645d2b232ecb05b015180029a88622adc3f09b3aeacde6161ab7cde22c2ad26e7797df54e072cbd3b2673800b3e4338dbd5024100eb90aa1a40135b4cea07197cedc8819be1e7cbff2547662116f465a4a9f487ab12f3ba4fef13822265a65297d98b7bded9372e3ffe81a38b3e9600fed055754f0241012f7f8138f9404062eb85a42924520b38f5bb886a0196f48bb8dcea60fd92cc027f18e78158a34a5c5d5f860a0f6c04071a7d01312c065062f1eb48b79d1c83cb
+
+Decrypt = RSA-OAEP-5
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 036046a4a47d9ed3ba9a89139c105038eb7492b05a5d68bfd53accff4597f7a68651b47b4a4627d927e485eed7b4566420e8b409879e5d606eae251d22a5df799f7920bfc117b992572a53b1263146bcea03385cc5e853c9a101c8c3e1bda31a519807496c6cb5e5efb408823a352b8fa0661fb664efadd593deb99fff5ed000e5
+Output = af71a901e3a61d3132f0fc1fdb474f9ea6579257ffc24d164170145b3dbde8
+
+Decrypt = RSA-OAEP-5
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 03d6eb654edce615bc59f455265ed4e5a18223cbb9be4e4069b473804d5de96f54dcaaa603d049c5d94aa1470dfcd2254066b7c7b61ff1f6f6770e3215c51399fd4e34ec5082bc48f089840ad04354ae66dc0f1bd18e461a33cc1258b443a2837a6df26759aa2302334986f87380c9cc9d53be9f99605d2c9a97da7b0915a4a7ad
+Output = a3b844a08239a8ac41605af17a6cfda4d350136585903a417a79268760519a4b4ac3303ec73f0f87cfb32399
+
+Decrypt = RSA-OAEP-5
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 0770952181649f9f9f07ff626ff3a22c35c462443d905d456a9fd0bff43cac2ca7a9f554e9478b9acc3ac838b02040ffd3e1847de2e4253929f9dd9ee4044325a9b05cabb808b2ee840d34e15d105a3f1f7b27695a1a07a2d73fe08ecaaa3c9c9d4d5a89ff890d54727d7ae40c0ec1a8dd86165d8ee2c6368141016a48b55b6967
+Output = 308b0ecbd2c76cb77fc6f70c5edd233fd2f20929d629f026953bb62a8f4a3a314bde195de85b5f816da2aab074d26cb6acddf323ae3b9c678ac3cf12fbdde7
+
+Decrypt = RSA-OAEP-5
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 0812b76768ebcb642d040258e5f4441a018521bd96687e6c5e899fcd6c17588ff59a82cc8ae03a4b45b31299af1788c329f7dcd285f8cf4ced82606b97612671a45bedca133442144d1617d114f802857f0f9d739751c57a3f9ee400912c61e2e6992be031a43dd48fa6ba14eef7c422b5edc4e7afa04fdd38f402d1c8bb719abf
+Output = 15c5b9ee1185
+
+Decrypt = RSA-OAEP-5
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 07b60e14ec954bfd29e60d0047e789f51d57186c63589903306793ced3f68241c743529aba6a6374f92e19e0163efa33697e196f7661dfaaa47aac6bde5e51deb507c72c589a2ca1693d96b1460381249b2cdb9eac44769f2489c5d3d2f99f0ee3c7ee5bf64a5ac79c42bd433f149be8cb59548361640595513c97af7bc2509723
+Output = 21026e6800c7fa728fcaaba0d196ae28d7a2ac4ffd8abce794f0985f60c8a6737277365d3fea11db8923a2029a
+
+Decrypt = RSA-OAEP-5
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 08c36d4dda33423b2ed6830d85f6411ba1dcf470a1fae0ebefee7c089f256cef74cb96ea69c38f60f39abee44129bcb4c92de7f797623b20074e3d9c2899701ed9071e1efa0bdd84d4c3e5130302d8f0240baba4b84a71cc032f2235a5ff0fae277c3e8f9112bef44c9ae20d175fc9a4058bfc930ba31b02e2e4f444483710f24a
+Output = 541e37b68b6c8872b84c02
+
+PrivateKey = RSA-OAEP-6
+Type = RSA
+Input = 30820279020100300d06092a864886f70d0101010500048202633082025f02010002818112b17f6dad2ecd19ff46dc13f7860f09e0e0cfb677b38a52592305ceaf022c166db90d04ac29e33f7dd12d9faf66e0816bb63ead267cc7d46c17c37be214bca2a22d723a64e44407436b6fc965729aefc2554f376cd5dcea68293780a62bf39d0029485a160bbb9e5dc0972d21a504f52e5ee028aa416332f510b2e9cff5f722af02030100010281810295eca3560618369559cecd303aa9cfdafc1d9f06959df75ffef929aa896961bcd190dc6997eda7f5963e724d07b4dc11f3065e5ae97d96835112280b9084bb14f2a21ebd4e889d41b9c4132ec1956fcab8bb2fed0575884936522c5ff7d33261904824e7cadee4e0bb372d2457cf78e2bd1286228ff83f10731ce63c90cff3f9024104a6ce8b7358dfa69bdcf742617005afb5385f5f3a58a24ef74a22a8c05cb7cc38ebd4cc9d9a9d789a62cd0f60f0cb941d3423c9692efa4fe3adff290c4749a38b02410404c9a803371fedb4c5be39f3c00b009e5e08a63be1e40035cdaca5011cc701cf7eebcb99f0ffe17cfd0a4bf7befd2dd536ac946db797fdbc4abe8f29349b91ed024103961c8f760aa2bd5154c7aafd77225b3bacd0139ae7b5948ea3311fccd86fb95c75afa767284b9b2de559572f15d8d044c7eb83a1be5fadf2cc377c0d8475294b0241022197e066742196aabc03fa2feeb4e70b15cb787d617acd31bb75c7bc234ad706f7c48d2182d1f0ff9c228dcf41967b6c0ba6d2c0ad110a1b857831ec245e2cb102410401c4c0c53d45dbdb5e9d96d0fecf4275df0974bc4a0736b4a74c3269053efb686ace2406e22c9e058ddb4ae540627ae2fdb08261e8e7e4bcbc994daafa305c45
+
+Decrypt = RSA-OAEP-6
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 0630eebcd2856c24f798806e41f9e67345eda9ceda386acc9facaea1eeed06ace583709718d9d169fadf414d5c76f92996833ef305b75b1e4b95f662a20faedc3bae0c4827a8bf8a88edbd57ec203a27a841f02e43a615bab1a8cac0701de34debdef62a088089b55ec36ea7522fd3ec8d06b6a073e6df833153bc0aefd93bd1a3
+Output = 4046ca8baa3347ca27f49e0d81f9cc1d71be9ba517d4
+
+Decrypt = RSA-OAEP-6
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 0ebc37376173a4fd2f89cc55c2ca62b26b11d51c3c7ce49e8845f74e7607317c436bc8d23b9667dfeb9d087234b47bc6837175ae5c0559f6b81d7d22416d3e50f4ac533d8f0812f2db9e791fe9c775ac8b6ad0f535ad9ceb23a4a02014c58ab3f8d3161499a260f39348e714ae2a1d3443208fd8b722ccfdfb393e98011f99e63f
+Output = 5cc72c60231df03b3d40f9b57931bc31109f972527f28b19e7480c7288cb3c92b22512214e4be6c914792ddabdf57faa8aa7
+
+Decrypt = RSA-OAEP-6
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 0a98bf1093619394436cf68d8f38e2f158fde8ea54f3435f239b8d06b8321844202476aeed96009492480ce3a8d705498c4c8c68f01501dc81db608f60087350c8c3b0bd2e9ef6a81458b7c801b89f2e4fe99d4900ba6a4b5e5a96d865dc676c7755928794130d6280a8160a190f2df3ea7cf9aa0271d88e9e6905ecf1c5152d65
+Output = b20e651303092f4bccb43070c0f86d23049362ed96642fc5632c27db4a52e3d831f2ab068b23b149879c002f6bf3feee97591112562c
+
+Decrypt = RSA-OAEP-6
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 008e7a67cacfb5c4e24bec7dee149117f19598ce8c45808fef88c608ff9cd6e695263b9a3c0ad4b8ba4c95238e96a8422b8535629c8d5382374479ad13fa39974b242f9a759eeaf9c83ad5a8ca18940a0162ba755876df263f4bd50c6525c56090267c1f0e09ce0899a0cf359e88120abd9bf893445b3cae77d3607359ae9a52f8
+Output = 684e3038c5c041f7
+
+Decrypt = RSA-OAEP-6
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 00003474416c7b68bdf961c385737944d7f1f40cb395343c693cc0b4fe63b31fedf1eaeeac9ccc0678b31dc32e0977489514c4f09085f6298a9653f01aea4045ff582ee887be26ae575b73eef7f3774921e375a3d19adda0ca31aa1849887c1f42cac9677f7a2f4e923f6e5a868b38c084ef187594dc9f7f048fea2e02955384ab
+Output = 32488cb262d041d6e4dd35f987bf3ca696db1f06ac29a44693
+
+Decrypt = RSA-OAEP-6
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 0a026dda5fc8785f7bd9bf75327b63e85e2c0fdee5dadb65ebdcac9ae1de95c92c672ab433aa7a8e69ce6a6d8897fac4ac4a54de841ae5e5bbce7687879d79634cea7a30684065c714d52409b928256bbf53eabcd5231eb7259504537399bd29164b726d33a46da701360a4168a091ccab72d44a62fed246c0ffea5b1348ab5470
+Output = 50ba14be8462720279c306ba
+
+PrivateKey = RSA-OAEP-7
+Type = RSA
+Input = 30820278020100300d06092a864886f70d0101010500048202623082025e020100028181311179f0bcfc9b9d3ca315d00ef30d7bdd3a2cfae9911bfedcb948b3a4782d0732b6ab44aa4bf03741a644dc01bec3e69b01a033e675d8acd7c4925c6b1aec3119051dfd89762d215d45475ffcb59f908148623f37177156f6ae86dd7a7c5f43dc1e1f908254058a284a5f06c0021793a87f1ac5feff7dcaee69c5e51a3789e3730203010001028181070cfcff2feb8276e27432c45dfee48f49b7917d6530e1f0ca3460f32e0276174487c56e22a45d2500d7775495219d7d165a9cf3bd92c32af9a98d8dc9cc296800adc94a0a54fb40f34291bf84ee8ea12b6f109359c6d3542a50f9c767f5cfff05a681c2e656fb77caaadb4be9468d8abcd4df98f58e86d2053fa1349f748e21b102410749262c111cd470ec2566e6b3732fc09329469aa19071d3b9c01906514c6f1d26baa14beab0971c8b7e611a4f79009d6fea776928ca25285b0de3643d1a3f8c71024106bc1e50e96c02bf636e9eea8b899bbebf7651de77dd474c3e9bc23bad8182b61904c7d97dfbebfb1e00108878b6e67e415391d67942c2b2bf9b4435f88b0cb023024103bc7ea7f0aab143abc6ce8b97118636a30172e4cfe02c8fa0dda3b7baaf90f8092982985525f488bdfcb4bd726e22639ac64a3092ab7ffcbf1d5334cfa50b5bf102410262a6aa29c2a3c67dc5346c06381afd987aa3cc93cfbfecf54fdd9f9d787d7f59a523d398979da137a2f6381fe94801f7c94da21518dc34cb40870c4697994ad90240649d4c17b6ee1721e772d0389a559c3d3cdf9550d457c46b037b74641b1d52166af8a213c8396206cdfba4422f18d6f61dbcb5d214c971bf482aeb976a7370c2
+
+Decrypt = RSA-OAEP-7
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 1688e4ce7794bba6cb7014169ecd559cede2a30b56a52b68d9fe18cf1973ef97b2a03153951c755f6294aa49adbdb55845ab6875fb3986c93ecf927962840d282f9e54ce8b690f7c0cb8bbd73440d9571d1b16cd9260f9eab4783cc482e5223dc60973871783ec27b0ae0fd47732cbc286a173fc92b00fb4ba6824647cd93c85c1
+Output = 47aae909
+
+Decrypt = RSA-OAEP-7
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 1052ed397b2e01e1d0ee1c50bf24363f95e504f4a03434a08fd822574ed6b9736edbb5f390db10321479a8a139350e2bd4977c3778ef331f3e78ae118b268451f20a2f01d471f5d53c566937171b2dbc2d4bde459a5799f0372d6574239b2323d245d0bb81c286b63c89a361017337e4902f88a467f4c7f244bfd5ab46437ff3b6
+Output = 1d9b2e2223d9bc13bfb9f162ce735db48ba7c68f6822a0a1a7b6ae165834e7
+
+Decrypt = RSA-OAEP-7
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 2155cd843ff24a4ee8badb7694260028a490813ba8b369a4cbf106ec148e5298707f5965be7d101c1049ea8584c24cd63455ad9c104d686282d3fb803a4c11c1c2e9b91c7178801d1b6640f003f5728df007b8a4ccc92bce05e41a27278d7c85018c52414313a5077789001d4f01910b72aad05d220aa14a58733a7489bc54556b
+Output = d976fc
+
+Decrypt = RSA-OAEP-7
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 0ab14c373aeb7d4328d0aaad8c094d88b9eb098b95f21054a29082522be7c27a312878b637917e3d819e6c3c568db5d843802b06d51d9e98a2be0bf40c031423b00edfbff8320efb9171bd2044653a4cb9c5122f6c65e83cda2ec3c126027a9c1a56ba874d0fea23f380b82cf240b8cf540004758c4c77d934157a74f3fc12bfac
+Output = d4738623df223aa43843df8467534c41d013e0c803c624e263666b239bde40a5f29aeb8de79e3daa61dd0370f49bd4b013834b98212aef6b1c5ee373b3cb
+
+Decrypt = RSA-OAEP-7
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 028387a318277434798b4d97f460068df5298faba5041ba11761a1cb7316b24184114ec500257e2589ed3b607a1ebbe97a6cc2e02bf1b681f42312a33b7a77d8e7855c4a6de03e3c04643f786b91a264a0d6805e2cea91e68177eb7a64d9255e4f27e713b7ccec00dc200ebd21c2ea2bb890feae4942df941dc3f97890ed347478
+Output = bb47231ca5ea1d3ad46c99345d9a8a61
+
+Decrypt = RSA-OAEP-7
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 14c678a94ad60525ef39e959b2f3ba5c097a94ff912b67dbace80535c187abd47d075420b1872152bba08f7fc31f313bbf9273c912fc4c0149a9b0cfb79807e346eb332069611bec0ff9bcd168f1f7c33e77313cea454b94e2549eecf002e2acf7f6f2d2845d4fe0aab2e5a92ddf68c480ae11247935d1f62574842216ae674115
+Output = 2184827095d35c3f86f600e8e59754013296
+
+PrivateKey = RSA-OAEP-8
+Type = RSA
+Input = 30820279020100300d06092a864886f70d0101010500048202633082025f0201000281815bdf0e30d321dda5147f882408fa69195480df8f80d3f6e8bf5818504f36427ca9b1f5540b9c65a8f6974cf8447a244d9280201bb49fcbbe6378d1944cd227e230f96e3d10f819dcef276c64a00b2a4b6701e7d01de5fabde3b1e9a0df82f4631359cd22669647fbb1717246134ed7b497cfffbdc42b59c73a96ed90166212dff702030100010281810f7d1e9e5aaa25fd13e4a0663ae144e0d15f5cd18bcdb09df2cc7e64e3c5e915ad62645304161d098c715bb7ab8bd01d07eaf3fed7c7ed08af2a8a62ef44ab16b320e14af72a48f96afe262a0ae4cf65e635e910790cd4ee5cea768a4b2639f7e6f677b3f0bb6be32b75747d8909036f0264f58d401cdba131716157a75ecf633102410a02ef8448d9fad8bbd0d004c8c2aa9751ef9721c1b0d03236a54b0df947cbaed5a255ee9e8e20d491ea1723fe094704a9762e88afd16ebb5994412ca966dc4f9f0241092d362e7ed3a0bfd9e9fd0e6c0301b6df29159cf50cc83b9b0cf4d6eea71a61e002b46e0ae9f2de62d25b5d7452d498b81c9ac6fc58593d4c3fb4f5d72dfbb0a9024107c71410af103962db367404e37ae850baa4e9c29dd92145815294a67c7d1c6ded263aa030a9b633ae50303e14035d1af014123eba687820308d8ebc85b6957d7d024100ae2c75380c02c016ad05891b3301de881f28ae1171182b6b2c83bea7c515eca9ca298c7b1cab5817a597068fc85060de4da8a016378aae43c7f967bcc37904b902410598d1059e3ada4f6320752c09d805ff7d1f1ae0d017aeeee9cefa0d7dd7ff775e44b578322f6405d6211da19519666aa87fdc4cd8c88f6b6e3d67e961dcbba3d0
+
+Decrypt = RSA-OAEP-8
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 09b3683d8a2eb0fb295b62ed1fb9290b714457b7825319f4647872af889b30409472020ad12912bf19b11d4819f49614824ffd84d09c0a17e7d17309d12919790410aa2995699f6a86dbe3242b5acc23af45691080d6b1ae810fb3e3057087f0970092ce00be9562ff4053b6262ce0caa93e13723d2e3a5ba075d45f0d61b54b61
+Output = 050b755e5e6880f7b9e9d692a74c37aae449b31bfea6deff83747a897f6c2c825bb1adbf850a3c96994b5de5b33cbc7d4a17913a7967
+
+Decrypt = RSA-OAEP-8
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 2ecf15c97c5a15b1476ae986b371b57a24284f4a162a8d0c8182e7905e792256f1812ba5f83f1f7a130e42dcc02232844edc14a31a68ee97ae564a383a3411656424c5f62ddb646093c367be1fcda426cf00a06d8acb7e57776fbbd855ac3df506fc16b1d7c3f2110f3d8068e91e186363831c8409680d8da9ecd8cf1fa20ee39d
+Output = 4eb68dcd93ca9b19df111bd43608f557026fe4aa1d5cfac227a3eb5ab9548c18a06dded23f81825986b2fcd71109ecef7eff88873f075c2aa0c469f69c92bc
+
+Decrypt = RSA-OAEP-8
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 4bc89130a5b2dabb7c2fcf90eb5d0eaf9e681b7146a38f3173a3d9cfec52ea9e0a41932e648a9d69344c50da763f51a03c95762131e8052254dcd2248cba40fd31667786ce05a2b7b531ac9dac9ed584a59b677c1a8aed8c5d15d68c05569e2be780bf7db638fd2bfd2a85ab276860f3777338fca989ffd743d13ee08e0ca9893f
+Output = 8604ac56328c1ab5ad917861
+
+Decrypt = RSA-OAEP-8
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 2e456847d8fc36ff0147d6993594b9397227d577752c79d0f904fcb039d4d812fea605a7b574dd82ca786f93752348438ee9f5b5454985d5f0e1699e3e7ad175a32e15f03deb042ab9fe1dd9db1bb86f8c089ccb45e7ef0c5ee7ca9b7290ca6b15bed47039788a8a93ff83e0e8d6244c71006362deef69b6f416fb3c684383fbd0
+Output = fdda5fbf6ec361a9d9a4ac68af216a0686f438b1e0e5c36b955f74e107f39c0dddcc
+
+Decrypt = RSA-OAEP-8
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 1fb9356fd5c4b1796db2ebf7d0d393cc810adf6145defc2fce714f79d93800d5e2ac211ea8bbecca4b654b94c3b18b30dd576ce34dc95436ef57a09415645923359a5d7b4171ef22c24670f1b229d3603e91f76671b7df97e7317c97734476d5f3d17d21cf82b5ba9f83df2e588d36984fd1b584468bd23b2e875f32f68953f7b2
+Output = 4a5f4914bee25de3c69341de07
+
+Decrypt = RSA-OAEP-8
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 3afd9c6600147b21798d818c655a0f4c9212db26d0b0dfdc2a7594ccb3d22f5bf1d7c3e112cd73fc7d509c7a8bafdd3c274d1399009f9609ec4be6477e453f075aa33db382870c1c3409aef392d7386ae3a696b99a94b4da0589447e955d16c98b17602a59bd736279fcd8fb280c4462d590bfa9bf13fed570eafde97330a2c210
+Output = 8e07d66f7b880a72563abcd3f35092bc33409fb7f88f2472be
+
+PrivateKey = RSA-OAEP-9
+Type = RSA
+Input = 30820397020100300d06092a864886f70d0101010500048203813082037d0201000281c100cf2cd41e34ca3a728ea5cb8aff64c36d27bdef5364e336fd68d3123c5a196a8c287013e853d5156d58d151954520fb4f6d7b17abb6817765909c576119659d902b1906ed8a2b10c155c24d124528dab9eeae379beac66e4a411786dcb8fd0062ebc030de1219a04c2a8c1b7dd3131e4d6b6caee2e31a5ed41ac1509b2ef1ee2ab18364be568ca941c25ecc84ff9d643b5ec1aaae102a20d73f479b780fd6da91075212d9eac03a0674d899eba2e431f4c44b615b6ba2232bd4b33baed73d625d02030100010281c0198c141e23715a92bccf6a119a5bc11389468d2811f548d727e17b4ab0eb986d6f211efb53b71f7ccbea87ee69c75ee615008c5332deb52bf390abdfbfe37d7205368159b2638c1de326e21d22251f0fb5848b3bf15005d2a74330f0afe916ee62ccc1344d1d83a709e60676273840f7f377424a5e0a4da75f01b31ff76819cf9cbfdd215243c3917c03ef38199312e567b3bf7aed3ab457f371ef8a1423f45b68c6e282ec111bba2833b987fd69fad83bc1b8c613c5e1ea16c11ed125ea7ec1026100fc8d6c04bec4eb9a8192ca7900cbe536e2e8b519decf33b2459798c6909df4f176db7d23190fc72b8865a718af895f1bcd9145298027423b605e70a47cf58390a8c3e88fc8c48e8b32e3da210dfbe3e881ea5674b6a348c21e93f9e55ea65efd026100d200d45e788aacea606a401d0460f87dd5c1027e12dc1a0d7586e8939d9cf789b40f51ac0442961de7d21cc21e05c83155c1f2aa9193387cfdf956cb48d153ba270406f9bbba537d4987d9e2f9942d7a14cbfffea74fecdda928d23e259f5ee1026100db16802f79a2f0d45f358d69fd33e44b81fae828622e93a54253e997d01b0743759da0e812b4aa4e6c8beab2328d5431955a418a67ff26a8c5c807a5da354e05ef31cc8cf758f463732950b03e265726fb94e39d6a572a26244ab08db75752ad026100a0a317cfe7df1423f87a6dee8451f4e2b4a67e5497f29b4f1e4e830b9fadd9401167026f5596e5a39c97817e0f5f16e27e19ec9902e01d7ea6fb9aa3c760afee1e381b69de6ac9c07585a06ad9c4ba00bf75c8ad2fa898a479e80ae294fed2a102600b21f335c353342eb44c3aa24445780c2d655b940174cae38c7c8a4e6493c0ba9fd303748267b083b9a7a6cb61e42db362b8c9896db7064e02ad5ae61587da15b4649c90594909feb37dbcb654beb7268ec801e5a8b4aa3911bebd88542f05be
+
+Decrypt = RSA-OAEP-9
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 267bcd118acab1fc8ba81c85d73003cb8610fa55c1d97da8d48a7c7f06896a4db751aa284255b9d36ad65f37653d829f1b37f97b8001942545b2fc2c55a7376ca7a1be4b1760c8e05a33e5aa2526b8d98e317088e7834c755b2a59b12631a182c05d5d43ab1779264f8456f515ce57dfdf512d5493dab7b7338dc4b7d78db9c091ac3baf537a69fc7f549d979f0eff9a94fda4169bd4d1d19a69c99e33c3b55490d501b39b1edae118ff6793a153261584d3a5f39f6e682e3d17c8cd1261fa72
+Output = f735fd55ba92592c3b52b8f9c4f69aaa1cbef8fe88add095595412467f9cf4ec0b896c59eda16210e7549c8abb10cdbc21a12ec9b6b5b8fd2f10399eb6
+
+Decrypt = RSA-OAEP-9
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 93ac9f0671ec29acbb444effc1a5741351d60fdb0e393fbf754acf0de49761a14841df7772e9bc82773966a1584c4d72baea00118f83f35cca6e537cbd4d811f5583b29783d8a6d94cd31be70d6f526c10ff09c6fa7ce069795a3fcd0511fd5fcb564bcc80ea9c78f38b80012539d8a4ddf6fe81e9cddb7f50dbbbbcc7e5d86097ccf4ec49189fb8bf318be6d5a0715d516b49af191258cd32dc833ce6eb4673c03a19bbace88cc54895f636cc0c1ec89096d11ce235a265ca1764232a689ae8
+Output = 81b906605015a63aabe42ddf11e1978912f5404c7474b26dce3ed482bf961ecc818bf420c54659
+
+Decrypt = RSA-OAEP-9
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 81ebdd95054b0c822ef9ad7693f5a87adfb4b4c4ce70df2df84ed49c04da58ba5fc20a19e1a6e8b7a3900b22796dc4e869ee6b42792d15a8eceb56c09c69914e813cea8f6931e4b8ed6f421af298d595c97f4789c7caa612c7ef360984c21b93edc5401068b5af4c78a8771b984d53b8ea8adf2f6a7d4a0ba76c75e1dd9f658f20ded4a46071d46d7791b56803d8fea7f0b0f8e41ae3f09383a6f9585fe7753eaaffd2bf94563108beecc207bbb535f5fcc705f0dde9f708c62f49a9c90371d3
+Output = fd326429df9b890e09b54b18b8f34f1e24
+
+Decrypt = RSA-OAEP-9
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = bcc35f94cde66cb1136625d625b94432a35b22f3d2fa11a613ff0fca5bd57f87b902ccdc1cd0aebcb0715ee869d1d1fe395f6793003f5eca465059c88660d446ff5f0818552022557e38c08a67ead991262254f10682975ec56397768537f4977af6d5f6aaceb7fb25dec5937230231fd8978af49119a29f29e424ab8272b47562792d5c94f774b8829d0b0d9f1a8c9eddf37574d5fa248eefa9c5271fc5ec2579c81bdd61b410fa61fe36e424221c113addb275664c801d34ca8c6351e4a858
+Output = f1459b5f0c92f01a0f723a2e5662484d8f8c0a20fc29dad6acd43bb5f3effdf4e1b63e07fdfe6628d0d74ca19bf2d69e4a0abf86d293925a796772f8088e
+
+Decrypt = RSA-OAEP-9
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 232afbc927fa08c2f6a27b87d4a5cb09c07dc26fae73d73a90558839f4fd66d281b87ec734bce237ba166698ed829106a7de6942cd6cdce78fed8d2e4d81428e66490d036264cef92af941d3e35055fe3981e14d29cbb9a4f67473063baec79a1179f5a17c9c1832f2838fd7d5e59bb9659d56dce8a019edef1bb3accc697cc6cc7a778f60a064c7f6f5d529c6210262e003de583e81e3167b89971fb8c0e15d44fffef89b53d8d64dd797d159b56d2b08ea5307ea12c241bd58d4ee278a1f2e
+Output = 53e6e8c729d6f9c319dd317e74b0db8e4ccca25f3c8305746e137ac63a63ef3739e7b595abb96e8d55e54f7bd41ab433378ffb911d
+
+Decrypt = RSA-OAEP-9
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 438cc7dc08a68da249e42505f8573ba60e2c2773d5b290f4cf9dff718e842081c383e67024a0f29594ea987b9d25e4b738f285970d195abb3a8c8054e3d79d6b9c9a8327ba596f1259e27126674766907d8d582ff3a8476154929adb1e6d1235b2ccb4ec8f663ba9cc670a92bebd853c8dbf69c6436d016f61add836e94732450434207f9fd4c43dec2a12a958efa01efe2669899b5e604c255c55fb7166de5589e369597bb09168c06dd5db177e06a1740eb2d5c82faeca6d92fcee9931ba9f
+Output = b6b28ea2198d0c1008bc64
+
+PrivateKey = RSA-OAEP-10
+Type = RSA
+Input = 308204bd020100300d06092a864886f70d0101010500048204a7308204a30201000282010100ae45ed5601cec6b8cc05f803935c674ddbe0d75c4c09fd7951fc6b0caec313a8df39970c518bffba5ed68f3f0d7f22a4029d413f1ae07e4ebe9e4177ce23e7f5404b569e4ee1bdcf3c1fb03ef113802d4f855eb9b5134b5a7c8085adcae6fa2fa1417ec3763be171b0c62b760ede23c12ad92b980884c641f5a8fac26bdad4a03381a22fe1b754885094c82506d4019a535a286afeb271bb9ba592de18dcf600c2aeeae56e02f7cf79fc14cf3bdc7cd84febbbf950ca90304b2219a7aa063aefa2c3c1980e560cd64afe779585b6107657b957857efde6010988ab7de417fc88d8f384c4e6e72c3f943e0c31c0c4a5cc36f879d8a3ac9d7d59860eaada6b83bb020301000102820100056b04216fe5f354ac77250a4b6b0c8525a85c59b0bd80c56450a22d5f438e596a333aa875e291dd43f48cb88b9d5fc0d499f9fcd1c397f9afc070cd9e398c8d19e61db7c7410a6b2675dfbf5d345b804d201add502d5ce2dfcb091ce9997bbebe57306f383e4d588103f036f7e85d1934d152a323e4a8db451d6f4a5b1b0f102cc150e02feee2b88dea4ad4c1baccb24d84072d14e1d24a6771f7408ee30564fb86d4393a34bcf0b788501d193303f13a2284b001f0f649eaf79328d4ac5c430ab4414920a9460ed1b7bc40ec653e876d09abc509ae45b525190116a0c26101848298509c1c3bf3a483e7274054e15e97075036e989f60932807b5257751e7902818100ecf5aecd1e5515fffacbd75a2816c6ebf49018cdfb4638e185d66a7396b6f8090f8018c7fd95cc34b857dc17f0cc6516bb1346ab4d582cadad7b4103352387b70338d084047c9d9539b6496204b3dd6ea442499207bec01f964287ff6336c3984658336846f56e46861881c10233d2176bf15a5e96ddc780bc868aa77d3ce76902818100bc46c464fc6ac4ca783b0eb08a3c841b772f7e9b2f28babd588ae885e1a0c61e4858a0fb25ac299990f35be85164c259ba1175cdd7192707135184992b6c29b746dd0d2cabe142835f7d148cc161524b4a09946d48b828473f1ce76b6cb6886c345c03e05f41d51b5c3a90a3f24073c7d74a4fe25d9cf21c75960f3fc386318302818100c73564571d00fb15d08a3de9957a50915d7126e9442dacf42bc82e862e5673ff6a008ed4d2e374617df89f17a160b43b7fda9cb6b6b74218609815f7d45ca263c159aa32d272d127faf4bc8ca2d77378e8aeb19b0ad7da3cb3de0ae7314980f62b6d4b0a875d1df03c1bae39ccd833ef6cd7e2d9528bf084d1f969e794e9f6c10281802658b37f6df9c1030be1db68117fa9d87e39ea2b693b7e6d3a2f70947413eec6142e18fb8dfcb6ac545d7c86a0ad48f8457170f0efb26bc48126c53efd1d16920198dc2a1107dc282db6a80cd3062360ba3fa13f70e4312ff1a6cd6b8fc4cd9c5c3db17c6d6a57212f73ae29f619327bad59b153858585ba4e28b60a62a45e490281806f38526b3925085534ef3e415a836ede8b86158a2c7cbfeccb0bd834304fec683ba8d4f479c433d43416e63269623cea100776d85aff401d3fff610ee65411ce3b1363d63a9709eede42647cea561493d54570a879c18682cd97710b96205ec31117d73b5f36223fadd6e8ba90dd7c0ee61d44e163251e20c7f66eb305117cb8
+
+Decrypt = RSA-OAEP-10
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 53ea5dc08cd260fb3b858567287fa91552c30b2febfba213f0ae87702d068d19bab07fe574523dfb42139d68c3c5afeee0bfe4cb7969cbf382b804d6e61396144e2d0e60741f8993c3014b58b9b1957a8babcd23af854f4c356fb1662aa72bfcc7e586559dc4280d160c126785a723ebeebeff71f11594440aaef87d10793a8774a239d4a04c87fe1467b9daf85208ec6c7255794a96cc29142f9a8bd418e3c1fd67344b0cd0829df3b2bec60253196293c6b34d3f75d32f213dd45c6273d505adf4cced1057cb758fc26aeefa441255ed4e64c199ee075e7f16646182fdb464739b68ab5daff0e63e9552016824f054bf4d3c8c90a97bb6b6553284eb429fcc
+Output = 8bba6bf82a6c0f86d5f1756e97956870b08953b06b4eb205bc1694ee
+
+Decrypt = RSA-OAEP-10
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = a2b1a430a9d657e2fa1c2bb5ed43ffb25c05a308fe9093c01031795f5874400110828ae58fb9b581ce9dddd3e549ae04a0985459bde6c626594e7b05dc4278b2a1465c1368408823c85e96dc66c3a30983c639664fc4569a37fe21e5a195b5776eed2df8d8d361af686e750229bbd663f161868a50615e0c337bec0ca35fec0bb19c36eb2e0bbcc0582fa1d93aacdb061063f59f2ce1ee43605e5d89eca183d2acdfe9f81011022ad3b43a3dd417dac94b4e11ea81b192966e966b182082e71964607b4f8002f36299844a11f2ae0faeac2eae70f8f4f98088acdcd0ac556e9fccc511521908fad26f04c64201450305778758b0538bf8b5bb144a828e629795
+Output = e6ad181f053b58a904f2457510373e57
+
+Decrypt = RSA-OAEP-10
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 9886c3e6764a8b9a84e84148ebd8c3b1aa8050381a78f668714c16d9cfd2a6edc56979c535d9dee3b44b85c18be8928992371711472216d95dda98d2ee8347c9b14dffdff84aa48d25ac06f7d7e65398ac967b1ce90925f67dce049b7f812db0742997a74d44fe81dbe0e7a3feaf2e5c40af888d550ddbbe3bc20657a29543f8fc2913b9bd1a61b2ab2256ec409bbd7dc0d17717ea25c43f42ed27df8738bf4afc6766ff7aff0859555ee283920f4c8a63c4a7340cbafddc339ecdb4b0515002f96c932b5b79167af699c0ad3fccfdf0f44e85a70262bf2e18fe34b850589975e867ff969d48eabf212271546cdc05a69ecb526e52870c836f307bd798780ede
+Output = 510a2cf60e866fa2340553c94ea39fbc256311e83e94454b4124
+
+Decrypt = RSA-OAEP-10
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 6318e9fb5c0d05e5307e1683436e903293ac4642358aaa223d7163013aba87e2dfda8e60c6860e29a1e92686163ea0b9175f329ca3b131a1edd3a77759a8b97bad6a4f8f4396f28cf6f39ca58112e48160d6e203daa5856f3aca5ffed577af499408e3dfd233e3e604dbe34a9c4c9082de65527cac6331d29dc80e0508a0fa7122e7f329f6cca5cfa34d4d1da417805457e008bec549e478ff9e12a763c477d15bbb78f5b69bd57830fc2c4ed686d79bc72a95d85f88134c6b0afe56a8ccfbc855828bb339bd17909cf1d70de3335ae07039093e606d655365de6550b872cd6de1d440ee031b61945f629ad8a353b0d40939e96a3c450d2a8d5eee9f678093c8
+Output = bcdd190da3b7d300df9a06e22caae2a75f10c91ff667b7c16bde8b53064a2649a94045c9
+
+Decrypt = RSA-OAEP-10
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 75290872ccfd4a4505660d651f56da6daa09ca1301d890632f6a992f3d565cee464afded40ed3b5be9356714ea5aa7655f4a1366c2f17c728f6f2c5a5d1f8e28429bc4e6f8f2cff8da8dc0e0a9808e45fd09ea2fa40cb2b6ce6ffff5c0e159d11b68d90a85f7b84e103b09e682666480c657505c0929259468a314786d74eab131573cf234bf57db7d9e66cc6748192e002dc0deea930585f0831fdcd9bc33d51f79ed2ffc16bcf4d59812fcebcaa3f9069b0e445686d644c25ccf63b456ee5fa6ffe96f19cdf751fed9eaf35957754dbf4bfea5216aa1844dc507cb2d080e722eba150308c2b5ff1193620f1766ecf4481bafb943bd292877f2136ca494aba0
+Output = a7dd6c7dc24b46f9dd5f1e91ada4c3b3df947e877232a9
+
+Decrypt = RSA-OAEP-10
+RSAPadding = OAEP
+MGF1Digest = SHA1
+Input = 2d207a73432a8fb4c03051b3f73b28a61764098dfa34c47a20995f8115aa6816679b557e82dbee584908c6e69782d7deb34dbd65af063d57fca76a5fd069492fd6068d9984d209350565a62e5c77f23038c12cb10c6634709b547c46f6b4a709bd85ca122d74465ef97762c29763e06dbc7a9e738c78bfca0102dc5e79d65b973f28240caab2e161a78b57d262457ed8195d53e3c7ae9da021883c6db7c24afdd2322eac972ad3c354c5fcef1e146c3a0290fb67adf007066e00428d2cec18ce58f9328698defef4b2eb5ec76918fde1c198cbb38b7afc67626a9aefec4322bfd90d2563481c9a221f78c8272c82d1b62ab914e1c69f6af6ef30ca5260db4a46
+Output = eaf1a73a1b0c4609537de69cd9228bbcfb9a8ca8c6c3efaf056fe4a7f4634ed00b7c39ec6922d7b8ea2c04ebac
diff --git a/src/crypto/evp/internal.h b/src/crypto/evp/internal.h
index aa52d53..0783143 100644
--- a/src/crypto/evp/internal.h
+++ b/src/crypto/evp/internal.h
@@ -59,47 +59,42 @@
 
 #include <openssl/base.h>
 
+#include <openssl/rsa.h>
+
 #if defined(__cplusplus)
 extern "C" {
 #endif
 
 
-/* These values are flags for EVP_PKEY_ASN1_METHOD.flags. */
-
-/* ASN1_PKEY_SIGPARAM_NULL controls whether the default behavior of
- * EVP_DigestSignAlgorithm writes an explicit NULL parameter in the
- * AlgorithmIdentifier. */
-#define ASN1_PKEY_SIGPARAM_NULL 0x1
-
-/* evp_digest_sign_algorithm_result_t is the return value of the
- * digest_sign_algorithm function in EVP_PKEY_ASN1_METHOD. */
-typedef enum {
-  /* EVP_DIGEST_SIGN_ALGORITHM_ERROR signals an error. */
-  EVP_DIGEST_SIGN_ALGORITHM_ERROR = 0,
-  /* EVP_DIGEST_SIGN_ALGORITHM_SUCCESS signals that the parameters were
-   * serialized in the AlgorithmIdentifier. */
-  EVP_DIGEST_SIGN_ALGORITHM_SUCCESS = 1,
-  /* EVP_DIGEST_SIGN_ALGORITHM_DEFAULT signals that the parameters are
-   * serialized using the default behavior. */
-  EVP_DIGEST_SIGN_ALGORITHM_DEFAULT = 2,
-} evp_digest_sign_algorithm_result_t;
-
 struct evp_pkey_asn1_method_st {
   int pkey_id;
-  int pkey_base_id;
-  unsigned long pkey_flags;
+  uint8_t oid[9];
+  uint8_t oid_len;
 
-  const char *pem_str;
+  /* pub_decode decodes |params| and |key| as a SubjectPublicKeyInfo
+   * and writes the result into |out|. It returns one on success and zero on
+   * error. |params| is the AlgorithmIdentifier after the OBJECT IDENTIFIER
+   * type field, and |key| is the contents of the subjectPublicKey with the
+   * leading padding byte checked and removed. Although X.509 uses BIT STRINGs
+   * to represent SubjectPublicKeyInfo, every key type defined encodes the key
+   * as a byte string with the same conversion to BIT STRING. */
+  int (*pub_decode)(EVP_PKEY *out, CBS *params, CBS *key);
 
-  int (*pub_decode)(EVP_PKEY *pk, X509_PUBKEY *pub);
-  int (*pub_encode)(X509_PUBKEY *pub, const EVP_PKEY *pk);
+  /* pub_encode encodes |key| as a SubjectPublicKeyInfo and appends the result
+   * to |out|. It returns one on success and zero on error. */
+  int (*pub_encode)(CBB *out, const EVP_PKEY *key);
+
   int (*pub_cmp)(const EVP_PKEY *a, const EVP_PKEY *b);
-  int (*pub_print)(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx);
 
-  int (*priv_decode)(EVP_PKEY *pk, PKCS8_PRIV_KEY_INFO *p8inf);
-  int (*priv_encode)(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk);
-  int (*priv_print)(BIO *out, const EVP_PKEY *pkey, int indent,
-                    ASN1_PCTX *pctx);
+  /* priv_decode decodes |params| and |key| as a PrivateKeyInfo and writes the
+   * result into |out|. It returns one on success and zero on error. |params| is
+   * the AlgorithmIdentifier after the OBJECT IDENTIFIER type field, and |key|
+   * is the contents of the OCTET STRING privateKey field. */
+  int (*priv_decode)(EVP_PKEY *out, CBS *params, CBS *key);
+
+  /* priv_encode encodes |key| as a PrivateKeyInfo and appends the result to
+   * |out|. It returns one on success and zero on error. */
+  int (*priv_encode)(CBB *out, const EVP_PKEY *key);
 
   /* pkey_opaque returns 1 if the |pk| is opaque. Opaque keys are backed by
    * custom implementations which do not expose key material and parameters.*/
@@ -114,40 +109,15 @@
   int (*pkey_size)(const EVP_PKEY *pk);
   int (*pkey_bits)(const EVP_PKEY *pk);
 
-  int (*param_decode)(EVP_PKEY *pkey, const uint8_t **pder, int derlen);
-  int (*param_encode)(const EVP_PKEY *pkey, uint8_t **pder);
   int (*param_missing)(const EVP_PKEY *pk);
   int (*param_copy)(EVP_PKEY *to, const EVP_PKEY *from);
   int (*param_cmp)(const EVP_PKEY *a, const EVP_PKEY *b);
-  int (*param_print)(BIO *out, const EVP_PKEY *pkey, int indent,
-                     ASN1_PCTX *pctx);
-  int (*sig_print)(BIO *out, const X509_ALGOR *sigalg, const ASN1_STRING *sig,
-                   int indent, ASN1_PCTX *pctx);
-
 
   void (*pkey_free)(EVP_PKEY *pkey);
-
-  /* Legacy functions for old PEM */
-
-  int (*old_priv_decode)(EVP_PKEY *pkey, const uint8_t **pder,
-                         int derlen);
-  int (*old_priv_encode)(const EVP_PKEY *pkey, uint8_t **pder);
-
-  /* Converting parameters to/from AlgorithmIdentifier (X509_ALGOR). */
-  int (*digest_verify_init_from_algorithm)(EVP_MD_CTX *ctx,
-                                           X509_ALGOR *algor,
-                                           EVP_PKEY *pkey);
-  evp_digest_sign_algorithm_result_t (*digest_sign_algorithm)(
-      EVP_MD_CTX *ctx,
-      X509_ALGOR *algor);
-
 } /* EVP_PKEY_ASN1_METHOD */;
 
 
-typedef int EVP_PKEY_gen_cb(EVP_PKEY_CTX *ctx);
-
 #define EVP_PKEY_OP_UNDEFINED 0
-#define EVP_PKEY_OP_PARAMGEN (1 << 1)
 #define EVP_PKEY_OP_KEYGEN (1 << 2)
 #define EVP_PKEY_OP_SIGN (1 << 3)
 #define EVP_PKEY_OP_VERIFY (1 << 4)
@@ -156,7 +126,7 @@
 #define EVP_PKEY_OP_DECRYPT (1 << 7)
 #define EVP_PKEY_OP_DERIVE (1 << 8)
 
-#define EVP_PKEY_OP_TYPE_SIG                                           \
+#define EVP_PKEY_OP_TYPE_SIG \
   (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY | EVP_PKEY_OP_VERIFYRECOVER)
 
 #define EVP_PKEY_OP_TYPE_CRYPT (EVP_PKEY_OP_ENCRYPT | EVP_PKEY_OP_DECRYPT)
@@ -164,7 +134,7 @@
 #define EVP_PKEY_OP_TYPE_NOGEN \
   (EVP_PKEY_OP_SIG | EVP_PKEY_OP_CRYPT | EVP_PKEY_OP_DERIVE)
 
-#define EVP_PKEY_OP_TYPE_GEN (EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN)
+#define EVP_PKEY_OP_TYPE_GEN EVP_PKEY_OP_KEYGEN
 
 /* EVP_PKEY_CTX_ctrl performs |cmd| on |ctx|. The |keytype| and |optype|
  * arguments can be -1 to specify that any type and operation are acceptable,
@@ -208,8 +178,6 @@
 #define EVP_PKEY_CTRL_RSA_OAEP_LABEL (EVP_PKEY_ALG_CTRL + 11)
 #define EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL (EVP_PKEY_ALG_CTRL + 12)
 
-#define EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID (EVP_PKEY_ALG_CTRL + 1)
-
 struct evp_pkey_ctx_st {
   /* Method associated with this operation */
   const EVP_PKEY_METHOD *pmeth;
@@ -223,41 +191,32 @@
   int operation;
   /* Algorithm specific data */
   void *data;
-  /* Application specific data */
-  void *app_data;
 } /* EVP_PKEY_CTX */;
 
 struct evp_pkey_method_st {
   int pkey_id;
-  int flags;
 
   int (*init)(EVP_PKEY_CTX *ctx);
   int (*copy)(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src);
   void (*cleanup)(EVP_PKEY_CTX *ctx);
 
-  int (*paramgen_init)(EVP_PKEY_CTX *ctx);
-  int (*paramgen)(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey);
-
-  int (*keygen_init)(EVP_PKEY_CTX *ctx);
   int (*keygen)(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey);
 
-  int (*sign_init)(EVP_PKEY_CTX *ctx);
   int (*sign)(EVP_PKEY_CTX *ctx, uint8_t *sig, size_t *siglen,
               const uint8_t *tbs, size_t tbslen);
 
-  int (*verify_init)(EVP_PKEY_CTX *ctx);
   int (*verify)(EVP_PKEY_CTX *ctx, const uint8_t *sig, size_t siglen,
                 const uint8_t *tbs, size_t tbslen);
 
-  int (*encrypt_init)(EVP_PKEY_CTX *ctx);
+  int (*verify_recover)(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *out_len,
+                        const uint8_t *sig, size_t sig_len);
+
   int (*encrypt)(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *outlen,
                  const uint8_t *in, size_t inlen);
 
-  int (*decrypt_init)(EVP_PKEY_CTX *ctx);
   int (*decrypt)(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *outlen,
                  const uint8_t *in, size_t inlen);
 
-  int (*derive_init)(EVP_PKEY_CTX *ctx);
   int (*derive)(EVP_PKEY_CTX *ctx, uint8_t *key, size_t *keylen);
 
   int (*ctrl)(EVP_PKEY_CTX *ctx, int type, int p1, void *p2);
diff --git a/src/crypto/evp/p_dsa_asn1.c b/src/crypto/evp/p_dsa_asn1.c
index 3c89e5e..d4f4132 100644
--- a/src/crypto/evp/p_dsa_asn1.c
+++ b/src/crypto/evp/p_dsa_asn1.c
@@ -55,244 +55,140 @@
 
 #include <openssl/evp.h>
 
-#include <openssl/asn1.h>
-#include <openssl/asn1t.h>
 #include <openssl/digest.h>
+#include <openssl/bn.h>
+#include <openssl/bytestring.h>
 #include <openssl/dsa.h>
 #include <openssl/err.h>
-#include <openssl/mem.h>
-#include <openssl/obj.h>
-#include <openssl/x509.h>
 
-#include "../dsa/internal.h"
 #include "internal.h"
 
 
-static int dsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) {
-  const uint8_t *p, *pm;
-  int pklen, pmlen;
-  int ptype;
-  void *pval;
-  ASN1_STRING *pstr;
-  X509_ALGOR *palg;
-  ASN1_INTEGER *public_key = NULL;
+static int dsa_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) {
+  /* See RFC 3279, section 2.3.2. */
 
-  DSA *dsa = NULL;
-
-  if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey)) {
-    return 0;
-  }
-  X509_ALGOR_get0(NULL, &ptype, &pval, palg);
-
-  if (ptype == V_ASN1_SEQUENCE) {
-    pstr = pval;
-    pm = pstr->data;
-    pmlen = pstr->length;
-
-    dsa = d2i_DSAparams(NULL, &pm, pmlen);
+  /* Parameters may or may not be present. */
+  DSA *dsa;
+  if (CBS_len(params) == 0) {
+    dsa = DSA_new();
     if (dsa == NULL) {
+      return 0;
+    }
+  } else {
+    dsa = DSA_parse_parameters(params);
+    if (dsa == NULL || CBS_len(params) != 0) {
       OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
       goto err;
     }
-  } else if (ptype == V_ASN1_NULL || ptype == V_ASN1_UNDEF) {
-    dsa = DSA_new();
-    if (dsa == NULL) {
-      OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
-      goto err;
-    }
-  } else {
-    OPENSSL_PUT_ERROR(EVP, EVP_R_PARAMETER_ENCODING_ERROR);
+  }
+
+  dsa->pub_key = BN_new();
+  if (dsa->pub_key == NULL) {
     goto err;
   }
 
-  public_key = d2i_ASN1_INTEGER(NULL, &p, pklen);
-  if (public_key == NULL) {
+  if (!BN_parse_asn1_unsigned(key, dsa->pub_key) ||
+      CBS_len(key) != 0) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
     goto err;
   }
 
-  dsa->pub_key = ASN1_INTEGER_to_BN(public_key, NULL);
-  if (dsa->pub_key == NULL) {
-    OPENSSL_PUT_ERROR(EVP, EVP_R_BN_DECODE_ERROR);
-    goto err;
-  }
-
-  ASN1_INTEGER_free(public_key);
-  EVP_PKEY_assign_DSA(pkey, dsa);
+  EVP_PKEY_assign_DSA(out, dsa);
   return 1;
 
 err:
-  ASN1_INTEGER_free(public_key);
   DSA_free(dsa);
   return 0;
 }
 
-static int dsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) {
-  DSA *dsa;
-  ASN1_STRING *pval = NULL;
-  uint8_t *penc = NULL;
-  int penclen;
+static int dsa_pub_encode(CBB *out, const EVP_PKEY *key) {
+  const DSA *dsa = key->pkey.dsa;
+  const int has_params = dsa->p != NULL && dsa->q != NULL && dsa->g != NULL;
 
-  dsa = pkey->pkey.dsa;
-  dsa->write_params = 0;
-
-  int ptype;
-  if (dsa->p && dsa->q && dsa->g) {
-    pval = ASN1_STRING_new();
-    if (!pval) {
-      OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
-      goto err;
-    }
-    pval->length = i2d_DSAparams(dsa, &pval->data);
-    if (pval->length <= 0) {
-      OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
-      goto err;
-    }
-    ptype = V_ASN1_SEQUENCE;
-  } else {
-    ptype = V_ASN1_UNDEF;
-  }
-
-  penclen = i2d_DSAPublicKey(dsa, &penc);
-  if (penclen <= 0) {
-    OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
-    goto err;
-  }
-
-  if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_DSA), ptype, pval,
-                             penc, penclen)) {
-    return 1;
-  }
-
-err:
-  OPENSSL_free(penc);
-  ASN1_STRING_free(pval);
-
-  return 0;
-}
-
-static int dsa_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8) {
-  const uint8_t *p, *pm;
-  int pklen, pmlen;
-  int ptype;
-  void *pval;
-  ASN1_STRING *pstr;
-  X509_ALGOR *palg;
-  ASN1_INTEGER *privkey = NULL;
-  BN_CTX *ctx = NULL;
-
-  /* In PKCS#8 DSA: you just get a private key integer and parameters in the
-   * AlgorithmIdentifier the pubkey must be recalculated. */
-
-  DSA *dsa = NULL;
-
-  if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8)) {
+  /* See RFC 5480, section 2. */
+  CBB spki, algorithm, oid, key_bitstring;
+  if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) ||
+      !CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) ||
+      !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
+      !CBB_add_bytes(&oid, dsa_asn1_meth.oid, dsa_asn1_meth.oid_len) ||
+      (has_params &&
+       !DSA_marshal_parameters(&algorithm, dsa)) ||
+      !CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) ||
+      !CBB_add_u8(&key_bitstring, 0 /* padding */) ||
+      !BN_marshal_asn1(&key_bitstring, dsa->pub_key) ||
+      !CBB_flush(out)) {
+    OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
     return 0;
   }
-  privkey = d2i_ASN1_INTEGER(NULL, &p, pklen);
-  if (privkey == NULL || privkey->type == V_ASN1_NEG_INTEGER) {
-    goto decerr;
-  }
-
-  X509_ALGOR_get0(NULL, &ptype, &pval, palg);
-  if (ptype != V_ASN1_SEQUENCE) {
-    goto decerr;
-  }
-  pstr = pval;
-  pm = pstr->data;
-  pmlen = pstr->length;
-  dsa = d2i_DSAparams(NULL, &pm, pmlen);
-  if (dsa == NULL) {
-    goto decerr;
-  }
-  /* We have parameters. Now set private key */
-  dsa->priv_key = ASN1_INTEGER_to_BN(privkey, NULL);
-  if (dsa->priv_key == NULL) {
-    OPENSSL_PUT_ERROR(EVP, ERR_LIB_BN);
-    goto dsaerr;
-  }
-  /* Calculate public key. */
-  dsa->pub_key = BN_new();
-  if (dsa->pub_key == NULL) {
-    OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
-    goto dsaerr;
-  }
-  ctx = BN_CTX_new();
-  if (ctx == NULL) {
-    OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
-    goto dsaerr;
-  }
-
-  if (!BN_mod_exp(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx)) {
-    OPENSSL_PUT_ERROR(EVP, ERR_LIB_BN);
-    goto dsaerr;
-  }
-
-  EVP_PKEY_assign_DSA(pkey, dsa);
-  BN_CTX_free(ctx);
-  ASN1_INTEGER_free(privkey);
 
   return 1;
+}
 
-decerr:
-  OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
+static int dsa_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) {
+  /* See PKCS#11, v2.40, section 2.5. */
 
-dsaerr:
+  /* Decode parameters. */
+  BN_CTX *ctx = NULL;
+  DSA *dsa = DSA_parse_parameters(params);
+  if (dsa == NULL || CBS_len(params) != 0) {
+    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
+    goto err;
+  }
+
+  dsa->priv_key = BN_new();
+  dsa->pub_key = BN_new();
+  if (dsa->priv_key == NULL || dsa->pub_key == NULL) {
+    goto err;
+  }
+
+  /* Decode the key. */
+  if (!BN_parse_asn1_unsigned(key, dsa->priv_key) ||
+      CBS_len(key) != 0) {
+    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
+    goto err;
+  }
+
+  /* Calculate the public key. */
+  ctx = BN_CTX_new();
+  if (ctx == NULL ||
+      !BN_mod_exp_mont(dsa->pub_key, dsa->g, dsa->priv_key, dsa->p, ctx,
+                       NULL)) {
+    goto err;
+  }
+
   BN_CTX_free(ctx);
-  ASN1_INTEGER_free(privkey);
+  EVP_PKEY_assign_DSA(out, dsa);
+  return 1;
+
+err:
+  BN_CTX_free(ctx);
   DSA_free(dsa);
   return 0;
 }
 
-static int dsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) {
-  ASN1_STRING *params = NULL;
-  ASN1_INTEGER *prkey = NULL;
-  uint8_t *dp = NULL;
-  int dplen;
-
-  if (!pkey->pkey.dsa || !pkey->pkey.dsa->priv_key) {
+static int dsa_priv_encode(CBB *out, const EVP_PKEY *key) {
+  const DSA *dsa = key->pkey.dsa;
+  if (dsa == NULL || dsa->priv_key == NULL) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_MISSING_PARAMETERS);
-    goto err;
+    return 0;
   }
 
-  params = ASN1_STRING_new();
-  if (!params) {
-    OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
-    goto err;
-  }
-
-  params->length = i2d_DSAparams(pkey->pkey.dsa, &params->data);
-  if (params->length <= 0) {
-    OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
-    goto err;
-  }
-  params->type = V_ASN1_SEQUENCE;
-
-  /* Get private key into integer. */
-  prkey = BN_to_ASN1_INTEGER(pkey->pkey.dsa->priv_key, NULL);
-
-  if (!prkey) {
-    OPENSSL_PUT_ERROR(EVP, ERR_LIB_BN);
-    goto err;
-  }
-
-  dplen = i2d_ASN1_INTEGER(prkey, &dp);
-
-  ASN1_INTEGER_free(prkey);
-  prkey = NULL;
-
-  if (!PKCS8_pkey_set0(p8, (ASN1_OBJECT *)OBJ_nid2obj(NID_dsa), 0,
-                       V_ASN1_SEQUENCE, params, dp, dplen)) {
-    goto err;
+  /* See PKCS#11, v2.40, section 2.5. */
+  CBB pkcs8, algorithm, oid, private_key;
+  if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) ||
+      !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) ||
+      !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
+      !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
+      !CBB_add_bytes(&oid, dsa_asn1_meth.oid, dsa_asn1_meth.oid_len) ||
+      !DSA_marshal_parameters(&algorithm, dsa) ||
+      !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) ||
+      !BN_marshal_asn1(&private_key, dsa->priv_key) ||
+      !CBB_flush(out)) {
+    OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
+    return 0;
   }
 
   return 1;
-
-err:
-  OPENSSL_free(dp);
-  ASN1_STRING_free(params);
-  ASN1_INTEGER_free(prkey);
-  return 0;
 }
 
 static int int_dsa_size(const EVP_PKEY *pkey) {
@@ -347,177 +243,17 @@
 
 static void int_dsa_free(EVP_PKEY *pkey) { DSA_free(pkey->pkey.dsa); }
 
-static void update_buflen(const BIGNUM *b, size_t *pbuflen) {
-  size_t i;
-
-  if (!b) {
-    return;
-  }
-  i = BN_num_bytes(b);
-  if (*pbuflen < i) {
-    *pbuflen = i;
-  }
-}
-
-static int do_dsa_print(BIO *bp, const DSA *x, int off, int ptype) {
-  uint8_t *m = NULL;
-  int ret = 0;
-  size_t buf_len = 0;
-  const char *ktype = NULL;
-
-  const BIGNUM *priv_key, *pub_key;
-
-  priv_key = NULL;
-  if (ptype == 2) {
-    priv_key = x->priv_key;
-  }
-
-  pub_key = NULL;
-  if (ptype > 0) {
-    pub_key = x->pub_key;
-  }
-
-  ktype = "DSA-Parameters";
-  if (ptype == 2) {
-    ktype = "Private-Key";
-  } else if (ptype == 1) {
-    ktype = "Public-Key";
-  }
-
-  update_buflen(x->p, &buf_len);
-  update_buflen(x->q, &buf_len);
-  update_buflen(x->g, &buf_len);
-  update_buflen(priv_key, &buf_len);
-  update_buflen(pub_key, &buf_len);
-
-  m = (uint8_t *)OPENSSL_malloc(buf_len + 10);
-  if (m == NULL) {
-    OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
-    goto err;
-  }
-
-  if (priv_key) {
-    if (!BIO_indent(bp, off, 128) ||
-        BIO_printf(bp, "%s: (%d bit)\n", ktype, BN_num_bits(x->p)) <= 0) {
-      goto err;
-    }
-  }
-
-  if (!ASN1_bn_print(bp, "priv:", priv_key, m, off) ||
-      !ASN1_bn_print(bp, "pub: ", pub_key, m, off) ||
-      !ASN1_bn_print(bp, "P:   ", x->p, m, off) ||
-      !ASN1_bn_print(bp, "Q:   ", x->q, m, off) ||
-      !ASN1_bn_print(bp, "G:   ", x->g, m, off)) {
-    goto err;
-  }
-  ret = 1;
-
-err:
-  OPENSSL_free(m);
-  return ret;
-}
-
-static int dsa_param_decode(EVP_PKEY *pkey, const uint8_t **pder, int derlen) {
-  DSA *dsa;
-  dsa = d2i_DSAparams(NULL, pder, derlen);
-  if (dsa == NULL) {
-    OPENSSL_PUT_ERROR(EVP, ERR_R_DSA_LIB);
-    return 0;
-  }
-  EVP_PKEY_assign_DSA(pkey, dsa);
-  return 1;
-}
-
-static int dsa_param_encode(const EVP_PKEY *pkey, uint8_t **pder) {
-  return i2d_DSAparams(pkey->pkey.dsa, pder);
-}
-
-static int dsa_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
-                           ASN1_PCTX *ctx) {
-  return do_dsa_print(bp, pkey->pkey.dsa, indent, 0);
-}
-
-static int dsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
-                         ASN1_PCTX *ctx) {
-  return do_dsa_print(bp, pkey->pkey.dsa, indent, 1);
-}
-
-static int dsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
-                          ASN1_PCTX *ctx) {
-  return do_dsa_print(bp, pkey->pkey.dsa, indent, 2);
-}
-
-static int old_dsa_priv_decode(EVP_PKEY *pkey, const uint8_t **pder,
-                               int derlen) {
-  DSA *dsa;
-  dsa = d2i_DSAPrivateKey(NULL, pder, derlen);
-  if (dsa == NULL) {
-    OPENSSL_PUT_ERROR(EVP, ERR_R_DSA_LIB);
-    return 0;
-  }
-  EVP_PKEY_assign_DSA(pkey, dsa);
-  return 1;
-}
-
-static int old_dsa_priv_encode(const EVP_PKEY *pkey, uint8_t **pder) {
-  return i2d_DSAPrivateKey(pkey->pkey.dsa, pder);
-}
-
-static int dsa_sig_print(BIO *bp, const X509_ALGOR *sigalg,
-                         const ASN1_STRING *sig, int indent, ASN1_PCTX *pctx) {
-  DSA_SIG *dsa_sig;
-  const uint8_t *p;
-
-  if (!sig) {
-    return BIO_puts(bp, "\n") > 0;
-  }
-
-  p = sig->data;
-  dsa_sig = d2i_DSA_SIG(NULL, &p, sig->length);
-  if (dsa_sig == NULL) {
-    return X509_signature_dump(bp, sig, indent);
-  }
-
-  int rv = 0;
-  size_t buf_len = 0;
-  uint8_t *m = NULL;
-
-  update_buflen(dsa_sig->r, &buf_len);
-  update_buflen(dsa_sig->s, &buf_len);
-  m = OPENSSL_malloc(buf_len + 10);
-  if (m == NULL) {
-    OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
-    goto err;
-  }
-
-  if (BIO_write(bp, "\n", 1) != 1 ||
-      !ASN1_bn_print(bp, "r:   ", dsa_sig->r, m, indent) ||
-      !ASN1_bn_print(bp, "s:   ", dsa_sig->s, m, indent)) {
-    goto err;
-  }
-  rv = 1;
-
-err:
-  OPENSSL_free(m);
-  DSA_SIG_free(dsa_sig);
-  return rv;
-}
-
 const EVP_PKEY_ASN1_METHOD dsa_asn1_meth = {
   EVP_PKEY_DSA,
-  EVP_PKEY_DSA,
-  0,
-
-  "DSA",
+  /* 1.2.840.10040.4.1 */
+  {0x2a, 0x86, 0x48, 0xce, 0x38, 0x04, 0x01}, 7,
 
   dsa_pub_decode,
   dsa_pub_encode,
   dsa_pub_cmp,
-  dsa_pub_print,
 
   dsa_priv_decode,
   dsa_priv_encode,
-  dsa_priv_print,
 
   NULL /* pkey_opaque */,
   NULL /* pkey_supports_digest */,
@@ -525,18 +261,9 @@
   int_dsa_size,
   dsa_bits,
 
-  dsa_param_decode,
-  dsa_param_encode,
   dsa_missing_parameters,
   dsa_copy_parameters,
   dsa_cmp_parameters,
-  dsa_param_print,
-  dsa_sig_print,
 
   int_dsa_free,
-  old_dsa_priv_decode,
-  old_dsa_priv_encode,
-
-  NULL  /* digest_verify_init_from_algorithm */,
-  NULL  /* digest_sign_algorithm */,
 };
diff --git a/src/crypto/evp/p_ec.c b/src/crypto/evp/p_ec.c
index 77f213d..dc1ea6f 100644
--- a/src/crypto/evp/p_ec.c
+++ b/src/crypto/evp/p_ec.c
@@ -57,7 +57,6 @@
 
 #include <string.h>
 
-#include <openssl/asn1.h>
 #include <openssl/bn.h>
 #include <openssl/buf.h>
 #include <openssl/digest.h>
@@ -67,15 +66,14 @@
 #include <openssl/ecdsa.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
 
 #include "internal.h"
 #include "../ec/internal.h"
+#include "../internal.h"
 
 
 typedef struct {
-  /* Key and paramgen group */
-  EC_GROUP *gen_group;
   /* message digest */
   const EVP_MD *md;
 } EC_PKEY_CTX;
@@ -87,7 +85,7 @@
   if (!dctx) {
     return 0;
   }
-  memset(dctx, 0, sizeof(EC_PKEY_CTX));
+  OPENSSL_memset(dctx, 0, sizeof(EC_PKEY_CTX));
 
   ctx->data = dctx;
 
@@ -102,12 +100,6 @@
   sctx = src->data;
   dctx = dst->data;
 
-  if (sctx->gen_group) {
-    dctx->gen_group = EC_GROUP_dup(sctx->gen_group);
-    if (!dctx->gen_group) {
-      return 0;
-    }
-  }
   dctx->md = sctx->md;
 
   return 1;
@@ -119,7 +111,6 @@
     return;
   }
 
-  EC_GROUP_free(dctx->gen_group);
   OPENSSL_free(dctx);
 }
 
@@ -185,19 +176,8 @@
 
 static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) {
   EC_PKEY_CTX *dctx = ctx->data;
-  EC_GROUP *group;
 
   switch (type) {
-    case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID:
-      group = EC_GROUP_new_by_curve_name(p1);
-      if (group == NULL) {
-        OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_CURVE);
-        return 0;
-      }
-      EC_GROUP_free(dctx->gen_group);
-      dctx->gen_group = group;
-      return 1;
-
     case EVP_PKEY_CTRL_MD:
       if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 &&
           EVP_MD_type((const EVP_MD *)p2) != NID_ecdsa_with_SHA1 &&
@@ -225,59 +205,33 @@
   }
 }
 
-static int pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) {
-  EC_KEY *ec = NULL;
-  EC_PKEY_CTX *dctx = ctx->data;
-  int ret = 0;
-
-  if (dctx->gen_group == NULL) {
-    OPENSSL_PUT_ERROR(EVP, EVP_R_NO_PARAMETERS_SET);
-    return 0;
-  }
-  ec = EC_KEY_new();
-  if (!ec) {
-    return 0;
-  }
-  ret = EC_KEY_set_group(ec, dctx->gen_group);
-  if (ret) {
-    EVP_PKEY_assign_EC_KEY(pkey, ec);
-  } else {
-    EC_KEY_free(ec);
-  }
-  return ret;
-}
-
 static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) {
-  EC_KEY *ec = NULL;
-  EC_PKEY_CTX *dctx = ctx->data;
-  if (ctx->pkey == NULL && dctx->gen_group == NULL) {
+  if (ctx->pkey == NULL) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_NO_PARAMETERS_SET);
     return 0;
   }
-  ec = EC_KEY_new();
-  if (!ec) {
+  EC_KEY *ec = EC_KEY_new();
+  if (ec == NULL ||
+      !EC_KEY_set_group(ec, EC_KEY_get0_group(ctx->pkey->pkey.ec)) ||
+      !EC_KEY_generate_key(ec)) {
+    EC_KEY_free(ec);
     return 0;
   }
   EVP_PKEY_assign_EC_KEY(pkey, ec);
-  if (ctx->pkey) {
-    /* Note: if error return, pkey is freed by parent routine */
-    if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey)) {
-      return 0;
-    }
-  } else {
-    if (!EC_KEY_set_group(ec, dctx->gen_group)) {
-      return 0;
-    }
-  }
-  return EC_KEY_generate_key(pkey->pkey.ec);
+  return 1;
 }
 
 const EVP_PKEY_METHOD ec_pkey_meth = {
-    EVP_PKEY_EC,          0 /* flags */,        pkey_ec_init,
-    pkey_ec_copy,         pkey_ec_cleanup,      0 /* paramgen_init */,
-    pkey_ec_paramgen,     0 /* keygen_init */,  pkey_ec_keygen,
-    0 /* sign_init */,    pkey_ec_sign,         0 /* verify_init */,
-    pkey_ec_verify,       0 /* encrypt_init */, 0 /* encrypt */,
-    0 /* decrypt_init */, 0 /* decrypt */,      0 /* derive_init */,
-    pkey_ec_derive,       pkey_ec_ctrl,
+    EVP_PKEY_EC,
+    pkey_ec_init,
+    pkey_ec_copy,
+    pkey_ec_cleanup,
+    pkey_ec_keygen,
+    pkey_ec_sign,
+    pkey_ec_verify,
+    0 /* verify_recover */,
+    0 /* encrypt */,
+    0 /* decrypt */,
+    pkey_ec_derive,
+    pkey_ec_ctrl,
 };
diff --git a/src/crypto/evp/p_ec_asn1.c b/src/crypto/evp/p_ec_asn1.c
index f40b976..8d44dcd 100644
--- a/src/crypto/evp/p_ec_asn1.c
+++ b/src/crypto/evp/p_ec_asn1.c
@@ -55,145 +55,73 @@
 
 #include <openssl/evp.h>
 
-#include <openssl/asn1t.h>
 #include <openssl/bn.h>
+#include <openssl/bytestring.h>
 #include <openssl/ec.h>
+#include <openssl/ec_key.h>
+#include <openssl/ecdsa.h>
 #include <openssl/err.h>
-#include <openssl/mem.h>
-#include <openssl/obj.h>
-#include <openssl/x509.h>
 
 #include "internal.h"
 
 
-static int eckey_param2type(int *pptype, void **ppval, EC_KEY *ec_key) {
-  const EC_GROUP *group;
-  int nid;
+static int eckey_pub_encode(CBB *out, const EVP_PKEY *key) {
+  const EC_KEY *ec_key = key->pkey.ec;
+  const EC_GROUP *group = EC_KEY_get0_group(ec_key);
+  const EC_POINT *public_key = EC_KEY_get0_public_key(ec_key);
 
-  if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL) {
-    OPENSSL_PUT_ERROR(EVP, EVP_R_MISSING_PARAMETERS);
+  /* See RFC 5480, section 2. */
+  CBB spki, algorithm, oid, key_bitstring;
+  if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) ||
+      !CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) ||
+      !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
+      !CBB_add_bytes(&oid, ec_asn1_meth.oid, ec_asn1_meth.oid_len) ||
+      !EC_KEY_marshal_curve_name(&algorithm, group) ||
+      !CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) ||
+      !CBB_add_u8(&key_bitstring, 0 /* padding */) ||
+      !EC_POINT_point2cbb(&key_bitstring, group, public_key,
+                          POINT_CONVERSION_UNCOMPRESSED, NULL) ||
+      !CBB_flush(out)) {
+    OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
     return 0;
   }
 
-  nid = EC_GROUP_get_curve_name(group);
-  if (nid == NID_undef) {
-    OPENSSL_PUT_ERROR(EVP, EVP_R_NO_NID_FOR_CURVE);
-    return 0;
-  }
-
-  *ppval = (void*) OBJ_nid2obj(nid);
-  *pptype = V_ASN1_OBJECT;
   return 1;
 }
 
-static int eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) {
-  EC_KEY *ec_key = pkey->pkey.ec;
-  void *pval = NULL;
-  int ptype;
-  uint8_t *penc = NULL, *p;
-  int penclen;
+static int eckey_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) {
+  /* See RFC 5480, section 2. */
 
-  if (!eckey_param2type(&ptype, &pval, ec_key)) {
-    OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB);
-    return 0;
-  }
-  penclen = i2o_ECPublicKey(ec_key, NULL);
-  if (penclen <= 0) {
-    goto err;
-  }
-  penc = OPENSSL_malloc(penclen);
-  if (!penc) {
-    goto err;
-  }
-  p = penc;
-  penclen = i2o_ECPublicKey(ec_key, &p);
-  if (penclen <= 0) {
-    goto err;
-  }
-  if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_EC), ptype, pval, penc,
-                             penclen)) {
-    return 1;
-  }
-
-err:
-  if (ptype == V_ASN1_OBJECT) {
-    ASN1_OBJECT_free(pval);
-  } else {
-    ASN1_STRING_free(pval);
-  }
-  if (penc) {
-    OPENSSL_free(penc);
-  }
-  return 0;
-}
-
-static EC_KEY *eckey_type2param(int ptype, void *pval) {
+  /* The parameters are a named curve. */
+  EC_POINT *point = NULL;
   EC_KEY *eckey = NULL;
-
-  if (ptype == V_ASN1_SEQUENCE) {
-    ASN1_STRING *pstr = pval;
-    const uint8_t *pm = pstr->data;
-    int pmlen = pstr->length;
-
-    eckey = d2i_ECParameters(NULL, &pm, pmlen);
-    if (eckey == NULL) {
-      OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
-      goto err;
-    }
-  } else if (ptype == V_ASN1_OBJECT) {
-    ASN1_OBJECT *poid = pval;
-
-    /* type == V_ASN1_OBJECT => the parameters are given
-     * by an asn1 OID */
-    eckey = EC_KEY_new_by_curve_name(OBJ_obj2nid(poid));
-    if (eckey == NULL) {
-      goto err;
-    }
-  } else {
+  EC_GROUP *group = EC_KEY_parse_curve_name(params);
+  if (group == NULL || CBS_len(params) != 0) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
     goto err;
   }
 
-  return eckey;
-
-err:
-  if (eckey) {
-    EC_KEY_free(eckey);
-  }
-  return NULL;
-}
-
-static int eckey_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) {
-  const uint8_t *p = NULL;
-  void *pval;
-  int ptype, pklen;
-  EC_KEY *eckey = NULL;
-  X509_ALGOR *palg;
-
-  if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey)) {
-    return 0;
-  }
-  X509_ALGOR_get0(NULL, &ptype, &pval, palg);
-
-  eckey = eckey_type2param(ptype, pval);
-  if (!eckey) {
-    OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB);
-    return 0;
-  }
-
-  /* We have parameters now set public key */
-  if (!o2i_ECPublicKey(&eckey, &p, pklen)) {
-    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
+  eckey = EC_KEY_new();
+  if (eckey == NULL || !EC_KEY_set_group(eckey, group)) {
     goto err;
   }
 
-  EVP_PKEY_assign_EC_KEY(pkey, eckey);
+  point = EC_POINT_new(group);
+  if (point == NULL ||
+      !EC_POINT_oct2point(group, point, CBS_data(key), CBS_len(key), NULL) ||
+      !EC_KEY_set_public_key(eckey, point)) {
+    goto err;
+  }
+
+  EC_GROUP_free(group);
+  EC_POINT_free(point);
+  EVP_PKEY_assign_EC_KEY(out, eckey);
   return 1;
 
 err:
-  if (eckey) {
-    EC_KEY_free(eckey);
-  }
+  EC_GROUP_free(group);
+  EC_POINT_free(point);
+  EC_KEY_free(eckey);
   return 0;
 }
 
@@ -212,120 +140,48 @@
   }
 }
 
-static int eckey_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8) {
-  const uint8_t *p = NULL;
-  void *pval;
-  int ptype, pklen;
-  EC_KEY *eckey = NULL;
-  X509_ALGOR *palg;
-
-  if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8)) {
+static int eckey_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) {
+  /* See RFC 5915. */
+  EC_GROUP *group = EC_KEY_parse_parameters(params);
+  if (group == NULL || CBS_len(params) != 0) {
+    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
+    EC_GROUP_free(group);
     return 0;
   }
-  X509_ALGOR_get0(NULL, &ptype, &pval, palg);
 
-  eckey = eckey_type2param(ptype, pval);
-
-  if (!eckey) {
-    goto ecliberr;
-  }
-
-  /* We have parameters now set private key */
-  if (!d2i_ECPrivateKey(&eckey, &p, pklen)) {
+  EC_KEY *ec_key = EC_KEY_parse_private_key(key, group);
+  EC_GROUP_free(group);
+  if (ec_key == NULL || CBS_len(key) != 0) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
-    goto ecerr;
+    EC_KEY_free(ec_key);
+    return 0;
   }
 
-  /* calculate public key (if necessary) */
-  if (EC_KEY_get0_public_key(eckey) == NULL) {
-    const BIGNUM *priv_key;
-    const EC_GROUP *group;
-    EC_POINT *pub_key;
-    /* the public key was not included in the SEC1 private
-     * key => calculate the public key */
-    group = EC_KEY_get0_group(eckey);
-    pub_key = EC_POINT_new(group);
-    if (pub_key == NULL) {
-      OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB);
-      goto ecliberr;
-    }
-    if (!EC_POINT_copy(pub_key, EC_GROUP_get0_generator(group))) {
-      EC_POINT_free(pub_key);
-      OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB);
-      goto ecliberr;
-    }
-    priv_key = EC_KEY_get0_private_key(eckey);
-    if (!EC_POINT_mul(group, pub_key, priv_key, NULL, NULL, NULL)) {
-      EC_POINT_free(pub_key);
-      OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB);
-      goto ecliberr;
-    }
-    if (EC_KEY_set_public_key(eckey, pub_key) == 0) {
-      EC_POINT_free(pub_key);
-      OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB);
-      goto ecliberr;
-    }
-    EC_POINT_free(pub_key);
-  }
-
-  EVP_PKEY_assign_EC_KEY(pkey, eckey);
+  EVP_PKEY_assign_EC_KEY(out, ec_key);
   return 1;
-
-ecliberr:
-  OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB);
-ecerr:
-  if (eckey) {
-    EC_KEY_free(eckey);
-  }
-  return 0;
 }
 
-static int eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) {
-  EC_KEY *ec_key;
-  uint8_t *ep, *p;
-  int eplen, ptype;
-  void *pval;
-  unsigned int tmp_flags, old_flags;
+static int eckey_priv_encode(CBB *out, const EVP_PKEY *key) {
+  const EC_KEY *ec_key = key->pkey.ec;
 
-  ec_key = pkey->pkey.ec;
+  /* Omit the redundant copy of the curve name. This contradicts RFC 5915 but
+   * aligns with PKCS #11. SEC 1 only says they may be omitted if known by other
+   * means. Both OpenSSL and NSS omit the redundant parameters, so we omit them
+   * as well. */
+  unsigned enc_flags = EC_KEY_get_enc_flags(ec_key) | EC_PKEY_NO_PARAMETERS;
 
-  if (!eckey_param2type(&ptype, &pval, ec_key)) {
-    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
-    return 0;
-  }
-
-  /* set the private key */
-
-  /* do not include the parameters in the SEC1 private key
-   * see PKCS#11 12.11 */
-  old_flags = EC_KEY_get_enc_flags(ec_key);
-  tmp_flags = old_flags | EC_PKEY_NO_PARAMETERS;
-  EC_KEY_set_enc_flags(ec_key, tmp_flags);
-  eplen = i2d_ECPrivateKey(ec_key, NULL);
-  if (!eplen) {
-    EC_KEY_set_enc_flags(ec_key, old_flags);
-    OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB);
-    return 0;
-  }
-  ep = (uint8_t *)OPENSSL_malloc(eplen);
-  if (!ep) {
-    EC_KEY_set_enc_flags(ec_key, old_flags);
-    OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
-    return 0;
-  }
-  p = ep;
-  if (!i2d_ECPrivateKey(ec_key, &p)) {
-    EC_KEY_set_enc_flags(ec_key, old_flags);
-    OPENSSL_free(ep);
-    OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB);
-    return 0;
-  }
-  /* restore old encoding flags */
-  EC_KEY_set_enc_flags(ec_key, old_flags);
-
-  if (!PKCS8_pkey_set0(p8, (ASN1_OBJECT *)OBJ_nid2obj(NID_X9_62_id_ecPublicKey),
-                       0, ptype, pval, ep, eplen)) {
-    OPENSSL_free(ep);
+  /* See RFC 5915. */
+  CBB pkcs8, algorithm, oid, private_key;
+  if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) ||
+      !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) ||
+      !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
+      !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
+      !CBB_add_bytes(&oid, ec_asn1_meth.oid, ec_asn1_meth.oid_len) ||
+      !EC_KEY_marshal_curve_name(&algorithm, EC_KEY_get0_group(ec_key)) ||
+      !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) ||
+      !EC_KEY_marshal_private_key(&private_key, ec_key, enc_flags) ||
+      !CBB_flush(out)) {
+    OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
     return 0;
   }
 
@@ -371,173 +227,21 @@
 
 static void int_ec_free(EVP_PKEY *pkey) { EC_KEY_free(pkey->pkey.ec); }
 
-static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype) {
-  uint8_t *buffer = NULL;
-  const char *ecstr;
-  size_t buf_len = 0, i;
-  int ret = 0, reason = ERR_R_BIO_LIB;
-  BN_CTX *ctx = NULL;
-  const EC_GROUP *group;
-  const EC_POINT *public_key;
-  const BIGNUM *priv_key;
-  uint8_t *pub_key_bytes = NULL;
-  size_t pub_key_bytes_len = 0;
-
-  if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) {
-    reason = ERR_R_PASSED_NULL_PARAMETER;
-    goto err;
-  }
-
-  ctx = BN_CTX_new();
-  if (ctx == NULL) {
-    reason = ERR_R_MALLOC_FAILURE;
-    goto err;
-  }
-
-  if (ktype > 0) {
-    public_key = EC_KEY_get0_public_key(x);
-    if (public_key != NULL) {
-      pub_key_bytes_len = EC_POINT_point2oct(
-          group, public_key, EC_KEY_get_conv_form(x), NULL, 0, ctx);
-      if (pub_key_bytes_len == 0) {
-        reason = ERR_R_MALLOC_FAILURE;
-        goto err;
-      }
-      pub_key_bytes = OPENSSL_malloc(pub_key_bytes_len);
-      if (pub_key_bytes == NULL) {
-        reason = ERR_R_MALLOC_FAILURE;
-        goto err;
-      }
-      pub_key_bytes_len =
-          EC_POINT_point2oct(group, public_key, EC_KEY_get_conv_form(x),
-                             pub_key_bytes, pub_key_bytes_len, ctx);
-      if (pub_key_bytes_len == 0) {
-        reason = ERR_R_MALLOC_FAILURE;
-        goto err;
-      }
-      buf_len = pub_key_bytes_len;
-    }
-  }
-
-  if (ktype == 2) {
-    priv_key = EC_KEY_get0_private_key(x);
-    if (priv_key && (i = (size_t)BN_num_bytes(priv_key)) > buf_len) {
-      buf_len = i;
-    }
-  } else {
-    priv_key = NULL;
-  }
-
-  if (ktype > 0) {
-    buf_len += 10;
-    if ((buffer = OPENSSL_malloc(buf_len)) == NULL) {
-      reason = ERR_R_MALLOC_FAILURE;
-      goto err;
-    }
-  }
-  if (ktype == 2) {
-    ecstr = "Private-Key";
-  } else if (ktype == 1) {
-    ecstr = "Public-Key";
-  } else {
-    ecstr = "ECDSA-Parameters";
-  }
-
-  if (!BIO_indent(bp, off, 128)) {
-    goto err;
-  }
-  const BIGNUM *order = EC_GROUP_get0_order(group);
-  if (BIO_printf(bp, "%s: (%d bit)\n", ecstr, BN_num_bits(order)) <= 0) {
-    goto err;
-  }
-
-  if ((priv_key != NULL) &&
-      !ASN1_bn_print(bp, "priv:", priv_key, buffer, off)) {
-    goto err;
-  }
-  if (pub_key_bytes != NULL) {
-    BIO_hexdump(bp, pub_key_bytes, pub_key_bytes_len, off);
-  }
-  /* TODO(fork): implement */
-  /*
-  if (!ECPKParameters_print(bp, group, off))
-    goto err; */
-  ret = 1;
-
-err:
-  if (!ret) {
-    OPENSSL_PUT_ERROR(EVP, reason);
-  }
-  OPENSSL_free(pub_key_bytes);
-  BN_CTX_free(ctx);
-  OPENSSL_free(buffer);
-  return ret;
-}
-
-static int eckey_param_decode(EVP_PKEY *pkey, const uint8_t **pder,
-                              int derlen) {
-  EC_KEY *eckey;
-  if (!(eckey = d2i_ECParameters(NULL, pder, derlen))) {
-    OPENSSL_PUT_ERROR(EVP, ERR_R_EC_LIB);
-    return 0;
-  }
-  EVP_PKEY_assign_EC_KEY(pkey, eckey);
-  return 1;
-}
-
-static int eckey_param_encode(const EVP_PKEY *pkey, uint8_t **pder) {
-  return i2d_ECParameters(pkey->pkey.ec, pder);
-}
-
-static int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
-                             ASN1_PCTX *ctx) {
-  return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 0);
-}
-
-static int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
-                           ASN1_PCTX *ctx) {
-  return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 1);
-}
-
-
-static int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
-                            ASN1_PCTX *ctx) {
-  return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 2);
-}
-
 static int eckey_opaque(const EVP_PKEY *pkey) {
   return EC_KEY_is_opaque(pkey->pkey.ec);
 }
 
-static int old_ec_priv_decode(EVP_PKEY *pkey, const uint8_t **pder,
-                              int derlen) {
-  EC_KEY *ec;
-  if (!(ec = d2i_ECPrivateKey(NULL, pder, derlen))) {
-    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
-    return 0;
-  }
-  EVP_PKEY_assign_EC_KEY(pkey, ec);
-  return 1;
-}
-
-static int old_ec_priv_encode(const EVP_PKEY *pkey, uint8_t **pder) {
-  return i2d_ECPrivateKey(pkey->pkey.ec, pder);
-}
-
 const EVP_PKEY_ASN1_METHOD ec_asn1_meth = {
   EVP_PKEY_EC,
-  EVP_PKEY_EC,
-  0,
-  "EC",
+  /* 1.2.840.10045.2.1 */
+  {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01}, 7,
 
   eckey_pub_decode,
   eckey_pub_encode,
   eckey_pub_cmp,
-  eckey_pub_print,
 
   eckey_priv_decode,
   eckey_priv_encode,
-  eckey_priv_print,
 
   eckey_opaque,
   0 /* pkey_supports_digest */,
@@ -545,18 +249,9 @@
   int_ec_size,
   ec_bits,
 
-  eckey_param_decode,
-  eckey_param_encode,
   ec_missing_parameters,
   ec_copy_parameters,
   ec_cmp_parameters,
-  eckey_param_print,
-  0,
 
   int_ec_free,
-  old_ec_priv_decode,
-  old_ec_priv_encode,
-
-  NULL /* digest_verify_init_from_algorithm */,
-  NULL /* digest_sign_algorithm */,
 };
diff --git a/src/crypto/evp/p_rsa.c b/src/crypto/evp/p_rsa.c
index 895d351..ea2ba99 100644
--- a/src/crypto/evp/p_rsa.c
+++ b/src/crypto/evp/p_rsa.c
@@ -64,9 +64,10 @@
 #include <openssl/digest.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
 #include <openssl/rsa.h>
 
+#include "../internal.h"
 #include "../rsa/internal.h"
 #include "internal.h"
 
@@ -97,7 +98,7 @@
   if (!rctx) {
     return 0;
   }
-  memset(rctx, 0, sizeof(RSA_PKEY_CTX));
+  OPENSSL_memset(rctx, 0, sizeof(RSA_PKEY_CTX));
 
   rctx->nbits = 2048;
   rctx->pad_mode = RSA_PKCS1_PADDING;
@@ -231,6 +232,11 @@
         return RSA_verify(EVP_MD_type(rctx->md), tbs, tbslen, sig, siglen, rsa);
 
       case RSA_PKCS1_PSS_PADDING:
+        if (tbslen != EVP_MD_size(rctx->md)) {
+          OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_DIGEST_LENGTH);
+          return 0;
+        }
+
         if (!setup_tbuf(rctx, ctx) ||
             !RSA_verify_raw(rsa, &rslen, rctx->tbuf, key_len, sig, siglen,
                             RSA_NO_PADDING) ||
@@ -256,6 +262,81 @@
   return 1;
 }
 
+static int pkey_rsa_verify_recover(EVP_PKEY_CTX *ctx, uint8_t *out,
+                                   size_t *out_len, const uint8_t *sig,
+                                   size_t sig_len) {
+  RSA_PKEY_CTX *rctx = ctx->data;
+  RSA *rsa = ctx->pkey->pkey.rsa;
+  const size_t key_len = EVP_PKEY_size(ctx->pkey);
+
+  if (out == NULL) {
+    *out_len = key_len;
+    return 1;
+  }
+
+  if (*out_len < key_len) {
+    OPENSSL_PUT_ERROR(EVP, EVP_R_BUFFER_TOO_SMALL);
+    return 0;
+  }
+
+  if (!setup_tbuf(rctx, ctx)) {
+    return 0;
+  }
+
+  if (rctx->md == NULL) {
+    const int ret = RSA_public_decrypt(sig_len, sig, rctx->tbuf,
+                                       ctx->pkey->pkey.rsa, rctx->pad_mode);
+    if (ret < 0) {
+      return 0;
+    }
+    *out_len = ret;
+    OPENSSL_memcpy(out, rctx->tbuf, *out_len);
+    return 1;
+  }
+
+  if (rctx->pad_mode != RSA_PKCS1_PADDING) {
+    return 0;
+  }
+
+  uint8_t *asn1_prefix;
+  size_t asn1_prefix_len;
+  int asn1_prefix_allocated;
+  if (!RSA_add_pkcs1_prefix(&asn1_prefix, &asn1_prefix_len,
+                            &asn1_prefix_allocated, EVP_MD_type(rctx->md), NULL,
+                            0)) {
+    return 0;
+  }
+
+  size_t rslen;
+  int ok = 1;
+  if (!RSA_verify_raw(rsa, &rslen, rctx->tbuf, key_len, sig, sig_len,
+                      RSA_PKCS1_PADDING) ||
+      rslen < asn1_prefix_len ||
+      CRYPTO_memcmp(rctx->tbuf, asn1_prefix, asn1_prefix_len) != 0) {
+    ok = 0;
+  }
+
+  if (asn1_prefix_allocated) {
+    OPENSSL_free(asn1_prefix);
+  }
+
+  if (!ok) {
+    return 0;
+  }
+
+  const size_t result_len = rslen - asn1_prefix_len;
+  if (result_len != EVP_MD_size(rctx->md)) {
+    return 0;
+  }
+
+  if (out != NULL) {
+    OPENSSL_memcpy(out, rctx->tbuf + asn1_prefix_len, result_len);
+  }
+  *out_len = result_len;
+
+  return 1;
+}
+
 static int pkey_rsa_encrypt(EVP_PKEY_CTX *ctx, uint8_t *out, size_t *outlen,
                             const uint8_t *in, size_t inlen) {
   RSA_PKEY_CTX *rctx = ctx->data;
@@ -503,13 +584,18 @@
 }
 
 const EVP_PKEY_METHOD rsa_pkey_meth = {
-    EVP_PKEY_RSA,         0 /* flags */,        pkey_rsa_init,
-    pkey_rsa_copy,        pkey_rsa_cleanup,     0 /* paramgen_init */,
-    0 /* paramgen */,     0 /* keygen_init */,  pkey_rsa_keygen,
-    0 /* sign_init */,    pkey_rsa_sign,        0 /* verify_init */,
-    pkey_rsa_verify,      0 /* encrypt_init */, pkey_rsa_encrypt,
-    0 /* decrypt_init */, pkey_rsa_decrypt,     0 /* derive_init */,
-    0 /* derive */,       pkey_rsa_ctrl,
+    EVP_PKEY_RSA,
+    pkey_rsa_init,
+    pkey_rsa_copy,
+    pkey_rsa_cleanup,
+    pkey_rsa_keygen,
+    pkey_rsa_sign,
+    pkey_rsa_verify,
+    pkey_rsa_verify_recover,
+    pkey_rsa_encrypt,
+    pkey_rsa_decrypt,
+    0 /* derive */,
+    pkey_rsa_ctrl,
 };
 
 int EVP_PKEY_CTX_set_rsa_padding(EVP_PKEY_CTX *ctx, int padding) {
@@ -566,15 +652,14 @@
                            EVP_PKEY_CTRL_GET_RSA_MGF1_MD, 0, (void*) out_md);
 }
 
-int EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx, const uint8_t *label,
+int EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx, uint8_t *label,
                                      size_t label_len) {
-  int label_len_int = label_len;
-  if (((size_t) label_len_int) != label_len) {
+  if (label_len > INT_MAX) {
     return 0;
   }
 
   return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, EVP_PKEY_OP_TYPE_CRYPT,
-                           EVP_PKEY_CTRL_RSA_OAEP_LABEL, label_len,
+                           EVP_PKEY_CTRL_RSA_OAEP_LABEL, (int)label_len,
                            (void *)label);
 }
 
diff --git a/src/crypto/evp/p_rsa_asn1.c b/src/crypto/evp/p_rsa_asn1.c
index db38d5c..2c4b266 100644
--- a/src/crypto/evp/p_rsa_asn1.c
+++ b/src/crypto/evp/p_rsa_asn1.c
@@ -55,40 +55,45 @@
 
 #include <openssl/evp.h>
 
-#include <openssl/asn1.h>
-#include <openssl/asn1t.h>
+#include <openssl/bn.h>
 #include <openssl/bytestring.h>
 #include <openssl/digest.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
-#include <openssl/obj.h>
 #include <openssl/rsa.h>
-#include <openssl/x509.h>
 
 #include "../rsa/internal.h"
 #include "internal.h"
 
 
-static int rsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) {
-  uint8_t *encoded;
-  size_t encoded_len;
-  if (!RSA_public_key_to_bytes(&encoded, &encoded_len, pkey->pkey.rsa)) {
-    return 0;
-  }
-
-  if (!X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_RSA), V_ASN1_NULL, NULL,
-                              encoded, encoded_len)) {
-    OPENSSL_free(encoded);
+static int rsa_pub_encode(CBB *out, const EVP_PKEY *key) {
+  /* See RFC 3279, section 2.3.1. */
+  CBB spki, algorithm, oid, null, key_bitstring;
+  if (!CBB_add_asn1(out, &spki, CBS_ASN1_SEQUENCE) ||
+      !CBB_add_asn1(&spki, &algorithm, CBS_ASN1_SEQUENCE) ||
+      !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
+      !CBB_add_bytes(&oid, rsa_asn1_meth.oid, rsa_asn1_meth.oid_len) ||
+      !CBB_add_asn1(&algorithm, &null, CBS_ASN1_NULL) ||
+      !CBB_add_asn1(&spki, &key_bitstring, CBS_ASN1_BITSTRING) ||
+      !CBB_add_u8(&key_bitstring, 0 /* padding */) ||
+      !RSA_marshal_public_key(&key_bitstring, key->pkey.rsa) ||
+      !CBB_flush(out)) {
+    OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
     return 0;
   }
 
   return 1;
 }
 
-static int rsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey) {
-  const uint8_t *p;
-  int pklen;
-  if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, NULL, pubkey)) {
+static int rsa_pub_decode(EVP_PKEY *out, CBS *params, CBS *key) {
+  /* See RFC 3279, section 2.3.1. */
+
+  /* The parameters must be NULL. */
+  CBS null;
+  if (!CBS_get_asn1(params, &null, CBS_ASN1_NULL) ||
+      CBS_len(&null) != 0 ||
+      CBS_len(params) != 0) {
+    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
     return 0;
   }
 
@@ -98,16 +103,14 @@
    * TODO(davidben): Switch this to the strict version in March 2016 or when
    * Chromium can force client certificates down a different codepath, whichever
    * comes first. */
-  CBS cbs;
-  CBS_init(&cbs, p, pklen);
-  RSA *rsa = RSA_parse_public_key_buggy(&cbs);
-  if (rsa == NULL || CBS_len(&cbs) != 0) {
+  RSA *rsa = RSA_parse_public_key_buggy(key);
+  if (rsa == NULL || CBS_len(key) != 0) {
     OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
     RSA_free(rsa);
     return 0;
   }
 
-  EVP_PKEY_assign_RSA(pkey, rsa);
+  EVP_PKEY_assign_RSA(out, rsa);
   return 1;
 }
 
@@ -116,39 +119,42 @@
          BN_cmp(b->pkey.rsa->e, a->pkey.rsa->e) == 0;
 }
 
-static int rsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) {
-  uint8_t *encoded;
-  size_t encoded_len;
-  if (!RSA_private_key_to_bytes(&encoded, &encoded_len, pkey->pkey.rsa)) {
-    return 0;
-  }
-
-  /* TODO(fork): const correctness in next line. */
-  if (!PKCS8_pkey_set0(p8, (ASN1_OBJECT *)OBJ_nid2obj(NID_rsaEncryption), 0,
-                       V_ASN1_NULL, NULL, encoded, encoded_len)) {
-    OPENSSL_free(encoded);
-    OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
+static int rsa_priv_encode(CBB *out, const EVP_PKEY *key) {
+  CBB pkcs8, algorithm, oid, null, private_key;
+  if (!CBB_add_asn1(out, &pkcs8, CBS_ASN1_SEQUENCE) ||
+      !CBB_add_asn1_uint64(&pkcs8, 0 /* version */) ||
+      !CBB_add_asn1(&pkcs8, &algorithm, CBS_ASN1_SEQUENCE) ||
+      !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
+      !CBB_add_bytes(&oid, rsa_asn1_meth.oid, rsa_asn1_meth.oid_len) ||
+      !CBB_add_asn1(&algorithm, &null, CBS_ASN1_NULL) ||
+      !CBB_add_asn1(&pkcs8, &private_key, CBS_ASN1_OCTETSTRING) ||
+      !RSA_marshal_private_key(&private_key, key->pkey.rsa) ||
+      !CBB_flush(out)) {
+    OPENSSL_PUT_ERROR(EVP, EVP_R_ENCODE_ERROR);
     return 0;
   }
 
   return 1;
 }
 
-static int rsa_priv_decode(EVP_PKEY *pkey, PKCS8_PRIV_KEY_INFO *p8) {
-  const uint8_t *p;
-  int pklen;
-  if (!PKCS8_pkey_get0(NULL, &p, &pklen, NULL, p8)) {
-    OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
+static int rsa_priv_decode(EVP_PKEY *out, CBS *params, CBS *key) {
+  /* Per RFC 3447, A.1, the parameters have type NULL. */
+  CBS null;
+  if (!CBS_get_asn1(params, &null, CBS_ASN1_NULL) ||
+      CBS_len(&null) != 0 ||
+      CBS_len(params) != 0) {
+    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
     return 0;
   }
 
-  RSA *rsa = RSA_private_key_from_bytes(p, pklen);
-  if (rsa == NULL) {
-    OPENSSL_PUT_ERROR(EVP, ERR_R_RSA_LIB);
+  RSA *rsa = RSA_parse_private_key(key);
+  if (rsa == NULL || CBS_len(key) != 0) {
+    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
+    RSA_free(rsa);
     return 0;
   }
 
-  EVP_PKEY_assign_RSA(pkey, rsa);
+  EVP_PKEY_assign_RSA(out, rsa);
   return 1;
 }
 
@@ -170,553 +176,17 @@
 
 static void int_rsa_free(EVP_PKEY *pkey) { RSA_free(pkey->pkey.rsa); }
 
-static void update_buflen(const BIGNUM *b, size_t *pbuflen) {
-  size_t i;
-
-  if (!b) {
-    return;
-  }
-
-  i = BN_num_bytes(b);
-  if (*pbuflen < i) {
-    *pbuflen = i;
-  }
-}
-
-static int do_rsa_print(BIO *out, const RSA *rsa, int off,
-                        int include_private) {
-  char *str;
-  const char *s;
-  uint8_t *m = NULL;
-  int ret = 0, mod_len = 0;
-  size_t buf_len = 0;
-
-  update_buflen(rsa->n, &buf_len);
-  update_buflen(rsa->e, &buf_len);
-
-  if (include_private) {
-    update_buflen(rsa->d, &buf_len);
-    update_buflen(rsa->p, &buf_len);
-    update_buflen(rsa->q, &buf_len);
-    update_buflen(rsa->dmp1, &buf_len);
-    update_buflen(rsa->dmq1, &buf_len);
-    update_buflen(rsa->iqmp, &buf_len);
-
-    if (rsa->additional_primes != NULL) {
-      size_t i;
-
-      for (i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes);
-           i++) {
-        const RSA_additional_prime *ap =
-            sk_RSA_additional_prime_value(rsa->additional_primes, i);
-        update_buflen(ap->prime, &buf_len);
-        update_buflen(ap->exp, &buf_len);
-        update_buflen(ap->coeff, &buf_len);
-      }
-    }
-  }
-
-  m = (uint8_t *)OPENSSL_malloc(buf_len + 10);
-  if (m == NULL) {
-    OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
-    goto err;
-  }
-
-  if (rsa->n != NULL) {
-    mod_len = BN_num_bits(rsa->n);
-  }
-
-  if (!BIO_indent(out, off, 128)) {
-    goto err;
-  }
-
-  if (include_private && rsa->d) {
-    if (BIO_printf(out, "Private-Key: (%d bit)\n", mod_len) <= 0) {
-      goto err;
-    }
-    str = "modulus:";
-    s = "publicExponent:";
-  } else {
-    if (BIO_printf(out, "Public-Key: (%d bit)\n", mod_len) <= 0) {
-      goto err;
-    }
-    str = "Modulus:";
-    s = "Exponent:";
-  }
-  if (!ASN1_bn_print(out, str, rsa->n, m, off) ||
-      !ASN1_bn_print(out, s, rsa->e, m, off)) {
-    goto err;
-  }
-
-  if (include_private) {
-    if (!ASN1_bn_print(out, "privateExponent:", rsa->d, m, off) ||
-        !ASN1_bn_print(out, "prime1:", rsa->p, m, off) ||
-        !ASN1_bn_print(out, "prime2:", rsa->q, m, off) ||
-        !ASN1_bn_print(out, "exponent1:", rsa->dmp1, m, off) ||
-        !ASN1_bn_print(out, "exponent2:", rsa->dmq1, m, off) ||
-        !ASN1_bn_print(out, "coefficient:", rsa->iqmp, m, off)) {
-      goto err;
-    }
-
-    if (rsa->additional_primes != NULL &&
-        sk_RSA_additional_prime_num(rsa->additional_primes) > 0) {
-      size_t i;
-
-      if (BIO_printf(out, "otherPrimeInfos:\n") <= 0) {
-        goto err;
-      }
-      for (i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes);
-           i++) {
-        const RSA_additional_prime *ap =
-            sk_RSA_additional_prime_value(rsa->additional_primes, i);
-
-        if (BIO_printf(out, "otherPrimeInfo (prime %u):\n",
-                       (unsigned)(i + 3)) <= 0 ||
-            !ASN1_bn_print(out, "prime:", ap->prime, m, off) ||
-            !ASN1_bn_print(out, "exponent:", ap->exp, m, off) ||
-            !ASN1_bn_print(out, "coeff:", ap->coeff, m, off)) {
-          goto err;
-        }
-      }
-    }
-  }
-  ret = 1;
-
-err:
-  OPENSSL_free(m);
-  return ret;
-}
-
-static int rsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
-                         ASN1_PCTX *ctx) {
-  return do_rsa_print(bp, pkey->pkey.rsa, indent, 0);
-}
-
-
-static int rsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
-                          ASN1_PCTX *ctx) {
-  return do_rsa_print(bp, pkey->pkey.rsa, indent, 1);
-}
-
-/* Given an MGF1 Algorithm ID decode to an Algorithm Identifier */
-static X509_ALGOR *rsa_mgf1_decode(X509_ALGOR *alg) {
-  const uint8_t *p;
-  int plen;
-
-  if (alg == NULL || alg->parameter == NULL ||
-      OBJ_obj2nid(alg->algorithm) != NID_mgf1 ||
-      alg->parameter->type != V_ASN1_SEQUENCE) {
-    return NULL;
-  }
-
-  p = alg->parameter->value.sequence->data;
-  plen = alg->parameter->value.sequence->length;
-  return d2i_X509_ALGOR(NULL, &p, plen);
-}
-
-static RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg,
-                                      X509_ALGOR **pmaskHash) {
-  const uint8_t *p;
-  int plen;
-  RSA_PSS_PARAMS *pss;
-
-  *pmaskHash = NULL;
-
-  if (!alg->parameter || alg->parameter->type != V_ASN1_SEQUENCE) {
-    return NULL;
-  }
-  p = alg->parameter->value.sequence->data;
-  plen = alg->parameter->value.sequence->length;
-  pss = d2i_RSA_PSS_PARAMS(NULL, &p, plen);
-
-  if (!pss) {
-    return NULL;
-  }
-
-  *pmaskHash = rsa_mgf1_decode(pss->maskGenAlgorithm);
-
-  return pss;
-}
-
-static int rsa_pss_param_print(BIO *bp, RSA_PSS_PARAMS *pss,
-                               X509_ALGOR *maskHash, int indent) {
-  int rv = 0;
-
-  if (!pss) {
-    if (BIO_puts(bp, " (INVALID PSS PARAMETERS)\n") <= 0) {
-      return 0;
-    }
-    return 1;
-  }
-
-  if (BIO_puts(bp, "\n") <= 0 ||
-      !BIO_indent(bp, indent, 128) ||
-      BIO_puts(bp, "Hash Algorithm: ") <= 0) {
-    goto err;
-  }
-
-  if (pss->hashAlgorithm) {
-    if (i2a_ASN1_OBJECT(bp, pss->hashAlgorithm->algorithm) <= 0) {
-      goto err;
-    }
-  } else if (BIO_puts(bp, "sha1 (default)") <= 0) {
-    goto err;
-  }
-
-  if (BIO_puts(bp, "\n") <= 0 ||
-      !BIO_indent(bp, indent, 128) ||
-      BIO_puts(bp, "Mask Algorithm: ") <= 0) {
-    goto err;
-  }
-
-  if (pss->maskGenAlgorithm) {
-    if (i2a_ASN1_OBJECT(bp, pss->maskGenAlgorithm->algorithm) <= 0 ||
-        BIO_puts(bp, " with ") <= 0) {
-      goto err;
-    }
-
-    if (maskHash) {
-      if (i2a_ASN1_OBJECT(bp, maskHash->algorithm) <= 0) {
-        goto err;
-      }
-    } else if (BIO_puts(bp, "INVALID") <= 0) {
-      goto err;
-    }
-  } else if (BIO_puts(bp, "mgf1 with sha1 (default)") <= 0) {
-    goto err;
-  }
-  BIO_puts(bp, "\n");
-
-  if (!BIO_indent(bp, indent, 128) ||
-      BIO_puts(bp, "Salt Length: 0x") <= 0) {
-    goto err;
-  }
-
-  if (pss->saltLength) {
-    if (i2a_ASN1_INTEGER(bp, pss->saltLength) <= 0) {
-      goto err;
-    }
-  } else if (BIO_puts(bp, "14 (default)") <= 0) {
-    goto err;
-  }
-  BIO_puts(bp, "\n");
-
-  if (!BIO_indent(bp, indent, 128) ||
-      BIO_puts(bp, "Trailer Field: 0x") <= 0) {
-    goto err;
-  }
-
-  if (pss->trailerField) {
-    if (i2a_ASN1_INTEGER(bp, pss->trailerField) <= 0) {
-      goto err;
-    }
-  } else if (BIO_puts(bp, "BC (default)") <= 0) {
-    goto err;
-  }
-  BIO_puts(bp, "\n");
-
-  rv = 1;
-
-err:
-  return rv;
-}
-
-static int rsa_sig_print(BIO *bp, const X509_ALGOR *sigalg,
-                         const ASN1_STRING *sig, int indent, ASN1_PCTX *pctx) {
-  if (OBJ_obj2nid(sigalg->algorithm) == NID_rsassaPss) {
-    int rv;
-    RSA_PSS_PARAMS *pss;
-    X509_ALGOR *maskHash;
-
-    pss = rsa_pss_decode(sigalg, &maskHash);
-    rv = rsa_pss_param_print(bp, pss, maskHash, indent);
-    RSA_PSS_PARAMS_free(pss);
-    X509_ALGOR_free(maskHash);
-    if (!rv) {
-      return 0;
-    }
-  } else if (!sig && BIO_puts(bp, "\n") <= 0) {
-    return 0;
-  }
-
-  if (sig) {
-    return X509_signature_dump(bp, sig, indent);
-  }
-  return 1;
-}
-
-static int old_rsa_priv_decode(EVP_PKEY *pkey, const uint8_t **pder,
-                               int derlen) {
-  RSA *rsa = d2i_RSAPrivateKey(NULL, pder, derlen);
-  if (rsa == NULL) {
-    OPENSSL_PUT_ERROR(EVP, ERR_R_RSA_LIB);
-    return 0;
-  }
-  EVP_PKEY_assign_RSA(pkey, rsa);
-  return 1;
-}
-
-static int old_rsa_priv_encode(const EVP_PKEY *pkey, uint8_t **pder) {
-  return i2d_RSAPrivateKey(pkey->pkey.rsa, pder);
-}
-
-/* allocate and set algorithm ID from EVP_MD, default SHA1 */
-static int rsa_md_to_algor(X509_ALGOR **palg, const EVP_MD *md) {
-  if (EVP_MD_type(md) == NID_sha1) {
-    return 1;
-  }
-  *palg = X509_ALGOR_new();
-  if (!*palg) {
-    return 0;
-  }
-  X509_ALGOR_set_md(*palg, md);
-  return 1;
-}
-
-/* Allocate and set MGF1 algorithm ID from EVP_MD */
-static int rsa_md_to_mgf1(X509_ALGOR **palg, const EVP_MD *mgf1md) {
-  X509_ALGOR *algtmp = NULL;
-  ASN1_STRING *stmp = NULL;
-  *palg = NULL;
-
-  if (EVP_MD_type(mgf1md) == NID_sha1) {
-    return 1;
-  }
-  /* need to embed algorithm ID inside another */
-  if (!rsa_md_to_algor(&algtmp, mgf1md) ||
-      !ASN1_item_pack(algtmp, ASN1_ITEM_rptr(X509_ALGOR), &stmp)) {
-    goto err;
-  }
-  *palg = X509_ALGOR_new();
-  if (!*palg) {
-    goto err;
-  }
-  X509_ALGOR_set0(*palg, OBJ_nid2obj(NID_mgf1), V_ASN1_SEQUENCE, stmp);
-  stmp = NULL;
-
-err:
-  ASN1_STRING_free(stmp);
-  X509_ALGOR_free(algtmp);
-  if (*palg) {
-    return 1;
-  }
-
-  return 0;
-}
-
-/* convert algorithm ID to EVP_MD, default SHA1 */
-static const EVP_MD *rsa_algor_to_md(X509_ALGOR *alg) {
-  const EVP_MD *md;
-  if (!alg) {
-    return EVP_sha1();
-  }
-  md = EVP_get_digestbyobj(alg->algorithm);
-  if (md == NULL) {
-    OPENSSL_PUT_ERROR(EVP, EVP_R_UNKNOWN_DIGEST);
-  }
-  return md;
-}
-
-/* convert MGF1 algorithm ID to EVP_MD, default SHA1 */
-static const EVP_MD *rsa_mgf1_to_md(X509_ALGOR *alg, X509_ALGOR *maskHash) {
-  const EVP_MD *md;
-  if (!alg) {
-    return EVP_sha1();
-  }
-  /* Check mask and lookup mask hash algorithm */
-  if (OBJ_obj2nid(alg->algorithm) != NID_mgf1) {
-    OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_MASK_ALGORITHM);
-    return NULL;
-  }
-  if (!maskHash) {
-    OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_MASK_PARAMETER);
-    return NULL;
-  }
-  md = EVP_get_digestbyobj(maskHash->algorithm);
-  if (md == NULL) {
-    OPENSSL_PUT_ERROR(EVP, EVP_R_UNKNOWN_MASK_DIGEST);
-    return NULL;
-  }
-  return md;
-}
-
-/* rsa_ctx_to_pss converts EVP_PKEY_CTX in PSS mode into corresponding
- * algorithm parameter, suitable for setting as an AlgorithmIdentifier. */
-static ASN1_STRING *rsa_ctx_to_pss(EVP_PKEY_CTX *pkctx) {
-  const EVP_MD *sigmd, *mgf1md;
-  RSA_PSS_PARAMS *pss = NULL;
-  ASN1_STRING *os = NULL;
-  EVP_PKEY *pk = EVP_PKEY_CTX_get0_pkey(pkctx);
-  int saltlen, rv = 0;
-
-  if (!EVP_PKEY_CTX_get_signature_md(pkctx, &sigmd) ||
-      !EVP_PKEY_CTX_get_rsa_mgf1_md(pkctx, &mgf1md) ||
-      !EVP_PKEY_CTX_get_rsa_pss_saltlen(pkctx, &saltlen)) {
-    goto err;
-  }
-
-  if (saltlen == -1) {
-    saltlen = EVP_MD_size(sigmd);
-  } else if (saltlen == -2) {
-    saltlen = EVP_PKEY_size(pk) - EVP_MD_size(sigmd) - 2;
-    if (((EVP_PKEY_bits(pk) - 1) & 0x7) == 0) {
-      saltlen--;
-    }
-  } else {
-    goto err;
-  }
-
-  pss = RSA_PSS_PARAMS_new();
-  if (!pss) {
-    goto err;
-  }
-
-  if (saltlen != 20) {
-    pss->saltLength = ASN1_INTEGER_new();
-    if (!pss->saltLength ||
-        !ASN1_INTEGER_set(pss->saltLength, saltlen)) {
-      goto err;
-    }
-  }
-
-  if (!rsa_md_to_algor(&pss->hashAlgorithm, sigmd) ||
-      !rsa_md_to_mgf1(&pss->maskGenAlgorithm, mgf1md)) {
-    goto err;
-  }
-
-  /* Finally create string with pss parameter encoding. */
-  if (!ASN1_item_pack(pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), &os)) {
-    goto err;
-  }
-  rv = 1;
-
-err:
-  if (pss) {
-    RSA_PSS_PARAMS_free(pss);
-  }
-  if (rv) {
-    return os;
-  }
-  if (os) {
-    ASN1_STRING_free(os);
-  }
-  return NULL;
-}
-
-/* From PSS AlgorithmIdentifier set public key parameters. */
-static int rsa_pss_to_ctx(EVP_MD_CTX *ctx, X509_ALGOR *sigalg, EVP_PKEY *pkey) {
-  int ret = 0;
-  int saltlen;
-  const EVP_MD *mgf1md = NULL, *md = NULL;
-  RSA_PSS_PARAMS *pss;
-  X509_ALGOR *maskHash;
-  EVP_PKEY_CTX *pkctx;
-
-  /* Sanity check: make sure it is PSS */
-  if (OBJ_obj2nid(sigalg->algorithm) != NID_rsassaPss) {
-    OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_SIGNATURE_TYPE);
-    return 0;
-  }
-  /* Decode PSS parameters */
-  pss = rsa_pss_decode(sigalg, &maskHash);
-  if (pss == NULL) {
-    OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_PSS_PARAMETERS);
-    goto err;
-  }
-
-  mgf1md = rsa_mgf1_to_md(pss->maskGenAlgorithm, maskHash);
-  if (!mgf1md) {
-    goto err;
-  }
-  md = rsa_algor_to_md(pss->hashAlgorithm);
-  if (!md) {
-    goto err;
-  }
-
-  saltlen = 20;
-  if (pss->saltLength) {
-    saltlen = ASN1_INTEGER_get(pss->saltLength);
-
-    /* Could perform more salt length sanity checks but the main
-     * RSA routines will trap other invalid values anyway. */
-    if (saltlen < 0) {
-      OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_SALT_LENGTH);
-      goto err;
-    }
-  }
-
-  /* low-level routines support only trailer field 0xbc (value 1)
-   * and PKCS#1 says we should reject any other value anyway. */
-  if (pss->trailerField && ASN1_INTEGER_get(pss->trailerField) != 1) {
-    OPENSSL_PUT_ERROR(EVP, EVP_R_INVALID_TRAILER);
-    goto err;
-  }
-
-  if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey) ||
-      !EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) ||
-      !EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) ||
-      !EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md)) {
-    goto err;
-  }
-
-  ret = 1;
-
-err:
-  RSA_PSS_PARAMS_free(pss);
-  if (maskHash) {
-    X509_ALGOR_free(maskHash);
-  }
-  return ret;
-}
-
-/* Customised RSA AlgorithmIdentifier handling. This is called when a signature
- * is encountered requiring special handling. We currently only handle PSS. */
-static int rsa_digest_verify_init_from_algorithm(EVP_MD_CTX *ctx,
-                                                 X509_ALGOR *sigalg,
-                                                 EVP_PKEY *pkey) {
-  /* Sanity check: make sure it is PSS */
-  if (OBJ_obj2nid(sigalg->algorithm) != NID_rsassaPss) {
-    OPENSSL_PUT_ERROR(EVP, EVP_R_UNSUPPORTED_SIGNATURE_TYPE);
-    return 0;
-  }
-  return rsa_pss_to_ctx(ctx, sigalg, pkey);
-}
-
-static evp_digest_sign_algorithm_result_t rsa_digest_sign_algorithm(
-    EVP_MD_CTX *ctx, X509_ALGOR *sigalg) {
-  int pad_mode;
-  EVP_PKEY_CTX *pkctx = ctx->pctx;
-  if (!EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode)) {
-    return EVP_DIGEST_SIGN_ALGORITHM_ERROR;
-  }
-  if (pad_mode == RSA_PKCS1_PSS_PADDING) {
-    ASN1_STRING *os1 = rsa_ctx_to_pss(pkctx);
-    if (!os1) {
-      return EVP_DIGEST_SIGN_ALGORITHM_ERROR;
-    }
-    X509_ALGOR_set0(sigalg, OBJ_nid2obj(NID_rsassaPss), V_ASN1_SEQUENCE, os1);
-    return EVP_DIGEST_SIGN_ALGORITHM_SUCCESS;
-  }
-
-  /* Other padding schemes use the default behavior. */
-  return EVP_DIGEST_SIGN_ALGORITHM_DEFAULT;
-}
-
 const EVP_PKEY_ASN1_METHOD rsa_asn1_meth = {
   EVP_PKEY_RSA,
-  EVP_PKEY_RSA,
-  ASN1_PKEY_SIGPARAM_NULL,
-
-  "RSA",
+  /* 1.2.840.113549.1.1.1 */
+  {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01}, 9,
 
   rsa_pub_decode,
   rsa_pub_encode,
   rsa_pub_cmp,
-  rsa_pub_print,
 
   rsa_priv_decode,
   rsa_priv_encode,
-  rsa_priv_print,
 
   rsa_opaque,
   rsa_supports_digest,
@@ -724,14 +194,7 @@
   int_rsa_size,
   rsa_bits,
 
-  0,0,0,0,0,0,
+  0,0,0,
 
-  rsa_sig_print,
   int_rsa_free,
-
-  old_rsa_priv_decode,
-  old_rsa_priv_encode,
-
-  rsa_digest_verify_init_from_algorithm,
-  rsa_digest_sign_algorithm,
 };
diff --git a/src/crypto/evp/pbkdf.c b/src/crypto/evp/pbkdf.c
index b06b922..1792cdc 100644
--- a/src/crypto/evp/pbkdf.c
+++ b/src/crypto/evp/pbkdf.c
@@ -59,6 +59,8 @@
 
 #include <openssl/hmac.h>
 
+#include "../internal.h"
+
 
 int PKCS5_PBKDF2_HMAC(const char *password, size_t password_len,
                       const uint8_t *salt, size_t salt_len, unsigned iterations,
@@ -101,7 +103,7 @@
       return 0;
     }
     HMAC_CTX_cleanup(&hctx);
-    memcpy(p, digest_tmp, cplen);
+    OPENSSL_memcpy(p, digest_tmp, cplen);
     for (j = 1; j < iterations; j++) {
       if (!HMAC_CTX_copy(&hctx, &hctx_tpl)) {
         HMAC_CTX_cleanup(&hctx_tpl);
diff --git a/src/crypto/evp/pbkdf_test.cc b/src/crypto/evp/pbkdf_test.cc
index a39189f..5284700 100644
--- a/src/crypto/evp/pbkdf_test.cc
+++ b/src/crypto/evp/pbkdf_test.cc
@@ -15,12 +15,13 @@
 #include <stdio.h>
 #include <string.h>
 
-#include <openssl/bio.h>
 #include <openssl/crypto.h>
 #include <openssl/digest.h>
 #include <openssl/err.h>
 #include <openssl/evp.h>
 
+#include "../internal.h"
+
 
 // Prints out the data buffer as a sequence of hex bytes.
 static void PrintDataHex(const void *data, size_t len) {
@@ -50,7 +51,7 @@
     return false;
   }
 
-  if (memcmp(key, expected_key, key_len) != 0) {
+  if (OPENSSL_memcmp(key, expected_key, key_len) != 0) {
     fprintf(stderr, "Resulting key material does not match expectation\n");
     fprintf(stderr, "Expected:\n    ");
     PrintDataHex(expected_key, key_len);
@@ -189,7 +190,6 @@
 
 int main(void) {
   CRYPTO_library_init();
-  ERR_load_crypto_strings();
 
   if (!TestEmptyPassword()) {
     fprintf(stderr, "TestEmptyPassword failed\n");
diff --git a/src/crypto/evp/print.c b/src/crypto/evp/print.c
new file mode 100644
index 0000000..b2e3509
--- /dev/null
+++ b/src/crypto/evp/print.c
@@ -0,0 +1,520 @@
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com). */
+
+#include <openssl/evp.h>
+
+#include <openssl/bio.h>
+#include <openssl/bn.h>
+#include <openssl/dsa.h>
+#include <openssl/ec.h>
+#include <openssl/ec_key.h>
+#include <openssl/mem.h>
+#include <openssl/rsa.h>
+
+#include "../internal.h"
+#include "../rsa/internal.h"
+
+
+static int bn_print(BIO *bp, const char *number, const BIGNUM *num,
+                    uint8_t *buf, int off) {
+  if (num == NULL) {
+    return 1;
+  }
+
+  if (!BIO_indent(bp, off, 128)) {
+    return 0;
+  }
+  if (BN_is_zero(num)) {
+    if (BIO_printf(bp, "%s 0\n", number) <= 0) {
+      return 0;
+    }
+    return 1;
+  }
+
+  if (BN_num_bytes(num) <= sizeof(long)) {
+    const char *neg = BN_is_negative(num) ? "-" : "";
+    if (BIO_printf(bp, "%s %s%lu (%s0x%lx)\n", number, neg,
+                   (unsigned long)num->d[0], neg,
+                   (unsigned long)num->d[0]) <= 0) {
+      return 0;
+    }
+  } else {
+    buf[0] = 0;
+    if (BIO_printf(bp, "%s%s", number,
+                   (BN_is_negative(num)) ? " (Negative)" : "") <= 0) {
+      return 0;
+    }
+    int n = BN_bn2bin(num, &buf[1]);
+
+    if (buf[1] & 0x80) {
+      n++;
+    } else {
+      buf++;
+    }
+
+    int i;
+    for (i = 0; i < n; i++) {
+      if ((i % 15) == 0) {
+        if (BIO_puts(bp, "\n") <= 0 ||
+            !BIO_indent(bp, off + 4, 128)) {
+          return 0;
+        }
+      }
+      if (BIO_printf(bp, "%02x%s", buf[i], ((i + 1) == n) ? "" : ":") <= 0) {
+        return 0;
+      }
+    }
+    if (BIO_write(bp, "\n", 1) <= 0) {
+      return 0;
+    }
+  }
+  return 1;
+}
+
+static void update_buflen(const BIGNUM *b, size_t *pbuflen) {
+  if (!b) {
+    return;
+  }
+
+  size_t len = BN_num_bytes(b);
+  if (*pbuflen < len) {
+    *pbuflen = len;
+  }
+}
+
+/* RSA keys. */
+
+static int do_rsa_print(BIO *out, const RSA *rsa, int off,
+                        int include_private) {
+  const char *s, *str;
+  uint8_t *m = NULL;
+  int ret = 0, mod_len = 0;
+  size_t buf_len = 0;
+
+  update_buflen(rsa->n, &buf_len);
+  update_buflen(rsa->e, &buf_len);
+
+  if (include_private) {
+    update_buflen(rsa->d, &buf_len);
+    update_buflen(rsa->p, &buf_len);
+    update_buflen(rsa->q, &buf_len);
+    update_buflen(rsa->dmp1, &buf_len);
+    update_buflen(rsa->dmq1, &buf_len);
+    update_buflen(rsa->iqmp, &buf_len);
+
+    if (rsa->additional_primes != NULL) {
+      for (size_t i = 0;
+           i < sk_RSA_additional_prime_num(rsa->additional_primes); i++) {
+        const RSA_additional_prime *ap =
+            sk_RSA_additional_prime_value(rsa->additional_primes, i);
+        update_buflen(ap->prime, &buf_len);
+        update_buflen(ap->exp, &buf_len);
+        update_buflen(ap->coeff, &buf_len);
+      }
+    }
+  }
+
+  m = (uint8_t *)OPENSSL_malloc(buf_len + 10);
+  if (m == NULL) {
+    OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
+    goto err;
+  }
+
+  if (rsa->n != NULL) {
+    mod_len = BN_num_bits(rsa->n);
+  }
+
+  if (!BIO_indent(out, off, 128)) {
+    goto err;
+  }
+
+  if (include_private && rsa->d) {
+    if (BIO_printf(out, "Private-Key: (%d bit)\n", mod_len) <= 0) {
+      goto err;
+    }
+    str = "modulus:";
+    s = "publicExponent:";
+  } else {
+    if (BIO_printf(out, "Public-Key: (%d bit)\n", mod_len) <= 0) {
+      goto err;
+    }
+    str = "Modulus:";
+    s = "Exponent:";
+  }
+  if (!bn_print(out, str, rsa->n, m, off) ||
+      !bn_print(out, s, rsa->e, m, off)) {
+    goto err;
+  }
+
+  if (include_private) {
+    if (!bn_print(out, "privateExponent:", rsa->d, m, off) ||
+        !bn_print(out, "prime1:", rsa->p, m, off) ||
+        !bn_print(out, "prime2:", rsa->q, m, off) ||
+        !bn_print(out, "exponent1:", rsa->dmp1, m, off) ||
+        !bn_print(out, "exponent2:", rsa->dmq1, m, off) ||
+        !bn_print(out, "coefficient:", rsa->iqmp, m, off)) {
+      goto err;
+    }
+
+    if (rsa->additional_primes != NULL &&
+        sk_RSA_additional_prime_num(rsa->additional_primes) > 0) {
+      if (BIO_printf(out, "otherPrimeInfos:\n") <= 0) {
+        goto err;
+      }
+      for (size_t i = 0;
+           i < sk_RSA_additional_prime_num(rsa->additional_primes); i++) {
+        const RSA_additional_prime *ap =
+            sk_RSA_additional_prime_value(rsa->additional_primes, i);
+
+        if (BIO_printf(out, "otherPrimeInfo (prime %u):\n",
+                       (unsigned)(i + 3)) <= 0 ||
+            !bn_print(out, "prime:", ap->prime, m, off) ||
+            !bn_print(out, "exponent:", ap->exp, m, off) ||
+            !bn_print(out, "coeff:", ap->coeff, m, off)) {
+          goto err;
+        }
+      }
+    }
+  }
+  ret = 1;
+
+err:
+  OPENSSL_free(m);
+  return ret;
+}
+
+static int rsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+                         ASN1_PCTX *ctx) {
+  return do_rsa_print(bp, pkey->pkey.rsa, indent, 0);
+}
+
+static int rsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+                          ASN1_PCTX *ctx) {
+  return do_rsa_print(bp, pkey->pkey.rsa, indent, 1);
+}
+
+
+/* DSA keys. */
+
+static int do_dsa_print(BIO *bp, const DSA *x, int off, int ptype) {
+  uint8_t *m = NULL;
+  int ret = 0;
+  size_t buf_len = 0;
+  const char *ktype = NULL;
+
+  const BIGNUM *priv_key, *pub_key;
+
+  priv_key = NULL;
+  if (ptype == 2) {
+    priv_key = x->priv_key;
+  }
+
+  pub_key = NULL;
+  if (ptype > 0) {
+    pub_key = x->pub_key;
+  }
+
+  ktype = "DSA-Parameters";
+  if (ptype == 2) {
+    ktype = "Private-Key";
+  } else if (ptype == 1) {
+    ktype = "Public-Key";
+  }
+
+  update_buflen(x->p, &buf_len);
+  update_buflen(x->q, &buf_len);
+  update_buflen(x->g, &buf_len);
+  update_buflen(priv_key, &buf_len);
+  update_buflen(pub_key, &buf_len);
+
+  m = (uint8_t *)OPENSSL_malloc(buf_len + 10);
+  if (m == NULL) {
+    OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
+    goto err;
+  }
+
+  if (priv_key) {
+    if (!BIO_indent(bp, off, 128) ||
+        BIO_printf(bp, "%s: (%d bit)\n", ktype, BN_num_bits(x->p)) <= 0) {
+      goto err;
+    }
+  }
+
+  if (!bn_print(bp, "priv:", priv_key, m, off) ||
+      !bn_print(bp, "pub: ", pub_key, m, off) ||
+      !bn_print(bp, "P:   ", x->p, m, off) ||
+      !bn_print(bp, "Q:   ", x->q, m, off) ||
+      !bn_print(bp, "G:   ", x->g, m, off)) {
+    goto err;
+  }
+  ret = 1;
+
+err:
+  OPENSSL_free(m);
+  return ret;
+}
+
+static int dsa_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+                           ASN1_PCTX *ctx) {
+  return do_dsa_print(bp, pkey->pkey.dsa, indent, 0);
+}
+
+static int dsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+                         ASN1_PCTX *ctx) {
+  return do_dsa_print(bp, pkey->pkey.dsa, indent, 1);
+}
+
+static int dsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+                          ASN1_PCTX *ctx) {
+  return do_dsa_print(bp, pkey->pkey.dsa, indent, 2);
+}
+
+
+/* EC keys. */
+
+static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype) {
+  uint8_t *buffer = NULL;
+  const char *ecstr;
+  size_t buf_len = 0, i;
+  int ret = 0, reason = ERR_R_BIO_LIB;
+  BIGNUM *order = NULL;
+  BN_CTX *ctx = NULL;
+  const EC_GROUP *group;
+  const EC_POINT *public_key;
+  const BIGNUM *priv_key;
+  uint8_t *pub_key_bytes = NULL;
+  size_t pub_key_bytes_len = 0;
+
+  if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) {
+    reason = ERR_R_PASSED_NULL_PARAMETER;
+    goto err;
+  }
+
+  ctx = BN_CTX_new();
+  if (ctx == NULL) {
+    reason = ERR_R_MALLOC_FAILURE;
+    goto err;
+  }
+
+  if (ktype > 0) {
+    public_key = EC_KEY_get0_public_key(x);
+    if (public_key != NULL) {
+      pub_key_bytes_len = EC_POINT_point2oct(
+          group, public_key, EC_KEY_get_conv_form(x), NULL, 0, ctx);
+      if (pub_key_bytes_len == 0) {
+        reason = ERR_R_MALLOC_FAILURE;
+        goto err;
+      }
+      pub_key_bytes = OPENSSL_malloc(pub_key_bytes_len);
+      if (pub_key_bytes == NULL) {
+        reason = ERR_R_MALLOC_FAILURE;
+        goto err;
+      }
+      pub_key_bytes_len =
+          EC_POINT_point2oct(group, public_key, EC_KEY_get_conv_form(x),
+                             pub_key_bytes, pub_key_bytes_len, ctx);
+      if (pub_key_bytes_len == 0) {
+        reason = ERR_R_MALLOC_FAILURE;
+        goto err;
+      }
+      buf_len = pub_key_bytes_len;
+    }
+  }
+
+  if (ktype == 2) {
+    priv_key = EC_KEY_get0_private_key(x);
+    if (priv_key && (i = (size_t)BN_num_bytes(priv_key)) > buf_len) {
+      buf_len = i;
+    }
+  } else {
+    priv_key = NULL;
+  }
+
+  if (ktype > 0) {
+    buf_len += 10;
+    if ((buffer = OPENSSL_malloc(buf_len)) == NULL) {
+      reason = ERR_R_MALLOC_FAILURE;
+      goto err;
+    }
+  }
+  if (ktype == 2) {
+    ecstr = "Private-Key";
+  } else if (ktype == 1) {
+    ecstr = "Public-Key";
+  } else {
+    ecstr = "ECDSA-Parameters";
+  }
+
+  if (!BIO_indent(bp, off, 128)) {
+    goto err;
+  }
+  order = BN_new();
+  if (order == NULL || !EC_GROUP_get_order(group, order, NULL) ||
+      BIO_printf(bp, "%s: (%d bit)\n", ecstr, BN_num_bits(order)) <= 0) {
+    goto err;
+  }
+
+  if ((priv_key != NULL) &&
+      !bn_print(bp, "priv:", priv_key, buffer, off)) {
+    goto err;
+  }
+  if (pub_key_bytes != NULL) {
+    BIO_hexdump(bp, pub_key_bytes, pub_key_bytes_len, off);
+  }
+  /* TODO(fork): implement */
+  /*
+  if (!ECPKParameters_print(bp, group, off))
+    goto err; */
+  ret = 1;
+
+err:
+  if (!ret) {
+    OPENSSL_PUT_ERROR(EVP, reason);
+  }
+  OPENSSL_free(pub_key_bytes);
+  BN_free(order);
+  BN_CTX_free(ctx);
+  OPENSSL_free(buffer);
+  return ret;
+}
+
+static int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+                             ASN1_PCTX *ctx) {
+  return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 0);
+}
+
+static int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+                           ASN1_PCTX *ctx) {
+  return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 1);
+}
+
+
+static int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
+                            ASN1_PCTX *ctx) {
+  return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 2);
+}
+
+
+typedef struct {
+  int type;
+  int (*pub_print)(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx);
+  int (*priv_print)(BIO *out, const EVP_PKEY *pkey, int indent,
+                    ASN1_PCTX *pctx);
+  int (*param_print)(BIO *out, const EVP_PKEY *pkey, int indent,
+                     ASN1_PCTX *pctx);
+} EVP_PKEY_PRINT_METHOD;
+
+static EVP_PKEY_PRINT_METHOD kPrintMethods[] = {
+    {
+        EVP_PKEY_RSA,
+        rsa_pub_print,
+        rsa_priv_print,
+        NULL /* param_print */,
+    },
+    {
+        EVP_PKEY_DSA,
+        dsa_pub_print,
+        dsa_priv_print,
+        dsa_param_print,
+    },
+    {
+        EVP_PKEY_EC,
+        eckey_pub_print,
+        eckey_priv_print,
+        eckey_param_print,
+    },
+};
+
+static size_t kPrintMethodsLen = OPENSSL_ARRAY_SIZE(kPrintMethods);
+
+static EVP_PKEY_PRINT_METHOD *find_method(int type) {
+  for (size_t i = 0; i < kPrintMethodsLen; i++) {
+    if (kPrintMethods[i].type == type) {
+      return &kPrintMethods[i];
+    }
+  }
+  return NULL;
+}
+
+static int print_unsupported(BIO *out, const EVP_PKEY *pkey, int indent,
+                             const char *kstr) {
+  BIO_indent(out, indent, 128);
+  BIO_printf(out, "%s algorithm unsupported\n", kstr);
+  return 1;
+}
+
+int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey, int indent,
+                          ASN1_PCTX *pctx) {
+  EVP_PKEY_PRINT_METHOD *method = find_method(pkey->type);
+  if (method != NULL && method->pub_print != NULL) {
+    return method->pub_print(out, pkey, indent, pctx);
+  }
+  return print_unsupported(out, pkey, indent, "Public Key");
+}
+
+int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey, int indent,
+                           ASN1_PCTX *pctx) {
+  EVP_PKEY_PRINT_METHOD *method = find_method(pkey->type);
+  if (method != NULL && method->priv_print != NULL) {
+    return method->priv_print(out, pkey, indent, pctx);
+  }
+  return print_unsupported(out, pkey, indent, "Private Key");
+}
+
+int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey, int indent,
+                          ASN1_PCTX *pctx) {
+  EVP_PKEY_PRINT_METHOD *method = find_method(pkey->type);
+  if (method != NULL && method->param_print != NULL) {
+    return method->param_print(out, pkey, indent, pctx);
+  }
+  return print_unsupported(out, pkey, indent, "Parameters");
+}
diff --git a/src/crypto/ex_data.c b/src/crypto/ex_data.c
index 8fa1240..5286513 100644
--- a/src/crypto/ex_data.c
+++ b/src/crypto/ex_data.c
@@ -163,7 +163,7 @@
   ret = 1;
 
 err:
-  CRYPTO_STATIC_MUTEX_unlock(&ex_data_class->lock);
+  CRYPTO_STATIC_MUTEX_unlock_write(&ex_data_class->lock);
   return ret;
 }
 
@@ -217,7 +217,7 @@
   if (n > 0) {
     *out = sk_CRYPTO_EX_DATA_FUNCS_dup(ex_data_class->meth);
   }
-  CRYPTO_STATIC_MUTEX_unlock(&ex_data_class->lock);
+  CRYPTO_STATIC_MUTEX_unlock_read(&ex_data_class->lock);
 
   if (n > 0 && *out == NULL) {
     OPENSSL_PUT_ERROR(CRYPTO, ERR_R_MALLOC_FAILURE);
@@ -244,8 +244,7 @@
     return 0;
   }
 
-  size_t i;
-  for (i = 0; i < sk_CRYPTO_EX_DATA_FUNCS_num(func_pointers); i++) {
+  for (size_t i = 0; i < sk_CRYPTO_EX_DATA_FUNCS_num(func_pointers); i++) {
     CRYPTO_EX_DATA_FUNCS *func_pointer =
         sk_CRYPTO_EX_DATA_FUNCS_value(func_pointers, i);
     void *ptr = CRYPTO_get_ex_data(from, i + ex_data_class->num_reserved);
@@ -274,8 +273,7 @@
     return;
   }
 
-  size_t i;
-  for (i = 0; i < sk_CRYPTO_EX_DATA_FUNCS_num(func_pointers); i++) {
+  for (size_t i = 0; i < sk_CRYPTO_EX_DATA_FUNCS_num(func_pointers); i++) {
     CRYPTO_EX_DATA_FUNCS *func_pointer =
         sk_CRYPTO_EX_DATA_FUNCS_value(func_pointers, i);
     if (func_pointer->free_func) {
diff --git a/src/crypto/hkdf/CMakeLists.txt b/src/crypto/hkdf/CMakeLists.txt
index d9db933..3056a54 100644
--- a/src/crypto/hkdf/CMakeLists.txt
+++ b/src/crypto/hkdf/CMakeLists.txt
@@ -11,7 +11,7 @@
 add_executable(
   hkdf_test
 
-  hkdf_test.c
+  hkdf_test.cc
 
   $<TARGET_OBJECTS:test_support>
 )
diff --git a/src/crypto/hkdf/hkdf.c b/src/crypto/hkdf/hkdf.c
index f9cdcb0..ae43b69 100644
--- a/src/crypto/hkdf/hkdf.c
+++ b/src/crypto/hkdf/hkdf.c
@@ -20,22 +20,52 @@
 #include <openssl/err.h>
 #include <openssl/hmac.h>
 
+#include "../internal.h"
 
-int HKDF(uint8_t *out_key, size_t out_len,
-         const EVP_MD *digest,
-         const uint8_t *secret, size_t secret_len,
-         const uint8_t *salt, size_t salt_len,
-         const uint8_t *info, size_t info_len) {
+
+int HKDF(uint8_t *out_key, size_t out_len, const EVP_MD *digest,
+         const uint8_t *secret, size_t secret_len, const uint8_t *salt,
+         size_t salt_len, const uint8_t *info, size_t info_len) {
+  /* https://tools.ietf.org/html/rfc5869#section-2 */
+  uint8_t prk[EVP_MAX_MD_SIZE];
+  size_t prk_len;
+
+  if (!HKDF_extract(prk, &prk_len, digest, secret, secret_len, salt,
+                    salt_len) ||
+      !HKDF_expand(out_key, out_len, digest, prk, prk_len, info, info_len)) {
+    return 0;
+  }
+
+  return 1;
+}
+
+int HKDF_extract(uint8_t *out_key, size_t *out_len, const EVP_MD *digest,
+                 const uint8_t *secret, size_t secret_len, const uint8_t *salt,
+                 size_t salt_len) {
   /* https://tools.ietf.org/html/rfc5869#section-2.2 */
-  const size_t digest_len = EVP_MD_size(digest);
-  uint8_t prk[EVP_MAX_MD_SIZE], previous[EVP_MAX_MD_SIZE];
-  size_t n, done = 0;
-  unsigned i, prk_len;
-  int ret = 0;
-  HMAC_CTX hmac;
 
   /* If salt is not given, HashLength zeros are used. However, HMAC does that
    * internally already so we can ignore it.*/
+  unsigned len;
+  if (HMAC(digest, salt, salt_len, secret, secret_len, out_key, &len) == NULL) {
+    OPENSSL_PUT_ERROR(HKDF, ERR_R_HMAC_LIB);
+    return 0;
+  }
+  *out_len = len;
+  assert(*out_len == EVP_MD_size(digest));
+  return 1;
+}
+
+int HKDF_expand(uint8_t *out_key, size_t out_len, const EVP_MD *digest,
+                const uint8_t *prk, size_t prk_len, const uint8_t *info,
+                size_t info_len) {
+  /* https://tools.ietf.org/html/rfc5869#section-2.3 */
+  const size_t digest_len = EVP_MD_size(digest);
+  uint8_t previous[EVP_MAX_MD_SIZE];
+  size_t n, done = 0;
+  unsigned i;
+  int ret = 0;
+  HMAC_CTX hmac;
 
   /* Expand key material to desired length. */
   n = (out_len + digest_len - 1) / digest_len;
@@ -45,13 +75,6 @@
   }
 
   HMAC_CTX_init(&hmac);
-
-  /* Extract input keying material into pseudorandom key |prk|. */
-  if (HMAC(digest, salt, salt_len, secret, secret_len, prk, &prk_len) == NULL) {
-    goto out;
-  }
-  assert(prk_len == digest_len);
-
   if (!HMAC_Init_ex(&hmac, prk, prk_len, digest, NULL)) {
     goto out;
   }
@@ -74,7 +97,7 @@
     if (done + todo > out_len) {
       todo = out_len - done;
     }
-    memcpy(out_key + done, previous, todo);
+    OPENSSL_memcpy(out_key + done, previous, todo);
     done += todo;
   }
 
diff --git a/src/crypto/hkdf/hkdf_test.c b/src/crypto/hkdf/hkdf_test.cc
similarity index 76%
rename from src/crypto/hkdf/hkdf_test.c
rename to src/crypto/hkdf/hkdf_test.cc
index 63070dc..164fa1f 100644
--- a/src/crypto/hkdf/hkdf_test.c
+++ b/src/crypto/hkdf/hkdf_test.cc
@@ -20,8 +20,11 @@
 #include <openssl/err.h>
 #include <openssl/hkdf.h>
 
+#include "../internal.h"
+#include "../test/test_util.h"
 
-typedef struct {
+
+struct HKDFTestVector {
   const EVP_MD *(*md_func)(void);
   const uint8_t ikm[80];
   const size_t ikm_len;
@@ -29,12 +32,14 @@
   const size_t salt_len;
   const uint8_t info[80];
   const size_t info_len;
+  const uint8_t prk[EVP_MAX_MD_SIZE];
+  const size_t prk_len;
   const size_t out_len;
   const uint8_t out[82];
-} hkdf_test_vector_t;
+};
 
 /* These test vectors are from RFC 5869. */
-static const hkdf_test_vector_t kTests[] = {
+static const HKDFTestVector kTests[] = {
   {
     EVP_sha256,
     {
@@ -48,6 +53,11 @@
     {
       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
     }, 10,
+    {
+      0x07, 0x77, 0x09, 0x36, 0x2c, 0x2e, 0x32, 0xdf, 0x0d, 0xdc, 0x3f, 0x0d,
+      0xc4, 0x7b, 0xba, 0x63, 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31,
+      0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5,
+    }, 32,
     42, {
       0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, 0x90, 0x43, 0x4f, 0x64,
       0xd0, 0x36, 0x2f, 0x2a, 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c,
@@ -84,6 +94,11 @@
       0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
     }, 80,
+    {
+       0x06, 0xa6, 0xb8, 0x8c, 0x58, 0x53, 0x36, 0x1a, 0x06, 0x10, 0x4c, 0x9c,
+       0xeb, 0x35, 0xb4, 0x5c, 0xef, 0x76, 0x00, 0x14, 0x90, 0x46, 0x71, 0x01,
+       0x4a, 0x19, 0x3f, 0x40, 0xc1, 0x5f, 0xc2, 0x44,
+    }, 32,
     82, {
       0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1, 0xc8, 0xe7, 0xf7, 0x8c,
       0x59, 0x6a, 0x49, 0x34, 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8,
@@ -106,6 +121,11 @@
     {
        0,
     }, 0,
+    {
+      0x19, 0xef, 0x24, 0xa3, 0x2c, 0x71, 0x7b, 0x16, 0x7f, 0x33, 0xa9, 0x1d,
+      0x6f, 0x64, 0x8b, 0xdf, 0x96, 0x59, 0x67, 0x76, 0xaf, 0xdb, 0x63, 0x77,
+      0xac, 0x43, 0x4c, 0x1c, 0x29, 0x3c, 0xcb, 0x04
+    }, 32,
     42, {
       0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, 0x71, 0x5f, 0x80, 0x2a,
       0x06, 0x3c, 0x5a, 0x31, 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e,
@@ -125,6 +145,10 @@
     {
       0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9,
     }, 10,
+    {
+      0x9b, 0x6c, 0x18, 0xc4, 0x32, 0xa7, 0xbf, 0x8f, 0x0e, 0x71, 0xc8, 0xeb,
+      0x88, 0xf4, 0xb3, 0x0b, 0xaa, 0x2b, 0xa2, 0x43
+    }, 20,
     42, {
       0x08, 0x5a, 0x01, 0xea, 0x1b, 0x10, 0xf3, 0x69, 0x33, 0x06, 0x8b, 0x56,
       0xef, 0xa5, 0xad, 0x81, 0xa4, 0xf1, 0x4b, 0x82, 0x2f, 0x5b, 0x09, 0x15,
@@ -161,6 +185,10 @@
       0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
       0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
     }, 80,
+    {
+      0x8a, 0xda, 0xe0, 0x9a, 0x2a, 0x30, 0x70, 0x59, 0x47, 0x8d, 0x30, 0x9b,
+      0x26, 0xc4, 0x11, 0x5a, 0x22, 0x4c, 0xfa, 0xf6,
+    }, 20,
     82, {
       0x0b, 0xd7, 0x70, 0xa7, 0x4d, 0x11, 0x60, 0xf7, 0xc9, 0xf1, 0x2c, 0xd5,
       0x91, 0x2a, 0x06, 0xeb, 0xff, 0x6a, 0xdc, 0xae, 0x89, 0x9d, 0x92, 0x19,
@@ -183,6 +211,10 @@
     {
        0,
     }, 0,
+    {
+      0xda, 0x8c, 0x8a, 0x73, 0xc7, 0xfa, 0x77, 0x28, 0x8e, 0xc6, 0xf5, 0xe7,
+      0xc2, 0x97, 0x78, 0x6a, 0xa0, 0xd3, 0x2d, 0x01,
+    }, 20,
     42, {
       0x0a, 0xc1, 0xaf, 0x70, 0x02, 0xb3, 0xd7, 0x61, 0xd1, 0xe5, 0x52, 0x98,
       0xda, 0x9d, 0x05, 0x06, 0xb9, 0xae, 0x52, 0x05, 0x72, 0x20, 0xa3, 0x06,
@@ -202,6 +234,10 @@
     {
        0,
     }, 0,
+    {
+      0x2a, 0xdc, 0xca, 0xda, 0x18, 0x77, 0x9e, 0x7c, 0x20, 0x77, 0xad, 0x2e,
+      0xb1, 0x9d, 0x3f, 0x3e, 0x73, 0x13, 0x85, 0xdd,
+    }, 20,
     42, {
       0x2c, 0x91, 0x11, 0x72, 0x04, 0xd7, 0x45, 0xf3, 0x50, 0x0d, 0x63, 0x6a,
       0x62, 0xf6, 0x4f, 0x0a, 0xb3, 0xba, 0xe5, 0x48, 0xaa, 0x53, 0xd4, 0x23,
@@ -212,28 +248,49 @@
 };
 
 int main(void) {
-  uint8_t buf[82];
-  size_t i;
-
   CRYPTO_library_init();
-  ERR_load_crypto_strings();
 
-  for (i = 0; i < sizeof(kTests) / sizeof(kTests[0]); i++) {
-    const hkdf_test_vector_t *test = &kTests[i];
+  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kTests); i++) {
+    const HKDFTestVector *test = &kTests[i];
+    uint8_t prk[EVP_MAX_MD_SIZE];
+    size_t prk_len;
+    if (!HKDF_extract(prk, &prk_len, test->md_func(), test->ikm, test->ikm_len,
+                      test->salt, test->salt_len)) {
+      fprintf(stderr, "Call to HKDF_extract failed\n");
+      ERR_print_errors_fp(stderr);
+      return 1;
+    }
+    if (prk_len != test->prk_len ||
+        OPENSSL_memcmp(prk, test->prk, test->prk_len) != 0) {
+      fprintf(stderr, "%zu: Resulting PRK does not match test vector\n", i);
+      return 1;
+    }
+    uint8_t buf[82];
+    if (!HKDF_expand(buf, test->out_len, test->md_func(), prk, prk_len,
+                     test->info, test->info_len)) {
+      fprintf(stderr, "Call to HKDF_expand failed\n");
+      ERR_print_errors_fp(stderr);
+      return 1;
+    }
+    if (OPENSSL_memcmp(buf, test->out, test->out_len) != 0) {
+      fprintf(stderr,
+              "%zu: Resulting key material does not match test vector\n", i);
+      return 1;
+    }
+
     if (!HKDF(buf, test->out_len, test->md_func(), test->ikm, test->ikm_len,
               test->salt, test->salt_len, test->info, test->info_len)) {
       fprintf(stderr, "Call to HKDF failed\n");
       ERR_print_errors_fp(stderr);
       return 1;
     }
-    if (memcmp(buf, test->out, test->out_len) != 0) {
-      fprintf(stderr, "%u: Resulting key material does not match test vector\n",
-              (unsigned)i);
+    if (OPENSSL_memcmp(buf, test->out, test->out_len) != 0) {
+      fprintf(stderr,
+              "%zu: Resulting key material does not match test vector\n", i);
       return 1;
     }
   }
 
   printf("PASS\n");
-  ERR_free_strings();
   return 0;
 }
diff --git a/src/crypto/hmac/hmac.c b/src/crypto/hmac/hmac.c
index be2dcce..a252667 100644
--- a/src/crypto/hmac/hmac.c
+++ b/src/crypto/hmac/hmac.c
@@ -59,8 +59,11 @@
 #include <assert.h>
 #include <string.h>
 
+#include <openssl/digest.h>
 #include <openssl/mem.h>
 
+#include "../internal.h"
+
 
 uint8_t *HMAC(const EVP_MD *evp_md, const void *key, size_t key_len,
               const uint8_t *data, size_t data_len, uint8_t *out,
@@ -114,9 +117,8 @@
    * exist callers which intend the latter, but the former is an awkward edge
    * case. Fix to API to avoid this. */
   if (md != ctx->md || key != NULL) {
-    size_t i;
-    uint8_t pad[HMAC_MAX_MD_CBLOCK];
-    uint8_t key_block[HMAC_MAX_MD_CBLOCK];
+    uint8_t pad[EVP_MAX_MD_BLOCK_SIZE];
+    uint8_t key_block[EVP_MAX_MD_BLOCK_SIZE];
     unsigned key_block_len;
 
     size_t block_size = EVP_MD_block_size(md);
@@ -130,15 +132,15 @@
       }
     } else {
       assert(key_len <= sizeof(key_block));
-      memcpy(key_block, key, key_len);
+      OPENSSL_memcpy(key_block, key, key_len);
       key_block_len = (unsigned)key_len;
     }
     /* Keys are then padded with zeros. */
-    if (key_block_len != HMAC_MAX_MD_CBLOCK) {
-      memset(&key_block[key_block_len], 0, sizeof(key_block) - key_block_len);
+    if (key_block_len != EVP_MAX_MD_BLOCK_SIZE) {
+      OPENSSL_memset(&key_block[key_block_len], 0, sizeof(key_block) - key_block_len);
     }
 
-    for (i = 0; i < HMAC_MAX_MD_CBLOCK; i++) {
+    for (size_t i = 0; i < EVP_MAX_MD_BLOCK_SIZE; i++) {
       pad[i] = 0x36 ^ key_block[i];
     }
     if (!EVP_DigestInit_ex(&ctx->i_ctx, md, impl) ||
@@ -146,7 +148,7 @@
       return 0;
     }
 
-    for (i = 0; i < HMAC_MAX_MD_CBLOCK; i++) {
+    for (size_t i = 0; i < EVP_MAX_MD_BLOCK_SIZE; i++) {
       pad[i] = 0x5c ^ key_block[i];
     }
     if (!EVP_DigestInit_ex(&ctx->o_ctx, md, impl) ||
diff --git a/src/crypto/hmac/hmac_test.cc b/src/crypto/hmac/hmac_test.cc
index da390ef..7b216e2 100644
--- a/src/crypto/hmac/hmac_test.cc
+++ b/src/crypto/hmac/hmac_test.cc
@@ -57,6 +57,7 @@
 #include <stdio.h>
 #include <string.h>
 
+#include <memory>
 #include <string>
 #include <vector>
 
@@ -65,7 +66,6 @@
 #include <openssl/hmac.h>
 
 #include "../test/file_test.h"
-#include "../test/scoped_types.h"
 
 
 static const EVP_MD *GetDigest(const std::string &name) {
@@ -104,21 +104,24 @@
   }
 
   // Test using the one-shot API.
-  uint8_t mac[EVP_MAX_MD_SIZE];
+  unsigned expected_mac_len = EVP_MD_size(digest);
+  std::unique_ptr<uint8_t[]> mac(new uint8_t[expected_mac_len]);
   unsigned mac_len;
   if (nullptr == HMAC(digest, key.data(), key.size(), input.data(),
-                      input.size(), mac, &mac_len) ||
-      !t->ExpectBytesEqual(output.data(), output.size(), mac, mac_len)) {
+                      input.size(), mac.get(), &mac_len) ||
+      mac_len != expected_mac_len ||
+      !t->ExpectBytesEqual(output.data(), output.size(), mac.get(), mac_len)) {
     t->PrintLine("One-shot API failed.");
     return false;
   }
 
   // Test using HMAC_CTX.
-  ScopedHMAC_CTX ctx;
+  bssl::ScopedHMAC_CTX ctx;
   if (!HMAC_Init_ex(ctx.get(), key.data(), key.size(), digest, nullptr) ||
       !HMAC_Update(ctx.get(), input.data(), input.size()) ||
-      !HMAC_Final(ctx.get(), mac, &mac_len) ||
-      !t->ExpectBytesEqual(output.data(), output.size(), mac, mac_len)) {
+      !HMAC_Final(ctx.get(), mac.get(), &mac_len) ||
+      mac_len != expected_mac_len ||
+      !t->ExpectBytesEqual(output.data(), output.size(), mac.get(), mac_len)) {
     t->PrintLine("HMAC_CTX failed.");
    return false;
   }
@@ -126,8 +129,9 @@
   // Test that an HMAC_CTX may be reset with the same key.
   if (!HMAC_Init_ex(ctx.get(), nullptr, 0, digest, nullptr) ||
       !HMAC_Update(ctx.get(), input.data(), input.size()) ||
-      !HMAC_Final(ctx.get(), mac, &mac_len) ||
-      !t->ExpectBytesEqual(output.data(), output.size(), mac, mac_len)) {
+      !HMAC_Final(ctx.get(), mac.get(), &mac_len) ||
+      mac_len != expected_mac_len ||
+      !t->ExpectBytesEqual(output.data(), output.size(), mac.get(), mac_len)) {
     t->PrintLine("HMAC_CTX with reset failed.");
    return false;
   }
@@ -143,8 +147,9 @@
       return false;
     }
   }
-  if (!HMAC_Final(ctx.get(), mac, &mac_len) ||
-      !t->ExpectBytesEqual(output.data(), output.size(), mac, mac_len)) {
+  if (!HMAC_Final(ctx.get(), mac.get(), &mac_len) ||
+      mac_len != expected_mac_len ||
+      !t->ExpectBytesEqual(output.data(), output.size(), mac.get(), mac_len)) {
     t->PrintLine("HMAC_CTX streaming failed.");
     return false;
   }
diff --git a/src/crypto/internal.h b/src/crypto/internal.h
index bf45349..2724956 100644
--- a/src/crypto/internal.h
+++ b/src/crypto/internal.h
@@ -112,13 +112,29 @@
 #include <openssl/ex_data.h>
 #include <openssl/thread.h>
 
-#if defined(OPENSSL_NO_THREADS)
-#elif defined(OPENSSL_WINDOWS)
-#pragma warning(push, 3)
-#include <windows.h>
-#pragma warning(pop)
+#include <string.h>
+
+#if defined(_MSC_VER)
+#if !defined(__cplusplus) || _MSC_VER < 1900
+#define alignas(x) __declspec(align(x))
+#define alignof __alignof
+#endif
 #else
+#include <stdalign.h>
+#endif
+
+#if !defined(OPENSSL_NO_THREADS) && \
+    (!defined(OPENSSL_WINDOWS) || defined(__MINGW32__))
 #include <pthread.h>
+#define OPENSSL_PTHREADS
+#endif
+
+#if !defined(OPENSSL_NO_THREADS) && !defined(OPENSSL_PTHREADS) && \
+    defined(OPENSSL_WINDOWS)
+#define OPENSSL_WINDOWS_THREADS
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
+#include <windows.h>
+OPENSSL_MSVC_PRAGMA(warning(pop))
 #endif
 
 #if defined(__cplusplus)
@@ -126,58 +142,32 @@
 #endif
 
 
-/* MSVC's C4701 warning about the use of *potentially*--as opposed to
- * *definitely*--uninitialized values sometimes has false positives. Usually
- * the false positives can and should be worked around by simplifying the
- * control flow. When that is not practical, annotate the function containing
- * the code that triggers the warning with
- * OPENSSL_SUPPRESS_POTENTIALLY_UNINITIALIZED_WARNINGS after its parameters:
- *
- *    void f() OPENSSL_SUPPRESS_POTENTIALLY_UNINITIALIZED_WARNINGS {
- *       ...
- *    }
- *
- * Note that MSVC's control flow analysis seems to operate on a whole-function
- * basis, so the annotation must be placed on the entire function, not just a
- * block within the function. */
-#if defined(_MSC_VER)
-#define OPENSSL_SUPPRESS_POTENTIALLY_UNINITIALIZED_WARNINGS \
-        __pragma(warning(suppress:4701))
-#else
-#define OPENSSL_SUPPRESS_POTENTIALLY_UNINITIALIZED_WARNINGS
-#endif
-
-/* MSVC will sometimes correctly detect unreachable code and issue a warning,
- * which breaks the build since we treat errors as warnings, in some rare cases
- * where we want to allow the dead code to continue to exist. In these
- * situations, annotate the function containing the unreachable code with
- * OPENSSL_SUPPRESS_UNREACHABLE_CODE_WARNINGS after its parameters:
- *
- *    void f() OPENSSL_SUPPRESS_UNREACHABLE_CODE_WARNINGS {
- *       ...
- *    }
- *
- * Note that MSVC's reachability analysis seems to operate on a whole-function
- * basis, so the annotation must be placed on the entire function, not just a
- * block within the function. */
-#if defined(_MSC_VER)
-#define OPENSSL_SUPPRESS_UNREACHABLE_CODE_WARNINGS \
-        __pragma(warning(suppress:4702))
-#else
-#define OPENSSL_SUPPRESS_UNREACHABLE_CODE_WARNINGS
-#endif
-
-
 #if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || defined(OPENSSL_ARM) || \
-    defined(OPENSSL_AARCH64)
-/* OPENSSL_cpuid_setup initializes OPENSSL_ia32cap_P. */
+    defined(OPENSSL_AARCH64) || defined(OPENSSL_PPC64LE)
+/* OPENSSL_cpuid_setup initializes the platform-specific feature cache. */
 void OPENSSL_cpuid_setup(void);
 #endif
 
-#if !defined(inline)
-#define inline __inline
+
+#if !defined(_MSC_VER) && defined(OPENSSL_64_BIT)
+typedef __int128_t int128_t;
+typedef __uint128_t uint128_t;
 #endif
 
+#define OPENSSL_ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
+
+/* buffers_alias returns one if |a| and |b| alias and zero otherwise. */
+static inline int buffers_alias(const uint8_t *a, size_t a_len,
+                                const uint8_t *b, size_t b_len) {
+  /* Cast |a| and |b| to integers. In C, pointer comparisons between unrelated
+   * objects are undefined whereas pointer to integer conversions are merely
+   * implementation-defined. We assume the implementation defined it in a sane
+   * way. */
+  uintptr_t a_u = (uintptr_t)a;
+  uintptr_t b_u = (uintptr_t)b;
+  return a_u + a_len > b_u && b_u + b_len > a_u;
+}
+
 
 /* Constant-time utility functions.
  *
@@ -324,12 +314,14 @@
 #if defined(OPENSSL_NO_THREADS)
 typedef uint32_t CRYPTO_once_t;
 #define CRYPTO_ONCE_INIT 0
-#elif defined(OPENSSL_WINDOWS)
-typedef LONG CRYPTO_once_t;
-#define CRYPTO_ONCE_INIT 0
-#else
+#elif defined(OPENSSL_WINDOWS_THREADS)
+typedef INIT_ONCE CRYPTO_once_t;
+#define CRYPTO_ONCE_INIT INIT_ONCE_STATIC_INIT
+#elif defined(OPENSSL_PTHREADS)
 typedef pthread_once_t CRYPTO_once_t;
 #define CRYPTO_ONCE_INIT PTHREAD_ONCE_INIT
+#else
+#error "Unknown threading library"
 #endif
 
 /* CRYPTO_once calls |init| exactly once per process. This is thread-safe: if
@@ -372,27 +364,26 @@
  * |CRYPTO_STATIC_MUTEX_INIT|.
  *
  * |CRYPTO_MUTEX| can appear in public structures and so is defined in
- * thread.h.
- *
- * The global lock is a different type because there's no static initialiser
- * value on Windows for locks, so global locks have to be coupled with a
- * |CRYPTO_once_t| to ensure that the lock is setup before use. This is done
- * automatically by |CRYPTO_STATIC_MUTEX_lock_*|. */
+ * thread.h as a structure large enough to fit the real type. The global lock is
+ * a different type so it may be initialized with platform initializer macros.*/
 
 #if defined(OPENSSL_NO_THREADS)
-struct CRYPTO_STATIC_MUTEX {};
-#define CRYPTO_STATIC_MUTEX_INIT {}
-#elif defined(OPENSSL_WINDOWS)
 struct CRYPTO_STATIC_MUTEX {
-  CRYPTO_once_t once;
-  CRITICAL_SECTION lock;
+  char padding;  /* Empty structs have different sizes in C and C++. */
 };
-#define CRYPTO_STATIC_MUTEX_INIT { CRYPTO_ONCE_INIT, { 0 } }
-#else
+#define CRYPTO_STATIC_MUTEX_INIT { 0 }
+#elif defined(OPENSSL_WINDOWS_THREADS)
+struct CRYPTO_STATIC_MUTEX {
+  SRWLOCK lock;
+};
+#define CRYPTO_STATIC_MUTEX_INIT { SRWLOCK_INIT }
+#elif defined(OPENSSL_PTHREADS)
 struct CRYPTO_STATIC_MUTEX {
   pthread_rwlock_t lock;
 };
 #define CRYPTO_STATIC_MUTEX_INIT { PTHREAD_RWLOCK_INITIALIZER }
+#else
+#error "Unknown threading library"
 #endif
 
 /* CRYPTO_MUTEX_init initialises |lock|. If |lock| is a static variable, use a
@@ -400,16 +391,18 @@
 OPENSSL_EXPORT void CRYPTO_MUTEX_init(CRYPTO_MUTEX *lock);
 
 /* CRYPTO_MUTEX_lock_read locks |lock| such that other threads may also have a
- * read lock, but none may have a write lock. (On Windows, read locks are
- * actually fully exclusive.) */
+ * read lock, but none may have a write lock. */
 OPENSSL_EXPORT void CRYPTO_MUTEX_lock_read(CRYPTO_MUTEX *lock);
 
 /* CRYPTO_MUTEX_lock_write locks |lock| such that no other thread has any type
  * of lock on it. */
 OPENSSL_EXPORT void CRYPTO_MUTEX_lock_write(CRYPTO_MUTEX *lock);
 
-/* CRYPTO_MUTEX_unlock unlocks |lock|. */
-OPENSSL_EXPORT void CRYPTO_MUTEX_unlock(CRYPTO_MUTEX *lock);
+/* CRYPTO_MUTEX_unlock_read unlocks |lock| for reading. */
+OPENSSL_EXPORT void CRYPTO_MUTEX_unlock_read(CRYPTO_MUTEX *lock);
+
+/* CRYPTO_MUTEX_unlock_write unlocks |lock| for writing. */
+OPENSSL_EXPORT void CRYPTO_MUTEX_unlock_write(CRYPTO_MUTEX *lock);
 
 /* CRYPTO_MUTEX_cleanup releases all resources held by |lock|. */
 OPENSSL_EXPORT void CRYPTO_MUTEX_cleanup(CRYPTO_MUTEX *lock);
@@ -428,8 +421,12 @@
 OPENSSL_EXPORT void CRYPTO_STATIC_MUTEX_lock_write(
     struct CRYPTO_STATIC_MUTEX *lock);
 
-/* CRYPTO_STATIC_MUTEX_unlock unlocks |lock|. */
-OPENSSL_EXPORT void CRYPTO_STATIC_MUTEX_unlock(
+/* CRYPTO_STATIC_MUTEX_unlock_read unlocks |lock| for reading. */
+OPENSSL_EXPORT void CRYPTO_STATIC_MUTEX_unlock_read(
+    struct CRYPTO_STATIC_MUTEX *lock);
+
+/* CRYPTO_STATIC_MUTEX_unlock_write unlocks |lock| for writing. */
+OPENSSL_EXPORT void CRYPTO_STATIC_MUTEX_unlock_write(
     struct CRYPTO_STATIC_MUTEX *lock);
 
 
@@ -525,6 +522,85 @@
                                         void *obj, CRYPTO_EX_DATA *ad);
 
 
+/* Language bug workarounds.
+ *
+ * Most C standard library functions are undefined if passed NULL, even when the
+ * corresponding length is zero. This gives them (and, in turn, all functions
+ * which call them) surprising behavior on empty arrays. Some compilers will
+ * miscompile code due to this rule. See also
+ * https://www.imperialviolet.org/2016/06/26/nonnull.html
+ *
+ * These wrapper functions behave the same as the corresponding C standard
+ * functions, but behave as expected when passed NULL if the length is zero.
+ *
+ * Note |OPENSSL_memcmp| is a different function from |CRYPTO_memcmp|. */
+
+/* C++ defines |memchr| as a const-correct overload. */
+#if defined(__cplusplus)
+extern "C++" {
+
+static inline const void *OPENSSL_memchr(const void *s, int c, size_t n) {
+  if (n == 0) {
+    return NULL;
+  }
+
+  return memchr(s, c, n);
+}
+
+static inline void *OPENSSL_memchr(void *s, int c, size_t n) {
+  if (n == 0) {
+    return NULL;
+  }
+
+  return memchr(s, c, n);
+}
+
+}  /* extern "C++" */
+#else  /* __cplusplus */
+
+static inline void *OPENSSL_memchr(const void *s, int c, size_t n) {
+  if (n == 0) {
+    return NULL;
+  }
+
+  return memchr(s, c, n);
+}
+
+#endif  /* __cplusplus */
+
+static inline int OPENSSL_memcmp(const void *s1, const void *s2, size_t n) {
+  if (n == 0) {
+    return 0;
+  }
+
+  return memcmp(s1, s2, n);
+}
+
+static inline void *OPENSSL_memcpy(void *dst, const void *src, size_t n) {
+  if (n == 0) {
+    return dst;
+  }
+
+  return memcpy(dst, src, n);
+}
+
+static inline void *OPENSSL_memmove(void *dst, const void *src, size_t n) {
+  if (n == 0) {
+    return dst;
+  }
+
+  return memmove(dst, src, n);
+}
+
+static inline void *OPENSSL_memset(void *dst, int c, size_t n) {
+  if (n == 0) {
+    return dst;
+  }
+
+  return memset(dst, c, n);
+}
+
+
 #if defined(__cplusplus)
 }  /* extern C */
 #endif
diff --git a/src/crypto/lhash/CMakeLists.txt b/src/crypto/lhash/CMakeLists.txt
index 4f4dea7..bd6005b 100644
--- a/src/crypto/lhash/CMakeLists.txt
+++ b/src/crypto/lhash/CMakeLists.txt
@@ -11,7 +11,7 @@
 add_executable(
   lhash_test
 
-  lhash_test.c
+  lhash_test.cc
 
   $<TARGET_OBJECTS:test_support>
 )
diff --git a/src/crypto/lhash/lhash.c b/src/crypto/lhash/lhash.c
index 257900e..27960d9 100644
--- a/src/crypto/lhash/lhash.c
+++ b/src/crypto/lhash/lhash.c
@@ -62,6 +62,9 @@
 
 #include <openssl/mem.h>
 
+#include "../internal.h"
+
+
 /* kMinNumBuckets is the minimum size of the buckets array in an |_LHASH|. */
 static const size_t kMinNumBuckets = 16;
 
@@ -71,13 +74,11 @@
 static const size_t kMinAverageChainLength = 1;
 
 _LHASH *lh_new(lhash_hash_func hash, lhash_cmp_func comp) {
-  _LHASH *ret;
-
-  ret = OPENSSL_malloc(sizeof(_LHASH));
+  _LHASH *ret = OPENSSL_malloc(sizeof(_LHASH));
   if (ret == NULL) {
     return NULL;
   }
-  memset(ret, 0, sizeof(_LHASH));
+  OPENSSL_memset(ret, 0, sizeof(_LHASH));
 
   ret->num_buckets = kMinNumBuckets;
   ret->buckets = OPENSSL_malloc(sizeof(LHASH_ITEM *) * ret->num_buckets);
@@ -85,30 +86,21 @@
     OPENSSL_free(ret);
     return NULL;
   }
-  memset(ret->buckets, 0, sizeof(LHASH_ITEM *) * ret->num_buckets);
+  OPENSSL_memset(ret->buckets, 0, sizeof(LHASH_ITEM *) * ret->num_buckets);
 
   ret->comp = comp;
-  if (ret->comp == NULL) {
-    ret->comp = (lhash_cmp_func) strcmp;
-  }
   ret->hash = hash;
-  if (ret->hash == NULL) {
-    ret->hash = (lhash_hash_func) lh_strhash;
-  }
-
   return ret;
 }
 
 void lh_free(_LHASH *lh) {
-  size_t i;
-  LHASH_ITEM *n, *next;
-
   if (lh == NULL) {
     return;
   }
 
-  for (i = 0; i < lh->num_buckets; i++) {
-    for (n = lh->buckets[i]; n != NULL; n = next) {
+  for (size_t i = 0; i < lh->num_buckets; i++) {
+    LHASH_ITEM *next;
+    for (LHASH_ITEM *n = lh->buckets[i]; n != NULL; n = next) {
       next = n->next;
       OPENSSL_free(n);
     }
@@ -175,7 +167,7 @@
   if (new_buckets == NULL) {
     return;
   }
-  memset(new_buckets, 0, alloc_size);
+  OPENSSL_memset(new_buckets, 0, alloc_size);
 
   for (i = 0; i < lh->num_buckets; i++) {
     for (cur = lh->buckets[i]; cur != NULL; cur = next) {
@@ -277,9 +269,6 @@
 
 static void lh_doall_internal(_LHASH *lh, void (*no_arg_func)(void *),
                               void (*arg_func)(void *, void *), void *arg) {
-  size_t i;
-  LHASH_ITEM *cur, *next;
-
   if (lh == NULL) {
     return;
   }
@@ -289,8 +278,9 @@
     lh->callback_depth++;
   }
 
-  for (i = 0; i < lh->num_buckets; i++) {
-    for (cur = lh->buckets[i]; cur != NULL; cur = next) {
+  for (size_t i = 0; i < lh->num_buckets; i++) {
+    LHASH_ITEM *next;
+    for (LHASH_ITEM *cur = lh->buckets[i]; cur != NULL; cur = next) {
       next = cur->next;
       if (arg_func) {
         arg_func(cur->data, arg);
diff --git a/src/crypto/lhash/lhash_test.c b/src/crypto/lhash/lhash_test.c
deleted file mode 100644
index 63748e7..0000000
--- a/src/crypto/lhash/lhash_test.c
+++ /dev/null
@@ -1,199 +0,0 @@
-/* Copyright (c) 2014, Google Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
-
-#if !defined(_POSIX_C_SOURCE)
-#define _POSIX_C_SOURCE 201410L
-#endif
-
-#include <openssl/crypto.h>
-#include <openssl/lhash.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-struct dummy_lhash_node {
-  char *s;
-  struct dummy_lhash_node *next;
-};
-
-struct dummy_lhash {
-  struct dummy_lhash_node *head;
-};
-
-static void dummy_lh_free(struct dummy_lhash *lh) {
-  struct dummy_lhash_node *cur, *next;
-
-  for (cur = lh->head; cur != NULL; cur = next) {
-    next = cur->next;
-    free(cur->s);
-    free(cur);
-  }
-}
-
-static size_t dummy_lh_num_items(const struct dummy_lhash *lh) {
-  size_t count = 0;
-  struct dummy_lhash_node *cur;
-
-  for (cur = lh->head; cur != NULL; cur = cur->next) {
-    count++;
-  }
-
-  return count;
-}
-
-static char *dummy_lh_retrieve(struct dummy_lhash *lh, const char *s) {
-  struct dummy_lhash_node *cur;
-
-  for (cur = lh->head; cur != NULL; cur = cur->next) {
-    if (strcmp(cur->s, s) == 0) {
-      return cur->s;
-    }
-  }
-
-  return NULL;
-}
-
-static int dummy_lh_insert(struct dummy_lhash *lh, char **old_data, char *s) {
-  struct dummy_lhash_node *node, *cur;
-
-  for (cur = lh->head; cur != NULL; cur = cur->next) {
-    if (strcmp(cur->s, s) == 0) {
-      *old_data = cur->s;
-      cur->s = s;
-      return 1;
-    }
-  }
-
-  node = malloc(sizeof(struct dummy_lhash_node));
-  *old_data = NULL;
-  node->s = s;
-  node->next = lh->head;
-  lh->head = node;
-  return 1;
-}
-
-static char *dummy_lh_delete(struct dummy_lhash *lh, const void *s) {
-  struct dummy_lhash_node *cur, **next_ptr;
-  char *ret;
-
-  next_ptr = &lh->head;
-  for (cur = lh->head; cur != NULL; cur = cur->next) {
-    if (strcmp(cur->s, s) == 0) {
-      ret = cur->s;
-      *next_ptr = cur->next;
-      free(cur);
-      return ret;
-    }
-    next_ptr = &cur->next;
-  }
-
-  return NULL;
-}
-
-static char *rand_string(void) {
-  unsigned len = 1 + (rand() % 3);
-  char *ret = malloc(len + 1);
-  unsigned i;
-
-  for (i = 0; i < len; i++) {
-    ret[i] = '0' + (rand() & 7);
-  }
-  ret[i] = 0;
-
-  return ret;
-}
-
-int main(int argc, char **argv) {
-  _LHASH *lh;
-  struct dummy_lhash dummy_lh = {NULL};
-  unsigned i;
-
-  CRYPTO_library_init();
-
-  lh = lh_new(NULL, NULL);
-  if (lh == NULL) {
-    return 1;
-  }
-
-  for (i = 0; i < 100000; i++) {
-    unsigned action;
-    char *s, *s1, *s2;
-
-    if (dummy_lh_num_items(&dummy_lh) != lh_num_items(lh)) {
-      fprintf(stderr, "Length mismatch\n");
-      return 1;
-    }
-
-    action = rand() % 3;
-    switch (action) {
-      case 0:
-        s = rand_string();
-        s1 = (char *)lh_retrieve(lh, s);
-        s2 = dummy_lh_retrieve(&dummy_lh, s);
-        if (s1 != NULL && (s2 == NULL || strcmp(s1, s2) != 0)) {
-          fprintf(stderr, "lh_retrieve failure\n");
-          abort();
-        }
-        free(s);
-        break;
-
-      case 1:
-        s = rand_string();
-        lh_insert(lh, (void **)&s1, s);
-        dummy_lh_insert(&dummy_lh, &s2, strdup(s));
-
-        if (s1 != NULL && (s2 == NULL || strcmp(s1, s2) != 0)) {
-          fprintf(stderr, "lh_insert failure\n");
-          abort();
-        }
-
-        if (s1) {
-          free(s1);
-        }
-        if (s2) {
-          free(s2);
-        }
-        break;
-
-      case 2:
-        s = rand_string();
-        s1 = lh_delete(lh, s);
-        s2 = dummy_lh_delete(&dummy_lh, s);
-
-        if (s1 != NULL && (s2 == NULL || strcmp(s1, s2) != 0)) {
-          fprintf(stderr, "lh_insert failure\n");
-          abort();
-        }
-
-        if (s1) {
-          free(s1);
-        }
-        if (s2) {
-          free(s2);
-        }
-        free(s);
-        break;
-
-      default:
-        abort();
-    }
-  }
-
-  lh_doall(lh, free);
-  lh_free(lh);
-  dummy_lh_free(&dummy_lh);
-  printf("PASS\n");
-  return 0;
-}
diff --git a/src/crypto/lhash/lhash_test.cc b/src/crypto/lhash/lhash_test.cc
new file mode 100644
index 0000000..cbeb15b
--- /dev/null
+++ b/src/crypto/lhash/lhash_test.cc
@@ -0,0 +1,161 @@
+/* Copyright (c) 2014, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#if !defined(_POSIX_C_SOURCE)
+#define _POSIX_C_SOURCE 201410L
+#endif
+
+#include <openssl/crypto.h>
+#include <openssl/lhash.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <algorithm>
+#include <memory>
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+
+static std::unique_ptr<char[]> RandString(void) {
+  unsigned len = 1 + (rand() % 3);
+  std::unique_ptr<char[]> ret(new char[len + 1]);
+
+  for (unsigned i = 0; i < len; i++) {
+    ret[i] = '0' + (rand() & 7);
+  }
+  ret[len] = 0;
+
+  return ret;
+}
+
+struct FreeLHASH {
+  void operator()(_LHASH *lh) { lh_free(lh); }
+};
+
+static const char *Lookup(
+    std::map<std::string, std::unique_ptr<char[]>> *dummy_lh, const char *key) {
+  // Using operator[] implicitly inserts into the map.
+  auto iter = dummy_lh->find(key);
+  if (iter == dummy_lh->end()) {
+    return nullptr;
+  }
+  return iter->second.get();
+}
+
+int main(int argc, char **argv) {
+  CRYPTO_library_init();
+
+  std::unique_ptr<_LHASH, FreeLHASH> lh(
+      lh_new((lhash_hash_func)lh_strhash, (lhash_cmp_func)strcmp));
+  if (!lh) {
+    return 1;
+  }
+
+  // lh is expected to store a canonical instance of each string. dummy_lh
+  // mirrors what it stores for comparison. It also manages ownership of the
+  // pointers.
+  std::map<std::string, std::unique_ptr<char[]>> dummy_lh;
+
+  for (unsigned i = 0; i < 100000; i++) {
+    if (dummy_lh.size() != lh_num_items(lh.get())) {
+      fprintf(stderr, "Length mismatch\n");
+      return 1;
+    }
+
+    // Check the entire contents and test |lh_doall_arg|. This takes O(N) time,
+    // so only do it every few iterations.
+    //
+    // TODO(davidben): |lh_doall_arg| also supports modifying the hash in the
+    // callback. Test this.
+    if (i % 1000 == 0) {
+      using ValueList = std::vector<const char *>;
+      ValueList expected, actual;
+      for (const auto &pair : dummy_lh) {
+        expected.push_back(pair.second.get());
+      }
+      std::sort(expected.begin(), expected.end());
+
+      lh_doall_arg(lh.get(),
+                   [](void *ptr, void *arg) {
+                     ValueList *out = reinterpret_cast<ValueList *>(arg);
+                     out->push_back(reinterpret_cast<char *>(ptr));
+                   },
+                   &actual);
+      std::sort(actual.begin(), actual.end());
+
+      if (expected != actual) {
+        fprintf(stderr, "Contents mismatch\n");
+        return 1;
+      }
+    }
+
+    enum Action {
+      kRetrieve = 0,
+      kInsert,
+      kDelete,
+    };
+
+    Action action = static_cast<Action>(rand() % 3);
+    switch (action) {
+      case kRetrieve: {
+        std::unique_ptr<char[]> key = RandString();
+        void *value = lh_retrieve(lh.get(), key.get());
+        if (value != Lookup(&dummy_lh, key.get())) {
+          fprintf(stderr, "lh_retrieve failure\n");
+          return 1;
+        }
+        break;
+      }
+
+      case kInsert: {
+        std::unique_ptr<char[]> key = RandString();
+        void *previous;
+        if (!lh_insert(lh.get(), &previous, key.get())) {
+          return 1;
+        }
+
+        if (previous != Lookup(&dummy_lh, key.get())) {
+          fprintf(stderr, "lh_insert failure\n");
+          return 1;
+        }
+
+        dummy_lh[key.get()] = std::move(key);
+        break;
+      }
+
+      case kDelete: {
+        std::unique_ptr<char[]> key = RandString();
+        void *value = lh_delete(lh.get(), key.get());
+
+        if (value != Lookup(&dummy_lh, key.get())) {
+          fprintf(stderr, "lh_delete failure\n");
+          return 1;
+        }
+
+        dummy_lh.erase(key.get());
+        break;
+      }
+
+      default:
+        abort();
+    }
+  }
+
+  printf("PASS\n");
+  return 0;
+}
diff --git a/src/crypto/md4/md4.c b/src/crypto/md4/md4.c
index 86a540b..0046c21 100644
--- a/src/crypto/md4/md4.c
+++ b/src/crypto/md4/md4.c
@@ -59,11 +59,22 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "../internal.h"
+
+
+uint8_t *MD4(const uint8_t *data, size_t len, uint8_t *out) {
+  MD4_CTX ctx;
+  MD4_Init(&ctx);
+  MD4_Update(&ctx, data, len);
+  MD4_Final(out, &ctx);
+
+  return out;
+}
 
 /* Implemented from RFC1186 The MD4 Message-Digest Algorithm. */
 
 int MD4_Init(MD4_CTX *md4) {
-  memset(md4, 0, sizeof(MD4_CTX));
+  OPENSSL_memset(md4, 0, sizeof(MD4_CTX));
   md4->h[0] = 0x67452301UL;
   md4->h[1] = 0xefcdab89UL;
   md4->h[2] = 0x98badcfeUL;
@@ -105,23 +116,23 @@
 
 #define ROTATE(a, n) (((a) << (n)) | ((a) >> (32 - (n))))
 
-#define R0(a, b, c, d, k, s, t)        \
-  {                                    \
-    a += ((k) + (t)+F((b), (c), (d))); \
-    a = ROTATE(a, s);                  \
-  };
+#define R0(a, b, c, d, k, s, t)            \
+  do {                                     \
+    (a) += ((k) + (t) + F((b), (c), (d))); \
+    (a) = ROTATE(a, s);                    \
+  } while (0)
 
-#define R1(a, b, c, d, k, s, t)        \
-  {                                    \
-    a += ((k) + (t)+G((b), (c), (d))); \
-    a = ROTATE(a, s);                  \
-  };
+#define R1(a, b, c, d, k, s, t)            \
+  do {                                     \
+    (a) += ((k) + (t) + G((b), (c), (d))); \
+    (a) = ROTATE(a, s);                    \
+  } while (0)
 
-#define R2(a, b, c, d, k, s, t)        \
-  {                                    \
-    a += ((k) + (t)+H((b), (c), (d))); \
-    a = ROTATE(a, s);                  \
-  };
+#define R2(a, b, c, d, k, s, t)            \
+  do {                                     \
+    (a) += ((k) + (t) + H((b), (c), (d))); \
+    (a) = ROTATE(a, s);                    \
+  } while (0)
 
 void md4_block_data_order(uint32_t *state, const uint8_t *data, size_t num) {
   uint32_t A, B, C, D, l;
diff --git a/src/crypto/md5/asm/md5-586.pl b/src/crypto/md5/asm/md5-586.pl
index 6cb66bb..a032d9b 100644
--- a/src/crypto/md5/asm/md5-586.pl
+++ b/src/crypto/md5/asm/md5-586.pl
@@ -11,6 +11,9 @@
 push(@INC,"${dir}","${dir}../../perlasm");
 require "x86asm.pl";
 
+$output=pop;
+open STDOUT,">$output";
+
 &asm_init($ARGV[0],$0);
 
 $A="eax";
@@ -33,6 +36,8 @@
 &md5_block("md5_block_asm_data_order");
 &asm_finish();
 
+close STDOUT;
+
 sub Np
 	{
 	local($p)=@_;
@@ -45,7 +50,7 @@
 	local($pos,$a,$b,$c,$d,$K,$ki,$s,$t)=@_;
 
 	&mov($tmp1,$C)  if $pos < 0;
-	&mov($tmp2,&DWP($xo[$ki]*4,$K,"",0)) if $pos < 0; # very first one 
+	&mov($tmp2,&DWP($xo[$ki]*4,$K,"",0)) if $pos < 0; # very first one
 
 	# body proper
 
diff --git a/src/crypto/md5/asm/md5-x86_64.pl b/src/crypto/md5/asm/md5-x86_64.pl
index 77a6e01..5ba0c62 100644
--- a/src/crypto/md5/asm/md5-x86_64.pl
+++ b/src/crypto/md5/asm/md5-x86_64.pl
@@ -110,7 +110,7 @@
 
 no warnings qw(uninitialized);
 my $flavour = shift;
-my $output  = shift || "";
+my $output  = shift;
 if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
 
 my $win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
@@ -120,7 +120,7 @@
 ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
 die "can't locate x86_64-xlate.pl";
 
-open OUT,"| \"$^X\" $xlate $flavour $output";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
 *STDOUT=*OUT;
 
 $code .= <<EOF;
diff --git a/src/crypto/md5/md5.c b/src/crypto/md5/md5.c
index 66483b8..7712f47 100644
--- a/src/crypto/md5/md5.c
+++ b/src/crypto/md5/md5.c
@@ -60,6 +60,8 @@
 
 #include <openssl/mem.h>
 
+#include "../internal.h"
+
 
 uint8_t *MD5(const uint8_t *data, size_t len, uint8_t *out) {
   MD5_CTX ctx;
@@ -78,7 +80,7 @@
 }
 
 int MD5_Init(MD5_CTX *md5) {
-  memset(md5, 0, sizeof(MD5_CTX));
+  OPENSSL_memset(md5, 0, sizeof(MD5_CTX));
   md5->h[0] = 0x67452301UL;
   md5->h[1] = 0xefcdab89UL;
   md5->h[2] = 0x98badcfeUL;
@@ -122,32 +124,40 @@
  * simplified to the code below.  Wei attributes these optimizations
  * to Peter Gutmann's SHS code, and he attributes it to Rich Schroeppel.
  */
-#define	F(b,c,d)	((((c) ^ (d)) & (b)) ^ (d))
-#define	G(b,c,d)	((((b) ^ (c)) & (d)) ^ (c))
-#define	H(b,c,d)	((b) ^ (c) ^ (d))
-#define	I(b,c,d)	(((~(d)) | (b)) ^ (c))
+#define F(b, c, d) ((((c) ^ (d)) & (b)) ^ (d))
+#define G(b, c, d) ((((b) ^ (c)) & (d)) ^ (c))
+#define H(b, c, d) ((b) ^ (c) ^ (d))
+#define I(b, c, d) (((~(d)) | (b)) ^ (c))
 
 #define ROTATE(a, n) (((a) << (n)) | ((a) >> (32 - (n))))
 
-#define R0(a,b,c,d,k,s,t) { \
-	a+=((k)+(t)+F((b),(c),(d))); \
-	a=ROTATE(a,s); \
-	a+=b; };\
+#define R0(a, b, c, d, k, s, t)            \
+  do {                                     \
+    (a) += ((k) + (t) + F((b), (c), (d))); \
+    (a) = ROTATE(a, s);                    \
+    (a) += (b);                            \
+  } while (0)
 
-#define R1(a,b,c,d,k,s,t) { \
-	a+=((k)+(t)+G((b),(c),(d))); \
-	a=ROTATE(a,s); \
-	a+=b; };
+#define R1(a, b, c, d, k, s, t)            \
+  do {                                     \
+    (a) += ((k) + (t) + G((b), (c), (d))); \
+    (a) = ROTATE(a, s);                    \
+    (a) += (b);                            \
+  } while (0)
 
-#define R2(a,b,c,d,k,s,t) { \
-	a+=((k)+(t)+H((b),(c),(d))); \
-	a=ROTATE(a,s); \
-	a+=b; };
+#define R2(a, b, c, d, k, s, t)            \
+  do {                                     \
+    (a) += ((k) + (t) + H((b), (c), (d))); \
+    (a) = ROTATE(a, s);                    \
+    (a) += (b);                            \
+  } while (0)
 
-#define R3(a,b,c,d,k,s,t) { \
-	a+=((k)+(t)+I((b),(c),(d))); \
-	a=ROTATE(a,s); \
-	a+=b; };
+#define R3(a, b, c, d, k, s, t)            \
+  do {                                     \
+    (a) += ((k) + (t) + I((b), (c), (d))); \
+    (a) = ROTATE(a, s);                    \
+    (a) += (b);                            \
+  } while (0)
 
 #ifndef md5_block_data_order
 #ifdef X
diff --git a/src/crypto/mem.c b/src/crypto/mem.c
index edd14a8..390ca2e 100644
--- a/src/crypto/mem.c
+++ b/src/crypto/mem.c
@@ -66,17 +66,17 @@
 #include <string.h>
 
 #if defined(OPENSSL_WINDOWS)
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <windows.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
 #else
 #include <strings.h>
 #endif
 
+#include "internal.h"
+
 
 void *OPENSSL_realloc_clean(void *ptr, size_t old_size, size_t new_size) {
-  void *ret = NULL;
-
   if (ptr == NULL) {
     return OPENSSL_malloc(new_size);
   }
@@ -91,12 +91,12 @@
     return NULL;
   }
 
-  ret = OPENSSL_malloc(new_size);
+  void *ret = OPENSSL_malloc(new_size);
   if (ret == NULL) {
     return NULL;
   }
 
-  memcpy(ret, ptr, old_size);
+  OPENSSL_memcpy(ret, ptr, old_size);
   OPENSSL_cleanse(ptr, old_size);
   OPENSSL_free(ptr);
   return ret;
@@ -104,9 +104,9 @@
 
 void OPENSSL_cleanse(void *ptr, size_t len) {
 #if defined(OPENSSL_WINDOWS)
-	SecureZeroMemory(ptr, len);
+  SecureZeroMemory(ptr, len);
 #else
-	memset(ptr, 0, len);
+  OPENSSL_memset(ptr, 0, len);
 
 #if !defined(OPENSSL_NO_ASM)
   /* As best as we can tell, this is sufficient to break any optimisations that
@@ -118,12 +118,11 @@
 }
 
 int CRYPTO_memcmp(const void *in_a, const void *in_b, size_t len) {
-  size_t i;
   const uint8_t *a = in_a;
   const uint8_t *b = in_b;
   uint8_t x = 0;
 
-  for (i = 0; i < len; i++) {
+  for (size_t i = 0; i < len; i++) {
     x |= a[i] ^ b[i];
   }
 
@@ -136,10 +135,9 @@
   static const uint32_t kOffsetBasis = 2166136261u;
 
   const uint8_t *in = ptr;
-  size_t i;
   uint32_t h = kOffsetBasis;
 
-  for (i = 0; i < len; i++) {
+  for (size_t i = 0; i < len; i++) {
     h ^= in[i];
     h *= kPrime;
   }
@@ -147,12 +145,8 @@
   return h;
 }
 
-char *OPENSSL_strdup(const char *s) { return strdup(s); }
-
 size_t OPENSSL_strnlen(const char *s, size_t len) {
-  size_t i;
-
-  for (i = 0; i < len; i++) {
+  for (size_t i = 0; i < len; i++) {
     if (s[i] == 0) {
       return i;
     }
@@ -163,6 +157,8 @@
 
 #if defined(OPENSSL_WINDOWS)
 
+char *OPENSSL_strdup(const char *s) { return _strdup(s); }
+
 int OPENSSL_strcasecmp(const char *a, const char *b) {
   return _stricmp(a, b);
 }
@@ -173,6 +169,8 @@
 
 #else
 
+char *OPENSSL_strdup(const char *s) { return strdup(s); }
+
 int OPENSSL_strcasecmp(const char *a, const char *b) {
   return strcasecmp(a, b);
 }
@@ -185,12 +183,8 @@
 
 int BIO_snprintf(char *buf, size_t n, const char *format, ...) {
   va_list args;
-  int ret;
-
   va_start(args, format);
-
-  ret = BIO_vsnprintf(buf, n, format, args);
-
+  int ret = BIO_vsnprintf(buf, n, format, args);
   va_end(args);
   return ret;
 }
diff --git a/src/crypto/modes/CMakeLists.txt b/src/crypto/modes/CMakeLists.txt
index 41f71d7..dc9e504 100644
--- a/src/crypto/modes/CMakeLists.txt
+++ b/src/crypto/modes/CMakeLists.txt
@@ -34,16 +34,25 @@
   )
 endif()
 
+if (${ARCH} STREQUAL "ppc64le")
+  set(
+    MODES_ARCH_SOURCES
+
+    ghashp8-ppc.${ASM_EXT}
+  )
+endif()
+
 add_library(
   modes
 
   OBJECT
 
   cbc.c
-  ctr.c
-  ofb.c
   cfb.c
+  ctr.c
   gcm.c
+  ofb.c
+  polyval.c
 
   ${MODES_ARCH_SOURCES}
 )
@@ -53,11 +62,12 @@
 perlasm(ghash-x86.${ASM_EXT} asm/ghash-x86.pl)
 perlasm(ghash-armv4.${ASM_EXT} asm/ghash-armv4.pl)
 perlasm(ghashv8-armx.${ASM_EXT} asm/ghashv8-armx.pl)
+perlasm(ghashp8-ppc.${ASM_EXT} asm/ghashp8-ppc.pl)
 
 add_executable(
   gcm_test
 
-  gcm_test.c
+  gcm_test.cc
 
   $<TARGET_OBJECTS:test_support>
 )
diff --git a/src/crypto/modes/asm/aesni-gcm-x86_64.pl b/src/crypto/modes/asm/aesni-gcm-x86_64.pl
index 0ca89c7..139014f 100644
--- a/src/crypto/modes/asm/aesni-gcm-x86_64.pl
+++ b/src/crypto/modes/asm/aesni-gcm-x86_64.pl
@@ -22,10 +22,11 @@
 # [1] and [2], with MOVBE twist suggested by Ilya Albrekht and Max
 # Locktyukhin of Intel Corp. who verified that it reduces shuffles
 # pressure with notable relative improvement, achieving 1.0 cycle per
-# byte processed with 128-bit key on Haswell processor, and 0.74 -
-# on Broadwell. [Mentioned results are raw profiled measurements for
-# favourable packet size, one divisible by 96. Applications using the
-# EVP interface will observe a few percent worse performance.]
+# byte processed with 128-bit key on Haswell processor, 0.74 - on
+# Broadwell, 0.63 - on Skylake... [Mentioned results are raw profiled
+# measurements for favourable packet size, one divisible by 96.
+# Applications using the EVP interface will observe a few percent
+# worse performance.]
 #
 # [1] http://rt.openssl.org/Ticket/Display.html?id=2900&user=guest&pass=guest
 # [2] http://www.intel.com/content/dam/www/public/us/en/documents/software-support/enabling-high-performance-gcm.pdf
@@ -41,16 +42,24 @@
 ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
 die "can't locate x86_64-xlate.pl";
 
+# |$avx| in ghash-x86_64.pl must be set to at least 1; otherwise tags will
+# be computed incorrectly.
+#
 # In upstream, this is controlled by shelling out to the compiler to check
 # versions, but BoringSSL is intended to be used with pre-generated perlasm
 # output, so this isn't useful anyway.
 #
-# TODO(davidben): Enable this after testing. $avx goes up to 2.
-$avx = 0;
+# The upstream code uses the condition |$avx>1| even though no AVX2
+# instructions are used, because it assumes MOVBE is supported by the assembler
+# if and only if AVX2 is also supported by the assembler; see
+# https://marc.info/?l=openssl-dev&m=146567589526984&w=2.
+$avx = 2;
 
-open OUT,"| \"$^X\" $xlate $flavour $output";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
 *STDOUT=*OUT;
 
+# See the comment above regarding why the condition is ($avx>1) when there are
+# no AVX2 instructions being used.
 if ($avx>1) {{{
 
 ($inp,$out,$len,$key,$ivp,$Xip)=("%rdi","%rsi","%rdx","%rcx","%r8","%r9");
@@ -96,6 +105,23 @@
 	  vpxor		$rndkey,$inout3,$inout3
 	  vmovups	0x10-0x80($key),$T2	# borrow $T2 for $rndkey
 	vpclmulqdq	\$0x01,$Hkey,$Z3,$Z2
+
+	# At this point, the current block of 96 (0x60) bytes has already been
+	# loaded into registers. Concurrently with processing it, we want to
+	# load the next 96 bytes of input for the next round. Obviously, we can
+	# only do this if there are at least 96 more bytes of input beyond the
+	# input we're currently processing, or else we'd read past the end of
+	# the input buffer. Here, we set |%r12| to 96 if there are at least 96
+	# bytes of input beyond the 96 bytes we're already processing, and we
+	# set |%r12| to 0 otherwise. In the case where we set |%r12| to 96,
+	# we'll read in the next block so that it is in registers for the next
+	# loop iteration. In the case where we set |%r12| to 0, we'll re-read
+	# the current block and then ignore what we re-read.
+	#
+	# At this point, |$in0| points to the current (already read into
+	# registers) block, and |$end0| points to 2*96 bytes before the end of
+	# the input. Thus, |$in0| > |$end0| means that we do not have the next
+	# 96-byte block to read in, and |$in0| <= |$end0| means we do.
 	xor		%r12,%r12
 	cmp		$in0,$end0
 
@@ -388,6 +414,9 @@
 .align	32
 aesni_gcm_decrypt:
 	xor	$ret,$ret
+
+	# We call |_aesni_ctr32_ghash_6x|, which requires at least 96 (0x60)
+	# bytes of input.
 	cmp	\$0x60,$len			# minimal accepted length
 	jb	.Lgcm_dec_abort
 
@@ -442,7 +471,15 @@
 	vmovdqu		0x50($inp),$Z3		# I[5]
 	lea		($inp),$in0
 	vmovdqu		0x40($inp),$Z0
+
+	# |_aesni_ctr32_ghash_6x| requires |$end0| to point to 2*96 (0xc0)
+	# bytes before the end of the input. Note, in particular, that this is
+	# correct even if |$len| is not an even multiple of 96 or 16. XXX: This
+	# seems to require that |$inp| + |$len| >= 2*96 (0xc0); i.e. |$inp| must
+	# not be near the very beginning of the address space when |$len| < 2*96
+	# (0xc0).
 	lea		-0xc0($inp,$len),$end0
+
 	vmovdqu		0x30($inp),$Z1
 	shr		\$4,$len
 	xor		$ret,$ret
@@ -477,7 +514,7 @@
 ___
 $code.=<<___ if ($win64);
 	movaps	-0xd8(%rax),%xmm6
-	movaps	-0xd8(%rax),%xmm7
+	movaps	-0xc8(%rax),%xmm7
 	movaps	-0xb8(%rax),%xmm8
 	movaps	-0xa8(%rax),%xmm9
 	movaps	-0x98(%rax),%xmm10
@@ -598,6 +635,10 @@
 .align	32
 aesni_gcm_encrypt:
 	xor	$ret,$ret
+
+	# We call |_aesni_ctr32_6x| twice, each call consuming 96 bytes of
+	# input. Then we call |_aesni_ctr32_ghash_6x|, which requires at
+	# least 96 more bytes of input.
 	cmp	\$0x60*3,$len			# minimal accepted length
 	jb	.Lgcm_enc_abort
 
@@ -647,7 +688,16 @@
 .Lenc_no_key_aliasing:
 
 	lea		($out),$in0
+
+	# |_aesni_ctr32_ghash_6x| requires |$end0| to point to 2*96 (0xc0)
+	# bytes before the end of the input. Note, in particular, that this is
+	# correct even if |$len| is not an even multiple of 96 or 16. Unlike in
+	# the decryption case, there's no caveat that |$out| must not be near
+	# the very beginning of the address space, because we know that
+	# |$len| >= 3*96 from the check above, and so we know
+	# |$out| + |$len| >= 2*96 (0xc0).
 	lea		-0xc0($out,$len),$end0
+
 	shr		\$4,$len
 
 	call		_aesni_ctr32_6x
diff --git a/src/crypto/modes/asm/ghash-armv4.pl b/src/crypto/modes/asm/ghash-armv4.pl
index d328822..1a03251 100644
--- a/src/crypto/modes/asm/ghash-armv4.pl
+++ b/src/crypto/modes/asm/ghash-armv4.pl
@@ -47,7 +47,7 @@
 #
 # Câmara, D.; Gouvêa, C. P. L.; López, J. & Dahab, R.: Fast Software
 # Polynomial Multiplication on ARM Processors using the NEON Engine.
-# 
+#
 # http://conradoplg.cryptoland.net/files/2010/12/mocrysen13.pdf
 
 # ====================================================================
@@ -72,8 +72,8 @@
 # example...
 
 $flavour = shift;
-if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
-else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} }
+if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
+else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} }
 
 if ($flavour && $flavour ne "void") {
     $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
@@ -163,7 +163,6 @@
 .size	rem_4bit_get,.-rem_4bit_get
 
 .global	gcm_ghash_4bit
-.hidden	gcm_ghash_4bit
 .type	gcm_ghash_4bit,%function
 gcm_ghash_4bit:
 	sub	r12,pc,#8
@@ -260,7 +259,6 @@
 .size	gcm_ghash_4bit,.-gcm_ghash_4bit
 
 .global	gcm_gmult_4bit
-.hidden	gcm_gmult_4bit
 .type	gcm_gmult_4bit,%function
 gcm_gmult_4bit:
 	stmdb	sp!,{r4-r11,lr}
@@ -391,7 +389,6 @@
 .fpu	neon
 
 .global	gcm_init_neon
-.hidden	gcm_init_neon
 .type	gcm_init_neon,%function
 .align	4
 gcm_init_neon:
@@ -413,7 +410,6 @@
 .size	gcm_init_neon,.-gcm_init_neon
 
 .global	gcm_gmult_neon
-.hidden	gcm_gmult_neon
 .type	gcm_gmult_neon,%function
 .align	4
 gcm_gmult_neon:
@@ -432,7 +428,6 @@
 .size	gcm_gmult_neon,.-gcm_gmult_neon
 
 .global	gcm_ghash_neon
-.hidden	gcm_ghash_neon
 .type	gcm_ghash_neon,%function
 .align	4
 gcm_ghash_neon:
@@ -491,7 +486,7 @@
 #ifdef __ARMEL__
 	vrev64.8	$Xl,$Xl
 #endif
-	sub		$Xi,#16	
+	sub		$Xi,#16
 	vst1.64		$Xl#hi,[$Xi]!		@ write out Xi
 	vst1.64		$Xl#lo,[$Xi]
 
diff --git a/src/crypto/modes/asm/ghash-x86.pl b/src/crypto/modes/asm/ghash-x86.pl
index 0269169..d3a79e1 100644
--- a/src/crypto/modes/asm/ghash-x86.pl
+++ b/src/crypto/modes/asm/ghash-x86.pl
@@ -88,7 +88,7 @@
 # where Tproc is time required for Karatsuba pre- and post-processing,
 # is more realistic estimate. In this case it gives ... 1.91 cycles.
 # Or in other words, depending on how well we can interleave reduction
-# and one of the two multiplications the performance should be betwen
+# and one of the two multiplications the performance should be between
 # 1.91 and 2.16. As already mentioned, this implementation processes
 # one byte out of 8KB buffer in 2.10 cycles, while x86_64 counterpart
 # - in 2.02. x86_64 performance is better, because larger register
@@ -129,6 +129,9 @@
 push(@INC,"${dir}","${dir}../../perlasm");
 require "x86asm.pl";
 
+$output=pop;
+open STDOUT,">$output";
+
 &asm_init($ARGV[0],"ghash-x86.pl",$x86only = $ARGV[$#ARGV] eq "386");
 
 $sse2=0;
@@ -255,245 +258,17 @@
 	&mov	(&DWP($bias+56,"esp"),0xA9C0<<16);
 	&mov	(&DWP($bias+60,"esp"),0xB5E0<<16);
 }
-
-$suffix = $x86only ? "" : "_x86";
 
-&function_begin("gcm_gmult_4bit".$suffix);
-	&stack_push(16+4+1);			# +1 for stack alignment
-	&mov	($inp,&wparam(0));		# load Xi
-	&mov	($Htbl,&wparam(1));		# load Htable
-
-	&mov	($Zhh,&DWP(0,$inp));		# load Xi[16]
-	&mov	($Zhl,&DWP(4,$inp));
-	&mov	($Zlh,&DWP(8,$inp));
-	&mov	($Zll,&DWP(12,$inp));
-
-	&deposit_rem_4bit(16);
-
-	&mov	(&DWP(0,"esp"),$Zhh);		# copy Xi[16] on stack
-	&mov	(&DWP(4,"esp"),$Zhl);
-	&mov	(&DWP(8,"esp"),$Zlh);
-	&mov	(&DWP(12,"esp"),$Zll);
-	&shr	($Zll,20);
-	&and	($Zll,0xf0);
-
-	if ($unroll) {
-		&call	("_x86_gmult_4bit_inner");
-	} else {
-		&x86_loop(0);
-		&mov	($inp,&wparam(0));
-	}
-
-	&mov	(&DWP(12,$inp),$Zll);
-	&mov	(&DWP(8,$inp),$Zlh);
-	&mov	(&DWP(4,$inp),$Zhl);
-	&mov	(&DWP(0,$inp),$Zhh);
-	&stack_pop(16+4+1);
-&function_end("gcm_gmult_4bit".$suffix);
-
-&function_begin("gcm_ghash_4bit".$suffix);
-	&stack_push(16+4+1);			# +1 for 64-bit alignment
-	&mov	($Zll,&wparam(0));		# load Xi
-	&mov	($Htbl,&wparam(1));		# load Htable
-	&mov	($inp,&wparam(2));		# load in
-	&mov	("ecx",&wparam(3));		# load len
-	&add	("ecx",$inp);
-	&mov	(&wparam(3),"ecx");
-
-	&mov	($Zhh,&DWP(0,$Zll));		# load Xi[16]
-	&mov	($Zhl,&DWP(4,$Zll));
-	&mov	($Zlh,&DWP(8,$Zll));
-	&mov	($Zll,&DWP(12,$Zll));
-
-	&deposit_rem_4bit(16);
-
-    &set_label("x86_outer_loop",16);
-	&xor	($Zll,&DWP(12,$inp));		# xor with input
-	&xor	($Zlh,&DWP(8,$inp));
-	&xor	($Zhl,&DWP(4,$inp));
-	&xor	($Zhh,&DWP(0,$inp));
-	&mov	(&DWP(12,"esp"),$Zll);		# dump it on stack
-	&mov	(&DWP(8,"esp"),$Zlh);
-	&mov	(&DWP(4,"esp"),$Zhl);
-	&mov	(&DWP(0,"esp"),$Zhh);
-
-	&shr	($Zll,20);
-	&and	($Zll,0xf0);
-
-	if ($unroll) {
-		&call	("_x86_gmult_4bit_inner");
-	} else {
-		&x86_loop(0);
-		&mov	($inp,&wparam(2));
-	}
-	&lea	($inp,&DWP(16,$inp));
-	&cmp	($inp,&wparam(3));
-	&mov	(&wparam(2),$inp)	if (!$unroll);
-	&jb	(&label("x86_outer_loop"));
-
-	&mov	($inp,&wparam(0));	# load Xi
-	&mov	(&DWP(12,$inp),$Zll);
-	&mov	(&DWP(8,$inp),$Zlh);
-	&mov	(&DWP(4,$inp),$Zhl);
-	&mov	(&DWP(0,$inp),$Zhh);
-	&stack_pop(16+4+1);
-&function_end("gcm_ghash_4bit".$suffix);
-
 if (!$x86only) {{{
 
 &static_label("rem_4bit");
 
 if (!$sse2) {{	# pure-MMX "May" version...
 
-$S=12;		# shift factor for rem_4bit
+    # This code was removed since SSE2 is required for BoringSSL. The
+    # outer structure of the code was retained to minimize future merge
+    # conflicts.
 
-&function_begin_B("_mmx_gmult_4bit_inner");
-# MMX version performs 3.5 times better on P4 (see comment in non-MMX
-# routine for further details), 100% better on Opteron, ~70% better
-# on Core2 and PIII... In other words effort is considered to be well
-# spent... Since initial release the loop was unrolled in order to
-# "liberate" register previously used as loop counter. Instead it's
-# used to optimize critical path in 'Z.hi ^= rem_4bit[Z.lo&0xf]'.
-# The path involves move of Z.lo from MMX to integer register,
-# effective address calculation and finally merge of value to Z.hi.
-# Reference to rem_4bit is scheduled so late that I had to >>4
-# rem_4bit elements. This resulted in 20-45% procent improvement
-# on contemporary µ-archs.
-{
-    my $cnt;
-    my $rem_4bit = "eax";
-    my @rem = ($Zhh,$Zll);
-    my $nhi = $Zhl;
-    my $nlo = $Zlh;
-
-    my ($Zlo,$Zhi) = ("mm0","mm1");
-    my $tmp = "mm2";
-
-	&xor	($nlo,$nlo);	# avoid partial register stalls on PIII
-	&mov	($nhi,$Zll);
-	&mov	(&LB($nlo),&LB($nhi));
-	&shl	(&LB($nlo),4);
-	&and	($nhi,0xf0);
-	&movq	($Zlo,&QWP(8,$Htbl,$nlo));
-	&movq	($Zhi,&QWP(0,$Htbl,$nlo));
-	&movd	($rem[0],$Zlo);
-
-	for ($cnt=28;$cnt>=-2;$cnt--) {
-	    my $odd = $cnt&1;
-	    my $nix = $odd ? $nlo : $nhi;
-
-		&shl	(&LB($nlo),4)			if ($odd);
-		&psrlq	($Zlo,4);
-		&movq	($tmp,$Zhi);
-		&psrlq	($Zhi,4);
-		&pxor	($Zlo,&QWP(8,$Htbl,$nix));
-		&mov	(&LB($nlo),&BP($cnt/2,$inp))	if (!$odd && $cnt>=0);
-		&psllq	($tmp,60);
-		&and	($nhi,0xf0)			if ($odd);
-		&pxor	($Zhi,&QWP(0,$rem_4bit,$rem[1],8)) if ($cnt<28);
-		&and	($rem[0],0xf);
-		&pxor	($Zhi,&QWP(0,$Htbl,$nix));
-		&mov	($nhi,$nlo)			if (!$odd && $cnt>=0);
-		&movd	($rem[1],$Zlo);
-		&pxor	($Zlo,$tmp);
-
-		push	(@rem,shift(@rem));		# "rotate" registers
-	}
-
-	&mov	($inp,&DWP(4,$rem_4bit,$rem[1],8));	# last rem_4bit[rem]
-
-	&psrlq	($Zlo,32);	# lower part of Zlo is already there
-	&movd	($Zhl,$Zhi);
-	&psrlq	($Zhi,32);
-	&movd	($Zlh,$Zlo);
-	&movd	($Zhh,$Zhi);
-	&shl	($inp,4);	# compensate for rem_4bit[i] being >>4
-
-	&bswap	($Zll);
-	&bswap	($Zhl);
-	&bswap	($Zlh);
-	&xor	($Zhh,$inp);
-	&bswap	($Zhh);
-
-	&ret	();
-}
-&function_end_B("_mmx_gmult_4bit_inner");
-
-&function_begin("gcm_gmult_4bit_mmx");
-	&mov	($inp,&wparam(0));	# load Xi
-	&mov	($Htbl,&wparam(1));	# load Htable
-
-	&call	(&label("pic_point"));
-	&set_label("pic_point");
-	&blindpop("eax");
-	&lea	("eax",&DWP(&label("rem_4bit")."-".&label("pic_point"),"eax"));
-
-	&movz	($Zll,&BP(15,$inp));
-
-	&call	("_mmx_gmult_4bit_inner");
-
-	&mov	($inp,&wparam(0));	# load Xi
-	&emms	();
-	&mov	(&DWP(12,$inp),$Zll);
-	&mov	(&DWP(4,$inp),$Zhl);
-	&mov	(&DWP(8,$inp),$Zlh);
-	&mov	(&DWP(0,$inp),$Zhh);
-&function_end("gcm_gmult_4bit_mmx");
-
-# Streamed version performs 20% better on P4, 7% on Opteron,
-# 10% on Core2 and PIII...
-&function_begin("gcm_ghash_4bit_mmx");
-	&mov	($Zhh,&wparam(0));	# load Xi
-	&mov	($Htbl,&wparam(1));	# load Htable
-	&mov	($inp,&wparam(2));	# load in
-	&mov	($Zlh,&wparam(3));	# load len
-
-	&call	(&label("pic_point"));
-	&set_label("pic_point");
-	&blindpop("eax");
-	&lea	("eax",&DWP(&label("rem_4bit")."-".&label("pic_point"),"eax"));
-
-	&add	($Zlh,$inp);
-	&mov	(&wparam(3),$Zlh);	# len to point at the end of input
-	&stack_push(4+1);		# +1 for stack alignment
-
-	&mov	($Zll,&DWP(12,$Zhh));	# load Xi[16]
-	&mov	($Zhl,&DWP(4,$Zhh));
-	&mov	($Zlh,&DWP(8,$Zhh));
-	&mov	($Zhh,&DWP(0,$Zhh));
-	&jmp	(&label("mmx_outer_loop"));
-
-    &set_label("mmx_outer_loop",16);
-	&xor	($Zll,&DWP(12,$inp));
-	&xor	($Zhl,&DWP(4,$inp));
-	&xor	($Zlh,&DWP(8,$inp));
-	&xor	($Zhh,&DWP(0,$inp));
-	&mov	(&wparam(2),$inp);
-	&mov	(&DWP(12,"esp"),$Zll);
-	&mov	(&DWP(4,"esp"),$Zhl);
-	&mov	(&DWP(8,"esp"),$Zlh);
-	&mov	(&DWP(0,"esp"),$Zhh);
-
-	&mov	($inp,"esp");
-	&shr	($Zll,24);
-
-	&call	("_mmx_gmult_4bit_inner");
-
-	&mov	($inp,&wparam(2));
-	&lea	($inp,&DWP(16,$inp));
-	&cmp	($inp,&wparam(3));
-	&jb	(&label("mmx_outer_loop"));
-
-	&mov	($inp,&wparam(0));	# load Xi
-	&emms	();
-	&mov	(&DWP(12,$inp),$Zll);
-	&mov	(&DWP(4,$inp),$Zhl);
-	&mov	(&DWP(8,$inp),$Zlh);
-	&mov	(&DWP(0,$inp),$Zhh);
-
-	&stack_pop(4+1);
-&function_end("gcm_ghash_4bit_mmx");
-
 }} else {{	# "June" MMX version...
 		# ... has slower "April" gcm_gmult_4bit_mmx with folded
 		# loop. This is done to conserve code size...
@@ -712,7 +487,7 @@
     &pxor	($red[1],$red[1]);
     &pxor	($red[2],$red[2]);
 
-    # Just like in "May" verson modulo-schedule for critical path in
+    # Just like in "May" version modulo-schedule for critical path in
     # 'Z.hi ^= rem_8bit[Z.lo&0xff^((u8)H[nhi]<<4)]<<48'. Final 'pxor'
     # is scheduled so late that rem_8bit[] has to be shifted *right*
     # by 16, which is why last argument to pinsrw is 2, which
@@ -801,7 +576,7 @@
     &bswap	($dat);
     &pshufw	($Zhi,$Zhi,0b00011011);		# 76543210
     &bswap	("ebx");
-    
+
     &cmp	("ecx",&DWP(528+16+8,"esp"));	# are we done?
     &jne	(&label("outer"));
   }
@@ -905,7 +680,7 @@
 	&psllq		($Xi,57);		#
 	&movdqa		($T1,$Xi);		#
 	&pslldq		($Xi,8);
-	&psrldq		($T1,8);		#	
+	&psrldq		($T1,8);		#
 	&pxor		($Xi,$T2);
 	&pxor		($Xhi,$T1);		#
 
@@ -1075,7 +850,7 @@
 	  &psllq	($Xi,57);		#
 	  &movdqa	($T1,$Xi);		#
 	  &pslldq	($Xi,8);
-	  &psrldq	($T1,8);		#	
+	  &psrldq	($T1,8);		#
 	  &pxor		($Xi,$T2);
 	  &pxor		($Xhi,$T1);		#
 	&pshufd		($T1,$Xhn,0b01001110);
@@ -1138,7 +913,7 @@
 	&movdqu		(&QWP(0,$Xip),$Xi);
 &function_end("gcm_ghash_clmul");
 
-} else {		# Algorith 5. Kept for reference purposes.
+} else {		# Algorithm 5. Kept for reference purposes.
 
 sub reduction_alg5 {	# 19/16 times faster than Intel version
 my ($Xhi,$Xi)=@_;
@@ -1369,6 +1144,8 @@
 &asciz("GHASH for x86, CRYPTOGAMS by <appro\@openssl.org>");
 &asm_finish();
 
+close STDOUT;
+
 # A question was risen about choice of vanilla MMX. Or rather why wasn't
 # SSE2 chosen instead? In addition to the fact that MMX runs on legacy
 # CPUs such as PIII, "4-bit" MMX version was observed to provide better
diff --git a/src/crypto/modes/asm/ghash-x86_64.pl b/src/crypto/modes/asm/ghash-x86_64.pl
index e42ca32..0e6e348 100644
--- a/src/crypto/modes/asm/ghash-x86_64.pl
+++ b/src/crypto/modes/asm/ghash-x86_64.pl
@@ -64,8 +64,10 @@
 # Ivy Bridge	1.80(+7%)
 # Haswell	0.55(+93%) (if system doesn't support AVX)
 # Broadwell	0.45(+110%)(if system doesn't support AVX)
+# Skylake	0.44(+110%)(if system doesn't support AVX)
 # Bulldozer	1.49(+27%)
 # Silvermont	2.88(+13%)
+# Goldmont	1.08(+24%)
 
 # March 2013
 #
@@ -74,8 +76,8 @@
 # CPUs such as Sandy and Ivy Bridge can execute it, the code performs
 # sub-optimally in comparison to above mentioned version. But thanks
 # to Ilya Albrekht and Max Locktyukhin of Intel Corp. we knew that
-# it performs in 0.41 cycles per byte on Haswell processor, and in
-# 0.29 on Broadwell.
+# it performs in 0.41 cycles per byte on Haswell processor, in
+# 0.29 on Broadwell, and in 0.36 on Skylake.
 #
 # [1] http://rt.openssl.org/Ticket/Display.html?id=2900&user=guest&pass=guest
 
@@ -90,14 +92,15 @@
 ( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
 die "can't locate x86_64-xlate.pl";
 
+# See the notes about |$avx| in aesni-gcm-x86_64.pl; otherwise tags will be
+# computed incorrectly.
+#
 # In upstream, this is controlled by shelling out to the compiler to check
 # versions, but BoringSSL is intended to be used with pre-generated perlasm
 # output, so this isn't useful anyway.
-#
-# TODO(davidben): Enable this after testing. $avx goes up to 2.
-$avx = 0;
+$avx = 1;
 
-open OUT,"| \"$^X\" $xlate $flavour $output";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
 *STDOUT=*OUT;
 
 $do4xaggr=1;
@@ -216,8 +219,12 @@
 .align	16
 gcm_gmult_4bit:
 	push	%rbx
-	push	%rbp		# %rbp and %r12 are pushed exclusively in
+	push	%rbp		# %rbp and others are pushed exclusively in
 	push	%r12		# order to reuse Win64 exception handler...
+	push	%r13
+	push	%r14
+	push	%r15
+	sub	\$280,%rsp
 .Lgmult_prologue:
 
 	movzb	15($Xi),$Zlo
@@ -228,8 +235,9 @@
 	mov	$Zlo,8($Xi)
 	mov	$Zhi,($Xi)
 
-	mov	16(%rsp),%rbx
-	lea	24(%rsp),%rsp
+	lea	280+48(%rsp),%rsi
+	mov	-8(%rsi),%rbx
+	lea	(%rsi),%rsp
 .Lgmult_epilogue:
 	ret
 .size	gcm_gmult_4bit,.-gcm_gmult_4bit
@@ -379,14 +387,14 @@
 	mov	$Zlo,8($Xi)
 	mov	$Zhi,($Xi)
 
-	lea	280(%rsp),%rsi
-	mov	0(%rsi),%r15
-	mov	8(%rsi),%r14
-	mov	16(%rsi),%r13
-	mov	24(%rsi),%r12
-	mov	32(%rsi),%rbp
-	mov	40(%rsi),%rbx
-	lea	48(%rsi),%rsp
+	lea	280+48(%rsp),%rsi
+	mov	-48(%rsi),%r15
+	mov	-40(%rsi),%r14
+	mov	-32(%rsi),%r13
+	mov	-24(%rsi),%r12
+	mov	-16(%rsi),%rbp
+	mov	-8(%rsi),%rbx
+	lea	0(%rsi),%rsp
 .Lghash_epilogue:
 	ret
 .size	gcm_ghash_4bit,.-gcm_ghash_4bit
@@ -448,7 +456,7 @@
 	psllq		\$57,$Xi		#
 	movdqa		$Xi,$T1			#
 	pslldq		\$8,$Xi
-	psrldq		\$8,$T1			#	
+	psrldq		\$8,$T1			#
 	pxor		$T2,$Xi
 	pxor		$T1,$Xhi		#
 
@@ -562,7 +570,7 @@
 	&clmul64x64_T2	($Xhi,$Xi,$Hkey,$T2);
 $code.=<<___ if (0 || (&reduction_alg9($Xhi,$Xi)&&0));
 	# experimental alternative. special thing about is that there
-	# no dependency between the two multiplications... 
+	# no dependency between the two multiplications...
 	mov		\$`0xE1<<1`,%eax
 	mov		\$0xA040608020C0E000,%r10	# ((7..0)·0xE0)&0xff
 	mov		\$0x07,%r11d
@@ -737,7 +745,7 @@
 	movdqa		$T2,$T1			#
 	pslldq		\$8,$T2
 	 pclmulqdq	\$0x00,$Hkey2,$Xln
-	psrldq		\$8,$T1			#	
+	psrldq		\$8,$T1			#
 	pxor		$T2,$Xi
 	pxor		$T1,$Xhi		#
 	movdqu		0($inp),$T1
@@ -873,7 +881,7 @@
 	  psllq		\$57,$Xi		#
 	  movdqa	$Xi,$T1			#
 	  pslldq	\$8,$Xi
-	  psrldq	\$8,$T1			#	
+	  psrldq	\$8,$T1			#
 	  pxor		$T2,$Xi
 	pshufd		\$0b01001110,$Xhn,$Xmn
 	  pxor		$T1,$Xhi		#
@@ -1627,14 +1635,20 @@
 	cmp	%r10,%rbx		# context->Rip>=epilogue label
 	jae	.Lin_prologue
 
-	lea	24(%rax),%rax		# adjust "rsp"
+	lea	48+280(%rax),%rax	# adjust "rsp"
 
 	mov	-8(%rax),%rbx
 	mov	-16(%rax),%rbp
 	mov	-24(%rax),%r12
+	mov	-32(%rax),%r13
+	mov	-40(%rax),%r14
+	mov	-48(%rax),%r15
 	mov	%rbx,144($context)	# restore context->Rbx
 	mov	%rbp,160($context)	# restore context->Rbp
 	mov	%r12,216($context)	# restore context->R12
+	mov	%r13,224($context)	# restore context->R13
+	mov	%r14,232($context)	# restore context->R14
+	mov	%r15,240($context)	# restore context->R15
 
 .Lin_prologue:
 	mov	8(%rax),%rdi
diff --git a/src/crypto/modes/asm/ghashp8-ppc.pl b/src/crypto/modes/asm/ghashp8-ppc.pl
new file mode 100644
index 0000000..f0598cb
--- /dev/null
+++ b/src/crypto/modes/asm/ghashp8-ppc.pl
@@ -0,0 +1,670 @@
+#! /usr/bin/env perl
+# Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the OpenSSL license (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+#
+# ====================================================================
+# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
+# project. The module is, however, dual licensed under OpenSSL and
+# CRYPTOGAMS licenses depending on where you obtain it. For further
+# details see http://www.openssl.org/~appro/cryptogams/.
+# ====================================================================
+#
+# GHASH for for PowerISA v2.07.
+#
+# July 2014
+#
+# Accurate performance measurements are problematic, because it's
+# always virtualized setup with possibly throttled processor.
+# Relative comparison is therefore more informative. This initial
+# version is ~2.1x slower than hardware-assisted AES-128-CTR, ~12x
+# faster than "4-bit" integer-only compiler-generated 64-bit code.
+# "Initial version" means that there is room for futher improvement.
+
+# May 2016
+#
+# 2x aggregated reduction improves performance by 50% (resulting
+# performance on POWER8 is 1 cycle per processed byte), and 4x
+# aggregated reduction - by 170% or 2.7x (resulting in 0.55 cpb).
+
+$flavour=shift;
+$output =shift;
+
+if ($flavour =~ /64/) {
+	$SIZE_T=8;
+	$LRSAVE=2*$SIZE_T;
+	$STU="stdu";
+	$POP="ld";
+	$PUSH="std";
+	$UCMP="cmpld";
+	$SHRI="srdi";
+} elsif ($flavour =~ /32/) {
+	$SIZE_T=4;
+	$LRSAVE=$SIZE_T;
+	$STU="stwu";
+	$POP="lwz";
+	$PUSH="stw";
+	$UCMP="cmplw";
+	$SHRI="srwi";
+} else { die "nonsense $flavour"; }
+
+$sp="r1";
+$FRAME=6*$SIZE_T+13*16;	# 13*16 is for v20-v31 offload
+
+$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
+( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or
+( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
+die "can't locate ppc-xlate.pl";
+
+open STDOUT,"| $^X $xlate $flavour $output" || die "can't call $xlate: $!";
+
+my ($Xip,$Htbl,$inp,$len)=map("r$_",(3..6));	# argument block
+
+my ($Xl,$Xm,$Xh,$IN)=map("v$_",(0..3));
+my ($zero,$t0,$t1,$t2,$xC2,$H,$Hh,$Hl,$lemask)=map("v$_",(4..12));
+my ($Xl1,$Xm1,$Xh1,$IN1,$H2,$H2h,$H2l)=map("v$_",(13..19));
+my $vrsave="r12";
+
+$code=<<___;
+.machine	"any"
+
+.text
+
+.globl	.gcm_init_p8
+.align	5
+.gcm_init_p8:
+	li		r0,-4096
+	li		r8,0x10
+	mfspr		$vrsave,256
+	li		r9,0x20
+	mtspr		256,r0
+	li		r10,0x30
+	lvx_u		$H,0,r4			# load H
+
+	vspltisb	$xC2,-16		# 0xf0
+	vspltisb	$t0,1			# one
+	vaddubm		$xC2,$xC2,$xC2		# 0xe0
+	vxor		$zero,$zero,$zero
+	vor		$xC2,$xC2,$t0		# 0xe1
+	vsldoi		$xC2,$xC2,$zero,15	# 0xe1...
+	vsldoi		$t1,$zero,$t0,1		# ...1
+	vaddubm		$xC2,$xC2,$xC2		# 0xc2...
+	vspltisb	$t2,7
+	vor		$xC2,$xC2,$t1		# 0xc2....01
+	vspltb		$t1,$H,0		# most significant byte
+	vsl		$H,$H,$t0		# H<<=1
+	vsrab		$t1,$t1,$t2		# broadcast carry bit
+	vand		$t1,$t1,$xC2
+	vxor		$IN,$H,$t1		# twisted H
+
+	vsldoi		$H,$IN,$IN,8		# twist even more ...
+	vsldoi		$xC2,$zero,$xC2,8	# 0xc2.0
+	vsldoi		$Hl,$zero,$H,8		# ... and split
+	vsldoi		$Hh,$H,$zero,8
+
+	stvx_u		$xC2,0,r3		# save pre-computed table
+	stvx_u		$Hl,r8,r3
+	li		r8,0x40
+	stvx_u		$H, r9,r3
+	li		r9,0x50
+	stvx_u		$Hh,r10,r3
+	li		r10,0x60
+
+	vpmsumd		$Xl,$IN,$Hl		# H.lo·H.lo
+	vpmsumd		$Xm,$IN,$H		# H.hi·H.lo+H.lo·H.hi
+	vpmsumd		$Xh,$IN,$Hh		# H.hi·H.hi
+
+	vpmsumd		$t2,$Xl,$xC2		# 1st reduction phase
+
+	vsldoi		$t0,$Xm,$zero,8
+	vsldoi		$t1,$zero,$Xm,8
+	vxor		$Xl,$Xl,$t0
+	vxor		$Xh,$Xh,$t1
+
+	vsldoi		$Xl,$Xl,$Xl,8
+	vxor		$Xl,$Xl,$t2
+
+	vsldoi		$t1,$Xl,$Xl,8		# 2nd reduction phase
+	vpmsumd		$Xl,$Xl,$xC2
+	vxor		$t1,$t1,$Xh
+	vxor		$IN1,$Xl,$t1
+
+	vsldoi		$H2,$IN1,$IN1,8
+	vsldoi		$H2l,$zero,$H2,8
+	vsldoi		$H2h,$H2,$zero,8
+
+	stvx_u		$H2l,r8,r3		# save H^2
+	li		r8,0x70
+	stvx_u		$H2,r9,r3
+	li		r9,0x80
+	stvx_u		$H2h,r10,r3
+	li		r10,0x90
+___
+{
+my ($t4,$t5,$t6) = ($Hl,$H,$Hh);
+$code.=<<___;
+	vpmsumd		$Xl,$IN,$H2l		# H.lo·H^2.lo
+	 vpmsumd	$Xl1,$IN1,$H2l		# H^2.lo·H^2.lo
+	vpmsumd		$Xm,$IN,$H2		# H.hi·H^2.lo+H.lo·H^2.hi
+	 vpmsumd	$Xm1,$IN1,$H2		# H^2.hi·H^2.lo+H^2.lo·H^2.hi
+	vpmsumd		$Xh,$IN,$H2h		# H.hi·H^2.hi
+	 vpmsumd	$Xh1,$IN1,$H2h		# H^2.hi·H^2.hi
+
+	vpmsumd		$t2,$Xl,$xC2		# 1st reduction phase
+	 vpmsumd	$t6,$Xl1,$xC2		# 1st reduction phase
+
+	vsldoi		$t0,$Xm,$zero,8
+	vsldoi		$t1,$zero,$Xm,8
+	 vsldoi		$t4,$Xm1,$zero,8
+	 vsldoi		$t5,$zero,$Xm1,8
+	vxor		$Xl,$Xl,$t0
+	vxor		$Xh,$Xh,$t1
+	 vxor		$Xl1,$Xl1,$t4
+	 vxor		$Xh1,$Xh1,$t5
+
+	vsldoi		$Xl,$Xl,$Xl,8
+	 vsldoi		$Xl1,$Xl1,$Xl1,8
+	vxor		$Xl,$Xl,$t2
+	 vxor		$Xl1,$Xl1,$t6
+
+	vsldoi		$t1,$Xl,$Xl,8		# 2nd reduction phase
+	 vsldoi		$t5,$Xl1,$Xl1,8		# 2nd reduction phase
+	vpmsumd		$Xl,$Xl,$xC2
+	 vpmsumd	$Xl1,$Xl1,$xC2
+	vxor		$t1,$t1,$Xh
+	 vxor		$t5,$t5,$Xh1
+	vxor		$Xl,$Xl,$t1
+	 vxor		$Xl1,$Xl1,$t5
+
+	vsldoi		$H,$Xl,$Xl,8
+	 vsldoi		$H2,$Xl1,$Xl1,8
+	vsldoi		$Hl,$zero,$H,8
+	vsldoi		$Hh,$H,$zero,8
+	 vsldoi		$H2l,$zero,$H2,8
+	 vsldoi		$H2h,$H2,$zero,8
+
+	stvx_u		$Hl,r8,r3		# save H^3
+	li		r8,0xa0
+	stvx_u		$H,r9,r3
+	li		r9,0xb0
+	stvx_u		$Hh,r10,r3
+	li		r10,0xc0
+	 stvx_u		$H2l,r8,r3		# save H^4
+	 stvx_u		$H2,r9,r3
+	 stvx_u		$H2h,r10,r3
+
+	mtspr		256,$vrsave
+	blr
+	.long		0
+	.byte		0,12,0x14,0,0,0,2,0
+	.long		0
+.size	.gcm_init_p8,.-.gcm_init_p8
+___
+}
+$code.=<<___;
+.globl	.gcm_gmult_p8
+.align	5
+.gcm_gmult_p8:
+	lis		r0,0xfff8
+	li		r8,0x10
+	mfspr		$vrsave,256
+	li		r9,0x20
+	mtspr		256,r0
+	li		r10,0x30
+	lvx_u		$IN,0,$Xip		# load Xi
+
+	lvx_u		$Hl,r8,$Htbl		# load pre-computed table
+	 le?lvsl	$lemask,r0,r0
+	lvx_u		$H, r9,$Htbl
+	 le?vspltisb	$t0,0x07
+	lvx_u		$Hh,r10,$Htbl
+	 le?vxor	$lemask,$lemask,$t0
+	lvx_u		$xC2,0,$Htbl
+	 le?vperm	$IN,$IN,$IN,$lemask
+	vxor		$zero,$zero,$zero
+
+	vpmsumd		$Xl,$IN,$Hl		# H.lo·Xi.lo
+	vpmsumd		$Xm,$IN,$H		# H.hi·Xi.lo+H.lo·Xi.hi
+	vpmsumd		$Xh,$IN,$Hh		# H.hi·Xi.hi
+
+	vpmsumd		$t2,$Xl,$xC2		# 1st reduction phase
+
+	vsldoi		$t0,$Xm,$zero,8
+	vsldoi		$t1,$zero,$Xm,8
+	vxor		$Xl,$Xl,$t0
+	vxor		$Xh,$Xh,$t1
+
+	vsldoi		$Xl,$Xl,$Xl,8
+	vxor		$Xl,$Xl,$t2
+
+	vsldoi		$t1,$Xl,$Xl,8		# 2nd reduction phase
+	vpmsumd		$Xl,$Xl,$xC2
+	vxor		$t1,$t1,$Xh
+	vxor		$Xl,$Xl,$t1
+
+	le?vperm	$Xl,$Xl,$Xl,$lemask
+	stvx_u		$Xl,0,$Xip		# write out Xi
+
+	mtspr		256,$vrsave
+	blr
+	.long		0
+	.byte		0,12,0x14,0,0,0,2,0
+	.long		0
+.size	.gcm_gmult_p8,.-.gcm_gmult_p8
+
+.globl	.gcm_ghash_p8
+.align	5
+.gcm_ghash_p8:
+	li		r0,-4096
+	li		r8,0x10
+	mfspr		$vrsave,256
+	li		r9,0x20
+	mtspr		256,r0
+	li		r10,0x30
+	lvx_u		$Xl,0,$Xip		# load Xi
+
+	lvx_u		$Hl,r8,$Htbl		# load pre-computed table
+	li		r8,0x40
+	 le?lvsl	$lemask,r0,r0
+	lvx_u		$H, r9,$Htbl
+	li		r9,0x50
+	 le?vspltisb	$t0,0x07
+	lvx_u		$Hh,r10,$Htbl
+	li		r10,0x60
+	 le?vxor	$lemask,$lemask,$t0
+	lvx_u		$xC2,0,$Htbl
+	 le?vperm	$Xl,$Xl,$Xl,$lemask
+	vxor		$zero,$zero,$zero
+
+	${UCMP}i	$len,64
+	bge		Lgcm_ghash_p8_4x
+
+	lvx_u		$IN,0,$inp
+	addi		$inp,$inp,16
+	subic.		$len,$len,16
+	 le?vperm	$IN,$IN,$IN,$lemask
+	vxor		$IN,$IN,$Xl
+	beq		Lshort
+
+	lvx_u		$H2l,r8,$Htbl		# load H^2
+	li		r8,16
+	lvx_u		$H2, r9,$Htbl
+	add		r9,$inp,$len		# end of input
+	lvx_u		$H2h,r10,$Htbl
+	be?b		Loop_2x
+
+.align	5
+Loop_2x:
+	lvx_u		$IN1,0,$inp
+	le?vperm	$IN1,$IN1,$IN1,$lemask
+
+	 subic		$len,$len,32
+	vpmsumd		$Xl,$IN,$H2l		# H^2.lo·Xi.lo
+	 vpmsumd	$Xl1,$IN1,$Hl		# H.lo·Xi+1.lo
+	 subfe		r0,r0,r0		# borrow?-1:0
+	vpmsumd		$Xm,$IN,$H2		# H^2.hi·Xi.lo+H^2.lo·Xi.hi
+	 vpmsumd	$Xm1,$IN1,$H		# H.hi·Xi+1.lo+H.lo·Xi+1.hi
+	 and		r0,r0,$len
+	vpmsumd		$Xh,$IN,$H2h		# H^2.hi·Xi.hi
+	 vpmsumd	$Xh1,$IN1,$Hh		# H.hi·Xi+1.hi
+	 add		$inp,$inp,r0
+
+	vxor		$Xl,$Xl,$Xl1
+	vxor		$Xm,$Xm,$Xm1
+
+	vpmsumd		$t2,$Xl,$xC2		# 1st reduction phase
+
+	vsldoi		$t0,$Xm,$zero,8
+	vsldoi		$t1,$zero,$Xm,8
+	 vxor		$Xh,$Xh,$Xh1
+	vxor		$Xl,$Xl,$t0
+	vxor		$Xh,$Xh,$t1
+
+	vsldoi		$Xl,$Xl,$Xl,8
+	vxor		$Xl,$Xl,$t2
+	 lvx_u		$IN,r8,$inp
+	 addi		$inp,$inp,32
+
+	vsldoi		$t1,$Xl,$Xl,8		# 2nd reduction phase
+	vpmsumd		$Xl,$Xl,$xC2
+	 le?vperm	$IN,$IN,$IN,$lemask
+	vxor		$t1,$t1,$Xh
+	vxor		$IN,$IN,$t1
+	vxor		$IN,$IN,$Xl
+	$UCMP		r9,$inp
+	bgt		Loop_2x			# done yet?
+
+	cmplwi		$len,0
+	bne		Leven
+
+Lshort:
+	vpmsumd		$Xl,$IN,$Hl		# H.lo·Xi.lo
+	vpmsumd		$Xm,$IN,$H		# H.hi·Xi.lo+H.lo·Xi.hi
+	vpmsumd		$Xh,$IN,$Hh		# H.hi·Xi.hi
+
+	vpmsumd		$t2,$Xl,$xC2		# 1st reduction phase
+
+	vsldoi		$t0,$Xm,$zero,8
+	vsldoi		$t1,$zero,$Xm,8
+	vxor		$Xl,$Xl,$t0
+	vxor		$Xh,$Xh,$t1
+
+	vsldoi		$Xl,$Xl,$Xl,8
+	vxor		$Xl,$Xl,$t2
+
+	vsldoi		$t1,$Xl,$Xl,8		# 2nd reduction phase
+	vpmsumd		$Xl,$Xl,$xC2
+	vxor		$t1,$t1,$Xh
+
+Leven:
+	vxor		$Xl,$Xl,$t1
+	le?vperm	$Xl,$Xl,$Xl,$lemask
+	stvx_u		$Xl,0,$Xip		# write out Xi
+
+	mtspr		256,$vrsave
+	blr
+	.long		0
+	.byte		0,12,0x14,0,0,0,4,0
+	.long		0
+___
+{
+my ($Xl3,$Xm2,$IN2,$H3l,$H3,$H3h,
+    $Xh3,$Xm3,$IN3,$H4l,$H4,$H4h) = map("v$_",(20..31));
+my $IN0=$IN;
+my ($H21l,$H21h,$loperm,$hiperm) = ($Hl,$Hh,$H2l,$H2h);
+
+$code.=<<___;
+.align	5
+.gcm_ghash_p8_4x:
+Lgcm_ghash_p8_4x:
+	$STU		$sp,-$FRAME($sp)
+	li		r10,`15+6*$SIZE_T`
+	li		r11,`31+6*$SIZE_T`
+	stvx		v20,r10,$sp
+	addi		r10,r10,32
+	stvx		v21,r11,$sp
+	addi		r11,r11,32
+	stvx		v22,r10,$sp
+	addi		r10,r10,32
+	stvx		v23,r11,$sp
+	addi		r11,r11,32
+	stvx		v24,r10,$sp
+	addi		r10,r10,32
+	stvx		v25,r11,$sp
+	addi		r11,r11,32
+	stvx		v26,r10,$sp
+	addi		r10,r10,32
+	stvx		v27,r11,$sp
+	addi		r11,r11,32
+	stvx		v28,r10,$sp
+	addi		r10,r10,32
+	stvx		v29,r11,$sp
+	addi		r11,r11,32
+	stvx		v30,r10,$sp
+	li		r10,0x60
+	stvx		v31,r11,$sp
+	li		r0,-1
+	stw		$vrsave,`$FRAME-4`($sp)	# save vrsave
+	mtspr		256,r0			# preserve all AltiVec registers
+
+	lvsl		$t0,0,r8		# 0x0001..0e0f
+	#lvx_u		$H2l,r8,$Htbl		# load H^2
+	li		r8,0x70
+	lvx_u		$H2, r9,$Htbl
+	li		r9,0x80
+	vspltisb	$t1,8			# 0x0808..0808
+	#lvx_u		$H2h,r10,$Htbl
+	li		r10,0x90
+	lvx_u		$H3l,r8,$Htbl		# load H^3
+	li		r8,0xa0
+	lvx_u		$H3, r9,$Htbl
+	li		r9,0xb0
+	lvx_u		$H3h,r10,$Htbl
+	li		r10,0xc0
+	lvx_u		$H4l,r8,$Htbl		# load H^4
+	li		r8,0x10
+	lvx_u		$H4, r9,$Htbl
+	li		r9,0x20
+	lvx_u		$H4h,r10,$Htbl
+	li		r10,0x30
+
+	vsldoi		$t2,$zero,$t1,8		# 0x0000..0808
+	vaddubm		$hiperm,$t0,$t2		# 0x0001..1617
+	vaddubm		$loperm,$t1,$hiperm	# 0x0809..1e1f
+
+	$SHRI		$len,$len,4		# this allows to use sign bit
+						# as carry
+	lvx_u		$IN0,0,$inp		# load input
+	lvx_u		$IN1,r8,$inp
+	subic.		$len,$len,8
+	lvx_u		$IN2,r9,$inp
+	lvx_u		$IN3,r10,$inp
+	addi		$inp,$inp,0x40
+	le?vperm	$IN0,$IN0,$IN0,$lemask
+	le?vperm	$IN1,$IN1,$IN1,$lemask
+	le?vperm	$IN2,$IN2,$IN2,$lemask
+	le?vperm	$IN3,$IN3,$IN3,$lemask
+
+	vxor		$Xh,$IN0,$Xl
+
+	 vpmsumd	$Xl1,$IN1,$H3l
+	 vpmsumd	$Xm1,$IN1,$H3
+	 vpmsumd	$Xh1,$IN1,$H3h
+
+	 vperm		$H21l,$H2,$H,$hiperm
+	 vperm		$t0,$IN2,$IN3,$loperm
+	 vperm		$H21h,$H2,$H,$loperm
+	 vperm		$t1,$IN2,$IN3,$hiperm
+	 vpmsumd	$Xm2,$IN2,$H2		# H^2.lo·Xi+2.hi+H^2.hi·Xi+2.lo
+	 vpmsumd	$Xl3,$t0,$H21l		# H^2.lo·Xi+2.lo+H.lo·Xi+3.lo
+	 vpmsumd	$Xm3,$IN3,$H		# H.hi·Xi+3.lo  +H.lo·Xi+3.hi
+	 vpmsumd	$Xh3,$t1,$H21h		# H^2.hi·Xi+2.hi+H.hi·Xi+3.hi
+
+	 vxor		$Xm2,$Xm2,$Xm1
+	 vxor		$Xl3,$Xl3,$Xl1
+	 vxor		$Xm3,$Xm3,$Xm2
+	 vxor		$Xh3,$Xh3,$Xh1
+
+	blt		Ltail_4x
+
+Loop_4x:
+	lvx_u		$IN0,0,$inp
+	lvx_u		$IN1,r8,$inp
+	subic.		$len,$len,4
+	lvx_u		$IN2,r9,$inp
+	lvx_u		$IN3,r10,$inp
+	addi		$inp,$inp,0x40
+	le?vperm	$IN1,$IN1,$IN1,$lemask
+	le?vperm	$IN2,$IN2,$IN2,$lemask
+	le?vperm	$IN3,$IN3,$IN3,$lemask
+	le?vperm	$IN0,$IN0,$IN0,$lemask
+
+	vpmsumd		$Xl,$Xh,$H4l		# H^4.lo·Xi.lo
+	vpmsumd		$Xm,$Xh,$H4		# H^4.hi·Xi.lo+H^4.lo·Xi.hi
+	vpmsumd		$Xh,$Xh,$H4h		# H^4.hi·Xi.hi
+	 vpmsumd	$Xl1,$IN1,$H3l
+	 vpmsumd	$Xm1,$IN1,$H3
+	 vpmsumd	$Xh1,$IN1,$H3h
+
+	vxor		$Xl,$Xl,$Xl3
+	vxor		$Xm,$Xm,$Xm3
+	vxor		$Xh,$Xh,$Xh3
+	 vperm		$t0,$IN2,$IN3,$loperm
+	 vperm		$t1,$IN2,$IN3,$hiperm
+
+	vpmsumd		$t2,$Xl,$xC2		# 1st reduction phase
+	 vpmsumd	$Xl3,$t0,$H21l		# H.lo·Xi+3.lo  +H^2.lo·Xi+2.lo
+	 vpmsumd	$Xh3,$t1,$H21h		# H.hi·Xi+3.hi  +H^2.hi·Xi+2.hi
+
+	vsldoi		$t0,$Xm,$zero,8
+	vsldoi		$t1,$zero,$Xm,8
+	vxor		$Xl,$Xl,$t0
+	vxor		$Xh,$Xh,$t1
+
+	vsldoi		$Xl,$Xl,$Xl,8
+	vxor		$Xl,$Xl,$t2
+
+	vsldoi		$t1,$Xl,$Xl,8		# 2nd reduction phase
+	 vpmsumd	$Xm2,$IN2,$H2		# H^2.hi·Xi+2.lo+H^2.lo·Xi+2.hi
+	 vpmsumd	$Xm3,$IN3,$H		# H.hi·Xi+3.lo  +H.lo·Xi+3.hi
+	vpmsumd		$Xl,$Xl,$xC2
+
+	 vxor		$Xl3,$Xl3,$Xl1
+	 vxor		$Xh3,$Xh3,$Xh1
+	vxor		$Xh,$Xh,$IN0
+	 vxor		$Xm2,$Xm2,$Xm1
+	vxor		$Xh,$Xh,$t1
+	 vxor		$Xm3,$Xm3,$Xm2
+	vxor		$Xh,$Xh,$Xl
+	bge		Loop_4x
+
+Ltail_4x:
+	vpmsumd		$Xl,$Xh,$H4l		# H^4.lo·Xi.lo
+	vpmsumd		$Xm,$Xh,$H4		# H^4.hi·Xi.lo+H^4.lo·Xi.hi
+	vpmsumd		$Xh,$Xh,$H4h		# H^4.hi·Xi.hi
+
+	vxor		$Xl,$Xl,$Xl3
+	vxor		$Xm,$Xm,$Xm3
+
+	vpmsumd		$t2,$Xl,$xC2		# 1st reduction phase
+
+	vsldoi		$t0,$Xm,$zero,8
+	vsldoi		$t1,$zero,$Xm,8
+	 vxor		$Xh,$Xh,$Xh3
+	vxor		$Xl,$Xl,$t0
+	vxor		$Xh,$Xh,$t1
+
+	vsldoi		$Xl,$Xl,$Xl,8
+	vxor		$Xl,$Xl,$t2
+
+	vsldoi		$t1,$Xl,$Xl,8		# 2nd reduction phase
+	vpmsumd		$Xl,$Xl,$xC2
+	vxor		$t1,$t1,$Xh
+	vxor		$Xl,$Xl,$t1
+
+	addic.		$len,$len,4
+	beq		Ldone_4x
+
+	lvx_u		$IN0,0,$inp
+	${UCMP}i	$len,2
+	li		$len,-4
+	blt		Lone
+	lvx_u		$IN1,r8,$inp
+	beq		Ltwo
+
+Lthree:
+	lvx_u		$IN2,r9,$inp
+	le?vperm	$IN0,$IN0,$IN0,$lemask
+	le?vperm	$IN1,$IN1,$IN1,$lemask
+	le?vperm	$IN2,$IN2,$IN2,$lemask
+
+	vxor		$Xh,$IN0,$Xl
+	vmr		$H4l,$H3l
+	vmr		$H4, $H3
+	vmr		$H4h,$H3h
+
+	vperm		$t0,$IN1,$IN2,$loperm
+	vperm		$t1,$IN1,$IN2,$hiperm
+	vpmsumd		$Xm2,$IN1,$H2		# H^2.lo·Xi+1.hi+H^2.hi·Xi+1.lo
+	vpmsumd		$Xm3,$IN2,$H		# H.hi·Xi+2.lo  +H.lo·Xi+2.hi
+	vpmsumd		$Xl3,$t0,$H21l		# H^2.lo·Xi+1.lo+H.lo·Xi+2.lo
+	vpmsumd		$Xh3,$t1,$H21h		# H^2.hi·Xi+1.hi+H.hi·Xi+2.hi
+
+	vxor		$Xm3,$Xm3,$Xm2
+	b		Ltail_4x
+
+.align	4
+Ltwo:
+	le?vperm	$IN0,$IN0,$IN0,$lemask
+	le?vperm	$IN1,$IN1,$IN1,$lemask
+
+	vxor		$Xh,$IN0,$Xl
+	vperm		$t0,$zero,$IN1,$loperm
+	vperm		$t1,$zero,$IN1,$hiperm
+
+	vsldoi		$H4l,$zero,$H2,8
+	vmr		$H4, $H2
+	vsldoi		$H4h,$H2,$zero,8
+
+	vpmsumd		$Xl3,$t0, $H21l		# H.lo·Xi+1.lo
+	vpmsumd		$Xm3,$IN1,$H		# H.hi·Xi+1.lo+H.lo·Xi+2.hi
+	vpmsumd		$Xh3,$t1, $H21h		# H.hi·Xi+1.hi
+
+	b		Ltail_4x
+
+.align	4
+Lone:
+	le?vperm	$IN0,$IN0,$IN0,$lemask
+
+	vsldoi		$H4l,$zero,$H,8
+	vmr		$H4, $H
+	vsldoi		$H4h,$H,$zero,8
+
+	vxor		$Xh,$IN0,$Xl
+	vxor		$Xl3,$Xl3,$Xl3
+	vxor		$Xm3,$Xm3,$Xm3
+	vxor		$Xh3,$Xh3,$Xh3
+
+	b		Ltail_4x
+
+Ldone_4x:
+	le?vperm	$Xl,$Xl,$Xl,$lemask
+	stvx_u		$Xl,0,$Xip		# write out Xi
+
+	li		r10,`15+6*$SIZE_T`
+	li		r11,`31+6*$SIZE_T`
+	mtspr		256,$vrsave
+	lvx		v20,r10,$sp
+	addi		r10,r10,32
+	lvx		v21,r11,$sp
+	addi		r11,r11,32
+	lvx		v22,r10,$sp
+	addi		r10,r10,32
+	lvx		v23,r11,$sp
+	addi		r11,r11,32
+	lvx		v24,r10,$sp
+	addi		r10,r10,32
+	lvx		v25,r11,$sp
+	addi		r11,r11,32
+	lvx		v26,r10,$sp
+	addi		r10,r10,32
+	lvx		v27,r11,$sp
+	addi		r11,r11,32
+	lvx		v28,r10,$sp
+	addi		r10,r10,32
+	lvx		v29,r11,$sp
+	addi		r11,r11,32
+	lvx		v30,r10,$sp
+	lvx		v31,r11,$sp
+	addi		$sp,$sp,$FRAME
+	blr
+	.long		0
+	.byte		0,12,0x04,0,0x80,0,4,0
+	.long		0
+___
+}
+$code.=<<___;
+.size	.gcm_ghash_p8,.-.gcm_ghash_p8
+
+.asciz  "GHASH for PowerISA 2.07, CRYPTOGAMS by <appro\@openssl.org>"
+.align  2
+___
+
+foreach (split("\n",$code)) {
+	s/\`([^\`]*)\`/eval $1/geo;
+
+	if ($flavour =~ /le$/o) {	# little-endian
+	    s/le\?//o		or
+	    s/be\?/#be#/o;
+	} else {
+	    s/le\?/#le#/o	or
+	    s/be\?//o;
+	}
+	print $_,"\n";
+}
+
+close STDOUT; # enforce flush
diff --git a/src/crypto/modes/asm/ghashv8-armx.pl b/src/crypto/modes/asm/ghashv8-armx.pl
index 3a7b8d8..15fc478 100644
--- a/src/crypto/modes/asm/ghashv8-armx.pl
+++ b/src/crypto/modes/asm/ghashv8-armx.pl
@@ -59,7 +59,7 @@
 .text
 ___
 $code.=<<___ if ($flavour =~ /64/);
-#if !defined(__clang__)
+#if !defined(__clang__) || defined(BORINGSSL_CLANG_SUPPORTS_DOT_ARCH)
 .arch  armv8-a+crypto
 #endif
 ___
diff --git a/src/crypto/modes/cbc.c b/src/crypto/modes/cbc.c
index e41f2b4..12d551c 100644
--- a/src/crypto/modes/cbc.c
+++ b/src/crypto/modes/cbc.c
@@ -52,10 +52,6 @@
 #include "internal.h"
 
 
-#ifndef STRICT_ALIGNMENT
-#  define STRICT_ALIGNMENT 0
-#endif
-
 void CRYPTO_cbc128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
                            const void *key, uint8_t ivec[16],
                            block128_f block) {
@@ -107,7 +103,7 @@
     out += 16;
   }
 
-  memcpy(ivec, iv, 16);
+  OPENSSL_memcpy(ivec, iv, 16);
 }
 
 void CRYPTO_cbc128_decrypt(const uint8_t *in, uint8_t *out, size_t len,
@@ -158,7 +154,7 @@
         out += 16;
       }
     }
-    memcpy(ivec, iv, 16);
+    OPENSSL_memcpy(ivec, iv, 16);
   } else {
     /* |out| is less than two blocks behind |in|. Decrypting an input block
      * directly to |out| would overwrite a ciphertext block before it is used as
diff --git a/src/crypto/modes/cfb.c b/src/crypto/modes/cfb.c
index c58614b..af15255 100644
--- a/src/crypto/modes/cfb.c
+++ b/src/crypto/modes/cfb.c
@@ -57,14 +57,13 @@
 OPENSSL_COMPILE_ASSERT((16 % sizeof(size_t)) == 0, bad_size_t_size);
 
 void CRYPTO_cfb128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
-                           const void *key, uint8_t ivec[16], int *num, int enc,
-                           block128_f block) {
-  unsigned int n;
+                           const void *key, uint8_t ivec[16], unsigned *num,
+                           int enc, block128_f block) {
   size_t l = 0;
 
   assert(in && out && key && ivec && num);
 
-  n = *num;
+  unsigned n = *num;
 
   if (enc) {
     while (n && len) {
@@ -168,7 +167,7 @@
   }
 
   /* fill in the first half of the new IV with the current IV */
-  memcpy(ovec, ivec, 16);
+  OPENSSL_memcpy(ovec, ivec, 16);
   /* construct the new IV */
   (*block)(ivec, ivec, key);
   num = (nbits + 7) / 8;
@@ -187,7 +186,7 @@
   rem = nbits % 8;
   num = nbits / 8;
   if (rem == 0) {
-    memcpy(ivec, ovec + num, 16);
+    OPENSSL_memcpy(ivec, ovec + num, 16);
   } else {
     for (n = 0; n < 16; ++n) {
       ivec[n] = ovec[n + num] << rem | ovec[n + num + 1] >> (8 - rem);
@@ -199,7 +198,7 @@
 
 /* N.B. This expects the input to be packed, MS bit first */
 void CRYPTO_cfb128_1_encrypt(const uint8_t *in, uint8_t *out, size_t bits,
-                             const void *key, uint8_t ivec[16], int *num,
+                             const void *key, uint8_t ivec[16], unsigned *num,
                              int enc, block128_f block) {
   size_t n;
   uint8_t c[1], d[1];
@@ -217,7 +216,7 @@
 
 void CRYPTO_cfb128_8_encrypt(const unsigned char *in, unsigned char *out,
                              size_t length, const void *key,
-                             unsigned char ivec[16], int *num, int enc,
+                             unsigned char ivec[16], unsigned *num, int enc,
                              block128_f block) {
   size_t n;
 
diff --git a/src/crypto/modes/ctr.c b/src/crypto/modes/ctr.c
index 52ff048..c026d15 100644
--- a/src/crypto/modes/ctr.c
+++ b/src/crypto/modes/ctr.c
@@ -59,17 +59,13 @@
 
 /* increment counter (128-bit int) by 1 */
 static void ctr128_inc(uint8_t *counter) {
-  uint32_t n = 16;
-  uint8_t c;
+  uint32_t n = 16, c = 1;
 
   do {
     --n;
-    c = counter[n];
-    ++c;
-    counter[n] = c;
-    if (c) {
-      return;
-    }
+    c += counter[n];
+    counter[n] = (uint8_t) c;
+    c >>= 8;
   } while (n);
 }
 
@@ -104,7 +100,7 @@
   }
 
 #if STRICT_ALIGNMENT
-  if (((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) {
+  if (((size_t)in | (size_t)out | (size_t)ecount_buf) % sizeof(size_t) != 0) {
     size_t l = 0;
     while (l < len) {
       if (n == 0) {
@@ -124,8 +120,9 @@
   while (len >= 16) {
     (*block)(ivec, ecount_buf, key);
     ctr128_inc(ivec);
-    for (; n < 16; n += sizeof(size_t)) {
-      *(size_t *)(out + n) = *(size_t *)(in + n) ^ *(size_t *)(ecount_buf + n);
+    for (n = 0; n < 16; n += sizeof(size_t)) {
+      *(size_t *)(out + n) = *(const size_t *)(in + n) ^
+                             *(const size_t *)(ecount_buf + n);
     }
     len -= 16;
     out += 16;
@@ -145,17 +142,13 @@
 
 /* increment upper 96 bits of 128-bit counter by 1 */
 static void ctr96_inc(uint8_t *counter) {
-  uint32_t n = 12;
-  uint8_t c;
+  uint32_t n = 12, c = 1;
 
   do {
     --n;
-    c = counter[n];
-    ++c;
-    counter[n] = c;
-    if (c) {
-      return;
-    }
+    c += counter[n];
+    counter[n] = (uint8_t) c;
+    c >>= 8;
   } while (n);
 }
 
@@ -209,7 +202,7 @@
     in += blocks;
   }
   if (len) {
-    memset(ecount_buf, 0, 16);
+    OPENSSL_memset(ecount_buf, 0, 16);
     (*func)(ecount_buf, ecount_buf, 1, key, ivec);
     ++ctr32;
     PUTU32(ivec + 12, ctr32);
diff --git a/src/crypto/modes/gcm.c b/src/crypto/modes/gcm.c
index 65451a6..1330ad6 100644
--- a/src/crypto/modes/gcm.c
+++ b/src/crypto/modes/gcm.c
@@ -55,34 +55,28 @@
 #include <openssl/cpu.h>
 
 #include "internal.h"
+#include "../internal.h"
 
 
 #if !defined(OPENSSL_NO_ASM) &&                         \
     (defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \
-     defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64))
+     defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64) || \
+     defined(OPENSSL_PPC64LE))
 #define GHASH_ASM
 #endif
 
-#if defined(BSWAP4) && STRICT_ALIGNMENT == 1
-/* redefine, because alignment is ensured */
-#undef GETU32
-#define GETU32(p) BSWAP4(*(const uint32_t *)(p))
-#undef PUTU32
-#define PUTU32(p, v) *(uint32_t *)(p) = BSWAP4(v)
-#endif
-
 #define PACK(s) ((size_t)(s) << (sizeof(size_t) * 8 - 16))
-#define REDUCE1BIT(V)                                                  \
-  do {                                                                 \
-    if (sizeof(size_t) == 8) {                                         \
-      uint64_t T = UINT64_C(0xe100000000000000) & (0 - (V.lo & 1)); \
-      V.lo = (V.hi << 63) | (V.lo >> 1);                               \
-      V.hi = (V.hi >> 1) ^ T;                                          \
-    } else {                                                           \
-      uint32_t T = 0xe1000000U & (0 - (uint32_t)(V.lo & 1));           \
-      V.lo = (V.hi << 63) | (V.lo >> 1);                               \
-      V.hi = (V.hi >> 1) ^ ((uint64_t)T << 32);                        \
-    }                                                                  \
+#define REDUCE1BIT(V)                                                 \
+  do {                                                                \
+    if (sizeof(size_t) == 8) {                                        \
+      uint64_t T = UINT64_C(0xe100000000000000) & (0 - ((V).lo & 1)); \
+      (V).lo = ((V).hi << 63) | ((V).lo >> 1);                        \
+      (V).hi = ((V).hi >> 1) ^ T;                                     \
+    } else {                                                          \
+      uint32_t T = 0xe1000000U & (0 - (uint32_t)((V).lo & 1));        \
+      (V).lo = ((V).hi << 63) | ((V).lo >> 1);                        \
+      (V).hi = ((V).hi >> 1) ^ ((uint64_t)T << 32);                   \
+    }                                                                 \
   } while (0)
 
 // kSizeTWithoutLower4Bits is a mask that can be used to zero the lower four
@@ -119,32 +113,15 @@
   Htable[15].hi = V.hi ^ Htable[7].hi, Htable[15].lo = V.lo ^ Htable[7].lo;
 
 #if defined(GHASH_ASM) && defined(OPENSSL_ARM)
-  /* ARM assembler expects specific dword order in Htable. */
-  {
-    int j;
-    const union {
-      long one;
-      char little;
-    } is_endian = {1};
-
-    if (is_endian.little) {
-      for (j = 0; j < 16; ++j) {
-        V = Htable[j];
-        Htable[j].hi = V.lo;
-        Htable[j].lo = V.hi;
-      }
-    } else {
-      for (j = 0; j < 16; ++j) {
-        V = Htable[j];
-        Htable[j].hi = V.lo << 32 | V.lo >> 32;
-        Htable[j].lo = V.hi << 32 | V.hi >> 32;
-      }
-    }
+  for (int j = 0; j < 16; ++j) {
+    V = Htable[j];
+    Htable[j].hi = V.lo;
+    Htable[j].lo = V.hi;
   }
 #endif
 }
 
-#if !defined(GHASH_ASM) || defined(OPENSSL_AARCH64)
+#if !defined(GHASH_ASM) || defined(OPENSSL_AARCH64) || defined(OPENSSL_PPC64LE)
 static const size_t rem_4bit[16] = {
     PACK(0x0000), PACK(0x1C20), PACK(0x3840), PACK(0x2460),
     PACK(0x7080), PACK(0x6CA0), PACK(0x48C0), PACK(0x54E0),
@@ -155,10 +132,6 @@
   u128 Z;
   int cnt = 15;
   size_t rem, nlo, nhi;
-  const union {
-    long one;
-    char little;
-  } is_endian = {1};
 
   nlo = ((const uint8_t *)Xi)[15];
   nhi = nlo >> 4;
@@ -201,26 +174,8 @@
     Z.lo ^= Htable[nlo].lo;
   }
 
-  if (is_endian.little) {
-#ifdef BSWAP8
-    Xi[0] = BSWAP8(Z.hi);
-    Xi[1] = BSWAP8(Z.lo);
-#else
-    uint8_t *p = (uint8_t *)Xi;
-    uint32_t v;
-    v = (uint32_t)(Z.hi >> 32);
-    PUTU32(p, v);
-    v = (uint32_t)(Z.hi);
-    PUTU32(p + 4, v);
-    v = (uint32_t)(Z.lo >> 32);
-    PUTU32(p + 8, v);
-    v = (uint32_t)(Z.lo);
-    PUTU32(p + 12, v);
-#endif
-  } else {
-    Xi[0] = Z.hi;
-    Xi[1] = Z.lo;
-  }
+  Xi[0] = CRYPTO_bswap8(Z.hi);
+  Xi[1] = CRYPTO_bswap8(Z.lo);
 }
 
 /* Streamed gcm_mult_4bit, see CRYPTO_gcm128_[en|de]crypt for
@@ -228,15 +183,11 @@
  * performance improvement, at least not on x86[_64]. It's here
  * mostly as reference and a placeholder for possible future
  * non-trivial optimization[s]... */
-static void gcm_ghash_4bit(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp,
-                           size_t len) {
+static void gcm_ghash_4bit(uint64_t Xi[2], const u128 Htable[16],
+                           const uint8_t *inp, size_t len) {
   u128 Z;
   int cnt;
   size_t rem, nlo, nhi;
-  const union {
-    long one;
-    char little;
-  } is_endian = {1};
 
   do {
     cnt = 15;
@@ -283,26 +234,8 @@
       Z.lo ^= Htable[nlo].lo;
     }
 
-    if (is_endian.little) {
-#ifdef BSWAP8
-      Xi[0] = BSWAP8(Z.hi);
-      Xi[1] = BSWAP8(Z.lo);
-#else
-      uint8_t *p = (uint8_t *)Xi;
-      uint32_t v;
-      v = (uint32_t)(Z.hi >> 32);
-      PUTU32(p, v);
-      v = (uint32_t)(Z.hi);
-      PUTU32(p + 4, v);
-      v = (uint32_t)(Z.lo >> 32);
-      PUTU32(p + 8, v);
-      v = (uint32_t)(Z.lo);
-      PUTU32(p + 12, v);
-#endif
-    } else {
-      Xi[0] = Z.hi;
-      Xi[1] = Z.lo;
-    }
+    Xi[0] = CRYPTO_bswap8(Z.hi);
+    Xi[1] = CRYPTO_bswap8(Z.lo);
   } while (inp += 16, len -= 16);
 }
 #else /* GHASH_ASM */
@@ -311,7 +244,7 @@
                     size_t len);
 #endif
 
-#define GCM_MUL(ctx, Xi) gcm_gmult_4bit(ctx->Xi.u, ctx->Htable)
+#define GCM_MUL(ctx, Xi) gcm_gmult_4bit((ctx)->Xi.u, (ctx)->Htable)
 #if defined(GHASH_ASM)
 #define GHASH(ctx, in, len) gcm_ghash_4bit((ctx)->Xi.u, (ctx)->Htable, in, len)
 /* GHASH_CHUNK is "stride parameter" missioned to mitigate cache
@@ -322,22 +255,30 @@
 
 
 #if defined(GHASH_ASM)
+
 #if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
-#define GHASH_ASM_X86_OR_64
 #define GCM_FUNCREF_4BIT
 void gcm_init_clmul(u128 Htable[16], const uint64_t Xi[2]);
 void gcm_gmult_clmul(uint64_t Xi[2], const u128 Htable[16]);
 void gcm_ghash_clmul(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp,
                      size_t len);
 
-#if defined(OPENSSL_X86)
-#define gcm_init_avx gcm_init_clmul
-#define gcm_gmult_avx gcm_gmult_clmul
-#define gcm_ghash_avx gcm_ghash_clmul
-#else
+#if defined(OPENSSL_X86_64)
+#define GHASH_ASM_X86_64
 void gcm_init_avx(u128 Htable[16], const uint64_t Xi[2]);
 void gcm_gmult_avx(uint64_t Xi[2], const u128 Htable[16]);
-void gcm_ghash_avx(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp, size_t len);
+void gcm_ghash_avx(uint64_t Xi[2], const u128 Htable[16], const uint8_t *in,
+                   size_t len);
+#define AESNI_GCM
+static int aesni_gcm_enabled(GCM128_CONTEXT *ctx, ctr128_f stream) {
+  return stream == aesni_ctr32_encrypt_blocks &&
+         ctx->ghash == gcm_ghash_avx;
+}
+
+size_t aesni_gcm_encrypt(const uint8_t *in, uint8_t *out, size_t len,
+                         const void *key, uint8_t ivec[16], uint64_t *Xi);
+size_t aesni_gcm_decrypt(const uint8_t *in, uint8_t *out, size_t len,
+                         const void *key, uint8_t ivec[16], uint64_t *Xi);
 #endif
 
 #if defined(OPENSSL_X86)
@@ -345,11 +286,8 @@
 void gcm_gmult_4bit_mmx(uint64_t Xi[2], const u128 Htable[16]);
 void gcm_ghash_4bit_mmx(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp,
                         size_t len);
-
-void gcm_gmult_4bit_x86(uint64_t Xi[2], const u128 Htable[16]);
-void gcm_ghash_4bit_x86(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp,
-                        size_t len);
 #endif
+
 #elif defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)
 #include <openssl/arm_arch.h>
 #if __ARM_ARCH__ >= 7
@@ -380,122 +318,121 @@
 static int neon_capable(void) {
   return 0;
 }
-void gcm_init_neon(u128 Htable[16], const uint64_t Xi[2]) {
+static void gcm_init_neon(u128 Htable[16], const uint64_t Xi[2]) {
   abort();
 }
-void gcm_gmult_neon(uint64_t Xi[2], const u128 Htable[16]) {
+static void gcm_gmult_neon(uint64_t Xi[2], const u128 Htable[16]) {
   abort();
 }
-void gcm_ghash_neon(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp,
-                    size_t len) {
+static void gcm_ghash_neon(uint64_t Xi[2], const u128 Htable[16],
+                           const uint8_t *inp, size_t len) {
   abort();
 }
 #endif
 
 #endif
+#elif defined(OPENSSL_PPC64LE)
+#define GHASH_ASM_PPC64LE
+#define GCM_FUNCREF_4BIT
+void gcm_init_p8(u128 Htable[16], const uint64_t Xi[2]);
+void gcm_gmult_p8(uint64_t Xi[2], const u128 Htable[16]);
+void gcm_ghash_p8(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp,
+                  size_t len);
 #endif
 #endif
 
 #ifdef GCM_FUNCREF_4BIT
 #undef GCM_MUL
-#define GCM_MUL(ctx, Xi) (*gcm_gmult_p)(ctx->Xi.u, ctx->Htable)
+#define GCM_MUL(ctx, Xi) (*gcm_gmult_p)((ctx)->Xi.u, (ctx)->Htable)
 #ifdef GHASH
 #undef GHASH
-#define GHASH(ctx, in, len) (*gcm_ghash_p)(ctx->Xi.u, ctx->Htable, in, len)
+#define GHASH(ctx, in, len) (*gcm_ghash_p)((ctx)->Xi.u, (ctx)->Htable, in, len)
 #endif
 #endif
 
-GCM128_CONTEXT *CRYPTO_gcm128_new(const void *key, block128_f block) {
-  GCM128_CONTEXT *ret;
+void CRYPTO_ghash_init(gmult_func *out_mult, ghash_func *out_hash,
+                       u128 *out_key, u128 out_table[16],
+                       const uint8_t *gcm_key) {
+  union {
+    uint64_t u[2];
+    uint8_t c[16];
+  } H;
 
-  ret = (GCM128_CONTEXT *)OPENSSL_malloc(sizeof(GCM128_CONTEXT));
-  if (ret != NULL) {
-    CRYPTO_gcm128_init(ret, key, block);
-  }
+  OPENSSL_memcpy(H.c, gcm_key, 16);
 
-  return ret;
-}
+  /* H is stored in host byte order */
+  H.u[0] = CRYPTO_bswap8(H.u[0]);
+  H.u[1] = CRYPTO_bswap8(H.u[1]);
 
-void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, const void *key,
-                        block128_f block) {
-  const union {
-    long one;
-    char little;
-  } is_endian = {1};
+  OPENSSL_memcpy(out_key, H.c, 16);
 
-  memset(ctx, 0, sizeof(*ctx));
-  ctx->block = block;
-
-  (*block)(ctx->H.c, ctx->H.c, key);
-
-  if (is_endian.little) {
-/* H is stored in host byte order */
-#ifdef BSWAP8
-    ctx->H.u[0] = BSWAP8(ctx->H.u[0]);
-    ctx->H.u[1] = BSWAP8(ctx->H.u[1]);
-#else
-    uint8_t *p = ctx->H.c;
-    uint64_t hi, lo;
-    hi = (uint64_t)GETU32(p) << 32 | GETU32(p + 4);
-    lo = (uint64_t)GETU32(p + 8) << 32 | GETU32(p + 12);
-    ctx->H.u[0] = hi;
-    ctx->H.u[1] = lo;
-#endif
-  }
-
-#if defined(GHASH_ASM_X86_OR_64)
+#if defined(GHASH_ASM_X86_64)
   if (crypto_gcm_clmul_enabled()) {
     if (((OPENSSL_ia32cap_P[1] >> 22) & 0x41) == 0x41) { /* AVX+MOVBE */
-      gcm_init_avx(ctx->Htable, ctx->H.u);
-      ctx->gmult = gcm_gmult_avx;
-      ctx->ghash = gcm_ghash_avx;
-    } else {
-      gcm_init_clmul(ctx->Htable, ctx->H.u);
-      ctx->gmult = gcm_gmult_clmul;
-      ctx->ghash = gcm_ghash_clmul;
+      gcm_init_avx(out_table, H.u);
+      *out_mult = gcm_gmult_avx;
+      *out_hash = gcm_ghash_avx;
+      return;
     }
+    gcm_init_clmul(out_table, H.u);
+    *out_mult = gcm_gmult_clmul;
+    *out_hash = gcm_ghash_clmul;
     return;
   }
-  gcm_init_4bit(ctx->Htable, ctx->H.u);
-#if defined(GHASH_ASM_X86) /* x86 only */
-  if (OPENSSL_ia32cap_P[0] & (1 << 25)) { /* check SSE bit */
-    ctx->gmult = gcm_gmult_4bit_mmx;
-    ctx->ghash = gcm_ghash_4bit_mmx;
-  } else {
-    ctx->gmult = gcm_gmult_4bit_x86;
-    ctx->ghash = gcm_ghash_4bit_x86;
+#elif defined(GHASH_ASM_X86)
+  if (crypto_gcm_clmul_enabled()) {
+    gcm_init_clmul(out_table, H.u);
+    *out_mult = gcm_gmult_clmul;
+    *out_hash = gcm_ghash_clmul;
+    return;
   }
-#else
-  ctx->gmult = gcm_gmult_4bit;
-  ctx->ghash = gcm_ghash_4bit;
-#endif
 #elif defined(GHASH_ASM_ARM)
   if (pmull_capable()) {
-    gcm_init_v8(ctx->Htable, ctx->H.u);
-    ctx->gmult = gcm_gmult_v8;
-    ctx->ghash = gcm_ghash_v8;
-  } else if (neon_capable()) {
-    gcm_init_neon(ctx->Htable,ctx->H.u);
-    ctx->gmult = gcm_gmult_neon;
-    ctx->ghash = gcm_ghash_neon;
-  } else {
-    gcm_init_4bit(ctx->Htable, ctx->H.u);
-    ctx->gmult = gcm_gmult_4bit;
-    ctx->ghash = gcm_ghash_4bit;
+    gcm_init_v8(out_table, H.u);
+    *out_mult = gcm_gmult_v8;
+    *out_hash = gcm_ghash_v8;
+    return;
   }
-#else
-  gcm_init_4bit(ctx->Htable, ctx->H.u);
-  ctx->gmult = gcm_gmult_4bit;
-  ctx->ghash = gcm_ghash_4bit;
+
+  if (neon_capable()) {
+    gcm_init_neon(out_table, H.u);
+    *out_mult = gcm_gmult_neon;
+    *out_hash = gcm_ghash_neon;
+    return;
+  }
+#elif defined(GHASH_ASM_PPC64LE)
+  if (CRYPTO_is_PPC64LE_vcrypto_capable()) {
+    gcm_init_p8(out_table, H.u);
+    *out_mult = gcm_gmult_p8;
+    *out_hash = gcm_ghash_p8;
+    return;
+  }
 #endif
+
+  gcm_init_4bit(out_table, H.u);
+#if defined(GHASH_ASM_X86)
+  *out_mult = gcm_gmult_4bit_mmx;
+  *out_hash = gcm_ghash_4bit_mmx;
+#else
+  *out_mult = gcm_gmult_4bit;
+  *out_hash = gcm_ghash_4bit;
+#endif
+}
+
+void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, const void *aes_key,
+                        block128_f block) {
+  OPENSSL_memset(ctx, 0, sizeof(*ctx));
+  ctx->block = block;
+
+  uint8_t gcm_key[16];
+  OPENSSL_memset(gcm_key, 0, sizeof(gcm_key));
+  (*block)(gcm_key, gcm_key, aes_key);
+
+  CRYPTO_ghash_init(&ctx->gmult, &ctx->ghash, &ctx->H, ctx->Htable, gcm_key);
 }
 
 void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx, const void *key,
                          const uint8_t *iv, size_t len) {
-  const union {
-    long one;
-    char little;
-  } is_endian = {1};
   unsigned int ctr;
 #ifdef GCM_FUNCREF_4BIT
   void (*gcm_gmult_p)(uint64_t Xi[2], const u128 Htable[16]) = ctx->gmult;
@@ -511,15 +448,14 @@
   ctx->mres = 0;
 
   if (len == 12) {
-    memcpy(ctx->Yi.c, iv, 12);
+    OPENSSL_memcpy(ctx->Yi.c, iv, 12);
     ctx->Yi.c[15] = 1;
     ctr = 1;
   } else {
-    size_t i;
     uint64_t len0 = len;
 
     while (len >= 16) {
-      for (i = 0; i < 16; ++i) {
+      for (size_t i = 0; i < 16; ++i) {
         ctx->Yi.c[i] ^= iv[i];
       }
       GCM_MUL(ctx, Yi);
@@ -527,49 +463,24 @@
       len -= 16;
     }
     if (len) {
-      for (i = 0; i < len; ++i) {
+      for (size_t i = 0; i < len; ++i) {
         ctx->Yi.c[i] ^= iv[i];
       }
       GCM_MUL(ctx, Yi);
     }
     len0 <<= 3;
-    if (is_endian.little) {
-#ifdef BSWAP8
-      ctx->Yi.u[1] ^= BSWAP8(len0);
-#else
-      ctx->Yi.c[8] ^= (uint8_t)(len0 >> 56);
-      ctx->Yi.c[9] ^= (uint8_t)(len0 >> 48);
-      ctx->Yi.c[10] ^= (uint8_t)(len0 >> 40);
-      ctx->Yi.c[11] ^= (uint8_t)(len0 >> 32);
-      ctx->Yi.c[12] ^= (uint8_t)(len0 >> 24);
-      ctx->Yi.c[13] ^= (uint8_t)(len0 >> 16);
-      ctx->Yi.c[14] ^= (uint8_t)(len0 >> 8);
-      ctx->Yi.c[15] ^= (uint8_t)(len0);
-#endif
-    } else {
-      ctx->Yi.u[1] ^= len0;
-    }
+    ctx->Yi.u[1] ^= CRYPTO_bswap8(len0);
 
     GCM_MUL(ctx, Yi);
-
-    if (is_endian.little) {
-      ctr = GETU32(ctx->Yi.c + 12);
-    } else {
-      ctr = ctx->Yi.d[3];
-    }
+    ctr = GETU32_aligned(ctx->Yi.c + 12);
   }
 
   (*ctx->block)(ctx->Yi.c, ctx->EK0.c, key);
   ++ctr;
-  if (is_endian.little) {
-    PUTU32(ctx->Yi.c + 12, ctr);
-  } else {
-    ctx->Yi.d[3] = ctr;
-  }
+  PUTU32_aligned(ctx->Yi.c + 12, ctr);
 }
 
 int CRYPTO_gcm128_aad(GCM128_CONTEXT *ctx, const uint8_t *aad, size_t len) {
-  size_t i;
   unsigned int n;
   uint64_t alen = ctx->len.u[0];
 #ifdef GCM_FUNCREF_4BIT
@@ -605,15 +516,17 @@
     }
   }
 
+  /* Process a whole number of blocks. */
 #ifdef GHASH
-  if ((i = (len & (size_t) - 16))) {
-    GHASH(ctx, aad, i);
-    aad += i;
-    len -= i;
+  size_t len_blocks = len & kSizeTWithoutLower4Bits;
+  if (len_blocks != 0) {
+    GHASH(ctx, aad, len_blocks);
+    aad += len_blocks;
+    len -= len_blocks;
   }
 #else
   while (len >= 16) {
-    for (i = 0; i < 16; ++i) {
+    for (size_t i = 0; i < 16; ++i) {
       ctx->Xi.c[i] ^= aad[i];
     }
     GCM_MUL(ctx, Xi);
@@ -621,9 +534,11 @@
     len -= 16;
   }
 #endif
-  if (len) {
+
+  /* Process the remainder. */
+  if (len != 0) {
     n = (unsigned int)len;
-    for (i = 0; i < len; ++i) {
+    for (size_t i = 0; i < len; ++i) {
       ctx->Xi.c[i] ^= aad[i];
     }
   }
@@ -635,12 +550,7 @@
 int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx, const void *key,
                           const unsigned char *in, unsigned char *out,
                           size_t len) {
-  const union {
-    long one;
-    char little;
-  } is_endian = {1};
   unsigned int n, ctr;
-  size_t i;
   uint64_t mlen = ctx->len.u[1];
   block128_f block = ctx->block;
 #ifdef GCM_FUNCREF_4BIT
@@ -664,11 +574,7 @@
     ctx->ares = 0;
   }
 
-  if (is_endian.little) {
-    ctr = GETU32(ctx->Yi.c + 12);
-  } else {
-    ctr = ctx->Yi.d[3];
-  }
+  ctr = GETU32_aligned(ctx->Yi.c + 12);
 
   n = ctx->mres;
   if (n) {
@@ -685,15 +591,11 @@
     }
   }
   if (STRICT_ALIGNMENT && ((size_t)in | (size_t)out) % sizeof(size_t) != 0) {
-    for (i = 0; i < len; ++i) {
+    for (size_t i = 0; i < len; ++i) {
       if (n == 0) {
         (*block)(ctx->Yi.c, ctx->EKi.c, key);
         ++ctr;
-        if (is_endian.little) {
-          PUTU32(ctx->Yi.c + 12, ctr);
-        } else {
-          ctx->Yi.d[3] = ctr;
-        }
+        PUTU32_aligned(ctx->Yi.c + 12, ctr);
       }
       ctx->Xi.c[n] ^= out[i] = in[i] ^ ctx->EKi.c[n];
       n = (n + 1) % 16;
@@ -715,12 +617,8 @@
 
       (*block)(ctx->Yi.c, ctx->EKi.c, key);
       ++ctr;
-      if (is_endian.little) {
-        PUTU32(ctx->Yi.c + 12, ctr);
-      } else {
-        ctx->Yi.d[3] = ctr;
-      }
-      for (i = 0; i < 16 / sizeof(size_t); ++i) {
+      PUTU32_aligned(ctx->Yi.c + 12, ctr);
+      for (size_t i = 0; i < 16 / sizeof(size_t); ++i) {
         out_t[i] = in_t[i] ^ ctx->EKi.t[i];
       }
       out += 16;
@@ -730,28 +628,23 @@
     GHASH(ctx, out - GHASH_CHUNK, GHASH_CHUNK);
     len -= GHASH_CHUNK;
   }
-  if ((i = (len & (size_t) - 16))) {
-    size_t j = i;
-
+  size_t len_blocks = len & kSizeTWithoutLower4Bits;
+  if (len_blocks != 0) {
     while (len >= 16) {
       size_t *out_t = (size_t *)out;
       const size_t *in_t = (const size_t *)in;
 
       (*block)(ctx->Yi.c, ctx->EKi.c, key);
       ++ctr;
-      if (is_endian.little) {
-        PUTU32(ctx->Yi.c + 12, ctr);
-      } else {
-        ctx->Yi.d[3] = ctr;
-      }
-      for (i = 0; i < 16 / sizeof(size_t); ++i) {
+      PUTU32_aligned(ctx->Yi.c + 12, ctr);
+      for (size_t i = 0; i < 16 / sizeof(size_t); ++i) {
         out_t[i] = in_t[i] ^ ctx->EKi.t[i];
       }
       out += 16;
       in += 16;
       len -= 16;
     }
-    GHASH(ctx, out - j, j);
+    GHASH(ctx, out - len_blocks, len_blocks);
   }
 #else
   while (len >= 16) {
@@ -760,12 +653,8 @@
 
     (*block)(ctx->Yi.c, ctx->EKi.c, key);
     ++ctr;
-    if (is_endian.little) {
-      PUTU32(ctx->Yi.c + 12, ctr);
-    } else {
-      ctx->Yi.d[3] = ctr;
-    }
-    for (i = 0; i < 16 / sizeof(size_t); ++i) {
+    PUTU32_aligned(ctx->Yi.c + 12, ctr);
+    for (size_t i = 0; i < 16 / sizeof(size_t); ++i) {
       ctx->Xi.t[i] ^= out_t[i] = in_t[i] ^ ctx->EKi.t[i];
     }
     GCM_MUL(ctx, Xi);
@@ -777,11 +666,7 @@
   if (len) {
     (*block)(ctx->Yi.c, ctx->EKi.c, key);
     ++ctr;
-    if (is_endian.little) {
-      PUTU32(ctx->Yi.c + 12, ctr);
-    } else {
-      ctx->Yi.d[3] = ctr;
-    }
+    PUTU32_aligned(ctx->Yi.c + 12, ctr);
     while (len--) {
       ctx->Xi.c[n] ^= out[n] = in[n] ^ ctx->EKi.c[n];
       ++n;
@@ -795,12 +680,7 @@
 int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, const void *key,
                           const unsigned char *in, unsigned char *out,
                           size_t len) {
-  const union {
-    long one;
-    char little;
-  } is_endian = {1};
   unsigned int n, ctr;
-  size_t i;
   uint64_t mlen = ctx->len.u[1];
   block128_f block = ctx->block;
 #ifdef GCM_FUNCREF_4BIT
@@ -824,11 +704,7 @@
     ctx->ares = 0;
   }
 
-  if (is_endian.little) {
-    ctr = GETU32(ctx->Yi.c + 12);
-  } else {
-    ctr = ctx->Yi.d[3];
-  }
+  ctr = GETU32_aligned(ctx->Yi.c + 12);
 
   n = ctx->mres;
   if (n) {
@@ -847,16 +723,12 @@
     }
   }
   if (STRICT_ALIGNMENT && ((size_t)in | (size_t)out) % sizeof(size_t) != 0) {
-    for (i = 0; i < len; ++i) {
+    for (size_t i = 0; i < len; ++i) {
       uint8_t c;
       if (n == 0) {
         (*block)(ctx->Yi.c, ctx->EKi.c, key);
         ++ctr;
-        if (is_endian.little) {
-          PUTU32(ctx->Yi.c + 12, ctr);
-        } else {
-          ctx->Yi.d[3] = ctr;
-        }
+        PUTU32_aligned(ctx->Yi.c + 12, ctr);
       }
       c = in[i];
       out[i] = c ^ ctx->EKi.c[n];
@@ -881,12 +753,8 @@
 
       (*block)(ctx->Yi.c, ctx->EKi.c, key);
       ++ctr;
-      if (is_endian.little) {
-        PUTU32(ctx->Yi.c + 12, ctr);
-      } else {
-        ctx->Yi.d[3] = ctr;
-      }
-      for (i = 0; i < 16 / sizeof(size_t); ++i) {
+      PUTU32_aligned(ctx->Yi.c + 12, ctr);
+      for (size_t i = 0; i < 16 / sizeof(size_t); ++i) {
         out_t[i] = in_t[i] ^ ctx->EKi.t[i];
       }
       out += 16;
@@ -895,20 +763,17 @@
     }
     len -= GHASH_CHUNK;
   }
-  if ((i = (len & (size_t) - 16))) {
-    GHASH(ctx, in, i);
+  size_t len_blocks = len & kSizeTWithoutLower4Bits;
+  if (len_blocks != 0) {
+    GHASH(ctx, in, len_blocks);
     while (len >= 16) {
       size_t *out_t = (size_t *)out;
       const size_t *in_t = (const size_t *)in;
 
       (*block)(ctx->Yi.c, ctx->EKi.c, key);
       ++ctr;
-      if (is_endian.little) {
-        PUTU32(ctx->Yi.c + 12, ctr);
-      } else {
-        ctx->Yi.d[3] = ctr;
-      }
-      for (i = 0; i < 16 / sizeof(size_t); ++i) {
+      PUTU32_aligned(ctx->Yi.c + 12, ctr);
+      for (size_t i = 0; i < 16 / sizeof(size_t); ++i) {
         out_t[i] = in_t[i] ^ ctx->EKi.t[i];
       }
       out += 16;
@@ -923,12 +788,8 @@
 
     (*block)(ctx->Yi.c, ctx->EKi.c, key);
     ++ctr;
-    if (is_endian.little) {
-      PUTU32(ctx->Yi.c + 12, ctr);
-    } else {
-      ctx->Yi.d[3] = ctr;
-    }
-    for (i = 0; i < 16 / sizeof(size_t); ++i) {
+    PUTU32_aligned(ctx->Yi.c + 12, ctr);
+    for (size_t i = 0; i < 16 / sizeof(size_t); ++i) {
       size_t c = in_t[i];
       out_t[i] = c ^ ctx->EKi.t[i];
       ctx->Xi.t[i] ^= c;
@@ -942,11 +803,7 @@
   if (len) {
     (*block)(ctx->Yi.c, ctx->EKi.c, key);
     ++ctr;
-    if (is_endian.little) {
-      PUTU32(ctx->Yi.c + 12, ctr);
-    } else {
-      ctx->Yi.d[3] = ctr;
-    }
+    PUTU32_aligned(ctx->Yi.c + 12, ctr);
     while (len--) {
       uint8_t c = in[n];
       ctx->Xi.c[n] ^= c;
@@ -962,10 +819,6 @@
 int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx, const void *key,
                                 const uint8_t *in, uint8_t *out, size_t len,
                                 ctr128_f stream) {
-  const union {
-    long one;
-    char little;
-  } is_endian = {1};
   unsigned int n, ctr;
   uint64_t mlen = ctx->len.u[1];
 #ifdef GCM_FUNCREF_4BIT
@@ -989,12 +842,6 @@
     ctx->ares = 0;
   }
 
-  if (is_endian.little) {
-    ctr = GETU32(ctx->Yi.c + 12);
-  } else {
-    ctr = ctx->Yi.d[3];
-  }
-
   n = ctx->mres;
   if (n) {
     while (n && len) {
@@ -1009,15 +856,25 @@
       return 1;
     }
   }
+
+#if defined(AESNI_GCM)
+  if (aesni_gcm_enabled(ctx, stream)) {
+    /* |aesni_gcm_encrypt| may not process all the input given to it. It may
+     * not process *any* of its input if it is deemed too small. */
+    size_t bulk = aesni_gcm_encrypt(in, out, len, key, ctx->Yi.c, ctx->Xi.u);
+    in += bulk;
+    out += bulk;
+    len -= bulk;
+  }
+#endif
+
+  ctr = GETU32_aligned(ctx->Yi.c + 12);
+
 #if defined(GHASH)
   while (len >= GHASH_CHUNK) {
     (*stream)(in, out, GHASH_CHUNK / 16, key, ctx->Yi.c);
     ctr += GHASH_CHUNK / 16;
-    if (is_endian.little) {
-      PUTU32(ctx->Yi.c + 12, ctr);
-    } else {
-      ctx->Yi.d[3] = ctr;
-    }
+    PUTU32_aligned(ctx->Yi.c + 12, ctr);
     GHASH(ctx, out, GHASH_CHUNK);
     out += GHASH_CHUNK;
     in += GHASH_CHUNK;
@@ -1030,11 +887,7 @@
 
     (*stream)(in, out, j, key, ctx->Yi.c);
     ctr += (unsigned int)j;
-    if (is_endian.little) {
-      PUTU32(ctx->Yi.c + 12, ctr);
-    } else {
-      ctx->Yi.d[3] = ctr;
-    }
+    PUTU32_aligned(ctx->Yi.c + 12, ctr);
     in += i;
     len -= i;
 #if defined(GHASH)
@@ -1053,11 +906,7 @@
   if (len) {
     (*ctx->block)(ctx->Yi.c, ctx->EKi.c, key);
     ++ctr;
-    if (is_endian.little) {
-      PUTU32(ctx->Yi.c + 12, ctr);
-    } else {
-      ctx->Yi.d[3] = ctr;
-    }
+    PUTU32_aligned(ctx->Yi.c + 12, ctr);
     while (len--) {
       ctx->Xi.c[n] ^= out[n] = in[n] ^ ctx->EKi.c[n];
       ++n;
@@ -1071,10 +920,6 @@
 int CRYPTO_gcm128_decrypt_ctr32(GCM128_CONTEXT *ctx, const void *key,
                                 const uint8_t *in, uint8_t *out, size_t len,
                                 ctr128_f stream) {
-  const union {
-    long one;
-    char little;
-  } is_endian = {1};
   unsigned int n, ctr;
   uint64_t mlen = ctx->len.u[1];
 #ifdef GCM_FUNCREF_4BIT
@@ -1098,12 +943,6 @@
     ctx->ares = 0;
   }
 
-  if (is_endian.little) {
-    ctr = GETU32(ctx->Yi.c + 12);
-  } else {
-    ctr = ctx->Yi.d[3];
-  }
-
   n = ctx->mres;
   if (n) {
     while (n && len) {
@@ -1120,16 +959,26 @@
       return 1;
     }
   }
+
+#if defined(AESNI_GCM)
+  if (aesni_gcm_enabled(ctx, stream)) {
+    /* |aesni_gcm_decrypt| may not process all the input given to it. It may
+     * not process *any* of its input if it is deemed too small. */
+    size_t bulk = aesni_gcm_decrypt(in, out, len, key, ctx->Yi.c, ctx->Xi.u);
+    in += bulk;
+    out += bulk;
+    len -= bulk;
+  }
+#endif
+
+  ctr = GETU32_aligned(ctx->Yi.c + 12);
+
 #if defined(GHASH)
   while (len >= GHASH_CHUNK) {
     GHASH(ctx, in, GHASH_CHUNK);
     (*stream)(in, out, GHASH_CHUNK / 16, key, ctx->Yi.c);
     ctr += GHASH_CHUNK / 16;
-    if (is_endian.little) {
-      PUTU32(ctx->Yi.c + 12, ctr);
-    } else {
-      ctx->Yi.d[3] = ctr;
-    }
+    PUTU32_aligned(ctx->Yi.c + 12, ctr);
     out += GHASH_CHUNK;
     in += GHASH_CHUNK;
     len -= GHASH_CHUNK;
@@ -1155,11 +1004,7 @@
 #endif
     (*stream)(in, out, j, key, ctx->Yi.c);
     ctr += (unsigned int)j;
-    if (is_endian.little) {
-      PUTU32(ctx->Yi.c + 12, ctr);
-    } else {
-      ctx->Yi.d[3] = ctr;
-    }
+    PUTU32_aligned(ctx->Yi.c + 12, ctr);
     out += i;
     in += i;
     len -= i;
@@ -1167,11 +1012,7 @@
   if (len) {
     (*ctx->block)(ctx->Yi.c, ctx->EKi.c, key);
     ++ctr;
-    if (is_endian.little) {
-      PUTU32(ctx->Yi.c + 12, ctr);
-    } else {
-      ctx->Yi.d[3] = ctr;
-    }
+    PUTU32_aligned(ctx->Yi.c + 12, ctr);
     while (len--) {
       uint8_t c = in[n];
       ctx->Xi.c[n] ^= c;
@@ -1185,10 +1026,6 @@
 }
 
 int CRYPTO_gcm128_finish(GCM128_CONTEXT *ctx, const uint8_t *tag, size_t len) {
-  const union {
-    long one;
-    char little;
-  } is_endian = {1};
   uint64_t alen = ctx->len.u[0] << 3;
   uint64_t clen = ctx->len.u[1] << 3;
 #ifdef GCM_FUNCREF_4BIT
@@ -1199,20 +1036,8 @@
     GCM_MUL(ctx, Xi);
   }
 
-  if (is_endian.little) {
-#ifdef BSWAP8
-    alen = BSWAP8(alen);
-    clen = BSWAP8(clen);
-#else
-    uint8_t *p = ctx->len.c;
-
-    ctx->len.u[0] = alen;
-    ctx->len.u[1] = clen;
-
-    alen = (uint64_t)GETU32(p) << 32 | GETU32(p + 4);
-    clen = (uint64_t)GETU32(p + 8) << 32 | GETU32(p + 12);
-#endif
-  }
+  alen = CRYPTO_bswap8(alen);
+  clen = CRYPTO_bswap8(clen);
 
   ctx->Xi.u[0] ^= alen;
   ctx->Xi.u[1] ^= clen;
@@ -1230,14 +1055,8 @@
 
 void CRYPTO_gcm128_tag(GCM128_CONTEXT *ctx, unsigned char *tag, size_t len) {
   CRYPTO_gcm128_finish(ctx, NULL, 0);
-  memcpy(tag, ctx->Xi.c, len <= sizeof(ctx->Xi.c) ? len : sizeof(ctx->Xi.c));
-}
-
-void CRYPTO_gcm128_release(GCM128_CONTEXT *ctx) {
-  if (ctx) {
-    OPENSSL_cleanse(ctx, sizeof(*ctx));
-    OPENSSL_free(ctx);
-  }
+  OPENSSL_memcpy(tag, ctx->Xi.c,
+                 len <= sizeof(ctx->Xi.c) ? len : sizeof(ctx->Xi.c));
 }
 
 #if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
diff --git a/src/crypto/modes/gcm_test.c b/src/crypto/modes/gcm_test.cc
similarity index 93%
rename from src/crypto/modes/gcm_test.c
rename to src/crypto/modes/gcm_test.cc
index 9414ac6..1a5e034 100644
--- a/src/crypto/modes/gcm_test.c
+++ b/src/crypto/modes/gcm_test.cc
@@ -46,6 +46,13 @@
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  * ==================================================================== */
 
+/* Per C99, various stdint.h and inttypes.h macros (the latter used by
+ * internal.h) are unavailable in C++ unless some macros are defined. C++11
+ * overruled this decision, but older Android NDKs still require it. */
+#if !defined(__STDC_CONSTANT_MACROS)
+#define __STDC_CONSTANT_MACROS
+#endif
+
 #include <stdio.h>
 #include <string.h>
 
@@ -257,9 +264,6 @@
 
 static int decode_hex(uint8_t **out, size_t *out_len, const char *in,
                       unsigned test_num, const char *description) {
-  uint8_t *buf = NULL;
-  size_t i;
-
   if (in == NULL) {
     *out = NULL;
     *out_len = 0;
@@ -269,21 +273,21 @@
   size_t len = strlen(in);
   if (len & 1) {
     fprintf(stderr, "%u: Odd-length %s input.\n", test_num, description);
-    goto err;
+    return 0;
   }
 
-  buf = OPENSSL_malloc(len / 2);
+  uint8_t *buf = reinterpret_cast<uint8_t *>(OPENSSL_malloc(len / 2));
   if (buf == NULL) {
     fprintf(stderr, "%u: malloc failure.\n", test_num);
     goto err;
   }
 
-  for (i = 0; i < len; i += 2) {
+  for (size_t i = 0; i < len; i += 2) {
     uint8_t v, v2;
     if (!from_hex(&v, in[i]) ||
         !from_hex(&v2, in[i+1])) {
-      fprintf(stderr, "%u: invalid hex digit in %s around offset %u.\n",
-              test_num, description, (unsigned)i);
+      fprintf(stderr, "%u: invalid hex digit in %s around offset %zu.\n",
+              test_num, description, i);
       goto err;
     }
     buf[i/2] = (v << 4) | v2;
@@ -335,8 +339,8 @@
     goto out;
   }
 
-  out = OPENSSL_malloc(plaintext_len);
-  if (out == NULL) {
+  out = reinterpret_cast<uint8_t *>(OPENSSL_malloc(plaintext_len));
+  if (plaintext_len != 0 && out == NULL) {
     goto out;
   }
   if (AES_set_encrypt_key(key, key_len*8, &aes_key)) {
@@ -346,7 +350,7 @@
 
   CRYPTO_gcm128_init(&ctx, &aes_key, (block128_f) AES_encrypt);
   CRYPTO_gcm128_setiv(&ctx, &aes_key, nonce, nonce_len);
-  memset(out, 0, plaintext_len);
+  OPENSSL_memset(out, 0, plaintext_len);
   if (additional_data) {
     CRYPTO_gcm128_aad(&ctx, additional_data, additional_data_len);
   }
@@ -354,7 +358,7 @@
     CRYPTO_gcm128_encrypt(&ctx, &aes_key, plaintext, out, plaintext_len);
   }
   if (!CRYPTO_gcm128_finish(&ctx, tag, tag_len) ||
-      (ciphertext && memcmp(out, ciphertext, plaintext_len) != 0)) {
+      (ciphertext && OPENSSL_memcmp(out, ciphertext, plaintext_len) != 0)) {
     fprintf(stderr, "%u: encrypt failed.\n", test_num);
     hexdump(stderr, "got :", out, plaintext_len);
     hexdump(stderr, "want:", ciphertext, plaintext_len);
@@ -362,7 +366,7 @@
   }
 
   CRYPTO_gcm128_setiv(&ctx, &aes_key, nonce, nonce_len);
-  memset(out, 0, plaintext_len);
+  OPENSSL_memset(out, 0, plaintext_len);
   if (additional_data) {
     CRYPTO_gcm128_aad(&ctx, additional_data, additional_data_len);
   }
@@ -373,7 +377,7 @@
     fprintf(stderr, "%u: decrypt failed.\n", test_num);
     goto out;
   }
-  if (plaintext && memcmp(out, plaintext, plaintext_len)) {
+  if (plaintext && OPENSSL_memcmp(out, plaintext, plaintext_len)) {
     fprintf(stderr, "%u: plaintext doesn't match.\n", test_num);
     goto out;
   }
@@ -391,12 +395,22 @@
   return ret;
 }
 
+static bool TestByteSwap() {
+  return CRYPTO_bswap4(0x01020304) == 0x04030201 &&
+         CRYPTO_bswap8(UINT64_C(0x0102030405060708)) ==
+             UINT64_C(0x0807060504030201);
+}
+
 int main(void) {
   int ret = 0;
   unsigned i;
 
   CRYPTO_library_init();
 
+  if (!TestByteSwap()) {
+    ret = 1;
+  }
+
   for (i = 0; i < sizeof(test_cases) / sizeof(struct test_case); i++) {
     if (!run_test_case(i, &test_cases[i])) {
       ret = 1;
diff --git a/src/crypto/modes/internal.h b/src/crypto/modes/internal.h
index 7255a7c..94072ec 100644
--- a/src/crypto/modes/internal.h
+++ b/src/crypto/modes/internal.h
@@ -51,6 +51,10 @@
 
 #include <openssl/base.h>
 
+#include <string.h>
+
+#include "../internal.h"
+
 #if defined(__cplusplus)
 extern "C" {
 #endif
@@ -64,90 +68,58 @@
 #define STRICT_ALIGNMENT 0
 #endif
 
-#if !defined(PEDANTIC) && !defined(OPENSSL_NO_ASM)
 #if defined(__GNUC__) && __GNUC__ >= 2
-#if defined(OPENSSL_X86_64)
-#define BSWAP8(x)                 \
-  ({                              \
-    uint64_t ret = (x);           \
-    asm("bswapq %0" : "+r"(ret)); \
-    ret;                          \
-  })
-#define BSWAP4(x)                 \
-  ({                              \
-    uint32_t ret = (x);           \
-    asm("bswapl %0" : "+r"(ret)); \
-    ret;                          \
-  })
-#elif defined(OPENSSL_X86)
-#define BSWAP8(x)                                     \
-  ({                                                  \
-    uint32_t lo = (uint64_t)(x) >> 32, hi = (x);      \
-    asm("bswapl %0; bswapl %1" : "+r"(hi), "+r"(lo)); \
-    (uint64_t) hi << 32 | lo;                         \
-  })
-#define BSWAP4(x)                 \
-  ({                              \
-    uint32_t ret = (x);           \
-    asm("bswapl %0" : "+r"(ret)); \
-    ret;                          \
-  })
-#elif defined(OPENSSL_AARCH64)
-#define BSWAP8(x)                          \
-  ({                                       \
-    uint64_t ret;                          \
-    asm("rev %0,%1" : "=r"(ret) : "r"(x)); \
-    ret;                                   \
-  })
-#define BSWAP4(x)                            \
-  ({                                         \
-    uint32_t ret;                            \
-    asm("rev %w0,%w1" : "=r"(ret) : "r"(x)); \
-    ret;                                     \
-  })
-#elif defined(OPENSSL_ARM) && !defined(STRICT_ALIGNMENT)
-#define BSWAP8(x)                                     \
-  ({                                                  \
-    uint32_t lo = (uint64_t)(x) >> 32, hi = (x);      \
-    asm("rev %0,%0; rev %1,%1" : "+r"(hi), "+r"(lo)); \
-    (uint64_t) hi << 32 | lo;                         \
-  })
-#define BSWAP4(x)                                      \
-  ({                                                   \
-    uint32_t ret;                                      \
-    asm("rev %0,%1" : "=r"(ret) : "r"((uint32_t)(x))); \
-    ret;                                               \
-  })
-#endif
-#elif defined(_MSC_VER)
-#if _MSC_VER >= 1300
-#pragma warning(push, 3)
-#include <intrin.h>
-#pragma warning(pop)
-#pragma intrinsic(_byteswap_uint64, _byteswap_ulong)
-#define BSWAP8(x) _byteswap_uint64((uint64_t)(x))
-#define BSWAP4(x) _byteswap_ulong((uint32_t)(x))
-#elif defined(OPENSSL_X86)
-__inline uint32_t _bswap4(uint32_t val) {
-  _asm mov eax, val
-  _asm bswap eax
+static inline uint32_t CRYPTO_bswap4(uint32_t x) {
+  return __builtin_bswap32(x);
 }
-#define BSWAP4(x) _bswap4(x)
-#endif
-#endif
-#endif
 
-#if defined(BSWAP4) && !defined(STRICT_ALIGNMENT)
-#define GETU32(p) BSWAP4(*(const uint32_t *)(p))
-#define PUTU32(p, v) *(uint32_t *)(p) = BSWAP4(v)
+static inline uint64_t CRYPTO_bswap8(uint64_t x) {
+  return __builtin_bswap64(x);
+}
+#elif defined(_MSC_VER)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
+#include <intrin.h>
+OPENSSL_MSVC_PRAGMA(warning(pop))
+#pragma intrinsic(_byteswap_uint64, _byteswap_ulong)
+static inline uint32_t CRYPTO_bswap4(uint32_t x) {
+  return _byteswap_ulong(x);
+}
+
+static inline uint64_t CRYPTO_bswap8(uint64_t x) {
+  return _byteswap_uint64(x);
+}
 #else
-#define GETU32(p) \
-  ((uint32_t)(p)[0] << 24 | (uint32_t)(p)[1] << 16 | (uint32_t)(p)[2] << 8 | (uint32_t)(p)[3])
-#define PUTU32(p, v)                                   \
-  ((p)[0] = (uint8_t)((v) >> 24), (p)[1] = (uint8_t)((v) >> 16), \
-   (p)[2] = (uint8_t)((v) >> 8), (p)[3] = (uint8_t)(v))
+static inline uint32_t CRYPTO_bswap4(uint32_t x) {
+  x = (x >> 16) | (x << 16);
+  x = ((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8);
+  return x;
+}
+
+static inline uint64_t CRYPTO_bswap8(uint64_t x) {
+  return CRYPTO_bswap4(x >> 32) | (((uint64_t)CRYPTO_bswap4(x)) << 32);
+}
 #endif
 
+static inline uint32_t GETU32(const void *in) {
+  uint32_t v;
+  OPENSSL_memcpy(&v, in, sizeof(v));
+  return CRYPTO_bswap4(v);
+}
+
+static inline void PUTU32(void *out, uint32_t v) {
+  v = CRYPTO_bswap4(v);
+  OPENSSL_memcpy(out, &v, sizeof(v));
+}
+
+static inline uint32_t GETU32_aligned(const void *in) {
+  const char *alias = (const char *) in;
+  return CRYPTO_bswap4(*((const uint32_t *) alias));
+}
+
+static inline void PUTU32_aligned(void *in, uint32_t v) {
+  char *alias = (char *) in;
+  *((uint32_t *) alias) = CRYPTO_bswap4(v);
+}
 
 /* block128_f is the type of a 128-bit, block cipher. */
 typedef void (*block128_f)(const uint8_t in[16], uint8_t out[16],
@@ -156,6 +128,16 @@
 /* GCM definitions */
 typedef struct { uint64_t hi,lo; } u128;
 
+/* gmult_func multiplies |Xi| by the GCM key and writes the result back to
+ * |Xi|. */
+typedef void (*gmult_func)(uint64_t Xi[2], const u128 Htable[16]);
+
+/* ghash_func repeatedly multiplies |Xi| by the GCM key and adds in blocks from
+ * |inp|. The result is written back to |Xi| and the |len| argument must be a
+ * multiple of 16. */
+typedef void (*ghash_func)(uint64_t Xi[2], const u128 Htable[16],
+                           const uint8_t *inp, size_t len);
+
 /* This differs from upstream's |gcm128_context| in that it does not have the
  * |key| pointer, in order to make it |memcpy|-friendly. Rather the key is
  * passed into each call that needs it. */
@@ -166,29 +148,19 @@
     uint32_t d[4];
     uint8_t c[16];
     size_t t[16 / sizeof(size_t)];
-  } Yi, EKi, EK0, len, Xi, H;
+  } Yi, EKi, EK0, len, Xi;
 
-  /* Relative position of Xi, H and pre-computed Htable is used in some
-   * assembler modules, i.e. don't change the order! */
+  /* Note that the order of |Xi|, |H| and |Htable| is fixed by the MOVBE-based,
+   * x86-64, GHASH assembly. */
+  u128 H;
   u128 Htable[16];
-  void (*gmult)(uint64_t Xi[2], const u128 Htable[16]);
-  void (*ghash)(uint64_t Xi[2], const u128 Htable[16], const uint8_t *inp,
-                size_t len);
+  gmult_func gmult;
+  ghash_func ghash;
 
   unsigned int mres, ares;
   block128_f block;
 };
 
-struct ccm128_context {
-  union {
-    uint64_t u[2];
-    uint8_t c[16];
-  } nonce, cmac;
-  uint64_t blocks;
-  block128_f block;
-  void *key;
-};
-
 #if defined(OPENSSL_X86) || defined(OPENSSL_X86_64)
 /* crypto_gcm_clmul_enabled returns one if the CLMUL implementation of GCM is
  * used. */
@@ -210,7 +182,7 @@
  * incremented by this function. */
 void CRYPTO_ctr128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
                            const void *key, uint8_t ivec[16],
-                           uint8_t ecount_buf[16], unsigned int *num,
+                           uint8_t ecount_buf[16], unsigned *num,
                            block128_f block);
 
 /* CRYPTO_ctr128_encrypt_ctr32 acts like |CRYPTO_ctr128_encrypt| but takes
@@ -219,9 +191,15 @@
  * function. */
 void CRYPTO_ctr128_encrypt_ctr32(const uint8_t *in, uint8_t *out, size_t len,
                                  const void *key, uint8_t ivec[16],
-                                 uint8_t ecount_buf[16], unsigned int *num,
+                                 uint8_t ecount_buf[16], unsigned *num,
                                  ctr128_f ctr);
 
+#if !defined(OPENSSL_NO_ASM) && \
+    (defined(OPENSSL_X86) || defined(OPENSSL_X86_64))
+void aesni_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t blocks,
+                                const void *key, const uint8_t *ivec);
+#endif
+
 
 /* GCM.
  *
@@ -232,10 +210,12 @@
 
 typedef struct gcm128_context GCM128_CONTEXT;
 
-/* CRYPTO_gcm128_new allocates a fresh |GCM128_CONTEXT| and calls
- * |CRYPTO_gcm128_init|. It returns the new context, or NULL on error. */
-OPENSSL_EXPORT GCM128_CONTEXT *CRYPTO_gcm128_new(const void *key,
-                                                 block128_f block);
+/* CRYPTO_ghash_init writes a precomputed table of powers of |gcm_key| to
+ * |out_table| and sets |*out_mult| and |*out_hash| to (potentially hardware
+ * accelerated) functions for performing operations in the GHASH field. */
+void CRYPTO_ghash_init(gmult_func *out_mult, ghash_func *out_hash,
+                       u128 *out_key, u128 out_table[16],
+                       const uint8_t *gcm_key);
 
 /* CRYPTO_gcm128_init initialises |ctx| to use |block| (typically AES) with
  * the given key. */
@@ -297,9 +277,6 @@
 OPENSSL_EXPORT void CRYPTO_gcm128_tag(GCM128_CONTEXT *ctx, uint8_t *tag,
                                       size_t len);
 
-/* CRYPTO_gcm128_release clears and frees |ctx|. */
-OPENSSL_EXPORT void CRYPTO_gcm128_release(GCM128_CONTEXT *ctx);
-
 
 /* CBC. */
 
@@ -331,7 +308,7 @@
  * call. */
 void CRYPTO_ofb128_encrypt(const uint8_t *in, uint8_t *out,
                            size_t len, const void *key, uint8_t ivec[16],
-                           int *num, block128_f block);
+                           unsigned *num, block128_f block);
 
 
 /* CFB. */
@@ -341,21 +318,21 @@
  * |len| be a multiple of any value and any partial blocks are stored in |ivec|
  * and |*num|, the latter must be zero before the initial call. */
 void CRYPTO_cfb128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
-                           const void *key, uint8_t ivec[16], int *num, int enc,
-                           block128_f block);
+                           const void *key, uint8_t ivec[16], unsigned *num,
+                           int enc, block128_f block);
 
 /* CRYPTO_cfb128_8_encrypt encrypts (or decrypts, if |enc| is zero) |len| bytes
  * from |in| to |out| using |block| in CFB-8 mode. Prior to the first call
  * |num| should be set to zero. */
 void CRYPTO_cfb128_8_encrypt(const uint8_t *in, uint8_t *out, size_t len,
-                             const void *key, uint8_t ivec[16], int *num,
+                             const void *key, uint8_t ivec[16], unsigned *num,
                              int enc, block128_f block);
 
 /* CRYPTO_cfb128_1_encrypt encrypts (or decrypts, if |enc| is zero) |len| bytes
  * from |in| to |out| using |block| in CFB-1 mode. Prior to the first call
  * |num| should be set to zero. */
 void CRYPTO_cfb128_1_encrypt(const uint8_t *in, uint8_t *out, size_t bits,
-                             const void *key, uint8_t ivec[16], int *num,
+                             const void *key, uint8_t ivec[16], unsigned *num,
                              int enc, block128_f block);
 
 size_t CRYPTO_cts128_encrypt_block(const uint8_t *in, uint8_t *out, size_t len,
@@ -363,6 +340,40 @@
                                    block128_f block);
 
 
+/* POLYVAL.
+ *
+ * POLYVAL is a polynomial authenticator that operates over a field very
+ * similar to the one that GHASH uses. See
+ * https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-02#section-3. */
+
+typedef union {
+  uint64_t u[2];
+  uint8_t c[16];
+} polyval_block;
+
+struct polyval_ctx {
+  /* Note that the order of |S|, |H| and |Htable| is fixed by the MOVBE-based,
+   * x86-64, GHASH assembly. */
+  polyval_block S;
+  u128 H;
+  u128 Htable[16];
+  gmult_func gmult;
+  ghash_func ghash;
+};
+
+/* CRYPTO_POLYVAL_init initialises |ctx| using |key|. */
+void CRYPTO_POLYVAL_init(struct polyval_ctx *ctx, const uint8_t key[16]);
+
+/* CRYPTO_POLYVAL_update_blocks updates the accumulator in |ctx| given the
+ * blocks from |in|. Only a whole number of blocks can be processed so |in_len|
+ * must be a multiple of 16. */
+void CRYPTO_POLYVAL_update_blocks(struct polyval_ctx *ctx, const uint8_t *in,
+                                  size_t in_len);
+
+/* CRYPTO_POLYVAL_finish writes the accumulator from |ctx| to |out|. */
+void CRYPTO_POLYVAL_finish(const struct polyval_ctx *ctx, uint8_t out[16]);
+
+
 #if defined(__cplusplus)
 } /* extern C */
 #endif
diff --git a/src/crypto/modes/ofb.c b/src/crypto/modes/ofb.c
index 63c3165..95d15c3 100644
--- a/src/crypto/modes/ofb.c
+++ b/src/crypto/modes/ofb.c
@@ -49,6 +49,7 @@
 #include <openssl/type_check.h>
 
 #include <assert.h>
+#include <string.h>
 
 #include "internal.h"
 
@@ -56,13 +57,11 @@
 OPENSSL_COMPILE_ASSERT((16 % sizeof(size_t)) == 0, bad_size_t_size);
 
 void CRYPTO_ofb128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
-                           const void *key, uint8_t ivec[16], int *num,
+                           const void *key, uint8_t ivec[16], unsigned *num,
                            block128_f block) {
-  unsigned int n;
-
   assert(in && out && key && ivec && num);
 
-  n = *num;
+  unsigned n = *num;
 
   while (n && len) {
     *(out++) = *(in++) ^ ivec[n];
@@ -70,27 +69,15 @@
     n = (n + 1) % 16;
   }
 
-#if STRICT_ALIGNMENT
-  if (((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != 0) {
-    size_t l = 0;
-    while (l < len) {
-      if (n == 0) {
-        (*block)(ivec, ivec, key);
-      }
-      out[l] = in[l] ^ ivec[n];
-      ++l;
-      n = (n + 1) % 16;
-    }
-
-    *num = n;
-    return;
-  }
-#endif
-
   while (len >= 16) {
     (*block)(ivec, ivec, key);
     for (; n < 16; n += sizeof(size_t)) {
-      *(size_t *)(out + n) = *(size_t *)(in + n) ^ *(size_t *)(ivec + n);
+      size_t a, b;
+      OPENSSL_memcpy(&a, in + n, sizeof(size_t));
+      OPENSSL_memcpy(&b, ivec + n, sizeof(size_t));
+
+      const size_t c = a ^ b;
+      OPENSSL_memcpy(out + n, &c, sizeof(size_t));
     }
     len -= 16;
     out += 16;
diff --git a/src/crypto/modes/polyval.c b/src/crypto/modes/polyval.c
new file mode 100644
index 0000000..33d37eb
--- /dev/null
+++ b/src/crypto/modes/polyval.c
@@ -0,0 +1,94 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/base.h>
+
+#if !defined(OPENSSL_SMALL)
+
+#include <assert.h>
+#include <string.h>
+
+#include "internal.h"
+#include "../internal.h"
+
+
+/* byte_reverse reverses the order of the bytes in |b->c|. */
+static void byte_reverse(polyval_block *b) {
+  const uint64_t t = CRYPTO_bswap8(b->u[0]);
+  b->u[0] = CRYPTO_bswap8(b->u[1]);
+  b->u[1] = t;
+}
+
+/* reverse_and_mulX_ghash interprets the bytes |b->c| as a reversed element of
+ * the GHASH field, multiplies that by 'x' and serialises the result back into
+ * |b|, but with GHASH's backwards bit ordering. */
+static void reverse_and_mulX_ghash(polyval_block *b) {
+  uint64_t hi = b->u[0];
+  uint64_t lo = b->u[1];
+  const unsigned carry = constant_time_eq(hi & 1, 1);
+  hi >>= 1;
+  hi |= lo << 63;
+  lo >>= 1;
+  lo ^= ((uint64_t) constant_time_select(carry, 0xe1, 0)) << 56;
+
+  b->u[0] = CRYPTO_bswap8(lo);
+  b->u[1] = CRYPTO_bswap8(hi);
+}
+
+/* POLYVAL(H, X_1, ..., X_n) =
+ * ByteReverse(GHASH(mulX_GHASH(ByteReverse(H)), ByteReverse(X_1), ...,
+ * ByteReverse(X_n))).
+ *
+ * See https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-02#appendix-A. */
+
+void CRYPTO_POLYVAL_init(struct polyval_ctx *ctx, const uint8_t key[16]) {
+  polyval_block H;
+  OPENSSL_memcpy(H.c, key, 16);
+  reverse_and_mulX_ghash(&H);
+
+  CRYPTO_ghash_init(&ctx->gmult, &ctx->ghash, &ctx->H, ctx->Htable, H.c);
+  OPENSSL_memset(&ctx->S, 0, sizeof(ctx->S));
+}
+
+void CRYPTO_POLYVAL_update_blocks(struct polyval_ctx *ctx, const uint8_t *in,
+                                  size_t in_len) {
+  assert((in_len & 15) == 0);
+  polyval_block reversed[32];
+
+  while (in_len > 0) {
+    size_t todo = in_len;
+    if (todo > sizeof(reversed)) {
+      todo = sizeof(reversed);
+    }
+    OPENSSL_memcpy(reversed, in, todo);
+    in += todo;
+    in_len -= todo;
+
+    size_t blocks = todo / sizeof(polyval_block);
+    for (size_t i = 0; i < blocks; i++) {
+      byte_reverse(&reversed[i]);
+    }
+
+    ctx->ghash(ctx->S.u, ctx->Htable, (const uint8_t *) reversed, todo);
+  }
+}
+
+void CRYPTO_POLYVAL_finish(const struct polyval_ctx *ctx, uint8_t out[16]) {
+  polyval_block S = ctx->S;
+  byte_reverse(&S);
+  OPENSSL_memcpy(out, &S.c, sizeof(polyval_block));
+}
+
+
+#endif  /* !OPENSSL_SMALL */
diff --git a/src/crypto/obj/CMakeLists.txt b/src/crypto/obj/CMakeLists.txt
index b8a4ef3..f49d499 100644
--- a/src/crypto/obj/CMakeLists.txt
+++ b/src/crypto/obj/CMakeLists.txt
@@ -8,3 +8,14 @@
   obj.c
   obj_xref.c
 )
+
+add_executable(
+  obj_test
+
+  obj_test.cc
+
+  $<TARGET_OBJECTS:test_support>
+)
+
+target_link_libraries(obj_test crypto)
+add_dependencies(all_tests obj_test)
diff --git a/src/crypto/obj/README b/src/crypto/obj/README
index 8826e59..797bb68 100644
--- a/src/crypto/obj/README
+++ b/src/crypto/obj/README
@@ -1,37 +1,15 @@
-OID information is generated via a series of perl scripts. In order, the full
-list of commands to run are:
+The files nid.h, obj_mac.num, and obj_dat.h are generated from objects.txt and
+obj_mac.num. To regenerate them, run:
 
-        perl objects.pl objects.txt obj_mac.num ../../include/openssl/obj_mac.h
-        perl obj_dat.pl ../../include/openssl/obj_mac.h obj_dat.h
-        perl obj_xref.pl obj_mac.num obj_xref.txt > obj_xref.h
+    go run objects.go
 
 objects.txt contains the list of all built-in OIDs. It is processed by
-objects.pl to output obj_mac.num and obj_mac.h. obj_mac.num is the list of NID
-values for each OID. This is an input/output parameter so NID values are stable
-across regenerations. obj_mac.h is the header which defines macros for all the
-built-in OIDs in C.
+objects.go to output obj_mac.num, obj_dat.h, and nid.h.
 
-obj_mac.h is read by obj_dat.pl to generate obj_dat.h. obj_dat.h contains the
-ASN1_OBJECTs corresponding to built-in OIDs themselves along with lookup tables
-for search by short name, OID, etc.
+obj_mac.num is the list of NID values for each OID. This is an input/output
+file so NID values are stable across regenerations.
 
-obj_mac.num and obj_xref.txt are read by obj_xref.pl to generate
-obj_xref.h. obj_xref.txt links signature OIDs to corresponding public key
-algorithms and digests. obj_xref.h contains lookup tables for querying this
-information in both directions.
+nid.h is the header which defines macros for all the built-in OIDs in C.
 
-Dependency graph:
-
-                        objects.txt
-                            |
-                            V
-                       [objects.pl] <--+
-                         /      \      |
-                        V        V     |
-                  obj_mac.h    obj_mac.num  obj_xref.txt
-                      |              \      /
-                      V               V    V
-                 [obj_dat.pl]      [obj_xref.pl]
-                      |                  |
-                      V                  V
-                  obj_dat.h         obj_xref.h
+obj_dat.h contains the ASN1_OBJECTs corresponding to built-in OIDs themselves
+along with lookup tables for search by short name, OID, etc.
diff --git a/src/crypto/obj/obj.c b/src/crypto/obj/obj.c
index 94f739c..173257f 100644
--- a/src/crypto/obj/obj.c
+++ b/src/crypto/obj/obj.c
@@ -54,8 +54,13 @@
  * copied and put under another distribution licence
  * [including the GNU Public Licence.] */
 
+#if !defined(__STDC_FORMAT_MACROS)
+#define __STDC_FORMAT_MACROS
+#endif
+
 #include <openssl/obj.h>
 
+#include <inttypes.h>
 #include <limits.h>
 #include <string.h>
 
@@ -87,7 +92,7 @@
 
   CRYPTO_STATIC_MUTEX_lock_write(&global_next_nid_lock);
   ret = global_next_nid++;
-  CRYPTO_STATIC_MUTEX_unlock(&global_next_nid_lock);
+  CRYPTO_STATIC_MUTEX_unlock_write(&global_next_nid_lock);
 
   return ret;
 }
@@ -118,7 +123,7 @@
     goto err;
   }
   if (o->data != NULL) {
-    memcpy(data, o->data, o->length);
+    OPENSSL_memcpy(data, o->data, o->length);
   }
 
   /* once data is attached to an object, it remains const */
@@ -164,7 +169,7 @@
   if (ret) {
     return ret;
   }
-  return memcmp(a->data, b->data, a->length);
+  return OPENSSL_memcmp(a->data, b->data, a->length);
 }
 
 /* obj_cmp is called to search the kNIDsInOIDOrder array. The |key| argument is
@@ -180,7 +185,7 @@
   } else if (a->length > b->length) {
     return 1;
   }
-  return memcmp(a->data, b->data, a->length);
+  return OPENSSL_memcmp(a->data, b->data, a->length);
 }
 
 int OBJ_obj2nid(const ASN1_OBJECT *obj) {
@@ -200,13 +205,14 @@
 
     match = lh_ASN1_OBJECT_retrieve(global_added_by_data, obj);
     if (match != NULL) {
-      CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
+      CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
       return match->nid;
     }
   }
-  CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
+  CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
 
-  nid_ptr = bsearch(obj, kNIDsInOIDOrder, NUM_OBJ, sizeof(unsigned), obj_cmp);
+  nid_ptr = bsearch(obj, kNIDsInOIDOrder, OPENSSL_ARRAY_SIZE(kNIDsInOIDOrder),
+                    sizeof(kNIDsInOIDOrder[0]), obj_cmp);
   if (nid_ptr == NULL) {
     return NID_undef;
   }
@@ -215,10 +221,14 @@
 }
 
 int OBJ_cbs2nid(const CBS *cbs) {
+  if (CBS_len(cbs) > INT_MAX) {
+    return NID_undef;
+  }
+
   ASN1_OBJECT obj;
-  memset(&obj, 0, sizeof(obj));
+  OPENSSL_memset(&obj, 0, sizeof(obj));
   obj.data = CBS_data(cbs);
-  obj.length = CBS_len(cbs);
+  obj.length = (int)CBS_len(cbs);
 
   return OBJ_obj2nid(&obj);
 }
@@ -243,13 +253,15 @@
     template.sn = short_name;
     match = lh_ASN1_OBJECT_retrieve(global_added_by_short_name, &template);
     if (match != NULL) {
-      CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
+      CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
       return match->nid;
     }
   }
-  CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
+  CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
 
-  nid_ptr = bsearch(short_name, kNIDsInShortNameOrder, NUM_SN, sizeof(unsigned), short_name_cmp);
+  nid_ptr = bsearch(short_name, kNIDsInShortNameOrder,
+                    OPENSSL_ARRAY_SIZE(kNIDsInShortNameOrder),
+                    sizeof(kNIDsInShortNameOrder[0]), short_name_cmp);
   if (nid_ptr == NULL) {
     return NID_undef;
   }
@@ -277,13 +289,15 @@
     template.ln = long_name;
     match = lh_ASN1_OBJECT_retrieve(global_added_by_long_name, &template);
     if (match != NULL) {
-      CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
+      CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
       return match->nid;
     }
   }
-  CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
+  CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
 
-  nid_ptr = bsearch(long_name, kNIDsInLongNameOrder, NUM_LN, sizeof(unsigned), long_name_cmp);
+  nid_ptr = bsearch(long_name, kNIDsInLongNameOrder,
+                    OPENSSL_ARRAY_SIZE(kNIDsInLongNameOrder),
+                    sizeof(kNIDsInLongNameOrder[0]), long_name_cmp);
   if (nid_ptr == NULL) {
     return NID_undef;
   }
@@ -330,11 +344,11 @@
     template.nid = nid;
     match = lh_ASN1_OBJECT_retrieve(global_added_by_nid, &template);
     if (match != NULL) {
-      CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
+      CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
       return match;
     }
   }
-  CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
+  CRYPTO_STATIC_MUTEX_unlock_read(&global_added_lock);
 
 err:
   OPENSSL_PUT_ERROR(OBJ, OBJ_R_UNKNOWN_NID);
@@ -405,148 +419,115 @@
   return op;
 }
 
-int OBJ_obj2txt(char *out, int out_len, const ASN1_OBJECT *obj, int dont_return_name) {
-  int i, n = 0, len, nid, first, use_bn;
-  BIGNUM *bl;
-  unsigned long l;
-  const unsigned char *p;
-  char tbuf[DECIMAL_SIZE(i) + DECIMAL_SIZE(l) + 2];
-
-  if (out && out_len > 0) {
-    out[0] = 0;
+static int strlcpy_int(char *dst, const char *src, int dst_size) {
+  size_t ret = BUF_strlcpy(dst, src, dst_size < 0 ? 0 : (size_t)dst_size);
+  if (ret > INT_MAX) {
+    OPENSSL_PUT_ERROR(OBJ, ERR_R_OVERFLOW);
+    return -1;
   }
+  return (int)ret;
+}
 
-  if (obj == NULL || obj->data == NULL) {
-    return 0;
-  }
-
-  if (!dont_return_name && (nid = OBJ_obj2nid(obj)) != NID_undef) {
-    const char *s;
-    s = OBJ_nid2ln(nid);
-    if (s == NULL) {
-      s = OBJ_nid2sn(nid);
+static int parse_oid_component(CBS *cbs, uint64_t *out) {
+  uint64_t v = 0;
+  uint8_t b;
+  do {
+    if (!CBS_get_u8(cbs, &b)) {
+      return 0;
     }
-    if (s) {
-      if (out) {
-        BUF_strlcpy(out, s, out_len);
+    if ((v >> (64 - 7)) != 0) {
+      /* The component is too large. */
+      return 0;
+    }
+    if (v == 0 && b == 0x80) {
+      /* The component must be minimally encoded. */
+      return 0;
+    }
+    v = (v << 7) | (b & 0x7f);
+
+    /* Components end at an octet with the high bit cleared. */
+  } while (b & 0x80);
+
+  *out = v;
+  return 1;
+}
+
+static int add_decimal(CBB *out, uint64_t v) {
+  char buf[DECIMAL_SIZE(uint64_t) + 1];
+  BIO_snprintf(buf, sizeof(buf), "%" PRIu64, v);
+  return CBB_add_bytes(out, (const uint8_t *)buf, strlen(buf));
+}
+
+int OBJ_obj2txt(char *out, int out_len, const ASN1_OBJECT *obj,
+                int always_return_oid) {
+  /* Python depends on the empty OID successfully encoding as the empty
+   * string. */
+  if (obj == NULL || obj->length == 0) {
+    return strlcpy_int(out, "", out_len);
+  }
+
+  if (!always_return_oid) {
+    int nid = OBJ_obj2nid(obj);
+    if (nid != NID_undef) {
+      const char *name = OBJ_nid2ln(nid);
+      if (name == NULL) {
+        name = OBJ_nid2sn(nid);
       }
-      return strlen(s);
+      if (name != NULL) {
+        return strlcpy_int(out, name, out_len);
+      }
     }
   }
 
-  len = obj->length;
-  p = obj->data;
+  CBB cbb;
+  if (!CBB_init(&cbb, 32)) {
+    goto err;
+  }
 
-  first = 1;
-  bl = NULL;
+  CBS cbs;
+  CBS_init(&cbs, obj->data, obj->length);
 
-  while (len > 0) {
-    l = 0;
-    use_bn = 0;
-    for (;;) {
-      unsigned char c = *p++;
-      len--;
-      if (len == 0 && (c & 0x80)) {
-        goto err;
-      }
-      if (use_bn) {
-        if (!BN_add_word(bl, c & 0x7f)) {
-          goto err;
-        }
-      } else {
-        l |= c & 0x7f;
-      }
-      if (!(c & 0x80)) {
-        break;
-      }
-      if (!use_bn && (l > (ULONG_MAX >> 7L))) {
-        if (!bl && !(bl = BN_new())) {
-          goto err;
-        }
-        if (!BN_set_word(bl, l)) {
-          goto err;
-        }
-        use_bn = 1;
-      }
-      if (use_bn) {
-        if (!BN_lshift(bl, bl, 7)) {
-          goto err;
-        }
-      } else {
-        l <<= 7L;
-      }
+  /* The first component is 40 * value1 + value2, where value1 is 0, 1, or 2. */
+  uint64_t v;
+  if (!parse_oid_component(&cbs, &v)) {
+    goto err;
+  }
+
+  if (v >= 80) {
+    if (!CBB_add_bytes(&cbb, (const uint8_t *)"2.", 2) ||
+        !add_decimal(&cbb, v - 80)) {
+      goto err;
     }
+  } else if (!add_decimal(&cbb, v / 40) ||
+             !CBB_add_u8(&cbb, '.') ||
+             !add_decimal(&cbb, v % 40)) {
+    goto err;
+  }
 
-    if (first) {
-      first = 0;
-      if (l >= 80) {
-        i = 2;
-        if (use_bn) {
-          if (!BN_sub_word(bl, 80)) {
-            goto err;
-          }
-        } else {
-          l -= 80;
-        }
-      } else {
-        i = (int)(l / 40);
-        l -= (long)(i * 40);
-      }
-      if (out && out_len > 1) {
-        *out++ = i + '0';
-        *out = '0';
-        out_len--;
-      }
-      n++;
-    }
-
-    if (use_bn) {
-      char *bndec;
-      bndec = BN_bn2dec(bl);
-      if (!bndec) {
-        goto err;
-      }
-      i = strlen(bndec);
-      if (out) {
-        if (out_len > 1) {
-          *out++ = '.';
-          *out = 0;
-          out_len--;
-        }
-        BUF_strlcpy(out, bndec, out_len);
-        if (i > out_len) {
-          out += out_len;
-          out_len = 0;
-        } else {
-          out += i;
-          out_len -= i;
-        }
-      }
-      n++;
-      n += i;
-      OPENSSL_free(bndec);
-    } else {
-      BIO_snprintf(tbuf, sizeof(tbuf), ".%lu", l);
-      i = strlen(tbuf);
-      if (out && out_len > 0) {
-        BUF_strlcpy(out, tbuf, out_len);
-        if (i > out_len) {
-          out += out_len;
-          out_len = 0;
-        } else {
-          out += i;
-          out_len -= i;
-        }
-      }
-      n += i;
+  while (CBS_len(&cbs) != 0) {
+    if (!parse_oid_component(&cbs, &v) ||
+        !CBB_add_u8(&cbb, '.') ||
+        !add_decimal(&cbb, v)) {
+      goto err;
     }
   }
 
-  BN_free(bl);
-  return n;
+  uint8_t *txt;
+  size_t txt_len;
+  if (!CBB_add_u8(&cbb, '\0') ||
+      !CBB_finish(&cbb, &txt, &txt_len)) {
+    goto err;
+  }
+
+  int ret = strlcpy_int(out, (const char *)txt, out_len);
+  OPENSSL_free(txt);
+  return ret;
 
 err:
-  BN_free(bl);
+  CBB_cleanup(&cbb);
+  if (out_len > 0) {
+    out[0] = '\0';
+  }
   return -1;
 }
 
@@ -567,7 +548,7 @@
   if (i) {
     return i;
   }
-  return memcmp(a->data, b->data, a->length);
+  return OPENSSL_memcmp(a->data, b->data, a->length);
 }
 
 static uint32_t hash_short_name(const ASN1_OBJECT *obj) {
@@ -618,7 +599,7 @@
   if (obj->ln != NULL) {
     ok &= lh_ASN1_OBJECT_insert(global_added_by_long_name, &old_object, obj);
   }
-  CRYPTO_STATIC_MUTEX_unlock(&global_added_lock);
+  CRYPTO_STATIC_MUTEX_unlock_write(&global_added_lock);
 
   return ok;
 }
diff --git a/src/crypto/obj/obj_dat.h b/src/crypto/obj/obj_dat.h
index bf44c6d..4905f0d 100644
--- a/src/crypto/obj/obj_dat.h
+++ b/src/crypto/obj/obj_dat.h
@@ -1,7 +1,3 @@
-/* THIS FILE IS GENERATED FROM objects.h by obj_dat.pl via the
- * following command:
- * perl obj_dat.pl ../../include/openssl/obj_mac.h obj_dat.h */
-
 /* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
@@ -58,5203 +54,6123 @@
  * copied and put under another distribution licence
  * [including the GNU Public Licence.] */
 
+/* This file is generated by crypto/obj/objects.go. */
+
 #define NUM_NID 949
-#define NUM_SN 941
-#define NUM_LN 941
-#define NUM_OBJ 882
 
-static const unsigned char lvalues[6176]={
-0x2A,0x86,0x48,0x86,0xF7,0x0D,               /* [  0] OBJ_rsadsi */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,          /* [  6] OBJ_pkcs */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x02,     /* [ 13] OBJ_md2 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x05,     /* [ 21] OBJ_md5 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x03,0x04,     /* [ 29] OBJ_rc4 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01,/* [ 37] OBJ_rsaEncryption */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x02,/* [ 46] OBJ_md2WithRSAEncryption */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x04,/* [ 55] OBJ_md5WithRSAEncryption */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x01,/* [ 64] OBJ_pbeWithMD2AndDES_CBC */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x03,/* [ 73] OBJ_pbeWithMD5AndDES_CBC */
-0x55,                                        /* [ 82] OBJ_X500 */
-0x55,0x04,                                   /* [ 83] OBJ_X509 */
-0x55,0x04,0x03,                              /* [ 85] OBJ_commonName */
-0x55,0x04,0x06,                              /* [ 88] OBJ_countryName */
-0x55,0x04,0x07,                              /* [ 91] OBJ_localityName */
-0x55,0x04,0x08,                              /* [ 94] OBJ_stateOrProvinceName */
-0x55,0x04,0x0A,                              /* [ 97] OBJ_organizationName */
-0x55,0x04,0x0B,                              /* [100] OBJ_organizationalUnitName */
-0x55,0x08,0x01,0x01,                         /* [103] OBJ_rsa */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,     /* [107] OBJ_pkcs7 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x01,/* [115] OBJ_pkcs7_data */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x02,/* [124] OBJ_pkcs7_signed */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x03,/* [133] OBJ_pkcs7_enveloped */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x04,/* [142] OBJ_pkcs7_signedAndEnveloped */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x05,/* [151] OBJ_pkcs7_digest */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x06,/* [160] OBJ_pkcs7_encrypted */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x03,     /* [169] OBJ_pkcs3 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x03,0x01,/* [177] OBJ_dhKeyAgreement */
-0x2B,0x0E,0x03,0x02,0x06,                    /* [186] OBJ_des_ecb */
-0x2B,0x0E,0x03,0x02,0x09,                    /* [191] OBJ_des_cfb64 */
-0x2B,0x0E,0x03,0x02,0x07,                    /* [196] OBJ_des_cbc */
-0x2B,0x0E,0x03,0x02,0x11,                    /* [201] OBJ_des_ede_ecb */
-0x2B,0x06,0x01,0x04,0x01,0x81,0x3C,0x07,0x01,0x01,0x02,/* [206] OBJ_idea_cbc */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x03,0x02,     /* [217] OBJ_rc2_cbc */
-0x2B,0x0E,0x03,0x02,0x12,                    /* [225] OBJ_sha */
-0x2B,0x0E,0x03,0x02,0x0F,                    /* [230] OBJ_shaWithRSAEncryption */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x03,0x07,     /* [235] OBJ_des_ede3_cbc */
-0x2B,0x0E,0x03,0x02,0x08,                    /* [243] OBJ_des_ofb64 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,     /* [248] OBJ_pkcs9 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x01,/* [256] OBJ_pkcs9_emailAddress */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x02,/* [265] OBJ_pkcs9_unstructuredName */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x03,/* [274] OBJ_pkcs9_contentType */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x04,/* [283] OBJ_pkcs9_messageDigest */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x05,/* [292] OBJ_pkcs9_signingTime */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x06,/* [301] OBJ_pkcs9_countersignature */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x07,/* [310] OBJ_pkcs9_challengePassword */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x08,/* [319] OBJ_pkcs9_unstructuredAddress */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x09,/* [328] OBJ_pkcs9_extCertAttributes */
-0x60,0x86,0x48,0x01,0x86,0xF8,0x42,          /* [337] OBJ_netscape */
-0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,     /* [344] OBJ_netscape_cert_extension */
-0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x02,     /* [352] OBJ_netscape_data_type */
-0x2B,0x0E,0x03,0x02,0x1A,                    /* [360] OBJ_sha1 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05,/* [365] OBJ_sha1WithRSAEncryption */
-0x2B,0x0E,0x03,0x02,0x0D,                    /* [374] OBJ_dsaWithSHA */
-0x2B,0x0E,0x03,0x02,0x0C,                    /* [379] OBJ_dsa_2 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x0B,/* [384] OBJ_pbeWithSHA1AndRC2_CBC */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x0C,/* [393] OBJ_id_pbkdf2 */
-0x2B,0x0E,0x03,0x02,0x1B,                    /* [402] OBJ_dsaWithSHA1_2 */
-0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x01,/* [407] OBJ_netscape_cert_type */
-0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x02,/* [416] OBJ_netscape_base_url */
-0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x03,/* [425] OBJ_netscape_revocation_url */
-0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x04,/* [434] OBJ_netscape_ca_revocation_url */
-0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x07,/* [443] OBJ_netscape_renewal_url */
-0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x08,/* [452] OBJ_netscape_ca_policy_url */
-0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x0C,/* [461] OBJ_netscape_ssl_server_name */
-0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x0D,/* [470] OBJ_netscape_comment */
-0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x02,0x05,/* [479] OBJ_netscape_cert_sequence */
-0x55,0x1D,                                   /* [488] OBJ_id_ce */
-0x55,0x1D,0x0E,                              /* [490] OBJ_subject_key_identifier */
-0x55,0x1D,0x0F,                              /* [493] OBJ_key_usage */
-0x55,0x1D,0x10,                              /* [496] OBJ_private_key_usage_period */
-0x55,0x1D,0x11,                              /* [499] OBJ_subject_alt_name */
-0x55,0x1D,0x12,                              /* [502] OBJ_issuer_alt_name */
-0x55,0x1D,0x13,                              /* [505] OBJ_basic_constraints */
-0x55,0x1D,0x14,                              /* [508] OBJ_crl_number */
-0x55,0x1D,0x20,                              /* [511] OBJ_certificate_policies */
-0x55,0x1D,0x23,                              /* [514] OBJ_authority_key_identifier */
-0x2B,0x06,0x01,0x04,0x01,0x97,0x55,0x01,0x02,/* [517] OBJ_bf_cbc */
-0x55,0x08,0x03,0x65,                         /* [526] OBJ_mdc2 */
-0x55,0x08,0x03,0x64,                         /* [530] OBJ_mdc2WithRSA */
-0x55,0x04,0x2A,                              /* [534] OBJ_givenName */
-0x55,0x04,0x04,                              /* [537] OBJ_surname */
-0x55,0x04,0x2B,                              /* [540] OBJ_initials */
-0x55,0x1D,0x1F,                              /* [543] OBJ_crl_distribution_points */
-0x2B,0x0E,0x03,0x02,0x03,                    /* [546] OBJ_md5WithRSA */
-0x55,0x04,0x05,                              /* [551] OBJ_serialNumber */
-0x55,0x04,0x0C,                              /* [554] OBJ_title */
-0x55,0x04,0x0D,                              /* [557] OBJ_description */
-0x2A,0x86,0x48,0x86,0xF6,0x7D,0x07,0x42,0x0A,/* [560] OBJ_cast5_cbc */
-0x2A,0x86,0x48,0x86,0xF6,0x7D,0x07,0x42,0x0C,/* [569] OBJ_pbeWithMD5AndCast5_CBC */
-0x2A,0x86,0x48,0xCE,0x38,0x04,0x03,          /* [578] OBJ_dsaWithSHA1 */
-0x2B,0x0E,0x03,0x02,0x1D,                    /* [585] OBJ_sha1WithRSA */
-0x2A,0x86,0x48,0xCE,0x38,0x04,0x01,          /* [590] OBJ_dsa */
-0x2B,0x24,0x03,0x02,0x01,                    /* [597] OBJ_ripemd160 */
-0x2B,0x24,0x03,0x03,0x01,0x02,               /* [602] OBJ_ripemd160WithRSA */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x03,0x08,     /* [608] OBJ_rc5_cbc */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x08,/* [616] OBJ_zlib_compression */
-0x55,0x1D,0x25,                              /* [627] OBJ_ext_key_usage */
-0x2B,0x06,0x01,0x05,0x05,0x07,               /* [630] OBJ_id_pkix */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x03,          /* [636] OBJ_id_kp */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01,     /* [643] OBJ_server_auth */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02,     /* [651] OBJ_client_auth */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x03,     /* [659] OBJ_code_sign */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x04,     /* [667] OBJ_email_protect */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x08,     /* [675] OBJ_time_stamp */
-0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x02,0x01,0x15,/* [683] OBJ_ms_code_ind */
-0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x02,0x01,0x16,/* [693] OBJ_ms_code_com */
-0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x0A,0x03,0x01,/* [703] OBJ_ms_ctl_sign */
-0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x0A,0x03,0x03,/* [713] OBJ_ms_sgc */
-0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x0A,0x03,0x04,/* [723] OBJ_ms_efs */
-0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x04,0x01,/* [733] OBJ_ns_sgc */
-0x55,0x1D,0x1B,                              /* [742] OBJ_delta_crl */
-0x55,0x1D,0x15,                              /* [745] OBJ_crl_reason */
-0x55,0x1D,0x18,                              /* [748] OBJ_invalidity_date */
-0x2B,0x65,0x01,0x04,0x01,                    /* [751] OBJ_sxnet */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x01,0x01,/* [756] OBJ_pbe_WithSHA1And128BitRC4 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x01,0x02,/* [766] OBJ_pbe_WithSHA1And40BitRC4 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x01,0x03,/* [776] OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x01,0x04,/* [786] OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x01,0x05,/* [796] OBJ_pbe_WithSHA1And128BitRC2_CBC */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x01,0x06,/* [806] OBJ_pbe_WithSHA1And40BitRC2_CBC */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x0A,0x01,0x01,/* [816] OBJ_keyBag */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x0A,0x01,0x02,/* [827] OBJ_pkcs8ShroudedKeyBag */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x0A,0x01,0x03,/* [838] OBJ_certBag */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x0A,0x01,0x04,/* [849] OBJ_crlBag */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x0A,0x01,0x05,/* [860] OBJ_secretBag */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x0A,0x01,0x06,/* [871] OBJ_safeContentsBag */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x14,/* [882] OBJ_friendlyName */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x15,/* [891] OBJ_localKeyID */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x16,0x01,/* [900] OBJ_x509Certificate */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x16,0x02,/* [910] OBJ_sdsiCertificate */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x17,0x01,/* [920] OBJ_x509Crl */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x0D,/* [930] OBJ_pbes2 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x0E,/* [939] OBJ_pbmac1 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x07,     /* [948] OBJ_hmacWithSHA1 */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01,     /* [956] OBJ_id_qt_cps */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x02,     /* [964] OBJ_id_qt_unotice */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x0F,/* [972] OBJ_SMIMECapabilities */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x04,/* [981] OBJ_pbeWithMD2AndRC2_CBC */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x06,/* [990] OBJ_pbeWithMD5AndRC2_CBC */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x0A,/* [999] OBJ_pbeWithSHA1AndDES_CBC */
-0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x02,0x01,0x0E,/* [1008] OBJ_ms_ext_req */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x0E,/* [1018] OBJ_ext_req */
-0x55,0x04,0x29,                              /* [1027] OBJ_name */
-0x55,0x04,0x2E,                              /* [1030] OBJ_dnQualifier */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x01,          /* [1033] OBJ_id_pe */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x30,          /* [1040] OBJ_id_ad */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01,     /* [1047] OBJ_info_access */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,     /* [1055] OBJ_ad_OCSP */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x02,     /* [1063] OBJ_ad_ca_issuers */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x09,     /* [1071] OBJ_OCSP_sign */
-0x2A,                                        /* [1079] OBJ_member_body */
-0x2A,0x86,0x48,                              /* [1080] OBJ_ISO_US */
-0x2A,0x86,0x48,0xCE,0x38,                    /* [1083] OBJ_X9_57 */
-0x2A,0x86,0x48,0xCE,0x38,0x04,               /* [1088] OBJ_X9cm */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,     /* [1094] OBJ_pkcs1 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,     /* [1102] OBJ_pkcs5 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,/* [1110] OBJ_SMIME */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,/* [1119] OBJ_id_smime_mod */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,/* [1129] OBJ_id_smime_ct */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,/* [1139] OBJ_id_smime_aa */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,/* [1149] OBJ_id_smime_alg */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x04,/* [1159] OBJ_id_smime_cd */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x05,/* [1169] OBJ_id_smime_spq */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x06,/* [1179] OBJ_id_smime_cti */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,0x01,/* [1189] OBJ_id_smime_mod_cms */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,0x02,/* [1200] OBJ_id_smime_mod_ess */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,0x03,/* [1211] OBJ_id_smime_mod_oid */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,0x04,/* [1222] OBJ_id_smime_mod_msg_v3 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,0x05,/* [1233] OBJ_id_smime_mod_ets_eSignature_88 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,0x06,/* [1244] OBJ_id_smime_mod_ets_eSignature_97 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,0x07,/* [1255] OBJ_id_smime_mod_ets_eSigPolicy_88 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,0x08,/* [1266] OBJ_id_smime_mod_ets_eSigPolicy_97 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x01,/* [1277] OBJ_id_smime_ct_receipt */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x02,/* [1288] OBJ_id_smime_ct_authData */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x03,/* [1299] OBJ_id_smime_ct_publishCert */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x04,/* [1310] OBJ_id_smime_ct_TSTInfo */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x05,/* [1321] OBJ_id_smime_ct_TDTInfo */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x06,/* [1332] OBJ_id_smime_ct_contentInfo */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x07,/* [1343] OBJ_id_smime_ct_DVCSRequestData */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x08,/* [1354] OBJ_id_smime_ct_DVCSResponseData */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x01,/* [1365] OBJ_id_smime_aa_receiptRequest */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x02,/* [1376] OBJ_id_smime_aa_securityLabel */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x03,/* [1387] OBJ_id_smime_aa_mlExpandHistory */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x04,/* [1398] OBJ_id_smime_aa_contentHint */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x05,/* [1409] OBJ_id_smime_aa_msgSigDigest */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x06,/* [1420] OBJ_id_smime_aa_encapContentType */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x07,/* [1431] OBJ_id_smime_aa_contentIdentifier */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x08,/* [1442] OBJ_id_smime_aa_macValue */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x09,/* [1453] OBJ_id_smime_aa_equivalentLabels */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x0A,/* [1464] OBJ_id_smime_aa_contentReference */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x0B,/* [1475] OBJ_id_smime_aa_encrypKeyPref */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x0C,/* [1486] OBJ_id_smime_aa_signingCertificate */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x0D,/* [1497] OBJ_id_smime_aa_smimeEncryptCerts */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x0E,/* [1508] OBJ_id_smime_aa_timeStampToken */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x0F,/* [1519] OBJ_id_smime_aa_ets_sigPolicyId */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x10,/* [1530] OBJ_id_smime_aa_ets_commitmentType */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x11,/* [1541] OBJ_id_smime_aa_ets_signerLocation */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x12,/* [1552] OBJ_id_smime_aa_ets_signerAttr */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x13,/* [1563] OBJ_id_smime_aa_ets_otherSigCert */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x14,/* [1574] OBJ_id_smime_aa_ets_contentTimestamp */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x15,/* [1585] OBJ_id_smime_aa_ets_CertificateRefs */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x16,/* [1596] OBJ_id_smime_aa_ets_RevocationRefs */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x17,/* [1607] OBJ_id_smime_aa_ets_certValues */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x18,/* [1618] OBJ_id_smime_aa_ets_revocationValues */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x19,/* [1629] OBJ_id_smime_aa_ets_escTimeStamp */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x1A,/* [1640] OBJ_id_smime_aa_ets_certCRLTimestamp */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x1B,/* [1651] OBJ_id_smime_aa_ets_archiveTimeStamp */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x1C,/* [1662] OBJ_id_smime_aa_signatureType */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x1D,/* [1673] OBJ_id_smime_aa_dvcs_dvc */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x01,/* [1684] OBJ_id_smime_alg_ESDHwith3DES */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x02,/* [1695] OBJ_id_smime_alg_ESDHwithRC2 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x03,/* [1706] OBJ_id_smime_alg_3DESwrap */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x04,/* [1717] OBJ_id_smime_alg_RC2wrap */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x05,/* [1728] OBJ_id_smime_alg_ESDH */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x06,/* [1739] OBJ_id_smime_alg_CMS3DESwrap */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x07,/* [1750] OBJ_id_smime_alg_CMSRC2wrap */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x04,0x01,/* [1761] OBJ_id_smime_cd_ldap */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x05,0x01,/* [1772] OBJ_id_smime_spq_ets_sqt_uri */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x05,0x02,/* [1783] OBJ_id_smime_spq_ets_sqt_unotice */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x06,0x01,/* [1794] OBJ_id_smime_cti_ets_proofOfOrigin */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x06,0x02,/* [1805] OBJ_id_smime_cti_ets_proofOfReceipt */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x06,0x03,/* [1816] OBJ_id_smime_cti_ets_proofOfDelivery */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x06,0x04,/* [1827] OBJ_id_smime_cti_ets_proofOfSender */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x06,0x05,/* [1838] OBJ_id_smime_cti_ets_proofOfApproval */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x06,0x06,/* [1849] OBJ_id_smime_cti_ets_proofOfCreation */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x04,     /* [1860] OBJ_md4 */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x00,          /* [1868] OBJ_id_pkix_mod */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x02,          /* [1875] OBJ_id_qt */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x04,          /* [1882] OBJ_id_it */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x05,          /* [1889] OBJ_id_pkip */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x06,          /* [1896] OBJ_id_alg */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x07,          /* [1903] OBJ_id_cmc */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x08,          /* [1910] OBJ_id_on */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x09,          /* [1917] OBJ_id_pda */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x0A,          /* [1924] OBJ_id_aca */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x0B,          /* [1931] OBJ_id_qcs */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x0C,          /* [1938] OBJ_id_cct */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x01,     /* [1945] OBJ_id_pkix1_explicit_88 */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x02,     /* [1953] OBJ_id_pkix1_implicit_88 */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x03,     /* [1961] OBJ_id_pkix1_explicit_93 */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x04,     /* [1969] OBJ_id_pkix1_implicit_93 */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x05,     /* [1977] OBJ_id_mod_crmf */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x06,     /* [1985] OBJ_id_mod_cmc */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x07,     /* [1993] OBJ_id_mod_kea_profile_88 */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x08,     /* [2001] OBJ_id_mod_kea_profile_93 */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x09,     /* [2009] OBJ_id_mod_cmp */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x0A,     /* [2017] OBJ_id_mod_qualified_cert_88 */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x0B,     /* [2025] OBJ_id_mod_qualified_cert_93 */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x0C,     /* [2033] OBJ_id_mod_attribute_cert */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x0D,     /* [2041] OBJ_id_mod_timestamp_protocol */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x0E,     /* [2049] OBJ_id_mod_ocsp */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x0F,     /* [2057] OBJ_id_mod_dvcs */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x10,     /* [2065] OBJ_id_mod_cmp2000 */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x02,     /* [2073] OBJ_biometricInfo */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x03,     /* [2081] OBJ_qcStatements */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x04,     /* [2089] OBJ_ac_auditEntity */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x05,     /* [2097] OBJ_ac_targeting */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x06,     /* [2105] OBJ_aaControls */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x07,     /* [2113] OBJ_sbgp_ipAddrBlock */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x08,     /* [2121] OBJ_sbgp_autonomousSysNum */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x09,     /* [2129] OBJ_sbgp_routerIdentifier */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x03,     /* [2137] OBJ_textNotice */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x05,     /* [2145] OBJ_ipsecEndSystem */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x06,     /* [2153] OBJ_ipsecTunnel */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x07,     /* [2161] OBJ_ipsecUser */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x0A,     /* [2169] OBJ_dvcs */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x01,     /* [2177] OBJ_id_it_caProtEncCert */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x02,     /* [2185] OBJ_id_it_signKeyPairTypes */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x03,     /* [2193] OBJ_id_it_encKeyPairTypes */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x04,     /* [2201] OBJ_id_it_preferredSymmAlg */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x05,     /* [2209] OBJ_id_it_caKeyUpdateInfo */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x06,     /* [2217] OBJ_id_it_currentCRL */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x07,     /* [2225] OBJ_id_it_unsupportedOIDs */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x08,     /* [2233] OBJ_id_it_subscriptionRequest */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x09,     /* [2241] OBJ_id_it_subscriptionResponse */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x0A,     /* [2249] OBJ_id_it_keyPairParamReq */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x0B,     /* [2257] OBJ_id_it_keyPairParamRep */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x0C,     /* [2265] OBJ_id_it_revPassphrase */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x0D,     /* [2273] OBJ_id_it_implicitConfirm */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x0E,     /* [2281] OBJ_id_it_confirmWaitTime */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x0F,     /* [2289] OBJ_id_it_origPKIMessage */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x01,     /* [2297] OBJ_id_regCtrl */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x02,     /* [2305] OBJ_id_regInfo */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x01,0x01,/* [2313] OBJ_id_regCtrl_regToken */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x01,0x02,/* [2322] OBJ_id_regCtrl_authenticator */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x01,0x03,/* [2331] OBJ_id_regCtrl_pkiPublicationInfo */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x01,0x04,/* [2340] OBJ_id_regCtrl_pkiArchiveOptions */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x01,0x05,/* [2349] OBJ_id_regCtrl_oldCertID */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x01,0x06,/* [2358] OBJ_id_regCtrl_protocolEncrKey */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x02,0x01,/* [2367] OBJ_id_regInfo_utf8Pairs */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x02,0x02,/* [2376] OBJ_id_regInfo_certReq */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x06,0x01,     /* [2385] OBJ_id_alg_des40 */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x06,0x02,     /* [2393] OBJ_id_alg_noSignature */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x06,0x03,     /* [2401] OBJ_id_alg_dh_sig_hmac_sha1 */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x06,0x04,     /* [2409] OBJ_id_alg_dh_pop */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x01,     /* [2417] OBJ_id_cmc_statusInfo */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x02,     /* [2425] OBJ_id_cmc_identification */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x03,     /* [2433] OBJ_id_cmc_identityProof */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x04,     /* [2441] OBJ_id_cmc_dataReturn */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x05,     /* [2449] OBJ_id_cmc_transactionId */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x06,     /* [2457] OBJ_id_cmc_senderNonce */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x07,     /* [2465] OBJ_id_cmc_recipientNonce */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x08,     /* [2473] OBJ_id_cmc_addExtensions */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x09,     /* [2481] OBJ_id_cmc_encryptedPOP */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x0A,     /* [2489] OBJ_id_cmc_decryptedPOP */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x0B,     /* [2497] OBJ_id_cmc_lraPOPWitness */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x0F,     /* [2505] OBJ_id_cmc_getCert */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x10,     /* [2513] OBJ_id_cmc_getCRL */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x11,     /* [2521] OBJ_id_cmc_revokeRequest */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x12,     /* [2529] OBJ_id_cmc_regInfo */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x13,     /* [2537] OBJ_id_cmc_responseInfo */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x15,     /* [2545] OBJ_id_cmc_queryPending */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x16,     /* [2553] OBJ_id_cmc_popLinkRandom */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x17,     /* [2561] OBJ_id_cmc_popLinkWitness */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x18,     /* [2569] OBJ_id_cmc_confirmCertAcceptance */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x08,0x01,     /* [2577] OBJ_id_on_personalData */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x09,0x01,     /* [2585] OBJ_id_pda_dateOfBirth */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x09,0x02,     /* [2593] OBJ_id_pda_placeOfBirth */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x09,0x03,     /* [2601] OBJ_id_pda_gender */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x09,0x04,     /* [2609] OBJ_id_pda_countryOfCitizenship */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x09,0x05,     /* [2617] OBJ_id_pda_countryOfResidence */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x0A,0x01,     /* [2625] OBJ_id_aca_authenticationInfo */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x0A,0x02,     /* [2633] OBJ_id_aca_accessIdentity */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x0A,0x03,     /* [2641] OBJ_id_aca_chargingIdentity */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x0A,0x04,     /* [2649] OBJ_id_aca_group */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x0A,0x05,     /* [2657] OBJ_id_aca_role */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x0B,0x01,     /* [2665] OBJ_id_qcs_pkixQCSyntax_v1 */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x0C,0x01,     /* [2673] OBJ_id_cct_crs */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x0C,0x02,     /* [2681] OBJ_id_cct_PKIData */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x0C,0x03,     /* [2689] OBJ_id_cct_PKIResponse */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x03,     /* [2697] OBJ_ad_timeStamping */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x04,     /* [2705] OBJ_ad_dvcs */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x01,/* [2713] OBJ_id_pkix_OCSP_basic */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x02,/* [2722] OBJ_id_pkix_OCSP_Nonce */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x03,/* [2731] OBJ_id_pkix_OCSP_CrlID */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x04,/* [2740] OBJ_id_pkix_OCSP_acceptableResponses */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x05,/* [2749] OBJ_id_pkix_OCSP_noCheck */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x06,/* [2758] OBJ_id_pkix_OCSP_archiveCutoff */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x07,/* [2767] OBJ_id_pkix_OCSP_serviceLocator */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x08,/* [2776] OBJ_id_pkix_OCSP_extendedStatus */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x09,/* [2785] OBJ_id_pkix_OCSP_valid */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x0A,/* [2794] OBJ_id_pkix_OCSP_path */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x0B,/* [2803] OBJ_id_pkix_OCSP_trustRoot */
-0x2B,0x0E,0x03,0x02,                         /* [2812] OBJ_algorithm */
-0x2B,0x0E,0x03,0x02,0x0B,                    /* [2816] OBJ_rsaSignature */
-0x55,0x08,                                   /* [2821] OBJ_X500algorithms */
-0x2B,                                        /* [2823] OBJ_org */
-0x2B,0x06,                                   /* [2824] OBJ_dod */
-0x2B,0x06,0x01,                              /* [2826] OBJ_iana */
-0x2B,0x06,0x01,0x01,                         /* [2829] OBJ_Directory */
-0x2B,0x06,0x01,0x02,                         /* [2833] OBJ_Management */
-0x2B,0x06,0x01,0x03,                         /* [2837] OBJ_Experimental */
-0x2B,0x06,0x01,0x04,                         /* [2841] OBJ_Private */
-0x2B,0x06,0x01,0x05,                         /* [2845] OBJ_Security */
-0x2B,0x06,0x01,0x06,                         /* [2849] OBJ_SNMPv2 */
-0x2B,0x06,0x01,0x07,                         /* [2853] OBJ_Mail */
-0x2B,0x06,0x01,0x04,0x01,                    /* [2857] OBJ_Enterprises */
-0x2B,0x06,0x01,0x04,0x01,0x8B,0x3A,0x82,0x58,/* [2862] OBJ_dcObject */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x19,/* [2871] OBJ_domainComponent */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x0D,/* [2881] OBJ_Domain */
-0x55,0x01,0x05,                              /* [2891] OBJ_selected_attribute_types */
-0x55,0x01,0x05,0x37,                         /* [2894] OBJ_clearance */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x03,/* [2898] OBJ_md4WithRSAEncryption */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x0A,     /* [2907] OBJ_ac_proxying */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x0B,     /* [2915] OBJ_sinfo_access */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x0A,0x06,     /* [2923] OBJ_id_aca_encAttrs */
-0x55,0x04,0x48,                              /* [2931] OBJ_role */
-0x55,0x1D,0x24,                              /* [2934] OBJ_policy_constraints */
-0x55,0x1D,0x37,                              /* [2937] OBJ_target_information */
-0x55,0x1D,0x38,                              /* [2940] OBJ_no_rev_avail */
-0x2A,0x86,0x48,0xCE,0x3D,                    /* [2943] OBJ_ansi_X9_62 */
-0x2A,0x86,0x48,0xCE,0x3D,0x01,0x01,          /* [2948] OBJ_X9_62_prime_field */
-0x2A,0x86,0x48,0xCE,0x3D,0x01,0x02,          /* [2955] OBJ_X9_62_characteristic_two_field */
-0x2A,0x86,0x48,0xCE,0x3D,0x02,0x01,          /* [2962] OBJ_X9_62_id_ecPublicKey */
-0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x01,     /* [2969] OBJ_X9_62_prime192v1 */
-0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x02,     /* [2977] OBJ_X9_62_prime192v2 */
-0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x03,     /* [2985] OBJ_X9_62_prime192v3 */
-0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x04,     /* [2993] OBJ_X9_62_prime239v1 */
-0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x05,     /* [3001] OBJ_X9_62_prime239v2 */
-0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x06,     /* [3009] OBJ_X9_62_prime239v3 */
-0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07,     /* [3017] OBJ_X9_62_prime256v1 */
-0x2A,0x86,0x48,0xCE,0x3D,0x04,0x01,          /* [3025] OBJ_ecdsa_with_SHA1 */
-0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x11,0x01,/* [3032] OBJ_ms_csp_name */
-0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x01,/* [3041] OBJ_aes_128_ecb */
-0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x02,/* [3050] OBJ_aes_128_cbc */
-0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x03,/* [3059] OBJ_aes_128_ofb128 */
-0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x04,/* [3068] OBJ_aes_128_cfb128 */
-0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x15,/* [3077] OBJ_aes_192_ecb */
-0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x16,/* [3086] OBJ_aes_192_cbc */
-0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x17,/* [3095] OBJ_aes_192_ofb128 */
-0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x18,/* [3104] OBJ_aes_192_cfb128 */
-0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x29,/* [3113] OBJ_aes_256_ecb */
-0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x2A,/* [3122] OBJ_aes_256_cbc */
-0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x2B,/* [3131] OBJ_aes_256_ofb128 */
-0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x2C,/* [3140] OBJ_aes_256_cfb128 */
-0x55,0x1D,0x17,                              /* [3149] OBJ_hold_instruction_code */
-0x2A,0x86,0x48,0xCE,0x38,0x02,0x01,          /* [3152] OBJ_hold_instruction_none */
-0x2A,0x86,0x48,0xCE,0x38,0x02,0x02,          /* [3159] OBJ_hold_instruction_call_issuer */
-0x2A,0x86,0x48,0xCE,0x38,0x02,0x03,          /* [3166] OBJ_hold_instruction_reject */
-0x09,                                        /* [3173] OBJ_data */
-0x09,0x92,0x26,                              /* [3174] OBJ_pss */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,          /* [3177] OBJ_ucl */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,     /* [3184] OBJ_pilot */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,/* [3192] OBJ_pilotAttributeType */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x03,/* [3201] OBJ_pilotAttributeSyntax */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,/* [3210] OBJ_pilotObjectClass */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x0A,/* [3219] OBJ_pilotGroups */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x03,0x04,/* [3228] OBJ_iA5StringSyntax */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x03,0x05,/* [3238] OBJ_caseIgnoreIA5StringSyntax */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x03,/* [3248] OBJ_pilotObject */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x04,/* [3258] OBJ_pilotPerson */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x05,/* [3268] OBJ_account */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x06,/* [3278] OBJ_document */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x07,/* [3288] OBJ_room */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x09,/* [3298] OBJ_documentSeries */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x0E,/* [3308] OBJ_rFC822localPart */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x0F,/* [3318] OBJ_dNSDomain */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x11,/* [3328] OBJ_domainRelatedObject */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x12,/* [3338] OBJ_friendlyCountry */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x13,/* [3348] OBJ_simpleSecurityObject */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x14,/* [3358] OBJ_pilotOrganization */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x15,/* [3368] OBJ_pilotDSA */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x16,/* [3378] OBJ_qualityLabelledData */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x01,/* [3388] OBJ_userId */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x02,/* [3398] OBJ_textEncodedORAddress */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x03,/* [3408] OBJ_rfc822Mailbox */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x04,/* [3418] OBJ_info */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x05,/* [3428] OBJ_favouriteDrink */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x06,/* [3438] OBJ_roomNumber */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x07,/* [3448] OBJ_photo */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x08,/* [3458] OBJ_userClass */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x09,/* [3468] OBJ_host */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x0A,/* [3478] OBJ_manager */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x0B,/* [3488] OBJ_documentIdentifier */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x0C,/* [3498] OBJ_documentTitle */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x0D,/* [3508] OBJ_documentVersion */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x0E,/* [3518] OBJ_documentAuthor */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x0F,/* [3528] OBJ_documentLocation */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x14,/* [3538] OBJ_homeTelephoneNumber */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x15,/* [3548] OBJ_secretary */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x16,/* [3558] OBJ_otherMailbox */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x17,/* [3568] OBJ_lastModifiedTime */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x18,/* [3578] OBJ_lastModifiedBy */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x1A,/* [3588] OBJ_aRecord */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x1B,/* [3598] OBJ_pilotAttributeType27 */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x1C,/* [3608] OBJ_mXRecord */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x1D,/* [3618] OBJ_nSRecord */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x1E,/* [3628] OBJ_sOARecord */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x1F,/* [3638] OBJ_cNAMERecord */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x25,/* [3648] OBJ_associatedDomain */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x26,/* [3658] OBJ_associatedName */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x27,/* [3668] OBJ_homePostalAddress */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x28,/* [3678] OBJ_personalTitle */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x29,/* [3688] OBJ_mobileTelephoneNumber */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x2A,/* [3698] OBJ_pagerTelephoneNumber */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x2B,/* [3708] OBJ_friendlyCountryName */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x2D,/* [3718] OBJ_organizationalStatus */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x2E,/* [3728] OBJ_janetMailbox */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x2F,/* [3738] OBJ_mailPreferenceOption */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x30,/* [3748] OBJ_buildingName */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x31,/* [3758] OBJ_dSAQuality */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x32,/* [3768] OBJ_singleLevelQuality */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x33,/* [3778] OBJ_subtreeMinimumQuality */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x34,/* [3788] OBJ_subtreeMaximumQuality */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x35,/* [3798] OBJ_personalSignature */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x36,/* [3808] OBJ_dITRedirect */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x37,/* [3818] OBJ_audio */
-0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x38,/* [3828] OBJ_documentPublisher */
-0x55,0x04,0x2D,                              /* [3838] OBJ_x500UniqueIdentifier */
-0x2B,0x06,0x01,0x07,0x01,                    /* [3841] OBJ_mime_mhs */
-0x2B,0x06,0x01,0x07,0x01,0x01,               /* [3846] OBJ_mime_mhs_headings */
-0x2B,0x06,0x01,0x07,0x01,0x02,               /* [3852] OBJ_mime_mhs_bodies */
-0x2B,0x06,0x01,0x07,0x01,0x01,0x01,          /* [3858] OBJ_id_hex_partial_message */
-0x2B,0x06,0x01,0x07,0x01,0x01,0x02,          /* [3865] OBJ_id_hex_multipart_message */
-0x55,0x04,0x2C,                              /* [3872] OBJ_generationQualifier */
-0x55,0x04,0x41,                              /* [3875] OBJ_pseudonym */
-0x67,0x2A,                                   /* [3878] OBJ_id_set */
-0x67,0x2A,0x00,                              /* [3880] OBJ_set_ctype */
-0x67,0x2A,0x01,                              /* [3883] OBJ_set_msgExt */
-0x67,0x2A,0x03,                              /* [3886] OBJ_set_attr */
-0x67,0x2A,0x05,                              /* [3889] OBJ_set_policy */
-0x67,0x2A,0x07,                              /* [3892] OBJ_set_certExt */
-0x67,0x2A,0x08,                              /* [3895] OBJ_set_brand */
-0x67,0x2A,0x00,0x00,                         /* [3898] OBJ_setct_PANData */
-0x67,0x2A,0x00,0x01,                         /* [3902] OBJ_setct_PANToken */
-0x67,0x2A,0x00,0x02,                         /* [3906] OBJ_setct_PANOnly */
-0x67,0x2A,0x00,0x03,                         /* [3910] OBJ_setct_OIData */
-0x67,0x2A,0x00,0x04,                         /* [3914] OBJ_setct_PI */
-0x67,0x2A,0x00,0x05,                         /* [3918] OBJ_setct_PIData */
-0x67,0x2A,0x00,0x06,                         /* [3922] OBJ_setct_PIDataUnsigned */
-0x67,0x2A,0x00,0x07,                         /* [3926] OBJ_setct_HODInput */
-0x67,0x2A,0x00,0x08,                         /* [3930] OBJ_setct_AuthResBaggage */
-0x67,0x2A,0x00,0x09,                         /* [3934] OBJ_setct_AuthRevReqBaggage */
-0x67,0x2A,0x00,0x0A,                         /* [3938] OBJ_setct_AuthRevResBaggage */
-0x67,0x2A,0x00,0x0B,                         /* [3942] OBJ_setct_CapTokenSeq */
-0x67,0x2A,0x00,0x0C,                         /* [3946] OBJ_setct_PInitResData */
-0x67,0x2A,0x00,0x0D,                         /* [3950] OBJ_setct_PI_TBS */
-0x67,0x2A,0x00,0x0E,                         /* [3954] OBJ_setct_PResData */
-0x67,0x2A,0x00,0x10,                         /* [3958] OBJ_setct_AuthReqTBS */
-0x67,0x2A,0x00,0x11,                         /* [3962] OBJ_setct_AuthResTBS */
-0x67,0x2A,0x00,0x12,                         /* [3966] OBJ_setct_AuthResTBSX */
-0x67,0x2A,0x00,0x13,                         /* [3970] OBJ_setct_AuthTokenTBS */
-0x67,0x2A,0x00,0x14,                         /* [3974] OBJ_setct_CapTokenData */
-0x67,0x2A,0x00,0x15,                         /* [3978] OBJ_setct_CapTokenTBS */
-0x67,0x2A,0x00,0x16,                         /* [3982] OBJ_setct_AcqCardCodeMsg */
-0x67,0x2A,0x00,0x17,                         /* [3986] OBJ_setct_AuthRevReqTBS */
-0x67,0x2A,0x00,0x18,                         /* [3990] OBJ_setct_AuthRevResData */
-0x67,0x2A,0x00,0x19,                         /* [3994] OBJ_setct_AuthRevResTBS */
-0x67,0x2A,0x00,0x1A,                         /* [3998] OBJ_setct_CapReqTBS */
-0x67,0x2A,0x00,0x1B,                         /* [4002] OBJ_setct_CapReqTBSX */
-0x67,0x2A,0x00,0x1C,                         /* [4006] OBJ_setct_CapResData */
-0x67,0x2A,0x00,0x1D,                         /* [4010] OBJ_setct_CapRevReqTBS */
-0x67,0x2A,0x00,0x1E,                         /* [4014] OBJ_setct_CapRevReqTBSX */
-0x67,0x2A,0x00,0x1F,                         /* [4018] OBJ_setct_CapRevResData */
-0x67,0x2A,0x00,0x20,                         /* [4022] OBJ_setct_CredReqTBS */
-0x67,0x2A,0x00,0x21,                         /* [4026] OBJ_setct_CredReqTBSX */
-0x67,0x2A,0x00,0x22,                         /* [4030] OBJ_setct_CredResData */
-0x67,0x2A,0x00,0x23,                         /* [4034] OBJ_setct_CredRevReqTBS */
-0x67,0x2A,0x00,0x24,                         /* [4038] OBJ_setct_CredRevReqTBSX */
-0x67,0x2A,0x00,0x25,                         /* [4042] OBJ_setct_CredRevResData */
-0x67,0x2A,0x00,0x26,                         /* [4046] OBJ_setct_PCertReqData */
-0x67,0x2A,0x00,0x27,                         /* [4050] OBJ_setct_PCertResTBS */
-0x67,0x2A,0x00,0x28,                         /* [4054] OBJ_setct_BatchAdminReqData */
-0x67,0x2A,0x00,0x29,                         /* [4058] OBJ_setct_BatchAdminResData */
-0x67,0x2A,0x00,0x2A,                         /* [4062] OBJ_setct_CardCInitResTBS */
-0x67,0x2A,0x00,0x2B,                         /* [4066] OBJ_setct_MeAqCInitResTBS */
-0x67,0x2A,0x00,0x2C,                         /* [4070] OBJ_setct_RegFormResTBS */
-0x67,0x2A,0x00,0x2D,                         /* [4074] OBJ_setct_CertReqData */
-0x67,0x2A,0x00,0x2E,                         /* [4078] OBJ_setct_CertReqTBS */
-0x67,0x2A,0x00,0x2F,                         /* [4082] OBJ_setct_CertResData */
-0x67,0x2A,0x00,0x30,                         /* [4086] OBJ_setct_CertInqReqTBS */
-0x67,0x2A,0x00,0x31,                         /* [4090] OBJ_setct_ErrorTBS */
-0x67,0x2A,0x00,0x32,                         /* [4094] OBJ_setct_PIDualSignedTBE */
-0x67,0x2A,0x00,0x33,                         /* [4098] OBJ_setct_PIUnsignedTBE */
-0x67,0x2A,0x00,0x34,                         /* [4102] OBJ_setct_AuthReqTBE */
-0x67,0x2A,0x00,0x35,                         /* [4106] OBJ_setct_AuthResTBE */
-0x67,0x2A,0x00,0x36,                         /* [4110] OBJ_setct_AuthResTBEX */
-0x67,0x2A,0x00,0x37,                         /* [4114] OBJ_setct_AuthTokenTBE */
-0x67,0x2A,0x00,0x38,                         /* [4118] OBJ_setct_CapTokenTBE */
-0x67,0x2A,0x00,0x39,                         /* [4122] OBJ_setct_CapTokenTBEX */
-0x67,0x2A,0x00,0x3A,                         /* [4126] OBJ_setct_AcqCardCodeMsgTBE */
-0x67,0x2A,0x00,0x3B,                         /* [4130] OBJ_setct_AuthRevReqTBE */
-0x67,0x2A,0x00,0x3C,                         /* [4134] OBJ_setct_AuthRevResTBE */
-0x67,0x2A,0x00,0x3D,                         /* [4138] OBJ_setct_AuthRevResTBEB */
-0x67,0x2A,0x00,0x3E,                         /* [4142] OBJ_setct_CapReqTBE */
-0x67,0x2A,0x00,0x3F,                         /* [4146] OBJ_setct_CapReqTBEX */
-0x67,0x2A,0x00,0x40,                         /* [4150] OBJ_setct_CapResTBE */
-0x67,0x2A,0x00,0x41,                         /* [4154] OBJ_setct_CapRevReqTBE */
-0x67,0x2A,0x00,0x42,                         /* [4158] OBJ_setct_CapRevReqTBEX */
-0x67,0x2A,0x00,0x43,                         /* [4162] OBJ_setct_CapRevResTBE */
-0x67,0x2A,0x00,0x44,                         /* [4166] OBJ_setct_CredReqTBE */
-0x67,0x2A,0x00,0x45,                         /* [4170] OBJ_setct_CredReqTBEX */
-0x67,0x2A,0x00,0x46,                         /* [4174] OBJ_setct_CredResTBE */
-0x67,0x2A,0x00,0x47,                         /* [4178] OBJ_setct_CredRevReqTBE */
-0x67,0x2A,0x00,0x48,                         /* [4182] OBJ_setct_CredRevReqTBEX */
-0x67,0x2A,0x00,0x49,                         /* [4186] OBJ_setct_CredRevResTBE */
-0x67,0x2A,0x00,0x4A,                         /* [4190] OBJ_setct_BatchAdminReqTBE */
-0x67,0x2A,0x00,0x4B,                         /* [4194] OBJ_setct_BatchAdminResTBE */
-0x67,0x2A,0x00,0x4C,                         /* [4198] OBJ_setct_RegFormReqTBE */
-0x67,0x2A,0x00,0x4D,                         /* [4202] OBJ_setct_CertReqTBE */
-0x67,0x2A,0x00,0x4E,                         /* [4206] OBJ_setct_CertReqTBEX */
-0x67,0x2A,0x00,0x4F,                         /* [4210] OBJ_setct_CertResTBE */
-0x67,0x2A,0x00,0x50,                         /* [4214] OBJ_setct_CRLNotificationTBS */
-0x67,0x2A,0x00,0x51,                         /* [4218] OBJ_setct_CRLNotificationResTBS */
-0x67,0x2A,0x00,0x52,                         /* [4222] OBJ_setct_BCIDistributionTBS */
-0x67,0x2A,0x01,0x01,                         /* [4226] OBJ_setext_genCrypt */
-0x67,0x2A,0x01,0x03,                         /* [4230] OBJ_setext_miAuth */
-0x67,0x2A,0x01,0x04,                         /* [4234] OBJ_setext_pinSecure */
-0x67,0x2A,0x01,0x05,                         /* [4238] OBJ_setext_pinAny */
-0x67,0x2A,0x01,0x07,                         /* [4242] OBJ_setext_track2 */
-0x67,0x2A,0x01,0x08,                         /* [4246] OBJ_setext_cv */
-0x67,0x2A,0x05,0x00,                         /* [4250] OBJ_set_policy_root */
-0x67,0x2A,0x07,0x00,                         /* [4254] OBJ_setCext_hashedRoot */
-0x67,0x2A,0x07,0x01,                         /* [4258] OBJ_setCext_certType */
-0x67,0x2A,0x07,0x02,                         /* [4262] OBJ_setCext_merchData */
-0x67,0x2A,0x07,0x03,                         /* [4266] OBJ_setCext_cCertRequired */
-0x67,0x2A,0x07,0x04,                         /* [4270] OBJ_setCext_tunneling */
-0x67,0x2A,0x07,0x05,                         /* [4274] OBJ_setCext_setExt */
-0x67,0x2A,0x07,0x06,                         /* [4278] OBJ_setCext_setQualf */
-0x67,0x2A,0x07,0x07,                         /* [4282] OBJ_setCext_PGWYcapabilities */
-0x67,0x2A,0x07,0x08,                         /* [4286] OBJ_setCext_TokenIdentifier */
-0x67,0x2A,0x07,0x09,                         /* [4290] OBJ_setCext_Track2Data */
-0x67,0x2A,0x07,0x0A,                         /* [4294] OBJ_setCext_TokenType */
-0x67,0x2A,0x07,0x0B,                         /* [4298] OBJ_setCext_IssuerCapabilities */
-0x67,0x2A,0x03,0x00,                         /* [4302] OBJ_setAttr_Cert */
-0x67,0x2A,0x03,0x01,                         /* [4306] OBJ_setAttr_PGWYcap */
-0x67,0x2A,0x03,0x02,                         /* [4310] OBJ_setAttr_TokenType */
-0x67,0x2A,0x03,0x03,                         /* [4314] OBJ_setAttr_IssCap */
-0x67,0x2A,0x03,0x00,0x00,                    /* [4318] OBJ_set_rootKeyThumb */
-0x67,0x2A,0x03,0x00,0x01,                    /* [4323] OBJ_set_addPolicy */
-0x67,0x2A,0x03,0x02,0x01,                    /* [4328] OBJ_setAttr_Token_EMV */
-0x67,0x2A,0x03,0x02,0x02,                    /* [4333] OBJ_setAttr_Token_B0Prime */
-0x67,0x2A,0x03,0x03,0x03,                    /* [4338] OBJ_setAttr_IssCap_CVM */
-0x67,0x2A,0x03,0x03,0x04,                    /* [4343] OBJ_setAttr_IssCap_T2 */
-0x67,0x2A,0x03,0x03,0x05,                    /* [4348] OBJ_setAttr_IssCap_Sig */
-0x67,0x2A,0x03,0x03,0x03,0x01,               /* [4353] OBJ_setAttr_GenCryptgrm */
-0x67,0x2A,0x03,0x03,0x04,0x01,               /* [4359] OBJ_setAttr_T2Enc */
-0x67,0x2A,0x03,0x03,0x04,0x02,               /* [4365] OBJ_setAttr_T2cleartxt */
-0x67,0x2A,0x03,0x03,0x05,0x01,               /* [4371] OBJ_setAttr_TokICCsig */
-0x67,0x2A,0x03,0x03,0x05,0x02,               /* [4377] OBJ_setAttr_SecDevSig */
-0x67,0x2A,0x08,0x01,                         /* [4383] OBJ_set_brand_IATA_ATA */
-0x67,0x2A,0x08,0x1E,                         /* [4387] OBJ_set_brand_Diners */
-0x67,0x2A,0x08,0x22,                         /* [4391] OBJ_set_brand_AmericanExpress */
-0x67,0x2A,0x08,0x23,                         /* [4395] OBJ_set_brand_JCB */
-0x67,0x2A,0x08,0x04,                         /* [4399] OBJ_set_brand_Visa */
-0x67,0x2A,0x08,0x05,                         /* [4403] OBJ_set_brand_MasterCard */
-0x67,0x2A,0x08,0xAE,0x7B,                    /* [4407] OBJ_set_brand_Novus */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x03,0x0A,     /* [4412] OBJ_des_cdmf */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x06,/* [4420] OBJ_rsaOAEPEncryptionSET */
-0x67,                                        /* [4429] OBJ_international_organizations */
-0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x14,0x02,0x02,/* [4430] OBJ_ms_smartcard_login */
-0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x14,0x02,0x03,/* [4440] OBJ_ms_upn */
-0x55,0x04,0x09,                              /* [4450] OBJ_streetAddress */
-0x55,0x04,0x11,                              /* [4453] OBJ_postalCode */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x15,          /* [4456] OBJ_id_ppl */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x0E,     /* [4463] OBJ_proxyCertInfo */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x15,0x00,     /* [4471] OBJ_id_ppl_anyLanguage */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x15,0x01,     /* [4479] OBJ_id_ppl_inheritAll */
-0x55,0x1D,0x1E,                              /* [4487] OBJ_name_constraints */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x15,0x02,     /* [4490] OBJ_Independent */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B,/* [4498] OBJ_sha256WithRSAEncryption */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0C,/* [4507] OBJ_sha384WithRSAEncryption */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0D,/* [4516] OBJ_sha512WithRSAEncryption */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0E,/* [4525] OBJ_sha224WithRSAEncryption */
-0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01,/* [4534] OBJ_sha256 */
-0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02,/* [4543] OBJ_sha384 */
-0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03,/* [4552] OBJ_sha512 */
-0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x04,/* [4561] OBJ_sha224 */
-0x2B,                                        /* [4570] OBJ_identified_organization */
-0x2B,0x81,0x04,                              /* [4571] OBJ_certicom_arc */
-0x67,0x2B,                                   /* [4574] OBJ_wap */
-0x67,0x2B,0x01,                              /* [4576] OBJ_wap_wsg */
-0x2A,0x86,0x48,0xCE,0x3D,0x01,0x02,0x03,     /* [4579] OBJ_X9_62_id_characteristic_two_basis */
-0x2A,0x86,0x48,0xCE,0x3D,0x01,0x02,0x03,0x01,/* [4587] OBJ_X9_62_onBasis */
-0x2A,0x86,0x48,0xCE,0x3D,0x01,0x02,0x03,0x02,/* [4596] OBJ_X9_62_tpBasis */
-0x2A,0x86,0x48,0xCE,0x3D,0x01,0x02,0x03,0x03,/* [4605] OBJ_X9_62_ppBasis */
-0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x01,     /* [4614] OBJ_X9_62_c2pnb163v1 */
-0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x02,     /* [4622] OBJ_X9_62_c2pnb163v2 */
-0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x03,     /* [4630] OBJ_X9_62_c2pnb163v3 */
-0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x04,     /* [4638] OBJ_X9_62_c2pnb176v1 */
-0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x05,     /* [4646] OBJ_X9_62_c2tnb191v1 */
-0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x06,     /* [4654] OBJ_X9_62_c2tnb191v2 */
-0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x07,     /* [4662] OBJ_X9_62_c2tnb191v3 */
-0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x08,     /* [4670] OBJ_X9_62_c2onb191v4 */
-0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x09,     /* [4678] OBJ_X9_62_c2onb191v5 */
-0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x0A,     /* [4686] OBJ_X9_62_c2pnb208w1 */
-0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x0B,     /* [4694] OBJ_X9_62_c2tnb239v1 */
-0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x0C,     /* [4702] OBJ_X9_62_c2tnb239v2 */
-0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x0D,     /* [4710] OBJ_X9_62_c2tnb239v3 */
-0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x0E,     /* [4718] OBJ_X9_62_c2onb239v4 */
-0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x0F,     /* [4726] OBJ_X9_62_c2onb239v5 */
-0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x10,     /* [4734] OBJ_X9_62_c2pnb272w1 */
-0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x11,     /* [4742] OBJ_X9_62_c2pnb304w1 */
-0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x12,     /* [4750] OBJ_X9_62_c2tnb359v1 */
-0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x13,     /* [4758] OBJ_X9_62_c2pnb368w1 */
-0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x14,     /* [4766] OBJ_X9_62_c2tnb431r1 */
-0x2B,0x81,0x04,0x00,0x06,                    /* [4774] OBJ_secp112r1 */
-0x2B,0x81,0x04,0x00,0x07,                    /* [4779] OBJ_secp112r2 */
-0x2B,0x81,0x04,0x00,0x1C,                    /* [4784] OBJ_secp128r1 */
-0x2B,0x81,0x04,0x00,0x1D,                    /* [4789] OBJ_secp128r2 */
-0x2B,0x81,0x04,0x00,0x09,                    /* [4794] OBJ_secp160k1 */
-0x2B,0x81,0x04,0x00,0x08,                    /* [4799] OBJ_secp160r1 */
-0x2B,0x81,0x04,0x00,0x1E,                    /* [4804] OBJ_secp160r2 */
-0x2B,0x81,0x04,0x00,0x1F,                    /* [4809] OBJ_secp192k1 */
-0x2B,0x81,0x04,0x00,0x20,                    /* [4814] OBJ_secp224k1 */
-0x2B,0x81,0x04,0x00,0x21,                    /* [4819] OBJ_secp224r1 */
-0x2B,0x81,0x04,0x00,0x0A,                    /* [4824] OBJ_secp256k1 */
-0x2B,0x81,0x04,0x00,0x22,                    /* [4829] OBJ_secp384r1 */
-0x2B,0x81,0x04,0x00,0x23,                    /* [4834] OBJ_secp521r1 */
-0x2B,0x81,0x04,0x00,0x04,                    /* [4839] OBJ_sect113r1 */
-0x2B,0x81,0x04,0x00,0x05,                    /* [4844] OBJ_sect113r2 */
-0x2B,0x81,0x04,0x00,0x16,                    /* [4849] OBJ_sect131r1 */
-0x2B,0x81,0x04,0x00,0x17,                    /* [4854] OBJ_sect131r2 */
-0x2B,0x81,0x04,0x00,0x01,                    /* [4859] OBJ_sect163k1 */
-0x2B,0x81,0x04,0x00,0x02,                    /* [4864] OBJ_sect163r1 */
-0x2B,0x81,0x04,0x00,0x0F,                    /* [4869] OBJ_sect163r2 */
-0x2B,0x81,0x04,0x00,0x18,                    /* [4874] OBJ_sect193r1 */
-0x2B,0x81,0x04,0x00,0x19,                    /* [4879] OBJ_sect193r2 */
-0x2B,0x81,0x04,0x00,0x1A,                    /* [4884] OBJ_sect233k1 */
-0x2B,0x81,0x04,0x00,0x1B,                    /* [4889] OBJ_sect233r1 */
-0x2B,0x81,0x04,0x00,0x03,                    /* [4894] OBJ_sect239k1 */
-0x2B,0x81,0x04,0x00,0x10,                    /* [4899] OBJ_sect283k1 */
-0x2B,0x81,0x04,0x00,0x11,                    /* [4904] OBJ_sect283r1 */
-0x2B,0x81,0x04,0x00,0x24,                    /* [4909] OBJ_sect409k1 */
-0x2B,0x81,0x04,0x00,0x25,                    /* [4914] OBJ_sect409r1 */
-0x2B,0x81,0x04,0x00,0x26,                    /* [4919] OBJ_sect571k1 */
-0x2B,0x81,0x04,0x00,0x27,                    /* [4924] OBJ_sect571r1 */
-0x67,0x2B,0x01,0x04,0x01,                    /* [4929] OBJ_wap_wsg_idm_ecid_wtls1 */
-0x67,0x2B,0x01,0x04,0x03,                    /* [4934] OBJ_wap_wsg_idm_ecid_wtls3 */
-0x67,0x2B,0x01,0x04,0x04,                    /* [4939] OBJ_wap_wsg_idm_ecid_wtls4 */
-0x67,0x2B,0x01,0x04,0x05,                    /* [4944] OBJ_wap_wsg_idm_ecid_wtls5 */
-0x67,0x2B,0x01,0x04,0x06,                    /* [4949] OBJ_wap_wsg_idm_ecid_wtls6 */
-0x67,0x2B,0x01,0x04,0x07,                    /* [4954] OBJ_wap_wsg_idm_ecid_wtls7 */
-0x67,0x2B,0x01,0x04,0x08,                    /* [4959] OBJ_wap_wsg_idm_ecid_wtls8 */
-0x67,0x2B,0x01,0x04,0x09,                    /* [4964] OBJ_wap_wsg_idm_ecid_wtls9 */
-0x67,0x2B,0x01,0x04,0x0A,                    /* [4969] OBJ_wap_wsg_idm_ecid_wtls10 */
-0x67,0x2B,0x01,0x04,0x0B,                    /* [4974] OBJ_wap_wsg_idm_ecid_wtls11 */
-0x67,0x2B,0x01,0x04,0x0C,                    /* [4979] OBJ_wap_wsg_idm_ecid_wtls12 */
-0x55,0x1D,0x20,0x00,                         /* [4984] OBJ_any_policy */
-0x55,0x1D,0x21,                              /* [4988] OBJ_policy_mappings */
-0x55,0x1D,0x36,                              /* [4991] OBJ_inhibit_any_policy */
-0x2A,0x83,0x08,0x8C,0x9A,0x4B,0x3D,0x01,0x01,0x01,0x02,/* [4994] OBJ_camellia_128_cbc */
-0x2A,0x83,0x08,0x8C,0x9A,0x4B,0x3D,0x01,0x01,0x01,0x03,/* [5005] OBJ_camellia_192_cbc */
-0x2A,0x83,0x08,0x8C,0x9A,0x4B,0x3D,0x01,0x01,0x01,0x04,/* [5016] OBJ_camellia_256_cbc */
-0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x01,     /* [5027] OBJ_camellia_128_ecb */
-0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x15,     /* [5035] OBJ_camellia_192_ecb */
-0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x29,     /* [5043] OBJ_camellia_256_ecb */
-0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x04,     /* [5051] OBJ_camellia_128_cfb128 */
-0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x18,     /* [5059] OBJ_camellia_192_cfb128 */
-0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x2C,     /* [5067] OBJ_camellia_256_cfb128 */
-0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x03,     /* [5075] OBJ_camellia_128_ofb128 */
-0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x17,     /* [5083] OBJ_camellia_192_ofb128 */
-0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x2B,     /* [5091] OBJ_camellia_256_ofb128 */
-0x55,0x1D,0x09,                              /* [5099] OBJ_subject_directory_attributes */
-0x55,0x1D,0x1C,                              /* [5102] OBJ_issuing_distribution_point */
-0x55,0x1D,0x1D,                              /* [5105] OBJ_certificate_issuer */
-0x2A,0x83,0x1A,0x8C,0x9A,0x44,               /* [5108] OBJ_kisa */
-0x2A,0x83,0x1A,0x8C,0x9A,0x44,0x01,0x03,     /* [5114] OBJ_seed_ecb */
-0x2A,0x83,0x1A,0x8C,0x9A,0x44,0x01,0x04,     /* [5122] OBJ_seed_cbc */
-0x2A,0x83,0x1A,0x8C,0x9A,0x44,0x01,0x06,     /* [5130] OBJ_seed_ofb128 */
-0x2A,0x83,0x1A,0x8C,0x9A,0x44,0x01,0x05,     /* [5138] OBJ_seed_cfb128 */
-0x2B,0x06,0x01,0x05,0x05,0x08,0x01,0x01,     /* [5146] OBJ_hmac_md5 */
-0x2B,0x06,0x01,0x05,0x05,0x08,0x01,0x02,     /* [5154] OBJ_hmac_sha1 */
-0x2A,0x86,0x48,0x86,0xF6,0x7D,0x07,0x42,0x0D,/* [5162] OBJ_id_PasswordBasedMAC */
-0x2A,0x86,0x48,0x86,0xF6,0x7D,0x07,0x42,0x1E,/* [5171] OBJ_id_DHBasedMac */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x10,     /* [5180] OBJ_id_it_suppLangTags */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x05,     /* [5188] OBJ_caRepository */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x09,/* [5196] OBJ_id_smime_ct_compressedData */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x1B,/* [5207] OBJ_id_ct_asciiTextWithCRLF */
-0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x05,/* [5218] OBJ_id_aes128_wrap */
-0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x19,/* [5227] OBJ_id_aes192_wrap */
-0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x2D,/* [5236] OBJ_id_aes256_wrap */
-0x2A,0x86,0x48,0xCE,0x3D,0x04,0x02,          /* [5245] OBJ_ecdsa_with_Recommended */
-0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,          /* [5252] OBJ_ecdsa_with_Specified */
-0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x01,     /* [5259] OBJ_ecdsa_with_SHA224 */
-0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x02,     /* [5267] OBJ_ecdsa_with_SHA256 */
-0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x03,     /* [5275] OBJ_ecdsa_with_SHA384 */
-0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x04,     /* [5283] OBJ_ecdsa_with_SHA512 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x06,     /* [5291] OBJ_hmacWithMD5 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x08,     /* [5299] OBJ_hmacWithSHA224 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x09,     /* [5307] OBJ_hmacWithSHA256 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x0A,     /* [5315] OBJ_hmacWithSHA384 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x0B,     /* [5323] OBJ_hmacWithSHA512 */
-0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x01,/* [5331] OBJ_dsa_with_SHA224 */
-0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x02,/* [5340] OBJ_dsa_with_SHA256 */
-0x28,0xCF,0x06,0x03,0x00,0x37,               /* [5349] OBJ_whirlpool */
-0x2A,0x85,0x03,0x02,0x02,                    /* [5355] OBJ_cryptopro */
-0x2A,0x85,0x03,0x02,0x09,                    /* [5360] OBJ_cryptocom */
-0x2A,0x85,0x03,0x02,0x02,0x03,               /* [5365] OBJ_id_GostR3411_94_with_GostR3410_2001 */
-0x2A,0x85,0x03,0x02,0x02,0x04,               /* [5371] OBJ_id_GostR3411_94_with_GostR3410_94 */
-0x2A,0x85,0x03,0x02,0x02,0x09,               /* [5377] OBJ_id_GostR3411_94 */
-0x2A,0x85,0x03,0x02,0x02,0x0A,               /* [5383] OBJ_id_HMACGostR3411_94 */
-0x2A,0x85,0x03,0x02,0x02,0x13,               /* [5389] OBJ_id_GostR3410_2001 */
-0x2A,0x85,0x03,0x02,0x02,0x14,               /* [5395] OBJ_id_GostR3410_94 */
-0x2A,0x85,0x03,0x02,0x02,0x15,               /* [5401] OBJ_id_Gost28147_89 */
-0x2A,0x85,0x03,0x02,0x02,0x16,               /* [5407] OBJ_id_Gost28147_89_MAC */
-0x2A,0x85,0x03,0x02,0x02,0x17,               /* [5413] OBJ_id_GostR3411_94_prf */
-0x2A,0x85,0x03,0x02,0x02,0x62,               /* [5419] OBJ_id_GostR3410_2001DH */
-0x2A,0x85,0x03,0x02,0x02,0x63,               /* [5425] OBJ_id_GostR3410_94DH */
-0x2A,0x85,0x03,0x02,0x02,0x0E,0x01,          /* [5431] OBJ_id_Gost28147_89_CryptoPro_KeyMeshing */
-0x2A,0x85,0x03,0x02,0x02,0x0E,0x00,          /* [5438] OBJ_id_Gost28147_89_None_KeyMeshing */
-0x2A,0x85,0x03,0x02,0x02,0x1E,0x00,          /* [5445] OBJ_id_GostR3411_94_TestParamSet */
-0x2A,0x85,0x03,0x02,0x02,0x1E,0x01,          /* [5452] OBJ_id_GostR3411_94_CryptoProParamSet */
-0x2A,0x85,0x03,0x02,0x02,0x1F,0x00,          /* [5459] OBJ_id_Gost28147_89_TestParamSet */
-0x2A,0x85,0x03,0x02,0x02,0x1F,0x01,          /* [5466] OBJ_id_Gost28147_89_CryptoPro_A_ParamSet */
-0x2A,0x85,0x03,0x02,0x02,0x1F,0x02,          /* [5473] OBJ_id_Gost28147_89_CryptoPro_B_ParamSet */
-0x2A,0x85,0x03,0x02,0x02,0x1F,0x03,          /* [5480] OBJ_id_Gost28147_89_CryptoPro_C_ParamSet */
-0x2A,0x85,0x03,0x02,0x02,0x1F,0x04,          /* [5487] OBJ_id_Gost28147_89_CryptoPro_D_ParamSet */
-0x2A,0x85,0x03,0x02,0x02,0x1F,0x05,          /* [5494] OBJ_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet */
-0x2A,0x85,0x03,0x02,0x02,0x1F,0x06,          /* [5501] OBJ_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet */
-0x2A,0x85,0x03,0x02,0x02,0x1F,0x07,          /* [5508] OBJ_id_Gost28147_89_CryptoPro_RIC_1_ParamSet */
-0x2A,0x85,0x03,0x02,0x02,0x20,0x00,          /* [5515] OBJ_id_GostR3410_94_TestParamSet */
-0x2A,0x85,0x03,0x02,0x02,0x20,0x02,          /* [5522] OBJ_id_GostR3410_94_CryptoPro_A_ParamSet */
-0x2A,0x85,0x03,0x02,0x02,0x20,0x03,          /* [5529] OBJ_id_GostR3410_94_CryptoPro_B_ParamSet */
-0x2A,0x85,0x03,0x02,0x02,0x20,0x04,          /* [5536] OBJ_id_GostR3410_94_CryptoPro_C_ParamSet */
-0x2A,0x85,0x03,0x02,0x02,0x20,0x05,          /* [5543] OBJ_id_GostR3410_94_CryptoPro_D_ParamSet */
-0x2A,0x85,0x03,0x02,0x02,0x21,0x01,          /* [5550] OBJ_id_GostR3410_94_CryptoPro_XchA_ParamSet */
-0x2A,0x85,0x03,0x02,0x02,0x21,0x02,          /* [5557] OBJ_id_GostR3410_94_CryptoPro_XchB_ParamSet */
-0x2A,0x85,0x03,0x02,0x02,0x21,0x03,          /* [5564] OBJ_id_GostR3410_94_CryptoPro_XchC_ParamSet */
-0x2A,0x85,0x03,0x02,0x02,0x23,0x00,          /* [5571] OBJ_id_GostR3410_2001_TestParamSet */
-0x2A,0x85,0x03,0x02,0x02,0x23,0x01,          /* [5578] OBJ_id_GostR3410_2001_CryptoPro_A_ParamSet */
-0x2A,0x85,0x03,0x02,0x02,0x23,0x02,          /* [5585] OBJ_id_GostR3410_2001_CryptoPro_B_ParamSet */
-0x2A,0x85,0x03,0x02,0x02,0x23,0x03,          /* [5592] OBJ_id_GostR3410_2001_CryptoPro_C_ParamSet */
-0x2A,0x85,0x03,0x02,0x02,0x24,0x00,          /* [5599] OBJ_id_GostR3410_2001_CryptoPro_XchA_ParamSet */
-0x2A,0x85,0x03,0x02,0x02,0x24,0x01,          /* [5606] OBJ_id_GostR3410_2001_CryptoPro_XchB_ParamSet */
-0x2A,0x85,0x03,0x02,0x02,0x14,0x01,          /* [5613] OBJ_id_GostR3410_94_a */
-0x2A,0x85,0x03,0x02,0x02,0x14,0x02,          /* [5620] OBJ_id_GostR3410_94_aBis */
-0x2A,0x85,0x03,0x02,0x02,0x14,0x03,          /* [5627] OBJ_id_GostR3410_94_b */
-0x2A,0x85,0x03,0x02,0x02,0x14,0x04,          /* [5634] OBJ_id_GostR3410_94_bBis */
-0x2A,0x85,0x03,0x02,0x09,0x01,0x06,0x01,     /* [5641] OBJ_id_Gost28147_89_cc */
-0x2A,0x85,0x03,0x02,0x09,0x01,0x05,0x03,     /* [5649] OBJ_id_GostR3410_94_cc */
-0x2A,0x85,0x03,0x02,0x09,0x01,0x05,0x04,     /* [5657] OBJ_id_GostR3410_2001_cc */
-0x2A,0x85,0x03,0x02,0x09,0x01,0x03,0x03,     /* [5665] OBJ_id_GostR3411_94_with_GostR3410_94_cc */
-0x2A,0x85,0x03,0x02,0x09,0x01,0x03,0x04,     /* [5673] OBJ_id_GostR3411_94_with_GostR3410_2001_cc */
-0x2A,0x85,0x03,0x02,0x09,0x01,0x08,0x01,     /* [5681] OBJ_id_GostR3410_2001_ParamSet_cc */
-0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x11,0x02,/* [5689] OBJ_LocalKeySet */
-0x55,0x1D,0x2E,                              /* [5698] OBJ_freshest_crl */
-0x2B,0x06,0x01,0x05,0x05,0x07,0x08,0x03,     /* [5701] OBJ_id_on_permanentIdentifier */
-0x55,0x04,0x0E,                              /* [5709] OBJ_searchGuide */
-0x55,0x04,0x0F,                              /* [5712] OBJ_businessCategory */
-0x55,0x04,0x10,                              /* [5715] OBJ_postalAddress */
-0x55,0x04,0x12,                              /* [5718] OBJ_postOfficeBox */
-0x55,0x04,0x13,                              /* [5721] OBJ_physicalDeliveryOfficeName */
-0x55,0x04,0x14,                              /* [5724] OBJ_telephoneNumber */
-0x55,0x04,0x15,                              /* [5727] OBJ_telexNumber */
-0x55,0x04,0x16,                              /* [5730] OBJ_teletexTerminalIdentifier */
-0x55,0x04,0x17,                              /* [5733] OBJ_facsimileTelephoneNumber */
-0x55,0x04,0x18,                              /* [5736] OBJ_x121Address */
-0x55,0x04,0x19,                              /* [5739] OBJ_internationaliSDNNumber */
-0x55,0x04,0x1A,                              /* [5742] OBJ_registeredAddress */
-0x55,0x04,0x1B,                              /* [5745] OBJ_destinationIndicator */
-0x55,0x04,0x1C,                              /* [5748] OBJ_preferredDeliveryMethod */
-0x55,0x04,0x1D,                              /* [5751] OBJ_presentationAddress */
-0x55,0x04,0x1E,                              /* [5754] OBJ_supportedApplicationContext */
-0x55,0x04,0x1F,                              /* [5757] OBJ_member */
-0x55,0x04,0x20,                              /* [5760] OBJ_owner */
-0x55,0x04,0x21,                              /* [5763] OBJ_roleOccupant */
-0x55,0x04,0x22,                              /* [5766] OBJ_seeAlso */
-0x55,0x04,0x23,                              /* [5769] OBJ_userPassword */
-0x55,0x04,0x24,                              /* [5772] OBJ_userCertificate */
-0x55,0x04,0x25,                              /* [5775] OBJ_cACertificate */
-0x55,0x04,0x26,                              /* [5778] OBJ_authorityRevocationList */
-0x55,0x04,0x27,                              /* [5781] OBJ_certificateRevocationList */
-0x55,0x04,0x28,                              /* [5784] OBJ_crossCertificatePair */
-0x55,0x04,0x2F,                              /* [5787] OBJ_enhancedSearchGuide */
-0x55,0x04,0x30,                              /* [5790] OBJ_protocolInformation */
-0x55,0x04,0x31,                              /* [5793] OBJ_distinguishedName */
-0x55,0x04,0x32,                              /* [5796] OBJ_uniqueMember */
-0x55,0x04,0x33,                              /* [5799] OBJ_houseIdentifier */
-0x55,0x04,0x34,                              /* [5802] OBJ_supportedAlgorithms */
-0x55,0x04,0x35,                              /* [5805] OBJ_deltaRevocationList */
-0x55,0x04,0x36,                              /* [5808] OBJ_dmdName */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x09,/* [5811] OBJ_id_alg_PWRI_KEK */
-0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x06,/* [5822] OBJ_aes_128_gcm */
-0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x07,/* [5831] OBJ_aes_128_ccm */
-0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x08,/* [5840] OBJ_id_aes128_wrap_pad */
-0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x1A,/* [5849] OBJ_aes_192_gcm */
-0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x1B,/* [5858] OBJ_aes_192_ccm */
-0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x1C,/* [5867] OBJ_id_aes192_wrap_pad */
-0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x2E,/* [5876] OBJ_aes_256_gcm */
-0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x2F,/* [5885] OBJ_aes_256_ccm */
-0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x30,/* [5894] OBJ_id_aes256_wrap_pad */
-0x2A,0x83,0x08,0x8C,0x9A,0x4B,0x3D,0x01,0x01,0x03,0x02,/* [5903] OBJ_id_camellia128_wrap */
-0x2A,0x83,0x08,0x8C,0x9A,0x4B,0x3D,0x01,0x01,0x03,0x03,/* [5914] OBJ_id_camellia192_wrap */
-0x2A,0x83,0x08,0x8C,0x9A,0x4B,0x3D,0x01,0x01,0x03,0x04,/* [5925] OBJ_id_camellia256_wrap */
-0x55,0x1D,0x25,0x00,                         /* [5936] OBJ_anyExtendedKeyUsage */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x08,/* [5940] OBJ_mgf1 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0A,/* [5949] OBJ_rsassaPss */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x07,/* [5958] OBJ_rsaesOaep */
-0x2A,0x86,0x48,0xCE,0x3E,0x02,0x01,          /* [5967] OBJ_dhpublicnumber */
-0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x01,/* [5974] OBJ_brainpoolP160r1 */
-0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x02,/* [5983] OBJ_brainpoolP160t1 */
-0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x03,/* [5992] OBJ_brainpoolP192r1 */
-0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x04,/* [6001] OBJ_brainpoolP192t1 */
-0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x05,/* [6010] OBJ_brainpoolP224r1 */
-0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x06,/* [6019] OBJ_brainpoolP224t1 */
-0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x07,/* [6028] OBJ_brainpoolP256r1 */
-0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x08,/* [6037] OBJ_brainpoolP256t1 */
-0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x09,/* [6046] OBJ_brainpoolP320r1 */
-0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0A,/* [6055] OBJ_brainpoolP320t1 */
-0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0B,/* [6064] OBJ_brainpoolP384r1 */
-0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0C,/* [6073] OBJ_brainpoolP384t1 */
-0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0D,/* [6082] OBJ_brainpoolP512r1 */
-0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0E,/* [6091] OBJ_brainpoolP512t1 */
-0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x09,/* [6100] OBJ_pSpecified */
-0x2B,0x81,0x05,0x10,0x86,0x48,0x3F,0x00,0x02,/* [6109] OBJ_dhSinglePass_stdDH_sha1kdf_scheme */
-0x2B,0x81,0x04,0x01,0x0B,0x00,               /* [6118] OBJ_dhSinglePass_stdDH_sha224kdf_scheme */
-0x2B,0x81,0x04,0x01,0x0B,0x01,               /* [6124] OBJ_dhSinglePass_stdDH_sha256kdf_scheme */
-0x2B,0x81,0x04,0x01,0x0B,0x02,               /* [6130] OBJ_dhSinglePass_stdDH_sha384kdf_scheme */
-0x2B,0x81,0x04,0x01,0x0B,0x03,               /* [6136] OBJ_dhSinglePass_stdDH_sha512kdf_scheme */
-0x2B,0x81,0x05,0x10,0x86,0x48,0x3F,0x00,0x03,/* [6142] OBJ_dhSinglePass_cofactorDH_sha1kdf_scheme */
-0x2B,0x81,0x04,0x01,0x0E,0x00,               /* [6151] OBJ_dhSinglePass_cofactorDH_sha224kdf_scheme */
-0x2B,0x81,0x04,0x01,0x0E,0x01,               /* [6157] OBJ_dhSinglePass_cofactorDH_sha256kdf_scheme */
-0x2B,0x81,0x04,0x01,0x0E,0x02,               /* [6163] OBJ_dhSinglePass_cofactorDH_sha384kdf_scheme */
-0x2B,0x81,0x04,0x01,0x0E,0x03,               /* [6169] OBJ_dhSinglePass_cofactorDH_sha512kdf_scheme */
+static const uint8_t kObjectData[] = {
+    /* NID_rsadsi */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+    /* NID_pkcs */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
+    /* NID_md2 */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x02,
+    /* NID_md5 */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05,
+    /* NID_rc4 */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x04,
+    /* NID_rsaEncryption */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
+    /* NID_md2WithRSAEncryption */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02,
+    /* NID_md5WithRSAEncryption */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x04,
+    /* NID_pbeWithMD2AndDES_CBC */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x01,
+    /* NID_pbeWithMD5AndDES_CBC */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x03,
+    /* NID_X500 */
+    0x55,
+    /* NID_X509 */
+    0x55, 0x04,
+    /* NID_commonName */
+    0x55, 0x04, 0x03,
+    /* NID_countryName */
+    0x55, 0x04, 0x06,
+    /* NID_localityName */
+    0x55, 0x04, 0x07,
+    /* NID_stateOrProvinceName */
+    0x55, 0x04, 0x08,
+    /* NID_organizationName */
+    0x55, 0x04, 0x0a,
+    /* NID_organizationalUnitName */
+    0x55, 0x04, 0x0b,
+    /* NID_rsa */
+    0x55, 0x08, 0x01, 0x01,
+    /* NID_pkcs7 */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07,
+    /* NID_pkcs7_data */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01,
+    /* NID_pkcs7_signed */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02,
+    /* NID_pkcs7_enveloped */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x03,
+    /* NID_pkcs7_signedAndEnveloped */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x04,
+    /* NID_pkcs7_digest */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x05,
+    /* NID_pkcs7_encrypted */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x06,
+    /* NID_pkcs3 */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x03,
+    /* NID_dhKeyAgreement */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x03, 0x01,
+    /* NID_des_ecb */
+    0x2b, 0x0e, 0x03, 0x02, 0x06,
+    /* NID_des_cfb64 */
+    0x2b, 0x0e, 0x03, 0x02, 0x09,
+    /* NID_des_cbc */
+    0x2b, 0x0e, 0x03, 0x02, 0x07,
+    /* NID_des_ede_ecb */
+    0x2b, 0x0e, 0x03, 0x02, 0x11,
+    /* NID_idea_cbc */
+    0x2b, 0x06, 0x01, 0x04, 0x01, 0x81, 0x3c, 0x07, 0x01, 0x01, 0x02,
+    /* NID_rc2_cbc */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x02,
+    /* NID_sha */
+    0x2b, 0x0e, 0x03, 0x02, 0x12,
+    /* NID_shaWithRSAEncryption */
+    0x2b, 0x0e, 0x03, 0x02, 0x0f,
+    /* NID_des_ede3_cbc */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x07,
+    /* NID_des_ofb64 */
+    0x2b, 0x0e, 0x03, 0x02, 0x08,
+    /* NID_pkcs9 */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09,
+    /* NID_pkcs9_emailAddress */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01,
+    /* NID_pkcs9_unstructuredName */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x02,
+    /* NID_pkcs9_contentType */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x03,
+    /* NID_pkcs9_messageDigest */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x04,
+    /* NID_pkcs9_signingTime */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x05,
+    /* NID_pkcs9_countersignature */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x06,
+    /* NID_pkcs9_challengePassword */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x07,
+    /* NID_pkcs9_unstructuredAddress */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x08,
+    /* NID_pkcs9_extCertAttributes */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x09,
+    /* NID_netscape */
+    0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42,
+    /* NID_netscape_cert_extension */
+    0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01,
+    /* NID_netscape_data_type */
+    0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x02,
+    /* NID_sha1 */
+    0x2b, 0x0e, 0x03, 0x02, 0x1a,
+    /* NID_sha1WithRSAEncryption */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
+    /* NID_dsaWithSHA */
+    0x2b, 0x0e, 0x03, 0x02, 0x0d,
+    /* NID_dsa_2 */
+    0x2b, 0x0e, 0x03, 0x02, 0x0c,
+    /* NID_pbeWithSHA1AndRC2_CBC */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0b,
+    /* NID_id_pbkdf2 */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0c,
+    /* NID_dsaWithSHA1_2 */
+    0x2b, 0x0e, 0x03, 0x02, 0x1b,
+    /* NID_netscape_cert_type */
+    0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x01,
+    /* NID_netscape_base_url */
+    0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x02,
+    /* NID_netscape_revocation_url */
+    0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x03,
+    /* NID_netscape_ca_revocation_url */
+    0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x04,
+    /* NID_netscape_renewal_url */
+    0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x07,
+    /* NID_netscape_ca_policy_url */
+    0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x08,
+    /* NID_netscape_ssl_server_name */
+    0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x0c,
+    /* NID_netscape_comment */
+    0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x0d,
+    /* NID_netscape_cert_sequence */
+    0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x02, 0x05,
+    /* NID_id_ce */
+    0x55, 0x1d,
+    /* NID_subject_key_identifier */
+    0x55, 0x1d, 0x0e,
+    /* NID_key_usage */
+    0x55, 0x1d, 0x0f,
+    /* NID_private_key_usage_period */
+    0x55, 0x1d, 0x10,
+    /* NID_subject_alt_name */
+    0x55, 0x1d, 0x11,
+    /* NID_issuer_alt_name */
+    0x55, 0x1d, 0x12,
+    /* NID_basic_constraints */
+    0x55, 0x1d, 0x13,
+    /* NID_crl_number */
+    0x55, 0x1d, 0x14,
+    /* NID_certificate_policies */
+    0x55, 0x1d, 0x20,
+    /* NID_authority_key_identifier */
+    0x55, 0x1d, 0x23,
+    /* NID_bf_cbc */
+    0x2b, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x02,
+    /* NID_mdc2 */
+    0x55, 0x08, 0x03, 0x65,
+    /* NID_mdc2WithRSA */
+    0x55, 0x08, 0x03, 0x64,
+    /* NID_givenName */
+    0x55, 0x04, 0x2a,
+    /* NID_surname */
+    0x55, 0x04, 0x04,
+    /* NID_initials */
+    0x55, 0x04, 0x2b,
+    /* NID_crl_distribution_points */
+    0x55, 0x1d, 0x1f,
+    /* NID_md5WithRSA */
+    0x2b, 0x0e, 0x03, 0x02, 0x03,
+    /* NID_serialNumber */
+    0x55, 0x04, 0x05,
+    /* NID_title */
+    0x55, 0x04, 0x0c,
+    /* NID_description */
+    0x55, 0x04, 0x0d,
+    /* NID_cast5_cbc */
+    0x2a, 0x86, 0x48, 0x86, 0xf6, 0x7d, 0x07, 0x42, 0x0a,
+    /* NID_pbeWithMD5AndCast5_CBC */
+    0x2a, 0x86, 0x48, 0x86, 0xf6, 0x7d, 0x07, 0x42, 0x0c,
+    /* NID_dsaWithSHA1 */
+    0x2a, 0x86, 0x48, 0xce, 0x38, 0x04, 0x03,
+    /* NID_sha1WithRSA */
+    0x2b, 0x0e, 0x03, 0x02, 0x1d,
+    /* NID_dsa */
+    0x2a, 0x86, 0x48, 0xce, 0x38, 0x04, 0x01,
+    /* NID_ripemd160 */
+    0x2b, 0x24, 0x03, 0x02, 0x01,
+    /* NID_ripemd160WithRSA */
+    0x2b, 0x24, 0x03, 0x03, 0x01, 0x02,
+    /* NID_rc5_cbc */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x08,
+    /* NID_zlib_compression */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x03, 0x08,
+    /* NID_ext_key_usage */
+    0x55, 0x1d, 0x25,
+    /* NID_id_pkix */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
+    /* NID_id_kp */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03,
+    /* NID_server_auth */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01,
+    /* NID_client_auth */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02,
+    /* NID_code_sign */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
+    /* NID_email_protect */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x04,
+    /* NID_time_stamp */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x08,
+    /* NID_ms_code_ind */
+    0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x15,
+    /* NID_ms_code_com */
+    0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x16,
+    /* NID_ms_ctl_sign */
+    0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x0a, 0x03, 0x01,
+    /* NID_ms_sgc */
+    0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x0a, 0x03, 0x03,
+    /* NID_ms_efs */
+    0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x0a, 0x03, 0x04,
+    /* NID_ns_sgc */
+    0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x04, 0x01,
+    /* NID_delta_crl */
+    0x55, 0x1d, 0x1b,
+    /* NID_crl_reason */
+    0x55, 0x1d, 0x15,
+    /* NID_invalidity_date */
+    0x55, 0x1d, 0x18,
+    /* NID_sxnet */
+    0x2b, 0x65, 0x01, 0x04, 0x01,
+    /* NID_pbe_WithSHA1And128BitRC4 */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x01,
+    /* NID_pbe_WithSHA1And40BitRC4 */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x02,
+    /* NID_pbe_WithSHA1And3_Key_TripleDES_CBC */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x03,
+    /* NID_pbe_WithSHA1And2_Key_TripleDES_CBC */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x04,
+    /* NID_pbe_WithSHA1And128BitRC2_CBC */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x05,
+    /* NID_pbe_WithSHA1And40BitRC2_CBC */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x06,
+    /* NID_keyBag */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x01,
+    /* NID_pkcs8ShroudedKeyBag */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x02,
+    /* NID_certBag */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x03,
+    /* NID_crlBag */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x04,
+    /* NID_secretBag */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x05,
+    /* NID_safeContentsBag */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x06,
+    /* NID_friendlyName */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x14,
+    /* NID_localKeyID */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x15,
+    /* NID_x509Certificate */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x16, 0x01,
+    /* NID_sdsiCertificate */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x16, 0x02,
+    /* NID_x509Crl */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x17, 0x01,
+    /* NID_pbes2 */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0d,
+    /* NID_pbmac1 */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0e,
+    /* NID_hmacWithSHA1 */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x07,
+    /* NID_id_qt_cps */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01,
+    /* NID_id_qt_unotice */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x02,
+    /* NID_SMIMECapabilities */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x0f,
+    /* NID_pbeWithMD2AndRC2_CBC */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x04,
+    /* NID_pbeWithMD5AndRC2_CBC */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x06,
+    /* NID_pbeWithSHA1AndDES_CBC */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0a,
+    /* NID_ms_ext_req */
+    0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x0e,
+    /* NID_ext_req */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x0e,
+    /* NID_name */
+    0x55, 0x04, 0x29,
+    /* NID_dnQualifier */
+    0x55, 0x04, 0x2e,
+    /* NID_id_pe */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01,
+    /* NID_id_ad */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30,
+    /* NID_info_access */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01,
+    /* NID_ad_OCSP */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01,
+    /* NID_ad_ca_issuers */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02,
+    /* NID_OCSP_sign */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x09,
+    /* NID_member_body */
+    0x2a,
+    /* NID_ISO_US */
+    0x2a, 0x86, 0x48,
+    /* NID_X9_57 */
+    0x2a, 0x86, 0x48, 0xce, 0x38,
+    /* NID_X9cm */
+    0x2a, 0x86, 0x48, 0xce, 0x38, 0x04,
+    /* NID_pkcs1 */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
+    /* NID_pkcs5 */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05,
+    /* NID_SMIME */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10,
+    /* NID_id_smime_mod */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x00,
+    /* NID_id_smime_ct */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x01,
+    /* NID_id_smime_aa */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02,
+    /* NID_id_smime_alg */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x03,
+    /* NID_id_smime_cd */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x04,
+    /* NID_id_smime_spq */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x05,
+    /* NID_id_smime_cti */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x06,
+    /* NID_id_smime_mod_cms */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x00, 0x01,
+    /* NID_id_smime_mod_ess */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x00, 0x02,
+    /* NID_id_smime_mod_oid */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x00, 0x03,
+    /* NID_id_smime_mod_msg_v3 */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x00, 0x04,
+    /* NID_id_smime_mod_ets_eSignature_88 */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x00, 0x05,
+    /* NID_id_smime_mod_ets_eSignature_97 */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x00, 0x06,
+    /* NID_id_smime_mod_ets_eSigPolicy_88 */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x00, 0x07,
+    /* NID_id_smime_mod_ets_eSigPolicy_97 */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x00, 0x08,
+    /* NID_id_smime_ct_receipt */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x01, 0x01,
+    /* NID_id_smime_ct_authData */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x01, 0x02,
+    /* NID_id_smime_ct_publishCert */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x01, 0x03,
+    /* NID_id_smime_ct_TSTInfo */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x01, 0x04,
+    /* NID_id_smime_ct_TDTInfo */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x01, 0x05,
+    /* NID_id_smime_ct_contentInfo */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x01, 0x06,
+    /* NID_id_smime_ct_DVCSRequestData */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x01, 0x07,
+    /* NID_id_smime_ct_DVCSResponseData */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x01, 0x08,
+    /* NID_id_smime_aa_receiptRequest */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02, 0x01,
+    /* NID_id_smime_aa_securityLabel */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02, 0x02,
+    /* NID_id_smime_aa_mlExpandHistory */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02, 0x03,
+    /* NID_id_smime_aa_contentHint */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02, 0x04,
+    /* NID_id_smime_aa_msgSigDigest */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02, 0x05,
+    /* NID_id_smime_aa_encapContentType */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02, 0x06,
+    /* NID_id_smime_aa_contentIdentifier */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02, 0x07,
+    /* NID_id_smime_aa_macValue */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02, 0x08,
+    /* NID_id_smime_aa_equivalentLabels */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02, 0x09,
+    /* NID_id_smime_aa_contentReference */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02, 0x0a,
+    /* NID_id_smime_aa_encrypKeyPref */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02, 0x0b,
+    /* NID_id_smime_aa_signingCertificate */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02, 0x0c,
+    /* NID_id_smime_aa_smimeEncryptCerts */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02, 0x0d,
+    /* NID_id_smime_aa_timeStampToken */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02, 0x0e,
+    /* NID_id_smime_aa_ets_sigPolicyId */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02, 0x0f,
+    /* NID_id_smime_aa_ets_commitmentType */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02, 0x10,
+    /* NID_id_smime_aa_ets_signerLocation */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02, 0x11,
+    /* NID_id_smime_aa_ets_signerAttr */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02, 0x12,
+    /* NID_id_smime_aa_ets_otherSigCert */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02, 0x13,
+    /* NID_id_smime_aa_ets_contentTimestamp */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02, 0x14,
+    /* NID_id_smime_aa_ets_CertificateRefs */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02, 0x15,
+    /* NID_id_smime_aa_ets_RevocationRefs */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02, 0x16,
+    /* NID_id_smime_aa_ets_certValues */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02, 0x17,
+    /* NID_id_smime_aa_ets_revocationValues */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02, 0x18,
+    /* NID_id_smime_aa_ets_escTimeStamp */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02, 0x19,
+    /* NID_id_smime_aa_ets_certCRLTimestamp */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02, 0x1a,
+    /* NID_id_smime_aa_ets_archiveTimeStamp */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02, 0x1b,
+    /* NID_id_smime_aa_signatureType */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02, 0x1c,
+    /* NID_id_smime_aa_dvcs_dvc */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x02, 0x1d,
+    /* NID_id_smime_alg_ESDHwith3DES */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x03, 0x01,
+    /* NID_id_smime_alg_ESDHwithRC2 */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x03, 0x02,
+    /* NID_id_smime_alg_3DESwrap */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x03, 0x03,
+    /* NID_id_smime_alg_RC2wrap */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x03, 0x04,
+    /* NID_id_smime_alg_ESDH */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x03, 0x05,
+    /* NID_id_smime_alg_CMS3DESwrap */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x03, 0x06,
+    /* NID_id_smime_alg_CMSRC2wrap */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x03, 0x07,
+    /* NID_id_smime_cd_ldap */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x04, 0x01,
+    /* NID_id_smime_spq_ets_sqt_uri */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x05, 0x01,
+    /* NID_id_smime_spq_ets_sqt_unotice */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x05, 0x02,
+    /* NID_id_smime_cti_ets_proofOfOrigin */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x06, 0x01,
+    /* NID_id_smime_cti_ets_proofOfReceipt */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x06, 0x02,
+    /* NID_id_smime_cti_ets_proofOfDelivery */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x06, 0x03,
+    /* NID_id_smime_cti_ets_proofOfSender */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x06, 0x04,
+    /* NID_id_smime_cti_ets_proofOfApproval */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x06, 0x05,
+    /* NID_id_smime_cti_ets_proofOfCreation */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x06, 0x06,
+    /* NID_md4 */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x04,
+    /* NID_id_pkix_mod */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x00,
+    /* NID_id_qt */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02,
+    /* NID_id_it */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x04,
+    /* NID_id_pkip */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x05,
+    /* NID_id_alg */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x06,
+    /* NID_id_cmc */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x07,
+    /* NID_id_on */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x08,
+    /* NID_id_pda */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x09,
+    /* NID_id_aca */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x0a,
+    /* NID_id_qcs */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x0b,
+    /* NID_id_cct */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x0c,
+    /* NID_id_pkix1_explicit_88 */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x00, 0x01,
+    /* NID_id_pkix1_implicit_88 */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x00, 0x02,
+    /* NID_id_pkix1_explicit_93 */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x00, 0x03,
+    /* NID_id_pkix1_implicit_93 */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x00, 0x04,
+    /* NID_id_mod_crmf */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x00, 0x05,
+    /* NID_id_mod_cmc */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x00, 0x06,
+    /* NID_id_mod_kea_profile_88 */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x00, 0x07,
+    /* NID_id_mod_kea_profile_93 */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x00, 0x08,
+    /* NID_id_mod_cmp */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x00, 0x09,
+    /* NID_id_mod_qualified_cert_88 */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x00, 0x0a,
+    /* NID_id_mod_qualified_cert_93 */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x00, 0x0b,
+    /* NID_id_mod_attribute_cert */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x00, 0x0c,
+    /* NID_id_mod_timestamp_protocol */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x00, 0x0d,
+    /* NID_id_mod_ocsp */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x00, 0x0e,
+    /* NID_id_mod_dvcs */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x00, 0x0f,
+    /* NID_id_mod_cmp2000 */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x00, 0x10,
+    /* NID_biometricInfo */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x02,
+    /* NID_qcStatements */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x03,
+    /* NID_ac_auditEntity */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x04,
+    /* NID_ac_targeting */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x05,
+    /* NID_aaControls */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x06,
+    /* NID_sbgp_ipAddrBlock */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x07,
+    /* NID_sbgp_autonomousSysNum */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x08,
+    /* NID_sbgp_routerIdentifier */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x09,
+    /* NID_textNotice */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x03,
+    /* NID_ipsecEndSystem */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x05,
+    /* NID_ipsecTunnel */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x06,
+    /* NID_ipsecUser */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x07,
+    /* NID_dvcs */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x0a,
+    /* NID_id_it_caProtEncCert */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x04, 0x01,
+    /* NID_id_it_signKeyPairTypes */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x04, 0x02,
+    /* NID_id_it_encKeyPairTypes */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x04, 0x03,
+    /* NID_id_it_preferredSymmAlg */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x04, 0x04,
+    /* NID_id_it_caKeyUpdateInfo */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x04, 0x05,
+    /* NID_id_it_currentCRL */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x04, 0x06,
+    /* NID_id_it_unsupportedOIDs */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x04, 0x07,
+    /* NID_id_it_subscriptionRequest */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x04, 0x08,
+    /* NID_id_it_subscriptionResponse */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x04, 0x09,
+    /* NID_id_it_keyPairParamReq */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x04, 0x0a,
+    /* NID_id_it_keyPairParamRep */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x04, 0x0b,
+    /* NID_id_it_revPassphrase */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x04, 0x0c,
+    /* NID_id_it_implicitConfirm */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x04, 0x0d,
+    /* NID_id_it_confirmWaitTime */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x04, 0x0e,
+    /* NID_id_it_origPKIMessage */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x04, 0x0f,
+    /* NID_id_regCtrl */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x05, 0x01,
+    /* NID_id_regInfo */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x05, 0x02,
+    /* NID_id_regCtrl_regToken */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x05, 0x01, 0x01,
+    /* NID_id_regCtrl_authenticator */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x05, 0x01, 0x02,
+    /* NID_id_regCtrl_pkiPublicationInfo */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x05, 0x01, 0x03,
+    /* NID_id_regCtrl_pkiArchiveOptions */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x05, 0x01, 0x04,
+    /* NID_id_regCtrl_oldCertID */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x05, 0x01, 0x05,
+    /* NID_id_regCtrl_protocolEncrKey */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x05, 0x01, 0x06,
+    /* NID_id_regInfo_utf8Pairs */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x05, 0x02, 0x01,
+    /* NID_id_regInfo_certReq */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x05, 0x02, 0x02,
+    /* NID_id_alg_des40 */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x06, 0x01,
+    /* NID_id_alg_noSignature */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x06, 0x02,
+    /* NID_id_alg_dh_sig_hmac_sha1 */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x06, 0x03,
+    /* NID_id_alg_dh_pop */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x06, 0x04,
+    /* NID_id_cmc_statusInfo */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x07, 0x01,
+    /* NID_id_cmc_identification */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x07, 0x02,
+    /* NID_id_cmc_identityProof */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x07, 0x03,
+    /* NID_id_cmc_dataReturn */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x07, 0x04,
+    /* NID_id_cmc_transactionId */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x07, 0x05,
+    /* NID_id_cmc_senderNonce */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x07, 0x06,
+    /* NID_id_cmc_recipientNonce */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x07, 0x07,
+    /* NID_id_cmc_addExtensions */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x07, 0x08,
+    /* NID_id_cmc_encryptedPOP */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x07, 0x09,
+    /* NID_id_cmc_decryptedPOP */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x07, 0x0a,
+    /* NID_id_cmc_lraPOPWitness */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x07, 0x0b,
+    /* NID_id_cmc_getCert */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x07, 0x0f,
+    /* NID_id_cmc_getCRL */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x07, 0x10,
+    /* NID_id_cmc_revokeRequest */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x07, 0x11,
+    /* NID_id_cmc_regInfo */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x07, 0x12,
+    /* NID_id_cmc_responseInfo */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x07, 0x13,
+    /* NID_id_cmc_queryPending */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x07, 0x15,
+    /* NID_id_cmc_popLinkRandom */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x07, 0x16,
+    /* NID_id_cmc_popLinkWitness */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x07, 0x17,
+    /* NID_id_cmc_confirmCertAcceptance */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x07, 0x18,
+    /* NID_id_on_personalData */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x08, 0x01,
+    /* NID_id_pda_dateOfBirth */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x09, 0x01,
+    /* NID_id_pda_placeOfBirth */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x09, 0x02,
+    /* NID_id_pda_gender */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x09, 0x03,
+    /* NID_id_pda_countryOfCitizenship */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x09, 0x04,
+    /* NID_id_pda_countryOfResidence */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x09, 0x05,
+    /* NID_id_aca_authenticationInfo */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x0a, 0x01,
+    /* NID_id_aca_accessIdentity */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x0a, 0x02,
+    /* NID_id_aca_chargingIdentity */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x0a, 0x03,
+    /* NID_id_aca_group */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x0a, 0x04,
+    /* NID_id_aca_role */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x0a, 0x05,
+    /* NID_id_qcs_pkixQCSyntax_v1 */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x0b, 0x01,
+    /* NID_id_cct_crs */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x0c, 0x01,
+    /* NID_id_cct_PKIData */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x0c, 0x02,
+    /* NID_id_cct_PKIResponse */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x0c, 0x03,
+    /* NID_ad_timeStamping */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x03,
+    /* NID_ad_dvcs */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x04,
+    /* NID_id_pkix_OCSP_basic */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01,
+    /* NID_id_pkix_OCSP_Nonce */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x02,
+    /* NID_id_pkix_OCSP_CrlID */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x03,
+    /* NID_id_pkix_OCSP_acceptableResponses */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x04,
+    /* NID_id_pkix_OCSP_noCheck */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x05,
+    /* NID_id_pkix_OCSP_archiveCutoff */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x06,
+    /* NID_id_pkix_OCSP_serviceLocator */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x07,
+    /* NID_id_pkix_OCSP_extendedStatus */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x08,
+    /* NID_id_pkix_OCSP_valid */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x09,
+    /* NID_id_pkix_OCSP_path */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x0a,
+    /* NID_id_pkix_OCSP_trustRoot */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x0b,
+    /* NID_algorithm */
+    0x2b, 0x0e, 0x03, 0x02,
+    /* NID_rsaSignature */
+    0x2b, 0x0e, 0x03, 0x02, 0x0b,
+    /* NID_X500algorithms */
+    0x55, 0x08,
+    /* NID_org */
+    0x2b,
+    /* NID_dod */
+    0x2b, 0x06,
+    /* NID_iana */
+    0x2b, 0x06, 0x01,
+    /* NID_Directory */
+    0x2b, 0x06, 0x01, 0x01,
+    /* NID_Management */
+    0x2b, 0x06, 0x01, 0x02,
+    /* NID_Experimental */
+    0x2b, 0x06, 0x01, 0x03,
+    /* NID_Private */
+    0x2b, 0x06, 0x01, 0x04,
+    /* NID_Security */
+    0x2b, 0x06, 0x01, 0x05,
+    /* NID_SNMPv2 */
+    0x2b, 0x06, 0x01, 0x06,
+    /* NID_Mail */
+    0x2b, 0x06, 0x01, 0x07,
+    /* NID_Enterprises */
+    0x2b, 0x06, 0x01, 0x04, 0x01,
+    /* NID_dcObject */
+    0x2b, 0x06, 0x01, 0x04, 0x01, 0x8b, 0x3a, 0x82, 0x58,
+    /* NID_domainComponent */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
+    /* NID_Domain */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x04, 0x0d,
+    /* NID_selected_attribute_types */
+    0x55, 0x01, 0x05,
+    /* NID_clearance */
+    0x55, 0x01, 0x05, 0x37,
+    /* NID_md4WithRSAEncryption */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x03,
+    /* NID_ac_proxying */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x0a,
+    /* NID_sinfo_access */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x0b,
+    /* NID_id_aca_encAttrs */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x0a, 0x06,
+    /* NID_role */
+    0x55, 0x04, 0x48,
+    /* NID_policy_constraints */
+    0x55, 0x1d, 0x24,
+    /* NID_target_information */
+    0x55, 0x1d, 0x37,
+    /* NID_no_rev_avail */
+    0x55, 0x1d, 0x38,
+    /* NID_ansi_X9_62 */
+    0x2a, 0x86, 0x48, 0xce, 0x3d,
+    /* NID_X9_62_prime_field */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, 0x01,
+    /* NID_X9_62_characteristic_two_field */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, 0x02,
+    /* NID_X9_62_id_ecPublicKey */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01,
+    /* NID_X9_62_prime192v1 */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x01,
+    /* NID_X9_62_prime192v2 */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x02,
+    /* NID_X9_62_prime192v3 */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x03,
+    /* NID_X9_62_prime239v1 */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x04,
+    /* NID_X9_62_prime239v2 */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x05,
+    /* NID_X9_62_prime239v3 */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x06,
+    /* NID_X9_62_prime256v1 */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07,
+    /* NID_ecdsa_with_SHA1 */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x01,
+    /* NID_ms_csp_name */
+    0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x11, 0x01,
+    /* NID_aes_128_ecb */
+    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x01,
+    /* NID_aes_128_cbc */
+    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x02,
+    /* NID_aes_128_ofb128 */
+    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x03,
+    /* NID_aes_128_cfb128 */
+    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x04,
+    /* NID_aes_192_ecb */
+    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x15,
+    /* NID_aes_192_cbc */
+    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x16,
+    /* NID_aes_192_ofb128 */
+    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x17,
+    /* NID_aes_192_cfb128 */
+    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x18,
+    /* NID_aes_256_ecb */
+    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x29,
+    /* NID_aes_256_cbc */
+    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2a,
+    /* NID_aes_256_ofb128 */
+    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2b,
+    /* NID_aes_256_cfb128 */
+    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2c,
+    /* NID_hold_instruction_code */
+    0x55, 0x1d, 0x17,
+    /* NID_hold_instruction_none */
+    0x2a, 0x86, 0x48, 0xce, 0x38, 0x02, 0x01,
+    /* NID_hold_instruction_call_issuer */
+    0x2a, 0x86, 0x48, 0xce, 0x38, 0x02, 0x02,
+    /* NID_hold_instruction_reject */
+    0x2a, 0x86, 0x48, 0xce, 0x38, 0x02, 0x03,
+    /* NID_data */
+    0x09,
+    /* NID_pss */
+    0x09, 0x92, 0x26,
+    /* NID_ucl */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c,
+    /* NID_pilot */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64,
+    /* NID_pilotAttributeType */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01,
+    /* NID_pilotAttributeSyntax */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x03,
+    /* NID_pilotObjectClass */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x04,
+    /* NID_pilotGroups */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x0a,
+    /* NID_iA5StringSyntax */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x03, 0x04,
+    /* NID_caseIgnoreIA5StringSyntax */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x03, 0x05,
+    /* NID_pilotObject */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x04, 0x03,
+    /* NID_pilotPerson */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x04, 0x04,
+    /* NID_account */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x04, 0x05,
+    /* NID_document */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x04, 0x06,
+    /* NID_room */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x04, 0x07,
+    /* NID_documentSeries */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x04, 0x09,
+    /* NID_rFC822localPart */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x04, 0x0e,
+    /* NID_dNSDomain */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x04, 0x0f,
+    /* NID_domainRelatedObject */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x04, 0x11,
+    /* NID_friendlyCountry */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x04, 0x12,
+    /* NID_simpleSecurityObject */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x04, 0x13,
+    /* NID_pilotOrganization */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x04, 0x14,
+    /* NID_pilotDSA */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x04, 0x15,
+    /* NID_qualityLabelledData */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x04, 0x16,
+    /* NID_userId */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x01,
+    /* NID_textEncodedORAddress */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x02,
+    /* NID_rfc822Mailbox */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x03,
+    /* NID_info */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x04,
+    /* NID_favouriteDrink */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x05,
+    /* NID_roomNumber */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x06,
+    /* NID_photo */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x07,
+    /* NID_userClass */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x08,
+    /* NID_host */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x09,
+    /* NID_manager */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x0a,
+    /* NID_documentIdentifier */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x0b,
+    /* NID_documentTitle */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x0c,
+    /* NID_documentVersion */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x0d,
+    /* NID_documentAuthor */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x0e,
+    /* NID_documentLocation */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x0f,
+    /* NID_homeTelephoneNumber */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x14,
+    /* NID_secretary */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x15,
+    /* NID_otherMailbox */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x16,
+    /* NID_lastModifiedTime */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x17,
+    /* NID_lastModifiedBy */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x18,
+    /* NID_aRecord */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x1a,
+    /* NID_pilotAttributeType27 */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x1b,
+    /* NID_mXRecord */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x1c,
+    /* NID_nSRecord */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x1d,
+    /* NID_sOARecord */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x1e,
+    /* NID_cNAMERecord */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x1f,
+    /* NID_associatedDomain */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x25,
+    /* NID_associatedName */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x26,
+    /* NID_homePostalAddress */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x27,
+    /* NID_personalTitle */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x28,
+    /* NID_mobileTelephoneNumber */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x29,
+    /* NID_pagerTelephoneNumber */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x2a,
+    /* NID_friendlyCountryName */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x2b,
+    /* NID_organizationalStatus */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x2d,
+    /* NID_janetMailbox */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x2e,
+    /* NID_mailPreferenceOption */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x2f,
+    /* NID_buildingName */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x30,
+    /* NID_dSAQuality */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x31,
+    /* NID_singleLevelQuality */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x32,
+    /* NID_subtreeMinimumQuality */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x33,
+    /* NID_subtreeMaximumQuality */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x34,
+    /* NID_personalSignature */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x35,
+    /* NID_dITRedirect */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x36,
+    /* NID_audio */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x37,
+    /* NID_documentPublisher */
+    0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x38,
+    /* NID_x500UniqueIdentifier */
+    0x55, 0x04, 0x2d,
+    /* NID_mime_mhs */
+    0x2b, 0x06, 0x01, 0x07, 0x01,
+    /* NID_mime_mhs_headings */
+    0x2b, 0x06, 0x01, 0x07, 0x01, 0x01,
+    /* NID_mime_mhs_bodies */
+    0x2b, 0x06, 0x01, 0x07, 0x01, 0x02,
+    /* NID_id_hex_partial_message */
+    0x2b, 0x06, 0x01, 0x07, 0x01, 0x01, 0x01,
+    /* NID_id_hex_multipart_message */
+    0x2b, 0x06, 0x01, 0x07, 0x01, 0x01, 0x02,
+    /* NID_generationQualifier */
+    0x55, 0x04, 0x2c,
+    /* NID_pseudonym */
+    0x55, 0x04, 0x41,
+    /* NID_id_set */
+    0x67, 0x2a,
+    /* NID_set_ctype */
+    0x67, 0x2a, 0x00,
+    /* NID_set_msgExt */
+    0x67, 0x2a, 0x01,
+    /* NID_set_attr */
+    0x67, 0x2a, 0x03,
+    /* NID_set_policy */
+    0x67, 0x2a, 0x05,
+    /* NID_set_certExt */
+    0x67, 0x2a, 0x07,
+    /* NID_set_brand */
+    0x67, 0x2a, 0x08,
+    /* NID_setct_PANData */
+    0x67, 0x2a, 0x00, 0x00,
+    /* NID_setct_PANToken */
+    0x67, 0x2a, 0x00, 0x01,
+    /* NID_setct_PANOnly */
+    0x67, 0x2a, 0x00, 0x02,
+    /* NID_setct_OIData */
+    0x67, 0x2a, 0x00, 0x03,
+    /* NID_setct_PI */
+    0x67, 0x2a, 0x00, 0x04,
+    /* NID_setct_PIData */
+    0x67, 0x2a, 0x00, 0x05,
+    /* NID_setct_PIDataUnsigned */
+    0x67, 0x2a, 0x00, 0x06,
+    /* NID_setct_HODInput */
+    0x67, 0x2a, 0x00, 0x07,
+    /* NID_setct_AuthResBaggage */
+    0x67, 0x2a, 0x00, 0x08,
+    /* NID_setct_AuthRevReqBaggage */
+    0x67, 0x2a, 0x00, 0x09,
+    /* NID_setct_AuthRevResBaggage */
+    0x67, 0x2a, 0x00, 0x0a,
+    /* NID_setct_CapTokenSeq */
+    0x67, 0x2a, 0x00, 0x0b,
+    /* NID_setct_PInitResData */
+    0x67, 0x2a, 0x00, 0x0c,
+    /* NID_setct_PI_TBS */
+    0x67, 0x2a, 0x00, 0x0d,
+    /* NID_setct_PResData */
+    0x67, 0x2a, 0x00, 0x0e,
+    /* NID_setct_AuthReqTBS */
+    0x67, 0x2a, 0x00, 0x10,
+    /* NID_setct_AuthResTBS */
+    0x67, 0x2a, 0x00, 0x11,
+    /* NID_setct_AuthResTBSX */
+    0x67, 0x2a, 0x00, 0x12,
+    /* NID_setct_AuthTokenTBS */
+    0x67, 0x2a, 0x00, 0x13,
+    /* NID_setct_CapTokenData */
+    0x67, 0x2a, 0x00, 0x14,
+    /* NID_setct_CapTokenTBS */
+    0x67, 0x2a, 0x00, 0x15,
+    /* NID_setct_AcqCardCodeMsg */
+    0x67, 0x2a, 0x00, 0x16,
+    /* NID_setct_AuthRevReqTBS */
+    0x67, 0x2a, 0x00, 0x17,
+    /* NID_setct_AuthRevResData */
+    0x67, 0x2a, 0x00, 0x18,
+    /* NID_setct_AuthRevResTBS */
+    0x67, 0x2a, 0x00, 0x19,
+    /* NID_setct_CapReqTBS */
+    0x67, 0x2a, 0x00, 0x1a,
+    /* NID_setct_CapReqTBSX */
+    0x67, 0x2a, 0x00, 0x1b,
+    /* NID_setct_CapResData */
+    0x67, 0x2a, 0x00, 0x1c,
+    /* NID_setct_CapRevReqTBS */
+    0x67, 0x2a, 0x00, 0x1d,
+    /* NID_setct_CapRevReqTBSX */
+    0x67, 0x2a, 0x00, 0x1e,
+    /* NID_setct_CapRevResData */
+    0x67, 0x2a, 0x00, 0x1f,
+    /* NID_setct_CredReqTBS */
+    0x67, 0x2a, 0x00, 0x20,
+    /* NID_setct_CredReqTBSX */
+    0x67, 0x2a, 0x00, 0x21,
+    /* NID_setct_CredResData */
+    0x67, 0x2a, 0x00, 0x22,
+    /* NID_setct_CredRevReqTBS */
+    0x67, 0x2a, 0x00, 0x23,
+    /* NID_setct_CredRevReqTBSX */
+    0x67, 0x2a, 0x00, 0x24,
+    /* NID_setct_CredRevResData */
+    0x67, 0x2a, 0x00, 0x25,
+    /* NID_setct_PCertReqData */
+    0x67, 0x2a, 0x00, 0x26,
+    /* NID_setct_PCertResTBS */
+    0x67, 0x2a, 0x00, 0x27,
+    /* NID_setct_BatchAdminReqData */
+    0x67, 0x2a, 0x00, 0x28,
+    /* NID_setct_BatchAdminResData */
+    0x67, 0x2a, 0x00, 0x29,
+    /* NID_setct_CardCInitResTBS */
+    0x67, 0x2a, 0x00, 0x2a,
+    /* NID_setct_MeAqCInitResTBS */
+    0x67, 0x2a, 0x00, 0x2b,
+    /* NID_setct_RegFormResTBS */
+    0x67, 0x2a, 0x00, 0x2c,
+    /* NID_setct_CertReqData */
+    0x67, 0x2a, 0x00, 0x2d,
+    /* NID_setct_CertReqTBS */
+    0x67, 0x2a, 0x00, 0x2e,
+    /* NID_setct_CertResData */
+    0x67, 0x2a, 0x00, 0x2f,
+    /* NID_setct_CertInqReqTBS */
+    0x67, 0x2a, 0x00, 0x30,
+    /* NID_setct_ErrorTBS */
+    0x67, 0x2a, 0x00, 0x31,
+    /* NID_setct_PIDualSignedTBE */
+    0x67, 0x2a, 0x00, 0x32,
+    /* NID_setct_PIUnsignedTBE */
+    0x67, 0x2a, 0x00, 0x33,
+    /* NID_setct_AuthReqTBE */
+    0x67, 0x2a, 0x00, 0x34,
+    /* NID_setct_AuthResTBE */
+    0x67, 0x2a, 0x00, 0x35,
+    /* NID_setct_AuthResTBEX */
+    0x67, 0x2a, 0x00, 0x36,
+    /* NID_setct_AuthTokenTBE */
+    0x67, 0x2a, 0x00, 0x37,
+    /* NID_setct_CapTokenTBE */
+    0x67, 0x2a, 0x00, 0x38,
+    /* NID_setct_CapTokenTBEX */
+    0x67, 0x2a, 0x00, 0x39,
+    /* NID_setct_AcqCardCodeMsgTBE */
+    0x67, 0x2a, 0x00, 0x3a,
+    /* NID_setct_AuthRevReqTBE */
+    0x67, 0x2a, 0x00, 0x3b,
+    /* NID_setct_AuthRevResTBE */
+    0x67, 0x2a, 0x00, 0x3c,
+    /* NID_setct_AuthRevResTBEB */
+    0x67, 0x2a, 0x00, 0x3d,
+    /* NID_setct_CapReqTBE */
+    0x67, 0x2a, 0x00, 0x3e,
+    /* NID_setct_CapReqTBEX */
+    0x67, 0x2a, 0x00, 0x3f,
+    /* NID_setct_CapResTBE */
+    0x67, 0x2a, 0x00, 0x40,
+    /* NID_setct_CapRevReqTBE */
+    0x67, 0x2a, 0x00, 0x41,
+    /* NID_setct_CapRevReqTBEX */
+    0x67, 0x2a, 0x00, 0x42,
+    /* NID_setct_CapRevResTBE */
+    0x67, 0x2a, 0x00, 0x43,
+    /* NID_setct_CredReqTBE */
+    0x67, 0x2a, 0x00, 0x44,
+    /* NID_setct_CredReqTBEX */
+    0x67, 0x2a, 0x00, 0x45,
+    /* NID_setct_CredResTBE */
+    0x67, 0x2a, 0x00, 0x46,
+    /* NID_setct_CredRevReqTBE */
+    0x67, 0x2a, 0x00, 0x47,
+    /* NID_setct_CredRevReqTBEX */
+    0x67, 0x2a, 0x00, 0x48,
+    /* NID_setct_CredRevResTBE */
+    0x67, 0x2a, 0x00, 0x49,
+    /* NID_setct_BatchAdminReqTBE */
+    0x67, 0x2a, 0x00, 0x4a,
+    /* NID_setct_BatchAdminResTBE */
+    0x67, 0x2a, 0x00, 0x4b,
+    /* NID_setct_RegFormReqTBE */
+    0x67, 0x2a, 0x00, 0x4c,
+    /* NID_setct_CertReqTBE */
+    0x67, 0x2a, 0x00, 0x4d,
+    /* NID_setct_CertReqTBEX */
+    0x67, 0x2a, 0x00, 0x4e,
+    /* NID_setct_CertResTBE */
+    0x67, 0x2a, 0x00, 0x4f,
+    /* NID_setct_CRLNotificationTBS */
+    0x67, 0x2a, 0x00, 0x50,
+    /* NID_setct_CRLNotificationResTBS */
+    0x67, 0x2a, 0x00, 0x51,
+    /* NID_setct_BCIDistributionTBS */
+    0x67, 0x2a, 0x00, 0x52,
+    /* NID_setext_genCrypt */
+    0x67, 0x2a, 0x01, 0x01,
+    /* NID_setext_miAuth */
+    0x67, 0x2a, 0x01, 0x03,
+    /* NID_setext_pinSecure */
+    0x67, 0x2a, 0x01, 0x04,
+    /* NID_setext_pinAny */
+    0x67, 0x2a, 0x01, 0x05,
+    /* NID_setext_track2 */
+    0x67, 0x2a, 0x01, 0x07,
+    /* NID_setext_cv */
+    0x67, 0x2a, 0x01, 0x08,
+    /* NID_set_policy_root */
+    0x67, 0x2a, 0x05, 0x00,
+    /* NID_setCext_hashedRoot */
+    0x67, 0x2a, 0x07, 0x00,
+    /* NID_setCext_certType */
+    0x67, 0x2a, 0x07, 0x01,
+    /* NID_setCext_merchData */
+    0x67, 0x2a, 0x07, 0x02,
+    /* NID_setCext_cCertRequired */
+    0x67, 0x2a, 0x07, 0x03,
+    /* NID_setCext_tunneling */
+    0x67, 0x2a, 0x07, 0x04,
+    /* NID_setCext_setExt */
+    0x67, 0x2a, 0x07, 0x05,
+    /* NID_setCext_setQualf */
+    0x67, 0x2a, 0x07, 0x06,
+    /* NID_setCext_PGWYcapabilities */
+    0x67, 0x2a, 0x07, 0x07,
+    /* NID_setCext_TokenIdentifier */
+    0x67, 0x2a, 0x07, 0x08,
+    /* NID_setCext_Track2Data */
+    0x67, 0x2a, 0x07, 0x09,
+    /* NID_setCext_TokenType */
+    0x67, 0x2a, 0x07, 0x0a,
+    /* NID_setCext_IssuerCapabilities */
+    0x67, 0x2a, 0x07, 0x0b,
+    /* NID_setAttr_Cert */
+    0x67, 0x2a, 0x03, 0x00,
+    /* NID_setAttr_PGWYcap */
+    0x67, 0x2a, 0x03, 0x01,
+    /* NID_setAttr_TokenType */
+    0x67, 0x2a, 0x03, 0x02,
+    /* NID_setAttr_IssCap */
+    0x67, 0x2a, 0x03, 0x03,
+    /* NID_set_rootKeyThumb */
+    0x67, 0x2a, 0x03, 0x00, 0x00,
+    /* NID_set_addPolicy */
+    0x67, 0x2a, 0x03, 0x00, 0x01,
+    /* NID_setAttr_Token_EMV */
+    0x67, 0x2a, 0x03, 0x02, 0x01,
+    /* NID_setAttr_Token_B0Prime */
+    0x67, 0x2a, 0x03, 0x02, 0x02,
+    /* NID_setAttr_IssCap_CVM */
+    0x67, 0x2a, 0x03, 0x03, 0x03,
+    /* NID_setAttr_IssCap_T2 */
+    0x67, 0x2a, 0x03, 0x03, 0x04,
+    /* NID_setAttr_IssCap_Sig */
+    0x67, 0x2a, 0x03, 0x03, 0x05,
+    /* NID_setAttr_GenCryptgrm */
+    0x67, 0x2a, 0x03, 0x03, 0x03, 0x01,
+    /* NID_setAttr_T2Enc */
+    0x67, 0x2a, 0x03, 0x03, 0x04, 0x01,
+    /* NID_setAttr_T2cleartxt */
+    0x67, 0x2a, 0x03, 0x03, 0x04, 0x02,
+    /* NID_setAttr_TokICCsig */
+    0x67, 0x2a, 0x03, 0x03, 0x05, 0x01,
+    /* NID_setAttr_SecDevSig */
+    0x67, 0x2a, 0x03, 0x03, 0x05, 0x02,
+    /* NID_set_brand_IATA_ATA */
+    0x67, 0x2a, 0x08, 0x01,
+    /* NID_set_brand_Diners */
+    0x67, 0x2a, 0x08, 0x1e,
+    /* NID_set_brand_AmericanExpress */
+    0x67, 0x2a, 0x08, 0x22,
+    /* NID_set_brand_JCB */
+    0x67, 0x2a, 0x08, 0x23,
+    /* NID_set_brand_Visa */
+    0x67, 0x2a, 0x08, 0x04,
+    /* NID_set_brand_MasterCard */
+    0x67, 0x2a, 0x08, 0x05,
+    /* NID_set_brand_Novus */
+    0x67, 0x2a, 0x08, 0xae, 0x7b,
+    /* NID_des_cdmf */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x0a,
+    /* NID_rsaOAEPEncryptionSET */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x06,
+    /* NID_international_organizations */
+    0x67,
+    /* NID_ms_smartcard_login */
+    0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x14, 0x02, 0x02,
+    /* NID_ms_upn */
+    0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x14, 0x02, 0x03,
+    /* NID_streetAddress */
+    0x55, 0x04, 0x09,
+    /* NID_postalCode */
+    0x55, 0x04, 0x11,
+    /* NID_id_ppl */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x15,
+    /* NID_proxyCertInfo */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x0e,
+    /* NID_id_ppl_anyLanguage */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x15, 0x00,
+    /* NID_id_ppl_inheritAll */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x15, 0x01,
+    /* NID_name_constraints */
+    0x55, 0x1d, 0x1e,
+    /* NID_Independent */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x15, 0x02,
+    /* NID_sha256WithRSAEncryption */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
+    /* NID_sha384WithRSAEncryption */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0c,
+    /* NID_sha512WithRSAEncryption */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d,
+    /* NID_sha224WithRSAEncryption */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0e,
+    /* NID_sha256 */
+    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
+    /* NID_sha384 */
+    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
+    /* NID_sha512 */
+    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
+    /* NID_sha224 */
+    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04,
+    /* NID_identified_organization */
+    0x2b,
+    /* NID_certicom_arc */
+    0x2b, 0x81, 0x04,
+    /* NID_wap */
+    0x67, 0x2b,
+    /* NID_wap_wsg */
+    0x67, 0x2b, 0x01,
+    /* NID_X9_62_id_characteristic_two_basis */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, 0x02, 0x03,
+    /* NID_X9_62_onBasis */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, 0x02, 0x03, 0x01,
+    /* NID_X9_62_tpBasis */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, 0x02, 0x03, 0x02,
+    /* NID_X9_62_ppBasis */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x01, 0x02, 0x03, 0x03,
+    /* NID_X9_62_c2pnb163v1 */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x00, 0x01,
+    /* NID_X9_62_c2pnb163v2 */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x00, 0x02,
+    /* NID_X9_62_c2pnb163v3 */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x00, 0x03,
+    /* NID_X9_62_c2pnb176v1 */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x00, 0x04,
+    /* NID_X9_62_c2tnb191v1 */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x00, 0x05,
+    /* NID_X9_62_c2tnb191v2 */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x00, 0x06,
+    /* NID_X9_62_c2tnb191v3 */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x00, 0x07,
+    /* NID_X9_62_c2onb191v4 */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x00, 0x08,
+    /* NID_X9_62_c2onb191v5 */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x00, 0x09,
+    /* NID_X9_62_c2pnb208w1 */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x00, 0x0a,
+    /* NID_X9_62_c2tnb239v1 */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x00, 0x0b,
+    /* NID_X9_62_c2tnb239v2 */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x00, 0x0c,
+    /* NID_X9_62_c2tnb239v3 */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x00, 0x0d,
+    /* NID_X9_62_c2onb239v4 */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x00, 0x0e,
+    /* NID_X9_62_c2onb239v5 */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x00, 0x0f,
+    /* NID_X9_62_c2pnb272w1 */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x00, 0x10,
+    /* NID_X9_62_c2pnb304w1 */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x00, 0x11,
+    /* NID_X9_62_c2tnb359v1 */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x00, 0x12,
+    /* NID_X9_62_c2pnb368w1 */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x00, 0x13,
+    /* NID_X9_62_c2tnb431r1 */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x00, 0x14,
+    /* NID_secp112r1 */
+    0x2b, 0x81, 0x04, 0x00, 0x06,
+    /* NID_secp112r2 */
+    0x2b, 0x81, 0x04, 0x00, 0x07,
+    /* NID_secp128r1 */
+    0x2b, 0x81, 0x04, 0x00, 0x1c,
+    /* NID_secp128r2 */
+    0x2b, 0x81, 0x04, 0x00, 0x1d,
+    /* NID_secp160k1 */
+    0x2b, 0x81, 0x04, 0x00, 0x09,
+    /* NID_secp160r1 */
+    0x2b, 0x81, 0x04, 0x00, 0x08,
+    /* NID_secp160r2 */
+    0x2b, 0x81, 0x04, 0x00, 0x1e,
+    /* NID_secp192k1 */
+    0x2b, 0x81, 0x04, 0x00, 0x1f,
+    /* NID_secp224k1 */
+    0x2b, 0x81, 0x04, 0x00, 0x20,
+    /* NID_secp224r1 */
+    0x2b, 0x81, 0x04, 0x00, 0x21,
+    /* NID_secp256k1 */
+    0x2b, 0x81, 0x04, 0x00, 0x0a,
+    /* NID_secp384r1 */
+    0x2b, 0x81, 0x04, 0x00, 0x22,
+    /* NID_secp521r1 */
+    0x2b, 0x81, 0x04, 0x00, 0x23,
+    /* NID_sect113r1 */
+    0x2b, 0x81, 0x04, 0x00, 0x04,
+    /* NID_sect113r2 */
+    0x2b, 0x81, 0x04, 0x00, 0x05,
+    /* NID_sect131r1 */
+    0x2b, 0x81, 0x04, 0x00, 0x16,
+    /* NID_sect131r2 */
+    0x2b, 0x81, 0x04, 0x00, 0x17,
+    /* NID_sect163k1 */
+    0x2b, 0x81, 0x04, 0x00, 0x01,
+    /* NID_sect163r1 */
+    0x2b, 0x81, 0x04, 0x00, 0x02,
+    /* NID_sect163r2 */
+    0x2b, 0x81, 0x04, 0x00, 0x0f,
+    /* NID_sect193r1 */
+    0x2b, 0x81, 0x04, 0x00, 0x18,
+    /* NID_sect193r2 */
+    0x2b, 0x81, 0x04, 0x00, 0x19,
+    /* NID_sect233k1 */
+    0x2b, 0x81, 0x04, 0x00, 0x1a,
+    /* NID_sect233r1 */
+    0x2b, 0x81, 0x04, 0x00, 0x1b,
+    /* NID_sect239k1 */
+    0x2b, 0x81, 0x04, 0x00, 0x03,
+    /* NID_sect283k1 */
+    0x2b, 0x81, 0x04, 0x00, 0x10,
+    /* NID_sect283r1 */
+    0x2b, 0x81, 0x04, 0x00, 0x11,
+    /* NID_sect409k1 */
+    0x2b, 0x81, 0x04, 0x00, 0x24,
+    /* NID_sect409r1 */
+    0x2b, 0x81, 0x04, 0x00, 0x25,
+    /* NID_sect571k1 */
+    0x2b, 0x81, 0x04, 0x00, 0x26,
+    /* NID_sect571r1 */
+    0x2b, 0x81, 0x04, 0x00, 0x27,
+    /* NID_wap_wsg_idm_ecid_wtls1 */
+    0x67, 0x2b, 0x01, 0x04, 0x01,
+    /* NID_wap_wsg_idm_ecid_wtls3 */
+    0x67, 0x2b, 0x01, 0x04, 0x03,
+    /* NID_wap_wsg_idm_ecid_wtls4 */
+    0x67, 0x2b, 0x01, 0x04, 0x04,
+    /* NID_wap_wsg_idm_ecid_wtls5 */
+    0x67, 0x2b, 0x01, 0x04, 0x05,
+    /* NID_wap_wsg_idm_ecid_wtls6 */
+    0x67, 0x2b, 0x01, 0x04, 0x06,
+    /* NID_wap_wsg_idm_ecid_wtls7 */
+    0x67, 0x2b, 0x01, 0x04, 0x07,
+    /* NID_wap_wsg_idm_ecid_wtls8 */
+    0x67, 0x2b, 0x01, 0x04, 0x08,
+    /* NID_wap_wsg_idm_ecid_wtls9 */
+    0x67, 0x2b, 0x01, 0x04, 0x09,
+    /* NID_wap_wsg_idm_ecid_wtls10 */
+    0x67, 0x2b, 0x01, 0x04, 0x0a,
+    /* NID_wap_wsg_idm_ecid_wtls11 */
+    0x67, 0x2b, 0x01, 0x04, 0x0b,
+    /* NID_wap_wsg_idm_ecid_wtls12 */
+    0x67, 0x2b, 0x01, 0x04, 0x0c,
+    /* NID_any_policy */
+    0x55, 0x1d, 0x20, 0x00,
+    /* NID_policy_mappings */
+    0x55, 0x1d, 0x21,
+    /* NID_inhibit_any_policy */
+    0x55, 0x1d, 0x36,
+    /* NID_camellia_128_cbc */
+    0x2a, 0x83, 0x08, 0x8c, 0x9a, 0x4b, 0x3d, 0x01, 0x01, 0x01, 0x02,
+    /* NID_camellia_192_cbc */
+    0x2a, 0x83, 0x08, 0x8c, 0x9a, 0x4b, 0x3d, 0x01, 0x01, 0x01, 0x03,
+    /* NID_camellia_256_cbc */
+    0x2a, 0x83, 0x08, 0x8c, 0x9a, 0x4b, 0x3d, 0x01, 0x01, 0x01, 0x04,
+    /* NID_camellia_128_ecb */
+    0x03, 0xa2, 0x31, 0x05, 0x03, 0x01, 0x09, 0x01,
+    /* NID_camellia_192_ecb */
+    0x03, 0xa2, 0x31, 0x05, 0x03, 0x01, 0x09, 0x15,
+    /* NID_camellia_256_ecb */
+    0x03, 0xa2, 0x31, 0x05, 0x03, 0x01, 0x09, 0x29,
+    /* NID_camellia_128_cfb128 */
+    0x03, 0xa2, 0x31, 0x05, 0x03, 0x01, 0x09, 0x04,
+    /* NID_camellia_192_cfb128 */
+    0x03, 0xa2, 0x31, 0x05, 0x03, 0x01, 0x09, 0x18,
+    /* NID_camellia_256_cfb128 */
+    0x03, 0xa2, 0x31, 0x05, 0x03, 0x01, 0x09, 0x2c,
+    /* NID_camellia_128_ofb128 */
+    0x03, 0xa2, 0x31, 0x05, 0x03, 0x01, 0x09, 0x03,
+    /* NID_camellia_192_ofb128 */
+    0x03, 0xa2, 0x31, 0x05, 0x03, 0x01, 0x09, 0x17,
+    /* NID_camellia_256_ofb128 */
+    0x03, 0xa2, 0x31, 0x05, 0x03, 0x01, 0x09, 0x2b,
+    /* NID_subject_directory_attributes */
+    0x55, 0x1d, 0x09,
+    /* NID_issuing_distribution_point */
+    0x55, 0x1d, 0x1c,
+    /* NID_certificate_issuer */
+    0x55, 0x1d, 0x1d,
+    /* NID_kisa */
+    0x2a, 0x83, 0x1a, 0x8c, 0x9a, 0x44,
+    /* NID_seed_ecb */
+    0x2a, 0x83, 0x1a, 0x8c, 0x9a, 0x44, 0x01, 0x03,
+    /* NID_seed_cbc */
+    0x2a, 0x83, 0x1a, 0x8c, 0x9a, 0x44, 0x01, 0x04,
+    /* NID_seed_ofb128 */
+    0x2a, 0x83, 0x1a, 0x8c, 0x9a, 0x44, 0x01, 0x06,
+    /* NID_seed_cfb128 */
+    0x2a, 0x83, 0x1a, 0x8c, 0x9a, 0x44, 0x01, 0x05,
+    /* NID_hmac_md5 */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x08, 0x01, 0x01,
+    /* NID_hmac_sha1 */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x08, 0x01, 0x02,
+    /* NID_id_PasswordBasedMAC */
+    0x2a, 0x86, 0x48, 0x86, 0xf6, 0x7d, 0x07, 0x42, 0x0d,
+    /* NID_id_DHBasedMac */
+    0x2a, 0x86, 0x48, 0x86, 0xf6, 0x7d, 0x07, 0x42, 0x1e,
+    /* NID_id_it_suppLangTags */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x04, 0x10,
+    /* NID_caRepository */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x05,
+    /* NID_id_smime_ct_compressedData */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x01, 0x09,
+    /* NID_id_ct_asciiTextWithCRLF */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x01, 0x1b,
+    /* NID_id_aes128_wrap */
+    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x05,
+    /* NID_id_aes192_wrap */
+    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x19,
+    /* NID_id_aes256_wrap */
+    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2d,
+    /* NID_ecdsa_with_Recommended */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x02,
+    /* NID_ecdsa_with_Specified */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03,
+    /* NID_ecdsa_with_SHA224 */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x01,
+    /* NID_ecdsa_with_SHA256 */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02,
+    /* NID_ecdsa_with_SHA384 */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03,
+    /* NID_ecdsa_with_SHA512 */
+    0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x04,
+    /* NID_hmacWithMD5 */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x06,
+    /* NID_hmacWithSHA224 */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x08,
+    /* NID_hmacWithSHA256 */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x09,
+    /* NID_hmacWithSHA384 */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x0a,
+    /* NID_hmacWithSHA512 */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x0b,
+    /* NID_dsa_with_SHA224 */
+    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x01,
+    /* NID_dsa_with_SHA256 */
+    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x03, 0x02,
+    /* NID_whirlpool */
+    0x28, 0xcf, 0x06, 0x03, 0x00, 0x37,
+    /* NID_cryptopro */
+    0x2a, 0x85, 0x03, 0x02, 0x02,
+    /* NID_cryptocom */
+    0x2a, 0x85, 0x03, 0x02, 0x09,
+    /* NID_id_GostR3411_94_with_GostR3410_2001 */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x03,
+    /* NID_id_GostR3411_94_with_GostR3410_94 */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x04,
+    /* NID_id_GostR3411_94 */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x09,
+    /* NID_id_HMACGostR3411_94 */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x0a,
+    /* NID_id_GostR3410_2001 */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x13,
+    /* NID_id_GostR3410_94 */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x14,
+    /* NID_id_Gost28147_89 */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x15,
+    /* NID_id_Gost28147_89_MAC */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x16,
+    /* NID_id_GostR3411_94_prf */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x17,
+    /* NID_id_GostR3410_2001DH */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x62,
+    /* NID_id_GostR3410_94DH */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x63,
+    /* NID_id_Gost28147_89_CryptoPro_KeyMeshing */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x0e, 0x01,
+    /* NID_id_Gost28147_89_None_KeyMeshing */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x0e, 0x00,
+    /* NID_id_GostR3411_94_TestParamSet */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x1e, 0x00,
+    /* NID_id_GostR3411_94_CryptoProParamSet */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x1e, 0x01,
+    /* NID_id_Gost28147_89_TestParamSet */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x1f, 0x00,
+    /* NID_id_Gost28147_89_CryptoPro_A_ParamSet */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x1f, 0x01,
+    /* NID_id_Gost28147_89_CryptoPro_B_ParamSet */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x1f, 0x02,
+    /* NID_id_Gost28147_89_CryptoPro_C_ParamSet */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x1f, 0x03,
+    /* NID_id_Gost28147_89_CryptoPro_D_ParamSet */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x1f, 0x04,
+    /* NID_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x1f, 0x05,
+    /* NID_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x1f, 0x06,
+    /* NID_id_Gost28147_89_CryptoPro_RIC_1_ParamSet */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x1f, 0x07,
+    /* NID_id_GostR3410_94_TestParamSet */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x20, 0x00,
+    /* NID_id_GostR3410_94_CryptoPro_A_ParamSet */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x20, 0x02,
+    /* NID_id_GostR3410_94_CryptoPro_B_ParamSet */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x20, 0x03,
+    /* NID_id_GostR3410_94_CryptoPro_C_ParamSet */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x20, 0x04,
+    /* NID_id_GostR3410_94_CryptoPro_D_ParamSet */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x20, 0x05,
+    /* NID_id_GostR3410_94_CryptoPro_XchA_ParamSet */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x21, 0x01,
+    /* NID_id_GostR3410_94_CryptoPro_XchB_ParamSet */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x21, 0x02,
+    /* NID_id_GostR3410_94_CryptoPro_XchC_ParamSet */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x21, 0x03,
+    /* NID_id_GostR3410_2001_TestParamSet */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x23, 0x00,
+    /* NID_id_GostR3410_2001_CryptoPro_A_ParamSet */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x23, 0x01,
+    /* NID_id_GostR3410_2001_CryptoPro_B_ParamSet */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x23, 0x02,
+    /* NID_id_GostR3410_2001_CryptoPro_C_ParamSet */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x23, 0x03,
+    /* NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x24, 0x00,
+    /* NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x24, 0x01,
+    /* NID_id_GostR3410_94_a */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x14, 0x01,
+    /* NID_id_GostR3410_94_aBis */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x14, 0x02,
+    /* NID_id_GostR3410_94_b */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x14, 0x03,
+    /* NID_id_GostR3410_94_bBis */
+    0x2a, 0x85, 0x03, 0x02, 0x02, 0x14, 0x04,
+    /* NID_id_Gost28147_89_cc */
+    0x2a, 0x85, 0x03, 0x02, 0x09, 0x01, 0x06, 0x01,
+    /* NID_id_GostR3410_94_cc */
+    0x2a, 0x85, 0x03, 0x02, 0x09, 0x01, 0x05, 0x03,
+    /* NID_id_GostR3410_2001_cc */
+    0x2a, 0x85, 0x03, 0x02, 0x09, 0x01, 0x05, 0x04,
+    /* NID_id_GostR3411_94_with_GostR3410_94_cc */
+    0x2a, 0x85, 0x03, 0x02, 0x09, 0x01, 0x03, 0x03,
+    /* NID_id_GostR3411_94_with_GostR3410_2001_cc */
+    0x2a, 0x85, 0x03, 0x02, 0x09, 0x01, 0x03, 0x04,
+    /* NID_id_GostR3410_2001_ParamSet_cc */
+    0x2a, 0x85, 0x03, 0x02, 0x09, 0x01, 0x08, 0x01,
+    /* NID_LocalKeySet */
+    0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x11, 0x02,
+    /* NID_freshest_crl */
+    0x55, 0x1d, 0x2e,
+    /* NID_id_on_permanentIdentifier */
+    0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x08, 0x03,
+    /* NID_searchGuide */
+    0x55, 0x04, 0x0e,
+    /* NID_businessCategory */
+    0x55, 0x04, 0x0f,
+    /* NID_postalAddress */
+    0x55, 0x04, 0x10,
+    /* NID_postOfficeBox */
+    0x55, 0x04, 0x12,
+    /* NID_physicalDeliveryOfficeName */
+    0x55, 0x04, 0x13,
+    /* NID_telephoneNumber */
+    0x55, 0x04, 0x14,
+    /* NID_telexNumber */
+    0x55, 0x04, 0x15,
+    /* NID_teletexTerminalIdentifier */
+    0x55, 0x04, 0x16,
+    /* NID_facsimileTelephoneNumber */
+    0x55, 0x04, 0x17,
+    /* NID_x121Address */
+    0x55, 0x04, 0x18,
+    /* NID_internationaliSDNNumber */
+    0x55, 0x04, 0x19,
+    /* NID_registeredAddress */
+    0x55, 0x04, 0x1a,
+    /* NID_destinationIndicator */
+    0x55, 0x04, 0x1b,
+    /* NID_preferredDeliveryMethod */
+    0x55, 0x04, 0x1c,
+    /* NID_presentationAddress */
+    0x55, 0x04, 0x1d,
+    /* NID_supportedApplicationContext */
+    0x55, 0x04, 0x1e,
+    /* NID_member */
+    0x55, 0x04, 0x1f,
+    /* NID_owner */
+    0x55, 0x04, 0x20,
+    /* NID_roleOccupant */
+    0x55, 0x04, 0x21,
+    /* NID_seeAlso */
+    0x55, 0x04, 0x22,
+    /* NID_userPassword */
+    0x55, 0x04, 0x23,
+    /* NID_userCertificate */
+    0x55, 0x04, 0x24,
+    /* NID_cACertificate */
+    0x55, 0x04, 0x25,
+    /* NID_authorityRevocationList */
+    0x55, 0x04, 0x26,
+    /* NID_certificateRevocationList */
+    0x55, 0x04, 0x27,
+    /* NID_crossCertificatePair */
+    0x55, 0x04, 0x28,
+    /* NID_enhancedSearchGuide */
+    0x55, 0x04, 0x2f,
+    /* NID_protocolInformation */
+    0x55, 0x04, 0x30,
+    /* NID_distinguishedName */
+    0x55, 0x04, 0x31,
+    /* NID_uniqueMember */
+    0x55, 0x04, 0x32,
+    /* NID_houseIdentifier */
+    0x55, 0x04, 0x33,
+    /* NID_supportedAlgorithms */
+    0x55, 0x04, 0x34,
+    /* NID_deltaRevocationList */
+    0x55, 0x04, 0x35,
+    /* NID_dmdName */
+    0x55, 0x04, 0x36,
+    /* NID_id_alg_PWRI_KEK */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x10, 0x03, 0x09,
+    /* NID_aes_128_gcm */
+    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x06,
+    /* NID_aes_128_ccm */
+    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x07,
+    /* NID_id_aes128_wrap_pad */
+    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x08,
+    /* NID_aes_192_gcm */
+    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x1a,
+    /* NID_aes_192_ccm */
+    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x1b,
+    /* NID_id_aes192_wrap_pad */
+    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x1c,
+    /* NID_aes_256_gcm */
+    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2e,
+    /* NID_aes_256_ccm */
+    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2f,
+    /* NID_id_aes256_wrap_pad */
+    0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x30,
+    /* NID_id_camellia128_wrap */
+    0x2a, 0x83, 0x08, 0x8c, 0x9a, 0x4b, 0x3d, 0x01, 0x01, 0x03, 0x02,
+    /* NID_id_camellia192_wrap */
+    0x2a, 0x83, 0x08, 0x8c, 0x9a, 0x4b, 0x3d, 0x01, 0x01, 0x03, 0x03,
+    /* NID_id_camellia256_wrap */
+    0x2a, 0x83, 0x08, 0x8c, 0x9a, 0x4b, 0x3d, 0x01, 0x01, 0x03, 0x04,
+    /* NID_anyExtendedKeyUsage */
+    0x55, 0x1d, 0x25, 0x00,
+    /* NID_mgf1 */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x08,
+    /* NID_rsassaPss */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0a,
+    /* NID_rsaesOaep */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x07,
+    /* NID_dhpublicnumber */
+    0x2a, 0x86, 0x48, 0xce, 0x3e, 0x02, 0x01,
+    /* NID_brainpoolP160r1 */
+    0x2b, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x01,
+    /* NID_brainpoolP160t1 */
+    0x2b, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x02,
+    /* NID_brainpoolP192r1 */
+    0x2b, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x03,
+    /* NID_brainpoolP192t1 */
+    0x2b, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x04,
+    /* NID_brainpoolP224r1 */
+    0x2b, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x05,
+    /* NID_brainpoolP224t1 */
+    0x2b, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x06,
+    /* NID_brainpoolP256r1 */
+    0x2b, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x07,
+    /* NID_brainpoolP256t1 */
+    0x2b, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x08,
+    /* NID_brainpoolP320r1 */
+    0x2b, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x09,
+    /* NID_brainpoolP320t1 */
+    0x2b, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0a,
+    /* NID_brainpoolP384r1 */
+    0x2b, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0b,
+    /* NID_brainpoolP384t1 */
+    0x2b, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0c,
+    /* NID_brainpoolP512r1 */
+    0x2b, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0d,
+    /* NID_brainpoolP512t1 */
+    0x2b, 0x24, 0x03, 0x03, 0x02, 0x08, 0x01, 0x01, 0x0e,
+    /* NID_pSpecified */
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x09,
+    /* NID_dhSinglePass_stdDH_sha1kdf_scheme */
+    0x2b, 0x81, 0x05, 0x10, 0x86, 0x48, 0x3f, 0x00, 0x02,
+    /* NID_dhSinglePass_stdDH_sha224kdf_scheme */
+    0x2b, 0x81, 0x04, 0x01, 0x0b, 0x00,
+    /* NID_dhSinglePass_stdDH_sha256kdf_scheme */
+    0x2b, 0x81, 0x04, 0x01, 0x0b, 0x01,
+    /* NID_dhSinglePass_stdDH_sha384kdf_scheme */
+    0x2b, 0x81, 0x04, 0x01, 0x0b, 0x02,
+    /* NID_dhSinglePass_stdDH_sha512kdf_scheme */
+    0x2b, 0x81, 0x04, 0x01, 0x0b, 0x03,
+    /* NID_dhSinglePass_cofactorDH_sha1kdf_scheme */
+    0x2b, 0x81, 0x05, 0x10, 0x86, 0x48, 0x3f, 0x00, 0x03,
+    /* NID_dhSinglePass_cofactorDH_sha224kdf_scheme */
+    0x2b, 0x81, 0x04, 0x01, 0x0e, 0x00,
+    /* NID_dhSinglePass_cofactorDH_sha256kdf_scheme */
+    0x2b, 0x81, 0x04, 0x01, 0x0e, 0x01,
+    /* NID_dhSinglePass_cofactorDH_sha384kdf_scheme */
+    0x2b, 0x81, 0x04, 0x01, 0x0e, 0x02,
+    /* NID_dhSinglePass_cofactorDH_sha512kdf_scheme */
+    0x2b, 0x81, 0x04, 0x01, 0x0e, 0x03,
 };
 
-static const ASN1_OBJECT kObjects[NUM_NID]={
-{"UNDEF","undefined",NID_undef,0,NULL,0},
-{"rsadsi","RSA Data Security, Inc.",NID_rsadsi,6,&(lvalues[0]),0},
-{"pkcs","RSA Data Security, Inc. PKCS",NID_pkcs,7,&(lvalues[6]),0},
-{"MD2","md2",NID_md2,8,&(lvalues[13]),0},
-{"MD5","md5",NID_md5,8,&(lvalues[21]),0},
-{"RC4","rc4",NID_rc4,8,&(lvalues[29]),0},
-{"rsaEncryption","rsaEncryption",NID_rsaEncryption,9,&(lvalues[37]),0},
-{"RSA-MD2","md2WithRSAEncryption",NID_md2WithRSAEncryption,9,
-	&(lvalues[46]),0},
-{"RSA-MD5","md5WithRSAEncryption",NID_md5WithRSAEncryption,9,
-	&(lvalues[55]),0},
-{"PBE-MD2-DES","pbeWithMD2AndDES-CBC",NID_pbeWithMD2AndDES_CBC,9,
-	&(lvalues[64]),0},
-{"PBE-MD5-DES","pbeWithMD5AndDES-CBC",NID_pbeWithMD5AndDES_CBC,9,
-	&(lvalues[73]),0},
-{"X500","directory services (X.500)",NID_X500,1,&(lvalues[82]),0},
-{"X509","X509",NID_X509,2,&(lvalues[83]),0},
-{"CN","commonName",NID_commonName,3,&(lvalues[85]),0},
-{"C","countryName",NID_countryName,3,&(lvalues[88]),0},
-{"L","localityName",NID_localityName,3,&(lvalues[91]),0},
-{"ST","stateOrProvinceName",NID_stateOrProvinceName,3,&(lvalues[94]),0},
-{"O","organizationName",NID_organizationName,3,&(lvalues[97]),0},
-{"OU","organizationalUnitName",NID_organizationalUnitName,3,
-	&(lvalues[100]),0},
-{"RSA","rsa",NID_rsa,4,&(lvalues[103]),0},
-{"pkcs7","pkcs7",NID_pkcs7,8,&(lvalues[107]),0},
-{"pkcs7-data","pkcs7-data",NID_pkcs7_data,9,&(lvalues[115]),0},
-{"pkcs7-signedData","pkcs7-signedData",NID_pkcs7_signed,9,
-	&(lvalues[124]),0},
-{"pkcs7-envelopedData","pkcs7-envelopedData",NID_pkcs7_enveloped,9,
-	&(lvalues[133]),0},
-{"pkcs7-signedAndEnvelopedData","pkcs7-signedAndEnvelopedData",
-	NID_pkcs7_signedAndEnveloped,9,&(lvalues[142]),0},
-{"pkcs7-digestData","pkcs7-digestData",NID_pkcs7_digest,9,
-	&(lvalues[151]),0},
-{"pkcs7-encryptedData","pkcs7-encryptedData",NID_pkcs7_encrypted,9,
-	&(lvalues[160]),0},
-{"pkcs3","pkcs3",NID_pkcs3,8,&(lvalues[169]),0},
-{"dhKeyAgreement","dhKeyAgreement",NID_dhKeyAgreement,9,
-	&(lvalues[177]),0},
-{"DES-ECB","des-ecb",NID_des_ecb,5,&(lvalues[186]),0},
-{"DES-CFB","des-cfb",NID_des_cfb64,5,&(lvalues[191]),0},
-{"DES-CBC","des-cbc",NID_des_cbc,5,&(lvalues[196]),0},
-{"DES-EDE","des-ede",NID_des_ede_ecb,5,&(lvalues[201]),0},
-{"DES-EDE3","des-ede3",NID_des_ede3_ecb,0,NULL,0},
-{"IDEA-CBC","idea-cbc",NID_idea_cbc,11,&(lvalues[206]),0},
-{"IDEA-CFB","idea-cfb",NID_idea_cfb64,0,NULL,0},
-{"IDEA-ECB","idea-ecb",NID_idea_ecb,0,NULL,0},
-{"RC2-CBC","rc2-cbc",NID_rc2_cbc,8,&(lvalues[217]),0},
-{"RC2-ECB","rc2-ecb",NID_rc2_ecb,0,NULL,0},
-{"RC2-CFB","rc2-cfb",NID_rc2_cfb64,0,NULL,0},
-{"RC2-OFB","rc2-ofb",NID_rc2_ofb64,0,NULL,0},
-{"SHA","sha",NID_sha,5,&(lvalues[225]),0},
-{"RSA-SHA","shaWithRSAEncryption",NID_shaWithRSAEncryption,5,
-	&(lvalues[230]),0},
-{"DES-EDE-CBC","des-ede-cbc",NID_des_ede_cbc,0,NULL,0},
-{"DES-EDE3-CBC","des-ede3-cbc",NID_des_ede3_cbc,8,&(lvalues[235]),0},
-{"DES-OFB","des-ofb",NID_des_ofb64,5,&(lvalues[243]),0},
-{"IDEA-OFB","idea-ofb",NID_idea_ofb64,0,NULL,0},
-{"pkcs9","pkcs9",NID_pkcs9,8,&(lvalues[248]),0},
-{"emailAddress","emailAddress",NID_pkcs9_emailAddress,9,
-	&(lvalues[256]),0},
-{"unstructuredName","unstructuredName",NID_pkcs9_unstructuredName,9,
-	&(lvalues[265]),0},
-{"contentType","contentType",NID_pkcs9_contentType,9,&(lvalues[274]),0},
-{"messageDigest","messageDigest",NID_pkcs9_messageDigest,9,
-	&(lvalues[283]),0},
-{"signingTime","signingTime",NID_pkcs9_signingTime,9,&(lvalues[292]),0},
-{"countersignature","countersignature",NID_pkcs9_countersignature,9,
-	&(lvalues[301]),0},
-{"challengePassword","challengePassword",NID_pkcs9_challengePassword,
-	9,&(lvalues[310]),0},
-{"unstructuredAddress","unstructuredAddress",
-	NID_pkcs9_unstructuredAddress,9,&(lvalues[319]),0},
-{"extendedCertificateAttributes","extendedCertificateAttributes",
-	NID_pkcs9_extCertAttributes,9,&(lvalues[328]),0},
-{"Netscape","Netscape Communications Corp.",NID_netscape,7,
-	&(lvalues[337]),0},
-{"nsCertExt","Netscape Certificate Extension",
-	NID_netscape_cert_extension,8,&(lvalues[344]),0},
-{"nsDataType","Netscape Data Type",NID_netscape_data_type,8,
-	&(lvalues[352]),0},
-{"DES-EDE-CFB","des-ede-cfb",NID_des_ede_cfb64,0,NULL,0},
-{"DES-EDE3-CFB","des-ede3-cfb",NID_des_ede3_cfb64,0,NULL,0},
-{"DES-EDE-OFB","des-ede-ofb",NID_des_ede_ofb64,0,NULL,0},
-{"DES-EDE3-OFB","des-ede3-ofb",NID_des_ede3_ofb64,0,NULL,0},
-{"SHA1","sha1",NID_sha1,5,&(lvalues[360]),0},
-{"RSA-SHA1","sha1WithRSAEncryption",NID_sha1WithRSAEncryption,9,
-	&(lvalues[365]),0},
-{"DSA-SHA","dsaWithSHA",NID_dsaWithSHA,5,&(lvalues[374]),0},
-{"DSA-old","dsaEncryption-old",NID_dsa_2,5,&(lvalues[379]),0},
-{"PBE-SHA1-RC2-64","pbeWithSHA1AndRC2-CBC",NID_pbeWithSHA1AndRC2_CBC,
-	9,&(lvalues[384]),0},
-{"PBKDF2","PBKDF2",NID_id_pbkdf2,9,&(lvalues[393]),0},
-{"DSA-SHA1-old","dsaWithSHA1-old",NID_dsaWithSHA1_2,5,&(lvalues[402]),0},
-{"nsCertType","Netscape Cert Type",NID_netscape_cert_type,9,
-	&(lvalues[407]),0},
-{"nsBaseUrl","Netscape Base Url",NID_netscape_base_url,9,
-	&(lvalues[416]),0},
-{"nsRevocationUrl","Netscape Revocation Url",
-	NID_netscape_revocation_url,9,&(lvalues[425]),0},
-{"nsCaRevocationUrl","Netscape CA Revocation Url",
-	NID_netscape_ca_revocation_url,9,&(lvalues[434]),0},
-{"nsRenewalUrl","Netscape Renewal Url",NID_netscape_renewal_url,9,
-	&(lvalues[443]),0},
-{"nsCaPolicyUrl","Netscape CA Policy Url",NID_netscape_ca_policy_url,
-	9,&(lvalues[452]),0},
-{"nsSslServerName","Netscape SSL Server Name",
-	NID_netscape_ssl_server_name,9,&(lvalues[461]),0},
-{"nsComment","Netscape Comment",NID_netscape_comment,9,&(lvalues[470]),0},
-{"nsCertSequence","Netscape Certificate Sequence",
-	NID_netscape_cert_sequence,9,&(lvalues[479]),0},
-{"DESX-CBC","desx-cbc",NID_desx_cbc,0,NULL,0},
-{"id-ce","id-ce",NID_id_ce,2,&(lvalues[488]),0},
-{"subjectKeyIdentifier","X509v3 Subject Key Identifier",
-	NID_subject_key_identifier,3,&(lvalues[490]),0},
-{"keyUsage","X509v3 Key Usage",NID_key_usage,3,&(lvalues[493]),0},
-{"privateKeyUsagePeriod","X509v3 Private Key Usage Period",
-	NID_private_key_usage_period,3,&(lvalues[496]),0},
-{"subjectAltName","X509v3 Subject Alternative Name",
-	NID_subject_alt_name,3,&(lvalues[499]),0},
-{"issuerAltName","X509v3 Issuer Alternative Name",NID_issuer_alt_name,
-	3,&(lvalues[502]),0},
-{"basicConstraints","X509v3 Basic Constraints",NID_basic_constraints,
-	3,&(lvalues[505]),0},
-{"crlNumber","X509v3 CRL Number",NID_crl_number,3,&(lvalues[508]),0},
-{"certificatePolicies","X509v3 Certificate Policies",
-	NID_certificate_policies,3,&(lvalues[511]),0},
-{"authorityKeyIdentifier","X509v3 Authority Key Identifier",
-	NID_authority_key_identifier,3,&(lvalues[514]),0},
-{"BF-CBC","bf-cbc",NID_bf_cbc,9,&(lvalues[517]),0},
-{"BF-ECB","bf-ecb",NID_bf_ecb,0,NULL,0},
-{"BF-CFB","bf-cfb",NID_bf_cfb64,0,NULL,0},
-{"BF-OFB","bf-ofb",NID_bf_ofb64,0,NULL,0},
-{"MDC2","mdc2",NID_mdc2,4,&(lvalues[526]),0},
-{"RSA-MDC2","mdc2WithRSA",NID_mdc2WithRSA,4,&(lvalues[530]),0},
-{"RC4-40","rc4-40",NID_rc4_40,0,NULL,0},
-{"RC2-40-CBC","rc2-40-cbc",NID_rc2_40_cbc,0,NULL,0},
-{"GN","givenName",NID_givenName,3,&(lvalues[534]),0},
-{"SN","surname",NID_surname,3,&(lvalues[537]),0},
-{"initials","initials",NID_initials,3,&(lvalues[540]),0},
-{NULL,NULL,NID_undef,0,NULL,0},
-{"crlDistributionPoints","X509v3 CRL Distribution Points",
-	NID_crl_distribution_points,3,&(lvalues[543]),0},
-{"RSA-NP-MD5","md5WithRSA",NID_md5WithRSA,5,&(lvalues[546]),0},
-{"serialNumber","serialNumber",NID_serialNumber,3,&(lvalues[551]),0},
-{"title","title",NID_title,3,&(lvalues[554]),0},
-{"description","description",NID_description,3,&(lvalues[557]),0},
-{"CAST5-CBC","cast5-cbc",NID_cast5_cbc,9,&(lvalues[560]),0},
-{"CAST5-ECB","cast5-ecb",NID_cast5_ecb,0,NULL,0},
-{"CAST5-CFB","cast5-cfb",NID_cast5_cfb64,0,NULL,0},
-{"CAST5-OFB","cast5-ofb",NID_cast5_ofb64,0,NULL,0},
-{"pbeWithMD5AndCast5CBC","pbeWithMD5AndCast5CBC",
-	NID_pbeWithMD5AndCast5_CBC,9,&(lvalues[569]),0},
-{"DSA-SHA1","dsaWithSHA1",NID_dsaWithSHA1,7,&(lvalues[578]),0},
-{"MD5-SHA1","md5-sha1",NID_md5_sha1,0,NULL,0},
-{"RSA-SHA1-2","sha1WithRSA",NID_sha1WithRSA,5,&(lvalues[585]),0},
-{"DSA","dsaEncryption",NID_dsa,7,&(lvalues[590]),0},
-{"RIPEMD160","ripemd160",NID_ripemd160,5,&(lvalues[597]),0},
-{NULL,NULL,NID_undef,0,NULL,0},
-{"RSA-RIPEMD160","ripemd160WithRSA",NID_ripemd160WithRSA,6,
-	&(lvalues[602]),0},
-{"RC5-CBC","rc5-cbc",NID_rc5_cbc,8,&(lvalues[608]),0},
-{"RC5-ECB","rc5-ecb",NID_rc5_ecb,0,NULL,0},
-{"RC5-CFB","rc5-cfb",NID_rc5_cfb64,0,NULL,0},
-{"RC5-OFB","rc5-ofb",NID_rc5_ofb64,0,NULL,0},
-{NULL,NULL,NID_undef,0,NULL,0},
-{"ZLIB","zlib compression",NID_zlib_compression,11,&(lvalues[616]),0},
-{"extendedKeyUsage","X509v3 Extended Key Usage",NID_ext_key_usage,3,
-	&(lvalues[627]),0},
-{"PKIX","PKIX",NID_id_pkix,6,&(lvalues[630]),0},
-{"id-kp","id-kp",NID_id_kp,7,&(lvalues[636]),0},
-{"serverAuth","TLS Web Server Authentication",NID_server_auth,8,
-	&(lvalues[643]),0},
-{"clientAuth","TLS Web Client Authentication",NID_client_auth,8,
-	&(lvalues[651]),0},
-{"codeSigning","Code Signing",NID_code_sign,8,&(lvalues[659]),0},
-{"emailProtection","E-mail Protection",NID_email_protect,8,
-	&(lvalues[667]),0},
-{"timeStamping","Time Stamping",NID_time_stamp,8,&(lvalues[675]),0},
-{"msCodeInd","Microsoft Individual Code Signing",NID_ms_code_ind,10,
-	&(lvalues[683]),0},
-{"msCodeCom","Microsoft Commercial Code Signing",NID_ms_code_com,10,
-	&(lvalues[693]),0},
-{"msCTLSign","Microsoft Trust List Signing",NID_ms_ctl_sign,10,
-	&(lvalues[703]),0},
-{"msSGC","Microsoft Server Gated Crypto",NID_ms_sgc,10,&(lvalues[713]),0},
-{"msEFS","Microsoft Encrypted File System",NID_ms_efs,10,
-	&(lvalues[723]),0},
-{"nsSGC","Netscape Server Gated Crypto",NID_ns_sgc,9,&(lvalues[733]),0},
-{"deltaCRL","X509v3 Delta CRL Indicator",NID_delta_crl,3,
-	&(lvalues[742]),0},
-{"CRLReason","X509v3 CRL Reason Code",NID_crl_reason,3,&(lvalues[745]),0},
-{"invalidityDate","Invalidity Date",NID_invalidity_date,3,
-	&(lvalues[748]),0},
-{"SXNetID","Strong Extranet ID",NID_sxnet,5,&(lvalues[751]),0},
-{"PBE-SHA1-RC4-128","pbeWithSHA1And128BitRC4",
-	NID_pbe_WithSHA1And128BitRC4,10,&(lvalues[756]),0},
-{"PBE-SHA1-RC4-40","pbeWithSHA1And40BitRC4",
-	NID_pbe_WithSHA1And40BitRC4,10,&(lvalues[766]),0},
-{"PBE-SHA1-3DES","pbeWithSHA1And3-KeyTripleDES-CBC",
-	NID_pbe_WithSHA1And3_Key_TripleDES_CBC,10,&(lvalues[776]),0},
-{"PBE-SHA1-2DES","pbeWithSHA1And2-KeyTripleDES-CBC",
-	NID_pbe_WithSHA1And2_Key_TripleDES_CBC,10,&(lvalues[786]),0},
-{"PBE-SHA1-RC2-128","pbeWithSHA1And128BitRC2-CBC",
-	NID_pbe_WithSHA1And128BitRC2_CBC,10,&(lvalues[796]),0},
-{"PBE-SHA1-RC2-40","pbeWithSHA1And40BitRC2-CBC",
-	NID_pbe_WithSHA1And40BitRC2_CBC,10,&(lvalues[806]),0},
-{"keyBag","keyBag",NID_keyBag,11,&(lvalues[816]),0},
-{"pkcs8ShroudedKeyBag","pkcs8ShroudedKeyBag",NID_pkcs8ShroudedKeyBag,
-	11,&(lvalues[827]),0},
-{"certBag","certBag",NID_certBag,11,&(lvalues[838]),0},
-{"crlBag","crlBag",NID_crlBag,11,&(lvalues[849]),0},
-{"secretBag","secretBag",NID_secretBag,11,&(lvalues[860]),0},
-{"safeContentsBag","safeContentsBag",NID_safeContentsBag,11,
-	&(lvalues[871]),0},
-{"friendlyName","friendlyName",NID_friendlyName,9,&(lvalues[882]),0},
-{"localKeyID","localKeyID",NID_localKeyID,9,&(lvalues[891]),0},
-{"x509Certificate","x509Certificate",NID_x509Certificate,10,
-	&(lvalues[900]),0},
-{"sdsiCertificate","sdsiCertificate",NID_sdsiCertificate,10,
-	&(lvalues[910]),0},
-{"x509Crl","x509Crl",NID_x509Crl,10,&(lvalues[920]),0},
-{"PBES2","PBES2",NID_pbes2,9,&(lvalues[930]),0},
-{"PBMAC1","PBMAC1",NID_pbmac1,9,&(lvalues[939]),0},
-{"hmacWithSHA1","hmacWithSHA1",NID_hmacWithSHA1,8,&(lvalues[948]),0},
-{"id-qt-cps","Policy Qualifier CPS",NID_id_qt_cps,8,&(lvalues[956]),0},
-{"id-qt-unotice","Policy Qualifier User Notice",NID_id_qt_unotice,8,
-	&(lvalues[964]),0},
-{"RC2-64-CBC","rc2-64-cbc",NID_rc2_64_cbc,0,NULL,0},
-{"SMIME-CAPS","S/MIME Capabilities",NID_SMIMECapabilities,9,
-	&(lvalues[972]),0},
-{"PBE-MD2-RC2-64","pbeWithMD2AndRC2-CBC",NID_pbeWithMD2AndRC2_CBC,9,
-	&(lvalues[981]),0},
-{"PBE-MD5-RC2-64","pbeWithMD5AndRC2-CBC",NID_pbeWithMD5AndRC2_CBC,9,
-	&(lvalues[990]),0},
-{"PBE-SHA1-DES","pbeWithSHA1AndDES-CBC",NID_pbeWithSHA1AndDES_CBC,9,
-	&(lvalues[999]),0},
-{"msExtReq","Microsoft Extension Request",NID_ms_ext_req,10,
-	&(lvalues[1008]),0},
-{"extReq","Extension Request",NID_ext_req,9,&(lvalues[1018]),0},
-{"name","name",NID_name,3,&(lvalues[1027]),0},
-{"dnQualifier","dnQualifier",NID_dnQualifier,3,&(lvalues[1030]),0},
-{"id-pe","id-pe",NID_id_pe,7,&(lvalues[1033]),0},
-{"id-ad","id-ad",NID_id_ad,7,&(lvalues[1040]),0},
-{"authorityInfoAccess","Authority Information Access",NID_info_access,
-	8,&(lvalues[1047]),0},
-{"OCSP","OCSP",NID_ad_OCSP,8,&(lvalues[1055]),0},
-{"caIssuers","CA Issuers",NID_ad_ca_issuers,8,&(lvalues[1063]),0},
-{"OCSPSigning","OCSP Signing",NID_OCSP_sign,8,&(lvalues[1071]),0},
-{"ISO","iso",NID_iso,0,NULL,0},
-{"member-body","ISO Member Body",NID_member_body,1,&(lvalues[1079]),0},
-{"ISO-US","ISO US Member Body",NID_ISO_US,3,&(lvalues[1080]),0},
-{"X9-57","X9.57",NID_X9_57,5,&(lvalues[1083]),0},
-{"X9cm","X9.57 CM ?",NID_X9cm,6,&(lvalues[1088]),0},
-{"pkcs1","pkcs1",NID_pkcs1,8,&(lvalues[1094]),0},
-{"pkcs5","pkcs5",NID_pkcs5,8,&(lvalues[1102]),0},
-{"SMIME","S/MIME",NID_SMIME,9,&(lvalues[1110]),0},
-{"id-smime-mod","id-smime-mod",NID_id_smime_mod,10,&(lvalues[1119]),0},
-{"id-smime-ct","id-smime-ct",NID_id_smime_ct,10,&(lvalues[1129]),0},
-{"id-smime-aa","id-smime-aa",NID_id_smime_aa,10,&(lvalues[1139]),0},
-{"id-smime-alg","id-smime-alg",NID_id_smime_alg,10,&(lvalues[1149]),0},
-{"id-smime-cd","id-smime-cd",NID_id_smime_cd,10,&(lvalues[1159]),0},
-{"id-smime-spq","id-smime-spq",NID_id_smime_spq,10,&(lvalues[1169]),0},
-{"id-smime-cti","id-smime-cti",NID_id_smime_cti,10,&(lvalues[1179]),0},
-{"id-smime-mod-cms","id-smime-mod-cms",NID_id_smime_mod_cms,11,
-	&(lvalues[1189]),0},
-{"id-smime-mod-ess","id-smime-mod-ess",NID_id_smime_mod_ess,11,
-	&(lvalues[1200]),0},
-{"id-smime-mod-oid","id-smime-mod-oid",NID_id_smime_mod_oid,11,
-	&(lvalues[1211]),0},
-{"id-smime-mod-msg-v3","id-smime-mod-msg-v3",NID_id_smime_mod_msg_v3,
-	11,&(lvalues[1222]),0},
-{"id-smime-mod-ets-eSignature-88","id-smime-mod-ets-eSignature-88",
-	NID_id_smime_mod_ets_eSignature_88,11,&(lvalues[1233]),0},
-{"id-smime-mod-ets-eSignature-97","id-smime-mod-ets-eSignature-97",
-	NID_id_smime_mod_ets_eSignature_97,11,&(lvalues[1244]),0},
-{"id-smime-mod-ets-eSigPolicy-88","id-smime-mod-ets-eSigPolicy-88",
-	NID_id_smime_mod_ets_eSigPolicy_88,11,&(lvalues[1255]),0},
-{"id-smime-mod-ets-eSigPolicy-97","id-smime-mod-ets-eSigPolicy-97",
-	NID_id_smime_mod_ets_eSigPolicy_97,11,&(lvalues[1266]),0},
-{"id-smime-ct-receipt","id-smime-ct-receipt",NID_id_smime_ct_receipt,
-	11,&(lvalues[1277]),0},
-{"id-smime-ct-authData","id-smime-ct-authData",
-	NID_id_smime_ct_authData,11,&(lvalues[1288]),0},
-{"id-smime-ct-publishCert","id-smime-ct-publishCert",
-	NID_id_smime_ct_publishCert,11,&(lvalues[1299]),0},
-{"id-smime-ct-TSTInfo","id-smime-ct-TSTInfo",NID_id_smime_ct_TSTInfo,
-	11,&(lvalues[1310]),0},
-{"id-smime-ct-TDTInfo","id-smime-ct-TDTInfo",NID_id_smime_ct_TDTInfo,
-	11,&(lvalues[1321]),0},
-{"id-smime-ct-contentInfo","id-smime-ct-contentInfo",
-	NID_id_smime_ct_contentInfo,11,&(lvalues[1332]),0},
-{"id-smime-ct-DVCSRequestData","id-smime-ct-DVCSRequestData",
-	NID_id_smime_ct_DVCSRequestData,11,&(lvalues[1343]),0},
-{"id-smime-ct-DVCSResponseData","id-smime-ct-DVCSResponseData",
-	NID_id_smime_ct_DVCSResponseData,11,&(lvalues[1354]),0},
-{"id-smime-aa-receiptRequest","id-smime-aa-receiptRequest",
-	NID_id_smime_aa_receiptRequest,11,&(lvalues[1365]),0},
-{"id-smime-aa-securityLabel","id-smime-aa-securityLabel",
-	NID_id_smime_aa_securityLabel,11,&(lvalues[1376]),0},
-{"id-smime-aa-mlExpandHistory","id-smime-aa-mlExpandHistory",
-	NID_id_smime_aa_mlExpandHistory,11,&(lvalues[1387]),0},
-{"id-smime-aa-contentHint","id-smime-aa-contentHint",
-	NID_id_smime_aa_contentHint,11,&(lvalues[1398]),0},
-{"id-smime-aa-msgSigDigest","id-smime-aa-msgSigDigest",
-	NID_id_smime_aa_msgSigDigest,11,&(lvalues[1409]),0},
-{"id-smime-aa-encapContentType","id-smime-aa-encapContentType",
-	NID_id_smime_aa_encapContentType,11,&(lvalues[1420]),0},
-{"id-smime-aa-contentIdentifier","id-smime-aa-contentIdentifier",
-	NID_id_smime_aa_contentIdentifier,11,&(lvalues[1431]),0},
-{"id-smime-aa-macValue","id-smime-aa-macValue",
-	NID_id_smime_aa_macValue,11,&(lvalues[1442]),0},
-{"id-smime-aa-equivalentLabels","id-smime-aa-equivalentLabels",
-	NID_id_smime_aa_equivalentLabels,11,&(lvalues[1453]),0},
-{"id-smime-aa-contentReference","id-smime-aa-contentReference",
-	NID_id_smime_aa_contentReference,11,&(lvalues[1464]),0},
-{"id-smime-aa-encrypKeyPref","id-smime-aa-encrypKeyPref",
-	NID_id_smime_aa_encrypKeyPref,11,&(lvalues[1475]),0},
-{"id-smime-aa-signingCertificate","id-smime-aa-signingCertificate",
-	NID_id_smime_aa_signingCertificate,11,&(lvalues[1486]),0},
-{"id-smime-aa-smimeEncryptCerts","id-smime-aa-smimeEncryptCerts",
-	NID_id_smime_aa_smimeEncryptCerts,11,&(lvalues[1497]),0},
-{"id-smime-aa-timeStampToken","id-smime-aa-timeStampToken",
-	NID_id_smime_aa_timeStampToken,11,&(lvalues[1508]),0},
-{"id-smime-aa-ets-sigPolicyId","id-smime-aa-ets-sigPolicyId",
-	NID_id_smime_aa_ets_sigPolicyId,11,&(lvalues[1519]),0},
-{"id-smime-aa-ets-commitmentType","id-smime-aa-ets-commitmentType",
-	NID_id_smime_aa_ets_commitmentType,11,&(lvalues[1530]),0},
-{"id-smime-aa-ets-signerLocation","id-smime-aa-ets-signerLocation",
-	NID_id_smime_aa_ets_signerLocation,11,&(lvalues[1541]),0},
-{"id-smime-aa-ets-signerAttr","id-smime-aa-ets-signerAttr",
-	NID_id_smime_aa_ets_signerAttr,11,&(lvalues[1552]),0},
-{"id-smime-aa-ets-otherSigCert","id-smime-aa-ets-otherSigCert",
-	NID_id_smime_aa_ets_otherSigCert,11,&(lvalues[1563]),0},
-{"id-smime-aa-ets-contentTimestamp",
-	"id-smime-aa-ets-contentTimestamp",
-	NID_id_smime_aa_ets_contentTimestamp,11,&(lvalues[1574]),0},
-{"id-smime-aa-ets-CertificateRefs","id-smime-aa-ets-CertificateRefs",
-	NID_id_smime_aa_ets_CertificateRefs,11,&(lvalues[1585]),0},
-{"id-smime-aa-ets-RevocationRefs","id-smime-aa-ets-RevocationRefs",
-	NID_id_smime_aa_ets_RevocationRefs,11,&(lvalues[1596]),0},
-{"id-smime-aa-ets-certValues","id-smime-aa-ets-certValues",
-	NID_id_smime_aa_ets_certValues,11,&(lvalues[1607]),0},
-{"id-smime-aa-ets-revocationValues",
-	"id-smime-aa-ets-revocationValues",
-	NID_id_smime_aa_ets_revocationValues,11,&(lvalues[1618]),0},
-{"id-smime-aa-ets-escTimeStamp","id-smime-aa-ets-escTimeStamp",
-	NID_id_smime_aa_ets_escTimeStamp,11,&(lvalues[1629]),0},
-{"id-smime-aa-ets-certCRLTimestamp",
-	"id-smime-aa-ets-certCRLTimestamp",
-	NID_id_smime_aa_ets_certCRLTimestamp,11,&(lvalues[1640]),0},
-{"id-smime-aa-ets-archiveTimeStamp",
-	"id-smime-aa-ets-archiveTimeStamp",
-	NID_id_smime_aa_ets_archiveTimeStamp,11,&(lvalues[1651]),0},
-{"id-smime-aa-signatureType","id-smime-aa-signatureType",
-	NID_id_smime_aa_signatureType,11,&(lvalues[1662]),0},
-{"id-smime-aa-dvcs-dvc","id-smime-aa-dvcs-dvc",
-	NID_id_smime_aa_dvcs_dvc,11,&(lvalues[1673]),0},
-{"id-smime-alg-ESDHwith3DES","id-smime-alg-ESDHwith3DES",
-	NID_id_smime_alg_ESDHwith3DES,11,&(lvalues[1684]),0},
-{"id-smime-alg-ESDHwithRC2","id-smime-alg-ESDHwithRC2",
-	NID_id_smime_alg_ESDHwithRC2,11,&(lvalues[1695]),0},
-{"id-smime-alg-3DESwrap","id-smime-alg-3DESwrap",
-	NID_id_smime_alg_3DESwrap,11,&(lvalues[1706]),0},
-{"id-smime-alg-RC2wrap","id-smime-alg-RC2wrap",
-	NID_id_smime_alg_RC2wrap,11,&(lvalues[1717]),0},
-{"id-smime-alg-ESDH","id-smime-alg-ESDH",NID_id_smime_alg_ESDH,11,
-	&(lvalues[1728]),0},
-{"id-smime-alg-CMS3DESwrap","id-smime-alg-CMS3DESwrap",
-	NID_id_smime_alg_CMS3DESwrap,11,&(lvalues[1739]),0},
-{"id-smime-alg-CMSRC2wrap","id-smime-alg-CMSRC2wrap",
-	NID_id_smime_alg_CMSRC2wrap,11,&(lvalues[1750]),0},
-{"id-smime-cd-ldap","id-smime-cd-ldap",NID_id_smime_cd_ldap,11,
-	&(lvalues[1761]),0},
-{"id-smime-spq-ets-sqt-uri","id-smime-spq-ets-sqt-uri",
-	NID_id_smime_spq_ets_sqt_uri,11,&(lvalues[1772]),0},
-{"id-smime-spq-ets-sqt-unotice","id-smime-spq-ets-sqt-unotice",
-	NID_id_smime_spq_ets_sqt_unotice,11,&(lvalues[1783]),0},
-{"id-smime-cti-ets-proofOfOrigin","id-smime-cti-ets-proofOfOrigin",
-	NID_id_smime_cti_ets_proofOfOrigin,11,&(lvalues[1794]),0},
-{"id-smime-cti-ets-proofOfReceipt","id-smime-cti-ets-proofOfReceipt",
-	NID_id_smime_cti_ets_proofOfReceipt,11,&(lvalues[1805]),0},
-{"id-smime-cti-ets-proofOfDelivery",
-	"id-smime-cti-ets-proofOfDelivery",
-	NID_id_smime_cti_ets_proofOfDelivery,11,&(lvalues[1816]),0},
-{"id-smime-cti-ets-proofOfSender","id-smime-cti-ets-proofOfSender",
-	NID_id_smime_cti_ets_proofOfSender,11,&(lvalues[1827]),0},
-{"id-smime-cti-ets-proofOfApproval",
-	"id-smime-cti-ets-proofOfApproval",
-	NID_id_smime_cti_ets_proofOfApproval,11,&(lvalues[1838]),0},
-{"id-smime-cti-ets-proofOfCreation",
-	"id-smime-cti-ets-proofOfCreation",
-	NID_id_smime_cti_ets_proofOfCreation,11,&(lvalues[1849]),0},
-{"MD4","md4",NID_md4,8,&(lvalues[1860]),0},
-{"id-pkix-mod","id-pkix-mod",NID_id_pkix_mod,7,&(lvalues[1868]),0},
-{"id-qt","id-qt",NID_id_qt,7,&(lvalues[1875]),0},
-{"id-it","id-it",NID_id_it,7,&(lvalues[1882]),0},
-{"id-pkip","id-pkip",NID_id_pkip,7,&(lvalues[1889]),0},
-{"id-alg","id-alg",NID_id_alg,7,&(lvalues[1896]),0},
-{"id-cmc","id-cmc",NID_id_cmc,7,&(lvalues[1903]),0},
-{"id-on","id-on",NID_id_on,7,&(lvalues[1910]),0},
-{"id-pda","id-pda",NID_id_pda,7,&(lvalues[1917]),0},
-{"id-aca","id-aca",NID_id_aca,7,&(lvalues[1924]),0},
-{"id-qcs","id-qcs",NID_id_qcs,7,&(lvalues[1931]),0},
-{"id-cct","id-cct",NID_id_cct,7,&(lvalues[1938]),0},
-{"id-pkix1-explicit-88","id-pkix1-explicit-88",
-	NID_id_pkix1_explicit_88,8,&(lvalues[1945]),0},
-{"id-pkix1-implicit-88","id-pkix1-implicit-88",
-	NID_id_pkix1_implicit_88,8,&(lvalues[1953]),0},
-{"id-pkix1-explicit-93","id-pkix1-explicit-93",
-	NID_id_pkix1_explicit_93,8,&(lvalues[1961]),0},
-{"id-pkix1-implicit-93","id-pkix1-implicit-93",
-	NID_id_pkix1_implicit_93,8,&(lvalues[1969]),0},
-{"id-mod-crmf","id-mod-crmf",NID_id_mod_crmf,8,&(lvalues[1977]),0},
-{"id-mod-cmc","id-mod-cmc",NID_id_mod_cmc,8,&(lvalues[1985]),0},
-{"id-mod-kea-profile-88","id-mod-kea-profile-88",
-	NID_id_mod_kea_profile_88,8,&(lvalues[1993]),0},
-{"id-mod-kea-profile-93","id-mod-kea-profile-93",
-	NID_id_mod_kea_profile_93,8,&(lvalues[2001]),0},
-{"id-mod-cmp","id-mod-cmp",NID_id_mod_cmp,8,&(lvalues[2009]),0},
-{"id-mod-qualified-cert-88","id-mod-qualified-cert-88",
-	NID_id_mod_qualified_cert_88,8,&(lvalues[2017]),0},
-{"id-mod-qualified-cert-93","id-mod-qualified-cert-93",
-	NID_id_mod_qualified_cert_93,8,&(lvalues[2025]),0},
-{"id-mod-attribute-cert","id-mod-attribute-cert",
-	NID_id_mod_attribute_cert,8,&(lvalues[2033]),0},
-{"id-mod-timestamp-protocol","id-mod-timestamp-protocol",
-	NID_id_mod_timestamp_protocol,8,&(lvalues[2041]),0},
-{"id-mod-ocsp","id-mod-ocsp",NID_id_mod_ocsp,8,&(lvalues[2049]),0},
-{"id-mod-dvcs","id-mod-dvcs",NID_id_mod_dvcs,8,&(lvalues[2057]),0},
-{"id-mod-cmp2000","id-mod-cmp2000",NID_id_mod_cmp2000,8,
-	&(lvalues[2065]),0},
-{"biometricInfo","Biometric Info",NID_biometricInfo,8,&(lvalues[2073]),0},
-{"qcStatements","qcStatements",NID_qcStatements,8,&(lvalues[2081]),0},
-{"ac-auditEntity","ac-auditEntity",NID_ac_auditEntity,8,
-	&(lvalues[2089]),0},
-{"ac-targeting","ac-targeting",NID_ac_targeting,8,&(lvalues[2097]),0},
-{"aaControls","aaControls",NID_aaControls,8,&(lvalues[2105]),0},
-{"sbgp-ipAddrBlock","sbgp-ipAddrBlock",NID_sbgp_ipAddrBlock,8,
-	&(lvalues[2113]),0},
-{"sbgp-autonomousSysNum","sbgp-autonomousSysNum",
-	NID_sbgp_autonomousSysNum,8,&(lvalues[2121]),0},
-{"sbgp-routerIdentifier","sbgp-routerIdentifier",
-	NID_sbgp_routerIdentifier,8,&(lvalues[2129]),0},
-{"textNotice","textNotice",NID_textNotice,8,&(lvalues[2137]),0},
-{"ipsecEndSystem","IPSec End System",NID_ipsecEndSystem,8,
-	&(lvalues[2145]),0},
-{"ipsecTunnel","IPSec Tunnel",NID_ipsecTunnel,8,&(lvalues[2153]),0},
-{"ipsecUser","IPSec User",NID_ipsecUser,8,&(lvalues[2161]),0},
-{"DVCS","dvcs",NID_dvcs,8,&(lvalues[2169]),0},
-{"id-it-caProtEncCert","id-it-caProtEncCert",NID_id_it_caProtEncCert,
-	8,&(lvalues[2177]),0},
-{"id-it-signKeyPairTypes","id-it-signKeyPairTypes",
-	NID_id_it_signKeyPairTypes,8,&(lvalues[2185]),0},
-{"id-it-encKeyPairTypes","id-it-encKeyPairTypes",
-	NID_id_it_encKeyPairTypes,8,&(lvalues[2193]),0},
-{"id-it-preferredSymmAlg","id-it-preferredSymmAlg",
-	NID_id_it_preferredSymmAlg,8,&(lvalues[2201]),0},
-{"id-it-caKeyUpdateInfo","id-it-caKeyUpdateInfo",
-	NID_id_it_caKeyUpdateInfo,8,&(lvalues[2209]),0},
-{"id-it-currentCRL","id-it-currentCRL",NID_id_it_currentCRL,8,
-	&(lvalues[2217]),0},
-{"id-it-unsupportedOIDs","id-it-unsupportedOIDs",
-	NID_id_it_unsupportedOIDs,8,&(lvalues[2225]),0},
-{"id-it-subscriptionRequest","id-it-subscriptionRequest",
-	NID_id_it_subscriptionRequest,8,&(lvalues[2233]),0},
-{"id-it-subscriptionResponse","id-it-subscriptionResponse",
-	NID_id_it_subscriptionResponse,8,&(lvalues[2241]),0},
-{"id-it-keyPairParamReq","id-it-keyPairParamReq",
-	NID_id_it_keyPairParamReq,8,&(lvalues[2249]),0},
-{"id-it-keyPairParamRep","id-it-keyPairParamRep",
-	NID_id_it_keyPairParamRep,8,&(lvalues[2257]),0},
-{"id-it-revPassphrase","id-it-revPassphrase",NID_id_it_revPassphrase,
-	8,&(lvalues[2265]),0},
-{"id-it-implicitConfirm","id-it-implicitConfirm",
-	NID_id_it_implicitConfirm,8,&(lvalues[2273]),0},
-{"id-it-confirmWaitTime","id-it-confirmWaitTime",
-	NID_id_it_confirmWaitTime,8,&(lvalues[2281]),0},
-{"id-it-origPKIMessage","id-it-origPKIMessage",
-	NID_id_it_origPKIMessage,8,&(lvalues[2289]),0},
-{"id-regCtrl","id-regCtrl",NID_id_regCtrl,8,&(lvalues[2297]),0},
-{"id-regInfo","id-regInfo",NID_id_regInfo,8,&(lvalues[2305]),0},
-{"id-regCtrl-regToken","id-regCtrl-regToken",NID_id_regCtrl_regToken,
-	9,&(lvalues[2313]),0},
-{"id-regCtrl-authenticator","id-regCtrl-authenticator",
-	NID_id_regCtrl_authenticator,9,&(lvalues[2322]),0},
-{"id-regCtrl-pkiPublicationInfo","id-regCtrl-pkiPublicationInfo",
-	NID_id_regCtrl_pkiPublicationInfo,9,&(lvalues[2331]),0},
-{"id-regCtrl-pkiArchiveOptions","id-regCtrl-pkiArchiveOptions",
-	NID_id_regCtrl_pkiArchiveOptions,9,&(lvalues[2340]),0},
-{"id-regCtrl-oldCertID","id-regCtrl-oldCertID",
-	NID_id_regCtrl_oldCertID,9,&(lvalues[2349]),0},
-{"id-regCtrl-protocolEncrKey","id-regCtrl-protocolEncrKey",
-	NID_id_regCtrl_protocolEncrKey,9,&(lvalues[2358]),0},
-{"id-regInfo-utf8Pairs","id-regInfo-utf8Pairs",
-	NID_id_regInfo_utf8Pairs,9,&(lvalues[2367]),0},
-{"id-regInfo-certReq","id-regInfo-certReq",NID_id_regInfo_certReq,9,
-	&(lvalues[2376]),0},
-{"id-alg-des40","id-alg-des40",NID_id_alg_des40,8,&(lvalues[2385]),0},
-{"id-alg-noSignature","id-alg-noSignature",NID_id_alg_noSignature,8,
-	&(lvalues[2393]),0},
-{"id-alg-dh-sig-hmac-sha1","id-alg-dh-sig-hmac-sha1",
-	NID_id_alg_dh_sig_hmac_sha1,8,&(lvalues[2401]),0},
-{"id-alg-dh-pop","id-alg-dh-pop",NID_id_alg_dh_pop,8,&(lvalues[2409]),0},
-{"id-cmc-statusInfo","id-cmc-statusInfo",NID_id_cmc_statusInfo,8,
-	&(lvalues[2417]),0},
-{"id-cmc-identification","id-cmc-identification",
-	NID_id_cmc_identification,8,&(lvalues[2425]),0},
-{"id-cmc-identityProof","id-cmc-identityProof",
-	NID_id_cmc_identityProof,8,&(lvalues[2433]),0},
-{"id-cmc-dataReturn","id-cmc-dataReturn",NID_id_cmc_dataReturn,8,
-	&(lvalues[2441]),0},
-{"id-cmc-transactionId","id-cmc-transactionId",
-	NID_id_cmc_transactionId,8,&(lvalues[2449]),0},
-{"id-cmc-senderNonce","id-cmc-senderNonce",NID_id_cmc_senderNonce,8,
-	&(lvalues[2457]),0},
-{"id-cmc-recipientNonce","id-cmc-recipientNonce",
-	NID_id_cmc_recipientNonce,8,&(lvalues[2465]),0},
-{"id-cmc-addExtensions","id-cmc-addExtensions",
-	NID_id_cmc_addExtensions,8,&(lvalues[2473]),0},
-{"id-cmc-encryptedPOP","id-cmc-encryptedPOP",NID_id_cmc_encryptedPOP,
-	8,&(lvalues[2481]),0},
-{"id-cmc-decryptedPOP","id-cmc-decryptedPOP",NID_id_cmc_decryptedPOP,
-	8,&(lvalues[2489]),0},
-{"id-cmc-lraPOPWitness","id-cmc-lraPOPWitness",
-	NID_id_cmc_lraPOPWitness,8,&(lvalues[2497]),0},
-{"id-cmc-getCert","id-cmc-getCert",NID_id_cmc_getCert,8,
-	&(lvalues[2505]),0},
-{"id-cmc-getCRL","id-cmc-getCRL",NID_id_cmc_getCRL,8,&(lvalues[2513]),0},
-{"id-cmc-revokeRequest","id-cmc-revokeRequest",
-	NID_id_cmc_revokeRequest,8,&(lvalues[2521]),0},
-{"id-cmc-regInfo","id-cmc-regInfo",NID_id_cmc_regInfo,8,
-	&(lvalues[2529]),0},
-{"id-cmc-responseInfo","id-cmc-responseInfo",NID_id_cmc_responseInfo,
-	8,&(lvalues[2537]),0},
-{"id-cmc-queryPending","id-cmc-queryPending",NID_id_cmc_queryPending,
-	8,&(lvalues[2545]),0},
-{"id-cmc-popLinkRandom","id-cmc-popLinkRandom",
-	NID_id_cmc_popLinkRandom,8,&(lvalues[2553]),0},
-{"id-cmc-popLinkWitness","id-cmc-popLinkWitness",
-	NID_id_cmc_popLinkWitness,8,&(lvalues[2561]),0},
-{"id-cmc-confirmCertAcceptance","id-cmc-confirmCertAcceptance",
-	NID_id_cmc_confirmCertAcceptance,8,&(lvalues[2569]),0},
-{"id-on-personalData","id-on-personalData",NID_id_on_personalData,8,
-	&(lvalues[2577]),0},
-{"id-pda-dateOfBirth","id-pda-dateOfBirth",NID_id_pda_dateOfBirth,8,
-	&(lvalues[2585]),0},
-{"id-pda-placeOfBirth","id-pda-placeOfBirth",NID_id_pda_placeOfBirth,
-	8,&(lvalues[2593]),0},
-{NULL,NULL,NID_undef,0,NULL,0},
-{"id-pda-gender","id-pda-gender",NID_id_pda_gender,8,&(lvalues[2601]),0},
-{"id-pda-countryOfCitizenship","id-pda-countryOfCitizenship",
-	NID_id_pda_countryOfCitizenship,8,&(lvalues[2609]),0},
-{"id-pda-countryOfResidence","id-pda-countryOfResidence",
-	NID_id_pda_countryOfResidence,8,&(lvalues[2617]),0},
-{"id-aca-authenticationInfo","id-aca-authenticationInfo",
-	NID_id_aca_authenticationInfo,8,&(lvalues[2625]),0},
-{"id-aca-accessIdentity","id-aca-accessIdentity",
-	NID_id_aca_accessIdentity,8,&(lvalues[2633]),0},
-{"id-aca-chargingIdentity","id-aca-chargingIdentity",
-	NID_id_aca_chargingIdentity,8,&(lvalues[2641]),0},
-{"id-aca-group","id-aca-group",NID_id_aca_group,8,&(lvalues[2649]),0},
-{"id-aca-role","id-aca-role",NID_id_aca_role,8,&(lvalues[2657]),0},
-{"id-qcs-pkixQCSyntax-v1","id-qcs-pkixQCSyntax-v1",
-	NID_id_qcs_pkixQCSyntax_v1,8,&(lvalues[2665]),0},
-{"id-cct-crs","id-cct-crs",NID_id_cct_crs,8,&(lvalues[2673]),0},
-{"id-cct-PKIData","id-cct-PKIData",NID_id_cct_PKIData,8,
-	&(lvalues[2681]),0},
-{"id-cct-PKIResponse","id-cct-PKIResponse",NID_id_cct_PKIResponse,8,
-	&(lvalues[2689]),0},
-{"ad_timestamping","AD Time Stamping",NID_ad_timeStamping,8,
-	&(lvalues[2697]),0},
-{"AD_DVCS","ad dvcs",NID_ad_dvcs,8,&(lvalues[2705]),0},
-{"basicOCSPResponse","Basic OCSP Response",NID_id_pkix_OCSP_basic,9,
-	&(lvalues[2713]),0},
-{"Nonce","OCSP Nonce",NID_id_pkix_OCSP_Nonce,9,&(lvalues[2722]),0},
-{"CrlID","OCSP CRL ID",NID_id_pkix_OCSP_CrlID,9,&(lvalues[2731]),0},
-{"acceptableResponses","Acceptable OCSP Responses",
-	NID_id_pkix_OCSP_acceptableResponses,9,&(lvalues[2740]),0},
-{"noCheck","OCSP No Check",NID_id_pkix_OCSP_noCheck,9,&(lvalues[2749]),0},
-{"archiveCutoff","OCSP Archive Cutoff",NID_id_pkix_OCSP_archiveCutoff,
-	9,&(lvalues[2758]),0},
-{"serviceLocator","OCSP Service Locator",
-	NID_id_pkix_OCSP_serviceLocator,9,&(lvalues[2767]),0},
-{"extendedStatus","Extended OCSP Status",
-	NID_id_pkix_OCSP_extendedStatus,9,&(lvalues[2776]),0},
-{"valid","valid",NID_id_pkix_OCSP_valid,9,&(lvalues[2785]),0},
-{"path","path",NID_id_pkix_OCSP_path,9,&(lvalues[2794]),0},
-{"trustRoot","Trust Root",NID_id_pkix_OCSP_trustRoot,9,
-	&(lvalues[2803]),0},
-{"algorithm","algorithm",NID_algorithm,4,&(lvalues[2812]),0},
-{"rsaSignature","rsaSignature",NID_rsaSignature,5,&(lvalues[2816]),0},
-{"X500algorithms","directory services - algorithms",
-	NID_X500algorithms,2,&(lvalues[2821]),0},
-{"ORG","org",NID_org,1,&(lvalues[2823]),0},
-{"DOD","dod",NID_dod,2,&(lvalues[2824]),0},
-{"IANA","iana",NID_iana,3,&(lvalues[2826]),0},
-{"directory","Directory",NID_Directory,4,&(lvalues[2829]),0},
-{"mgmt","Management",NID_Management,4,&(lvalues[2833]),0},
-{"experimental","Experimental",NID_Experimental,4,&(lvalues[2837]),0},
-{"private","Private",NID_Private,4,&(lvalues[2841]),0},
-{"security","Security",NID_Security,4,&(lvalues[2845]),0},
-{"snmpv2","SNMPv2",NID_SNMPv2,4,&(lvalues[2849]),0},
-{"Mail","Mail",NID_Mail,4,&(lvalues[2853]),0},
-{"enterprises","Enterprises",NID_Enterprises,5,&(lvalues[2857]),0},
-{"dcobject","dcObject",NID_dcObject,9,&(lvalues[2862]),0},
-{"DC","domainComponent",NID_domainComponent,10,&(lvalues[2871]),0},
-{"domain","Domain",NID_Domain,10,&(lvalues[2881]),0},
-{"NULL","NULL",NID_joint_iso_ccitt,0,NULL,0},
-{"selected-attribute-types","Selected Attribute Types",
-	NID_selected_attribute_types,3,&(lvalues[2891]),0},
-{"clearance","clearance",NID_clearance,4,&(lvalues[2894]),0},
-{"RSA-MD4","md4WithRSAEncryption",NID_md4WithRSAEncryption,9,
-	&(lvalues[2898]),0},
-{"ac-proxying","ac-proxying",NID_ac_proxying,8,&(lvalues[2907]),0},
-{"subjectInfoAccess","Subject Information Access",NID_sinfo_access,8,
-	&(lvalues[2915]),0},
-{"id-aca-encAttrs","id-aca-encAttrs",NID_id_aca_encAttrs,8,
-	&(lvalues[2923]),0},
-{"role","role",NID_role,3,&(lvalues[2931]),0},
-{"policyConstraints","X509v3 Policy Constraints",
-	NID_policy_constraints,3,&(lvalues[2934]),0},
-{"targetInformation","X509v3 AC Targeting",NID_target_information,3,
-	&(lvalues[2937]),0},
-{"noRevAvail","X509v3 No Revocation Available",NID_no_rev_avail,3,
-	&(lvalues[2940]),0},
-{"NULL","NULL",NID_ccitt,0,NULL,0},
-{"ansi-X9-62","ANSI X9.62",NID_ansi_X9_62,5,&(lvalues[2943]),0},
-{"prime-field","prime-field",NID_X9_62_prime_field,7,&(lvalues[2948]),0},
-{"characteristic-two-field","characteristic-two-field",
-	NID_X9_62_characteristic_two_field,7,&(lvalues[2955]),0},
-{"id-ecPublicKey","id-ecPublicKey",NID_X9_62_id_ecPublicKey,7,
-	&(lvalues[2962]),0},
-{"prime192v1","prime192v1",NID_X9_62_prime192v1,8,&(lvalues[2969]),0},
-{"prime192v2","prime192v2",NID_X9_62_prime192v2,8,&(lvalues[2977]),0},
-{"prime192v3","prime192v3",NID_X9_62_prime192v3,8,&(lvalues[2985]),0},
-{"prime239v1","prime239v1",NID_X9_62_prime239v1,8,&(lvalues[2993]),0},
-{"prime239v2","prime239v2",NID_X9_62_prime239v2,8,&(lvalues[3001]),0},
-{"prime239v3","prime239v3",NID_X9_62_prime239v3,8,&(lvalues[3009]),0},
-{"prime256v1","prime256v1",NID_X9_62_prime256v1,8,&(lvalues[3017]),0},
-{"ecdsa-with-SHA1","ecdsa-with-SHA1",NID_ecdsa_with_SHA1,7,
-	&(lvalues[3025]),0},
-{"CSPName","Microsoft CSP Name",NID_ms_csp_name,9,&(lvalues[3032]),0},
-{"AES-128-ECB","aes-128-ecb",NID_aes_128_ecb,9,&(lvalues[3041]),0},
-{"AES-128-CBC","aes-128-cbc",NID_aes_128_cbc,9,&(lvalues[3050]),0},
-{"AES-128-OFB","aes-128-ofb",NID_aes_128_ofb128,9,&(lvalues[3059]),0},
-{"AES-128-CFB","aes-128-cfb",NID_aes_128_cfb128,9,&(lvalues[3068]),0},
-{"AES-192-ECB","aes-192-ecb",NID_aes_192_ecb,9,&(lvalues[3077]),0},
-{"AES-192-CBC","aes-192-cbc",NID_aes_192_cbc,9,&(lvalues[3086]),0},
-{"AES-192-OFB","aes-192-ofb",NID_aes_192_ofb128,9,&(lvalues[3095]),0},
-{"AES-192-CFB","aes-192-cfb",NID_aes_192_cfb128,9,&(lvalues[3104]),0},
-{"AES-256-ECB","aes-256-ecb",NID_aes_256_ecb,9,&(lvalues[3113]),0},
-{"AES-256-CBC","aes-256-cbc",NID_aes_256_cbc,9,&(lvalues[3122]),0},
-{"AES-256-OFB","aes-256-ofb",NID_aes_256_ofb128,9,&(lvalues[3131]),0},
-{"AES-256-CFB","aes-256-cfb",NID_aes_256_cfb128,9,&(lvalues[3140]),0},
-{"holdInstructionCode","Hold Instruction Code",
-	NID_hold_instruction_code,3,&(lvalues[3149]),0},
-{"holdInstructionNone","Hold Instruction None",
-	NID_hold_instruction_none,7,&(lvalues[3152]),0},
-{"holdInstructionCallIssuer","Hold Instruction Call Issuer",
-	NID_hold_instruction_call_issuer,7,&(lvalues[3159]),0},
-{"holdInstructionReject","Hold Instruction Reject",
-	NID_hold_instruction_reject,7,&(lvalues[3166]),0},
-{"data","data",NID_data,1,&(lvalues[3173]),0},
-{"pss","pss",NID_pss,3,&(lvalues[3174]),0},
-{"ucl","ucl",NID_ucl,7,&(lvalues[3177]),0},
-{"pilot","pilot",NID_pilot,8,&(lvalues[3184]),0},
-{"pilotAttributeType","pilotAttributeType",NID_pilotAttributeType,9,
-	&(lvalues[3192]),0},
-{"pilotAttributeSyntax","pilotAttributeSyntax",
-	NID_pilotAttributeSyntax,9,&(lvalues[3201]),0},
-{"pilotObjectClass","pilotObjectClass",NID_pilotObjectClass,9,
-	&(lvalues[3210]),0},
-{"pilotGroups","pilotGroups",NID_pilotGroups,9,&(lvalues[3219]),0},
-{"iA5StringSyntax","iA5StringSyntax",NID_iA5StringSyntax,10,
-	&(lvalues[3228]),0},
-{"caseIgnoreIA5StringSyntax","caseIgnoreIA5StringSyntax",
-	NID_caseIgnoreIA5StringSyntax,10,&(lvalues[3238]),0},
-{"pilotObject","pilotObject",NID_pilotObject,10,&(lvalues[3248]),0},
-{"pilotPerson","pilotPerson",NID_pilotPerson,10,&(lvalues[3258]),0},
-{"account","account",NID_account,10,&(lvalues[3268]),0},
-{"document","document",NID_document,10,&(lvalues[3278]),0},
-{"room","room",NID_room,10,&(lvalues[3288]),0},
-{"documentSeries","documentSeries",NID_documentSeries,10,
-	&(lvalues[3298]),0},
-{"rFC822localPart","rFC822localPart",NID_rFC822localPart,10,
-	&(lvalues[3308]),0},
-{"dNSDomain","dNSDomain",NID_dNSDomain,10,&(lvalues[3318]),0},
-{"domainRelatedObject","domainRelatedObject",NID_domainRelatedObject,
-	10,&(lvalues[3328]),0},
-{"friendlyCountry","friendlyCountry",NID_friendlyCountry,10,
-	&(lvalues[3338]),0},
-{"simpleSecurityObject","simpleSecurityObject",
-	NID_simpleSecurityObject,10,&(lvalues[3348]),0},
-{"pilotOrganization","pilotOrganization",NID_pilotOrganization,10,
-	&(lvalues[3358]),0},
-{"pilotDSA","pilotDSA",NID_pilotDSA,10,&(lvalues[3368]),0},
-{"qualityLabelledData","qualityLabelledData",NID_qualityLabelledData,
-	10,&(lvalues[3378]),0},
-{"UID","userId",NID_userId,10,&(lvalues[3388]),0},
-{"textEncodedORAddress","textEncodedORAddress",
-	NID_textEncodedORAddress,10,&(lvalues[3398]),0},
-{"mail","rfc822Mailbox",NID_rfc822Mailbox,10,&(lvalues[3408]),0},
-{"info","info",NID_info,10,&(lvalues[3418]),0},
-{"favouriteDrink","favouriteDrink",NID_favouriteDrink,10,
-	&(lvalues[3428]),0},
-{"roomNumber","roomNumber",NID_roomNumber,10,&(lvalues[3438]),0},
-{"photo","photo",NID_photo,10,&(lvalues[3448]),0},
-{"userClass","userClass",NID_userClass,10,&(lvalues[3458]),0},
-{"host","host",NID_host,10,&(lvalues[3468]),0},
-{"manager","manager",NID_manager,10,&(lvalues[3478]),0},
-{"documentIdentifier","documentIdentifier",NID_documentIdentifier,10,
-	&(lvalues[3488]),0},
-{"documentTitle","documentTitle",NID_documentTitle,10,&(lvalues[3498]),0},
-{"documentVersion","documentVersion",NID_documentVersion,10,
-	&(lvalues[3508]),0},
-{"documentAuthor","documentAuthor",NID_documentAuthor,10,
-	&(lvalues[3518]),0},
-{"documentLocation","documentLocation",NID_documentLocation,10,
-	&(lvalues[3528]),0},
-{"homeTelephoneNumber","homeTelephoneNumber",NID_homeTelephoneNumber,
-	10,&(lvalues[3538]),0},
-{"secretary","secretary",NID_secretary,10,&(lvalues[3548]),0},
-{"otherMailbox","otherMailbox",NID_otherMailbox,10,&(lvalues[3558]),0},
-{"lastModifiedTime","lastModifiedTime",NID_lastModifiedTime,10,
-	&(lvalues[3568]),0},
-{"lastModifiedBy","lastModifiedBy",NID_lastModifiedBy,10,
-	&(lvalues[3578]),0},
-{"aRecord","aRecord",NID_aRecord,10,&(lvalues[3588]),0},
-{"pilotAttributeType27","pilotAttributeType27",
-	NID_pilotAttributeType27,10,&(lvalues[3598]),0},
-{"mXRecord","mXRecord",NID_mXRecord,10,&(lvalues[3608]),0},
-{"nSRecord","nSRecord",NID_nSRecord,10,&(lvalues[3618]),0},
-{"sOARecord","sOARecord",NID_sOARecord,10,&(lvalues[3628]),0},
-{"cNAMERecord","cNAMERecord",NID_cNAMERecord,10,&(lvalues[3638]),0},
-{"associatedDomain","associatedDomain",NID_associatedDomain,10,
-	&(lvalues[3648]),0},
-{"associatedName","associatedName",NID_associatedName,10,
-	&(lvalues[3658]),0},
-{"homePostalAddress","homePostalAddress",NID_homePostalAddress,10,
-	&(lvalues[3668]),0},
-{"personalTitle","personalTitle",NID_personalTitle,10,&(lvalues[3678]),0},
-{"mobileTelephoneNumber","mobileTelephoneNumber",
-	NID_mobileTelephoneNumber,10,&(lvalues[3688]),0},
-{"pagerTelephoneNumber","pagerTelephoneNumber",
-	NID_pagerTelephoneNumber,10,&(lvalues[3698]),0},
-{"friendlyCountryName","friendlyCountryName",NID_friendlyCountryName,
-	10,&(lvalues[3708]),0},
-{"organizationalStatus","organizationalStatus",
-	NID_organizationalStatus,10,&(lvalues[3718]),0},
-{"janetMailbox","janetMailbox",NID_janetMailbox,10,&(lvalues[3728]),0},
-{"mailPreferenceOption","mailPreferenceOption",
-	NID_mailPreferenceOption,10,&(lvalues[3738]),0},
-{"buildingName","buildingName",NID_buildingName,10,&(lvalues[3748]),0},
-{"dSAQuality","dSAQuality",NID_dSAQuality,10,&(lvalues[3758]),0},
-{"singleLevelQuality","singleLevelQuality",NID_singleLevelQuality,10,
-	&(lvalues[3768]),0},
-{"subtreeMinimumQuality","subtreeMinimumQuality",
-	NID_subtreeMinimumQuality,10,&(lvalues[3778]),0},
-{"subtreeMaximumQuality","subtreeMaximumQuality",
-	NID_subtreeMaximumQuality,10,&(lvalues[3788]),0},
-{"personalSignature","personalSignature",NID_personalSignature,10,
-	&(lvalues[3798]),0},
-{"dITRedirect","dITRedirect",NID_dITRedirect,10,&(lvalues[3808]),0},
-{"audio","audio",NID_audio,10,&(lvalues[3818]),0},
-{"documentPublisher","documentPublisher",NID_documentPublisher,10,
-	&(lvalues[3828]),0},
-{"x500UniqueIdentifier","x500UniqueIdentifier",
-	NID_x500UniqueIdentifier,3,&(lvalues[3838]),0},
-{"mime-mhs","MIME MHS",NID_mime_mhs,5,&(lvalues[3841]),0},
-{"mime-mhs-headings","mime-mhs-headings",NID_mime_mhs_headings,6,
-	&(lvalues[3846]),0},
-{"mime-mhs-bodies","mime-mhs-bodies",NID_mime_mhs_bodies,6,
-	&(lvalues[3852]),0},
-{"id-hex-partial-message","id-hex-partial-message",
-	NID_id_hex_partial_message,7,&(lvalues[3858]),0},
-{"id-hex-multipart-message","id-hex-multipart-message",
-	NID_id_hex_multipart_message,7,&(lvalues[3865]),0},
-{"generationQualifier","generationQualifier",NID_generationQualifier,
-	3,&(lvalues[3872]),0},
-{"pseudonym","pseudonym",NID_pseudonym,3,&(lvalues[3875]),0},
-{NULL,NULL,NID_undef,0,NULL,0},
-{"id-set","Secure Electronic Transactions",NID_id_set,2,
-	&(lvalues[3878]),0},
-{"set-ctype","content types",NID_set_ctype,3,&(lvalues[3880]),0},
-{"set-msgExt","message extensions",NID_set_msgExt,3,&(lvalues[3883]),0},
-{"set-attr","set-attr",NID_set_attr,3,&(lvalues[3886]),0},
-{"set-policy","set-policy",NID_set_policy,3,&(lvalues[3889]),0},
-{"set-certExt","certificate extensions",NID_set_certExt,3,
-	&(lvalues[3892]),0},
-{"set-brand","set-brand",NID_set_brand,3,&(lvalues[3895]),0},
-{"setct-PANData","setct-PANData",NID_setct_PANData,4,&(lvalues[3898]),0},
-{"setct-PANToken","setct-PANToken",NID_setct_PANToken,4,
-	&(lvalues[3902]),0},
-{"setct-PANOnly","setct-PANOnly",NID_setct_PANOnly,4,&(lvalues[3906]),0},
-{"setct-OIData","setct-OIData",NID_setct_OIData,4,&(lvalues[3910]),0},
-{"setct-PI","setct-PI",NID_setct_PI,4,&(lvalues[3914]),0},
-{"setct-PIData","setct-PIData",NID_setct_PIData,4,&(lvalues[3918]),0},
-{"setct-PIDataUnsigned","setct-PIDataUnsigned",
-	NID_setct_PIDataUnsigned,4,&(lvalues[3922]),0},
-{"setct-HODInput","setct-HODInput",NID_setct_HODInput,4,
-	&(lvalues[3926]),0},
-{"setct-AuthResBaggage","setct-AuthResBaggage",
-	NID_setct_AuthResBaggage,4,&(lvalues[3930]),0},
-{"setct-AuthRevReqBaggage","setct-AuthRevReqBaggage",
-	NID_setct_AuthRevReqBaggage,4,&(lvalues[3934]),0},
-{"setct-AuthRevResBaggage","setct-AuthRevResBaggage",
-	NID_setct_AuthRevResBaggage,4,&(lvalues[3938]),0},
-{"setct-CapTokenSeq","setct-CapTokenSeq",NID_setct_CapTokenSeq,4,
-	&(lvalues[3942]),0},
-{"setct-PInitResData","setct-PInitResData",NID_setct_PInitResData,4,
-	&(lvalues[3946]),0},
-{"setct-PI-TBS","setct-PI-TBS",NID_setct_PI_TBS,4,&(lvalues[3950]),0},
-{"setct-PResData","setct-PResData",NID_setct_PResData,4,
-	&(lvalues[3954]),0},
-{"setct-AuthReqTBS","setct-AuthReqTBS",NID_setct_AuthReqTBS,4,
-	&(lvalues[3958]),0},
-{"setct-AuthResTBS","setct-AuthResTBS",NID_setct_AuthResTBS,4,
-	&(lvalues[3962]),0},
-{"setct-AuthResTBSX","setct-AuthResTBSX",NID_setct_AuthResTBSX,4,
-	&(lvalues[3966]),0},
-{"setct-AuthTokenTBS","setct-AuthTokenTBS",NID_setct_AuthTokenTBS,4,
-	&(lvalues[3970]),0},
-{"setct-CapTokenData","setct-CapTokenData",NID_setct_CapTokenData,4,
-	&(lvalues[3974]),0},
-{"setct-CapTokenTBS","setct-CapTokenTBS",NID_setct_CapTokenTBS,4,
-	&(lvalues[3978]),0},
-{"setct-AcqCardCodeMsg","setct-AcqCardCodeMsg",
-	NID_setct_AcqCardCodeMsg,4,&(lvalues[3982]),0},
-{"setct-AuthRevReqTBS","setct-AuthRevReqTBS",NID_setct_AuthRevReqTBS,
-	4,&(lvalues[3986]),0},
-{"setct-AuthRevResData","setct-AuthRevResData",
-	NID_setct_AuthRevResData,4,&(lvalues[3990]),0},
-{"setct-AuthRevResTBS","setct-AuthRevResTBS",NID_setct_AuthRevResTBS,
-	4,&(lvalues[3994]),0},
-{"setct-CapReqTBS","setct-CapReqTBS",NID_setct_CapReqTBS,4,
-	&(lvalues[3998]),0},
-{"setct-CapReqTBSX","setct-CapReqTBSX",NID_setct_CapReqTBSX,4,
-	&(lvalues[4002]),0},
-{"setct-CapResData","setct-CapResData",NID_setct_CapResData,4,
-	&(lvalues[4006]),0},
-{"setct-CapRevReqTBS","setct-CapRevReqTBS",NID_setct_CapRevReqTBS,4,
-	&(lvalues[4010]),0},
-{"setct-CapRevReqTBSX","setct-CapRevReqTBSX",NID_setct_CapRevReqTBSX,
-	4,&(lvalues[4014]),0},
-{"setct-CapRevResData","setct-CapRevResData",NID_setct_CapRevResData,
-	4,&(lvalues[4018]),0},
-{"setct-CredReqTBS","setct-CredReqTBS",NID_setct_CredReqTBS,4,
-	&(lvalues[4022]),0},
-{"setct-CredReqTBSX","setct-CredReqTBSX",NID_setct_CredReqTBSX,4,
-	&(lvalues[4026]),0},
-{"setct-CredResData","setct-CredResData",NID_setct_CredResData,4,
-	&(lvalues[4030]),0},
-{"setct-CredRevReqTBS","setct-CredRevReqTBS",NID_setct_CredRevReqTBS,
-	4,&(lvalues[4034]),0},
-{"setct-CredRevReqTBSX","setct-CredRevReqTBSX",
-	NID_setct_CredRevReqTBSX,4,&(lvalues[4038]),0},
-{"setct-CredRevResData","setct-CredRevResData",
-	NID_setct_CredRevResData,4,&(lvalues[4042]),0},
-{"setct-PCertReqData","setct-PCertReqData",NID_setct_PCertReqData,4,
-	&(lvalues[4046]),0},
-{"setct-PCertResTBS","setct-PCertResTBS",NID_setct_PCertResTBS,4,
-	&(lvalues[4050]),0},
-{"setct-BatchAdminReqData","setct-BatchAdminReqData",
-	NID_setct_BatchAdminReqData,4,&(lvalues[4054]),0},
-{"setct-BatchAdminResData","setct-BatchAdminResData",
-	NID_setct_BatchAdminResData,4,&(lvalues[4058]),0},
-{"setct-CardCInitResTBS","setct-CardCInitResTBS",
-	NID_setct_CardCInitResTBS,4,&(lvalues[4062]),0},
-{"setct-MeAqCInitResTBS","setct-MeAqCInitResTBS",
-	NID_setct_MeAqCInitResTBS,4,&(lvalues[4066]),0},
-{"setct-RegFormResTBS","setct-RegFormResTBS",NID_setct_RegFormResTBS,
-	4,&(lvalues[4070]),0},
-{"setct-CertReqData","setct-CertReqData",NID_setct_CertReqData,4,
-	&(lvalues[4074]),0},
-{"setct-CertReqTBS","setct-CertReqTBS",NID_setct_CertReqTBS,4,
-	&(lvalues[4078]),0},
-{"setct-CertResData","setct-CertResData",NID_setct_CertResData,4,
-	&(lvalues[4082]),0},
-{"setct-CertInqReqTBS","setct-CertInqReqTBS",NID_setct_CertInqReqTBS,
-	4,&(lvalues[4086]),0},
-{"setct-ErrorTBS","setct-ErrorTBS",NID_setct_ErrorTBS,4,
-	&(lvalues[4090]),0},
-{"setct-PIDualSignedTBE","setct-PIDualSignedTBE",
-	NID_setct_PIDualSignedTBE,4,&(lvalues[4094]),0},
-{"setct-PIUnsignedTBE","setct-PIUnsignedTBE",NID_setct_PIUnsignedTBE,
-	4,&(lvalues[4098]),0},
-{"setct-AuthReqTBE","setct-AuthReqTBE",NID_setct_AuthReqTBE,4,
-	&(lvalues[4102]),0},
-{"setct-AuthResTBE","setct-AuthResTBE",NID_setct_AuthResTBE,4,
-	&(lvalues[4106]),0},
-{"setct-AuthResTBEX","setct-AuthResTBEX",NID_setct_AuthResTBEX,4,
-	&(lvalues[4110]),0},
-{"setct-AuthTokenTBE","setct-AuthTokenTBE",NID_setct_AuthTokenTBE,4,
-	&(lvalues[4114]),0},
-{"setct-CapTokenTBE","setct-CapTokenTBE",NID_setct_CapTokenTBE,4,
-	&(lvalues[4118]),0},
-{"setct-CapTokenTBEX","setct-CapTokenTBEX",NID_setct_CapTokenTBEX,4,
-	&(lvalues[4122]),0},
-{"setct-AcqCardCodeMsgTBE","setct-AcqCardCodeMsgTBE",
-	NID_setct_AcqCardCodeMsgTBE,4,&(lvalues[4126]),0},
-{"setct-AuthRevReqTBE","setct-AuthRevReqTBE",NID_setct_AuthRevReqTBE,
-	4,&(lvalues[4130]),0},
-{"setct-AuthRevResTBE","setct-AuthRevResTBE",NID_setct_AuthRevResTBE,
-	4,&(lvalues[4134]),0},
-{"setct-AuthRevResTBEB","setct-AuthRevResTBEB",
-	NID_setct_AuthRevResTBEB,4,&(lvalues[4138]),0},
-{"setct-CapReqTBE","setct-CapReqTBE",NID_setct_CapReqTBE,4,
-	&(lvalues[4142]),0},
-{"setct-CapReqTBEX","setct-CapReqTBEX",NID_setct_CapReqTBEX,4,
-	&(lvalues[4146]),0},
-{"setct-CapResTBE","setct-CapResTBE",NID_setct_CapResTBE,4,
-	&(lvalues[4150]),0},
-{"setct-CapRevReqTBE","setct-CapRevReqTBE",NID_setct_CapRevReqTBE,4,
-	&(lvalues[4154]),0},
-{"setct-CapRevReqTBEX","setct-CapRevReqTBEX",NID_setct_CapRevReqTBEX,
-	4,&(lvalues[4158]),0},
-{"setct-CapRevResTBE","setct-CapRevResTBE",NID_setct_CapRevResTBE,4,
-	&(lvalues[4162]),0},
-{"setct-CredReqTBE","setct-CredReqTBE",NID_setct_CredReqTBE,4,
-	&(lvalues[4166]),0},
-{"setct-CredReqTBEX","setct-CredReqTBEX",NID_setct_CredReqTBEX,4,
-	&(lvalues[4170]),0},
-{"setct-CredResTBE","setct-CredResTBE",NID_setct_CredResTBE,4,
-	&(lvalues[4174]),0},
-{"setct-CredRevReqTBE","setct-CredRevReqTBE",NID_setct_CredRevReqTBE,
-	4,&(lvalues[4178]),0},
-{"setct-CredRevReqTBEX","setct-CredRevReqTBEX",
-	NID_setct_CredRevReqTBEX,4,&(lvalues[4182]),0},
-{"setct-CredRevResTBE","setct-CredRevResTBE",NID_setct_CredRevResTBE,
-	4,&(lvalues[4186]),0},
-{"setct-BatchAdminReqTBE","setct-BatchAdminReqTBE",
-	NID_setct_BatchAdminReqTBE,4,&(lvalues[4190]),0},
-{"setct-BatchAdminResTBE","setct-BatchAdminResTBE",
-	NID_setct_BatchAdminResTBE,4,&(lvalues[4194]),0},
-{"setct-RegFormReqTBE","setct-RegFormReqTBE",NID_setct_RegFormReqTBE,
-	4,&(lvalues[4198]),0},
-{"setct-CertReqTBE","setct-CertReqTBE",NID_setct_CertReqTBE,4,
-	&(lvalues[4202]),0},
-{"setct-CertReqTBEX","setct-CertReqTBEX",NID_setct_CertReqTBEX,4,
-	&(lvalues[4206]),0},
-{"setct-CertResTBE","setct-CertResTBE",NID_setct_CertResTBE,4,
-	&(lvalues[4210]),0},
-{"setct-CRLNotificationTBS","setct-CRLNotificationTBS",
-	NID_setct_CRLNotificationTBS,4,&(lvalues[4214]),0},
-{"setct-CRLNotificationResTBS","setct-CRLNotificationResTBS",
-	NID_setct_CRLNotificationResTBS,4,&(lvalues[4218]),0},
-{"setct-BCIDistributionTBS","setct-BCIDistributionTBS",
-	NID_setct_BCIDistributionTBS,4,&(lvalues[4222]),0},
-{"setext-genCrypt","generic cryptogram",NID_setext_genCrypt,4,
-	&(lvalues[4226]),0},
-{"setext-miAuth","merchant initiated auth",NID_setext_miAuth,4,
-	&(lvalues[4230]),0},
-{"setext-pinSecure","setext-pinSecure",NID_setext_pinSecure,4,
-	&(lvalues[4234]),0},
-{"setext-pinAny","setext-pinAny",NID_setext_pinAny,4,&(lvalues[4238]),0},
-{"setext-track2","setext-track2",NID_setext_track2,4,&(lvalues[4242]),0},
-{"setext-cv","additional verification",NID_setext_cv,4,
-	&(lvalues[4246]),0},
-{"set-policy-root","set-policy-root",NID_set_policy_root,4,
-	&(lvalues[4250]),0},
-{"setCext-hashedRoot","setCext-hashedRoot",NID_setCext_hashedRoot,4,
-	&(lvalues[4254]),0},
-{"setCext-certType","setCext-certType",NID_setCext_certType,4,
-	&(lvalues[4258]),0},
-{"setCext-merchData","setCext-merchData",NID_setCext_merchData,4,
-	&(lvalues[4262]),0},
-{"setCext-cCertRequired","setCext-cCertRequired",
-	NID_setCext_cCertRequired,4,&(lvalues[4266]),0},
-{"setCext-tunneling","setCext-tunneling",NID_setCext_tunneling,4,
-	&(lvalues[4270]),0},
-{"setCext-setExt","setCext-setExt",NID_setCext_setExt,4,
-	&(lvalues[4274]),0},
-{"setCext-setQualf","setCext-setQualf",NID_setCext_setQualf,4,
-	&(lvalues[4278]),0},
-{"setCext-PGWYcapabilities","setCext-PGWYcapabilities",
-	NID_setCext_PGWYcapabilities,4,&(lvalues[4282]),0},
-{"setCext-TokenIdentifier","setCext-TokenIdentifier",
-	NID_setCext_TokenIdentifier,4,&(lvalues[4286]),0},
-{"setCext-Track2Data","setCext-Track2Data",NID_setCext_Track2Data,4,
-	&(lvalues[4290]),0},
-{"setCext-TokenType","setCext-TokenType",NID_setCext_TokenType,4,
-	&(lvalues[4294]),0},
-{"setCext-IssuerCapabilities","setCext-IssuerCapabilities",
-	NID_setCext_IssuerCapabilities,4,&(lvalues[4298]),0},
-{"setAttr-Cert","setAttr-Cert",NID_setAttr_Cert,4,&(lvalues[4302]),0},
-{"setAttr-PGWYcap","payment gateway capabilities",NID_setAttr_PGWYcap,
-	4,&(lvalues[4306]),0},
-{"setAttr-TokenType","setAttr-TokenType",NID_setAttr_TokenType,4,
-	&(lvalues[4310]),0},
-{"setAttr-IssCap","issuer capabilities",NID_setAttr_IssCap,4,
-	&(lvalues[4314]),0},
-{"set-rootKeyThumb","set-rootKeyThumb",NID_set_rootKeyThumb,5,
-	&(lvalues[4318]),0},
-{"set-addPolicy","set-addPolicy",NID_set_addPolicy,5,&(lvalues[4323]),0},
-{"setAttr-Token-EMV","setAttr-Token-EMV",NID_setAttr_Token_EMV,5,
-	&(lvalues[4328]),0},
-{"setAttr-Token-B0Prime","setAttr-Token-B0Prime",
-	NID_setAttr_Token_B0Prime,5,&(lvalues[4333]),0},
-{"setAttr-IssCap-CVM","setAttr-IssCap-CVM",NID_setAttr_IssCap_CVM,5,
-	&(lvalues[4338]),0},
-{"setAttr-IssCap-T2","setAttr-IssCap-T2",NID_setAttr_IssCap_T2,5,
-	&(lvalues[4343]),0},
-{"setAttr-IssCap-Sig","setAttr-IssCap-Sig",NID_setAttr_IssCap_Sig,5,
-	&(lvalues[4348]),0},
-{"setAttr-GenCryptgrm","generate cryptogram",NID_setAttr_GenCryptgrm,
-	6,&(lvalues[4353]),0},
-{"setAttr-T2Enc","encrypted track 2",NID_setAttr_T2Enc,6,
-	&(lvalues[4359]),0},
-{"setAttr-T2cleartxt","cleartext track 2",NID_setAttr_T2cleartxt,6,
-	&(lvalues[4365]),0},
-{"setAttr-TokICCsig","ICC or token signature",NID_setAttr_TokICCsig,6,
-	&(lvalues[4371]),0},
-{"setAttr-SecDevSig","secure device signature",NID_setAttr_SecDevSig,
-	6,&(lvalues[4377]),0},
-{"set-brand-IATA-ATA","set-brand-IATA-ATA",NID_set_brand_IATA_ATA,4,
-	&(lvalues[4383]),0},
-{"set-brand-Diners","set-brand-Diners",NID_set_brand_Diners,4,
-	&(lvalues[4387]),0},
-{"set-brand-AmericanExpress","set-brand-AmericanExpress",
-	NID_set_brand_AmericanExpress,4,&(lvalues[4391]),0},
-{"set-brand-JCB","set-brand-JCB",NID_set_brand_JCB,4,&(lvalues[4395]),0},
-{"set-brand-Visa","set-brand-Visa",NID_set_brand_Visa,4,
-	&(lvalues[4399]),0},
-{"set-brand-MasterCard","set-brand-MasterCard",
-	NID_set_brand_MasterCard,4,&(lvalues[4403]),0},
-{"set-brand-Novus","set-brand-Novus",NID_set_brand_Novus,5,
-	&(lvalues[4407]),0},
-{"DES-CDMF","des-cdmf",NID_des_cdmf,8,&(lvalues[4412]),0},
-{"rsaOAEPEncryptionSET","rsaOAEPEncryptionSET",
-	NID_rsaOAEPEncryptionSET,9,&(lvalues[4420]),0},
-{"ITU-T","itu-t",NID_itu_t,0,NULL,0},
-{"JOINT-ISO-ITU-T","joint-iso-itu-t",NID_joint_iso_itu_t,0,NULL,0},
-{"international-organizations","International Organizations",
-	NID_international_organizations,1,&(lvalues[4429]),0},
-{"msSmartcardLogin","Microsoft Smartcardlogin",NID_ms_smartcard_login,
-	10,&(lvalues[4430]),0},
-{"msUPN","Microsoft Universal Principal Name",NID_ms_upn,10,
-	&(lvalues[4440]),0},
-{"AES-128-CFB1","aes-128-cfb1",NID_aes_128_cfb1,0,NULL,0},
-{"AES-192-CFB1","aes-192-cfb1",NID_aes_192_cfb1,0,NULL,0},
-{"AES-256-CFB1","aes-256-cfb1",NID_aes_256_cfb1,0,NULL,0},
-{"AES-128-CFB8","aes-128-cfb8",NID_aes_128_cfb8,0,NULL,0},
-{"AES-192-CFB8","aes-192-cfb8",NID_aes_192_cfb8,0,NULL,0},
-{"AES-256-CFB8","aes-256-cfb8",NID_aes_256_cfb8,0,NULL,0},
-{"DES-CFB1","des-cfb1",NID_des_cfb1,0,NULL,0},
-{"DES-CFB8","des-cfb8",NID_des_cfb8,0,NULL,0},
-{"DES-EDE3-CFB1","des-ede3-cfb1",NID_des_ede3_cfb1,0,NULL,0},
-{"DES-EDE3-CFB8","des-ede3-cfb8",NID_des_ede3_cfb8,0,NULL,0},
-{"street","streetAddress",NID_streetAddress,3,&(lvalues[4450]),0},
-{"postalCode","postalCode",NID_postalCode,3,&(lvalues[4453]),0},
-{"id-ppl","id-ppl",NID_id_ppl,7,&(lvalues[4456]),0},
-{"proxyCertInfo","Proxy Certificate Information",NID_proxyCertInfo,8,
-	&(lvalues[4463]),0},
-{"id-ppl-anyLanguage","Any language",NID_id_ppl_anyLanguage,8,
-	&(lvalues[4471]),0},
-{"id-ppl-inheritAll","Inherit all",NID_id_ppl_inheritAll,8,
-	&(lvalues[4479]),0},
-{"nameConstraints","X509v3 Name Constraints",NID_name_constraints,3,
-	&(lvalues[4487]),0},
-{"id-ppl-independent","Independent",NID_Independent,8,&(lvalues[4490]),0},
-{"RSA-SHA256","sha256WithRSAEncryption",NID_sha256WithRSAEncryption,9,
-	&(lvalues[4498]),0},
-{"RSA-SHA384","sha384WithRSAEncryption",NID_sha384WithRSAEncryption,9,
-	&(lvalues[4507]),0},
-{"RSA-SHA512","sha512WithRSAEncryption",NID_sha512WithRSAEncryption,9,
-	&(lvalues[4516]),0},
-{"RSA-SHA224","sha224WithRSAEncryption",NID_sha224WithRSAEncryption,9,
-	&(lvalues[4525]),0},
-{"SHA256","sha256",NID_sha256,9,&(lvalues[4534]),0},
-{"SHA384","sha384",NID_sha384,9,&(lvalues[4543]),0},
-{"SHA512","sha512",NID_sha512,9,&(lvalues[4552]),0},
-{"SHA224","sha224",NID_sha224,9,&(lvalues[4561]),0},
-{"identified-organization","identified-organization",
-	NID_identified_organization,1,&(lvalues[4570]),0},
-{"certicom-arc","certicom-arc",NID_certicom_arc,3,&(lvalues[4571]),0},
-{"wap","wap",NID_wap,2,&(lvalues[4574]),0},
-{"wap-wsg","wap-wsg",NID_wap_wsg,3,&(lvalues[4576]),0},
-{"id-characteristic-two-basis","id-characteristic-two-basis",
-	NID_X9_62_id_characteristic_two_basis,8,&(lvalues[4579]),0},
-{"onBasis","onBasis",NID_X9_62_onBasis,9,&(lvalues[4587]),0},
-{"tpBasis","tpBasis",NID_X9_62_tpBasis,9,&(lvalues[4596]),0},
-{"ppBasis","ppBasis",NID_X9_62_ppBasis,9,&(lvalues[4605]),0},
-{"c2pnb163v1","c2pnb163v1",NID_X9_62_c2pnb163v1,8,&(lvalues[4614]),0},
-{"c2pnb163v2","c2pnb163v2",NID_X9_62_c2pnb163v2,8,&(lvalues[4622]),0},
-{"c2pnb163v3","c2pnb163v3",NID_X9_62_c2pnb163v3,8,&(lvalues[4630]),0},
-{"c2pnb176v1","c2pnb176v1",NID_X9_62_c2pnb176v1,8,&(lvalues[4638]),0},
-{"c2tnb191v1","c2tnb191v1",NID_X9_62_c2tnb191v1,8,&(lvalues[4646]),0},
-{"c2tnb191v2","c2tnb191v2",NID_X9_62_c2tnb191v2,8,&(lvalues[4654]),0},
-{"c2tnb191v3","c2tnb191v3",NID_X9_62_c2tnb191v3,8,&(lvalues[4662]),0},
-{"c2onb191v4","c2onb191v4",NID_X9_62_c2onb191v4,8,&(lvalues[4670]),0},
-{"c2onb191v5","c2onb191v5",NID_X9_62_c2onb191v5,8,&(lvalues[4678]),0},
-{"c2pnb208w1","c2pnb208w1",NID_X9_62_c2pnb208w1,8,&(lvalues[4686]),0},
-{"c2tnb239v1","c2tnb239v1",NID_X9_62_c2tnb239v1,8,&(lvalues[4694]),0},
-{"c2tnb239v2","c2tnb239v2",NID_X9_62_c2tnb239v2,8,&(lvalues[4702]),0},
-{"c2tnb239v3","c2tnb239v3",NID_X9_62_c2tnb239v3,8,&(lvalues[4710]),0},
-{"c2onb239v4","c2onb239v4",NID_X9_62_c2onb239v4,8,&(lvalues[4718]),0},
-{"c2onb239v5","c2onb239v5",NID_X9_62_c2onb239v5,8,&(lvalues[4726]),0},
-{"c2pnb272w1","c2pnb272w1",NID_X9_62_c2pnb272w1,8,&(lvalues[4734]),0},
-{"c2pnb304w1","c2pnb304w1",NID_X9_62_c2pnb304w1,8,&(lvalues[4742]),0},
-{"c2tnb359v1","c2tnb359v1",NID_X9_62_c2tnb359v1,8,&(lvalues[4750]),0},
-{"c2pnb368w1","c2pnb368w1",NID_X9_62_c2pnb368w1,8,&(lvalues[4758]),0},
-{"c2tnb431r1","c2tnb431r1",NID_X9_62_c2tnb431r1,8,&(lvalues[4766]),0},
-{"secp112r1","secp112r1",NID_secp112r1,5,&(lvalues[4774]),0},
-{"secp112r2","secp112r2",NID_secp112r2,5,&(lvalues[4779]),0},
-{"secp128r1","secp128r1",NID_secp128r1,5,&(lvalues[4784]),0},
-{"secp128r2","secp128r2",NID_secp128r2,5,&(lvalues[4789]),0},
-{"secp160k1","secp160k1",NID_secp160k1,5,&(lvalues[4794]),0},
-{"secp160r1","secp160r1",NID_secp160r1,5,&(lvalues[4799]),0},
-{"secp160r2","secp160r2",NID_secp160r2,5,&(lvalues[4804]),0},
-{"secp192k1","secp192k1",NID_secp192k1,5,&(lvalues[4809]),0},
-{"secp224k1","secp224k1",NID_secp224k1,5,&(lvalues[4814]),0},
-{"secp224r1","secp224r1",NID_secp224r1,5,&(lvalues[4819]),0},
-{"secp256k1","secp256k1",NID_secp256k1,5,&(lvalues[4824]),0},
-{"secp384r1","secp384r1",NID_secp384r1,5,&(lvalues[4829]),0},
-{"secp521r1","secp521r1",NID_secp521r1,5,&(lvalues[4834]),0},
-{"sect113r1","sect113r1",NID_sect113r1,5,&(lvalues[4839]),0},
-{"sect113r2","sect113r2",NID_sect113r2,5,&(lvalues[4844]),0},
-{"sect131r1","sect131r1",NID_sect131r1,5,&(lvalues[4849]),0},
-{"sect131r2","sect131r2",NID_sect131r2,5,&(lvalues[4854]),0},
-{"sect163k1","sect163k1",NID_sect163k1,5,&(lvalues[4859]),0},
-{"sect163r1","sect163r1",NID_sect163r1,5,&(lvalues[4864]),0},
-{"sect163r2","sect163r2",NID_sect163r2,5,&(lvalues[4869]),0},
-{"sect193r1","sect193r1",NID_sect193r1,5,&(lvalues[4874]),0},
-{"sect193r2","sect193r2",NID_sect193r2,5,&(lvalues[4879]),0},
-{"sect233k1","sect233k1",NID_sect233k1,5,&(lvalues[4884]),0},
-{"sect233r1","sect233r1",NID_sect233r1,5,&(lvalues[4889]),0},
-{"sect239k1","sect239k1",NID_sect239k1,5,&(lvalues[4894]),0},
-{"sect283k1","sect283k1",NID_sect283k1,5,&(lvalues[4899]),0},
-{"sect283r1","sect283r1",NID_sect283r1,5,&(lvalues[4904]),0},
-{"sect409k1","sect409k1",NID_sect409k1,5,&(lvalues[4909]),0},
-{"sect409r1","sect409r1",NID_sect409r1,5,&(lvalues[4914]),0},
-{"sect571k1","sect571k1",NID_sect571k1,5,&(lvalues[4919]),0},
-{"sect571r1","sect571r1",NID_sect571r1,5,&(lvalues[4924]),0},
-{"wap-wsg-idm-ecid-wtls1","wap-wsg-idm-ecid-wtls1",
-	NID_wap_wsg_idm_ecid_wtls1,5,&(lvalues[4929]),0},
-{"wap-wsg-idm-ecid-wtls3","wap-wsg-idm-ecid-wtls3",
-	NID_wap_wsg_idm_ecid_wtls3,5,&(lvalues[4934]),0},
-{"wap-wsg-idm-ecid-wtls4","wap-wsg-idm-ecid-wtls4",
-	NID_wap_wsg_idm_ecid_wtls4,5,&(lvalues[4939]),0},
-{"wap-wsg-idm-ecid-wtls5","wap-wsg-idm-ecid-wtls5",
-	NID_wap_wsg_idm_ecid_wtls5,5,&(lvalues[4944]),0},
-{"wap-wsg-idm-ecid-wtls6","wap-wsg-idm-ecid-wtls6",
-	NID_wap_wsg_idm_ecid_wtls6,5,&(lvalues[4949]),0},
-{"wap-wsg-idm-ecid-wtls7","wap-wsg-idm-ecid-wtls7",
-	NID_wap_wsg_idm_ecid_wtls7,5,&(lvalues[4954]),0},
-{"wap-wsg-idm-ecid-wtls8","wap-wsg-idm-ecid-wtls8",
-	NID_wap_wsg_idm_ecid_wtls8,5,&(lvalues[4959]),0},
-{"wap-wsg-idm-ecid-wtls9","wap-wsg-idm-ecid-wtls9",
-	NID_wap_wsg_idm_ecid_wtls9,5,&(lvalues[4964]),0},
-{"wap-wsg-idm-ecid-wtls10","wap-wsg-idm-ecid-wtls10",
-	NID_wap_wsg_idm_ecid_wtls10,5,&(lvalues[4969]),0},
-{"wap-wsg-idm-ecid-wtls11","wap-wsg-idm-ecid-wtls11",
-	NID_wap_wsg_idm_ecid_wtls11,5,&(lvalues[4974]),0},
-{"wap-wsg-idm-ecid-wtls12","wap-wsg-idm-ecid-wtls12",
-	NID_wap_wsg_idm_ecid_wtls12,5,&(lvalues[4979]),0},
-{"anyPolicy","X509v3 Any Policy",NID_any_policy,4,&(lvalues[4984]),0},
-{"policyMappings","X509v3 Policy Mappings",NID_policy_mappings,3,
-	&(lvalues[4988]),0},
-{"inhibitAnyPolicy","X509v3 Inhibit Any Policy",
-	NID_inhibit_any_policy,3,&(lvalues[4991]),0},
-{"Oakley-EC2N-3","ipsec3",NID_ipsec3,0,NULL,0},
-{"Oakley-EC2N-4","ipsec4",NID_ipsec4,0,NULL,0},
-{"CAMELLIA-128-CBC","camellia-128-cbc",NID_camellia_128_cbc,11,
-	&(lvalues[4994]),0},
-{"CAMELLIA-192-CBC","camellia-192-cbc",NID_camellia_192_cbc,11,
-	&(lvalues[5005]),0},
-{"CAMELLIA-256-CBC","camellia-256-cbc",NID_camellia_256_cbc,11,
-	&(lvalues[5016]),0},
-{"CAMELLIA-128-ECB","camellia-128-ecb",NID_camellia_128_ecb,8,
-	&(lvalues[5027]),0},
-{"CAMELLIA-192-ECB","camellia-192-ecb",NID_camellia_192_ecb,8,
-	&(lvalues[5035]),0},
-{"CAMELLIA-256-ECB","camellia-256-ecb",NID_camellia_256_ecb,8,
-	&(lvalues[5043]),0},
-{"CAMELLIA-128-CFB","camellia-128-cfb",NID_camellia_128_cfb128,8,
-	&(lvalues[5051]),0},
-{"CAMELLIA-192-CFB","camellia-192-cfb",NID_camellia_192_cfb128,8,
-	&(lvalues[5059]),0},
-{"CAMELLIA-256-CFB","camellia-256-cfb",NID_camellia_256_cfb128,8,
-	&(lvalues[5067]),0},
-{"CAMELLIA-128-CFB1","camellia-128-cfb1",NID_camellia_128_cfb1,0,NULL,0},
-{"CAMELLIA-192-CFB1","camellia-192-cfb1",NID_camellia_192_cfb1,0,NULL,0},
-{"CAMELLIA-256-CFB1","camellia-256-cfb1",NID_camellia_256_cfb1,0,NULL,0},
-{"CAMELLIA-128-CFB8","camellia-128-cfb8",NID_camellia_128_cfb8,0,NULL,0},
-{"CAMELLIA-192-CFB8","camellia-192-cfb8",NID_camellia_192_cfb8,0,NULL,0},
-{"CAMELLIA-256-CFB8","camellia-256-cfb8",NID_camellia_256_cfb8,0,NULL,0},
-{"CAMELLIA-128-OFB","camellia-128-ofb",NID_camellia_128_ofb128,8,
-	&(lvalues[5075]),0},
-{"CAMELLIA-192-OFB","camellia-192-ofb",NID_camellia_192_ofb128,8,
-	&(lvalues[5083]),0},
-{"CAMELLIA-256-OFB","camellia-256-ofb",NID_camellia_256_ofb128,8,
-	&(lvalues[5091]),0},
-{"subjectDirectoryAttributes","X509v3 Subject Directory Attributes",
-	NID_subject_directory_attributes,3,&(lvalues[5099]),0},
-{"issuingDistributionPoint","X509v3 Issuing Distribution Point",
-	NID_issuing_distribution_point,3,&(lvalues[5102]),0},
-{"certificateIssuer","X509v3 Certificate Issuer",
-	NID_certificate_issuer,3,&(lvalues[5105]),0},
-{NULL,NULL,NID_undef,0,NULL,0},
-{"KISA","kisa",NID_kisa,6,&(lvalues[5108]),0},
-{NULL,NULL,NID_undef,0,NULL,0},
-{NULL,NULL,NID_undef,0,NULL,0},
-{"SEED-ECB","seed-ecb",NID_seed_ecb,8,&(lvalues[5114]),0},
-{"SEED-CBC","seed-cbc",NID_seed_cbc,8,&(lvalues[5122]),0},
-{"SEED-OFB","seed-ofb",NID_seed_ofb128,8,&(lvalues[5130]),0},
-{"SEED-CFB","seed-cfb",NID_seed_cfb128,8,&(lvalues[5138]),0},
-{"HMAC-MD5","hmac-md5",NID_hmac_md5,8,&(lvalues[5146]),0},
-{"HMAC-SHA1","hmac-sha1",NID_hmac_sha1,8,&(lvalues[5154]),0},
-{"id-PasswordBasedMAC","password based MAC",NID_id_PasswordBasedMAC,9,
-	&(lvalues[5162]),0},
-{"id-DHBasedMac","Diffie-Hellman based MAC",NID_id_DHBasedMac,9,
-	&(lvalues[5171]),0},
-{"id-it-suppLangTags","id-it-suppLangTags",NID_id_it_suppLangTags,8,
-	&(lvalues[5180]),0},
-{"caRepository","CA Repository",NID_caRepository,8,&(lvalues[5188]),0},
-{"id-smime-ct-compressedData","id-smime-ct-compressedData",
-	NID_id_smime_ct_compressedData,11,&(lvalues[5196]),0},
-{"id-ct-asciiTextWithCRLF","id-ct-asciiTextWithCRLF",
-	NID_id_ct_asciiTextWithCRLF,11,&(lvalues[5207]),0},
-{"id-aes128-wrap","id-aes128-wrap",NID_id_aes128_wrap,9,
-	&(lvalues[5218]),0},
-{"id-aes192-wrap","id-aes192-wrap",NID_id_aes192_wrap,9,
-	&(lvalues[5227]),0},
-{"id-aes256-wrap","id-aes256-wrap",NID_id_aes256_wrap,9,
-	&(lvalues[5236]),0},
-{"ecdsa-with-Recommended","ecdsa-with-Recommended",
-	NID_ecdsa_with_Recommended,7,&(lvalues[5245]),0},
-{"ecdsa-with-Specified","ecdsa-with-Specified",
-	NID_ecdsa_with_Specified,7,&(lvalues[5252]),0},
-{"ecdsa-with-SHA224","ecdsa-with-SHA224",NID_ecdsa_with_SHA224,8,
-	&(lvalues[5259]),0},
-{"ecdsa-with-SHA256","ecdsa-with-SHA256",NID_ecdsa_with_SHA256,8,
-	&(lvalues[5267]),0},
-{"ecdsa-with-SHA384","ecdsa-with-SHA384",NID_ecdsa_with_SHA384,8,
-	&(lvalues[5275]),0},
-{"ecdsa-with-SHA512","ecdsa-with-SHA512",NID_ecdsa_with_SHA512,8,
-	&(lvalues[5283]),0},
-{"hmacWithMD5","hmacWithMD5",NID_hmacWithMD5,8,&(lvalues[5291]),0},
-{"hmacWithSHA224","hmacWithSHA224",NID_hmacWithSHA224,8,
-	&(lvalues[5299]),0},
-{"hmacWithSHA256","hmacWithSHA256",NID_hmacWithSHA256,8,
-	&(lvalues[5307]),0},
-{"hmacWithSHA384","hmacWithSHA384",NID_hmacWithSHA384,8,
-	&(lvalues[5315]),0},
-{"hmacWithSHA512","hmacWithSHA512",NID_hmacWithSHA512,8,
-	&(lvalues[5323]),0},
-{"dsa_with_SHA224","dsa_with_SHA224",NID_dsa_with_SHA224,9,
-	&(lvalues[5331]),0},
-{"dsa_with_SHA256","dsa_with_SHA256",NID_dsa_with_SHA256,9,
-	&(lvalues[5340]),0},
-{"whirlpool","whirlpool",NID_whirlpool,6,&(lvalues[5349]),0},
-{"cryptopro","cryptopro",NID_cryptopro,5,&(lvalues[5355]),0},
-{"cryptocom","cryptocom",NID_cryptocom,5,&(lvalues[5360]),0},
-{"id-GostR3411-94-with-GostR3410-2001",
-	"GOST R 34.11-94 with GOST R 34.10-2001",
-	NID_id_GostR3411_94_with_GostR3410_2001,6,&(lvalues[5365]),0},
-{"id-GostR3411-94-with-GostR3410-94",
-	"GOST R 34.11-94 with GOST R 34.10-94",
-	NID_id_GostR3411_94_with_GostR3410_94,6,&(lvalues[5371]),0},
-{"md_gost94","GOST R 34.11-94",NID_id_GostR3411_94,6,&(lvalues[5377]),0},
-{"id-HMACGostR3411-94","HMAC GOST 34.11-94",NID_id_HMACGostR3411_94,6,
-	&(lvalues[5383]),0},
-{"gost2001","GOST R 34.10-2001",NID_id_GostR3410_2001,6,
-	&(lvalues[5389]),0},
-{"gost94","GOST R 34.10-94",NID_id_GostR3410_94,6,&(lvalues[5395]),0},
-{"gost89","GOST 28147-89",NID_id_Gost28147_89,6,&(lvalues[5401]),0},
-{"gost89-cnt","gost89-cnt",NID_gost89_cnt,0,NULL,0},
-{"gost-mac","GOST 28147-89 MAC",NID_id_Gost28147_89_MAC,6,
-	&(lvalues[5407]),0},
-{"prf-gostr3411-94","GOST R 34.11-94 PRF",NID_id_GostR3411_94_prf,6,
-	&(lvalues[5413]),0},
-{"id-GostR3410-2001DH","GOST R 34.10-2001 DH",NID_id_GostR3410_2001DH,
-	6,&(lvalues[5419]),0},
-{"id-GostR3410-94DH","GOST R 34.10-94 DH",NID_id_GostR3410_94DH,6,
-	&(lvalues[5425]),0},
-{"id-Gost28147-89-CryptoPro-KeyMeshing",
-	"id-Gost28147-89-CryptoPro-KeyMeshing",
-	NID_id_Gost28147_89_CryptoPro_KeyMeshing,7,&(lvalues[5431]),0},
-{"id-Gost28147-89-None-KeyMeshing","id-Gost28147-89-None-KeyMeshing",
-	NID_id_Gost28147_89_None_KeyMeshing,7,&(lvalues[5438]),0},
-{"id-GostR3411-94-TestParamSet","id-GostR3411-94-TestParamSet",
-	NID_id_GostR3411_94_TestParamSet,7,&(lvalues[5445]),0},
-{"id-GostR3411-94-CryptoProParamSet",
-	"id-GostR3411-94-CryptoProParamSet",
-	NID_id_GostR3411_94_CryptoProParamSet,7,&(lvalues[5452]),0},
-{"id-Gost28147-89-TestParamSet","id-Gost28147-89-TestParamSet",
-	NID_id_Gost28147_89_TestParamSet,7,&(lvalues[5459]),0},
-{"id-Gost28147-89-CryptoPro-A-ParamSet",
-	"id-Gost28147-89-CryptoPro-A-ParamSet",
-	NID_id_Gost28147_89_CryptoPro_A_ParamSet,7,&(lvalues[5466]),0},
-{"id-Gost28147-89-CryptoPro-B-ParamSet",
-	"id-Gost28147-89-CryptoPro-B-ParamSet",
-	NID_id_Gost28147_89_CryptoPro_B_ParamSet,7,&(lvalues[5473]),0},
-{"id-Gost28147-89-CryptoPro-C-ParamSet",
-	"id-Gost28147-89-CryptoPro-C-ParamSet",
-	NID_id_Gost28147_89_CryptoPro_C_ParamSet,7,&(lvalues[5480]),0},
-{"id-Gost28147-89-CryptoPro-D-ParamSet",
-	"id-Gost28147-89-CryptoPro-D-ParamSet",
-	NID_id_Gost28147_89_CryptoPro_D_ParamSet,7,&(lvalues[5487]),0},
-{"id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet",
-	"id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet",
-	NID_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet,7,&(lvalues[5494]),
-	0},
-{"id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet",
-	"id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet",
-	NID_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet,7,&(lvalues[5501]),
-	0},
-{"id-Gost28147-89-CryptoPro-RIC-1-ParamSet",
-	"id-Gost28147-89-CryptoPro-RIC-1-ParamSet",
-	NID_id_Gost28147_89_CryptoPro_RIC_1_ParamSet,7,&(lvalues[5508]),0},
-{"id-GostR3410-94-TestParamSet","id-GostR3410-94-TestParamSet",
-	NID_id_GostR3410_94_TestParamSet,7,&(lvalues[5515]),0},
-{"id-GostR3410-94-CryptoPro-A-ParamSet",
-	"id-GostR3410-94-CryptoPro-A-ParamSet",
-	NID_id_GostR3410_94_CryptoPro_A_ParamSet,7,&(lvalues[5522]),0},
-{"id-GostR3410-94-CryptoPro-B-ParamSet",
-	"id-GostR3410-94-CryptoPro-B-ParamSet",
-	NID_id_GostR3410_94_CryptoPro_B_ParamSet,7,&(lvalues[5529]),0},
-{"id-GostR3410-94-CryptoPro-C-ParamSet",
-	"id-GostR3410-94-CryptoPro-C-ParamSet",
-	NID_id_GostR3410_94_CryptoPro_C_ParamSet,7,&(lvalues[5536]),0},
-{"id-GostR3410-94-CryptoPro-D-ParamSet",
-	"id-GostR3410-94-CryptoPro-D-ParamSet",
-	NID_id_GostR3410_94_CryptoPro_D_ParamSet,7,&(lvalues[5543]),0},
-{"id-GostR3410-94-CryptoPro-XchA-ParamSet",
-	"id-GostR3410-94-CryptoPro-XchA-ParamSet",
-	NID_id_GostR3410_94_CryptoPro_XchA_ParamSet,7,&(lvalues[5550]),0},
-{"id-GostR3410-94-CryptoPro-XchB-ParamSet",
-	"id-GostR3410-94-CryptoPro-XchB-ParamSet",
-	NID_id_GostR3410_94_CryptoPro_XchB_ParamSet,7,&(lvalues[5557]),0},
-{"id-GostR3410-94-CryptoPro-XchC-ParamSet",
-	"id-GostR3410-94-CryptoPro-XchC-ParamSet",
-	NID_id_GostR3410_94_CryptoPro_XchC_ParamSet,7,&(lvalues[5564]),0},
-{"id-GostR3410-2001-TestParamSet","id-GostR3410-2001-TestParamSet",
-	NID_id_GostR3410_2001_TestParamSet,7,&(lvalues[5571]),0},
-{"id-GostR3410-2001-CryptoPro-A-ParamSet",
-	"id-GostR3410-2001-CryptoPro-A-ParamSet",
-	NID_id_GostR3410_2001_CryptoPro_A_ParamSet,7,&(lvalues[5578]),0},
-{"id-GostR3410-2001-CryptoPro-B-ParamSet",
-	"id-GostR3410-2001-CryptoPro-B-ParamSet",
-	NID_id_GostR3410_2001_CryptoPro_B_ParamSet,7,&(lvalues[5585]),0},
-{"id-GostR3410-2001-CryptoPro-C-ParamSet",
-	"id-GostR3410-2001-CryptoPro-C-ParamSet",
-	NID_id_GostR3410_2001_CryptoPro_C_ParamSet,7,&(lvalues[5592]),0},
-{"id-GostR3410-2001-CryptoPro-XchA-ParamSet",
-	"id-GostR3410-2001-CryptoPro-XchA-ParamSet",
-	NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet,7,&(lvalues[5599]),0},
-	
-{"id-GostR3410-2001-CryptoPro-XchB-ParamSet",
-	"id-GostR3410-2001-CryptoPro-XchB-ParamSet",
-	NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet,7,&(lvalues[5606]),0},
-	
-{"id-GostR3410-94-a","id-GostR3410-94-a",NID_id_GostR3410_94_a,7,
-	&(lvalues[5613]),0},
-{"id-GostR3410-94-aBis","id-GostR3410-94-aBis",
-	NID_id_GostR3410_94_aBis,7,&(lvalues[5620]),0},
-{"id-GostR3410-94-b","id-GostR3410-94-b",NID_id_GostR3410_94_b,7,
-	&(lvalues[5627]),0},
-{"id-GostR3410-94-bBis","id-GostR3410-94-bBis",
-	NID_id_GostR3410_94_bBis,7,&(lvalues[5634]),0},
-{"id-Gost28147-89-cc","GOST 28147-89 Cryptocom ParamSet",
-	NID_id_Gost28147_89_cc,8,&(lvalues[5641]),0},
-{"gost94cc","GOST 34.10-94 Cryptocom",NID_id_GostR3410_94_cc,8,
-	&(lvalues[5649]),0},
-{"gost2001cc","GOST 34.10-2001 Cryptocom",NID_id_GostR3410_2001_cc,8,
-	&(lvalues[5657]),0},
-{"id-GostR3411-94-with-GostR3410-94-cc",
-	"GOST R 34.11-94 with GOST R 34.10-94 Cryptocom",
-	NID_id_GostR3411_94_with_GostR3410_94_cc,8,&(lvalues[5665]),0},
-{"id-GostR3411-94-with-GostR3410-2001-cc",
-	"GOST R 34.11-94 with GOST R 34.10-2001 Cryptocom",
-	NID_id_GostR3411_94_with_GostR3410_2001_cc,8,&(lvalues[5673]),0},
-{"id-GostR3410-2001-ParamSet-cc",
-	"GOST R 3410-2001 Parameter Set Cryptocom",
-	NID_id_GostR3410_2001_ParamSet_cc,8,&(lvalues[5681]),0},
-{"HMAC","hmac",NID_hmac,0,NULL,0},
-{"LocalKeySet","Microsoft Local Key set",NID_LocalKeySet,9,
-	&(lvalues[5689]),0},
-{"freshestCRL","X509v3 Freshest CRL",NID_freshest_crl,3,
-	&(lvalues[5698]),0},
-{"id-on-permanentIdentifier","Permanent Identifier",
-	NID_id_on_permanentIdentifier,8,&(lvalues[5701]),0},
-{"searchGuide","searchGuide",NID_searchGuide,3,&(lvalues[5709]),0},
-{"businessCategory","businessCategory",NID_businessCategory,3,
-	&(lvalues[5712]),0},
-{"postalAddress","postalAddress",NID_postalAddress,3,&(lvalues[5715]),0},
-{"postOfficeBox","postOfficeBox",NID_postOfficeBox,3,&(lvalues[5718]),0},
-{"physicalDeliveryOfficeName","physicalDeliveryOfficeName",
-	NID_physicalDeliveryOfficeName,3,&(lvalues[5721]),0},
-{"telephoneNumber","telephoneNumber",NID_telephoneNumber,3,
-	&(lvalues[5724]),0},
-{"telexNumber","telexNumber",NID_telexNumber,3,&(lvalues[5727]),0},
-{"teletexTerminalIdentifier","teletexTerminalIdentifier",
-	NID_teletexTerminalIdentifier,3,&(lvalues[5730]),0},
-{"facsimileTelephoneNumber","facsimileTelephoneNumber",
-	NID_facsimileTelephoneNumber,3,&(lvalues[5733]),0},
-{"x121Address","x121Address",NID_x121Address,3,&(lvalues[5736]),0},
-{"internationaliSDNNumber","internationaliSDNNumber",
-	NID_internationaliSDNNumber,3,&(lvalues[5739]),0},
-{"registeredAddress","registeredAddress",NID_registeredAddress,3,
-	&(lvalues[5742]),0},
-{"destinationIndicator","destinationIndicator",
-	NID_destinationIndicator,3,&(lvalues[5745]),0},
-{"preferredDeliveryMethod","preferredDeliveryMethod",
-	NID_preferredDeliveryMethod,3,&(lvalues[5748]),0},
-{"presentationAddress","presentationAddress",NID_presentationAddress,
-	3,&(lvalues[5751]),0},
-{"supportedApplicationContext","supportedApplicationContext",
-	NID_supportedApplicationContext,3,&(lvalues[5754]),0},
-{"member","member",NID_member,3,&(lvalues[5757]),0},
-{"owner","owner",NID_owner,3,&(lvalues[5760]),0},
-{"roleOccupant","roleOccupant",NID_roleOccupant,3,&(lvalues[5763]),0},
-{"seeAlso","seeAlso",NID_seeAlso,3,&(lvalues[5766]),0},
-{"userPassword","userPassword",NID_userPassword,3,&(lvalues[5769]),0},
-{"userCertificate","userCertificate",NID_userCertificate,3,
-	&(lvalues[5772]),0},
-{"cACertificate","cACertificate",NID_cACertificate,3,&(lvalues[5775]),0},
-{"authorityRevocationList","authorityRevocationList",
-	NID_authorityRevocationList,3,&(lvalues[5778]),0},
-{"certificateRevocationList","certificateRevocationList",
-	NID_certificateRevocationList,3,&(lvalues[5781]),0},
-{"crossCertificatePair","crossCertificatePair",
-	NID_crossCertificatePair,3,&(lvalues[5784]),0},
-{"enhancedSearchGuide","enhancedSearchGuide",NID_enhancedSearchGuide,
-	3,&(lvalues[5787]),0},
-{"protocolInformation","protocolInformation",NID_protocolInformation,
-	3,&(lvalues[5790]),0},
-{"distinguishedName","distinguishedName",NID_distinguishedName,3,
-	&(lvalues[5793]),0},
-{"uniqueMember","uniqueMember",NID_uniqueMember,3,&(lvalues[5796]),0},
-{"houseIdentifier","houseIdentifier",NID_houseIdentifier,3,
-	&(lvalues[5799]),0},
-{"supportedAlgorithms","supportedAlgorithms",NID_supportedAlgorithms,
-	3,&(lvalues[5802]),0},
-{"deltaRevocationList","deltaRevocationList",NID_deltaRevocationList,
-	3,&(lvalues[5805]),0},
-{"dmdName","dmdName",NID_dmdName,3,&(lvalues[5808]),0},
-{"id-alg-PWRI-KEK","id-alg-PWRI-KEK",NID_id_alg_PWRI_KEK,11,
-	&(lvalues[5811]),0},
-{"CMAC","cmac",NID_cmac,0,NULL,0},
-{"id-aes128-GCM","aes-128-gcm",NID_aes_128_gcm,9,&(lvalues[5822]),0},
-{"id-aes128-CCM","aes-128-ccm",NID_aes_128_ccm,9,&(lvalues[5831]),0},
-{"id-aes128-wrap-pad","id-aes128-wrap-pad",NID_id_aes128_wrap_pad,9,
-	&(lvalues[5840]),0},
-{"id-aes192-GCM","aes-192-gcm",NID_aes_192_gcm,9,&(lvalues[5849]),0},
-{"id-aes192-CCM","aes-192-ccm",NID_aes_192_ccm,9,&(lvalues[5858]),0},
-{"id-aes192-wrap-pad","id-aes192-wrap-pad",NID_id_aes192_wrap_pad,9,
-	&(lvalues[5867]),0},
-{"id-aes256-GCM","aes-256-gcm",NID_aes_256_gcm,9,&(lvalues[5876]),0},
-{"id-aes256-CCM","aes-256-ccm",NID_aes_256_ccm,9,&(lvalues[5885]),0},
-{"id-aes256-wrap-pad","id-aes256-wrap-pad",NID_id_aes256_wrap_pad,9,
-	&(lvalues[5894]),0},
-{"AES-128-CTR","aes-128-ctr",NID_aes_128_ctr,0,NULL,0},
-{"AES-192-CTR","aes-192-ctr",NID_aes_192_ctr,0,NULL,0},
-{"AES-256-CTR","aes-256-ctr",NID_aes_256_ctr,0,NULL,0},
-{"id-camellia128-wrap","id-camellia128-wrap",NID_id_camellia128_wrap,
-	11,&(lvalues[5903]),0},
-{"id-camellia192-wrap","id-camellia192-wrap",NID_id_camellia192_wrap,
-	11,&(lvalues[5914]),0},
-{"id-camellia256-wrap","id-camellia256-wrap",NID_id_camellia256_wrap,
-	11,&(lvalues[5925]),0},
-{"anyExtendedKeyUsage","Any Extended Key Usage",
-	NID_anyExtendedKeyUsage,4,&(lvalues[5936]),0},
-{"MGF1","mgf1",NID_mgf1,9,&(lvalues[5940]),0},
-{"RSASSA-PSS","rsassaPss",NID_rsassaPss,9,&(lvalues[5949]),0},
-{"AES-128-XTS","aes-128-xts",NID_aes_128_xts,0,NULL,0},
-{"AES-256-XTS","aes-256-xts",NID_aes_256_xts,0,NULL,0},
-{"RC4-HMAC-MD5","rc4-hmac-md5",NID_rc4_hmac_md5,0,NULL,0},
-{"AES-128-CBC-HMAC-SHA1","aes-128-cbc-hmac-sha1",
-	NID_aes_128_cbc_hmac_sha1,0,NULL,0},
-{"AES-192-CBC-HMAC-SHA1","aes-192-cbc-hmac-sha1",
-	NID_aes_192_cbc_hmac_sha1,0,NULL,0},
-{"AES-256-CBC-HMAC-SHA1","aes-256-cbc-hmac-sha1",
-	NID_aes_256_cbc_hmac_sha1,0,NULL,0},
-{"RSAES-OAEP","rsaesOaep",NID_rsaesOaep,9,&(lvalues[5958]),0},
-{"dhpublicnumber","X9.42 DH",NID_dhpublicnumber,7,&(lvalues[5967]),0},
-{"brainpoolP160r1","brainpoolP160r1",NID_brainpoolP160r1,9,
-	&(lvalues[5974]),0},
-{"brainpoolP160t1","brainpoolP160t1",NID_brainpoolP160t1,9,
-	&(lvalues[5983]),0},
-{"brainpoolP192r1","brainpoolP192r1",NID_brainpoolP192r1,9,
-	&(lvalues[5992]),0},
-{"brainpoolP192t1","brainpoolP192t1",NID_brainpoolP192t1,9,
-	&(lvalues[6001]),0},
-{"brainpoolP224r1","brainpoolP224r1",NID_brainpoolP224r1,9,
-	&(lvalues[6010]),0},
-{"brainpoolP224t1","brainpoolP224t1",NID_brainpoolP224t1,9,
-	&(lvalues[6019]),0},
-{"brainpoolP256r1","brainpoolP256r1",NID_brainpoolP256r1,9,
-	&(lvalues[6028]),0},
-{"brainpoolP256t1","brainpoolP256t1",NID_brainpoolP256t1,9,
-	&(lvalues[6037]),0},
-{"brainpoolP320r1","brainpoolP320r1",NID_brainpoolP320r1,9,
-	&(lvalues[6046]),0},
-{"brainpoolP320t1","brainpoolP320t1",NID_brainpoolP320t1,9,
-	&(lvalues[6055]),0},
-{"brainpoolP384r1","brainpoolP384r1",NID_brainpoolP384r1,9,
-	&(lvalues[6064]),0},
-{"brainpoolP384t1","brainpoolP384t1",NID_brainpoolP384t1,9,
-	&(lvalues[6073]),0},
-{"brainpoolP512r1","brainpoolP512r1",NID_brainpoolP512r1,9,
-	&(lvalues[6082]),0},
-{"brainpoolP512t1","brainpoolP512t1",NID_brainpoolP512t1,9,
-	&(lvalues[6091]),0},
-{"PSPECIFIED","pSpecified",NID_pSpecified,9,&(lvalues[6100]),0},
-{"dhSinglePass-stdDH-sha1kdf-scheme",
-	"dhSinglePass-stdDH-sha1kdf-scheme",
-	NID_dhSinglePass_stdDH_sha1kdf_scheme,9,&(lvalues[6109]),0},
-{"dhSinglePass-stdDH-sha224kdf-scheme",
-	"dhSinglePass-stdDH-sha224kdf-scheme",
-	NID_dhSinglePass_stdDH_sha224kdf_scheme,6,&(lvalues[6118]),0},
-{"dhSinglePass-stdDH-sha256kdf-scheme",
-	"dhSinglePass-stdDH-sha256kdf-scheme",
-	NID_dhSinglePass_stdDH_sha256kdf_scheme,6,&(lvalues[6124]),0},
-{"dhSinglePass-stdDH-sha384kdf-scheme",
-	"dhSinglePass-stdDH-sha384kdf-scheme",
-	NID_dhSinglePass_stdDH_sha384kdf_scheme,6,&(lvalues[6130]),0},
-{"dhSinglePass-stdDH-sha512kdf-scheme",
-	"dhSinglePass-stdDH-sha512kdf-scheme",
-	NID_dhSinglePass_stdDH_sha512kdf_scheme,6,&(lvalues[6136]),0},
-{"dhSinglePass-cofactorDH-sha1kdf-scheme",
-	"dhSinglePass-cofactorDH-sha1kdf-scheme",
-	NID_dhSinglePass_cofactorDH_sha1kdf_scheme,9,&(lvalues[6142]),0},
-{"dhSinglePass-cofactorDH-sha224kdf-scheme",
-	"dhSinglePass-cofactorDH-sha224kdf-scheme",
-	NID_dhSinglePass_cofactorDH_sha224kdf_scheme,6,&(lvalues[6151]),0},
-{"dhSinglePass-cofactorDH-sha256kdf-scheme",
-	"dhSinglePass-cofactorDH-sha256kdf-scheme",
-	NID_dhSinglePass_cofactorDH_sha256kdf_scheme,6,&(lvalues[6157]),0},
-{"dhSinglePass-cofactorDH-sha384kdf-scheme",
-	"dhSinglePass-cofactorDH-sha384kdf-scheme",
-	NID_dhSinglePass_cofactorDH_sha384kdf_scheme,6,&(lvalues[6163]),0},
-{"dhSinglePass-cofactorDH-sha512kdf-scheme",
-	"dhSinglePass-cofactorDH-sha512kdf-scheme",
-	NID_dhSinglePass_cofactorDH_sha512kdf_scheme,6,&(lvalues[6169]),0},
-{"dh-std-kdf","dh-std-kdf",NID_dh_std_kdf,0,NULL,0},
-{"dh-cofactor-kdf","dh-cofactor-kdf",NID_dh_cofactor_kdf,0,NULL,0},
-{"X25519","x25519",NID_x25519,0,NULL,0},
+static const ASN1_OBJECT kObjects[NUM_NID] = {
+    {"UNDEF", "undefined", NID_undef, 0, NULL, 0},
+    {"rsadsi", "RSA Data Security, Inc.", NID_rsadsi, 6, &kObjectData[0], 0},
+    {"pkcs", "RSA Data Security, Inc. PKCS", NID_pkcs, 7, &kObjectData[6], 0},
+    {"MD2", "md2", NID_md2, 8, &kObjectData[13], 0},
+    {"MD5", "md5", NID_md5, 8, &kObjectData[21], 0},
+    {"RC4", "rc4", NID_rc4, 8, &kObjectData[29], 0},
+    {"rsaEncryption", "rsaEncryption", NID_rsaEncryption, 9, &kObjectData[37],
+     0},
+    {"RSA-MD2", "md2WithRSAEncryption", NID_md2WithRSAEncryption, 9,
+     &kObjectData[46], 0},
+    {"RSA-MD5", "md5WithRSAEncryption", NID_md5WithRSAEncryption, 9,
+     &kObjectData[55], 0},
+    {"PBE-MD2-DES", "pbeWithMD2AndDES-CBC", NID_pbeWithMD2AndDES_CBC, 9,
+     &kObjectData[64], 0},
+    {"PBE-MD5-DES", "pbeWithMD5AndDES-CBC", NID_pbeWithMD5AndDES_CBC, 9,
+     &kObjectData[73], 0},
+    {"X500", "directory services (X.500)", NID_X500, 1, &kObjectData[82], 0},
+    {"X509", "X509", NID_X509, 2, &kObjectData[83], 0},
+    {"CN", "commonName", NID_commonName, 3, &kObjectData[85], 0},
+    {"C", "countryName", NID_countryName, 3, &kObjectData[88], 0},
+    {"L", "localityName", NID_localityName, 3, &kObjectData[91], 0},
+    {"ST", "stateOrProvinceName", NID_stateOrProvinceName, 3, &kObjectData[94],
+     0},
+    {"O", "organizationName", NID_organizationName, 3, &kObjectData[97], 0},
+    {"OU", "organizationalUnitName", NID_organizationalUnitName, 3,
+     &kObjectData[100], 0},
+    {"RSA", "rsa", NID_rsa, 4, &kObjectData[103], 0},
+    {"pkcs7", "pkcs7", NID_pkcs7, 8, &kObjectData[107], 0},
+    {"pkcs7-data", "pkcs7-data", NID_pkcs7_data, 9, &kObjectData[115], 0},
+    {"pkcs7-signedData", "pkcs7-signedData", NID_pkcs7_signed, 9,
+     &kObjectData[124], 0},
+    {"pkcs7-envelopedData", "pkcs7-envelopedData", NID_pkcs7_enveloped, 9,
+     &kObjectData[133], 0},
+    {"pkcs7-signedAndEnvelopedData", "pkcs7-signedAndEnvelopedData",
+     NID_pkcs7_signedAndEnveloped, 9, &kObjectData[142], 0},
+    {"pkcs7-digestData", "pkcs7-digestData", NID_pkcs7_digest, 9,
+     &kObjectData[151], 0},
+    {"pkcs7-encryptedData", "pkcs7-encryptedData", NID_pkcs7_encrypted, 9,
+     &kObjectData[160], 0},
+    {"pkcs3", "pkcs3", NID_pkcs3, 8, &kObjectData[169], 0},
+    {"dhKeyAgreement", "dhKeyAgreement", NID_dhKeyAgreement, 9,
+     &kObjectData[177], 0},
+    {"DES-ECB", "des-ecb", NID_des_ecb, 5, &kObjectData[186], 0},
+    {"DES-CFB", "des-cfb", NID_des_cfb64, 5, &kObjectData[191], 0},
+    {"DES-CBC", "des-cbc", NID_des_cbc, 5, &kObjectData[196], 0},
+    {"DES-EDE", "des-ede", NID_des_ede_ecb, 5, &kObjectData[201], 0},
+    {"DES-EDE3", "des-ede3", NID_des_ede3_ecb, 0, NULL, 0},
+    {"IDEA-CBC", "idea-cbc", NID_idea_cbc, 11, &kObjectData[206], 0},
+    {"IDEA-CFB", "idea-cfb", NID_idea_cfb64, 0, NULL, 0},
+    {"IDEA-ECB", "idea-ecb", NID_idea_ecb, 0, NULL, 0},
+    {"RC2-CBC", "rc2-cbc", NID_rc2_cbc, 8, &kObjectData[217], 0},
+    {"RC2-ECB", "rc2-ecb", NID_rc2_ecb, 0, NULL, 0},
+    {"RC2-CFB", "rc2-cfb", NID_rc2_cfb64, 0, NULL, 0},
+    {"RC2-OFB", "rc2-ofb", NID_rc2_ofb64, 0, NULL, 0},
+    {"SHA", "sha", NID_sha, 5, &kObjectData[225], 0},
+    {"RSA-SHA", "shaWithRSAEncryption", NID_shaWithRSAEncryption, 5,
+     &kObjectData[230], 0},
+    {"DES-EDE-CBC", "des-ede-cbc", NID_des_ede_cbc, 0, NULL, 0},
+    {"DES-EDE3-CBC", "des-ede3-cbc", NID_des_ede3_cbc, 8, &kObjectData[235], 0},
+    {"DES-OFB", "des-ofb", NID_des_ofb64, 5, &kObjectData[243], 0},
+    {"IDEA-OFB", "idea-ofb", NID_idea_ofb64, 0, NULL, 0},
+    {"pkcs9", "pkcs9", NID_pkcs9, 8, &kObjectData[248], 0},
+    {"emailAddress", "emailAddress", NID_pkcs9_emailAddress, 9,
+     &kObjectData[256], 0},
+    {"unstructuredName", "unstructuredName", NID_pkcs9_unstructuredName, 9,
+     &kObjectData[265], 0},
+    {"contentType", "contentType", NID_pkcs9_contentType, 9, &kObjectData[274],
+     0},
+    {"messageDigest", "messageDigest", NID_pkcs9_messageDigest, 9,
+     &kObjectData[283], 0},
+    {"signingTime", "signingTime", NID_pkcs9_signingTime, 9, &kObjectData[292],
+     0},
+    {"countersignature", "countersignature", NID_pkcs9_countersignature, 9,
+     &kObjectData[301], 0},
+    {"challengePassword", "challengePassword", NID_pkcs9_challengePassword, 9,
+     &kObjectData[310], 0},
+    {"unstructuredAddress", "unstructuredAddress",
+     NID_pkcs9_unstructuredAddress, 9, &kObjectData[319], 0},
+    {"extendedCertificateAttributes", "extendedCertificateAttributes",
+     NID_pkcs9_extCertAttributes, 9, &kObjectData[328], 0},
+    {"Netscape", "Netscape Communications Corp.", NID_netscape, 7,
+     &kObjectData[337], 0},
+    {"nsCertExt", "Netscape Certificate Extension", NID_netscape_cert_extension,
+     8, &kObjectData[344], 0},
+    {"nsDataType", "Netscape Data Type", NID_netscape_data_type, 8,
+     &kObjectData[352], 0},
+    {"DES-EDE-CFB", "des-ede-cfb", NID_des_ede_cfb64, 0, NULL, 0},
+    {"DES-EDE3-CFB", "des-ede3-cfb", NID_des_ede3_cfb64, 0, NULL, 0},
+    {"DES-EDE-OFB", "des-ede-ofb", NID_des_ede_ofb64, 0, NULL, 0},
+    {"DES-EDE3-OFB", "des-ede3-ofb", NID_des_ede3_ofb64, 0, NULL, 0},
+    {"SHA1", "sha1", NID_sha1, 5, &kObjectData[360], 0},
+    {"RSA-SHA1", "sha1WithRSAEncryption", NID_sha1WithRSAEncryption, 9,
+     &kObjectData[365], 0},
+    {"DSA-SHA", "dsaWithSHA", NID_dsaWithSHA, 5, &kObjectData[374], 0},
+    {"DSA-old", "dsaEncryption-old", NID_dsa_2, 5, &kObjectData[379], 0},
+    {"PBE-SHA1-RC2-64", "pbeWithSHA1AndRC2-CBC", NID_pbeWithSHA1AndRC2_CBC, 9,
+     &kObjectData[384], 0},
+    {"PBKDF2", "PBKDF2", NID_id_pbkdf2, 9, &kObjectData[393], 0},
+    {"DSA-SHA1-old", "dsaWithSHA1-old", NID_dsaWithSHA1_2, 5, &kObjectData[402],
+     0},
+    {"nsCertType", "Netscape Cert Type", NID_netscape_cert_type, 9,
+     &kObjectData[407], 0},
+    {"nsBaseUrl", "Netscape Base Url", NID_netscape_base_url, 9,
+     &kObjectData[416], 0},
+    {"nsRevocationUrl", "Netscape Revocation Url", NID_netscape_revocation_url,
+     9, &kObjectData[425], 0},
+    {"nsCaRevocationUrl", "Netscape CA Revocation Url",
+     NID_netscape_ca_revocation_url, 9, &kObjectData[434], 0},
+    {"nsRenewalUrl", "Netscape Renewal Url", NID_netscape_renewal_url, 9,
+     &kObjectData[443], 0},
+    {"nsCaPolicyUrl", "Netscape CA Policy Url", NID_netscape_ca_policy_url, 9,
+     &kObjectData[452], 0},
+    {"nsSslServerName", "Netscape SSL Server Name",
+     NID_netscape_ssl_server_name, 9, &kObjectData[461], 0},
+    {"nsComment", "Netscape Comment", NID_netscape_comment, 9,
+     &kObjectData[470], 0},
+    {"nsCertSequence", "Netscape Certificate Sequence",
+     NID_netscape_cert_sequence, 9, &kObjectData[479], 0},
+    {"DESX-CBC", "desx-cbc", NID_desx_cbc, 0, NULL, 0},
+    {"id-ce", "id-ce", NID_id_ce, 2, &kObjectData[488], 0},
+    {"subjectKeyIdentifier", "X509v3 Subject Key Identifier",
+     NID_subject_key_identifier, 3, &kObjectData[490], 0},
+    {"keyUsage", "X509v3 Key Usage", NID_key_usage, 3, &kObjectData[493], 0},
+    {"privateKeyUsagePeriod", "X509v3 Private Key Usage Period",
+     NID_private_key_usage_period, 3, &kObjectData[496], 0},
+    {"subjectAltName", "X509v3 Subject Alternative Name", NID_subject_alt_name,
+     3, &kObjectData[499], 0},
+    {"issuerAltName", "X509v3 Issuer Alternative Name", NID_issuer_alt_name, 3,
+     &kObjectData[502], 0},
+    {"basicConstraints", "X509v3 Basic Constraints", NID_basic_constraints, 3,
+     &kObjectData[505], 0},
+    {"crlNumber", "X509v3 CRL Number", NID_crl_number, 3, &kObjectData[508], 0},
+    {"certificatePolicies", "X509v3 Certificate Policies",
+     NID_certificate_policies, 3, &kObjectData[511], 0},
+    {"authorityKeyIdentifier", "X509v3 Authority Key Identifier",
+     NID_authority_key_identifier, 3, &kObjectData[514], 0},
+    {"BF-CBC", "bf-cbc", NID_bf_cbc, 9, &kObjectData[517], 0},
+    {"BF-ECB", "bf-ecb", NID_bf_ecb, 0, NULL, 0},
+    {"BF-CFB", "bf-cfb", NID_bf_cfb64, 0, NULL, 0},
+    {"BF-OFB", "bf-ofb", NID_bf_ofb64, 0, NULL, 0},
+    {"MDC2", "mdc2", NID_mdc2, 4, &kObjectData[526], 0},
+    {"RSA-MDC2", "mdc2WithRSA", NID_mdc2WithRSA, 4, &kObjectData[530], 0},
+    {"RC4-40", "rc4-40", NID_rc4_40, 0, NULL, 0},
+    {"RC2-40-CBC", "rc2-40-cbc", NID_rc2_40_cbc, 0, NULL, 0},
+    {"GN", "givenName", NID_givenName, 3, &kObjectData[534], 0},
+    {"SN", "surname", NID_surname, 3, &kObjectData[537], 0},
+    {"initials", "initials", NID_initials, 3, &kObjectData[540], 0},
+    {NULL, NULL, NID_undef, 0, NULL, 0},
+    {"crlDistributionPoints", "X509v3 CRL Distribution Points",
+     NID_crl_distribution_points, 3, &kObjectData[543], 0},
+    {"RSA-NP-MD5", "md5WithRSA", NID_md5WithRSA, 5, &kObjectData[546], 0},
+    {"serialNumber", "serialNumber", NID_serialNumber, 3, &kObjectData[551], 0},
+    {"title", "title", NID_title, 3, &kObjectData[554], 0},
+    {"description", "description", NID_description, 3, &kObjectData[557], 0},
+    {"CAST5-CBC", "cast5-cbc", NID_cast5_cbc, 9, &kObjectData[560], 0},
+    {"CAST5-ECB", "cast5-ecb", NID_cast5_ecb, 0, NULL, 0},
+    {"CAST5-CFB", "cast5-cfb", NID_cast5_cfb64, 0, NULL, 0},
+    {"CAST5-OFB", "cast5-ofb", NID_cast5_ofb64, 0, NULL, 0},
+    {"pbeWithMD5AndCast5CBC", "pbeWithMD5AndCast5CBC",
+     NID_pbeWithMD5AndCast5_CBC, 9, &kObjectData[569], 0},
+    {"DSA-SHA1", "dsaWithSHA1", NID_dsaWithSHA1, 7, &kObjectData[578], 0},
+    {"MD5-SHA1", "md5-sha1", NID_md5_sha1, 0, NULL, 0},
+    {"RSA-SHA1-2", "sha1WithRSA", NID_sha1WithRSA, 5, &kObjectData[585], 0},
+    {"DSA", "dsaEncryption", NID_dsa, 7, &kObjectData[590], 0},
+    {"RIPEMD160", "ripemd160", NID_ripemd160, 5, &kObjectData[597], 0},
+    {NULL, NULL, NID_undef, 0, NULL, 0},
+    {"RSA-RIPEMD160", "ripemd160WithRSA", NID_ripemd160WithRSA, 6,
+     &kObjectData[602], 0},
+    {"RC5-CBC", "rc5-cbc", NID_rc5_cbc, 8, &kObjectData[608], 0},
+    {"RC5-ECB", "rc5-ecb", NID_rc5_ecb, 0, NULL, 0},
+    {"RC5-CFB", "rc5-cfb", NID_rc5_cfb64, 0, NULL, 0},
+    {"RC5-OFB", "rc5-ofb", NID_rc5_ofb64, 0, NULL, 0},
+    {NULL, NULL, NID_undef, 0, NULL, 0},
+    {"ZLIB", "zlib compression", NID_zlib_compression, 11, &kObjectData[616],
+     0},
+    {"extendedKeyUsage", "X509v3 Extended Key Usage", NID_ext_key_usage, 3,
+     &kObjectData[627], 0},
+    {"PKIX", "PKIX", NID_id_pkix, 6, &kObjectData[630], 0},
+    {"id-kp", "id-kp", NID_id_kp, 7, &kObjectData[636], 0},
+    {"serverAuth", "TLS Web Server Authentication", NID_server_auth, 8,
+     &kObjectData[643], 0},
+    {"clientAuth", "TLS Web Client Authentication", NID_client_auth, 8,
+     &kObjectData[651], 0},
+    {"codeSigning", "Code Signing", NID_code_sign, 8, &kObjectData[659], 0},
+    {"emailProtection", "E-mail Protection", NID_email_protect, 8,
+     &kObjectData[667], 0},
+    {"timeStamping", "Time Stamping", NID_time_stamp, 8, &kObjectData[675], 0},
+    {"msCodeInd", "Microsoft Individual Code Signing", NID_ms_code_ind, 10,
+     &kObjectData[683], 0},
+    {"msCodeCom", "Microsoft Commercial Code Signing", NID_ms_code_com, 10,
+     &kObjectData[693], 0},
+    {"msCTLSign", "Microsoft Trust List Signing", NID_ms_ctl_sign, 10,
+     &kObjectData[703], 0},
+    {"msSGC", "Microsoft Server Gated Crypto", NID_ms_sgc, 10,
+     &kObjectData[713], 0},
+    {"msEFS", "Microsoft Encrypted File System", NID_ms_efs, 10,
+     &kObjectData[723], 0},
+    {"nsSGC", "Netscape Server Gated Crypto", NID_ns_sgc, 9, &kObjectData[733],
+     0},
+    {"deltaCRL", "X509v3 Delta CRL Indicator", NID_delta_crl, 3,
+     &kObjectData[742], 0},
+    {"CRLReason", "X509v3 CRL Reason Code", NID_crl_reason, 3,
+     &kObjectData[745], 0},
+    {"invalidityDate", "Invalidity Date", NID_invalidity_date, 3,
+     &kObjectData[748], 0},
+    {"SXNetID", "Strong Extranet ID", NID_sxnet, 5, &kObjectData[751], 0},
+    {"PBE-SHA1-RC4-128", "pbeWithSHA1And128BitRC4",
+     NID_pbe_WithSHA1And128BitRC4, 10, &kObjectData[756], 0},
+    {"PBE-SHA1-RC4-40", "pbeWithSHA1And40BitRC4", NID_pbe_WithSHA1And40BitRC4,
+     10, &kObjectData[766], 0},
+    {"PBE-SHA1-3DES", "pbeWithSHA1And3-KeyTripleDES-CBC",
+     NID_pbe_WithSHA1And3_Key_TripleDES_CBC, 10, &kObjectData[776], 0},
+    {"PBE-SHA1-2DES", "pbeWithSHA1And2-KeyTripleDES-CBC",
+     NID_pbe_WithSHA1And2_Key_TripleDES_CBC, 10, &kObjectData[786], 0},
+    {"PBE-SHA1-RC2-128", "pbeWithSHA1And128BitRC2-CBC",
+     NID_pbe_WithSHA1And128BitRC2_CBC, 10, &kObjectData[796], 0},
+    {"PBE-SHA1-RC2-40", "pbeWithSHA1And40BitRC2-CBC",
+     NID_pbe_WithSHA1And40BitRC2_CBC, 10, &kObjectData[806], 0},
+    {"keyBag", "keyBag", NID_keyBag, 11, &kObjectData[816], 0},
+    {"pkcs8ShroudedKeyBag", "pkcs8ShroudedKeyBag", NID_pkcs8ShroudedKeyBag, 11,
+     &kObjectData[827], 0},
+    {"certBag", "certBag", NID_certBag, 11, &kObjectData[838], 0},
+    {"crlBag", "crlBag", NID_crlBag, 11, &kObjectData[849], 0},
+    {"secretBag", "secretBag", NID_secretBag, 11, &kObjectData[860], 0},
+    {"safeContentsBag", "safeContentsBag", NID_safeContentsBag, 11,
+     &kObjectData[871], 0},
+    {"friendlyName", "friendlyName", NID_friendlyName, 9, &kObjectData[882], 0},
+    {"localKeyID", "localKeyID", NID_localKeyID, 9, &kObjectData[891], 0},
+    {"x509Certificate", "x509Certificate", NID_x509Certificate, 10,
+     &kObjectData[900], 0},
+    {"sdsiCertificate", "sdsiCertificate", NID_sdsiCertificate, 10,
+     &kObjectData[910], 0},
+    {"x509Crl", "x509Crl", NID_x509Crl, 10, &kObjectData[920], 0},
+    {"PBES2", "PBES2", NID_pbes2, 9, &kObjectData[930], 0},
+    {"PBMAC1", "PBMAC1", NID_pbmac1, 9, &kObjectData[939], 0},
+    {"hmacWithSHA1", "hmacWithSHA1", NID_hmacWithSHA1, 8, &kObjectData[948], 0},
+    {"id-qt-cps", "Policy Qualifier CPS", NID_id_qt_cps, 8, &kObjectData[956],
+     0},
+    {"id-qt-unotice", "Policy Qualifier User Notice", NID_id_qt_unotice, 8,
+     &kObjectData[964], 0},
+    {"RC2-64-CBC", "rc2-64-cbc", NID_rc2_64_cbc, 0, NULL, 0},
+    {"SMIME-CAPS", "S/MIME Capabilities", NID_SMIMECapabilities, 9,
+     &kObjectData[972], 0},
+    {"PBE-MD2-RC2-64", "pbeWithMD2AndRC2-CBC", NID_pbeWithMD2AndRC2_CBC, 9,
+     &kObjectData[981], 0},
+    {"PBE-MD5-RC2-64", "pbeWithMD5AndRC2-CBC", NID_pbeWithMD5AndRC2_CBC, 9,
+     &kObjectData[990], 0},
+    {"PBE-SHA1-DES", "pbeWithSHA1AndDES-CBC", NID_pbeWithSHA1AndDES_CBC, 9,
+     &kObjectData[999], 0},
+    {"msExtReq", "Microsoft Extension Request", NID_ms_ext_req, 10,
+     &kObjectData[1008], 0},
+    {"extReq", "Extension Request", NID_ext_req, 9, &kObjectData[1018], 0},
+    {"name", "name", NID_name, 3, &kObjectData[1027], 0},
+    {"dnQualifier", "dnQualifier", NID_dnQualifier, 3, &kObjectData[1030], 0},
+    {"id-pe", "id-pe", NID_id_pe, 7, &kObjectData[1033], 0},
+    {"id-ad", "id-ad", NID_id_ad, 7, &kObjectData[1040], 0},
+    {"authorityInfoAccess", "Authority Information Access", NID_info_access, 8,
+     &kObjectData[1047], 0},
+    {"OCSP", "OCSP", NID_ad_OCSP, 8, &kObjectData[1055], 0},
+    {"caIssuers", "CA Issuers", NID_ad_ca_issuers, 8, &kObjectData[1063], 0},
+    {"OCSPSigning", "OCSP Signing", NID_OCSP_sign, 8, &kObjectData[1071], 0},
+    {"ISO", "iso", NID_iso, 0, NULL, 0},
+    {"member-body", "ISO Member Body", NID_member_body, 1, &kObjectData[1079],
+     0},
+    {"ISO-US", "ISO US Member Body", NID_ISO_US, 3, &kObjectData[1080], 0},
+    {"X9-57", "X9.57", NID_X9_57, 5, &kObjectData[1083], 0},
+    {"X9cm", "X9.57 CM ?", NID_X9cm, 6, &kObjectData[1088], 0},
+    {"pkcs1", "pkcs1", NID_pkcs1, 8, &kObjectData[1094], 0},
+    {"pkcs5", "pkcs5", NID_pkcs5, 8, &kObjectData[1102], 0},
+    {"SMIME", "S/MIME", NID_SMIME, 9, &kObjectData[1110], 0},
+    {"id-smime-mod", "id-smime-mod", NID_id_smime_mod, 10, &kObjectData[1119],
+     0},
+    {"id-smime-ct", "id-smime-ct", NID_id_smime_ct, 10, &kObjectData[1129], 0},
+    {"id-smime-aa", "id-smime-aa", NID_id_smime_aa, 10, &kObjectData[1139], 0},
+    {"id-smime-alg", "id-smime-alg", NID_id_smime_alg, 10, &kObjectData[1149],
+     0},
+    {"id-smime-cd", "id-smime-cd", NID_id_smime_cd, 10, &kObjectData[1159], 0},
+    {"id-smime-spq", "id-smime-spq", NID_id_smime_spq, 10, &kObjectData[1169],
+     0},
+    {"id-smime-cti", "id-smime-cti", NID_id_smime_cti, 10, &kObjectData[1179],
+     0},
+    {"id-smime-mod-cms", "id-smime-mod-cms", NID_id_smime_mod_cms, 11,
+     &kObjectData[1189], 0},
+    {"id-smime-mod-ess", "id-smime-mod-ess", NID_id_smime_mod_ess, 11,
+     &kObjectData[1200], 0},
+    {"id-smime-mod-oid", "id-smime-mod-oid", NID_id_smime_mod_oid, 11,
+     &kObjectData[1211], 0},
+    {"id-smime-mod-msg-v3", "id-smime-mod-msg-v3", NID_id_smime_mod_msg_v3, 11,
+     &kObjectData[1222], 0},
+    {"id-smime-mod-ets-eSignature-88", "id-smime-mod-ets-eSignature-88",
+     NID_id_smime_mod_ets_eSignature_88, 11, &kObjectData[1233], 0},
+    {"id-smime-mod-ets-eSignature-97", "id-smime-mod-ets-eSignature-97",
+     NID_id_smime_mod_ets_eSignature_97, 11, &kObjectData[1244], 0},
+    {"id-smime-mod-ets-eSigPolicy-88", "id-smime-mod-ets-eSigPolicy-88",
+     NID_id_smime_mod_ets_eSigPolicy_88, 11, &kObjectData[1255], 0},
+    {"id-smime-mod-ets-eSigPolicy-97", "id-smime-mod-ets-eSigPolicy-97",
+     NID_id_smime_mod_ets_eSigPolicy_97, 11, &kObjectData[1266], 0},
+    {"id-smime-ct-receipt", "id-smime-ct-receipt", NID_id_smime_ct_receipt, 11,
+     &kObjectData[1277], 0},
+    {"id-smime-ct-authData", "id-smime-ct-authData", NID_id_smime_ct_authData,
+     11, &kObjectData[1288], 0},
+    {"id-smime-ct-publishCert", "id-smime-ct-publishCert",
+     NID_id_smime_ct_publishCert, 11, &kObjectData[1299], 0},
+    {"id-smime-ct-TSTInfo", "id-smime-ct-TSTInfo", NID_id_smime_ct_TSTInfo, 11,
+     &kObjectData[1310], 0},
+    {"id-smime-ct-TDTInfo", "id-smime-ct-TDTInfo", NID_id_smime_ct_TDTInfo, 11,
+     &kObjectData[1321], 0},
+    {"id-smime-ct-contentInfo", "id-smime-ct-contentInfo",
+     NID_id_smime_ct_contentInfo, 11, &kObjectData[1332], 0},
+    {"id-smime-ct-DVCSRequestData", "id-smime-ct-DVCSRequestData",
+     NID_id_smime_ct_DVCSRequestData, 11, &kObjectData[1343], 0},
+    {"id-smime-ct-DVCSResponseData", "id-smime-ct-DVCSResponseData",
+     NID_id_smime_ct_DVCSResponseData, 11, &kObjectData[1354], 0},
+    {"id-smime-aa-receiptRequest", "id-smime-aa-receiptRequest",
+     NID_id_smime_aa_receiptRequest, 11, &kObjectData[1365], 0},
+    {"id-smime-aa-securityLabel", "id-smime-aa-securityLabel",
+     NID_id_smime_aa_securityLabel, 11, &kObjectData[1376], 0},
+    {"id-smime-aa-mlExpandHistory", "id-smime-aa-mlExpandHistory",
+     NID_id_smime_aa_mlExpandHistory, 11, &kObjectData[1387], 0},
+    {"id-smime-aa-contentHint", "id-smime-aa-contentHint",
+     NID_id_smime_aa_contentHint, 11, &kObjectData[1398], 0},
+    {"id-smime-aa-msgSigDigest", "id-smime-aa-msgSigDigest",
+     NID_id_smime_aa_msgSigDigest, 11, &kObjectData[1409], 0},
+    {"id-smime-aa-encapContentType", "id-smime-aa-encapContentType",
+     NID_id_smime_aa_encapContentType, 11, &kObjectData[1420], 0},
+    {"id-smime-aa-contentIdentifier", "id-smime-aa-contentIdentifier",
+     NID_id_smime_aa_contentIdentifier, 11, &kObjectData[1431], 0},
+    {"id-smime-aa-macValue", "id-smime-aa-macValue", NID_id_smime_aa_macValue,
+     11, &kObjectData[1442], 0},
+    {"id-smime-aa-equivalentLabels", "id-smime-aa-equivalentLabels",
+     NID_id_smime_aa_equivalentLabels, 11, &kObjectData[1453], 0},
+    {"id-smime-aa-contentReference", "id-smime-aa-contentReference",
+     NID_id_smime_aa_contentReference, 11, &kObjectData[1464], 0},
+    {"id-smime-aa-encrypKeyPref", "id-smime-aa-encrypKeyPref",
+     NID_id_smime_aa_encrypKeyPref, 11, &kObjectData[1475], 0},
+    {"id-smime-aa-signingCertificate", "id-smime-aa-signingCertificate",
+     NID_id_smime_aa_signingCertificate, 11, &kObjectData[1486], 0},
+    {"id-smime-aa-smimeEncryptCerts", "id-smime-aa-smimeEncryptCerts",
+     NID_id_smime_aa_smimeEncryptCerts, 11, &kObjectData[1497], 0},
+    {"id-smime-aa-timeStampToken", "id-smime-aa-timeStampToken",
+     NID_id_smime_aa_timeStampToken, 11, &kObjectData[1508], 0},
+    {"id-smime-aa-ets-sigPolicyId", "id-smime-aa-ets-sigPolicyId",
+     NID_id_smime_aa_ets_sigPolicyId, 11, &kObjectData[1519], 0},
+    {"id-smime-aa-ets-commitmentType", "id-smime-aa-ets-commitmentType",
+     NID_id_smime_aa_ets_commitmentType, 11, &kObjectData[1530], 0},
+    {"id-smime-aa-ets-signerLocation", "id-smime-aa-ets-signerLocation",
+     NID_id_smime_aa_ets_signerLocation, 11, &kObjectData[1541], 0},
+    {"id-smime-aa-ets-signerAttr", "id-smime-aa-ets-signerAttr",
+     NID_id_smime_aa_ets_signerAttr, 11, &kObjectData[1552], 0},
+    {"id-smime-aa-ets-otherSigCert", "id-smime-aa-ets-otherSigCert",
+     NID_id_smime_aa_ets_otherSigCert, 11, &kObjectData[1563], 0},
+    {"id-smime-aa-ets-contentTimestamp", "id-smime-aa-ets-contentTimestamp",
+     NID_id_smime_aa_ets_contentTimestamp, 11, &kObjectData[1574], 0},
+    {"id-smime-aa-ets-CertificateRefs", "id-smime-aa-ets-CertificateRefs",
+     NID_id_smime_aa_ets_CertificateRefs, 11, &kObjectData[1585], 0},
+    {"id-smime-aa-ets-RevocationRefs", "id-smime-aa-ets-RevocationRefs",
+     NID_id_smime_aa_ets_RevocationRefs, 11, &kObjectData[1596], 0},
+    {"id-smime-aa-ets-certValues", "id-smime-aa-ets-certValues",
+     NID_id_smime_aa_ets_certValues, 11, &kObjectData[1607], 0},
+    {"id-smime-aa-ets-revocationValues", "id-smime-aa-ets-revocationValues",
+     NID_id_smime_aa_ets_revocationValues, 11, &kObjectData[1618], 0},
+    {"id-smime-aa-ets-escTimeStamp", "id-smime-aa-ets-escTimeStamp",
+     NID_id_smime_aa_ets_escTimeStamp, 11, &kObjectData[1629], 0},
+    {"id-smime-aa-ets-certCRLTimestamp", "id-smime-aa-ets-certCRLTimestamp",
+     NID_id_smime_aa_ets_certCRLTimestamp, 11, &kObjectData[1640], 0},
+    {"id-smime-aa-ets-archiveTimeStamp", "id-smime-aa-ets-archiveTimeStamp",
+     NID_id_smime_aa_ets_archiveTimeStamp, 11, &kObjectData[1651], 0},
+    {"id-smime-aa-signatureType", "id-smime-aa-signatureType",
+     NID_id_smime_aa_signatureType, 11, &kObjectData[1662], 0},
+    {"id-smime-aa-dvcs-dvc", "id-smime-aa-dvcs-dvc", NID_id_smime_aa_dvcs_dvc,
+     11, &kObjectData[1673], 0},
+    {"id-smime-alg-ESDHwith3DES", "id-smime-alg-ESDHwith3DES",
+     NID_id_smime_alg_ESDHwith3DES, 11, &kObjectData[1684], 0},
+    {"id-smime-alg-ESDHwithRC2", "id-smime-alg-ESDHwithRC2",
+     NID_id_smime_alg_ESDHwithRC2, 11, &kObjectData[1695], 0},
+    {"id-smime-alg-3DESwrap", "id-smime-alg-3DESwrap",
+     NID_id_smime_alg_3DESwrap, 11, &kObjectData[1706], 0},
+    {"id-smime-alg-RC2wrap", "id-smime-alg-RC2wrap", NID_id_smime_alg_RC2wrap,
+     11, &kObjectData[1717], 0},
+    {"id-smime-alg-ESDH", "id-smime-alg-ESDH", NID_id_smime_alg_ESDH, 11,
+     &kObjectData[1728], 0},
+    {"id-smime-alg-CMS3DESwrap", "id-smime-alg-CMS3DESwrap",
+     NID_id_smime_alg_CMS3DESwrap, 11, &kObjectData[1739], 0},
+    {"id-smime-alg-CMSRC2wrap", "id-smime-alg-CMSRC2wrap",
+     NID_id_smime_alg_CMSRC2wrap, 11, &kObjectData[1750], 0},
+    {"id-smime-cd-ldap", "id-smime-cd-ldap", NID_id_smime_cd_ldap, 11,
+     &kObjectData[1761], 0},
+    {"id-smime-spq-ets-sqt-uri", "id-smime-spq-ets-sqt-uri",
+     NID_id_smime_spq_ets_sqt_uri, 11, &kObjectData[1772], 0},
+    {"id-smime-spq-ets-sqt-unotice", "id-smime-spq-ets-sqt-unotice",
+     NID_id_smime_spq_ets_sqt_unotice, 11, &kObjectData[1783], 0},
+    {"id-smime-cti-ets-proofOfOrigin", "id-smime-cti-ets-proofOfOrigin",
+     NID_id_smime_cti_ets_proofOfOrigin, 11, &kObjectData[1794], 0},
+    {"id-smime-cti-ets-proofOfReceipt", "id-smime-cti-ets-proofOfReceipt",
+     NID_id_smime_cti_ets_proofOfReceipt, 11, &kObjectData[1805], 0},
+    {"id-smime-cti-ets-proofOfDelivery", "id-smime-cti-ets-proofOfDelivery",
+     NID_id_smime_cti_ets_proofOfDelivery, 11, &kObjectData[1816], 0},
+    {"id-smime-cti-ets-proofOfSender", "id-smime-cti-ets-proofOfSender",
+     NID_id_smime_cti_ets_proofOfSender, 11, &kObjectData[1827], 0},
+    {"id-smime-cti-ets-proofOfApproval", "id-smime-cti-ets-proofOfApproval",
+     NID_id_smime_cti_ets_proofOfApproval, 11, &kObjectData[1838], 0},
+    {"id-smime-cti-ets-proofOfCreation", "id-smime-cti-ets-proofOfCreation",
+     NID_id_smime_cti_ets_proofOfCreation, 11, &kObjectData[1849], 0},
+    {"MD4", "md4", NID_md4, 8, &kObjectData[1860], 0},
+    {"id-pkix-mod", "id-pkix-mod", NID_id_pkix_mod, 7, &kObjectData[1868], 0},
+    {"id-qt", "id-qt", NID_id_qt, 7, &kObjectData[1875], 0},
+    {"id-it", "id-it", NID_id_it, 7, &kObjectData[1882], 0},
+    {"id-pkip", "id-pkip", NID_id_pkip, 7, &kObjectData[1889], 0},
+    {"id-alg", "id-alg", NID_id_alg, 7, &kObjectData[1896], 0},
+    {"id-cmc", "id-cmc", NID_id_cmc, 7, &kObjectData[1903], 0},
+    {"id-on", "id-on", NID_id_on, 7, &kObjectData[1910], 0},
+    {"id-pda", "id-pda", NID_id_pda, 7, &kObjectData[1917], 0},
+    {"id-aca", "id-aca", NID_id_aca, 7, &kObjectData[1924], 0},
+    {"id-qcs", "id-qcs", NID_id_qcs, 7, &kObjectData[1931], 0},
+    {"id-cct", "id-cct", NID_id_cct, 7, &kObjectData[1938], 0},
+    {"id-pkix1-explicit-88", "id-pkix1-explicit-88", NID_id_pkix1_explicit_88,
+     8, &kObjectData[1945], 0},
+    {"id-pkix1-implicit-88", "id-pkix1-implicit-88", NID_id_pkix1_implicit_88,
+     8, &kObjectData[1953], 0},
+    {"id-pkix1-explicit-93", "id-pkix1-explicit-93", NID_id_pkix1_explicit_93,
+     8, &kObjectData[1961], 0},
+    {"id-pkix1-implicit-93", "id-pkix1-implicit-93", NID_id_pkix1_implicit_93,
+     8, &kObjectData[1969], 0},
+    {"id-mod-crmf", "id-mod-crmf", NID_id_mod_crmf, 8, &kObjectData[1977], 0},
+    {"id-mod-cmc", "id-mod-cmc", NID_id_mod_cmc, 8, &kObjectData[1985], 0},
+    {"id-mod-kea-profile-88", "id-mod-kea-profile-88",
+     NID_id_mod_kea_profile_88, 8, &kObjectData[1993], 0},
+    {"id-mod-kea-profile-93", "id-mod-kea-profile-93",
+     NID_id_mod_kea_profile_93, 8, &kObjectData[2001], 0},
+    {"id-mod-cmp", "id-mod-cmp", NID_id_mod_cmp, 8, &kObjectData[2009], 0},
+    {"id-mod-qualified-cert-88", "id-mod-qualified-cert-88",
+     NID_id_mod_qualified_cert_88, 8, &kObjectData[2017], 0},
+    {"id-mod-qualified-cert-93", "id-mod-qualified-cert-93",
+     NID_id_mod_qualified_cert_93, 8, &kObjectData[2025], 0},
+    {"id-mod-attribute-cert", "id-mod-attribute-cert",
+     NID_id_mod_attribute_cert, 8, &kObjectData[2033], 0},
+    {"id-mod-timestamp-protocol", "id-mod-timestamp-protocol",
+     NID_id_mod_timestamp_protocol, 8, &kObjectData[2041], 0},
+    {"id-mod-ocsp", "id-mod-ocsp", NID_id_mod_ocsp, 8, &kObjectData[2049], 0},
+    {"id-mod-dvcs", "id-mod-dvcs", NID_id_mod_dvcs, 8, &kObjectData[2057], 0},
+    {"id-mod-cmp2000", "id-mod-cmp2000", NID_id_mod_cmp2000, 8,
+     &kObjectData[2065], 0},
+    {"biometricInfo", "Biometric Info", NID_biometricInfo, 8,
+     &kObjectData[2073], 0},
+    {"qcStatements", "qcStatements", NID_qcStatements, 8, &kObjectData[2081],
+     0},
+    {"ac-auditEntity", "ac-auditEntity", NID_ac_auditEntity, 8,
+     &kObjectData[2089], 0},
+    {"ac-targeting", "ac-targeting", NID_ac_targeting, 8, &kObjectData[2097],
+     0},
+    {"aaControls", "aaControls", NID_aaControls, 8, &kObjectData[2105], 0},
+    {"sbgp-ipAddrBlock", "sbgp-ipAddrBlock", NID_sbgp_ipAddrBlock, 8,
+     &kObjectData[2113], 0},
+    {"sbgp-autonomousSysNum", "sbgp-autonomousSysNum",
+     NID_sbgp_autonomousSysNum, 8, &kObjectData[2121], 0},
+    {"sbgp-routerIdentifier", "sbgp-routerIdentifier",
+     NID_sbgp_routerIdentifier, 8, &kObjectData[2129], 0},
+    {"textNotice", "textNotice", NID_textNotice, 8, &kObjectData[2137], 0},
+    {"ipsecEndSystem", "IPSec End System", NID_ipsecEndSystem, 8,
+     &kObjectData[2145], 0},
+    {"ipsecTunnel", "IPSec Tunnel", NID_ipsecTunnel, 8, &kObjectData[2153], 0},
+    {"ipsecUser", "IPSec User", NID_ipsecUser, 8, &kObjectData[2161], 0},
+    {"DVCS", "dvcs", NID_dvcs, 8, &kObjectData[2169], 0},
+    {"id-it-caProtEncCert", "id-it-caProtEncCert", NID_id_it_caProtEncCert, 8,
+     &kObjectData[2177], 0},
+    {"id-it-signKeyPairTypes", "id-it-signKeyPairTypes",
+     NID_id_it_signKeyPairTypes, 8, &kObjectData[2185], 0},
+    {"id-it-encKeyPairTypes", "id-it-encKeyPairTypes",
+     NID_id_it_encKeyPairTypes, 8, &kObjectData[2193], 0},
+    {"id-it-preferredSymmAlg", "id-it-preferredSymmAlg",
+     NID_id_it_preferredSymmAlg, 8, &kObjectData[2201], 0},
+    {"id-it-caKeyUpdateInfo", "id-it-caKeyUpdateInfo",
+     NID_id_it_caKeyUpdateInfo, 8, &kObjectData[2209], 0},
+    {"id-it-currentCRL", "id-it-currentCRL", NID_id_it_currentCRL, 8,
+     &kObjectData[2217], 0},
+    {"id-it-unsupportedOIDs", "id-it-unsupportedOIDs",
+     NID_id_it_unsupportedOIDs, 8, &kObjectData[2225], 0},
+    {"id-it-subscriptionRequest", "id-it-subscriptionRequest",
+     NID_id_it_subscriptionRequest, 8, &kObjectData[2233], 0},
+    {"id-it-subscriptionResponse", "id-it-subscriptionResponse",
+     NID_id_it_subscriptionResponse, 8, &kObjectData[2241], 0},
+    {"id-it-keyPairParamReq", "id-it-keyPairParamReq",
+     NID_id_it_keyPairParamReq, 8, &kObjectData[2249], 0},
+    {"id-it-keyPairParamRep", "id-it-keyPairParamRep",
+     NID_id_it_keyPairParamRep, 8, &kObjectData[2257], 0},
+    {"id-it-revPassphrase", "id-it-revPassphrase", NID_id_it_revPassphrase, 8,
+     &kObjectData[2265], 0},
+    {"id-it-implicitConfirm", "id-it-implicitConfirm",
+     NID_id_it_implicitConfirm, 8, &kObjectData[2273], 0},
+    {"id-it-confirmWaitTime", "id-it-confirmWaitTime",
+     NID_id_it_confirmWaitTime, 8, &kObjectData[2281], 0},
+    {"id-it-origPKIMessage", "id-it-origPKIMessage", NID_id_it_origPKIMessage,
+     8, &kObjectData[2289], 0},
+    {"id-regCtrl", "id-regCtrl", NID_id_regCtrl, 8, &kObjectData[2297], 0},
+    {"id-regInfo", "id-regInfo", NID_id_regInfo, 8, &kObjectData[2305], 0},
+    {"id-regCtrl-regToken", "id-regCtrl-regToken", NID_id_regCtrl_regToken, 9,
+     &kObjectData[2313], 0},
+    {"id-regCtrl-authenticator", "id-regCtrl-authenticator",
+     NID_id_regCtrl_authenticator, 9, &kObjectData[2322], 0},
+    {"id-regCtrl-pkiPublicationInfo", "id-regCtrl-pkiPublicationInfo",
+     NID_id_regCtrl_pkiPublicationInfo, 9, &kObjectData[2331], 0},
+    {"id-regCtrl-pkiArchiveOptions", "id-regCtrl-pkiArchiveOptions",
+     NID_id_regCtrl_pkiArchiveOptions, 9, &kObjectData[2340], 0},
+    {"id-regCtrl-oldCertID", "id-regCtrl-oldCertID", NID_id_regCtrl_oldCertID,
+     9, &kObjectData[2349], 0},
+    {"id-regCtrl-protocolEncrKey", "id-regCtrl-protocolEncrKey",
+     NID_id_regCtrl_protocolEncrKey, 9, &kObjectData[2358], 0},
+    {"id-regInfo-utf8Pairs", "id-regInfo-utf8Pairs", NID_id_regInfo_utf8Pairs,
+     9, &kObjectData[2367], 0},
+    {"id-regInfo-certReq", "id-regInfo-certReq", NID_id_regInfo_certReq, 9,
+     &kObjectData[2376], 0},
+    {"id-alg-des40", "id-alg-des40", NID_id_alg_des40, 8, &kObjectData[2385],
+     0},
+    {"id-alg-noSignature", "id-alg-noSignature", NID_id_alg_noSignature, 8,
+     &kObjectData[2393], 0},
+    {"id-alg-dh-sig-hmac-sha1", "id-alg-dh-sig-hmac-sha1",
+     NID_id_alg_dh_sig_hmac_sha1, 8, &kObjectData[2401], 0},
+    {"id-alg-dh-pop", "id-alg-dh-pop", NID_id_alg_dh_pop, 8, &kObjectData[2409],
+     0},
+    {"id-cmc-statusInfo", "id-cmc-statusInfo", NID_id_cmc_statusInfo, 8,
+     &kObjectData[2417], 0},
+    {"id-cmc-identification", "id-cmc-identification",
+     NID_id_cmc_identification, 8, &kObjectData[2425], 0},
+    {"id-cmc-identityProof", "id-cmc-identityProof", NID_id_cmc_identityProof,
+     8, &kObjectData[2433], 0},
+    {"id-cmc-dataReturn", "id-cmc-dataReturn", NID_id_cmc_dataReturn, 8,
+     &kObjectData[2441], 0},
+    {"id-cmc-transactionId", "id-cmc-transactionId", NID_id_cmc_transactionId,
+     8, &kObjectData[2449], 0},
+    {"id-cmc-senderNonce", "id-cmc-senderNonce", NID_id_cmc_senderNonce, 8,
+     &kObjectData[2457], 0},
+    {"id-cmc-recipientNonce", "id-cmc-recipientNonce",
+     NID_id_cmc_recipientNonce, 8, &kObjectData[2465], 0},
+    {"id-cmc-addExtensions", "id-cmc-addExtensions", NID_id_cmc_addExtensions,
+     8, &kObjectData[2473], 0},
+    {"id-cmc-encryptedPOP", "id-cmc-encryptedPOP", NID_id_cmc_encryptedPOP, 8,
+     &kObjectData[2481], 0},
+    {"id-cmc-decryptedPOP", "id-cmc-decryptedPOP", NID_id_cmc_decryptedPOP, 8,
+     &kObjectData[2489], 0},
+    {"id-cmc-lraPOPWitness", "id-cmc-lraPOPWitness", NID_id_cmc_lraPOPWitness,
+     8, &kObjectData[2497], 0},
+    {"id-cmc-getCert", "id-cmc-getCert", NID_id_cmc_getCert, 8,
+     &kObjectData[2505], 0},
+    {"id-cmc-getCRL", "id-cmc-getCRL", NID_id_cmc_getCRL, 8, &kObjectData[2513],
+     0},
+    {"id-cmc-revokeRequest", "id-cmc-revokeRequest", NID_id_cmc_revokeRequest,
+     8, &kObjectData[2521], 0},
+    {"id-cmc-regInfo", "id-cmc-regInfo", NID_id_cmc_regInfo, 8,
+     &kObjectData[2529], 0},
+    {"id-cmc-responseInfo", "id-cmc-responseInfo", NID_id_cmc_responseInfo, 8,
+     &kObjectData[2537], 0},
+    {"id-cmc-queryPending", "id-cmc-queryPending", NID_id_cmc_queryPending, 8,
+     &kObjectData[2545], 0},
+    {"id-cmc-popLinkRandom", "id-cmc-popLinkRandom", NID_id_cmc_popLinkRandom,
+     8, &kObjectData[2553], 0},
+    {"id-cmc-popLinkWitness", "id-cmc-popLinkWitness",
+     NID_id_cmc_popLinkWitness, 8, &kObjectData[2561], 0},
+    {"id-cmc-confirmCertAcceptance", "id-cmc-confirmCertAcceptance",
+     NID_id_cmc_confirmCertAcceptance, 8, &kObjectData[2569], 0},
+    {"id-on-personalData", "id-on-personalData", NID_id_on_personalData, 8,
+     &kObjectData[2577], 0},
+    {"id-pda-dateOfBirth", "id-pda-dateOfBirth", NID_id_pda_dateOfBirth, 8,
+     &kObjectData[2585], 0},
+    {"id-pda-placeOfBirth", "id-pda-placeOfBirth", NID_id_pda_placeOfBirth, 8,
+     &kObjectData[2593], 0},
+    {NULL, NULL, NID_undef, 0, NULL, 0},
+    {"id-pda-gender", "id-pda-gender", NID_id_pda_gender, 8, &kObjectData[2601],
+     0},
+    {"id-pda-countryOfCitizenship", "id-pda-countryOfCitizenship",
+     NID_id_pda_countryOfCitizenship, 8, &kObjectData[2609], 0},
+    {"id-pda-countryOfResidence", "id-pda-countryOfResidence",
+     NID_id_pda_countryOfResidence, 8, &kObjectData[2617], 0},
+    {"id-aca-authenticationInfo", "id-aca-authenticationInfo",
+     NID_id_aca_authenticationInfo, 8, &kObjectData[2625], 0},
+    {"id-aca-accessIdentity", "id-aca-accessIdentity",
+     NID_id_aca_accessIdentity, 8, &kObjectData[2633], 0},
+    {"id-aca-chargingIdentity", "id-aca-chargingIdentity",
+     NID_id_aca_chargingIdentity, 8, &kObjectData[2641], 0},
+    {"id-aca-group", "id-aca-group", NID_id_aca_group, 8, &kObjectData[2649],
+     0},
+    {"id-aca-role", "id-aca-role", NID_id_aca_role, 8, &kObjectData[2657], 0},
+    {"id-qcs-pkixQCSyntax-v1", "id-qcs-pkixQCSyntax-v1",
+     NID_id_qcs_pkixQCSyntax_v1, 8, &kObjectData[2665], 0},
+    {"id-cct-crs", "id-cct-crs", NID_id_cct_crs, 8, &kObjectData[2673], 0},
+    {"id-cct-PKIData", "id-cct-PKIData", NID_id_cct_PKIData, 8,
+     &kObjectData[2681], 0},
+    {"id-cct-PKIResponse", "id-cct-PKIResponse", NID_id_cct_PKIResponse, 8,
+     &kObjectData[2689], 0},
+    {"ad_timestamping", "AD Time Stamping", NID_ad_timeStamping, 8,
+     &kObjectData[2697], 0},
+    {"AD_DVCS", "ad dvcs", NID_ad_dvcs, 8, &kObjectData[2705], 0},
+    {"basicOCSPResponse", "Basic OCSP Response", NID_id_pkix_OCSP_basic, 9,
+     &kObjectData[2713], 0},
+    {"Nonce", "OCSP Nonce", NID_id_pkix_OCSP_Nonce, 9, &kObjectData[2722], 0},
+    {"CrlID", "OCSP CRL ID", NID_id_pkix_OCSP_CrlID, 9, &kObjectData[2731], 0},
+    {"acceptableResponses", "Acceptable OCSP Responses",
+     NID_id_pkix_OCSP_acceptableResponses, 9, &kObjectData[2740], 0},
+    {"noCheck", "OCSP No Check", NID_id_pkix_OCSP_noCheck, 9,
+     &kObjectData[2749], 0},
+    {"archiveCutoff", "OCSP Archive Cutoff", NID_id_pkix_OCSP_archiveCutoff, 9,
+     &kObjectData[2758], 0},
+    {"serviceLocator", "OCSP Service Locator", NID_id_pkix_OCSP_serviceLocator,
+     9, &kObjectData[2767], 0},
+    {"extendedStatus", "Extended OCSP Status", NID_id_pkix_OCSP_extendedStatus,
+     9, &kObjectData[2776], 0},
+    {"valid", "valid", NID_id_pkix_OCSP_valid, 9, &kObjectData[2785], 0},
+    {"path", "path", NID_id_pkix_OCSP_path, 9, &kObjectData[2794], 0},
+    {"trustRoot", "Trust Root", NID_id_pkix_OCSP_trustRoot, 9,
+     &kObjectData[2803], 0},
+    {"algorithm", "algorithm", NID_algorithm, 4, &kObjectData[2812], 0},
+    {"rsaSignature", "rsaSignature", NID_rsaSignature, 5, &kObjectData[2816],
+     0},
+    {"X500algorithms", "directory services - algorithms", NID_X500algorithms, 2,
+     &kObjectData[2821], 0},
+    {"ORG", "org", NID_org, 1, &kObjectData[2823], 0},
+    {"DOD", "dod", NID_dod, 2, &kObjectData[2824], 0},
+    {"IANA", "iana", NID_iana, 3, &kObjectData[2826], 0},
+    {"directory", "Directory", NID_Directory, 4, &kObjectData[2829], 0},
+    {"mgmt", "Management", NID_Management, 4, &kObjectData[2833], 0},
+    {"experimental", "Experimental", NID_Experimental, 4, &kObjectData[2837],
+     0},
+    {"private", "Private", NID_Private, 4, &kObjectData[2841], 0},
+    {"security", "Security", NID_Security, 4, &kObjectData[2845], 0},
+    {"snmpv2", "SNMPv2", NID_SNMPv2, 4, &kObjectData[2849], 0},
+    {"Mail", "Mail", NID_Mail, 4, &kObjectData[2853], 0},
+    {"enterprises", "Enterprises", NID_Enterprises, 5, &kObjectData[2857], 0},
+    {"dcobject", "dcObject", NID_dcObject, 9, &kObjectData[2862], 0},
+    {"DC", "domainComponent", NID_domainComponent, 10, &kObjectData[2871], 0},
+    {"domain", "Domain", NID_Domain, 10, &kObjectData[2881], 0},
+    {NULL, NULL, NID_undef, 0, NULL, 0},
+    {"selected-attribute-types", "Selected Attribute Types",
+     NID_selected_attribute_types, 3, &kObjectData[2891], 0},
+    {"clearance", "clearance", NID_clearance, 4, &kObjectData[2894], 0},
+    {"RSA-MD4", "md4WithRSAEncryption", NID_md4WithRSAEncryption, 9,
+     &kObjectData[2898], 0},
+    {"ac-proxying", "ac-proxying", NID_ac_proxying, 8, &kObjectData[2907], 0},
+    {"subjectInfoAccess", "Subject Information Access", NID_sinfo_access, 8,
+     &kObjectData[2915], 0},
+    {"id-aca-encAttrs", "id-aca-encAttrs", NID_id_aca_encAttrs, 8,
+     &kObjectData[2923], 0},
+    {"role", "role", NID_role, 3, &kObjectData[2931], 0},
+    {"policyConstraints", "X509v3 Policy Constraints", NID_policy_constraints,
+     3, &kObjectData[2934], 0},
+    {"targetInformation", "X509v3 AC Targeting", NID_target_information, 3,
+     &kObjectData[2937], 0},
+    {"noRevAvail", "X509v3 No Revocation Available", NID_no_rev_avail, 3,
+     &kObjectData[2940], 0},
+    {NULL, NULL, NID_undef, 0, NULL, 0},
+    {"ansi-X9-62", "ANSI X9.62", NID_ansi_X9_62, 5, &kObjectData[2943], 0},
+    {"prime-field", "prime-field", NID_X9_62_prime_field, 7, &kObjectData[2948],
+     0},
+    {"characteristic-two-field", "characteristic-two-field",
+     NID_X9_62_characteristic_two_field, 7, &kObjectData[2955], 0},
+    {"id-ecPublicKey", "id-ecPublicKey", NID_X9_62_id_ecPublicKey, 7,
+     &kObjectData[2962], 0},
+    {"prime192v1", "prime192v1", NID_X9_62_prime192v1, 8, &kObjectData[2969],
+     0},
+    {"prime192v2", "prime192v2", NID_X9_62_prime192v2, 8, &kObjectData[2977],
+     0},
+    {"prime192v3", "prime192v3", NID_X9_62_prime192v3, 8, &kObjectData[2985],
+     0},
+    {"prime239v1", "prime239v1", NID_X9_62_prime239v1, 8, &kObjectData[2993],
+     0},
+    {"prime239v2", "prime239v2", NID_X9_62_prime239v2, 8, &kObjectData[3001],
+     0},
+    {"prime239v3", "prime239v3", NID_X9_62_prime239v3, 8, &kObjectData[3009],
+     0},
+    {"prime256v1", "prime256v1", NID_X9_62_prime256v1, 8, &kObjectData[3017],
+     0},
+    {"ecdsa-with-SHA1", "ecdsa-with-SHA1", NID_ecdsa_with_SHA1, 7,
+     &kObjectData[3025], 0},
+    {"CSPName", "Microsoft CSP Name", NID_ms_csp_name, 9, &kObjectData[3032],
+     0},
+    {"AES-128-ECB", "aes-128-ecb", NID_aes_128_ecb, 9, &kObjectData[3041], 0},
+    {"AES-128-CBC", "aes-128-cbc", NID_aes_128_cbc, 9, &kObjectData[3050], 0},
+    {"AES-128-OFB", "aes-128-ofb", NID_aes_128_ofb128, 9, &kObjectData[3059],
+     0},
+    {"AES-128-CFB", "aes-128-cfb", NID_aes_128_cfb128, 9, &kObjectData[3068],
+     0},
+    {"AES-192-ECB", "aes-192-ecb", NID_aes_192_ecb, 9, &kObjectData[3077], 0},
+    {"AES-192-CBC", "aes-192-cbc", NID_aes_192_cbc, 9, &kObjectData[3086], 0},
+    {"AES-192-OFB", "aes-192-ofb", NID_aes_192_ofb128, 9, &kObjectData[3095],
+     0},
+    {"AES-192-CFB", "aes-192-cfb", NID_aes_192_cfb128, 9, &kObjectData[3104],
+     0},
+    {"AES-256-ECB", "aes-256-ecb", NID_aes_256_ecb, 9, &kObjectData[3113], 0},
+    {"AES-256-CBC", "aes-256-cbc", NID_aes_256_cbc, 9, &kObjectData[3122], 0},
+    {"AES-256-OFB", "aes-256-ofb", NID_aes_256_ofb128, 9, &kObjectData[3131],
+     0},
+    {"AES-256-CFB", "aes-256-cfb", NID_aes_256_cfb128, 9, &kObjectData[3140],
+     0},
+    {"holdInstructionCode", "Hold Instruction Code", NID_hold_instruction_code,
+     3, &kObjectData[3149], 0},
+    {"holdInstructionNone", "Hold Instruction None", NID_hold_instruction_none,
+     7, &kObjectData[3152], 0},
+    {"holdInstructionCallIssuer", "Hold Instruction Call Issuer",
+     NID_hold_instruction_call_issuer, 7, &kObjectData[3159], 0},
+    {"holdInstructionReject", "Hold Instruction Reject",
+     NID_hold_instruction_reject, 7, &kObjectData[3166], 0},
+    {"data", "data", NID_data, 1, &kObjectData[3173], 0},
+    {"pss", "pss", NID_pss, 3, &kObjectData[3174], 0},
+    {"ucl", "ucl", NID_ucl, 7, &kObjectData[3177], 0},
+    {"pilot", "pilot", NID_pilot, 8, &kObjectData[3184], 0},
+    {"pilotAttributeType", "pilotAttributeType", NID_pilotAttributeType, 9,
+     &kObjectData[3192], 0},
+    {"pilotAttributeSyntax", "pilotAttributeSyntax", NID_pilotAttributeSyntax,
+     9, &kObjectData[3201], 0},
+    {"pilotObjectClass", "pilotObjectClass", NID_pilotObjectClass, 9,
+     &kObjectData[3210], 0},
+    {"pilotGroups", "pilotGroups", NID_pilotGroups, 9, &kObjectData[3219], 0},
+    {"iA5StringSyntax", "iA5StringSyntax", NID_iA5StringSyntax, 10,
+     &kObjectData[3228], 0},
+    {"caseIgnoreIA5StringSyntax", "caseIgnoreIA5StringSyntax",
+     NID_caseIgnoreIA5StringSyntax, 10, &kObjectData[3238], 0},
+    {"pilotObject", "pilotObject", NID_pilotObject, 10, &kObjectData[3248], 0},
+    {"pilotPerson", "pilotPerson", NID_pilotPerson, 10, &kObjectData[3258], 0},
+    {"account", "account", NID_account, 10, &kObjectData[3268], 0},
+    {"document", "document", NID_document, 10, &kObjectData[3278], 0},
+    {"room", "room", NID_room, 10, &kObjectData[3288], 0},
+    {"documentSeries", "documentSeries", NID_documentSeries, 10,
+     &kObjectData[3298], 0},
+    {"rFC822localPart", "rFC822localPart", NID_rFC822localPart, 10,
+     &kObjectData[3308], 0},
+    {"dNSDomain", "dNSDomain", NID_dNSDomain, 10, &kObjectData[3318], 0},
+    {"domainRelatedObject", "domainRelatedObject", NID_domainRelatedObject, 10,
+     &kObjectData[3328], 0},
+    {"friendlyCountry", "friendlyCountry", NID_friendlyCountry, 10,
+     &kObjectData[3338], 0},
+    {"simpleSecurityObject", "simpleSecurityObject", NID_simpleSecurityObject,
+     10, &kObjectData[3348], 0},
+    {"pilotOrganization", "pilotOrganization", NID_pilotOrganization, 10,
+     &kObjectData[3358], 0},
+    {"pilotDSA", "pilotDSA", NID_pilotDSA, 10, &kObjectData[3368], 0},
+    {"qualityLabelledData", "qualityLabelledData", NID_qualityLabelledData, 10,
+     &kObjectData[3378], 0},
+    {"UID", "userId", NID_userId, 10, &kObjectData[3388], 0},
+    {"textEncodedORAddress", "textEncodedORAddress", NID_textEncodedORAddress,
+     10, &kObjectData[3398], 0},
+    {"mail", "rfc822Mailbox", NID_rfc822Mailbox, 10, &kObjectData[3408], 0},
+    {"info", "info", NID_info, 10, &kObjectData[3418], 0},
+    {"favouriteDrink", "favouriteDrink", NID_favouriteDrink, 10,
+     &kObjectData[3428], 0},
+    {"roomNumber", "roomNumber", NID_roomNumber, 10, &kObjectData[3438], 0},
+    {"photo", "photo", NID_photo, 10, &kObjectData[3448], 0},
+    {"userClass", "userClass", NID_userClass, 10, &kObjectData[3458], 0},
+    {"host", "host", NID_host, 10, &kObjectData[3468], 0},
+    {"manager", "manager", NID_manager, 10, &kObjectData[3478], 0},
+    {"documentIdentifier", "documentIdentifier", NID_documentIdentifier, 10,
+     &kObjectData[3488], 0},
+    {"documentTitle", "documentTitle", NID_documentTitle, 10,
+     &kObjectData[3498], 0},
+    {"documentVersion", "documentVersion", NID_documentVersion, 10,
+     &kObjectData[3508], 0},
+    {"documentAuthor", "documentAuthor", NID_documentAuthor, 10,
+     &kObjectData[3518], 0},
+    {"documentLocation", "documentLocation", NID_documentLocation, 10,
+     &kObjectData[3528], 0},
+    {"homeTelephoneNumber", "homeTelephoneNumber", NID_homeTelephoneNumber, 10,
+     &kObjectData[3538], 0},
+    {"secretary", "secretary", NID_secretary, 10, &kObjectData[3548], 0},
+    {"otherMailbox", "otherMailbox", NID_otherMailbox, 10, &kObjectData[3558],
+     0},
+    {"lastModifiedTime", "lastModifiedTime", NID_lastModifiedTime, 10,
+     &kObjectData[3568], 0},
+    {"lastModifiedBy", "lastModifiedBy", NID_lastModifiedBy, 10,
+     &kObjectData[3578], 0},
+    {"aRecord", "aRecord", NID_aRecord, 10, &kObjectData[3588], 0},
+    {"pilotAttributeType27", "pilotAttributeType27", NID_pilotAttributeType27,
+     10, &kObjectData[3598], 0},
+    {"mXRecord", "mXRecord", NID_mXRecord, 10, &kObjectData[3608], 0},
+    {"nSRecord", "nSRecord", NID_nSRecord, 10, &kObjectData[3618], 0},
+    {"sOARecord", "sOARecord", NID_sOARecord, 10, &kObjectData[3628], 0},
+    {"cNAMERecord", "cNAMERecord", NID_cNAMERecord, 10, &kObjectData[3638], 0},
+    {"associatedDomain", "associatedDomain", NID_associatedDomain, 10,
+     &kObjectData[3648], 0},
+    {"associatedName", "associatedName", NID_associatedName, 10,
+     &kObjectData[3658], 0},
+    {"homePostalAddress", "homePostalAddress", NID_homePostalAddress, 10,
+     &kObjectData[3668], 0},
+    {"personalTitle", "personalTitle", NID_personalTitle, 10,
+     &kObjectData[3678], 0},
+    {"mobileTelephoneNumber", "mobileTelephoneNumber",
+     NID_mobileTelephoneNumber, 10, &kObjectData[3688], 0},
+    {"pagerTelephoneNumber", "pagerTelephoneNumber", NID_pagerTelephoneNumber,
+     10, &kObjectData[3698], 0},
+    {"friendlyCountryName", "friendlyCountryName", NID_friendlyCountryName, 10,
+     &kObjectData[3708], 0},
+    {"organizationalStatus", "organizationalStatus", NID_organizationalStatus,
+     10, &kObjectData[3718], 0},
+    {"janetMailbox", "janetMailbox", NID_janetMailbox, 10, &kObjectData[3728],
+     0},
+    {"mailPreferenceOption", "mailPreferenceOption", NID_mailPreferenceOption,
+     10, &kObjectData[3738], 0},
+    {"buildingName", "buildingName", NID_buildingName, 10, &kObjectData[3748],
+     0},
+    {"dSAQuality", "dSAQuality", NID_dSAQuality, 10, &kObjectData[3758], 0},
+    {"singleLevelQuality", "singleLevelQuality", NID_singleLevelQuality, 10,
+     &kObjectData[3768], 0},
+    {"subtreeMinimumQuality", "subtreeMinimumQuality",
+     NID_subtreeMinimumQuality, 10, &kObjectData[3778], 0},
+    {"subtreeMaximumQuality", "subtreeMaximumQuality",
+     NID_subtreeMaximumQuality, 10, &kObjectData[3788], 0},
+    {"personalSignature", "personalSignature", NID_personalSignature, 10,
+     &kObjectData[3798], 0},
+    {"dITRedirect", "dITRedirect", NID_dITRedirect, 10, &kObjectData[3808], 0},
+    {"audio", "audio", NID_audio, 10, &kObjectData[3818], 0},
+    {"documentPublisher", "documentPublisher", NID_documentPublisher, 10,
+     &kObjectData[3828], 0},
+    {"x500UniqueIdentifier", "x500UniqueIdentifier", NID_x500UniqueIdentifier,
+     3, &kObjectData[3838], 0},
+    {"mime-mhs", "MIME MHS", NID_mime_mhs, 5, &kObjectData[3841], 0},
+    {"mime-mhs-headings", "mime-mhs-headings", NID_mime_mhs_headings, 6,
+     &kObjectData[3846], 0},
+    {"mime-mhs-bodies", "mime-mhs-bodies", NID_mime_mhs_bodies, 6,
+     &kObjectData[3852], 0},
+    {"id-hex-partial-message", "id-hex-partial-message",
+     NID_id_hex_partial_message, 7, &kObjectData[3858], 0},
+    {"id-hex-multipart-message", "id-hex-multipart-message",
+     NID_id_hex_multipart_message, 7, &kObjectData[3865], 0},
+    {"generationQualifier", "generationQualifier", NID_generationQualifier, 3,
+     &kObjectData[3872], 0},
+    {"pseudonym", "pseudonym", NID_pseudonym, 3, &kObjectData[3875], 0},
+    {NULL, NULL, NID_undef, 0, NULL, 0},
+    {"id-set", "Secure Electronic Transactions", NID_id_set, 2,
+     &kObjectData[3878], 0},
+    {"set-ctype", "content types", NID_set_ctype, 3, &kObjectData[3880], 0},
+    {"set-msgExt", "message extensions", NID_set_msgExt, 3, &kObjectData[3883],
+     0},
+    {"set-attr", "set-attr", NID_set_attr, 3, &kObjectData[3886], 0},
+    {"set-policy", "set-policy", NID_set_policy, 3, &kObjectData[3889], 0},
+    {"set-certExt", "certificate extensions", NID_set_certExt, 3,
+     &kObjectData[3892], 0},
+    {"set-brand", "set-brand", NID_set_brand, 3, &kObjectData[3895], 0},
+    {"setct-PANData", "setct-PANData", NID_setct_PANData, 4, &kObjectData[3898],
+     0},
+    {"setct-PANToken", "setct-PANToken", NID_setct_PANToken, 4,
+     &kObjectData[3902], 0},
+    {"setct-PANOnly", "setct-PANOnly", NID_setct_PANOnly, 4, &kObjectData[3906],
+     0},
+    {"setct-OIData", "setct-OIData", NID_setct_OIData, 4, &kObjectData[3910],
+     0},
+    {"setct-PI", "setct-PI", NID_setct_PI, 4, &kObjectData[3914], 0},
+    {"setct-PIData", "setct-PIData", NID_setct_PIData, 4, &kObjectData[3918],
+     0},
+    {"setct-PIDataUnsigned", "setct-PIDataUnsigned", NID_setct_PIDataUnsigned,
+     4, &kObjectData[3922], 0},
+    {"setct-HODInput", "setct-HODInput", NID_setct_HODInput, 4,
+     &kObjectData[3926], 0},
+    {"setct-AuthResBaggage", "setct-AuthResBaggage", NID_setct_AuthResBaggage,
+     4, &kObjectData[3930], 0},
+    {"setct-AuthRevReqBaggage", "setct-AuthRevReqBaggage",
+     NID_setct_AuthRevReqBaggage, 4, &kObjectData[3934], 0},
+    {"setct-AuthRevResBaggage", "setct-AuthRevResBaggage",
+     NID_setct_AuthRevResBaggage, 4, &kObjectData[3938], 0},
+    {"setct-CapTokenSeq", "setct-CapTokenSeq", NID_setct_CapTokenSeq, 4,
+     &kObjectData[3942], 0},
+    {"setct-PInitResData", "setct-PInitResData", NID_setct_PInitResData, 4,
+     &kObjectData[3946], 0},
+    {"setct-PI-TBS", "setct-PI-TBS", NID_setct_PI_TBS, 4, &kObjectData[3950],
+     0},
+    {"setct-PResData", "setct-PResData", NID_setct_PResData, 4,
+     &kObjectData[3954], 0},
+    {"setct-AuthReqTBS", "setct-AuthReqTBS", NID_setct_AuthReqTBS, 4,
+     &kObjectData[3958], 0},
+    {"setct-AuthResTBS", "setct-AuthResTBS", NID_setct_AuthResTBS, 4,
+     &kObjectData[3962], 0},
+    {"setct-AuthResTBSX", "setct-AuthResTBSX", NID_setct_AuthResTBSX, 4,
+     &kObjectData[3966], 0},
+    {"setct-AuthTokenTBS", "setct-AuthTokenTBS", NID_setct_AuthTokenTBS, 4,
+     &kObjectData[3970], 0},
+    {"setct-CapTokenData", "setct-CapTokenData", NID_setct_CapTokenData, 4,
+     &kObjectData[3974], 0},
+    {"setct-CapTokenTBS", "setct-CapTokenTBS", NID_setct_CapTokenTBS, 4,
+     &kObjectData[3978], 0},
+    {"setct-AcqCardCodeMsg", "setct-AcqCardCodeMsg", NID_setct_AcqCardCodeMsg,
+     4, &kObjectData[3982], 0},
+    {"setct-AuthRevReqTBS", "setct-AuthRevReqTBS", NID_setct_AuthRevReqTBS, 4,
+     &kObjectData[3986], 0},
+    {"setct-AuthRevResData", "setct-AuthRevResData", NID_setct_AuthRevResData,
+     4, &kObjectData[3990], 0},
+    {"setct-AuthRevResTBS", "setct-AuthRevResTBS", NID_setct_AuthRevResTBS, 4,
+     &kObjectData[3994], 0},
+    {"setct-CapReqTBS", "setct-CapReqTBS", NID_setct_CapReqTBS, 4,
+     &kObjectData[3998], 0},
+    {"setct-CapReqTBSX", "setct-CapReqTBSX", NID_setct_CapReqTBSX, 4,
+     &kObjectData[4002], 0},
+    {"setct-CapResData", "setct-CapResData", NID_setct_CapResData, 4,
+     &kObjectData[4006], 0},
+    {"setct-CapRevReqTBS", "setct-CapRevReqTBS", NID_setct_CapRevReqTBS, 4,
+     &kObjectData[4010], 0},
+    {"setct-CapRevReqTBSX", "setct-CapRevReqTBSX", NID_setct_CapRevReqTBSX, 4,
+     &kObjectData[4014], 0},
+    {"setct-CapRevResData", "setct-CapRevResData", NID_setct_CapRevResData, 4,
+     &kObjectData[4018], 0},
+    {"setct-CredReqTBS", "setct-CredReqTBS", NID_setct_CredReqTBS, 4,
+     &kObjectData[4022], 0},
+    {"setct-CredReqTBSX", "setct-CredReqTBSX", NID_setct_CredReqTBSX, 4,
+     &kObjectData[4026], 0},
+    {"setct-CredResData", "setct-CredResData", NID_setct_CredResData, 4,
+     &kObjectData[4030], 0},
+    {"setct-CredRevReqTBS", "setct-CredRevReqTBS", NID_setct_CredRevReqTBS, 4,
+     &kObjectData[4034], 0},
+    {"setct-CredRevReqTBSX", "setct-CredRevReqTBSX", NID_setct_CredRevReqTBSX,
+     4, &kObjectData[4038], 0},
+    {"setct-CredRevResData", "setct-CredRevResData", NID_setct_CredRevResData,
+     4, &kObjectData[4042], 0},
+    {"setct-PCertReqData", "setct-PCertReqData", NID_setct_PCertReqData, 4,
+     &kObjectData[4046], 0},
+    {"setct-PCertResTBS", "setct-PCertResTBS", NID_setct_PCertResTBS, 4,
+     &kObjectData[4050], 0},
+    {"setct-BatchAdminReqData", "setct-BatchAdminReqData",
+     NID_setct_BatchAdminReqData, 4, &kObjectData[4054], 0},
+    {"setct-BatchAdminResData", "setct-BatchAdminResData",
+     NID_setct_BatchAdminResData, 4, &kObjectData[4058], 0},
+    {"setct-CardCInitResTBS", "setct-CardCInitResTBS",
+     NID_setct_CardCInitResTBS, 4, &kObjectData[4062], 0},
+    {"setct-MeAqCInitResTBS", "setct-MeAqCInitResTBS",
+     NID_setct_MeAqCInitResTBS, 4, &kObjectData[4066], 0},
+    {"setct-RegFormResTBS", "setct-RegFormResTBS", NID_setct_RegFormResTBS, 4,
+     &kObjectData[4070], 0},
+    {"setct-CertReqData", "setct-CertReqData", NID_setct_CertReqData, 4,
+     &kObjectData[4074], 0},
+    {"setct-CertReqTBS", "setct-CertReqTBS", NID_setct_CertReqTBS, 4,
+     &kObjectData[4078], 0},
+    {"setct-CertResData", "setct-CertResData", NID_setct_CertResData, 4,
+     &kObjectData[4082], 0},
+    {"setct-CertInqReqTBS", "setct-CertInqReqTBS", NID_setct_CertInqReqTBS, 4,
+     &kObjectData[4086], 0},
+    {"setct-ErrorTBS", "setct-ErrorTBS", NID_setct_ErrorTBS, 4,
+     &kObjectData[4090], 0},
+    {"setct-PIDualSignedTBE", "setct-PIDualSignedTBE",
+     NID_setct_PIDualSignedTBE, 4, &kObjectData[4094], 0},
+    {"setct-PIUnsignedTBE", "setct-PIUnsignedTBE", NID_setct_PIUnsignedTBE, 4,
+     &kObjectData[4098], 0},
+    {"setct-AuthReqTBE", "setct-AuthReqTBE", NID_setct_AuthReqTBE, 4,
+     &kObjectData[4102], 0},
+    {"setct-AuthResTBE", "setct-AuthResTBE", NID_setct_AuthResTBE, 4,
+     &kObjectData[4106], 0},
+    {"setct-AuthResTBEX", "setct-AuthResTBEX", NID_setct_AuthResTBEX, 4,
+     &kObjectData[4110], 0},
+    {"setct-AuthTokenTBE", "setct-AuthTokenTBE", NID_setct_AuthTokenTBE, 4,
+     &kObjectData[4114], 0},
+    {"setct-CapTokenTBE", "setct-CapTokenTBE", NID_setct_CapTokenTBE, 4,
+     &kObjectData[4118], 0},
+    {"setct-CapTokenTBEX", "setct-CapTokenTBEX", NID_setct_CapTokenTBEX, 4,
+     &kObjectData[4122], 0},
+    {"setct-AcqCardCodeMsgTBE", "setct-AcqCardCodeMsgTBE",
+     NID_setct_AcqCardCodeMsgTBE, 4, &kObjectData[4126], 0},
+    {"setct-AuthRevReqTBE", "setct-AuthRevReqTBE", NID_setct_AuthRevReqTBE, 4,
+     &kObjectData[4130], 0},
+    {"setct-AuthRevResTBE", "setct-AuthRevResTBE", NID_setct_AuthRevResTBE, 4,
+     &kObjectData[4134], 0},
+    {"setct-AuthRevResTBEB", "setct-AuthRevResTBEB", NID_setct_AuthRevResTBEB,
+     4, &kObjectData[4138], 0},
+    {"setct-CapReqTBE", "setct-CapReqTBE", NID_setct_CapReqTBE, 4,
+     &kObjectData[4142], 0},
+    {"setct-CapReqTBEX", "setct-CapReqTBEX", NID_setct_CapReqTBEX, 4,
+     &kObjectData[4146], 0},
+    {"setct-CapResTBE", "setct-CapResTBE", NID_setct_CapResTBE, 4,
+     &kObjectData[4150], 0},
+    {"setct-CapRevReqTBE", "setct-CapRevReqTBE", NID_setct_CapRevReqTBE, 4,
+     &kObjectData[4154], 0},
+    {"setct-CapRevReqTBEX", "setct-CapRevReqTBEX", NID_setct_CapRevReqTBEX, 4,
+     &kObjectData[4158], 0},
+    {"setct-CapRevResTBE", "setct-CapRevResTBE", NID_setct_CapRevResTBE, 4,
+     &kObjectData[4162], 0},
+    {"setct-CredReqTBE", "setct-CredReqTBE", NID_setct_CredReqTBE, 4,
+     &kObjectData[4166], 0},
+    {"setct-CredReqTBEX", "setct-CredReqTBEX", NID_setct_CredReqTBEX, 4,
+     &kObjectData[4170], 0},
+    {"setct-CredResTBE", "setct-CredResTBE", NID_setct_CredResTBE, 4,
+     &kObjectData[4174], 0},
+    {"setct-CredRevReqTBE", "setct-CredRevReqTBE", NID_setct_CredRevReqTBE, 4,
+     &kObjectData[4178], 0},
+    {"setct-CredRevReqTBEX", "setct-CredRevReqTBEX", NID_setct_CredRevReqTBEX,
+     4, &kObjectData[4182], 0},
+    {"setct-CredRevResTBE", "setct-CredRevResTBE", NID_setct_CredRevResTBE, 4,
+     &kObjectData[4186], 0},
+    {"setct-BatchAdminReqTBE", "setct-BatchAdminReqTBE",
+     NID_setct_BatchAdminReqTBE, 4, &kObjectData[4190], 0},
+    {"setct-BatchAdminResTBE", "setct-BatchAdminResTBE",
+     NID_setct_BatchAdminResTBE, 4, &kObjectData[4194], 0},
+    {"setct-RegFormReqTBE", "setct-RegFormReqTBE", NID_setct_RegFormReqTBE, 4,
+     &kObjectData[4198], 0},
+    {"setct-CertReqTBE", "setct-CertReqTBE", NID_setct_CertReqTBE, 4,
+     &kObjectData[4202], 0},
+    {"setct-CertReqTBEX", "setct-CertReqTBEX", NID_setct_CertReqTBEX, 4,
+     &kObjectData[4206], 0},
+    {"setct-CertResTBE", "setct-CertResTBE", NID_setct_CertResTBE, 4,
+     &kObjectData[4210], 0},
+    {"setct-CRLNotificationTBS", "setct-CRLNotificationTBS",
+     NID_setct_CRLNotificationTBS, 4, &kObjectData[4214], 0},
+    {"setct-CRLNotificationResTBS", "setct-CRLNotificationResTBS",
+     NID_setct_CRLNotificationResTBS, 4, &kObjectData[4218], 0},
+    {"setct-BCIDistributionTBS", "setct-BCIDistributionTBS",
+     NID_setct_BCIDistributionTBS, 4, &kObjectData[4222], 0},
+    {"setext-genCrypt", "generic cryptogram", NID_setext_genCrypt, 4,
+     &kObjectData[4226], 0},
+    {"setext-miAuth", "merchant initiated auth", NID_setext_miAuth, 4,
+     &kObjectData[4230], 0},
+    {"setext-pinSecure", "setext-pinSecure", NID_setext_pinSecure, 4,
+     &kObjectData[4234], 0},
+    {"setext-pinAny", "setext-pinAny", NID_setext_pinAny, 4, &kObjectData[4238],
+     0},
+    {"setext-track2", "setext-track2", NID_setext_track2, 4, &kObjectData[4242],
+     0},
+    {"setext-cv", "additional verification", NID_setext_cv, 4,
+     &kObjectData[4246], 0},
+    {"set-policy-root", "set-policy-root", NID_set_policy_root, 4,
+     &kObjectData[4250], 0},
+    {"setCext-hashedRoot", "setCext-hashedRoot", NID_setCext_hashedRoot, 4,
+     &kObjectData[4254], 0},
+    {"setCext-certType", "setCext-certType", NID_setCext_certType, 4,
+     &kObjectData[4258], 0},
+    {"setCext-merchData", "setCext-merchData", NID_setCext_merchData, 4,
+     &kObjectData[4262], 0},
+    {"setCext-cCertRequired", "setCext-cCertRequired",
+     NID_setCext_cCertRequired, 4, &kObjectData[4266], 0},
+    {"setCext-tunneling", "setCext-tunneling", NID_setCext_tunneling, 4,
+     &kObjectData[4270], 0},
+    {"setCext-setExt", "setCext-setExt", NID_setCext_setExt, 4,
+     &kObjectData[4274], 0},
+    {"setCext-setQualf", "setCext-setQualf", NID_setCext_setQualf, 4,
+     &kObjectData[4278], 0},
+    {"setCext-PGWYcapabilities", "setCext-PGWYcapabilities",
+     NID_setCext_PGWYcapabilities, 4, &kObjectData[4282], 0},
+    {"setCext-TokenIdentifier", "setCext-TokenIdentifier",
+     NID_setCext_TokenIdentifier, 4, &kObjectData[4286], 0},
+    {"setCext-Track2Data", "setCext-Track2Data", NID_setCext_Track2Data, 4,
+     &kObjectData[4290], 0},
+    {"setCext-TokenType", "setCext-TokenType", NID_setCext_TokenType, 4,
+     &kObjectData[4294], 0},
+    {"setCext-IssuerCapabilities", "setCext-IssuerCapabilities",
+     NID_setCext_IssuerCapabilities, 4, &kObjectData[4298], 0},
+    {"setAttr-Cert", "setAttr-Cert", NID_setAttr_Cert, 4, &kObjectData[4302],
+     0},
+    {"setAttr-PGWYcap", "payment gateway capabilities", NID_setAttr_PGWYcap, 4,
+     &kObjectData[4306], 0},
+    {"setAttr-TokenType", "setAttr-TokenType", NID_setAttr_TokenType, 4,
+     &kObjectData[4310], 0},
+    {"setAttr-IssCap", "issuer capabilities", NID_setAttr_IssCap, 4,
+     &kObjectData[4314], 0},
+    {"set-rootKeyThumb", "set-rootKeyThumb", NID_set_rootKeyThumb, 5,
+     &kObjectData[4318], 0},
+    {"set-addPolicy", "set-addPolicy", NID_set_addPolicy, 5, &kObjectData[4323],
+     0},
+    {"setAttr-Token-EMV", "setAttr-Token-EMV", NID_setAttr_Token_EMV, 5,
+     &kObjectData[4328], 0},
+    {"setAttr-Token-B0Prime", "setAttr-Token-B0Prime",
+     NID_setAttr_Token_B0Prime, 5, &kObjectData[4333], 0},
+    {"setAttr-IssCap-CVM", "setAttr-IssCap-CVM", NID_setAttr_IssCap_CVM, 5,
+     &kObjectData[4338], 0},
+    {"setAttr-IssCap-T2", "setAttr-IssCap-T2", NID_setAttr_IssCap_T2, 5,
+     &kObjectData[4343], 0},
+    {"setAttr-IssCap-Sig", "setAttr-IssCap-Sig", NID_setAttr_IssCap_Sig, 5,
+     &kObjectData[4348], 0},
+    {"setAttr-GenCryptgrm", "generate cryptogram", NID_setAttr_GenCryptgrm, 6,
+     &kObjectData[4353], 0},
+    {"setAttr-T2Enc", "encrypted track 2", NID_setAttr_T2Enc, 6,
+     &kObjectData[4359], 0},
+    {"setAttr-T2cleartxt", "cleartext track 2", NID_setAttr_T2cleartxt, 6,
+     &kObjectData[4365], 0},
+    {"setAttr-TokICCsig", "ICC or token signature", NID_setAttr_TokICCsig, 6,
+     &kObjectData[4371], 0},
+    {"setAttr-SecDevSig", "secure device signature", NID_setAttr_SecDevSig, 6,
+     &kObjectData[4377], 0},
+    {"set-brand-IATA-ATA", "set-brand-IATA-ATA", NID_set_brand_IATA_ATA, 4,
+     &kObjectData[4383], 0},
+    {"set-brand-Diners", "set-brand-Diners", NID_set_brand_Diners, 4,
+     &kObjectData[4387], 0},
+    {"set-brand-AmericanExpress", "set-brand-AmericanExpress",
+     NID_set_brand_AmericanExpress, 4, &kObjectData[4391], 0},
+    {"set-brand-JCB", "set-brand-JCB", NID_set_brand_JCB, 4, &kObjectData[4395],
+     0},
+    {"set-brand-Visa", "set-brand-Visa", NID_set_brand_Visa, 4,
+     &kObjectData[4399], 0},
+    {"set-brand-MasterCard", "set-brand-MasterCard", NID_set_brand_MasterCard,
+     4, &kObjectData[4403], 0},
+    {"set-brand-Novus", "set-brand-Novus", NID_set_brand_Novus, 5,
+     &kObjectData[4407], 0},
+    {"DES-CDMF", "des-cdmf", NID_des_cdmf, 8, &kObjectData[4412], 0},
+    {"rsaOAEPEncryptionSET", "rsaOAEPEncryptionSET", NID_rsaOAEPEncryptionSET,
+     9, &kObjectData[4420], 0},
+    {"ITU-T", "itu-t", NID_itu_t, 0, NULL, 0},
+    {"JOINT-ISO-ITU-T", "joint-iso-itu-t", NID_joint_iso_itu_t, 0, NULL, 0},
+    {"international-organizations", "International Organizations",
+     NID_international_organizations, 1, &kObjectData[4429], 0},
+    {"msSmartcardLogin", "Microsoft Smartcardlogin", NID_ms_smartcard_login, 10,
+     &kObjectData[4430], 0},
+    {"msUPN", "Microsoft Universal Principal Name", NID_ms_upn, 10,
+     &kObjectData[4440], 0},
+    {"AES-128-CFB1", "aes-128-cfb1", NID_aes_128_cfb1, 0, NULL, 0},
+    {"AES-192-CFB1", "aes-192-cfb1", NID_aes_192_cfb1, 0, NULL, 0},
+    {"AES-256-CFB1", "aes-256-cfb1", NID_aes_256_cfb1, 0, NULL, 0},
+    {"AES-128-CFB8", "aes-128-cfb8", NID_aes_128_cfb8, 0, NULL, 0},
+    {"AES-192-CFB8", "aes-192-cfb8", NID_aes_192_cfb8, 0, NULL, 0},
+    {"AES-256-CFB8", "aes-256-cfb8", NID_aes_256_cfb8, 0, NULL, 0},
+    {"DES-CFB1", "des-cfb1", NID_des_cfb1, 0, NULL, 0},
+    {"DES-CFB8", "des-cfb8", NID_des_cfb8, 0, NULL, 0},
+    {"DES-EDE3-CFB1", "des-ede3-cfb1", NID_des_ede3_cfb1, 0, NULL, 0},
+    {"DES-EDE3-CFB8", "des-ede3-cfb8", NID_des_ede3_cfb8, 0, NULL, 0},
+    {"street", "streetAddress", NID_streetAddress, 3, &kObjectData[4450], 0},
+    {"postalCode", "postalCode", NID_postalCode, 3, &kObjectData[4453], 0},
+    {"id-ppl", "id-ppl", NID_id_ppl, 7, &kObjectData[4456], 0},
+    {"proxyCertInfo", "Proxy Certificate Information", NID_proxyCertInfo, 8,
+     &kObjectData[4463], 0},
+    {"id-ppl-anyLanguage", "Any language", NID_id_ppl_anyLanguage, 8,
+     &kObjectData[4471], 0},
+    {"id-ppl-inheritAll", "Inherit all", NID_id_ppl_inheritAll, 8,
+     &kObjectData[4479], 0},
+    {"nameConstraints", "X509v3 Name Constraints", NID_name_constraints, 3,
+     &kObjectData[4487], 0},
+    {"id-ppl-independent", "Independent", NID_Independent, 8,
+     &kObjectData[4490], 0},
+    {"RSA-SHA256", "sha256WithRSAEncryption", NID_sha256WithRSAEncryption, 9,
+     &kObjectData[4498], 0},
+    {"RSA-SHA384", "sha384WithRSAEncryption", NID_sha384WithRSAEncryption, 9,
+     &kObjectData[4507], 0},
+    {"RSA-SHA512", "sha512WithRSAEncryption", NID_sha512WithRSAEncryption, 9,
+     &kObjectData[4516], 0},
+    {"RSA-SHA224", "sha224WithRSAEncryption", NID_sha224WithRSAEncryption, 9,
+     &kObjectData[4525], 0},
+    {"SHA256", "sha256", NID_sha256, 9, &kObjectData[4534], 0},
+    {"SHA384", "sha384", NID_sha384, 9, &kObjectData[4543], 0},
+    {"SHA512", "sha512", NID_sha512, 9, &kObjectData[4552], 0},
+    {"SHA224", "sha224", NID_sha224, 9, &kObjectData[4561], 0},
+    {"identified-organization", "identified-organization",
+     NID_identified_organization, 1, &kObjectData[4570], 0},
+    {"certicom-arc", "certicom-arc", NID_certicom_arc, 3, &kObjectData[4571],
+     0},
+    {"wap", "wap", NID_wap, 2, &kObjectData[4574], 0},
+    {"wap-wsg", "wap-wsg", NID_wap_wsg, 3, &kObjectData[4576], 0},
+    {"id-characteristic-two-basis", "id-characteristic-two-basis",
+     NID_X9_62_id_characteristic_two_basis, 8, &kObjectData[4579], 0},
+    {"onBasis", "onBasis", NID_X9_62_onBasis, 9, &kObjectData[4587], 0},
+    {"tpBasis", "tpBasis", NID_X9_62_tpBasis, 9, &kObjectData[4596], 0},
+    {"ppBasis", "ppBasis", NID_X9_62_ppBasis, 9, &kObjectData[4605], 0},
+    {"c2pnb163v1", "c2pnb163v1", NID_X9_62_c2pnb163v1, 8, &kObjectData[4614],
+     0},
+    {"c2pnb163v2", "c2pnb163v2", NID_X9_62_c2pnb163v2, 8, &kObjectData[4622],
+     0},
+    {"c2pnb163v3", "c2pnb163v3", NID_X9_62_c2pnb163v3, 8, &kObjectData[4630],
+     0},
+    {"c2pnb176v1", "c2pnb176v1", NID_X9_62_c2pnb176v1, 8, &kObjectData[4638],
+     0},
+    {"c2tnb191v1", "c2tnb191v1", NID_X9_62_c2tnb191v1, 8, &kObjectData[4646],
+     0},
+    {"c2tnb191v2", "c2tnb191v2", NID_X9_62_c2tnb191v2, 8, &kObjectData[4654],
+     0},
+    {"c2tnb191v3", "c2tnb191v3", NID_X9_62_c2tnb191v3, 8, &kObjectData[4662],
+     0},
+    {"c2onb191v4", "c2onb191v4", NID_X9_62_c2onb191v4, 8, &kObjectData[4670],
+     0},
+    {"c2onb191v5", "c2onb191v5", NID_X9_62_c2onb191v5, 8, &kObjectData[4678],
+     0},
+    {"c2pnb208w1", "c2pnb208w1", NID_X9_62_c2pnb208w1, 8, &kObjectData[4686],
+     0},
+    {"c2tnb239v1", "c2tnb239v1", NID_X9_62_c2tnb239v1, 8, &kObjectData[4694],
+     0},
+    {"c2tnb239v2", "c2tnb239v2", NID_X9_62_c2tnb239v2, 8, &kObjectData[4702],
+     0},
+    {"c2tnb239v3", "c2tnb239v3", NID_X9_62_c2tnb239v3, 8, &kObjectData[4710],
+     0},
+    {"c2onb239v4", "c2onb239v4", NID_X9_62_c2onb239v4, 8, &kObjectData[4718],
+     0},
+    {"c2onb239v5", "c2onb239v5", NID_X9_62_c2onb239v5, 8, &kObjectData[4726],
+     0},
+    {"c2pnb272w1", "c2pnb272w1", NID_X9_62_c2pnb272w1, 8, &kObjectData[4734],
+     0},
+    {"c2pnb304w1", "c2pnb304w1", NID_X9_62_c2pnb304w1, 8, &kObjectData[4742],
+     0},
+    {"c2tnb359v1", "c2tnb359v1", NID_X9_62_c2tnb359v1, 8, &kObjectData[4750],
+     0},
+    {"c2pnb368w1", "c2pnb368w1", NID_X9_62_c2pnb368w1, 8, &kObjectData[4758],
+     0},
+    {"c2tnb431r1", "c2tnb431r1", NID_X9_62_c2tnb431r1, 8, &kObjectData[4766],
+     0},
+    {"secp112r1", "secp112r1", NID_secp112r1, 5, &kObjectData[4774], 0},
+    {"secp112r2", "secp112r2", NID_secp112r2, 5, &kObjectData[4779], 0},
+    {"secp128r1", "secp128r1", NID_secp128r1, 5, &kObjectData[4784], 0},
+    {"secp128r2", "secp128r2", NID_secp128r2, 5, &kObjectData[4789], 0},
+    {"secp160k1", "secp160k1", NID_secp160k1, 5, &kObjectData[4794], 0},
+    {"secp160r1", "secp160r1", NID_secp160r1, 5, &kObjectData[4799], 0},
+    {"secp160r2", "secp160r2", NID_secp160r2, 5, &kObjectData[4804], 0},
+    {"secp192k1", "secp192k1", NID_secp192k1, 5, &kObjectData[4809], 0},
+    {"secp224k1", "secp224k1", NID_secp224k1, 5, &kObjectData[4814], 0},
+    {"secp224r1", "secp224r1", NID_secp224r1, 5, &kObjectData[4819], 0},
+    {"secp256k1", "secp256k1", NID_secp256k1, 5, &kObjectData[4824], 0},
+    {"secp384r1", "secp384r1", NID_secp384r1, 5, &kObjectData[4829], 0},
+    {"secp521r1", "secp521r1", NID_secp521r1, 5, &kObjectData[4834], 0},
+    {"sect113r1", "sect113r1", NID_sect113r1, 5, &kObjectData[4839], 0},
+    {"sect113r2", "sect113r2", NID_sect113r2, 5, &kObjectData[4844], 0},
+    {"sect131r1", "sect131r1", NID_sect131r1, 5, &kObjectData[4849], 0},
+    {"sect131r2", "sect131r2", NID_sect131r2, 5, &kObjectData[4854], 0},
+    {"sect163k1", "sect163k1", NID_sect163k1, 5, &kObjectData[4859], 0},
+    {"sect163r1", "sect163r1", NID_sect163r1, 5, &kObjectData[4864], 0},
+    {"sect163r2", "sect163r2", NID_sect163r2, 5, &kObjectData[4869], 0},
+    {"sect193r1", "sect193r1", NID_sect193r1, 5, &kObjectData[4874], 0},
+    {"sect193r2", "sect193r2", NID_sect193r2, 5, &kObjectData[4879], 0},
+    {"sect233k1", "sect233k1", NID_sect233k1, 5, &kObjectData[4884], 0},
+    {"sect233r1", "sect233r1", NID_sect233r1, 5, &kObjectData[4889], 0},
+    {"sect239k1", "sect239k1", NID_sect239k1, 5, &kObjectData[4894], 0},
+    {"sect283k1", "sect283k1", NID_sect283k1, 5, &kObjectData[4899], 0},
+    {"sect283r1", "sect283r1", NID_sect283r1, 5, &kObjectData[4904], 0},
+    {"sect409k1", "sect409k1", NID_sect409k1, 5, &kObjectData[4909], 0},
+    {"sect409r1", "sect409r1", NID_sect409r1, 5, &kObjectData[4914], 0},
+    {"sect571k1", "sect571k1", NID_sect571k1, 5, &kObjectData[4919], 0},
+    {"sect571r1", "sect571r1", NID_sect571r1, 5, &kObjectData[4924], 0},
+    {"wap-wsg-idm-ecid-wtls1", "wap-wsg-idm-ecid-wtls1",
+     NID_wap_wsg_idm_ecid_wtls1, 5, &kObjectData[4929], 0},
+    {"wap-wsg-idm-ecid-wtls3", "wap-wsg-idm-ecid-wtls3",
+     NID_wap_wsg_idm_ecid_wtls3, 5, &kObjectData[4934], 0},
+    {"wap-wsg-idm-ecid-wtls4", "wap-wsg-idm-ecid-wtls4",
+     NID_wap_wsg_idm_ecid_wtls4, 5, &kObjectData[4939], 0},
+    {"wap-wsg-idm-ecid-wtls5", "wap-wsg-idm-ecid-wtls5",
+     NID_wap_wsg_idm_ecid_wtls5, 5, &kObjectData[4944], 0},
+    {"wap-wsg-idm-ecid-wtls6", "wap-wsg-idm-ecid-wtls6",
+     NID_wap_wsg_idm_ecid_wtls6, 5, &kObjectData[4949], 0},
+    {"wap-wsg-idm-ecid-wtls7", "wap-wsg-idm-ecid-wtls7",
+     NID_wap_wsg_idm_ecid_wtls7, 5, &kObjectData[4954], 0},
+    {"wap-wsg-idm-ecid-wtls8", "wap-wsg-idm-ecid-wtls8",
+     NID_wap_wsg_idm_ecid_wtls8, 5, &kObjectData[4959], 0},
+    {"wap-wsg-idm-ecid-wtls9", "wap-wsg-idm-ecid-wtls9",
+     NID_wap_wsg_idm_ecid_wtls9, 5, &kObjectData[4964], 0},
+    {"wap-wsg-idm-ecid-wtls10", "wap-wsg-idm-ecid-wtls10",
+     NID_wap_wsg_idm_ecid_wtls10, 5, &kObjectData[4969], 0},
+    {"wap-wsg-idm-ecid-wtls11", "wap-wsg-idm-ecid-wtls11",
+     NID_wap_wsg_idm_ecid_wtls11, 5, &kObjectData[4974], 0},
+    {"wap-wsg-idm-ecid-wtls12", "wap-wsg-idm-ecid-wtls12",
+     NID_wap_wsg_idm_ecid_wtls12, 5, &kObjectData[4979], 0},
+    {"anyPolicy", "X509v3 Any Policy", NID_any_policy, 4, &kObjectData[4984],
+     0},
+    {"policyMappings", "X509v3 Policy Mappings", NID_policy_mappings, 3,
+     &kObjectData[4988], 0},
+    {"inhibitAnyPolicy", "X509v3 Inhibit Any Policy", NID_inhibit_any_policy, 3,
+     &kObjectData[4991], 0},
+    {"Oakley-EC2N-3", "ipsec3", NID_ipsec3, 0, NULL, 0},
+    {"Oakley-EC2N-4", "ipsec4", NID_ipsec4, 0, NULL, 0},
+    {"CAMELLIA-128-CBC", "camellia-128-cbc", NID_camellia_128_cbc, 11,
+     &kObjectData[4994], 0},
+    {"CAMELLIA-192-CBC", "camellia-192-cbc", NID_camellia_192_cbc, 11,
+     &kObjectData[5005], 0},
+    {"CAMELLIA-256-CBC", "camellia-256-cbc", NID_camellia_256_cbc, 11,
+     &kObjectData[5016], 0},
+    {"CAMELLIA-128-ECB", "camellia-128-ecb", NID_camellia_128_ecb, 8,
+     &kObjectData[5027], 0},
+    {"CAMELLIA-192-ECB", "camellia-192-ecb", NID_camellia_192_ecb, 8,
+     &kObjectData[5035], 0},
+    {"CAMELLIA-256-ECB", "camellia-256-ecb", NID_camellia_256_ecb, 8,
+     &kObjectData[5043], 0},
+    {"CAMELLIA-128-CFB", "camellia-128-cfb", NID_camellia_128_cfb128, 8,
+     &kObjectData[5051], 0},
+    {"CAMELLIA-192-CFB", "camellia-192-cfb", NID_camellia_192_cfb128, 8,
+     &kObjectData[5059], 0},
+    {"CAMELLIA-256-CFB", "camellia-256-cfb", NID_camellia_256_cfb128, 8,
+     &kObjectData[5067], 0},
+    {"CAMELLIA-128-CFB1", "camellia-128-cfb1", NID_camellia_128_cfb1, 0, NULL,
+     0},
+    {"CAMELLIA-192-CFB1", "camellia-192-cfb1", NID_camellia_192_cfb1, 0, NULL,
+     0},
+    {"CAMELLIA-256-CFB1", "camellia-256-cfb1", NID_camellia_256_cfb1, 0, NULL,
+     0},
+    {"CAMELLIA-128-CFB8", "camellia-128-cfb8", NID_camellia_128_cfb8, 0, NULL,
+     0},
+    {"CAMELLIA-192-CFB8", "camellia-192-cfb8", NID_camellia_192_cfb8, 0, NULL,
+     0},
+    {"CAMELLIA-256-CFB8", "camellia-256-cfb8", NID_camellia_256_cfb8, 0, NULL,
+     0},
+    {"CAMELLIA-128-OFB", "camellia-128-ofb", NID_camellia_128_ofb128, 8,
+     &kObjectData[5075], 0},
+    {"CAMELLIA-192-OFB", "camellia-192-ofb", NID_camellia_192_ofb128, 8,
+     &kObjectData[5083], 0},
+    {"CAMELLIA-256-OFB", "camellia-256-ofb", NID_camellia_256_ofb128, 8,
+     &kObjectData[5091], 0},
+    {"subjectDirectoryAttributes", "X509v3 Subject Directory Attributes",
+     NID_subject_directory_attributes, 3, &kObjectData[5099], 0},
+    {"issuingDistributionPoint", "X509v3 Issuing Distribution Point",
+     NID_issuing_distribution_point, 3, &kObjectData[5102], 0},
+    {"certificateIssuer", "X509v3 Certificate Issuer", NID_certificate_issuer,
+     3, &kObjectData[5105], 0},
+    {NULL, NULL, NID_undef, 0, NULL, 0},
+    {"KISA", "kisa", NID_kisa, 6, &kObjectData[5108], 0},
+    {NULL, NULL, NID_undef, 0, NULL, 0},
+    {NULL, NULL, NID_undef, 0, NULL, 0},
+    {"SEED-ECB", "seed-ecb", NID_seed_ecb, 8, &kObjectData[5114], 0},
+    {"SEED-CBC", "seed-cbc", NID_seed_cbc, 8, &kObjectData[5122], 0},
+    {"SEED-OFB", "seed-ofb", NID_seed_ofb128, 8, &kObjectData[5130], 0},
+    {"SEED-CFB", "seed-cfb", NID_seed_cfb128, 8, &kObjectData[5138], 0},
+    {"HMAC-MD5", "hmac-md5", NID_hmac_md5, 8, &kObjectData[5146], 0},
+    {"HMAC-SHA1", "hmac-sha1", NID_hmac_sha1, 8, &kObjectData[5154], 0},
+    {"id-PasswordBasedMAC", "password based MAC", NID_id_PasswordBasedMAC, 9,
+     &kObjectData[5162], 0},
+    {"id-DHBasedMac", "Diffie-Hellman based MAC", NID_id_DHBasedMac, 9,
+     &kObjectData[5171], 0},
+    {"id-it-suppLangTags", "id-it-suppLangTags", NID_id_it_suppLangTags, 8,
+     &kObjectData[5180], 0},
+    {"caRepository", "CA Repository", NID_caRepository, 8, &kObjectData[5188],
+     0},
+    {"id-smime-ct-compressedData", "id-smime-ct-compressedData",
+     NID_id_smime_ct_compressedData, 11, &kObjectData[5196], 0},
+    {"id-ct-asciiTextWithCRLF", "id-ct-asciiTextWithCRLF",
+     NID_id_ct_asciiTextWithCRLF, 11, &kObjectData[5207], 0},
+    {"id-aes128-wrap", "id-aes128-wrap", NID_id_aes128_wrap, 9,
+     &kObjectData[5218], 0},
+    {"id-aes192-wrap", "id-aes192-wrap", NID_id_aes192_wrap, 9,
+     &kObjectData[5227], 0},
+    {"id-aes256-wrap", "id-aes256-wrap", NID_id_aes256_wrap, 9,
+     &kObjectData[5236], 0},
+    {"ecdsa-with-Recommended", "ecdsa-with-Recommended",
+     NID_ecdsa_with_Recommended, 7, &kObjectData[5245], 0},
+    {"ecdsa-with-Specified", "ecdsa-with-Specified", NID_ecdsa_with_Specified,
+     7, &kObjectData[5252], 0},
+    {"ecdsa-with-SHA224", "ecdsa-with-SHA224", NID_ecdsa_with_SHA224, 8,
+     &kObjectData[5259], 0},
+    {"ecdsa-with-SHA256", "ecdsa-with-SHA256", NID_ecdsa_with_SHA256, 8,
+     &kObjectData[5267], 0},
+    {"ecdsa-with-SHA384", "ecdsa-with-SHA384", NID_ecdsa_with_SHA384, 8,
+     &kObjectData[5275], 0},
+    {"ecdsa-with-SHA512", "ecdsa-with-SHA512", NID_ecdsa_with_SHA512, 8,
+     &kObjectData[5283], 0},
+    {"hmacWithMD5", "hmacWithMD5", NID_hmacWithMD5, 8, &kObjectData[5291], 0},
+    {"hmacWithSHA224", "hmacWithSHA224", NID_hmacWithSHA224, 8,
+     &kObjectData[5299], 0},
+    {"hmacWithSHA256", "hmacWithSHA256", NID_hmacWithSHA256, 8,
+     &kObjectData[5307], 0},
+    {"hmacWithSHA384", "hmacWithSHA384", NID_hmacWithSHA384, 8,
+     &kObjectData[5315], 0},
+    {"hmacWithSHA512", "hmacWithSHA512", NID_hmacWithSHA512, 8,
+     &kObjectData[5323], 0},
+    {"dsa_with_SHA224", "dsa_with_SHA224", NID_dsa_with_SHA224, 9,
+     &kObjectData[5331], 0},
+    {"dsa_with_SHA256", "dsa_with_SHA256", NID_dsa_with_SHA256, 9,
+     &kObjectData[5340], 0},
+    {"whirlpool", "whirlpool", NID_whirlpool, 6, &kObjectData[5349], 0},
+    {"cryptopro", "cryptopro", NID_cryptopro, 5, &kObjectData[5355], 0},
+    {"cryptocom", "cryptocom", NID_cryptocom, 5, &kObjectData[5360], 0},
+    {"id-GostR3411-94-with-GostR3410-2001",
+     "GOST R 34.11-94 with GOST R 34.10-2001",
+     NID_id_GostR3411_94_with_GostR3410_2001, 6, &kObjectData[5365], 0},
+    {"id-GostR3411-94-with-GostR3410-94",
+     "GOST R 34.11-94 with GOST R 34.10-94",
+     NID_id_GostR3411_94_with_GostR3410_94, 6, &kObjectData[5371], 0},
+    {"md_gost94", "GOST R 34.11-94", NID_id_GostR3411_94, 6, &kObjectData[5377],
+     0},
+    {"id-HMACGostR3411-94", "HMAC GOST 34.11-94", NID_id_HMACGostR3411_94, 6,
+     &kObjectData[5383], 0},
+    {"gost2001", "GOST R 34.10-2001", NID_id_GostR3410_2001, 6,
+     &kObjectData[5389], 0},
+    {"gost94", "GOST R 34.10-94", NID_id_GostR3410_94, 6, &kObjectData[5395],
+     0},
+    {"gost89", "GOST 28147-89", NID_id_Gost28147_89, 6, &kObjectData[5401], 0},
+    {"gost89-cnt", "gost89-cnt", NID_gost89_cnt, 0, NULL, 0},
+    {"gost-mac", "GOST 28147-89 MAC", NID_id_Gost28147_89_MAC, 6,
+     &kObjectData[5407], 0},
+    {"prf-gostr3411-94", "GOST R 34.11-94 PRF", NID_id_GostR3411_94_prf, 6,
+     &kObjectData[5413], 0},
+    {"id-GostR3410-2001DH", "GOST R 34.10-2001 DH", NID_id_GostR3410_2001DH, 6,
+     &kObjectData[5419], 0},
+    {"id-GostR3410-94DH", "GOST R 34.10-94 DH", NID_id_GostR3410_94DH, 6,
+     &kObjectData[5425], 0},
+    {"id-Gost28147-89-CryptoPro-KeyMeshing",
+     "id-Gost28147-89-CryptoPro-KeyMeshing",
+     NID_id_Gost28147_89_CryptoPro_KeyMeshing, 7, &kObjectData[5431], 0},
+    {"id-Gost28147-89-None-KeyMeshing", "id-Gost28147-89-None-KeyMeshing",
+     NID_id_Gost28147_89_None_KeyMeshing, 7, &kObjectData[5438], 0},
+    {"id-GostR3411-94-TestParamSet", "id-GostR3411-94-TestParamSet",
+     NID_id_GostR3411_94_TestParamSet, 7, &kObjectData[5445], 0},
+    {"id-GostR3411-94-CryptoProParamSet", "id-GostR3411-94-CryptoProParamSet",
+     NID_id_GostR3411_94_CryptoProParamSet, 7, &kObjectData[5452], 0},
+    {"id-Gost28147-89-TestParamSet", "id-Gost28147-89-TestParamSet",
+     NID_id_Gost28147_89_TestParamSet, 7, &kObjectData[5459], 0},
+    {"id-Gost28147-89-CryptoPro-A-ParamSet",
+     "id-Gost28147-89-CryptoPro-A-ParamSet",
+     NID_id_Gost28147_89_CryptoPro_A_ParamSet, 7, &kObjectData[5466], 0},
+    {"id-Gost28147-89-CryptoPro-B-ParamSet",
+     "id-Gost28147-89-CryptoPro-B-ParamSet",
+     NID_id_Gost28147_89_CryptoPro_B_ParamSet, 7, &kObjectData[5473], 0},
+    {"id-Gost28147-89-CryptoPro-C-ParamSet",
+     "id-Gost28147-89-CryptoPro-C-ParamSet",
+     NID_id_Gost28147_89_CryptoPro_C_ParamSet, 7, &kObjectData[5480], 0},
+    {"id-Gost28147-89-CryptoPro-D-ParamSet",
+     "id-Gost28147-89-CryptoPro-D-ParamSet",
+     NID_id_Gost28147_89_CryptoPro_D_ParamSet, 7, &kObjectData[5487], 0},
+    {"id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet",
+     "id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet",
+     NID_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet, 7, &kObjectData[5494],
+     0},
+    {"id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet",
+     "id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet",
+     NID_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet, 7, &kObjectData[5501],
+     0},
+    {"id-Gost28147-89-CryptoPro-RIC-1-ParamSet",
+     "id-Gost28147-89-CryptoPro-RIC-1-ParamSet",
+     NID_id_Gost28147_89_CryptoPro_RIC_1_ParamSet, 7, &kObjectData[5508], 0},
+    {"id-GostR3410-94-TestParamSet", "id-GostR3410-94-TestParamSet",
+     NID_id_GostR3410_94_TestParamSet, 7, &kObjectData[5515], 0},
+    {"id-GostR3410-94-CryptoPro-A-ParamSet",
+     "id-GostR3410-94-CryptoPro-A-ParamSet",
+     NID_id_GostR3410_94_CryptoPro_A_ParamSet, 7, &kObjectData[5522], 0},
+    {"id-GostR3410-94-CryptoPro-B-ParamSet",
+     "id-GostR3410-94-CryptoPro-B-ParamSet",
+     NID_id_GostR3410_94_CryptoPro_B_ParamSet, 7, &kObjectData[5529], 0},
+    {"id-GostR3410-94-CryptoPro-C-ParamSet",
+     "id-GostR3410-94-CryptoPro-C-ParamSet",
+     NID_id_GostR3410_94_CryptoPro_C_ParamSet, 7, &kObjectData[5536], 0},
+    {"id-GostR3410-94-CryptoPro-D-ParamSet",
+     "id-GostR3410-94-CryptoPro-D-ParamSet",
+     NID_id_GostR3410_94_CryptoPro_D_ParamSet, 7, &kObjectData[5543], 0},
+    {"id-GostR3410-94-CryptoPro-XchA-ParamSet",
+     "id-GostR3410-94-CryptoPro-XchA-ParamSet",
+     NID_id_GostR3410_94_CryptoPro_XchA_ParamSet, 7, &kObjectData[5550], 0},
+    {"id-GostR3410-94-CryptoPro-XchB-ParamSet",
+     "id-GostR3410-94-CryptoPro-XchB-ParamSet",
+     NID_id_GostR3410_94_CryptoPro_XchB_ParamSet, 7, &kObjectData[5557], 0},
+    {"id-GostR3410-94-CryptoPro-XchC-ParamSet",
+     "id-GostR3410-94-CryptoPro-XchC-ParamSet",
+     NID_id_GostR3410_94_CryptoPro_XchC_ParamSet, 7, &kObjectData[5564], 0},
+    {"id-GostR3410-2001-TestParamSet", "id-GostR3410-2001-TestParamSet",
+     NID_id_GostR3410_2001_TestParamSet, 7, &kObjectData[5571], 0},
+    {"id-GostR3410-2001-CryptoPro-A-ParamSet",
+     "id-GostR3410-2001-CryptoPro-A-ParamSet",
+     NID_id_GostR3410_2001_CryptoPro_A_ParamSet, 7, &kObjectData[5578], 0},
+    {"id-GostR3410-2001-CryptoPro-B-ParamSet",
+     "id-GostR3410-2001-CryptoPro-B-ParamSet",
+     NID_id_GostR3410_2001_CryptoPro_B_ParamSet, 7, &kObjectData[5585], 0},
+    {"id-GostR3410-2001-CryptoPro-C-ParamSet",
+     "id-GostR3410-2001-CryptoPro-C-ParamSet",
+     NID_id_GostR3410_2001_CryptoPro_C_ParamSet, 7, &kObjectData[5592], 0},
+    {"id-GostR3410-2001-CryptoPro-XchA-ParamSet",
+     "id-GostR3410-2001-CryptoPro-XchA-ParamSet",
+     NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet, 7, &kObjectData[5599], 0},
+    {"id-GostR3410-2001-CryptoPro-XchB-ParamSet",
+     "id-GostR3410-2001-CryptoPro-XchB-ParamSet",
+     NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet, 7, &kObjectData[5606], 0},
+    {"id-GostR3410-94-a", "id-GostR3410-94-a", NID_id_GostR3410_94_a, 7,
+     &kObjectData[5613], 0},
+    {"id-GostR3410-94-aBis", "id-GostR3410-94-aBis", NID_id_GostR3410_94_aBis,
+     7, &kObjectData[5620], 0},
+    {"id-GostR3410-94-b", "id-GostR3410-94-b", NID_id_GostR3410_94_b, 7,
+     &kObjectData[5627], 0},
+    {"id-GostR3410-94-bBis", "id-GostR3410-94-bBis", NID_id_GostR3410_94_bBis,
+     7, &kObjectData[5634], 0},
+    {"id-Gost28147-89-cc", "GOST 28147-89 Cryptocom ParamSet",
+     NID_id_Gost28147_89_cc, 8, &kObjectData[5641], 0},
+    {"gost94cc", "GOST 34.10-94 Cryptocom", NID_id_GostR3410_94_cc, 8,
+     &kObjectData[5649], 0},
+    {"gost2001cc", "GOST 34.10-2001 Cryptocom", NID_id_GostR3410_2001_cc, 8,
+     &kObjectData[5657], 0},
+    {"id-GostR3411-94-with-GostR3410-94-cc",
+     "GOST R 34.11-94 with GOST R 34.10-94 Cryptocom",
+     NID_id_GostR3411_94_with_GostR3410_94_cc, 8, &kObjectData[5665], 0},
+    {"id-GostR3411-94-with-GostR3410-2001-cc",
+     "GOST R 34.11-94 with GOST R 34.10-2001 Cryptocom",
+     NID_id_GostR3411_94_with_GostR3410_2001_cc, 8, &kObjectData[5673], 0},
+    {"id-GostR3410-2001-ParamSet-cc",
+     "GOST R 3410-2001 Parameter Set Cryptocom",
+     NID_id_GostR3410_2001_ParamSet_cc, 8, &kObjectData[5681], 0},
+    {"HMAC", "hmac", NID_hmac, 0, NULL, 0},
+    {"LocalKeySet", "Microsoft Local Key set", NID_LocalKeySet, 9,
+     &kObjectData[5689], 0},
+    {"freshestCRL", "X509v3 Freshest CRL", NID_freshest_crl, 3,
+     &kObjectData[5698], 0},
+    {"id-on-permanentIdentifier", "Permanent Identifier",
+     NID_id_on_permanentIdentifier, 8, &kObjectData[5701], 0},
+    {"searchGuide", "searchGuide", NID_searchGuide, 3, &kObjectData[5709], 0},
+    {"businessCategory", "businessCategory", NID_businessCategory, 3,
+     &kObjectData[5712], 0},
+    {"postalAddress", "postalAddress", NID_postalAddress, 3, &kObjectData[5715],
+     0},
+    {"postOfficeBox", "postOfficeBox", NID_postOfficeBox, 3, &kObjectData[5718],
+     0},
+    {"physicalDeliveryOfficeName", "physicalDeliveryOfficeName",
+     NID_physicalDeliveryOfficeName, 3, &kObjectData[5721], 0},
+    {"telephoneNumber", "telephoneNumber", NID_telephoneNumber, 3,
+     &kObjectData[5724], 0},
+    {"telexNumber", "telexNumber", NID_telexNumber, 3, &kObjectData[5727], 0},
+    {"teletexTerminalIdentifier", "teletexTerminalIdentifier",
+     NID_teletexTerminalIdentifier, 3, &kObjectData[5730], 0},
+    {"facsimileTelephoneNumber", "facsimileTelephoneNumber",
+     NID_facsimileTelephoneNumber, 3, &kObjectData[5733], 0},
+    {"x121Address", "x121Address", NID_x121Address, 3, &kObjectData[5736], 0},
+    {"internationaliSDNNumber", "internationaliSDNNumber",
+     NID_internationaliSDNNumber, 3, &kObjectData[5739], 0},
+    {"registeredAddress", "registeredAddress", NID_registeredAddress, 3,
+     &kObjectData[5742], 0},
+    {"destinationIndicator", "destinationIndicator", NID_destinationIndicator,
+     3, &kObjectData[5745], 0},
+    {"preferredDeliveryMethod", "preferredDeliveryMethod",
+     NID_preferredDeliveryMethod, 3, &kObjectData[5748], 0},
+    {"presentationAddress", "presentationAddress", NID_presentationAddress, 3,
+     &kObjectData[5751], 0},
+    {"supportedApplicationContext", "supportedApplicationContext",
+     NID_supportedApplicationContext, 3, &kObjectData[5754], 0},
+    {"member", "member", NID_member, 3, &kObjectData[5757], 0},
+    {"owner", "owner", NID_owner, 3, &kObjectData[5760], 0},
+    {"roleOccupant", "roleOccupant", NID_roleOccupant, 3, &kObjectData[5763],
+     0},
+    {"seeAlso", "seeAlso", NID_seeAlso, 3, &kObjectData[5766], 0},
+    {"userPassword", "userPassword", NID_userPassword, 3, &kObjectData[5769],
+     0},
+    {"userCertificate", "userCertificate", NID_userCertificate, 3,
+     &kObjectData[5772], 0},
+    {"cACertificate", "cACertificate", NID_cACertificate, 3, &kObjectData[5775],
+     0},
+    {"authorityRevocationList", "authorityRevocationList",
+     NID_authorityRevocationList, 3, &kObjectData[5778], 0},
+    {"certificateRevocationList", "certificateRevocationList",
+     NID_certificateRevocationList, 3, &kObjectData[5781], 0},
+    {"crossCertificatePair", "crossCertificatePair", NID_crossCertificatePair,
+     3, &kObjectData[5784], 0},
+    {"enhancedSearchGuide", "enhancedSearchGuide", NID_enhancedSearchGuide, 3,
+     &kObjectData[5787], 0},
+    {"protocolInformation", "protocolInformation", NID_protocolInformation, 3,
+     &kObjectData[5790], 0},
+    {"distinguishedName", "distinguishedName", NID_distinguishedName, 3,
+     &kObjectData[5793], 0},
+    {"uniqueMember", "uniqueMember", NID_uniqueMember, 3, &kObjectData[5796],
+     0},
+    {"houseIdentifier", "houseIdentifier", NID_houseIdentifier, 3,
+     &kObjectData[5799], 0},
+    {"supportedAlgorithms", "supportedAlgorithms", NID_supportedAlgorithms, 3,
+     &kObjectData[5802], 0},
+    {"deltaRevocationList", "deltaRevocationList", NID_deltaRevocationList, 3,
+     &kObjectData[5805], 0},
+    {"dmdName", "dmdName", NID_dmdName, 3, &kObjectData[5808], 0},
+    {"id-alg-PWRI-KEK", "id-alg-PWRI-KEK", NID_id_alg_PWRI_KEK, 11,
+     &kObjectData[5811], 0},
+    {"CMAC", "cmac", NID_cmac, 0, NULL, 0},
+    {"id-aes128-GCM", "aes-128-gcm", NID_aes_128_gcm, 9, &kObjectData[5822], 0},
+    {"id-aes128-CCM", "aes-128-ccm", NID_aes_128_ccm, 9, &kObjectData[5831], 0},
+    {"id-aes128-wrap-pad", "id-aes128-wrap-pad", NID_id_aes128_wrap_pad, 9,
+     &kObjectData[5840], 0},
+    {"id-aes192-GCM", "aes-192-gcm", NID_aes_192_gcm, 9, &kObjectData[5849], 0},
+    {"id-aes192-CCM", "aes-192-ccm", NID_aes_192_ccm, 9, &kObjectData[5858], 0},
+    {"id-aes192-wrap-pad", "id-aes192-wrap-pad", NID_id_aes192_wrap_pad, 9,
+     &kObjectData[5867], 0},
+    {"id-aes256-GCM", "aes-256-gcm", NID_aes_256_gcm, 9, &kObjectData[5876], 0},
+    {"id-aes256-CCM", "aes-256-ccm", NID_aes_256_ccm, 9, &kObjectData[5885], 0},
+    {"id-aes256-wrap-pad", "id-aes256-wrap-pad", NID_id_aes256_wrap_pad, 9,
+     &kObjectData[5894], 0},
+    {"AES-128-CTR", "aes-128-ctr", NID_aes_128_ctr, 0, NULL, 0},
+    {"AES-192-CTR", "aes-192-ctr", NID_aes_192_ctr, 0, NULL, 0},
+    {"AES-256-CTR", "aes-256-ctr", NID_aes_256_ctr, 0, NULL, 0},
+    {"id-camellia128-wrap", "id-camellia128-wrap", NID_id_camellia128_wrap, 11,
+     &kObjectData[5903], 0},
+    {"id-camellia192-wrap", "id-camellia192-wrap", NID_id_camellia192_wrap, 11,
+     &kObjectData[5914], 0},
+    {"id-camellia256-wrap", "id-camellia256-wrap", NID_id_camellia256_wrap, 11,
+     &kObjectData[5925], 0},
+    {"anyExtendedKeyUsage", "Any Extended Key Usage", NID_anyExtendedKeyUsage,
+     4, &kObjectData[5936], 0},
+    {"MGF1", "mgf1", NID_mgf1, 9, &kObjectData[5940], 0},
+    {"RSASSA-PSS", "rsassaPss", NID_rsassaPss, 9, &kObjectData[5949], 0},
+    {"AES-128-XTS", "aes-128-xts", NID_aes_128_xts, 0, NULL, 0},
+    {"AES-256-XTS", "aes-256-xts", NID_aes_256_xts, 0, NULL, 0},
+    {"RC4-HMAC-MD5", "rc4-hmac-md5", NID_rc4_hmac_md5, 0, NULL, 0},
+    {"AES-128-CBC-HMAC-SHA1", "aes-128-cbc-hmac-sha1",
+     NID_aes_128_cbc_hmac_sha1, 0, NULL, 0},
+    {"AES-192-CBC-HMAC-SHA1", "aes-192-cbc-hmac-sha1",
+     NID_aes_192_cbc_hmac_sha1, 0, NULL, 0},
+    {"AES-256-CBC-HMAC-SHA1", "aes-256-cbc-hmac-sha1",
+     NID_aes_256_cbc_hmac_sha1, 0, NULL, 0},
+    {"RSAES-OAEP", "rsaesOaep", NID_rsaesOaep, 9, &kObjectData[5958], 0},
+    {"dhpublicnumber", "X9.42 DH", NID_dhpublicnumber, 7, &kObjectData[5967],
+     0},
+    {"brainpoolP160r1", "brainpoolP160r1", NID_brainpoolP160r1, 9,
+     &kObjectData[5974], 0},
+    {"brainpoolP160t1", "brainpoolP160t1", NID_brainpoolP160t1, 9,
+     &kObjectData[5983], 0},
+    {"brainpoolP192r1", "brainpoolP192r1", NID_brainpoolP192r1, 9,
+     &kObjectData[5992], 0},
+    {"brainpoolP192t1", "brainpoolP192t1", NID_brainpoolP192t1, 9,
+     &kObjectData[6001], 0},
+    {"brainpoolP224r1", "brainpoolP224r1", NID_brainpoolP224r1, 9,
+     &kObjectData[6010], 0},
+    {"brainpoolP224t1", "brainpoolP224t1", NID_brainpoolP224t1, 9,
+     &kObjectData[6019], 0},
+    {"brainpoolP256r1", "brainpoolP256r1", NID_brainpoolP256r1, 9,
+     &kObjectData[6028], 0},
+    {"brainpoolP256t1", "brainpoolP256t1", NID_brainpoolP256t1, 9,
+     &kObjectData[6037], 0},
+    {"brainpoolP320r1", "brainpoolP320r1", NID_brainpoolP320r1, 9,
+     &kObjectData[6046], 0},
+    {"brainpoolP320t1", "brainpoolP320t1", NID_brainpoolP320t1, 9,
+     &kObjectData[6055], 0},
+    {"brainpoolP384r1", "brainpoolP384r1", NID_brainpoolP384r1, 9,
+     &kObjectData[6064], 0},
+    {"brainpoolP384t1", "brainpoolP384t1", NID_brainpoolP384t1, 9,
+     &kObjectData[6073], 0},
+    {"brainpoolP512r1", "brainpoolP512r1", NID_brainpoolP512r1, 9,
+     &kObjectData[6082], 0},
+    {"brainpoolP512t1", "brainpoolP512t1", NID_brainpoolP512t1, 9,
+     &kObjectData[6091], 0},
+    {"PSPECIFIED", "pSpecified", NID_pSpecified, 9, &kObjectData[6100], 0},
+    {"dhSinglePass-stdDH-sha1kdf-scheme", "dhSinglePass-stdDH-sha1kdf-scheme",
+     NID_dhSinglePass_stdDH_sha1kdf_scheme, 9, &kObjectData[6109], 0},
+    {"dhSinglePass-stdDH-sha224kdf-scheme",
+     "dhSinglePass-stdDH-sha224kdf-scheme",
+     NID_dhSinglePass_stdDH_sha224kdf_scheme, 6, &kObjectData[6118], 0},
+    {"dhSinglePass-stdDH-sha256kdf-scheme",
+     "dhSinglePass-stdDH-sha256kdf-scheme",
+     NID_dhSinglePass_stdDH_sha256kdf_scheme, 6, &kObjectData[6124], 0},
+    {"dhSinglePass-stdDH-sha384kdf-scheme",
+     "dhSinglePass-stdDH-sha384kdf-scheme",
+     NID_dhSinglePass_stdDH_sha384kdf_scheme, 6, &kObjectData[6130], 0},
+    {"dhSinglePass-stdDH-sha512kdf-scheme",
+     "dhSinglePass-stdDH-sha512kdf-scheme",
+     NID_dhSinglePass_stdDH_sha512kdf_scheme, 6, &kObjectData[6136], 0},
+    {"dhSinglePass-cofactorDH-sha1kdf-scheme",
+     "dhSinglePass-cofactorDH-sha1kdf-scheme",
+     NID_dhSinglePass_cofactorDH_sha1kdf_scheme, 9, &kObjectData[6142], 0},
+    {"dhSinglePass-cofactorDH-sha224kdf-scheme",
+     "dhSinglePass-cofactorDH-sha224kdf-scheme",
+     NID_dhSinglePass_cofactorDH_sha224kdf_scheme, 6, &kObjectData[6151], 0},
+    {"dhSinglePass-cofactorDH-sha256kdf-scheme",
+     "dhSinglePass-cofactorDH-sha256kdf-scheme",
+     NID_dhSinglePass_cofactorDH_sha256kdf_scheme, 6, &kObjectData[6157], 0},
+    {"dhSinglePass-cofactorDH-sha384kdf-scheme",
+     "dhSinglePass-cofactorDH-sha384kdf-scheme",
+     NID_dhSinglePass_cofactorDH_sha384kdf_scheme, 6, &kObjectData[6163], 0},
+    {"dhSinglePass-cofactorDH-sha512kdf-scheme",
+     "dhSinglePass-cofactorDH-sha512kdf-scheme",
+     NID_dhSinglePass_cofactorDH_sha512kdf_scheme, 6, &kObjectData[6169], 0},
+    {"dh-std-kdf", "dh-std-kdf", NID_dh_std_kdf, 0, NULL, 0},
+    {"dh-cofactor-kdf", "dh-cofactor-kdf", NID_dh_cofactor_kdf, 0, NULL, 0},
+    {"X25519", "X25519", NID_X25519, 0, NULL, 0},
 };
 
-static const unsigned int kNIDsInShortNameOrder[NUM_SN]={
-364,	/* "AD_DVCS" */
-419,	/* "AES-128-CBC" */
-916,	/* "AES-128-CBC-HMAC-SHA1" */
-421,	/* "AES-128-CFB" */
-650,	/* "AES-128-CFB1" */
-653,	/* "AES-128-CFB8" */
-904,	/* "AES-128-CTR" */
-418,	/* "AES-128-ECB" */
-420,	/* "AES-128-OFB" */
-913,	/* "AES-128-XTS" */
-423,	/* "AES-192-CBC" */
-917,	/* "AES-192-CBC-HMAC-SHA1" */
-425,	/* "AES-192-CFB" */
-651,	/* "AES-192-CFB1" */
-654,	/* "AES-192-CFB8" */
-905,	/* "AES-192-CTR" */
-422,	/* "AES-192-ECB" */
-424,	/* "AES-192-OFB" */
-427,	/* "AES-256-CBC" */
-918,	/* "AES-256-CBC-HMAC-SHA1" */
-429,	/* "AES-256-CFB" */
-652,	/* "AES-256-CFB1" */
-655,	/* "AES-256-CFB8" */
-906,	/* "AES-256-CTR" */
-426,	/* "AES-256-ECB" */
-428,	/* "AES-256-OFB" */
-914,	/* "AES-256-XTS" */
-91,	/* "BF-CBC" */
-93,	/* "BF-CFB" */
-92,	/* "BF-ECB" */
-94,	/* "BF-OFB" */
-14,	/* "C" */
-751,	/* "CAMELLIA-128-CBC" */
-757,	/* "CAMELLIA-128-CFB" */
-760,	/* "CAMELLIA-128-CFB1" */
-763,	/* "CAMELLIA-128-CFB8" */
-754,	/* "CAMELLIA-128-ECB" */
-766,	/* "CAMELLIA-128-OFB" */
-752,	/* "CAMELLIA-192-CBC" */
-758,	/* "CAMELLIA-192-CFB" */
-761,	/* "CAMELLIA-192-CFB1" */
-764,	/* "CAMELLIA-192-CFB8" */
-755,	/* "CAMELLIA-192-ECB" */
-767,	/* "CAMELLIA-192-OFB" */
-753,	/* "CAMELLIA-256-CBC" */
-759,	/* "CAMELLIA-256-CFB" */
-762,	/* "CAMELLIA-256-CFB1" */
-765,	/* "CAMELLIA-256-CFB8" */
-756,	/* "CAMELLIA-256-ECB" */
-768,	/* "CAMELLIA-256-OFB" */
-108,	/* "CAST5-CBC" */
-110,	/* "CAST5-CFB" */
-109,	/* "CAST5-ECB" */
-111,	/* "CAST5-OFB" */
-894,	/* "CMAC" */
-13,	/* "CN" */
-141,	/* "CRLReason" */
-417,	/* "CSPName" */
-367,	/* "CrlID" */
-391,	/* "DC" */
-31,	/* "DES-CBC" */
-643,	/* "DES-CDMF" */
-30,	/* "DES-CFB" */
-656,	/* "DES-CFB1" */
-657,	/* "DES-CFB8" */
-29,	/* "DES-ECB" */
-32,	/* "DES-EDE" */
-43,	/* "DES-EDE-CBC" */
-60,	/* "DES-EDE-CFB" */
-62,	/* "DES-EDE-OFB" */
-33,	/* "DES-EDE3" */
-44,	/* "DES-EDE3-CBC" */
-61,	/* "DES-EDE3-CFB" */
-658,	/* "DES-EDE3-CFB1" */
-659,	/* "DES-EDE3-CFB8" */
-63,	/* "DES-EDE3-OFB" */
-45,	/* "DES-OFB" */
-80,	/* "DESX-CBC" */
-380,	/* "DOD" */
-116,	/* "DSA" */
-66,	/* "DSA-SHA" */
-113,	/* "DSA-SHA1" */
-70,	/* "DSA-SHA1-old" */
-67,	/* "DSA-old" */
-297,	/* "DVCS" */
-99,	/* "GN" */
-855,	/* "HMAC" */
-780,	/* "HMAC-MD5" */
-781,	/* "HMAC-SHA1" */
-381,	/* "IANA" */
-34,	/* "IDEA-CBC" */
-35,	/* "IDEA-CFB" */
-36,	/* "IDEA-ECB" */
-46,	/* "IDEA-OFB" */
-181,	/* "ISO" */
-183,	/* "ISO-US" */
-645,	/* "ITU-T" */
-646,	/* "JOINT-ISO-ITU-T" */
-773,	/* "KISA" */
-15,	/* "L" */
-856,	/* "LocalKeySet" */
- 3,	/* "MD2" */
-257,	/* "MD4" */
- 4,	/* "MD5" */
-114,	/* "MD5-SHA1" */
-95,	/* "MDC2" */
-911,	/* "MGF1" */
-388,	/* "Mail" */
-393,	/* "NULL" */
-404,	/* "NULL" */
-57,	/* "Netscape" */
-366,	/* "Nonce" */
-17,	/* "O" */
-178,	/* "OCSP" */
-180,	/* "OCSPSigning" */
-379,	/* "ORG" */
-18,	/* "OU" */
-749,	/* "Oakley-EC2N-3" */
-750,	/* "Oakley-EC2N-4" */
- 9,	/* "PBE-MD2-DES" */
-168,	/* "PBE-MD2-RC2-64" */
-10,	/* "PBE-MD5-DES" */
-169,	/* "PBE-MD5-RC2-64" */
-147,	/* "PBE-SHA1-2DES" */
-146,	/* "PBE-SHA1-3DES" */
-170,	/* "PBE-SHA1-DES" */
-148,	/* "PBE-SHA1-RC2-128" */
-149,	/* "PBE-SHA1-RC2-40" */
-68,	/* "PBE-SHA1-RC2-64" */
-144,	/* "PBE-SHA1-RC4-128" */
-145,	/* "PBE-SHA1-RC4-40" */
-161,	/* "PBES2" */
-69,	/* "PBKDF2" */
-162,	/* "PBMAC1" */
-127,	/* "PKIX" */
-935,	/* "PSPECIFIED" */
-98,	/* "RC2-40-CBC" */
-166,	/* "RC2-64-CBC" */
-37,	/* "RC2-CBC" */
-39,	/* "RC2-CFB" */
-38,	/* "RC2-ECB" */
-40,	/* "RC2-OFB" */
- 5,	/* "RC4" */
-97,	/* "RC4-40" */
-915,	/* "RC4-HMAC-MD5" */
-120,	/* "RC5-CBC" */
-122,	/* "RC5-CFB" */
-121,	/* "RC5-ECB" */
-123,	/* "RC5-OFB" */
-117,	/* "RIPEMD160" */
-19,	/* "RSA" */
- 7,	/* "RSA-MD2" */
-396,	/* "RSA-MD4" */
- 8,	/* "RSA-MD5" */
-96,	/* "RSA-MDC2" */
-104,	/* "RSA-NP-MD5" */
-119,	/* "RSA-RIPEMD160" */
-42,	/* "RSA-SHA" */
-65,	/* "RSA-SHA1" */
-115,	/* "RSA-SHA1-2" */
-671,	/* "RSA-SHA224" */
-668,	/* "RSA-SHA256" */
-669,	/* "RSA-SHA384" */
-670,	/* "RSA-SHA512" */
-919,	/* "RSAES-OAEP" */
-912,	/* "RSASSA-PSS" */
-777,	/* "SEED-CBC" */
-779,	/* "SEED-CFB" */
-776,	/* "SEED-ECB" */
-778,	/* "SEED-OFB" */
-41,	/* "SHA" */
-64,	/* "SHA1" */
-675,	/* "SHA224" */
-672,	/* "SHA256" */
-673,	/* "SHA384" */
-674,	/* "SHA512" */
-188,	/* "SMIME" */
-167,	/* "SMIME-CAPS" */
-100,	/* "SN" */
-16,	/* "ST" */
-143,	/* "SXNetID" */
-458,	/* "UID" */
- 0,	/* "UNDEF" */
-948,	/* "X25519" */
-11,	/* "X500" */
-378,	/* "X500algorithms" */
-12,	/* "X509" */
-184,	/* "X9-57" */
-185,	/* "X9cm" */
-125,	/* "ZLIB" */
-478,	/* "aRecord" */
-289,	/* "aaControls" */
-287,	/* "ac-auditEntity" */
-397,	/* "ac-proxying" */
-288,	/* "ac-targeting" */
-368,	/* "acceptableResponses" */
-446,	/* "account" */
-363,	/* "ad_timestamping" */
-376,	/* "algorithm" */
-405,	/* "ansi-X9-62" */
-910,	/* "anyExtendedKeyUsage" */
-746,	/* "anyPolicy" */
-370,	/* "archiveCutoff" */
-484,	/* "associatedDomain" */
-485,	/* "associatedName" */
-501,	/* "audio" */
-177,	/* "authorityInfoAccess" */
-90,	/* "authorityKeyIdentifier" */
-882,	/* "authorityRevocationList" */
-87,	/* "basicConstraints" */
-365,	/* "basicOCSPResponse" */
-285,	/* "biometricInfo" */
-921,	/* "brainpoolP160r1" */
-922,	/* "brainpoolP160t1" */
-923,	/* "brainpoolP192r1" */
-924,	/* "brainpoolP192t1" */
-925,	/* "brainpoolP224r1" */
-926,	/* "brainpoolP224t1" */
-927,	/* "brainpoolP256r1" */
-928,	/* "brainpoolP256t1" */
-929,	/* "brainpoolP320r1" */
-930,	/* "brainpoolP320t1" */
-931,	/* "brainpoolP384r1" */
-932,	/* "brainpoolP384t1" */
-933,	/* "brainpoolP512r1" */
-934,	/* "brainpoolP512t1" */
-494,	/* "buildingName" */
-860,	/* "businessCategory" */
-691,	/* "c2onb191v4" */
-692,	/* "c2onb191v5" */
-697,	/* "c2onb239v4" */
-698,	/* "c2onb239v5" */
-684,	/* "c2pnb163v1" */
-685,	/* "c2pnb163v2" */
-686,	/* "c2pnb163v3" */
-687,	/* "c2pnb176v1" */
-693,	/* "c2pnb208w1" */
-699,	/* "c2pnb272w1" */
-700,	/* "c2pnb304w1" */
-702,	/* "c2pnb368w1" */
-688,	/* "c2tnb191v1" */
-689,	/* "c2tnb191v2" */
-690,	/* "c2tnb191v3" */
-694,	/* "c2tnb239v1" */
-695,	/* "c2tnb239v2" */
-696,	/* "c2tnb239v3" */
-701,	/* "c2tnb359v1" */
-703,	/* "c2tnb431r1" */
-881,	/* "cACertificate" */
-483,	/* "cNAMERecord" */
-179,	/* "caIssuers" */
-785,	/* "caRepository" */
-443,	/* "caseIgnoreIA5StringSyntax" */
-152,	/* "certBag" */
-677,	/* "certicom-arc" */
-771,	/* "certificateIssuer" */
-89,	/* "certificatePolicies" */
-883,	/* "certificateRevocationList" */
-54,	/* "challengePassword" */
-407,	/* "characteristic-two-field" */
-395,	/* "clearance" */
-130,	/* "clientAuth" */
-131,	/* "codeSigning" */
-50,	/* "contentType" */
-53,	/* "countersignature" */
-153,	/* "crlBag" */
-103,	/* "crlDistributionPoints" */
-88,	/* "crlNumber" */
-884,	/* "crossCertificatePair" */
-806,	/* "cryptocom" */
-805,	/* "cryptopro" */
-500,	/* "dITRedirect" */
-451,	/* "dNSDomain" */
-495,	/* "dSAQuality" */
-434,	/* "data" */
-390,	/* "dcobject" */
-140,	/* "deltaCRL" */
-891,	/* "deltaRevocationList" */
-107,	/* "description" */
-871,	/* "destinationIndicator" */
-947,	/* "dh-cofactor-kdf" */
-946,	/* "dh-std-kdf" */
-28,	/* "dhKeyAgreement" */
-941,	/* "dhSinglePass-cofactorDH-sha1kdf-scheme" */
-942,	/* "dhSinglePass-cofactorDH-sha224kdf-scheme" */
-943,	/* "dhSinglePass-cofactorDH-sha256kdf-scheme" */
-944,	/* "dhSinglePass-cofactorDH-sha384kdf-scheme" */
-945,	/* "dhSinglePass-cofactorDH-sha512kdf-scheme" */
-936,	/* "dhSinglePass-stdDH-sha1kdf-scheme" */
-937,	/* "dhSinglePass-stdDH-sha224kdf-scheme" */
-938,	/* "dhSinglePass-stdDH-sha256kdf-scheme" */
-939,	/* "dhSinglePass-stdDH-sha384kdf-scheme" */
-940,	/* "dhSinglePass-stdDH-sha512kdf-scheme" */
-920,	/* "dhpublicnumber" */
-382,	/* "directory" */
-887,	/* "distinguishedName" */
-892,	/* "dmdName" */
-174,	/* "dnQualifier" */
-447,	/* "document" */
-471,	/* "documentAuthor" */
-468,	/* "documentIdentifier" */
-472,	/* "documentLocation" */
-502,	/* "documentPublisher" */
-449,	/* "documentSeries" */
-469,	/* "documentTitle" */
-470,	/* "documentVersion" */
-392,	/* "domain" */
-452,	/* "domainRelatedObject" */
-802,	/* "dsa_with_SHA224" */
-803,	/* "dsa_with_SHA256" */
-791,	/* "ecdsa-with-Recommended" */
-416,	/* "ecdsa-with-SHA1" */
-793,	/* "ecdsa-with-SHA224" */
-794,	/* "ecdsa-with-SHA256" */
-795,	/* "ecdsa-with-SHA384" */
-796,	/* "ecdsa-with-SHA512" */
-792,	/* "ecdsa-with-Specified" */
-48,	/* "emailAddress" */
-132,	/* "emailProtection" */
-885,	/* "enhancedSearchGuide" */
-389,	/* "enterprises" */
-384,	/* "experimental" */
-172,	/* "extReq" */
-56,	/* "extendedCertificateAttributes" */
-126,	/* "extendedKeyUsage" */
-372,	/* "extendedStatus" */
-867,	/* "facsimileTelephoneNumber" */
-462,	/* "favouriteDrink" */
-857,	/* "freshestCRL" */
-453,	/* "friendlyCountry" */
-490,	/* "friendlyCountryName" */
-156,	/* "friendlyName" */
-509,	/* "generationQualifier" */
-815,	/* "gost-mac" */
-811,	/* "gost2001" */
-851,	/* "gost2001cc" */
-813,	/* "gost89" */
-814,	/* "gost89-cnt" */
-812,	/* "gost94" */
-850,	/* "gost94cc" */
-797,	/* "hmacWithMD5" */
-163,	/* "hmacWithSHA1" */
-798,	/* "hmacWithSHA224" */
-799,	/* "hmacWithSHA256" */
-800,	/* "hmacWithSHA384" */
-801,	/* "hmacWithSHA512" */
-432,	/* "holdInstructionCallIssuer" */
-430,	/* "holdInstructionCode" */
-431,	/* "holdInstructionNone" */
-433,	/* "holdInstructionReject" */
-486,	/* "homePostalAddress" */
-473,	/* "homeTelephoneNumber" */
-466,	/* "host" */
-889,	/* "houseIdentifier" */
-442,	/* "iA5StringSyntax" */
-783,	/* "id-DHBasedMac" */
-824,	/* "id-Gost28147-89-CryptoPro-A-ParamSet" */
-825,	/* "id-Gost28147-89-CryptoPro-B-ParamSet" */
-826,	/* "id-Gost28147-89-CryptoPro-C-ParamSet" */
-827,	/* "id-Gost28147-89-CryptoPro-D-ParamSet" */
-819,	/* "id-Gost28147-89-CryptoPro-KeyMeshing" */
-829,	/* "id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet" */
-828,	/* "id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet" */
-830,	/* "id-Gost28147-89-CryptoPro-RIC-1-ParamSet" */
-820,	/* "id-Gost28147-89-None-KeyMeshing" */
-823,	/* "id-Gost28147-89-TestParamSet" */
-849,	/* "id-Gost28147-89-cc" */
-840,	/* "id-GostR3410-2001-CryptoPro-A-ParamSet" */
-841,	/* "id-GostR3410-2001-CryptoPro-B-ParamSet" */
-842,	/* "id-GostR3410-2001-CryptoPro-C-ParamSet" */
-843,	/* "id-GostR3410-2001-CryptoPro-XchA-ParamSet" */
-844,	/* "id-GostR3410-2001-CryptoPro-XchB-ParamSet" */
-854,	/* "id-GostR3410-2001-ParamSet-cc" */
-839,	/* "id-GostR3410-2001-TestParamSet" */
-817,	/* "id-GostR3410-2001DH" */
-832,	/* "id-GostR3410-94-CryptoPro-A-ParamSet" */
-833,	/* "id-GostR3410-94-CryptoPro-B-ParamSet" */
-834,	/* "id-GostR3410-94-CryptoPro-C-ParamSet" */
-835,	/* "id-GostR3410-94-CryptoPro-D-ParamSet" */
-836,	/* "id-GostR3410-94-CryptoPro-XchA-ParamSet" */
-837,	/* "id-GostR3410-94-CryptoPro-XchB-ParamSet" */
-838,	/* "id-GostR3410-94-CryptoPro-XchC-ParamSet" */
-831,	/* "id-GostR3410-94-TestParamSet" */
-845,	/* "id-GostR3410-94-a" */
-846,	/* "id-GostR3410-94-aBis" */
-847,	/* "id-GostR3410-94-b" */
-848,	/* "id-GostR3410-94-bBis" */
-818,	/* "id-GostR3410-94DH" */
-822,	/* "id-GostR3411-94-CryptoProParamSet" */
-821,	/* "id-GostR3411-94-TestParamSet" */
-807,	/* "id-GostR3411-94-with-GostR3410-2001" */
-853,	/* "id-GostR3411-94-with-GostR3410-2001-cc" */
-808,	/* "id-GostR3411-94-with-GostR3410-94" */
-852,	/* "id-GostR3411-94-with-GostR3410-94-cc" */
-810,	/* "id-HMACGostR3411-94" */
-782,	/* "id-PasswordBasedMAC" */
-266,	/* "id-aca" */
-355,	/* "id-aca-accessIdentity" */
-354,	/* "id-aca-authenticationInfo" */
-356,	/* "id-aca-chargingIdentity" */
-399,	/* "id-aca-encAttrs" */
-357,	/* "id-aca-group" */
-358,	/* "id-aca-role" */
-176,	/* "id-ad" */
-896,	/* "id-aes128-CCM" */
-895,	/* "id-aes128-GCM" */
-788,	/* "id-aes128-wrap" */
-897,	/* "id-aes128-wrap-pad" */
-899,	/* "id-aes192-CCM" */
-898,	/* "id-aes192-GCM" */
-789,	/* "id-aes192-wrap" */
-900,	/* "id-aes192-wrap-pad" */
-902,	/* "id-aes256-CCM" */
-901,	/* "id-aes256-GCM" */
-790,	/* "id-aes256-wrap" */
-903,	/* "id-aes256-wrap-pad" */
-262,	/* "id-alg" */
-893,	/* "id-alg-PWRI-KEK" */
-323,	/* "id-alg-des40" */
-326,	/* "id-alg-dh-pop" */
-325,	/* "id-alg-dh-sig-hmac-sha1" */
-324,	/* "id-alg-noSignature" */
-907,	/* "id-camellia128-wrap" */
-908,	/* "id-camellia192-wrap" */
-909,	/* "id-camellia256-wrap" */
-268,	/* "id-cct" */
-361,	/* "id-cct-PKIData" */
-362,	/* "id-cct-PKIResponse" */
-360,	/* "id-cct-crs" */
-81,	/* "id-ce" */
-680,	/* "id-characteristic-two-basis" */
-263,	/* "id-cmc" */
-334,	/* "id-cmc-addExtensions" */
-346,	/* "id-cmc-confirmCertAcceptance" */
-330,	/* "id-cmc-dataReturn" */
-336,	/* "id-cmc-decryptedPOP" */
-335,	/* "id-cmc-encryptedPOP" */
-339,	/* "id-cmc-getCRL" */
-338,	/* "id-cmc-getCert" */
-328,	/* "id-cmc-identification" */
-329,	/* "id-cmc-identityProof" */
-337,	/* "id-cmc-lraPOPWitness" */
-344,	/* "id-cmc-popLinkRandom" */
-345,	/* "id-cmc-popLinkWitness" */
-343,	/* "id-cmc-queryPending" */
-333,	/* "id-cmc-recipientNonce" */
-341,	/* "id-cmc-regInfo" */
-342,	/* "id-cmc-responseInfo" */
-340,	/* "id-cmc-revokeRequest" */
-332,	/* "id-cmc-senderNonce" */
-327,	/* "id-cmc-statusInfo" */
-331,	/* "id-cmc-transactionId" */
-787,	/* "id-ct-asciiTextWithCRLF" */
-408,	/* "id-ecPublicKey" */
-508,	/* "id-hex-multipart-message" */
-507,	/* "id-hex-partial-message" */
-260,	/* "id-it" */
-302,	/* "id-it-caKeyUpdateInfo" */
-298,	/* "id-it-caProtEncCert" */
-311,	/* "id-it-confirmWaitTime" */
-303,	/* "id-it-currentCRL" */
-300,	/* "id-it-encKeyPairTypes" */
-310,	/* "id-it-implicitConfirm" */
-308,	/* "id-it-keyPairParamRep" */
-307,	/* "id-it-keyPairParamReq" */
-312,	/* "id-it-origPKIMessage" */
-301,	/* "id-it-preferredSymmAlg" */
-309,	/* "id-it-revPassphrase" */
-299,	/* "id-it-signKeyPairTypes" */
-305,	/* "id-it-subscriptionRequest" */
-306,	/* "id-it-subscriptionResponse" */
-784,	/* "id-it-suppLangTags" */
-304,	/* "id-it-unsupportedOIDs" */
-128,	/* "id-kp" */
-280,	/* "id-mod-attribute-cert" */
-274,	/* "id-mod-cmc" */
-277,	/* "id-mod-cmp" */
-284,	/* "id-mod-cmp2000" */
-273,	/* "id-mod-crmf" */
-283,	/* "id-mod-dvcs" */
-275,	/* "id-mod-kea-profile-88" */
-276,	/* "id-mod-kea-profile-93" */
-282,	/* "id-mod-ocsp" */
-278,	/* "id-mod-qualified-cert-88" */
-279,	/* "id-mod-qualified-cert-93" */
-281,	/* "id-mod-timestamp-protocol" */
-264,	/* "id-on" */
-858,	/* "id-on-permanentIdentifier" */
-347,	/* "id-on-personalData" */
-265,	/* "id-pda" */
-352,	/* "id-pda-countryOfCitizenship" */
-353,	/* "id-pda-countryOfResidence" */
-348,	/* "id-pda-dateOfBirth" */
-351,	/* "id-pda-gender" */
-349,	/* "id-pda-placeOfBirth" */
-175,	/* "id-pe" */
-261,	/* "id-pkip" */
-258,	/* "id-pkix-mod" */
-269,	/* "id-pkix1-explicit-88" */
-271,	/* "id-pkix1-explicit-93" */
-270,	/* "id-pkix1-implicit-88" */
-272,	/* "id-pkix1-implicit-93" */
-662,	/* "id-ppl" */
-664,	/* "id-ppl-anyLanguage" */
-667,	/* "id-ppl-independent" */
-665,	/* "id-ppl-inheritAll" */
-267,	/* "id-qcs" */
-359,	/* "id-qcs-pkixQCSyntax-v1" */
-259,	/* "id-qt" */
-164,	/* "id-qt-cps" */
-165,	/* "id-qt-unotice" */
-313,	/* "id-regCtrl" */
-316,	/* "id-regCtrl-authenticator" */
-319,	/* "id-regCtrl-oldCertID" */
-318,	/* "id-regCtrl-pkiArchiveOptions" */
-317,	/* "id-regCtrl-pkiPublicationInfo" */
-320,	/* "id-regCtrl-protocolEncrKey" */
-315,	/* "id-regCtrl-regToken" */
-314,	/* "id-regInfo" */
-322,	/* "id-regInfo-certReq" */
-321,	/* "id-regInfo-utf8Pairs" */
-512,	/* "id-set" */
-191,	/* "id-smime-aa" */
-215,	/* "id-smime-aa-contentHint" */
-218,	/* "id-smime-aa-contentIdentifier" */
-221,	/* "id-smime-aa-contentReference" */
-240,	/* "id-smime-aa-dvcs-dvc" */
-217,	/* "id-smime-aa-encapContentType" */
-222,	/* "id-smime-aa-encrypKeyPref" */
-220,	/* "id-smime-aa-equivalentLabels" */
-232,	/* "id-smime-aa-ets-CertificateRefs" */
-233,	/* "id-smime-aa-ets-RevocationRefs" */
-238,	/* "id-smime-aa-ets-archiveTimeStamp" */
-237,	/* "id-smime-aa-ets-certCRLTimestamp" */
-234,	/* "id-smime-aa-ets-certValues" */
-227,	/* "id-smime-aa-ets-commitmentType" */
-231,	/* "id-smime-aa-ets-contentTimestamp" */
-236,	/* "id-smime-aa-ets-escTimeStamp" */
-230,	/* "id-smime-aa-ets-otherSigCert" */
-235,	/* "id-smime-aa-ets-revocationValues" */
-226,	/* "id-smime-aa-ets-sigPolicyId" */
-229,	/* "id-smime-aa-ets-signerAttr" */
-228,	/* "id-smime-aa-ets-signerLocation" */
-219,	/* "id-smime-aa-macValue" */
-214,	/* "id-smime-aa-mlExpandHistory" */
-216,	/* "id-smime-aa-msgSigDigest" */
-212,	/* "id-smime-aa-receiptRequest" */
-213,	/* "id-smime-aa-securityLabel" */
-239,	/* "id-smime-aa-signatureType" */
-223,	/* "id-smime-aa-signingCertificate" */
-224,	/* "id-smime-aa-smimeEncryptCerts" */
-225,	/* "id-smime-aa-timeStampToken" */
-192,	/* "id-smime-alg" */
-243,	/* "id-smime-alg-3DESwrap" */
-246,	/* "id-smime-alg-CMS3DESwrap" */
-247,	/* "id-smime-alg-CMSRC2wrap" */
-245,	/* "id-smime-alg-ESDH" */
-241,	/* "id-smime-alg-ESDHwith3DES" */
-242,	/* "id-smime-alg-ESDHwithRC2" */
-244,	/* "id-smime-alg-RC2wrap" */
-193,	/* "id-smime-cd" */
-248,	/* "id-smime-cd-ldap" */
-190,	/* "id-smime-ct" */
-210,	/* "id-smime-ct-DVCSRequestData" */
-211,	/* "id-smime-ct-DVCSResponseData" */
-208,	/* "id-smime-ct-TDTInfo" */
-207,	/* "id-smime-ct-TSTInfo" */
-205,	/* "id-smime-ct-authData" */
-786,	/* "id-smime-ct-compressedData" */
-209,	/* "id-smime-ct-contentInfo" */
-206,	/* "id-smime-ct-publishCert" */
-204,	/* "id-smime-ct-receipt" */
-195,	/* "id-smime-cti" */
-255,	/* "id-smime-cti-ets-proofOfApproval" */
-256,	/* "id-smime-cti-ets-proofOfCreation" */
-253,	/* "id-smime-cti-ets-proofOfDelivery" */
-251,	/* "id-smime-cti-ets-proofOfOrigin" */
-252,	/* "id-smime-cti-ets-proofOfReceipt" */
-254,	/* "id-smime-cti-ets-proofOfSender" */
-189,	/* "id-smime-mod" */
-196,	/* "id-smime-mod-cms" */
-197,	/* "id-smime-mod-ess" */
-202,	/* "id-smime-mod-ets-eSigPolicy-88" */
-203,	/* "id-smime-mod-ets-eSigPolicy-97" */
-200,	/* "id-smime-mod-ets-eSignature-88" */
-201,	/* "id-smime-mod-ets-eSignature-97" */
-199,	/* "id-smime-mod-msg-v3" */
-198,	/* "id-smime-mod-oid" */
-194,	/* "id-smime-spq" */
-250,	/* "id-smime-spq-ets-sqt-unotice" */
-249,	/* "id-smime-spq-ets-sqt-uri" */
-676,	/* "identified-organization" */
-461,	/* "info" */
-748,	/* "inhibitAnyPolicy" */
-101,	/* "initials" */
-647,	/* "international-organizations" */
-869,	/* "internationaliSDNNumber" */
-142,	/* "invalidityDate" */
-294,	/* "ipsecEndSystem" */
-295,	/* "ipsecTunnel" */
-296,	/* "ipsecUser" */
-86,	/* "issuerAltName" */
-770,	/* "issuingDistributionPoint" */
-492,	/* "janetMailbox" */
-150,	/* "keyBag" */
-83,	/* "keyUsage" */
-477,	/* "lastModifiedBy" */
-476,	/* "lastModifiedTime" */
-157,	/* "localKeyID" */
-480,	/* "mXRecord" */
-460,	/* "mail" */
-493,	/* "mailPreferenceOption" */
-467,	/* "manager" */
-809,	/* "md_gost94" */
-875,	/* "member" */
-182,	/* "member-body" */
-51,	/* "messageDigest" */
-383,	/* "mgmt" */
-504,	/* "mime-mhs" */
-506,	/* "mime-mhs-bodies" */
-505,	/* "mime-mhs-headings" */
-488,	/* "mobileTelephoneNumber" */
-136,	/* "msCTLSign" */
-135,	/* "msCodeCom" */
-134,	/* "msCodeInd" */
-138,	/* "msEFS" */
-171,	/* "msExtReq" */
-137,	/* "msSGC" */
-648,	/* "msSmartcardLogin" */
-649,	/* "msUPN" */
-481,	/* "nSRecord" */
-173,	/* "name" */
-666,	/* "nameConstraints" */
-369,	/* "noCheck" */
-403,	/* "noRevAvail" */
-72,	/* "nsBaseUrl" */
-76,	/* "nsCaPolicyUrl" */
-74,	/* "nsCaRevocationUrl" */
-58,	/* "nsCertExt" */
-79,	/* "nsCertSequence" */
-71,	/* "nsCertType" */
-78,	/* "nsComment" */
-59,	/* "nsDataType" */
-75,	/* "nsRenewalUrl" */
-73,	/* "nsRevocationUrl" */
-139,	/* "nsSGC" */
-77,	/* "nsSslServerName" */
-681,	/* "onBasis" */
-491,	/* "organizationalStatus" */
-475,	/* "otherMailbox" */
-876,	/* "owner" */
-489,	/* "pagerTelephoneNumber" */
-374,	/* "path" */
-112,	/* "pbeWithMD5AndCast5CBC" */
-499,	/* "personalSignature" */
-487,	/* "personalTitle" */
-464,	/* "photo" */
-863,	/* "physicalDeliveryOfficeName" */
-437,	/* "pilot" */
-439,	/* "pilotAttributeSyntax" */
-438,	/* "pilotAttributeType" */
-479,	/* "pilotAttributeType27" */
-456,	/* "pilotDSA" */
-441,	/* "pilotGroups" */
-444,	/* "pilotObject" */
-440,	/* "pilotObjectClass" */
-455,	/* "pilotOrganization" */
-445,	/* "pilotPerson" */
- 2,	/* "pkcs" */
-186,	/* "pkcs1" */
-27,	/* "pkcs3" */
-187,	/* "pkcs5" */
-20,	/* "pkcs7" */
-21,	/* "pkcs7-data" */
-25,	/* "pkcs7-digestData" */
-26,	/* "pkcs7-encryptedData" */
-23,	/* "pkcs7-envelopedData" */
-24,	/* "pkcs7-signedAndEnvelopedData" */
-22,	/* "pkcs7-signedData" */
-151,	/* "pkcs8ShroudedKeyBag" */
-47,	/* "pkcs9" */
-401,	/* "policyConstraints" */
-747,	/* "policyMappings" */
-862,	/* "postOfficeBox" */
-861,	/* "postalAddress" */
-661,	/* "postalCode" */
-683,	/* "ppBasis" */
-872,	/* "preferredDeliveryMethod" */
-873,	/* "presentationAddress" */
-816,	/* "prf-gostr3411-94" */
-406,	/* "prime-field" */
-409,	/* "prime192v1" */
-410,	/* "prime192v2" */
-411,	/* "prime192v3" */
-412,	/* "prime239v1" */
-413,	/* "prime239v2" */
-414,	/* "prime239v3" */
-415,	/* "prime256v1" */
-385,	/* "private" */
-84,	/* "privateKeyUsagePeriod" */
-886,	/* "protocolInformation" */
-663,	/* "proxyCertInfo" */
-510,	/* "pseudonym" */
-435,	/* "pss" */
-286,	/* "qcStatements" */
-457,	/* "qualityLabelledData" */
-450,	/* "rFC822localPart" */
-870,	/* "registeredAddress" */
-400,	/* "role" */
-877,	/* "roleOccupant" */
-448,	/* "room" */
-463,	/* "roomNumber" */
- 6,	/* "rsaEncryption" */
-644,	/* "rsaOAEPEncryptionSET" */
-377,	/* "rsaSignature" */
- 1,	/* "rsadsi" */
-482,	/* "sOARecord" */
-155,	/* "safeContentsBag" */
-291,	/* "sbgp-autonomousSysNum" */
-290,	/* "sbgp-ipAddrBlock" */
-292,	/* "sbgp-routerIdentifier" */
-159,	/* "sdsiCertificate" */
-859,	/* "searchGuide" */
-704,	/* "secp112r1" */
-705,	/* "secp112r2" */
-706,	/* "secp128r1" */
-707,	/* "secp128r2" */
-708,	/* "secp160k1" */
-709,	/* "secp160r1" */
-710,	/* "secp160r2" */
-711,	/* "secp192k1" */
-712,	/* "secp224k1" */
-713,	/* "secp224r1" */
-714,	/* "secp256k1" */
-715,	/* "secp384r1" */
-716,	/* "secp521r1" */
-154,	/* "secretBag" */
-474,	/* "secretary" */
-717,	/* "sect113r1" */
-718,	/* "sect113r2" */
-719,	/* "sect131r1" */
-720,	/* "sect131r2" */
-721,	/* "sect163k1" */
-722,	/* "sect163r1" */
-723,	/* "sect163r2" */
-724,	/* "sect193r1" */
-725,	/* "sect193r2" */
-726,	/* "sect233k1" */
-727,	/* "sect233r1" */
-728,	/* "sect239k1" */
-729,	/* "sect283k1" */
-730,	/* "sect283r1" */
-731,	/* "sect409k1" */
-732,	/* "sect409r1" */
-733,	/* "sect571k1" */
-734,	/* "sect571r1" */
-386,	/* "security" */
-878,	/* "seeAlso" */
-394,	/* "selected-attribute-types" */
-105,	/* "serialNumber" */
-129,	/* "serverAuth" */
-371,	/* "serviceLocator" */
-625,	/* "set-addPolicy" */
-515,	/* "set-attr" */
-518,	/* "set-brand" */
-638,	/* "set-brand-AmericanExpress" */
-637,	/* "set-brand-Diners" */
-636,	/* "set-brand-IATA-ATA" */
-639,	/* "set-brand-JCB" */
-641,	/* "set-brand-MasterCard" */
-642,	/* "set-brand-Novus" */
-640,	/* "set-brand-Visa" */
-517,	/* "set-certExt" */
-513,	/* "set-ctype" */
-514,	/* "set-msgExt" */
-516,	/* "set-policy" */
-607,	/* "set-policy-root" */
-624,	/* "set-rootKeyThumb" */
-620,	/* "setAttr-Cert" */
-631,	/* "setAttr-GenCryptgrm" */
-623,	/* "setAttr-IssCap" */
-628,	/* "setAttr-IssCap-CVM" */
-630,	/* "setAttr-IssCap-Sig" */
-629,	/* "setAttr-IssCap-T2" */
-621,	/* "setAttr-PGWYcap" */
-635,	/* "setAttr-SecDevSig" */
-632,	/* "setAttr-T2Enc" */
-633,	/* "setAttr-T2cleartxt" */
-634,	/* "setAttr-TokICCsig" */
-627,	/* "setAttr-Token-B0Prime" */
-626,	/* "setAttr-Token-EMV" */
-622,	/* "setAttr-TokenType" */
-619,	/* "setCext-IssuerCapabilities" */
-615,	/* "setCext-PGWYcapabilities" */
-616,	/* "setCext-TokenIdentifier" */
-618,	/* "setCext-TokenType" */
-617,	/* "setCext-Track2Data" */
-611,	/* "setCext-cCertRequired" */
-609,	/* "setCext-certType" */
-608,	/* "setCext-hashedRoot" */
-610,	/* "setCext-merchData" */
-613,	/* "setCext-setExt" */
-614,	/* "setCext-setQualf" */
-612,	/* "setCext-tunneling" */
-540,	/* "setct-AcqCardCodeMsg" */
-576,	/* "setct-AcqCardCodeMsgTBE" */
-570,	/* "setct-AuthReqTBE" */
-534,	/* "setct-AuthReqTBS" */
-527,	/* "setct-AuthResBaggage" */
-571,	/* "setct-AuthResTBE" */
-572,	/* "setct-AuthResTBEX" */
-535,	/* "setct-AuthResTBS" */
-536,	/* "setct-AuthResTBSX" */
-528,	/* "setct-AuthRevReqBaggage" */
-577,	/* "setct-AuthRevReqTBE" */
-541,	/* "setct-AuthRevReqTBS" */
-529,	/* "setct-AuthRevResBaggage" */
-542,	/* "setct-AuthRevResData" */
-578,	/* "setct-AuthRevResTBE" */
-579,	/* "setct-AuthRevResTBEB" */
-543,	/* "setct-AuthRevResTBS" */
-573,	/* "setct-AuthTokenTBE" */
-537,	/* "setct-AuthTokenTBS" */
-600,	/* "setct-BCIDistributionTBS" */
-558,	/* "setct-BatchAdminReqData" */
-592,	/* "setct-BatchAdminReqTBE" */
-559,	/* "setct-BatchAdminResData" */
-593,	/* "setct-BatchAdminResTBE" */
-599,	/* "setct-CRLNotificationResTBS" */
-598,	/* "setct-CRLNotificationTBS" */
-580,	/* "setct-CapReqTBE" */
-581,	/* "setct-CapReqTBEX" */
-544,	/* "setct-CapReqTBS" */
-545,	/* "setct-CapReqTBSX" */
-546,	/* "setct-CapResData" */
-582,	/* "setct-CapResTBE" */
-583,	/* "setct-CapRevReqTBE" */
-584,	/* "setct-CapRevReqTBEX" */
-547,	/* "setct-CapRevReqTBS" */
-548,	/* "setct-CapRevReqTBSX" */
-549,	/* "setct-CapRevResData" */
-585,	/* "setct-CapRevResTBE" */
-538,	/* "setct-CapTokenData" */
-530,	/* "setct-CapTokenSeq" */
-574,	/* "setct-CapTokenTBE" */
-575,	/* "setct-CapTokenTBEX" */
-539,	/* "setct-CapTokenTBS" */
-560,	/* "setct-CardCInitResTBS" */
-566,	/* "setct-CertInqReqTBS" */
-563,	/* "setct-CertReqData" */
-595,	/* "setct-CertReqTBE" */
-596,	/* "setct-CertReqTBEX" */
-564,	/* "setct-CertReqTBS" */
-565,	/* "setct-CertResData" */
-597,	/* "setct-CertResTBE" */
-586,	/* "setct-CredReqTBE" */
-587,	/* "setct-CredReqTBEX" */
-550,	/* "setct-CredReqTBS" */
-551,	/* "setct-CredReqTBSX" */
-552,	/* "setct-CredResData" */
-588,	/* "setct-CredResTBE" */
-589,	/* "setct-CredRevReqTBE" */
-590,	/* "setct-CredRevReqTBEX" */
-553,	/* "setct-CredRevReqTBS" */
-554,	/* "setct-CredRevReqTBSX" */
-555,	/* "setct-CredRevResData" */
-591,	/* "setct-CredRevResTBE" */
-567,	/* "setct-ErrorTBS" */
-526,	/* "setct-HODInput" */
-561,	/* "setct-MeAqCInitResTBS" */
-522,	/* "setct-OIData" */
-519,	/* "setct-PANData" */
-521,	/* "setct-PANOnly" */
-520,	/* "setct-PANToken" */
-556,	/* "setct-PCertReqData" */
-557,	/* "setct-PCertResTBS" */
-523,	/* "setct-PI" */
-532,	/* "setct-PI-TBS" */
-524,	/* "setct-PIData" */
-525,	/* "setct-PIDataUnsigned" */
-568,	/* "setct-PIDualSignedTBE" */
-569,	/* "setct-PIUnsignedTBE" */
-531,	/* "setct-PInitResData" */
-533,	/* "setct-PResData" */
-594,	/* "setct-RegFormReqTBE" */
-562,	/* "setct-RegFormResTBS" */
-606,	/* "setext-cv" */
-601,	/* "setext-genCrypt" */
-602,	/* "setext-miAuth" */
-604,	/* "setext-pinAny" */
-603,	/* "setext-pinSecure" */
-605,	/* "setext-track2" */
-52,	/* "signingTime" */
-454,	/* "simpleSecurityObject" */
-496,	/* "singleLevelQuality" */
-387,	/* "snmpv2" */
-660,	/* "street" */
-85,	/* "subjectAltName" */
-769,	/* "subjectDirectoryAttributes" */
-398,	/* "subjectInfoAccess" */
-82,	/* "subjectKeyIdentifier" */
-498,	/* "subtreeMaximumQuality" */
-497,	/* "subtreeMinimumQuality" */
-890,	/* "supportedAlgorithms" */
-874,	/* "supportedApplicationContext" */
-402,	/* "targetInformation" */
-864,	/* "telephoneNumber" */
-866,	/* "teletexTerminalIdentifier" */
-865,	/* "telexNumber" */
-459,	/* "textEncodedORAddress" */
-293,	/* "textNotice" */
-133,	/* "timeStamping" */
-106,	/* "title" */
-682,	/* "tpBasis" */
-375,	/* "trustRoot" */
-436,	/* "ucl" */
-888,	/* "uniqueMember" */
-55,	/* "unstructuredAddress" */
-49,	/* "unstructuredName" */
-880,	/* "userCertificate" */
-465,	/* "userClass" */
-879,	/* "userPassword" */
-373,	/* "valid" */
-678,	/* "wap" */
-679,	/* "wap-wsg" */
-735,	/* "wap-wsg-idm-ecid-wtls1" */
-743,	/* "wap-wsg-idm-ecid-wtls10" */
-744,	/* "wap-wsg-idm-ecid-wtls11" */
-745,	/* "wap-wsg-idm-ecid-wtls12" */
-736,	/* "wap-wsg-idm-ecid-wtls3" */
-737,	/* "wap-wsg-idm-ecid-wtls4" */
-738,	/* "wap-wsg-idm-ecid-wtls5" */
-739,	/* "wap-wsg-idm-ecid-wtls6" */
-740,	/* "wap-wsg-idm-ecid-wtls7" */
-741,	/* "wap-wsg-idm-ecid-wtls8" */
-742,	/* "wap-wsg-idm-ecid-wtls9" */
-804,	/* "whirlpool" */
-868,	/* "x121Address" */
-503,	/* "x500UniqueIdentifier" */
-158,	/* "x509Certificate" */
-160,	/* "x509Crl" */
+static const unsigned kNIDsInShortNameOrder[] = {
+    364 /* AD_DVCS */,
+    419 /* AES-128-CBC */,
+    916 /* AES-128-CBC-HMAC-SHA1 */,
+    421 /* AES-128-CFB */,
+    650 /* AES-128-CFB1 */,
+    653 /* AES-128-CFB8 */,
+    904 /* AES-128-CTR */,
+    418 /* AES-128-ECB */,
+    420 /* AES-128-OFB */,
+    913 /* AES-128-XTS */,
+    423 /* AES-192-CBC */,
+    917 /* AES-192-CBC-HMAC-SHA1 */,
+    425 /* AES-192-CFB */,
+    651 /* AES-192-CFB1 */,
+    654 /* AES-192-CFB8 */,
+    905 /* AES-192-CTR */,
+    422 /* AES-192-ECB */,
+    424 /* AES-192-OFB */,
+    427 /* AES-256-CBC */,
+    918 /* AES-256-CBC-HMAC-SHA1 */,
+    429 /* AES-256-CFB */,
+    652 /* AES-256-CFB1 */,
+    655 /* AES-256-CFB8 */,
+    906 /* AES-256-CTR */,
+    426 /* AES-256-ECB */,
+    428 /* AES-256-OFB */,
+    914 /* AES-256-XTS */,
+    91 /* BF-CBC */,
+    93 /* BF-CFB */,
+    92 /* BF-ECB */,
+    94 /* BF-OFB */,
+    14 /* C */,
+    751 /* CAMELLIA-128-CBC */,
+    757 /* CAMELLIA-128-CFB */,
+    760 /* CAMELLIA-128-CFB1 */,
+    763 /* CAMELLIA-128-CFB8 */,
+    754 /* CAMELLIA-128-ECB */,
+    766 /* CAMELLIA-128-OFB */,
+    752 /* CAMELLIA-192-CBC */,
+    758 /* CAMELLIA-192-CFB */,
+    761 /* CAMELLIA-192-CFB1 */,
+    764 /* CAMELLIA-192-CFB8 */,
+    755 /* CAMELLIA-192-ECB */,
+    767 /* CAMELLIA-192-OFB */,
+    753 /* CAMELLIA-256-CBC */,
+    759 /* CAMELLIA-256-CFB */,
+    762 /* CAMELLIA-256-CFB1 */,
+    765 /* CAMELLIA-256-CFB8 */,
+    756 /* CAMELLIA-256-ECB */,
+    768 /* CAMELLIA-256-OFB */,
+    108 /* CAST5-CBC */,
+    110 /* CAST5-CFB */,
+    109 /* CAST5-ECB */,
+    111 /* CAST5-OFB */,
+    894 /* CMAC */,
+    13 /* CN */,
+    141 /* CRLReason */,
+    417 /* CSPName */,
+    367 /* CrlID */,
+    391 /* DC */,
+    31 /* DES-CBC */,
+    643 /* DES-CDMF */,
+    30 /* DES-CFB */,
+    656 /* DES-CFB1 */,
+    657 /* DES-CFB8 */,
+    29 /* DES-ECB */,
+    32 /* DES-EDE */,
+    43 /* DES-EDE-CBC */,
+    60 /* DES-EDE-CFB */,
+    62 /* DES-EDE-OFB */,
+    33 /* DES-EDE3 */,
+    44 /* DES-EDE3-CBC */,
+    61 /* DES-EDE3-CFB */,
+    658 /* DES-EDE3-CFB1 */,
+    659 /* DES-EDE3-CFB8 */,
+    63 /* DES-EDE3-OFB */,
+    45 /* DES-OFB */,
+    80 /* DESX-CBC */,
+    380 /* DOD */,
+    116 /* DSA */,
+    66 /* DSA-SHA */,
+    113 /* DSA-SHA1 */,
+    70 /* DSA-SHA1-old */,
+    67 /* DSA-old */,
+    297 /* DVCS */,
+    99 /* GN */,
+    855 /* HMAC */,
+    780 /* HMAC-MD5 */,
+    781 /* HMAC-SHA1 */,
+    381 /* IANA */,
+    34 /* IDEA-CBC */,
+    35 /* IDEA-CFB */,
+    36 /* IDEA-ECB */,
+    46 /* IDEA-OFB */,
+    181 /* ISO */,
+    183 /* ISO-US */,
+    645 /* ITU-T */,
+    646 /* JOINT-ISO-ITU-T */,
+    773 /* KISA */,
+    15 /* L */,
+    856 /* LocalKeySet */,
+    3 /* MD2 */,
+    257 /* MD4 */,
+    4 /* MD5 */,
+    114 /* MD5-SHA1 */,
+    95 /* MDC2 */,
+    911 /* MGF1 */,
+    388 /* Mail */,
+    57 /* Netscape */,
+    366 /* Nonce */,
+    17 /* O */,
+    178 /* OCSP */,
+    180 /* OCSPSigning */,
+    379 /* ORG */,
+    18 /* OU */,
+    749 /* Oakley-EC2N-3 */,
+    750 /* Oakley-EC2N-4 */,
+    9 /* PBE-MD2-DES */,
+    168 /* PBE-MD2-RC2-64 */,
+    10 /* PBE-MD5-DES */,
+    169 /* PBE-MD5-RC2-64 */,
+    147 /* PBE-SHA1-2DES */,
+    146 /* PBE-SHA1-3DES */,
+    170 /* PBE-SHA1-DES */,
+    148 /* PBE-SHA1-RC2-128 */,
+    149 /* PBE-SHA1-RC2-40 */,
+    68 /* PBE-SHA1-RC2-64 */,
+    144 /* PBE-SHA1-RC4-128 */,
+    145 /* PBE-SHA1-RC4-40 */,
+    161 /* PBES2 */,
+    69 /* PBKDF2 */,
+    162 /* PBMAC1 */,
+    127 /* PKIX */,
+    935 /* PSPECIFIED */,
+    98 /* RC2-40-CBC */,
+    166 /* RC2-64-CBC */,
+    37 /* RC2-CBC */,
+    39 /* RC2-CFB */,
+    38 /* RC2-ECB */,
+    40 /* RC2-OFB */,
+    5 /* RC4 */,
+    97 /* RC4-40 */,
+    915 /* RC4-HMAC-MD5 */,
+    120 /* RC5-CBC */,
+    122 /* RC5-CFB */,
+    121 /* RC5-ECB */,
+    123 /* RC5-OFB */,
+    117 /* RIPEMD160 */,
+    19 /* RSA */,
+    7 /* RSA-MD2 */,
+    396 /* RSA-MD4 */,
+    8 /* RSA-MD5 */,
+    96 /* RSA-MDC2 */,
+    104 /* RSA-NP-MD5 */,
+    119 /* RSA-RIPEMD160 */,
+    42 /* RSA-SHA */,
+    65 /* RSA-SHA1 */,
+    115 /* RSA-SHA1-2 */,
+    671 /* RSA-SHA224 */,
+    668 /* RSA-SHA256 */,
+    669 /* RSA-SHA384 */,
+    670 /* RSA-SHA512 */,
+    919 /* RSAES-OAEP */,
+    912 /* RSASSA-PSS */,
+    777 /* SEED-CBC */,
+    779 /* SEED-CFB */,
+    776 /* SEED-ECB */,
+    778 /* SEED-OFB */,
+    41 /* SHA */,
+    64 /* SHA1 */,
+    675 /* SHA224 */,
+    672 /* SHA256 */,
+    673 /* SHA384 */,
+    674 /* SHA512 */,
+    188 /* SMIME */,
+    167 /* SMIME-CAPS */,
+    100 /* SN */,
+    16 /* ST */,
+    143 /* SXNetID */,
+    458 /* UID */,
+    0 /* UNDEF */,
+    948 /* X25519 */,
+    11 /* X500 */,
+    378 /* X500algorithms */,
+    12 /* X509 */,
+    184 /* X9-57 */,
+    185 /* X9cm */,
+    125 /* ZLIB */,
+    478 /* aRecord */,
+    289 /* aaControls */,
+    287 /* ac-auditEntity */,
+    397 /* ac-proxying */,
+    288 /* ac-targeting */,
+    368 /* acceptableResponses */,
+    446 /* account */,
+    363 /* ad_timestamping */,
+    376 /* algorithm */,
+    405 /* ansi-X9-62 */,
+    910 /* anyExtendedKeyUsage */,
+    746 /* anyPolicy */,
+    370 /* archiveCutoff */,
+    484 /* associatedDomain */,
+    485 /* associatedName */,
+    501 /* audio */,
+    177 /* authorityInfoAccess */,
+    90 /* authorityKeyIdentifier */,
+    882 /* authorityRevocationList */,
+    87 /* basicConstraints */,
+    365 /* basicOCSPResponse */,
+    285 /* biometricInfo */,
+    921 /* brainpoolP160r1 */,
+    922 /* brainpoolP160t1 */,
+    923 /* brainpoolP192r1 */,
+    924 /* brainpoolP192t1 */,
+    925 /* brainpoolP224r1 */,
+    926 /* brainpoolP224t1 */,
+    927 /* brainpoolP256r1 */,
+    928 /* brainpoolP256t1 */,
+    929 /* brainpoolP320r1 */,
+    930 /* brainpoolP320t1 */,
+    931 /* brainpoolP384r1 */,
+    932 /* brainpoolP384t1 */,
+    933 /* brainpoolP512r1 */,
+    934 /* brainpoolP512t1 */,
+    494 /* buildingName */,
+    860 /* businessCategory */,
+    691 /* c2onb191v4 */,
+    692 /* c2onb191v5 */,
+    697 /* c2onb239v4 */,
+    698 /* c2onb239v5 */,
+    684 /* c2pnb163v1 */,
+    685 /* c2pnb163v2 */,
+    686 /* c2pnb163v3 */,
+    687 /* c2pnb176v1 */,
+    693 /* c2pnb208w1 */,
+    699 /* c2pnb272w1 */,
+    700 /* c2pnb304w1 */,
+    702 /* c2pnb368w1 */,
+    688 /* c2tnb191v1 */,
+    689 /* c2tnb191v2 */,
+    690 /* c2tnb191v3 */,
+    694 /* c2tnb239v1 */,
+    695 /* c2tnb239v2 */,
+    696 /* c2tnb239v3 */,
+    701 /* c2tnb359v1 */,
+    703 /* c2tnb431r1 */,
+    881 /* cACertificate */,
+    483 /* cNAMERecord */,
+    179 /* caIssuers */,
+    785 /* caRepository */,
+    443 /* caseIgnoreIA5StringSyntax */,
+    152 /* certBag */,
+    677 /* certicom-arc */,
+    771 /* certificateIssuer */,
+    89 /* certificatePolicies */,
+    883 /* certificateRevocationList */,
+    54 /* challengePassword */,
+    407 /* characteristic-two-field */,
+    395 /* clearance */,
+    130 /* clientAuth */,
+    131 /* codeSigning */,
+    50 /* contentType */,
+    53 /* countersignature */,
+    153 /* crlBag */,
+    103 /* crlDistributionPoints */,
+    88 /* crlNumber */,
+    884 /* crossCertificatePair */,
+    806 /* cryptocom */,
+    805 /* cryptopro */,
+    500 /* dITRedirect */,
+    451 /* dNSDomain */,
+    495 /* dSAQuality */,
+    434 /* data */,
+    390 /* dcobject */,
+    140 /* deltaCRL */,
+    891 /* deltaRevocationList */,
+    107 /* description */,
+    871 /* destinationIndicator */,
+    947 /* dh-cofactor-kdf */,
+    946 /* dh-std-kdf */,
+    28 /* dhKeyAgreement */,
+    941 /* dhSinglePass-cofactorDH-sha1kdf-scheme */,
+    942 /* dhSinglePass-cofactorDH-sha224kdf-scheme */,
+    943 /* dhSinglePass-cofactorDH-sha256kdf-scheme */,
+    944 /* dhSinglePass-cofactorDH-sha384kdf-scheme */,
+    945 /* dhSinglePass-cofactorDH-sha512kdf-scheme */,
+    936 /* dhSinglePass-stdDH-sha1kdf-scheme */,
+    937 /* dhSinglePass-stdDH-sha224kdf-scheme */,
+    938 /* dhSinglePass-stdDH-sha256kdf-scheme */,
+    939 /* dhSinglePass-stdDH-sha384kdf-scheme */,
+    940 /* dhSinglePass-stdDH-sha512kdf-scheme */,
+    920 /* dhpublicnumber */,
+    382 /* directory */,
+    887 /* distinguishedName */,
+    892 /* dmdName */,
+    174 /* dnQualifier */,
+    447 /* document */,
+    471 /* documentAuthor */,
+    468 /* documentIdentifier */,
+    472 /* documentLocation */,
+    502 /* documentPublisher */,
+    449 /* documentSeries */,
+    469 /* documentTitle */,
+    470 /* documentVersion */,
+    392 /* domain */,
+    452 /* domainRelatedObject */,
+    802 /* dsa_with_SHA224 */,
+    803 /* dsa_with_SHA256 */,
+    791 /* ecdsa-with-Recommended */,
+    416 /* ecdsa-with-SHA1 */,
+    793 /* ecdsa-with-SHA224 */,
+    794 /* ecdsa-with-SHA256 */,
+    795 /* ecdsa-with-SHA384 */,
+    796 /* ecdsa-with-SHA512 */,
+    792 /* ecdsa-with-Specified */,
+    48 /* emailAddress */,
+    132 /* emailProtection */,
+    885 /* enhancedSearchGuide */,
+    389 /* enterprises */,
+    384 /* experimental */,
+    172 /* extReq */,
+    56 /* extendedCertificateAttributes */,
+    126 /* extendedKeyUsage */,
+    372 /* extendedStatus */,
+    867 /* facsimileTelephoneNumber */,
+    462 /* favouriteDrink */,
+    857 /* freshestCRL */,
+    453 /* friendlyCountry */,
+    490 /* friendlyCountryName */,
+    156 /* friendlyName */,
+    509 /* generationQualifier */,
+    815 /* gost-mac */,
+    811 /* gost2001 */,
+    851 /* gost2001cc */,
+    813 /* gost89 */,
+    814 /* gost89-cnt */,
+    812 /* gost94 */,
+    850 /* gost94cc */,
+    797 /* hmacWithMD5 */,
+    163 /* hmacWithSHA1 */,
+    798 /* hmacWithSHA224 */,
+    799 /* hmacWithSHA256 */,
+    800 /* hmacWithSHA384 */,
+    801 /* hmacWithSHA512 */,
+    432 /* holdInstructionCallIssuer */,
+    430 /* holdInstructionCode */,
+    431 /* holdInstructionNone */,
+    433 /* holdInstructionReject */,
+    486 /* homePostalAddress */,
+    473 /* homeTelephoneNumber */,
+    466 /* host */,
+    889 /* houseIdentifier */,
+    442 /* iA5StringSyntax */,
+    783 /* id-DHBasedMac */,
+    824 /* id-Gost28147-89-CryptoPro-A-ParamSet */,
+    825 /* id-Gost28147-89-CryptoPro-B-ParamSet */,
+    826 /* id-Gost28147-89-CryptoPro-C-ParamSet */,
+    827 /* id-Gost28147-89-CryptoPro-D-ParamSet */,
+    819 /* id-Gost28147-89-CryptoPro-KeyMeshing */,
+    829 /* id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet */,
+    828 /* id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet */,
+    830 /* id-Gost28147-89-CryptoPro-RIC-1-ParamSet */,
+    820 /* id-Gost28147-89-None-KeyMeshing */,
+    823 /* id-Gost28147-89-TestParamSet */,
+    849 /* id-Gost28147-89-cc */,
+    840 /* id-GostR3410-2001-CryptoPro-A-ParamSet */,
+    841 /* id-GostR3410-2001-CryptoPro-B-ParamSet */,
+    842 /* id-GostR3410-2001-CryptoPro-C-ParamSet */,
+    843 /* id-GostR3410-2001-CryptoPro-XchA-ParamSet */,
+    844 /* id-GostR3410-2001-CryptoPro-XchB-ParamSet */,
+    854 /* id-GostR3410-2001-ParamSet-cc */,
+    839 /* id-GostR3410-2001-TestParamSet */,
+    817 /* id-GostR3410-2001DH */,
+    832 /* id-GostR3410-94-CryptoPro-A-ParamSet */,
+    833 /* id-GostR3410-94-CryptoPro-B-ParamSet */,
+    834 /* id-GostR3410-94-CryptoPro-C-ParamSet */,
+    835 /* id-GostR3410-94-CryptoPro-D-ParamSet */,
+    836 /* id-GostR3410-94-CryptoPro-XchA-ParamSet */,
+    837 /* id-GostR3410-94-CryptoPro-XchB-ParamSet */,
+    838 /* id-GostR3410-94-CryptoPro-XchC-ParamSet */,
+    831 /* id-GostR3410-94-TestParamSet */,
+    845 /* id-GostR3410-94-a */,
+    846 /* id-GostR3410-94-aBis */,
+    847 /* id-GostR3410-94-b */,
+    848 /* id-GostR3410-94-bBis */,
+    818 /* id-GostR3410-94DH */,
+    822 /* id-GostR3411-94-CryptoProParamSet */,
+    821 /* id-GostR3411-94-TestParamSet */,
+    807 /* id-GostR3411-94-with-GostR3410-2001 */,
+    853 /* id-GostR3411-94-with-GostR3410-2001-cc */,
+    808 /* id-GostR3411-94-with-GostR3410-94 */,
+    852 /* id-GostR3411-94-with-GostR3410-94-cc */,
+    810 /* id-HMACGostR3411-94 */,
+    782 /* id-PasswordBasedMAC */,
+    266 /* id-aca */,
+    355 /* id-aca-accessIdentity */,
+    354 /* id-aca-authenticationInfo */,
+    356 /* id-aca-chargingIdentity */,
+    399 /* id-aca-encAttrs */,
+    357 /* id-aca-group */,
+    358 /* id-aca-role */,
+    176 /* id-ad */,
+    896 /* id-aes128-CCM */,
+    895 /* id-aes128-GCM */,
+    788 /* id-aes128-wrap */,
+    897 /* id-aes128-wrap-pad */,
+    899 /* id-aes192-CCM */,
+    898 /* id-aes192-GCM */,
+    789 /* id-aes192-wrap */,
+    900 /* id-aes192-wrap-pad */,
+    902 /* id-aes256-CCM */,
+    901 /* id-aes256-GCM */,
+    790 /* id-aes256-wrap */,
+    903 /* id-aes256-wrap-pad */,
+    262 /* id-alg */,
+    893 /* id-alg-PWRI-KEK */,
+    323 /* id-alg-des40 */,
+    326 /* id-alg-dh-pop */,
+    325 /* id-alg-dh-sig-hmac-sha1 */,
+    324 /* id-alg-noSignature */,
+    907 /* id-camellia128-wrap */,
+    908 /* id-camellia192-wrap */,
+    909 /* id-camellia256-wrap */,
+    268 /* id-cct */,
+    361 /* id-cct-PKIData */,
+    362 /* id-cct-PKIResponse */,
+    360 /* id-cct-crs */,
+    81 /* id-ce */,
+    680 /* id-characteristic-two-basis */,
+    263 /* id-cmc */,
+    334 /* id-cmc-addExtensions */,
+    346 /* id-cmc-confirmCertAcceptance */,
+    330 /* id-cmc-dataReturn */,
+    336 /* id-cmc-decryptedPOP */,
+    335 /* id-cmc-encryptedPOP */,
+    339 /* id-cmc-getCRL */,
+    338 /* id-cmc-getCert */,
+    328 /* id-cmc-identification */,
+    329 /* id-cmc-identityProof */,
+    337 /* id-cmc-lraPOPWitness */,
+    344 /* id-cmc-popLinkRandom */,
+    345 /* id-cmc-popLinkWitness */,
+    343 /* id-cmc-queryPending */,
+    333 /* id-cmc-recipientNonce */,
+    341 /* id-cmc-regInfo */,
+    342 /* id-cmc-responseInfo */,
+    340 /* id-cmc-revokeRequest */,
+    332 /* id-cmc-senderNonce */,
+    327 /* id-cmc-statusInfo */,
+    331 /* id-cmc-transactionId */,
+    787 /* id-ct-asciiTextWithCRLF */,
+    408 /* id-ecPublicKey */,
+    508 /* id-hex-multipart-message */,
+    507 /* id-hex-partial-message */,
+    260 /* id-it */,
+    302 /* id-it-caKeyUpdateInfo */,
+    298 /* id-it-caProtEncCert */,
+    311 /* id-it-confirmWaitTime */,
+    303 /* id-it-currentCRL */,
+    300 /* id-it-encKeyPairTypes */,
+    310 /* id-it-implicitConfirm */,
+    308 /* id-it-keyPairParamRep */,
+    307 /* id-it-keyPairParamReq */,
+    312 /* id-it-origPKIMessage */,
+    301 /* id-it-preferredSymmAlg */,
+    309 /* id-it-revPassphrase */,
+    299 /* id-it-signKeyPairTypes */,
+    305 /* id-it-subscriptionRequest */,
+    306 /* id-it-subscriptionResponse */,
+    784 /* id-it-suppLangTags */,
+    304 /* id-it-unsupportedOIDs */,
+    128 /* id-kp */,
+    280 /* id-mod-attribute-cert */,
+    274 /* id-mod-cmc */,
+    277 /* id-mod-cmp */,
+    284 /* id-mod-cmp2000 */,
+    273 /* id-mod-crmf */,
+    283 /* id-mod-dvcs */,
+    275 /* id-mod-kea-profile-88 */,
+    276 /* id-mod-kea-profile-93 */,
+    282 /* id-mod-ocsp */,
+    278 /* id-mod-qualified-cert-88 */,
+    279 /* id-mod-qualified-cert-93 */,
+    281 /* id-mod-timestamp-protocol */,
+    264 /* id-on */,
+    858 /* id-on-permanentIdentifier */,
+    347 /* id-on-personalData */,
+    265 /* id-pda */,
+    352 /* id-pda-countryOfCitizenship */,
+    353 /* id-pda-countryOfResidence */,
+    348 /* id-pda-dateOfBirth */,
+    351 /* id-pda-gender */,
+    349 /* id-pda-placeOfBirth */,
+    175 /* id-pe */,
+    261 /* id-pkip */,
+    258 /* id-pkix-mod */,
+    269 /* id-pkix1-explicit-88 */,
+    271 /* id-pkix1-explicit-93 */,
+    270 /* id-pkix1-implicit-88 */,
+    272 /* id-pkix1-implicit-93 */,
+    662 /* id-ppl */,
+    664 /* id-ppl-anyLanguage */,
+    667 /* id-ppl-independent */,
+    665 /* id-ppl-inheritAll */,
+    267 /* id-qcs */,
+    359 /* id-qcs-pkixQCSyntax-v1 */,
+    259 /* id-qt */,
+    164 /* id-qt-cps */,
+    165 /* id-qt-unotice */,
+    313 /* id-regCtrl */,
+    316 /* id-regCtrl-authenticator */,
+    319 /* id-regCtrl-oldCertID */,
+    318 /* id-regCtrl-pkiArchiveOptions */,
+    317 /* id-regCtrl-pkiPublicationInfo */,
+    320 /* id-regCtrl-protocolEncrKey */,
+    315 /* id-regCtrl-regToken */,
+    314 /* id-regInfo */,
+    322 /* id-regInfo-certReq */,
+    321 /* id-regInfo-utf8Pairs */,
+    512 /* id-set */,
+    191 /* id-smime-aa */,
+    215 /* id-smime-aa-contentHint */,
+    218 /* id-smime-aa-contentIdentifier */,
+    221 /* id-smime-aa-contentReference */,
+    240 /* id-smime-aa-dvcs-dvc */,
+    217 /* id-smime-aa-encapContentType */,
+    222 /* id-smime-aa-encrypKeyPref */,
+    220 /* id-smime-aa-equivalentLabels */,
+    232 /* id-smime-aa-ets-CertificateRefs */,
+    233 /* id-smime-aa-ets-RevocationRefs */,
+    238 /* id-smime-aa-ets-archiveTimeStamp */,
+    237 /* id-smime-aa-ets-certCRLTimestamp */,
+    234 /* id-smime-aa-ets-certValues */,
+    227 /* id-smime-aa-ets-commitmentType */,
+    231 /* id-smime-aa-ets-contentTimestamp */,
+    236 /* id-smime-aa-ets-escTimeStamp */,
+    230 /* id-smime-aa-ets-otherSigCert */,
+    235 /* id-smime-aa-ets-revocationValues */,
+    226 /* id-smime-aa-ets-sigPolicyId */,
+    229 /* id-smime-aa-ets-signerAttr */,
+    228 /* id-smime-aa-ets-signerLocation */,
+    219 /* id-smime-aa-macValue */,
+    214 /* id-smime-aa-mlExpandHistory */,
+    216 /* id-smime-aa-msgSigDigest */,
+    212 /* id-smime-aa-receiptRequest */,
+    213 /* id-smime-aa-securityLabel */,
+    239 /* id-smime-aa-signatureType */,
+    223 /* id-smime-aa-signingCertificate */,
+    224 /* id-smime-aa-smimeEncryptCerts */,
+    225 /* id-smime-aa-timeStampToken */,
+    192 /* id-smime-alg */,
+    243 /* id-smime-alg-3DESwrap */,
+    246 /* id-smime-alg-CMS3DESwrap */,
+    247 /* id-smime-alg-CMSRC2wrap */,
+    245 /* id-smime-alg-ESDH */,
+    241 /* id-smime-alg-ESDHwith3DES */,
+    242 /* id-smime-alg-ESDHwithRC2 */,
+    244 /* id-smime-alg-RC2wrap */,
+    193 /* id-smime-cd */,
+    248 /* id-smime-cd-ldap */,
+    190 /* id-smime-ct */,
+    210 /* id-smime-ct-DVCSRequestData */,
+    211 /* id-smime-ct-DVCSResponseData */,
+    208 /* id-smime-ct-TDTInfo */,
+    207 /* id-smime-ct-TSTInfo */,
+    205 /* id-smime-ct-authData */,
+    786 /* id-smime-ct-compressedData */,
+    209 /* id-smime-ct-contentInfo */,
+    206 /* id-smime-ct-publishCert */,
+    204 /* id-smime-ct-receipt */,
+    195 /* id-smime-cti */,
+    255 /* id-smime-cti-ets-proofOfApproval */,
+    256 /* id-smime-cti-ets-proofOfCreation */,
+    253 /* id-smime-cti-ets-proofOfDelivery */,
+    251 /* id-smime-cti-ets-proofOfOrigin */,
+    252 /* id-smime-cti-ets-proofOfReceipt */,
+    254 /* id-smime-cti-ets-proofOfSender */,
+    189 /* id-smime-mod */,
+    196 /* id-smime-mod-cms */,
+    197 /* id-smime-mod-ess */,
+    202 /* id-smime-mod-ets-eSigPolicy-88 */,
+    203 /* id-smime-mod-ets-eSigPolicy-97 */,
+    200 /* id-smime-mod-ets-eSignature-88 */,
+    201 /* id-smime-mod-ets-eSignature-97 */,
+    199 /* id-smime-mod-msg-v3 */,
+    198 /* id-smime-mod-oid */,
+    194 /* id-smime-spq */,
+    250 /* id-smime-spq-ets-sqt-unotice */,
+    249 /* id-smime-spq-ets-sqt-uri */,
+    676 /* identified-organization */,
+    461 /* info */,
+    748 /* inhibitAnyPolicy */,
+    101 /* initials */,
+    647 /* international-organizations */,
+    869 /* internationaliSDNNumber */,
+    142 /* invalidityDate */,
+    294 /* ipsecEndSystem */,
+    295 /* ipsecTunnel */,
+    296 /* ipsecUser */,
+    86 /* issuerAltName */,
+    770 /* issuingDistributionPoint */,
+    492 /* janetMailbox */,
+    150 /* keyBag */,
+    83 /* keyUsage */,
+    477 /* lastModifiedBy */,
+    476 /* lastModifiedTime */,
+    157 /* localKeyID */,
+    480 /* mXRecord */,
+    460 /* mail */,
+    493 /* mailPreferenceOption */,
+    467 /* manager */,
+    809 /* md_gost94 */,
+    875 /* member */,
+    182 /* member-body */,
+    51 /* messageDigest */,
+    383 /* mgmt */,
+    504 /* mime-mhs */,
+    506 /* mime-mhs-bodies */,
+    505 /* mime-mhs-headings */,
+    488 /* mobileTelephoneNumber */,
+    136 /* msCTLSign */,
+    135 /* msCodeCom */,
+    134 /* msCodeInd */,
+    138 /* msEFS */,
+    171 /* msExtReq */,
+    137 /* msSGC */,
+    648 /* msSmartcardLogin */,
+    649 /* msUPN */,
+    481 /* nSRecord */,
+    173 /* name */,
+    666 /* nameConstraints */,
+    369 /* noCheck */,
+    403 /* noRevAvail */,
+    72 /* nsBaseUrl */,
+    76 /* nsCaPolicyUrl */,
+    74 /* nsCaRevocationUrl */,
+    58 /* nsCertExt */,
+    79 /* nsCertSequence */,
+    71 /* nsCertType */,
+    78 /* nsComment */,
+    59 /* nsDataType */,
+    75 /* nsRenewalUrl */,
+    73 /* nsRevocationUrl */,
+    139 /* nsSGC */,
+    77 /* nsSslServerName */,
+    681 /* onBasis */,
+    491 /* organizationalStatus */,
+    475 /* otherMailbox */,
+    876 /* owner */,
+    489 /* pagerTelephoneNumber */,
+    374 /* path */,
+    112 /* pbeWithMD5AndCast5CBC */,
+    499 /* personalSignature */,
+    487 /* personalTitle */,
+    464 /* photo */,
+    863 /* physicalDeliveryOfficeName */,
+    437 /* pilot */,
+    439 /* pilotAttributeSyntax */,
+    438 /* pilotAttributeType */,
+    479 /* pilotAttributeType27 */,
+    456 /* pilotDSA */,
+    441 /* pilotGroups */,
+    444 /* pilotObject */,
+    440 /* pilotObjectClass */,
+    455 /* pilotOrganization */,
+    445 /* pilotPerson */,
+    2 /* pkcs */,
+    186 /* pkcs1 */,
+    27 /* pkcs3 */,
+    187 /* pkcs5 */,
+    20 /* pkcs7 */,
+    21 /* pkcs7-data */,
+    25 /* pkcs7-digestData */,
+    26 /* pkcs7-encryptedData */,
+    23 /* pkcs7-envelopedData */,
+    24 /* pkcs7-signedAndEnvelopedData */,
+    22 /* pkcs7-signedData */,
+    151 /* pkcs8ShroudedKeyBag */,
+    47 /* pkcs9 */,
+    401 /* policyConstraints */,
+    747 /* policyMappings */,
+    862 /* postOfficeBox */,
+    861 /* postalAddress */,
+    661 /* postalCode */,
+    683 /* ppBasis */,
+    872 /* preferredDeliveryMethod */,
+    873 /* presentationAddress */,
+    816 /* prf-gostr3411-94 */,
+    406 /* prime-field */,
+    409 /* prime192v1 */,
+    410 /* prime192v2 */,
+    411 /* prime192v3 */,
+    412 /* prime239v1 */,
+    413 /* prime239v2 */,
+    414 /* prime239v3 */,
+    415 /* prime256v1 */,
+    385 /* private */,
+    84 /* privateKeyUsagePeriod */,
+    886 /* protocolInformation */,
+    663 /* proxyCertInfo */,
+    510 /* pseudonym */,
+    435 /* pss */,
+    286 /* qcStatements */,
+    457 /* qualityLabelledData */,
+    450 /* rFC822localPart */,
+    870 /* registeredAddress */,
+    400 /* role */,
+    877 /* roleOccupant */,
+    448 /* room */,
+    463 /* roomNumber */,
+    6 /* rsaEncryption */,
+    644 /* rsaOAEPEncryptionSET */,
+    377 /* rsaSignature */,
+    1 /* rsadsi */,
+    482 /* sOARecord */,
+    155 /* safeContentsBag */,
+    291 /* sbgp-autonomousSysNum */,
+    290 /* sbgp-ipAddrBlock */,
+    292 /* sbgp-routerIdentifier */,
+    159 /* sdsiCertificate */,
+    859 /* searchGuide */,
+    704 /* secp112r1 */,
+    705 /* secp112r2 */,
+    706 /* secp128r1 */,
+    707 /* secp128r2 */,
+    708 /* secp160k1 */,
+    709 /* secp160r1 */,
+    710 /* secp160r2 */,
+    711 /* secp192k1 */,
+    712 /* secp224k1 */,
+    713 /* secp224r1 */,
+    714 /* secp256k1 */,
+    715 /* secp384r1 */,
+    716 /* secp521r1 */,
+    154 /* secretBag */,
+    474 /* secretary */,
+    717 /* sect113r1 */,
+    718 /* sect113r2 */,
+    719 /* sect131r1 */,
+    720 /* sect131r2 */,
+    721 /* sect163k1 */,
+    722 /* sect163r1 */,
+    723 /* sect163r2 */,
+    724 /* sect193r1 */,
+    725 /* sect193r2 */,
+    726 /* sect233k1 */,
+    727 /* sect233r1 */,
+    728 /* sect239k1 */,
+    729 /* sect283k1 */,
+    730 /* sect283r1 */,
+    731 /* sect409k1 */,
+    732 /* sect409r1 */,
+    733 /* sect571k1 */,
+    734 /* sect571r1 */,
+    386 /* security */,
+    878 /* seeAlso */,
+    394 /* selected-attribute-types */,
+    105 /* serialNumber */,
+    129 /* serverAuth */,
+    371 /* serviceLocator */,
+    625 /* set-addPolicy */,
+    515 /* set-attr */,
+    518 /* set-brand */,
+    638 /* set-brand-AmericanExpress */,
+    637 /* set-brand-Diners */,
+    636 /* set-brand-IATA-ATA */,
+    639 /* set-brand-JCB */,
+    641 /* set-brand-MasterCard */,
+    642 /* set-brand-Novus */,
+    640 /* set-brand-Visa */,
+    517 /* set-certExt */,
+    513 /* set-ctype */,
+    514 /* set-msgExt */,
+    516 /* set-policy */,
+    607 /* set-policy-root */,
+    624 /* set-rootKeyThumb */,
+    620 /* setAttr-Cert */,
+    631 /* setAttr-GenCryptgrm */,
+    623 /* setAttr-IssCap */,
+    628 /* setAttr-IssCap-CVM */,
+    630 /* setAttr-IssCap-Sig */,
+    629 /* setAttr-IssCap-T2 */,
+    621 /* setAttr-PGWYcap */,
+    635 /* setAttr-SecDevSig */,
+    632 /* setAttr-T2Enc */,
+    633 /* setAttr-T2cleartxt */,
+    634 /* setAttr-TokICCsig */,
+    627 /* setAttr-Token-B0Prime */,
+    626 /* setAttr-Token-EMV */,
+    622 /* setAttr-TokenType */,
+    619 /* setCext-IssuerCapabilities */,
+    615 /* setCext-PGWYcapabilities */,
+    616 /* setCext-TokenIdentifier */,
+    618 /* setCext-TokenType */,
+    617 /* setCext-Track2Data */,
+    611 /* setCext-cCertRequired */,
+    609 /* setCext-certType */,
+    608 /* setCext-hashedRoot */,
+    610 /* setCext-merchData */,
+    613 /* setCext-setExt */,
+    614 /* setCext-setQualf */,
+    612 /* setCext-tunneling */,
+    540 /* setct-AcqCardCodeMsg */,
+    576 /* setct-AcqCardCodeMsgTBE */,
+    570 /* setct-AuthReqTBE */,
+    534 /* setct-AuthReqTBS */,
+    527 /* setct-AuthResBaggage */,
+    571 /* setct-AuthResTBE */,
+    572 /* setct-AuthResTBEX */,
+    535 /* setct-AuthResTBS */,
+    536 /* setct-AuthResTBSX */,
+    528 /* setct-AuthRevReqBaggage */,
+    577 /* setct-AuthRevReqTBE */,
+    541 /* setct-AuthRevReqTBS */,
+    529 /* setct-AuthRevResBaggage */,
+    542 /* setct-AuthRevResData */,
+    578 /* setct-AuthRevResTBE */,
+    579 /* setct-AuthRevResTBEB */,
+    543 /* setct-AuthRevResTBS */,
+    573 /* setct-AuthTokenTBE */,
+    537 /* setct-AuthTokenTBS */,
+    600 /* setct-BCIDistributionTBS */,
+    558 /* setct-BatchAdminReqData */,
+    592 /* setct-BatchAdminReqTBE */,
+    559 /* setct-BatchAdminResData */,
+    593 /* setct-BatchAdminResTBE */,
+    599 /* setct-CRLNotificationResTBS */,
+    598 /* setct-CRLNotificationTBS */,
+    580 /* setct-CapReqTBE */,
+    581 /* setct-CapReqTBEX */,
+    544 /* setct-CapReqTBS */,
+    545 /* setct-CapReqTBSX */,
+    546 /* setct-CapResData */,
+    582 /* setct-CapResTBE */,
+    583 /* setct-CapRevReqTBE */,
+    584 /* setct-CapRevReqTBEX */,
+    547 /* setct-CapRevReqTBS */,
+    548 /* setct-CapRevReqTBSX */,
+    549 /* setct-CapRevResData */,
+    585 /* setct-CapRevResTBE */,
+    538 /* setct-CapTokenData */,
+    530 /* setct-CapTokenSeq */,
+    574 /* setct-CapTokenTBE */,
+    575 /* setct-CapTokenTBEX */,
+    539 /* setct-CapTokenTBS */,
+    560 /* setct-CardCInitResTBS */,
+    566 /* setct-CertInqReqTBS */,
+    563 /* setct-CertReqData */,
+    595 /* setct-CertReqTBE */,
+    596 /* setct-CertReqTBEX */,
+    564 /* setct-CertReqTBS */,
+    565 /* setct-CertResData */,
+    597 /* setct-CertResTBE */,
+    586 /* setct-CredReqTBE */,
+    587 /* setct-CredReqTBEX */,
+    550 /* setct-CredReqTBS */,
+    551 /* setct-CredReqTBSX */,
+    552 /* setct-CredResData */,
+    588 /* setct-CredResTBE */,
+    589 /* setct-CredRevReqTBE */,
+    590 /* setct-CredRevReqTBEX */,
+    553 /* setct-CredRevReqTBS */,
+    554 /* setct-CredRevReqTBSX */,
+    555 /* setct-CredRevResData */,
+    591 /* setct-CredRevResTBE */,
+    567 /* setct-ErrorTBS */,
+    526 /* setct-HODInput */,
+    561 /* setct-MeAqCInitResTBS */,
+    522 /* setct-OIData */,
+    519 /* setct-PANData */,
+    521 /* setct-PANOnly */,
+    520 /* setct-PANToken */,
+    556 /* setct-PCertReqData */,
+    557 /* setct-PCertResTBS */,
+    523 /* setct-PI */,
+    532 /* setct-PI-TBS */,
+    524 /* setct-PIData */,
+    525 /* setct-PIDataUnsigned */,
+    568 /* setct-PIDualSignedTBE */,
+    569 /* setct-PIUnsignedTBE */,
+    531 /* setct-PInitResData */,
+    533 /* setct-PResData */,
+    594 /* setct-RegFormReqTBE */,
+    562 /* setct-RegFormResTBS */,
+    606 /* setext-cv */,
+    601 /* setext-genCrypt */,
+    602 /* setext-miAuth */,
+    604 /* setext-pinAny */,
+    603 /* setext-pinSecure */,
+    605 /* setext-track2 */,
+    52 /* signingTime */,
+    454 /* simpleSecurityObject */,
+    496 /* singleLevelQuality */,
+    387 /* snmpv2 */,
+    660 /* street */,
+    85 /* subjectAltName */,
+    769 /* subjectDirectoryAttributes */,
+    398 /* subjectInfoAccess */,
+    82 /* subjectKeyIdentifier */,
+    498 /* subtreeMaximumQuality */,
+    497 /* subtreeMinimumQuality */,
+    890 /* supportedAlgorithms */,
+    874 /* supportedApplicationContext */,
+    402 /* targetInformation */,
+    864 /* telephoneNumber */,
+    866 /* teletexTerminalIdentifier */,
+    865 /* telexNumber */,
+    459 /* textEncodedORAddress */,
+    293 /* textNotice */,
+    133 /* timeStamping */,
+    106 /* title */,
+    682 /* tpBasis */,
+    375 /* trustRoot */,
+    436 /* ucl */,
+    888 /* uniqueMember */,
+    55 /* unstructuredAddress */,
+    49 /* unstructuredName */,
+    880 /* userCertificate */,
+    465 /* userClass */,
+    879 /* userPassword */,
+    373 /* valid */,
+    678 /* wap */,
+    679 /* wap-wsg */,
+    735 /* wap-wsg-idm-ecid-wtls1 */,
+    743 /* wap-wsg-idm-ecid-wtls10 */,
+    744 /* wap-wsg-idm-ecid-wtls11 */,
+    745 /* wap-wsg-idm-ecid-wtls12 */,
+    736 /* wap-wsg-idm-ecid-wtls3 */,
+    737 /* wap-wsg-idm-ecid-wtls4 */,
+    738 /* wap-wsg-idm-ecid-wtls5 */,
+    739 /* wap-wsg-idm-ecid-wtls6 */,
+    740 /* wap-wsg-idm-ecid-wtls7 */,
+    741 /* wap-wsg-idm-ecid-wtls8 */,
+    742 /* wap-wsg-idm-ecid-wtls9 */,
+    804 /* whirlpool */,
+    868 /* x121Address */,
+    503 /* x500UniqueIdentifier */,
+    158 /* x509Certificate */,
+    160 /* x509Crl */,
 };
 
-static const unsigned int kNIDsInLongNameOrder[NUM_LN]={
-363,	/* "AD Time Stamping" */
-405,	/* "ANSI X9.62" */
-368,	/* "Acceptable OCSP Responses" */
-910,	/* "Any Extended Key Usage" */
-664,	/* "Any language" */
-177,	/* "Authority Information Access" */
-365,	/* "Basic OCSP Response" */
-285,	/* "Biometric Info" */
-179,	/* "CA Issuers" */
-785,	/* "CA Repository" */
-131,	/* "Code Signing" */
-783,	/* "Diffie-Hellman based MAC" */
-382,	/* "Directory" */
-392,	/* "Domain" */
-132,	/* "E-mail Protection" */
-389,	/* "Enterprises" */
-384,	/* "Experimental" */
-372,	/* "Extended OCSP Status" */
-172,	/* "Extension Request" */
-813,	/* "GOST 28147-89" */
-849,	/* "GOST 28147-89 Cryptocom ParamSet" */
-815,	/* "GOST 28147-89 MAC" */
-851,	/* "GOST 34.10-2001 Cryptocom" */
-850,	/* "GOST 34.10-94 Cryptocom" */
-811,	/* "GOST R 34.10-2001" */
-817,	/* "GOST R 34.10-2001 DH" */
-812,	/* "GOST R 34.10-94" */
-818,	/* "GOST R 34.10-94 DH" */
-809,	/* "GOST R 34.11-94" */
-816,	/* "GOST R 34.11-94 PRF" */
-807,	/* "GOST R 34.11-94 with GOST R 34.10-2001" */
-853,	/* "GOST R 34.11-94 with GOST R 34.10-2001 Cryptocom" */
-808,	/* "GOST R 34.11-94 with GOST R 34.10-94" */
-852,	/* "GOST R 34.11-94 with GOST R 34.10-94 Cryptocom" */
-854,	/* "GOST R 3410-2001 Parameter Set Cryptocom" */
-810,	/* "HMAC GOST 34.11-94" */
-432,	/* "Hold Instruction Call Issuer" */
-430,	/* "Hold Instruction Code" */
-431,	/* "Hold Instruction None" */
-433,	/* "Hold Instruction Reject" */
-634,	/* "ICC or token signature" */
-294,	/* "IPSec End System" */
-295,	/* "IPSec Tunnel" */
-296,	/* "IPSec User" */
-182,	/* "ISO Member Body" */
-183,	/* "ISO US Member Body" */
-667,	/* "Independent" */
-665,	/* "Inherit all" */
-647,	/* "International Organizations" */
-142,	/* "Invalidity Date" */
-504,	/* "MIME MHS" */
-388,	/* "Mail" */
-383,	/* "Management" */
-417,	/* "Microsoft CSP Name" */
-135,	/* "Microsoft Commercial Code Signing" */
-138,	/* "Microsoft Encrypted File System" */
-171,	/* "Microsoft Extension Request" */
-134,	/* "Microsoft Individual Code Signing" */
-856,	/* "Microsoft Local Key set" */
-137,	/* "Microsoft Server Gated Crypto" */
-648,	/* "Microsoft Smartcardlogin" */
-136,	/* "Microsoft Trust List Signing" */
-649,	/* "Microsoft Universal Principal Name" */
-393,	/* "NULL" */
-404,	/* "NULL" */
-72,	/* "Netscape Base Url" */
-76,	/* "Netscape CA Policy Url" */
-74,	/* "Netscape CA Revocation Url" */
-71,	/* "Netscape Cert Type" */
-58,	/* "Netscape Certificate Extension" */
-79,	/* "Netscape Certificate Sequence" */
-78,	/* "Netscape Comment" */
-57,	/* "Netscape Communications Corp." */
-59,	/* "Netscape Data Type" */
-75,	/* "Netscape Renewal Url" */
-73,	/* "Netscape Revocation Url" */
-77,	/* "Netscape SSL Server Name" */
-139,	/* "Netscape Server Gated Crypto" */
-178,	/* "OCSP" */
-370,	/* "OCSP Archive Cutoff" */
-367,	/* "OCSP CRL ID" */
-369,	/* "OCSP No Check" */
-366,	/* "OCSP Nonce" */
-371,	/* "OCSP Service Locator" */
-180,	/* "OCSP Signing" */
-161,	/* "PBES2" */
-69,	/* "PBKDF2" */
-162,	/* "PBMAC1" */
-127,	/* "PKIX" */
-858,	/* "Permanent Identifier" */
-164,	/* "Policy Qualifier CPS" */
-165,	/* "Policy Qualifier User Notice" */
-385,	/* "Private" */
-663,	/* "Proxy Certificate Information" */
- 1,	/* "RSA Data Security, Inc." */
- 2,	/* "RSA Data Security, Inc. PKCS" */
-188,	/* "S/MIME" */
-167,	/* "S/MIME Capabilities" */
-387,	/* "SNMPv2" */
-512,	/* "Secure Electronic Transactions" */
-386,	/* "Security" */
-394,	/* "Selected Attribute Types" */
-143,	/* "Strong Extranet ID" */
-398,	/* "Subject Information Access" */
-130,	/* "TLS Web Client Authentication" */
-129,	/* "TLS Web Server Authentication" */
-133,	/* "Time Stamping" */
-375,	/* "Trust Root" */
-12,	/* "X509" */
-402,	/* "X509v3 AC Targeting" */
-746,	/* "X509v3 Any Policy" */
-90,	/* "X509v3 Authority Key Identifier" */
-87,	/* "X509v3 Basic Constraints" */
-103,	/* "X509v3 CRL Distribution Points" */
-88,	/* "X509v3 CRL Number" */
-141,	/* "X509v3 CRL Reason Code" */
-771,	/* "X509v3 Certificate Issuer" */
-89,	/* "X509v3 Certificate Policies" */
-140,	/* "X509v3 Delta CRL Indicator" */
-126,	/* "X509v3 Extended Key Usage" */
-857,	/* "X509v3 Freshest CRL" */
-748,	/* "X509v3 Inhibit Any Policy" */
-86,	/* "X509v3 Issuer Alternative Name" */
-770,	/* "X509v3 Issuing Distribution Point" */
-83,	/* "X509v3 Key Usage" */
-666,	/* "X509v3 Name Constraints" */
-403,	/* "X509v3 No Revocation Available" */
-401,	/* "X509v3 Policy Constraints" */
-747,	/* "X509v3 Policy Mappings" */
-84,	/* "X509v3 Private Key Usage Period" */
-85,	/* "X509v3 Subject Alternative Name" */
-769,	/* "X509v3 Subject Directory Attributes" */
-82,	/* "X509v3 Subject Key Identifier" */
-920,	/* "X9.42 DH" */
-184,	/* "X9.57" */
-185,	/* "X9.57 CM ?" */
-478,	/* "aRecord" */
-289,	/* "aaControls" */
-287,	/* "ac-auditEntity" */
-397,	/* "ac-proxying" */
-288,	/* "ac-targeting" */
-446,	/* "account" */
-364,	/* "ad dvcs" */
-606,	/* "additional verification" */
-419,	/* "aes-128-cbc" */
-916,	/* "aes-128-cbc-hmac-sha1" */
-896,	/* "aes-128-ccm" */
-421,	/* "aes-128-cfb" */
-650,	/* "aes-128-cfb1" */
-653,	/* "aes-128-cfb8" */
-904,	/* "aes-128-ctr" */
-418,	/* "aes-128-ecb" */
-895,	/* "aes-128-gcm" */
-420,	/* "aes-128-ofb" */
-913,	/* "aes-128-xts" */
-423,	/* "aes-192-cbc" */
-917,	/* "aes-192-cbc-hmac-sha1" */
-899,	/* "aes-192-ccm" */
-425,	/* "aes-192-cfb" */
-651,	/* "aes-192-cfb1" */
-654,	/* "aes-192-cfb8" */
-905,	/* "aes-192-ctr" */
-422,	/* "aes-192-ecb" */
-898,	/* "aes-192-gcm" */
-424,	/* "aes-192-ofb" */
-427,	/* "aes-256-cbc" */
-918,	/* "aes-256-cbc-hmac-sha1" */
-902,	/* "aes-256-ccm" */
-429,	/* "aes-256-cfb" */
-652,	/* "aes-256-cfb1" */
-655,	/* "aes-256-cfb8" */
-906,	/* "aes-256-ctr" */
-426,	/* "aes-256-ecb" */
-901,	/* "aes-256-gcm" */
-428,	/* "aes-256-ofb" */
-914,	/* "aes-256-xts" */
-376,	/* "algorithm" */
-484,	/* "associatedDomain" */
-485,	/* "associatedName" */
-501,	/* "audio" */
-882,	/* "authorityRevocationList" */
-91,	/* "bf-cbc" */
-93,	/* "bf-cfb" */
-92,	/* "bf-ecb" */
-94,	/* "bf-ofb" */
-921,	/* "brainpoolP160r1" */
-922,	/* "brainpoolP160t1" */
-923,	/* "brainpoolP192r1" */
-924,	/* "brainpoolP192t1" */
-925,	/* "brainpoolP224r1" */
-926,	/* "brainpoolP224t1" */
-927,	/* "brainpoolP256r1" */
-928,	/* "brainpoolP256t1" */
-929,	/* "brainpoolP320r1" */
-930,	/* "brainpoolP320t1" */
-931,	/* "brainpoolP384r1" */
-932,	/* "brainpoolP384t1" */
-933,	/* "brainpoolP512r1" */
-934,	/* "brainpoolP512t1" */
-494,	/* "buildingName" */
-860,	/* "businessCategory" */
-691,	/* "c2onb191v4" */
-692,	/* "c2onb191v5" */
-697,	/* "c2onb239v4" */
-698,	/* "c2onb239v5" */
-684,	/* "c2pnb163v1" */
-685,	/* "c2pnb163v2" */
-686,	/* "c2pnb163v3" */
-687,	/* "c2pnb176v1" */
-693,	/* "c2pnb208w1" */
-699,	/* "c2pnb272w1" */
-700,	/* "c2pnb304w1" */
-702,	/* "c2pnb368w1" */
-688,	/* "c2tnb191v1" */
-689,	/* "c2tnb191v2" */
-690,	/* "c2tnb191v3" */
-694,	/* "c2tnb239v1" */
-695,	/* "c2tnb239v2" */
-696,	/* "c2tnb239v3" */
-701,	/* "c2tnb359v1" */
-703,	/* "c2tnb431r1" */
-881,	/* "cACertificate" */
-483,	/* "cNAMERecord" */
-751,	/* "camellia-128-cbc" */
-757,	/* "camellia-128-cfb" */
-760,	/* "camellia-128-cfb1" */
-763,	/* "camellia-128-cfb8" */
-754,	/* "camellia-128-ecb" */
-766,	/* "camellia-128-ofb" */
-752,	/* "camellia-192-cbc" */
-758,	/* "camellia-192-cfb" */
-761,	/* "camellia-192-cfb1" */
-764,	/* "camellia-192-cfb8" */
-755,	/* "camellia-192-ecb" */
-767,	/* "camellia-192-ofb" */
-753,	/* "camellia-256-cbc" */
-759,	/* "camellia-256-cfb" */
-762,	/* "camellia-256-cfb1" */
-765,	/* "camellia-256-cfb8" */
-756,	/* "camellia-256-ecb" */
-768,	/* "camellia-256-ofb" */
-443,	/* "caseIgnoreIA5StringSyntax" */
-108,	/* "cast5-cbc" */
-110,	/* "cast5-cfb" */
-109,	/* "cast5-ecb" */
-111,	/* "cast5-ofb" */
-152,	/* "certBag" */
-677,	/* "certicom-arc" */
-517,	/* "certificate extensions" */
-883,	/* "certificateRevocationList" */
-54,	/* "challengePassword" */
-407,	/* "characteristic-two-field" */
-395,	/* "clearance" */
-633,	/* "cleartext track 2" */
-894,	/* "cmac" */
-13,	/* "commonName" */
-513,	/* "content types" */
-50,	/* "contentType" */
-53,	/* "countersignature" */
-14,	/* "countryName" */
-153,	/* "crlBag" */
-884,	/* "crossCertificatePair" */
-806,	/* "cryptocom" */
-805,	/* "cryptopro" */
-500,	/* "dITRedirect" */
-451,	/* "dNSDomain" */
-495,	/* "dSAQuality" */
-434,	/* "data" */
-390,	/* "dcObject" */
-891,	/* "deltaRevocationList" */
-31,	/* "des-cbc" */
-643,	/* "des-cdmf" */
-30,	/* "des-cfb" */
-656,	/* "des-cfb1" */
-657,	/* "des-cfb8" */
-29,	/* "des-ecb" */
-32,	/* "des-ede" */
-43,	/* "des-ede-cbc" */
-60,	/* "des-ede-cfb" */
-62,	/* "des-ede-ofb" */
-33,	/* "des-ede3" */
-44,	/* "des-ede3-cbc" */
-61,	/* "des-ede3-cfb" */
-658,	/* "des-ede3-cfb1" */
-659,	/* "des-ede3-cfb8" */
-63,	/* "des-ede3-ofb" */
-45,	/* "des-ofb" */
-107,	/* "description" */
-871,	/* "destinationIndicator" */
-80,	/* "desx-cbc" */
-947,	/* "dh-cofactor-kdf" */
-946,	/* "dh-std-kdf" */
-28,	/* "dhKeyAgreement" */
-941,	/* "dhSinglePass-cofactorDH-sha1kdf-scheme" */
-942,	/* "dhSinglePass-cofactorDH-sha224kdf-scheme" */
-943,	/* "dhSinglePass-cofactorDH-sha256kdf-scheme" */
-944,	/* "dhSinglePass-cofactorDH-sha384kdf-scheme" */
-945,	/* "dhSinglePass-cofactorDH-sha512kdf-scheme" */
-936,	/* "dhSinglePass-stdDH-sha1kdf-scheme" */
-937,	/* "dhSinglePass-stdDH-sha224kdf-scheme" */
-938,	/* "dhSinglePass-stdDH-sha256kdf-scheme" */
-939,	/* "dhSinglePass-stdDH-sha384kdf-scheme" */
-940,	/* "dhSinglePass-stdDH-sha512kdf-scheme" */
-11,	/* "directory services (X.500)" */
-378,	/* "directory services - algorithms" */
-887,	/* "distinguishedName" */
-892,	/* "dmdName" */
-174,	/* "dnQualifier" */
-447,	/* "document" */
-471,	/* "documentAuthor" */
-468,	/* "documentIdentifier" */
-472,	/* "documentLocation" */
-502,	/* "documentPublisher" */
-449,	/* "documentSeries" */
-469,	/* "documentTitle" */
-470,	/* "documentVersion" */
-380,	/* "dod" */
-391,	/* "domainComponent" */
-452,	/* "domainRelatedObject" */
-116,	/* "dsaEncryption" */
-67,	/* "dsaEncryption-old" */
-66,	/* "dsaWithSHA" */
-113,	/* "dsaWithSHA1" */
-70,	/* "dsaWithSHA1-old" */
-802,	/* "dsa_with_SHA224" */
-803,	/* "dsa_with_SHA256" */
-297,	/* "dvcs" */
-791,	/* "ecdsa-with-Recommended" */
-416,	/* "ecdsa-with-SHA1" */
-793,	/* "ecdsa-with-SHA224" */
-794,	/* "ecdsa-with-SHA256" */
-795,	/* "ecdsa-with-SHA384" */
-796,	/* "ecdsa-with-SHA512" */
-792,	/* "ecdsa-with-Specified" */
-48,	/* "emailAddress" */
-632,	/* "encrypted track 2" */
-885,	/* "enhancedSearchGuide" */
-56,	/* "extendedCertificateAttributes" */
-867,	/* "facsimileTelephoneNumber" */
-462,	/* "favouriteDrink" */
-453,	/* "friendlyCountry" */
-490,	/* "friendlyCountryName" */
-156,	/* "friendlyName" */
-631,	/* "generate cryptogram" */
-509,	/* "generationQualifier" */
-601,	/* "generic cryptogram" */
-99,	/* "givenName" */
-814,	/* "gost89-cnt" */
-855,	/* "hmac" */
-780,	/* "hmac-md5" */
-781,	/* "hmac-sha1" */
-797,	/* "hmacWithMD5" */
-163,	/* "hmacWithSHA1" */
-798,	/* "hmacWithSHA224" */
-799,	/* "hmacWithSHA256" */
-800,	/* "hmacWithSHA384" */
-801,	/* "hmacWithSHA512" */
-486,	/* "homePostalAddress" */
-473,	/* "homeTelephoneNumber" */
-466,	/* "host" */
-889,	/* "houseIdentifier" */
-442,	/* "iA5StringSyntax" */
-381,	/* "iana" */
-824,	/* "id-Gost28147-89-CryptoPro-A-ParamSet" */
-825,	/* "id-Gost28147-89-CryptoPro-B-ParamSet" */
-826,	/* "id-Gost28147-89-CryptoPro-C-ParamSet" */
-827,	/* "id-Gost28147-89-CryptoPro-D-ParamSet" */
-819,	/* "id-Gost28147-89-CryptoPro-KeyMeshing" */
-829,	/* "id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet" */
-828,	/* "id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet" */
-830,	/* "id-Gost28147-89-CryptoPro-RIC-1-ParamSet" */
-820,	/* "id-Gost28147-89-None-KeyMeshing" */
-823,	/* "id-Gost28147-89-TestParamSet" */
-840,	/* "id-GostR3410-2001-CryptoPro-A-ParamSet" */
-841,	/* "id-GostR3410-2001-CryptoPro-B-ParamSet" */
-842,	/* "id-GostR3410-2001-CryptoPro-C-ParamSet" */
-843,	/* "id-GostR3410-2001-CryptoPro-XchA-ParamSet" */
-844,	/* "id-GostR3410-2001-CryptoPro-XchB-ParamSet" */
-839,	/* "id-GostR3410-2001-TestParamSet" */
-832,	/* "id-GostR3410-94-CryptoPro-A-ParamSet" */
-833,	/* "id-GostR3410-94-CryptoPro-B-ParamSet" */
-834,	/* "id-GostR3410-94-CryptoPro-C-ParamSet" */
-835,	/* "id-GostR3410-94-CryptoPro-D-ParamSet" */
-836,	/* "id-GostR3410-94-CryptoPro-XchA-ParamSet" */
-837,	/* "id-GostR3410-94-CryptoPro-XchB-ParamSet" */
-838,	/* "id-GostR3410-94-CryptoPro-XchC-ParamSet" */
-831,	/* "id-GostR3410-94-TestParamSet" */
-845,	/* "id-GostR3410-94-a" */
-846,	/* "id-GostR3410-94-aBis" */
-847,	/* "id-GostR3410-94-b" */
-848,	/* "id-GostR3410-94-bBis" */
-822,	/* "id-GostR3411-94-CryptoProParamSet" */
-821,	/* "id-GostR3411-94-TestParamSet" */
-266,	/* "id-aca" */
-355,	/* "id-aca-accessIdentity" */
-354,	/* "id-aca-authenticationInfo" */
-356,	/* "id-aca-chargingIdentity" */
-399,	/* "id-aca-encAttrs" */
-357,	/* "id-aca-group" */
-358,	/* "id-aca-role" */
-176,	/* "id-ad" */
-788,	/* "id-aes128-wrap" */
-897,	/* "id-aes128-wrap-pad" */
-789,	/* "id-aes192-wrap" */
-900,	/* "id-aes192-wrap-pad" */
-790,	/* "id-aes256-wrap" */
-903,	/* "id-aes256-wrap-pad" */
-262,	/* "id-alg" */
-893,	/* "id-alg-PWRI-KEK" */
-323,	/* "id-alg-des40" */
-326,	/* "id-alg-dh-pop" */
-325,	/* "id-alg-dh-sig-hmac-sha1" */
-324,	/* "id-alg-noSignature" */
-907,	/* "id-camellia128-wrap" */
-908,	/* "id-camellia192-wrap" */
-909,	/* "id-camellia256-wrap" */
-268,	/* "id-cct" */
-361,	/* "id-cct-PKIData" */
-362,	/* "id-cct-PKIResponse" */
-360,	/* "id-cct-crs" */
-81,	/* "id-ce" */
-680,	/* "id-characteristic-two-basis" */
-263,	/* "id-cmc" */
-334,	/* "id-cmc-addExtensions" */
-346,	/* "id-cmc-confirmCertAcceptance" */
-330,	/* "id-cmc-dataReturn" */
-336,	/* "id-cmc-decryptedPOP" */
-335,	/* "id-cmc-encryptedPOP" */
-339,	/* "id-cmc-getCRL" */
-338,	/* "id-cmc-getCert" */
-328,	/* "id-cmc-identification" */
-329,	/* "id-cmc-identityProof" */
-337,	/* "id-cmc-lraPOPWitness" */
-344,	/* "id-cmc-popLinkRandom" */
-345,	/* "id-cmc-popLinkWitness" */
-343,	/* "id-cmc-queryPending" */
-333,	/* "id-cmc-recipientNonce" */
-341,	/* "id-cmc-regInfo" */
-342,	/* "id-cmc-responseInfo" */
-340,	/* "id-cmc-revokeRequest" */
-332,	/* "id-cmc-senderNonce" */
-327,	/* "id-cmc-statusInfo" */
-331,	/* "id-cmc-transactionId" */
-787,	/* "id-ct-asciiTextWithCRLF" */
-408,	/* "id-ecPublicKey" */
-508,	/* "id-hex-multipart-message" */
-507,	/* "id-hex-partial-message" */
-260,	/* "id-it" */
-302,	/* "id-it-caKeyUpdateInfo" */
-298,	/* "id-it-caProtEncCert" */
-311,	/* "id-it-confirmWaitTime" */
-303,	/* "id-it-currentCRL" */
-300,	/* "id-it-encKeyPairTypes" */
-310,	/* "id-it-implicitConfirm" */
-308,	/* "id-it-keyPairParamRep" */
-307,	/* "id-it-keyPairParamReq" */
-312,	/* "id-it-origPKIMessage" */
-301,	/* "id-it-preferredSymmAlg" */
-309,	/* "id-it-revPassphrase" */
-299,	/* "id-it-signKeyPairTypes" */
-305,	/* "id-it-subscriptionRequest" */
-306,	/* "id-it-subscriptionResponse" */
-784,	/* "id-it-suppLangTags" */
-304,	/* "id-it-unsupportedOIDs" */
-128,	/* "id-kp" */
-280,	/* "id-mod-attribute-cert" */
-274,	/* "id-mod-cmc" */
-277,	/* "id-mod-cmp" */
-284,	/* "id-mod-cmp2000" */
-273,	/* "id-mod-crmf" */
-283,	/* "id-mod-dvcs" */
-275,	/* "id-mod-kea-profile-88" */
-276,	/* "id-mod-kea-profile-93" */
-282,	/* "id-mod-ocsp" */
-278,	/* "id-mod-qualified-cert-88" */
-279,	/* "id-mod-qualified-cert-93" */
-281,	/* "id-mod-timestamp-protocol" */
-264,	/* "id-on" */
-347,	/* "id-on-personalData" */
-265,	/* "id-pda" */
-352,	/* "id-pda-countryOfCitizenship" */
-353,	/* "id-pda-countryOfResidence" */
-348,	/* "id-pda-dateOfBirth" */
-351,	/* "id-pda-gender" */
-349,	/* "id-pda-placeOfBirth" */
-175,	/* "id-pe" */
-261,	/* "id-pkip" */
-258,	/* "id-pkix-mod" */
-269,	/* "id-pkix1-explicit-88" */
-271,	/* "id-pkix1-explicit-93" */
-270,	/* "id-pkix1-implicit-88" */
-272,	/* "id-pkix1-implicit-93" */
-662,	/* "id-ppl" */
-267,	/* "id-qcs" */
-359,	/* "id-qcs-pkixQCSyntax-v1" */
-259,	/* "id-qt" */
-313,	/* "id-regCtrl" */
-316,	/* "id-regCtrl-authenticator" */
-319,	/* "id-regCtrl-oldCertID" */
-318,	/* "id-regCtrl-pkiArchiveOptions" */
-317,	/* "id-regCtrl-pkiPublicationInfo" */
-320,	/* "id-regCtrl-protocolEncrKey" */
-315,	/* "id-regCtrl-regToken" */
-314,	/* "id-regInfo" */
-322,	/* "id-regInfo-certReq" */
-321,	/* "id-regInfo-utf8Pairs" */
-191,	/* "id-smime-aa" */
-215,	/* "id-smime-aa-contentHint" */
-218,	/* "id-smime-aa-contentIdentifier" */
-221,	/* "id-smime-aa-contentReference" */
-240,	/* "id-smime-aa-dvcs-dvc" */
-217,	/* "id-smime-aa-encapContentType" */
-222,	/* "id-smime-aa-encrypKeyPref" */
-220,	/* "id-smime-aa-equivalentLabels" */
-232,	/* "id-smime-aa-ets-CertificateRefs" */
-233,	/* "id-smime-aa-ets-RevocationRefs" */
-238,	/* "id-smime-aa-ets-archiveTimeStamp" */
-237,	/* "id-smime-aa-ets-certCRLTimestamp" */
-234,	/* "id-smime-aa-ets-certValues" */
-227,	/* "id-smime-aa-ets-commitmentType" */
-231,	/* "id-smime-aa-ets-contentTimestamp" */
-236,	/* "id-smime-aa-ets-escTimeStamp" */
-230,	/* "id-smime-aa-ets-otherSigCert" */
-235,	/* "id-smime-aa-ets-revocationValues" */
-226,	/* "id-smime-aa-ets-sigPolicyId" */
-229,	/* "id-smime-aa-ets-signerAttr" */
-228,	/* "id-smime-aa-ets-signerLocation" */
-219,	/* "id-smime-aa-macValue" */
-214,	/* "id-smime-aa-mlExpandHistory" */
-216,	/* "id-smime-aa-msgSigDigest" */
-212,	/* "id-smime-aa-receiptRequest" */
-213,	/* "id-smime-aa-securityLabel" */
-239,	/* "id-smime-aa-signatureType" */
-223,	/* "id-smime-aa-signingCertificate" */
-224,	/* "id-smime-aa-smimeEncryptCerts" */
-225,	/* "id-smime-aa-timeStampToken" */
-192,	/* "id-smime-alg" */
-243,	/* "id-smime-alg-3DESwrap" */
-246,	/* "id-smime-alg-CMS3DESwrap" */
-247,	/* "id-smime-alg-CMSRC2wrap" */
-245,	/* "id-smime-alg-ESDH" */
-241,	/* "id-smime-alg-ESDHwith3DES" */
-242,	/* "id-smime-alg-ESDHwithRC2" */
-244,	/* "id-smime-alg-RC2wrap" */
-193,	/* "id-smime-cd" */
-248,	/* "id-smime-cd-ldap" */
-190,	/* "id-smime-ct" */
-210,	/* "id-smime-ct-DVCSRequestData" */
-211,	/* "id-smime-ct-DVCSResponseData" */
-208,	/* "id-smime-ct-TDTInfo" */
-207,	/* "id-smime-ct-TSTInfo" */
-205,	/* "id-smime-ct-authData" */
-786,	/* "id-smime-ct-compressedData" */
-209,	/* "id-smime-ct-contentInfo" */
-206,	/* "id-smime-ct-publishCert" */
-204,	/* "id-smime-ct-receipt" */
-195,	/* "id-smime-cti" */
-255,	/* "id-smime-cti-ets-proofOfApproval" */
-256,	/* "id-smime-cti-ets-proofOfCreation" */
-253,	/* "id-smime-cti-ets-proofOfDelivery" */
-251,	/* "id-smime-cti-ets-proofOfOrigin" */
-252,	/* "id-smime-cti-ets-proofOfReceipt" */
-254,	/* "id-smime-cti-ets-proofOfSender" */
-189,	/* "id-smime-mod" */
-196,	/* "id-smime-mod-cms" */
-197,	/* "id-smime-mod-ess" */
-202,	/* "id-smime-mod-ets-eSigPolicy-88" */
-203,	/* "id-smime-mod-ets-eSigPolicy-97" */
-200,	/* "id-smime-mod-ets-eSignature-88" */
-201,	/* "id-smime-mod-ets-eSignature-97" */
-199,	/* "id-smime-mod-msg-v3" */
-198,	/* "id-smime-mod-oid" */
-194,	/* "id-smime-spq" */
-250,	/* "id-smime-spq-ets-sqt-unotice" */
-249,	/* "id-smime-spq-ets-sqt-uri" */
-34,	/* "idea-cbc" */
-35,	/* "idea-cfb" */
-36,	/* "idea-ecb" */
-46,	/* "idea-ofb" */
-676,	/* "identified-organization" */
-461,	/* "info" */
-101,	/* "initials" */
-869,	/* "internationaliSDNNumber" */
-749,	/* "ipsec3" */
-750,	/* "ipsec4" */
-181,	/* "iso" */
-623,	/* "issuer capabilities" */
-645,	/* "itu-t" */
-492,	/* "janetMailbox" */
-646,	/* "joint-iso-itu-t" */
-150,	/* "keyBag" */
-773,	/* "kisa" */
-477,	/* "lastModifiedBy" */
-476,	/* "lastModifiedTime" */
-157,	/* "localKeyID" */
-15,	/* "localityName" */
-480,	/* "mXRecord" */
-493,	/* "mailPreferenceOption" */
-467,	/* "manager" */
- 3,	/* "md2" */
- 7,	/* "md2WithRSAEncryption" */
-257,	/* "md4" */
-396,	/* "md4WithRSAEncryption" */
- 4,	/* "md5" */
-114,	/* "md5-sha1" */
-104,	/* "md5WithRSA" */
- 8,	/* "md5WithRSAEncryption" */
-95,	/* "mdc2" */
-96,	/* "mdc2WithRSA" */
-875,	/* "member" */
-602,	/* "merchant initiated auth" */
-514,	/* "message extensions" */
-51,	/* "messageDigest" */
-911,	/* "mgf1" */
-506,	/* "mime-mhs-bodies" */
-505,	/* "mime-mhs-headings" */
-488,	/* "mobileTelephoneNumber" */
-481,	/* "nSRecord" */
-173,	/* "name" */
-681,	/* "onBasis" */
-379,	/* "org" */
-17,	/* "organizationName" */
-491,	/* "organizationalStatus" */
-18,	/* "organizationalUnitName" */
-475,	/* "otherMailbox" */
-876,	/* "owner" */
-935,	/* "pSpecified" */
-489,	/* "pagerTelephoneNumber" */
-782,	/* "password based MAC" */
-374,	/* "path" */
-621,	/* "payment gateway capabilities" */
- 9,	/* "pbeWithMD2AndDES-CBC" */
-168,	/* "pbeWithMD2AndRC2-CBC" */
-112,	/* "pbeWithMD5AndCast5CBC" */
-10,	/* "pbeWithMD5AndDES-CBC" */
-169,	/* "pbeWithMD5AndRC2-CBC" */
-148,	/* "pbeWithSHA1And128BitRC2-CBC" */
-144,	/* "pbeWithSHA1And128BitRC4" */
-147,	/* "pbeWithSHA1And2-KeyTripleDES-CBC" */
-146,	/* "pbeWithSHA1And3-KeyTripleDES-CBC" */
-149,	/* "pbeWithSHA1And40BitRC2-CBC" */
-145,	/* "pbeWithSHA1And40BitRC4" */
-170,	/* "pbeWithSHA1AndDES-CBC" */
-68,	/* "pbeWithSHA1AndRC2-CBC" */
-499,	/* "personalSignature" */
-487,	/* "personalTitle" */
-464,	/* "photo" */
-863,	/* "physicalDeliveryOfficeName" */
-437,	/* "pilot" */
-439,	/* "pilotAttributeSyntax" */
-438,	/* "pilotAttributeType" */
-479,	/* "pilotAttributeType27" */
-456,	/* "pilotDSA" */
-441,	/* "pilotGroups" */
-444,	/* "pilotObject" */
-440,	/* "pilotObjectClass" */
-455,	/* "pilotOrganization" */
-445,	/* "pilotPerson" */
-186,	/* "pkcs1" */
-27,	/* "pkcs3" */
-187,	/* "pkcs5" */
-20,	/* "pkcs7" */
-21,	/* "pkcs7-data" */
-25,	/* "pkcs7-digestData" */
-26,	/* "pkcs7-encryptedData" */
-23,	/* "pkcs7-envelopedData" */
-24,	/* "pkcs7-signedAndEnvelopedData" */
-22,	/* "pkcs7-signedData" */
-151,	/* "pkcs8ShroudedKeyBag" */
-47,	/* "pkcs9" */
-862,	/* "postOfficeBox" */
-861,	/* "postalAddress" */
-661,	/* "postalCode" */
-683,	/* "ppBasis" */
-872,	/* "preferredDeliveryMethod" */
-873,	/* "presentationAddress" */
-406,	/* "prime-field" */
-409,	/* "prime192v1" */
-410,	/* "prime192v2" */
-411,	/* "prime192v3" */
-412,	/* "prime239v1" */
-413,	/* "prime239v2" */
-414,	/* "prime239v3" */
-415,	/* "prime256v1" */
-886,	/* "protocolInformation" */
-510,	/* "pseudonym" */
-435,	/* "pss" */
-286,	/* "qcStatements" */
-457,	/* "qualityLabelledData" */
-450,	/* "rFC822localPart" */
-98,	/* "rc2-40-cbc" */
-166,	/* "rc2-64-cbc" */
-37,	/* "rc2-cbc" */
-39,	/* "rc2-cfb" */
-38,	/* "rc2-ecb" */
-40,	/* "rc2-ofb" */
- 5,	/* "rc4" */
-97,	/* "rc4-40" */
-915,	/* "rc4-hmac-md5" */
-120,	/* "rc5-cbc" */
-122,	/* "rc5-cfb" */
-121,	/* "rc5-ecb" */
-123,	/* "rc5-ofb" */
-870,	/* "registeredAddress" */
-460,	/* "rfc822Mailbox" */
-117,	/* "ripemd160" */
-119,	/* "ripemd160WithRSA" */
-400,	/* "role" */
-877,	/* "roleOccupant" */
-448,	/* "room" */
-463,	/* "roomNumber" */
-19,	/* "rsa" */
- 6,	/* "rsaEncryption" */
-644,	/* "rsaOAEPEncryptionSET" */
-377,	/* "rsaSignature" */
-919,	/* "rsaesOaep" */
-912,	/* "rsassaPss" */
-482,	/* "sOARecord" */
-155,	/* "safeContentsBag" */
-291,	/* "sbgp-autonomousSysNum" */
-290,	/* "sbgp-ipAddrBlock" */
-292,	/* "sbgp-routerIdentifier" */
-159,	/* "sdsiCertificate" */
-859,	/* "searchGuide" */
-704,	/* "secp112r1" */
-705,	/* "secp112r2" */
-706,	/* "secp128r1" */
-707,	/* "secp128r2" */
-708,	/* "secp160k1" */
-709,	/* "secp160r1" */
-710,	/* "secp160r2" */
-711,	/* "secp192k1" */
-712,	/* "secp224k1" */
-713,	/* "secp224r1" */
-714,	/* "secp256k1" */
-715,	/* "secp384r1" */
-716,	/* "secp521r1" */
-154,	/* "secretBag" */
-474,	/* "secretary" */
-717,	/* "sect113r1" */
-718,	/* "sect113r2" */
-719,	/* "sect131r1" */
-720,	/* "sect131r2" */
-721,	/* "sect163k1" */
-722,	/* "sect163r1" */
-723,	/* "sect163r2" */
-724,	/* "sect193r1" */
-725,	/* "sect193r2" */
-726,	/* "sect233k1" */
-727,	/* "sect233r1" */
-728,	/* "sect239k1" */
-729,	/* "sect283k1" */
-730,	/* "sect283r1" */
-731,	/* "sect409k1" */
-732,	/* "sect409r1" */
-733,	/* "sect571k1" */
-734,	/* "sect571r1" */
-635,	/* "secure device signature" */
-878,	/* "seeAlso" */
-777,	/* "seed-cbc" */
-779,	/* "seed-cfb" */
-776,	/* "seed-ecb" */
-778,	/* "seed-ofb" */
-105,	/* "serialNumber" */
-625,	/* "set-addPolicy" */
-515,	/* "set-attr" */
-518,	/* "set-brand" */
-638,	/* "set-brand-AmericanExpress" */
-637,	/* "set-brand-Diners" */
-636,	/* "set-brand-IATA-ATA" */
-639,	/* "set-brand-JCB" */
-641,	/* "set-brand-MasterCard" */
-642,	/* "set-brand-Novus" */
-640,	/* "set-brand-Visa" */
-516,	/* "set-policy" */
-607,	/* "set-policy-root" */
-624,	/* "set-rootKeyThumb" */
-620,	/* "setAttr-Cert" */
-628,	/* "setAttr-IssCap-CVM" */
-630,	/* "setAttr-IssCap-Sig" */
-629,	/* "setAttr-IssCap-T2" */
-627,	/* "setAttr-Token-B0Prime" */
-626,	/* "setAttr-Token-EMV" */
-622,	/* "setAttr-TokenType" */
-619,	/* "setCext-IssuerCapabilities" */
-615,	/* "setCext-PGWYcapabilities" */
-616,	/* "setCext-TokenIdentifier" */
-618,	/* "setCext-TokenType" */
-617,	/* "setCext-Track2Data" */
-611,	/* "setCext-cCertRequired" */
-609,	/* "setCext-certType" */
-608,	/* "setCext-hashedRoot" */
-610,	/* "setCext-merchData" */
-613,	/* "setCext-setExt" */
-614,	/* "setCext-setQualf" */
-612,	/* "setCext-tunneling" */
-540,	/* "setct-AcqCardCodeMsg" */
-576,	/* "setct-AcqCardCodeMsgTBE" */
-570,	/* "setct-AuthReqTBE" */
-534,	/* "setct-AuthReqTBS" */
-527,	/* "setct-AuthResBaggage" */
-571,	/* "setct-AuthResTBE" */
-572,	/* "setct-AuthResTBEX" */
-535,	/* "setct-AuthResTBS" */
-536,	/* "setct-AuthResTBSX" */
-528,	/* "setct-AuthRevReqBaggage" */
-577,	/* "setct-AuthRevReqTBE" */
-541,	/* "setct-AuthRevReqTBS" */
-529,	/* "setct-AuthRevResBaggage" */
-542,	/* "setct-AuthRevResData" */
-578,	/* "setct-AuthRevResTBE" */
-579,	/* "setct-AuthRevResTBEB" */
-543,	/* "setct-AuthRevResTBS" */
-573,	/* "setct-AuthTokenTBE" */
-537,	/* "setct-AuthTokenTBS" */
-600,	/* "setct-BCIDistributionTBS" */
-558,	/* "setct-BatchAdminReqData" */
-592,	/* "setct-BatchAdminReqTBE" */
-559,	/* "setct-BatchAdminResData" */
-593,	/* "setct-BatchAdminResTBE" */
-599,	/* "setct-CRLNotificationResTBS" */
-598,	/* "setct-CRLNotificationTBS" */
-580,	/* "setct-CapReqTBE" */
-581,	/* "setct-CapReqTBEX" */
-544,	/* "setct-CapReqTBS" */
-545,	/* "setct-CapReqTBSX" */
-546,	/* "setct-CapResData" */
-582,	/* "setct-CapResTBE" */
-583,	/* "setct-CapRevReqTBE" */
-584,	/* "setct-CapRevReqTBEX" */
-547,	/* "setct-CapRevReqTBS" */
-548,	/* "setct-CapRevReqTBSX" */
-549,	/* "setct-CapRevResData" */
-585,	/* "setct-CapRevResTBE" */
-538,	/* "setct-CapTokenData" */
-530,	/* "setct-CapTokenSeq" */
-574,	/* "setct-CapTokenTBE" */
-575,	/* "setct-CapTokenTBEX" */
-539,	/* "setct-CapTokenTBS" */
-560,	/* "setct-CardCInitResTBS" */
-566,	/* "setct-CertInqReqTBS" */
-563,	/* "setct-CertReqData" */
-595,	/* "setct-CertReqTBE" */
-596,	/* "setct-CertReqTBEX" */
-564,	/* "setct-CertReqTBS" */
-565,	/* "setct-CertResData" */
-597,	/* "setct-CertResTBE" */
-586,	/* "setct-CredReqTBE" */
-587,	/* "setct-CredReqTBEX" */
-550,	/* "setct-CredReqTBS" */
-551,	/* "setct-CredReqTBSX" */
-552,	/* "setct-CredResData" */
-588,	/* "setct-CredResTBE" */
-589,	/* "setct-CredRevReqTBE" */
-590,	/* "setct-CredRevReqTBEX" */
-553,	/* "setct-CredRevReqTBS" */
-554,	/* "setct-CredRevReqTBSX" */
-555,	/* "setct-CredRevResData" */
-591,	/* "setct-CredRevResTBE" */
-567,	/* "setct-ErrorTBS" */
-526,	/* "setct-HODInput" */
-561,	/* "setct-MeAqCInitResTBS" */
-522,	/* "setct-OIData" */
-519,	/* "setct-PANData" */
-521,	/* "setct-PANOnly" */
-520,	/* "setct-PANToken" */
-556,	/* "setct-PCertReqData" */
-557,	/* "setct-PCertResTBS" */
-523,	/* "setct-PI" */
-532,	/* "setct-PI-TBS" */
-524,	/* "setct-PIData" */
-525,	/* "setct-PIDataUnsigned" */
-568,	/* "setct-PIDualSignedTBE" */
-569,	/* "setct-PIUnsignedTBE" */
-531,	/* "setct-PInitResData" */
-533,	/* "setct-PResData" */
-594,	/* "setct-RegFormReqTBE" */
-562,	/* "setct-RegFormResTBS" */
-604,	/* "setext-pinAny" */
-603,	/* "setext-pinSecure" */
-605,	/* "setext-track2" */
-41,	/* "sha" */
-64,	/* "sha1" */
-115,	/* "sha1WithRSA" */
-65,	/* "sha1WithRSAEncryption" */
-675,	/* "sha224" */
-671,	/* "sha224WithRSAEncryption" */
-672,	/* "sha256" */
-668,	/* "sha256WithRSAEncryption" */
-673,	/* "sha384" */
-669,	/* "sha384WithRSAEncryption" */
-674,	/* "sha512" */
-670,	/* "sha512WithRSAEncryption" */
-42,	/* "shaWithRSAEncryption" */
-52,	/* "signingTime" */
-454,	/* "simpleSecurityObject" */
-496,	/* "singleLevelQuality" */
-16,	/* "stateOrProvinceName" */
-660,	/* "streetAddress" */
-498,	/* "subtreeMaximumQuality" */
-497,	/* "subtreeMinimumQuality" */
-890,	/* "supportedAlgorithms" */
-874,	/* "supportedApplicationContext" */
-100,	/* "surname" */
-864,	/* "telephoneNumber" */
-866,	/* "teletexTerminalIdentifier" */
-865,	/* "telexNumber" */
-459,	/* "textEncodedORAddress" */
-293,	/* "textNotice" */
-106,	/* "title" */
-682,	/* "tpBasis" */
-436,	/* "ucl" */
- 0,	/* "undefined" */
-888,	/* "uniqueMember" */
-55,	/* "unstructuredAddress" */
-49,	/* "unstructuredName" */
-880,	/* "userCertificate" */
-465,	/* "userClass" */
-458,	/* "userId" */
-879,	/* "userPassword" */
-373,	/* "valid" */
-678,	/* "wap" */
-679,	/* "wap-wsg" */
-735,	/* "wap-wsg-idm-ecid-wtls1" */
-743,	/* "wap-wsg-idm-ecid-wtls10" */
-744,	/* "wap-wsg-idm-ecid-wtls11" */
-745,	/* "wap-wsg-idm-ecid-wtls12" */
-736,	/* "wap-wsg-idm-ecid-wtls3" */
-737,	/* "wap-wsg-idm-ecid-wtls4" */
-738,	/* "wap-wsg-idm-ecid-wtls5" */
-739,	/* "wap-wsg-idm-ecid-wtls6" */
-740,	/* "wap-wsg-idm-ecid-wtls7" */
-741,	/* "wap-wsg-idm-ecid-wtls8" */
-742,	/* "wap-wsg-idm-ecid-wtls9" */
-804,	/* "whirlpool" */
-868,	/* "x121Address" */
-948,	/* "x25519" */
-503,	/* "x500UniqueIdentifier" */
-158,	/* "x509Certificate" */
-160,	/* "x509Crl" */
-125,	/* "zlib compression" */
+static const unsigned kNIDsInLongNameOrder[] = {
+    363 /* AD Time Stamping */,
+    405 /* ANSI X9.62 */,
+    368 /* Acceptable OCSP Responses */,
+    910 /* Any Extended Key Usage */,
+    664 /* Any language */,
+    177 /* Authority Information Access */,
+    365 /* Basic OCSP Response */,
+    285 /* Biometric Info */,
+    179 /* CA Issuers */,
+    785 /* CA Repository */,
+    131 /* Code Signing */,
+    783 /* Diffie-Hellman based MAC */,
+    382 /* Directory */,
+    392 /* Domain */,
+    132 /* E-mail Protection */,
+    389 /* Enterprises */,
+    384 /* Experimental */,
+    372 /* Extended OCSP Status */,
+    172 /* Extension Request */,
+    813 /* GOST 28147-89 */,
+    849 /* GOST 28147-89 Cryptocom ParamSet */,
+    815 /* GOST 28147-89 MAC */,
+    851 /* GOST 34.10-2001 Cryptocom */,
+    850 /* GOST 34.10-94 Cryptocom */,
+    811 /* GOST R 34.10-2001 */,
+    817 /* GOST R 34.10-2001 DH */,
+    812 /* GOST R 34.10-94 */,
+    818 /* GOST R 34.10-94 DH */,
+    809 /* GOST R 34.11-94 */,
+    816 /* GOST R 34.11-94 PRF */,
+    807 /* GOST R 34.11-94 with GOST R 34.10-2001 */,
+    853 /* GOST R 34.11-94 with GOST R 34.10-2001 Cryptocom */,
+    808 /* GOST R 34.11-94 with GOST R 34.10-94 */,
+    852 /* GOST R 34.11-94 with GOST R 34.10-94 Cryptocom */,
+    854 /* GOST R 3410-2001 Parameter Set Cryptocom */,
+    810 /* HMAC GOST 34.11-94 */,
+    432 /* Hold Instruction Call Issuer */,
+    430 /* Hold Instruction Code */,
+    431 /* Hold Instruction None */,
+    433 /* Hold Instruction Reject */,
+    634 /* ICC or token signature */,
+    294 /* IPSec End System */,
+    295 /* IPSec Tunnel */,
+    296 /* IPSec User */,
+    182 /* ISO Member Body */,
+    183 /* ISO US Member Body */,
+    667 /* Independent */,
+    665 /* Inherit all */,
+    647 /* International Organizations */,
+    142 /* Invalidity Date */,
+    504 /* MIME MHS */,
+    388 /* Mail */,
+    383 /* Management */,
+    417 /* Microsoft CSP Name */,
+    135 /* Microsoft Commercial Code Signing */,
+    138 /* Microsoft Encrypted File System */,
+    171 /* Microsoft Extension Request */,
+    134 /* Microsoft Individual Code Signing */,
+    856 /* Microsoft Local Key set */,
+    137 /* Microsoft Server Gated Crypto */,
+    648 /* Microsoft Smartcardlogin */,
+    136 /* Microsoft Trust List Signing */,
+    649 /* Microsoft Universal Principal Name */,
+    72 /* Netscape Base Url */,
+    76 /* Netscape CA Policy Url */,
+    74 /* Netscape CA Revocation Url */,
+    71 /* Netscape Cert Type */,
+    58 /* Netscape Certificate Extension */,
+    79 /* Netscape Certificate Sequence */,
+    78 /* Netscape Comment */,
+    57 /* Netscape Communications Corp. */,
+    59 /* Netscape Data Type */,
+    75 /* Netscape Renewal Url */,
+    73 /* Netscape Revocation Url */,
+    77 /* Netscape SSL Server Name */,
+    139 /* Netscape Server Gated Crypto */,
+    178 /* OCSP */,
+    370 /* OCSP Archive Cutoff */,
+    367 /* OCSP CRL ID */,
+    369 /* OCSP No Check */,
+    366 /* OCSP Nonce */,
+    371 /* OCSP Service Locator */,
+    180 /* OCSP Signing */,
+    161 /* PBES2 */,
+    69 /* PBKDF2 */,
+    162 /* PBMAC1 */,
+    127 /* PKIX */,
+    858 /* Permanent Identifier */,
+    164 /* Policy Qualifier CPS */,
+    165 /* Policy Qualifier User Notice */,
+    385 /* Private */,
+    663 /* Proxy Certificate Information */,
+    1 /* RSA Data Security, Inc. */,
+    2 /* RSA Data Security, Inc. PKCS */,
+    188 /* S/MIME */,
+    167 /* S/MIME Capabilities */,
+    387 /* SNMPv2 */,
+    512 /* Secure Electronic Transactions */,
+    386 /* Security */,
+    394 /* Selected Attribute Types */,
+    143 /* Strong Extranet ID */,
+    398 /* Subject Information Access */,
+    130 /* TLS Web Client Authentication */,
+    129 /* TLS Web Server Authentication */,
+    133 /* Time Stamping */,
+    375 /* Trust Root */,
+    948 /* X25519 */,
+    12 /* X509 */,
+    402 /* X509v3 AC Targeting */,
+    746 /* X509v3 Any Policy */,
+    90 /* X509v3 Authority Key Identifier */,
+    87 /* X509v3 Basic Constraints */,
+    103 /* X509v3 CRL Distribution Points */,
+    88 /* X509v3 CRL Number */,
+    141 /* X509v3 CRL Reason Code */,
+    771 /* X509v3 Certificate Issuer */,
+    89 /* X509v3 Certificate Policies */,
+    140 /* X509v3 Delta CRL Indicator */,
+    126 /* X509v3 Extended Key Usage */,
+    857 /* X509v3 Freshest CRL */,
+    748 /* X509v3 Inhibit Any Policy */,
+    86 /* X509v3 Issuer Alternative Name */,
+    770 /* X509v3 Issuing Distribution Point */,
+    83 /* X509v3 Key Usage */,
+    666 /* X509v3 Name Constraints */,
+    403 /* X509v3 No Revocation Available */,
+    401 /* X509v3 Policy Constraints */,
+    747 /* X509v3 Policy Mappings */,
+    84 /* X509v3 Private Key Usage Period */,
+    85 /* X509v3 Subject Alternative Name */,
+    769 /* X509v3 Subject Directory Attributes */,
+    82 /* X509v3 Subject Key Identifier */,
+    920 /* X9.42 DH */,
+    184 /* X9.57 */,
+    185 /* X9.57 CM ? */,
+    478 /* aRecord */,
+    289 /* aaControls */,
+    287 /* ac-auditEntity */,
+    397 /* ac-proxying */,
+    288 /* ac-targeting */,
+    446 /* account */,
+    364 /* ad dvcs */,
+    606 /* additional verification */,
+    419 /* aes-128-cbc */,
+    916 /* aes-128-cbc-hmac-sha1 */,
+    896 /* aes-128-ccm */,
+    421 /* aes-128-cfb */,
+    650 /* aes-128-cfb1 */,
+    653 /* aes-128-cfb8 */,
+    904 /* aes-128-ctr */,
+    418 /* aes-128-ecb */,
+    895 /* aes-128-gcm */,
+    420 /* aes-128-ofb */,
+    913 /* aes-128-xts */,
+    423 /* aes-192-cbc */,
+    917 /* aes-192-cbc-hmac-sha1 */,
+    899 /* aes-192-ccm */,
+    425 /* aes-192-cfb */,
+    651 /* aes-192-cfb1 */,
+    654 /* aes-192-cfb8 */,
+    905 /* aes-192-ctr */,
+    422 /* aes-192-ecb */,
+    898 /* aes-192-gcm */,
+    424 /* aes-192-ofb */,
+    427 /* aes-256-cbc */,
+    918 /* aes-256-cbc-hmac-sha1 */,
+    902 /* aes-256-ccm */,
+    429 /* aes-256-cfb */,
+    652 /* aes-256-cfb1 */,
+    655 /* aes-256-cfb8 */,
+    906 /* aes-256-ctr */,
+    426 /* aes-256-ecb */,
+    901 /* aes-256-gcm */,
+    428 /* aes-256-ofb */,
+    914 /* aes-256-xts */,
+    376 /* algorithm */,
+    484 /* associatedDomain */,
+    485 /* associatedName */,
+    501 /* audio */,
+    882 /* authorityRevocationList */,
+    91 /* bf-cbc */,
+    93 /* bf-cfb */,
+    92 /* bf-ecb */,
+    94 /* bf-ofb */,
+    921 /* brainpoolP160r1 */,
+    922 /* brainpoolP160t1 */,
+    923 /* brainpoolP192r1 */,
+    924 /* brainpoolP192t1 */,
+    925 /* brainpoolP224r1 */,
+    926 /* brainpoolP224t1 */,
+    927 /* brainpoolP256r1 */,
+    928 /* brainpoolP256t1 */,
+    929 /* brainpoolP320r1 */,
+    930 /* brainpoolP320t1 */,
+    931 /* brainpoolP384r1 */,
+    932 /* brainpoolP384t1 */,
+    933 /* brainpoolP512r1 */,
+    934 /* brainpoolP512t1 */,
+    494 /* buildingName */,
+    860 /* businessCategory */,
+    691 /* c2onb191v4 */,
+    692 /* c2onb191v5 */,
+    697 /* c2onb239v4 */,
+    698 /* c2onb239v5 */,
+    684 /* c2pnb163v1 */,
+    685 /* c2pnb163v2 */,
+    686 /* c2pnb163v3 */,
+    687 /* c2pnb176v1 */,
+    693 /* c2pnb208w1 */,
+    699 /* c2pnb272w1 */,
+    700 /* c2pnb304w1 */,
+    702 /* c2pnb368w1 */,
+    688 /* c2tnb191v1 */,
+    689 /* c2tnb191v2 */,
+    690 /* c2tnb191v3 */,
+    694 /* c2tnb239v1 */,
+    695 /* c2tnb239v2 */,
+    696 /* c2tnb239v3 */,
+    701 /* c2tnb359v1 */,
+    703 /* c2tnb431r1 */,
+    881 /* cACertificate */,
+    483 /* cNAMERecord */,
+    751 /* camellia-128-cbc */,
+    757 /* camellia-128-cfb */,
+    760 /* camellia-128-cfb1 */,
+    763 /* camellia-128-cfb8 */,
+    754 /* camellia-128-ecb */,
+    766 /* camellia-128-ofb */,
+    752 /* camellia-192-cbc */,
+    758 /* camellia-192-cfb */,
+    761 /* camellia-192-cfb1 */,
+    764 /* camellia-192-cfb8 */,
+    755 /* camellia-192-ecb */,
+    767 /* camellia-192-ofb */,
+    753 /* camellia-256-cbc */,
+    759 /* camellia-256-cfb */,
+    762 /* camellia-256-cfb1 */,
+    765 /* camellia-256-cfb8 */,
+    756 /* camellia-256-ecb */,
+    768 /* camellia-256-ofb */,
+    443 /* caseIgnoreIA5StringSyntax */,
+    108 /* cast5-cbc */,
+    110 /* cast5-cfb */,
+    109 /* cast5-ecb */,
+    111 /* cast5-ofb */,
+    152 /* certBag */,
+    677 /* certicom-arc */,
+    517 /* certificate extensions */,
+    883 /* certificateRevocationList */,
+    54 /* challengePassword */,
+    407 /* characteristic-two-field */,
+    395 /* clearance */,
+    633 /* cleartext track 2 */,
+    894 /* cmac */,
+    13 /* commonName */,
+    513 /* content types */,
+    50 /* contentType */,
+    53 /* countersignature */,
+    14 /* countryName */,
+    153 /* crlBag */,
+    884 /* crossCertificatePair */,
+    806 /* cryptocom */,
+    805 /* cryptopro */,
+    500 /* dITRedirect */,
+    451 /* dNSDomain */,
+    495 /* dSAQuality */,
+    434 /* data */,
+    390 /* dcObject */,
+    891 /* deltaRevocationList */,
+    31 /* des-cbc */,
+    643 /* des-cdmf */,
+    30 /* des-cfb */,
+    656 /* des-cfb1 */,
+    657 /* des-cfb8 */,
+    29 /* des-ecb */,
+    32 /* des-ede */,
+    43 /* des-ede-cbc */,
+    60 /* des-ede-cfb */,
+    62 /* des-ede-ofb */,
+    33 /* des-ede3 */,
+    44 /* des-ede3-cbc */,
+    61 /* des-ede3-cfb */,
+    658 /* des-ede3-cfb1 */,
+    659 /* des-ede3-cfb8 */,
+    63 /* des-ede3-ofb */,
+    45 /* des-ofb */,
+    107 /* description */,
+    871 /* destinationIndicator */,
+    80 /* desx-cbc */,
+    947 /* dh-cofactor-kdf */,
+    946 /* dh-std-kdf */,
+    28 /* dhKeyAgreement */,
+    941 /* dhSinglePass-cofactorDH-sha1kdf-scheme */,
+    942 /* dhSinglePass-cofactorDH-sha224kdf-scheme */,
+    943 /* dhSinglePass-cofactorDH-sha256kdf-scheme */,
+    944 /* dhSinglePass-cofactorDH-sha384kdf-scheme */,
+    945 /* dhSinglePass-cofactorDH-sha512kdf-scheme */,
+    936 /* dhSinglePass-stdDH-sha1kdf-scheme */,
+    937 /* dhSinglePass-stdDH-sha224kdf-scheme */,
+    938 /* dhSinglePass-stdDH-sha256kdf-scheme */,
+    939 /* dhSinglePass-stdDH-sha384kdf-scheme */,
+    940 /* dhSinglePass-stdDH-sha512kdf-scheme */,
+    11 /* directory services (X.500) */,
+    378 /* directory services - algorithms */,
+    887 /* distinguishedName */,
+    892 /* dmdName */,
+    174 /* dnQualifier */,
+    447 /* document */,
+    471 /* documentAuthor */,
+    468 /* documentIdentifier */,
+    472 /* documentLocation */,
+    502 /* documentPublisher */,
+    449 /* documentSeries */,
+    469 /* documentTitle */,
+    470 /* documentVersion */,
+    380 /* dod */,
+    391 /* domainComponent */,
+    452 /* domainRelatedObject */,
+    116 /* dsaEncryption */,
+    67 /* dsaEncryption-old */,
+    66 /* dsaWithSHA */,
+    113 /* dsaWithSHA1 */,
+    70 /* dsaWithSHA1-old */,
+    802 /* dsa_with_SHA224 */,
+    803 /* dsa_with_SHA256 */,
+    297 /* dvcs */,
+    791 /* ecdsa-with-Recommended */,
+    416 /* ecdsa-with-SHA1 */,
+    793 /* ecdsa-with-SHA224 */,
+    794 /* ecdsa-with-SHA256 */,
+    795 /* ecdsa-with-SHA384 */,
+    796 /* ecdsa-with-SHA512 */,
+    792 /* ecdsa-with-Specified */,
+    48 /* emailAddress */,
+    632 /* encrypted track 2 */,
+    885 /* enhancedSearchGuide */,
+    56 /* extendedCertificateAttributes */,
+    867 /* facsimileTelephoneNumber */,
+    462 /* favouriteDrink */,
+    453 /* friendlyCountry */,
+    490 /* friendlyCountryName */,
+    156 /* friendlyName */,
+    631 /* generate cryptogram */,
+    509 /* generationQualifier */,
+    601 /* generic cryptogram */,
+    99 /* givenName */,
+    814 /* gost89-cnt */,
+    855 /* hmac */,
+    780 /* hmac-md5 */,
+    781 /* hmac-sha1 */,
+    797 /* hmacWithMD5 */,
+    163 /* hmacWithSHA1 */,
+    798 /* hmacWithSHA224 */,
+    799 /* hmacWithSHA256 */,
+    800 /* hmacWithSHA384 */,
+    801 /* hmacWithSHA512 */,
+    486 /* homePostalAddress */,
+    473 /* homeTelephoneNumber */,
+    466 /* host */,
+    889 /* houseIdentifier */,
+    442 /* iA5StringSyntax */,
+    381 /* iana */,
+    824 /* id-Gost28147-89-CryptoPro-A-ParamSet */,
+    825 /* id-Gost28147-89-CryptoPro-B-ParamSet */,
+    826 /* id-Gost28147-89-CryptoPro-C-ParamSet */,
+    827 /* id-Gost28147-89-CryptoPro-D-ParamSet */,
+    819 /* id-Gost28147-89-CryptoPro-KeyMeshing */,
+    829 /* id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet */,
+    828 /* id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet */,
+    830 /* id-Gost28147-89-CryptoPro-RIC-1-ParamSet */,
+    820 /* id-Gost28147-89-None-KeyMeshing */,
+    823 /* id-Gost28147-89-TestParamSet */,
+    840 /* id-GostR3410-2001-CryptoPro-A-ParamSet */,
+    841 /* id-GostR3410-2001-CryptoPro-B-ParamSet */,
+    842 /* id-GostR3410-2001-CryptoPro-C-ParamSet */,
+    843 /* id-GostR3410-2001-CryptoPro-XchA-ParamSet */,
+    844 /* id-GostR3410-2001-CryptoPro-XchB-ParamSet */,
+    839 /* id-GostR3410-2001-TestParamSet */,
+    832 /* id-GostR3410-94-CryptoPro-A-ParamSet */,
+    833 /* id-GostR3410-94-CryptoPro-B-ParamSet */,
+    834 /* id-GostR3410-94-CryptoPro-C-ParamSet */,
+    835 /* id-GostR3410-94-CryptoPro-D-ParamSet */,
+    836 /* id-GostR3410-94-CryptoPro-XchA-ParamSet */,
+    837 /* id-GostR3410-94-CryptoPro-XchB-ParamSet */,
+    838 /* id-GostR3410-94-CryptoPro-XchC-ParamSet */,
+    831 /* id-GostR3410-94-TestParamSet */,
+    845 /* id-GostR3410-94-a */,
+    846 /* id-GostR3410-94-aBis */,
+    847 /* id-GostR3410-94-b */,
+    848 /* id-GostR3410-94-bBis */,
+    822 /* id-GostR3411-94-CryptoProParamSet */,
+    821 /* id-GostR3411-94-TestParamSet */,
+    266 /* id-aca */,
+    355 /* id-aca-accessIdentity */,
+    354 /* id-aca-authenticationInfo */,
+    356 /* id-aca-chargingIdentity */,
+    399 /* id-aca-encAttrs */,
+    357 /* id-aca-group */,
+    358 /* id-aca-role */,
+    176 /* id-ad */,
+    788 /* id-aes128-wrap */,
+    897 /* id-aes128-wrap-pad */,
+    789 /* id-aes192-wrap */,
+    900 /* id-aes192-wrap-pad */,
+    790 /* id-aes256-wrap */,
+    903 /* id-aes256-wrap-pad */,
+    262 /* id-alg */,
+    893 /* id-alg-PWRI-KEK */,
+    323 /* id-alg-des40 */,
+    326 /* id-alg-dh-pop */,
+    325 /* id-alg-dh-sig-hmac-sha1 */,
+    324 /* id-alg-noSignature */,
+    907 /* id-camellia128-wrap */,
+    908 /* id-camellia192-wrap */,
+    909 /* id-camellia256-wrap */,
+    268 /* id-cct */,
+    361 /* id-cct-PKIData */,
+    362 /* id-cct-PKIResponse */,
+    360 /* id-cct-crs */,
+    81 /* id-ce */,
+    680 /* id-characteristic-two-basis */,
+    263 /* id-cmc */,
+    334 /* id-cmc-addExtensions */,
+    346 /* id-cmc-confirmCertAcceptance */,
+    330 /* id-cmc-dataReturn */,
+    336 /* id-cmc-decryptedPOP */,
+    335 /* id-cmc-encryptedPOP */,
+    339 /* id-cmc-getCRL */,
+    338 /* id-cmc-getCert */,
+    328 /* id-cmc-identification */,
+    329 /* id-cmc-identityProof */,
+    337 /* id-cmc-lraPOPWitness */,
+    344 /* id-cmc-popLinkRandom */,
+    345 /* id-cmc-popLinkWitness */,
+    343 /* id-cmc-queryPending */,
+    333 /* id-cmc-recipientNonce */,
+    341 /* id-cmc-regInfo */,
+    342 /* id-cmc-responseInfo */,
+    340 /* id-cmc-revokeRequest */,
+    332 /* id-cmc-senderNonce */,
+    327 /* id-cmc-statusInfo */,
+    331 /* id-cmc-transactionId */,
+    787 /* id-ct-asciiTextWithCRLF */,
+    408 /* id-ecPublicKey */,
+    508 /* id-hex-multipart-message */,
+    507 /* id-hex-partial-message */,
+    260 /* id-it */,
+    302 /* id-it-caKeyUpdateInfo */,
+    298 /* id-it-caProtEncCert */,
+    311 /* id-it-confirmWaitTime */,
+    303 /* id-it-currentCRL */,
+    300 /* id-it-encKeyPairTypes */,
+    310 /* id-it-implicitConfirm */,
+    308 /* id-it-keyPairParamRep */,
+    307 /* id-it-keyPairParamReq */,
+    312 /* id-it-origPKIMessage */,
+    301 /* id-it-preferredSymmAlg */,
+    309 /* id-it-revPassphrase */,
+    299 /* id-it-signKeyPairTypes */,
+    305 /* id-it-subscriptionRequest */,
+    306 /* id-it-subscriptionResponse */,
+    784 /* id-it-suppLangTags */,
+    304 /* id-it-unsupportedOIDs */,
+    128 /* id-kp */,
+    280 /* id-mod-attribute-cert */,
+    274 /* id-mod-cmc */,
+    277 /* id-mod-cmp */,
+    284 /* id-mod-cmp2000 */,
+    273 /* id-mod-crmf */,
+    283 /* id-mod-dvcs */,
+    275 /* id-mod-kea-profile-88 */,
+    276 /* id-mod-kea-profile-93 */,
+    282 /* id-mod-ocsp */,
+    278 /* id-mod-qualified-cert-88 */,
+    279 /* id-mod-qualified-cert-93 */,
+    281 /* id-mod-timestamp-protocol */,
+    264 /* id-on */,
+    347 /* id-on-personalData */,
+    265 /* id-pda */,
+    352 /* id-pda-countryOfCitizenship */,
+    353 /* id-pda-countryOfResidence */,
+    348 /* id-pda-dateOfBirth */,
+    351 /* id-pda-gender */,
+    349 /* id-pda-placeOfBirth */,
+    175 /* id-pe */,
+    261 /* id-pkip */,
+    258 /* id-pkix-mod */,
+    269 /* id-pkix1-explicit-88 */,
+    271 /* id-pkix1-explicit-93 */,
+    270 /* id-pkix1-implicit-88 */,
+    272 /* id-pkix1-implicit-93 */,
+    662 /* id-ppl */,
+    267 /* id-qcs */,
+    359 /* id-qcs-pkixQCSyntax-v1 */,
+    259 /* id-qt */,
+    313 /* id-regCtrl */,
+    316 /* id-regCtrl-authenticator */,
+    319 /* id-regCtrl-oldCertID */,
+    318 /* id-regCtrl-pkiArchiveOptions */,
+    317 /* id-regCtrl-pkiPublicationInfo */,
+    320 /* id-regCtrl-protocolEncrKey */,
+    315 /* id-regCtrl-regToken */,
+    314 /* id-regInfo */,
+    322 /* id-regInfo-certReq */,
+    321 /* id-regInfo-utf8Pairs */,
+    191 /* id-smime-aa */,
+    215 /* id-smime-aa-contentHint */,
+    218 /* id-smime-aa-contentIdentifier */,
+    221 /* id-smime-aa-contentReference */,
+    240 /* id-smime-aa-dvcs-dvc */,
+    217 /* id-smime-aa-encapContentType */,
+    222 /* id-smime-aa-encrypKeyPref */,
+    220 /* id-smime-aa-equivalentLabels */,
+    232 /* id-smime-aa-ets-CertificateRefs */,
+    233 /* id-smime-aa-ets-RevocationRefs */,
+    238 /* id-smime-aa-ets-archiveTimeStamp */,
+    237 /* id-smime-aa-ets-certCRLTimestamp */,
+    234 /* id-smime-aa-ets-certValues */,
+    227 /* id-smime-aa-ets-commitmentType */,
+    231 /* id-smime-aa-ets-contentTimestamp */,
+    236 /* id-smime-aa-ets-escTimeStamp */,
+    230 /* id-smime-aa-ets-otherSigCert */,
+    235 /* id-smime-aa-ets-revocationValues */,
+    226 /* id-smime-aa-ets-sigPolicyId */,
+    229 /* id-smime-aa-ets-signerAttr */,
+    228 /* id-smime-aa-ets-signerLocation */,
+    219 /* id-smime-aa-macValue */,
+    214 /* id-smime-aa-mlExpandHistory */,
+    216 /* id-smime-aa-msgSigDigest */,
+    212 /* id-smime-aa-receiptRequest */,
+    213 /* id-smime-aa-securityLabel */,
+    239 /* id-smime-aa-signatureType */,
+    223 /* id-smime-aa-signingCertificate */,
+    224 /* id-smime-aa-smimeEncryptCerts */,
+    225 /* id-smime-aa-timeStampToken */,
+    192 /* id-smime-alg */,
+    243 /* id-smime-alg-3DESwrap */,
+    246 /* id-smime-alg-CMS3DESwrap */,
+    247 /* id-smime-alg-CMSRC2wrap */,
+    245 /* id-smime-alg-ESDH */,
+    241 /* id-smime-alg-ESDHwith3DES */,
+    242 /* id-smime-alg-ESDHwithRC2 */,
+    244 /* id-smime-alg-RC2wrap */,
+    193 /* id-smime-cd */,
+    248 /* id-smime-cd-ldap */,
+    190 /* id-smime-ct */,
+    210 /* id-smime-ct-DVCSRequestData */,
+    211 /* id-smime-ct-DVCSResponseData */,
+    208 /* id-smime-ct-TDTInfo */,
+    207 /* id-smime-ct-TSTInfo */,
+    205 /* id-smime-ct-authData */,
+    786 /* id-smime-ct-compressedData */,
+    209 /* id-smime-ct-contentInfo */,
+    206 /* id-smime-ct-publishCert */,
+    204 /* id-smime-ct-receipt */,
+    195 /* id-smime-cti */,
+    255 /* id-smime-cti-ets-proofOfApproval */,
+    256 /* id-smime-cti-ets-proofOfCreation */,
+    253 /* id-smime-cti-ets-proofOfDelivery */,
+    251 /* id-smime-cti-ets-proofOfOrigin */,
+    252 /* id-smime-cti-ets-proofOfReceipt */,
+    254 /* id-smime-cti-ets-proofOfSender */,
+    189 /* id-smime-mod */,
+    196 /* id-smime-mod-cms */,
+    197 /* id-smime-mod-ess */,
+    202 /* id-smime-mod-ets-eSigPolicy-88 */,
+    203 /* id-smime-mod-ets-eSigPolicy-97 */,
+    200 /* id-smime-mod-ets-eSignature-88 */,
+    201 /* id-smime-mod-ets-eSignature-97 */,
+    199 /* id-smime-mod-msg-v3 */,
+    198 /* id-smime-mod-oid */,
+    194 /* id-smime-spq */,
+    250 /* id-smime-spq-ets-sqt-unotice */,
+    249 /* id-smime-spq-ets-sqt-uri */,
+    34 /* idea-cbc */,
+    35 /* idea-cfb */,
+    36 /* idea-ecb */,
+    46 /* idea-ofb */,
+    676 /* identified-organization */,
+    461 /* info */,
+    101 /* initials */,
+    869 /* internationaliSDNNumber */,
+    749 /* ipsec3 */,
+    750 /* ipsec4 */,
+    181 /* iso */,
+    623 /* issuer capabilities */,
+    645 /* itu-t */,
+    492 /* janetMailbox */,
+    646 /* joint-iso-itu-t */,
+    150 /* keyBag */,
+    773 /* kisa */,
+    477 /* lastModifiedBy */,
+    476 /* lastModifiedTime */,
+    157 /* localKeyID */,
+    15 /* localityName */,
+    480 /* mXRecord */,
+    493 /* mailPreferenceOption */,
+    467 /* manager */,
+    3 /* md2 */,
+    7 /* md2WithRSAEncryption */,
+    257 /* md4 */,
+    396 /* md4WithRSAEncryption */,
+    4 /* md5 */,
+    114 /* md5-sha1 */,
+    104 /* md5WithRSA */,
+    8 /* md5WithRSAEncryption */,
+    95 /* mdc2 */,
+    96 /* mdc2WithRSA */,
+    875 /* member */,
+    602 /* merchant initiated auth */,
+    514 /* message extensions */,
+    51 /* messageDigest */,
+    911 /* mgf1 */,
+    506 /* mime-mhs-bodies */,
+    505 /* mime-mhs-headings */,
+    488 /* mobileTelephoneNumber */,
+    481 /* nSRecord */,
+    173 /* name */,
+    681 /* onBasis */,
+    379 /* org */,
+    17 /* organizationName */,
+    491 /* organizationalStatus */,
+    18 /* organizationalUnitName */,
+    475 /* otherMailbox */,
+    876 /* owner */,
+    935 /* pSpecified */,
+    489 /* pagerTelephoneNumber */,
+    782 /* password based MAC */,
+    374 /* path */,
+    621 /* payment gateway capabilities */,
+    9 /* pbeWithMD2AndDES-CBC */,
+    168 /* pbeWithMD2AndRC2-CBC */,
+    112 /* pbeWithMD5AndCast5CBC */,
+    10 /* pbeWithMD5AndDES-CBC */,
+    169 /* pbeWithMD5AndRC2-CBC */,
+    148 /* pbeWithSHA1And128BitRC2-CBC */,
+    144 /* pbeWithSHA1And128BitRC4 */,
+    147 /* pbeWithSHA1And2-KeyTripleDES-CBC */,
+    146 /* pbeWithSHA1And3-KeyTripleDES-CBC */,
+    149 /* pbeWithSHA1And40BitRC2-CBC */,
+    145 /* pbeWithSHA1And40BitRC4 */,
+    170 /* pbeWithSHA1AndDES-CBC */,
+    68 /* pbeWithSHA1AndRC2-CBC */,
+    499 /* personalSignature */,
+    487 /* personalTitle */,
+    464 /* photo */,
+    863 /* physicalDeliveryOfficeName */,
+    437 /* pilot */,
+    439 /* pilotAttributeSyntax */,
+    438 /* pilotAttributeType */,
+    479 /* pilotAttributeType27 */,
+    456 /* pilotDSA */,
+    441 /* pilotGroups */,
+    444 /* pilotObject */,
+    440 /* pilotObjectClass */,
+    455 /* pilotOrganization */,
+    445 /* pilotPerson */,
+    186 /* pkcs1 */,
+    27 /* pkcs3 */,
+    187 /* pkcs5 */,
+    20 /* pkcs7 */,
+    21 /* pkcs7-data */,
+    25 /* pkcs7-digestData */,
+    26 /* pkcs7-encryptedData */,
+    23 /* pkcs7-envelopedData */,
+    24 /* pkcs7-signedAndEnvelopedData */,
+    22 /* pkcs7-signedData */,
+    151 /* pkcs8ShroudedKeyBag */,
+    47 /* pkcs9 */,
+    862 /* postOfficeBox */,
+    861 /* postalAddress */,
+    661 /* postalCode */,
+    683 /* ppBasis */,
+    872 /* preferredDeliveryMethod */,
+    873 /* presentationAddress */,
+    406 /* prime-field */,
+    409 /* prime192v1 */,
+    410 /* prime192v2 */,
+    411 /* prime192v3 */,
+    412 /* prime239v1 */,
+    413 /* prime239v2 */,
+    414 /* prime239v3 */,
+    415 /* prime256v1 */,
+    886 /* protocolInformation */,
+    510 /* pseudonym */,
+    435 /* pss */,
+    286 /* qcStatements */,
+    457 /* qualityLabelledData */,
+    450 /* rFC822localPart */,
+    98 /* rc2-40-cbc */,
+    166 /* rc2-64-cbc */,
+    37 /* rc2-cbc */,
+    39 /* rc2-cfb */,
+    38 /* rc2-ecb */,
+    40 /* rc2-ofb */,
+    5 /* rc4 */,
+    97 /* rc4-40 */,
+    915 /* rc4-hmac-md5 */,
+    120 /* rc5-cbc */,
+    122 /* rc5-cfb */,
+    121 /* rc5-ecb */,
+    123 /* rc5-ofb */,
+    870 /* registeredAddress */,
+    460 /* rfc822Mailbox */,
+    117 /* ripemd160 */,
+    119 /* ripemd160WithRSA */,
+    400 /* role */,
+    877 /* roleOccupant */,
+    448 /* room */,
+    463 /* roomNumber */,
+    19 /* rsa */,
+    6 /* rsaEncryption */,
+    644 /* rsaOAEPEncryptionSET */,
+    377 /* rsaSignature */,
+    919 /* rsaesOaep */,
+    912 /* rsassaPss */,
+    482 /* sOARecord */,
+    155 /* safeContentsBag */,
+    291 /* sbgp-autonomousSysNum */,
+    290 /* sbgp-ipAddrBlock */,
+    292 /* sbgp-routerIdentifier */,
+    159 /* sdsiCertificate */,
+    859 /* searchGuide */,
+    704 /* secp112r1 */,
+    705 /* secp112r2 */,
+    706 /* secp128r1 */,
+    707 /* secp128r2 */,
+    708 /* secp160k1 */,
+    709 /* secp160r1 */,
+    710 /* secp160r2 */,
+    711 /* secp192k1 */,
+    712 /* secp224k1 */,
+    713 /* secp224r1 */,
+    714 /* secp256k1 */,
+    715 /* secp384r1 */,
+    716 /* secp521r1 */,
+    154 /* secretBag */,
+    474 /* secretary */,
+    717 /* sect113r1 */,
+    718 /* sect113r2 */,
+    719 /* sect131r1 */,
+    720 /* sect131r2 */,
+    721 /* sect163k1 */,
+    722 /* sect163r1 */,
+    723 /* sect163r2 */,
+    724 /* sect193r1 */,
+    725 /* sect193r2 */,
+    726 /* sect233k1 */,
+    727 /* sect233r1 */,
+    728 /* sect239k1 */,
+    729 /* sect283k1 */,
+    730 /* sect283r1 */,
+    731 /* sect409k1 */,
+    732 /* sect409r1 */,
+    733 /* sect571k1 */,
+    734 /* sect571r1 */,
+    635 /* secure device signature */,
+    878 /* seeAlso */,
+    777 /* seed-cbc */,
+    779 /* seed-cfb */,
+    776 /* seed-ecb */,
+    778 /* seed-ofb */,
+    105 /* serialNumber */,
+    625 /* set-addPolicy */,
+    515 /* set-attr */,
+    518 /* set-brand */,
+    638 /* set-brand-AmericanExpress */,
+    637 /* set-brand-Diners */,
+    636 /* set-brand-IATA-ATA */,
+    639 /* set-brand-JCB */,
+    641 /* set-brand-MasterCard */,
+    642 /* set-brand-Novus */,
+    640 /* set-brand-Visa */,
+    516 /* set-policy */,
+    607 /* set-policy-root */,
+    624 /* set-rootKeyThumb */,
+    620 /* setAttr-Cert */,
+    628 /* setAttr-IssCap-CVM */,
+    630 /* setAttr-IssCap-Sig */,
+    629 /* setAttr-IssCap-T2 */,
+    627 /* setAttr-Token-B0Prime */,
+    626 /* setAttr-Token-EMV */,
+    622 /* setAttr-TokenType */,
+    619 /* setCext-IssuerCapabilities */,
+    615 /* setCext-PGWYcapabilities */,
+    616 /* setCext-TokenIdentifier */,
+    618 /* setCext-TokenType */,
+    617 /* setCext-Track2Data */,
+    611 /* setCext-cCertRequired */,
+    609 /* setCext-certType */,
+    608 /* setCext-hashedRoot */,
+    610 /* setCext-merchData */,
+    613 /* setCext-setExt */,
+    614 /* setCext-setQualf */,
+    612 /* setCext-tunneling */,
+    540 /* setct-AcqCardCodeMsg */,
+    576 /* setct-AcqCardCodeMsgTBE */,
+    570 /* setct-AuthReqTBE */,
+    534 /* setct-AuthReqTBS */,
+    527 /* setct-AuthResBaggage */,
+    571 /* setct-AuthResTBE */,
+    572 /* setct-AuthResTBEX */,
+    535 /* setct-AuthResTBS */,
+    536 /* setct-AuthResTBSX */,
+    528 /* setct-AuthRevReqBaggage */,
+    577 /* setct-AuthRevReqTBE */,
+    541 /* setct-AuthRevReqTBS */,
+    529 /* setct-AuthRevResBaggage */,
+    542 /* setct-AuthRevResData */,
+    578 /* setct-AuthRevResTBE */,
+    579 /* setct-AuthRevResTBEB */,
+    543 /* setct-AuthRevResTBS */,
+    573 /* setct-AuthTokenTBE */,
+    537 /* setct-AuthTokenTBS */,
+    600 /* setct-BCIDistributionTBS */,
+    558 /* setct-BatchAdminReqData */,
+    592 /* setct-BatchAdminReqTBE */,
+    559 /* setct-BatchAdminResData */,
+    593 /* setct-BatchAdminResTBE */,
+    599 /* setct-CRLNotificationResTBS */,
+    598 /* setct-CRLNotificationTBS */,
+    580 /* setct-CapReqTBE */,
+    581 /* setct-CapReqTBEX */,
+    544 /* setct-CapReqTBS */,
+    545 /* setct-CapReqTBSX */,
+    546 /* setct-CapResData */,
+    582 /* setct-CapResTBE */,
+    583 /* setct-CapRevReqTBE */,
+    584 /* setct-CapRevReqTBEX */,
+    547 /* setct-CapRevReqTBS */,
+    548 /* setct-CapRevReqTBSX */,
+    549 /* setct-CapRevResData */,
+    585 /* setct-CapRevResTBE */,
+    538 /* setct-CapTokenData */,
+    530 /* setct-CapTokenSeq */,
+    574 /* setct-CapTokenTBE */,
+    575 /* setct-CapTokenTBEX */,
+    539 /* setct-CapTokenTBS */,
+    560 /* setct-CardCInitResTBS */,
+    566 /* setct-CertInqReqTBS */,
+    563 /* setct-CertReqData */,
+    595 /* setct-CertReqTBE */,
+    596 /* setct-CertReqTBEX */,
+    564 /* setct-CertReqTBS */,
+    565 /* setct-CertResData */,
+    597 /* setct-CertResTBE */,
+    586 /* setct-CredReqTBE */,
+    587 /* setct-CredReqTBEX */,
+    550 /* setct-CredReqTBS */,
+    551 /* setct-CredReqTBSX */,
+    552 /* setct-CredResData */,
+    588 /* setct-CredResTBE */,
+    589 /* setct-CredRevReqTBE */,
+    590 /* setct-CredRevReqTBEX */,
+    553 /* setct-CredRevReqTBS */,
+    554 /* setct-CredRevReqTBSX */,
+    555 /* setct-CredRevResData */,
+    591 /* setct-CredRevResTBE */,
+    567 /* setct-ErrorTBS */,
+    526 /* setct-HODInput */,
+    561 /* setct-MeAqCInitResTBS */,
+    522 /* setct-OIData */,
+    519 /* setct-PANData */,
+    521 /* setct-PANOnly */,
+    520 /* setct-PANToken */,
+    556 /* setct-PCertReqData */,
+    557 /* setct-PCertResTBS */,
+    523 /* setct-PI */,
+    532 /* setct-PI-TBS */,
+    524 /* setct-PIData */,
+    525 /* setct-PIDataUnsigned */,
+    568 /* setct-PIDualSignedTBE */,
+    569 /* setct-PIUnsignedTBE */,
+    531 /* setct-PInitResData */,
+    533 /* setct-PResData */,
+    594 /* setct-RegFormReqTBE */,
+    562 /* setct-RegFormResTBS */,
+    604 /* setext-pinAny */,
+    603 /* setext-pinSecure */,
+    605 /* setext-track2 */,
+    41 /* sha */,
+    64 /* sha1 */,
+    115 /* sha1WithRSA */,
+    65 /* sha1WithRSAEncryption */,
+    675 /* sha224 */,
+    671 /* sha224WithRSAEncryption */,
+    672 /* sha256 */,
+    668 /* sha256WithRSAEncryption */,
+    673 /* sha384 */,
+    669 /* sha384WithRSAEncryption */,
+    674 /* sha512 */,
+    670 /* sha512WithRSAEncryption */,
+    42 /* shaWithRSAEncryption */,
+    52 /* signingTime */,
+    454 /* simpleSecurityObject */,
+    496 /* singleLevelQuality */,
+    16 /* stateOrProvinceName */,
+    660 /* streetAddress */,
+    498 /* subtreeMaximumQuality */,
+    497 /* subtreeMinimumQuality */,
+    890 /* supportedAlgorithms */,
+    874 /* supportedApplicationContext */,
+    100 /* surname */,
+    864 /* telephoneNumber */,
+    866 /* teletexTerminalIdentifier */,
+    865 /* telexNumber */,
+    459 /* textEncodedORAddress */,
+    293 /* textNotice */,
+    106 /* title */,
+    682 /* tpBasis */,
+    436 /* ucl */,
+    0 /* undefined */,
+    888 /* uniqueMember */,
+    55 /* unstructuredAddress */,
+    49 /* unstructuredName */,
+    880 /* userCertificate */,
+    465 /* userClass */,
+    458 /* userId */,
+    879 /* userPassword */,
+    373 /* valid */,
+    678 /* wap */,
+    679 /* wap-wsg */,
+    735 /* wap-wsg-idm-ecid-wtls1 */,
+    743 /* wap-wsg-idm-ecid-wtls10 */,
+    744 /* wap-wsg-idm-ecid-wtls11 */,
+    745 /* wap-wsg-idm-ecid-wtls12 */,
+    736 /* wap-wsg-idm-ecid-wtls3 */,
+    737 /* wap-wsg-idm-ecid-wtls4 */,
+    738 /* wap-wsg-idm-ecid-wtls5 */,
+    739 /* wap-wsg-idm-ecid-wtls6 */,
+    740 /* wap-wsg-idm-ecid-wtls7 */,
+    741 /* wap-wsg-idm-ecid-wtls8 */,
+    742 /* wap-wsg-idm-ecid-wtls9 */,
+    804 /* whirlpool */,
+    868 /* x121Address */,
+    503 /* x500UniqueIdentifier */,
+    158 /* x509Certificate */,
+    160 /* x509Crl */,
+    125 /* zlib compression */,
 };
 
-static const unsigned int kNIDsInOIDOrder[NUM_OBJ]={
- 0,	/* OBJ_undef                        0 */
-181,	/* OBJ_iso                          1 */
-393,	/* OBJ_joint_iso_ccitt              OBJ_joint_iso_itu_t */
-404,	/* OBJ_ccitt                        OBJ_itu_t */
-645,	/* OBJ_itu_t                        0 */
-646,	/* OBJ_joint_iso_itu_t              2 */
-434,	/* OBJ_data                         0 9 */
-182,	/* OBJ_member_body                  1 2 */
-379,	/* OBJ_org                          1 3 */
-676,	/* OBJ_identified_organization      1 3 */
-11,	/* OBJ_X500                         2 5 */
-647,	/* OBJ_international_organizations  2 23 */
-380,	/* OBJ_dod                          1 3 6 */
-12,	/* OBJ_X509                         2 5 4 */
-378,	/* OBJ_X500algorithms               2 5 8 */
-81,	/* OBJ_id_ce                        2 5 29 */
-512,	/* OBJ_id_set                       2 23 42 */
-678,	/* OBJ_wap                          2 23 43 */
-435,	/* OBJ_pss                          0 9 2342 */
-183,	/* OBJ_ISO_US                       1 2 840 */
-381,	/* OBJ_iana                         1 3 6 1 */
-677,	/* OBJ_certicom_arc                 1 3 132 */
-394,	/* OBJ_selected_attribute_types     2 5 1 5 */
-13,	/* OBJ_commonName                   2 5 4 3 */
-100,	/* OBJ_surname                      2 5 4 4 */
-105,	/* OBJ_serialNumber                 2 5 4 5 */
-14,	/* OBJ_countryName                  2 5 4 6 */
-15,	/* OBJ_localityName                 2 5 4 7 */
-16,	/* OBJ_stateOrProvinceName          2 5 4 8 */
-660,	/* OBJ_streetAddress                2 5 4 9 */
-17,	/* OBJ_organizationName             2 5 4 10 */
-18,	/* OBJ_organizationalUnitName       2 5 4 11 */
-106,	/* OBJ_title                        2 5 4 12 */
-107,	/* OBJ_description                  2 5 4 13 */
-859,	/* OBJ_searchGuide                  2 5 4 14 */
-860,	/* OBJ_businessCategory             2 5 4 15 */
-861,	/* OBJ_postalAddress                2 5 4 16 */
-661,	/* OBJ_postalCode                   2 5 4 17 */
-862,	/* OBJ_postOfficeBox                2 5 4 18 */
-863,	/* OBJ_physicalDeliveryOfficeName   2 5 4 19 */
-864,	/* OBJ_telephoneNumber              2 5 4 20 */
-865,	/* OBJ_telexNumber                  2 5 4 21 */
-866,	/* OBJ_teletexTerminalIdentifier    2 5 4 22 */
-867,	/* OBJ_facsimileTelephoneNumber     2 5 4 23 */
-868,	/* OBJ_x121Address                  2 5 4 24 */
-869,	/* OBJ_internationaliSDNNumber      2 5 4 25 */
-870,	/* OBJ_registeredAddress            2 5 4 26 */
-871,	/* OBJ_destinationIndicator         2 5 4 27 */
-872,	/* OBJ_preferredDeliveryMethod      2 5 4 28 */
-873,	/* OBJ_presentationAddress          2 5 4 29 */
-874,	/* OBJ_supportedApplicationContext  2 5 4 30 */
-875,	/* OBJ_member                       2 5 4 31 */
-876,	/* OBJ_owner                        2 5 4 32 */
-877,	/* OBJ_roleOccupant                 2 5 4 33 */
-878,	/* OBJ_seeAlso                      2 5 4 34 */
-879,	/* OBJ_userPassword                 2 5 4 35 */
-880,	/* OBJ_userCertificate              2 5 4 36 */
-881,	/* OBJ_cACertificate                2 5 4 37 */
-882,	/* OBJ_authorityRevocationList      2 5 4 38 */
-883,	/* OBJ_certificateRevocationList    2 5 4 39 */
-884,	/* OBJ_crossCertificatePair         2 5 4 40 */
-173,	/* OBJ_name                         2 5 4 41 */
-99,	/* OBJ_givenName                    2 5 4 42 */
-101,	/* OBJ_initials                     2 5 4 43 */
-509,	/* OBJ_generationQualifier          2 5 4 44 */
-503,	/* OBJ_x500UniqueIdentifier         2 5 4 45 */
-174,	/* OBJ_dnQualifier                  2 5 4 46 */
-885,	/* OBJ_enhancedSearchGuide          2 5 4 47 */
-886,	/* OBJ_protocolInformation          2 5 4 48 */
-887,	/* OBJ_distinguishedName            2 5 4 49 */
-888,	/* OBJ_uniqueMember                 2 5 4 50 */
-889,	/* OBJ_houseIdentifier              2 5 4 51 */
-890,	/* OBJ_supportedAlgorithms          2 5 4 52 */
-891,	/* OBJ_deltaRevocationList          2 5 4 53 */
-892,	/* OBJ_dmdName                      2 5 4 54 */
-510,	/* OBJ_pseudonym                    2 5 4 65 */
-400,	/* OBJ_role                         2 5 4 72 */
-769,	/* OBJ_subject_directory_attributes 2 5 29 9 */
-82,	/* OBJ_subject_key_identifier       2 5 29 14 */
-83,	/* OBJ_key_usage                    2 5 29 15 */
-84,	/* OBJ_private_key_usage_period     2 5 29 16 */
-85,	/* OBJ_subject_alt_name             2 5 29 17 */
-86,	/* OBJ_issuer_alt_name              2 5 29 18 */
-87,	/* OBJ_basic_constraints            2 5 29 19 */
-88,	/* OBJ_crl_number                   2 5 29 20 */
-141,	/* OBJ_crl_reason                   2 5 29 21 */
-430,	/* OBJ_hold_instruction_code        2 5 29 23 */
-142,	/* OBJ_invalidity_date              2 5 29 24 */
-140,	/* OBJ_delta_crl                    2 5 29 27 */
-770,	/* OBJ_issuing_distribution_point   2 5 29 28 */
-771,	/* OBJ_certificate_issuer           2 5 29 29 */
-666,	/* OBJ_name_constraints             2 5 29 30 */
-103,	/* OBJ_crl_distribution_points      2 5 29 31 */
-89,	/* OBJ_certificate_policies         2 5 29 32 */
-747,	/* OBJ_policy_mappings              2 5 29 33 */
-90,	/* OBJ_authority_key_identifier     2 5 29 35 */
-401,	/* OBJ_policy_constraints           2 5 29 36 */
-126,	/* OBJ_ext_key_usage                2 5 29 37 */
-857,	/* OBJ_freshest_crl                 2 5 29 46 */
-748,	/* OBJ_inhibit_any_policy           2 5 29 54 */
-402,	/* OBJ_target_information           2 5 29 55 */
-403,	/* OBJ_no_rev_avail                 2 5 29 56 */
-513,	/* OBJ_set_ctype                    2 23 42 0 */
-514,	/* OBJ_set_msgExt                   2 23 42 1 */
-515,	/* OBJ_set_attr                     2 23 42 3 */
-516,	/* OBJ_set_policy                   2 23 42 5 */
-517,	/* OBJ_set_certExt                  2 23 42 7 */
-518,	/* OBJ_set_brand                    2 23 42 8 */
-679,	/* OBJ_wap_wsg                      2 23 43 1 */
-382,	/* OBJ_Directory                    1 3 6 1 1 */
-383,	/* OBJ_Management                   1 3 6 1 2 */
-384,	/* OBJ_Experimental                 1 3 6 1 3 */
-385,	/* OBJ_Private                      1 3 6 1 4 */
-386,	/* OBJ_Security                     1 3 6 1 5 */
-387,	/* OBJ_SNMPv2                       1 3 6 1 6 */
-388,	/* OBJ_Mail                         1 3 6 1 7 */
-376,	/* OBJ_algorithm                    1 3 14 3 2 */
-395,	/* OBJ_clearance                    2 5 1 5 55 */
-19,	/* OBJ_rsa                          2 5 8 1 1 */
-96,	/* OBJ_mdc2WithRSA                  2 5 8 3 100 */
-95,	/* OBJ_mdc2                         2 5 8 3 101 */
-746,	/* OBJ_any_policy                   2 5 29 32 0 */
-910,	/* OBJ_anyExtendedKeyUsage          2 5 29 37 0 */
-519,	/* OBJ_setct_PANData                2 23 42 0 0 */
-520,	/* OBJ_setct_PANToken               2 23 42 0 1 */
-521,	/* OBJ_setct_PANOnly                2 23 42 0 2 */
-522,	/* OBJ_setct_OIData                 2 23 42 0 3 */
-523,	/* OBJ_setct_PI                     2 23 42 0 4 */
-524,	/* OBJ_setct_PIData                 2 23 42 0 5 */
-525,	/* OBJ_setct_PIDataUnsigned         2 23 42 0 6 */
-526,	/* OBJ_setct_HODInput               2 23 42 0 7 */
-527,	/* OBJ_setct_AuthResBaggage         2 23 42 0 8 */
-528,	/* OBJ_setct_AuthRevReqBaggage      2 23 42 0 9 */
-529,	/* OBJ_setct_AuthRevResBaggage      2 23 42 0 10 */
-530,	/* OBJ_setct_CapTokenSeq            2 23 42 0 11 */
-531,	/* OBJ_setct_PInitResData           2 23 42 0 12 */
-532,	/* OBJ_setct_PI_TBS                 2 23 42 0 13 */
-533,	/* OBJ_setct_PResData               2 23 42 0 14 */
-534,	/* OBJ_setct_AuthReqTBS             2 23 42 0 16 */
-535,	/* OBJ_setct_AuthResTBS             2 23 42 0 17 */
-536,	/* OBJ_setct_AuthResTBSX            2 23 42 0 18 */
-537,	/* OBJ_setct_AuthTokenTBS           2 23 42 0 19 */
-538,	/* OBJ_setct_CapTokenData           2 23 42 0 20 */
-539,	/* OBJ_setct_CapTokenTBS            2 23 42 0 21 */
-540,	/* OBJ_setct_AcqCardCodeMsg         2 23 42 0 22 */
-541,	/* OBJ_setct_AuthRevReqTBS          2 23 42 0 23 */
-542,	/* OBJ_setct_AuthRevResData         2 23 42 0 24 */
-543,	/* OBJ_setct_AuthRevResTBS          2 23 42 0 25 */
-544,	/* OBJ_setct_CapReqTBS              2 23 42 0 26 */
-545,	/* OBJ_setct_CapReqTBSX             2 23 42 0 27 */
-546,	/* OBJ_setct_CapResData             2 23 42 0 28 */
-547,	/* OBJ_setct_CapRevReqTBS           2 23 42 0 29 */
-548,	/* OBJ_setct_CapRevReqTBSX          2 23 42 0 30 */
-549,	/* OBJ_setct_CapRevResData          2 23 42 0 31 */
-550,	/* OBJ_setct_CredReqTBS             2 23 42 0 32 */
-551,	/* OBJ_setct_CredReqTBSX            2 23 42 0 33 */
-552,	/* OBJ_setct_CredResData            2 23 42 0 34 */
-553,	/* OBJ_setct_CredRevReqTBS          2 23 42 0 35 */
-554,	/* OBJ_setct_CredRevReqTBSX         2 23 42 0 36 */
-555,	/* OBJ_setct_CredRevResData         2 23 42 0 37 */
-556,	/* OBJ_setct_PCertReqData           2 23 42 0 38 */
-557,	/* OBJ_setct_PCertResTBS            2 23 42 0 39 */
-558,	/* OBJ_setct_BatchAdminReqData      2 23 42 0 40 */
-559,	/* OBJ_setct_BatchAdminResData      2 23 42 0 41 */
-560,	/* OBJ_setct_CardCInitResTBS        2 23 42 0 42 */
-561,	/* OBJ_setct_MeAqCInitResTBS        2 23 42 0 43 */
-562,	/* OBJ_setct_RegFormResTBS          2 23 42 0 44 */
-563,	/* OBJ_setct_CertReqData            2 23 42 0 45 */
-564,	/* OBJ_setct_CertReqTBS             2 23 42 0 46 */
-565,	/* OBJ_setct_CertResData            2 23 42 0 47 */
-566,	/* OBJ_setct_CertInqReqTBS          2 23 42 0 48 */
-567,	/* OBJ_setct_ErrorTBS               2 23 42 0 49 */
-568,	/* OBJ_setct_PIDualSignedTBE        2 23 42 0 50 */
-569,	/* OBJ_setct_PIUnsignedTBE          2 23 42 0 51 */
-570,	/* OBJ_setct_AuthReqTBE             2 23 42 0 52 */
-571,	/* OBJ_setct_AuthResTBE             2 23 42 0 53 */
-572,	/* OBJ_setct_AuthResTBEX            2 23 42 0 54 */
-573,	/* OBJ_setct_AuthTokenTBE           2 23 42 0 55 */
-574,	/* OBJ_setct_CapTokenTBE            2 23 42 0 56 */
-575,	/* OBJ_setct_CapTokenTBEX           2 23 42 0 57 */
-576,	/* OBJ_setct_AcqCardCodeMsgTBE      2 23 42 0 58 */
-577,	/* OBJ_setct_AuthRevReqTBE          2 23 42 0 59 */
-578,	/* OBJ_setct_AuthRevResTBE          2 23 42 0 60 */
-579,	/* OBJ_setct_AuthRevResTBEB         2 23 42 0 61 */
-580,	/* OBJ_setct_CapReqTBE              2 23 42 0 62 */
-581,	/* OBJ_setct_CapReqTBEX             2 23 42 0 63 */
-582,	/* OBJ_setct_CapResTBE              2 23 42 0 64 */
-583,	/* OBJ_setct_CapRevReqTBE           2 23 42 0 65 */
-584,	/* OBJ_setct_CapRevReqTBEX          2 23 42 0 66 */
-585,	/* OBJ_setct_CapRevResTBE           2 23 42 0 67 */
-586,	/* OBJ_setct_CredReqTBE             2 23 42 0 68 */
-587,	/* OBJ_setct_CredReqTBEX            2 23 42 0 69 */
-588,	/* OBJ_setct_CredResTBE             2 23 42 0 70 */
-589,	/* OBJ_setct_CredRevReqTBE          2 23 42 0 71 */
-590,	/* OBJ_setct_CredRevReqTBEX         2 23 42 0 72 */
-591,	/* OBJ_setct_CredRevResTBE          2 23 42 0 73 */
-592,	/* OBJ_setct_BatchAdminReqTBE       2 23 42 0 74 */
-593,	/* OBJ_setct_BatchAdminResTBE       2 23 42 0 75 */
-594,	/* OBJ_setct_RegFormReqTBE          2 23 42 0 76 */
-595,	/* OBJ_setct_CertReqTBE             2 23 42 0 77 */
-596,	/* OBJ_setct_CertReqTBEX            2 23 42 0 78 */
-597,	/* OBJ_setct_CertResTBE             2 23 42 0 79 */
-598,	/* OBJ_setct_CRLNotificationTBS     2 23 42 0 80 */
-599,	/* OBJ_setct_CRLNotificationResTBS  2 23 42 0 81 */
-600,	/* OBJ_setct_BCIDistributionTBS     2 23 42 0 82 */
-601,	/* OBJ_setext_genCrypt              2 23 42 1 1 */
-602,	/* OBJ_setext_miAuth                2 23 42 1 3 */
-603,	/* OBJ_setext_pinSecure             2 23 42 1 4 */
-604,	/* OBJ_setext_pinAny                2 23 42 1 5 */
-605,	/* OBJ_setext_track2                2 23 42 1 7 */
-606,	/* OBJ_setext_cv                    2 23 42 1 8 */
-620,	/* OBJ_setAttr_Cert                 2 23 42 3 0 */
-621,	/* OBJ_setAttr_PGWYcap              2 23 42 3 1 */
-622,	/* OBJ_setAttr_TokenType            2 23 42 3 2 */
-623,	/* OBJ_setAttr_IssCap               2 23 42 3 3 */
-607,	/* OBJ_set_policy_root              2 23 42 5 0 */
-608,	/* OBJ_setCext_hashedRoot           2 23 42 7 0 */
-609,	/* OBJ_setCext_certType             2 23 42 7 1 */
-610,	/* OBJ_setCext_merchData            2 23 42 7 2 */
-611,	/* OBJ_setCext_cCertRequired        2 23 42 7 3 */
-612,	/* OBJ_setCext_tunneling            2 23 42 7 4 */
-613,	/* OBJ_setCext_setExt               2 23 42 7 5 */
-614,	/* OBJ_setCext_setQualf             2 23 42 7 6 */
-615,	/* OBJ_setCext_PGWYcapabilities     2 23 42 7 7 */
-616,	/* OBJ_setCext_TokenIdentifier      2 23 42 7 8 */
-617,	/* OBJ_setCext_Track2Data           2 23 42 7 9 */
-618,	/* OBJ_setCext_TokenType            2 23 42 7 10 */
-619,	/* OBJ_setCext_IssuerCapabilities   2 23 42 7 11 */
-636,	/* OBJ_set_brand_IATA_ATA           2 23 42 8 1 */
-640,	/* OBJ_set_brand_Visa               2 23 42 8 4 */
-641,	/* OBJ_set_brand_MasterCard         2 23 42 8 5 */
-637,	/* OBJ_set_brand_Diners             2 23 42 8 30 */
-638,	/* OBJ_set_brand_AmericanExpress    2 23 42 8 34 */
-639,	/* OBJ_set_brand_JCB                2 23 42 8 35 */
-805,	/* OBJ_cryptopro                    1 2 643 2 2 */
-806,	/* OBJ_cryptocom                    1 2 643 2 9 */
-184,	/* OBJ_X9_57                        1 2 840 10040 */
-405,	/* OBJ_ansi_X9_62                   1 2 840 10045 */
-389,	/* OBJ_Enterprises                  1 3 6 1 4 1 */
-504,	/* OBJ_mime_mhs                     1 3 6 1 7 1 */
-104,	/* OBJ_md5WithRSA                   1 3 14 3 2 3 */
-29,	/* OBJ_des_ecb                      1 3 14 3 2 6 */
-31,	/* OBJ_des_cbc                      1 3 14 3 2 7 */
-45,	/* OBJ_des_ofb64                    1 3 14 3 2 8 */
-30,	/* OBJ_des_cfb64                    1 3 14 3 2 9 */
-377,	/* OBJ_rsaSignature                 1 3 14 3 2 11 */
-67,	/* OBJ_dsa_2                        1 3 14 3 2 12 */
-66,	/* OBJ_dsaWithSHA                   1 3 14 3 2 13 */
-42,	/* OBJ_shaWithRSAEncryption         1 3 14 3 2 15 */
-32,	/* OBJ_des_ede_ecb                  1 3 14 3 2 17 */
-41,	/* OBJ_sha                          1 3 14 3 2 18 */
-64,	/* OBJ_sha1                         1 3 14 3 2 26 */
-70,	/* OBJ_dsaWithSHA1_2                1 3 14 3 2 27 */
-115,	/* OBJ_sha1WithRSA                  1 3 14 3 2 29 */
-117,	/* OBJ_ripemd160                    1 3 36 3 2 1 */
-143,	/* OBJ_sxnet                        1 3 101 1 4 1 */
-721,	/* OBJ_sect163k1                    1 3 132 0 1 */
-722,	/* OBJ_sect163r1                    1 3 132 0 2 */
-728,	/* OBJ_sect239k1                    1 3 132 0 3 */
-717,	/* OBJ_sect113r1                    1 3 132 0 4 */
-718,	/* OBJ_sect113r2                    1 3 132 0 5 */
-704,	/* OBJ_secp112r1                    1 3 132 0 6 */
-705,	/* OBJ_secp112r2                    1 3 132 0 7 */
-709,	/* OBJ_secp160r1                    1 3 132 0 8 */
-708,	/* OBJ_secp160k1                    1 3 132 0 9 */
-714,	/* OBJ_secp256k1                    1 3 132 0 10 */
-723,	/* OBJ_sect163r2                    1 3 132 0 15 */
-729,	/* OBJ_sect283k1                    1 3 132 0 16 */
-730,	/* OBJ_sect283r1                    1 3 132 0 17 */
-719,	/* OBJ_sect131r1                    1 3 132 0 22 */
-720,	/* OBJ_sect131r2                    1 3 132 0 23 */
-724,	/* OBJ_sect193r1                    1 3 132 0 24 */
-725,	/* OBJ_sect193r2                    1 3 132 0 25 */
-726,	/* OBJ_sect233k1                    1 3 132 0 26 */
-727,	/* OBJ_sect233r1                    1 3 132 0 27 */
-706,	/* OBJ_secp128r1                    1 3 132 0 28 */
-707,	/* OBJ_secp128r2                    1 3 132 0 29 */
-710,	/* OBJ_secp160r2                    1 3 132 0 30 */
-711,	/* OBJ_secp192k1                    1 3 132 0 31 */
-712,	/* OBJ_secp224k1                    1 3 132 0 32 */
-713,	/* OBJ_secp224r1                    1 3 132 0 33 */
-715,	/* OBJ_secp384r1                    1 3 132 0 34 */
-716,	/* OBJ_secp521r1                    1 3 132 0 35 */
-731,	/* OBJ_sect409k1                    1 3 132 0 36 */
-732,	/* OBJ_sect409r1                    1 3 132 0 37 */
-733,	/* OBJ_sect571k1                    1 3 132 0 38 */
-734,	/* OBJ_sect571r1                    1 3 132 0 39 */
-624,	/* OBJ_set_rootKeyThumb             2 23 42 3 0 0 */
-625,	/* OBJ_set_addPolicy                2 23 42 3 0 1 */
-626,	/* OBJ_setAttr_Token_EMV            2 23 42 3 2 1 */
-627,	/* OBJ_setAttr_Token_B0Prime        2 23 42 3 2 2 */
-628,	/* OBJ_setAttr_IssCap_CVM           2 23 42 3 3 3 */
-629,	/* OBJ_setAttr_IssCap_T2            2 23 42 3 3 4 */
-630,	/* OBJ_setAttr_IssCap_Sig           2 23 42 3 3 5 */
-642,	/* OBJ_set_brand_Novus              2 23 42 8 6011 */
-735,	/* OBJ_wap_wsg_idm_ecid_wtls1       2 23 43 1 4 1 */
-736,	/* OBJ_wap_wsg_idm_ecid_wtls3       2 23 43 1 4 3 */
-737,	/* OBJ_wap_wsg_idm_ecid_wtls4       2 23 43 1 4 4 */
-738,	/* OBJ_wap_wsg_idm_ecid_wtls5       2 23 43 1 4 5 */
-739,	/* OBJ_wap_wsg_idm_ecid_wtls6       2 23 43 1 4 6 */
-740,	/* OBJ_wap_wsg_idm_ecid_wtls7       2 23 43 1 4 7 */
-741,	/* OBJ_wap_wsg_idm_ecid_wtls8       2 23 43 1 4 8 */
-742,	/* OBJ_wap_wsg_idm_ecid_wtls9       2 23 43 1 4 9 */
-743,	/* OBJ_wap_wsg_idm_ecid_wtls10      2 23 43 1 4 10 */
-744,	/* OBJ_wap_wsg_idm_ecid_wtls11      2 23 43 1 4 11 */
-745,	/* OBJ_wap_wsg_idm_ecid_wtls12      2 23 43 1 4 12 */
-804,	/* OBJ_whirlpool                    1 0 10118 3 0 55 */
-773,	/* OBJ_kisa                         1 2 410 200004 */
-807,	/* OBJ_id_GostR3411_94_with_GostR3410_2001 1 2 643 2 2 3 */
-808,	/* OBJ_id_GostR3411_94_with_GostR3410_94 1 2 643 2 2 4 */
-809,	/* OBJ_id_GostR3411_94              1 2 643 2 2 9 */
-810,	/* OBJ_id_HMACGostR3411_94          1 2 643 2 2 10 */
-811,	/* OBJ_id_GostR3410_2001            1 2 643 2 2 19 */
-812,	/* OBJ_id_GostR3410_94              1 2 643 2 2 20 */
-813,	/* OBJ_id_Gost28147_89              1 2 643 2 2 21 */
-815,	/* OBJ_id_Gost28147_89_MAC          1 2 643 2 2 22 */
-816,	/* OBJ_id_GostR3411_94_prf          1 2 643 2 2 23 */
-817,	/* OBJ_id_GostR3410_2001DH          1 2 643 2 2 98 */
-818,	/* OBJ_id_GostR3410_94DH            1 2 643 2 2 99 */
- 1,	/* OBJ_rsadsi                       1 2 840 113549 */
-185,	/* OBJ_X9cm                         1 2 840 10040 4 */
-127,	/* OBJ_id_pkix                      1 3 6 1 5 5 7 */
-505,	/* OBJ_mime_mhs_headings            1 3 6 1 7 1 1 */
-506,	/* OBJ_mime_mhs_bodies              1 3 6 1 7 1 2 */
-119,	/* OBJ_ripemd160WithRSA             1 3 36 3 3 1 2 */
-937,	/* OBJ_dhSinglePass_stdDH_sha224kdf_scheme 1 3 132 1 11 0 */
-938,	/* OBJ_dhSinglePass_stdDH_sha256kdf_scheme 1 3 132 1 11 1 */
-939,	/* OBJ_dhSinglePass_stdDH_sha384kdf_scheme 1 3 132 1 11 2 */
-940,	/* OBJ_dhSinglePass_stdDH_sha512kdf_scheme 1 3 132 1 11 3 */
-942,	/* OBJ_dhSinglePass_cofactorDH_sha224kdf_scheme 1 3 132 1 14 0 */
-943,	/* OBJ_dhSinglePass_cofactorDH_sha256kdf_scheme 1 3 132 1 14 1 */
-944,	/* OBJ_dhSinglePass_cofactorDH_sha384kdf_scheme 1 3 132 1 14 2 */
-945,	/* OBJ_dhSinglePass_cofactorDH_sha512kdf_scheme 1 3 132 1 14 3 */
-631,	/* OBJ_setAttr_GenCryptgrm          2 23 42 3 3 3 1 */
-632,	/* OBJ_setAttr_T2Enc                2 23 42 3 3 4 1 */
-633,	/* OBJ_setAttr_T2cleartxt           2 23 42 3 3 4 2 */
-634,	/* OBJ_setAttr_TokICCsig            2 23 42 3 3 5 1 */
-635,	/* OBJ_setAttr_SecDevSig            2 23 42 3 3 5 2 */
-436,	/* OBJ_ucl                          0 9 2342 19200300 */
-820,	/* OBJ_id_Gost28147_89_None_KeyMeshing 1 2 643 2 2 14 0 */
-819,	/* OBJ_id_Gost28147_89_CryptoPro_KeyMeshing 1 2 643 2 2 14 1 */
-845,	/* OBJ_id_GostR3410_94_a            1 2 643 2 2 20 1 */
-846,	/* OBJ_id_GostR3410_94_aBis         1 2 643 2 2 20 2 */
-847,	/* OBJ_id_GostR3410_94_b            1 2 643 2 2 20 3 */
-848,	/* OBJ_id_GostR3410_94_bBis         1 2 643 2 2 20 4 */
-821,	/* OBJ_id_GostR3411_94_TestParamSet 1 2 643 2 2 30 0 */
-822,	/* OBJ_id_GostR3411_94_CryptoProParamSet 1 2 643 2 2 30 1 */
-823,	/* OBJ_id_Gost28147_89_TestParamSet 1 2 643 2 2 31 0 */
-824,	/* OBJ_id_Gost28147_89_CryptoPro_A_ParamSet 1 2 643 2 2 31 1 */
-825,	/* OBJ_id_Gost28147_89_CryptoPro_B_ParamSet 1 2 643 2 2 31 2 */
-826,	/* OBJ_id_Gost28147_89_CryptoPro_C_ParamSet 1 2 643 2 2 31 3 */
-827,	/* OBJ_id_Gost28147_89_CryptoPro_D_ParamSet 1 2 643 2 2 31 4 */
-828,	/* OBJ_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet 1 2 643 2 2 31 5 */
-829,	/* OBJ_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet 1 2 643 2 2 31 6 */
-830,	/* OBJ_id_Gost28147_89_CryptoPro_RIC_1_ParamSet 1 2 643 2 2 31 7 */
-831,	/* OBJ_id_GostR3410_94_TestParamSet 1 2 643 2 2 32 0 */
-832,	/* OBJ_id_GostR3410_94_CryptoPro_A_ParamSet 1 2 643 2 2 32 2 */
-833,	/* OBJ_id_GostR3410_94_CryptoPro_B_ParamSet 1 2 643 2 2 32 3 */
-834,	/* OBJ_id_GostR3410_94_CryptoPro_C_ParamSet 1 2 643 2 2 32 4 */
-835,	/* OBJ_id_GostR3410_94_CryptoPro_D_ParamSet 1 2 643 2 2 32 5 */
-836,	/* OBJ_id_GostR3410_94_CryptoPro_XchA_ParamSet 1 2 643 2 2 33 1 */
-837,	/* OBJ_id_GostR3410_94_CryptoPro_XchB_ParamSet 1 2 643 2 2 33 2 */
-838,	/* OBJ_id_GostR3410_94_CryptoPro_XchC_ParamSet 1 2 643 2 2 33 3 */
-839,	/* OBJ_id_GostR3410_2001_TestParamSet 1 2 643 2 2 35 0 */
-840,	/* OBJ_id_GostR3410_2001_CryptoPro_A_ParamSet 1 2 643 2 2 35 1 */
-841,	/* OBJ_id_GostR3410_2001_CryptoPro_B_ParamSet 1 2 643 2 2 35 2 */
-842,	/* OBJ_id_GostR3410_2001_CryptoPro_C_ParamSet 1 2 643 2 2 35 3 */
-843,	/* OBJ_id_GostR3410_2001_CryptoPro_XchA_ParamSet 1 2 643 2 2 36 0 */
-844,	/* OBJ_id_GostR3410_2001_CryptoPro_XchB_ParamSet 1 2 643 2 2 36 1 */
- 2,	/* OBJ_pkcs                         1 2 840 113549 1 */
-431,	/* OBJ_hold_instruction_none        1 2 840 10040 2 1 */
-432,	/* OBJ_hold_instruction_call_issuer 1 2 840 10040 2 2 */
-433,	/* OBJ_hold_instruction_reject      1 2 840 10040 2 3 */
-116,	/* OBJ_dsa                          1 2 840 10040 4 1 */
-113,	/* OBJ_dsaWithSHA1                  1 2 840 10040 4 3 */
-406,	/* OBJ_X9_62_prime_field            1 2 840 10045 1 1 */
-407,	/* OBJ_X9_62_characteristic_two_field 1 2 840 10045 1 2 */
-408,	/* OBJ_X9_62_id_ecPublicKey         1 2 840 10045 2 1 */
-416,	/* OBJ_ecdsa_with_SHA1              1 2 840 10045 4 1 */
-791,	/* OBJ_ecdsa_with_Recommended       1 2 840 10045 4 2 */
-792,	/* OBJ_ecdsa_with_Specified         1 2 840 10045 4 3 */
-920,	/* OBJ_dhpublicnumber               1 2 840 10046 2 1 */
-258,	/* OBJ_id_pkix_mod                  1 3 6 1 5 5 7 0 */
-175,	/* OBJ_id_pe                        1 3 6 1 5 5 7 1 */
-259,	/* OBJ_id_qt                        1 3 6 1 5 5 7 2 */
-128,	/* OBJ_id_kp                        1 3 6 1 5 5 7 3 */
-260,	/* OBJ_id_it                        1 3 6 1 5 5 7 4 */
-261,	/* OBJ_id_pkip                      1 3 6 1 5 5 7 5 */
-262,	/* OBJ_id_alg                       1 3 6 1 5 5 7 6 */
-263,	/* OBJ_id_cmc                       1 3 6 1 5 5 7 7 */
-264,	/* OBJ_id_on                        1 3 6 1 5 5 7 8 */
-265,	/* OBJ_id_pda                       1 3 6 1 5 5 7 9 */
-266,	/* OBJ_id_aca                       1 3 6 1 5 5 7 10 */
-267,	/* OBJ_id_qcs                       1 3 6 1 5 5 7 11 */
-268,	/* OBJ_id_cct                       1 3 6 1 5 5 7 12 */
-662,	/* OBJ_id_ppl                       1 3 6 1 5 5 7 21 */
-176,	/* OBJ_id_ad                        1 3 6 1 5 5 7 48 */
-507,	/* OBJ_id_hex_partial_message       1 3 6 1 7 1 1 1 */
-508,	/* OBJ_id_hex_multipart_message     1 3 6 1 7 1 1 2 */
-57,	/* OBJ_netscape                     2 16 840 1 113730 */
-754,	/* OBJ_camellia_128_ecb             0 3 4401 5 3 1 9 1 */
-766,	/* OBJ_camellia_128_ofb128          0 3 4401 5 3 1 9 3 */
-757,	/* OBJ_camellia_128_cfb128          0 3 4401 5 3 1 9 4 */
-755,	/* OBJ_camellia_192_ecb             0 3 4401 5 3 1 9 21 */
-767,	/* OBJ_camellia_192_ofb128          0 3 4401 5 3 1 9 23 */
-758,	/* OBJ_camellia_192_cfb128          0 3 4401 5 3 1 9 24 */
-756,	/* OBJ_camellia_256_ecb             0 3 4401 5 3 1 9 41 */
-768,	/* OBJ_camellia_256_ofb128          0 3 4401 5 3 1 9 43 */
-759,	/* OBJ_camellia_256_cfb128          0 3 4401 5 3 1 9 44 */
-437,	/* OBJ_pilot                        0 9 2342 19200300 100 */
-776,	/* OBJ_seed_ecb                     1 2 410 200004 1 3 */
-777,	/* OBJ_seed_cbc                     1 2 410 200004 1 4 */
-779,	/* OBJ_seed_cfb128                  1 2 410 200004 1 5 */
-778,	/* OBJ_seed_ofb128                  1 2 410 200004 1 6 */
-852,	/* OBJ_id_GostR3411_94_with_GostR3410_94_cc 1 2 643 2 9 1 3 3 */
-853,	/* OBJ_id_GostR3411_94_with_GostR3410_2001_cc 1 2 643 2 9 1 3 4 */
-850,	/* OBJ_id_GostR3410_94_cc           1 2 643 2 9 1 5 3 */
-851,	/* OBJ_id_GostR3410_2001_cc         1 2 643 2 9 1 5 4 */
-849,	/* OBJ_id_Gost28147_89_cc           1 2 643 2 9 1 6 1 */
-854,	/* OBJ_id_GostR3410_2001_ParamSet_cc 1 2 643 2 9 1 8 1 */
-186,	/* OBJ_pkcs1                        1 2 840 113549 1 1 */
-27,	/* OBJ_pkcs3                        1 2 840 113549 1 3 */
-187,	/* OBJ_pkcs5                        1 2 840 113549 1 5 */
-20,	/* OBJ_pkcs7                        1 2 840 113549 1 7 */
-47,	/* OBJ_pkcs9                        1 2 840 113549 1 9 */
- 3,	/* OBJ_md2                          1 2 840 113549 2 2 */
-257,	/* OBJ_md4                          1 2 840 113549 2 4 */
- 4,	/* OBJ_md5                          1 2 840 113549 2 5 */
-797,	/* OBJ_hmacWithMD5                  1 2 840 113549 2 6 */
-163,	/* OBJ_hmacWithSHA1                 1 2 840 113549 2 7 */
-798,	/* OBJ_hmacWithSHA224               1 2 840 113549 2 8 */
-799,	/* OBJ_hmacWithSHA256               1 2 840 113549 2 9 */
-800,	/* OBJ_hmacWithSHA384               1 2 840 113549 2 10 */
-801,	/* OBJ_hmacWithSHA512               1 2 840 113549 2 11 */
-37,	/* OBJ_rc2_cbc                      1 2 840 113549 3 2 */
- 5,	/* OBJ_rc4                          1 2 840 113549 3 4 */
-44,	/* OBJ_des_ede3_cbc                 1 2 840 113549 3 7 */
-120,	/* OBJ_rc5_cbc                      1 2 840 113549 3 8 */
-643,	/* OBJ_des_cdmf                     1 2 840 113549 3 10 */
-680,	/* OBJ_X9_62_id_characteristic_two_basis 1 2 840 10045 1 2 3 */
-684,	/* OBJ_X9_62_c2pnb163v1             1 2 840 10045 3 0 1 */
-685,	/* OBJ_X9_62_c2pnb163v2             1 2 840 10045 3 0 2 */
-686,	/* OBJ_X9_62_c2pnb163v3             1 2 840 10045 3 0 3 */
-687,	/* OBJ_X9_62_c2pnb176v1             1 2 840 10045 3 0 4 */
-688,	/* OBJ_X9_62_c2tnb191v1             1 2 840 10045 3 0 5 */
-689,	/* OBJ_X9_62_c2tnb191v2             1 2 840 10045 3 0 6 */
-690,	/* OBJ_X9_62_c2tnb191v3             1 2 840 10045 3 0 7 */
-691,	/* OBJ_X9_62_c2onb191v4             1 2 840 10045 3 0 8 */
-692,	/* OBJ_X9_62_c2onb191v5             1 2 840 10045 3 0 9 */
-693,	/* OBJ_X9_62_c2pnb208w1             1 2 840 10045 3 0 10 */
-694,	/* OBJ_X9_62_c2tnb239v1             1 2 840 10045 3 0 11 */
-695,	/* OBJ_X9_62_c2tnb239v2             1 2 840 10045 3 0 12 */
-696,	/* OBJ_X9_62_c2tnb239v3             1 2 840 10045 3 0 13 */
-697,	/* OBJ_X9_62_c2onb239v4             1 2 840 10045 3 0 14 */
-698,	/* OBJ_X9_62_c2onb239v5             1 2 840 10045 3 0 15 */
-699,	/* OBJ_X9_62_c2pnb272w1             1 2 840 10045 3 0 16 */
-700,	/* OBJ_X9_62_c2pnb304w1             1 2 840 10045 3 0 17 */
-701,	/* OBJ_X9_62_c2tnb359v1             1 2 840 10045 3 0 18 */
-702,	/* OBJ_X9_62_c2pnb368w1             1 2 840 10045 3 0 19 */
-703,	/* OBJ_X9_62_c2tnb431r1             1 2 840 10045 3 0 20 */
-409,	/* OBJ_X9_62_prime192v1             1 2 840 10045 3 1 1 */
-410,	/* OBJ_X9_62_prime192v2             1 2 840 10045 3 1 2 */
-411,	/* OBJ_X9_62_prime192v3             1 2 840 10045 3 1 3 */
-412,	/* OBJ_X9_62_prime239v1             1 2 840 10045 3 1 4 */
-413,	/* OBJ_X9_62_prime239v2             1 2 840 10045 3 1 5 */
-414,	/* OBJ_X9_62_prime239v3             1 2 840 10045 3 1 6 */
-415,	/* OBJ_X9_62_prime256v1             1 2 840 10045 3 1 7 */
-793,	/* OBJ_ecdsa_with_SHA224            1 2 840 10045 4 3 1 */
-794,	/* OBJ_ecdsa_with_SHA256            1 2 840 10045 4 3 2 */
-795,	/* OBJ_ecdsa_with_SHA384            1 2 840 10045 4 3 3 */
-796,	/* OBJ_ecdsa_with_SHA512            1 2 840 10045 4 3 4 */
-269,	/* OBJ_id_pkix1_explicit_88         1 3 6 1 5 5 7 0 1 */
-270,	/* OBJ_id_pkix1_implicit_88         1 3 6 1 5 5 7 0 2 */
-271,	/* OBJ_id_pkix1_explicit_93         1 3 6 1 5 5 7 0 3 */
-272,	/* OBJ_id_pkix1_implicit_93         1 3 6 1 5 5 7 0 4 */
-273,	/* OBJ_id_mod_crmf                  1 3 6 1 5 5 7 0 5 */
-274,	/* OBJ_id_mod_cmc                   1 3 6 1 5 5 7 0 6 */
-275,	/* OBJ_id_mod_kea_profile_88        1 3 6 1 5 5 7 0 7 */
-276,	/* OBJ_id_mod_kea_profile_93        1 3 6 1 5 5 7 0 8 */
-277,	/* OBJ_id_mod_cmp                   1 3 6 1 5 5 7 0 9 */
-278,	/* OBJ_id_mod_qualified_cert_88     1 3 6 1 5 5 7 0 10 */
-279,	/* OBJ_id_mod_qualified_cert_93     1 3 6 1 5 5 7 0 11 */
-280,	/* OBJ_id_mod_attribute_cert        1 3 6 1 5 5 7 0 12 */
-281,	/* OBJ_id_mod_timestamp_protocol    1 3 6 1 5 5 7 0 13 */
-282,	/* OBJ_id_mod_ocsp                  1 3 6 1 5 5 7 0 14 */
-283,	/* OBJ_id_mod_dvcs                  1 3 6 1 5 5 7 0 15 */
-284,	/* OBJ_id_mod_cmp2000               1 3 6 1 5 5 7 0 16 */
-177,	/* OBJ_info_access                  1 3 6 1 5 5 7 1 1 */
-285,	/* OBJ_biometricInfo                1 3 6 1 5 5 7 1 2 */
-286,	/* OBJ_qcStatements                 1 3 6 1 5 5 7 1 3 */
-287,	/* OBJ_ac_auditEntity               1 3 6 1 5 5 7 1 4 */
-288,	/* OBJ_ac_targeting                 1 3 6 1 5 5 7 1 5 */
-289,	/* OBJ_aaControls                   1 3 6 1 5 5 7 1 6 */
-290,	/* OBJ_sbgp_ipAddrBlock             1 3 6 1 5 5 7 1 7 */
-291,	/* OBJ_sbgp_autonomousSysNum        1 3 6 1 5 5 7 1 8 */
-292,	/* OBJ_sbgp_routerIdentifier        1 3 6 1 5 5 7 1 9 */
-397,	/* OBJ_ac_proxying                  1 3 6 1 5 5 7 1 10 */
-398,	/* OBJ_sinfo_access                 1 3 6 1 5 5 7 1 11 */
-663,	/* OBJ_proxyCertInfo                1 3 6 1 5 5 7 1 14 */
-164,	/* OBJ_id_qt_cps                    1 3 6 1 5 5 7 2 1 */
-165,	/* OBJ_id_qt_unotice                1 3 6 1 5 5 7 2 2 */
-293,	/* OBJ_textNotice                   1 3 6 1 5 5 7 2 3 */
-129,	/* OBJ_server_auth                  1 3 6 1 5 5 7 3 1 */
-130,	/* OBJ_client_auth                  1 3 6 1 5 5 7 3 2 */
-131,	/* OBJ_code_sign                    1 3 6 1 5 5 7 3 3 */
-132,	/* OBJ_email_protect                1 3 6 1 5 5 7 3 4 */
-294,	/* OBJ_ipsecEndSystem               1 3 6 1 5 5 7 3 5 */
-295,	/* OBJ_ipsecTunnel                  1 3 6 1 5 5 7 3 6 */
-296,	/* OBJ_ipsecUser                    1 3 6 1 5 5 7 3 7 */
-133,	/* OBJ_time_stamp                   1 3 6 1 5 5 7 3 8 */
-180,	/* OBJ_OCSP_sign                    1 3 6 1 5 5 7 3 9 */
-297,	/* OBJ_dvcs                         1 3 6 1 5 5 7 3 10 */
-298,	/* OBJ_id_it_caProtEncCert          1 3 6 1 5 5 7 4 1 */
-299,	/* OBJ_id_it_signKeyPairTypes       1 3 6 1 5 5 7 4 2 */
-300,	/* OBJ_id_it_encKeyPairTypes        1 3 6 1 5 5 7 4 3 */
-301,	/* OBJ_id_it_preferredSymmAlg       1 3 6 1 5 5 7 4 4 */
-302,	/* OBJ_id_it_caKeyUpdateInfo        1 3 6 1 5 5 7 4 5 */
-303,	/* OBJ_id_it_currentCRL             1 3 6 1 5 5 7 4 6 */
-304,	/* OBJ_id_it_unsupportedOIDs        1 3 6 1 5 5 7 4 7 */
-305,	/* OBJ_id_it_subscriptionRequest    1 3 6 1 5 5 7 4 8 */
-306,	/* OBJ_id_it_subscriptionResponse   1 3 6 1 5 5 7 4 9 */
-307,	/* OBJ_id_it_keyPairParamReq        1 3 6 1 5 5 7 4 10 */
-308,	/* OBJ_id_it_keyPairParamRep        1 3 6 1 5 5 7 4 11 */
-309,	/* OBJ_id_it_revPassphrase          1 3 6 1 5 5 7 4 12 */
-310,	/* OBJ_id_it_implicitConfirm        1 3 6 1 5 5 7 4 13 */
-311,	/* OBJ_id_it_confirmWaitTime        1 3 6 1 5 5 7 4 14 */
-312,	/* OBJ_id_it_origPKIMessage         1 3 6 1 5 5 7 4 15 */
-784,	/* OBJ_id_it_suppLangTags           1 3 6 1 5 5 7 4 16 */
-313,	/* OBJ_id_regCtrl                   1 3 6 1 5 5 7 5 1 */
-314,	/* OBJ_id_regInfo                   1 3 6 1 5 5 7 5 2 */
-323,	/* OBJ_id_alg_des40                 1 3 6 1 5 5 7 6 1 */
-324,	/* OBJ_id_alg_noSignature           1 3 6 1 5 5 7 6 2 */
-325,	/* OBJ_id_alg_dh_sig_hmac_sha1      1 3 6 1 5 5 7 6 3 */
-326,	/* OBJ_id_alg_dh_pop                1 3 6 1 5 5 7 6 4 */
-327,	/* OBJ_id_cmc_statusInfo            1 3 6 1 5 5 7 7 1 */
-328,	/* OBJ_id_cmc_identification        1 3 6 1 5 5 7 7 2 */
-329,	/* OBJ_id_cmc_identityProof         1 3 6 1 5 5 7 7 3 */
-330,	/* OBJ_id_cmc_dataReturn            1 3 6 1 5 5 7 7 4 */
-331,	/* OBJ_id_cmc_transactionId         1 3 6 1 5 5 7 7 5 */
-332,	/* OBJ_id_cmc_senderNonce           1 3 6 1 5 5 7 7 6 */
-333,	/* OBJ_id_cmc_recipientNonce        1 3 6 1 5 5 7 7 7 */
-334,	/* OBJ_id_cmc_addExtensions         1 3 6 1 5 5 7 7 8 */
-335,	/* OBJ_id_cmc_encryptedPOP          1 3 6 1 5 5 7 7 9 */
-336,	/* OBJ_id_cmc_decryptedPOP          1 3 6 1 5 5 7 7 10 */
-337,	/* OBJ_id_cmc_lraPOPWitness         1 3 6 1 5 5 7 7 11 */
-338,	/* OBJ_id_cmc_getCert               1 3 6 1 5 5 7 7 15 */
-339,	/* OBJ_id_cmc_getCRL                1 3 6 1 5 5 7 7 16 */
-340,	/* OBJ_id_cmc_revokeRequest         1 3 6 1 5 5 7 7 17 */
-341,	/* OBJ_id_cmc_regInfo               1 3 6 1 5 5 7 7 18 */
-342,	/* OBJ_id_cmc_responseInfo          1 3 6 1 5 5 7 7 19 */
-343,	/* OBJ_id_cmc_queryPending          1 3 6 1 5 5 7 7 21 */
-344,	/* OBJ_id_cmc_popLinkRandom         1 3 6 1 5 5 7 7 22 */
-345,	/* OBJ_id_cmc_popLinkWitness        1 3 6 1 5 5 7 7 23 */
-346,	/* OBJ_id_cmc_confirmCertAcceptance 1 3 6 1 5 5 7 7 24 */
-347,	/* OBJ_id_on_personalData           1 3 6 1 5 5 7 8 1 */
-858,	/* OBJ_id_on_permanentIdentifier    1 3 6 1 5 5 7 8 3 */
-348,	/* OBJ_id_pda_dateOfBirth           1 3 6 1 5 5 7 9 1 */
-349,	/* OBJ_id_pda_placeOfBirth          1 3 6 1 5 5 7 9 2 */
-351,	/* OBJ_id_pda_gender                1 3 6 1 5 5 7 9 3 */
-352,	/* OBJ_id_pda_countryOfCitizenship  1 3 6 1 5 5 7 9 4 */
-353,	/* OBJ_id_pda_countryOfResidence    1 3 6 1 5 5 7 9 5 */
-354,	/* OBJ_id_aca_authenticationInfo    1 3 6 1 5 5 7 10 1 */
-355,	/* OBJ_id_aca_accessIdentity        1 3 6 1 5 5 7 10 2 */
-356,	/* OBJ_id_aca_chargingIdentity      1 3 6 1 5 5 7 10 3 */
-357,	/* OBJ_id_aca_group                 1 3 6 1 5 5 7 10 4 */
-358,	/* OBJ_id_aca_role                  1 3 6 1 5 5 7 10 5 */
-399,	/* OBJ_id_aca_encAttrs              1 3 6 1 5 5 7 10 6 */
-359,	/* OBJ_id_qcs_pkixQCSyntax_v1       1 3 6 1 5 5 7 11 1 */
-360,	/* OBJ_id_cct_crs                   1 3 6 1 5 5 7 12 1 */
-361,	/* OBJ_id_cct_PKIData               1 3 6 1 5 5 7 12 2 */
-362,	/* OBJ_id_cct_PKIResponse           1 3 6 1 5 5 7 12 3 */
-664,	/* OBJ_id_ppl_anyLanguage           1 3 6 1 5 5 7 21 0 */
-665,	/* OBJ_id_ppl_inheritAll            1 3 6 1 5 5 7 21 1 */
-667,	/* OBJ_Independent                  1 3 6 1 5 5 7 21 2 */
-178,	/* OBJ_ad_OCSP                      1 3 6 1 5 5 7 48 1 */
-179,	/* OBJ_ad_ca_issuers                1 3 6 1 5 5 7 48 2 */
-363,	/* OBJ_ad_timeStamping              1 3 6 1 5 5 7 48 3 */
-364,	/* OBJ_ad_dvcs                      1 3 6 1 5 5 7 48 4 */
-785,	/* OBJ_caRepository                 1 3 6 1 5 5 7 48 5 */
-780,	/* OBJ_hmac_md5                     1 3 6 1 5 5 8 1 1 */
-781,	/* OBJ_hmac_sha1                    1 3 6 1 5 5 8 1 2 */
-58,	/* OBJ_netscape_cert_extension      2 16 840 1 113730 1 */
-59,	/* OBJ_netscape_data_type           2 16 840 1 113730 2 */
-438,	/* OBJ_pilotAttributeType           0 9 2342 19200300 100 1 */
-439,	/* OBJ_pilotAttributeSyntax         0 9 2342 19200300 100 3 */
-440,	/* OBJ_pilotObjectClass             0 9 2342 19200300 100 4 */
-441,	/* OBJ_pilotGroups                  0 9 2342 19200300 100 10 */
-108,	/* OBJ_cast5_cbc                    1 2 840 113533 7 66 10 */
-112,	/* OBJ_pbeWithMD5AndCast5_CBC       1 2 840 113533 7 66 12 */
-782,	/* OBJ_id_PasswordBasedMAC          1 2 840 113533 7 66 13 */
-783,	/* OBJ_id_DHBasedMac                1 2 840 113533 7 66 30 */
- 6,	/* OBJ_rsaEncryption                1 2 840 113549 1 1 1 */
- 7,	/* OBJ_md2WithRSAEncryption         1 2 840 113549 1 1 2 */
-396,	/* OBJ_md4WithRSAEncryption         1 2 840 113549 1 1 3 */
- 8,	/* OBJ_md5WithRSAEncryption         1 2 840 113549 1 1 4 */
-65,	/* OBJ_sha1WithRSAEncryption        1 2 840 113549 1 1 5 */
-644,	/* OBJ_rsaOAEPEncryptionSET         1 2 840 113549 1 1 6 */
-919,	/* OBJ_rsaesOaep                    1 2 840 113549 1 1 7 */
-911,	/* OBJ_mgf1                         1 2 840 113549 1 1 8 */
-935,	/* OBJ_pSpecified                   1 2 840 113549 1 1 9 */
-912,	/* OBJ_rsassaPss                    1 2 840 113549 1 1 10 */
-668,	/* OBJ_sha256WithRSAEncryption      1 2 840 113549 1 1 11 */
-669,	/* OBJ_sha384WithRSAEncryption      1 2 840 113549 1 1 12 */
-670,	/* OBJ_sha512WithRSAEncryption      1 2 840 113549 1 1 13 */
-671,	/* OBJ_sha224WithRSAEncryption      1 2 840 113549 1 1 14 */
-28,	/* OBJ_dhKeyAgreement               1 2 840 113549 1 3 1 */
- 9,	/* OBJ_pbeWithMD2AndDES_CBC         1 2 840 113549 1 5 1 */
-10,	/* OBJ_pbeWithMD5AndDES_CBC         1 2 840 113549 1 5 3 */
-168,	/* OBJ_pbeWithMD2AndRC2_CBC         1 2 840 113549 1 5 4 */
-169,	/* OBJ_pbeWithMD5AndRC2_CBC         1 2 840 113549 1 5 6 */
-170,	/* OBJ_pbeWithSHA1AndDES_CBC        1 2 840 113549 1 5 10 */
-68,	/* OBJ_pbeWithSHA1AndRC2_CBC        1 2 840 113549 1 5 11 */
-69,	/* OBJ_id_pbkdf2                    1 2 840 113549 1 5 12 */
-161,	/* OBJ_pbes2                        1 2 840 113549 1 5 13 */
-162,	/* OBJ_pbmac1                       1 2 840 113549 1 5 14 */
-21,	/* OBJ_pkcs7_data                   1 2 840 113549 1 7 1 */
-22,	/* OBJ_pkcs7_signed                 1 2 840 113549 1 7 2 */
-23,	/* OBJ_pkcs7_enveloped              1 2 840 113549 1 7 3 */
-24,	/* OBJ_pkcs7_signedAndEnveloped     1 2 840 113549 1 7 4 */
-25,	/* OBJ_pkcs7_digest                 1 2 840 113549 1 7 5 */
-26,	/* OBJ_pkcs7_encrypted              1 2 840 113549 1 7 6 */
-48,	/* OBJ_pkcs9_emailAddress           1 2 840 113549 1 9 1 */
-49,	/* OBJ_pkcs9_unstructuredName       1 2 840 113549 1 9 2 */
-50,	/* OBJ_pkcs9_contentType            1 2 840 113549 1 9 3 */
-51,	/* OBJ_pkcs9_messageDigest          1 2 840 113549 1 9 4 */
-52,	/* OBJ_pkcs9_signingTime            1 2 840 113549 1 9 5 */
-53,	/* OBJ_pkcs9_countersignature       1 2 840 113549 1 9 6 */
-54,	/* OBJ_pkcs9_challengePassword      1 2 840 113549 1 9 7 */
-55,	/* OBJ_pkcs9_unstructuredAddress    1 2 840 113549 1 9 8 */
-56,	/* OBJ_pkcs9_extCertAttributes      1 2 840 113549 1 9 9 */
-172,	/* OBJ_ext_req                      1 2 840 113549 1 9 14 */
-167,	/* OBJ_SMIMECapabilities            1 2 840 113549 1 9 15 */
-188,	/* OBJ_SMIME                        1 2 840 113549 1 9 16 */
-156,	/* OBJ_friendlyName                 1 2 840 113549 1 9 20 */
-157,	/* OBJ_localKeyID                   1 2 840 113549 1 9 21 */
-681,	/* OBJ_X9_62_onBasis                1 2 840 10045 1 2 3 1 */
-682,	/* OBJ_X9_62_tpBasis                1 2 840 10045 1 2 3 2 */
-683,	/* OBJ_X9_62_ppBasis                1 2 840 10045 1 2 3 3 */
-417,	/* OBJ_ms_csp_name                  1 3 6 1 4 1 311 17 1 */
-856,	/* OBJ_LocalKeySet                  1 3 6 1 4 1 311 17 2 */
-390,	/* OBJ_dcObject                     1 3 6 1 4 1 1466 344 */
-91,	/* OBJ_bf_cbc                       1 3 6 1 4 1 3029 1 2 */
-315,	/* OBJ_id_regCtrl_regToken          1 3 6 1 5 5 7 5 1 1 */
-316,	/* OBJ_id_regCtrl_authenticator     1 3 6 1 5 5 7 5 1 2 */
-317,	/* OBJ_id_regCtrl_pkiPublicationInfo 1 3 6 1 5 5 7 5 1 3 */
-318,	/* OBJ_id_regCtrl_pkiArchiveOptions 1 3 6 1 5 5 7 5 1 4 */
-319,	/* OBJ_id_regCtrl_oldCertID         1 3 6 1 5 5 7 5 1 5 */
-320,	/* OBJ_id_regCtrl_protocolEncrKey   1 3 6 1 5 5 7 5 1 6 */
-321,	/* OBJ_id_regInfo_utf8Pairs         1 3 6 1 5 5 7 5 2 1 */
-322,	/* OBJ_id_regInfo_certReq           1 3 6 1 5 5 7 5 2 2 */
-365,	/* OBJ_id_pkix_OCSP_basic           1 3 6 1 5 5 7 48 1 1 */
-366,	/* OBJ_id_pkix_OCSP_Nonce           1 3 6 1 5 5 7 48 1 2 */
-367,	/* OBJ_id_pkix_OCSP_CrlID           1 3 6 1 5 5 7 48 1 3 */
-368,	/* OBJ_id_pkix_OCSP_acceptableResponses 1 3 6 1 5 5 7 48 1 4 */
-369,	/* OBJ_id_pkix_OCSP_noCheck         1 3 6 1 5 5 7 48 1 5 */
-370,	/* OBJ_id_pkix_OCSP_archiveCutoff   1 3 6 1 5 5 7 48 1 6 */
-371,	/* OBJ_id_pkix_OCSP_serviceLocator  1 3 6 1 5 5 7 48 1 7 */
-372,	/* OBJ_id_pkix_OCSP_extendedStatus  1 3 6 1 5 5 7 48 1 8 */
-373,	/* OBJ_id_pkix_OCSP_valid           1 3 6 1 5 5 7 48 1 9 */
-374,	/* OBJ_id_pkix_OCSP_path            1 3 6 1 5 5 7 48 1 10 */
-375,	/* OBJ_id_pkix_OCSP_trustRoot       1 3 6 1 5 5 7 48 1 11 */
-921,	/* OBJ_brainpoolP160r1              1 3 36 3 3 2 8 1 1 1 */
-922,	/* OBJ_brainpoolP160t1              1 3 36 3 3 2 8 1 1 2 */
-923,	/* OBJ_brainpoolP192r1              1 3 36 3 3 2 8 1 1 3 */
-924,	/* OBJ_brainpoolP192t1              1 3 36 3 3 2 8 1 1 4 */
-925,	/* OBJ_brainpoolP224r1              1 3 36 3 3 2 8 1 1 5 */
-926,	/* OBJ_brainpoolP224t1              1 3 36 3 3 2 8 1 1 6 */
-927,	/* OBJ_brainpoolP256r1              1 3 36 3 3 2 8 1 1 7 */
-928,	/* OBJ_brainpoolP256t1              1 3 36 3 3 2 8 1 1 8 */
-929,	/* OBJ_brainpoolP320r1              1 3 36 3 3 2 8 1 1 9 */
-930,	/* OBJ_brainpoolP320t1              1 3 36 3 3 2 8 1 1 10 */
-931,	/* OBJ_brainpoolP384r1              1 3 36 3 3 2 8 1 1 11 */
-932,	/* OBJ_brainpoolP384t1              1 3 36 3 3 2 8 1 1 12 */
-933,	/* OBJ_brainpoolP512r1              1 3 36 3 3 2 8 1 1 13 */
-934,	/* OBJ_brainpoolP512t1              1 3 36 3 3 2 8 1 1 14 */
-936,	/* OBJ_dhSinglePass_stdDH_sha1kdf_scheme 1 3 133 16 840 63 0 2 */
-941,	/* OBJ_dhSinglePass_cofactorDH_sha1kdf_scheme 1 3 133 16 840 63 0 3 */
-418,	/* OBJ_aes_128_ecb                  2 16 840 1 101 3 4 1 1 */
-419,	/* OBJ_aes_128_cbc                  2 16 840 1 101 3 4 1 2 */
-420,	/* OBJ_aes_128_ofb128               2 16 840 1 101 3 4 1 3 */
-421,	/* OBJ_aes_128_cfb128               2 16 840 1 101 3 4 1 4 */
-788,	/* OBJ_id_aes128_wrap               2 16 840 1 101 3 4 1 5 */
-895,	/* OBJ_aes_128_gcm                  2 16 840 1 101 3 4 1 6 */
-896,	/* OBJ_aes_128_ccm                  2 16 840 1 101 3 4 1 7 */
-897,	/* OBJ_id_aes128_wrap_pad           2 16 840 1 101 3 4 1 8 */
-422,	/* OBJ_aes_192_ecb                  2 16 840 1 101 3 4 1 21 */
-423,	/* OBJ_aes_192_cbc                  2 16 840 1 101 3 4 1 22 */
-424,	/* OBJ_aes_192_ofb128               2 16 840 1 101 3 4 1 23 */
-425,	/* OBJ_aes_192_cfb128               2 16 840 1 101 3 4 1 24 */
-789,	/* OBJ_id_aes192_wrap               2 16 840 1 101 3 4 1 25 */
-898,	/* OBJ_aes_192_gcm                  2 16 840 1 101 3 4 1 26 */
-899,	/* OBJ_aes_192_ccm                  2 16 840 1 101 3 4 1 27 */
-900,	/* OBJ_id_aes192_wrap_pad           2 16 840 1 101 3 4 1 28 */
-426,	/* OBJ_aes_256_ecb                  2 16 840 1 101 3 4 1 41 */
-427,	/* OBJ_aes_256_cbc                  2 16 840 1 101 3 4 1 42 */
-428,	/* OBJ_aes_256_ofb128               2 16 840 1 101 3 4 1 43 */
-429,	/* OBJ_aes_256_cfb128               2 16 840 1 101 3 4 1 44 */
-790,	/* OBJ_id_aes256_wrap               2 16 840 1 101 3 4 1 45 */
-901,	/* OBJ_aes_256_gcm                  2 16 840 1 101 3 4 1 46 */
-902,	/* OBJ_aes_256_ccm                  2 16 840 1 101 3 4 1 47 */
-903,	/* OBJ_id_aes256_wrap_pad           2 16 840 1 101 3 4 1 48 */
-672,	/* OBJ_sha256                       2 16 840 1 101 3 4 2 1 */
-673,	/* OBJ_sha384                       2 16 840 1 101 3 4 2 2 */
-674,	/* OBJ_sha512                       2 16 840 1 101 3 4 2 3 */
-675,	/* OBJ_sha224                       2 16 840 1 101 3 4 2 4 */
-802,	/* OBJ_dsa_with_SHA224              2 16 840 1 101 3 4 3 1 */
-803,	/* OBJ_dsa_with_SHA256              2 16 840 1 101 3 4 3 2 */
-71,	/* OBJ_netscape_cert_type           2 16 840 1 113730 1 1 */
-72,	/* OBJ_netscape_base_url            2 16 840 1 113730 1 2 */
-73,	/* OBJ_netscape_revocation_url      2 16 840 1 113730 1 3 */
-74,	/* OBJ_netscape_ca_revocation_url   2 16 840 1 113730 1 4 */
-75,	/* OBJ_netscape_renewal_url         2 16 840 1 113730 1 7 */
-76,	/* OBJ_netscape_ca_policy_url       2 16 840 1 113730 1 8 */
-77,	/* OBJ_netscape_ssl_server_name     2 16 840 1 113730 1 12 */
-78,	/* OBJ_netscape_comment             2 16 840 1 113730 1 13 */
-79,	/* OBJ_netscape_cert_sequence       2 16 840 1 113730 2 5 */
-139,	/* OBJ_ns_sgc                       2 16 840 1 113730 4 1 */
-458,	/* OBJ_userId                       0 9 2342 19200300 100 1 1 */
-459,	/* OBJ_textEncodedORAddress         0 9 2342 19200300 100 1 2 */
-460,	/* OBJ_rfc822Mailbox                0 9 2342 19200300 100 1 3 */
-461,	/* OBJ_info                         0 9 2342 19200300 100 1 4 */
-462,	/* OBJ_favouriteDrink               0 9 2342 19200300 100 1 5 */
-463,	/* OBJ_roomNumber                   0 9 2342 19200300 100 1 6 */
-464,	/* OBJ_photo                        0 9 2342 19200300 100 1 7 */
-465,	/* OBJ_userClass                    0 9 2342 19200300 100 1 8 */
-466,	/* OBJ_host                         0 9 2342 19200300 100 1 9 */
-467,	/* OBJ_manager                      0 9 2342 19200300 100 1 10 */
-468,	/* OBJ_documentIdentifier           0 9 2342 19200300 100 1 11 */
-469,	/* OBJ_documentTitle                0 9 2342 19200300 100 1 12 */
-470,	/* OBJ_documentVersion              0 9 2342 19200300 100 1 13 */
-471,	/* OBJ_documentAuthor               0 9 2342 19200300 100 1 14 */
-472,	/* OBJ_documentLocation             0 9 2342 19200300 100 1 15 */
-473,	/* OBJ_homeTelephoneNumber          0 9 2342 19200300 100 1 20 */
-474,	/* OBJ_secretary                    0 9 2342 19200300 100 1 21 */
-475,	/* OBJ_otherMailbox                 0 9 2342 19200300 100 1 22 */
-476,	/* OBJ_lastModifiedTime             0 9 2342 19200300 100 1 23 */
-477,	/* OBJ_lastModifiedBy               0 9 2342 19200300 100 1 24 */
-391,	/* OBJ_domainComponent              0 9 2342 19200300 100 1 25 */
-478,	/* OBJ_aRecord                      0 9 2342 19200300 100 1 26 */
-479,	/* OBJ_pilotAttributeType27         0 9 2342 19200300 100 1 27 */
-480,	/* OBJ_mXRecord                     0 9 2342 19200300 100 1 28 */
-481,	/* OBJ_nSRecord                     0 9 2342 19200300 100 1 29 */
-482,	/* OBJ_sOARecord                    0 9 2342 19200300 100 1 30 */
-483,	/* OBJ_cNAMERecord                  0 9 2342 19200300 100 1 31 */
-484,	/* OBJ_associatedDomain             0 9 2342 19200300 100 1 37 */
-485,	/* OBJ_associatedName               0 9 2342 19200300 100 1 38 */
-486,	/* OBJ_homePostalAddress            0 9 2342 19200300 100 1 39 */
-487,	/* OBJ_personalTitle                0 9 2342 19200300 100 1 40 */
-488,	/* OBJ_mobileTelephoneNumber        0 9 2342 19200300 100 1 41 */
-489,	/* OBJ_pagerTelephoneNumber         0 9 2342 19200300 100 1 42 */
-490,	/* OBJ_friendlyCountryName          0 9 2342 19200300 100 1 43 */
-491,	/* OBJ_organizationalStatus         0 9 2342 19200300 100 1 45 */
-492,	/* OBJ_janetMailbox                 0 9 2342 19200300 100 1 46 */
-493,	/* OBJ_mailPreferenceOption         0 9 2342 19200300 100 1 47 */
-494,	/* OBJ_buildingName                 0 9 2342 19200300 100 1 48 */
-495,	/* OBJ_dSAQuality                   0 9 2342 19200300 100 1 49 */
-496,	/* OBJ_singleLevelQuality           0 9 2342 19200300 100 1 50 */
-497,	/* OBJ_subtreeMinimumQuality        0 9 2342 19200300 100 1 51 */
-498,	/* OBJ_subtreeMaximumQuality        0 9 2342 19200300 100 1 52 */
-499,	/* OBJ_personalSignature            0 9 2342 19200300 100 1 53 */
-500,	/* OBJ_dITRedirect                  0 9 2342 19200300 100 1 54 */
-501,	/* OBJ_audio                        0 9 2342 19200300 100 1 55 */
-502,	/* OBJ_documentPublisher            0 9 2342 19200300 100 1 56 */
-442,	/* OBJ_iA5StringSyntax              0 9 2342 19200300 100 3 4 */
-443,	/* OBJ_caseIgnoreIA5StringSyntax    0 9 2342 19200300 100 3 5 */
-444,	/* OBJ_pilotObject                  0 9 2342 19200300 100 4 3 */
-445,	/* OBJ_pilotPerson                  0 9 2342 19200300 100 4 4 */
-446,	/* OBJ_account                      0 9 2342 19200300 100 4 5 */
-447,	/* OBJ_document                     0 9 2342 19200300 100 4 6 */
-448,	/* OBJ_room                         0 9 2342 19200300 100 4 7 */
-449,	/* OBJ_documentSeries               0 9 2342 19200300 100 4 9 */
-392,	/* OBJ_Domain                       0 9 2342 19200300 100 4 13 */
-450,	/* OBJ_rFC822localPart              0 9 2342 19200300 100 4 14 */
-451,	/* OBJ_dNSDomain                    0 9 2342 19200300 100 4 15 */
-452,	/* OBJ_domainRelatedObject          0 9 2342 19200300 100 4 17 */
-453,	/* OBJ_friendlyCountry              0 9 2342 19200300 100 4 18 */
-454,	/* OBJ_simpleSecurityObject         0 9 2342 19200300 100 4 19 */
-455,	/* OBJ_pilotOrganization            0 9 2342 19200300 100 4 20 */
-456,	/* OBJ_pilotDSA                     0 9 2342 19200300 100 4 21 */
-457,	/* OBJ_qualityLabelledData          0 9 2342 19200300 100 4 22 */
-189,	/* OBJ_id_smime_mod                 1 2 840 113549 1 9 16 0 */
-190,	/* OBJ_id_smime_ct                  1 2 840 113549 1 9 16 1 */
-191,	/* OBJ_id_smime_aa                  1 2 840 113549 1 9 16 2 */
-192,	/* OBJ_id_smime_alg                 1 2 840 113549 1 9 16 3 */
-193,	/* OBJ_id_smime_cd                  1 2 840 113549 1 9 16 4 */
-194,	/* OBJ_id_smime_spq                 1 2 840 113549 1 9 16 5 */
-195,	/* OBJ_id_smime_cti                 1 2 840 113549 1 9 16 6 */
-158,	/* OBJ_x509Certificate              1 2 840 113549 1 9 22 1 */
-159,	/* OBJ_sdsiCertificate              1 2 840 113549 1 9 22 2 */
-160,	/* OBJ_x509Crl                      1 2 840 113549 1 9 23 1 */
-144,	/* OBJ_pbe_WithSHA1And128BitRC4     1 2 840 113549 1 12 1 1 */
-145,	/* OBJ_pbe_WithSHA1And40BitRC4      1 2 840 113549 1 12 1 2 */
-146,	/* OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC 1 2 840 113549 1 12 1 3 */
-147,	/* OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC 1 2 840 113549 1 12 1 4 */
-148,	/* OBJ_pbe_WithSHA1And128BitRC2_CBC 1 2 840 113549 1 12 1 5 */
-149,	/* OBJ_pbe_WithSHA1And40BitRC2_CBC  1 2 840 113549 1 12 1 6 */
-171,	/* OBJ_ms_ext_req                   1 3 6 1 4 1 311 2 1 14 */
-134,	/* OBJ_ms_code_ind                  1 3 6 1 4 1 311 2 1 21 */
-135,	/* OBJ_ms_code_com                  1 3 6 1 4 1 311 2 1 22 */
-136,	/* OBJ_ms_ctl_sign                  1 3 6 1 4 1 311 10 3 1 */
-137,	/* OBJ_ms_sgc                       1 3 6 1 4 1 311 10 3 3 */
-138,	/* OBJ_ms_efs                       1 3 6 1 4 1 311 10 3 4 */
-648,	/* OBJ_ms_smartcard_login           1 3 6 1 4 1 311 20 2 2 */
-649,	/* OBJ_ms_upn                       1 3 6 1 4 1 311 20 2 3 */
-751,	/* OBJ_camellia_128_cbc             1 2 392 200011 61 1 1 1 2 */
-752,	/* OBJ_camellia_192_cbc             1 2 392 200011 61 1 1 1 3 */
-753,	/* OBJ_camellia_256_cbc             1 2 392 200011 61 1 1 1 4 */
-907,	/* OBJ_id_camellia128_wrap          1 2 392 200011 61 1 1 3 2 */
-908,	/* OBJ_id_camellia192_wrap          1 2 392 200011 61 1 1 3 3 */
-909,	/* OBJ_id_camellia256_wrap          1 2 392 200011 61 1 1 3 4 */
-196,	/* OBJ_id_smime_mod_cms             1 2 840 113549 1 9 16 0 1 */
-197,	/* OBJ_id_smime_mod_ess             1 2 840 113549 1 9 16 0 2 */
-198,	/* OBJ_id_smime_mod_oid             1 2 840 113549 1 9 16 0 3 */
-199,	/* OBJ_id_smime_mod_msg_v3          1 2 840 113549 1 9 16 0 4 */
-200,	/* OBJ_id_smime_mod_ets_eSignature_88 1 2 840 113549 1 9 16 0 5 */
-201,	/* OBJ_id_smime_mod_ets_eSignature_97 1 2 840 113549 1 9 16 0 6 */
-202,	/* OBJ_id_smime_mod_ets_eSigPolicy_88 1 2 840 113549 1 9 16 0 7 */
-203,	/* OBJ_id_smime_mod_ets_eSigPolicy_97 1 2 840 113549 1 9 16 0 8 */
-204,	/* OBJ_id_smime_ct_receipt          1 2 840 113549 1 9 16 1 1 */
-205,	/* OBJ_id_smime_ct_authData         1 2 840 113549 1 9 16 1 2 */
-206,	/* OBJ_id_smime_ct_publishCert      1 2 840 113549 1 9 16 1 3 */
-207,	/* OBJ_id_smime_ct_TSTInfo          1 2 840 113549 1 9 16 1 4 */
-208,	/* OBJ_id_smime_ct_TDTInfo          1 2 840 113549 1 9 16 1 5 */
-209,	/* OBJ_id_smime_ct_contentInfo      1 2 840 113549 1 9 16 1 6 */
-210,	/* OBJ_id_smime_ct_DVCSRequestData  1 2 840 113549 1 9 16 1 7 */
-211,	/* OBJ_id_smime_ct_DVCSResponseData 1 2 840 113549 1 9 16 1 8 */
-786,	/* OBJ_id_smime_ct_compressedData   1 2 840 113549 1 9 16 1 9 */
-787,	/* OBJ_id_ct_asciiTextWithCRLF      1 2 840 113549 1 9 16 1 27 */
-212,	/* OBJ_id_smime_aa_receiptRequest   1 2 840 113549 1 9 16 2 1 */
-213,	/* OBJ_id_smime_aa_securityLabel    1 2 840 113549 1 9 16 2 2 */
-214,	/* OBJ_id_smime_aa_mlExpandHistory  1 2 840 113549 1 9 16 2 3 */
-215,	/* OBJ_id_smime_aa_contentHint      1 2 840 113549 1 9 16 2 4 */
-216,	/* OBJ_id_smime_aa_msgSigDigest     1 2 840 113549 1 9 16 2 5 */
-217,	/* OBJ_id_smime_aa_encapContentType 1 2 840 113549 1 9 16 2 6 */
-218,	/* OBJ_id_smime_aa_contentIdentifier 1 2 840 113549 1 9 16 2 7 */
-219,	/* OBJ_id_smime_aa_macValue         1 2 840 113549 1 9 16 2 8 */
-220,	/* OBJ_id_smime_aa_equivalentLabels 1 2 840 113549 1 9 16 2 9 */
-221,	/* OBJ_id_smime_aa_contentReference 1 2 840 113549 1 9 16 2 10 */
-222,	/* OBJ_id_smime_aa_encrypKeyPref    1 2 840 113549 1 9 16 2 11 */
-223,	/* OBJ_id_smime_aa_signingCertificate 1 2 840 113549 1 9 16 2 12 */
-224,	/* OBJ_id_smime_aa_smimeEncryptCerts 1 2 840 113549 1 9 16 2 13 */
-225,	/* OBJ_id_smime_aa_timeStampToken   1 2 840 113549 1 9 16 2 14 */
-226,	/* OBJ_id_smime_aa_ets_sigPolicyId  1 2 840 113549 1 9 16 2 15 */
-227,	/* OBJ_id_smime_aa_ets_commitmentType 1 2 840 113549 1 9 16 2 16 */
-228,	/* OBJ_id_smime_aa_ets_signerLocation 1 2 840 113549 1 9 16 2 17 */
-229,	/* OBJ_id_smime_aa_ets_signerAttr   1 2 840 113549 1 9 16 2 18 */
-230,	/* OBJ_id_smime_aa_ets_otherSigCert 1 2 840 113549 1 9 16 2 19 */
-231,	/* OBJ_id_smime_aa_ets_contentTimestamp 1 2 840 113549 1 9 16 2 20 */
-232,	/* OBJ_id_smime_aa_ets_CertificateRefs 1 2 840 113549 1 9 16 2 21 */
-233,	/* OBJ_id_smime_aa_ets_RevocationRefs 1 2 840 113549 1 9 16 2 22 */
-234,	/* OBJ_id_smime_aa_ets_certValues   1 2 840 113549 1 9 16 2 23 */
-235,	/* OBJ_id_smime_aa_ets_revocationValues 1 2 840 113549 1 9 16 2 24 */
-236,	/* OBJ_id_smime_aa_ets_escTimeStamp 1 2 840 113549 1 9 16 2 25 */
-237,	/* OBJ_id_smime_aa_ets_certCRLTimestamp 1 2 840 113549 1 9 16 2 26 */
-238,	/* OBJ_id_smime_aa_ets_archiveTimeStamp 1 2 840 113549 1 9 16 2 27 */
-239,	/* OBJ_id_smime_aa_signatureType    1 2 840 113549 1 9 16 2 28 */
-240,	/* OBJ_id_smime_aa_dvcs_dvc         1 2 840 113549 1 9 16 2 29 */
-241,	/* OBJ_id_smime_alg_ESDHwith3DES    1 2 840 113549 1 9 16 3 1 */
-242,	/* OBJ_id_smime_alg_ESDHwithRC2     1 2 840 113549 1 9 16 3 2 */
-243,	/* OBJ_id_smime_alg_3DESwrap        1 2 840 113549 1 9 16 3 3 */
-244,	/* OBJ_id_smime_alg_RC2wrap         1 2 840 113549 1 9 16 3 4 */
-245,	/* OBJ_id_smime_alg_ESDH            1 2 840 113549 1 9 16 3 5 */
-246,	/* OBJ_id_smime_alg_CMS3DESwrap     1 2 840 113549 1 9 16 3 6 */
-247,	/* OBJ_id_smime_alg_CMSRC2wrap      1 2 840 113549 1 9 16 3 7 */
-125,	/* OBJ_zlib_compression             1 2 840 113549 1 9 16 3 8 */
-893,	/* OBJ_id_alg_PWRI_KEK              1 2 840 113549 1 9 16 3 9 */
-248,	/* OBJ_id_smime_cd_ldap             1 2 840 113549 1 9 16 4 1 */
-249,	/* OBJ_id_smime_spq_ets_sqt_uri     1 2 840 113549 1 9 16 5 1 */
-250,	/* OBJ_id_smime_spq_ets_sqt_unotice 1 2 840 113549 1 9 16 5 2 */
-251,	/* OBJ_id_smime_cti_ets_proofOfOrigin 1 2 840 113549 1 9 16 6 1 */
-252,	/* OBJ_id_smime_cti_ets_proofOfReceipt 1 2 840 113549 1 9 16 6 2 */
-253,	/* OBJ_id_smime_cti_ets_proofOfDelivery 1 2 840 113549 1 9 16 6 3 */
-254,	/* OBJ_id_smime_cti_ets_proofOfSender 1 2 840 113549 1 9 16 6 4 */
-255,	/* OBJ_id_smime_cti_ets_proofOfApproval 1 2 840 113549 1 9 16 6 5 */
-256,	/* OBJ_id_smime_cti_ets_proofOfCreation 1 2 840 113549 1 9 16 6 6 */
-150,	/* OBJ_keyBag                       1 2 840 113549 1 12 10 1 1 */
-151,	/* OBJ_pkcs8ShroudedKeyBag          1 2 840 113549 1 12 10 1 2 */
-152,	/* OBJ_certBag                      1 2 840 113549 1 12 10 1 3 */
-153,	/* OBJ_crlBag                       1 2 840 113549 1 12 10 1 4 */
-154,	/* OBJ_secretBag                    1 2 840 113549 1 12 10 1 5 */
-155,	/* OBJ_safeContentsBag              1 2 840 113549 1 12 10 1 6 */
-34,	/* OBJ_idea_cbc                     1 3 6 1 4 1 188 7 1 1 2 */
+static const unsigned kNIDsInOIDOrder[] = {
+    434 /* 0.9 (OBJ_data) */, 182 /* 1.2 (OBJ_member_body) */,
+    379 /* 1.3 (OBJ_org) */, 676 /* 1.3 (OBJ_identified_organization) */,
+    11 /* 2.5 (OBJ_X500) */, 647 /* 2.23 (OBJ_international_organizations) */,
+    380 /* 1.3.6 (OBJ_dod) */, 12 /* 2.5.4 (OBJ_X509) */,
+    378 /* 2.5.8 (OBJ_X500algorithms) */, 81 /* 2.5.29 (OBJ_id_ce) */,
+    512 /* 2.23.42 (OBJ_id_set) */, 678 /* 2.23.43 (OBJ_wap) */,
+    435 /* 0.9.2342 (OBJ_pss) */, 183 /* 1.2.840 (OBJ_ISO_US) */,
+    381 /* 1.3.6.1 (OBJ_iana) */, 677 /* 1.3.132 (OBJ_certicom_arc) */,
+    394 /* 2.5.1.5 (OBJ_selected_attribute_types) */,
+    13 /* 2.5.4.3 (OBJ_commonName) */, 100 /* 2.5.4.4 (OBJ_surname) */,
+    105 /* 2.5.4.5 (OBJ_serialNumber) */, 14 /* 2.5.4.6 (OBJ_countryName) */,
+    15 /* 2.5.4.7 (OBJ_localityName) */,
+    16 /* 2.5.4.8 (OBJ_stateOrProvinceName) */,
+    660 /* 2.5.4.9 (OBJ_streetAddress) */,
+    17 /* 2.5.4.10 (OBJ_organizationName) */,
+    18 /* 2.5.4.11 (OBJ_organizationalUnitName) */,
+    106 /* 2.5.4.12 (OBJ_title) */, 107 /* 2.5.4.13 (OBJ_description) */,
+    859 /* 2.5.4.14 (OBJ_searchGuide) */,
+    860 /* 2.5.4.15 (OBJ_businessCategory) */,
+    861 /* 2.5.4.16 (OBJ_postalAddress) */, 661 /* 2.5.4.17 (OBJ_postalCode) */,
+    862 /* 2.5.4.18 (OBJ_postOfficeBox) */,
+    863 /* 2.5.4.19 (OBJ_physicalDeliveryOfficeName) */,
+    864 /* 2.5.4.20 (OBJ_telephoneNumber) */,
+    865 /* 2.5.4.21 (OBJ_telexNumber) */,
+    866 /* 2.5.4.22 (OBJ_teletexTerminalIdentifier) */,
+    867 /* 2.5.4.23 (OBJ_facsimileTelephoneNumber) */,
+    868 /* 2.5.4.24 (OBJ_x121Address) */,
+    869 /* 2.5.4.25 (OBJ_internationaliSDNNumber) */,
+    870 /* 2.5.4.26 (OBJ_registeredAddress) */,
+    871 /* 2.5.4.27 (OBJ_destinationIndicator) */,
+    872 /* 2.5.4.28 (OBJ_preferredDeliveryMethod) */,
+    873 /* 2.5.4.29 (OBJ_presentationAddress) */,
+    874 /* 2.5.4.30 (OBJ_supportedApplicationContext) */,
+    875 /* 2.5.4.31 (OBJ_member) */, 876 /* 2.5.4.32 (OBJ_owner) */,
+    877 /* 2.5.4.33 (OBJ_roleOccupant) */, 878 /* 2.5.4.34 (OBJ_seeAlso) */,
+    879 /* 2.5.4.35 (OBJ_userPassword) */,
+    880 /* 2.5.4.36 (OBJ_userCertificate) */,
+    881 /* 2.5.4.37 (OBJ_cACertificate) */,
+    882 /* 2.5.4.38 (OBJ_authorityRevocationList) */,
+    883 /* 2.5.4.39 (OBJ_certificateRevocationList) */,
+    884 /* 2.5.4.40 (OBJ_crossCertificatePair) */,
+    173 /* 2.5.4.41 (OBJ_name) */, 99 /* 2.5.4.42 (OBJ_givenName) */,
+    101 /* 2.5.4.43 (OBJ_initials) */,
+    509 /* 2.5.4.44 (OBJ_generationQualifier) */,
+    503 /* 2.5.4.45 (OBJ_x500UniqueIdentifier) */,
+    174 /* 2.5.4.46 (OBJ_dnQualifier) */,
+    885 /* 2.5.4.47 (OBJ_enhancedSearchGuide) */,
+    886 /* 2.5.4.48 (OBJ_protocolInformation) */,
+    887 /* 2.5.4.49 (OBJ_distinguishedName) */,
+    888 /* 2.5.4.50 (OBJ_uniqueMember) */,
+    889 /* 2.5.4.51 (OBJ_houseIdentifier) */,
+    890 /* 2.5.4.52 (OBJ_supportedAlgorithms) */,
+    891 /* 2.5.4.53 (OBJ_deltaRevocationList) */,
+    892 /* 2.5.4.54 (OBJ_dmdName) */, 510 /* 2.5.4.65 (OBJ_pseudonym) */,
+    400 /* 2.5.4.72 (OBJ_role) */,
+    769 /* 2.5.29.9 (OBJ_subject_directory_attributes) */,
+    82 /* 2.5.29.14 (OBJ_subject_key_identifier) */,
+    83 /* 2.5.29.15 (OBJ_key_usage) */,
+    84 /* 2.5.29.16 (OBJ_private_key_usage_period) */,
+    85 /* 2.5.29.17 (OBJ_subject_alt_name) */,
+    86 /* 2.5.29.18 (OBJ_issuer_alt_name) */,
+    87 /* 2.5.29.19 (OBJ_basic_constraints) */,
+    88 /* 2.5.29.20 (OBJ_crl_number) */, 141 /* 2.5.29.21 (OBJ_crl_reason) */,
+    430 /* 2.5.29.23 (OBJ_hold_instruction_code) */,
+    142 /* 2.5.29.24 (OBJ_invalidity_date) */,
+    140 /* 2.5.29.27 (OBJ_delta_crl) */,
+    770 /* 2.5.29.28 (OBJ_issuing_distribution_point) */,
+    771 /* 2.5.29.29 (OBJ_certificate_issuer) */,
+    666 /* 2.5.29.30 (OBJ_name_constraints) */,
+    103 /* 2.5.29.31 (OBJ_crl_distribution_points) */,
+    89 /* 2.5.29.32 (OBJ_certificate_policies) */,
+    747 /* 2.5.29.33 (OBJ_policy_mappings) */,
+    90 /* 2.5.29.35 (OBJ_authority_key_identifier) */,
+    401 /* 2.5.29.36 (OBJ_policy_constraints) */,
+    126 /* 2.5.29.37 (OBJ_ext_key_usage) */,
+    857 /* 2.5.29.46 (OBJ_freshest_crl) */,
+    748 /* 2.5.29.54 (OBJ_inhibit_any_policy) */,
+    402 /* 2.5.29.55 (OBJ_target_information) */,
+    403 /* 2.5.29.56 (OBJ_no_rev_avail) */, 513 /* 2.23.42.0 (OBJ_set_ctype) */,
+    514 /* 2.23.42.1 (OBJ_set_msgExt) */, 515 /* 2.23.42.3 (OBJ_set_attr) */,
+    516 /* 2.23.42.5 (OBJ_set_policy) */, 517 /* 2.23.42.7 (OBJ_set_certExt) */,
+    518 /* 2.23.42.8 (OBJ_set_brand) */, 679 /* 2.23.43.1 (OBJ_wap_wsg) */,
+    382 /* 1.3.6.1.1 (OBJ_Directory) */, 383 /* 1.3.6.1.2 (OBJ_Management) */,
+    384 /* 1.3.6.1.3 (OBJ_Experimental) */, 385 /* 1.3.6.1.4 (OBJ_Private) */,
+    386 /* 1.3.6.1.5 (OBJ_Security) */, 387 /* 1.3.6.1.6 (OBJ_SNMPv2) */,
+    388 /* 1.3.6.1.7 (OBJ_Mail) */, 376 /* 1.3.14.3.2 (OBJ_algorithm) */,
+    395 /* 2.5.1.5.55 (OBJ_clearance) */, 19 /* 2.5.8.1.1 (OBJ_rsa) */,
+    96 /* 2.5.8.3.100 (OBJ_mdc2WithRSA) */, 95 /* 2.5.8.3.101 (OBJ_mdc2) */,
+    746 /* 2.5.29.32.0 (OBJ_any_policy) */,
+    910 /* 2.5.29.37.0 (OBJ_anyExtendedKeyUsage) */,
+    519 /* 2.23.42.0.0 (OBJ_setct_PANData) */,
+    520 /* 2.23.42.0.1 (OBJ_setct_PANToken) */,
+    521 /* 2.23.42.0.2 (OBJ_setct_PANOnly) */,
+    522 /* 2.23.42.0.3 (OBJ_setct_OIData) */,
+    523 /* 2.23.42.0.4 (OBJ_setct_PI) */,
+    524 /* 2.23.42.0.5 (OBJ_setct_PIData) */,
+    525 /* 2.23.42.0.6 (OBJ_setct_PIDataUnsigned) */,
+    526 /* 2.23.42.0.7 (OBJ_setct_HODInput) */,
+    527 /* 2.23.42.0.8 (OBJ_setct_AuthResBaggage) */,
+    528 /* 2.23.42.0.9 (OBJ_setct_AuthRevReqBaggage) */,
+    529 /* 2.23.42.0.10 (OBJ_setct_AuthRevResBaggage) */,
+    530 /* 2.23.42.0.11 (OBJ_setct_CapTokenSeq) */,
+    531 /* 2.23.42.0.12 (OBJ_setct_PInitResData) */,
+    532 /* 2.23.42.0.13 (OBJ_setct_PI_TBS) */,
+    533 /* 2.23.42.0.14 (OBJ_setct_PResData) */,
+    534 /* 2.23.42.0.16 (OBJ_setct_AuthReqTBS) */,
+    535 /* 2.23.42.0.17 (OBJ_setct_AuthResTBS) */,
+    536 /* 2.23.42.0.18 (OBJ_setct_AuthResTBSX) */,
+    537 /* 2.23.42.0.19 (OBJ_setct_AuthTokenTBS) */,
+    538 /* 2.23.42.0.20 (OBJ_setct_CapTokenData) */,
+    539 /* 2.23.42.0.21 (OBJ_setct_CapTokenTBS) */,
+    540 /* 2.23.42.0.22 (OBJ_setct_AcqCardCodeMsg) */,
+    541 /* 2.23.42.0.23 (OBJ_setct_AuthRevReqTBS) */,
+    542 /* 2.23.42.0.24 (OBJ_setct_AuthRevResData) */,
+    543 /* 2.23.42.0.25 (OBJ_setct_AuthRevResTBS) */,
+    544 /* 2.23.42.0.26 (OBJ_setct_CapReqTBS) */,
+    545 /* 2.23.42.0.27 (OBJ_setct_CapReqTBSX) */,
+    546 /* 2.23.42.0.28 (OBJ_setct_CapResData) */,
+    547 /* 2.23.42.0.29 (OBJ_setct_CapRevReqTBS) */,
+    548 /* 2.23.42.0.30 (OBJ_setct_CapRevReqTBSX) */,
+    549 /* 2.23.42.0.31 (OBJ_setct_CapRevResData) */,
+    550 /* 2.23.42.0.32 (OBJ_setct_CredReqTBS) */,
+    551 /* 2.23.42.0.33 (OBJ_setct_CredReqTBSX) */,
+    552 /* 2.23.42.0.34 (OBJ_setct_CredResData) */,
+    553 /* 2.23.42.0.35 (OBJ_setct_CredRevReqTBS) */,
+    554 /* 2.23.42.0.36 (OBJ_setct_CredRevReqTBSX) */,
+    555 /* 2.23.42.0.37 (OBJ_setct_CredRevResData) */,
+    556 /* 2.23.42.0.38 (OBJ_setct_PCertReqData) */,
+    557 /* 2.23.42.0.39 (OBJ_setct_PCertResTBS) */,
+    558 /* 2.23.42.0.40 (OBJ_setct_BatchAdminReqData) */,
+    559 /* 2.23.42.0.41 (OBJ_setct_BatchAdminResData) */,
+    560 /* 2.23.42.0.42 (OBJ_setct_CardCInitResTBS) */,
+    561 /* 2.23.42.0.43 (OBJ_setct_MeAqCInitResTBS) */,
+    562 /* 2.23.42.0.44 (OBJ_setct_RegFormResTBS) */,
+    563 /* 2.23.42.0.45 (OBJ_setct_CertReqData) */,
+    564 /* 2.23.42.0.46 (OBJ_setct_CertReqTBS) */,
+    565 /* 2.23.42.0.47 (OBJ_setct_CertResData) */,
+    566 /* 2.23.42.0.48 (OBJ_setct_CertInqReqTBS) */,
+    567 /* 2.23.42.0.49 (OBJ_setct_ErrorTBS) */,
+    568 /* 2.23.42.0.50 (OBJ_setct_PIDualSignedTBE) */,
+    569 /* 2.23.42.0.51 (OBJ_setct_PIUnsignedTBE) */,
+    570 /* 2.23.42.0.52 (OBJ_setct_AuthReqTBE) */,
+    571 /* 2.23.42.0.53 (OBJ_setct_AuthResTBE) */,
+    572 /* 2.23.42.0.54 (OBJ_setct_AuthResTBEX) */,
+    573 /* 2.23.42.0.55 (OBJ_setct_AuthTokenTBE) */,
+    574 /* 2.23.42.0.56 (OBJ_setct_CapTokenTBE) */,
+    575 /* 2.23.42.0.57 (OBJ_setct_CapTokenTBEX) */,
+    576 /* 2.23.42.0.58 (OBJ_setct_AcqCardCodeMsgTBE) */,
+    577 /* 2.23.42.0.59 (OBJ_setct_AuthRevReqTBE) */,
+    578 /* 2.23.42.0.60 (OBJ_setct_AuthRevResTBE) */,
+    579 /* 2.23.42.0.61 (OBJ_setct_AuthRevResTBEB) */,
+    580 /* 2.23.42.0.62 (OBJ_setct_CapReqTBE) */,
+    581 /* 2.23.42.0.63 (OBJ_setct_CapReqTBEX) */,
+    582 /* 2.23.42.0.64 (OBJ_setct_CapResTBE) */,
+    583 /* 2.23.42.0.65 (OBJ_setct_CapRevReqTBE) */,
+    584 /* 2.23.42.0.66 (OBJ_setct_CapRevReqTBEX) */,
+    585 /* 2.23.42.0.67 (OBJ_setct_CapRevResTBE) */,
+    586 /* 2.23.42.0.68 (OBJ_setct_CredReqTBE) */,
+    587 /* 2.23.42.0.69 (OBJ_setct_CredReqTBEX) */,
+    588 /* 2.23.42.0.70 (OBJ_setct_CredResTBE) */,
+    589 /* 2.23.42.0.71 (OBJ_setct_CredRevReqTBE) */,
+    590 /* 2.23.42.0.72 (OBJ_setct_CredRevReqTBEX) */,
+    591 /* 2.23.42.0.73 (OBJ_setct_CredRevResTBE) */,
+    592 /* 2.23.42.0.74 (OBJ_setct_BatchAdminReqTBE) */,
+    593 /* 2.23.42.0.75 (OBJ_setct_BatchAdminResTBE) */,
+    594 /* 2.23.42.0.76 (OBJ_setct_RegFormReqTBE) */,
+    595 /* 2.23.42.0.77 (OBJ_setct_CertReqTBE) */,
+    596 /* 2.23.42.0.78 (OBJ_setct_CertReqTBEX) */,
+    597 /* 2.23.42.0.79 (OBJ_setct_CertResTBE) */,
+    598 /* 2.23.42.0.80 (OBJ_setct_CRLNotificationTBS) */,
+    599 /* 2.23.42.0.81 (OBJ_setct_CRLNotificationResTBS) */,
+    600 /* 2.23.42.0.82 (OBJ_setct_BCIDistributionTBS) */,
+    601 /* 2.23.42.1.1 (OBJ_setext_genCrypt) */,
+    602 /* 2.23.42.1.3 (OBJ_setext_miAuth) */,
+    603 /* 2.23.42.1.4 (OBJ_setext_pinSecure) */,
+    604 /* 2.23.42.1.5 (OBJ_setext_pinAny) */,
+    605 /* 2.23.42.1.7 (OBJ_setext_track2) */,
+    606 /* 2.23.42.1.8 (OBJ_setext_cv) */,
+    620 /* 2.23.42.3.0 (OBJ_setAttr_Cert) */,
+    621 /* 2.23.42.3.1 (OBJ_setAttr_PGWYcap) */,
+    622 /* 2.23.42.3.2 (OBJ_setAttr_TokenType) */,
+    623 /* 2.23.42.3.3 (OBJ_setAttr_IssCap) */,
+    607 /* 2.23.42.5.0 (OBJ_set_policy_root) */,
+    608 /* 2.23.42.7.0 (OBJ_setCext_hashedRoot) */,
+    609 /* 2.23.42.7.1 (OBJ_setCext_certType) */,
+    610 /* 2.23.42.7.2 (OBJ_setCext_merchData) */,
+    611 /* 2.23.42.7.3 (OBJ_setCext_cCertRequired) */,
+    612 /* 2.23.42.7.4 (OBJ_setCext_tunneling) */,
+    613 /* 2.23.42.7.5 (OBJ_setCext_setExt) */,
+    614 /* 2.23.42.7.6 (OBJ_setCext_setQualf) */,
+    615 /* 2.23.42.7.7 (OBJ_setCext_PGWYcapabilities) */,
+    616 /* 2.23.42.7.8 (OBJ_setCext_TokenIdentifier) */,
+    617 /* 2.23.42.7.9 (OBJ_setCext_Track2Data) */,
+    618 /* 2.23.42.7.10 (OBJ_setCext_TokenType) */,
+    619 /* 2.23.42.7.11 (OBJ_setCext_IssuerCapabilities) */,
+    636 /* 2.23.42.8.1 (OBJ_set_brand_IATA_ATA) */,
+    640 /* 2.23.42.8.4 (OBJ_set_brand_Visa) */,
+    641 /* 2.23.42.8.5 (OBJ_set_brand_MasterCard) */,
+    637 /* 2.23.42.8.30 (OBJ_set_brand_Diners) */,
+    638 /* 2.23.42.8.34 (OBJ_set_brand_AmericanExpress) */,
+    639 /* 2.23.42.8.35 (OBJ_set_brand_JCB) */,
+    805 /* 1.2.643.2.2 (OBJ_cryptopro) */,
+    806 /* 1.2.643.2.9 (OBJ_cryptocom) */, 184 /* 1.2.840.10040 (OBJ_X9_57) */,
+    405 /* 1.2.840.10045 (OBJ_ansi_X9_62) */,
+    389 /* 1.3.6.1.4.1 (OBJ_Enterprises) */,
+    504 /* 1.3.6.1.7.1 (OBJ_mime_mhs) */,
+    104 /* 1.3.14.3.2.3 (OBJ_md5WithRSA) */,
+    29 /* 1.3.14.3.2.6 (OBJ_des_ecb) */, 31 /* 1.3.14.3.2.7 (OBJ_des_cbc) */,
+    45 /* 1.3.14.3.2.8 (OBJ_des_ofb64) */,
+    30 /* 1.3.14.3.2.9 (OBJ_des_cfb64) */,
+    377 /* 1.3.14.3.2.11 (OBJ_rsaSignature) */,
+    67 /* 1.3.14.3.2.12 (OBJ_dsa_2) */, 66 /* 1.3.14.3.2.13 (OBJ_dsaWithSHA) */,
+    42 /* 1.3.14.3.2.15 (OBJ_shaWithRSAEncryption) */,
+    32 /* 1.3.14.3.2.17 (OBJ_des_ede_ecb) */, 41 /* 1.3.14.3.2.18 (OBJ_sha) */,
+    64 /* 1.3.14.3.2.26 (OBJ_sha1) */,
+    70 /* 1.3.14.3.2.27 (OBJ_dsaWithSHA1_2) */,
+    115 /* 1.3.14.3.2.29 (OBJ_sha1WithRSA) */,
+    117 /* 1.3.36.3.2.1 (OBJ_ripemd160) */, 143 /* 1.3.101.1.4.1 (OBJ_sxnet) */,
+    721 /* 1.3.132.0.1 (OBJ_sect163k1) */,
+    722 /* 1.3.132.0.2 (OBJ_sect163r1) */,
+    728 /* 1.3.132.0.3 (OBJ_sect239k1) */,
+    717 /* 1.3.132.0.4 (OBJ_sect113r1) */,
+    718 /* 1.3.132.0.5 (OBJ_sect113r2) */,
+    704 /* 1.3.132.0.6 (OBJ_secp112r1) */,
+    705 /* 1.3.132.0.7 (OBJ_secp112r2) */,
+    709 /* 1.3.132.0.8 (OBJ_secp160r1) */,
+    708 /* 1.3.132.0.9 (OBJ_secp160k1) */,
+    714 /* 1.3.132.0.10 (OBJ_secp256k1) */,
+    723 /* 1.3.132.0.15 (OBJ_sect163r2) */,
+    729 /* 1.3.132.0.16 (OBJ_sect283k1) */,
+    730 /* 1.3.132.0.17 (OBJ_sect283r1) */,
+    719 /* 1.3.132.0.22 (OBJ_sect131r1) */,
+    720 /* 1.3.132.0.23 (OBJ_sect131r2) */,
+    724 /* 1.3.132.0.24 (OBJ_sect193r1) */,
+    725 /* 1.3.132.0.25 (OBJ_sect193r2) */,
+    726 /* 1.3.132.0.26 (OBJ_sect233k1) */,
+    727 /* 1.3.132.0.27 (OBJ_sect233r1) */,
+    706 /* 1.3.132.0.28 (OBJ_secp128r1) */,
+    707 /* 1.3.132.0.29 (OBJ_secp128r2) */,
+    710 /* 1.3.132.0.30 (OBJ_secp160r2) */,
+    711 /* 1.3.132.0.31 (OBJ_secp192k1) */,
+    712 /* 1.3.132.0.32 (OBJ_secp224k1) */,
+    713 /* 1.3.132.0.33 (OBJ_secp224r1) */,
+    715 /* 1.3.132.0.34 (OBJ_secp384r1) */,
+    716 /* 1.3.132.0.35 (OBJ_secp521r1) */,
+    731 /* 1.3.132.0.36 (OBJ_sect409k1) */,
+    732 /* 1.3.132.0.37 (OBJ_sect409r1) */,
+    733 /* 1.3.132.0.38 (OBJ_sect571k1) */,
+    734 /* 1.3.132.0.39 (OBJ_sect571r1) */,
+    624 /* 2.23.42.3.0.0 (OBJ_set_rootKeyThumb) */,
+    625 /* 2.23.42.3.0.1 (OBJ_set_addPolicy) */,
+    626 /* 2.23.42.3.2.1 (OBJ_setAttr_Token_EMV) */,
+    627 /* 2.23.42.3.2.2 (OBJ_setAttr_Token_B0Prime) */,
+    628 /* 2.23.42.3.3.3 (OBJ_setAttr_IssCap_CVM) */,
+    629 /* 2.23.42.3.3.4 (OBJ_setAttr_IssCap_T2) */,
+    630 /* 2.23.42.3.3.5 (OBJ_setAttr_IssCap_Sig) */,
+    642 /* 2.23.42.8.6011 (OBJ_set_brand_Novus) */,
+    735 /* 2.23.43.1.4.1 (OBJ_wap_wsg_idm_ecid_wtls1) */,
+    736 /* 2.23.43.1.4.3 (OBJ_wap_wsg_idm_ecid_wtls3) */,
+    737 /* 2.23.43.1.4.4 (OBJ_wap_wsg_idm_ecid_wtls4) */,
+    738 /* 2.23.43.1.4.5 (OBJ_wap_wsg_idm_ecid_wtls5) */,
+    739 /* 2.23.43.1.4.6 (OBJ_wap_wsg_idm_ecid_wtls6) */,
+    740 /* 2.23.43.1.4.7 (OBJ_wap_wsg_idm_ecid_wtls7) */,
+    741 /* 2.23.43.1.4.8 (OBJ_wap_wsg_idm_ecid_wtls8) */,
+    742 /* 2.23.43.1.4.9 (OBJ_wap_wsg_idm_ecid_wtls9) */,
+    743 /* 2.23.43.1.4.10 (OBJ_wap_wsg_idm_ecid_wtls10) */,
+    744 /* 2.23.43.1.4.11 (OBJ_wap_wsg_idm_ecid_wtls11) */,
+    745 /* 2.23.43.1.4.12 (OBJ_wap_wsg_idm_ecid_wtls12) */,
+    804 /* 1.0.10118.3.0.55 (OBJ_whirlpool) */,
+    773 /* 1.2.410.200004 (OBJ_kisa) */,
+    807 /* 1.2.643.2.2.3 (OBJ_id_GostR3411_94_with_GostR3410_2001) */,
+    808 /* 1.2.643.2.2.4 (OBJ_id_GostR3411_94_with_GostR3410_94) */,
+    809 /* 1.2.643.2.2.9 (OBJ_id_GostR3411_94) */,
+    810 /* 1.2.643.2.2.10 (OBJ_id_HMACGostR3411_94) */,
+    811 /* 1.2.643.2.2.19 (OBJ_id_GostR3410_2001) */,
+    812 /* 1.2.643.2.2.20 (OBJ_id_GostR3410_94) */,
+    813 /* 1.2.643.2.2.21 (OBJ_id_Gost28147_89) */,
+    815 /* 1.2.643.2.2.22 (OBJ_id_Gost28147_89_MAC) */,
+    816 /* 1.2.643.2.2.23 (OBJ_id_GostR3411_94_prf) */,
+    817 /* 1.2.643.2.2.98 (OBJ_id_GostR3410_2001DH) */,
+    818 /* 1.2.643.2.2.99 (OBJ_id_GostR3410_94DH) */,
+    1 /* 1.2.840.113549 (OBJ_rsadsi) */, 185 /* 1.2.840.10040.4 (OBJ_X9cm) */,
+    127 /* 1.3.6.1.5.5.7 (OBJ_id_pkix) */,
+    505 /* 1.3.6.1.7.1.1 (OBJ_mime_mhs_headings) */,
+    506 /* 1.3.6.1.7.1.2 (OBJ_mime_mhs_bodies) */,
+    119 /* 1.3.36.3.3.1.2 (OBJ_ripemd160WithRSA) */,
+    937 /* 1.3.132.1.11.0 (OBJ_dhSinglePass_stdDH_sha224kdf_scheme) */,
+    938 /* 1.3.132.1.11.1 (OBJ_dhSinglePass_stdDH_sha256kdf_scheme) */,
+    939 /* 1.3.132.1.11.2 (OBJ_dhSinglePass_stdDH_sha384kdf_scheme) */,
+    940 /* 1.3.132.1.11.3 (OBJ_dhSinglePass_stdDH_sha512kdf_scheme) */,
+    942 /* 1.3.132.1.14.0 (OBJ_dhSinglePass_cofactorDH_sha224kdf_scheme) */,
+    943 /* 1.3.132.1.14.1 (OBJ_dhSinglePass_cofactorDH_sha256kdf_scheme) */,
+    944 /* 1.3.132.1.14.2 (OBJ_dhSinglePass_cofactorDH_sha384kdf_scheme) */,
+    945 /* 1.3.132.1.14.3 (OBJ_dhSinglePass_cofactorDH_sha512kdf_scheme) */,
+    631 /* 2.23.42.3.3.3.1 (OBJ_setAttr_GenCryptgrm) */,
+    632 /* 2.23.42.3.3.4.1 (OBJ_setAttr_T2Enc) */,
+    633 /* 2.23.42.3.3.4.2 (OBJ_setAttr_T2cleartxt) */,
+    634 /* 2.23.42.3.3.5.1 (OBJ_setAttr_TokICCsig) */,
+    635 /* 2.23.42.3.3.5.2 (OBJ_setAttr_SecDevSig) */,
+    436 /* 0.9.2342.19200300 (OBJ_ucl) */,
+    820 /* 1.2.643.2.2.14.0 (OBJ_id_Gost28147_89_None_KeyMeshing) */,
+    819 /* 1.2.643.2.2.14.1 (OBJ_id_Gost28147_89_CryptoPro_KeyMeshing) */,
+    845 /* 1.2.643.2.2.20.1 (OBJ_id_GostR3410_94_a) */,
+    846 /* 1.2.643.2.2.20.2 (OBJ_id_GostR3410_94_aBis) */,
+    847 /* 1.2.643.2.2.20.3 (OBJ_id_GostR3410_94_b) */,
+    848 /* 1.2.643.2.2.20.4 (OBJ_id_GostR3410_94_bBis) */,
+    821 /* 1.2.643.2.2.30.0 (OBJ_id_GostR3411_94_TestParamSet) */,
+    822 /* 1.2.643.2.2.30.1 (OBJ_id_GostR3411_94_CryptoProParamSet) */,
+    823 /* 1.2.643.2.2.31.0 (OBJ_id_Gost28147_89_TestParamSet) */,
+    824 /* 1.2.643.2.2.31.1 (OBJ_id_Gost28147_89_CryptoPro_A_ParamSet) */,
+    825 /* 1.2.643.2.2.31.2 (OBJ_id_Gost28147_89_CryptoPro_B_ParamSet) */,
+    826 /* 1.2.643.2.2.31.3 (OBJ_id_Gost28147_89_CryptoPro_C_ParamSet) */,
+    827 /* 1.2.643.2.2.31.4 (OBJ_id_Gost28147_89_CryptoPro_D_ParamSet) */,
+    828 /* 1.2.643.2.2.31.5 (OBJ_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet) */
+    ,
+    829 /* 1.2.643.2.2.31.6 (OBJ_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet) */
+    ,
+    830 /* 1.2.643.2.2.31.7 (OBJ_id_Gost28147_89_CryptoPro_RIC_1_ParamSet) */,
+    831 /* 1.2.643.2.2.32.0 (OBJ_id_GostR3410_94_TestParamSet) */,
+    832 /* 1.2.643.2.2.32.2 (OBJ_id_GostR3410_94_CryptoPro_A_ParamSet) */,
+    833 /* 1.2.643.2.2.32.3 (OBJ_id_GostR3410_94_CryptoPro_B_ParamSet) */,
+    834 /* 1.2.643.2.2.32.4 (OBJ_id_GostR3410_94_CryptoPro_C_ParamSet) */,
+    835 /* 1.2.643.2.2.32.5 (OBJ_id_GostR3410_94_CryptoPro_D_ParamSet) */,
+    836 /* 1.2.643.2.2.33.1 (OBJ_id_GostR3410_94_CryptoPro_XchA_ParamSet) */,
+    837 /* 1.2.643.2.2.33.2 (OBJ_id_GostR3410_94_CryptoPro_XchB_ParamSet) */,
+    838 /* 1.2.643.2.2.33.3 (OBJ_id_GostR3410_94_CryptoPro_XchC_ParamSet) */,
+    839 /* 1.2.643.2.2.35.0 (OBJ_id_GostR3410_2001_TestParamSet) */,
+    840 /* 1.2.643.2.2.35.1 (OBJ_id_GostR3410_2001_CryptoPro_A_ParamSet) */,
+    841 /* 1.2.643.2.2.35.2 (OBJ_id_GostR3410_2001_CryptoPro_B_ParamSet) */,
+    842 /* 1.2.643.2.2.35.3 (OBJ_id_GostR3410_2001_CryptoPro_C_ParamSet) */,
+    843 /* 1.2.643.2.2.36.0 (OBJ_id_GostR3410_2001_CryptoPro_XchA_ParamSet) */,
+    844 /* 1.2.643.2.2.36.1 (OBJ_id_GostR3410_2001_CryptoPro_XchB_ParamSet) */,
+    2 /* 1.2.840.113549.1 (OBJ_pkcs) */,
+    431 /* 1.2.840.10040.2.1 (OBJ_hold_instruction_none) */,
+    432 /* 1.2.840.10040.2.2 (OBJ_hold_instruction_call_issuer) */,
+    433 /* 1.2.840.10040.2.3 (OBJ_hold_instruction_reject) */,
+    116 /* 1.2.840.10040.4.1 (OBJ_dsa) */,
+    113 /* 1.2.840.10040.4.3 (OBJ_dsaWithSHA1) */,
+    406 /* 1.2.840.10045.1.1 (OBJ_X9_62_prime_field) */,
+    407 /* 1.2.840.10045.1.2 (OBJ_X9_62_characteristic_two_field) */,
+    408 /* 1.2.840.10045.2.1 (OBJ_X9_62_id_ecPublicKey) */,
+    416 /* 1.2.840.10045.4.1 (OBJ_ecdsa_with_SHA1) */,
+    791 /* 1.2.840.10045.4.2 (OBJ_ecdsa_with_Recommended) */,
+    792 /* 1.2.840.10045.4.3 (OBJ_ecdsa_with_Specified) */,
+    920 /* 1.2.840.10046.2.1 (OBJ_dhpublicnumber) */,
+    258 /* 1.3.6.1.5.5.7.0 (OBJ_id_pkix_mod) */,
+    175 /* 1.3.6.1.5.5.7.1 (OBJ_id_pe) */,
+    259 /* 1.3.6.1.5.5.7.2 (OBJ_id_qt) */,
+    128 /* 1.3.6.1.5.5.7.3 (OBJ_id_kp) */,
+    260 /* 1.3.6.1.5.5.7.4 (OBJ_id_it) */,
+    261 /* 1.3.6.1.5.5.7.5 (OBJ_id_pkip) */,
+    262 /* 1.3.6.1.5.5.7.6 (OBJ_id_alg) */,
+    263 /* 1.3.6.1.5.5.7.7 (OBJ_id_cmc) */,
+    264 /* 1.3.6.1.5.5.7.8 (OBJ_id_on) */,
+    265 /* 1.3.6.1.5.5.7.9 (OBJ_id_pda) */,
+    266 /* 1.3.6.1.5.5.7.10 (OBJ_id_aca) */,
+    267 /* 1.3.6.1.5.5.7.11 (OBJ_id_qcs) */,
+    268 /* 1.3.6.1.5.5.7.12 (OBJ_id_cct) */,
+    662 /* 1.3.6.1.5.5.7.21 (OBJ_id_ppl) */,
+    176 /* 1.3.6.1.5.5.7.48 (OBJ_id_ad) */,
+    507 /* 1.3.6.1.7.1.1.1 (OBJ_id_hex_partial_message) */,
+    508 /* 1.3.6.1.7.1.1.2 (OBJ_id_hex_multipart_message) */,
+    57 /* 2.16.840.1.113730 (OBJ_netscape) */,
+    754 /* 0.3.4401.5.3.1.9.1 (OBJ_camellia_128_ecb) */,
+    766 /* 0.3.4401.5.3.1.9.3 (OBJ_camellia_128_ofb128) */,
+    757 /* 0.3.4401.5.3.1.9.4 (OBJ_camellia_128_cfb128) */,
+    755 /* 0.3.4401.5.3.1.9.21 (OBJ_camellia_192_ecb) */,
+    767 /* 0.3.4401.5.3.1.9.23 (OBJ_camellia_192_ofb128) */,
+    758 /* 0.3.4401.5.3.1.9.24 (OBJ_camellia_192_cfb128) */,
+    756 /* 0.3.4401.5.3.1.9.41 (OBJ_camellia_256_ecb) */,
+    768 /* 0.3.4401.5.3.1.9.43 (OBJ_camellia_256_ofb128) */,
+    759 /* 0.3.4401.5.3.1.9.44 (OBJ_camellia_256_cfb128) */,
+    437 /* 0.9.2342.19200300.100 (OBJ_pilot) */,
+    776 /* 1.2.410.200004.1.3 (OBJ_seed_ecb) */,
+    777 /* 1.2.410.200004.1.4 (OBJ_seed_cbc) */,
+    779 /* 1.2.410.200004.1.5 (OBJ_seed_cfb128) */,
+    778 /* 1.2.410.200004.1.6 (OBJ_seed_ofb128) */,
+    852 /* 1.2.643.2.9.1.3.3 (OBJ_id_GostR3411_94_with_GostR3410_94_cc) */,
+    853 /* 1.2.643.2.9.1.3.4 (OBJ_id_GostR3411_94_with_GostR3410_2001_cc) */,
+    850 /* 1.2.643.2.9.1.5.3 (OBJ_id_GostR3410_94_cc) */,
+    851 /* 1.2.643.2.9.1.5.4 (OBJ_id_GostR3410_2001_cc) */,
+    849 /* 1.2.643.2.9.1.6.1 (OBJ_id_Gost28147_89_cc) */,
+    854 /* 1.2.643.2.9.1.8.1 (OBJ_id_GostR3410_2001_ParamSet_cc) */,
+    186 /* 1.2.840.113549.1.1 (OBJ_pkcs1) */,
+    27 /* 1.2.840.113549.1.3 (OBJ_pkcs3) */,
+    187 /* 1.2.840.113549.1.5 (OBJ_pkcs5) */,
+    20 /* 1.2.840.113549.1.7 (OBJ_pkcs7) */,
+    47 /* 1.2.840.113549.1.9 (OBJ_pkcs9) */,
+    3 /* 1.2.840.113549.2.2 (OBJ_md2) */,
+    257 /* 1.2.840.113549.2.4 (OBJ_md4) */,
+    4 /* 1.2.840.113549.2.5 (OBJ_md5) */,
+    797 /* 1.2.840.113549.2.6 (OBJ_hmacWithMD5) */,
+    163 /* 1.2.840.113549.2.7 (OBJ_hmacWithSHA1) */,
+    798 /* 1.2.840.113549.2.8 (OBJ_hmacWithSHA224) */,
+    799 /* 1.2.840.113549.2.9 (OBJ_hmacWithSHA256) */,
+    800 /* 1.2.840.113549.2.10 (OBJ_hmacWithSHA384) */,
+    801 /* 1.2.840.113549.2.11 (OBJ_hmacWithSHA512) */,
+    37 /* 1.2.840.113549.3.2 (OBJ_rc2_cbc) */,
+    5 /* 1.2.840.113549.3.4 (OBJ_rc4) */,
+    44 /* 1.2.840.113549.3.7 (OBJ_des_ede3_cbc) */,
+    120 /* 1.2.840.113549.3.8 (OBJ_rc5_cbc) */,
+    643 /* 1.2.840.113549.3.10 (OBJ_des_cdmf) */,
+    680 /* 1.2.840.10045.1.2.3 (OBJ_X9_62_id_characteristic_two_basis) */,
+    684 /* 1.2.840.10045.3.0.1 (OBJ_X9_62_c2pnb163v1) */,
+    685 /* 1.2.840.10045.3.0.2 (OBJ_X9_62_c2pnb163v2) */,
+    686 /* 1.2.840.10045.3.0.3 (OBJ_X9_62_c2pnb163v3) */,
+    687 /* 1.2.840.10045.3.0.4 (OBJ_X9_62_c2pnb176v1) */,
+    688 /* 1.2.840.10045.3.0.5 (OBJ_X9_62_c2tnb191v1) */,
+    689 /* 1.2.840.10045.3.0.6 (OBJ_X9_62_c2tnb191v2) */,
+    690 /* 1.2.840.10045.3.0.7 (OBJ_X9_62_c2tnb191v3) */,
+    691 /* 1.2.840.10045.3.0.8 (OBJ_X9_62_c2onb191v4) */,
+    692 /* 1.2.840.10045.3.0.9 (OBJ_X9_62_c2onb191v5) */,
+    693 /* 1.2.840.10045.3.0.10 (OBJ_X9_62_c2pnb208w1) */,
+    694 /* 1.2.840.10045.3.0.11 (OBJ_X9_62_c2tnb239v1) */,
+    695 /* 1.2.840.10045.3.0.12 (OBJ_X9_62_c2tnb239v2) */,
+    696 /* 1.2.840.10045.3.0.13 (OBJ_X9_62_c2tnb239v3) */,
+    697 /* 1.2.840.10045.3.0.14 (OBJ_X9_62_c2onb239v4) */,
+    698 /* 1.2.840.10045.3.0.15 (OBJ_X9_62_c2onb239v5) */,
+    699 /* 1.2.840.10045.3.0.16 (OBJ_X9_62_c2pnb272w1) */,
+    700 /* 1.2.840.10045.3.0.17 (OBJ_X9_62_c2pnb304w1) */,
+    701 /* 1.2.840.10045.3.0.18 (OBJ_X9_62_c2tnb359v1) */,
+    702 /* 1.2.840.10045.3.0.19 (OBJ_X9_62_c2pnb368w1) */,
+    703 /* 1.2.840.10045.3.0.20 (OBJ_X9_62_c2tnb431r1) */,
+    409 /* 1.2.840.10045.3.1.1 (OBJ_X9_62_prime192v1) */,
+    410 /* 1.2.840.10045.3.1.2 (OBJ_X9_62_prime192v2) */,
+    411 /* 1.2.840.10045.3.1.3 (OBJ_X9_62_prime192v3) */,
+    412 /* 1.2.840.10045.3.1.4 (OBJ_X9_62_prime239v1) */,
+    413 /* 1.2.840.10045.3.1.5 (OBJ_X9_62_prime239v2) */,
+    414 /* 1.2.840.10045.3.1.6 (OBJ_X9_62_prime239v3) */,
+    415 /* 1.2.840.10045.3.1.7 (OBJ_X9_62_prime256v1) */,
+    793 /* 1.2.840.10045.4.3.1 (OBJ_ecdsa_with_SHA224) */,
+    794 /* 1.2.840.10045.4.3.2 (OBJ_ecdsa_with_SHA256) */,
+    795 /* 1.2.840.10045.4.3.3 (OBJ_ecdsa_with_SHA384) */,
+    796 /* 1.2.840.10045.4.3.4 (OBJ_ecdsa_with_SHA512) */,
+    269 /* 1.3.6.1.5.5.7.0.1 (OBJ_id_pkix1_explicit_88) */,
+    270 /* 1.3.6.1.5.5.7.0.2 (OBJ_id_pkix1_implicit_88) */,
+    271 /* 1.3.6.1.5.5.7.0.3 (OBJ_id_pkix1_explicit_93) */,
+    272 /* 1.3.6.1.5.5.7.0.4 (OBJ_id_pkix1_implicit_93) */,
+    273 /* 1.3.6.1.5.5.7.0.5 (OBJ_id_mod_crmf) */,
+    274 /* 1.3.6.1.5.5.7.0.6 (OBJ_id_mod_cmc) */,
+    275 /* 1.3.6.1.5.5.7.0.7 (OBJ_id_mod_kea_profile_88) */,
+    276 /* 1.3.6.1.5.5.7.0.8 (OBJ_id_mod_kea_profile_93) */,
+    277 /* 1.3.6.1.5.5.7.0.9 (OBJ_id_mod_cmp) */,
+    278 /* 1.3.6.1.5.5.7.0.10 (OBJ_id_mod_qualified_cert_88) */,
+    279 /* 1.3.6.1.5.5.7.0.11 (OBJ_id_mod_qualified_cert_93) */,
+    280 /* 1.3.6.1.5.5.7.0.12 (OBJ_id_mod_attribute_cert) */,
+    281 /* 1.3.6.1.5.5.7.0.13 (OBJ_id_mod_timestamp_protocol) */,
+    282 /* 1.3.6.1.5.5.7.0.14 (OBJ_id_mod_ocsp) */,
+    283 /* 1.3.6.1.5.5.7.0.15 (OBJ_id_mod_dvcs) */,
+    284 /* 1.3.6.1.5.5.7.0.16 (OBJ_id_mod_cmp2000) */,
+    177 /* 1.3.6.1.5.5.7.1.1 (OBJ_info_access) */,
+    285 /* 1.3.6.1.5.5.7.1.2 (OBJ_biometricInfo) */,
+    286 /* 1.3.6.1.5.5.7.1.3 (OBJ_qcStatements) */,
+    287 /* 1.3.6.1.5.5.7.1.4 (OBJ_ac_auditEntity) */,
+    288 /* 1.3.6.1.5.5.7.1.5 (OBJ_ac_targeting) */,
+    289 /* 1.3.6.1.5.5.7.1.6 (OBJ_aaControls) */,
+    290 /* 1.3.6.1.5.5.7.1.7 (OBJ_sbgp_ipAddrBlock) */,
+    291 /* 1.3.6.1.5.5.7.1.8 (OBJ_sbgp_autonomousSysNum) */,
+    292 /* 1.3.6.1.5.5.7.1.9 (OBJ_sbgp_routerIdentifier) */,
+    397 /* 1.3.6.1.5.5.7.1.10 (OBJ_ac_proxying) */,
+    398 /* 1.3.6.1.5.5.7.1.11 (OBJ_sinfo_access) */,
+    663 /* 1.3.6.1.5.5.7.1.14 (OBJ_proxyCertInfo) */,
+    164 /* 1.3.6.1.5.5.7.2.1 (OBJ_id_qt_cps) */,
+    165 /* 1.3.6.1.5.5.7.2.2 (OBJ_id_qt_unotice) */,
+    293 /* 1.3.6.1.5.5.7.2.3 (OBJ_textNotice) */,
+    129 /* 1.3.6.1.5.5.7.3.1 (OBJ_server_auth) */,
+    130 /* 1.3.6.1.5.5.7.3.2 (OBJ_client_auth) */,
+    131 /* 1.3.6.1.5.5.7.3.3 (OBJ_code_sign) */,
+    132 /* 1.3.6.1.5.5.7.3.4 (OBJ_email_protect) */,
+    294 /* 1.3.6.1.5.5.7.3.5 (OBJ_ipsecEndSystem) */,
+    295 /* 1.3.6.1.5.5.7.3.6 (OBJ_ipsecTunnel) */,
+    296 /* 1.3.6.1.5.5.7.3.7 (OBJ_ipsecUser) */,
+    133 /* 1.3.6.1.5.5.7.3.8 (OBJ_time_stamp) */,
+    180 /* 1.3.6.1.5.5.7.3.9 (OBJ_OCSP_sign) */,
+    297 /* 1.3.6.1.5.5.7.3.10 (OBJ_dvcs) */,
+    298 /* 1.3.6.1.5.5.7.4.1 (OBJ_id_it_caProtEncCert) */,
+    299 /* 1.3.6.1.5.5.7.4.2 (OBJ_id_it_signKeyPairTypes) */,
+    300 /* 1.3.6.1.5.5.7.4.3 (OBJ_id_it_encKeyPairTypes) */,
+    301 /* 1.3.6.1.5.5.7.4.4 (OBJ_id_it_preferredSymmAlg) */,
+    302 /* 1.3.6.1.5.5.7.4.5 (OBJ_id_it_caKeyUpdateInfo) */,
+    303 /* 1.3.6.1.5.5.7.4.6 (OBJ_id_it_currentCRL) */,
+    304 /* 1.3.6.1.5.5.7.4.7 (OBJ_id_it_unsupportedOIDs) */,
+    305 /* 1.3.6.1.5.5.7.4.8 (OBJ_id_it_subscriptionRequest) */,
+    306 /* 1.3.6.1.5.5.7.4.9 (OBJ_id_it_subscriptionResponse) */,
+    307 /* 1.3.6.1.5.5.7.4.10 (OBJ_id_it_keyPairParamReq) */,
+    308 /* 1.3.6.1.5.5.7.4.11 (OBJ_id_it_keyPairParamRep) */,
+    309 /* 1.3.6.1.5.5.7.4.12 (OBJ_id_it_revPassphrase) */,
+    310 /* 1.3.6.1.5.5.7.4.13 (OBJ_id_it_implicitConfirm) */,
+    311 /* 1.3.6.1.5.5.7.4.14 (OBJ_id_it_confirmWaitTime) */,
+    312 /* 1.3.6.1.5.5.7.4.15 (OBJ_id_it_origPKIMessage) */,
+    784 /* 1.3.6.1.5.5.7.4.16 (OBJ_id_it_suppLangTags) */,
+    313 /* 1.3.6.1.5.5.7.5.1 (OBJ_id_regCtrl) */,
+    314 /* 1.3.6.1.5.5.7.5.2 (OBJ_id_regInfo) */,
+    323 /* 1.3.6.1.5.5.7.6.1 (OBJ_id_alg_des40) */,
+    324 /* 1.3.6.1.5.5.7.6.2 (OBJ_id_alg_noSignature) */,
+    325 /* 1.3.6.1.5.5.7.6.3 (OBJ_id_alg_dh_sig_hmac_sha1) */,
+    326 /* 1.3.6.1.5.5.7.6.4 (OBJ_id_alg_dh_pop) */,
+    327 /* 1.3.6.1.5.5.7.7.1 (OBJ_id_cmc_statusInfo) */,
+    328 /* 1.3.6.1.5.5.7.7.2 (OBJ_id_cmc_identification) */,
+    329 /* 1.3.6.1.5.5.7.7.3 (OBJ_id_cmc_identityProof) */,
+    330 /* 1.3.6.1.5.5.7.7.4 (OBJ_id_cmc_dataReturn) */,
+    331 /* 1.3.6.1.5.5.7.7.5 (OBJ_id_cmc_transactionId) */,
+    332 /* 1.3.6.1.5.5.7.7.6 (OBJ_id_cmc_senderNonce) */,
+    333 /* 1.3.6.1.5.5.7.7.7 (OBJ_id_cmc_recipientNonce) */,
+    334 /* 1.3.6.1.5.5.7.7.8 (OBJ_id_cmc_addExtensions) */,
+    335 /* 1.3.6.1.5.5.7.7.9 (OBJ_id_cmc_encryptedPOP) */,
+    336 /* 1.3.6.1.5.5.7.7.10 (OBJ_id_cmc_decryptedPOP) */,
+    337 /* 1.3.6.1.5.5.7.7.11 (OBJ_id_cmc_lraPOPWitness) */,
+    338 /* 1.3.6.1.5.5.7.7.15 (OBJ_id_cmc_getCert) */,
+    339 /* 1.3.6.1.5.5.7.7.16 (OBJ_id_cmc_getCRL) */,
+    340 /* 1.3.6.1.5.5.7.7.17 (OBJ_id_cmc_revokeRequest) */,
+    341 /* 1.3.6.1.5.5.7.7.18 (OBJ_id_cmc_regInfo) */,
+    342 /* 1.3.6.1.5.5.7.7.19 (OBJ_id_cmc_responseInfo) */,
+    343 /* 1.3.6.1.5.5.7.7.21 (OBJ_id_cmc_queryPending) */,
+    344 /* 1.3.6.1.5.5.7.7.22 (OBJ_id_cmc_popLinkRandom) */,
+    345 /* 1.3.6.1.5.5.7.7.23 (OBJ_id_cmc_popLinkWitness) */,
+    346 /* 1.3.6.1.5.5.7.7.24 (OBJ_id_cmc_confirmCertAcceptance) */,
+    347 /* 1.3.6.1.5.5.7.8.1 (OBJ_id_on_personalData) */,
+    858 /* 1.3.6.1.5.5.7.8.3 (OBJ_id_on_permanentIdentifier) */,
+    348 /* 1.3.6.1.5.5.7.9.1 (OBJ_id_pda_dateOfBirth) */,
+    349 /* 1.3.6.1.5.5.7.9.2 (OBJ_id_pda_placeOfBirth) */,
+    351 /* 1.3.6.1.5.5.7.9.3 (OBJ_id_pda_gender) */,
+    352 /* 1.3.6.1.5.5.7.9.4 (OBJ_id_pda_countryOfCitizenship) */,
+    353 /* 1.3.6.1.5.5.7.9.5 (OBJ_id_pda_countryOfResidence) */,
+    354 /* 1.3.6.1.5.5.7.10.1 (OBJ_id_aca_authenticationInfo) */,
+    355 /* 1.3.6.1.5.5.7.10.2 (OBJ_id_aca_accessIdentity) */,
+    356 /* 1.3.6.1.5.5.7.10.3 (OBJ_id_aca_chargingIdentity) */,
+    357 /* 1.3.6.1.5.5.7.10.4 (OBJ_id_aca_group) */,
+    358 /* 1.3.6.1.5.5.7.10.5 (OBJ_id_aca_role) */,
+    399 /* 1.3.6.1.5.5.7.10.6 (OBJ_id_aca_encAttrs) */,
+    359 /* 1.3.6.1.5.5.7.11.1 (OBJ_id_qcs_pkixQCSyntax_v1) */,
+    360 /* 1.3.6.1.5.5.7.12.1 (OBJ_id_cct_crs) */,
+    361 /* 1.3.6.1.5.5.7.12.2 (OBJ_id_cct_PKIData) */,
+    362 /* 1.3.6.1.5.5.7.12.3 (OBJ_id_cct_PKIResponse) */,
+    664 /* 1.3.6.1.5.5.7.21.0 (OBJ_id_ppl_anyLanguage) */,
+    665 /* 1.3.6.1.5.5.7.21.1 (OBJ_id_ppl_inheritAll) */,
+    667 /* 1.3.6.1.5.5.7.21.2 (OBJ_Independent) */,
+    178 /* 1.3.6.1.5.5.7.48.1 (OBJ_ad_OCSP) */,
+    179 /* 1.3.6.1.5.5.7.48.2 (OBJ_ad_ca_issuers) */,
+    363 /* 1.3.6.1.5.5.7.48.3 (OBJ_ad_timeStamping) */,
+    364 /* 1.3.6.1.5.5.7.48.4 (OBJ_ad_dvcs) */,
+    785 /* 1.3.6.1.5.5.7.48.5 (OBJ_caRepository) */,
+    780 /* 1.3.6.1.5.5.8.1.1 (OBJ_hmac_md5) */,
+    781 /* 1.3.6.1.5.5.8.1.2 (OBJ_hmac_sha1) */,
+    58 /* 2.16.840.1.113730.1 (OBJ_netscape_cert_extension) */,
+    59 /* 2.16.840.1.113730.2 (OBJ_netscape_data_type) */,
+    438 /* 0.9.2342.19200300.100.1 (OBJ_pilotAttributeType) */,
+    439 /* 0.9.2342.19200300.100.3 (OBJ_pilotAttributeSyntax) */,
+    440 /* 0.9.2342.19200300.100.4 (OBJ_pilotObjectClass) */,
+    441 /* 0.9.2342.19200300.100.10 (OBJ_pilotGroups) */,
+    108 /* 1.2.840.113533.7.66.10 (OBJ_cast5_cbc) */,
+    112 /* 1.2.840.113533.7.66.12 (OBJ_pbeWithMD5AndCast5_CBC) */,
+    782 /* 1.2.840.113533.7.66.13 (OBJ_id_PasswordBasedMAC) */,
+    783 /* 1.2.840.113533.7.66.30 (OBJ_id_DHBasedMac) */,
+    6 /* 1.2.840.113549.1.1.1 (OBJ_rsaEncryption) */,
+    7 /* 1.2.840.113549.1.1.2 (OBJ_md2WithRSAEncryption) */,
+    396 /* 1.2.840.113549.1.1.3 (OBJ_md4WithRSAEncryption) */,
+    8 /* 1.2.840.113549.1.1.4 (OBJ_md5WithRSAEncryption) */,
+    65 /* 1.2.840.113549.1.1.5 (OBJ_sha1WithRSAEncryption) */,
+    644 /* 1.2.840.113549.1.1.6 (OBJ_rsaOAEPEncryptionSET) */,
+    919 /* 1.2.840.113549.1.1.7 (OBJ_rsaesOaep) */,
+    911 /* 1.2.840.113549.1.1.8 (OBJ_mgf1) */,
+    935 /* 1.2.840.113549.1.1.9 (OBJ_pSpecified) */,
+    912 /* 1.2.840.113549.1.1.10 (OBJ_rsassaPss) */,
+    668 /* 1.2.840.113549.1.1.11 (OBJ_sha256WithRSAEncryption) */,
+    669 /* 1.2.840.113549.1.1.12 (OBJ_sha384WithRSAEncryption) */,
+    670 /* 1.2.840.113549.1.1.13 (OBJ_sha512WithRSAEncryption) */,
+    671 /* 1.2.840.113549.1.1.14 (OBJ_sha224WithRSAEncryption) */,
+    28 /* 1.2.840.113549.1.3.1 (OBJ_dhKeyAgreement) */,
+    9 /* 1.2.840.113549.1.5.1 (OBJ_pbeWithMD2AndDES_CBC) */,
+    10 /* 1.2.840.113549.1.5.3 (OBJ_pbeWithMD5AndDES_CBC) */,
+    168 /* 1.2.840.113549.1.5.4 (OBJ_pbeWithMD2AndRC2_CBC) */,
+    169 /* 1.2.840.113549.1.5.6 (OBJ_pbeWithMD5AndRC2_CBC) */,
+    170 /* 1.2.840.113549.1.5.10 (OBJ_pbeWithSHA1AndDES_CBC) */,
+    68 /* 1.2.840.113549.1.5.11 (OBJ_pbeWithSHA1AndRC2_CBC) */,
+    69 /* 1.2.840.113549.1.5.12 (OBJ_id_pbkdf2) */,
+    161 /* 1.2.840.113549.1.5.13 (OBJ_pbes2) */,
+    162 /* 1.2.840.113549.1.5.14 (OBJ_pbmac1) */,
+    21 /* 1.2.840.113549.1.7.1 (OBJ_pkcs7_data) */,
+    22 /* 1.2.840.113549.1.7.2 (OBJ_pkcs7_signed) */,
+    23 /* 1.2.840.113549.1.7.3 (OBJ_pkcs7_enveloped) */,
+    24 /* 1.2.840.113549.1.7.4 (OBJ_pkcs7_signedAndEnveloped) */,
+    25 /* 1.2.840.113549.1.7.5 (OBJ_pkcs7_digest) */,
+    26 /* 1.2.840.113549.1.7.6 (OBJ_pkcs7_encrypted) */,
+    48 /* 1.2.840.113549.1.9.1 (OBJ_pkcs9_emailAddress) */,
+    49 /* 1.2.840.113549.1.9.2 (OBJ_pkcs9_unstructuredName) */,
+    50 /* 1.2.840.113549.1.9.3 (OBJ_pkcs9_contentType) */,
+    51 /* 1.2.840.113549.1.9.4 (OBJ_pkcs9_messageDigest) */,
+    52 /* 1.2.840.113549.1.9.5 (OBJ_pkcs9_signingTime) */,
+    53 /* 1.2.840.113549.1.9.6 (OBJ_pkcs9_countersignature) */,
+    54 /* 1.2.840.113549.1.9.7 (OBJ_pkcs9_challengePassword) */,
+    55 /* 1.2.840.113549.1.9.8 (OBJ_pkcs9_unstructuredAddress) */,
+    56 /* 1.2.840.113549.1.9.9 (OBJ_pkcs9_extCertAttributes) */,
+    172 /* 1.2.840.113549.1.9.14 (OBJ_ext_req) */,
+    167 /* 1.2.840.113549.1.9.15 (OBJ_SMIMECapabilities) */,
+    188 /* 1.2.840.113549.1.9.16 (OBJ_SMIME) */,
+    156 /* 1.2.840.113549.1.9.20 (OBJ_friendlyName) */,
+    157 /* 1.2.840.113549.1.9.21 (OBJ_localKeyID) */,
+    681 /* 1.2.840.10045.1.2.3.1 (OBJ_X9_62_onBasis) */,
+    682 /* 1.2.840.10045.1.2.3.2 (OBJ_X9_62_tpBasis) */,
+    683 /* 1.2.840.10045.1.2.3.3 (OBJ_X9_62_ppBasis) */,
+    417 /* 1.3.6.1.4.1.311.17.1 (OBJ_ms_csp_name) */,
+    856 /* 1.3.6.1.4.1.311.17.2 (OBJ_LocalKeySet) */,
+    390 /* 1.3.6.1.4.1.1466.344 (OBJ_dcObject) */,
+    91 /* 1.3.6.1.4.1.3029.1.2 (OBJ_bf_cbc) */,
+    315 /* 1.3.6.1.5.5.7.5.1.1 (OBJ_id_regCtrl_regToken) */,
+    316 /* 1.3.6.1.5.5.7.5.1.2 (OBJ_id_regCtrl_authenticator) */,
+    317 /* 1.3.6.1.5.5.7.5.1.3 (OBJ_id_regCtrl_pkiPublicationInfo) */,
+    318 /* 1.3.6.1.5.5.7.5.1.4 (OBJ_id_regCtrl_pkiArchiveOptions) */,
+    319 /* 1.3.6.1.5.5.7.5.1.5 (OBJ_id_regCtrl_oldCertID) */,
+    320 /* 1.3.6.1.5.5.7.5.1.6 (OBJ_id_regCtrl_protocolEncrKey) */,
+    321 /* 1.3.6.1.5.5.7.5.2.1 (OBJ_id_regInfo_utf8Pairs) */,
+    322 /* 1.3.6.1.5.5.7.5.2.2 (OBJ_id_regInfo_certReq) */,
+    365 /* 1.3.6.1.5.5.7.48.1.1 (OBJ_id_pkix_OCSP_basic) */,
+    366 /* 1.3.6.1.5.5.7.48.1.2 (OBJ_id_pkix_OCSP_Nonce) */,
+    367 /* 1.3.6.1.5.5.7.48.1.3 (OBJ_id_pkix_OCSP_CrlID) */,
+    368 /* 1.3.6.1.5.5.7.48.1.4 (OBJ_id_pkix_OCSP_acceptableResponses) */,
+    369 /* 1.3.6.1.5.5.7.48.1.5 (OBJ_id_pkix_OCSP_noCheck) */,
+    370 /* 1.3.6.1.5.5.7.48.1.6 (OBJ_id_pkix_OCSP_archiveCutoff) */,
+    371 /* 1.3.6.1.5.5.7.48.1.7 (OBJ_id_pkix_OCSP_serviceLocator) */,
+    372 /* 1.3.6.1.5.5.7.48.1.8 (OBJ_id_pkix_OCSP_extendedStatus) */,
+    373 /* 1.3.6.1.5.5.7.48.1.9 (OBJ_id_pkix_OCSP_valid) */,
+    374 /* 1.3.6.1.5.5.7.48.1.10 (OBJ_id_pkix_OCSP_path) */,
+    375 /* 1.3.6.1.5.5.7.48.1.11 (OBJ_id_pkix_OCSP_trustRoot) */,
+    921 /* 1.3.36.3.3.2.8.1.1.1 (OBJ_brainpoolP160r1) */,
+    922 /* 1.3.36.3.3.2.8.1.1.2 (OBJ_brainpoolP160t1) */,
+    923 /* 1.3.36.3.3.2.8.1.1.3 (OBJ_brainpoolP192r1) */,
+    924 /* 1.3.36.3.3.2.8.1.1.4 (OBJ_brainpoolP192t1) */,
+    925 /* 1.3.36.3.3.2.8.1.1.5 (OBJ_brainpoolP224r1) */,
+    926 /* 1.3.36.3.3.2.8.1.1.6 (OBJ_brainpoolP224t1) */,
+    927 /* 1.3.36.3.3.2.8.1.1.7 (OBJ_brainpoolP256r1) */,
+    928 /* 1.3.36.3.3.2.8.1.1.8 (OBJ_brainpoolP256t1) */,
+    929 /* 1.3.36.3.3.2.8.1.1.9 (OBJ_brainpoolP320r1) */,
+    930 /* 1.3.36.3.3.2.8.1.1.10 (OBJ_brainpoolP320t1) */,
+    931 /* 1.3.36.3.3.2.8.1.1.11 (OBJ_brainpoolP384r1) */,
+    932 /* 1.3.36.3.3.2.8.1.1.12 (OBJ_brainpoolP384t1) */,
+    933 /* 1.3.36.3.3.2.8.1.1.13 (OBJ_brainpoolP512r1) */,
+    934 /* 1.3.36.3.3.2.8.1.1.14 (OBJ_brainpoolP512t1) */,
+    936 /* 1.3.133.16.840.63.0.2 (OBJ_dhSinglePass_stdDH_sha1kdf_scheme) */,
+    941 /* 1.3.133.16.840.63.0.3 (OBJ_dhSinglePass_cofactorDH_sha1kdf_scheme) */
+    ,
+    418 /* 2.16.840.1.101.3.4.1.1 (OBJ_aes_128_ecb) */,
+    419 /* 2.16.840.1.101.3.4.1.2 (OBJ_aes_128_cbc) */,
+    420 /* 2.16.840.1.101.3.4.1.3 (OBJ_aes_128_ofb128) */,
+    421 /* 2.16.840.1.101.3.4.1.4 (OBJ_aes_128_cfb128) */,
+    788 /* 2.16.840.1.101.3.4.1.5 (OBJ_id_aes128_wrap) */,
+    895 /* 2.16.840.1.101.3.4.1.6 (OBJ_aes_128_gcm) */,
+    896 /* 2.16.840.1.101.3.4.1.7 (OBJ_aes_128_ccm) */,
+    897 /* 2.16.840.1.101.3.4.1.8 (OBJ_id_aes128_wrap_pad) */,
+    422 /* 2.16.840.1.101.3.4.1.21 (OBJ_aes_192_ecb) */,
+    423 /* 2.16.840.1.101.3.4.1.22 (OBJ_aes_192_cbc) */,
+    424 /* 2.16.840.1.101.3.4.1.23 (OBJ_aes_192_ofb128) */,
+    425 /* 2.16.840.1.101.3.4.1.24 (OBJ_aes_192_cfb128) */,
+    789 /* 2.16.840.1.101.3.4.1.25 (OBJ_id_aes192_wrap) */,
+    898 /* 2.16.840.1.101.3.4.1.26 (OBJ_aes_192_gcm) */,
+    899 /* 2.16.840.1.101.3.4.1.27 (OBJ_aes_192_ccm) */,
+    900 /* 2.16.840.1.101.3.4.1.28 (OBJ_id_aes192_wrap_pad) */,
+    426 /* 2.16.840.1.101.3.4.1.41 (OBJ_aes_256_ecb) */,
+    427 /* 2.16.840.1.101.3.4.1.42 (OBJ_aes_256_cbc) */,
+    428 /* 2.16.840.1.101.3.4.1.43 (OBJ_aes_256_ofb128) */,
+    429 /* 2.16.840.1.101.3.4.1.44 (OBJ_aes_256_cfb128) */,
+    790 /* 2.16.840.1.101.3.4.1.45 (OBJ_id_aes256_wrap) */,
+    901 /* 2.16.840.1.101.3.4.1.46 (OBJ_aes_256_gcm) */,
+    902 /* 2.16.840.1.101.3.4.1.47 (OBJ_aes_256_ccm) */,
+    903 /* 2.16.840.1.101.3.4.1.48 (OBJ_id_aes256_wrap_pad) */,
+    672 /* 2.16.840.1.101.3.4.2.1 (OBJ_sha256) */,
+    673 /* 2.16.840.1.101.3.4.2.2 (OBJ_sha384) */,
+    674 /* 2.16.840.1.101.3.4.2.3 (OBJ_sha512) */,
+    675 /* 2.16.840.1.101.3.4.2.4 (OBJ_sha224) */,
+    802 /* 2.16.840.1.101.3.4.3.1 (OBJ_dsa_with_SHA224) */,
+    803 /* 2.16.840.1.101.3.4.3.2 (OBJ_dsa_with_SHA256) */,
+    71 /* 2.16.840.1.113730.1.1 (OBJ_netscape_cert_type) */,
+    72 /* 2.16.840.1.113730.1.2 (OBJ_netscape_base_url) */,
+    73 /* 2.16.840.1.113730.1.3 (OBJ_netscape_revocation_url) */,
+    74 /* 2.16.840.1.113730.1.4 (OBJ_netscape_ca_revocation_url) */,
+    75 /* 2.16.840.1.113730.1.7 (OBJ_netscape_renewal_url) */,
+    76 /* 2.16.840.1.113730.1.8 (OBJ_netscape_ca_policy_url) */,
+    77 /* 2.16.840.1.113730.1.12 (OBJ_netscape_ssl_server_name) */,
+    78 /* 2.16.840.1.113730.1.13 (OBJ_netscape_comment) */,
+    79 /* 2.16.840.1.113730.2.5 (OBJ_netscape_cert_sequence) */,
+    139 /* 2.16.840.1.113730.4.1 (OBJ_ns_sgc) */,
+    458 /* 0.9.2342.19200300.100.1.1 (OBJ_userId) */,
+    459 /* 0.9.2342.19200300.100.1.2 (OBJ_textEncodedORAddress) */,
+    460 /* 0.9.2342.19200300.100.1.3 (OBJ_rfc822Mailbox) */,
+    461 /* 0.9.2342.19200300.100.1.4 (OBJ_info) */,
+    462 /* 0.9.2342.19200300.100.1.5 (OBJ_favouriteDrink) */,
+    463 /* 0.9.2342.19200300.100.1.6 (OBJ_roomNumber) */,
+    464 /* 0.9.2342.19200300.100.1.7 (OBJ_photo) */,
+    465 /* 0.9.2342.19200300.100.1.8 (OBJ_userClass) */,
+    466 /* 0.9.2342.19200300.100.1.9 (OBJ_host) */,
+    467 /* 0.9.2342.19200300.100.1.10 (OBJ_manager) */,
+    468 /* 0.9.2342.19200300.100.1.11 (OBJ_documentIdentifier) */,
+    469 /* 0.9.2342.19200300.100.1.12 (OBJ_documentTitle) */,
+    470 /* 0.9.2342.19200300.100.1.13 (OBJ_documentVersion) */,
+    471 /* 0.9.2342.19200300.100.1.14 (OBJ_documentAuthor) */,
+    472 /* 0.9.2342.19200300.100.1.15 (OBJ_documentLocation) */,
+    473 /* 0.9.2342.19200300.100.1.20 (OBJ_homeTelephoneNumber) */,
+    474 /* 0.9.2342.19200300.100.1.21 (OBJ_secretary) */,
+    475 /* 0.9.2342.19200300.100.1.22 (OBJ_otherMailbox) */,
+    476 /* 0.9.2342.19200300.100.1.23 (OBJ_lastModifiedTime) */,
+    477 /* 0.9.2342.19200300.100.1.24 (OBJ_lastModifiedBy) */,
+    391 /* 0.9.2342.19200300.100.1.25 (OBJ_domainComponent) */,
+    478 /* 0.9.2342.19200300.100.1.26 (OBJ_aRecord) */,
+    479 /* 0.9.2342.19200300.100.1.27 (OBJ_pilotAttributeType27) */,
+    480 /* 0.9.2342.19200300.100.1.28 (OBJ_mXRecord) */,
+    481 /* 0.9.2342.19200300.100.1.29 (OBJ_nSRecord) */,
+    482 /* 0.9.2342.19200300.100.1.30 (OBJ_sOARecord) */,
+    483 /* 0.9.2342.19200300.100.1.31 (OBJ_cNAMERecord) */,
+    484 /* 0.9.2342.19200300.100.1.37 (OBJ_associatedDomain) */,
+    485 /* 0.9.2342.19200300.100.1.38 (OBJ_associatedName) */,
+    486 /* 0.9.2342.19200300.100.1.39 (OBJ_homePostalAddress) */,
+    487 /* 0.9.2342.19200300.100.1.40 (OBJ_personalTitle) */,
+    488 /* 0.9.2342.19200300.100.1.41 (OBJ_mobileTelephoneNumber) */,
+    489 /* 0.9.2342.19200300.100.1.42 (OBJ_pagerTelephoneNumber) */,
+    490 /* 0.9.2342.19200300.100.1.43 (OBJ_friendlyCountryName) */,
+    491 /* 0.9.2342.19200300.100.1.45 (OBJ_organizationalStatus) */,
+    492 /* 0.9.2342.19200300.100.1.46 (OBJ_janetMailbox) */,
+    493 /* 0.9.2342.19200300.100.1.47 (OBJ_mailPreferenceOption) */,
+    494 /* 0.9.2342.19200300.100.1.48 (OBJ_buildingName) */,
+    495 /* 0.9.2342.19200300.100.1.49 (OBJ_dSAQuality) */,
+    496 /* 0.9.2342.19200300.100.1.50 (OBJ_singleLevelQuality) */,
+    497 /* 0.9.2342.19200300.100.1.51 (OBJ_subtreeMinimumQuality) */,
+    498 /* 0.9.2342.19200300.100.1.52 (OBJ_subtreeMaximumQuality) */,
+    499 /* 0.9.2342.19200300.100.1.53 (OBJ_personalSignature) */,
+    500 /* 0.9.2342.19200300.100.1.54 (OBJ_dITRedirect) */,
+    501 /* 0.9.2342.19200300.100.1.55 (OBJ_audio) */,
+    502 /* 0.9.2342.19200300.100.1.56 (OBJ_documentPublisher) */,
+    442 /* 0.9.2342.19200300.100.3.4 (OBJ_iA5StringSyntax) */,
+    443 /* 0.9.2342.19200300.100.3.5 (OBJ_caseIgnoreIA5StringSyntax) */,
+    444 /* 0.9.2342.19200300.100.4.3 (OBJ_pilotObject) */,
+    445 /* 0.9.2342.19200300.100.4.4 (OBJ_pilotPerson) */,
+    446 /* 0.9.2342.19200300.100.4.5 (OBJ_account) */,
+    447 /* 0.9.2342.19200300.100.4.6 (OBJ_document) */,
+    448 /* 0.9.2342.19200300.100.4.7 (OBJ_room) */,
+    449 /* 0.9.2342.19200300.100.4.9 (OBJ_documentSeries) */,
+    392 /* 0.9.2342.19200300.100.4.13 (OBJ_Domain) */,
+    450 /* 0.9.2342.19200300.100.4.14 (OBJ_rFC822localPart) */,
+    451 /* 0.9.2342.19200300.100.4.15 (OBJ_dNSDomain) */,
+    452 /* 0.9.2342.19200300.100.4.17 (OBJ_domainRelatedObject) */,
+    453 /* 0.9.2342.19200300.100.4.18 (OBJ_friendlyCountry) */,
+    454 /* 0.9.2342.19200300.100.4.19 (OBJ_simpleSecurityObject) */,
+    455 /* 0.9.2342.19200300.100.4.20 (OBJ_pilotOrganization) */,
+    456 /* 0.9.2342.19200300.100.4.21 (OBJ_pilotDSA) */,
+    457 /* 0.9.2342.19200300.100.4.22 (OBJ_qualityLabelledData) */,
+    189 /* 1.2.840.113549.1.9.16.0 (OBJ_id_smime_mod) */,
+    190 /* 1.2.840.113549.1.9.16.1 (OBJ_id_smime_ct) */,
+    191 /* 1.2.840.113549.1.9.16.2 (OBJ_id_smime_aa) */,
+    192 /* 1.2.840.113549.1.9.16.3 (OBJ_id_smime_alg) */,
+    193 /* 1.2.840.113549.1.9.16.4 (OBJ_id_smime_cd) */,
+    194 /* 1.2.840.113549.1.9.16.5 (OBJ_id_smime_spq) */,
+    195 /* 1.2.840.113549.1.9.16.6 (OBJ_id_smime_cti) */,
+    158 /* 1.2.840.113549.1.9.22.1 (OBJ_x509Certificate) */,
+    159 /* 1.2.840.113549.1.9.22.2 (OBJ_sdsiCertificate) */,
+    160 /* 1.2.840.113549.1.9.23.1 (OBJ_x509Crl) */,
+    144 /* 1.2.840.113549.1.12.1.1 (OBJ_pbe_WithSHA1And128BitRC4) */,
+    145 /* 1.2.840.113549.1.12.1.2 (OBJ_pbe_WithSHA1And40BitRC4) */,
+    146 /* 1.2.840.113549.1.12.1.3 (OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC) */,
+    147 /* 1.2.840.113549.1.12.1.4 (OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC) */,
+    148 /* 1.2.840.113549.1.12.1.5 (OBJ_pbe_WithSHA1And128BitRC2_CBC) */,
+    149 /* 1.2.840.113549.1.12.1.6 (OBJ_pbe_WithSHA1And40BitRC2_CBC) */,
+    171 /* 1.3.6.1.4.1.311.2.1.14 (OBJ_ms_ext_req) */,
+    134 /* 1.3.6.1.4.1.311.2.1.21 (OBJ_ms_code_ind) */,
+    135 /* 1.3.6.1.4.1.311.2.1.22 (OBJ_ms_code_com) */,
+    136 /* 1.3.6.1.4.1.311.10.3.1 (OBJ_ms_ctl_sign) */,
+    137 /* 1.3.6.1.4.1.311.10.3.3 (OBJ_ms_sgc) */,
+    138 /* 1.3.6.1.4.1.311.10.3.4 (OBJ_ms_efs) */,
+    648 /* 1.3.6.1.4.1.311.20.2.2 (OBJ_ms_smartcard_login) */,
+    649 /* 1.3.6.1.4.1.311.20.2.3 (OBJ_ms_upn) */,
+    751 /* 1.2.392.200011.61.1.1.1.2 (OBJ_camellia_128_cbc) */,
+    752 /* 1.2.392.200011.61.1.1.1.3 (OBJ_camellia_192_cbc) */,
+    753 /* 1.2.392.200011.61.1.1.1.4 (OBJ_camellia_256_cbc) */,
+    907 /* 1.2.392.200011.61.1.1.3.2 (OBJ_id_camellia128_wrap) */,
+    908 /* 1.2.392.200011.61.1.1.3.3 (OBJ_id_camellia192_wrap) */,
+    909 /* 1.2.392.200011.61.1.1.3.4 (OBJ_id_camellia256_wrap) */,
+    196 /* 1.2.840.113549.1.9.16.0.1 (OBJ_id_smime_mod_cms) */,
+    197 /* 1.2.840.113549.1.9.16.0.2 (OBJ_id_smime_mod_ess) */,
+    198 /* 1.2.840.113549.1.9.16.0.3 (OBJ_id_smime_mod_oid) */,
+    199 /* 1.2.840.113549.1.9.16.0.4 (OBJ_id_smime_mod_msg_v3) */,
+    200 /* 1.2.840.113549.1.9.16.0.5 (OBJ_id_smime_mod_ets_eSignature_88) */,
+    201 /* 1.2.840.113549.1.9.16.0.6 (OBJ_id_smime_mod_ets_eSignature_97) */,
+    202 /* 1.2.840.113549.1.9.16.0.7 (OBJ_id_smime_mod_ets_eSigPolicy_88) */,
+    203 /* 1.2.840.113549.1.9.16.0.8 (OBJ_id_smime_mod_ets_eSigPolicy_97) */,
+    204 /* 1.2.840.113549.1.9.16.1.1 (OBJ_id_smime_ct_receipt) */,
+    205 /* 1.2.840.113549.1.9.16.1.2 (OBJ_id_smime_ct_authData) */,
+    206 /* 1.2.840.113549.1.9.16.1.3 (OBJ_id_smime_ct_publishCert) */,
+    207 /* 1.2.840.113549.1.9.16.1.4 (OBJ_id_smime_ct_TSTInfo) */,
+    208 /* 1.2.840.113549.1.9.16.1.5 (OBJ_id_smime_ct_TDTInfo) */,
+    209 /* 1.2.840.113549.1.9.16.1.6 (OBJ_id_smime_ct_contentInfo) */,
+    210 /* 1.2.840.113549.1.9.16.1.7 (OBJ_id_smime_ct_DVCSRequestData) */,
+    211 /* 1.2.840.113549.1.9.16.1.8 (OBJ_id_smime_ct_DVCSResponseData) */,
+    786 /* 1.2.840.113549.1.9.16.1.9 (OBJ_id_smime_ct_compressedData) */,
+    787 /* 1.2.840.113549.1.9.16.1.27 (OBJ_id_ct_asciiTextWithCRLF) */,
+    212 /* 1.2.840.113549.1.9.16.2.1 (OBJ_id_smime_aa_receiptRequest) */,
+    213 /* 1.2.840.113549.1.9.16.2.2 (OBJ_id_smime_aa_securityLabel) */,
+    214 /* 1.2.840.113549.1.9.16.2.3 (OBJ_id_smime_aa_mlExpandHistory) */,
+    215 /* 1.2.840.113549.1.9.16.2.4 (OBJ_id_smime_aa_contentHint) */,
+    216 /* 1.2.840.113549.1.9.16.2.5 (OBJ_id_smime_aa_msgSigDigest) */,
+    217 /* 1.2.840.113549.1.9.16.2.6 (OBJ_id_smime_aa_encapContentType) */,
+    218 /* 1.2.840.113549.1.9.16.2.7 (OBJ_id_smime_aa_contentIdentifier) */,
+    219 /* 1.2.840.113549.1.9.16.2.8 (OBJ_id_smime_aa_macValue) */,
+    220 /* 1.2.840.113549.1.9.16.2.9 (OBJ_id_smime_aa_equivalentLabels) */,
+    221 /* 1.2.840.113549.1.9.16.2.10 (OBJ_id_smime_aa_contentReference) */,
+    222 /* 1.2.840.113549.1.9.16.2.11 (OBJ_id_smime_aa_encrypKeyPref) */,
+    223 /* 1.2.840.113549.1.9.16.2.12 (OBJ_id_smime_aa_signingCertificate) */,
+    224 /* 1.2.840.113549.1.9.16.2.13 (OBJ_id_smime_aa_smimeEncryptCerts) */,
+    225 /* 1.2.840.113549.1.9.16.2.14 (OBJ_id_smime_aa_timeStampToken) */,
+    226 /* 1.2.840.113549.1.9.16.2.15 (OBJ_id_smime_aa_ets_sigPolicyId) */,
+    227 /* 1.2.840.113549.1.9.16.2.16 (OBJ_id_smime_aa_ets_commitmentType) */,
+    228 /* 1.2.840.113549.1.9.16.2.17 (OBJ_id_smime_aa_ets_signerLocation) */,
+    229 /* 1.2.840.113549.1.9.16.2.18 (OBJ_id_smime_aa_ets_signerAttr) */,
+    230 /* 1.2.840.113549.1.9.16.2.19 (OBJ_id_smime_aa_ets_otherSigCert) */,
+    231 /* 1.2.840.113549.1.9.16.2.20 (OBJ_id_smime_aa_ets_contentTimestamp) */,
+    232 /* 1.2.840.113549.1.9.16.2.21 (OBJ_id_smime_aa_ets_CertificateRefs) */,
+    233 /* 1.2.840.113549.1.9.16.2.22 (OBJ_id_smime_aa_ets_RevocationRefs) */,
+    234 /* 1.2.840.113549.1.9.16.2.23 (OBJ_id_smime_aa_ets_certValues) */,
+    235 /* 1.2.840.113549.1.9.16.2.24 (OBJ_id_smime_aa_ets_revocationValues) */,
+    236 /* 1.2.840.113549.1.9.16.2.25 (OBJ_id_smime_aa_ets_escTimeStamp) */,
+    237 /* 1.2.840.113549.1.9.16.2.26 (OBJ_id_smime_aa_ets_certCRLTimestamp) */,
+    238 /* 1.2.840.113549.1.9.16.2.27 (OBJ_id_smime_aa_ets_archiveTimeStamp) */,
+    239 /* 1.2.840.113549.1.9.16.2.28 (OBJ_id_smime_aa_signatureType) */,
+    240 /* 1.2.840.113549.1.9.16.2.29 (OBJ_id_smime_aa_dvcs_dvc) */,
+    241 /* 1.2.840.113549.1.9.16.3.1 (OBJ_id_smime_alg_ESDHwith3DES) */,
+    242 /* 1.2.840.113549.1.9.16.3.2 (OBJ_id_smime_alg_ESDHwithRC2) */,
+    243 /* 1.2.840.113549.1.9.16.3.3 (OBJ_id_smime_alg_3DESwrap) */,
+    244 /* 1.2.840.113549.1.9.16.3.4 (OBJ_id_smime_alg_RC2wrap) */,
+    245 /* 1.2.840.113549.1.9.16.3.5 (OBJ_id_smime_alg_ESDH) */,
+    246 /* 1.2.840.113549.1.9.16.3.6 (OBJ_id_smime_alg_CMS3DESwrap) */,
+    247 /* 1.2.840.113549.1.9.16.3.7 (OBJ_id_smime_alg_CMSRC2wrap) */,
+    125 /* 1.2.840.113549.1.9.16.3.8 (OBJ_zlib_compression) */,
+    893 /* 1.2.840.113549.1.9.16.3.9 (OBJ_id_alg_PWRI_KEK) */,
+    248 /* 1.2.840.113549.1.9.16.4.1 (OBJ_id_smime_cd_ldap) */,
+    249 /* 1.2.840.113549.1.9.16.5.1 (OBJ_id_smime_spq_ets_sqt_uri) */,
+    250 /* 1.2.840.113549.1.9.16.5.2 (OBJ_id_smime_spq_ets_sqt_unotice) */,
+    251 /* 1.2.840.113549.1.9.16.6.1 (OBJ_id_smime_cti_ets_proofOfOrigin) */,
+    252 /* 1.2.840.113549.1.9.16.6.2 (OBJ_id_smime_cti_ets_proofOfReceipt) */,
+    253 /* 1.2.840.113549.1.9.16.6.3 (OBJ_id_smime_cti_ets_proofOfDelivery) */,
+    254 /* 1.2.840.113549.1.9.16.6.4 (OBJ_id_smime_cti_ets_proofOfSender) */,
+    255 /* 1.2.840.113549.1.9.16.6.5 (OBJ_id_smime_cti_ets_proofOfApproval) */,
+    256 /* 1.2.840.113549.1.9.16.6.6 (OBJ_id_smime_cti_ets_proofOfCreation) */,
+    150 /* 1.2.840.113549.1.12.10.1.1 (OBJ_keyBag) */,
+    151 /* 1.2.840.113549.1.12.10.1.2 (OBJ_pkcs8ShroudedKeyBag) */,
+    152 /* 1.2.840.113549.1.12.10.1.3 (OBJ_certBag) */,
+    153 /* 1.2.840.113549.1.12.10.1.4 (OBJ_crlBag) */,
+    154 /* 1.2.840.113549.1.12.10.1.5 (OBJ_secretBag) */,
+    155 /* 1.2.840.113549.1.12.10.1.6 (OBJ_safeContentsBag) */,
+    34 /* 1.3.6.1.4.1.188.7.1.1.2 (OBJ_idea_cbc) */,
 };
-
diff --git a/src/crypto/obj/obj_dat.pl b/src/crypto/obj/obj_dat.pl
deleted file mode 100644
index 201ec72..0000000
--- a/src/crypto/obj/obj_dat.pl
+++ /dev/null
@@ -1,309 +0,0 @@
-#!/usr/bin/env perl
-
-# fixes bug in floating point emulation on sparc64 when
-# this script produces off-by-one output on sparc64
-use integer;
-
-if (scalar @ARGV != 2)
-	{
-	print "Usage: perl obj_dat.pl ../../include/openssl/obj_mac.h obj_dat.h\n";
-	exit 1;
-	}
-
-sub obj_cmp
-	{
-	local(@a,@b,$_,$r);
-
-	$A=$obj_len{$obj{$nid{$a}}};
-	$B=$obj_len{$obj{$nid{$b}}};
-
-	$r=($A-$B);
-	return($r) if $r != 0;
-
-	$A=$obj_der{$obj{$nid{$a}}};
-	$B=$obj_der{$obj{$nid{$b}}};
-
-	return($A cmp $B);
-	}
-
-sub expand_obj
-	{
-	local(*v)=@_;
-	local($k,$d);
-	local($i);
-
-	do	{
-		$i=0;
-		foreach $k (keys %v)
-			{
-			if (($v{$k} =~ s/(OBJ_[^,]+),/$v{$1},/))
-				{ $i++; }
-			}
-		} while($i);
-	foreach $k (keys %v)
-		{
-		@a=split(/,/,$v{$k});
-		$objn{$k}=$#a+1;
-		}
-	return(%objn);
-	}
-
-open (IN,"$ARGV[0]") || die "Can't open input file $ARGV[0]";
-open (OUT,">$ARGV[1]") || die "Can't open output file $ARGV[1]";
-
-while (<IN>)
-	{
-	next unless /^\#define\s+(\S+)\s+(.*)$/;
-	$v=$1;
-	$d=$2;
-	$d =~ s/^\"//;
-	$d =~ s/\"$//;
-	if ($v =~ /^SN_(.*)$/)
-		{
-		if(defined $snames{$d})
-			{
-			print "WARNING: Duplicate short name \"$d\"\n";
-			}
-		else 
-			{ $snames{$d} = "X"; }
-		$sn{$1}=$d;
-		}
-	elsif ($v =~ /^LN_(.*)$/)
-		{
-		if(defined $lnames{$d})
-			{
-			print "WARNING: Duplicate long name \"$d\"\n";
-			}
-		else 
-			{ $lnames{$d} = "X"; }
-		$ln{$1}=$d;
-		}
-	elsif ($v =~ /^NID_(.*)$/)
-		{ $nid{$d}=$1; }
-	elsif ($v =~ /^OBJ_(.*)$/)
-		{
-		$obj{$1}=$v;
-		$objd{$v}=$d;
-		}
-	}
-close IN;
-
-%ob=&expand_obj(*objd);
-
-@a=sort { $a <=> $b } keys %nid;
-$n=$a[$#a]+1;
-
-@lvalues=();
-$lvalues=0;
-
-for ($i=0; $i<$n; $i++)
-	{
-	if (!defined($nid{$i}))
-		{
-		push(@out,"{NULL,NULL,NID_undef,0,NULL,0},\n");
-		}
-	else
-		{
-		$sn=defined($sn{$nid{$i}})?"$sn{$nid{$i}}":"NULL";
-		$ln=defined($ln{$nid{$i}})?"$ln{$nid{$i}}":"NULL";
-
-		if ($sn eq "NULL") {
-			$sn=$ln;
-			$sn{$nid{$i}} = $ln;
-		}
-
-		if ($ln eq "NULL") {
-			$ln=$sn;
-			$ln{$nid{$i}} = $sn;
-		}
-			
-		$out ="{";
-		$out.="\"$sn\"";
-		$out.=","."\"$ln\"";
-		$out.=",NID_$nid{$i},";
-		if (defined($obj{$nid{$i}}) && $objd{$obj{$nid{$i}}} =~ /,/)
-			{
-			$v=$objd{$obj{$nid{$i}}};
-			$v =~ s/L//g;
-			$v =~ s/,/ /g;
-			$r=&der_it($v);
-			$z="";
-			$length=0;
-			foreach (unpack("C*",$r))
-				{
-				$z.=sprintf("0x%02X,",$_);
-				$length++;
-				}
-			$obj_der{$obj{$nid{$i}}}=$z;
-			$obj_len{$obj{$nid{$i}}}=$length;
-
-			push(@lvalues,sprintf("%-45s/* [%3d] %s */\n",
-				$z,$lvalues,$obj{$nid{$i}}));
-			$out.="$length,&(lvalues[$lvalues]),0";
-			$lvalues+=$length;
-			}
-		else
-			{
-			$out.="0,NULL,0";
-			}
-		$out.="},\n";
-		push(@out,$out);
-		}
-	}
-
-@a=grep(defined($sn{$nid{$_}}),0 .. $n);
-foreach (sort { $sn{$nid{$a}} cmp $sn{$nid{$b}} } @a)
-	{
-	push(@sn,sprintf("%2d,\t/* \"$sn{$nid{$_}}\" */\n",$_));
-	}
-
-@a=grep(defined($ln{$nid{$_}}),0 .. $n);
-foreach (sort { $ln{$nid{$a}} cmp $ln{$nid{$b}} } @a)
-	{
-	push(@ln,sprintf("%2d,\t/* \"$ln{$nid{$_}}\" */\n",$_));
-	}
-
-@a=grep(defined($obj{$nid{$_}}),0 .. $n);
-foreach (sort obj_cmp @a)
-	{
-	$m=$obj{$nid{$_}};
-	$v=$objd{$m};
-	$v =~ s/L//g;
-	$v =~ s/,/ /g;
-	push(@ob,sprintf("%2d,\t/* %-32s %s */\n",$_,$m,$v));
-	}
-
-print OUT <<'EOF';
-/* THIS FILE IS GENERATED FROM objects.h by obj_dat.pl via the
- * following command:
- * perl obj_dat.pl ../../include/openssl/obj_mac.h obj_dat.h */
-
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to.  The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *    "This product includes cryptographic software written by
- *     Eric Young (eay@cryptsoft.com)"
- *    The word 'cryptographic' can be left out if the rouines from the library
- *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- *    the apps directory (application code) you must include an acknowledgement:
- *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed.  i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.] */
-
-EOF
-
-printf OUT "#define NUM_NID %d\n",$n;
-printf OUT "#define NUM_SN %d\n",$#sn+1;
-printf OUT "#define NUM_LN %d\n",$#ln+1;
-printf OUT "#define NUM_OBJ %d\n\n",$#ob+1;
-
-printf OUT "static const unsigned char lvalues[%d]={\n",$lvalues+1;
-print OUT @lvalues;
-print OUT "};\n\n";
-
-printf OUT "static const ASN1_OBJECT kObjects[NUM_NID]={\n";
-foreach (@out)
-	{
-	if (length($_) > 75)
-		{
-		$out="";
-		foreach (split(/,/))
-			{
-			$t=$out.$_.",";
-			if (length($t) > 70)
-				{
-				print OUT "$out\n";
-				$t="\t$_,";
-				}
-			$out=$t;
-			}
-		chop $out;
-		print OUT "$out";
-		}
-	else
-		{ print OUT $_; }
-	}
-print  OUT "};\n\n";
-
-printf OUT "static const unsigned int kNIDsInShortNameOrder[NUM_SN]={\n";
-print  OUT @sn;
-print  OUT "};\n\n";
-
-printf OUT "static const unsigned int kNIDsInLongNameOrder[NUM_LN]={\n";
-print  OUT @ln;
-print  OUT "};\n\n";
-
-printf OUT "static const unsigned int kNIDsInOIDOrder[NUM_OBJ]={\n";
-print  OUT @ob;
-print  OUT "};\n\n";
-
-close OUT;
-
-sub der_it
-	{
-	local($v)=@_;
-	local(@a,$i,$ret,@r);
-
-	@a=split(/\s+/,$v);
-	$ret.=pack("C*",$a[0]*40+$a[1]);
-	shift @a;
-	shift @a;
-	foreach (@a)
-		{
-		@r=();
-		$t=0;
-		while ($_ >= 128)
-			{
-			$x=$_%128;
-			$_/=128;
-			push(@r,((($t++)?0x80:0)|$x));
-			}
-		push(@r,((($t++)?0x80:0)|$_));
-		$ret.=pack("C*",reverse(@r));
-		}
-	return($ret);
-	}
diff --git a/src/crypto/obj/obj_mac.num b/src/crypto/obj/obj_mac.num
index a0e09b8..ef19a6d 100644
--- a/src/crypto/obj/obj_mac.num
+++ b/src/crypto/obj/obj_mac.num
@@ -100,7 +100,6 @@
 givenName		99
 surname		100
 initials		101
-uniqueIdentifier		102
 crl_distribution_points		103
 md5WithRSA		104
 serialNumber		105
@@ -121,7 +120,6 @@
 rc5_ecb		121
 rc5_cfb64		122
 rc5_ofb64		123
-rle_compression		124
 zlib_compression		125
 ext_key_usage		126
 id_pkix		127
@@ -347,7 +345,6 @@
 id_on_personalData		347
 id_pda_dateOfBirth		348
 id_pda_placeOfBirth		349
-id_pda_pseudonym		350
 id_pda_gender		351
 id_pda_countryOfCitizenship		352
 id_pda_countryOfResidence		353
@@ -390,7 +387,6 @@
 dcObject		390
 domainComponent		391
 Domain		392
-joint_iso_ccitt		393
 selected_attribute_types		394
 clearance		395
 md4WithRSAEncryption		396
@@ -401,7 +397,6 @@
 policy_constraints		401
 target_information		402
 no_rev_avail		403
-ccitt		404
 ansi_X9_62		405
 X9_62_prime_field		406
 X9_62_characteristic_two_field		407
@@ -508,7 +503,6 @@
 id_hex_multipart_message		508
 generationQualifier		509
 pseudonym		510
-InternationalRA		511
 id_set		512
 set_ctype		513
 set_msgExt		514
@@ -769,10 +763,7 @@
 subject_directory_attributes		769
 issuing_distribution_point		770
 certificate_issuer		771
-korea		772
 kisa		773
-kftc		774
-npki_alg		775
 seed_ecb		776
 seed_cbc		777
 seed_ofb128		778
@@ -945,4 +936,4 @@
 dhSinglePass_cofactorDH_sha512kdf_scheme		945
 dh_std_kdf		946
 dh_cofactor_kdf		947
-x25519		948
+X25519		948
diff --git a/src/crypto/obj/obj_test.cc b/src/crypto/obj/obj_test.cc
new file mode 100644
index 0000000..6c9dc3f
--- /dev/null
+++ b/src/crypto/obj/obj_test.cc
@@ -0,0 +1,244 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/asn1.h>
+#include <openssl/bytestring.h>
+#include <openssl/crypto.h>
+#include <openssl/obj.h>
+
+#include "../internal.h"
+
+
+static bool TestBasic() {
+  static const int kNID = NID_sha256WithRSAEncryption;
+  static const char kShortName[] = "RSA-SHA256";
+  static const char kLongName[] = "sha256WithRSAEncryption";
+  static const char kText[] = "1.2.840.113549.1.1.11";
+  static const uint8_t kDER[] = {
+      0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
+  };
+
+  CBS cbs;
+  CBS_init(&cbs, kDER, sizeof(kDER));
+  if (OBJ_cbs2nid(&cbs) != kNID ||
+      OBJ_sn2nid(kShortName) != kNID ||
+      OBJ_ln2nid(kLongName) != kNID ||
+      OBJ_txt2nid(kShortName) != kNID ||
+      OBJ_txt2nid(kLongName) != kNID ||
+      OBJ_txt2nid(kText) != kNID) {
+    return false;
+  }
+
+  if (strcmp(kShortName, OBJ_nid2sn(kNID)) != 0 ||
+      strcmp(kLongName, OBJ_nid2ln(kNID)) != 0) {
+    return false;
+  }
+
+  if (OBJ_sn2nid("this is not an OID") != NID_undef ||
+      OBJ_ln2nid("this is not an OID") != NID_undef ||
+      OBJ_txt2nid("this is not an OID") != NID_undef) {
+    return false;
+  }
+
+  CBS_init(&cbs, NULL, 0);
+  if (OBJ_cbs2nid(&cbs) != NID_undef) {
+    return false;
+  }
+
+  // 1.2.840.113554.4.1.72585.2 (https://davidben.net/oid).
+  static const uint8_t kUnknownDER[] = {
+      0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01, 0x84, 0xb7, 0x09, 0x02,
+  };
+  CBS_init(&cbs, kUnknownDER, sizeof(kUnknownDER));
+  if (OBJ_cbs2nid(&cbs) != NID_undef) {
+    return false;
+  }
+
+  return true;
+}
+
+static bool TestSignatureAlgorithms() {
+  int digest_nid, pkey_nid;
+  if (!OBJ_find_sigid_algs(NID_sha256WithRSAEncryption, &digest_nid,
+                           &pkey_nid) ||
+      digest_nid != NID_sha256 || pkey_nid != NID_rsaEncryption) {
+    return false;
+  }
+
+  if (OBJ_find_sigid_algs(NID_sha256, &digest_nid, &pkey_nid)) {
+    return false;
+  }
+
+  int sign_nid;
+  if (!OBJ_find_sigid_by_algs(&sign_nid, NID_sha256, NID_rsaEncryption) ||
+      sign_nid != NID_sha256WithRSAEncryption) {
+    return false;
+  }
+
+  if (OBJ_find_sigid_by_algs(&sign_nid, NID_dsa, NID_rsaEncryption)) {
+    return false;
+  }
+
+  return true;
+}
+
+static bool ExpectObj2Txt(const uint8_t *der, size_t der_len,
+                          bool always_return_oid, const char *expected) {
+  ASN1_OBJECT obj;
+  OPENSSL_memset(&obj, 0, sizeof(obj));
+  obj.data = der;
+  obj.length = static_cast<int>(der_len);
+
+  int expected_len = static_cast<int>(strlen(expected));
+
+  int len = OBJ_obj2txt(nullptr, 0, &obj, always_return_oid);
+  if (len != expected_len) {
+    fprintf(stderr,
+            "OBJ_obj2txt of %s with out_len = 0 returned %d, wanted %d.\n",
+            expected, len, expected_len);
+    return false;
+  }
+
+  char short_buf[1];
+  OPENSSL_memset(short_buf, 0xff, sizeof(short_buf));
+  len = OBJ_obj2txt(short_buf, sizeof(short_buf), &obj, always_return_oid);
+  if (len != expected_len) {
+    fprintf(stderr,
+            "OBJ_obj2txt of %s with out_len = 1 returned %d, wanted %d.\n",
+            expected, len, expected_len);
+    return false;
+  }
+
+  if (OPENSSL_memchr(short_buf, '\0', sizeof(short_buf)) == nullptr) {
+    fprintf(stderr,
+            "OBJ_obj2txt of %s with out_len = 1 did not NUL-terminate the "
+            "output.\n",
+            expected);
+    return false;
+  }
+
+  char buf[256];
+  len = OBJ_obj2txt(buf, sizeof(buf), &obj, always_return_oid);
+  if (len != expected_len) {
+    fprintf(stderr,
+            "OBJ_obj2txt of %s with out_len = 256 returned %d, wanted %d.\n",
+            expected, len, expected_len);
+    return false;
+  }
+
+  if (strcmp(buf, expected) != 0) {
+    fprintf(stderr, "OBJ_obj2txt returned \"%s\"; wanted \"%s\".\n", buf,
+            expected);
+    return false;
+  }
+
+  return true;
+}
+
+static bool TestObj2Txt() {
+  // kSHA256WithRSAEncryption is the DER representation of
+  // 1.2.840.113549.1.1.11, id-sha256WithRSAEncryption.
+  static const uint8_t kSHA256WithRSAEncryption[] = {
+      0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b,
+  };
+
+  // kBasicConstraints is the DER representation of 2.5.29.19,
+  // id-basicConstraints.
+  static const uint8_t kBasicConstraints[] = {
+      0x55, 0x1d, 0x13,
+  };
+
+  // kTestOID is the DER representation of 1.2.840.113554.4.1.72585.0,
+  // from https://davidben.net/oid.
+  static const uint8_t kTestOID[] = {
+      0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01, 0x84, 0xb7, 0x09, 0x00,
+  };
+
+  if (!ExpectObj2Txt(kSHA256WithRSAEncryption, sizeof(kSHA256WithRSAEncryption),
+                     true /* don't return name */, "1.2.840.113549.1.1.11") ||
+      !ExpectObj2Txt(kSHA256WithRSAEncryption, sizeof(kSHA256WithRSAEncryption),
+                     false /* return name */, "sha256WithRSAEncryption") ||
+      !ExpectObj2Txt(kBasicConstraints, sizeof(kBasicConstraints),
+                     true /* don't return name */, "2.5.29.19") ||
+      !ExpectObj2Txt(kBasicConstraints, sizeof(kBasicConstraints),
+                     false /* return name */, "X509v3 Basic Constraints") ||
+      !ExpectObj2Txt(kTestOID, sizeof(kTestOID), true /* don't return name */,
+                     "1.2.840.113554.4.1.72585.0") ||
+      !ExpectObj2Txt(kTestOID, sizeof(kTestOID), false /* return name */,
+                     "1.2.840.113554.4.1.72585.0") ||
+      // Python depends on the empty OID successfully encoding as the empty
+      // string.
+      !ExpectObj2Txt(nullptr, 0, false /* return name */, "") ||
+      !ExpectObj2Txt(nullptr, 0, true /* don't return name */, "")) {
+    return false;
+  }
+
+  ASN1_OBJECT obj;
+  OPENSSL_memset(&obj, 0, sizeof(obj));
+
+  // kNonMinimalOID is kBasicConstraints with the final component non-minimally
+  // encoded.
+  static const uint8_t kNonMinimalOID[] = {
+      0x55, 0x1d, 0x80, 0x13,
+  };
+  obj.data = kNonMinimalOID;
+  obj.length = sizeof(kNonMinimalOID);
+  if (OBJ_obj2txt(NULL, 0, &obj, 0) != -1) {
+    fprintf(stderr, "OBJ_obj2txt accepted non-minimal OIDs.\n");
+    return false;
+  }
+
+  // kOverflowOID is the DER representation of
+  // 1.2.840.113554.4.1.72585.18446744073709551616. (The final value is 2^64.)
+  static const uint8_t kOverflowOID[] = {
+      0x2a, 0x86, 0x48, 0x86, 0xf7, 0x12, 0x04, 0x01, 0x84, 0xb7, 0x09,
+      0x82, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00,
+  };
+  obj.data = kOverflowOID;
+  obj.length = sizeof(kOverflowOID);
+  if (OBJ_obj2txt(NULL, 0, &obj, 0) != -1) {
+    fprintf(stderr, "OBJ_obj2txt accepted an OID with a large component.\n");
+    return false;
+  }
+
+  // kInvalidOID is a mis-encoded version of kBasicConstraints with the final
+  // octet having the high bit set.
+  static const uint8_t kInvalidOID[] = {
+      0x55, 0x1d, 0x93,
+  };
+  obj.data = kInvalidOID;
+  obj.length = sizeof(kInvalidOID);
+  if (OBJ_obj2txt(NULL, 0, &obj, 0) != -1) {
+    fprintf(stderr, "OBJ_obj2txt accepted a mis-encoded OID.\n");
+    return false;
+  }
+
+  return true;
+}
+
+int main() {
+  CRYPTO_library_init();
+
+  if (!TestBasic() ||
+      !TestSignatureAlgorithms() ||
+      !TestObj2Txt()) {
+    return 1;
+  }
+
+  printf("PASS\n");
+  return 0;
+}
diff --git a/src/crypto/obj/obj_xref.c b/src/crypto/obj/obj_xref.c
index 70babea..7b4ff12 100644
--- a/src/crypto/obj/obj_xref.c
+++ b/src/crypto/obj/obj_xref.c
@@ -56,69 +56,67 @@
 
 #include <openssl/obj.h>
 
-#include <stdlib.h>
-
-#include "obj_xref.h"
+#include "../internal.h"
 
 
-static int nid_triple_cmp_by_sign_id(const void *in_a, const void *in_b) {
-  const nid_triple *a = in_a;
-  const nid_triple *b = in_b;
+typedef struct {
+  int sign_nid;
+  int digest_nid;
+  int pkey_nid;
+} nid_triple;
 
-  return a->sign_id - b->sign_id;
-}
+static const nid_triple kTriples[] = {
+    /* RSA PKCS#1. */
+    {NID_md4WithRSAEncryption, NID_md4, NID_rsaEncryption},
+    {NID_md5WithRSAEncryption, NID_md5, NID_rsaEncryption},
+    {NID_sha1WithRSAEncryption, NID_sha1, NID_rsaEncryption},
+    {NID_sha224WithRSAEncryption, NID_sha224, NID_rsaEncryption},
+    {NID_sha256WithRSAEncryption, NID_sha256, NID_rsaEncryption},
+    {NID_sha384WithRSAEncryption, NID_sha384, NID_rsaEncryption},
+    {NID_sha512WithRSAEncryption, NID_sha512, NID_rsaEncryption},
+    /* DSA. */
+    {NID_dsaWithSHA1, NID_sha1, NID_dsa},
+    {NID_dsaWithSHA1_2, NID_sha1, NID_dsa_2},
+    {NID_dsa_with_SHA224, NID_sha224, NID_dsa},
+    {NID_dsa_with_SHA256, NID_sha256, NID_dsa},
+    /* ECDSA. */
+    {NID_ecdsa_with_SHA1, NID_sha1, NID_X9_62_id_ecPublicKey},
+    {NID_ecdsa_with_SHA224, NID_sha224, NID_X9_62_id_ecPublicKey},
+    {NID_ecdsa_with_SHA256, NID_sha256, NID_X9_62_id_ecPublicKey},
+    {NID_ecdsa_with_SHA384, NID_sha384, NID_X9_62_id_ecPublicKey},
+    {NID_ecdsa_with_SHA512, NID_sha512, NID_X9_62_id_ecPublicKey},
+    /* For PSS the digest algorithm can vary and depends on the included
+     * AlgorithmIdentifier. The digest "undef" indicates the public key method
+     * should handle this explicitly. */
+    {NID_rsassaPss, NID_undef, NID_rsaEncryption},
+};
 
 int OBJ_find_sigid_algs(int sign_nid, int *out_digest_nid, int *out_pkey_nid) {
-  nid_triple key;
-  const nid_triple *triple;
-
-  key.sign_id = sign_nid;
-
-  triple = bsearch(&key, sigoid_srt, sizeof(sigoid_srt) / sizeof(nid_triple),
-                   sizeof(nid_triple), nid_triple_cmp_by_sign_id);
-
-  if (triple == NULL) {
-    return 0;
-  }
-  if (out_digest_nid) {
-    *out_digest_nid = triple->hash_id;
-  }
-  if (out_pkey_nid) {
-    *out_pkey_nid = triple->pkey_id;
+  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kTriples); i++) {
+    if (kTriples[i].sign_nid == sign_nid) {
+      if (out_digest_nid != NULL) {
+        *out_digest_nid = kTriples[i].digest_nid;
+      }
+      if (out_pkey_nid != NULL) {
+        *out_pkey_nid = kTriples[i].pkey_nid;
+      }
+      return 1;
+    }
   }
 
-  return 1;
-}
-
-static int nid_triple_cmp_by_digest_and_hash(const void *in_a,
-                                             const void *in_b) {
-  const nid_triple *a = *((nid_triple**) in_a);
-  const nid_triple *b = *((nid_triple**) in_b);
-
-  int ret = a->hash_id - b->hash_id;
-  if (ret) {
-    return ret;
-  }
-  return a->pkey_id - b->pkey_id;
+  return 0;
 }
 
 int OBJ_find_sigid_by_algs(int *out_sign_nid, int digest_nid, int pkey_nid) {
-  nid_triple key, *pkey;
-  const nid_triple **triple;
-
-  key.hash_id = digest_nid;
-  key.pkey_id = pkey_nid;
-  pkey = &key;
-
-  triple = bsearch(&pkey, sigoid_srt_xref,
-                   sizeof(sigoid_srt_xref) / sizeof(nid_triple *),
-                   sizeof(nid_triple *), nid_triple_cmp_by_digest_and_hash);
-
-  if (triple == NULL) {
-    return 0;
+  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kTriples); i++) {
+    if (kTriples[i].digest_nid == digest_nid &&
+        kTriples[i].pkey_nid == pkey_nid) {
+      if (out_sign_nid != NULL) {
+        *out_sign_nid = kTriples[i].sign_nid;
+      }
+      return 1;
+    }
   }
-  if (out_sign_nid) {
-    *out_sign_nid = (*triple)->sign_id;
-  }
-  return 1;
+
+  return 0;
 }
diff --git a/src/crypto/obj/obj_xref.h b/src/crypto/obj/obj_xref.h
deleted file mode 100644
index b2082f5..0000000
--- a/src/crypto/obj/obj_xref.h
+++ /dev/null
@@ -1,96 +0,0 @@
-/* THIS FILE IS GENERATED FROM obj_xref.txt by obj_xref.pl via the
- * following command:
- * perl obj_xref.pl obj_mac.num obj_xref.txt > obj_xref.h */
-
-typedef struct
-	{
-	int sign_id;
-	int hash_id;
-	int pkey_id;
-	} nid_triple;
-
-static const nid_triple sigoid_srt[] =
-	{
-	{NID_md2WithRSAEncryption, NID_md2, NID_rsaEncryption},
-	{NID_md5WithRSAEncryption, NID_md5, NID_rsaEncryption},
-	{NID_shaWithRSAEncryption, NID_sha, NID_rsaEncryption},
-	{NID_sha1WithRSAEncryption, NID_sha1, NID_rsaEncryption},
-	{NID_dsaWithSHA, NID_sha, NID_dsa},
-	{NID_dsaWithSHA1_2, NID_sha1, NID_dsa_2},
-	{NID_mdc2WithRSA, NID_mdc2, NID_rsaEncryption},
-	{NID_md5WithRSA, NID_md5, NID_rsa},
-	{NID_dsaWithSHA1, NID_sha1, NID_dsa},
-	{NID_sha1WithRSA, NID_sha1, NID_rsa},
-	{NID_ripemd160WithRSA, NID_ripemd160, NID_rsaEncryption},
-	{NID_md4WithRSAEncryption, NID_md4, NID_rsaEncryption},
-	{NID_ecdsa_with_SHA1, NID_sha1, NID_X9_62_id_ecPublicKey},
-	{NID_sha256WithRSAEncryption, NID_sha256, NID_rsaEncryption},
-	{NID_sha384WithRSAEncryption, NID_sha384, NID_rsaEncryption},
-	{NID_sha512WithRSAEncryption, NID_sha512, NID_rsaEncryption},
-	{NID_sha224WithRSAEncryption, NID_sha224, NID_rsaEncryption},
-	{NID_ecdsa_with_Recommended, NID_undef, NID_X9_62_id_ecPublicKey},
-	{NID_ecdsa_with_Specified, NID_undef, NID_X9_62_id_ecPublicKey},
-	{NID_ecdsa_with_SHA224, NID_sha224, NID_X9_62_id_ecPublicKey},
-	{NID_ecdsa_with_SHA256, NID_sha256, NID_X9_62_id_ecPublicKey},
-	{NID_ecdsa_with_SHA384, NID_sha384, NID_X9_62_id_ecPublicKey},
-	{NID_ecdsa_with_SHA512, NID_sha512, NID_X9_62_id_ecPublicKey},
-	{NID_dsa_with_SHA224, NID_sha224, NID_dsa},
-	{NID_dsa_with_SHA256, NID_sha256, NID_dsa},
-	{NID_id_GostR3411_94_with_GostR3410_2001, NID_id_GostR3411_94, NID_id_GostR3410_2001},
-	{NID_id_GostR3411_94_with_GostR3410_94, NID_id_GostR3411_94, NID_id_GostR3410_94},
-	{NID_id_GostR3411_94_with_GostR3410_94_cc, NID_id_GostR3411_94, NID_id_GostR3410_94_cc},
-	{NID_id_GostR3411_94_with_GostR3410_2001_cc, NID_id_GostR3411_94, NID_id_GostR3410_2001_cc},
-	{NID_rsassaPss, NID_undef, NID_rsaEncryption},
-	{NID_dhSinglePass_stdDH_sha1kdf_scheme, NID_sha1, NID_dh_std_kdf},
-	{NID_dhSinglePass_stdDH_sha224kdf_scheme, NID_sha224, NID_dh_std_kdf},
-	{NID_dhSinglePass_stdDH_sha256kdf_scheme, NID_sha256, NID_dh_std_kdf},
-	{NID_dhSinglePass_stdDH_sha384kdf_scheme, NID_sha384, NID_dh_std_kdf},
-	{NID_dhSinglePass_stdDH_sha512kdf_scheme, NID_sha512, NID_dh_std_kdf},
-	{NID_dhSinglePass_cofactorDH_sha1kdf_scheme, NID_sha1, NID_dh_cofactor_kdf},
-	{NID_dhSinglePass_cofactorDH_sha224kdf_scheme, NID_sha224, NID_dh_cofactor_kdf},
-	{NID_dhSinglePass_cofactorDH_sha256kdf_scheme, NID_sha256, NID_dh_cofactor_kdf},
-	{NID_dhSinglePass_cofactorDH_sha384kdf_scheme, NID_sha384, NID_dh_cofactor_kdf},
-	{NID_dhSinglePass_cofactorDH_sha512kdf_scheme, NID_sha512, NID_dh_cofactor_kdf},
-	};
-
-static const nid_triple * const sigoid_srt_xref[] =
-	{
-	&sigoid_srt[0],
-	&sigoid_srt[1],
-	&sigoid_srt[7],
-	&sigoid_srt[2],
-	&sigoid_srt[4],
-	&sigoid_srt[3],
-	&sigoid_srt[9],
-	&sigoid_srt[5],
-	&sigoid_srt[8],
-	&sigoid_srt[12],
-	&sigoid_srt[30],
-	&sigoid_srt[35],
-	&sigoid_srt[6],
-	&sigoid_srt[10],
-	&sigoid_srt[11],
-	&sigoid_srt[13],
-	&sigoid_srt[24],
-	&sigoid_srt[20],
-	&sigoid_srt[32],
-	&sigoid_srt[37],
-	&sigoid_srt[14],
-	&sigoid_srt[21],
-	&sigoid_srt[33],
-	&sigoid_srt[38],
-	&sigoid_srt[15],
-	&sigoid_srt[22],
-	&sigoid_srt[34],
-	&sigoid_srt[39],
-	&sigoid_srt[16],
-	&sigoid_srt[23],
-	&sigoid_srt[19],
-	&sigoid_srt[31],
-	&sigoid_srt[36],
-	&sigoid_srt[25],
-	&sigoid_srt[26],
-	&sigoid_srt[27],
-	&sigoid_srt[28],
-	};
-
diff --git a/src/crypto/obj/obj_xref.pl b/src/crypto/obj/obj_xref.pl
deleted file mode 100644
index 51dd68f..0000000
--- a/src/crypto/obj/obj_xref.pl
+++ /dev/null
@@ -1,118 +0,0 @@
-#!/usr/bin/env perl
-
-use strict;
-
-if (scalar @ARGV != 2)
-	{
-	print "Usage: perl obj_xref.pl obj_mac.num obj_xref.txt > obj_xref.h\n";
-	exit 1;
-	}
-
-my %xref_tbl;
-my %oid_tbl;
-
-my ($mac_file, $xref_file) = @ARGV;
-
-open(IN, $mac_file) || die "Can't open $mac_file";
-
-# Read in OID nid values for a lookup table.
-
-while (<IN>)
-	{
-	chomp;
-	my ($name, $num) = /^(\S+)\s+(\S+)$/;
-	$oid_tbl{$name} = $num;
-	}
-close IN;
-
-open(IN, $xref_file) || die "Can't open $xref_file";
-
-my $ln = 1;
-
-while (<IN>)
-	{
-	chomp;
-	s/#.*$//;
-	next if (/^\S*$/);
-	my ($xr, $p1, $p2) = /^(\S+)\s+(\S+)\s+(\S+)/;
-	check_oid($xr);
-	check_oid($p1);
-	check_oid($p2);
-	$xref_tbl{$xr} = [$p1, $p2, $ln];
-	}
-
-my @xrkeys = keys %xref_tbl;
-
-my @srt1 = sort { $oid_tbl{$a} <=> $oid_tbl{$b}} @xrkeys;
-
-for(my $i = 0; $i <= $#srt1; $i++)
-	{
-	$xref_tbl{$srt1[$i]}[2] = $i;
-	}
-
-my @srt2 = sort
-	{
-	my$ap1 = $oid_tbl{$xref_tbl{$a}[0]};
-	my$bp1 = $oid_tbl{$xref_tbl{$b}[0]};
-	return $ap1 - $bp1 if ($ap1 != $bp1);
-	my$ap2 = $oid_tbl{$xref_tbl{$a}[1]};
-	my$bp2 = $oid_tbl{$xref_tbl{$b}[1]};
-
-	return $ap2 - $bp2;
-	} @xrkeys;
-
-my $pname = $0;
-
-$pname =~ s|^.[^/]/||;
-
-print <<EOF;
-/* THIS FILE IS GENERATED FROM obj_xref.txt by obj_xref.pl via the
- * following command:
- * perl obj_xref.pl obj_mac.num obj_xref.txt > obj_xref.h */
-
-typedef struct
-	{
-	int sign_id;
-	int hash_id;
-	int pkey_id;
-	} nid_triple;
-
-static const nid_triple sigoid_srt[] =
-	{
-EOF
-
-foreach (@srt1)
-	{
-	my $xr = $_;
-	my ($p1, $p2) = @{$xref_tbl{$_}};
-	print "\t{NID_$xr, NID_$p1, NID_$p2},\n";
-	}
-
-print "\t};";
-print <<EOF;
-
-
-static const nid_triple * const sigoid_srt_xref[] =
-	{
-EOF
-
-foreach (@srt2)
-	{
-	my ($p1, $p2, $x) = @{$xref_tbl{$_}};
-	# If digest or signature algorithm is "undef" then the algorithm
-	# needs special handling and is excluded from the cross reference table.
-	next if $p1 eq "undef" || $p2 eq "undef";
-	print "\t\&sigoid_srt\[$x\],\n";
-	}
-
-print "\t};\n\n";
-
-sub check_oid
-	{
-	my ($chk) = @_;
-	if (!exists $oid_tbl{$chk})
-		{
-		die "Not Found \"$chk\"\n";
-		}
-	}
-
diff --git a/src/crypto/obj/obj_xref.txt b/src/crypto/obj/obj_xref.txt
deleted file mode 100644
index 19c9422..0000000
--- a/src/crypto/obj/obj_xref.txt
+++ /dev/null
@@ -1,58 +0,0 @@
-# OID cross reference table.
-# Links signatures OIDs to their corresponding public key algorithms
-# and digests.
-
-md2WithRSAEncryption	md2	rsaEncryption
-md5WithRSAEncryption	md5	rsaEncryption
-shaWithRSAEncryption	sha	rsaEncryption
-sha1WithRSAEncryption	sha1	rsaEncryption
-md4WithRSAEncryption	md4	rsaEncryption
-sha256WithRSAEncryption sha256	rsaEncryption
-sha384WithRSAEncryption	sha384	rsaEncryption
-sha512WithRSAEncryption	sha512	rsaEncryption
-sha224WithRSAEncryption	sha224	rsaEncryption
-mdc2WithRSA		mdc2	rsaEncryption
-ripemd160WithRSA	ripemd160 rsaEncryption
-# For PSS the digest algorithm can vary and depends on the included
-# AlgorithmIdentifier. The digest "undef" indicates the public key
-# method should handle this explicitly.
-rsassaPss		undef	rsaEncryption
-
-# Alternative deprecated OIDs. By using the older "rsa" OID this
-# type will be recognized by not normally used.
-
-md5WithRSA		md5	rsa
-sha1WithRSA		sha1	rsa
-
-dsaWithSHA		sha	dsa
-dsaWithSHA1		sha1	dsa
-
-dsaWithSHA1_2		sha1	dsa_2
-
-ecdsa_with_SHA1		sha1	X9_62_id_ecPublicKey
-ecdsa_with_SHA224	sha224	X9_62_id_ecPublicKey
-ecdsa_with_SHA256	sha256	X9_62_id_ecPublicKey
-ecdsa_with_SHA384	sha384	X9_62_id_ecPublicKey
-ecdsa_with_SHA512	sha512	X9_62_id_ecPublicKey
-ecdsa_with_Recommended	undef	X9_62_id_ecPublicKey
-ecdsa_with_Specified	undef	X9_62_id_ecPublicKey
-
-dsa_with_SHA224		sha224	dsa
-dsa_with_SHA256		sha256	dsa
-
-id_GostR3411_94_with_GostR3410_2001	id_GostR3411_94 id_GostR3410_2001
-id_GostR3411_94_with_GostR3410_94	id_GostR3411_94 id_GostR3410_94
-id_GostR3411_94_with_GostR3410_94_cc	id_GostR3411_94 id_GostR3410_94_cc
-id_GostR3411_94_with_GostR3410_2001_cc	id_GostR3411_94 id_GostR3410_2001_cc
-# ECDH KDFs and their corresponding message digests and schemes
-dhSinglePass_stdDH_sha1kdf_scheme		sha1	dh_std_kdf
-dhSinglePass_stdDH_sha224kdf_scheme		sha224	dh_std_kdf
-dhSinglePass_stdDH_sha256kdf_scheme		sha256	dh_std_kdf
-dhSinglePass_stdDH_sha384kdf_scheme		sha384	dh_std_kdf
-dhSinglePass_stdDH_sha512kdf_scheme		sha512	dh_std_kdf
-
-dhSinglePass_cofactorDH_sha1kdf_scheme		sha1	dh_cofactor_kdf
-dhSinglePass_cofactorDH_sha224kdf_scheme	sha224	dh_cofactor_kdf
-dhSinglePass_cofactorDH_sha256kdf_scheme	sha256	dh_cofactor_kdf
-dhSinglePass_cofactorDH_sha384kdf_scheme	sha384	dh_cofactor_kdf
-dhSinglePass_cofactorDH_sha512kdf_scheme	sha512	dh_cofactor_kdf
diff --git a/src/crypto/obj/objects.go b/src/crypto/obj/objects.go
new file mode 100644
index 0000000..28887c0
--- /dev/null
+++ b/src/crypto/obj/objects.go
@@ -0,0 +1,732 @@
+// Copyright (c) 2016, Google Inc.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+package main
+
+import (
+	"bufio"
+	"bytes"
+	"errors"
+	"fmt"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"sort"
+	"strconv"
+	"strings"
+)
+
+func sanitizeName(in string) string {
+	in = strings.Replace(in, "-", "_", -1)
+	in = strings.Replace(in, ".", "_", -1)
+	in = strings.Replace(in, " ", "_", -1)
+	return in
+}
+
+type object struct {
+	name string
+	// shortName and longName are the short and long names, respectively. If
+	// one is missing, it takes the value of the other, but the
+	// corresponding SN_foo or LN_foo macro is not defined.
+	shortName, longName       string
+	hasShortName, hasLongName bool
+	oid                       []int
+	encoded                   []byte
+}
+
+type objects struct {
+	// byNID is the list of all objects, indexed by nid.
+	byNID []object
+	// nameToNID is a map from object name to nid.
+	nameToNID map[string]int
+}
+
+func readNumbers(path string) (nameToNID map[string]int, numNIDs int, err error) {
+	in, err := os.Open(path)
+	if err != nil {
+		return nil, 0, err
+	}
+	defer in.Close()
+
+	nameToNID = make(map[string]int)
+	nidsSeen := make(map[int]struct{})
+
+	// Reserve NID 0 for NID_undef.
+	numNIDs = 1
+	nameToNID["undef"] = 0
+	nidsSeen[0] = struct{}{}
+
+	var lineNo int
+	scanner := bufio.NewScanner(in)
+	for scanner.Scan() {
+		line := scanner.Text()
+		lineNo++
+		withLine := func(err error) error {
+			return fmt.Errorf("%s:%d: %s", path, lineNo, err)
+		}
+
+		fields := strings.Fields(line)
+		if len(fields) == 0 {
+			// Skip blank lines.
+			continue
+		}
+
+		// Each line is a name and a nid, separated by space.
+		if len(fields) != 2 {
+			return nil, 0, withLine(errors.New("syntax error"))
+		}
+		name := fields[0]
+		nid, err := strconv.Atoi(fields[1])
+		if err != nil {
+			return nil, 0, withLine(err)
+		}
+		if nid < 0 {
+			return nil, 0, withLine(errors.New("invalid NID"))
+		}
+
+		// NID_undef is implicitly defined.
+		if name == "undef" && nid == 0 {
+			continue
+		}
+
+		// Forbid duplicates.
+		if _, ok := nameToNID[name]; ok {
+			return nil, 0, withLine(fmt.Errorf("duplicate name %q", name))
+		}
+		if _, ok := nidsSeen[nid]; ok {
+			return nil, 0, withLine(fmt.Errorf("duplicate NID %d", nid))
+		}
+
+		nameToNID[name] = nid
+		nidsSeen[nid] = struct{}{}
+
+		if nid >= numNIDs {
+			numNIDs = nid + 1
+		}
+	}
+	if err := scanner.Err(); err != nil {
+		return nil, 0, fmt.Errorf("error reading %s: %s", path, err)
+	}
+
+	return nameToNID, numNIDs, nil
+}
+
+func parseOID(aliases map[string][]int, in []string) (oid []int, err error) {
+	if len(in) == 0 {
+		return
+	}
+
+	// The first entry may be a reference to a previous alias.
+	if alias, ok := aliases[sanitizeName(in[0])]; ok {
+		in = in[1:]
+		oid = append(oid, alias...)
+	}
+
+	for _, c := range in {
+		val, err := strconv.Atoi(c)
+		if err != nil {
+			return nil, err
+		}
+		if val < 0 {
+			return nil, fmt.Errorf("negative component")
+		}
+		oid = append(oid, val)
+	}
+	return
+}
+
+func appendBase128(dst []byte, value int) []byte {
+	// Zero is encoded with one, not zero bytes.
+	if value == 0 {
+		return append(dst, 0)
+	}
+
+	// Count how many bytes are needed.
+	var l int
+	for n := value; n != 0; n >>= 7 {
+		l++
+	}
+	for ; l > 0; l-- {
+		b := byte(value>>uint(7*(l-1))) & 0x7f
+		if l > 1 {
+			b |= 0x80
+		}
+		dst = append(dst, b)
+	}
+	return dst
+}
+
+func encodeOID(oid []int) []byte {
+	if len(oid) < 2 {
+		return nil
+	}
+
+	var der []byte
+	der = appendBase128(der, 40*oid[0]+oid[1])
+	for _, value := range oid[2:] {
+		der = appendBase128(der, value)
+	}
+	return der
+}
+
+func readObjects(numPath, objectsPath string) (*objects, error) {
+	nameToNID, numNIDs, err := readNumbers(numPath)
+	if err != nil {
+		return nil, err
+	}
+
+	in, err := os.Open(objectsPath)
+	if err != nil {
+		return nil, err
+	}
+	defer in.Close()
+
+	// Implicitly define NID_undef.
+	objs := &objects{
+		byNID:     make([]object, numNIDs),
+		nameToNID: make(map[string]int),
+	}
+
+	objs.byNID[0] = object{
+		name:         "undef",
+		shortName:    "UNDEF",
+		longName:     "undefined",
+		hasShortName: true,
+		hasLongName:  true,
+	}
+	objs.nameToNID["undef"] = 0
+
+	var module, nextName string
+	var lineNo int
+	longNamesSeen := make(map[string]struct{})
+	shortNamesSeen := make(map[string]struct{})
+	aliases := make(map[string][]int)
+	scanner := bufio.NewScanner(in)
+	for scanner.Scan() {
+		line := scanner.Text()
+		lineNo++
+		withLine := func(err error) error {
+			return fmt.Errorf("%s:%d: %s", objectsPath, lineNo, err)
+		}
+
+		// Remove comments.
+		idx := strings.IndexRune(line, '#')
+		if idx >= 0 {
+			line = line[:idx]
+		}
+
+		// Skip empty lines.
+		line = strings.TrimSpace(line)
+		if len(line) == 0 {
+			continue
+		}
+
+		if line[0] == '!' {
+			args := strings.Fields(line)
+			switch args[0] {
+			case "!module":
+				if len(args) != 2 {
+					return nil, withLine(errors.New("too many arguments"))
+				}
+				module = sanitizeName(args[1]) + "_"
+			case "!global":
+				module = ""
+			case "!Cname":
+				// !Cname directives override the name for the
+				// next object.
+				if len(args) != 2 {
+					return nil, withLine(errors.New("too many arguments"))
+				}
+				nextName = sanitizeName(args[1])
+			case "!Alias":
+				// !Alias directives define an alias for an OID
+				// without emitting an object.
+				if len(nextName) != 0 {
+					return nil, withLine(errors.New("!Cname directives may not modify !Alias directives."))
+				}
+				if len(args) < 3 {
+					return nil, withLine(errors.New("not enough arguments"))
+				}
+				aliasName := module + sanitizeName(args[1])
+				oid, err := parseOID(aliases, args[2:])
+				if err != nil {
+					return nil, withLine(err)
+				}
+				if _, ok := aliases[aliasName]; ok {
+					return nil, withLine(fmt.Errorf("duplicate name '%s'", aliasName))
+				}
+				aliases[aliasName] = oid
+			default:
+				return nil, withLine(fmt.Errorf("unknown directive '%s'", args[0]))
+			}
+			continue
+		}
+
+		fields := strings.Split(line, ":")
+		if len(fields) < 2 || len(fields) > 3 {
+			return nil, withLine(errors.New("invalid field count"))
+		}
+
+		obj := object{name: nextName}
+		nextName = ""
+
+		var err error
+		obj.oid, err = parseOID(aliases, strings.Fields(fields[0]))
+		if err != nil {
+			return nil, withLine(err)
+		}
+		obj.encoded = encodeOID(obj.oid)
+
+		obj.shortName = strings.TrimSpace(fields[1])
+		if len(fields) == 3 {
+			obj.longName = strings.TrimSpace(fields[2])
+		}
+
+		// Long and short names default to each other if missing.
+		if len(obj.shortName) == 0 {
+			obj.shortName = obj.longName
+		} else {
+			obj.hasShortName = true
+		}
+		if len(obj.longName) == 0 {
+			obj.longName = obj.shortName
+		} else {
+			obj.hasLongName = true
+		}
+		if len(obj.shortName) == 0 || len(obj.longName) == 0 {
+			return nil, withLine(errors.New("object with no name"))
+		}
+
+		// If not already specified, prefer the long name if it has no
+		// spaces, otherwise the short name.
+		if len(obj.name) == 0 && strings.IndexRune(obj.longName, ' ') < 0 {
+			obj.name = sanitizeName(obj.longName)
+		}
+		if len(obj.name) == 0 {
+			obj.name = sanitizeName(obj.shortName)
+		}
+		obj.name = module + obj.name
+
+		// Check for duplicate names.
+		if _, ok := aliases[obj.name]; ok {
+			return nil, withLine(fmt.Errorf("duplicate name '%s'", obj.name))
+		}
+		if _, ok := shortNamesSeen[obj.shortName]; ok && len(obj.shortName) > 0 {
+			return nil, withLine(fmt.Errorf("duplicate short name '%s'", obj.shortName))
+		}
+		if _, ok := longNamesSeen[obj.longName]; ok && len(obj.longName) > 0 {
+			return nil, withLine(fmt.Errorf("duplicate long name '%s'", obj.longName))
+		}
+
+		// Allocate a NID.
+		nid, ok := nameToNID[obj.name]
+		if !ok {
+			nid = len(objs.byNID)
+			objs.byNID = append(objs.byNID, object{})
+		}
+
+		objs.byNID[nid] = obj
+		objs.nameToNID[obj.name] = nid
+
+		longNamesSeen[obj.longName] = struct{}{}
+		shortNamesSeen[obj.shortName] = struct{}{}
+		aliases[obj.name] = obj.oid
+	}
+	if err := scanner.Err(); err != nil {
+		return nil, err
+	}
+
+	return objs, nil
+}
+
+func writeNumbers(path string, objs *objects) error {
+	out, err := os.Create(path)
+	if err != nil {
+		return err
+	}
+	defer out.Close()
+
+	for nid, obj := range objs.byNID {
+		if len(obj.name) == 0 {
+			continue
+		}
+		if _, err := fmt.Fprintf(out, "%s\t\t%d\n", obj.name, nid); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func clangFormat(input string) (string, error) {
+	var b bytes.Buffer
+	cmd := exec.Command("clang-format")
+	cmd.Stdin = strings.NewReader(input)
+	cmd.Stdout = &b
+	cmd.Stderr = os.Stderr
+	if err := cmd.Run(); err != nil {
+		return "", err
+	}
+	return b.String(), nil
+}
+
+func writeHeader(path string, objs *objects) error {
+	var b bytes.Buffer
+	fmt.Fprintf(&b, `/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG `+"``"+`AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+/* This file is generated by crypto/obj/objects.go. */
+
+#ifndef OPENSSL_HEADER_NID_H
+#define OPENSSL_HEADER_NID_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* The nid library provides numbered values for ASN.1 object identifiers and
+ * other symbols. These values are used by other libraries to identify
+ * cryptographic primitives.
+ *
+ * A separate objects library, obj.h, provides functions for converting between
+ * nids and object identifiers. However it depends on large internal tables with
+ * the encodings of every nid defined. Consumers concerned with binary size
+ * should instead embed the encodings of the few consumed OIDs and compare
+ * against those.
+ *
+ * These values should not be used outside of a single process; they are not
+ * stable identifiers. */
+
+
+`)
+
+	for nid, obj := range objs.byNID {
+		if len(obj.name) == 0 {
+			continue
+		}
+
+		if obj.hasShortName {
+			fmt.Fprintf(&b, "#define SN_%s \"%s\"\n", obj.name, obj.shortName)
+		}
+		if obj.hasLongName {
+			fmt.Fprintf(&b, "#define LN_%s \"%s\"\n", obj.name, obj.longName)
+		}
+		fmt.Fprintf(&b, "#define NID_%s %d\n", obj.name, nid)
+
+		// Although NID_undef does not have an OID, OpenSSL emits
+		// OBJ_undef as if it were zero.
+		oid := obj.oid
+		if nid == 0 {
+			oid = []int{0}
+		}
+		if len(oid) != 0 {
+			var oidStr string
+			for _, val := range oid {
+				if len(oidStr) != 0 {
+					oidStr += ","
+				}
+				oidStr += fmt.Sprintf("%dL", val)
+			}
+
+			fmt.Fprintf(&b, "#define OBJ_%s %s\n", obj.name, oidStr)
+		}
+
+		fmt.Fprintf(&b, "\n")
+	}
+
+	fmt.Fprintf(&b, `
+#if defined(__cplusplus)
+}  /* extern C */
+#endif
+
+#endif  /* OPENSSL_HEADER_NID_H */
+`)
+
+	formatted, err := clangFormat(b.String())
+	if err != nil {
+		return err
+	}
+
+	return ioutil.WriteFile(path, []byte(formatted), 0666)
+}
+
+// TODO(davidben): Replace this with sort.Slice once Go 1.8 is sufficiently
+// common.
+type nidSorter struct {
+	nids []int
+	objs *objects
+	cmp  func(a, b object) bool
+}
+
+func (a nidSorter) obj(i int) object   { return a.objs.byNID[a.nids[i]] }
+func (a nidSorter) Len() int           { return len(a.nids) }
+func (a nidSorter) Swap(i, j int)      { a.nids[i], a.nids[j] = a.nids[j], a.nids[i] }
+func (a nidSorter) Less(i, j int) bool { return a.cmp(a.obj(i), a.obj(j)) }
+
+func sortNIDs(nids []int, objs *objects, cmp func(a, b object) bool) {
+	sort.Sort(&nidSorter{nids, objs, cmp})
+}
+
+func writeData(path string, objs *objects) error {
+	var b bytes.Buffer
+	fmt.Fprintf(&b, `/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG `+"``"+`AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+/* This file is generated by crypto/obj/objects.go. */
+
+
+`)
+
+	fmt.Fprintf(&b, "#define NUM_NID %d\n", len(objs.byNID))
+
+	// Emit each object's DER encoding, concatenated, and save the offsets.
+	fmt.Fprintf(&b, "\nstatic const uint8_t kObjectData[] = {\n")
+	offsets := make([]int, len(objs.byNID))
+	var nextOffset int
+	for nid, obj := range objs.byNID {
+		if len(obj.name) == 0 || len(obj.encoded) == 0 {
+			offsets[nid] = -1
+			continue
+		}
+
+		offsets[nid] = nextOffset
+		nextOffset += len(obj.encoded)
+		fmt.Fprintf(&b, "/* NID_%s */\n", obj.name)
+		for _, val := range obj.encoded {
+			fmt.Fprintf(&b, "0x%02x, ", val)
+		}
+		fmt.Fprintf(&b, "\n")
+	}
+	fmt.Fprintf(&b, "};\n")
+
+	// Emit an ASN1_OBJECT for each object.
+	fmt.Fprintf(&b, "\nstatic const ASN1_OBJECT kObjects[NUM_NID] = {\n")
+	for nid, obj := range objs.byNID {
+		if len(obj.name) == 0 {
+			fmt.Fprintf(&b, "{NULL, NULL, NID_undef, 0, NULL, 0},\n")
+			continue
+		}
+
+		fmt.Fprintf(&b, "{\"%s\", \"%s\", NID_%s, ", obj.shortName, obj.longName, obj.name)
+		if offset := offsets[nid]; offset >= 0 {
+			fmt.Fprintf(&b, "%d, &kObjectData[%d], 0},\n", len(obj.encoded), offset)
+		} else {
+			fmt.Fprintf(&b, "0, NULL, 0},\n")
+		}
+	}
+	fmt.Fprintf(&b, "};\n")
+
+	// Emit a list of NIDs sorted by short name.
+	var nids []int
+	for nid, obj := range objs.byNID {
+		if len(obj.name) == 0 || len(obj.shortName) == 0 {
+			continue
+		}
+		nids = append(nids, nid)
+	}
+	sortNIDs(nids, objs, func(a, b object) bool { return a.shortName < b.shortName })
+
+	fmt.Fprintf(&b, "\nstatic const unsigned kNIDsInShortNameOrder[] = {\n")
+	for _, nid := range nids {
+		fmt.Fprintf(&b, "%d /* %s */,\n", nid, objs.byNID[nid].shortName)
+	}
+	fmt.Fprintf(&b, "};\n")
+
+	// Emit a list of NIDs sorted by long name.
+	nids = nil
+	for nid, obj := range objs.byNID {
+		if len(obj.name) == 0 || len(obj.longName) == 0 {
+			continue
+		}
+		nids = append(nids, nid)
+	}
+	sortNIDs(nids, objs, func(a, b object) bool { return a.longName < b.longName })
+
+	fmt.Fprintf(&b, "\nstatic const unsigned kNIDsInLongNameOrder[] = {\n")
+	for _, nid := range nids {
+		fmt.Fprintf(&b, "%d /* %s */,\n", nid, objs.byNID[nid].longName)
+	}
+	fmt.Fprintf(&b, "};\n")
+
+	// Emit a list of NIDs sorted by OID.
+	nids = nil
+	for nid, obj := range objs.byNID {
+		if len(obj.name) == 0 || len(obj.encoded) == 0 {
+			continue
+		}
+		nids = append(nids, nid)
+	}
+	sortNIDs(nids, objs, func(a, b object) bool {
+		// This comparison must match the definition of |obj_cmp|.
+		if len(a.encoded) < len(b.encoded) {
+			return true
+		}
+		if len(a.encoded) > len(b.encoded) {
+			return false
+		}
+		return bytes.Compare(a.encoded, b.encoded) < 0
+	})
+
+	fmt.Fprintf(&b, "\nstatic const unsigned kNIDsInOIDOrder[] = {\n")
+	for _, nid := range nids {
+		obj := objs.byNID[nid]
+		fmt.Fprintf(&b, "%d /* ", nid)
+		for i, c := range obj.oid {
+			if i > 0 {
+				fmt.Fprintf(&b, ".")
+			}
+			fmt.Fprintf(&b, "%d", c)
+		}
+		fmt.Fprintf(&b, " (OBJ_%s) */,\n", obj.name)
+	}
+	fmt.Fprintf(&b, "};\n")
+
+	formatted, err := clangFormat(b.String())
+	if err != nil {
+		return err
+	}
+
+	return ioutil.WriteFile(path, []byte(formatted), 0666)
+}
+
+func main() {
+	objs, err := readObjects("obj_mac.num", "objects.txt")
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "Error reading objects: %s\n", err)
+		os.Exit(1)
+	}
+
+	if err := writeNumbers("obj_mac.num", objs); err != nil {
+		fmt.Fprintf(os.Stderr, "Error writing numbers: %s\n", err)
+		os.Exit(1)
+	}
+
+	if err := writeHeader("../../include/openssl/nid.h", objs); err != nil {
+		fmt.Fprintf(os.Stderr, "Error writing header: %s\n", err)
+		os.Exit(1)
+	}
+
+	if err := writeData("obj_dat.h", objs); err != nil {
+		fmt.Fprintf(os.Stderr, "Error writing data: %s\n", err)
+		os.Exit(1)
+	}
+}
diff --git a/src/crypto/obj/objects.pl b/src/crypto/obj/objects.pl
deleted file mode 100644
index 7073e85..0000000
--- a/src/crypto/obj/objects.pl
+++ /dev/null
@@ -1,235 +0,0 @@
-#!/usr/bin/env perl
-
-if (scalar @ARGV != 3)
-	{
-	print "Usage: perl objects.pl objects.txt obj_mac.num ../../include/openssl/obj_mac.h\n";
-	exit 1;
-	}
-
-open (NUMIN,"$ARGV[1]") || die "Can't open number file $ARGV[1]";
-$max_nid=0;
-$o=0;
-while(<NUMIN>)
-	{
-	chop;
-	$o++;
-	s/#.*$//;
-	next if /^\s*$/;
-	$_ = 'X'.$_;
-	($Cname,$mynum) = split;
-	$Cname =~ s/^X//;
-	if (defined($nidn{$mynum}))
-		{ die "$ARGV[1]:$o:There's already an object with NID ",$mynum," on line ",$order{$mynum},"\n"; }
-	if (defined($nid{$Cname}))
-		{ die "$ARGV[1]:$o:There's already an object with name ",$Cname," on line ",$order{$nid{$Cname}},"\n"; }
-	$nid{$Cname} = $mynum;
-	$nidn{$mynum} = $Cname;
-	$order{$mynum} = $o;
-	$max_nid = $mynum if $mynum > $max_nid;
-	}
-close NUMIN;
-
-open (IN,"$ARGV[0]") || die "Can't open input file $ARGV[0]";
-$Cname="";
-$o=0;
-while (<IN>)
-	{
-	chop;
-	$o++;
-        if (/^!module\s+(.*)$/)
-		{
-		$module = $1."-";
-		$module =~ s/\./_/g;
-		$module =~ s/-/_/g;
-		}
-        if (/^!global$/)
-		{ $module = ""; }
-	if (/^!Cname\s+(.*)$/)
-		{ $Cname = $1; }
-	if (/^!Alias\s+(.+?)\s+(.*)$/)
-		{
-		$Cname = $module.$1;
-		$myoid = $2;
-		$myoid = &process_oid($myoid);
-		$Cname =~ s/-/_/g;
-		$ordern{$o} = $Cname;
-		$order{$Cname} = $o;
-		$obj{$Cname} = $myoid;
-		$_ = "";
-		$Cname = "";
-		}
-	s/!.*$//;
-	s/#.*$//;
-	next if /^\s*$/;
-	($myoid,$mysn,$myln) = split ':';
-	$mysn =~ s/^\s*//;
-	$mysn =~ s/\s*$//;
-	$myln =~ s/^\s*//;
-	$myln =~ s/\s*$//;
-	$myoid =~ s/^\s*//;
-	$myoid =~ s/\s*$//;
-	if ($myoid ne "")
-		{
-		$myoid = &process_oid($myoid);
-		}
-
-	if ($Cname eq "" && !($myln =~ / /))
-		{
-		$Cname = $myln;
-		$Cname =~ s/\./_/g;
-		$Cname =~ s/-/_/g;
-		if ($Cname ne "" && defined($ln{$module.$Cname}))
-			{ die "objects.txt:$o:There's already an object with long name ",$ln{$module.$Cname}," on line ",$order{$module.$Cname},"\n"; }
-		}
-	if ($Cname eq "")
-		{
-		$Cname = $mysn;
-		$Cname =~ s/-/_/g;
-		if ($Cname ne "" && defined($sn{$module.$Cname}))
-			{ die "objects.txt:$o:There's already an object with short name ",$sn{$module.$Cname}," on line ",$order{$module.$Cname},"\n"; }
-		}
-	if ($Cname eq "")
-		{
-		$Cname = $myln;
-		$Cname =~ s/-/_/g;
-		$Cname =~ s/\./_/g;
-		$Cname =~ s/ /_/g;
-		if ($Cname ne "" && defined($ln{$module.$Cname}))
-			{ die "objects.txt:$o:There's already an object with long name ",$ln{$module.$Cname}," on line ",$order{$module.$Cname},"\n"; }
-		}
-	$Cname =~ s/\./_/g;
-	$Cname =~ s/-/_/g;
-	$Cname = $module.$Cname;
-	$ordern{$o} = $Cname;
-	$order{$Cname} = $o;
-	$sn{$Cname} = $mysn;
-	$ln{$Cname} = $myln;
-	$obj{$Cname} = $myoid;
-	if (!defined($nid{$Cname}))
-		{
-		$max_nid++;
-		$nid{$Cname} = $max_nid;
-		$nidn{$max_nid} = $Cname;
-print STDERR "Added OID $Cname\n";
-		}
-	$Cname="";
-	}
-close IN;
-
-open (NUMOUT,">$ARGV[1]") || die "Can't open output file $ARGV[1]";
-foreach (sort { $a <=> $b } keys %nidn)
-	{
-	print NUMOUT $nidn{$_},"\t\t",$_,"\n";
-	}
-close NUMOUT;
-
-open (OUT,">$ARGV[2]") || die "Can't open output file $ARGV[2]";
-print OUT <<'EOF';
-/* THIS FILE IS GENERATED FROM objects.txt by objects.pl via the
- * following command:
- * perl objects.pl objects.txt obj_mac.num ../../include/openssl/obj_mac.h */
-
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- * 
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to.  The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- * 
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- * 
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *    "This product includes cryptographic software written by
- *     Eric Young (eay@cryptsoft.com)"
- *    The word 'cryptographic' can be left out if the rouines from the library
- *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from 
- *    the apps directory (application code) you must include an acknowledgement:
- *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- * 
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * 
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed.  i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- */
-
-#define SN_undef			"UNDEF"
-#define LN_undef			"undefined"
-#define NID_undef			0
-#define OBJ_undef			0L
-
-EOF
-
-foreach (sort { $a <=> $b } keys %ordern)
-	{
-	$Cname=$ordern{$_};
-	print OUT "#define SN_",$Cname,"\t\t\"",$sn{$Cname},"\"\n" if $sn{$Cname} ne "";
-	print OUT "#define LN_",$Cname,"\t\t\"",$ln{$Cname},"\"\n" if $ln{$Cname} ne "";
-	print OUT "#define NID_",$Cname,"\t\t",$nid{$Cname},"\n" if $nid{$Cname} ne "";
-	print OUT "#define OBJ_",$Cname,"\t\t",$obj{$Cname},"\n" if $obj{$Cname} ne "";
-	print OUT "\n";
-	}
-
-close OUT;
-
-sub process_oid
-	{
-	local($oid)=@_;
-	local(@a,$oid_pref);
-
-	@a = split(/\s+/,$myoid);
-	$pref_oid = "";
-	$pref_sep = "";
-	if (!($a[0] =~ /^[0-9]+$/))
-		{
-		$a[0] =~ s/-/_/g;
-		if (!defined($obj{$a[0]}))
-			{ die "$ARGV[0]:$o:Undefined identifier ",$a[0],"\n"; }
-		$pref_oid = "OBJ_" . $a[0];
-		$pref_sep = ",";
-		shift @a;
-		}
-	$oids = join('L,',@a) . "L";
-	if ($oids ne "L")
-		{
-		$oids = $pref_oid . $pref_sep . $oids;
-		}
-	else
-		{
-		$oids = $pref_oid;
-		}
-	return($oids);
-	}
diff --git a/src/crypto/obj/objects.txt b/src/crypto/obj/objects.txt
index 93cf53a..f3990d0 100644
--- a/src/crypto/obj/objects.txt
+++ b/src/crypto/obj/objects.txt
@@ -1332,4 +1332,4 @@
                  : dh-cofactor-kdf
 
 # NID for X25519 (no corresponding OID).
- : X25519 : x25519
+ : X25519
diff --git a/src/crypto/pem/pem_all.c b/src/crypto/pem/pem_all.c
index c9f8b6e..e94ff26 100644
--- a/src/crypto/pem/pem_all.c
+++ b/src/crypto/pem/pem_all.c
@@ -113,159 +113,150 @@
 #include <openssl/dsa.h>
 #include <openssl/evp.h>
 #include <openssl/pem.h>
-/*#include <openssl/pkcs7.h> */
+/*
+ * #include <openssl/pkcs7.h>
+ */
 #include <openssl/rsa.h>
 #include <openssl/x509.h>
 
-
 static RSA *pkey_get_rsa(EVP_PKEY *key, RSA **rsa);
 static DSA *pkey_get_dsa(EVP_PKEY *key, DSA **dsa);
 static EC_KEY *pkey_get_eckey(EVP_PKEY *key, EC_KEY **eckey);
 
-
 IMPLEMENT_PEM_rw(X509_REQ, X509_REQ, PEM_STRING_X509_REQ, X509_REQ)
 
 IMPLEMENT_PEM_write(X509_REQ_NEW, X509_REQ, PEM_STRING_X509_REQ_OLD, X509_REQ)
-
 IMPLEMENT_PEM_rw(X509_CRL, X509_CRL, PEM_STRING_X509_CRL, X509_CRL)
 
-
-
-/* We treat RSA or DSA private keys as a special case.
- *
- * For private keys we read in an EVP_PKEY structure with
- * PEM_read_bio_PrivateKey() and extract the relevant private
- * key: this means can handle "traditional" and PKCS#8 formats
- * transparently.
+/*
+ * We treat RSA or DSA private keys as a special case. For private keys we
+ * read in an EVP_PKEY structure with PEM_read_bio_PrivateKey() and extract
+ * the relevant private key: this means can handle "traditional" and PKCS#8
+ * formats transparently.
  */
-
 static RSA *pkey_get_rsa(EVP_PKEY *key, RSA **rsa)
 {
-	RSA *rtmp;
-	if(!key) return NULL;
-	rtmp = EVP_PKEY_get1_RSA(key);
-	EVP_PKEY_free(key);
-	if(!rtmp) return NULL;
-	if(rsa) {
-		RSA_free(*rsa);
-		*rsa = rtmp;
-	}
-	return rtmp;
+    RSA *rtmp;
+    if (!key)
+        return NULL;
+    rtmp = EVP_PKEY_get1_RSA(key);
+    EVP_PKEY_free(key);
+    if (!rtmp)
+        return NULL;
+    if (rsa) {
+        RSA_free(*rsa);
+        *rsa = rtmp;
+    }
+    return rtmp;
 }
 
 RSA *PEM_read_bio_RSAPrivateKey(BIO *bp, RSA **rsa, pem_password_cb *cb,
-								void *u)
+                                void *u)
 {
-	EVP_PKEY *pktmp;
-	pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u);
-	return pkey_get_rsa(pktmp, rsa);
+    EVP_PKEY *pktmp;
+    pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u);
+    return pkey_get_rsa(pktmp, rsa);
 }
 
 #ifndef OPENSSL_NO_FP_API
 
-RSA *PEM_read_RSAPrivateKey(FILE *fp, RSA **rsa, pem_password_cb *cb,
-								void *u)
+RSA *PEM_read_RSAPrivateKey(FILE *fp, RSA **rsa, pem_password_cb *cb, void *u)
 {
-	EVP_PKEY *pktmp;
-	pktmp = PEM_read_PrivateKey(fp, NULL, cb, u);
-	return pkey_get_rsa(pktmp, rsa);
+    EVP_PKEY *pktmp;
+    pktmp = PEM_read_PrivateKey(fp, NULL, cb, u);
+    return pkey_get_rsa(pktmp, rsa);
 }
 
 #endif
 
-IMPLEMENT_PEM_write_cb_const(RSAPrivateKey, RSA, PEM_STRING_RSA, RSAPrivateKey)
+IMPLEMENT_PEM_write_cb_const(RSAPrivateKey, RSA, PEM_STRING_RSA,
+                             RSAPrivateKey)
 
-IMPLEMENT_PEM_rw_const(RSAPublicKey, RSA, PEM_STRING_RSA_PUBLIC, RSAPublicKey)
-IMPLEMENT_PEM_rw(RSA_PUBKEY, RSA, PEM_STRING_PUBLIC, RSA_PUBKEY)
 
+IMPLEMENT_PEM_rw_const(RSAPublicKey, RSA, PEM_STRING_RSA_PUBLIC,
+                       RSAPublicKey) IMPLEMENT_PEM_rw(RSA_PUBKEY, RSA,
+                                                      PEM_STRING_PUBLIC,
+                                                      RSA_PUBKEY)
 #ifndef OPENSSL_NO_DSA
-
 static DSA *pkey_get_dsa(EVP_PKEY *key, DSA **dsa)
 {
-	DSA *dtmp;
-	if(!key) return NULL;
-	dtmp = EVP_PKEY_get1_DSA(key);
-	EVP_PKEY_free(key);
-	if(!dtmp) return NULL;
-	if(dsa) {
-		DSA_free(*dsa);
-		*dsa = dtmp;
-	}
-	return dtmp;
+    DSA *dtmp;
+    if (!key)
+        return NULL;
+    dtmp = EVP_PKEY_get1_DSA(key);
+    EVP_PKEY_free(key);
+    if (!dtmp)
+        return NULL;
+    if (dsa) {
+        DSA_free(*dsa);
+        *dsa = dtmp;
+    }
+    return dtmp;
 }
 
 DSA *PEM_read_bio_DSAPrivateKey(BIO *bp, DSA **dsa, pem_password_cb *cb,
-								void *u)
+                                void *u)
 {
-	EVP_PKEY *pktmp;
-	pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u);
-	return pkey_get_dsa(pktmp, dsa);	/* will free pktmp */
+    EVP_PKEY *pktmp;
+    pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u);
+    return pkey_get_dsa(pktmp, dsa); /* will free pktmp */
 }
 
+IMPLEMENT_PEM_write_cb_const(DSAPrivateKey, DSA, PEM_STRING_DSA,
+                             DSAPrivateKey)
 
-IMPLEMENT_PEM_write_cb_const(DSAPrivateKey, DSA, PEM_STRING_DSA, DSAPrivateKey)
-
-IMPLEMENT_PEM_rw(DSA_PUBKEY, DSA, PEM_STRING_PUBLIC, DSA_PUBKEY)
-
-#ifndef OPENSSL_NO_FP_API
-
-DSA *PEM_read_DSAPrivateKey(FILE *fp, DSA **dsa, pem_password_cb *cb,
-								void *u)
+    IMPLEMENT_PEM_rw(DSA_PUBKEY, DSA, PEM_STRING_PUBLIC, DSA_PUBKEY)
+# ifndef OPENSSL_NO_FP_API
+DSA *PEM_read_DSAPrivateKey(FILE *fp, DSA **dsa, pem_password_cb *cb, void *u)
 {
-	EVP_PKEY *pktmp;
-	pktmp = PEM_read_PrivateKey(fp, NULL, cb, u);
-	return pkey_get_dsa(pktmp, dsa);	/* will free pktmp */
+    EVP_PKEY *pktmp;
+    pktmp = PEM_read_PrivateKey(fp, NULL, cb, u);
+    return pkey_get_dsa(pktmp, dsa); /* will free pktmp */
 }
 
-#endif
+# endif
 
 IMPLEMENT_PEM_rw_const(DSAparams, DSA, PEM_STRING_DSAPARAMS, DSAparams)
-
 #endif
-
-
 static EC_KEY *pkey_get_eckey(EVP_PKEY *key, EC_KEY **eckey)
 {
-	EC_KEY *dtmp;
-	if(!key) return NULL;
-	dtmp = EVP_PKEY_get1_EC_KEY(key);
-	EVP_PKEY_free(key);
-	if(!dtmp) return NULL;
-	if(eckey) 
-	{
- 		EC_KEY_free(*eckey);
-		*eckey = dtmp;
-	}
-	return dtmp;
+    EC_KEY *dtmp;
+    if (!key)
+        return NULL;
+    dtmp = EVP_PKEY_get1_EC_KEY(key);
+    EVP_PKEY_free(key);
+    if (!dtmp)
+        return NULL;
+    if (eckey) {
+        EC_KEY_free(*eckey);
+        *eckey = dtmp;
+    }
+    return dtmp;
 }
 
 EC_KEY *PEM_read_bio_ECPrivateKey(BIO *bp, EC_KEY **key, pem_password_cb *cb,
-							void *u)
+                                  void *u)
 {
-	EVP_PKEY *pktmp;
-	pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u);
-	return pkey_get_eckey(pktmp, key);	/* will free pktmp */
+    EVP_PKEY *pktmp;
+    pktmp = PEM_read_bio_PrivateKey(bp, NULL, cb, u);
+    return pkey_get_eckey(pktmp, key); /* will free pktmp */
 }
 
-IMPLEMENT_PEM_write_cb(ECPrivateKey, EC_KEY, PEM_STRING_ECPRIVATEKEY, ECPrivateKey)
+IMPLEMENT_PEM_write_cb(ECPrivateKey, EC_KEY, PEM_STRING_ECPRIVATEKEY,
+                       ECPrivateKey)
 
-
-IMPLEMENT_PEM_rw(EC_PUBKEY, EC_KEY, PEM_STRING_PUBLIC, EC_PUBKEY)
-
+    IMPLEMENT_PEM_rw(EC_PUBKEY, EC_KEY, PEM_STRING_PUBLIC, EC_PUBKEY)
 #ifndef OPENSSL_NO_FP_API
- 
 EC_KEY *PEM_read_ECPrivateKey(FILE *fp, EC_KEY **eckey, pem_password_cb *cb,
- 								void *u)
+                              void *u)
 {
-	EVP_PKEY *pktmp;
-	pktmp = PEM_read_PrivateKey(fp, NULL, cb, u);
-	return pkey_get_eckey(pktmp, eckey);	/* will free pktmp */
+    EVP_PKEY *pktmp;
+    pktmp = PEM_read_PrivateKey(fp, NULL, cb, u);
+    return pkey_get_eckey(pktmp, eckey); /* will free pktmp */
 }
 
 #endif
 
-
-
 IMPLEMENT_PEM_write_const(DHparams, DH, PEM_STRING_DHPARAMS, DHparams)
 
-IMPLEMENT_PEM_rw(PUBKEY, EVP_PKEY, PEM_STRING_PUBLIC, PUBKEY)
+    IMPLEMENT_PEM_rw(PUBKEY, EVP_PKEY, PEM_STRING_PUBLIC, PUBKEY)
diff --git a/src/crypto/pem/pem_info.c b/src/crypto/pem/pem_info.c
index 2a39a5b..57c87d4 100644
--- a/src/crypto/pem/pem_info.c
+++ b/src/crypto/pem/pem_info.c
@@ -5,21 +5,21 @@
  * This package is an SSL implementation written
  * by Eric Young (eay@cryptsoft.com).
  * The implementation was written so as to conform with Netscapes SSL.
- * 
+ *
  * This library is free for commercial and non-commercial use as long as
  * the following conditions are aheared to.  The following conditions
  * apply to all code found in this distribution, be it the RC4, RSA,
  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
  * included with this distribution is covered by the same copyright terms
  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- * 
+ *
  * Copyright remains Eric Young's, and as such any Copyright notices in
  * the code are not to be removed.
  * If this package is used in a product, Eric Young should be given attribution
  * as the author of the parts of the library used.
  * This can be in the form of a textual message at program startup or
  * in documentation (online or textual) provided with the package.
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -34,10 +34,10 @@
  *     Eric Young (eay@cryptsoft.com)"
  *    The word 'cryptographic' can be left out if the rouines from the library
  *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from 
+ * 4. If you include any Windows specific code (or a derivative thereof) from
  *    the apps directory (application code) you must include an acknowledgement:
  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- * 
+ *
  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -49,7 +49,7 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
- * 
+ *
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
@@ -71,334 +71,311 @@
 #include <openssl/rsa.h>
 #include <openssl/x509.h>
 
-
 #ifndef OPENSSL_NO_FP_API
-STACK_OF(X509_INFO) *PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb, void *u)
-	{
-        BIO *b;
-        STACK_OF(X509_INFO) *ret;
+STACK_OF(X509_INFO) *PEM_X509_INFO_read(FILE *fp, STACK_OF(X509_INFO) *sk,
+                                        pem_password_cb *cb, void *u)
+{
+    BIO *b;
+    STACK_OF(X509_INFO) *ret;
 
-        if ((b=BIO_new(BIO_s_file())) == NULL)
-		{
-		OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
-                return(0);
-		}
-        BIO_set_fp(b,fp,BIO_NOCLOSE);
-        ret=PEM_X509_INFO_read_bio(b,sk,cb,u);
-        BIO_free(b);
-        return(ret);
-	}
+    if ((b = BIO_new(BIO_s_file())) == NULL) {
+        OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
+        return (0);
+    }
+    BIO_set_fp(b, fp, BIO_NOCLOSE);
+    ret = PEM_X509_INFO_read_bio(b, sk, cb, u);
+    BIO_free(b);
+    return (ret);
+}
 #endif
 
-STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk, pem_password_cb *cb, void *u)
-	{
-	X509_INFO *xi=NULL;
-	char *name=NULL,*header=NULL;
-	void *pp;
-	unsigned char *data=NULL;
-	const unsigned char *p;
-	long len,error=0;
-	int ok=0;
-	STACK_OF(X509_INFO) *ret=NULL;
-	unsigned int i,raw,ptype;
-	d2i_of_void *d2i = 0;
+STACK_OF(X509_INFO) *PEM_X509_INFO_read_bio(BIO *bp, STACK_OF(X509_INFO) *sk,
+                                            pem_password_cb *cb, void *u)
+{
+    X509_INFO *xi = NULL;
+    char *name = NULL, *header = NULL;
+    void *pp;
+    unsigned char *data = NULL;
+    const unsigned char *p;
+    long len, error = 0;
+    int ok = 0;
+    STACK_OF(X509_INFO) *ret = NULL;
+    unsigned int i, raw, ptype;
+    d2i_of_void *d2i = 0;
 
-	if (sk == NULL)
-		{
-		if ((ret=sk_X509_INFO_new_null()) == NULL)
-			{
-			OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
-			goto err;
-			}
-		}
-	else
-		ret=sk;
+    if (sk == NULL) {
+        if ((ret = sk_X509_INFO_new_null()) == NULL) {
+            OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
+            goto err;
+        }
+    } else
+        ret = sk;
 
-	if ((xi=X509_INFO_new()) == NULL) goto err;
-	for (;;)
-		{
-		raw=0;
-		ptype = 0;
-		i=PEM_read_bio(bp,&name,&header,&data,&len);
-		if (i == 0)
-			{
-			error=ERR_GET_REASON(ERR_peek_last_error());
-			if (error == PEM_R_NO_START_LINE)
-				{
-				ERR_clear_error();
-				break;
-				}
-			goto err;
-			}
-start:
-		if (	(strcmp(name,PEM_STRING_X509) == 0) ||
-			(strcmp(name,PEM_STRING_X509_OLD) == 0))
-			{
-			d2i=(D2I_OF(void))d2i_X509;
-			if (xi->x509 != NULL)
-				{
-				if (!sk_X509_INFO_push(ret,xi)) goto err;
-				if ((xi=X509_INFO_new()) == NULL) goto err;
-				goto start;
-				}
-			pp=&(xi->x509);
-			}
-		else if ((strcmp(name,PEM_STRING_X509_TRUSTED) == 0))
-			{
-			d2i=(D2I_OF(void))d2i_X509_AUX;
-			if (xi->x509 != NULL)
-				{
-				if (!sk_X509_INFO_push(ret,xi)) goto err;
-				if ((xi=X509_INFO_new()) == NULL) goto err;
-				goto start;
-				}
-			pp=&(xi->x509);
-			}
-		else if (strcmp(name,PEM_STRING_X509_CRL) == 0)
-			{
-			d2i=(D2I_OF(void))d2i_X509_CRL;
-			if (xi->crl != NULL)
-				{
-				if (!sk_X509_INFO_push(ret,xi)) goto err;
-				if ((xi=X509_INFO_new()) == NULL) goto err;
-				goto start;
-				}
-			pp=&(xi->crl);
-			}
-		else
-			if (strcmp(name,PEM_STRING_RSA) == 0)
-			{
-			d2i=(D2I_OF(void))d2i_RSAPrivateKey;
-			if (xi->x_pkey != NULL) 
-				{
-				if (!sk_X509_INFO_push(ret,xi)) goto err;
-				if ((xi=X509_INFO_new()) == NULL) goto err;
-				goto start;
-				}
+    if ((xi = X509_INFO_new()) == NULL)
+        goto err;
+    for (;;) {
+        raw = 0;
+        ptype = 0;
+        i = PEM_read_bio(bp, &name, &header, &data, &len);
+        if (i == 0) {
+            error = ERR_GET_REASON(ERR_peek_last_error());
+            if (error == PEM_R_NO_START_LINE) {
+                ERR_clear_error();
+                break;
+            }
+            goto err;
+        }
+ start:
+        if ((strcmp(name, PEM_STRING_X509) == 0) ||
+            (strcmp(name, PEM_STRING_X509_OLD) == 0)) {
+            d2i = (D2I_OF(void)) d2i_X509;
+            if (xi->x509 != NULL) {
+                if (!sk_X509_INFO_push(ret, xi))
+                    goto err;
+                if ((xi = X509_INFO_new()) == NULL)
+                    goto err;
+                goto start;
+            }
+            pp = &(xi->x509);
+        } else if ((strcmp(name, PEM_STRING_X509_TRUSTED) == 0)) {
+            d2i = (D2I_OF(void)) d2i_X509_AUX;
+            if (xi->x509 != NULL) {
+                if (!sk_X509_INFO_push(ret, xi))
+                    goto err;
+                if ((xi = X509_INFO_new()) == NULL)
+                    goto err;
+                goto start;
+            }
+            pp = &(xi->x509);
+        } else if (strcmp(name, PEM_STRING_X509_CRL) == 0) {
+            d2i = (D2I_OF(void)) d2i_X509_CRL;
+            if (xi->crl != NULL) {
+                if (!sk_X509_INFO_push(ret, xi))
+                    goto err;
+                if ((xi = X509_INFO_new()) == NULL)
+                    goto err;
+                goto start;
+            }
+            pp = &(xi->crl);
+        } else if (strcmp(name, PEM_STRING_RSA) == 0) {
+            d2i = (D2I_OF(void)) d2i_RSAPrivateKey;
+            if (xi->x_pkey != NULL) {
+                if (!sk_X509_INFO_push(ret, xi))
+                    goto err;
+                if ((xi = X509_INFO_new()) == NULL)
+                    goto err;
+                goto start;
+            }
 
-			xi->enc_data=NULL;
-			xi->enc_len=0;
+            xi->enc_data = NULL;
+            xi->enc_len = 0;
 
-			xi->x_pkey=X509_PKEY_new();
-			ptype=EVP_PKEY_RSA;
-			pp=&xi->x_pkey->dec_pkey;
-			if ((int)strlen(header) > 10) /* assume encrypted */
-				raw=1;
-			}
-		else
+            xi->x_pkey = X509_PKEY_new();
+            ptype = EVP_PKEY_RSA;
+            pp = &xi->x_pkey->dec_pkey;
+            if ((int)strlen(header) > 10) /* assume encrypted */
+                raw = 1;
+        } else
 #ifndef OPENSSL_NO_DSA
-			if (strcmp(name,PEM_STRING_DSA) == 0)
-			{
-			d2i=(D2I_OF(void))d2i_DSAPrivateKey;
-			if (xi->x_pkey != NULL) 
-				{
-				if (!sk_X509_INFO_push(ret,xi)) goto err;
-				if ((xi=X509_INFO_new()) == NULL) goto err;
-				goto start;
-				}
+        if (strcmp(name, PEM_STRING_DSA) == 0) {
+            d2i = (D2I_OF(void)) d2i_DSAPrivateKey;
+            if (xi->x_pkey != NULL) {
+                if (!sk_X509_INFO_push(ret, xi))
+                    goto err;
+                if ((xi = X509_INFO_new()) == NULL)
+                    goto err;
+                goto start;
+            }
 
-			xi->enc_data=NULL;
-			xi->enc_len=0;
+            xi->enc_data = NULL;
+            xi->enc_len = 0;
 
-			xi->x_pkey=X509_PKEY_new();
-			ptype = EVP_PKEY_DSA;
-			pp=&xi->x_pkey->dec_pkey;
-			if ((int)strlen(header) > 10) /* assume encrypted */
-				raw=1;
-			}
-		else
+            xi->x_pkey = X509_PKEY_new();
+            ptype = EVP_PKEY_DSA;
+            pp = &xi->x_pkey->dec_pkey;
+            if ((int)strlen(header) > 10) /* assume encrypted */
+                raw = 1;
+        } else
 #endif
- 			if (strcmp(name,PEM_STRING_ECPRIVATEKEY) == 0)
- 			{
- 				d2i=(D2I_OF(void))d2i_ECPrivateKey;
- 				if (xi->x_pkey != NULL) 
- 				{
- 					if (!sk_X509_INFO_push(ret,xi)) goto err;
- 					if ((xi=X509_INFO_new()) == NULL) goto err;
- 						goto start;
- 				}
- 
- 			xi->enc_data=NULL;
- 			xi->enc_len=0;
- 
- 			xi->x_pkey=X509_PKEY_new();
-			ptype = EVP_PKEY_EC;
- 			pp=&xi->x_pkey->dec_pkey;
- 			if ((int)strlen(header) > 10) /* assume encrypted */
- 				raw=1;
-			}
-		else
-			{
-			d2i=NULL;
-			pp=NULL;
-			}
+        if (strcmp(name, PEM_STRING_ECPRIVATEKEY) == 0) {
+            d2i = (D2I_OF(void)) d2i_ECPrivateKey;
+            if (xi->x_pkey != NULL) {
+                if (!sk_X509_INFO_push(ret, xi))
+                    goto err;
+                if ((xi = X509_INFO_new()) == NULL)
+                    goto err;
+                goto start;
+            }
 
-		if (d2i != NULL)
-			{
-			if (!raw)
-				{
-				EVP_CIPHER_INFO cipher;
+            xi->enc_data = NULL;
+            xi->enc_len = 0;
 
-				if (!PEM_get_EVP_CIPHER_INFO(header,&cipher))
-					goto err;
-				if (!PEM_do_header(&cipher,data,&len,cb,u))
-					goto err;
-				p=data;
-				if (ptype)
-					{
-					if (!d2i_PrivateKey(ptype, pp, &p, len))
-						{
-						OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB);
-						goto err;
-						}
-					}
-				else if (d2i(pp,&p,len) == NULL)
-					{
-					OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB);
-					goto err;
-					}
-				}
-			else
-				{ /* encrypted RSA data */
-				if (!PEM_get_EVP_CIPHER_INFO(header,
-					&xi->enc_cipher)) goto err;
-				xi->enc_data=(char *)data;
-				xi->enc_len=(int)len;
-				data=NULL;
-				}
-			}
-		else	{
-			/* unknown */
-			}
-		if (name != NULL) OPENSSL_free(name);
-		if (header != NULL) OPENSSL_free(header);
-		if (data != NULL) OPENSSL_free(data);
-		name=NULL;
-		header=NULL;
-		data=NULL;
-		}
+            xi->x_pkey = X509_PKEY_new();
+            ptype = EVP_PKEY_EC;
+            pp = &xi->x_pkey->dec_pkey;
+            if ((int)strlen(header) > 10) /* assume encrypted */
+                raw = 1;
+        } else {
+            d2i = NULL;
+            pp = NULL;
+        }
 
-	/* if the last one hasn't been pushed yet and there is anything
-	 * in it then add it to the stack ... 
-	 */
-	if ((xi->x509 != NULL) || (xi->crl != NULL) ||
-		(xi->x_pkey != NULL) || (xi->enc_data != NULL))
-		{
-		if (!sk_X509_INFO_push(ret,xi)) goto err;
-		xi=NULL;
-		}
-	ok=1;
-err:
-	if (xi != NULL) X509_INFO_free(xi);
-	if (!ok)
-		{
-		for (i=0; i<sk_X509_INFO_num(ret); i++)
-			{
-			xi=sk_X509_INFO_value(ret,i);
-			X509_INFO_free(xi);
-			}
-		if (ret != sk) sk_X509_INFO_free(ret);
-		ret=NULL;
-		}
-		
-	if (name != NULL) OPENSSL_free(name);
-	if (header != NULL) OPENSSL_free(header);
-	if (data != NULL) OPENSSL_free(data);
-	return(ret);
-	}
+        if (d2i != NULL) {
+            if (!raw) {
+                EVP_CIPHER_INFO cipher;
 
+                if (!PEM_get_EVP_CIPHER_INFO(header, &cipher))
+                    goto err;
+                if (!PEM_do_header(&cipher, data, &len, cb, u))
+                    goto err;
+                p = data;
+                if (ptype) {
+                    if (!d2i_PrivateKey(ptype, pp, &p, len)) {
+                        OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB);
+                        goto err;
+                    }
+                } else if (d2i(pp, &p, len) == NULL) {
+                    OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB);
+                    goto err;
+                }
+            } else {            /* encrypted RSA data */
+                if (!PEM_get_EVP_CIPHER_INFO(header, &xi->enc_cipher))
+                    goto err;
+                xi->enc_data = (char *)data;
+                xi->enc_len = (int)len;
+                data = NULL;
+            }
+        } else {
+            /* unknown */
+        }
+        if (name != NULL)
+            OPENSSL_free(name);
+        if (header != NULL)
+            OPENSSL_free(header);
+        if (data != NULL)
+            OPENSSL_free(data);
+        name = NULL;
+        header = NULL;
+        data = NULL;
+    }
+
+    /*
+     * if the last one hasn't been pushed yet and there is anything in it
+     * then add it to the stack ...
+     */
+    if ((xi->x509 != NULL) || (xi->crl != NULL) ||
+        (xi->x_pkey != NULL) || (xi->enc_data != NULL)) {
+        if (!sk_X509_INFO_push(ret, xi))
+            goto err;
+        xi = NULL;
+    }
+    ok = 1;
+ err:
+    if (xi != NULL)
+        X509_INFO_free(xi);
+    if (!ok) {
+        for (i = 0; i < sk_X509_INFO_num(ret); i++) {
+            xi = sk_X509_INFO_value(ret, i);
+            X509_INFO_free(xi);
+        }
+        if (ret != sk)
+            sk_X509_INFO_free(ret);
+        ret = NULL;
+    }
+
+    if (name != NULL)
+        OPENSSL_free(name);
+    if (header != NULL)
+        OPENSSL_free(header);
+    if (data != NULL)
+        OPENSSL_free(data);
+    return (ret);
+}
 
 /* A TJH addition */
 int PEM_X509_INFO_write_bio(BIO *bp, X509_INFO *xi, EVP_CIPHER *enc,
-	     unsigned char *kstr, int klen, pem_password_cb *cb, void *u)
-	{
-	EVP_CIPHER_CTX ctx;
-	int i,ret=0;
-	unsigned char *data=NULL;
-	const char *objstr=NULL;
-	char buf[PEM_BUFSIZE];
-	unsigned char *iv=NULL;
-	unsigned iv_len = 0;
-	
-	if (enc != NULL)
-		{
-		iv_len = EVP_CIPHER_iv_length(enc);
-		objstr=OBJ_nid2sn(EVP_CIPHER_nid(enc));
-		if (objstr == NULL)
-			{
-			OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_CIPHER);
-			goto err;
-			}
-		}
+                            unsigned char *kstr, int klen,
+                            pem_password_cb *cb, void *u)
+{
+    EVP_CIPHER_CTX ctx;
+    int i, ret = 0;
+    unsigned char *data = NULL;
+    const char *objstr = NULL;
+    char buf[PEM_BUFSIZE];
+    unsigned char *iv = NULL;
+    unsigned iv_len = 0;
 
-	/* now for the fun part ... if we have a private key then 
-	 * we have to be able to handle a not-yet-decrypted key
-	 * being written out correctly ... if it is decrypted or
-	 * it is non-encrypted then we use the base code
-	 */
-	if (xi->x_pkey!=NULL)
-		{
-		if ( (xi->enc_data!=NULL) && (xi->enc_len>0) )
-			{
-			if (enc == NULL)
-				{
-				OPENSSL_PUT_ERROR(PEM, PEM_R_CIPHER_IS_NULL);
-				goto err;
-				}
+    if (enc != NULL) {
+        iv_len = EVP_CIPHER_iv_length(enc);
+        objstr = OBJ_nid2sn(EVP_CIPHER_nid(enc));
+        if (objstr == NULL) {
+            OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_CIPHER);
+            goto err;
+        }
+    }
 
-			/* copy from weirdo names into more normal things */
-			iv=xi->enc_cipher.iv;
-			data=(unsigned char *)xi->enc_data;
-			i=xi->enc_len;
+    /*
+     * now for the fun part ... if we have a private key then we have to be
+     * able to handle a not-yet-decrypted key being written out correctly ...
+     * if it is decrypted or it is non-encrypted then we use the base code
+     */
+    if (xi->x_pkey != NULL) {
+        if ((xi->enc_data != NULL) && (xi->enc_len > 0)) {
+            if (enc == NULL) {
+                OPENSSL_PUT_ERROR(PEM, PEM_R_CIPHER_IS_NULL);
+                goto err;
+            }
 
-			/* we take the encryption data from the
-			 * internal stuff rather than what the
-			 * user has passed us ... as we have to 
-			 * match exactly for some strange reason
-			 */
-			objstr=OBJ_nid2sn(
-				EVP_CIPHER_nid(xi->enc_cipher.cipher));
-			if (objstr == NULL)
-				{
-				OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_CIPHER);
-				goto err;
-				}
+            /* copy from weirdo names into more normal things */
+            iv = xi->enc_cipher.iv;
+            data = (unsigned char *)xi->enc_data;
+            i = xi->enc_len;
 
-			/* create the right magic header stuff */
-			assert(strlen(objstr)+23+2*iv_len+13 <= sizeof buf);
-			buf[0]='\0';
-			PEM_proc_type(buf,PEM_TYPE_ENCRYPTED);
-			PEM_dek_info(buf,objstr,iv_len,(char *)iv);
+            /*
+             * we take the encryption data from the internal stuff rather
+             * than what the user has passed us ... as we have to match
+             * exactly for some strange reason
+             */
+            objstr = OBJ_nid2sn(EVP_CIPHER_nid(xi->enc_cipher.cipher));
+            if (objstr == NULL) {
+                OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_CIPHER);
+                goto err;
+            }
 
-			/* use the normal code to write things out */
-			i=PEM_write_bio(bp,PEM_STRING_RSA,buf,data,i);
-			if (i <= 0) goto err;
-			}
-		else
-			{
-			/* Add DSA/DH */
-			/* normal optionally encrypted stuff */
-			if (PEM_write_bio_RSAPrivateKey(bp,
-				xi->x_pkey->dec_pkey->pkey.rsa,
-				enc,kstr,klen,cb,u)<=0)
-				goto err;
-			}
-		}
+            /* create the right magic header stuff */
+            assert(strlen(objstr) + 23 + 2 * iv_len + 13 <= sizeof buf);
+            buf[0] = '\0';
+            PEM_proc_type(buf, PEM_TYPE_ENCRYPTED);
+            PEM_dek_info(buf, objstr, iv_len, (char *)iv);
 
-	/* if we have a certificate then write it out now */
-	if ((xi->x509 != NULL) && (PEM_write_bio_X509(bp,xi->x509) <= 0))
-		goto err;
+            /* use the normal code to write things out */
+            i = PEM_write_bio(bp, PEM_STRING_RSA, buf, data, i);
+            if (i <= 0)
+                goto err;
+        } else {
+            /* Add DSA/DH */
+            /* normal optionally encrypted stuff */
+            if (PEM_write_bio_RSAPrivateKey(bp,
+                                            xi->x_pkey->dec_pkey->pkey.rsa,
+                                            enc, kstr, klen, cb, u) <= 0)
+                goto err;
+        }
+    }
 
-	/* we are ignoring anything else that is loaded into the X509_INFO
-	 * structure for the moment ... as I don't need it so I'm not
-	 * coding it here and Eric can do it when this makes it into the
-	 * base library --tjh
-	 */
+    /* if we have a certificate then write it out now */
+    if ((xi->x509 != NULL) && (PEM_write_bio_X509(bp, xi->x509) <= 0))
+        goto err;
 
-	ret=1;
+    /*
+     * we are ignoring anything else that is loaded into the X509_INFO
+     * structure for the moment ... as I don't need it so I'm not coding it
+     * here and Eric can do it when this makes it into the base library --tjh
+     */
 
-err:
-	OPENSSL_cleanse((char *)&ctx,sizeof(ctx));
-	OPENSSL_cleanse(buf,PEM_BUFSIZE);
-	return(ret);
-	}
+    ret = 1;
+
+ err:
+    OPENSSL_cleanse((char *)&ctx, sizeof(ctx));
+    OPENSSL_cleanse(buf, PEM_BUFSIZE);
+    return (ret);
+}
diff --git a/src/crypto/pem/pem_lib.c b/src/crypto/pem/pem_lib.c
index 12d9674..8b7932e 100644
--- a/src/crypto/pem/pem_lib.c
+++ b/src/crypto/pem/pem_lib.c
@@ -71,761 +71,711 @@
 #include <openssl/rand.h>
 #include <openssl/x509.h>
 
-#include "../evp/internal.h"
+#include "../internal.h"
 
 
-#define MIN_LENGTH	4
+#define MIN_LENGTH      4
 
-static int load_iv(char **fromp,unsigned char *to, int num);
+static int load_iv(char **fromp, unsigned char *to, int num);
 static int check_pem(const char *nm, const char *name);
-int pem_check_suffix(const char *pem_str, const char *suffix);
 
 void PEM_proc_type(char *buf, int type)
-	{
-	const char *str;
+{
+    const char *str;
 
-	if (type == PEM_TYPE_ENCRYPTED)
-		str="ENCRYPTED";
-	else if (type == PEM_TYPE_MIC_CLEAR)
-		str="MIC-CLEAR";
-	else if (type == PEM_TYPE_MIC_ONLY)
-		str="MIC-ONLY";
-	else
-		str="BAD-TYPE";
-		
-	BUF_strlcat(buf,"Proc-Type: 4,",PEM_BUFSIZE);
-	BUF_strlcat(buf,str,PEM_BUFSIZE);
-	BUF_strlcat(buf,"\n",PEM_BUFSIZE);
-	}
+    if (type == PEM_TYPE_ENCRYPTED)
+        str = "ENCRYPTED";
+    else if (type == PEM_TYPE_MIC_CLEAR)
+        str = "MIC-CLEAR";
+    else if (type == PEM_TYPE_MIC_ONLY)
+        str = "MIC-ONLY";
+    else
+        str = "BAD-TYPE";
+
+    BUF_strlcat(buf, "Proc-Type: 4,", PEM_BUFSIZE);
+    BUF_strlcat(buf, str, PEM_BUFSIZE);
+    BUF_strlcat(buf, "\n", PEM_BUFSIZE);
+}
 
 void PEM_dek_info(char *buf, const char *type, int len, char *str)
-	{
-	static const unsigned char map[17]="0123456789ABCDEF";
-	long i;
-	int j;
+{
+    static const unsigned char map[17] = "0123456789ABCDEF";
+    long i;
+    int j;
 
-	BUF_strlcat(buf,"DEK-Info: ",PEM_BUFSIZE);
-	BUF_strlcat(buf,type,PEM_BUFSIZE);
-	BUF_strlcat(buf,",",PEM_BUFSIZE);
-	j=strlen(buf);
-	if (j + (len * 2) + 1 > PEM_BUFSIZE)
-        	return;
-	for (i=0; i<len; i++)
-		{
-		buf[j+i*2]  =map[(str[i]>>4)&0x0f];
-		buf[j+i*2+1]=map[(str[i]   )&0x0f];
-		}
-	buf[j+i*2]='\n';
-	buf[j+i*2+1]='\0';
-	}
+    BUF_strlcat(buf, "DEK-Info: ", PEM_BUFSIZE);
+    BUF_strlcat(buf, type, PEM_BUFSIZE);
+    BUF_strlcat(buf, ",", PEM_BUFSIZE);
+    j = strlen(buf);
+    if (j + (len * 2) + 1 > PEM_BUFSIZE)
+        return;
+    for (i = 0; i < len; i++) {
+        buf[j + i * 2] = map[(str[i] >> 4) & 0x0f];
+        buf[j + i * 2 + 1] = map[(str[i]) & 0x0f];
+    }
+    buf[j + i * 2] = '\n';
+    buf[j + i * 2 + 1] = '\0';
+}
 
 #ifndef OPENSSL_NO_FP_API
 void *PEM_ASN1_read(d2i_of_void *d2i, const char *name, FILE *fp, void **x,
-		    pem_password_cb *cb, void *u)
-	{
-        BIO *b;
-        void *ret;
+                    pem_password_cb *cb, void *u)
+{
+    BIO *b;
+    void *ret;
 
-        if ((b=BIO_new(BIO_s_file())) == NULL)
-		{
-		OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
-                return(0);
-		}
-        BIO_set_fp(b,fp,BIO_NOCLOSE);
-        ret=PEM_ASN1_read_bio(d2i,name,b,x,cb,u);
-        BIO_free(b);
-        return(ret);
-	}
+    if ((b = BIO_new(BIO_s_file())) == NULL) {
+        OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
+        return (0);
+    }
+    BIO_set_fp(b, fp, BIO_NOCLOSE);
+    ret = PEM_ASN1_read_bio(d2i, name, b, x, cb, u);
+    BIO_free(b);
+    return (ret);
+}
 #endif
 
 static int check_pem(const char *nm, const char *name)
 {
-	/* Normal matching nm and name */
-	if (!strcmp(nm,name)) return 1;
+    /* Normal matching nm and name */
+    if (!strcmp(nm, name))
+        return 1;
 
-	/* Make PEM_STRING_EVP_PKEY match any private key */
+    /* Make PEM_STRING_EVP_PKEY match any private key */
 
-	if(!strcmp(name,PEM_STRING_EVP_PKEY))
-		{
-		int slen;
-		const EVP_PKEY_ASN1_METHOD *ameth;
-		if(!strcmp(nm,PEM_STRING_PKCS8))
-			return 1;
-		if(!strcmp(nm,PEM_STRING_PKCS8INF))
-			return 1;
-		slen = pem_check_suffix(nm, "PRIVATE KEY"); 
-		if (slen > 0)
-			{
-			/* NB: ENGINE implementations wont contain
-			 * a deprecated old private key decode function
-			 * so don't look for them.
-			 */
-			ameth = EVP_PKEY_asn1_find_str(NULL, nm, slen);
-			if (ameth && ameth->old_priv_decode)
-				return 1;
-			}
-		return 0;
-		}
+    if (!strcmp(name, PEM_STRING_EVP_PKEY)) {
+        return !strcmp(nm, PEM_STRING_PKCS8) ||
+               !strcmp(nm, PEM_STRING_PKCS8INF) ||
+               !strcmp(nm, PEM_STRING_RSA) ||
+               !strcmp(nm, PEM_STRING_EC) ||
+               !strcmp(nm, PEM_STRING_DSA);
+    }
 
-	if(!strcmp(name,PEM_STRING_PARAMETERS))
-		{
-		int slen;
-		const EVP_PKEY_ASN1_METHOD *ameth;
-		slen = pem_check_suffix(nm, "PARAMETERS"); 
-		if (slen > 0)
-			{
-			ENGINE *e;
-			ameth = EVP_PKEY_asn1_find_str(&e, nm, slen);
-			if (ameth)
-				{
-				int r;
-				if (ameth->param_decode)
-					r = 1;
-				else
-					r = 0;
-				return r;
-				}
-			}
-		return 0;
-		}
-	/* Permit older strings */
+    /* Permit older strings */
 
-	if(!strcmp(nm,PEM_STRING_X509_OLD) &&
-		!strcmp(name,PEM_STRING_X509)) return 1;
+    if (!strcmp(nm, PEM_STRING_X509_OLD) && !strcmp(name, PEM_STRING_X509))
+        return 1;
 
-	if(!strcmp(nm,PEM_STRING_X509_REQ_OLD) &&
-		!strcmp(name,PEM_STRING_X509_REQ)) return 1;
+    if (!strcmp(nm, PEM_STRING_X509_REQ_OLD) &&
+        !strcmp(name, PEM_STRING_X509_REQ))
+        return 1;
 
-	/* Allow normal certs to be read as trusted certs */
-	if(!strcmp(nm,PEM_STRING_X509) &&
-		!strcmp(name,PEM_STRING_X509_TRUSTED)) return 1;
+    /* Allow normal certs to be read as trusted certs */
+    if (!strcmp(nm, PEM_STRING_X509) &&
+        !strcmp(name, PEM_STRING_X509_TRUSTED))
+        return 1;
 
-	if(!strcmp(nm,PEM_STRING_X509_OLD) &&
-		!strcmp(name,PEM_STRING_X509_TRUSTED)) return 1;
+    if (!strcmp(nm, PEM_STRING_X509_OLD) &&
+        !strcmp(name, PEM_STRING_X509_TRUSTED))
+        return 1;
 
-	/* Some CAs use PKCS#7 with CERTIFICATE headers */
-	if(!strcmp(nm, PEM_STRING_X509) &&
-		!strcmp(name, PEM_STRING_PKCS7)) return 1;
+    /* Some CAs use PKCS#7 with CERTIFICATE headers */
+    if (!strcmp(nm, PEM_STRING_X509) && !strcmp(name, PEM_STRING_PKCS7))
+        return 1;
 
-	if(!strcmp(nm, PEM_STRING_PKCS7_SIGNED) &&
-		!strcmp(name, PEM_STRING_PKCS7)) return 1;
+    if (!strcmp(nm, PEM_STRING_PKCS7_SIGNED) &&
+        !strcmp(name, PEM_STRING_PKCS7))
+        return 1;
 
 #ifndef OPENSSL_NO_CMS
-	if(!strcmp(nm, PEM_STRING_X509) &&
-		!strcmp(name, PEM_STRING_CMS)) return 1;
-	/* Allow CMS to be read from PKCS#7 headers */
-	if(!strcmp(nm, PEM_STRING_PKCS7) &&
-		!strcmp(name, PEM_STRING_CMS)) return 1;
+    if (!strcmp(nm, PEM_STRING_X509) && !strcmp(name, PEM_STRING_CMS))
+        return 1;
+    /* Allow CMS to be read from PKCS#7 headers */
+    if (!strcmp(nm, PEM_STRING_PKCS7) && !strcmp(name, PEM_STRING_CMS))
+        return 1;
 #endif
 
-	return 0;
+    return 0;
 }
 
-int PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm, const char *name, BIO *bp,
-	     pem_password_cb *cb, void *u)
-	{
-	EVP_CIPHER_INFO cipher;
-	char *nm=NULL,*header=NULL;
-	unsigned char *data=NULL;
-	long len;
-	int ret = 0;
+int PEM_bytes_read_bio(unsigned char **pdata, long *plen, char **pnm,
+                       const char *name, BIO *bp, pem_password_cb *cb,
+                       void *u)
+{
+    EVP_CIPHER_INFO cipher;
+    char *nm = NULL, *header = NULL;
+    unsigned char *data = NULL;
+    long len;
+    int ret = 0;
 
-	for (;;)
-		{
-		if (!PEM_read_bio(bp,&nm,&header,&data,&len)) {
-			if(ERR_GET_REASON(ERR_peek_error()) ==
-				PEM_R_NO_START_LINE)
-				ERR_add_error_data(2, "Expecting: ", name);
-			return 0;
-		}
-		if(check_pem(nm, name)) break;
-		OPENSSL_free(nm);
-		OPENSSL_free(header);
-		OPENSSL_free(data);
-		}
-	if (!PEM_get_EVP_CIPHER_INFO(header,&cipher)) goto err;
-	if (!PEM_do_header(&cipher,data,&len,cb,u)) goto err;
+    for (;;) {
+        if (!PEM_read_bio(bp, &nm, &header, &data, &len)) {
+            if (ERR_GET_REASON(ERR_peek_error()) == PEM_R_NO_START_LINE)
+                ERR_add_error_data(2, "Expecting: ", name);
+            return 0;
+        }
+        if (check_pem(nm, name))
+            break;
+        OPENSSL_free(nm);
+        OPENSSL_free(header);
+        OPENSSL_free(data);
+    }
+    if (!PEM_get_EVP_CIPHER_INFO(header, &cipher))
+        goto err;
+    if (!PEM_do_header(&cipher, data, &len, cb, u))
+        goto err;
 
-	*pdata = data;
-	*plen = len;
+    *pdata = data;
+    *plen = len;
 
-	if (pnm)
-		*pnm = nm;
+    if (pnm)
+        *pnm = nm;
 
-	ret = 1;
+    ret = 1;
 
-err:
-	if (!ret || !pnm) OPENSSL_free(nm);
-	OPENSSL_free(header);
-	if (!ret) OPENSSL_free(data);
-	return ret;
-	}
+ err:
+    if (!ret || !pnm)
+        OPENSSL_free(nm);
+    OPENSSL_free(header);
+    if (!ret)
+        OPENSSL_free(data);
+    return ret;
+}
 
 #ifndef OPENSSL_NO_FP_API
 int PEM_ASN1_write(i2d_of_void *i2d, const char *name, FILE *fp,
-		   void *x, const EVP_CIPHER *enc, unsigned char *kstr,
-		   int klen, pem_password_cb *callback, void *u)
-        {
-        BIO *b;
-        int ret;
+                   void *x, const EVP_CIPHER *enc, unsigned char *kstr,
+                   int klen, pem_password_cb *callback, void *u)
+{
+    BIO *b;
+    int ret;
 
-        if ((b=BIO_new(BIO_s_file())) == NULL)
-		{
-		OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
-                return(0);
-		}
-        BIO_set_fp(b,fp,BIO_NOCLOSE);
-        ret=PEM_ASN1_write_bio(i2d,name,b,x,enc,kstr,klen,callback,u);
-        BIO_free(b);
-        return(ret);
-        }
+    if ((b = BIO_new(BIO_s_file())) == NULL) {
+        OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
+        return (0);
+    }
+    BIO_set_fp(b, fp, BIO_NOCLOSE);
+    ret = PEM_ASN1_write_bio(i2d, name, b, x, enc, kstr, klen, callback, u);
+    BIO_free(b);
+    return (ret);
+}
 #endif
 
 int PEM_ASN1_write_bio(i2d_of_void *i2d, const char *name, BIO *bp,
-		       void *x, const EVP_CIPHER *enc, unsigned char *kstr,
-		       int klen, pem_password_cb *callback, void *u)
-	{
-	EVP_CIPHER_CTX ctx;
-	int dsize=0,i,j,ret=0;
-	unsigned char *p,*data=NULL;
-	const char *objstr=NULL;
-	char buf[PEM_BUFSIZE];
-	unsigned char key[EVP_MAX_KEY_LENGTH];
-	unsigned char iv[EVP_MAX_IV_LENGTH];
-	
-	if (enc != NULL)
-		{
-		objstr=OBJ_nid2sn(EVP_CIPHER_nid(enc));
-		if (objstr == NULL)
-			{
-			OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_CIPHER);
-			goto err;
-			}
-		}
+                       void *x, const EVP_CIPHER *enc, unsigned char *kstr,
+                       int klen, pem_password_cb *callback, void *u)
+{
+    EVP_CIPHER_CTX ctx;
+    int dsize = 0, i, j, ret = 0;
+    unsigned char *p, *data = NULL;
+    const char *objstr = NULL;
+    char buf[PEM_BUFSIZE];
+    unsigned char key[EVP_MAX_KEY_LENGTH];
+    unsigned char iv[EVP_MAX_IV_LENGTH];
 
-	if ((dsize=i2d(x,NULL)) < 0)
-		{
-		OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB);
-		dsize=0;
-		goto err;
-		}
-	/* dzise + 8 bytes are needed */
-	/* actually it needs the cipher block size extra... */
-	data=(unsigned char *)OPENSSL_malloc((unsigned int)dsize+20);
-	if (data == NULL)
-		{
-		OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
-		goto err;
-		}
-	p=data;
-	i=i2d(x,&p);
+    if (enc != NULL) {
+        objstr = OBJ_nid2sn(EVP_CIPHER_nid(enc));
+        if (objstr == NULL || EVP_CIPHER_iv_length(enc) == 0) {
+            OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_CIPHER);
+            goto err;
+        }
+    }
 
-	if (enc != NULL)
-		{
-		const unsigned iv_len = EVP_CIPHER_iv_length(enc);
+    if ((dsize = i2d(x, NULL)) < 0) {
+        OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB);
+        dsize = 0;
+        goto err;
+    }
+    /* dzise + 8 bytes are needed */
+    /* actually it needs the cipher block size extra... */
+    data = (unsigned char *)OPENSSL_malloc((unsigned int)dsize + 20);
+    if (data == NULL) {
+        OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+    p = data;
+    i = i2d(x, &p);
 
-		if (kstr == NULL)
-			{
-			klen = 0;
-			if (!callback)
-				callback = PEM_def_callback;
- 			klen=(*callback)(buf,PEM_BUFSIZE,1,u);
-			if (klen <= 0)
-				{
-				OPENSSL_PUT_ERROR(PEM, PEM_R_READ_KEY);
-				goto err;
-				}
-			kstr=(unsigned char *)buf;
-			}
-		assert(iv_len <= (int)sizeof(iv));
-		if (!RAND_bytes(iv, iv_len)) /* Generate a salt */
-			goto err;
-		/* The 'iv' is used as the iv and as a salt.  It is
-		 * NOT taken from the BytesToKey function */
-		if (!EVP_BytesToKey(enc,EVP_md5(),iv,kstr,klen,1,key,NULL))
-			goto err;
+    if (enc != NULL) {
+        const unsigned iv_len = EVP_CIPHER_iv_length(enc);
 
-		if (kstr == (unsigned char *)buf) OPENSSL_cleanse(buf,PEM_BUFSIZE);
+        if (kstr == NULL) {
+            klen = 0;
+            if (!callback)
+                callback = PEM_def_callback;
+            klen = (*callback) (buf, PEM_BUFSIZE, 1, u);
+            if (klen <= 0) {
+                OPENSSL_PUT_ERROR(PEM, PEM_R_READ_KEY);
+                goto err;
+            }
+            kstr = (unsigned char *)buf;
+        }
+        assert(iv_len <= (int)sizeof(iv));
+        if (!RAND_bytes(iv, iv_len)) /* Generate a salt */
+            goto err;
+        /*
+         * The 'iv' is used as the iv and as a salt.  It is NOT taken from
+         * the BytesToKey function
+         */
+        if (!EVP_BytesToKey(enc, EVP_md5(), iv, kstr, klen, 1, key, NULL))
+            goto err;
 
-		assert(strlen(objstr)+23+2*iv_len+13 <= sizeof buf);
+        if (kstr == (unsigned char *)buf)
+            OPENSSL_cleanse(buf, PEM_BUFSIZE);
 
-		buf[0]='\0';
-		PEM_proc_type(buf,PEM_TYPE_ENCRYPTED);
-		PEM_dek_info(buf,objstr,iv_len,(char *)iv);
-		/* k=strlen(buf); */
+        assert(strlen(objstr) + 23 + 2 * iv_len + 13 <= sizeof buf);
 
-		EVP_CIPHER_CTX_init(&ctx);
-		ret = 1;
-		if (!EVP_EncryptInit_ex(&ctx,enc,NULL,key,iv)
-			|| !EVP_EncryptUpdate(&ctx,data,&j,data,i)
-			|| !EVP_EncryptFinal_ex(&ctx,&(data[j]),&i))
-			ret = 0;
-		else
-			i += j;
-		EVP_CIPHER_CTX_cleanup(&ctx);
-		if (ret == 0)
-			goto err;
-		}
-	else
-		{
-		ret=1;
-		buf[0]='\0';
-		}
-	i=PEM_write_bio(bp,name,buf,data,i);
-	if (i <= 0) ret=0;
-err:
-	OPENSSL_cleanse(key,sizeof(key));
-	OPENSSL_cleanse(iv,sizeof(iv));
-	OPENSSL_cleanse((char *)&ctx,sizeof(ctx));
-	OPENSSL_cleanse(buf,PEM_BUFSIZE);
-	if (data != NULL)
-		{
-		OPENSSL_cleanse(data,(unsigned int)dsize);
-		OPENSSL_free(data);
-		}
-	return(ret);
-	}
+        buf[0] = '\0';
+        PEM_proc_type(buf, PEM_TYPE_ENCRYPTED);
+        PEM_dek_info(buf, objstr, iv_len, (char *)iv);
+        /* k=strlen(buf); */
+
+        EVP_CIPHER_CTX_init(&ctx);
+        ret = 1;
+        if (!EVP_EncryptInit_ex(&ctx, enc, NULL, key, iv)
+            || !EVP_EncryptUpdate(&ctx, data, &j, data, i)
+            || !EVP_EncryptFinal_ex(&ctx, &(data[j]), &i))
+            ret = 0;
+        else
+            i += j;
+        EVP_CIPHER_CTX_cleanup(&ctx);
+        if (ret == 0)
+            goto err;
+    } else {
+        ret = 1;
+        buf[0] = '\0';
+    }
+    i = PEM_write_bio(bp, name, buf, data, i);
+    if (i <= 0)
+        ret = 0;
+ err:
+    OPENSSL_cleanse(key, sizeof(key));
+    OPENSSL_cleanse(iv, sizeof(iv));
+    OPENSSL_cleanse((char *)&ctx, sizeof(ctx));
+    OPENSSL_cleanse(buf, PEM_BUFSIZE);
+    if (data != NULL) {
+        OPENSSL_cleanse(data, (unsigned int)dsize);
+        OPENSSL_free(data);
+    }
+    return (ret);
+}
 
 int PEM_do_header(EVP_CIPHER_INFO *cipher, unsigned char *data, long *plen,
-	     pem_password_cb *callback,void *u)
-	{
-	int i=0,j,o,klen;
-	long len;
-	EVP_CIPHER_CTX ctx;
-	unsigned char key[EVP_MAX_KEY_LENGTH];
-	char buf[PEM_BUFSIZE];
+                  pem_password_cb *callback, void *u)
+{
+    int i = 0, j, o, klen;
+    long len;
+    EVP_CIPHER_CTX ctx;
+    unsigned char key[EVP_MAX_KEY_LENGTH];
+    char buf[PEM_BUFSIZE];
 
-	len= *plen;
+    len = *plen;
 
-	if (cipher->cipher == NULL) return(1);
+    if (cipher->cipher == NULL)
+        return (1);
 
-	klen = 0;
-	if (!callback) callback = PEM_def_callback;
-	klen=callback(buf,PEM_BUFSIZE,0,u);
-	if (klen <= 0)
-		{
-		OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_PASSWORD_READ);
-		return(0);
-		}
+    klen = 0;
+    if (!callback)
+        callback = PEM_def_callback;
+    klen = callback(buf, PEM_BUFSIZE, 0, u);
+    if (klen <= 0) {
+        OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_PASSWORD_READ);
+        return (0);
+    }
 
-	if (!EVP_BytesToKey(cipher->cipher,EVP_md5(),&(cipher->iv[0]),
-		(unsigned char *)buf,klen,1,key,NULL))
-		return 0;
+    if (!EVP_BytesToKey(cipher->cipher, EVP_md5(), &(cipher->iv[0]),
+                        (unsigned char *)buf, klen, 1, key, NULL))
+        return 0;
 
-	j=(int)len;
-	EVP_CIPHER_CTX_init(&ctx);
-	o = EVP_DecryptInit_ex(&ctx,cipher->cipher,NULL, key,&(cipher->iv[0]));
-	if (o)
-		o = EVP_DecryptUpdate(&ctx,data,&i,data,j);
-	if (o)
-		o = EVP_DecryptFinal_ex(&ctx,&(data[i]),&j);
-	EVP_CIPHER_CTX_cleanup(&ctx);
-	OPENSSL_cleanse((char *)buf,sizeof(buf));
-	OPENSSL_cleanse((char *)key,sizeof(key));
-	if (!o)
-		{
-		OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_DECRYPT);
-		return(0);
-		}
-	j+=i;
-	*plen=j;
-	return(1);
-	}
+    j = (int)len;
+    EVP_CIPHER_CTX_init(&ctx);
+    o = EVP_DecryptInit_ex(&ctx, cipher->cipher, NULL, key, &(cipher->iv[0]));
+    if (o)
+        o = EVP_DecryptUpdate(&ctx, data, &i, data, j);
+    if (o)
+        o = EVP_DecryptFinal_ex(&ctx, &(data[i]), &j);
+    EVP_CIPHER_CTX_cleanup(&ctx);
+    OPENSSL_cleanse((char *)buf, sizeof(buf));
+    OPENSSL_cleanse((char *)key, sizeof(key));
+    if (!o) {
+        OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_DECRYPT);
+        return (0);
+    }
+    j += i;
+    *plen = j;
+    return (1);
+}
 
-static const EVP_CIPHER* cipher_by_name(const char *name) {
-  /* This is similar to the (deprecated) function |EVP_get_cipherbyname|. */
-  if (0 == strcmp(name, SN_rc4)) {
-    return EVP_rc4();
-  } else if (0 == strcmp(name, SN_des_cbc)) {
-    return EVP_des_cbc();
-  } else if (0 == strcmp(name, SN_des_ede3_cbc)) {
-    return EVP_des_ede3_cbc();
-  } else if (0 == strcmp(name, SN_aes_128_cbc)) {
-    return EVP_aes_128_cbc();
-  } else if (0 == strcmp(name, SN_aes_192_cbc)) {
-    return EVP_aes_192_cbc();
-  } else if (0 == strcmp(name, SN_aes_256_cbc)) {
-    return EVP_aes_256_cbc();
-  } else {
-    return NULL;
-  }
+static const EVP_CIPHER *cipher_by_name(const char *name)
+{
+    /* This is similar to the (deprecated) function |EVP_get_cipherbyname|. */
+    if (0 == strcmp(name, SN_rc4)) {
+        return EVP_rc4();
+    } else if (0 == strcmp(name, SN_des_cbc)) {
+        return EVP_des_cbc();
+    } else if (0 == strcmp(name, SN_des_ede3_cbc)) {
+        return EVP_des_ede3_cbc();
+    } else if (0 == strcmp(name, SN_aes_128_cbc)) {
+        return EVP_aes_128_cbc();
+    } else if (0 == strcmp(name, SN_aes_192_cbc)) {
+        return EVP_aes_192_cbc();
+    } else if (0 == strcmp(name, SN_aes_256_cbc)) {
+        return EVP_aes_256_cbc();
+    } else {
+        return NULL;
+    }
 }
 
 int PEM_get_EVP_CIPHER_INFO(char *header, EVP_CIPHER_INFO *cipher)
-	{
-	const EVP_CIPHER *enc=NULL;
-	char *p,c;
-	char **header_pp = &header;
+{
+    const EVP_CIPHER *enc = NULL;
+    char *p, c;
+    char **header_pp = &header;
 
-	cipher->cipher=NULL;
-	if ((header == NULL) || (*header == '\0') || (*header == '\n'))
-		return(1);
-	if (strncmp(header,"Proc-Type: ",11) != 0)
-		{ OPENSSL_PUT_ERROR(PEM, PEM_R_NOT_PROC_TYPE); return(0); }
-	header+=11;
-	if (*header != '4') return(0); header++;
-	if (*header != ',') return(0); header++;
-	if (strncmp(header,"ENCRYPTED",9) != 0)
-		{ OPENSSL_PUT_ERROR(PEM, PEM_R_NOT_ENCRYPTED); return(0); }
-	for (; (*header != '\n') && (*header != '\0'); header++)
-		;
-	if (*header == '\0')
-		{ OPENSSL_PUT_ERROR(PEM, PEM_R_SHORT_HEADER); return(0); }
-	header++;
-	if (strncmp(header,"DEK-Info: ",10) != 0)
-		{ OPENSSL_PUT_ERROR(PEM, PEM_R_NOT_DEK_INFO); return(0); }
-	header+=10;
+    cipher->cipher = NULL;
+    if ((header == NULL) || (*header == '\0') || (*header == '\n'))
+        return (1);
+    if (strncmp(header, "Proc-Type: ", 11) != 0) {
+        OPENSSL_PUT_ERROR(PEM, PEM_R_NOT_PROC_TYPE);
+        return (0);
+    }
+    header += 11;
+    if (*header != '4')
+        return (0);
+    header++;
+    if (*header != ',')
+        return (0);
+    header++;
+    if (strncmp(header, "ENCRYPTED", 9) != 0) {
+        OPENSSL_PUT_ERROR(PEM, PEM_R_NOT_ENCRYPTED);
+        return (0);
+    }
+    for (; (*header != '\n') && (*header != '\0'); header++) ;
+    if (*header == '\0') {
+        OPENSSL_PUT_ERROR(PEM, PEM_R_SHORT_HEADER);
+        return (0);
+    }
+    header++;
+    if (strncmp(header, "DEK-Info: ", 10) != 0) {
+        OPENSSL_PUT_ERROR(PEM, PEM_R_NOT_DEK_INFO);
+        return (0);
+    }
+    header += 10;
 
-	p=header;
-	for (;;)
-		{
-		c= *header;
-		if (!(	((c >= 'A') && (c <= 'Z')) || (c == '-') ||
-			((c >= '0') && (c <= '9'))))
-			break;
-		header++;
-		}
-	*header='\0';
-	cipher->cipher=enc=cipher_by_name(p);
-	*header=c;
-	header++;
+    p = header;
+    for (;;) {
+        c = *header;
+        if (!(((c >= 'A') && (c <= 'Z')) || (c == '-') ||
+              ((c >= '0') && (c <= '9'))))
+            break;
+        header++;
+    }
+    *header = '\0';
+    cipher->cipher = enc = cipher_by_name(p);
+    *header = c;
+    header++;
 
-	if (enc == NULL)
-		{
-		OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_ENCRYPTION);
-		return(0);
-		}
-	if (!load_iv(header_pp,&(cipher->iv[0]),EVP_CIPHER_iv_length(enc)))
-		return(0);
+    if (enc == NULL) {
+        OPENSSL_PUT_ERROR(PEM, PEM_R_UNSUPPORTED_ENCRYPTION);
+        return (0);
+    }
+    if (!load_iv(header_pp, &(cipher->iv[0]), EVP_CIPHER_iv_length(enc)))
+        return (0);
 
-	return(1);
-	}
+    return (1);
+}
 
 static int load_iv(char **fromp, unsigned char *to, int num)
-	{
-	int v,i;
-	char *from;
+{
+    int v, i;
+    char *from;
 
-	from= *fromp;
-	for (i=0; i<num; i++) to[i]=0;
-	num*=2;
-	for (i=0; i<num; i++)
-		{
-		if ((*from >= '0') && (*from <= '9'))
-			v= *from-'0';
-		else if ((*from >= 'A') && (*from <= 'F'))
-			v= *from-'A'+10;
-		else if ((*from >= 'a') && (*from <= 'f'))
-			v= *from-'a'+10;
-		else
-			{
-			OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_IV_CHARS);
-			return(0);
-			}
-		from++;
-		to[i/2]|=v<<(long)((!(i&1))*4);
-		}
+    from = *fromp;
+    for (i = 0; i < num; i++)
+        to[i] = 0;
+    num *= 2;
+    for (i = 0; i < num; i++) {
+        if ((*from >= '0') && (*from <= '9'))
+            v = *from - '0';
+        else if ((*from >= 'A') && (*from <= 'F'))
+            v = *from - 'A' + 10;
+        else if ((*from >= 'a') && (*from <= 'f'))
+            v = *from - 'a' + 10;
+        else {
+            OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_IV_CHARS);
+            return (0);
+        }
+        from++;
+        to[i / 2] |= v << (long)((!(i & 1)) * 4);
+    }
 
-	*fromp=from;
-	return(1);
-	}
+    *fromp = from;
+    return (1);
+}
 
 #ifndef OPENSSL_NO_FP_API
 int PEM_write(FILE *fp, const char *name, const char *header,
-	      const unsigned char *data, long len)
-        {
-        BIO *b;
-        int ret;
+              const unsigned char *data, long len)
+{
+    BIO *b;
+    int ret;
 
-        if ((b=BIO_new(BIO_s_file())) == NULL)
-		{
-		OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
-                return(0);
-		}
-        BIO_set_fp(b,fp,BIO_NOCLOSE);
-        ret=PEM_write_bio(b, name, header, data,len);
-        BIO_free(b);
-        return(ret);
-        }
+    if ((b = BIO_new(BIO_s_file())) == NULL) {
+        OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
+        return (0);
+    }
+    BIO_set_fp(b, fp, BIO_NOCLOSE);
+    ret = PEM_write_bio(b, name, header, data, len);
+    BIO_free(b);
+    return (ret);
+}
 #endif
 
 int PEM_write_bio(BIO *bp, const char *name, const char *header,
-		  const unsigned char *data, long len)
-	{
-	int nlen,n,i,j,outl;
-	unsigned char *buf = NULL;
-	EVP_ENCODE_CTX ctx;
-	int reason=ERR_R_BUF_LIB;
-	
-	EVP_EncodeInit(&ctx);
-	nlen=strlen(name);
+                  const unsigned char *data, long len)
+{
+    int nlen, n, i, j, outl;
+    unsigned char *buf = NULL;
+    EVP_ENCODE_CTX ctx;
+    int reason = ERR_R_BUF_LIB;
 
-	if (	(BIO_write(bp,"-----BEGIN ",11) != 11) ||
-		(BIO_write(bp,name,nlen) != nlen) ||
-		(BIO_write(bp,"-----\n",6) != 6))
-		goto err;
-		
-	i=strlen(header);
-	if (i > 0)
-		{
-		if (	(BIO_write(bp,header,i) != i) ||
-			(BIO_write(bp,"\n",1) != 1))
-			goto err;
-		}
+    EVP_EncodeInit(&ctx);
+    nlen = strlen(name);
 
-	buf = OPENSSL_malloc(PEM_BUFSIZE*8);
-	if (buf == NULL)
-		{
-		reason=ERR_R_MALLOC_FAILURE;
-		goto err;
-		}
+    if ((BIO_write(bp, "-----BEGIN ", 11) != 11) ||
+        (BIO_write(bp, name, nlen) != nlen) ||
+        (BIO_write(bp, "-----\n", 6) != 6))
+        goto err;
 
-	i=j=0;
-	while (len > 0)
-		{
-		n=(int)((len>(PEM_BUFSIZE*5))?(PEM_BUFSIZE*5):len);
-		EVP_EncodeUpdate(&ctx,buf,&outl,&(data[j]),n);
-		if ((outl) && (BIO_write(bp,(char *)buf,outl) != outl))
-			goto err;
-		i+=outl;
-		len-=n;
-		j+=n;
-		}
-	EVP_EncodeFinal(&ctx,buf,&outl);
-	if ((outl > 0) && (BIO_write(bp,(char *)buf,outl) != outl)) goto err;
-	OPENSSL_cleanse(buf, PEM_BUFSIZE*8);
-	OPENSSL_free(buf);
-	buf = NULL;
-	if (	(BIO_write(bp,"-----END ",9) != 9) ||
-		(BIO_write(bp,name,nlen) != nlen) ||
-		(BIO_write(bp,"-----\n",6) != 6))
-		goto err;
-	return(i+outl);
-err:
-	if (buf) {
-		OPENSSL_cleanse(buf, PEM_BUFSIZE*8);
-		OPENSSL_free(buf);
-	}
-	OPENSSL_PUT_ERROR(PEM, reason);
-	return(0);
-	}
+    i = strlen(header);
+    if (i > 0) {
+        if ((BIO_write(bp, header, i) != i) || (BIO_write(bp, "\n", 1) != 1))
+            goto err;
+    }
+
+    buf = OPENSSL_malloc(PEM_BUFSIZE * 8);
+    if (buf == NULL) {
+        reason = ERR_R_MALLOC_FAILURE;
+        goto err;
+    }
+
+    i = j = 0;
+    while (len > 0) {
+        n = (int)((len > (PEM_BUFSIZE * 5)) ? (PEM_BUFSIZE * 5) : len);
+        EVP_EncodeUpdate(&ctx, buf, &outl, &(data[j]), n);
+        if ((outl) && (BIO_write(bp, (char *)buf, outl) != outl))
+            goto err;
+        i += outl;
+        len -= n;
+        j += n;
+    }
+    EVP_EncodeFinal(&ctx, buf, &outl);
+    if ((outl > 0) && (BIO_write(bp, (char *)buf, outl) != outl))
+        goto err;
+    OPENSSL_cleanse(buf, PEM_BUFSIZE * 8);
+    OPENSSL_free(buf);
+    buf = NULL;
+    if ((BIO_write(bp, "-----END ", 9) != 9) ||
+        (BIO_write(bp, name, nlen) != nlen) ||
+        (BIO_write(bp, "-----\n", 6) != 6))
+        goto err;
+    return (i + outl);
+ err:
+    if (buf) {
+        OPENSSL_cleanse(buf, PEM_BUFSIZE * 8);
+        OPENSSL_free(buf);
+    }
+    OPENSSL_PUT_ERROR(PEM, reason);
+    return (0);
+}
 
 #ifndef OPENSSL_NO_FP_API
 int PEM_read(FILE *fp, char **name, char **header, unsigned char **data,
-	     long *len)
-        {
-        BIO *b;
-        int ret;
+             long *len)
+{
+    BIO *b;
+    int ret;
 
-        if ((b=BIO_new(BIO_s_file())) == NULL)
-		{
-		OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
-                return(0);
-		}
-        BIO_set_fp(b,fp,BIO_NOCLOSE);
-        ret=PEM_read_bio(b, name, header, data,len);
-        BIO_free(b);
-        return(ret);
-        }
+    if ((b = BIO_new(BIO_s_file())) == NULL) {
+        OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
+        return (0);
+    }
+    BIO_set_fp(b, fp, BIO_NOCLOSE);
+    ret = PEM_read_bio(b, name, header, data, len);
+    BIO_free(b);
+    return (ret);
+}
 #endif
 
 int PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data,
-	     long *len)
-	{
-	EVP_ENCODE_CTX ctx;
-	int end=0,i,k,bl=0,hl=0,nohead=0;
-	char buf[256];
-	BUF_MEM *nameB;
-	BUF_MEM *headerB;
-	BUF_MEM *dataB,*tmpB;
-	
-	nameB=BUF_MEM_new();
-	headerB=BUF_MEM_new();
-	dataB=BUF_MEM_new();
-	if ((nameB == NULL) || (headerB == NULL) || (dataB == NULL))
-		{
-		BUF_MEM_free(nameB);
-		BUF_MEM_free(headerB);
-		BUF_MEM_free(dataB);
-		OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
-		return(0);
-		}
+                 long *len)
+{
+    EVP_ENCODE_CTX ctx;
+    int end = 0, i, k, bl = 0, hl = 0, nohead = 0;
+    char buf[256];
+    BUF_MEM *nameB;
+    BUF_MEM *headerB;
+    BUF_MEM *dataB, *tmpB;
 
-	buf[254]='\0';
-	for (;;)
-		{
-		i=BIO_gets(bp,buf,254);
+    nameB = BUF_MEM_new();
+    headerB = BUF_MEM_new();
+    dataB = BUF_MEM_new();
+    if ((nameB == NULL) || (headerB == NULL) || (dataB == NULL)) {
+        BUF_MEM_free(nameB);
+        BUF_MEM_free(headerB);
+        BUF_MEM_free(dataB);
+        OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
+        return (0);
+    }
 
-		if (i <= 0)
-			{
-			OPENSSL_PUT_ERROR(PEM, PEM_R_NO_START_LINE);
-			goto err;
-			}
+    buf[254] = '\0';
+    for (;;) {
+        i = BIO_gets(bp, buf, 254);
 
-		while ((i >= 0) && (buf[i] <= ' ')) i--;
-		buf[++i]='\n'; buf[++i]='\0';
+        if (i <= 0) {
+            OPENSSL_PUT_ERROR(PEM, PEM_R_NO_START_LINE);
+            goto err;
+        }
 
-		if (strncmp(buf,"-----BEGIN ",11) == 0)
-			{
-			i=strlen(&(buf[11]));
+        while ((i >= 0) && (buf[i] <= ' '))
+            i--;
+        buf[++i] = '\n';
+        buf[++i] = '\0';
 
-			if (strncmp(&(buf[11+i-6]),"-----\n",6) != 0)
-				continue;
-			if (!BUF_MEM_grow(nameB,i+9))
-				{
-				OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
-				goto err;
-				}
-			memcpy(nameB->data,&(buf[11]),i-6);
-			nameB->data[i-6]='\0';
-			break;
-			}
-		}
-	hl=0;
-	if (!BUF_MEM_grow(headerB,256))
-		{ OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); goto err; }
-	headerB->data[0]='\0';
-	for (;;)
-		{
-		i=BIO_gets(bp,buf,254);
-		if (i <= 0) break;
+        if (strncmp(buf, "-----BEGIN ", 11) == 0) {
+            i = strlen(&(buf[11]));
 
-		while ((i >= 0) && (buf[i] <= ' ')) i--;
-		buf[++i]='\n'; buf[++i]='\0';
+            if (strncmp(&(buf[11 + i - 6]), "-----\n", 6) != 0)
+                continue;
+            if (!BUF_MEM_grow(nameB, i + 9)) {
+                OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
+                goto err;
+            }
+            OPENSSL_memcpy(nameB->data, &(buf[11]), i - 6);
+            nameB->data[i - 6] = '\0';
+            break;
+        }
+    }
+    hl = 0;
+    if (!BUF_MEM_grow(headerB, 256)) {
+        OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+    headerB->data[0] = '\0';
+    for (;;) {
+        i = BIO_gets(bp, buf, 254);
+        if (i <= 0)
+            break;
 
-		if (buf[0] == '\n') break;
-		if (!BUF_MEM_grow(headerB,hl+i+9))
-			{ OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); goto err; }
-		if (strncmp(buf,"-----END ",9) == 0)
-			{
-			nohead=1;
-			break;
-			}
-		memcpy(&(headerB->data[hl]),buf,i);
-		headerB->data[hl+i]='\0';
-		hl+=i;
-		}
+        while ((i >= 0) && (buf[i] <= ' '))
+            i--;
+        buf[++i] = '\n';
+        buf[++i] = '\0';
 
-	bl=0;
-	if (!BUF_MEM_grow(dataB,1024))
-		{ OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE); goto err; }
-	dataB->data[0]='\0';
-	if (!nohead)
-		{
-		for (;;)
-			{
-			i=BIO_gets(bp,buf,254);
-			if (i <= 0) break;
+        if (buf[0] == '\n')
+            break;
+        if (!BUF_MEM_grow(headerB, hl + i + 9)) {
+            OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
+            goto err;
+        }
+        if (strncmp(buf, "-----END ", 9) == 0) {
+            nohead = 1;
+            break;
+        }
+        OPENSSL_memcpy(&(headerB->data[hl]), buf, i);
+        headerB->data[hl + i] = '\0';
+        hl += i;
+    }
 
-			while ((i >= 0) && (buf[i] <= ' ')) i--;
-			buf[++i]='\n'; buf[++i]='\0';
+    bl = 0;
+    if (!BUF_MEM_grow(dataB, 1024)) {
+        OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+    dataB->data[0] = '\0';
+    if (!nohead) {
+        for (;;) {
+            i = BIO_gets(bp, buf, 254);
+            if (i <= 0)
+                break;
 
-			if (i != 65) end=1;
-			if (strncmp(buf,"-----END ",9) == 0)
-				break;
-			if (i > 65) break;
-			if (!BUF_MEM_grow_clean(dataB,i+bl+9))
-				{
-				OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
-				goto err;
-				}
-			memcpy(&(dataB->data[bl]),buf,i);
-			dataB->data[bl+i]='\0';
-			bl+=i;
-			if (end)
-				{
-				buf[0]='\0';
-				i=BIO_gets(bp,buf,254);
-				if (i <= 0) break;
+            while ((i >= 0) && (buf[i] <= ' '))
+                i--;
+            buf[++i] = '\n';
+            buf[++i] = '\0';
 
-				while ((i >= 0) && (buf[i] <= ' ')) i--;
-				buf[++i]='\n'; buf[++i]='\0';
+            if (i != 65)
+                end = 1;
+            if (strncmp(buf, "-----END ", 9) == 0)
+                break;
+            if (i > 65)
+                break;
+            if (!BUF_MEM_grow_clean(dataB, i + bl + 9)) {
+                OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
+                goto err;
+            }
+            OPENSSL_memcpy(&(dataB->data[bl]), buf, i);
+            dataB->data[bl + i] = '\0';
+            bl += i;
+            if (end) {
+                buf[0] = '\0';
+                i = BIO_gets(bp, buf, 254);
+                if (i <= 0)
+                    break;
 
-				break;
-				}
-			}
-		}
-	else
-		{
-		tmpB=headerB;
-		headerB=dataB;
-		dataB=tmpB;
-		bl=hl;
-		}
-	i=strlen(nameB->data);
-	if (	(strncmp(buf,"-----END ",9) != 0) ||
-		(strncmp(nameB->data,&(buf[9]),i) != 0) ||
-		(strncmp(&(buf[9+i]),"-----\n",6) != 0))
-		{
-		OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_END_LINE);
-		goto err;
-		}
+                while ((i >= 0) && (buf[i] <= ' '))
+                    i--;
+                buf[++i] = '\n';
+                buf[++i] = '\0';
 
-	EVP_DecodeInit(&ctx);
-	i=EVP_DecodeUpdate(&ctx,
-		(unsigned char *)dataB->data,&bl,
-		(unsigned char *)dataB->data,bl);
-	if (i < 0)
-		{
-		OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_BASE64_DECODE);
-		goto err;
-		}
-	i=EVP_DecodeFinal(&ctx,(unsigned char *)&(dataB->data[bl]),&k);
-	if (i < 0)
-		{
-		OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_BASE64_DECODE);
-		goto err;
-		}
-	bl+=k;
+                break;
+            }
+        }
+    } else {
+        tmpB = headerB;
+        headerB = dataB;
+        dataB = tmpB;
+        bl = hl;
+    }
+    i = strlen(nameB->data);
+    if ((strncmp(buf, "-----END ", 9) != 0) ||
+        (strncmp(nameB->data, &(buf[9]), i) != 0) ||
+        (strncmp(&(buf[9 + i]), "-----\n", 6) != 0)) {
+        OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_END_LINE);
+        goto err;
+    }
 
-	if (bl == 0) goto err;
-	*name=nameB->data;
-	*header=headerB->data;
-	*data=(unsigned char *)dataB->data;
-	*len=bl;
-	OPENSSL_free(nameB);
-	OPENSSL_free(headerB);
-	OPENSSL_free(dataB);
-	return(1);
-err:
-	BUF_MEM_free(nameB);
-	BUF_MEM_free(headerB);
-	BUF_MEM_free(dataB);
-	return(0);
-	}
+    EVP_DecodeInit(&ctx);
+    i = EVP_DecodeUpdate(&ctx,
+                         (unsigned char *)dataB->data, &bl,
+                         (unsigned char *)dataB->data, bl);
+    if (i < 0) {
+        OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_BASE64_DECODE);
+        goto err;
+    }
+    i = EVP_DecodeFinal(&ctx, (unsigned char *)&(dataB->data[bl]), &k);
+    if (i < 0) {
+        OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_BASE64_DECODE);
+        goto err;
+    }
+    bl += k;
 
-/* Check pem string and return prefix length.
- * If for example the pem_str == "RSA PRIVATE KEY" and suffix = "PRIVATE KEY"
- * the return value is 3 for the string "RSA".
- */
-
-int pem_check_suffix(const char *pem_str, const char *suffix)
-	{
-	int pem_len = strlen(pem_str);
-	int suffix_len = strlen(suffix);
-	const char *p;
-	if (suffix_len + 1 >= pem_len)
-		return 0;
-	p = pem_str + pem_len - suffix_len;
-	if (strcmp(p, suffix))
-		return 0;
-	p--;
-	if (*p != ' ')
-		return 0;
-	return p - pem_str;
-	}
+    if (bl == 0)
+        goto err;
+    *name = nameB->data;
+    *header = headerB->data;
+    *data = (unsigned char *)dataB->data;
+    *len = bl;
+    OPENSSL_free(nameB);
+    OPENSSL_free(headerB);
+    OPENSSL_free(dataB);
+    return (1);
+ err:
+    BUF_MEM_free(nameB);
+    BUF_MEM_free(headerB);
+    BUF_MEM_free(dataB);
+    return (0);
+}
 
 int PEM_def_callback(char *buf, int size, int rwflag, void *userdata)
-	{
-	if (!buf || !userdata)
-		{
-		return 0;
-		}
-	size_t len = strlen((char *) userdata);
-	if (len >= (size_t) size)
-		{
-		return 0;
-		}
-	strcpy(buf, (char *) userdata);
-	return len;
-	}
+{
+    if (!buf || !userdata) {
+        return 0;
+    }
+    size_t len = strlen((char *)userdata);
+    if (len >= (size_t)size) {
+        return 0;
+    }
+    strcpy(buf, (char *)userdata);
+    return len;
+}
diff --git a/src/crypto/pem/pem_oth.c b/src/crypto/pem/pem_oth.c
index 3e8f6bd..8530c56 100644
--- a/src/crypto/pem/pem_oth.c
+++ b/src/crypto/pem/pem_oth.c
@@ -67,23 +67,22 @@
 #include <openssl/rand.h>
 #include <openssl/x509.h>
 
-
 /* Handle 'other' PEMs: not private keys */
 
 void *PEM_ASN1_read_bio(d2i_of_void *d2i, const char *name, BIO *bp, void **x,
-			pem_password_cb *cb, void *u)
-	{
-	const unsigned char *p=NULL;
-	unsigned char *data=NULL;
-	long len;
-	char *ret=NULL;
+                        pem_password_cb *cb, void *u)
+{
+    const unsigned char *p = NULL;
+    unsigned char *data = NULL;
+    long len;
+    char *ret = NULL;
 
-	if (!PEM_bytes_read_bio(&data, &len, NULL, name, bp, cb, u))
-		return NULL;
-	p = data;
-	ret=d2i(x,&p,len);
-	if (ret == NULL)
-		OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB);
-	OPENSSL_free(data);
-	return ret;
-	}
+    if (!PEM_bytes_read_bio(&data, &len, NULL, name, bp, cb, u))
+        return NULL;
+    p = data;
+    ret = d2i(x, &p, len);
+    if (ret == NULL)
+        OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB);
+    OPENSSL_free(data);
+    return ret;
+}
diff --git a/src/crypto/pem/pem_pk8.c b/src/crypto/pem/pem_pk8.c
index 0824477..550661d 100644
--- a/src/crypto/pem/pem_pk8.c
+++ b/src/crypto/pem/pem_pk8.c
@@ -65,180 +65,193 @@
 #include <openssl/rand.h>
 #include <openssl/x509.h>
 
-
 static int do_pk8pkey(BIO *bp, EVP_PKEY *x, int isder,
-				int nid, const EVP_CIPHER *enc,
-				char *kstr, int klen,
-				pem_password_cb *cb, void *u);
+                      int nid, const EVP_CIPHER *enc,
+                      char *kstr, int klen, pem_password_cb *cb, void *u);
 static int do_pk8pkey_fp(FILE *bp, EVP_PKEY *x, int isder,
-				int nid, const EVP_CIPHER *enc,
-				char *kstr, int klen,
-				pem_password_cb *cb, void *u);
+                         int nid, const EVP_CIPHER *enc,
+                         char *kstr, int klen, pem_password_cb *cb, void *u);
 
-/* These functions write a private key in PKCS#8 format: it is a "drop in"
+/*
+ * These functions write a private key in PKCS#8 format: it is a "drop in"
  * replacement for PEM_write_bio_PrivateKey() and friends. As usual if 'enc'
  * is NULL then it uses the unencrypted private key form. The 'nid' versions
  * uses PKCS#5 v1.5 PBE algorithms whereas the others use PKCS#5 v2.0.
  */
 
 int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, EVP_PKEY *x, int nid,
-				  char *kstr, int klen,
-				  pem_password_cb *cb, void *u)
+                                      char *kstr, int klen,
+                                      pem_password_cb *cb, void *u)
 {
-	return do_pk8pkey(bp, x, 0, nid, NULL, kstr, klen, cb, u);
+    return do_pk8pkey(bp, x, 0, nid, NULL, kstr, klen, cb, u);
 }
 
 int PEM_write_bio_PKCS8PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
-				  char *kstr, int klen,
-				  pem_password_cb *cb, void *u)
+                                  char *kstr, int klen,
+                                  pem_password_cb *cb, void *u)
 {
-	return do_pk8pkey(bp, x, 0, -1, enc, kstr, klen, cb, u);
+    return do_pk8pkey(bp, x, 0, -1, enc, kstr, klen, cb, u);
 }
 
 int i2d_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
-				  char *kstr, int klen,
-				  pem_password_cb *cb, void *u)
+                            char *kstr, int klen,
+                            pem_password_cb *cb, void *u)
 {
-	return do_pk8pkey(bp, x, 1, -1, enc, kstr, klen, cb, u);
+    return do_pk8pkey(bp, x, 1, -1, enc, kstr, klen, cb, u);
 }
 
 int i2d_PKCS8PrivateKey_nid_bio(BIO *bp, EVP_PKEY *x, int nid,
-				  char *kstr, int klen,
-				  pem_password_cb *cb, void *u)
+                                char *kstr, int klen,
+                                pem_password_cb *cb, void *u)
 {
-	return do_pk8pkey(bp, x, 1, nid, NULL, kstr, klen, cb, u);
+    return do_pk8pkey(bp, x, 1, nid, NULL, kstr, klen, cb, u);
 }
 
-static int do_pk8pkey(BIO *bp, EVP_PKEY *x, int isder, int nid, const EVP_CIPHER *enc,
-				  char *kstr, int klen,
-				  pem_password_cb *cb, void *u)
+static int do_pk8pkey(BIO *bp, EVP_PKEY *x, int isder, int nid,
+                      const EVP_CIPHER *enc, char *kstr, int klen,
+                      pem_password_cb *cb, void *u)
 {
-	X509_SIG *p8;
-	PKCS8_PRIV_KEY_INFO *p8inf;
-	char buf[PEM_BUFSIZE];
-	int ret;
-	if(!(p8inf = EVP_PKEY2PKCS8(x))) {
-		OPENSSL_PUT_ERROR(PEM, PEM_R_ERROR_CONVERTING_PRIVATE_KEY);
-		return 0;
-	}
-	if(enc || (nid != -1)) {
-		if(!kstr) {
-			klen = 0;
-			if (!cb) cb = PEM_def_callback;
-			klen = cb(buf, PEM_BUFSIZE, 1, u);
-			if(klen <= 0) {
-				OPENSSL_PUT_ERROR(PEM, PEM_R_READ_KEY);
-				PKCS8_PRIV_KEY_INFO_free(p8inf);
-				return 0;
-			}
-				
-			kstr = buf;
-		}
-		p8 = PKCS8_encrypt(nid, enc, kstr, klen, NULL, 0, 0, p8inf);
-		if(kstr == buf) OPENSSL_cleanse(buf, klen);
-		PKCS8_PRIV_KEY_INFO_free(p8inf);
-		if(isder) ret = i2d_PKCS8_bio(bp, p8);
-		else ret = PEM_write_bio_PKCS8(bp, p8);
-		X509_SIG_free(p8);
-		return ret;
-	} else {
-		if(isder) ret = i2d_PKCS8_PRIV_KEY_INFO_bio(bp, p8inf);
-		else ret = PEM_write_bio_PKCS8_PRIV_KEY_INFO(bp, p8inf);
-		PKCS8_PRIV_KEY_INFO_free(p8inf);
-		return ret;
-	}
+    X509_SIG *p8;
+    PKCS8_PRIV_KEY_INFO *p8inf;
+    char buf[PEM_BUFSIZE];
+    int ret;
+    if (!(p8inf = EVP_PKEY2PKCS8(x))) {
+        OPENSSL_PUT_ERROR(PEM, PEM_R_ERROR_CONVERTING_PRIVATE_KEY);
+        return 0;
+    }
+    if (enc || (nid != -1)) {
+        if (!kstr) {
+            klen = 0;
+            if (!cb)
+                cb = PEM_def_callback;
+            klen = cb(buf, PEM_BUFSIZE, 1, u);
+            if (klen <= 0) {
+                OPENSSL_PUT_ERROR(PEM, PEM_R_READ_KEY);
+                PKCS8_PRIV_KEY_INFO_free(p8inf);
+                return 0;
+            }
+
+            kstr = buf;
+        }
+        p8 = PKCS8_encrypt(nid, enc, kstr, klen, NULL, 0, 0, p8inf);
+        if (kstr == buf)
+            OPENSSL_cleanse(buf, klen);
+        PKCS8_PRIV_KEY_INFO_free(p8inf);
+        if (isder)
+            ret = i2d_PKCS8_bio(bp, p8);
+        else
+            ret = PEM_write_bio_PKCS8(bp, p8);
+        X509_SIG_free(p8);
+        return ret;
+    } else {
+        if (isder)
+            ret = i2d_PKCS8_PRIV_KEY_INFO_bio(bp, p8inf);
+        else
+            ret = PEM_write_bio_PKCS8_PRIV_KEY_INFO(bp, p8inf);
+        PKCS8_PRIV_KEY_INFO_free(p8inf);
+        return ret;
+    }
 }
 
-EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, void *u)
+EVP_PKEY *d2i_PKCS8PrivateKey_bio(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
+                                  void *u)
 {
-	PKCS8_PRIV_KEY_INFO *p8inf = NULL;
-	X509_SIG *p8 = NULL;
-	int klen;
-	EVP_PKEY *ret;
-	char psbuf[PEM_BUFSIZE];
-	p8 = d2i_PKCS8_bio(bp, NULL);
-	if(!p8) return NULL;
+    PKCS8_PRIV_KEY_INFO *p8inf = NULL;
+    X509_SIG *p8 = NULL;
+    int klen;
+    EVP_PKEY *ret;
+    char psbuf[PEM_BUFSIZE];
+    p8 = d2i_PKCS8_bio(bp, NULL);
+    if (!p8)
+        return NULL;
 
-	klen = 0;
-	if (!cb) cb = PEM_def_callback;
-	klen=cb(psbuf,PEM_BUFSIZE,0,u);
-	if (klen <= 0) {
-		OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_PASSWORD_READ);
-		X509_SIG_free(p8);
-		return NULL;	
-	}
-	p8inf = PKCS8_decrypt(p8, psbuf, klen);
-	X509_SIG_free(p8);
-	if(!p8inf) return NULL;
-	ret = EVP_PKCS82PKEY(p8inf);
-	PKCS8_PRIV_KEY_INFO_free(p8inf);
-	if(!ret) return NULL;
-	if(x) {
-		if(*x) EVP_PKEY_free(*x);
-		*x = ret;
-	}
-	return ret;
+    klen = 0;
+    if (!cb)
+        cb = PEM_def_callback;
+    klen = cb(psbuf, PEM_BUFSIZE, 0, u);
+    if (klen <= 0) {
+        OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_PASSWORD_READ);
+        X509_SIG_free(p8);
+        return NULL;
+    }
+    p8inf = PKCS8_decrypt(p8, psbuf, klen);
+    X509_SIG_free(p8);
+    if (!p8inf)
+        return NULL;
+    ret = EVP_PKCS82PKEY(p8inf);
+    PKCS8_PRIV_KEY_INFO_free(p8inf);
+    if (!ret)
+        return NULL;
+    if (x) {
+        if (*x)
+            EVP_PKEY_free(*x);
+        *x = ret;
+    }
+    return ret;
 }
 
 #ifndef OPENSSL_NO_FP_API
 
 int i2d_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
-				  char *kstr, int klen,
-				  pem_password_cb *cb, void *u)
+                           char *kstr, int klen, pem_password_cb *cb, void *u)
 {
-	return do_pk8pkey_fp(fp, x, 1, -1, enc, kstr, klen, cb, u);
+    return do_pk8pkey_fp(fp, x, 1, -1, enc, kstr, klen, cb, u);
 }
 
 int i2d_PKCS8PrivateKey_nid_fp(FILE *fp, EVP_PKEY *x, int nid,
-				  char *kstr, int klen,
-				  pem_password_cb *cb, void *u)
+                               char *kstr, int klen,
+                               pem_password_cb *cb, void *u)
 {
-	return do_pk8pkey_fp(fp, x, 1, nid, NULL, kstr, klen, cb, u);
+    return do_pk8pkey_fp(fp, x, 1, nid, NULL, kstr, klen, cb, u);
 }
 
 int PEM_write_PKCS8PrivateKey_nid(FILE *fp, EVP_PKEY *x, int nid,
-				  char *kstr, int klen,
-				  pem_password_cb *cb, void *u)
+                                  char *kstr, int klen,
+                                  pem_password_cb *cb, void *u)
 {
-	return do_pk8pkey_fp(fp, x, 0, nid, NULL, kstr, klen, cb, u);
+    return do_pk8pkey_fp(fp, x, 0, nid, NULL, kstr, klen, cb, u);
 }
 
 int PEM_write_PKCS8PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
-			      char *kstr, int klen, pem_password_cb *cb, void *u)
+                              char *kstr, int klen, pem_password_cb *cb,
+                              void *u)
 {
-	return do_pk8pkey_fp(fp, x, 0, -1, enc, kstr, klen, cb, u);
+    return do_pk8pkey_fp(fp, x, 0, -1, enc, kstr, klen, cb, u);
 }
 
-static int do_pk8pkey_fp(FILE *fp, EVP_PKEY *x, int isder, int nid, const EVP_CIPHER *enc,
-				  char *kstr, int klen,
-				  pem_password_cb *cb, void *u)
+static int do_pk8pkey_fp(FILE *fp, EVP_PKEY *x, int isder, int nid,
+                         const EVP_CIPHER *enc, char *kstr, int klen,
+                         pem_password_cb *cb, void *u)
 {
-	BIO *bp;
-	int ret;
-	if(!(bp = BIO_new_fp(fp, BIO_NOCLOSE))) {
-		OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
-                return(0);
-	}
-	ret = do_pk8pkey(bp, x, isder, nid, enc, kstr, klen, cb, u);
-	BIO_free(bp);
-	return ret;
+    BIO *bp;
+    int ret;
+    if (!(bp = BIO_new_fp(fp, BIO_NOCLOSE))) {
+        OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
+        return (0);
+    }
+    ret = do_pk8pkey(bp, x, isder, nid, enc, kstr, klen, cb, u);
+    BIO_free(bp);
+    return ret;
 }
 
-EVP_PKEY *d2i_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, void *u)
+EVP_PKEY *d2i_PKCS8PrivateKey_fp(FILE *fp, EVP_PKEY **x, pem_password_cb *cb,
+                                 void *u)
 {
-	BIO *bp;
-	EVP_PKEY *ret;
-	if(!(bp = BIO_new_fp(fp, BIO_NOCLOSE))) {
-		OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
-                return NULL;
-	}
-	ret = d2i_PKCS8PrivateKey_bio(bp, x, cb, u);
-	BIO_free(bp);
-	return ret;
+    BIO *bp;
+    EVP_PKEY *ret;
+    if (!(bp = BIO_new_fp(fp, BIO_NOCLOSE))) {
+        OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
+        return NULL;
+    }
+    ret = d2i_PKCS8PrivateKey_bio(bp, x, cb, u);
+    BIO_free(bp);
+    return ret;
 }
 
 #endif
 
 IMPLEMENT_PEM_rw(PKCS8, X509_SIG, PEM_STRING_PKCS8, X509_SIG)
+
+
 IMPLEMENT_PEM_rw(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO, PEM_STRING_PKCS8INF,
-							 PKCS8_PRIV_KEY_INFO)
+             PKCS8_PRIV_KEY_INFO)
diff --git a/src/crypto/pem/pem_pkey.c b/src/crypto/pem/pem_pkey.c
index cd334b4..058c031 100644
--- a/src/crypto/pem/pem_pkey.c
+++ b/src/crypto/pem/pem_pkey.c
@@ -69,240 +69,159 @@
 #include <openssl/rand.h>
 #include <openssl/x509.h>
 
-#include "../evp/internal.h"
+EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb,
+                                  void *u)
+{
+    char *nm = NULL;
+    const unsigned char *p = NULL;
+    unsigned char *data = NULL;
+    long len;
+    EVP_PKEY *ret = NULL;
 
+    if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_EVP_PKEY, bp, cb, u))
+        return NULL;
+    p = data;
 
-int pem_check_suffix(const char *pem_str, const char *suffix);
+    if (strcmp(nm, PEM_STRING_PKCS8INF) == 0) {
+        PKCS8_PRIV_KEY_INFO *p8inf;
+        p8inf = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len);
+        if (!p8inf)
+            goto p8err;
+        ret = EVP_PKCS82PKEY(p8inf);
+        if (x) {
+            if (*x)
+                EVP_PKEY_free((EVP_PKEY *)*x);
+            *x = ret;
+        }
+        PKCS8_PRIV_KEY_INFO_free(p8inf);
+    } else if (strcmp(nm, PEM_STRING_PKCS8) == 0) {
+        PKCS8_PRIV_KEY_INFO *p8inf;
+        X509_SIG *p8;
+        int klen;
+        char psbuf[PEM_BUFSIZE];
+        p8 = d2i_X509_SIG(NULL, &p, len);
+        if (!p8)
+            goto p8err;
 
-EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x, pem_password_cb *cb, void *u)
-	{
-	char *nm=NULL;
-	const unsigned char *p=NULL;
-	unsigned char *data=NULL;
-	long len;
-	int slen;
-	EVP_PKEY *ret=NULL;
+        klen = 0;
+        if (!cb)
+            cb = PEM_def_callback;
+        klen = cb(psbuf, PEM_BUFSIZE, 0, u);
+        if (klen <= 0) {
+            OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_PASSWORD_READ);
+            X509_SIG_free(p8);
+            goto err;
+        }
+        p8inf = PKCS8_decrypt(p8, psbuf, klen);
+        X509_SIG_free(p8);
+        if (!p8inf)
+            goto p8err;
+        ret = EVP_PKCS82PKEY(p8inf);
+        if (x) {
+            if (*x)
+                EVP_PKEY_free((EVP_PKEY *)*x);
+            *x = ret;
+        }
+        PKCS8_PRIV_KEY_INFO_free(p8inf);
+    } else if (strcmp(nm, PEM_STRING_RSA) == 0) {
+        /* TODO(davidben): d2i_PrivateKey parses PKCS#8 along with the
+         * standalone format. This and the cases below probably should not
+         * accept PKCS#8. */
+        ret = d2i_PrivateKey(EVP_PKEY_RSA, x, &p, len);
+    } else if (strcmp(nm, PEM_STRING_EC) == 0) {
+        ret = d2i_PrivateKey(EVP_PKEY_EC, x, &p, len);
+    } else if (strcmp(nm, PEM_STRING_DSA) == 0) {
+        ret = d2i_PrivateKey(EVP_PKEY_DSA, x, &p, len);
+    }
+ p8err:
+    if (ret == NULL)
+        OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB);
 
-	if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_EVP_PKEY, bp, cb, u))
-		return NULL;
-	p = data;
-
-	if (strcmp(nm,PEM_STRING_PKCS8INF) == 0) {
-		PKCS8_PRIV_KEY_INFO *p8inf;
-		p8inf=d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, len);
-		if(!p8inf) goto p8err;
-		ret = EVP_PKCS82PKEY(p8inf);
-		if(x) {
-			if(*x) EVP_PKEY_free((EVP_PKEY *)*x);
-			*x = ret;
-		}
-		PKCS8_PRIV_KEY_INFO_free(p8inf);
-	} else if (strcmp(nm,PEM_STRING_PKCS8) == 0) {
-		PKCS8_PRIV_KEY_INFO *p8inf;
-		X509_SIG *p8;
-		int klen;
-		char psbuf[PEM_BUFSIZE];
-		p8 = d2i_X509_SIG(NULL, &p, len);
-		if(!p8) goto p8err;
-
-		klen = 0;
-		if (!cb) cb = PEM_def_callback;
-		klen=cb(psbuf,PEM_BUFSIZE,0,u);
-		if (klen <= 0) {
-			OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_PASSWORD_READ);
-			X509_SIG_free(p8);
-			goto err;
-		}
-		p8inf = PKCS8_decrypt(p8, psbuf, klen);
-		X509_SIG_free(p8);
-		if(!p8inf) goto p8err;
-		ret = EVP_PKCS82PKEY(p8inf);
-		if(x) {
-			if(*x) EVP_PKEY_free((EVP_PKEY *)*x);
-			*x = ret;
-		}
-		PKCS8_PRIV_KEY_INFO_free(p8inf);
-	} else if ((slen = pem_check_suffix(nm, "PRIVATE KEY")) > 0)
-		{
-		const EVP_PKEY_ASN1_METHOD *ameth;
-		ameth = EVP_PKEY_asn1_find_str(NULL, nm, slen);
-		if (!ameth || !ameth->old_priv_decode)
-			goto p8err;
-		ret=d2i_PrivateKey(ameth->pkey_id,x,&p,len);
-		}
-p8err:
-	if (ret == NULL)
-		OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB);
-
-err:
-	OPENSSL_free(nm);
-	OPENSSL_cleanse(data, len);
-	OPENSSL_free(data);
-	return(ret);
-	}
+ err:
+    OPENSSL_free(nm);
+    OPENSSL_cleanse(data, len);
+    OPENSSL_free(data);
+    return (ret);
+}
 
 int PEM_write_bio_PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
-                                               unsigned char *kstr, int klen,
-                                               pem_password_cb *cb, void *u)
-	{
-	char pem_str[80];
-	if (!x->ameth || x->ameth->priv_encode)
-		return PEM_write_bio_PKCS8PrivateKey(bp, x, enc,
-							(char *)kstr, klen,
-							cb, u);
-
-	BIO_snprintf(pem_str, 80, "%s PRIVATE KEY", x->ameth->pem_str);
-	return PEM_ASN1_write_bio((i2d_of_void *)i2d_PrivateKey,
-				pem_str,bp,x,enc,kstr,klen,cb,u);
-	}
-
-static int public_key_type_from_str(const char *name, size_t len) {
-  if (len == 3 && memcmp(name, "RSA", 3) == 0) {
-    return EVP_PKEY_RSA;
-  } else if (len == 2 && memcmp(name, "DH", 2) == 0) {
-    return EVP_PKEY_DH;
-  } else if (len == 2 && memcmp(name, "EC", 2) == 0) {
-    return EVP_PKEY_EC;
-  }
-  return NID_undef;
+                             unsigned char *kstr, int klen,
+                             pem_password_cb *cb, void *u)
+{
+    return PEM_write_bio_PKCS8PrivateKey(bp, x, enc, (char *)kstr, klen, cb, u);
 }
 
-static int set_pkey_type_from_str(EVP_PKEY *pkey, const char *name, size_t len) {
-  int nid = public_key_type_from_str(name, len);
-  if (nid == NID_undef) {
-    return 0;
-  }
-  return EVP_PKEY_set_type(pkey, nid);
-}
-
-EVP_PKEY *PEM_read_bio_Parameters(BIO *bp, EVP_PKEY **x)
-	{
-	char *nm=NULL;
-	const unsigned char *p=NULL;
-	unsigned char *data=NULL;
-	long len;
-	int slen;
-	EVP_PKEY *ret=NULL;
-
-	if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_PARAMETERS,
-								bp, 0, NULL))
-		return NULL;
-	p = data;
-
-	if ((slen = pem_check_suffix(nm, "PARAMETERS")) > 0)
-		{
-		ret = EVP_PKEY_new();
-		if (!ret)
-			goto err;
-		if (!set_pkey_type_from_str(ret, nm, slen)
-			|| !ret->ameth->param_decode
-			|| !ret->ameth->param_decode(ret, &p, len))
-			{
-			EVP_PKEY_free(ret);
-			ret = NULL;
-			goto err;
-			}
-		if(x)
-			{
-			if(*x) EVP_PKEY_free((EVP_PKEY *)*x);
-			*x = ret;
-			}
-		}
-err:
-	if (ret == NULL)
-		OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB);
-	OPENSSL_free(nm);
-	OPENSSL_free(data);
-	return(ret);
-	}
-
-int PEM_write_bio_Parameters(BIO *bp, EVP_PKEY *x)
-	{
-	char pem_str[80];
-	if (!x->ameth || !x->ameth->param_encode)
-		return 0;
-
-	BIO_snprintf(pem_str, 80, "%s PARAMETERS", x->ameth->pem_str);
-	return PEM_ASN1_write_bio(
-		(i2d_of_void *)x->ameth->param_encode,
-				pem_str,bp,x,NULL,NULL,0,0,NULL);
-	}
-
 #ifndef OPENSSL_NO_FP_API
-EVP_PKEY *PEM_read_PrivateKey(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, void *u)
-	{
-        BIO *b;
-        EVP_PKEY *ret;
+EVP_PKEY *PEM_read_PrivateKey(FILE *fp, EVP_PKEY **x, pem_password_cb *cb,
+                              void *u)
+{
+    BIO *b;
+    EVP_PKEY *ret;
 
-        if ((b=BIO_new(BIO_s_file())) == NULL)
-		{
-		OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
-                return(0);
-		}
-        BIO_set_fp(b,fp,BIO_NOCLOSE);
-        ret=PEM_read_bio_PrivateKey(b,x,cb,u);
-        BIO_free(b);
-        return(ret);
-	}
+    if ((b = BIO_new(BIO_s_file())) == NULL) {
+        OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
+        return (0);
+    }
+    BIO_set_fp(b, fp, BIO_NOCLOSE);
+    ret = PEM_read_bio_PrivateKey(b, x, cb, u);
+    BIO_free(b);
+    return (ret);
+}
 
 int PEM_write_PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
-                                               unsigned char *kstr, int klen,
-                                               pem_password_cb *cb, void *u)
-	{
-        BIO *b;
-        int ret;
+                         unsigned char *kstr, int klen,
+                         pem_password_cb *cb, void *u)
+{
+    BIO *b;
+    int ret;
 
-        if ((b=BIO_new_fp(fp, BIO_NOCLOSE)) == NULL)
-		{
-		OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
-                return 0;
-		}
-        ret=PEM_write_bio_PrivateKey(b, x, enc, kstr, klen, cb, u);
-        BIO_free(b);
-        return ret;
-	}
+    if ((b = BIO_new_fp(fp, BIO_NOCLOSE)) == NULL) {
+        OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
+        return 0;
+    }
+    ret = PEM_write_bio_PrivateKey(b, x, enc, kstr, klen, cb, u);
+    BIO_free(b);
+    return ret;
+}
 
 #endif
 
-
 /* Transparently read in PKCS#3 or X9.42 DH parameters */
 
 DH *PEM_read_bio_DHparams(BIO *bp, DH **x, pem_password_cb *cb, void *u)
-	{
-	char *nm=NULL;
-	const unsigned char *p=NULL;
-	unsigned char *data=NULL;
-	long len;
-	DH *ret=NULL;
+{
+    char *nm = NULL;
+    const unsigned char *p = NULL;
+    unsigned char *data = NULL;
+    long len;
+    DH *ret = NULL;
 
-	if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_DHPARAMS,
-								bp, cb, u))
-		return NULL;
-	p = data;
+    if (!PEM_bytes_read_bio(&data, &len, &nm, PEM_STRING_DHPARAMS, bp, cb, u))
+        return NULL;
+    p = data;
 
-	ret = d2i_DHparams(x, &p, len);
+    ret = d2i_DHparams(x, &p, len);
 
-	if (ret == NULL)
-		OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB);
-	OPENSSL_free(nm);
-	OPENSSL_free(data);
-	return ret;
-	}
+    if (ret == NULL)
+        OPENSSL_PUT_ERROR(PEM, ERR_R_ASN1_LIB);
+    OPENSSL_free(nm);
+    OPENSSL_free(data);
+    return ret;
+}
 
 #ifndef OPENSSL_NO_FP_API
 DH *PEM_read_DHparams(FILE *fp, DH **x, pem_password_cb *cb, void *u)
-	{
-        BIO *b;
-        DH *ret;
+{
+    BIO *b;
+    DH *ret;
 
-        if ((b=BIO_new(BIO_s_file())) == NULL)
-		{
-		OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
-                return(0);
-		}
-        BIO_set_fp(b,fp,BIO_NOCLOSE);
-        ret=PEM_read_bio_DHparams(b,x,cb,u);
-        BIO_free(b);
-        return(ret);
-	}
+    if ((b = BIO_new(BIO_s_file())) == NULL) {
+        OPENSSL_PUT_ERROR(PEM, ERR_R_BUF_LIB);
+        return (0);
+    }
+    BIO_set_fp(b, fp, BIO_NOCLOSE);
+    ret = PEM_read_bio_DHparams(b, x, cb, u);
+    BIO_free(b);
+    return (ret);
+}
 #endif
diff --git a/src/crypto/pem/pem_x509.c b/src/crypto/pem/pem_x509.c
index f463047..97f814d 100644
--- a/src/crypto/pem/pem_x509.c
+++ b/src/crypto/pem/pem_x509.c
@@ -1,6 +1,7 @@
 /* pem_x509.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 2001.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 2001.
  */
 /* ====================================================================
  * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
@@ -61,5 +62,4 @@
 #include <openssl/pem.h>
 #include <openssl/x509.h>
 
-
 IMPLEMENT_PEM_rw(X509, X509, PEM_STRING_X509, X509)
diff --git a/src/crypto/pem/pem_xaux.c b/src/crypto/pem/pem_xaux.c
index 8dabd41..386dd60 100644
--- a/src/crypto/pem/pem_xaux.c
+++ b/src/crypto/pem/pem_xaux.c
@@ -1,6 +1,7 @@
 /* pem_xaux.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 2001.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 2001.
  */
 /* ====================================================================
  * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
@@ -61,6 +62,6 @@
 #include <openssl/pem.h>
 #include <openssl/x509.h>
 
-
 IMPLEMENT_PEM_rw(X509_AUX, X509, PEM_STRING_X509_TRUSTED, X509_AUX)
-IMPLEMENT_PEM_rw(X509_CERT_PAIR, X509_CERT_PAIR, PEM_STRING_X509_PAIR, X509_CERT_PAIR)
+IMPLEMENT_PEM_rw(X509_CERT_PAIR, X509_CERT_PAIR, PEM_STRING_X509_PAIR,
+                 X509_CERT_PAIR)
diff --git a/src/crypto/perlasm/arm-xlate.pl b/src/crypto/perlasm/arm-xlate.pl
index 706fa70..aae2462 100755
--- a/src/crypto/perlasm/arm-xlate.pl
+++ b/src/crypto/perlasm/arm-xlate.pl
@@ -2,6 +2,8 @@
 
 # ARM assembler distiller by <appro>.
 
+use strict;
+
 my $flavour = shift;
 my $output = shift;
 open STDOUT,">$output" || die "can't open $output: $!";
@@ -55,7 +57,9 @@
 			      };
     }
 
-    $ret = ".globl	$name" if (!$ret);
+    $ret = ".globl	$name\n";
+    # All symbols in assembly files are hidden.
+    $ret .= &$hidden($name);
     $$global = $name;
     $ret;
 };
@@ -119,7 +123,7 @@
 print "#if defined(__arm__)\n" if ($flavour eq "linux32");
 print "#if defined(__aarch64__)\n" if ($flavour eq "linux64");
 
-while($line=<>) {
+while(my $line=<>) {
 
     if ($line =~ m/^\s*(#|@|\/\/)/)	{ print $line; next; }
 
@@ -165,6 +169,6 @@
     print "\n";
 }
 
-print "#endif" if ($flavour eq "linux32" || $flavour eq "linux64");
+print "#endif\n" if ($flavour eq "linux32" || $flavour eq "linux64");
 
 close STDOUT;
diff --git a/src/crypto/perlasm/cbc.pl b/src/crypto/perlasm/cbc.pl
deleted file mode 100644
index 24561e7..0000000
--- a/src/crypto/perlasm/cbc.pl
+++ /dev/null
@@ -1,349 +0,0 @@
-#!/usr/local/bin/perl
-
-# void des_ncbc_encrypt(input, output, length, schedule, ivec, enc)
-# des_cblock (*input);
-# des_cblock (*output);
-# long length;
-# des_key_schedule schedule;
-# des_cblock (*ivec);
-# int enc;
-#
-# calls 
-# des_encrypt((DES_LONG *)tin,schedule,DES_ENCRYPT);
-#
-
-#&cbc("des_ncbc_encrypt","des_encrypt",0);
-#&cbc("BF_cbc_encrypt","BF_encrypt","BF_encrypt",
-#	1,4,5,3,5,-1);
-#&cbc("des_ncbc_encrypt","des_encrypt","des_encrypt",
-#	0,4,5,3,5,-1);
-#&cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3",
-#	0,6,7,3,4,5);
-#
-# When doing a cipher that needs bigendian order,
-# for encrypt, the iv is kept in bigendian form,
-# while for decrypt, it is kept in little endian.
-sub cbc
-	{
-	local($name,$enc_func,$dec_func,$swap,$iv_off,$enc_off,$p1,$p2,$p3)=@_;
-	# name is the function name
-	# enc_func and dec_func and the functions to call for encrypt/decrypt
-	# swap is true if byte order needs to be reversed
-	# iv_off is parameter number for the iv 
-	# enc_off is parameter number for the encrypt/decrypt flag
-	# p1,p2,p3 are the offsets for parameters to be passed to the
-	# underlying calls.
-
-	&function_begin_B($name,"");
-	&comment("");
-
-	$in="esi";
-	$out="edi";
-	$count="ebp";
-
-	&push("ebp");
-	&push("ebx");
-	&push("esi");
-	&push("edi");
-
-	$data_off=4;
-	$data_off+=4 if ($p1 > 0);
-	$data_off+=4 if ($p2 > 0);
-	$data_off+=4 if ($p3 > 0);
-
-	&mov($count,	&wparam(2));	# length
-
-	&comment("getting iv ptr from parameter $iv_off");
-	&mov("ebx",	&wparam($iv_off));	# Get iv ptr
-
-	&mov($in,	&DWP(0,"ebx","",0));#	iv[0]
-	&mov($out,	&DWP(4,"ebx","",0));#	iv[1]
-
-	&push($out);
-	&push($in);
-	&push($out);	# used in decrypt for iv[1]
-	&push($in);	# used in decrypt for iv[0]
-
-	&mov("ebx",	"esp");		# This is the address of tin[2]
-
-	&mov($in,	&wparam(0));	# in
-	&mov($out,	&wparam(1));	# out
-
-	# We have loaded them all, how lets push things
-	&comment("getting encrypt flag from parameter $enc_off");
-	&mov("ecx",	&wparam($enc_off));	# Get enc flag
-	if ($p3 > 0)
-		{
-		&comment("get and push parameter $p3");
-		if ($enc_off != $p3)
-			{ &mov("eax",	&wparam($p3)); &push("eax"); }
-		else	{ &push("ecx"); }
-		}
-	if ($p2 > 0)
-		{
-		&comment("get and push parameter $p2");
-		if ($enc_off != $p2)
-			{ &mov("eax",	&wparam($p2)); &push("eax"); }
-		else	{ &push("ecx"); }
-		}
-	if ($p1 > 0)
-		{
-		&comment("get and push parameter $p1");
-		if ($enc_off != $p1)
-			{ &mov("eax",	&wparam($p1)); &push("eax"); }
-		else	{ &push("ecx"); }
-		}
-	&push("ebx");		# push data/iv
-
-	&cmp("ecx",0);
-	&jz(&label("decrypt"));
-
-	&and($count,0xfffffff8);
-	&mov("eax",	&DWP($data_off,"esp","",0));	# load iv[0]
-	&mov("ebx",	&DWP($data_off+4,"esp","",0));	# load iv[1]
-
-	&jz(&label("encrypt_finish"));
-
-	#############################################################
-
-	&set_label("encrypt_loop");
-	# encrypt start 
-	# "eax" and "ebx" hold iv (or the last cipher text)
-
-	&mov("ecx",	&DWP(0,$in,"",0));	# load first 4 bytes
-	&mov("edx",	&DWP(4,$in,"",0));	# second 4 bytes
-
-	&xor("eax",	"ecx");
-	&xor("ebx",	"edx");
-
-	&bswap("eax")	if $swap;
-	&bswap("ebx")	if $swap;
-
-	&mov(&DWP($data_off,"esp","",0),	"eax");	# put in array for call
-	&mov(&DWP($data_off+4,"esp","",0),	"ebx");	#
-
-	&call($enc_func);
-
-	&mov("eax",	&DWP($data_off,"esp","",0));
-	&mov("ebx",	&DWP($data_off+4,"esp","",0));
-
-	&bswap("eax")	if $swap;
-	&bswap("ebx")	if $swap;
-
-	&mov(&DWP(0,$out,"",0),"eax");
-	&mov(&DWP(4,$out,"",0),"ebx");
-
-	# eax and ebx are the next iv.
-
-	&add($in,	8);
-	&add($out,	8);
-
-	&sub($count,	8);
-	&jnz(&label("encrypt_loop"));
-
-###################################################################3
-	&set_label("encrypt_finish");
-	&mov($count,	&wparam(2));	# length
-	&and($count,	7);
-	&jz(&label("finish"));
-	&call(&label("PIC_point"));
-&set_label("PIC_point");
-	&blindpop("edx");
-	&lea("ecx",&DWP(&label("cbc_enc_jmp_table")."-".&label("PIC_point"),"edx"));
-	&mov($count,&DWP(0,"ecx",$count,4));
-	&add($count,"edx");
-	&xor("ecx","ecx");
-	&xor("edx","edx");
-	#&mov($count,&DWP(&label("cbc_enc_jmp_table"),"",$count,4));
-	&jmp_ptr($count);
-
-&set_label("ej7");
-	&movb(&HB("edx"),	&BP(6,$in,"",0));
-	&shl("edx",8);
-&set_label("ej6");
-	&movb(&HB("edx"),	&BP(5,$in,"",0));
-&set_label("ej5");
-	&movb(&LB("edx"),	&BP(4,$in,"",0));
-&set_label("ej4");
-	&mov("ecx",		&DWP(0,$in,"",0));
-	&jmp(&label("ejend"));
-&set_label("ej3");
-	&movb(&HB("ecx"),	&BP(2,$in,"",0));
-	&shl("ecx",8);
-&set_label("ej2");
-	&movb(&HB("ecx"),	&BP(1,$in,"",0));
-&set_label("ej1");
-	&movb(&LB("ecx"),	&BP(0,$in,"",0));
-&set_label("ejend");
-
-	&xor("eax",	"ecx");
-	&xor("ebx",	"edx");
-
-	&bswap("eax")	if $swap;
-	&bswap("ebx")	if $swap;
-
-	&mov(&DWP($data_off,"esp","",0),	"eax");	# put in array for call
-	&mov(&DWP($data_off+4,"esp","",0),	"ebx");	#
-
-	&call($enc_func);
-
-	&mov("eax",	&DWP($data_off,"esp","",0));
-	&mov("ebx",	&DWP($data_off+4,"esp","",0));
-
-	&bswap("eax")	if $swap;
-	&bswap("ebx")	if $swap;
-
-	&mov(&DWP(0,$out,"",0),"eax");
-	&mov(&DWP(4,$out,"",0),"ebx");
-
-	&jmp(&label("finish"));
-
-	#############################################################
-	#############################################################
-	&set_label("decrypt",1);
-	# decrypt start 
-	&and($count,0xfffffff8);
-	# The next 2 instructions are only for if the jz is taken
-	&mov("eax",	&DWP($data_off+8,"esp","",0));	# get iv[0]
-	&mov("ebx",	&DWP($data_off+12,"esp","",0));	# get iv[1]
-	&jz(&label("decrypt_finish"));
-
-	&set_label("decrypt_loop");
-	&mov("eax",	&DWP(0,$in,"",0));	# load first 4 bytes
-	&mov("ebx",	&DWP(4,$in,"",0));	# second 4 bytes
-
-	&bswap("eax")	if $swap;
-	&bswap("ebx")	if $swap;
-
-	&mov(&DWP($data_off,"esp","",0),	"eax");	# put back
-	&mov(&DWP($data_off+4,"esp","",0),	"ebx");	#
-
-	&call($dec_func);
-
-	&mov("eax",	&DWP($data_off,"esp","",0));	# get return
-	&mov("ebx",	&DWP($data_off+4,"esp","",0));	#
-
-	&bswap("eax")	if $swap;
-	&bswap("ebx")	if $swap;
-
-	&mov("ecx",	&DWP($data_off+8,"esp","",0));	# get iv[0]
-	&mov("edx",	&DWP($data_off+12,"esp","",0));	# get iv[1]
-
-	&xor("ecx",	"eax");
-	&xor("edx",	"ebx");
-
-	&mov("eax",	&DWP(0,$in,"",0));	# get old cipher text,
-	&mov("ebx",	&DWP(4,$in,"",0));	# next iv actually
-
-	&mov(&DWP(0,$out,"",0),"ecx");
-	&mov(&DWP(4,$out,"",0),"edx");
-
-	&mov(&DWP($data_off+8,"esp","",0),	"eax");	# save iv
-	&mov(&DWP($data_off+12,"esp","",0),	"ebx");	#
-
-	&add($in,	8);
-	&add($out,	8);
-
-	&sub($count,	8);
-	&jnz(&label("decrypt_loop"));
-############################ ENDIT #######################3
-	&set_label("decrypt_finish");
-	&mov($count,	&wparam(2));	# length
-	&and($count,	7);
-	&jz(&label("finish"));
-
-	&mov("eax",	&DWP(0,$in,"",0));	# load first 4 bytes
-	&mov("ebx",	&DWP(4,$in,"",0));	# second 4 bytes
-
-	&bswap("eax")	if $swap;
-	&bswap("ebx")	if $swap;
-
-	&mov(&DWP($data_off,"esp","",0),	"eax");	# put back
-	&mov(&DWP($data_off+4,"esp","",0),	"ebx");	#
-
-	&call($dec_func);
-
-	&mov("eax",	&DWP($data_off,"esp","",0));	# get return
-	&mov("ebx",	&DWP($data_off+4,"esp","",0));	#
-
-	&bswap("eax")	if $swap;
-	&bswap("ebx")	if $swap;
-
-	&mov("ecx",	&DWP($data_off+8,"esp","",0));	# get iv[0]
-	&mov("edx",	&DWP($data_off+12,"esp","",0));	# get iv[1]
-
-	&xor("ecx",	"eax");
-	&xor("edx",	"ebx");
-
-	# this is for when we exit
-	&mov("eax",	&DWP(0,$in,"",0));	# get old cipher text,
-	&mov("ebx",	&DWP(4,$in,"",0));	# next iv actually
-
-&set_label("dj7");
-	&rotr("edx",	16);
-	&movb(&BP(6,$out,"",0),	&LB("edx"));
-	&shr("edx",16);
-&set_label("dj6");
-	&movb(&BP(5,$out,"",0),	&HB("edx"));
-&set_label("dj5");
-	&movb(&BP(4,$out,"",0),	&LB("edx"));
-&set_label("dj4");
-	&mov(&DWP(0,$out,"",0),	"ecx");
-	&jmp(&label("djend"));
-&set_label("dj3");
-	&rotr("ecx",	16);
-	&movb(&BP(2,$out,"",0),	&LB("ecx"));
-	&shl("ecx",16);
-&set_label("dj2");
-	&movb(&BP(1,$in,"",0),	&HB("ecx"));
-&set_label("dj1");
-	&movb(&BP(0,$in,"",0),	&LB("ecx"));
-&set_label("djend");
-
-	# final iv is still in eax:ebx
-	&jmp(&label("finish"));
-
-
-############################ FINISH #######################3
-	&set_label("finish",1);
-	&mov("ecx",	&wparam($iv_off));	# Get iv ptr
-
-	#################################################
-	$total=16+4;
-	$total+=4 if ($p1 > 0);
-	$total+=4 if ($p2 > 0);
-	$total+=4 if ($p3 > 0);
-	&add("esp",$total);
-
-	&mov(&DWP(0,"ecx","",0),	"eax");	# save iv
-	&mov(&DWP(4,"ecx","",0),	"ebx");	# save iv
-
-	&function_end_A($name);
-
-	&align(64);
-	&set_label("cbc_enc_jmp_table");
-	&data_word("0");
-	&data_word(&label("ej1")."-".&label("PIC_point"));
-	&data_word(&label("ej2")."-".&label("PIC_point"));
-	&data_word(&label("ej3")."-".&label("PIC_point"));
-	&data_word(&label("ej4")."-".&label("PIC_point"));
-	&data_word(&label("ej5")."-".&label("PIC_point"));
-	&data_word(&label("ej6")."-".&label("PIC_point"));
-	&data_word(&label("ej7")."-".&label("PIC_point"));
-	# not used
-	#&set_label("cbc_dec_jmp_table",1);
-	#&data_word("0");
-	#&data_word(&label("dj1")."-".&label("PIC_point"));
-	#&data_word(&label("dj2")."-".&label("PIC_point"));
-	#&data_word(&label("dj3")."-".&label("PIC_point"));
-	#&data_word(&label("dj4")."-".&label("PIC_point"));
-	#&data_word(&label("dj5")."-".&label("PIC_point"));
-	#&data_word(&label("dj6")."-".&label("PIC_point"));
-	#&data_word(&label("dj7")."-".&label("PIC_point"));
-	&align(64);
-
-	&function_end_B($name);
-	
-	}
-
-1;
diff --git a/src/crypto/perlasm/ppc-xlate.pl b/src/crypto/perlasm/ppc-xlate.pl
new file mode 100644
index 0000000..de796d7
--- /dev/null
+++ b/src/crypto/perlasm/ppc-xlate.pl
@@ -0,0 +1,299 @@
+#! /usr/bin/env perl
+# Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the OpenSSL license (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
+my $flavour = shift;
+my $output = shift;
+open STDOUT,">$output" || die "can't open $output: $!";
+
+my %GLOBALS;
+my %TYPES;
+my $dotinlocallabels=($flavour=~/linux/)?1:0;
+
+################################################################
+# directives which need special treatment on different platforms
+################################################################
+my $type = sub {
+    my ($dir,$name,$type) = @_;
+
+    $TYPES{$name} = $type;
+    if ($flavour =~ /linux/) {
+	$name =~ s|^\.||;
+	".type	$name,$type";
+    } else {
+	"";
+    }
+};
+my $globl = sub {
+    my $junk = shift;
+    my $name = shift;
+    my $global = \$GLOBALS{$name};
+    my $type = \$TYPES{$name};
+    my $ret;
+
+    $name =~ s|^\.||;
+
+    SWITCH: for ($flavour) {
+	/aix/		&& do { if (!$$type) {
+				    $$type = "\@function";
+				}
+				if ($$type =~ /function/) {
+				    $name = ".$name";
+				}
+				last;
+			      };
+	/osx/		&& do { $name = "_$name";
+				last;
+			      };
+	/linux.*(32|64le)/
+			&& do {	$ret .= ".globl	$name";
+				if (!$$type) {
+				    $ret .= "\n.type	$name,\@function";
+				    $$type = "\@function";
+				}
+				last;
+			      };
+	/linux.*64/	&& do {	$ret .= ".globl	$name";
+				if (!$$type) {
+				    $ret .= "\n.type	$name,\@function";
+				    $$type = "\@function";
+				}
+				if ($$type =~ /function/) {
+				    $ret .= "\n.section	\".opd\",\"aw\"";
+				    $ret .= "\n.align	3";
+				    $ret .= "\n$name:";
+				    $ret .= "\n.quad	.$name,.TOC.\@tocbase,0";
+				    $ret .= "\n.previous";
+				    $name = ".$name";
+				}
+				last;
+			      };
+    }
+
+    $ret = ".globl	$name" if (!$ret);
+    $$global = $name;
+    $ret;
+};
+my $text = sub {
+    my $ret = ($flavour =~ /aix/) ? ".csect\t.text[PR],7" : ".text";
+    $ret = ".abiversion	2\n".$ret	if ($flavour =~ /linux.*64le/);
+    $ret;
+};
+my $machine = sub {
+    my $junk = shift;
+    my $arch = shift;
+    if ($flavour =~ /osx/)
+    {	$arch =~ s/\"//g;
+	$arch = ($flavour=~/64/) ? "ppc970-64" : "ppc970" if ($arch eq "any");
+    }
+    ".machine	$arch";
+};
+my $size = sub {
+    if ($flavour =~ /linux/)
+    {	shift;
+	my $name = shift;
+	my $real = $GLOBALS{$name} ? \$GLOBALS{$name} : \$name;
+	my $ret  = ".size	$$real,.-$$real";
+	$name =~ s|^\.||;
+	if ($$real ne $name) {
+	    $ret .= "\n.size	$name,.-$$real";
+	}
+	$ret;
+    }
+    else
+    {	"";	}
+};
+my $asciz = sub {
+    shift;
+    my $line = join(",",@_);
+    if ($line =~ /^"(.*)"$/)
+    {	".byte	" . join(",",unpack("C*",$1),0) . "\n.align	2";	}
+    else
+    {	"";	}
+};
+my $quad = sub {
+    shift;
+    my @ret;
+    my ($hi,$lo);
+    for (@_) {
+	if (/^0x([0-9a-f]*?)([0-9a-f]{1,8})$/io)
+	{  $hi=$1?"0x$1":"0"; $lo="0x$2";  }
+	elsif (/^([0-9]+)$/o)
+	{  $hi=$1>>32; $lo=$1&0xffffffff;  } # error-prone with 32-bit perl
+	else
+	{  $hi=undef; $lo=$_; }
+
+	if (defined($hi))
+	{  push(@ret,$flavour=~/le$/o?".long\t$lo,$hi":".long\t$hi,$lo");  }
+	else
+	{  push(@ret,".quad	$lo");  }
+    }
+    join("\n",@ret);
+};
+
+################################################################
+# simplified mnemonics not handled by at least one assembler
+################################################################
+my $cmplw = sub {
+    my $f = shift;
+    my $cr = 0; $cr = shift if ($#_>1);
+    # Some out-of-date 32-bit GNU assembler just can't handle cmplw...
+    ($flavour =~ /linux.*32/) ?
+	"	.long	".sprintf "0x%x",31<<26|$cr<<23|$_[0]<<16|$_[1]<<11|64 :
+	"	cmplw	".join(',',$cr,@_);
+};
+my $bdnz = sub {
+    my $f = shift;
+    my $bo = $f=~/[\+\-]/ ? 16+9 : 16;	# optional "to be taken" hint
+    "	bc	$bo,0,".shift;
+} if ($flavour!~/linux/);
+my $bltlr = sub {
+    my $f = shift;
+    my $bo = $f=~/\-/ ? 12+2 : 12;	# optional "not to be taken" hint
+    ($flavour =~ /linux/) ?		# GNU as doesn't allow most recent hints
+	"	.long	".sprintf "0x%x",19<<26|$bo<<21|16<<1 :
+	"	bclr	$bo,0";
+};
+my $bnelr = sub {
+    my $f = shift;
+    my $bo = $f=~/\-/ ? 4+2 : 4;	# optional "not to be taken" hint
+    ($flavour =~ /linux/) ?		# GNU as doesn't allow most recent hints
+	"	.long	".sprintf "0x%x",19<<26|$bo<<21|2<<16|16<<1 :
+	"	bclr	$bo,2";
+};
+my $beqlr = sub {
+    my $f = shift;
+    my $bo = $f=~/-/ ? 12+2 : 12;	# optional "not to be taken" hint
+    ($flavour =~ /linux/) ?		# GNU as doesn't allow most recent hints
+	"	.long	".sprintf "0x%X",19<<26|$bo<<21|2<<16|16<<1 :
+	"	bclr	$bo,2";
+};
+# GNU assembler can't handle extrdi rA,rS,16,48, or when sum of last two
+# arguments is 64, with "operand out of range" error.
+my $extrdi = sub {
+    my ($f,$ra,$rs,$n,$b) = @_;
+    $b = ($b+$n)&63; $n = 64-$n;
+    "	rldicl	$ra,$rs,$b,$n";
+};
+my $vmr = sub {
+    my ($f,$vx,$vy) = @_;
+    "	vor	$vx,$vy,$vy";
+};
+
+# Some ABIs specify vrsave, special-purpose register #256, as reserved
+# for system use.
+my $no_vrsave = ($flavour =~ /aix|linux64le/);
+my $mtspr = sub {
+    my ($f,$idx,$ra) = @_;
+    if ($idx == 256 && $no_vrsave) {
+	"	or	$ra,$ra,$ra";
+    } else {
+	"	mtspr	$idx,$ra";
+    }
+};
+my $mfspr = sub {
+    my ($f,$rd,$idx) = @_;
+    if ($idx == 256 && $no_vrsave) {
+	"	li	$rd,-1";
+    } else {
+	"	mfspr	$rd,$idx";
+    }
+};
+
+# PowerISA 2.06 stuff
+sub vsxmem_op {
+    my ($f, $vrt, $ra, $rb, $op) = @_;
+    "	.long	".sprintf "0x%X",(31<<26)|($vrt<<21)|($ra<<16)|($rb<<11)|($op*2+1);
+}
+# made-up unaligned memory reference AltiVec/VMX instructions
+my $lvx_u	= sub {	vsxmem_op(@_, 844); };	# lxvd2x
+my $stvx_u	= sub {	vsxmem_op(@_, 972); };	# stxvd2x
+my $lvdx_u	= sub {	vsxmem_op(@_, 588); };	# lxsdx
+my $stvdx_u	= sub {	vsxmem_op(@_, 716); };	# stxsdx
+my $lvx_4w	= sub { vsxmem_op(@_, 780); };	# lxvw4x
+my $stvx_4w	= sub { vsxmem_op(@_, 908); };	# stxvw4x
+
+# PowerISA 2.07 stuff
+sub vcrypto_op {
+    my ($f, $vrt, $vra, $vrb, $op) = @_;
+    "	.long	".sprintf "0x%X",(4<<26)|($vrt<<21)|($vra<<16)|($vrb<<11)|$op;
+}
+my $vcipher	= sub { vcrypto_op(@_, 1288); };
+my $vcipherlast	= sub { vcrypto_op(@_, 1289); };
+my $vncipher	= sub { vcrypto_op(@_, 1352); };
+my $vncipherlast= sub { vcrypto_op(@_, 1353); };
+my $vsbox	= sub { vcrypto_op(@_, 0, 1480); };
+my $vshasigmad	= sub { my ($st,$six)=splice(@_,-2); vcrypto_op(@_, $st<<4|$six, 1730); };
+my $vshasigmaw	= sub { my ($st,$six)=splice(@_,-2); vcrypto_op(@_, $st<<4|$six, 1666); };
+my $vpmsumb	= sub { vcrypto_op(@_, 1032); };
+my $vpmsumd	= sub { vcrypto_op(@_, 1224); };
+my $vpmsubh	= sub { vcrypto_op(@_, 1096); };
+my $vpmsumw	= sub { vcrypto_op(@_, 1160); };
+my $vaddudm	= sub { vcrypto_op(@_, 192);  };
+
+my $mtsle	= sub {
+    my ($f, $arg) = @_;
+    "	.long	".sprintf "0x%X",(31<<26)|($arg<<21)|(147*2);
+};
+
+# PowerISA 3.0 stuff
+my $maddhdu = sub {
+    my ($f, $rt, $ra, $rb, $rc) = @_;
+    "	.long	".sprintf "0x%X",(4<<26)|($rt<<21)|($ra<<16)|($rb<<11)|($rc<<6)|49;
+};
+my $maddld = sub {
+    my ($f, $rt, $ra, $rb, $rc) = @_;
+    "	.long	".sprintf "0x%X",(4<<26)|($rt<<21)|($ra<<16)|($rb<<11)|($rc<<6)|51;
+};
+
+my $darn = sub {
+    my ($f, $rt, $l) = @_;
+    "	.long	".sprintf "0x%X",(31<<26)|($rt<<21)|($l<<16)|(755<<1);
+};
+
+while($line=<>) {
+
+    $line =~ s|[#!;].*$||;	# get rid of asm-style comments...
+    $line =~ s|/\*.*\*/||;	# ... and C-style comments...
+    $line =~ s|^\s+||;		# ... and skip white spaces in beginning...
+    $line =~ s|\s+$||;		# ... and at the end
+
+    {
+	$line =~ s|\.L(\w+)|L$1|g;	# common denominator for Locallabel
+	$line =~ s|\bL(\w+)|\.L$1|g	if ($dotinlocallabels);
+    }
+
+    {
+	$line =~ s|(^[\.\w]+)\:\s*||;
+	my $label = $1;
+	if ($label) {
+	    my $xlated = ($GLOBALS{$label} or $label);
+	    print "$xlated:";
+	    if ($flavour =~ /linux.*64le/) {
+		if ($TYPES{$label} =~ /function/) {
+		    printf "\n.localentry	%s,0\n",$xlated;
+		}
+	    }
+	}
+    }
+
+    {
+	$line =~ s|^\s*(\.?)(\w+)([\.\+\-]?)\s*||;
+	my $c = $1; $c = "\t" if ($c eq "");
+	my $mnemonic = $2;
+	my $f = $3;
+	my $opcode = eval("\$$mnemonic");
+	$line =~ s/\b(c?[rf]|v|vs)([0-9]+)\b/$2/g if ($c ne "." and $flavour !~ /osx/);
+	if (ref($opcode) eq 'CODE') { $line = &$opcode($f,split(',',$line)); }
+	elsif ($mnemonic)           { $line = $c.$mnemonic.$f."\t".$line; }
+    }
+
+    print $line if ($line);
+    print "\n";
+}
+
+close STDOUT;
diff --git a/src/crypto/perlasm/readme b/src/crypto/perlasm/readme
index f02bbee..57d2083 100644
--- a/src/crypto/perlasm/readme
+++ b/src/crypto/perlasm/readme
@@ -7,7 +7,7 @@
 push(@INC,"perlasm","../../perlasm");
 require "x86asm.pl";
 
-The first thing we do is setup the file and type of assember
+The first thing we do is setup the file and type of assembler
 
 &asm_init($ARGV[0],$0);
 
@@ -18,7 +18,7 @@
 The reciprocal function is
 &asm_finish() which should be called at the end.
 
-There are 2 main 'packages'. x86ms.pl, which is the microsoft assembler,
+There are 2 main 'packages'. x86ms.pl, which is the Microsoft assembler,
 and x86unix.pl which is the unix (gas) version.
 
 Functions of interest are:
@@ -32,7 +32,7 @@
 &function_begin(name,extra)	Start a function with pushing of
 				edi, esi, ebx and ebp.  extra is extra win32
 				external info that may be required.
-&function_begin_B(name,extra)	Same as norma function_begin but no pushing.
+&function_begin_B(name,extra)	Same as normal function_begin but no pushing.
 &function_end(name)		Call at end of function.
 &function_end_A(name)		Standard pop and ret, for use inside functions
 &function_end_B(name)		Call at end but with poping or 'ret'.
@@ -98,27 +98,3 @@
 
 The above example is very very unoptimised but gives an idea of how
 things work.
-
-There is also a cbc mode function generator in cbc.pl
-
-&cbc(	$name,
-	$encrypt_function_name,
-	$decrypt_function_name,
-	$true_if_byte_swap_needed,
-	$parameter_number_for_iv,
-	$parameter_number_for_encrypt_flag,
-	$first_parameter_to_pass,
-	$second_parameter_to_pass,
-	$third_parameter_to_pass);
-
-So for example, given
-void BF_encrypt(BF_LONG *data,BF_KEY *key);
-void BF_decrypt(BF_LONG *data,BF_KEY *key);
-void BF_cbc_encrypt(unsigned char *in, unsigned char *out, long length,
-        BF_KEY *ks, unsigned char *iv, int enc);
-
-&cbc("BF_cbc_encrypt","BF_encrypt","BF_encrypt",1,4,5,3,-1,-1);
-
-&cbc("des_ncbc_encrypt","des_encrypt","des_encrypt",0,4,5,3,5,-1);
-&cbc("des_ede3_cbc_encrypt","des_encrypt3","des_decrypt3",0,6,7,3,4,5);
-
diff --git a/src/crypto/perlasm/x86_64-xlate.pl b/src/crypto/perlasm/x86_64-xlate.pl
index 3ebb018..6e487b8 100755
--- a/src/crypto/perlasm/x86_64-xlate.pl
+++ b/src/crypto/perlasm/x86_64-xlate.pl
@@ -1,4 +1,11 @@
-#!/usr/bin/env perl
+#! /usr/bin/env perl
+# Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the OpenSSL license (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
 
 # Ascetic x86_64 AT&T to MASM/NASM assembler translator by <appro>.
 #
@@ -44,12 +51,7 @@
 # 7. Stick to explicit ip-relative addressing. If you have to use
 #    GOTPCREL addressing, stick to mov symbol@GOTPCREL(%rip),%r??.
 #    Both are recognized and translated to proper Win64 addressing
-#    modes. To support legacy code a synthetic directive, .picmeup,
-#    is implemented. It puts address of the *next* instruction into
-#    target register, e.g.:
-#
-#		.picmeup	%rax
-#		lea		.Label-.(%rax),%rax
+#    modes.
 #
 # 8. In order to provide for structured exception handling unified
 #    Win64 prologue copies %rsp value to %rax. For further details
@@ -58,6 +60,9 @@
 # a. If function accepts more than 4 arguments *and* >4th argument
 #    is declared as non 64-bit value, do clear its upper part.
 
+
+use strict;
+
 my $flavour = shift;
 my $output  = shift;
 if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
@@ -84,12 +89,12 @@
 				  # environment variable check.
                                   die "mingw64 not supported";
 				  $prefix=`echo __USER_LABEL_PREFIX__ | $ENV{CC} -E -P -`;
-				  chomp($prefix);
+				  $prefix =~ s|\R$||; # Better chomp
 				}
 elsif ($flavour eq "macosx")	{ $gas=1; $elf=0; $prefix="_"; $decor="L\$"; }
 elsif ($flavour eq "masm")	{ $gas=0; $elf=0; $masm=$masmref; $win64=1; $decor="\$L\$"; }
 elsif ($flavour eq "nasm")	{ $gas=0; $elf=0; $nasm=$nasmref; $win64=1; $decor="\$L\$"; $PTR=""; }
-elsif (!$gas)                   { die "unknown flavour $flavour"; }
+elsif (!$gas)			{ die "unknown flavour $flavour"; }
 
 my $current_segment;
 my $current_function;
@@ -97,14 +102,15 @@
 
 { package opcode;	# pick up opcodes
     sub re {
-	my	$self = shift;	# single instance in enough...
-	local	*line = shift;
-	undef	$ret;
+	my	($class, $line) = @_;
+	my	$self = {};
+	my	$ret;
 
-	if ($line =~ /^([a-z][a-z0-9]*)/i) {
+	if ($$line =~ /^([a-z][a-z0-9]*)/i) {
+	    bless $self,$class;
 	    $self->{op} = $1;
 	    $ret = $self;
-	    $line = substr($line,@+[0]); $line =~ s/^\s+//;
+	    $$line = substr($$line,@+[0]); $$line =~ s/^\s+//;
 
 	    undef $self->{sz};
 	    if ($self->{op} =~ /^(movz)x?([bw]).*/) {	# movz is pain...
@@ -114,9 +120,9 @@
 		$self->{sz} = "";
 	    } elsif ($self->{op} =~ /^p/ && $' !~ /^(ush|op|insrw)/) { # SSEn
 		$self->{sz} = "";
-	    } elsif ($self->{op} =~ /^v/) { # VEX
+	    } elsif ($self->{op} =~ /^[vk]/) { # VEX or k* such as kmov
 		$self->{sz} = "";
-	    } elsif ($self->{op} =~ /mov[dq]/ && $line =~ /%xmm/) {
+	    } elsif ($self->{op} =~ /mov[dq]/ && $$line =~ /%xmm/) {
 		$self->{sz} = "";
 	    } elsif ($self->{op} =~ /([a-z]{3,})([qlwb])$/) {
 		$self->{op} = $1;
@@ -126,8 +132,7 @@
 	$ret;
     }
     sub size {
-	my $self = shift;
-	my $sz   = shift;
+	my ($self, $sz) = @_;
 	$self->{sz} = $sz if (defined($sz) && !defined($self->{sz}));
 	$self->{sz};
     }
@@ -136,7 +141,7 @@
 	if ($gas) {
 	    if ($self->{op} eq "movz") {	# movz is pain...
 		sprintf "%s%s%s",$self->{op},$self->{sz},shift;
-	    } elsif ($self->{op} =~ /^set/) { 
+	    } elsif ($self->{op} =~ /^set/) {
 		"$self->{op}";
 	    } elsif ($self->{op} eq "ret") {
 		my $epilogue = "";
@@ -155,82 +160,95 @@
 	    if ($self->{op} eq "ret") {
 		$self->{op} = "";
 		if ($win64 && $current_function->{abi} eq "svr4") {
-		    $self->{op} = "mov	rdi,QWORD${PTR}[8+rsp]\t;WIN64 epilogue\n\t".
-				  "mov	rsi,QWORD${PTR}[16+rsp]\n\t";
+		    $self->{op} = "mov	rdi,QWORD$PTR\[8+rsp\]\t;WIN64 epilogue\n\t".
+				  "mov	rsi,QWORD$PTR\[16+rsp\]\n\t";
 	    	}
 		$self->{op} .= "DB\t0F3h,0C3h\t\t;repret";
 	    } elsif ($self->{op} =~ /^(pop|push)f/) {
 		$self->{op} .= $self->{sz};
 	    } elsif ($self->{op} eq "call" && $current_segment eq ".CRT\$XCU") {
 		$self->{op} = "\tDQ";
-	    } 
+	    }
 	    $self->{op};
 	}
     }
     sub mnemonic {
-	my $self=shift;
-	my $op=shift;
+	my ($self, $op) = @_;
 	$self->{op}=$op if (defined($op));
 	$self->{op};
     }
 }
 { package const;	# pick up constants, which start with $
     sub re {
-	my	$self = shift;	# single instance in enough...
-	local	*line = shift;
-	undef	$ret;
+	my	($class, $line) = @_;
+	my	$self = {};
+	my	$ret;
 
-	if ($line =~ /^\$([^,]+)/) {
+	if ($$line =~ /^\$([^,]+)/) {
+	    bless $self, $class;
 	    $self->{value} = $1;
 	    $ret = $self;
-	    $line = substr($line,@+[0]); $line =~ s/^\s+//;
+	    $$line = substr($$line,@+[0]); $$line =~ s/^\s+//;
 	}
 	$ret;
     }
     sub out {
     	my $self = shift;
 
+	$self->{value} =~ s/\b(0b[0-1]+)/oct($1)/eig;
 	if ($gas) {
 	    # Solaris /usr/ccs/bin/as can't handle multiplications
 	    # in $self->{value}
-	    $self->{value} =~ s/(?<![\w\$\.])(0x?[0-9a-f]+)/oct($1)/egi;
-	    $self->{value} =~ s/([0-9]+\s*[\*\/\%]\s*[0-9]+)/eval($1)/eg;
+	    my $value = $self->{value};
+	    no warnings;    # oct might complain about overflow, ignore here...
+	    $value =~ s/(?<![\w\$\.])(0x?[0-9a-f]+)/oct($1)/egi;
+	    if ($value =~ s/([0-9]+\s*[\*\/\%]\s*[0-9]+)/eval($1)/eg) {
+		$self->{value} = $value;
+	    }
 	    sprintf "\$%s",$self->{value};
 	} else {
-	    $self->{value} =~ s/(0b[0-1]+)/oct($1)/eig;
 	    $self->{value} =~ s/0x([0-9a-f]+)/0$1h/ig if ($masm);
 	    sprintf "%s",$self->{value};
 	}
     }
 }
 { package ea;		# pick up effective addresses: expr(%reg,%reg,scale)
-    sub re {
-	my	$self = shift;	# single instance in enough...
-	local	*line = shift;
-	undef	$ret;
 
-	# optional * ---vvv--- appears in indirect jmp/call
-	if ($line =~ /^(\*?)([^\(,]*)\(([%\w,]+)\)/) {
+    my %szmap = (	b=>"BYTE$PTR",    w=>"WORD$PTR",
+			l=>"DWORD$PTR",   d=>"DWORD$PTR",
+			q=>"QWORD$PTR",   o=>"OWORD$PTR",
+			x=>"XMMWORD$PTR", y=>"YMMWORD$PTR",
+			z=>"ZMMWORD$PTR" ) if (!$gas);
+
+    sub re {
+	my	($class, $line, $opcode) = @_;
+	my	$self = {};
+	my	$ret;
+
+	# optional * ----vvv--- appears in indirect jmp/call
+	if ($$line =~ /^(\*?)([^\(,]*)\(([%\w,]+)\)((?:{[^}]+})*)/) {
+	    bless $self, $class;
 	    $self->{asterisk} = $1;
 	    $self->{label} = $2;
 	    ($self->{base},$self->{index},$self->{scale})=split(/,/,$3);
 	    $self->{scale} = 1 if (!defined($self->{scale}));
+	    $self->{opmask} = $4;
 	    $ret = $self;
-	    $line = substr($line,@+[0]); $line =~ s/^\s+//;
+	    $$line = substr($$line,@+[0]); $$line =~ s/^\s+//;
 
 	    if ($win64 && $self->{label} =~ s/\@GOTPCREL//) {
-		die if (opcode->mnemonic() ne "mov");
-		opcode->mnemonic("lea");
+		die if ($opcode->mnemonic() ne "mov");
+		$opcode->mnemonic("lea");
 	    }
 	    $self->{base}  =~ s/^%//;
 	    $self->{index} =~ s/^%// if (defined($self->{index}));
+	    $self->{opcode} = $opcode;
 	}
 	$ret;
     }
     sub size {}
     sub out {
-    	my $self = shift;
-	my $sz = shift;
+	my ($self, $sz) = @_;
 
 	$self->{label} =~ s/([_a-z][_a-z0-9]*)/$globals{$1} or $1/gei;
 	$self->{label} =~ s/\.L/$decor/g;
@@ -242,12 +260,21 @@
 	$self->{base}  =~ s/^[er](.?[0-9xpi])[d]?$/r\1/;
 
 	# Solaris /usr/ccs/bin/as can't handle multiplications
-	# in $self->{label}, new gas requires sign extension...
+	# in $self->{label}...
 	use integer;
 	$self->{label} =~ s/(?<![\w\$\.])(0x?[0-9a-f]+)/oct($1)/egi;
 	$self->{label} =~ s/\b([0-9]+\s*[\*\/\%]\s*[0-9]+)\b/eval($1)/eg;
-	$self->{label} =~ s/\b([0-9]+)\b/$1<<32>>32/eg;
 
+	# Some assemblers insist on signed presentation of 32-bit
+	# offsets, but sign extension is a tricky business in perl...
+	if ((1<<31)<<1) {
+	    $self->{label} =~ s/\b([0-9]+)\b/$1<<32>>32/eg;
+	} else {
+	    $self->{label} =~ s/\b([0-9]+)\b/$1>>0/eg;
+	}
+
+	# if base register is %rbp or %r13, see if it's possible to
+	# flip base and index registers [for better performance]
 	if (!$self->{label} && $self->{index} && $self->{scale}==1 &&
 	    $self->{base} =~ /(rbp|r13)/) {
 		$self->{base} = $self->{index}; $self->{index} = $1;
@@ -257,64 +284,66 @@
 	    $self->{label} =~ s/^___imp_/__imp__/   if ($flavour eq "mingw64");
 
 	    if (defined($self->{index})) {
-		sprintf "%s%s(%s,%%%s,%d)",$self->{asterisk},
-					$self->{label},
+		sprintf "%s%s(%s,%%%s,%d)%s",
+					$self->{asterisk},$self->{label},
 					$self->{base}?"%$self->{base}":"",
-					$self->{index},$self->{scale};
+					$self->{index},$self->{scale},
+					$self->{opmask};
 	    } else {
-		sprintf "%s%s(%%%s)",	$self->{asterisk},$self->{label},$self->{base};
+		sprintf "%s%s(%%%s)%s",	$self->{asterisk},$self->{label},
+					$self->{base},$self->{opmask};
 	    }
 	} else {
-	    %szmap = (	b=>"BYTE$PTR",  w=>"WORD$PTR",
-			l=>"DWORD$PTR", d=>"DWORD$PTR",
-	    		q=>"QWORD$PTR", o=>"OWORD$PTR",
-			x=>"XMMWORD$PTR", y=>"YMMWORD$PTR", z=>"ZMMWORD$PTR" );
-
 	    $self->{label} =~ s/\./\$/g;
 	    $self->{label} =~ s/(?<![\w\$\.])0x([0-9a-f]+)/0$1h/ig;
 	    $self->{label} = "($self->{label})" if ($self->{label} =~ /[\*\+\-\/]/);
 
-	    ($self->{asterisk})					&& ($sz="q") ||
-	    (opcode->mnemonic() =~ /^v?mov([qd])$/)		&& ($sz=$1)  ||
-	    (opcode->mnemonic() =~ /^v?pinsr([qdwb])$/)		&& ($sz=$1)  ||
-	    (opcode->mnemonic() =~ /^vpbroadcast([qdwb])$/)	&& ($sz=$1)  ||
-	    (opcode->mnemonic() =~ /^vinsert[fi]128$/)		&& ($sz="x");
+	    my $mnemonic = $self->{opcode}->mnemonic();
+	    ($self->{asterisk})				&& ($sz="q") ||
+	    ($mnemonic =~ /^v?mov([qd])$/)		&& ($sz=$1)  ||
+	    ($mnemonic =~ /^v?pinsr([qdwb])$/)		&& ($sz=$1)  ||
+	    ($mnemonic =~ /^vpbroadcast([qdwb])$/)	&& ($sz=$1)  ||
+	    ($mnemonic =~ /^v(?!perm)[a-z]+[fi]128$/)	&& ($sz="x");
+
+	    $self->{opmask}  =~ s/%(k[0-7])/$1/;
 
 	    if (defined($self->{index})) {
-		sprintf "%s[%s%s*%d%s]",$szmap{$sz},
+		sprintf "%s[%s%s*%d%s]%s",$szmap{$sz},
 					$self->{label}?"$self->{label}+":"",
 					$self->{index},$self->{scale},
-					$self->{base}?"+$self->{base}":"";
+					$self->{base}?"+$self->{base}":"",
+					$self->{opmask};
 	    } elsif ($self->{base} eq "rip") {
 		sprintf "%s[%s]",$szmap{$sz},$self->{label};
 	    } else {
-		sprintf "%s[%s%s]",$szmap{$sz},
+		sprintf "%s[%s%s]%s",	$szmap{$sz},
 					$self->{label}?"$self->{label}+":"",
-					$self->{base};
+					$self->{base},$self->{opmask};
 	    }
 	}
     }
 }
 { package register;	# pick up registers, which start with %.
     sub re {
-	my	$class = shift;	# muliple instances...
+	my	($class, $line, $opcode) = @_;
 	my	$self = {};
-	local	*line = shift;
-	undef	$ret;
+	my	$ret;
 
-	# optional * ---vvv--- appears in indirect jmp/call
-	if ($line =~ /^(\*?)%(\w+)/) {
+	# optional * ----vvv--- appears in indirect jmp/call
+	if ($$line =~ /^(\*?)%(\w+)((?:{[^}]+})*)/) {
 	    bless $self,$class;
 	    $self->{asterisk} = $1;
 	    $self->{value} = $2;
+	    $self->{opmask} = $3;
+	    $opcode->size($self->size());
 	    $ret = $self;
-	    $line = substr($line,@+[0]); $line =~ s/^\s+//;
+	    $$line = substr($$line,@+[0]); $$line =~ s/^\s+//;
 	}
 	$ret;
     }
     sub size {
 	my	$self = shift;
-	undef	$ret;
+	my	$ret;
 
 	if    ($self->{value} =~ /^r[\d]+b$/i)	{ $ret="b"; }
 	elsif ($self->{value} =~ /^r[\d]+w$/i)	{ $ret="w"; }
@@ -329,20 +358,24 @@
     }
     sub out {
     	my $self = shift;
-	if ($gas)	{ sprintf "%s%%%s",$self->{asterisk},$self->{value}; }
-	else		{ $self->{value}; }
+	if ($gas)	{ sprintf "%s%%%s%s",	$self->{asterisk},
+						$self->{value},
+						$self->{opmask}; }
+	else		{ $self->{opmask} =~ s/%(k[0-7])/$1/;
+			  $self->{value}.$self->{opmask}; }
     }
 }
 { package label;	# pick up labels, which end with :
     sub re {
-	my	$self = shift;	# single instance is enough...
-	local	*line = shift;
-	undef	$ret;
+	my	($class, $line) = @_;
+	my	$self = {};
+	my	$ret;
 
-	if ($line =~ /(^[\.\w]+)\:/) {
+	if ($$line =~ /(^[\.\w]+)\:/) {
+	    bless $self,$class;
 	    $self->{value} = $1;
 	    $ret = $self;
-	    $line = substr($line,@+[0]); $line =~ s/^\s+//;
+	    $$line = substr($$line,@+[0]); $$line =~ s/^\s+//;
 
 	    $self->{value} =~ s/^\.L/$decor/;
 	}
@@ -353,9 +386,8 @@
 
 	if ($gas) {
 	    my $func = ($globals{$self->{value}} or $self->{value}) . ":";
-	    if ($win64	&&
-			$current_function->{name} eq $self->{value} &&
-			$current_function->{abi} eq "svr4") {
+	    if ($win64	&& $current_function->{name} eq $self->{value}
+			&& $current_function->{abi} eq "svr4") {
 		$func .= "\n";
 		$func .= "	movq	%rdi,8(%rsp)\n";
 		$func .= "	movq	%rsi,16(%rsp)\n";
@@ -372,14 +404,15 @@
 	    }
 	    $func;
 	} elsif ($self->{value} ne "$current_function->{name}") {
-	    $self->{value} .= ":" if ($masm && $ret!~m/^\$/);
+	    # Make all labels in masm global.
+	    $self->{value} .= ":" if ($masm);
 	    $self->{value} . ":";
 	} elsif ($win64 && $current_function->{abi} eq "svr4") {
 	    my $func =	"$current_function->{name}" .
 			($nasm ? ":" : "\tPROC $current_function->{scope}") .
 			"\n";
-	    $func .= "	mov	QWORD${PTR}[8+rsp],rdi\t;WIN64 prologue\n";
-	    $func .= "	mov	QWORD${PTR}[16+rsp],rsi\n";
+	    $func .= "	mov	QWORD$PTR\[8+rsp\],rdi\t;WIN64 prologue\n";
+	    $func .= "	mov	QWORD$PTR\[16+rsp\],rsi\n";
 	    $func .= "	mov	rax,rsp\n";
 	    $func .= "${decor}SEH_begin_$current_function->{name}:";
 	    $func .= ":" if ($masm);
@@ -390,8 +423,8 @@
 	    $func .= "	mov	rsi,rdx\n" if ($narg>1);
 	    $func .= "	mov	rdx,r8\n"  if ($narg>2);
 	    $func .= "	mov	rcx,r9\n"  if ($narg>3);
-	    $func .= "	mov	r8,QWORD${PTR}[40+rsp]\n" if ($narg>4);
-	    $func .= "	mov	r9,QWORD${PTR}[48+rsp]\n" if ($narg>5);
+	    $func .= "	mov	r8,QWORD$PTR\[40+rsp\]\n" if ($narg>4);
+	    $func .= "	mov	r9,QWORD$PTR\[48+rsp\]\n" if ($narg>5);
 	    $func .= "\n";
 	} else {
 	   "$current_function->{name}".
@@ -399,67 +432,294 @@
 	}
     }
 }
-{ package expr;		# pick up expressioins
+{ package expr;		# pick up expressions
     sub re {
-	my	$self = shift;	# single instance is enough...
-	local	*line = shift;
-	undef	$ret;
+	my	($class, $line, $opcode) = @_;
+	my	$self = {};
+	my	$ret;
 
-	if ($line =~ /(^[^,]+)/) {
+	if ($$line =~ /(^[^,]+)/) {
+	    bless $self,$class;
 	    $self->{value} = $1;
 	    $ret = $self;
-	    $line = substr($line,@+[0]); $line =~ s/^\s+//;
+	    $$line = substr($$line,@+[0]); $$line =~ s/^\s+//;
 
 	    $self->{value} =~ s/\@PLT// if (!$elf);
 	    $self->{value} =~ s/([_a-z][_a-z0-9]*)/$globals{$1} or $1/gei;
 	    $self->{value} =~ s/\.L/$decor/g;
+	    $self->{opcode} = $opcode;
 	}
 	$ret;
     }
     sub out {
 	my $self = shift;
-	if ($nasm && opcode->mnemonic()=~m/^j(?![re]cxz)/) {
+	if ($nasm && $self->{opcode}->mnemonic()=~m/^j(?![re]cxz)/) {
 	    "NEAR ".$self->{value};
 	} else {
 	    $self->{value};
 	}
     }
 }
+{ package cfi_directive;
+    # CFI directives annotate instructions that are significant for
+    # stack unwinding procedure compliant with DWARF specification,
+    # see http://dwarfstd.org/. Besides naturally expected for this
+    # script platform-specific filtering function, this module adds
+    # three auxiliary synthetic directives not recognized by [GNU]
+    # assembler:
+    #
+    # - .cfi_push to annotate push instructions in prologue, which
+    #   translates to .cfi_adjust_cfa_offset (if needed) and
+    #   .cfi_offset;
+    # - .cfi_pop to annotate pop instructions in epilogue, which
+    #   translates to .cfi_adjust_cfa_offset (if needed) and
+    #   .cfi_restore;
+    # - [and most notably] .cfi_cfa_expression which encodes
+    #   DW_CFA_def_cfa_expression and passes it to .cfi_escape as
+    #   byte vector;
+    #
+    # CFA expressions were introduced in DWARF specification version
+    # 3 and describe how to deduce CFA, Canonical Frame Address. This
+    # becomes handy if your stack frame is variable and you can't
+    # spare register for [previous] frame pointer. Suggested directive
+    # syntax is made-up mix of DWARF operator suffixes [subset of]
+    # and references to registers with optional bias. Following example
+    # describes offloaded *original* stack pointer at specific offset
+    # from *current* stack pointer:
+    #
+    #   .cfi_cfa_expression     %rsp+40,deref,+8
+    #
+    # Final +8 has everything to do with the fact that CFA is defined
+    # as reference to top of caller's stack, and on x86_64 call to
+    # subroutine pushes 8-byte return address. In other words original
+    # stack pointer upon entry to a subroutine is 8 bytes off from CFA.
+
+    # Below constants are taken from "DWARF Expressions" section of the
+    # DWARF specification, section is numbered 7.7 in versions 3 and 4.
+    my %DW_OP_simple = (	# no-arg operators, mapped directly
+	deref	=> 0x06,	dup	=> 0x12,
+	drop	=> 0x13,	over	=> 0x14,
+	pick	=> 0x15,	swap	=> 0x16,
+	rot	=> 0x17,	xderef	=> 0x18,
+
+	abs	=> 0x19,	and	=> 0x1a,
+	div	=> 0x1b,	minus	=> 0x1c,
+	mod	=> 0x1d,	mul	=> 0x1e,
+	neg	=> 0x1f,	not	=> 0x20,
+	or	=> 0x21,	plus	=> 0x22,
+	shl	=> 0x24,	shr	=> 0x25,
+	shra	=> 0x26,	xor	=> 0x27,
+	);
+
+    my %DW_OP_complex = (	# used in specific subroutines
+	constu		=> 0x10,	# uleb128
+	consts		=> 0x11,	# sleb128
+	plus_uconst	=> 0x23,	# uleb128
+	lit0 		=> 0x30,	# add 0-31 to opcode
+	reg0		=> 0x50,	# add 0-31 to opcode
+	breg0		=> 0x70,	# add 0-31 to opcole, sleb128
+	regx		=> 0x90,	# uleb28
+	fbreg		=> 0x91,	# sleb128
+	bregx		=> 0x92,	# uleb128, sleb128
+	piece		=> 0x93,	# uleb128
+	);
+
+    # Following constants are defined in x86_64 ABI supplement, for
+    # example avaiable at https://www.uclibc.org/docs/psABI-x86_64.pdf,
+    # see section 3.7 "Stack Unwind Algorithm".
+    my %DW_reg_idx = (
+	"%rax"=>0,  "%rdx"=>1,  "%rcx"=>2,  "%rbx"=>3,
+	"%rsi"=>4,  "%rdi"=>5,  "%rbp"=>6,  "%rsp"=>7,
+	"%r8" =>8,  "%r9" =>9,  "%r10"=>10, "%r11"=>11,
+	"%r12"=>12, "%r13"=>13, "%r14"=>14, "%r15"=>15
+	);
+
+    my ($cfa_reg, $cfa_rsp);
+
+    # [us]leb128 format is variable-length integer representation base
+    # 2^128, with most significant bit of each byte being 0 denoting
+    # *last* most significat digit. See "Variable Length Data" in the
+    # DWARF specification, numbered 7.6 at least in versions 3 and 4.
+    sub sleb128 {
+	use integer;	# get right shift extend sign
+
+	my $val = shift;
+	my $sign = ($val < 0) ? -1 : 0;
+	my @ret = ();
+
+	while(1) {
+	    push @ret, $val&0x7f;
+
+	    # see if remaining bits are same and equal to most
+	    # significant bit of the current digit, if so, it's
+	    # last digit...
+	    last if (($val>>6) == $sign);
+
+	    @ret[-1] |= 0x80;
+	    $val >>= 7;
+	}
+
+	return @ret;
+    }
+    sub uleb128 {
+	my $val = shift;
+	my @ret = ();
+
+	while(1) {
+	    push @ret, $val&0x7f;
+
+	    # see if it's last significant digit...
+	    last if (($val >>= 7) == 0);
+
+	    @ret[-1] |= 0x80;
+	}
+
+	return @ret;
+    }
+    sub const {
+	my $val = shift;
+
+	if ($val >= 0 && $val < 32) {
+            return ($DW_OP_complex{lit0}+$val);
+	}
+	return ($DW_OP_complex{consts}, sleb128($val));
+    }
+    sub reg {
+	my $val = shift;
+
+	return if ($val !~ m/^(%r\w+)(?:([\+\-])((?:0x)?[0-9a-f]+))?/);
+
+	my $reg = $DW_reg_idx{$1};
+	my $off = eval ("0 $2 $3");
+
+	return (($DW_OP_complex{breg0} + $reg), sleb128($off));
+	# Yes, we use DW_OP_bregX+0 to push register value and not
+	# DW_OP_regX, because latter would require even DW_OP_piece,
+	# which would be a waste under the circumstances. If you have
+	# to use DWP_OP_reg, use "regx:N"...
+    }
+    sub cfa_expression {
+	my $line = shift;
+	my @ret;
+
+	foreach my $token (split(/,\s*/,$line)) {
+	    if ($token =~ /^%r/) {
+		push @ret,reg($token);
+	    } elsif ($token =~ /((?:0x)?[0-9a-f]+)\((%r\w+)\)/) {
+		push @ret,reg("$2+$1");
+	    } elsif ($token =~ /(\w+):(\-?(?:0x)?[0-9a-f]+)(U?)/i) {
+		my $i = 1*eval($2);
+		push @ret,$DW_OP_complex{$1}, ($3 ? uleb128($i) : sleb128($i));
+	    } elsif (my $i = 1*eval($token) or $token eq "0") {
+		if ($token =~ /^\+/) {
+		    push @ret,$DW_OP_complex{plus_uconst},uleb128($i);
+		} else {
+		    push @ret,const($i);
+		}
+	    } else {
+		push @ret,$DW_OP_simple{$token};
+	    }
+	}
+
+	# Finally we return DW_CFA_def_cfa_expression, 15, followed by
+	# length of the expression and of course the expression itself.
+	return (15,scalar(@ret),@ret);
+    }
+    sub re {
+	my	($class, $line) = @_;
+	my	$self = {};
+	my	$ret;
+
+	if ($$line =~ s/^\s*\.cfi_(\w+)\s*//) {
+	    bless $self,$class;
+	    $ret = $self;
+	    undef $self->{value};
+	    my $dir = $1;
+
+	    SWITCH: for ($dir) {
+	    # What is $cfa_rsp? Effectively it's difference between %rsp
+	    # value and current CFA, Canonical Frame Address, which is
+	    # why it starts with -8. Recall that CFA is top of caller's
+	    # stack...
+	    /startproc/	&& do {	($cfa_reg, $cfa_rsp) = ("%rsp", -8); last; };
+	    /endproc/	&& do {	($cfa_reg, $cfa_rsp) = ("%rsp",  0); last; };
+	    /def_cfa_register/
+			&& do {	$cfa_reg = $$line; last; };
+	    /def_cfa_offset/
+			&& do {	$cfa_rsp = -1*eval($$line) if ($cfa_reg eq "%rsp");
+				last;
+			      };
+	    /adjust_cfa_offset/
+			&& do {	$cfa_rsp -= 1*eval($$line) if ($cfa_reg eq "%rsp");
+				last;
+			      };
+	    /def_cfa/	&& do {	if ($$line =~ /(%r\w+)\s*,\s*(.+)/) {
+				    $cfa_reg = $1;
+				    $cfa_rsp = -1*eval($2) if ($cfa_reg eq "%rsp");
+				}
+				last;
+			      };
+	    /push/	&& do {	$dir = undef;
+				$cfa_rsp -= 8;
+				if ($cfa_reg eq "%rsp") {
+				    $self->{value} = ".cfi_adjust_cfa_offset\t8\n";
+				}
+				$self->{value} .= ".cfi_offset\t$$line,$cfa_rsp";
+				last;
+			      };
+	    /pop/	&& do {	$dir = undef;
+				$cfa_rsp += 8;
+				if ($cfa_reg eq "%rsp") {
+				    $self->{value} = ".cfi_adjust_cfa_offset\t-8\n";
+				}
+				$self->{value} .= ".cfi_restore\t$$line";
+				last;
+			      };
+	    /cfa_expression/
+			&& do {	$dir = undef;
+				$self->{value} = ".cfi_escape\t" .
+					join(",", map(sprintf("0x%02x", $_),
+						      cfa_expression($$line)));
+				last;
+			      };
+	    }
+
+	    $self->{value} = ".cfi_$dir\t$$line" if ($dir);
+
+	    $$line = "";
+	}
+
+	return $ret;
+    }
+    sub out {
+	my $self = shift;
+	return ($elf ? $self->{value} : undef);
+    }
+}
 { package directive;	# pick up directives, which start with .
     sub re {
-	my	$self = shift;	# single instance is enough...
-	local	*line = shift;
-	undef	$ret;
+	my	($class, $line) = @_;
+	my	$self = {};
+	my	$ret;
 	my	$dir;
-	my	%opcode =	# lea 2f-1f(%rip),%dst; 1: nop; 2:
-		(	"%rax"=>0x01058d48,	"%rcx"=>0x010d8d48,
-			"%rdx"=>0x01158d48,	"%rbx"=>0x011d8d48,
-			"%rsp"=>0x01258d48,	"%rbp"=>0x012d8d48,
-			"%rsi"=>0x01358d48,	"%rdi"=>0x013d8d48,
-			"%r8" =>0x01058d4c,	"%r9" =>0x010d8d4c,
-			"%r10"=>0x01158d4c,	"%r11"=>0x011d8d4c,
-			"%r12"=>0x01258d4c,	"%r13"=>0x012d8d4c,
-			"%r14"=>0x01358d4c,	"%r15"=>0x013d8d4c	);
 
-	if ($line =~ /^\s*(\.\w+)/) {
+	# chain-call to cfi_directive
+	$ret = cfi_directive->re($line) and return $ret;
+
+	if ($$line =~ /^\s*(\.\w+)/) {
+	    bless $self,$class;
 	    $dir = $1;
 	    $ret = $self;
 	    undef $self->{value};
-	    $line = substr($line,@+[0]); $line =~ s/^\s+//;
+	    $$line = substr($$line,@+[0]); $$line =~ s/^\s+//;
 
 	    SWITCH: for ($dir) {
-		/\.picmeup/ && do { if ($line =~ /(%r[\w]+)/i) {
-			    		$dir="\t.long";
-					$line=sprintf "0x%x,0x90000000",$opcode{$1};
-				    }
-				    last;
-				  };
 		/\.global|\.globl|\.extern/
-			    && do { $globals{$line} = $prefix . $line;
-				    $line = $globals{$line} if ($prefix);
+			    && do { $globals{$$line} = $prefix . $$line;
+				    $$line = $globals{$$line} if ($prefix);
 				    last;
 				  };
-		/\.type/    && do { ($sym,$type,$narg) = split(',',$line);
+		/\.type/    && do { my ($sym,$type,$narg) = split(',',$$line);
 				    if ($type eq "\@function") {
 					undef $current_function;
 					$current_function->{name} = $sym;
@@ -471,29 +731,29 @@
 					$current_function->{name} = $sym;
 					$current_function->{scope} = defined($globals{$sym})?"PUBLIC":"PRIVATE";
 				    }
-				    $line =~ s/\@abi\-omnipotent/\@function/;
-				    $line =~ s/\@function.*/\@function/;
+				    $$line =~ s/\@abi\-omnipotent/\@function/;
+				    $$line =~ s/\@function.*/\@function/;
 				    last;
 				  };
-		/\.asciz/   && do { if ($line =~ /^"(.*)"$/) {
+		/\.asciz/   && do { if ($$line =~ /^"(.*)"$/) {
 					$dir  = ".byte";
-					$line = join(",",unpack("C*",$1),0);
+					$$line = join(",",unpack("C*",$1),0);
 				    }
 				    last;
 				  };
 		/\.rva|\.long|\.quad/
-			    && do { $line =~ s/([_a-z][_a-z0-9]*)/$globals{$1} or $1/gei;
-				    $line =~ s/\.L/$decor/g;
+			    && do { $$line =~ s/([_a-z][_a-z0-9]*)/$globals{$1} or $1/gei;
+				    $$line =~ s/\.L/$decor/g;
 				    last;
 				  };
 	    }
 
 	    if ($gas) {
-		$self->{value} = $dir . "\t" . $line;
+		$self->{value} = $dir . "\t" . $$line;
 
 		if ($dir =~ /\.extern/) {
 		    if ($flavour eq "elf") {
-			$self->{value} .= "\n.hidden $line";
+			$self->{value} .= "\n.hidden $$line";
 		    } else {
 			$self->{value} = "";
 		    }
@@ -502,7 +762,7 @@
 		    $self->{value} = ".def\t" . ($globals{$1} or $1) . ";\t" .
 				(defined($globals{$1})?".scl 2;":".scl 3;") .
 				"\t.type 32;\t.endef"
-				if ($win64 && $line =~ /([^,]+),\@function/);
+				if ($win64 && $$line =~ /([^,]+),\@function/);
 		} elsif (!$elf && $dir =~ /\.size/) {
 		    $self->{value} = "";
 		    if (defined($current_function)) {
@@ -511,9 +771,9 @@
 			undef $current_function;
 		    }
 		} elsif (!$elf && $dir =~ /\.align/) {
-		    $self->{value} = ".p2align\t" . (log($line)/log(2));
+		    $self->{value} = ".p2align\t" . (log($$line)/log(2));
 		} elsif ($dir eq ".section") {
-		    $current_segment=$line;
+		    $current_segment=$$line;
 		    if (!$elf && $current_segment eq ".init") {
 			if	($flavour eq "macosx")	{ $self->{value} = ".mod_init_func"; }
 			elsif	($flavour eq "mingw64")	{ $self->{value} = ".section\t.ctors"; }
@@ -522,18 +782,18 @@
 		    $current_segment=".$1";
 		} elsif ($dir =~ /\.global|\.globl|\.extern/) {
 		    if ($flavour eq "macosx") {
-		        $self->{value} .= "\n.private_extern $line";
+		        $self->{value} .= "\n.private_extern $$line";
 		    } else {
-		        $self->{value} .= "\n.hidden $line";
+		        $self->{value} .= "\n.hidden $$line";
 		    }
 		} elsif ($dir =~ /\.hidden/) {
-		    if    ($flavour eq "macosx")  { $self->{value} = ".private_extern\t$prefix$line"; }
+		    if    ($flavour eq "macosx")  { $self->{value} = ".private_extern\t$prefix$$line"; }
 		    elsif ($flavour eq "mingw64") { $self->{value} = ""; }
 		} elsif ($dir =~ /\.comm/) {
-		    $self->{value} = "$dir\t$prefix$line";
+		    $self->{value} = "$dir\t$prefix$$line";
 		    $self->{value} =~ s|,([0-9]+),([0-9]+)$|",$1,".log($2)/log(2)|e if ($flavour eq "macosx");
 		}
-		$line = "";
+		$$line = "";
 		return $self;
 	    }
 
@@ -564,38 +824,38 @@
 				    last;
 				  };
 		/\.section/ && do { my $v=undef;
-				    $line =~ s/([^,]*).*/$1/;
-				    $line = ".CRT\$XCU" if ($line eq ".init");
+				    $$line =~ s/([^,]*).*/$1/;
+				    $$line = ".CRT\$XCU" if ($$line eq ".init");
 				    if ($nasm) {
-					$v="section	$line";
-					if ($line=~/\.([px])data/) {
+					$v="section	$$line";
+					if ($$line=~/\.([px])data/) {
 					    $v.=" rdata align=";
 					    $v.=$1 eq "p"? 4 : 8;
-					} elsif ($line=~/\.CRT\$/i) {
+					} elsif ($$line=~/\.CRT\$/i) {
 					    $v.=" rdata align=8";
 					}
 				    } else {
 					$v="$current_segment\tENDS\n" if ($current_segment);
-					$v.="$line\tSEGMENT";
-					if ($line=~/\.([px])data/) {
+					$v.="$$line\tSEGMENT";
+					if ($$line=~/\.([px])data/) {
 					    $v.=" READONLY";
 					    $v.=" ALIGN(".($1 eq "p" ? 4 : 8).")" if ($masm>=$masmref);
-					} elsif ($line=~/\.CRT\$/i) {
+					} elsif ($$line=~/\.CRT\$/i) {
 					    $v.=" READONLY ";
 					    $v.=$masm>=$masmref ? "ALIGN(8)" : "DWORD";
 					}
 				    }
-				    $current_segment = $line;
+				    $current_segment = $$line;
 				    $self->{value} = $v;
 				    last;
 				  };
-		/\.extern/  && do { $self->{value}  = "EXTERN\t".$line;
+		/\.extern/  && do { $self->{value}  = "EXTERN\t".$$line;
 				    $self->{value} .= ":NEAR" if ($masm);
 				    last;
 				  };
 		/\.globl|.global/
 			    && do { $self->{value}  = $masm?"PUBLIC":"global";
-				    $self->{value} .= "\t".$line;
+				    $self->{value} .= "\t".$$line;
 				    last;
 				  };
 		/\.size/    && do { if (defined($current_function)) {
@@ -609,10 +869,13 @@
 				    }
 				    last;
 				  };
-		/\.align/   && do { $self->{value} = "ALIGN\t".$line; last; };
+		/\.align/   && do { my $max = ($masm && $masm>=$masmref) ? 256 : 4096;
+				    $self->{value} = "ALIGN\t".($$line>$max?$max:$$line);
+				    last;
+				  };
 		/\.(value|long|rva|quad)/
 			    && do { my $sz  = substr($1,0,1);
-				    my @arr = split(/,\s*/,$line);
+				    my @arr = split(/,\s*/,$$line);
 				    my $last = pop(@arr);
 				    my $conv = sub  {	my $var=shift;
 							$var=~s/^(0b[0-1]+)/oct($1)/eig;
@@ -620,7 +883,7 @@
 							if ($sz eq "D" && ($current_segment=~/.[px]data/ || $dir eq ".rva"))
 							{ $var=~s/([_a-z\$\@][_a-z0-9\$\@]*)/$nasm?"$1 wrt ..imagebase":"imagerel $1"/egi; }
 							$var;
-						    };  
+						    };
 
 				    $sz =~ tr/bvlrq/BWDDQ/;
 				    $self->{value} = "\tD$sz\t";
@@ -628,9 +891,9 @@
 				    $self->{value} .= &$conv($last);
 				    last;
 				  };
-		/\.byte/    && do { my @str=split(/,\s*/,$line);
+		/\.byte/    && do { my @str=split(/,\s*/,$$line);
 				    map(s/(0b[0-1]+)/oct($1)/eig,@str);
-				    map(s/0x([0-9a-f]+)/0$1h/ig,@str) if ($masm);	
+				    map(s/0x([0-9a-f]+)/0$1h/ig,@str) if ($masm);
 				    while ($#str>15) {
 					$self->{value}.="DB\t"
 						.join(",",@str[0..15])."\n";
@@ -640,7 +903,7 @@
 						.join(",",@str) if (@str);
 				    last;
 				  };
-		/\.comm/    && do { my @str=split(/,\s*/,$line);
+		/\.comm/    && do { my @str=split(/,\s*/,$$line);
 				    my $v=undef;
 				    if ($nasm) {
 					$v.="common	$prefix@str[0] @str[1]";
@@ -654,7 +917,7 @@
 				    last;
 				  };
 	    }
-	    $line = "";
+	    $$line = "";
 	}
 
 	$ret;
@@ -665,19 +928,25 @@
     }
 }
 
+# Upon initial x86_64 introduction SSE>2 extensions were not introduced
+# yet. In order not to be bothered by tracing exact assembler versions,
+# but at the same time to provide a bare security minimum of AES-NI, we
+# hard-code some instructions. Extensions past AES-NI on the other hand
+# are traced by examining assembler version in individual perlasm
+# modules...
+
+my %regrm = (	"%eax"=>0, "%ecx"=>1, "%edx"=>2, "%ebx"=>3,
+		"%esp"=>4, "%ebp"=>5, "%esi"=>6, "%edi"=>7	);
+
 sub rex {
- local *opcode=shift;
+ my $opcode=shift;
  my ($dst,$src,$rex)=@_;
 
    $rex|=0x04 if($dst>=8);
    $rex|=0x01 if($src>=8);
-   push @opcode,($rex|0x40) if ($rex);
+   push @$opcode,($rex|0x40) if ($rex);
 }
 
-# older gas and ml64 don't handle SSE>2 instructions
-my %regrm = (	"%eax"=>0, "%ecx"=>1, "%edx"=>2, "%ebx"=>3,
-		"%esp"=>4, "%ebp"=>5, "%esi"=>6, "%edi"=>7	);
-
 my $movq = sub {	# elderly gas can't handle inter-register movq
   my $arg = shift;
   my @opcode=(0x66);
@@ -703,9 +972,9 @@
 my $pextrd = sub {
     if (shift =~ /\$([0-9]+),\s*%xmm([0-9]+),\s*(%\w+)/) {
       my @opcode=(0x66);
-	$imm=$1;
-	$src=$2;
-	$dst=$3;
+	my $imm=$1;
+	my $src=$2;
+	my $dst=$3;
 	if ($dst =~ /%r([0-9]+)d/)	{ $dst = $1; }
 	elsif ($dst =~ /%e/)		{ $dst = $regrm{$dst}; }
 	rex(\@opcode,$src,$dst);
@@ -721,9 +990,9 @@
 my $pinsrd = sub {
     if (shift =~ /\$([0-9]+),\s*(%\w+),\s*%xmm([0-9]+)/) {
       my @opcode=(0x66);
-	$imm=$1;
-	$src=$2;
-	$dst=$3;
+	my $imm=$1;
+	my $src=$2;
+	my $dst=$3;
 	if ($src =~ /%r([0-9]+)/)	{ $src = $1; }
 	elsif ($src =~ /%e/)		{ $src = $regrm{$src}; }
 	rex(\@opcode,$dst,$src);
@@ -780,7 +1049,7 @@
       my @opcode=();
       my $dst=$1;
 	if ($dst !~ /[0-9]+/) { $dst = $regrm{"%e$dst"}; }
-	rex(\@opcode,0,$1,8);
+	rex(\@opcode,0,$dst,8);
 	push @opcode,0x0f,0xc7,0xf0|($dst&7);
 	@opcode;
     } else {
@@ -793,7 +1062,7 @@
       my @opcode=();
       my $dst=$1;
 	if ($dst !~ /[0-9]+/) { $dst = $regrm{"%e$dst"}; }
-	rex(\@opcode,0,$1,8);
+	rex(\@opcode,0,$dst,8);
 	push @opcode,0x0f,0xc7,0xf8|($dst&7);
 	@opcode;
     } else {
@@ -801,15 +1070,19 @@
     }
 };
 
+# Not all AVX-capable assemblers recognize AMD XOP extension. Since we
+# are using only two instructions hand-code them in order to be excused
+# from chasing assembler versions...
+
 sub rxb {
- local *opcode=shift;
+ my $opcode=shift;
  my ($dst,$src1,$src2,$rxb)=@_;
 
    $rxb|=0x7<<5;
    $rxb&=~(0x04<<5) if($dst>=8);
    $rxb&=~(0x01<<5) if($src1>=8);
    $rxb&=~(0x02<<5) if($src2>=8);
-   push @opcode,$rxb;
+   push @$opcode,$rxb;
 }
 
 my $vprotd = sub {
@@ -840,6 +1113,15 @@
     }
 };
 
+# Intel Control-flow Enforcement Technology extension. All functions and
+# indirect branch targets will have to start with this instruction...
+
+my $endbranch = sub {
+    (0xf3,0x0f,0x1e,0xfa);
+};
+
+########################################################################
+
 if ($nasm) {
     print <<___;
 default	rel
@@ -852,54 +1134,49 @@
 OPTION	DOTNAME
 ___
 }
-
 print STDOUT "#if defined(__x86_64__)\n" if ($gas);
 
-while($line=<>) {
+while(defined(my $line=<>)) {
 
-    chomp($line);
+    $line =~ s|\R$||;           # Better chomp
 
     $line =~ s|[#!].*$||;	# get rid of asm-style comments...
     $line =~ s|/\*.*\*/||;	# ... and C-style comments...
     $line =~ s|^\s+||;		# ... and skip white spaces in beginning
     $line =~ s|\s+$||;		# ... and at the end
 
-    undef $label;
-    undef $opcode;
-    undef @args;
+    if (my $label=label->re(\$line))	{ print $label->out(); }
 
-    if ($label=label->re(\$line))	{ print $label->out(); }
-
-    if (directive->re(\$line)) {
-	printf "%s",directive->out();
-    } elsif ($opcode=opcode->re(\$line)) {
+    if (my $directive=directive->re(\$line)) {
+	printf "%s",$directive->out();
+    } elsif (my $opcode=opcode->re(\$line)) {
 	my $asm = eval("\$".$opcode->mnemonic());
-	undef @bytes;
-	
-	if ((ref($asm) eq 'CODE') && scalar(@bytes=&$asm($line))) {
+
+	if ((ref($asm) eq 'CODE') && scalar(my @bytes=&$asm($line))) {
 	    print $gas?".byte\t":"DB\t",join(',',@bytes),"\n";
 	    next;
 	}
 
+	my @args;
 	ARGUMENT: while (1) {
-	my $arg;
+	    my $arg;
 
-	if ($arg=register->re(\$line))	{ opcode->size($arg->size()); }
-	elsif ($arg=const->re(\$line))	{ }
-	elsif ($arg=ea->re(\$line))	{ }
-	elsif ($arg=expr->re(\$line))	{ }
-	else				{ last ARGUMENT; }
+	    ($arg=register->re(\$line, $opcode))||
+	    ($arg=const->re(\$line))		||
+	    ($arg=ea->re(\$line, $opcode))	||
+	    ($arg=expr->re(\$line, $opcode))	||
+	    last ARGUMENT;
 
-	push @args,$arg;
+	    push @args,$arg;
 
-	last ARGUMENT if ($line !~ /^,/);
+	    last ARGUMENT if ($line !~ /^,/);
 
-	$line =~ s/^,\s*//;
+	    $line =~ s/^,\s*//;
 	} # ARGUMENT:
 
 	if ($#args>=0) {
 	    my $insn;
-	    my $sz=opcode->size();
+	    my $sz=$opcode->size();
 
 	    if ($gas) {
 		$insn = $opcode->out($#args>=1?$args[$#args]->size():$sz);
@@ -960,13 +1237,13 @@
 # %r13		-		-
 # %r14		-		-
 # %r15		-		-
-# 
+#
 # (*)	volatile register
 # (-)	preserved by callee
 # (#)	Nth argument, volatile
 #
 # In Unix terms top of stack is argument transfer area for arguments
-# which could not be accomodated in registers. Or in other words 7th
+# which could not be accommodated in registers. Or in other words 7th
 # [integer] argument resides at 8(%rsp) upon function entry point.
 # 128 bytes above %rsp constitute a "red zone" which is not touched
 # by signal handlers and can be used as temporal storage without
@@ -983,7 +1260,7 @@
 # the area above user stack pointer in true asynchronous manner...
 #
 # All the above means that if assembler programmer adheres to Unix
-# register and stack layout, but disregards the "red zone" existense,
+# register and stack layout, but disregards the "red zone" existence,
 # it's possible to use following prologue and epilogue to "gear" from
 # Unix to Win64 ABI in leaf functions with not more than 6 arguments.
 #
@@ -1041,6 +1318,7 @@
 #	movq	-16(%rcx),%rbx
 #	movq	-8(%rcx),%r15
 #	movq	%rcx,%rsp	# restore original rsp
+# magic_epilogue:
 #	ret
 # .size function,.-function
 #
@@ -1053,11 +1331,16 @@
 # EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
 #		CONTEXT *context,DISPATCHER_CONTEXT *disp)
 # {	ULONG64 *rsp = (ULONG64 *)context->Rax;
-#	if (context->Rip >= magic_point)
-#	{   rsp = ((ULONG64 **)context->Rsp)[0];
-#	    context->Rbp = rsp[-3];
-#	    context->Rbx = rsp[-2];
-#	    context->R15 = rsp[-1];
+#	ULONG64  rip = context->Rip;
+#
+#	if (rip >= magic_point)
+#	{   rsp = (ULONG64 *)context->Rsp;
+#	    if (rip < magic_epilogue)
+#	    {	rsp = (ULONG64 *)rsp[0];
+#		context->Rbp = rsp[-3];
+#		context->Rbx = rsp[-2];
+#		context->R15 = rsp[-1];
+#	    }
 #	}
 #	context->Rsp = (ULONG64)rsp;
 #	context->Rdi = rsp[1];
@@ -1130,7 +1413,7 @@
 #	.rva	.LSEH_end_function
 #	.rva	function_unwind_info
 #
-# Reference to functon_unwind_info from .xdata segment is the anchor.
+# Reference to function_unwind_info from .xdata segment is the anchor.
 # In case you wonder why references are 32-bit .rvas and not 64-bit
 # .quads. References put into these two segments are required to be
 # *relative* to the base address of the current binary module, a.k.a.
@@ -1149,13 +1432,12 @@
 # instruction and reflecting it in finer grade unwind logic in handler.
 # After all, isn't it why it's called *language-specific* handler...
 #
-# Attentive reader can notice that exceptions would be mishandled in
-# auto-generated "gear" epilogue. Well, exception effectively can't
-# occur there, because if memory area used by it was subject to
-# segmentation violation, then it would be raised upon call to the
-# function (and as already mentioned be accounted to caller, which is
-# not a problem). If you're still not comfortable, then define tail
-# "magic point" just prior ret instruction and have handler treat it...
+# SE handlers are also involved in unwinding stack when executable is
+# profiled or debugged. Profiling implies additional limitations that
+# are too subtle to discuss here. For now it's sufficient to say that
+# in order to simplify handlers one should either a) offload original
+# %rsp to stack (like discussed above); or b) if you have a register to
+# spare for frame pointer, choose volatile one.
 #
 # (*)	Note that we're talking about run-time, not debug-time. Lack of
 #	unwind information makes debugging hard on both Windows and
diff --git a/src/crypto/perlasm/x86asm.pl b/src/crypto/perlasm/x86asm.pl
index 3c7be40..dc10d99 100644
--- a/src/crypto/perlasm/x86asm.pl
+++ b/src/crypto/perlasm/x86asm.pl
@@ -1,4 +1,11 @@
-#!/usr/bin/env perl
+#! /usr/bin/env perl
+# Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the OpenSSL license (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
 
 # require 'x86asm.pl';
 # &asm_init(<flavor>,"des-586.pl"[,$i386only]);
@@ -131,6 +138,14 @@
     {	&::generic("rdrand",@_);	}
 }
 
+sub ::rdseed
+{ my ($dst)=@_;
+    if ($dst =~ /(e[a-dsd][ixp])/)
+    {	&::data_byte(0x0f,0xc7,0xf8|$regrm{$dst});	}
+    else
+    {	&::generic("rdrand",@_);	}
+}
+
 sub rxb {
  local *opcode=shift;
  my ($dst,$src1,$src2,$rxb)=@_;
@@ -157,6 +172,11 @@
     {	&::generic("vprotd",@_);	}
 }
 
+sub ::endbranch
+{
+    &::data_byte(0xf3,0x0f,0x1e,0xfb);
+}
+
 # label management
 $lbdecor="L";		# local label decoration, set by package
 $label="000";
diff --git a/src/crypto/perlasm/x86gas.pl b/src/crypto/perlasm/x86gas.pl
index 99d7c1b..ab4c5a3 100644
--- a/src/crypto/perlasm/x86gas.pl
+++ b/src/crypto/perlasm/x86gas.pl
@@ -1,4 +1,11 @@
-#!/usr/bin/env perl
+#! /usr/bin/env perl
+# Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the OpenSSL license (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
 
 package x86gas;
 
@@ -17,7 +24,7 @@
 { my $reg=shift;
     if    ($reg =~ m/^%e/o)		{ "l"; }
     elsif ($reg =~ m/^%[a-d][hl]$/o)	{ "b"; }
-    elsif ($reg =~ m/^%[xm]/o)		{ undef; }
+    elsif ($reg =~ m/^%[yxm]/o)		{ undef; }
     else				{ "w"; }
 }
 
diff --git a/src/crypto/perlasm/x86masm.pl b/src/crypto/perlasm/x86masm.pl
index b7f49d1..a0a354c 100644
--- a/src/crypto/perlasm/x86masm.pl
+++ b/src/crypto/perlasm/x86masm.pl
@@ -1,4 +1,11 @@
-#!/usr/bin/env perl
+#! /usr/bin/env perl
+# Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the OpenSSL license (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
 
 package x86masm;
 
@@ -82,7 +89,7 @@
 IF \@Version LT 800
 ECHO MASM version 8.00 or later is strongly recommended.
 ENDIF
-.686
+.486
 .MODEL	FLAT
 OPTION	DOTNAME
 IF \@Version LT 800
diff --git a/src/crypto/perlasm/x86nasm.pl b/src/crypto/perlasm/x86nasm.pl
index f8332bb..d3773b6 100644
--- a/src/crypto/perlasm/x86nasm.pl
+++ b/src/crypto/perlasm/x86nasm.pl
@@ -1,4 +1,11 @@
-#!/usr/bin/env perl
+#! /usr/bin/env perl
+# Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the OpenSSL license (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
 
 package x86nasm;
 
@@ -133,7 +140,7 @@
 	grep {s/(^extern\s+${nmdecor}OPENSSL_ia32cap_P)/\;$1/} @out;
 	push (@out,$comm)
     }
-    push (@out,$initseg) if ($initseg);		
+    push (@out,$initseg) if ($initseg);
 }
 
 sub ::comment {   foreach (@_) { push(@out,"\t; $_\n"); }   }
diff --git a/src/crypto/pkcs8/CMakeLists.txt b/src/crypto/pkcs8/CMakeLists.txt
index 9550109..0bdccec 100644
--- a/src/crypto/pkcs8/CMakeLists.txt
+++ b/src/crypto/pkcs8/CMakeLists.txt
@@ -1,13 +1,12 @@
 include_directories(../../include)
 
 add_library(
-  pkcs8
+  pkcs8_lib
 
   OBJECT
 
   pkcs8.c
-  p8_pkey.c
-  p5_pbe.c
+  pkcs8_x509.c
   p5_pbev2.c
 )
 
diff --git a/src/crypto/pkcs8/internal.h b/src/crypto/pkcs8/internal.h
index 7995e78..583997d 100644
--- a/src/crypto/pkcs8/internal.h
+++ b/src/crypto/pkcs8/internal.h
@@ -63,17 +63,54 @@
 #endif
 
 
+/* pkcs8_pbe_decrypt decrypts |in| using the PBE scheme described by
+ * |algorithm|, which should be a serialized AlgorithmIdentifier structure. On
+ * success, it sets |*out| to a newly-allocated buffer containing the decrypted
+ * result and returns one. Otherwise, it returns zero. */
+int pkcs8_pbe_decrypt(uint8_t **out, size_t *out_len, CBS *algorithm,
+                      const char *pass, size_t pass_len, const uint8_t *in,
+                      size_t in_len);
+
+#define PKCS12_KEY_ID 1
+#define PKCS12_IV_ID 2
+#define PKCS12_MAC_ID 3
+
+/* pkcs12_key_gen runs the PKCS#12 key derivation function as specified in
+ * RFC 7292, appendix B. On success, it writes the resulting |out_len| bytes of
+ * key material to |out| and returns one. Otherwise, it returns zero. |id|
+ * should be one of the |PKCS12_*_ID| values. */
+int pkcs12_key_gen(const char *pass, size_t pass_len, const uint8_t *salt,
+                   size_t salt_len, uint8_t id, unsigned iterations,
+                   size_t out_len, uint8_t *out, const EVP_MD *md);
+
+struct pbe_suite {
+  int pbe_nid;
+  uint8_t oid[10];
+  uint8_t oid_len;
+  const EVP_CIPHER *(*cipher_func)(void);
+  const EVP_MD *(*md_func)(void);
+  /* decrypt_init initialize |ctx| for decrypting. The password is specified by
+   * |pass| and |pass_len|. |param| contains the serialized parameters field of
+   * the AlgorithmIdentifier.
+   *
+   * It returns one on success and zero on error. */
+  int (*decrypt_init)(const struct pbe_suite *suite, EVP_CIPHER_CTX *ctx,
+                      const char *pass, size_t pass_len, CBS *param);
+};
+
 #define PKCS5_DEFAULT_ITERATIONS 2048
 #define PKCS5_SALT_LEN 8
 
-/* PKCS5_v2_PBE_keyivgen intializes the supplied |ctx| for PBKDF v2, which must
- * be specified by |param|. The password is specified by |pass_raw| and
- * |pass_raw_len|. |cipher| and |md| are ignored.
- *
- * It returns one on success and zero on error. */
-int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const uint8_t *pass_raw,
-                          size_t pass_raw_len, ASN1_TYPE *param,
-                          const EVP_CIPHER *cipher, const EVP_MD *md, int enc);
+int PKCS5_pbe2_decrypt_init(const struct pbe_suite *suite, EVP_CIPHER_CTX *ctx,
+                            const char *pass, size_t pass_len, CBS *param);
+
+/* PKCS5_pbe2_encrypt_init configures |ctx| for encrypting with PKCS #5 PBES2,
+ * as defined in RFC 2998, with the specified parameters. It writes the
+ * corresponding AlgorithmIdentifier to |out|. */
+int PKCS5_pbe2_encrypt_init(CBB *out, EVP_CIPHER_CTX *ctx,
+                            const EVP_CIPHER *cipher, unsigned iterations,
+                            const char *pass, size_t pass_len,
+                            const uint8_t *salt, size_t salt_len);
 
 
 #if defined(__cplusplus)
diff --git a/src/crypto/pkcs8/p5_pbe.c b/src/crypto/pkcs8/p5_pbe.c
deleted file mode 100644
index 653cabf..0000000
--- a/src/crypto/pkcs8/p5_pbe.c
+++ /dev/null
@@ -1,150 +0,0 @@
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
- */
-/* ====================================================================
- * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- *    software must display the following acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- *    endorse or promote products derived from this software without
- *    prior written permission. For written permission, please contact
- *    licensing@OpenSSL.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- *    nor may "OpenSSL" appear in their names without prior written
- *    permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- *    acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- *
- * This product includes cryptographic software written by Eric Young
- * (eay@cryptsoft.com).  This product includes software written by Tim
- * Hudson (tjh@cryptsoft.com). */
-
-#include <string.h>
-
-#include <openssl/asn1t.h>
-#include <openssl/err.h>
-#include <openssl/pkcs8.h>
-#include <openssl/rand.h>
-#include <openssl/x509.h>
-
-#include "internal.h"
-
-
-/* PKCS#5 password based encryption structure */
-
-ASN1_SEQUENCE(PBEPARAM) = {
-	ASN1_SIMPLE(PBEPARAM, salt, ASN1_OCTET_STRING),
-	ASN1_SIMPLE(PBEPARAM, iter, ASN1_INTEGER)
-} ASN1_SEQUENCE_END(PBEPARAM)
-
-IMPLEMENT_ASN1_FUNCTIONS(PBEPARAM)
-
-
-/* Set an algorithm identifier for a PKCS#5 PBE algorithm */
-
-int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter,
-				const unsigned char *salt, int saltlen)
-	{
-	PBEPARAM *pbe=NULL;
-	ASN1_STRING *pbe_str=NULL;
-	unsigned char *sstr;
-
-	pbe = PBEPARAM_new();
-	if (!pbe)
-		{
-		OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE);
-		goto err;
-		}
-	if(iter <= 0)
-		iter = PKCS5_DEFAULT_ITERATIONS;
-	if (!ASN1_INTEGER_set(pbe->iter, iter))
-		{
-		OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE);
-		goto err;
-		}
-	if (!saltlen)
-		saltlen = PKCS5_SALT_LEN;
-	if (!ASN1_STRING_set(pbe->salt, NULL, saltlen))
-		{
-		OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE);
-		goto err;
-		}
-	sstr = ASN1_STRING_data(pbe->salt);
-	if (salt)
-		memcpy(sstr, salt, saltlen);
-	else if (!RAND_bytes(sstr, saltlen))
-		goto err;
-
-	if(!ASN1_item_pack(pbe, ASN1_ITEM_rptr(PBEPARAM), &pbe_str))
-		{
-		OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE);
-		goto err;
-		}
-
-	PBEPARAM_free(pbe);
-	pbe = NULL;
-
-	if (X509_ALGOR_set0(algor, OBJ_nid2obj(alg), V_ASN1_SEQUENCE, pbe_str))
-		return 1;
-
-err:
-	if (pbe != NULL)
-		PBEPARAM_free(pbe);
-	if (pbe_str != NULL)
-		ASN1_STRING_free(pbe_str);
-	return 0;
-	}
-
-/* Return an algorithm identifier for a PKCS#5 PBE algorithm */
-
-X509_ALGOR *PKCS5_pbe_set(int alg, int iter,
-				const unsigned char *salt, int saltlen)
-	{
-	X509_ALGOR *ret;
-	ret = X509_ALGOR_new();
-	if (!ret)
-		{
-		OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE);
-		return NULL;
-		}
-
-	if (PKCS5_pbe_set0_algor(ret, alg, iter, salt, saltlen)) 
-		return ret;
-
-	X509_ALGOR_free(ret);
-	return NULL;
-	}
diff --git a/src/crypto/pkcs8/p5_pbev2.c b/src/crypto/pkcs8/p5_pbev2.c
index fec0d86..29d8929 100644
--- a/src/crypto/pkcs8/p5_pbev2.c
+++ b/src/crypto/pkcs8/p5_pbev2.c
@@ -53,388 +53,255 @@
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com). */
 
-#include <assert.h>
+#include <openssl/pkcs8.h>
+
 #include <limits.h>
 #include <string.h>
 
-#include <openssl/asn1t.h>
+#include <openssl/bytestring.h>
 #include <openssl/cipher.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
-#include <openssl/pkcs8.h>
+#include <openssl/nid.h>
 #include <openssl/rand.h>
-#include <openssl/x509.h>
 
 #include "internal.h"
+#include "../internal.h"
 
 
-/* PKCS#5 v2.0 password based encryption structures */
+/* 1.2.840.113549.1.5.12 */
+static const uint8_t kPBKDF2[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
+                                  0x0d, 0x01, 0x05, 0x0c};
 
-ASN1_SEQUENCE(PBE2PARAM) = {
-	ASN1_SIMPLE(PBE2PARAM, keyfunc, X509_ALGOR),
-	ASN1_SIMPLE(PBE2PARAM, encryption, X509_ALGOR)
-} ASN1_SEQUENCE_END(PBE2PARAM)
+/* 1.2.840.113549.1.5.13 */
+static const uint8_t kPBES2[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
+                                 0x0d, 0x01, 0x05, 0x0d};
 
-IMPLEMENT_ASN1_FUNCTIONS(PBE2PARAM)
+/* 1.2.840.113549.2.7 */
+static const uint8_t kHMACWithSHA1[] = {0x2a, 0x86, 0x48, 0x86,
+                                        0xf7, 0x0d, 0x02, 0x07};
 
-ASN1_SEQUENCE(PBKDF2PARAM) = {
-	ASN1_SIMPLE(PBKDF2PARAM, salt, ASN1_ANY),
-	ASN1_SIMPLE(PBKDF2PARAM, iter, ASN1_INTEGER),
-	ASN1_OPT(PBKDF2PARAM, keylength, ASN1_INTEGER),
-	ASN1_OPT(PBKDF2PARAM, prf, X509_ALGOR)
-} ASN1_SEQUENCE_END(PBKDF2PARAM)
+static const struct {
+  uint8_t oid[9];
+  uint8_t oid_len;
+  int nid;
+  const EVP_CIPHER *(*cipher_func)(void);
+} kCipherOIDs[] = {
+    /* 1.2.840.113549.3.2 */
+    {{0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x02},
+     8,
+     NID_rc2_cbc,
+     &EVP_rc2_cbc},
+    /* 1.2.840.113549.3.7 */
+    {{0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x03, 0x07},
+     8,
+     NID_des_ede3_cbc,
+     &EVP_des_ede3_cbc},
+    /* 2.16.840.1.101.3.4.1.2 */
+    {{0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x02},
+     9,
+     NID_aes_128_cbc,
+     &EVP_aes_128_cbc},
+    /* 2.16.840.1.101.3.4.1.22 */
+    {{0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x16},
+     9,
+     NID_aes_192_cbc,
+     &EVP_aes_192_cbc},
+    /* 2.16.840.1.101.3.4.1.42 */
+    {{0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x2a},
+     9,
+     NID_aes_256_cbc,
+     &EVP_aes_256_cbc},
+};
 
-IMPLEMENT_ASN1_FUNCTIONS(PBKDF2PARAM);
+static const EVP_CIPHER *cbs_to_cipher(const CBS *cbs) {
+  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kCipherOIDs); i++) {
+    if (CBS_mem_equal(cbs, kCipherOIDs[i].oid, kCipherOIDs[i].oid_len)) {
+      return kCipherOIDs[i].cipher_func();
+    }
+  }
 
-static int ASN1_TYPE_set_octetstring(ASN1_TYPE *a, unsigned char *data, int len)
-	{
-	ASN1_STRING *os;
-
-	if ((os=M_ASN1_OCTET_STRING_new()) == NULL) return(0);
-	if (!M_ASN1_OCTET_STRING_set(os,data,len))
-		{
-		M_ASN1_OCTET_STRING_free(os);
-		return 0;
-		}
-	ASN1_TYPE_set(a,V_ASN1_OCTET_STRING,os);
-	return(1);
-	}
-
-static int param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type)
-	{
-	unsigned iv_len;
-
-	iv_len = EVP_CIPHER_CTX_iv_length(c);
-	return ASN1_TYPE_set_octetstring(type, c->oiv, iv_len);
-	}
-
-/* Return an algorithm identifier for a PKCS#5 v2.0 PBE algorithm:
- * yes I know this is horrible!
- *
- * Extended version to allow application supplied PRF NID and IV. */
-
-X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
-				 unsigned char *salt, int saltlen,
-				 unsigned char *aiv, int prf_nid)
-{
-	X509_ALGOR *scheme = NULL, *kalg = NULL, *ret = NULL;
-	int alg_nid, keylen;
-	EVP_CIPHER_CTX ctx;
-	unsigned char iv[EVP_MAX_IV_LENGTH];
-	PBE2PARAM *pbe2 = NULL;
-	const ASN1_OBJECT *obj;
-
-	alg_nid = EVP_CIPHER_nid(cipher);
-	if(alg_nid == NID_undef) {
-		OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER);
-		goto err;
-	}
-	obj = OBJ_nid2obj(alg_nid);
-
-	if(!(pbe2 = PBE2PARAM_new())) goto merr;
-
-	/* Setup the AlgorithmIdentifier for the encryption scheme */
-	scheme = pbe2->encryption;
-
-	scheme->algorithm = (ASN1_OBJECT*) obj;
-	if(!(scheme->parameter = ASN1_TYPE_new())) goto merr;
-
-	/* Create random IV */
-	if (EVP_CIPHER_iv_length(cipher))
-		{
-		if (aiv)
-			memcpy(iv, aiv, EVP_CIPHER_iv_length(cipher));
-		else if (!RAND_bytes(iv, EVP_CIPHER_iv_length(cipher)))
-  			goto err;
-		}
-
-	EVP_CIPHER_CTX_init(&ctx);
-
-	/* Dummy cipherinit to just setup the IV, and PRF */
-	if (!EVP_CipherInit_ex(&ctx, cipher, NULL, NULL, iv, 0))
-		goto err;
-	if(param_to_asn1(&ctx, scheme->parameter) < 0) {
-		OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_ERROR_SETTING_CIPHER_PARAMS);
-		EVP_CIPHER_CTX_cleanup(&ctx);
-		goto err;
-	}
-	/* If prf NID unspecified see if cipher has a preference.
-	 * An error is OK here: just means use default PRF.
-	 */
-	if ((prf_nid == -1) && 
-	EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_PBE_PRF_NID, 0, &prf_nid) <= 0)
-		{
-		ERR_clear_error();
-		prf_nid = NID_hmacWithSHA1;
-		}
-	EVP_CIPHER_CTX_cleanup(&ctx);
-
-	/* If its RC2 then we'd better setup the key length */
-
-	if(alg_nid == NID_rc2_cbc)
-		keylen = EVP_CIPHER_key_length(cipher);
-	else
-		keylen = -1;
-
-	/* Setup keyfunc */
-
-	X509_ALGOR_free(pbe2->keyfunc);
-
-	pbe2->keyfunc = PKCS5_pbkdf2_set(iter, salt, saltlen, prf_nid, keylen);
-
-	if (!pbe2->keyfunc)
-		goto merr;
-
-	/* Now set up top level AlgorithmIdentifier */
-
-	if(!(ret = X509_ALGOR_new())) goto merr;
-	if(!(ret->parameter = ASN1_TYPE_new())) goto merr;
-
-	ret->algorithm = (ASN1_OBJECT*) OBJ_nid2obj(NID_pbes2);
-
-	/* Encode PBE2PARAM into parameter */
-
-	if(!ASN1_item_pack(pbe2, ASN1_ITEM_rptr(PBE2PARAM),
-				 &ret->parameter->value.sequence)) goto merr;
-	ret->parameter->type = V_ASN1_SEQUENCE;
-
-	PBE2PARAM_free(pbe2);
-	pbe2 = NULL;
-
-	return ret;
-
-	merr:
-	OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE);
-
-	err:
-	PBE2PARAM_free(pbe2);
-	/* Note 'scheme' is freed as part of pbe2 */
-	X509_ALGOR_free(kalg);
-	X509_ALGOR_free(ret);
-
-	return NULL;
-
+  return NULL;
 }
 
-X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter,
-				 unsigned char *salt, int saltlen)
-	{
-	return PKCS5_pbe2_set_iv(cipher, iter, salt, saltlen, NULL, -1);
-	}
-
-X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen,
-				int prf_nid, int keylen)
-	{
-	X509_ALGOR *keyfunc = NULL;
-	PBKDF2PARAM *kdf = NULL;
-	ASN1_OCTET_STRING *osalt = NULL;
-
-	if(!(kdf = PBKDF2PARAM_new()))
-		goto merr;
-	if(!(osalt = M_ASN1_OCTET_STRING_new()))
-		goto merr;
-
-	kdf->salt->value.octet_string = osalt;
-	kdf->salt->type = V_ASN1_OCTET_STRING;
-
-	if (!saltlen)
-		saltlen = PKCS5_SALT_LEN;
-	if (!(osalt->data = OPENSSL_malloc (saltlen)))
-		goto merr;
-
-	osalt->length = saltlen;
-
-	if (salt)
-		memcpy (osalt->data, salt, saltlen);
-	else if (!RAND_bytes(osalt->data, saltlen))
-		goto merr;
-
-	if(iter <= 0)
-		iter = PKCS5_DEFAULT_ITERATIONS;
-
-	if(!ASN1_INTEGER_set(kdf->iter, iter))
-		goto merr;
-
-	/* If have a key len set it up */
-
-	if(keylen > 0) 
-		{
-		if(!(kdf->keylength = M_ASN1_INTEGER_new()))
-			goto merr;
-		if(!ASN1_INTEGER_set (kdf->keylength, keylen))
-			goto merr;
-		}
-
-	/* prf can stay NULL if we are using hmacWithSHA1 */
-	if (prf_nid > 0 && prf_nid != NID_hmacWithSHA1)
-		{
-		kdf->prf = X509_ALGOR_new();
-		if (!kdf->prf)
-			goto merr;
-		X509_ALGOR_set0(kdf->prf, OBJ_nid2obj(prf_nid),
-					V_ASN1_NULL, NULL);
-		}
-
-	/* Finally setup the keyfunc structure */
-
-	keyfunc = X509_ALGOR_new();
-	if (!keyfunc)
-		goto merr;
-
-	keyfunc->algorithm = (ASN1_OBJECT*) OBJ_nid2obj(NID_id_pbkdf2);
-
-	/* Encode PBKDF2PARAM into parameter of pbe2 */
-
-	if(!(keyfunc->parameter = ASN1_TYPE_new()))
-		goto merr;
-
-	if(!ASN1_item_pack(kdf, ASN1_ITEM_rptr(PBKDF2PARAM),
-			 &keyfunc->parameter->value.sequence))
-		goto merr;
-	keyfunc->parameter->type = V_ASN1_SEQUENCE;
-
-	PBKDF2PARAM_free(kdf);
-	return keyfunc;
-
-	merr:
-	OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE);
-	PBKDF2PARAM_free(kdf);
-	X509_ALGOR_free(keyfunc);
-	return NULL;
-	}
-
-static int PKCS5_v2_PBKDF2_keyivgen(EVP_CIPHER_CTX *ctx,
-                                    const uint8_t *pass_raw,
-                                    size_t pass_raw_len, const ASN1_TYPE *param,
-                                    const ASN1_TYPE *iv, int enc) {
-  int rv = 0;
-  PBKDF2PARAM *pbkdf2param = NULL;
-
-  if (EVP_CIPHER_CTX_cipher(ctx) == NULL) {
-    OPENSSL_PUT_ERROR(PKCS8, CIPHER_R_NO_CIPHER_SET);
-    goto err;
+static int add_cipher_oid(CBB *out, int nid) {
+  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kCipherOIDs); i++) {
+    if (kCipherOIDs[i].nid == nid) {
+      CBB child;
+      return CBB_add_asn1(out, &child, CBS_ASN1_OBJECT) &&
+             CBB_add_bytes(&child, kCipherOIDs[i].oid,
+                           kCipherOIDs[i].oid_len) &&
+             CBB_flush(out);
+    }
   }
 
-  /* Decode parameters. */
-  if (param == NULL || param->type != V_ASN1_SEQUENCE) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
-    goto err;
+  OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_CIPHER);
+  return 0;
+}
+
+static int pkcs5_pbe2_cipher_init(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
+                                  unsigned iterations, const char *pass,
+                                  size_t pass_len, const uint8_t *salt,
+                                  size_t salt_len, const uint8_t *iv,
+                                  size_t iv_len, int enc) {
+  if (iv_len != EVP_CIPHER_iv_length(cipher)) {
+    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_ERROR_SETTING_CIPHER_PARAMS);
+    return 0;
   }
 
-  const uint8_t *pbuf = param->value.sequence->data;
-  int plen = param->value.sequence->length;
-  pbkdf2param = d2i_PBKDF2PARAM(NULL, &pbuf, plen);
-  if (pbkdf2param == NULL || pbuf != param->value.sequence->data + plen) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
-    goto err;
-  }
-
-  /* Now check the parameters. */
   uint8_t key[EVP_MAX_KEY_LENGTH];
-  const size_t key_len = EVP_CIPHER_CTX_key_length(ctx);
-  assert(key_len <= sizeof(key));
-
-  if (pbkdf2param->keylength != NULL &&
-      ASN1_INTEGER_get(pbkdf2param->keylength) != (int) key_len) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_KEYLENGTH);
-    goto err;
-  }
-
-  if (pbkdf2param->prf != NULL &&
-      OBJ_obj2nid(pbkdf2param->prf->algorithm) != NID_hmacWithSHA1) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_PRF);
-    goto err;
-  }
-
-  if (pbkdf2param->salt->type != V_ASN1_OCTET_STRING) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_SALT_TYPE);
-    goto err;
-  }
-
-  if (pbkdf2param->iter->type != V_ASN1_INTEGER) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_ITERATION_COUNT);
-    goto err;
-  }
-  long iterations = ASN1_INTEGER_get(pbkdf2param->iter);
-  if (iterations <= 0 ||
-      (sizeof(long) > sizeof(unsigned) && iterations > (long)UINT_MAX)) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_ITERATION_COUNT);
-    goto err;
-  }
-
-  if (iv->type != V_ASN1_OCTET_STRING || iv->value.octet_string == NULL) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_ERROR_SETTING_CIPHER_PARAMS);
-    goto err;
-  }
-
-  const size_t iv_len = EVP_CIPHER_CTX_iv_length(ctx);
-  if ((size_t) iv->value.octet_string->length != iv_len) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_ERROR_SETTING_CIPHER_PARAMS);
-    goto err;
-  }
-
-  if (!PKCS5_PBKDF2_HMAC_SHA1((const char *) pass_raw, pass_raw_len,
-                              pbkdf2param->salt->value.octet_string->data,
-                              pbkdf2param->salt->value.octet_string->length,
-                              iterations, key_len, key)) {
-    goto err;
-  }
-
-  rv = EVP_CipherInit_ex(ctx, NULL /* cipher */, NULL /* engine */, key,
-                         iv->value.octet_string->data, enc);
-
- err:
-  PBKDF2PARAM_free(pbkdf2param);
-  return rv;
+  int ret = PKCS5_PBKDF2_HMAC_SHA1(pass, pass_len, salt, salt_len, iterations,
+                                   EVP_CIPHER_key_length(cipher), key) &&
+            EVP_CipherInit_ex(ctx, cipher, NULL /* engine */, key, iv, enc);
+  OPENSSL_cleanse(key, EVP_MAX_KEY_LENGTH);
+  return ret;
 }
 
-int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const uint8_t *pass_raw,
-                          size_t pass_raw_len, ASN1_TYPE *param,
-                          const EVP_CIPHER *unused, const EVP_MD *unused2,
-                          int enc) {
-  PBE2PARAM *pbe2param = NULL;
-  int rv = 0;
-
-  if (param == NULL ||
-      param->type != V_ASN1_SEQUENCE ||
-      param->value.sequence == NULL) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
-    goto err;
+int PKCS5_pbe2_encrypt_init(CBB *out, EVP_CIPHER_CTX *ctx,
+                            const EVP_CIPHER *cipher, unsigned iterations,
+                            const char *pass, size_t pass_len,
+                            const uint8_t *salt, size_t salt_len) {
+  int cipher_nid = EVP_CIPHER_nid(cipher);
+  if (cipher_nid == NID_undef) {
+    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER);
+    return 0;
   }
 
-  const uint8_t *pbuf = param->value.sequence->data;
-  int plen = param->value.sequence->length;
-  pbe2param = d2i_PBE2PARAM(NULL, &pbuf, plen);
-  if (pbe2param == NULL || pbuf != param->value.sequence->data + plen) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
-    goto err;
+  /* Generate a random IV. */
+  uint8_t iv[EVP_MAX_IV_LENGTH];
+  if (!RAND_bytes(iv, EVP_CIPHER_iv_length(cipher))) {
+    return 0;
   }
 
-  /* Check that the key derivation function is PBKDF2. */
-  if (OBJ_obj2nid(pbe2param->keyfunc->algorithm) != NID_id_pbkdf2) {
+  /* See RFC 2898, appendix A. */
+  CBB algorithm, oid, param, kdf, kdf_oid, kdf_param, salt_cbb, cipher_cbb,
+      iv_cbb;
+  if (!CBB_add_asn1(out, &algorithm, CBS_ASN1_SEQUENCE) ||
+      !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
+      !CBB_add_bytes(&oid, kPBES2, sizeof(kPBES2)) ||
+      !CBB_add_asn1(&algorithm, &param, CBS_ASN1_SEQUENCE) ||
+      !CBB_add_asn1(&param, &kdf, CBS_ASN1_SEQUENCE) ||
+      !CBB_add_asn1(&kdf, &kdf_oid, CBS_ASN1_OBJECT) ||
+      !CBB_add_bytes(&kdf_oid, kPBKDF2, sizeof(kPBKDF2)) ||
+      !CBB_add_asn1(&kdf, &kdf_param, CBS_ASN1_SEQUENCE) ||
+      !CBB_add_asn1(&kdf_param, &salt_cbb, CBS_ASN1_OCTETSTRING) ||
+      !CBB_add_bytes(&salt_cbb, salt, salt_len) ||
+      !CBB_add_asn1_uint64(&kdf_param, iterations) ||
+      /* Specify a key length for RC2. */
+      (cipher_nid == NID_rc2_cbc &&
+       !CBB_add_asn1_uint64(&kdf_param, EVP_CIPHER_key_length(cipher))) ||
+      /* Omit the PRF. We use the default hmacWithSHA1. */
+      !CBB_add_asn1(&param, &cipher_cbb, CBS_ASN1_SEQUENCE) ||
+      !add_cipher_oid(&cipher_cbb, cipher_nid) ||
+      /* RFC 2898 says RC2-CBC and RC5-CBC-Pad use a SEQUENCE with version and
+       * IV, but OpenSSL always uses an OCTET STRING IV, so we do the same. */
+      !CBB_add_asn1(&cipher_cbb, &iv_cbb, CBS_ASN1_OCTETSTRING) ||
+      !CBB_add_bytes(&iv_cbb, iv, EVP_CIPHER_iv_length(cipher)) ||
+      !CBB_flush(out)) {
+    return 0;
+  }
+
+  return pkcs5_pbe2_cipher_init(ctx, cipher, iterations, pass, pass_len, salt,
+                                salt_len, iv, EVP_CIPHER_iv_length(cipher),
+                                1 /* encrypt */);
+}
+
+int PKCS5_pbe2_decrypt_init(const struct pbe_suite *suite, EVP_CIPHER_CTX *ctx,
+                            const char *pass, size_t pass_len, CBS *param) {
+  CBS pbe_param, kdf, kdf_obj, enc_scheme, enc_obj;
+  if (!CBS_get_asn1(param, &pbe_param, CBS_ASN1_SEQUENCE) ||
+      CBS_len(param) != 0 ||
+      !CBS_get_asn1(&pbe_param, &kdf, CBS_ASN1_SEQUENCE) ||
+      !CBS_get_asn1(&pbe_param, &enc_scheme, CBS_ASN1_SEQUENCE) ||
+      CBS_len(&pbe_param) != 0 ||
+      !CBS_get_asn1(&kdf, &kdf_obj, CBS_ASN1_OBJECT) ||
+      !CBS_get_asn1(&enc_scheme, &enc_obj, CBS_ASN1_OBJECT)) {
+    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
+    return 0;
+  }
+
+  /* Only PBKDF2 is supported. */
+  if (!CBS_mem_equal(&kdf_obj, kPBKDF2, sizeof(kPBKDF2))) {
     OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_KEY_DERIVATION_FUNCTION);
-    goto err;
+    return 0;
   }
 
   /* See if we recognise the encryption algorithm. */
-  const EVP_CIPHER *cipher =
-      EVP_get_cipherbynid(OBJ_obj2nid(pbe2param->encryption->algorithm));
+  const EVP_CIPHER *cipher = cbs_to_cipher(&enc_obj);
   if (cipher == NULL) {
     OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_CIPHER);
-    goto err;
+    return 0;
   }
 
-  /* Fixup cipher based on AlgorithmIdentifier. */
-  if (!EVP_CipherInit_ex(ctx, cipher, NULL /* engine */, NULL /* key */,
-                         NULL /* iv */, enc)) {
-    goto err;
+  /* Parse the KDF parameters. See RFC 8018, appendix A.2. */
+  CBS pbkdf2_params, salt;
+  uint64_t iterations;
+  if (!CBS_get_asn1(&kdf, &pbkdf2_params, CBS_ASN1_SEQUENCE) ||
+      CBS_len(&kdf) != 0 ||
+      !CBS_get_asn1(&pbkdf2_params, &salt, CBS_ASN1_OCTETSTRING) ||
+      !CBS_get_asn1_uint64(&pbkdf2_params, &iterations)) {
+    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
+    return 0;
   }
 
-  rv = PKCS5_v2_PBKDF2_keyivgen(ctx, pass_raw, pass_raw_len,
-                                pbe2param->keyfunc->parameter,
-                                pbe2param->encryption->parameter, enc);
+  if (iterations == 0 || iterations > UINT_MAX) {
+    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_ITERATION_COUNT);
+    return 0;
+  }
 
- err:
-  PBE2PARAM_free(pbe2param);
-  return rv;
+  /* The optional keyLength parameter, if present, must match the key length of
+   * the cipher. */
+  if (CBS_peek_asn1_tag(&pbkdf2_params, CBS_ASN1_INTEGER)) {
+    uint64_t key_len;
+    if (!CBS_get_asn1_uint64(&pbkdf2_params, &key_len)) {
+      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
+      return 0;
+    }
+
+    if (key_len != EVP_CIPHER_key_length(cipher)) {
+      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_KEYLENGTH);
+      return 0;
+    }
+  }
+
+  if (CBS_len(&pbkdf2_params) != 0) {
+    CBS alg_id, prf;
+    if (!CBS_get_asn1(&pbkdf2_params, &alg_id, CBS_ASN1_SEQUENCE) ||
+        !CBS_get_asn1(&alg_id, &prf, CBS_ASN1_OBJECT) ||
+        CBS_len(&pbkdf2_params) != 0) {
+      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
+      return 0;
+    }
+
+    /* We only support hmacWithSHA1. It is the DEFAULT, so DER requires it be
+     * omitted, but we match OpenSSL in tolerating it being present. */
+    if (!CBS_mem_equal(&prf, kHMACWithSHA1, sizeof(kHMACWithSHA1))) {
+      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_PRF);
+      return 0;
+    }
+
+    /* hmacWithSHA1 has a NULL parameter. */
+    CBS null;
+    if (!CBS_get_asn1(&alg_id, &null, CBS_ASN1_NULL) ||
+        CBS_len(&null) != 0 ||
+        CBS_len(&alg_id) != 0) {
+      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
+      return 0;
+    }
+  }
+
+  /* Parse the encryption scheme parameters. Note OpenSSL does not match the
+   * specification. Per RFC 2898, this should depend on the encryption scheme.
+   * In particular, RC2-CBC uses a SEQUENCE with version and IV. We align with
+   * OpenSSL. */
+  CBS iv;
+  if (!CBS_get_asn1(&enc_scheme, &iv, CBS_ASN1_OCTETSTRING) ||
+      CBS_len(&enc_scheme) != 0) {
+    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_PRF);
+    return 0;
+  }
+
+  return pkcs5_pbe2_cipher_init(ctx, cipher, (unsigned)iterations, pass,
+                                pass_len, CBS_data(&salt), CBS_len(&salt),
+                                CBS_data(&iv), CBS_len(&iv), 0 /* decrypt */);
 }
diff --git a/src/crypto/pkcs8/pkcs12_test.cc b/src/crypto/pkcs8/pkcs12_test.cc
index 55006b4..ba02761 100644
--- a/src/crypto/pkcs8/pkcs12_test.cc
+++ b/src/crypto/pkcs8/pkcs12_test.cc
@@ -23,8 +23,6 @@
 #include <openssl/stack.h>
 #include <openssl/x509.h>
 
-#include "../test/scoped_types.h"
-
 
 /* kPKCS12DER contains sample PKCS#12 data generated by OpenSSL with:
  * openssl pkcs12 -export -inkey key.pem -in cacert.pem */
@@ -681,10 +679,229 @@
     0xfe, 0x3a, 0x66, 0x47, 0x40, 0x49, 0x02, 0x02, 0x07, 0xd0,
 };
 
+/* kPBES2 is a PKCS#12 file using PBES2 created with:
+ * openssl pkcs12 -export -inkey key.pem -in cert.pem -keypbe AES-128-CBC \
+ * -certpbe AES-128-CBC */
+static const uint8_t kPBES2[] = {
+  0x30, 0x82, 0x0a, 0x03, 0x02, 0x01, 0x03, 0x30, 0x82, 0x09, 0xc9, 0x06,
+  0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x01, 0xa0, 0x82,
+  0x09, 0xba, 0x04, 0x82, 0x09, 0xb6, 0x30, 0x82, 0x09, 0xb2, 0x30, 0x82,
+  0x04, 0x34, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07,
+  0x06, 0xa0, 0x82, 0x04, 0x25, 0x30, 0x82, 0x04, 0x21, 0x02, 0x01, 0x00,
+  0x30, 0x82, 0x04, 0x1a, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+  0x01, 0x07, 0x01, 0x30, 0x49, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+  0x0d, 0x01, 0x05, 0x0d, 0x30, 0x3c, 0x30, 0x1b, 0x06, 0x09, 0x2a, 0x86,
+  0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0c, 0x30, 0x0e, 0x04, 0x08, 0xdb,
+  0x48, 0xe6, 0x98, 0x09, 0x8f, 0x6e, 0x2d, 0x02, 0x02, 0x08, 0x00, 0x30,
+  0x1d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x02,
+  0x04, 0x10, 0xee, 0xb3, 0x10, 0xe5, 0x21, 0x85, 0x03, 0x3e, 0x69, 0xad,
+  0xdf, 0x78, 0xa7, 0xd8, 0xac, 0xf1, 0x80, 0x82, 0x03, 0xc0, 0xcb, 0x58,
+  0x11, 0x28, 0x1d, 0xbc, 0x3c, 0x8c, 0xe7, 0x7b, 0x15, 0x67, 0x30, 0xf3,
+  0x2b, 0x94, 0x10, 0x8c, 0xbe, 0xfd, 0xaa, 0x11, 0xd7, 0x99, 0xee, 0x21,
+  0xb6, 0x1b, 0x4f, 0x53, 0xcb, 0x44, 0xff, 0x4f, 0xbf, 0xf6, 0x43, 0x3d,
+  0x12, 0xe6, 0x09, 0xe8, 0x05, 0xdd, 0x2f, 0xc5, 0x39, 0xde, 0x0c, 0x88,
+  0xe8, 0x4e, 0x89, 0x8f, 0x5f, 0xdf, 0x23, 0x50, 0xe6, 0xb7, 0xba, 0x1a,
+  0xdd, 0x1c, 0x63, 0x51, 0x0e, 0x71, 0xb7, 0xf7, 0x39, 0x3c, 0xd4, 0xe7,
+  0x52, 0x50, 0xc5, 0xd7, 0xbf, 0x65, 0x94, 0x72, 0x97, 0x2a, 0xb9, 0x68,
+  0xc2, 0xbd, 0x0c, 0x97, 0x02, 0x74, 0x23, 0x7f, 0x11, 0x6b, 0xea, 0xb4,
+  0xe4, 0x2f, 0xf0, 0x8b, 0x91, 0x5c, 0xdb, 0xae, 0x10, 0xbf, 0x89, 0xbc,
+  0x62, 0xef, 0x99, 0xbf, 0x07, 0x59, 0x58, 0x12, 0xef, 0xaf, 0xe6, 0xcd,
+  0x30, 0x27, 0xe4, 0xab, 0x44, 0xf7, 0xf9, 0x14, 0xb2, 0x5d, 0xfa, 0x97,
+  0xe6, 0x9a, 0xed, 0x85, 0x60, 0x86, 0xd9, 0xb0, 0xd7, 0xa4, 0xe4, 0x00,
+  0xa8, 0xee, 0xbb, 0xfc, 0x0d, 0xe8, 0x58, 0x7a, 0xca, 0x02, 0x1d, 0x02,
+  0xab, 0xbd, 0x16, 0x50, 0x4f, 0xfc, 0x60, 0xde, 0x48, 0xb1, 0x7f, 0xea,
+  0xba, 0x45, 0x7b, 0x29, 0xfe, 0x8e, 0xed, 0x48, 0xd2, 0x31, 0x64, 0xda,
+  0x89, 0x84, 0x6f, 0xd1, 0xd2, 0xb1, 0x7b, 0x97, 0x19, 0x38, 0x16, 0xd9,
+  0x3f, 0xd6, 0xdb, 0x6f, 0xab, 0x56, 0x34, 0xca, 0x34, 0x9c, 0x57, 0x41,
+  0x6e, 0x87, 0x85, 0x2a, 0xa8, 0xfb, 0xe9, 0xf6, 0x3d, 0xb6, 0x83, 0x7b,
+  0x02, 0xc9, 0xbe, 0xf1, 0xbb, 0x8e, 0xe5, 0x68, 0xae, 0xaa, 0xe1, 0x25,
+  0x8d, 0x1f, 0x1f, 0x52, 0x45, 0x3e, 0xef, 0x33, 0xd8, 0x58, 0xd9, 0x48,
+  0xd4, 0xb5, 0xe1, 0x53, 0x21, 0xb5, 0xbd, 0xd4, 0x63, 0x1f, 0xbf, 0xe4,
+  0x30, 0x5e, 0xc3, 0x63, 0xce, 0xdc, 0x12, 0x8c, 0xc7, 0x0c, 0xea, 0x3b,
+  0xf3, 0x0b, 0x38, 0x8d, 0xcc, 0x9b, 0xe7, 0xa0, 0x14, 0x5e, 0x48, 0x9c,
+  0x74, 0x86, 0x8e, 0x2b, 0x77, 0x80, 0xbb, 0x85, 0xa6, 0xd4, 0x25, 0x6e,
+  0x75, 0x07, 0x59, 0xd6, 0x88, 0x00, 0x35, 0x03, 0x5a, 0xb0, 0x86, 0x7e,
+  0x01, 0xa7, 0x77, 0x74, 0x13, 0xfa, 0x9f, 0x2d, 0xe3, 0x90, 0xda, 0x68,
+  0x23, 0x36, 0x0b, 0x62, 0x21, 0x76, 0xda, 0x6c, 0x05, 0x35, 0x80, 0xfc,
+  0xee, 0x5f, 0x3c, 0xac, 0x60, 0x2a, 0x9c, 0x6e, 0x4c, 0xaa, 0xa3, 0xd1,
+  0xdf, 0x2c, 0x7e, 0x0e, 0xc0, 0xa0, 0x84, 0xe4, 0xb2, 0x33, 0x1f, 0x8c,
+  0xcb, 0x74, 0x31, 0x18, 0x5b, 0x0b, 0x18, 0x41, 0xc6, 0x87, 0x13, 0xa2,
+  0xad, 0x1d, 0x43, 0x5e, 0x67, 0xd0, 0x31, 0xf5, 0x61, 0x7c, 0x3d, 0x16,
+  0x55, 0x01, 0x94, 0x45, 0xa4, 0x50, 0x0f, 0xb1, 0x1b, 0x81, 0x51, 0xa7,
+  0x92, 0xae, 0xa3, 0x6d, 0x4e, 0x55, 0x46, 0x37, 0x98, 0xe1, 0xe4, 0x5c,
+  0x29, 0x79, 0xc9, 0x76, 0x0a, 0xb5, 0x9d, 0x1b, 0x8a, 0xf6, 0xab, 0xeb,
+  0x69, 0x6e, 0x17, 0x88, 0xeb, 0x82, 0xfa, 0x78, 0x2f, 0x8c, 0x30, 0xfd,
+  0xf1, 0x74, 0xcd, 0x53, 0x78, 0x27, 0x43, 0x82, 0x05, 0x37, 0x07, 0xb3,
+  0x4c, 0x89, 0x9d, 0x00, 0x1d, 0x73, 0xad, 0x0f, 0xcd, 0x63, 0xbe, 0x9b,
+  0xa9, 0x50, 0xa5, 0x43, 0x74, 0x86, 0x87, 0xbc, 0xd9, 0x97, 0x66, 0x84,
+  0x35, 0x3e, 0x67, 0xce, 0x92, 0x2c, 0x78, 0xc7, 0x88, 0x19, 0x6a, 0x1c,
+  0xa8, 0x93, 0x0b, 0x79, 0x21, 0xe5, 0x39, 0x1b, 0x00, 0x68, 0x2a, 0x0b,
+  0xac, 0x6a, 0x2f, 0xc1, 0x9c, 0x90, 0x18, 0x86, 0x63, 0x53, 0x72, 0x34,
+  0xd9, 0xa8, 0x92, 0xce, 0x64, 0x3a, 0xeb, 0xba, 0xd8, 0x31, 0xf3, 0xfb,
+  0x2a, 0xac, 0xc6, 0xe7, 0xd1, 0x0b, 0x7c, 0xfc, 0xbb, 0x69, 0x57, 0xc8,
+  0x97, 0x3d, 0xdb, 0x81, 0x77, 0x2a, 0x9f, 0x07, 0x2c, 0x79, 0x69, 0xbc,
+  0x51, 0x0e, 0x68, 0x11, 0x00, 0x10, 0xed, 0x9f, 0xb8, 0x8d, 0xa0, 0x25,
+  0x20, 0xd3, 0x3d, 0x08, 0x20, 0x46, 0xfa, 0x89, 0xef, 0x69, 0x4c, 0x60,
+  0x33, 0x80, 0xb9, 0x53, 0xb4, 0x7b, 0xab, 0x38, 0xf1, 0xcd, 0xb8, 0x75,
+  0xc4, 0x85, 0x0a, 0xda, 0xab, 0x19, 0x40, 0xd3, 0x88, 0xd5, 0xf7, 0x5f,
+  0x8e, 0xcd, 0x8e, 0xa4, 0x1c, 0x9c, 0x22, 0x6d, 0xce, 0x66, 0x29, 0xfa,
+  0x62, 0x6f, 0x01, 0xdc, 0x46, 0x45, 0x38, 0x64, 0xf7, 0xc4, 0x94, 0xfd,
+  0x48, 0x44, 0x70, 0x4d, 0xef, 0xf0, 0x4b, 0x95, 0xf8, 0x68, 0x8d, 0xb7,
+  0x35, 0x7d, 0xc6, 0xf5, 0x97, 0xce, 0x5d, 0xad, 0xe8, 0x5c, 0xeb, 0x4f,
+  0x9b, 0x5b, 0x03, 0xce, 0x33, 0x60, 0xf5, 0xce, 0xcc, 0xfe, 0xfb, 0x77,
+  0x40, 0xc4, 0xf4, 0x9d, 0xf3, 0x2c, 0xdb, 0x83, 0xc2, 0x1a, 0xf2, 0xb6,
+  0xbe, 0xfc, 0x2c, 0x7f, 0x29, 0x20, 0x35, 0x50, 0x00, 0x60, 0x03, 0xd2,
+  0xb3, 0x03, 0x18, 0x64, 0xb9, 0x64, 0x98, 0x33, 0xdb, 0x47, 0x43, 0xe2,
+  0xa1, 0x85, 0x79, 0x9b, 0xb1, 0x0b, 0x0e, 0xbb, 0x14, 0x5f, 0xb9, 0x16,
+  0xb6, 0xc3, 0xf6, 0x5c, 0x01, 0xe3, 0xaa, 0x3f, 0x03, 0xad, 0x18, 0xeb,
+  0x0e, 0x3d, 0xa3, 0x1f, 0xcc, 0x4d, 0x48, 0x44, 0x7e, 0xda, 0xb9, 0x9d,
+  0x17, 0xe8, 0x92, 0x46, 0xea, 0xf5, 0x3e, 0x05, 0x4e, 0xa7, 0xb5, 0x94,
+  0x6d, 0x95, 0x42, 0xa7, 0x71, 0xfb, 0xc2, 0x45, 0xd6, 0xd2, 0x86, 0xd0,
+  0x79, 0x99, 0x1f, 0x96, 0x78, 0x22, 0xeb, 0x05, 0x26, 0xf2, 0xa1, 0x67,
+  0x67, 0x2b, 0xae, 0x1d, 0x28, 0x42, 0xd6, 0xbe, 0x08, 0xf6, 0xb7, 0x54,
+  0xc8, 0x82, 0xbf, 0x92, 0x0f, 0x2c, 0xba, 0x47, 0xe2, 0x01, 0x73, 0x2c,
+  0xd7, 0x34, 0x84, 0x2f, 0xb6, 0x41, 0x84, 0xeb, 0x7a, 0xb2, 0xf9, 0xdd,
+  0x31, 0xbe, 0x07, 0xb4, 0x88, 0x05, 0xd8, 0xe1, 0x79, 0x55, 0xe6, 0x4b,
+  0x8c, 0xdc, 0xd1, 0x76, 0x58, 0x72, 0x42, 0x28, 0xb3, 0x9f, 0xd0, 0x05,
+  0x37, 0x6b, 0x65, 0x74, 0xce, 0x0d, 0x01, 0xa9, 0x49, 0xc5, 0x90, 0xab,
+  0x90, 0x16, 0x2c, 0x9c, 0xba, 0xcb, 0x94, 0xc7, 0xfa, 0xe0, 0x39, 0x82,
+  0xa2, 0x88, 0xd6, 0x0c, 0xc4, 0x4d, 0xfe, 0xb4, 0xbc, 0x87, 0xe5, 0x63,
+  0x3b, 0x6b, 0xf0, 0xd1, 0x09, 0x39, 0x8f, 0x51, 0x4f, 0x32, 0xae, 0xed,
+  0x0c, 0xff, 0x79, 0x52, 0x19, 0xa9, 0x4e, 0x45, 0x11, 0xc3, 0x5f, 0xd6,
+  0x2b, 0x66, 0xe3, 0x9c, 0xbe, 0xbc, 0xda, 0x65, 0x25, 0xcd, 0xf5, 0x73,
+  0x45, 0x09, 0xf5, 0x5d, 0x6b, 0x83, 0x45, 0x28, 0x98, 0x2c, 0x58, 0x44,
+  0xca, 0x37, 0xeb, 0xc3, 0xc2, 0x10, 0x77, 0x14, 0x79, 0x9b, 0xd8, 0xb2,
+  0xbf, 0x45, 0xd5, 0x63, 0xe4, 0x37, 0x42, 0x7b, 0x2d, 0xe2, 0x49, 0xb3,
+  0x18, 0x8e, 0x86, 0x73, 0xf1, 0x59, 0x8a, 0xf2, 0x3c, 0x49, 0x12, 0x7b,
+  0xb1, 0x40, 0x8c, 0x8c, 0xac, 0x05, 0x50, 0xbd, 0x9b, 0x3b, 0x84, 0x81,
+  0x68, 0x26, 0x88, 0x1b, 0xbf, 0xa0, 0x28, 0xc2, 0x06, 0xa9, 0xe4, 0xd9,
+  0x1f, 0x5d, 0xca, 0x96, 0x4f, 0xfe, 0xd8, 0x64, 0xee, 0x73, 0x30, 0x82,
+  0x05, 0x76, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07,
+  0x01, 0xa0, 0x82, 0x05, 0x67, 0x04, 0x82, 0x05, 0x63, 0x30, 0x82, 0x05,
+  0x5f, 0x30, 0x82, 0x05, 0x5b, 0x06, 0x0b, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+  0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x02, 0xa0, 0x82, 0x05, 0x23, 0x30, 0x82,
+  0x05, 0x1f, 0x30, 0x49, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+  0x01, 0x05, 0x0d, 0x30, 0x3c, 0x30, 0x1b, 0x06, 0x09, 0x2a, 0x86, 0x48,
+  0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0c, 0x30, 0x0e, 0x04, 0x08, 0xe3, 0x3e,
+  0xd3, 0x8d, 0xd6, 0xb5, 0x8a, 0x05, 0x02, 0x02, 0x08, 0x00, 0x30, 0x1d,
+  0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x01, 0x02, 0x04,
+  0x10, 0x61, 0xa0, 0x2f, 0x8d, 0x0c, 0xa1, 0x03, 0xc9, 0xdf, 0x2e, 0x81,
+  0x65, 0xe0, 0x63, 0x70, 0x55, 0x04, 0x82, 0x04, 0xd0, 0x24, 0x1e, 0xf9,
+  0x1d, 0xc4, 0xe9, 0xbf, 0x49, 0x3c, 0x1e, 0x55, 0x4a, 0xd4, 0xb0, 0x0c,
+  0xdd, 0x5b, 0x92, 0xb2, 0xed, 0x18, 0xac, 0x66, 0x90, 0x1b, 0x29, 0x3d,
+  0x10, 0xad, 0x02, 0xe7, 0x17, 0x83, 0x44, 0x67, 0xba, 0x11, 0x6f, 0x05,
+  0xf5, 0xf7, 0x37, 0xcb, 0x5a, 0xe9, 0x0e, 0xc3, 0x4b, 0x1b, 0x62, 0xee,
+  0xb2, 0xb7, 0x14, 0x85, 0x07, 0x2d, 0x95, 0x83, 0xa9, 0xdc, 0x3d, 0x4b,
+  0x33, 0xad, 0x68, 0xbf, 0x54, 0xf8, 0xef, 0x25, 0x05, 0x40, 0xcd, 0x61,
+  0xbe, 0x12, 0xeb, 0x78, 0x75, 0x36, 0x08, 0x8c, 0x5a, 0x57, 0xa1, 0x98,
+  0xd5, 0x42, 0x01, 0x1b, 0x4c, 0x25, 0xc2, 0x18, 0x9f, 0x91, 0xfe, 0x78,
+  0x88, 0x99, 0x47, 0x5a, 0x20, 0x2c, 0x37, 0x31, 0x05, 0x98, 0xef, 0x91,
+  0x6e, 0xeb, 0x2e, 0x86, 0x90, 0x61, 0xb1, 0x57, 0x1a, 0x05, 0x82, 0x14,
+  0x0c, 0xa8, 0x94, 0xae, 0x56, 0x7b, 0xd6, 0x2f, 0x8b, 0x2e, 0x91, 0xa6,
+  0x12, 0x68, 0x1f, 0x06, 0x09, 0x2f, 0xa6, 0xed, 0x33, 0x99, 0x72, 0x56,
+  0xe5, 0xf7, 0xea, 0xcc, 0xcf, 0x27, 0xa5, 0xad, 0x49, 0x5a, 0xbc, 0x7b,
+  0xe3, 0x62, 0x63, 0x8f, 0x00, 0x2b, 0x96, 0xc5, 0x3f, 0xaf, 0x24, 0xba,
+  0xf6, 0x8d, 0xe2, 0xef, 0x18, 0x50, 0xd6, 0xd8, 0x4f, 0xb2, 0x5d, 0xb7,
+  0x96, 0x6f, 0x02, 0xf7, 0x7d, 0xf2, 0xa2, 0x7b, 0x9b, 0x13, 0x98, 0xde,
+  0xdd, 0x6e, 0xb5, 0x48, 0x52, 0x8e, 0x44, 0xad, 0xe0, 0xcf, 0x40, 0x9f,
+  0xfd, 0x88, 0x33, 0x66, 0xce, 0x6a, 0x49, 0x5f, 0xe7, 0x4b, 0x36, 0x93,
+  0x7f, 0x49, 0x62, 0xc9, 0x5a, 0xae, 0xa1, 0xca, 0xf7, 0x5a, 0xbe, 0x85,
+  0x77, 0x9a, 0x8f, 0xce, 0x4d, 0x84, 0x81, 0xd0, 0xa2, 0xee, 0x60, 0x92,
+  0x86, 0x16, 0x2a, 0xd5, 0x08, 0xb6, 0x58, 0x63, 0x07, 0x7c, 0x41, 0xac,
+  0x97, 0x4f, 0xf0, 0xcf, 0xd8, 0xd2, 0xb1, 0xd7, 0x1d, 0xe5, 0xb8, 0x7c,
+  0x04, 0x2b, 0xd9, 0xee, 0xf7, 0x22, 0x88, 0xa1, 0x53, 0xdb, 0x5e, 0x5b,
+  0x47, 0x49, 0xeb, 0xcf, 0x04, 0x78, 0x69, 0xd1, 0xfc, 0x8a, 0xa9, 0x61,
+  0x92, 0xbf, 0x5c, 0x7f, 0xde, 0x49, 0x42, 0xfc, 0x0d, 0xc2, 0xa2, 0x8f,
+  0xba, 0xdf, 0x12, 0xa4, 0x62, 0xfb, 0x8d, 0xd3, 0xc5, 0xf9, 0x85, 0x4c,
+  0x17, 0x70, 0xb7, 0xf7, 0x99, 0x29, 0x52, 0x92, 0x36, 0xc5, 0x4b, 0x31,
+  0x23, 0x5c, 0x09, 0x27, 0x3c, 0xa0, 0x76, 0x5d, 0x92, 0x99, 0x63, 0x88,
+  0xca, 0xad, 0xed, 0xd7, 0x85, 0x98, 0x2f, 0xbe, 0xaa, 0xa5, 0xf3, 0x0a,
+  0x76, 0x13, 0x01, 0x90, 0x8a, 0xe7, 0x5a, 0x2d, 0x2b, 0x1a, 0x80, 0x33,
+  0x86, 0xab, 0xd8, 0xa7, 0xae, 0x0b, 0x7d, 0xcd, 0x64, 0x8d, 0xa6, 0xb6,
+  0xfb, 0x83, 0x9f, 0x91, 0x23, 0xcb, 0xda, 0x63, 0xd0, 0xde, 0xf4, 0xdd,
+  0xaa, 0x23, 0x49, 0x6c, 0x44, 0xfa, 0x6f, 0x12, 0x13, 0x90, 0x37, 0xde,
+  0xa3, 0x72, 0x45, 0x1a, 0xa7, 0xab, 0x01, 0x6d, 0xd6, 0x34, 0xe7, 0x51,
+  0x0e, 0x33, 0xbc, 0x09, 0xbf, 0xb6, 0x16, 0xf8, 0xd3, 0x11, 0x11, 0xd1,
+  0x5f, 0xaa, 0x32, 0xb6, 0x5b, 0xe7, 0xbc, 0xdd, 0xaa, 0xe4, 0xed, 0x42,
+  0x3d, 0x2e, 0xf7, 0xa1, 0x06, 0x39, 0xd4, 0x00, 0xc6, 0xc8, 0xed, 0xb5,
+  0x96, 0xc1, 0xbf, 0x4c, 0xf1, 0xf6, 0xc6, 0x59, 0xf4, 0x99, 0x9c, 0x10,
+  0x22, 0xa1, 0x3a, 0xcd, 0x94, 0xac, 0x0b, 0xc8, 0x7e, 0x29, 0xbc, 0xf0,
+  0xae, 0x27, 0x7a, 0xb8, 0x5c, 0xa0, 0x13, 0x36, 0xb5, 0x19, 0x4b, 0x2c,
+  0xc1, 0xce, 0x49, 0x57, 0x1d, 0x36, 0xf0, 0xc2, 0x4c, 0xdf, 0x6d, 0xc9,
+  0x64, 0x68, 0xcb, 0xea, 0x22, 0x32, 0xd7, 0x11, 0x2c, 0x77, 0xbe, 0x01,
+  0xa3, 0x82, 0x2d, 0xa1, 0x4b, 0x13, 0x93, 0x87, 0x3d, 0x01, 0x74, 0xc6,
+  0xc6, 0xf9, 0xae, 0x2e, 0xa1, 0x44, 0x5d, 0x47, 0x6c, 0x6f, 0xc6, 0xce,
+  0xef, 0x32, 0xf8, 0x8d, 0x53, 0x4d, 0xa5, 0xf0, 0xa0, 0x51, 0x7e, 0xd8,
+  0x35, 0x55, 0x2a, 0x04, 0xb9, 0x42, 0xa7, 0x51, 0xba, 0xad, 0xce, 0x88,
+  0x7b, 0x93, 0x25, 0x9d, 0x03, 0x08, 0xfa, 0x75, 0x38, 0x63, 0x78, 0x13,
+  0x11, 0x9d, 0xf6, 0xcc, 0x18, 0xe3, 0x99, 0xa9, 0x5d, 0x90, 0x6b, 0xbf,
+  0x9c, 0x69, 0x99, 0x63, 0x27, 0x35, 0x8a, 0x26, 0x07, 0x67, 0xd1, 0xae,
+  0x57, 0xec, 0xc0, 0x45, 0x6e, 0x2a, 0x42, 0x46, 0x8f, 0xe4, 0x84, 0xc7,
+  0x67, 0x06, 0x0c, 0xa7, 0x7e, 0x5c, 0x20, 0x80, 0xdc, 0xc1, 0xe4, 0x7a,
+  0x74, 0x76, 0x8f, 0x41, 0x78, 0xce, 0x6a, 0xf9, 0xcb, 0x7f, 0xe9, 0x17,
+  0x70, 0x45, 0x01, 0x9a, 0xc3, 0x9c, 0xa2, 0x68, 0xa0, 0x79, 0xfd, 0x44,
+  0x4c, 0xc8, 0xa0, 0xaf, 0xa5, 0xba, 0x0f, 0x03, 0x30, 0x43, 0x4a, 0x1d,
+  0x3e, 0xd4, 0x8e, 0x1f, 0x6d, 0x09, 0xf9, 0x63, 0xde, 0xd2, 0x9e, 0x77,
+  0xe7, 0xde, 0x61, 0x52, 0x76, 0x0f, 0x6d, 0x37, 0xf7, 0xc2, 0x69, 0x96,
+  0x9d, 0xc5, 0xd9, 0x15, 0x10, 0xf2, 0x22, 0x1f, 0x3b, 0x83, 0xb3, 0xb4,
+  0x2c, 0x25, 0x36, 0xc3, 0x3a, 0x24, 0x17, 0xed, 0xad, 0x11, 0x1f, 0x46,
+  0x31, 0x0c, 0x6a, 0x3c, 0xd2, 0x1a, 0xe7, 0x41, 0xb3, 0x75, 0xd8, 0x80,
+  0xb3, 0xf8, 0x2b, 0xab, 0xb5, 0x81, 0xc6, 0x5e, 0x40, 0x9a, 0x77, 0xaa,
+  0x79, 0x31, 0x1f, 0x79, 0xfe, 0x0f, 0x0f, 0xb0, 0x36, 0xb7, 0xdc, 0xca,
+  0xf6, 0xbf, 0x80, 0xeb, 0x78, 0xc6, 0x73, 0x6a, 0xb3, 0x71, 0x69, 0x9c,
+  0x1d, 0xdd, 0x90, 0xd9, 0x73, 0x07, 0x43, 0x37, 0x19, 0x7f, 0x22, 0xa4,
+  0x9a, 0x4d, 0x98, 0x66, 0x10, 0x5b, 0x08, 0x62, 0xb3, 0xd8, 0x2f, 0x56,
+  0x68, 0x22, 0xdf, 0xd1, 0xa2, 0x5a, 0x45, 0xf9, 0xb4, 0xb9, 0xf2, 0x48,
+  0x4e, 0x38, 0x1a, 0x23, 0x36, 0x6d, 0x42, 0x56, 0xbb, 0x32, 0xe3, 0x00,
+  0x84, 0xa9, 0xe2, 0xba, 0xb6, 0x86, 0xc9, 0xa6, 0x64, 0x8a, 0xd6, 0xa6,
+  0xc4, 0xd7, 0x3e, 0x8b, 0x34, 0x1b, 0x6b, 0x65, 0xfe, 0xb1, 0xc9, 0x93,
+  0xe1, 0xeb, 0x8a, 0x3b, 0xf1, 0x0f, 0xdb, 0x84, 0xe2, 0x2d, 0xf8, 0x69,
+  0x04, 0xee, 0xaf, 0x58, 0x2f, 0xc7, 0x96, 0x70, 0x4d, 0xd9, 0x4c, 0x1d,
+  0x52, 0x38, 0xc6, 0x26, 0x27, 0x41, 0x38, 0x0b, 0xa5, 0x1c, 0x16, 0xd0,
+  0x1d, 0x32, 0x99, 0xb9, 0x1f, 0x35, 0xaf, 0x02, 0xb0, 0x13, 0x0f, 0x95,
+  0xd3, 0x9b, 0xd6, 0x09, 0xcc, 0x29, 0x46, 0xe8, 0xf1, 0x54, 0x4d, 0xb8,
+  0x96, 0xa6, 0x0d, 0x59, 0x61, 0x1f, 0xee, 0xaf, 0xbc, 0x23, 0x58, 0xff,
+  0xcf, 0x96, 0x91, 0x1f, 0x00, 0x80, 0x4e, 0x9a, 0xa2, 0xe0, 0x00, 0xf7,
+  0x3e, 0xb1, 0x91, 0x6c, 0x29, 0x58, 0x5e, 0xe7, 0xc7, 0x23, 0xfa, 0x88,
+  0xf7, 0xfb, 0x0b, 0x0e, 0x4a, 0x04, 0x46, 0xe0, 0x67, 0x10, 0x09, 0xea,
+  0xc0, 0xa9, 0xbe, 0x83, 0x11, 0x33, 0x8e, 0xfb, 0xd6, 0xd5, 0x67, 0xef,
+  0xb4, 0x13, 0x4d, 0x17, 0xa1, 0x44, 0xb7, 0x98, 0x77, 0xd0, 0x63, 0xe7,
+  0x9c, 0xa7, 0x96, 0x29, 0xe5, 0xfe, 0x72, 0x4c, 0xa9, 0x85, 0x9b, 0xc9,
+  0xf3, 0xf6, 0x05, 0x0a, 0x28, 0x68, 0x99, 0x31, 0xe8, 0x64, 0x30, 0x9c,
+  0x2a, 0x90, 0x48, 0x84, 0x00, 0x1a, 0x66, 0x0e, 0x3e, 0xf7, 0xaa, 0xc9,
+  0x6c, 0x5b, 0x57, 0x7b, 0xa9, 0x17, 0x91, 0x1e, 0x6b, 0xe8, 0x12, 0xa1,
+  0xd4, 0xde, 0x1e, 0x38, 0x14, 0x7b, 0xe0, 0x9a, 0x15, 0xae, 0x5a, 0x26,
+  0x93, 0x7a, 0xd6, 0x8d, 0x26, 0x61, 0x28, 0xf2, 0x40, 0x71, 0xc7, 0x8a,
+  0x2d, 0x69, 0x72, 0x04, 0x5b, 0xb9, 0xc1, 0x7b, 0x17, 0xde, 0x2c, 0xfc,
+  0xa9, 0xf2, 0xf8, 0x34, 0x33, 0x09, 0x87, 0x91, 0xdf, 0xeb, 0xf7, 0x57,
+  0x5b, 0x32, 0xe2, 0xd4, 0xe4, 0x47, 0x78, 0xe8, 0x9b, 0x1a, 0xab, 0x44,
+  0x55, 0x28, 0x98, 0x20, 0xa7, 0x16, 0x8b, 0x4e, 0x42, 0xf1, 0x91, 0xbe,
+  0x00, 0x87, 0x3a, 0x91, 0x63, 0x9a, 0xc2, 0x8d, 0x13, 0x34, 0x8b, 0x33,
+  0x02, 0x88, 0x1e, 0xb1, 0xa8, 0x07, 0x6d, 0xb1, 0xf5, 0xb3, 0x7a, 0x3d,
+  0x17, 0x3f, 0xbd, 0xa1, 0xdb, 0x04, 0x0f, 0x29, 0x7b, 0x0e, 0x98, 0x18,
+  0x63, 0x0b, 0x60, 0xcd, 0xa5, 0x0d, 0x5f, 0x1e, 0x53, 0xcd, 0xfa, 0xc0,
+  0xc7, 0x99, 0x53, 0x5f, 0xb7, 0xe5, 0x4a, 0x30, 0xde, 0x14, 0xc9, 0x49,
+  0x46, 0x31, 0xb6, 0x92, 0xf3, 0x4b, 0xc1, 0xb0, 0xdd, 0xec, 0x48, 0xff,
+  0x2d, 0x52, 0x53, 0x64, 0x27, 0x4c, 0x78, 0x96, 0x80, 0x90, 0xa3, 0xd7,
+  0xfd, 0x7a, 0x23, 0x36, 0xa0, 0x76, 0x9e, 0x96, 0xfc, 0xcd, 0xec, 0x58,
+  0xf8, 0x76, 0x4b, 0x2f, 0x8d, 0xb9, 0xd6, 0x89, 0xa1, 0x57, 0xe1, 0xc6,
+  0xed, 0x9a, 0x1e, 0xde, 0xc7, 0x68, 0x93, 0x2b, 0x2e, 0x84, 0x1a, 0xf9,
+  0x8c, 0x58, 0xb8, 0xf0, 0x29, 0xfe, 0x7b, 0x03, 0x84, 0xe8, 0x52, 0x1c,
+  0x01, 0xbb, 0xcc, 0x5d, 0x88, 0xcd, 0x37, 0x8b, 0xe2, 0x2d, 0x30, 0xd1,
+  0xbe, 0xf7, 0xc1, 0x95, 0xb7, 0x01, 0x43, 0xab, 0x30, 0x3f, 0x96, 0x47,
+  0x6d, 0x52, 0x29, 0x87, 0x10, 0x31, 0x25, 0x30, 0x23, 0x06, 0x09, 0x2a,
+  0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x15, 0x31, 0x16, 0x04, 0x14,
+  0x14, 0x74, 0x2d, 0x52, 0x8e, 0x0d, 0x0c, 0x06, 0x6c, 0x32, 0x64, 0xd3,
+  0x7e, 0x33, 0x31, 0x68, 0x8b, 0x28, 0x1a, 0x75, 0x30, 0x31, 0x30, 0x21,
+  0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04,
+  0x14, 0x2f, 0x5c, 0xc6, 0xaf, 0xa7, 0xcc, 0xb5, 0x77, 0x40, 0xca, 0x71,
+  0xc3, 0x8c, 0xc6, 0x69, 0xdc, 0xc6, 0x7f, 0x54, 0xef, 0x04, 0x08, 0xf8,
+  0x9c, 0x8b, 0x12, 0x27, 0xe8, 0xec, 0x65, 0x02, 0x02, 0x08, 0x00};
+
 static const char kPassword[] = "foo";
 
 static bool Test(const char *name, const uint8_t *der, size_t der_len) {
-  ScopedX509Stack certs(sk_X509_new_null());
+  bssl::UniquePtr<STACK_OF(X509)> certs(sk_X509_new_null());
   if (!certs) {
     return false;
   }
@@ -697,7 +914,7 @@
     ERR_print_errors_fp(stderr);
     return false;
   }
-  ScopedEVP_PKEY delete_key(key);
+  bssl::UniquePtr<EVP_PKEY> delete_key(key);
 
   if (sk_X509_num(certs.get()) != 1 || key == nullptr) {
     fprintf(stderr, "Bad result from %s data.\n", name);
@@ -708,12 +925,12 @@
 }
 
 static bool TestCompat(const uint8_t *der, size_t der_len) {
-  ScopedBIO bio(BIO_new_mem_buf((void*) der, der_len));
+  bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(der, der_len));
   if (!bio) {
     return false;
   }
 
-  ScopedPKCS12 p12(d2i_PKCS12_bio(bio.get(), nullptr));
+  bssl::UniquePtr<PKCS12> p12(d2i_PKCS12_bio(bio.get(), nullptr));
   if (!p12) {
     fprintf(stderr, "PKCS12_parse failed.\n");
     ERR_print_errors_fp(stderr);
@@ -738,9 +955,9 @@
     ERR_print_errors_fp(stderr);
     return false;
   }
-  ScopedEVP_PKEY delete_key(key);
-  ScopedX509 delete_cert(cert);
-  ScopedX509Stack delete_ca_certs(ca_certs);
+  bssl::UniquePtr<EVP_PKEY> delete_key(key);
+  bssl::UniquePtr<X509> delete_cert(cert);
+  bssl::UniquePtr<STACK_OF(X509)> delete_ca_certs(ca_certs);
 
   if (key == nullptr || cert == nullptr) {
     fprintf(stderr, "Bad result from PKCS12_parse.\n");
@@ -757,11 +974,11 @@
 
 int main(int argc, char **argv) {
   CRYPTO_library_init();
-  ERR_load_crypto_strings();
 
   if (!Test("OpenSSL", kOpenSSL, sizeof(kOpenSSL)) ||
       !Test("NSS", kNSS, sizeof(kNSS)) ||
       !Test("Windows", kWindows, sizeof(kWindows)) ||
+      !Test("PBES2", kPBES2, sizeof(kPBES2)) ||
       !TestCompat(kWindows, sizeof(kWindows))) {
     return 1;
   }
diff --git a/src/crypto/pkcs8/pkcs8.c b/src/crypto/pkcs8/pkcs8.c
index 31a34a7..08cc5a3 100644
--- a/src/crypto/pkcs8/pkcs8.c
+++ b/src/crypto/pkcs8/pkcs8.c
@@ -59,44 +59,36 @@
 #include <limits.h>
 #include <string.h>
 
-#include <openssl/asn1.h>
-#include <openssl/bn.h>
-#include <openssl/buf.h>
+#include <openssl/bytestring.h>
 #include <openssl/cipher.h>
 #include <openssl/digest.h>
 #include <openssl/err.h>
-#include <openssl/hmac.h>
 #include <openssl/mem.h>
-#include <openssl/x509.h>
+#include <openssl/nid.h>
+#include <openssl/rand.h>
 
 #include "internal.h"
-#include "../bytestring/internal.h"
-#include "../evp/internal.h"
+#include "../internal.h"
 
 
-#define PKCS12_KEY_ID 1
-#define PKCS12_IV_ID 2
-#define PKCS12_MAC_ID 3
-
 static int ascii_to_ucs2(const char *ascii, size_t ascii_len,
                          uint8_t **out, size_t *out_len) {
-  uint8_t *unitmp;
-  size_t ulen, i;
+  size_t ulen = ascii_len * 2 + 2;
+  if (ascii_len * 2 < ascii_len || ulen < ascii_len * 2) {
+    return 0;
+  }
 
-  ulen = ascii_len * 2 + 2;
-  if (ulen < ascii_len) {
-    return 0;
-  }
-  unitmp = OPENSSL_malloc(ulen);
+  uint8_t *unitmp = OPENSSL_malloc(ulen);
   if (unitmp == NULL) {
+    OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE);
     return 0;
   }
-  for (i = 0; i < ulen - 2; i += 2) {
+  for (size_t i = 0; i < ulen - 2; i += 2) {
     unitmp[i] = 0;
     unitmp[i + 1] = ascii[i >> 1];
   }
 
-  /* Make result double null terminated */
+  /* Terminate the result with a UCS-2 NUL. */
   unitmp[ulen - 2] = 0;
   unitmp[ulen - 1] = 0;
   *out_len = ulen;
@@ -104,203 +96,225 @@
   return 1;
 }
 
-static int pkcs12_key_gen_raw(const uint8_t *pass_raw, size_t pass_raw_len,
-                              const uint8_t *salt, size_t salt_len,
-                              int id, int iterations,
-                              size_t out_len, uint8_t *out,
-                              const EVP_MD *md_type) {
-  uint8_t *B, *D, *I, *p, *Ai;
-  int Slen, Plen, Ilen, Ijlen;
-  int i, j, v;
-  size_t u;
-  int ret = 0;
-  BIGNUM *Ij, *Bpl1; /* These hold Ij and B + 1 */
-  EVP_MD_CTX ctx;
+int pkcs12_key_gen(const char *pass, size_t pass_len, const uint8_t *salt,
+                   size_t salt_len, uint8_t id, unsigned iterations,
+                   size_t out_len, uint8_t *out, const EVP_MD *md) {
+  /* See https://tools.ietf.org/html/rfc7292#appendix-B. Quoted parts of the
+   * specification have errata applied and other typos fixed. */
 
-  EVP_MD_CTX_init(&ctx);
-  v = EVP_MD_block_size(md_type);
-  u = EVP_MD_size(md_type);
-  D = OPENSSL_malloc(v);
-  Ai = OPENSSL_malloc(u);
-  B = OPENSSL_malloc(v + 1);
-  Slen = v * ((salt_len + v - 1) / v);
-  if (pass_raw_len) {
-    Plen = v * ((pass_raw_len + v - 1) / v);
-  } else {
-    Plen = 0;
+  if (iterations < 1) {
+    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_ITERATION_COUNT);
+    return 0;
   }
-  Ilen = Slen + Plen;
-  I = OPENSSL_malloc(Ilen);
-  Ij = BN_new();
-  Bpl1 = BN_new();
-  if (!D || !Ai || !B || !I || !Ij || !Bpl1) {
+
+  int ret = 0;
+  EVP_MD_CTX ctx;
+  EVP_MD_CTX_init(&ctx);
+  uint8_t *pass_raw = NULL, *I = NULL;
+  size_t pass_raw_len = 0, I_len = 0;
+  /* If |pass| is NULL, we use the empty string rather than {0, 0} as the raw
+   * password. */
+  if (pass != NULL &&
+      !ascii_to_ucs2(pass, pass_len, &pass_raw, &pass_raw_len)) {
     goto err;
   }
-  for (i = 0; i < v; i++) {
-    D[i] = id;
+
+  /* In the spec, |block_size| is called "v", but measured in bits. */
+  size_t block_size = EVP_MD_block_size(md);
+
+  /* 1. Construct a string, D (the "diversifier"), by concatenating v/8 copies
+   * of ID. */
+  uint8_t D[EVP_MAX_MD_BLOCK_SIZE];
+  OPENSSL_memset(D, id, block_size);
+
+  /* 2. Concatenate copies of the salt together to create a string S of length
+   * v(ceiling(s/v)) bits (the final copy of the salt may be truncated to
+   * create S). Note that if the salt is the empty string, then so is S.
+   *
+   * 3. Concatenate copies of the password together to create a string P of
+   * length v(ceiling(p/v)) bits (the final copy of the password may be
+   * truncated to create P).  Note that if the password is the empty string,
+   * then so is P.
+   *
+   * 4. Set I=S||P to be the concatenation of S and P. */
+  if (salt_len + block_size - 1 < salt_len ||
+      pass_raw_len + block_size - 1 < pass_raw_len) {
+    OPENSSL_PUT_ERROR(PKCS8, ERR_R_OVERFLOW);
+    goto err;
   }
-  p = I;
-  for (i = 0; i < Slen; i++) {
-    *p++ = salt[i % salt_len];
+  size_t S_len = block_size * ((salt_len + block_size - 1) / block_size);
+  size_t P_len = block_size * ((pass_raw_len + block_size - 1) / block_size);
+  I_len = S_len + P_len;
+  if (I_len < S_len) {
+    OPENSSL_PUT_ERROR(PKCS8, ERR_R_OVERFLOW);
+    goto err;
   }
-  for (i = 0; i < Plen; i++) {
-    *p++ = pass_raw[i % pass_raw_len];
+
+  I = OPENSSL_malloc(I_len);
+  if (I_len != 0 && I == NULL) {
+    OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE);
+    goto err;
   }
-  for (;;) {
-    if (!EVP_DigestInit_ex(&ctx, md_type, NULL) ||
-        !EVP_DigestUpdate(&ctx, D, v) ||
-        !EVP_DigestUpdate(&ctx, I, Ilen) ||
-        !EVP_DigestFinal_ex(&ctx, Ai, NULL)) {
+
+  for (size_t i = 0; i < S_len; i++) {
+    I[i] = salt[i % salt_len];
+  }
+  for (size_t i = 0; i < P_len; i++) {
+    I[i + S_len] = pass_raw[i % pass_raw_len];
+  }
+
+  while (out_len != 0) {
+    /* A. Set A_i=H^r(D||I). (i.e., the r-th hash of D||I,
+     * H(H(H(... H(D||I)))) */
+    uint8_t A[EVP_MAX_MD_SIZE];
+    unsigned A_len;
+    if (!EVP_DigestInit_ex(&ctx, md, NULL) ||
+        !EVP_DigestUpdate(&ctx, D, block_size) ||
+        !EVP_DigestUpdate(&ctx, I, I_len) ||
+        !EVP_DigestFinal_ex(&ctx, A, &A_len)) {
       goto err;
     }
-    for (j = 1; j < iterations; j++) {
-      if (!EVP_DigestInit_ex(&ctx, md_type, NULL) ||
-          !EVP_DigestUpdate(&ctx, Ai, u) ||
-          !EVP_DigestFinal_ex(&ctx, Ai, NULL)) {
+    for (unsigned iter = 1; iter < iterations; iter++) {
+      if (!EVP_DigestInit_ex(&ctx, md, NULL) ||
+          !EVP_DigestUpdate(&ctx, A, A_len) ||
+          !EVP_DigestFinal_ex(&ctx, A, &A_len)) {
         goto err;
       }
     }
-    memcpy(out, Ai, out_len < u ? out_len : u);
-    if (u >= out_len) {
-      ret = 1;
-      goto end;
+
+    size_t todo = out_len < A_len ? out_len : A_len;
+    OPENSSL_memcpy(out, A, todo);
+    out += todo;
+    out_len -= todo;
+    if (out_len == 0) {
+      break;
     }
-    out_len -= u;
-    out += u;
-    for (j = 0; j < v; j++) {
-      B[j] = Ai[j % u];
+
+    /* B. Concatenate copies of A_i to create a string B of length v bits (the
+     * final copy of A_i may be truncated to create B). */
+    uint8_t B[EVP_MAX_MD_BLOCK_SIZE];
+    for (size_t i = 0; i < block_size; i++) {
+      B[i] = A[i % A_len];
     }
-    /* Work out B + 1 first then can use B as tmp space */
-    if (!BN_bin2bn(B, v, Bpl1) ||
-        !BN_add_word(Bpl1, 1)) {
-      goto err;
-    }
-    for (j = 0; j < Ilen; j += v) {
-      if (!BN_bin2bn(I + j, v, Ij) ||
-          !BN_add(Ij, Ij, Bpl1) ||
-          !BN_bn2bin(Ij, B)) {
-        goto err;
-      }
-      Ijlen = BN_num_bytes(Ij);
-      /* If more than 2^(v*8) - 1 cut off MSB */
-      if (Ijlen > v) {
-        if (!BN_bn2bin(Ij, B)) {
-          goto err;
-        }
-        memcpy(I + j, B + 1, v);
-        /* If less than v bytes pad with zeroes */
-      } else if (Ijlen < v) {
-        memset(I + j, 0, v - Ijlen);
-        if (!BN_bn2bin(Ij, I + j + v - Ijlen)) {
-          goto err;
-        }
-      } else if (!BN_bn2bin(Ij, I + j)) {
-        goto err;
+
+    /* C. Treating I as a concatenation I_0, I_1, ..., I_(k-1) of v-bit blocks,
+     * where k=ceiling(s/v)+ceiling(p/v), modify I by setting I_j=(I_j+B+1) mod
+     * 2^v for each j. */
+    assert(I_len % block_size == 0);
+    for (size_t i = 0; i < I_len; i += block_size) {
+      unsigned carry = 1;
+      for (size_t j = block_size - 1; j < block_size; j--) {
+        carry += I[i + j] + B[j];
+        I[i + j] = (uint8_t)carry;
+        carry >>= 8;
       }
     }
   }
 
+  ret = 1;
+
 err:
-  OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE);
-
-end:
-  OPENSSL_free(Ai);
-  OPENSSL_free(B);
-  OPENSSL_free(D);
-  OPENSSL_free(I);
-  BN_free(Ij);
-  BN_free(Bpl1);
+  if (I != NULL) {
+    OPENSSL_cleanse(I, I_len);
+    OPENSSL_free(I);
+  }
+  if (pass_raw != NULL) {
+    OPENSSL_cleanse(pass_raw, pass_raw_len);
+    OPENSSL_free(pass_raw);
+  }
   EVP_MD_CTX_cleanup(&ctx);
-
   return ret;
 }
 
-static int pkcs12_pbe_keyivgen(EVP_CIPHER_CTX *ctx, const uint8_t *pass_raw,
-                               size_t pass_raw_len, ASN1_TYPE *param,
-                               const EVP_CIPHER *cipher, const EVP_MD *md,
-                               int is_encrypt) {
-  PBEPARAM *pbe;
-  int salt_len, iterations, ret;
-  uint8_t *salt;
-  const uint8_t *pbuf;
-  uint8_t key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
+static int pkcs12_pbe_cipher_init(const struct pbe_suite *suite,
+                                  EVP_CIPHER_CTX *ctx, unsigned iterations,
+                                  const char *pass, size_t pass_len,
+                                  const uint8_t *salt, size_t salt_len,
+                                  int is_encrypt) {
+  const EVP_CIPHER *cipher = suite->cipher_func();
+  const EVP_MD *md = suite->md_func();
 
-  /* Extract useful info from parameter */
-  if (param == NULL || param->type != V_ASN1_SEQUENCE ||
-      param->value.sequence == NULL) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
-    return 0;
-  }
-
-  pbuf = param->value.sequence->data;
-  pbe = d2i_PBEPARAM(NULL, &pbuf, param->value.sequence->length);
-  if (pbe == NULL) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
-    return 0;
-  }
-
-  if (!pbe->iter) {
-    iterations = 1;
-  } else {
-    iterations = ASN1_INTEGER_get(pbe->iter);
-  }
-  salt = pbe->salt->data;
-  salt_len = pbe->salt->length;
-  if (!pkcs12_key_gen_raw(pass_raw, pass_raw_len, salt, salt_len, PKCS12_KEY_ID,
-                          iterations, EVP_CIPHER_key_length(cipher), key, md)) {
+  uint8_t key[EVP_MAX_KEY_LENGTH];
+  uint8_t iv[EVP_MAX_IV_LENGTH];
+  if (!pkcs12_key_gen(pass, pass_len, salt, salt_len, PKCS12_KEY_ID, iterations,
+                      EVP_CIPHER_key_length(cipher), key, md) ||
+      !pkcs12_key_gen(pass, pass_len, salt, salt_len, PKCS12_IV_ID, iterations,
+                      EVP_CIPHER_iv_length(cipher), iv, md)) {
     OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_KEY_GEN_ERROR);
-    PBEPARAM_free(pbe);
     return 0;
   }
-  if (!pkcs12_key_gen_raw(pass_raw, pass_raw_len, salt, salt_len, PKCS12_IV_ID,
-                          iterations, EVP_CIPHER_iv_length(cipher), iv, md)) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_KEY_GEN_ERROR);
-    PBEPARAM_free(pbe);
-    return 0;
-  }
-  PBEPARAM_free(pbe);
-  ret = EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, is_encrypt);
+
+  int ret = EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, is_encrypt);
   OPENSSL_cleanse(key, EVP_MAX_KEY_LENGTH);
   OPENSSL_cleanse(iv, EVP_MAX_IV_LENGTH);
   return ret;
 }
 
-typedef int (*keygen_func)(EVP_CIPHER_CTX *ctx, const uint8_t *pass_raw,
-                           size_t pass_raw_len, ASN1_TYPE *param,
-                           const EVP_CIPHER *cipher, const EVP_MD *md,
-                           int is_encrypt);
+static int pkcs12_pbe_decrypt_init(const struct pbe_suite *suite,
+                                   EVP_CIPHER_CTX *ctx, const char *pass,
+                                   size_t pass_len, CBS *param) {
+  CBS pbe_param, salt;
+  uint64_t iterations;
+  if (!CBS_get_asn1(param, &pbe_param, CBS_ASN1_SEQUENCE) ||
+      !CBS_get_asn1(&pbe_param, &salt, CBS_ASN1_OCTETSTRING) ||
+      !CBS_get_asn1_uint64(&pbe_param, &iterations) ||
+      CBS_len(&pbe_param) != 0 ||
+      CBS_len(param) != 0) {
+    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
+    return 0;
+  }
 
-struct pbe_suite {
-  int pbe_nid;
-  const EVP_CIPHER* (*cipher_func)(void);
-  const EVP_MD* (*md_func)(void);
-  keygen_func keygen;
-  int flags;
-};
+  if (iterations == 0 || iterations > UINT_MAX) {
+    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_ITERATION_COUNT);
+    return 0;
+  }
 
-#define PBE_UCS2_CONVERT_PASSWORD 0x1
+  return pkcs12_pbe_cipher_init(suite, ctx, (unsigned)iterations, pass,
+                                pass_len, CBS_data(&salt), CBS_len(&salt),
+                                0 /* decrypt */);
+}
 
 static const struct pbe_suite kBuiltinPBE[] = {
     {
-     NID_pbe_WithSHA1And40BitRC2_CBC, EVP_rc2_40_cbc, EVP_sha1,
-     pkcs12_pbe_keyivgen, PBE_UCS2_CONVERT_PASSWORD
+        NID_pbe_WithSHA1And40BitRC2_CBC,
+        /* 1.2.840.113549.1.12.1.6 */
+        {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x06},
+        10,
+        EVP_rc2_40_cbc,
+        EVP_sha1,
+        pkcs12_pbe_decrypt_init,
     },
     {
-     NID_pbe_WithSHA1And128BitRC4, EVP_rc4, EVP_sha1, pkcs12_pbe_keyivgen,
-     PBE_UCS2_CONVERT_PASSWORD
+        NID_pbe_WithSHA1And128BitRC4,
+        /* 1.2.840.113549.1.12.1.1 */
+        {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x01},
+        10,
+        EVP_rc4,
+        EVP_sha1,
+        pkcs12_pbe_decrypt_init,
     },
     {
-     NID_pbe_WithSHA1And3_Key_TripleDES_CBC, EVP_des_ede3_cbc, EVP_sha1,
-     pkcs12_pbe_keyivgen, PBE_UCS2_CONVERT_PASSWORD
+        NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
+        /* 1.2.840.113549.1.12.1.3 */
+        {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x03},
+        10,
+        EVP_des_ede3_cbc,
+        EVP_sha1,
+        pkcs12_pbe_decrypt_init,
     },
     {
-      NID_pbes2, NULL, NULL,  PKCS5_v2_PBE_keyivgen, 0
+        NID_pbes2,
+        /* 1.2.840.113549.1.5.13 */
+        {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0d},
+        9,
+        NULL,
+        NULL,
+        PKCS5_pbe2_decrypt_init,
     },
 };
 
 static const struct pbe_suite *get_pbe_suite(int pbe_nid) {
-  unsigned i;
-  for (i = 0; i < sizeof(kBuiltinPBE) / sizeof(kBuiltinPBE[0]); i++) {
+  for (unsigned i = 0; i < OPENSSL_ARRAY_SIZE(kBuiltinPBE); i++) {
     if (kBuiltinPBE[i].pbe_nid == pbe_nid) {
       return &kBuiltinPBE[i];
     }
@@ -309,909 +323,201 @@
   return NULL;
 }
 
-/* pass_to_pass_raw performs a password conversion (possibly a no-op)
- * appropriate to the supplied |pbe_nid|. The input |pass| is treated as a
- * NUL-terminated string if |pass_len| is -1, otherwise it is treated as a
- * buffer of the specified length. If the supplied PBE NID sets the
- * |PBE_UCS2_CONVERT_PASSWORD| flag, the supplied |pass| will be converted to
- * UCS-2.
- *
- * It sets |*out_pass_raw| to a new buffer that must be freed by the caller. It
- * returns one on success and zero on error. */
-static int pass_to_pass_raw(int pbe_nid, const char *pass, int pass_len,
-                            uint8_t **out_pass_raw, size_t *out_pass_raw_len) {
-  if (pass == NULL) {
-    *out_pass_raw = NULL;
-    *out_pass_raw_len = 0;
-    return 1;
-  }
-
-  if (pass_len == -1) {
-    pass_len = strlen(pass);
-  } else if (pass_len < 0 || pass_len > 2000000000) {
-    OPENSSL_PUT_ERROR(PKCS8, ERR_R_OVERFLOW);
-    return 0;
-  }
-
-  const struct pbe_suite *suite = get_pbe_suite(pbe_nid);
-  if (suite != NULL && (suite->flags & PBE_UCS2_CONVERT_PASSWORD)) {
-    if (!ascii_to_ucs2(pass, pass_len, out_pass_raw, out_pass_raw_len)) {
-      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
-      return 0;
-    }
-  } else {
-    *out_pass_raw = BUF_memdup(pass, pass_len);
-    if (*out_pass_raw == NULL) {
-      OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE);
-      return 0;
-    }
-    *out_pass_raw_len = (size_t)pass_len;
-  }
-
-  return 1;
-}
-
-static int pbe_cipher_init(ASN1_OBJECT *pbe_obj,
-                           const uint8_t *pass_raw, size_t pass_raw_len,
-                           ASN1_TYPE *param,
-                           EVP_CIPHER_CTX *ctx, int is_encrypt) {
-  const EVP_CIPHER *cipher;
-  const EVP_MD *md;
-
-  const struct pbe_suite *suite = get_pbe_suite(OBJ_obj2nid(pbe_obj));
+static int pkcs12_pbe_encrypt_init(CBB *out, EVP_CIPHER_CTX *ctx, int alg,
+                                   unsigned iterations, const char *pass,
+                                   size_t pass_len, const uint8_t *salt,
+                                   size_t salt_len) {
+  const struct pbe_suite *suite = get_pbe_suite(alg);
   if (suite == NULL) {
-    char obj_str[80];
     OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNKNOWN_ALGORITHM);
-    if (!pbe_obj) {
-      strncpy(obj_str, "NULL", sizeof(obj_str));
-    } else {
-      i2t_ASN1_OBJECT(obj_str, sizeof(obj_str), pbe_obj);
-    }
-    ERR_add_error_data(2, "TYPE=", obj_str);
     return 0;
   }
 
-  if (suite->cipher_func == NULL) {
-    cipher = NULL;
-  } else {
-    cipher = suite->cipher_func();
-    if (!cipher) {
-      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNKNOWN_CIPHER);
-      return 0;
-    }
-  }
-
-  if (suite->md_func == NULL) {
-    md = NULL;
-  } else {
-    md = suite->md_func();
-    if (!md) {
-      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNKNOWN_DIGEST);
-      return 0;
-    }
-  }
-
-  if (!suite->keygen(ctx, pass_raw, pass_raw_len, param, cipher, md,
-                     is_encrypt)) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_KEYGEN_FAILURE);
+  /* See RFC 2898, appendix A.3. */
+  CBB algorithm, oid, param, salt_cbb;
+  if (!CBB_add_asn1(out, &algorithm, CBS_ASN1_SEQUENCE) ||
+      !CBB_add_asn1(&algorithm, &oid, CBS_ASN1_OBJECT) ||
+      !CBB_add_bytes(&oid, suite->oid, suite->oid_len) ||
+      !CBB_add_asn1(&algorithm, &param, CBS_ASN1_SEQUENCE) ||
+      !CBB_add_asn1(&param, &salt_cbb, CBS_ASN1_OCTETSTRING) ||
+      !CBB_add_bytes(&salt_cbb, salt, salt_len) ||
+      !CBB_add_asn1_uint64(&param, iterations) ||
+      !CBB_flush(out)) {
     return 0;
   }
 
-  return 1;
+  return pkcs12_pbe_cipher_init(suite, ctx, iterations, pass, pass_len, salt,
+                                salt_len, 1 /* encrypt */);
 }
 
-static int pbe_crypt(const X509_ALGOR *algor,
-                     const uint8_t *pass_raw, size_t pass_raw_len,
-                     const uint8_t *in, size_t in_len,
-                     uint8_t **out, size_t *out_len,
-                     int is_encrypt) {
-  uint8_t *buf;
-  int n, ret = 0;
+int pkcs8_pbe_decrypt(uint8_t **out, size_t *out_len, CBS *algorithm,
+                      const char *pass, size_t pass_len, const uint8_t *in,
+                      size_t in_len) {
+  int ret = 0;
+  uint8_t *buf = NULL;;
   EVP_CIPHER_CTX ctx;
-  unsigned block_size;
-
   EVP_CIPHER_CTX_init(&ctx);
 
-  if (!pbe_cipher_init(algor->algorithm, pass_raw, pass_raw_len,
-                       algor->parameter, &ctx, is_encrypt)) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNKNOWN_CIPHER_ALGORITHM);
-    return 0;
-  }
-  block_size = EVP_CIPHER_CTX_block_size(&ctx);
-
-  if (in_len + block_size < in_len) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_TOO_LONG);
+  CBS obj;
+  if (!CBS_get_asn1(algorithm, &obj, CBS_ASN1_OBJECT)) {
+    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
     goto err;
   }
 
-  buf = OPENSSL_malloc(in_len + block_size);
+  const struct pbe_suite *suite = NULL;
+  for (unsigned i = 0; i < OPENSSL_ARRAY_SIZE(kBuiltinPBE); i++) {
+    if (CBS_mem_equal(&obj, kBuiltinPBE[i].oid, kBuiltinPBE[i].oid_len)) {
+      suite = &kBuiltinPBE[i];
+      break;
+    }
+  }
+  if (suite == NULL) {
+    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNKNOWN_ALGORITHM);
+    goto err;
+  }
+
+  if (!suite->decrypt_init(suite, &ctx, pass, pass_len, algorithm)) {
+    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_KEYGEN_FAILURE);
+    goto err;
+  }
+
+  buf = OPENSSL_malloc(in_len);
   if (buf == NULL) {
     OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE);
     goto err;
   }
 
-  if (!EVP_CipherUpdate(&ctx, buf, &n, in, in_len)) {
-    OPENSSL_free(buf);
-    OPENSSL_PUT_ERROR(PKCS8, ERR_R_EVP_LIB);
+  if (in_len > INT_MAX) {
+    OPENSSL_PUT_ERROR(PKCS8, ERR_R_OVERFLOW);
     goto err;
   }
-  *out_len = n;
 
-  if (!EVP_CipherFinal_ex(&ctx, buf + n, &n)) {
-    OPENSSL_free(buf);
-    OPENSSL_PUT_ERROR(PKCS8, ERR_R_EVP_LIB);
+  int n1, n2;
+  if (!EVP_DecryptUpdate(&ctx, buf, &n1, in, (int)in_len) ||
+      !EVP_DecryptFinal_ex(&ctx, buf + n1, &n2)) {
     goto err;
   }
-  *out_len += n;
+
   *out = buf;
+  *out_len = n1 + n2;
   ret = 1;
+  buf = NULL;
 
 err:
+  OPENSSL_free(buf);
   EVP_CIPHER_CTX_cleanup(&ctx);
   return ret;
 }
 
-static void *pkcs12_item_decrypt_d2i(X509_ALGOR *algor, const ASN1_ITEM *it,
-                                     const uint8_t *pass_raw,
-                                     size_t pass_raw_len,
-                                     ASN1_OCTET_STRING *oct) {
-  uint8_t *out;
-  const uint8_t *p;
-  void *ret;
-  size_t out_len;
-
-  if (!pbe_crypt(algor, pass_raw, pass_raw_len, oct->data, oct->length,
-                 &out, &out_len, 0 /* decrypt */)) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_CRYPT_ERROR);
-    return NULL;
-  }
-  p = out;
-  ret = ASN1_item_d2i(NULL, &p, out_len, it);
-  OPENSSL_cleanse(out, out_len);
-  if (!ret) {
+EVP_PKEY *PKCS8_parse_encrypted_private_key(CBS *cbs, const char *pass,
+                                            size_t pass_len) {
+  /* See RFC 5208, section 6. */
+  CBS epki, algorithm, ciphertext;
+  if (!CBS_get_asn1(cbs, &epki, CBS_ASN1_SEQUENCE) ||
+      !CBS_get_asn1(&epki, &algorithm, CBS_ASN1_SEQUENCE) ||
+      !CBS_get_asn1(&epki, &ciphertext, CBS_ASN1_OCTETSTRING) ||
+      CBS_len(&epki) != 0) {
     OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
+    return 0;
   }
+
+  uint8_t *out;
+  size_t out_len;
+  if (!pkcs8_pbe_decrypt(&out, &out_len, &algorithm, pass, pass_len,
+                         CBS_data(&ciphertext), CBS_len(&ciphertext))) {
+    return 0;
+  }
+
+  CBS pki;
+  CBS_init(&pki, out, out_len);
+  EVP_PKEY *ret = EVP_parse_private_key(&pki);
+  OPENSSL_cleanse(out, out_len);
   OPENSSL_free(out);
   return ret;
 }
 
-PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(X509_SIG *pkcs8, const char *pass,
-                                   int pass_len) {
-  uint8_t *pass_raw = NULL;
-  size_t pass_raw_len = 0;
-  if (!pass_to_pass_raw(OBJ_obj2nid(pkcs8->algor->algorithm), pass, pass_len,
-                        &pass_raw, &pass_raw_len)) {
-    return NULL;
+int PKCS8_marshal_encrypted_private_key(CBB *out, int pbe_nid,
+                                        const EVP_CIPHER *cipher,
+                                        const char *pass, size_t pass_len,
+                                        const uint8_t *salt, size_t salt_len,
+                                        int iterations, const EVP_PKEY *pkey) {
+  int ret = 0;
+  uint8_t *plaintext = NULL, *salt_buf = NULL;
+  size_t plaintext_len = 0;
+  EVP_CIPHER_CTX ctx;
+  EVP_CIPHER_CTX_init(&ctx);
+
+  /* Generate a random salt if necessary. */
+  if (salt == NULL) {
+    if (salt_len == 0) {
+      salt_len = PKCS5_SALT_LEN;
+    }
+
+    salt_buf = OPENSSL_malloc(salt_len);
+    if (salt_buf == NULL ||
+        !RAND_bytes(salt_buf, salt_len)) {
+      goto err;
+    }
+
+    salt = salt_buf;
   }
 
-  PKCS8_PRIV_KEY_INFO *ret = PKCS8_decrypt_pbe(pkcs8, pass_raw, pass_raw_len);
-
-  if (pass_raw) {
-    OPENSSL_cleanse(pass_raw, pass_raw_len);
-    OPENSSL_free(pass_raw);
-  }
-  return ret;
-}
-
-PKCS8_PRIV_KEY_INFO *PKCS8_decrypt_pbe(X509_SIG *pkcs8, const uint8_t *pass_raw,
-                                       size_t pass_raw_len) {
-  return pkcs12_item_decrypt_d2i(pkcs8->algor,
-                                 ASN1_ITEM_rptr(PKCS8_PRIV_KEY_INFO), pass_raw,
-                                 pass_raw_len, pkcs8->digest);
-}
-
-static ASN1_OCTET_STRING *pkcs12_item_i2d_encrypt(X509_ALGOR *algor,
-                                                  const ASN1_ITEM *it,
-                                                  const uint8_t *pass_raw,
-                                                  size_t pass_raw_len, void *obj) {
-  ASN1_OCTET_STRING *oct;
-  uint8_t *in = NULL;
-  int in_len;
-  size_t crypt_len;
-
-  oct = M_ASN1_OCTET_STRING_new();
-  if (oct == NULL) {
-    OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE);
-    return NULL;
-  }
-  in_len = ASN1_item_i2d(obj, &in, it);
-  if (!in) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_ENCODE_ERROR);
-    return NULL;
-  }
-  if (!pbe_crypt(algor, pass_raw, pass_raw_len, in, in_len, &oct->data, &crypt_len,
-                 1 /* encrypt */)) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_ENCRYPT_ERROR);
-    OPENSSL_free(in);
-    return NULL;
-  }
-  oct->length = crypt_len;
-  OPENSSL_cleanse(in, in_len);
-  OPENSSL_free(in);
-  return oct;
-}
-
-X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher, const char *pass,
-                        int pass_len, uint8_t *salt, size_t salt_len,
-                        int iterations, PKCS8_PRIV_KEY_INFO *p8inf) {
-  uint8_t *pass_raw = NULL;
-  size_t pass_raw_len = 0;
-  if (!pass_to_pass_raw(pbe_nid, pass, pass_len, &pass_raw, &pass_raw_len)) {
-    return NULL;
+  if (iterations <= 0) {
+    iterations = PKCS5_DEFAULT_ITERATIONS;
   }
 
-  X509_SIG *ret = PKCS8_encrypt_pbe(pbe_nid, cipher, pass_raw, pass_raw_len,
-                                    salt, salt_len, iterations, p8inf);
-
-  if (pass_raw) {
-    OPENSSL_cleanse(pass_raw, pass_raw_len);
-    OPENSSL_free(pass_raw);
-  }
-  return ret;
-}
-
-X509_SIG *PKCS8_encrypt_pbe(int pbe_nid, const EVP_CIPHER *cipher,
-                            const uint8_t *pass_raw, size_t pass_raw_len,
-                            uint8_t *salt, size_t salt_len,
-                            int iterations, PKCS8_PRIV_KEY_INFO *p8inf) {
-  X509_SIG *pkcs8 = NULL;
-  X509_ALGOR *pbe;
-
-  pkcs8 = X509_SIG_new();
-  if (pkcs8 == NULL) {
-    OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE);
+  /* Serialize the input key. */
+  CBB plaintext_cbb;
+  if (!CBB_init(&plaintext_cbb, 128) ||
+      !EVP_marshal_private_key(&plaintext_cbb, pkey) ||
+      !CBB_finish(&plaintext_cbb, &plaintext, &plaintext_len)) {
+    CBB_cleanup(&plaintext_cbb);
     goto err;
   }
 
+  CBB epki;
+  if (!CBB_add_asn1(out, &epki, CBS_ASN1_SEQUENCE)) {
+    goto err;
+  }
+
+  int alg_ok;
   if (pbe_nid == -1) {
-    pbe = PKCS5_pbe2_set(cipher, iterations, salt, salt_len);
+    alg_ok = PKCS5_pbe2_encrypt_init(&epki, &ctx, cipher, (unsigned)iterations,
+                                     pass, pass_len, salt, salt_len);
   } else {
-    pbe = PKCS5_pbe_set(pbe_nid, iterations, salt, salt_len);
+    alg_ok = pkcs12_pbe_encrypt_init(&epki, &ctx, pbe_nid, (unsigned)iterations,
+                                     pass, pass_len, salt, salt_len);
   }
-  if (!pbe) {
-    OPENSSL_PUT_ERROR(PKCS8, ERR_R_ASN1_LIB);
+  if (!alg_ok) {
     goto err;
   }
 
-  X509_ALGOR_free(pkcs8->algor);
-  pkcs8->algor = pbe;
-  M_ASN1_OCTET_STRING_free(pkcs8->digest);
-  pkcs8->digest = pkcs12_item_i2d_encrypt(
-      pbe, ASN1_ITEM_rptr(PKCS8_PRIV_KEY_INFO), pass_raw, pass_raw_len, p8inf);
-  if (!pkcs8->digest) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_ENCRYPT_ERROR);
+  size_t max_out = plaintext_len + EVP_CIPHER_CTX_block_size(&ctx);
+  if (max_out < plaintext_len) {
+    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_TOO_LONG);
     goto err;
   }
 
-  return pkcs8;
-
-err:
-  X509_SIG_free(pkcs8);
-  return NULL;
-}
-
-EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8) {
-  EVP_PKEY *pkey = NULL;
-  ASN1_OBJECT *algoid;
-  char obj_tmp[80];
-
-  if (!PKCS8_pkey_get0(&algoid, NULL, NULL, NULL, p8)) {
-    return NULL;
-  }
-
-  pkey = EVP_PKEY_new();
-  if (pkey == NULL) {
-    OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE);
-    return NULL;
-  }
-
-  if (!EVP_PKEY_set_type(pkey, OBJ_obj2nid(algoid))) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM);
-    i2t_ASN1_OBJECT(obj_tmp, 80, algoid);
-    ERR_add_error_data(2, "TYPE=", obj_tmp);
-    goto error;
-  }
-
-  if (pkey->ameth->priv_decode) {
-    if (!pkey->ameth->priv_decode(pkey, p8)) {
-      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_PRIVATE_KEY_DECODE_ERROR);
-      goto error;
-    }
-  } else {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_METHOD_NOT_SUPPORTED);
-    goto error;
-  }
-
-  return pkey;
-
-error:
-  EVP_PKEY_free(pkey);
-  return NULL;
-}
-
-PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey) {
-  PKCS8_PRIV_KEY_INFO *p8;
-
-  p8 = PKCS8_PRIV_KEY_INFO_new();
-  if (p8 == NULL) {
-    OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE);
-    return NULL;
-  }
-  p8->broken = PKCS8_OK;
-
-  if (pkey->ameth) {
-    if (pkey->ameth->priv_encode) {
-      if (!pkey->ameth->priv_encode(p8, pkey)) {
-        OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_PRIVATE_KEY_ENCODE_ERROR);
-        goto error;
-      }
-    } else {
-      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_METHOD_NOT_SUPPORTED);
-      goto error;
-    }
-  } else {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM);
-    goto error;
-  }
-  return p8;
-
-error:
-  PKCS8_PRIV_KEY_INFO_free(p8);
-  return NULL;
-}
-
-struct pkcs12_context {
-  EVP_PKEY **out_key;
-  STACK_OF(X509) *out_certs;
-  uint8_t *password;
-  size_t password_len;
-};
-
-static int PKCS12_handle_content_info(CBS *content_info, unsigned depth,
-                                      struct pkcs12_context *ctx);
-
-/* PKCS12_handle_content_infos parses a series of PKCS#7 ContentInfos in a
- * SEQUENCE. */
-static int PKCS12_handle_content_infos(CBS *content_infos,
-                                       unsigned depth,
-                                       struct pkcs12_context *ctx) {
-  uint8_t *der_bytes = NULL;
-  size_t der_len;
-  CBS in;
-  int ret = 0;
-
-  /* Generally we only expect depths 0 (the top level, with a
-   * pkcs7-encryptedData and a pkcs7-data) and depth 1 (the various PKCS#12
-   * bags). */
-  if (depth > 3) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_PKCS12_TOO_DEEPLY_NESTED);
-    return 0;
-  }
-
-  /* Although a BER->DER conversion is done at the beginning of |PKCS12_parse|,
-   * the ASN.1 data gets wrapped in OCTETSTRINGs and/or encrypted and the
-   * conversion cannot see through those wrappings. So each time we step
-   * through one we need to convert to DER again. */
-  if (!CBS_asn1_ber_to_der(content_infos, &der_bytes, &der_len)) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
-    return 0;
-  }
-
-  if (der_bytes != NULL) {
-    CBS_init(&in, der_bytes, der_len);
-  } else {
-    CBS_init(&in, CBS_data(content_infos), CBS_len(content_infos));
-  }
-
-  if (!CBS_get_asn1(&in, &in, CBS_ASN1_SEQUENCE)) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
-    goto err;
-  }
-
-  while (CBS_len(&in) > 0) {
-    CBS content_info;
-    if (!CBS_get_asn1(&in, &content_info, CBS_ASN1_SEQUENCE)) {
-      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
-      goto err;
-    }
-
-    if (!PKCS12_handle_content_info(&content_info, depth + 1, ctx)) {
-      goto err;
-    }
-  }
-
-  /* NSS includes additional data after the SEQUENCE, but it's an (unwrapped)
-   * copy of the same encrypted private key (with the same IV and
-   * ciphertext)! */
-
-  ret = 1;
-
-err:
-  OPENSSL_free(der_bytes);
-  return ret;
-}
-
-/* PKCS12_handle_content_info parses a single PKCS#7 ContentInfo element in a
- * PKCS#12 structure. */
-static int PKCS12_handle_content_info(CBS *content_info, unsigned depth,
-                                      struct pkcs12_context *ctx) {
-  CBS content_type, wrapped_contents, contents, content_infos;
-  int nid, ret = 0;
-
-  if (!CBS_get_asn1(content_info, &content_type, CBS_ASN1_OBJECT) ||
-      !CBS_get_asn1(content_info, &wrapped_contents,
-                        CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
-    goto err;
-  }
-
-  nid = OBJ_cbs2nid(&content_type);
-  if (nid == NID_pkcs7_encrypted) {
-    /* See https://tools.ietf.org/html/rfc2315#section-13.
-     *
-     * PKCS#7 encrypted data inside a PKCS#12 structure is generally an
-     * encrypted certificate bag and it's generally encrypted with 40-bit
-     * RC2-CBC. */
-    CBS version_bytes, eci, contents_type, ai, encrypted_contents;
-    X509_ALGOR *algor = NULL;
-    const uint8_t *inp;
-    uint8_t *out;
-    size_t out_len;
-
-    if (!CBS_get_asn1(&wrapped_contents, &contents, CBS_ASN1_SEQUENCE) ||
-        !CBS_get_asn1(&contents, &version_bytes, CBS_ASN1_INTEGER) ||
-        /* EncryptedContentInfo, see
-         * https://tools.ietf.org/html/rfc2315#section-10.1 */
-        !CBS_get_asn1(&contents, &eci, CBS_ASN1_SEQUENCE) ||
-        !CBS_get_asn1(&eci, &contents_type, CBS_ASN1_OBJECT) ||
-        /* AlgorithmIdentifier, see
-         * https://tools.ietf.org/html/rfc5280#section-4.1.1.2 */
-        !CBS_get_asn1_element(&eci, &ai, CBS_ASN1_SEQUENCE) ||
-        !CBS_get_asn1(&eci, &encrypted_contents,
-                      CBS_ASN1_CONTEXT_SPECIFIC | 0)) {
-      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
-      goto err;
-    }
-
-    if (OBJ_cbs2nid(&contents_type) != NID_pkcs7_data ||
-        CBS_len(&ai) > LONG_MAX) {
-      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
-      goto err;
-    }
-
-    inp = CBS_data(&ai);
-    algor = d2i_X509_ALGOR(NULL, &inp, (long)CBS_len(&ai));
-    if (algor == NULL) {
-      goto err;
-    }
-    if (inp != CBS_data(&ai) + CBS_len(&ai)) {
-      X509_ALGOR_free(algor);
-      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
-      goto err;
-    }
-
-    if (!pbe_crypt(algor, ctx->password, ctx->password_len,
-                   CBS_data(&encrypted_contents), CBS_len(&encrypted_contents),
-                   &out, &out_len, 0 /* decrypt */)) {
-      X509_ALGOR_free(algor);
-      goto err;
-    }
-    X509_ALGOR_free(algor);
-
-    CBS_init(&content_infos, out, out_len);
-    ret = PKCS12_handle_content_infos(&content_infos, depth + 1, ctx);
-    OPENSSL_free(out);
-  } else if (nid == NID_pkcs7_data) {
-    CBS octet_string_contents;
-
-    if (!CBS_get_asn1(&wrapped_contents, &octet_string_contents,
-                          CBS_ASN1_OCTETSTRING)) {
-      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
-      goto err;
-    }
-
-    ret = PKCS12_handle_content_infos(&octet_string_contents, depth + 1, ctx);
-  } else if (nid == NID_pkcs8ShroudedKeyBag) {
-    /* See ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1.pdf, section
-     * 4.2.2. */
-    const uint8_t *inp = CBS_data(&wrapped_contents);
-    PKCS8_PRIV_KEY_INFO *pki = NULL;
-    X509_SIG *encrypted = NULL;
-
-    if (*ctx->out_key) {
-      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_MULTIPLE_PRIVATE_KEYS_IN_PKCS12);
-      goto err;
-    }
-
-    if (CBS_len(&wrapped_contents) > LONG_MAX) {
-      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
-      goto err;
-    }
-
-    /* encrypted isn't actually an X.509 signature, but it has the same
-     * structure as one and so |X509_SIG| is reused to store it. */
-    encrypted = d2i_X509_SIG(NULL, &inp, (long)CBS_len(&wrapped_contents));
-    if (encrypted == NULL) {
-      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
-      goto err;
-    }
-    if (inp != CBS_data(&wrapped_contents) + CBS_len(&wrapped_contents)) {
-      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
-      X509_SIG_free(encrypted);
-      goto err;
-    }
-
-    pki = PKCS8_decrypt_pbe(encrypted, ctx->password, ctx->password_len);
-    X509_SIG_free(encrypted);
-    if (pki == NULL) {
-      goto err;
-    }
-
-    *ctx->out_key = EVP_PKCS82PKEY(pki);
-    PKCS8_PRIV_KEY_INFO_free(pki);
-
-    if (ctx->out_key == NULL) {
-      goto err;
-    }
-    ret = 1;
-  } else if (nid == NID_certBag) {
-    CBS cert_bag, cert_type, wrapped_cert, cert;
-
-    if (!CBS_get_asn1(&wrapped_contents, &cert_bag, CBS_ASN1_SEQUENCE) ||
-        !CBS_get_asn1(&cert_bag, &cert_type, CBS_ASN1_OBJECT) ||
-        !CBS_get_asn1(&cert_bag, &wrapped_cert,
-                      CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
-        !CBS_get_asn1(&wrapped_cert, &cert, CBS_ASN1_OCTETSTRING)) {
-      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
-      goto err;
-    }
-
-    if (OBJ_cbs2nid(&cert_type) == NID_x509Certificate) {
-      if (CBS_len(&cert) > LONG_MAX) {
-        OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
-        goto err;
-      }
-      const uint8_t *inp = CBS_data(&cert);
-      X509 *x509 = d2i_X509(NULL, &inp, (long)CBS_len(&cert));
-      if (!x509) {
-        OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
-        goto err;
-      }
-      if (inp != CBS_data(&cert) + CBS_len(&cert)) {
-        OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
-        X509_free(x509);
-        goto err;
-      }
-
-      if (0 == sk_X509_push(ctx->out_certs, x509)) {
-        X509_free(x509);
-        goto err;
-      }
-    }
-    ret = 1;
-  } else {
-    /* Unknown element type - ignore it. */
-    ret = 1;
-  }
-
-err:
-  return ret;
-}
-
-int PKCS12_get_key_and_certs(EVP_PKEY **out_key, STACK_OF(X509) *out_certs,
-                             CBS *ber_in, const char *password) {
-  uint8_t *der_bytes = NULL;
-  size_t der_len;
-  CBS in, pfx, mac_data, authsafe, content_type, wrapped_authsafes, authsafes;
-  uint64_t version;
-  int ret = 0;
-  struct pkcs12_context ctx;
-  const size_t original_out_certs_len = sk_X509_num(out_certs);
-
-  /* The input may be in BER format. */
-  if (!CBS_asn1_ber_to_der(ber_in, &der_bytes, &der_len)) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
-    return 0;
-  }
-  if (der_bytes != NULL) {
-    CBS_init(&in, der_bytes, der_len);
-  } else {
-    CBS_init(&in, CBS_data(ber_in), CBS_len(ber_in));
-  }
-
-  *out_key = NULL;
-  memset(&ctx, 0, sizeof(ctx));
-
-  /* See ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1.pdf, section
-   * four. */
-  if (!CBS_get_asn1(&in, &pfx, CBS_ASN1_SEQUENCE) ||
-      CBS_len(&in) != 0 ||
-      !CBS_get_asn1_uint64(&pfx, &version)) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
-    goto err;
-  }
-
-  if (version < 3) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_VERSION);
-    goto err;
-  }
-
-  if (!CBS_get_asn1(&pfx, &authsafe, CBS_ASN1_SEQUENCE)) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
-    goto err;
-  }
-
-  if (CBS_len(&pfx) == 0) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_MISSING_MAC);
-    goto err;
-  }
-
-  if (!CBS_get_asn1(&pfx, &mac_data, CBS_ASN1_SEQUENCE)) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
-    goto err;
-  }
-
-  /* authsafe is a PKCS#7 ContentInfo. See
-   * https://tools.ietf.org/html/rfc2315#section-7. */
-  if (!CBS_get_asn1(&authsafe, &content_type, CBS_ASN1_OBJECT) ||
-      !CBS_get_asn1(&authsafe, &wrapped_authsafes,
-                        CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
-    goto err;
-  }
-
-  /* The content type can either be |NID_pkcs7_data| or |NID_pkcs7_signed|. The
-   * latter indicates that it's signed by a public key, which isn't
-   * supported. */
-  if (OBJ_cbs2nid(&content_type) != NID_pkcs7_data) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED);
-    goto err;
-  }
-
-  if (!CBS_get_asn1(&wrapped_authsafes, &authsafes, CBS_ASN1_OCTETSTRING)) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
-    goto err;
-  }
-
-  ctx.out_key = out_key;
-  ctx.out_certs = out_certs;
-  if (!ascii_to_ucs2(password, strlen(password), &ctx.password,
-                     &ctx.password_len)) {
-    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
-    goto err;
-  }
-
-  /* Verify the MAC. */
-  {
-    CBS mac, hash_type_seq, hash_oid, salt, expected_mac;
-    uint64_t iterations;
-    int hash_nid;
-    const EVP_MD *md;
-    uint8_t hmac_key[EVP_MAX_MD_SIZE];
-    uint8_t hmac[EVP_MAX_MD_SIZE];
-    unsigned hmac_len;
-
-    if (!CBS_get_asn1(&mac_data, &mac, CBS_ASN1_SEQUENCE) ||
-        !CBS_get_asn1(&mac, &hash_type_seq, CBS_ASN1_SEQUENCE) ||
-        !CBS_get_asn1(&hash_type_seq, &hash_oid, CBS_ASN1_OBJECT) ||
-        !CBS_get_asn1(&mac, &expected_mac, CBS_ASN1_OCTETSTRING) ||
-        !CBS_get_asn1(&mac_data, &salt, CBS_ASN1_OCTETSTRING)) {
-      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
-      goto err;
-    }
-
-    /* The iteration count is optional and the default is one. */
-    iterations = 1;
-    if (CBS_len(&mac_data) > 0) {
-      if (!CBS_get_asn1_uint64(&mac_data, &iterations) ||
-          iterations > INT_MAX) {
-        OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
-        goto err;
-      }
-    }
-
-    hash_nid = OBJ_cbs2nid(&hash_oid);
-    if (hash_nid == NID_undef ||
-        (md = EVP_get_digestbynid(hash_nid)) == NULL) {
-      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_UNKNOWN_HASH);
-      goto err;
-    }
-
-    if (!pkcs12_key_gen_raw(ctx.password, ctx.password_len, CBS_data(&salt),
-                            CBS_len(&salt), PKCS12_MAC_ID, iterations,
-                            EVP_MD_size(md), hmac_key, md)) {
-      goto err;
-    }
-
-    if (NULL == HMAC(md, hmac_key, EVP_MD_size(md), CBS_data(&authsafes),
-                     CBS_len(&authsafes), hmac, &hmac_len)) {
-      goto err;
-    }
-
-    if (!CBS_mem_equal(&expected_mac, hmac, hmac_len)) {
-      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_INCORRECT_PASSWORD);
-      goto err;
-    }
-  }
-
-  /* authsafes contains a series of PKCS#7 ContentInfos. */
-  if (!PKCS12_handle_content_infos(&authsafes, 0, &ctx)) {
+  CBB ciphertext;
+  uint8_t *ptr;
+  int n1, n2;
+  if (!CBB_add_asn1(&epki, &ciphertext, CBS_ASN1_OCTETSTRING) ||
+      !CBB_reserve(&ciphertext, &ptr, max_out) ||
+      !EVP_CipherUpdate(&ctx, ptr, &n1, plaintext, plaintext_len) ||
+      !EVP_CipherFinal_ex(&ctx, ptr + n1, &n2) ||
+      !CBB_did_write(&ciphertext, n1 + n2) ||
+      !CBB_flush(out)) {
     goto err;
   }
 
   ret = 1;
 
 err:
-  OPENSSL_free(ctx.password);
-  OPENSSL_free(der_bytes);
-  if (!ret) {
-    EVP_PKEY_free(*out_key);
-    *out_key = NULL;
-    while (sk_X509_num(out_certs) > original_out_certs_len) {
-      X509 *x509 = sk_X509_pop(out_certs);
-      X509_free(x509);
-    }
+  if (plaintext != NULL) {
+    OPENSSL_cleanse(plaintext, plaintext_len);
+    OPENSSL_free(plaintext);
   }
-
+  OPENSSL_free(salt_buf);
+  EVP_CIPHER_CTX_cleanup(&ctx);
   return ret;
 }
-
-void PKCS12_PBE_add(void) {}
-
-struct pkcs12_st {
-  uint8_t *ber_bytes;
-  size_t ber_len;
-};
-
-PKCS12* d2i_PKCS12(PKCS12 **out_p12, const uint8_t **ber_bytes, size_t ber_len) {
-  PKCS12 *p12;
-
-  /* out_p12 must be NULL because we don't export the PKCS12 structure. */
-  assert(out_p12 == NULL);
-
-  p12 = OPENSSL_malloc(sizeof(PKCS12));
-  if (!p12) {
-    return NULL;
-  }
-
-  p12->ber_bytes = OPENSSL_malloc(ber_len);
-  if (!p12->ber_bytes) {
-    OPENSSL_free(p12);
-    return NULL;
-  }
-
-  memcpy(p12->ber_bytes, *ber_bytes, ber_len);
-  p12->ber_len = ber_len;
-  *ber_bytes += ber_len;
-
-  return p12;
-}
-
-PKCS12* d2i_PKCS12_bio(BIO *bio, PKCS12 **out_p12) {
-  size_t used = 0;
-  BUF_MEM *buf;
-  const uint8_t *dummy;
-  static const size_t kMaxSize = 256 * 1024;
-  PKCS12 *ret = NULL;
-
-  buf = BUF_MEM_new();
-  if (buf == NULL) {
-    return NULL;
-  }
-  if (BUF_MEM_grow(buf, 8192) == 0) {
-    goto out;
-  }
-
-  for (;;) {
-    int n = BIO_read(bio, &buf->data[used], buf->length - used);
-    if (n < 0) {
-      goto out;
-    }
-
-    if (n == 0) {
-      break;
-    }
-    used += n;
-
-    if (used < buf->length) {
-      continue;
-    }
-
-    if (buf->length > kMaxSize ||
-        BUF_MEM_grow(buf, buf->length * 2) == 0) {
-      goto out;
-    }
-  }
-
-  dummy = (uint8_t*) buf->data;
-  ret = d2i_PKCS12(out_p12, &dummy, used);
-
-out:
-  BUF_MEM_free(buf);
-  return ret;
-}
-
-PKCS12* d2i_PKCS12_fp(FILE *fp, PKCS12 **out_p12) {
-  BIO *bio;
-  PKCS12 *ret;
-
-  bio = BIO_new_fp(fp, 0 /* don't take ownership */);
-  if (!bio) {
-    return NULL;
-  }
-
-  ret = d2i_PKCS12_bio(bio, out_p12);
-  BIO_free(bio);
-  return ret;
-}
-
-int PKCS12_parse(const PKCS12 *p12, const char *password, EVP_PKEY **out_pkey,
-                 X509 **out_cert, STACK_OF(X509) **out_ca_certs) {
-  CBS ber_bytes;
-  STACK_OF(X509) *ca_certs = NULL;
-  char ca_certs_alloced = 0;
-
-  if (out_ca_certs != NULL && *out_ca_certs != NULL) {
-    ca_certs = *out_ca_certs;
-  }
-
-  if (!ca_certs) {
-    ca_certs = sk_X509_new_null();
-    if (ca_certs == NULL) {
-      OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE);
-      return 0;
-    }
-    ca_certs_alloced = 1;
-  }
-
-  CBS_init(&ber_bytes, p12->ber_bytes, p12->ber_len);
-  if (!PKCS12_get_key_and_certs(out_pkey, ca_certs, &ber_bytes, password)) {
-    if (ca_certs_alloced) {
-      sk_X509_free(ca_certs);
-    }
-    return 0;
-  }
-
-  *out_cert = NULL;
-  if (sk_X509_num(ca_certs) > 0) {
-    *out_cert = sk_X509_shift(ca_certs);
-  }
-
-  if (out_ca_certs) {
-    *out_ca_certs = ca_certs;
-  } else {
-    sk_X509_pop_free(ca_certs, X509_free);
-  }
-
-  return 1;
-}
-
-int PKCS12_verify_mac(const PKCS12 *p12, const char *password,
-                      int password_len) {
-  if (password == NULL) {
-    if (password_len != 0) {
-      return 0;
-    }
-  } else if (password_len != -1 &&
-             (password[password_len] != 0 ||
-              memchr(password, 0, password_len) != NULL)) {
-    return 0;
-  }
-
-  EVP_PKEY *pkey = NULL;
-  X509 *cert = NULL;
-  if (!PKCS12_parse(p12, password, &pkey, &cert, NULL)) {
-    ERR_clear_error();
-    return 0;
-  }
-
-  EVP_PKEY_free(pkey);
-  X509_free(cert);
-
-  return 1;
-}
-
-void PKCS12_free(PKCS12 *p12) {
-  OPENSSL_free(p12->ber_bytes);
-  OPENSSL_free(p12);
-}
diff --git a/src/crypto/pkcs8/pkcs8_test.cc b/src/crypto/pkcs8/pkcs8_test.cc
index 7a88ddf..94385ac 100644
--- a/src/crypto/pkcs8/pkcs8_test.cc
+++ b/src/crypto/pkcs8/pkcs8_test.cc
@@ -21,7 +21,7 @@
 #include <openssl/pkcs8.h>
 #include <openssl/x509.h>
 
-#include "../test/scoped_types.h"
+#include "../internal.h"
 
 
 /* kDER is a PKCS#8 encrypted private key. It was generated with:
@@ -62,16 +62,123 @@
   0xd6, 0x2d,
 };
 
-static bool test(const uint8_t *der, size_t der_len) {
+/* kNullPassword is a PKCS#8 encrypted private key using the null password. */
+static const uint8_t kNullPassword[] = {
+    0x30, 0x81, 0xb0, 0x30, 0x1b, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+    0x0d, 0x01, 0x0c, 0x01, 0x03, 0x30, 0x0d, 0x04, 0x08, 0xb2, 0xfe, 0x68,
+    0xc2, 0xea, 0x0f, 0x10, 0x9c, 0x02, 0x01, 0x01, 0x04, 0x81, 0x90, 0xe2,
+    0xf6, 0x1c, 0xca, 0xad, 0x64, 0x30, 0xbf, 0x88, 0x04, 0x35, 0xe5, 0x0f,
+    0x11, 0x49, 0x06, 0x01, 0x14, 0x33, 0x80, 0xa2, 0x78, 0x44, 0x5b, 0xaa,
+    0x0d, 0xd7, 0x00, 0x36, 0x9d, 0x91, 0x97, 0x37, 0x20, 0x7b, 0x27, 0xc1,
+    0xa0, 0xa2, 0x73, 0x06, 0x15, 0xdf, 0xc8, 0x13, 0x9b, 0xc9, 0x8c, 0x9c,
+    0xce, 0x00, 0xd0, 0xc8, 0x42, 0xc1, 0xda, 0x2b, 0x07, 0x2b, 0x12, 0xa3,
+    0xce, 0x10, 0x39, 0x7a, 0xf1, 0x55, 0x69, 0x8d, 0xa5, 0xc4, 0x2a, 0x00,
+    0x0d, 0x94, 0xc6, 0xde, 0x6a, 0x3d, 0xb7, 0xe5, 0x6d, 0x59, 0x3e, 0x09,
+    0xb5, 0xe3, 0x3e, 0xfc, 0x50, 0x56, 0xe9, 0x50, 0x42, 0x7c, 0xe7, 0xf0,
+    0x19, 0xbd, 0x31, 0xa7, 0x85, 0x47, 0xb3, 0xe9, 0xb3, 0x50, 0x3c, 0xc9,
+    0x32, 0x37, 0x1a, 0x93, 0x78, 0x48, 0x78, 0x82, 0xde, 0xad, 0x5c, 0xf2,
+    0xcf, 0xf2, 0xbb, 0x2c, 0x44, 0x05, 0x7f, 0x4a, 0xf9, 0xb1, 0x2b, 0xdd,
+    0x49, 0xf6, 0x7e, 0xd0, 0x42, 0xaa, 0x14, 0x3c, 0x24, 0x77, 0xb4,
+};
+
+/* kNullPasswordNSS is a PKCS#8 encrypted private key using the null password
+ * and generated by NSS. */
+static const uint8_t kNullPasswordNSS[] = {
+    0x30, 0x81, 0xb8, 0x30, 0x23, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+    0x0d, 0x01, 0x0c, 0x01, 0x03, 0x30, 0x15, 0x04, 0x10, 0x3f, 0xac, 0xe9,
+    0x38, 0xdb, 0x40, 0x6b, 0x26, 0x89, 0x09, 0x73, 0x18, 0x8d, 0x7f, 0x1c,
+    0x82, 0x02, 0x01, 0x01, 0x04, 0x81, 0x90, 0x5e, 0x5e, 0x11, 0xef, 0xbb,
+    0x7c, 0x4d, 0xec, 0xc0, 0xdc, 0xc7, 0x23, 0xd2, 0xc4, 0x77, 0xbc, 0xf4,
+    0x5d, 0x59, 0x4c, 0x07, 0xc2, 0x8a, 0x26, 0xfa, 0x25, 0x1c, 0xaa, 0x42,
+    0xed, 0xd0, 0xed, 0xbb, 0x5c, 0xe9, 0x13, 0x07, 0xaa, 0xdd, 0x52, 0x3c,
+    0x65, 0x25, 0xbf, 0x94, 0x02, 0xaf, 0xd6, 0x97, 0xe9, 0x33, 0x00, 0x76,
+    0x64, 0x4a, 0x73, 0xab, 0xfb, 0x99, 0x6e, 0x83, 0x12, 0x05, 0x86, 0x72,
+    0x6c, 0xd5, 0xa4, 0xcf, 0xb1, 0xd5, 0x4d, 0x54, 0x87, 0x8b, 0x4b, 0x95,
+    0x1d, 0xcd, 0xf3, 0xfe, 0xa8, 0xda, 0xe0, 0xb6, 0x72, 0x13, 0x3f, 0x2e,
+    0x66, 0xe0, 0xb9, 0x2e, 0xfa, 0x69, 0x40, 0xbe, 0xd7, 0x67, 0x6e, 0x53,
+    0x2b, 0x3f, 0x53, 0xe5, 0x39, 0x54, 0x77, 0xe1, 0x1d, 0xe6, 0x81, 0x92,
+    0x58, 0x82, 0x14, 0xfb, 0x47, 0x85, 0x3c, 0xc3, 0xdf, 0xdd, 0xcc, 0x79,
+    0x9f, 0x41, 0x83, 0x72, 0xf2, 0x0a, 0xe9, 0xe1, 0x2c, 0x12, 0xb0, 0xb0,
+    0x0a, 0xb2, 0x1d, 0xca, 0x15, 0xb2, 0xca,
+};
+
+/* kEmptyPasswordOpenSSL is a PKCS#8 encrypted private key using the empty
+ * password and generated by OpenSSL. */
+static const uint8_t kEmptyPasswordOpenSSL[] = {
+    0x30, 0x82, 0x01, 0xa1, 0x30, 0x1b, 0x06, 0x0a, 0x2a, 0x86, 0x48, 0x86,
+    0xf7, 0x0d, 0x01, 0x0c, 0x01, 0x03, 0x30, 0x0d, 0x04, 0x08, 0x86, 0xaa,
+    0xd7, 0xdf, 0x3b, 0x91, 0x97, 0x60, 0x02, 0x01, 0x01, 0x04, 0x82, 0x01,
+    0x80, 0xcb, 0x2a, 0x14, 0xaa, 0x4f, 0x38, 0x4c, 0xe1, 0x49, 0x00, 0xe2,
+    0x1a, 0x3a, 0x75, 0x87, 0x7e, 0x3d, 0xea, 0x4d, 0x53, 0xd4, 0x46, 0x47,
+    0x23, 0x8f, 0xa1, 0x72, 0x51, 0x92, 0x86, 0x8b, 0xeb, 0x53, 0xe6, 0x6a,
+    0x0a, 0x6b, 0xb6, 0xa0, 0xdc, 0x0f, 0xdc, 0x20, 0xc3, 0x45, 0x85, 0xf1,
+    0x95, 0x90, 0x5c, 0xf4, 0xfa, 0xee, 0x47, 0xaf, 0x35, 0xd0, 0xd0, 0xd3,
+    0x14, 0xde, 0x0d, 0xca, 0x1b, 0xd3, 0xbb, 0x20, 0xec, 0x9d, 0x6a, 0xd4,
+    0xc1, 0xce, 0x60, 0x81, 0xab, 0x0c, 0x72, 0x10, 0xfa, 0x28, 0x3c, 0xac,
+    0x87, 0x7b, 0x82, 0x85, 0x00, 0xb8, 0x58, 0x9c, 0x07, 0xc4, 0x7d, 0xa9,
+    0xc5, 0x94, 0x95, 0xf7, 0x23, 0x93, 0x3f, 0xed, 0xef, 0x92, 0x55, 0x25,
+    0x74, 0xbb, 0xd3, 0xd1, 0x67, 0x3b, 0x3d, 0x5a, 0xfe, 0x84, 0xf8, 0x97,
+    0x7d, 0x7c, 0x01, 0xc7, 0xd7, 0x0d, 0xf8, 0xc3, 0x6d, 0xd6, 0xf1, 0xaa,
+    0x9d, 0x1f, 0x69, 0x97, 0x45, 0x06, 0xc4, 0x1c, 0x95, 0x3c, 0xe0, 0xef,
+    0x11, 0xb2, 0xb3, 0x72, 0x91, 0x9e, 0x7d, 0x0f, 0x7f, 0xc8, 0xf6, 0x64,
+    0x49, 0x5e, 0x3c, 0x53, 0x37, 0x79, 0x03, 0x1c, 0x3f, 0x29, 0x6c, 0x6b,
+    0xea, 0x4c, 0x35, 0x9b, 0x6d, 0x1b, 0x59, 0x43, 0x4c, 0x14, 0x47, 0x2a,
+    0x36, 0x39, 0x2a, 0xd8, 0x96, 0x90, 0xdc, 0xfc, 0xd2, 0xdd, 0x23, 0x0e,
+    0x2c, 0xb3, 0x83, 0xf9, 0xf2, 0xe3, 0xe6, 0x99, 0x53, 0x57, 0x33, 0xc5,
+    0x5f, 0xf9, 0xfd, 0x56, 0x0b, 0x32, 0xd4, 0xf3, 0x9d, 0x5b, 0x34, 0xe5,
+    0x94, 0xbf, 0xb6, 0xc0, 0xce, 0xe1, 0x73, 0x5c, 0x02, 0x7a, 0x4c, 0xed,
+    0xde, 0x23, 0x38, 0x89, 0x9f, 0xcd, 0x51, 0xf3, 0x90, 0x80, 0xd3, 0x4b,
+    0x83, 0xd3, 0xee, 0xf2, 0x9e, 0x35, 0x91, 0xa5, 0xa3, 0xc0, 0x5c, 0xce,
+    0xdb, 0xaa, 0x70, 0x1e, 0x1d, 0xc1, 0x44, 0xea, 0x3b, 0xa7, 0x5a, 0x11,
+    0xd1, 0xf3, 0xf3, 0xd0, 0xf4, 0x5a, 0xc4, 0x99, 0xaf, 0x8d, 0xe2, 0xbc,
+    0xa2, 0xb9, 0x3d, 0x86, 0x5e, 0xba, 0xa0, 0xdf, 0x78, 0x81, 0x7c, 0x54,
+    0x31, 0xe3, 0x98, 0xb5, 0x46, 0xcb, 0x4d, 0x26, 0x4b, 0xf8, 0xac, 0x3a,
+    0x54, 0x1b, 0x77, 0x5a, 0x18, 0xa5, 0x43, 0x0e, 0x14, 0xde, 0x7b, 0xb7,
+    0x4e, 0x45, 0x99, 0x03, 0xd1, 0x3d, 0x18, 0xb2, 0x36, 0x00, 0x48, 0x07,
+    0x72, 0xbb, 0x4f, 0x21, 0x25, 0x3e, 0xda, 0x25, 0x24, 0x5b, 0xc8, 0xa0,
+    0x28, 0xd5, 0x9b, 0x96, 0x87, 0x07, 0x77, 0x84, 0xff, 0xd7, 0xac, 0x71,
+    0xf6, 0x61, 0x63, 0x0b, 0xfb, 0x42, 0xfd, 0x52, 0xf4, 0xc4, 0x35, 0x0c,
+    0xc2, 0xc1, 0x55, 0x22, 0x42, 0x2f, 0x13, 0x7d, 0x93, 0x27, 0xc8, 0x11,
+    0x35, 0xc5, 0xe3, 0xc5, 0xaa, 0x15, 0x3c, 0xac, 0x30, 0xbc, 0x45, 0x16,
+    0xed,
+};
+
+// kExplicitHMACWithSHA1 is a PBES2-encrypted private key with an explicit
+// hmacWithSHA1 AlgorithmIdentifier in the PBKDF2 parameters.
+static const uint8_t kExplicitHMACWithSHA1[] = {
+    0x30, 0x81, 0xec, 0x30, 0x57, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+    0x0d, 0x01, 0x05, 0x0d, 0x30, 0x4a, 0x30, 0x29, 0x06, 0x09, 0x2a, 0x86,
+    0x48, 0x86, 0xf7, 0x0d, 0x01, 0x05, 0x0c, 0x30, 0x1c, 0x04, 0x08, 0x90,
+    0xcd, 0x1e, 0x47, 0x1d, 0xff, 0x4c, 0xa8, 0x02, 0x02, 0x08, 0x00, 0x30,
+    0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x07, 0x05,
+    0x00, 0x30, 0x1d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04,
+    0x01, 0x02, 0x04, 0x10, 0x34, 0xe7, 0x5b, 0x9b, 0xf9, 0x17, 0xcf, 0x15,
+    0x59, 0x7c, 0xfd, 0xc1, 0xac, 0xed, 0x6f, 0xdd, 0x04, 0x81, 0x90, 0xe3,
+    0xd7, 0xfc, 0xbe, 0xe6, 0xe8, 0x92, 0xc1, 0xa2, 0x57, 0x42, 0x4b, 0xf1,
+    0x35, 0x6c, 0x4f, 0x58, 0x61, 0x14, 0x30, 0x4e, 0xa3, 0x8d, 0x4f, 0xde,
+    0x2d, 0x0b, 0xa2, 0x62, 0x4b, 0xee, 0x9f, 0xc4, 0xeb, 0x89, 0x33, 0x76,
+    0x3f, 0x0c, 0x20, 0xad, 0x75, 0x29, 0x42, 0xbc, 0xbd, 0x83, 0x46, 0x1d,
+    0x5c, 0xae, 0xec, 0x10, 0x05, 0xbb, 0xd3, 0x98, 0xc9, 0x5a, 0x5e, 0x0a,
+    0x95, 0x12, 0x1e, 0x65, 0x93, 0xdd, 0xdd, 0x51, 0xd5, 0x56, 0xc2, 0xa9,
+    0xf9, 0x43, 0x0f, 0x68, 0x8a, 0x14, 0x40, 0xe5, 0x62, 0x9e, 0x0d, 0xd7,
+    0x67, 0x62, 0xf4, 0x49, 0xb1, 0x62, 0x22, 0x42, 0xb1, 0xe1, 0xb2, 0x1d,
+    0x37, 0x3e, 0x95, 0x52, 0xe9, 0x61, 0x89, 0xc7, 0x62, 0xcc, 0xb1, 0x44,
+    0x40, 0xef, 0x89, 0xc8, 0xc4, 0x0e, 0xae, 0xa8, 0xf9, 0x17, 0x42, 0x2b,
+    0x8c, 0x0b, 0x26, 0xf6, 0x07, 0x00, 0xab, 0x25, 0x2b, 0x64, 0xcf, 0xc3,
+    0x68, 0xf9, 0x5e, 0x01, 0x66, 0x59, 0x5f, 0x3f, 0x05, 0x57, 0xcd,
+};
+
+static bool TestDecrypt(const uint8_t *der, size_t der_len,
+                        const char *password) {
   const uint8_t *data = der;
-  ScopedX509_SIG sig(d2i_X509_SIG(NULL, &data, der_len));
+  bssl::UniquePtr<X509_SIG> sig(d2i_X509_SIG(NULL, &data, der_len));
   if (sig.get() == NULL || data != der + der_len) {
     fprintf(stderr, "d2i_X509_SIG failed or did not consume all bytes.\n");
     return false;
   }
 
-  static const char kPassword[] = "testing";
-  ScopedPKCS8_PRIV_KEY_INFO keypair(PKCS8_decrypt(sig.get(), kPassword, -1));
+  bssl::UniquePtr<PKCS8_PRIV_KEY_INFO> keypair(
+      PKCS8_decrypt(sig.get(), password, -1));
   if (!keypair) {
     fprintf(stderr, "PKCS8_decrypt failed.\n");
     ERR_print_errors_fp(stderr);
@@ -81,8 +188,94 @@
   return true;
 }
 
+static bool TestRoundTrip(int pbe_nid, const EVP_CIPHER *cipher,
+                          const char *password, const uint8_t *salt,
+                          size_t salt_len, int iterations) {
+  static const uint8_t kSampleKey[] = {
+      0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
+      0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
+      0x03, 0x01, 0x07, 0x04, 0x6d, 0x30, 0x6b, 0x02, 0x01, 0x01, 0x04, 0x20,
+      0x8a, 0x87, 0x2f, 0xb6, 0x28, 0x93, 0xc4, 0xd1, 0xff, 0xc5, 0xb9, 0xf0,
+      0xf9, 0x17, 0x58, 0x06, 0x9f, 0x83, 0x52, 0xe0, 0x8f, 0xa0, 0x5a, 0x49,
+      0xf8, 0xdb, 0x92, 0x6c, 0xb5, 0x72, 0x87, 0x25, 0xa1, 0x44, 0x03, 0x42,
+      0x00, 0x04, 0x2c, 0x15, 0x0f, 0x42, 0x9c, 0xe7, 0x0f, 0x21, 0x6c, 0x25,
+      0x2c, 0xf5, 0xe0, 0x62, 0xce, 0x1f, 0x63, 0x9c, 0xd5, 0xd1, 0x65, 0xc7,
+      0xf8, 0x94, 0x24, 0x07, 0x2c, 0x27, 0x19, 0x7d, 0x78, 0xb3, 0x3b, 0x92,
+      0x0e, 0x95, 0xcd, 0xb6, 0x64, 0xe9, 0x90, 0xdc, 0xf0, 0xcf, 0xea, 0x0d,
+      0x94, 0xe2, 0xa8, 0xe6, 0xaf, 0x9d, 0x0e, 0x58, 0x05, 0x6e, 0x65, 0x31,
+      0x04, 0x92, 0x5b, 0x9f, 0xe6, 0xc9,
+  };
+
+  const uint8_t *ptr = kSampleKey;
+  bssl::UniquePtr<PKCS8_PRIV_KEY_INFO> key(
+      d2i_PKCS8_PRIV_KEY_INFO(nullptr, &ptr, sizeof(kSampleKey)));
+  if (!key || ptr != kSampleKey + sizeof(kSampleKey)) {
+    return false;
+  }
+
+  bssl::UniquePtr<X509_SIG> encrypted(PKCS8_encrypt(
+      pbe_nid, cipher, password, -1, salt, salt_len, iterations, key.get()));
+  if (!encrypted) {
+    fprintf(stderr, "Failed to encrypt private key.\n");
+    return false;
+  }
+
+  bssl::UniquePtr<PKCS8_PRIV_KEY_INFO> key2(
+      PKCS8_decrypt(encrypted.get(), password, -1));
+  if (!key2) {
+    fprintf(stderr, "Failed to decrypt private key.\n");
+    return false;
+  }
+
+  uint8_t *encoded = nullptr;
+  int len = i2d_PKCS8_PRIV_KEY_INFO(key2.get(), &encoded);
+  bssl::UniquePtr<uint8_t> free_encoded(encoded);
+  if (len < 0 ||
+      static_cast<size_t>(len) != sizeof(kSampleKey) ||
+      OPENSSL_memcmp(encoded, kSampleKey, sizeof(kSampleKey)) != 0) {
+    fprintf(stderr, "Decrypted private key did not round-trip.");
+    return false;
+  }
+
+  return true;
+}
+
 int main(int argc, char **argv) {
-  if (!test(kDER, sizeof(kDER))) {
+  CRYPTO_library_init();
+
+  if (!TestDecrypt(kDER, sizeof(kDER), "testing") ||
+      !TestDecrypt(kNullPassword, sizeof(kNullPassword), NULL) ||
+      !TestDecrypt(kNullPasswordNSS, sizeof(kNullPasswordNSS), NULL) ||
+      !TestDecrypt(kEmptyPasswordOpenSSL, sizeof(kEmptyPasswordOpenSSL), "") ||
+      !TestDecrypt(kExplicitHMACWithSHA1, sizeof(kExplicitHMACWithSHA1),
+                   "foo") ||
+      !TestRoundTrip(NID_pbe_WithSHA1And3_Key_TripleDES_CBC, nullptr,
+                     "password", nullptr, 0, 10) ||
+      // Vary the salt
+      !TestRoundTrip(NID_pbe_WithSHA1And3_Key_TripleDES_CBC, nullptr,
+                     "password", nullptr, 4, 10) ||
+      !TestRoundTrip(NID_pbe_WithSHA1And3_Key_TripleDES_CBC, nullptr,
+                     "password", (const uint8_t *)"salt", 4, 10) ||
+      // Vary the iteration count.
+      !TestRoundTrip(NID_pbe_WithSHA1And3_Key_TripleDES_CBC, nullptr,
+                     "password", nullptr, 0, 1) ||
+      // Vary the password.
+      !TestRoundTrip(NID_pbe_WithSHA1And3_Key_TripleDES_CBC, nullptr, "",
+                     nullptr, 0, 1) ||
+      !TestRoundTrip(NID_pbe_WithSHA1And3_Key_TripleDES_CBC, nullptr, nullptr,
+                     nullptr, 0, 1) ||
+      // Vary the PBE suite.
+      !TestRoundTrip(NID_pbe_WithSHA1And40BitRC2_CBC, nullptr, "password",
+                     nullptr, 0, 10) ||
+      !TestRoundTrip(NID_pbe_WithSHA1And128BitRC4, nullptr, "password", nullptr,
+                     0, 10) ||
+      // Test PBES2.
+      !TestRoundTrip(-1, EVP_aes_128_cbc(), "password", nullptr, 0, 10) ||
+      !TestRoundTrip(-1, EVP_aes_128_cbc(), "password", nullptr, 4, 10) ||
+      !TestRoundTrip(-1, EVP_aes_128_cbc(), "password", (const uint8_t *)"salt",
+                     4, 10) ||
+      !TestRoundTrip(-1, EVP_aes_128_cbc(), "password", nullptr, 0, 1) ||
+      !TestRoundTrip(-1, EVP_rc2_cbc(), "password", nullptr, 0, 10)) {
     return 1;
   }
 
diff --git a/src/crypto/pkcs8/pkcs8_x509.c b/src/crypto/pkcs8/pkcs8_x509.c
new file mode 100644
index 0000000..242f911
--- /dev/null
+++ b/src/crypto/pkcs8/pkcs8_x509.c
@@ -0,0 +1,790 @@
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 1999.
+ */
+/* ====================================================================
+ * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com). */
+
+#include <openssl/pkcs8.h>
+
+#include <limits.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/asn1.h>
+#include <openssl/bio.h>
+#include <openssl/buf.h>
+#include <openssl/bytestring.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/digest.h>
+#include <openssl/hmac.h>
+#include <openssl/mem.h>
+#include <openssl/x509.h>
+
+#include "internal.h"
+#include "../bytestring/internal.h"
+#include "../digest/internal.h"
+#include "../internal.h"
+
+
+/* Minor tweak to operation: zero private key data */
+static int pkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
+                   void *exarg) {
+  /* Since the structure must still be valid use ASN1_OP_FREE_PRE */
+  if (operation == ASN1_OP_FREE_PRE) {
+    PKCS8_PRIV_KEY_INFO *key = (PKCS8_PRIV_KEY_INFO *)*pval;
+    if (key->pkey && key->pkey->type == V_ASN1_OCTET_STRING &&
+        key->pkey->value.octet_string) {
+      OPENSSL_cleanse(key->pkey->value.octet_string->data,
+                      key->pkey->value.octet_string->length);
+    }
+  }
+  return 1;
+}
+
+ASN1_SEQUENCE_cb(PKCS8_PRIV_KEY_INFO, pkey_cb) = {
+  ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, version, ASN1_INTEGER),
+  ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkeyalg, X509_ALGOR),
+  ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkey, ASN1_ANY),
+  ASN1_IMP_SET_OF_OPT(PKCS8_PRIV_KEY_INFO, attributes, X509_ATTRIBUTE, 0)
+} ASN1_SEQUENCE_END_cb(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO)
+
+IMPLEMENT_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO)
+
+EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8) {
+  uint8_t *der = NULL;
+  int der_len = i2d_PKCS8_PRIV_KEY_INFO(p8, &der);
+  if (der_len < 0) {
+    return NULL;
+  }
+
+  CBS cbs;
+  CBS_init(&cbs, der, (size_t)der_len);
+  EVP_PKEY *ret = EVP_parse_private_key(&cbs);
+  if (ret == NULL || CBS_len(&cbs) != 0) {
+    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
+    EVP_PKEY_free(ret);
+    OPENSSL_free(der);
+    return NULL;
+  }
+
+  OPENSSL_free(der);
+  return ret;
+}
+
+PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey) {
+  CBB cbb;
+  uint8_t *der = NULL;
+  size_t der_len;
+  if (!CBB_init(&cbb, 0) ||
+      !EVP_marshal_private_key(&cbb, pkey) ||
+      !CBB_finish(&cbb, &der, &der_len) ||
+      der_len > LONG_MAX) {
+    CBB_cleanup(&cbb);
+    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_ENCODE_ERROR);
+    goto err;
+  }
+
+  const uint8_t *p = der;
+  PKCS8_PRIV_KEY_INFO *p8 = d2i_PKCS8_PRIV_KEY_INFO(NULL, &p, (long)der_len);
+  if (p8 == NULL || p != der + der_len) {
+    PKCS8_PRIV_KEY_INFO_free(p8);
+    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_DECODE_ERROR);
+    goto err;
+  }
+
+  OPENSSL_free(der);
+  return p8;
+
+err:
+  OPENSSL_free(der);
+  return NULL;
+}
+
+PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(X509_SIG *pkcs8, const char *pass,
+                                   int pass_len_in) {
+  size_t pass_len;
+  if (pass_len_in == -1 && pass != NULL) {
+    pass_len = strlen(pass);
+  } else {
+    pass_len = (size_t)pass_len_in;
+  }
+
+  PKCS8_PRIV_KEY_INFO *ret = NULL;
+  EVP_PKEY *pkey = NULL;
+  uint8_t *in = NULL;
+
+  /* Convert the legacy ASN.1 object to a byte string. */
+  int in_len = i2d_X509_SIG(pkcs8, &in);
+  if (in_len < 0) {
+    goto err;
+  }
+
+  CBS cbs;
+  CBS_init(&cbs, in, in_len);
+  pkey = PKCS8_parse_encrypted_private_key(&cbs, pass, pass_len);
+  if (pkey == NULL || CBS_len(&cbs) != 0) {
+    goto err;
+  }
+
+  ret = EVP_PKEY2PKCS8(pkey);
+
+err:
+  OPENSSL_free(in);
+  EVP_PKEY_free(pkey);
+  return ret;
+}
+
+X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher, const char *pass,
+                        int pass_len_in, const uint8_t *salt, size_t salt_len,
+                        int iterations, PKCS8_PRIV_KEY_INFO *p8inf) {
+  size_t pass_len;
+  if (pass_len_in == -1 && pass != NULL) {
+    pass_len = strlen(pass);
+  } else {
+    pass_len = (size_t)pass_len_in;
+  }
+
+  /* Parse out the private key. */
+  EVP_PKEY *pkey = EVP_PKCS82PKEY(p8inf);
+  if (pkey == NULL) {
+    return NULL;
+  }
+
+  X509_SIG *ret = NULL;
+  uint8_t *der = NULL;
+  size_t der_len;
+  CBB cbb;
+  if (!CBB_init(&cbb, 128) ||
+      !PKCS8_marshal_encrypted_private_key(&cbb, pbe_nid, cipher, pass,
+                                           pass_len, salt, salt_len, iterations,
+                                           pkey) ||
+      !CBB_finish(&cbb, &der, &der_len)) {
+    CBB_cleanup(&cbb);
+    goto err;
+  }
+
+  /* Convert back to legacy ASN.1 objects. */
+  const uint8_t *ptr = der;
+  ret = d2i_X509_SIG(NULL, &ptr, der_len);
+  if (ret == NULL || ptr != der + der_len) {
+    OPENSSL_PUT_ERROR(PKCS8, ERR_R_INTERNAL_ERROR);
+    X509_SIG_free(ret);
+    ret = NULL;
+  }
+
+err:
+  OPENSSL_free(der);
+  EVP_PKEY_free(pkey);
+  return ret;
+}
+
+struct pkcs12_context {
+  EVP_PKEY **out_key;
+  STACK_OF(X509) *out_certs;
+  const char *password;
+  size_t password_len;
+};
+
+/* PKCS12_handle_sequence parses a BER-encoded SEQUENCE of elements in a PKCS#12
+ * structure. */
+static int PKCS12_handle_sequence(
+    CBS *sequence, struct pkcs12_context *ctx,
+    int (*handle_element)(CBS *cbs, struct pkcs12_context *ctx)) {
+  uint8_t *der_bytes = NULL;
+  size_t der_len;
+  CBS in;
+  int ret = 0;
+
+  /* Although a BER->DER conversion is done at the beginning of |PKCS12_parse|,
+   * the ASN.1 data gets wrapped in OCTETSTRINGs and/or encrypted and the
+   * conversion cannot see through those wrappings. So each time we step
+   * through one we need to convert to DER again. */
+  if (!CBS_asn1_ber_to_der(sequence, &der_bytes, &der_len)) {
+    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
+    return 0;
+  }
+
+  if (der_bytes != NULL) {
+    CBS_init(&in, der_bytes, der_len);
+  } else {
+    CBS_init(&in, CBS_data(sequence), CBS_len(sequence));
+  }
+
+  CBS child;
+  if (!CBS_get_asn1(&in, &child, CBS_ASN1_SEQUENCE) ||
+      CBS_len(&in) != 0) {
+    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
+    goto err;
+  }
+
+  while (CBS_len(&child) > 0) {
+    CBS element;
+    if (!CBS_get_asn1(&child, &element, CBS_ASN1_SEQUENCE)) {
+      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
+      goto err;
+    }
+
+    if (!handle_element(&element, ctx)) {
+      goto err;
+    }
+  }
+
+  ret = 1;
+
+err:
+  OPENSSL_free(der_bytes);
+  return ret;
+}
+
+/* 1.2.840.113549.1.12.10.1.2 */
+static const uint8_t kPKCS8ShroudedKeyBag[] = {
+    0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x0c, 0x0a, 0x01, 0x02};
+
+/* 1.2.840.113549.1.12.10.1.3 */
+static const uint8_t kCertBag[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+                                   0x01, 0x0c, 0x0a, 0x01, 0x03};
+
+/* 1.2.840.113549.1.9.22.1 */
+static const uint8_t kX509Certificate[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
+                                           0x0d, 0x01, 0x09, 0x16, 0x01};
+
+/* PKCS12_handle_safe_bag parses a single SafeBag element in a PKCS#12
+ * structure. */
+static int PKCS12_handle_safe_bag(CBS *safe_bag, struct pkcs12_context *ctx) {
+  CBS bag_id, wrapped_value;
+  if (!CBS_get_asn1(safe_bag, &bag_id, CBS_ASN1_OBJECT) ||
+      !CBS_get_asn1(safe_bag, &wrapped_value,
+                        CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)
+      /* Ignore the bagAttributes field. */) {
+    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
+    return 0;
+  }
+
+  if (CBS_mem_equal(&bag_id, kPKCS8ShroudedKeyBag,
+                    sizeof(kPKCS8ShroudedKeyBag))) {
+    /* See RFC 7292, section 4.2.2. */
+    if (*ctx->out_key) {
+      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_MULTIPLE_PRIVATE_KEYS_IN_PKCS12);
+      return 0;
+    }
+
+    EVP_PKEY *pkey = PKCS8_parse_encrypted_private_key(
+        &wrapped_value, ctx->password, ctx->password_len);
+    if (pkey == NULL) {
+      return 0;
+    }
+
+    if (CBS_len(&wrapped_value) != 0) {
+      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
+      EVP_PKEY_free(pkey);
+      return 0;
+    }
+
+    *ctx->out_key = pkey;
+    return 1;
+  }
+
+  if (CBS_mem_equal(&bag_id, kCertBag, sizeof(kCertBag))) {
+    /* See RFC 7292, section 4.2.3. */
+    CBS cert_bag, cert_type, wrapped_cert, cert;
+    if (!CBS_get_asn1(&wrapped_value, &cert_bag, CBS_ASN1_SEQUENCE) ||
+        !CBS_get_asn1(&cert_bag, &cert_type, CBS_ASN1_OBJECT) ||
+        !CBS_get_asn1(&cert_bag, &wrapped_cert,
+                      CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
+        !CBS_get_asn1(&wrapped_cert, &cert, CBS_ASN1_OCTETSTRING)) {
+      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
+      return 0;
+    }
+
+    /* Skip unknown certificate types. */
+    if (!CBS_mem_equal(&cert_type, kX509Certificate,
+                       sizeof(kX509Certificate))) {
+      return 1;
+    }
+
+    if (CBS_len(&cert) > LONG_MAX) {
+      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
+      return 0;
+    }
+
+    const uint8_t *inp = CBS_data(&cert);
+    X509 *x509 = d2i_X509(NULL, &inp, (long)CBS_len(&cert));
+    if (!x509) {
+      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
+      return 0;
+    }
+
+    if (inp != CBS_data(&cert) + CBS_len(&cert)) {
+      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
+      X509_free(x509);
+      return 0;
+    }
+
+    if (0 == sk_X509_push(ctx->out_certs, x509)) {
+      X509_free(x509);
+      return 0;
+    }
+
+    return 1;
+  }
+
+  /* Unknown element type - ignore it. */
+  return 1;
+}
+
+/* 1.2.840.113549.1.7.1 */
+static const uint8_t kPKCS7Data[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
+                                     0x0d, 0x01, 0x07, 0x01};
+
+/* 1.2.840.113549.1.7.6 */
+static const uint8_t kPKCS7EncryptedData[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
+                                              0x0d, 0x01, 0x07, 0x06};
+
+/* PKCS12_handle_content_info parses a single PKCS#7 ContentInfo element in a
+ * PKCS#12 structure. */
+static int PKCS12_handle_content_info(CBS *content_info,
+                                      struct pkcs12_context *ctx) {
+  CBS content_type, wrapped_contents, contents;
+  int ret = 0;
+  uint8_t *storage = NULL;
+
+  if (!CBS_get_asn1(content_info, &content_type, CBS_ASN1_OBJECT) ||
+      !CBS_get_asn1(content_info, &wrapped_contents,
+                        CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
+      CBS_len(content_info) != 0) {
+    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
+    goto err;
+  }
+
+  if (CBS_mem_equal(&content_type, kPKCS7EncryptedData,
+                    sizeof(kPKCS7EncryptedData))) {
+    /* See https://tools.ietf.org/html/rfc2315#section-13.
+     *
+     * PKCS#7 encrypted data inside a PKCS#12 structure is generally an
+     * encrypted certificate bag and it's generally encrypted with 40-bit
+     * RC2-CBC. */
+    CBS version_bytes, eci, contents_type, ai, encrypted_contents;
+    uint8_t *out;
+    size_t out_len;
+
+    if (!CBS_get_asn1(&wrapped_contents, &contents, CBS_ASN1_SEQUENCE) ||
+        !CBS_get_asn1(&contents, &version_bytes, CBS_ASN1_INTEGER) ||
+        /* EncryptedContentInfo, see
+         * https://tools.ietf.org/html/rfc2315#section-10.1 */
+        !CBS_get_asn1(&contents, &eci, CBS_ASN1_SEQUENCE) ||
+        !CBS_get_asn1(&eci, &contents_type, CBS_ASN1_OBJECT) ||
+        /* AlgorithmIdentifier, see
+         * https://tools.ietf.org/html/rfc5280#section-4.1.1.2 */
+        !CBS_get_asn1(&eci, &ai, CBS_ASN1_SEQUENCE) ||
+        !CBS_get_asn1_implicit_string(
+            &eci, &encrypted_contents, &storage,
+            CBS_ASN1_CONTEXT_SPECIFIC | 0, CBS_ASN1_OCTETSTRING)) {
+      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
+      goto err;
+    }
+
+    if (!CBS_mem_equal(&contents_type, kPKCS7Data, sizeof(kPKCS7Data))) {
+      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
+      goto err;
+    }
+
+    if (!pkcs8_pbe_decrypt(&out, &out_len, &ai, ctx->password,
+                           ctx->password_len, CBS_data(&encrypted_contents),
+                           CBS_len(&encrypted_contents))) {
+      goto err;
+    }
+
+    CBS safe_contents;
+    CBS_init(&safe_contents, out, out_len);
+    ret = PKCS12_handle_sequence(&safe_contents, ctx, PKCS12_handle_safe_bag);
+    OPENSSL_free(out);
+  } else if (CBS_mem_equal(&content_type, kPKCS7Data, sizeof(kPKCS7Data))) {
+    CBS octet_string_contents;
+
+    if (!CBS_get_asn1(&wrapped_contents, &octet_string_contents,
+                      CBS_ASN1_OCTETSTRING)) {
+      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
+      goto err;
+    }
+
+    ret = PKCS12_handle_sequence(&octet_string_contents, ctx,
+                                 PKCS12_handle_safe_bag);
+  } else {
+    /* Unknown element type - ignore it. */
+    ret = 1;
+  }
+
+err:
+  OPENSSL_free(storage);
+  return ret;
+}
+
+int PKCS12_get_key_and_certs(EVP_PKEY **out_key, STACK_OF(X509) *out_certs,
+                             CBS *ber_in, const char *password) {
+  uint8_t *der_bytes = NULL;
+  size_t der_len;
+  CBS in, pfx, mac_data, authsafe, content_type, wrapped_authsafes, authsafes;
+  uint64_t version;
+  int ret = 0;
+  struct pkcs12_context ctx;
+  const size_t original_out_certs_len = sk_X509_num(out_certs);
+
+  /* The input may be in BER format. */
+  if (!CBS_asn1_ber_to_der(ber_in, &der_bytes, &der_len)) {
+    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
+    return 0;
+  }
+  if (der_bytes != NULL) {
+    CBS_init(&in, der_bytes, der_len);
+  } else {
+    CBS_init(&in, CBS_data(ber_in), CBS_len(ber_in));
+  }
+
+  *out_key = NULL;
+  OPENSSL_memset(&ctx, 0, sizeof(ctx));
+
+  /* See ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1.pdf, section
+   * four. */
+  if (!CBS_get_asn1(&in, &pfx, CBS_ASN1_SEQUENCE) ||
+      CBS_len(&in) != 0 ||
+      !CBS_get_asn1_uint64(&pfx, &version)) {
+    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
+    goto err;
+  }
+
+  if (version < 3) {
+    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_VERSION);
+    goto err;
+  }
+
+  if (!CBS_get_asn1(&pfx, &authsafe, CBS_ASN1_SEQUENCE)) {
+    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
+    goto err;
+  }
+
+  if (CBS_len(&pfx) == 0) {
+    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_MISSING_MAC);
+    goto err;
+  }
+
+  if (!CBS_get_asn1(&pfx, &mac_data, CBS_ASN1_SEQUENCE)) {
+    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
+    goto err;
+  }
+
+  /* authsafe is a PKCS#7 ContentInfo. See
+   * https://tools.ietf.org/html/rfc2315#section-7. */
+  if (!CBS_get_asn1(&authsafe, &content_type, CBS_ASN1_OBJECT) ||
+      !CBS_get_asn1(&authsafe, &wrapped_authsafes,
+                        CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)) {
+    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
+    goto err;
+  }
+
+  /* The content type can either be data or signedData. The latter indicates
+   * that it's signed by a public key, which isn't supported. */
+  if (!CBS_mem_equal(&content_type, kPKCS7Data, sizeof(kPKCS7Data))) {
+    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_PKCS12_PUBLIC_KEY_INTEGRITY_NOT_SUPPORTED);
+    goto err;
+  }
+
+  if (!CBS_get_asn1(&wrapped_authsafes, &authsafes, CBS_ASN1_OCTETSTRING)) {
+    OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
+    goto err;
+  }
+
+  ctx.out_key = out_key;
+  ctx.out_certs = out_certs;
+  ctx.password = password;
+  ctx.password_len = password != NULL ? strlen(password) : 0;
+
+  /* Verify the MAC. */
+  {
+    CBS mac, salt, expected_mac;
+    if (!CBS_get_asn1(&mac_data, &mac, CBS_ASN1_SEQUENCE)) {
+      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
+      goto err;
+    }
+
+    const EVP_MD *md = EVP_parse_digest_algorithm(&mac);
+    if (md == NULL) {
+      goto err;
+    }
+
+    if (!CBS_get_asn1(&mac, &expected_mac, CBS_ASN1_OCTETSTRING) ||
+        !CBS_get_asn1(&mac_data, &salt, CBS_ASN1_OCTETSTRING)) {
+      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
+      goto err;
+    }
+
+    /* The iteration count is optional and the default is one. */
+    uint64_t iterations = 1;
+    if (CBS_len(&mac_data) > 0) {
+      if (!CBS_get_asn1_uint64(&mac_data, &iterations) ||
+          iterations > UINT_MAX) {
+        OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_BAD_PKCS12_DATA);
+        goto err;
+      }
+    }
+
+    uint8_t hmac_key[EVP_MAX_MD_SIZE];
+    if (!pkcs12_key_gen(ctx.password, ctx.password_len, CBS_data(&salt),
+                        CBS_len(&salt), PKCS12_MAC_ID, iterations,
+                        EVP_MD_size(md), hmac_key, md)) {
+      goto err;
+    }
+
+    uint8_t hmac[EVP_MAX_MD_SIZE];
+    unsigned hmac_len;
+    if (NULL == HMAC(md, hmac_key, EVP_MD_size(md), CBS_data(&authsafes),
+                     CBS_len(&authsafes), hmac, &hmac_len)) {
+      goto err;
+    }
+
+    if (!CBS_mem_equal(&expected_mac, hmac, hmac_len)) {
+      OPENSSL_PUT_ERROR(PKCS8, PKCS8_R_INCORRECT_PASSWORD);
+      goto err;
+    }
+  }
+
+  /* authsafes contains a series of PKCS#7 ContentInfos. */
+  if (!PKCS12_handle_sequence(&authsafes, &ctx, PKCS12_handle_content_info)) {
+    goto err;
+  }
+
+  ret = 1;
+
+err:
+  OPENSSL_free(der_bytes);
+  if (!ret) {
+    EVP_PKEY_free(*out_key);
+    *out_key = NULL;
+    while (sk_X509_num(out_certs) > original_out_certs_len) {
+      X509 *x509 = sk_X509_pop(out_certs);
+      X509_free(x509);
+    }
+  }
+
+  return ret;
+}
+
+void PKCS12_PBE_add(void) {}
+
+struct pkcs12_st {
+  uint8_t *ber_bytes;
+  size_t ber_len;
+};
+
+PKCS12 *d2i_PKCS12(PKCS12 **out_p12, const uint8_t **ber_bytes,
+                   size_t ber_len) {
+  PKCS12 *p12;
+
+  p12 = OPENSSL_malloc(sizeof(PKCS12));
+  if (!p12) {
+    return NULL;
+  }
+
+  p12->ber_bytes = OPENSSL_malloc(ber_len);
+  if (!p12->ber_bytes) {
+    OPENSSL_free(p12);
+    return NULL;
+  }
+
+  OPENSSL_memcpy(p12->ber_bytes, *ber_bytes, ber_len);
+  p12->ber_len = ber_len;
+  *ber_bytes += ber_len;
+
+  if (out_p12) {
+    PKCS12_free(*out_p12);
+
+    *out_p12 = p12;
+  }
+
+  return p12;
+}
+
+PKCS12* d2i_PKCS12_bio(BIO *bio, PKCS12 **out_p12) {
+  size_t used = 0;
+  BUF_MEM *buf;
+  const uint8_t *dummy;
+  static const size_t kMaxSize = 256 * 1024;
+  PKCS12 *ret = NULL;
+
+  buf = BUF_MEM_new();
+  if (buf == NULL) {
+    return NULL;
+  }
+  if (BUF_MEM_grow(buf, 8192) == 0) {
+    goto out;
+  }
+
+  for (;;) {
+    int n = BIO_read(bio, &buf->data[used], buf->length - used);
+    if (n < 0) {
+      if (used == 0) {
+        goto out;
+      }
+      /* Workaround a bug in node.js. It uses a memory BIO for this in the wrong
+       * mode. */
+      n = 0;
+    }
+
+    if (n == 0) {
+      break;
+    }
+    used += n;
+
+    if (used < buf->length) {
+      continue;
+    }
+
+    if (buf->length > kMaxSize ||
+        BUF_MEM_grow(buf, buf->length * 2) == 0) {
+      goto out;
+    }
+  }
+
+  dummy = (uint8_t*) buf->data;
+  ret = d2i_PKCS12(out_p12, &dummy, used);
+
+out:
+  BUF_MEM_free(buf);
+  return ret;
+}
+
+PKCS12* d2i_PKCS12_fp(FILE *fp, PKCS12 **out_p12) {
+  BIO *bio;
+  PKCS12 *ret;
+
+  bio = BIO_new_fp(fp, 0 /* don't take ownership */);
+  if (!bio) {
+    return NULL;
+  }
+
+  ret = d2i_PKCS12_bio(bio, out_p12);
+  BIO_free(bio);
+  return ret;
+}
+
+int PKCS12_parse(const PKCS12 *p12, const char *password, EVP_PKEY **out_pkey,
+                 X509 **out_cert, STACK_OF(X509) **out_ca_certs) {
+  CBS ber_bytes;
+  STACK_OF(X509) *ca_certs = NULL;
+  char ca_certs_alloced = 0;
+
+  if (out_ca_certs != NULL && *out_ca_certs != NULL) {
+    ca_certs = *out_ca_certs;
+  }
+
+  if (!ca_certs) {
+    ca_certs = sk_X509_new_null();
+    if (ca_certs == NULL) {
+      OPENSSL_PUT_ERROR(PKCS8, ERR_R_MALLOC_FAILURE);
+      return 0;
+    }
+    ca_certs_alloced = 1;
+  }
+
+  CBS_init(&ber_bytes, p12->ber_bytes, p12->ber_len);
+  if (!PKCS12_get_key_and_certs(out_pkey, ca_certs, &ber_bytes, password)) {
+    if (ca_certs_alloced) {
+      sk_X509_free(ca_certs);
+    }
+    return 0;
+  }
+
+  *out_cert = NULL;
+  if (sk_X509_num(ca_certs) > 0) {
+    *out_cert = sk_X509_shift(ca_certs);
+  }
+
+  if (out_ca_certs) {
+    *out_ca_certs = ca_certs;
+  } else {
+    sk_X509_pop_free(ca_certs, X509_free);
+  }
+
+  return 1;
+}
+
+int PKCS12_verify_mac(const PKCS12 *p12, const char *password,
+                      int password_len) {
+  if (password == NULL) {
+    if (password_len != 0) {
+      return 0;
+    }
+  } else if (password_len != -1 &&
+             (password[password_len] != 0 ||
+              OPENSSL_memchr(password, 0, password_len) != NULL)) {
+    return 0;
+  }
+
+  EVP_PKEY *pkey = NULL;
+  X509 *cert = NULL;
+  if (!PKCS12_parse(p12, password, &pkey, &cert, NULL)) {
+    ERR_clear_error();
+    return 0;
+  }
+
+  EVP_PKEY_free(pkey);
+  X509_free(cert);
+
+  return 1;
+}
+
+void PKCS12_free(PKCS12 *p12) {
+  if (p12 == NULL) {
+    return;
+  }
+  OPENSSL_free(p12->ber_bytes);
+  OPENSSL_free(p12);
+}
diff --git a/src/crypto/poly1305/internal.h b/src/crypto/poly1305/internal.h
new file mode 100644
index 0000000..df6769e
--- /dev/null
+++ b/src/crypto/poly1305/internal.h
@@ -0,0 +1,40 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#ifndef OPENSSL_HEADER_POLY1305_INTERNAL_H
+#define OPENSSL_HEADER_POLY1305_INTERNAL_H
+
+#include <openssl/base.h>
+#include <openssl/poly1305.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
+void CRYPTO_poly1305_init_neon(poly1305_state *state, const uint8_t key[32]);
+
+void CRYPTO_poly1305_update_neon(poly1305_state *state, const uint8_t *in,
+                                 size_t in_len);
+
+void CRYPTO_poly1305_finish_neon(poly1305_state *state, uint8_t mac[16]);
+#endif
+
+
+#if defined(__cplusplus)
+}  /* extern C */
+#endif
+
+#endif  /* OPENSSL_HEADER_POLY1305_INTERNAL_H */
diff --git a/src/crypto/poly1305/poly1305.c b/src/crypto/poly1305/poly1305.c
index 5a49e2d..77e8046 100644
--- a/src/crypto/poly1305/poly1305.c
+++ b/src/crypto/poly1305/poly1305.c
@@ -22,40 +22,22 @@
 
 #include <openssl/cpu.h>
 
+#include "internal.h"
+#include "../internal.h"
+
 
 #if defined(OPENSSL_WINDOWS) || !defined(OPENSSL_X86_64)
 
-#if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || defined(OPENSSL_ARM)
 /* We can assume little-endian. */
 static uint32_t U8TO32_LE(const uint8_t *m) {
   uint32_t r;
-  memcpy(&r, m, sizeof(r));
+  OPENSSL_memcpy(&r, m, sizeof(r));
   return r;
 }
 
-static void U32TO8_LE(uint8_t *m, uint32_t v) { memcpy(m, &v, sizeof(v)); }
-#else
-static uint32_t U8TO32_LE(const uint8_t *m) {
-  return (uint32_t)m[0] | (uint32_t)m[1] << 8 | (uint32_t)m[2] << 16 |
-         (uint32_t)m[3] << 24;
-}
-
 static void U32TO8_LE(uint8_t *m, uint32_t v) {
-  m[0] = v;
-  m[1] = v >> 8;
-  m[2] = v >> 16;
-  m[3] = v >> 24;
+  OPENSSL_memcpy(m, &v, sizeof(v));
 }
-#endif
-
-#if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
-void CRYPTO_poly1305_init_neon(poly1305_state *state, const uint8_t key[32]);
-
-void CRYPTO_poly1305_update_neon(poly1305_state *state, const uint8_t *in,
-                                 size_t in_len);
-
-void CRYPTO_poly1305_finish_neon(poly1305_state *state, uint8_t mac[16]);
-#endif
 
 static uint64_t mul32x32_64(uint32_t a, uint32_t b) { return (uint64_t)a * b; }
 
@@ -68,6 +50,11 @@
   uint8_t key[16];
 };
 
+static inline struct poly1305_state_st *poly1305_aligned_state(
+    poly1305_state *state) {
+  return (struct poly1305_state_st *)(((uintptr_t)state + 63) & ~63);
+}
+
 /* poly1305_blocks updates |state| given some amount of input data. This
  * function may only be called with a |len| that is not a multiple of 16 at the
  * end of the data. Otherwise the input must be buffered into 16 byte blocks. */
@@ -166,11 +153,11 @@
 }
 
 void CRYPTO_poly1305_init(poly1305_state *statep, const uint8_t key[32]) {
-  struct poly1305_state_st *state = (struct poly1305_state_st *)statep;
+  struct poly1305_state_st *state = poly1305_aligned_state(statep);
   uint32_t t0, t1, t2, t3;
 
 #if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
-  if (CRYPTO_is_NEON_functional()) {
+  if (CRYPTO_is_NEON_capable()) {
     CRYPTO_poly1305_init_neon(statep, key);
     return;
   }
@@ -208,25 +195,25 @@
   state->h4 = 0;
 
   state->buf_used = 0;
-  memcpy(state->key, key + 16, sizeof(state->key));
+  OPENSSL_memcpy(state->key, key + 16, sizeof(state->key));
 }
 
 void CRYPTO_poly1305_update(poly1305_state *statep, const uint8_t *in,
                             size_t in_len) {
   unsigned int i;
-  struct poly1305_state_st *state = (struct poly1305_state_st *)statep;
+  struct poly1305_state_st *state = poly1305_aligned_state(statep);
 
 #if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
-  if (CRYPTO_is_NEON_functional()) {
+  if (CRYPTO_is_NEON_capable()) {
     CRYPTO_poly1305_update_neon(statep, in, in_len);
     return;
   }
 #endif
 
   if (state->buf_used) {
-    unsigned int todo = 16 - state->buf_used;
+    unsigned todo = 16 - state->buf_used;
     if (todo > in_len) {
-      todo = in_len;
+      todo = (unsigned)in_len;
     }
     for (i = 0; i < todo; i++) {
       state->buf[state->buf_used + i] = in[i];
@@ -252,18 +239,18 @@
     for (i = 0; i < in_len; i++) {
       state->buf[i] = in[i];
     }
-    state->buf_used = in_len;
+    state->buf_used = (unsigned)in_len;
   }
 }
 
 void CRYPTO_poly1305_finish(poly1305_state *statep, uint8_t mac[16]) {
-  struct poly1305_state_st *state = (struct poly1305_state_st *)statep;
+  struct poly1305_state_st *state = poly1305_aligned_state(statep);
   uint64_t f0, f1, f2, f3;
   uint32_t g0, g1, g2, g3, g4;
   uint32_t b, nb;
 
 #if defined(OPENSSL_ARM) && !defined(OPENSSL_NO_ASM)
-  if (CRYPTO_is_NEON_functional()) {
+  if (CRYPTO_is_NEON_capable()) {
     CRYPTO_poly1305_finish_neon(statep, mac);
     return;
   }
diff --git a/src/crypto/poly1305/poly1305_arm.c b/src/crypto/poly1305/poly1305_arm.c
index 5e78dc0..444413b 100644
--- a/src/crypto/poly1305/poly1305_arm.c
+++ b/src/crypto/poly1305/poly1305_arm.c
@@ -21,6 +21,9 @@
 
 #include <string.h>
 
+#include "../internal.h"
+#include "internal.h"
+
 
 typedef struct {
   uint32_t v[12]; /* for alignment; only using 10 */
@@ -126,7 +129,7 @@
  * fe1305x2_frombytearray. */
 static uint32_t load32(uint8_t *t) {
   uint32_t tmp;
-  memcpy(&tmp, t, sizeof(tmp));
+  OPENSSL_memcpy(&tmp, t, sizeof(tmp));
   return tmp;
 }
 
@@ -170,7 +173,7 @@
   }
 }
 
-static const fe1305x2 zero __attribute__((aligned(16)));
+static const alignas(16) fe1305x2 zero;
 
 struct poly1305_state_st {
   uint8_t data[sizeof(fe1305x2[5]) + 128];
@@ -200,7 +203,7 @@
   addmulmod(precomp, r, r, &zero);                 /* precompute r^2 */
   addmulmod(precomp + 1, precomp, precomp, &zero); /* precompute r^4 */
 
-  memcpy(st->key, key + 16, 16);
+  OPENSSL_memcpy(st->key, key + 16, 16);
   st->buf_used = 0;
 }
 
diff --git a/src/crypto/poly1305/poly1305_test.cc b/src/crypto/poly1305/poly1305_test.cc
index 3a72668..2c25e93 100644
--- a/src/crypto/poly1305/poly1305_test.cc
+++ b/src/crypto/poly1305/poly1305_test.cc
@@ -20,16 +20,57 @@
 #include <openssl/crypto.h>
 #include <openssl/poly1305.h>
 
+#include "../internal.h"
 #include "../test/file_test.h"
 
 
-// |CRYPTO_poly1305_finish| requires a 16-byte-aligned output.
-#if defined(OPENSSL_WINDOWS)
-// MSVC doesn't support C++11 |alignas|.
-#define ALIGNED __declspec(align(16))
-#else
-#define ALIGNED alignas(16)
-#endif
+static bool TestSIMD(FileTest *t, unsigned excess,
+                     const std::vector<uint8_t> &key,
+                     const std::vector<uint8_t> &in,
+                     const std::vector<uint8_t> &mac) {
+  poly1305_state state;
+  CRYPTO_poly1305_init(&state, key.data());
+
+  size_t done = 0;
+
+  // Feed 16 bytes in. Some implementations begin in non-SIMD mode and upgrade
+  // on-demand. Stress the upgrade path.
+  size_t todo = 16;
+  if (todo > in.size()) {
+    todo = in.size();
+  }
+  CRYPTO_poly1305_update(&state, in.data(), todo);
+  done += todo;
+
+  for (;;) {
+    // Feed 128 + |excess| bytes to test SIMD mode.
+    if (done + 128 + excess > in.size()) {
+      break;
+    }
+    CRYPTO_poly1305_update(&state, in.data() + done, 128 + excess);
+    done += 128 + excess;
+
+    // Feed |excess| bytes to ensure SIMD mode can handle short inputs.
+    if (done + excess > in.size()) {
+      break;
+    }
+    CRYPTO_poly1305_update(&state, in.data() + done, excess);
+    done += excess;
+  }
+
+  // Consume the remainder and finish.
+  CRYPTO_poly1305_update(&state, in.data() + done, in.size() - done);
+
+  // |CRYPTO_poly1305_finish| requires a 16-byte-aligned output.
+  alignas(16) uint8_t out[16];
+  CRYPTO_poly1305_finish(&state, out);
+  if (!t->ExpectBytesEqual(mac.data(), mac.size(), out, 16)) {
+    t->PrintLine("SIMD pattern %u failed.", excess);
+    return false;
+  }
+
+  return true;
+}
 
 static bool TestPoly1305(FileTest *t, void *arg) {
   std::vector<uint8_t> key, in, mac;
@@ -47,7 +88,8 @@
   poly1305_state state;
   CRYPTO_poly1305_init(&state, key.data());
   CRYPTO_poly1305_update(&state, in.data(), in.size());
-  ALIGNED uint8_t out[16];
+  // |CRYPTO_poly1305_finish| requires a 16-byte-aligned output.
+  alignas(16) uint8_t out[16];
   CRYPTO_poly1305_finish(&state, out);
   if (!t->ExpectBytesEqual(out, 16, mac.data(), mac.size())) {
     t->PrintLine("Single-shot Poly1305 failed.");
@@ -60,11 +102,20 @@
     CRYPTO_poly1305_update(&state, &in[i], 1);
   }
   CRYPTO_poly1305_finish(&state, out);
-  if (!t->ExpectBytesEqual(out, 16, mac.data(), mac.size())) {
+  if (!t->ExpectBytesEqual(mac.data(), mac.size(), out, 16)) {
     t->PrintLine("Streaming Poly1305 failed.");
     return false;
   }
 
+  // Test SIMD stress patterns. OpenSSL's AVX2 assembly needs a multiple of
+  // four blocks, so test up to three blocks of excess.
+  if (!TestSIMD(t, 0, key, in, mac) ||
+      !TestSIMD(t, 16, key, in, mac) ||
+      !TestSIMD(t, 32, key, in, mac) ||
+      !TestSIMD(t, 48, key, in, mac)) {
+    return false;
+  }
+
   return true;
 }
 
diff --git a/src/crypto/poly1305/poly1305_test.txt b/src/crypto/poly1305/poly1305_test.txt
deleted file mode 100644
index ad40699..0000000
--- a/src/crypto/poly1305/poly1305_test.txt
+++ /dev/null
@@ -1,52 +0,0 @@
-# RFC 7539, section 2.5.2.
-
-Key = 85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b
-Input = "Cryptographic Forum Research Group"
-MAC = a8061dc1305136c6c22b8baf0c0127a9
-
-
-# RFC 7539, section A.3.
-
-Key = 0000000000000000000000000000000000000000000000000000000000000000
-Input = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-MAC = 00000000000000000000000000000000
-
-Key = 0000000000000000000000000000000036e5f6b5c5e06070f0efca96227a863e
-Input = 416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e7472696275746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e20224945544620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c2073746174656d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c656374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207768696368206172652061646472657373656420746f
-MAC = 36e5f6b5c5e06070f0efca96227a863e
-
-Key = 36e5f6b5c5e06070f0efca96227a863e00000000000000000000000000000000
-Input = 416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e7472696275746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e20224945544620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c2073746174656d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c656374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207768696368206172652061646472657373656420746f
-MAC = f3477e7cd95417af89a6b8794c310cf0
-
-Key = 1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0
-Input = 2754776173206272696c6c69672c20616e642074686520736c6974687920746f7665730a446964206779726520616e642067696d626c6520696e2074686520776162653a0a416c6c206d696d737920776572652074686520626f726f676f7665732c0a416e6420746865206d6f6d65207261746873206f757467726162652e
-MAC = 4541669a7eaaee61e708dc7cbcc5eb62
-
-Key = 0200000000000000000000000000000000000000000000000000000000000000
-Input = ffffffffffffffffffffffffffffffff
-MAC = 03000000000000000000000000000000
-
-Key = 02000000000000000000000000000000ffffffffffffffffffffffffffffffff
-Input = 02000000000000000000000000000000
-MAC = 03000000000000000000000000000000
-
-Key = 0100000000000000000000000000000000000000000000000000000000000000
-Input = fffffffffffffffffffffffffffffffff0ffffffffffffffffffffffffffffff11000000000000000000000000000000
-MAC = 05000000000000000000000000000000
-
-Key = 0100000000000000000000000000000000000000000000000000000000000000
-Input = fffffffffffffffffffffffffffffffffbfefefefefefefefefefefefefefefe01010101010101010101010101010101
-MAC = 00000000000000000000000000000000
-
-Key = 0200000000000000000000000000000000000000000000000000000000000000
-Input = fdffffffffffffffffffffffffffffff
-MAC = faffffffffffffffffffffffffffffff
-
-Key = 0100000000000000040000000000000000000000000000000000000000000000
-Input = e33594d7505e43b900000000000000003394d7505e4379cd01000000000000000000000000000000000000000000000001000000000000000000000000000000
-MAC = 14000000000000005500000000000000
-
-Key = 0100000000000000040000000000000000000000000000000000000000000000
-Input = e33594d7505e43b900000000000000003394d7505e4379cd010000000000000000000000000000000000000000000000
-MAC = 13000000000000000000000000000000
diff --git a/src/crypto/poly1305/poly1305_tests.txt b/src/crypto/poly1305/poly1305_tests.txt
new file mode 100644
index 0000000..611007a
--- /dev/null
+++ b/src/crypto/poly1305/poly1305_tests.txt
@@ -0,0 +1,159 @@
+# RFC 7539, section 2.5.2.
+
+Key = 85d6be7857556d337f4452fe42d506a80103808afb0db2fd4abff6af4149f51b
+Input = "Cryptographic Forum Research Group"
+MAC = a8061dc1305136c6c22b8baf0c0127a9
+
+
+# RFC 7539, section A.3.
+
+Key = 0000000000000000000000000000000000000000000000000000000000000000
+Input = 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+MAC = 00000000000000000000000000000000
+
+Key = 0000000000000000000000000000000036e5f6b5c5e06070f0efca96227a863e
+Input = 416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e7472696275746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e20224945544620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c2073746174656d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c656374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207768696368206172652061646472657373656420746f
+MAC = 36e5f6b5c5e06070f0efca96227a863e
+
+Key = 36e5f6b5c5e06070f0efca96227a863e00000000000000000000000000000000
+Input = 416e79207375626d697373696f6e20746f20746865204945544620696e74656e6465642062792074686520436f6e7472696275746f7220666f72207075626c69636174696f6e20617320616c6c206f722070617274206f6620616e204945544620496e7465726e65742d4472616674206f722052464320616e6420616e792073746174656d656e74206d6164652077697468696e2074686520636f6e74657874206f6620616e204945544620616374697669747920697320636f6e7369646572656420616e20224945544620436f6e747269627574696f6e222e20537563682073746174656d656e747320696e636c756465206f72616c2073746174656d656e747320696e20494554462073657373696f6e732c2061732077656c6c206173207772697474656e20616e6420656c656374726f6e696320636f6d6d756e69636174696f6e73206d61646520617420616e792074696d65206f7220706c6163652c207768696368206172652061646472657373656420746f
+MAC = f3477e7cd95417af89a6b8794c310cf0
+
+Key = 1c9240a5eb55d38af333888604f6b5f0473917c1402b80099dca5cbc207075c0
+Input = 2754776173206272696c6c69672c20616e642074686520736c6974687920746f7665730a446964206779726520616e642067696d626c6520696e2074686520776162653a0a416c6c206d696d737920776572652074686520626f726f676f7665732c0a416e6420746865206d6f6d65207261746873206f757467726162652e
+MAC = 4541669a7eaaee61e708dc7cbcc5eb62
+
+Key = 0200000000000000000000000000000000000000000000000000000000000000
+Input = ffffffffffffffffffffffffffffffff
+MAC = 03000000000000000000000000000000
+
+Key = 02000000000000000000000000000000ffffffffffffffffffffffffffffffff
+Input = 02000000000000000000000000000000
+MAC = 03000000000000000000000000000000
+
+Key = 0100000000000000000000000000000000000000000000000000000000000000
+Input = fffffffffffffffffffffffffffffffff0ffffffffffffffffffffffffffffff11000000000000000000000000000000
+MAC = 05000000000000000000000000000000
+
+Key = 0100000000000000000000000000000000000000000000000000000000000000
+Input = fffffffffffffffffffffffffffffffffbfefefefefefefefefefefefefefefe01010101010101010101010101010101
+MAC = 00000000000000000000000000000000
+
+Key = 0200000000000000000000000000000000000000000000000000000000000000
+Input = fdffffffffffffffffffffffffffffff
+MAC = faffffffffffffffffffffffffffffff
+
+Key = 0100000000000000040000000000000000000000000000000000000000000000
+Input = e33594d7505e43b900000000000000003394d7505e4379cd01000000000000000000000000000000000000000000000001000000000000000000000000000000
+MAC = 14000000000000005500000000000000
+
+Key = 0100000000000000040000000000000000000000000000000000000000000000
+Input = e33594d7505e43b900000000000000003394d7505e4379cd010000000000000000000000000000000000000000000000
+MAC = 13000000000000000000000000000000
+
+
+# Additional test vectors that are long enough to ensure OpenSSL's SIMD
+# assembly is fully tested.
+
+# Length 2048.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfed
+MAC = 69d28f73dd09d39a92aa179da354b7ea
+
+# Length 2049.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc8
+MAC = d6a26654b88572e875d9661c83471c1b
+
+# Length 2050.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852
+MAC = 9fbbb7f7adcd0cd5b46a4a520b22499a
+
+# Length 2051.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f5
+MAC = eb7cdceb97ade2a07622f8f5a4b1ce15
+
+# Length 2052.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f590
+MAC = d41c310927cd92e14784ea78b85503db
+
+# Length 2053.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073
+MAC = 16af133c423f783a14c49d9f526384cf
+
+# Length 2054.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4
+MAC = 00c75db8f0636b22f195645b03091f5f
+
+# Length 2055.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f434
+MAC = 4a532bc740f581555831345f3b75bf33
+
+# Length 2056.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a
+MAC = 698c7d32c5923871d124a2479e521706
+
+# Length 2057.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c
+MAC = a677187dbf3c927aeeafb9ebce0f61dc
+
+# Length 2058.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c8a
+MAC = 201fed7eee981b31d2cc42ff6c38141a
+
+# Length 2059.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c8a28
+MAC = 0c3d3d01a37f347c4f7c5826bcafb3e1
+
+# Length 2060.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c8a28c9
+MAC = 33a4e0e0bed7c84c5cc5dd4784410f07
+
+# Length 2061.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c8a28c99e
+MAC = 8e41c40a2f8ec58fe594f3a3a2de4ae1
+
+# Length 2062.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c8a28c99e21
+MAC = c6e5d1810fd878ac6b844c66cef36a22
+
+# Length 2063.
+Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
+Input = 248ac31085b6c2adaaa38259a0d7192c5c35d1bb4ef39ad94c38d1c82479e2dd2159a077024b0589bc8a20101b506f0a1ad0bbab76e83a83f1b94be6beae74e874cab692c5963a75436b776121ec9f62399a3e66b2d22707dae81933b6277f3c8516bcbe26dbbd86f373103d7cf4cad1888c952118fbfbd0d7b4bedc4ae4936aff91157e7aa47c54442ea78d6ac251d324a0fbe49d89cc3521b66d16e9c66a3709894e4eb0a4eedc4ae19468e66b81f271351b1d921ea551047abcc6b87a901fde7db79fa1818c11336dbc07244a40eb14cf77bde35e78ae9ad7d3f57ed7e7f23926c9172f82d77684ea5ed7d74ebc6f142b997036bcb7cce8df1bbc0d5b35a46509c954fc9469d214d6238f166cbf872156b4c41d7aac5942cffb175023078252a3f36e315c5d4ce0e39928a018252862becacef96a19f03bdcf46d75584299d1f8b03c0169e9e407d937145b5e5024139e7022a1978f114f24cdfa23780a119735c41da8fb759bbb3f025c6ec30e6c6e9bce8615be68e392fce59fd26a8e6a6cc5c606e3848116e4d01d29565a1facfb524b6d29643b826eee1e42869fc76df229dd79b39a2b1df28bb335c3a5f15a855d0121e4a6da34b5e4d5b7b5d5746a03ecff70811e1516fcec1bf7462e8876a2d21710aa168c78f45a6a15015950e221da85d3ec822ad6d0a6931b25a06b7bb5f3c10bb36cd4d647f9561982fde9818de5d4bf8db7f86c53b4ff14928ac15f79023b61861e73e44216540bb302153770da2533de9795252ab5fb77ad924c9338c8144c23d4c90dab9a18feac1a1574d4545e1435eb405e6c4c439fc724fce992ae85badf345bad16d85fbd338f04433703614754d0e7e54c4ccde2670587d52ecfb5a70a14a501bacc727722649931d8515b13d020a78e511fe136d45fbf97f9c7f689fcc677cfb3683723878350ffe9d08130cc6e567b6179e01b7eb2b3bbcf0873e1308eec018edeb8cce946338e15d5bf68c71916a83a99358039ef071e009546a2df936879dffbba397a93925d229a469fd17d71b7f524e03a30da6ee927542f8b369bed4734fe25dbd63d24ffd2a222f5f84f75d858ab989be925af570ad6d45bd28ce61b5139e1dd2f0b7795fe072e6e83acbb5e7b777a70c641e4cab2af40eed69abc334cd2703c3273204fac580c6a3d6680427e5f7d051e8380a53f93a180f4556ecea4530b9a2d5948dad63d415b6874f6b90e767d6d265be86351b53ba690780bb57c21b57418c5b97559e840c68257f839e7583a4bf7c7645c5987d40cc1ba79a218c35edfacdabe581d950e4bb7a481ebe64d61d00e75b1f25f1ce5f5462334a5b9038a697aa0937a3f8017e05d2c9c05dcb05c0b02508dea619b137f5444b6f088eb3cb2c66788f88afdfbba8faa1c490485624c88ae11e57347a676902e7553f056188493209bdbb30acc63c9e41e16a9d6c009416b520a76ba38f57628170c43626b5cb46179dc5bf65de865085f84bf741c223fbe474d2d19d8f43914fbd6586351089e73babf344f988b7963fe44528457d7aad3c564f6bcbd0d772a4c9fd328e6022d1c7c9f86726f8d5a23797d309c0f653ab1ac687833eb2700f156296062a8b377078f45f6b68c3d07cae1913ba8d5a6f9bf7525a3439eb932d4cefc4bf8e1b07b48ca13ece366cbc3e0388915915d1757475103a9e9454e7e6355de2d6acbf4710f9a63e4f6d3cd70c2d6fca88dd8a14448fdb63ce9350fdaafbe0b8bd1c5d307dae76dfed799aef2d8f23d5608d37d1330dd38b94860905dbeebf78d7b7318b7d42aed40d3f9899e9f420cbd92a6eeae3026f7725694e0e4bee016ba346fed2c21172bdb4a461cebe0cfe38e76645226ac127a259c193264d735ce8c8a57e17dd3f0579e2e86dc295ad1f45ba2d85db35044da61f7d401274b31eefbeb34e8d2ae596e9b4541aae117bdac5ed0b324c20539c27c07a411d5288b0b5f6fa16e9a7df85dc319fa6b71cd08a859c06a3f7b0289e1750adbf182f9750fea96fea5ab7aa3473340607cd7ed2c626f5382491c26d5d5bea61401dee7319c94d418f297e61ceac8f258ee8c23831bda081591f5a918e96855774ddedffc51e5b180f1971806d42fc333020b734aeb45adb0bc47325d0cea5f6713a786558022afc39d573892aa3635efbfd8bcb11c57f306c72146afe8b45388125cb7bf9ecf965a7ba4f768c77be366470dcdcf214b7f6a5a9460ed4fe44ae559d85e2fdc2094de83fff12ea8804db1215c4ca865871bdd7f8ef32ab799bf923ffb02c1ded7d129beadad46c5eda31ab1a6f43da05ea08bff7ffa88d8966353d01830558c39b930b01d175e437124d8edd0d2698fd8932f2b2c9b14746e52879c57a395538150f390264f00e60d470711202f4194499ff79037ca9885dc8d695f7d917a3086ca88e8f8d0243efee09302cf39e039eb7cc8dd19d28120d5fe533b5727cd39133181c729ca6f90a015ed30be7668d5cb5ecc33a53ee69bf7d1a5ecbdb153803743c6adaaabd36bf84e5be38d3f04a5d5dbfd67bdcd3b176e65bd1391ade775cc32ce43a847fb6c672a3fe97a5d4081c4986959ec5fb898f42a9397ba2b3ec2c1018f8d76d057f2366bd0e4465514ad6560c599664fb85621fe771e00f43d39b591b2a6a321100f4d1ef23a376d5ae3eeedbfe23da73dff0ee4d16b34ebddd8f5f053db9824105fc7300dbee7ea6af56b112319e3e215a0fc79ae946f6b5227453ec7fcaf17cf7651f71499a50d81221404d5f129ac50ea7528ff0e0069ec4ab8acb7919d81749ab37a870c5ef2cc5a15cf96709d3c65b4addc77e7416847160bcabb94ea36377e0ef71be80b5cc53effd5444888044a353574c72c924bba2a8b4e8354188ebfedc852f59073f4347a8c8a28c99e21df
+MAC = f6eaae369c3cb5c05748e8d919178e00
+
+# Regression test for https://rt.openssl.org/Ticket/Display.html?id=4439
+Key = 2d773be37adb1e4d683bf0075e79c4ee037918535a7f99ccb7040fb5f5f43aea
+Input = 89dab80b7717c1db5db437860a3f70218e93e1b8f461fb677f16f35f6f87e2a91c99bc3a47ace47640cc95c345be5ecca5a3523c35cc01893af0b64a620334270372ec12482d1b1e363561698a578b359803495bb4e2ef1930b17a5190b580f141300df30adbeca28f6427a8bc1a999fd51c554a017d095d8c3e3127daf9f595
+MAC = c85d15ed44c378d6b00e23064c7bcd51
+
+# Regression tests for https://rt.openssl.org/Ticket/Display.html?id=4483
+
+Key = 7f1b02640000000000000000000000000000000000000000cccccccccccccccc
+Input = cccccccccccccccccccccccccccccccccccccccccccccccccc80ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccceccccccccccccccccccccccccccccccccccccc5cccccccccccccccccccccccccccccccccccccccccce3ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccaccccccccccccccccccccce6cccccccccc000000afccccccccccccccccccfffffff5000000000000000000000000000000000000000000000000000000ffffffe70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000719205a8521dfc
+MAC = 8559b876eceed66eb37798c0457baff9
+
+Key = e00016000000000000000000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaaaa
+Input = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa000000000000000000800264
+MAC = 00bd1258978e205444c9aaaa82006fed
+
+Key = 0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c
+Input = 02fc
+MAC = 06120c0c0c0c0c0c0c0c0c0c0c0c0c0c
+
+Key = 00ff000000000000000000000000000000000000001e00000000000000007b7b
+Input = 7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7a7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b5c7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b6e7b007b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7a7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b5c7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b7b6e7b001300000000b300000000000000000000000000000000000000000000f20000000000000000000000000000000000002000efff0009000000000000000000000000100000000009000000640000000000000000000000001300000000b300000000000000000000000000000000000000000000f20000000000000000000000000000000000002000efff00090000000000000000007a000010000000000900000064000000000000000000000000000000000000000000000000fc
+MAC = 33205bbf9e9f8f7212ab9e2ab9b7e4a5
diff --git a/src/crypto/poly1305/poly1305_vec.c b/src/crypto/poly1305/poly1305_vec.c
index 07578d0..3045a2f 100644
--- a/src/crypto/poly1305/poly1305_vec.c
+++ b/src/crypto/poly1305/poly1305_vec.c
@@ -20,42 +20,40 @@
 
 #include <openssl/poly1305.h>
 
+#include "../internal.h"
+
 
 #if !defined(OPENSSL_WINDOWS) && defined(OPENSSL_X86_64)
 
 #include <emmintrin.h>
 
-#define ALIGN(x) __attribute__((aligned(x)))
-/* inline is not a keyword in C89. */
-#define INLINE 
-#define U8TO64_LE(m) (*(uint64_t *)(m))
-#define U8TO32_LE(m) (*(uint32_t *)(m))
+#define U8TO64_LE(m) (*(const uint64_t *)(m))
+#define U8TO32_LE(m) (*(const uint32_t *)(m))
 #define U64TO8_LE(m, v) (*(uint64_t *)(m)) = v
 
 typedef __m128i xmmi;
-typedef unsigned __int128 uint128_t;
 
-static const uint32_t ALIGN(16) poly1305_x64_sse2_message_mask[4] = {
+static const alignas(16) uint32_t poly1305_x64_sse2_message_mask[4] = {
     (1 << 26) - 1, 0, (1 << 26) - 1, 0};
-static const uint32_t ALIGN(16) poly1305_x64_sse2_5[4] = {5, 0, 5, 0};
-static const uint32_t ALIGN(16) poly1305_x64_sse2_1shl128[4] = {(1 << 24), 0,
-                                                                (1 << 24), 0};
+static const alignas(16) uint32_t poly1305_x64_sse2_5[4] = {5, 0, 5, 0};
+static const alignas(16) uint32_t poly1305_x64_sse2_1shl128[4] = {
+    (1 << 24), 0, (1 << 24), 0};
 
-static uint128_t INLINE add128(uint128_t a, uint128_t b) { return a + b; }
+static inline uint128_t add128(uint128_t a, uint128_t b) { return a + b; }
 
-static uint128_t INLINE add128_64(uint128_t a, uint64_t b) { return a + b; }
+static inline uint128_t add128_64(uint128_t a, uint64_t b) { return a + b; }
 
-static uint128_t INLINE mul64x64_128(uint64_t a, uint64_t b) {
+static inline uint128_t mul64x64_128(uint64_t a, uint64_t b) {
   return (uint128_t)a * b;
 }
 
-static uint64_t INLINE lo128(uint128_t a) { return (uint64_t)a; }
+static inline uint64_t lo128(uint128_t a) { return (uint64_t)a; }
 
-static uint64_t INLINE shr128(uint128_t v, const int shift) {
+static inline uint64_t shr128(uint128_t v, const int shift) {
   return (uint64_t)(v >> shift);
 }
 
-static uint64_t INLINE shr128_pair(uint64_t hi, uint64_t lo, const int shift) {
+static inline uint64_t shr128_pair(uint64_t hi, uint64_t lo, const int shift) {
   return (uint64_t)((((uint128_t)hi << 64) | lo) >> shift);
 }
 
@@ -82,32 +80,32 @@
 } poly1305_state_internal; /* 448 bytes total + 63 bytes for
                               alignment = 511 bytes raw */
 
-static poly1305_state_internal INLINE *poly1305_aligned_state(
+static inline poly1305_state_internal *poly1305_aligned_state(
     poly1305_state *state) {
   return (poly1305_state_internal *)(((uint64_t)state + 63) & ~63);
 }
 
 /* copy 0-63 bytes */
-static void INLINE
+static inline void
 poly1305_block_copy(uint8_t *dst, const uint8_t *src, size_t bytes) {
   size_t offset = src - dst;
   if (bytes & 32) {
     _mm_storeu_si128((xmmi *)(dst + 0),
-                     _mm_loadu_si128((xmmi *)(dst + offset + 0)));
+                     _mm_loadu_si128((const xmmi *)(dst + offset + 0)));
     _mm_storeu_si128((xmmi *)(dst + 16),
-                     _mm_loadu_si128((xmmi *)(dst + offset + 16)));
+                     _mm_loadu_si128((const xmmi *)(dst + offset + 16)));
     dst += 32;
   }
   if (bytes & 16) {
-    _mm_storeu_si128((xmmi *)dst, _mm_loadu_si128((xmmi *)(dst + offset)));
+    _mm_storeu_si128((xmmi *)dst, _mm_loadu_si128((const xmmi *)(dst + offset)));
     dst += 16;
   }
   if (bytes & 8) {
-    *(uint64_t *)dst = *(uint64_t *)(dst + offset);
+    *(uint64_t *)dst = *(const uint64_t *)(dst + offset);
     dst += 8;
   }
   if (bytes & 4) {
-    *(uint32_t *)dst = *(uint32_t *)(dst + offset);
+    *(uint32_t *)dst = *(const uint32_t *)(dst + offset);
     dst += 4;
   }
   if (bytes & 2) {
@@ -120,7 +118,7 @@
 }
 
 /* zero 0-15 bytes */
-static void INLINE poly1305_block_zero(uint8_t *dst, size_t bytes) {
+static inline void poly1305_block_zero(uint8_t *dst, size_t bytes) {
   if (bytes & 8) {
     *(uint64_t *)dst = 0;
     dst += 8;
@@ -138,7 +136,7 @@
   }
 }
 
-static size_t INLINE poly1305_min(size_t a, size_t b) {
+static inline size_t poly1305_min(size_t a, size_t b) {
   return (a < b) ? a : b;
 }
 
@@ -186,9 +184,9 @@
 
 static void poly1305_first_block(poly1305_state_internal *st,
                                  const uint8_t *m) {
-  const xmmi MMASK = _mm_load_si128((xmmi *)poly1305_x64_sse2_message_mask);
-  const xmmi FIVE = _mm_load_si128((xmmi *)poly1305_x64_sse2_5);
-  const xmmi HIBIT = _mm_load_si128((xmmi *)poly1305_x64_sse2_1shl128);
+  const xmmi MMASK = _mm_load_si128((const xmmi *)poly1305_x64_sse2_message_mask);
+  const xmmi FIVE = _mm_load_si128((const xmmi *)poly1305_x64_sse2_5);
+  const xmmi HIBIT = _mm_load_si128((const xmmi *)poly1305_x64_sse2_1shl128);
   xmmi T5, T6;
   poly1305_power *p;
   uint128_t d[3];
@@ -265,10 +263,10 @@
   p->R24.d[3] = (uint32_t)(pad1 >> 32);
 
   /* H = [Mx,My] */
-  T5 = _mm_unpacklo_epi64(_mm_loadl_epi64((xmmi *)(m + 0)),
-                          _mm_loadl_epi64((xmmi *)(m + 16)));
-  T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((xmmi *)(m + 8)),
-                          _mm_loadl_epi64((xmmi *)(m + 24)));
+  T5 = _mm_unpacklo_epi64(_mm_loadl_epi64((const xmmi *)(m + 0)),
+                          _mm_loadl_epi64((const xmmi *)(m + 16)));
+  T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((const xmmi *)(m + 8)),
+                          _mm_loadl_epi64((const xmmi *)(m + 24)));
   st->H[0] = _mm_and_si128(MMASK, T5);
   st->H[1] = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26));
   T5 = _mm_or_si128(_mm_srli_epi64(T5, 52), _mm_slli_epi64(T6, 12));
@@ -279,9 +277,9 @@
 
 static void poly1305_blocks(poly1305_state_internal *st, const uint8_t *m,
                             size_t bytes) {
-  const xmmi MMASK = _mm_load_si128((xmmi *)poly1305_x64_sse2_message_mask);
-  const xmmi FIVE = _mm_load_si128((xmmi *)poly1305_x64_sse2_5);
-  const xmmi HIBIT = _mm_load_si128((xmmi *)poly1305_x64_sse2_1shl128);
+  const xmmi MMASK = _mm_load_si128((const xmmi *)poly1305_x64_sse2_message_mask);
+  const xmmi FIVE = _mm_load_si128((const xmmi *)poly1305_x64_sse2_5);
+  const xmmi HIBIT = _mm_load_si128((const xmmi *)poly1305_x64_sse2_1shl128);
 
   poly1305_power *p;
   xmmi H0, H1, H2, H3, H4;
@@ -345,10 +343,10 @@
     T4 = _mm_add_epi64(T4, T5);
 
     /* H += [Mx,My]*[r^2,r^2] */
-    T5 = _mm_unpacklo_epi64(_mm_loadl_epi64((xmmi *)(m + 0)),
-                            _mm_loadl_epi64((xmmi *)(m + 16)));
-    T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((xmmi *)(m + 8)),
-                            _mm_loadl_epi64((xmmi *)(m + 24)));
+    T5 = _mm_unpacklo_epi64(_mm_loadl_epi64((const xmmi *)(m + 0)),
+                            _mm_loadl_epi64((const xmmi *)(m + 16)));
+    T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((const xmmi *)(m + 8)),
+                            _mm_loadl_epi64((const xmmi *)(m + 24)));
     M0 = _mm_and_si128(MMASK, T5);
     M1 = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26));
     T5 = _mm_or_si128(_mm_srli_epi64(T5, 52), _mm_slli_epi64(T6, 12));
@@ -409,10 +407,10 @@
     T4 = _mm_add_epi64(T4, T5);
 
     /* H += [Mx,My] */
-    T5 = _mm_unpacklo_epi64(_mm_loadl_epi64((xmmi *)(m + 32)),
-                            _mm_loadl_epi64((xmmi *)(m + 48)));
-    T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((xmmi *)(m + 40)),
-                            _mm_loadl_epi64((xmmi *)(m + 56)));
+    T5 = _mm_unpacklo_epi64(_mm_loadl_epi64((const xmmi *)(m + 32)),
+                            _mm_loadl_epi64((const xmmi *)(m + 48)));
+    T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((const xmmi *)(m + 40)),
+                            _mm_loadl_epi64((const xmmi *)(m + 56)));
     M0 = _mm_and_si128(MMASK, T5);
     M1 = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26));
     T5 = _mm_or_si128(_mm_srli_epi64(T5, 52), _mm_slli_epi64(T6, 12));
@@ -469,9 +467,9 @@
 
 static size_t poly1305_combine(poly1305_state_internal *st, const uint8_t *m,
                                size_t bytes) {
-  const xmmi MMASK = _mm_load_si128((xmmi *)poly1305_x64_sse2_message_mask);
-  const xmmi HIBIT = _mm_load_si128((xmmi *)poly1305_x64_sse2_1shl128);
-  const xmmi FIVE = _mm_load_si128((xmmi *)poly1305_x64_sse2_5);
+  const xmmi MMASK = _mm_load_si128((const xmmi *)poly1305_x64_sse2_message_mask);
+  const xmmi HIBIT = _mm_load_si128((const xmmi *)poly1305_x64_sse2_1shl128);
+  const xmmi FIVE = _mm_load_si128((const xmmi *)poly1305_x64_sse2_5);
 
   poly1305_power *p;
   xmmi H0, H1, H2, H3, H4;
@@ -542,10 +540,10 @@
     T4 = _mm_add_epi64(T4, T5);
 
     /* H += [Mx,My] */
-    T5 = _mm_unpacklo_epi64(_mm_loadl_epi64((xmmi *)(m + 0)),
-                            _mm_loadl_epi64((xmmi *)(m + 16)));
-    T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((xmmi *)(m + 8)),
-                            _mm_loadl_epi64((xmmi *)(m + 24)));
+    T5 = _mm_unpacklo_epi64(_mm_loadl_epi64((const xmmi *)(m + 0)),
+                            _mm_loadl_epi64((const xmmi *)(m + 16)));
+    T6 = _mm_unpacklo_epi64(_mm_loadl_epi64((const xmmi *)(m + 8)),
+                            _mm_loadl_epi64((const xmmi *)(m + 24)));
     M0 = _mm_and_si128(MMASK, T5);
     M1 = _mm_and_si128(MMASK, _mm_srli_epi64(T5, 26));
     T5 = _mm_or_si128(_mm_srli_epi64(T5, 52), _mm_slli_epi64(T6, 12));
@@ -703,9 +701,9 @@
   t0 &= 0x3ffffff;
   t1 = t1 + c;
 
-  st->HH[0] = ((t0) | (t1 << 26)) & 0xfffffffffffull;
-  st->HH[1] = ((t1 >> 18) | (t2 << 8) | (t3 << 34)) & 0xfffffffffffull;
-  st->HH[2] = ((t3 >> 10) | (t4 << 16)) & 0x3ffffffffffull;
+  st->HH[0] = ((t0) | (t1 << 26)) & UINT64_C(0xfffffffffff);
+  st->HH[1] = ((t1 >> 18) | (t2 << 8) | (t3 << 34)) & UINT64_C(0xfffffffffff);
+  st->HH[2] = ((t3 >> 10) | (t4 << 16)) & UINT64_C(0x3ffffffffff);
 
   return consumed;
 }
diff --git a/src/crypto/pool/CMakeLists.txt b/src/crypto/pool/CMakeLists.txt
new file mode 100644
index 0000000..fe55af2
--- /dev/null
+++ b/src/crypto/pool/CMakeLists.txt
@@ -0,0 +1,20 @@
+include_directories(../../include)
+
+add_library(
+  pool
+
+  OBJECT
+
+  pool.c
+)
+
+add_executable(
+  pool_test
+
+  pool_test.cc
+
+  $<TARGET_OBJECTS:test_support>
+)
+
+target_link_libraries(pool_test crypto)
+add_dependencies(all_tests pool_test)
diff --git a/src/crypto/pool/internal.h b/src/crypto/pool/internal.h
new file mode 100644
index 0000000..3ec2ec2
--- /dev/null
+++ b/src/crypto/pool/internal.h
@@ -0,0 +1,45 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#ifndef OPENSSL_HEADER_POOL_INTERNAL_H
+#define OPENSSL_HEADER_POOL_INTERNAL_H
+
+#include <openssl/lhash.h>
+#include <openssl/thread.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+DECLARE_LHASH_OF(CRYPTO_BUFFER);
+
+struct crypto_buffer_st {
+  CRYPTO_BUFFER_POOL *pool;
+  uint8_t *data;
+  size_t len;
+  CRYPTO_refcount_t references;
+};
+
+struct crypto_buffer_pool_st {
+  LHASH_OF(CRYPTO_BUFFER) *bufs;
+  CRYPTO_MUTEX lock;
+};
+
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_POOL_INTERNAL_H */
diff --git a/src/crypto/pool/pool.c b/src/crypto/pool/pool.c
new file mode 100644
index 0000000..44d10af
--- /dev/null
+++ b/src/crypto/pool/pool.c
@@ -0,0 +1,200 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/pool.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/buf.h>
+#include <openssl/bytestring.h>
+#include <openssl/mem.h>
+#include <openssl/thread.h>
+
+#include "../internal.h"
+#include "internal.h"
+
+
+static uint32_t CRYPTO_BUFFER_hash(const CRYPTO_BUFFER *buf) {
+  return OPENSSL_hash32(buf->data, buf->len);
+}
+
+static int CRYPTO_BUFFER_cmp(const CRYPTO_BUFFER *a, const CRYPTO_BUFFER *b) {
+  if (a->len != b->len) {
+    return 1;
+  }
+  return OPENSSL_memcmp(a->data, b->data, a->len);
+}
+
+CRYPTO_BUFFER_POOL* CRYPTO_BUFFER_POOL_new(void) {
+  CRYPTO_BUFFER_POOL *pool = OPENSSL_malloc(sizeof(CRYPTO_BUFFER_POOL));
+  if (pool == NULL) {
+    return NULL;
+  }
+
+  OPENSSL_memset(pool, 0, sizeof(CRYPTO_BUFFER_POOL));
+  pool->bufs = lh_CRYPTO_BUFFER_new(CRYPTO_BUFFER_hash, CRYPTO_BUFFER_cmp);
+  if (pool->bufs == NULL) {
+    OPENSSL_free(pool);
+    return NULL;
+  }
+
+  CRYPTO_MUTEX_init(&pool->lock);
+
+  return pool;
+}
+
+void CRYPTO_BUFFER_POOL_free(CRYPTO_BUFFER_POOL *pool) {
+  if (pool == NULL) {
+    return;
+  }
+
+#if !defined(NDEBUG)
+  CRYPTO_MUTEX_lock_write(&pool->lock);
+  assert(lh_CRYPTO_BUFFER_num_items(pool->bufs) == 0);
+  CRYPTO_MUTEX_unlock_write(&pool->lock);
+#endif
+
+  lh_CRYPTO_BUFFER_free(pool->bufs);
+  CRYPTO_MUTEX_cleanup(&pool->lock);
+  OPENSSL_free(pool);
+}
+
+CRYPTO_BUFFER *CRYPTO_BUFFER_new(const uint8_t *data, size_t len,
+                                 CRYPTO_BUFFER_POOL *pool) {
+  if (pool != NULL) {
+    CRYPTO_BUFFER tmp;
+    tmp.data = (uint8_t *) data;
+    tmp.len = len;
+
+    CRYPTO_MUTEX_lock_read(&pool->lock);
+    CRYPTO_BUFFER *const duplicate =
+        lh_CRYPTO_BUFFER_retrieve(pool->bufs, &tmp);
+    if (duplicate != NULL) {
+      CRYPTO_refcount_inc(&duplicate->references);
+    }
+    CRYPTO_MUTEX_unlock_read(&pool->lock);
+
+    if (duplicate != NULL) {
+      return duplicate;
+    }
+  }
+
+  CRYPTO_BUFFER *const buf = OPENSSL_malloc(sizeof(CRYPTO_BUFFER));
+  if (buf == NULL) {
+    return NULL;
+  }
+  OPENSSL_memset(buf, 0, sizeof(CRYPTO_BUFFER));
+
+  buf->data = BUF_memdup(data, len);
+  if (len != 0 && buf->data == NULL) {
+    OPENSSL_free(buf);
+    return NULL;
+  }
+
+  buf->len = len;
+  buf->references = 1;
+
+  if (pool == NULL) {
+    return buf;
+  }
+
+  buf->pool = pool;
+
+  CRYPTO_MUTEX_lock_write(&pool->lock);
+  CRYPTO_BUFFER *duplicate = lh_CRYPTO_BUFFER_retrieve(pool->bufs, buf);
+  int inserted = 0;
+  if (duplicate == NULL) {
+    CRYPTO_BUFFER *old = NULL;
+    inserted = lh_CRYPTO_BUFFER_insert(pool->bufs, &old, buf);
+    assert(old == NULL);
+  } else {
+    CRYPTO_refcount_inc(&duplicate->references);
+  }
+  CRYPTO_MUTEX_unlock_write(&pool->lock);
+
+  if (!inserted) {
+    /* We raced to insert |buf| into the pool and lost, or else there was an
+     * error inserting. */
+    OPENSSL_free(buf->data);
+    OPENSSL_free(buf);
+    return duplicate;
+  }
+
+  return buf;
+}
+
+CRYPTO_BUFFER* CRYPTO_BUFFER_new_from_CBS(CBS *cbs, CRYPTO_BUFFER_POOL *pool) {
+  return CRYPTO_BUFFER_new(CBS_data(cbs), CBS_len(cbs), pool);
+}
+
+void CRYPTO_BUFFER_free(CRYPTO_BUFFER *buf) {
+  if (buf == NULL) {
+    return;
+  }
+
+  CRYPTO_BUFFER_POOL *const pool = buf->pool;
+  if (pool == NULL) {
+    if (CRYPTO_refcount_dec_and_test_zero(&buf->references)) {
+      /* If a reference count of zero is observed, there cannot be a reference
+       * from any pool to this buffer and thus we are able to free this
+       * buffer. */
+      OPENSSL_free(buf->data);
+      OPENSSL_free(buf);
+    }
+
+    return;
+  }
+
+  CRYPTO_MUTEX_lock_write(&pool->lock);
+  if (!CRYPTO_refcount_dec_and_test_zero(&buf->references)) {
+    CRYPTO_MUTEX_unlock_write(&buf->pool->lock);
+    return;
+  }
+
+  /* We have an exclusive lock on the pool, therefore no concurrent lookups can
+   * find this buffer and increment the reference count. Thus, if the count is
+   * zero there are and can never be any more references and thus we can free
+   * this buffer. */
+  void *found = lh_CRYPTO_BUFFER_delete(pool->bufs, buf);
+  assert(found != NULL);
+  assert(found == buf);
+  (void)found;
+  CRYPTO_MUTEX_unlock_write(&buf->pool->lock);
+  OPENSSL_free(buf->data);
+  OPENSSL_free(buf);
+}
+
+int CRYPTO_BUFFER_up_ref(CRYPTO_BUFFER *buf) {
+  /* This is safe in the case that |buf->pool| is NULL because it's just
+   * standard reference counting in that case.
+   *
+   * This is also safe if |buf->pool| is non-NULL because, if it were racing
+   * with |CRYPTO_BUFFER_free| then the two callers must have independent
+   * references already and so the reference count will never hit zero. */
+  CRYPTO_refcount_inc(&buf->references);
+  return 1;
+}
+
+const uint8_t *CRYPTO_BUFFER_data(const CRYPTO_BUFFER *buf) {
+  return buf->data;
+}
+
+size_t CRYPTO_BUFFER_len(const CRYPTO_BUFFER *buf) {
+  return buf->len;
+}
+
+void CRYPTO_BUFFER_init_CBS(const CRYPTO_BUFFER *buf, CBS *out) {
+  CBS_init(out, buf->data, buf->len);
+}
diff --git a/src/crypto/pool/pool_test.cc b/src/crypto/pool/pool_test.cc
new file mode 100644
index 0000000..72b8ce0
--- /dev/null
+++ b/src/crypto/pool/pool_test.cc
@@ -0,0 +1,89 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/pool.h>
+
+#include "../internal.h"
+
+
+static bool TestUnpooled() {
+  static const uint8_t kData[4] = {1, 2, 3, 4};
+  bssl::UniquePtr<CRYPTO_BUFFER> buf(
+      CRYPTO_BUFFER_new(kData, sizeof(kData), nullptr));
+  if (!buf) {
+    return false;
+  }
+
+  if (CRYPTO_BUFFER_len(buf.get()) != sizeof(kData) ||
+      OPENSSL_memcmp(kData, CRYPTO_BUFFER_data(buf.get()), sizeof(kData)) !=
+          0) {
+    fprintf(stderr, "CRYPTO_BUFFER corrupted data.\n");
+    return false;
+  }
+
+  CRYPTO_BUFFER_up_ref(buf.get());
+  bssl::UniquePtr<CRYPTO_BUFFER> buf2(buf.get());
+
+  return true;
+}
+
+static bool TestEmpty() {
+  bssl::UniquePtr<CRYPTO_BUFFER> buf(CRYPTO_BUFFER_new(nullptr, 0, nullptr));
+  if (!buf) {
+    return false;
+  }
+
+  return true;
+}
+
+static bool TestPool() {
+  bssl::UniquePtr<CRYPTO_BUFFER_POOL> pool(CRYPTO_BUFFER_POOL_new());
+  if (!pool) {
+    return false;
+  }
+
+  static const uint8_t kData[4] = {1, 2, 3, 4};
+  bssl::UniquePtr<CRYPTO_BUFFER> buf(
+      CRYPTO_BUFFER_new(kData, sizeof(kData), pool.get()));
+  if (!buf) {
+    return false;
+  }
+
+  bssl::UniquePtr<CRYPTO_BUFFER> buf2(
+      CRYPTO_BUFFER_new(kData, sizeof(kData), pool.get()));
+  if (!buf2) {
+    return false;
+  }
+
+  if (buf.get() != buf2.get()) {
+    fprintf(stderr, "CRYPTO_BUFFER_POOL did not dedup data.\n");
+    return false;
+  }
+
+  return true;
+}
+
+int main(int argc, char **argv) {
+  if (!TestUnpooled() ||
+      !TestEmpty() ||
+      !TestPool()) {
+    return 1;
+  }
+
+  printf("PASS\n");
+  return 0;
+}
diff --git a/src/crypto/rand/CMakeLists.txt b/src/crypto/rand/CMakeLists.txt
index eedf81b..f7c11f1 100644
--- a/src/crypto/rand/CMakeLists.txt
+++ b/src/crypto/rand/CMakeLists.txt
@@ -13,6 +13,8 @@
 
   OBJECT
 
+  deterministic.c
+  fuchsia.c
   rand.c
   urandom.c
   windows.c
diff --git a/src/crypto/rand/deterministic.c b/src/crypto/rand/deterministic.c
new file mode 100644
index 0000000..8c754c1
--- /dev/null
+++ b/src/crypto/rand/deterministic.c
@@ -0,0 +1,48 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/rand.h>
+
+#if defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE)
+
+#include <string.h>
+
+#include <openssl/chacha.h>
+
+#include "internal.h"
+#include "../internal.h"
+
+
+/* g_num_calls is the number of calls to |CRYPTO_sysrand| that have occurred.
+ *
+ * This is intentionally not thread-safe. If the fuzzer mode is ever used in a
+ * multi-threaded program, replace this with a thread-local. (A mutex would not
+ * be deterministic.) */
+static uint64_t g_num_calls = 0;
+
+void RAND_reset_for_fuzzing(void) { g_num_calls = 0; }
+
+void CRYPTO_sysrand(uint8_t *out, size_t requested) {
+  static const uint8_t kZeroKey[32];
+
+  uint8_t nonce[12];
+  OPENSSL_memset(nonce, 0, sizeof(nonce));
+  OPENSSL_memcpy(nonce, &g_num_calls, sizeof(g_num_calls));
+
+  OPENSSL_memset(out, 0, requested);
+  CRYPTO_chacha_20(out, out, requested, kZeroKey, nonce, 0);
+  g_num_calls++;
+}
+
+#endif  /* BORINGSSL_UNSAFE_DETERMINISTIC_MODE */
diff --git a/src/crypto/rand/fuchsia.c b/src/crypto/rand/fuchsia.c
new file mode 100644
index 0000000..2e138d0
--- /dev/null
+++ b/src/crypto/rand/fuchsia.c
@@ -0,0 +1,43 @@
+/* Copyright (c) 2017, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/rand.h>
+
+#if defined(OPENSSL_FUCHSIA) && !defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE)
+
+#include <limits.h>
+#include <stdlib.h>
+
+#include <magenta/syscalls.h>
+
+#include "internal.h"
+
+void CRYPTO_sysrand(uint8_t *out, size_t requested) {
+  while (requested > 0) {
+    size_t output_bytes_this_pass = MX_CPRNG_DRAW_MAX_LEN;
+    if (requested < output_bytes_this_pass) {
+      output_bytes_this_pass = requested;
+    }
+    size_t bytes_drawn;
+    mx_status_t status =
+        mx_cprng_draw(out, output_bytes_this_pass, &bytes_drawn);
+    if (status != NO_ERROR) {
+      abort();
+    }
+    requested -= bytes_drawn;
+    out += bytes_drawn;
+  }
+}
+
+#endif /* OPENSSL_FUCHSIA && !BORINGSSL_UNSAFE_DETERMINISTIC_MODE */
diff --git a/src/crypto/rand/rand.c b/src/crypto/rand/rand.c
index 82087ba..51da6ba 100644
--- a/src/crypto/rand/rand.c
+++ b/src/crypto/rand/rand.c
@@ -72,7 +72,8 @@
   OPENSSL_free(state);
 }
 
-#if defined(OPENSSL_X86_64) && !defined(OPENSSL_NO_ASM)
+#if defined(OPENSSL_X86_64) && !defined(OPENSSL_NO_ASM) && \
+    !defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE)
 
 /* These functions are defined in asm/rdrand-x86_64.pl */
 extern int CRYPTO_rdrand(uint8_t out[8]);
@@ -100,7 +101,7 @@
     if (!CRYPTO_rdrand(rand_buf)) {
       return 0;
     }
-    memcpy(buf + len_multiple8, rand_buf, len);
+    OPENSSL_memcpy(buf + len_multiple8, rand_buf, len);
   }
 
   return 1;
@@ -137,7 +138,7 @@
       return 1;
     }
 
-    memset(state->partial_block, 0, sizeof(state->partial_block));
+    OPENSSL_memset(state->partial_block, 0, sizeof(state->partial_block));
     state->calls_used = kMaxCallsPerRefresh;
   }
 
@@ -160,8 +161,8 @@
         todo = kMaxBytesPerCall;
       }
       uint8_t nonce[12];
-      memset(nonce, 0, 4);
-      memcpy(nonce + 4, &state->calls_used, sizeof(state->calls_used));
+      OPENSSL_memset(nonce, 0, 4);
+      OPENSSL_memcpy(nonce + 4, &state->calls_used, sizeof(state->calls_used));
       CRYPTO_chacha_20(buf, buf, todo, state->key, nonce, 0);
       buf += todo;
       remaining -= todo;
@@ -170,8 +171,8 @@
   } else {
     if (sizeof(state->partial_block) - state->partial_block_used < len) {
       uint8_t nonce[12];
-      memset(nonce, 0, 4);
-      memcpy(nonce + 4, &state->calls_used, sizeof(state->calls_used));
+      OPENSSL_memset(nonce, 0, 4);
+      OPENSSL_memcpy(nonce + 4, &state->calls_used, sizeof(state->calls_used));
       CRYPTO_chacha_20(state->partial_block, state->partial_block,
                        sizeof(state->partial_block), state->key, nonce, 0);
       state->partial_block_used = 0;
@@ -239,3 +240,5 @@
 }
 
 void RAND_set_rand_method(const RAND_METHOD *method) {}
+
+void RAND_cleanup(void) {}
diff --git a/src/crypto/rand/urandom.c b/src/crypto/rand/urandom.c
index 5bf5c73..23bdcf4 100644
--- a/src/crypto/rand/urandom.c
+++ b/src/crypto/rand/urandom.c
@@ -12,16 +12,26 @@
  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
 
+#if !defined(_GNU_SOURCE)
+#define _GNU_SOURCE  /* needed for syscall() on Linux. */
+#endif
+
 #include <openssl/rand.h>
 
-#if !defined(OPENSSL_WINDOWS)
+#if !defined(OPENSSL_WINDOWS) && !defined(OPENSSL_FUCHSIA) && \
+    !defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE)
 
 #include <assert.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <stdio.h>
 #include <string.h>
 #include <unistd.h>
 
+#if defined(OPENSSL_LINUX)
+#include <sys/syscall.h>
+#endif
+
 #include <openssl/thread.h>
 #include <openssl/mem.h>
 
@@ -29,6 +39,43 @@
 #include "../internal.h"
 
 
+#if defined(OPENSSL_LINUX)
+
+#if defined(OPENSSL_X86_64)
+#define EXPECTED_SYS_getrandom 318
+#elif defined(OPENSSL_X86)
+#define EXPECTED_SYS_getrandom 355
+#elif defined(OPENSSL_AARCH64)
+#define EXPECTED_SYS_getrandom 278
+#elif defined(OPENSSL_ARM)
+#define EXPECTED_SYS_getrandom 384
+#elif defined(OPENSSL_PPC64LE)
+#define EXPECTED_SYS_getrandom 359
+#endif
+
+#if defined(EXPECTED_SYS_getrandom)
+#define USE_SYS_getrandom
+
+#if defined(SYS_getrandom)
+
+#if SYS_getrandom != EXPECTED_SYS_getrandom
+#error "system call number for getrandom is not the expected value"
+#endif
+
+#else  /* SYS_getrandom */
+
+#define SYS_getrandom EXPECTED_SYS_getrandom
+
+#endif  /* SYS_getrandom */
+
+#endif /* EXPECTED_SYS_getrandom */
+
+#if !defined(GRND_NONBLOCK)
+#define GRND_NONBLOCK 1
+#endif
+
+#endif  /* OPENSSL_LINUX */
+
 /* This file implements a PRNG by reading from /dev/urandom, optionally with a
  * buffer, which is unsafe across |fork|. */
 
@@ -44,12 +91,16 @@
 /* requested_lock is used to protect the |*_requested| variables. */
 static struct CRYPTO_STATIC_MUTEX requested_lock = CRYPTO_STATIC_MUTEX_INIT;
 
-/* urandom_fd_requested is set by |RAND_set_urandom_fd|.  It's protected by
+/* The following constants are magic values of |urandom_fd|. */
+static const int kUnset = -2;
+static const int kHaveGetrandom = -3;
+
+/* urandom_fd_requested is set by |RAND_set_urandom_fd|. It's protected by
  * |requested_lock|. */
-static int urandom_fd_requested = -2;
+static int urandom_fd_requested = -2 /* kUnset */;
 
 /* urandom_fd is a file descriptor to /dev/urandom. It's protected by |once|. */
-static int urandom_fd = -2;
+static int urandom_fd = -2 /* kUnset */;
 
 /* urandom_buffering_requested is set by |RAND_enable_fork_unsafe_buffering|.
  * It's protected by |requested_lock|. */
@@ -69,9 +120,34 @@
   CRYPTO_STATIC_MUTEX_lock_read(&requested_lock);
   urandom_buffering = urandom_buffering_requested;
   int fd = urandom_fd_requested;
-  CRYPTO_STATIC_MUTEX_unlock(&requested_lock);
+  CRYPTO_STATIC_MUTEX_unlock_read(&requested_lock);
 
-  if (fd == -2) {
+#if defined(USE_SYS_getrandom)
+  uint8_t dummy;
+  long getrandom_ret =
+      syscall(SYS_getrandom, &dummy, sizeof(dummy), GRND_NONBLOCK);
+
+  if (getrandom_ret == 1) {
+    urandom_fd = kHaveGetrandom;
+    return;
+  } else if (getrandom_ret == -1 && errno == EAGAIN) {
+    fprintf(stderr,
+            "getrandom indicates that the entropy pool has not been "
+            "initialized. Rather than continue with poor entropy, this process "
+            "will block until entropy is available.\n");
+    do {
+      getrandom_ret =
+          syscall(SYS_getrandom, &dummy, sizeof(dummy), 0 /* no flags */);
+    } while (getrandom_ret == -1 && errno == EINTR);
+
+    if (getrandom_ret == 1) {
+      urandom_fd = kHaveGetrandom;
+      return;
+    }
+  }
+#endif  /* USE_SYS_getrandom */
+
+  if (fd == kUnset) {
     do {
       fd = open("/dev/urandom", O_RDONLY);
     } while (fd == -1 && errno == EINTR);
@@ -96,8 +172,6 @@
   urandom_fd = fd;
 }
 
-void RAND_cleanup(void) {}
-
 void RAND_set_urandom_fd(int fd) {
   fd = dup(fd);
   if (fd < 0) {
@@ -106,10 +180,12 @@
 
   CRYPTO_STATIC_MUTEX_lock_write(&requested_lock);
   urandom_fd_requested = fd;
-  CRYPTO_STATIC_MUTEX_unlock(&requested_lock);
+  CRYPTO_STATIC_MUTEX_unlock_write(&requested_lock);
 
   CRYPTO_once(&once, init_once);
-  if (urandom_fd != fd) {
+  if (urandom_fd == kHaveGetrandom) {
+    close(fd);
+  } else if (urandom_fd != fd) {
     abort();  // Already initialized.
   }
 }
@@ -121,17 +197,25 @@
       abort();
     }
   } else {
-    fd = -2;
+    fd = kUnset;
   }
 
   CRYPTO_STATIC_MUTEX_lock_write(&requested_lock);
   urandom_buffering_requested = 1;
   urandom_fd_requested = fd;
-  CRYPTO_STATIC_MUTEX_unlock(&requested_lock);
+  CRYPTO_STATIC_MUTEX_unlock_write(&requested_lock);
 
   CRYPTO_once(&once, init_once);
-  if (urandom_buffering != 1 || (fd >= 0 && urandom_fd != fd)) {
-    abort();  // Already initialized.
+  if (urandom_buffering != 1) {
+    abort();  // Already initialized
+  }
+
+  if (fd >= 0) {
+    if (urandom_fd == kHaveGetrandom) {
+      close(fd);
+    } else if (urandom_fd != fd) {
+      abort();  // Already initialized.
+    }
   }
 }
 
@@ -146,7 +230,7 @@
   if (buf == NULL) {
     return NULL;
   }
-  buf->used = BUF_SIZE;  /* To trigger a |read_full| on first use. */
+  buf->used = BUF_SIZE;  /* To trigger a |fill_with_entropy| on first use. */
   if (!CRYPTO_set_thread_local(OPENSSL_THREAD_LOCAL_URANDOM_BUF, buf,
                                OPENSSL_free)) {
     OPENSSL_free(buf);
@@ -156,15 +240,42 @@
   return buf;
 }
 
-/* read_full reads exactly |len| bytes from |fd| into |out| and returns 1. In
- * the case of an error it returns 0. */
-static char read_full(int fd, uint8_t *out, size_t len) {
-  ssize_t r;
+#if defined(USE_SYS_getrandom) && defined(__has_feature)
+#if __has_feature(memory_sanitizer)
+void __msan_unpoison(void *, size_t);
+#endif
+#endif
 
+/* fill_with_entropy writes |len| bytes of entropy into |out|. It returns one
+ * on success and zero on error. */
+static char fill_with_entropy(uint8_t *out, size_t len) {
   while (len > 0) {
-    do {
-      r = read(fd, out, len);
-    } while (r == -1 && errno == EINTR);
+    ssize_t r;
+
+    if (urandom_fd == kHaveGetrandom) {
+#if defined(USE_SYS_getrandom)
+      do {
+        r = syscall(SYS_getrandom, out, len, 0 /* no flags */);
+      } while (r == -1 && errno == EINTR);
+
+#if defined(__has_feature)
+#if __has_feature(memory_sanitizer)
+      if (r > 0) {
+        /* MSAN doesn't recognise |syscall| and thus doesn't notice that we
+         * have initialised the output buffer. */
+        __msan_unpoison(out, r);
+      }
+#endif /* memory_sanitizer */
+#endif /*__has_feature */
+
+#else /* USE_SYS_getrandom */
+      abort();
+#endif
+    } else {
+      do {
+        r = read(urandom_fd, out, len);
+      } while (r == -1 && errno == EINTR);
+    }
 
     if (r <= 0) {
       return 0;
@@ -183,12 +294,12 @@
   size_t remaining = BUF_SIZE - buf->used;
 
   while (requested > remaining) {
-    memcpy(out, &buf->rand[buf->used], remaining);
+    OPENSSL_memcpy(out, &buf->rand[buf->used], remaining);
     buf->used += remaining;
     out += remaining;
     requested -= remaining;
 
-    if (!read_full(urandom_fd, buf->rand, BUF_SIZE)) {
+    if (!fill_with_entropy(buf->rand, BUF_SIZE)) {
       abort();
       return;
     }
@@ -196,7 +307,7 @@
     remaining = BUF_SIZE;
   }
 
-  memcpy(out, &buf->rand[buf->used], requested);
+  OPENSSL_memcpy(out, &buf->rand[buf->used], requested);
   buf->used += requested;
 }
 
@@ -215,9 +326,10 @@
     }
   }
 
-  if (!read_full(urandom_fd, out, requested)) {
+  if (!fill_with_entropy(out, requested)) {
     abort();
   }
 }
 
-#endif  /* !OPENSSL_WINDOWS */
+#endif /* !OPENSSL_WINDOWS && !defined(OPENSSL_FUCHSIA) && \
+          !BORINGSSL_UNSAFE_DETERMINISTIC_MODE */
diff --git a/src/crypto/rand/windows.c b/src/crypto/rand/windows.c
index 1a0cb8b..f47182d 100644
--- a/src/crypto/rand/windows.c
+++ b/src/crypto/rand/windows.c
@@ -14,12 +14,12 @@
 
 #include <openssl/rand.h>
 
-#if defined(OPENSSL_WINDOWS)
+#if defined(OPENSSL_WINDOWS) && !defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE)
 
 #include <limits.h>
 #include <stdlib.h>
 
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
 
 #include <windows.h>
 
@@ -30,19 +30,16 @@
 #include <ntsecapi.h>
 #undef SystemFunction036
 
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
 
 #include "internal.h"
 
 
-void RAND_cleanup(void) {
-}
-
 void CRYPTO_sysrand(uint8_t *out, size_t requested) {
   while (requested > 0) {
     ULONG output_bytes_this_pass = ULONG_MAX;
     if (requested < output_bytes_this_pass) {
-      output_bytes_this_pass = requested;
+      output_bytes_this_pass = (ULONG)requested;
     }
     if (RtlGenRandom(out, output_bytes_this_pass) == FALSE) {
       abort();
@@ -53,4 +50,4 @@
   return;
 }
 
-#endif  /* OPENSSL_WINDOWS */
+#endif  /* OPENSSL_WINDOWS && !BORINGSSL_UNSAFE_DETERMINISTIC_MODE */
diff --git a/src/crypto/rc4/CMakeLists.txt b/src/crypto/rc4/CMakeLists.txt
index 151773a..a008fe5 100644
--- a/src/crypto/rc4/CMakeLists.txt
+++ b/src/crypto/rc4/CMakeLists.txt
@@ -1,29 +1,9 @@
 include_directories(../../include)
 
-if (${ARCH} STREQUAL "x86_64")
-  set(
-    RC4_ARCH_SOURCES
-
-    rc4-x86_64.${ASM_EXT}
-  )
-endif()
-
-if (${ARCH} STREQUAL "x86")
-  set(
-    RC4_ARCH_SOURCES
-
-    rc4-586.${ASM_EXT}
-  )
-endif()
-
 add_library(
   rc4
 
   OBJECT
 
   rc4.c
-  ${RC4_ARCH_SOURCES}
 )
-
-perlasm(rc4-x86_64.${ASM_EXT} asm/rc4-x86_64.pl)
-perlasm(rc4-586.${ASM_EXT} asm/rc4-586.pl)
diff --git a/src/crypto/rc4/asm/rc4-586.pl b/src/crypto/rc4/asm/rc4-586.pl
deleted file mode 100644
index fc860ae..0000000
--- a/src/crypto/rc4/asm/rc4-586.pl
+++ /dev/null
@@ -1,414 +0,0 @@
-#!/usr/bin/env perl
-
-# ====================================================================
-# [Re]written by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
-# project. The module is, however, dual licensed under OpenSSL and
-# CRYPTOGAMS licenses depending on where you obtain it. For further
-# details see http://www.openssl.org/~appro/cryptogams/.
-# ====================================================================
-
-# At some point it became apparent that the original SSLeay RC4
-# assembler implementation performs suboptimally on latest IA-32
-# microarchitectures. After re-tuning performance has changed as
-# following:
-#
-# Pentium	-10%
-# Pentium III	+12%
-# AMD		+50%(*)
-# P4		+250%(**)
-#
-# (*)	This number is actually a trade-off:-) It's possible to
-#	achieve	+72%, but at the cost of -48% off PIII performance.
-#	In other words code performing further 13% faster on AMD
-#	would perform almost 2 times slower on Intel PIII...
-#	For reference! This code delivers ~80% of rc4-amd64.pl
-#	performance on the same Opteron machine.
-# (**)	This number requires compressed key schedule set up by
-#	RC4_set_key [see commentary below for further details].
-#
-#					<appro@fy.chalmers.se>
-
-# May 2011
-#
-# Optimize for Core2 and Westmere [and incidentally Opteron]. Current
-# performance in cycles per processed byte (less is better) and
-# improvement relative to previous version of this module is:
-#
-# Pentium	10.2			# original numbers
-# Pentium III	7.8(*)
-# Intel P4	7.5
-#
-# Opteron	6.1/+20%		# new MMX numbers
-# Core2		5.3/+67%(**)
-# Westmere	5.1/+94%(**)
-# Sandy Bridge	5.0/+8%
-# Atom		12.6/+6%
-#
-# (*)	PIII can actually deliver 6.6 cycles per byte with MMX code,
-#	but this specific code performs poorly on Core2. And vice
-#	versa, below MMX/SSE code delivering 5.8/7.1 on Core2 performs
-#	poorly on PIII, at 8.0/14.5:-( As PIII is not a "hot" CPU
-#	[anymore], I chose to discard PIII-specific code path and opt
-#	for original IALU-only code, which is why MMX/SSE code path
-#	is guarded by SSE2 bit (see below), not MMX/SSE.
-# (**)	Performance vs. block size on Core2 and Westmere had a maximum
-#	at ... 64 bytes block size. And it was quite a maximum, 40-60%
-#	in comparison to largest 8KB block size. Above improvement
-#	coefficients are for the largest block size.
-
-$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
-push(@INC,"${dir}","${dir}../../perlasm");
-require "x86asm.pl";
-
-&asm_init($ARGV[0],"rc4-586.pl",$x86only = $ARGV[$#ARGV] eq "386");
-
-$xx="eax";
-$yy="ebx";
-$tx="ecx";
-$ty="edx";
-$inp="esi";
-$out="ebp";
-$dat="edi";
-
-sub RC4_loop {
-  my $i=shift;
-  my $func = ($i==0)?*mov:*or;
-
-	&add	(&LB($yy),&LB($tx));
-	&mov	($ty,&DWP(0,$dat,$yy,4));
-	&mov	(&DWP(0,$dat,$yy,4),$tx);
-	&mov	(&DWP(0,$dat,$xx,4),$ty);
-	&add	($ty,$tx);
-	&inc	(&LB($xx));
-	&and	($ty,0xff);
-	&ror	($out,8)	if ($i!=0);
-	if ($i<3) {
-	  &mov	($tx,&DWP(0,$dat,$xx,4));
-	} else {
-	  &mov	($tx,&wparam(3));	# reload [re-biased] out
-	}
-	&$func	($out,&DWP(0,$dat,$ty,4));
-}
-
-if ($alt=0) {
-  # >20% faster on Atom and Sandy Bridge[!], 8% faster on Opteron,
-  # but ~40% slower on Core2 and Westmere... Attempt to add movz
-  # brings down Opteron by 25%, Atom and Sandy Bridge by 15%, yet
-  # on Core2 with movz it's almost 20% slower than below alternative
-  # code... Yes, it's a total mess...
-  my @XX=($xx,$out);
-  $RC4_loop_mmx = sub {		# SSE actually...
-    my $i=shift;
-    my $j=$i<=0?0:$i>>1;
-    my $mm=$i<=0?"mm0":"mm".($i&1);
-
-	&add	(&LB($yy),&LB($tx));
-	&lea	(@XX[1],&DWP(1,@XX[0]));
-	&pxor	("mm2","mm0")				if ($i==0);
-	&psllq	("mm1",8)				if ($i==0);
-	&and	(@XX[1],0xff);
-	&pxor	("mm0","mm0")				if ($i<=0);
-	&mov	($ty,&DWP(0,$dat,$yy,4));
-	&mov	(&DWP(0,$dat,$yy,4),$tx);
-	&pxor	("mm1","mm2")				if ($i==0);
-	&mov	(&DWP(0,$dat,$XX[0],4),$ty);
-	&add	(&LB($ty),&LB($tx));
-	&movd	(@XX[0],"mm7")				if ($i==0);
-	&mov	($tx,&DWP(0,$dat,@XX[1],4));
-	&pxor	("mm1","mm1")				if ($i==1);
-	&movq	("mm2",&QWP(0,$inp))			if ($i==1);
-	&movq	(&QWP(-8,(@XX[0],$inp)),"mm1")		if ($i==0);
-	&pinsrw	($mm,&DWP(0,$dat,$ty,4),$j);
-
-	push	(@XX,shift(@XX))			if ($i>=0);
-  }
-} else {
-  # Using pinsrw here improves performane on Intel CPUs by 2-3%, but
-  # brings down AMD by 7%...
-  $RC4_loop_mmx = sub {
-    my $i=shift;
-
-	&add	(&LB($yy),&LB($tx));
-	&psllq	("mm1",8*(($i-1)&7))			if (abs($i)!=1);
-	&mov	($ty,&DWP(0,$dat,$yy,4));
-	&mov	(&DWP(0,$dat,$yy,4),$tx);
-	&mov	(&DWP(0,$dat,$xx,4),$ty);
-	&inc	($xx);
-	&add	($ty,$tx);
-	&movz	($xx,&LB($xx));				# (*)
-	&movz	($ty,&LB($ty));				# (*)
-	&pxor	("mm2",$i==1?"mm0":"mm1")		if ($i>=0);
-	&movq	("mm0",&QWP(0,$inp))			if ($i<=0);
-	&movq	(&QWP(-8,($out,$inp)),"mm2")		if ($i==0);
-	&mov	($tx,&DWP(0,$dat,$xx,4));
-	&movd	($i>0?"mm1":"mm2",&DWP(0,$dat,$ty,4));
-
-	# (*)	This is the key to Core2 and Westmere performance.
-	#	Whithout movz out-of-order execution logic confuses
-	#	itself and fails to reorder loads and stores. Problem
-	#	appears to be fixed in Sandy Bridge...
-  }
-}
-
-&external_label("OPENSSL_ia32cap_P");
-
-# void asm_RC4(RC4_KEY *key,size_t len,const unsigned char *inp,unsigned char *out);
-&function_begin("asm_RC4");
-	&mov	($dat,&wparam(0));	# load key schedule pointer
-	&mov	($ty, &wparam(1));	# load len
-	&mov	($inp,&wparam(2));	# load inp
-	&mov	($out,&wparam(3));	# load out
-
-	&xor	($xx,$xx);		# avoid partial register stalls
-	&xor	($yy,$yy);
-
-	&cmp	($ty,0);		# safety net
-	&je	(&label("abort"));
-
-	&mov	(&LB($xx),&BP(0,$dat));	# load key->x
-	&mov	(&LB($yy),&BP(4,$dat));	# load key->y
-	&add	($dat,8);
-
-	&lea	($tx,&DWP(0,$inp,$ty));
-	&sub	($out,$inp);		# re-bias out
-	&mov	(&wparam(1),$tx);	# save input+len
-
-	&inc	(&LB($xx));
-
-	# detect compressed key schedule...
-	&cmp	(&DWP(256,$dat),-1);
-	&je	(&label("RC4_CHAR"));
-
-	&mov	($tx,&DWP(0,$dat,$xx,4));
-
-	&and	($ty,-4);		# how many 4-byte chunks?
-	&jz	(&label("loop1"));
-
-	&mov	(&wparam(3),$out);	# $out as accumulator in these loops
-					if ($x86only) {
-	&jmp	(&label("go4loop4"));
-					} else {
-	&test	($ty,-8);
-	&jz	(&label("go4loop4"));
-
-	&picmeup($out,"OPENSSL_ia32cap_P");
-	&bt	(&DWP(0,$out),26);	# check SSE2 bit [could have been MMX]
-	&jnc	(&label("go4loop4"));
-
-	&mov	($out,&wparam(3))	if (!$alt);
-	&movd	("mm7",&wparam(3))	if ($alt);
-	&and	($ty,-8);
-	&lea	($ty,&DWP(-8,$inp,$ty));
-	&mov	(&DWP(-4,$dat),$ty);	# save input+(len/8)*8-8
-
-	&$RC4_loop_mmx(-1);
-	&jmp(&label("loop_mmx_enter"));
-
-	&set_label("loop_mmx",16);
-		&$RC4_loop_mmx(0);
-	&set_label("loop_mmx_enter");
-		for 	($i=1;$i<8;$i++) { &$RC4_loop_mmx($i); }
-		&mov	($ty,$yy);
-		&xor	($yy,$yy);		# this is second key to Core2
-		&mov	(&LB($yy),&LB($ty));	# and Westmere performance...
-		&cmp	($inp,&DWP(-4,$dat));
-		&lea	($inp,&DWP(8,$inp));
-	&jb	(&label("loop_mmx"));
-
-    if ($alt) {
-	&movd	($out,"mm7");
-	&pxor	("mm2","mm0");
-	&psllq	("mm1",8);
-	&pxor	("mm1","mm2");
-	&movq	(&QWP(-8,$out,$inp),"mm1");
-    } else {
-	&psllq	("mm1",56);
-	&pxor	("mm2","mm1");
-	&movq	(&QWP(-8,$out,$inp),"mm2");
-    }
-	&emms	();
-
-	&cmp	($inp,&wparam(1));	# compare to input+len
-	&je	(&label("done"));
-	&jmp	(&label("loop1"));
-					}
-
-&set_label("go4loop4",16);
-	&lea	($ty,&DWP(-4,$inp,$ty));
-	&mov	(&wparam(2),$ty);	# save input+(len/4)*4-4
-
-	&set_label("loop4");
-		for ($i=0;$i<4;$i++) { RC4_loop($i); }
-		&ror	($out,8);
-		&xor	($out,&DWP(0,$inp));
-		&cmp	($inp,&wparam(2));	# compare to input+(len/4)*4-4
-		&mov	(&DWP(0,$tx,$inp),$out);# $tx holds re-biased out here
-		&lea	($inp,&DWP(4,$inp));
-		&mov	($tx,&DWP(0,$dat,$xx,4));
-	&jb	(&label("loop4"));
-
-	&cmp	($inp,&wparam(1));	# compare to input+len
-	&je	(&label("done"));
-	&mov	($out,&wparam(3));	# restore $out
-
-	&set_label("loop1",16);
-		&add	(&LB($yy),&LB($tx));
-		&mov	($ty,&DWP(0,$dat,$yy,4));
-		&mov	(&DWP(0,$dat,$yy,4),$tx);
-		&mov	(&DWP(0,$dat,$xx,4),$ty);
-		&add	($ty,$tx);
-		&inc	(&LB($xx));
-		&and	($ty,0xff);
-		&mov	($ty,&DWP(0,$dat,$ty,4));
-		&xor	(&LB($ty),&BP(0,$inp));
-		&lea	($inp,&DWP(1,$inp));
-		&mov	($tx,&DWP(0,$dat,$xx,4));
-		&cmp	($inp,&wparam(1));	# compare to input+len
-		&mov	(&BP(-1,$out,$inp),&LB($ty));
-	&jb	(&label("loop1"));
-
-	&jmp	(&label("done"));
-
-# this is essentially Intel P4 specific codepath...
-&set_label("RC4_CHAR",16);
-	&movz	($tx,&BP(0,$dat,$xx));
-	# strangely enough unrolled loop performs over 20% slower...
-	&set_label("cloop1");
-		&add	(&LB($yy),&LB($tx));
-		&movz	($ty,&BP(0,$dat,$yy));
-		&mov	(&BP(0,$dat,$yy),&LB($tx));
-		&mov	(&BP(0,$dat,$xx),&LB($ty));
-		&add	(&LB($ty),&LB($tx));
-		&movz	($ty,&BP(0,$dat,$ty));
-		&add	(&LB($xx),1);
-		&xor	(&LB($ty),&BP(0,$inp));
-		&lea	($inp,&DWP(1,$inp));
-		&movz	($tx,&BP(0,$dat,$xx));
-		&cmp	($inp,&wparam(1));
-		&mov	(&BP(-1,$out,$inp),&LB($ty));
-	&jb	(&label("cloop1"));
-
-&set_label("done");
-	&dec	(&LB($xx));
-	&mov	(&DWP(-4,$dat),$yy);		# save key->y
-	&mov	(&BP(-8,$dat),&LB($xx));	# save key->x
-&set_label("abort");
-&function_end("asm_RC4");
-
-########################################################################
-
-$inp="esi";
-$out="edi";
-$idi="ebp";
-$ido="ecx";
-$idx="edx";
-
-# void asm_RC4_set_key(RC4_KEY *key,int len,const unsigned char *data);
-&function_begin("asm_RC4_set_key");
-	&mov	($out,&wparam(0));		# load key
-	&mov	($idi,&wparam(1));		# load len
-	&mov	($inp,&wparam(2));		# load data
-	&picmeup($idx,"OPENSSL_ia32cap_P");
-
-	&lea	($out,&DWP(2*4,$out));		# &key->data
-	&lea	($inp,&DWP(0,$inp,$idi));	# $inp to point at the end
-	&neg	($idi);
-	&xor	("eax","eax");
-	&mov	(&DWP(-4,$out),$idi);		# borrow key->y
-
-	&bt	(&DWP(0,$idx),20);		# check for bit#20
-	&jc	(&label("c1stloop"));
-
-&set_label("w1stloop",16);
-	&mov	(&DWP(0,$out,"eax",4),"eax");	# key->data[i]=i;
-	&add	(&LB("eax"),1);			# i++;
-	&jnc	(&label("w1stloop"));
-
-	&xor	($ido,$ido);
-	&xor	($idx,$idx);
-
-&set_label("w2ndloop",16);
-	&mov	("eax",&DWP(0,$out,$ido,4));
-	&add	(&LB($idx),&BP(0,$inp,$idi));
-	&add	(&LB($idx),&LB("eax"));
-	&add	($idi,1);
-	&mov	("ebx",&DWP(0,$out,$idx,4));
-	&jnz	(&label("wnowrap"));
-	  &mov	($idi,&DWP(-4,$out));
-	&set_label("wnowrap");
-	&mov	(&DWP(0,$out,$idx,4),"eax");
-	&mov	(&DWP(0,$out,$ido,4),"ebx");
-	&add	(&LB($ido),1);
-	&jnc	(&label("w2ndloop"));
-&jmp	(&label("exit"));
-
-# Unlike all other x86 [and x86_64] implementations, Intel P4 core
-# [including EM64T] was found to perform poorly with above "32-bit" key
-# schedule, a.k.a. RC4_INT. Performance improvement for IA-32 hand-coded
-# assembler turned out to be 3.5x if re-coded for compressed 8-bit one,
-# a.k.a. RC4_CHAR! It's however inappropriate to just switch to 8-bit
-# schedule for x86[_64], because non-P4 implementations suffer from
-# significant performance losses then, e.g. PIII exhibits >2x
-# deterioration, and so does Opteron. In order to assure optimal
-# all-round performance, we detect P4 at run-time and set up compressed
-# key schedule, which is recognized by RC4 procedure.
-
-&set_label("c1stloop",16);
-	&mov	(&BP(0,$out,"eax"),&LB("eax"));	# key->data[i]=i;
-	&add	(&LB("eax"),1);			# i++;
-	&jnc	(&label("c1stloop"));
-
-	&xor	($ido,$ido);
-	&xor	($idx,$idx);
-	&xor	("ebx","ebx");
-
-&set_label("c2ndloop",16);
-	&mov	(&LB("eax"),&BP(0,$out,$ido));
-	&add	(&LB($idx),&BP(0,$inp,$idi));
-	&add	(&LB($idx),&LB("eax"));
-	&add	($idi,1);
-	&mov	(&LB("ebx"),&BP(0,$out,$idx));
-	&jnz	(&label("cnowrap"));
-	  &mov	($idi,&DWP(-4,$out));
-	&set_label("cnowrap");
-	&mov	(&BP(0,$out,$idx),&LB("eax"));
-	&mov	(&BP(0,$out,$ido),&LB("ebx"));
-	&add	(&LB($ido),1);
-	&jnc	(&label("c2ndloop"));
-
-	&mov	(&DWP(256,$out),-1);		# mark schedule as compressed
-
-&set_label("exit");
-	&xor	("eax","eax");
-	&mov	(&DWP(-8,$out),"eax");		# key->x=0;
-	&mov	(&DWP(-4,$out),"eax");		# key->y=0;
-&function_end("asm_RC4_set_key");
-
-# const char *RC4_options(void);
-&function_begin_B("RC4_options");
-	&call	(&label("pic_point"));
-&set_label("pic_point");
-	&blindpop("eax");
-	&lea	("eax",&DWP(&label("opts")."-".&label("pic_point"),"eax"));
-	&picmeup("edx","OPENSSL_ia32cap_P");
-	&mov	("edx",&DWP(0,"edx"));
-	&bt	("edx",20);
-	&jc	(&label("1xchar"));
-	&bt	("edx",26);
-	&jnc	(&label("ret"));
-	&add	("eax",25);
-	&ret	();
-&set_label("1xchar");
-	&add	("eax",12);
-&set_label("ret");
-	&ret	();
-&set_label("opts",64);
-&asciz	("rc4(4x,int)");
-&asciz	("rc4(1x,char)");
-&asciz	("rc4(8x,mmx)");
-&asciz	("RC4 for x86, CRYPTOGAMS by <appro\@openssl.org>");
-&align	(64);
-&function_end_B("RC4_options");
-
-&asm_finish();
-
diff --git a/src/crypto/rc4/asm/rc4-x86_64.pl b/src/crypto/rc4/asm/rc4-x86_64.pl
deleted file mode 100644
index cef6268..0000000
--- a/src/crypto/rc4/asm/rc4-x86_64.pl
+++ /dev/null
@@ -1,653 +0,0 @@
-#!/usr/bin/env perl
-#
-# ====================================================================
-# Written by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
-# project. The module is, however, dual licensed under OpenSSL and
-# CRYPTOGAMS licenses depending on where you obtain it. For further
-# details see http://www.openssl.org/~appro/cryptogams/.
-# ====================================================================
-#
-# July 2004
-#
-# 2.22x RC4 tune-up:-) It should be noted though that my hand [as in
-# "hand-coded assembler"] doesn't stand for the whole improvement
-# coefficient. It turned out that eliminating RC4_CHAR from config
-# line results in ~40% improvement (yes, even for C implementation).
-# Presumably it has everything to do with AMD cache architecture and
-# RAW or whatever penalties. Once again! The module *requires* config
-# line *without* RC4_CHAR! As for coding "secret," I bet on partial
-# register arithmetics. For example instead of 'inc %r8; and $255,%r8'
-# I simply 'inc %r8b'. Even though optimization manual discourages
-# to operate on partial registers, it turned out to be the best bet.
-# At least for AMD... How IA32E would perform remains to be seen...
-
-# November 2004
-#
-# As was shown by Marc Bevand reordering of couple of load operations
-# results in even higher performance gain of 3.3x:-) At least on
-# Opteron... For reference, 1x in this case is RC4_CHAR C-code
-# compiled with gcc 3.3.2, which performs at ~54MBps per 1GHz clock.
-# Latter means that if you want to *estimate* what to expect from
-# *your* Opteron, then multiply 54 by 3.3 and clock frequency in GHz.
-
-# November 2004
-#
-# Intel P4 EM64T core was found to run the AMD64 code really slow...
-# The only way to achieve comparable performance on P4 was to keep
-# RC4_CHAR. Kind of ironic, huh? As it's apparently impossible to
-# compose blended code, which would perform even within 30% marginal
-# on either AMD and Intel platforms, I implement both cases. See
-# rc4_skey.c for further details...
-
-# April 2005
-#
-# P4 EM64T core appears to be "allergic" to 64-bit inc/dec. Replacing 
-# those with add/sub results in 50% performance improvement of folded
-# loop...
-
-# May 2005
-#
-# As was shown by Zou Nanhai loop unrolling can improve Intel EM64T
-# performance by >30% [unlike P4 32-bit case that is]. But this is
-# provided that loads are reordered even more aggressively! Both code
-# pathes, AMD64 and EM64T, reorder loads in essentially same manner
-# as my IA-64 implementation. On Opteron this resulted in modest 5%
-# improvement [I had to test it], while final Intel P4 performance
-# achieves respectful 432MBps on 2.8GHz processor now. For reference.
-# If executed on Xeon, current RC4_CHAR code-path is 2.7x faster than
-# RC4_INT code-path. While if executed on Opteron, it's only 25%
-# slower than the RC4_INT one [meaning that if CPU µ-arch detection
-# is not implemented, then this final RC4_CHAR code-path should be
-# preferred, as it provides better *all-round* performance].
-
-# March 2007
-#
-# Intel Core2 was observed to perform poorly on both code paths:-( It
-# apparently suffers from some kind of partial register stall, which
-# occurs in 64-bit mode only [as virtually identical 32-bit loop was
-# observed to outperform 64-bit one by almost 50%]. Adding two movzb to
-# cloop1 boosts its performance by 80%! This loop appears to be optimal
-# fit for Core2 and therefore the code was modified to skip cloop8 on
-# this CPU.
-
-# May 2010
-#
-# Intel Westmere was observed to perform suboptimally. Adding yet
-# another movzb to cloop1 improved performance by almost 50%! Core2
-# performance is improved too, but nominally...
-
-# May 2011
-#
-# The only code path that was not modified is P4-specific one. Non-P4
-# Intel code path optimization is heavily based on submission by Maxim
-# Perminov, Maxim Locktyukhin and Jim Guilford of Intel. I've used
-# some of the ideas even in attempt to optmize the original RC4_INT
-# code path... Current performance in cycles per processed byte (less
-# is better) and improvement coefficients relative to previous
-# version of this module are:
-#
-# Opteron	5.3/+0%(*)
-# P4		6.5
-# Core2		6.2/+15%(**)
-# Westmere	4.2/+60%
-# Sandy Bridge	4.2/+120%
-# Atom		9.3/+80%
-#
-# (*)	But corresponding loop has less instructions, which should have
-#	positive effect on upcoming Bulldozer, which has one less ALU.
-#	For reference, Intel code runs at 6.8 cpb rate on Opteron.
-# (**)	Note that Core2 result is ~15% lower than corresponding result
-#	for 32-bit code, meaning that it's possible to improve it,
-#	but more than likely at the cost of the others (see rc4-586.pl
-#	to get the idea)...
-
-$flavour = shift;
-$output  = shift;
-if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
-
-$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
-
-$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
-( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
-( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
-die "can't locate x86_64-xlate.pl";
-
-open OUT,"| \"$^X\" $xlate $flavour $output";
-*STDOUT=*OUT;
-
-$dat="%rdi";	    # arg1
-$len="%rsi";	    # arg2
-$inp="%rdx";	    # arg3
-$out="%rcx";	    # arg4
-
-{
-$code=<<___;
-.text
-.extern	OPENSSL_ia32cap_P
-
-.globl	asm_RC4
-.type	asm_RC4,\@function,4
-.align	16
-asm_RC4:
-	or	$len,$len
-	jne	.Lentry
-	ret
-.Lentry:
-	push	%rbx
-	push	%r12
-	push	%r13
-.Lprologue:
-	mov	$len,%r11
-	mov	$inp,%r12
-	mov	$out,%r13
-___
-my $len="%r11";		# reassign input arguments
-my $inp="%r12";
-my $out="%r13";
-
-my @XX=("%r10","%rsi");
-my @TX=("%rax","%rbx");
-my $YY="%rcx";
-my $TY="%rdx";
-
-$code.=<<___;
-	xor	$XX[0],$XX[0]
-	xor	$YY,$YY
-
-	lea	8($dat),$dat
-	mov	-8($dat),$XX[0]#b
-	mov	-4($dat),$YY#b
-	cmpl	\$-1,256($dat)
-	je	.LRC4_CHAR
-	mov	OPENSSL_ia32cap_P(%rip),%r8d
-	xor	$TX[1],$TX[1]
-	inc	$XX[0]#b
-	sub	$XX[0],$TX[1]
-	sub	$inp,$out
-	movl	($dat,$XX[0],4),$TX[0]#d
-	test	\$-16,$len
-	jz	.Lloop1
-	bt	\$30,%r8d	# Intel CPU?
-	jc	.Lintel
-	and	\$7,$TX[1]
-	lea	1($XX[0]),$XX[1]
-	jz	.Loop8
-	sub	$TX[1],$len
-.Loop8_warmup:
-	add	$TX[0]#b,$YY#b
-	movl	($dat,$YY,4),$TY#d
-	movl	$TX[0]#d,($dat,$YY,4)
-	movl	$TY#d,($dat,$XX[0],4)
-	add	$TY#b,$TX[0]#b
-	inc	$XX[0]#b
-	movl	($dat,$TX[0],4),$TY#d
-	movl	($dat,$XX[0],4),$TX[0]#d
-	xorb	($inp),$TY#b
-	movb	$TY#b,($out,$inp)
-	lea	1($inp),$inp
-	dec	$TX[1]
-	jnz	.Loop8_warmup
-
-	lea	1($XX[0]),$XX[1]
-	jmp	.Loop8
-.align	16
-.Loop8:
-___
-for ($i=0;$i<8;$i++) {
-$code.=<<___ if ($i==7);
-	add	\$8,$XX[1]#b
-___
-$code.=<<___;
-	add	$TX[0]#b,$YY#b
-	movl	($dat,$YY,4),$TY#d
-	movl	$TX[0]#d,($dat,$YY,4)
-	movl	`4*($i==7?-1:$i)`($dat,$XX[1],4),$TX[1]#d
-	ror	\$8,%r8				# ror is redundant when $i=0
-	movl	$TY#d,4*$i($dat,$XX[0],4)
-	add	$TX[0]#b,$TY#b
-	movb	($dat,$TY,4),%r8b
-___
-push(@TX,shift(@TX)); #push(@XX,shift(@XX));	# "rotate" registers
-}
-$code.=<<___;
-	add	\$8,$XX[0]#b
-	ror	\$8,%r8
-	sub	\$8,$len
-
-	xor	($inp),%r8
-	mov	%r8,($out,$inp)
-	lea	8($inp),$inp
-
-	test	\$-8,$len
-	jnz	.Loop8
-	cmp	\$0,$len
-	jne	.Lloop1
-	jmp	.Lexit
-
-.align	16
-.Lintel:
-	test	\$-32,$len
-	jz	.Lloop1
-	and	\$15,$TX[1]
-	jz	.Loop16_is_hot
-	sub	$TX[1],$len
-.Loop16_warmup:
-	add	$TX[0]#b,$YY#b
-	movl	($dat,$YY,4),$TY#d
-	movl	$TX[0]#d,($dat,$YY,4)
-	movl	$TY#d,($dat,$XX[0],4)
-	add	$TY#b,$TX[0]#b
-	inc	$XX[0]#b
-	movl	($dat,$TX[0],4),$TY#d
-	movl	($dat,$XX[0],4),$TX[0]#d
-	xorb	($inp),$TY#b
-	movb	$TY#b,($out,$inp)
-	lea	1($inp),$inp
-	dec	$TX[1]
-	jnz	.Loop16_warmup
-
-	mov	$YY,$TX[1]
-	xor	$YY,$YY
-	mov	$TX[1]#b,$YY#b
-
-.Loop16_is_hot:
-	lea	($dat,$XX[0],4),$XX[1]
-___
-sub RC4_loop {
-  my $i=shift;
-  my $j=$i<0?0:$i;
-  my $xmm="%xmm".($j&1);
-
-    $code.="	add	\$16,$XX[0]#b\n"		if ($i==15);
-    $code.="	movdqu	($inp),%xmm2\n"			if ($i==15);
-    $code.="	add	$TX[0]#b,$YY#b\n"		if ($i<=0);
-    $code.="	movl	($dat,$YY,4),$TY#d\n";
-    $code.="	pxor	%xmm0,%xmm2\n"			if ($i==0);
-    $code.="	psllq	\$8,%xmm1\n"			if ($i==0);
-    $code.="	pxor	$xmm,$xmm\n"			if ($i<=1);
-    $code.="	movl	$TX[0]#d,($dat,$YY,4)\n";
-    $code.="	add	$TY#b,$TX[0]#b\n";
-    $code.="	movl	`4*($j+1)`($XX[1]),$TX[1]#d\n"	if ($i<15);
-    $code.="	movz	$TX[0]#b,$TX[0]#d\n";
-    $code.="	movl	$TY#d,4*$j($XX[1])\n";
-    $code.="	pxor	%xmm1,%xmm2\n"			if ($i==0);
-    $code.="	lea	($dat,$XX[0],4),$XX[1]\n"	if ($i==15);
-    $code.="	add	$TX[1]#b,$YY#b\n"		if ($i<15);
-    $code.="	pinsrw	\$`($j>>1)&7`,($dat,$TX[0],4),$xmm\n";
-    $code.="	movdqu	%xmm2,($out,$inp)\n"		if ($i==0);
-    $code.="	lea	16($inp),$inp\n"		if ($i==0);
-    $code.="	movl	($XX[1]),$TX[1]#d\n"		if ($i==15);
-}
-	RC4_loop(-1);
-$code.=<<___;
-	jmp	.Loop16_enter
-.align	16
-.Loop16:
-___
-
-for ($i=0;$i<16;$i++) {
-    $code.=".Loop16_enter:\n"		if ($i==1);
-	RC4_loop($i);
-	push(@TX,shift(@TX)); 		# "rotate" registers
-}
-$code.=<<___;
-	mov	$YY,$TX[1]
-	xor	$YY,$YY			# keyword to partial register
-	sub	\$16,$len
-	mov	$TX[1]#b,$YY#b
-	test	\$-16,$len
-	jnz	.Loop16
-
-	psllq	\$8,%xmm1
-	pxor	%xmm0,%xmm2
-	pxor	%xmm1,%xmm2
-	movdqu	%xmm2,($out,$inp)
-	lea	16($inp),$inp
-
-	cmp	\$0,$len
-	jne	.Lloop1
-	jmp	.Lexit
-
-.align	16
-.Lloop1:
-	add	$TX[0]#b,$YY#b
-	movl	($dat,$YY,4),$TY#d
-	movl	$TX[0]#d,($dat,$YY,4)
-	movl	$TY#d,($dat,$XX[0],4)
-	add	$TY#b,$TX[0]#b
-	inc	$XX[0]#b
-	movl	($dat,$TX[0],4),$TY#d
-	movl	($dat,$XX[0],4),$TX[0]#d
-	xorb	($inp),$TY#b
-	movb	$TY#b,($out,$inp)
-	lea	1($inp),$inp
-	dec	$len
-	jnz	.Lloop1
-	jmp	.Lexit
-
-.align	16
-.LRC4_CHAR:
-	add	\$1,$XX[0]#b
-	movzb	($dat,$XX[0]),$TX[0]#d
-	test	\$-8,$len
-	jz	.Lcloop1
-	jmp	.Lcloop8
-.align	16
-.Lcloop8:
-	mov	($inp),%r8d
-	mov	4($inp),%r9d
-___
-# unroll 2x4-wise, because 64-bit rotates kill Intel P4...
-for ($i=0;$i<4;$i++) {
-$code.=<<___;
-	add	$TX[0]#b,$YY#b
-	lea	1($XX[0]),$XX[1]
-	movzb	($dat,$YY),$TY#d
-	movzb	$XX[1]#b,$XX[1]#d
-	movzb	($dat,$XX[1]),$TX[1]#d
-	movb	$TX[0]#b,($dat,$YY)
-	cmp	$XX[1],$YY
-	movb	$TY#b,($dat,$XX[0])
-	jne	.Lcmov$i			# Intel cmov is sloooow...
-	mov	$TX[0],$TX[1]
-.Lcmov$i:
-	add	$TX[0]#b,$TY#b
-	xor	($dat,$TY),%r8b
-	ror	\$8,%r8d
-___
-push(@TX,shift(@TX)); push(@XX,shift(@XX));	# "rotate" registers
-}
-for ($i=4;$i<8;$i++) {
-$code.=<<___;
-	add	$TX[0]#b,$YY#b
-	lea	1($XX[0]),$XX[1]
-	movzb	($dat,$YY),$TY#d
-	movzb	$XX[1]#b,$XX[1]#d
-	movzb	($dat,$XX[1]),$TX[1]#d
-	movb	$TX[0]#b,($dat,$YY)
-	cmp	$XX[1],$YY
-	movb	$TY#b,($dat,$XX[0])
-	jne	.Lcmov$i			# Intel cmov is sloooow...
-	mov	$TX[0],$TX[1]
-.Lcmov$i:
-	add	$TX[0]#b,$TY#b
-	xor	($dat,$TY),%r9b
-	ror	\$8,%r9d
-___
-push(@TX,shift(@TX)); push(@XX,shift(@XX));	# "rotate" registers
-}
-$code.=<<___;
-	lea	-8($len),$len
-	mov	%r8d,($out)
-	lea	8($inp),$inp
-	mov	%r9d,4($out)
-	lea	8($out),$out
-
-	test	\$-8,$len
-	jnz	.Lcloop8
-	cmp	\$0,$len
-	jne	.Lcloop1
-	jmp	.Lexit
-___
-$code.=<<___;
-.align	16
-.Lcloop1:
-	add	$TX[0]#b,$YY#b
-	movzb	$YY#b,$YY#d
-	movzb	($dat,$YY),$TY#d
-	movb	$TX[0]#b,($dat,$YY)
-	movb	$TY#b,($dat,$XX[0])
-	add	$TX[0]#b,$TY#b
-	add	\$1,$XX[0]#b
-	movzb	$TY#b,$TY#d
-	movzb	$XX[0]#b,$XX[0]#d
-	movzb	($dat,$TY),$TY#d
-	movzb	($dat,$XX[0]),$TX[0]#d
-	xorb	($inp),$TY#b
-	lea	1($inp),$inp
-	movb	$TY#b,($out)
-	lea	1($out),$out
-	sub	\$1,$len
-	jnz	.Lcloop1
-	jmp	.Lexit
-
-.align	16
-.Lexit:
-	sub	\$1,$XX[0]#b
-	movl	$XX[0]#d,-8($dat)
-	movl	$YY#d,-4($dat)
-
-	mov	(%rsp),%r13
-	mov	8(%rsp),%r12
-	mov	16(%rsp),%rbx
-	add	\$24,%rsp
-.Lepilogue:
-	ret
-.size	asm_RC4,.-asm_RC4
-___
-}
-
-$idx="%r8";
-$ido="%r9";
-
-$code.=<<___;
-.globl	asm_RC4_set_key
-.type	asm_RC4_set_key,\@function,3
-.align	16
-asm_RC4_set_key:
-	lea	8($dat),$dat
-	lea	($inp,$len),$inp
-	neg	$len
-	mov	$len,%rcx
-	xor	%eax,%eax
-	xor	$ido,$ido
-	xor	%r10,%r10
-	xor	%r11,%r11
-
-	mov	OPENSSL_ia32cap_P(%rip),$idx#d
-	bt	\$20,$idx#d	# RC4_CHAR?
-	jc	.Lc1stloop
-	jmp	.Lw1stloop
-
-.align	16
-.Lw1stloop:
-	mov	%eax,($dat,%rax,4)
-	add	\$1,%al
-	jnc	.Lw1stloop
-
-	xor	$ido,$ido
-	xor	$idx,$idx
-.align	16
-.Lw2ndloop:
-	mov	($dat,$ido,4),%r10d
-	add	($inp,$len,1),$idx#b
-	add	%r10b,$idx#b
-	add	\$1,$len
-	mov	($dat,$idx,4),%r11d
-	cmovz	%rcx,$len
-	mov	%r10d,($dat,$idx,4)
-	mov	%r11d,($dat,$ido,4)
-	add	\$1,$ido#b
-	jnc	.Lw2ndloop
-	jmp	.Lexit_key
-
-.align	16
-.Lc1stloop:
-	mov	%al,($dat,%rax)
-	add	\$1,%al
-	jnc	.Lc1stloop
-
-	xor	$ido,$ido
-	xor	$idx,$idx
-.align	16
-.Lc2ndloop:
-	mov	($dat,$ido),%r10b
-	add	($inp,$len),$idx#b
-	add	%r10b,$idx#b
-	add	\$1,$len
-	mov	($dat,$idx),%r11b
-	jnz	.Lcnowrap
-	mov	%rcx,$len
-.Lcnowrap:
-	mov	%r10b,($dat,$idx)
-	mov	%r11b,($dat,$ido)
-	add	\$1,$ido#b
-	jnc	.Lc2ndloop
-	movl	\$-1,256($dat)
-
-.align	16
-.Lexit_key:
-	xor	%eax,%eax
-	mov	%eax,-8($dat)
-	mov	%eax,-4($dat)
-	ret
-.size	asm_RC4_set_key,.-asm_RC4_set_key
-___
-
-# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
-#		CONTEXT *context,DISPATCHER_CONTEXT *disp)
-if ($win64) {
-$rec="%rcx";
-$frame="%rdx";
-$context="%r8";
-$disp="%r9";
-
-$code.=<<___;
-.extern	__imp_RtlVirtualUnwind
-.type	stream_se_handler,\@abi-omnipotent
-.align	16
-stream_se_handler:
-	push	%rsi
-	push	%rdi
-	push	%rbx
-	push	%rbp
-	push	%r12
-	push	%r13
-	push	%r14
-	push	%r15
-	pushfq
-	sub	\$64,%rsp
-
-	mov	120($context),%rax	# pull context->Rax
-	mov	248($context),%rbx	# pull context->Rip
-
-	lea	.Lprologue(%rip),%r10
-	cmp	%r10,%rbx		# context->Rip<prologue label
-	jb	.Lin_prologue
-
-	mov	152($context),%rax	# pull context->Rsp
-
-	lea	.Lepilogue(%rip),%r10
-	cmp	%r10,%rbx		# context->Rip>=epilogue label
-	jae	.Lin_prologue
-
-	lea	24(%rax),%rax
-
-	mov	-8(%rax),%rbx
-	mov	-16(%rax),%r12
-	mov	-24(%rax),%r13
-	mov	%rbx,144($context)	# restore context->Rbx
-	mov	%r12,216($context)	# restore context->R12
-	mov	%r13,224($context)	# restore context->R13
-
-.Lin_prologue:
-	mov	8(%rax),%rdi
-	mov	16(%rax),%rsi
-	mov	%rax,152($context)	# restore context->Rsp
-	mov	%rsi,168($context)	# restore context->Rsi
-	mov	%rdi,176($context)	# restore context->Rdi
-
-	jmp	.Lcommon_seh_exit
-.size	stream_se_handler,.-stream_se_handler
-
-.type	key_se_handler,\@abi-omnipotent
-.align	16
-key_se_handler:
-	push	%rsi
-	push	%rdi
-	push	%rbx
-	push	%rbp
-	push	%r12
-	push	%r13
-	push	%r14
-	push	%r15
-	pushfq
-	sub	\$64,%rsp
-
-	mov	152($context),%rax	# pull context->Rsp
-	mov	8(%rax),%rdi
-	mov	16(%rax),%rsi
-	mov	%rsi,168($context)	# restore context->Rsi
-	mov	%rdi,176($context)	# restore context->Rdi
-
-.Lcommon_seh_exit:
-
-	mov	40($disp),%rdi		# disp->ContextRecord
-	mov	$context,%rsi		# context
-	mov	\$154,%ecx		# sizeof(CONTEXT)
-	.long	0xa548f3fc		# cld; rep movsq
-
-	mov	$disp,%rsi
-	xor	%rcx,%rcx		# arg1, UNW_FLAG_NHANDLER
-	mov	8(%rsi),%rdx		# arg2, disp->ImageBase
-	mov	0(%rsi),%r8		# arg3, disp->ControlPc
-	mov	16(%rsi),%r9		# arg4, disp->FunctionEntry
-	mov	40(%rsi),%r10		# disp->ContextRecord
-	lea	56(%rsi),%r11		# &disp->HandlerData
-	lea	24(%rsi),%r12		# &disp->EstablisherFrame
-	mov	%r10,32(%rsp)		# arg5
-	mov	%r11,40(%rsp)		# arg6
-	mov	%r12,48(%rsp)		# arg7
-	mov	%rcx,56(%rsp)		# arg8, (NULL)
-	call	*__imp_RtlVirtualUnwind(%rip)
-
-	mov	\$1,%eax		# ExceptionContinueSearch
-	add	\$64,%rsp
-	popfq
-	pop	%r15
-	pop	%r14
-	pop	%r13
-	pop	%r12
-	pop	%rbp
-	pop	%rbx
-	pop	%rdi
-	pop	%rsi
-	ret
-.size	key_se_handler,.-key_se_handler
-
-.section	.pdata
-.align	4
-	.rva	.LSEH_begin_asm_RC4
-	.rva	.LSEH_end_asm_RC4
-	.rva	.LSEH_info_asm_RC4
-
-	.rva	.LSEH_begin_asm_RC4_set_key
-	.rva	.LSEH_end_asm_RC4_set_key
-	.rva	.LSEH_info_asm_RC4_set_key
-
-.section	.xdata
-.align	8
-.LSEH_info_asm_RC4:
-	.byte	9,0,0,0
-	.rva	stream_se_handler
-.LSEH_info_asm_RC4_set_key:
-	.byte	9,0,0,0
-	.rva	key_se_handler
-___
-}
-
-sub reg_part {
-my ($reg,$conv)=@_;
-    if ($reg =~ /%r[0-9]+/)	{ $reg .= $conv; }
-    elsif ($conv eq "b")	{ $reg =~ s/%[er]([^x]+)x?/%$1l/;	}
-    elsif ($conv eq "w")	{ $reg =~ s/%[er](.+)/%$1/;		}
-    elsif ($conv eq "d")	{ $reg =~ s/%[er](.+)/%e$1/;		}
-    return $reg;
-}
-
-$code =~ s/(%[a-z0-9]+)#([bwd])/reg_part($1,$2)/gem;
-$code =~ s/\`([^\`]*)\`/eval $1/gem;
-
-print $code;
-
-close STDOUT;
diff --git a/src/crypto/rc4/rc4.c b/src/crypto/rc4/rc4.c
index b8e1d9f..a27a657 100644
--- a/src/crypto/rc4/rc4.c
+++ b/src/crypto/rc4/rc4.c
@@ -56,228 +56,43 @@
 
 #include <openssl/rc4.h>
 
-#if defined(OPENSSL_NO_ASM) || \
-    (!defined(OPENSSL_X86_64) && !defined(OPENSSL_X86))
-
-#if defined(OPENSSL_64_BIT)
-#define RC4_CHUNK uint64_t
-#elif defined(OPENSSL_32_BIT)
-#define RC4_CHUNK uint32_t
-#else
-#error "Unknown word size"
-#endif
-
-
-/* RC4 as implemented from a posting from
- * Newsgroups: sci.crypt
- * From: sterndark@netcom.com (David Sterndark)
- * Subject: RC4 Algorithm revealed.
- * Message-ID: <sternCvKL4B.Hyy@netcom.com>
- * Date: Wed, 14 Sep 1994 06:35:31 GMT */
 
 void RC4(RC4_KEY *key, size_t len, const uint8_t *in, uint8_t *out) {
-  uint32_t *d;
-  uint32_t x, y, tx, ty;
-  size_t i;
+  uint32_t x = key->x;
+  uint32_t y = key->y;
+  uint32_t *d = key->data;
 
-  x = key->x;
-  y = key->y;
-  d = key->data;
-
-#define RC4_STEP                                                             \
-  (x = (x + 1) & 0xff, tx = d[x], y = (tx + y) & 0xff, ty = d[y], d[y] = tx, \
-   d[x] = ty, (RC4_CHUNK)d[(tx + ty) & 0xff])
-
-  if ((((size_t)in & (sizeof(RC4_CHUNK) - 1)) |
-       ((size_t)out & (sizeof(RC4_CHUNK) - 1))) == 0) {
-    RC4_CHUNK ichunk, otp;
-    const union {
-      long one;
-      char little;
-    } is_endian = {1};
-
-    /* I reckon we can afford to implement both endian
-     * cases and to decide which way to take at run-time
-     * because the machine code appears to be very compact
-     * and redundant 1-2KB is perfectly tolerable (i.e.
-     * in case the compiler fails to eliminate it:-). By
-     * suggestion from Terrel Larson <terr@terralogic.net>
-     * who also stands for the is_endian union:-)
-     *
-     * Special notes.
-     *
-     * - is_endian is declared automatic as doing otherwise
-     *   (declaring static) prevents gcc from eliminating
-     *   the redundant code;
-     * - compilers (those I've tried) don't seem to have
-     *   problems eliminating either the operators guarded
-     *   by "if (sizeof(RC4_CHUNK)==8)" or the condition
-     *   expressions themselves so I've got 'em to replace
-     *   corresponding #ifdefs from the previous version;
-     * - I chose to let the redundant switch cases when
-     *   sizeof(RC4_CHUNK)!=8 be (were also #ifdefed
-     *   before);
-     * - in case you wonder "&(sizeof(RC4_CHUNK)*8-1)" in
-     *   [LB]ESHFT guards against "shift is out of range"
-     *   warnings when sizeof(RC4_CHUNK)!=8
-     *
-     *			<appro@fy.chalmers.se> */
-    if (!is_endian.little) { /* BIG-ENDIAN CASE */
-#define BESHFT(c) \
-  (((sizeof(RC4_CHUNK) - (c) - 1) * 8) & (sizeof(RC4_CHUNK) * 8 - 1))
-      for (; len & (0 - sizeof(RC4_CHUNK)); len -= sizeof(RC4_CHUNK)) {
-        ichunk = *(RC4_CHUNK *)in;
-        otp = RC4_STEP << BESHFT(0);
-        otp |= RC4_STEP << BESHFT(1);
-        otp |= RC4_STEP << BESHFT(2);
-        otp |= RC4_STEP << BESHFT(3);
-#if defined(OPENSSL_64_BIT)
-        otp |= RC4_STEP << BESHFT(4);
-        otp |= RC4_STEP << BESHFT(5);
-        otp |= RC4_STEP << BESHFT(6);
-        otp |= RC4_STEP << BESHFT(7);
-#endif
-        *(RC4_CHUNK *)out = otp ^ ichunk;
-        in += sizeof(RC4_CHUNK);
-        out += sizeof(RC4_CHUNK);
-      }
-    } else { /* LITTLE-ENDIAN CASE */
-#define LESHFT(c) (((c) * 8) & (sizeof(RC4_CHUNK) * 8 - 1))
-      for (; len & (0 - sizeof(RC4_CHUNK)); len -= sizeof(RC4_CHUNK)) {
-        ichunk = *(RC4_CHUNK *)in;
-        otp = RC4_STEP;
-        otp |= RC4_STEP << 8;
-        otp |= RC4_STEP << 16;
-        otp |= RC4_STEP << 24;
-#if defined(OPENSSL_64_BIT)
-        otp |= RC4_STEP << LESHFT(4);
-        otp |= RC4_STEP << LESHFT(5);
-        otp |= RC4_STEP << LESHFT(6);
-        otp |= RC4_STEP << LESHFT(7);
-#endif
-        *(RC4_CHUNK *)out = otp ^ ichunk;
-        in += sizeof(RC4_CHUNK);
-        out += sizeof(RC4_CHUNK);
-      }
-    }
+  for (size_t i = 0; i < len; i++) {
+    x = (x + 1) & 0xff;
+    uint32_t tx = d[x];
+    y = (tx + y) & 0xff;
+    uint32_t ty = d[y];
+    d[x] = ty;
+    d[y] = tx;
+    out[i] = d[(tx + ty) & 0xff] ^ in[i];
   }
-#define LOOP(in, out)   \
-  x = ((x + 1) & 0xff); \
-  tx = d[x];            \
-  y = (tx + y) & 0xff;  \
-  d[x] = ty = d[y];     \
-  d[y] = tx;            \
-  (out) = d[(tx + ty) & 0xff] ^ (in);
 
-#ifndef RC4_INDEX
-#define RC4_LOOP(a, b, i) LOOP(*((a)++), *((b)++))
-#else
-#define RC4_LOOP(a, b, i) LOOP(a[i], b[i])
-#endif
-
-  i = len >> 3;
-  if (i) {
-    for (;;) {
-      RC4_LOOP(in, out, 0);
-      RC4_LOOP(in, out, 1);
-      RC4_LOOP(in, out, 2);
-      RC4_LOOP(in, out, 3);
-      RC4_LOOP(in, out, 4);
-      RC4_LOOP(in, out, 5);
-      RC4_LOOP(in, out, 6);
-      RC4_LOOP(in, out, 7);
-#ifdef RC4_INDEX
-      in += 8;
-      out += 8;
-#endif
-      if (--i == 0) {
-        break;
-      }
-    }
-  }
-  i = len & 0x07;
-  if (i) {
-    for (;;) {
-      RC4_LOOP(in, out, 0);
-      if (--i == 0) {
-        break;
-      }
-      RC4_LOOP(in, out, 1);
-      if (--i == 0) {
-        break;
-      }
-      RC4_LOOP(in, out, 2);
-      if (--i == 0) {
-        break;
-      }
-      RC4_LOOP(in, out, 3);
-      if (--i == 0) {
-        break;
-      }
-      RC4_LOOP(in, out, 4);
-      if (--i == 0) {
-        break;
-      }
-      RC4_LOOP(in, out, 5);
-      if (--i == 0) {
-        break;
-      }
-      RC4_LOOP(in, out, 6);
-      if (--i == 0) {
-        break;
-      }
-    }
-  }
   key->x = x;
   key->y = y;
 }
 
 void RC4_set_key(RC4_KEY *rc4key, unsigned len, const uint8_t *key) {
-  uint32_t tmp;
-  unsigned i, id1, id2;
-  uint32_t *d;
-
-  d = &rc4key->data[0];
+  uint32_t *d = &rc4key->data[0];
   rc4key->x = 0;
   rc4key->y = 0;
-  id1 = id2 = 0;
 
-#define SK_LOOP(d, n)                    \
-  {                                      \
-    tmp = d[(n)];                        \
-    id2 = (key[id1] + tmp + id2) & 0xff; \
-    if (++id1 == len)                    \
-      id1 = 0;                           \
-    d[(n)] = d[id2];                     \
-    d[id2] = tmp;                        \
-  }
-
-  for (i = 0; i < 256; i++) {
+  for (unsigned i = 0; i < 256; i++) {
     d[i] = i;
   }
-  for (i = 0; i < 256; i += 4) {
-    SK_LOOP(d, i + 0);
-    SK_LOOP(d, i + 1);
-    SK_LOOP(d, i + 2);
-    SK_LOOP(d, i + 3);
+
+  unsigned id1 = 0, id2 = 0;
+  for (unsigned i = 0; i < 256; i++) {
+    uint32_t tmp = d[i];
+    id2 = (key[id1] + tmp + id2) & 0xff;
+    if (++id1 == len) {
+      id1 = 0;
+    }
+    d[i] = d[id2];
+    d[id2] = tmp;
   }
 }
-
-#else
-
-/* In this case several functions are provided by asm code. However, one cannot
- * control asm symbol visibility with command line flags and such so they are
- * always hidden and wrapped by these C functions, which can be so
- * controlled. */
-
-void asm_RC4(RC4_KEY *key, size_t len, const uint8_t *in, uint8_t *out);
-void RC4(RC4_KEY *key, size_t len, const uint8_t *in, uint8_t *out) {
-  asm_RC4(key, len, in, out);
-}
-
-void asm_RC4_set_key(RC4_KEY *rc4key, unsigned len, const uint8_t *key);
-void RC4_set_key(RC4_KEY *rc4key, unsigned len, const uint8_t *key) {
-  asm_RC4_set_key(rc4key, len, key);
-}
-
-#endif  /* OPENSSL_NO_ASM || (!OPENSSL_X86_64 && !OPENSSL_X86) */
diff --git a/src/crypto/refcount_lock.c b/src/crypto/refcount_lock.c
index bb8ef86..ea6a06d 100644
--- a/src/crypto/refcount_lock.c
+++ b/src/crypto/refcount_lock.c
@@ -31,7 +31,7 @@
   if (*count < CRYPTO_REFCOUNT_MAX) {
     (*count)++;
   }
-  CRYPTO_STATIC_MUTEX_unlock(&g_refcount_lock);
+  CRYPTO_STATIC_MUTEX_unlock_write(&g_refcount_lock);
 }
 
 int CRYPTO_refcount_dec_and_test_zero(CRYPTO_refcount_t *count) {
@@ -45,7 +45,7 @@
     (*count)--;
   }
   ret = (*count == 0);
-  CRYPTO_STATIC_MUTEX_unlock(&g_refcount_lock);
+  CRYPTO_STATIC_MUTEX_unlock_write(&g_refcount_lock);
 
   return ret;
 }
diff --git a/src/crypto/refcount_test.c b/src/crypto/refcount_test.cc
similarity index 100%
rename from src/crypto/refcount_test.c
rename to src/crypto/refcount_test.cc
diff --git a/src/crypto/rsa/CMakeLists.txt b/src/crypto/rsa/CMakeLists.txt
index 969b753..76937c1 100644
--- a/src/crypto/rsa/CMakeLists.txt
+++ b/src/crypto/rsa/CMakeLists.txt
@@ -11,14 +11,3 @@
   padding.c
   rsa_asn1.c
 )
-
-add_executable(
-  rsa_test
-
-  rsa_test.cc
-
-  $<TARGET_OBJECTS:test_support>
-)
-
-target_link_libraries(rsa_test crypto)
-add_dependencies(all_tests rsa_test)
\ No newline at end of file
diff --git a/src/crypto/rsa/blinding.c b/src/crypto/rsa/blinding.c
index d21633f..693dced 100644
--- a/src/crypto/rsa/blinding.c
+++ b/src/crypto/rsa/blinding.c
@@ -113,62 +113,43 @@
 #include <openssl/bn.h>
 #include <openssl/mem.h>
 #include <openssl/err.h>
-#include <openssl/thread.h>
 
 #include "internal.h"
+#include "../internal.h"
 
 
 #define BN_BLINDING_COUNTER 32
 
 struct bn_blinding_st {
-  BIGNUM *A;
-  BIGNUM *Ai;
-  BIGNUM *e;
-  BIGNUM *mod; /* just a reference */
-  int counter;
-  unsigned long flags;
-  /* mont is the Montgomery context used for this |BN_BLINDING|. It is not
-   * owned and must outlive this structure. */
-  const BN_MONT_CTX *mont;
-  int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
-                    const BIGNUM *m, BN_CTX *ctx, const BN_MONT_CTX *mont);
+  BIGNUM *A; /* The base blinding factor, Montgomery-encoded. */
+  BIGNUM *Ai; /* The inverse of the blinding factor, Montgomery-encoded. */
+  unsigned counter;
 };
 
-BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod) {
-  BN_BLINDING *ret = NULL;
+static int bn_blinding_create_param(BN_BLINDING *b, const BIGNUM *e,
+                                    const BN_MONT_CTX *mont, BN_CTX *ctx);
 
-  ret = (BN_BLINDING*) OPENSSL_malloc(sizeof(BN_BLINDING));
+BN_BLINDING *BN_BLINDING_new(void) {
+  BN_BLINDING *ret = OPENSSL_malloc(sizeof(BN_BLINDING));
   if (ret == NULL) {
     OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
     return NULL;
   }
-  memset(ret, 0, sizeof(BN_BLINDING));
-  if (A != NULL) {
-    ret->A = BN_dup(A);
-    if (ret->A == NULL) {
-      goto err;
-    }
-  }
-  if (Ai != NULL) {
-    ret->Ai = BN_dup(Ai);
-    if (ret->Ai == NULL) {
-      goto err;
-    }
-  }
+  OPENSSL_memset(ret, 0, sizeof(BN_BLINDING));
 
-  /* save a copy of mod in the BN_BLINDING structure */
-  ret->mod = BN_dup(mod);
-  if (ret->mod == NULL) {
+  ret->A = BN_new();
+  if (ret->A == NULL) {
     goto err;
   }
-  if (BN_get_flags(mod, BN_FLG_CONSTTIME) != 0) {
-    BN_set_flags(ret->mod, BN_FLG_CONSTTIME);
+
+  ret->Ai = BN_new();
+  if (ret->Ai == NULL) {
+    goto err;
   }
 
-  /* Set the counter to the special value -1
-   * to indicate that this is never-used fresh blinding
-   * that does not need updating before first use. */
-  ret->counter = -1;
+  /* The blinding values need to be created before this blinding can be used. */
+  ret->counter = BN_BLINDING_COUNTER - 1;
+
   return ret;
 
 err:
@@ -183,280 +164,102 @@
 
   BN_free(r->A);
   BN_free(r->Ai);
-  BN_free(r->e);
-  BN_free(r->mod);
   OPENSSL_free(r);
 }
 
-int BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx) {
-  int ret = 0;
-
-  if (b->A == NULL || b->Ai == NULL) {
-    OPENSSL_PUT_ERROR(RSA, RSA_R_BN_NOT_INITIALIZED);
-    goto err;
-  }
-
-  if (b->counter == -1) {
-    b->counter = 0;
-  }
-
-  if (++b->counter == BN_BLINDING_COUNTER && b->e != NULL &&
-      !(b->flags & BN_BLINDING_NO_RECREATE)) {
+static int bn_blinding_update(BN_BLINDING *b, const BIGNUM *e,
+                              const BN_MONT_CTX *mont, BN_CTX *ctx) {
+  if (++b->counter == BN_BLINDING_COUNTER) {
     /* re-create blinding parameters */
-    if (!BN_BLINDING_create_param(b, NULL, NULL, ctx, NULL, NULL)) {
+    if (!bn_blinding_create_param(b, e, mont, ctx)) {
       goto err;
     }
-  } else if (!(b->flags & BN_BLINDING_NO_UPDATE)) {
-    if (!BN_mod_mul(b->A, b->A, b->A, b->mod, ctx)) {
-      goto err;
-    }
-    if (!BN_mod_mul(b->Ai, b->Ai, b->Ai, b->mod, ctx)) {
+    b->counter = 0;
+  } else {
+    if (!BN_mod_mul_montgomery(b->A, b->A, b->A, mont, ctx) ||
+        !BN_mod_mul_montgomery(b->Ai, b->Ai, b->Ai, mont, ctx)) {
       goto err;
     }
   }
 
-  ret = 1;
+  return 1;
 
 err:
-  if (b->counter == BN_BLINDING_COUNTER) {
-    b->counter = 0;
-  }
-  return ret;
+  /* |A| and |Ai| may be in an inconsistent state so they both need to be
+   * replaced the next time this blinding is used. Note that this is only
+   * sufficient because support for |BN_BLINDING_NO_UPDATE| and
+   * |BN_BLINDING_NO_RECREATE| was previously dropped. */
+  b->counter = BN_BLINDING_COUNTER - 1;
+
+  return 0;
 }
 
-int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx) {
-  return BN_BLINDING_convert_ex(n, NULL, b, ctx);
-}
-
-int BN_BLINDING_convert_ex(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *ctx) {
-  int ret = 1;
-
-  if (b->A == NULL || b->Ai == NULL) {
-    OPENSSL_PUT_ERROR(RSA, RSA_R_BN_NOT_INITIALIZED);
+int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, const BIGNUM *e,
+                        const BN_MONT_CTX *mont, BN_CTX *ctx) {
+  /* |n| is not Montgomery-encoded and |b->A| is. |BN_mod_mul_montgomery|
+   * cancels one Montgomery factor, so the resulting value of |n| is unencoded.
+   */
+  if (!bn_blinding_update(b, e, mont, ctx) ||
+      !BN_mod_mul_montgomery(n, n, b->A, mont, ctx)) {
     return 0;
   }
 
-  if (b->counter == -1) {
-    /* Fresh blinding, doesn't need updating. */
-    b->counter = 0;
-  } else if (!BN_BLINDING_update(b, ctx)) {
-    return 0;
-  }
-
-  if (r != NULL) {
-    if (!BN_copy(r, b->Ai)) {
-      ret = 0;
-    }
-  }
-
-  if (!BN_mod_mul(n, n, b->A, b->mod, ctx)) {
-    ret = 0;
-  }
-
-  return ret;
+  return 1;
 }
 
-int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx) {
-  return BN_BLINDING_invert_ex(n, NULL, b, ctx);
+int BN_BLINDING_invert(BIGNUM *n, const BN_BLINDING *b, BN_MONT_CTX *mont,
+                       BN_CTX *ctx) {
+  /* |n| is not Montgomery-encoded and |b->A| is. |BN_mod_mul_montgomery|
+   * cancels one Montgomery factor, so the resulting value of |n| is unencoded.
+   */
+  return BN_mod_mul_montgomery(n, n, b->Ai, mont, ctx);
 }
 
-int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b,
-                          BN_CTX *ctx) {
-  int ret;
-
-  if (r != NULL) {
-    ret = BN_mod_mul(n, n, r, b->mod, ctx);
-  } else {
-    if (b->Ai == NULL) {
-      OPENSSL_PUT_ERROR(RSA, RSA_R_BN_NOT_INITIALIZED);
-      return 0;
-    }
-    ret = BN_mod_mul(n, n, b->Ai, b->mod, ctx);
-  }
-
-  return ret;
-}
-
-unsigned long BN_BLINDING_get_flags(const BN_BLINDING *b) { return b->flags; }
-
-void BN_BLINDING_set_flags(BN_BLINDING *b, unsigned long flags) {
-  b->flags = flags;
-}
-
-BN_BLINDING *BN_BLINDING_create_param(
-    BN_BLINDING *b, const BIGNUM *e, BIGNUM *m, BN_CTX *ctx,
-    int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
-                      const BIGNUM *m, BN_CTX *ctx, const BN_MONT_CTX *mont),
-    const BN_MONT_CTX *mont) {
+static int bn_blinding_create_param(BN_BLINDING *b, const BIGNUM *e,
+                                    const BN_MONT_CTX *mont, BN_CTX *ctx) {
   int retry_counter = 32;
-  BN_BLINDING *ret = NULL;
-
-  if (b == NULL) {
-    ret = BN_BLINDING_new(NULL, NULL, m);
-  } else {
-    ret = b;
-  }
-
-  if (ret == NULL) {
-    goto err;
-  }
-
-  if (ret->A == NULL && (ret->A = BN_new()) == NULL) {
-    goto err;
-  }
-  if (ret->Ai == NULL && (ret->Ai = BN_new()) == NULL) {
-    goto err;
-  }
-
-  if (e != NULL) {
-    BN_free(ret->e);
-    ret->e = BN_dup(e);
-  }
-  if (ret->e == NULL) {
-    goto err;
-  }
-
-  if (bn_mod_exp != NULL) {
-    ret->bn_mod_exp = bn_mod_exp;
-  }
-  if (mont != NULL) {
-    ret->mont = mont;
-  }
 
   do {
-    if (!BN_rand_range(ret->A, ret->mod)) {
-      goto err;
+    if (!BN_rand_range_ex(b->A, 1, &mont->N)) {
+      OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
+      return 0;
+    }
+
+    /* |BN_from_montgomery| + |BN_mod_inverse_blinded| is equivalent to, but
+     * more efficient than, |BN_mod_inverse_blinded| + |BN_to_montgomery|. */
+    if (!BN_from_montgomery(b->Ai, b->A, mont, ctx)) {
+      OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
+      return 0;
     }
 
     int no_inverse;
-    if (BN_mod_inverse_ex(ret->Ai, &no_inverse, ret->A, ret->mod, ctx) == NULL) {
-      /* this should almost never happen for good RSA keys */
-      if (no_inverse) {
-        if (retry_counter-- == 0) {
-          OPENSSL_PUT_ERROR(RSA, RSA_R_TOO_MANY_ITERATIONS);
-          goto err;
-        }
-        ERR_clear_error();
-      } else {
-        goto err;
-      }
-    } else {
+    if (BN_mod_inverse_blinded(b->Ai, &no_inverse, b->Ai, mont, ctx)) {
       break;
     }
-  } while (1);
 
-  if (ret->bn_mod_exp != NULL && ret->mont != NULL) {
-    if (!ret->bn_mod_exp(ret->A, ret->A, ret->e, ret->mod, ctx, ret->mont)) {
-      goto err;
-    }
-  } else {
-    if (!BN_mod_exp(ret->A, ret->A, ret->e, ret->mod, ctx)) {
-      goto err;
-    }
-  }
-
-  return ret;
-
-err:
-  if (b == NULL) {
-    BN_BLINDING_free(ret);
-    ret = NULL;
-  }
-
-  return ret;
-}
-
-static BIGNUM *rsa_get_public_exp(const BIGNUM *d, const BIGNUM *p,
-                                  const BIGNUM *q, BN_CTX *ctx) {
-  BIGNUM *ret = NULL, *r0, *r1, *r2;
-
-  if (d == NULL || p == NULL || q == NULL) {
-    return NULL;
-  }
-
-  BN_CTX_start(ctx);
-  r0 = BN_CTX_get(ctx);
-  r1 = BN_CTX_get(ctx);
-  r2 = BN_CTX_get(ctx);
-  if (r2 == NULL) {
-    goto err;
-  }
-
-  if (!BN_sub(r1, p, BN_value_one())) {
-    goto err;
-  }
-  if (!BN_sub(r2, q, BN_value_one())) {
-    goto err;
-  }
-  if (!BN_mul(r0, r1, r2, ctx)) {
-    goto err;
-  }
-
-  ret = BN_mod_inverse(NULL, d, r0, ctx);
-
-err:
-  BN_CTX_end(ctx);
-  return ret;
-}
-
-BN_BLINDING *rsa_setup_blinding(RSA *rsa, BN_CTX *in_ctx) {
-  BIGNUM local_n;
-  BIGNUM *e, *n;
-  BN_CTX *ctx;
-  BN_BLINDING *ret = NULL;
-  BN_MONT_CTX *mont_ctx = NULL;
-
-  if (in_ctx == NULL) {
-    ctx = BN_CTX_new();
-    if (ctx == NULL) {
+    if (!no_inverse) {
+      OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
       return 0;
     }
-  } else {
-    ctx = in_ctx;
-  }
 
-  BN_CTX_start(ctx);
-  e = BN_CTX_get(ctx);
-  if (e == NULL) {
-    OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
-    goto err;
-  }
-
-  if (rsa->e == NULL) {
-    e = rsa_get_public_exp(rsa->d, rsa->p, rsa->q, ctx);
-    if (e == NULL) {
-      OPENSSL_PUT_ERROR(RSA, RSA_R_NO_PUBLIC_EXPONENT);
-      goto err;
+    /* For reasonably-sized RSA keys, it should almost never be the case that a
+     * random value doesn't have an inverse. */
+    if (retry_counter-- == 0) {
+      OPENSSL_PUT_ERROR(RSA, RSA_R_TOO_MANY_ITERATIONS);
+      return 0;
     }
-  } else {
-    e = rsa->e;
+    ERR_clear_error();
+  } while (1);
+
+  if (!BN_mod_exp_mont(b->A, b->A, e, &mont->N, ctx, mont)) {
+    OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
+    return 0;
   }
 
-  n = &local_n;
-  BN_with_flags(n, rsa->n, BN_FLG_CONSTTIME);
-
-  if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) {
-    mont_ctx = BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx);
-    if (mont_ctx == NULL) {
-      goto err;
-    }
+  if (!BN_to_montgomery(b->A, b->A, mont, ctx)) {
+    OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
+    return 0;
   }
 
-  ret = BN_BLINDING_create_param(NULL, e, n, ctx, rsa->meth->bn_mod_exp,
-                                 mont_ctx);
-  if (ret == NULL) {
-    OPENSSL_PUT_ERROR(RSA, ERR_R_BN_LIB);
-    goto err;
-  }
-
-err:
-  BN_CTX_end(ctx);
-  if (in_ctx == NULL) {
-    BN_CTX_free(ctx);
-  }
-  if (rsa->e == NULL) {
-    BN_free(e);
-  }
-
-  return ret;
+  return 1;
 }
diff --git a/src/crypto/rsa/internal.h b/src/crypto/rsa/internal.h
index 4e896e2..b6a0727 100644
--- a/src/crypto/rsa/internal.h
+++ b/src/crypto/rsa/internal.h
@@ -77,9 +77,6 @@
                          int padding);
 int rsa_default_decrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
                         const uint8_t *in, size_t in_len, int padding);
-int rsa_default_verify_raw(RSA *rsa, size_t *out_len, uint8_t *out,
-                           size_t max_out, const uint8_t *in, size_t in_len,
-                           int padding);
 int rsa_default_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in,
                                   size_t len);
 int rsa_default_multi_prime_keygen(RSA *rsa, int bits, int num_primes,
@@ -90,45 +87,28 @@
 #define RSA_PKCS1_PADDING_SIZE 11
 
 
-/* BN_BLINDING flags */
-#define BN_BLINDING_NO_UPDATE 0x00000001
-#define BN_BLINDING_NO_RECREATE 0x00000002
-
-BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod);
+BN_BLINDING *BN_BLINDING_new(void);
 void BN_BLINDING_free(BN_BLINDING *b);
-int BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx);
-int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx);
-int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx);
-int BN_BLINDING_convert_ex(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *);
-int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b, BN_CTX *);
-unsigned long BN_BLINDING_get_flags(const BN_BLINDING *);
-void BN_BLINDING_set_flags(BN_BLINDING *, unsigned long);
-BN_BLINDING *BN_BLINDING_create_param(
-    BN_BLINDING *b, const BIGNUM *e, BIGNUM *m, BN_CTX *ctx,
-    int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
-                      const BIGNUM *m, BN_CTX *ctx, const BN_MONT_CTX *mont),
-    const BN_MONT_CTX *mont);
-BN_BLINDING *rsa_setup_blinding(RSA *rsa, BN_CTX *in_ctx);
+int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, const BIGNUM *e,
+                        const BN_MONT_CTX *mont_ctx, BN_CTX *ctx);
+int BN_BLINDING_invert(BIGNUM *n, const BN_BLINDING *b, BN_MONT_CTX *mont_ctx,
+                       BN_CTX *ctx);
 
 
-int RSA_padding_add_PKCS1_type_1(uint8_t *to, unsigned to_len,
-                                 const uint8_t *from, unsigned from_len);
+int RSA_padding_add_PKCS1_type_1(uint8_t *to, size_t to_len,
+                                 const uint8_t *from, size_t from_len);
 int RSA_padding_check_PKCS1_type_1(uint8_t *to, unsigned to_len,
                                    const uint8_t *from, unsigned from_len);
-int RSA_padding_add_PKCS1_type_2(uint8_t *to, unsigned to_len,
-                                 const uint8_t *from, unsigned from_len);
+int RSA_padding_add_PKCS1_type_2(uint8_t *to, size_t to_len,
+                                 const uint8_t *from, size_t from_len);
 int RSA_padding_check_PKCS1_type_2(uint8_t *to, unsigned to_len,
                                    const uint8_t *from, unsigned from_len);
-int RSA_padding_add_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len,
-                                    const uint8_t *from, unsigned from_len,
-                                    const uint8_t *param, unsigned plen,
-                                    const EVP_MD *md, const EVP_MD *mgf1md);
 int RSA_padding_check_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len,
                                       const uint8_t *from, unsigned from_len,
                                       const uint8_t *param, unsigned plen,
                                       const EVP_MD *md, const EVP_MD *mgf1md);
-int RSA_padding_add_none(uint8_t *to, unsigned to_len, const uint8_t *from,
-                         unsigned from_len);
+int RSA_padding_add_none(uint8_t *to, size_t to_len, const uint8_t *from,
+                         size_t from_len);
 
 /* RSA_private_transform calls either the method-specific |private_transform|
  * function (if given) or the generic one. See the comment for
diff --git a/src/crypto/rsa/padding.c b/src/crypto/rsa/padding.c
index 032df2e..ac583c4 100644
--- a/src/crypto/rsa/padding.c
+++ b/src/crypto/rsa/padding.c
@@ -59,6 +59,7 @@
 #include <limits.h>
 #include <string.h>
 
+#include <openssl/bn.h>
 #include <openssl/digest.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
@@ -70,11 +71,9 @@
 
 /* TODO(fork): don't the check functions have to be constant time? */
 
-int RSA_padding_add_PKCS1_type_1(uint8_t *to, unsigned to_len,
-                                 const uint8_t *from, unsigned from_len) {
-  unsigned j;
-  uint8_t *p;
-
+int RSA_padding_add_PKCS1_type_1(uint8_t *to, size_t to_len,
+                                 const uint8_t *from, size_t from_len) {
+  /* See RFC 8017, section 9.2. */
   if (to_len < RSA_PKCS1_PADDING_SIZE) {
     OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
     return 0;
@@ -85,17 +84,11 @@
     return 0;
   }
 
-  p = (uint8_t *)to;
-
-  *(p++) = 0;
-  *(p++) = 1; /* Private Key BT (Block Type) */
-
-  /* pad out with 0xff data */
-  j = to_len - 3 - from_len;
-  memset(p, 0xff, j);
-  p += j;
-  *(p++) = 0;
-  memcpy(p, from, (unsigned int)from_len);
+  to[0] = 0;
+  to[1] = 1;
+  OPENSSL_memset(to + 2, 0xff, to_len - 3 - from_len);
+  to[to_len - from_len - 1] = 0;
+  OPENSSL_memcpy(to + to_len - from_len, from, from_len);
   return 1;
 }
 
@@ -146,16 +139,30 @@
     OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
     return -1;
   }
-  memcpy(to, p, j);
+  OPENSSL_memcpy(to, p, j);
 
   return j;
 }
 
-int RSA_padding_add_PKCS1_type_2(uint8_t *to, unsigned to_len,
-                                 const uint8_t *from, unsigned from_len) {
-  unsigned i, j;
-  uint8_t *p;
+static int rand_nonzero(uint8_t *out, size_t len) {
+  if (!RAND_bytes(out, len)) {
+    return 0;
+  }
 
+  for (size_t i = 0; i < len; i++) {
+    while (out[i] == 0) {
+      if (!RAND_bytes(out + i, 1)) {
+        return 0;
+      }
+    }
+  }
+
+  return 1;
+}
+
+int RSA_padding_add_PKCS1_type_2(uint8_t *to, size_t to_len,
+                                 const uint8_t *from, size_t from_len) {
+  /* See RFC 8017, section 7.2.1. */
   if (to_len < RSA_PKCS1_PADDING_SIZE) {
     OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
     return 0;
@@ -166,30 +173,16 @@
     return 0;
   }
 
-  p = (unsigned char *)to;
+  to[0] = 0;
+  to[1] = 2;
 
-  *(p++) = 0;
-  *(p++) = 2; /* Public Key BT (Block Type) */
-
-  /* pad out with non-zero random data */
-  j = to_len - 3 - from_len;
-
-  if (!RAND_bytes(p, j)) {
+  size_t padding_len = to_len - 3 - from_len;
+  if (!rand_nonzero(to + 2, padding_len)) {
     return 0;
   }
 
-  for (i = 0; i < j; i++) {
-    while (*p == 0) {
-      if (!RAND_bytes(p, 1)) {
-        return 0;
-      }
-    }
-    p++;
-  }
-
-  *(p++) = 0;
-
-  memcpy(p, from, (unsigned int)from_len);
+  to[2 + padding_len] = 0;
+  OPENSSL_memcpy(to + to_len - from_len, from, from_len);
   return 1;
 }
 
@@ -255,12 +248,12 @@
     return -1;
   }
 
-  memcpy(to, &from[zero_index], msg_len);
+  OPENSSL_memcpy(to, &from[zero_index], msg_len);
   return (int)msg_len;
 }
 
-int RSA_padding_add_none(uint8_t *to, unsigned to_len, const uint8_t *from,
-                         unsigned from_len) {
+int RSA_padding_add_none(uint8_t *to, size_t to_len, const uint8_t *from,
+                         size_t from_len) {
   if (from_len > to_len) {
     OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
     return 0;
@@ -271,63 +264,57 @@
     return 0;
   }
 
-  memcpy(to, from, (unsigned int)from_len);
+  OPENSSL_memcpy(to, from, from_len);
   return 1;
 }
 
-int PKCS1_MGF1(uint8_t *mask, unsigned len, const uint8_t *seed,
-               unsigned seedlen, const EVP_MD *dgst) {
-  unsigned outlen = 0;
-  uint32_t i;
-  uint8_t cnt[4];
-  EVP_MD_CTX c;
-  uint8_t md[EVP_MAX_MD_SIZE];
-  unsigned mdlen;
-  int ret = -1;
+static int PKCS1_MGF1(uint8_t *out, size_t len, const uint8_t *seed,
+                      size_t seed_len, const EVP_MD *md) {
+  int ret = 0;
+  EVP_MD_CTX ctx;
+  EVP_MD_CTX_init(&ctx);
 
-  EVP_MD_CTX_init(&c);
-  mdlen = EVP_MD_size(dgst);
+  size_t md_len = EVP_MD_size(md);
 
-  for (i = 0; outlen < len; i++) {
-    cnt[0] = (uint8_t)((i >> 24) & 255);
-    cnt[1] = (uint8_t)((i >> 16) & 255);
-    cnt[2] = (uint8_t)((i >> 8)) & 255;
-    cnt[3] = (uint8_t)(i & 255);
-    if (!EVP_DigestInit_ex(&c, dgst, NULL) ||
-        !EVP_DigestUpdate(&c, seed, seedlen) ||
-        !EVP_DigestUpdate(&c, cnt, 4)) {
+  for (uint32_t i = 0; len > 0; i++) {
+    uint8_t counter[4];
+    counter[0] = (uint8_t)(i >> 24);
+    counter[1] = (uint8_t)(i >> 16);
+    counter[2] = (uint8_t)(i >> 8);
+    counter[3] = (uint8_t)i;
+    if (!EVP_DigestInit_ex(&ctx, md, NULL) ||
+        !EVP_DigestUpdate(&ctx, seed, seed_len) ||
+        !EVP_DigestUpdate(&ctx, counter, sizeof(counter))) {
       goto err;
     }
 
-    if (outlen + mdlen <= len) {
-      if (!EVP_DigestFinal_ex(&c, mask + outlen, NULL)) {
+    if (md_len <= len) {
+      if (!EVP_DigestFinal_ex(&ctx, out, NULL)) {
         goto err;
       }
-      outlen += mdlen;
+      out += md_len;
+      len -= md_len;
     } else {
-      if (!EVP_DigestFinal_ex(&c, md, NULL)) {
+      uint8_t digest[EVP_MAX_MD_SIZE];
+      if (!EVP_DigestFinal_ex(&ctx, digest, NULL)) {
         goto err;
       }
-      memcpy(mask + outlen, md, len - outlen);
-      outlen = len;
+      OPENSSL_memcpy(out, digest, len);
+      len = 0;
     }
   }
-  ret = 0;
+
+  ret = 1;
 
 err:
-  EVP_MD_CTX_cleanup(&c);
+  EVP_MD_CTX_cleanup(&ctx);
   return ret;
 }
 
-int RSA_padding_add_PKCS1_OAEP_mgf1(uint8_t *to, unsigned to_len,
-                                    const uint8_t *from, unsigned from_len,
-                                    const uint8_t *param, unsigned param_len,
+int RSA_padding_add_PKCS1_OAEP_mgf1(uint8_t *to, size_t to_len,
+                                    const uint8_t *from, size_t from_len,
+                                    const uint8_t *param, size_t param_len,
                                     const EVP_MD *md, const EVP_MD *mgf1md) {
-  unsigned i, emlen, mdlen;
-  uint8_t *db, *seed;
-  uint8_t *dbmask = NULL, seedmask[EVP_MAX_MD_SIZE];
-  int ret = 0;
-
   if (md == NULL) {
     md = EVP_sha1();
   }
@@ -335,14 +322,14 @@
     mgf1md = md;
   }
 
-  mdlen = EVP_MD_size(md);
+  size_t mdlen = EVP_MD_size(md);
 
   if (to_len < 2 * mdlen + 2) {
     OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
     return 0;
   }
 
-  emlen = to_len - 1;
+  size_t emlen = to_len - 1;
   if (from_len > emlen - 2 * mdlen - 1) {
     OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
     return 0;
@@ -354,36 +341,38 @@
   }
 
   to[0] = 0;
-  seed = to + 1;
-  db = to + mdlen + 1;
+  uint8_t *seed = to + 1;
+  uint8_t *db = to + mdlen + 1;
 
-  if (!EVP_Digest((void *)param, param_len, db, NULL, md, NULL)) {
+  if (!EVP_Digest(param, param_len, db, NULL, md, NULL)) {
     return 0;
   }
-  memset(db + mdlen, 0, emlen - from_len - 2 * mdlen - 1);
+  OPENSSL_memset(db + mdlen, 0, emlen - from_len - 2 * mdlen - 1);
   db[emlen - from_len - mdlen - 1] = 0x01;
-  memcpy(db + emlen - from_len - mdlen, from, from_len);
+  OPENSSL_memcpy(db + emlen - from_len - mdlen, from, from_len);
   if (!RAND_bytes(seed, mdlen)) {
     return 0;
   }
 
-  dbmask = OPENSSL_malloc(emlen - mdlen);
+  uint8_t *dbmask = OPENSSL_malloc(emlen - mdlen);
   if (dbmask == NULL) {
     OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
     return 0;
   }
 
-  if (PKCS1_MGF1(dbmask, emlen - mdlen, seed, mdlen, mgf1md) < 0) {
+  int ret = 0;
+  if (!PKCS1_MGF1(dbmask, emlen - mdlen, seed, mdlen, mgf1md)) {
     goto out;
   }
-  for (i = 0; i < emlen - mdlen; i++) {
+  for (size_t i = 0; i < emlen - mdlen; i++) {
     db[i] ^= dbmask[i];
   }
 
-  if (PKCS1_MGF1(seedmask, mdlen, db, emlen - mdlen, mgf1md) < 0) {
+  uint8_t seedmask[EVP_MAX_MD_SIZE];
+  if (!PKCS1_MGF1(seedmask, mdlen, db, emlen - mdlen, mgf1md)) {
     goto out;
   }
-  for (i = 0; i < mdlen; i++) {
+  for (size_t i = 0; i < mdlen; i++) {
     seed[i] ^= seedmask[i];
   }
   ret = 1;
@@ -429,21 +418,21 @@
   maskedseed = from + 1;
   maskeddb = from + 1 + mdlen;
 
-  if (PKCS1_MGF1(seed, mdlen, maskeddb, dblen, mgf1md)) {
+  if (!PKCS1_MGF1(seed, mdlen, maskeddb, dblen, mgf1md)) {
     goto err;
   }
   for (i = 0; i < mdlen; i++) {
     seed[i] ^= maskedseed[i];
   }
 
-  if (PKCS1_MGF1(db, dblen, seed, mdlen, mgf1md)) {
+  if (!PKCS1_MGF1(db, dblen, seed, mdlen, mgf1md)) {
     goto err;
   }
   for (i = 0; i < dblen; i++) {
     db[i] ^= maskeddb[i];
   }
 
-  if (!EVP_Digest((void *)param, param_len, phash, NULL, md, NULL)) {
+  if (!EVP_Digest(param, param_len, phash, NULL, md, NULL)) {
     goto err;
   }
 
@@ -473,7 +462,7 @@
     OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
     mlen = -1;
   } else {
-    memcpy(to, db + one_index, mlen);
+    OPENSSL_memcpy(to, db + one_index, mlen);
   }
 
   OPENSSL_free(db);
@@ -488,7 +477,7 @@
   return -1;
 }
 
-static const unsigned char zeroes[] = {0,0,0,0,0,0,0,0};
+static const uint8_t kPSSZeroes[] = {0, 0, 0, 0, 0, 0, 0, 0};
 
 int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const uint8_t *mHash,
                               const EVP_MD *Hash, const EVP_MD *mgf1Hash,
@@ -532,7 +521,7 @@
     EM++;
     emLen--;
   }
-  if (emLen < ((int)hLen + sLen + 2)) {
+  if (emLen < (int)hLen + 2 || emLen < ((int)hLen + sLen + 2)) {
     /* sLen can be small negative */
     OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE);
     goto err;
@@ -548,7 +537,7 @@
     OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
     goto err;
   }
-  if (PKCS1_MGF1(DB, maskedDBLen, H, hLen, mgf1Hash) < 0) {
+  if (!PKCS1_MGF1(DB, maskedDBLen, H, hLen, mgf1Hash)) {
     goto err;
   }
   for (i = 0; i < maskedDBLen; i++) {
@@ -569,19 +558,13 @@
     goto err;
   }
   if (!EVP_DigestInit_ex(&ctx, Hash, NULL) ||
-      !EVP_DigestUpdate(&ctx, zeroes, sizeof zeroes) ||
-      !EVP_DigestUpdate(&ctx, mHash, hLen)) {
+      !EVP_DigestUpdate(&ctx, kPSSZeroes, sizeof(kPSSZeroes)) ||
+      !EVP_DigestUpdate(&ctx, mHash, hLen) ||
+      !EVP_DigestUpdate(&ctx, DB + i, maskedDBLen - i) ||
+      !EVP_DigestFinal_ex(&ctx, H_, NULL)) {
     goto err;
   }
-  if (maskedDBLen - i) {
-    if (!EVP_DigestUpdate(&ctx, DB + i, maskedDBLen - i)) {
-      goto err;
-    }
-  }
-  if (!EVP_DigestFinal_ex(&ctx, H_, NULL)) {
-    goto err;
-  }
-  if (memcmp(H_, H, hLen)) {
+  if (OPENSSL_memcmp(H_, H, hLen)) {
     OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_SIGNATURE);
     ret = 0;
   } else {
@@ -598,13 +581,11 @@
 int RSA_padding_add_PKCS1_PSS_mgf1(RSA *rsa, unsigned char *EM,
                                    const unsigned char *mHash,
                                    const EVP_MD *Hash, const EVP_MD *mgf1Hash,
-                                   int sLen) {
-  int i;
+                                   int sLenRequested) {
   int ret = 0;
   size_t maskedDBLen, MSBits, emLen;
   size_t hLen;
   unsigned char *H, *salt = NULL, *p;
-  EVP_MD_CTX ctx;
 
   if (mgf1Hash == NULL) {
     mgf1Hash = Hash;
@@ -612,19 +593,6 @@
 
   hLen = EVP_MD_size(Hash);
 
-  /* Negative sLen has special meanings:
-   *	-1	sLen == hLen
-   *	-2	salt length is maximized
-   *	-N	reserved */
-  if (sLen == -1) {
-    sLen = hLen;
-  } else if (sLen == -2) {
-    sLen = -2;
-  } else if (sLen < -2) {
-    OPENSSL_PUT_ERROR(RSA, RSA_R_SLEN_CHECK_FAILED);
-    goto err;
-  }
-
   if (BN_is_zero(rsa->n)) {
     OPENSSL_PUT_ERROR(RSA, RSA_R_EMPTY_PUBLIC_KEY);
     goto err;
@@ -637,16 +605,33 @@
     *EM++ = 0;
     emLen--;
   }
-  if (sLen == -2) {
-    if (emLen < hLen + 2) {
-      OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
-      goto err;
-    }
-    sLen = emLen - hLen - 2;
-  } else if (emLen < hLen + sLen + 2) {
+
+  if (emLen < hLen + 2) {
     OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
     goto err;
   }
+
+  /* Negative sLenRequested has special meanings:
+   *   -1  sLen == hLen
+   *   -2  salt length is maximized
+   *   -N  reserved */
+  size_t sLen;
+  if (sLenRequested == -1) {
+    sLen = hLen;
+  } else if (sLenRequested == -2) {
+    sLen = emLen - hLen - 2;
+  } else if (sLenRequested < 0) {
+    OPENSSL_PUT_ERROR(RSA, RSA_R_SLEN_CHECK_FAILED);
+    goto err;
+  } else {
+    sLen = (size_t)sLenRequested;
+  }
+
+  if (emLen - hLen - 2 < sLen) {
+    OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
+    goto err;
+  }
+
   if (sLen > 0) {
     salt = OPENSSL_malloc(sLen);
     if (!salt) {
@@ -659,22 +644,21 @@
   }
   maskedDBLen = emLen - hLen - 1;
   H = EM + maskedDBLen;
+
+  EVP_MD_CTX ctx;
   EVP_MD_CTX_init(&ctx);
-  if (!EVP_DigestInit_ex(&ctx, Hash, NULL) ||
-      !EVP_DigestUpdate(&ctx, zeroes, sizeof zeroes) ||
-      !EVP_DigestUpdate(&ctx, mHash, hLen)) {
-    goto err;
-  }
-  if (sLen && !EVP_DigestUpdate(&ctx, salt, sLen)) {
-    goto err;
-  }
-  if (!EVP_DigestFinal_ex(&ctx, H, NULL)) {
-    goto err;
-  }
+  int digest_ok = EVP_DigestInit_ex(&ctx, Hash, NULL) &&
+                  EVP_DigestUpdate(&ctx, kPSSZeroes, sizeof(kPSSZeroes)) &&
+                  EVP_DigestUpdate(&ctx, mHash, hLen) &&
+                  EVP_DigestUpdate(&ctx, salt, sLen) &&
+                  EVP_DigestFinal_ex(&ctx, H, NULL);
   EVP_MD_CTX_cleanup(&ctx);
+  if (!digest_ok) {
+    goto err;
+  }
 
   /* Generate dbMask in place then perform XOR on it */
-  if (PKCS1_MGF1(EM, maskedDBLen, H, hLen, mgf1Hash)) {
+  if (!PKCS1_MGF1(EM, maskedDBLen, H, hLen, mgf1Hash)) {
     goto err;
   }
 
@@ -686,7 +670,7 @@
   p += emLen - sLen - hLen - 2;
   *p++ ^= 0x1;
   if (sLen > 0) {
-    for (i = 0; i < sLen; i++) {
+    for (size_t i = 0; i < sLen; i++) {
       *p++ ^= salt[i];
     }
   }
diff --git a/src/crypto/rsa/rsa.c b/src/crypto/rsa/rsa.c
index 6c28ad7..731293f 100644
--- a/src/crypto/rsa/rsa.c
+++ b/src/crypto/rsa/rsa.c
@@ -64,7 +64,7 @@
 #include <openssl/err.h>
 #include <openssl/ex_data.h>
 #include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
 #include <openssl/thread.h>
 
 #include "internal.h"
@@ -76,13 +76,13 @@
 RSA *RSA_new(void) { return RSA_new_method(NULL); }
 
 RSA *RSA_new_method(const ENGINE *engine) {
-  RSA *rsa = (RSA *)OPENSSL_malloc(sizeof(RSA));
+  RSA *rsa = OPENSSL_malloc(sizeof(RSA));
   if (rsa == NULL) {
     OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
     return NULL;
   }
 
-  memset(rsa, 0, sizeof(RSA));
+  OPENSSL_memset(rsa, 0, sizeof(RSA));
 
   if (engine) {
     rsa->meth = ENGINE_get_RSA_method(engine);
@@ -169,6 +169,42 @@
   return 1;
 }
 
+void RSA_get0_key(const RSA *rsa, const BIGNUM **out_n, const BIGNUM **out_e,
+                  const BIGNUM **out_d) {
+  if (out_n != NULL) {
+    *out_n = rsa->n;
+  }
+  if (out_e != NULL) {
+    *out_e = rsa->e;
+  }
+  if (out_d != NULL) {
+    *out_d = rsa->d;
+  }
+}
+
+void RSA_get0_factors(const RSA *rsa, const BIGNUM **out_p,
+                      const BIGNUM **out_q) {
+  if (out_p != NULL) {
+    *out_p = rsa->p;
+  }
+  if (out_q != NULL) {
+    *out_q = rsa->q;
+  }
+}
+
+void RSA_get0_crt_params(const RSA *rsa, const BIGNUM **out_dmp1,
+                         const BIGNUM **out_dmq1, const BIGNUM **out_iqmp) {
+  if (out_dmp1 != NULL) {
+    *out_dmp1 = rsa->dmp1;
+  }
+  if (out_dmq1 != NULL) {
+    *out_dmq1 = rsa->dmq1;
+  }
+  if (out_iqmp != NULL) {
+    *out_iqmp = rsa->iqmp;
+  }
+}
+
 int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) {
   if (rsa->meth->keygen) {
     return rsa->meth->keygen(rsa, bits, e_value, cb);
@@ -258,16 +294,6 @@
   return out_len;
 }
 
-int RSA_verify_raw(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
-                   const uint8_t *in, size_t in_len, int padding) {
-  if (rsa->meth->verify_raw) {
-    return rsa->meth->verify_raw(rsa, out_len, out, max_out, in, in_len, padding);
-  }
-
-  return rsa_default_verify_raw(rsa, out_len, out, max_out, in, in_len,
-                                padding);
-}
-
 int RSA_public_decrypt(size_t flen, const uint8_t *from, uint8_t *to, RSA *rsa,
                        int padding) {
   size_t out_len;
@@ -420,8 +446,8 @@
       return 0;
     }
 
-    memcpy(signed_msg, prefix, prefix_len);
-    memcpy(signed_msg + prefix_len, msg, msg_len);
+    OPENSSL_memcpy(signed_msg, prefix, prefix_len);
+    OPENSSL_memcpy(signed_msg + prefix_len, msg, msg_len);
 
     *out_msg = signed_msg;
     *out_msg_len = signed_msg_len;
@@ -473,6 +499,11 @@
 
 int RSA_verify(int hash_nid, const uint8_t *msg, size_t msg_len,
                const uint8_t *sig, size_t sig_len, RSA *rsa) {
+  if (rsa->n == NULL || rsa->e == NULL) {
+    OPENSSL_PUT_ERROR(RSA, RSA_R_VALUE_MISSING);
+    return 0;
+  }
+
   const size_t rsa_size = RSA_size(rsa);
   uint8_t *buf = NULL;
   int ret = 0;
@@ -480,15 +511,6 @@
   size_t signed_msg_len, len;
   int signed_msg_is_alloced = 0;
 
-  if (rsa->meth->verify) {
-    return rsa->meth->verify(hash_nid, msg, msg_len, sig, sig_len, rsa);
-  }
-
-  if (sig_len != rsa_size) {
-    OPENSSL_PUT_ERROR(RSA, RSA_R_WRONG_SIGNATURE_LENGTH);
-    return 0;
-  }
-
   if (hash_nid == NID_md5_sha1 && msg_len != SSL_SIG_LENGTH) {
     OPENSSL_PUT_ERROR(RSA, RSA_R_INVALID_MESSAGE_LENGTH);
     return 0;
@@ -510,7 +532,7 @@
     goto out;
   }
 
-  if (len != signed_msg_len || CRYPTO_memcmp(buf, signed_msg, len) != 0) {
+  if (len != signed_msg_len || OPENSSL_memcmp(buf, signed_msg, len) != 0) {
     OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_SIGNATURE);
     goto out;
   }
@@ -531,7 +553,7 @@
 }
 
 int RSA_check_key(const RSA *key) {
-  BIGNUM n, pm1, qm1, lcm, gcd, de, dmp1, dmq1, iqmp;
+  BIGNUM n, pm1, qm1, lcm, gcd, de, dmp1, dmq1, iqmp_times_q;
   BN_CTX *ctx;
   int ok = 0, has_crt_values;
 
@@ -570,7 +592,7 @@
   BN_init(&de);
   BN_init(&dmp1);
   BN_init(&dmq1);
-  BN_init(&iqmp);
+  BN_init(&iqmp_times_q);
 
   if (!BN_mul(&n, key->p, key->q, ctx) ||
       /* lcm = lcm(prime-1, for all primes) */
@@ -587,8 +609,7 @@
     num_additional_primes = sk_RSA_additional_prime_num(key->additional_primes);
   }
 
-  size_t i;
-  for (i = 0; i < num_additional_primes; i++) {
+  for (size_t i = 0; i < num_additional_primes; i++) {
     const RSA_additional_prime *ap =
         sk_RSA_additional_prime_value(key->additional_primes, i);
     if (!BN_mul(&n, &n, ap->prime, ctx) ||
@@ -631,14 +652,15 @@
         /* dmq1 = d mod (q-1) */
         !BN_mod(&dmq1, key->d, &qm1, ctx) ||
         /* iqmp = q^-1 mod p */
-        !BN_mod_inverse(&iqmp, key->q, key->p, ctx)) {
+        !BN_mod_mul(&iqmp_times_q, key->iqmp, key->q, key->p, ctx)) {
       OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN);
       goto out;
     }
 
     if (BN_cmp(&dmp1, key->dmp1) != 0 ||
         BN_cmp(&dmq1, key->dmq1) != 0 ||
-        BN_cmp(&iqmp, key->iqmp) != 0) {
+        BN_cmp(key->iqmp, key->p) >= 0 ||
+        !BN_is_one(&iqmp_times_q)) {
       OPENSSL_PUT_ERROR(RSA, RSA_R_CRT_VALUES_INCORRECT);
       goto out;
     }
@@ -655,7 +677,7 @@
   BN_free(&de);
   BN_free(&dmp1);
   BN_free(&dmq1);
-  BN_free(&iqmp);
+  BN_free(&iqmp_times_q);
   BN_CTX_free(ctx);
 
   return ok;
diff --git a/src/crypto/rsa/rsa_asn1.c b/src/crypto/rsa/rsa_asn1.c
index b73a0e1..88b1dfb 100644
--- a/src/crypto/rsa/rsa_asn1.c
+++ b/src/crypto/rsa/rsa_asn1.c
@@ -59,14 +59,14 @@
 #include <limits.h>
 #include <string.h>
 
-#include <openssl/asn1.h>
-#include <openssl/asn1t.h>
 #include <openssl/bn.h>
 #include <openssl/bytestring.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
 #include "internal.h"
+#include "../bytestring/internal.h"
+#include "../internal.h"
 
 
 static int parse_integer_buggy(CBS *cbs, BIGNUM **out, int buggy) {
@@ -76,9 +76,9 @@
     return 0;
   }
   if (buggy) {
-    return BN_cbs2unsigned_buggy(cbs, *out);
+    return BN_parse_asn1_unsigned_buggy(cbs, *out);
   }
-  return BN_cbs2unsigned(cbs, *out);
+  return BN_parse_asn1_unsigned(cbs, *out);
 }
 
 static int parse_integer(CBS *cbs, BIGNUM **out) {
@@ -91,7 +91,7 @@
     OPENSSL_PUT_ERROR(RSA, RSA_R_VALUE_MISSING);
     return 0;
   }
-  return BN_bn2cbb(cbb, bn);
+  return BN_marshal_asn1(cbb, bn);
 }
 
 static RSA *parse_public_key(CBS *cbs, int buggy) {
@@ -184,7 +184,7 @@
     OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
     return 0;
   }
-  memset(ret, 0, sizeof(RSA_additional_prime));
+  OPENSSL_memset(ret, 0, sizeof(RSA_additional_prime));
 
   CBS child;
   if (!CBS_get_asn1(cbs, &child, CBS_ASN1_SEQUENCE) ||
@@ -232,9 +232,11 @@
     goto err;
   }
 
-  /* Multi-prime RSA requires a newer version. */
-  if (version == kVersionMulti &&
-      CBS_peek_asn1_tag(&child, CBS_ASN1_SEQUENCE)) {
+  if (version == kVersionMulti) {
+    /* Although otherPrimeInfos is written as OPTIONAL in RFC 3447, it later
+     * says "[otherPrimeInfos] shall be omitted if version is 0 and shall
+     * contain at least one instance of OtherPrimeInfo if version is 1." The
+     * OPTIONAL is just so both versions share a single definition. */
     CBS other_prime_infos;
     if (!CBS_get_asn1(&child, &other_prime_infos, CBS_ASN1_SEQUENCE) ||
         CBS_len(&other_prime_infos) == 0) {
@@ -279,6 +281,11 @@
     goto err;
   }
 
+  if (!RSA_check_key(ret)) {
+    OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_RSA_PARAMETERS);
+    goto err;
+  }
+
   BN_CTX_free(ctx);
   BN_free(product_of_primes_so_far);
   return ret;
@@ -322,22 +329,23 @@
     return 0;
   }
 
+  CBB other_prime_infos;
   if (is_multiprime) {
-    CBB other_prime_infos;
     if (!CBB_add_asn1(&child, &other_prime_infos, CBS_ASN1_SEQUENCE)) {
       OPENSSL_PUT_ERROR(RSA, RSA_R_ENCODE_ERROR);
       return 0;
     }
-    size_t i;
-    for (i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes); i++) {
+    for (size_t i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes);
+         i++) {
       RSA_additional_prime *ap =
-              sk_RSA_additional_prime_value(rsa->additional_primes, i);
+          sk_RSA_additional_prime_value(rsa->additional_primes, i);
       CBB other_prime_info;
       if (!CBB_add_asn1(&other_prime_infos, &other_prime_info,
                         CBS_ASN1_SEQUENCE) ||
           !marshal_integer(&other_prime_info, ap->prime) ||
           !marshal_integer(&other_prime_info, ap->exp) ||
-          !marshal_integer(&other_prime_info, ap->coeff)) {
+          !marshal_integer(&other_prime_info, ap->coeff) ||
+          !CBB_flush(&other_prime_infos)) {
         OPENSSL_PUT_ERROR(RSA, RSA_R_ENCODE_ERROR);
         return 0;
       }
@@ -379,32 +387,18 @@
     RSA_free(*out);
     *out = ret;
   }
-  *inp += (size_t)len - CBS_len(&cbs);
+  *inp = CBS_data(&cbs);
   return ret;
 }
 
 int i2d_RSAPublicKey(const RSA *in, uint8_t **outp) {
-  uint8_t *der;
-  size_t der_len;
-  if (!RSA_public_key_to_bytes(&der, &der_len, in)) {
+  CBB cbb;
+  if (!CBB_init(&cbb, 0) ||
+      !RSA_marshal_public_key(&cbb, in)) {
+    CBB_cleanup(&cbb);
     return -1;
   }
-  if (der_len > INT_MAX) {
-    OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW);
-    OPENSSL_free(der);
-    return -1;
-  }
-  if (outp != NULL) {
-    if (*outp == NULL) {
-      *outp = der;
-      der = NULL;
-    } else {
-      memcpy(*outp, der, der_len);
-      *outp += der_len;
-    }
-  }
-  OPENSSL_free(der);
-  return (int)der_len;
+  return CBB_finish_i2d(&cbb, outp);
 }
 
 RSA *d2i_RSAPrivateKey(RSA **out, const uint8_t **inp, long len) {
@@ -421,43 +415,20 @@
     RSA_free(*out);
     *out = ret;
   }
-  *inp += (size_t)len - CBS_len(&cbs);
+  *inp = CBS_data(&cbs);
   return ret;
 }
 
 int i2d_RSAPrivateKey(const RSA *in, uint8_t **outp) {
-  uint8_t *der;
-  size_t der_len;
-  if (!RSA_private_key_to_bytes(&der, &der_len, in)) {
+  CBB cbb;
+  if (!CBB_init(&cbb, 0) ||
+      !RSA_marshal_private_key(&cbb, in)) {
+    CBB_cleanup(&cbb);
     return -1;
   }
-  if (der_len > INT_MAX) {
-    OPENSSL_PUT_ERROR(RSA, ERR_R_OVERFLOW);
-    OPENSSL_free(der);
-    return -1;
-  }
-  if (outp != NULL) {
-    if (*outp == NULL) {
-      *outp = der;
-      der = NULL;
-    } else {
-      memcpy(*outp, der, der_len);
-      *outp += der_len;
-    }
-  }
-  OPENSSL_free(der);
-  return (int)der_len;
+  return CBB_finish_i2d(&cbb, outp);
 }
 
-ASN1_SEQUENCE(RSA_PSS_PARAMS) = {
-  ASN1_EXP_OPT(RSA_PSS_PARAMS, hashAlgorithm, X509_ALGOR,0),
-  ASN1_EXP_OPT(RSA_PSS_PARAMS, maskGenAlgorithm, X509_ALGOR,1),
-  ASN1_EXP_OPT(RSA_PSS_PARAMS, saltLength, ASN1_INTEGER,2),
-  ASN1_EXP_OPT(RSA_PSS_PARAMS, trailerField, ASN1_INTEGER,3),
-} ASN1_SEQUENCE_END(RSA_PSS_PARAMS);
-
-IMPLEMENT_ASN1_FUNCTIONS(RSA_PSS_PARAMS);
-
 RSA *RSAPublicKey_dup(const RSA *rsa) {
   uint8_t *der;
   size_t der_len;
diff --git a/src/crypto/rsa/rsa_impl.c b/src/crypto/rsa/rsa_impl.c
index b1cfaa6..8e0aa9c 100644
--- a/src/crypto/rsa/rsa_impl.c
+++ b/src/crypto/rsa/rsa_impl.c
@@ -56,6 +56,7 @@
 
 #include <openssl/rsa.h>
 
+#include <assert.h>
 #include <string.h>
 
 #include <openssl/bn.h>
@@ -64,14 +65,46 @@
 #include <openssl/thread.h>
 
 #include "internal.h"
+#include "../bn/internal.h"
 #include "../internal.h"
 
 
-#define OPENSSL_RSA_MAX_MODULUS_BITS 16384
-#define OPENSSL_RSA_SMALL_MODULUS_BITS 3072
-#define OPENSSL_RSA_MAX_PUBEXP_BITS \
-  64 /* exponent limit enforced for "large" modulus only */
+static int check_modulus_and_exponent_sizes(const RSA *rsa) {
+  unsigned rsa_bits = BN_num_bits(rsa->n);
 
+  if (rsa_bits > 16 * 1024) {
+    OPENSSL_PUT_ERROR(RSA, RSA_R_MODULUS_TOO_LARGE);
+    return 0;
+  }
+
+  /* Mitigate DoS attacks by limiting the exponent size. 33 bits was chosen as
+   * the limit based on the recommendations in [1] and [2]. Windows CryptoAPI
+   * doesn't support values larger than 32 bits [3], so it is unlikely that
+   * exponents larger than 32 bits are being used for anything Windows commonly
+   * does.
+   *
+   * [1] https://www.imperialviolet.org/2012/03/16/rsae.html
+   * [2] https://www.imperialviolet.org/2012/03/17/rsados.html
+   * [3] https://msdn.microsoft.com/en-us/library/aa387685(VS.85).aspx */
+  static const unsigned kMaxExponentBits = 33;
+
+  if (BN_num_bits(rsa->e) > kMaxExponentBits) {
+    OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_E_VALUE);
+    return 0;
+  }
+
+  /* Verify |n > e|. Comparing |rsa_bits| to |kMaxExponentBits| is a small
+   * shortcut to comparing |n| and |e| directly. In reality, |kMaxExponentBits|
+   * is much smaller than the minimum RSA key size that any application should
+   * accept. */
+  if (rsa_bits <= kMaxExponentBits) {
+    OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
+    return 0;
+  }
+  assert(BN_ucmp(rsa->n, rsa->e) > 0);
+
+  return 1;
+}
 
 size_t rsa_default_size(const RSA *rsa) {
   return BN_num_bytes(rsa->n);
@@ -85,25 +118,12 @@
   BN_CTX *ctx = NULL;
   int i, ret = 0;
 
-  if (rsa_size > OPENSSL_RSA_MAX_MODULUS_BITS) {
-    OPENSSL_PUT_ERROR(RSA, RSA_R_MODULUS_TOO_LARGE);
-    return 0;
-  }
-
   if (max_out < rsa_size) {
     OPENSSL_PUT_ERROR(RSA, RSA_R_OUTPUT_BUFFER_TOO_SMALL);
     return 0;
   }
 
-  if (BN_ucmp(rsa->n, rsa->e) <= 0) {
-    OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_E_VALUE);
-    return 0;
-  }
-
-  /* for large moduli, enforce exponent limit */
-  if (BN_num_bits(rsa->n) > OPENSSL_RSA_SMALL_MODULUS_BITS &&
-      BN_num_bits(rsa->e) > OPENSSL_RSA_MAX_PUBEXP_BITS) {
-    OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_E_VALUE);
+  if (!check_modulus_and_exponent_sizes(rsa)) {
     return 0;
   }
 
@@ -152,13 +172,8 @@
     goto err;
   }
 
-  if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) {
-    if (BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx) == NULL) {
-      goto err;
-    }
-  }
-
-  if (!rsa->meth->bn_mod_exp(result, f, rsa->e, rsa->n, ctx, rsa->mont_n)) {
+  if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx) ||
+      !BN_mod_exp_mont(result, f, rsa->e, rsa->n, ctx, rsa->mont_n)) {
     goto err;
   }
 
@@ -199,6 +214,9 @@
  * |*index_used| and must be passed to |rsa_blinding_release| when finished. */
 static BN_BLINDING *rsa_blinding_get(RSA *rsa, unsigned *index_used,
                                      BN_CTX *ctx) {
+  assert(ctx != NULL);
+  assert(rsa->mont_n != NULL);
+
   BN_BLINDING *ret = NULL;
   BN_BLINDING **new_blindings;
   uint8_t *new_blindings_inuse;
@@ -217,7 +235,7 @@
   }
 
   if (ret != NULL) {
-    CRYPTO_MUTEX_unlock(&rsa->lock);
+    CRYPTO_MUTEX_unlock_write(&rsa->lock);
     return ret;
   }
 
@@ -226,8 +244,8 @@
   /* We didn't find a free BN_BLINDING to use so increase the length of
    * the arrays by one and use the newly created element. */
 
-  CRYPTO_MUTEX_unlock(&rsa->lock);
-  ret = rsa_setup_blinding(rsa, ctx);
+  CRYPTO_MUTEX_unlock_write(&rsa->lock);
+  ret = BN_BLINDING_new();
   if (ret == NULL) {
     return NULL;
   }
@@ -246,7 +264,7 @@
   if (new_blindings == NULL) {
     goto err1;
   }
-  memcpy(new_blindings, rsa->blindings,
+  OPENSSL_memcpy(new_blindings, rsa->blindings,
          sizeof(BN_BLINDING *) * rsa->num_blindings);
   new_blindings[rsa->num_blindings] = ret;
 
@@ -254,7 +272,7 @@
   if (new_blindings_inuse == NULL) {
     goto err2;
   }
-  memcpy(new_blindings_inuse, rsa->blindings_inuse, rsa->num_blindings);
+  OPENSSL_memcpy(new_blindings_inuse, rsa->blindings_inuse, rsa->num_blindings);
   new_blindings_inuse[rsa->num_blindings] = 1;
   *index_used = rsa->num_blindings;
 
@@ -264,14 +282,14 @@
   rsa->blindings_inuse = new_blindings_inuse;
   rsa->num_blindings++;
 
-  CRYPTO_MUTEX_unlock(&rsa->lock);
+  CRYPTO_MUTEX_unlock_write(&rsa->lock);
   return ret;
 
 err2:
   OPENSSL_free(new_blindings);
 
 err1:
-  CRYPTO_MUTEX_unlock(&rsa->lock);
+  CRYPTO_MUTEX_unlock_write(&rsa->lock);
   BN_BLINDING_free(ret);
   return NULL;
 }
@@ -288,7 +306,7 @@
 
   CRYPTO_MUTEX_lock_write(&rsa->lock);
   rsa->blindings_inuse[blinding_index] = 0;
-  CRYPTO_MUTEX_unlock(&rsa->lock);
+  CRYPTO_MUTEX_unlock_write(&rsa->lock);
 }
 
 /* signing */
@@ -407,46 +425,49 @@
   return ret;
 }
 
-int rsa_default_verify_raw(RSA *rsa, size_t *out_len, uint8_t *out,
-                           size_t max_out, const uint8_t *in, size_t in_len,
-                           int padding) {
+static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx);
+
+int RSA_verify_raw(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
+                   const uint8_t *in, size_t in_len, int padding) {
+  if (rsa->n == NULL || rsa->e == NULL) {
+    OPENSSL_PUT_ERROR(RSA, RSA_R_VALUE_MISSING);
+    return 0;
+  }
+
   const unsigned rsa_size = RSA_size(rsa);
   BIGNUM *f, *result;
-  int ret = 0;
   int r = -1;
-  uint8_t *buf = NULL;
-  BN_CTX *ctx = NULL;
-
-  if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS) {
-    OPENSSL_PUT_ERROR(RSA, RSA_R_MODULUS_TOO_LARGE);
-    return 0;
-  }
-
-  if (BN_ucmp(rsa->n, rsa->e) <= 0) {
-    OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_E_VALUE);
-    return 0;
-  }
 
   if (max_out < rsa_size) {
     OPENSSL_PUT_ERROR(RSA, RSA_R_OUTPUT_BUFFER_TOO_SMALL);
     return 0;
   }
 
-  /* for large moduli, enforce exponent limit */
-  if (BN_num_bits(rsa->n) > OPENSSL_RSA_SMALL_MODULUS_BITS &&
-      BN_num_bits(rsa->e) > OPENSSL_RSA_MAX_PUBEXP_BITS) {
-    OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_E_VALUE);
+  if (in_len != rsa_size) {
+    OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_LEN_NOT_EQUAL_TO_MOD_LEN);
     return 0;
   }
 
-  ctx = BN_CTX_new();
-  if (ctx == NULL) {
-    goto err;
+  if (!check_modulus_and_exponent_sizes(rsa)) {
+    return 0;
   }
 
+  BN_CTX *ctx = BN_CTX_new();
+  if (ctx == NULL) {
+    return 0;
+  }
+
+  int ret = 0;
+  uint8_t *buf = NULL;
+
   BN_CTX_start(ctx);
   f = BN_CTX_get(ctx);
   result = BN_CTX_get(ctx);
+  if (f == NULL || result == NULL) {
+    OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
+    goto err;
+  }
+
   if (padding == RSA_NO_PADDING) {
     buf = out;
   } else {
@@ -457,15 +478,6 @@
       goto err;
     }
   }
-  if (!f || !result) {
-    OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
-    goto err;
-  }
-
-  if (in_len != rsa_size) {
-    OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_LEN_NOT_EQUAL_TO_MOD_LEN);
-    goto err;
-  }
 
   if (BN_bin2bn(in, in_len, f) == NULL) {
     goto err;
@@ -476,13 +488,8 @@
     goto err;
   }
 
-  if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) {
-    if (BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx) == NULL) {
-      goto err;
-    }
-  }
-
-  if (!rsa->meth->bn_mod_exp(result, f, rsa->e, rsa->n, ctx, rsa->mont_n)) {
+  if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx) ||
+      !BN_mod_exp_mont(result, f, rsa->e, rsa->n, ctx, rsa->mont_n)) {
     goto err;
   }
 
@@ -511,12 +518,9 @@
   }
 
 err:
-  if (ctx != NULL) {
-    BN_CTX_end(ctx);
-    BN_CTX_free(ctx);
-  }
-  if (padding != RSA_NO_PADDING && buf != NULL) {
-    OPENSSL_cleanse(buf, rsa_size);
+  BN_CTX_end(ctx);
+  BN_CTX_free(ctx);
+  if (buf != out) {
     OPENSSL_free(buf);
   }
   return ret;
@@ -553,45 +557,64 @@
     goto err;
   }
 
-  if (!(rsa->flags & RSA_FLAG_NO_BLINDING)) {
+  if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx)) {
+    OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
+    goto err;
+  }
+
+  /* We cannot do blinding or verification without |e|, and continuing without
+   * those countermeasures is dangerous. However, the Java/Android RSA API
+   * requires support for keys where only |d| and |n| (and not |e|) are known.
+   * The callers that require that bad behavior set |RSA_FLAG_NO_BLINDING|. */
+  int disable_security = (rsa->flags & RSA_FLAG_NO_BLINDING) && rsa->e == NULL;
+
+  if (!disable_security) {
+    /* Keys without public exponents must have blinding explicitly disabled to
+     * be used. */
+    if (rsa->e == NULL) {
+      OPENSSL_PUT_ERROR(RSA, RSA_R_NO_PUBLIC_EXPONENT);
+      goto err;
+    }
+
     blinding = rsa_blinding_get(rsa, &blinding_index, ctx);
     if (blinding == NULL) {
       OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
       goto err;
     }
-    if (!BN_BLINDING_convert_ex(f, NULL, blinding, ctx)) {
+    if (!BN_BLINDING_convert(f, blinding, rsa->e, rsa->mont_n, ctx)) {
       goto err;
     }
   }
 
-  if ((rsa->flags & RSA_FLAG_EXT_PKEY) ||
-      ((rsa->p != NULL) && (rsa->q != NULL) && (rsa->dmp1 != NULL) &&
-       (rsa->dmq1 != NULL) && (rsa->iqmp != NULL))) {
-    if (!rsa->meth->mod_exp(result, f, rsa, ctx)) {
+  if (rsa->p != NULL && rsa->q != NULL && rsa->e != NULL && rsa->dmp1 != NULL &&
+      rsa->dmq1 != NULL && rsa->iqmp != NULL) {
+    if (!mod_exp(result, f, rsa, ctx)) {
       goto err;
     }
-  } else {
-    BIGNUM local_d;
-    BIGNUM *d = NULL;
-
-    BN_init(&local_d);
-    d = &local_d;
-    BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
-
-    if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) {
-      if (BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx) ==
-          NULL) {
-        goto err;
-      }
-    }
-
-    if (!rsa->meth->bn_mod_exp(result, f, d, rsa->n, ctx, rsa->mont_n)) {
-      goto err;
-    }
+  } else if (!BN_mod_exp_mont_consttime(result, f, rsa->d, rsa->n, ctx,
+                                        rsa->mont_n)) {
+    goto err;
   }
 
-  if (blinding) {
-    if (!BN_BLINDING_invert_ex(result, NULL, blinding, ctx)) {
+  /* Verify the result to protect against fault attacks as described in the
+   * 1997 paper "On the Importance of Checking Cryptographic Protocols for
+   * Faults" by Dan Boneh, Richard A. DeMillo, and Richard J. Lipton. Some
+   * implementations do this only when the CRT is used, but we do it in all
+   * cases. Section 6 of the aforementioned paper describes an attack that
+   * works when the CRT isn't used. That attack is much less likely to succeed
+   * than the CRT attack, but there have likely been improvements since 1997.
+   *
+   * This check is cheap assuming |e| is small; it almost always is. */
+  if (!disable_security) {
+    BIGNUM *vrfy = BN_CTX_get(ctx);
+    if (vrfy == NULL ||
+        !BN_mod_exp_mont(vrfy, result, rsa->e, rsa->n, ctx, rsa->mont_n) ||
+        !BN_equal_consttime(vrfy, f)) {
+      OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
+      goto err;
+    }
+
+    if (!BN_BLINDING_invert(result, blinding, rsa->mont_n, ctx)) {
       goto err;
     }
   }
@@ -616,9 +639,18 @@
 }
 
 static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) {
+  assert(ctx != NULL);
+
+  assert(rsa->n != NULL);
+  assert(rsa->e != NULL);
+  assert(rsa->d != NULL);
+  assert(rsa->p != NULL);
+  assert(rsa->q != NULL);
+  assert(rsa->dmp1 != NULL);
+  assert(rsa->dmq1 != NULL);
+  assert(rsa->iqmp != NULL);
+
   BIGNUM *r1, *m1, *vrfy;
-  BIGNUM local_dmp1, local_dmq1, local_c, local_r1;
-  BIGNUM *dmp1, *dmq1, *c, *pr1;
   int ret = 0;
   size_t i, num_additional_primes = 0;
 
@@ -630,62 +662,38 @@
   r1 = BN_CTX_get(ctx);
   m1 = BN_CTX_get(ctx);
   vrfy = BN_CTX_get(ctx);
-
-  {
-    BIGNUM local_p, local_q;
-    BIGNUM *p = NULL, *q = NULL;
-
-    /* Make sure BN_mod_inverse in Montgomery intialization uses the
-     * BN_FLG_CONSTTIME flag. */
-    BN_init(&local_p);
-    p = &local_p;
-    BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME);
-
-    BN_init(&local_q);
-    q = &local_q;
-    BN_with_flags(q, rsa->q, BN_FLG_CONSTTIME);
-
-    if (rsa->flags & RSA_FLAG_CACHE_PRIVATE) {
-      if (BN_MONT_CTX_set_locked(&rsa->mont_p, &rsa->lock, p, ctx) == NULL) {
-        goto err;
-      }
-      if (BN_MONT_CTX_set_locked(&rsa->mont_q, &rsa->lock, q, ctx) == NULL) {
-        goto err;
-      }
-    }
+  if (r1 == NULL ||
+      m1 == NULL ||
+      vrfy == NULL) {
+    goto err;
   }
 
-  if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) {
-    if (BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx) == NULL) {
-      goto err;
-    }
+  if (!BN_MONT_CTX_set_locked(&rsa->mont_p, &rsa->lock, rsa->p, ctx) ||
+      !BN_MONT_CTX_set_locked(&rsa->mont_q, &rsa->lock, rsa->q, ctx)) {
+    goto err;
+  }
+
+  if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx)) {
+    goto err;
   }
 
   /* compute I mod q */
-  c = &local_c;
-  BN_with_flags(c, I, BN_FLG_CONSTTIME);
-  if (!BN_mod(r1, c, rsa->q, ctx)) {
+  if (!BN_mod(r1, I, rsa->q, ctx)) {
     goto err;
   }
 
   /* compute r1^dmq1 mod q */
-  dmq1 = &local_dmq1;
-  BN_with_flags(dmq1, rsa->dmq1, BN_FLG_CONSTTIME);
-  if (!rsa->meth->bn_mod_exp(m1, r1, dmq1, rsa->q, ctx, rsa->mont_q)) {
+  if (!BN_mod_exp_mont_consttime(m1, r1, rsa->dmq1, rsa->q, ctx, rsa->mont_q)) {
     goto err;
   }
 
   /* compute I mod p */
-  c = &local_c;
-  BN_with_flags(c, I, BN_FLG_CONSTTIME);
-  if (!BN_mod(r1, c, rsa->p, ctx)) {
+  if (!BN_mod(r1, I, rsa->p, ctx)) {
     goto err;
   }
 
   /* compute r1^dmp1 mod p */
-  dmp1 = &local_dmp1;
-  BN_with_flags(dmp1, rsa->dmp1, BN_FLG_CONSTTIME);
-  if (!rsa->meth->bn_mod_exp(r0, r1, dmp1, rsa->p, ctx, rsa->mont_p)) {
+  if (!BN_mod_exp_mont_consttime(r0, r1, rsa->dmp1, rsa->p, ctx, rsa->mont_p)) {
     goto err;
   }
 
@@ -704,11 +712,7 @@
     goto err;
   }
 
-  /* Turn BN_FLG_CONSTTIME flag on before division operation */
-  pr1 = &local_r1;
-  BN_with_flags(pr1, r1, BN_FLG_CONSTTIME);
-
-  if (!BN_mod(r0, pr1, rsa->p, ctx)) {
+  if (!BN_mod(r0, r1, rsa->p, ctx)) {
     goto err;
   }
 
@@ -732,74 +736,29 @@
 
   for (i = 0; i < num_additional_primes; i++) {
     /* multi-prime RSA. */
-    BIGNUM local_exp, local_prime;
-    BIGNUM *exp = &local_exp, *prime = &local_prime;
     RSA_additional_prime *ap =
         sk_RSA_additional_prime_value(rsa->additional_primes, i);
 
-    BN_with_flags(exp, ap->exp, BN_FLG_CONSTTIME);
-    BN_with_flags(prime, ap->prime, BN_FLG_CONSTTIME);
-
     /* c will already point to a BIGNUM with the correct flags. */
-    if (!BN_mod(r1, c, prime, ctx)) {
+    if (!BN_mod(r1, I, ap->prime, ctx)) {
       goto err;
     }
 
-    if ((rsa->flags & RSA_FLAG_CACHE_PRIVATE) &&
-        !BN_MONT_CTX_set_locked(&ap->mont, &rsa->lock, prime, ctx)) {
+    if (!BN_MONT_CTX_set_locked(&ap->mont, &rsa->lock, ap->prime, ctx) ||
+        !BN_mod_exp_mont_consttime(m1, r1, ap->exp, ap->prime, ctx, ap->mont)) {
       goto err;
     }
 
-    if (!rsa->meth->bn_mod_exp(m1, r1, exp, prime, ctx, ap->mont)) {
-      goto err;
-    }
-
-    BN_set_flags(m1, BN_FLG_CONSTTIME);
-
     if (!BN_sub(m1, m1, r0) ||
         !BN_mul(m1, m1, ap->coeff, ctx) ||
-        !BN_mod(m1, m1, prime, ctx) ||
-        (BN_is_negative(m1) && !BN_add(m1, m1, prime)) ||
+        !BN_mod(m1, m1, ap->prime, ctx) ||
+        (BN_is_negative(m1) && !BN_add(m1, m1, ap->prime)) ||
         !BN_mul(m1, m1, ap->r, ctx) ||
         !BN_add(r0, r0, m1)) {
       goto err;
     }
   }
 
-  if (rsa->e && rsa->n) {
-    if (!rsa->meth->bn_mod_exp(vrfy, r0, rsa->e, rsa->n, ctx, rsa->mont_n)) {
-      goto err;
-    }
-    /* If 'I' was greater than (or equal to) rsa->n, the operation
-     * will be equivalent to using 'I mod n'. However, the result of
-     * the verify will *always* be less than 'n' so we don't check
-     * for absolute equality, just congruency. */
-    if (!BN_sub(vrfy, vrfy, I)) {
-      goto err;
-    }
-    if (!BN_mod(vrfy, vrfy, rsa->n, ctx)) {
-      goto err;
-    }
-    if (BN_is_negative(vrfy)) {
-      if (!BN_add(vrfy, vrfy, rsa->n)) {
-        goto err;
-      }
-    }
-    if (!BN_is_zero(vrfy)) {
-      /* 'I' and 'vrfy' aren't congruent mod n. Don't leak
-       * miscalculated CRT output, just do a raw (slower)
-       * mod_exp and return that instead. */
-
-      BIGNUM local_d;
-      BIGNUM *d = NULL;
-
-      d = &local_d;
-      BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
-      if (!rsa->meth->bn_mod_exp(r0, I, d, rsa->n, ctx, rsa->mont_n)) {
-        goto err;
-      }
-    }
-  }
   ret = 1;
 
 err:
@@ -810,8 +769,6 @@
 int rsa_default_multi_prime_keygen(RSA *rsa, int bits, int num_primes,
                                    BIGNUM *e_value, BN_GENCB *cb) {
   BIGNUM *r0 = NULL, *r1 = NULL, *r2 = NULL, *r3 = NULL, *tmp;
-  BIGNUM local_r0, local_d, local_p;
-  BIGNUM *pr0, *d, *p;
   int prime_bits, ok = -1, n = 0, i, j;
   BN_CTX *ctx = NULL;
   STACK_OF(RSA_additional_prime) *additional_primes = NULL;
@@ -847,7 +804,7 @@
     if (ap == NULL) {
       goto err;
     }
-    memset(ap, 0, sizeof(RSA_additional_prime));
+    OPENSSL_memset(ap, 0, sizeof(RSA_additional_prime));
     ap->prime = BN_new();
     ap->exp = BN_new();
     ap->coeff = BN_new();
@@ -1040,31 +997,27 @@
       goto err;
     }
   }
-  pr0 = &local_r0;
-  BN_with_flags(pr0, r0, BN_FLG_CONSTTIME);
-  if (!BN_mod_inverse(rsa->d, rsa->e, pr0, ctx)) {
+  if (!BN_mod_inverse(rsa->d, rsa->e, r0, ctx)) {
     goto err; /* d */
   }
 
-  /* set up d for correct BN_FLG_CONSTTIME flag */
-  d = &local_d;
-  BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
-
   /* calculate d mod (p-1) */
-  if (!BN_mod(rsa->dmp1, d, r1, ctx)) {
+  if (!BN_mod(rsa->dmp1, rsa->d, r1, ctx)) {
     goto err;
   }
 
   /* calculate d mod (q-1) */
-  if (!BN_mod(rsa->dmq1, d, r2, ctx)) {
+  if (!BN_mod(rsa->dmq1, rsa->d, r2, ctx)) {
     goto err;
   }
 
-  /* calculate inverse of q mod p */
-  p = &local_p;
-  BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME);
-
-  if (!BN_mod_inverse(rsa->iqmp, rsa->q, p, ctx)) {
+  /* Calculate inverse of q mod p. Note that although RSA key generation is far
+   * from constant-time, |bn_mod_inverse_secret_prime| uses the same modular
+   * exponentation logic as in RSA private key operations and, if the RSAZ-1024
+   * code is enabled, will be optimized for common RSA prime sizes. */
+  if (!BN_MONT_CTX_set_locked(&rsa->mont_p, &rsa->lock, rsa->p, ctx) ||
+      !bn_mod_inverse_secret_prime(rsa->iqmp, rsa->q, rsa->p, ctx,
+                                   rsa->mont_p)) {
     goto err;
   }
 
@@ -1073,15 +1026,24 @@
         sk_RSA_additional_prime_value(additional_primes, i - 2);
     if (!BN_sub(ap->exp, ap->prime, BN_value_one()) ||
         !BN_mod(ap->exp, rsa->d, ap->exp, ctx) ||
-        !BN_mod_inverse(ap->coeff, ap->r, ap->prime, ctx)) {
+        !BN_MONT_CTX_set_locked(&ap->mont, &rsa->lock, ap->prime, ctx) ||
+        !bn_mod_inverse_secret_prime(ap->coeff, ap->r, ap->prime, ctx,
+                                     ap->mont)) {
       goto err;
     }
   }
 
-  ok = 1;
   rsa->additional_primes = additional_primes;
   additional_primes = NULL;
 
+  /* The key generation process is complex and thus error-prone. It could be
+   * disastrous to generate and then use a bad key so double-check that the key
+   * makes sense. */
+  ok = RSA_check_key(rsa);
+  if (!ok) {
+    OPENSSL_PUT_ERROR(RSA, RSA_R_INTERNAL_ERROR);
+  }
+
 err:
   if (ok == -1) {
     OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN);
@@ -1101,9 +1063,9 @@
                                         cb);
 }
 
-/* Many of these methods are NULL to more easily drop unused functions. The
- * wrapper functions will select the appropriate |rsa_default_*| for all
- * methods. */
+/* All of the methods are NULL to make it easier for the compiler/linker to drop
+ * unused functions. The wrapper functions will select the appropriate
+ * |rsa_default_*| implementation. */
 const RSA_METHOD RSA_default_method = {
   {
     0 /* references */,
@@ -1126,8 +1088,8 @@
 
   NULL /* private_transform (defaults to rsa_default_private_transform) */,
 
-  mod_exp,
-  BN_mod_exp_mont /* bn_mod_exp */,
+  NULL /* mod_exp (ignored) */,
+  NULL /* bn_mod_exp (ignored) */,
 
   RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_CACHE_PRIVATE,
 
diff --git a/src/crypto/rsa/rsa_test.cc b/src/crypto/rsa/rsa_test.cc
index 5545161..401efdf 100644
--- a/src/crypto/rsa/rsa_test.cc
+++ b/src/crypto/rsa/rsa_test.cc
@@ -59,13 +59,16 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include <gtest/gtest.h>
+
 #include <openssl/bn.h>
 #include <openssl/bytestring.h>
 #include <openssl/crypto.h>
 #include <openssl/err.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
 
-#include "../test/scoped_types.h"
+#include "../internal.h"
+#include "../test/test_util.h"
 
 
 // kPlaintext is a sample plaintext.
@@ -523,396 +526,308 @@
     0xdd, 0x02, 0x01, 0x01,
 };
 
-static bool TestRSA(const uint8_t *der, size_t der_len,
-                    const uint8_t *oaep_ciphertext,
-                    size_t oaep_ciphertext_len) {
-  ScopedRSA key(RSA_private_key_from_bytes(der, der_len));
-  if (!key) {
-    return false;
-  }
+struct RSAEncryptParam {
+  const uint8_t *der;
+  size_t der_len;
+  const uint8_t *oaep_ciphertext;
+  size_t oaep_ciphertext_len;
+} kRSAEncryptParams[] = {
+    {kKey1, sizeof(kKey1) - 1, kOAEPCiphertext1, sizeof(kOAEPCiphertext1) - 1},
+    {kKey2, sizeof(kKey2) - 1, kOAEPCiphertext2, sizeof(kOAEPCiphertext2) - 1},
+    {kKey3, sizeof(kKey3) - 1, kOAEPCiphertext3, sizeof(kOAEPCiphertext3) - 1},
+};
 
-  if (!RSA_check_key(key.get())) {
-    fprintf(stderr, "RSA_check_key failed\n");
-    return false;
-  }
+class RSAEncryptTest : public testing::TestWithParam<RSAEncryptParam> {};
+
+TEST_P(RSAEncryptTest, TestKey) {
+  const auto &param = GetParam();
+  bssl::UniquePtr<RSA> key(
+      RSA_private_key_from_bytes(param.der, param.der_len));
+  ASSERT_TRUE(key);
+
+  EXPECT_TRUE(RSA_check_key(key.get()));
 
   uint8_t ciphertext[256];
 
+  // Test that PKCS#1 v1.5 encryption round-trips.
   size_t ciphertext_len = 0;
-  if (!RSA_encrypt(key.get(), &ciphertext_len, ciphertext, sizeof(ciphertext),
-                   kPlaintext, kPlaintextLen, RSA_PKCS1_PADDING) ||
-      ciphertext_len != RSA_size(key.get())) {
-    fprintf(stderr, "PKCS#1 v1.5 encryption failed!\n");
-    return false;
-  }
+  ASSERT_TRUE(RSA_encrypt(key.get(), &ciphertext_len, ciphertext,
+                          sizeof(ciphertext), kPlaintext, kPlaintextLen,
+                          RSA_PKCS1_PADDING));
+  EXPECT_EQ(RSA_size(key.get()), ciphertext_len);
 
   uint8_t plaintext[256];
   size_t plaintext_len = 0;
-  if (!RSA_decrypt(key.get(), &plaintext_len, plaintext, sizeof(plaintext),
-                   ciphertext, ciphertext_len, RSA_PKCS1_PADDING) ||
-      plaintext_len != kPlaintextLen ||
-      memcmp(plaintext, kPlaintext, plaintext_len) != 0) {
-    fprintf(stderr, "PKCS#1 v1.5 decryption failed!\n");
-    return false;
-  }
+  ASSERT_TRUE(RSA_decrypt(key.get(), &plaintext_len, plaintext,
+                          sizeof(plaintext), ciphertext, ciphertext_len,
+                          RSA_PKCS1_PADDING));
+  EXPECT_EQ(Bytes(kPlaintext, kPlaintextLen), Bytes(plaintext, plaintext_len));
 
+  // Test that OAEP encryption round-trips.
   ciphertext_len = 0;
-  if (!RSA_encrypt(key.get(), &ciphertext_len, ciphertext, sizeof(ciphertext),
-                   kPlaintext, kPlaintextLen, RSA_PKCS1_OAEP_PADDING) ||
-      ciphertext_len != RSA_size(key.get())) {
-    fprintf(stderr, "OAEP encryption failed!\n");
-    return false;
-  }
+  ASSERT_TRUE(RSA_encrypt(key.get(), &ciphertext_len, ciphertext,
+                          sizeof(ciphertext), kPlaintext, kPlaintextLen,
+                          RSA_PKCS1_OAEP_PADDING));
+  EXPECT_EQ(RSA_size(key.get()), ciphertext_len);
 
   plaintext_len = 0;
-  if (!RSA_decrypt(key.get(), &plaintext_len, plaintext, sizeof(plaintext),
-                   ciphertext, ciphertext_len, RSA_PKCS1_OAEP_PADDING) ||
-      plaintext_len != kPlaintextLen ||
-      memcmp(plaintext, kPlaintext, plaintext_len) != 0) {
-    fprintf(stderr, "OAEP decryption (encrypted data) failed!\n");
-    return false;
-  }
+  ASSERT_TRUE(RSA_decrypt(key.get(), &plaintext_len, plaintext,
+                          sizeof(plaintext), ciphertext, ciphertext_len,
+                          RSA_PKCS1_OAEP_PADDING));
+  EXPECT_EQ(Bytes(kPlaintext, kPlaintextLen), Bytes(plaintext, plaintext_len));
 
   // |oaep_ciphertext| should decrypt to |kPlaintext|.
   plaintext_len = 0;
-  if (!RSA_decrypt(key.get(), &plaintext_len, plaintext, sizeof(plaintext),
-                   oaep_ciphertext, oaep_ciphertext_len,
-                   RSA_PKCS1_OAEP_PADDING) ||
-      plaintext_len != kPlaintextLen ||
-      memcmp(plaintext, kPlaintext, plaintext_len) != 0) {
-    fprintf(stderr, "OAEP decryption (test vector data) failed!\n");
-    return false;
-  }
+  ASSERT_TRUE(RSA_decrypt(key.get(), &plaintext_len, plaintext,
+                          sizeof(plaintext), param.oaep_ciphertext,
+                          param.oaep_ciphertext_len, RSA_PKCS1_OAEP_PADDING));
+  EXPECT_EQ(Bytes(kPlaintext, kPlaintextLen), Bytes(plaintext, plaintext_len));
 
   // Try decrypting corrupted ciphertexts.
-  memcpy(ciphertext, oaep_ciphertext, oaep_ciphertext_len);
-  for (size_t i = 0; i < oaep_ciphertext_len; i++) {
+  OPENSSL_memcpy(ciphertext, param.oaep_ciphertext, param.oaep_ciphertext_len);
+  for (size_t i = 0; i < param.oaep_ciphertext_len; i++) {
+    SCOPED_TRACE(i);
     ciphertext[i] ^= 1;
-    if (RSA_decrypt(key.get(), &plaintext_len, plaintext, sizeof(plaintext),
-                    ciphertext, oaep_ciphertext_len, RSA_PKCS1_OAEP_PADDING)) {
-      fprintf(stderr, "Corrupt data decrypted!\n");
-      return false;
-    }
+    EXPECT_FALSE(RSA_decrypt(
+        key.get(), &plaintext_len, plaintext, sizeof(plaintext), ciphertext,
+        param.oaep_ciphertext_len, RSA_PKCS1_OAEP_PADDING));
+    ERR_clear_error();
     ciphertext[i] ^= 1;
   }
 
   // Test truncated ciphertexts.
-  for (size_t len = 0; len < oaep_ciphertext_len; len++) {
-    if (RSA_decrypt(key.get(), &plaintext_len, plaintext, sizeof(plaintext),
-                    ciphertext, len, RSA_PKCS1_OAEP_PADDING)) {
-      fprintf(stderr, "Corrupt data decrypted!\n");
-      return false;
-    }
+  for (size_t len = 0; len < param.oaep_ciphertext_len; len++) {
+    SCOPED_TRACE(len);
+    EXPECT_FALSE(RSA_decrypt(key.get(), &plaintext_len, plaintext,
+                             sizeof(plaintext), ciphertext, len,
+                             RSA_PKCS1_OAEP_PADDING));
+    ERR_clear_error();
   }
-
-  return true;
 }
 
-static bool TestMultiPrimeKey(int nprimes, const uint8_t *der, size_t der_size,
-                              const uint8_t *enc, size_t enc_size) {
-  ScopedRSA rsa(d2i_RSAPrivateKey(nullptr, &der, der_size));
-  if (!rsa) {
-    fprintf(stderr, "%d-prime key failed to parse.\n", nprimes);
-    ERR_print_errors_fp(stderr);
-    return false;
-  }
+INSTANTIATE_TEST_CASE_P(, RSAEncryptTest, testing::ValuesIn(kRSAEncryptParams));
 
-  if (!RSA_check_key(rsa.get())) {
-    fprintf(stderr, "RSA_check_key failed for %d-prime key.\n", nprimes);
-    ERR_print_errors_fp(stderr);
-    return false;
-  }
+struct RSAMultiPrimeParam {
+  const uint8_t *der;
+  size_t der_size;
+  const uint8_t *enc;
+  size_t enc_size;
+} kRSAMultiPrimeParams[] = {
+    {kTwoPrimeKey, sizeof(kTwoPrimeKey) - 1, kTwoPrimeEncryptedMessage,
+     sizeof(kTwoPrimeEncryptedMessage)},
+    {kThreePrimeKey, sizeof(kThreePrimeKey) - 1, kThreePrimeEncryptedMessage,
+     sizeof(kThreePrimeEncryptedMessage)},
+    {kSixPrimeKey, sizeof(kSixPrimeKey) - 1, kSixPrimeEncryptedMessage,
+     sizeof(kSixPrimeEncryptedMessage)},
+};
+
+class RSAMultiPrimeTest : public testing::TestWithParam<RSAMultiPrimeParam> {};
+
+TEST_P(RSAMultiPrimeTest, TestDecrypt) {
+  const auto &param = GetParam();
+  bssl::UniquePtr<RSA> rsa(
+      RSA_private_key_from_bytes(param.der, param.der_size));
+  ASSERT_TRUE(rsa);
+
+  EXPECT_TRUE(RSA_check_key(rsa.get()));
 
   uint8_t out[256];
   size_t out_len;
-  if (!RSA_decrypt(rsa.get(), &out_len, out, sizeof(out), enc, enc_size,
-                   RSA_PKCS1_PADDING) ||
-      out_len != 11 ||
-      memcmp(out, "hello world", 11) != 0) {
-    fprintf(stderr, "%d-prime key failed to decrypt.\n", nprimes);
-    ERR_print_errors_fp(stderr);
-    return false;
-  }
-
-  return true;
+  ASSERT_TRUE(RSA_decrypt(rsa.get(), &out_len, out, sizeof(out), param.enc,
+                          param.enc_size, RSA_PKCS1_PADDING));
+  EXPECT_EQ(Bytes("hello world"), Bytes(out, out_len));
 }
 
-static bool TestMultiPrimeKeygen() {
-  static const char kMessage[] = "Hello world.";
+INSTANTIATE_TEST_CASE_P(, RSAMultiPrimeTest,
+                        testing::ValuesIn(kRSAMultiPrimeParams));
+
+TEST(RSATest, MultiPrimeKeygen) {
+  bssl::UniquePtr<RSA> rsa(RSA_new());
+  bssl::UniquePtr<BIGNUM> e(BN_new());
+  ASSERT_TRUE(rsa);
+  ASSERT_TRUE(e);
+  ASSERT_TRUE(BN_set_word(e.get(), RSA_F4));
+
+  // Test key generation.
   static const size_t kBits = 1024;
+  ASSERT_TRUE(
+      RSA_generate_multi_prime_key(rsa.get(), kBits, 3, e.get(), nullptr));
+  ASSERT_TRUE(RSA_check_key(rsa.get()));
+
+  // Test the key round-trips.
+  static const char kMessage[] = "Hello world.";
   uint8_t encrypted[kBits / 8], decrypted[kBits / 8];
   size_t encrypted_len, decrypted_len;
-
-  ScopedRSA rsa(RSA_new());
-  ScopedBIGNUM e(BN_new());
-  if (!rsa || !e ||
-      !BN_set_word(e.get(), RSA_F4) ||
-      !RSA_generate_multi_prime_key(rsa.get(), kBits, 3, e.get(), nullptr) ||
-      !RSA_check_key(rsa.get()) ||
-      !RSA_encrypt(rsa.get(), &encrypted_len, encrypted, sizeof(encrypted),
-                   (const uint8_t *)kMessage, sizeof(kMessage),
-                   RSA_PKCS1_PADDING) ||
-      !RSA_decrypt(rsa.get(), &decrypted_len, decrypted, sizeof(decrypted),
-                   encrypted, encrypted_len, RSA_PKCS1_PADDING) ||
-      decrypted_len != sizeof(kMessage) ||
-      memcmp(decrypted, kMessage, sizeof(kMessage)) != 0) {
-    ERR_print_errors_fp(stderr);
-    return false;
-  }
-
-  return true;
+  ASSERT_TRUE(RSA_encrypt(rsa.get(), &encrypted_len, encrypted,
+                          sizeof(encrypted), (const uint8_t *)kMessage,
+                          sizeof(kMessage), RSA_PKCS1_PADDING));
+  ASSERT_TRUE(RSA_decrypt(rsa.get(), &decrypted_len, decrypted,
+                          sizeof(decrypted), encrypted, encrypted_len,
+                          RSA_PKCS1_PADDING));
+  EXPECT_EQ(Bytes((const uint8_t *)kMessage, sizeof(kMessage)),
+            Bytes(decrypted, decrypted_len));
 }
 
-static bool TestBadKey() {
-  ScopedRSA key(RSA_new());
-  ScopedBIGNUM e(BN_new());
+TEST(RSATest, BadKey) {
+  bssl::UniquePtr<RSA> key(RSA_new());
+  bssl::UniquePtr<BIGNUM> e(BN_new());
+  ASSERT_TRUE(key);
+  ASSERT_TRUE(e);
+  ASSERT_TRUE(BN_set_word(e.get(), RSA_F4));
 
-  if (!key || !e || !BN_set_word(e.get(), RSA_F4)) {
-    return false;
-  }
+  // Generate a bad key.
+  ASSERT_TRUE(RSA_generate_key_ex(key.get(), 512, e.get(), nullptr));
+  ASSERT_TRUE(BN_add(key->p, key->p, BN_value_one()));
 
-  if (!RSA_generate_key_ex(key.get(), 512, e.get(), nullptr)) {
-    fprintf(stderr, "RSA_generate_key_ex failed.\n");
-    ERR_print_errors_fp(stderr);
-    return false;
-  }
+  // Bad keys are detected.
+  EXPECT_FALSE(RSA_check_key(key.get()));
 
-  if (!BN_add(key->p, key->p, BN_value_one())) {
-    fprintf(stderr, "BN error.\n");
-    ERR_print_errors_fp(stderr);
-    return false;
-  }
-
-  if (RSA_check_key(key.get())) {
-    fprintf(stderr, "RSA_check_key passed with invalid key!\n");
-    return false;
-  }
-
-  ERR_clear_error();
-  return true;
+  // Bad keys may not be parsed.
+  uint8_t *der;
+  size_t der_len;
+  ASSERT_TRUE(RSA_private_key_to_bytes(&der, &der_len, key.get()));
+  bssl::UniquePtr<uint8_t> delete_der(der);
+  key.reset(RSA_private_key_from_bytes(der, der_len));
+  EXPECT_FALSE(key);
 }
 
-static bool TestOnlyDGiven() {
-  uint8_t buf[64];
-  unsigned buf_len = sizeof(buf);
-  ScopedRSA key(RSA_new());
-  if (!key ||
-      !BN_hex2bn(&key->n,
-                 "00e77bbf3889d4ef36a9a25d4d69f3f632eb4362214c74517da6d6aeaa9bd"
-                 "09ac42b26621cd88f3a6eb013772fc3bf9f83914b6467231c630202c35b3e"
-                 "5808c659") ||
-      !BN_hex2bn(&key->e, "010001") ||
-      !BN_hex2bn(&key->d,
-                 "0365db9eb6d73b53b015c40cd8db4de7dd7035c68b5ac1bf786d7a4ee2cea"
-                 "316eaeca21a73ac365e58713195f2ae9849348525ca855386b6d028e437a9"
-                 "495a01") ||
-      RSA_size(key.get()) > sizeof(buf)) {
-    return false;
-  }
+TEST(RSATest, OnlyDGiven) {
+  static const char kN[] =
+      "00e77bbf3889d4ef36a9a25d4d69f3f632eb4362214c74517da6d6aeaa9bd09ac42b2662"
+      "1cd88f3a6eb013772fc3bf9f83914b6467231c630202c35b3e5808c659";
+  static const char kE[] = "010001";
+  static const char kD[] =
+      "0365db9eb6d73b53b015c40cd8db4de7dd7035c68b5ac1bf786d7a4ee2cea316eaeca21a"
+      "73ac365e58713195f2ae9849348525ca855386b6d028e437a9495a01";
 
-  if (!RSA_check_key(key.get())) {
-    fprintf(stderr, "RSA_check_key failed with only d given.\n");
-    ERR_print_errors_fp(stderr);
-    return false;
-  }
+  bssl::UniquePtr<RSA> key(RSA_new());
+  ASSERT_TRUE(key);
+  ASSERT_TRUE(BN_hex2bn(&key->n, kN));
+  ASSERT_TRUE(BN_hex2bn(&key->e, kE));
+  ASSERT_TRUE(BN_hex2bn(&key->d, kD));
+
+  // Keys with only n, e, and d are functional.
+  EXPECT_TRUE(RSA_check_key(key.get()));
 
   const uint8_t kDummyHash[16] = {0};
+  uint8_t buf[64];
+  unsigned buf_len = sizeof(buf);
+  ASSERT_LE(RSA_size(key.get()), sizeof(buf));
+  EXPECT_TRUE(RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash), buf,
+                       &buf_len, key.get()));
+  EXPECT_TRUE(RSA_verify(NID_sha256, kDummyHash, sizeof(kDummyHash), buf,
+                         buf_len, key.get()));
 
-  if (!RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash), buf, &buf_len,
-                key.get())) {
-    fprintf(stderr, "RSA_sign failed with only d given.\n");
-    ERR_print_errors_fp(stderr);
-    return false;
-  }
+  // Keys without the public exponent must continue to work when blinding is
+  // disabled to support Java's RSAPrivateKeySpec API. See
+  // https://bugs.chromium.org/p/boringssl/issues/detail?id=12.
+  bssl::UniquePtr<RSA> key2(RSA_new());
+  ASSERT_TRUE(key2);
+  ASSERT_TRUE(BN_hex2bn(&key2->n, kN));
+  ASSERT_TRUE(BN_hex2bn(&key2->d, kD));
+  key2->flags |= RSA_FLAG_NO_BLINDING;
 
-  if (!RSA_verify(NID_sha256, kDummyHash, sizeof(kDummyHash), buf, buf_len,
-                  key.get())) {
-    fprintf(stderr, "RSA_verify failed with only d given.\n");
-    ERR_print_errors_fp(stderr);
-    return false;
-  }
+  ASSERT_LE(RSA_size(key2.get()), sizeof(buf));
+  EXPECT_TRUE(RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash), buf,
+                       &buf_len, key2.get()));
 
-  return true;
+  // Verify the signature with |key|. |key2| has no public exponent.
+  EXPECT_TRUE(RSA_verify(NID_sha256, kDummyHash, sizeof(kDummyHash), buf,
+                         buf_len, key.get()));
 }
 
-static bool TestRecoverCRTParams() {
-  ScopedBIGNUM e(BN_new());
-  if (!e || !BN_set_word(e.get(), RSA_F4)) {
-    return false;
-  }
+TEST(RSATest, RecoverCRTParams) {
+  bssl::UniquePtr<BIGNUM> e(BN_new());
+  ASSERT_TRUE(e);
+  ASSERT_TRUE(BN_set_word(e.get(), RSA_F4));
 
-  ERR_clear_error();
+  bssl::UniquePtr<RSA> key1(RSA_new());
+  ASSERT_TRUE(key1);
+  ASSERT_TRUE(RSA_generate_key_ex(key1.get(), 512, e.get(), nullptr));
 
-  for (unsigned i = 0; i < 1; i++) {
-    ScopedRSA key1(RSA_new());
-    if (!key1 ||
-        !RSA_generate_key_ex(key1.get(), 512, e.get(), nullptr)) {
-      fprintf(stderr, "RSA_generate_key_ex failed.\n");
-      ERR_print_errors_fp(stderr);
-      return false;
-    }
+  EXPECT_TRUE(RSA_check_key(key1.get()));
 
-    if (!RSA_check_key(key1.get())) {
-      fprintf(stderr, "RSA_check_key failed with original key.\n");
-      ERR_print_errors_fp(stderr);
-      return false;
-    }
+  // Create a copy of the key without CRT parameters.
+  bssl::UniquePtr<RSA> key2(RSA_new());
+  ASSERT_TRUE(key2);
+  key2->n = BN_dup(key1->n);
+  key2->e = BN_dup(key1->e);
+  key2->d = BN_dup(key1->d);
+  ASSERT_TRUE(key2->n);
+  ASSERT_TRUE(key2->e);
+  ASSERT_TRUE(key2->d);
 
-    ScopedRSA key2(RSA_new());
-    if (!key2) {
-      return false;
-    }
-    key2->n = BN_dup(key1->n);
-    key2->e = BN_dup(key1->e);
-    key2->d = BN_dup(key1->d);
-    if (key2->n == nullptr || key2->e == nullptr || key2->d == nullptr) {
-      return false;
-    }
+  ASSERT_TRUE(RSA_recover_crt_params(key2.get()));
 
-    if (!RSA_recover_crt_params(key2.get())) {
-      fprintf(stderr, "RSA_recover_crt_params failed.\n");
-      ERR_print_errors_fp(stderr);
-      return false;
-    }
+  // The recovered RSA parameters should work.
+  EXPECT_TRUE(RSA_check_key(key2.get()));
 
-    uint8_t buf[128];
-    unsigned buf_len = sizeof(buf);
-    if (RSA_size(key2.get()) > buf_len) {
-      return false;
-    }
+  uint8_t buf[128];
+  unsigned buf_len = sizeof(buf);
+  ASSERT_LE(RSA_size(key2.get()), buf_len);
 
-    if (!RSA_check_key(key2.get())) {
-      fprintf(stderr, "RSA_check_key failed with recovered key.\n");
-      ERR_print_errors_fp(stderr);
-      return false;
-    }
-
-    const uint8_t kDummyHash[16] = {0};
-    if (!RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash), buf, &buf_len,
-                  key2.get())) {
-      fprintf(stderr, "RSA_sign failed with recovered key.\n");
-      ERR_print_errors_fp(stderr);
-      return false;
-    }
-
-    if (!RSA_verify(NID_sha256, kDummyHash, sizeof(kDummyHash), buf, buf_len,
-                    key2.get())) {
-      fprintf(stderr, "RSA_verify failed with recovered key.\n");
-      ERR_print_errors_fp(stderr);
-      return false;
-    }
-  }
-
-  return true;
+  const uint8_t kDummyHash[16] = {0};
+  EXPECT_TRUE(RSA_sign(NID_sha256, kDummyHash, sizeof(kDummyHash), buf,
+                       &buf_len, key2.get()));
+  EXPECT_TRUE(RSA_verify(NID_sha256, kDummyHash, sizeof(kDummyHash), buf,
+                         buf_len, key2.get()));
 }
 
-static bool TestASN1() {
+TEST(RSATest, ASN1) {
   // Test that private keys may be decoded.
-  ScopedRSA rsa(RSA_private_key_from_bytes(kKey1, sizeof(kKey1) - 1));
-  if (!rsa) {
-    return false;
-  }
+  bssl::UniquePtr<RSA> rsa(
+      RSA_private_key_from_bytes(kKey1, sizeof(kKey1) - 1));
+  ASSERT_TRUE(rsa);
 
   // Test that the serialization round-trips.
   uint8_t *der;
   size_t der_len;
-  if (!RSA_private_key_to_bytes(&der, &der_len, rsa.get())) {
-    return false;
-  }
-  ScopedOpenSSLBytes delete_der(der);
-  if (der_len != sizeof(kKey1) - 1 || memcmp(der, kKey1, der_len) != 0) {
-    return false;
-  }
+  ASSERT_TRUE(RSA_private_key_to_bytes(&der, &der_len, rsa.get()));
+  bssl::UniquePtr<uint8_t> delete_der(der);
+  EXPECT_EQ(Bytes(kKey1, sizeof(kKey1) - 1), Bytes(der, der_len));
 
   // Test that serializing public keys works.
-  if (!RSA_public_key_to_bytes(&der, &der_len, rsa.get())) {
-    return false;
-  }
+  ASSERT_TRUE(RSA_public_key_to_bytes(&der, &der_len, rsa.get()));
   delete_der.reset(der);
 
   // Public keys may be parsed back out.
   rsa.reset(RSA_public_key_from_bytes(der, der_len));
-  if (!rsa || rsa->p != NULL || rsa->q != NULL) {
-    return false;
-  }
+  ASSERT_TRUE(rsa);
+  EXPECT_FALSE(rsa->p);
+  EXPECT_FALSE(rsa->q);
 
   // Serializing the result round-trips.
   uint8_t *der2;
   size_t der2_len;
-  if (!RSA_public_key_to_bytes(&der2, &der2_len, rsa.get())) {
-    return false;
-  }
-  ScopedOpenSSLBytes delete_der2(der2);
-  if (der_len != der2_len || memcmp(der, der2, der_len) != 0) {
-    return false;
-  }
+  ASSERT_TRUE(RSA_public_key_to_bytes(&der2, &der2_len, rsa.get()));
+  bssl::UniquePtr<uint8_t> delete_der2(der2);
+  EXPECT_EQ(Bytes(der, der_len), Bytes(der2, der2_len));
 
   // Public keys cannot be serialized as private keys.
-  if (RSA_private_key_to_bytes(&der, &der_len, rsa.get())) {
+  int ok = RSA_private_key_to_bytes(&der, &der_len, rsa.get());
+  if (ok) {
     OPENSSL_free(der);
-    return false;
   }
+  EXPECT_FALSE(ok);
   ERR_clear_error();
 
   // Public keys with negative moduli are invalid.
   rsa.reset(RSA_public_key_from_bytes(kEstonianRSAKey,
                                       sizeof(kEstonianRSAKey)));
-  if (rsa) {
-    return false;
-  }
+  EXPECT_FALSE(rsa);
   ERR_clear_error();
 
   // But |RSA_parse_public_key_buggy| will accept it.
   CBS cbs;
   CBS_init(&cbs, kEstonianRSAKey, sizeof(kEstonianRSAKey));
   rsa.reset(RSA_parse_public_key_buggy(&cbs));
-  if (!rsa || CBS_len(&cbs) != 0) {
-    return false;
-  }
-
-  return true;
+  EXPECT_TRUE(rsa);
+  EXPECT_EQ(0u, CBS_len(&cbs));
 }
 
-static bool TestBadExponent() {
-  ScopedRSA rsa(RSA_public_key_from_bytes(kExponent1RSAKey,
-                                          sizeof(kExponent1RSAKey)));
-
-  if (rsa) {
-    fprintf(stderr, "kExponent1RSAKey parsed but should have failed.\n");
-    return false;
-  }
-
+TEST(RSATest, BadExponent) {
+  bssl::UniquePtr<RSA> rsa(
+      RSA_public_key_from_bytes(kExponent1RSAKey, sizeof(kExponent1RSAKey)));
+  EXPECT_FALSE(rsa);
   ERR_clear_error();
-  return true;
-}
-
-int main(int argc, char *argv[]) {
-  CRYPTO_library_init();
-
-  if (!TestRSA(kKey1, sizeof(kKey1) - 1, kOAEPCiphertext1,
-               sizeof(kOAEPCiphertext1) - 1) ||
-      !TestRSA(kKey2, sizeof(kKey2) - 1, kOAEPCiphertext2,
-               sizeof(kOAEPCiphertext2) - 1) ||
-      !TestRSA(kKey3, sizeof(kKey3) - 1, kOAEPCiphertext3,
-               sizeof(kOAEPCiphertext3) - 1) ||
-      !TestOnlyDGiven() ||
-      !TestRecoverCRTParams() ||
-      !TestBadKey() ||
-      !TestMultiPrimeKey(2, kTwoPrimeKey, sizeof(kTwoPrimeKey) - 1,
-                            kTwoPrimeEncryptedMessage,
-                            sizeof(kTwoPrimeEncryptedMessage)) ||
-      !TestMultiPrimeKey(3, kThreePrimeKey, sizeof(kThreePrimeKey) - 1,
-                            kThreePrimeEncryptedMessage,
-                            sizeof(kThreePrimeEncryptedMessage)) ||
-      !TestMultiPrimeKey(6, kSixPrimeKey, sizeof(kSixPrimeKey) - 1,
-                            kSixPrimeEncryptedMessage,
-                            sizeof(kSixPrimeEncryptedMessage)) ||
-      !TestMultiPrimeKeygen() ||
-      !TestASN1() ||
-      !TestBadExponent()) {
-    return 1;
-  }
-
-  printf("PASS\n");
-  return 0;
 }
diff --git a/src/crypto/sha/CMakeLists.txt b/src/crypto/sha/CMakeLists.txt
index ecff09b..64c77db 100644
--- a/src/crypto/sha/CMakeLists.txt
+++ b/src/crypto/sha/CMakeLists.txt
@@ -45,6 +45,7 @@
 
   OBJECT
 
+  sha1-altivec.c
   sha1.c
   sha256.c
   sha512.c
@@ -53,8 +54,8 @@
 )
 
 perlasm(sha1-x86_64.${ASM_EXT} asm/sha1-x86_64.pl)
-perlasm(sha256-x86_64.${ASM_EXT} asm/sha512-x86_64.pl sha256)
-perlasm(sha512-x86_64.${ASM_EXT} asm/sha512-x86_64.pl sha512)
+perlasm(sha256-x86_64.${ASM_EXT} asm/sha512-x86_64.pl)
+perlasm(sha512-x86_64.${ASM_EXT} asm/sha512-x86_64.pl)
 perlasm(sha1-586.${ASM_EXT} asm/sha1-586.pl)
 perlasm(sha256-586.${ASM_EXT} asm/sha256-586.pl)
 perlasm(sha512-586.${ASM_EXT} asm/sha512-586.pl)
@@ -62,5 +63,5 @@
 perlasm(sha256-armv4.${ASM_EXT} asm/sha256-armv4.pl)
 perlasm(sha512-armv4.${ASM_EXT} asm/sha512-armv4.pl)
 perlasm(sha1-armv8.${ASM_EXT} asm/sha1-armv8.pl)
-perlasm(sha256-armv8.${ASM_EXT} asm/sha512-armv8.pl sha256)
-perlasm(sha512-armv8.${ASM_EXT} asm/sha512-armv8.pl sha512)
+perlasm(sha256-armv8.${ASM_EXT} asm/sha512-armv8.pl)
+perlasm(sha512-armv8.${ASM_EXT} asm/sha512-armv8.pl)
diff --git a/src/crypto/sha/asm/sha1-586.pl b/src/crypto/sha/asm/sha1-586.pl
index 3514273..acf383d 100644
--- a/src/crypto/sha/asm/sha1-586.pl
+++ b/src/crypto/sha/asm/sha1-586.pl
@@ -97,10 +97,12 @@
 # Sandy Bridge	8.8		6.2/+40%	5.1(**)/+73%
 # Ivy Bridge	7.2		4.8/+51%	4.7(**)/+53%
 # Haswell	6.5		4.3/+51%	4.1(**)/+58%
+# Skylake	6.4		4.1/+55%	4.1(**)/+55%
 # Bulldozer	11.6		6.0/+92%
 # VIA Nano	10.6		7.5/+41%
 # Atom		12.5		9.3(*)/+35%
 # Silvermont	14.5		9.9(*)/+46%
+# Goldmont	8.8		6.7/+30%	1.7(***)/+415%
 #
 # (*)	Loop is 1056 instructions long and expected result is ~8.25.
 #	The discrepancy is because of front-end limitations, so
@@ -108,11 +110,16 @@
 #	limited parallelism.
 #
 # (**)	As per above comment, the result is for AVX *plus* sh[rl]d.
+#
+# (***)	SHAEXT result
 
 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
 push(@INC,"${dir}","${dir}../../perlasm");
 require "x86asm.pl";
 
+$output=pop;
+open STDOUT,">$output";
+
 &asm_init($ARGV[0],"sha1-586.pl",$ARGV[$#ARGV] eq "386");
 
 $xmm=$ymm=0;
@@ -1469,3 +1476,5 @@
 &asciz("SHA1 block transform for x86, CRYPTOGAMS by <appro\@openssl.org>");
 
 &asm_finish();
+
+close STDOUT;
diff --git a/src/crypto/sha/asm/sha1-armv4-large.pl b/src/crypto/sha/asm/sha1-armv4-large.pl
index 64e2ed6..4fef524 100644
--- a/src/crypto/sha/asm/sha1-armv4-large.pl
+++ b/src/crypto/sha/asm/sha1-armv4-large.pl
@@ -69,8 +69,8 @@
 # Add ARMv8 code path performing at 2.35 cpb on Apple A7.
 
 $flavour = shift;
-if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
-else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} }
+if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
+else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} }
 
 if ($flavour && $flavour ne "void") {
     $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
diff --git a/src/crypto/sha/asm/sha1-x86_64.pl b/src/crypto/sha/asm/sha1-x86_64.pl
old mode 100644
new mode 100755
index 4895f92..9a13f6c
--- a/src/crypto/sha/asm/sha1-x86_64.pl
+++ b/src/crypto/sha/asm/sha1-x86_64.pl
@@ -73,13 +73,16 @@
 # Sandy Bridge	7.70		6.10/+26%	4.99/+54%
 # Ivy Bridge	6.06		4.67/+30%	4.60/+32%
 # Haswell	5.45		4.15/+31%	3.57/+53%
+# Skylake	5.18		4.06/+28%	3.54/+46%
 # Bulldozer	9.11		5.95/+53%
 # VIA Nano	9.32		7.15/+30%
 # Atom		10.3		9.17/+12%
 # Silvermont	13.1(*)		9.37/+40%
+# Goldmont	8.13		6.42/+27%	1.70/+380%(**)
 #
 # (*)	obviously suboptimal result, nothing was done about it,
 #	because SSSE3 code is compiled unconditionally;
+# (**)	SHAEXT result
 
 $flavour = shift;
 $output  = shift;
@@ -106,7 +109,7 @@
 $shaext=0;	### set to zero if compiling for 1.0.1
 $avx=1		if (!$shaext && $avx);
 
-open OUT,"| \"$^X\" $xlate $flavour $output";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
 *STDOUT=*OUT;
 
 $ctx="%rdi";	# 1st arg
@@ -246,7 +249,7 @@
 	jz	.Lialu
 ___
 $code.=<<___ if ($shaext);
-	test	\$`1<<29`,%r10d		# check SHA bit	
+	test	\$`1<<29`,%r10d		# check SHA bit
 	jnz	_shaext_shortcut
 ___
 $code.=<<___ if ($avx>1);
@@ -364,9 +367,9 @@
 .align	16
 .Loop_shaext:
 	dec		$num
-	lea		0x40($inp),%rax		# next input block
+	lea		0x40($inp),%r8		# next input block
 	paddd		@MSG[0],$E
-	cmovne		%rax,$inp
+	cmovne		%r8,$inp
 	movdqa		$ABCD,$ABCD_SAVE	# offload $ABCD
 ___
 for($i=0;$i<20-4;$i+=2) {
@@ -444,7 +447,8 @@
 my @T=("%esi","%edi");
 my $j=0;
 my $rx=0;
-my $K_XX_XX="%r11";
+my $K_XX_XX="%r14";
+my $fp="%r11";
 
 my $_rol=sub { &rol(@_) };
 my $_ror=sub { &ror(@_) };
@@ -465,7 +469,7 @@
 .align	16
 sha1_block_data_order_ssse3:
 _ssse3_shortcut:
-	mov	%rsp,%rax
+	mov	%rsp,$fp	# frame pointer
 	push	%rbx
 	push	%rbp
 	push	%r12
@@ -474,16 +478,15 @@
 	lea	`-64-($win64?6*16:0)`(%rsp),%rsp
 ___
 $code.=<<___ if ($win64);
-	movaps	%xmm6,-40-6*16(%rax)
-	movaps	%xmm7,-40-5*16(%rax)
-	movaps	%xmm8,-40-4*16(%rax)
-	movaps	%xmm9,-40-3*16(%rax)
-	movaps	%xmm10,-40-2*16(%rax)
-	movaps	%xmm11,-40-1*16(%rax)
+	movaps	%xmm6,-40-6*16($fp)
+	movaps	%xmm7,-40-5*16($fp)
+	movaps	%xmm8,-40-4*16($fp)
+	movaps	%xmm9,-40-3*16($fp)
+	movaps	%xmm10,-40-2*16($fp)
+	movaps	%xmm11,-40-1*16($fp)
 .Lprologue_ssse3:
 ___
 $code.=<<___;
-	mov	%rax,%r14	# original %rsp
 	and	\$-64,%rsp
 	mov	%rdi,$ctx	# reassigned argument
 	mov	%rsi,$inp	# reassigned argument
@@ -890,21 +893,20 @@
 	mov	$E,16($ctx)
 ___
 $code.=<<___ if ($win64);
-	movaps	-40-6*16(%r14),%xmm6
-	movaps	-40-5*16(%r14),%xmm7
-	movaps	-40-4*16(%r14),%xmm8
-	movaps	-40-3*16(%r14),%xmm9
-	movaps	-40-2*16(%r14),%xmm10
-	movaps	-40-1*16(%r14),%xmm11
+	movaps	-40-6*16($fp),%xmm6
+	movaps	-40-5*16($fp),%xmm7
+	movaps	-40-4*16($fp),%xmm8
+	movaps	-40-3*16($fp),%xmm9
+	movaps	-40-2*16($fp),%xmm10
+	movaps	-40-1*16($fp),%xmm11
 ___
 $code.=<<___;
-	lea	(%r14),%rsi
-	mov	-40(%rsi),%r14
-	mov	-32(%rsi),%r13
-	mov	-24(%rsi),%r12
-	mov	-16(%rsi),%rbp
-	mov	-8(%rsi),%rbx
-	lea	(%rsi),%rsp
+	mov	-40($fp),%r14
+	mov	-32($fp),%r13
+	mov	-24($fp),%r12
+	mov	-16($fp),%rbp
+	mov	-8($fp),%rbx
+	lea	($fp),%rsp
 .Lepilogue_ssse3:
 	ret
 .size	sha1_block_data_order_ssse3,.-sha1_block_data_order_ssse3
@@ -927,7 +929,7 @@
 .align	16
 sha1_block_data_order_avx:
 _avx_shortcut:
-	mov	%rsp,%rax
+	mov	%rsp,$fp
 	push	%rbx
 	push	%rbp
 	push	%r12
@@ -937,16 +939,15 @@
 	vzeroupper
 ___
 $code.=<<___ if ($win64);
-	vmovaps	%xmm6,-40-6*16(%rax)
-	vmovaps	%xmm7,-40-5*16(%rax)
-	vmovaps	%xmm8,-40-4*16(%rax)
-	vmovaps	%xmm9,-40-3*16(%rax)
-	vmovaps	%xmm10,-40-2*16(%rax)
-	vmovaps	%xmm11,-40-1*16(%rax)
+	vmovaps	%xmm6,-40-6*16($fp)
+	vmovaps	%xmm7,-40-5*16($fp)
+	vmovaps	%xmm8,-40-4*16($fp)
+	vmovaps	%xmm9,-40-3*16($fp)
+	vmovaps	%xmm10,-40-2*16($fp)
+	vmovaps	%xmm11,-40-1*16($fp)
 .Lprologue_avx:
 ___
 $code.=<<___;
-	mov	%rax,%r14	# original %rsp
 	and	\$-64,%rsp
 	mov	%rdi,$ctx	# reassigned argument
 	mov	%rsi,$inp	# reassigned argument
@@ -1254,21 +1255,20 @@
 	mov	$E,16($ctx)
 ___
 $code.=<<___ if ($win64);
-	movaps	-40-6*16(%r14),%xmm6
-	movaps	-40-5*16(%r14),%xmm7
-	movaps	-40-4*16(%r14),%xmm8
-	movaps	-40-3*16(%r14),%xmm9
-	movaps	-40-2*16(%r14),%xmm10
-	movaps	-40-1*16(%r14),%xmm11
+	movaps	-40-6*16($fp),%xmm6
+	movaps	-40-5*16($fp),%xmm7
+	movaps	-40-4*16($fp),%xmm8
+	movaps	-40-3*16($fp),%xmm9
+	movaps	-40-2*16($fp),%xmm10
+	movaps	-40-1*16($fp),%xmm11
 ___
 $code.=<<___;
-	lea	(%r14),%rsi
-	mov	-40(%rsi),%r14
-	mov	-32(%rsi),%r13
-	mov	-24(%rsi),%r12
-	mov	-16(%rsi),%rbp
-	mov	-8(%rsi),%rbx
-	lea	(%rsi),%rsp
+	mov	-40($fp),%r14
+	mov	-32($fp),%r13
+	mov	-24($fp),%r12
+	mov	-16($fp),%rbp
+	mov	-8($fp),%rbx
+	lea	($fp),%rsp
 .Lepilogue_avx:
 	ret
 .size	sha1_block_data_order_avx,.-sha1_block_data_order_avx
@@ -1294,7 +1294,7 @@
 .align	16
 sha1_block_data_order_avx2:
 _avx2_shortcut:
-	mov	%rsp,%rax
+	mov	%rsp,$fp
 	push	%rbx
 	push	%rbp
 	push	%r12
@@ -1304,16 +1304,15 @@
 ___
 $code.=<<___ if ($win64);
 	lea	-6*16(%rsp),%rsp
-	vmovaps	%xmm6,-40-6*16(%rax)
-	vmovaps	%xmm7,-40-5*16(%rax)
-	vmovaps	%xmm8,-40-4*16(%rax)
-	vmovaps	%xmm9,-40-3*16(%rax)
-	vmovaps	%xmm10,-40-2*16(%rax)
-	vmovaps	%xmm11,-40-1*16(%rax)
+	vmovaps	%xmm6,-40-6*16($fp)
+	vmovaps	%xmm7,-40-5*16($fp)
+	vmovaps	%xmm8,-40-4*16($fp)
+	vmovaps	%xmm9,-40-3*16($fp)
+	vmovaps	%xmm10,-40-2*16($fp)
+	vmovaps	%xmm11,-40-1*16($fp)
 .Lprologue_avx2:
 ___
 $code.=<<___;
-	mov	%rax,%r14		# original %rsp
 	mov	%rdi,$ctx		# reassigned argument
 	mov	%rsi,$inp		# reassigned argument
 	mov	%rdx,$num		# reassigned argument
@@ -1733,21 +1732,20 @@
 	vzeroupper
 ___
 $code.=<<___ if ($win64);
-	movaps	-40-6*16(%r14),%xmm6
-	movaps	-40-5*16(%r14),%xmm7
-	movaps	-40-4*16(%r14),%xmm8
-	movaps	-40-3*16(%r14),%xmm9
-	movaps	-40-2*16(%r14),%xmm10
-	movaps	-40-1*16(%r14),%xmm11
+	movaps	-40-6*16($fp),%xmm6
+	movaps	-40-5*16($fp),%xmm7
+	movaps	-40-4*16($fp),%xmm8
+	movaps	-40-3*16($fp),%xmm9
+	movaps	-40-2*16($fp),%xmm10
+	movaps	-40-1*16($fp),%xmm11
 ___
 $code.=<<___;
-	lea	(%r14),%rsi
-	mov	-40(%rsi),%r14
-	mov	-32(%rsi),%r13
-	mov	-24(%rsi),%r12
-	mov	-16(%rsi),%rbp
-	mov	-8(%rsi),%rbx
-	lea	(%rsi),%rsp
+	mov	-40($fp),%r14
+	mov	-32($fp),%r13
+	mov	-24($fp),%r12
+	mov	-16($fp),%rbp
+	mov	-8($fp),%rbx
+	lea	($fp),%rsp
 .Lepilogue_avx2:
 	ret
 .size	sha1_block_data_order_avx2,.-sha1_block_data_order_avx2
@@ -1890,15 +1888,13 @@
 	cmp	%r10,%rbx		# context->Rip<prologue label
 	jb	.Lcommon_seh_tail
 
-	mov	152($context),%rax	# pull context->Rsp
+	mov	208($context),%rax	# pull context->R11
 
 	mov	4(%r11),%r10d		# HandlerData[1]
 	lea	(%rsi,%r10),%r10	# epilogue label
 	cmp	%r10,%rbx		# context->Rip>=epilogue label
 	jae	.Lcommon_seh_tail
 
-	mov	232($context),%rax	# pull context->R14
-
 	lea	-40-6*16(%rax),%rsi
 	lea	512($context),%rdi	# &context.Xmm6
 	mov	\$12,%ecx
diff --git a/src/crypto/sha/asm/sha256-586.pl b/src/crypto/sha/asm/sha256-586.pl
index fa8f264..d85004c 100644
--- a/src/crypto/sha/asm/sha256-586.pl
+++ b/src/crypto/sha/asm/sha256-586.pl
@@ -40,7 +40,7 @@
 #
 # Performance in clock cycles per processed byte (less is better):
 #
-#		gcc	icc	x86 asm(*)	SIMD	x86_64 asm(**)	
+#		gcc	icc	x86 asm(*)	SIMD	x86_64 asm(**)
 # Pentium	46	57	40/38		-	-
 # PIII		36	33	27/24		-	-
 # P4		41	38	28		-	17.3
@@ -50,19 +50,25 @@
 # Sandy Bridge	25	-	15.9		12.4	11.6
 # Ivy Bridge	24	-	15.0		11.4	10.3
 # Haswell	22	-	13.9		9.46	7.80
+# Skylake	20	-	14.9		9.50	7.70
 # Bulldozer	36	-	27/22		17.0	13.6
 # VIA Nano	36	-	25/22		16.8	16.5
 # Atom		50	-	30/25		21.9	18.9
 # Silvermont	40	-	34/31		22.9	20.6
+# Goldmont	29	-	20		16.3(***)
 #
 # (*)	numbers after slash are for unrolled loop, where applicable;
 # (**)	x86_64 assembly performance is presented for reference
 #	purposes, results are best-available;
+# (***)	SHAEXT result is 4.1, strangely enough better than 64-bit one;
 
 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
 push(@INC,"${dir}","${dir}../../perlasm");
 require "x86asm.pl";
 
+$output=pop;
+open STDOUT,">$output";
+
 &asm_init($ARGV[0],"sha512-586.pl",$ARGV[$#ARGV] eq "386");
 
 $xmm=$avx=0;
@@ -260,7 +266,7 @@
 	&mov	($Coff,"ecx");
 	&mov	($Doff,"edi");
 	&mov	(&DWP(0,"esp"),"ebx");	# magic
-	&mov	($E,&DWP(16,"esi"));	
+	&mov	($E,&DWP(16,"esi"));
 	&mov	("ebx",&DWP(20,"esi"));
 	&mov	("ecx",&DWP(24,"esi"));
 	&mov	("edi",&DWP(28,"esi"));
@@ -369,7 +375,7 @@
 	&xor	($AH[1],"ecx");		# magic
 	&mov	(&DWP(8,"esp"),"ecx");
 	&mov	(&DWP(12,"esp"),"ebx");
-	&mov	($E,&DWP(16,"esi"));	
+	&mov	($E,&DWP(16,"esi"));
 	&mov	("ebx",&DWP(20,"esi"));
 	&mov	("ecx",&DWP(24,"esi"));
 	&mov	("esi",&DWP(28,"esi"));
@@ -1273,3 +1279,5 @@
 &function_end_B("sha256_block_data_order");
 
 &asm_finish();
+
+close STDOUT;
diff --git a/src/crypto/sha/asm/sha256-armv4.pl b/src/crypto/sha/asm/sha256-armv4.pl
index 7e07147..bac7ce8 100644
--- a/src/crypto/sha/asm/sha256-armv4.pl
+++ b/src/crypto/sha/asm/sha256-armv4.pl
@@ -1,4 +1,11 @@
-#!/usr/bin/env perl
+#! /usr/bin/env perl
+# Copyright 2007-2016 The OpenSSL Project Authors. All Rights Reserved.
+#
+# Licensed under the OpenSSL license (the "License").  You may not use
+# this file except in compliance with the License.  You can obtain a copy
+# in the file LICENSE in the source distribution or at
+# https://www.openssl.org/source/license.html
+
 
 # ====================================================================
 # Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
@@ -38,8 +45,8 @@
 # Add ARMv8 code path performing at 2.0 cpb on Apple A7.
 
 $flavour = shift;
-if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
-else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} }
+if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
+else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} }
 
 if ($flavour && $flavour ne "void") {
     $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
@@ -175,16 +182,11 @@
 #endif
 
 .text
-#if __ARM_ARCH__<7
-.code	32
-#else
+#if defined(__thumb2__)
 .syntax unified
-# if defined(__thumb2__) && !defined(__APPLE__)
-#  define adrl adr
 .thumb
-# else
+#else
 .code   32
-# endif
 #endif
 
 .type	K256,%object
@@ -218,10 +220,10 @@
 .type	sha256_block_data_order,%function
 sha256_block_data_order:
 .Lsha256_block_data_order:
-#if __ARM_ARCH__<7
+#if __ARM_ARCH__<7 && !defined(__thumb2__)
 	sub	r3,pc,#8		@ sha256_block_data_order
 #else
-	adr	r3,sha256_block_data_order
+	adr	r3,.Lsha256_block_data_order
 #endif
 #if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
 	ldr	r12,.LOPENSSL_armcap
@@ -473,13 +475,14 @@
 
 .global	sha256_block_data_order_neon
 .type	sha256_block_data_order_neon,%function
-.align	4
+.align	5
+.skip	16
 sha256_block_data_order_neon:
 .LNEON:
 	stmdb	sp!,{r4-r12,lr}
 
 	sub	$H,sp,#16*4+16
-	adrl	$Ktbl,K256
+	adr	$Ktbl,K256
 	bic	$H,$H,#15		@ align for 128-bit stores
 	mov	$t2,sp
 	mov	sp,$H			@ alloca
@@ -599,7 +602,7 @@
 $code.=<<___;
 #if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__)
 
-# if defined(__thumb2__) && !defined(__APPLE__)
+# if defined(__thumb2__)
 #  define INST(a,b,c,d)	.byte	c,d|0xc,a,b
 # else
 #  define INST(a,b,c,d)	.byte	a,b,c,d
@@ -610,16 +613,11 @@
 sha256_block_data_order_armv8:
 .LARMv8:
 	vld1.32	{$ABCD,$EFGH},[$ctx]
-# ifdef	__APPLE__
 	sub	$Ktbl,$Ktbl,#256+32
-# elif	defined(__thumb2__)
-	adr	$Ktbl,.LARMv8
-	sub	$Ktbl,$Ktbl,#.LARMv8-K256
-# else
-	adrl	$Ktbl,K256
-# endif
 	add	$len,$inp,$len,lsl#6	@ len to point at the end of inp
+	b	.Loop_v8
 
+.align	4
 .Loop_v8:
 	vld1.8		{@MSG[0]-@MSG[1]},[$inp]!
 	vld1.8		{@MSG[2]-@MSG[3]},[$inp]!
diff --git a/src/crypto/sha/asm/sha512-586.pl b/src/crypto/sha/asm/sha512-586.pl
index 2f6a202..6d909ed 100644
--- a/src/crypto/sha/asm/sha512-586.pl
+++ b/src/crypto/sha/asm/sha512-586.pl
@@ -25,10 +25,12 @@
 # Sandy Bridge	58	-	35	11.9	11.2
 # Ivy Bridge	50	-	33	11.5	8.17
 # Haswell	46	-	29	11.3	7.66
+# Skylake	40	-	26	13.3	7.25
 # Bulldozer	121	-	50	14.0	13.5
 # VIA Nano	91	-	52	33	14.7
 # Atom		126	-	68	48(***)	14.7
 # Silvermont	97	-	58	42(***)	17.5
+# Goldmont	80	-	48	19.5	12.0
 #
 # (*)	whichever best applicable.
 # (**)	x86_64 assembler performance is presented for reference
@@ -50,6 +52,9 @@
 push(@INC,"${dir}","${dir}../../perlasm");
 require "x86asm.pl";
 
+$output=pop;
+open STDOUT,">$output";
+
 &asm_init($ARGV[0],"sha512-586.pl",$ARGV[$#ARGV] eq "386");
 
 $sse2=0;
@@ -373,7 +378,7 @@
 
 &set_label("16_79_sse2",16);
     for ($j=0;$j<2;$j++) {			# 2x unroll
-	#&movq	("mm7",&QWP(8*(9+16-1),"esp"));	# prefetched in BODY_00_15 
+	#&movq	("mm7",&QWP(8*(9+16-1),"esp"));	# prefetched in BODY_00_15
 	&movq	("mm5",&QWP(8*(9+16-14),"esp"));
 	&movq	("mm1","mm7");
 	&psrlq	("mm7",1);
@@ -909,3 +914,5 @@
 &asciz("SHA512 block transform for x86, CRYPTOGAMS by <appro\@openssl.org>");
 
 &asm_finish();
+
+close STDOUT;
diff --git a/src/crypto/sha/asm/sha512-armv4.pl b/src/crypto/sha/asm/sha512-armv4.pl
index cd3662a..0320c16 100644
--- a/src/crypto/sha/asm/sha512-armv4.pl
+++ b/src/crypto/sha/asm/sha512-armv4.pl
@@ -51,8 +51,8 @@
 # ====================================================================
 
 $flavour = shift;
-if ($flavour=~/^\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
-else { while (($output=shift) && ($output!~/^\w[\w\-]*\.\w+$/)) {} }
+if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
+else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} }
 
 if ($flavour && $flavour ne "void") {
     $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
@@ -291,7 +291,7 @@
 #ifdef	__APPLE__
 	ldr	r12,[r12]
 #endif
-	tst	r12,#1
+	tst	r12,#ARMV7_NEON
 	bne	.LNEON
 #endif
 	add	$len,$inp,$len,lsl#7	@ len to point at the end of inp
diff --git a/src/crypto/sha/asm/sha512-armv8.pl b/src/crypto/sha/asm/sha512-armv8.pl
index 40eb17a..494e633 100644
--- a/src/crypto/sha/asm/sha512-armv8.pl
+++ b/src/crypto/sha/asm/sha512-armv8.pl
@@ -18,7 +18,7 @@
 # Cortex-A57	2.31		11.6 (+86%)	7.51 (+260%(***))
 # Denver	2.01		10.5 (+26%)	6.70 (+8%)
 # X-Gene			20.0 (+100%)	12.8 (+300%(***))
-# 
+#
 # (*)	Software SHA256 results are of lesser relevance, presented
 #	mostly for informational purposes.
 # (**)	The result is a trade-off: it's possible to improve it by
@@ -30,10 +30,6 @@
 #	and the gap is only 40-90%.
 
 $flavour=shift;
-# Unlike most perlasm files, sha512-armv8.pl takes an additional argument to
-# determine which hash function to emit. This differs from upstream OpenSSL so
-# that the script may continue to output to stdout.
-$variant=shift;
 $output=shift;
 
 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
@@ -44,7 +40,7 @@
 open OUT,"| \"$^X\" $xlate $flavour $output";
 *STDOUT=*OUT;
 
-if ($variant eq "sha512") {
+if ($output =~ /512/) {
 	$BITS=512;
 	$SZ=8;
 	@Sigma0=(28,34,39);
@@ -53,7 +49,7 @@
 	@sigma1=(19,61, 6);
 	$rounds=80;
 	$reg_t="x";
-} elsif ($variant eq "sha256") {
+} else {
 	$BITS=256;
 	$SZ=4;
 	@Sigma0=( 2,13,22);
@@ -62,8 +58,6 @@
 	@sigma1=(17,19,10);
 	$rounds=64;
 	$reg_t="w";
-} else {
-  die "Unknown variant: $variant";
 }
 
 $func="sha${BITS}_block_data_order";
diff --git a/src/crypto/sha/asm/sha512-x86_64.pl b/src/crypto/sha/asm/sha512-x86_64.pl
old mode 100644
new mode 100755
index 2bc33c6..5716791
--- a/src/crypto/sha/asm/sha512-x86_64.pl
+++ b/src/crypto/sha/asm/sha512-x86_64.pl
@@ -34,7 +34,7 @@
 # level parallelism, on a given CPU implementation in this case.
 #
 # Special note on Intel EM64T. While Opteron CPU exhibits perfect
-# perfromance ratio of 1.5 between 64- and 32-bit flavors [see above],
+# performance ratio of 1.5 between 64- and 32-bit flavors [see above],
 # [currently available] EM64T CPUs apparently are far from it. On the
 # contrary, 64-bit version, sha512_block, is ~30% *slower* than 32-bit
 # sha256_block:-( This is presumably because 64-bit shifts/rotates
@@ -86,12 +86,14 @@
 # Sandy Bridge	17.4	14.2(+23%)  11.6(+50%(**))  11.2    8.10(+38%(**))
 # Ivy Bridge	12.6	10.5(+20%)  10.3(+22%)	    8.17    7.22(+13%)
 # Haswell	12.2	9.28(+31%)  7.80(+56%)	    7.66    5.40(+42%)
+# Skylake	11.4	9.03(+26%)  7.70(+48%)      7.25    5.20(+40%)
 # Bulldozer	21.1	13.6(+54%)  13.6(+54%(***)) 13.5    8.58(+57%)
 # VIA Nano	23.0	16.5(+39%)  -		    14.7    -
 # Atom		23.0	18.9(+22%)  -		    14.7    -
 # Silvermont	27.4	20.6(+33%)  -               17.5    -
+# Goldmont	18.9	14.3(+32%)  4.16(+350%)     12.0    -
 #
-# (*)	whichever best applicable;
+# (*)	whichever best applicable, including SHAEXT;
 # (**)	switch from ror to shrd stands for fair share of improvement;
 # (***)	execution time is fully determined by remaining integer-only
 #	part, body_00_15; reducing the amount of SIMD instructions
@@ -123,7 +125,7 @@
 $shaext=0;	### set to zero if compiling for 1.0.1
 $avx=1		if (!$shaext && $avx);
 
-open OUT,"| \"$^X\" $xlate $flavour";
+open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
 *STDOUT=*OUT;
 
 if ($output =~ /512/) {
@@ -284,13 +286,13 @@
 	jnz	.Lssse3_shortcut
 ___
 $code.=<<___;
+	mov	%rsp,%rax		# copy %rsp
 	push	%rbx
 	push	%rbp
 	push	%r12
 	push	%r13
 	push	%r14
 	push	%r15
-	mov	%rsp,%r11		# copy %rsp
 	shl	\$4,%rdx		# num*16
 	sub	\$$framesz,%rsp
 	lea	($inp,%rdx,$SZ),%rdx	# inp+num*16*$SZ
@@ -298,7 +300,7 @@
 	mov	$ctx,$_ctx		# save ctx, 1st arg
 	mov	$inp,$_inp		# save inp, 2nd arh
 	mov	%rdx,$_end		# save end pointer, "3rd" arg
-	mov	%r11,$_rsp		# save copy of %rsp
+	mov	%rax,$_rsp		# save copy of %rsp
 .Lprologue:
 
 	mov	$SZ*0($ctx),$A
@@ -365,13 +367,13 @@
 	jb	.Lloop
 
 	mov	$_rsp,%rsi
-	mov	(%rsi),%r15
-	mov	8(%rsi),%r14
-	mov	16(%rsi),%r13
-	mov	24(%rsi),%r12
-	mov	32(%rsi),%rbp
-	mov	40(%rsi),%rbx
-	lea	48(%rsi),%rsp
+	mov	-48(%rsi),%r15
+	mov	-40(%rsi),%r14
+	mov	-32(%rsi),%r13
+	mov	-24(%rsi),%r12
+	mov	-16(%rsi),%rbp
+	mov	-8(%rsi),%rbx
+	lea	(%rsi),%rsp
 .Lepilogue:
 	ret
 .size	$func,.-$func
@@ -744,13 +746,13 @@
 .align	64
 ${func}_ssse3:
 .Lssse3_shortcut:
+	mov	%rsp,%rax		# copy %rsp
 	push	%rbx
 	push	%rbp
 	push	%r12
 	push	%r13
 	push	%r14
 	push	%r15
-	mov	%rsp,%r11		# copy %rsp
 	shl	\$4,%rdx		# num*16
 	sub	\$`$framesz+$win64*16*4`,%rsp
 	lea	($inp,%rdx,$SZ),%rdx	# inp+num*16*$SZ
@@ -758,7 +760,7 @@
 	mov	$ctx,$_ctx		# save ctx, 1st arg
 	mov	$inp,$_inp		# save inp, 2nd arh
 	mov	%rdx,$_end		# save end pointer, "3rd" arg
-	mov	%r11,$_rsp		# save copy of %rsp
+	mov	%rax,$_rsp		# save copy of %rsp
 ___
 $code.=<<___ if ($win64);
 	movaps	%xmm6,16*$SZ+32(%rsp)
@@ -1065,13 +1067,13 @@
 	movaps	16*$SZ+80(%rsp),%xmm9
 ___
 $code.=<<___;
-	mov	(%rsi),%r15
-	mov	8(%rsi),%r14
-	mov	16(%rsi),%r13
-	mov	24(%rsi),%r12
-	mov	32(%rsi),%rbp
-	mov	40(%rsi),%rbx
-	lea	48(%rsi),%rsp
+	mov	-48(%rsi),%r15
+	mov	-40(%rsi),%r14
+	mov	-32(%rsi),%r13
+	mov	-24(%rsi),%r12
+	mov	-16(%rsi),%rbp
+	mov	-8(%rsi),%rbx
+	lea	(%rsi),%rsp
 .Lepilogue_ssse3:
 	ret
 .size	${func}_ssse3,.-${func}_ssse3
@@ -1088,13 +1090,13 @@
 .align	64
 ${func}_xop:
 .Lxop_shortcut:
+	mov	%rsp,%rax		# copy %rsp
 	push	%rbx
 	push	%rbp
 	push	%r12
 	push	%r13
 	push	%r14
 	push	%r15
-	mov	%rsp,%r11		# copy %rsp
 	shl	\$4,%rdx		# num*16
 	sub	\$`$framesz+$win64*16*($SZ==4?4:6)`,%rsp
 	lea	($inp,%rdx,$SZ),%rdx	# inp+num*16*$SZ
@@ -1102,7 +1104,7 @@
 	mov	$ctx,$_ctx		# save ctx, 1st arg
 	mov	$inp,$_inp		# save inp, 2nd arh
 	mov	%rdx,$_end		# save end pointer, "3rd" arg
-	mov	%r11,$_rsp		# save copy of %rsp
+	mov	%rax,$_rsp		# save copy of %rsp
 ___
 $code.=<<___ if ($win64);
 	movaps	%xmm6,16*$SZ+32(%rsp)
@@ -1442,13 +1444,13 @@
 	movaps	16*$SZ+112(%rsp),%xmm11
 ___
 $code.=<<___;
-	mov	(%rsi),%r15
-	mov	8(%rsi),%r14
-	mov	16(%rsi),%r13
-	mov	24(%rsi),%r12
-	mov	32(%rsi),%rbp
-	mov	40(%rsi),%rbx
-	lea	48(%rsi),%rsp
+	mov	-48(%rsi),%r15
+	mov	-40(%rsi),%r14
+	mov	-32(%rsi),%r13
+	mov	-24(%rsi),%r12
+	mov	-16(%rsi),%rbp
+	mov	-8(%rsi),%rbx
+	lea	(%rsi),%rsp
 .Lepilogue_xop:
 	ret
 .size	${func}_xop,.-${func}_xop
@@ -1464,13 +1466,13 @@
 .align	64
 ${func}_avx:
 .Lavx_shortcut:
+	mov	%rsp,%rax		# copy %rsp
 	push	%rbx
 	push	%rbp
 	push	%r12
 	push	%r13
 	push	%r14
 	push	%r15
-	mov	%rsp,%r11		# copy %rsp
 	shl	\$4,%rdx		# num*16
 	sub	\$`$framesz+$win64*16*($SZ==4?4:6)`,%rsp
 	lea	($inp,%rdx,$SZ),%rdx	# inp+num*16*$SZ
@@ -1478,7 +1480,7 @@
 	mov	$ctx,$_ctx		# save ctx, 1st arg
 	mov	$inp,$_inp		# save inp, 2nd arh
 	mov	%rdx,$_end		# save end pointer, "3rd" arg
-	mov	%r11,$_rsp		# save copy of %rsp
+	mov	%rax,$_rsp		# save copy of %rsp
 ___
 $code.=<<___ if ($win64);
 	movaps	%xmm6,16*$SZ+32(%rsp)
@@ -1750,13 +1752,13 @@
 	movaps	16*$SZ+112(%rsp),%xmm11
 ___
 $code.=<<___;
-	mov	(%rsi),%r15
-	mov	8(%rsi),%r14
-	mov	16(%rsi),%r13
-	mov	24(%rsi),%r12
-	mov	32(%rsi),%rbp
-	mov	40(%rsi),%rbx
-	lea	48(%rsi),%rsp
+	mov	-48(%rsi),%r15
+	mov	-40(%rsi),%r14
+	mov	-32(%rsi),%r13
+	mov	-24(%rsi),%r12
+	mov	-16(%rsi),%rbp
+	mov	-8(%rsi),%rbx
+	lea	(%rsi),%rsp
 .Lepilogue_avx:
 	ret
 .size	${func}_avx,.-${func}_avx
@@ -1766,7 +1768,7 @@
 ######################################################################
 # AVX2+BMI code path
 #
-my $a5=$SZ==4?"%esi":"%rsi";	# zap $inp 
+my $a5=$SZ==4?"%esi":"%rsi";	# zap $inp
 my $PUSH8=8*2*$SZ;
 use integer;
 
@@ -1815,13 +1817,13 @@
 .align	64
 ${func}_avx2:
 .Lavx2_shortcut:
+	mov	%rsp,%rax		# copy %rsp
 	push	%rbx
 	push	%rbp
 	push	%r12
 	push	%r13
 	push	%r14
 	push	%r15
-	mov	%rsp,%r11		# copy %rsp
 	sub	\$`2*$SZ*$rounds+4*8+$win64*16*($SZ==4?4:6)`,%rsp
 	shl	\$4,%rdx		# num*16
 	and	\$-256*$SZ,%rsp		# align stack frame
@@ -1830,7 +1832,7 @@
 	mov	$ctx,$_ctx		# save ctx, 1st arg
 	mov	$inp,$_inp		# save inp, 2nd arh
 	mov	%rdx,$_end		# save end pointer, "3rd" arg
-	mov	%r11,$_rsp		# save copy of %rsp
+	mov	%rax,$_rsp		# save copy of %rsp
 ___
 $code.=<<___ if ($win64);
 	movaps	%xmm6,16*$SZ+32(%rsp)
@@ -2124,13 +2126,13 @@
 	movaps	16*$SZ+112(%rsp),%xmm11
 ___
 $code.=<<___;
-	mov	(%rsi),%r15
-	mov	8(%rsi),%r14
-	mov	16(%rsi),%r13
-	mov	24(%rsi),%r12
-	mov	32(%rsi),%rbp
-	mov	40(%rsi),%rbx
-	lea	48(%rsi),%rsp
+	mov	-48(%rsi),%r15
+	mov	-40(%rsi),%r14
+	mov	-32(%rsi),%r13
+	mov	-24(%rsi),%r12
+	mov	-16(%rsi),%rbp
+	mov	-8(%rsi),%rbx
+	lea	(%rsi),%rsp
 .Lepilogue_avx2:
 	ret
 .size	${func}_avx2,.-${func}_avx2
@@ -2192,7 +2194,6 @@
 $code.=<<___;
 	mov	%rax,%rsi		# put aside Rsp
 	mov	16*$SZ+3*8(%rax),%rax	# pull $_rsp
-	lea	48(%rax),%rax
 
 	mov	-8(%rax),%rbx
 	mov	-16(%rax),%rbp
diff --git a/src/crypto/sha/sha1-altivec.c b/src/crypto/sha/sha1-altivec.c
new file mode 100644
index 0000000..500986e
--- /dev/null
+++ b/src/crypto/sha/sha1-altivec.c
@@ -0,0 +1,346 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+/* Altivec-optimized SHA1 in C. This is tested on ppc64le only.
+ *
+ * References:
+ * https://software.intel.com/en-us/articles/improving-the-performance-of-the-secure-hash-algorithm-1
+ * http://arctic.org/~dean/crypto/sha1.html
+ *
+ * This code used the generic SHA-1 from OpenSSL as a basis and AltiVec
+ * optimisations were added on top. */
+
+#include <openssl/sha.h>
+
+#if defined(OPENSSL_PPC64LE)
+
+#include <altivec.h>
+
+void sha1_block_data_order(uint32_t *state, const uint8_t *data, size_t num);
+
+static uint32_t rotate(uint32_t a, int n) { return (a << n) | (a >> (32 - n)); }
+
+typedef vector unsigned int vec_uint32_t;
+typedef vector unsigned char vec_uint8_t;
+
+/* Vector constants */
+static const vec_uint8_t k_swap_endianness = {3,  2,  1, 0, 7,  6,  5,  4,
+                                              11, 10, 9, 8, 15, 14, 13, 12};
+
+/* Shift amounts for byte and bit shifts and rotations */
+static const vec_uint8_t k_4_bytes = {32, 32, 32, 32, 32, 32, 32, 32,
+                                      32, 32, 32, 32, 32, 32, 32, 32};
+static const vec_uint8_t k_12_bytes = {96, 96, 96, 96, 96, 96, 96, 96,
+                                       96, 96, 96, 96, 96, 96, 96, 96};
+
+#define K_00_19 0x5a827999UL
+#define K_20_39 0x6ed9eba1UL
+#define K_40_59 0x8f1bbcdcUL
+#define K_60_79 0xca62c1d6UL
+
+/* Vector versions of the above. */
+static const vec_uint32_t K_00_19_x_4 = {K_00_19, K_00_19, K_00_19, K_00_19};
+static const vec_uint32_t K_20_39_x_4 = {K_20_39, K_20_39, K_20_39, K_20_39};
+static const vec_uint32_t K_40_59_x_4 = {K_40_59, K_40_59, K_40_59, K_40_59};
+static const vec_uint32_t K_60_79_x_4 = {K_60_79, K_60_79, K_60_79, K_60_79};
+
+/* vector message scheduling: compute message schedule for round i..i+3 where i
+ * is divisible by 4. We return the schedule w[i..i+3] as a vector. In
+ * addition, we also precompute sum w[i..+3] and an additive constant K. This
+ * is done to offload some computation of f() in the integer execution units.
+ *
+ * Byte shifting code below may not be correct for big-endian systems. */
+static vec_uint32_t sched_00_15(vec_uint32_t *pre_added, const void *data,
+                                vec_uint32_t k) {
+  const vec_uint32_t v = *((const vec_uint32_t *)data);
+  const vec_uint32_t w = vec_perm(v, v, k_swap_endianness);
+  vec_st(w + k, 0, pre_added);
+  return w;
+}
+
+/* Compute w[i..i+3] using these steps for i in [16, 20, 24, 28]
+ *
+ * w'[i  ]  = (w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16]) <<< 1
+ * w'[i+1]  = (w[i-2] ^ w[i-7] ^ w[i-13] ^ w[i-15]) <<< 1
+ * w'[i+2]  = (w[i-1] ^ w[i-6] ^ w[i-12] ^ w[i-14]) <<< 1
+ * w'[i+3]  = (     0 ^ w[i-5] ^ w[i-11] ^ w[i-13]) <<< 1
+ *
+ * w[  i] = w'[  i]
+ * w[i+1] = w'[i+1]
+ * w[i+2] = w'[i+2]
+ * w[i+3] = w'[i+3] ^ (w'[i] <<< 1) */
+static vec_uint32_t sched_16_31(vec_uint32_t *pre_added, vec_uint32_t minus_4,
+                                vec_uint32_t minus_8, vec_uint32_t minus_12,
+                                vec_uint32_t minus_16, vec_uint32_t k) {
+  const vec_uint32_t minus_3 = vec_sro(minus_4, k_4_bytes);
+  const vec_uint32_t minus_14 = vec_sld((minus_12), (minus_16), 8);
+  const vec_uint32_t k_1_bit = vec_splat_u32(1);
+  const vec_uint32_t w_prime =
+      vec_rl(minus_3 ^ minus_8 ^ minus_14 ^ minus_16, k_1_bit);
+  const vec_uint32_t w =
+      w_prime ^ vec_rl(vec_slo(w_prime, k_12_bytes), k_1_bit);
+  vec_st(w + k, 0, pre_added);
+  return w;
+}
+
+/* Compute w[i..i+3] using this relation for i in [32, 36, 40 ... 76]
+ * w[i] = (w[i-6] ^ w[i-16] ^ w[i-28] ^ w[i-32]), 2) <<< 2 */
+static vec_uint32_t sched_32_79(vec_uint32_t *pre_added, vec_uint32_t minus_4,
+                                vec_uint32_t minus_8, vec_uint32_t minus_16,
+                                vec_uint32_t minus_28, vec_uint32_t minus_32,
+                                vec_uint32_t k) {
+  const vec_uint32_t minus_6 = vec_sld(minus_4, minus_8, 8);
+  const vec_uint32_t k_2_bits = vec_splat_u32(2);
+  const vec_uint32_t w =
+      vec_rl(minus_6 ^ minus_16 ^ minus_28 ^ minus_32, k_2_bits);
+  vec_st(w + k, 0, pre_added);
+  return w;
+}
+
+/* As pointed out by Wei Dai <weidai@eskimo.com>, F() below can be simplified
+ * to the code in F_00_19. Wei attributes these optimisations to Peter
+ * Gutmann's SHS code, and he attributes it to Rich Schroeppel. #define
+ * F(x,y,z) (((x) & (y))  |  ((~(x)) & (z))) I've just become aware of another
+ * tweak to be made, again from Wei Dai, in F_40_59, (x&a)|(y&a) -> (x|y)&a */
+#define F_00_19(b, c, d) ((((c) ^ (d)) & (b)) ^ (d))
+#define F_20_39(b, c, d) ((b) ^ (c) ^ (d))
+#define F_40_59(b, c, d) (((b) & (c)) | (((b) | (c)) & (d)))
+#define F_60_79(b, c, d) F_20_39(b, c, d)
+
+/* We pre-added the K constants during message scheduling. */
+#define BODY_00_19(i, a, b, c, d, e, f)                         \
+  do {                                                          \
+    (f) = w[i] + (e) + rotate((a), 5) + F_00_19((b), (c), (d)); \
+    (b) = rotate((b), 30);                                      \
+  } while (0)
+
+#define BODY_20_39(i, a, b, c, d, e, f)                         \
+  do {                                                          \
+    (f) = w[i] + (e) + rotate((a), 5) + F_20_39((b), (c), (d)); \
+    (b) = rotate((b), 30);                                      \
+  } while (0)
+
+#define BODY_40_59(i, a, b, c, d, e, f)                         \
+  do {                                                          \
+    (f) = w[i] + (e) + rotate((a), 5) + F_40_59((b), (c), (d)); \
+    (b) = rotate((b), 30);                                      \
+  } while (0)
+
+#define BODY_60_79(i, a, b, c, d, e, f)                         \
+  do {                                                          \
+    (f) = w[i] + (e) + rotate((a), 5) + F_60_79((b), (c), (d)); \
+    (b) = rotate((b), 30);                                      \
+  } while (0)
+
+void sha1_block_data_order(uint32_t *state, const uint8_t *data, size_t num) {
+  uint32_t A, B, C, D, E, T;
+
+  A = state[0];
+  B = state[1];
+  C = state[2];
+  D = state[3];
+  E = state[4];
+
+  for (;;) {
+    vec_uint32_t vw[20];
+    const uint32_t *w = (const uint32_t *)&vw;
+
+    vec_uint32_t k = K_00_19_x_4;
+    const vec_uint32_t w0 = sched_00_15(vw + 0, data + 0, k);
+    BODY_00_19(0, A, B, C, D, E, T);
+    BODY_00_19(1, T, A, B, C, D, E);
+    BODY_00_19(2, E, T, A, B, C, D);
+    BODY_00_19(3, D, E, T, A, B, C);
+
+    const vec_uint32_t w4 = sched_00_15(vw + 1, data + 16, k);
+    BODY_00_19(4, C, D, E, T, A, B);
+    BODY_00_19(5, B, C, D, E, T, A);
+    BODY_00_19(6, A, B, C, D, E, T);
+    BODY_00_19(7, T, A, B, C, D, E);
+
+    const vec_uint32_t w8 = sched_00_15(vw + 2, data + 32, k);
+    BODY_00_19(8, E, T, A, B, C, D);
+    BODY_00_19(9, D, E, T, A, B, C);
+    BODY_00_19(10, C, D, E, T, A, B);
+    BODY_00_19(11, B, C, D, E, T, A);
+
+    const vec_uint32_t w12 = sched_00_15(vw + 3, data + 48, k);
+    BODY_00_19(12, A, B, C, D, E, T);
+    BODY_00_19(13, T, A, B, C, D, E);
+    BODY_00_19(14, E, T, A, B, C, D);
+    BODY_00_19(15, D, E, T, A, B, C);
+
+    const vec_uint32_t w16 = sched_16_31(vw + 4, w12, w8, w4, w0, k);
+    BODY_00_19(16, C, D, E, T, A, B);
+    BODY_00_19(17, B, C, D, E, T, A);
+    BODY_00_19(18, A, B, C, D, E, T);
+    BODY_00_19(19, T, A, B, C, D, E);
+
+    k = K_20_39_x_4;
+    const vec_uint32_t w20 = sched_16_31(vw + 5, w16, w12, w8, w4, k);
+    BODY_20_39(20, E, T, A, B, C, D);
+    BODY_20_39(21, D, E, T, A, B, C);
+    BODY_20_39(22, C, D, E, T, A, B);
+    BODY_20_39(23, B, C, D, E, T, A);
+
+    const vec_uint32_t w24 = sched_16_31(vw + 6, w20, w16, w12, w8, k);
+    BODY_20_39(24, A, B, C, D, E, T);
+    BODY_20_39(25, T, A, B, C, D, E);
+    BODY_20_39(26, E, T, A, B, C, D);
+    BODY_20_39(27, D, E, T, A, B, C);
+
+    const vec_uint32_t w28 = sched_16_31(vw + 7, w24, w20, w16, w12, k);
+    BODY_20_39(28, C, D, E, T, A, B);
+    BODY_20_39(29, B, C, D, E, T, A);
+    BODY_20_39(30, A, B, C, D, E, T);
+    BODY_20_39(31, T, A, B, C, D, E);
+
+    const vec_uint32_t w32 = sched_32_79(vw + 8, w28, w24, w16, w4, w0, k);
+    BODY_20_39(32, E, T, A, B, C, D);
+    BODY_20_39(33, D, E, T, A, B, C);
+    BODY_20_39(34, C, D, E, T, A, B);
+    BODY_20_39(35, B, C, D, E, T, A);
+
+    const vec_uint32_t w36 = sched_32_79(vw + 9, w32, w28, w20, w8, w4, k);
+    BODY_20_39(36, A, B, C, D, E, T);
+    BODY_20_39(37, T, A, B, C, D, E);
+    BODY_20_39(38, E, T, A, B, C, D);
+    BODY_20_39(39, D, E, T, A, B, C);
+
+    k = K_40_59_x_4;
+    const vec_uint32_t w40 = sched_32_79(vw + 10, w36, w32, w24, w12, w8, k);
+    BODY_40_59(40, C, D, E, T, A, B);
+    BODY_40_59(41, B, C, D, E, T, A);
+    BODY_40_59(42, A, B, C, D, E, T);
+    BODY_40_59(43, T, A, B, C, D, E);
+
+    const vec_uint32_t w44 = sched_32_79(vw + 11, w40, w36, w28, w16, w12, k);
+    BODY_40_59(44, E, T, A, B, C, D);
+    BODY_40_59(45, D, E, T, A, B, C);
+    BODY_40_59(46, C, D, E, T, A, B);
+    BODY_40_59(47, B, C, D, E, T, A);
+
+    const vec_uint32_t w48 = sched_32_79(vw + 12, w44, w40, w32, w20, w16, k);
+    BODY_40_59(48, A, B, C, D, E, T);
+    BODY_40_59(49, T, A, B, C, D, E);
+    BODY_40_59(50, E, T, A, B, C, D);
+    BODY_40_59(51, D, E, T, A, B, C);
+
+    const vec_uint32_t w52 = sched_32_79(vw + 13, w48, w44, w36, w24, w20, k);
+    BODY_40_59(52, C, D, E, T, A, B);
+    BODY_40_59(53, B, C, D, E, T, A);
+    BODY_40_59(54, A, B, C, D, E, T);
+    BODY_40_59(55, T, A, B, C, D, E);
+
+    const vec_uint32_t w56 = sched_32_79(vw + 14, w52, w48, w40, w28, w24, k);
+    BODY_40_59(56, E, T, A, B, C, D);
+    BODY_40_59(57, D, E, T, A, B, C);
+    BODY_40_59(58, C, D, E, T, A, B);
+    BODY_40_59(59, B, C, D, E, T, A);
+
+    k = K_60_79_x_4;
+    const vec_uint32_t w60 = sched_32_79(vw + 15, w56, w52, w44, w32, w28, k);
+    BODY_60_79(60, A, B, C, D, E, T);
+    BODY_60_79(61, T, A, B, C, D, E);
+    BODY_60_79(62, E, T, A, B, C, D);
+    BODY_60_79(63, D, E, T, A, B, C);
+
+    const vec_uint32_t w64 = sched_32_79(vw + 16, w60, w56, w48, w36, w32, k);
+    BODY_60_79(64, C, D, E, T, A, B);
+    BODY_60_79(65, B, C, D, E, T, A);
+    BODY_60_79(66, A, B, C, D, E, T);
+    BODY_60_79(67, T, A, B, C, D, E);
+
+    const vec_uint32_t w68 = sched_32_79(vw + 17, w64, w60, w52, w40, w36, k);
+    BODY_60_79(68, E, T, A, B, C, D);
+    BODY_60_79(69, D, E, T, A, B, C);
+    BODY_60_79(70, C, D, E, T, A, B);
+    BODY_60_79(71, B, C, D, E, T, A);
+
+    const vec_uint32_t w72 = sched_32_79(vw + 18, w68, w64, w56, w44, w40, k);
+    BODY_60_79(72, A, B, C, D, E, T);
+    BODY_60_79(73, T, A, B, C, D, E);
+    BODY_60_79(74, E, T, A, B, C, D);
+    BODY_60_79(75, D, E, T, A, B, C);
+
+    /* We don't use the last value */
+    (void)sched_32_79(vw + 19, w72, w68, w60, w48, w44, k);
+    BODY_60_79(76, C, D, E, T, A, B);
+    BODY_60_79(77, B, C, D, E, T, A);
+    BODY_60_79(78, A, B, C, D, E, T);
+    BODY_60_79(79, T, A, B, C, D, E);
+
+    const uint32_t mask = 0xffffffffUL;
+    state[0] = (state[0] + E) & mask;
+    state[1] = (state[1] + T) & mask;
+    state[2] = (state[2] + A) & mask;
+    state[3] = (state[3] + B) & mask;
+    state[4] = (state[4] + C) & mask;
+
+    data += 64;
+    if (--num == 0) {
+      break;
+    }
+
+    A = state[0];
+    B = state[1];
+    C = state[2];
+    D = state[3];
+    E = state[4];
+  }
+}
+
+#endif  /* OPENSSL_PPC64LE */
diff --git a/src/crypto/sha/sha1.c b/src/crypto/sha/sha1.c
index 74e841c..7c72713 100644
--- a/src/crypto/sha/sha1.c
+++ b/src/crypto/sha/sha1.c
@@ -60,15 +60,18 @@
 
 #include <openssl/mem.h>
 
+#include "../internal.h"
+
 
 #if !defined(OPENSSL_NO_ASM) &&                         \
     (defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \
-     defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64))
+     defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64) || \
+     defined(OPENSSL_PPC64LE))
 #define SHA1_ASM
 #endif
 
 int SHA1_Init(SHA_CTX *sha) {
-  memset(sha, 0, sizeof(SHA_CTX));
+  OPENSSL_memset(sha, 0, sizeof(SHA_CTX));
   sha->h[0] = 0x67452301UL;
   sha->h[1] = 0xefcdab89UL;
   sha->h[2] = 0x98badcfeUL;
@@ -119,7 +122,10 @@
 #define HASH_BLOCK_DATA_ORDER sha1_block_data_order
 #define ROTATE(a, n) (((a) << (n)) | ((a) >> (32 - (n))))
 #define Xupdate(a, ix, ia, ib, ic, id) \
-  ((a) = (ia ^ ib ^ ic ^ id), ix = (a) = ROTATE((a), 1))
+  do {                                 \
+    (a) = ((ia) ^ (ib) ^ (ic) ^ (id)); \
+    (ix) = (a) = ROTATE((a), 1);       \
+  } while (0)
 
 #ifndef SHA1_ASM
 static
@@ -143,34 +149,46 @@
 #define F_40_59(b, c, d) (((b) & (c)) | (((b) | (c)) & (d)))
 #define F_60_79(b, c, d) F_20_39(b, c, d)
 
-#define BODY_00_15(i, a, b, c, d, e, f, xi)                           \
-  (f) = xi + (e) + K_00_19 + ROTATE((a), 5) + F_00_19((b), (c), (d)); \
-  (b) = ROTATE((b), 30);
+#define BODY_00_15(i, a, b, c, d, e, f, xi)                               \
+  do {                                                                    \
+    (f) = (xi) + (e) + K_00_19 + ROTATE((a), 5) + F_00_19((b), (c), (d)); \
+    (b) = ROTATE((b), 30);                                                \
+  } while (0)
 
-#define BODY_16_19(i, a, b, c, d, e, f, xi, xa, xb, xc, xd)       \
-  Xupdate(f, xi, xa, xb, xc, xd);                                 \
-  (f) += (e) + K_00_19 + ROTATE((a), 5) + F_00_19((b), (c), (d)); \
-  (b) = ROTATE((b), 30);
+#define BODY_16_19(i, a, b, c, d, e, f, xi, xa, xb, xc, xd)         \
+  do {                                                              \
+    Xupdate(f, xi, xa, xb, xc, xd);                                 \
+    (f) += (e) + K_00_19 + ROTATE((a), 5) + F_00_19((b), (c), (d)); \
+    (b) = ROTATE((b), 30);                                          \
+  } while (0)
 
-#define BODY_20_31(i, a, b, c, d, e, f, xi, xa, xb, xc, xd)       \
-  Xupdate(f, xi, xa, xb, xc, xd);                                 \
-  (f) += (e) + K_20_39 + ROTATE((a), 5) + F_20_39((b), (c), (d)); \
-  (b) = ROTATE((b), 30);
+#define BODY_20_31(i, a, b, c, d, e, f, xi, xa, xb, xc, xd)         \
+  do {                                                              \
+    Xupdate(f, xi, xa, xb, xc, xd);                                 \
+    (f) += (e) + K_20_39 + ROTATE((a), 5) + F_20_39((b), (c), (d)); \
+    (b) = ROTATE((b), 30);                                          \
+  } while (0)
 
-#define BODY_32_39(i, a, b, c, d, e, f, xa, xb, xc, xd)           \
-  Xupdate(f, xa, xa, xb, xc, xd);                                 \
-  (f) += (e) + K_20_39 + ROTATE((a), 5) + F_20_39((b), (c), (d)); \
-  (b) = ROTATE((b), 30);
+#define BODY_32_39(i, a, b, c, d, e, f, xa, xb, xc, xd)             \
+  do {                                                              \
+    Xupdate(f, xa, xa, xb, xc, xd);                                 \
+    (f) += (e) + K_20_39 + ROTATE((a), 5) + F_20_39((b), (c), (d)); \
+    (b) = ROTATE((b), 30);                                          \
+  } while (0)
 
-#define BODY_40_59(i, a, b, c, d, e, f, xa, xb, xc, xd)           \
-  Xupdate(f, xa, xa, xb, xc, xd);                                 \
-  (f) += (e) + K_40_59 + ROTATE((a), 5) + F_40_59((b), (c), (d)); \
-  (b) = ROTATE((b), 30);
+#define BODY_40_59(i, a, b, c, d, e, f, xa, xb, xc, xd)             \
+  do {                                                              \
+    Xupdate(f, xa, xa, xb, xc, xd);                                 \
+    (f) += (e) + K_40_59 + ROTATE((a), 5) + F_40_59((b), (c), (d)); \
+    (b) = ROTATE((b), 30);                                          \
+  } while (0)
 
-#define BODY_60_79(i, a, b, c, d, e, f, xa, xb, xc, xd)               \
-  Xupdate(f, xa, xa, xb, xc, xd);                                     \
-  (f) = xa + (e) + K_60_79 + ROTATE((a), 5) + F_60_79((b), (c), (d)); \
-  (b) = ROTATE((b), 30);
+#define BODY_60_79(i, a, b, c, d, e, f, xa, xb, xc, xd)                   \
+  do {                                                                    \
+    Xupdate(f, xa, xa, xb, xc, xd);                                       \
+    (f) = (xa) + (e) + K_60_79 + ROTATE((a), 5) + F_60_79((b), (c), (d)); \
+    (b) = ROTATE((b), 30);                                                \
+  } while (0)
 
 #ifdef X
 #undef X
@@ -199,51 +217,51 @@
   E = state[4];
 
   for (;;) {
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(0) = l;
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(1) = l;
     BODY_00_15(0, A, B, C, D, E, T, X(0));
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(2) = l;
     BODY_00_15(1, T, A, B, C, D, E, X(1));
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(3) = l;
     BODY_00_15(2, E, T, A, B, C, D, X(2));
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(4) = l;
     BODY_00_15(3, D, E, T, A, B, C, X(3));
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(5) = l;
     BODY_00_15(4, C, D, E, T, A, B, X(4));
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(6) = l;
     BODY_00_15(5, B, C, D, E, T, A, X(5));
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(7) = l;
     BODY_00_15(6, A, B, C, D, E, T, X(6));
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(8) = l;
     BODY_00_15(7, T, A, B, C, D, E, X(7));
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(9) = l;
     BODY_00_15(8, E, T, A, B, C, D, X(8));
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(10) = l;
     BODY_00_15(9, D, E, T, A, B, C, X(9));
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(11) = l;
     BODY_00_15(10, C, D, E, T, A, B, X(10));
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(12) = l;
     BODY_00_15(11, B, C, D, E, T, A, X(11));
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(13) = l;
     BODY_00_15(12, A, B, C, D, E, T, X(12));
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(14) = l;
     BODY_00_15(13, T, A, B, C, D, E, X(13));
-    (void)HOST_c2l(data, l);
+    HOST_c2l(data, l);
     X(15) = l;
     BODY_00_15(14, E, T, A, B, C, D, X(14));
     BODY_00_15(15, D, E, T, A, B, C, X(15));
diff --git a/src/crypto/sha/sha256.c b/src/crypto/sha/sha256.c
index 0ddacba..fb950d7 100644
--- a/src/crypto/sha/sha256.c
+++ b/src/crypto/sha/sha256.c
@@ -60,6 +60,8 @@
 
 #include <openssl/mem.h>
 
+#include "../internal.h"
+
 
 #if !defined(OPENSSL_NO_ASM) &&                         \
     (defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \
@@ -68,7 +70,7 @@
 #endif
 
 int SHA224_Init(SHA256_CTX *sha) {
-  memset(sha, 0, sizeof(SHA256_CTX));
+  OPENSSL_memset(sha, 0, sizeof(SHA256_CTX));
   sha->h[0] = 0xc1059ed8UL;
   sha->h[1] = 0x367cd507UL;
   sha->h[2] = 0x3070dd17UL;
@@ -82,7 +84,7 @@
 }
 
 int SHA256_Init(SHA256_CTX *sha) {
-  memset(sha, 0, sizeof(SHA256_CTX));
+  OPENSSL_memset(sha, 0, sizeof(SHA256_CTX));
   sha->h[0] = 0x6a09e667UL;
   sha->h[1] = 0xbb67ae85UL;
   sha->h[2] = 0x3c6ef372UL;
@@ -104,8 +106,8 @@
     out = buf;
   }
   SHA224_Init(&ctx);
-  SHA256_Update(&ctx, data, len);
-  SHA256_Final(out, &ctx);
+  SHA224_Update(&ctx, data, len);
+  SHA224_Final(out, &ctx);
   OPENSSL_cleanse(&ctx, sizeof(ctx));
   return out;
 }
diff --git a/src/crypto/sha/sha512.c b/src/crypto/sha/sha512.c
index 6ad8d40..8761150 100644
--- a/src/crypto/sha/sha512.c
+++ b/src/crypto/sha/sha512.c
@@ -60,6 +60,8 @@
 
 #include <openssl/mem.h>
 
+#include "../internal.h"
+
 
 /* IMPLEMENTATION NOTES.
  *
@@ -129,8 +131,8 @@
   }
 
   SHA384_Init(&ctx);
-  SHA512_Update(&ctx, data, len);
-  SHA512_Final(out, &ctx);
+  SHA384_Update(&ctx, data, len);
+  SHA384_Final(out, &ctx);
   OPENSSL_cleanse(&ctx, sizeof(ctx));
   return out;
 }
@@ -164,14 +166,14 @@
   return SHA512_Update(sha, data, len);
 }
 
-void SHA512_Transform(SHA512_CTX *c, const uint8_t *data) {
+void SHA512_Transform(SHA512_CTX *c, const uint8_t *block) {
 #ifndef SHA512_BLOCK_CAN_MANAGE_UNALIGNED_DATA
-  if ((size_t)data % sizeof(c->u.d[0]) != 0) {
-    memcpy(c->u.p, data, sizeof(c->u.p));
-    data = c->u.p;
+  if ((size_t)block % sizeof(c->u.d[0]) != 0) {
+    OPENSSL_memcpy(c->u.p, block, sizeof(c->u.p));
+    block = c->u.p;
   }
 #endif
-  sha512_block_data_order(c->h, (uint64_t *)data, 1);
+  sha512_block_data_order(c->h, (uint64_t *)block, 1);
 }
 
 int SHA512_Update(SHA512_CTX *c, const void *in_data, size_t len) {
@@ -196,11 +198,11 @@
     size_t n = sizeof(c->u) - c->num;
 
     if (len < n) {
-      memcpy(p + c->num, data, len);
+      OPENSSL_memcpy(p + c->num, data, len);
       c->num += (unsigned int)len;
       return 1;
     } else {
-      memcpy(p + c->num, data, n), c->num = 0;
+      OPENSSL_memcpy(p + c->num, data, n), c->num = 0;
       len -= n;
       data += n;
       sha512_block_data_order(c->h, (uint64_t *)p, 1);
@@ -211,7 +213,7 @@
 #ifndef SHA512_BLOCK_CAN_MANAGE_UNALIGNED_DATA
     if ((size_t)data % sizeof(c->u.d[0]) != 0) {
       while (len >= sizeof(c->u)) {
-        memcpy(p, data, sizeof(c->u));
+        OPENSSL_memcpy(p, data, sizeof(c->u));
         sha512_block_data_order(c->h, (uint64_t *)p, 1);
         len -= sizeof(c->u);
         data += sizeof(c->u);
@@ -227,7 +229,7 @@
   }
 
   if (len != 0) {
-    memcpy(p, data, len);
+    OPENSSL_memcpy(p, data, len);
     c->num = (int)len;
   }
 
@@ -241,12 +243,12 @@
   p[n] = 0x80; /* There always is a room for one */
   n++;
   if (n > (sizeof(sha->u) - 16)) {
-    memset(p + n, 0, sizeof(sha->u) - n);
+    OPENSSL_memset(p + n, 0, sizeof(sha->u) - n);
     n = 0;
     sha512_block_data_order(sha->h, (uint64_t *)p, 1);
   }
 
-  memset(p + n, 0, sizeof(sha->u) - 16 - n);
+  OPENSSL_memset(p + n, 0, sizeof(sha->u) - 16 - n);
   p[sizeof(sha->u) - 1] = (uint8_t)(sha->Nl);
   p[sizeof(sha->u) - 2] = (uint8_t)(sha->Nl >> 8);
   p[sizeof(sha->u) - 3] = (uint8_t)(sha->Nl >> 16);
diff --git a/src/crypto/stack/make_macros.sh b/src/crypto/stack/make_macros.sh
index 4837e44..3c3691b 100644
--- a/src/crypto/stack/make_macros.sh
+++ b/src/crypto/stack/make_macros.sh
@@ -36,13 +36,13 @@
   ((STACK_OF(${type})*) sk_new_null())
 
 #define sk_${type}_num(sk)\\
-  sk_num(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk))
+  sk_num(CHECKED_CAST(const _STACK*, const STACK_OF(${type})*, sk))
 
 #define sk_${type}_zero(sk)\\
   sk_zero(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk));
 
 #define sk_${type}_value(sk, i)\\
-  ((${ptrtype}) sk_value(CHECKED_CAST(_STACK*, const STACK_OF(${type})*, sk), (i)))
+  ((${ptrtype}) sk_value(CHECKED_CAST(const _STACK*, const STACK_OF(${type})*, sk), (i)))
 
 #define sk_${type}_set(sk, i, p)\\
   ((${ptrtype}) sk_set(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk), (i), CHECKED_CAST(void*, ${ptrtype}, p)))
@@ -75,13 +75,13 @@
   ((${ptrtype}) sk_pop(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk)))
 
 #define sk_${type}_dup(sk)\\
-  ((STACK_OF(${type})*) sk_dup(CHECKED_CAST(_STACK*, const STACK_OF(${type})*, sk)))
+  ((STACK_OF(${type})*) sk_dup(CHECKED_CAST(const _STACK*, const STACK_OF(${type})*, sk)))
 
 #define sk_${type}_sort(sk)\\
   sk_sort(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk))
 
 #define sk_${type}_is_sorted(sk)\\
-  sk_is_sorted(CHECKED_CAST(_STACK*, const STACK_OF(${type})*, sk))
+  sk_is_sorted(CHECKED_CAST(const _STACK*, const STACK_OF(${type})*, sk))
 
 #define sk_${type}_set_cmp_func(sk, comp)\\
   ((int (*) (const ${type} **a, const ${type} **b)) sk_set_cmp_func(CHECKED_CAST(_STACK*, STACK_OF(${type})*, sk), CHECKED_CAST(stack_cmp_func, int (*) (const ${type} **a, const ${type} **b), comp)))
@@ -89,7 +89,6 @@
 #define sk_${type}_deep_copy(sk, copy_func, free_func)\\
 ((STACK_OF(${type})*) sk_deep_copy(CHECKED_CAST(const _STACK*, const STACK_OF(${type})*, sk), CHECKED_CAST(void* (*) (void*), ${ptrtype} (*) (${ptrtype}), copy_func), CHECKED_CAST(void (*) (void*), void (*) (${ptrtype}), free_func)))
 
-
 EOF
 }
 
diff --git a/src/crypto/stack/stack.c b/src/crypto/stack/stack.c
index c584515..f78209d 100644
--- a/src/crypto/stack/stack.c
+++ b/src/crypto/stack/stack.c
@@ -60,6 +60,9 @@
 
 #include <openssl/mem.h>
 
+#include "../internal.h"
+
+
 /* kMinSize is the number of pointers that will be initially allocated in a new
  * stack. */
 static const size_t kMinSize = 4;
@@ -71,14 +74,14 @@
   if (ret == NULL) {
     goto err;
   }
-  memset(ret, 0, sizeof(_STACK));
+  OPENSSL_memset(ret, 0, sizeof(_STACK));
 
   ret->data = OPENSSL_malloc(sizeof(void *) * kMinSize);
   if (ret->data == NULL) {
     goto err;
   }
 
-  memset(ret->data, 0, sizeof(void *) * kMinSize);
+  OPENSSL_memset(ret->data, 0, sizeof(void *) * kMinSize);
 
   ret->comp = comp;
   ret->num_alloc = kMinSize;
@@ -103,7 +106,7 @@
   if (sk == NULL || sk->num == 0) {
     return;
   }
-  memset(sk->data, 0, sizeof(void*) * sk->num);
+  OPENSSL_memset(sk->data, 0, sizeof(void*) * sk->num);
   sk->num = 0;
   sk->sorted = 0;
 }
@@ -131,13 +134,11 @@
 }
 
 void sk_pop_free(_STACK *sk, void (*func)(void *)) {
-  size_t i;
-
   if (sk == NULL) {
     return;
   }
 
-  for (i = 0; i < sk->num; i++) {
+  for (size_t i = 0; i < sk->num; i++) {
     if (sk->data[i] != NULL) {
       func(sk->data[i]);
     }
@@ -179,8 +180,8 @@
   if (where >= sk->num) {
     sk->data[sk->num] = p;
   } else {
-    memmove(&sk->data[where + 1], &sk->data[where],
-            sizeof(void *) * (sk->num - where));
+    OPENSSL_memmove(&sk->data[where + 1], &sk->data[where],
+                    sizeof(void *) * (sk->num - where));
     sk->data[where] = p;
   }
 
@@ -200,7 +201,7 @@
   ret = sk->data[where];
 
   if (where != sk->num - 1) {
-    memmove(&sk->data[where], &sk->data[where + 1],
+    OPENSSL_memmove(&sk->data[where], &sk->data[where + 1],
             sizeof(void *) * (sk->num - where - 1));
   }
 
@@ -209,13 +210,11 @@
 }
 
 void *sk_delete_ptr(_STACK *sk, void *p) {
-  size_t i;
-
   if (sk == NULL) {
     return NULL;
   }
 
-  for (i = 0; i < sk->num; i++) {
+  for (size_t i = 0; i < sk->num; i++) {
     if (sk->data[i] == p) {
       return sk_delete(sk, i);
     }
@@ -225,17 +224,13 @@
 }
 
 int sk_find(_STACK *sk, size_t *out_index, void *p) {
-  const void *const *r;
-  size_t i;
-  int (*comp_func)(const void *,const void *);
-
   if (sk == NULL) {
     return 0;
   }
 
   if (sk->comp == NULL) {
     /* Use pointer equality when no comparison function has been set. */
-    for (i = 0; i < sk->num; i++) {
+    for (size_t i = 0; i < sk->num; i++) {
       if (sk->data[i] == p) {
         if (out_index) {
           *out_index = i;
@@ -257,18 +252,19 @@
    * elements. However, since we're passing an array of pointers to
    * qsort/bsearch, we can just cast the comparison function and everything
    * works. */
-  comp_func=(int (*)(const void *,const void *))(sk->comp);
-  r = bsearch(&p, sk->data, sk->num, sizeof(void *), comp_func);
+  const void *const *r = bsearch(&p, sk->data, sk->num, sizeof(void *),
+                                 (int (*)(const void *, const void *))sk->comp);
   if (r == NULL) {
     return 0;
   }
-  i = ((void **)r) - sk->data;
+  size_t idx = ((void **)r) - sk->data;
   /* This function always returns the first result. */
-  while (i > 0 && sk->comp((const void**) &p, (const void**) &sk->data[i-1]) == 0) {
-    i--;
+  while (idx > 0 &&
+         sk->comp((const void **)&p, (const void **)&sk->data[idx - 1]) == 0) {
+    idx--;
   }
   if (out_index) {
-    *out_index = i;
+    *out_index = idx;
   }
   return 1;
 }
@@ -315,7 +311,7 @@
   ret->data = s;
 
   ret->num = sk->num;
-  memcpy(ret->data, sk->data, sizeof(void *) * sk->num);
+  OPENSSL_memcpy(ret->data, sk->data, sizeof(void *) * sk->num);
   ret->sorted = sk->sorted;
   ret->num_alloc = sk->num_alloc;
   ret->comp = sk->comp;
@@ -329,7 +325,7 @@
 void sk_sort(_STACK *sk) {
   int (*comp_func)(const void *,const void *);
 
-  if (sk == NULL || sk->sorted) {
+  if (sk == NULL || sk->comp == NULL || sk->sorted) {
     return;
   }
 
@@ -364,15 +360,13 @@
     return NULL;
   }
 
-  size_t i;
-  for (i = 0; i < ret->num; i++) {
+  for (size_t i = 0; i < ret->num; i++) {
     if (ret->data[i] == NULL) {
       continue;
     }
     ret->data[i] = copy_func(ret->data[i]);
     if (ret->data[i] == NULL) {
-      size_t j;
-      for (j = 0; j < i; j++) {
+      for (size_t j = 0; j < i; j++) {
         if (ret->data[j] != NULL) {
           free_func(ret->data[j]);
         }
diff --git a/src/crypto/test/CMakeLists.txt b/src/crypto/test/CMakeLists.txt
index 8c75314..8857913 100644
--- a/src/crypto/test/CMakeLists.txt
+++ b/src/crypto/test/CMakeLists.txt
@@ -7,3 +7,11 @@
   malloc.cc
   test_util.cc
 )
+
+add_library(
+  gtest_main
+
+  OBJECT
+
+  gtest_main.cc
+)
diff --git a/src/crypto/test/file_test.cc b/src/crypto/test/file_test.cc
index 4752f04..715907e 100644
--- a/src/crypto/test/file_test.cc
+++ b/src/crypto/test/file_test.cc
@@ -14,6 +14,8 @@
 
 #include "file_test.h"
 
+#include <memory>
+
 #include <ctype.h>
 #include <errno.h>
 #include <stdarg.h>
@@ -22,6 +24,8 @@
 
 #include <openssl/err.h>
 
+#include "../internal.h"
+
 
 FileTest::FileTest(const char *path) {
   file_ = fopen(path, "r");
@@ -63,30 +67,23 @@
 }
 
 FileTest::ReadResult FileTest::ReadNext() {
-  // If the previous test had unused attributes or block, it is an error.
+  // If the previous test had unused attributes, it is an error.
   if (!unused_attributes_.empty()) {
     for (const std::string &key : unused_attributes_) {
       PrintLine("Unused attribute: %s", key.c_str());
     }
     return kReadError;
   }
-  if (!block_.empty() && !used_block_) {
-    PrintLine("Unused block");
-    return kReadError;
-  }
 
   ClearTest();
 
-  bool in_block = false;
+  static const size_t kBufLen = 64 + 8192*2;
+  std::unique_ptr<char[]> buf(new char[kBufLen]);
+
   while (true) {
     // Read the next line.
-    char buf[4096];
-    if (fgets(buf, sizeof(buf), file_) == nullptr) {
+    if (fgets(buf.get(), kBufLen, file_) == nullptr) {
       if (feof(file_)) {
-        if (in_block) {
-          fprintf(stderr, "Unterminated block.\n");
-          return kReadError;
-        }
         // EOF is a valid terminator for a test.
         return start_line_ > 0 ? kReadSuccess : kReadEOF;
       }
@@ -95,42 +92,28 @@
     }
 
     line_++;
-    size_t len = strlen(buf);
+    size_t len = strlen(buf.get());
     // Check for truncation.
     if (len > 0 && buf[len - 1] != '\n' && !feof(file_)) {
       fprintf(stderr, "Line %u too long.\n", line_);
       return kReadError;
     }
 
-    bool is_delimiter = strncmp(buf, "---", 3) == 0;
-    if (in_block) {
-      block_ += buf;
-      if (is_delimiter) {
-        // Ending the block completes the test.
-        return kReadSuccess;
-      }
-    } else if (is_delimiter) {
-      if (start_line_ == 0) {
-        fprintf(stderr, "Line %u: Unexpected block.\n", line_);
-        return kReadError;
-      }
-      in_block = true;
-      block_ += buf;
-    } else if (buf[0] == '\n' || buf[0] == '\0') {
+    if (buf[0] == '\n' || buf[0] == '\0') {
       // Empty lines delimit tests.
       if (start_line_ > 0) {
         return kReadSuccess;
       }
     } else if (buf[0] != '#') {  // Comment lines are ignored.
       // Parse the line as an attribute.
-      const char *delimiter = FindDelimiter(buf);
+      const char *delimiter = FindDelimiter(buf.get());
       if (delimiter == nullptr) {
         fprintf(stderr, "Line %u: Could not parse attribute.\n", line_);
         return kReadError;
       }
-      std::string key = StripSpace(buf, delimiter - buf);
+      std::string key = StripSpace(buf.get(), delimiter - buf.get());
       std::string value = StripSpace(delimiter + 1,
-                                     buf + len - delimiter - 1);
+                                     buf.get() + len - delimiter - 1);
 
       unused_attributes_.insert(key);
       attributes_[key] = value;
@@ -165,11 +148,6 @@
   return parameter_;
 }
 
-const std::string &FileTest::GetBlock() {
-  used_block_ = true;
-  return block_;
-}
-
 bool FileTest::HasAttribute(const std::string &key) {
   OnKeyUsed(key);
   return attributes_.count(key) > 0;
@@ -224,6 +202,7 @@
     PrintLine("Error decoding value: %s", value.c_str());
     return false;
   }
+  out->clear();
   out->reserve(value.size() / 2);
   for (size_t i = 0; i < value.size(); i += 2) {
     uint8_t hi, lo;
@@ -250,7 +229,7 @@
 bool FileTest::ExpectBytesEqual(const uint8_t *expected, size_t expected_len,
                                 const uint8_t *actual, size_t actual_len) {
   if (expected_len == actual_len &&
-      memcmp(expected, actual, expected_len) == 0) {
+      OPENSSL_memcmp(expected, actual, expected_len) == 0) {
     return true;
   }
 
@@ -266,9 +245,7 @@
   type_.clear();
   parameter_.clear();
   attributes_.clear();
-  block_.clear();
   unused_attributes_.clear();
-  used_block_ = false;
 }
 
 void FileTest::OnKeyUsed(const std::string &key) {
@@ -304,6 +281,7 @@
                      t.GetAttributeOrDie("Error").c_str(),
                      ERR_reason_error_string(err));
         failed = true;
+        ERR_clear_error();
         continue;
       }
       ERR_clear_error();
diff --git a/src/crypto/test/file_test.h b/src/crypto/test/file_test.h
index 24651ab..a859127 100644
--- a/src/crypto/test/file_test.h
+++ b/src/crypto/test/file_test.h
@@ -15,28 +15,26 @@
 #ifndef OPENSSL_HEADER_CRYPTO_TEST_FILE_TEST_H
 #define OPENSSL_HEADER_CRYPTO_TEST_FILE_TEST_H
 
+#include <openssl/base.h>
+
 #include <stdint.h>
 #include <stdio.h>
 
-#if defined(_MSC_VER)
-#pragma warning(push)
-#pragma warning(disable: 4702)
-#endif
+OPENSSL_MSVC_PRAGMA(warning(push))
+OPENSSL_MSVC_PRAGMA(warning(disable: 4702))
 
 #include <string>
 #include <map>
 #include <set>
 #include <vector>
 
-#if defined(_MSC_VER)
-#pragma warning(pop)
-#endif
+OPENSSL_MSVC_PRAGMA(warning(pop))
 
 // File-based test framework.
 //
 // This module provides a file-based test framework. The file format is based on
 // that of OpenSSL upstream's evp_test and BoringSSL's aead_test. Each input
-// file is a sequence of attributes, blocks, and blank lines.
+// file is a sequence of attributes and blank lines.
 //
 // Each attribute has the form:
 //
@@ -45,15 +43,11 @@
 // Either '=' or ':' may be used to delimit the name from the value. Both the
 // name and value have leading and trailing spaces stripped.
 //
-// Blocks are delimited by lines beginning with three hyphens, "---". One such
-// line begins a block and another ends it. Blocks are intended as a convenient
-// way to embed PEM data and include their delimiters.
+// Lines beginning with # are ignored.
 //
-// Outside a block, lines beginning with # are ignored.
-//
-// A test is a sequence of one or more attributes followed by a block or blank
-// line. Blank lines are otherwise ignored. For tests that process multiple
-// kinds of test cases, the first attribute is parsed out as the test's type and
+// A test is a sequence of one or more attributes followed by a blank line.
+// Blank lines are otherwise ignored. For tests that process multiple kinds of
+// test cases, the first attribute is parsed out as the test's type and
 // parameter. Otherwise, attributes are unordered. The first attribute is also
 // included in the set of attributes, so tests which do not dispatch may ignore
 // this mechanism.
@@ -88,11 +82,7 @@
 
   // PrintLine is a variant of printf which prepends the line number and appends
   // a trailing newline.
-  void PrintLine(const char *format, ...)
-#ifdef __GNUC__
-      __attribute__((__format__(__printf__, 2, 3)))
-#endif
-  ;
+  void PrintLine(const char *format, ...) OPENSSL_PRINTF_FORMAT_FUNC(2, 3);
 
   unsigned start_line() const { return start_line_; }
 
@@ -100,9 +90,6 @@
   const std::string &GetType();
   // GetParameter returns the value of the first attribute of the current test.
   const std::string &GetParameter();
-  // GetBlock returns the optional block of the current test, or the empty
-  // if there was no block.
-  const std::string &GetBlock();
 
   // HasAttribute returns true if the current test has an attribute named |key|.
   bool HasAttribute(const std::string &key);
@@ -113,7 +100,7 @@
   bool GetAttribute(std::string *out_value, const std::string &key);
 
   // GetAttributeOrDie looks up the attribute with key |key| and aborts if it is
-  // missing. It only be used after a |HasAttribute| call.
+  // missing. It should only be used after a |HasAttribute| call.
   const std::string &GetAttributeOrDie(const std::string &key);
 
   // GetBytes looks up the attribute with key |key| and decodes it as a byte
@@ -144,13 +131,9 @@
   std::string parameter_;
   // attributes_ contains all attributes in the test, including the first.
   std::map<std::string, std::string> attributes_;
-  // block_, if non-empty, is the test's optional trailing block.
-  std::string block_;
 
   // unused_attributes_ is the set of attributes that have been queried.
   std::set<std::string> unused_attributes_;
-  // used_block_ is true if the block has been queried.
-  bool used_block_ = false;
 
   FileTest(const FileTest&) = delete;
   FileTest &operator=(const FileTest&) = delete;
diff --git a/src/crypto/test/gtest_main.cc b/src/crypto/test/gtest_main.cc
new file mode 100644
index 0000000..ea1135c
--- /dev/null
+++ b/src/crypto/test/gtest_main.cc
@@ -0,0 +1,71 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <gtest/gtest.h>
+
+#include <stdio.h>
+
+#include <openssl/err.h>
+#include <openssl/crypto.h>
+
+#if defined(OPENSSL_WINDOWS)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
+#include <winsock2.h>
+OPENSSL_MSVC_PRAGMA(warning(pop))
+#endif
+
+
+namespace {
+
+class ErrorTestEventListener : public testing::EmptyTestEventListener {
+ public:
+  ErrorTestEventListener() {}
+  ~ErrorTestEventListener() override {}
+
+  void OnTestEnd(const testing::TestInfo &test_info) override {
+    // If the test failed, print any errors left in the error queue.
+    if (test_info.result()->Failed()) {
+      ERR_print_errors_fp(stdout);
+    }
+
+    // Clean up the error queue for the next run.
+    ERR_clear_error();
+  }
+};
+
+}  // namespace
+
+int main(int argc, char **argv) {
+  CRYPTO_library_init();
+
+#if defined(OPENSSL_WINDOWS)
+  // Initialize Winsock.
+  WORD wsa_version = MAKEWORD(2, 2);
+  WSADATA wsa_data;
+  int wsa_err = WSAStartup(wsa_version, &wsa_data);
+  if (wsa_err != 0) {
+    fprintf(stderr, "WSAStartup failed: %d\n", wsa_err);
+    return 1;
+  }
+  if (wsa_data.wVersion != wsa_version) {
+    fprintf(stderr, "Didn't get expected version: %x\n", wsa_data.wVersion);
+    return 1;
+  }
+#endif
+
+  testing::InitGoogleTest(&argc, argv);
+  testing::UnitTest::GetInstance()->listeners().Append(
+      new ErrorTestEventListener);
+  return RUN_ALL_TESTS();
+}
diff --git a/src/crypto/test/malloc.cc b/src/crypto/test/malloc.cc
index 898f2a7..33f0972 100644
--- a/src/crypto/test/malloc.cc
+++ b/src/crypto/test/malloc.cc
@@ -44,21 +44,20 @@
 #include <new>
 
 
-/* This file defines overrides for the standard allocation functions that allow
- * a given allocation to be made to fail for testing. If the program is run
- * with MALLOC_NUMBER_TO_FAIL set to a base-10 number then that allocation will
- * return NULL. If MALLOC_BREAK_ON_FAIL is also defined then the allocation
- * will signal SIGTRAP rather than return NULL.
- *
- * This code is not thread safe. */
+// This file defines overrides for the standard allocation functions that allow
+// a given allocation to be made to fail for testing. If the program is run
+// with MALLOC_NUMBER_TO_FAIL set to a base-10 number then that allocation will
+// return NULL. If MALLOC_BREAK_ON_FAIL is also defined then the allocation
+// will signal SIGTRAP rather than return NULL.
+//
+// This code is not thread safe.
 
 static uint64_t current_malloc_count = 0;
 static uint64_t malloc_number_to_fail = 0;
-static char failure_enabled = 0, break_on_fail = 0;
-static int in_call = 0;
+static bool failure_enabled = false, break_on_fail = false, in_call = false;
 
 extern "C" {
-/* These are other names for the standard allocation functions. */
+// These are other names for the standard allocation functions.
 extern void *__libc_malloc(size_t size);
 extern void *__libc_calloc(size_t num_elems, size_t size);
 extern void *__libc_realloc(void *ptr, size_t size);
@@ -75,16 +74,15 @@
   return;
 }
 
-/* should_fail_allocation returns true if the current allocation should fail. */
-static int should_fail_allocation() {
-  static int init = 0;
-  char should_fail;
+// should_fail_allocation returns true if the current allocation should fail.
+static bool should_fail_allocation() {
+  static bool init = false;
 
   if (in_call) {
-    return 0;
+    return false;
   }
 
-  in_call = 1;
+  in_call = true;
 
   if (!init) {
     const char *env = getenv("MALLOC_NUMBER_TO_FAIL");
@@ -92,22 +90,22 @@
       char *endptr;
       malloc_number_to_fail = strtoull(env, &endptr, 10);
       if (*endptr == 0) {
-        failure_enabled = 1;
+        failure_enabled = true;
         atexit(exit_handler);
         std::set_new_handler(cpp_new_handler);
       }
     }
     break_on_fail = (NULL != getenv("MALLOC_BREAK_ON_FAIL"));
-    init = 1;
+    init = true;
   }
 
-  in_call = 0;
+  in_call = false;
 
   if (!failure_enabled) {
-    return 0;
+    return false;
   }
 
-  should_fail = (current_malloc_count == malloc_number_to_fail);
+  bool should_fail = (current_malloc_count == malloc_number_to_fail);
   current_malloc_count++;
 
   if (should_fail && break_on_fail) {
diff --git a/src/crypto/test/scoped_types.h b/src/crypto/test/scoped_types.h
deleted file mode 100644
index 590f926..0000000
--- a/src/crypto/test/scoped_types.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/* Copyright (c) 2015, Google Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
-
-#ifndef OPENSSL_HEADER_CRYPTO_TEST_SCOPED_TYPES_H
-#define OPENSSL_HEADER_CRYPTO_TEST_SCOPED_TYPES_H
-
-#include <stdint.h>
-#include <stdio.h>
-
-#include <memory>
-
-#include <openssl/aead.h>
-#include <openssl/bio.h>
-#include <openssl/bn.h>
-#include <openssl/cmac.h>
-#include <openssl/dh.h>
-#include <openssl/ec.h>
-#include <openssl/ec_key.h>
-#include <openssl/ecdsa.h>
-#include <openssl/evp.h>
-#include <openssl/hmac.h>
-#include <openssl/mem.h>
-#include <openssl/pkcs8.h>
-#include <openssl/rsa.h>
-#include <openssl/stack.h>
-#include <openssl/x509.h>
-
-
-template<typename T, void (*func)(T*)>
-struct OpenSSLDeleter {
-  void operator()(T *obj) {
-    func(obj);
-  }
-};
-
-template<typename StackType, typename T, void (*func)(T*)>
-struct OpenSSLStackDeleter {
-  void operator()(StackType *obj) {
-    sk_pop_free(reinterpret_cast<_STACK*>(obj),
-                reinterpret_cast<void (*)(void *)>(func));
-  }
-};
-
-template<typename T>
-struct OpenSSLFree {
-  void operator()(T *buf) {
-    OPENSSL_free(buf);
-  }
-};
-
-struct FileCloser {
-  void operator()(FILE *file) {
-    fclose(file);
-  }
-};
-
-template<typename T, void (*func)(T*)>
-using ScopedOpenSSLType = std::unique_ptr<T, OpenSSLDeleter<T, func>>;
-
-template<typename StackType, typename T, void (*func)(T*)>
-using ScopedOpenSSLStack =
-    std::unique_ptr<StackType, OpenSSLStackDeleter<StackType, T, func>>;
-
-template<typename T, typename CleanupRet, void (*init_func)(T*),
-         CleanupRet (*cleanup_func)(T*)>
-class ScopedOpenSSLContext {
- public:
-  ScopedOpenSSLContext() {
-    init_func(&ctx_);
-  }
-  ~ScopedOpenSSLContext() {
-    cleanup_func(&ctx_);
-  }
-
-  T *get() { return &ctx_; }
-  const T *get() const { return &ctx_; }
-
-  void Reset() {
-    cleanup_func(&ctx_);
-    init_func(&ctx_);
-  }
-
- private:
-  T ctx_;
-};
-
-using ScopedBIO = ScopedOpenSSLType<BIO, BIO_vfree>;
-using ScopedBIGNUM = ScopedOpenSSLType<BIGNUM, BN_free>;
-using ScopedBN_CTX = ScopedOpenSSLType<BN_CTX, BN_CTX_free>;
-using ScopedBN_MONT_CTX = ScopedOpenSSLType<BN_MONT_CTX, BN_MONT_CTX_free>;
-using ScopedCMAC_CTX = ScopedOpenSSLType<CMAC_CTX, CMAC_CTX_free>;
-using ScopedDH = ScopedOpenSSLType<DH, DH_free>;
-using ScopedECDSA_SIG = ScopedOpenSSLType<ECDSA_SIG, ECDSA_SIG_free>;
-using ScopedEC_GROUP = ScopedOpenSSLType<EC_GROUP, EC_GROUP_free>;
-using ScopedEC_KEY = ScopedOpenSSLType<EC_KEY, EC_KEY_free>;
-using ScopedEC_POINT = ScopedOpenSSLType<EC_POINT, EC_POINT_free>;
-using ScopedEVP_PKEY = ScopedOpenSSLType<EVP_PKEY, EVP_PKEY_free>;
-using ScopedEVP_PKEY_CTX = ScopedOpenSSLType<EVP_PKEY_CTX, EVP_PKEY_CTX_free>;
-using ScopedPKCS8_PRIV_KEY_INFO = ScopedOpenSSLType<PKCS8_PRIV_KEY_INFO,
-                                                    PKCS8_PRIV_KEY_INFO_free>;
-using ScopedPKCS12 = ScopedOpenSSLType<PKCS12, PKCS12_free>;
-using ScopedRSA = ScopedOpenSSLType<RSA, RSA_free>;
-using ScopedX509 = ScopedOpenSSLType<X509, X509_free>;
-using ScopedX509_ALGOR = ScopedOpenSSLType<X509_ALGOR, X509_ALGOR_free>;
-using ScopedX509_SIG = ScopedOpenSSLType<X509_SIG, X509_SIG_free>;
-
-using ScopedX509Stack = ScopedOpenSSLStack<STACK_OF(X509), X509, X509_free>;
-
-using ScopedCBB = ScopedOpenSSLContext<CBB, void, CBB_zero, CBB_cleanup>;
-using ScopedEVP_AEAD_CTX = ScopedOpenSSLContext<EVP_AEAD_CTX, void,
-                                                EVP_AEAD_CTX_zero,
-                                                EVP_AEAD_CTX_cleanup>;
-using ScopedEVP_CIPHER_CTX = ScopedOpenSSLContext<EVP_CIPHER_CTX, int,
-                                                  EVP_CIPHER_CTX_init,
-                                                  EVP_CIPHER_CTX_cleanup>;
-using ScopedEVP_MD_CTX = ScopedOpenSSLContext<EVP_MD_CTX, int, EVP_MD_CTX_init,
-                                              EVP_MD_CTX_cleanup>;
-using ScopedHMAC_CTX = ScopedOpenSSLContext<HMAC_CTX, void, HMAC_CTX_init,
-                                            HMAC_CTX_cleanup>;
-
-using ScopedOpenSSLBytes = std::unique_ptr<uint8_t, OpenSSLFree<uint8_t>>;
-using ScopedOpenSSLString = std::unique_ptr<char, OpenSSLFree<char>>;
-
-using ScopedFILE = std::unique_ptr<FILE, FileCloser>;
-
-#endif  // OPENSSL_HEADER_CRYPTO_TEST_SCOPED_TYPES_H
diff --git a/src/crypto/test/test_util.cc b/src/crypto/test/test_util.cc
index 8021aaa..493b124 100644
--- a/src/crypto/test/test_util.cc
+++ b/src/crypto/test/test_util.cc
@@ -12,19 +12,29 @@
  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
 
-#include <stdint.h>
-#include <stdio.h>
-
 #include "test_util.h"
 
+#include <ostream>
+
+#include "../internal.h"
+
 
 void hexdump(FILE *fp, const char *msg, const void *in, size_t len) {
   const uint8_t *data = reinterpret_cast<const uint8_t*>(in);
-  size_t i;
 
   fputs(msg, fp);
-  for (i = 0; i < len; i++) {
+  for (size_t i = 0; i < len; i++) {
     fprintf(fp, "%02x", data[i]);
   }
   fputs("\n", fp);
 }
+
+std::ostream &operator<<(std::ostream &os, const Bytes &in) {
+  // Print a byte slice as hex.
+  static const char hex[] = "0123456789abcdef";
+  for (size_t i = 0; i < in.len; i++) {
+    os << hex[in.data[i] >> 4];
+    os << hex[in.data[i] & 0xf];
+  }
+  return os;
+}
diff --git a/src/crypto/test/test_util.h b/src/crypto/test/test_util.h
index 972e206..bce34d4 100644
--- a/src/crypto/test/test_util.h
+++ b/src/crypto/test/test_util.h
@@ -16,20 +16,44 @@
 #define OPENSSL_HEADER_CRYPTO_TEST_TEST_UTIL_H
 
 #include <stddef.h>
+#include <stdint.h>
 #include <stdio.h>
+#include <string.h>
 
-#if defined(__cplusplus)
-extern "C" {
-#endif
+#include <iosfwd>
+
+#include "../internal.h"
 
 
-/* hexdump writes |msg| to |fp| followed by the hex encoding of |len| bytes
- * from |in|. */
+// hexdump writes |msg| to |fp| followed by the hex encoding of |len| bytes
+// from |in|.
 void hexdump(FILE *fp, const char *msg, const void *in, size_t len);
 
+// Bytes is a wrapper over a byte slice which may be compared for equality. This
+// allows it to be used in EXPECT_EQ macros.
+struct Bytes {
+  Bytes(const uint8_t *data_arg, size_t len_arg)
+      : data(data_arg), len(len_arg) {}
+  Bytes(const char *data_arg, size_t len_arg)
+      : data(reinterpret_cast<const uint8_t *>(data_arg)), len(len_arg) {}
 
-#if defined(__cplusplus)
+  Bytes(const char *str)
+      : data(reinterpret_cast<const uint8_t *>(str)), len(strlen(str)) {}
+
+  template <size_t N>
+  Bytes(const uint8_t (&array)[N]) : data(array), len(N) {}
+
+  const uint8_t *data;
+  size_t len;
+};
+
+inline bool operator==(const Bytes &a, const Bytes &b) {
+  return a.len == b.len && OPENSSL_memcmp(a.data, b.data, a.len) == 0;
 }
-#endif
+
+inline bool operator!=(const Bytes &a, const Bytes &b) { return !(a == b); }
+
+std::ostream &operator<<(std::ostream &os, const Bytes &in);
+
 
 #endif /* OPENSSL_HEADER_CRYPTO_TEST_TEST_UTIL_H */
diff --git a/src/crypto/thread.c b/src/crypto/thread.c
index 8837115..25acce1 100644
--- a/src/crypto/thread.c
+++ b/src/crypto/thread.c
@@ -56,24 +56,17 @@
 
 #include <openssl/thread.h>
 
-#include <string.h>
-
-#if !defined(OPENSSL_WINDOWS)
-#include <errno.h>
-#else
-#pragma warning(push, 3)
-#include <windows.h>
-#pragma warning(pop)
-#endif
-
-#include <openssl/mem.h>
-
 
 int CRYPTO_num_locks(void) { return 1; }
 
 void CRYPTO_set_locking_callback(void (*func)(int mode, int lock_num,
                                               const char *file, int line)) {}
 
+void (*CRYPTO_get_locking_callback(void))(int mode, int lock_num,
+                                          const char *file, int line) {
+  return NULL;
+}
+
 void CRYPTO_set_add_lock_callback(int (*func)(int *num, int mount, int lock_num,
                                               const char *file, int line)) {}
 
@@ -99,3 +92,19 @@
 
 void CRYPTO_set_dynlock_destroy_callback(void (*dyn_destroy_function)(
     struct CRYPTO_dynlock_value *l, const char *file, int line)) {}
+
+struct CRYPTO_dynlock_value *(*CRYPTO_get_dynlock_create_callback(void))(
+    const char *file, int line) {
+  return NULL;
+}
+
+void (*CRYPTO_get_dynlock_lock_callback(void))(int mode,
+                                               struct CRYPTO_dynlock_value *l,
+                                               const char *file, int line) {
+  return NULL;
+}
+
+void (*CRYPTO_get_dynlock_destroy_callback(void))(
+    struct CRYPTO_dynlock_value *l, const char *file, int line) {
+  return NULL;
+}
diff --git a/src/crypto/thread_none.c b/src/crypto/thread_none.c
index cf4e85a..85768b4 100644
--- a/src/crypto/thread_none.c
+++ b/src/crypto/thread_none.c
@@ -22,7 +22,9 @@
 
 void CRYPTO_MUTEX_lock_write(CRYPTO_MUTEX *lock) {}
 
-void CRYPTO_MUTEX_unlock(CRYPTO_MUTEX *lock) {}
+void CRYPTO_MUTEX_unlock_read(CRYPTO_MUTEX *lock) {}
+
+void CRYPTO_MUTEX_unlock_write(CRYPTO_MUTEX *lock) {}
 
 void CRYPTO_MUTEX_cleanup(CRYPTO_MUTEX *lock) {}
 
@@ -30,7 +32,9 @@
 
 void CRYPTO_STATIC_MUTEX_lock_write(struct CRYPTO_STATIC_MUTEX *lock) {}
 
-void CRYPTO_STATIC_MUTEX_unlock(struct CRYPTO_STATIC_MUTEX *lock) {}
+void CRYPTO_STATIC_MUTEX_unlock_read(struct CRYPTO_STATIC_MUTEX *lock) {}
+
+void CRYPTO_STATIC_MUTEX_unlock_write(struct CRYPTO_STATIC_MUTEX *lock) {}
 
 void CRYPTO_once(CRYPTO_once_t *once, void (*init)(void)) {
   if (*once) {
diff --git a/src/crypto/thread_pthread.c b/src/crypto/thread_pthread.c
index 68aaab5..d9e87f2 100644
--- a/src/crypto/thread_pthread.c
+++ b/src/crypto/thread_pthread.c
@@ -14,10 +14,9 @@
 
 #include "internal.h"
 
-#if !defined(OPENSSL_WINDOWS) && !defined(OPENSSL_NO_THREADS)
+#if defined(OPENSSL_PTHREADS)
 
 #include <pthread.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -46,7 +45,13 @@
   }
 }
 
-void CRYPTO_MUTEX_unlock(CRYPTO_MUTEX *lock) {
+void CRYPTO_MUTEX_unlock_read(CRYPTO_MUTEX *lock) {
+  if (pthread_rwlock_unlock((pthread_rwlock_t *) lock) != 0) {
+    abort();
+  }
+}
+
+void CRYPTO_MUTEX_unlock_write(CRYPTO_MUTEX *lock) {
   if (pthread_rwlock_unlock((pthread_rwlock_t *) lock) != 0) {
     abort();
   }
@@ -68,7 +73,13 @@
   }
 }
 
-void CRYPTO_STATIC_MUTEX_unlock(struct CRYPTO_STATIC_MUTEX *lock) {
+void CRYPTO_STATIC_MUTEX_unlock_read(struct CRYPTO_STATIC_MUTEX *lock) {
+  if (pthread_rwlock_unlock(&lock->lock) != 0) {
+    abort();
+  }
+}
+
+void CRYPTO_STATIC_MUTEX_unlock_write(struct CRYPTO_STATIC_MUTEX *lock) {
   if (pthread_rwlock_unlock(&lock->lock) != 0) {
     abort();
   }
@@ -76,8 +87,6 @@
 
 void CRYPTO_once(CRYPTO_once_t *once, void (*init)(void)) {
   if (pthread_once(once, init) != 0) {
-    fprintf(stderr,
-            "pthread_once failed. Did you link against a threading library?\n");
     abort();
   }
 }
@@ -94,7 +103,7 @@
   if (pthread_mutex_lock(&g_destructors_lock) != 0) {
     return;
   }
-  memcpy(destructors, g_destructors, sizeof(destructors));
+  OPENSSL_memcpy(destructors, g_destructors, sizeof(destructors));
   pthread_mutex_unlock(&g_destructors_lock);
 
   unsigned i;
@@ -145,7 +154,7 @@
       destructor(value);
       return 0;
     }
-    memset(pointers, 0, sizeof(void *) * NUM_OPENSSL_THREAD_LOCALS);
+    OPENSSL_memset(pointers, 0, sizeof(void *) * NUM_OPENSSL_THREAD_LOCALS);
     if (pthread_setspecific(g_thread_local_key, pointers) != 0) {
       OPENSSL_free(pointers);
       destructor(value);
@@ -164,4 +173,4 @@
   return 1;
 }
 
-#endif  /* !OPENSSL_WINDOWS && !OPENSSL_NO_THREADS */
+#endif  /* OPENSSL_PTHREADS */
diff --git a/src/crypto/thread_test.c b/src/crypto/thread_test.c
index e028b1b..c702ace 100644
--- a/src/crypto/thread_test.c
+++ b/src/crypto/thread_test.c
@@ -21,16 +21,16 @@
 
 #if defined(OPENSSL_WINDOWS)
 
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <windows.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
 
 typedef HANDLE thread_t;
 
 static DWORD WINAPI thread_run(LPVOID arg) {
   void (*thread_func)(void);
   /* VC really doesn't like casting between data and function pointers. */
-  memcpy(&thread_func, &arg, sizeof(thread_func));
+  OPENSSL_memcpy(&thread_func, &arg, sizeof(thread_func));
   thread_func();
   return 0;
 }
@@ -38,7 +38,7 @@
 static int run_thread(thread_t *out_thread, void (*thread_func)(void)) {
   void *arg;
   /* VC really doesn't like casting between data and function pointers. */
-  memcpy(&arg, &thread_func, sizeof(arg));
+  OPENSSL_memcpy(&arg, &thread_func, sizeof(arg));
 
   *out_thread = CreateThread(NULL /* security attributes */,
                              0 /* default stack size */, thread_run, arg,
@@ -53,6 +53,8 @@
 #else
 
 #include <pthread.h>
+#include <string.h>
+#include <time.h>
 
 typedef pthread_t thread_t;
 
@@ -77,6 +79,17 @@
 
 static void once_init(void) {
   g_once_init_called++;
+
+  /* Sleep briefly so one |call_once_thread| instance will call |CRYPTO_once|
+   * while the other is running this function. */
+#if defined(OPENSSL_WINDOWS)
+  Sleep(1 /* milliseconds */);
+#else
+  struct timespec req;
+  OPENSSL_memset(&req, 0, sizeof(req));
+  req.tv_nsec = 1000000;
+  nanosleep(&req, NULL);
+#endif
 }
 
 static CRYPTO_once_t g_test_once = CRYPTO_ONCE_INIT;
@@ -91,9 +104,11 @@
     return 0;
   }
 
-  thread_t thread;
-  if (!run_thread(&thread, call_once_thread) ||
-      !wait_for_thread(thread)) {
+  thread_t thread1, thread2;
+  if (!run_thread(&thread1, call_once_thread) ||
+      !run_thread(&thread2, call_once_thread) ||
+      !wait_for_thread(thread1) ||
+      !wait_for_thread(thread2)) {
     fprintf(stderr, "thread failed.\n");
     return 0;
   }
diff --git a/src/crypto/thread_win.c b/src/crypto/thread_win.c
index 5efd8be..62119b4 100644
--- a/src/crypto/thread_win.c
+++ b/src/crypto/thread_win.c
@@ -14,13 +14,12 @@
 
 #include "internal.h"
 
-#if defined(OPENSSL_WINDOWS) && !defined(OPENSSL_NO_THREADS)
+#if defined(OPENSSL_WINDOWS_THREADS)
 
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <windows.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
 
-#include <assert.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -28,108 +27,59 @@
 #include <openssl/type_check.h>
 
 
-OPENSSL_COMPILE_ASSERT(sizeof(CRYPTO_MUTEX) >= sizeof(CRITICAL_SECTION),
+OPENSSL_COMPILE_ASSERT(sizeof(CRYPTO_MUTEX) >= sizeof(SRWLOCK),
                        CRYPTO_MUTEX_too_small);
 
-static void run_once(CRYPTO_once_t *in_once, void (*init)(void *), void *arg) {
-  volatile LONG *once = in_once;
-
-  /* Values must be aligned. */
-  assert((((uintptr_t) once) & 3) == 0);
-
-  /* This assumes that reading *once has acquire semantics. This should be true
-   * on x86 and x86-64, where we expect Windows to run. */
-#if !defined(OPENSSL_X86) && !defined(OPENSSL_X86_64)
-#error "Windows once code may not work on other platforms." \
-       "You can use InitOnceBeginInitialize on >=Vista"
-#endif
-  if (*once == 1) {
-    return;
-  }
-
-  for (;;) {
-    switch (InterlockedCompareExchange(once, 2, 0)) {
-      case 0:
-        /* The value was zero so we are the first thread to call |CRYPTO_once|
-         * on it. */
-        init(arg);
-        /* Write one to indicate that initialisation is complete. */
-        InterlockedExchange(once, 1);
-        return;
-
-      case 1:
-        /* Another thread completed initialisation between our fast-path check
-         * and |InterlockedCompareExchange|. */
-        return;
-
-      case 2:
-        /* Another thread is running the initialisation. Switch to it then try
-         * again. */
-        SwitchToThread();
-        break;
-
-      default:
-        abort();
-    }
-  }
+static BOOL CALLBACK call_once_init(INIT_ONCE *once, void *arg, void **out) {
+  void (**init)(void) = (void (**)(void))arg;
+  (**init)();
+  return TRUE;
 }
 
-static void call_once_init(void *arg) {
-  void (*init_func)(void);
-  /* MSVC does not like casting between data and function pointers. */
-  memcpy(&init_func, &arg, sizeof(void *));
-  init_func();
-}
-
-void CRYPTO_once(CRYPTO_once_t *in_once, void (*init)(void)) {
-  void *arg;
-  /* MSVC does not like casting between data and function pointers. */
-  memcpy(&arg, &init, sizeof(void *));
-  run_once(in_once, call_once_init, arg);
+void CRYPTO_once(CRYPTO_once_t *once, void (*init)(void)) {
+  if (!InitOnceExecuteOnce(once, call_once_init, &init, NULL)) {
+    abort();
+  }
 }
 
 void CRYPTO_MUTEX_init(CRYPTO_MUTEX *lock) {
-  if (!InitializeCriticalSectionAndSpinCount((CRITICAL_SECTION *) lock, 0x400)) {
-    abort();
-  }
+  InitializeSRWLock((SRWLOCK *) lock);
 }
 
 void CRYPTO_MUTEX_lock_read(CRYPTO_MUTEX *lock) {
-  /* Since we have to support Windows XP, read locks are actually exclusive. */
-  EnterCriticalSection((CRITICAL_SECTION *) lock);
+  AcquireSRWLockShared((SRWLOCK *) lock);
 }
 
 void CRYPTO_MUTEX_lock_write(CRYPTO_MUTEX *lock) {
-  EnterCriticalSection((CRITICAL_SECTION *) lock);
+  AcquireSRWLockExclusive((SRWLOCK *) lock);
 }
 
-void CRYPTO_MUTEX_unlock(CRYPTO_MUTEX *lock) {
-  LeaveCriticalSection((CRITICAL_SECTION *) lock);
+void CRYPTO_MUTEX_unlock_read(CRYPTO_MUTEX *lock) {
+  ReleaseSRWLockShared((SRWLOCK *) lock);
+}
+
+void CRYPTO_MUTEX_unlock_write(CRYPTO_MUTEX *lock) {
+  ReleaseSRWLockExclusive((SRWLOCK *) lock);
 }
 
 void CRYPTO_MUTEX_cleanup(CRYPTO_MUTEX *lock) {
-  DeleteCriticalSection((CRITICAL_SECTION *) lock);
-}
-
-static void static_lock_init(void *arg) {
-  struct CRYPTO_STATIC_MUTEX *lock = arg;
-  if (!InitializeCriticalSectionAndSpinCount(&lock->lock, 0x400)) {
-    abort();
-  }
+  /* SRWLOCKs require no cleanup. */
 }
 
 void CRYPTO_STATIC_MUTEX_lock_read(struct CRYPTO_STATIC_MUTEX *lock) {
-  /* Since we have to support Windows XP, read locks are actually exclusive. */
-  run_once(&lock->once, static_lock_init, lock);
-  EnterCriticalSection(&lock->lock);
+  AcquireSRWLockShared(&lock->lock);
 }
 
 void CRYPTO_STATIC_MUTEX_lock_write(struct CRYPTO_STATIC_MUTEX *lock) {
-  CRYPTO_STATIC_MUTEX_lock_read(lock);
+  AcquireSRWLockExclusive(&lock->lock);
 }
 
-void CRYPTO_STATIC_MUTEX_unlock(struct CRYPTO_STATIC_MUTEX *lock) {
-  LeaveCriticalSection(&lock->lock);
+void CRYPTO_STATIC_MUTEX_unlock_read(struct CRYPTO_STATIC_MUTEX *lock) {
+  ReleaseSRWLockShared(&lock->lock);
+}
+
+void CRYPTO_STATIC_MUTEX_unlock_write(struct CRYPTO_STATIC_MUTEX *lock) {
+  ReleaseSRWLockExclusive(&lock->lock);
 }
 
 static CRITICAL_SECTION g_destructors_lock;
@@ -148,9 +98,14 @@
   g_thread_local_failed = (g_thread_local_key == TLS_OUT_OF_INDEXES);
 }
 
-static void NTAPI thread_local_destructor(PVOID module,
-                                          DWORD reason, PVOID reserved) {
-  if (DLL_THREAD_DETACH != reason && DLL_PROCESS_DETACH != reason) {
+static void NTAPI thread_local_destructor(PVOID module, DWORD reason,
+                                          PVOID reserved) {
+  /* Only free memory on |DLL_THREAD_DETACH|, not |DLL_PROCESS_DETACH|. In
+   * VS2015's debug runtime, the C runtime has been unloaded by the time
+   * |DLL_PROCESS_DETACH| runs. See https://crbug.com/575795. This is consistent
+   * with |pthread_key_create| which does not call destructors on process exit,
+   * only thread exit. */
+  if (reason != DLL_THREAD_DETACH) {
     return;
   }
 
@@ -167,7 +122,7 @@
   thread_local_destructor_t destructors[NUM_OPENSSL_THREAD_LOCALS];
 
   EnterCriticalSection(&g_destructors_lock);
-  memcpy(destructors, g_destructors, sizeof(destructors));
+  OPENSSL_memcpy(destructors, g_destructors, sizeof(destructors));
   LeaveCriticalSection(&g_destructors_lock);
 
   unsigned i;
@@ -263,7 +218,7 @@
       destructor(value);
       return 0;
     }
-    memset(pointers, 0, sizeof(void *) * NUM_OPENSSL_THREAD_LOCALS);
+    OPENSSL_memset(pointers, 0, sizeof(void *) * NUM_OPENSSL_THREAD_LOCALS);
     if (TlsSetValue(g_thread_local_key, pointers) == 0) {
       OPENSSL_free(pointers);
       destructor(value);
@@ -279,4 +234,4 @@
   return 1;
 }
 
-#endif  /* OPENSSL_WINDOWS && !OPENSSL_NO_THREADS */
+#endif  /* OPENSSL_WINDOWS_THREADS */
diff --git a/src/crypto/x509/CMakeLists.txt b/src/crypto/x509/CMakeLists.txt
index 8ffeaa0..5d82e0a 100644
--- a/src/crypto/x509/CMakeLists.txt
+++ b/src/crypto/x509/CMakeLists.txt
@@ -9,11 +9,13 @@
   a_sign.c
   a_strex.c
   a_verify.c
+  algorithm.c
   asn1_gen.c
   by_dir.c
   by_file.c
   i2d_pr.c
   pkcs7.c
+  rsa_pss.c
   t_crl.c
   t_req.c
   t_x509.c
@@ -64,5 +66,14 @@
   $<TARGET_OBJECTS:test_support>
 )
 
+add_executable(
+  x509_test
+
+  x509_test.cc
+
+  $<TARGET_OBJECTS:test_support>
+)
+
 target_link_libraries(pkcs7_test crypto)
-add_dependencies(all_tests pkcs7_test)
+target_link_libraries(x509_test crypto)
+add_dependencies(all_tests pkcs7_test x509_test)
diff --git a/src/crypto/x509/a_digest.c b/src/crypto/x509/a_digest.c
index 430e2e6..b88d6ac 100644
--- a/src/crypto/x509/a_digest.c
+++ b/src/crypto/x509/a_digest.c
@@ -61,37 +61,36 @@
 #include <openssl/err.h>
 #include <openssl/mem.h>
 
-
 int ASN1_digest(i2d_of_void *i2d, const EVP_MD *type, char *data,
-		unsigned char *md, unsigned int *len)
-	{
-	int i, ret;
-	unsigned char *str,*p;
+                unsigned char *md, unsigned int *len)
+{
+    int i, ret;
+    unsigned char *str, *p;
 
-	i=i2d(data,NULL);
-	if ((str=(unsigned char *)OPENSSL_malloc(i)) == NULL)
-		{
-		OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-		return(0);
-		}
-	p=str;
-	i2d(data,&p);
+    i = i2d(data, NULL);
+    if ((str = (unsigned char *)OPENSSL_malloc(i)) == NULL) {
+        OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+        return (0);
+    }
+    p = str;
+    i2d(data, &p);
 
-	ret = EVP_Digest(str, i, md, len, type, NULL);
-	OPENSSL_free(str);
-	return ret;
-	}
+    ret = EVP_Digest(str, i, md, len, type, NULL);
+    OPENSSL_free(str);
+    return ret;
+}
 
 int ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *type, void *asn,
-		unsigned char *md, unsigned int *len)
-	{
-	int i, ret;
-	unsigned char *str = NULL;
+                     unsigned char *md, unsigned int *len)
+{
+    int i, ret;
+    unsigned char *str = NULL;
 
-	i=ASN1_item_i2d(asn,&str, it);
-	if (!str) return(0);
+    i = ASN1_item_i2d(asn, &str, it);
+    if (!str)
+        return (0);
 
-	ret = EVP_Digest(str, i, md, len, type, NULL);
-	OPENSSL_free(str);
-	return ret;
-	}
+    ret = EVP_Digest(str, i, md, len, type, NULL);
+    OPENSSL_free(str);
+    return ret;
+}
diff --git a/src/crypto/x509/a_sign.c b/src/crypto/x509/a_sign.c
index 4e9be8a..13a3ac2 100644
--- a/src/crypto/x509/a_sign.c
+++ b/src/crypto/x509/a_sign.c
@@ -62,75 +62,74 @@
 #include <openssl/obj.h>
 #include <openssl/x509.h>
 
-#include "../evp/internal.h"
+#include "internal.h"
 
-
-int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2,
-	     ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey,
-	     const EVP_MD *type)
-	{
-	EVP_MD_CTX ctx;
-	EVP_MD_CTX_init(&ctx);
-	if (!EVP_DigestSignInit(&ctx, NULL, type, NULL, pkey))
-		{
-		EVP_MD_CTX_cleanup(&ctx);
-		return 0;
-		}
-	return ASN1_item_sign_ctx(it, algor1, algor2, signature, asn, &ctx);
-	}
-		
+int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1,
+                   X509_ALGOR *algor2, ASN1_BIT_STRING *signature, void *asn,
+                   EVP_PKEY *pkey, const EVP_MD *type)
+{
+    EVP_MD_CTX ctx;
+    EVP_MD_CTX_init(&ctx);
+    if (!EVP_DigestSignInit(&ctx, NULL, type, NULL, pkey)) {
+        EVP_MD_CTX_cleanup(&ctx);
+        return 0;
+    }
+    return ASN1_item_sign_ctx(it, algor1, algor2, signature, asn, &ctx);
+}
 
 int ASN1_item_sign_ctx(const ASN1_ITEM *it,
-		X509_ALGOR *algor1, X509_ALGOR *algor2,
-	     	ASN1_BIT_STRING *signature, void *asn, EVP_MD_CTX *ctx)
-	{
-	EVP_PKEY *pkey;
-	unsigned char *buf_in=NULL,*buf_out=NULL;
-	size_t inl=0,outl=0,outll=0;
+                       X509_ALGOR *algor1, X509_ALGOR *algor2,
+                       ASN1_BIT_STRING *signature, void *asn, EVP_MD_CTX *ctx)
+{
+    EVP_PKEY *pkey;
+    unsigned char *buf_in = NULL, *buf_out = NULL;
+    size_t inl = 0, outl = 0, outll = 0;
 
-	pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);
+    pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);
 
-	/* Write out the requested copies of the AlgorithmIdentifier. */
-	if (algor1 && !EVP_DigestSignAlgorithm(ctx, algor1))
-		{
-		goto err;
-		}
-	if (algor2 && !EVP_DigestSignAlgorithm(ctx, algor2))
-		{
-		goto err;
-		}
+    /* Write out the requested copies of the AlgorithmIdentifier. */
+    if (algor1 && !x509_digest_sign_algorithm(ctx, algor1)) {
+        goto err;
+    }
+    if (algor2 && !x509_digest_sign_algorithm(ctx, algor2)) {
+        goto err;
+    }
 
-	inl=ASN1_item_i2d(asn,&buf_in, it);
-	outll=outl=EVP_PKEY_size(pkey);
-	buf_out=OPENSSL_malloc((unsigned int)outl);
-	if ((buf_in == NULL) || (buf_out == NULL))
-		{
-		outl=0;
-		OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-		goto err;
-		}
+    inl = ASN1_item_i2d(asn, &buf_in, it);
+    outll = outl = EVP_PKEY_size(pkey);
+    buf_out = OPENSSL_malloc((unsigned int)outl);
+    if ((buf_in == NULL) || (buf_out == NULL)) {
+        outl = 0;
+        OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
 
-	if (!EVP_DigestSignUpdate(ctx, buf_in, inl)
-		|| !EVP_DigestSignFinal(ctx, buf_out, &outl))
-		{
-		outl=0;
-		OPENSSL_PUT_ERROR(X509, ERR_R_EVP_LIB);
-		goto err;
-		}
-	if (signature->data != NULL) OPENSSL_free(signature->data);
-	signature->data=buf_out;
-	buf_out=NULL;
-	signature->length=outl;
-	/* In the interests of compatibility, I'll make sure that
-	 * the bit string has a 'not-used bits' value of 0
-	 */
-	signature->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
-	signature->flags|=ASN1_STRING_FLAG_BITS_LEFT;
-err:
-	EVP_MD_CTX_cleanup(ctx);
-	if (buf_in != NULL)
-		{ OPENSSL_cleanse((char *)buf_in,(unsigned int)inl); OPENSSL_free(buf_in); }
-	if (buf_out != NULL)
-		{ OPENSSL_cleanse((char *)buf_out,outll); OPENSSL_free(buf_out); }
-	return(outl);
-	}
+    if (!EVP_DigestSignUpdate(ctx, buf_in, inl)
+        || !EVP_DigestSignFinal(ctx, buf_out, &outl)) {
+        outl = 0;
+        OPENSSL_PUT_ERROR(X509, ERR_R_EVP_LIB);
+        goto err;
+    }
+    if (signature->data != NULL)
+        OPENSSL_free(signature->data);
+    signature->data = buf_out;
+    buf_out = NULL;
+    signature->length = outl;
+    /*
+     * In the interests of compatibility, I'll make sure that the bit string
+     * has a 'not-used bits' value of 0
+     */
+    signature->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
+    signature->flags |= ASN1_STRING_FLAG_BITS_LEFT;
+ err:
+    EVP_MD_CTX_cleanup(ctx);
+    if (buf_in != NULL) {
+        OPENSSL_cleanse((char *)buf_in, (unsigned int)inl);
+        OPENSSL_free(buf_in);
+    }
+    if (buf_out != NULL) {
+        OPENSSL_cleanse((char *)buf_out, outll);
+        OPENSSL_free(buf_out);
+    }
+    return (outl);
+}
diff --git a/src/crypto/x509/a_strex.c b/src/crypto/x509/a_strex.c
index b194d18..d0d8356 100644
--- a/src/crypto/x509/a_strex.c
+++ b/src/crypto/x509/a_strex.c
@@ -64,501 +64,570 @@
 
 #include "charmap.h"
 
-
-/* ASN1_STRING_print_ex() and X509_NAME_print_ex().
- * Enhanced string and name printing routines handling
- * multibyte characters, RFC2253 and a host of other
- * options.
+/*
+ * ASN1_STRING_print_ex() and X509_NAME_print_ex(). Enhanced string and name
+ * printing routines handling multibyte characters, RFC2253 and a host of
+ * other options.
  */
 
-
-#define CHARTYPE_BS_ESC		(ASN1_STRFLGS_ESC_2253 | CHARTYPE_FIRST_ESC_2253 | CHARTYPE_LAST_ESC_2253)
+#define CHARTYPE_BS_ESC         (ASN1_STRFLGS_ESC_2253 | CHARTYPE_FIRST_ESC_2253 | CHARTYPE_LAST_ESC_2253)
 
 #define ESC_FLAGS (ASN1_STRFLGS_ESC_2253 | \
-		  ASN1_STRFLGS_ESC_QUOTE | \
-		  ASN1_STRFLGS_ESC_CTRL | \
-		  ASN1_STRFLGS_ESC_MSB)
-
+                  ASN1_STRFLGS_ESC_QUOTE | \
+                  ASN1_STRFLGS_ESC_CTRL | \
+                  ASN1_STRFLGS_ESC_MSB)
 
 static int send_bio_chars(void *arg, const void *buf, int len)
 {
-	if(!arg) return 1;
-	if(BIO_write(arg, buf, len) != len) return 0;
-	return 1;
+    if (!arg)
+        return 1;
+    if (BIO_write(arg, buf, len) != len)
+        return 0;
+    return 1;
 }
 
 static int send_fp_chars(void *arg, const void *buf, int len)
 {
-	if(!arg) return 1;
-	if(fwrite(buf, 1, len, arg) != (unsigned int)len) return 0;
-	return 1;
+    if (!arg)
+        return 1;
+    if (fwrite(buf, 1, len, arg) != (unsigned int)len)
+        return 0;
+    return 1;
 }
 
-typedef int char_io(void *arg, const void *buf, int len);
+typedef int char_io (void *arg, const void *buf, int len);
 
-/* This function handles display of
- * strings, one character at a time.
- * It is passed an unsigned long for each
- * character because it could come from 2 or even
- * 4 byte forms.
+/*
+ * This function handles display of strings, one character at a time. It is
+ * passed an unsigned long for each character because it could come from 2 or
+ * even 4 byte forms.
  */
 
 #define HEX_SIZE(type) (sizeof(type)*2)
 
-static int do_esc_char(unsigned long c, unsigned char flags, char *do_quotes, char_io *io_ch, void *arg)
+static int do_esc_char(unsigned long c, unsigned char flags, char *do_quotes,
+                       char_io *io_ch, void *arg)
 {
-	unsigned char chflgs, chtmp;
-	char tmphex[HEX_SIZE(long)+3];
+    unsigned char chflgs, chtmp;
+    char tmphex[HEX_SIZE(long) + 3];
 
-	if(c > 0xffffffffL)
-		return -1;
-	if(c > 0xffff) {
-		BIO_snprintf(tmphex, sizeof tmphex, "\\W%08lX", c);
-		if(!io_ch(arg, tmphex, 10)) return -1;
-		return 10;
-	}
-	if(c > 0xff) {
-		BIO_snprintf(tmphex, sizeof tmphex, "\\U%04lX", c);
-		if(!io_ch(arg, tmphex, 6)) return -1;
-		return 6;
-	}
-	chtmp = (unsigned char)c;
-	if(chtmp > 0x7f) chflgs = flags & ASN1_STRFLGS_ESC_MSB;
-	else chflgs = char_type[chtmp] & flags;
-	if(chflgs & CHARTYPE_BS_ESC) {
-		/* If we don't escape with quotes, signal we need quotes */
-		if(chflgs & ASN1_STRFLGS_ESC_QUOTE) {
-			if(do_quotes) *do_quotes = 1;
-			if(!io_ch(arg, &chtmp, 1)) return -1;
-			return 1;
-		}
-		if(!io_ch(arg, "\\", 1)) return -1;
-		if(!io_ch(arg, &chtmp, 1)) return -1;
-		return 2;
-	}
-	if(chflgs & (ASN1_STRFLGS_ESC_CTRL|ASN1_STRFLGS_ESC_MSB)) {
-		BIO_snprintf(tmphex, 11, "\\%02X", chtmp);
-		if(!io_ch(arg, tmphex, 3)) return -1;
-		return 3;
-	}
-	/* If we get this far and do any escaping at all must escape 
-	 * the escape character itself: backslash.
-	 */
-	if (chtmp == '\\' && flags & ESC_FLAGS) {
-		if(!io_ch(arg, "\\\\", 2)) return -1;
-		return 2;
-	}
-	if(!io_ch(arg, &chtmp, 1)) return -1;
-	return 1;
+    if (c > 0xffffffffL)
+        return -1;
+    if (c > 0xffff) {
+        BIO_snprintf(tmphex, sizeof tmphex, "\\W%08lX", c);
+        if (!io_ch(arg, tmphex, 10))
+            return -1;
+        return 10;
+    }
+    if (c > 0xff) {
+        BIO_snprintf(tmphex, sizeof tmphex, "\\U%04lX", c);
+        if (!io_ch(arg, tmphex, 6))
+            return -1;
+        return 6;
+    }
+    chtmp = (unsigned char)c;
+    if (chtmp > 0x7f)
+        chflgs = flags & ASN1_STRFLGS_ESC_MSB;
+    else
+        chflgs = char_type[chtmp] & flags;
+    if (chflgs & CHARTYPE_BS_ESC) {
+        /* If we don't escape with quotes, signal we need quotes */
+        if (chflgs & ASN1_STRFLGS_ESC_QUOTE) {
+            if (do_quotes)
+                *do_quotes = 1;
+            if (!io_ch(arg, &chtmp, 1))
+                return -1;
+            return 1;
+        }
+        if (!io_ch(arg, "\\", 1))
+            return -1;
+        if (!io_ch(arg, &chtmp, 1))
+            return -1;
+        return 2;
+    }
+    if (chflgs & (ASN1_STRFLGS_ESC_CTRL | ASN1_STRFLGS_ESC_MSB)) {
+        BIO_snprintf(tmphex, 11, "\\%02X", chtmp);
+        if (!io_ch(arg, tmphex, 3))
+            return -1;
+        return 3;
+    }
+    /*
+     * If we get this far and do any escaping at all must escape the escape
+     * character itself: backslash.
+     */
+    if (chtmp == '\\' && flags & ESC_FLAGS) {
+        if (!io_ch(arg, "\\\\", 2))
+            return -1;
+        return 2;
+    }
+    if (!io_ch(arg, &chtmp, 1))
+        return -1;
+    return 1;
 }
 
-#define BUF_TYPE_WIDTH_MASK	0x7
-#define BUF_TYPE_CONVUTF8	0x8
+#define BUF_TYPE_WIDTH_MASK     0x7
+#define BUF_TYPE_CONVUTF8       0x8
 
-/* This function sends each character in a buffer to
- * do_esc_char(). It interprets the content formats
- * and converts to or from UTF8 as appropriate.
+/*
+ * This function sends each character in a buffer to do_esc_char(). It
+ * interprets the content formats and converts to or from UTF8 as
+ * appropriate.
  */
 
 static int do_buf(unsigned char *buf, int buflen,
-			int type, unsigned char flags, char *quotes, char_io *io_ch, void *arg)
+                  int type, unsigned char flags, char *quotes, char_io *io_ch,
+                  void *arg)
 {
-	int i, outlen, len;
-	unsigned char orflags, *p, *q;
-	unsigned long c;
-	p = buf;
-	q = buf + buflen;
-	outlen = 0;
-	while(p != q) {
-		if(p == buf && flags & ASN1_STRFLGS_ESC_2253) orflags = CHARTYPE_FIRST_ESC_2253;
-		else orflags = 0;
-		switch(type & BUF_TYPE_WIDTH_MASK) {
-			case 4:
-			c = ((unsigned long)*p++) << 24;
-			c |= ((unsigned long)*p++) << 16;
-			c |= ((unsigned long)*p++) << 8;
-			c |= *p++;
-			break;
+    int i, outlen, len;
+    unsigned char orflags, *p, *q;
+    unsigned long c;
+    p = buf;
+    q = buf + buflen;
+    outlen = 0;
+    while (p != q) {
+        if (p == buf && flags & ASN1_STRFLGS_ESC_2253)
+            orflags = CHARTYPE_FIRST_ESC_2253;
+        else
+            orflags = 0;
+        switch (type & BUF_TYPE_WIDTH_MASK) {
+        case 4:
+            c = ((unsigned long)*p++) << 24;
+            c |= ((unsigned long)*p++) << 16;
+            c |= ((unsigned long)*p++) << 8;
+            c |= *p++;
+            break;
 
-			case 2:
-			c = ((unsigned long)*p++) << 8;
-			c |= *p++;
-			break;
+        case 2:
+            c = ((unsigned long)*p++) << 8;
+            c |= *p++;
+            break;
 
-			case 1:
-			c = *p++;
-			break;
-			
-			case 0:
-			i = UTF8_getc(p, buflen, &c);
-			if(i < 0) return -1;	/* Invalid UTF8String */
-			p += i;
-			break;
-			default:
-			return -1;	/* invalid width */
-		}
-		if (p == q && flags & ASN1_STRFLGS_ESC_2253) orflags = CHARTYPE_LAST_ESC_2253;
-		if(type & BUF_TYPE_CONVUTF8) {
-			unsigned char utfbuf[6];
-			int utflen;
-			utflen = UTF8_putc(utfbuf, sizeof utfbuf, c);
-			for(i = 0; i < utflen; i++) {
-				/* We don't need to worry about setting orflags correctly
-				 * because if utflen==1 its value will be correct anyway 
-				 * otherwise each character will be > 0x7f and so the 
-				 * character will never be escaped on first and last.
-				 */
-				len = do_esc_char(utfbuf[i], (unsigned char)(flags | orflags), quotes, io_ch, arg);
-				if(len < 0) return -1;
-				outlen += len;
-			}
-		} else {
-			len = do_esc_char(c, (unsigned char)(flags | orflags), quotes, io_ch, arg);
-			if(len < 0) return -1;
-			outlen += len;
-		}
-	}
-	return outlen;
+        case 1:
+            c = *p++;
+            break;
+
+        case 0:
+            i = UTF8_getc(p, buflen, &c);
+            if (i < 0)
+                return -1;      /* Invalid UTF8String */
+            p += i;
+            break;
+        default:
+            return -1;          /* invalid width */
+        }
+        if (p == q && flags & ASN1_STRFLGS_ESC_2253)
+            orflags = CHARTYPE_LAST_ESC_2253;
+        if (type & BUF_TYPE_CONVUTF8) {
+            unsigned char utfbuf[6];
+            int utflen;
+            utflen = UTF8_putc(utfbuf, sizeof utfbuf, c);
+            for (i = 0; i < utflen; i++) {
+                /*
+                 * We don't need to worry about setting orflags correctly
+                 * because if utflen==1 its value will be correct anyway
+                 * otherwise each character will be > 0x7f and so the
+                 * character will never be escaped on first and last.
+                 */
+                len =
+                    do_esc_char(utfbuf[i], (unsigned char)(flags | orflags),
+                                quotes, io_ch, arg);
+                if (len < 0)
+                    return -1;
+                outlen += len;
+            }
+        } else {
+            len =
+                do_esc_char(c, (unsigned char)(flags | orflags), quotes,
+                            io_ch, arg);
+            if (len < 0)
+                return -1;
+            outlen += len;
+        }
+    }
+    return outlen;
 }
 
 /* This function hex dumps a buffer of characters */
 
-static int do_hex_dump(char_io *io_ch, void *arg, unsigned char *buf, int buflen)
+static int do_hex_dump(char_io *io_ch, void *arg, unsigned char *buf,
+                       int buflen)
 {
-	static const char hexdig[] = "0123456789ABCDEF";
-	unsigned char *p, *q;
-	char hextmp[2];
-	if(arg) {
-		p = buf;
-		q = buf + buflen;
-		while(p != q) {
-			hextmp[0] = hexdig[*p >> 4];
-			hextmp[1] = hexdig[*p & 0xf];
-			if(!io_ch(arg, hextmp, 2)) return -1;
-			p++;
-		}
-	}
-	return buflen << 1;
+    static const char hexdig[] = "0123456789ABCDEF";
+    unsigned char *p, *q;
+    char hextmp[2];
+    if (arg) {
+        p = buf;
+        q = buf + buflen;
+        while (p != q) {
+            hextmp[0] = hexdig[*p >> 4];
+            hextmp[1] = hexdig[*p & 0xf];
+            if (!io_ch(arg, hextmp, 2))
+                return -1;
+            p++;
+        }
+    }
+    return buflen << 1;
 }
 
-/* "dump" a string. This is done when the type is unknown,
- * or the flags request it. We can either dump the content
- * octets or the entire DER encoding. This uses the RFC2253
- * #01234 format.
+/*
+ * "dump" a string. This is done when the type is unknown, or the flags
+ * request it. We can either dump the content octets or the entire DER
+ * encoding. This uses the RFC2253 #01234 format.
  */
 
-static int do_dump(unsigned long lflags, char_io *io_ch, void *arg, ASN1_STRING *str)
+static int do_dump(unsigned long lflags, char_io *io_ch, void *arg,
+                   ASN1_STRING *str)
 {
-	/* Placing the ASN1_STRING in a temp ASN1_TYPE allows
-	 * the DER encoding to readily obtained
-	 */
-	ASN1_TYPE t;
-	unsigned char *der_buf, *p;
-	int outlen, der_len;
+    /*
+     * Placing the ASN1_STRING in a temp ASN1_TYPE allows the DER encoding to
+     * readily obtained
+     */
+    ASN1_TYPE t;
+    unsigned char *der_buf, *p;
+    int outlen, der_len;
 
-	if(!io_ch(arg, "#", 1)) return -1;
-	/* If we don't dump DER encoding just dump content octets */
-	if(!(lflags & ASN1_STRFLGS_DUMP_DER)) {
-		outlen = do_hex_dump(io_ch, arg, str->data, str->length);
-		if(outlen < 0) return -1;
-		return outlen + 1;
-	}
-	t.type = str->type;
-	t.value.ptr = (char *)str;
-	der_len = i2d_ASN1_TYPE(&t, NULL);
-	der_buf = OPENSSL_malloc(der_len);
-	if(!der_buf) return -1;
-	p = der_buf;
-	i2d_ASN1_TYPE(&t, &p);
-	outlen = do_hex_dump(io_ch, arg, der_buf, der_len);
-	OPENSSL_free(der_buf);
-	if(outlen < 0) return -1;
-	return outlen + 1;
+    if (!io_ch(arg, "#", 1))
+        return -1;
+    /* If we don't dump DER encoding just dump content octets */
+    if (!(lflags & ASN1_STRFLGS_DUMP_DER)) {
+        outlen = do_hex_dump(io_ch, arg, str->data, str->length);
+        if (outlen < 0)
+            return -1;
+        return outlen + 1;
+    }
+    t.type = str->type;
+    t.value.ptr = (char *)str;
+    der_len = i2d_ASN1_TYPE(&t, NULL);
+    der_buf = OPENSSL_malloc(der_len);
+    if (!der_buf)
+        return -1;
+    p = der_buf;
+    i2d_ASN1_TYPE(&t, &p);
+    outlen = do_hex_dump(io_ch, arg, der_buf, der_len);
+    OPENSSL_free(der_buf);
+    if (outlen < 0)
+        return -1;
+    return outlen + 1;
 }
 
-/* Lookup table to convert tags to character widths,
- * 0 = UTF8 encoded, -1 is used for non string types
- * otherwise it is the number of bytes per character
+/*
+ * Lookup table to convert tags to character widths, 0 = UTF8 encoded, -1 is
+ * used for non string types otherwise it is the number of bytes per
+ * character
  */
 
 static const signed char tag2nbyte[] = {
-	-1, -1, -1, -1, -1,	/* 0-4 */
-	-1, -1, -1, -1, -1,	/* 5-9 */
-	-1, -1, 0, -1,		/* 10-13 */
-	-1, -1, -1, -1,		/* 15-17 */
-	-1, 1, 1,		/* 18-20 */
-	-1, 1, 1, 1,		/* 21-24 */
-	-1, 1, -1,		/* 25-27 */
-	4, -1, 2		/* 28-30 */
+    -1, -1, -1, -1, -1,         /* 0-4 */
+    -1, -1, -1, -1, -1,         /* 5-9 */
+    -1, -1, 0, -1,              /* 10-13 */
+    -1, -1, -1, -1,             /* 15-17 */
+    1, 1, 1,                    /* 18-20 */
+    -1, 1, 1, 1,                /* 21-24 */
+    -1, 1, -1,                  /* 25-27 */
+    4, -1, 2                    /* 28-30 */
 };
 
-/* This is the main function, print out an
- * ASN1_STRING taking note of various escape
- * and display options. Returns number of
- * characters written or -1 if an error
- * occurred.
+/*
+ * This is the main function, print out an ASN1_STRING taking note of various
+ * escape and display options. Returns number of characters written or -1 if
+ * an error occurred.
  */
 
-static int do_print_ex(char_io *io_ch, void *arg, unsigned long lflags, ASN1_STRING *str)
+static int do_print_ex(char_io *io_ch, void *arg, unsigned long lflags,
+                       ASN1_STRING *str)
 {
-	int outlen, len;
-	int type;
-	char quotes;
-	unsigned char flags;
-	quotes = 0;
-	/* Keep a copy of escape flags */
-	flags = (unsigned char)(lflags & ESC_FLAGS);
+    int outlen, len;
+    int type;
+    char quotes;
+    unsigned char flags;
+    quotes = 0;
+    /* Keep a copy of escape flags */
+    flags = (unsigned char)(lflags & ESC_FLAGS);
 
-	type = str->type;
+    type = str->type;
 
-	outlen = 0;
+    outlen = 0;
 
+    if (lflags & ASN1_STRFLGS_SHOW_TYPE) {
+        const char *tagname;
+        tagname = ASN1_tag2str(type);
+        outlen += strlen(tagname);
+        if (!io_ch(arg, tagname, outlen) || !io_ch(arg, ":", 1))
+            return -1;
+        outlen++;
+    }
 
-	if(lflags & ASN1_STRFLGS_SHOW_TYPE) {
-		const char *tagname;
-		tagname = ASN1_tag2str(type);
-		outlen += strlen(tagname);
-		if(!io_ch(arg, tagname, outlen) || !io_ch(arg, ":", 1)) return -1; 
-		outlen++;
-	}
+    /* Decide what to do with type, either dump content or display it */
 
-	/* Decide what to do with type, either dump content or display it */
+    /* Dump everything */
+    if (lflags & ASN1_STRFLGS_DUMP_ALL)
+        type = -1;
+    /* Ignore the string type */
+    else if (lflags & ASN1_STRFLGS_IGNORE_TYPE)
+        type = 1;
+    else {
+        /* Else determine width based on type */
+        if ((type > 0) && (type < 31))
+            type = tag2nbyte[type];
+        else
+            type = -1;
+        if ((type == -1) && !(lflags & ASN1_STRFLGS_DUMP_UNKNOWN))
+            type = 1;
+    }
 
-	/* Dump everything */
-	if(lflags & ASN1_STRFLGS_DUMP_ALL) type = -1;
-	/* Ignore the string type */
-	else if(lflags & ASN1_STRFLGS_IGNORE_TYPE) type = 1;
-	else {
-		/* Else determine width based on type */
-		if((type > 0) && (type < 31)) type = tag2nbyte[type];
-		else type = -1;
-		if((type == -1) && !(lflags & ASN1_STRFLGS_DUMP_UNKNOWN)) type = 1;
-	}
+    if (type == -1) {
+        len = do_dump(lflags, io_ch, arg, str);
+        if (len < 0)
+            return -1;
+        outlen += len;
+        return outlen;
+    }
 
-	if(type == -1) {
-		len = do_dump(lflags, io_ch, arg, str);
-		if(len < 0) return -1;
-		outlen += len;
-		return outlen;
-	}
+    if (lflags & ASN1_STRFLGS_UTF8_CONVERT) {
+        /*
+         * Note: if string is UTF8 and we want to convert to UTF8 then we
+         * just interpret it as 1 byte per character to avoid converting
+         * twice.
+         */
+        if (!type)
+            type = 1;
+        else
+            type |= BUF_TYPE_CONVUTF8;
+    }
 
-	if(lflags & ASN1_STRFLGS_UTF8_CONVERT) {
-		/* Note: if string is UTF8 and we want
-		 * to convert to UTF8 then we just interpret
-		 * it as 1 byte per character to avoid converting
-		 * twice.
-		 */
-		if(!type) type = 1;
-		else type |= BUF_TYPE_CONVUTF8;
-	}
-
-	len = do_buf(str->data, str->length, type, flags, &quotes, io_ch, NULL);
-	if(len < 0) return -1;
-	outlen += len;
-	if(quotes) outlen += 2;
-	if(!arg) return outlen;
-	if(quotes && !io_ch(arg, "\"", 1)) return -1;
-	if(do_buf(str->data, str->length, type, flags, NULL, io_ch, arg) < 0)
-		return -1;
-	if(quotes && !io_ch(arg, "\"", 1)) return -1;
-	return outlen;
+    len = do_buf(str->data, str->length, type, flags, &quotes, io_ch, NULL);
+    if (len < 0)
+        return -1;
+    outlen += len;
+    if (quotes)
+        outlen += 2;
+    if (!arg)
+        return outlen;
+    if (quotes && !io_ch(arg, "\"", 1))
+        return -1;
+    if (do_buf(str->data, str->length, type, flags, NULL, io_ch, arg) < 0)
+        return -1;
+    if (quotes && !io_ch(arg, "\"", 1))
+        return -1;
+    return outlen;
 }
 
 /* Used for line indenting: print 'indent' spaces */
 
 static int do_indent(char_io *io_ch, void *arg, int indent)
 {
-	int i;
-	for(i = 0; i < indent; i++)
-			if(!io_ch(arg, " ", 1)) return 0;
-	return 1;
+    int i;
+    for (i = 0; i < indent; i++)
+        if (!io_ch(arg, " ", 1))
+            return 0;
+    return 1;
 }
 
-#define FN_WIDTH_LN	25
-#define FN_WIDTH_SN	10
+#define FN_WIDTH_LN     25
+#define FN_WIDTH_SN     10
 
 static int do_name_ex(char_io *io_ch, void *arg, X509_NAME *n,
-				int indent, unsigned long flags)
+                      int indent, unsigned long flags)
 {
-	int i, prev = -1, orflags, cnt;
-	int fn_opt, fn_nid;
-	ASN1_OBJECT *fn;
-	ASN1_STRING *val;
-	X509_NAME_ENTRY *ent;
-	char objtmp[80];
-	const char *objbuf;
-	int outlen, len;
-	const char *sep_dn, *sep_mv, *sep_eq;
-	int sep_dn_len, sep_mv_len, sep_eq_len;
-	if(indent < 0) indent = 0;
-	outlen = indent;
-	if(!do_indent(io_ch, arg, indent)) return -1;
-	switch (flags & XN_FLAG_SEP_MASK)
-	{
-		case XN_FLAG_SEP_MULTILINE:
-		sep_dn = "\n";
-		sep_dn_len = 1;
-		sep_mv = " + ";
-		sep_mv_len = 3;
-		break;
+    int i, prev = -1, orflags, cnt;
+    int fn_opt, fn_nid;
+    ASN1_OBJECT *fn;
+    ASN1_STRING *val;
+    X509_NAME_ENTRY *ent;
+    char objtmp[80];
+    const char *objbuf;
+    int outlen, len;
+    const char *sep_dn, *sep_mv, *sep_eq;
+    int sep_dn_len, sep_mv_len, sep_eq_len;
+    if (indent < 0)
+        indent = 0;
+    outlen = indent;
+    if (!do_indent(io_ch, arg, indent))
+        return -1;
+    switch (flags & XN_FLAG_SEP_MASK) {
+    case XN_FLAG_SEP_MULTILINE:
+        sep_dn = "\n";
+        sep_dn_len = 1;
+        sep_mv = " + ";
+        sep_mv_len = 3;
+        break;
 
-		case XN_FLAG_SEP_COMMA_PLUS:
-		sep_dn = ",";
-		sep_dn_len = 1;
-		sep_mv = "+";
-		sep_mv_len = 1;
-		indent = 0;
-		break;
+    case XN_FLAG_SEP_COMMA_PLUS:
+        sep_dn = ",";
+        sep_dn_len = 1;
+        sep_mv = "+";
+        sep_mv_len = 1;
+        indent = 0;
+        break;
 
-		case XN_FLAG_SEP_CPLUS_SPC:
-		sep_dn = ", ";
-		sep_dn_len = 2;
-		sep_mv = " + ";
-		sep_mv_len = 3;
-		indent = 0;
-		break;
+    case XN_FLAG_SEP_CPLUS_SPC:
+        sep_dn = ", ";
+        sep_dn_len = 2;
+        sep_mv = " + ";
+        sep_mv_len = 3;
+        indent = 0;
+        break;
 
-		case XN_FLAG_SEP_SPLUS_SPC:
-		sep_dn = "; ";
-		sep_dn_len = 2;
-		sep_mv = " + ";
-		sep_mv_len = 3;
-		indent = 0;
-		break;
+    case XN_FLAG_SEP_SPLUS_SPC:
+        sep_dn = "; ";
+        sep_dn_len = 2;
+        sep_mv = " + ";
+        sep_mv_len = 3;
+        indent = 0;
+        break;
 
-		default:
-		return -1;
-	}
+    default:
+        return -1;
+    }
 
-	if(flags & XN_FLAG_SPC_EQ) {
-		sep_eq = " = ";
-		sep_eq_len = 3;
-	} else {
-		sep_eq = "=";
-		sep_eq_len = 1;
-	}
+    if (flags & XN_FLAG_SPC_EQ) {
+        sep_eq = " = ";
+        sep_eq_len = 3;
+    } else {
+        sep_eq = "=";
+        sep_eq_len = 1;
+    }
 
-	fn_opt = flags & XN_FLAG_FN_MASK;
+    fn_opt = flags & XN_FLAG_FN_MASK;
 
-	cnt = X509_NAME_entry_count(n);	
-	for(i = 0; i < cnt; i++) {
-		if(flags & XN_FLAG_DN_REV)
-				ent = X509_NAME_get_entry(n, cnt - i - 1);
-		else ent = X509_NAME_get_entry(n, i);
-		if(prev != -1) {
-			if(prev == ent->set) {
-				if(!io_ch(arg, sep_mv, sep_mv_len)) return -1;
-				outlen += sep_mv_len;
-			} else {
-				if(!io_ch(arg, sep_dn, sep_dn_len)) return -1;
-				outlen += sep_dn_len;
-				if(!do_indent(io_ch, arg, indent)) return -1;
-				outlen += indent;
-			}
-		}
-		prev = ent->set;
-		fn = X509_NAME_ENTRY_get_object(ent);
-		val = X509_NAME_ENTRY_get_data(ent);
-		fn_nid = OBJ_obj2nid(fn);
-		if(fn_opt != XN_FLAG_FN_NONE) {
-			int objlen, fld_len;
-			if((fn_opt == XN_FLAG_FN_OID) || (fn_nid==NID_undef) ) {
-				OBJ_obj2txt(objtmp, sizeof objtmp, fn, 1);
-				fld_len = 0; /* XXX: what should this be? */
-				objbuf = objtmp;
-			} else {
-				if(fn_opt == XN_FLAG_FN_SN) {
-					fld_len = FN_WIDTH_SN;
-					objbuf = OBJ_nid2sn(fn_nid);
-				} else if(fn_opt == XN_FLAG_FN_LN) {
-					fld_len = FN_WIDTH_LN;
-					objbuf = OBJ_nid2ln(fn_nid);
-				} else {
-					fld_len = 0; /* XXX: what should this be? */
-					objbuf = "";
-				}
-			}
-			objlen = strlen(objbuf);
-			if(!io_ch(arg, objbuf, objlen)) return -1;
-			if ((objlen < fld_len) && (flags & XN_FLAG_FN_ALIGN)) {
-				if (!do_indent(io_ch, arg, fld_len - objlen)) return -1;
-				outlen += fld_len - objlen;
-			}
-			if(!io_ch(arg, sep_eq, sep_eq_len)) return -1;
-			outlen += objlen + sep_eq_len;
-		}
-		/* If the field name is unknown then fix up the DER dump
-		 * flag. We might want to limit this further so it will
- 		 * DER dump on anything other than a few 'standard' fields.
-		 */
-		if((fn_nid == NID_undef) && (flags & XN_FLAG_DUMP_UNKNOWN_FIELDS)) 
-					orflags = ASN1_STRFLGS_DUMP_ALL;
-		else orflags = 0;
-     
-		len = do_print_ex(io_ch, arg, flags | orflags, val);
-		if(len < 0) return -1;
-		outlen += len;
-	}
-	return outlen;
+    cnt = X509_NAME_entry_count(n);
+    for (i = 0; i < cnt; i++) {
+        if (flags & XN_FLAG_DN_REV)
+            ent = X509_NAME_get_entry(n, cnt - i - 1);
+        else
+            ent = X509_NAME_get_entry(n, i);
+        if (prev != -1) {
+            if (prev == ent->set) {
+                if (!io_ch(arg, sep_mv, sep_mv_len))
+                    return -1;
+                outlen += sep_mv_len;
+            } else {
+                if (!io_ch(arg, sep_dn, sep_dn_len))
+                    return -1;
+                outlen += sep_dn_len;
+                if (!do_indent(io_ch, arg, indent))
+                    return -1;
+                outlen += indent;
+            }
+        }
+        prev = ent->set;
+        fn = X509_NAME_ENTRY_get_object(ent);
+        val = X509_NAME_ENTRY_get_data(ent);
+        fn_nid = OBJ_obj2nid(fn);
+        if (fn_opt != XN_FLAG_FN_NONE) {
+            int objlen, fld_len;
+            if ((fn_opt == XN_FLAG_FN_OID) || (fn_nid == NID_undef)) {
+                OBJ_obj2txt(objtmp, sizeof objtmp, fn, 1);
+                fld_len = 0;    /* XXX: what should this be? */
+                objbuf = objtmp;
+            } else {
+                if (fn_opt == XN_FLAG_FN_SN) {
+                    fld_len = FN_WIDTH_SN;
+                    objbuf = OBJ_nid2sn(fn_nid);
+                } else if (fn_opt == XN_FLAG_FN_LN) {
+                    fld_len = FN_WIDTH_LN;
+                    objbuf = OBJ_nid2ln(fn_nid);
+                } else {
+                    fld_len = 0; /* XXX: what should this be? */
+                    objbuf = "";
+                }
+            }
+            objlen = strlen(objbuf);
+            if (!io_ch(arg, objbuf, objlen))
+                return -1;
+            if ((objlen < fld_len) && (flags & XN_FLAG_FN_ALIGN)) {
+                if (!do_indent(io_ch, arg, fld_len - objlen))
+                    return -1;
+                outlen += fld_len - objlen;
+            }
+            if (!io_ch(arg, sep_eq, sep_eq_len))
+                return -1;
+            outlen += objlen + sep_eq_len;
+        }
+        /*
+         * If the field name is unknown then fix up the DER dump flag. We
+         * might want to limit this further so it will DER dump on anything
+         * other than a few 'standard' fields.
+         */
+        if ((fn_nid == NID_undef) && (flags & XN_FLAG_DUMP_UNKNOWN_FIELDS))
+            orflags = ASN1_STRFLGS_DUMP_ALL;
+        else
+            orflags = 0;
+
+        len = do_print_ex(io_ch, arg, flags | orflags, val);
+        if (len < 0)
+            return -1;
+        outlen += len;
+    }
+    return outlen;
 }
 
 /* Wrappers round the main functions */
 
-int X509_NAME_print_ex(BIO *out, X509_NAME *nm, int indent, unsigned long flags)
+int X509_NAME_print_ex(BIO *out, X509_NAME *nm, int indent,
+                       unsigned long flags)
 {
-	if(flags == XN_FLAG_COMPAT)
-		return X509_NAME_print(out, nm, indent);
-	return do_name_ex(send_bio_chars, out, nm, indent, flags);
+    if (flags == XN_FLAG_COMPAT)
+        return X509_NAME_print(out, nm, indent);
+    return do_name_ex(send_bio_chars, out, nm, indent, flags);
 }
 
 #ifndef OPENSSL_NO_FP_API
-int X509_NAME_print_ex_fp(FILE *fp, X509_NAME *nm, int indent, unsigned long flags)
+int X509_NAME_print_ex_fp(FILE *fp, X509_NAME *nm, int indent,
+                          unsigned long flags)
 {
-	if(flags == XN_FLAG_COMPAT)
-		{
-		BIO *btmp;
-		int ret;
-		btmp = BIO_new_fp(fp, BIO_NOCLOSE);
-		if(!btmp) return -1;
-		ret = X509_NAME_print(btmp, nm, indent);
-		BIO_free(btmp);
-		return ret;
-		}
-	return do_name_ex(send_fp_chars, fp, nm, indent, flags);
+    if (flags == XN_FLAG_COMPAT) {
+        BIO *btmp;
+        int ret;
+        btmp = BIO_new_fp(fp, BIO_NOCLOSE);
+        if (!btmp)
+            return -1;
+        ret = X509_NAME_print(btmp, nm, indent);
+        BIO_free(btmp);
+        return ret;
+    }
+    return do_name_ex(send_fp_chars, fp, nm, indent, flags);
 }
 #endif
 
 int ASN1_STRING_print_ex(BIO *out, ASN1_STRING *str, unsigned long flags)
 {
-	return do_print_ex(send_bio_chars, out, flags, str);
+    return do_print_ex(send_bio_chars, out, flags, str);
 }
 
 #ifndef OPENSSL_NO_FP_API
 int ASN1_STRING_print_ex_fp(FILE *fp, ASN1_STRING *str, unsigned long flags)
 {
-	return do_print_ex(send_fp_chars, fp, flags, str);
+    return do_print_ex(send_fp_chars, fp, flags, str);
 }
 #endif
 
-/* Utility function: convert any string type to UTF8, returns number of bytes
+/*
+ * Utility function: convert any string type to UTF8, returns number of bytes
  * in output string or a negative error code
  */
 
 int ASN1_STRING_to_UTF8(unsigned char **out, ASN1_STRING *in)
 {
-	ASN1_STRING stmp, *str = &stmp;
-	int mbflag, type, ret;
-	if(!in) return -1;
-	type = in->type;
-	if((type < 0) || (type > 30)) return -1;
-	mbflag = tag2nbyte[type];
-	if(mbflag == -1) return -1;
-	mbflag |= MBSTRING_FLAG;
-	stmp.data = NULL;
-	stmp.length = 0;
-	stmp.flags = 0;
-	ret = ASN1_mbstring_copy(&str, in->data, in->length, mbflag, B_ASN1_UTF8STRING);
-	if(ret < 0) return ret;
-	*out = stmp.data;
-	return stmp.length;
+    ASN1_STRING stmp, *str = &stmp;
+    int mbflag, type, ret;
+    if (!in)
+        return -1;
+    type = in->type;
+    if ((type < 0) || (type > 30))
+        return -1;
+    mbflag = tag2nbyte[type];
+    if (mbflag == -1)
+        return -1;
+    mbflag |= MBSTRING_FLAG;
+    stmp.data = NULL;
+    stmp.length = 0;
+    stmp.flags = 0;
+    ret =
+        ASN1_mbstring_copy(&str, in->data, in->length, mbflag,
+                           B_ASN1_UTF8STRING);
+    if (ret < 0)
+        return ret;
+    *out = stmp.data;
+    return stmp.length;
 }
diff --git a/src/crypto/x509/a_verify.c b/src/crypto/x509/a_verify.c
index 572a139..0af4197 100644
--- a/src/crypto/x509/a_verify.c
+++ b/src/crypto/x509/a_verify.c
@@ -68,66 +68,60 @@
 #include <openssl/mem.h>
 #include <openssl/obj.h>
 
-#include "../evp/internal.h"
-
+#include "internal.h"
 
 int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a,
-		ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey)
-	{
-	EVP_MD_CTX ctx;
-	uint8_t *buf_in = NULL;
-	int ret = 0, inl;
+                     ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey)
+{
+    EVP_MD_CTX ctx;
+    uint8_t *buf_in = NULL;
+    int ret = 0, inl;
 
-	if (!pkey)
-		{
-		OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER);
-		return 0;
-		}
+    if (!pkey) {
+        OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER);
+        return 0;
+    }
 
-	if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7)
-		{
-		OPENSSL_PUT_ERROR(X509, X509_R_INVALID_BIT_STRING_BITS_LEFT);
-		return 0;
-		}
+    if (signature->type == V_ASN1_BIT_STRING && signature->flags & 0x7) {
+        OPENSSL_PUT_ERROR(X509, X509_R_INVALID_BIT_STRING_BITS_LEFT);
+        return 0;
+    }
 
-	EVP_MD_CTX_init(&ctx);
+    EVP_MD_CTX_init(&ctx);
 
-	if (!EVP_DigestVerifyInitFromAlgorithm(&ctx, a, pkey))
-		{
-		goto err;
-		}
+    if (!x509_digest_verify_init(&ctx, a, pkey)) {
+        goto err;
+    }
 
-	inl = ASN1_item_i2d(asn, &buf_in, it);
-	
-	if (buf_in == NULL)
-		{
-		OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-		goto err;
-		}
+    inl = ASN1_item_i2d(asn, &buf_in, it);
 
-	if (!EVP_DigestVerifyUpdate(&ctx,buf_in,inl))
-		{
-		OPENSSL_cleanse(buf_in,(unsigned int)inl);
-		OPENSSL_free(buf_in);
-		OPENSSL_PUT_ERROR(X509, ERR_R_EVP_LIB);
-		goto err;
-		}
+    if (buf_in == NULL) {
+        OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
 
-	OPENSSL_cleanse(buf_in,(unsigned int)inl);
-	OPENSSL_free(buf_in);
+    if (!EVP_DigestVerifyUpdate(&ctx, buf_in, inl)) {
+        OPENSSL_cleanse(buf_in, (unsigned int)inl);
+        OPENSSL_free(buf_in);
+        OPENSSL_PUT_ERROR(X509, ERR_R_EVP_LIB);
+        goto err;
+    }
 
-	if (EVP_DigestVerifyFinal(&ctx,signature->data,
-			(size_t)signature->length) <= 0)
-		{
-		OPENSSL_PUT_ERROR(X509, ERR_R_EVP_LIB);
-		goto err;
-		}
-	/* we don't need to zero the 'ctx' because we just checked
-	 * public information */
-	/* memset(&ctx,0,sizeof(ctx)); */
-	ret = 1;
-err:
-	EVP_MD_CTX_cleanup(&ctx);
-	return ret;
-	}
+    OPENSSL_cleanse(buf_in, (unsigned int)inl);
+    OPENSSL_free(buf_in);
 
+    if (EVP_DigestVerifyFinal(&ctx, signature->data,
+                              (size_t)signature->length) <= 0) {
+        OPENSSL_PUT_ERROR(X509, ERR_R_EVP_LIB);
+        goto err;
+    }
+    /*
+     * we don't need to zero the 'ctx' because we just checked public
+     * information
+     */
+    /* OPENSSL_memset(&ctx,0,sizeof(ctx)); */
+    ret = 1;
+ err:
+    EVP_MD_CTX_cleanup(&ctx);
+    return ret;
+}
diff --git a/src/crypto/evp/algorithm.c b/src/crypto/x509/algorithm.c
similarity index 67%
rename from src/crypto/evp/algorithm.c
rename to src/crypto/x509/algorithm.c
index 63bc77a..78ae882 100644
--- a/src/crypto/evp/algorithm.c
+++ b/src/crypto/x509/algorithm.c
@@ -54,100 +54,84 @@
  * copied and put under another distribution licence
  * [including the GNU Public Licence.] */
 
-#include <openssl/evp.h>
-
-#include <assert.h>
+#include <openssl/x509.h>
 
 #include <openssl/asn1.h>
+#include <openssl/digest.h>
 #include <openssl/err.h>
+#include <openssl/evp.h>
 #include <openssl/obj.h>
-#include <openssl/x509.h>
 
 #include "internal.h"
 
 
-int EVP_DigestSignAlgorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor) {
-  const EVP_MD *digest;
-  EVP_PKEY *pkey;
-  int sign_nid, paramtype;
-
-  digest = EVP_MD_CTX_md(ctx);
-  pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);
-  if (!digest || !pkey) {
-    OPENSSL_PUT_ERROR(EVP, EVP_R_CONTEXT_NOT_INITIALISED);
+int x509_digest_sign_algorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor) {
+  const EVP_MD *digest = EVP_MD_CTX_md(ctx);
+  EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx);
+  if (digest == NULL || pkey == NULL) {
+    OPENSSL_PUT_ERROR(ASN1, ASN1_R_CONTEXT_NOT_INITIALISED);
     return 0;
   }
 
-  if (pkey->ameth->digest_sign_algorithm) {
-    switch (pkey->ameth->digest_sign_algorithm(ctx, algor)) {
-      case EVP_DIGEST_SIGN_ALGORITHM_ERROR:
-        return 0;
-      case EVP_DIGEST_SIGN_ALGORITHM_SUCCESS:
-        return 1;
-      case EVP_DIGEST_SIGN_ALGORITHM_DEFAULT:
-        /* Use default behavior. */
-        break;
-      default:
-        assert(0);
+  if (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) {
+    int pad_mode;
+    if (!EVP_PKEY_CTX_get_rsa_padding(ctx->pctx, &pad_mode)) {
+      return 0;
+    }
+    /* RSA-PSS has special signature algorithm logic. */
+    if (pad_mode == RSA_PKCS1_PSS_PADDING) {
+      return x509_rsa_ctx_to_pss(ctx, algor);
     }
   }
 
   /* Default behavior: look up the OID for the algorithm/hash pair and encode
    * that. */
+  int sign_nid;
   if (!OBJ_find_sigid_by_algs(&sign_nid, EVP_MD_type(digest),
-                              pkey->ameth->pkey_id)) {
-    OPENSSL_PUT_ERROR(EVP, EVP_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
+                              EVP_PKEY_id(pkey))) {
+    OPENSSL_PUT_ERROR(ASN1, ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED);
     return 0;
   }
 
-  if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL) {
-    paramtype = V_ASN1_NULL;
-  } else {
-    paramtype = V_ASN1_UNDEF;
-  }
-
+  /* RSA signature algorithms include an explicit NULL parameter. Others omit
+   * it. */
+  int paramtype =
+      (EVP_PKEY_id(pkey) == EVP_PKEY_RSA) ? V_ASN1_NULL : V_ASN1_UNDEF;
   X509_ALGOR_set0(algor, OBJ_nid2obj(sign_nid), paramtype, NULL);
   return 1;
 }
 
-int EVP_DigestVerifyInitFromAlgorithm(EVP_MD_CTX *ctx,
-                                      X509_ALGOR *algor,
-                                      EVP_PKEY *pkey) {
+int x509_digest_verify_init(EVP_MD_CTX *ctx, X509_ALGOR *sigalg,
+                            EVP_PKEY *pkey) {
+  /* Convert the signature OID into digest and public key OIDs. */
+  int sigalg_nid = OBJ_obj2nid(sigalg->algorithm);
   int digest_nid, pkey_nid;
-  const EVP_PKEY_ASN1_METHOD *ameth;
-  const EVP_MD *digest;
-
-  /* Convert signature OID into digest and public key OIDs */
-  if (!OBJ_find_sigid_algs(OBJ_obj2nid(algor->algorithm), &digest_nid,
-                           &pkey_nid)) {
-    OPENSSL_PUT_ERROR(EVP, EVP_R_UNKNOWN_SIGNATURE_ALGORITHM);
+  if (!OBJ_find_sigid_algs(sigalg_nid, &digest_nid, &pkey_nid)) {
+    OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
     return 0;
   }
 
-  /* Check public key OID matches public key type */
-  ameth = EVP_PKEY_asn1_find(NULL, pkey_nid);
-  if (ameth == NULL || ameth->pkey_id != pkey->ameth->pkey_id) {
-    OPENSSL_PUT_ERROR(EVP, EVP_R_WRONG_PUBLIC_KEY_TYPE);
+  /* Check the public key OID matches the public key type. */
+  if (pkey_nid != EVP_PKEY_id(pkey)) {
+    OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_PUBLIC_KEY_TYPE);
     return 0;
   }
 
   /* NID_undef signals that there are custom parameters to set. */
   if (digest_nid == NID_undef) {
-    if (!pkey->ameth || !pkey->ameth->digest_verify_init_from_algorithm) {
-      OPENSSL_PUT_ERROR(EVP, EVP_R_UNKNOWN_SIGNATURE_ALGORITHM);
+    if (sigalg_nid != NID_rsassaPss) {
+      OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM);
       return 0;
     }
-
-    return pkey->ameth->digest_verify_init_from_algorithm(ctx, algor, pkey);
+    return x509_rsa_pss_to_ctx(ctx, sigalg, pkey);
   }
 
   /* Otherwise, initialize with the digest from the OID. */
-  digest = EVP_get_digestbynid(digest_nid);
+  const EVP_MD *digest = EVP_get_digestbynid(digest_nid);
   if (digest == NULL) {
-    OPENSSL_PUT_ERROR(EVP, EVP_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
+    OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
     return 0;
   }
 
   return EVP_DigestVerifyInit(ctx, NULL, digest, NULL, pkey);
 }
-
diff --git a/src/crypto/x509/asn1_gen.c b/src/crypto/x509/asn1_gen.c
index 850a816..c52a1ac 100644
--- a/src/crypto/x509/asn1_gen.c
+++ b/src/crypto/x509/asn1_gen.c
@@ -66,808 +66,753 @@
 
 #include "../internal.h"
 
+/*
+ * Although this file is in crypto/x509 for layering purposes, it emits
+ * errors from the ASN.1 module for OpenSSL compatibility.
+ */
 
-/* Although this file is in crypto/x509 for layering purposes, it emits errors
- * from the ASN.1 module for OpenSSL compatibility. */
+#define ASN1_GEN_FLAG           0x10000
+#define ASN1_GEN_FLAG_IMP       (ASN1_GEN_FLAG|1)
+#define ASN1_GEN_FLAG_EXP       (ASN1_GEN_FLAG|2)
+#define ASN1_GEN_FLAG_TAG       (ASN1_GEN_FLAG|3)
+#define ASN1_GEN_FLAG_BITWRAP   (ASN1_GEN_FLAG|4)
+#define ASN1_GEN_FLAG_OCTWRAP   (ASN1_GEN_FLAG|5)
+#define ASN1_GEN_FLAG_SEQWRAP   (ASN1_GEN_FLAG|6)
+#define ASN1_GEN_FLAG_SETWRAP   (ASN1_GEN_FLAG|7)
+#define ASN1_GEN_FLAG_FORMAT    (ASN1_GEN_FLAG|8)
 
-#define ASN1_GEN_FLAG		0x10000
-#define ASN1_GEN_FLAG_IMP	(ASN1_GEN_FLAG|1)
-#define ASN1_GEN_FLAG_EXP	(ASN1_GEN_FLAG|2)
-#define ASN1_GEN_FLAG_TAG	(ASN1_GEN_FLAG|3)
-#define ASN1_GEN_FLAG_BITWRAP	(ASN1_GEN_FLAG|4)
-#define ASN1_GEN_FLAG_OCTWRAP	(ASN1_GEN_FLAG|5)
-#define ASN1_GEN_FLAG_SEQWRAP	(ASN1_GEN_FLAG|6)
-#define ASN1_GEN_FLAG_SETWRAP	(ASN1_GEN_FLAG|7)
-#define ASN1_GEN_FLAG_FORMAT	(ASN1_GEN_FLAG|8)
+#define ASN1_GEN_STR(str,val)   {str, sizeof(str) - 1, val}
 
-#define ASN1_GEN_STR(str,val)	{str, sizeof(str) - 1, val}
-
-#define ASN1_FLAG_EXP_MAX	20
+#define ASN1_FLAG_EXP_MAX       20
 
 /* Input formats */
 
 /* ASCII: default */
-#define ASN1_GEN_FORMAT_ASCII	1
+#define ASN1_GEN_FORMAT_ASCII   1
 /* UTF8 */
-#define ASN1_GEN_FORMAT_UTF8	2
+#define ASN1_GEN_FORMAT_UTF8    2
 /* Hex */
-#define ASN1_GEN_FORMAT_HEX	3
+#define ASN1_GEN_FORMAT_HEX     3
 /* List of bits */
-#define ASN1_GEN_FORMAT_BITLIST	4
+#define ASN1_GEN_FORMAT_BITLIST 4
 
+struct tag_name_st {
+    const char *strnam;
+    int len;
+    int tag;
+};
 
-struct tag_name_st
-	{
-	const char *strnam;
-	int len;
-	int tag;
-	};
+typedef struct {
+    int exp_tag;
+    int exp_class;
+    int exp_constructed;
+    int exp_pad;
+    long exp_len;
+} tag_exp_type;
 
-typedef struct
-	{
-	int exp_tag;
-	int exp_class;
-	int exp_constructed;
-	int exp_pad;
-	long exp_len;
-	} tag_exp_type;
-
-typedef struct
-	{
-	int imp_tag;
-	int imp_class;
-	int utype;
-	int format;
-	const char *str;
-	tag_exp_type exp_list[ASN1_FLAG_EXP_MAX];
-	int exp_count;
-	} tag_exp_arg;
+typedef struct {
+    int imp_tag;
+    int imp_class;
+    int utype;
+    int format;
+    const char *str;
+    tag_exp_type exp_list[ASN1_FLAG_EXP_MAX];
+    int exp_count;
+} tag_exp_arg;
 
 static int bitstr_cb(const char *elem, int len, void *bitstr);
 static int asn1_cb(const char *elem, int len, void *bitstr);
-static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class, int exp_constructed, int exp_pad, int imp_ok);
-static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass);
+static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class,
+                      int exp_constructed, int exp_pad, int imp_ok);
+static int parse_tagging(const char *vstart, int vlen, int *ptag,
+                         int *pclass);
 static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf);
 static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype);
 static int asn1_str2tag(const char *tagstr, int len);
 
 ASN1_TYPE *ASN1_generate_nconf(char *str, CONF *nconf)
-	{
-	X509V3_CTX cnf;
+{
+    X509V3_CTX cnf;
 
-	if (!nconf)
-		return ASN1_generate_v3(str, NULL);
+    if (!nconf)
+        return ASN1_generate_v3(str, NULL);
 
-	X509V3_set_nconf(&cnf, nconf);
-	return ASN1_generate_v3(str, &cnf);
-	}
+    X509V3_set_nconf(&cnf, nconf);
+    return ASN1_generate_v3(str, &cnf);
+}
 
 ASN1_TYPE *ASN1_generate_v3(char *str, X509V3_CTX *cnf)
-                            OPENSSL_SUPPRESS_POTENTIALLY_UNINITIALIZED_WARNINGS
-	{
-	ASN1_TYPE *ret;
-	tag_exp_arg asn1_tags;
-	tag_exp_type *etmp;
+{
+    ASN1_TYPE *ret;
+    tag_exp_arg asn1_tags;
+    tag_exp_type *etmp;
 
-	int i, len;
+    int i, len;
 
-	unsigned char *orig_der = NULL, *new_der = NULL;
-	const unsigned char *cpy_start;
-	unsigned char *p;
-	const unsigned char *cp;
-	int cpy_len;
-	long hdr_len;
-	int hdr_constructed = 0, hdr_tag, hdr_class;
-	int r;
+    unsigned char *orig_der = NULL, *new_der = NULL;
+    const unsigned char *cpy_start;
+    unsigned char *p;
+    const unsigned char *cp;
+    int cpy_len;
+    long hdr_len = 0;
+    int hdr_constructed = 0, hdr_tag, hdr_class;
+    int r;
 
-	asn1_tags.imp_tag = -1;
-	asn1_tags.imp_class = -1;
-	asn1_tags.format = ASN1_GEN_FORMAT_ASCII;
-	asn1_tags.exp_count = 0;
-	if (CONF_parse_list(str, ',', 1, asn1_cb, &asn1_tags) != 0)
-		return NULL;
+    asn1_tags.imp_tag = -1;
+    asn1_tags.imp_class = -1;
+    asn1_tags.format = ASN1_GEN_FORMAT_ASCII;
+    asn1_tags.exp_count = 0;
+    if (CONF_parse_list(str, ',', 1, asn1_cb, &asn1_tags) != 0)
+        return NULL;
 
-	if ((asn1_tags.utype == V_ASN1_SEQUENCE) || (asn1_tags.utype == V_ASN1_SET))
-		{
-		if (!cnf)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG);
-			return NULL;
-			}
-		ret = asn1_multi(asn1_tags.utype, asn1_tags.str, cnf);
-		}
-	else
-		ret = asn1_str2type(asn1_tags.str, asn1_tags.format, asn1_tags.utype);
+    if ((asn1_tags.utype == V_ASN1_SEQUENCE)
+        || (asn1_tags.utype == V_ASN1_SET)) {
+        if (!cnf) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG);
+            return NULL;
+        }
+        ret = asn1_multi(asn1_tags.utype, asn1_tags.str, cnf);
+    } else
+        ret = asn1_str2type(asn1_tags.str, asn1_tags.format, asn1_tags.utype);
 
-	if (!ret)
-		return NULL;
+    if (!ret)
+        return NULL;
 
-	/* If no tagging return base type */
-	if ((asn1_tags.imp_tag == -1) && (asn1_tags.exp_count == 0))
-		return ret;
+    /* If no tagging return base type */
+    if ((asn1_tags.imp_tag == -1) && (asn1_tags.exp_count == 0))
+        return ret;
 
-	/* Generate the encoding */
-	cpy_len = i2d_ASN1_TYPE(ret, &orig_der);
-	ASN1_TYPE_free(ret);
-	ret = NULL;
-	/* Set point to start copying for modified encoding */
-	cpy_start = orig_der;
+    /* Generate the encoding */
+    cpy_len = i2d_ASN1_TYPE(ret, &orig_der);
+    ASN1_TYPE_free(ret);
+    ret = NULL;
+    /* Set point to start copying for modified encoding */
+    cpy_start = orig_der;
 
-	/* Do we need IMPLICIT tagging? */
-	if (asn1_tags.imp_tag != -1)
-		{
-		/* If IMPLICIT we will replace the underlying tag */
-		/* Skip existing tag+len */
-		r = ASN1_get_object(&cpy_start, &hdr_len, &hdr_tag, &hdr_class, cpy_len);
-		if (r & 0x80)
-			goto err;
-		/* Update copy length */
-		cpy_len -= cpy_start - orig_der;
-		/* For IMPLICIT tagging the length should match the
-		 * original length and constructed flag should be
-		 * consistent.
-		 */
-		if (r & 0x1)
-			{
-			/* Indefinite length constructed */
-			hdr_constructed = 2;
-			hdr_len = 0;
-			}
-		else
-			/* Just retain constructed flag */
-			hdr_constructed = r & V_ASN1_CONSTRUCTED;
-		/* Work out new length with IMPLICIT tag: ignore constructed
-		 * because it will mess up if indefinite length
-		 */
-		len = ASN1_object_size(0, hdr_len, asn1_tags.imp_tag);
-		}
-	else
-		len = cpy_len;
+    /* Do we need IMPLICIT tagging? */
+    if (asn1_tags.imp_tag != -1) {
+        /* If IMPLICIT we will replace the underlying tag */
+        /* Skip existing tag+len */
+        r = ASN1_get_object(&cpy_start, &hdr_len, &hdr_tag, &hdr_class,
+                            cpy_len);
+        if (r & 0x80)
+            goto err;
+        /* Update copy length */
+        cpy_len -= cpy_start - orig_der;
+        /*
+         * For IMPLICIT tagging the length should match the original length
+         * and constructed flag should be consistent.
+         */
+        if (r & 0x1) {
+            /* Indefinite length constructed */
+            hdr_constructed = 2;
+            hdr_len = 0;
+        } else
+            /* Just retain constructed flag */
+            hdr_constructed = r & V_ASN1_CONSTRUCTED;
+        /*
+         * Work out new length with IMPLICIT tag: ignore constructed because
+         * it will mess up if indefinite length
+         */
+        len = ASN1_object_size(0, hdr_len, asn1_tags.imp_tag);
+    } else
+        len = cpy_len;
 
-	/* Work out length in any EXPLICIT, starting from end */
+    /* Work out length in any EXPLICIT, starting from end */
 
-	for(i = 0, etmp = asn1_tags.exp_list + asn1_tags.exp_count - 1; i < asn1_tags.exp_count; i++, etmp--)
-		{
-		/* Content length: number of content octets + any padding */
-		len += etmp->exp_pad;
-		etmp->exp_len = len;
-		/* Total object length: length including new header */
-		len = ASN1_object_size(0, len, etmp->exp_tag);
-		}
+    for (i = 0, etmp = asn1_tags.exp_list + asn1_tags.exp_count - 1;
+         i < asn1_tags.exp_count; i++, etmp--) {
+        /* Content length: number of content octets + any padding */
+        len += etmp->exp_pad;
+        etmp->exp_len = len;
+        /* Total object length: length including new header */
+        len = ASN1_object_size(0, len, etmp->exp_tag);
+    }
 
-	/* Allocate buffer for new encoding */
+    /* Allocate buffer for new encoding */
 
-	new_der = OPENSSL_malloc(len);
-	if (!new_der)
-		goto err;
+    new_der = OPENSSL_malloc(len);
+    if (!new_der)
+        goto err;
 
-	/* Generate tagged encoding */
+    /* Generate tagged encoding */
 
-	p = new_der;
+    p = new_der;
 
-	/* Output explicit tags first */
+    /* Output explicit tags first */
 
-	for (i = 0, etmp = asn1_tags.exp_list; i < asn1_tags.exp_count; i++, etmp++)
-		{
-		ASN1_put_object(&p, etmp->exp_constructed, etmp->exp_len,
-					etmp->exp_tag, etmp->exp_class);
-		if (etmp->exp_pad)
-			*p++ = 0;
-		}
+    for (i = 0, etmp = asn1_tags.exp_list; i < asn1_tags.exp_count;
+         i++, etmp++) {
+        ASN1_put_object(&p, etmp->exp_constructed, etmp->exp_len,
+                        etmp->exp_tag, etmp->exp_class);
+        if (etmp->exp_pad)
+            *p++ = 0;
+    }
 
-	/* If IMPLICIT, output tag */
+    /* If IMPLICIT, output tag */
 
-	if (asn1_tags.imp_tag != -1)
-		{
-		if (asn1_tags.imp_class == V_ASN1_UNIVERSAL 
-		    && (asn1_tags.imp_tag == V_ASN1_SEQUENCE
-		     || asn1_tags.imp_tag == V_ASN1_SET) )
-			hdr_constructed = V_ASN1_CONSTRUCTED;
-		ASN1_put_object(&p, hdr_constructed, hdr_len,
-					asn1_tags.imp_tag, asn1_tags.imp_class);
-		}
+    if (asn1_tags.imp_tag != -1) {
+        if (asn1_tags.imp_class == V_ASN1_UNIVERSAL
+            && (asn1_tags.imp_tag == V_ASN1_SEQUENCE
+                || asn1_tags.imp_tag == V_ASN1_SET))
+            hdr_constructed = V_ASN1_CONSTRUCTED;
+        ASN1_put_object(&p, hdr_constructed, hdr_len,
+                        asn1_tags.imp_tag, asn1_tags.imp_class);
+    }
 
-	/* Copy across original encoding */
-	memcpy(p, cpy_start, cpy_len);
+    /* Copy across original encoding */
+    OPENSSL_memcpy(p, cpy_start, cpy_len);
 
-	cp = new_der;
+    cp = new_der;
 
-	/* Obtain new ASN1_TYPE structure */
-	ret = d2i_ASN1_TYPE(NULL, &cp, len);
+    /* Obtain new ASN1_TYPE structure */
+    ret = d2i_ASN1_TYPE(NULL, &cp, len);
 
-	err:
-	if (orig_der)
-		OPENSSL_free(orig_der);
-	if (new_der)
-		OPENSSL_free(new_der);
+ err:
+    if (orig_der)
+        OPENSSL_free(orig_der);
+    if (new_der)
+        OPENSSL_free(new_der);
 
-	return ret;
+    return ret;
 
-	}
+}
 
 static int asn1_cb(const char *elem, int len, void *bitstr)
-	{
-	tag_exp_arg *arg = bitstr;
-	int i;
-	int utype;
-	int vlen = 0;
-	const char *p, *vstart = NULL;
+{
+    tag_exp_arg *arg = bitstr;
+    int i;
+    int utype;
+    int vlen = 0;
+    const char *p, *vstart = NULL;
 
-	int tmp_tag, tmp_class;
+    int tmp_tag, tmp_class;
 
-	if (elem == NULL)
-		return 0;
+    if (elem == NULL)
+        return 0;
 
-	for(i = 0, p = elem; i < len; p++, i++)
-		{
-		/* Look for the ':' in name value pairs */
-		if (*p == ':')
-			{
-			vstart = p + 1;
-			vlen = len - (vstart - elem);
-			len = p - elem;
-			break;
-			}
-		}
+    for (i = 0, p = elem; i < len; p++, i++) {
+        /* Look for the ':' in name value pairs */
+        if (*p == ':') {
+            vstart = p + 1;
+            vlen = len - (vstart - elem);
+            len = p - elem;
+            break;
+        }
+    }
 
-	utype = asn1_str2tag(elem, len);
+    utype = asn1_str2tag(elem, len);
 
-	if (utype == -1)
-		{
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_TAG);
-		ERR_add_error_data(2, "tag=", elem);
-		return -1;
-		}
+    if (utype == -1) {
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_TAG);
+        ERR_add_error_data(2, "tag=", elem);
+        return -1;
+    }
 
-	/* If this is not a modifier mark end of string and exit */
-	if (!(utype & ASN1_GEN_FLAG))
-		{
-		arg->utype = utype;
-		arg->str = vstart;
-		/* If no value and not end of string, error */
-		if (!vstart && elem[len])
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE);
-			return -1;
-			}
-		return 0;
-		}
+    /* If this is not a modifier mark end of string and exit */
+    if (!(utype & ASN1_GEN_FLAG)) {
+        arg->utype = utype;
+        arg->str = vstart;
+        /* If no value and not end of string, error */
+        if (!vstart && elem[len]) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_MISSING_VALUE);
+            return -1;
+        }
+        return 0;
+    }
 
-	switch(utype)
-		{
+    switch (utype) {
 
-		case ASN1_GEN_FLAG_IMP:
-		/* Check for illegal multiple IMPLICIT tagging */
-		if (arg->imp_tag != -1)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_NESTED_TAGGING);
-			return -1;
-			}
-		if (!parse_tagging(vstart, vlen, &arg->imp_tag, &arg->imp_class))
-			return -1;
-		break;
+    case ASN1_GEN_FLAG_IMP:
+        /* Check for illegal multiple IMPLICIT tagging */
+        if (arg->imp_tag != -1) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_NESTED_TAGGING);
+            return -1;
+        }
+        if (!parse_tagging(vstart, vlen, &arg->imp_tag, &arg->imp_class))
+            return -1;
+        break;
 
-		case ASN1_GEN_FLAG_EXP:
+    case ASN1_GEN_FLAG_EXP:
 
-		if (!parse_tagging(vstart, vlen, &tmp_tag, &tmp_class))
-			return -1;
-		if (!append_exp(arg, tmp_tag, tmp_class, 1, 0, 0))
-			return -1;
-		break;
+        if (!parse_tagging(vstart, vlen, &tmp_tag, &tmp_class))
+            return -1;
+        if (!append_exp(arg, tmp_tag, tmp_class, 1, 0, 0))
+            return -1;
+        break;
 
-		case ASN1_GEN_FLAG_SEQWRAP:
-		if (!append_exp(arg, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL, 1, 0, 1))
-			return -1;
-		break;
+    case ASN1_GEN_FLAG_SEQWRAP:
+        if (!append_exp(arg, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL, 1, 0, 1))
+            return -1;
+        break;
 
-		case ASN1_GEN_FLAG_SETWRAP:
-		if (!append_exp(arg, V_ASN1_SET, V_ASN1_UNIVERSAL, 1, 0, 1))
-			return -1;
-		break;
+    case ASN1_GEN_FLAG_SETWRAP:
+        if (!append_exp(arg, V_ASN1_SET, V_ASN1_UNIVERSAL, 1, 0, 1))
+            return -1;
+        break;
 
-		case ASN1_GEN_FLAG_BITWRAP:
-		if (!append_exp(arg, V_ASN1_BIT_STRING, V_ASN1_UNIVERSAL, 0, 1, 1))
-			return -1;
-		break;
+    case ASN1_GEN_FLAG_BITWRAP:
+        if (!append_exp(arg, V_ASN1_BIT_STRING, V_ASN1_UNIVERSAL, 0, 1, 1))
+            return -1;
+        break;
 
-		case ASN1_GEN_FLAG_OCTWRAP:
-		if (!append_exp(arg, V_ASN1_OCTET_STRING, V_ASN1_UNIVERSAL, 0, 0, 1))
-			return -1;
-		break;
+    case ASN1_GEN_FLAG_OCTWRAP:
+        if (!append_exp(arg, V_ASN1_OCTET_STRING, V_ASN1_UNIVERSAL, 0, 0, 1))
+            return -1;
+        break;
 
-		case ASN1_GEN_FLAG_FORMAT:
-		if (!vstart)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT);
-			return -1;
-			}
-		if (!strncmp(vstart, "ASCII", 5))
-			arg->format = ASN1_GEN_FORMAT_ASCII;
-		else if (!strncmp(vstart, "UTF8", 4))
-			arg->format = ASN1_GEN_FORMAT_UTF8;
-		else if (!strncmp(vstart, "HEX", 3))
-			arg->format = ASN1_GEN_FORMAT_HEX;
-		else if (!strncmp(vstart, "BITLIST", 7))
-			arg->format = ASN1_GEN_FORMAT_BITLIST;
-		else
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT);
-			return -1;
-			}
-		break;
+    case ASN1_GEN_FLAG_FORMAT:
+        if (!vstart) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT);
+            return -1;
+        }
+        if (!strncmp(vstart, "ASCII", 5))
+            arg->format = ASN1_GEN_FORMAT_ASCII;
+        else if (!strncmp(vstart, "UTF8", 4))
+            arg->format = ASN1_GEN_FORMAT_UTF8;
+        else if (!strncmp(vstart, "HEX", 3))
+            arg->format = ASN1_GEN_FORMAT_HEX;
+        else if (!strncmp(vstart, "BITLIST", 7))
+            arg->format = ASN1_GEN_FORMAT_BITLIST;
+        else {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNKNOWN_FORMAT);
+            return -1;
+        }
+        break;
 
-		}
+    }
 
-	return 1;
+    return 1;
 
-	}
+}
 
 static int parse_tagging(const char *vstart, int vlen, int *ptag, int *pclass)
-	{
-	char erch[2];
-	long tag_num;
-	char *eptr;
-	if (!vstart)
-		return 0;
-	tag_num = strtoul(vstart, &eptr, 10);
-	/* Check we haven't gone past max length: should be impossible */
-	if (eptr && *eptr && (eptr > vstart + vlen))
-		return 0;
-	if (tag_num < 0)
-		{
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_NUMBER);
-		return 0;
-		}
-	*ptag = tag_num;
-	/* If we have non numeric characters, parse them */
-	if (eptr)
-		vlen -= eptr - vstart;
-	else 
-		vlen = 0;
-	if (vlen)
-		{
-		switch (*eptr)
-			{
+{
+    char erch[2];
+    long tag_num;
+    char *eptr;
+    if (!vstart)
+        return 0;
+    tag_num = strtoul(vstart, &eptr, 10);
+    /* Check we haven't gone past max length: should be impossible */
+    if (eptr && *eptr && (eptr > vstart + vlen))
+        return 0;
+    if (tag_num < 0) {
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_NUMBER);
+        return 0;
+    }
+    *ptag = tag_num;
+    /* If we have non numeric characters, parse them */
+    if (eptr)
+        vlen -= eptr - vstart;
+    else
+        vlen = 0;
+    if (vlen) {
+        switch (*eptr) {
 
-			case 'U':
-			*pclass = V_ASN1_UNIVERSAL;
-			break;
+        case 'U':
+            *pclass = V_ASN1_UNIVERSAL;
+            break;
 
-			case 'A':
-			*pclass = V_ASN1_APPLICATION;
-			break;
+        case 'A':
+            *pclass = V_ASN1_APPLICATION;
+            break;
 
-			case 'P':
-			*pclass = V_ASN1_PRIVATE;
-			break;
+        case 'P':
+            *pclass = V_ASN1_PRIVATE;
+            break;
 
-			case 'C':
-			*pclass = V_ASN1_CONTEXT_SPECIFIC;
-			break;
+        case 'C':
+            *pclass = V_ASN1_CONTEXT_SPECIFIC;
+            break;
 
-			default:
-			erch[0] = *eptr;
-			erch[1] = 0;
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_MODIFIER);
-			ERR_add_error_data(2, "Char=", erch);
-			return 0;
-			break;
+        default:
+            erch[0] = *eptr;
+            erch[1] = 0;
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_MODIFIER);
+            ERR_add_error_data(2, "Char=", erch);
+            return 0;
+            break;
 
-			}
-		}
-	else
-		*pclass = V_ASN1_CONTEXT_SPECIFIC;
+        }
+    } else
+        *pclass = V_ASN1_CONTEXT_SPECIFIC;
 
-	return 1;
+    return 1;
 
-	}
+}
 
 /* Handle multiple types: SET and SEQUENCE */
 
 static ASN1_TYPE *asn1_multi(int utype, const char *section, X509V3_CTX *cnf)
-	{
-	ASN1_TYPE *ret = NULL;
-	STACK_OF(ASN1_TYPE) *sk = NULL;
-	STACK_OF(CONF_VALUE) *sect = NULL;
-	unsigned char *der = NULL;
-	int derlen;
-	size_t i;
-	sk = sk_ASN1_TYPE_new_null();
-	if (!sk)
-		goto bad;
-	if (section)
-		{
-		if (!cnf)
-			goto bad;
-		sect = X509V3_get_section(cnf, (char *)section);
-		if (!sect)
-			goto bad;
-		for (i = 0; i < sk_CONF_VALUE_num(sect); i++)
-			{
-			ASN1_TYPE *typ = ASN1_generate_v3(sk_CONF_VALUE_value(sect, i)->value, cnf);
-			if (!typ)
-				goto bad;
-			if (!sk_ASN1_TYPE_push(sk, typ))
-				goto bad;
-			}
-		}
+{
+    ASN1_TYPE *ret = NULL;
+    STACK_OF(ASN1_TYPE) *sk = NULL;
+    STACK_OF(CONF_VALUE) *sect = NULL;
+    unsigned char *der = NULL;
+    int derlen;
+    size_t i;
+    sk = sk_ASN1_TYPE_new_null();
+    if (!sk)
+        goto bad;
+    if (section) {
+        if (!cnf)
+            goto bad;
+        sect = X509V3_get_section(cnf, (char *)section);
+        if (!sect)
+            goto bad;
+        for (i = 0; i < sk_CONF_VALUE_num(sect); i++) {
+            ASN1_TYPE *typ =
+                ASN1_generate_v3(sk_CONF_VALUE_value(sect, i)->value, cnf);
+            if (!typ)
+                goto bad;
+            if (!sk_ASN1_TYPE_push(sk, typ))
+                goto bad;
+        }
+    }
 
-	/* Now we has a STACK of the components, convert to the correct form */
+    /*
+     * Now we has a STACK of the components, convert to the correct form
+     */
 
-	if (utype == V_ASN1_SET)
-		derlen = i2d_ASN1_SET_ANY(sk, &der);
-	else
-		derlen = i2d_ASN1_SEQUENCE_ANY(sk, &der);
+    if (utype == V_ASN1_SET)
+        derlen = i2d_ASN1_SET_ANY(sk, &der);
+    else
+        derlen = i2d_ASN1_SEQUENCE_ANY(sk, &der);
 
-	if (derlen < 0)
-		goto bad;
+    if (derlen < 0)
+        goto bad;
 
-	if (!(ret = ASN1_TYPE_new()))
-		goto bad;
+    if (!(ret = ASN1_TYPE_new()))
+        goto bad;
 
-	if (!(ret->value.asn1_string = ASN1_STRING_type_new(utype)))
-		goto bad;
+    if (!(ret->value.asn1_string = ASN1_STRING_type_new(utype)))
+        goto bad;
 
-	ret->type = utype;
+    ret->type = utype;
 
-	ret->value.asn1_string->data = der;
-	ret->value.asn1_string->length = derlen;
+    ret->value.asn1_string->data = der;
+    ret->value.asn1_string->length = derlen;
 
-	der = NULL;
+    der = NULL;
 
-	bad:
+ bad:
 
-	if (der)
-		OPENSSL_free(der);
+    if (der)
+        OPENSSL_free(der);
 
-	if (sk)
-		sk_ASN1_TYPE_pop_free(sk, ASN1_TYPE_free);
-	if (sect)
-		X509V3_section_free(cnf, sect);
+    if (sk)
+        sk_ASN1_TYPE_pop_free(sk, ASN1_TYPE_free);
+    if (sect)
+        X509V3_section_free(cnf, sect);
 
-	return ret;
-	}
+    return ret;
+}
 
-static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class, int exp_constructed, int exp_pad, int imp_ok)
-	{
-	tag_exp_type *exp_tmp;
-	/* Can only have IMPLICIT if permitted */
-	if ((arg->imp_tag != -1) && !imp_ok)
-		{
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_IMPLICIT_TAG);
-		return 0;
-		}
+static int append_exp(tag_exp_arg *arg, int exp_tag, int exp_class,
+                      int exp_constructed, int exp_pad, int imp_ok)
+{
+    tag_exp_type *exp_tmp;
+    /* Can only have IMPLICIT if permitted */
+    if ((arg->imp_tag != -1) && !imp_ok) {
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_IMPLICIT_TAG);
+        return 0;
+    }
 
-	if (arg->exp_count == ASN1_FLAG_EXP_MAX)
-		{
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_DEPTH_EXCEEDED);
-		return 0;
-		}
+    if (arg->exp_count == ASN1_FLAG_EXP_MAX) {
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_DEPTH_EXCEEDED);
+        return 0;
+    }
 
-	exp_tmp = &arg->exp_list[arg->exp_count++];
+    exp_tmp = &arg->exp_list[arg->exp_count++];
 
-	/* If IMPLICIT set tag to implicit value then
-	 * reset implicit tag since it has been used.
-	 */
-	if (arg->imp_tag != -1)
-		{
-		exp_tmp->exp_tag = arg->imp_tag;
-		exp_tmp->exp_class = arg->imp_class;
-		arg->imp_tag = -1;
-		arg->imp_class = -1;
-		}
-	else
-		{
-		exp_tmp->exp_tag = exp_tag;
-		exp_tmp->exp_class = exp_class;
-		}
-	exp_tmp->exp_constructed = exp_constructed;
-	exp_tmp->exp_pad = exp_pad;
+    /*
+     * If IMPLICIT set tag to implicit value then reset implicit tag since it
+     * has been used.
+     */
+    if (arg->imp_tag != -1) {
+        exp_tmp->exp_tag = arg->imp_tag;
+        exp_tmp->exp_class = arg->imp_class;
+        arg->imp_tag = -1;
+        arg->imp_class = -1;
+    } else {
+        exp_tmp->exp_tag = exp_tag;
+        exp_tmp->exp_class = exp_class;
+    }
+    exp_tmp->exp_constructed = exp_constructed;
+    exp_tmp->exp_pad = exp_pad;
 
-	return 1;
-	}
-
+    return 1;
+}
 
 static int asn1_str2tag(const char *tagstr, int len)
-	{
-	unsigned int i;
-	static const struct tag_name_st *tntmp, tnst [] = {
-		ASN1_GEN_STR("BOOL", V_ASN1_BOOLEAN),
-		ASN1_GEN_STR("BOOLEAN", V_ASN1_BOOLEAN),
-		ASN1_GEN_STR("NULL", V_ASN1_NULL),
-		ASN1_GEN_STR("INT", V_ASN1_INTEGER),
-		ASN1_GEN_STR("INTEGER", V_ASN1_INTEGER),
-		ASN1_GEN_STR("ENUM", V_ASN1_ENUMERATED),
-		ASN1_GEN_STR("ENUMERATED", V_ASN1_ENUMERATED),
-		ASN1_GEN_STR("OID", V_ASN1_OBJECT),
-		ASN1_GEN_STR("OBJECT", V_ASN1_OBJECT),
-		ASN1_GEN_STR("UTCTIME", V_ASN1_UTCTIME),
-		ASN1_GEN_STR("UTC", V_ASN1_UTCTIME),
-		ASN1_GEN_STR("GENERALIZEDTIME", V_ASN1_GENERALIZEDTIME),
-		ASN1_GEN_STR("GENTIME", V_ASN1_GENERALIZEDTIME),
-		ASN1_GEN_STR("OCT", V_ASN1_OCTET_STRING),
-		ASN1_GEN_STR("OCTETSTRING", V_ASN1_OCTET_STRING),
-		ASN1_GEN_STR("BITSTR", V_ASN1_BIT_STRING),
-		ASN1_GEN_STR("BITSTRING", V_ASN1_BIT_STRING),
-		ASN1_GEN_STR("UNIVERSALSTRING", V_ASN1_UNIVERSALSTRING),
-		ASN1_GEN_STR("UNIV", V_ASN1_UNIVERSALSTRING),
-		ASN1_GEN_STR("IA5", V_ASN1_IA5STRING),
-		ASN1_GEN_STR("IA5STRING", V_ASN1_IA5STRING),
-		ASN1_GEN_STR("UTF8", V_ASN1_UTF8STRING),
-		ASN1_GEN_STR("UTF8String", V_ASN1_UTF8STRING),
-		ASN1_GEN_STR("BMP", V_ASN1_BMPSTRING),
-		ASN1_GEN_STR("BMPSTRING", V_ASN1_BMPSTRING),
-		ASN1_GEN_STR("VISIBLESTRING", V_ASN1_VISIBLESTRING),
-		ASN1_GEN_STR("VISIBLE", V_ASN1_VISIBLESTRING),
-		ASN1_GEN_STR("PRINTABLESTRING", V_ASN1_PRINTABLESTRING),
-		ASN1_GEN_STR("PRINTABLE", V_ASN1_PRINTABLESTRING),
-		ASN1_GEN_STR("T61", V_ASN1_T61STRING),
-		ASN1_GEN_STR("T61STRING", V_ASN1_T61STRING),
-		ASN1_GEN_STR("TELETEXSTRING", V_ASN1_T61STRING),
-		ASN1_GEN_STR("GeneralString", V_ASN1_GENERALSTRING),
-		ASN1_GEN_STR("GENSTR", V_ASN1_GENERALSTRING),
-		ASN1_GEN_STR("NUMERIC", V_ASN1_NUMERICSTRING),
-		ASN1_GEN_STR("NUMERICSTRING", V_ASN1_NUMERICSTRING),
+{
+    unsigned int i;
+    static const struct tag_name_st *tntmp, tnst[] = {
+        ASN1_GEN_STR("BOOL", V_ASN1_BOOLEAN),
+        ASN1_GEN_STR("BOOLEAN", V_ASN1_BOOLEAN),
+        ASN1_GEN_STR("NULL", V_ASN1_NULL),
+        ASN1_GEN_STR("INT", V_ASN1_INTEGER),
+        ASN1_GEN_STR("INTEGER", V_ASN1_INTEGER),
+        ASN1_GEN_STR("ENUM", V_ASN1_ENUMERATED),
+        ASN1_GEN_STR("ENUMERATED", V_ASN1_ENUMERATED),
+        ASN1_GEN_STR("OID", V_ASN1_OBJECT),
+        ASN1_GEN_STR("OBJECT", V_ASN1_OBJECT),
+        ASN1_GEN_STR("UTCTIME", V_ASN1_UTCTIME),
+        ASN1_GEN_STR("UTC", V_ASN1_UTCTIME),
+        ASN1_GEN_STR("GENERALIZEDTIME", V_ASN1_GENERALIZEDTIME),
+        ASN1_GEN_STR("GENTIME", V_ASN1_GENERALIZEDTIME),
+        ASN1_GEN_STR("OCT", V_ASN1_OCTET_STRING),
+        ASN1_GEN_STR("OCTETSTRING", V_ASN1_OCTET_STRING),
+        ASN1_GEN_STR("BITSTR", V_ASN1_BIT_STRING),
+        ASN1_GEN_STR("BITSTRING", V_ASN1_BIT_STRING),
+        ASN1_GEN_STR("UNIVERSALSTRING", V_ASN1_UNIVERSALSTRING),
+        ASN1_GEN_STR("UNIV", V_ASN1_UNIVERSALSTRING),
+        ASN1_GEN_STR("IA5", V_ASN1_IA5STRING),
+        ASN1_GEN_STR("IA5STRING", V_ASN1_IA5STRING),
+        ASN1_GEN_STR("UTF8", V_ASN1_UTF8STRING),
+        ASN1_GEN_STR("UTF8String", V_ASN1_UTF8STRING),
+        ASN1_GEN_STR("BMP", V_ASN1_BMPSTRING),
+        ASN1_GEN_STR("BMPSTRING", V_ASN1_BMPSTRING),
+        ASN1_GEN_STR("VISIBLESTRING", V_ASN1_VISIBLESTRING),
+        ASN1_GEN_STR("VISIBLE", V_ASN1_VISIBLESTRING),
+        ASN1_GEN_STR("PRINTABLESTRING", V_ASN1_PRINTABLESTRING),
+        ASN1_GEN_STR("PRINTABLE", V_ASN1_PRINTABLESTRING),
+        ASN1_GEN_STR("T61", V_ASN1_T61STRING),
+        ASN1_GEN_STR("T61STRING", V_ASN1_T61STRING),
+        ASN1_GEN_STR("TELETEXSTRING", V_ASN1_T61STRING),
+        ASN1_GEN_STR("GeneralString", V_ASN1_GENERALSTRING),
+        ASN1_GEN_STR("GENSTR", V_ASN1_GENERALSTRING),
+        ASN1_GEN_STR("NUMERIC", V_ASN1_NUMERICSTRING),
+        ASN1_GEN_STR("NUMERICSTRING", V_ASN1_NUMERICSTRING),
 
-		/* Special cases */
-		ASN1_GEN_STR("SEQUENCE", V_ASN1_SEQUENCE),
-		ASN1_GEN_STR("SEQ", V_ASN1_SEQUENCE),
-		ASN1_GEN_STR("SET", V_ASN1_SET),
-		/* type modifiers */
-		/* Explicit tag */
-		ASN1_GEN_STR("EXP", ASN1_GEN_FLAG_EXP),
-		ASN1_GEN_STR("EXPLICIT", ASN1_GEN_FLAG_EXP),
-		/* Implicit tag */
-		ASN1_GEN_STR("IMP", ASN1_GEN_FLAG_IMP),
-		ASN1_GEN_STR("IMPLICIT", ASN1_GEN_FLAG_IMP),
-		/* OCTET STRING wrapper */
-		ASN1_GEN_STR("OCTWRAP", ASN1_GEN_FLAG_OCTWRAP),
-		/* SEQUENCE wrapper */
-		ASN1_GEN_STR("SEQWRAP", ASN1_GEN_FLAG_SEQWRAP),
-		/* SET wrapper */
-		ASN1_GEN_STR("SETWRAP", ASN1_GEN_FLAG_SETWRAP),
-		/* BIT STRING wrapper */
-		ASN1_GEN_STR("BITWRAP", ASN1_GEN_FLAG_BITWRAP),
-		ASN1_GEN_STR("FORM", ASN1_GEN_FLAG_FORMAT),
-		ASN1_GEN_STR("FORMAT", ASN1_GEN_FLAG_FORMAT),
-	};
+        /* Special cases */
+        ASN1_GEN_STR("SEQUENCE", V_ASN1_SEQUENCE),
+        ASN1_GEN_STR("SEQ", V_ASN1_SEQUENCE),
+        ASN1_GEN_STR("SET", V_ASN1_SET),
+        /* type modifiers */
+        /* Explicit tag */
+        ASN1_GEN_STR("EXP", ASN1_GEN_FLAG_EXP),
+        ASN1_GEN_STR("EXPLICIT", ASN1_GEN_FLAG_EXP),
+        /* Implicit tag */
+        ASN1_GEN_STR("IMP", ASN1_GEN_FLAG_IMP),
+        ASN1_GEN_STR("IMPLICIT", ASN1_GEN_FLAG_IMP),
+        /* OCTET STRING wrapper */
+        ASN1_GEN_STR("OCTWRAP", ASN1_GEN_FLAG_OCTWRAP),
+        /* SEQUENCE wrapper */
+        ASN1_GEN_STR("SEQWRAP", ASN1_GEN_FLAG_SEQWRAP),
+        /* SET wrapper */
+        ASN1_GEN_STR("SETWRAP", ASN1_GEN_FLAG_SETWRAP),
+        /* BIT STRING wrapper */
+        ASN1_GEN_STR("BITWRAP", ASN1_GEN_FLAG_BITWRAP),
+        ASN1_GEN_STR("FORM", ASN1_GEN_FLAG_FORMAT),
+        ASN1_GEN_STR("FORMAT", ASN1_GEN_FLAG_FORMAT),
+    };
 
-	if (len == -1)
-		len = strlen(tagstr);
-	
-	tntmp = tnst;	
-	for (i = 0; i < sizeof(tnst) / sizeof(struct tag_name_st); i++, tntmp++)
-		{
-		if ((len == tntmp->len) && !strncmp(tntmp->strnam, tagstr, len))
-			return tntmp->tag;
-		}
-	
-	return -1;
-	}
+    if (len == -1)
+        len = strlen(tagstr);
+
+    tntmp = tnst;
+    for (i = 0; i < sizeof(tnst) / sizeof(struct tag_name_st); i++, tntmp++) {
+        if ((len == tntmp->len) && !strncmp(tntmp->strnam, tagstr, len))
+            return tntmp->tag;
+    }
+
+    return -1;
+}
 
 static ASN1_TYPE *asn1_str2type(const char *str, int format, int utype)
-	{
-	ASN1_TYPE *atmp = NULL;
+{
+    ASN1_TYPE *atmp = NULL;
 
-	CONF_VALUE vtmp;
+    CONF_VALUE vtmp;
 
-	unsigned char *rdata;
-	long rdlen;
+    unsigned char *rdata;
+    long rdlen;
 
-	int no_unused = 1;
+    int no_unused = 1;
 
-	if (!(atmp = ASN1_TYPE_new()))
-		{
-		OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-		return NULL;
-		}
+    if (!(atmp = ASN1_TYPE_new())) {
+        OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
 
-	if (!str)
-		str = "";
+    if (!str)
+        str = "";
 
-	switch(utype)
-		{
+    switch (utype) {
 
-		case V_ASN1_NULL:
-		if (str && *str)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_NULL_VALUE);
-			goto bad_form;
-			}
-		break;
-		
-		case V_ASN1_BOOLEAN:
-		if (format != ASN1_GEN_FORMAT_ASCII)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ASCII_FORMAT);
-			goto bad_form;
-			}
-		vtmp.name = NULL;
-		vtmp.section = NULL;
-		vtmp.value = (char *)str;
-		if (!X509V3_get_value_bool(&vtmp, &atmp->value.boolean))
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_BOOLEAN);
-			goto bad_str;
-			}
-		break;
+    case V_ASN1_NULL:
+        if (str && *str) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_NULL_VALUE);
+            goto bad_form;
+        }
+        break;
 
-		case V_ASN1_INTEGER:
-		case V_ASN1_ENUMERATED:
-		if (format != ASN1_GEN_FORMAT_ASCII)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_INTEGER_NOT_ASCII_FORMAT);
-			goto bad_form;
-			}
-		if (!(atmp->value.integer = s2i_ASN1_INTEGER(NULL, (char *)str)))
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_INTEGER);
-			goto bad_str;
-			}
-		break;
+    case V_ASN1_BOOLEAN:
+        if (format != ASN1_GEN_FORMAT_ASCII) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_NOT_ASCII_FORMAT);
+            goto bad_form;
+        }
+        vtmp.name = NULL;
+        vtmp.section = NULL;
+        vtmp.value = (char *)str;
+        if (!X509V3_get_value_bool(&vtmp, &atmp->value.boolean)) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_BOOLEAN);
+            goto bad_str;
+        }
+        break;
 
-		case V_ASN1_OBJECT:
-		if (format != ASN1_GEN_FORMAT_ASCII)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_OBJECT_NOT_ASCII_FORMAT);
-			goto bad_form;
-			}
-		if (!(atmp->value.object = OBJ_txt2obj(str, 0)))
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OBJECT);
-			goto bad_str;
-			}
-		break;
+    case V_ASN1_INTEGER:
+    case V_ASN1_ENUMERATED:
+        if (format != ASN1_GEN_FORMAT_ASCII) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_INTEGER_NOT_ASCII_FORMAT);
+            goto bad_form;
+        }
+        if (!(atmp->value.integer = s2i_ASN1_INTEGER(NULL, (char *)str))) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_INTEGER);
+            goto bad_str;
+        }
+        break;
 
-		case V_ASN1_UTCTIME:
-		case V_ASN1_GENERALIZEDTIME:
-		if (format != ASN1_GEN_FORMAT_ASCII)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_TIME_NOT_ASCII_FORMAT);
-			goto bad_form;
-			}
-		if (!(atmp->value.asn1_string = ASN1_STRING_new()))
-			{
-			OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-			goto bad_str;
-			}
-		if (!ASN1_STRING_set(atmp->value.asn1_string, str, -1))
-			{
-			OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-			goto bad_str;
-			}
-		atmp->value.asn1_string->type = utype;
-		if (!ASN1_TIME_check(atmp->value.asn1_string))
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_TIME_VALUE);
-			goto bad_str;
-			}
+    case V_ASN1_OBJECT:
+        if (format != ASN1_GEN_FORMAT_ASCII) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_OBJECT_NOT_ASCII_FORMAT);
+            goto bad_form;
+        }
+        if (!(atmp->value.object = OBJ_txt2obj(str, 0))) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OBJECT);
+            goto bad_str;
+        }
+        break;
 
-		break;
+    case V_ASN1_UTCTIME:
+    case V_ASN1_GENERALIZEDTIME:
+        if (format != ASN1_GEN_FORMAT_ASCII) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_TIME_NOT_ASCII_FORMAT);
+            goto bad_form;
+        }
+        if (!(atmp->value.asn1_string = ASN1_STRING_new())) {
+            OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+            goto bad_str;
+        }
+        if (!ASN1_STRING_set(atmp->value.asn1_string, str, -1)) {
+            OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+            goto bad_str;
+        }
+        atmp->value.asn1_string->type = utype;
+        if (!ASN1_TIME_check(atmp->value.asn1_string)) {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_TIME_VALUE);
+            goto bad_str;
+        }
 
-		case V_ASN1_BMPSTRING:
-		case V_ASN1_PRINTABLESTRING:
-		case V_ASN1_IA5STRING:
-		case V_ASN1_T61STRING:
-		case V_ASN1_UTF8STRING:
-		case V_ASN1_VISIBLESTRING:
-		case V_ASN1_UNIVERSALSTRING:
-		case V_ASN1_GENERALSTRING:
-		case V_ASN1_NUMERICSTRING:
+        break;
 
-		if (format == ASN1_GEN_FORMAT_ASCII)
-			format = MBSTRING_ASC;
-		else if (format == ASN1_GEN_FORMAT_UTF8)
-			format = MBSTRING_UTF8;
-		else
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_FORMAT);
-			goto bad_form;
-			}
+    case V_ASN1_BMPSTRING:
+    case V_ASN1_PRINTABLESTRING:
+    case V_ASN1_IA5STRING:
+    case V_ASN1_T61STRING:
+    case V_ASN1_UTF8STRING:
+    case V_ASN1_VISIBLESTRING:
+    case V_ASN1_UNIVERSALSTRING:
+    case V_ASN1_GENERALSTRING:
+    case V_ASN1_NUMERICSTRING:
 
+        if (format == ASN1_GEN_FORMAT_ASCII)
+            format = MBSTRING_ASC;
+        else if (format == ASN1_GEN_FORMAT_UTF8)
+            format = MBSTRING_UTF8;
+        else {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_FORMAT);
+            goto bad_form;
+        }
 
-		if (ASN1_mbstring_copy(&atmp->value.asn1_string, (unsigned char *)str,
-						-1, format, ASN1_tag2bit(utype)) <= 0)
-			{
-			OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-			goto bad_str;
-			}
-		
+        if (ASN1_mbstring_copy(&atmp->value.asn1_string, (unsigned char *)str,
+                               -1, format, ASN1_tag2bit(utype)) <= 0) {
+            OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+            goto bad_str;
+        }
 
-		break;
+        break;
 
-		case V_ASN1_BIT_STRING:
+    case V_ASN1_BIT_STRING:
 
-		case V_ASN1_OCTET_STRING:
+    case V_ASN1_OCTET_STRING:
 
-		if (!(atmp->value.asn1_string = ASN1_STRING_new()))
-			{
-			OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-			goto bad_form;
-			}
+        if (!(atmp->value.asn1_string = ASN1_STRING_new())) {
+            OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+            goto bad_form;
+        }
 
-		if (format == ASN1_GEN_FORMAT_HEX)
-			{
+        if (format == ASN1_GEN_FORMAT_HEX) {
 
-			if (!(rdata = string_to_hex((char *)str, &rdlen)))
-				{
-				OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_HEX);
-				goto bad_str;
-				}
+            if (!(rdata = string_to_hex((char *)str, &rdlen))) {
+                OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_HEX);
+                goto bad_str;
+            }
 
-			atmp->value.asn1_string->data = rdata;
-			atmp->value.asn1_string->length = rdlen;
-			atmp->value.asn1_string->type = utype;
+            atmp->value.asn1_string->data = rdata;
+            atmp->value.asn1_string->length = rdlen;
+            atmp->value.asn1_string->type = utype;
 
-			}
-		else if (format == ASN1_GEN_FORMAT_ASCII)
-			ASN1_STRING_set(atmp->value.asn1_string, str, -1);
-		else if ((format == ASN1_GEN_FORMAT_BITLIST) && (utype == V_ASN1_BIT_STRING))
-			{
-			if (!CONF_parse_list(str, ',', 1, bitstr_cb, atmp->value.bit_string))
-				{
-				OPENSSL_PUT_ERROR(ASN1, ASN1_R_LIST_ERROR);
-				goto bad_str;
-				}
-			no_unused = 0;
-			
-			}
-		else 
-			{
-			OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_BITSTRING_FORMAT);
-			goto bad_form;
-			}
+        } else if (format == ASN1_GEN_FORMAT_ASCII)
+            ASN1_STRING_set(atmp->value.asn1_string, str, -1);
+        else if ((format == ASN1_GEN_FORMAT_BITLIST)
+                 && (utype == V_ASN1_BIT_STRING)) {
+            if (!CONF_parse_list
+                (str, ',', 1, bitstr_cb, atmp->value.bit_string)) {
+                OPENSSL_PUT_ERROR(ASN1, ASN1_R_LIST_ERROR);
+                goto bad_str;
+            }
+            no_unused = 0;
 
-		if ((utype == V_ASN1_BIT_STRING) && no_unused)
-			{
-			atmp->value.asn1_string->flags
-				&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
-        		atmp->value.asn1_string->flags
-				|= ASN1_STRING_FLAG_BITS_LEFT;
-			}
+        } else {
+            OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_BITSTRING_FORMAT);
+            goto bad_form;
+        }
 
+        if ((utype == V_ASN1_BIT_STRING) && no_unused) {
+            atmp->value.asn1_string->flags
+                &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
+            atmp->value.asn1_string->flags |= ASN1_STRING_FLAG_BITS_LEFT;
+        }
 
-		break;
+        break;
 
-		default:
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNSUPPORTED_TYPE);
-		goto bad_str;
-		break;
-		}
+    default:
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNSUPPORTED_TYPE);
+        goto bad_str;
+        break;
+    }
 
+    atmp->type = utype;
+    return atmp;
 
-	atmp->type = utype;
-	return atmp;
+ bad_str:
+    ERR_add_error_data(2, "string=", str);
+ bad_form:
 
+    ASN1_TYPE_free(atmp);
+    return NULL;
 
-	bad_str:
-	ERR_add_error_data(2, "string=", str);
-	bad_form:
-
-	ASN1_TYPE_free(atmp);
-	return NULL;
-
-	}
+}
 
 static int bitstr_cb(const char *elem, int len, void *bitstr)
-	{
-	long bitnum;
-	char *eptr;
-	if (!elem)
-		return 0;
-	bitnum = strtoul(elem, &eptr, 10);
-	if (eptr && *eptr && (eptr != elem + len))
-		return 0;
-	if (bitnum < 0)
-		{
-		OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_NUMBER);
-		return 0;
-		}
-	if (!ASN1_BIT_STRING_set_bit(bitstr, bitnum, 1))
-		{
-		OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
-		return 0;
-		}
-	return 1;
-	}
-
+{
+    long bitnum;
+    char *eptr;
+    if (!elem)
+        return 0;
+    bitnum = strtoul(elem, &eptr, 10);
+    if (eptr && *eptr && (eptr != elem + len))
+        return 0;
+    if (bitnum < 0) {
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_NUMBER);
+        return 0;
+    }
+    if (!ASN1_BIT_STRING_set_bit(bitstr, bitnum, 1)) {
+        OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
+    return 1;
+}
diff --git a/src/crypto/x509/by_dir.c b/src/crypto/x509/by_dir.c
index ae50ae1..e68ca5a 100644
--- a/src/crypto/x509/by_dir.c
+++ b/src/crypto/x509/by_dir.c
@@ -68,424 +68,386 @@
 
 #include "../internal.h"
 
+typedef struct lookup_dir_hashes_st {
+    unsigned long hash;
+    int suffix;
+} BY_DIR_HASH;
 
-typedef struct lookup_dir_hashes_st
-	{
-	unsigned long hash;
-	int suffix;
-	} BY_DIR_HASH;
+typedef struct lookup_dir_entry_st {
+    char *dir;
+    int dir_type;
+    STACK_OF(BY_DIR_HASH) *hashes;
+} BY_DIR_ENTRY;
 
-typedef struct lookup_dir_entry_st
-	{
-	char *dir;
-	int dir_type;
-	STACK_OF(BY_DIR_HASH) *hashes;
-	} BY_DIR_ENTRY;
-
-typedef struct lookup_dir_st
-	{
-	BUF_MEM *buffer;
-	STACK_OF(BY_DIR_ENTRY) *dirs;
-	} BY_DIR;
+typedef struct lookup_dir_st {
+    BUF_MEM *buffer;
+    STACK_OF(BY_DIR_ENTRY) *dirs;
+} BY_DIR;
 
 DECLARE_STACK_OF(BY_DIR_HASH)
 DECLARE_STACK_OF(BY_DIR_ENTRY)
 
 static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl,
-	char **ret);
+                    char **ret);
 static int new_dir(X509_LOOKUP *lu);
 static void free_dir(X509_LOOKUP *lu);
-static int add_cert_dir(BY_DIR *ctx,const char *dir,int type);
-static int get_cert_by_subject(X509_LOOKUP *xl,int type,X509_NAME *name,
-	X509_OBJECT *ret);
-static X509_LOOKUP_METHOD x509_dir_lookup=
-	{
-	"Load certs from files in a directory",
-	new_dir,		/* new */
-	free_dir,		/* free */
-	NULL, 			/* init */
-	NULL,			/* shutdown */
-	dir_ctrl,		/* ctrl */
-	get_cert_by_subject,	/* get_by_subject */
-	NULL,			/* get_by_issuer_serial */
-	NULL,			/* get_by_fingerprint */
-	NULL,			/* get_by_alias */
-	};
+static int add_cert_dir(BY_DIR *ctx, const char *dir, int type);
+static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name,
+                               X509_OBJECT *ret);
+static X509_LOOKUP_METHOD x509_dir_lookup = {
+    "Load certs from files in a directory",
+    new_dir,                    /* new */
+    free_dir,                   /* free */
+    NULL,                       /* init */
+    NULL,                       /* shutdown */
+    dir_ctrl,                   /* ctrl */
+    get_cert_by_subject,        /* get_by_subject */
+    NULL,                       /* get_by_issuer_serial */
+    NULL,                       /* get_by_fingerprint */
+    NULL,                       /* get_by_alias */
+};
 
 X509_LOOKUP_METHOD *X509_LOOKUP_hash_dir(void)
-	{
-	return(&x509_dir_lookup);
-	}
+{
+    return (&x509_dir_lookup);
+}
 
 static int dir_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl,
-	     char **retp)
-	{
-	int ret=0;
-	BY_DIR *ld;
-	char *dir = NULL;
+                    char **retp)
+{
+    int ret = 0;
+    BY_DIR *ld;
+    char *dir = NULL;
 
-	ld=(BY_DIR *)ctx->method_data;
+    ld = (BY_DIR *)ctx->method_data;
 
-	switch (cmd)
-		{
-	case X509_L_ADD_DIR:
-		if (argl == X509_FILETYPE_DEFAULT)
-			{
-			dir=(char *)getenv(X509_get_default_cert_dir_env());
-			if (dir)
-				ret=add_cert_dir(ld,dir,X509_FILETYPE_PEM);
-			else
-				ret=add_cert_dir(ld,X509_get_default_cert_dir(),
-					X509_FILETYPE_PEM);
-			if (!ret)
-				{
-				OPENSSL_PUT_ERROR(X509, X509_R_LOADING_CERT_DIR);
-				}
-			}
-		else
-			ret=add_cert_dir(ld,argp,(int)argl);
-		break;
-		}
-	return(ret);
-	}
+    switch (cmd) {
+    case X509_L_ADD_DIR:
+        if (argl == X509_FILETYPE_DEFAULT) {
+            dir = (char *)getenv(X509_get_default_cert_dir_env());
+            if (dir)
+                ret = add_cert_dir(ld, dir, X509_FILETYPE_PEM);
+            else
+                ret = add_cert_dir(ld, X509_get_default_cert_dir(),
+                                   X509_FILETYPE_PEM);
+            if (!ret) {
+                OPENSSL_PUT_ERROR(X509, X509_R_LOADING_CERT_DIR);
+            }
+        } else
+            ret = add_cert_dir(ld, argp, (int)argl);
+        break;
+    }
+    return (ret);
+}
 
 static int new_dir(X509_LOOKUP *lu)
-	{
-	BY_DIR *a;
+{
+    BY_DIR *a;
 
-	if ((a=(BY_DIR *)OPENSSL_malloc(sizeof(BY_DIR))) == NULL)
-		return(0);
-	if ((a->buffer=BUF_MEM_new()) == NULL)
-		{
-		OPENSSL_free(a);
-		return(0);
-		}
-	a->dirs=NULL;
-	lu->method_data=(char *)a;
-	return(1);
-	}
+    if ((a = (BY_DIR *)OPENSSL_malloc(sizeof(BY_DIR))) == NULL)
+        return (0);
+    if ((a->buffer = BUF_MEM_new()) == NULL) {
+        OPENSSL_free(a);
+        return (0);
+    }
+    a->dirs = NULL;
+    lu->method_data = (char *)a;
+    return (1);
+}
 
 static void by_dir_hash_free(BY_DIR_HASH *hash)
-	{
-	OPENSSL_free(hash);
-	}
+{
+    OPENSSL_free(hash);
+}
 
-static int by_dir_hash_cmp(const BY_DIR_HASH **a,
-			const BY_DIR_HASH **b)
-	{
-	if ((*a)->hash > (*b)->hash)
-		return 1;
-	if ((*a)->hash < (*b)->hash)
-		return -1;
-	return 0;
-	}
+static int by_dir_hash_cmp(const BY_DIR_HASH **a, const BY_DIR_HASH **b)
+{
+    if ((*a)->hash > (*b)->hash)
+        return 1;
+    if ((*a)->hash < (*b)->hash)
+        return -1;
+    return 0;
+}
 
 static void by_dir_entry_free(BY_DIR_ENTRY *ent)
-	{
-	if (ent->dir)
-		OPENSSL_free(ent->dir);
-	if (ent->hashes)
-		sk_BY_DIR_HASH_pop_free(ent->hashes, by_dir_hash_free);
-	OPENSSL_free(ent);
-	}
+{
+    if (ent->dir)
+        OPENSSL_free(ent->dir);
+    if (ent->hashes)
+        sk_BY_DIR_HASH_pop_free(ent->hashes, by_dir_hash_free);
+    OPENSSL_free(ent);
+}
 
 static void free_dir(X509_LOOKUP *lu)
-	{
-	BY_DIR *a;
+{
+    BY_DIR *a;
 
-	a=(BY_DIR *)lu->method_data;
-	if (a->dirs != NULL)
-		sk_BY_DIR_ENTRY_pop_free(a->dirs, by_dir_entry_free);
-	if (a->buffer != NULL)
-		BUF_MEM_free(a->buffer);
-	OPENSSL_free(a);
-	}
+    a = (BY_DIR *)lu->method_data;
+    if (a->dirs != NULL)
+        sk_BY_DIR_ENTRY_pop_free(a->dirs, by_dir_entry_free);
+    if (a->buffer != NULL)
+        BUF_MEM_free(a->buffer);
+    OPENSSL_free(a);
+}
 
 static int add_cert_dir(BY_DIR *ctx, const char *dir, int type)
-	{
-	size_t j,len;
-	const char *s,*ss,*p;
+{
+    size_t j, len;
+    const char *s, *ss, *p;
 
-	if (dir == NULL || !*dir)
-	    {
-	    OPENSSL_PUT_ERROR(X509, X509_R_INVALID_DIRECTORY);
-	    return 0;
-	    }
+    if (dir == NULL || !*dir) {
+        OPENSSL_PUT_ERROR(X509, X509_R_INVALID_DIRECTORY);
+        return 0;
+    }
 
-	s=dir;
-	p=s;
-	do
-		{
-		if ((*p == ':') || (*p == '\0'))
-			{
-			BY_DIR_ENTRY *ent;
-			ss=s;
-			s=p+1;
-			len=p-ss;
-			if (len == 0) continue;
-			for (j=0; j < sk_BY_DIR_ENTRY_num(ctx->dirs); j++)
-				{
-				ent = sk_BY_DIR_ENTRY_value(ctx->dirs, j);
-				if (strlen(ent->dir) == len &&
-				    strncmp(ent->dir,ss,len) == 0)
-					break;
-				}
-			if (j < sk_BY_DIR_ENTRY_num(ctx->dirs))
-				continue;
-			if (ctx->dirs == NULL)
-				{
-				ctx->dirs = sk_BY_DIR_ENTRY_new_null();
-				if (!ctx->dirs)
-					{
-					OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-					return 0;
-					}
-				}
-			ent = OPENSSL_malloc(sizeof(BY_DIR_ENTRY));
-			if (!ent)
-				return 0;
-			ent->dir_type = type;
-			ent->hashes = sk_BY_DIR_HASH_new(by_dir_hash_cmp);
-			ent->dir = OPENSSL_malloc(len+1);
-			if (!ent->dir || !ent->hashes)
-				{
-				by_dir_entry_free(ent);
-				return 0;
-				}
-			strncpy(ent->dir,ss,len);
-			ent->dir[len] = '\0';
-			if (!sk_BY_DIR_ENTRY_push(ctx->dirs, ent))
-				{
-				by_dir_entry_free(ent);
-				return 0;
-				}
-			}
-		} while (*p++ != '\0');
-	return 1;
-	}
+    s = dir;
+    p = s;
+    do {
+        if ((*p == ':') || (*p == '\0')) {
+            BY_DIR_ENTRY *ent;
+            ss = s;
+            s = p + 1;
+            len = p - ss;
+            if (len == 0)
+                continue;
+            for (j = 0; j < sk_BY_DIR_ENTRY_num(ctx->dirs); j++) {
+                ent = sk_BY_DIR_ENTRY_value(ctx->dirs, j);
+                if (strlen(ent->dir) == len &&
+                    strncmp(ent->dir, ss, len) == 0)
+                    break;
+            }
+            if (j < sk_BY_DIR_ENTRY_num(ctx->dirs))
+                continue;
+            if (ctx->dirs == NULL) {
+                ctx->dirs = sk_BY_DIR_ENTRY_new_null();
+                if (!ctx->dirs) {
+                    OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+                    return 0;
+                }
+            }
+            ent = OPENSSL_malloc(sizeof(BY_DIR_ENTRY));
+            if (!ent)
+                return 0;
+            ent->dir_type = type;
+            ent->hashes = sk_BY_DIR_HASH_new(by_dir_hash_cmp);
+            ent->dir = OPENSSL_malloc(len + 1);
+            if (!ent->dir || !ent->hashes) {
+                by_dir_entry_free(ent);
+                return 0;
+            }
+            strncpy(ent->dir, ss, len);
+            ent->dir[len] = '\0';
+            if (!sk_BY_DIR_ENTRY_push(ctx->dirs, ent)) {
+                by_dir_entry_free(ent);
+                return 0;
+            }
+        }
+    } while (*p++ != '\0');
+    return 1;
+}
 
-/* g_ent_hashes_lock protects the |hashes| member of all |BY_DIR_ENTRY|
- * objects. */
-static struct CRYPTO_STATIC_MUTEX g_ent_hashes_lock = CRYPTO_STATIC_MUTEX_INIT;
+/*
+ * g_ent_hashes_lock protects the |hashes| member of all |BY_DIR_ENTRY|
+ * objects.
+ */
+static struct CRYPTO_STATIC_MUTEX g_ent_hashes_lock =
+    CRYPTO_STATIC_MUTEX_INIT;
 
 static int get_cert_by_subject(X509_LOOKUP *xl, int type, X509_NAME *name,
-	     X509_OBJECT *ret)
-	{
-	BY_DIR *ctx;
-	union	{
-		struct	{
-			X509 st_x509;
-			X509_CINF st_x509_cinf;
-			} x509;
-		struct	{
-			X509_CRL st_crl;
-			X509_CRL_INFO st_crl_info;
-			} crl;
-		} data;
-	int ok=0;
-	size_t i;
-	int j,k;
-	unsigned long h;
-	unsigned long hash_array[2];
-	int hash_index;
-	BUF_MEM *b=NULL;
-	X509_OBJECT stmp,*tmp;
-	const char *postfix="";
+                               X509_OBJECT *ret)
+{
+    BY_DIR *ctx;
+    union {
+        struct {
+            X509 st_x509;
+            X509_CINF st_x509_cinf;
+        } x509;
+        struct {
+            X509_CRL st_crl;
+            X509_CRL_INFO st_crl_info;
+        } crl;
+    } data;
+    int ok = 0;
+    size_t i;
+    int j, k;
+    unsigned long h;
+    unsigned long hash_array[2];
+    int hash_index;
+    BUF_MEM *b = NULL;
+    X509_OBJECT stmp, *tmp;
+    const char *postfix = "";
 
-	if (name == NULL) return(0);
+    if (name == NULL)
+        return (0);
 
-	stmp.type=type;
-	if (type == X509_LU_X509)
-		{
-		data.x509.st_x509.cert_info= &data.x509.st_x509_cinf;
-		data.x509.st_x509_cinf.subject=name;
-		stmp.data.x509= &data.x509.st_x509;
-		postfix="";
-		}
-	else if (type == X509_LU_CRL)
-		{
-		data.crl.st_crl.crl= &data.crl.st_crl_info;
-		data.crl.st_crl_info.issuer=name;
-		stmp.data.crl= &data.crl.st_crl;
-		postfix="r";
-		}
-	else
-		{
-		OPENSSL_PUT_ERROR(X509, X509_R_WRONG_LOOKUP_TYPE);
-		goto finish;
-		}
+    stmp.type = type;
+    if (type == X509_LU_X509) {
+        data.x509.st_x509.cert_info = &data.x509.st_x509_cinf;
+        data.x509.st_x509_cinf.subject = name;
+        stmp.data.x509 = &data.x509.st_x509;
+        postfix = "";
+    } else if (type == X509_LU_CRL) {
+        data.crl.st_crl.crl = &data.crl.st_crl_info;
+        data.crl.st_crl_info.issuer = name;
+        stmp.data.crl = &data.crl.st_crl;
+        postfix = "r";
+    } else {
+        OPENSSL_PUT_ERROR(X509, X509_R_WRONG_LOOKUP_TYPE);
+        goto finish;
+    }
 
-	if ((b=BUF_MEM_new()) == NULL)
-		{
-		OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB);
-		goto finish;
-		}
-	
-	ctx=(BY_DIR *)xl->method_data;
+    if ((b = BUF_MEM_new()) == NULL) {
+        OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB);
+        goto finish;
+    }
 
-	hash_array[0]=X509_NAME_hash(name);
-	hash_array[1]=X509_NAME_hash_old(name);
-	for (hash_index=0; hash_index < 2; ++hash_index)
-		{
-		h=hash_array[hash_index];
-		for (i=0; i < sk_BY_DIR_ENTRY_num(ctx->dirs); i++)
-			{
-			BY_DIR_ENTRY *ent;
-			size_t idx;
-			BY_DIR_HASH htmp, *hent;
-			ent = sk_BY_DIR_ENTRY_value(ctx->dirs, i);
-			j=strlen(ent->dir)+1+8+6+1+1;
-			if (!BUF_MEM_grow(b,j))
-				{
-				OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-				goto finish;
-				}
-			if (type == X509_LU_CRL && ent->hashes)
-				{
-				htmp.hash = h;
-				CRYPTO_STATIC_MUTEX_lock_read(&g_ent_hashes_lock);
-				if (sk_BY_DIR_HASH_find(ent->hashes, &idx, &htmp))
-					{
-					hent = sk_BY_DIR_HASH_value(ent->hashes, idx);
-					k = hent->suffix;
-					}
-				else
-					{
-					hent = NULL;
-					k=0;
-					}
-				CRYPTO_STATIC_MUTEX_unlock(&g_ent_hashes_lock);
-				}
-			else
-				{
-				k = 0;
-				hent = NULL;
-				}
-			for (;;)
-				{
-				char c = '/';
+    ctx = (BY_DIR *)xl->method_data;
+
+    hash_array[0] = X509_NAME_hash(name);
+    hash_array[1] = X509_NAME_hash_old(name);
+    for (hash_index = 0; hash_index < 2; ++hash_index) {
+        h = hash_array[hash_index];
+        for (i = 0; i < sk_BY_DIR_ENTRY_num(ctx->dirs); i++) {
+            BY_DIR_ENTRY *ent;
+            size_t idx;
+            BY_DIR_HASH htmp, *hent;
+            ent = sk_BY_DIR_ENTRY_value(ctx->dirs, i);
+            j = strlen(ent->dir) + 1 + 8 + 6 + 1 + 1;
+            if (!BUF_MEM_grow(b, j)) {
+                OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+                goto finish;
+            }
+            if (type == X509_LU_CRL && ent->hashes) {
+                htmp.hash = h;
+                CRYPTO_STATIC_MUTEX_lock_read(&g_ent_hashes_lock);
+                if (sk_BY_DIR_HASH_find(ent->hashes, &idx, &htmp)) {
+                    hent = sk_BY_DIR_HASH_value(ent->hashes, idx);
+                    k = hent->suffix;
+                } else {
+                    hent = NULL;
+                    k = 0;
+                }
+                CRYPTO_STATIC_MUTEX_unlock_read(&g_ent_hashes_lock);
+            } else {
+                k = 0;
+                hent = NULL;
+            }
+            for (;;) {
+                char c = '/';
 #ifdef OPENSSL_SYS_VMS
-				c = ent->dir[strlen(ent->dir)-1];
-				if (c != ':' && c != '>' && c != ']')
-					{
-					/* If no separator is present, we assume the
-					   directory specifier is a logical name, and
-					   add a colon.  We really should use better
-					   VMS routines for merging things like this,
-					   but this will do for now...
-					   -- Richard Levitte */
-					c = ':';
-					}
-				else
-					{
-					c = '\0';
-					}
+                c = ent->dir[strlen(ent->dir) - 1];
+                if (c != ':' && c != '>' && c != ']') {
+                    /*
+                     * If no separator is present, we assume the directory
+                     * specifier is a logical name, and add a colon.  We
+                     * really should use better VMS routines for merging
+                     * things like this, but this will do for now... --
+                     * Richard Levitte
+                     */
+                    c = ':';
+                } else {
+                    c = '\0';
+                }
 #endif
-				if (c == '\0')
-					{
-					/* This is special.  When c == '\0', no
-					   directory separator should be added. */
-					BIO_snprintf(b->data,b->max,
-						"%s%08lx.%s%d",ent->dir,h,
-						postfix,k);
-					}
-				else
-					{
-					BIO_snprintf(b->data,b->max,
-						"%s%c%08lx.%s%d",ent->dir,c,h,
-						postfix,k);
-					}
+                if (c == '\0') {
+                    /*
+                     * This is special.  When c == '\0', no directory
+                     * separator should be added.
+                     */
+                    BIO_snprintf(b->data, b->max,
+                                 "%s%08lx.%s%d", ent->dir, h, postfix, k);
+                } else {
+                    BIO_snprintf(b->data, b->max,
+                                 "%s%c%08lx.%s%d", ent->dir, c, h,
+                                 postfix, k);
+                }
 #ifndef OPENSSL_NO_POSIX_IO
-#ifdef _WIN32
-#define stat _stat
+# if defined(_WIN32) && !defined(stat)
+#  define stat _stat
+# endif
+                {
+                    struct stat st;
+                    if (stat(b->data, &st) < 0)
+                        break;
+                }
 #endif
-				{
-				struct stat st;
-				if (stat(b->data,&st) < 0)
-					break;
-				}
-#endif
-				/* found one. */
-				if (type == X509_LU_X509)
-					{
-					if ((X509_load_cert_file(xl,b->data,
-						ent->dir_type)) == 0)
-						break;
-					}
-				else if (type == X509_LU_CRL)
-					{
-					if ((X509_load_crl_file(xl,b->data,
-						ent->dir_type)) == 0)
-						break;
-					}
-				/* else case will caught higher up */
-				k++;
-				}
+                /* found one. */
+                if (type == X509_LU_X509) {
+                    if ((X509_load_cert_file(xl, b->data,
+                                             ent->dir_type)) == 0)
+                        break;
+                } else if (type == X509_LU_CRL) {
+                    if ((X509_load_crl_file(xl, b->data, ent->dir_type)) == 0)
+                        break;
+                }
+                /* else case will caught higher up */
+                k++;
+            }
 
-			/* we have added it to the cache so now pull
-			 * it out again */
-			CRYPTO_MUTEX_lock_write(&xl->store_ctx->objs_lock);
-			tmp = NULL;
-			if (sk_X509_OBJECT_find(xl->store_ctx->objs, &idx, &stmp)) {
-				tmp=sk_X509_OBJECT_value(xl->store_ctx->objs,idx);
-			}
-			CRYPTO_MUTEX_unlock(&xl->store_ctx->objs_lock);
+            /*
+             * we have added it to the cache so now pull it out again
+             */
+            CRYPTO_MUTEX_lock_write(&xl->store_ctx->objs_lock);
+            tmp = NULL;
+            if (sk_X509_OBJECT_find(xl->store_ctx->objs, &idx, &stmp)) {
+                tmp = sk_X509_OBJECT_value(xl->store_ctx->objs, idx);
+            }
+            CRYPTO_MUTEX_unlock_write(&xl->store_ctx->objs_lock);
 
+            /*
+             * If a CRL, update the last file suffix added for this
+             */
 
-			/* If a CRL, update the last file suffix added for this */
+            if (type == X509_LU_CRL) {
+                CRYPTO_STATIC_MUTEX_lock_write(&g_ent_hashes_lock);
+                /*
+                 * Look for entry again in case another thread added an entry
+                 * first.
+                 */
+                if (!hent) {
+                    htmp.hash = h;
+                    if (sk_BY_DIR_HASH_find(ent->hashes, &idx, &htmp))
+                        hent = sk_BY_DIR_HASH_value(ent->hashes, idx);
+                }
+                if (!hent) {
+                    hent = OPENSSL_malloc(sizeof(BY_DIR_HASH));
+                    if (hent == NULL) {
+                        CRYPTO_STATIC_MUTEX_unlock_write(&g_ent_hashes_lock);
+                        ok = 0;
+                        goto finish;
+                    }
+                    hent->hash = h;
+                    hent->suffix = k;
+                    if (!sk_BY_DIR_HASH_push(ent->hashes, hent)) {
+                        CRYPTO_STATIC_MUTEX_unlock_write(&g_ent_hashes_lock);
+                        OPENSSL_free(hent);
+                        ok = 0;
+                        goto finish;
+                    }
+                } else if (hent->suffix < k)
+                    hent->suffix = k;
 
-			if (type == X509_LU_CRL)
-				{
-				CRYPTO_STATIC_MUTEX_lock_write(&g_ent_hashes_lock);
-				/* Look for entry again in case another thread added
-				 * an entry first.
-				 */
-				if (!hent)
-					{
-					htmp.hash = h;
-					if (sk_BY_DIR_HASH_find(ent->hashes, &idx, &htmp))
-						hent = sk_BY_DIR_HASH_value(ent->hashes, idx);
-					}
-				if (!hent)
-					{
-					hent = OPENSSL_malloc(sizeof(BY_DIR_HASH));
-					if (hent == NULL)
-						{
-						CRYPTO_STATIC_MUTEX_unlock(&g_ent_hashes_lock);
-						ok = 0;
-						goto finish;
-						}
-					hent->hash = h;
-					hent->suffix = k;
-					if (!sk_BY_DIR_HASH_push(ent->hashes, hent))
-						{
-						CRYPTO_STATIC_MUTEX_unlock(&g_ent_hashes_lock);
-						OPENSSL_free(hent);
-						ok = 0;
-						goto finish;
-						}
-					}
-				else if (hent->suffix < k)
-					hent->suffix = k;
+                CRYPTO_STATIC_MUTEX_unlock_write(&g_ent_hashes_lock);
+            }
 
-				CRYPTO_STATIC_MUTEX_unlock(&g_ent_hashes_lock);
-				}
-
-			if (tmp != NULL)
-				{
-				ok=1;
-				ret->type=tmp->type;
-				memcpy(&ret->data,&tmp->data,sizeof(ret->data));
-				/* If we were going to up the reference count,
-				 * we would need to do it on a perl 'type'
-				 * basis */
-		/*		CRYPTO_add(&tmp->data.x509->references,1,
-					CRYPTO_LOCK_X509);*/
-				goto finish;
-				}
-			}
-		}
-finish:
-	if (b != NULL) BUF_MEM_free(b);
-	return(ok);
-	}
+            if (tmp != NULL) {
+                ok = 1;
+                ret->type = tmp->type;
+                OPENSSL_memcpy(&ret->data, &tmp->data, sizeof(ret->data));
+                /*
+                 * If we were going to up the reference count, we would need
+                 * to do it on a perl 'type' basis
+                 */
+                /*
+                 * CRYPTO_add(&tmp->data.x509->references,1,
+                 * CRYPTO_LOCK_X509);
+                 */
+                goto finish;
+            }
+        }
+    }
+ finish:
+    if (b != NULL)
+        BUF_MEM_free(b);
+    return (ok);
+}
diff --git a/src/crypto/x509/by_file.c b/src/crypto/x509/by_file.c
index 3460b57..ebeb72e 100644
--- a/src/crypto/x509/by_file.c
+++ b/src/crypto/x509/by_file.c
@@ -63,233 +63,213 @@
 #include <openssl/pem.h>
 #include <openssl/thread.h>
 
-
 #ifndef OPENSSL_NO_STDIO
 
 static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc,
-	long argl, char **ret);
-static X509_LOOKUP_METHOD x509_file_lookup=
-	{
-	"Load file into cache",
-	NULL,		/* new */
-	NULL,		/* free */
-	NULL, 		/* init */
-	NULL,		/* shutdown */
-	by_file_ctrl,	/* ctrl */
-	NULL,		/* get_by_subject */
-	NULL,		/* get_by_issuer_serial */
-	NULL,		/* get_by_fingerprint */
-	NULL,		/* get_by_alias */
-	};
+                        long argl, char **ret);
+static X509_LOOKUP_METHOD x509_file_lookup = {
+    "Load file into cache",
+    NULL,                       /* new */
+    NULL,                       /* free */
+    NULL,                       /* init */
+    NULL,                       /* shutdown */
+    by_file_ctrl,               /* ctrl */
+    NULL,                       /* get_by_subject */
+    NULL,                       /* get_by_issuer_serial */
+    NULL,                       /* get_by_fingerprint */
+    NULL,                       /* get_by_alias */
+};
 
 X509_LOOKUP_METHOD *X509_LOOKUP_file(void)
-	{
-	return(&x509_file_lookup);
-	}
+{
+    return (&x509_file_lookup);
+}
 
-static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp, long argl,
-	     char **ret)
-	{
-	int ok=0;
-	char *file;
+static int by_file_ctrl(X509_LOOKUP *ctx, int cmd, const char *argp,
+                        long argl, char **ret)
+{
+    int ok = 0;
+    char *file;
 
-	switch (cmd)
-		{
-	case X509_L_FILE_LOAD:
-		if (argl == X509_FILETYPE_DEFAULT)
-			{
-			file = (char *)getenv(X509_get_default_cert_file_env());
-			if (file)
-				ok = (X509_load_cert_crl_file(ctx,file,
-					      X509_FILETYPE_PEM) != 0);
+    switch (cmd) {
+    case X509_L_FILE_LOAD:
+        if (argl == X509_FILETYPE_DEFAULT) {
+            file = (char *)getenv(X509_get_default_cert_file_env());
+            if (file)
+                ok = (X509_load_cert_crl_file(ctx, file,
+                                              X509_FILETYPE_PEM) != 0);
 
-			else
-				ok = (X509_load_cert_crl_file(ctx,X509_get_default_cert_file(),
-					      X509_FILETYPE_PEM) != 0);
+            else
+                ok = (X509_load_cert_crl_file
+                      (ctx, X509_get_default_cert_file(),
+                       X509_FILETYPE_PEM) != 0);
 
-			if (!ok)
-				{
-				OPENSSL_PUT_ERROR(X509, X509_R_LOADING_DEFAULTS);
-				}
-			}
-		else
-			{
-			if(argl == X509_FILETYPE_PEM)
-				ok = (X509_load_cert_crl_file(ctx,argp,
-					X509_FILETYPE_PEM) != 0);
-			else
-				ok = (X509_load_cert_file(ctx,argp,(int)argl) != 0);
-			}
-		break;
-		}
-	return(ok);
-	}
+            if (!ok) {
+                OPENSSL_PUT_ERROR(X509, X509_R_LOADING_DEFAULTS);
+            }
+        } else {
+            if (argl == X509_FILETYPE_PEM)
+                ok = (X509_load_cert_crl_file(ctx, argp,
+                                              X509_FILETYPE_PEM) != 0);
+            else
+                ok = (X509_load_cert_file(ctx, argp, (int)argl) != 0);
+        }
+        break;
+    }
+    return (ok);
+}
 
 int X509_load_cert_file(X509_LOOKUP *ctx, const char *file, int type)
-	{
-	int ret=0;
-	BIO *in=NULL;
-	int i,count=0;
-	X509 *x=NULL;
+{
+    int ret = 0;
+    BIO *in = NULL;
+    int i, count = 0;
+    X509 *x = NULL;
 
-	if (file == NULL) return(1);
-	in=BIO_new(BIO_s_file());
+    if (file == NULL)
+        return (1);
+    in = BIO_new(BIO_s_file());
 
-	if ((in == NULL) || (BIO_read_filename(in,file) <= 0))
-		{
-		OPENSSL_PUT_ERROR(X509, ERR_R_SYS_LIB);
-		goto err;
-		}
+    if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) {
+        OPENSSL_PUT_ERROR(X509, ERR_R_SYS_LIB);
+        goto err;
+    }
 
-	if (type == X509_FILETYPE_PEM)
-		{
-		for (;;)
-			{
-			x=PEM_read_bio_X509_AUX(in,NULL,NULL,NULL);
-			if (x == NULL)
-				{
-				if ((ERR_GET_REASON(ERR_peek_last_error()) ==
-					PEM_R_NO_START_LINE) && (count > 0))
-					{
-					ERR_clear_error();
-					break;
-					}
-				else
-					{
-					OPENSSL_PUT_ERROR(X509, ERR_R_PEM_LIB);
-					goto err;
-					}
-				}
-			i=X509_STORE_add_cert(ctx->store_ctx,x);
-			if (!i) goto err;
-			count++;
-			X509_free(x);
-			x=NULL;
-			}
-		ret=count;
-		}
-	else if (type == X509_FILETYPE_ASN1)
-		{
-		x=d2i_X509_bio(in,NULL);
-		if (x == NULL)
-			{
-			OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB);
-			goto err;
-			}
-		i=X509_STORE_add_cert(ctx->store_ctx,x);
-		if (!i) goto err;
-		ret=i;
-		}
-	else
-		{
-		OPENSSL_PUT_ERROR(X509, X509_R_BAD_X509_FILETYPE);
-		goto err;
-		}
-err:
-	if (x != NULL) X509_free(x);
-	if (in != NULL) BIO_free(in);
-	return(ret);
-	}
+    if (type == X509_FILETYPE_PEM) {
+        for (;;) {
+            x = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
+            if (x == NULL) {
+                if ((ERR_GET_REASON(ERR_peek_last_error()) ==
+                     PEM_R_NO_START_LINE) && (count > 0)) {
+                    ERR_clear_error();
+                    break;
+                } else {
+                    OPENSSL_PUT_ERROR(X509, ERR_R_PEM_LIB);
+                    goto err;
+                }
+            }
+            i = X509_STORE_add_cert(ctx->store_ctx, x);
+            if (!i)
+                goto err;
+            count++;
+            X509_free(x);
+            x = NULL;
+        }
+        ret = count;
+    } else if (type == X509_FILETYPE_ASN1) {
+        x = d2i_X509_bio(in, NULL);
+        if (x == NULL) {
+            OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB);
+            goto err;
+        }
+        i = X509_STORE_add_cert(ctx->store_ctx, x);
+        if (!i)
+            goto err;
+        ret = i;
+    } else {
+        OPENSSL_PUT_ERROR(X509, X509_R_BAD_X509_FILETYPE);
+        goto err;
+    }
+ err:
+    if (x != NULL)
+        X509_free(x);
+    if (in != NULL)
+        BIO_free(in);
+    return (ret);
+}
 
 int X509_load_crl_file(X509_LOOKUP *ctx, const char *file, int type)
-	{
-	int ret=0;
-	BIO *in=NULL;
-	int i,count=0;
-	X509_CRL *x=NULL;
+{
+    int ret = 0;
+    BIO *in = NULL;
+    int i, count = 0;
+    X509_CRL *x = NULL;
 
-	if (file == NULL) return(1);
-	in=BIO_new(BIO_s_file());
+    if (file == NULL)
+        return (1);
+    in = BIO_new(BIO_s_file());
 
-	if ((in == NULL) || (BIO_read_filename(in,file) <= 0))
-		{
-		OPENSSL_PUT_ERROR(X509, ERR_R_SYS_LIB);
-		goto err;
-		}
+    if ((in == NULL) || (BIO_read_filename(in, file) <= 0)) {
+        OPENSSL_PUT_ERROR(X509, ERR_R_SYS_LIB);
+        goto err;
+    }
 
-	if (type == X509_FILETYPE_PEM)
-		{
-		for (;;)
-			{
-			x=PEM_read_bio_X509_CRL(in,NULL,NULL,NULL);
-			if (x == NULL)
-				{
-				if ((ERR_GET_REASON(ERR_peek_last_error()) ==
-					PEM_R_NO_START_LINE) && (count > 0))
-					{
-					ERR_clear_error();
-					break;
-					}
-				else
-					{
-					OPENSSL_PUT_ERROR(X509, ERR_R_PEM_LIB);
-					goto err;
-					}
-				}
-			i=X509_STORE_add_crl(ctx->store_ctx,x);
-			if (!i) goto err;
-			count++;
-			X509_CRL_free(x);
-			x=NULL;
-			}
-		ret=count;
-		}
-	else if (type == X509_FILETYPE_ASN1)
-		{
-		x=d2i_X509_CRL_bio(in,NULL);
-		if (x == NULL)
-			{
-			OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB);
-			goto err;
-			}
-		i=X509_STORE_add_crl(ctx->store_ctx,x);
-		if (!i) goto err;
-		ret=i;
-		}
-	else
-		{
-		OPENSSL_PUT_ERROR(X509, X509_R_BAD_X509_FILETYPE);
-		goto err;
-		}
-err:
-	if (x != NULL) X509_CRL_free(x);
-	if (in != NULL) BIO_free(in);
-	return(ret);
-	}
+    if (type == X509_FILETYPE_PEM) {
+        for (;;) {
+            x = PEM_read_bio_X509_CRL(in, NULL, NULL, NULL);
+            if (x == NULL) {
+                if ((ERR_GET_REASON(ERR_peek_last_error()) ==
+                     PEM_R_NO_START_LINE) && (count > 0)) {
+                    ERR_clear_error();
+                    break;
+                } else {
+                    OPENSSL_PUT_ERROR(X509, ERR_R_PEM_LIB);
+                    goto err;
+                }
+            }
+            i = X509_STORE_add_crl(ctx->store_ctx, x);
+            if (!i)
+                goto err;
+            count++;
+            X509_CRL_free(x);
+            x = NULL;
+        }
+        ret = count;
+    } else if (type == X509_FILETYPE_ASN1) {
+        x = d2i_X509_CRL_bio(in, NULL);
+        if (x == NULL) {
+            OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB);
+            goto err;
+        }
+        i = X509_STORE_add_crl(ctx->store_ctx, x);
+        if (!i)
+            goto err;
+        ret = i;
+    } else {
+        OPENSSL_PUT_ERROR(X509, X509_R_BAD_X509_FILETYPE);
+        goto err;
+    }
+ err:
+    if (x != NULL)
+        X509_CRL_free(x);
+    if (in != NULL)
+        BIO_free(in);
+    return (ret);
+}
 
 int X509_load_cert_crl_file(X509_LOOKUP *ctx, const char *file, int type)
 {
-	STACK_OF(X509_INFO) *inf;
-	X509_INFO *itmp;
-	BIO *in;
-	size_t i;
-	int count = 0;
-	if(type != X509_FILETYPE_PEM)
-		return X509_load_cert_file(ctx, file, type);
-	in = BIO_new_file(file, "r");
-	if(!in) {
-		OPENSSL_PUT_ERROR(X509, ERR_R_SYS_LIB);
-		return 0;
-	}
-	inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL);
-	BIO_free(in);
-	if(!inf) {
-		OPENSSL_PUT_ERROR(X509, ERR_R_PEM_LIB);
-		return 0;
-	}
-	for(i = 0; i < sk_X509_INFO_num(inf); i++) {
-		itmp = sk_X509_INFO_value(inf, i);
-		if(itmp->x509) {
-			X509_STORE_add_cert(ctx->store_ctx, itmp->x509);
-			count++;
-		}
-		if(itmp->crl) {
-			X509_STORE_add_crl(ctx->store_ctx, itmp->crl);
-			count++;
-		}
-	}
-	sk_X509_INFO_pop_free(inf, X509_INFO_free);
-	return count;
+    STACK_OF(X509_INFO) *inf;
+    X509_INFO *itmp;
+    BIO *in;
+    size_t i;
+    int count = 0;
+    if (type != X509_FILETYPE_PEM)
+        return X509_load_cert_file(ctx, file, type);
+    in = BIO_new_file(file, "r");
+    if (!in) {
+        OPENSSL_PUT_ERROR(X509, ERR_R_SYS_LIB);
+        return 0;
+    }
+    inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL);
+    BIO_free(in);
+    if (!inf) {
+        OPENSSL_PUT_ERROR(X509, ERR_R_PEM_LIB);
+        return 0;
+    }
+    for (i = 0; i < sk_X509_INFO_num(inf); i++) {
+        itmp = sk_X509_INFO_value(inf, i);
+        if (itmp->x509) {
+            X509_STORE_add_cert(ctx->store_ctx, itmp->x509);
+            count++;
+        }
+        if (itmp->crl) {
+            X509_STORE_add_crl(ctx->store_ctx, itmp->crl);
+            count++;
+        }
+    }
+    sk_X509_INFO_pop_free(inf, X509_INFO_free);
+    return count;
 }
 
-#endif /* OPENSSL_NO_STDIO */
+#endif                          /* OPENSSL_NO_STDIO */
diff --git a/src/crypto/x509/charmap.h b/src/crypto/x509/charmap.h
index b55e638..3305ad1 100644
--- a/src/crypto/x509/charmap.h
+++ b/src/crypto/x509/charmap.h
@@ -1,15 +1,15 @@
-/* Auto generated with chartype.pl script.
- * Mask of various character properties
+/*
+ * Auto generated with chartype.pl script. Mask of various character
+ * properties
  */
 
 static const unsigned char char_type[] = {
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
-120, 0, 1,40, 0, 0, 0,16,16,16, 0,25,25,16,16,16,
-16,16,16,16,16,16,16,16,16,16,16, 9, 9,16, 9,16,
- 0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,16,16,16,16, 0, 1, 0, 0, 0,
- 0,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,
-16,16,16,16,16,16,16,16,16,16,16, 0, 0, 0, 0, 2
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+    120, 0, 1, 40, 0, 0, 0, 16, 16, 16, 0, 25, 25, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 9, 9, 16, 9, 16,
+    0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 1, 0, 0, 0,
+    0, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+    16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 0, 0, 0, 0, 2
 };
-
diff --git a/src/crypto/x509/i2d_pr.c b/src/crypto/x509/i2d_pr.c
index e7f4269..c3fb8a8 100644
--- a/src/crypto/x509/i2d_pr.c
+++ b/src/crypto/x509/i2d_pr.c
@@ -55,30 +55,29 @@
  * copied and put under another distribution licence
  * [including the GNU Public Licence.] */
 
-#include <openssl/x509.h>
-
 #include <openssl/asn1.h>
+#include <openssl/ec_key.h>
 #include <openssl/err.h>
 #include <openssl/evp.h>
-
-#include "../evp/internal.h"
+#include <openssl/rsa.h>
+#include <openssl/dsa.h>
 
 
-int i2d_PrivateKey(const EVP_PKEY *a, unsigned char **pp)
-	{
-	if (a->ameth && a->ameth->old_priv_encode)
-		{
-		return a->ameth->old_priv_encode(a, pp);
-		}
-	if (a->ameth && a->ameth->priv_encode) {
-		PKCS8_PRIV_KEY_INFO *p8 = EVP_PKEY2PKCS8((EVP_PKEY*)a);
-		int ret = i2d_PKCS8_PRIV_KEY_INFO(p8,pp);
-		PKCS8_PRIV_KEY_INFO_free(p8);
-		return ret;
-	}
-	/* Although this file is in crypto/x509 for layering reasons, it emits
-	 * an error code from ASN1 for OpenSSL compatibility. */
-	OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
-	return -1;
-	}
-
+int i2d_PrivateKey(const EVP_PKEY *a, uint8_t **pp)
+{
+    switch (EVP_PKEY_id(a)) {
+    case EVP_PKEY_RSA:
+        return i2d_RSAPrivateKey(a->pkey.rsa, pp);
+    case EVP_PKEY_EC:
+        return i2d_ECPrivateKey(a->pkey.ec, pp);
+    case EVP_PKEY_DSA:
+        return i2d_DSAPrivateKey(a->pkey.dsa, pp);
+    default:
+        /*
+         * Although this file is in crypto/x509 for layering reasons, it emits
+         * an error code from ASN1 for OpenSSL compatibility.
+         */
+        OPENSSL_PUT_ERROR(ASN1, ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE);
+        return -1;
+    }
+}
diff --git a/src/crypto/x509/internal.h b/src/crypto/x509/internal.h
new file mode 100644
index 0000000..4957c1e
--- /dev/null
+++ b/src/crypto/x509/internal.h
@@ -0,0 +1,66 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#ifndef OPENSSL_HEADER_X509_INTERNAL_H
+#define OPENSSL_HEADER_X509_INTERNAL_H
+
+#include <openssl/base.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* RSA-PSS functions. */
+
+/* x509_rsa_pss_to_ctx configures |ctx| for an RSA-PSS operation based on
+ * signature algorithm parameters in |sigalg| (which must have type
+ * |NID_rsassaPss|) and key |pkey|. It returns one on success and zero on
+ * error. */
+int x509_rsa_pss_to_ctx(EVP_MD_CTX *ctx, X509_ALGOR *sigalg, EVP_PKEY *pkey);
+
+/* x509_rsa_pss_to_ctx sets |algor| to the signature algorithm parameters for
+ * |ctx|, which must have been configured for an RSA-PSS signing operation. It
+ * returns one on success and zero on error. */
+int x509_rsa_ctx_to_pss(EVP_MD_CTX *ctx, X509_ALGOR *algor);
+
+/* x509_print_rsa_pss_params prints a human-readable representation of RSA-PSS
+ * parameters in |sigalg| to |bp|. It returns one on success and zero on
+ * error. */
+int x509_print_rsa_pss_params(BIO *bp, const X509_ALGOR *sigalg, int indent,
+                              ASN1_PCTX *pctx);
+
+
+/* Signature algorithm functions. */
+
+/* x509_digest_sign_algorithm encodes the signing parameters of |ctx| as an
+ * AlgorithmIdentifer and saves the result in |algor|. It returns one on
+ * success, or zero on error. */
+int x509_digest_sign_algorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor);
+
+/* x509_digest_verify_init sets up |ctx| for a signature verification operation
+ * with public key |pkey| and parameters from |algor|. The |ctx| argument must
+ * have been initialised with |EVP_MD_CTX_init|. It returns one on success, or
+ * zero on error. */
+int x509_digest_verify_init(EVP_MD_CTX *ctx, X509_ALGOR *sigalg,
+                            EVP_PKEY *pkey);
+
+
+#if defined(__cplusplus)
+}  /* extern C */
+#endif
+
+#endif  /* OPENSSL_HEADER_X509_INTERNAL_H */
diff --git a/src/crypto/x509/pkcs7.c b/src/crypto/x509/pkcs7.c
index 9e6a52f..dc3ea7d 100644
--- a/src/crypto/x509/pkcs7.c
+++ b/src/crypto/x509/pkcs7.c
@@ -27,6 +27,14 @@
 #include "../bytestring/internal.h"
 
 
+/* 1.2.840.113549.1.7.1 */
+static const uint8_t kPKCS7Data[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
+                                     0x0d, 0x01, 0x07, 0x01};
+
+/* 1.2.840.113549.1.7.2 */
+static const uint8_t kPKCS7SignedData[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
+                                           0x0d, 0x01, 0x07, 0x02};
+
 /* pkcs7_parse_header reads the non-certificate/non-CRL prefix of a PKCS#7
  * SignedData blob from |cbs| and sets |*out| to point to the rest of the
  * input. If the input is in BER format, then |*der_bytes| will be set to a
@@ -57,7 +65,8 @@
     goto err;
   }
 
-  if (OBJ_cbs2nid(&content_type) != NID_pkcs7_signed) {
+  if (!CBS_mem_equal(&content_type, kPKCS7SignedData,
+                     sizeof(kPKCS7SignedData))) {
     OPENSSL_PUT_ERROR(X509, X509_R_NOT_PKCS7_SIGNED_DATA);
     goto err;
   }
@@ -81,11 +90,8 @@
   return 1;
 
 err:
-  if (*der_bytes) {
-    OPENSSL_free(*der_bytes);
-    *der_bytes = NULL;
-  }
-
+  OPENSSL_free(*der_bytes);
+  *der_bytes = NULL;
   return 0;
 }
 
@@ -135,9 +141,7 @@
   ret = 1;
 
 err:
-  if (der_bytes) {
-    OPENSSL_free(der_bytes);
-  }
+  OPENSSL_free(der_bytes);
 
   if (!ret) {
     while (sk_X509_num(out_certs) != initial_certs_len) {
@@ -205,9 +209,7 @@
   ret = 1;
 
 err:
-  if (der_bytes) {
-    OPENSSL_free(der_bytes);
-  }
+  OPENSSL_free(der_bytes);
 
   if (!ret) {
     while (sk_X509_CRL_num(out_crls) != initial_crls_len) {
@@ -270,12 +272,13 @@
  * pkcs7_bundle returns one on success or zero on error. */
 static int pkcs7_bundle(CBB *out, int (*cb)(CBB *out, const void *arg),
                         const void *arg) {
-  CBB outer_seq, wrapped_seq, seq, version_bytes, digest_algos_set,
+  CBB outer_seq, oid, wrapped_seq, seq, version_bytes, digest_algos_set,
       content_info;
 
   /* See https://tools.ietf.org/html/rfc2315#section-7 */
   if (!CBB_add_asn1(out, &outer_seq, CBS_ASN1_SEQUENCE) ||
-      !OBJ_nid2cbb(&outer_seq, NID_pkcs7_signed) ||
+      !CBB_add_asn1(&outer_seq, &oid, CBS_ASN1_OBJECT) ||
+      !CBB_add_bytes(&oid, kPKCS7SignedData, sizeof(kPKCS7SignedData)) ||
       !CBB_add_asn1(&outer_seq, &wrapped_seq,
                     CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) ||
       /* See https://tools.ietf.org/html/rfc2315#section-9.1 */
@@ -284,7 +287,8 @@
       !CBB_add_u8(&version_bytes, 1) ||
       !CBB_add_asn1(&seq, &digest_algos_set, CBS_ASN1_SET) ||
       !CBB_add_asn1(&seq, &content_info, CBS_ASN1_SEQUENCE) ||
-      !OBJ_nid2cbb(&content_info, NID_pkcs7_data) ||
+      !CBB_add_asn1(&content_info, &oid, CBS_ASN1_OBJECT) ||
+      !CBB_add_bytes(&oid, kPKCS7Data, sizeof(kPKCS7Data)) ||
       !cb(&seq, arg)) {
     return 0;
   }
diff --git a/src/crypto/x509/pkcs7_test.c b/src/crypto/x509/pkcs7_test.c
index 38beb3e..f620b9b 100644
--- a/src/crypto/x509/pkcs7_test.c
+++ b/src/crypto/x509/pkcs7_test.c
@@ -22,6 +22,8 @@
 #include <openssl/stack.h>
 #include <openssl/x509.h>
 
+#include "../internal.h"
+
 
 /* kPKCS7NSS contains the certificate chain of mail.google.com, as saved by NSS
  * using the Chrome UI. */
@@ -504,7 +506,7 @@
     X509 *b = sk_X509_value(certs2, i);
 
     if (X509_cmp(a, b) != 0) {
-      fprintf(stderr, "Certificate %u differs.\n", (unsigned) i);
+      fprintf(stderr, "Certificate %zu differs.\n", i);
       return 0;
     }
   }
@@ -518,7 +520,7 @@
   }
 
   if (result_len != result2_len ||
-      memcmp(result_data, result2_data, result_len) != 0) {
+      OPENSSL_memcmp(result_data, result2_data, result_len) != 0) {
     fprintf(stderr, "Serialisation is not stable.\n");
     return 0;
   }
@@ -568,7 +570,7 @@
     X509_CRL *b = sk_X509_CRL_value(crls2, i);
 
     if (X509_CRL_cmp(a, b) != 0) {
-      fprintf(stderr, "CRL %u differs.\n", (unsigned) i);
+      fprintf(stderr, "CRL %zu differs.\n", i);
       return 0;
     }
   }
@@ -582,7 +584,7 @@
   }
 
   if (result_len != result2_len ||
-      memcmp(result_data, result2_data, result_len) != 0) {
+      OPENSSL_memcmp(result_data, result2_data, result_len) != 0) {
     fprintf(stderr, "Serialisation is not stable.\n");
     return 0;
   }
@@ -596,7 +598,7 @@
 }
 
 static int test_pem_certs(const char *pem) {
-  BIO *bio = BIO_new_mem_buf((char *) pem, strlen(pem));
+  BIO *bio = BIO_new_mem_buf(pem, strlen(pem));
   STACK_OF(X509) *certs = sk_X509_new_null();
 
   if (!PKCS7_get_PEM_certificates(certs, bio)) {
@@ -606,8 +608,8 @@
 
   if (sk_X509_num(certs) != 1) {
     fprintf(stderr,
-            "Bad number of certificates from PKCS7_get_PEM_certificates: %u\n",
-            (unsigned)sk_X509_num(certs));
+            "Bad number of certificates from PKCS7_get_PEM_certificates: %zu\n",
+            sk_X509_num(certs));
     return 0;
   }
 
@@ -618,7 +620,7 @@
 }
 
 static int test_pem_crls(const char *pem) {
-  BIO *bio = BIO_new_mem_buf((char *) pem, strlen(pem));
+  BIO *bio = BIO_new_mem_buf(pem, strlen(pem));
   STACK_OF(X509_CRL) *crls = sk_X509_CRL_new_null();
 
   if (!PKCS7_get_PEM_CRLs(crls, bio)) {
@@ -627,9 +629,8 @@
   }
 
   if (sk_X509_CRL_num(crls) != 1) {
-    fprintf(stderr,
-            "Bad number of CRLs from PKCS7_get_PEM_CRLs: %u\n",
-            (unsigned)sk_X509_CRL_num(crls));
+    fprintf(stderr, "Bad number of CRLs from PKCS7_get_PEM_CRLs: %zu\n",
+            sk_X509_CRL_num(crls));
     return 0;
   }
 
@@ -653,4 +654,3 @@
   printf("PASS\n");
   return 0;
 }
-
diff --git a/src/crypto/x509/rsa_pss.c b/src/crypto/x509/rsa_pss.c
new file mode 100644
index 0000000..4913c3d
--- /dev/null
+++ b/src/crypto/x509/rsa_pss.c
@@ -0,0 +1,385 @@
+/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+ * project 2006.
+ */
+/* ====================================================================
+ * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    licensing@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com). */
+
+#include <openssl/x509.h>
+
+#include <assert.h>
+
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/bio.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/obj.h>
+
+#include "internal.h"
+
+
+ASN1_SEQUENCE(RSA_PSS_PARAMS) = {
+  ASN1_EXP_OPT(RSA_PSS_PARAMS, hashAlgorithm, X509_ALGOR,0),
+  ASN1_EXP_OPT(RSA_PSS_PARAMS, maskGenAlgorithm, X509_ALGOR,1),
+  ASN1_EXP_OPT(RSA_PSS_PARAMS, saltLength, ASN1_INTEGER,2),
+  ASN1_EXP_OPT(RSA_PSS_PARAMS, trailerField, ASN1_INTEGER,3),
+} ASN1_SEQUENCE_END(RSA_PSS_PARAMS)
+
+IMPLEMENT_ASN1_FUNCTIONS(RSA_PSS_PARAMS)
+
+
+/* Given an MGF1 Algorithm ID decode to an Algorithm Identifier */
+static X509_ALGOR *rsa_mgf1_decode(X509_ALGOR *alg) {
+  if (alg == NULL || alg->parameter == NULL ||
+      OBJ_obj2nid(alg->algorithm) != NID_mgf1 ||
+      alg->parameter->type != V_ASN1_SEQUENCE) {
+    return NULL;
+  }
+
+  const uint8_t *p = alg->parameter->value.sequence->data;
+  int plen = alg->parameter->value.sequence->length;
+  return d2i_X509_ALGOR(NULL, &p, plen);
+}
+
+static RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg,
+                                      X509_ALGOR **pmaskHash) {
+  *pmaskHash = NULL;
+
+  if (alg->parameter == NULL || alg->parameter->type != V_ASN1_SEQUENCE) {
+    return NULL;
+  }
+
+  const uint8_t *p = alg->parameter->value.sequence->data;
+  int plen = alg->parameter->value.sequence->length;
+  RSA_PSS_PARAMS *pss = d2i_RSA_PSS_PARAMS(NULL, &p, plen);
+  if (pss == NULL) {
+    return NULL;
+  }
+
+  *pmaskHash = rsa_mgf1_decode(pss->maskGenAlgorithm);
+  return pss;
+}
+
+/* allocate and set algorithm ID from EVP_MD, default SHA1 */
+static int rsa_md_to_algor(X509_ALGOR **palg, const EVP_MD *md) {
+  if (EVP_MD_type(md) == NID_sha1) {
+    return 1;
+  }
+  *palg = X509_ALGOR_new();
+  if (*palg == NULL) {
+    return 0;
+  }
+  X509_ALGOR_set_md(*palg, md);
+  return 1;
+}
+
+/* Allocate and set MGF1 algorithm ID from EVP_MD */
+static int rsa_md_to_mgf1(X509_ALGOR **palg, const EVP_MD *mgf1md) {
+  X509_ALGOR *algtmp = NULL;
+  ASN1_STRING *stmp = NULL;
+  *palg = NULL;
+
+  if (EVP_MD_type(mgf1md) == NID_sha1) {
+    return 1;
+  }
+  /* need to embed algorithm ID inside another */
+  if (!rsa_md_to_algor(&algtmp, mgf1md) ||
+      !ASN1_item_pack(algtmp, ASN1_ITEM_rptr(X509_ALGOR), &stmp)) {
+    goto err;
+  }
+  *palg = X509_ALGOR_new();
+  if (!*palg) {
+    goto err;
+  }
+  X509_ALGOR_set0(*palg, OBJ_nid2obj(NID_mgf1), V_ASN1_SEQUENCE, stmp);
+  stmp = NULL;
+
+err:
+  ASN1_STRING_free(stmp);
+  X509_ALGOR_free(algtmp);
+  if (*palg) {
+    return 1;
+  }
+
+  return 0;
+}
+
+/* convert algorithm ID to EVP_MD, default SHA1 */
+static const EVP_MD *rsa_algor_to_md(X509_ALGOR *alg) {
+  const EVP_MD *md;
+  if (!alg) {
+    return EVP_sha1();
+  }
+  md = EVP_get_digestbyobj(alg->algorithm);
+  if (md == NULL) {
+    OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS);
+  }
+  return md;
+}
+
+/* convert MGF1 algorithm ID to EVP_MD, default SHA1 */
+static const EVP_MD *rsa_mgf1_to_md(X509_ALGOR *alg, X509_ALGOR *maskHash) {
+  const EVP_MD *md;
+  if (!alg) {
+    return EVP_sha1();
+  }
+  /* Check mask and lookup mask hash algorithm */
+  if (OBJ_obj2nid(alg->algorithm) != NID_mgf1 ||
+      maskHash == NULL) {
+    OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS);
+    return NULL;
+  }
+  md = EVP_get_digestbyobj(maskHash->algorithm);
+  if (md == NULL) {
+    OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS);
+    return NULL;
+  }
+  return md;
+}
+
+int x509_rsa_ctx_to_pss(EVP_MD_CTX *ctx, X509_ALGOR *algor) {
+  const EVP_MD *sigmd, *mgf1md;
+  int saltlen;
+  if (!EVP_PKEY_CTX_get_signature_md(ctx->pctx, &sigmd) ||
+      !EVP_PKEY_CTX_get_rsa_mgf1_md(ctx->pctx, &mgf1md) ||
+      !EVP_PKEY_CTX_get_rsa_pss_saltlen(ctx->pctx, &saltlen)) {
+    return 0;
+  }
+
+  EVP_PKEY *pk = EVP_PKEY_CTX_get0_pkey(ctx->pctx);
+  if (saltlen == -1) {
+    saltlen = EVP_MD_size(sigmd);
+  } else if (saltlen == -2) {
+    saltlen = EVP_PKEY_size(pk) - EVP_MD_size(sigmd) - 2;
+    if (((EVP_PKEY_bits(pk) - 1) & 0x7) == 0) {
+      saltlen--;
+    }
+  } else {
+    return 0;
+  }
+
+  int ret = 0;
+  ASN1_STRING *os = NULL;
+  RSA_PSS_PARAMS *pss = RSA_PSS_PARAMS_new();
+  if (!pss) {
+    goto err;
+  }
+
+  if (saltlen != 20) {
+    pss->saltLength = ASN1_INTEGER_new();
+    if (!pss->saltLength ||
+        !ASN1_INTEGER_set(pss->saltLength, saltlen)) {
+      goto err;
+    }
+  }
+
+  if (!rsa_md_to_algor(&pss->hashAlgorithm, sigmd) ||
+      !rsa_md_to_mgf1(&pss->maskGenAlgorithm, mgf1md)) {
+    goto err;
+  }
+
+  /* Finally create string with pss parameter encoding. */
+  if (!ASN1_item_pack(pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), &os)) {
+    goto err;
+  }
+
+  X509_ALGOR_set0(algor, OBJ_nid2obj(NID_rsassaPss), V_ASN1_SEQUENCE, os);
+  os = NULL;
+  ret = 1;
+
+err:
+  RSA_PSS_PARAMS_free(pss);
+  ASN1_STRING_free(os);
+  return ret;
+}
+
+int x509_rsa_pss_to_ctx(EVP_MD_CTX *ctx, X509_ALGOR *sigalg, EVP_PKEY *pkey) {
+  assert(OBJ_obj2nid(sigalg->algorithm) == NID_rsassaPss);
+
+  /* Decode PSS parameters */
+  int ret = 0;
+  X509_ALGOR *maskHash;
+  RSA_PSS_PARAMS *pss = rsa_pss_decode(sigalg, &maskHash);
+  if (pss == NULL) {
+    OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS);
+    goto err;
+  }
+
+  const EVP_MD *mgf1md = rsa_mgf1_to_md(pss->maskGenAlgorithm, maskHash);
+  const EVP_MD *md = rsa_algor_to_md(pss->hashAlgorithm);
+  if (mgf1md == NULL || md == NULL) {
+    goto err;
+  }
+
+  int saltlen = 20;
+  if (pss->saltLength != NULL) {
+    saltlen = ASN1_INTEGER_get(pss->saltLength);
+
+    /* Could perform more salt length sanity checks but the main
+     * RSA routines will trap other invalid values anyway. */
+    if (saltlen < 0) {
+      OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS);
+      goto err;
+    }
+  }
+
+  /* low-level routines support only trailer field 0xbc (value 1)
+   * and PKCS#1 says we should reject any other value anyway. */
+  if (pss->trailerField != NULL && ASN1_INTEGER_get(pss->trailerField) != 1) {
+    OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PSS_PARAMETERS);
+    goto err;
+  }
+
+  EVP_PKEY_CTX *pkctx;
+  if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey) ||
+      !EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) ||
+      !EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) ||
+      !EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md)) {
+    goto err;
+  }
+
+  ret = 1;
+
+err:
+  RSA_PSS_PARAMS_free(pss);
+  X509_ALGOR_free(maskHash);
+  return ret;
+}
+
+int x509_print_rsa_pss_params(BIO *bp, const X509_ALGOR *sigalg, int indent,
+                              ASN1_PCTX *pctx) {
+  assert(OBJ_obj2nid(sigalg->algorithm) == NID_rsassaPss);
+
+  int rv = 0;
+  X509_ALGOR *maskHash;
+  RSA_PSS_PARAMS *pss = rsa_pss_decode(sigalg, &maskHash);
+  if (!pss) {
+    if (BIO_puts(bp, " (INVALID PSS PARAMETERS)\n") <= 0) {
+      goto err;
+    }
+    rv = 1;
+    goto err;
+  }
+
+  if (BIO_puts(bp, "\n") <= 0 ||
+      !BIO_indent(bp, indent, 128) ||
+      BIO_puts(bp, "Hash Algorithm: ") <= 0) {
+    goto err;
+  }
+
+  if (pss->hashAlgorithm) {
+    if (i2a_ASN1_OBJECT(bp, pss->hashAlgorithm->algorithm) <= 0) {
+      goto err;
+    }
+  } else if (BIO_puts(bp, "sha1 (default)") <= 0) {
+    goto err;
+  }
+
+  if (BIO_puts(bp, "\n") <= 0 ||
+      !BIO_indent(bp, indent, 128) ||
+      BIO_puts(bp, "Mask Algorithm: ") <= 0) {
+    goto err;
+  }
+
+  if (pss->maskGenAlgorithm) {
+    if (i2a_ASN1_OBJECT(bp, pss->maskGenAlgorithm->algorithm) <= 0 ||
+        BIO_puts(bp, " with ") <= 0) {
+      goto err;
+    }
+
+    if (maskHash) {
+      if (i2a_ASN1_OBJECT(bp, maskHash->algorithm) <= 0) {
+        goto err;
+      }
+    } else if (BIO_puts(bp, "INVALID") <= 0) {
+      goto err;
+    }
+  } else if (BIO_puts(bp, "mgf1 with sha1 (default)") <= 0) {
+    goto err;
+  }
+  BIO_puts(bp, "\n");
+
+  if (!BIO_indent(bp, indent, 128) ||
+      BIO_puts(bp, "Salt Length: 0x") <= 0) {
+    goto err;
+  }
+
+  if (pss->saltLength) {
+    if (i2a_ASN1_INTEGER(bp, pss->saltLength) <= 0) {
+      goto err;
+    }
+  } else if (BIO_puts(bp, "14 (default)") <= 0) {
+    goto err;
+  }
+  BIO_puts(bp, "\n");
+
+  if (!BIO_indent(bp, indent, 128) ||
+      BIO_puts(bp, "Trailer Field: 0x") <= 0) {
+    goto err;
+  }
+
+  if (pss->trailerField) {
+    if (i2a_ASN1_INTEGER(bp, pss->trailerField) <= 0) {
+      goto err;
+    }
+  } else if (BIO_puts(bp, "BC (default)") <= 0) {
+    goto err;
+  }
+  BIO_puts(bp, "\n");
+
+  rv = 1;
+
+err:
+  RSA_PSS_PARAMS_free(pss);
+  X509_ALGOR_free(maskHash);
+  return rv;
+}
diff --git a/src/crypto/x509/t_crl.c b/src/crypto/x509/t_crl.c
index a2d8bc7..6c347cb 100644
--- a/src/crypto/x509/t_crl.c
+++ b/src/crypto/x509/t_crl.c
@@ -61,69 +61,68 @@
 #include <openssl/x509.h>
 #include <openssl/x509v3.h>
 
-
 #ifndef OPENSSL_NO_FP_API
 int X509_CRL_print_fp(FILE *fp, X509_CRL *x)
-        {
-        BIO *b;
-        int ret;
+{
+    BIO *b;
+    int ret;
 
-        if ((b=BIO_new(BIO_s_file())) == NULL)
-		{
-		OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB);
-                return(0);
-		}
-        BIO_set_fp(b,fp,BIO_NOCLOSE);
-        ret=X509_CRL_print(b, x);
-        BIO_free(b);
-        return(ret);
-        }
+    if ((b = BIO_new(BIO_s_file())) == NULL) {
+        OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB);
+        return (0);
+    }
+    BIO_set_fp(b, fp, BIO_NOCLOSE);
+    ret = X509_CRL_print(b, x);
+    BIO_free(b);
+    return (ret);
+}
 #endif
 
 int X509_CRL_print(BIO *out, X509_CRL *x)
 {
-	STACK_OF(X509_REVOKED) *rev;
-	X509_REVOKED *r;
-	long l;
-	size_t i;
-	char *p;
+    STACK_OF(X509_REVOKED) *rev;
+    X509_REVOKED *r;
+    long l;
+    size_t i;
+    char *p;
 
-	BIO_printf(out, "Certificate Revocation List (CRL):\n");
-	l = X509_CRL_get_version(x);
-	BIO_printf(out, "%8sVersion %lu (0x%lx)\n", "", l+1, l);
-	X509_signature_print(out, x->sig_alg, NULL);
-	p=X509_NAME_oneline(X509_CRL_get_issuer(x),NULL,0);
-	BIO_printf(out,"%8sIssuer: %s\n","",p);
-	OPENSSL_free(p);
-	BIO_printf(out,"%8sLast Update: ","");
-	ASN1_TIME_print(out,X509_CRL_get_lastUpdate(x));
-	BIO_printf(out,"\n%8sNext Update: ","");
-	if (X509_CRL_get_nextUpdate(x))
-		 ASN1_TIME_print(out,X509_CRL_get_nextUpdate(x));
-	else BIO_printf(out,"NONE");
-	BIO_printf(out,"\n");
+    BIO_printf(out, "Certificate Revocation List (CRL):\n");
+    l = X509_CRL_get_version(x);
+    BIO_printf(out, "%8sVersion %lu (0x%lx)\n", "", l + 1, l);
+    X509_signature_print(out, x->sig_alg, NULL);
+    p = X509_NAME_oneline(X509_CRL_get_issuer(x), NULL, 0);
+    BIO_printf(out, "%8sIssuer: %s\n", "", p);
+    OPENSSL_free(p);
+    BIO_printf(out, "%8sLast Update: ", "");
+    ASN1_TIME_print(out, X509_CRL_get_lastUpdate(x));
+    BIO_printf(out, "\n%8sNext Update: ", "");
+    if (X509_CRL_get_nextUpdate(x))
+        ASN1_TIME_print(out, X509_CRL_get_nextUpdate(x));
+    else
+        BIO_printf(out, "NONE");
+    BIO_printf(out, "\n");
 
-	X509V3_extensions_print(out, "CRL extensions",
-						x->crl->extensions, 0, 8);
+    X509V3_extensions_print(out, "CRL extensions", x->crl->extensions, 0, 8);
 
-	rev = X509_CRL_get_REVOKED(x);
+    rev = X509_CRL_get_REVOKED(x);
 
-	if(sk_X509_REVOKED_num(rev) > 0)
-	    BIO_printf(out, "Revoked Certificates:\n");
-	else BIO_printf(out, "No Revoked Certificates.\n");
+    if (sk_X509_REVOKED_num(rev) > 0)
+        BIO_printf(out, "Revoked Certificates:\n");
+    else
+        BIO_printf(out, "No Revoked Certificates.\n");
 
-	for(i = 0; i < sk_X509_REVOKED_num(rev); i++) {
-		r = sk_X509_REVOKED_value(rev, i);
-		BIO_printf(out,"    Serial Number: ");
-		i2a_ASN1_INTEGER(out,r->serialNumber);
-		BIO_printf(out,"\n        Revocation Date: ");
-		ASN1_TIME_print(out,r->revocationDate);
-		BIO_printf(out,"\n");
-		X509V3_extensions_print(out, "CRL entry extensions",
-						r->extensions, 0, 8);
-	}
-	X509_signature_print(out, x->sig_alg, x->signature);
+    for (i = 0; i < sk_X509_REVOKED_num(rev); i++) {
+        r = sk_X509_REVOKED_value(rev, i);
+        BIO_printf(out, "    Serial Number: ");
+        i2a_ASN1_INTEGER(out, r->serialNumber);
+        BIO_printf(out, "\n        Revocation Date: ");
+        ASN1_TIME_print(out, r->revocationDate);
+        BIO_printf(out, "\n");
+        X509V3_extensions_print(out, "CRL entry extensions",
+                                r->extensions, 0, 8);
+    }
+    X509_signature_print(out, x->sig_alg, x->signature);
 
-	return 1;
+    return 1;
 
 }
diff --git a/src/crypto/x509/t_x509.c b/src/crypto/x509/t_x509.c
index 7785ebf..d4f6bba 100644
--- a/src/crypto/x509/t_x509.c
+++ b/src/crypto/x509/t_x509.c
@@ -54,6 +54,7 @@
  * copied and put under another distribution licence
  * [including the GNU Public Licence.] */
 
+#include <ctype.h>
 #include <openssl/asn1.h>
 #include <openssl/bio.h>
 #include <openssl/digest.h>
@@ -64,437 +65,482 @@
 #include <openssl/x509.h>
 #include <openssl/x509v3.h>
 
-#include "../evp/internal.h"
+#include "internal.h"
+
 
 #ifndef OPENSSL_NO_FP_API
-int X509_print_ex_fp(FILE *fp, X509 *x, unsigned long nmflag, unsigned long cflag)
-        {
-        BIO *b;
-        int ret;
+int X509_print_ex_fp(FILE *fp, X509 *x, unsigned long nmflag,
+                     unsigned long cflag)
+{
+    BIO *b;
+    int ret;
 
-        if ((b=BIO_new(BIO_s_file())) == NULL)
-		{
-		OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB);
-                return(0);
-		}
-        BIO_set_fp(b,fp,BIO_NOCLOSE);
-        ret=X509_print_ex(b, x, nmflag, cflag);
-        BIO_free(b);
-        return(ret);
-        }
+    if ((b = BIO_new(BIO_s_file())) == NULL) {
+        OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB);
+        return (0);
+    }
+    BIO_set_fp(b, fp, BIO_NOCLOSE);
+    ret = X509_print_ex(b, x, nmflag, cflag);
+    BIO_free(b);
+    return (ret);
+}
 
 int X509_print_fp(FILE *fp, X509 *x)
-	{
-	return X509_print_ex_fp(fp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
-	}
+{
+    return X509_print_ex_fp(fp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
+}
 #endif
 
 int X509_print(BIO *bp, X509 *x)
 {
-	return X509_print_ex(bp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
+    return X509_print_ex(bp, x, XN_FLAG_COMPAT, X509_FLAG_COMPAT);
 }
 
-int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags, unsigned long cflag)
-	{
-	long l;
-	int ret=0,i;
-	char *m=NULL,mlch = ' ';
-	int nmindent = 0;
-	X509_CINF *ci;
-	ASN1_INTEGER *bs;
-	EVP_PKEY *pkey=NULL;
-	const char *neg;
+int X509_print_ex(BIO *bp, X509 *x, unsigned long nmflags,
+                  unsigned long cflag)
+{
+    long l;
+    int ret = 0, i;
+    char *m = NULL, mlch = ' ';
+    int nmindent = 0;
+    X509_CINF *ci;
+    ASN1_INTEGER *bs;
+    EVP_PKEY *pkey = NULL;
+    const char *neg;
 
-	if((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
-			mlch = '\n';
-			nmindent = 12;
-	}
+    if ((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) {
+        mlch = '\n';
+        nmindent = 12;
+    }
 
-	if(nmflags == X509_FLAG_COMPAT)
-		nmindent = 16;
+    if (nmflags == X509_FLAG_COMPAT)
+        nmindent = 16;
 
-	ci=x->cert_info;
-	if(!(cflag & X509_FLAG_NO_HEADER))
-		{
-		if (BIO_write(bp,"Certificate:\n",13) <= 0) goto err;
-		if (BIO_write(bp,"    Data:\n",10) <= 0) goto err;
-		}
-	if(!(cflag & X509_FLAG_NO_VERSION))
-		{
-		l=X509_get_version(x);
-		if (BIO_printf(bp,"%8sVersion: %lu (0x%lx)\n","",l+1,l) <= 0) goto err;
-		}
-	if(!(cflag & X509_FLAG_NO_SERIAL))
-		{
+    ci = x->cert_info;
+    if (!(cflag & X509_FLAG_NO_HEADER)) {
+        if (BIO_write(bp, "Certificate:\n", 13) <= 0)
+            goto err;
+        if (BIO_write(bp, "    Data:\n", 10) <= 0)
+            goto err;
+    }
+    if (!(cflag & X509_FLAG_NO_VERSION)) {
+        l = X509_get_version(x);
+        if (BIO_printf(bp, "%8sVersion: %lu (0x%lx)\n", "", l + 1, l) <= 0)
+            goto err;
+    }
+    if (!(cflag & X509_FLAG_NO_SERIAL)) {
 
-		if (BIO_write(bp,"        Serial Number:",22) <= 0) goto err;
+        if (BIO_write(bp, "        Serial Number:", 22) <= 0)
+            goto err;
 
-		bs=X509_get_serialNumber(x);
-		if (bs->length <= (int)sizeof(long))
-			{
-			l=ASN1_INTEGER_get(bs);
-			if (bs->type == V_ASN1_NEG_INTEGER)
-				{
-				l= -l;
-				neg="-";
-				}
-			else
-				neg="";
-			if (BIO_printf(bp," %s%lu (%s0x%lx)\n",neg,l,neg,l) <= 0)
-				goto err;
-			}
-		else
-			{
-			neg=(bs->type == V_ASN1_NEG_INTEGER)?" (Negative)":"";
-			if (BIO_printf(bp,"\n%12s%s","",neg) <= 0) goto err;
+        bs = X509_get_serialNumber(x);
+        if (bs->length < (int)sizeof(long)
+            || (bs->length == sizeof(long) && (bs->data[0] & 0x80) == 0)) {
+            l = ASN1_INTEGER_get(bs);
+            if (bs->type == V_ASN1_NEG_INTEGER) {
+                l = -l;
+                neg = "-";
+            } else
+                neg = "";
+            if (BIO_printf(bp, " %s%lu (%s0x%lx)\n", neg, l, neg, l) <= 0)
+                goto err;
+        } else {
+            neg = (bs->type == V_ASN1_NEG_INTEGER) ? " (Negative)" : "";
+            if (BIO_printf(bp, "\n%12s%s", "", neg) <= 0)
+                goto err;
 
-			for (i=0; i<bs->length; i++)
-				{
-				if (BIO_printf(bp,"%02x%c",bs->data[i],
-					((i+1 == bs->length)?'\n':':')) <= 0)
-					goto err;
-				}
-			}
+            for (i = 0; i < bs->length; i++) {
+                if (BIO_printf(bp, "%02x%c", bs->data[i],
+                               ((i + 1 == bs->length) ? '\n' : ':')) <= 0)
+                    goto err;
+            }
+        }
 
-		}
+    }
 
-	if(!(cflag & X509_FLAG_NO_SIGNAME))
-		{
-		if (X509_signature_print(bp, ci->signature, NULL) <= 0)
-			goto err;
-		}
+    if (!(cflag & X509_FLAG_NO_SIGNAME)) {
+        if (X509_signature_print(bp, ci->signature, NULL) <= 0)
+            goto err;
+    }
 
-	if(!(cflag & X509_FLAG_NO_ISSUER))
-		{
-		if (BIO_printf(bp,"        Issuer:%c",mlch) <= 0) goto err;
-		if (X509_NAME_print_ex(bp,X509_get_issuer_name(x),nmindent, nmflags) < 0) goto err;
-		if (BIO_write(bp,"\n",1) <= 0) goto err;
-		}
-	if(!(cflag & X509_FLAG_NO_VALIDITY))
-		{
-		if (BIO_write(bp,"        Validity\n",17) <= 0) goto err;
-		if (BIO_write(bp,"            Not Before: ",24) <= 0) goto err;
-		if (!ASN1_TIME_print(bp,X509_get_notBefore(x))) goto err;
-		if (BIO_write(bp,"\n            Not After : ",25) <= 0) goto err;
-		if (!ASN1_TIME_print(bp,X509_get_notAfter(x))) goto err;
-		if (BIO_write(bp,"\n",1) <= 0) goto err;
-		}
-	if(!(cflag & X509_FLAG_NO_SUBJECT))
-		{
-		if (BIO_printf(bp,"        Subject:%c",mlch) <= 0) goto err;
-		if (X509_NAME_print_ex(bp,X509_get_subject_name(x),nmindent, nmflags) < 0) goto err;
-		if (BIO_write(bp,"\n",1) <= 0) goto err;
-		}
-	if(!(cflag & X509_FLAG_NO_PUBKEY))
-		{
-		if (BIO_write(bp,"        Subject Public Key Info:\n",33) <= 0)
-			goto err;
-		if (BIO_printf(bp,"%12sPublic Key Algorithm: ","") <= 0)
-			goto err;
-		if (i2a_ASN1_OBJECT(bp, ci->key->algor->algorithm) <= 0)
-			goto err;
-		if (BIO_puts(bp, "\n") <= 0)
-			goto err;
+    if (!(cflag & X509_FLAG_NO_ISSUER)) {
+        if (BIO_printf(bp, "        Issuer:%c", mlch) <= 0)
+            goto err;
+        if (X509_NAME_print_ex(bp, X509_get_issuer_name(x), nmindent, nmflags)
+            < 0)
+            goto err;
+        if (BIO_write(bp, "\n", 1) <= 0)
+            goto err;
+    }
+    if (!(cflag & X509_FLAG_NO_VALIDITY)) {
+        if (BIO_write(bp, "        Validity\n", 17) <= 0)
+            goto err;
+        if (BIO_write(bp, "            Not Before: ", 24) <= 0)
+            goto err;
+        if (!ASN1_TIME_print(bp, X509_get_notBefore(x)))
+            goto err;
+        if (BIO_write(bp, "\n            Not After : ", 25) <= 0)
+            goto err;
+        if (!ASN1_TIME_print(bp, X509_get_notAfter(x)))
+            goto err;
+        if (BIO_write(bp, "\n", 1) <= 0)
+            goto err;
+    }
+    if (!(cflag & X509_FLAG_NO_SUBJECT)) {
+        if (BIO_printf(bp, "        Subject:%c", mlch) <= 0)
+            goto err;
+        if (X509_NAME_print_ex
+            (bp, X509_get_subject_name(x), nmindent, nmflags) < 0)
+            goto err;
+        if (BIO_write(bp, "\n", 1) <= 0)
+            goto err;
+    }
+    if (!(cflag & X509_FLAG_NO_PUBKEY)) {
+        if (BIO_write(bp, "        Subject Public Key Info:\n", 33) <= 0)
+            goto err;
+        if (BIO_printf(bp, "%12sPublic Key Algorithm: ", "") <= 0)
+            goto err;
+        if (i2a_ASN1_OBJECT(bp, ci->key->algor->algorithm) <= 0)
+            goto err;
+        if (BIO_puts(bp, "\n") <= 0)
+            goto err;
 
-		pkey=X509_get_pubkey(x);
-		if (pkey == NULL)
-			{
-			BIO_printf(bp,"%12sUnable to load Public Key\n","");
-			BIO_print_errors(bp);
-			}
-		else
-			{
-			EVP_PKEY_print_public(bp, pkey, 16, NULL);
-			EVP_PKEY_free(pkey);
-			}
-		}
+        pkey = X509_get_pubkey(x);
+        if (pkey == NULL) {
+            BIO_printf(bp, "%12sUnable to load Public Key\n", "");
+            ERR_print_errors(bp);
+        } else {
+            EVP_PKEY_print_public(bp, pkey, 16, NULL);
+            EVP_PKEY_free(pkey);
+        }
+    }
 
-	if(!(cflag & X509_FLAG_NO_IDS))
-		{
-		if (ci->issuerUID)
-			{
-			if (BIO_printf(bp,"%8sIssuer Unique ID: ","") <= 0) 
-				goto err;
-			if (!X509_signature_dump(bp, ci->issuerUID, 12))
-				goto err;
-			}
-		if (ci->subjectUID)
-			{
-			if (BIO_printf(bp,"%8sSubject Unique ID: ","") <= 0) 
-				goto err;
-			if (!X509_signature_dump(bp, ci->subjectUID, 12))
-				goto err;
-			}
-		}
+    if (!(cflag & X509_FLAG_NO_IDS)) {
+        if (ci->issuerUID) {
+            if (BIO_printf(bp, "%8sIssuer Unique ID: ", "") <= 0)
+                goto err;
+            if (!X509_signature_dump(bp, ci->issuerUID, 12))
+                goto err;
+        }
+        if (ci->subjectUID) {
+            if (BIO_printf(bp, "%8sSubject Unique ID: ", "") <= 0)
+                goto err;
+            if (!X509_signature_dump(bp, ci->subjectUID, 12))
+                goto err;
+        }
+    }
 
-	if (!(cflag & X509_FLAG_NO_EXTENSIONS))
-		X509V3_extensions_print(bp, "X509v3 extensions",
-					ci->extensions, cflag, 8);
+    if (!(cflag & X509_FLAG_NO_EXTENSIONS))
+        X509V3_extensions_print(bp, "X509v3 extensions",
+                                ci->extensions, cflag, 8);
 
-	if(!(cflag & X509_FLAG_NO_SIGDUMP))
-		{
-		if(X509_signature_print(bp, x->sig_alg, x->signature) <= 0) goto err;
-		}
-	if(!(cflag & X509_FLAG_NO_AUX))
-		{
-		if (!X509_CERT_AUX_print(bp, x->aux, 0)) goto err;
-		}
-	ret=1;
-err:
-	if (m != NULL) OPENSSL_free(m);
-	return(ret);
-	}
+    if (!(cflag & X509_FLAG_NO_SIGDUMP)) {
+        if (X509_signature_print(bp, x->sig_alg, x->signature) <= 0)
+            goto err;
+    }
+    if (!(cflag & X509_FLAG_NO_AUX)) {
+        if (!X509_CERT_AUX_print(bp, x->aux, 0))
+            goto err;
+    }
+    ret = 1;
+ err:
+    if (m != NULL)
+        OPENSSL_free(m);
+    return (ret);
+}
 
-int X509_ocspid_print (BIO *bp, X509 *x)
-	{
-	unsigned char *der=NULL ;
-	unsigned char *dertmp;
-	int derlen;
-	int i;
-	unsigned char SHA1md[SHA_DIGEST_LENGTH];
+int X509_ocspid_print(BIO *bp, X509 *x)
+{
+    unsigned char *der = NULL;
+    unsigned char *dertmp;
+    int derlen;
+    int i;
+    unsigned char SHA1md[SHA_DIGEST_LENGTH];
 
-	/* display the hash of the subject as it would appear
-	   in OCSP requests */
-	if (BIO_printf(bp,"        Subject OCSP hash: ") <= 0)
-		goto err;
-	derlen = i2d_X509_NAME(x->cert_info->subject, NULL);
-	if ((der = dertmp = (unsigned char *)OPENSSL_malloc (derlen)) == NULL)
-		goto err;
-	i2d_X509_NAME(x->cert_info->subject, &dertmp);
+    /*
+     * display the hash of the subject as it would appear in OCSP requests
+     */
+    if (BIO_printf(bp, "        Subject OCSP hash: ") <= 0)
+        goto err;
+    derlen = i2d_X509_NAME(x->cert_info->subject, NULL);
+    if ((der = dertmp = (unsigned char *)OPENSSL_malloc(derlen)) == NULL)
+        goto err;
+    i2d_X509_NAME(x->cert_info->subject, &dertmp);
 
-	if (!EVP_Digest(der, derlen, SHA1md, NULL, EVP_sha1(), NULL))
-		goto err;
-	for (i=0; i < SHA_DIGEST_LENGTH; i++)
-		{
-		if (BIO_printf(bp,"%02X",SHA1md[i]) <= 0) goto err;
-		}
-	OPENSSL_free (der);
-	der=NULL;
+    if (!EVP_Digest(der, derlen, SHA1md, NULL, EVP_sha1(), NULL))
+        goto err;
+    for (i = 0; i < SHA_DIGEST_LENGTH; i++) {
+        if (BIO_printf(bp, "%02X", SHA1md[i]) <= 0)
+            goto err;
+    }
+    OPENSSL_free(der);
+    der = NULL;
 
-	/* display the hash of the public key as it would appear
-	   in OCSP requests */
-	if (BIO_printf(bp,"\n        Public key OCSP hash: ") <= 0)
-		goto err;
+    /*
+     * display the hash of the public key as it would appear in OCSP requests
+     */
+    if (BIO_printf(bp, "\n        Public key OCSP hash: ") <= 0)
+        goto err;
 
-	if (!EVP_Digest(x->cert_info->key->public_key->data,
-			x->cert_info->key->public_key->length,
-			SHA1md, NULL, EVP_sha1(), NULL))
-		goto err;
-	for (i=0; i < SHA_DIGEST_LENGTH; i++)
-		{
-		if (BIO_printf(bp,"%02X",SHA1md[i]) <= 0)
-			goto err;
-		}
-	BIO_printf(bp,"\n");
+    if (!EVP_Digest(x->cert_info->key->public_key->data,
+                    x->cert_info->key->public_key->length,
+                    SHA1md, NULL, EVP_sha1(), NULL))
+        goto err;
+    for (i = 0; i < SHA_DIGEST_LENGTH; i++) {
+        if (BIO_printf(bp, "%02X", SHA1md[i]) <= 0)
+            goto err;
+    }
+    BIO_printf(bp, "\n");
 
-	return (1);
-err:
-	if (der != NULL) OPENSSL_free(der);
-	return(0);
-	}
+    return (1);
+ err:
+    if (der != NULL)
+        OPENSSL_free(der);
+    return (0);
+}
 
 int X509_signature_print(BIO *bp, X509_ALGOR *sigalg, ASN1_STRING *sig)
 {
-	int sig_nid;
-	if (BIO_puts(bp,"    Signature Algorithm: ") <= 0) return 0;
-	if (i2a_ASN1_OBJECT(bp, sigalg->algorithm) <= 0) return 0;
+    if (BIO_puts(bp, "    Signature Algorithm: ") <= 0)
+        return 0;
+    if (i2a_ASN1_OBJECT(bp, sigalg->algorithm) <= 0)
+        return 0;
 
-	sig_nid = OBJ_obj2nid(sigalg->algorithm);
-	if (sig_nid != NID_undef)
-		{
-		int pkey_nid, dig_nid;
-		const EVP_PKEY_ASN1_METHOD *ameth;
-		if (OBJ_find_sigid_algs(sig_nid, &dig_nid, &pkey_nid))
-			{
-			ameth = EVP_PKEY_asn1_find(NULL, pkey_nid);
-			if (ameth && ameth->sig_print)
-				return ameth->sig_print(bp, sigalg, sig, 9, 0);
-			}
-		}
-	if (sig)
-		return X509_signature_dump(bp, sig, 9);
-	else if (BIO_puts(bp, "\n") <= 0)
-		return 0;
-	return 1;
+    /* RSA-PSS signatures have parameters to print. */
+    int sig_nid = OBJ_obj2nid(sigalg->algorithm);
+    if (sig_nid == NID_rsassaPss &&
+        !x509_print_rsa_pss_params(bp, sigalg, 9, 0)) {
+        return 0;
+    }
+
+    if (sig)
+        return X509_signature_dump(bp, sig, 9);
+    else if (BIO_puts(bp, "\n") <= 0)
+        return 0;
+    return 1;
 }
 
 int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v)
-	{
-	int i,n;
-	char buf[80];
-	const char *p;
+{
+    int i, n;
+    char buf[80];
+    const char *p;
 
-	if (v == NULL) return(0);
-	n=0;
-	p=(const char *)v->data;
-	for (i=0; i<v->length; i++)
-		{
-		if ((p[i] > '~') || ((p[i] < ' ') &&
-			(p[i] != '\n') && (p[i] != '\r')))
-			buf[n]='.';
-		else
-			buf[n]=p[i];
-		n++;
-		if (n >= 80)
-			{
-			if (BIO_write(bp,buf,n) <= 0)
-				return(0);
-			n=0;
-			}
-		}
-	if (n > 0)
-		if (BIO_write(bp,buf,n) <= 0)
-			return(0);
-	return(1);
-	}
+    if (v == NULL)
+        return (0);
+    n = 0;
+    p = (const char *)v->data;
+    for (i = 0; i < v->length; i++) {
+        if ((p[i] > '~') || ((p[i] < ' ') &&
+                             (p[i] != '\n') && (p[i] != '\r')))
+            buf[n] = '.';
+        else
+            buf[n] = p[i];
+        n++;
+        if (n >= 80) {
+            if (BIO_write(bp, buf, n) <= 0)
+                return (0);
+            n = 0;
+        }
+    }
+    if (n > 0)
+        if (BIO_write(bp, buf, n) <= 0)
+            return (0);
+    return (1);
+}
 
 int ASN1_TIME_print(BIO *bp, const ASN1_TIME *tm)
 {
-	if(tm->type == V_ASN1_UTCTIME) return ASN1_UTCTIME_print(bp, tm);
-	if(tm->type == V_ASN1_GENERALIZEDTIME)
-				return ASN1_GENERALIZEDTIME_print(bp, tm);
-	BIO_write(bp,"Bad time value",14);
-	return(0);
+    if (tm->type == V_ASN1_UTCTIME)
+        return ASN1_UTCTIME_print(bp, tm);
+    if (tm->type == V_ASN1_GENERALIZEDTIME)
+        return ASN1_GENERALIZEDTIME_print(bp, tm);
+    BIO_write(bp, "Bad time value", 14);
+    return (0);
 }
 
-static const char *const mon[12]=
-    {
-    "Jan","Feb","Mar","Apr","May","Jun",
-    "Jul","Aug","Sep","Oct","Nov","Dec"
-    };
+static const char *const mon[12] = {
+    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
 
 int ASN1_GENERALIZEDTIME_print(BIO *bp, const ASN1_GENERALIZEDTIME *tm)
-	{
-	char *v;
-	int gmt=0;
-	int i;
-	int y=0,M=0,d=0,h=0,m=0,s=0;
-	char *f = NULL;
-	int f_len = 0;
+{
+    char *v;
+    int gmt = 0;
+    int i;
+    int y = 0, M = 0, d = 0, h = 0, m = 0, s = 0;
+    char *f = NULL;
+    int f_len = 0;
 
-	i=tm->length;
-	v=(char *)tm->data;
+    i = tm->length;
+    v = (char *)tm->data;
 
-	if (i < 12) goto err;
-	if (v[i-1] == 'Z') gmt=1;
-	for (i=0; i<12; i++)
-		if ((v[i] > '9') || (v[i] < '0')) goto err;
-	y= (v[0]-'0')*1000+(v[1]-'0')*100 + (v[2]-'0')*10+(v[3]-'0');
-	M= (v[4]-'0')*10+(v[5]-'0');
-	if ((M > 12) || (M < 1)) goto err;
-	d= (v[6]-'0')*10+(v[7]-'0');
-	h= (v[8]-'0')*10+(v[9]-'0');
-	m=  (v[10]-'0')*10+(v[11]-'0');
-	if (tm->length >= 14 &&
-	    (v[12] >= '0') && (v[12] <= '9') &&
-	    (v[13] >= '0') && (v[13] <= '9'))
-		{
-		s=  (v[12]-'0')*10+(v[13]-'0');
-		/* Check for fractions of seconds. */
-		if (tm->length >= 15 && v[14] == '.')
-			{
-			int l = tm->length;
-			f = &v[14];	/* The decimal point. */
-			f_len = 1;
-			while (14 + f_len < l && f[f_len] >= '0' && f[f_len] <= '9')
-				++f_len;
-			}
-		}
+    if (i < 12)
+        goto err;
+    if (v[i - 1] == 'Z')
+        gmt = 1;
+    for (i = 0; i < 12; i++)
+        if ((v[i] > '9') || (v[i] < '0'))
+            goto err;
+    y = (v[0] - '0') * 1000 + (v[1] - '0') * 100 + (v[2] - '0') * 10 + (v[3] -
+                                                                        '0');
+    M = (v[4] - '0') * 10 + (v[5] - '0');
+    if ((M > 12) || (M < 1))
+        goto err;
+    d = (v[6] - '0') * 10 + (v[7] - '0');
+    h = (v[8] - '0') * 10 + (v[9] - '0');
+    m = (v[10] - '0') * 10 + (v[11] - '0');
+    if (tm->length >= 14 &&
+        (v[12] >= '0') && (v[12] <= '9') &&
+        (v[13] >= '0') && (v[13] <= '9')) {
+        s = (v[12] - '0') * 10 + (v[13] - '0');
+        /* Check for fractions of seconds. */
+        if (tm->length >= 15 && v[14] == '.') {
+            int l = tm->length;
+            f = &v[14];         /* The decimal point. */
+            f_len = 1;
+            while (14 + f_len < l && f[f_len] >= '0' && f[f_len] <= '9')
+                ++f_len;
+        }
+    }
 
-	if (BIO_printf(bp,"%s %2d %02d:%02d:%02d%.*s %d%s",
-		mon[M-1],d,h,m,s,f_len,f,y,(gmt)?" GMT":"") <= 0)
-		return(0);
-	else
-		return(1);
+    if (BIO_printf(bp, "%s %2d %02d:%02d:%02d%.*s %d%s",
+                   mon[M - 1], d, h, m, s, f_len, f, y,
+                   (gmt) ? " GMT" : "") <= 0)
+        return (0);
+    else
+        return (1);
+ err:
+    BIO_write(bp, "Bad time value", 14);
+    return (0);
+}
+
+// consume_two_digits is a helper function for ASN1_UTCTIME_print. If |*v|,
+// assumed to be |*len| bytes long, has two leading digits, updates |*out| with
+// their value, updates |v| and |len|, and returns one. Otherwise, returns
+// zero.
+static int consume_two_digits(int* out, const char **v, int *len) {
+  if (*len < 2|| !isdigit((*v)[0]) || !isdigit((*v)[1])) {
+    return 0;
+  }
+  *out = ((*v)[0] - '0') * 10 + ((*v)[1] - '0');
+  *len -= 2;
+  *v += 2;
+  return 1;
+}
+
+// consume_zulu_timezone is a helper function for ASN1_UTCTIME_print. If |*v|,
+// assumed to be |*len| bytes long, starts with "Z" then it updates |*v| and
+// |*len| and returns one. Otherwise returns zero.
+static int consume_zulu_timezone(const char **v, int *len) {
+  if (*len == 0 || (*v)[0] != 'Z') {
+    return 0;
+  }
+
+  *len -= 1;
+  *v += 1;
+  return 1;
+}
+
+int ASN1_UTCTIME_print(BIO *bp, const ASN1_UTCTIME *tm) {
+  const char *v = (const char *)tm->data;
+  int len = tm->length;
+  int Y = 0, M = 0, D = 0, h = 0, m = 0, s = 0;
+
+  // YYMMDDhhmm are required to be present.
+  if (!consume_two_digits(&Y, &v, &len) ||
+      !consume_two_digits(&M, &v, &len) ||
+      !consume_two_digits(&D, &v, &len) ||
+      !consume_two_digits(&h, &v, &len) ||
+      !consume_two_digits(&m, &v, &len)) {
+    goto err;
+  }
+  // https://tools.ietf.org/html/rfc5280, section 4.1.2.5.1, requires seconds
+  // to be present, but historically this code has forgiven its absence.
+  consume_two_digits(&s, &v, &len);
+
+  // https://tools.ietf.org/html/rfc5280, section 4.1.2.5.1, specifies this
+  // interpretation of the year.
+  if (Y < 50) {
+    Y += 2000;
+  } else {
+    Y += 1900;
+  }
+  if (M > 12 || M == 0) {
+    goto err;
+  }
+  if (D > 31 || D == 0) {
+    goto err;
+  }
+  if (h > 23 || m > 59 || s > 60) {
+    goto err;
+  }
+
+  // https://tools.ietf.org/html/rfc5280, section 4.1.2.5.1, requires the "Z"
+  // to be present, but historically this code has forgiven its absence.
+  const int is_gmt = consume_zulu_timezone(&v, &len);
+
+  // https://tools.ietf.org/html/rfc5280, section 4.1.2.5.1, does not permit
+  // the specification of timezones using the +hhmm / -hhmm syntax, which is
+  // the only other thing that might legitimately be found at the end.
+  if (len) {
+    goto err;
+  }
+
+  return BIO_printf(bp, "%s %2d %02d:%02d:%02d %d%s", mon[M - 1], D, h, m, s, Y,
+                    is_gmt ? " GMT" : "") > 0;
+
 err:
-	BIO_write(bp,"Bad time value",14);
-	return(0);
-	}
-
-int ASN1_UTCTIME_print(BIO *bp, const ASN1_UTCTIME *tm)
-	{
-	const char *v;
-	int gmt=0;
-	int i;
-	int y=0,M=0,d=0,h=0,m=0,s=0;
-
-	i=tm->length;
-	v=(const char *)tm->data;
-
-	if (i < 10) goto err;
-	if (v[i-1] == 'Z') gmt=1;
-	for (i=0; i<10; i++)
-		if ((v[i] > '9') || (v[i] < '0')) goto err;
-	y= (v[0]-'0')*10+(v[1]-'0');
-	if (y < 50) y+=100;
-	M= (v[2]-'0')*10+(v[3]-'0');
-	if ((M > 12) || (M < 1)) goto err;
-	d= (v[4]-'0')*10+(v[5]-'0');
-	h= (v[6]-'0')*10+(v[7]-'0');
-	m=  (v[8]-'0')*10+(v[9]-'0');
-	if (tm->length >=12 &&
-	    (v[10] >= '0') && (v[10] <= '9') &&
-	    (v[11] >= '0') && (v[11] <= '9'))
-		s=  (v[10]-'0')*10+(v[11]-'0');
-
-	if (BIO_printf(bp,"%s %2d %02d:%02d:%02d %d%s",
-		mon[M-1],d,h,m,s,y+1900,(gmt)?" GMT":"") <= 0)
-		return(0);
-	else
-		return(1);
-err:
-	BIO_write(bp,"Bad time value",14);
-	return(0);
-	}
+  BIO_write(bp, "Bad time value", 14);
+  return 0;
+}
 
 int X509_NAME_print(BIO *bp, X509_NAME *name, int obase)
-	{
-	char *s,*c,*b;
-	int ret=0,l,i;
+{
+    char *s, *c, *b;
+    int ret = 0, l, i;
 
-	l=80-2-obase;
+    l = 80 - 2 - obase;
 
-	b=X509_NAME_oneline(name,NULL,0);
-	if (!b)
-		return 0;
-	if (!*b)
-		{
-		OPENSSL_free(b);
-		return 1;
-		}
-	s=b+1; /* skip the first slash */
+    b = X509_NAME_oneline(name, NULL, 0);
+    if (!b)
+        return 0;
+    if (!*b) {
+        OPENSSL_free(b);
+        return 1;
+    }
+    s = b + 1;                  /* skip the first slash */
 
-	c=s;
-	for (;;)
-		{
-		if (	((*s == '/') &&
-				((s[1] >= 'A') && (s[1] <= 'Z') && (
-					(s[2] == '=') ||
-					((s[2] >= 'A') && (s[2] <= 'Z') &&
-					(s[3] == '='))
-				 ))) ||
-			(*s == '\0'))
-			{
-			i=s-c;
-			if (BIO_write(bp,c,i) != i) goto err;
-			c=s+1;	/* skip following slash */
-			if (*s != '\0')
-				{
-				if (BIO_write(bp,", ",2) != 2) goto err;
-				}
-			l--;
-			}
-		if (*s == '\0') break;
-		s++;
-		l--;
-		}
-	
-	ret=1;
-	if (0)
-		{
-err:
-		OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB);
-		}
-	OPENSSL_free(b);
-	return(ret);
-	}
+    c = s;
+    for (;;) {
+        if (((*s == '/') &&
+             ((s[1] >= 'A') && (s[1] <= 'Z') && ((s[2] == '=') ||
+                                                 ((s[2] >= 'A')
+                                                  && (s[2] <= 'Z')
+                                                  && (s[3] == '='))
+              ))) || (*s == '\0')) {
+            i = s - c;
+            if (BIO_write(bp, c, i) != i)
+                goto err;
+            c = s + 1;          /* skip following slash */
+            if (*s != '\0') {
+                if (BIO_write(bp, ", ", 2) != 2)
+                    goto err;
+            }
+            l--;
+        }
+        if (*s == '\0')
+            break;
+        s++;
+        l--;
+    }
+
+    ret = 1;
+    if (0) {
+ err:
+        OPENSSL_PUT_ERROR(X509, ERR_R_BUF_LIB);
+    }
+    OPENSSL_free(b);
+    return (ret);
+}
diff --git a/src/crypto/x509/t_x509a.c b/src/crypto/x509/t_x509a.c
index 7667268..5436828 100644
--- a/src/crypto/x509/t_x509a.c
+++ b/src/crypto/x509/t_x509a.c
@@ -60,50 +60,52 @@
 #include <openssl/obj.h>
 #include <openssl/x509.h>
 
-
 /* X509_CERT_AUX and string set routines */
 
 int X509_CERT_AUX_print(BIO *out, X509_CERT_AUX *aux, int indent)
 {
-	char oidstr[80], first;
-	size_t i;
-	int j;
-	if(!aux) return 1;
-	if(aux->trust) {
-		first = 1;
-		BIO_printf(out, "%*sTrusted Uses:\n%*s",
-						indent, "", indent + 2, "");
-		for(i = 0; i < sk_ASN1_OBJECT_num(aux->trust); i++) {
-			if(!first) BIO_puts(out, ", ");
-			else first = 0;
-			OBJ_obj2txt(oidstr, sizeof oidstr,
-				sk_ASN1_OBJECT_value(aux->trust, i), 0);
-			BIO_puts(out, oidstr);
-		}
-		BIO_puts(out, "\n");
-	} else BIO_printf(out, "%*sNo Trusted Uses.\n", indent, "");
-	if(aux->reject) {
-		first = 1;
-		BIO_printf(out, "%*sRejected Uses:\n%*s",
-						indent, "", indent + 2, "");
-		for(i = 0; i < sk_ASN1_OBJECT_num(aux->reject); i++) {
-			if(!first) BIO_puts(out, ", ");
-			else first = 0;
-			OBJ_obj2txt(oidstr, sizeof oidstr,
-				sk_ASN1_OBJECT_value(aux->reject, i), 0);
-			BIO_puts(out, oidstr);
-		}
-		BIO_puts(out, "\n");
-	} else BIO_printf(out, "%*sNo Rejected Uses.\n", indent, "");
-	if(aux->alias) BIO_printf(out, "%*sAlias: %s\n", indent, "",
-							aux->alias->data);
-	if(aux->keyid) {
-		BIO_printf(out, "%*sKey Id: ", indent, "");
-		for(j = 0; j < aux->keyid->length; j++)
-			BIO_printf(out, "%s%02X",
-				j ? ":" : "",
-				aux->keyid->data[j]);
-		BIO_write(out,"\n",1);
-	}
-	return 1;
+    char oidstr[80], first;
+    size_t i;
+    int j;
+    if (!aux)
+        return 1;
+    if (aux->trust) {
+        first = 1;
+        BIO_printf(out, "%*sTrusted Uses:\n%*s", indent, "", indent + 2, "");
+        for (i = 0; i < sk_ASN1_OBJECT_num(aux->trust); i++) {
+            if (!first)
+                BIO_puts(out, ", ");
+            else
+                first = 0;
+            OBJ_obj2txt(oidstr, sizeof oidstr,
+                        sk_ASN1_OBJECT_value(aux->trust, i), 0);
+            BIO_puts(out, oidstr);
+        }
+        BIO_puts(out, "\n");
+    } else
+        BIO_printf(out, "%*sNo Trusted Uses.\n", indent, "");
+    if (aux->reject) {
+        first = 1;
+        BIO_printf(out, "%*sRejected Uses:\n%*s", indent, "", indent + 2, "");
+        for (i = 0; i < sk_ASN1_OBJECT_num(aux->reject); i++) {
+            if (!first)
+                BIO_puts(out, ", ");
+            else
+                first = 0;
+            OBJ_obj2txt(oidstr, sizeof oidstr,
+                        sk_ASN1_OBJECT_value(aux->reject, i), 0);
+            BIO_puts(out, oidstr);
+        }
+        BIO_puts(out, "\n");
+    } else
+        BIO_printf(out, "%*sNo Rejected Uses.\n", indent, "");
+    if (aux->alias)
+        BIO_printf(out, "%*sAlias: %s\n", indent, "", aux->alias->data);
+    if (aux->keyid) {
+        BIO_printf(out, "%*sKey Id: ", indent, "");
+        for (j = 0; j < aux->keyid->length; j++)
+            BIO_printf(out, "%s%02X", j ? ":" : "", aux->keyid->data[j]);
+        BIO_write(out, "\n", 1);
+    }
+    return 1;
 }
diff --git a/src/crypto/x509/vpm_int.h b/src/crypto/x509/vpm_int.h
index 9edbd5a..9c55def 100644
--- a/src/crypto/x509/vpm_int.h
+++ b/src/crypto/x509/vpm_int.h
@@ -1,6 +1,7 @@
 /* vpm_int.h */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 2013.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 2013.
  */
 /* ====================================================================
  * Copyright (c) 2013 The OpenSSL Project.  All rights reserved.
@@ -10,7 +11,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -58,13 +59,12 @@
 
 /* internal only structure to hold additional X509_VERIFY_PARAM data */
 
-struct X509_VERIFY_PARAM_ID_st
-	{
-	STACK_OF(OPENSSL_STRING) *hosts;	/* Set of acceptable names */
-	unsigned int hostflags;	/* Flags to control matching features */
-	char *peername;		/* Matching hostname in peer certificate */
-	char *email;		/* If not NULL email address to match */
-	size_t emaillen;
-	unsigned char *ip;	/* If not NULL IP address to match */
-	size_t iplen;		/* Length of IP address */
-	};
+struct X509_VERIFY_PARAM_ID_st {
+    STACK_OF(OPENSSL_STRING) *hosts; /* Set of acceptable names */
+    unsigned int hostflags;     /* Flags to control matching features */
+    char *peername;             /* Matching hostname in peer certificate */
+    char *email;                /* If not NULL email address to match */
+    size_t emaillen;
+    unsigned char *ip;          /* If not NULL IP address to match */
+    size_t iplen;               /* Length of IP address */
+};
diff --git a/src/crypto/x509/x509.c b/src/crypto/x509/x509.c
index 31f9e1e..188fd49 100644
--- a/src/crypto/x509/x509.c
+++ b/src/crypto/x509/x509.c
@@ -57,9 +57,14 @@
 #include <openssl/x509.h>
 
 #include <openssl/bio.h>
+#include <openssl/err.h>
 #include <openssl/mem.h>
 
 
+/* |X509_R_UNSUPPORTED_ALGORITHM| is no longer emitted, but continue to define
+ * it to avoid downstream churn. */
+OPENSSL_DECLARE_ERROR_REASON(X509, UNSUPPORTED_ALGORITHM)
+
 int PKCS8_pkey_set0(PKCS8_PRIV_KEY_INFO *priv, ASN1_OBJECT *aobj, int version,
                     int ptype, void *pval, uint8_t *penc, int penclen) {
   uint8_t **ppenc = NULL;
diff --git a/src/crypto/x509/x509_att.c b/src/crypto/x509/x509_att.c
index 1491484..85d65e7 100644
--- a/src/crypto/x509/x509_att.c
+++ b/src/crypto/x509/x509_att.c
@@ -62,292 +62,320 @@
 #include <openssl/stack.h>
 #include <openssl/x509.h>
 
-
 int X509at_get_attr_count(const STACK_OF(X509_ATTRIBUTE) *x)
 {
-	return sk_X509_ATTRIBUTE_num(x);
+    return sk_X509_ATTRIBUTE_num(x);
 }
 
 int X509at_get_attr_by_NID(const STACK_OF(X509_ATTRIBUTE) *x, int nid,
-			  int lastpos)
+                           int lastpos)
 {
-	const ASN1_OBJECT *obj;
+    const ASN1_OBJECT *obj;
 
-	obj=OBJ_nid2obj(nid);
-	if (obj == NULL) return(-2);
-	return(X509at_get_attr_by_OBJ(x,obj,lastpos));
+    obj = OBJ_nid2obj(nid);
+    if (obj == NULL)
+        return (-2);
+    return (X509at_get_attr_by_OBJ(x, obj, lastpos));
 }
 
-int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk, const ASN1_OBJECT *obj,
-			  int lastpos)
+int X509at_get_attr_by_OBJ(const STACK_OF(X509_ATTRIBUTE) *sk,
+                           const ASN1_OBJECT *obj, int lastpos)
 {
-	int n;
-	X509_ATTRIBUTE *ex;
+    int n;
+    X509_ATTRIBUTE *ex;
 
-	if (sk == NULL) return(-1);
-	lastpos++;
-	if (lastpos < 0)
-		lastpos=0;
-	n=sk_X509_ATTRIBUTE_num(sk);
-	for ( ; lastpos < n; lastpos++)
-		{
-		ex=sk_X509_ATTRIBUTE_value(sk,lastpos);
-		if (OBJ_cmp(ex->object,obj) == 0)
-			return(lastpos);
-		}
-	return(-1);
+    if (sk == NULL)
+        return (-1);
+    lastpos++;
+    if (lastpos < 0)
+        lastpos = 0;
+    n = sk_X509_ATTRIBUTE_num(sk);
+    for (; lastpos < n; lastpos++) {
+        ex = sk_X509_ATTRIBUTE_value(sk, lastpos);
+        if (OBJ_cmp(ex->object, obj) == 0)
+            return (lastpos);
+    }
+    return (-1);
 }
 
 X509_ATTRIBUTE *X509at_get_attr(const STACK_OF(X509_ATTRIBUTE) *x, int loc)
 {
-	if (x == NULL || loc < 0 || sk_X509_ATTRIBUTE_num(x) <= (size_t) loc)
-		return NULL;
-	else
-		return sk_X509_ATTRIBUTE_value(x,loc);
+    if (x == NULL || loc < 0 || sk_X509_ATTRIBUTE_num(x) <= (size_t)loc)
+        return NULL;
+    else
+        return sk_X509_ATTRIBUTE_value(x, loc);
 }
 
 X509_ATTRIBUTE *X509at_delete_attr(STACK_OF(X509_ATTRIBUTE) *x, int loc)
 {
-	X509_ATTRIBUTE *ret;
+    X509_ATTRIBUTE *ret;
 
-	if (x == NULL || loc < 0 || sk_X509_ATTRIBUTE_num(x) <= (size_t) loc)
-		return(NULL);
-	ret=sk_X509_ATTRIBUTE_delete(x,loc);
-	return(ret);
+    if (x == NULL || loc < 0 || sk_X509_ATTRIBUTE_num(x) <= (size_t)loc)
+        return (NULL);
+    ret = sk_X509_ATTRIBUTE_delete(x, loc);
+    return (ret);
 }
 
 STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr(STACK_OF(X509_ATTRIBUTE) **x,
-					 X509_ATTRIBUTE *attr)
+                                           X509_ATTRIBUTE *attr)
 {
-	X509_ATTRIBUTE *new_attr=NULL;
-	STACK_OF(X509_ATTRIBUTE) *sk=NULL;
+    X509_ATTRIBUTE *new_attr = NULL;
+    STACK_OF(X509_ATTRIBUTE) *sk = NULL;
 
-	if (x == NULL)
-		{
-		OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER);
-		goto err2;
-		} 
+    if (x == NULL) {
+        OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER);
+        goto err2;
+    }
 
-	if (*x == NULL)
-		{
-		if ((sk=sk_X509_ATTRIBUTE_new_null()) == NULL)
-			goto err;
-		}
-	else
-		sk= *x;
+    if (*x == NULL) {
+        if ((sk = sk_X509_ATTRIBUTE_new_null()) == NULL)
+            goto err;
+    } else
+        sk = *x;
 
-	if ((new_attr=X509_ATTRIBUTE_dup(attr)) == NULL)
-		goto err2;
-	if (!sk_X509_ATTRIBUTE_push(sk,new_attr))
-		goto err;
-	if (*x == NULL)
-		*x=sk;
-	return(sk);
-err:
-	OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-err2:
-	if (new_attr != NULL) X509_ATTRIBUTE_free(new_attr);
-	if (sk != NULL) sk_X509_ATTRIBUTE_free(sk);
-	return(NULL);
+    if ((new_attr = X509_ATTRIBUTE_dup(attr)) == NULL)
+        goto err2;
+    if (!sk_X509_ATTRIBUTE_push(sk, new_attr))
+        goto err;
+    if (*x == NULL)
+        *x = sk;
+    return (sk);
+ err:
+    OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ err2:
+    if (new_attr != NULL)
+        X509_ATTRIBUTE_free(new_attr);
+    if (sk != NULL)
+        sk_X509_ATTRIBUTE_free(sk);
+    return (NULL);
 }
 
-STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE) **x,
-			const ASN1_OBJECT *obj, int type,
-			const unsigned char *bytes, int len)
+STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_OBJ(STACK_OF(X509_ATTRIBUTE)
+                                                  **x, const ASN1_OBJECT *obj,
+                                                  int type,
+                                                  const unsigned char *bytes,
+                                                  int len)
 {
-	X509_ATTRIBUTE *attr;
-	STACK_OF(X509_ATTRIBUTE) *ret;
-	attr = X509_ATTRIBUTE_create_by_OBJ(NULL, obj, type, bytes, len);
-	if(!attr) return 0;
-	ret = X509at_add1_attr(x, attr);
-	X509_ATTRIBUTE_free(attr);
-	return ret;
+    X509_ATTRIBUTE *attr;
+    STACK_OF(X509_ATTRIBUTE) *ret;
+    attr = X509_ATTRIBUTE_create_by_OBJ(NULL, obj, type, bytes, len);
+    if (!attr)
+        return 0;
+    ret = X509at_add1_attr(x, attr);
+    X509_ATTRIBUTE_free(attr);
+    return ret;
 }
 
-STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE) **x,
-			int nid, int type,
-			const unsigned char *bytes, int len)
+STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_NID(STACK_OF(X509_ATTRIBUTE)
+                                                  **x, int nid, int type,
+                                                  const unsigned char *bytes,
+                                                  int len)
 {
-	X509_ATTRIBUTE *attr;
-	STACK_OF(X509_ATTRIBUTE) *ret;
-	attr = X509_ATTRIBUTE_create_by_NID(NULL, nid, type, bytes, len);
-	if(!attr) return 0;
-	ret = X509at_add1_attr(x, attr);
-	X509_ATTRIBUTE_free(attr);
-	return ret;
+    X509_ATTRIBUTE *attr;
+    STACK_OF(X509_ATTRIBUTE) *ret;
+    attr = X509_ATTRIBUTE_create_by_NID(NULL, nid, type, bytes, len);
+    if (!attr)
+        return 0;
+    ret = X509at_add1_attr(x, attr);
+    X509_ATTRIBUTE_free(attr);
+    return ret;
 }
 
-STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE) **x,
-			const char *attrname, int type,
-			const unsigned char *bytes, int len)
+STACK_OF(X509_ATTRIBUTE) *X509at_add1_attr_by_txt(STACK_OF(X509_ATTRIBUTE)
+                                                  **x, const char *attrname,
+                                                  int type,
+                                                  const unsigned char *bytes,
+                                                  int len)
 {
-	X509_ATTRIBUTE *attr;
-	STACK_OF(X509_ATTRIBUTE) *ret;
-	attr = X509_ATTRIBUTE_create_by_txt(NULL, attrname, type, bytes, len);
-	if(!attr) return 0;
-	ret = X509at_add1_attr(x, attr);
-	X509_ATTRIBUTE_free(attr);
-	return ret;
+    X509_ATTRIBUTE *attr;
+    STACK_OF(X509_ATTRIBUTE) *ret;
+    attr = X509_ATTRIBUTE_create_by_txt(NULL, attrname, type, bytes, len);
+    if (!attr)
+        return 0;
+    ret = X509at_add1_attr(x, attr);
+    X509_ATTRIBUTE_free(attr);
+    return ret;
 }
 
 void *X509at_get0_data_by_OBJ(STACK_OF(X509_ATTRIBUTE) *x,
-				ASN1_OBJECT *obj, int lastpos, int type)
+                              ASN1_OBJECT *obj, int lastpos, int type)
 {
-	int i;
-	X509_ATTRIBUTE *at;
-	i = X509at_get_attr_by_OBJ(x, obj, lastpos);
-	if (i == -1)
-		return NULL;
-	if ((lastpos <= -2) && (X509at_get_attr_by_OBJ(x, obj, i) != -1))
-		return NULL;
-	at = X509at_get_attr(x, i);
-	if (lastpos <= -3 && (X509_ATTRIBUTE_count(at) != 1))
-		return NULL;
-	return X509_ATTRIBUTE_get0_data(at, 0, type, NULL);
+    int i;
+    X509_ATTRIBUTE *at;
+    i = X509at_get_attr_by_OBJ(x, obj, lastpos);
+    if (i == -1)
+        return NULL;
+    if ((lastpos <= -2) && (X509at_get_attr_by_OBJ(x, obj, i) != -1))
+        return NULL;
+    at = X509at_get_attr(x, i);
+    if (lastpos <= -3 && (X509_ATTRIBUTE_count(at) != 1))
+        return NULL;
+    return X509_ATTRIBUTE_get0_data(at, 0, type, NULL);
 }
 
 X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_NID(X509_ATTRIBUTE **attr, int nid,
-	     int atrtype, const void *data, int len)
+                                             int atrtype, const void *data,
+                                             int len)
 {
-	const ASN1_OBJECT *obj;
+    const ASN1_OBJECT *obj;
 
-	obj=OBJ_nid2obj(nid);
-	if (obj == NULL)
-		{
-		OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_NID);
-		return(NULL);
-		}
-	return X509_ATTRIBUTE_create_by_OBJ(attr,obj,atrtype,data,len);
+    obj = OBJ_nid2obj(nid);
+    if (obj == NULL) {
+        OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_NID);
+        return (NULL);
+    }
+    return X509_ATTRIBUTE_create_by_OBJ(attr, obj, atrtype, data, len);
 }
 
 X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_OBJ(X509_ATTRIBUTE **attr,
-	     const ASN1_OBJECT *obj, int atrtype, const void *data, int len)
+                                             const ASN1_OBJECT *obj,
+                                             int atrtype, const void *data,
+                                             int len)
 {
-	X509_ATTRIBUTE *ret;
+    X509_ATTRIBUTE *ret;
 
-	if ((attr == NULL) || (*attr == NULL))
-		{
-		if ((ret=X509_ATTRIBUTE_new()) == NULL)
-			{
-			OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-			return(NULL);
-			}
-		}
-	else
-		ret= *attr;
+    if ((attr == NULL) || (*attr == NULL)) {
+        if ((ret = X509_ATTRIBUTE_new()) == NULL) {
+            OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+            return (NULL);
+        }
+    } else
+        ret = *attr;
 
-	if (!X509_ATTRIBUTE_set1_object(ret,obj))
-		goto err;
-	if (!X509_ATTRIBUTE_set1_data(ret,atrtype,data,len))
-		goto err;
+    if (!X509_ATTRIBUTE_set1_object(ret, obj))
+        goto err;
+    if (!X509_ATTRIBUTE_set1_data(ret, atrtype, data, len))
+        goto err;
 
-	if ((attr != NULL) && (*attr == NULL)) *attr=ret;
-	return(ret);
-err:
-	if ((attr == NULL) || (ret != *attr))
-		X509_ATTRIBUTE_free(ret);
-	return(NULL);
+    if ((attr != NULL) && (*attr == NULL))
+        *attr = ret;
+    return (ret);
+ err:
+    if ((attr == NULL) || (ret != *attr))
+        X509_ATTRIBUTE_free(ret);
+    return (NULL);
 }
 
 X509_ATTRIBUTE *X509_ATTRIBUTE_create_by_txt(X509_ATTRIBUTE **attr,
-		const char *atrname, int type, const unsigned char *bytes, int len)
-	{
-	ASN1_OBJECT *obj;
-	X509_ATTRIBUTE *nattr;
+                                             const char *atrname, int type,
+                                             const unsigned char *bytes,
+                                             int len)
+{
+    ASN1_OBJECT *obj;
+    X509_ATTRIBUTE *nattr;
 
-	obj=OBJ_txt2obj(atrname, 0);
-	if (obj == NULL)
-		{
-		OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_NAME);
-		ERR_add_error_data(2, "name=", atrname);
-		return(NULL);
-		}
-	nattr = X509_ATTRIBUTE_create_by_OBJ(attr,obj,type,bytes,len);
-	ASN1_OBJECT_free(obj);
-	return nattr;
-	}
+    obj = OBJ_txt2obj(atrname, 0);
+    if (obj == NULL) {
+        OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_NAME);
+        ERR_add_error_data(2, "name=", atrname);
+        return (NULL);
+    }
+    nattr = X509_ATTRIBUTE_create_by_OBJ(attr, obj, type, bytes, len);
+    ASN1_OBJECT_free(obj);
+    return nattr;
+}
 
 int X509_ATTRIBUTE_set1_object(X509_ATTRIBUTE *attr, const ASN1_OBJECT *obj)
 {
-	if ((attr == NULL) || (obj == NULL))
-		return(0);
-	ASN1_OBJECT_free(attr->object);
-	attr->object=OBJ_dup(obj);
-	return attr->object != NULL;
+    if ((attr == NULL) || (obj == NULL))
+        return (0);
+    ASN1_OBJECT_free(attr->object);
+    attr->object = OBJ_dup(obj);
+    return attr->object != NULL;
 }
 
-int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype, const void *data, int len)
+int X509_ATTRIBUTE_set1_data(X509_ATTRIBUTE *attr, int attrtype,
+                             const void *data, int len)
 {
-	ASN1_TYPE *ttmp;
-	ASN1_STRING *stmp = NULL;
-	int atype = 0;
-	if (!attr) return 0;
-	if(attrtype & MBSTRING_FLAG) {
-		stmp = ASN1_STRING_set_by_NID(NULL, data, len, attrtype,
-						OBJ_obj2nid(attr->object));
-		if(!stmp) {
-			OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB);
-			return 0;
-		}
-		atype = stmp->type;
-	} else if (len != -1){
-		if(!(stmp = ASN1_STRING_type_new(attrtype))) goto err;
-		if(!ASN1_STRING_set(stmp, data, len)) goto err;
-		atype = attrtype;
-	}
-	if(!(attr->value.set = sk_ASN1_TYPE_new_null())) goto err;
-	attr->single = 0;
-	/* This is a bit naughty because the attribute should really have
-	 * at least one value but some types use and zero length SET and
-	 * require this.
-	 */
-	if (attrtype == 0)
-		return 1;
-	if(!(ttmp = ASN1_TYPE_new())) goto err;
-	if ((len == -1) && !(attrtype & MBSTRING_FLAG))
-		{
-		if (!ASN1_TYPE_set1(ttmp, attrtype, data))
-			goto err;
-		}
-	else
-		ASN1_TYPE_set(ttmp, atype, stmp);
-	if(!sk_ASN1_TYPE_push(attr->value.set, ttmp)) goto err;
-	return 1;
-	err:
-	OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-	return 0;
+    ASN1_TYPE *ttmp = NULL;
+    ASN1_STRING *stmp = NULL;
+    int atype = 0;
+    if (!attr)
+        return 0;
+    if (attrtype & MBSTRING_FLAG) {
+        stmp = ASN1_STRING_set_by_NID(NULL, data, len, attrtype,
+                                      OBJ_obj2nid(attr->object));
+        if (!stmp) {
+            OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB);
+            return 0;
+        }
+        atype = stmp->type;
+    } else if (len != -1) {
+        if (!(stmp = ASN1_STRING_type_new(attrtype)))
+            goto err;
+        if (!ASN1_STRING_set(stmp, data, len))
+            goto err;
+        atype = attrtype;
+    }
+    if (!(attr->value.set = sk_ASN1_TYPE_new_null()))
+        goto err;
+    attr->single = 0;
+    /*
+     * This is a bit naughty because the attribute should really have at
+     * least one value but some types use and zero length SET and require
+     * this.
+     */
+    if (attrtype == 0) {
+        ASN1_STRING_free(stmp);
+        return 1;
+    }
+    if (!(ttmp = ASN1_TYPE_new()))
+        goto err;
+    if ((len == -1) && !(attrtype & MBSTRING_FLAG)) {
+        if (!ASN1_TYPE_set1(ttmp, attrtype, data))
+            goto err;
+    } else {
+        ASN1_TYPE_set(ttmp, atype, stmp);
+        stmp = NULL;
+    }
+    if (!sk_ASN1_TYPE_push(attr->value.set, ttmp))
+        goto err;
+    return 1;
+ err:
+    OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+    ASN1_TYPE_free(ttmp);
+    ASN1_STRING_free(stmp);
+    return 0;
 }
 
 int X509_ATTRIBUTE_count(X509_ATTRIBUTE *attr)
 {
-	if(!attr->single) return sk_ASN1_TYPE_num(attr->value.set);
-	if(attr->value.single) return 1;
-	return 0;
+    if (!attr->single)
+        return sk_ASN1_TYPE_num(attr->value.set);
+    if (attr->value.single)
+        return 1;
+    return 0;
 }
 
 ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr)
 {
-	if (attr == NULL) return(NULL);
-	return(attr->object);
+    if (attr == NULL)
+        return (NULL);
+    return (attr->object);
 }
 
 void *X509_ATTRIBUTE_get0_data(X509_ATTRIBUTE *attr, int idx,
-					int atrtype, void *data)
+                               int atrtype, void *data)
 {
-	ASN1_TYPE *ttmp;
-	ttmp = X509_ATTRIBUTE_get0_type(attr, idx);
-	if(!ttmp) return NULL;
-	if(atrtype != ASN1_TYPE_get(ttmp)){
-		OPENSSL_PUT_ERROR(X509, X509_R_WRONG_TYPE);
-		return NULL;
-	}
-	return ttmp->value.ptr;
+    ASN1_TYPE *ttmp;
+    ttmp = X509_ATTRIBUTE_get0_type(attr, idx);
+    if (!ttmp)
+        return NULL;
+    if (atrtype != ASN1_TYPE_get(ttmp)) {
+        OPENSSL_PUT_ERROR(X509, X509_R_WRONG_TYPE);
+        return NULL;
+    }
+    return ttmp->value.ptr;
 }
 
 ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx)
 {
-	if (attr == NULL) return(NULL);
-	if(idx >= X509_ATTRIBUTE_count(attr)) return NULL;
-	if(!attr->single) return sk_ASN1_TYPE_value(attr->value.set, idx);
-	else return attr->value.single;
+    if (attr == NULL)
+        return (NULL);
+    if (idx >= X509_ATTRIBUTE_count(attr))
+        return NULL;
+    if (!attr->single)
+        return sk_ASN1_TYPE_value(attr->value.set, idx);
+    else
+        return attr->value.single;
 }
diff --git a/src/crypto/x509/x509_cmp.c b/src/crypto/x509/x509_cmp.c
index 0e35f3e..98236d9 100644
--- a/src/crypto/x509/x509_cmp.c
+++ b/src/crypto/x509/x509_cmp.c
@@ -67,424 +67,411 @@
 #include <openssl/x509.h>
 #include <openssl/x509v3.h>
 
+#include "../internal.h"
+
 
 int X509_issuer_and_serial_cmp(const X509 *a, const X509 *b)
-	{
-	int i;
-	X509_CINF *ai,*bi;
+{
+    int i;
+    X509_CINF *ai, *bi;
 
-	ai=a->cert_info;
-	bi=b->cert_info;
-	i=M_ASN1_INTEGER_cmp(ai->serialNumber,bi->serialNumber);
-	if (i) return(i);
-	return(X509_NAME_cmp(ai->issuer,bi->issuer));
-	}
+    ai = a->cert_info;
+    bi = b->cert_info;
+    i = M_ASN1_INTEGER_cmp(ai->serialNumber, bi->serialNumber);
+    if (i)
+        return (i);
+    return (X509_NAME_cmp(ai->issuer, bi->issuer));
+}
 
 unsigned long X509_issuer_and_serial_hash(X509 *a)
-	{
-	unsigned long ret=0;
-	EVP_MD_CTX ctx;
-	unsigned char md[16];
-	char *f;
+{
+    unsigned long ret = 0;
+    EVP_MD_CTX ctx;
+    unsigned char md[16];
+    char *f;
 
-	EVP_MD_CTX_init(&ctx);
-	f=X509_NAME_oneline(a->cert_info->issuer,NULL,0);
-	if (!EVP_DigestInit_ex(&ctx, EVP_md5(), NULL))
-		goto err;
-	if (!EVP_DigestUpdate(&ctx,(unsigned char *)f,strlen(f)))
-		goto err;
-	OPENSSL_free(f);
-	if(!EVP_DigestUpdate(&ctx,(unsigned char *)a->cert_info->serialNumber->data,
-		(unsigned long)a->cert_info->serialNumber->length))
-		goto err;
-	if (!EVP_DigestFinal_ex(&ctx,&(md[0]),NULL))
-		goto err;
-	ret=(	((unsigned long)md[0]     )|((unsigned long)md[1]<<8L)|
-		((unsigned long)md[2]<<16L)|((unsigned long)md[3]<<24L)
-		)&0xffffffffL;
-	err:
-	EVP_MD_CTX_cleanup(&ctx);
-	return(ret);
-	}
-	
+    EVP_MD_CTX_init(&ctx);
+    f = X509_NAME_oneline(a->cert_info->issuer, NULL, 0);
+    if (!EVP_DigestInit_ex(&ctx, EVP_md5(), NULL))
+        goto err;
+    if (!EVP_DigestUpdate(&ctx, (unsigned char *)f, strlen(f)))
+        goto err;
+    OPENSSL_free(f);
+    if (!EVP_DigestUpdate
+        (&ctx, (unsigned char *)a->cert_info->serialNumber->data,
+         (unsigned long)a->cert_info->serialNumber->length))
+        goto err;
+    if (!EVP_DigestFinal_ex(&ctx, &(md[0]), NULL))
+        goto err;
+    ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) |
+           ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)
+        ) & 0xffffffffL;
+ err:
+    EVP_MD_CTX_cleanup(&ctx);
+    return (ret);
+}
+
 int X509_issuer_name_cmp(const X509 *a, const X509 *b)
-	{
-	return(X509_NAME_cmp(a->cert_info->issuer,b->cert_info->issuer));
-	}
+{
+    return (X509_NAME_cmp(a->cert_info->issuer, b->cert_info->issuer));
+}
 
 int X509_subject_name_cmp(const X509 *a, const X509 *b)
-	{
-	return(X509_NAME_cmp(a->cert_info->subject,b->cert_info->subject));
-	}
+{
+    return (X509_NAME_cmp(a->cert_info->subject, b->cert_info->subject));
+}
 
 int X509_CRL_cmp(const X509_CRL *a, const X509_CRL *b)
-	{
-	return(X509_NAME_cmp(a->crl->issuer,b->crl->issuer));
-	}
+{
+    return (X509_NAME_cmp(a->crl->issuer, b->crl->issuer));
+}
 
 int X509_CRL_match(const X509_CRL *a, const X509_CRL *b)
-	{
-	return memcmp(a->sha1_hash, b->sha1_hash, 20);
-	}
+{
+    return OPENSSL_memcmp(a->sha1_hash, b->sha1_hash, 20);
+}
 
 X509_NAME *X509_get_issuer_name(X509 *a)
-	{
-	return(a->cert_info->issuer);
-	}
+{
+    return (a->cert_info->issuer);
+}
 
 unsigned long X509_issuer_name_hash(X509 *x)
-	{
-	return(X509_NAME_hash(x->cert_info->issuer));
-	}
+{
+    return (X509_NAME_hash(x->cert_info->issuer));
+}
 
 unsigned long X509_issuer_name_hash_old(X509 *x)
-	{
-	return(X509_NAME_hash_old(x->cert_info->issuer));
-	}
+{
+    return (X509_NAME_hash_old(x->cert_info->issuer));
+}
 
 X509_NAME *X509_get_subject_name(X509 *a)
-	{
-	return(a->cert_info->subject);
-	}
+{
+    return (a->cert_info->subject);
+}
 
 ASN1_INTEGER *X509_get_serialNumber(X509 *a)
-	{
-	return(a->cert_info->serialNumber);
-	}
+{
+    return (a->cert_info->serialNumber);
+}
 
 unsigned long X509_subject_name_hash(X509 *x)
-	{
-	return(X509_NAME_hash(x->cert_info->subject));
-	}
+{
+    return (X509_NAME_hash(x->cert_info->subject));
+}
 
 unsigned long X509_subject_name_hash_old(X509 *x)
-	{
-	return(X509_NAME_hash_old(x->cert_info->subject));
-	}
+{
+    return (X509_NAME_hash_old(x->cert_info->subject));
+}
 
-/* Compare two certificates: they must be identical for
- * this to work. NB: Although "cmp" operations are generally
- * prototyped to take "const" arguments (eg. for use in
- * STACKs), the way X509 handling is - these operations may
- * involve ensuring the hashes are up-to-date and ensuring
- * certain cert information is cached. So this is the point
- * where the "depth-first" constification tree has to halt
- * with an evil cast.
+/*
+ * Compare two certificates: they must be identical for this to work. NB:
+ * Although "cmp" operations are generally prototyped to take "const"
+ * arguments (eg. for use in STACKs), the way X509 handling is - these
+ * operations may involve ensuring the hashes are up-to-date and ensuring
+ * certain cert information is cached. So this is the point where the
+ * "depth-first" constification tree has to halt with an evil cast.
  */
 int X509_cmp(const X509 *a, const X509 *b)
 {
-	int rv;
-	/* ensure hash is valid */
-	X509_check_purpose((X509 *)a, -1, 0);
-	X509_check_purpose((X509 *)b, -1, 0);
+    int rv;
+    /* ensure hash is valid */
+    X509_check_purpose((X509 *)a, -1, 0);
+    X509_check_purpose((X509 *)b, -1, 0);
 
-	rv = memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH);
-	if (rv)
-		return rv;
-	/* Check for match against stored encoding too */
-	if (!a->cert_info->enc.modified && !b->cert_info->enc.modified)
-		{
-		rv = (int)(a->cert_info->enc.len - b->cert_info->enc.len);
-		if (rv)
-			return rv;
-		return memcmp(a->cert_info->enc.enc, b->cert_info->enc.enc,
-				a->cert_info->enc.len);
-		}
-	return rv;
+    rv = OPENSSL_memcmp(a->sha1_hash, b->sha1_hash, SHA_DIGEST_LENGTH);
+    if (rv)
+        return rv;
+    /* Check for match against stored encoding too */
+    if (!a->cert_info->enc.modified && !b->cert_info->enc.modified) {
+        rv = (int)(a->cert_info->enc.len - b->cert_info->enc.len);
+        if (rv)
+            return rv;
+        return OPENSSL_memcmp(a->cert_info->enc.enc, b->cert_info->enc.enc,
+                              a->cert_info->enc.len);
+    }
+    return rv;
 }
 
-
 int X509_NAME_cmp(const X509_NAME *a, const X509_NAME *b)
-	{
-	int ret;
+{
+    int ret;
 
-	/* Ensure canonical encoding is present and up to date */
+    /* Ensure canonical encoding is present and up to date */
 
-	if (!a->canon_enc || a->modified)
-		{
-		ret = i2d_X509_NAME((X509_NAME *)a, NULL);
-		if (ret < 0)
-			return -2;
-		}
+    if (!a->canon_enc || a->modified) {
+        ret = i2d_X509_NAME((X509_NAME *)a, NULL);
+        if (ret < 0)
+            return -2;
+    }
 
-	if (!b->canon_enc || b->modified)
-		{
-		ret = i2d_X509_NAME((X509_NAME *)b, NULL);
-		if (ret < 0)
-			return -2;
-		}
+    if (!b->canon_enc || b->modified) {
+        ret = i2d_X509_NAME((X509_NAME *)b, NULL);
+        if (ret < 0)
+            return -2;
+    }
 
-	ret = a->canon_enclen - b->canon_enclen;
+    ret = a->canon_enclen - b->canon_enclen;
 
-	if (ret)
-		return ret;
+    if (ret)
+        return ret;
 
-	return memcmp(a->canon_enc, b->canon_enc, a->canon_enclen);
+    return OPENSSL_memcmp(a->canon_enc, b->canon_enc, a->canon_enclen);
 
-	}
+}
 
 unsigned long X509_NAME_hash(X509_NAME *x)
-	{
-	unsigned long ret=0;
-	unsigned char md[SHA_DIGEST_LENGTH];
+{
+    unsigned long ret = 0;
+    unsigned char md[SHA_DIGEST_LENGTH];
 
-	/* Make sure X509_NAME structure contains valid cached encoding */
-	i2d_X509_NAME(x,NULL);
-	if (!EVP_Digest(x->canon_enc, x->canon_enclen, md, NULL, EVP_sha1(),
-		NULL))
-		return 0;
+    /* Make sure X509_NAME structure contains valid cached encoding */
+    i2d_X509_NAME(x, NULL);
+    if (!EVP_Digest(x->canon_enc, x->canon_enclen, md, NULL, EVP_sha1(),
+                    NULL))
+        return 0;
 
-	ret=(	((unsigned long)md[0]     )|((unsigned long)md[1]<<8L)|
-		((unsigned long)md[2]<<16L)|((unsigned long)md[3]<<24L)
-		)&0xffffffffL;
-	return(ret);
-	}
+    ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) |
+           ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)
+        ) & 0xffffffffL;
+    return (ret);
+}
 
-
-/* I now DER encode the name and hash it.  Since I cache the DER encoding,
- * this is reasonably efficient. */
+/*
+ * I now DER encode the name and hash it.  Since I cache the DER encoding,
+ * this is reasonably efficient.
+ */
 
 unsigned long X509_NAME_hash_old(X509_NAME *x)
-	{
-	EVP_MD_CTX md_ctx;
-	unsigned long ret=0;
-	unsigned char md[16];
+{
+    EVP_MD_CTX md_ctx;
+    unsigned long ret = 0;
+    unsigned char md[16];
 
-	/* Make sure X509_NAME structure contains valid cached encoding */
-	i2d_X509_NAME(x,NULL);
-	EVP_MD_CTX_init(&md_ctx);
-	/* EVP_MD_CTX_set_flags(&md_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); */
-	if (EVP_DigestInit_ex(&md_ctx, EVP_md5(), NULL)
-	    && EVP_DigestUpdate(&md_ctx, x->bytes->data, x->bytes->length)
-	    && EVP_DigestFinal_ex(&md_ctx,md,NULL))
-		ret=(((unsigned long)md[0]     )|((unsigned long)md[1]<<8L)|
-		     ((unsigned long)md[2]<<16L)|((unsigned long)md[3]<<24L)
-		     )&0xffffffffL;
-	EVP_MD_CTX_cleanup(&md_ctx);
+    /* Make sure X509_NAME structure contains valid cached encoding */
+    i2d_X509_NAME(x, NULL);
+    EVP_MD_CTX_init(&md_ctx);
+    /* EVP_MD_CTX_set_flags(&md_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); */
+    if (EVP_DigestInit_ex(&md_ctx, EVP_md5(), NULL)
+        && EVP_DigestUpdate(&md_ctx, x->bytes->data, x->bytes->length)
+        && EVP_DigestFinal_ex(&md_ctx, md, NULL))
+        ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) |
+               ((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)
+            ) & 0xffffffffL;
+    EVP_MD_CTX_cleanup(&md_ctx);
 
-	return(ret);
-	}
+    return (ret);
+}
 
 /* Search a stack of X509 for a match */
 X509 *X509_find_by_issuer_and_serial(STACK_OF(X509) *sk, X509_NAME *name,
-		ASN1_INTEGER *serial)
-	{
-	size_t i;
-	X509_CINF cinf;
-	X509 x,*x509=NULL;
+                                     ASN1_INTEGER *serial)
+{
+    size_t i;
+    X509_CINF cinf;
+    X509 x, *x509 = NULL;
 
-	if(!sk) return NULL;
+    if (!sk)
+        return NULL;
 
-	x.cert_info= &cinf;
-	cinf.serialNumber=serial;
-	cinf.issuer=name;
+    x.cert_info = &cinf;
+    cinf.serialNumber = serial;
+    cinf.issuer = name;
 
-	for (i=0; i<sk_X509_num(sk); i++)
-		{
-		x509=sk_X509_value(sk,i);
-		if (X509_issuer_and_serial_cmp(x509,&x) == 0)
-			return(x509);
-		}
-	return(NULL);
-	}
+    for (i = 0; i < sk_X509_num(sk); i++) {
+        x509 = sk_X509_value(sk, i);
+        if (X509_issuer_and_serial_cmp(x509, &x) == 0)
+            return (x509);
+    }
+    return (NULL);
+}
 
 X509 *X509_find_by_subject(STACK_OF(X509) *sk, X509_NAME *name)
-	{
-	X509 *x509;
-	size_t i;
+{
+    X509 *x509;
+    size_t i;
 
-	for (i=0; i<sk_X509_num(sk); i++)
-		{
-		x509=sk_X509_value(sk,i);
-		if (X509_NAME_cmp(X509_get_subject_name(x509),name) == 0)
-			return(x509);
-		}
-	return(NULL);
-	}
+    for (i = 0; i < sk_X509_num(sk); i++) {
+        x509 = sk_X509_value(sk, i);
+        if (X509_NAME_cmp(X509_get_subject_name(x509), name) == 0)
+            return (x509);
+    }
+    return (NULL);
+}
 
 EVP_PKEY *X509_get_pubkey(X509 *x)
-	{
-	if ((x == NULL) || (x->cert_info == NULL))
-		return(NULL);
-	return(X509_PUBKEY_get(x->cert_info->key));
-	}
+{
+    if ((x == NULL) || (x->cert_info == NULL))
+        return (NULL);
+    return (X509_PUBKEY_get(x->cert_info->key));
+}
 
 ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x)
-	{
-	if(!x) return NULL;
-	return x->cert_info->key->public_key;
-	}
-
+{
+    if (!x)
+        return NULL;
+    return x->cert_info->key->public_key;
+}
 
 int X509_check_private_key(X509 *x, EVP_PKEY *k)
-	{
-	EVP_PKEY *xk;
-	int ret;
+{
+    EVP_PKEY *xk;
+    int ret;
 
-	xk=X509_get_pubkey(x);
+    xk = X509_get_pubkey(x);
 
-	if (xk)
-		ret = EVP_PKEY_cmp(xk, k);
-	else
-		ret = -2;
+    if (xk)
+        ret = EVP_PKEY_cmp(xk, k);
+    else
+        ret = -2;
 
-	switch (ret)
-		{
-	case 1:
-		break;
-	case 0:
-		OPENSSL_PUT_ERROR(X509, X509_R_KEY_VALUES_MISMATCH);
-		break;
-	case -1:
-		OPENSSL_PUT_ERROR(X509, X509_R_KEY_TYPE_MISMATCH);
-		break;
-	case -2:
-	        OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_KEY_TYPE);
-		}
-	if (xk)
-		EVP_PKEY_free(xk);
-	if (ret > 0)
-		return 1;
-	return 0;
-	}
+    switch (ret) {
+    case 1:
+        break;
+    case 0:
+        OPENSSL_PUT_ERROR(X509, X509_R_KEY_VALUES_MISMATCH);
+        break;
+    case -1:
+        OPENSSL_PUT_ERROR(X509, X509_R_KEY_TYPE_MISMATCH);
+        break;
+    case -2:
+        OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_KEY_TYPE);
+    }
+    if (xk)
+        EVP_PKEY_free(xk);
+    if (ret > 0)
+        return 1;
+    return 0;
+}
 
-/* Check a suite B algorithm is permitted: pass in a public key and
- * the NID of its signature (or 0 if no signature). The pflags is
- * a pointer to a flags field which must contain the suite B verification
- * flags.
+/*
+ * Check a suite B algorithm is permitted: pass in a public key and the NID
+ * of its signature (or 0 if no signature). The pflags is a pointer to a
+ * flags field which must contain the suite B verification flags.
  */
 
-
 static int check_suite_b(EVP_PKEY *pkey, int sign_nid, unsigned long *pflags)
-	{
-	const EC_GROUP *grp = NULL;
-	int curve_nid;
-	if (pkey && pkey->type == EVP_PKEY_EC)
-		grp = EC_KEY_get0_group(pkey->pkey.ec);
-	if (!grp)
-		return X509_V_ERR_SUITE_B_INVALID_ALGORITHM;
-	curve_nid = EC_GROUP_get_curve_name(grp);
-	/* Check curve is consistent with LOS */
-	if (curve_nid == NID_secp384r1) /* P-384 */
-		{
-		/* Check signature algorithm is consistent with
-		 * curve.
-		 */
-		if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA384)
-			return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM;
-		if (!(*pflags & X509_V_FLAG_SUITEB_192_LOS))
-			return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED;
-		/* If we encounter P-384 we cannot use P-256 later */
-		*pflags &= ~X509_V_FLAG_SUITEB_128_LOS_ONLY;
-		}
-	else if (curve_nid == NID_X9_62_prime256v1) /* P-256 */
-		{
-		if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA256)
-			return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM;
-		if (!(*pflags & X509_V_FLAG_SUITEB_128_LOS_ONLY))
-			return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED;
-		}
-	else
-		return X509_V_ERR_SUITE_B_INVALID_CURVE;
+{
+    const EC_GROUP *grp = NULL;
+    int curve_nid;
+    if (pkey && pkey->type == EVP_PKEY_EC)
+        grp = EC_KEY_get0_group(pkey->pkey.ec);
+    if (!grp)
+        return X509_V_ERR_SUITE_B_INVALID_ALGORITHM;
+    curve_nid = EC_GROUP_get_curve_name(grp);
+    /* Check curve is consistent with LOS */
+    if (curve_nid == NID_secp384r1) { /* P-384 */
+        /*
+         * Check signature algorithm is consistent with curve.
+         */
+        if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA384)
+            return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM;
+        if (!(*pflags & X509_V_FLAG_SUITEB_192_LOS))
+            return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED;
+        /* If we encounter P-384 we cannot use P-256 later */
+        *pflags &= ~X509_V_FLAG_SUITEB_128_LOS_ONLY;
+    } else if (curve_nid == NID_X9_62_prime256v1) { /* P-256 */
+        if (sign_nid != -1 && sign_nid != NID_ecdsa_with_SHA256)
+            return X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM;
+        if (!(*pflags & X509_V_FLAG_SUITEB_128_LOS_ONLY))
+            return X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED;
+    } else
+        return X509_V_ERR_SUITE_B_INVALID_CURVE;
 
-	return X509_V_OK;
-	}
+    return X509_V_OK;
+}
 
 int X509_chain_check_suiteb(int *perror_depth, X509 *x, STACK_OF(X509) *chain,
-							unsigned long flags)
-	{
-	int rv, sign_nid;
-	size_t i;
-	EVP_PKEY *pk = NULL;
-	unsigned long tflags;
-	if (!(flags & X509_V_FLAG_SUITEB_128_LOS))
-		return X509_V_OK;
-	tflags = flags;
-	/* If no EE certificate passed in must be first in chain */
-	if (x == NULL)
-		{
-		x = sk_X509_value(chain, 0);
-		i = 1;
-		}
-	else
-		i = 0;
+                            unsigned long flags)
+{
+    int rv, sign_nid;
+    size_t i;
+    EVP_PKEY *pk = NULL;
+    unsigned long tflags;
+    if (!(flags & X509_V_FLAG_SUITEB_128_LOS))
+        return X509_V_OK;
+    tflags = flags;
+    /* If no EE certificate passed in must be first in chain */
+    if (x == NULL) {
+        x = sk_X509_value(chain, 0);
+        i = 1;
+    } else
+        i = 0;
 
-	if (X509_get_version(x) != 2)
-		{
-		rv = X509_V_ERR_SUITE_B_INVALID_VERSION;
-		/* Correct error depth */
-		i = 0;
-		goto end;
-		}
+    if (X509_get_version(x) != 2) {
+        rv = X509_V_ERR_SUITE_B_INVALID_VERSION;
+        /* Correct error depth */
+        i = 0;
+        goto end;
+    }
 
-	pk = X509_get_pubkey(x);
-	/* Check EE key only */
-	rv = check_suite_b(pk, -1, &tflags);
-	if (rv != X509_V_OK)
-		{
-		/* Correct error depth */
-		i = 0;
-		goto end;
-		}
-	for(; i < sk_X509_num(chain); i++)
-		{
-		sign_nid = X509_get_signature_nid(x);
-		x = sk_X509_value(chain, i);
-		if (X509_get_version(x) != 2)
-			{
-			rv = X509_V_ERR_SUITE_B_INVALID_VERSION;
-			goto end;
-			}
-		EVP_PKEY_free(pk);
-		pk = X509_get_pubkey(x);
-		rv = check_suite_b(pk, sign_nid, &tflags);
-		if (rv != X509_V_OK)
-			goto end;
-		}
+    pk = X509_get_pubkey(x);
+    /* Check EE key only */
+    rv = check_suite_b(pk, -1, &tflags);
+    if (rv != X509_V_OK) {
+        /* Correct error depth */
+        i = 0;
+        goto end;
+    }
+    for (; i < sk_X509_num(chain); i++) {
+        sign_nid = X509_get_signature_nid(x);
+        x = sk_X509_value(chain, i);
+        if (X509_get_version(x) != 2) {
+            rv = X509_V_ERR_SUITE_B_INVALID_VERSION;
+            goto end;
+        }
+        EVP_PKEY_free(pk);
+        pk = X509_get_pubkey(x);
+        rv = check_suite_b(pk, sign_nid, &tflags);
+        if (rv != X509_V_OK)
+            goto end;
+    }
 
-	/* Final check: root CA signature */
-	rv = check_suite_b(pk, X509_get_signature_nid(x), &tflags);
-	end:
-	if (pk)
-		EVP_PKEY_free(pk);
-	if (rv != X509_V_OK)
-		{
-		/* Invalid signature or LOS errors are for previous cert */
-		if ((rv == X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM
-		    || rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED) && i)
-			i--;
-		/* If we have LOS error and flags changed then we are signing
-		 * P-384 with P-256. Use more meaninggul error.
-		 */
-		if (rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED && flags != tflags)
-			rv = X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256;
-		if (perror_depth)
-			*perror_depth = i;
-		}
-	return rv;
-	}
+    /* Final check: root CA signature */
+    rv = check_suite_b(pk, X509_get_signature_nid(x), &tflags);
+ end:
+    if (pk)
+        EVP_PKEY_free(pk);
+    if (rv != X509_V_OK) {
+        /* Invalid signature or LOS errors are for previous cert */
+        if ((rv == X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM
+             || rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED) && i)
+            i--;
+        /*
+         * If we have LOS error and flags changed then we are signing P-384
+         * with P-256. Use more meaninggul error.
+         */
+        if (rv == X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED && flags != tflags)
+            rv = X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256;
+        if (perror_depth)
+            *perror_depth = i;
+    }
+    return rv;
+}
 
 int X509_CRL_check_suiteb(X509_CRL *crl, EVP_PKEY *pk, unsigned long flags)
-	{
-	int sign_nid;
-	if (!(flags & X509_V_FLAG_SUITEB_128_LOS))
-		return X509_V_OK;
-	sign_nid = OBJ_obj2nid(crl->crl->sig_alg->algorithm);
-	return check_suite_b(pk, sign_nid, &flags);
-	}
+{
+    int sign_nid;
+    if (!(flags & X509_V_FLAG_SUITEB_128_LOS))
+        return X509_V_OK;
+    sign_nid = OBJ_obj2nid(crl->crl->sig_alg->algorithm);
+    return check_suite_b(pk, sign_nid, &flags);
+}
 
-/* Not strictly speaking an "up_ref" as a STACK doesn't have a reference
- * count but it has the same effect by duping the STACK and upping the ref
- * of each X509 structure.
+/*
+ * Not strictly speaking an "up_ref" as a STACK doesn't have a reference
+ * count but it has the same effect by duping the STACK and upping the ref of
+ * each X509 structure.
  */
 STACK_OF(X509) *X509_chain_up_ref(STACK_OF(X509) *chain)
-	{
-	STACK_OF(X509) *ret;
-	size_t i;
-	ret = sk_X509_dup(chain);
-	for (i = 0; i < sk_X509_num(ret); i++)
-		{
-		X509_up_ref(sk_X509_value(ret, i));
-		}
-	return ret;
-	}
+{
+    STACK_OF(X509) *ret;
+    size_t i;
+    ret = sk_X509_dup(chain);
+    for (i = 0; i < sk_X509_num(ret); i++) {
+        X509_up_ref(sk_X509_value(ret, i));
+    }
+    return ret;
+}
diff --git a/src/crypto/x509/x509_d2.c b/src/crypto/x509/x509_d2.c
index 2161d85..69ae54e 100644
--- a/src/crypto/x509/x509_d2.c
+++ b/src/crypto/x509/x509_d2.c
@@ -58,48 +58,49 @@
 #include <openssl/err.h>
 #include <openssl/x509.h>
 
-
 #ifndef OPENSSL_NO_STDIO
 int X509_STORE_set_default_paths(X509_STORE *ctx)
-	{
-	X509_LOOKUP *lookup;
+{
+    X509_LOOKUP *lookup;
 
-	lookup=X509_STORE_add_lookup(ctx,X509_LOOKUP_file());
-	if (lookup == NULL) return(0);
-	X509_LOOKUP_load_file(lookup,NULL,X509_FILETYPE_DEFAULT);
+    lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_file());
+    if (lookup == NULL)
+        return (0);
+    X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT);
 
-	lookup=X509_STORE_add_lookup(ctx,X509_LOOKUP_hash_dir());
-	if (lookup == NULL) return(0);
-	X509_LOOKUP_add_dir(lookup,NULL,X509_FILETYPE_DEFAULT);
-	
-	/* clear any errors */
-	ERR_clear_error();
+    lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_hash_dir());
+    if (lookup == NULL)
+        return (0);
+    X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
 
-	return(1);
-	}
+    /* clear any errors */
+    ERR_clear_error();
+
+    return (1);
+}
 
 int X509_STORE_load_locations(X509_STORE *ctx, const char *file,
-		const char *path)
-	{
-	X509_LOOKUP *lookup;
+                              const char *path)
+{
+    X509_LOOKUP *lookup;
 
-	if (file != NULL)
-		{
-		lookup=X509_STORE_add_lookup(ctx,X509_LOOKUP_file());
-		if (lookup == NULL) return(0);
-		if (X509_LOOKUP_load_file(lookup,file,X509_FILETYPE_PEM) != 1)
-		    return(0);
-		}
-	if (path != NULL)
-		{
-		lookup=X509_STORE_add_lookup(ctx,X509_LOOKUP_hash_dir());
-		if (lookup == NULL) return(0);
-		if (X509_LOOKUP_add_dir(lookup,path,X509_FILETYPE_PEM) != 1)
-		    return(0);
-		}
-	if ((path == NULL) && (file == NULL))
-		return(0);
-	return(1);
-	}
+    if (file != NULL) {
+        lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_file());
+        if (lookup == NULL)
+            return (0);
+        if (X509_LOOKUP_load_file(lookup, file, X509_FILETYPE_PEM) != 1)
+            return (0);
+    }
+    if (path != NULL) {
+        lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_hash_dir());
+        if (lookup == NULL)
+            return (0);
+        if (X509_LOOKUP_add_dir(lookup, path, X509_FILETYPE_PEM) != 1)
+            return (0);
+    }
+    if ((path == NULL) && (file == NULL))
+        return (0);
+    return (1);
+}
 
 #endif
diff --git a/src/crypto/x509/x509_def.c b/src/crypto/x509/x509_def.c
index dbae289..2bf2240 100644
--- a/src/crypto/x509/x509_def.c
+++ b/src/crypto/x509/x509_def.c
@@ -57,32 +57,42 @@
 
 #include <openssl/x509.h>
 
-
 /* TODO(fork): cleanup */
 
 #define OPENSSLDIR "/etc/ssl"
-#define X509_CERT_AREA		OPENSSLDIR
-#define X509_CERT_DIR		OPENSSLDIR "/certs"
-#define X509_CERT_FILE		OPENSSLDIR "/cert.pem"
-#define X509_PRIVATE_DIR	OPENSSLDIR "/private"
+#define X509_CERT_AREA          OPENSSLDIR
+#define X509_CERT_DIR           OPENSSLDIR "/certs"
+#define X509_CERT_FILE          OPENSSLDIR "/cert.pem"
+#define X509_PRIVATE_DIR        OPENSSLDIR "/private"
 #define X509_CERT_DIR_EVP        "SSL_CERT_DIR"
 #define X509_CERT_FILE_EVP       "SSL_CERT_FILE"
 
 const char *X509_get_default_private_dir(void)
-	{ return(X509_PRIVATE_DIR); }
-	
+{
+    return (X509_PRIVATE_DIR);
+}
+
 const char *X509_get_default_cert_area(void)
-	{ return(X509_CERT_AREA); }
+{
+    return (X509_CERT_AREA);
+}
 
 const char *X509_get_default_cert_dir(void)
-	{ return(X509_CERT_DIR); }
+{
+    return (X509_CERT_DIR);
+}
 
 const char *X509_get_default_cert_file(void)
-	{ return(X509_CERT_FILE); }
+{
+    return (X509_CERT_FILE);
+}
 
 const char *X509_get_default_cert_dir_env(void)
-	{ return(X509_CERT_DIR_EVP); }
+{
+    return (X509_CERT_DIR_EVP);
+}
 
 const char *X509_get_default_cert_file_env(void)
-	{ return(X509_CERT_FILE_EVP); }
-
+{
+    return (X509_CERT_FILE_EVP);
+}
diff --git a/src/crypto/x509/x509_ext.c b/src/crypto/x509/x509_ext.c
index 2f1e0c5..a329f6f 100644
--- a/src/crypto/x509/x509_ext.c
+++ b/src/crypto/x509/x509_ext.c
@@ -62,145 +62,145 @@
 #include <openssl/x509.h>
 #include <openssl/x509v3.h>
 
-
 int X509_CRL_get_ext_count(X509_CRL *x)
-	{
-	return(X509v3_get_ext_count(x->crl->extensions));
-	}
+{
+    return (X509v3_get_ext_count(x->crl->extensions));
+}
 
 int X509_CRL_get_ext_by_NID(X509_CRL *x, int nid, int lastpos)
-	{
-	return(X509v3_get_ext_by_NID(x->crl->extensions,nid,lastpos));
-	}
+{
+    return (X509v3_get_ext_by_NID(x->crl->extensions, nid, lastpos));
+}
 
 int X509_CRL_get_ext_by_OBJ(X509_CRL *x, ASN1_OBJECT *obj, int lastpos)
-	{
-	return(X509v3_get_ext_by_OBJ(x->crl->extensions,obj,lastpos));
-	}
+{
+    return (X509v3_get_ext_by_OBJ(x->crl->extensions, obj, lastpos));
+}
 
 int X509_CRL_get_ext_by_critical(X509_CRL *x, int crit, int lastpos)
-	{
-	return(X509v3_get_ext_by_critical(x->crl->extensions,crit,lastpos));
-	}
+{
+    return (X509v3_get_ext_by_critical(x->crl->extensions, crit, lastpos));
+}
 
 X509_EXTENSION *X509_CRL_get_ext(X509_CRL *x, int loc)
-	{
-	return(X509v3_get_ext(x->crl->extensions,loc));
-	}
+{
+    return (X509v3_get_ext(x->crl->extensions, loc));
+}
 
 X509_EXTENSION *X509_CRL_delete_ext(X509_CRL *x, int loc)
-	{
-	return(X509v3_delete_ext(x->crl->extensions,loc));
-	}
+{
+    return (X509v3_delete_ext(x->crl->extensions, loc));
+}
 
 void *X509_CRL_get_ext_d2i(X509_CRL *x, int nid, int *crit, int *idx)
 {
-	return X509V3_get_d2i(x->crl->extensions, nid, crit, idx);
+    return X509V3_get_d2i(x->crl->extensions, nid, crit, idx);
 }
 
 int X509_CRL_add1_ext_i2d(X509_CRL *x, int nid, void *value, int crit,
-							unsigned long flags)
+                          unsigned long flags)
 {
-	return X509V3_add1_i2d(&x->crl->extensions, nid, value, crit, flags);
+    return X509V3_add1_i2d(&x->crl->extensions, nid, value, crit, flags);
 }
 
 int X509_CRL_add_ext(X509_CRL *x, X509_EXTENSION *ex, int loc)
-	{
-	return(X509v3_add_ext(&(x->crl->extensions),ex,loc) != NULL);
-	}
+{
+    return (X509v3_add_ext(&(x->crl->extensions), ex, loc) != NULL);
+}
 
 int X509_get_ext_count(X509 *x)
-	{
-	return(X509v3_get_ext_count(x->cert_info->extensions));
-	}
+{
+    return (X509v3_get_ext_count(x->cert_info->extensions));
+}
 
 int X509_get_ext_by_NID(X509 *x, int nid, int lastpos)
-	{
-	return(X509v3_get_ext_by_NID(x->cert_info->extensions,nid,lastpos));
-	}
+{
+    return (X509v3_get_ext_by_NID(x->cert_info->extensions, nid, lastpos));
+}
 
 int X509_get_ext_by_OBJ(X509 *x, ASN1_OBJECT *obj, int lastpos)
-	{
-	return(X509v3_get_ext_by_OBJ(x->cert_info->extensions,obj,lastpos));
-	}
+{
+    return (X509v3_get_ext_by_OBJ(x->cert_info->extensions, obj, lastpos));
+}
 
 int X509_get_ext_by_critical(X509 *x, int crit, int lastpos)
-	{
-	return(X509v3_get_ext_by_critical(x->cert_info->extensions,crit,lastpos));
-	}
+{
+    return (X509v3_get_ext_by_critical
+            (x->cert_info->extensions, crit, lastpos));
+}
 
 X509_EXTENSION *X509_get_ext(X509 *x, int loc)
-	{
-	return(X509v3_get_ext(x->cert_info->extensions,loc));
-	}
+{
+    return (X509v3_get_ext(x->cert_info->extensions, loc));
+}
 
 X509_EXTENSION *X509_delete_ext(X509 *x, int loc)
-	{
-	return(X509v3_delete_ext(x->cert_info->extensions,loc));
-	}
+{
+    return (X509v3_delete_ext(x->cert_info->extensions, loc));
+}
 
 int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc)
-	{
-	return(X509v3_add_ext(&(x->cert_info->extensions),ex,loc) != NULL);
-	}
+{
+    return (X509v3_add_ext(&(x->cert_info->extensions), ex, loc) != NULL);
+}
 
 void *X509_get_ext_d2i(X509 *x, int nid, int *crit, int *idx)
 {
-	return X509V3_get_d2i(x->cert_info->extensions, nid, crit, idx);
+    return X509V3_get_d2i(x->cert_info->extensions, nid, crit, idx);
 }
 
 int X509_add1_ext_i2d(X509 *x, int nid, void *value, int crit,
-							unsigned long flags)
+                      unsigned long flags)
 {
-	return X509V3_add1_i2d(&x->cert_info->extensions, nid, value, crit,
-							flags);
+    return X509V3_add1_i2d(&x->cert_info->extensions, nid, value, crit,
+                           flags);
 }
 
 int X509_REVOKED_get_ext_count(X509_REVOKED *x)
-	{
-	return(X509v3_get_ext_count(x->extensions));
-	}
+{
+    return (X509v3_get_ext_count(x->extensions));
+}
 
 int X509_REVOKED_get_ext_by_NID(X509_REVOKED *x, int nid, int lastpos)
-	{
-	return(X509v3_get_ext_by_NID(x->extensions,nid,lastpos));
-	}
+{
+    return (X509v3_get_ext_by_NID(x->extensions, nid, lastpos));
+}
 
 int X509_REVOKED_get_ext_by_OBJ(X509_REVOKED *x, ASN1_OBJECT *obj,
-	     int lastpos)
-	{
-	return(X509v3_get_ext_by_OBJ(x->extensions,obj,lastpos));
-	}
+                                int lastpos)
+{
+    return (X509v3_get_ext_by_OBJ(x->extensions, obj, lastpos));
+}
 
 int X509_REVOKED_get_ext_by_critical(X509_REVOKED *x, int crit, int lastpos)
-	{
-	return(X509v3_get_ext_by_critical(x->extensions,crit,lastpos));
-	}
+{
+    return (X509v3_get_ext_by_critical(x->extensions, crit, lastpos));
+}
 
 X509_EXTENSION *X509_REVOKED_get_ext(X509_REVOKED *x, int loc)
-	{
-	return(X509v3_get_ext(x->extensions,loc));
-	}
+{
+    return (X509v3_get_ext(x->extensions, loc));
+}
 
 X509_EXTENSION *X509_REVOKED_delete_ext(X509_REVOKED *x, int loc)
-	{
-	return(X509v3_delete_ext(x->extensions,loc));
-	}
+{
+    return (X509v3_delete_ext(x->extensions, loc));
+}
 
 int X509_REVOKED_add_ext(X509_REVOKED *x, X509_EXTENSION *ex, int loc)
-	{
-	return(X509v3_add_ext(&(x->extensions),ex,loc) != NULL);
-	}
+{
+    return (X509v3_add_ext(&(x->extensions), ex, loc) != NULL);
+}
 
 void *X509_REVOKED_get_ext_d2i(X509_REVOKED *x, int nid, int *crit, int *idx)
 {
-	return X509V3_get_d2i(x->extensions, nid, crit, idx);
+    return X509V3_get_d2i(x->extensions, nid, crit, idx);
 }
 
 int X509_REVOKED_add1_ext_i2d(X509_REVOKED *x, int nid, void *value, int crit,
-							unsigned long flags)
+                              unsigned long flags)
 {
-	return X509V3_add1_i2d(&x->extensions, nid, value, crit, flags);
+    return X509V3_add1_i2d(&x->extensions, nid, value, crit, flags);
 }
 
 IMPLEMENT_ASN1_SET_OF(X509_EXTENSION)
diff --git a/src/crypto/x509/x509_lu.c b/src/crypto/x509/x509_lu.c
index 5751f75..f2371bd 100644
--- a/src/crypto/x509/x509_lu.c
+++ b/src/crypto/x509/x509_lu.c
@@ -66,673 +66,638 @@
 
 #include "../internal.h"
 
-
 X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method)
-	{
-	X509_LOOKUP *ret;
+{
+    X509_LOOKUP *ret;
 
-	ret=(X509_LOOKUP *)OPENSSL_malloc(sizeof(X509_LOOKUP));
-	if (ret == NULL) return NULL;
+    ret = (X509_LOOKUP *)OPENSSL_malloc(sizeof(X509_LOOKUP));
+    if (ret == NULL)
+        return NULL;
 
-	ret->init=0;
-	ret->skip=0;
-	ret->method=method;
-	ret->method_data=NULL;
-	ret->store_ctx=NULL;
-	if ((method->new_item != NULL) && !method->new_item(ret))
-		{
-		OPENSSL_free(ret);
-		return NULL;
-		}
-	return ret;
-	}
+    ret->init = 0;
+    ret->skip = 0;
+    ret->method = method;
+    ret->method_data = NULL;
+    ret->store_ctx = NULL;
+    if ((method->new_item != NULL) && !method->new_item(ret)) {
+        OPENSSL_free(ret);
+        return NULL;
+    }
+    return ret;
+}
 
 void X509_LOOKUP_free(X509_LOOKUP *ctx)
-	{
-	if (ctx == NULL) return;
-	if (	(ctx->method != NULL) &&
-		(ctx->method->free != NULL))
-		(*ctx->method->free)(ctx);
-	OPENSSL_free(ctx);
-	}
+{
+    if (ctx == NULL)
+        return;
+    if ((ctx->method != NULL) && (ctx->method->free != NULL))
+        (*ctx->method->free) (ctx);
+    OPENSSL_free(ctx);
+}
 
 int X509_LOOKUP_init(X509_LOOKUP *ctx)
-	{
-	if (ctx->method == NULL) return 0;
-	if (ctx->method->init != NULL)
-		return ctx->method->init(ctx);
-	else
-		return 1;
-	}
+{
+    if (ctx->method == NULL)
+        return 0;
+    if (ctx->method->init != NULL)
+        return ctx->method->init(ctx);
+    else
+        return 1;
+}
 
 int X509_LOOKUP_shutdown(X509_LOOKUP *ctx)
-	{
-	if (ctx->method == NULL) return 0;
-	if (ctx->method->shutdown != NULL)
-		return ctx->method->shutdown(ctx);
-	else
-		return 1;
-	}
+{
+    if (ctx->method == NULL)
+        return 0;
+    if (ctx->method->shutdown != NULL)
+        return ctx->method->shutdown(ctx);
+    else
+        return 1;
+}
 
 int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
-	     char **ret)
-	{
-	if (ctx->method == NULL) return -1;
-	if (ctx->method->ctrl != NULL)
-		return ctx->method->ctrl(ctx,cmd,argc,argl,ret);
-	else
-		return 1;
-	}
+                     char **ret)
+{
+    if (ctx->method == NULL)
+        return -1;
+    if (ctx->method->ctrl != NULL)
+        return ctx->method->ctrl(ctx, cmd, argc, argl, ret);
+    else
+        return 1;
+}
 
 int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, int type, X509_NAME *name,
-	     X509_OBJECT *ret)
-	{
-	if ((ctx->method == NULL) || (ctx->method->get_by_subject == NULL))
-		return X509_LU_FAIL;
-	if (ctx->skip) return 0;
-	return ctx->method->get_by_subject(ctx,type,name,ret);
-	}
+                           X509_OBJECT *ret)
+{
+    if ((ctx->method == NULL) || (ctx->method->get_by_subject == NULL))
+        return 0;
+    if (ctx->skip)
+        return 0;
+    return ctx->method->get_by_subject(ctx, type, name, ret) > 0;
+}
 
 int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, int type, X509_NAME *name,
-	     ASN1_INTEGER *serial, X509_OBJECT *ret)
-	{
-	if ((ctx->method == NULL) ||
-		(ctx->method->get_by_issuer_serial == NULL))
-		return X509_LU_FAIL;
-	return ctx->method->get_by_issuer_serial(ctx,type,name,serial,ret);
-	}
+                                 ASN1_INTEGER *serial, X509_OBJECT *ret)
+{
+    if ((ctx->method == NULL) || (ctx->method->get_by_issuer_serial == NULL))
+        return 0;
+    return ctx->method->get_by_issuer_serial(ctx, type, name, serial, ret) > 0;
+}
 
 int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, int type,
-	     unsigned char *bytes, int len, X509_OBJECT *ret)
-	{
-	if ((ctx->method == NULL) || (ctx->method->get_by_fingerprint == NULL))
-		return X509_LU_FAIL;
-	return ctx->method->get_by_fingerprint(ctx,type,bytes,len,ret);
-	}
+                               unsigned char *bytes, int len,
+                               X509_OBJECT *ret)
+{
+    if ((ctx->method == NULL) || (ctx->method->get_by_fingerprint == NULL))
+        return 0;
+    return ctx->method->get_by_fingerprint(ctx, type, bytes, len, ret) > 0;
+}
 
 int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, int type, char *str, int len,
-	     X509_OBJECT *ret)
-	{
-	if ((ctx->method == NULL) || (ctx->method->get_by_alias == NULL))
-		return X509_LU_FAIL;
-	return ctx->method->get_by_alias(ctx,type,str,len,ret);
-	}
+                         X509_OBJECT *ret)
+{
+    if ((ctx->method == NULL) || (ctx->method->get_by_alias == NULL))
+        return 0;
+    return ctx->method->get_by_alias(ctx, type, str, len, ret) > 0;
+}
 
-  
 static int x509_object_cmp(const X509_OBJECT **a, const X509_OBJECT **b)
-  	{
- 	int ret;
+{
+    int ret;
 
- 	ret=((*a)->type - (*b)->type);
- 	if (ret) return ret;
- 	switch ((*a)->type)
- 		{
- 	case X509_LU_X509:
- 		ret=X509_subject_name_cmp((*a)->data.x509,(*b)->data.x509);
- 		break;
- 	case X509_LU_CRL:
- 		ret=X509_CRL_cmp((*a)->data.crl,(*b)->data.crl);
- 		break;
-	default:
-		/* abort(); */
-		return 0;
-		}
-	return ret;
-	}
+    ret = ((*a)->type - (*b)->type);
+    if (ret)
+        return ret;
+    switch ((*a)->type) {
+    case X509_LU_X509:
+        ret = X509_subject_name_cmp((*a)->data.x509, (*b)->data.x509);
+        break;
+    case X509_LU_CRL:
+        ret = X509_CRL_cmp((*a)->data.crl, (*b)->data.crl);
+        break;
+    default:
+        /* abort(); */
+        return 0;
+    }
+    return ret;
+}
 
 X509_STORE *X509_STORE_new(void)
-	{
-	X509_STORE *ret;
+{
+    X509_STORE *ret;
 
-	if ((ret=(X509_STORE *)OPENSSL_malloc(sizeof(X509_STORE))) == NULL)
-		return NULL;
-	memset(ret, 0, sizeof(*ret));
-	CRYPTO_MUTEX_init(&ret->objs_lock);
-	ret->objs = sk_X509_OBJECT_new(x509_object_cmp);
-	if (ret->objs == NULL)
-		goto err;
-	ret->cache = 1;
-	ret->get_cert_methods = sk_X509_LOOKUP_new_null();
-	if (ret->get_cert_methods == NULL)
-		goto err;
-	ret->param = X509_VERIFY_PARAM_new();
-	if (ret->param == NULL)
-		goto err;
+    if ((ret = (X509_STORE *)OPENSSL_malloc(sizeof(X509_STORE))) == NULL)
+        return NULL;
+    OPENSSL_memset(ret, 0, sizeof(*ret));
+    CRYPTO_MUTEX_init(&ret->objs_lock);
+    ret->objs = sk_X509_OBJECT_new(x509_object_cmp);
+    if (ret->objs == NULL)
+        goto err;
+    ret->cache = 1;
+    ret->get_cert_methods = sk_X509_LOOKUP_new_null();
+    if (ret->get_cert_methods == NULL)
+        goto err;
+    ret->param = X509_VERIFY_PARAM_new();
+    if (ret->param == NULL)
+        goto err;
 
-	ret->references = 1;
-	return ret;
-err:
-	if (ret)
-		{
-		CRYPTO_MUTEX_cleanup(&ret->objs_lock);
-		if (ret->param)
-			X509_VERIFY_PARAM_free(ret->param);
-		if (ret->get_cert_methods)
-			sk_X509_LOOKUP_free(ret->get_cert_methods);
-		if (ret->objs)
-			sk_X509_OBJECT_free(ret->objs);
-		OPENSSL_free(ret);
-		}
-	return NULL;
-	}
+    ret->references = 1;
+    return ret;
+ err:
+    if (ret) {
+        CRYPTO_MUTEX_cleanup(&ret->objs_lock);
+        if (ret->param)
+            X509_VERIFY_PARAM_free(ret->param);
+        if (ret->get_cert_methods)
+            sk_X509_LOOKUP_free(ret->get_cert_methods);
+        if (ret->objs)
+            sk_X509_OBJECT_free(ret->objs);
+        OPENSSL_free(ret);
+    }
+    return NULL;
+}
+
+int X509_STORE_up_ref(X509_STORE *store)
+{
+    CRYPTO_refcount_inc(&store->references);
+    return 1;
+}
 
 static void cleanup(X509_OBJECT *a)
-	{
-	if (a->type == X509_LU_X509)
-		{
-		X509_free(a->data.x509);
-		}
-	else if (a->type == X509_LU_CRL)
-		{
-		X509_CRL_free(a->data.crl);
-		}
-	else
-		{
-		/* abort(); */
-		}
+{
+    if (a == NULL) {
+        return;
+    }
+    if (a->type == X509_LU_X509) {
+        X509_free(a->data.x509);
+    } else if (a->type == X509_LU_CRL) {
+        X509_CRL_free(a->data.crl);
+    } else {
+        /* abort(); */
+    }
 
-	OPENSSL_free(a);
-	}
+    OPENSSL_free(a);
+}
 
 void X509_STORE_free(X509_STORE *vfy)
-	{
-	size_t j;
-	STACK_OF(X509_LOOKUP) *sk;
-	X509_LOOKUP *lu;
+{
+    size_t j;
+    STACK_OF(X509_LOOKUP) *sk;
+    X509_LOOKUP *lu;
 
-	if (vfy == NULL)
-	    return;
+    if (vfy == NULL)
+        return;
 
-	if (!CRYPTO_refcount_dec_and_test_zero(&vfy->references)) {
-	  return;
-	}
+    if (!CRYPTO_refcount_dec_and_test_zero(&vfy->references)) {
+        return;
+    }
 
-	CRYPTO_MUTEX_cleanup(&vfy->objs_lock);
+    CRYPTO_MUTEX_cleanup(&vfy->objs_lock);
 
-	sk=vfy->get_cert_methods;
-	for (j=0; j<sk_X509_LOOKUP_num(sk); j++)
-		{
-		lu=sk_X509_LOOKUP_value(sk,j);
-		X509_LOOKUP_shutdown(lu);
-		X509_LOOKUP_free(lu);
-		}
-	sk_X509_LOOKUP_free(sk);
-	sk_X509_OBJECT_pop_free(vfy->objs, cleanup);
+    sk = vfy->get_cert_methods;
+    for (j = 0; j < sk_X509_LOOKUP_num(sk); j++) {
+        lu = sk_X509_LOOKUP_value(sk, j);
+        X509_LOOKUP_shutdown(lu);
+        X509_LOOKUP_free(lu);
+    }
+    sk_X509_LOOKUP_free(sk);
+    sk_X509_OBJECT_pop_free(vfy->objs, cleanup);
 
-	if (vfy->param)
-		X509_VERIFY_PARAM_free(vfy->param);
-	OPENSSL_free(vfy);
-	}
+    if (vfy->param)
+        X509_VERIFY_PARAM_free(vfy->param);
+    OPENSSL_free(vfy);
+}
 
 X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m)
-	{
-	size_t i;
-	STACK_OF(X509_LOOKUP) *sk;
-	X509_LOOKUP *lu;
+{
+    size_t i;
+    STACK_OF(X509_LOOKUP) *sk;
+    X509_LOOKUP *lu;
 
-	sk=v->get_cert_methods;
-	for (i=0; i<sk_X509_LOOKUP_num(sk); i++)
-		{
-		lu=sk_X509_LOOKUP_value(sk,i);
-		if (m == lu->method)
-			{
-			return lu;
-			}
-		}
-	/* a new one */
-	lu=X509_LOOKUP_new(m);
-	if (lu == NULL)
-		return NULL;
-	else
-		{
-		lu->store_ctx=v;
-		if (sk_X509_LOOKUP_push(v->get_cert_methods,lu))
-			return lu;
-		else
-			{
-			X509_LOOKUP_free(lu);
-			return NULL;
-			}
-		}
-	}
+    sk = v->get_cert_methods;
+    for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) {
+        lu = sk_X509_LOOKUP_value(sk, i);
+        if (m == lu->method) {
+            return lu;
+        }
+    }
+    /* a new one */
+    lu = X509_LOOKUP_new(m);
+    if (lu == NULL)
+        return NULL;
+    else {
+        lu->store_ctx = v;
+        if (sk_X509_LOOKUP_push(v->get_cert_methods, lu))
+            return lu;
+        else {
+            X509_LOOKUP_free(lu);
+            return NULL;
+        }
+    }
+}
 
 int X509_STORE_get_by_subject(X509_STORE_CTX *vs, int type, X509_NAME *name,
-	     X509_OBJECT *ret)
-	{
-	X509_STORE *ctx=vs->ctx;
-	X509_LOOKUP *lu;
-	X509_OBJECT stmp,*tmp;
-	int i,j;
+                              X509_OBJECT *ret)
+{
+    X509_STORE *ctx = vs->ctx;
+    X509_LOOKUP *lu;
+    X509_OBJECT stmp, *tmp;
+    int i;
 
-	CRYPTO_MUTEX_lock_write(&ctx->objs_lock);
-	tmp=X509_OBJECT_retrieve_by_subject(ctx->objs,type,name);
-	CRYPTO_MUTEX_unlock(&ctx->objs_lock);
+    CRYPTO_MUTEX_lock_write(&ctx->objs_lock);
+    tmp = X509_OBJECT_retrieve_by_subject(ctx->objs, type, name);
+    CRYPTO_MUTEX_unlock_write(&ctx->objs_lock);
 
-	if (tmp == NULL || type == X509_LU_CRL)
-		{
-		for (i=vs->current_method; i<(int)sk_X509_LOOKUP_num(ctx->get_cert_methods); i++)
-			{
-			lu=sk_X509_LOOKUP_value(ctx->get_cert_methods,i);
-			j=X509_LOOKUP_by_subject(lu,type,name,&stmp);
-			if (j < 0)
-				{
-				vs->current_method=j;
-				return j;
-				}
-			else if (j)
-				{
-				tmp= &stmp;
-				break;
-				}
-			}
-		vs->current_method=0;
-		if (tmp == NULL)
-			return 0;
-		}
+    if (tmp == NULL || type == X509_LU_CRL) {
+        for (i = 0; i < (int)sk_X509_LOOKUP_num(ctx->get_cert_methods); i++) {
+            lu = sk_X509_LOOKUP_value(ctx->get_cert_methods, i);
+            if (X509_LOOKUP_by_subject(lu, type, name, &stmp)) {
+                tmp = &stmp;
+                break;
+            }
+        }
+        if (tmp == NULL)
+            return 0;
+    }
 
-/*	if (ret->data.ptr != NULL)
-		X509_OBJECT_free_contents(ret); */
+    /*
+     * if (ret->data.ptr != NULL) X509_OBJECT_free_contents(ret);
+     */
 
-	ret->type=tmp->type;
-	ret->data.ptr=tmp->data.ptr;
+    ret->type = tmp->type;
+    ret->data.ptr = tmp->data.ptr;
 
-	X509_OBJECT_up_ref_count(ret);
+    X509_OBJECT_up_ref_count(ret);
 
-	return 1;
-	}
+    return 1;
+}
 
 int X509_STORE_add_cert(X509_STORE *ctx, X509 *x)
-	{
-	X509_OBJECT *obj;
-	int ret=1;
+{
+    X509_OBJECT *obj;
+    int ret = 1;
 
-	if (x == NULL) return 0;
-	obj=(X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT));
-	if (obj == NULL)
-		{
-		OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-		return 0;
-		}
-	obj->type=X509_LU_X509;
-	obj->data.x509=x;
+    if (x == NULL)
+        return 0;
+    obj = (X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT));
+    if (obj == NULL) {
+        OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
+    obj->type = X509_LU_X509;
+    obj->data.x509 = x;
 
-	CRYPTO_MUTEX_lock_write(&ctx->objs_lock);
+    CRYPTO_MUTEX_lock_write(&ctx->objs_lock);
 
-	X509_OBJECT_up_ref_count(obj);
+    X509_OBJECT_up_ref_count(obj);
 
-	if (X509_OBJECT_retrieve_match(ctx->objs, obj))
-		{
-		X509_OBJECT_free_contents(obj);
-		OPENSSL_free(obj);
-		OPENSSL_PUT_ERROR(X509, X509_R_CERT_ALREADY_IN_HASH_TABLE);
-		ret=0;
-		} 
-	else sk_X509_OBJECT_push(ctx->objs, obj);
+    if (X509_OBJECT_retrieve_match(ctx->objs, obj)) {
+        X509_OBJECT_free_contents(obj);
+        OPENSSL_free(obj);
+        OPENSSL_PUT_ERROR(X509, X509_R_CERT_ALREADY_IN_HASH_TABLE);
+        ret = 0;
+    } else if (!sk_X509_OBJECT_push(ctx->objs, obj)) {
+        X509_OBJECT_free_contents(obj);
+        OPENSSL_free(obj);
+        OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+        ret = 0;
+    }
 
-	CRYPTO_MUTEX_unlock(&ctx->objs_lock);
+    CRYPTO_MUTEX_unlock_write(&ctx->objs_lock);
 
-	return ret;
-	}
+    return ret;
+}
 
 int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x)
-	{
-	X509_OBJECT *obj;
-	int ret=1;
+{
+    X509_OBJECT *obj;
+    int ret = 1;
 
-	if (x == NULL) return 0;
-	obj=(X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT));
-	if (obj == NULL)
-		{
-		OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-		return 0;
-		}
-	obj->type=X509_LU_CRL;
-	obj->data.crl=x;
+    if (x == NULL)
+        return 0;
+    obj = (X509_OBJECT *)OPENSSL_malloc(sizeof(X509_OBJECT));
+    if (obj == NULL) {
+        OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
+    obj->type = X509_LU_CRL;
+    obj->data.crl = x;
 
-	CRYPTO_MUTEX_lock_write(&ctx->objs_lock);
+    CRYPTO_MUTEX_lock_write(&ctx->objs_lock);
 
-	X509_OBJECT_up_ref_count(obj);
+    X509_OBJECT_up_ref_count(obj);
 
-	if (X509_OBJECT_retrieve_match(ctx->objs, obj))
-		{
-		X509_OBJECT_free_contents(obj);
-		OPENSSL_free(obj);
-		OPENSSL_PUT_ERROR(X509, X509_R_CERT_ALREADY_IN_HASH_TABLE);
-		ret=0;
-		}
-	else sk_X509_OBJECT_push(ctx->objs, obj);
+    if (X509_OBJECT_retrieve_match(ctx->objs, obj)) {
+        X509_OBJECT_free_contents(obj);
+        OPENSSL_free(obj);
+        OPENSSL_PUT_ERROR(X509, X509_R_CERT_ALREADY_IN_HASH_TABLE);
+        ret = 0;
+    } else if (!sk_X509_OBJECT_push(ctx->objs, obj)) {
+        X509_OBJECT_free_contents(obj);
+        OPENSSL_free(obj);
+        OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+        ret = 0;
+    }
 
-	CRYPTO_MUTEX_unlock(&ctx->objs_lock);
+    CRYPTO_MUTEX_unlock_write(&ctx->objs_lock);
 
-	return ret;
-	}
+    return ret;
+}
 
-void X509_OBJECT_up_ref_count(X509_OBJECT *a)
-	{
-	switch (a->type)
-		{
-	case X509_LU_X509:
-		X509_up_ref(a->data.x509);
-		break;
-	case X509_LU_CRL:
-		X509_CRL_up_ref(a->data.crl);
-		break;
-		}
-	}
+void X509_STORE_set0_additional_untrusted(X509_STORE *ctx,
+                                          STACK_OF(X509) *untrusted) {
+  ctx->additional_untrusted = untrusted;
+}
+
+int X509_OBJECT_up_ref_count(X509_OBJECT *a)
+{
+    switch (a->type) {
+    case X509_LU_X509:
+        X509_up_ref(a->data.x509);
+        break;
+    case X509_LU_CRL:
+        X509_CRL_up_ref(a->data.crl);
+        break;
+    }
+    return 1;
+}
 
 void X509_OBJECT_free_contents(X509_OBJECT *a)
-	{
-	switch (a->type)
-		{
-	case X509_LU_X509:
-		X509_free(a->data.x509);
-		break;
-	case X509_LU_CRL:
-		X509_CRL_free(a->data.crl);
-		break;
-		}
-	}
+{
+    switch (a->type) {
+    case X509_LU_X509:
+        X509_free(a->data.x509);
+        break;
+    case X509_LU_CRL:
+        X509_CRL_free(a->data.crl);
+        break;
+    }
+}
 
 static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, int type,
-	     X509_NAME *name, int *pnmatch)
-	{
-	X509_OBJECT stmp;
-	X509 x509_s;
-	X509_CINF cinf_s;
-	X509_CRL crl_s;
-	X509_CRL_INFO crl_info_s;
+                               X509_NAME *name, int *pnmatch)
+{
+    X509_OBJECT stmp;
+    X509 x509_s;
+    X509_CINF cinf_s;
+    X509_CRL crl_s;
+    X509_CRL_INFO crl_info_s;
 
-	stmp.type=type;
-	switch (type)
-		{
-	case X509_LU_X509:
-		stmp.data.x509= &x509_s;
-		x509_s.cert_info= &cinf_s;
-		cinf_s.subject=name;
-		break;
-	case X509_LU_CRL:
-		stmp.data.crl= &crl_s;
-		crl_s.crl= &crl_info_s;
-		crl_info_s.issuer=name;
-		break;
-	default:
-		/* abort(); */
-		return -1;
-		}
+    stmp.type = type;
+    switch (type) {
+    case X509_LU_X509:
+        stmp.data.x509 = &x509_s;
+        x509_s.cert_info = &cinf_s;
+        cinf_s.subject = name;
+        break;
+    case X509_LU_CRL:
+        stmp.data.crl = &crl_s;
+        crl_s.crl = &crl_info_s;
+        crl_info_s.issuer = name;
+        break;
+    default:
+        /* abort(); */
+        return -1;
+    }
 
-	size_t idx;
-	if (!sk_X509_OBJECT_find(h, &idx, &stmp))
-		return -1;
+    size_t idx;
+    if (!sk_X509_OBJECT_find(h, &idx, &stmp))
+        return -1;
 
-	if (pnmatch != NULL)
-		{
-		int tidx;
-		const X509_OBJECT *tobj, *pstmp;
-		*pnmatch = 1;
-		pstmp = &stmp;
-		for (tidx = idx + 1; tidx < (int)sk_X509_OBJECT_num(h); tidx++)
-			{
-			tobj = sk_X509_OBJECT_value(h, tidx);
-			if (x509_object_cmp(&tobj, &pstmp))
-				break;
-			(*pnmatch)++;
-			}
-		}
+    if (pnmatch != NULL) {
+        int tidx;
+        const X509_OBJECT *tobj, *pstmp;
+        *pnmatch = 1;
+        pstmp = &stmp;
+        for (tidx = idx + 1; tidx < (int)sk_X509_OBJECT_num(h); tidx++) {
+            tobj = sk_X509_OBJECT_value(h, tidx);
+            if (x509_object_cmp(&tobj, &pstmp))
+                break;
+            (*pnmatch)++;
+        }
+    }
 
-	return idx;
-	}
-
+    return idx;
+}
 
 int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, int type,
-	     X509_NAME *name)
-	{
-	return x509_object_idx_cnt(h, type, name, NULL);
-	}
+                               X509_NAME *name)
+{
+    return x509_object_idx_cnt(h, type, name, NULL);
+}
 
-X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h, int type,
-	     X509_NAME *name)
-	{
-	int idx;
-	idx = X509_OBJECT_idx_by_subject(h, type, name);
-	if (idx==-1) return NULL;
-	return sk_X509_OBJECT_value(h, idx);
-	}
+X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h,
+                                             int type, X509_NAME *name)
+{
+    int idx;
+    idx = X509_OBJECT_idx_by_subject(h, type, name);
+    if (idx == -1)
+        return NULL;
+    return sk_X509_OBJECT_value(h, idx);
+}
 
-STACK_OF(X509)* X509_STORE_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm)
-	{
-	int i, idx, cnt;
-	STACK_OF(X509) *sk;
-	X509 *x;
-	X509_OBJECT *obj;
-	sk = sk_X509_new_null();
-	if (sk == NULL)
-		return NULL;
-	CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
-	idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt);
-	if (idx < 0)
-		{
-		/* Nothing found in cache: do lookup to possibly add new
-		 * objects to cache
-		 */
-		X509_OBJECT xobj;
-		CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
-		if (!X509_STORE_get_by_subject(ctx, X509_LU_X509, nm, &xobj))
-			{
-			sk_X509_free(sk);
-			return NULL;
-			}
-		X509_OBJECT_free_contents(&xobj);
-		CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
-		idx = x509_object_idx_cnt(ctx->ctx->objs,X509_LU_X509,nm, &cnt);
-		if (idx < 0)
-			{
-			CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
-			sk_X509_free(sk);
-			return NULL;
-			}
-		}
-	for (i = 0; i < cnt; i++, idx++)
-		{
-		obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx);
-		x = obj->data.x509;
-		if (!sk_X509_push(sk, X509_up_ref(x)))
-			{
-			CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
-			X509_free(x);
-			sk_X509_pop_free(sk, X509_free);
-			return NULL;
-			}
-		}
-	CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
-	return sk;
+STACK_OF (X509) * X509_STORE_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm)
+{
+    int i, idx, cnt;
+    STACK_OF(X509) *sk;
+    X509 *x;
+    X509_OBJECT *obj;
+    sk = sk_X509_new_null();
+    if (sk == NULL)
+        return NULL;
+    CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
+    idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt);
+    if (idx < 0) {
+        /*
+         * Nothing found in cache: do lookup to possibly add new objects to
+         * cache
+         */
+        X509_OBJECT xobj;
+        CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
+        if (!X509_STORE_get_by_subject(ctx, X509_LU_X509, nm, &xobj)) {
+            sk_X509_free(sk);
+            return NULL;
+        }
+        X509_OBJECT_free_contents(&xobj);
+        CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
+        idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt);
+        if (idx < 0) {
+            CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
+            sk_X509_free(sk);
+            return NULL;
+        }
+    }
+    for (i = 0; i < cnt; i++, idx++) {
+        obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx);
+        x = obj->data.x509;
+        if (!sk_X509_push(sk, x)) {
+            CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
+            sk_X509_pop_free(sk, X509_free);
+            return NULL;
+        }
+        X509_up_ref(x);
+    }
+    CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
+    return sk;
 
-	}
+}
 
-STACK_OF(X509_CRL)* X509_STORE_get1_crls(X509_STORE_CTX *ctx, X509_NAME *nm)
-	{
-	int i, idx, cnt;
-	STACK_OF(X509_CRL) *sk;
-	X509_CRL *x;
-	X509_OBJECT *obj, xobj;
-	sk = sk_X509_CRL_new_null();
-	if (sk == NULL)
-		return NULL;
+STACK_OF (X509_CRL) * X509_STORE_get1_crls(X509_STORE_CTX *ctx, X509_NAME *nm)
+{
+    int i, idx, cnt;
+    STACK_OF(X509_CRL) *sk;
+    X509_CRL *x;
+    X509_OBJECT *obj, xobj;
+    sk = sk_X509_CRL_new_null();
+    if (sk == NULL)
+        return NULL;
 
-	/* Always do lookup to possibly add new CRLs to cache. */
-	if (!X509_STORE_get_by_subject(ctx, X509_LU_CRL, nm, &xobj))
-		{
-		sk_X509_CRL_free(sk);
-		return NULL;
-		}
-	X509_OBJECT_free_contents(&xobj);
-	CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
-	idx = x509_object_idx_cnt(ctx->ctx->objs,X509_LU_CRL, nm, &cnt);
-	if (idx < 0)
-		{
-		CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
-		sk_X509_CRL_free(sk);
-		return NULL;
-		}
+    /* Always do lookup to possibly add new CRLs to cache. */
+    if (!X509_STORE_get_by_subject(ctx, X509_LU_CRL, nm, &xobj)) {
+        sk_X509_CRL_free(sk);
+        return NULL;
+    }
+    X509_OBJECT_free_contents(&xobj);
+    CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
+    idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_CRL, nm, &cnt);
+    if (idx < 0) {
+        CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
+        sk_X509_CRL_free(sk);
+        return NULL;
+    }
 
-	for (i = 0; i < cnt; i++, idx++)
-		{
-		obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx);
-		x = obj->data.crl;
-		X509_CRL_up_ref(x);
-		if (!sk_X509_CRL_push(sk, x))
-			{
-			CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
-			X509_CRL_free(x);
-			sk_X509_CRL_pop_free(sk, X509_CRL_free);
-			return NULL;
-			}
-		}
-	CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
-	return sk;
-	}
+    for (i = 0; i < cnt; i++, idx++) {
+        obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx);
+        x = obj->data.crl;
+        X509_CRL_up_ref(x);
+        if (!sk_X509_CRL_push(sk, x)) {
+            CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
+            X509_CRL_free(x);
+            sk_X509_CRL_pop_free(sk, X509_CRL_free);
+            return NULL;
+        }
+    }
+    CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
+    return sk;
+}
 
-X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, X509_OBJECT *x)
-	{
-	size_t idx, i;
-	X509_OBJECT *obj;
+X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h,
+                                        X509_OBJECT *x)
+{
+    size_t idx, i;
+    X509_OBJECT *obj;
 
-	if (!sk_X509_OBJECT_find(h, &idx, x)) {
-		return NULL;
-	}
-	if ((x->type != X509_LU_X509) && (x->type != X509_LU_CRL))
-		return sk_X509_OBJECT_value(h, idx);
-	for (i = idx; i < sk_X509_OBJECT_num(h); i++)
-		{
-		obj = sk_X509_OBJECT_value(h, i);
-		if (x509_object_cmp((const X509_OBJECT **)&obj, (const X509_OBJECT **)&x))
-			return NULL;
-		if (x->type == X509_LU_X509)
-			{
-			if (!X509_cmp(obj->data.x509, x->data.x509))
-				return obj;
-			}
-		else if (x->type == X509_LU_CRL)
-			{
-			if (!X509_CRL_match(obj->data.crl, x->data.crl))
-				return obj;
-			}
-		else
-			return obj;
-		}
-	return NULL;
-	}
+    if (!sk_X509_OBJECT_find(h, &idx, x)) {
+        return NULL;
+    }
+    if ((x->type != X509_LU_X509) && (x->type != X509_LU_CRL))
+        return sk_X509_OBJECT_value(h, idx);
+    for (i = idx; i < sk_X509_OBJECT_num(h); i++) {
+        obj = sk_X509_OBJECT_value(h, i);
+        if (x509_object_cmp
+            ((const X509_OBJECT **)&obj, (const X509_OBJECT **)&x))
+            return NULL;
+        if (x->type == X509_LU_X509) {
+            if (!X509_cmp(obj->data.x509, x->data.x509))
+                return obj;
+        } else if (x->type == X509_LU_CRL) {
+            if (!X509_CRL_match(obj->data.crl, x->data.crl))
+                return obj;
+        } else
+            return obj;
+    }
+    return NULL;
+}
 
-
-/* Try to get issuer certificate from store. Due to limitations
- * of the API this can only retrieve a single certificate matching
- * a given subject name. However it will fill the cache with all
- * matching certificates, so we can examine the cache for all
- * matches.
- *
- * Return values are:
- *  1 lookup successful.
- *  0 certificate not found.
- * -1 some other error.
+/*
+ * Try to get issuer certificate from store. Due to limitations of the API
+ * this can only retrieve a single certificate matching a given subject name.
+ * However it will fill the cache with all matching certificates, so we can
+ * examine the cache for all matches. Return values are: 1 lookup
+ * successful.  0 certificate not found. -1 some other error.
  */
 int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
-	{
-	X509_NAME *xn;
-	X509_OBJECT obj, *pobj;
-	int ok, idx, ret;
-	size_t i;
-	xn=X509_get_issuer_name(x);
-	ok=X509_STORE_get_by_subject(ctx,X509_LU_X509,xn,&obj);
-	if (ok != X509_LU_X509)
-		{
-		if (ok == X509_LU_RETRY)
-			{
-			X509_OBJECT_free_contents(&obj);
-			OPENSSL_PUT_ERROR(X509, X509_R_SHOULD_RETRY);
-			return -1;
-			}
-		else if (ok != X509_LU_FAIL)
-			{
-			X509_OBJECT_free_contents(&obj);
-			/* not good :-(, break anyway */
-			return -1;
-			}
-		return 0;
-		}
-	/* If certificate matches all OK */
-	if (ctx->check_issued(ctx, x, obj.data.x509))
-		{
-		*issuer = obj.data.x509;
-		return 1;
-		}
-	X509_OBJECT_free_contents(&obj);
+{
+    X509_NAME *xn;
+    X509_OBJECT obj, *pobj;
+    int idx, ret;
+    size_t i;
+    xn = X509_get_issuer_name(x);
+    if (!X509_STORE_get_by_subject(ctx, X509_LU_X509, xn, &obj))
+        return 0;
+    /* If certificate matches all OK */
+    if (ctx->check_issued(ctx, x, obj.data.x509)) {
+        *issuer = obj.data.x509;
+        return 1;
+    }
+    X509_OBJECT_free_contents(&obj);
 
-	/* Else find index of first cert accepted by 'check_issued' */
-	ret = 0;
-	CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
-	idx = X509_OBJECT_idx_by_subject(ctx->ctx->objs, X509_LU_X509, xn);
-	if (idx != -1) /* should be true as we've had at least one match */
-		{
-		/* Look through all matching certs for suitable issuer */
-		for (i = idx; i < sk_X509_OBJECT_num(ctx->ctx->objs); i++)
-			{
-			pobj = sk_X509_OBJECT_value(ctx->ctx->objs, i);
-			/* See if we've run past the matches */
-			if (pobj->type != X509_LU_X509)
-				break;
-			if (X509_NAME_cmp(xn, X509_get_subject_name(pobj->data.x509)))
-				break;
-			if (ctx->check_issued(ctx, x, pobj->data.x509))
-				{
-				*issuer = pobj->data.x509;
-				X509_OBJECT_up_ref_count(pobj);
-				ret = 1;
-				break;
-				}
-			}
-		}
-	CRYPTO_MUTEX_unlock(&ctx->ctx->objs_lock);
-	return ret;
-	}
+    /* Else find index of first cert accepted by 'check_issued' */
+    ret = 0;
+    CRYPTO_MUTEX_lock_write(&ctx->ctx->objs_lock);
+    idx = X509_OBJECT_idx_by_subject(ctx->ctx->objs, X509_LU_X509, xn);
+    if (idx != -1) {            /* should be true as we've had at least one
+                                 * match */
+        /* Look through all matching certs for suitable issuer */
+        for (i = idx; i < sk_X509_OBJECT_num(ctx->ctx->objs); i++) {
+            pobj = sk_X509_OBJECT_value(ctx->ctx->objs, i);
+            /* See if we've run past the matches */
+            if (pobj->type != X509_LU_X509)
+                break;
+            if (X509_NAME_cmp(xn, X509_get_subject_name(pobj->data.x509)))
+                break;
+            if (ctx->check_issued(ctx, x, pobj->data.x509)) {
+                *issuer = pobj->data.x509;
+                X509_OBJECT_up_ref_count(pobj);
+                ret = 1;
+                break;
+            }
+        }
+    }
+    CRYPTO_MUTEX_unlock_write(&ctx->ctx->objs_lock);
+    return ret;
+}
 
 int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags)
-	{
-	return X509_VERIFY_PARAM_set_flags(ctx->param, flags);
-	}
+{
+    return X509_VERIFY_PARAM_set_flags(ctx->param, flags);
+}
 
 int X509_STORE_set_depth(X509_STORE *ctx, int depth)
-	{
-	X509_VERIFY_PARAM_set_depth(ctx->param, depth);
-	return 1;
-	}
+{
+    X509_VERIFY_PARAM_set_depth(ctx->param, depth);
+    return 1;
+}
 
 int X509_STORE_set_purpose(X509_STORE *ctx, int purpose)
-	{
-	return X509_VERIFY_PARAM_set_purpose(ctx->param, purpose);
-	}
+{
+    return X509_VERIFY_PARAM_set_purpose(ctx->param, purpose);
+}
 
 int X509_STORE_set_trust(X509_STORE *ctx, int trust)
-	{
-	return X509_VERIFY_PARAM_set_trust(ctx->param, trust);
-	}
+{
+    return X509_VERIFY_PARAM_set_trust(ctx->param, trust);
+}
 
 int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *param)
-	{
-	return X509_VERIFY_PARAM_set1(ctx->param, param);
-	}
+{
+    return X509_VERIFY_PARAM_set1(ctx->param, param);
+}
 
 void X509_STORE_set_verify_cb(X509_STORE *ctx,
-				  int (*verify_cb)(int, X509_STORE_CTX *))
-	{
-	ctx->verify_cb = verify_cb;
-	}
+                              int (*verify_cb) (int, X509_STORE_CTX *))
+{
+    ctx->verify_cb = verify_cb;
+}
 
 void X509_STORE_set_lookup_crls_cb(X509_STORE *ctx,
-		STACK_OF(X509_CRL)* (*cb)(X509_STORE_CTX *ctx, X509_NAME *nm))
-	{
-	ctx->lookup_crls = cb;
-	}
+                                   STACK_OF (X509_CRL) *
+                                   (*cb) (X509_STORE_CTX *ctx, X509_NAME *nm))
+{
+    ctx->lookup_crls = cb;
+}
 
 X509_STORE *X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx)
-	{
-	return ctx->ctx;
-	}
+{
+    return ctx->ctx;
+}
diff --git a/src/crypto/x509/x509_obj.c b/src/crypto/x509/x509_obj.c
index b6f0816..33eafc4 100644
--- a/src/crypto/x509/x509_obj.c
+++ b/src/crypto/x509/x509_obj.c
@@ -64,128 +64,137 @@
 #include <openssl/obj.h>
 #include <openssl/x509.h>
 
+#include "../internal.h"
+
+
+/*
+ * Limit to ensure we don't overflow: much greater than
+ * anything enountered in practice.
+ */
+
+#define NAME_ONELINE_MAX    (1024 * 1024)
 
 char *X509_NAME_oneline(X509_NAME *a, char *buf, int len)
-	{
-	X509_NAME_ENTRY *ne;
-	size_t i;
-	int n,lold,l,l1,l2,num,j,type;
-	const char *s;
-	char *p;
-	unsigned char *q;
-	BUF_MEM *b=NULL;
-	static const char hex[17]="0123456789ABCDEF";
-	int gs_doit[4];
-	char tmp_buf[80];
+{
+    X509_NAME_ENTRY *ne;
+    size_t i;
+    int n, lold, l, l1, l2, num, j, type;
+    const char *s;
+    char *p;
+    unsigned char *q;
+    BUF_MEM *b = NULL;
+    static const char hex[17] = "0123456789ABCDEF";
+    int gs_doit[4];
+    char tmp_buf[80];
 
-	if (buf == NULL)
-		{
-		if ((b=BUF_MEM_new()) == NULL) goto err;
-		if (!BUF_MEM_grow(b,200)) goto err;
-		b->data[0]='\0';
-		len=200;
-		}
-	if (a == NULL)
-	    {
-	    if(b)
-		{
-		buf=b->data;
-		OPENSSL_free(b);
-		}
-	    strncpy(buf,"NO X509_NAME",len);
-	    buf[len-1]='\0';
-	    return buf;
-	    }
+    if (buf == NULL) {
+        if ((b = BUF_MEM_new()) == NULL)
+            goto err;
+        if (!BUF_MEM_grow(b, 200))
+            goto err;
+        b->data[0] = '\0';
+        len = 200;
+    } else if (len <= 0) {
+        return NULL;
+    }
+    if (a == NULL) {
+        if (b) {
+            buf = b->data;
+            OPENSSL_free(b);
+        }
+        strncpy(buf, "NO X509_NAME", len);
+        buf[len - 1] = '\0';
+        return buf;
+    }
 
-	len--; /* space for '\0' */
-	l=0;
-	for (i=0; i<sk_X509_NAME_ENTRY_num(a->entries); i++)
-		{
-		ne=sk_X509_NAME_ENTRY_value(a->entries,i);
-		n=OBJ_obj2nid(ne->object);
-		if ((n == NID_undef) || ((s=OBJ_nid2sn(n)) == NULL))
-			{
-			i2t_ASN1_OBJECT(tmp_buf,sizeof(tmp_buf),ne->object);
-			s=tmp_buf;
-			}
-		l1=strlen(s);
+    len--;                      /* space for '\0' */
+    l = 0;
+    for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
+        ne = sk_X509_NAME_ENTRY_value(a->entries, i);
+        n = OBJ_obj2nid(ne->object);
+        if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) {
+            i2t_ASN1_OBJECT(tmp_buf, sizeof(tmp_buf), ne->object);
+            s = tmp_buf;
+        }
+        l1 = strlen(s);
 
-		type=ne->value->type;
-		num=ne->value->length;
-		q=ne->value->data;
+        type = ne->value->type;
+        num = ne->value->length;
+        if (num > NAME_ONELINE_MAX) {
+            OPENSSL_PUT_ERROR(X509, X509_R_NAME_TOO_LONG);
+            goto end;
+        }
+        q = ne->value->data;
 
-		if ((type == V_ASN1_GENERALSTRING) && ((num%4) == 0))
-			{
-			gs_doit[0]=gs_doit[1]=gs_doit[2]=gs_doit[3]=0;
-			for (j=0; j<num; j++)
-				if (q[j] != 0) gs_doit[j&3]=1;
+        if ((type == V_ASN1_GENERALSTRING) && ((num % 4) == 0)) {
+            gs_doit[0] = gs_doit[1] = gs_doit[2] = gs_doit[3] = 0;
+            for (j = 0; j < num; j++)
+                if (q[j] != 0)
+                    gs_doit[j & 3] = 1;
 
-			if (gs_doit[0]|gs_doit[1]|gs_doit[2])
-				gs_doit[0]=gs_doit[1]=gs_doit[2]=gs_doit[3]=1;
-			else
-				{
-				gs_doit[0]=gs_doit[1]=gs_doit[2]=0;
-				gs_doit[3]=1;
-				}
-			}
-		else
-			gs_doit[0]=gs_doit[1]=gs_doit[2]=gs_doit[3]=1;
+            if (gs_doit[0] | gs_doit[1] | gs_doit[2])
+                gs_doit[0] = gs_doit[1] = gs_doit[2] = gs_doit[3] = 1;
+            else {
+                gs_doit[0] = gs_doit[1] = gs_doit[2] = 0;
+                gs_doit[3] = 1;
+            }
+        } else
+            gs_doit[0] = gs_doit[1] = gs_doit[2] = gs_doit[3] = 1;
 
-		for (l2=j=0; j<num; j++)
-			{
-			if (!gs_doit[j&3]) continue;
-			l2++;
-			if ((q[j] < ' ') || (q[j] > '~')) l2+=3;
-			}
+        for (l2 = j = 0; j < num; j++) {
+            if (!gs_doit[j & 3])
+                continue;
+            l2++;
+            if ((q[j] < ' ') || (q[j] > '~'))
+                l2 += 3;
+        }
 
-		lold=l;
-		l+=1+l1+1+l2;
-		if (b != NULL)
-			{
-			if (!BUF_MEM_grow(b,l+1)) goto err;
-			p= &(b->data[lold]);
-			}
-		else if (l > len)
-			{
-			break;
-			}
-		else
-			p= &(buf[lold]);
-		*(p++)='/';
-		memcpy(p,s,(unsigned int)l1); p+=l1;
-		*(p++)='=';
+        lold = l;
+        l += 1 + l1 + 1 + l2;
+        if (l > NAME_ONELINE_MAX) {
+            OPENSSL_PUT_ERROR(X509, X509_R_NAME_TOO_LONG);
+            goto end;
+        }
+        if (b != NULL) {
+            if (!BUF_MEM_grow(b, l + 1))
+                goto err;
+            p = &(b->data[lold]);
+        } else if (l > len) {
+            break;
+        } else
+            p = &(buf[lold]);
+        *(p++) = '/';
+        OPENSSL_memcpy(p, s, (unsigned int)l1);
+        p += l1;
+        *(p++) = '=';
 
-		q=ne->value->data;
+        q = ne->value->data;
 
-		for (j=0; j<num; j++)
-			{
-			if (!gs_doit[j&3]) continue;
-			n=q[j];
-			if ((n < ' ') || (n > '~'))
-				{
-				*(p++)='\\';
-				*(p++)='x';
-				*(p++)=hex[(n>>4)&0x0f];
-				*(p++)=hex[n&0x0f];
-				}
-			else
-				*(p++)=n;
-			}
-		*p='\0';
-		}
-	if (b != NULL)
-		{
-		p=b->data;
-		OPENSSL_free(b);
-		}
-	else
-		p=buf;
-	if (i == 0)
-		*p = '\0';
-	return(p);
-err:
-	OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-	if (b != NULL) BUF_MEM_free(b);
-	return(NULL);
-	}
-
+        for (j = 0; j < num; j++) {
+            if (!gs_doit[j & 3])
+                continue;
+            n = q[j];
+            if ((n < ' ') || (n > '~')) {
+                *(p++) = '\\';
+                *(p++) = 'x';
+                *(p++) = hex[(n >> 4) & 0x0f];
+                *(p++) = hex[n & 0x0f];
+            } else
+                *(p++) = n;
+        }
+        *p = '\0';
+    }
+    if (b != NULL) {
+        p = b->data;
+        OPENSSL_free(b);
+    } else
+        p = buf;
+    if (i == 0)
+        *p = '\0';
+    return (p);
+ err:
+    OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ end:
+    BUF_MEM_free(b);
+    return (NULL);
+}
diff --git a/src/crypto/x509/x509_r2x.c b/src/crypto/x509/x509_r2x.c
index 85979ac..9bdf441 100644
--- a/src/crypto/x509/x509_r2x.c
+++ b/src/crypto/x509/x509_r2x.c
@@ -63,51 +63,55 @@
 #include <openssl/obj.h>
 #include <openssl/x509.h>
 
-
 X509 *X509_REQ_to_X509(X509_REQ *r, int days, EVP_PKEY *pkey)
-	{
-	X509 *ret=NULL;
-	X509_CINF *xi=NULL;
-	X509_NAME *xn;
+{
+    X509 *ret = NULL;
+    X509_CINF *xi = NULL;
+    X509_NAME *xn;
+    EVP_PKEY *pubkey = NULL;
+    int res;
 
-	if ((ret=X509_new()) == NULL)
-		{
-		OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-		goto err;
-		}
+    if ((ret = X509_new()) == NULL) {
+        OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
 
-	/* duplicate the request */
-	xi=ret->cert_info;
+    /* duplicate the request */
+    xi = ret->cert_info;
 
-	if (sk_X509_ATTRIBUTE_num(r->req_info->attributes) != 0)
-		{
-		if ((xi->version=M_ASN1_INTEGER_new()) == NULL) goto err;
-		if (!ASN1_INTEGER_set(xi->version,2)) goto err;
-/*		xi->extensions=ri->attributes; <- bad, should not ever be done
-		ri->attributes=NULL; */
-		}
+    if (sk_X509_ATTRIBUTE_num(r->req_info->attributes) != 0) {
+        if ((xi->version = M_ASN1_INTEGER_new()) == NULL)
+            goto err;
+        if (!ASN1_INTEGER_set(xi->version, 2))
+            goto err;
+        /*
+         * xi->extensions=ri->attributes; <- bad, should not ever be done
+         * ri->attributes=NULL;
+         */
+    }
 
-	xn=X509_REQ_get_subject_name(r);
-	if (X509_set_subject_name(ret,X509_NAME_dup(xn)) == 0)
-		goto err;
-	if (X509_set_issuer_name(ret,X509_NAME_dup(xn)) == 0)
-		goto err;
+    xn = X509_REQ_get_subject_name(r);
+    if (X509_set_subject_name(ret, xn) == 0)
+        goto err;
+    if (X509_set_issuer_name(ret, xn) == 0)
+        goto err;
 
-	if (X509_gmtime_adj(xi->validity->notBefore,0) == NULL)
-		goto err;
-	if (X509_gmtime_adj(xi->validity->notAfter,(long)60*60*24*days) == NULL)
-		goto err;
+    if (X509_gmtime_adj(xi->validity->notBefore, 0) == NULL)
+        goto err;
+    if (X509_gmtime_adj(xi->validity->notAfter, (long)60 * 60 * 24 * days) ==
+        NULL)
+        goto err;
 
-	X509_set_pubkey(ret,X509_REQ_get_pubkey(r));
+    pubkey = X509_REQ_get_pubkey(r);
+    res = X509_set_pubkey(ret, pubkey);
+    EVP_PKEY_free(pubkey);
 
-	if (!X509_sign(ret,pkey,EVP_md5()))
-		goto err;
-	if (0)
-		{
-err:
-		X509_free(ret);
-		ret=NULL;
-		}
-	return(ret);
-	}
-
+    if (!res || !X509_sign(ret, pkey, EVP_md5()))
+        goto err;
+    if (0) {
+ err:
+        X509_free(ret);
+        ret = NULL;
+    }
+    return (ret);
+}
diff --git a/src/crypto/x509/x509_req.c b/src/crypto/x509/x509_req.c
index 01c5113..69bc6f1 100644
--- a/src/crypto/x509/x509_req.c
+++ b/src/crypto/x509/x509_req.c
@@ -66,250 +66,257 @@
 #include <openssl/pem.h>
 #include <openssl/x509.h>
 
-
 X509_REQ *X509_to_X509_REQ(X509 *x, EVP_PKEY *pkey, const EVP_MD *md)
-	{
-	X509_REQ *ret;
-	X509_REQ_INFO *ri;
-	int i;
-	EVP_PKEY *pktmp;
+{
+    X509_REQ *ret;
+    X509_REQ_INFO *ri;
+    int i;
+    EVP_PKEY *pktmp;
 
-	ret=X509_REQ_new();
-	if (ret == NULL)
-		{
-		OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-		goto err;
-		}
+    ret = X509_REQ_new();
+    if (ret == NULL) {
+        OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
 
-	ri=ret->req_info;
+    ri = ret->req_info;
 
-	ri->version->length=1;
-	ri->version->data=(unsigned char *)OPENSSL_malloc(1);
-	if (ri->version->data == NULL) goto err;
-	ri->version->data[0]=0; /* version == 0 */
+    ri->version->length = 1;
+    ri->version->data = (unsigned char *)OPENSSL_malloc(1);
+    if (ri->version->data == NULL)
+        goto err;
+    ri->version->data[0] = 0;   /* version == 0 */
 
-	if (!X509_REQ_set_subject_name(ret,X509_get_subject_name(x)))
-		goto err;
+    if (!X509_REQ_set_subject_name(ret, X509_get_subject_name(x)))
+        goto err;
 
-	pktmp = X509_get_pubkey(x);
-	if (pktmp == NULL)
-		goto err;
-	i=X509_REQ_set_pubkey(ret,pktmp);
-	EVP_PKEY_free(pktmp);
-	if (!i) goto err;
+    pktmp = X509_get_pubkey(x);
+    if (pktmp == NULL)
+        goto err;
+    i = X509_REQ_set_pubkey(ret, pktmp);
+    EVP_PKEY_free(pktmp);
+    if (!i)
+        goto err;
 
-	if (pkey != NULL)
-		{
-		if (!X509_REQ_sign(ret,pkey,md))
-			goto err;
-		}
-	return(ret);
-err:
-	X509_REQ_free(ret);
-	return(NULL);
-	}
+    if (pkey != NULL) {
+        if (!X509_REQ_sign(ret, pkey, md))
+            goto err;
+    }
+    return (ret);
+ err:
+    X509_REQ_free(ret);
+    return (NULL);
+}
 
 EVP_PKEY *X509_REQ_get_pubkey(X509_REQ *req)
-	{
-	if ((req == NULL) || (req->req_info == NULL))
-		return(NULL);
-	return(X509_PUBKEY_get(req->req_info->pubkey));
-	}
+{
+    if ((req == NULL) || (req->req_info == NULL))
+        return (NULL);
+    return (X509_PUBKEY_get(req->req_info->pubkey));
+}
 
 int X509_REQ_check_private_key(X509_REQ *x, EVP_PKEY *k)
-	{
-	EVP_PKEY *xk=NULL;
-	int ok=0;
+{
+    EVP_PKEY *xk = NULL;
+    int ok = 0;
 
-	xk=X509_REQ_get_pubkey(x);
-	switch (EVP_PKEY_cmp(xk, k))
-		{
-	case 1:
-		ok=1;
-		break;
-	case 0:
-		OPENSSL_PUT_ERROR(X509, X509_R_KEY_VALUES_MISMATCH);
-		break;
-	case -1:
-		OPENSSL_PUT_ERROR(X509, X509_R_KEY_TYPE_MISMATCH);
-		break;
-	case -2:
-		if (k->type == EVP_PKEY_EC)
-			{
-			OPENSSL_PUT_ERROR(X509, ERR_R_EC_LIB);
-			break;
-			}
-		if (k->type == EVP_PKEY_DH)
-			{
-			/* No idea */
-			OPENSSL_PUT_ERROR(X509, X509_R_CANT_CHECK_DH_KEY);
-			break;
-			}
-	        OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_KEY_TYPE);
-		}
+    xk = X509_REQ_get_pubkey(x);
+    switch (EVP_PKEY_cmp(xk, k)) {
+    case 1:
+        ok = 1;
+        break;
+    case 0:
+        OPENSSL_PUT_ERROR(X509, X509_R_KEY_VALUES_MISMATCH);
+        break;
+    case -1:
+        OPENSSL_PUT_ERROR(X509, X509_R_KEY_TYPE_MISMATCH);
+        break;
+    case -2:
+        if (k->type == EVP_PKEY_EC) {
+            OPENSSL_PUT_ERROR(X509, ERR_R_EC_LIB);
+            break;
+        }
+        if (k->type == EVP_PKEY_DH) {
+            /* No idea */
+            OPENSSL_PUT_ERROR(X509, X509_R_CANT_CHECK_DH_KEY);
+            break;
+        }
+        OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_KEY_TYPE);
+    }
 
-	EVP_PKEY_free(xk);
-	return(ok);
-	}
+    EVP_PKEY_free(xk);
+    return (ok);
+}
 
-/* It seems several organisations had the same idea of including a list of
+/*
+ * It seems several organisations had the same idea of including a list of
  * extensions in a certificate request. There are at least two OIDs that are
  * used and there may be more: so the list is configurable.
  */
 
-static const int ext_nid_list[] = { NID_ext_req, NID_ms_ext_req, NID_undef};
+static const int ext_nid_list[] = { NID_ext_req, NID_ms_ext_req, NID_undef };
 
 static const int *ext_nids = ext_nid_list;
 
 int X509_REQ_extension_nid(int req_nid)
 {
-	int i, nid;
-	for(i = 0; ; i++) {
-		nid = ext_nids[i];
-		if(nid == NID_undef) return 0;
-		else if (req_nid == nid) return 1;
-	}
+    int i, nid;
+    for (i = 0;; i++) {
+        nid = ext_nids[i];
+        if (nid == NID_undef)
+            return 0;
+        else if (req_nid == nid)
+            return 1;
+    }
 }
 
 const int *X509_REQ_get_extension_nids(void)
 {
-	return ext_nids;
+    return ext_nids;
 }
-	
+
 void X509_REQ_set_extension_nids(const int *nids)
 {
-	ext_nids = nids;
+    ext_nids = nids;
 }
 
 STACK_OF(X509_EXTENSION) *X509_REQ_get_extensions(X509_REQ *req)
-	{
-	X509_ATTRIBUTE *attr;
-	ASN1_TYPE *ext = NULL;
-	int idx;
-	const int *pnid;
-	const unsigned char *p;
+{
+    X509_ATTRIBUTE *attr;
+    ASN1_TYPE *ext = NULL;
+    int idx;
+    const int *pnid;
+    const unsigned char *p;
 
-	if ((req == NULL) || (req->req_info == NULL) || !ext_nids)
-		return(NULL);
-	for (pnid = ext_nids; *pnid != NID_undef; pnid++)
-		{
-		idx = X509_REQ_get_attr_by_NID(req, *pnid, -1);
-		if (idx == -1)
-			continue;
-		attr = X509_REQ_get_attr(req, idx);
-		if(attr->single) ext = attr->value.single;
-		else if(sk_ASN1_TYPE_num(attr->value.set))
-			ext = sk_ASN1_TYPE_value(attr->value.set, 0);
-		break;
-		}
-	if(!ext || (ext->type != V_ASN1_SEQUENCE))
-		return NULL;
-	p = ext->value.sequence->data;
-	return (STACK_OF(X509_EXTENSION) *)
-		ASN1_item_d2i(NULL, &p, ext->value.sequence->length,
-				ASN1_ITEM_rptr(X509_EXTENSIONS));
+    if ((req == NULL) || (req->req_info == NULL) || !ext_nids)
+        return (NULL);
+    for (pnid = ext_nids; *pnid != NID_undef; pnid++) {
+        idx = X509_REQ_get_attr_by_NID(req, *pnid, -1);
+        if (idx == -1)
+            continue;
+        attr = X509_REQ_get_attr(req, idx);
+        if (attr->single)
+            ext = attr->value.single;
+        else if (sk_ASN1_TYPE_num(attr->value.set))
+            ext = sk_ASN1_TYPE_value(attr->value.set, 0);
+        break;
+    }
+    if (!ext || (ext->type != V_ASN1_SEQUENCE))
+        return NULL;
+    p = ext->value.sequence->data;
+    return (STACK_OF(X509_EXTENSION) *)
+        ASN1_item_d2i(NULL, &p, ext->value.sequence->length,
+                      ASN1_ITEM_rptr(X509_EXTENSIONS));
 }
 
-/* Add a STACK_OF extensions to a certificate request: allow alternative OIDs
+/*
+ * Add a STACK_OF extensions to a certificate request: allow alternative OIDs
  * in case we want to create a non standard one.
  */
 
 int X509_REQ_add_extensions_nid(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts,
-				int nid)
+                                int nid)
 {
-	ASN1_TYPE *at = NULL;
-	X509_ATTRIBUTE *attr = NULL;
-	if(!(at = ASN1_TYPE_new()) ||
-		!(at->value.sequence = ASN1_STRING_new())) goto err;
+    ASN1_TYPE *at = NULL;
+    X509_ATTRIBUTE *attr = NULL;
+    if (!(at = ASN1_TYPE_new()) || !(at->value.sequence = ASN1_STRING_new()))
+        goto err;
 
-	at->type = V_ASN1_SEQUENCE;
-	/* Generate encoding of extensions */
-	at->value.sequence->length = 
-			ASN1_item_i2d((ASN1_VALUE *)exts,
-				&at->value.sequence->data,
-				ASN1_ITEM_rptr(X509_EXTENSIONS));
-	if(!(attr = X509_ATTRIBUTE_new())) goto err;
-	if(!(attr->value.set = sk_ASN1_TYPE_new_null())) goto err;
-	if(!sk_ASN1_TYPE_push(attr->value.set, at)) goto err;
-	at = NULL;
-	attr->single = 0;
-	attr->object = (ASN1_OBJECT*) OBJ_nid2obj(nid);
-	if (!req->req_info->attributes)
-		{
-		if (!(req->req_info->attributes = sk_X509_ATTRIBUTE_new_null()))
-			goto err;
-		}
-	if(!sk_X509_ATTRIBUTE_push(req->req_info->attributes, attr)) goto err;
-	return 1;
-	err:
-	X509_ATTRIBUTE_free(attr);
-	ASN1_TYPE_free(at);
-	return 0;
+    at->type = V_ASN1_SEQUENCE;
+    /* Generate encoding of extensions */
+    at->value.sequence->length =
+        ASN1_item_i2d((ASN1_VALUE *)exts,
+                      &at->value.sequence->data,
+                      ASN1_ITEM_rptr(X509_EXTENSIONS));
+    if (!(attr = X509_ATTRIBUTE_new()))
+        goto err;
+    if (!(attr->value.set = sk_ASN1_TYPE_new_null()))
+        goto err;
+    if (!sk_ASN1_TYPE_push(attr->value.set, at))
+        goto err;
+    at = NULL;
+    attr->single = 0;
+    attr->object = (ASN1_OBJECT *)OBJ_nid2obj(nid);
+    if (!req->req_info->attributes) {
+        if (!(req->req_info->attributes = sk_X509_ATTRIBUTE_new_null()))
+            goto err;
+    }
+    if (!sk_X509_ATTRIBUTE_push(req->req_info->attributes, attr))
+        goto err;
+    return 1;
+ err:
+    X509_ATTRIBUTE_free(attr);
+    ASN1_TYPE_free(at);
+    return 0;
 }
+
 /* This is the normal usage: use the "official" OID */
 int X509_REQ_add_extensions(X509_REQ *req, STACK_OF(X509_EXTENSION) *exts)
 {
-	return X509_REQ_add_extensions_nid(req, exts, NID_ext_req);
+    return X509_REQ_add_extensions_nid(req, exts, NID_ext_req);
 }
 
 /* Request attribute functions */
 
 int X509_REQ_get_attr_count(const X509_REQ *req)
 {
-	return X509at_get_attr_count(req->req_info->attributes);
+    return X509at_get_attr_count(req->req_info->attributes);
 }
 
-int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid,
-			  int lastpos)
+int X509_REQ_get_attr_by_NID(const X509_REQ *req, int nid, int lastpos)
 {
-	return X509at_get_attr_by_NID(req->req_info->attributes, nid, lastpos);
+    return X509at_get_attr_by_NID(req->req_info->attributes, nid, lastpos);
 }
 
 int X509_REQ_get_attr_by_OBJ(const X509_REQ *req, ASN1_OBJECT *obj,
-			  int lastpos)
+                             int lastpos)
 {
-	return X509at_get_attr_by_OBJ(req->req_info->attributes, obj, lastpos);
+    return X509at_get_attr_by_OBJ(req->req_info->attributes, obj, lastpos);
 }
 
 X509_ATTRIBUTE *X509_REQ_get_attr(const X509_REQ *req, int loc)
 {
-	return X509at_get_attr(req->req_info->attributes, loc);
+    return X509at_get_attr(req->req_info->attributes, loc);
 }
 
 X509_ATTRIBUTE *X509_REQ_delete_attr(X509_REQ *req, int loc)
 {
-	return X509at_delete_attr(req->req_info->attributes, loc);
+    return X509at_delete_attr(req->req_info->attributes, loc);
 }
 
 int X509_REQ_add1_attr(X509_REQ *req, X509_ATTRIBUTE *attr)
 {
-	if(X509at_add1_attr(&req->req_info->attributes, attr)) return 1;
-	return 0;
+    if (X509at_add1_attr(&req->req_info->attributes, attr))
+        return 1;
+    return 0;
 }
 
 int X509_REQ_add1_attr_by_OBJ(X509_REQ *req,
-			const ASN1_OBJECT *obj, int type,
-			const unsigned char *bytes, int len)
+                              const ASN1_OBJECT *obj, int type,
+                              const unsigned char *bytes, int len)
 {
-	if(X509at_add1_attr_by_OBJ(&req->req_info->attributes, obj,
-				type, bytes, len)) return 1;
-	return 0;
+    if (X509at_add1_attr_by_OBJ(&req->req_info->attributes, obj,
+                                type, bytes, len))
+        return 1;
+    return 0;
 }
 
 int X509_REQ_add1_attr_by_NID(X509_REQ *req,
-			int nid, int type,
-			const unsigned char *bytes, int len)
+                              int nid, int type,
+                              const unsigned char *bytes, int len)
 {
-	if(X509at_add1_attr_by_NID(&req->req_info->attributes, nid,
-				type, bytes, len)) return 1;
-	return 0;
+    if (X509at_add1_attr_by_NID(&req->req_info->attributes, nid,
+                                type, bytes, len))
+        return 1;
+    return 0;
 }
 
 int X509_REQ_add1_attr_by_txt(X509_REQ *req,
-			const char *attrname, int type,
-			const unsigned char *bytes, int len)
+                              const char *attrname, int type,
+                              const unsigned char *bytes, int len)
 {
-	if(X509at_add1_attr_by_txt(&req->req_info->attributes, attrname,
-				type, bytes, len)) return 1;
-	return 0;
+    if (X509at_add1_attr_by_txt(&req->req_info->attributes, attrname,
+                                type, bytes, len))
+        return 1;
+    return 0;
 }
diff --git a/src/crypto/x509/x509_set.c b/src/crypto/x509/x509_set.c
index 06658b0..67c1842 100644
--- a/src/crypto/x509/x509_set.c
+++ b/src/crypto/x509/x509_set.c
@@ -60,95 +60,95 @@
 #include <openssl/obj.h>
 #include <openssl/x509.h>
 
-
 int X509_set_version(X509 *x, long version)
-	{
-	if (x == NULL) return(0);
-	if (version == 0)
-		{
-		M_ASN1_INTEGER_free(x->cert_info->version);
-		x->cert_info->version = NULL;
-		return(1);
-		}
-	if (x->cert_info->version == NULL)
-		{
-		if ((x->cert_info->version=M_ASN1_INTEGER_new()) == NULL)
-			return(0);
-		}
-	return(ASN1_INTEGER_set(x->cert_info->version,version));
-	}
+{
+    if (x == NULL)
+        return (0);
+    if (version == 0) {
+        M_ASN1_INTEGER_free(x->cert_info->version);
+        x->cert_info->version = NULL;
+        return (1);
+    }
+    if (x->cert_info->version == NULL) {
+        if ((x->cert_info->version = M_ASN1_INTEGER_new()) == NULL)
+            return (0);
+    }
+    return (ASN1_INTEGER_set(x->cert_info->version, version));
+}
 
 int X509_set_serialNumber(X509 *x, ASN1_INTEGER *serial)
-	{
-	ASN1_INTEGER *in;
+{
+    ASN1_INTEGER *in;
 
-	if (x == NULL) return(0);
-	in=x->cert_info->serialNumber;
-	if (in != serial)
-		{
-		in=M_ASN1_INTEGER_dup(serial);
-		if (in != NULL)
-			{
-			M_ASN1_INTEGER_free(x->cert_info->serialNumber);
-			x->cert_info->serialNumber=in;
-			}
-		}
-	return(in != NULL);
-	}
+    if (x == NULL)
+        return (0);
+    in = x->cert_info->serialNumber;
+    if (in != serial) {
+        in = M_ASN1_INTEGER_dup(serial);
+        if (in != NULL) {
+            M_ASN1_INTEGER_free(x->cert_info->serialNumber);
+            x->cert_info->serialNumber = in;
+        }
+    }
+    return (in != NULL);
+}
 
 int X509_set_issuer_name(X509 *x, X509_NAME *name)
-	{
-	if ((x == NULL) || (x->cert_info == NULL)) return(0);
-	return(X509_NAME_set(&x->cert_info->issuer,name));
-	}
+{
+    if ((x == NULL) || (x->cert_info == NULL))
+        return (0);
+    return (X509_NAME_set(&x->cert_info->issuer, name));
+}
 
 int X509_set_subject_name(X509 *x, X509_NAME *name)
-	{
-	if ((x == NULL) || (x->cert_info == NULL)) return(0);
-	return(X509_NAME_set(&x->cert_info->subject,name));
-	}
+{
+    if ((x == NULL) || (x->cert_info == NULL))
+        return (0);
+    return (X509_NAME_set(&x->cert_info->subject, name));
+}
 
 int X509_set_notBefore(X509 *x, const ASN1_TIME *tm)
-	{
-	ASN1_TIME *in;
+{
+    ASN1_TIME *in;
 
-	if ((x == NULL) || (x->cert_info->validity == NULL)) return(0);
-	in=x->cert_info->validity->notBefore;
-	if (in != tm)
-		{
-		in=M_ASN1_TIME_dup(tm);
-		if (in != NULL)
-			{
-			M_ASN1_TIME_free(x->cert_info->validity->notBefore);
-			x->cert_info->validity->notBefore=in;
-			}
-		}
-	return(in != NULL);
-	}
+    if ((x == NULL) || (x->cert_info->validity == NULL))
+        return (0);
+    in = x->cert_info->validity->notBefore;
+    if (in != tm) {
+        in = M_ASN1_TIME_dup(tm);
+        if (in != NULL) {
+            M_ASN1_TIME_free(x->cert_info->validity->notBefore);
+            x->cert_info->validity->notBefore = in;
+        }
+    }
+    return (in != NULL);
+}
 
 int X509_set_notAfter(X509 *x, const ASN1_TIME *tm)
-	{
-	ASN1_TIME *in;
+{
+    ASN1_TIME *in;
 
-	if ((x == NULL) || (x->cert_info->validity == NULL)) return(0);
-	in=x->cert_info->validity->notAfter;
-	if (in != tm)
-		{
-		in=M_ASN1_TIME_dup(tm);
-		if (in != NULL)
-			{
-			M_ASN1_TIME_free(x->cert_info->validity->notAfter);
-			x->cert_info->validity->notAfter=in;
-			}
-		}
-	return(in != NULL);
-	}
+    if ((x == NULL) || (x->cert_info->validity == NULL))
+        return (0);
+    in = x->cert_info->validity->notAfter;
+    if (in != tm) {
+        in = M_ASN1_TIME_dup(tm);
+        if (in != NULL) {
+            M_ASN1_TIME_free(x->cert_info->validity->notAfter);
+            x->cert_info->validity->notAfter = in;
+        }
+    }
+    return (in != NULL);
+}
 
 int X509_set_pubkey(X509 *x, EVP_PKEY *pkey)
-	{
-	if ((x == NULL) || (x->cert_info == NULL)) return(0);
-	return(X509_PUBKEY_set(&(x->cert_info->key),pkey));
-	}
+{
+    if ((x == NULL) || (x->cert_info == NULL))
+        return (0);
+    return (X509_PUBKEY_set(&(x->cert_info->key), pkey));
+}
 
-
-
+STACK_OF(X509_EXTENSION) *X509_get0_extensions(const X509 *x)
+{
+    return x->cert_info->extensions;
+}
diff --git a/src/crypto/x509/x509_test.cc b/src/crypto/x509/x509_test.cc
new file mode 100644
index 0000000..4b80af8
--- /dev/null
+++ b/src/crypto/x509/x509_test.cc
@@ -0,0 +1,1101 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <vector>
+
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/bio.h>
+#include <openssl/bytestring.h>
+#include <openssl/crypto.h>
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/pool.h>
+#include <openssl/x509.h>
+
+#include "../internal.h"
+
+
+static const char kCrossSigningRootPEM[] =
+    "-----BEGIN CERTIFICATE-----\n"
+    "MIICcTCCAdqgAwIBAgIIagJHiPvE0MowDQYJKoZIhvcNAQELBQAwPDEaMBgGA1UE\n"
+    "ChMRQm9yaW5nU1NMIFRFU1RJTkcxHjAcBgNVBAMTFUNyb3NzLXNpZ25pbmcgUm9v\n"
+    "dCBDQTAgFw0xNTAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowPDEaMBgGA1UE\n"
+    "ChMRQm9yaW5nU1NMIFRFU1RJTkcxHjAcBgNVBAMTFUNyb3NzLXNpZ25pbmcgUm9v\n"
+    "dCBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwo3qFvSB9Zmlbpzn9wJp\n"
+    "ikI75Rxkatez8VkLqyxbOhPYl2Haz8F5p1gDG96dCI6jcLGgu3AKT9uhEQyyUko5\n"
+    "EKYasazSeA9CQrdyhPg0mkTYVETnPM1W/ebid1YtqQbq1CMWlq2aTDoSGAReGFKP\n"
+    "RTdXAbuAXzpCfi/d8LqV13UCAwEAAaN6MHgwDgYDVR0PAQH/BAQDAgIEMB0GA1Ud\n"
+    "JQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAPBgNVHRMBAf8EBTADAQH/MBkGA1Ud\n"
+    "DgQSBBBHKHC7V3Z/3oLvEZx0RZRwMBsGA1UdIwQUMBKAEEcocLtXdn/egu8RnHRF\n"
+    "lHAwDQYJKoZIhvcNAQELBQADgYEAnglibsy6mGtpIXivtlcz4zIEnHw/lNW+r/eC\n"
+    "CY7evZTmOoOuC/x9SS3MF9vawt1HFUummWM6ZgErqVBOXIB4//ykrcCgf5ZbF5Hr\n"
+    "+3EFprKhBqYiXdD8hpBkrBoXwn85LPYWNd2TceCrx0YtLIprE2R5MB2RIq8y4Jk3\n"
+    "YFXvkME=\n"
+    "-----END CERTIFICATE-----\n";
+
+static const char kRootCAPEM[] =
+    "-----BEGIN CERTIFICATE-----\n"
+    "MIICVTCCAb6gAwIBAgIIAj5CwoHlWuYwDQYJKoZIhvcNAQELBQAwLjEaMBgGA1UE\n"
+    "ChMRQm9yaW5nU1NMIFRFU1RJTkcxEDAOBgNVBAMTB1Jvb3QgQ0EwIBcNMTUwMTAx\n"
+    "MDAwMDAwWhgPMjEwMDAxMDEwMDAwMDBaMC4xGjAYBgNVBAoTEUJvcmluZ1NTTCBU\n"
+    "RVNUSU5HMRAwDgYDVQQDEwdSb290IENBMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB\n"
+    "iQKBgQDpDn8RDOZa5oaDcPZRBy4CeBH1siSSOO4mYgLHlPE+oXdqwI/VImi2XeJM\n"
+    "2uCFETXCknJJjYG0iJdrt/yyRFvZTQZw+QzGj+mz36NqhGxDWb6dstB2m8PX+plZ\n"
+    "w7jl81MDvUnWs8yiQ/6twgu5AbhWKZQDJKcNKCEpqa6UW0r5nwIDAQABo3oweDAO\n"
+    "BgNVHQ8BAf8EBAMCAgQwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA8G\n"
+    "A1UdEwEB/wQFMAMBAf8wGQYDVR0OBBIEEEA31wH7QC+4HH5UBCeMWQEwGwYDVR0j\n"
+    "BBQwEoAQQDfXAftAL7gcflQEJ4xZATANBgkqhkiG9w0BAQsFAAOBgQDXylEK77Za\n"
+    "kKeY6ZerrScWyZhrjIGtHFu09qVpdJEzrk87k2G7iHHR9CAvSofCgEExKtWNS9dN\n"
+    "+9WiZp/U48iHLk7qaYXdEuO07No4BYtXn+lkOykE+FUxmA4wvOF1cTd2tdj3MzX2\n"
+    "kfGIBAYhzGZWhY3JbhIfTEfY1PNM1pWChQ==\n"
+    "-----END CERTIFICATE-----\n";
+
+static const char kRootCrossSignedPEM[] =
+    "-----BEGIN CERTIFICATE-----\n"
+    "MIICYzCCAcygAwIBAgIIAj5CwoHlWuYwDQYJKoZIhvcNAQELBQAwPDEaMBgGA1UE\n"
+    "ChMRQm9yaW5nU1NMIFRFU1RJTkcxHjAcBgNVBAMTFUNyb3NzLXNpZ25pbmcgUm9v\n"
+    "dCBDQTAgFw0xNTAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowLjEaMBgGA1UE\n"
+    "ChMRQm9yaW5nU1NMIFRFU1RJTkcxEDAOBgNVBAMTB1Jvb3QgQ0EwgZ8wDQYJKoZI\n"
+    "hvcNAQEBBQADgY0AMIGJAoGBAOkOfxEM5lrmhoNw9lEHLgJ4EfWyJJI47iZiAseU\n"
+    "8T6hd2rAj9UiaLZd4kza4IURNcKSckmNgbSIl2u3/LJEW9lNBnD5DMaP6bPfo2qE\n"
+    "bENZvp2y0Habw9f6mVnDuOXzUwO9SdazzKJD/q3CC7kBuFYplAMkpw0oISmprpRb\n"
+    "SvmfAgMBAAGjejB4MA4GA1UdDwEB/wQEAwICBDAdBgNVHSUEFjAUBggrBgEFBQcD\n"
+    "AQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAZBgNVHQ4EEgQQQDfXAftAL7gc\n"
+    "flQEJ4xZATAbBgNVHSMEFDASgBBHKHC7V3Z/3oLvEZx0RZRwMA0GCSqGSIb3DQEB\n"
+    "CwUAA4GBAErTxYJ0en9HVRHAAr5OO5wuk5Iq3VMc79TMyQLCXVL8YH8Uk7KEwv+q\n"
+    "9MEKZv2eR/Vfm4HlXlUuIqfgUXbwrAYC/YVVX86Wnbpy/jc73NYVCq8FEZeO+0XU\n"
+    "90SWAPDdp+iL7aZdimnMtG1qlM1edmz8AKbrhN/R3IbA2CL0nCWV\n"
+    "-----END CERTIFICATE-----\n";
+
+static const char kIntermediatePEM[] =
+    "-----BEGIN CERTIFICATE-----\n"
+    "MIICXjCCAcegAwIBAgIJAKJMH+7rscPcMA0GCSqGSIb3DQEBCwUAMC4xGjAYBgNV\n"
+    "BAoTEUJvcmluZ1NTTCBURVNUSU5HMRAwDgYDVQQDEwdSb290IENBMCAXDTE1MDEw\n"
+    "MTAwMDAwMFoYDzIxMDAwMTAxMDAwMDAwWjA2MRowGAYDVQQKExFCb3JpbmdTU0wg\n"
+    "VEVTVElORzEYMBYGA1UEAxMPSW50ZXJtZWRpYXRlIENBMIGfMA0GCSqGSIb3DQEB\n"
+    "AQUAA4GNADCBiQKBgQC7YtI0l8ocTYJ0gKyXTtPL4iMJCNY4OcxXl48jkncVG1Hl\n"
+    "blicgNUa1r9m9YFtVkxvBinb8dXiUpEGhVg4awRPDcatlsBSEBuJkiZGYbRcAmSu\n"
+    "CmZYnf6u3aYQ18SU8WqVERPpE4cwVVs+6kwlzRw0+XDoZAczu8ZezVhCUc6NbQID\n"
+    "AQABo3oweDAOBgNVHQ8BAf8EBAMCAgQwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG\n"
+    "AQUFBwMCMA8GA1UdEwEB/wQFMAMBAf8wGQYDVR0OBBIEEIwaaKi1dttdV3sfjRSy\n"
+    "BqMwGwYDVR0jBBQwEoAQQDfXAftAL7gcflQEJ4xZATANBgkqhkiG9w0BAQsFAAOB\n"
+    "gQCvnolNWEHuQS8PFVVyuLR+FKBeUUdrVbSfHSzTqNAqQGp0C9fk5oCzDq6ZgTfY\n"
+    "ESXM4cJhb3IAnW0UM0NFsYSKQJ50JZL2L3z5ZLQhHdbs4RmODGoC40BVdnJ4/qgB\n"
+    "aGSh09eQRvAVmbVCviDK2ipkWNegdyI19jFfNP5uIkGlYg==\n"
+    "-----END CERTIFICATE-----\n";
+
+static const char kIntermediateSelfSignedPEM[] =
+    "-----BEGIN CERTIFICATE-----\n"
+    "MIICZjCCAc+gAwIBAgIJAKJMH+7rscPcMA0GCSqGSIb3DQEBCwUAMDYxGjAYBgNV\n"
+    "BAoTEUJvcmluZ1NTTCBURVNUSU5HMRgwFgYDVQQDEw9JbnRlcm1lZGlhdGUgQ0Ew\n"
+    "IBcNMTUwMTAxMDAwMDAwWhgPMjEwMDAxMDEwMDAwMDBaMDYxGjAYBgNVBAoTEUJv\n"
+    "cmluZ1NTTCBURVNUSU5HMRgwFgYDVQQDEw9JbnRlcm1lZGlhdGUgQ0EwgZ8wDQYJ\n"
+    "KoZIhvcNAQEBBQADgY0AMIGJAoGBALti0jSXyhxNgnSArJdO08viIwkI1jg5zFeX\n"
+    "jyOSdxUbUeVuWJyA1RrWv2b1gW1WTG8GKdvx1eJSkQaFWDhrBE8Nxq2WwFIQG4mS\n"
+    "JkZhtFwCZK4KZlid/q7dphDXxJTxapURE+kThzBVWz7qTCXNHDT5cOhkBzO7xl7N\n"
+    "WEJRzo1tAgMBAAGjejB4MA4GA1UdDwEB/wQEAwICBDAdBgNVHSUEFjAUBggrBgEF\n"
+    "BQcDAQYIKwYBBQUHAwIwDwYDVR0TAQH/BAUwAwEB/zAZBgNVHQ4EEgQQjBpoqLV2\n"
+    "211Xex+NFLIGozAbBgNVHSMEFDASgBCMGmiotXbbXVd7H40UsgajMA0GCSqGSIb3\n"
+    "DQEBCwUAA4GBALcccSrAQ0/EqQBsx0ZDTUydHXXNP2DrUkpUKmAXIe8McqIVSlkT\n"
+    "6H4xz7z8VRKBo9j+drjjtCw2i0CQc8aOLxRb5WJ8eVLnaW2XRlUqAzhF0CrulfVI\n"
+    "E4Vs6ZLU+fra1WAuIj6qFiigRja+3YkZArG8tMA9vtlhTX/g7YBZIkqH\n"
+    "-----END CERTIFICATE-----\n";
+
+static const char kLeafPEM[] =
+    "-----BEGIN CERTIFICATE-----\n"
+    "MIICXjCCAcegAwIBAgIIWjO48ufpunYwDQYJKoZIhvcNAQELBQAwNjEaMBgGA1UE\n"
+    "ChMRQm9yaW5nU1NMIFRFU1RJTkcxGDAWBgNVBAMTD0ludGVybWVkaWF0ZSBDQTAg\n"
+    "Fw0xNTAxMDEwMDAwMDBaGA8yMTAwMDEwMTAwMDAwMFowMjEaMBgGA1UEChMRQm9y\n"
+    "aW5nU1NMIFRFU1RJTkcxFDASBgNVBAMTC2V4YW1wbGUuY29tMIGfMA0GCSqGSIb3\n"
+    "DQEBAQUAA4GNADCBiQKBgQDD0U0ZYgqShJ7oOjsyNKyVXEHqeafmk/bAoPqY/h1c\n"
+    "oPw2E8KmeqiUSoTPjG5IXSblOxcqpbAXgnjPzo8DI3GNMhAf8SYNYsoH7gc7Uy7j\n"
+    "5x8bUrisGnuTHqkqH6d4/e7ETJ7i3CpR8bvK16DggEvQTudLipz8FBHtYhFakfdh\n"
+    "TwIDAQABo3cwdTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEG\n"
+    "CCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwGQYDVR0OBBIEEKN5pvbur7mlXjeMEYA0\n"
+    "4nUwGwYDVR0jBBQwEoAQjBpoqLV2211Xex+NFLIGozANBgkqhkiG9w0BAQsFAAOB\n"
+    "gQBj/p+JChp//LnXWC1k121LM/ii7hFzQzMrt70bny406SGz9jAjaPOX4S3gt38y\n"
+    "rhjpPukBlSzgQXFg66y6q5qp1nQTD1Cw6NkKBe9WuBlY3iYfmsf7WT8nhlT1CttU\n"
+    "xNCwyMX9mtdXdQicOfNjIGUCD5OLV5PgHFPRKiHHioBAhg==\n"
+    "-----END CERTIFICATE-----\n";
+
+static const char kLeafNoKeyUsagePEM[] =
+    "-----BEGIN CERTIFICATE-----\n"
+    "MIICNTCCAZ6gAwIBAgIJAIFQGaLQ0G2mMA0GCSqGSIb3DQEBCwUAMDYxGjAYBgNV\n"
+    "BAoTEUJvcmluZ1NTTCBURVNUSU5HMRgwFgYDVQQDEw9JbnRlcm1lZGlhdGUgQ0Ew\n"
+    "IBcNMTUwMTAxMDAwMDAwWhgPMjEwMDAxMDEwMDAwMDBaMDcxGjAYBgNVBAoTEUJv\n"
+    "cmluZ1NTTCBURVNUSU5HMRkwFwYDVQQDExBldmlsLmV4YW1wbGUuY29tMIGfMA0G\n"
+    "CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOKoZe75NPz77EOaMMl4/0s3PyQw++zJvp\n"
+    "ejHAxZiTPCJgMbEHLrSzNoHdopg+CLUH5bE4wTXM8w9Inv5P8OAFJt7gJuPUunmk\n"
+    "j+NoU3QfzOR6BroePcz1vXX9jyVHRs087M/sLqWRHu9IR+/A+UTcBaWaFiDVUxtJ\n"
+    "YOwFMwjNPQIDAQABo0gwRjAMBgNVHRMBAf8EAjAAMBkGA1UdDgQSBBBJfLEUWHq1\n"
+    "27rZ1AVx2J5GMBsGA1UdIwQUMBKAEIwaaKi1dttdV3sfjRSyBqMwDQYJKoZIhvcN\n"
+    "AQELBQADgYEALVKN2Y3LZJOtu6SxFIYKxbLaXhTGTdIjxipZhmbBRDFjbZjZZOTe\n"
+    "6Oo+VDNPYco4rBexK7umYXJyfTqoY0E8dbiImhTcGTEj7OAB3DbBomgU1AYe+t2D\n"
+    "uwBqh4Y3Eto+Zn4pMVsxGEfUpjzjZDel7bN1/oU/9KWPpDfywfUmjgk=\n"
+    "-----END CERTIFICATE-----\n";
+
+static const char kForgeryPEM[] =
+    "-----BEGIN CERTIFICATE-----\n"
+    "MIICZzCCAdCgAwIBAgIIdTlMzQoKkeMwDQYJKoZIhvcNAQELBQAwNzEaMBgGA1UE\n"
+    "ChMRQm9yaW5nU1NMIFRFU1RJTkcxGTAXBgNVBAMTEGV2aWwuZXhhbXBsZS5jb20w\n"
+    "IBcNMTUwMTAxMDAwMDAwWhgPMjEwMDAxMDEwMDAwMDBaMDoxGjAYBgNVBAoTEUJv\n"
+    "cmluZ1NTTCBURVNUSU5HMRwwGgYDVQQDExNmb3JnZXJ5LmV4YW1wbGUuY29tMIGf\n"
+    "MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDADTwruBQZGb7Ay6s9HiYv5d1lwtEy\n"
+    "xQdA2Sy8Rn8uA20Q4KgqwVY7wzIZ+z5Butrsmwb70gdG1XU+yRaDeE7XVoW6jSpm\n"
+    "0sw35/5vJbTcL4THEFbnX0OPZnvpuZDFUkvVtq5kxpDWsVyM24G8EEq7kPih3Sa3\n"
+    "OMhXVXF8kso6UQIDAQABo3cwdTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYI\n"
+    "KwYBBQUHAwEGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwGQYDVR0OBBIEEEYJ/WHM\n"
+    "8p64erPWIg4/liwwGwYDVR0jBBQwEoAQSXyxFFh6tdu62dQFcdieRjANBgkqhkiG\n"
+    "9w0BAQsFAAOBgQA+zH7bHPElWRWJvjxDqRexmYLn+D3Aivs8XgXQJsM94W0EzSUf\n"
+    "DSLfRgaQwcb2gg2xpDFoG+W0vc6O651uF23WGt5JaFFJJxqjII05IexfCNhuPmp4\n"
+    "4UZAXPttuJXpn74IY1tuouaM06B3vXKZR+/ityKmfJvSwxacmFcK+2ziAg==\n"
+    "-----END CERTIFICATE-----\n";
+
+// kExamplePSSCert is an example RSA-PSS self-signed certificate, signed with
+// the default hash functions.
+static const char kExamplePSSCert[] =
+    "-----BEGIN CERTIFICATE-----\n"
+    "MIICYjCCAcagAwIBAgIJAI3qUyT6SIfzMBIGCSqGSIb3DQEBCjAFogMCAWowRTEL\n"
+    "MAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVy\n"
+    "bmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0xNDEwMDkxOTA5NTVaFw0xNTEwMDkxOTA5\n"
+    "NTVaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQK\n"
+    "DBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwgZ8wDQYJKoZIhvcNAQEBBQADgY0A\n"
+    "MIGJAoGBAPi4bIO0vNmoV8CltFl2jFQdeesiUgR+0zfrQf2D+fCmhRU0dXFahKg8\n"
+    "0u9aTtPel4rd/7vPCqqGkr64UOTNb4AzMHYTj8p73OxaymPHAyXvqIqDWHYg+hZ3\n"
+    "13mSYwFIGth7Z/FSVUlO1m5KXNd6NzYM3t2PROjCpywrta9kS2EHAgMBAAGjUDBO\n"
+    "MB0GA1UdDgQWBBTQQfuJQR6nrVrsNF1JEflVgXgfEzAfBgNVHSMEGDAWgBTQQfuJ\n"
+    "QR6nrVrsNF1JEflVgXgfEzAMBgNVHRMEBTADAQH/MBIGCSqGSIb3DQEBCjAFogMC\n"
+    "AWoDgYEASUy2RZcgNbNQZA0/7F+V1YTLEXwD16bm+iSVnzGwtexmQVEYIZG74K/w\n"
+    "xbdZQdTbpNJkp1QPjPfh0zsatw6dmt5QoZ8K8No0DjR9dgf+Wvv5WJvJUIQBoAVN\n"
+    "Z0IL+OQFz6+LcTHxD27JJCebrATXZA0wThGTQDm7crL+a+SujBY=\n"
+    "-----END CERTIFICATE-----\n";
+
+// kBadPSSCertPEM is a self-signed RSA-PSS certificate with bad parameters.
+static const char kBadPSSCertPEM[] =
+    "-----BEGIN CERTIFICATE-----\n"
+    "MIIDdjCCAjqgAwIBAgIJANcwZLyfEv7DMD4GCSqGSIb3DQEBCjAxoA0wCwYJYIZI\n"
+    "AWUDBAIBoRowGAYJKoZIhvcNAQEIMAsGCWCGSAFlAwQCAaIEAgIA3jAnMSUwIwYD\n"
+    "VQQDDBxUZXN0IEludmFsaWQgUFNTIGNlcnRpZmljYXRlMB4XDTE1MTEwNDE2MDIz\n"
+    "NVoXDTE1MTIwNDE2MDIzNVowJzElMCMGA1UEAwwcVGVzdCBJbnZhbGlkIFBTUyBj\n"
+    "ZXJ0aWZpY2F0ZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMTaM7WH\n"
+    "qVCAGAIA+zL1KWvvASTrhlq+1ePdO7wsrWX2KiYoTYrJYTnxhLnn0wrHqApt79nL\n"
+    "IBG7cfShyZqFHOY/IzlYPMVt+gPo293gw96Fds5JBsjhjkyGnOyr9OUntFqvxDbT\n"
+    "IIFU7o9IdxD4edaqjRv+fegVE+B79pDk4s0ujsk6dULtCg9Rst0ucGFo19mr+b7k\n"
+    "dbfn8pZ72ZNDJPueVdrUAWw9oll61UcYfk75XdrLk6JlL41GrYHc8KlfXf43gGQq\n"
+    "QfrpHkg4Ih2cI6Wt2nhFGAzrlcorzLliQIUJRIhM8h4IgDfpBpaPdVQLqS2pFbXa\n"
+    "5eQjqiyJwak2vJ8CAwEAAaNQME4wHQYDVR0OBBYEFCt180N4oGUt5LbzBwQ4Ia+2\n"
+    "4V97MB8GA1UdIwQYMBaAFCt180N4oGUt5LbzBwQ4Ia+24V97MAwGA1UdEwQFMAMB\n"
+    "Af8wMQYJKoZIhvcNAQEKMCSgDTALBglghkgBZQMEAgGhDTALBgkqhkiG9w0BAQii\n"
+    "BAICAN4DggEBAAjBtm90lGxgddjc4Xu/nbXXFHVs2zVcHv/mqOZoQkGB9r/BVgLb\n"
+    "xhHrFZ2pHGElbUYPfifdS9ztB73e1d4J+P29o0yBqfd4/wGAc/JA8qgn6AAEO/Xn\n"
+    "plhFeTRJQtLZVl75CkHXgUGUd3h+ADvKtcBuW9dSUncaUrgNKR8u/h/2sMG38RWY\n"
+    "DzBddC/66YTa3r7KkVUfW7yqRQfELiGKdcm+bjlTEMsvS+EhHup9CzbpoCx2Fx9p\n"
+    "NPtFY3yEObQhmL1JyoCRWqBE75GzFPbRaiux5UpEkns+i3trkGssZzsOuVqHNTNZ\n"
+    "lC9+9hPHIoc9UMmAQNo1vGIW3NWVoeGbaJ8=\n"
+    "-----END CERTIFICATE-----\n";
+
+static const char kRSAKey[] =
+    "-----BEGIN RSA PRIVATE KEY-----\n"
+    "MIICXgIBAAKBgQDYK8imMuRi/03z0K1Zi0WnvfFHvwlYeyK9Na6XJYaUoIDAtB92\n"
+    "kWdGMdAQhLciHnAjkXLI6W15OoV3gA/ElRZ1xUpxTMhjP6PyY5wqT5r6y8FxbiiF\n"
+    "KKAnHmUcrgfVW28tQ+0rkLGMryRtrukXOgXBv7gcrmU7G1jC2a7WqmeI8QIDAQAB\n"
+    "AoGBAIBy09Fd4DOq/Ijp8HeKuCMKTHqTW1xGHshLQ6jwVV2vWZIn9aIgmDsvkjCe\n"
+    "i6ssZvnbjVcwzSoByhjN8ZCf/i15HECWDFFh6gt0P5z0MnChwzZmvatV/FXCT0j+\n"
+    "WmGNB/gkehKjGXLLcjTb6dRYVJSCZhVuOLLcbWIV10gggJQBAkEA8S8sGe4ezyyZ\n"
+    "m4e9r95g6s43kPqtj5rewTsUxt+2n4eVodD+ZUlCULWVNAFLkYRTBCASlSrm9Xhj\n"
+    "QpmWAHJUkQJBAOVzQdFUaewLtdOJoPCtpYoY1zd22eae8TQEmpGOR11L6kbxLQsk\n"
+    "aMly/DOnOaa82tqAGTdqDEZgSNmCeKKknmECQAvpnY8GUOVAubGR6c+W90iBuQLj\n"
+    "LtFp/9ihd2w/PoDwrHZaoUYVcT4VSfJQog/k7kjE4MYXYWL8eEKg3WTWQNECQQDk\n"
+    "104Wi91Umd1PzF0ijd2jXOERJU1wEKe6XLkYYNHWQAe5l4J4MWj9OdxFXAxIuuR/\n"
+    "tfDwbqkta4xcux67//khAkEAvvRXLHTaa6VFzTaiiO8SaFsHV3lQyXOtMrBpB5jd\n"
+    "moZWgjHvB2W9Ckn7sDqsPB+U2tyX0joDdQEyuiMECDY8oQ==\n"
+    "-----END RSA PRIVATE KEY-----\n";
+
+// kCRLTestRoot is a test root certificate. It has private key:
+//
+//     -----BEGIN RSA PRIVATE KEY-----
+//     MIIEpAIBAAKCAQEAo16WiLWZuaymsD8n5SKPmxV1y6jjgr3BS/dUBpbrzd1aeFzN
+//     lI8l2jfAnzUyp+I21RQ+nh/MhqjGElkTtK9xMn1Y+S9GMRh+5R/Du0iCb1tCZIPY
+//     07Tgrb0KMNWe0v2QKVVruuYSgxIWodBfxlKO64Z8AJ5IbnWpuRqO6rctN9qUoMlT
+//     IAB6dL4G0tDJ/PGFWOJYwOMEIX54bly2wgyYJVBKiRRt4f7n8H922qmvPNA9idmX
+//     9G1VAtgV6x97XXi7ULORIQvn9lVQF6nTYDBJhyuPB+mLThbLP2o9orxGx7aCtnnB
+//     ZUIxUvHNOI0FaSaZH7Fi0xsZ/GkG2HZe7ImPJwIDAQABAoIBAQCJF9MTHfHGkk+/
+//     DwCXlA0Wg0e6hBuHl10iNobYkMWIl/xXjOknhYiqOqb181py76472SVC5ERprC+r
+//     Lf0PXzqKuA117mnkwT2bYLCL9Skf8WEhoFLQNbVlloF6wYjqXcYgKYKh8HgQbZl4
+//     aLg2YQl2NADTNABsUWj/4H2WEelsODVviqfFs725lFg9KHDI8zxAZXLzDt/M9uVL
+//     GxJiX12tr0AwaeAFZ1oPM/y+LznM3N3+Ht3jHHw3jZ/u8Z1RdAmdpu3bZ6tbwGBr
+//     9edsH5rKkm9aBvMrY7eX5VHqaqyRNFyG152ZOJh4XiiFG7EmgTPCpaHo50Y018Re
+//     grVtk+FBAoGBANY3lY+V8ZOwMxSHes+kTnoimHO5Ob7nxrOC71i27x+4HHsYUeAr
+//     /zOOghiDIn+oNkuiX5CIOWZKx159Bp65CPpCbTb/fh+HYnSgXFgCw7XptycO7LXM
+//     5GwR5jSfpfzBFdYxjxoUzDMFBwTEYRTm0HkUHkH+s+ajjw5wqqbcGLcfAoGBAMM8
+//     DKW6Tb66xsf708f0jonAjKYTLZ+WOcwsBEWSFHoY8dUjvW5gqx5acHTEsc5ZTeh4
+//     BCFLa+Mn9cuJWVJNs09k7Xb2PNl92HQ4GN2vbdkJhExbkT6oLDHg1hVD0w8KLfz1
+//     lTAW6pS+6CdOHMEJpvqx89EgU/1GgIQ1fXYczE75AoGAKeJoXdDFkUjsU+FBhAPu
+//     TDcjc80Nm2QaF9NMFR5/lsYa236f06MGnQAKM9zADBHJu/Qdl1brUjLg1HrBppsr
+//     RDNkw1IlSOjhuUf5hkPUHGd8Jijm440SRIcjabqla8wdBupdvo2+d2NOQgJbsQiI
+//     ToQ+fkzcxAXK3Nnuo/1436UCgYBjLH7UNOZHS8OsVM0I1r8NVKVdu4JCfeJQR8/H
+//     s2P5ffBir+wLRMnH+nMDreMQiibcPxMCArkERAlE4jlgaJ38Z62E76KLbLTmnJRt
+//     EC9Bv+bXjvAiHvWMRMUbOj/ddPNVez7Uld+FvdBaHwDWQlvzHzBWfBCOKSEhh7Z6
+//     qDhUqQKBgQDPMDx2i5rfmQp3imV9xUcCkIRsyYQVf8Eo7NV07IdUy/otmksgn4Zt
+//     Lbf3v2dvxOpTNTONWjp2c+iUQo8QxJCZr5Sfb21oQ9Ktcrmc/CY7LeBVDibXwxdM
+//     vRG8kBzvslFWh7REzC3u06GSVhyKDfW93kN2cKVwGoahRlhj7oHuZQ==
+//     -----END RSA PRIVATE KEY-----
+static const char kCRLTestRoot[] =
+    "-----BEGIN CERTIFICATE-----\n"
+    "MIIDbzCCAlegAwIBAgIJAODri7v0dDUFMA0GCSqGSIb3DQEBCwUAME4xCzAJBgNV\n"
+    "BAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1Nb3VudGFpbiBW\n"
+    "aWV3MRIwEAYDVQQKDAlCb3JpbmdTU0wwHhcNMTYwOTI2MTUwNjI2WhcNMjYwOTI0\n"
+    "MTUwNjI2WjBOMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQG\n"
+    "A1UEBwwNTW91bnRhaW4gVmlldzESMBAGA1UECgwJQm9yaW5nU1NMMIIBIjANBgkq\n"
+    "hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAo16WiLWZuaymsD8n5SKPmxV1y6jjgr3B\n"
+    "S/dUBpbrzd1aeFzNlI8l2jfAnzUyp+I21RQ+nh/MhqjGElkTtK9xMn1Y+S9GMRh+\n"
+    "5R/Du0iCb1tCZIPY07Tgrb0KMNWe0v2QKVVruuYSgxIWodBfxlKO64Z8AJ5IbnWp\n"
+    "uRqO6rctN9qUoMlTIAB6dL4G0tDJ/PGFWOJYwOMEIX54bly2wgyYJVBKiRRt4f7n\n"
+    "8H922qmvPNA9idmX9G1VAtgV6x97XXi7ULORIQvn9lVQF6nTYDBJhyuPB+mLThbL\n"
+    "P2o9orxGx7aCtnnBZUIxUvHNOI0FaSaZH7Fi0xsZ/GkG2HZe7ImPJwIDAQABo1Aw\n"
+    "TjAdBgNVHQ4EFgQUWPt3N5cZ/CRvubbrkqfBnAqhq94wHwYDVR0jBBgwFoAUWPt3\n"
+    "N5cZ/CRvubbrkqfBnAqhq94wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC\n"
+    "AQEAORu6M0MOwXy+3VEBwNilfTxyqDfruQsc1jA4PT8Oe8zora1WxE1JB4q2FJOz\n"
+    "EAuM3H/NXvEnBuN+ITvKZAJUfm4NKX97qmjMJwLKWe1gVv+VQTr63aR7mgWJReQN\n"
+    "XdMztlVeZs2dppV6uEg3ia1X0G7LARxGpA9ETbMyCpb39XxlYuTClcbA5ftDN99B\n"
+    "3Xg9KNdd++Ew22O3HWRDvdDpTO/JkzQfzi3sYwUtzMEonENhczJhGf7bQMmvL/w5\n"
+    "24Wxj4Z7KzzWIHsNqE/RIs6RV3fcW61j/mRgW2XyoWnMVeBzvcJr9NXp4VQYmFPw\n"
+    "amd8GKMZQvP0ufGnUn7D7uartA==\n"
+    "-----END CERTIFICATE-----\n";
+
+static const char kCRLTestLeaf[] =
+    "-----BEGIN CERTIFICATE-----\n"
+    "MIIDkDCCAnigAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwTjELMAkGA1UEBhMCVVMx\n"
+    "EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxEjAQ\n"
+    "BgNVBAoMCUJvcmluZ1NTTDAeFw0xNjA5MjYxNTA4MzFaFw0xNzA5MjYxNTA4MzFa\n"
+    "MEsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQKDAlC\n"
+    "b3JpbmdTU0wxEzARBgNVBAMMCmJvcmluZy5zc2wwggEiMA0GCSqGSIb3DQEBAQUA\n"
+    "A4IBDwAwggEKAoIBAQDc5v1S1M0W+QWM+raWfO0LH8uvqEwuJQgODqMaGnSlWUx9\n"
+    "8iQcnWfjyPja3lWg9K62hSOFDuSyEkysKHDxijz5R93CfLcfnVXjWQDJe7EJTTDP\n"
+    "ozEvxN6RjAeYv7CF000euYr3QT5iyBjg76+bon1p0jHZBJeNPP1KqGYgyxp+hzpx\n"
+    "e0gZmTlGAXd8JQK4v8kpdYwD6PPifFL/jpmQpqOtQmH/6zcLjY4ojmqpEdBqIKIX\n"
+    "+saA29hMq0+NK3K+wgg31RU+cVWxu3tLOIiesETkeDgArjWRS1Vkzbi4v9SJxtNu\n"
+    "OZuAxWiynRJw3JwH/OFHYZIvQqz68ZBoj96cepjPAgMBAAGjezB5MAkGA1UdEwQC\n"
+    "MAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRl\n"
+    "MB0GA1UdDgQWBBTGn0OVVh/aoYt0bvEKG+PIERqnDzAfBgNVHSMEGDAWgBRY+3c3\n"
+    "lxn8JG+5tuuSp8GcCqGr3jANBgkqhkiG9w0BAQsFAAOCAQEAd2nM8gCQN2Dc8QJw\n"
+    "XSZXyuI3DBGGCHcay/3iXu0JvTC3EiQo8J6Djv7WLI0N5KH8mkm40u89fJAB2lLZ\n"
+    "ShuHVtcC182bOKnePgwp9CNwQ21p0rDEu/P3X46ZvFgdxx82E9xLa0tBB8PiPDWh\n"
+    "lV16jbaKTgX5AZqjnsyjR5o9/mbZVupZJXx5Syq+XA8qiJfstSYJs4KyKK9UOjql\n"
+    "ICkJVKpi2ahDBqX4MOH4SLfzVk8pqSpviS6yaA1RXqjpkxiN45WWaXDldVHMSkhC\n"
+    "5CNXsXi4b1nAntu89crwSLA3rEwzCWeYj+BX7e1T9rr3oJdwOU/2KQtW1js1yQUG\n"
+    "tjJMFw==\n"
+    "-----END CERTIFICATE-----\n";
+
+static const char kBasicCRL[] =
+    "-----BEGIN X509 CRL-----\n"
+    "MIIBpzCBkAIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzETMBEGA1UE\n"
+    "CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzESMBAGA1UECgwJ\n"
+    "Qm9yaW5nU1NMFw0xNjA5MjYxNTEwNTVaFw0xNjEwMjYxNTEwNTVaoA4wDDAKBgNV\n"
+    "HRQEAwIBATANBgkqhkiG9w0BAQsFAAOCAQEAnrBKKgvd9x9zwK9rtUvVeFeJ7+LN\n"
+    "ZEAc+a5oxpPNEsJx6hXoApYEbzXMxuWBQoCs5iEBycSGudct21L+MVf27M38KrWo\n"
+    "eOkq0a2siqViQZO2Fb/SUFR0k9zb8xl86Zf65lgPplALun0bV/HT7MJcl04Tc4os\n"
+    "dsAReBs5nqTGNEd5AlC1iKHvQZkM//MD51DspKnDpsDiUVi54h9C1SpfZmX8H2Vv\n"
+    "diyu0fZ/bPAM3VAGawatf/SyWfBMyKpoPXEG39oAzmjjOj8en82psn7m474IGaho\n"
+    "/vBbhl1ms5qQiLYPjm4YELtnXQoFyC72tBjbdFd/ZE9k4CNKDbxFUXFbkw==\n"
+    "-----END X509 CRL-----\n";
+
+static const char kRevokedCRL[] =
+    "-----BEGIN X509 CRL-----\n"
+    "MIIBvjCBpwIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzETMBEGA1UE\n"
+    "CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzESMBAGA1UECgwJ\n"
+    "Qm9yaW5nU1NMFw0xNjA5MjYxNTEyNDRaFw0xNjEwMjYxNTEyNDRaMBUwEwICEAAX\n"
+    "DTE2MDkyNjE1MTIyNlqgDjAMMAoGA1UdFAQDAgECMA0GCSqGSIb3DQEBCwUAA4IB\n"
+    "AQCUGaM4DcWzlQKrcZvI8TMeR8BpsvQeo5BoI/XZu2a8h//PyRyMwYeaOM+3zl0d\n"
+    "sjgCT8b3C1FPgT+P2Lkowv7rJ+FHJRNQkogr+RuqCSPTq65ha4WKlRGWkMFybzVH\n"
+    "NloxC+aU3lgp/NlX9yUtfqYmJek1CDrOOGPrAEAwj1l/BUeYKNGqfBWYJQtPJu+5\n"
+    "OaSvIYGpETCZJscUWODmLEb/O3DM438vLvxonwGqXqS0KX37+CHpUlyhnSovxXxp\n"
+    "Pz4aF+L7OtczxL0GYtD2fR9B7TDMqsNmHXgQrixvvOY7MUdLGbd4RfJL3yA53hyO\n"
+    "xzfKY2TzxLiOmctG0hXFkH5J\n"
+    "-----END X509 CRL-----\n";
+
+static const char kBadIssuerCRL[] =
+    "-----BEGIN X509 CRL-----\n"
+    "MIIBwjCBqwIBATANBgkqhkiG9w0BAQsFADBSMQswCQYDVQQGEwJVUzETMBEGA1UE\n"
+    "CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEWMBQGA1UECgwN\n"
+    "Tm90IEJvcmluZ1NTTBcNMTYwOTI2MTUxMjQ0WhcNMTYxMDI2MTUxMjQ0WjAVMBMC\n"
+    "AhAAFw0xNjA5MjYxNTEyMjZaoA4wDDAKBgNVHRQEAwIBAjANBgkqhkiG9w0BAQsF\n"
+    "AAOCAQEAlBmjOA3Fs5UCq3GbyPEzHkfAabL0HqOQaCP12btmvIf/z8kcjMGHmjjP\n"
+    "t85dHbI4Ak/G9wtRT4E/j9i5KML+6yfhRyUTUJKIK/kbqgkj06uuYWuFipURlpDB\n"
+    "cm81RzZaMQvmlN5YKfzZV/clLX6mJiXpNQg6zjhj6wBAMI9ZfwVHmCjRqnwVmCUL\n"
+    "TybvuTmkryGBqREwmSbHFFjg5ixG/ztwzON/Ly78aJ8Bql6ktCl9+/gh6VJcoZ0q\n"
+    "L8V8aT8+Ghfi+zrXM8S9BmLQ9n0fQe0wzKrDZh14EK4sb7zmOzFHSxm3eEXyS98g\n"
+    "Od4cjsc3ymNk88S4jpnLRtIVxZB+SQ==\n"
+    "-----END X509 CRL-----\n";
+
+// kKnownCriticalCRL is kBasicCRL but with a critical issuing distribution point
+// extension.
+static const char kKnownCriticalCRL[] =
+    "-----BEGIN X509 CRL-----\n"
+    "MIIBujCBowIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzETMBEGA1UE\n"
+    "CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzESMBAGA1UECgwJ\n"
+    "Qm9yaW5nU1NMFw0xNjA5MjYxNTEwNTVaFw0xNjEwMjYxNTEwNTVaoCEwHzAKBgNV\n"
+    "HRQEAwIBATARBgNVHRwBAf8EBzAFoQMBAf8wDQYJKoZIhvcNAQELBQADggEBAA+3\n"
+    "i+5e5Ub8sccfgOBs6WVJFI9c8gvJjrJ8/dYfFIAuCyeocs7DFXn1n13CRZ+URR/Q\n"
+    "mVWgU28+xeusuSPYFpd9cyYTcVyNUGNTI3lwgcE/yVjPaOmzSZKdPakApRxtpKKQ\n"
+    "NN/56aQz3bnT/ZSHQNciRB8U6jiD9V30t0w+FDTpGaG+7bzzUH3UVF9xf9Ctp60A\n"
+    "3mfLe0scas7owSt4AEFuj2SPvcE7yvdOXbu+IEv21cEJUVExJAbhvIweHXh6yRW+\n"
+    "7VVeiNzdIjkZjyTmAzoXGha4+wbxXyBRbfH+XWcO/H+8nwyG8Gktdu2QB9S9nnIp\n"
+    "o/1TpfOMSGhMyMoyPrk=\n"
+    "-----END X509 CRL-----\n";
+
+// kUnknownCriticalCRL is kBasicCRL but with an unknown critical extension.
+static const char kUnknownCriticalCRL[] =
+    "-----BEGIN X509 CRL-----\n"
+    "MIIBvDCBpQIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzETMBEGA1UE\n"
+    "CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzESMBAGA1UECgwJ\n"
+    "Qm9yaW5nU1NMFw0xNjA5MjYxNTEwNTVaFw0xNjEwMjYxNTEwNTVaoCMwITAKBgNV\n"
+    "HRQEAwIBATATBgwqhkiG9xIEAYS3CQABAf8EADANBgkqhkiG9w0BAQsFAAOCAQEA\n"
+    "GvBP0xqL509InMj/3493YVRV+ldTpBv5uTD6jewzf5XdaxEQ/VjTNe5zKnxbpAib\n"
+    "Kf7cwX0PMSkZjx7k7kKdDlEucwVvDoqC+O9aJcqVmM6GDyNb9xENxd0XCXja6MZC\n"
+    "yVgP4AwLauB2vSiEprYJyI1APph3iAEeDm60lTXX/wBM/tupQDDujKh2GPyvBRfJ\n"
+    "+wEDwGg3ICwvu4gO4zeC5qnFR+bpL9t5tOMAQnVZ0NWv+k7mkd2LbHdD44dxrfXC\n"
+    "nhtfERx99SDmC/jtUAJrGhtCO8acr7exCeYcduN7KKCm91OeCJKK6OzWst0Og1DB\n"
+    "kwzzU2rL3G65CrZ7H0SZsQ==\n"
+    "-----END X509 CRL-----\n";
+
+// kUnknownCriticalCRL2 is kBasicCRL but with a critical issuing distribution
+// point extension followed by an unknown critical extension
+static const char kUnknownCriticalCRL2[] =
+    "-----BEGIN X509 CRL-----\n"
+    "MIIBzzCBuAIBATANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJVUzETMBEGA1UE\n"
+    "CAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzESMBAGA1UECgwJ\n"
+    "Qm9yaW5nU1NMFw0xNjA5MjYxNTEwNTVaFw0xNjEwMjYxNTEwNTVaoDYwNDAKBgNV\n"
+    "HRQEAwIBATARBgNVHRwBAf8EBzAFoQMBAf8wEwYMKoZIhvcSBAGEtwkAAQH/BAAw\n"
+    "DQYJKoZIhvcNAQELBQADggEBACTcpQC8jXL12JN5YzOcQ64ubQIe0XxRAd30p7qB\n"
+    "BTXGpgqBjrjxRfLms7EBYodEXB2oXMsDq3km0vT1MfYdsDD05S+SQ9CDsq/pUfaC\n"
+    "E2WNI5p8WircRnroYvbN2vkjlRbMd1+yNITohXYXCJwjEOAWOx3XIM10bwPYBv4R\n"
+    "rDobuLHoMgL3yHgMHmAkP7YpkBucNqeBV8cCdeAZLuhXFWi6yfr3r/X18yWbC/r2\n"
+    "2xXdkrSqXLFo7ToyP8YKTgiXpya4x6m53biEYwa2ULlas0igL6DK7wjYZX95Uy7H\n"
+    "GKljn9weIYiMPV/BzGymwfv2EW0preLwtyJNJPaxbdin6Jc=\n"
+    "-----END X509 CRL-----\n";
+
+// CertFromPEM parses the given, NUL-terminated pem block and returns an
+// |X509*|.
+static bssl::UniquePtr<X509> CertFromPEM(const char *pem) {
+  bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(pem, strlen(pem)));
+  return bssl::UniquePtr<X509>(
+      PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr));
+}
+
+// CRLFromPEM parses the given, NUL-terminated pem block and returns an
+// |X509_CRL*|.
+static bssl::UniquePtr<X509_CRL> CRLFromPEM(const char *pem) {
+  bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(pem, strlen(pem)));
+  return bssl::UniquePtr<X509_CRL>(
+      PEM_read_bio_X509_CRL(bio.get(), nullptr, nullptr, nullptr));
+}
+
+// PrivateKeyFromPEM parses the given, NUL-terminated pem block and returns an
+// |EVP_PKEY*|.
+static bssl::UniquePtr<EVP_PKEY> PrivateKeyFromPEM(const char *pem) {
+  bssl::UniquePtr<BIO> bio(
+      BIO_new_mem_buf(const_cast<char *>(pem), strlen(pem)));
+  return bssl::UniquePtr<EVP_PKEY>(
+      PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr, nullptr));
+}
+
+// CertsToStack converts a vector of |X509*| to an OpenSSL STACK_OF(X509),
+// bumping the reference counts for each certificate in question.
+static bssl::UniquePtr<STACK_OF(X509)> CertsToStack(
+    const std::vector<X509 *> &certs) {
+  bssl::UniquePtr<STACK_OF(X509)> stack(sk_X509_new_null());
+  if (!stack) {
+    return nullptr;
+  }
+  for (auto cert : certs) {
+    if (!sk_X509_push(stack.get(), cert)) {
+      return nullptr;
+    }
+    X509_up_ref(cert);
+  }
+
+  return stack;
+}
+
+// CRLsToStack converts a vector of |X509_CRL*| to an OpenSSL
+// STACK_OF(X509_CRL), bumping the reference counts for each CRL in question.
+static bssl::UniquePtr<STACK_OF(X509_CRL)> CRLsToStack(
+    const std::vector<X509_CRL *> &crls) {
+  bssl::UniquePtr<STACK_OF(X509_CRL)> stack(sk_X509_CRL_new_null());
+  if (!stack) {
+    return nullptr;
+  }
+  for (auto crl : crls) {
+    if (!sk_X509_CRL_push(stack.get(), crl)) {
+      return nullptr;
+    }
+    X509_CRL_up_ref(crl);
+  }
+
+  return stack;
+}
+
+static int Verify(X509 *leaf, const std::vector<X509 *> &roots,
+                   const std::vector<X509 *> &intermediates,
+                   const std::vector<X509_CRL *> &crls,
+                   unsigned long flags,
+                   bool use_additional_untrusted) {
+  bssl::UniquePtr<STACK_OF(X509)> roots_stack(CertsToStack(roots));
+  bssl::UniquePtr<STACK_OF(X509)> intermediates_stack(
+      CertsToStack(intermediates));
+  bssl::UniquePtr<STACK_OF(X509_CRL)> crls_stack(CRLsToStack(crls));
+
+  if (!roots_stack ||
+      !intermediates_stack ||
+      !crls_stack) {
+    return X509_V_ERR_UNSPECIFIED;
+  }
+
+  bssl::UniquePtr<X509_STORE_CTX> ctx(X509_STORE_CTX_new());
+  bssl::UniquePtr<X509_STORE> store(X509_STORE_new());
+  if (!ctx ||
+      !store) {
+    return X509_V_ERR_UNSPECIFIED;
+  }
+
+  if (use_additional_untrusted) {
+    X509_STORE_set0_additional_untrusted(store.get(),
+                                         intermediates_stack.get());
+  }
+
+  if (!X509_STORE_CTX_init(
+          ctx.get(), store.get(), leaf,
+          use_additional_untrusted ? nullptr : intermediates_stack.get())) {
+    return X509_V_ERR_UNSPECIFIED;
+  }
+
+  X509_STORE_CTX_trusted_stack(ctx.get(), roots_stack.get());
+  X509_STORE_CTX_set0_crls(ctx.get(), crls_stack.get());
+
+  X509_VERIFY_PARAM *param = X509_VERIFY_PARAM_new();
+  if (param == nullptr) {
+    return X509_V_ERR_UNSPECIFIED;
+  }
+  X509_VERIFY_PARAM_set_time(param, 1474934400 /* Sep 27th, 2016 */);
+  X509_VERIFY_PARAM_set_depth(param, 16);
+  if (flags) {
+    X509_VERIFY_PARAM_set_flags(param, flags);
+  }
+  X509_STORE_CTX_set0_param(ctx.get(), param);
+
+  ERR_clear_error();
+  if (X509_verify_cert(ctx.get()) != 1) {
+    return X509_STORE_CTX_get_error(ctx.get());
+  }
+
+  return X509_V_OK;
+}
+
+static int Verify(X509 *leaf, const std::vector<X509 *> &roots,
+                   const std::vector<X509 *> &intermediates,
+                   const std::vector<X509_CRL *> &crls,
+                   unsigned long flags = 0) {
+  const int r1 = Verify(leaf, roots, intermediates, crls, flags, false);
+  const int r2 = Verify(leaf, roots, intermediates, crls, flags, true);
+
+  if (r1 != r2) {
+    fprintf(stderr,
+            "Verify with, and without, use_additional_untrusted gave different "
+            "results: %d vs %d.\n",
+            r1, r2);
+    return false;
+  }
+
+  return r1;
+}
+
+static bool TestVerify() {
+  bssl::UniquePtr<X509> cross_signing_root(CertFromPEM(kCrossSigningRootPEM));
+  bssl::UniquePtr<X509> root(CertFromPEM(kRootCAPEM));
+  bssl::UniquePtr<X509> root_cross_signed(CertFromPEM(kRootCrossSignedPEM));
+  bssl::UniquePtr<X509> intermediate(CertFromPEM(kIntermediatePEM));
+  bssl::UniquePtr<X509> intermediate_self_signed(
+      CertFromPEM(kIntermediateSelfSignedPEM));
+  bssl::UniquePtr<X509> leaf(CertFromPEM(kLeafPEM));
+  bssl::UniquePtr<X509> leaf_no_key_usage(CertFromPEM(kLeafNoKeyUsagePEM));
+  bssl::UniquePtr<X509> forgery(CertFromPEM(kForgeryPEM));
+
+  if (!cross_signing_root ||
+      !root ||
+      !root_cross_signed ||
+      !intermediate ||
+      !intermediate_self_signed ||
+      !leaf ||
+      !leaf_no_key_usage ||
+      !forgery) {
+    fprintf(stderr, "Failed to parse certificates\n");
+    return false;
+  }
+
+  std::vector<X509*> empty;
+  std::vector<X509_CRL*> empty_crls;
+  if (Verify(leaf.get(), empty, empty, empty_crls) !=
+      X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) {
+    fprintf(stderr, "Leaf verified with no roots!\n");
+    return false;
+  }
+
+  if (Verify(leaf.get(), empty, {intermediate.get()}, empty_crls) !=
+      X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) {
+    fprintf(stderr, "Leaf verified with no roots!\n");
+    return false;
+  }
+
+  if (Verify(leaf.get(), {root.get()}, {intermediate.get()}, empty_crls) !=
+      X509_V_OK) {
+    ERR_print_errors_fp(stderr);
+    fprintf(stderr, "Basic chain didn't verify.\n");
+    return false;
+  }
+
+  if (Verify(leaf.get(), {cross_signing_root.get()},
+             {intermediate.get(), root_cross_signed.get()},
+             empty_crls) != X509_V_OK) {
+    ERR_print_errors_fp(stderr);
+    fprintf(stderr, "Cross-signed chain didn't verify.\n");
+    return false;
+  }
+
+  if (Verify(leaf.get(), {cross_signing_root.get(), root.get()},
+             {intermediate.get(), root_cross_signed.get()},
+             empty_crls) != X509_V_OK) {
+    ERR_print_errors_fp(stderr);
+    fprintf(stderr, "Cross-signed chain with root didn't verify.\n");
+    return false;
+  }
+
+  /* This is the “altchains” test – we remove the cross-signing CA but include
+   * the cross-sign in the intermediates. */
+  if (Verify(leaf.get(), {root.get()},
+             {intermediate.get(), root_cross_signed.get()},
+             empty_crls) != X509_V_OK) {
+    ERR_print_errors_fp(stderr);
+    fprintf(stderr, "Chain with cross-sign didn't backtrack to find root.\n");
+    return false;
+  }
+
+  if (Verify(leaf.get(), {root.get()},
+             {intermediate.get(), root_cross_signed.get()}, empty_crls,
+             X509_V_FLAG_NO_ALT_CHAINS) !=
+      X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) {
+    fprintf(stderr, "Altchains test still passed when disabled.\n");
+    return false;
+  }
+
+  if (Verify(forgery.get(), {intermediate_self_signed.get()},
+             {leaf_no_key_usage.get()},
+             empty_crls) != X509_V_ERR_INVALID_CA) {
+    fprintf(stderr, "Basic constraints weren't checked.\n");
+    return false;
+  }
+
+  /* Test that one cannot skip Basic Constraints checking with a contorted set
+   * of roots and intermediates. This is a regression test for CVE-2015-1793. */
+  if (Verify(forgery.get(),
+             {intermediate_self_signed.get(), root_cross_signed.get()},
+             {leaf_no_key_usage.get(), intermediate.get()},
+             empty_crls) != X509_V_ERR_INVALID_CA) {
+    fprintf(stderr, "Basic constraints weren't checked.\n");
+    return false;
+  }
+
+  return true;
+}
+
+static bool TestCRL() {
+  bssl::UniquePtr<X509> root(CertFromPEM(kCRLTestRoot));
+  bssl::UniquePtr<X509> leaf(CertFromPEM(kCRLTestLeaf));
+  bssl::UniquePtr<X509_CRL> basic_crl(CRLFromPEM(kBasicCRL));
+  bssl::UniquePtr<X509_CRL> revoked_crl(CRLFromPEM(kRevokedCRL));
+  bssl::UniquePtr<X509_CRL> bad_issuer_crl(CRLFromPEM(kBadIssuerCRL));
+  bssl::UniquePtr<X509_CRL> known_critical_crl(CRLFromPEM(kKnownCriticalCRL));
+  bssl::UniquePtr<X509_CRL> unknown_critical_crl(
+      CRLFromPEM(kUnknownCriticalCRL));
+  bssl::UniquePtr<X509_CRL> unknown_critical_crl2(
+      CRLFromPEM(kUnknownCriticalCRL2));
+
+  if (!root ||
+      !leaf ||
+      !basic_crl ||
+      !revoked_crl ||
+      !bad_issuer_crl ||
+      !known_critical_crl ||
+      !unknown_critical_crl ||
+      !unknown_critical_crl2) {
+    fprintf(stderr, "Failed to parse certificates and CRLs.\n");
+    return false;
+  }
+
+  if (Verify(leaf.get(), {root.get()}, {root.get()}, {basic_crl.get()},
+             X509_V_FLAG_CRL_CHECK) != X509_V_OK) {
+    fprintf(stderr, "Cert with CRL didn't verify.\n");
+    return false;
+  }
+
+  if (Verify(leaf.get(), {root.get()}, {root.get()},
+             {basic_crl.get(), revoked_crl.get()},
+             X509_V_FLAG_CRL_CHECK) != X509_V_ERR_CERT_REVOKED) {
+    fprintf(stderr, "Revoked CRL wasn't checked.\n");
+    return false;
+  }
+
+  std::vector<X509_CRL *> empty_crls;
+  if (Verify(leaf.get(), {root.get()}, {root.get()}, empty_crls,
+             X509_V_FLAG_CRL_CHECK) != X509_V_ERR_UNABLE_TO_GET_CRL) {
+    fprintf(stderr, "CRLs were not required.\n");
+    return false;
+  }
+
+  if (Verify(leaf.get(), {root.get()}, {root.get()}, {bad_issuer_crl.get()},
+             X509_V_FLAG_CRL_CHECK) != X509_V_ERR_UNABLE_TO_GET_CRL) {
+    fprintf(stderr, "Bad CRL issuer was unnoticed.\n");
+    return false;
+  }
+
+  if (Verify(leaf.get(), {root.get()}, {root.get()}, {known_critical_crl.get()},
+             X509_V_FLAG_CRL_CHECK) != X509_V_OK) {
+    fprintf(stderr, "CRL with known critical extension was rejected.\n");
+    return false;
+  }
+
+  if (Verify(leaf.get(), {root.get()}, {root.get()},
+             {unknown_critical_crl.get()}, X509_V_FLAG_CRL_CHECK) !=
+      X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION) {
+    fprintf(stderr, "CRL with unknown critical extension was accepted.\n");
+    return false;
+  }
+
+  if (Verify(leaf.get(), {root.get()}, {root.get()},
+             {unknown_critical_crl2.get()}, X509_V_FLAG_CRL_CHECK) !=
+      X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION) {
+    fprintf(stderr, "CRL with unknown critical extension (2) was accepted.\n");
+    return false;
+  }
+
+  return true;
+}
+
+static bool TestPSS() {
+  bssl::UniquePtr<X509> cert(CertFromPEM(kExamplePSSCert));
+  if (!cert) {
+    return false;
+  }
+
+  bssl::UniquePtr<EVP_PKEY> pkey(X509_get_pubkey(cert.get()));
+  if (!pkey) {
+    return false;
+  }
+
+  if (!X509_verify(cert.get(), pkey.get())) {
+    fprintf(stderr, "Could not verify certificate.\n");
+    return false;
+  }
+  return true;
+}
+
+static bool TestBadPSSParameters() {
+  bssl::UniquePtr<X509> cert(CertFromPEM(kBadPSSCertPEM));
+  if (!cert) {
+    return false;
+  }
+
+  bssl::UniquePtr<EVP_PKEY> pkey(X509_get_pubkey(cert.get()));
+  if (!pkey) {
+    return false;
+  }
+
+  if (X509_verify(cert.get(), pkey.get())) {
+    fprintf(stderr, "Unexpectedly verified bad certificate.\n");
+    return false;
+  }
+  ERR_clear_error();
+  return true;
+}
+
+static bool SignatureRoundTrips(EVP_MD_CTX *md_ctx, EVP_PKEY *pkey) {
+  // Make a certificate like signed with |md_ctx|'s settings.'
+  bssl::UniquePtr<X509> cert(CertFromPEM(kLeafPEM));
+  if (!cert || !X509_sign_ctx(cert.get(), md_ctx)) {
+    return false;
+  }
+
+  // Ensure that |pkey| may still be used to verify the resulting signature. All
+  // settings in |md_ctx| must have been serialized appropriately.
+  return !!X509_verify(cert.get(), pkey);
+}
+
+static bool TestSignCtx() {
+  bssl::UniquePtr<EVP_PKEY> pkey(PrivateKeyFromPEM(kRSAKey));
+  if (!pkey) {
+    return false;
+  }
+
+  // Test PKCS#1 v1.5.
+  bssl::ScopedEVP_MD_CTX md_ctx;
+  if (!EVP_DigestSignInit(md_ctx.get(), NULL, EVP_sha256(), NULL, pkey.get()) ||
+      !SignatureRoundTrips(md_ctx.get(), pkey.get())) {
+    fprintf(stderr, "RSA PKCS#1 with SHA-256 failed\n");
+    return false;
+  }
+
+  // Test RSA-PSS with custom parameters.
+  md_ctx.Reset();
+  EVP_PKEY_CTX *pkey_ctx;
+  if (!EVP_DigestSignInit(md_ctx.get(), &pkey_ctx, EVP_sha256(), NULL,
+                          pkey.get()) ||
+      !EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING) ||
+      !EVP_PKEY_CTX_set_rsa_mgf1_md(pkey_ctx, EVP_sha512()) ||
+      !SignatureRoundTrips(md_ctx.get(), pkey.get())) {
+    fprintf(stderr, "RSA-PSS failed\n");
+    return false;
+  }
+
+  return true;
+}
+
+static bool PEMToDER(bssl::UniquePtr<uint8_t> *out, size_t *out_len,
+                     const char *pem) {
+  bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(pem, strlen(pem)));
+  if (!bio) {
+    return false;
+  }
+
+  char *name, *header;
+  uint8_t *data;
+  long data_len;
+  if (!PEM_read_bio(bio.get(), &name, &header, &data, &data_len)) {
+    fprintf(stderr, "failed to read PEM data.\n");
+    return false;
+  }
+  OPENSSL_free(name);
+  OPENSSL_free(header);
+
+  out->reset(data);
+  *out_len = data_len;
+
+  return true;
+}
+
+static bool TestFromBuffer() {
+  size_t data_len;
+  bssl::UniquePtr<uint8_t> data;
+  if (!PEMToDER(&data, &data_len, kRootCAPEM)) {
+    return false;
+  }
+
+  bssl::UniquePtr<CRYPTO_BUFFER> buf(
+      CRYPTO_BUFFER_new(data.get(), data_len, nullptr));
+  if (!buf) {
+    return false;
+  }
+
+  bssl::UniquePtr<X509> root(X509_parse_from_buffer(buf.get()));
+  if (!root) {
+    return false;
+  }
+
+  const uint8_t *enc_pointer = root->cert_info->enc.enc;
+  const uint8_t *buf_pointer = CRYPTO_BUFFER_data(buf.get());
+  if (enc_pointer < buf_pointer ||
+      enc_pointer >= buf_pointer + CRYPTO_BUFFER_len(buf.get())) {
+    fprintf(stderr, "TestFromBuffer: enc does not alias the buffer.\n");
+    return false;
+  }
+
+  buf.reset();
+
+  /* This ensures the X509 took a reference to |buf|, otherwise this will be a
+   * reference to free memory and ASAN should notice. */
+  if (enc_pointer[0] != CBS_ASN1_SEQUENCE) {
+    fprintf(stderr, "TestFromBuffer: enc data is not a SEQUENCE.\n");
+    return false;
+  }
+
+  return true;
+}
+
+static bool TestFromBufferTrailingData() {
+  size_t data_len;
+  bssl::UniquePtr<uint8_t> data;
+  if (!PEMToDER(&data, &data_len, kRootCAPEM)) {
+    return false;
+  }
+
+  std::unique_ptr<uint8_t[]> trailing_data(new uint8_t[data_len + 1]);
+  OPENSSL_memcpy(trailing_data.get(), data.get(), data_len);
+
+  bssl::UniquePtr<CRYPTO_BUFFER> buf_trailing_data(
+      CRYPTO_BUFFER_new(trailing_data.get(), data_len + 1, nullptr));
+  if (!buf_trailing_data) {
+    return false;
+  }
+
+  bssl::UniquePtr<X509> root_trailing_data(
+      X509_parse_from_buffer(buf_trailing_data.get()));
+  if (root_trailing_data) {
+    fprintf(stderr, "TestFromBuffer: trailing data was not rejected.\n");
+    return false;
+  }
+
+  return true;
+}
+
+static bool TestFromBufferModified() {
+  size_t data_len;
+  bssl::UniquePtr<uint8_t> data;
+  if (!PEMToDER(&data, &data_len, kRootCAPEM)) {
+    return false;
+  }
+
+  bssl::UniquePtr<CRYPTO_BUFFER> buf(
+      CRYPTO_BUFFER_new(data.get(), data_len, nullptr));
+  if (!buf) {
+    return false;
+  }
+
+  bssl::UniquePtr<X509> root(X509_parse_from_buffer(buf.get()));
+  if (!root) {
+    return false;
+  }
+
+  bssl::UniquePtr<ASN1_INTEGER> fourty_two(ASN1_INTEGER_new());
+  ASN1_INTEGER_set(fourty_two.get(), 42);
+  X509_set_serialNumber(root.get(), fourty_two.get());
+
+  if (i2d_X509(root.get(), nullptr) != static_cast<long>(data_len)) {
+    fprintf(stderr,
+            "TestFromBufferModified: i2d_X509 gives different answer before "
+            "marking as modified.\n");
+    return false;
+  }
+
+  X509_CINF_set_modified(root->cert_info);
+
+  if (i2d_X509(root.get(), nullptr) == static_cast<long>(data_len)) {
+    fprintf(stderr,
+            "TestFromBufferModified: i2d_X509 gives same answer after marking "
+            "as modified.\n");
+    return false;
+  }
+
+  return true;
+}
+
+static bool TestFromBufferReused() {
+  size_t data_len;
+  bssl::UniquePtr<uint8_t> data;
+  if (!PEMToDER(&data, &data_len, kRootCAPEM)) {
+    return false;
+  }
+
+  bssl::UniquePtr<CRYPTO_BUFFER> buf(
+      CRYPTO_BUFFER_new(data.get(), data_len, nullptr));
+  if (!buf) {
+    return false;
+  }
+
+  bssl::UniquePtr<X509> root(X509_parse_from_buffer(buf.get()));
+  if (!root) {
+    return false;
+  }
+
+  size_t data2_len;
+  bssl::UniquePtr<uint8_t> data2;
+  if (!PEMToDER(&data2, &data2_len, kLeafPEM)) {
+    return false;
+  }
+
+  X509 *x509p = root.get();
+  const uint8_t *inp = data2.get();
+  X509 *ret = d2i_X509(&x509p, &inp, data2_len);
+  if (ret != root.get()) {
+    fprintf(stderr,
+            "TestFromBufferReused: d2i_X509 parsed into a different object.\n");
+    return false;
+  }
+
+  if (root->buf != nullptr) {
+    fprintf(stderr,
+            "TestFromBufferReused: d2i_X509 didn't clear |buf| pointer.\n");
+    return false;
+  }
+
+  // Free |data2| and ensure that |root| took its own copy. Otherwise the
+  // following will trigger a use-after-free.
+  data2.reset();
+
+  uint8_t *i2d = nullptr;
+  int i2d_len = i2d_X509(root.get(), &i2d);
+  if (i2d_len < 0) {
+    return false;
+  }
+  bssl::UniquePtr<uint8_t> i2d_storage(i2d);
+
+  if (!PEMToDER(&data2, &data2_len, kLeafPEM)) {
+    return false;
+  }
+  if (i2d_len != static_cast<long>(data2_len) ||
+      OPENSSL_memcmp(data2.get(), i2d, i2d_len) != 0) {
+    fprintf(stderr, "TestFromBufferReused: i2d gave wrong result.\n");
+    return false;
+  }
+
+  if (root->buf != NULL) {
+    fprintf(stderr, "TestFromBufferReused: X509.buf was not cleared.\n");
+    return false;
+  }
+
+  return true;
+}
+
+static bool TestFailedParseFromBuffer() {
+  static const uint8_t kNonsense[] = {1, 2, 3, 4, 5};
+
+  bssl::UniquePtr<CRYPTO_BUFFER> buf(
+      CRYPTO_BUFFER_new(kNonsense, sizeof(kNonsense), nullptr));
+  if (!buf) {
+    return false;
+  }
+
+  bssl::UniquePtr<X509> cert(X509_parse_from_buffer(buf.get()));
+  if (cert) {
+    fprintf(stderr, "Nonsense somehow parsed.\n");
+    return false;
+  }
+  ERR_clear_error();
+
+  // Test a buffer with trailing data.
+  size_t data_len;
+  bssl::UniquePtr<uint8_t> data;
+  if (!PEMToDER(&data, &data_len, kRootCAPEM)) {
+    return false;
+  }
+
+  std::unique_ptr<uint8_t[]> data_with_trailing_byte(new uint8_t[data_len + 1]);
+  OPENSSL_memcpy(data_with_trailing_byte.get(), data.get(), data_len);
+  data_with_trailing_byte[data_len] = 0;
+
+  bssl::UniquePtr<CRYPTO_BUFFER> buf_with_trailing_byte(
+      CRYPTO_BUFFER_new(data_with_trailing_byte.get(), data_len + 1, nullptr));
+  if (!buf_with_trailing_byte) {
+    return false;
+  }
+
+  bssl::UniquePtr<X509> root(
+      X509_parse_from_buffer(buf_with_trailing_byte.get()));
+  if (root) {
+    fprintf(stderr, "Parsed buffer with trailing byte.\n");
+    return false;
+  }
+  ERR_clear_error();
+
+  return true;
+}
+
+static bool TestPrintUTCTIME() {
+  static const struct {
+    const char *val, *want;
+  } asn1_utctime_tests[] = {
+    {"", "Bad time value"},
+
+    // Correct RFC 5280 form. Test years < 2000 and > 2000.
+    {"090303125425Z", "Mar  3 12:54:25 2009 GMT"},
+    {"900303125425Z", "Mar  3 12:54:25 1990 GMT"},
+    {"000303125425Z", "Mar  3 12:54:25 2000 GMT"},
+
+    // Correct form, bad values.
+    {"000000000000Z", "Bad time value"},
+    {"999999999999Z", "Bad time value"},
+
+    // Missing components. Not legal RFC 5280, but permitted.
+    {"090303125425", "Mar  3 12:54:25 2009"},
+    {"9003031254", "Mar  3 12:54:00 1990"},
+    {"9003031254Z", "Mar  3 12:54:00 1990 GMT"},
+
+    // GENERALIZEDTIME confused for UTCTIME.
+    {"20090303125425Z", "Bad time value"},
+
+    // Legal ASN.1, but not legal RFC 5280.
+    {"9003031254+0800", "Bad time value"},
+    {"9003031254-0800", "Bad time value"},
+
+    // Trailing garbage.
+    {"9003031254Z ", "Bad time value"},
+  };
+
+  for (auto t : asn1_utctime_tests) {
+    bssl::UniquePtr<ASN1_UTCTIME> tm(ASN1_UTCTIME_new());
+    bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_mem()));
+
+    // Use this instead of ASN1_UTCTIME_set() because some callers get
+    // type-confused and pass ASN1_GENERALIZEDTIME to ASN1_UTCTIME_print().
+    // ASN1_UTCTIME_set_string() is stricter, and would reject the inputs in
+    // question.
+    if (!ASN1_STRING_set(tm.get(), t.val, strlen(t.val))) {
+      fprintf(stderr, "ASN1_STRING_set\n");
+      return false;
+    }
+    const int ok = ASN1_UTCTIME_print(bio.get(), tm.get());
+
+    const uint8_t *contents;
+    size_t len;
+    if (!BIO_mem_contents(bio.get(), &contents, &len)) {
+      fprintf(stderr, "BIO_mem_contents\n");
+      return false;
+    }
+
+    if (ok != (strcmp(t.want, "Bad time value") != 0)) {
+      fprintf(stderr, "ASN1_UTCTIME_print(%s): bad return value\n", t.val);
+      return false;
+    }
+    if (len != strlen(t.want) || memcmp(contents, t.want, len)) {
+      fprintf(stderr, "ASN1_UTCTIME_print(%s): got %.*s, want %s\n", t.val,
+              static_cast<int>(len),
+              reinterpret_cast<const char *>(contents), t.want);
+      return false;
+    }
+  }
+
+  return true;
+}
+
+int main() {
+  CRYPTO_library_init();
+
+  if (!TestVerify() ||
+      !TestCRL() ||
+      !TestPSS() ||
+      !TestBadPSSParameters() ||
+      !TestSignCtx() ||
+      !TestFromBuffer() ||
+      !TestFromBufferTrailingData() ||
+      !TestFromBufferModified() ||
+      !TestFromBufferReused() ||
+      !TestFailedParseFromBuffer() ||
+      !TestPrintUTCTIME()) {
+    return 1;
+  }
+
+  printf("PASS\n");
+  return 0;
+}
diff --git a/src/crypto/x509/x509_trs.c b/src/crypto/x509/x509_trs.c
index 820e605..c7dfcad 100644
--- a/src/crypto/x509/x509_trs.c
+++ b/src/crypto/x509/x509_trs.c
@@ -1,5 +1,7 @@
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999. */
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
+ */
 /* ====================================================================
  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
  *
@@ -8,7 +10,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -58,9 +60,7 @@
 #include <openssl/obj.h>
 #include <openssl/x509v3.h>
 
-
-static int tr_cmp(const X509_TRUST **a,
-		const X509_TRUST **b);
+static int tr_cmp(const X509_TRUST **a, const X509_TRUST **b);
 static void trtable_free(X509_TRUST *p);
 
 static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags);
@@ -68,237 +68,259 @@
 static int trust_compat(X509_TRUST *trust, X509 *x, int flags);
 
 static int obj_trust(int id, X509 *x, int flags);
-static int (*default_trust)(int id, X509 *x, int flags) = obj_trust;
+static int (*default_trust) (int id, X509 *x, int flags) = obj_trust;
 
-/* WARNING: the following table should be kept in order of trust
- * and without any gaps so we can just subtract the minimum trust
- * value to get an index into the table
+/*
+ * WARNING: the following table should be kept in order of trust and without
+ * any gaps so we can just subtract the minimum trust value to get an index
+ * into the table
  */
 
 static X509_TRUST trstandard[] = {
-{X509_TRUST_COMPAT, 0, trust_compat, (char *) "compatible", 0, NULL},
-{X509_TRUST_SSL_CLIENT, 0, trust_1oidany, (char *) "SSL Client", NID_client_auth, NULL},
-{X509_TRUST_SSL_SERVER, 0, trust_1oidany, (char *) "SSL Server", NID_server_auth, NULL},
-{X509_TRUST_EMAIL, 0, trust_1oidany, (char *) "S/MIME email", NID_email_protect, NULL},
-{X509_TRUST_OBJECT_SIGN, 0, trust_1oidany, (char *) "Object Signer", NID_code_sign, NULL},
-{X509_TRUST_OCSP_SIGN, 0, trust_1oid, (char *) "OCSP responder", NID_OCSP_sign, NULL},
-{X509_TRUST_OCSP_REQUEST, 0, trust_1oid, (char *) "OCSP request", NID_ad_OCSP, NULL},
-{X509_TRUST_TSA, 0, trust_1oidany, (char *) "TSA server", NID_time_stamp, NULL}
+    {X509_TRUST_COMPAT, 0, trust_compat, (char *)"compatible", 0, NULL},
+    {X509_TRUST_SSL_CLIENT, 0, trust_1oidany, (char *)"SSL Client",
+     NID_client_auth, NULL},
+    {X509_TRUST_SSL_SERVER, 0, trust_1oidany, (char *)"SSL Server",
+     NID_server_auth, NULL},
+    {X509_TRUST_EMAIL, 0, trust_1oidany, (char *)"S/MIME email",
+     NID_email_protect, NULL},
+    {X509_TRUST_OBJECT_SIGN, 0, trust_1oidany, (char *)"Object Signer",
+     NID_code_sign, NULL},
+    {X509_TRUST_OCSP_SIGN, 0, trust_1oid, (char *)"OCSP responder",
+     NID_OCSP_sign, NULL},
+    {X509_TRUST_OCSP_REQUEST, 0, trust_1oid, (char *)"OCSP request",
+     NID_ad_OCSP, NULL},
+    {X509_TRUST_TSA, 0, trust_1oidany, (char *)"TSA server", NID_time_stamp,
+     NULL}
 };
 
-#define X509_TRUST_COUNT	(sizeof(trstandard)/sizeof(X509_TRUST))
+#define X509_TRUST_COUNT        (sizeof(trstandard)/sizeof(X509_TRUST))
 
 static STACK_OF(X509_TRUST) *trtable = NULL;
 
-static int tr_cmp(const X509_TRUST **a,
-		const X509_TRUST **b)
+static int tr_cmp(const X509_TRUST **a, const X509_TRUST **b)
 {
-	return (*a)->trust - (*b)->trust;
+    return (*a)->trust - (*b)->trust;
 }
 
-int (*X509_TRUST_set_default(int (*trust)(int , X509 *, int)))(int, X509 *, int)
-{
-	int (*oldtrust)(int , X509 *, int);
-	oldtrust = default_trust;
-	default_trust = trust;
-	return oldtrust;
+int (*X509_TRUST_set_default(int (*trust) (int, X509 *, int))) (int, X509 *,
+                                                                int) {
+    int (*oldtrust) (int, X509 *, int);
+    oldtrust = default_trust;
+    default_trust = trust;
+    return oldtrust;
 }
 
-
 int X509_check_trust(X509 *x, int id, int flags)
 {
-	X509_TRUST *pt;
-	int idx;
-	if(id == -1) return 1;
-	/* We get this as a default value */
-	if (id == 0)
-		{
-		int rv;
-		rv = obj_trust(NID_anyExtendedKeyUsage, x, 0);
-		if (rv != X509_TRUST_UNTRUSTED)
-			return rv;
-		return trust_compat(NULL, x, 0);
-		}
-	idx = X509_TRUST_get_by_id(id);
-	if(idx == -1) return default_trust(id, x, flags);
-	pt = X509_TRUST_get0(idx);
-	return pt->check_trust(pt, x, flags);
+    X509_TRUST *pt;
+    int idx;
+    if (id == -1)
+        return 1;
+    /* We get this as a default value */
+    if (id == 0) {
+        int rv;
+        rv = obj_trust(NID_anyExtendedKeyUsage, x, 0);
+        if (rv != X509_TRUST_UNTRUSTED)
+            return rv;
+        return trust_compat(NULL, x, 0);
+    }
+    idx = X509_TRUST_get_by_id(id);
+    if (idx == -1)
+        return default_trust(id, x, flags);
+    pt = X509_TRUST_get0(idx);
+    return pt->check_trust(pt, x, flags);
 }
 
 int X509_TRUST_get_count(void)
 {
-	if(!trtable) return X509_TRUST_COUNT;
-	return sk_X509_TRUST_num(trtable) + X509_TRUST_COUNT;
+    if (!trtable)
+        return X509_TRUST_COUNT;
+    return sk_X509_TRUST_num(trtable) + X509_TRUST_COUNT;
 }
 
-X509_TRUST * X509_TRUST_get0(int idx)
+X509_TRUST *X509_TRUST_get0(int idx)
 {
-	if(idx < 0) return NULL;
-	if(idx < (int)X509_TRUST_COUNT) return trstandard + idx;
-	return sk_X509_TRUST_value(trtable, idx - X509_TRUST_COUNT);
+    if (idx < 0)
+        return NULL;
+    if (idx < (int)X509_TRUST_COUNT)
+        return trstandard + idx;
+    return sk_X509_TRUST_value(trtable, idx - X509_TRUST_COUNT);
 }
 
 int X509_TRUST_get_by_id(int id)
 {
-	X509_TRUST tmp;
-	size_t idx;
+    X509_TRUST tmp;
+    size_t idx;
 
-	if((id >= X509_TRUST_MIN) && (id <= X509_TRUST_MAX))
-				 return id - X509_TRUST_MIN;
-	tmp.trust = id;
-	if(!trtable) return -1;
-	if (!sk_X509_TRUST_find(trtable, &idx, &tmp)) {
-		return -1;
-	}
-	return idx + X509_TRUST_COUNT;
+    if ((id >= X509_TRUST_MIN) && (id <= X509_TRUST_MAX))
+        return id - X509_TRUST_MIN;
+    tmp.trust = id;
+    if (!trtable)
+        return -1;
+    if (!sk_X509_TRUST_find(trtable, &idx, &tmp)) {
+        return -1;
+    }
+    return idx + X509_TRUST_COUNT;
 }
 
 int X509_TRUST_set(int *t, int trust)
 {
-	if(X509_TRUST_get_by_id(trust) == -1) {
-		OPENSSL_PUT_ERROR(X509, X509_R_INVALID_TRUST);
-		return 0;
-	}
-	*t = trust;
-	return 1;
+    if (X509_TRUST_get_by_id(trust) == -1) {
+        OPENSSL_PUT_ERROR(X509, X509_R_INVALID_TRUST);
+        return 0;
+    }
+    *t = trust;
+    return 1;
 }
 
-int X509_TRUST_add(int id, int flags, int (*ck)(X509_TRUST *, X509 *, int),
-					char *name, int arg1, void *arg2)
+int X509_TRUST_add(int id, int flags, int (*ck) (X509_TRUST *, X509 *, int),
+                   char *name, int arg1, void *arg2)
 {
-	int idx;
-	X509_TRUST *trtmp;
-	char *name_dup;
+    int idx;
+    X509_TRUST *trtmp;
+    char *name_dup;
 
-	/* This is set according to what we change: application can't set it */
-	flags &= ~X509_TRUST_DYNAMIC;
-	/* This will always be set for application modified trust entries */
-	flags |= X509_TRUST_DYNAMIC_NAME;
-	/* Get existing entry if any */
-	idx = X509_TRUST_get_by_id(id);
-	/* Need a new entry */
-	if(idx == -1) {
-		if(!(trtmp = OPENSSL_malloc(sizeof(X509_TRUST)))) {
-			OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-			return 0;
-		}
-		trtmp->flags = X509_TRUST_DYNAMIC;
-	} else trtmp = X509_TRUST_get0(idx);
+    /*
+     * This is set according to what we change: application can't set it
+     */
+    flags &= ~X509_TRUST_DYNAMIC;
+    /* This will always be set for application modified trust entries */
+    flags |= X509_TRUST_DYNAMIC_NAME;
+    /* Get existing entry if any */
+    idx = X509_TRUST_get_by_id(id);
+    /* Need a new entry */
+    if (idx == -1) {
+        if (!(trtmp = OPENSSL_malloc(sizeof(X509_TRUST)))) {
+            OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+            return 0;
+        }
+        trtmp->flags = X509_TRUST_DYNAMIC;
+    } else
+        trtmp = X509_TRUST_get0(idx);
 
-	/* Duplicate the supplied name. */
-	name_dup = BUF_strdup(name);
-	if (name_dup == NULL) {
-		OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-		if (idx == -1)
-			OPENSSL_free(trtmp);
-		return 0;
-	}
+    /* Duplicate the supplied name. */
+    name_dup = BUF_strdup(name);
+    if (name_dup == NULL) {
+        OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+        if (idx == -1)
+            OPENSSL_free(trtmp);
+        return 0;
+    }
 
-	/* OPENSSL_free existing name if dynamic */
-	if (trtmp->flags & X509_TRUST_DYNAMIC_NAME) OPENSSL_free(trtmp->name);
-	trtmp->name = name_dup;
-	/* Keep the dynamic flag of existing entry */
-	trtmp->flags &= X509_TRUST_DYNAMIC;
-	/* Set all other flags */
-	trtmp->flags |= flags;
+    /* OPENSSL_free existing name if dynamic */
+    if (trtmp->flags & X509_TRUST_DYNAMIC_NAME)
+        OPENSSL_free(trtmp->name);
+    trtmp->name = name_dup;
+    /* Keep the dynamic flag of existing entry */
+    trtmp->flags &= X509_TRUST_DYNAMIC;
+    /* Set all other flags */
+    trtmp->flags |= flags;
 
-	trtmp->trust = id;
-	trtmp->check_trust = ck;
-	trtmp->arg1 = arg1;
-	trtmp->arg2 = arg2;
+    trtmp->trust = id;
+    trtmp->check_trust = ck;
+    trtmp->arg1 = arg1;
+    trtmp->arg2 = arg2;
 
-	/* If its a new entry manage the dynamic table */
-	if(idx == -1) {
-		if(!trtable && !(trtable = sk_X509_TRUST_new(tr_cmp))) {
-			OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-			trtable_free(trtmp);
-			return 0;
-		}
-		if (!sk_X509_TRUST_push(trtable, trtmp)) {
-			OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-			trtable_free(trtmp);
-			return 0;
-		}
-	}
-	return 1;
+    /* If its a new entry manage the dynamic table */
+    if (idx == -1) {
+        if (!trtable && !(trtable = sk_X509_TRUST_new(tr_cmp))) {
+            OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+            trtable_free(trtmp);
+            return 0;
+        }
+        if (!sk_X509_TRUST_push(trtable, trtmp)) {
+            OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+            trtable_free(trtmp);
+            return 0;
+        }
+    }
+    return 1;
 }
 
 static void trtable_free(X509_TRUST *p)
-	{
-	if(!p) return;
-	if (p->flags & X509_TRUST_DYNAMIC) 
-		{
-		if (p->flags & X509_TRUST_DYNAMIC_NAME)
-			OPENSSL_free(p->name);
-		OPENSSL_free(p);
-		}
-	}
+{
+    if (!p)
+        return;
+    if (p->flags & X509_TRUST_DYNAMIC) {
+        if (p->flags & X509_TRUST_DYNAMIC_NAME)
+            OPENSSL_free(p->name);
+        OPENSSL_free(p);
+    }
+}
 
 void X509_TRUST_cleanup(void)
 {
-	unsigned int i;
-	for(i = 0; i < X509_TRUST_COUNT; i++) trtable_free(trstandard + i);
-	sk_X509_TRUST_pop_free(trtable, trtable_free);
-	trtable = NULL;
+    unsigned int i;
+    for (i = 0; i < X509_TRUST_COUNT; i++)
+        trtable_free(trstandard + i);
+    sk_X509_TRUST_pop_free(trtable, trtable_free);
+    trtable = NULL;
 }
 
 int X509_TRUST_get_flags(X509_TRUST *xp)
 {
-	return xp->flags;
+    return xp->flags;
 }
 
 char *X509_TRUST_get0_name(X509_TRUST *xp)
 {
-	return xp->name;
+    return xp->name;
 }
 
 int X509_TRUST_get_trust(X509_TRUST *xp)
 {
-	return xp->trust;
+    return xp->trust;
 }
 
 static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags)
 {
-	if(x->aux && (x->aux->trust || x->aux->reject))
-		return obj_trust(trust->arg1, x, flags);
-	/* we don't have any trust settings: for compatibility
-	 * we return trusted if it is self signed
-	 */
-	return trust_compat(trust, x, flags);
+    if (x->aux && (x->aux->trust || x->aux->reject))
+        return obj_trust(trust->arg1, x, flags);
+    /*
+     * we don't have any trust settings: for compatibility we return trusted
+     * if it is self signed
+     */
+    return trust_compat(trust, x, flags);
 }
 
 static int trust_1oid(X509_TRUST *trust, X509 *x, int flags)
 {
-	if(x->aux) return obj_trust(trust->arg1, x, flags);
-	return X509_TRUST_UNTRUSTED;
+    if (x->aux)
+        return obj_trust(trust->arg1, x, flags);
+    return X509_TRUST_UNTRUSTED;
 }
 
 static int trust_compat(X509_TRUST *trust, X509 *x, int flags)
 {
-	X509_check_purpose(x, -1, 0);
-	if(x->ex_flags & EXFLAG_SS) return X509_TRUST_TRUSTED;
-	else return X509_TRUST_UNTRUSTED;
+    X509_check_purpose(x, -1, 0);
+    if (x->ex_flags & EXFLAG_SS)
+        return X509_TRUST_TRUSTED;
+    else
+        return X509_TRUST_UNTRUSTED;
 }
 
 static int obj_trust(int id, X509 *x, int flags)
 {
-	ASN1_OBJECT *obj;
-	size_t i;
-	X509_CERT_AUX *ax;
-	ax = x->aux;
-	if(!ax) return X509_TRUST_UNTRUSTED;
-	if(ax->reject) {
-		for(i = 0; i < sk_ASN1_OBJECT_num(ax->reject); i++) {
-			obj = sk_ASN1_OBJECT_value(ax->reject, i);
-			if(OBJ_obj2nid(obj) == id) return X509_TRUST_REJECTED;
-		}
-	}	
-	if(ax->trust) {
-		for(i = 0; i < sk_ASN1_OBJECT_num(ax->trust); i++) {
-			obj = sk_ASN1_OBJECT_value(ax->trust, i);
-			if(OBJ_obj2nid(obj) == id) return X509_TRUST_TRUSTED;
-		}
-	}
-	return X509_TRUST_UNTRUSTED;
+    ASN1_OBJECT *obj;
+    size_t i;
+    X509_CERT_AUX *ax;
+    ax = x->aux;
+    if (!ax)
+        return X509_TRUST_UNTRUSTED;
+    if (ax->reject) {
+        for (i = 0; i < sk_ASN1_OBJECT_num(ax->reject); i++) {
+            obj = sk_ASN1_OBJECT_value(ax->reject, i);
+            if (OBJ_obj2nid(obj) == id)
+                return X509_TRUST_REJECTED;
+        }
+    }
+    if (ax->trust) {
+        for (i = 0; i < sk_ASN1_OBJECT_num(ax->trust); i++) {
+            obj = sk_ASN1_OBJECT_value(ax->trust, i);
+            if (OBJ_obj2nid(obj) == id)
+                return X509_TRUST_TRUSTED;
+        }
+    }
+    return X509_TRUST_UNTRUSTED;
 }
-
diff --git a/src/crypto/x509/x509_txt.c b/src/crypto/x509/x509_txt.c
index c286710..17e6cdb 100644
--- a/src/crypto/x509/x509_txt.c
+++ b/src/crypto/x509/x509_txt.c
@@ -63,147 +63,149 @@
 #include <openssl/obj.h>
 #include <openssl/x509.h>
 
-
 const char *X509_verify_cert_error_string(long n)
-	{
-	static char buf[100];
+{
+    static char buf[100];
 
-	switch ((int)n)
-		{
-	case X509_V_OK:
-		return("ok");
-	case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
-		return("unable to get issuer certificate");
-	case X509_V_ERR_UNABLE_TO_GET_CRL:
-		return("unable to get certificate CRL");
-	case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
-		return("unable to decrypt certificate's signature");
-	case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
-		return("unable to decrypt CRL's signature");
-	case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
-		return("unable to decode issuer public key");
-	case X509_V_ERR_CERT_SIGNATURE_FAILURE:
-		return("certificate signature failure");
-	case X509_V_ERR_CRL_SIGNATURE_FAILURE:
-		return("CRL signature failure");
-	case X509_V_ERR_CERT_NOT_YET_VALID:
-		return("certificate is not yet valid");
-	case X509_V_ERR_CRL_NOT_YET_VALID:
-		return("CRL is not yet valid");
-	case X509_V_ERR_CERT_HAS_EXPIRED:
-		return("certificate has expired");
-	case X509_V_ERR_CRL_HAS_EXPIRED:
-		return("CRL has expired");
-	case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
-		return("format error in certificate's notBefore field");
-	case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
-		return("format error in certificate's notAfter field");
-	case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
-		return("format error in CRL's lastUpdate field");
-	case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
-		return("format error in CRL's nextUpdate field");
-	case X509_V_ERR_OUT_OF_MEM:
-		return("out of memory");
-	case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
-		return("self signed certificate");
-	case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
-		return("self signed certificate in certificate chain");
-	case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
-		return("unable to get local issuer certificate");
-	case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
-		return("unable to verify the first certificate");
-	case X509_V_ERR_CERT_CHAIN_TOO_LONG:
-		return("certificate chain too long");
-	case X509_V_ERR_CERT_REVOKED:
-		return("certificate revoked");
-	case X509_V_ERR_INVALID_CA:
-		return ("invalid CA certificate");
-	case X509_V_ERR_INVALID_NON_CA:
-		return ("invalid non-CA certificate (has CA markings)");
-	case X509_V_ERR_PATH_LENGTH_EXCEEDED:
-		return ("path length constraint exceeded");
-	case X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED:
-		return("proxy path length constraint exceeded");
-	case X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED:
-		return("proxy certificates not allowed, please set the appropriate flag");
-	case X509_V_ERR_INVALID_PURPOSE:
-		return ("unsupported certificate purpose");
-	case X509_V_ERR_CERT_UNTRUSTED:
-		return ("certificate not trusted");
-	case X509_V_ERR_CERT_REJECTED:
-		return ("certificate rejected");
-	case X509_V_ERR_APPLICATION_VERIFICATION:
-		return("application verification failure");
-	case X509_V_ERR_SUBJECT_ISSUER_MISMATCH:
-		return("subject issuer mismatch");
-	case X509_V_ERR_AKID_SKID_MISMATCH:
-		return("authority and subject key identifier mismatch");
-	case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH:
-		return("authority and issuer serial number mismatch");
-	case X509_V_ERR_KEYUSAGE_NO_CERTSIGN:
-		return("key usage does not include certificate signing");
-	case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER:
-		return("unable to get CRL issuer certificate");
-	case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION:
-		return("unhandled critical extension");
-	case X509_V_ERR_KEYUSAGE_NO_CRL_SIGN:
-		return("key usage does not include CRL signing");
-	case X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE:
-		return("key usage does not include digital signature");
-	case X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION:
-		return("unhandled critical CRL extension");
-	case X509_V_ERR_INVALID_EXTENSION:
-		return("invalid or inconsistent certificate extension");
-	case X509_V_ERR_INVALID_POLICY_EXTENSION:
-		return("invalid or inconsistent certificate policy extension");
-	case X509_V_ERR_NO_EXPLICIT_POLICY:
-		return("no explicit policy");
-	case X509_V_ERR_DIFFERENT_CRL_SCOPE:
-	return("Different CRL scope");
-	case X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE:
-	return("Unsupported extension feature");
- 	case X509_V_ERR_UNNESTED_RESOURCE:
- 		return("RFC 3779 resource not subset of parent's resources");
+    switch ((int)n) {
+    case X509_V_OK:
+        return ("ok");
+    case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
+        return ("unable to get issuer certificate");
+    case X509_V_ERR_UNABLE_TO_GET_CRL:
+        return ("unable to get certificate CRL");
+    case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
+        return ("unable to decrypt certificate's signature");
+    case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
+        return ("unable to decrypt CRL's signature");
+    case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
+        return ("unable to decode issuer public key");
+    case X509_V_ERR_CERT_SIGNATURE_FAILURE:
+        return ("certificate signature failure");
+    case X509_V_ERR_CRL_SIGNATURE_FAILURE:
+        return ("CRL signature failure");
+    case X509_V_ERR_CERT_NOT_YET_VALID:
+        return ("certificate is not yet valid");
+    case X509_V_ERR_CRL_NOT_YET_VALID:
+        return ("CRL is not yet valid");
+    case X509_V_ERR_CERT_HAS_EXPIRED:
+        return ("certificate has expired");
+    case X509_V_ERR_CRL_HAS_EXPIRED:
+        return ("CRL has expired");
+    case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
+        return ("format error in certificate's notBefore field");
+    case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
+        return ("format error in certificate's notAfter field");
+    case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
+        return ("format error in CRL's lastUpdate field");
+    case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
+        return ("format error in CRL's nextUpdate field");
+    case X509_V_ERR_OUT_OF_MEM:
+        return ("out of memory");
+    case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
+        return ("self signed certificate");
+    case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
+        return ("self signed certificate in certificate chain");
+    case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
+        return ("unable to get local issuer certificate");
+    case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
+        return ("unable to verify the first certificate");
+    case X509_V_ERR_CERT_CHAIN_TOO_LONG:
+        return ("certificate chain too long");
+    case X509_V_ERR_CERT_REVOKED:
+        return ("certificate revoked");
+    case X509_V_ERR_INVALID_CA:
+        return ("invalid CA certificate");
+    case X509_V_ERR_INVALID_NON_CA:
+        return ("invalid non-CA certificate (has CA markings)");
+    case X509_V_ERR_PATH_LENGTH_EXCEEDED:
+        return ("path length constraint exceeded");
+    case X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED:
+        return ("proxy path length constraint exceeded");
+    case X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED:
+        return
+            ("proxy certificates not allowed, please set the appropriate flag");
+    case X509_V_ERR_INVALID_PURPOSE:
+        return ("unsupported certificate purpose");
+    case X509_V_ERR_CERT_UNTRUSTED:
+        return ("certificate not trusted");
+    case X509_V_ERR_CERT_REJECTED:
+        return ("certificate rejected");
+    case X509_V_ERR_APPLICATION_VERIFICATION:
+        return ("application verification failure");
+    case X509_V_ERR_SUBJECT_ISSUER_MISMATCH:
+        return ("subject issuer mismatch");
+    case X509_V_ERR_AKID_SKID_MISMATCH:
+        return ("authority and subject key identifier mismatch");
+    case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH:
+        return ("authority and issuer serial number mismatch");
+    case X509_V_ERR_KEYUSAGE_NO_CERTSIGN:
+        return ("key usage does not include certificate signing");
+    case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER:
+        return ("unable to get CRL issuer certificate");
+    case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION:
+        return ("unhandled critical extension");
+    case X509_V_ERR_KEYUSAGE_NO_CRL_SIGN:
+        return ("key usage does not include CRL signing");
+    case X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE:
+        return ("key usage does not include digital signature");
+    case X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION:
+        return ("unhandled critical CRL extension");
+    case X509_V_ERR_INVALID_EXTENSION:
+        return ("invalid or inconsistent certificate extension");
+    case X509_V_ERR_INVALID_POLICY_EXTENSION:
+        return ("invalid or inconsistent certificate policy extension");
+    case X509_V_ERR_NO_EXPLICIT_POLICY:
+        return ("no explicit policy");
+    case X509_V_ERR_DIFFERENT_CRL_SCOPE:
+        return ("Different CRL scope");
+    case X509_V_ERR_UNSUPPORTED_EXTENSION_FEATURE:
+        return ("Unsupported extension feature");
+    case X509_V_ERR_UNNESTED_RESOURCE:
+        return ("RFC 3779 resource not subset of parent's resources");
 
-	case X509_V_ERR_PERMITTED_VIOLATION:
-		return("permitted subtree violation");
-	case X509_V_ERR_EXCLUDED_VIOLATION:
-		return("excluded subtree violation");
-	case X509_V_ERR_SUBTREE_MINMAX:
-		return("name constraints minimum and maximum not supported");
-	case X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE:
-		return("unsupported name constraint type");
-	case X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX:
-		return("unsupported or invalid name constraint syntax");
-	case X509_V_ERR_UNSUPPORTED_NAME_SYNTAX:
-		return("unsupported or invalid name syntax");
-	case X509_V_ERR_CRL_PATH_VALIDATION_ERROR:
-		return("CRL path validation error");
+    case X509_V_ERR_PERMITTED_VIOLATION:
+        return ("permitted subtree violation");
+    case X509_V_ERR_EXCLUDED_VIOLATION:
+        return ("excluded subtree violation");
+    case X509_V_ERR_SUBTREE_MINMAX:
+        return ("name constraints minimum and maximum not supported");
+    case X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE:
+        return ("unsupported name constraint type");
+    case X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX:
+        return ("unsupported or invalid name constraint syntax");
+    case X509_V_ERR_UNSUPPORTED_NAME_SYNTAX:
+        return ("unsupported or invalid name syntax");
+    case X509_V_ERR_CRL_PATH_VALIDATION_ERROR:
+        return ("CRL path validation error");
 
-	case X509_V_ERR_SUITE_B_INVALID_VERSION:
-		return("Suite B: certificate version invalid");
-	case X509_V_ERR_SUITE_B_INVALID_ALGORITHM:
-		return("Suite B: invalid public key algorithm");
-	case X509_V_ERR_SUITE_B_INVALID_CURVE:
-		return("Suite B: invalid ECC curve");
-	case X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM:
-		return("Suite B: invalid signature algorithm");
-	case X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED:
-		return("Suite B: curve not allowed for this LOS");
-	case X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256:
-		return("Suite B: cannot sign P-384 with P-256");
+    case X509_V_ERR_SUITE_B_INVALID_VERSION:
+        return ("Suite B: certificate version invalid");
+    case X509_V_ERR_SUITE_B_INVALID_ALGORITHM:
+        return ("Suite B: invalid public key algorithm");
+    case X509_V_ERR_SUITE_B_INVALID_CURVE:
+        return ("Suite B: invalid ECC curve");
+    case X509_V_ERR_SUITE_B_INVALID_SIGNATURE_ALGORITHM:
+        return ("Suite B: invalid signature algorithm");
+    case X509_V_ERR_SUITE_B_LOS_NOT_ALLOWED:
+        return ("Suite B: curve not allowed for this LOS");
+    case X509_V_ERR_SUITE_B_CANNOT_SIGN_P_384_WITH_P_256:
+        return ("Suite B: cannot sign P-384 with P-256");
 
-	case X509_V_ERR_HOSTNAME_MISMATCH:
-		return("Hostname mismatch");
-	case X509_V_ERR_EMAIL_MISMATCH:
-		return("Email address mismatch");
-	case X509_V_ERR_IP_ADDRESS_MISMATCH:
-		return("IP address mismatch");
+    case X509_V_ERR_HOSTNAME_MISMATCH:
+        return ("Hostname mismatch");
+    case X509_V_ERR_EMAIL_MISMATCH:
+        return ("Email address mismatch");
+    case X509_V_ERR_IP_ADDRESS_MISMATCH:
+        return ("IP address mismatch");
 
-	default:
-		BIO_snprintf(buf,sizeof buf,"error number %ld",n);
-		return(buf);
-		}
-	}
+    case X509_V_ERR_INVALID_CALL:
+        return ("Invalid certificate verification context");
+    case X509_V_ERR_STORE_LOOKUP:
+        return ("Issuer certificate lookup error");
 
-
+    default:
+        BIO_snprintf(buf, sizeof buf, "error number %ld", n);
+        return (buf);
+    }
+}
diff --git a/src/crypto/x509/x509_v3.c b/src/crypto/x509/x509_v3.c
index b042985..ecbc0dd 100644
--- a/src/crypto/x509/x509_v3.c
+++ b/src/crypto/x509/x509_v3.c
@@ -62,210 +62,217 @@
 #include <openssl/x509.h>
 #include <openssl/x509v3.h>
 
-
 int X509v3_get_ext_count(const STACK_OF(X509_EXTENSION) *x)
-	{
-	if (x == NULL) return(0);
-	return(sk_X509_EXTENSION_num(x));
-	}
+{
+    if (x == NULL)
+        return (0);
+    return (sk_X509_EXTENSION_num(x));
+}
 
 int X509v3_get_ext_by_NID(const STACK_OF(X509_EXTENSION) *x, int nid,
-			  int lastpos)
-	{
-	const ASN1_OBJECT *obj;
+                          int lastpos)
+{
+    const ASN1_OBJECT *obj;
 
-	obj=OBJ_nid2obj(nid);
-	if (obj == NULL) return(-2);
-	return(X509v3_get_ext_by_OBJ(x,obj,lastpos));
-	}
+    obj = OBJ_nid2obj(nid);
+    if (obj == NULL)
+        return (-2);
+    return (X509v3_get_ext_by_OBJ(x, obj, lastpos));
+}
 
-int X509v3_get_ext_by_OBJ(const STACK_OF(X509_EXTENSION) *sk, const ASN1_OBJECT *obj,
-			  int lastpos)
-	{
-	int n;
-	X509_EXTENSION *ex;
+int X509v3_get_ext_by_OBJ(const STACK_OF(X509_EXTENSION) *sk,
+                          const ASN1_OBJECT *obj, int lastpos)
+{
+    int n;
+    X509_EXTENSION *ex;
 
-	if (sk == NULL) return(-1);
-	lastpos++;
-	if (lastpos < 0)
-		lastpos=0;
-	n=sk_X509_EXTENSION_num(sk);
-	for ( ; lastpos < n; lastpos++)
-		{
-		ex=sk_X509_EXTENSION_value(sk,lastpos);
-		if (OBJ_cmp(ex->object,obj) == 0)
-			return(lastpos);
-		}
-	return(-1);
-	}
+    if (sk == NULL)
+        return (-1);
+    lastpos++;
+    if (lastpos < 0)
+        lastpos = 0;
+    n = sk_X509_EXTENSION_num(sk);
+    for (; lastpos < n; lastpos++) {
+        ex = sk_X509_EXTENSION_value(sk, lastpos);
+        if (OBJ_cmp(ex->object, obj) == 0)
+            return (lastpos);
+    }
+    return (-1);
+}
 
 int X509v3_get_ext_by_critical(const STACK_OF(X509_EXTENSION) *sk, int crit,
-			       int lastpos)
-	{
-	int n;
-	X509_EXTENSION *ex;
+                               int lastpos)
+{
+    int n;
+    X509_EXTENSION *ex;
 
-	if (sk == NULL) return(-1);
-	lastpos++;
-	if (lastpos < 0)
-		lastpos=0;
-	n=sk_X509_EXTENSION_num(sk);
-	for ( ; lastpos < n; lastpos++)
-		{
-		ex=sk_X509_EXTENSION_value(sk,lastpos);
-		if (	((ex->critical > 0) && crit) ||
-			((ex->critical <= 0) && !crit))
-			return(lastpos);
-		}
-	return(-1);
-	}
+    if (sk == NULL)
+        return (-1);
+    lastpos++;
+    if (lastpos < 0)
+        lastpos = 0;
+    n = sk_X509_EXTENSION_num(sk);
+    for (; lastpos < n; lastpos++) {
+        ex = sk_X509_EXTENSION_value(sk, lastpos);
+        if (((ex->critical > 0) && crit) || ((ex->critical <= 0) && !crit))
+            return (lastpos);
+    }
+    return (-1);
+}
 
 X509_EXTENSION *X509v3_get_ext(const STACK_OF(X509_EXTENSION) *x, int loc)
-	{
-	if (x == NULL || loc < 0 || sk_X509_EXTENSION_num(x) <= (size_t) loc)
-		return NULL;
-	else
-		return sk_X509_EXTENSION_value(x,loc);
-	}
+{
+    if (x == NULL || loc < 0 || sk_X509_EXTENSION_num(x) <= (size_t)loc)
+        return NULL;
+    else
+        return sk_X509_EXTENSION_value(x, loc);
+}
 
 X509_EXTENSION *X509v3_delete_ext(STACK_OF(X509_EXTENSION) *x, int loc)
-	{
-	X509_EXTENSION *ret;
+{
+    X509_EXTENSION *ret;
 
-	if (x == NULL || loc < 0 || sk_X509_EXTENSION_num(x) <= (size_t) loc)
-		return(NULL);
-	ret=sk_X509_EXTENSION_delete(x,loc);
-	return(ret);
-	}
+    if (x == NULL || loc < 0 || sk_X509_EXTENSION_num(x) <= (size_t)loc)
+        return (NULL);
+    ret = sk_X509_EXTENSION_delete(x, loc);
+    return (ret);
+}
 
 STACK_OF(X509_EXTENSION) *X509v3_add_ext(STACK_OF(X509_EXTENSION) **x,
-					 X509_EXTENSION *ex, int loc)
-	{
-	X509_EXTENSION *new_ex=NULL;
-	int n;
-	STACK_OF(X509_EXTENSION) *sk=NULL;
+                                         X509_EXTENSION *ex, int loc)
+{
+    X509_EXTENSION *new_ex = NULL;
+    int n;
+    STACK_OF(X509_EXTENSION) *sk = NULL;
 
-	if (x == NULL)
-		{
-		OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER);
-		goto err2;
-		}
+    if (x == NULL) {
+        OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER);
+        goto err2;
+    }
 
-	if (*x == NULL)
-		{
-		if ((sk=sk_X509_EXTENSION_new_null()) == NULL)
-			goto err;
-		}
-	else
-		sk= *x;
+    if (*x == NULL) {
+        if ((sk = sk_X509_EXTENSION_new_null()) == NULL)
+            goto err;
+    } else
+        sk = *x;
 
-	n=sk_X509_EXTENSION_num(sk);
-	if (loc > n) loc=n;
-	else if (loc < 0) loc=n;
+    n = sk_X509_EXTENSION_num(sk);
+    if (loc > n)
+        loc = n;
+    else if (loc < 0)
+        loc = n;
 
-	if ((new_ex=X509_EXTENSION_dup(ex)) == NULL)
-		goto err2;
-	if (!sk_X509_EXTENSION_insert(sk,new_ex,loc))
-		goto err;
-	if (*x == NULL)
-		*x=sk;
-	return(sk);
-err:
-	OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-err2:
-	if (new_ex != NULL) X509_EXTENSION_free(new_ex);
-	if (sk != NULL) sk_X509_EXTENSION_free(sk);
-	return(NULL);
-	}
+    if ((new_ex = X509_EXTENSION_dup(ex)) == NULL)
+        goto err2;
+    if (!sk_X509_EXTENSION_insert(sk, new_ex, loc))
+        goto err;
+    if (*x == NULL)
+        *x = sk;
+    return (sk);
+ err:
+    OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+ err2:
+    if (new_ex != NULL)
+        X509_EXTENSION_free(new_ex);
+    if (sk != NULL)
+        sk_X509_EXTENSION_free(sk);
+    return (NULL);
+}
 
 X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex, int nid,
-	     int crit, ASN1_OCTET_STRING *data)
-	{
-	const ASN1_OBJECT *obj;
-	X509_EXTENSION *ret;
+                                             int crit,
+                                             ASN1_OCTET_STRING *data)
+{
+    const ASN1_OBJECT *obj;
+    X509_EXTENSION *ret;
 
-	obj=OBJ_nid2obj(nid);
-	if (obj == NULL)
-		{
-		OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_NID);
-		return(NULL);
-		}
-	ret=X509_EXTENSION_create_by_OBJ(ex,obj,crit,data);
-	return(ret);
-	}
+    obj = OBJ_nid2obj(nid);
+    if (obj == NULL) {
+        OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_NID);
+        return (NULL);
+    }
+    ret = X509_EXTENSION_create_by_OBJ(ex, obj, crit, data);
+    return (ret);
+}
 
 X509_EXTENSION *X509_EXTENSION_create_by_OBJ(X509_EXTENSION **ex,
-	     const ASN1_OBJECT *obj, int crit, ASN1_OCTET_STRING *data)
-	{
-	X509_EXTENSION *ret;
+                                             const ASN1_OBJECT *obj, int crit,
+                                             ASN1_OCTET_STRING *data)
+{
+    X509_EXTENSION *ret;
 
-	if ((ex == NULL) || (*ex == NULL))
-		{
-		if ((ret=X509_EXTENSION_new()) == NULL)
-			{
-			OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-			return(NULL);
-			}
-		}
-	else
-		ret= *ex;
+    if ((ex == NULL) || (*ex == NULL)) {
+        if ((ret = X509_EXTENSION_new()) == NULL) {
+            OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+            return (NULL);
+        }
+    } else
+        ret = *ex;
 
-	if (!X509_EXTENSION_set_object(ret,obj))
-		goto err;
-	if (!X509_EXTENSION_set_critical(ret,crit))
-		goto err;
-	if (!X509_EXTENSION_set_data(ret,data))
-		goto err;
-	
-	if ((ex != NULL) && (*ex == NULL)) *ex=ret;
-	return(ret);
-err:
-	if ((ex == NULL) || (ret != *ex))
-		X509_EXTENSION_free(ret);
-	return(NULL);
-	}
+    if (!X509_EXTENSION_set_object(ret, obj))
+        goto err;
+    if (!X509_EXTENSION_set_critical(ret, crit))
+        goto err;
+    if (!X509_EXTENSION_set_data(ret, data))
+        goto err;
+
+    if ((ex != NULL) && (*ex == NULL))
+        *ex = ret;
+    return (ret);
+ err:
+    if ((ex == NULL) || (ret != *ex))
+        X509_EXTENSION_free(ret);
+    return (NULL);
+}
 
 int X509_EXTENSION_set_object(X509_EXTENSION *ex, const ASN1_OBJECT *obj)
-	{
-	if ((ex == NULL) || (obj == NULL))
-		return(0);
-	ASN1_OBJECT_free(ex->object);
-	ex->object=OBJ_dup(obj);
-	return ex->object != NULL;
-	}
+{
+    if ((ex == NULL) || (obj == NULL))
+        return (0);
+    ASN1_OBJECT_free(ex->object);
+    ex->object = OBJ_dup(obj);
+    return ex->object != NULL;
+}
 
 int X509_EXTENSION_set_critical(X509_EXTENSION *ex, int crit)
-	{
-	if (ex == NULL) return(0);
-	ex->critical=(crit)?0xFF:-1;
-	return(1);
-	}
+{
+    if (ex == NULL)
+        return (0);
+    ex->critical = (crit) ? 0xFF : -1;
+    return (1);
+}
 
 int X509_EXTENSION_set_data(X509_EXTENSION *ex, ASN1_OCTET_STRING *data)
-	{
-	int i;
+{
+    int i;
 
-	if (ex == NULL) return(0);
-	i=M_ASN1_OCTET_STRING_set(ex->value,data->data,data->length);
-	if (!i) return(0);
-	return(1);
-	}
+    if (ex == NULL)
+        return (0);
+    i = M_ASN1_OCTET_STRING_set(ex->value, data->data, data->length);
+    if (!i)
+        return (0);
+    return (1);
+}
 
 ASN1_OBJECT *X509_EXTENSION_get_object(X509_EXTENSION *ex)
-	{
-	if (ex == NULL) return(NULL);
-	return(ex->object);
-	}
+{
+    if (ex == NULL)
+        return (NULL);
+    return (ex->object);
+}
 
 ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *ex)
-	{
-	if (ex == NULL) return(NULL);
-	return(ex->value);
-	}
+{
+    if (ex == NULL)
+        return (NULL);
+    return (ex->value);
+}
 
 int X509_EXTENSION_get_critical(X509_EXTENSION *ex)
-	{
-	if (ex == NULL) return(0);
-	if(ex->critical > 0) return 1;
-	return 0;
-	}
+{
+    if (ex == NULL)
+        return (0);
+    if (ex->critical > 0)
+        return 1;
+    return 0;
+}
diff --git a/src/crypto/x509/x509_vfy.c b/src/crypto/x509/x509_vfy.c
index c62a6f5..27b58f4 100644
--- a/src/crypto/x509/x509_vfy.c
+++ b/src/crypto/x509/x509_vfy.c
@@ -71,27 +71,26 @@
 #include "vpm_int.h"
 #include "../internal.h"
 
-
 static CRYPTO_EX_DATA_CLASS g_ex_data_class =
-	CRYPTO_EX_DATA_CLASS_INIT_WITH_APP_DATA;
+    CRYPTO_EX_DATA_CLASS_INIT_WITH_APP_DATA;
 
 /* CRL score values */
 
 /* No unhandled critical extensions */
 
-#define CRL_SCORE_NOCRITICAL	0x100
+#define CRL_SCORE_NOCRITICAL    0x100
 
 /* certificate is within CRL scope */
 
-#define CRL_SCORE_SCOPE		0x080
+#define CRL_SCORE_SCOPE         0x080
 
 /* CRL times valid */
 
-#define CRL_SCORE_TIME		0x040
+#define CRL_SCORE_TIME          0x040
 
 /* Issuer name matches certificate */
 
-#define CRL_SCORE_ISSUER_NAME	0x020
+#define CRL_SCORE_ISSUER_NAME   0x020
 
 /* If this score or above CRL is probably valid */
 
@@ -99,21 +98,21 @@
 
 /* CRL issuer is certificate issuer */
 
-#define CRL_SCORE_ISSUER_CERT	0x018
+#define CRL_SCORE_ISSUER_CERT   0x018
 
 /* CRL issuer is on certificate path */
 
-#define CRL_SCORE_SAME_PATH	0x008
+#define CRL_SCORE_SAME_PATH     0x008
 
 /* CRL issuer matches CRL AKID */
 
-#define CRL_SCORE_AKID		0x004
+#define CRL_SCORE_AKID          0x004
 
 /* Have a delta CRL with valid times */
 
-#define CRL_SCORE_TIME_DELTA	0x002
+#define CRL_SCORE_TIME_DELTA    0x002
 
-static int null_callback(int ok,X509_STORE_CTX *e);
+static int null_callback(int ok, X509_STORE_CTX *e);
 static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer);
 static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x);
 static int check_chain_extensions(X509_STORE_CTX *ctx);
@@ -125,2336 +124,2347 @@
 static int check_policy(X509_STORE_CTX *ctx);
 
 static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer,
-			unsigned int *preasons,
-			X509_CRL *crl, X509 *x);
+                         unsigned int *preasons, X509_CRL *crl, X509 *x);
 static int get_crl_delta(X509_STORE_CTX *ctx,
-				X509_CRL **pcrl, X509_CRL **pdcrl, X509 *x);
-static void get_delta_sk(X509_STORE_CTX *ctx, X509_CRL **dcrl, int *pcrl_score,
-			X509_CRL *base, STACK_OF(X509_CRL) *crls);
-static void crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl,
-				X509 **pissuer, int *pcrl_score);
+                         X509_CRL **pcrl, X509_CRL **pdcrl, X509 *x);
+static void get_delta_sk(X509_STORE_CTX *ctx, X509_CRL **dcrl,
+                         int *pcrl_score, X509_CRL *base,
+                         STACK_OF(X509_CRL) *crls);
+static void crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl, X509 **pissuer,
+                           int *pcrl_score);
 static int crl_crldp_check(X509 *x, X509_CRL *crl, int crl_score,
-				unsigned int *preasons);
+                           unsigned int *preasons);
 static int check_crl_path(X509_STORE_CTX *ctx, X509 *x);
 static int check_crl_chain(X509_STORE_CTX *ctx,
-			STACK_OF(X509) *cert_path,
-			STACK_OF(X509) *crl_path);
+                           STACK_OF(X509) *cert_path,
+                           STACK_OF(X509) *crl_path);
 
 static int internal_verify(X509_STORE_CTX *ctx);
 
-
 static int null_callback(int ok, X509_STORE_CTX *e)
-	{
-	return ok;
-	}
+{
+    return ok;
+}
 
 #if 0
 static int x509_subject_cmp(X509 **a, X509 **b)
-	{
-	return X509_subject_name_cmp(*a,*b);
-	}
+{
+    return X509_subject_name_cmp(*a, *b);
+}
 #endif
 /* Return 1 is a certificate is self signed */
 static int cert_self_signed(X509 *x)
-	{
-	X509_check_purpose(x, -1, 0);
-	if (x->ex_flags & EXFLAG_SS)
-		return 1;
-	else
-		return 0;
-	}
+{
+    X509_check_purpose(x, -1, 0);
+    if (x->ex_flags & EXFLAG_SS)
+        return 1;
+    else
+        return 0;
+}
 
 /* Given a certificate try and find an exact match in the store */
 
 static X509 *lookup_cert_match(X509_STORE_CTX *ctx, X509 *x)
-	{
-	STACK_OF(X509) *certs;
-	X509 *xtmp = NULL;
-	size_t i;
-	/* Lookup all certs with matching subject name */
-	certs = ctx->lookup_certs(ctx, X509_get_subject_name(x));
-	if (certs == NULL)
-		return NULL;
-	/* Look for exact match */
-	for (i = 0; i < sk_X509_num(certs); i++)
-		{
-		xtmp = sk_X509_value(certs, i);
-		if (!X509_cmp(xtmp, x))
-			break;
-		}
-	if (i < sk_X509_num(certs))
-		X509_up_ref(xtmp);
-	else
-		xtmp = NULL;
-	sk_X509_pop_free(certs, X509_free);
-	return xtmp;
-	}
+{
+    STACK_OF(X509) *certs;
+    X509 *xtmp = NULL;
+    size_t i;
+    /* Lookup all certs with matching subject name */
+    certs = ctx->lookup_certs(ctx, X509_get_subject_name(x));
+    if (certs == NULL)
+        return NULL;
+    /* Look for exact match */
+    for (i = 0; i < sk_X509_num(certs); i++) {
+        xtmp = sk_X509_value(certs, i);
+        if (!X509_cmp(xtmp, x))
+            break;
+    }
+    if (i < sk_X509_num(certs))
+        X509_up_ref(xtmp);
+    else
+        xtmp = NULL;
+    sk_X509_pop_free(certs, X509_free);
+    return xtmp;
+}
 
 int X509_verify_cert(X509_STORE_CTX *ctx)
-	{
-	X509 *x,*xtmp,*chain_ss=NULL;
-	int bad_chain = 0;
-	X509_VERIFY_PARAM *param = ctx->param;
-	int depth,i,ok=0;
-	int num;
-	int (*cb)(int xok,X509_STORE_CTX *xctx);
-	STACK_OF(X509) *sktmp=NULL;
-	if (ctx->cert == NULL)
-		{
-		OPENSSL_PUT_ERROR(X509, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY);
-		return -1;
-		}
-	if (ctx->chain != NULL)
-		{
-		/* This X509_STORE_CTX has already been used to verify a
-		 * cert. We cannot do another one. */
-		OPENSSL_PUT_ERROR(X509, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
-		return -1;
-		}
+{
+    X509 *x, *xtmp, *xtmp2, *chain_ss = NULL;
+    int bad_chain = 0;
+    X509_VERIFY_PARAM *param = ctx->param;
+    int depth, i, ok = 0;
+    int num, j, retry, trust;
+    int (*cb) (int xok, X509_STORE_CTX *xctx);
+    STACK_OF(X509) *sktmp = NULL;
+    if (ctx->cert == NULL) {
+        OPENSSL_PUT_ERROR(X509, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY);
+        ctx->error = X509_V_ERR_INVALID_CALL;
+        return -1;
+    }
+    if (ctx->chain != NULL) {
+        /*
+         * This X509_STORE_CTX has already been used to verify a cert. We
+         * cannot do another one.
+         */
+        OPENSSL_PUT_ERROR(X509, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
+        ctx->error = X509_V_ERR_INVALID_CALL;
+        return -1;
+    }
 
-	cb=ctx->verify_cb;
+    cb = ctx->verify_cb;
 
-	/* first we make sure the chain we are going to build is
-	 * present and that the first entry is in place */
-	ctx->chain = sk_X509_new_null();
-	if (ctx->chain == NULL || !sk_X509_push(ctx->chain, ctx->cert))
-		{
-		OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-		goto end;
-		}
-	X509_up_ref(ctx->cert);
-	ctx->last_untrusted = 1;
+    /*
+     * first we make sure the chain we are going to build is present and that
+     * the first entry is in place
+     */
+    ctx->chain = sk_X509_new_null();
+    if (ctx->chain == NULL || !sk_X509_push(ctx->chain, ctx->cert)) {
+        OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+        ctx->error = X509_V_ERR_OUT_OF_MEM;
+        goto end;
+    }
+    X509_up_ref(ctx->cert);
+    ctx->last_untrusted = 1;
 
-	/* We use a temporary STACK so we can chop and hack at it */
-	if (ctx->untrusted != NULL
-	    && (sktmp=sk_X509_dup(ctx->untrusted)) == NULL)
-		{
-		OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-		goto end;
-		}
+    /* We use a temporary STACK so we can chop and hack at it.
+     * sktmp = ctx->untrusted ++ ctx->ctx->additional_untrusted */
+    if (ctx->untrusted != NULL
+        && (sktmp = sk_X509_dup(ctx->untrusted)) == NULL) {
+        OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+        ctx->error = X509_V_ERR_OUT_OF_MEM;
+        goto end;
+    }
 
-	num=sk_X509_num(ctx->chain);
-	x=sk_X509_value(ctx->chain,num-1);
-	depth=param->depth;
+    if (ctx->ctx->additional_untrusted != NULL) {
+        if (sktmp == NULL) {
+            sktmp = sk_X509_new_null();
+            if (sktmp == NULL) {
+                OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+                ctx->error = X509_V_ERR_OUT_OF_MEM;
+                goto end;
+            }
+        }
 
+        for (size_t k = 0; k < sk_X509_num(ctx->ctx->additional_untrusted);
+             k++) {
+            if (!sk_X509_push(sktmp,
+                              sk_X509_value(ctx->ctx->additional_untrusted,
+                              k))) {
+                OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+                ctx->error = X509_V_ERR_OUT_OF_MEM;
+                goto end;
+            }
+        }
+    }
 
-	for (;;)
-		{
-		/* If we have enough, we break */
-		if (depth < num) break; /* FIXME: If this happens, we should take
-		                         * note of it and, if appropriate, use the
-		                         * X509_V_ERR_CERT_CHAIN_TOO_LONG error
-		                         * code later.
-		                         */
+    num = sk_X509_num(ctx->chain);
+    x = sk_X509_value(ctx->chain, num - 1);
+    depth = param->depth;
 
-		/* If we are self signed, we break */
-		if (cert_self_signed(x))
-			break;
-		/* If asked see if we can find issuer in trusted store first */
-		if (ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST)
-			{
-			ok = ctx->get_issuer(&xtmp, ctx, x);
-			if (ok < 0)
-				goto end;
-			/* If successful for now free up cert so it
-			 * will be picked up again later.
-			 */
-			if (ok > 0)
-				{
-				X509_free(xtmp);
-				break;
-				}
-			}
+    for (;;) {
+        /* If we have enough, we break */
+        if (depth < num)
+            break;              /* FIXME: If this happens, we should take
+                                 * note of it and, if appropriate, use the
+                                 * X509_V_ERR_CERT_CHAIN_TOO_LONG error code
+                                 * later. */
 
-		/* If we were passed a cert chain, use it first */
-		if (ctx->untrusted != NULL)
-			{
-			xtmp=find_issuer(ctx, sktmp,x);
-			if (xtmp != NULL)
-				{
-				if (!sk_X509_push(ctx->chain,xtmp))
-					{
-					OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-					goto end;
-					}
-				X509_up_ref(xtmp);
-				(void)sk_X509_delete_ptr(sktmp,xtmp);
-				ctx->last_untrusted++;
-				x=xtmp;
-				num++;
-				/* reparse the full chain for
-				 * the next one */
-				continue;
-				}
-			}
-		break;
-		}
+        /* If we are self signed, we break */
+        if (cert_self_signed(x))
+            break;
+        /*
+         * If asked see if we can find issuer in trusted store first
+         */
+        if (ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST) {
+            ok = ctx->get_issuer(&xtmp, ctx, x);
+            if (ok < 0) {
+                ctx->error = X509_V_ERR_STORE_LOOKUP;
+                goto end;
+            }
+            /*
+             * If successful for now free up cert so it will be picked up
+             * again later.
+             */
+            if (ok > 0) {
+                X509_free(xtmp);
+                break;
+            }
+        }
 
-	/* at this point, chain should contain a list of untrusted
-	 * certificates.  We now need to add at least one trusted one,
-	 * if possible, otherwise we complain. */
+        /* If we were passed a cert chain, use it first */
+        if (sktmp != NULL) {
+            xtmp = find_issuer(ctx, sktmp, x);
+            if (xtmp != NULL) {
+                if (!sk_X509_push(ctx->chain, xtmp)) {
+                    OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+                    ctx->error = X509_V_ERR_OUT_OF_MEM;
+                    ok = 0;
+                    goto end;
+                }
+                X509_up_ref(xtmp);
+                (void)sk_X509_delete_ptr(sktmp, xtmp);
+                ctx->last_untrusted++;
+                x = xtmp;
+                num++;
+                /*
+                 * reparse the full chain for the next one
+                 */
+                continue;
+            }
+        }
+        break;
+    }
 
-	/* Examine last certificate in chain and see if it
- 	 * is self signed.
- 	 */
+    /* Remember how many untrusted certs we have */
+    j = num;
+    /*
+     * at this point, chain should contain a list of untrusted certificates.
+     * We now need to add at least one trusted one, if possible, otherwise we
+     * complain.
+     */
 
-	i=sk_X509_num(ctx->chain);
-	x=sk_X509_value(ctx->chain,i-1);
-	if (cert_self_signed(x))
-		{
-		/* we have a self signed certificate */
-		if (sk_X509_num(ctx->chain) == 1)
-			{
-			/* We have a single self signed certificate: see if
-			 * we can find it in the store. We must have an exact
-			 * match to avoid possible impersonation.
-			 */
-			ok = ctx->get_issuer(&xtmp, ctx, x);
-			if ((ok <= 0) || X509_cmp(x, xtmp)) 
-				{
-				ctx->error=X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT;
-				ctx->current_cert=x;
-				ctx->error_depth=i-1;
-				if (ok == 1) X509_free(xtmp);
-				bad_chain = 1;
-				ok=cb(0,ctx);
-				if (!ok) goto end;
-				}
-			else 
-				{
-				/* We have a match: replace certificate with store version
-				 * so we get any trust settings.
-				 */
-				X509_free(x);
-				x = xtmp;
-				(void)sk_X509_set(ctx->chain, i - 1, x);
-				ctx->last_untrusted=0;
-				}
-			}
-		else
-			{
-			/* extract and save self signed certificate for later use */
-			chain_ss=sk_X509_pop(ctx->chain);
-			ctx->last_untrusted--;
-			num--;
-			x=sk_X509_value(ctx->chain,num-1);
-			}
-		}
+    do {
+        /*
+         * Examine last certificate in chain and see if it is self signed.
+         */
+        i = sk_X509_num(ctx->chain);
+        x = sk_X509_value(ctx->chain, i - 1);
+        if (cert_self_signed(x)) {
+            /* we have a self signed certificate */
+            if (sk_X509_num(ctx->chain) == 1) {
+                /*
+                 * We have a single self signed certificate: see if we can
+                 * find it in the store. We must have an exact match to avoid
+                 * possible impersonation.
+                 */
+                ok = ctx->get_issuer(&xtmp, ctx, x);
+                if ((ok <= 0) || X509_cmp(x, xtmp)) {
+                    ctx->error = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT;
+                    ctx->current_cert = x;
+                    ctx->error_depth = i - 1;
+                    if (ok == 1)
+                        X509_free(xtmp);
+                    bad_chain = 1;
+                    ok = cb(0, ctx);
+                    if (!ok)
+                        goto end;
+                } else {
+                    /*
+                     * We have a match: replace certificate with store
+                     * version so we get any trust settings.
+                     */
+                    X509_free(x);
+                    x = xtmp;
+                    (void)sk_X509_set(ctx->chain, i - 1, x);
+                    ctx->last_untrusted = 0;
+                }
+            } else {
+                /*
+                 * extract and save self signed certificate for later use
+                 */
+                chain_ss = sk_X509_pop(ctx->chain);
+                ctx->last_untrusted--;
+                num--;
+                j--;
+                x = sk_X509_value(ctx->chain, num - 1);
+            }
+        }
+        /* We now lookup certs from the certificate store */
+        for (;;) {
+            /* If we have enough, we break */
+            if (depth < num)
+                break;
+            /* If we are self signed, we break */
+            if (cert_self_signed(x))
+                break;
+            ok = ctx->get_issuer(&xtmp, ctx, x);
 
-	/* We now lookup certs from the certificate store */
-	for (;;)
-		{
-		/* If we have enough, we break */
-		if (depth < num) break;
+            if (ok < 0) {
+                ctx->error = X509_V_ERR_STORE_LOOKUP;
+                goto end;
+            }
+            if (ok == 0)
+                break;
+            x = xtmp;
+            if (!sk_X509_push(ctx->chain, x)) {
+                X509_free(xtmp);
+                OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+                ctx->error = X509_V_ERR_OUT_OF_MEM;
+                ok = 0;
+                goto end;
+            }
+            num++;
+        }
 
-		/* If we are self signed, we break */
-		if (cert_self_signed(x))
-			break;
+        /* we now have our chain, lets check it... */
+        trust = check_trust(ctx);
 
-		ok = ctx->get_issuer(&xtmp, ctx, x);
+        /* If explicitly rejected error */
+        if (trust == X509_TRUST_REJECTED) {
+            ok = 0;
+            goto end;
+        }
+        /*
+         * If it's not explicitly trusted then check if there is an alternative
+         * chain that could be used. We only do this if we haven't already
+         * checked via TRUSTED_FIRST and the user hasn't switched off alternate
+         * chain checking
+         */
+        retry = 0;
+        if (trust != X509_TRUST_TRUSTED
+            && !(ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST)
+            && !(ctx->param->flags & X509_V_FLAG_NO_ALT_CHAINS)) {
+            while (j-- > 1) {
+                xtmp2 = sk_X509_value(ctx->chain, j - 1);
+                ok = ctx->get_issuer(&xtmp, ctx, xtmp2);
+                if (ok < 0)
+                    goto end;
+                /* Check if we found an alternate chain */
+                if (ok > 0) {
+                    /*
+                     * Free up the found cert we'll add it again later
+                     */
+                    X509_free(xtmp);
 
-		if (ok < 0) goto end;
-		if (ok == 0) break;
+                    /*
+                     * Dump all the certs above this point - we've found an
+                     * alternate chain
+                     */
+                    while (num > j) {
+                        xtmp = sk_X509_pop(ctx->chain);
+                        X509_free(xtmp);
+                        num--;
+                    }
+                    ctx->last_untrusted = sk_X509_num(ctx->chain);
+                    retry = 1;
+                    break;
+                }
+            }
+        }
+    } while (retry);
 
-		x = xtmp;
-		if (!sk_X509_push(ctx->chain,x))
-			{
-			X509_free(xtmp);
-			OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-			ok = 0;
-			goto end;
-			}
-		num++;
-		}
+    /*
+     * If not explicitly trusted then indicate error unless it's a single
+     * self signed certificate in which case we've indicated an error already
+     * and set bad_chain == 1
+     */
+    if (trust != X509_TRUST_TRUSTED && !bad_chain) {
+        if ((chain_ss == NULL) || !ctx->check_issued(ctx, x, chain_ss)) {
+            if (ctx->last_untrusted >= num)
+                ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY;
+            else
+                ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT;
+            ctx->current_cert = x;
+        } else {
 
-	/* we now have our chain, lets check it... */
+            sk_X509_push(ctx->chain, chain_ss);
+            num++;
+            ctx->last_untrusted = num;
+            ctx->current_cert = chain_ss;
+            ctx->error = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN;
+            chain_ss = NULL;
+        }
 
-	i = check_trust(ctx);
+        ctx->error_depth = num - 1;
+        bad_chain = 1;
+        ok = cb(0, ctx);
+        if (!ok)
+            goto end;
+    }
 
-	/* If explicitly rejected error */
-	if (i == X509_TRUST_REJECTED)
-		goto end;
-	/* If not explicitly trusted then indicate error unless it's
-	 * a single self signed certificate in which case we've indicated
-	 * an error already and set bad_chain == 1
-	 */
-	if (i != X509_TRUST_TRUSTED && !bad_chain)
-		{
-		if ((chain_ss == NULL) || !ctx->check_issued(ctx, x, chain_ss))
-			{
-			if (ctx->last_untrusted >= num)
-				ctx->error=X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY;
-			else
-				ctx->error=X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT;
-			ctx->current_cert=x;
-			}
-		else
-			{
+    /* We have the chain complete: now we need to check its purpose */
+    ok = check_chain_extensions(ctx);
 
-			sk_X509_push(ctx->chain,chain_ss);
-			num++;
-			ctx->last_untrusted=num;
-			ctx->current_cert=chain_ss;
-			ctx->error=X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN;
-			chain_ss=NULL;
-			}
+    if (!ok)
+        goto end;
 
-		ctx->error_depth=num-1;
-		bad_chain = 1;
-		ok=cb(0,ctx);
-		if (!ok) goto end;
-		}
+    /* Check name constraints */
 
-	/* We have the chain complete: now we need to check its purpose */
-	ok = check_chain_extensions(ctx);
+    ok = check_name_constraints(ctx);
 
-	if (!ok) goto end;
+    if (!ok)
+        goto end;
 
-	/* Check name constraints */
+    ok = check_id(ctx);
 
-	ok = check_name_constraints(ctx);
-	
-	if (!ok) goto end;
+    if (!ok)
+        goto end;
 
-	ok = check_id(ctx);
+    /*
+     * Check revocation status: we do this after copying parameters because
+     * they may be needed for CRL signature verification.
+     */
 
-	if (!ok) goto end;
+    ok = ctx->check_revocation(ctx);
+    if (!ok)
+        goto end;
 
-	/* Check revocation status: we do this after copying parameters
-	 * because they may be needed for CRL signature verification.
-	 */
+    int err = X509_chain_check_suiteb(&ctx->error_depth, NULL, ctx->chain,
+                                      ctx->param->flags);
+    if (err != X509_V_OK) {
+        ctx->error = err;
+        ctx->current_cert = sk_X509_value(ctx->chain, ctx->error_depth);
+        ok = cb(0, ctx);
+        if (!ok)
+            goto end;
+    }
 
-	ok = ctx->check_revocation(ctx);
-	if(!ok) goto end;
+    /* At this point, we have a chain and need to verify it */
+    if (ctx->verify != NULL)
+        ok = ctx->verify(ctx);
+    else
+        ok = internal_verify(ctx);
+    if (!ok)
+        goto end;
 
-	i = X509_chain_check_suiteb(&ctx->error_depth, NULL, ctx->chain,
-							ctx->param->flags);
-	if (i != X509_V_OK)
-		{
-		ctx->error = i;
-		ctx->current_cert = sk_X509_value(ctx->chain, ctx->error_depth);
-		ok = cb(0, ctx);
-		if (!ok)
-			goto end;
-		}
+    /* If we get this far evaluate policies */
+    if (!bad_chain && (ctx->param->flags & X509_V_FLAG_POLICY_CHECK))
+        ok = ctx->check_policy(ctx);
 
-	/* At this point, we have a chain and need to verify it */
-	if (ctx->verify != NULL)
-		ok=ctx->verify(ctx);
-	else
-		ok=internal_verify(ctx);
-	if(!ok) goto end;
+ end:
+    if (sktmp != NULL)
+        sk_X509_free(sktmp);
+    if (chain_ss != NULL)
+        X509_free(chain_ss);
 
-	/* If we get this far evaluate policies */
-	if (!bad_chain && (ctx->param->flags & X509_V_FLAG_POLICY_CHECK))
-		ok = ctx->check_policy(ctx);
+    /* Safety net, error returns must set ctx->error */
+    if (ok <= 0 && ctx->error == X509_V_OK)
+        ctx->error = X509_V_ERR_UNSPECIFIED;
+    return ok;
+}
 
-end:
-	if (sktmp != NULL) sk_X509_free(sktmp);
-	if (chain_ss != NULL) X509_free(chain_ss);
-	return ok;
-	}
-
-
-/* Given a STACK_OF(X509) find the issuer of cert (if any)
+/*
+ * Given a STACK_OF(X509) find the issuer of cert (if any)
  */
 
 static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x)
 {
-	size_t i;
-	X509 *issuer;
-	for (i = 0; i < sk_X509_num(sk); i++)
-		{
-		issuer = sk_X509_value(sk, i);
-		if (ctx->check_issued(ctx, x, issuer))
-			return issuer;
-		}
-	return NULL;
+    size_t i;
+    X509 *issuer;
+    for (i = 0; i < sk_X509_num(sk); i++) {
+        issuer = sk_X509_value(sk, i);
+        if (ctx->check_issued(ctx, x, issuer))
+            return issuer;
+    }
+    return NULL;
 }
 
 /* Given a possible certificate and issuer check them */
 
 static int check_issued(X509_STORE_CTX *ctx, X509 *x, X509 *issuer)
 {
-	int ret;
-	ret = X509_check_issued(issuer, x);
-	if (ret == X509_V_OK)
-		return 1;
-	/* If we haven't asked for issuer errors don't set ctx */
-	if (!(ctx->param->flags & X509_V_FLAG_CB_ISSUER_CHECK))
-		return 0;
+    int ret;
+    ret = X509_check_issued(issuer, x);
+    if (ret == X509_V_OK)
+        return 1;
+    /* If we haven't asked for issuer errors don't set ctx */
+    if (!(ctx->param->flags & X509_V_FLAG_CB_ISSUER_CHECK))
+        return 0;
 
-	ctx->error = ret;
-	ctx->current_cert = x;
-	ctx->current_issuer = issuer;
-	return ctx->verify_cb(0, ctx);
+    ctx->error = ret;
+    ctx->current_cert = x;
+    ctx->current_issuer = issuer;
+    return ctx->verify_cb(0, ctx);
 }
 
 /* Alternative lookup method: look from a STACK stored in other_ctx */
 
 static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
 {
-	*issuer = find_issuer(ctx, ctx->other_ctx, x);
-	if (*issuer)
-		{
-		X509_up_ref(*issuer);
-		return 1;
-		}
-	else
-		return 0;
+    *issuer = find_issuer(ctx, ctx->other_ctx, x);
+    if (*issuer) {
+        X509_up_ref(*issuer);
+        return 1;
+    } else
+        return 0;
 }
-	
 
-/* Check a certificate chains extensions for consistency
- * with the supplied purpose
+/*
+ * Check a certificate chains extensions for consistency with the supplied
+ * purpose
  */
 
 static int check_chain_extensions(X509_STORE_CTX *ctx)
 {
-	int i, ok=0, must_be_ca, plen = 0;
-	X509 *x;
-	int (*cb)(int xok,X509_STORE_CTX *xctx);
-	int proxy_path_length = 0;
-	int purpose;
-	int allow_proxy_certs;
-	cb=ctx->verify_cb;
+    int i, ok = 0, must_be_ca, plen = 0;
+    X509 *x;
+    int (*cb) (int xok, X509_STORE_CTX *xctx);
+    int proxy_path_length = 0;
+    int purpose;
+    int allow_proxy_certs;
+    cb = ctx->verify_cb;
 
-	/* must_be_ca can have 1 of 3 values:
-	   -1: we accept both CA and non-CA certificates, to allow direct
-	       use of self-signed certificates (which are marked as CA).
-	   0:  we only accept non-CA certificates.  This is currently not
-	       used, but the possibility is present for future extensions.
-	   1:  we only accept CA certificates.  This is currently used for
-	       all certificates in the chain except the leaf certificate.
-	*/
-	must_be_ca = -1;
+    /*
+     * must_be_ca can have 1 of 3 values: -1: we accept both CA and non-CA
+     * certificates, to allow direct use of self-signed certificates (which
+     * are marked as CA). 0: we only accept non-CA certificates.  This is
+     * currently not used, but the possibility is present for future
+     * extensions. 1: we only accept CA certificates.  This is currently used
+     * for all certificates in the chain except the leaf certificate.
+     */
+    must_be_ca = -1;
 
-	/* CRL path validation */
-	if (ctx->parent)
-		{
-		allow_proxy_certs = 0;
-		purpose = X509_PURPOSE_CRL_SIGN;
-		}
-	else
-		{
-		allow_proxy_certs =
-			!!(ctx->param->flags & X509_V_FLAG_ALLOW_PROXY_CERTS);
-		/* A hack to keep people who don't want to modify their
-		   software happy */
-		if (getenv("OPENSSL_ALLOW_PROXY_CERTS"))
-			allow_proxy_certs = 1;
-		purpose = ctx->param->purpose;
-		}
+    /* CRL path validation */
+    if (ctx->parent) {
+        allow_proxy_certs = 0;
+        purpose = X509_PURPOSE_CRL_SIGN;
+    } else {
+        allow_proxy_certs =
+            ! !(ctx->param->flags & X509_V_FLAG_ALLOW_PROXY_CERTS);
+        purpose = ctx->param->purpose;
+    }
 
-	/* Check all untrusted certificates */
-	for (i = 0; i < ctx->last_untrusted; i++)
-		{
-		int ret;
-		x = sk_X509_value(ctx->chain, i);
-		if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL)
-			&& (x->ex_flags & EXFLAG_CRITICAL))
-			{
-			ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION;
-			ctx->error_depth = i;
-			ctx->current_cert = x;
-			ok=cb(0,ctx);
-			if (!ok) goto end;
-			}
-		if (!allow_proxy_certs && (x->ex_flags & EXFLAG_PROXY))
-			{
-			ctx->error = X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED;
-			ctx->error_depth = i;
-			ctx->current_cert = x;
-			ok=cb(0,ctx);
-			if (!ok) goto end;
-			}
-		ret = X509_check_ca(x);
-		switch(must_be_ca)
-			{
-		case -1:
-			if ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
-				&& (ret != 1) && (ret != 0))
-				{
-				ret = 0;
-				ctx->error = X509_V_ERR_INVALID_CA;
-				}
-			else
-				ret = 1;
-			break;
-		case 0:
-			if (ret != 0)
-				{
-				ret = 0;
-				ctx->error = X509_V_ERR_INVALID_NON_CA;
-				}
-			else
-				ret = 1;
-			break;
-		default:
-			if ((ret == 0)
-				|| ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
-					&& (ret != 1)))
-				{
-				ret = 0;
-				ctx->error = X509_V_ERR_INVALID_CA;
-				}
-			else
-				ret = 1;
-			break;
-			}
-		if (ret == 0)
-			{
-			ctx->error_depth = i;
-			ctx->current_cert = x;
-			ok=cb(0,ctx);
-			if (!ok) goto end;
-			}
-		if (ctx->param->purpose > 0)
-			{
-			ret = X509_check_purpose(x, purpose, must_be_ca > 0);
-			if ((ret == 0)
-				|| ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
-					&& (ret != 1)))
-				{
-				ctx->error = X509_V_ERR_INVALID_PURPOSE;
-				ctx->error_depth = i;
-				ctx->current_cert = x;
-				ok=cb(0,ctx);
-				if (!ok) goto end;
-				}
-			}
-		/* Check pathlen if not self issued */
-		if ((i > 1) && !(x->ex_flags & EXFLAG_SI)
-			   && (x->ex_pathlen != -1)
-			   && (plen > (x->ex_pathlen + proxy_path_length + 1)))
-			{
-			ctx->error = X509_V_ERR_PATH_LENGTH_EXCEEDED;
-			ctx->error_depth = i;
-			ctx->current_cert = x;
-			ok=cb(0,ctx);
-			if (!ok) goto end;
-			}
-		/* Increment path length if not self issued */
-		if (!(x->ex_flags & EXFLAG_SI))
-			plen++;
-		/* If this certificate is a proxy certificate, the next
-		   certificate must be another proxy certificate or a EE
-		   certificate.  If not, the next certificate must be a
-		   CA certificate.  */
-		if (x->ex_flags & EXFLAG_PROXY)
-			{
-			if (x->ex_pcpathlen != -1 && i > x->ex_pcpathlen)
-				{
-				ctx->error =
-					X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED;
-				ctx->error_depth = i;
-				ctx->current_cert = x;
-				ok=cb(0,ctx);
-				if (!ok) goto end;
-				}
-			proxy_path_length++;
-			must_be_ca = 0;
-			}
-		else
-			must_be_ca = 1;
-		}
-	ok = 1;
+    /* Check all untrusted certificates */
+    for (i = 0; i < ctx->last_untrusted; i++) {
+        int ret;
+        x = sk_X509_value(ctx->chain, i);
+        if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL)
+            && (x->ex_flags & EXFLAG_CRITICAL)) {
+            ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION;
+            ctx->error_depth = i;
+            ctx->current_cert = x;
+            ok = cb(0, ctx);
+            if (!ok)
+                goto end;
+        }
+        if (!allow_proxy_certs && (x->ex_flags & EXFLAG_PROXY)) {
+            ctx->error = X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED;
+            ctx->error_depth = i;
+            ctx->current_cert = x;
+            ok = cb(0, ctx);
+            if (!ok)
+                goto end;
+        }
+        ret = X509_check_ca(x);
+        switch (must_be_ca) {
+        case -1:
+            if ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
+                && (ret != 1) && (ret != 0)) {
+                ret = 0;
+                ctx->error = X509_V_ERR_INVALID_CA;
+            } else
+                ret = 1;
+            break;
+        case 0:
+            if (ret != 0) {
+                ret = 0;
+                ctx->error = X509_V_ERR_INVALID_NON_CA;
+            } else
+                ret = 1;
+            break;
+        default:
+            if ((ret == 0)
+                || ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
+                    && (ret != 1))) {
+                ret = 0;
+                ctx->error = X509_V_ERR_INVALID_CA;
+            } else
+                ret = 1;
+            break;
+        }
+        if (ret == 0) {
+            ctx->error_depth = i;
+            ctx->current_cert = x;
+            ok = cb(0, ctx);
+            if (!ok)
+                goto end;
+        }
+        if (ctx->param->purpose > 0) {
+            ret = X509_check_purpose(x, purpose, must_be_ca > 0);
+            if ((ret == 0)
+                || ((ctx->param->flags & X509_V_FLAG_X509_STRICT)
+                    && (ret != 1))) {
+                ctx->error = X509_V_ERR_INVALID_PURPOSE;
+                ctx->error_depth = i;
+                ctx->current_cert = x;
+                ok = cb(0, ctx);
+                if (!ok)
+                    goto end;
+            }
+        }
+        /* Check pathlen if not self issued */
+        if ((i > 1) && !(x->ex_flags & EXFLAG_SI)
+            && (x->ex_pathlen != -1)
+            && (plen > (x->ex_pathlen + proxy_path_length + 1))) {
+            ctx->error = X509_V_ERR_PATH_LENGTH_EXCEEDED;
+            ctx->error_depth = i;
+            ctx->current_cert = x;
+            ok = cb(0, ctx);
+            if (!ok)
+                goto end;
+        }
+        /* Increment path length if not self issued */
+        if (!(x->ex_flags & EXFLAG_SI))
+            plen++;
+        /*
+         * If this certificate is a proxy certificate, the next certificate
+         * must be another proxy certificate or a EE certificate.  If not,
+         * the next certificate must be a CA certificate.
+         */
+        if (x->ex_flags & EXFLAG_PROXY) {
+            if (x->ex_pcpathlen != -1 && i > x->ex_pcpathlen) {
+                ctx->error = X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED;
+                ctx->error_depth = i;
+                ctx->current_cert = x;
+                ok = cb(0, ctx);
+                if (!ok)
+                    goto end;
+            }
+            proxy_path_length++;
+            must_be_ca = 0;
+        } else
+            must_be_ca = 1;
+    }
+    ok = 1;
  end:
-	return ok;
+    return ok;
 }
 
 static int check_name_constraints(X509_STORE_CTX *ctx)
-	{
-	X509 *x;
-	int i, j, rv;
-	/* Check name constraints for all certificates */
-	for (i = sk_X509_num(ctx->chain) - 1; i >= 0; i--)
-		{
-		x = sk_X509_value(ctx->chain, i);
-		/* Ignore self issued certs unless last in chain */
-		if (i && (x->ex_flags & EXFLAG_SI))
-			continue;
-		/* Check against constraints for all certificates higher in
-		 * chain including trust anchor. Trust anchor not strictly
-		 * speaking needed but if it includes constraints it is to be
-		 * assumed it expects them to be obeyed.
-		 */
-		for (j = sk_X509_num(ctx->chain) - 1; j > i; j--)
-			{
-			NAME_CONSTRAINTS *nc = sk_X509_value(ctx->chain, j)->nc;
-			if (nc)
-				{
-				rv = NAME_CONSTRAINTS_check(x, nc);
-				if (rv != X509_V_OK)
-					{
-					ctx->error = rv;
-					ctx->error_depth = i;
-					ctx->current_cert = x;
-					if (!ctx->verify_cb(0,ctx))
-						return 0;
-					}
-				}
-			}
-		}
-	return 1;
-	}
+{
+    X509 *x;
+    int i, j, rv;
+    /* Check name constraints for all certificates */
+    for (i = sk_X509_num(ctx->chain) - 1; i >= 0; i--) {
+        x = sk_X509_value(ctx->chain, i);
+        /* Ignore self issued certs unless last in chain */
+        if (i && (x->ex_flags & EXFLAG_SI))
+            continue;
+        /*
+         * Check against constraints for all certificates higher in chain
+         * including trust anchor. Trust anchor not strictly speaking needed
+         * but if it includes constraints it is to be assumed it expects them
+         * to be obeyed.
+         */
+        for (j = sk_X509_num(ctx->chain) - 1; j > i; j--) {
+            NAME_CONSTRAINTS *nc = sk_X509_value(ctx->chain, j)->nc;
+            if (nc) {
+                rv = NAME_CONSTRAINTS_check(x, nc);
+                switch (rv) {
+                case X509_V_OK:
+                    continue;
+                case X509_V_ERR_OUT_OF_MEM:
+                    ctx->error = rv;
+                    return 0;
+                default:
+                    ctx->error = rv;
+                    ctx->error_depth = i;
+                    ctx->current_cert = x;
+                    if (!ctx->verify_cb(0, ctx))
+                        return 0;
+                    break;
+                }
+            }
+        }
+    }
+    return 1;
+}
 
 static int check_id_error(X509_STORE_CTX *ctx, int errcode)
-	{
-	ctx->error = errcode;
-	ctx->current_cert = ctx->cert;
-	ctx->error_depth = 0;
-	return ctx->verify_cb(0, ctx);
-	}
+{
+    ctx->error = errcode;
+    ctx->current_cert = ctx->cert;
+    ctx->error_depth = 0;
+    return ctx->verify_cb(0, ctx);
+}
 
 static int check_hosts(X509 *x, X509_VERIFY_PARAM_ID *id)
-	{
-	size_t i;
-	size_t n = sk_OPENSSL_STRING_num(id->hosts);
-	char *name;
+{
+    size_t i;
+    size_t n = sk_OPENSSL_STRING_num(id->hosts);
+    char *name;
 
-	for (i = 0; i < n; ++i)
-		{
-		name = sk_OPENSSL_STRING_value(id->hosts, i);
-		if (X509_check_host(x, name, strlen(name), id->hostflags,
-				    &id->peername) > 0)
-			return 1;
-		}
-	return n == 0;
-	}
+    if (id->peername != NULL) {
+        OPENSSL_free(id->peername);
+        id->peername = NULL;
+    }
+    for (i = 0; i < n; ++i) {
+        name = sk_OPENSSL_STRING_value(id->hosts, i);
+        if (X509_check_host(x, name, strlen(name), id->hostflags,
+                            &id->peername) > 0)
+            return 1;
+    }
+    return n == 0;
+}
 
 static int check_id(X509_STORE_CTX *ctx)
-	{
-	X509_VERIFY_PARAM *vpm = ctx->param;
-	X509_VERIFY_PARAM_ID *id = vpm->id;
-	X509 *x = ctx->cert;
-	if (id->hosts && check_hosts(x, id) <= 0)
-		{
-		if (!check_id_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH))
-			return 0;
-		}
-	if (id->email && X509_check_email(x, id->email, id->emaillen, 0) <= 0)
-		{
-		if (!check_id_error(ctx, X509_V_ERR_EMAIL_MISMATCH))
-			return 0;
-		}
-	if (id->ip && X509_check_ip(x, id->ip, id->iplen, 0) <= 0)
-		{
-		if (!check_id_error(ctx, X509_V_ERR_IP_ADDRESS_MISMATCH))
-			return 0;
-		}
-	return 1;
-	}
+{
+    X509_VERIFY_PARAM *vpm = ctx->param;
+    X509_VERIFY_PARAM_ID *id = vpm->id;
+    X509 *x = ctx->cert;
+    if (id->hosts && check_hosts(x, id) <= 0) {
+        if (!check_id_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH))
+            return 0;
+    }
+    if (id->email && X509_check_email(x, id->email, id->emaillen, 0) <= 0) {
+        if (!check_id_error(ctx, X509_V_ERR_EMAIL_MISMATCH))
+            return 0;
+    }
+    if (id->ip && X509_check_ip(x, id->ip, id->iplen, 0) <= 0) {
+        if (!check_id_error(ctx, X509_V_ERR_IP_ADDRESS_MISMATCH))
+            return 0;
+    }
+    return 1;
+}
 
 static int check_trust(X509_STORE_CTX *ctx)
 {
-	size_t i;
-	int ok;
-	X509 *x = NULL;
-	int (*cb)(int xok,X509_STORE_CTX *xctx);
-	cb=ctx->verify_cb;
-	/* Check all trusted certificates in chain */
-	for (i = ctx->last_untrusted; i < sk_X509_num(ctx->chain); i++)
-		{
-		x = sk_X509_value(ctx->chain, i);
-		ok = X509_check_trust(x, ctx->param->trust, 0);
-		/* If explicitly trusted return trusted */
-		if (ok == X509_TRUST_TRUSTED)
-			return X509_TRUST_TRUSTED;
-		/* If explicitly rejected notify callback and reject if
-		 * not overridden.
-		 */
-		if (ok == X509_TRUST_REJECTED)
-			{
-			ctx->error_depth = i;
-			ctx->current_cert = x;
-			ctx->error = X509_V_ERR_CERT_REJECTED;
-			ok = cb(0, ctx);
-			if (!ok)
-				return X509_TRUST_REJECTED;
-			}
-		}
-	/* If we accept partial chains and have at least one trusted
-	 * certificate return success.
-	 */
-	if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN)
-		{
-		X509 *mx;
-		if (ctx->last_untrusted < (int) sk_X509_num(ctx->chain))
-			return X509_TRUST_TRUSTED;
-		x = sk_X509_value(ctx->chain, 0);
-		mx = lookup_cert_match(ctx, x);
-		if (mx)
-			{
-			(void)sk_X509_set(ctx->chain, 0, mx);
-			X509_free(x);
-			ctx->last_untrusted = 0;
-			return X509_TRUST_TRUSTED;
-			}
-		}
+    size_t i;
+    int ok;
+    X509 *x = NULL;
+    int (*cb) (int xok, X509_STORE_CTX *xctx);
+    cb = ctx->verify_cb;
+    /* Check all trusted certificates in chain */
+    for (i = ctx->last_untrusted; i < sk_X509_num(ctx->chain); i++) {
+        x = sk_X509_value(ctx->chain, i);
+        ok = X509_check_trust(x, ctx->param->trust, 0);
+        /* If explicitly trusted return trusted */
+        if (ok == X509_TRUST_TRUSTED)
+            return X509_TRUST_TRUSTED;
+        /*
+         * If explicitly rejected notify callback and reject if not
+         * overridden.
+         */
+        if (ok == X509_TRUST_REJECTED) {
+            ctx->error_depth = i;
+            ctx->current_cert = x;
+            ctx->error = X509_V_ERR_CERT_REJECTED;
+            ok = cb(0, ctx);
+            if (!ok)
+                return X509_TRUST_REJECTED;
+        }
+    }
+    /*
+     * If we accept partial chains and have at least one trusted certificate
+     * return success.
+     */
+    if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) {
+        X509 *mx;
+        if (ctx->last_untrusted < (int)sk_X509_num(ctx->chain))
+            return X509_TRUST_TRUSTED;
+        x = sk_X509_value(ctx->chain, 0);
+        mx = lookup_cert_match(ctx, x);
+        if (mx) {
+            (void)sk_X509_set(ctx->chain, 0, mx);
+            X509_free(x);
+            ctx->last_untrusted = 0;
+            return X509_TRUST_TRUSTED;
+        }
+    }
 
-	/* If no trusted certs in chain at all return untrusted and
-	 * allow standard (no issuer cert) etc errors to be indicated.
-	 */
-	return X509_TRUST_UNTRUSTED;
+    /*
+     * If no trusted certs in chain at all return untrusted and allow
+     * standard (no issuer cert) etc errors to be indicated.
+     */
+    return X509_TRUST_UNTRUSTED;
 }
 
 static int check_revocation(X509_STORE_CTX *ctx)
-	{
-	int i, last, ok;
-	if (!(ctx->param->flags & X509_V_FLAG_CRL_CHECK))
-		return 1;
-	if (ctx->param->flags & X509_V_FLAG_CRL_CHECK_ALL)
-		last = sk_X509_num(ctx->chain) - 1;
-	else
-		{
-		/* If checking CRL paths this isn't the EE certificate */
-		if (ctx->parent)
-			return 1;
-		last = 0;
-		}
-	for(i = 0; i <= last; i++)
-		{
-		ctx->error_depth = i;
-		ok = check_cert(ctx);
-		if (!ok) return ok;
-		}
-	return 1;
-	}
+{
+    int i, last, ok;
+    if (!(ctx->param->flags & X509_V_FLAG_CRL_CHECK))
+        return 1;
+    if (ctx->param->flags & X509_V_FLAG_CRL_CHECK_ALL)
+        last = sk_X509_num(ctx->chain) - 1;
+    else {
+        /* If checking CRL paths this isn't the EE certificate */
+        if (ctx->parent)
+            return 1;
+        last = 0;
+    }
+    for (i = 0; i <= last; i++) {
+        ctx->error_depth = i;
+        ok = check_cert(ctx);
+        if (!ok)
+            return ok;
+    }
+    return 1;
+}
 
 static int check_cert(X509_STORE_CTX *ctx)
-                      OPENSSL_SUPPRESS_POTENTIALLY_UNINITIALIZED_WARNINGS
-	{
-	X509_CRL *crl = NULL, *dcrl = NULL;
-	X509 *x;
-	int ok, cnum;
-	unsigned int last_reasons;
-	cnum = ctx->error_depth;
-	x = sk_X509_value(ctx->chain, cnum);
-	ctx->current_cert = x;
-	ctx->current_issuer = NULL;
-	ctx->current_crl_score = 0;
-	ctx->current_reasons = 0;
-	while (ctx->current_reasons != CRLDP_ALL_REASONS)
-		{
-		last_reasons = ctx->current_reasons;
-		/* Try to retrieve relevant CRL */
-		if (ctx->get_crl)
-			ok = ctx->get_crl(ctx, &crl, x);
-		else
-			ok = get_crl_delta(ctx, &crl, &dcrl, x);
-		/* If error looking up CRL, nothing we can do except
-		 * notify callback
-		 */
-		if(!ok)
-			{
-			ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL;
-			ok = ctx->verify_cb(0, ctx);
-			goto err;
-			}
-		ctx->current_crl = crl;
-		ok = ctx->check_crl(ctx, crl);
-		if (!ok)
-			goto err;
+{
+    X509_CRL *crl = NULL, *dcrl = NULL;
+    X509 *x;
+    int ok = 0, cnum;
+    unsigned int last_reasons;
+    cnum = ctx->error_depth;
+    x = sk_X509_value(ctx->chain, cnum);
+    ctx->current_cert = x;
+    ctx->current_issuer = NULL;
+    ctx->current_crl_score = 0;
+    ctx->current_reasons = 0;
+    while (ctx->current_reasons != CRLDP_ALL_REASONS) {
+        last_reasons = ctx->current_reasons;
+        /* Try to retrieve relevant CRL */
+        if (ctx->get_crl)
+            ok = ctx->get_crl(ctx, &crl, x);
+        else
+            ok = get_crl_delta(ctx, &crl, &dcrl, x);
+        /*
+         * If error looking up CRL, nothing we can do except notify callback
+         */
+        if (!ok) {
+            ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL;
+            ok = ctx->verify_cb(0, ctx);
+            goto err;
+        }
+        ctx->current_crl = crl;
+        ok = ctx->check_crl(ctx, crl);
+        if (!ok)
+            goto err;
 
-		if (dcrl)
-			{
-			ok = ctx->check_crl(ctx, dcrl);
-			if (!ok)
-				goto err;
-			ok = ctx->cert_crl(ctx, dcrl, x);
-			if (!ok)
-				goto err;
-			}
-		else
-			ok = 1;
+        if (dcrl) {
+            ok = ctx->check_crl(ctx, dcrl);
+            if (!ok)
+                goto err;
+            ok = ctx->cert_crl(ctx, dcrl, x);
+            if (!ok)
+                goto err;
+        } else
+            ok = 1;
 
-		/* Don't look in full CRL if delta reason is removefromCRL */
-		if (ok != 2)
-			{
-			ok = ctx->cert_crl(ctx, crl, x);
-			if (!ok)
-				goto err;
-			}
+        /* Don't look in full CRL if delta reason is removefromCRL */
+        if (ok != 2) {
+            ok = ctx->cert_crl(ctx, crl, x);
+            if (!ok)
+                goto err;
+        }
 
-		X509_CRL_free(crl);
-		X509_CRL_free(dcrl);
-		crl = NULL;
-		dcrl = NULL;
-		/* If reasons not updated we wont get anywhere by
-		 * another iteration, so exit loop.
-		 */
-		if (last_reasons == ctx->current_reasons)
-			{
-			ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL;
-			ok = ctx->verify_cb(0, ctx);
-			goto err;
-			}
-		}
-	err:
-	X509_CRL_free(crl);
-	X509_CRL_free(dcrl);
+        X509_CRL_free(crl);
+        X509_CRL_free(dcrl);
+        crl = NULL;
+        dcrl = NULL;
+        /*
+         * If reasons not updated we wont get anywhere by another iteration,
+         * so exit loop.
+         */
+        if (last_reasons == ctx->current_reasons) {
+            ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL;
+            ok = ctx->verify_cb(0, ctx);
+            goto err;
+        }
+    }
+ err:
+    X509_CRL_free(crl);
+    X509_CRL_free(dcrl);
 
-	ctx->current_crl = NULL;
-	return ok;
+    ctx->current_crl = NULL;
+    return ok;
 
-	}
+}
 
 /* Check CRL times against values in X509_STORE_CTX */
 
 static int check_crl_time(X509_STORE_CTX *ctx, X509_CRL *crl, int notify)
-	{
-	time_t *ptime;
-	int i;
-	if (notify)
-		ctx->current_crl = crl;
-	if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME)
-		ptime = &ctx->param->check_time;
-	else
-		ptime = NULL;
+{
+    time_t *ptime;
+    int i;
+    if (notify)
+        ctx->current_crl = crl;
+    if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME)
+        ptime = &ctx->param->check_time;
+    else
+        ptime = NULL;
 
-	i=X509_cmp_time(X509_CRL_get_lastUpdate(crl), ptime);
-	if (i == 0)
-		{
-		if (!notify)
-			return 0;
-		ctx->error=X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD;
-		if (!ctx->verify_cb(0, ctx))
-			return 0;
-		}
+    i = X509_cmp_time(X509_CRL_get_lastUpdate(crl), ptime);
+    if (i == 0) {
+        if (!notify)
+            return 0;
+        ctx->error = X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD;
+        if (!ctx->verify_cb(0, ctx))
+            return 0;
+    }
 
-	if (i > 0)
-		{
-		if (!notify)
-			return 0;
-		ctx->error=X509_V_ERR_CRL_NOT_YET_VALID;
-		if (!ctx->verify_cb(0, ctx))
-			return 0;
-		}
+    if (i > 0) {
+        if (!notify)
+            return 0;
+        ctx->error = X509_V_ERR_CRL_NOT_YET_VALID;
+        if (!ctx->verify_cb(0, ctx))
+            return 0;
+    }
 
-	if(X509_CRL_get_nextUpdate(crl))
-		{
-		i=X509_cmp_time(X509_CRL_get_nextUpdate(crl), ptime);
+    if (X509_CRL_get_nextUpdate(crl)) {
+        i = X509_cmp_time(X509_CRL_get_nextUpdate(crl), ptime);
 
-		if (i == 0)
-			{
-			if (!notify)
-				return 0;
-			ctx->error=X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD;
-			if (!ctx->verify_cb(0, ctx))
-				return 0;
-			}
-		/* Ignore expiry of base CRL is delta is valid */
-		if ((i < 0) && !(ctx->current_crl_score & CRL_SCORE_TIME_DELTA))
-			{
-			if (!notify)
-				return 0;
-			ctx->error=X509_V_ERR_CRL_HAS_EXPIRED;
-			if (!ctx->verify_cb(0, ctx))
-				return 0;
-			}
-		}
+        if (i == 0) {
+            if (!notify)
+                return 0;
+            ctx->error = X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD;
+            if (!ctx->verify_cb(0, ctx))
+                return 0;
+        }
+        /* Ignore expiry of base CRL is delta is valid */
+        if ((i < 0) && !(ctx->current_crl_score & CRL_SCORE_TIME_DELTA)) {
+            if (!notify)
+                return 0;
+            ctx->error = X509_V_ERR_CRL_HAS_EXPIRED;
+            if (!ctx->verify_cb(0, ctx))
+                return 0;
+        }
+    }
 
-	if (notify)
-		ctx->current_crl = NULL;
+    if (notify)
+        ctx->current_crl = NULL;
 
-	return 1;
-	}
+    return 1;
+}
 
 static int get_crl_sk(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509_CRL **pdcrl,
-			X509 **pissuer, int *pscore, unsigned int *preasons,
-			STACK_OF(X509_CRL) *crls)
-	{
-	int crl_score, best_score = *pscore;
-	size_t i;
-	unsigned int reasons, best_reasons = 0;
-	X509 *x = ctx->current_cert;
-	X509_CRL *crl, *best_crl = NULL;
-	X509 *crl_issuer = NULL, *best_crl_issuer = NULL;
+                      X509 **pissuer, int *pscore, unsigned int *preasons,
+                      STACK_OF(X509_CRL) *crls)
+{
+    int crl_score, best_score = *pscore;
+    size_t i;
+    unsigned int reasons, best_reasons = 0;
+    X509 *x = ctx->current_cert;
+    X509_CRL *crl, *best_crl = NULL;
+    X509 *crl_issuer = NULL, *best_crl_issuer = NULL;
 
-	for (i = 0; i < sk_X509_CRL_num(crls); i++)
-		{
-		crl = sk_X509_CRL_value(crls, i);
-		reasons = *preasons;
-		crl_score = get_crl_score(ctx, &crl_issuer, &reasons, crl, x);
+    for (i = 0; i < sk_X509_CRL_num(crls); i++) {
+        crl = sk_X509_CRL_value(crls, i);
+        reasons = *preasons;
+        crl_score = get_crl_score(ctx, &crl_issuer, &reasons, crl, x);
+        if (crl_score < best_score || crl_score == 0)
+            continue;
+        /* If current CRL is equivalent use it if it is newer */
+        if (crl_score == best_score && best_crl != NULL) {
+            int day, sec;
+            if (ASN1_TIME_diff(&day, &sec, X509_CRL_get_lastUpdate(best_crl),
+                               X509_CRL_get_lastUpdate(crl)) == 0)
+                continue;
+            /*
+             * ASN1_TIME_diff never returns inconsistent signs for |day|
+             * and |sec|.
+             */
+            if (day <= 0 && sec <= 0)
+                continue;
+        }
+        best_crl = crl;
+        best_crl_issuer = crl_issuer;
+        best_score = crl_score;
+        best_reasons = reasons;
+    }
 
-		if (crl_score > best_score)
-			{
-			best_crl = crl;
-			best_crl_issuer = crl_issuer;
-			best_score = crl_score;
-			best_reasons = reasons;
-			}
-		}
+    if (best_crl) {
+        if (*pcrl)
+            X509_CRL_free(*pcrl);
+        *pcrl = best_crl;
+        *pissuer = best_crl_issuer;
+        *pscore = best_score;
+        *preasons = best_reasons;
+        X509_CRL_up_ref(best_crl);
+        if (*pdcrl) {
+            X509_CRL_free(*pdcrl);
+            *pdcrl = NULL;
+        }
+        get_delta_sk(ctx, pdcrl, pscore, best_crl, crls);
+    }
 
-	if (best_crl)
-		{
-		if (*pcrl)
-			X509_CRL_free(*pcrl);
-		*pcrl = best_crl;
-		*pissuer = best_crl_issuer;
-		*pscore = best_score;
-		*preasons = best_reasons;
-		X509_CRL_up_ref(best_crl);
-		if (*pdcrl)
-			{
-			X509_CRL_free(*pdcrl);
-			*pdcrl = NULL;
-			}
-		get_delta_sk(ctx, pdcrl, pscore, best_crl, crls);
-		}
+    if (best_score >= CRL_SCORE_VALID)
+        return 1;
 
-	if (best_score >= CRL_SCORE_VALID)
-		return 1;
+    return 0;
+}
 
-	return 0;
-	}
-
-/* Compare two CRL extensions for delta checking purposes. They should be
+/*
+ * Compare two CRL extensions for delta checking purposes. They should be
  * both present or both absent. If both present all fields must be identical.
  */
 
 static int crl_extension_match(X509_CRL *a, X509_CRL *b, int nid)
-	{
-	ASN1_OCTET_STRING *exta, *extb;
-	int i;
-	i = X509_CRL_get_ext_by_NID(a, nid, -1);
-	if (i >= 0)
-		{
-		/* Can't have multiple occurrences */
-		if (X509_CRL_get_ext_by_NID(a, nid, i) != -1)
-			return 0;
-		exta = X509_EXTENSION_get_data(X509_CRL_get_ext(a, i));
-		}
-	else
-		exta = NULL;
+{
+    ASN1_OCTET_STRING *exta, *extb;
+    int i;
+    i = X509_CRL_get_ext_by_NID(a, nid, -1);
+    if (i >= 0) {
+        /* Can't have multiple occurrences */
+        if (X509_CRL_get_ext_by_NID(a, nid, i) != -1)
+            return 0;
+        exta = X509_EXTENSION_get_data(X509_CRL_get_ext(a, i));
+    } else
+        exta = NULL;
 
-	i = X509_CRL_get_ext_by_NID(b, nid, -1);
+    i = X509_CRL_get_ext_by_NID(b, nid, -1);
 
-	if (i >= 0)
-		{
+    if (i >= 0) {
 
-		if (X509_CRL_get_ext_by_NID(b, nid, i) != -1)
-			return 0;
-		extb = X509_EXTENSION_get_data(X509_CRL_get_ext(b, i));
-		}
-	else
-		extb = NULL;
+        if (X509_CRL_get_ext_by_NID(b, nid, i) != -1)
+            return 0;
+        extb = X509_EXTENSION_get_data(X509_CRL_get_ext(b, i));
+    } else
+        extb = NULL;
 
-	if (!exta && !extb)
-		return 1;
+    if (!exta && !extb)
+        return 1;
 
-	if (!exta || !extb)
-		return 0;
+    if (!exta || !extb)
+        return 0;
 
+    if (ASN1_OCTET_STRING_cmp(exta, extb))
+        return 0;
 
-	if (ASN1_OCTET_STRING_cmp(exta, extb))
-		return 0;
-
-	return 1;
-	}
+    return 1;
+}
 
 /* See if a base and delta are compatible */
 
 static int check_delta_base(X509_CRL *delta, X509_CRL *base)
-	{
-	/* Delta CRL must be a delta */
-	if (!delta->base_crl_number)
-			return 0;
-	/* Base must have a CRL number */
-	if (!base->crl_number)
-			return 0;
-	/* Issuer names must match */
-	if (X509_NAME_cmp(X509_CRL_get_issuer(base),
-				X509_CRL_get_issuer(delta)))
-		return 0;
-	/* AKID and IDP must match */
-	if (!crl_extension_match(delta, base, NID_authority_key_identifier))
-			return 0;
-	if (!crl_extension_match(delta, base, NID_issuing_distribution_point))
-			return 0;
-	/* Delta CRL base number must not exceed Full CRL number. */
-	if (ASN1_INTEGER_cmp(delta->base_crl_number, base->crl_number) > 0)
-			return 0;
-	/* Delta CRL number must exceed full CRL number */
-	if (ASN1_INTEGER_cmp(delta->crl_number, base->crl_number) > 0)
-			return 1;
-	return 0;
-	}
+{
+    /* Delta CRL must be a delta */
+    if (!delta->base_crl_number)
+        return 0;
+    /* Base must have a CRL number */
+    if (!base->crl_number)
+        return 0;
+    /* Issuer names must match */
+    if (X509_NAME_cmp(X509_CRL_get_issuer(base), X509_CRL_get_issuer(delta)))
+        return 0;
+    /* AKID and IDP must match */
+    if (!crl_extension_match(delta, base, NID_authority_key_identifier))
+        return 0;
+    if (!crl_extension_match(delta, base, NID_issuing_distribution_point))
+        return 0;
+    /* Delta CRL base number must not exceed Full CRL number. */
+    if (ASN1_INTEGER_cmp(delta->base_crl_number, base->crl_number) > 0)
+        return 0;
+    /* Delta CRL number must exceed full CRL number */
+    if (ASN1_INTEGER_cmp(delta->crl_number, base->crl_number) > 0)
+        return 1;
+    return 0;
+}
 
-/* For a given base CRL find a delta... maybe extend to delta scoring
- * or retrieve a chain of deltas...
+/*
+ * For a given base CRL find a delta... maybe extend to delta scoring or
+ * retrieve a chain of deltas...
  */
 
 static void get_delta_sk(X509_STORE_CTX *ctx, X509_CRL **dcrl, int *pscore,
-			X509_CRL *base, STACK_OF(X509_CRL) *crls)
-	{
-	X509_CRL *delta;
-	size_t i;
-	if (!(ctx->param->flags & X509_V_FLAG_USE_DELTAS))
-		return;
-	if (!((ctx->current_cert->ex_flags | base->flags) & EXFLAG_FRESHEST))
-		return;
-	for (i = 0; i < sk_X509_CRL_num(crls); i++)
-		{
-		delta = sk_X509_CRL_value(crls, i);
-		if (check_delta_base(delta, base))
-			{
-			if (check_crl_time(ctx, delta, 0))
-				*pscore |= CRL_SCORE_TIME_DELTA;
-			X509_CRL_up_ref(delta);
-			*dcrl = delta;
-			return;
-			}
-		}
-	*dcrl = NULL;
-	}
+                         X509_CRL *base, STACK_OF(X509_CRL) *crls)
+{
+    X509_CRL *delta;
+    size_t i;
+    if (!(ctx->param->flags & X509_V_FLAG_USE_DELTAS))
+        return;
+    if (!((ctx->current_cert->ex_flags | base->flags) & EXFLAG_FRESHEST))
+        return;
+    for (i = 0; i < sk_X509_CRL_num(crls); i++) {
+        delta = sk_X509_CRL_value(crls, i);
+        if (check_delta_base(delta, base)) {
+            if (check_crl_time(ctx, delta, 0))
+                *pscore |= CRL_SCORE_TIME_DELTA;
+            X509_CRL_up_ref(delta);
+            *dcrl = delta;
+            return;
+        }
+    }
+    *dcrl = NULL;
+}
 
-/* For a given CRL return how suitable it is for the supplied certificate 'x'.
- * The return value is a mask of several criteria.
- * If the issuer is not the certificate issuer this is returned in *pissuer.
- * The reasons mask is also used to determine if the CRL is suitable: if
- * no new reasons the CRL is rejected, otherwise reasons is updated.
+/*
+ * For a given CRL return how suitable it is for the supplied certificate
+ * 'x'. The return value is a mask of several criteria. If the issuer is not
+ * the certificate issuer this is returned in *pissuer. The reasons mask is
+ * also used to determine if the CRL is suitable: if no new reasons the CRL
+ * is rejected, otherwise reasons is updated.
  */
 
 static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer,
-			unsigned int *preasons,
-			X509_CRL *crl, X509 *x)
-	{
+                         unsigned int *preasons, X509_CRL *crl, X509 *x)
+{
 
-	int crl_score = 0;
-	unsigned int tmp_reasons = *preasons, crl_reasons;
+    int crl_score = 0;
+    unsigned int tmp_reasons = *preasons, crl_reasons;
 
-	/* First see if we can reject CRL straight away */
+    /* First see if we can reject CRL straight away */
 
-	/* Invalid IDP cannot be processed */
-	if (crl->idp_flags & IDP_INVALID)
-		return 0;
-	/* Reason codes or indirect CRLs need extended CRL support */
-	if (!(ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT))
-		{
-		if (crl->idp_flags & (IDP_INDIRECT | IDP_REASONS))
-			return 0;
-		}
-	else if (crl->idp_flags & IDP_REASONS)
-		{
-		/* If no new reasons reject */
-		if (!(crl->idp_reasons & ~tmp_reasons))
-			return 0;
-		}
-	/* Don't process deltas at this stage */
-	else if (crl->base_crl_number)
-		return 0;
-	/* If issuer name doesn't match certificate need indirect CRL */
-	if (X509_NAME_cmp(X509_get_issuer_name(x), X509_CRL_get_issuer(crl)))
-		{
-		if (!(crl->idp_flags & IDP_INDIRECT))
-			return 0;
-		}
-	else
-		crl_score |= CRL_SCORE_ISSUER_NAME;
+    /* Invalid IDP cannot be processed */
+    if (crl->idp_flags & IDP_INVALID)
+        return 0;
+    /* Reason codes or indirect CRLs need extended CRL support */
+    if (!(ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT)) {
+        if (crl->idp_flags & (IDP_INDIRECT | IDP_REASONS))
+            return 0;
+    } else if (crl->idp_flags & IDP_REASONS) {
+        /* If no new reasons reject */
+        if (!(crl->idp_reasons & ~tmp_reasons))
+            return 0;
+    }
+    /* Don't process deltas at this stage */
+    else if (crl->base_crl_number)
+        return 0;
+    /* If issuer name doesn't match certificate need indirect CRL */
+    if (X509_NAME_cmp(X509_get_issuer_name(x), X509_CRL_get_issuer(crl))) {
+        if (!(crl->idp_flags & IDP_INDIRECT))
+            return 0;
+    } else
+        crl_score |= CRL_SCORE_ISSUER_NAME;
 
-	if (!(crl->flags & EXFLAG_CRITICAL))
-		crl_score |= CRL_SCORE_NOCRITICAL;
+    if (!(crl->flags & EXFLAG_CRITICAL))
+        crl_score |= CRL_SCORE_NOCRITICAL;
 
-	/* Check expiry */
-	if (check_crl_time(ctx, crl, 0))
-		crl_score |= CRL_SCORE_TIME;
+    /* Check expiry */
+    if (check_crl_time(ctx, crl, 0))
+        crl_score |= CRL_SCORE_TIME;
 
-	/* Check authority key ID and locate certificate issuer */
-	crl_akid_check(ctx, crl, pissuer, &crl_score);
+    /* Check authority key ID and locate certificate issuer */
+    crl_akid_check(ctx, crl, pissuer, &crl_score);
 
-	/* If we can't locate certificate issuer at this point forget it */
+    /* If we can't locate certificate issuer at this point forget it */
 
-	if (!(crl_score & CRL_SCORE_AKID))
-		return 0;
+    if (!(crl_score & CRL_SCORE_AKID))
+        return 0;
 
-	/* Check cert for matching CRL distribution points */
+    /* Check cert for matching CRL distribution points */
 
-	if (crl_crldp_check(x, crl, crl_score, &crl_reasons))
-		{
-		/* If no new reasons reject */
-		if (!(crl_reasons & ~tmp_reasons))
-			return 0;
-		tmp_reasons |= crl_reasons;
-		crl_score |= CRL_SCORE_SCOPE;
-		}
+    if (crl_crldp_check(x, crl, crl_score, &crl_reasons)) {
+        /* If no new reasons reject */
+        if (!(crl_reasons & ~tmp_reasons))
+            return 0;
+        tmp_reasons |= crl_reasons;
+        crl_score |= CRL_SCORE_SCOPE;
+    }
 
-	*preasons = tmp_reasons;
+    *preasons = tmp_reasons;
 
-	return crl_score;
+    return crl_score;
 
-	}
+}
 
 static void crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl,
-				X509 **pissuer, int *pcrl_score)
-	{
-	X509 *crl_issuer = NULL;
-	X509_NAME *cnm = X509_CRL_get_issuer(crl);
-	int cidx = ctx->error_depth;
-	size_t i;
+                           X509 **pissuer, int *pcrl_score)
+{
+    X509 *crl_issuer = NULL;
+    X509_NAME *cnm = X509_CRL_get_issuer(crl);
+    int cidx = ctx->error_depth;
+    size_t i;
 
-	if ((size_t) cidx != sk_X509_num(ctx->chain) - 1)
-		cidx++;
+    if ((size_t)cidx != sk_X509_num(ctx->chain) - 1)
+        cidx++;
 
-	crl_issuer = sk_X509_value(ctx->chain, cidx);
+    crl_issuer = sk_X509_value(ctx->chain, cidx);
 
-	if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK)
-		{
-		if (*pcrl_score & CRL_SCORE_ISSUER_NAME)
-			{
-			*pcrl_score |= CRL_SCORE_AKID|CRL_SCORE_ISSUER_CERT;
-			*pissuer = crl_issuer;
-			return;
-			}
-		}
+    if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) {
+        if (*pcrl_score & CRL_SCORE_ISSUER_NAME) {
+            *pcrl_score |= CRL_SCORE_AKID | CRL_SCORE_ISSUER_CERT;
+            *pissuer = crl_issuer;
+            return;
+        }
+    }
 
-	for (cidx++; cidx < (int) sk_X509_num(ctx->chain); cidx++)
-		{
-		crl_issuer = sk_X509_value(ctx->chain, cidx);
-		if (X509_NAME_cmp(X509_get_subject_name(crl_issuer), cnm))
-			continue;
-		if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK)
-			{
-			*pcrl_score |= CRL_SCORE_AKID|CRL_SCORE_SAME_PATH;
-			*pissuer = crl_issuer;
-			return;
-			}
-		}
+    for (cidx++; cidx < (int)sk_X509_num(ctx->chain); cidx++) {
+        crl_issuer = sk_X509_value(ctx->chain, cidx);
+        if (X509_NAME_cmp(X509_get_subject_name(crl_issuer), cnm))
+            continue;
+        if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) {
+            *pcrl_score |= CRL_SCORE_AKID | CRL_SCORE_SAME_PATH;
+            *pissuer = crl_issuer;
+            return;
+        }
+    }
 
-	/* Anything else needs extended CRL support */
+    /* Anything else needs extended CRL support */
 
-	if (!(ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT))
-		return;
+    if (!(ctx->param->flags & X509_V_FLAG_EXTENDED_CRL_SUPPORT))
+        return;
 
-	/* Otherwise the CRL issuer is not on the path. Look for it in the
-	 * set of untrusted certificates.
-	 */
-	for (i = 0; i < sk_X509_num(ctx->untrusted); i++)
-		{
-		crl_issuer = sk_X509_value(ctx->untrusted, i);
-		if (X509_NAME_cmp(X509_get_subject_name(crl_issuer), cnm))
-			continue;
-		if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK)
-			{
-			*pissuer = crl_issuer;
-			*pcrl_score |= CRL_SCORE_AKID;
-			return;
-			}
-		}
-	}
+    /*
+     * Otherwise the CRL issuer is not on the path. Look for it in the set of
+     * untrusted certificates.
+     */
+    for (i = 0; i < sk_X509_num(ctx->untrusted); i++) {
+        crl_issuer = sk_X509_value(ctx->untrusted, i);
+        if (X509_NAME_cmp(X509_get_subject_name(crl_issuer), cnm))
+            continue;
+        if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) {
+            *pissuer = crl_issuer;
+            *pcrl_score |= CRL_SCORE_AKID;
+            return;
+        }
+    }
 
-/* Check the path of a CRL issuer certificate. This creates a new
+    for (i = 0; i < sk_X509_num(ctx->ctx->additional_untrusted); i++) {
+        crl_issuer = sk_X509_value(ctx->ctx->additional_untrusted, i);
+        if (X509_NAME_cmp(X509_get_subject_name(crl_issuer), cnm))
+            continue;
+        if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) {
+            *pissuer = crl_issuer;
+            *pcrl_score |= CRL_SCORE_AKID;
+            return;
+        }
+    }
+}
+
+/*
+ * Check the path of a CRL issuer certificate. This creates a new
  * X509_STORE_CTX and populates it with most of the parameters from the
- * parent. This could be optimised somewhat since a lot of path checking
- * will be duplicated by the parent, but this will rarely be used in 
- * practice.
+ * parent. This could be optimised somewhat since a lot of path checking will
+ * be duplicated by the parent, but this will rarely be used in practice.
  */
 
 static int check_crl_path(X509_STORE_CTX *ctx, X509 *x)
-	{
-	X509_STORE_CTX crl_ctx;
-	int ret;
-	/* Don't allow recursive CRL path validation */
-	if (ctx->parent)
-		return 0;
-	if (!X509_STORE_CTX_init(&crl_ctx, ctx->ctx, x, ctx->untrusted))
-		return -1;
+{
+    X509_STORE_CTX crl_ctx;
+    int ret;
+    /* Don't allow recursive CRL path validation */
+    if (ctx->parent)
+        return 0;
+    if (!X509_STORE_CTX_init(&crl_ctx, ctx->ctx, x, ctx->untrusted))
+        return -1;
 
-	crl_ctx.crls = ctx->crls;
-	/* Copy verify params across */
-	X509_STORE_CTX_set0_param(&crl_ctx, ctx->param);
+    crl_ctx.crls = ctx->crls;
+    /* Copy verify params across */
+    X509_STORE_CTX_set0_param(&crl_ctx, ctx->param);
 
-	crl_ctx.parent = ctx;
-	crl_ctx.verify_cb = ctx->verify_cb;
+    crl_ctx.parent = ctx;
+    crl_ctx.verify_cb = ctx->verify_cb;
 
-	/* Verify CRL issuer */
-	ret = X509_verify_cert(&crl_ctx);
+    /* Verify CRL issuer */
+    ret = X509_verify_cert(&crl_ctx);
 
-	if (ret <= 0)
-		goto err;
+    if (ret <= 0)
+        goto err;
 
-	/* Check chain is acceptable */
+    /* Check chain is acceptable */
 
-	ret = check_crl_chain(ctx, ctx->chain, crl_ctx.chain);
-	err:
-	X509_STORE_CTX_cleanup(&crl_ctx);
-	return ret;
-	}
+    ret = check_crl_chain(ctx, ctx->chain, crl_ctx.chain);
+ err:
+    X509_STORE_CTX_cleanup(&crl_ctx);
+    return ret;
+}
 
-/* RFC3280 says nothing about the relationship between CRL path
- * and certificate path, which could lead to situations where a
- * certificate could be revoked or validated by a CA not authorised
- * to do so. RFC5280 is more strict and states that the two paths must
- * end in the same trust anchor, though some discussions remain...
- * until this is resolved we use the RFC5280 version
+/*
+ * RFC3280 says nothing about the relationship between CRL path and
+ * certificate path, which could lead to situations where a certificate could
+ * be revoked or validated by a CA not authorised to do so. RFC5280 is more
+ * strict and states that the two paths must end in the same trust anchor,
+ * though some discussions remain... until this is resolved we use the
+ * RFC5280 version
  */
 
 static int check_crl_chain(X509_STORE_CTX *ctx,
-			STACK_OF(X509) *cert_path,
-			STACK_OF(X509) *crl_path)
-	{
-	X509 *cert_ta, *crl_ta;
-	cert_ta = sk_X509_value(cert_path, sk_X509_num(cert_path) - 1);
-	crl_ta = sk_X509_value(crl_path, sk_X509_num(crl_path) - 1);
-	if (!X509_cmp(cert_ta, crl_ta))
-		return 1;
-	return 0;
-	}
+                           STACK_OF(X509) *cert_path,
+                           STACK_OF(X509) *crl_path)
+{
+    X509 *cert_ta, *crl_ta;
+    cert_ta = sk_X509_value(cert_path, sk_X509_num(cert_path) - 1);
+    crl_ta = sk_X509_value(crl_path, sk_X509_num(crl_path) - 1);
+    if (!X509_cmp(cert_ta, crl_ta))
+        return 1;
+    return 0;
+}
 
-/* Check for match between two dist point names: three separate cases.
- * 1. Both are relative names and compare X509_NAME types.
- * 2. One full, one relative. Compare X509_NAME to GENERAL_NAMES.
- * 3. Both are full names and compare two GENERAL_NAMES.
- * 4. One is NULL: automatic match.
+/*
+ * Check for match between two dist point names: three separate cases. 1.
+ * Both are relative names and compare X509_NAME types. 2. One full, one
+ * relative. Compare X509_NAME to GENERAL_NAMES. 3. Both are full names and
+ * compare two GENERAL_NAMES. 4. One is NULL: automatic match.
  */
 
-
 static int idp_check_dp(DIST_POINT_NAME *a, DIST_POINT_NAME *b)
-	{
-	X509_NAME *nm = NULL;
-	GENERAL_NAMES *gens = NULL;
-	GENERAL_NAME *gena, *genb;
-	size_t i, j;
-	if (!a || !b)
-		return 1;
-	if (a->type == 1)
-		{
-		if (!a->dpname)
-			return 0;
-		/* Case 1: two X509_NAME */
-		if (b->type == 1)
-			{
-			if (!b->dpname)
-				return 0;
-			if (!X509_NAME_cmp(a->dpname, b->dpname))
-				return 1;
-			else
-				return 0;
-			}
-		/* Case 2: set name and GENERAL_NAMES appropriately */
-		nm = a->dpname;
-		gens = b->name.fullname;
-		}
-	else if (b->type == 1)
-		{
-		if (!b->dpname)
-			return 0;
-		/* Case 2: set name and GENERAL_NAMES appropriately */
-		gens = a->name.fullname;
-		nm = b->dpname;
-		}
+{
+    X509_NAME *nm = NULL;
+    GENERAL_NAMES *gens = NULL;
+    GENERAL_NAME *gena, *genb;
+    size_t i, j;
+    if (!a || !b)
+        return 1;
+    if (a->type == 1) {
+        if (!a->dpname)
+            return 0;
+        /* Case 1: two X509_NAME */
+        if (b->type == 1) {
+            if (!b->dpname)
+                return 0;
+            if (!X509_NAME_cmp(a->dpname, b->dpname))
+                return 1;
+            else
+                return 0;
+        }
+        /* Case 2: set name and GENERAL_NAMES appropriately */
+        nm = a->dpname;
+        gens = b->name.fullname;
+    } else if (b->type == 1) {
+        if (!b->dpname)
+            return 0;
+        /* Case 2: set name and GENERAL_NAMES appropriately */
+        gens = a->name.fullname;
+        nm = b->dpname;
+    }
 
-	/* Handle case 2 with one GENERAL_NAMES and one X509_NAME */
-	if (nm)
-		{
-		for (i = 0; i < sk_GENERAL_NAME_num(gens); i++)
-			{
-			gena = sk_GENERAL_NAME_value(gens, i);	
-			if (gena->type != GEN_DIRNAME)
-				continue;
-			if (!X509_NAME_cmp(nm, gena->d.directoryName))
-				return 1;
-			}
-		return 0;
-		}
+    /* Handle case 2 with one GENERAL_NAMES and one X509_NAME */
+    if (nm) {
+        for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
+            gena = sk_GENERAL_NAME_value(gens, i);
+            if (gena->type != GEN_DIRNAME)
+                continue;
+            if (!X509_NAME_cmp(nm, gena->d.directoryName))
+                return 1;
+        }
+        return 0;
+    }
 
-	/* Else case 3: two GENERAL_NAMES */
+    /* Else case 3: two GENERAL_NAMES */
 
-	for (i = 0; i < sk_GENERAL_NAME_num(a->name.fullname); i++)
-		{
-		gena = sk_GENERAL_NAME_value(a->name.fullname, i);
-		for (j = 0; j < sk_GENERAL_NAME_num(b->name.fullname); j++)
-			{
-			genb = sk_GENERAL_NAME_value(b->name.fullname, j);
-			if (!GENERAL_NAME_cmp(gena, genb))
-				return 1;
-			}
-		}
+    for (i = 0; i < sk_GENERAL_NAME_num(a->name.fullname); i++) {
+        gena = sk_GENERAL_NAME_value(a->name.fullname, i);
+        for (j = 0; j < sk_GENERAL_NAME_num(b->name.fullname); j++) {
+            genb = sk_GENERAL_NAME_value(b->name.fullname, j);
+            if (!GENERAL_NAME_cmp(gena, genb))
+                return 1;
+        }
+    }
 
-	return 0;
+    return 0;
 
-	}
+}
 
 static int crldp_check_crlissuer(DIST_POINT *dp, X509_CRL *crl, int crl_score)
-	{
-	size_t i;
-	X509_NAME *nm = X509_CRL_get_issuer(crl);
-	/* If no CRLissuer return is successful iff don't need a match */
-	if (!dp->CRLissuer)
-		return !!(crl_score & CRL_SCORE_ISSUER_NAME);
-	for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++)
-		{
-		GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i);
-		if (gen->type != GEN_DIRNAME)
-			continue;
-		if (!X509_NAME_cmp(gen->d.directoryName, nm))
-			return 1;
-		}
-	return 0;
-	}
+{
+    size_t i;
+    X509_NAME *nm = X509_CRL_get_issuer(crl);
+    /* If no CRLissuer return is successful iff don't need a match */
+    if (!dp->CRLissuer)
+        return ! !(crl_score & CRL_SCORE_ISSUER_NAME);
+    for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++) {
+        GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i);
+        if (gen->type != GEN_DIRNAME)
+            continue;
+        if (!X509_NAME_cmp(gen->d.directoryName, nm))
+            return 1;
+    }
+    return 0;
+}
 
 /* Check CRLDP and IDP */
 
 static int crl_crldp_check(X509 *x, X509_CRL *crl, int crl_score,
-				unsigned int *preasons)
-	{
-	size_t i;
-	if (crl->idp_flags & IDP_ONLYATTR)
-		return 0;
-	if (x->ex_flags & EXFLAG_CA)
-		{
-		if (crl->idp_flags & IDP_ONLYUSER)
-			return 0;
-		}
-	else
-		{
-		if (crl->idp_flags & IDP_ONLYCA)
-			return 0;
-		}
-	*preasons = crl->idp_reasons;
-	for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++)
-		{
-		DIST_POINT *dp = sk_DIST_POINT_value(x->crldp, i);
-		if (crldp_check_crlissuer(dp, crl, crl_score))
-			{
-			if (!crl->idp ||
-			     idp_check_dp(dp->distpoint, crl->idp->distpoint))
-				{
-				*preasons &= dp->dp_reasons;
-				return 1;
-				}
-			}
-		}
-	if ((!crl->idp || !crl->idp->distpoint) && (crl_score & CRL_SCORE_ISSUER_NAME))
-		return 1;
-	return 0;
-	}
+                           unsigned int *preasons)
+{
+    size_t i;
+    if (crl->idp_flags & IDP_ONLYATTR)
+        return 0;
+    if (x->ex_flags & EXFLAG_CA) {
+        if (crl->idp_flags & IDP_ONLYUSER)
+            return 0;
+    } else {
+        if (crl->idp_flags & IDP_ONLYCA)
+            return 0;
+    }
+    *preasons = crl->idp_reasons;
+    for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++) {
+        DIST_POINT *dp = sk_DIST_POINT_value(x->crldp, i);
+        if (crldp_check_crlissuer(dp, crl, crl_score)) {
+            if (!crl->idp || idp_check_dp(dp->distpoint, crl->idp->distpoint)) {
+                *preasons &= dp->dp_reasons;
+                return 1;
+            }
+        }
+    }
+    if ((!crl->idp || !crl->idp->distpoint)
+        && (crl_score & CRL_SCORE_ISSUER_NAME))
+        return 1;
+    return 0;
+}
 
-/* Retrieve CRL corresponding to current certificate.
- * If deltas enabled try to find a delta CRL too
+/*
+ * Retrieve CRL corresponding to current certificate. If deltas enabled try
+ * to find a delta CRL too
  */
-	
+
 static int get_crl_delta(X509_STORE_CTX *ctx,
-				X509_CRL **pcrl, X509_CRL **pdcrl, X509 *x)
-	{
-	int ok;
-	X509 *issuer = NULL;
-	int crl_score = 0;
-	unsigned int reasons;
-	X509_CRL *crl = NULL, *dcrl = NULL;
-	STACK_OF(X509_CRL) *skcrl;
-	X509_NAME *nm = X509_get_issuer_name(x);
-	reasons = ctx->current_reasons;
-	ok = get_crl_sk(ctx, &crl, &dcrl, 
-				&issuer, &crl_score, &reasons, ctx->crls);
+                         X509_CRL **pcrl, X509_CRL **pdcrl, X509 *x)
+{
+    int ok;
+    X509 *issuer = NULL;
+    int crl_score = 0;
+    unsigned int reasons;
+    X509_CRL *crl = NULL, *dcrl = NULL;
+    STACK_OF(X509_CRL) *skcrl;
+    X509_NAME *nm = X509_get_issuer_name(x);
+    reasons = ctx->current_reasons;
+    ok = get_crl_sk(ctx, &crl, &dcrl,
+                    &issuer, &crl_score, &reasons, ctx->crls);
 
-	if (ok)
-		goto done;
+    if (ok)
+        goto done;
 
-	/* Lookup CRLs from store */
+    /* Lookup CRLs from store */
 
-	skcrl = ctx->lookup_crls(ctx, nm);
+    skcrl = ctx->lookup_crls(ctx, nm);
 
-	/* If no CRLs found and a near match from get_crl_sk use that */
-	if (!skcrl && crl)
-		goto done;
+    /* If no CRLs found and a near match from get_crl_sk use that */
+    if (!skcrl && crl)
+        goto done;
 
-	get_crl_sk(ctx, &crl, &dcrl, &issuer, &crl_score, &reasons, skcrl);
+    get_crl_sk(ctx, &crl, &dcrl, &issuer, &crl_score, &reasons, skcrl);
 
-	sk_X509_CRL_pop_free(skcrl, X509_CRL_free);
+    sk_X509_CRL_pop_free(skcrl, X509_CRL_free);
 
-	done:
+ done:
 
-	/* If we got any kind of CRL use it and return success */
-	if (crl)
-		{
-		ctx->current_issuer = issuer;
-		ctx->current_crl_score = crl_score;
-		ctx->current_reasons = reasons;
-		*pcrl = crl;
-		*pdcrl = dcrl;
-		return 1;
-		}
+    /* If we got any kind of CRL use it and return success */
+    if (crl) {
+        ctx->current_issuer = issuer;
+        ctx->current_crl_score = crl_score;
+        ctx->current_reasons = reasons;
+        *pcrl = crl;
+        *pdcrl = dcrl;
+        return 1;
+    }
 
-	return 0;
-	}
+    return 0;
+}
 
 /* Check CRL validity */
 static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl)
-	{
-	X509 *issuer = NULL;
-	EVP_PKEY *ikey = NULL;
-	int ok = 0, chnum, cnum;
-	cnum = ctx->error_depth;
-	chnum = sk_X509_num(ctx->chain) - 1;
-	/* if we have an alternative CRL issuer cert use that */
-	if (ctx->current_issuer)
-		issuer = ctx->current_issuer;
+{
+    X509 *issuer = NULL;
+    EVP_PKEY *ikey = NULL;
+    int ok = 0, chnum, cnum;
+    cnum = ctx->error_depth;
+    chnum = sk_X509_num(ctx->chain) - 1;
+    /* if we have an alternative CRL issuer cert use that */
+    if (ctx->current_issuer)
+        issuer = ctx->current_issuer;
 
-	/* Else find CRL issuer: if not last certificate then issuer
-	 * is next certificate in chain.
-	 */
-	else if (cnum < chnum)
-		issuer = sk_X509_value(ctx->chain, cnum + 1);
-	else
-		{
-		issuer = sk_X509_value(ctx->chain, chnum);
-		/* If not self signed, can't check signature */
-		if(!ctx->check_issued(ctx, issuer, issuer))
-			{
-			ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER;
-			ok = ctx->verify_cb(0, ctx);
-			if(!ok) goto err;
-			}
-		}
+    /*
+     * Else find CRL issuer: if not last certificate then issuer is next
+     * certificate in chain.
+     */
+    else if (cnum < chnum)
+        issuer = sk_X509_value(ctx->chain, cnum + 1);
+    else {
+        issuer = sk_X509_value(ctx->chain, chnum);
+        /* If not self signed, can't check signature */
+        if (!ctx->check_issued(ctx, issuer, issuer)) {
+            ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER;
+            ok = ctx->verify_cb(0, ctx);
+            if (!ok)
+                goto err;
+        }
+    }
 
-	if(issuer)
-		{
-		/* Skip most tests for deltas because they have already
-		 * been done
-		 */
-		if (!crl->base_crl_number)
-			{
-			/* Check for cRLSign bit if keyUsage present */
-			if ((issuer->ex_flags & EXFLAG_KUSAGE) &&
-				!(issuer->ex_kusage & KU_CRL_SIGN))
-				{
-				ctx->error = X509_V_ERR_KEYUSAGE_NO_CRL_SIGN;
-				ok = ctx->verify_cb(0, ctx);
-				if(!ok) goto err;
-				}
+    if (issuer) {
+        /*
+         * Skip most tests for deltas because they have already been done
+         */
+        if (!crl->base_crl_number) {
+            /* Check for cRLSign bit if keyUsage present */
+            if ((issuer->ex_flags & EXFLAG_KUSAGE) &&
+                !(issuer->ex_kusage & KU_CRL_SIGN)) {
+                ctx->error = X509_V_ERR_KEYUSAGE_NO_CRL_SIGN;
+                ok = ctx->verify_cb(0, ctx);
+                if (!ok)
+                    goto err;
+            }
 
-			if (!(ctx->current_crl_score & CRL_SCORE_SCOPE))
-				{
-				ctx->error = X509_V_ERR_DIFFERENT_CRL_SCOPE;
-				ok = ctx->verify_cb(0, ctx);
-				if(!ok) goto err;
-				}
+            if (!(ctx->current_crl_score & CRL_SCORE_SCOPE)) {
+                ctx->error = X509_V_ERR_DIFFERENT_CRL_SCOPE;
+                ok = ctx->verify_cb(0, ctx);
+                if (!ok)
+                    goto err;
+            }
 
-			if (!(ctx->current_crl_score & CRL_SCORE_SAME_PATH))
-				{
-				if (check_crl_path(ctx, ctx->current_issuer) <= 0)
-					{
-					ctx->error = X509_V_ERR_CRL_PATH_VALIDATION_ERROR;
-					ok = ctx->verify_cb(0, ctx);
-					if(!ok) goto err;
-					}
-				}
+            if (!(ctx->current_crl_score & CRL_SCORE_SAME_PATH)) {
+                if (check_crl_path(ctx, ctx->current_issuer) <= 0) {
+                    ctx->error = X509_V_ERR_CRL_PATH_VALIDATION_ERROR;
+                    ok = ctx->verify_cb(0, ctx);
+                    if (!ok)
+                        goto err;
+                }
+            }
 
-			if (crl->idp_flags & IDP_INVALID)
-				{
-				ctx->error = X509_V_ERR_INVALID_EXTENSION;
-				ok = ctx->verify_cb(0, ctx);
-				if(!ok) goto err;
-				}
+            if (crl->idp_flags & IDP_INVALID) {
+                ctx->error = X509_V_ERR_INVALID_EXTENSION;
+                ok = ctx->verify_cb(0, ctx);
+                if (!ok)
+                    goto err;
+            }
 
+        }
 
-			}
+        if (!(ctx->current_crl_score & CRL_SCORE_TIME)) {
+            ok = check_crl_time(ctx, crl, 1);
+            if (!ok)
+                goto err;
+        }
 
-		if (!(ctx->current_crl_score & CRL_SCORE_TIME))
-			{
-			ok = check_crl_time(ctx, crl, 1);
-			if (!ok)
-				goto err;
-			}
+        /* Attempt to get issuer certificate public key */
+        ikey = X509_get_pubkey(issuer);
 
-		/* Attempt to get issuer certificate public key */
-		ikey = X509_get_pubkey(issuer);
+        if (!ikey) {
+            ctx->error = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
+            ok = ctx->verify_cb(0, ctx);
+            if (!ok)
+                goto err;
+        } else {
+            int rv;
+            rv = X509_CRL_check_suiteb(crl, ikey, ctx->param->flags);
+            if (rv != X509_V_OK) {
+                ctx->error = rv;
+                ok = ctx->verify_cb(0, ctx);
+                if (!ok)
+                    goto err;
+            }
+            /* Verify CRL signature */
+            if (X509_CRL_verify(crl, ikey) <= 0) {
+                ctx->error = X509_V_ERR_CRL_SIGNATURE_FAILURE;
+                ok = ctx->verify_cb(0, ctx);
+                if (!ok)
+                    goto err;
+            }
+        }
+    }
 
-		if(!ikey)
-			{
-			ctx->error=X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
-			ok = ctx->verify_cb(0, ctx);
-			if (!ok) goto err;
-			}
-		else
-			{
-			int rv;
-			rv = X509_CRL_check_suiteb(crl, ikey, ctx->param->flags);
-			if (rv != X509_V_OK)
-				{
-				ctx->error=rv;
-				ok = ctx->verify_cb(0, ctx);
-				if (!ok)
-					goto err;
-				}
-			/* Verify CRL signature */
-			if(X509_CRL_verify(crl, ikey) <= 0)
-				{
-				ctx->error=X509_V_ERR_CRL_SIGNATURE_FAILURE;
-				ok = ctx->verify_cb(0, ctx);
-				if (!ok) goto err;
-				}
-			}
-		}
+    ok = 1;
 
-	ok = 1;
-
-	err:
-	EVP_PKEY_free(ikey);
-	return ok;
-	}
+ err:
+    EVP_PKEY_free(ikey);
+    return ok;
+}
 
 /* Check certificate against CRL */
 static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x)
-	{
-	int ok;
-	X509_REVOKED *rev;
-	/* The rules changed for this... previously if a CRL contained
-	 * unhandled critical extensions it could still be used to indicate
-	 * a certificate was revoked. This has since been changed since 
-	 * critical extension can change the meaning of CRL entries.
-	 */
-	if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL)
-		&& (crl->flags & EXFLAG_CRITICAL))
-		{
-		ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION;
-		ok = ctx->verify_cb(0, ctx);
-		if(!ok)
-			return 0;
-		}
-	/* Look for serial number of certificate in CRL
-	 * If found make sure reason is not removeFromCRL.
-	 */
-	if (X509_CRL_get0_by_cert(crl, &rev, x))
-		{
-		if (rev->reason == CRL_REASON_REMOVE_FROM_CRL)
-			return 2;
-		ctx->error = X509_V_ERR_CERT_REVOKED;
-		ok = ctx->verify_cb(0, ctx);
-		if (!ok)
-			return 0;
-		}
+{
+    int ok;
+    X509_REVOKED *rev;
+    /*
+     * The rules changed for this... previously if a CRL contained unhandled
+     * critical extensions it could still be used to indicate a certificate
+     * was revoked. This has since been changed since critical extension can
+     * change the meaning of CRL entries.
+     */
+    if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL)
+        && (crl->flags & EXFLAG_CRITICAL)) {
+        ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION;
+        ok = ctx->verify_cb(0, ctx);
+        if (!ok)
+            return 0;
+    }
+    /*
+     * Look for serial number of certificate in CRL If found make sure reason
+     * is not removeFromCRL.
+     */
+    if (X509_CRL_get0_by_cert(crl, &rev, x)) {
+        if (rev->reason == CRL_REASON_REMOVE_FROM_CRL)
+            return 2;
+        ctx->error = X509_V_ERR_CERT_REVOKED;
+        ok = ctx->verify_cb(0, ctx);
+        if (!ok)
+            return 0;
+    }
 
-	return 1;
-	}
+    return 1;
+}
 
 static int check_policy(X509_STORE_CTX *ctx)
-	{
-	int ret;
-	if (ctx->parent)
-		return 1;
-	ret = X509_policy_check(&ctx->tree, &ctx->explicit_policy, ctx->chain,
-				ctx->param->policies, ctx->param->flags);
-	if (ret == 0)
-		{
-		OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-		return 0;
-		}
-	/* Invalid or inconsistent extensions */
-	if (ret == -1)
-		{
-		/* Locate certificates with bad extensions and notify
-		 * callback.
-		 */
-		X509 *x;
-		size_t i;
-		for (i = 1; i < sk_X509_num(ctx->chain); i++)
-			{
-			x = sk_X509_value(ctx->chain, i);
-			if (!(x->ex_flags & EXFLAG_INVALID_POLICY))
-				continue;
-			ctx->current_cert = x;
-			ctx->error = X509_V_ERR_INVALID_POLICY_EXTENSION;
-			if(!ctx->verify_cb(0, ctx))
-				return 0;
-			}
-		return 1;
-		}
-	if (ret == -2)
-		{
-		ctx->current_cert = NULL;
-		ctx->error = X509_V_ERR_NO_EXPLICIT_POLICY;
-		return ctx->verify_cb(0, ctx);
-		}
+{
+    int ret;
+    if (ctx->parent)
+        return 1;
+    ret = X509_policy_check(&ctx->tree, &ctx->explicit_policy, ctx->chain,
+                            ctx->param->policies, ctx->param->flags);
+    if (ret == 0) {
+        OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+        ctx->error = X509_V_ERR_OUT_OF_MEM;
+        return 0;
+    }
+    /* Invalid or inconsistent extensions */
+    if (ret == -1) {
+        /*
+         * Locate certificates with bad extensions and notify callback.
+         */
+        X509 *x;
+        size_t i;
+        for (i = 1; i < sk_X509_num(ctx->chain); i++) {
+            x = sk_X509_value(ctx->chain, i);
+            if (!(x->ex_flags & EXFLAG_INVALID_POLICY))
+                continue;
+            ctx->current_cert = x;
+            ctx->error = X509_V_ERR_INVALID_POLICY_EXTENSION;
+            if (!ctx->verify_cb(0, ctx))
+                return 0;
+        }
+        return 1;
+    }
+    if (ret == -2) {
+        ctx->current_cert = NULL;
+        ctx->error = X509_V_ERR_NO_EXPLICIT_POLICY;
+        return ctx->verify_cb(0, ctx);
+    }
 
-	if (ctx->param->flags & X509_V_FLAG_NOTIFY_POLICY)
-		{
-		ctx->current_cert = NULL;
-		ctx->error = X509_V_OK;
-		if (!ctx->verify_cb(2, ctx))
-			return 0;
-		}
+    if (ctx->param->flags & X509_V_FLAG_NOTIFY_POLICY) {
+        ctx->current_cert = NULL;
+        /*
+         * Verification errors need to be "sticky", a callback may have allowed
+         * an SSL handshake to continue despite an error, and we must then
+         * remain in an error state.  Therefore, we MUST NOT clear earlier
+         * verification errors by setting the error to X509_V_OK.
+         */
+        if (!ctx->verify_cb(2, ctx))
+            return 0;
+    }
 
-	return 1;
-	}
+    return 1;
+}
 
 static int check_cert_time(X509_STORE_CTX *ctx, X509 *x)
-	{
-	time_t *ptime;
-	int i;
+{
+    time_t *ptime;
+    int i;
 
-	if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME)
-		ptime = &ctx->param->check_time;
-	else
-		ptime = NULL;
+    if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME)
+        ptime = &ctx->param->check_time;
+    else
+        ptime = NULL;
 
-	i=X509_cmp_time(X509_get_notBefore(x), ptime);
-	if (i == 0)
-		{
-		ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD;
-		ctx->current_cert=x;
-		if (!ctx->verify_cb(0, ctx))
-			return 0;
-		}
+    i = X509_cmp_time(X509_get_notBefore(x), ptime);
+    if (i == 0) {
+        ctx->error = X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD;
+        ctx->current_cert = x;
+        if (!ctx->verify_cb(0, ctx))
+            return 0;
+    }
 
-	if (i > 0)
-		{
-		ctx->error=X509_V_ERR_CERT_NOT_YET_VALID;
-		ctx->current_cert=x;
-		if (!ctx->verify_cb(0, ctx))
-			return 0;
-		}
+    if (i > 0) {
+        ctx->error = X509_V_ERR_CERT_NOT_YET_VALID;
+        ctx->current_cert = x;
+        if (!ctx->verify_cb(0, ctx))
+            return 0;
+    }
 
-	i=X509_cmp_time(X509_get_notAfter(x), ptime);
-	if (i == 0)
-		{
-		ctx->error=X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD;
-		ctx->current_cert=x;
-		if (!ctx->verify_cb(0, ctx))
-			return 0;
-		}
+    i = X509_cmp_time(X509_get_notAfter(x), ptime);
+    if (i == 0) {
+        ctx->error = X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD;
+        ctx->current_cert = x;
+        if (!ctx->verify_cb(0, ctx))
+            return 0;
+    }
 
-	if (i < 0)
-		{
-		ctx->error=X509_V_ERR_CERT_HAS_EXPIRED;
-		ctx->current_cert=x;
-		if (!ctx->verify_cb(0, ctx))
-			return 0;
-		}
+    if (i < 0) {
+        ctx->error = X509_V_ERR_CERT_HAS_EXPIRED;
+        ctx->current_cert = x;
+        if (!ctx->verify_cb(0, ctx))
+            return 0;
+    }
 
-	return 1;
-	}
+    return 1;
+}
 
 static int internal_verify(X509_STORE_CTX *ctx)
-	{
-	int ok=0,n;
-	X509 *xs,*xi;
-	EVP_PKEY *pkey=NULL;
-	int (*cb)(int xok,X509_STORE_CTX *xctx);
+{
+    int ok = 0, n;
+    X509 *xs, *xi;
+    EVP_PKEY *pkey = NULL;
+    int (*cb) (int xok, X509_STORE_CTX *xctx);
 
-	cb=ctx->verify_cb;
+    cb = ctx->verify_cb;
 
-	n=sk_X509_num(ctx->chain);
-	ctx->error_depth=n-1;
-	n--;
-	xi=sk_X509_value(ctx->chain,n);
+    n = sk_X509_num(ctx->chain);
+    ctx->error_depth = n - 1;
+    n--;
+    xi = sk_X509_value(ctx->chain, n);
 
-	if (ctx->check_issued(ctx, xi, xi))
-		xs=xi;
-	else
-		{
-		if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN)
-			{
-			xs = xi;
-			goto check_cert;
-			}
-		if (n <= 0)
-			{
-			ctx->error=X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE;
-			ctx->current_cert=xi;
-			ok=cb(0,ctx);
-			goto end;
-			}
-		else
-			{
-			n--;
-			ctx->error_depth=n;
-			xs=sk_X509_value(ctx->chain,n);
-			}
-		}
+    if (ctx->check_issued(ctx, xi, xi))
+        xs = xi;
+    else {
+        if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) {
+            xs = xi;
+            goto check_cert;
+        }
+        if (n <= 0) {
+            ctx->error = X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE;
+            ctx->current_cert = xi;
+            ok = cb(0, ctx);
+            goto end;
+        } else {
+            n--;
+            ctx->error_depth = n;
+            xs = sk_X509_value(ctx->chain, n);
+        }
+    }
 
-/*	ctx->error=0;  not needed */
-	while (n >= 0)
-		{
-		ctx->error_depth=n;
+/*      ctx->error=0;  not needed */
+    while (n >= 0) {
+        ctx->error_depth = n;
 
-		/* Skip signature check for self signed certificates unless
-		 * explicitly asked for. It doesn't add any security and
-		 * just wastes time.
-		 */
-		if (!xs->valid && (xs != xi || (ctx->param->flags & X509_V_FLAG_CHECK_SS_SIGNATURE)))
-			{
-			if ((pkey=X509_get_pubkey(xi)) == NULL)
-				{
-				ctx->error=X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
-				ctx->current_cert=xi;
-				ok=(*cb)(0,ctx);
-				if (!ok) goto end;
-				}
-			else if (X509_verify(xs,pkey) <= 0)
-				{
-				ctx->error=X509_V_ERR_CERT_SIGNATURE_FAILURE;
-				ctx->current_cert=xs;
-				ok=(*cb)(0,ctx);
-				if (!ok)
-					{
-					EVP_PKEY_free(pkey);
-					goto end;
-					}
-				}
-			EVP_PKEY_free(pkey);
-			pkey=NULL;
-			}
+        /*
+         * Skip signature check for self signed certificates unless
+         * explicitly asked for. It doesn't add any security and just wastes
+         * time.
+         */
+        if (xs != xi || (ctx->param->flags & X509_V_FLAG_CHECK_SS_SIGNATURE)) {
+            if ((pkey = X509_get_pubkey(xi)) == NULL) {
+                ctx->error = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
+                ctx->current_cert = xi;
+                ok = (*cb) (0, ctx);
+                if (!ok)
+                    goto end;
+            } else if (X509_verify(xs, pkey) <= 0) {
+                ctx->error = X509_V_ERR_CERT_SIGNATURE_FAILURE;
+                ctx->current_cert = xs;
+                ok = (*cb) (0, ctx);
+                if (!ok) {
+                    EVP_PKEY_free(pkey);
+                    goto end;
+                }
+            }
+            EVP_PKEY_free(pkey);
+            pkey = NULL;
+        }
 
-		xs->valid = 1;
+ check_cert:
+        ok = check_cert_time(ctx, xs);
+        if (!ok)
+            goto end;
 
-		check_cert:
-		ok = check_cert_time(ctx, xs);
-		if (!ok)
-			goto end;
+        /* The last error (if any) is still in the error value */
+        ctx->current_issuer = xi;
+        ctx->current_cert = xs;
+        ok = (*cb) (1, ctx);
+        if (!ok)
+            goto end;
 
-		/* The last error (if any) is still in the error value */
-		ctx->current_issuer=xi;
-		ctx->current_cert=xs;
-		ok=(*cb)(1,ctx);
-		if (!ok) goto end;
-
-		n--;
-		if (n >= 0)
-			{
-			xi=xs;
-			xs=sk_X509_value(ctx->chain,n);
-			}
-		}
-	ok=1;
-end:
-	return ok;
-	}
+        n--;
+        if (n >= 0) {
+            xi = xs;
+            xs = sk_X509_value(ctx->chain, n);
+        }
+    }
+    ok = 1;
+ end:
+    return ok;
+}
 
 int X509_cmp_current_time(const ASN1_TIME *ctm)
 {
-	return X509_cmp_time(ctm, NULL);
+    return X509_cmp_time(ctm, NULL);
 }
 
 int X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time)
-	{
-	char *str;
-	ASN1_TIME atm;
-	long offset;
-	char buff1[24],buff2[24],*p;
-	int i, j, remaining;
+{
+    char *str;
+    ASN1_TIME atm;
+    long offset;
+    char buff1[24], buff2[24], *p;
+    int i, j, remaining;
 
-	p=buff1;
-	remaining = ctm->length;
-	str=(char *)ctm->data;
-	/* Note that the following (historical) code allows much more slack in
-	 * the time format than RFC5280. In RFC5280, the representation is
-	 * fixed:
-	 * UTCTime: YYMMDDHHMMSSZ
-	 * GeneralizedTime: YYYYMMDDHHMMSSZ */
-	if (ctm->type == V_ASN1_UTCTIME)
-		{
-		/* YYMMDDHHMM[SS]Z or YYMMDDHHMM[SS](+-)hhmm */
-		int min_length = sizeof("YYMMDDHHMMZ") - 1;
-		int max_length = sizeof("YYMMDDHHMMSS+hhmm") - 1;
-		if (remaining < min_length || remaining > max_length)
-			return 0;
-		memcpy(p,str,10);
-		p+=10;
-		str+=10;
-		remaining -= 10;
-		}
-	else
-		{
-		/* YYYYMMDDHHMM[SS[.fff]]Z or YYYYMMDDHHMM[SS[.f[f[f]]]](+-)hhmm */
-		int min_length = sizeof("YYYYMMDDHHMMZ") - 1;
-		int max_length = sizeof("YYYYMMDDHHMMSS.fff+hhmm") - 1;
-		if (remaining < min_length || remaining > max_length)
-			return 0;
-		memcpy(p,str,12);
-		p+=12;
-		str+=12;
-		remaining -= 12;
-		}
+    p = buff1;
+    remaining = ctm->length;
+    str = (char *)ctm->data;
+    /*
+     * Note that the following (historical) code allows much more slack in
+     * the time format than RFC5280. In RFC5280, the representation is fixed:
+     * UTCTime: YYMMDDHHMMSSZ GeneralizedTime: YYYYMMDDHHMMSSZ
+     */
+    if (ctm->type == V_ASN1_UTCTIME) {
+        /* YYMMDDHHMM[SS]Z or YYMMDDHHMM[SS](+-)hhmm */
+        int min_length = sizeof("YYMMDDHHMMZ") - 1;
+        int max_length = sizeof("YYMMDDHHMMSS+hhmm") - 1;
+        if (remaining < min_length || remaining > max_length)
+            return 0;
+        OPENSSL_memcpy(p, str, 10);
+        p += 10;
+        str += 10;
+        remaining -= 10;
+    } else {
+        /*
+         * YYYYMMDDHHMM[SS[.fff]]Z or YYYYMMDDHHMM[SS[.f[f[f]]]](+-)hhmm
+         */
+        int min_length = sizeof("YYYYMMDDHHMMZ") - 1;
+        int max_length = sizeof("YYYYMMDDHHMMSS.fff+hhmm") - 1;
+        if (remaining < min_length || remaining > max_length)
+            return 0;
+        OPENSSL_memcpy(p, str, 12);
+        p += 12;
+        str += 12;
+        remaining -= 12;
+    }
 
-	if ((*str == 'Z') || (*str == '-') || (*str == '+'))
-		{ *(p++)='0'; *(p++)='0'; }
-	else
-		{ 
-		/* SS (seconds) */
-		if (remaining < 2)
-			return 0;
-		*(p++)= *(str++);
-		*(p++)= *(str++);
-		remaining -= 2;
-		/* Skip any (up to three) fractional seconds...
-		 * TODO(emilia): in RFC5280, fractional seconds are forbidden.
-		 * Can we just kill them altogether? */
-		if (remaining && *str == '.')
-			{
-			str++;
-			remaining--;
-			for (i = 0; i < 3 && remaining; i++, str++, remaining--)
-				{
-				if (*str < '0' || *str > '9')
-					break;
-				}
-			}
-		
-		}
-	*(p++)='Z';
-	*(p++)='\0';
+    if ((*str == 'Z') || (*str == '-') || (*str == '+')) {
+        *(p++) = '0';
+        *(p++) = '0';
+    } else {
+        /* SS (seconds) */
+        if (remaining < 2)
+            return 0;
+        *(p++) = *(str++);
+        *(p++) = *(str++);
+        remaining -= 2;
+        /*
+         * Skip any (up to three) fractional seconds... TODO(emilia): in
+         * RFC5280, fractional seconds are forbidden. Can we just kill them
+         * altogether?
+         */
+        if (remaining && *str == '.') {
+            str++;
+            remaining--;
+            for (i = 0; i < 3 && remaining; i++, str++, remaining--) {
+                if (*str < '0' || *str > '9')
+                    break;
+            }
+        }
 
-	/* We now need either a terminating 'Z' or an offset. */
-	if (!remaining)
-		return 0;
-	if (*str == 'Z')
-		{
-		if (remaining != 1)
-			return 0;
-		offset=0;
-		}
-	else
-		{
-		/* (+-)HHMM */
-		if ((*str != '+') && (*str != '-'))
-			return 0;
-		/* Historical behaviour: the (+-)hhmm offset is forbidden in RFC5280. */
-		if (remaining != 5)
-			return 0;
-		if (str[1] < '0' || str[1] > '9' || str[2] < '0' || str[2] > '9' ||
-			str[3] < '0' || str[3] > '9' || str[4] < '0' || str[4] > '9')
-			return 0;
-		offset=((str[1]-'0')*10+(str[2]-'0'))*60;
-		offset+=(str[3]-'0')*10+(str[4]-'0');
-		if (*str == '-')
-			offset= -offset;
-		}
-	atm.type=ctm->type;
-	atm.flags = 0;
-	atm.length=sizeof(buff2);
-	atm.data=(unsigned char *)buff2;
+    }
+    *(p++) = 'Z';
+    *(p++) = '\0';
 
-	if (X509_time_adj(&atm, offset*60, cmp_time) == NULL)
-		return 0;
+    /* We now need either a terminating 'Z' or an offset. */
+    if (!remaining)
+        return 0;
+    if (*str == 'Z') {
+        if (remaining != 1)
+            return 0;
+        offset = 0;
+    } else {
+        /* (+-)HHMM */
+        if ((*str != '+') && (*str != '-'))
+            return 0;
+        /*
+         * Historical behaviour: the (+-)hhmm offset is forbidden in RFC5280.
+         */
+        if (remaining != 5)
+            return 0;
+        if (str[1] < '0' || str[1] > '9' || str[2] < '0' || str[2] > '9' ||
+            str[3] < '0' || str[3] > '9' || str[4] < '0' || str[4] > '9')
+            return 0;
+        offset = ((str[1] - '0') * 10 + (str[2] - '0')) * 60;
+        offset += (str[3] - '0') * 10 + (str[4] - '0');
+        if (*str == '-')
+            offset = -offset;
+    }
+    atm.type = ctm->type;
+    atm.flags = 0;
+    atm.length = sizeof(buff2);
+    atm.data = (unsigned char *)buff2;
 
-	if (ctm->type == V_ASN1_UTCTIME)
-		{
-		i=(buff1[0]-'0')*10+(buff1[1]-'0');
-		if (i < 50) i+=100; /* cf. RFC 2459 */
-		j=(buff2[0]-'0')*10+(buff2[1]-'0');
-		if (j < 50) j+=100;
+    if (X509_time_adj(&atm, offset * 60, cmp_time) == NULL)
+        return 0;
 
-		if (i < j) return -1;
-		if (i > j) return 1;
-		}
-	i=strcmp(buff1,buff2);
-	if (i == 0) /* wait a second then return younger :-) */
-		return -1;
-	else
-		return i;
-	}
+    if (ctm->type == V_ASN1_UTCTIME) {
+        i = (buff1[0] - '0') * 10 + (buff1[1] - '0');
+        if (i < 50)
+            i += 100;           /* cf. RFC 2459 */
+        j = (buff2[0] - '0') * 10 + (buff2[1] - '0');
+        if (j < 50)
+            j += 100;
+
+        if (i < j)
+            return -1;
+        if (i > j)
+            return 1;
+    }
+    i = strcmp(buff1, buff2);
+    if (i == 0)                 /* wait a second then return younger :-) */
+        return -1;
+    else
+        return i;
+}
 
 ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long adj)
 {
-	return X509_time_adj(s, adj, NULL);
+    return X509_time_adj(s, adj, NULL);
 }
 
 ASN1_TIME *X509_time_adj(ASN1_TIME *s, long offset_sec, time_t *in_tm)
-	{
-	return X509_time_adj_ex(s, 0, offset_sec, in_tm);
-	}
+{
+    return X509_time_adj_ex(s, 0, offset_sec, in_tm);
+}
 
 ASN1_TIME *X509_time_adj_ex(ASN1_TIME *s,
-				int offset_day, long offset_sec, time_t *in_tm)
-	{
-	time_t t = 0;
+                            int offset_day, long offset_sec, time_t *in_tm)
+{
+    time_t t = 0;
 
-	if (in_tm) t = *in_tm;
-	else time(&t);
+    if (in_tm)
+        t = *in_tm;
+    else
+        time(&t);
 
-	if (s && !(s->flags & ASN1_STRING_FLAG_MSTRING))
-		{
-		if (s->type == V_ASN1_UTCTIME)
-			return ASN1_UTCTIME_adj(s,t, offset_day, offset_sec);
-		if (s->type == V_ASN1_GENERALIZEDTIME)
-			return ASN1_GENERALIZEDTIME_adj(s, t, offset_day,
-								offset_sec);
-		}
-	return ASN1_TIME_adj(s, t, offset_day, offset_sec);
-	}
+    if (s && !(s->flags & ASN1_STRING_FLAG_MSTRING)) {
+        if (s->type == V_ASN1_UTCTIME)
+            return ASN1_UTCTIME_adj(s, t, offset_day, offset_sec);
+        if (s->type == V_ASN1_GENERALIZEDTIME)
+            return ASN1_GENERALIZEDTIME_adj(s, t, offset_day, offset_sec);
+    }
+    return ASN1_TIME_adj(s, t, offset_day, offset_sec);
+}
 
 /* Make a delta CRL as the diff between two full CRLs */
 
 X509_CRL *X509_CRL_diff(X509_CRL *base, X509_CRL *newer,
-			EVP_PKEY *skey, const EVP_MD *md, unsigned int flags)
-	{
-	X509_CRL *crl = NULL;
-	int i;
-	size_t j;
-	STACK_OF(X509_REVOKED) *revs = NULL;
-	/* CRLs can't be delta already */
-	if (base->base_crl_number || newer->base_crl_number)
-			{
-			OPENSSL_PUT_ERROR(X509, X509_R_CRL_ALREADY_DELTA);
-			return NULL;
-			}
-	/* Base and new CRL must have a CRL number */
-	if (!base->crl_number || !newer->crl_number)
-			{
-			OPENSSL_PUT_ERROR(X509, X509_R_NO_CRL_NUMBER);
-			return NULL;
-			}
-	/* Issuer names must match */
-	if (X509_NAME_cmp(X509_CRL_get_issuer(base),
-				X509_CRL_get_issuer(newer)))
-			{
-			OPENSSL_PUT_ERROR(X509, X509_R_ISSUER_MISMATCH);
-			return NULL;
-			}
-	/* AKID and IDP must match */
-	if (!crl_extension_match(base, newer, NID_authority_key_identifier))
-			{
-			OPENSSL_PUT_ERROR(X509, X509_R_AKID_MISMATCH);
-			return NULL;
-			}
-	if (!crl_extension_match(base, newer, NID_issuing_distribution_point))
-			{
-			OPENSSL_PUT_ERROR(X509, X509_R_IDP_MISMATCH);
-			return NULL;
-			}
-	/* Newer CRL number must exceed full CRL number */
-	if (ASN1_INTEGER_cmp(newer->crl_number, base->crl_number) <= 0)
-			{
-			OPENSSL_PUT_ERROR(X509, X509_R_NEWER_CRL_NOT_NEWER);
-			return NULL;
-			}
-	/* CRLs must verify */
-	if (skey && (X509_CRL_verify(base, skey) <= 0 ||
-			X509_CRL_verify(newer, skey) <= 0))
-		{
-		OPENSSL_PUT_ERROR(X509, X509_R_CRL_VERIFY_FAILURE);
-		return NULL;
-		}
-	/* Create new CRL */
-	crl = X509_CRL_new();
-	if (!crl || !X509_CRL_set_version(crl, 1))
-		goto memerr;
-	/* Set issuer name */
-	if (!X509_CRL_set_issuer_name(crl, X509_CRL_get_issuer(newer)))
-		goto memerr;
+                        EVP_PKEY *skey, const EVP_MD *md, unsigned int flags)
+{
+    X509_CRL *crl = NULL;
+    int i;
+    size_t j;
+    STACK_OF(X509_REVOKED) *revs = NULL;
+    /* CRLs can't be delta already */
+    if (base->base_crl_number || newer->base_crl_number) {
+        OPENSSL_PUT_ERROR(X509, X509_R_CRL_ALREADY_DELTA);
+        return NULL;
+    }
+    /* Base and new CRL must have a CRL number */
+    if (!base->crl_number || !newer->crl_number) {
+        OPENSSL_PUT_ERROR(X509, X509_R_NO_CRL_NUMBER);
+        return NULL;
+    }
+    /* Issuer names must match */
+    if (X509_NAME_cmp(X509_CRL_get_issuer(base), X509_CRL_get_issuer(newer))) {
+        OPENSSL_PUT_ERROR(X509, X509_R_ISSUER_MISMATCH);
+        return NULL;
+    }
+    /* AKID and IDP must match */
+    if (!crl_extension_match(base, newer, NID_authority_key_identifier)) {
+        OPENSSL_PUT_ERROR(X509, X509_R_AKID_MISMATCH);
+        return NULL;
+    }
+    if (!crl_extension_match(base, newer, NID_issuing_distribution_point)) {
+        OPENSSL_PUT_ERROR(X509, X509_R_IDP_MISMATCH);
+        return NULL;
+    }
+    /* Newer CRL number must exceed full CRL number */
+    if (ASN1_INTEGER_cmp(newer->crl_number, base->crl_number) <= 0) {
+        OPENSSL_PUT_ERROR(X509, X509_R_NEWER_CRL_NOT_NEWER);
+        return NULL;
+    }
+    /* CRLs must verify */
+    if (skey && (X509_CRL_verify(base, skey) <= 0 ||
+                 X509_CRL_verify(newer, skey) <= 0)) {
+        OPENSSL_PUT_ERROR(X509, X509_R_CRL_VERIFY_FAILURE);
+        return NULL;
+    }
+    /* Create new CRL */
+    crl = X509_CRL_new();
+    if (!crl || !X509_CRL_set_version(crl, 1))
+        goto memerr;
+    /* Set issuer name */
+    if (!X509_CRL_set_issuer_name(crl, X509_CRL_get_issuer(newer)))
+        goto memerr;
 
-	if (!X509_CRL_set_lastUpdate(crl, X509_CRL_get_lastUpdate(newer)))
-		goto memerr;
-	if (!X509_CRL_set_nextUpdate(crl, X509_CRL_get_nextUpdate(newer)))
-		goto memerr;
+    if (!X509_CRL_set_lastUpdate(crl, X509_CRL_get_lastUpdate(newer)))
+        goto memerr;
+    if (!X509_CRL_set_nextUpdate(crl, X509_CRL_get_nextUpdate(newer)))
+        goto memerr;
 
-	/* Set base CRL number: must be critical */
+    /* Set base CRL number: must be critical */
 
-	if (!X509_CRL_add1_ext_i2d(crl, NID_delta_crl, base->crl_number, 1, 0))
-		goto memerr;
+    if (!X509_CRL_add1_ext_i2d(crl, NID_delta_crl, base->crl_number, 1, 0))
+        goto memerr;
 
-	/* Copy extensions across from newest CRL to delta: this will set
-	 * CRL number to correct value too.
-	 */
+    /*
+     * Copy extensions across from newest CRL to delta: this will set CRL
+     * number to correct value too.
+     */
 
-	for (i = 0; i < X509_CRL_get_ext_count(newer); i++)
-		{
-		X509_EXTENSION *ext;
-		ext = X509_CRL_get_ext(newer, i);
-		if (!X509_CRL_add_ext(crl, ext, -1))
-			goto memerr;
-		}
+    for (i = 0; i < X509_CRL_get_ext_count(newer); i++) {
+        X509_EXTENSION *ext;
+        ext = X509_CRL_get_ext(newer, i);
+        if (!X509_CRL_add_ext(crl, ext, -1))
+            goto memerr;
+    }
 
-	/* Go through revoked entries, copying as needed */
+    /* Go through revoked entries, copying as needed */
 
-	revs = X509_CRL_get_REVOKED(newer);
+    revs = X509_CRL_get_REVOKED(newer);
 
-	for (j = 0; j < sk_X509_REVOKED_num(revs); j++)
-		{
-		X509_REVOKED *rvn, *rvtmp;
-		rvn = sk_X509_REVOKED_value(revs, j);
-		/* Add only if not also in base.
-		 * TODO: need something cleverer here for some more complex
-		 * CRLs covering multiple CAs.
-		 */
-		if (!X509_CRL_get0_by_serial(base, &rvtmp, rvn->serialNumber))
-			{
-			rvtmp = X509_REVOKED_dup(rvn);
-			if (!rvtmp)
-				goto memerr;
-			if (!X509_CRL_add0_revoked(crl, rvtmp))
-				{
-				X509_REVOKED_free(rvtmp);
-				goto memerr;
-				}
-			}
-		}
-	/* TODO: optionally prune deleted entries */
+    for (j = 0; j < sk_X509_REVOKED_num(revs); j++) {
+        X509_REVOKED *rvn, *rvtmp;
+        rvn = sk_X509_REVOKED_value(revs, j);
+        /*
+         * Add only if not also in base. TODO: need something cleverer here
+         * for some more complex CRLs covering multiple CAs.
+         */
+        if (!X509_CRL_get0_by_serial(base, &rvtmp, rvn->serialNumber)) {
+            rvtmp = X509_REVOKED_dup(rvn);
+            if (!rvtmp)
+                goto memerr;
+            if (!X509_CRL_add0_revoked(crl, rvtmp)) {
+                X509_REVOKED_free(rvtmp);
+                goto memerr;
+            }
+        }
+    }
+    /* TODO: optionally prune deleted entries */
 
-	if (skey && md && !X509_CRL_sign(crl, skey, md))
-		goto memerr;
-	
-	return crl;
+    if (skey && md && !X509_CRL_sign(crl, skey, md))
+        goto memerr;
 
-	memerr:
-	OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-	if (crl)
-		X509_CRL_free(crl);
-	return NULL;
-	}
+    return crl;
 
-int X509_STORE_CTX_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused,
-	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
-	{
-	/* This function is (usually) called only once, by
-	 * SSL_get_ex_data_X509_STORE_CTX_idx (ssl/ssl_cert.c). */
-	int index;
-	if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp,
-			dup_func, free_func))
-		{
-		return -1;
-		}
-	return index;
-	}
+ memerr:
+    OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+    if (crl)
+        X509_CRL_free(crl);
+    return NULL;
+}
+
+int X509_STORE_CTX_get_ex_new_index(long argl, void *argp,
+                                    CRYPTO_EX_unused * unused,
+                                    CRYPTO_EX_dup *dup_func,
+                                    CRYPTO_EX_free *free_func)
+{
+    /*
+     * This function is (usually) called only once, by
+     * SSL_get_ex_data_X509_STORE_CTX_idx (ssl/ssl_cert.c).
+     */
+    int index;
+    if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp,
+                                 dup_func, free_func)) {
+        return -1;
+    }
+    return index;
+}
 
 int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data)
-	{
-	return CRYPTO_set_ex_data(&ctx->ex_data,idx,data);
-	}
+{
+    return CRYPTO_set_ex_data(&ctx->ex_data, idx, data);
+}
 
 void *X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx, int idx)
-	{
-	return CRYPTO_get_ex_data(&ctx->ex_data,idx);
-	}
+{
+    return CRYPTO_get_ex_data(&ctx->ex_data, idx);
+}
 
 int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx)
-	{
-	return ctx->error;
-	}
+{
+    return ctx->error;
+}
 
 void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int err)
-	{
-	ctx->error=err;
-	}
+{
+    ctx->error = err;
+}
 
 int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx)
-	{
-	return ctx->error_depth;
-	}
+{
+    return ctx->error_depth;
+}
 
 X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx)
-	{
-	return ctx->current_cert;
-	}
+{
+    return ctx->current_cert;
+}
 
 STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx)
-	{
-	return ctx->chain;
-	}
+{
+    return ctx->chain;
+}
 
 STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx)
-	{
-	if (!ctx->chain)
-		return NULL;
-	return X509_chain_up_ref(ctx->chain);
-	}
+{
+    if (!ctx->chain)
+        return NULL;
+    return X509_chain_up_ref(ctx->chain);
+}
 
 X509 *X509_STORE_CTX_get0_current_issuer(X509_STORE_CTX *ctx)
-	{
-	return ctx->current_issuer;
-	}
+{
+    return ctx->current_issuer;
+}
 
 X509_CRL *X509_STORE_CTX_get0_current_crl(X509_STORE_CTX *ctx)
-	{
-	return ctx->current_crl;
-	}
+{
+    return ctx->current_crl;
+}
 
 X509_STORE_CTX *X509_STORE_CTX_get0_parent_ctx(X509_STORE_CTX *ctx)
-	{
-	return ctx->parent;
-	}
+{
+    return ctx->parent;
+}
 
 void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *x)
-	{
-	ctx->cert=x;
-	}
+{
+    ctx->cert = x;
+}
 
 void X509_STORE_CTX_set_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk)
-	{
-	ctx->untrusted=sk;
-	}
+{
+    ctx->untrusted = sk;
+}
 
 void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk)
-	{
-	ctx->crls=sk;
-	}
+{
+    ctx->crls = sk;
+}
 
 int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose)
-	{
-	return X509_STORE_CTX_purpose_inherit(ctx, 0, purpose, 0);
-	}
+{
+    return X509_STORE_CTX_purpose_inherit(ctx, 0, purpose, 0);
+}
 
 int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust)
-	{
-	return X509_STORE_CTX_purpose_inherit(ctx, 0, 0, trust);
-	}
+{
+    return X509_STORE_CTX_purpose_inherit(ctx, 0, 0, trust);
+}
 
-/* This function is used to set the X509_STORE_CTX purpose and trust
- * values. This is intended to be used when another structure has its
- * own trust and purpose values which (if set) will be inherited by
- * the ctx. If they aren't set then we will usually have a default
- * purpose in mind which should then be used to set the trust value.
- * An example of this is SSL use: an SSL structure will have its own
- * purpose and trust settings which the application can set: if they
- * aren't set then we use the default of SSL client/server.
+/*
+ * This function is used to set the X509_STORE_CTX purpose and trust values.
+ * This is intended to be used when another structure has its own trust and
+ * purpose values which (if set) will be inherited by the ctx. If they aren't
+ * set then we will usually have a default purpose in mind which should then
+ * be used to set the trust value. An example of this is SSL use: an SSL
+ * structure will have its own purpose and trust settings which the
+ * application can set: if they aren't set then we use the default of SSL
+ * client/server.
  */
 
 int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose,
-				int purpose, int trust)
+                                   int purpose, int trust)
 {
-	int idx;
-	/* If purpose not set use default */
-	if (!purpose) purpose = def_purpose;
-	/* If we have a purpose then check it is valid */
-	if (purpose)
-		{
-		X509_PURPOSE *ptmp;
-		idx = X509_PURPOSE_get_by_id(purpose);
-		if (idx == -1)
-			{
-			OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_PURPOSE_ID);
-			return 0;
-			}
-		ptmp = X509_PURPOSE_get0(idx);
-		if (ptmp->trust == X509_TRUST_DEFAULT)
-			{
-			idx = X509_PURPOSE_get_by_id(def_purpose);
-			if (idx == -1)
-				{
-				OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_PURPOSE_ID);
-				return 0;
-				}
-			ptmp = X509_PURPOSE_get0(idx);
-			}
-		/* If trust not set then get from purpose default */
-		if (!trust) trust = ptmp->trust;
-		}
-	if (trust)
-		{
-		idx = X509_TRUST_get_by_id(trust);
-		if (idx == -1)
-			{
-			OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_TRUST_ID);
-			return 0;
-			}
-		}
+    int idx;
+    /* If purpose not set use default */
+    if (!purpose)
+        purpose = def_purpose;
+    /* If we have a purpose then check it is valid */
+    if (purpose) {
+        X509_PURPOSE *ptmp;
+        idx = X509_PURPOSE_get_by_id(purpose);
+        if (idx == -1) {
+            OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_PURPOSE_ID);
+            return 0;
+        }
+        ptmp = X509_PURPOSE_get0(idx);
+        if (ptmp->trust == X509_TRUST_DEFAULT) {
+            idx = X509_PURPOSE_get_by_id(def_purpose);
+            if (idx == -1) {
+                OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_PURPOSE_ID);
+                return 0;
+            }
+            ptmp = X509_PURPOSE_get0(idx);
+        }
+        /* If trust not set then get from purpose default */
+        if (!trust)
+            trust = ptmp->trust;
+    }
+    if (trust) {
+        idx = X509_TRUST_get_by_id(trust);
+        if (idx == -1) {
+            OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_TRUST_ID);
+            return 0;
+        }
+    }
 
-	if (purpose && !ctx->param->purpose) ctx->param->purpose = purpose;
-	if (trust && !ctx->param->trust) ctx->param->trust = trust;
-	return 1;
+    if (purpose && !ctx->param->purpose)
+        ctx->param->purpose = purpose;
+    if (trust && !ctx->param->trust)
+        ctx->param->trust = trust;
+    return 1;
 }
 
 X509_STORE_CTX *X509_STORE_CTX_new(void)
 {
-	X509_STORE_CTX *ctx;
-	ctx = (X509_STORE_CTX *)OPENSSL_malloc(sizeof(X509_STORE_CTX));
-	if (!ctx)
-		{
-		OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-		return NULL;
-		}
-	memset(ctx, 0, sizeof(X509_STORE_CTX));
-	return ctx;
+    X509_STORE_CTX *ctx;
+    ctx = (X509_STORE_CTX *)OPENSSL_malloc(sizeof(X509_STORE_CTX));
+    if (!ctx) {
+        OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+    OPENSSL_memset(ctx, 0, sizeof(X509_STORE_CTX));
+    return ctx;
 }
 
 void X509_STORE_CTX_free(X509_STORE_CTX *ctx)
 {
-	X509_STORE_CTX_cleanup(ctx);
-	OPENSSL_free(ctx);
+    if (ctx == NULL) {
+        return;
+    }
+    X509_STORE_CTX_cleanup(ctx);
+    OPENSSL_free(ctx);
 }
 
 int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
-	     STACK_OF(X509) *chain)
-	{
-	int ret = 1;
+                        STACK_OF(X509) *chain)
+{
+    int ret = 1;
 
-	memset(ctx, 0, sizeof(X509_STORE_CTX));
-	ctx->ctx=store;
-	ctx->cert=x509;
-	ctx->untrusted=chain;
+    OPENSSL_memset(ctx, 0, sizeof(X509_STORE_CTX));
+    ctx->ctx = store;
+    ctx->cert = x509;
+    ctx->untrusted = chain;
 
-	CRYPTO_new_ex_data(&ctx->ex_data);
+    CRYPTO_new_ex_data(&ctx->ex_data);
 
-	ctx->param = X509_VERIFY_PARAM_new();
-	if (!ctx->param)
-		goto err;
+    ctx->param = X509_VERIFY_PARAM_new();
+    if (!ctx->param)
+        goto err;
 
-	/* Inherit callbacks and flags from X509_STORE if not set
-	 * use defaults. */
+    /*
+     * Inherit callbacks and flags from X509_STORE if not set use defaults.
+     */
 
-	if (store)
-		ret = X509_VERIFY_PARAM_inherit(ctx->param, store->param);
-	else
-		ctx->param->inh_flags |= X509_VP_FLAG_DEFAULT|X509_VP_FLAG_ONCE;
+    if (store)
+        ret = X509_VERIFY_PARAM_inherit(ctx->param, store->param);
+    else
+        ctx->param->inh_flags |= X509_VP_FLAG_DEFAULT | X509_VP_FLAG_ONCE;
 
-	if (store)
-		{
-		ctx->verify_cb = store->verify_cb;
-		ctx->cleanup = store->cleanup;
-		}
-	else
-		ctx->cleanup = 0;
+    if (store) {
+        ctx->verify_cb = store->verify_cb;
+        ctx->cleanup = store->cleanup;
+    } else
+        ctx->cleanup = 0;
 
-	if (ret)
-		ret = X509_VERIFY_PARAM_inherit(ctx->param,
-					X509_VERIFY_PARAM_lookup("default"));
+    if (ret)
+        ret = X509_VERIFY_PARAM_inherit(ctx->param,
+                                        X509_VERIFY_PARAM_lookup("default"));
 
-	if (ret == 0)
-		goto err;
+    if (ret == 0)
+        goto err;
 
-	if (store && store->check_issued)
-		ctx->check_issued = store->check_issued;
-	else
-		ctx->check_issued = check_issued;
+    if (store && store->check_issued)
+        ctx->check_issued = store->check_issued;
+    else
+        ctx->check_issued = check_issued;
 
-	if (store && store->get_issuer)
-		ctx->get_issuer = store->get_issuer;
-	else
-		ctx->get_issuer = X509_STORE_CTX_get1_issuer;
+    if (store && store->get_issuer)
+        ctx->get_issuer = store->get_issuer;
+    else
+        ctx->get_issuer = X509_STORE_CTX_get1_issuer;
 
-	if (store && store->verify_cb)
-		ctx->verify_cb = store->verify_cb;
-	else
-		ctx->verify_cb = null_callback;
+    if (store && store->verify_cb)
+        ctx->verify_cb = store->verify_cb;
+    else
+        ctx->verify_cb = null_callback;
 
-	if (store && store->verify)
-		ctx->verify = store->verify;
-	else
-		ctx->verify = internal_verify;
+    if (store && store->verify)
+        ctx->verify = store->verify;
+    else
+        ctx->verify = internal_verify;
 
-	if (store && store->check_revocation)
-		ctx->check_revocation = store->check_revocation;
-	else
-		ctx->check_revocation = check_revocation;
+    if (store && store->check_revocation)
+        ctx->check_revocation = store->check_revocation;
+    else
+        ctx->check_revocation = check_revocation;
 
-	if (store && store->get_crl)
-		ctx->get_crl = store->get_crl;
-	else
-		ctx->get_crl = NULL;
+    if (store && store->get_crl)
+        ctx->get_crl = store->get_crl;
+    else
+        ctx->get_crl = NULL;
 
-	if (store && store->check_crl)
-		ctx->check_crl = store->check_crl;
-	else
-		ctx->check_crl = check_crl;
+    if (store && store->check_crl)
+        ctx->check_crl = store->check_crl;
+    else
+        ctx->check_crl = check_crl;
 
-	if (store && store->cert_crl)
-		ctx->cert_crl = store->cert_crl;
-	else
-		ctx->cert_crl = cert_crl;
+    if (store && store->cert_crl)
+        ctx->cert_crl = store->cert_crl;
+    else
+        ctx->cert_crl = cert_crl;
 
-	if (store && store->lookup_certs)
-		ctx->lookup_certs = store->lookup_certs;
-	else
-		ctx->lookup_certs = X509_STORE_get1_certs;
+    if (store && store->lookup_certs)
+        ctx->lookup_certs = store->lookup_certs;
+    else
+        ctx->lookup_certs = X509_STORE_get1_certs;
 
-	if (store && store->lookup_crls)
-		ctx->lookup_crls = store->lookup_crls;
-	else
-		ctx->lookup_crls = X509_STORE_get1_crls;
+    if (store && store->lookup_crls)
+        ctx->lookup_crls = store->lookup_crls;
+    else
+        ctx->lookup_crls = X509_STORE_get1_crls;
 
-	ctx->check_policy = check_policy;
+    ctx->check_policy = check_policy;
 
-	return 1;
+    return 1;
 
-err:
-	CRYPTO_free_ex_data(&g_ex_data_class, ctx, &ctx->ex_data);
-	if (ctx->param != NULL)
-		{
-		X509_VERIFY_PARAM_free(ctx->param);
-		}
+ err:
+    CRYPTO_free_ex_data(&g_ex_data_class, ctx, &ctx->ex_data);
+    if (ctx->param != NULL) {
+        X509_VERIFY_PARAM_free(ctx->param);
+    }
 
-	memset(ctx, 0, sizeof(X509_STORE_CTX));
-	OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-	return 0;
-	}
+    OPENSSL_memset(ctx, 0, sizeof(X509_STORE_CTX));
+    OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+    return 0;
+}
 
-/* Set alternative lookup method: just a STACK of trusted certificates.
- * This avoids X509_STORE nastiness where it isn't needed.
+/*
+ * Set alternative lookup method: just a STACK of trusted certificates. This
+ * avoids X509_STORE nastiness where it isn't needed.
  */
 
 void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk)
 {
-	ctx->other_ctx = sk;
-	ctx->get_issuer = get_issuer_sk;
+    ctx->other_ctx = sk;
+    ctx->get_issuer = get_issuer_sk;
 }
 
 void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx)
-	{
-	if (ctx->cleanup) ctx->cleanup(ctx);
-	if (ctx->param != NULL)
-		{
-		if (ctx->parent == NULL)
-			X509_VERIFY_PARAM_free(ctx->param);
-		ctx->param=NULL;
-		}
-	if (ctx->tree != NULL)
-		{
-		X509_policy_tree_free(ctx->tree);
-		ctx->tree=NULL;
-		}
-	if (ctx->chain != NULL)
-		{
-		sk_X509_pop_free(ctx->chain,X509_free);
-		ctx->chain=NULL;
-		}
-	CRYPTO_free_ex_data(&g_ex_data_class, ctx, &(ctx->ex_data));
-	memset(&ctx->ex_data,0,sizeof(CRYPTO_EX_DATA));
-	}
+{
+    /* We need to be idempotent because, unfortunately, |X509_STORE_CTX_free|
+     * also calls this function. */
+    if (ctx->cleanup != NULL) {
+        ctx->cleanup(ctx);
+        ctx->cleanup = NULL;
+    }
+    if (ctx->param != NULL) {
+        if (ctx->parent == NULL)
+            X509_VERIFY_PARAM_free(ctx->param);
+        ctx->param = NULL;
+    }
+    if (ctx->tree != NULL) {
+        X509_policy_tree_free(ctx->tree);
+        ctx->tree = NULL;
+    }
+    if (ctx->chain != NULL) {
+        sk_X509_pop_free(ctx->chain, X509_free);
+        ctx->chain = NULL;
+    }
+    CRYPTO_free_ex_data(&g_ex_data_class, ctx, &(ctx->ex_data));
+    OPENSSL_memset(&ctx->ex_data, 0, sizeof(CRYPTO_EX_DATA));
+}
 
 void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth)
-	{
-	X509_VERIFY_PARAM_set_depth(ctx->param, depth);
-	}
+{
+    X509_VERIFY_PARAM_set_depth(ctx->param, depth);
+}
 
 void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, unsigned long flags)
-	{
-	X509_VERIFY_PARAM_set_flags(ctx->param, flags);
-	}
+{
+    X509_VERIFY_PARAM_set_flags(ctx->param, flags);
+}
 
-void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags, time_t t)
-	{
-	X509_VERIFY_PARAM_set_time(ctx->param, t);
-	}
+void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags,
+                             time_t t)
+{
+    X509_VERIFY_PARAM_set_time(ctx->param, t);
+}
 
 void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx,
-				  int (*verify_cb)(int, X509_STORE_CTX *))
-	{
-	ctx->verify_cb=verify_cb;
-	}
+                                  int (*verify_cb) (int, X509_STORE_CTX *))
+{
+    ctx->verify_cb = verify_cb;
+}
 
 X509_POLICY_TREE *X509_STORE_CTX_get0_policy_tree(X509_STORE_CTX *ctx)
-	{
-	return ctx->tree;
-	}
+{
+    return ctx->tree;
+}
 
 int X509_STORE_CTX_get_explicit_policy(X509_STORE_CTX *ctx)
-	{
-	return ctx->explicit_policy;
-	}
+{
+    return ctx->explicit_policy;
+}
 
 int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name)
-	{
-	const X509_VERIFY_PARAM *param;
-	param = X509_VERIFY_PARAM_lookup(name);
-	if (!param)
-		return 0;
-	return X509_VERIFY_PARAM_inherit(ctx->param, param);
-	}
+{
+    const X509_VERIFY_PARAM *param;
+    param = X509_VERIFY_PARAM_lookup(name);
+    if (!param)
+        return 0;
+    return X509_VERIFY_PARAM_inherit(ctx->param, param);
+}
 
 X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx)
-	{
-	return ctx->param;
-	}
+{
+    return ctx->param;
+}
 
 void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param)
-	{
-	if (ctx->param)
-		X509_VERIFY_PARAM_free(ctx->param);
-	ctx->param = param;
-	}
+{
+    if (ctx->param)
+        X509_VERIFY_PARAM_free(ctx->param);
+    ctx->param = param;
+}
 
 IMPLEMENT_ASN1_SET_OF(X509)
+
 IMPLEMENT_ASN1_SET_OF(X509_ATTRIBUTE)
diff --git a/src/crypto/x509/x509_vpm.c b/src/crypto/x509/x509_vpm.c
index 8c8f98e..2317214 100644
--- a/src/crypto/x509/x509_vpm.c
+++ b/src/crypto/x509/x509_vpm.c
@@ -1,5 +1,7 @@
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 2004. */
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 2004.
+ */
 /* ====================================================================
  * Copyright (c) 2004 The OpenSSL Project.  All rights reserved.
  *
@@ -8,7 +10,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -63,6 +65,7 @@
 #include <openssl/x509v3.h>
 
 #include "vpm_int.h"
+#include "../internal.h"
 
 
 /* X509_VERIFY_PARAM functions */
@@ -70,129 +73,129 @@
 #define SET_HOST 0
 #define ADD_HOST 1
 
-static char *str_copy(char *s) { return OPENSSL_strdup(s); }
-static void str_free(char *s) { OPENSSL_free(s); }
+static char *str_copy(char *s)
+{
+    return OPENSSL_strdup(s);
+}
+
+static void str_free(char *s)
+{
+    OPENSSL_free(s);
+}
 
 #define string_stack_free(sk) sk_OPENSSL_STRING_pop_free(sk, str_free)
 
 static int int_x509_param_set_hosts(X509_VERIFY_PARAM_ID *id, int mode,
-				    const char *name, size_t namelen)
-	{
-	char *copy;
+                                    const char *name, size_t namelen)
+{
+    char *copy;
 
-	/*
-	 * Refuse names with embedded NUL bytes.
-	 * XXX: Do we need to push an error onto the error stack?
-	 */
-	if (name && memchr(name, '\0', namelen))
-		 return 0;
+    /*
+     * Refuse names with embedded NUL bytes.
+     * XXX: Do we need to push an error onto the error stack?
+     */
+    if (name && OPENSSL_memchr(name, '\0', namelen))
+        return 0;
 
-	if (mode == SET_HOST && id->hosts)
-		{
-		string_stack_free(id->hosts);
-		id->hosts = NULL;
-		}
-	if (name == NULL || namelen == 0)
-		return 1;
+    if (mode == SET_HOST && id->hosts) {
+        string_stack_free(id->hosts);
+        id->hosts = NULL;
+    }
+    if (name == NULL || namelen == 0)
+        return 1;
 
-	copy = BUF_strndup(name, namelen);
-	if (copy == NULL)
-		return 0;
+    copy = BUF_strndup(name, namelen);
+    if (copy == NULL)
+        return 0;
 
-	if (id->hosts == NULL &&
-	    (id->hosts = sk_OPENSSL_STRING_new_null()) == NULL)
-		{
-		OPENSSL_free(copy);
-		return 0;
-		}
+    if (id->hosts == NULL &&
+        (id->hosts = sk_OPENSSL_STRING_new_null()) == NULL) {
+        OPENSSL_free(copy);
+        return 0;
+    }
 
-	if (!sk_OPENSSL_STRING_push(id->hosts, copy))
-		{
-		OPENSSL_free(copy);
-		if (sk_OPENSSL_STRING_num(id->hosts) == 0)
-			{
-			sk_OPENSSL_STRING_free(id->hosts);
-			id->hosts = NULL;
-			}
-		return 0;
-		}
+    if (!sk_OPENSSL_STRING_push(id->hosts, copy)) {
+        OPENSSL_free(copy);
+        if (sk_OPENSSL_STRING_num(id->hosts) == 0) {
+            sk_OPENSSL_STRING_free(id->hosts);
+            id->hosts = NULL;
+        }
+        return 0;
+    }
 
-	return 1;
-	}
+    return 1;
+}
 
 static void x509_verify_param_zero(X509_VERIFY_PARAM *param)
-	{
-	X509_VERIFY_PARAM_ID *paramid;
-	if (!param)
-		return;
-	param->name = NULL;
-	param->purpose = 0;
-	param->trust = 0;
-	/*param->inh_flags = X509_VP_FLAG_DEFAULT;*/
-	param->inh_flags = 0;
-	param->flags = 0;
-	param->depth = -1;
-	if (param->policies)
-		{
-		sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
-		param->policies = NULL;
-		}
-	paramid = param->id;
-	if (paramid->hosts)
-		{
-		string_stack_free(paramid->hosts);
-		paramid->hosts = NULL;
-		}
-	if (paramid->peername)
-		{
-		OPENSSL_free(paramid->peername);
-		paramid->peername = NULL;
-		}
-	if (paramid->email)
-		{
-		OPENSSL_free(paramid->email);
-		paramid->email = NULL;
-		paramid->emaillen = 0;
-		}
-	if (paramid->ip)
-		{
-		OPENSSL_free(paramid->ip);
-		paramid->ip = NULL;
-		paramid->iplen = 0;
-		}
+{
+    X509_VERIFY_PARAM_ID *paramid;
+    if (!param)
+        return;
+    param->name = NULL;
+    param->purpose = 0;
+    param->trust = 0;
+    /*
+     * param->inh_flags = X509_VP_FLAG_DEFAULT;
+     */
+    param->inh_flags = 0;
+    param->flags = 0;
+    param->depth = -1;
+    if (param->policies) {
+        sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
+        param->policies = NULL;
+    }
+    paramid = param->id;
+    if (paramid->hosts) {
+        string_stack_free(paramid->hosts);
+        paramid->hosts = NULL;
+    }
+    if (paramid->peername) {
+        OPENSSL_free(paramid->peername);
+        paramid->peername = NULL;
+    }
+    if (paramid->email) {
+        OPENSSL_free(paramid->email);
+        paramid->email = NULL;
+        paramid->emaillen = 0;
+    }
+    if (paramid->ip) {
+        OPENSSL_free(paramid->ip);
+        paramid->ip = NULL;
+        paramid->iplen = 0;
+    }
 
-	}
+}
 
 X509_VERIFY_PARAM *X509_VERIFY_PARAM_new(void)
-	{
-	X509_VERIFY_PARAM *param;
-	X509_VERIFY_PARAM_ID *paramid;
-	param = OPENSSL_malloc(sizeof(X509_VERIFY_PARAM));
-	if (!param)
-		return NULL;
-	paramid = OPENSSL_malloc(sizeof(X509_VERIFY_PARAM_ID));
-	if (!paramid)
-		{
-		OPENSSL_free(param);
-		return NULL;
-		}
-	memset(param, 0, sizeof(X509_VERIFY_PARAM));
-	memset(paramid, 0, sizeof(X509_VERIFY_PARAM_ID));
-	param->id = paramid;
-	x509_verify_param_zero(param);
-	return param;
-	}
+{
+    X509_VERIFY_PARAM *param;
+    X509_VERIFY_PARAM_ID *paramid;
+    param = OPENSSL_malloc(sizeof(X509_VERIFY_PARAM));
+    if (!param)
+        return NULL;
+    paramid = OPENSSL_malloc(sizeof(X509_VERIFY_PARAM_ID));
+    if (!paramid) {
+        OPENSSL_free(param);
+        return NULL;
+    }
+    OPENSSL_memset(param, 0, sizeof(X509_VERIFY_PARAM));
+    OPENSSL_memset(paramid, 0, sizeof(X509_VERIFY_PARAM_ID));
+    param->id = paramid;
+    x509_verify_param_zero(param);
+    return param;
+}
 
 void X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param)
-	{
-	if (param == NULL)
-		return;
-	x509_verify_param_zero(param);
-	OPENSSL_free(param->id);
-	OPENSSL_free(param);
-	}
+{
+    if (param == NULL)
+        return;
+    x509_verify_param_zero(param);
+    OPENSSL_free(param->id);
+    OPENSSL_free(param);
+}
 
-/* This function determines how parameters are "inherited" from one structure
+/*-
+ * This function determines how parameters are "inherited" from one structure
  * to another. There are several different ways this can happen.
  *
  * 1. If a child structure needs to have its values initialized from a parent
@@ -202,7 +205,7 @@
  *    for SSL servers or clients but only if the application has not set new
  *    ones.
  *
- * The "inh_flags" field determines how this function behaves. 
+ * The "inh_flags" field determines how this function behaves.
  *
  * Normally any values which are set in the default are not copied from the
  * destination and verify flags are ORed together.
@@ -226,447 +229,421 @@
 /* Macro to test if a field should be copied from src to dest */
 
 #define test_x509_verify_param_copy(field, def) \
-	(to_overwrite || \
-		((src->field != def) && (to_default || (dest->field == def))))
+  (to_overwrite ||                              \
+   ((src->field != (def)) && (to_default || (dest->field == (def)))))
 
 /* As above but for ID fields */
 
 #define test_x509_verify_param_copy_id(idf, def) \
-	test_x509_verify_param_copy(id->idf, def)
+        test_x509_verify_param_copy(id->idf, def)
 
 /* Macro to test and copy a field if necessary */
 
 #define x509_verify_param_copy(field, def) \
-	if (test_x509_verify_param_copy(field, def)) \
-		dest->field = src->field
-
+        if (test_x509_verify_param_copy(field, def)) \
+                dest->field = src->field
 
 int X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest,
-						const X509_VERIFY_PARAM *src)
-	{
-	unsigned long inh_flags;
-	int to_default, to_overwrite;
-	X509_VERIFY_PARAM_ID *id;
-	if (!src)
-		return 1;
-	id = src->id;
-	inh_flags = dest->inh_flags | src->inh_flags;
+                              const X509_VERIFY_PARAM *src)
+{
+    unsigned long inh_flags;
+    int to_default, to_overwrite;
+    X509_VERIFY_PARAM_ID *id;
+    if (!src)
+        return 1;
+    id = src->id;
+    inh_flags = dest->inh_flags | src->inh_flags;
 
-	if (inh_flags & X509_VP_FLAG_ONCE)
-		dest->inh_flags = 0;
+    if (inh_flags & X509_VP_FLAG_ONCE)
+        dest->inh_flags = 0;
 
-	if (inh_flags & X509_VP_FLAG_LOCKED)
-		return 1;
+    if (inh_flags & X509_VP_FLAG_LOCKED)
+        return 1;
 
-	if (inh_flags & X509_VP_FLAG_DEFAULT)
-		to_default = 1;
-	else
-		to_default = 0;
+    if (inh_flags & X509_VP_FLAG_DEFAULT)
+        to_default = 1;
+    else
+        to_default = 0;
 
-	if (inh_flags & X509_VP_FLAG_OVERWRITE)
-		to_overwrite = 1;
-	else
-		to_overwrite = 0;
+    if (inh_flags & X509_VP_FLAG_OVERWRITE)
+        to_overwrite = 1;
+    else
+        to_overwrite = 0;
 
-	x509_verify_param_copy(purpose, 0);
-	x509_verify_param_copy(trust, 0);
-	x509_verify_param_copy(depth, -1);
+    x509_verify_param_copy(purpose, 0);
+    x509_verify_param_copy(trust, 0);
+    x509_verify_param_copy(depth, -1);
 
-	/* If overwrite or check time not set, copy across */
+    /* If overwrite or check time not set, copy across */
 
-	if (to_overwrite || !(dest->flags & X509_V_FLAG_USE_CHECK_TIME))
-		{
-		dest->check_time = src->check_time;
-		dest->flags &= ~X509_V_FLAG_USE_CHECK_TIME;
-		/* Don't need to copy flag: that is done below */
-		}
+    if (to_overwrite || !(dest->flags & X509_V_FLAG_USE_CHECK_TIME)) {
+        dest->check_time = src->check_time;
+        dest->flags &= ~X509_V_FLAG_USE_CHECK_TIME;
+        /* Don't need to copy flag: that is done below */
+    }
 
-	if (inh_flags & X509_VP_FLAG_RESET_FLAGS)
-		dest->flags = 0;
+    if (inh_flags & X509_VP_FLAG_RESET_FLAGS)
+        dest->flags = 0;
 
-	dest->flags |= src->flags;
+    dest->flags |= src->flags;
 
-	if (test_x509_verify_param_copy(policies, NULL))
-		{
-		if (!X509_VERIFY_PARAM_set1_policies(dest, src->policies))
-			return 0;
-		}
+    if (test_x509_verify_param_copy(policies, NULL)) {
+        if (!X509_VERIFY_PARAM_set1_policies(dest, src->policies))
+            return 0;
+    }
 
-	/* Copy the host flags if and only if we're copying the host list */
-	if (test_x509_verify_param_copy_id(hosts, NULL))
-		{
-		if (dest->id->hosts)
-			{
-			string_stack_free(dest->id->hosts);
-			dest->id->hosts = NULL;
-			}
-		if (id->hosts)
-			{
-			dest->id->hosts =
-			    sk_OPENSSL_STRING_deep_copy(id->hosts,
-							str_copy, str_free);
-			if (dest->id->hosts == NULL)
-				return 0;
-			dest->id->hostflags = id->hostflags;
-			}
-		}
+    /* Copy the host flags if and only if we're copying the host list */
+    if (test_x509_verify_param_copy_id(hosts, NULL)) {
+        if (dest->id->hosts) {
+            string_stack_free(dest->id->hosts);
+            dest->id->hosts = NULL;
+        }
+        if (id->hosts) {
+            dest->id->hosts =
+                sk_OPENSSL_STRING_deep_copy(id->hosts, str_copy, str_free);
+            if (dest->id->hosts == NULL)
+                return 0;
+            dest->id->hostflags = id->hostflags;
+        }
+    }
 
-	if (test_x509_verify_param_copy_id(email, NULL))
-		{
-		if (!X509_VERIFY_PARAM_set1_email(dest, id->email, id->emaillen))
-			return 0;
-		}
+    if (test_x509_verify_param_copy_id(email, NULL)) {
+        if (!X509_VERIFY_PARAM_set1_email(dest, id->email, id->emaillen))
+            return 0;
+    }
 
-	if (test_x509_verify_param_copy_id(ip, NULL))
-		{
-		if (!X509_VERIFY_PARAM_set1_ip(dest, id->ip, id->iplen))
-			return 0;
-		}
+    if (test_x509_verify_param_copy_id(ip, NULL)) {
+        if (!X509_VERIFY_PARAM_set1_ip(dest, id->ip, id->iplen))
+            return 0;
+    }
 
-	return 1;
-	}
+    return 1;
+}
 
 int X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to,
-						const X509_VERIFY_PARAM *from)
-	{
-	unsigned long save_flags = to->inh_flags;
-	int ret;
-	to->inh_flags |= X509_VP_FLAG_DEFAULT;
-	ret = X509_VERIFY_PARAM_inherit(to, from);
-	to->inh_flags = save_flags;
-	return ret;
-	}
+                           const X509_VERIFY_PARAM *from)
+{
+    unsigned long save_flags = to->inh_flags;
+    int ret;
+    to->inh_flags |= X509_VP_FLAG_DEFAULT;
+    ret = X509_VERIFY_PARAM_inherit(to, from);
+    to->inh_flags = save_flags;
+    return ret;
+}
 
 static int int_x509_param_set1(char **pdest, size_t *pdestlen,
-				const char *src, size_t srclen)
-	{
-	void *tmp;
-	if (src)
-		{
-		if (srclen == 0)
-			{
-			tmp = BUF_strdup(src);
-			srclen = strlen(src);
-			}
-		else
-			tmp = BUF_memdup(src, srclen);
-		if (!tmp)
-			return 0;
-		}
-	else
-		{
-		tmp = NULL;
-		srclen = 0;
-		}
-	if (*pdest)
-		OPENSSL_free(*pdest);
-	*pdest = tmp;
-	if (pdestlen)
-		*pdestlen = srclen;
-	return 1;
-	}
+                               const char *src, size_t srclen)
+{
+    void *tmp;
+    if (src) {
+        if (srclen == 0) {
+            tmp = BUF_strdup(src);
+            srclen = strlen(src);
+        } else
+            tmp = BUF_memdup(src, srclen);
+        if (!tmp)
+            return 0;
+    } else {
+        tmp = NULL;
+        srclen = 0;
+    }
+    if (*pdest)
+        OPENSSL_free(*pdest);
+    *pdest = tmp;
+    if (pdestlen)
+        *pdestlen = srclen;
+    return 1;
+}
 
 int X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name)
-	{
-	if (param->name)
-		OPENSSL_free(param->name);
-	param->name = BUF_strdup(name);
-	if (param->name)
-		return 1;
-	return 0;
-	}
+{
+    if (param->name)
+        OPENSSL_free(param->name);
+    param->name = BUF_strdup(name);
+    if (param->name)
+        return 1;
+    return 0;
+}
 
 int X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags)
-	{
-	param->flags |= flags;
-	if (flags & X509_V_FLAG_POLICY_MASK)
-		param->flags |= X509_V_FLAG_POLICY_CHECK;
-	return 1;
-	}
+{
+    param->flags |= flags;
+    if (flags & X509_V_FLAG_POLICY_MASK)
+        param->flags |= X509_V_FLAG_POLICY_CHECK;
+    return 1;
+}
 
-int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param, unsigned long flags)
-	{
-	param->flags &= ~flags;
-	return 1;
-	}
+int X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param,
+                                  unsigned long flags)
+{
+    param->flags &= ~flags;
+    return 1;
+}
 
 unsigned long X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param)
-	{
-	return param->flags;
-	}
+{
+    return param->flags;
+}
 
 int X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose)
-	{
-	return X509_PURPOSE_set(&param->purpose, purpose);
-	}
+{
+    return X509_PURPOSE_set(&param->purpose, purpose);
+}
 
 int X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust)
-	{
-	return X509_TRUST_set(&param->trust, trust);
-	}
+{
+    return X509_TRUST_set(&param->trust, trust);
+}
 
 void X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth)
-	{
-	param->depth = depth;
-	}
+{
+    param->depth = depth;
+}
 
 void X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t)
-	{
-	param->check_time = t;
-	param->flags |= X509_V_FLAG_USE_CHECK_TIME;
-	}
+{
+    param->check_time = t;
+    param->flags |= X509_V_FLAG_USE_CHECK_TIME;
+}
 
-int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param, ASN1_OBJECT *policy)
-	{
-	if (!param->policies)
-		{
-		param->policies = sk_ASN1_OBJECT_new_null();
-		if (!param->policies)
-			return 0;
-		}
-	if (!sk_ASN1_OBJECT_push(param->policies, policy))
-		return 0;
-	return 1;
-	}
+int X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param,
+                                  ASN1_OBJECT *policy)
+{
+    if (!param->policies) {
+        param->policies = sk_ASN1_OBJECT_new_null();
+        if (!param->policies)
+            return 0;
+    }
+    if (!sk_ASN1_OBJECT_push(param->policies, policy))
+        return 0;
+    return 1;
+}
 
-int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param, 
-					STACK_OF(ASN1_OBJECT) *policies)
-	{
-	size_t i;
-	ASN1_OBJECT *oid, *doid;
-	if (!param)
-		return 0;
-	if (param->policies)
-		sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
+int X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
+                                    STACK_OF(ASN1_OBJECT) *policies)
+{
+    size_t i;
+    ASN1_OBJECT *oid, *doid;
+    if (!param)
+        return 0;
+    if (param->policies)
+        sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
 
-	if (!policies)
-		{
-		param->policies = NULL;
-		return 1;
-		}
+    if (!policies) {
+        param->policies = NULL;
+        return 1;
+    }
 
-	param->policies = sk_ASN1_OBJECT_new_null();
-	if (!param->policies)
-		return 0;
+    param->policies = sk_ASN1_OBJECT_new_null();
+    if (!param->policies)
+        return 0;
 
-	for (i = 0; i < sk_ASN1_OBJECT_num(policies); i++)
-		{
-		oid = sk_ASN1_OBJECT_value(policies, i);
-		doid = OBJ_dup(oid);
-		if (!doid)
-			return 0;
-		if (!sk_ASN1_OBJECT_push(param->policies, doid))
-			{
-			ASN1_OBJECT_free(doid);
-			return 0;
-			}
-		}
-	param->flags |= X509_V_FLAG_POLICY_CHECK;
-	return 1;
-	}
+    for (i = 0; i < sk_ASN1_OBJECT_num(policies); i++) {
+        oid = sk_ASN1_OBJECT_value(policies, i);
+        doid = OBJ_dup(oid);
+        if (!doid)
+            return 0;
+        if (!sk_ASN1_OBJECT_push(param->policies, doid)) {
+            ASN1_OBJECT_free(doid);
+            return 0;
+        }
+    }
+    param->flags |= X509_V_FLAG_POLICY_CHECK;
+    return 1;
+}
 
 int X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param,
-				const char *name, size_t namelen)
-	{
-	return int_x509_param_set_hosts(param->id, SET_HOST, name, namelen);
-	}
+                                const char *name, size_t namelen)
+{
+    return int_x509_param_set_hosts(param->id, SET_HOST, name, namelen);
+}
 
 int X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param,
-				const char *name, size_t namelen)
-	{
-	return int_x509_param_set_hosts(param->id, ADD_HOST, name, namelen);
-	}
+                                const char *name, size_t namelen)
+{
+    return int_x509_param_set_hosts(param->id, ADD_HOST, name, namelen);
+}
 
 void X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param,
-					unsigned int flags)
-	{
-	param->id->hostflags = flags;
-	}
+                                     unsigned int flags)
+{
+    param->id->hostflags = flags;
+}
 
 char *X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *param)
-	{
-	return param->id->peername;
-	}
+{
+    return param->id->peername;
+}
 
 int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param,
-				const char *email, size_t emaillen)
-	{
-	return int_x509_param_set1(&param->id->email, &param->id->emaillen,
-					email, emaillen);
-	}
+                                 const char *email, size_t emaillen)
+{
+    return int_x509_param_set1(&param->id->email, &param->id->emaillen,
+                               email, emaillen);
+}
 
 int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param,
-					const unsigned char *ip, size_t iplen)
-	{
-	if (iplen != 0 && iplen != 4 && iplen != 16)
-		return 0;
-	return int_x509_param_set1((char **)&param->id->ip, &param->id->iplen,
-				   (char *)ip, iplen);
-	}
+                              const unsigned char *ip, size_t iplen)
+{
+    if (iplen != 0 && iplen != 4 && iplen != 16)
+        return 0;
+    return int_x509_param_set1((char **)&param->id->ip, &param->id->iplen,
+                               (char *)ip, iplen);
+}
 
 int X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc)
-	{
-	unsigned char ipout[16];
-	size_t iplen;
+{
+    unsigned char ipout[16];
+    size_t iplen;
 
-	iplen = (size_t) a2i_ipadd(ipout, ipasc);
-	if (iplen == 0)
-		return 0;
-	return X509_VERIFY_PARAM_set1_ip(param, ipout, iplen);
-	}
+    iplen = (size_t)a2i_ipadd(ipout, ipasc);
+    if (iplen == 0)
+        return 0;
+    return X509_VERIFY_PARAM_set1_ip(param, ipout, iplen);
+}
 
 int X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param)
-	{
-	return param->depth;
-	}
+{
+    return param->depth;
+}
 
 const char *X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param)
-	{
-	return param->name;
-	}
+{
+    return param->name;
+}
 
-static const X509_VERIFY_PARAM_ID _empty_id = {NULL, 0U, NULL, NULL, 0, NULL, 0};
+static const X509_VERIFY_PARAM_ID _empty_id =
+    { NULL, 0U, NULL, NULL, 0, NULL, 0 };
 
-#define vpm_empty_id (X509_VERIFY_PARAM_ID *)&_empty_id
+#define vpm_empty_id ((X509_VERIFY_PARAM_ID *)&_empty_id)
 
-/* Default verify parameters: these are used for various
- * applications and can be overridden by the user specified table.
- * NB: the 'name' field *must* be in alphabetical order because it
- * will be searched using OBJ_search.
+/*
+ * Default verify parameters: these are used for various applications and can
+ * be overridden by the user specified table. NB: the 'name' field *must* be
+ * in alphabetical order because it will be searched using OBJ_search.
  */
 
 static const X509_VERIFY_PARAM default_table[] = {
-	{
-	(char *) "default",	/* X509 default parameters */
-	0,		/* Check time */
-	0,		/* internal flags */
-	0,		/* flags */
-	0,		/* purpose */
-	0,		/* trust */
-	100,		/* depth */
-	NULL,		/* policies */
-	vpm_empty_id
-	},
-	{
-	(char *) "pkcs7",			/* S/MIME sign parameters */
-	0,				/* Check time */
-	0,				/* internal flags */
-	0,				/* flags */
-	X509_PURPOSE_SMIME_SIGN,	/* purpose */
-	X509_TRUST_EMAIL,		/* trust */
-	-1,				/* depth */
-	NULL,				/* policies */
-	vpm_empty_id
-	},
-	{
-	(char *) "smime_sign",			/* S/MIME sign parameters */
-	0,				/* Check time */
-	0,				/* internal flags */
-	0,				/* flags */
-	X509_PURPOSE_SMIME_SIGN,	/* purpose */
-	X509_TRUST_EMAIL,		/* trust */
-	-1,				/* depth */
-	NULL,				/* policies */
-	vpm_empty_id
-	},
-	{
-	(char *) "ssl_client",			/* SSL/TLS client parameters */
-	0,				/* Check time */
-	0,				/* internal flags */
-	0,				/* flags */
-	X509_PURPOSE_SSL_CLIENT,	/* purpose */
-	X509_TRUST_SSL_CLIENT,		/* trust */
-	-1,				/* depth */
-	NULL,				/* policies */
-	vpm_empty_id
-	},
-	{
-	(char *) "ssl_server",			/* SSL/TLS server parameters */
-	0,				/* Check time */
-	0,				/* internal flags */
-	0,				/* flags */
-	X509_PURPOSE_SSL_SERVER,	/* purpose */
-	X509_TRUST_SSL_SERVER,		/* trust */
-	-1,				/* depth */
-	NULL,				/* policies */
-	vpm_empty_id
-	}};
+    {
+     (char *)"default",         /* X509 default parameters */
+     0,                         /* Check time */
+     0,                         /* internal flags */
+     0,                         /* flags */
+     0,                         /* purpose */
+     0,                         /* trust */
+     100,                       /* depth */
+     NULL,                      /* policies */
+     vpm_empty_id},
+    {
+     (char *)"pkcs7",           /* S/MIME sign parameters */
+     0,                         /* Check time */
+     0,                         /* internal flags */
+     0,                         /* flags */
+     X509_PURPOSE_SMIME_SIGN,   /* purpose */
+     X509_TRUST_EMAIL,          /* trust */
+     -1,                        /* depth */
+     NULL,                      /* policies */
+     vpm_empty_id},
+    {
+     (char *)"smime_sign",      /* S/MIME sign parameters */
+     0,                         /* Check time */
+     0,                         /* internal flags */
+     0,                         /* flags */
+     X509_PURPOSE_SMIME_SIGN,   /* purpose */
+     X509_TRUST_EMAIL,          /* trust */
+     -1,                        /* depth */
+     NULL,                      /* policies */
+     vpm_empty_id},
+    {
+     (char *)"ssl_client",      /* SSL/TLS client parameters */
+     0,                         /* Check time */
+     0,                         /* internal flags */
+     0,                         /* flags */
+     X509_PURPOSE_SSL_CLIENT,   /* purpose */
+     X509_TRUST_SSL_CLIENT,     /* trust */
+     -1,                        /* depth */
+     NULL,                      /* policies */
+     vpm_empty_id},
+    {
+     (char *)"ssl_server",      /* SSL/TLS server parameters */
+     0,                         /* Check time */
+     0,                         /* internal flags */
+     0,                         /* flags */
+     X509_PURPOSE_SSL_SERVER,   /* purpose */
+     X509_TRUST_SSL_SERVER,     /* trust */
+     -1,                        /* depth */
+     NULL,                      /* policies */
+     vpm_empty_id}
+};
 
 static STACK_OF(X509_VERIFY_PARAM) *param_table = NULL;
 
-static int param_cmp(const X509_VERIFY_PARAM **a,
-			const X509_VERIFY_PARAM **b)
-	{
-	return strcmp((*a)->name, (*b)->name);
-	}
+static int param_cmp(const X509_VERIFY_PARAM **a, const X509_VERIFY_PARAM **b)
+{
+    return strcmp((*a)->name, (*b)->name);
+}
 
 int X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param)
-	{
-	X509_VERIFY_PARAM *ptmp;
-	if (!param_table)
-		{
-		param_table = sk_X509_VERIFY_PARAM_new(param_cmp);
-		if (!param_table)
-			return 0;
-		}
-	else
-		{
-		size_t idx;
+{
+    X509_VERIFY_PARAM *ptmp;
+    if (!param_table) {
+        param_table = sk_X509_VERIFY_PARAM_new(param_cmp);
+        if (!param_table)
+            return 0;
+    } else {
+        size_t idx;
 
-		if (sk_X509_VERIFY_PARAM_find(param_table, &idx, param))
-			{
-			ptmp = sk_X509_VERIFY_PARAM_value(param_table, idx);
-			X509_VERIFY_PARAM_free(ptmp);
-			(void)sk_X509_VERIFY_PARAM_delete(param_table, idx);
-			}
-		}
-	if (!sk_X509_VERIFY_PARAM_push(param_table, param))
-		return 0;
-	return 1;
-	}
+        if (sk_X509_VERIFY_PARAM_find(param_table, &idx, param)) {
+            ptmp = sk_X509_VERIFY_PARAM_value(param_table, idx);
+            X509_VERIFY_PARAM_free(ptmp);
+            (void)sk_X509_VERIFY_PARAM_delete(param_table, idx);
+        }
+    }
+    if (!sk_X509_VERIFY_PARAM_push(param_table, param))
+        return 0;
+    return 1;
+}
 
 int X509_VERIFY_PARAM_get_count(void)
-	{
-	int num = sizeof(default_table)/sizeof(X509_VERIFY_PARAM);
-	if (param_table)
-		num += sk_X509_VERIFY_PARAM_num(param_table);
-	return num;
-	}
+{
+    int num = sizeof(default_table) / sizeof(X509_VERIFY_PARAM);
+    if (param_table)
+        num += sk_X509_VERIFY_PARAM_num(param_table);
+    return num;
+}
 
 const X509_VERIFY_PARAM *X509_VERIFY_PARAM_get0(int id)
-	{
-	int num = sizeof(default_table)/sizeof(X509_VERIFY_PARAM);
-	if (id < num)
-		return default_table + id;
-	return sk_X509_VERIFY_PARAM_value(param_table, id - num);
-	}
+{
+    int num = sizeof(default_table) / sizeof(X509_VERIFY_PARAM);
+    if (id < num)
+        return default_table + id;
+    return sk_X509_VERIFY_PARAM_value(param_table, id - num);
+}
 
 const X509_VERIFY_PARAM *X509_VERIFY_PARAM_lookup(const char *name)
-	{
-	X509_VERIFY_PARAM pm;
-	unsigned i, limit;
+{
+    X509_VERIFY_PARAM pm;
+    unsigned i, limit;
 
-	pm.name = (char *)name;
-	if (param_table)
-		{
-		size_t idx;
-		if (sk_X509_VERIFY_PARAM_find(param_table, &idx, &pm))
-			return sk_X509_VERIFY_PARAM_value(param_table, idx);
-		}
+    pm.name = (char *)name;
+    if (param_table) {
+        size_t idx;
+        if (sk_X509_VERIFY_PARAM_find(param_table, &idx, &pm))
+            return sk_X509_VERIFY_PARAM_value(param_table, idx);
+    }
 
-	limit = sizeof(default_table)/sizeof(X509_VERIFY_PARAM);
-	for (i = 0; i < limit; i++) {
-		if (strcmp(default_table[i].name, name) == 0) {
-			return &default_table[i];
-		}
-	}
-	return NULL;
-	}
+    limit = sizeof(default_table) / sizeof(X509_VERIFY_PARAM);
+    for (i = 0; i < limit; i++) {
+        if (strcmp(default_table[i].name, name) == 0) {
+            return &default_table[i];
+        }
+    }
+    return NULL;
+}
 
 void X509_VERIFY_PARAM_table_cleanup(void)
-	{
-	if (param_table)
-		sk_X509_VERIFY_PARAM_pop_free(param_table,
-						X509_VERIFY_PARAM_free);
-	param_table = NULL;
-	}
+{
+    if (param_table)
+        sk_X509_VERIFY_PARAM_pop_free(param_table, X509_VERIFY_PARAM_free);
+    param_table = NULL;
+}
diff --git a/src/crypto/x509/x509cset.c b/src/crypto/x509/x509cset.c
index 82d61d0..2fd48a9 100644
--- a/src/crypto/x509/x509cset.c
+++ b/src/crypto/x509/x509cset.c
@@ -1,5 +1,7 @@
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 2001. */
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 2001.
+ */
 /* ====================================================================
  * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
  *
@@ -8,7 +10,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -59,114 +61,110 @@
 
 #include "../internal.h"
 
-
 int X509_CRL_set_version(X509_CRL *x, long version)
-	{
-	if (x == NULL) return(0);
-	if (x->crl->version == NULL)
-		{
-		if ((x->crl->version=M_ASN1_INTEGER_new()) == NULL)
-			return(0);
-		}
-	return(ASN1_INTEGER_set(x->crl->version,version));
-	}
+{
+    if (x == NULL)
+        return (0);
+    if (x->crl->version == NULL) {
+        if ((x->crl->version = M_ASN1_INTEGER_new()) == NULL)
+            return (0);
+    }
+    return (ASN1_INTEGER_set(x->crl->version, version));
+}
 
 int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name)
-	{
-	if ((x == NULL) || (x->crl == NULL)) return(0);
-	return(X509_NAME_set(&x->crl->issuer,name));
-	}
-
+{
+    if ((x == NULL) || (x->crl == NULL))
+        return (0);
+    return (X509_NAME_set(&x->crl->issuer, name));
+}
 
 int X509_CRL_set_lastUpdate(X509_CRL *x, const ASN1_TIME *tm)
-	{
-	ASN1_TIME *in;
+{
+    ASN1_TIME *in;
 
-	if (x == NULL) return(0);
-	in=x->crl->lastUpdate;
-	if (in != tm)
-		{
-		in=M_ASN1_TIME_dup(tm);
-		if (in != NULL)
-			{
-			M_ASN1_TIME_free(x->crl->lastUpdate);
-			x->crl->lastUpdate=in;
-			}
-		}
-	return(in != NULL);
-	}
+    if (x == NULL)
+        return (0);
+    in = x->crl->lastUpdate;
+    if (in != tm) {
+        in = M_ASN1_TIME_dup(tm);
+        if (in != NULL) {
+            M_ASN1_TIME_free(x->crl->lastUpdate);
+            x->crl->lastUpdate = in;
+        }
+    }
+    return (in != NULL);
+}
 
 int X509_CRL_set_nextUpdate(X509_CRL *x, const ASN1_TIME *tm)
-	{
-	ASN1_TIME *in;
+{
+    ASN1_TIME *in;
 
-	if (x == NULL) return(0);
-	in=x->crl->nextUpdate;
-	if (in != tm)
-		{
-		in=M_ASN1_TIME_dup(tm);
-		if (in != NULL)
-			{
-			M_ASN1_TIME_free(x->crl->nextUpdate);
-			x->crl->nextUpdate=in;
-			}
-		}
-	return(in != NULL);
-	}
+    if (x == NULL)
+        return (0);
+    in = x->crl->nextUpdate;
+    if (in != tm) {
+        in = M_ASN1_TIME_dup(tm);
+        if (in != NULL) {
+            M_ASN1_TIME_free(x->crl->nextUpdate);
+            x->crl->nextUpdate = in;
+        }
+    }
+    return (in != NULL);
+}
 
 int X509_CRL_sort(X509_CRL *c)
-	{
-	size_t i;
-	X509_REVOKED *r;
-	/* sort the data so it will be written in serial
-	 * number order */
-	sk_X509_REVOKED_sort(c->crl->revoked);
-	for (i=0; i<sk_X509_REVOKED_num(c->crl->revoked); i++)
-		{
-		r=sk_X509_REVOKED_value(c->crl->revoked,i);
-		r->sequence=i;
-		}
-	c->crl->enc.modified = 1;
-	return 1;
-	}
+{
+    size_t i;
+    X509_REVOKED *r;
+    /*
+     * sort the data so it will be written in serial number order
+     */
+    sk_X509_REVOKED_sort(c->crl->revoked);
+    for (i = 0; i < sk_X509_REVOKED_num(c->crl->revoked); i++) {
+        r = sk_X509_REVOKED_value(c->crl->revoked, i);
+        r->sequence = i;
+    }
+    c->crl->enc.modified = 1;
+    return 1;
+}
 
-void X509_CRL_up_ref(X509_CRL *crl)
-	{
-	CRYPTO_refcount_inc(&crl->references);
-	}
+int X509_CRL_up_ref(X509_CRL *crl)
+{
+    CRYPTO_refcount_inc(&crl->references);
+    return 1;
+}
 
 int X509_REVOKED_set_revocationDate(X509_REVOKED *x, ASN1_TIME *tm)
-	{
-	ASN1_TIME *in;
+{
+    ASN1_TIME *in;
 
-	if (x == NULL) return(0);
-	in=x->revocationDate;
-	if (in != tm)
-		{
-		in=M_ASN1_TIME_dup(tm);
-		if (in != NULL)
-			{
-			M_ASN1_TIME_free(x->revocationDate);
-			x->revocationDate=in;
-			}
-		}
-	return(in != NULL);
-	}
+    if (x == NULL)
+        return (0);
+    in = x->revocationDate;
+    if (in != tm) {
+        in = M_ASN1_TIME_dup(tm);
+        if (in != NULL) {
+            M_ASN1_TIME_free(x->revocationDate);
+            x->revocationDate = in;
+        }
+    }
+    return (in != NULL);
+}
 
 int X509_REVOKED_set_serialNumber(X509_REVOKED *x, ASN1_INTEGER *serial)
-	{
-	ASN1_INTEGER *in;
+{
+    ASN1_INTEGER *in;
 
-	if (x == NULL) return(0);
-	in=x->serialNumber;
-	if (in != serial)
-		{
-		in=M_ASN1_INTEGER_dup(serial);
-		if (in != NULL)
-			{
-			M_ASN1_INTEGER_free(x->serialNumber);
-			x->serialNumber=in;
-			}
-		}
-	return(in != NULL);
-	}
+    if (x == NULL)
+        return (0);
+    in = x->serialNumber;
+    if (in != serial) {
+        in = M_ASN1_INTEGER_dup(serial);
+        if (in != NULL) {
+            M_ASN1_INTEGER_free(x->serialNumber);
+            x->serialNumber = in;
+        }
+    }
+    return (in != NULL);
+}
diff --git a/src/crypto/x509/x509name.c b/src/crypto/x509/x509name.c
index 8b10fa2..610de5f 100644
--- a/src/crypto/x509/x509name.c
+++ b/src/crypto/x509/x509name.c
@@ -63,313 +63,327 @@
 #include <openssl/stack.h>
 #include <openssl/x509.h>
 
+#include "../internal.h"
+
 
 int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len)
-	{
-	const ASN1_OBJECT *obj;
+{
+    const ASN1_OBJECT *obj;
 
-	obj=OBJ_nid2obj(nid);
-	if (obj == NULL) return(-1);
-	return(X509_NAME_get_text_by_OBJ(name,obj,buf,len));
-	}
+    obj = OBJ_nid2obj(nid);
+    if (obj == NULL)
+        return (-1);
+    return (X509_NAME_get_text_by_OBJ(name, obj, buf, len));
+}
 
-int X509_NAME_get_text_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, char *buf,
-	     int len)
-	{
-	int i;
-	ASN1_STRING *data;
+int X509_NAME_get_text_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj,
+                              char *buf, int len)
+{
+    int i;
+    ASN1_STRING *data;
 
-	i=X509_NAME_get_index_by_OBJ(name,obj,-1);
-	if (i < 0) return(-1);
-	data=X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name,i));
-	i=(data->length > (len-1))?(len-1):data->length;
-	if (buf == NULL) return(data->length);
-	memcpy(buf,data->data,i);
-	buf[i]='\0';
-	return(i);
-	}
+    i = X509_NAME_get_index_by_OBJ(name, obj, -1);
+    if (i < 0)
+        return (-1);
+    data = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i));
+    i = (data->length > (len - 1)) ? (len - 1) : data->length;
+    if (buf == NULL)
+        return (data->length);
+    OPENSSL_memcpy(buf, data->data, i);
+    buf[i] = '\0';
+    return (i);
+}
 
 int X509_NAME_entry_count(X509_NAME *name)
-	{
-	if (name == NULL) return(0);
-	return(sk_X509_NAME_ENTRY_num(name->entries));
-	}
+{
+    if (name == NULL)
+        return (0);
+    return (sk_X509_NAME_ENTRY_num(name->entries));
+}
 
 int X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos)
-	{
-	const ASN1_OBJECT *obj;
+{
+    const ASN1_OBJECT *obj;
 
-	obj=OBJ_nid2obj(nid);
-	if (obj == NULL) return(-2);
-	return(X509_NAME_get_index_by_OBJ(name,obj,lastpos));
-	}
+    obj = OBJ_nid2obj(nid);
+    if (obj == NULL)
+        return (-2);
+    return (X509_NAME_get_index_by_OBJ(name, obj, lastpos));
+}
 
 /* NOTE: you should be passsing -1, not 0 as lastpos */
 int X509_NAME_get_index_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj,
-	     int lastpos)
-	{
-	int n;
-	X509_NAME_ENTRY *ne;
-	STACK_OF(X509_NAME_ENTRY) *sk;
+                               int lastpos)
+{
+    int n;
+    X509_NAME_ENTRY *ne;
+    STACK_OF(X509_NAME_ENTRY) *sk;
 
-	if (name == NULL) return(-1);
-	if (lastpos < 0)
-		lastpos= -1;
-	sk=name->entries;
-	n=sk_X509_NAME_ENTRY_num(sk);
-	for (lastpos++; lastpos < n; lastpos++)
-		{
-		ne=sk_X509_NAME_ENTRY_value(sk,lastpos);
-		if (OBJ_cmp(ne->object,obj) == 0)
-			return(lastpos);
-		}
-	return(-1);
-	}
+    if (name == NULL)
+        return (-1);
+    if (lastpos < 0)
+        lastpos = -1;
+    sk = name->entries;
+    n = sk_X509_NAME_ENTRY_num(sk);
+    for (lastpos++; lastpos < n; lastpos++) {
+        ne = sk_X509_NAME_ENTRY_value(sk, lastpos);
+        if (OBJ_cmp(ne->object, obj) == 0)
+            return (lastpos);
+    }
+    return (-1);
+}
 
 X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *name, int loc)
-	{
-	if(name == NULL || loc < 0 || sk_X509_NAME_ENTRY_num(name->entries) <= (size_t) loc)
-		return(NULL);
-	else
-		return(sk_X509_NAME_ENTRY_value(name->entries,loc));
-	}
+{
+    if (name == NULL || loc < 0
+        || sk_X509_NAME_ENTRY_num(name->entries) <= (size_t)loc)
+        return (NULL);
+    else
+        return (sk_X509_NAME_ENTRY_value(name->entries, loc));
+}
 
 X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc)
-	{
-	X509_NAME_ENTRY *ret;
-	int i,n,set_prev,set_next;
-	STACK_OF(X509_NAME_ENTRY) *sk;
+{
+    X509_NAME_ENTRY *ret;
+    int i, n, set_prev, set_next;
+    STACK_OF(X509_NAME_ENTRY) *sk;
 
-	if (name == NULL || loc < 0 || sk_X509_NAME_ENTRY_num(name->entries) <= (size_t) loc)
-		return(NULL);
-	sk=name->entries;
-	ret=sk_X509_NAME_ENTRY_delete(sk,loc);
-	n=sk_X509_NAME_ENTRY_num(sk);
-	name->modified=1;
-	if (loc == n) return(ret);
+    if (name == NULL || loc < 0
+        || sk_X509_NAME_ENTRY_num(name->entries) <= (size_t)loc)
+        return (NULL);
+    sk = name->entries;
+    ret = sk_X509_NAME_ENTRY_delete(sk, loc);
+    n = sk_X509_NAME_ENTRY_num(sk);
+    name->modified = 1;
+    if (loc == n)
+        return (ret);
 
-	/* else we need to fixup the set field */
-	if (loc != 0)
-		set_prev=(sk_X509_NAME_ENTRY_value(sk,loc-1))->set;
-	else
-		set_prev=ret->set-1;
-	set_next=sk_X509_NAME_ENTRY_value(sk,loc)->set;
+    /* else we need to fixup the set field */
+    if (loc != 0)
+        set_prev = (sk_X509_NAME_ENTRY_value(sk, loc - 1))->set;
+    else
+        set_prev = ret->set - 1;
+    set_next = sk_X509_NAME_ENTRY_value(sk, loc)->set;
 
-	/* set_prev is the previous set
-	 * set is the current set
-	 * set_next is the following
-	 * prev  1 1	1 1	1 1	1 1
-	 * set   1	1	2	2
-	 * next  1 1	2 2	2 2	3 2
-	 * so basically only if prev and next differ by 2, then
-	 * re-number down by 1 */
-	if (set_prev+1 < set_next)
-		for (i=loc; i<n; i++)
-			sk_X509_NAME_ENTRY_value(sk,i)->set--;
-	return(ret);
-	}
+    /*
+     * set_prev is the previous set set is the current set set_next is the
+     * following prev 1 1 1 1 1 1 1 1 set 1 1 2 2 next 1 1 2 2 2 2 3 2 so
+     * basically only if prev and next differ by 2, then re-number down by 1
+     */
+    if (set_prev + 1 < set_next)
+        for (i = loc; i < n; i++)
+            sk_X509_NAME_ENTRY_value(sk, i)->set--;
+    return (ret);
+}
 
 int X509_NAME_add_entry_by_OBJ(X509_NAME *name, ASN1_OBJECT *obj, int type,
-			unsigned char *bytes, int len, int loc, int set)
+                               unsigned char *bytes, int len, int loc,
+                               int set)
 {
-	X509_NAME_ENTRY *ne;
-	int ret;
-	ne = X509_NAME_ENTRY_create_by_OBJ(NULL, obj, type, bytes, len);
-	if(!ne) return 0;
-	ret = X509_NAME_add_entry(name, ne, loc, set);
-	X509_NAME_ENTRY_free(ne);
-	return ret;
+    X509_NAME_ENTRY *ne;
+    int ret;
+    ne = X509_NAME_ENTRY_create_by_OBJ(NULL, obj, type, bytes, len);
+    if (!ne)
+        return 0;
+    ret = X509_NAME_add_entry(name, ne, loc, set);
+    X509_NAME_ENTRY_free(ne);
+    return ret;
 }
 
 int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type,
-			unsigned char *bytes, int len, int loc, int set)
+                               unsigned char *bytes, int len, int loc,
+                               int set)
 {
-	X509_NAME_ENTRY *ne;
-	int ret;
-	ne = X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len);
-	if(!ne) return 0;
-	ret = X509_NAME_add_entry(name, ne, loc, set);
-	X509_NAME_ENTRY_free(ne);
-	return ret;
+    X509_NAME_ENTRY *ne;
+    int ret;
+    ne = X509_NAME_ENTRY_create_by_NID(NULL, nid, type, bytes, len);
+    if (!ne)
+        return 0;
+    ret = X509_NAME_add_entry(name, ne, loc, set);
+    X509_NAME_ENTRY_free(ne);
+    return ret;
 }
 
 int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type,
-			const unsigned char *bytes, int len, int loc, int set)
+                               const unsigned char *bytes, int len, int loc,
+                               int set)
 {
-	X509_NAME_ENTRY *ne;
-	int ret;
-	ne = X509_NAME_ENTRY_create_by_txt(NULL, field, type, bytes, len);
-	if(!ne) return 0;
-	ret = X509_NAME_add_entry(name, ne, loc, set);
-	X509_NAME_ENTRY_free(ne);
-	return ret;
+    X509_NAME_ENTRY *ne;
+    int ret;
+    ne = X509_NAME_ENTRY_create_by_txt(NULL, field, type, bytes, len);
+    if (!ne)
+        return 0;
+    ret = X509_NAME_add_entry(name, ne, loc, set);
+    X509_NAME_ENTRY_free(ne);
+    return ret;
 }
 
-/* if set is -1, append to previous set, 0 'a new one', and 1,
- * prepend to the guy we are about to stomp on. */
+/*
+ * if set is -1, append to previous set, 0 'a new one', and 1, prepend to the
+ * guy we are about to stomp on.
+ */
 int X509_NAME_add_entry(X509_NAME *name, X509_NAME_ENTRY *ne, int loc,
-	     int set)
-	{
-	X509_NAME_ENTRY *new_name=NULL;
-	int n,i,inc;
-	STACK_OF(X509_NAME_ENTRY) *sk;
+                        int set)
+{
+    X509_NAME_ENTRY *new_name = NULL;
+    int n, i, inc;
+    STACK_OF(X509_NAME_ENTRY) *sk;
 
-	if (name == NULL) return(0);
-	sk=name->entries;
-	n=sk_X509_NAME_ENTRY_num(sk);
-	if (loc > n) loc=n;
-	else if (loc < 0) loc=n;
+    if (name == NULL)
+        return (0);
+    sk = name->entries;
+    n = sk_X509_NAME_ENTRY_num(sk);
+    if (loc > n)
+        loc = n;
+    else if (loc < 0)
+        loc = n;
 
-	name->modified=1;
+    name->modified = 1;
 
-	if (set == -1)
-		{
-		if (loc == 0)
-			{
-			set=0;
-			inc=1;
-			}
-		else
-			{
-			set=sk_X509_NAME_ENTRY_value(sk,loc-1)->set;
-			inc=0;
-			}
-		}
-	else /* if (set >= 0) */
-		{
-		if (loc >= n)
-			{
-			if (loc != 0)
-				set=sk_X509_NAME_ENTRY_value(sk,loc-1)->set+1;
-			else
-				set=0;
-			}
-		else
-			set=sk_X509_NAME_ENTRY_value(sk,loc)->set;
-		inc=(set == 0)?1:0;
-		}
+    if (set == -1) {
+        if (loc == 0) {
+            set = 0;
+            inc = 1;
+        } else {
+            set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set;
+            inc = 0;
+        }
+    } else {                    /* if (set >= 0) */
 
-	if ((new_name=X509_NAME_ENTRY_dup(ne)) == NULL)
-		goto err;
-	new_name->set=set;
-	if (!sk_X509_NAME_ENTRY_insert(sk,new_name,loc))
-		{
-		OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-		goto err;
-		}
-	if (inc)
-		{
-		n=sk_X509_NAME_ENTRY_num(sk);
-		for (i=loc+1; i<n; i++)
-			sk_X509_NAME_ENTRY_value(sk,i-1)->set+=1;
-		}	
-	return(1);
-err:
-	if (new_name != NULL)
-		X509_NAME_ENTRY_free(new_name);
-	return(0);
-	}
+        if (loc >= n) {
+            if (loc != 0)
+                set = sk_X509_NAME_ENTRY_value(sk, loc - 1)->set + 1;
+            else
+                set = 0;
+        } else
+            set = sk_X509_NAME_ENTRY_value(sk, loc)->set;
+        inc = (set == 0) ? 1 : 0;
+    }
+
+    if ((new_name = X509_NAME_ENTRY_dup(ne)) == NULL)
+        goto err;
+    new_name->set = set;
+    if (!sk_X509_NAME_ENTRY_insert(sk, new_name, loc)) {
+        OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+    if (inc) {
+        n = sk_X509_NAME_ENTRY_num(sk);
+        for (i = loc + 1; i < n; i++)
+            sk_X509_NAME_ENTRY_value(sk, i - 1)->set += 1;
+    }
+    return (1);
+ err:
+    if (new_name != NULL)
+        X509_NAME_ENTRY_free(new_name);
+    return (0);
+}
 
 X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_txt(X509_NAME_ENTRY **ne,
-		const char *field, int type, const unsigned char *bytes, int len)
-	{
-	ASN1_OBJECT *obj;
-	X509_NAME_ENTRY *nentry;
+                                               const char *field, int type,
+                                               const unsigned char *bytes,
+                                               int len)
+{
+    ASN1_OBJECT *obj;
+    X509_NAME_ENTRY *nentry;
 
-	obj=OBJ_txt2obj(field, 0);
-	if (obj == NULL)
-		{
-		OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_NAME);
-		ERR_add_error_data(2, "name=", field);
-		return(NULL);
-		}
-	nentry = X509_NAME_ENTRY_create_by_OBJ(ne,obj,type,bytes,len);
-	ASN1_OBJECT_free(obj);
-	return nentry;
-	}
+    obj = OBJ_txt2obj(field, 0);
+    if (obj == NULL) {
+        OPENSSL_PUT_ERROR(X509, X509_R_INVALID_FIELD_NAME);
+        ERR_add_error_data(2, "name=", field);
+        return (NULL);
+    }
+    nentry = X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len);
+    ASN1_OBJECT_free(obj);
+    return nentry;
+}
 
 X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_NID(X509_NAME_ENTRY **ne, int nid,
-	     int type, unsigned char *bytes, int len)
-	{
-	const ASN1_OBJECT *obj = OBJ_nid2obj(nid);
-	if (obj == NULL)
-		{
-		OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_NID);
-		return NULL;
-		}
-	return X509_NAME_ENTRY_create_by_OBJ(ne,obj,type,bytes,len);
-	}
+                                               int type, unsigned char *bytes,
+                                               int len)
+{
+    const ASN1_OBJECT *obj = OBJ_nid2obj(nid);
+    if (obj == NULL) {
+        OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_NID);
+        return NULL;
+    }
+    return X509_NAME_ENTRY_create_by_OBJ(ne, obj, type, bytes, len);
+}
 
 X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **ne,
-	     const ASN1_OBJECT *obj, int type, const unsigned char *bytes, int len)
-	{
-	X509_NAME_ENTRY *ret;
+                                               const ASN1_OBJECT *obj,
+                                               int type,
+                                               const unsigned char *bytes,
+                                               int len)
+{
+    X509_NAME_ENTRY *ret;
 
-	if ((ne == NULL) || (*ne == NULL))
-		{
-		if ((ret=X509_NAME_ENTRY_new()) == NULL)
-			return(NULL);
-		}
-	else
-		ret= *ne;
+    if ((ne == NULL) || (*ne == NULL)) {
+        if ((ret = X509_NAME_ENTRY_new()) == NULL)
+            return (NULL);
+    } else
+        ret = *ne;
 
-	if (!X509_NAME_ENTRY_set_object(ret,obj))
-		goto err;
-	if (!X509_NAME_ENTRY_set_data(ret,type,bytes,len))
-		goto err;
+    if (!X509_NAME_ENTRY_set_object(ret, obj))
+        goto err;
+    if (!X509_NAME_ENTRY_set_data(ret, type, bytes, len))
+        goto err;
 
-	if ((ne != NULL) && (*ne == NULL)) *ne=ret;
-	return(ret);
-err:
-	if ((ne == NULL) || (ret != *ne))
-		X509_NAME_ENTRY_free(ret);
-	return(NULL);
-	}
+    if ((ne != NULL) && (*ne == NULL))
+        *ne = ret;
+    return (ret);
+ err:
+    if ((ne == NULL) || (ret != *ne))
+        X509_NAME_ENTRY_free(ret);
+    return (NULL);
+}
 
 int X509_NAME_ENTRY_set_object(X509_NAME_ENTRY *ne, const ASN1_OBJECT *obj)
-	{
-	if ((ne == NULL) || (obj == NULL))
-		{
-		OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER);
-		return(0);
-		}
-	ASN1_OBJECT_free(ne->object);
-	ne->object=OBJ_dup(obj);
-	return((ne->object == NULL)?0:1);
-	}
+{
+    if ((ne == NULL) || (obj == NULL)) {
+        OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER);
+        return (0);
+    }
+    ASN1_OBJECT_free(ne->object);
+    ne->object = OBJ_dup(obj);
+    return ((ne->object == NULL) ? 0 : 1);
+}
 
 int X509_NAME_ENTRY_set_data(X509_NAME_ENTRY *ne, int type,
-	     const unsigned char *bytes, int len)
-	{
-	int i;
+                             const unsigned char *bytes, int len)
+{
+    int i;
 
-	if ((ne == NULL) || ((bytes == NULL) && (len != 0))) return(0);
-	if((type > 0) && (type & MBSTRING_FLAG)) 
-		return ASN1_STRING_set_by_NID(&ne->value, bytes,
-						len, type,
-					OBJ_obj2nid(ne->object)) ? 1 : 0;
-	if (len < 0) len=strlen((const char *)bytes);
-	i=ASN1_STRING_set(ne->value,bytes,len);
-	if (!i) return(0);
-	if (type != V_ASN1_UNDEF)
-		{
-		if (type == V_ASN1_APP_CHOOSE)
-			ne->value->type=ASN1_PRINTABLE_type(bytes,len);
-		else
-			ne->value->type=type;
-		}
-	return(1);
-	}
+    if ((ne == NULL) || ((bytes == NULL) && (len != 0)))
+        return (0);
+    if ((type > 0) && (type & MBSTRING_FLAG))
+        return ASN1_STRING_set_by_NID(&ne->value, bytes,
+                                      len, type,
+                                      OBJ_obj2nid(ne->object)) ? 1 : 0;
+    if (len < 0)
+        len = strlen((const char *)bytes);
+    i = ASN1_STRING_set(ne->value, bytes, len);
+    if (!i)
+        return (0);
+    if (type != V_ASN1_UNDEF) {
+        if (type == V_ASN1_APP_CHOOSE)
+            ne->value->type = ASN1_PRINTABLE_type(bytes, len);
+        else
+            ne->value->type = type;
+    }
+    return (1);
+}
 
 ASN1_OBJECT *X509_NAME_ENTRY_get_object(X509_NAME_ENTRY *ne)
-	{
-	if (ne == NULL) return(NULL);
-	return(ne->object);
-	}
+{
+    if (ne == NULL)
+        return (NULL);
+    return (ne->object);
+}
 
 ASN1_STRING *X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *ne)
-	{
-	if (ne == NULL) return(NULL);
-	return(ne->value);
-	}
-
+{
+    if (ne == NULL)
+        return (NULL);
+    return (ne->value);
+}
diff --git a/src/crypto/x509/x509rset.c b/src/crypto/x509/x509rset.c
index dbab555..c4e6683 100644
--- a/src/crypto/x509/x509rset.c
+++ b/src/crypto/x509/x509rset.c
@@ -59,22 +59,23 @@
 #include <openssl/obj.h>
 #include <openssl/x509.h>
 
-
 int X509_REQ_set_version(X509_REQ *x, long version)
-	{
-	if (x == NULL) return(0);
-	return(ASN1_INTEGER_set(x->req_info->version,version));
-	}
+{
+    if (x == NULL)
+        return (0);
+    return (ASN1_INTEGER_set(x->req_info->version, version));
+}
 
 int X509_REQ_set_subject_name(X509_REQ *x, X509_NAME *name)
-	{
-	if ((x == NULL) || (x->req_info == NULL)) return(0);
-	return(X509_NAME_set(&x->req_info->subject,name));
-	}
+{
+    if ((x == NULL) || (x->req_info == NULL))
+        return (0);
+    return (X509_NAME_set(&x->req_info->subject, name));
+}
 
 int X509_REQ_set_pubkey(X509_REQ *x, EVP_PKEY *pkey)
-	{
-	if ((x == NULL) || (x->req_info == NULL)) return(0);
-	return(X509_PUBKEY_set(&x->req_info->pubkey,pkey));
-	}
-
+{
+    if ((x == NULL) || (x->req_info == NULL))
+        return (0);
+    return (X509_PUBKEY_set(&x->req_info->pubkey, pkey));
+}
diff --git a/src/crypto/x509/x509spki.c b/src/crypto/x509/x509spki.c
index ccf93e0..4a9b95e 100644
--- a/src/crypto/x509/x509spki.c
+++ b/src/crypto/x509/x509spki.c
@@ -1,5 +1,7 @@
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999. */
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
+ */
 /* ====================================================================
  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
  *
@@ -8,7 +10,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -59,77 +61,77 @@
 #include <openssl/mem.h>
 #include <openssl/x509.h>
 
-
 int NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *x, EVP_PKEY *pkey)
 {
-	if ((x == NULL) || (x->spkac == NULL)) return(0);
-	return(X509_PUBKEY_set(&(x->spkac->pubkey),pkey));
+    if ((x == NULL) || (x->spkac == NULL))
+        return (0);
+    return (X509_PUBKEY_set(&(x->spkac->pubkey), pkey));
 }
 
 EVP_PKEY *NETSCAPE_SPKI_get_pubkey(NETSCAPE_SPKI *x)
 {
-	if ((x == NULL) || (x->spkac == NULL))
-		return(NULL);
-	return(X509_PUBKEY_get(x->spkac->pubkey));
+    if ((x == NULL) || (x->spkac == NULL))
+        return (NULL);
+    return (X509_PUBKEY_get(x->spkac->pubkey));
 }
 
 /* Load a Netscape SPKI from a base64 encoded string */
 
-NETSCAPE_SPKI * NETSCAPE_SPKI_b64_decode(const char *str, int len)
+NETSCAPE_SPKI *NETSCAPE_SPKI_b64_decode(const char *str, int len)
 {
-	unsigned char *spki_der;
-	const unsigned char *p;
-	size_t spki_len;
-	NETSCAPE_SPKI *spki;
-	if (len <= 0)
-		len = strlen(str);
-	if (!EVP_DecodedLength(&spki_len, len)) {
-		OPENSSL_PUT_ERROR(X509, X509_R_BASE64_DECODE_ERROR);
-		return NULL;
-	}
-	if (!(spki_der = OPENSSL_malloc(spki_len))) {
-		OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-		return NULL;
-	}
-	if (!EVP_DecodeBase64(spki_der, &spki_len, spki_len, (const uint8_t *)str, len)) {
-		OPENSSL_PUT_ERROR(X509, X509_R_BASE64_DECODE_ERROR);
-		OPENSSL_free(spki_der);
-		return NULL;
-	}
-	p = spki_der;
-	spki = d2i_NETSCAPE_SPKI(NULL, &p, spki_len);
-	OPENSSL_free(spki_der);
-	return spki;
+    unsigned char *spki_der;
+    const unsigned char *p;
+    size_t spki_len;
+    NETSCAPE_SPKI *spki;
+    if (len <= 0)
+        len = strlen(str);
+    if (!EVP_DecodedLength(&spki_len, len)) {
+        OPENSSL_PUT_ERROR(X509, X509_R_BASE64_DECODE_ERROR);
+        return NULL;
+    }
+    if (!(spki_der = OPENSSL_malloc(spki_len))) {
+        OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+    if (!EVP_DecodeBase64
+        (spki_der, &spki_len, spki_len, (const uint8_t *)str, len)) {
+        OPENSSL_PUT_ERROR(X509, X509_R_BASE64_DECODE_ERROR);
+        OPENSSL_free(spki_der);
+        return NULL;
+    }
+    p = spki_der;
+    spki = d2i_NETSCAPE_SPKI(NULL, &p, spki_len);
+    OPENSSL_free(spki_der);
+    return spki;
 }
 
 /* Generate a base64 encoded string from an SPKI */
 
-char * NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *spki)
+char *NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *spki)
 {
-	unsigned char *der_spki, *p;
-	char *b64_str;
-	size_t b64_len;
-	int der_len;
-	der_len = i2d_NETSCAPE_SPKI(spki, NULL);
-	if (!EVP_EncodedLength(&b64_len, der_len))
-		{
-		OPENSSL_PUT_ERROR(X509, ERR_R_OVERFLOW);
-		return NULL;
-		}
-	der_spki = OPENSSL_malloc(der_len);
-	if (der_spki == NULL) {
-		OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-		return NULL;
-	}
-	b64_str = OPENSSL_malloc(b64_len);
-	if (b64_str == NULL) {
-		OPENSSL_free(der_spki);
-		OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-		return NULL;
-	}
-	p = der_spki;
-	i2d_NETSCAPE_SPKI(spki, &p);
-	EVP_EncodeBlock((unsigned char *)b64_str, der_spki, der_len);
-	OPENSSL_free(der_spki);
-	return b64_str;
+    unsigned char *der_spki, *p;
+    char *b64_str;
+    size_t b64_len;
+    int der_len;
+    der_len = i2d_NETSCAPE_SPKI(spki, NULL);
+    if (!EVP_EncodedLength(&b64_len, der_len)) {
+        OPENSSL_PUT_ERROR(X509, ERR_R_OVERFLOW);
+        return NULL;
+    }
+    der_spki = OPENSSL_malloc(der_len);
+    if (der_spki == NULL) {
+        OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+    b64_str = OPENSSL_malloc(b64_len);
+    if (b64_str == NULL) {
+        OPENSSL_free(der_spki);
+        OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+    p = der_spki;
+    i2d_NETSCAPE_SPKI(spki, &p);
+    EVP_EncodeBlock((unsigned char *)b64_str, der_spki, der_len);
+    OPENSSL_free(der_spki);
+    return b64_str;
 }
diff --git a/src/crypto/x509/x509type.c b/src/crypto/x509/x509type.c
index e7c7935..d4f5a4d 100644
--- a/src/crypto/x509/x509type.c
+++ b/src/crypto/x509/x509type.c
@@ -58,71 +58,69 @@
 #include <openssl/obj.h>
 #include <openssl/x509.h>
 
-
 int X509_certificate_type(X509 *x, EVP_PKEY *pkey)
-	{
-	EVP_PKEY *pk;
-	int ret=0,i;
+{
+    EVP_PKEY *pk;
+    int ret = 0, i;
 
-	if (x == NULL) return(0);
+    if (x == NULL)
+        return (0);
 
-	if (pkey == NULL)
-		pk=X509_get_pubkey(x);
-	else
-		pk=pkey;
+    if (pkey == NULL)
+        pk = X509_get_pubkey(x);
+    else
+        pk = pkey;
 
-	if (pk == NULL) return(0);
+    if (pk == NULL)
+        return (0);
 
-	switch (pk->type)
-		{
-	case EVP_PKEY_RSA:
-		ret=EVP_PK_RSA|EVP_PKT_SIGN;
-/*		if (!sign only extension) */
-			ret|=EVP_PKT_ENC;
-	break;
-	case EVP_PKEY_DSA:
-		ret=EVP_PK_DSA|EVP_PKT_SIGN;
-		break;
-	case EVP_PKEY_EC:
-		ret=EVP_PK_EC|EVP_PKT_SIGN|EVP_PKT_EXCH;
-		break;
-	case EVP_PKEY_DH:
-		ret=EVP_PK_DH|EVP_PKT_EXCH;
-		break;	
-	case NID_id_GostR3410_94:
-	case NID_id_GostR3410_2001:
-		ret=EVP_PKT_EXCH|EVP_PKT_SIGN;
-		break;
-	default:
-		break;
-		}
+    switch (pk->type) {
+    case EVP_PKEY_RSA:
+        ret = EVP_PK_RSA | EVP_PKT_SIGN;
+/*              if (!sign only extension) */
+        ret |= EVP_PKT_ENC;
+        break;
+    case EVP_PKEY_DSA:
+        ret = EVP_PK_DSA | EVP_PKT_SIGN;
+        break;
+    case EVP_PKEY_EC:
+        ret = EVP_PK_EC | EVP_PKT_SIGN | EVP_PKT_EXCH;
+        break;
+    case EVP_PKEY_DH:
+        ret = EVP_PK_DH | EVP_PKT_EXCH;
+        break;
+    case NID_id_GostR3410_94:
+    case NID_id_GostR3410_2001:
+        ret = EVP_PKT_EXCH | EVP_PKT_SIGN;
+        break;
+    default:
+        break;
+    }
 
-	i=OBJ_obj2nid(x->sig_alg->algorithm);
-	if (i && OBJ_find_sigid_algs(i, NULL, &i))
-		{
+    i = OBJ_obj2nid(x->sig_alg->algorithm);
+    if (i && OBJ_find_sigid_algs(i, NULL, &i)) {
 
-		switch (i)
-			{
-		case NID_rsaEncryption:
-		case NID_rsa:
-			ret|=EVP_PKS_RSA;
-			break;
-		case NID_dsa:
-		case NID_dsa_2:
-			ret|=EVP_PKS_DSA;
-			break;
-		case NID_X9_62_id_ecPublicKey:
-			ret|=EVP_PKS_EC;
-			break;
-		default:
-			break;
-			}
-		}
+        switch (i) {
+        case NID_rsaEncryption:
+        case NID_rsa:
+            ret |= EVP_PKS_RSA;
+            break;
+        case NID_dsa:
+        case NID_dsa_2:
+            ret |= EVP_PKS_DSA;
+            break;
+        case NID_X9_62_id_ecPublicKey:
+            ret |= EVP_PKS_EC;
+            break;
+        default:
+            break;
+        }
+    }
 
-	if (EVP_PKEY_size(pk) <= 1024/8)/* /8 because it's 1024 bits we look
-					   for, not bytes */
-		ret|=EVP_PKT_EXP;
-	if(pkey==NULL) EVP_PKEY_free(pk);
-	return(ret);
-	}
-
+    if (EVP_PKEY_size(pk) <= 1024 / 8) /* /8 because it's 1024 bits we look
+                                        * for, not bytes */
+        ret |= EVP_PKT_EXP;
+    if (pkey == NULL)
+        EVP_PKEY_free(pk);
+    return (ret);
+}
diff --git a/src/crypto/x509/x_algor.c b/src/crypto/x509/x_algor.c
index ae694e3..abacd06 100644
--- a/src/crypto/x509/x_algor.c
+++ b/src/crypto/x509/x_algor.c
@@ -1,5 +1,7 @@
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 2000. */
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 2000.
+ */
 /* ====================================================================
  * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
  *
@@ -8,7 +10,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -61,12 +63,12 @@
 
 
 ASN1_SEQUENCE(X509_ALGOR) = {
-	ASN1_SIMPLE(X509_ALGOR, algorithm, ASN1_OBJECT),
-	ASN1_OPT(X509_ALGOR, parameter, ASN1_ANY)
+        ASN1_SIMPLE(X509_ALGOR, algorithm, ASN1_OBJECT),
+        ASN1_OPT(X509_ALGOR, parameter, ASN1_ANY)
 } ASN1_SEQUENCE_END(X509_ALGOR)
 
-ASN1_ITEM_TEMPLATE(X509_ALGORS) = 
-	ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, algorithms, X509_ALGOR)
+ASN1_ITEM_TEMPLATE(X509_ALGORS) =
+        ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, algorithms, X509_ALGOR)
 ASN1_ITEM_TEMPLATE_END(X509_ALGORS)
 
 IMPLEMENT_ASN1_FUNCTIONS(X509_ALGOR)
@@ -75,80 +77,75 @@
 
 IMPLEMENT_ASN1_SET_OF(X509_ALGOR)
 
-int X509_ALGOR_set0(X509_ALGOR *alg, const ASN1_OBJECT *aobj, int ptype, void *pval)
-	{
-	if (!alg)
-		return 0;
-	if (ptype != V_ASN1_UNDEF)
-		{
-		if (alg->parameter == NULL)
-			alg->parameter = ASN1_TYPE_new();
-		if (alg->parameter == NULL)
-			return 0;
-		}
-	if (alg)
-		{
-		if (alg->algorithm)
-			ASN1_OBJECT_free(alg->algorithm);
-		alg->algorithm = (ASN1_OBJECT*) aobj;
-		}
-	if (ptype == 0)
-		return 1;	
-	if (ptype == V_ASN1_UNDEF)
-		{
-		if (alg->parameter)
-			{
-			ASN1_TYPE_free(alg->parameter);
-			alg->parameter = NULL;
-			}
-		}
-	else
-		ASN1_TYPE_set(alg->parameter, ptype, pval);
-	return 1;
-	}
+int X509_ALGOR_set0(X509_ALGOR *alg, const ASN1_OBJECT *aobj, int ptype,
+                    void *pval)
+{
+    if (!alg)
+        return 0;
+    if (ptype != V_ASN1_UNDEF) {
+        if (alg->parameter == NULL)
+            alg->parameter = ASN1_TYPE_new();
+        if (alg->parameter == NULL)
+            return 0;
+    }
+    if (alg) {
+        if (alg->algorithm)
+            ASN1_OBJECT_free(alg->algorithm);
+        alg->algorithm = (ASN1_OBJECT *)aobj;
+    }
+    if (ptype == 0)
+        return 1;
+    if (ptype == V_ASN1_UNDEF) {
+        if (alg->parameter) {
+            ASN1_TYPE_free(alg->parameter);
+            alg->parameter = NULL;
+        }
+    } else
+        ASN1_TYPE_set(alg->parameter, ptype, pval);
+    return 1;
+}
 
 void X509_ALGOR_get0(ASN1_OBJECT **paobj, int *pptype, void **ppval,
-						X509_ALGOR *algor)
-	{
-	if (paobj)
-		*paobj = algor->algorithm;
-	if (pptype)
-		{
-		if (algor->parameter == NULL)
-			{
-			*pptype = V_ASN1_UNDEF;
-			return;
-			}
-		else
-			*pptype = algor->parameter->type;
-		if (ppval)
-			*ppval = algor->parameter->value.ptr;
-		}
-	}
+                     X509_ALGOR *algor)
+{
+    if (paobj)
+        *paobj = algor->algorithm;
+    if (pptype) {
+        if (algor->parameter == NULL) {
+            *pptype = V_ASN1_UNDEF;
+            return;
+        } else
+            *pptype = algor->parameter->type;
+        if (ppval)
+            *ppval = algor->parameter->value.ptr;
+    }
+}
 
 /* Set up an X509_ALGOR DigestAlgorithmIdentifier from an EVP_MD */
 
 void X509_ALGOR_set_md(X509_ALGOR *alg, const EVP_MD *md)
-	{
-	int param_type;
+{
+    int param_type;
 
-	if (EVP_MD_flags(md) & EVP_MD_FLAG_DIGALGID_ABSENT)
-		param_type = V_ASN1_UNDEF;
-	else
-		param_type = V_ASN1_NULL;
+    if (EVP_MD_flags(md) & EVP_MD_FLAG_DIGALGID_ABSENT)
+        param_type = V_ASN1_UNDEF;
+    else
+        param_type = V_ASN1_NULL;
 
-	X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_type(md)), param_type, NULL);
+    X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_MD_type(md)), param_type, NULL);
 
-	}
+}
 
-/* X509_ALGOR_cmp returns 0 if |a| and |b| are equal and non-zero otherwise. */
+/*
+ * X509_ALGOR_cmp returns 0 if |a| and |b| are equal and non-zero otherwise.
+ */
 int X509_ALGOR_cmp(const X509_ALGOR *a, const X509_ALGOR *b)
-	{
-	int rv;
-	rv = OBJ_cmp(a->algorithm, b->algorithm);
-	if (rv)
-		return rv;
-	if (!a->parameter && !b->parameter)
-		return 0;
-	return ASN1_TYPE_cmp(a->parameter, b->parameter);
-	}
+{
+    int rv;
+    rv = OBJ_cmp(a->algorithm, b->algorithm);
+    if (rv)
+        return rv;
+    if (!a->parameter && !b->parameter)
+        return 0;
+    return ASN1_TYPE_cmp(a->parameter, b->parameter);
+}
diff --git a/src/crypto/x509/x_all.c b/src/crypto/x509/x_all.c
index 62b3f40..c430a7d 100644
--- a/src/crypto/x509/x_all.c
+++ b/src/crypto/x509/x_all.c
@@ -63,435 +63,439 @@
 #include <openssl/stack.h>
 #include <openssl/x509.h>
 
-
 int X509_verify(X509 *a, EVP_PKEY *r)
-	{
-	if (X509_ALGOR_cmp(a->sig_alg, a->cert_info->signature))
-		return 0;
-	return(ASN1_item_verify(ASN1_ITEM_rptr(X509_CINF),a->sig_alg,
-		a->signature,a->cert_info,r));
-	}
+{
+    if (X509_ALGOR_cmp(a->sig_alg, a->cert_info->signature))
+        return 0;
+    return (ASN1_item_verify(ASN1_ITEM_rptr(X509_CINF), a->sig_alg,
+                             a->signature, a->cert_info, r));
+}
 
 int X509_REQ_verify(X509_REQ *a, EVP_PKEY *r)
-	{
-	return( ASN1_item_verify(ASN1_ITEM_rptr(X509_REQ_INFO),
-		a->sig_alg,a->signature,a->req_info,r));
-	}
+{
+    return (ASN1_item_verify(ASN1_ITEM_rptr(X509_REQ_INFO),
+                             a->sig_alg, a->signature, a->req_info, r));
+}
 
 int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md)
-	{
-	x->cert_info->enc.modified = 1;
-	return(ASN1_item_sign(ASN1_ITEM_rptr(X509_CINF), x->cert_info->signature,
-		x->sig_alg, x->signature, x->cert_info,pkey,md));
-	}
+{
+    x->cert_info->enc.modified = 1;
+    return (ASN1_item_sign(ASN1_ITEM_rptr(X509_CINF), x->cert_info->signature,
+                           x->sig_alg, x->signature, x->cert_info, pkey, md));
+}
 
 int X509_sign_ctx(X509 *x, EVP_MD_CTX *ctx)
-	{
-	x->cert_info->enc.modified = 1;
-	return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CINF),
-		x->cert_info->signature,
-		x->sig_alg, x->signature, x->cert_info, ctx);
-	}
+{
+    x->cert_info->enc.modified = 1;
+    return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CINF),
+                              x->cert_info->signature,
+                              x->sig_alg, x->signature, x->cert_info, ctx);
+}
 
 int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md)
-	{
-	return(ASN1_item_sign(ASN1_ITEM_rptr(X509_REQ_INFO),x->sig_alg, NULL,
-		x->signature, x->req_info,pkey,md));
-	}
+{
+    return (ASN1_item_sign(ASN1_ITEM_rptr(X509_REQ_INFO), x->sig_alg, NULL,
+                           x->signature, x->req_info, pkey, md));
+}
 
 int X509_REQ_sign_ctx(X509_REQ *x, EVP_MD_CTX *ctx)
-	{
-	return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_REQ_INFO),
-		x->sig_alg, NULL, x->signature, x->req_info, ctx);
-	}
+{
+    return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_REQ_INFO),
+                              x->sig_alg, NULL, x->signature, x->req_info,
+                              ctx);
+}
 
 int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md)
-	{
-	x->crl->enc.modified = 1;
-	return(ASN1_item_sign(ASN1_ITEM_rptr(X509_CRL_INFO),x->crl->sig_alg,
-		x->sig_alg, x->signature, x->crl,pkey,md));
-	}
+{
+    x->crl->enc.modified = 1;
+    return (ASN1_item_sign(ASN1_ITEM_rptr(X509_CRL_INFO), x->crl->sig_alg,
+                           x->sig_alg, x->signature, x->crl, pkey, md));
+}
 
 int X509_CRL_sign_ctx(X509_CRL *x, EVP_MD_CTX *ctx)
-	{
-	x->crl->enc.modified = 1;
-	return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CRL_INFO),
-		x->crl->sig_alg, x->sig_alg, x->signature, x->crl, ctx);
-	}
+{
+    x->crl->enc.modified = 1;
+    return ASN1_item_sign_ctx(ASN1_ITEM_rptr(X509_CRL_INFO),
+                              x->crl->sig_alg, x->sig_alg, x->signature,
+                              x->crl, ctx);
+}
 
 int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md)
-	{
-	return(ASN1_item_sign(ASN1_ITEM_rptr(NETSCAPE_SPKAC), x->sig_algor,NULL,
-		x->signature, x->spkac,pkey,md));
-	}
+{
+    return (ASN1_item_sign(ASN1_ITEM_rptr(NETSCAPE_SPKAC), x->sig_algor, NULL,
+                           x->signature, x->spkac, pkey, md));
+}
 
 int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *x, EVP_PKEY *pkey)
-	{
-	return (ASN1_item_verify(ASN1_ITEM_rptr(NETSCAPE_SPKAC), x->sig_algor,
-		x->signature, x->spkac, pkey));
-	}
+{
+    return (ASN1_item_verify(ASN1_ITEM_rptr(NETSCAPE_SPKAC), x->sig_algor,
+                             x->signature, x->spkac, pkey));
+}
 
 #ifndef OPENSSL_NO_FP_API
 X509 *d2i_X509_fp(FILE *fp, X509 **x509)
-	{
-	return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509), fp, x509);
-	}
+{
+    return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509), fp, x509);
+}
 
 int i2d_X509_fp(FILE *fp, X509 *x509)
-	{
-	return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509), fp, x509);
-	}
+{
+    return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509), fp, x509);
+}
 #endif
 
 X509 *d2i_X509_bio(BIO *bp, X509 **x509)
-	{
-	return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509), bp, x509);
-	}
+{
+    return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509), bp, x509);
+}
 
 int i2d_X509_bio(BIO *bp, X509 *x509)
-	{
-	return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509), bp, x509);
-	}
+{
+    return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509), bp, x509);
+}
 
 #ifndef OPENSSL_NO_FP_API
 X509_CRL *d2i_X509_CRL_fp(FILE *fp, X509_CRL **crl)
-	{
-	return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_CRL), fp, crl);
-	}
+{
+    return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_CRL), fp, crl);
+}
 
 int i2d_X509_CRL_fp(FILE *fp, X509_CRL *crl)
-	{
-	return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509_CRL), fp, crl);
-	}
+{
+    return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509_CRL), fp, crl);
+}
 #endif
 
 X509_CRL *d2i_X509_CRL_bio(BIO *bp, X509_CRL **crl)
-	{
-	return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509_CRL), bp, crl);
-	}
+{
+    return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509_CRL), bp, crl);
+}
 
 int i2d_X509_CRL_bio(BIO *bp, X509_CRL *crl)
-	{
-	return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509_CRL), bp, crl);
-	}
+{
+    return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509_CRL), bp, crl);
+}
 
 #ifndef OPENSSL_NO_FP_API
 X509_REQ *d2i_X509_REQ_fp(FILE *fp, X509_REQ **req)
-	{
-	return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_REQ), fp, req);
-	}
+{
+    return ASN1_item_d2i_fp(ASN1_ITEM_rptr(X509_REQ), fp, req);
+}
 
 int i2d_X509_REQ_fp(FILE *fp, X509_REQ *req)
-	{
-	return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509_REQ), fp, req);
-	}
+{
+    return ASN1_item_i2d_fp(ASN1_ITEM_rptr(X509_REQ), fp, req);
+}
 #endif
 
 X509_REQ *d2i_X509_REQ_bio(BIO *bp, X509_REQ **req)
-	{
-	return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509_REQ), bp, req);
-	}
+{
+    return ASN1_item_d2i_bio(ASN1_ITEM_rptr(X509_REQ), bp, req);
+}
 
 int i2d_X509_REQ_bio(BIO *bp, X509_REQ *req)
-	{
-	return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509_REQ), bp, req);
-	}
-
+{
+    return ASN1_item_i2d_bio(ASN1_ITEM_rptr(X509_REQ), bp, req);
+}
 
 #ifndef OPENSSL_NO_FP_API
 RSA *d2i_RSAPrivateKey_fp(FILE *fp, RSA **rsa)
-	{
-	return ASN1_d2i_fp_of(RSA, RSA_new, d2i_RSAPrivateKey, fp, rsa);
-	}
+{
+    return ASN1_d2i_fp_of(RSA, RSA_new, d2i_RSAPrivateKey, fp, rsa);
+}
 
 int i2d_RSAPrivateKey_fp(FILE *fp, RSA *rsa)
-	{
-	return ASN1_i2d_fp_of_const(RSA, i2d_RSAPrivateKey, fp, rsa);
-	}
+{
+    return ASN1_i2d_fp_of_const(RSA, i2d_RSAPrivateKey, fp, rsa);
+}
 
 RSA *d2i_RSAPublicKey_fp(FILE *fp, RSA **rsa)
-	{
-	return ASN1_d2i_fp_of(RSA, RSA_new, d2i_RSAPublicKey, fp, rsa);
-	}
+{
+    return ASN1_d2i_fp_of(RSA, RSA_new, d2i_RSAPublicKey, fp, rsa);
+}
 
 RSA *d2i_RSA_PUBKEY_fp(FILE *fp, RSA **rsa)
-	{
-	return ASN1_d2i_fp((void *(*)(void))
-			   RSA_new,(D2I_OF(void))d2i_RSA_PUBKEY, fp,
-			   (void **)rsa);
-	}
+{
+    return ASN1_d2i_fp((void *(*)(void))
+                       RSA_new, (D2I_OF(void)) d2i_RSA_PUBKEY, fp,
+                       (void **)rsa);
+}
 
 int i2d_RSAPublicKey_fp(FILE *fp, RSA *rsa)
-	{
-	return ASN1_i2d_fp_of_const(RSA, i2d_RSAPublicKey, fp, rsa);
-	}
+{
+    return ASN1_i2d_fp_of_const(RSA, i2d_RSAPublicKey, fp, rsa);
+}
 
 int i2d_RSA_PUBKEY_fp(FILE *fp, RSA *rsa)
-	{
-	return ASN1_i2d_fp((I2D_OF_const(void))i2d_RSA_PUBKEY,fp,rsa);
-	}
+{
+    return ASN1_i2d_fp((I2D_OF_const(void))i2d_RSA_PUBKEY, fp, rsa);
+}
 #endif
 
 RSA *d2i_RSAPrivateKey_bio(BIO *bp, RSA **rsa)
-	{
-	return ASN1_d2i_bio_of(RSA, RSA_new, d2i_RSAPrivateKey, bp, rsa);
-	}
+{
+    return ASN1_d2i_bio_of(RSA, RSA_new, d2i_RSAPrivateKey, bp, rsa);
+}
 
 int i2d_RSAPrivateKey_bio(BIO *bp, RSA *rsa)
-	{
-	return ASN1_i2d_bio_of_const(RSA, i2d_RSAPrivateKey, bp, rsa);
-	}
+{
+    return ASN1_i2d_bio_of_const(RSA, i2d_RSAPrivateKey, bp, rsa);
+}
 
 RSA *d2i_RSAPublicKey_bio(BIO *bp, RSA **rsa)
-	{
-	return ASN1_d2i_bio_of(RSA, RSA_new, d2i_RSAPublicKey, bp, rsa);
-	}
-
+{
+    return ASN1_d2i_bio_of(RSA, RSA_new, d2i_RSAPublicKey, bp, rsa);
+}
 
 RSA *d2i_RSA_PUBKEY_bio(BIO *bp, RSA **rsa)
-	{
-	return ASN1_d2i_bio_of(RSA,RSA_new,d2i_RSA_PUBKEY,bp,rsa);
-	}
+{
+    return ASN1_d2i_bio_of(RSA, RSA_new, d2i_RSA_PUBKEY, bp, rsa);
+}
 
 int i2d_RSAPublicKey_bio(BIO *bp, RSA *rsa)
-	{
-	return ASN1_i2d_bio_of_const(RSA, i2d_RSAPublicKey, bp, rsa);
-	}
+{
+    return ASN1_i2d_bio_of_const(RSA, i2d_RSAPublicKey, bp, rsa);
+}
 
 int i2d_RSA_PUBKEY_bio(BIO *bp, RSA *rsa)
-	{
-	return ASN1_i2d_bio_of_const(RSA,i2d_RSA_PUBKEY,bp,rsa);
-	}
+{
+    return ASN1_i2d_bio_of_const(RSA, i2d_RSA_PUBKEY, bp, rsa);
+}
 
 #ifndef OPENSSL_NO_DSA
-#ifndef OPENSSL_NO_FP_API
+# ifndef OPENSSL_NO_FP_API
 DSA *d2i_DSAPrivateKey_fp(FILE *fp, DSA **dsa)
-	{
-	return ASN1_d2i_fp_of(DSA,DSA_new,d2i_DSAPrivateKey,fp,dsa);
-	}
+{
+    return ASN1_d2i_fp_of(DSA, DSA_new, d2i_DSAPrivateKey, fp, dsa);
+}
 
 int i2d_DSAPrivateKey_fp(FILE *fp, DSA *dsa)
-	{
-	return ASN1_i2d_fp_of_const(DSA,i2d_DSAPrivateKey,fp,dsa);
-	}
+{
+    return ASN1_i2d_fp_of_const(DSA, i2d_DSAPrivateKey, fp, dsa);
+}
 
 DSA *d2i_DSA_PUBKEY_fp(FILE *fp, DSA **dsa)
-	{
-	return ASN1_d2i_fp_of(DSA,DSA_new,d2i_DSA_PUBKEY,fp,dsa);
-	}
+{
+    return ASN1_d2i_fp_of(DSA, DSA_new, d2i_DSA_PUBKEY, fp, dsa);
+}
 
 int i2d_DSA_PUBKEY_fp(FILE *fp, DSA *dsa)
-	{
-	return ASN1_i2d_fp_of_const(DSA,i2d_DSA_PUBKEY,fp,dsa);
-	}
-#endif
+{
+    return ASN1_i2d_fp_of_const(DSA, i2d_DSA_PUBKEY, fp, dsa);
+}
+# endif
 
 DSA *d2i_DSAPrivateKey_bio(BIO *bp, DSA **dsa)
-	{
-	return ASN1_d2i_bio_of(DSA,DSA_new,d2i_DSAPrivateKey,bp,dsa
-);
-	}
+{
+    return ASN1_d2i_bio_of(DSA, DSA_new, d2i_DSAPrivateKey, bp, dsa);
+}
 
 int i2d_DSAPrivateKey_bio(BIO *bp, DSA *dsa)
-	{
-	return ASN1_i2d_bio_of_const(DSA,i2d_DSAPrivateKey,bp,dsa);
-	}
+{
+    return ASN1_i2d_bio_of_const(DSA, i2d_DSAPrivateKey, bp, dsa);
+}
 
 DSA *d2i_DSA_PUBKEY_bio(BIO *bp, DSA **dsa)
-	{
-	return ASN1_d2i_bio_of(DSA,DSA_new,d2i_DSA_PUBKEY,bp,dsa);
-	}
+{
+    return ASN1_d2i_bio_of(DSA, DSA_new, d2i_DSA_PUBKEY, bp, dsa);
+}
 
 int i2d_DSA_PUBKEY_bio(BIO *bp, DSA *dsa)
-	{
-	return ASN1_i2d_bio_of_const(DSA,i2d_DSA_PUBKEY,bp,dsa);
-	}
+{
+    return ASN1_i2d_bio_of_const(DSA, i2d_DSA_PUBKEY, bp, dsa);
+}
 
 #endif
 
 #ifndef OPENSSL_NO_FP_API
 EC_KEY *d2i_EC_PUBKEY_fp(FILE *fp, EC_KEY **eckey)
-	{
-	return ASN1_d2i_fp_of(EC_KEY,EC_KEY_new,d2i_EC_PUBKEY,fp,eckey);
-	}
-  
+{
+    return ASN1_d2i_fp_of(EC_KEY, EC_KEY_new, d2i_EC_PUBKEY, fp, eckey);
+}
+
 int i2d_EC_PUBKEY_fp(FILE *fp, EC_KEY *eckey)
-	{
-	return ASN1_i2d_fp_of_const(EC_KEY,i2d_EC_PUBKEY,fp,eckey);
-	}
+{
+    return ASN1_i2d_fp_of_const(EC_KEY, i2d_EC_PUBKEY, fp, eckey);
+}
 
 EC_KEY *d2i_ECPrivateKey_fp(FILE *fp, EC_KEY **eckey)
-	{
-	return ASN1_d2i_fp_of(EC_KEY,EC_KEY_new,d2i_ECPrivateKey,fp,eckey);
-	}
-  
+{
+    return ASN1_d2i_fp_of(EC_KEY, EC_KEY_new, d2i_ECPrivateKey, fp, eckey);
+}
+
 int i2d_ECPrivateKey_fp(FILE *fp, EC_KEY *eckey)
-	{
-	return ASN1_i2d_fp_of_const(EC_KEY,i2d_ECPrivateKey,fp,eckey);
-	}
+{
+    return ASN1_i2d_fp_of_const(EC_KEY, i2d_ECPrivateKey, fp, eckey);
+}
 #endif
 EC_KEY *d2i_EC_PUBKEY_bio(BIO *bp, EC_KEY **eckey)
-	{
-	return ASN1_d2i_bio_of(EC_KEY,EC_KEY_new,d2i_EC_PUBKEY,bp,eckey);
-	}
-  
+{
+    return ASN1_d2i_bio_of(EC_KEY, EC_KEY_new, d2i_EC_PUBKEY, bp, eckey);
+}
+
 int i2d_EC_PUBKEY_bio(BIO *bp, EC_KEY *ecdsa)
-	{
-	return ASN1_i2d_bio_of_const(EC_KEY,i2d_EC_PUBKEY,bp,ecdsa);
-	}
+{
+    return ASN1_i2d_bio_of_const(EC_KEY, i2d_EC_PUBKEY, bp, ecdsa);
+}
 
 EC_KEY *d2i_ECPrivateKey_bio(BIO *bp, EC_KEY **eckey)
-	{
-	return ASN1_d2i_bio_of(EC_KEY,EC_KEY_new,d2i_ECPrivateKey,bp,eckey);
-	}
-  
+{
+    return ASN1_d2i_bio_of(EC_KEY, EC_KEY_new, d2i_ECPrivateKey, bp, eckey);
+}
+
 int i2d_ECPrivateKey_bio(BIO *bp, EC_KEY *eckey)
-	{
-	return ASN1_i2d_bio_of_const(EC_KEY,i2d_ECPrivateKey,bp,eckey);
-	}
+{
+    return ASN1_i2d_bio_of_const(EC_KEY, i2d_ECPrivateKey, bp, eckey);
+}
 
-
-int X509_pubkey_digest(const X509 *data, const EVP_MD *type, unsigned char *md,
-	     unsigned int *len)
-	{
-	ASN1_BIT_STRING *key;
-	key = X509_get0_pubkey_bitstr(data);
-	if(!key) return 0;
-	return EVP_Digest(key->data, key->length, md, len, type, NULL);
-	}
+int X509_pubkey_digest(const X509 *data, const EVP_MD *type,
+                       unsigned char *md, unsigned int *len)
+{
+    ASN1_BIT_STRING *key;
+    key = X509_get0_pubkey_bitstr(data);
+    if (!key)
+        return 0;
+    return EVP_Digest(key->data, key->length, md, len, type, NULL);
+}
 
 int X509_digest(const X509 *data, const EVP_MD *type, unsigned char *md,
-	     unsigned int *len)
-	{
-	return(ASN1_item_digest(ASN1_ITEM_rptr(X509),type,(char *)data,md,len));
-	}
+                unsigned int *len)
+{
+    return (ASN1_item_digest
+            (ASN1_ITEM_rptr(X509), type, (char *)data, md, len));
+}
 
-int X509_CRL_digest(const X509_CRL *data, const EVP_MD *type, unsigned char *md,
-	     unsigned int *len)
-	{
-	return(ASN1_item_digest(ASN1_ITEM_rptr(X509_CRL),type,(char *)data,md,len));
-	}
+int X509_CRL_digest(const X509_CRL *data, const EVP_MD *type,
+                    unsigned char *md, unsigned int *len)
+{
+    return (ASN1_item_digest
+            (ASN1_ITEM_rptr(X509_CRL), type, (char *)data, md, len));
+}
 
-int X509_REQ_digest(const X509_REQ *data, const EVP_MD *type, unsigned char *md,
-	     unsigned int *len)
-	{
-	return(ASN1_item_digest(ASN1_ITEM_rptr(X509_REQ),type,(char *)data,md,len));
-	}
+int X509_REQ_digest(const X509_REQ *data, const EVP_MD *type,
+                    unsigned char *md, unsigned int *len)
+{
+    return (ASN1_item_digest
+            (ASN1_ITEM_rptr(X509_REQ), type, (char *)data, md, len));
+}
 
-int X509_NAME_digest(const X509_NAME *data, const EVP_MD *type, unsigned char *md,
-	     unsigned int *len)
-	{
-	return(ASN1_item_digest(ASN1_ITEM_rptr(X509_NAME),type,(char *)data,md,len));
-	}
+int X509_NAME_digest(const X509_NAME *data, const EVP_MD *type,
+                     unsigned char *md, unsigned int *len)
+{
+    return (ASN1_item_digest
+            (ASN1_ITEM_rptr(X509_NAME), type, (char *)data, md, len));
+}
 
 #ifndef OPENSSL_NO_FP_API
 X509_SIG *d2i_PKCS8_fp(FILE *fp, X509_SIG **p8)
-	{
-	return ASN1_d2i_fp_of(X509_SIG,X509_SIG_new,d2i_X509_SIG,fp,p8);
-	}
+{
+    return ASN1_d2i_fp_of(X509_SIG, X509_SIG_new, d2i_X509_SIG, fp, p8);
+}
 
 int i2d_PKCS8_fp(FILE *fp, X509_SIG *p8)
-	{
-	return ASN1_i2d_fp_of(X509_SIG,i2d_X509_SIG,fp,p8);
-	}
+{
+    return ASN1_i2d_fp_of(X509_SIG, i2d_X509_SIG, fp, p8);
+}
 #endif
 
 X509_SIG *d2i_PKCS8_bio(BIO *bp, X509_SIG **p8)
-	{
-	return ASN1_d2i_bio_of(X509_SIG,X509_SIG_new,d2i_X509_SIG,bp,p8);
-	}
+{
+    return ASN1_d2i_bio_of(X509_SIG, X509_SIG_new, d2i_X509_SIG, bp, p8);
+}
 
 int i2d_PKCS8_bio(BIO *bp, X509_SIG *p8)
-	{
-	return ASN1_i2d_bio_of(X509_SIG,i2d_X509_SIG,bp,p8);
-	}
+{
+    return ASN1_i2d_bio_of(X509_SIG, i2d_X509_SIG, bp, p8);
+}
 
 #ifndef OPENSSL_NO_FP_API
 PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_fp(FILE *fp,
-						 PKCS8_PRIV_KEY_INFO **p8inf)
-	{
-	return ASN1_d2i_fp_of(PKCS8_PRIV_KEY_INFO,PKCS8_PRIV_KEY_INFO_new,
-			      d2i_PKCS8_PRIV_KEY_INFO,fp,p8inf);
-	}
+                                                PKCS8_PRIV_KEY_INFO **p8inf)
+{
+    return ASN1_d2i_fp_of(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_new,
+                          d2i_PKCS8_PRIV_KEY_INFO, fp, p8inf);
+}
 
 int i2d_PKCS8_PRIV_KEY_INFO_fp(FILE *fp, PKCS8_PRIV_KEY_INFO *p8inf)
-	{
-	return ASN1_i2d_fp_of(PKCS8_PRIV_KEY_INFO,i2d_PKCS8_PRIV_KEY_INFO,fp,
-			      p8inf);
-	}
+{
+    return ASN1_i2d_fp_of(PKCS8_PRIV_KEY_INFO, i2d_PKCS8_PRIV_KEY_INFO, fp,
+                          p8inf);
+}
 
 int i2d_PKCS8PrivateKeyInfo_fp(FILE *fp, EVP_PKEY *key)
-	{
-	PKCS8_PRIV_KEY_INFO *p8inf;
-	int ret;
-	p8inf = EVP_PKEY2PKCS8(key);
-	if(!p8inf) return 0;
-	ret = i2d_PKCS8_PRIV_KEY_INFO_fp(fp, p8inf);
-	PKCS8_PRIV_KEY_INFO_free(p8inf);
-	return ret;
-	}
+{
+    PKCS8_PRIV_KEY_INFO *p8inf;
+    int ret;
+    p8inf = EVP_PKEY2PKCS8(key);
+    if (!p8inf)
+        return 0;
+    ret = i2d_PKCS8_PRIV_KEY_INFO_fp(fp, p8inf);
+    PKCS8_PRIV_KEY_INFO_free(p8inf);
+    return ret;
+}
 
 int i2d_PrivateKey_fp(FILE *fp, EVP_PKEY *pkey)
-	{
-	return ASN1_i2d_fp_of_const(EVP_PKEY,i2d_PrivateKey,fp,pkey);
-	}
+{
+    return ASN1_i2d_fp_of_const(EVP_PKEY, i2d_PrivateKey, fp, pkey);
+}
 
 EVP_PKEY *d2i_PrivateKey_fp(FILE *fp, EVP_PKEY **a)
 {
-	return ASN1_d2i_fp_of(EVP_PKEY,EVP_PKEY_new,d2i_AutoPrivateKey,fp,a);
+    return ASN1_d2i_fp_of(EVP_PKEY, EVP_PKEY_new, d2i_AutoPrivateKey, fp, a);
 }
 
 int i2d_PUBKEY_fp(FILE *fp, EVP_PKEY *pkey)
-	{
-	return ASN1_i2d_fp_of_const(EVP_PKEY,i2d_PUBKEY,fp,pkey);
-	}
+{
+    return ASN1_i2d_fp_of_const(EVP_PKEY, i2d_PUBKEY, fp, pkey);
+}
 
 EVP_PKEY *d2i_PUBKEY_fp(FILE *fp, EVP_PKEY **a)
 {
-	return ASN1_d2i_fp_of(EVP_PKEY,EVP_PKEY_new,d2i_PUBKEY,fp,a);
+    return ASN1_d2i_fp_of(EVP_PKEY, EVP_PKEY_new, d2i_PUBKEY, fp, a);
 }
 
 PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO_bio(BIO *bp,
-						 PKCS8_PRIV_KEY_INFO **p8inf)
-	{
-	return ASN1_d2i_bio_of(PKCS8_PRIV_KEY_INFO,PKCS8_PRIV_KEY_INFO_new,
-			    d2i_PKCS8_PRIV_KEY_INFO,bp,p8inf);
-	}
+                                                 PKCS8_PRIV_KEY_INFO **p8inf)
+{
+    return ASN1_d2i_bio_of(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_new,
+                           d2i_PKCS8_PRIV_KEY_INFO, bp, p8inf);
+}
 
 int i2d_PKCS8_PRIV_KEY_INFO_bio(BIO *bp, PKCS8_PRIV_KEY_INFO *p8inf)
-	{
-	return ASN1_i2d_bio_of(PKCS8_PRIV_KEY_INFO,i2d_PKCS8_PRIV_KEY_INFO,bp,
-			       p8inf);
-	}
+{
+    return ASN1_i2d_bio_of(PKCS8_PRIV_KEY_INFO, i2d_PKCS8_PRIV_KEY_INFO, bp,
+                           p8inf);
+}
 
 int i2d_PKCS8PrivateKeyInfo_bio(BIO *bp, EVP_PKEY *key)
-	{
-	PKCS8_PRIV_KEY_INFO *p8inf;
-	int ret;
-	p8inf = EVP_PKEY2PKCS8(key);
-	if(!p8inf) return 0;
-	ret = i2d_PKCS8_PRIV_KEY_INFO_bio(bp, p8inf);
-	PKCS8_PRIV_KEY_INFO_free(p8inf);
-	return ret;
-	}
+{
+    PKCS8_PRIV_KEY_INFO *p8inf;
+    int ret;
+    p8inf = EVP_PKEY2PKCS8(key);
+    if (!p8inf)
+        return 0;
+    ret = i2d_PKCS8_PRIV_KEY_INFO_bio(bp, p8inf);
+    PKCS8_PRIV_KEY_INFO_free(p8inf);
+    return ret;
+}
 #endif
 
 int i2d_PrivateKey_bio(BIO *bp, EVP_PKEY *pkey)
-	{
-	return ASN1_i2d_bio_of_const(EVP_PKEY,i2d_PrivateKey,bp,pkey);
-	}
+{
+    return ASN1_i2d_bio_of_const(EVP_PKEY, i2d_PrivateKey, bp, pkey);
+}
 
 EVP_PKEY *d2i_PrivateKey_bio(BIO *bp, EVP_PKEY **a)
-	{
-	return ASN1_d2i_bio_of(EVP_PKEY,EVP_PKEY_new,d2i_AutoPrivateKey,bp,a);
-	}
+{
+    return ASN1_d2i_bio_of(EVP_PKEY, EVP_PKEY_new, d2i_AutoPrivateKey, bp, a);
+}
 
 int i2d_PUBKEY_bio(BIO *bp, EVP_PKEY *pkey)
-	{
-	return ASN1_i2d_bio_of_const(EVP_PKEY,i2d_PUBKEY,bp,pkey);
-	}
+{
+    return ASN1_i2d_bio_of_const(EVP_PKEY, i2d_PUBKEY, bp, pkey);
+}
 
 EVP_PKEY *d2i_PUBKEY_bio(BIO *bp, EVP_PKEY **a)
-	{
-	return ASN1_d2i_bio_of(EVP_PKEY,EVP_PKEY_new,d2i_PUBKEY,bp,a);
-	}
+{
+    return ASN1_d2i_bio_of(EVP_PKEY, EVP_PKEY_new, d2i_PUBKEY, bp, a);
+}
diff --git a/src/crypto/x509/x_attrib.c b/src/crypto/x509/x_attrib.c
index c460a70..de8c95c 100644
--- a/src/crypto/x509/x_attrib.c
+++ b/src/crypto/x509/x_attrib.c
@@ -59,59 +59,53 @@
 #include <openssl/x509.h>
 #include <openssl/obj.h>
 
-
-/* X509_ATTRIBUTE: this has the following form:
- *
- * typedef struct x509_attributes_st
- *	{
- *	ASN1_OBJECT *object;
- *	int single;
- *	union	{
- *		char		*ptr;
- * 		STACK_OF(ASN1_TYPE) *set;
- * 		ASN1_TYPE	*single;
- *		} value;
- *	} X509_ATTRIBUTE;
- *
- * this needs some extra thought because the CHOICE type is
- * merged with the main structure and because the value can
- * be anything at all we *must* try the SET OF first because
- * the ASN1_ANY type will swallow anything including the whole
- * SET OF structure.
+/*
+ * X509_ATTRIBUTE: this has the following form: typedef struct
+ * x509_attributes_st { ASN1_OBJECT *object; int single; union { char *ptr;
+ * STACK_OF(ASN1_TYPE) *set; ASN1_TYPE *single; } value; } X509_ATTRIBUTE;
+ * this needs some extra thought because the CHOICE type is merged with the
+ * main structure and because the value can be anything at all we *must* try
+ * the SET OF first because the ASN1_ANY type will swallow anything including
+ * the whole SET OF structure.
  */
 
 ASN1_CHOICE(X509_ATTRIBUTE_SET) = {
-	ASN1_SET_OF(X509_ATTRIBUTE, value.set, ASN1_ANY),
-	ASN1_SIMPLE(X509_ATTRIBUTE, value.single, ASN1_ANY)
+        ASN1_SET_OF(X509_ATTRIBUTE, value.set, ASN1_ANY),
+        ASN1_SIMPLE(X509_ATTRIBUTE, value.single, ASN1_ANY)
 } ASN1_CHOICE_END_selector(X509_ATTRIBUTE, X509_ATTRIBUTE_SET, single)
 
 ASN1_SEQUENCE(X509_ATTRIBUTE) = {
-	ASN1_SIMPLE(X509_ATTRIBUTE, object, ASN1_OBJECT),
-	/* CHOICE type merged with parent */
-	ASN1_EX_COMBINE(0, 0, X509_ATTRIBUTE_SET)
+        ASN1_SIMPLE(X509_ATTRIBUTE, object, ASN1_OBJECT),
+        /* CHOICE type merged with parent */
+        ASN1_EX_COMBINE(0, 0, X509_ATTRIBUTE_SET)
 } ASN1_SEQUENCE_END(X509_ATTRIBUTE)
 
 IMPLEMENT_ASN1_FUNCTIONS(X509_ATTRIBUTE)
 IMPLEMENT_ASN1_DUP_FUNCTION(X509_ATTRIBUTE)
 
 X509_ATTRIBUTE *X509_ATTRIBUTE_create(int nid, int atrtype, void *value)
-	{
-	X509_ATTRIBUTE *ret=NULL;
-	ASN1_TYPE *val=NULL;
+{
+    X509_ATTRIBUTE *ret = NULL;
+    ASN1_TYPE *val = NULL;
 
-	if ((ret=X509_ATTRIBUTE_new()) == NULL)
-		return(NULL);
-        /* TODO(fork): const correctness. */
-	ret->object=(ASN1_OBJECT*) OBJ_nid2obj(nid);
-	ret->single=0;
-	if ((ret->value.set=sk_ASN1_TYPE_new_null()) == NULL) goto err;
-	if ((val=ASN1_TYPE_new()) == NULL) goto err;
-	if (!sk_ASN1_TYPE_push(ret->value.set,val)) goto err;
+    if ((ret = X509_ATTRIBUTE_new()) == NULL)
+        return (NULL);
+    /* TODO(fork): const correctness. */
+    ret->object = (ASN1_OBJECT *)OBJ_nid2obj(nid);
+    ret->single = 0;
+    if ((ret->value.set = sk_ASN1_TYPE_new_null()) == NULL)
+        goto err;
+    if ((val = ASN1_TYPE_new()) == NULL)
+        goto err;
+    if (!sk_ASN1_TYPE_push(ret->value.set, val))
+        goto err;
 
-	ASN1_TYPE_set(val,atrtype,value);
-	return(ret);
-err:
-	if (ret != NULL) X509_ATTRIBUTE_free(ret);
-	if (val != NULL) ASN1_TYPE_free(val);
-	return(NULL);
-	}
+    ASN1_TYPE_set(val, atrtype, value);
+    return (ret);
+ err:
+    if (ret != NULL)
+        X509_ATTRIBUTE_free(ret);
+    if (val != NULL)
+        ASN1_TYPE_free(val);
+    return (NULL);
+}
diff --git a/src/crypto/x509/x_crl.c b/src/crypto/x509/x_crl.c
index d516872..6450e84 100644
--- a/src/crypto/x509/x_crl.c
+++ b/src/crypto/x509/x_crl.c
@@ -67,494 +67,475 @@
 
 #include "../internal.h"
 
-
-/* Method to handle CRL access.
- * In general a CRL could be very large (several Mb) and can consume large
- * amounts of resources if stored in memory by multiple processes.
- * This method allows general CRL operations to be redirected to more
- * efficient callbacks: for example a CRL entry database.
+/*
+ * Method to handle CRL access. In general a CRL could be very large (several
+ * Mb) and can consume large amounts of resources if stored in memory by
+ * multiple processes. This method allows general CRL operations to be
+ * redirected to more efficient callbacks: for example a CRL entry database.
  */
 
-#define X509_CRL_METHOD_DYNAMIC		1
+#define X509_CRL_METHOD_DYNAMIC         1
 
-struct x509_crl_method_st
-	{
-	int flags;
-	int (*crl_init)(X509_CRL *crl);
-	int (*crl_free)(X509_CRL *crl);
-	int (*crl_lookup)(X509_CRL *crl, X509_REVOKED **ret,
-				ASN1_INTEGER *ser, X509_NAME *issuer);
-	int (*crl_verify)(X509_CRL *crl, EVP_PKEY *pk);
-	};
+struct x509_crl_method_st {
+    int flags;
+    int (*crl_init) (X509_CRL *crl);
+    int (*crl_free) (X509_CRL *crl);
+    int (*crl_lookup) (X509_CRL *crl, X509_REVOKED **ret,
+                       ASN1_INTEGER *ser, X509_NAME *issuer);
+    int (*crl_verify) (X509_CRL *crl, EVP_PKEY *pk);
+};
 
-static int X509_REVOKED_cmp(const X509_REVOKED **a,
-				const X509_REVOKED **b);
+static int X509_REVOKED_cmp(const X509_REVOKED **a, const X509_REVOKED **b);
 static void setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp);
 
 ASN1_SEQUENCE(X509_REVOKED) = {
-	ASN1_SIMPLE(X509_REVOKED,serialNumber, ASN1_INTEGER),
-	ASN1_SIMPLE(X509_REVOKED,revocationDate, ASN1_TIME),
-	ASN1_SEQUENCE_OF_OPT(X509_REVOKED,extensions, X509_EXTENSION)
+        ASN1_SIMPLE(X509_REVOKED,serialNumber, ASN1_INTEGER),
+        ASN1_SIMPLE(X509_REVOKED,revocationDate, ASN1_TIME),
+        ASN1_SEQUENCE_OF_OPT(X509_REVOKED,extensions, X509_EXTENSION)
 } ASN1_SEQUENCE_END(X509_REVOKED)
 
 static int def_crl_verify(X509_CRL *crl, EVP_PKEY *r);
 static int def_crl_lookup(X509_CRL *crl,
-		X509_REVOKED **ret, ASN1_INTEGER *serial, X509_NAME *issuer);
+                          X509_REVOKED **ret, ASN1_INTEGER *serial,
+                          X509_NAME *issuer);
 
-static const X509_CRL_METHOD int_crl_meth =
-	{
-	0,
-	0,0,
-	def_crl_lookup,
-	def_crl_verify
-	};
+static const X509_CRL_METHOD int_crl_meth = {
+    0,
+    0, 0,
+    def_crl_lookup,
+    def_crl_verify
+};
 
 static const X509_CRL_METHOD *default_crl_method = &int_crl_meth;
 
-/* The X509_CRL_INFO structure needs a bit of customisation.
- * Since we cache the original encoding the signature wont be affected by
- * reordering of the revoked field.
+/*
+ * The X509_CRL_INFO structure needs a bit of customisation. Since we cache
+ * the original encoding the signature wont be affected by reordering of the
+ * revoked field.
  */
 static int crl_inf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
-								void *exarg)
+                      void *exarg)
 {
-	X509_CRL_INFO *a = (X509_CRL_INFO *)*pval;
+    X509_CRL_INFO *a = (X509_CRL_INFO *)*pval;
 
-	if(!a || !a->revoked) return 1;
-	switch(operation) {
-		/* Just set cmp function here. We don't sort because that
-		 * would affect the output of X509_CRL_print().
-		 */
-		case ASN1_OP_D2I_POST:
-		(void)sk_X509_REVOKED_set_cmp_func(a->revoked,X509_REVOKED_cmp);
-		break;
-	}
-	return 1;
+    if (!a || !a->revoked)
+        return 1;
+    switch (operation) {
+        /*
+         * Just set cmp function here. We don't sort because that would
+         * affect the output of X509_CRL_print().
+         */
+    case ASN1_OP_D2I_POST:
+        (void)sk_X509_REVOKED_set_cmp_func(a->revoked, X509_REVOKED_cmp);
+        break;
+    }
+    return 1;
 }
 
 
 ASN1_SEQUENCE_enc(X509_CRL_INFO, enc, crl_inf_cb) = {
-	ASN1_OPT(X509_CRL_INFO, version, ASN1_INTEGER),
-	ASN1_SIMPLE(X509_CRL_INFO, sig_alg, X509_ALGOR),
-	ASN1_SIMPLE(X509_CRL_INFO, issuer, X509_NAME),
-	ASN1_SIMPLE(X509_CRL_INFO, lastUpdate, ASN1_TIME),
-	ASN1_OPT(X509_CRL_INFO, nextUpdate, ASN1_TIME),
-	ASN1_SEQUENCE_OF_OPT(X509_CRL_INFO, revoked, X509_REVOKED),
-	ASN1_EXP_SEQUENCE_OF_OPT(X509_CRL_INFO, extensions, X509_EXTENSION, 0)
+        ASN1_OPT(X509_CRL_INFO, version, ASN1_INTEGER),
+        ASN1_SIMPLE(X509_CRL_INFO, sig_alg, X509_ALGOR),
+        ASN1_SIMPLE(X509_CRL_INFO, issuer, X509_NAME),
+        ASN1_SIMPLE(X509_CRL_INFO, lastUpdate, ASN1_TIME),
+        ASN1_OPT(X509_CRL_INFO, nextUpdate, ASN1_TIME),
+        ASN1_SEQUENCE_OF_OPT(X509_CRL_INFO, revoked, X509_REVOKED),
+        ASN1_EXP_SEQUENCE_OF_OPT(X509_CRL_INFO, extensions, X509_EXTENSION, 0)
 } ASN1_SEQUENCE_END_enc(X509_CRL_INFO, X509_CRL_INFO)
 
-/* Set CRL entry issuer according to CRL certificate issuer extension.
- * Check for unhandled critical CRL entry extensions.
+/*
+ * Set CRL entry issuer according to CRL certificate issuer extension. Check
+ * for unhandled critical CRL entry extensions.
  */
 
 static int crl_set_issuers(X509_CRL *crl)
-	{
+{
 
-	size_t i, k;
-	int j;
-	GENERAL_NAMES *gens, *gtmp;
-	STACK_OF(X509_REVOKED) *revoked;
+    size_t i, k;
+    int j;
+    GENERAL_NAMES *gens, *gtmp;
+    STACK_OF(X509_REVOKED) *revoked;
 
-	revoked = X509_CRL_get_REVOKED(crl);
+    revoked = X509_CRL_get_REVOKED(crl);
 
-	gens = NULL;
-	for (i = 0; i < sk_X509_REVOKED_num(revoked); i++)
-		{
-		X509_REVOKED *rev = sk_X509_REVOKED_value(revoked, i);
-		STACK_OF(X509_EXTENSION) *exts;
-		ASN1_ENUMERATED *reason;
-		X509_EXTENSION *ext;
-		gtmp = X509_REVOKED_get_ext_d2i(rev, 
-						NID_certificate_issuer,
-						&j, NULL);
-		if (!gtmp && (j != -1))
-			{
-			crl->flags |= EXFLAG_INVALID;
-			return 1;
-			}
+    gens = NULL;
+    for (i = 0; i < sk_X509_REVOKED_num(revoked); i++) {
+        X509_REVOKED *rev = sk_X509_REVOKED_value(revoked, i);
+        STACK_OF(X509_EXTENSION) *exts;
+        ASN1_ENUMERATED *reason;
+        X509_EXTENSION *ext;
+        gtmp = X509_REVOKED_get_ext_d2i(rev,
+                                        NID_certificate_issuer, &j, NULL);
+        if (!gtmp && (j != -1)) {
+            crl->flags |= EXFLAG_INVALID;
+            return 1;
+        }
 
-		if (gtmp)
-			{
-			gens = gtmp;
-			if (!crl->issuers)
-				{
-				crl->issuers = sk_GENERAL_NAMES_new_null();
-				if (!crl->issuers)
-					return 0;
-				}
-			if (!sk_GENERAL_NAMES_push(crl->issuers, gtmp))
-				return 0;
-			}
-		rev->issuer = gens;
+        if (gtmp) {
+            gens = gtmp;
+            if (!crl->issuers) {
+                crl->issuers = sk_GENERAL_NAMES_new_null();
+                if (!crl->issuers)
+                    return 0;
+            }
+            if (!sk_GENERAL_NAMES_push(crl->issuers, gtmp))
+                return 0;
+        }
+        rev->issuer = gens;
 
-		reason = X509_REVOKED_get_ext_d2i(rev, NID_crl_reason,
-								&j, NULL);
-		if (!reason && (j != -1))
-			{
-			crl->flags |= EXFLAG_INVALID;
-			return 1;
-			}
+        reason = X509_REVOKED_get_ext_d2i(rev, NID_crl_reason, &j, NULL);
+        if (!reason && (j != -1)) {
+            crl->flags |= EXFLAG_INVALID;
+            return 1;
+        }
 
-		if (reason)
-			{
-			rev->reason = ASN1_ENUMERATED_get(reason);
-			ASN1_ENUMERATED_free(reason);
-			}
-		else
-			rev->reason = CRL_REASON_NONE;	
+        if (reason) {
+            rev->reason = ASN1_ENUMERATED_get(reason);
+            ASN1_ENUMERATED_free(reason);
+        } else
+            rev->reason = CRL_REASON_NONE;
 
-		/* Check for critical CRL entry extensions */
+        /* Check for critical CRL entry extensions */
 
-		exts = rev->extensions;
+        exts = rev->extensions;
 
-		for (k = 0; k < sk_X509_EXTENSION_num(exts); k++)
-			{
-			ext = sk_X509_EXTENSION_value(exts, k);
-			if (ext->critical > 0)
-				{
-				if (OBJ_obj2nid(ext->object) ==
-					NID_certificate_issuer)
-					continue;
-				crl->flags |= EXFLAG_CRITICAL;
-				break;
-				}
-			}
+        for (k = 0; k < sk_X509_EXTENSION_num(exts); k++) {
+            ext = sk_X509_EXTENSION_value(exts, k);
+            if (ext->critical > 0) {
+                if (OBJ_obj2nid(ext->object) == NID_certificate_issuer)
+                    continue;
+                crl->flags |= EXFLAG_CRITICAL;
+                break;
+            }
+        }
 
+    }
 
-		}
+    return 1;
 
-	return 1;
+}
 
-	}
-
-/* The X509_CRL structure needs a bit of customisation. Cache some extensions
+/*
+ * The X509_CRL structure needs a bit of customisation. Cache some extensions
  * and hash of the whole CRL.
  */
 static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
-								void *exarg)
-	{
-	X509_CRL *crl = (X509_CRL *)*pval;
-	STACK_OF(X509_EXTENSION) *exts;
-	X509_EXTENSION *ext;
-	size_t idx;
+                  void *exarg)
+{
+    X509_CRL *crl = (X509_CRL *)*pval;
+    STACK_OF(X509_EXTENSION) *exts;
+    X509_EXTENSION *ext;
+    size_t idx;
 
-	switch(operation)
-		{
-		case ASN1_OP_NEW_POST:
-		crl->idp = NULL;
-		crl->akid = NULL;
-		crl->flags = 0;
-		crl->idp_flags = 0;
-		crl->idp_reasons = CRLDP_ALL_REASONS;
-		crl->meth = default_crl_method;
-		crl->meth_data = NULL;
-		crl->issuers = NULL;
-		crl->crl_number = NULL;
-		crl->base_crl_number = NULL;
-		break;
+    switch (operation) {
+    case ASN1_OP_NEW_POST:
+        crl->idp = NULL;
+        crl->akid = NULL;
+        crl->flags = 0;
+        crl->idp_flags = 0;
+        crl->idp_reasons = CRLDP_ALL_REASONS;
+        crl->meth = default_crl_method;
+        crl->meth_data = NULL;
+        crl->issuers = NULL;
+        crl->crl_number = NULL;
+        crl->base_crl_number = NULL;
+        break;
 
-		case ASN1_OP_D2I_POST:
-		X509_CRL_digest(crl, EVP_sha1(), crl->sha1_hash, NULL);
-		crl->idp = X509_CRL_get_ext_d2i(crl,
-				NID_issuing_distribution_point, NULL, NULL);
-		if (crl->idp)
-			setup_idp(crl, crl->idp);
+    case ASN1_OP_D2I_POST:
+        X509_CRL_digest(crl, EVP_sha1(), crl->sha1_hash, NULL);
+        crl->idp = X509_CRL_get_ext_d2i(crl,
+                                        NID_issuing_distribution_point, NULL,
+                                        NULL);
+        if (crl->idp)
+            setup_idp(crl, crl->idp);
 
-		crl->akid = X509_CRL_get_ext_d2i(crl,
-				NID_authority_key_identifier, NULL, NULL);	
+        crl->akid = X509_CRL_get_ext_d2i(crl,
+                                         NID_authority_key_identifier, NULL,
+                                         NULL);
 
-		crl->crl_number = X509_CRL_get_ext_d2i(crl,
-				NID_crl_number, NULL, NULL);	
+        crl->crl_number = X509_CRL_get_ext_d2i(crl,
+                                               NID_crl_number, NULL, NULL);
 
-		crl->base_crl_number = X509_CRL_get_ext_d2i(crl,
-				NID_delta_crl, NULL, NULL);	
-		/* Delta CRLs must have CRL number */
-		if (crl->base_crl_number && !crl->crl_number)
-			crl->flags |= EXFLAG_INVALID;
+        crl->base_crl_number = X509_CRL_get_ext_d2i(crl,
+                                                    NID_delta_crl, NULL,
+                                                    NULL);
+        /* Delta CRLs must have CRL number */
+        if (crl->base_crl_number && !crl->crl_number)
+            crl->flags |= EXFLAG_INVALID;
 
-		/* See if we have any unhandled critical CRL extensions and 
-		 * indicate this in a flag. We only currently handle IDP so
-		 * anything else critical sets the flag.
-		 *
-		 * This code accesses the X509_CRL structure directly:
-		 * applications shouldn't do this.
-		 */
+        /*
+         * See if we have any unhandled critical CRL extensions and indicate
+         * this in a flag. We only currently handle IDP so anything else
+         * critical sets the flag. This code accesses the X509_CRL structure
+         * directly: applications shouldn't do this.
+         */
 
-		exts = crl->crl->extensions;
+        exts = crl->crl->extensions;
 
-		for (idx = 0; idx < sk_X509_EXTENSION_num(exts); idx++)
-			{
-			int nid;
-			ext = sk_X509_EXTENSION_value(exts, idx);
-			nid = OBJ_obj2nid(ext->object);
-			if (nid == NID_freshest_crl)
-				crl->flags |= EXFLAG_FRESHEST;
-			if (ext->critical > 0)
-				{
-				/* We handle IDP and deltas */
-				if ((nid == NID_issuing_distribution_point)
-					|| (nid == NID_authority_key_identifier)
-					|| (nid == NID_delta_crl))
-					break;;
-				crl->flags |= EXFLAG_CRITICAL;
-				break;
-				}
-			}
+        for (idx = 0; idx < sk_X509_EXTENSION_num(exts); idx++) {
+            int nid;
+            ext = sk_X509_EXTENSION_value(exts, idx);
+            nid = OBJ_obj2nid(ext->object);
+            if (nid == NID_freshest_crl)
+                crl->flags |= EXFLAG_FRESHEST;
+            if (ext->critical > 0) {
+                /* We handle IDP and deltas */
+                if ((nid == NID_issuing_distribution_point)
+                    || (nid == NID_authority_key_identifier)
+                    || (nid == NID_delta_crl))
+                    continue;
+                crl->flags |= EXFLAG_CRITICAL;
+                break;
+            }
+        }
 
+        if (!crl_set_issuers(crl))
+            return 0;
 
-		if (!crl_set_issuers(crl))
-			return 0;
+        if (crl->meth->crl_init) {
+            if (crl->meth->crl_init(crl) == 0)
+                return 0;
+        }
+        break;
 
-		if (crl->meth->crl_init)
-			{
-			if (crl->meth->crl_init(crl) == 0)
-				return 0;
-			}
-		break;
-
-		case ASN1_OP_FREE_POST:
-		if (crl->meth->crl_free)
-			{
-			if (!crl->meth->crl_free(crl))
-				return 0;
-			}
-		if (crl->akid)
-			AUTHORITY_KEYID_free(crl->akid);
-		if (crl->idp)
-			ISSUING_DIST_POINT_free(crl->idp);
-		ASN1_INTEGER_free(crl->crl_number);
-		ASN1_INTEGER_free(crl->base_crl_number);
-		sk_GENERAL_NAMES_pop_free(crl->issuers, GENERAL_NAMES_free);
-		break;
-		}
-	return 1;
-	}
+    case ASN1_OP_FREE_POST:
+        /* |crl->meth| may be NULL if constructing the object failed before
+         * |ASN1_OP_NEW_POST| was run. */
+        if (crl->meth && crl->meth->crl_free) {
+            if (!crl->meth->crl_free(crl))
+                return 0;
+        }
+        if (crl->akid)
+            AUTHORITY_KEYID_free(crl->akid);
+        if (crl->idp)
+            ISSUING_DIST_POINT_free(crl->idp);
+        ASN1_INTEGER_free(crl->crl_number);
+        ASN1_INTEGER_free(crl->base_crl_number);
+        sk_GENERAL_NAMES_pop_free(crl->issuers, GENERAL_NAMES_free);
+        break;
+    }
+    return 1;
+}
 
 /* Convert IDP into a more convenient form */
 
 static void setup_idp(X509_CRL *crl, ISSUING_DIST_POINT *idp)
-	{
-	int idp_only = 0;
-	/* Set various flags according to IDP */
-	crl->idp_flags |= IDP_PRESENT;
-	if (idp->onlyuser > 0)
-		{
-		idp_only++;
-		crl->idp_flags |= IDP_ONLYUSER;
-		}
-	if (idp->onlyCA > 0)
-		{
-		idp_only++;
-		crl->idp_flags |= IDP_ONLYCA;
-		}
-	if (idp->onlyattr > 0)
-		{
-		idp_only++;
-		crl->idp_flags |= IDP_ONLYATTR;
-		}
+{
+    int idp_only = 0;
+    /* Set various flags according to IDP */
+    crl->idp_flags |= IDP_PRESENT;
+    if (idp->onlyuser > 0) {
+        idp_only++;
+        crl->idp_flags |= IDP_ONLYUSER;
+    }
+    if (idp->onlyCA > 0) {
+        idp_only++;
+        crl->idp_flags |= IDP_ONLYCA;
+    }
+    if (idp->onlyattr > 0) {
+        idp_only++;
+        crl->idp_flags |= IDP_ONLYATTR;
+    }
 
-	if (idp_only > 1)
-		crl->idp_flags |= IDP_INVALID;
+    if (idp_only > 1)
+        crl->idp_flags |= IDP_INVALID;
 
-	if (idp->indirectCRL > 0)
-		crl->idp_flags |= IDP_INDIRECT;
+    if (idp->indirectCRL > 0)
+        crl->idp_flags |= IDP_INDIRECT;
 
-	if (idp->onlysomereasons)
-		{
-		crl->idp_flags |= IDP_REASONS;
-		if (idp->onlysomereasons->length > 0)
-			crl->idp_reasons = idp->onlysomereasons->data[0];
-		if (idp->onlysomereasons->length > 1)
-			crl->idp_reasons |=
-				(idp->onlysomereasons->data[1] << 8);
-		crl->idp_reasons &= CRLDP_ALL_REASONS;
-		}
+    if (idp->onlysomereasons) {
+        crl->idp_flags |= IDP_REASONS;
+        if (idp->onlysomereasons->length > 0)
+            crl->idp_reasons = idp->onlysomereasons->data[0];
+        if (idp->onlysomereasons->length > 1)
+            crl->idp_reasons |= (idp->onlysomereasons->data[1] << 8);
+        crl->idp_reasons &= CRLDP_ALL_REASONS;
+    }
 
-	DIST_POINT_set_dpname(idp->distpoint, X509_CRL_get_issuer(crl));
-	}
+    DIST_POINT_set_dpname(idp->distpoint, X509_CRL_get_issuer(crl));
+}
 
 ASN1_SEQUENCE_ref(X509_CRL, crl_cb) = {
-	ASN1_SIMPLE(X509_CRL, crl, X509_CRL_INFO),
-	ASN1_SIMPLE(X509_CRL, sig_alg, X509_ALGOR),
-	ASN1_SIMPLE(X509_CRL, signature, ASN1_BIT_STRING)
+        ASN1_SIMPLE(X509_CRL, crl, X509_CRL_INFO),
+        ASN1_SIMPLE(X509_CRL, sig_alg, X509_ALGOR),
+        ASN1_SIMPLE(X509_CRL, signature, ASN1_BIT_STRING)
 } ASN1_SEQUENCE_END_ref(X509_CRL, X509_CRL)
 
 IMPLEMENT_ASN1_FUNCTIONS(X509_REVOKED)
+
 IMPLEMENT_ASN1_DUP_FUNCTION(X509_REVOKED)
+
 IMPLEMENT_ASN1_FUNCTIONS(X509_CRL_INFO)
 IMPLEMENT_ASN1_FUNCTIONS(X509_CRL)
 IMPLEMENT_ASN1_DUP_FUNCTION(X509_CRL)
 
-static int X509_REVOKED_cmp(const X509_REVOKED **a,
-			const X509_REVOKED **b)
-	{
-	return(ASN1_STRING_cmp(
-		(ASN1_STRING *)(*a)->serialNumber,
-		(ASN1_STRING *)(*b)->serialNumber));
-	}
+static int X509_REVOKED_cmp(const X509_REVOKED **a, const X509_REVOKED **b)
+{
+    return (ASN1_STRING_cmp((ASN1_STRING *)(*a)->serialNumber,
+                            (ASN1_STRING *)(*b)->serialNumber));
+}
 
 int X509_CRL_add0_revoked(X509_CRL *crl, X509_REVOKED *rev)
 {
-	X509_CRL_INFO *inf;
-	inf = crl->crl;
-	if(!inf->revoked)
-		inf->revoked = sk_X509_REVOKED_new(X509_REVOKED_cmp);
-	if(!inf->revoked || !sk_X509_REVOKED_push(inf->revoked, rev)) {
-		OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-		return 0;
-	}
-	inf->enc.modified = 1;
-	return 1;
+    X509_CRL_INFO *inf;
+    inf = crl->crl;
+    if (!inf->revoked)
+        inf->revoked = sk_X509_REVOKED_new(X509_REVOKED_cmp);
+    if (!inf->revoked || !sk_X509_REVOKED_push(inf->revoked, rev)) {
+        OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
+    inf->enc.modified = 1;
+    return 1;
 }
 
 int X509_CRL_verify(X509_CRL *crl, EVP_PKEY *r)
-	{
-	if (crl->meth->crl_verify)
-		return crl->meth->crl_verify(crl, r);
-	return 0;
-	}
+{
+    if (crl->meth->crl_verify)
+        return crl->meth->crl_verify(crl, r);
+    return 0;
+}
 
 int X509_CRL_get0_by_serial(X509_CRL *crl,
-		X509_REVOKED **ret, ASN1_INTEGER *serial)
-	{
-	if (crl->meth->crl_lookup)
-		return crl->meth->crl_lookup(crl, ret, serial, NULL);
-	return 0;
-	}
+                            X509_REVOKED **ret, ASN1_INTEGER *serial)
+{
+    if (crl->meth->crl_lookup)
+        return crl->meth->crl_lookup(crl, ret, serial, NULL);
+    return 0;
+}
 
 int X509_CRL_get0_by_cert(X509_CRL *crl, X509_REVOKED **ret, X509 *x)
-	{
-	if (crl->meth->crl_lookup)
-		return crl->meth->crl_lookup(crl, ret,
-						X509_get_serialNumber(x),
-						X509_get_issuer_name(x));
-	return 0;
-	}
+{
+    if (crl->meth->crl_lookup)
+        return crl->meth->crl_lookup(crl, ret,
+                                     X509_get_serialNumber(x),
+                                     X509_get_issuer_name(x));
+    return 0;
+}
 
 static int def_crl_verify(X509_CRL *crl, EVP_PKEY *r)
-	{
-	return(ASN1_item_verify(ASN1_ITEM_rptr(X509_CRL_INFO),
-		crl->sig_alg, crl->signature,crl->crl,r));
-	}
+{
+    return (ASN1_item_verify(ASN1_ITEM_rptr(X509_CRL_INFO),
+                             crl->sig_alg, crl->signature, crl->crl, r));
+}
 
 static int crl_revoked_issuer_match(X509_CRL *crl, X509_NAME *nm,
-						X509_REVOKED *rev)
-	{
-	size_t i;
+                                    X509_REVOKED *rev)
+{
+    size_t i;
 
-	if (!rev->issuer)
-		{
-		if (!nm)
-			return 1;
-		if (!X509_NAME_cmp(nm, X509_CRL_get_issuer(crl)))
-			return 1;
-		return 0;
-		}
+    if (!rev->issuer) {
+        if (!nm)
+            return 1;
+        if (!X509_NAME_cmp(nm, X509_CRL_get_issuer(crl)))
+            return 1;
+        return 0;
+    }
 
-	if (!nm)
-		nm = X509_CRL_get_issuer(crl);
+    if (!nm)
+        nm = X509_CRL_get_issuer(crl);
 
-	for (i = 0; i < sk_GENERAL_NAME_num(rev->issuer); i++)
-		{
-		GENERAL_NAME *gen = sk_GENERAL_NAME_value(rev->issuer, i);
-		if (gen->type != GEN_DIRNAME)
-			continue;
-		if (!X509_NAME_cmp(nm, gen->d.directoryName))
-			return 1;
-		}
-	return 0;
+    for (i = 0; i < sk_GENERAL_NAME_num(rev->issuer); i++) {
+        GENERAL_NAME *gen = sk_GENERAL_NAME_value(rev->issuer, i);
+        if (gen->type != GEN_DIRNAME)
+            continue;
+        if (!X509_NAME_cmp(nm, gen->d.directoryName))
+            return 1;
+    }
+    return 0;
 
-	}
+}
 
 static struct CRYPTO_STATIC_MUTEX g_crl_sort_lock = CRYPTO_STATIC_MUTEX_INIT;
 
 static int def_crl_lookup(X509_CRL *crl,
-		X509_REVOKED **ret, ASN1_INTEGER *serial, X509_NAME *issuer)
-	{
-	X509_REVOKED rtmp, *rev;
-	size_t idx;
-	rtmp.serialNumber = serial;
-	/* Sort revoked into serial number order if not already sorted.
-	 * Do this under a lock to avoid race condition.
-	 */
+                          X509_REVOKED **ret, ASN1_INTEGER *serial,
+                          X509_NAME *issuer)
+{
+    X509_REVOKED rtmp, *rev;
+    size_t idx;
+    rtmp.serialNumber = serial;
+    /*
+     * Sort revoked into serial number order if not already sorted. Do this
+     * under a lock to avoid race condition.
+     */
 
-	CRYPTO_STATIC_MUTEX_lock_read(&g_crl_sort_lock);
-	const int is_sorted = sk_X509_REVOKED_is_sorted(crl->crl->revoked);
-	CRYPTO_STATIC_MUTEX_unlock(&g_crl_sort_lock);
+    CRYPTO_STATIC_MUTEX_lock_read(&g_crl_sort_lock);
+    const int is_sorted = sk_X509_REVOKED_is_sorted(crl->crl->revoked);
+    CRYPTO_STATIC_MUTEX_unlock_read(&g_crl_sort_lock);
 
-	if (!is_sorted)
-		{
-		CRYPTO_STATIC_MUTEX_lock_write(&g_crl_sort_lock);
-		if (!sk_X509_REVOKED_is_sorted(crl->crl->revoked))
-			{
-			sk_X509_REVOKED_sort(crl->crl->revoked);
-			}
-		CRYPTO_STATIC_MUTEX_unlock(&g_crl_sort_lock);
-		}
+    if (!is_sorted) {
+        CRYPTO_STATIC_MUTEX_lock_write(&g_crl_sort_lock);
+        if (!sk_X509_REVOKED_is_sorted(crl->crl->revoked)) {
+            sk_X509_REVOKED_sort(crl->crl->revoked);
+        }
+        CRYPTO_STATIC_MUTEX_unlock_write(&g_crl_sort_lock);
+    }
 
-	if (!sk_X509_REVOKED_find(crl->crl->revoked, &idx, &rtmp))
-		return 0;
-	/* Need to look for matching name */
-	for(;idx < sk_X509_REVOKED_num(crl->crl->revoked); idx++)
-		{
-		rev = sk_X509_REVOKED_value(crl->crl->revoked, idx);
-		if (ASN1_INTEGER_cmp(rev->serialNumber, serial))
-			return 0;
-		if (crl_revoked_issuer_match(crl, issuer, rev))
-			{
-			if (ret)
-				*ret = rev;
-			if (rev->reason == CRL_REASON_REMOVE_FROM_CRL)
-				return 2;
-			return 1;
-			}
-		}
-	return 0;
-	}
+    if (!sk_X509_REVOKED_find(crl->crl->revoked, &idx, &rtmp))
+        return 0;
+    /* Need to look for matching name */
+    for (; idx < sk_X509_REVOKED_num(crl->crl->revoked); idx++) {
+        rev = sk_X509_REVOKED_value(crl->crl->revoked, idx);
+        if (ASN1_INTEGER_cmp(rev->serialNumber, serial))
+            return 0;
+        if (crl_revoked_issuer_match(crl, issuer, rev)) {
+            if (ret)
+                *ret = rev;
+            if (rev->reason == CRL_REASON_REMOVE_FROM_CRL)
+                return 2;
+            return 1;
+        }
+    }
+    return 0;
+}
 
 void X509_CRL_set_default_method(const X509_CRL_METHOD *meth)
-	{
-	if (meth == NULL)
-		default_crl_method = &int_crl_meth;
-	else 
-		default_crl_method = meth;
-	}
+{
+    if (meth == NULL)
+        default_crl_method = &int_crl_meth;
+    else
+        default_crl_method = meth;
+}
 
-X509_CRL_METHOD *X509_CRL_METHOD_new(
-	int (*crl_init)(X509_CRL *crl),
-	int (*crl_free)(X509_CRL *crl),
-	int (*crl_lookup)(X509_CRL *crl, X509_REVOKED **ret,
-				ASN1_INTEGER *ser, X509_NAME *issuer),
-	int (*crl_verify)(X509_CRL *crl, EVP_PKEY *pk))
-	{
-	X509_CRL_METHOD *m;
-	m = OPENSSL_malloc(sizeof(X509_CRL_METHOD));
-	if (!m)
-		return NULL;
-	m->crl_init = crl_init;
-	m->crl_free = crl_free;
-	m->crl_lookup = crl_lookup;
-	m->crl_verify = crl_verify;
-	m->flags = X509_CRL_METHOD_DYNAMIC;
-	return m;
-	}
+X509_CRL_METHOD *X509_CRL_METHOD_new(int (*crl_init) (X509_CRL *crl),
+                                     int (*crl_free) (X509_CRL *crl),
+                                     int (*crl_lookup) (X509_CRL *crl,
+                                                        X509_REVOKED **ret,
+                                                        ASN1_INTEGER *ser,
+                                                        X509_NAME *issuer),
+                                     int (*crl_verify) (X509_CRL *crl,
+                                                        EVP_PKEY *pk))
+{
+    X509_CRL_METHOD *m;
+    m = OPENSSL_malloc(sizeof(X509_CRL_METHOD));
+    if (!m)
+        return NULL;
+    m->crl_init = crl_init;
+    m->crl_free = crl_free;
+    m->crl_lookup = crl_lookup;
+    m->crl_verify = crl_verify;
+    m->flags = X509_CRL_METHOD_DYNAMIC;
+    return m;
+}
 
 void X509_CRL_METHOD_free(X509_CRL_METHOD *m)
-	{
-	if (!(m->flags & X509_CRL_METHOD_DYNAMIC))
-		return;
-	OPENSSL_free(m);
-	}
+{
+    if (!(m->flags & X509_CRL_METHOD_DYNAMIC))
+        return;
+    OPENSSL_free(m);
+}
 
 void X509_CRL_set_meth_data(X509_CRL *crl, void *dat)
-	{
-	crl->meth_data = dat;
-	}
+{
+    crl->meth_data = dat;
+}
 
 void *X509_CRL_get_meth_data(X509_CRL *crl)
-	{
-	return crl->meth_data;
-	}
+{
+    return crl->meth_data;
+}
 
 IMPLEMENT_ASN1_SET_OF(X509_REVOKED)
+
 IMPLEMENT_ASN1_SET_OF(X509_CRL)
diff --git a/src/crypto/x509/x_exten.c b/src/crypto/x509/x_exten.c
index cf64c84..36403e4 100644
--- a/src/crypto/x509/x_exten.c
+++ b/src/crypto/x509/x_exten.c
@@ -61,13 +61,13 @@
 
 
 ASN1_SEQUENCE(X509_EXTENSION) = {
-	ASN1_SIMPLE(X509_EXTENSION, object, ASN1_OBJECT),
-	ASN1_OPT(X509_EXTENSION, critical, ASN1_BOOLEAN),
-	ASN1_SIMPLE(X509_EXTENSION, value, ASN1_OCTET_STRING)
+        ASN1_SIMPLE(X509_EXTENSION, object, ASN1_OBJECT),
+        ASN1_OPT(X509_EXTENSION, critical, ASN1_BOOLEAN),
+        ASN1_SIMPLE(X509_EXTENSION, value, ASN1_OCTET_STRING)
 } ASN1_SEQUENCE_END(X509_EXTENSION)
 
-ASN1_ITEM_TEMPLATE(X509_EXTENSIONS) = 
-	ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, Extension, X509_EXTENSION)
+ASN1_ITEM_TEMPLATE(X509_EXTENSIONS) =
+        ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, Extension, X509_EXTENSION)
 ASN1_ITEM_TEMPLATE_END(X509_EXTENSIONS)
 
 IMPLEMENT_ASN1_FUNCTIONS(X509_EXTENSION)
diff --git a/src/crypto/x509/x_info.c b/src/crypto/x509/x_info.c
index be579d7..177cd0e 100644
--- a/src/crypto/x509/x_info.c
+++ b/src/crypto/x509/x_info.c
@@ -61,35 +61,38 @@
 #include <openssl/mem.h>
 #include <openssl/thread.h>
 
-
 X509_INFO *X509_INFO_new(void)
-	{
-	X509_INFO *ret=NULL;
+{
+    X509_INFO *ret = NULL;
 
-	ret=(X509_INFO *)OPENSSL_malloc(sizeof(X509_INFO));
-	if (ret == NULL)
-		{
-		OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-		return(NULL);
-		}
- 
-        ret->enc_cipher.cipher=NULL;
-        ret->enc_len=0;
-        ret->enc_data=NULL;
- 
-	ret->x509=NULL;
-	ret->crl=NULL;
-	ret->x_pkey=NULL;
-	return(ret);
-	}
+    ret = (X509_INFO *)OPENSSL_malloc(sizeof(X509_INFO));
+    if (ret == NULL) {
+        OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+        return (NULL);
+    }
+
+    ret->enc_cipher.cipher = NULL;
+    ret->enc_len = 0;
+    ret->enc_data = NULL;
+
+    ret->x509 = NULL;
+    ret->crl = NULL;
+    ret->x_pkey = NULL;
+    return (ret);
+}
 
 void X509_INFO_free(X509_INFO *x)
-	{
-	if (x == NULL) return;
+{
+    if (x == NULL)
+        return;
 
-	if (x->x509 != NULL) X509_free(x->x509);
-	if (x->crl != NULL) X509_CRL_free(x->crl);
-	if (x->x_pkey != NULL) X509_PKEY_free(x->x_pkey);
-	if (x->enc_data != NULL) OPENSSL_free(x->enc_data);
-	OPENSSL_free(x);
-	}
+    if (x->x509 != NULL)
+        X509_free(x->x509);
+    if (x->crl != NULL)
+        X509_CRL_free(x->crl);
+    if (x->x_pkey != NULL)
+        X509_PKEY_free(x->x_pkey);
+    if (x->enc_data != NULL)
+        OPENSSL_free(x->enc_data);
+    OPENSSL_free(x);
+}
diff --git a/src/crypto/x509/x_name.c b/src/crypto/x509/x_name.c
index a1dcd16..4abdc91 100644
--- a/src/crypto/x509/x_name.c
+++ b/src/crypto/x509/x_name.c
@@ -67,472 +67,478 @@
 #include <openssl/x509.h>
 
 #include "../asn1/asn1_locl.h"
+#include "../internal.h"
 
 
 typedef STACK_OF(X509_NAME_ENTRY) STACK_OF_X509_NAME_ENTRY;
 DECLARE_STACK_OF(STACK_OF_X509_NAME_ENTRY)
 
+/*
+ * Maximum length of X509_NAME: much larger than anything we should
+ * ever see in practice.
+ */
+
+#define X509_NAME_MAX (1024 * 1024)
+
 static int x509_name_ex_d2i(ASN1_VALUE **val,
-				const unsigned char **in, long len,
-				const ASN1_ITEM *it,
-				int tag, int aclass, char opt, ASN1_TLC *ctx);
+                            const unsigned char **in, long len,
+                            const ASN1_ITEM *it,
+                            int tag, int aclass, char opt, ASN1_TLC *ctx);
 
 static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out,
-				const ASN1_ITEM *it, int tag, int aclass);
+                            const ASN1_ITEM *it, int tag, int aclass);
 static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it);
 static void x509_name_ex_free(ASN1_VALUE **val, const ASN1_ITEM *it);
 
 static int x509_name_encode(X509_NAME *a);
 static int x509_name_canon(X509_NAME *a);
 static int asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in);
-static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname,
-			  unsigned char **in);
-
-
-static int x509_name_ex_print(BIO *out, ASN1_VALUE **pval,
-						int indent,
-						const char *fname, 
-						const ASN1_PCTX *pctx);
+static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) * intname,
+                          unsigned char **in);
 
 ASN1_SEQUENCE(X509_NAME_ENTRY) = {
-	ASN1_SIMPLE(X509_NAME_ENTRY, object, ASN1_OBJECT),
-	ASN1_SIMPLE(X509_NAME_ENTRY, value, ASN1_PRINTABLE)
+        ASN1_SIMPLE(X509_NAME_ENTRY, object, ASN1_OBJECT),
+        ASN1_SIMPLE(X509_NAME_ENTRY, value, ASN1_PRINTABLE)
 } ASN1_SEQUENCE_END(X509_NAME_ENTRY)
 
 IMPLEMENT_ASN1_FUNCTIONS(X509_NAME_ENTRY)
 IMPLEMENT_ASN1_DUP_FUNCTION(X509_NAME_ENTRY)
 
-/* For the "Name" type we need a SEQUENCE OF { SET OF X509_NAME_ENTRY }
- * so declare two template wrappers for this
+/*
+ * For the "Name" type we need a SEQUENCE OF { SET OF X509_NAME_ENTRY } so
+ * declare two template wrappers for this
  */
 
 ASN1_ITEM_TEMPLATE(X509_NAME_ENTRIES) =
-	ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0, RDNS, X509_NAME_ENTRY)
+        ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_OF, 0, RDNS, X509_NAME_ENTRY)
 ASN1_ITEM_TEMPLATE_END(X509_NAME_ENTRIES)
 
 ASN1_ITEM_TEMPLATE(X509_NAME_INTERNAL) =
-	ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, Name, X509_NAME_ENTRIES)
+        ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, Name, X509_NAME_ENTRIES)
 ASN1_ITEM_TEMPLATE_END(X509_NAME_INTERNAL)
 
-/* Normally that's where it would end: we'd have two nested STACK structures
+/*
+ * Normally that's where it would end: we'd have two nested STACK structures
  * representing the ASN1. Unfortunately X509_NAME uses a completely different
- * form and caches encodings so we have to process the internal form and convert
- * to the external form.
+ * form and caches encodings so we have to process the internal form and
+ * convert to the external form.
  */
 
 static const ASN1_EXTERN_FUNCS x509_name_ff = {
-	NULL,
-	x509_name_ex_new,
-	x509_name_ex_free,
-	0,	/* Default clear behaviour is OK */
-	x509_name_ex_d2i,
-	x509_name_ex_i2d,
-	x509_name_ex_print
+    NULL,
+    x509_name_ex_new,
+    x509_name_ex_free,
+    0,                          /* Default clear behaviour is OK */
+    x509_name_ex_d2i,
+    x509_name_ex_i2d,
+    NULL,
 };
 
-IMPLEMENT_EXTERN_ASN1(X509_NAME, V_ASN1_SEQUENCE, x509_name_ff) 
+IMPLEMENT_EXTERN_ASN1(X509_NAME, V_ASN1_SEQUENCE, x509_name_ff)
 
 IMPLEMENT_ASN1_FUNCTIONS(X509_NAME)
+
 IMPLEMENT_ASN1_DUP_FUNCTION(X509_NAME)
 
 static int x509_name_ex_new(ASN1_VALUE **val, const ASN1_ITEM *it)
 {
-	X509_NAME *ret = NULL;
-	ret = OPENSSL_malloc(sizeof(X509_NAME));
-	if(!ret) goto memerr;
-	if ((ret->entries=sk_X509_NAME_ENTRY_new_null()) == NULL)
-		goto memerr;
-	if((ret->bytes = BUF_MEM_new()) == NULL) goto memerr;
-	ret->canon_enc = NULL;
-	ret->canon_enclen = 0;
-	ret->modified=1;
-	*val = (ASN1_VALUE *)ret;
-	return 1;
+    X509_NAME *ret = NULL;
+    ret = OPENSSL_malloc(sizeof(X509_NAME));
+    if (!ret)
+        goto memerr;
+    if ((ret->entries = sk_X509_NAME_ENTRY_new_null()) == NULL)
+        goto memerr;
+    if ((ret->bytes = BUF_MEM_new()) == NULL)
+        goto memerr;
+    ret->canon_enc = NULL;
+    ret->canon_enclen = 0;
+    ret->modified = 1;
+    *val = (ASN1_VALUE *)ret;
+    return 1;
 
  memerr:
-	OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-	if (ret)
-		{
-		if (ret->entries)
-			sk_X509_NAME_ENTRY_free(ret->entries);
-		OPENSSL_free(ret);
-		}
-	return 0;
+    OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+    if (ret) {
+        if (ret->entries)
+            sk_X509_NAME_ENTRY_free(ret->entries);
+        OPENSSL_free(ret);
+    }
+    return 0;
 }
 
 static void x509_name_ex_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
 {
-	X509_NAME *a;
-	if(!pval || !*pval)
-	    return;
-	a = (X509_NAME *)*pval;
+    X509_NAME *a;
+    if (!pval || !*pval)
+        return;
+    a = (X509_NAME *)*pval;
 
-	BUF_MEM_free(a->bytes);
-	sk_X509_NAME_ENTRY_pop_free(a->entries,X509_NAME_ENTRY_free);
-	if (a->canon_enc)
-		OPENSSL_free(a->canon_enc);
-	OPENSSL_free(a);
-	*pval = NULL;
+    BUF_MEM_free(a->bytes);
+    sk_X509_NAME_ENTRY_pop_free(a->entries, X509_NAME_ENTRY_free);
+    if (a->canon_enc)
+        OPENSSL_free(a->canon_enc);
+    OPENSSL_free(a);
+    *pval = NULL;
 }
 
 static void local_sk_X509_NAME_ENTRY_free(STACK_OF(X509_NAME_ENTRY) *ne)
 {
-	sk_X509_NAME_ENTRY_free(ne);
+    sk_X509_NAME_ENTRY_free(ne);
 }
 
 static void local_sk_X509_NAME_ENTRY_pop_free(STACK_OF(X509_NAME_ENTRY) *ne)
 {
-	sk_X509_NAME_ENTRY_pop_free(ne, X509_NAME_ENTRY_free);
+    sk_X509_NAME_ENTRY_pop_free(ne, X509_NAME_ENTRY_free);
 }
 
 static int x509_name_ex_d2i(ASN1_VALUE **val,
-			const unsigned char **in, long len, const ASN1_ITEM *it,
-				int tag, int aclass, char opt, ASN1_TLC *ctx)
+                            const unsigned char **in, long len,
+                            const ASN1_ITEM *it, int tag, int aclass,
+                            char opt, ASN1_TLC *ctx)
 {
-	const unsigned char *p = *in, *q;
-	union { STACK_OF(STACK_OF_X509_NAME_ENTRY) *s;
-		ASN1_VALUE *a; } intname = {NULL};
-	union { X509_NAME *x; ASN1_VALUE *a; } nm = {NULL};
-	size_t i, j;
-	int ret;
-	STACK_OF(X509_NAME_ENTRY) *entries;
-	X509_NAME_ENTRY *entry;
-	q = p;
+    const unsigned char *p = *in, *q;
+    union {
+        STACK_OF(STACK_OF_X509_NAME_ENTRY) *s;
+        ASN1_VALUE *a;
+    } intname = {
+        NULL
+    };
+    union {
+        X509_NAME *x;
+        ASN1_VALUE *a;
+    } nm = {
+        NULL
+    };
+    size_t i, j;
+    int ret;
+    STACK_OF(X509_NAME_ENTRY) *entries;
+    X509_NAME_ENTRY *entry;
+    /* Bound the size of an X509_NAME we are willing to parse. */
+    if (len > X509_NAME_MAX) {
+        len = X509_NAME_MAX;
+    }
+    q = p;
 
-	/* Get internal representation of Name */
-	ret = ASN1_item_ex_d2i(&intname.a,
-			       &p, len, ASN1_ITEM_rptr(X509_NAME_INTERNAL),
-			       tag, aclass, opt, ctx);
-	
-	if(ret <= 0) return ret;
+    /* Get internal representation of Name */
+    ret = ASN1_item_ex_d2i(&intname.a,
+                           &p, len, ASN1_ITEM_rptr(X509_NAME_INTERNAL),
+                           tag, aclass, opt, ctx);
 
-	if(*val) x509_name_ex_free(val, NULL);
-	/* We've decoded it: now cache encoding */
-	if (!x509_name_ex_new(&nm.a, NULL) ||
-		!BUF_MEM_grow(nm.x->bytes, p - q))
-		{
-		sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
-			local_sk_X509_NAME_ENTRY_pop_free);
-		goto err;
-		}
-	memcpy(nm.x->bytes->data, q, p - q);
+    if (ret <= 0)
+        return ret;
 
-	/* Convert internal representation to X509_NAME structure */
-	for(i = 0; i < sk_STACK_OF_X509_NAME_ENTRY_num(intname.s); i++) {
-		entries = sk_STACK_OF_X509_NAME_ENTRY_value(intname.s, i);
-		for(j = 0; j < sk_X509_NAME_ENTRY_num(entries); j++) {
-			entry = sk_X509_NAME_ENTRY_value(entries, j);
-			entry->set = i;
-			if(!sk_X509_NAME_ENTRY_push(nm.x->entries, entry))
-				goto err;
-		}
-		sk_X509_NAME_ENTRY_free(entries);
-	}
-	sk_STACK_OF_X509_NAME_ENTRY_free(intname.s);
-	ret = x509_name_canon(nm.x);
-	if (!ret)
-		goto err;
-	nm.x->modified = 0;
-	*val = nm.a;
-	*in = p;
-	return ret;
-err:
-        if (nm.x != NULL)
-		X509_NAME_free(nm.x);
-	OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB);
-	return 0;
+    if (*val)
+        x509_name_ex_free(val, NULL);
+    if (!x509_name_ex_new(&nm.a, NULL))
+        goto err;
+    /* We've decoded it: now cache encoding */
+    if (!BUF_MEM_grow(nm.x->bytes, p - q))
+        goto err;
+    OPENSSL_memcpy(nm.x->bytes->data, q, p - q);
+
+    /* Convert internal representation to X509_NAME structure */
+    for (i = 0; i < sk_STACK_OF_X509_NAME_ENTRY_num(intname.s); i++) {
+        entries = sk_STACK_OF_X509_NAME_ENTRY_value(intname.s, i);
+        for (j = 0; j < sk_X509_NAME_ENTRY_num(entries); j++) {
+            entry = sk_X509_NAME_ENTRY_value(entries, j);
+            entry->set = i;
+            if (!sk_X509_NAME_ENTRY_push(nm.x->entries, entry))
+                goto err;
+            sk_X509_NAME_ENTRY_set(entries, j, NULL);
+        }
+    }
+    ret = x509_name_canon(nm.x);
+    if (!ret)
+        goto err;
+    sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
+                                         local_sk_X509_NAME_ENTRY_free);
+    nm.x->modified = 0;
+    *val = nm.a;
+    *in = p;
+    return ret;
+ err:
+    if (nm.x != NULL)
+        X509_NAME_free(nm.x);
+    sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
+                                         local_sk_X509_NAME_ENTRY_pop_free);
+    OPENSSL_PUT_ERROR(X509, ERR_R_ASN1_LIB);
+    return 0;
 }
 
-static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out, const ASN1_ITEM *it, int tag, int aclass)
+static int x509_name_ex_i2d(ASN1_VALUE **val, unsigned char **out,
+                            const ASN1_ITEM *it, int tag, int aclass)
 {
-	int ret;
-	X509_NAME *a = (X509_NAME *)*val;
-	if(a->modified) {
-		ret = x509_name_encode(a);
-		if(ret < 0)
-			return ret;
-		ret = x509_name_canon(a);
-		if(ret < 0)
-			return ret;
-	}
-	ret = a->bytes->length;
-	if(out != NULL) {
-		memcpy(*out,a->bytes->data,ret);
-		*out+=ret;
-	}
-	return ret;
+    int ret;
+    X509_NAME *a = (X509_NAME *)*val;
+    if (a->modified) {
+        ret = x509_name_encode(a);
+        if (ret < 0)
+            return ret;
+        ret = x509_name_canon(a);
+        if (ret < 0)
+            return ret;
+    }
+    ret = a->bytes->length;
+    if (out != NULL) {
+        OPENSSL_memcpy(*out, a->bytes->data, ret);
+        *out += ret;
+    }
+    return ret;
 }
 
 static int x509_name_encode(X509_NAME *a)
 {
-	union { STACK_OF(STACK_OF_X509_NAME_ENTRY) *s;
-		ASN1_VALUE *a; } intname = {NULL};
-	int len;
-	unsigned char *p;
-	STACK_OF(X509_NAME_ENTRY) *entries = NULL;
-	X509_NAME_ENTRY *entry;
-	int set = -1;
-	size_t i;
-	intname.s = sk_STACK_OF_X509_NAME_ENTRY_new_null();
-	if(!intname.s) goto memerr;
-	for(i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
-		entry = sk_X509_NAME_ENTRY_value(a->entries, i);
-		if(entry->set != set) {
-			entries = sk_X509_NAME_ENTRY_new_null();
-			if(!entries) goto memerr;
-			if(!sk_STACK_OF_X509_NAME_ENTRY_push(intname.s,
-							     entries))
-				goto memerr;
-			set = entry->set;
-		}
-		if(!sk_X509_NAME_ENTRY_push(entries, entry)) goto memerr;
-	}
-	len = ASN1_item_ex_i2d(&intname.a, NULL,
-			       ASN1_ITEM_rptr(X509_NAME_INTERNAL), -1, -1);
-	if (!BUF_MEM_grow(a->bytes,len)) goto memerr;
-	p=(unsigned char *)a->bytes->data;
-	ASN1_item_ex_i2d(&intname.a,
-			 &p, ASN1_ITEM_rptr(X509_NAME_INTERNAL), -1, -1);
-	sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
-					     local_sk_X509_NAME_ENTRY_free);
-	a->modified = 0;
-	return len;
-memerr:
-	sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
-					     local_sk_X509_NAME_ENTRY_free);
-	OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-	return -1;
+    union {
+        STACK_OF(STACK_OF_X509_NAME_ENTRY) *s;
+        ASN1_VALUE *a;
+    } intname = {
+        NULL
+    };
+    int len;
+    unsigned char *p;
+    STACK_OF(X509_NAME_ENTRY) *entries = NULL;
+    X509_NAME_ENTRY *entry;
+    int set = -1;
+    size_t i;
+    intname.s = sk_STACK_OF_X509_NAME_ENTRY_new_null();
+    if (!intname.s)
+        goto memerr;
+    for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
+        entry = sk_X509_NAME_ENTRY_value(a->entries, i);
+        if (entry->set != set) {
+            entries = sk_X509_NAME_ENTRY_new_null();
+            if (!entries)
+                goto memerr;
+            if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname.s, entries)) {
+                sk_X509_NAME_ENTRY_free(entries);
+                goto memerr;
+            }
+            set = entry->set;
+        }
+        if (!sk_X509_NAME_ENTRY_push(entries, entry))
+            goto memerr;
+    }
+    len = ASN1_item_ex_i2d(&intname.a, NULL,
+                           ASN1_ITEM_rptr(X509_NAME_INTERNAL), -1, -1);
+    if (!BUF_MEM_grow(a->bytes, len))
+        goto memerr;
+    p = (unsigned char *)a->bytes->data;
+    ASN1_item_ex_i2d(&intname.a,
+                     &p, ASN1_ITEM_rptr(X509_NAME_INTERNAL), -1, -1);
+    sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
+                                         local_sk_X509_NAME_ENTRY_free);
+    a->modified = 0;
+    return len;
+ memerr:
+    sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname.s,
+                                         local_sk_X509_NAME_ENTRY_free);
+    OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+    return -1;
 }
 
-static int x509_name_ex_print(BIO *out, ASN1_VALUE **pval,
-						int indent,
-						const char *fname, 
-						const ASN1_PCTX *pctx)
-	{
-	if (X509_NAME_print_ex(out, (X509_NAME *)*pval,
-					indent, pctx->nm_flags) <= 0)
-		return 0;
-	return 2;
-	}
-
-/* This function generates the canonical encoding of the Name structure.
- * In it all strings are converted to UTF8, leading, trailing and
- * multiple spaces collapsed, converted to lower case and the leading
- * SEQUENCE header removed.
- *
- * In future we could also normalize the UTF8 too.
- *
- * By doing this comparison of Name structures can be rapidly
- * perfomed by just using memcmp() of the canonical encoding.
- * By omitting the leading SEQUENCE name constraints of type
- * dirName can also be checked with a simple memcmp().
+/*
+ * This function generates the canonical encoding of the Name structure. In
+ * it all strings are converted to UTF8, leading, trailing and multiple
+ * spaces collapsed, converted to lower case and the leading SEQUENCE header
+ * removed. In future we could also normalize the UTF8 too. By doing this
+ * comparison of Name structures can be rapidly perfomed by just using
+ * OPENSSL_memcmp() of the canonical encoding. By omitting the leading SEQUENCE name
+ * constraints of type dirName can also be checked with a simple OPENSSL_memcmp().
  */
 
 static int x509_name_canon(X509_NAME *a)
-	{
-	unsigned char *p;
-	STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname = NULL;
-	STACK_OF(X509_NAME_ENTRY) *entries = NULL;
-	X509_NAME_ENTRY *entry, *tmpentry = NULL;
-	int set = -1, ret = 0;
-	size_t i;
+{
+    unsigned char *p;
+    STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname = NULL;
+    STACK_OF(X509_NAME_ENTRY) *entries = NULL;
+    X509_NAME_ENTRY *entry, *tmpentry = NULL;
+    int set = -1, ret = 0, len;
+    size_t i;
 
-	if (a->canon_enc)
-		{
-		OPENSSL_free(a->canon_enc);
-		a->canon_enc = NULL;
-		}
-	/* Special case: empty X509_NAME => null encoding */
-	if (sk_X509_NAME_ENTRY_num(a->entries) == 0)
-		{
-		a->canon_enclen = 0;
-		return 1;
-		}
-	intname = sk_STACK_OF_X509_NAME_ENTRY_new_null();
-	if(!intname)
-		goto err;
-	for(i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++)
-		{
-		entry = sk_X509_NAME_ENTRY_value(a->entries, i);
-		if(entry->set != set)
-			{
-			entries = sk_X509_NAME_ENTRY_new_null();
-			if(!entries)
-				goto err;
-			if(!sk_STACK_OF_X509_NAME_ENTRY_push(intname, entries))
-				{
-				sk_X509_NAME_ENTRY_free(entries);
-				goto err;
-				}
-			set = entry->set;
-			}
-		tmpentry = X509_NAME_ENTRY_new();
-		if (tmpentry == NULL)
-			goto err;
-		tmpentry->object = OBJ_dup(entry->object);
-		if (!asn1_string_canon(tmpentry->value, entry->value))
-			goto err;
-		if(!sk_X509_NAME_ENTRY_push(entries, tmpentry))
-			goto err;
-		tmpentry = NULL;
-		}
+    if (a->canon_enc) {
+        OPENSSL_free(a->canon_enc);
+        a->canon_enc = NULL;
+    }
+    /* Special case: empty X509_NAME => null encoding */
+    if (sk_X509_NAME_ENTRY_num(a->entries) == 0) {
+        a->canon_enclen = 0;
+        return 1;
+    }
+    intname = sk_STACK_OF_X509_NAME_ENTRY_new_null();
+    if (!intname)
+        goto err;
+    for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
+        entry = sk_X509_NAME_ENTRY_value(a->entries, i);
+        if (entry->set != set) {
+            entries = sk_X509_NAME_ENTRY_new_null();
+            if (!entries)
+                goto err;
+            if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname, entries)) {
+                sk_X509_NAME_ENTRY_free(entries);
+                goto err;
+            }
+            set = entry->set;
+        }
+        tmpentry = X509_NAME_ENTRY_new();
+        if (tmpentry == NULL)
+            goto err;
+        tmpentry->object = OBJ_dup(entry->object);
+        if (!asn1_string_canon(tmpentry->value, entry->value))
+            goto err;
+        if (!sk_X509_NAME_ENTRY_push(entries, tmpentry))
+            goto err;
+        tmpentry = NULL;
+    }
 
-	/* Finally generate encoding */
+    /* Finally generate encoding */
 
-	a->canon_enclen = i2d_name_canon(intname, NULL);
+    len = i2d_name_canon(intname, NULL);
+    if (len < 0) {
+        goto err;
+    }
+    a->canon_enclen = len;
 
-	p = OPENSSL_malloc(a->canon_enclen);
+    p = OPENSSL_malloc(a->canon_enclen);
 
-	if (!p)
-		goto err;
+    if (!p)
+        goto err;
 
-	a->canon_enc = p;
+    a->canon_enc = p;
 
-	i2d_name_canon(intname, &p);
+    i2d_name_canon(intname, &p);
 
-	ret = 1;
+    ret = 1;
 
-	err:
+ err:
 
-	if (tmpentry)
-		X509_NAME_ENTRY_free(tmpentry);
-	if (intname)
-		sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname,
-					local_sk_X509_NAME_ENTRY_pop_free);
-	return ret;
-	}
+    if (tmpentry)
+        X509_NAME_ENTRY_free(tmpentry);
+    if (intname)
+        sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname,
+                                             local_sk_X509_NAME_ENTRY_pop_free);
+    return ret;
+}
 
 /* Bitmap of all the types of string that will be canonicalized. */
 
-#define ASN1_MASK_CANON	\
-	(B_ASN1_UTF8STRING | B_ASN1_BMPSTRING | B_ASN1_UNIVERSALSTRING \
-	| B_ASN1_PRINTABLESTRING | B_ASN1_T61STRING | B_ASN1_IA5STRING \
-	| B_ASN1_VISIBLESTRING)
-	
+#define ASN1_MASK_CANON \
+        (B_ASN1_UTF8STRING | B_ASN1_BMPSTRING | B_ASN1_UNIVERSALSTRING \
+        | B_ASN1_PRINTABLESTRING | B_ASN1_T61STRING | B_ASN1_IA5STRING \
+        | B_ASN1_VISIBLESTRING)
 
 static int asn1_string_canon(ASN1_STRING *out, ASN1_STRING *in)
-	{
-	unsigned char *to, *from;
-	int len, i;
+{
+    unsigned char *to, *from;
+    int len, i;
 
-	/* If type not in bitmask just copy string across */
-	if (!(ASN1_tag2bit(in->type) & ASN1_MASK_CANON))
-		{
-		if (!ASN1_STRING_copy(out, in))
-			return 0;
-		return 1;
-		}
+    /* If type not in bitmask just copy string across */
+    if (!(ASN1_tag2bit(in->type) & ASN1_MASK_CANON)) {
+        if (!ASN1_STRING_copy(out, in))
+            return 0;
+        return 1;
+    }
 
-	out->type = V_ASN1_UTF8STRING;
-	out->length = ASN1_STRING_to_UTF8(&out->data, in);
-	if (out->length == -1)
-		return 0;
+    out->type = V_ASN1_UTF8STRING;
+    out->length = ASN1_STRING_to_UTF8(&out->data, in);
+    if (out->length == -1)
+        return 0;
 
-	to = out->data;
-	from = to;
+    to = out->data;
+    from = to;
 
-	len = out->length;
+    len = out->length;
 
-	/* Convert string in place to canonical form.
-	 * Ultimately we may need to handle a wider range of characters
-	 * but for now ignore anything with MSB set and rely on the
-	 * isspace() and tolower() functions.
-	 */
+    /*
+     * Convert string in place to canonical form. Ultimately we may need to
+     * handle a wider range of characters but for now ignore anything with
+     * MSB set and rely on the isspace() and tolower() functions.
+     */
 
-	/* Ignore leading spaces */
-	while((len > 0) && !(*from & 0x80) && isspace(*from))
-		{
-		from++;
-		len--;
-		}
+    /* Ignore leading spaces */
+    while ((len > 0) && !(*from & 0x80) && isspace(*from)) {
+        from++;
+        len--;
+    }
 
-	to = from + len - 1;
+    to = from + len;
 
-	/* Ignore trailing spaces */
-	while ((len > 0) && !(*to & 0x80) && isspace(*to))
-		{
-		to--;
-		len--;
-		}
+    /* Ignore trailing spaces */
+    while ((len > 0) && !(to[-1] & 0x80) && isspace(to[-1])) {
+        to--;
+        len--;
+    }
 
-	to = out->data;
+    to = out->data;
 
-	i = 0;
-	while(i < len)
-		{
-		/* If MSB set just copy across */
-		if (*from & 0x80)
-			{
-			*to++ = *from++;
-			i++;
-			}
-		/* Collapse multiple spaces */
-		else if (isspace(*from))
-			{
-			/* Copy one space across */
-			*to++ = ' ';
-			/* Ignore subsequent spaces. Note: don't need to
-			 * check len here because we know the last 
-			 * character is a non-space so we can't overflow.
-			 */
-			do
-				{
-				from++;
-				i++;
-				}
-			while(!(*from & 0x80) && isspace(*from));
-			}
-		else
-			{
-			*to++ = tolower(*from);
-			from++;
-			i++;
-			}
-		}
+    i = 0;
+    while (i < len) {
+        /* If MSB set just copy across */
+        if (*from & 0x80) {
+            *to++ = *from++;
+            i++;
+        }
+        /* Collapse multiple spaces */
+        else if (isspace(*from)) {
+            /* Copy one space across */
+            *to++ = ' ';
+            /*
+             * Ignore subsequent spaces. Note: don't need to check len here
+             * because we know the last character is a non-space so we can't
+             * overflow.
+             */
+            do {
+                from++;
+                i++;
+            }
+            while (!(*from & 0x80) && isspace(*from));
+        } else {
+            *to++ = tolower(*from);
+            from++;
+            i++;
+        }
+    }
 
-	out->length = to - out->data;
+    out->length = to - out->data;
 
-	return 1;
+    return 1;
 
-	}
+}
 
-static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) *_intname,
-			  unsigned char **in)
-	{
-	int len, ltmp;
-	size_t i;
-	ASN1_VALUE *v;
-	STACK_OF(ASN1_VALUE) *intname = (STACK_OF(ASN1_VALUE) *)_intname;
+static int i2d_name_canon(STACK_OF(STACK_OF_X509_NAME_ENTRY) * _intname,
+                          unsigned char **in)
+{
+    int len, ltmp;
+    size_t i;
+    ASN1_VALUE *v;
+    STACK_OF(ASN1_VALUE) *intname = (STACK_OF(ASN1_VALUE) *)_intname;
 
-	len = 0;
-	for (i = 0; i < sk_ASN1_VALUE_num(intname); i++)
-		{
-		v = sk_ASN1_VALUE_value(intname, i);
-		ltmp = ASN1_item_ex_i2d(&v, in,
-			ASN1_ITEM_rptr(X509_NAME_ENTRIES), -1, -1);
-		if (ltmp < 0)
-			return ltmp;
-		len += ltmp;
-		}
-	return len;
-	}
+    len = 0;
+    for (i = 0; i < sk_ASN1_VALUE_num(intname); i++) {
+        v = sk_ASN1_VALUE_value(intname, i);
+        ltmp = ASN1_item_ex_i2d(&v, in,
+                                ASN1_ITEM_rptr(X509_NAME_ENTRIES), -1, -1);
+        if (ltmp < 0)
+            return ltmp;
+        len += ltmp;
+    }
+    return len;
+}
 
 int X509_NAME_set(X509_NAME **xn, X509_NAME *name)
-	{
-	X509_NAME *in;
+{
+    X509_NAME *in;
 
-	if (!xn || !name) return(0);
+    if (!xn || !name)
+        return (0);
 
-	if (*xn != name)
-		{
-		in=X509_NAME_dup(name);
-		if (in != NULL)
-			{
-			X509_NAME_free(*xn);
-			*xn=in;
-			}
-		}
-	return(*xn != NULL);
-	}
-	
+    if (*xn != name) {
+        in = X509_NAME_dup(name);
+        if (in != NULL) {
+            X509_NAME_free(*xn);
+            *xn = in;
+        }
+    }
+    return (*xn != NULL);
+}
+
 IMPLEMENT_ASN1_SET_OF(X509_NAME_ENTRY)
diff --git a/src/crypto/x509/x_pkey.c b/src/crypto/x509/x_pkey.c
index f5e98b8..8231a24 100644
--- a/src/crypto/x509/x_pkey.c
+++ b/src/crypto/x509/x_pkey.c
@@ -63,38 +63,44 @@
 #include <openssl/mem.h>
 #include <openssl/thread.h>
 
+#include "../internal.h"
+
 
 X509_PKEY *X509_PKEY_new(void)
-	{
-	X509_PKEY *ret = OPENSSL_malloc(sizeof(X509_PKEY));
-	if (ret == NULL)
-		{
-		OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-		goto err;
-		}
-	memset(ret, 0, sizeof(X509_PKEY));
+{
+    X509_PKEY *ret = OPENSSL_malloc(sizeof(X509_PKEY));
+    if (ret == NULL) {
+        OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+    OPENSSL_memset(ret, 0, sizeof(X509_PKEY));
 
-	ret->enc_algor = X509_ALGOR_new();
-	if (ret->enc_algor == NULL)
-		goto err;
-	ret->enc_pkey = M_ASN1_OCTET_STRING_new();
-	if (ret->enc_pkey == NULL)
-		goto err;
-	return ret;
+    ret->enc_algor = X509_ALGOR_new();
+    if (ret->enc_algor == NULL)
+        goto err;
+    ret->enc_pkey = M_ASN1_OCTET_STRING_new();
+    if (ret->enc_pkey == NULL)
+        goto err;
+    return ret;
 
-err:
-	if (ret != NULL)
-		X509_PKEY_free(ret);
-	return NULL;
-	}
+ err:
+    if (ret != NULL)
+        X509_PKEY_free(ret);
+    return NULL;
+}
 
 void X509_PKEY_free(X509_PKEY *x)
-	{
-	if (x == NULL) return;
+{
+    if (x == NULL)
+        return;
 
-	if (x->enc_algor != NULL) X509_ALGOR_free(x->enc_algor);
-	if (x->enc_pkey != NULL) M_ASN1_OCTET_STRING_free(x->enc_pkey);
-	if (x->dec_pkey != NULL)EVP_PKEY_free(x->dec_pkey);
-	if ((x->key_data != NULL) && (x->key_free)) OPENSSL_free(x->key_data);
-	OPENSSL_free(x);
-	}
+    if (x->enc_algor != NULL)
+        X509_ALGOR_free(x->enc_algor);
+    if (x->enc_pkey != NULL)
+        M_ASN1_OCTET_STRING_free(x->enc_pkey);
+    if (x->dec_pkey != NULL)
+        EVP_PKEY_free(x->dec_pkey);
+    if ((x->key_data != NULL) && (x->key_free))
+        OPENSSL_free(x->key_data);
+    OPENSSL_free(x);
+}
diff --git a/src/crypto/x509/x_pubkey.c b/src/crypto/x509/x_pubkey.c
index a16edca..3d07d66 100644
--- a/src/crypto/x509/x_pubkey.c
+++ b/src/crypto/x509/x_pubkey.c
@@ -54,78 +54,75 @@
  * copied and put under another distribution licence
  * [including the GNU Public Licence.] */
 
+#include <openssl/x509.h>
+
+#include <limits.h>
+
 #include <openssl/asn1.h>
 #include <openssl/asn1t.h>
+#include <openssl/bytestring.h>
 #include <openssl/err.h>
 #include <openssl/evp.h>
 #include <openssl/mem.h>
 #include <openssl/obj.h>
 #include <openssl/thread.h>
-#include <openssl/x509.h>
 
-#include "../evp/internal.h"
 #include "../internal.h"
 
-
 /* Minor tweak to operation: free up EVP_PKEY */
 static int pubkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
-			void *exarg)
-	{
-	if (operation == ASN1_OP_FREE_POST)
-		{
-		X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval;
-		EVP_PKEY_free(pubkey->pkey);
-		}
-	return 1;
-	}
+                     void *exarg)
+{
+    if (operation == ASN1_OP_FREE_POST) {
+        X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval;
+        EVP_PKEY_free(pubkey->pkey);
+    }
+    return 1;
+}
 
 ASN1_SEQUENCE_cb(X509_PUBKEY, pubkey_cb) = {
-	ASN1_SIMPLE(X509_PUBKEY, algor, X509_ALGOR),
-	ASN1_SIMPLE(X509_PUBKEY, public_key, ASN1_BIT_STRING)
+        ASN1_SIMPLE(X509_PUBKEY, algor, X509_ALGOR),
+        ASN1_SIMPLE(X509_PUBKEY, public_key, ASN1_BIT_STRING)
 } ASN1_SEQUENCE_END_cb(X509_PUBKEY, X509_PUBKEY)
 
 IMPLEMENT_ASN1_FUNCTIONS(X509_PUBKEY)
 
 int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey)
-	{
-	X509_PUBKEY *pk=NULL;
+{
+    X509_PUBKEY *pk = NULL;
+    uint8_t *spki = NULL;
+    size_t spki_len;
 
-	if (x == NULL) return(0);
+    if (x == NULL)
+        return (0);
 
-	if ((pk=X509_PUBKEY_new()) == NULL) goto error;
+    CBB cbb;
+    if (!CBB_init(&cbb, 0) ||
+        !EVP_marshal_public_key(&cbb, pkey) ||
+        !CBB_finish(&cbb, &spki, &spki_len) ||
+        spki_len > LONG_MAX) {
+        CBB_cleanup(&cbb);
+        OPENSSL_PUT_ERROR(X509, X509_R_PUBLIC_KEY_ENCODE_ERROR);
+        goto error;
+    }
 
-	if (pkey->ameth)
-		{
-		if (pkey->ameth->pub_encode)
-			{
-			if (!pkey->ameth->pub_encode(pk, pkey))
-				{
-				OPENSSL_PUT_ERROR(X509, X509_R_PUBLIC_KEY_ENCODE_ERROR);
-				goto error;
-				}
-			}
-		else
-			{
-			OPENSSL_PUT_ERROR(X509, X509_R_METHOD_NOT_SUPPORTED);
-			goto error;
-			}
-		}
-	else
-		{
-		OPENSSL_PUT_ERROR(X509, X509_R_UNSUPPORTED_ALGORITHM);
-		goto error;
-		}
+    const uint8_t *p = spki;
+    pk = d2i_X509_PUBKEY(NULL, &p, (long)spki_len);
+    if (pk == NULL || p != spki + spki_len) {
+        OPENSSL_PUT_ERROR(X509, X509_R_PUBLIC_KEY_DECODE_ERROR);
+        goto error;
+    }
 
-	if (*x != NULL)
-		X509_PUBKEY_free(*x);
+    OPENSSL_free(spki);
+    X509_PUBKEY_free(*x);
+    *x = pk;
 
-	*x=pk;
-
-	return 1;
-error:
-	if (pk != NULL) X509_PUBKEY_free(pk);
-	return 0;
-	}
+    return 1;
+ error:
+    X509_PUBKEY_free(pk);
+    OPENSSL_free(spki);
+    return 0;
+}
 
 /* g_pubkey_lock is used to protect the initialisation of the |pkey| member of
  * |X509_PUBKEY| objects. Really |X509_PUBKEY| should have a |CRYPTO_once_t|
@@ -134,251 +131,238 @@
 static struct CRYPTO_STATIC_MUTEX g_pubkey_lock = CRYPTO_STATIC_MUTEX_INIT;
 
 EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key)
-	{
-	EVP_PKEY *ret=NULL;
+{
+    EVP_PKEY *ret = NULL;
+    uint8_t *spki = NULL;
 
-	if (key == NULL) goto error;
+    if (key == NULL)
+        goto error;
 
-	CRYPTO_STATIC_MUTEX_lock_read(&g_pubkey_lock);
-	if (key->pkey != NULL)
-		{
-		CRYPTO_STATIC_MUTEX_unlock(&g_pubkey_lock);
-		return EVP_PKEY_up_ref(key->pkey);
-		}
-	CRYPTO_STATIC_MUTEX_unlock(&g_pubkey_lock);
+    CRYPTO_STATIC_MUTEX_lock_read(&g_pubkey_lock);
+    if (key->pkey != NULL) {
+        CRYPTO_STATIC_MUTEX_unlock_read(&g_pubkey_lock);
+        EVP_PKEY_up_ref(key->pkey);
+        return key->pkey;
+    }
+    CRYPTO_STATIC_MUTEX_unlock_read(&g_pubkey_lock);
 
-	if (key->public_key == NULL) goto error;
+    /* Re-encode the |X509_PUBKEY| to DER and parse it. */
+    int spki_len = i2d_X509_PUBKEY(key, &spki);
+    if (spki_len < 0) {
+        goto error;
+    }
+    CBS cbs;
+    CBS_init(&cbs, spki, (size_t)spki_len);
+    ret = EVP_parse_public_key(&cbs);
+    if (ret == NULL || CBS_len(&cbs) != 0) {
+        OPENSSL_PUT_ERROR(X509, X509_R_PUBLIC_KEY_DECODE_ERROR);
+        goto error;
+    }
 
-	if ((ret = EVP_PKEY_new()) == NULL)
-		{
-		OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-		goto error;
-		}
+    /* Check to see if another thread set key->pkey first */
+    CRYPTO_STATIC_MUTEX_lock_write(&g_pubkey_lock);
+    if (key->pkey) {
+        CRYPTO_STATIC_MUTEX_unlock_write(&g_pubkey_lock);
+        EVP_PKEY_free(ret);
+        ret = key->pkey;
+    } else {
+        key->pkey = ret;
+        CRYPTO_STATIC_MUTEX_unlock_write(&g_pubkey_lock);
+    }
 
-	if (!EVP_PKEY_set_type(ret, OBJ_obj2nid(key->algor->algorithm)))
-		{
-		OPENSSL_PUT_ERROR(X509, X509_R_UNSUPPORTED_ALGORITHM);
-		goto error;
-		}
+    OPENSSL_free(spki);
+    EVP_PKEY_up_ref(ret);
+    return ret;
 
-	if (ret->ameth->pub_decode)
-		{
-		if (!ret->ameth->pub_decode(ret, key))
-			{
-			OPENSSL_PUT_ERROR(X509, X509_R_PUBLIC_KEY_DECODE_ERROR);
-			goto error;
-			}
-		}
-	else
-		{
-		OPENSSL_PUT_ERROR(X509, X509_R_METHOD_NOT_SUPPORTED);
-		goto error;
-		}
+ error:
+    OPENSSL_free(spki);
+    EVP_PKEY_free(ret);
+    return NULL;
+}
 
-	/* Check to see if another thread set key->pkey first */
-	CRYPTO_STATIC_MUTEX_lock_write(&g_pubkey_lock);
-	if (key->pkey)
-		{
-		CRYPTO_STATIC_MUTEX_unlock(&g_pubkey_lock);
-		EVP_PKEY_free(ret);
-		ret = key->pkey;
-		}
-	else
-		{
-		key->pkey = ret;
-		CRYPTO_STATIC_MUTEX_unlock(&g_pubkey_lock);
-		}
-
-	return EVP_PKEY_up_ref(ret);
-
-	error:
-	if (ret != NULL)
-		EVP_PKEY_free(ret);
-	return(NULL);
-	}
-
-/* Now two pseudo ASN1 routines that take an EVP_PKEY structure
- * and encode or decode as X509_PUBKEY
+/*
+ * Now two pseudo ASN1 routines that take an EVP_PKEY structure and encode or
+ * decode as X509_PUBKEY
  */
 
-EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp,
-	     long length)
-	{
-	X509_PUBKEY *xpk;
-	EVP_PKEY *pktmp;
-	xpk = d2i_X509_PUBKEY(NULL, pp, length);
-	if(!xpk) return NULL;
-	pktmp = X509_PUBKEY_get(xpk);
-	X509_PUBKEY_free(xpk);
-	if(!pktmp) return NULL;
-	if(a)
-		{
-		EVP_PKEY_free(*a);
-		*a = pktmp;
-		}
-	return pktmp;
-	}
+EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp, long length)
+{
+    X509_PUBKEY *xpk;
+    EVP_PKEY *pktmp;
+    xpk = d2i_X509_PUBKEY(NULL, pp, length);
+    if (!xpk)
+        return NULL;
+    pktmp = X509_PUBKEY_get(xpk);
+    X509_PUBKEY_free(xpk);
+    if (!pktmp)
+        return NULL;
+    if (a) {
+        EVP_PKEY_free(*a);
+        *a = pktmp;
+    }
+    return pktmp;
+}
 
 int i2d_PUBKEY(const EVP_PKEY *a, unsigned char **pp)
-	{
-	X509_PUBKEY *xpk=NULL;
-	int ret;
-	if(!a) return 0;
-	if(!X509_PUBKEY_set(&xpk, (EVP_PKEY*) a)) return 0;
-	ret = i2d_X509_PUBKEY(xpk, pp);
-	X509_PUBKEY_free(xpk);
-	return ret;
-	}
+{
+    X509_PUBKEY *xpk = NULL;
+    int ret;
+    if (!a)
+        return 0;
+    if (!X509_PUBKEY_set(&xpk, (EVP_PKEY *)a))
+        return 0;
+    ret = i2d_X509_PUBKEY(xpk, pp);
+    X509_PUBKEY_free(xpk);
+    return ret;
+}
 
-/* The following are equivalents but which return RSA and DSA
- * keys
+/*
+ * The following are equivalents but which return RSA and DSA keys
  */
-RSA *d2i_RSA_PUBKEY(RSA **a, const unsigned char **pp,
-	     long length)
-	{
-	EVP_PKEY *pkey;
-	RSA *key;
-	const unsigned char *q;
-	q = *pp;
-	pkey = d2i_PUBKEY(NULL, &q, length);
-	if (!pkey) return NULL;
-	key = EVP_PKEY_get1_RSA(pkey);
-	EVP_PKEY_free(pkey);
-	if (!key) return NULL;
-	*pp = q;
-	if (a)
-		{
-		RSA_free(*a);
-		*a = key;
-		}
-	return key;
-	}
+RSA *d2i_RSA_PUBKEY(RSA **a, const unsigned char **pp, long length)
+{
+    EVP_PKEY *pkey;
+    RSA *key;
+    const unsigned char *q;
+    q = *pp;
+    pkey = d2i_PUBKEY(NULL, &q, length);
+    if (!pkey)
+        return NULL;
+    key = EVP_PKEY_get1_RSA(pkey);
+    EVP_PKEY_free(pkey);
+    if (!key)
+        return NULL;
+    *pp = q;
+    if (a) {
+        RSA_free(*a);
+        *a = key;
+    }
+    return key;
+}
 
 int i2d_RSA_PUBKEY(const RSA *a, unsigned char **pp)
-	{
-	EVP_PKEY *pktmp;
-	int ret;
-	if (!a) return 0;
-	pktmp = EVP_PKEY_new();
-	if (!pktmp)
-		{
-		OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-		return 0;
-		}
-	EVP_PKEY_set1_RSA(pktmp, (RSA*) a);
-	ret = i2d_PUBKEY(pktmp, pp);
-	EVP_PKEY_free(pktmp);
-	return ret;
-	}
+{
+    EVP_PKEY *pktmp;
+    int ret;
+    if (!a)
+        return 0;
+    pktmp = EVP_PKEY_new();
+    if (!pktmp) {
+        OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
+    EVP_PKEY_set1_RSA(pktmp, (RSA *)a);
+    ret = i2d_PUBKEY(pktmp, pp);
+    EVP_PKEY_free(pktmp);
+    return ret;
+}
 
 #ifndef OPENSSL_NO_DSA
-DSA *d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp,
-	     long length)
-	{
-	EVP_PKEY *pkey;
-	DSA *key;
-	const unsigned char *q;
-	q = *pp;
-	pkey = d2i_PUBKEY(NULL, &q, length);
-	if (!pkey) return NULL;
-	key = EVP_PKEY_get1_DSA(pkey);
-	EVP_PKEY_free(pkey);
-	if (!key) return NULL;
-	*pp = q;
-	if (a)
-		{
-		DSA_free(*a);
-		*a = key;
-		}
-	return key;
-	}
+DSA *d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp, long length)
+{
+    EVP_PKEY *pkey;
+    DSA *key;
+    const unsigned char *q;
+    q = *pp;
+    pkey = d2i_PUBKEY(NULL, &q, length);
+    if (!pkey)
+        return NULL;
+    key = EVP_PKEY_get1_DSA(pkey);
+    EVP_PKEY_free(pkey);
+    if (!key)
+        return NULL;
+    *pp = q;
+    if (a) {
+        DSA_free(*a);
+        *a = key;
+    }
+    return key;
+}
 
 int i2d_DSA_PUBKEY(const DSA *a, unsigned char **pp)
-	{
-	EVP_PKEY *pktmp;
-	int ret;
-	if(!a) return 0;
-	pktmp = EVP_PKEY_new();
-	if(!pktmp)
-		{
-		OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-		return 0;
-		}
-	EVP_PKEY_set1_DSA(pktmp, (DSA*) a);
-	ret = i2d_PUBKEY(pktmp, pp);
-	EVP_PKEY_free(pktmp);
-	return ret;
-	}
+{
+    EVP_PKEY *pktmp;
+    int ret;
+    if (!a)
+        return 0;
+    pktmp = EVP_PKEY_new();
+    if (!pktmp) {
+        OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
+    EVP_PKEY_set1_DSA(pktmp, (DSA *)a);
+    ret = i2d_PUBKEY(pktmp, pp);
+    EVP_PKEY_free(pktmp);
+    return ret;
+}
 #endif
 
 EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length)
-	{
-	EVP_PKEY *pkey;
-	EC_KEY *key;
-	const unsigned char *q;
-	q = *pp;
-	pkey = d2i_PUBKEY(NULL, &q, length);
-	if (!pkey) return(NULL);
-	key = EVP_PKEY_get1_EC_KEY(pkey);
-	EVP_PKEY_free(pkey);
-	if (!key)  return(NULL);
-	*pp = q;
-	if (a)
-		{
-		EC_KEY_free(*a);
-		*a = key;
-		}
-	return(key);
-	}
+{
+    EVP_PKEY *pkey;
+    EC_KEY *key;
+    const unsigned char *q;
+    q = *pp;
+    pkey = d2i_PUBKEY(NULL, &q, length);
+    if (!pkey)
+        return (NULL);
+    key = EVP_PKEY_get1_EC_KEY(pkey);
+    EVP_PKEY_free(pkey);
+    if (!key)
+        return (NULL);
+    *pp = q;
+    if (a) {
+        EC_KEY_free(*a);
+        *a = key;
+    }
+    return (key);
+}
 
 int i2d_EC_PUBKEY(const EC_KEY *a, unsigned char **pp)
-	{
-	EVP_PKEY *pktmp;
-	int ret;
-	if (!a)	return(0);
-	if ((pktmp = EVP_PKEY_new()) == NULL)
-		{
-		OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-		return(0);
-		}
-	EVP_PKEY_set1_EC_KEY(pktmp, (EC_KEY*) a);
-	ret = i2d_PUBKEY(pktmp, pp);
-	EVP_PKEY_free(pktmp);
-	return(ret);
-	}
+{
+    EVP_PKEY *pktmp;
+    int ret;
+    if (!a)
+        return (0);
+    if ((pktmp = EVP_PKEY_new()) == NULL) {
+        OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
+        return (0);
+    }
+    EVP_PKEY_set1_EC_KEY(pktmp, (EC_KEY *)a);
+    ret = i2d_PUBKEY(pktmp, pp);
+    EVP_PKEY_free(pktmp);
+    return (ret);
+}
 
 int X509_PUBKEY_set0_param(X509_PUBKEY *pub, const ASN1_OBJECT *aobj,
-					int ptype, void *pval,
-					unsigned char *penc, int penclen)
-	{
-	if (!X509_ALGOR_set0(pub->algor, aobj, ptype, pval))
-		return 0;
-	if (penc)
-		{
-		if (pub->public_key->data)
-			OPENSSL_free(pub->public_key->data);
-		pub->public_key->data = penc;
-		pub->public_key->length = penclen;
-  		/* Set number of unused bits to zero */
-		pub->public_key->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
-		pub->public_key->flags|=ASN1_STRING_FLAG_BITS_LEFT;
-		}
-	return 1;
-	}
+                           int ptype, void *pval,
+                           unsigned char *penc, int penclen)
+{
+    if (!X509_ALGOR_set0(pub->algor, aobj, ptype, pval))
+        return 0;
+    if (penc) {
+        if (pub->public_key->data)
+            OPENSSL_free(pub->public_key->data);
+        pub->public_key->data = penc;
+        pub->public_key->length = penclen;
+        /* Set number of unused bits to zero */
+        pub->public_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
+        pub->public_key->flags |= ASN1_STRING_FLAG_BITS_LEFT;
+    }
+    return 1;
+}
 
 int X509_PUBKEY_get0_param(ASN1_OBJECT **ppkalg,
-		const unsigned char **pk, int *ppklen,
-		X509_ALGOR **pa,
-		X509_PUBKEY *pub)
-	{
-	if (ppkalg)
-		*ppkalg = pub->algor->algorithm;
-	if (pk)
-		{
-		*pk = pub->public_key->data;
-		*ppklen = pub->public_key->length;
-		}
-	if (pa)
-		*pa = pub->algor;
-	return 1;
-	}
+                           const unsigned char **pk, int *ppklen,
+                           X509_ALGOR **pa, X509_PUBKEY *pub)
+{
+    if (ppkalg)
+        *ppkalg = pub->algor->algorithm;
+    if (pk) {
+        *pk = pub->public_key->data;
+        *ppklen = pub->public_key->length;
+    }
+    if (pa)
+        *pa = pub->algor;
+    return 1;
+}
diff --git a/src/crypto/x509/x_req.c b/src/crypto/x509/x_req.c
index 3d30129..5dfe19e 100644
--- a/src/crypto/x509/x_req.c
+++ b/src/crypto/x509/x_req.c
@@ -60,53 +60,50 @@
 #include <openssl/thread.h>
 #include <openssl/x509.h>
 
-/* X509_REQ_INFO is handled in an unusual way to get round
- * invalid encodings. Some broken certificate requests don't
- * encode the attributes field if it is empty. This is in
- * violation of PKCS#10 but we need to tolerate it. We do
- * this by making the attributes field OPTIONAL then using
- * the callback to initialise it to an empty STACK. 
- *
- * This means that the field will be correctly encoded unless
- * we NULL out the field.
- *
- * As a result we no longer need the req_kludge field because
- * the information is now contained in the attributes field:
- * 1. If it is NULL then it's the invalid omission.
- * 2. If it is empty it is the correct encoding.
- * 3. If it is not empty then some attributes are present.
- *
+/*
+ * X509_REQ_INFO is handled in an unusual way to get round invalid encodings.
+ * Some broken certificate requests don't encode the attributes field if it
+ * is empty. This is in violation of PKCS#10 but we need to tolerate it. We
+ * do this by making the attributes field OPTIONAL then using the callback to
+ * initialise it to an empty STACK. This means that the field will be
+ * correctly encoded unless we NULL out the field. As a result we no longer
+ * need the req_kludge field because the information is now contained in the
+ * attributes field: 1. If it is NULL then it's the invalid omission. 2. If
+ * it is empty it is the correct encoding. 3. If it is not empty then some
+ * attributes are present.
  */
 
 static int rinf_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
-							void *exarg)
+                   void *exarg)
 {
-	X509_REQ_INFO *rinf = (X509_REQ_INFO *)*pval;
+    X509_REQ_INFO *rinf = (X509_REQ_INFO *)*pval;
 
-	if(operation == ASN1_OP_NEW_POST) {
-		rinf->attributes = sk_X509_ATTRIBUTE_new_null();
-		if(!rinf->attributes) return 0;
-	}
-	return 1;
+    if (operation == ASN1_OP_NEW_POST) {
+        rinf->attributes = sk_X509_ATTRIBUTE_new_null();
+        if (!rinf->attributes)
+            return 0;
+    }
+    return 1;
 }
 
 ASN1_SEQUENCE_enc(X509_REQ_INFO, enc, rinf_cb) = {
-	ASN1_SIMPLE(X509_REQ_INFO, version, ASN1_INTEGER),
-	ASN1_SIMPLE(X509_REQ_INFO, subject, X509_NAME),
-	ASN1_SIMPLE(X509_REQ_INFO, pubkey, X509_PUBKEY),
-	/* This isn't really OPTIONAL but it gets round invalid
-	 * encodings
-	 */
-	ASN1_IMP_SET_OF_OPT(X509_REQ_INFO, attributes, X509_ATTRIBUTE, 0)
+        ASN1_SIMPLE(X509_REQ_INFO, version, ASN1_INTEGER),
+        ASN1_SIMPLE(X509_REQ_INFO, subject, X509_NAME),
+        ASN1_SIMPLE(X509_REQ_INFO, pubkey, X509_PUBKEY),
+        /* This isn't really OPTIONAL but it gets round invalid
+         * encodings
+         */
+        ASN1_IMP_SET_OF_OPT(X509_REQ_INFO, attributes, X509_ATTRIBUTE, 0)
 } ASN1_SEQUENCE_END_enc(X509_REQ_INFO, X509_REQ_INFO)
 
 IMPLEMENT_ASN1_FUNCTIONS(X509_REQ_INFO)
 
 ASN1_SEQUENCE_ref(X509_REQ, 0) = {
-	ASN1_SIMPLE(X509_REQ, req_info, X509_REQ_INFO),
-	ASN1_SIMPLE(X509_REQ, sig_alg, X509_ALGOR),
-	ASN1_SIMPLE(X509_REQ, signature, ASN1_BIT_STRING)
+        ASN1_SIMPLE(X509_REQ, req_info, X509_REQ_INFO),
+        ASN1_SIMPLE(X509_REQ, sig_alg, X509_ALGOR),
+        ASN1_SIMPLE(X509_REQ, signature, ASN1_BIT_STRING)
 } ASN1_SEQUENCE_END_ref(X509_REQ, X509_REQ)
 
 IMPLEMENT_ASN1_FUNCTIONS(X509_REQ)
+
 IMPLEMENT_ASN1_DUP_FUNCTION(X509_REQ)
diff --git a/src/crypto/x509/x_sig.c b/src/crypto/x509/x_sig.c
index fabdb67..e18024a 100644
--- a/src/crypto/x509/x_sig.c
+++ b/src/crypto/x509/x_sig.c
@@ -62,8 +62,8 @@
 
 
 ASN1_SEQUENCE(X509_SIG) = {
-	ASN1_SIMPLE(X509_SIG, algor, X509_ALGOR),
-	ASN1_SIMPLE(X509_SIG, digest, ASN1_OCTET_STRING)
+        ASN1_SIMPLE(X509_SIG, algor, X509_ALGOR),
+        ASN1_SIMPLE(X509_SIG, digest, ASN1_OCTET_STRING)
 } ASN1_SEQUENCE_END(X509_SIG)
 
 IMPLEMENT_ASN1_FUNCTIONS(X509_SIG)
diff --git a/src/crypto/x509/x_spki.c b/src/crypto/x509/x_spki.c
index 35bf246..86da6dd 100644
--- a/src/crypto/x509/x_spki.c
+++ b/src/crypto/x509/x_spki.c
@@ -55,24 +55,26 @@
  * copied and put under another distribution licence
  * [including the GNU Public Licence.] */
 
- /* This module was send to me my Pat Richards <patr@x509.com> who
-  * wrote it.  It is under my Copyright with his permission. */
+ /*
+  * This module was send to me my Pat Richards <patr@x509.com> who wrote it.
+  * It is under my Copyright with his permission.
+  */
 
 #include <openssl/x509.h>
 #include <openssl/asn1t.h>
 
 
 ASN1_SEQUENCE(NETSCAPE_SPKAC) = {
-	ASN1_SIMPLE(NETSCAPE_SPKAC, pubkey, X509_PUBKEY),
-	ASN1_SIMPLE(NETSCAPE_SPKAC, challenge, ASN1_IA5STRING)
+        ASN1_SIMPLE(NETSCAPE_SPKAC, pubkey, X509_PUBKEY),
+        ASN1_SIMPLE(NETSCAPE_SPKAC, challenge, ASN1_IA5STRING)
 } ASN1_SEQUENCE_END(NETSCAPE_SPKAC)
 
 IMPLEMENT_ASN1_FUNCTIONS(NETSCAPE_SPKAC)
 
 ASN1_SEQUENCE(NETSCAPE_SPKI) = {
-	ASN1_SIMPLE(NETSCAPE_SPKI, spkac, NETSCAPE_SPKAC),
-	ASN1_SIMPLE(NETSCAPE_SPKI, sig_algor, X509_ALGOR),
-	ASN1_SIMPLE(NETSCAPE_SPKI, signature, ASN1_BIT_STRING)
+        ASN1_SIMPLE(NETSCAPE_SPKI, spkac, NETSCAPE_SPKAC),
+        ASN1_SIMPLE(NETSCAPE_SPKI, sig_algor, X509_ALGOR),
+        ASN1_SIMPLE(NETSCAPE_SPKI, signature, ASN1_BIT_STRING)
 } ASN1_SEQUENCE_END(NETSCAPE_SPKI)
 
 IMPLEMENT_ASN1_FUNCTIONS(NETSCAPE_SPKI)
diff --git a/src/crypto/x509/x_val.c b/src/crypto/x509/x_val.c
index 26200ee..ad4f7e1 100644
--- a/src/crypto/x509/x_val.c
+++ b/src/crypto/x509/x_val.c
@@ -62,8 +62,8 @@
 
 
 ASN1_SEQUENCE(X509_VAL) = {
-	ASN1_SIMPLE(X509_VAL, notBefore, ASN1_TIME),
-	ASN1_SIMPLE(X509_VAL, notAfter, ASN1_TIME)
+        ASN1_SIMPLE(X509_VAL, notBefore, ASN1_TIME),
+        ASN1_SIMPLE(X509_VAL, notAfter, ASN1_TIME)
 } ASN1_SEQUENCE_END(X509_VAL)
 
 IMPLEMENT_ASN1_FUNCTIONS(X509_VAL)
diff --git a/src/crypto/x509/x_x509.c b/src/crypto/x509/x_x509.c
index 7bbe4f3..15118d2 100644
--- a/src/crypto/x509/x_x509.c
+++ b/src/crypto/x509/x_x509.c
@@ -55,32 +55,34 @@
  * copied and put under another distribution licence
  * [including the GNU Public Licence.] */
 
+#include <assert.h>
+#include <limits.h>
 #include <stdio.h>
 
 #include <openssl/asn1t.h>
 #include <openssl/evp.h>
 #include <openssl/mem.h>
 #include <openssl/obj.h>
+#include <openssl/pool.h>
 #include <openssl/thread.h>
 #include <openssl/x509.h>
 #include <openssl/x509v3.h>
 
 #include "../internal.h"
 
-
 static CRYPTO_EX_DATA_CLASS g_ex_data_class = CRYPTO_EX_DATA_CLASS_INIT;
 
 ASN1_SEQUENCE_enc(X509_CINF, enc, 0) = {
-	ASN1_EXP_OPT(X509_CINF, version, ASN1_INTEGER, 0),
-	ASN1_SIMPLE(X509_CINF, serialNumber, ASN1_INTEGER),
-	ASN1_SIMPLE(X509_CINF, signature, X509_ALGOR),
-	ASN1_SIMPLE(X509_CINF, issuer, X509_NAME),
-	ASN1_SIMPLE(X509_CINF, validity, X509_VAL),
-	ASN1_SIMPLE(X509_CINF, subject, X509_NAME),
-	ASN1_SIMPLE(X509_CINF, key, X509_PUBKEY),
-	ASN1_IMP_OPT(X509_CINF, issuerUID, ASN1_BIT_STRING, 1),
-	ASN1_IMP_OPT(X509_CINF, subjectUID, ASN1_BIT_STRING, 2),
-	ASN1_EXP_SEQUENCE_OF_OPT(X509_CINF, extensions, X509_EXTENSION, 3)
+        ASN1_EXP_OPT(X509_CINF, version, ASN1_INTEGER, 0),
+        ASN1_SIMPLE(X509_CINF, serialNumber, ASN1_INTEGER),
+        ASN1_SIMPLE(X509_CINF, signature, X509_ALGOR),
+        ASN1_SIMPLE(X509_CINF, issuer, X509_NAME),
+        ASN1_SIMPLE(X509_CINF, validity, X509_VAL),
+        ASN1_SIMPLE(X509_CINF, subject, X509_NAME),
+        ASN1_SIMPLE(X509_CINF, key, X509_PUBKEY),
+        ASN1_IMP_OPT(X509_CINF, issuerUID, ASN1_BIT_STRING, 1),
+        ASN1_IMP_OPT(X509_CINF, subjectUID, ASN1_BIT_STRING, 2),
+        ASN1_EXP_SEQUENCE_OF_OPT(X509_CINF, extensions, X509_EXTENSION, 3)
 } ASN1_SEQUENCE_END_enc(X509_CINF, X509_CINF)
 
 IMPLEMENT_ASN1_FUNCTIONS(X509_CINF)
@@ -89,139 +91,238 @@
 extern void policy_cache_free(X509_POLICY_CACHE *cache);
 
 static int x509_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
-								void *exarg)
+                   void *exarg)
 {
-	X509 *ret = (X509 *)*pval;
+    X509 *ret = (X509 *)*pval;
 
-	switch(operation) {
+    switch (operation) {
 
-		case ASN1_OP_NEW_POST:
-		ret->valid=0;
-		ret->name = NULL;
-		ret->ex_flags = 0;
-		ret->ex_pathlen = -1;
-		ret->skid = NULL;
-		ret->akid = NULL;
-		ret->aux = NULL;
-		ret->crldp = NULL;
-		CRYPTO_new_ex_data(&ret->ex_data);
-		break;
+    case ASN1_OP_NEW_POST:
+        ret->name = NULL;
+        ret->ex_flags = 0;
+        ret->ex_pathlen = -1;
+        ret->skid = NULL;
+        ret->akid = NULL;
+        ret->aux = NULL;
+        ret->crldp = NULL;
+        ret->buf = NULL;
+        CRYPTO_new_ex_data(&ret->ex_data);
+        CRYPTO_MUTEX_init(&ret->lock);
+        break;
 
-		case ASN1_OP_D2I_POST:
-		if (ret->name != NULL) OPENSSL_free(ret->name);
-		ret->name=X509_NAME_oneline(ret->cert_info->subject,NULL,0);
-		break;
+    case ASN1_OP_D2I_PRE:
+        CRYPTO_BUFFER_free(ret->buf);
+        ret->buf = NULL;
+        break;
 
-		case ASN1_OP_FREE_POST:
-		CRYPTO_free_ex_data(&g_ex_data_class, ret, &ret->ex_data);
-		X509_CERT_AUX_free(ret->aux);
-		ASN1_OCTET_STRING_free(ret->skid);
-		AUTHORITY_KEYID_free(ret->akid);
-		CRL_DIST_POINTS_free(ret->crldp);
-		policy_cache_free(ret->policy_cache);
-		GENERAL_NAMES_free(ret->altname);
-		NAME_CONSTRAINTS_free(ret->nc);
+    case ASN1_OP_D2I_POST:
+        if (ret->name != NULL)
+            OPENSSL_free(ret->name);
+        ret->name = X509_NAME_oneline(ret->cert_info->subject, NULL, 0);
+        break;
 
-		if (ret->name != NULL) OPENSSL_free(ret->name);
-		break;
+    case ASN1_OP_FREE_POST:
+        CRYPTO_MUTEX_cleanup(&ret->lock);
+        CRYPTO_free_ex_data(&g_ex_data_class, ret, &ret->ex_data);
+        X509_CERT_AUX_free(ret->aux);
+        ASN1_OCTET_STRING_free(ret->skid);
+        AUTHORITY_KEYID_free(ret->akid);
+        CRL_DIST_POINTS_free(ret->crldp);
+        policy_cache_free(ret->policy_cache);
+        GENERAL_NAMES_free(ret->altname);
+        NAME_CONSTRAINTS_free(ret->nc);
+        CRYPTO_BUFFER_free(ret->buf);
+        OPENSSL_free(ret->name);
+        break;
 
-	}
+    }
 
-	return 1;
+    return 1;
 
 }
 
 ASN1_SEQUENCE_ref(X509, x509_cb) = {
-	ASN1_SIMPLE(X509, cert_info, X509_CINF),
-	ASN1_SIMPLE(X509, sig_alg, X509_ALGOR),
-	ASN1_SIMPLE(X509, signature, ASN1_BIT_STRING)
+        ASN1_SIMPLE(X509, cert_info, X509_CINF),
+        ASN1_SIMPLE(X509, sig_alg, X509_ALGOR),
+        ASN1_SIMPLE(X509, signature, ASN1_BIT_STRING)
 } ASN1_SEQUENCE_END_ref(X509, X509)
 
 IMPLEMENT_ASN1_FUNCTIONS(X509)
+
 IMPLEMENT_ASN1_DUP_FUNCTION(X509)
 
-X509 *X509_up_ref(X509 *x)
-	{
-	CRYPTO_refcount_inc(&x->references);
-	return x;
-	}
+X509 *X509_parse_from_buffer(CRYPTO_BUFFER *buf) {
+  if (CRYPTO_BUFFER_len(buf) > LONG_MAX) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
+    return 0;
+  }
 
-int X509_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused,
-	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
-        {
-	int index;
-	if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp,
-			dup_func, free_func))
-		{
-		return -1;
-		}
-	return index;
-        }
+  X509 *x509 = X509_new();
+  if (x509 == NULL) {
+    return NULL;
+  }
+
+  x509->cert_info->enc.alias_only_on_next_parse = 1;
+
+  const uint8_t *inp = CRYPTO_BUFFER_data(buf);
+  X509 *x509p = x509;
+  X509 *ret = d2i_X509(&x509p, &inp, CRYPTO_BUFFER_len(buf));
+  if (ret == NULL ||
+      inp - CRYPTO_BUFFER_data(buf) != (ptrdiff_t)CRYPTO_BUFFER_len(buf)) {
+    X509_free(x509p);
+    return NULL;
+  }
+  assert(x509p == x509);
+  assert(ret == x509);
+
+  CRYPTO_BUFFER_up_ref(buf);
+  ret->buf = buf;
+
+  return ret;
+}
+
+int X509_up_ref(X509 *x)
+{
+    CRYPTO_refcount_inc(&x->references);
+    return 1;
+}
+
+int X509_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused * unused,
+                          CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
+{
+    int index;
+    if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp,
+                                 dup_func, free_func)) {
+        return -1;
+    }
+    return index;
+}
 
 int X509_set_ex_data(X509 *r, int idx, void *arg)
-	{
-	return(CRYPTO_set_ex_data(&r->ex_data,idx,arg));
-	}
+{
+    return (CRYPTO_set_ex_data(&r->ex_data, idx, arg));
+}
 
 void *X509_get_ex_data(X509 *r, int idx)
-	{
-	return(CRYPTO_get_ex_data(&r->ex_data,idx));
-	}
+{
+    return (CRYPTO_get_ex_data(&r->ex_data, idx));
+}
 
-/* X509_AUX ASN1 routines. X509_AUX is the name given to
- * a certificate with extra info tagged on the end. Since these
- * functions set how a certificate is trusted they should only
- * be used when the certificate comes from a reliable source
- * such as local storage.
- *
+/*
+ * X509_AUX ASN1 routines. X509_AUX is the name given to a certificate with
+ * extra info tagged on the end. Since these functions set how a certificate
+ * is trusted they should only be used when the certificate comes from a
+ * reliable source such as local storage.
  */
 
 X509 *d2i_X509_AUX(X509 **a, const unsigned char **pp, long length)
 {
-	const unsigned char *q = *pp;
-	X509 *ret;
-	int freeret = 0;
+    const unsigned char *q = *pp;
+    X509 *ret;
+    int freeret = 0;
 
-	if (!a || *a == NULL)
-		freeret = 1;
-	ret = d2i_X509(a, &q, length);
-	/* If certificate unreadable then forget it */
-	if(!ret) return NULL;
-	/* update length */
-	length -= q - *pp;
-	/* Parse auxiliary information if there is any. */
-	if (length > 0 && !d2i_X509_CERT_AUX(&ret->aux, &q, length))
-		goto err;
-	*pp = q;
-	return ret;
-	err:
-	if (freeret)
-		{
-		X509_free(ret);
-		if (a)
-			*a = NULL;
-		}
-	return NULL;
+    if (!a || *a == NULL)
+        freeret = 1;
+    ret = d2i_X509(a, &q, length);
+    /* If certificate unreadable then forget it */
+    if (!ret)
+        return NULL;
+    /* update length */
+    length -= q - *pp;
+    /* Parse auxiliary information if there is any. */
+    if (length > 0 && !d2i_X509_CERT_AUX(&ret->aux, &q, length))
+        goto err;
+    *pp = q;
+    return ret;
+ err:
+    if (freeret) {
+        X509_free(ret);
+        if (a)
+            *a = NULL;
+    }
+    return NULL;
 }
 
+/*
+ * Serialize trusted certificate to *pp or just return the required buffer
+ * length if pp == NULL.  We ultimately want to avoid modifying *pp in the
+ * error path, but that depends on similar hygiene in lower-level functions.
+ * Here we avoid compounding the problem.
+ */
+static int i2d_x509_aux_internal(X509 *a, unsigned char **pp)
+{
+    int length, tmplen;
+    unsigned char *start = pp != NULL ? *pp : NULL;
+
+    assert(pp == NULL || *pp != NULL);
+
+    /*
+     * This might perturb *pp on error, but fixing that belongs in i2d_X509()
+     * not here.  It should be that if a == NULL length is zero, but we check
+     * both just in case.
+     */
+    length = i2d_X509(a, pp);
+    if (length <= 0 || a == NULL) {
+        return length;
+    }
+
+    tmplen = i2d_X509_CERT_AUX(a->aux, pp);
+    if (tmplen < 0) {
+        if (start != NULL)
+            *pp = start;
+        return tmplen;
+    }
+    length += tmplen;
+
+    return length;
+}
+
+/*
+ * Serialize trusted certificate to *pp, or just return the required buffer
+ * length if pp == NULL.
+ *
+ * When pp is not NULL, but *pp == NULL, we allocate the buffer, but since
+ * we're writing two ASN.1 objects back to back, we can't have i2d_X509() do
+ * the allocation, nor can we allow i2d_X509_CERT_AUX() to increment the
+ * allocated buffer.
+ */
 int i2d_X509_AUX(X509 *a, unsigned char **pp)
 {
-	int length;
-	length = i2d_X509(a, pp);
-	if(a) length += i2d_X509_CERT_AUX(a->aux, pp);
-	return length;
+    int length;
+    unsigned char *tmp;
+
+    /* Buffer provided by caller */
+    if (pp == NULL || *pp != NULL)
+        return i2d_x509_aux_internal(a, pp);
+
+    /* Obtain the combined length */
+    if ((length = i2d_x509_aux_internal(a, NULL)) <= 0)
+        return length;
+
+    /* Allocate requisite combined storage */
+    *pp = tmp = OPENSSL_malloc(length);
+    if (tmp == NULL)
+        return -1; /* Push error onto error stack? */
+
+    /* Encode, but keep *pp at the originally malloced pointer */
+    length = i2d_x509_aux_internal(a, &tmp);
+    if (length <= 0) {
+        OPENSSL_free(*pp);
+        *pp = NULL;
+    }
+    return length;
 }
 
 void X509_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg,
-				const X509 *x)
-	{
-	if (psig)
-		*psig = x->signature;
-	if (palg)
-		*palg = x->sig_alg;
-	}
+                         const X509 *x)
+{
+    if (psig)
+        *psig = x->signature;
+    if (palg)
+        *palg = x->sig_alg;
+}
 
 int X509_get_signature_nid(const X509 *x)
-	{
-	return OBJ_obj2nid(x->sig_alg->algorithm);
-	}
+{
+    return OBJ_obj2nid(x->sig_alg->algorithm);
+}
diff --git a/src/crypto/x509/x_x509a.c b/src/crypto/x509/x_x509a.c
index fb7172b..a63ee42 100644
--- a/src/crypto/x509/x_x509a.c
+++ b/src/crypto/x509/x_x509a.c
@@ -1,5 +1,7 @@
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999. */
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
+ */
 /* ====================================================================
  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
  *
@@ -8,7 +10,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -59,139 +61,145 @@
 #include <openssl/obj.h>
 #include <openssl/x509.h>
 
-
-/* X509_CERT_AUX routines. These are used to encode additional
- * user modifiable data about a certificate. This data is
- * appended to the X509 encoding when the *_X509_AUX routines
- * are used. This means that the "traditional" X509 routines
- * will simply ignore the extra data. */
+/*
+ * X509_CERT_AUX routines. These are used to encode additional user
+ * modifiable data about a certificate. This data is appended to the X509
+ * encoding when the *_X509_AUX routines are used. This means that the
+ * "traditional" X509 routines will simply ignore the extra data.
+ */
 
 static X509_CERT_AUX *aux_get(X509 *x);
 
 ASN1_SEQUENCE(X509_CERT_AUX) = {
-	ASN1_SEQUENCE_OF_OPT(X509_CERT_AUX, trust, ASN1_OBJECT),
-	ASN1_IMP_SEQUENCE_OF_OPT(X509_CERT_AUX, reject, ASN1_OBJECT, 0),
-	ASN1_OPT(X509_CERT_AUX, alias, ASN1_UTF8STRING),
-	ASN1_OPT(X509_CERT_AUX, keyid, ASN1_OCTET_STRING),
-	ASN1_IMP_SEQUENCE_OF_OPT(X509_CERT_AUX, other, X509_ALGOR, 1)
+        ASN1_SEQUENCE_OF_OPT(X509_CERT_AUX, trust, ASN1_OBJECT),
+        ASN1_IMP_SEQUENCE_OF_OPT(X509_CERT_AUX, reject, ASN1_OBJECT, 0),
+        ASN1_OPT(X509_CERT_AUX, alias, ASN1_UTF8STRING),
+        ASN1_OPT(X509_CERT_AUX, keyid, ASN1_OCTET_STRING),
+        ASN1_IMP_SEQUENCE_OF_OPT(X509_CERT_AUX, other, X509_ALGOR, 1)
 } ASN1_SEQUENCE_END(X509_CERT_AUX)
 
 IMPLEMENT_ASN1_FUNCTIONS(X509_CERT_AUX)
 
 static X509_CERT_AUX *aux_get(X509 *x)
 {
-	if(!x) return NULL;
-	if(!x->aux && !(x->aux = X509_CERT_AUX_new())) return NULL;
-	return x->aux;
+    if (!x)
+        return NULL;
+    if (!x->aux && !(x->aux = X509_CERT_AUX_new()))
+        return NULL;
+    return x->aux;
 }
 
 int X509_alias_set1(X509 *x, unsigned char *name, int len)
 {
-	X509_CERT_AUX *aux;
-	if (!name)
-		{
-		if (!x || !x->aux || !x->aux->alias)
-			return 1;
-		ASN1_UTF8STRING_free(x->aux->alias);
-		x->aux->alias = NULL;
-		return 1;
-		}
-	if(!(aux = aux_get(x))) return 0;
-	if(!aux->alias && !(aux->alias = ASN1_UTF8STRING_new())) return 0;
-	return ASN1_STRING_set(aux->alias, name, len);
+    X509_CERT_AUX *aux;
+    if (!name) {
+        if (!x || !x->aux || !x->aux->alias)
+            return 1;
+        ASN1_UTF8STRING_free(x->aux->alias);
+        x->aux->alias = NULL;
+        return 1;
+    }
+    if (!(aux = aux_get(x)))
+        return 0;
+    if (!aux->alias && !(aux->alias = ASN1_UTF8STRING_new()))
+        return 0;
+    return ASN1_STRING_set(aux->alias, name, len);
 }
 
 int X509_keyid_set1(X509 *x, unsigned char *id, int len)
 {
-	X509_CERT_AUX *aux;
-	if (!id)
-		{
-		if (!x || !x->aux || !x->aux->keyid)
-			return 1;
-		ASN1_OCTET_STRING_free(x->aux->keyid);
-		x->aux->keyid = NULL;
-		return 1;
-		}
-	if(!(aux = aux_get(x))) return 0;
-	if(!aux->keyid && !(aux->keyid = ASN1_OCTET_STRING_new())) return 0;
-	return ASN1_STRING_set(aux->keyid, id, len);
+    X509_CERT_AUX *aux;
+    if (!id) {
+        if (!x || !x->aux || !x->aux->keyid)
+            return 1;
+        ASN1_OCTET_STRING_free(x->aux->keyid);
+        x->aux->keyid = NULL;
+        return 1;
+    }
+    if (!(aux = aux_get(x)))
+        return 0;
+    if (!aux->keyid && !(aux->keyid = ASN1_OCTET_STRING_new()))
+        return 0;
+    return ASN1_STRING_set(aux->keyid, id, len);
 }
 
 unsigned char *X509_alias_get0(X509 *x, int *len)
 {
-	if(!x->aux || !x->aux->alias) return NULL;
-	if(len) *len = x->aux->alias->length;
-	return x->aux->alias->data;
+    if (!x->aux || !x->aux->alias)
+        return NULL;
+    if (len)
+        *len = x->aux->alias->length;
+    return x->aux->alias->data;
 }
 
 unsigned char *X509_keyid_get0(X509 *x, int *len)
 {
-	if(!x->aux || !x->aux->keyid) return NULL;
-	if(len) *len = x->aux->keyid->length;
-	return x->aux->keyid->data;
+    if (!x->aux || !x->aux->keyid)
+        return NULL;
+    if (len)
+        *len = x->aux->keyid->length;
+    return x->aux->keyid->data;
 }
 
 int X509_add1_trust_object(X509 *x, ASN1_OBJECT *obj)
 {
-	ASN1_OBJECT *objtmp = OBJ_dup(obj);
-	if (objtmp == NULL)
-		goto err;
-	X509_CERT_AUX *aux = aux_get(x);
-	if (aux->trust == NULL)
-		{
-		aux->trust = sk_ASN1_OBJECT_new_null();
-		if (aux->trust == NULL)
-			goto err;
-		}
-	if (!sk_ASN1_OBJECT_push(aux->trust, objtmp))
-		goto err;
-	return 1;
+    ASN1_OBJECT *objtmp = OBJ_dup(obj);
+    if (objtmp == NULL)
+        goto err;
+    X509_CERT_AUX *aux = aux_get(x);
+    if (aux->trust == NULL) {
+        aux->trust = sk_ASN1_OBJECT_new_null();
+        if (aux->trust == NULL)
+            goto err;
+    }
+    if (!sk_ASN1_OBJECT_push(aux->trust, objtmp))
+        goto err;
+    return 1;
 
-err:
-	ASN1_OBJECT_free(objtmp);
-	return 0;
+ err:
+    ASN1_OBJECT_free(objtmp);
+    return 0;
 }
 
 int X509_add1_reject_object(X509 *x, ASN1_OBJECT *obj)
 {
-	ASN1_OBJECT *objtmp = OBJ_dup(obj);
-	if (objtmp == NULL)
-		goto err;
-	X509_CERT_AUX *aux = aux_get(x);
-	if (aux->reject == NULL)
-		{
-		aux->reject = sk_ASN1_OBJECT_new_null();
-		if (aux->reject == NULL)
-			goto err;
-		}
-	if (!sk_ASN1_OBJECT_push(aux->reject, objtmp))
-		goto err;
-	return 1;
+    ASN1_OBJECT *objtmp = OBJ_dup(obj);
+    if (objtmp == NULL)
+        goto err;
+    X509_CERT_AUX *aux = aux_get(x);
+    if (aux->reject == NULL) {
+        aux->reject = sk_ASN1_OBJECT_new_null();
+        if (aux->reject == NULL)
+            goto err;
+    }
+    if (!sk_ASN1_OBJECT_push(aux->reject, objtmp))
+        goto err;
+    return 1;
 
-err:
-	ASN1_OBJECT_free(objtmp);
-	return 0;
+ err:
+    ASN1_OBJECT_free(objtmp);
+    return 0;
 }
 
 void X509_trust_clear(X509 *x)
 {
-	if(x->aux && x->aux->trust) {
-		sk_ASN1_OBJECT_pop_free(x->aux->trust, ASN1_OBJECT_free);
-		x->aux->trust = NULL;
-	}
+    if (x->aux && x->aux->trust) {
+        sk_ASN1_OBJECT_pop_free(x->aux->trust, ASN1_OBJECT_free);
+        x->aux->trust = NULL;
+    }
 }
 
 void X509_reject_clear(X509 *x)
 {
-	if(x->aux && x->aux->reject) {
-		sk_ASN1_OBJECT_pop_free(x->aux->reject, ASN1_OBJECT_free);
-		x->aux->reject = NULL;
-	}
+    if (x->aux && x->aux->reject) {
+        sk_ASN1_OBJECT_pop_free(x->aux->reject, ASN1_OBJECT_free);
+        x->aux->reject = NULL;
+    }
 }
 
 ASN1_SEQUENCE(X509_CERT_PAIR) = {
-	ASN1_EXP_OPT(X509_CERT_PAIR, forward, X509, 0),
-	ASN1_EXP_OPT(X509_CERT_PAIR, reverse, X509, 1)
+        ASN1_EXP_OPT(X509_CERT_PAIR, forward, X509, 0),
+        ASN1_EXP_OPT(X509_CERT_PAIR, reverse, X509, 1)
 } ASN1_SEQUENCE_END(X509_CERT_PAIR)
 
 IMPLEMENT_ASN1_FUNCTIONS(X509_CERT_PAIR)
diff --git a/src/crypto/x509v3/ext_dat.h b/src/crypto/x509v3/ext_dat.h
index f1fb8ef..9ece19c 100644
--- a/src/crypto/x509v3/ext_dat.h
+++ b/src/crypto/x509v3/ext_dat.h
@@ -1,5 +1,6 @@
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
  */
 /* ====================================================================
  * Copyright (c) 1999-2004 The OpenSSL Project.  All rights reserved.
@@ -9,7 +10,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -56,74 +57,79 @@
 /* This file contains a table of "standard" extensions */
 
 extern const X509V3_EXT_METHOD v3_bcons, v3_nscert, v3_key_usage, v3_ext_ku;
-extern const X509V3_EXT_METHOD v3_pkey_usage_period, v3_sxnet, v3_info, v3_sinfo;
-extern const X509V3_EXT_METHOD v3_ns_ia5_list[], v3_alt[], v3_skey_id, v3_akey_id;
+extern const X509V3_EXT_METHOD v3_pkey_usage_period, v3_sxnet, v3_info,
+    v3_sinfo;
+extern const X509V3_EXT_METHOD v3_ns_ia5_list[], v3_alt[], v3_skey_id,
+    v3_akey_id;
 extern const X509V3_EXT_METHOD v3_crl_num, v3_crl_reason, v3_crl_invdate;
-extern const X509V3_EXT_METHOD v3_delta_crl, v3_cpols, v3_crld, v3_freshest_crl;
-extern const X509V3_EXT_METHOD v3_ocsp_nonce, v3_ocsp_accresp, v3_ocsp_acutoff;
-extern const X509V3_EXT_METHOD v3_ocsp_crlid, v3_ocsp_nocheck, v3_ocsp_serviceloc;
+extern const X509V3_EXT_METHOD v3_delta_crl, v3_cpols, v3_crld,
+    v3_freshest_crl;
+extern const X509V3_EXT_METHOD v3_ocsp_nonce, v3_ocsp_accresp,
+    v3_ocsp_acutoff;
+extern const X509V3_EXT_METHOD v3_ocsp_crlid, v3_ocsp_nocheck,
+    v3_ocsp_serviceloc;
 extern const X509V3_EXT_METHOD v3_crl_hold, v3_pci;
 extern const X509V3_EXT_METHOD v3_policy_mappings, v3_policy_constraints;
 extern const X509V3_EXT_METHOD v3_name_constraints, v3_inhibit_anyp, v3_idp;
 extern const X509V3_EXT_METHOD v3_addr, v3_asid;
 
-/* This table will be searched using OBJ_bsearch so it *must* kept in
- * order of the ext_nid values.
+/*
+ * This table will be searched using OBJ_bsearch so it *must* kept in order
+ * of the ext_nid values.
  */
 
 /* TODO(fork): OCSP support */
 #define OPENSSL_NO_OCSP
 
 static const X509V3_EXT_METHOD *const standard_exts[] = {
-&v3_nscert,
-&v3_ns_ia5_list[0],
-&v3_ns_ia5_list[1],
-&v3_ns_ia5_list[2],
-&v3_ns_ia5_list[3],
-&v3_ns_ia5_list[4],
-&v3_ns_ia5_list[5],
-&v3_ns_ia5_list[6],
-&v3_skey_id,
-&v3_key_usage,
-&v3_pkey_usage_period,
-&v3_alt[0],
-&v3_alt[1],
-&v3_bcons,
-&v3_crl_num,
-&v3_cpols,
-&v3_akey_id,
-&v3_crld,
-&v3_ext_ku,
-&v3_delta_crl,
-&v3_crl_reason,
+    &v3_nscert,
+    &v3_ns_ia5_list[0],
+    &v3_ns_ia5_list[1],
+    &v3_ns_ia5_list[2],
+    &v3_ns_ia5_list[3],
+    &v3_ns_ia5_list[4],
+    &v3_ns_ia5_list[5],
+    &v3_ns_ia5_list[6],
+    &v3_skey_id,
+    &v3_key_usage,
+    &v3_pkey_usage_period,
+    &v3_alt[0],
+    &v3_alt[1],
+    &v3_bcons,
+    &v3_crl_num,
+    &v3_cpols,
+    &v3_akey_id,
+    &v3_crld,
+    &v3_ext_ku,
+    &v3_delta_crl,
+    &v3_crl_reason,
 #ifndef OPENSSL_NO_OCSP
-&v3_crl_invdate,
+    &v3_crl_invdate,
 #endif
-&v3_sxnet,
-&v3_info,
+    &v3_sxnet,
+    &v3_info,
 #ifndef OPENSSL_NO_OCSP
-&v3_ocsp_nonce,
-&v3_ocsp_crlid,
-&v3_ocsp_accresp,
-&v3_ocsp_nocheck,
-&v3_ocsp_acutoff,
-&v3_ocsp_serviceloc,
+    &v3_ocsp_nonce,
+    &v3_ocsp_crlid,
+    &v3_ocsp_accresp,
+    &v3_ocsp_nocheck,
+    &v3_ocsp_acutoff,
+    &v3_ocsp_serviceloc,
 #endif
-&v3_sinfo,
-&v3_policy_constraints,
+    &v3_sinfo,
+    &v3_policy_constraints,
 #ifndef OPENSSL_NO_OCSP
-&v3_crl_hold,
+    &v3_crl_hold,
 #endif
-&v3_pci,
-&v3_name_constraints,
-&v3_policy_mappings,
-&v3_inhibit_anyp,
-&v3_idp,
-&v3_alt[2],
-&v3_freshest_crl,
+    &v3_pci,
+    &v3_name_constraints,
+    &v3_policy_mappings,
+    &v3_inhibit_anyp,
+    &v3_idp,
+    &v3_alt[2],
+    &v3_freshest_crl,
 };
 
 /* Number of standard extensions */
 
 #define STANDARD_EXTENSION_COUNT (sizeof(standard_exts)/sizeof(X509V3_EXT_METHOD *))
-
diff --git a/src/crypto/x509v3/pcy_cache.c b/src/crypto/x509v3/pcy_cache.c
index 08f20aa..b8a4be2 100644
--- a/src/crypto/x509v3/pcy_cache.c
+++ b/src/crypto/x509v3/pcy_cache.c
@@ -1,5 +1,6 @@
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 2004.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 2004.
  */
 /* ====================================================================
  * Copyright (c) 2004 The OpenSSL Project.  All rights reserved.
@@ -9,7 +10,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -62,238 +63,222 @@
 #include "pcy_int.h"
 #include "../internal.h"
 
-
 static int policy_data_cmp(const X509_POLICY_DATA **a,
-				const X509_POLICY_DATA **b);
+                           const X509_POLICY_DATA **b);
 static int policy_cache_set_int(long *out, ASN1_INTEGER *value);
 
-/* Set cache entry according to CertificatePolicies extension.
- * Note: this destroys the passed CERTIFICATEPOLICIES structure.
+/*
+ * Set cache entry according to CertificatePolicies extension. Note: this
+ * destroys the passed CERTIFICATEPOLICIES structure.
  */
 
 static int policy_cache_create(X509 *x,
-			CERTIFICATEPOLICIES *policies, int crit)
-	{
-	size_t i;
-	int ret = 0;
-	X509_POLICY_CACHE *cache = x->policy_cache;
-	X509_POLICY_DATA *data = NULL;
-	POLICYINFO *policy;
-	if (sk_POLICYINFO_num(policies) == 0)
-		goto bad_policy;
-	cache->data = sk_X509_POLICY_DATA_new(policy_data_cmp);
-	if (!cache->data)
-		goto bad_policy;
-	for (i = 0; i < sk_POLICYINFO_num(policies); i++)
-		{
-		policy = sk_POLICYINFO_value(policies, i);
-		data = policy_data_new(policy, NULL, crit);
-		if (!data)
-			goto bad_policy;
-		/* Duplicate policy OIDs are illegal: reject if matches
-		 * found.
-		 */
-		if (OBJ_obj2nid(data->valid_policy) == NID_any_policy)
-			{
-			if (cache->anyPolicy)
-				{
-				ret = -1;
-				goto bad_policy;
-				}
-			cache->anyPolicy = data;
-			}
-		else if (sk_X509_POLICY_DATA_find(cache->data, NULL, data))
-			{
-			ret = -1;
-			goto bad_policy;
-			}
-		else if (!sk_X509_POLICY_DATA_push(cache->data, data))
-			goto bad_policy;
-		data = NULL;
-		}
-	ret = 1;
-	bad_policy:
-	if (ret == -1)
-		x->ex_flags |= EXFLAG_INVALID_POLICY;
-	if (data)
-		policy_data_free(data);
-	sk_POLICYINFO_pop_free(policies, POLICYINFO_free);
-	if (ret <= 0)
-		{
-		sk_X509_POLICY_DATA_pop_free(cache->data, policy_data_free);
-		cache->data = NULL;
-		}
-	return ret;
-	}
+                               CERTIFICATEPOLICIES *policies, int crit)
+{
+    size_t i;
+    int ret = 0;
+    X509_POLICY_CACHE *cache = x->policy_cache;
+    X509_POLICY_DATA *data = NULL;
+    POLICYINFO *policy;
+    if (sk_POLICYINFO_num(policies) == 0)
+        goto bad_policy;
+    cache->data = sk_X509_POLICY_DATA_new(policy_data_cmp);
+    if (!cache->data)
+        goto bad_policy;
+    for (i = 0; i < sk_POLICYINFO_num(policies); i++) {
+        policy = sk_POLICYINFO_value(policies, i);
+        data = policy_data_new(policy, NULL, crit);
+        if (!data)
+            goto bad_policy;
+        /*
+         * Duplicate policy OIDs are illegal: reject if matches found.
+         */
+        if (OBJ_obj2nid(data->valid_policy) == NID_any_policy) {
+            if (cache->anyPolicy) {
+                ret = -1;
+                goto bad_policy;
+            }
+            cache->anyPolicy = data;
+        } else if (sk_X509_POLICY_DATA_find(cache->data, NULL, data)) {
+            ret = -1;
+            goto bad_policy;
+        } else if (!sk_X509_POLICY_DATA_push(cache->data, data))
+            goto bad_policy;
+        data = NULL;
+    }
+    ret = 1;
+ bad_policy:
+    if (ret == -1)
+        x->ex_flags |= EXFLAG_INVALID_POLICY;
+    if (data)
+        policy_data_free(data);
+    sk_POLICYINFO_pop_free(policies, POLICYINFO_free);
+    if (ret <= 0) {
+        sk_X509_POLICY_DATA_pop_free(cache->data, policy_data_free);
+        cache->data = NULL;
+    }
+    return ret;
+}
 
-	
 static int policy_cache_new(X509 *x)
-	{
-	X509_POLICY_CACHE *cache;
-	ASN1_INTEGER *ext_any = NULL;
-	POLICY_CONSTRAINTS *ext_pcons = NULL;
-	CERTIFICATEPOLICIES *ext_cpols = NULL;
-	POLICY_MAPPINGS *ext_pmaps = NULL;
-	int i;
-	cache = OPENSSL_malloc(sizeof(X509_POLICY_CACHE));
-	if (!cache)
-		return 0;
-	cache->anyPolicy = NULL;
-	cache->data = NULL;
-	cache->any_skip = -1;
-	cache->explicit_skip = -1;
-	cache->map_skip = -1;
+{
+    X509_POLICY_CACHE *cache;
+    ASN1_INTEGER *ext_any = NULL;
+    POLICY_CONSTRAINTS *ext_pcons = NULL;
+    CERTIFICATEPOLICIES *ext_cpols = NULL;
+    POLICY_MAPPINGS *ext_pmaps = NULL;
+    int i;
+    cache = OPENSSL_malloc(sizeof(X509_POLICY_CACHE));
+    if (!cache)
+        return 0;
+    cache->anyPolicy = NULL;
+    cache->data = NULL;
+    cache->any_skip = -1;
+    cache->explicit_skip = -1;
+    cache->map_skip = -1;
 
-	x->policy_cache = cache;
+    x->policy_cache = cache;
 
-	/* Handle requireExplicitPolicy *first*. Need to process this
-	 * even if we don't have any policies.
-	 */
-	ext_pcons = X509_get_ext_d2i(x, NID_policy_constraints, &i, NULL);
+    /*
+     * Handle requireExplicitPolicy *first*. Need to process this even if we
+     * don't have any policies.
+     */
+    ext_pcons = X509_get_ext_d2i(x, NID_policy_constraints, &i, NULL);
 
-	if (!ext_pcons)
-		{
-		if (i != -1)
-			goto bad_cache;
-		}
-	else
-		{
-		if (!ext_pcons->requireExplicitPolicy
-			&& !ext_pcons->inhibitPolicyMapping)
-			goto bad_cache;
-		if (!policy_cache_set_int(&cache->explicit_skip,
-			ext_pcons->requireExplicitPolicy))
-			goto bad_cache;
-		if (!policy_cache_set_int(&cache->map_skip,
-			ext_pcons->inhibitPolicyMapping))
-			goto bad_cache;
-		}
+    if (!ext_pcons) {
+        if (i != -1)
+            goto bad_cache;
+    } else {
+        if (!ext_pcons->requireExplicitPolicy
+            && !ext_pcons->inhibitPolicyMapping)
+            goto bad_cache;
+        if (!policy_cache_set_int(&cache->explicit_skip,
+                                  ext_pcons->requireExplicitPolicy))
+            goto bad_cache;
+        if (!policy_cache_set_int(&cache->map_skip,
+                                  ext_pcons->inhibitPolicyMapping))
+            goto bad_cache;
+    }
 
-	/* Process CertificatePolicies */
+    /* Process CertificatePolicies */
 
-	ext_cpols = X509_get_ext_d2i(x, NID_certificate_policies, &i, NULL);
-	/* If no CertificatePolicies extension or problem decoding then
-	 * there is no point continuing because the valid policies will be
-	 * NULL.
-	 */
-	if (!ext_cpols)
-		{
-		/* If not absent some problem with extension */
-		if (i != -1)
-			goto bad_cache;
-		return 1;
-		}
+    ext_cpols = X509_get_ext_d2i(x, NID_certificate_policies, &i, NULL);
+    /*
+     * If no CertificatePolicies extension or problem decoding then there is
+     * no point continuing because the valid policies will be NULL.
+     */
+    if (!ext_cpols) {
+        /* If not absent some problem with extension */
+        if (i != -1)
+            goto bad_cache;
+        return 1;
+    }
 
-	i = policy_cache_create(x, ext_cpols, i);
+    i = policy_cache_create(x, ext_cpols, i);
 
-	/* NB: ext_cpols freed by policy_cache_set_policies */
+    /* NB: ext_cpols freed by policy_cache_set_policies */
 
-	if (i <= 0)
-		return i;
+    if (i <= 0)
+        return i;
 
-	ext_pmaps = X509_get_ext_d2i(x, NID_policy_mappings, &i, NULL);
+    ext_pmaps = X509_get_ext_d2i(x, NID_policy_mappings, &i, NULL);
 
-	if (!ext_pmaps)
-		{
-		/* If not absent some problem with extension */
-		if (i != -1)
-			goto bad_cache;
-		}
-	else
-		{
-		i = policy_cache_set_mapping(x, ext_pmaps);
-		if (i <= 0)
-			goto bad_cache;
-		}
+    if (!ext_pmaps) {
+        /* If not absent some problem with extension */
+        if (i != -1)
+            goto bad_cache;
+    } else {
+        i = policy_cache_set_mapping(x, ext_pmaps);
+        if (i <= 0)
+            goto bad_cache;
+    }
 
-	ext_any = X509_get_ext_d2i(x, NID_inhibit_any_policy, &i, NULL);
+    ext_any = X509_get_ext_d2i(x, NID_inhibit_any_policy, &i, NULL);
 
-	if (!ext_any)
-		{
-		if (i != -1)
-			goto bad_cache;
-		}
-	else if (!policy_cache_set_int(&cache->any_skip, ext_any))
-			goto bad_cache;
+    if (!ext_any) {
+        if (i != -1)
+            goto bad_cache;
+    } else if (!policy_cache_set_int(&cache->any_skip, ext_any))
+        goto bad_cache;
 
-	if (0)
-		{
-		bad_cache:
-		x->ex_flags |= EXFLAG_INVALID_POLICY;
-		}
+    if (0) {
+ bad_cache:
+        x->ex_flags |= EXFLAG_INVALID_POLICY;
+    }
 
-	if(ext_pcons)
-		POLICY_CONSTRAINTS_free(ext_pcons);
+    if (ext_pcons)
+        POLICY_CONSTRAINTS_free(ext_pcons);
 
-	if (ext_any)
-		ASN1_INTEGER_free(ext_any);
+    if (ext_any)
+        ASN1_INTEGER_free(ext_any);
 
-	return 1;
+    return 1;
 
-	
 }
 
 void policy_cache_free(X509_POLICY_CACHE *cache)
-	{
-	if (!cache)
-		return;
-	if (cache->anyPolicy)
-		policy_data_free(cache->anyPolicy);
-	if (cache->data)
-		sk_X509_POLICY_DATA_pop_free(cache->data, policy_data_free);
-	OPENSSL_free(cache);
-	}
+{
+    if (!cache)
+        return;
+    if (cache->anyPolicy)
+        policy_data_free(cache->anyPolicy);
+    if (cache->data)
+        sk_X509_POLICY_DATA_pop_free(cache->data, policy_data_free);
+    OPENSSL_free(cache);
+}
 
-/* g_x509_policy_cache_lock is used to protect against concurrent calls to
- * |policy_cache_new|. Ideally this would be done with a |CRYPTO_once_t|
- * in the |X509| structure, but |CRYPTO_once_t| isn't public. */
+/*
+ * g_x509_policy_cache_lock is used to protect against concurrent calls to
+ * |policy_cache_new|. Ideally this would be done with a |CRYPTO_once_t| in
+ * the |X509| structure, but |CRYPTO_once_t| isn't public.
+ */
 static struct CRYPTO_STATIC_MUTEX g_x509_policy_cache_lock =
     CRYPTO_STATIC_MUTEX_INIT;
 
 const X509_POLICY_CACHE *policy_cache_set(X509 *x)
-	{
-	X509_POLICY_CACHE *cache;
+{
+    X509_POLICY_CACHE *cache;
 
-	CRYPTO_STATIC_MUTEX_lock_read(&g_x509_policy_cache_lock);
-	cache = x->policy_cache;
-	CRYPTO_STATIC_MUTEX_unlock(&g_x509_policy_cache_lock);
+    CRYPTO_STATIC_MUTEX_lock_read(&g_x509_policy_cache_lock);
+    cache = x->policy_cache;
+    CRYPTO_STATIC_MUTEX_unlock_read(&g_x509_policy_cache_lock);
 
-	if (cache != NULL)
-		return cache;
+    if (cache != NULL)
+        return cache;
 
-	CRYPTO_STATIC_MUTEX_lock_write(&g_x509_policy_cache_lock);
-	if (x->policy_cache == NULL)
-		policy_cache_new(x);
-	cache = x->policy_cache;
-	CRYPTO_STATIC_MUTEX_unlock(&g_x509_policy_cache_lock);
+    CRYPTO_STATIC_MUTEX_lock_write(&g_x509_policy_cache_lock);
+    if (x->policy_cache == NULL)
+        policy_cache_new(x);
+    cache = x->policy_cache;
+    CRYPTO_STATIC_MUTEX_unlock_write(&g_x509_policy_cache_lock);
 
-	return cache;
-	}
+    return cache;
+}
 
 X509_POLICY_DATA *policy_cache_find_data(const X509_POLICY_CACHE *cache,
-						const ASN1_OBJECT *id)
-	{
-	size_t idx;
-	X509_POLICY_DATA tmp;
+                                         const ASN1_OBJECT *id)
+{
+    size_t idx;
+    X509_POLICY_DATA tmp;
 
-	tmp.valid_policy = (ASN1_OBJECT *)id;
-	if (!sk_X509_POLICY_DATA_find(cache->data, &idx, &tmp))
-		return NULL;
-	return sk_X509_POLICY_DATA_value(cache->data, idx);
-	}
+    tmp.valid_policy = (ASN1_OBJECT *)id;
+    if (!sk_X509_POLICY_DATA_find(cache->data, &idx, &tmp))
+        return NULL;
+    return sk_X509_POLICY_DATA_value(cache->data, idx);
+}
 
 static int policy_data_cmp(const X509_POLICY_DATA **a,
-				const X509_POLICY_DATA **b)
-	{
-	return OBJ_cmp((*a)->valid_policy, (*b)->valid_policy);
-	}
+                           const X509_POLICY_DATA **b)
+{
+    return OBJ_cmp((*a)->valid_policy, (*b)->valid_policy);
+}
 
 static int policy_cache_set_int(long *out, ASN1_INTEGER *value)
-	{
-	if (value == NULL)
-		return 1;
-	if (value->type == V_ASN1_NEG_INTEGER)
-		return 0;
-	*out = ASN1_INTEGER_get(value);
-	return 1;
-	}
+{
+    if (value == NULL)
+        return 1;
+    if (value->type == V_ASN1_NEG_INTEGER)
+        return 0;
+    *out = ASN1_INTEGER_get(value);
+    return 1;
+}
diff --git a/src/crypto/x509v3/pcy_data.c b/src/crypto/x509v3/pcy_data.c
index cd45dca..498de4d 100644
--- a/src/crypto/x509v3/pcy_data.c
+++ b/src/crypto/x509v3/pcy_data.c
@@ -1,6 +1,7 @@
 /* pcy_data.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 2004.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 2004.
  */
 /* ====================================================================
  * Copyright (c) 2004 The OpenSSL Project.  All rights reserved.
@@ -10,7 +11,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -63,75 +64,67 @@
 
 #include "pcy_int.h"
 
-
 /* Policy Node routines */
 
 void policy_data_free(X509_POLICY_DATA *data)
-	{
-	ASN1_OBJECT_free(data->valid_policy);
-	/* Don't free qualifiers if shared */
-	if (!(data->flags & POLICY_DATA_FLAG_SHARED_QUALIFIERS))
-		sk_POLICYQUALINFO_pop_free(data->qualifier_set,
-					POLICYQUALINFO_free);
-	sk_ASN1_OBJECT_pop_free(data->expected_policy_set, ASN1_OBJECT_free);
-	OPENSSL_free(data);
-	}
+{
+    ASN1_OBJECT_free(data->valid_policy);
+    /* Don't free qualifiers if shared */
+    if (!(data->flags & POLICY_DATA_FLAG_SHARED_QUALIFIERS))
+        sk_POLICYQUALINFO_pop_free(data->qualifier_set, POLICYQUALINFO_free);
+    sk_ASN1_OBJECT_pop_free(data->expected_policy_set, ASN1_OBJECT_free);
+    OPENSSL_free(data);
+}
 
-/* Create a data based on an existing policy. If 'id' is NULL use the
- * oid in the policy, otherwise use 'id'. This behaviour covers the two
- * types of data in RFC3280: data with from a CertificatePolcies extension
- * and additional data with just the qualifiers of anyPolicy and ID from
- * another source.
+/*
+ * Create a data based on an existing policy. If 'id' is NULL use the oid in
+ * the policy, otherwise use 'id'. This behaviour covers the two types of
+ * data in RFC3280: data with from a CertificatePolcies extension and
+ * additional data with just the qualifiers of anyPolicy and ID from another
+ * source.
  */
 
 X509_POLICY_DATA *policy_data_new(POLICYINFO *policy,
-					const ASN1_OBJECT *cid, int crit)
-	{
-	X509_POLICY_DATA *ret;
-	ASN1_OBJECT *id;
-	if (!policy && !cid)
-		return NULL;
-	if (cid)
-		{
-		id = OBJ_dup(cid);
-		if (!id)
-			return NULL;
-		}
-	else
-		id = NULL;
-	ret = OPENSSL_malloc(sizeof(X509_POLICY_DATA));
-	if (!ret)
-		return NULL;
-	ret->expected_policy_set = sk_ASN1_OBJECT_new_null();
-	if (!ret->expected_policy_set)
-		{
-		OPENSSL_free(ret);
-		if (id)
-			ASN1_OBJECT_free(id);
-		return NULL;
-		}
+                                  const ASN1_OBJECT *cid, int crit)
+{
+    X509_POLICY_DATA *ret;
+    ASN1_OBJECT *id;
+    if (!policy && !cid)
+        return NULL;
+    if (cid) {
+        id = OBJ_dup(cid);
+        if (!id)
+            return NULL;
+    } else
+        id = NULL;
+    ret = OPENSSL_malloc(sizeof(X509_POLICY_DATA));
+    if (!ret)
+        return NULL;
+    ret->expected_policy_set = sk_ASN1_OBJECT_new_null();
+    if (!ret->expected_policy_set) {
+        OPENSSL_free(ret);
+        if (id)
+            ASN1_OBJECT_free(id);
+        return NULL;
+    }
 
-	if (crit)
-		ret->flags = POLICY_DATA_FLAG_CRITICAL;
-	else
-		ret->flags = 0;
+    if (crit)
+        ret->flags = POLICY_DATA_FLAG_CRITICAL;
+    else
+        ret->flags = 0;
 
-	if (id)
-		ret->valid_policy = id;
-	else
-		{
-		ret->valid_policy = policy->policyid;
-		policy->policyid = NULL;
-		}
+    if (id)
+        ret->valid_policy = id;
+    else {
+        ret->valid_policy = policy->policyid;
+        policy->policyid = NULL;
+    }
 
-	if (policy)
-		{
-		ret->qualifier_set = policy->qualifiers;
-		policy->qualifiers = NULL;
-		}
-	else
-		ret->qualifier_set = NULL;
+    if (policy) {
+        ret->qualifier_set = policy->qualifiers;
+        policy->qualifiers = NULL;
+    } else
+        ret->qualifier_set = NULL;
 
-	return ret;
-	}
-
+    return ret;
+}
diff --git a/src/crypto/x509v3/pcy_int.h b/src/crypto/x509v3/pcy_int.h
index ccff928..1e76503 100644
--- a/src/crypto/x509v3/pcy_int.h
+++ b/src/crypto/x509v3/pcy_int.h
@@ -1,6 +1,7 @@
 /* pcy_int.h */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 2004.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 2004.
  */
 /* ====================================================================
  * Copyright (c) 2004 The OpenSSL Project.  All rights reserved.
@@ -10,7 +11,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -56,138 +57,142 @@
  *
  */
 
-
 typedef struct X509_POLICY_DATA_st X509_POLICY_DATA;
 
 DECLARE_STACK_OF(X509_POLICY_DATA)
 
 /* Internal structures */
 
-/* This structure and the field names correspond to the Policy 'node' of
- * RFC3280. NB this structure contains no pointers to parent or child
- * data: X509_POLICY_NODE contains that. This means that the main policy data
- * can be kept static and cached with the certificate.
+/*
+ * This structure and the field names correspond to the Policy 'node' of
+ * RFC3280. NB this structure contains no pointers to parent or child data:
+ * X509_POLICY_NODE contains that. This means that the main policy data can
+ * be kept static and cached with the certificate.
  */
 
-struct X509_POLICY_DATA_st
-	{
-	unsigned int flags;
-	/* Policy OID and qualifiers for this data */
-	ASN1_OBJECT *valid_policy;
-	STACK_OF(POLICYQUALINFO) *qualifier_set;
-	STACK_OF(ASN1_OBJECT) *expected_policy_set;
-	};
+struct X509_POLICY_DATA_st {
+    unsigned int flags;
+    /* Policy OID and qualifiers for this data */
+    ASN1_OBJECT *valid_policy;
+    STACK_OF(POLICYQUALINFO) *qualifier_set;
+    STACK_OF(ASN1_OBJECT) *expected_policy_set;
+};
 
 /* X509_POLICY_DATA flags values */
 
-/* This flag indicates the structure has been mapped using a policy mapping
- * extension. If policy mapping is not active its references get deleted. 
+/*
+ * This flag indicates the structure has been mapped using a policy mapping
+ * extension. If policy mapping is not active its references get deleted.
  */
 
-#define POLICY_DATA_FLAG_MAPPED			0x1
+#define POLICY_DATA_FLAG_MAPPED                 0x1
 
-/* This flag indicates the data doesn't correspond to a policy in Certificate
+/*
+ * This flag indicates the data doesn't correspond to a policy in Certificate
  * Policies: it has been mapped to any policy.
  */
 
-#define POLICY_DATA_FLAG_MAPPED_ANY		0x2
+#define POLICY_DATA_FLAG_MAPPED_ANY             0x2
 
 /* AND with flags to see if any mapping has occurred */
 
-#define POLICY_DATA_FLAG_MAP_MASK		0x3
+#define POLICY_DATA_FLAG_MAP_MASK               0x3
 
 /* qualifiers are shared and shouldn't be freed */
 
-#define POLICY_DATA_FLAG_SHARED_QUALIFIERS	0x4
+#define POLICY_DATA_FLAG_SHARED_QUALIFIERS      0x4
 
 /* Parent node is an extra node and should be freed */
 
-#define POLICY_DATA_FLAG_EXTRA_NODE		0x8
+#define POLICY_DATA_FLAG_EXTRA_NODE             0x8
 
 /* Corresponding CertificatePolicies is critical */
 
-#define POLICY_DATA_FLAG_CRITICAL		0x10
+#define POLICY_DATA_FLAG_CRITICAL               0x10
 
 /* This structure is cached with a certificate */
 
 struct X509_POLICY_CACHE_st {
-	/* anyPolicy data or NULL if no anyPolicy */
-	X509_POLICY_DATA *anyPolicy;
-	/* other policy data */
-	STACK_OF(X509_POLICY_DATA) *data;
-	/* If InhibitAnyPolicy present this is its value or -1 if absent. */
-	long any_skip;
-	/* If policyConstraints and requireExplicitPolicy present this is its
-	 * value or -1 if absent.
-	 */
-	long explicit_skip;
-	/* If policyConstraints and policyMapping present this is its
-	 * value or -1 if absent.
-         */
-	long map_skip;
-	};
+    /* anyPolicy data or NULL if no anyPolicy */
+    X509_POLICY_DATA *anyPolicy;
+    /* other policy data */
+    STACK_OF(X509_POLICY_DATA) *data;
+    /* If InhibitAnyPolicy present this is its value or -1 if absent. */
+    long any_skip;
+    /*
+     * If policyConstraints and requireExplicitPolicy present this is its
+     * value or -1 if absent.
+     */
+    long explicit_skip;
+    /*
+     * If policyConstraints and policyMapping present this is its value or -1
+     * if absent.
+     */
+    long map_skip;
+};
 
-/*#define POLICY_CACHE_FLAG_CRITICAL		POLICY_DATA_FLAG_CRITICAL*/
+/*
+ * #define POLICY_CACHE_FLAG_CRITICAL POLICY_DATA_FLAG_CRITICAL
+ */
 
 /* This structure represents the relationship between nodes */
 
-struct X509_POLICY_NODE_st
-	{
-	/* node data this refers to */
-	const X509_POLICY_DATA *data;
-	/* Parent node */
-	X509_POLICY_NODE *parent;
-	/* Number of child nodes */
-	int nchild;
-	};
+struct X509_POLICY_NODE_st {
+    /* node data this refers to */
+    const X509_POLICY_DATA *data;
+    /* Parent node */
+    X509_POLICY_NODE *parent;
+    /* Number of child nodes */
+    int nchild;
+};
 
-struct X509_POLICY_LEVEL_st
-	{
-	/* Cert for this level */
-	X509 *cert;
-	/* nodes at this level */
-	STACK_OF(X509_POLICY_NODE) *nodes;
-	/* anyPolicy node */
-	X509_POLICY_NODE *anyPolicy;
-	/* Extra data */
-	/*STACK_OF(X509_POLICY_DATA) *extra_data;*/
-	unsigned int flags;
-	};
+struct X509_POLICY_LEVEL_st {
+    /* Cert for this level */
+    X509 *cert;
+    /* nodes at this level */
+    STACK_OF(X509_POLICY_NODE) *nodes;
+    /* anyPolicy node */
+    X509_POLICY_NODE *anyPolicy;
+    /* Extra data */
+    /*
+     * STACK_OF(X509_POLICY_DATA) *extra_data;
+     */
+    unsigned int flags;
+};
 
-struct X509_POLICY_TREE_st
-	{
-	/* This is the tree 'level' data */
-	X509_POLICY_LEVEL *levels;
-	int nlevel;
-	/* Extra policy data when additional nodes (not from the certificate)
-	 * are required.
-	 */
-	STACK_OF(X509_POLICY_DATA) *extra_data;
-	/* This is the authority constained policy set */
-	STACK_OF(X509_POLICY_NODE) *auth_policies;
-	STACK_OF(X509_POLICY_NODE) *user_policies;
-	unsigned int flags;
-	};
+struct X509_POLICY_TREE_st {
+    /* This is the tree 'level' data */
+    X509_POLICY_LEVEL *levels;
+    int nlevel;
+    /*
+     * Extra policy data when additional nodes (not from the certificate) are
+     * required.
+     */
+    STACK_OF(X509_POLICY_DATA) *extra_data;
+    /* This is the authority constained policy set */
+    STACK_OF(X509_POLICY_NODE) *auth_policies;
+    STACK_OF(X509_POLICY_NODE) *user_policies;
+    unsigned int flags;
+};
 
 /* Set if anyPolicy present in user policies */
-#define POLICY_FLAG_ANY_POLICY		0x2
+#define POLICY_FLAG_ANY_POLICY          0x2
 
 /* Useful macros */
 
-#define node_data_critical(data) (data->flags & POLICY_DATA_FLAG_CRITICAL)
-#define node_critical(node) node_data_critical(node->data)
+#define node_data_critical(data) ((data)->flags & POLICY_DATA_FLAG_CRITICAL)
+#define node_critical(node) node_data_critical((node)->data)
 
 /* Internal functions */
 
 X509_POLICY_DATA *policy_data_new(POLICYINFO *policy, const ASN1_OBJECT *id,
-								int crit);
+                                  int crit);
 void policy_data_free(X509_POLICY_DATA *data);
 
 X509_POLICY_DATA *policy_cache_find_data(const X509_POLICY_CACHE *cache,
-							const ASN1_OBJECT *id);
+                                         const ASN1_OBJECT *id);
 int policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps);
 
-
 STACK_OF(X509_POLICY_NODE) *policy_node_cmp_new(void);
 
 void policy_cache_init(void);
@@ -195,18 +200,18 @@
 void policy_cache_free(X509_POLICY_CACHE *cache);
 
 X509_POLICY_NODE *level_find_node(const X509_POLICY_LEVEL *level,
-					const X509_POLICY_NODE *parent,	
-					const ASN1_OBJECT *id);
+                                  const X509_POLICY_NODE *parent,
+                                  const ASN1_OBJECT *id);
 
 X509_POLICY_NODE *tree_find_sk(STACK_OF(X509_POLICY_NODE) *sk,
-						const ASN1_OBJECT *id);
+                               const ASN1_OBJECT *id);
 
 X509_POLICY_NODE *level_add_node(X509_POLICY_LEVEL *level,
-			const X509_POLICY_DATA *data,
-			X509_POLICY_NODE *parent,
-			X509_POLICY_TREE *tree);
+                                 const X509_POLICY_DATA *data,
+                                 X509_POLICY_NODE *parent,
+                                 X509_POLICY_TREE *tree);
 void policy_node_free(X509_POLICY_NODE *node);
 int policy_node_match(const X509_POLICY_LEVEL *lvl,
-		      const X509_POLICY_NODE *node, const ASN1_OBJECT *oid);
+                      const X509_POLICY_NODE *node, const ASN1_OBJECT *oid);
 
 const X509_POLICY_CACHE *policy_cache_set(X509 *x);
diff --git a/src/crypto/x509v3/pcy_lib.c b/src/crypto/x509v3/pcy_lib.c
index 16be2f0..764f38f 100644
--- a/src/crypto/x509v3/pcy_lib.c
+++ b/src/crypto/x509v3/pcy_lib.c
@@ -1,6 +1,7 @@
 /* pcy_lib.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 2004.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 2004.
  */
 /* ====================================================================
  * Copyright (c) 2004 The OpenSSL Project.  All rights reserved.
@@ -10,7 +11,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -54,112 +55,110 @@
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com). */
 
-
 #include <openssl/x509.h>
 #include <openssl/x509v3.h>
 
 #include "pcy_int.h"
 
-
 /* accessor functions */
 
 /* X509_POLICY_TREE stuff */
 
 int X509_policy_tree_level_count(const X509_POLICY_TREE *tree)
-	{
-	if (!tree)
-		return 0;
-	return tree->nlevel;
-	}
+{
+    if (!tree)
+        return 0;
+    return tree->nlevel;
+}
 
-X509_POLICY_LEVEL *
-	X509_policy_tree_get0_level(const X509_POLICY_TREE *tree, int i)
-	{
-	if (!tree || (i < 0) || (i >= tree->nlevel))
-		return NULL;
-	return tree->levels + i;
-	}
+X509_POLICY_LEVEL *X509_policy_tree_get0_level(const X509_POLICY_TREE *tree,
+                                               int i)
+{
+    if (!tree || (i < 0) || (i >= tree->nlevel))
+        return NULL;
+    return tree->levels + i;
+}
 
-STACK_OF(X509_POLICY_NODE) *
-		X509_policy_tree_get0_policies(const X509_POLICY_TREE *tree)
-	{
-	if (!tree)
-		return NULL;
-	return tree->auth_policies;
-	}
+STACK_OF(X509_POLICY_NODE) *X509_policy_tree_get0_policies(const
+                                                           X509_POLICY_TREE
+                                                           *tree)
+{
+    if (!tree)
+        return NULL;
+    return tree->auth_policies;
+}
 
-STACK_OF(X509_POLICY_NODE) *
-	X509_policy_tree_get0_user_policies(const X509_POLICY_TREE *tree)
-	{
-	if (!tree)
-		return NULL;
-	if (tree->flags & POLICY_FLAG_ANY_POLICY)
-		return tree->auth_policies;
-	else
-		return tree->user_policies;
-	}
+STACK_OF(X509_POLICY_NODE) *X509_policy_tree_get0_user_policies(const
+                                                                X509_POLICY_TREE
+                                                                *tree)
+{
+    if (!tree)
+        return NULL;
+    if (tree->flags & POLICY_FLAG_ANY_POLICY)
+        return tree->auth_policies;
+    else
+        return tree->user_policies;
+}
 
 /* X509_POLICY_LEVEL stuff */
 
 int X509_policy_level_node_count(X509_POLICY_LEVEL *level)
-	{
-	int n;
-	if (!level)
-		return 0;
-	if (level->anyPolicy)
-		n = 1;
-	else
-		n = 0;
-	if (level->nodes)
-		n += sk_X509_POLICY_NODE_num(level->nodes);
-	return n;
-	}
+{
+    int n;
+    if (!level)
+        return 0;
+    if (level->anyPolicy)
+        n = 1;
+    else
+        n = 0;
+    if (level->nodes)
+        n += sk_X509_POLICY_NODE_num(level->nodes);
+    return n;
+}
 
 X509_POLICY_NODE *X509_policy_level_get0_node(X509_POLICY_LEVEL *level, int i)
-	{
-	if (!level)
-		return NULL;
-	if (level->anyPolicy)
-		{
-		if (i == 0)
-			return level->anyPolicy;
-		i--;
-		}
-	return sk_X509_POLICY_NODE_value(level->nodes, i);
-	}
+{
+    if (!level)
+        return NULL;
+    if (level->anyPolicy) {
+        if (i == 0)
+            return level->anyPolicy;
+        i--;
+    }
+    return sk_X509_POLICY_NODE_value(level->nodes, i);
+}
 
 /* X509_POLICY_NODE stuff */
 
 const ASN1_OBJECT *X509_policy_node_get0_policy(const X509_POLICY_NODE *node)
-	{
-	if (!node)
-		return NULL;
-	return node->data->valid_policy;
-	}
+{
+    if (!node)
+        return NULL;
+    return node->data->valid_policy;
+}
 
 #if 0
 int X509_policy_node_get_critical(const X509_POLICY_NODE *node)
-	{
-	if (node_critical(node))
-		return 1;
-	return 0;
-	}
+{
+    if (node_critical(node))
+        return 1;
+    return 0;
+}
 #endif
 
-STACK_OF(POLICYQUALINFO) *
-		X509_policy_node_get0_qualifiers(const X509_POLICY_NODE *node)
-	{
-	if (!node)
-		return NULL;
-	return node->data->qualifier_set;
-	}
+STACK_OF(POLICYQUALINFO) *X509_policy_node_get0_qualifiers(const
+                                                           X509_POLICY_NODE
+                                                           *node)
+{
+    if (!node)
+        return NULL;
+    return node->data->qualifier_set;
+}
 
-const X509_POLICY_NODE *
-		X509_policy_node_get0_parent(const X509_POLICY_NODE *node)
-	{
-	if (!node)
-		return NULL;
-	return node->parent;
-	}
-
-
+const X509_POLICY_NODE *X509_policy_node_get0_parent(const X509_POLICY_NODE
+                                                     *node)
+{
+    if (!node)
+        return NULL;
+    return node->parent;
+}
diff --git a/src/crypto/x509v3/pcy_map.c b/src/crypto/x509v3/pcy_map.c
index 2b8307b..7263c69 100644
--- a/src/crypto/x509v3/pcy_map.c
+++ b/src/crypto/x509v3/pcy_map.c
@@ -1,6 +1,7 @@
 /* pcy_map.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 2004.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 2004.
  */
 /* ====================================================================
  * Copyright (c) 2004 The OpenSSL Project.  All rights reserved.
@@ -10,7 +11,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -62,72 +63,68 @@
 
 #include "pcy_int.h"
 
-
-/* Set policy mapping entries in cache.
- * Note: this modifies the passed POLICY_MAPPINGS structure
+/*
+ * Set policy mapping entries in cache. Note: this modifies the passed
+ * POLICY_MAPPINGS structure
  */
 
 int policy_cache_set_mapping(X509 *x, POLICY_MAPPINGS *maps)
-	{
-	POLICY_MAPPING *map;
-	X509_POLICY_DATA *data;
-	X509_POLICY_CACHE *cache = x->policy_cache;
-	size_t i;
-	int ret = 0;
-	if (sk_POLICY_MAPPING_num(maps) == 0)
-		{
-		ret = -1;
-		goto bad_mapping;
-		}
-	for (i = 0; i < sk_POLICY_MAPPING_num(maps); i++)
-		{
-		map = sk_POLICY_MAPPING_value(maps, i);
-		/* Reject if map to or from anyPolicy */
-		if ((OBJ_obj2nid(map->subjectDomainPolicy) == NID_any_policy)
-		   || (OBJ_obj2nid(map->issuerDomainPolicy) == NID_any_policy))
-			{
-			ret = -1;
-			goto bad_mapping;
-			}
+{
+    POLICY_MAPPING *map;
+    X509_POLICY_DATA *data;
+    X509_POLICY_CACHE *cache = x->policy_cache;
+    size_t i;
+    int ret = 0;
+    if (sk_POLICY_MAPPING_num(maps) == 0) {
+        ret = -1;
+        goto bad_mapping;
+    }
+    for (i = 0; i < sk_POLICY_MAPPING_num(maps); i++) {
+        map = sk_POLICY_MAPPING_value(maps, i);
+        /* Reject if map to or from anyPolicy */
+        if ((OBJ_obj2nid(map->subjectDomainPolicy) == NID_any_policy)
+            || (OBJ_obj2nid(map->issuerDomainPolicy) == NID_any_policy)) {
+            ret = -1;
+            goto bad_mapping;
+        }
 
-		/* Attempt to find matching policy data */
-		data = policy_cache_find_data(cache, map->issuerDomainPolicy);
-		/* If we don't have anyPolicy can't map */
-		if (!data && !cache->anyPolicy)
-			continue;
+        /* Attempt to find matching policy data */
+        data = policy_cache_find_data(cache, map->issuerDomainPolicy);
+        /* If we don't have anyPolicy can't map */
+        if (!data && !cache->anyPolicy)
+            continue;
 
-		/* Create a NODE from anyPolicy */
-		if (!data)
-			{
-			data = policy_data_new(NULL, map->issuerDomainPolicy,
-					cache->anyPolicy->flags
-						& POLICY_DATA_FLAG_CRITICAL);
-			if (!data)
-				goto bad_mapping;
-			data->qualifier_set = cache->anyPolicy->qualifier_set;
-			/*map->issuerDomainPolicy = NULL;*/
-			data->flags |= POLICY_DATA_FLAG_MAPPED_ANY;
-			data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
-			if (!sk_X509_POLICY_DATA_push(cache->data, data))
-				{
-				policy_data_free(data);
-				goto bad_mapping;
-				}
-			}
-		else
-			data->flags |= POLICY_DATA_FLAG_MAPPED;
-		if (!sk_ASN1_OBJECT_push(data->expected_policy_set, 
-						map->subjectDomainPolicy))
-			goto bad_mapping;
-		map->subjectDomainPolicy = NULL;
+        /* Create a NODE from anyPolicy */
+        if (!data) {
+            data = policy_data_new(NULL, map->issuerDomainPolicy,
+                                   cache->anyPolicy->flags
+                                   & POLICY_DATA_FLAG_CRITICAL);
+            if (!data)
+                goto bad_mapping;
+            data->qualifier_set = cache->anyPolicy->qualifier_set;
+            /*
+             * map->issuerDomainPolicy = NULL;
+             */
+            data->flags |= POLICY_DATA_FLAG_MAPPED_ANY;
+            data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
+            if (!sk_X509_POLICY_DATA_push(cache->data, data)) {
+                policy_data_free(data);
+                goto bad_mapping;
+            }
+        } else
+            data->flags |= POLICY_DATA_FLAG_MAPPED;
+        if (!sk_ASN1_OBJECT_push(data->expected_policy_set,
+                                 map->subjectDomainPolicy))
+            goto bad_mapping;
+        map->subjectDomainPolicy = NULL;
 
-		}
+    }
 
-	ret = 1;
-	bad_mapping:
-	if (ret == -1)
-		x->ex_flags |= EXFLAG_INVALID_POLICY;
-	sk_POLICY_MAPPING_pop_free(maps, POLICY_MAPPING_free);
-	return ret;
+    ret = 1;
+ bad_mapping:
+    if (ret == -1)
+        x->ex_flags |= EXFLAG_INVALID_POLICY;
+    sk_POLICY_MAPPING_pop_free(maps, POLICY_MAPPING_free);
+    return ret;
 
-	}
+}
diff --git a/src/crypto/x509v3/pcy_node.c b/src/crypto/x509v3/pcy_node.c
index 55cc203..cf4e79d 100644
--- a/src/crypto/x509v3/pcy_node.c
+++ b/src/crypto/x509v3/pcy_node.c
@@ -1,6 +1,7 @@
 /* pcy_node.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 2004.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 2004.
  */
 /* ====================================================================
  * Copyright (c) 2004 The OpenSSL Project.  All rights reserved.
@@ -10,7 +11,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -62,136 +63,126 @@
 
 #include "pcy_int.h"
 
-
-static int node_cmp(const X509_POLICY_NODE **a,
-			const X509_POLICY_NODE **b)
-	{
-	return OBJ_cmp((*a)->data->valid_policy, (*b)->data->valid_policy);
-	}
+static int node_cmp(const X509_POLICY_NODE **a, const X509_POLICY_NODE **b)
+{
+    return OBJ_cmp((*a)->data->valid_policy, (*b)->data->valid_policy);
+}
 
 STACK_OF(X509_POLICY_NODE) *policy_node_cmp_new(void)
-	{
-	return sk_X509_POLICY_NODE_new(node_cmp);
-	}
+{
+    return sk_X509_POLICY_NODE_new(node_cmp);
+}
 
 X509_POLICY_NODE *tree_find_sk(STACK_OF(X509_POLICY_NODE) *nodes,
-					const ASN1_OBJECT *id)
-	{
-	X509_POLICY_DATA n;
-	X509_POLICY_NODE l;
-	size_t idx;
+                               const ASN1_OBJECT *id)
+{
+    X509_POLICY_DATA n;
+    X509_POLICY_NODE l;
+    size_t idx;
 
-	n.valid_policy = (ASN1_OBJECT *)id;
-	l.data = &n;
+    n.valid_policy = (ASN1_OBJECT *)id;
+    l.data = &n;
 
-	if (!sk_X509_POLICY_NODE_find(nodes, &idx, &l))
-		return NULL;
+    if (!sk_X509_POLICY_NODE_find(nodes, &idx, &l))
+        return NULL;
 
-	return sk_X509_POLICY_NODE_value(nodes, idx);
+    return sk_X509_POLICY_NODE_value(nodes, idx);
 
-	}
+}
 
 X509_POLICY_NODE *level_find_node(const X509_POLICY_LEVEL *level,
-					const X509_POLICY_NODE *parent,	
-					const ASN1_OBJECT *id)
-	{
-	X509_POLICY_NODE *node;
-	size_t i;
-	for (i = 0; i < sk_X509_POLICY_NODE_num(level->nodes); i++)
-		{
-		node = sk_X509_POLICY_NODE_value(level->nodes, i);
-		if (node->parent == parent)
-			{
-			if (!OBJ_cmp(node->data->valid_policy, id))
-				return node;
-			}
-		}
-	return NULL;
-	}
+                                  const X509_POLICY_NODE *parent,
+                                  const ASN1_OBJECT *id)
+{
+    X509_POLICY_NODE *node;
+    size_t i;
+    for (i = 0; i < sk_X509_POLICY_NODE_num(level->nodes); i++) {
+        node = sk_X509_POLICY_NODE_value(level->nodes, i);
+        if (node->parent == parent) {
+            if (!OBJ_cmp(node->data->valid_policy, id))
+                return node;
+        }
+    }
+    return NULL;
+}
 
 X509_POLICY_NODE *level_add_node(X509_POLICY_LEVEL *level,
-			const X509_POLICY_DATA *data,
-			X509_POLICY_NODE *parent,
-			X509_POLICY_TREE *tree)
-	{
-	X509_POLICY_NODE *node;
-	node = OPENSSL_malloc(sizeof(X509_POLICY_NODE));
-	if (!node)
-		return NULL;
-	node->data = data;
-	node->parent = parent;
-	node->nchild = 0;
-	if (level)
-		{
-		if (OBJ_obj2nid(data->valid_policy) == NID_any_policy)
-			{
-			if (level->anyPolicy)
-				goto node_error;
-			level->anyPolicy = node;
-			}
-		else
-			{
+                                 const X509_POLICY_DATA *data,
+                                 X509_POLICY_NODE *parent,
+                                 X509_POLICY_TREE *tree)
+{
+    X509_POLICY_NODE *node;
+    node = OPENSSL_malloc(sizeof(X509_POLICY_NODE));
+    if (!node)
+        return NULL;
+    node->data = data;
+    node->parent = parent;
+    node->nchild = 0;
+    if (level) {
+        if (OBJ_obj2nid(data->valid_policy) == NID_any_policy) {
+            if (level->anyPolicy)
+                goto node_error;
+            level->anyPolicy = node;
+        } else {
 
-			if (!level->nodes)
-				level->nodes = policy_node_cmp_new();
-			if (!level->nodes)
-				goto node_error;
-			if (!sk_X509_POLICY_NODE_push(level->nodes, node))
-				goto node_error;
-			}
-		}
+            if (!level->nodes)
+                level->nodes = policy_node_cmp_new();
+            if (!level->nodes)
+                goto node_error;
+            if (!sk_X509_POLICY_NODE_push(level->nodes, node))
+                goto node_error;
+        }
+    }
 
-	if (tree)
-		{
-		if (!tree->extra_data)
-			 tree->extra_data = sk_X509_POLICY_DATA_new_null();
-		if (!tree->extra_data)
-			goto node_error;
-		if (!sk_X509_POLICY_DATA_push(tree->extra_data, data))
-			goto node_error;
-		}
+    if (tree) {
+        if (!tree->extra_data)
+            tree->extra_data = sk_X509_POLICY_DATA_new_null();
+        if (!tree->extra_data)
+            goto node_error;
+        if (!sk_X509_POLICY_DATA_push(tree->extra_data, data))
+            goto node_error;
+    }
 
-	if (parent)
-		parent->nchild++;
+    if (parent)
+        parent->nchild++;
 
-	return node;
+    return node;
 
-	node_error:
-	policy_node_free(node);
-	return 0;
+ node_error:
+    policy_node_free(node);
+    return 0;
 
-	}
+}
 
 void policy_node_free(X509_POLICY_NODE *node)
-	{
-	OPENSSL_free(node);
-	}
+{
+    OPENSSL_free(node);
+}
 
-/* See if a policy node matches a policy OID. If mapping enabled look through
+/*
+ * See if a policy node matches a policy OID. If mapping enabled look through
  * expected policy set otherwise just valid policy.
  */
 
 int policy_node_match(const X509_POLICY_LEVEL *lvl,
-		      const X509_POLICY_NODE *node, const ASN1_OBJECT *oid)
-	{
-	size_t i;
-	ASN1_OBJECT *policy_oid;
-	const X509_POLICY_DATA *x = node->data;
+                      const X509_POLICY_NODE *node, const ASN1_OBJECT *oid)
+{
+    size_t i;
+    ASN1_OBJECT *policy_oid;
+    const X509_POLICY_DATA *x = node->data;
 
-	if (	    (lvl->flags & X509_V_FLAG_INHIBIT_MAP)
-		|| !(x->flags & POLICY_DATA_FLAG_MAP_MASK))
-		{
-		if (!OBJ_cmp(x->valid_policy, oid))
-			return 1;
-		return 0;
-		}
+    if ((lvl->flags & X509_V_FLAG_INHIBIT_MAP)
+        || !(x->flags & POLICY_DATA_FLAG_MAP_MASK)) {
+        if (!OBJ_cmp(x->valid_policy, oid))
+            return 1;
+        return 0;
+    }
 
-	for (i = 0; i < sk_ASN1_OBJECT_num(x->expected_policy_set); i++)
-		{
-		policy_oid = sk_ASN1_OBJECT_value(x->expected_policy_set, i);
-		if (!OBJ_cmp(policy_oid, oid))
-			return 1;
-		}
-	return 0;
+    for (i = 0; i < sk_ASN1_OBJECT_num(x->expected_policy_set); i++) {
+        policy_oid = sk_ASN1_OBJECT_value(x->expected_policy_set, i);
+        if (!OBJ_cmp(policy_oid, oid))
+            return 1;
+    }
+    return 0;
 
-	}
+}
diff --git a/src/crypto/x509v3/pcy_tree.c b/src/crypto/x509v3/pcy_tree.c
index 8e9ef25..a588107 100644
--- a/src/crypto/x509v3/pcy_tree.c
+++ b/src/crypto/x509v3/pcy_tree.c
@@ -1,5 +1,6 @@
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 2004.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 2004.
  */
 /* ====================================================================
  * Copyright (c) 2004 The OpenSSL Project.  All rights reserved.
@@ -9,7 +10,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -65,812 +66,765 @@
 #include <openssl/x509v3.h>
 
 #include "pcy_int.h"
+#include "../internal.h"
 
-
-/* Enable this to print out the complete policy tree at various point during
+/*
+ * Enable this to print out the complete policy tree at various point during
  * evaluation.
  */
 
-/*#define OPENSSL_POLICY_DEBUG*/
+/*
+ * #define OPENSSL_POLICY_DEBUG
+ */
 
 #ifdef OPENSSL_POLICY_DEBUG
 
 static void expected_print(BIO *err, X509_POLICY_LEVEL *lev,
-				X509_POLICY_NODE *node, int indent)
-	{
-	if (	    (lev->flags & X509_V_FLAG_INHIBIT_MAP)
-		|| !(node->data->flags & POLICY_DATA_FLAG_MAP_MASK))
-		BIO_puts(err, "  Not Mapped\n");
-	else
-		{
-		int i;
-		STACK_OF(ASN1_OBJECT) *pset = node->data->expected_policy_set;
-		ASN1_OBJECT *oid;
-		BIO_puts(err, "  Expected: ");
-		for (i = 0; i < sk_ASN1_OBJECT_num(pset); i++)
-			{
-			oid = sk_ASN1_OBJECT_value(pset, i);
-			if (i)
-				BIO_puts(err, ", ");
-			i2a_ASN1_OBJECT(err, oid);
-			}
-		BIO_puts(err, "\n");
-		}
-	}
+                           X509_POLICY_NODE *node, int indent)
+{
+    if ((lev->flags & X509_V_FLAG_INHIBIT_MAP)
+        || !(node->data->flags & POLICY_DATA_FLAG_MAP_MASK))
+        BIO_puts(err, "  Not Mapped\n");
+    else {
+        int i;
+        STACK_OF(ASN1_OBJECT) *pset = node->data->expected_policy_set;
+        ASN1_OBJECT *oid;
+        BIO_puts(err, "  Expected: ");
+        for (i = 0; i < sk_ASN1_OBJECT_num(pset); i++) {
+            oid = sk_ASN1_OBJECT_value(pset, i);
+            if (i)
+                BIO_puts(err, ", ");
+            i2a_ASN1_OBJECT(err, oid);
+        }
+        BIO_puts(err, "\n");
+    }
+}
 
 static void tree_print(char *str, X509_POLICY_TREE *tree,
-			X509_POLICY_LEVEL *curr)
-	{
-	X509_POLICY_LEVEL *plev;
-	X509_POLICY_NODE *node;
-	int i;
-	BIO *err;
-	err = BIO_new_fp(stderr, BIO_NOCLOSE);
-	if (!curr)
-		curr = tree->levels + tree->nlevel;
-	else
-		curr++;
-	BIO_printf(err, "Level print after %s\n", str);
-	BIO_printf(err, "Printing Up to Level %ld\n", curr - tree->levels);
-	for (plev = tree->levels; plev != curr; plev++)
-		{
-		BIO_printf(err, "Level %ld, flags = %x\n",
-				plev - tree->levels, plev->flags);
-		for (i = 0; i < sk_X509_POLICY_NODE_num(plev->nodes); i++)
-			{
-			node = sk_X509_POLICY_NODE_value(plev->nodes, i);
-			X509_POLICY_NODE_print(err, node, 2);
-			expected_print(err, plev, node, 2);
-			BIO_printf(err, "  Flags: %x\n", node->data->flags);
-			}
-		if (plev->anyPolicy)
-			X509_POLICY_NODE_print(err, plev->anyPolicy, 2);
-		}
+                       X509_POLICY_LEVEL *curr)
+{
+    X509_POLICY_LEVEL *plev;
+    X509_POLICY_NODE *node;
+    int i;
+    BIO *err;
+    err = BIO_new_fp(stderr, BIO_NOCLOSE);
+    if (!curr)
+        curr = tree->levels + tree->nlevel;
+    else
+        curr++;
+    BIO_printf(err, "Level print after %s\n", str);
+    BIO_printf(err, "Printing Up to Level %ld\n", curr - tree->levels);
+    for (plev = tree->levels; plev != curr; plev++) {
+        BIO_printf(err, "Level %ld, flags = %x\n",
+                   plev - tree->levels, plev->flags);
+        for (i = 0; i < sk_X509_POLICY_NODE_num(plev->nodes); i++) {
+            node = sk_X509_POLICY_NODE_value(plev->nodes, i);
+            X509_POLICY_NODE_print(err, node, 2);
+            expected_print(err, plev, node, 2);
+            BIO_printf(err, "  Flags: %x\n", node->data->flags);
+        }
+        if (plev->anyPolicy)
+            X509_POLICY_NODE_print(err, plev->anyPolicy, 2);
+    }
 
-	BIO_free(err);
+    BIO_free(err);
 
-	}
+}
 #else
 
-#define tree_print(a,b,c) /* */
+# define tree_print(a,b,c)      /* */
 
 #endif
 
-/* Initialize policy tree. Return values:
- *  0 Some internal error occured.
- * -1 Inconsistent or invalid extensions in certificates.
- *  1 Tree initialized OK.
- *  2 Policy tree is empty.
- *  5 Tree OK and requireExplicitPolicy true.
- *  6 Tree empty and requireExplicitPolicy true.
+/*
+ * Initialize policy tree. Return values: 0 Some internal error occured. -1
+ * Inconsistent or invalid extensions in certificates.  1 Tree initialized
+ * OK.  2 Policy tree is empty.  5 Tree OK and requireExplicitPolicy true.  6
+ * Tree empty and requireExplicitPolicy true.
  */
 
 static int tree_init(X509_POLICY_TREE **ptree, STACK_OF(X509) *certs,
-			unsigned int flags)
-	{
-	X509_POLICY_TREE *tree;
-	X509_POLICY_LEVEL *level;
-	const X509_POLICY_CACHE *cache;
-	X509_POLICY_DATA *data = NULL;
-	X509 *x;
-	int ret = 1;
-	int i, n;
-	int explicit_policy;
-	int any_skip;
-	int map_skip;
-	*ptree = NULL;
-	n = sk_X509_num(certs);
+                     unsigned int flags)
+{
+    X509_POLICY_TREE *tree;
+    X509_POLICY_LEVEL *level;
+    const X509_POLICY_CACHE *cache;
+    X509_POLICY_DATA *data = NULL;
+    X509 *x;
+    int ret = 1;
+    int i, n;
+    int explicit_policy;
+    int any_skip;
+    int map_skip;
+    *ptree = NULL;
+    n = sk_X509_num(certs);
 
 #if 0
-	/* Disable policy mapping for now... */
-	flags |= X509_V_FLAG_INHIBIT_MAP;
+    /* Disable policy mapping for now... */
+    flags |= X509_V_FLAG_INHIBIT_MAP;
 #endif
 
-	if (flags & X509_V_FLAG_EXPLICIT_POLICY)
-		explicit_policy = 0;
-	else
-		explicit_policy = n + 1;
+    if (flags & X509_V_FLAG_EXPLICIT_POLICY)
+        explicit_policy = 0;
+    else
+        explicit_policy = n + 1;
 
-	if (flags & X509_V_FLAG_INHIBIT_ANY)
-		any_skip = 0;
-	else
-		any_skip = n + 1;
+    if (flags & X509_V_FLAG_INHIBIT_ANY)
+        any_skip = 0;
+    else
+        any_skip = n + 1;
 
-	if (flags & X509_V_FLAG_INHIBIT_MAP)
-		map_skip = 0;
-	else
-		map_skip = n + 1;
+    if (flags & X509_V_FLAG_INHIBIT_MAP)
+        map_skip = 0;
+    else
+        map_skip = n + 1;
 
-	/* Can't do anything with just a trust anchor */
-	if (n == 1)
-		return 1;
-	/* First setup policy cache in all certificates apart from the
-	 * trust anchor. Note any bad cache results on the way. Also can
-	 * calculate explicit_policy value at this point.
-	 */
-	for (i = n - 2; i >= 0; i--)
-		{
-		x = sk_X509_value(certs, i);
-		X509_check_purpose(x, -1, -1);
-		cache = policy_cache_set(x);
-		/* If cache NULL something bad happened: return immediately */
-		if (cache == NULL)
-			return 0;
-		/* If inconsistent extensions keep a note of it but continue */
-		if (x->ex_flags & EXFLAG_INVALID_POLICY)
-			ret = -1;
-		/* Otherwise if we have no data (hence no CertificatePolicies)
-		 * and haven't already set an inconsistent code note it.
-		 */
-		else if ((ret == 1) && !cache->data)
-			ret = 2;
-		if (explicit_policy > 0)
-			{
-			if (!(x->ex_flags & EXFLAG_SI))
-				explicit_policy--;
-			if ((cache->explicit_skip != -1)
-				&& (cache->explicit_skip < explicit_policy))
-				explicit_policy = cache->explicit_skip;
-			}
-		}
+    /* Can't do anything with just a trust anchor */
+    if (n == 1)
+        return 1;
+    /*
+     * First setup policy cache in all certificates apart from the trust
+     * anchor. Note any bad cache results on the way. Also can calculate
+     * explicit_policy value at this point.
+     */
+    for (i = n - 2; i >= 0; i--) {
+        x = sk_X509_value(certs, i);
+        X509_check_purpose(x, -1, -1);
+        cache = policy_cache_set(x);
+        /* If cache NULL something bad happened: return immediately */
+        if (cache == NULL)
+            return 0;
+        /*
+         * If inconsistent extensions keep a note of it but continue
+         */
+        if (x->ex_flags & EXFLAG_INVALID_POLICY)
+            ret = -1;
+        /*
+         * Otherwise if we have no data (hence no CertificatePolicies) and
+         * haven't already set an inconsistent code note it.
+         */
+        else if ((ret == 1) && !cache->data)
+            ret = 2;
+        if (explicit_policy > 0) {
+            if (!(x->ex_flags & EXFLAG_SI))
+                explicit_policy--;
+            if ((cache->explicit_skip != -1)
+                && (cache->explicit_skip < explicit_policy))
+                explicit_policy = cache->explicit_skip;
+        }
+    }
 
-	if (ret != 1)
-		{
-		if (ret == 2 && !explicit_policy)
-			return 6;
-		return ret;
-		}
+    if (ret != 1) {
+        if (ret == 2 && !explicit_policy)
+            return 6;
+        return ret;
+    }
 
+    /* If we get this far initialize the tree */
 
-	/* If we get this far initialize the tree */
+    tree = OPENSSL_malloc(sizeof(X509_POLICY_TREE));
 
-	tree = OPENSSL_malloc(sizeof(X509_POLICY_TREE));
+    if (!tree)
+        return 0;
 
-	if (!tree)
-		return 0;
+    tree->flags = 0;
+    tree->levels = OPENSSL_malloc(sizeof(X509_POLICY_LEVEL) * n);
+    tree->nlevel = 0;
+    tree->extra_data = NULL;
+    tree->auth_policies = NULL;
+    tree->user_policies = NULL;
 
-	tree->flags = 0;
-	tree->levels = OPENSSL_malloc(sizeof(X509_POLICY_LEVEL) * n);
-	tree->nlevel = 0;
-	tree->extra_data = NULL;
-	tree->auth_policies = NULL;
-	tree->user_policies = NULL;
+    if (!tree->levels) {
+        OPENSSL_free(tree);
+        return 0;
+    }
 
-	if (!tree->levels)
-		{
-		OPENSSL_free(tree);
-		return 0;
-		}
+    OPENSSL_memset(tree->levels, 0, n * sizeof(X509_POLICY_LEVEL));
 
-	memset(tree->levels, 0, n * sizeof(X509_POLICY_LEVEL));
+    tree->nlevel = n;
 
-	tree->nlevel = n;
+    level = tree->levels;
 
-	level = tree->levels;
+    /* Root data: initialize to anyPolicy */
 
-	/* Root data: initialize to anyPolicy */
+    data = policy_data_new(NULL, OBJ_nid2obj(NID_any_policy), 0);
 
-	data = policy_data_new(NULL, OBJ_nid2obj(NID_any_policy), 0);
+    if (!data || !level_add_node(level, data, NULL, tree))
+        goto bad_tree;
 
-	if (!data || !level_add_node(level, data, NULL, tree))
-		goto bad_tree;
+    for (i = n - 2; i >= 0; i--) {
+        level++;
+        x = sk_X509_value(certs, i);
+        cache = policy_cache_set(x);
+        X509_up_ref(x);
+        level->cert = x;
 
-	for (i = n - 2; i >= 0; i--)
-		{
-		level++;
-		x = sk_X509_value(certs, i);
-		cache = policy_cache_set(x);
-		level->cert = X509_up_ref(x);
+        if (!cache->anyPolicy)
+            level->flags |= X509_V_FLAG_INHIBIT_ANY;
 
-		if (!cache->anyPolicy)
-				level->flags |= X509_V_FLAG_INHIBIT_ANY;
+        /* Determine inhibit any and inhibit map flags */
+        if (any_skip == 0) {
+            /*
+             * Any matching allowed if certificate is self issued and not the
+             * last in the chain.
+             */
+            if (!(x->ex_flags & EXFLAG_SI) || (i == 0))
+                level->flags |= X509_V_FLAG_INHIBIT_ANY;
+        } else {
+            if (!(x->ex_flags & EXFLAG_SI))
+                any_skip--;
+            if ((cache->any_skip >= 0)
+                && (cache->any_skip < any_skip))
+                any_skip = cache->any_skip;
+        }
 
-		/* Determine inhibit any and inhibit map flags */
-		if (any_skip == 0)
-			{
-			/* Any matching allowed if certificate is self
-			 * issued and not the last in the chain.
-			 */
-			if (!(x->ex_flags & EXFLAG_SI) || (i == 0))
-				level->flags |= X509_V_FLAG_INHIBIT_ANY;
-			}
-		else
-			{
-			if (!(x->ex_flags & EXFLAG_SI))
-				any_skip--;
-			if ((cache->any_skip >= 0)
-				&& (cache->any_skip < any_skip))
-				any_skip = cache->any_skip;
-			}
+        if (map_skip == 0)
+            level->flags |= X509_V_FLAG_INHIBIT_MAP;
+        else {
+            if (!(x->ex_flags & EXFLAG_SI))
+                map_skip--;
+            if ((cache->map_skip >= 0)
+                && (cache->map_skip < map_skip))
+                map_skip = cache->map_skip;
+        }
 
-		if (map_skip == 0)
-			level->flags |= X509_V_FLAG_INHIBIT_MAP;
-		else
-			{
-			if (!(x->ex_flags & EXFLAG_SI))
-				map_skip--;
-			if ((cache->map_skip >= 0)
-				&& (cache->map_skip < map_skip))
-				map_skip = cache->map_skip;
-			}
+    }
 
-		}
+    *ptree = tree;
 
-	*ptree = tree;
+    if (explicit_policy)
+        return 1;
+    else
+        return 5;
 
-	if (explicit_policy)
-		return 1;
-	else
-		return 5;
+ bad_tree:
 
-	bad_tree:
+    X509_policy_tree_free(tree);
 
-	X509_policy_tree_free(tree);
+    return 0;
 
-	return 0;
-
-	}
+}
 
 static int tree_link_matching_nodes(X509_POLICY_LEVEL *curr,
-				const X509_POLICY_DATA *data)
-	{
-	X509_POLICY_LEVEL *last = curr - 1;
-	X509_POLICY_NODE *node;
-	int matched = 0;
-	size_t i;
-	/* Iterate through all in nodes linking matches */
-	for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++)
-		{
-		node = sk_X509_POLICY_NODE_value(last->nodes, i);
-		if (policy_node_match(last, node, data->valid_policy))
-			{
-			if (!level_add_node(curr, data, node, NULL))
-				return 0;
-			matched = 1;
-			}
-		}
-	if (!matched && last->anyPolicy)
-		{
-		if (!level_add_node(curr, data, last->anyPolicy, NULL))
-			return 0;
-		}
-	return 1;
-	}
+                                    const X509_POLICY_DATA *data)
+{
+    X509_POLICY_LEVEL *last = curr - 1;
+    X509_POLICY_NODE *node;
+    int matched = 0;
+    size_t i;
+    /* Iterate through all in nodes linking matches */
+    for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) {
+        node = sk_X509_POLICY_NODE_value(last->nodes, i);
+        if (policy_node_match(last, node, data->valid_policy)) {
+            if (!level_add_node(curr, data, node, NULL))
+                return 0;
+            matched = 1;
+        }
+    }
+    if (!matched && last->anyPolicy) {
+        if (!level_add_node(curr, data, last->anyPolicy, NULL))
+            return 0;
+    }
+    return 1;
+}
 
-/* This corresponds to RFC3280 6.1.3(d)(1):
- * link any data from CertificatePolicies onto matching parent
- * or anyPolicy if no match.
+/*
+ * This corresponds to RFC3280 6.1.3(d)(1): link any data from
+ * CertificatePolicies onto matching parent or anyPolicy if no match.
  */
 
 static int tree_link_nodes(X509_POLICY_LEVEL *curr,
-				const X509_POLICY_CACHE *cache)
-	{
-	size_t i;
-	X509_POLICY_DATA *data;
+                           const X509_POLICY_CACHE *cache)
+{
+    size_t i;
+    X509_POLICY_DATA *data;
 
-	for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++)
-		{
-		data = sk_X509_POLICY_DATA_value(cache->data, i);
-		/* If a node is mapped any it doesn't have a corresponding
-		 * CertificatePolicies entry. 
-		 * However such an identical node would be created
-		 * if anyPolicy matching is enabled because there would be
-		 * no match with the parent valid_policy_set. So we create
-		 * link because then it will have the mapping flags
-		 * right and we can prune it later.
-		 */
+    for (i = 0; i < sk_X509_POLICY_DATA_num(cache->data); i++) {
+        data = sk_X509_POLICY_DATA_value(cache->data, i);
+        /*
+         * If a node is mapped any it doesn't have a corresponding
+         * CertificatePolicies entry. However such an identical node would
+         * be created if anyPolicy matching is enabled because there would be
+         * no match with the parent valid_policy_set. So we create link
+         * because then it will have the mapping flags right and we can prune
+         * it later.
+         */
 #if 0
-		if ((data->flags & POLICY_DATA_FLAG_MAPPED_ANY)
-			&& !(curr->flags & X509_V_FLAG_INHIBIT_ANY))
-			continue;
+        if ((data->flags & POLICY_DATA_FLAG_MAPPED_ANY)
+            && !(curr->flags & X509_V_FLAG_INHIBIT_ANY))
+            continue;
 #endif
-		/* Look for matching nodes in previous level */
-		if (!tree_link_matching_nodes(curr, data))
-				return 0;
-		}
-	return 1;
-	}
+        /* Look for matching nodes in previous level */
+        if (!tree_link_matching_nodes(curr, data))
+            return 0;
+    }
+    return 1;
+}
 
-/* This corresponds to RFC3280 6.1.3(d)(2):
- * Create new data for any unmatched policies in the parent and link
- * to anyPolicy.
+/*
+ * This corresponds to RFC3280 6.1.3(d)(2): Create new data for any unmatched
+ * policies in the parent and link to anyPolicy.
  */
 
 static int tree_add_unmatched(X509_POLICY_LEVEL *curr,
-			const X509_POLICY_CACHE *cache,
-			const ASN1_OBJECT *id,
-			X509_POLICY_NODE *node,
-			X509_POLICY_TREE *tree)
-	{
-	X509_POLICY_DATA *data;
-	if (id == NULL)
-		id = node->data->valid_policy;
-	/* Create a new node with qualifiers from anyPolicy and
-	 * id from unmatched node.
-	 */
-	data = policy_data_new(NULL, id, node_critical(node));
+                              const X509_POLICY_CACHE *cache,
+                              const ASN1_OBJECT *id,
+                              X509_POLICY_NODE *node, X509_POLICY_TREE *tree)
+{
+    X509_POLICY_DATA *data;
+    if (id == NULL)
+        id = node->data->valid_policy;
+    /*
+     * Create a new node with qualifiers from anyPolicy and id from unmatched
+     * node.
+     */
+    data = policy_data_new(NULL, id, node_critical(node));
 
-	if (data == NULL)
-		return 0;
-	/* Curr may not have anyPolicy */
-	data->qualifier_set = cache->anyPolicy->qualifier_set;
-	data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
-	if (!level_add_node(curr, data, node, tree))
-		{
-		policy_data_free(data);
-		return 0;
-		}
+    if (data == NULL)
+        return 0;
+    /* Curr may not have anyPolicy */
+    data->qualifier_set = cache->anyPolicy->qualifier_set;
+    data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
+    if (!level_add_node(curr, data, node, tree)) {
+        policy_data_free(data);
+        return 0;
+    }
 
-	return 1;
-	}
+    return 1;
+}
 
 static int tree_link_unmatched(X509_POLICY_LEVEL *curr,
-			const X509_POLICY_CACHE *cache,
-			X509_POLICY_NODE *node,
-			X509_POLICY_TREE *tree)
-	{
-	const X509_POLICY_LEVEL *last = curr - 1;
-	size_t i;
+                               const X509_POLICY_CACHE *cache,
+                               X509_POLICY_NODE *node, X509_POLICY_TREE *tree)
+{
+    const X509_POLICY_LEVEL *last = curr - 1;
+    size_t i;
 
-	if (	    (last->flags & X509_V_FLAG_INHIBIT_MAP)
-		|| !(node->data->flags & POLICY_DATA_FLAG_MAPPED))
-		{
-		/* If no policy mapping: matched if one child present */
-		if (node->nchild)
-			return 1;
-		if (!tree_add_unmatched(curr, cache, NULL, node, tree))
-			return 0;
-		/* Add it */
-		}
-	else
-		{
-		/* If mapping: matched if one child per expected policy set */
-		STACK_OF(ASN1_OBJECT) *expset = node->data->expected_policy_set;
-		if ((size_t) node->nchild == sk_ASN1_OBJECT_num(expset))
-			return 1;
-		/* Locate unmatched nodes */
-		for (i = 0; i < sk_ASN1_OBJECT_num(expset); i++)
-			{
-			ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(expset, i);
-			if (level_find_node(curr, node, oid))
-				continue;
-			if (!tree_add_unmatched(curr, cache, oid, node, tree))
-				return 0;
-			}
+    if ((last->flags & X509_V_FLAG_INHIBIT_MAP)
+        || !(node->data->flags & POLICY_DATA_FLAG_MAPPED)) {
+        /* If no policy mapping: matched if one child present */
+        if (node->nchild)
+            return 1;
+        if (!tree_add_unmatched(curr, cache, NULL, node, tree))
+            return 0;
+        /* Add it */
+    } else {
+        /* If mapping: matched if one child per expected policy set */
+        STACK_OF(ASN1_OBJECT) *expset = node->data->expected_policy_set;
+        if ((size_t)node->nchild == sk_ASN1_OBJECT_num(expset))
+            return 1;
+        /* Locate unmatched nodes */
+        for (i = 0; i < sk_ASN1_OBJECT_num(expset); i++) {
+            ASN1_OBJECT *oid = sk_ASN1_OBJECT_value(expset, i);
+            if (level_find_node(curr, node, oid))
+                continue;
+            if (!tree_add_unmatched(curr, cache, oid, node, tree))
+                return 0;
+        }
 
-		}
+    }
 
-	return 1;
+    return 1;
 
-	}
+}
 
 static int tree_link_any(X509_POLICY_LEVEL *curr,
-			const X509_POLICY_CACHE *cache,
-			X509_POLICY_TREE *tree)
-	{
-	size_t i;
-	/*X509_POLICY_DATA *data;*/
-	X509_POLICY_NODE *node;
-	X509_POLICY_LEVEL *last = curr - 1;
+                         const X509_POLICY_CACHE *cache,
+                         X509_POLICY_TREE *tree)
+{
+    size_t i;
+    /*
+     * X509_POLICY_DATA *data;
+     */
+    X509_POLICY_NODE *node;
+    X509_POLICY_LEVEL *last = curr - 1;
 
-	for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++)
-		{
-		node = sk_X509_POLICY_NODE_value(last->nodes, i);
+    for (i = 0; i < sk_X509_POLICY_NODE_num(last->nodes); i++) {
+        node = sk_X509_POLICY_NODE_value(last->nodes, i);
 
-		if (!tree_link_unmatched(curr, cache, node, tree))
-			return 0;
+        if (!tree_link_unmatched(curr, cache, node, tree))
+            return 0;
 
 #if 0
 
-		/* Skip any node with any children: we only want unmathced
-		 * nodes.
-		 *
-		 * Note: need something better for policy mapping
-		 * because each node may have multiple children 
-		 */
-		if (node->nchild)
-			continue;
+        /*
+         * Skip any node with any children: we only want unmathced nodes.
+         * Note: need something better for policy mapping because each node
+         * may have multiple children
+         */
+        if (node->nchild)
+            continue;
 
-		/* Create a new node with qualifiers from anyPolicy and
-		 * id from unmatched node.
-		 */
-		data = policy_data_new(NULL, node->data->valid_policy, 
-						node_critical(node));
+        /*
+         * Create a new node with qualifiers from anyPolicy and id from
+         * unmatched node.
+         */
+        data = policy_data_new(NULL, node->data->valid_policy,
+                               node_critical(node));
 
-		if (data == NULL)
-			return 0;
-		/* Curr may not have anyPolicy */
-		data->qualifier_set = cache->anyPolicy->qualifier_set;
-		data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
-		if (!level_add_node(curr, data, node, tree))
-			{
-			policy_data_free(data);
-			return 0;
-			}
-
+        if (data == NULL)
+            return 0;
+        /* Curr may not have anyPolicy */
+        data->qualifier_set = cache->anyPolicy->qualifier_set;
+        data->flags |= POLICY_DATA_FLAG_SHARED_QUALIFIERS;
+        if (!level_add_node(curr, data, node, tree)) {
+            policy_data_free(data);
+            return 0;
+        }
 #endif
 
-		}
-	/* Finally add link to anyPolicy */
-	if (last->anyPolicy)
-		{
-		if (!level_add_node(curr, cache->anyPolicy,
-						last->anyPolicy, NULL))
-			return 0;
-		}
-	return 1;
-	}
+    }
+    /* Finally add link to anyPolicy */
+    if (last->anyPolicy) {
+        if (!level_add_node(curr, cache->anyPolicy, last->anyPolicy, NULL))
+            return 0;
+    }
+    return 1;
+}
 
-/* Prune the tree: delete any child mapped child data on the current level
+/*
+ * Prune the tree: delete any child mapped child data on the current level
  * then proceed up the tree deleting any data with no children. If we ever
  * have no data on a level we can halt because the tree will be empty.
  */
 
 static int tree_prune(X509_POLICY_TREE *tree, X509_POLICY_LEVEL *curr)
-	{
-	STACK_OF(X509_POLICY_NODE) *nodes;
-	X509_POLICY_NODE *node;
-	int i;
-	nodes = curr->nodes;
-	if (curr->flags & X509_V_FLAG_INHIBIT_MAP)
-		{
-		for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--)
-			{
-			node = sk_X509_POLICY_NODE_value(nodes, i);
-			/* Delete any mapped data: see RFC3280 XXXX */
-			if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK)
-				{
-				node->parent->nchild--;
-				OPENSSL_free(node);
-				(void)sk_X509_POLICY_NODE_delete(nodes,i);
-				}
-			}
-		}
+{
+    STACK_OF(X509_POLICY_NODE) *nodes;
+    X509_POLICY_NODE *node;
+    int i;
+    nodes = curr->nodes;
+    if (curr->flags & X509_V_FLAG_INHIBIT_MAP) {
+        for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) {
+            node = sk_X509_POLICY_NODE_value(nodes, i);
+            /* Delete any mapped data: see RFC3280 XXXX */
+            if (node->data->flags & POLICY_DATA_FLAG_MAP_MASK) {
+                node->parent->nchild--;
+                OPENSSL_free(node);
+                (void)sk_X509_POLICY_NODE_delete(nodes, i);
+            }
+        }
+    }
 
-	for(;;)	{
-		--curr;
-		nodes = curr->nodes;
-		for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--)
-			{
-			node = sk_X509_POLICY_NODE_value(nodes, i);
-			if (node->nchild == 0)
-				{
-				node->parent->nchild--;
-				OPENSSL_free(node);
-				(void)sk_X509_POLICY_NODE_delete(nodes, i);
-				}
-			}
-		if (curr->anyPolicy && !curr->anyPolicy->nchild)
-			{
-			if (curr->anyPolicy->parent)
-				curr->anyPolicy->parent->nchild--;
-			OPENSSL_free(curr->anyPolicy);
-			curr->anyPolicy = NULL;
-			}
-		if (curr == tree->levels)
-			{
-			/* If we zapped anyPolicy at top then tree is empty */
-			if (!curr->anyPolicy)
-					return 2;
-			return 1;
-			}
-		}
+    for (;;) {
+        --curr;
+        nodes = curr->nodes;
+        for (i = sk_X509_POLICY_NODE_num(nodes) - 1; i >= 0; i--) {
+            node = sk_X509_POLICY_NODE_value(nodes, i);
+            if (node->nchild == 0) {
+                node->parent->nchild--;
+                OPENSSL_free(node);
+                (void)sk_X509_POLICY_NODE_delete(nodes, i);
+            }
+        }
+        if (curr->anyPolicy && !curr->anyPolicy->nchild) {
+            if (curr->anyPolicy->parent)
+                curr->anyPolicy->parent->nchild--;
+            OPENSSL_free(curr->anyPolicy);
+            curr->anyPolicy = NULL;
+        }
+        if (curr == tree->levels) {
+            /* If we zapped anyPolicy at top then tree is empty */
+            if (!curr->anyPolicy)
+                return 2;
+            return 1;
+        }
+    }
 
-	}
+}
 
 static int tree_add_auth_node(STACK_OF(X509_POLICY_NODE) **pnodes,
-						 X509_POLICY_NODE *pcy)
-	{
-	if (!*pnodes)
-		{
-		*pnodes = policy_node_cmp_new();
-		if (!*pnodes)
-			return 0;
-		}
-	else if (sk_X509_POLICY_NODE_find(*pnodes, NULL, pcy))
-		return 1;
+                              X509_POLICY_NODE *pcy)
+{
+    if (!*pnodes) {
+        *pnodes = policy_node_cmp_new();
+        if (!*pnodes)
+            return 0;
+    } else if (sk_X509_POLICY_NODE_find(*pnodes, NULL, pcy))
+        return 1;
 
-	if (!sk_X509_POLICY_NODE_push(*pnodes, pcy))
-		return 0;
+    if (!sk_X509_POLICY_NODE_push(*pnodes, pcy))
+        return 0;
 
-	return 1;
+    return 1;
 
-	}
+}
 
-/* Calculate the authority set based on policy tree.
- * The 'pnodes' parameter is used as a store for the set of policy nodes
- * used to calculate the user set. If the authority set is not anyPolicy
- * then pnodes will just point to the authority set. If however the authority
- * set is anyPolicy then the set of valid policies (other than anyPolicy)
- * is store in pnodes. The return value of '2' is used in this case to indicate
- * that pnodes should be freed.
+/*
+ * Calculate the authority set based on policy tree. The 'pnodes' parameter
+ * is used as a store for the set of policy nodes used to calculate the user
+ * set. If the authority set is not anyPolicy then pnodes will just point to
+ * the authority set. If however the authority set is anyPolicy then the set
+ * of valid policies (other than anyPolicy) is store in pnodes. The return
+ * value of '2' is used in this case to indicate that pnodes should be freed.
  */
 
 static int tree_calculate_authority_set(X509_POLICY_TREE *tree,
-					STACK_OF(X509_POLICY_NODE) **pnodes)
-	{
-	X509_POLICY_LEVEL *curr;
-	X509_POLICY_NODE *node, *anyptr;
-	STACK_OF(X509_POLICY_NODE) **addnodes;
-	int i;
-	size_t j;
-	curr = tree->levels + tree->nlevel - 1;
+                                        STACK_OF(X509_POLICY_NODE) **pnodes)
+{
+    X509_POLICY_LEVEL *curr;
+    X509_POLICY_NODE *node, *anyptr;
+    STACK_OF(X509_POLICY_NODE) **addnodes;
+    int i;
+    size_t j;
+    curr = tree->levels + tree->nlevel - 1;
 
-	/* If last level contains anyPolicy set is anyPolicy */
-	if (curr->anyPolicy)
-		{
-		if (!tree_add_auth_node(&tree->auth_policies, curr->anyPolicy))
-			return 0;
-		addnodes = pnodes;
-		}
-	else
-		/* Add policies to authority set */
-		addnodes = &tree->auth_policies;
+    /* If last level contains anyPolicy set is anyPolicy */
+    if (curr->anyPolicy) {
+        if (!tree_add_auth_node(&tree->auth_policies, curr->anyPolicy))
+            return 0;
+        addnodes = pnodes;
+    } else
+        /* Add policies to authority set */
+        addnodes = &tree->auth_policies;
 
-	curr = tree->levels;
-	for (i = 1; i < tree->nlevel; i++)
-		{
-		/* If no anyPolicy node on this this level it can't
-		 * appear on lower levels so end search.
-		 */
-		if (!(anyptr = curr->anyPolicy))
-			break;
-		curr++;
-		for (j = 0; j < sk_X509_POLICY_NODE_num(curr->nodes); j++)
-			{
-			node = sk_X509_POLICY_NODE_value(curr->nodes, j);
-			if ((node->parent == anyptr)
-				&& !tree_add_auth_node(addnodes, node))
-					return 0;
-			}
-		}
+    curr = tree->levels;
+    for (i = 1; i < tree->nlevel; i++) {
+        /*
+         * If no anyPolicy node on this this level it can't appear on lower
+         * levels so end search.
+         */
+        if (!(anyptr = curr->anyPolicy))
+            break;
+        curr++;
+        for (j = 0; j < sk_X509_POLICY_NODE_num(curr->nodes); j++) {
+            node = sk_X509_POLICY_NODE_value(curr->nodes, j);
+            if ((node->parent == anyptr)
+                && !tree_add_auth_node(addnodes, node))
+                return 0;
+        }
+    }
 
-	if (addnodes == pnodes)
-		return 2;
+    if (addnodes == pnodes)
+        return 2;
 
-	*pnodes = tree->auth_policies;
+    *pnodes = tree->auth_policies;
 
-	return 1;
-	}
+    return 1;
+}
 
 static int tree_calculate_user_set(X509_POLICY_TREE *tree,
-				STACK_OF(ASN1_OBJECT) *policy_oids,
-				STACK_OF(X509_POLICY_NODE) *auth_nodes)
-	{
-	size_t i;
-	X509_POLICY_NODE *node;
-	ASN1_OBJECT *oid;
+                                   STACK_OF(ASN1_OBJECT) *policy_oids,
+                                   STACK_OF(X509_POLICY_NODE) *auth_nodes)
+{
+    size_t i;
+    X509_POLICY_NODE *node;
+    ASN1_OBJECT *oid;
 
-	X509_POLICY_NODE *anyPolicy;
-	X509_POLICY_DATA *extra;
+    X509_POLICY_NODE *anyPolicy;
+    X509_POLICY_DATA *extra;
 
-	/* Check if anyPolicy present in authority constrained policy set:
-	 * this will happen if it is a leaf node.
-	 */
+    /*
+     * Check if anyPolicy present in authority constrained policy set: this
+     * will happen if it is a leaf node.
+     */
 
-	if (sk_ASN1_OBJECT_num(policy_oids) <= 0)
-		return 1;
+    if (sk_ASN1_OBJECT_num(policy_oids) <= 0)
+        return 1;
 
-	anyPolicy = tree->levels[tree->nlevel - 1].anyPolicy;
+    anyPolicy = tree->levels[tree->nlevel - 1].anyPolicy;
 
-	for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++)
-		{
-		oid = sk_ASN1_OBJECT_value(policy_oids, i);
-		if (OBJ_obj2nid(oid) == NID_any_policy)
-			{
-			tree->flags |= POLICY_FLAG_ANY_POLICY;
-			return 1;
-			}
-		}
+    for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) {
+        oid = sk_ASN1_OBJECT_value(policy_oids, i);
+        if (OBJ_obj2nid(oid) == NID_any_policy) {
+            tree->flags |= POLICY_FLAG_ANY_POLICY;
+            return 1;
+        }
+    }
 
-	for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++)
-		{
-		oid = sk_ASN1_OBJECT_value(policy_oids, i);
-		node = tree_find_sk(auth_nodes, oid);
-		if (!node)
-			{
-			if (!anyPolicy)
-				continue;
-			/* Create a new node with policy ID from user set
-			 * and qualifiers from anyPolicy.
-			 */
-			extra = policy_data_new(NULL, oid,
-						node_critical(anyPolicy));
-			if (!extra)
-				return 0;
-			extra->qualifier_set = anyPolicy->data->qualifier_set;
-			extra->flags = POLICY_DATA_FLAG_SHARED_QUALIFIERS
-						| POLICY_DATA_FLAG_EXTRA_NODE;
-			node = level_add_node(NULL, extra, anyPolicy->parent,
-						tree);
-			}
-		if (!tree->user_policies)
-			{
-			tree->user_policies = sk_X509_POLICY_NODE_new_null();
-			if (!tree->user_policies)
-				return 1;
-			}
-		if (!sk_X509_POLICY_NODE_push(tree->user_policies, node))
-			return 0;
-		}
-	return 1;
+    for (i = 0; i < sk_ASN1_OBJECT_num(policy_oids); i++) {
+        oid = sk_ASN1_OBJECT_value(policy_oids, i);
+        node = tree_find_sk(auth_nodes, oid);
+        if (!node) {
+            if (!anyPolicy)
+                continue;
+            /*
+             * Create a new node with policy ID from user set and qualifiers
+             * from anyPolicy.
+             */
+            extra = policy_data_new(NULL, oid, node_critical(anyPolicy));
+            if (!extra)
+                return 0;
+            extra->qualifier_set = anyPolicy->data->qualifier_set;
+            extra->flags = POLICY_DATA_FLAG_SHARED_QUALIFIERS
+                | POLICY_DATA_FLAG_EXTRA_NODE;
+            node = level_add_node(NULL, extra, anyPolicy->parent, tree);
+        }
+        if (!tree->user_policies) {
+            tree->user_policies = sk_X509_POLICY_NODE_new_null();
+            if (!tree->user_policies)
+                return 1;
+        }
+        if (!sk_X509_POLICY_NODE_push(tree->user_policies, node))
+            return 0;
+    }
+    return 1;
 
-	}
+}
 
 static int tree_evaluate(X509_POLICY_TREE *tree)
-	{
-	int ret, i;
-	X509_POLICY_LEVEL *curr = tree->levels + 1;
-	const X509_POLICY_CACHE *cache;
+{
+    int ret, i;
+    X509_POLICY_LEVEL *curr = tree->levels + 1;
+    const X509_POLICY_CACHE *cache;
 
-	for(i = 1; i < tree->nlevel; i++, curr++)
-		{
-		cache = policy_cache_set(curr->cert);
-		if (!tree_link_nodes(curr, cache))
-			return 0;
+    for (i = 1; i < tree->nlevel; i++, curr++) {
+        cache = policy_cache_set(curr->cert);
+        if (!tree_link_nodes(curr, cache))
+            return 0;
 
-		if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY)
-			&& !tree_link_any(curr, cache, tree))
-			return 0;
-	tree_print("before tree_prune()", tree, curr);
-		ret = tree_prune(tree, curr);
-		if (ret != 1)
-			return ret;
-		}
+        if (!(curr->flags & X509_V_FLAG_INHIBIT_ANY)
+            && !tree_link_any(curr, cache, tree))
+            return 0;
+        tree_print("before tree_prune()", tree, curr);
+        ret = tree_prune(tree, curr);
+        if (ret != 1)
+            return ret;
+    }
 
-	return 1;
+    return 1;
 
-	}
+}
 
 static void exnode_free(X509_POLICY_NODE *node)
-	{
-	if (node->data && (node->data->flags & POLICY_DATA_FLAG_EXTRA_NODE))
-		OPENSSL_free(node);
-	}
-
+{
+    if (node->data && (node->data->flags & POLICY_DATA_FLAG_EXTRA_NODE))
+        OPENSSL_free(node);
+}
 
 void X509_policy_tree_free(X509_POLICY_TREE *tree)
-	{
-	X509_POLICY_LEVEL *curr;
-	int i;
+{
+    X509_POLICY_LEVEL *curr;
+    int i;
 
-	if (!tree)
-		return;
+    if (!tree)
+        return;
 
-	sk_X509_POLICY_NODE_free(tree->auth_policies);
-	sk_X509_POLICY_NODE_pop_free(tree->user_policies, exnode_free);
+    sk_X509_POLICY_NODE_free(tree->auth_policies);
+    sk_X509_POLICY_NODE_pop_free(tree->user_policies, exnode_free);
 
-	for(i = 0, curr = tree->levels; i < tree->nlevel; i++, curr++)
-		{
-		if (curr->cert)
-			X509_free(curr->cert);
-		if (curr->nodes)
-			sk_X509_POLICY_NODE_pop_free(curr->nodes,
-						policy_node_free);
-		if (curr->anyPolicy)
-			policy_node_free(curr->anyPolicy);
-		}
+    for (i = 0, curr = tree->levels; i < tree->nlevel; i++, curr++) {
+        if (curr->cert)
+            X509_free(curr->cert);
+        if (curr->nodes)
+            sk_X509_POLICY_NODE_pop_free(curr->nodes, policy_node_free);
+        if (curr->anyPolicy)
+            policy_node_free(curr->anyPolicy);
+    }
 
-	if (tree->extra_data)
-		sk_X509_POLICY_DATA_pop_free(tree->extra_data,
-						policy_data_free);
+    if (tree->extra_data)
+        sk_X509_POLICY_DATA_pop_free(tree->extra_data, policy_data_free);
 
-	OPENSSL_free(tree->levels);
-	OPENSSL_free(tree);
+    OPENSSL_free(tree->levels);
+    OPENSSL_free(tree);
 
-	}
+}
 
-/* Application policy checking function.
- * Return codes:
- *  0 	Internal Error.
- *  1   Successful.
- * -1   One or more certificates contain invalid or inconsistent extensions
- * -2	User constrained policy set empty and requireExplicit true.
+/*
+ * Application policy checking function. Return codes: 0 Internal Error.  1
+ * Successful. -1 One or more certificates contain invalid or inconsistent
+ * extensions -2 User constrained policy set empty and requireExplicit true.
  */
 
 int X509_policy_check(X509_POLICY_TREE **ptree, int *pexplicit_policy,
-			STACK_OF(X509) *certs,
-			STACK_OF(ASN1_OBJECT) *policy_oids,
-			unsigned int flags)
-	{
-	int ret;
-	X509_POLICY_TREE *tree = NULL;
-	STACK_OF(X509_POLICY_NODE) *nodes, *auth_nodes = NULL;
-	*ptree = NULL;
+                      STACK_OF(X509) *certs,
+                      STACK_OF(ASN1_OBJECT) *policy_oids, unsigned int flags)
+{
+    int ret;
+    X509_POLICY_TREE *tree = NULL;
+    STACK_OF(X509_POLICY_NODE) *nodes, *auth_nodes = NULL;
+    *ptree = NULL;
 
-	*pexplicit_policy = 0;
-	ret = tree_init(&tree, certs, flags);
+    *pexplicit_policy = 0;
+    ret = tree_init(&tree, certs, flags);
 
-	switch (ret)
-		{
+    switch (ret) {
 
-		/* Tree empty requireExplicit False: OK */
-		case 2:
-		return 1;
+        /* Tree empty requireExplicit False: OK */
+    case 2:
+        return 1;
 
-		/* Some internal error */
-		case -1:
-		return -1;
+        /* Some internal error */
+    case -1:
+        return -1;
 
-		/* Some internal error */
-		case 0:
-		return 0;
+        /* Some internal error */
+    case 0:
+        return 0;
 
-		/* Tree empty requireExplicit True: Error */
+        /* Tree empty requireExplicit True: Error */
 
-		case 6:
-		*pexplicit_policy = 1;
-		return -2;
+    case 6:
+        *pexplicit_policy = 1;
+        return -2;
 
-		/* Tree OK requireExplicit True: OK and continue */
-		case 5:
-		*pexplicit_policy = 1;
-		break;
+        /* Tree OK requireExplicit True: OK and continue */
+    case 5:
+        *pexplicit_policy = 1;
+        break;
 
-		/* Tree OK: continue */
+        /* Tree OK: continue */
 
-		case 1:
-		if (!tree)
-			/*
-			 * tree_init() returns success and a null tree
-			 * if it's just looking at a trust anchor.
-			 * I'm not sure that returning success here is
-			 * correct, but I'm sure that reporting this
-			 * as an internal error which our caller
-			 * interprets as a malloc failure is wrong.
-			 */
-			return 1;
-		break;
-		}
+    case 1:
+        if (!tree)
+            /*
+             * tree_init() returns success and a null tree
+             * if it's just looking at a trust anchor.
+             * I'm not sure that returning success here is
+             * correct, but I'm sure that reporting this
+             * as an internal error which our caller
+             * interprets as a malloc failure is wrong.
+             */
+            return 1;
+        break;
+    }
 
-	if (!tree) goto error;
-	ret = tree_evaluate(tree);
+    if (!tree)
+        goto error;
+    ret = tree_evaluate(tree);
 
-	tree_print("tree_evaluate()", tree, NULL);
+    tree_print("tree_evaluate()", tree, NULL);
 
-	if (ret <= 0)
-		goto error;
+    if (ret <= 0)
+        goto error;
 
-	/* Return value 2 means tree empty */
-	if (ret == 2)
-		{
-		X509_policy_tree_free(tree);
-		if (*pexplicit_policy)
-			return -2;
-		else
-			return 1;
-		}
+    /* Return value 2 means tree empty */
+    if (ret == 2) {
+        X509_policy_tree_free(tree);
+        if (*pexplicit_policy)
+            return -2;
+        else
+            return 1;
+    }
 
-	/* Tree is not empty: continue */
+    /* Tree is not empty: continue */
 
-	ret = tree_calculate_authority_set(tree, &auth_nodes);
+    ret = tree_calculate_authority_set(tree, &auth_nodes);
 
-	if (!ret)
-		goto error;
+    if (!ret)
+        goto error;
 
-	if (!tree_calculate_user_set(tree, policy_oids, auth_nodes))
-		goto error;
-	
-	if (ret == 2)
-		sk_X509_POLICY_NODE_free(auth_nodes);
+    if (!tree_calculate_user_set(tree, policy_oids, auth_nodes))
+        goto error;
 
-	if (tree)
-		*ptree = tree;
+    if (ret == 2)
+        sk_X509_POLICY_NODE_free(auth_nodes);
 
-	if (*pexplicit_policy)
-		{
-		nodes = X509_policy_tree_get0_user_policies(tree);
-		if (sk_X509_POLICY_NODE_num(nodes) <= 0)
-			return -2;
-		}
+    if (tree)
+        *ptree = tree;
 
-	return 1;
+    if (*pexplicit_policy) {
+        nodes = X509_policy_tree_get0_user_policies(tree);
+        if (sk_X509_POLICY_NODE_num(nodes) <= 0)
+            return -2;
+    }
 
-	error:
+    return 1;
 
-	X509_policy_tree_free(tree);
+ error:
 
-	return 0;
+    X509_policy_tree_free(tree);
 
-	}
+    return 0;
 
+}
diff --git a/src/crypto/x509v3/tab_test.c b/src/crypto/x509v3/tab_test.c
index c0e0cb6..1900547 100644
--- a/src/crypto/x509v3/tab_test.c
+++ b/src/crypto/x509v3/tab_test.c
@@ -1,6 +1,7 @@
 /* tabtest.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
  */
 /* ====================================================================
  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
@@ -10,7 +11,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -56,49 +57,52 @@
  *
  */
 
-/* Simple program to check the ext_dat.h is correct and print out
- * problems if it is not.
+/*
+ * Simple program to check the ext_dat.h is correct and print out problems if
+ * it is not.
  */
 
 #include <stdio.h>
 
 #include <openssl/base.h>
 #include <openssl/crypto.h>
+#include <openssl/obj.h>
 #include <openssl/x509v3.h>
 
 #if !defined(BORINGSSL_SHARED_LIBRARY)
-#include "ext_dat.h"
+# include "ext_dat.h"
 #endif
 
 int main(void)
 {
 #if !defined(BORINGSSL_SHARED_LIBRARY)
-	unsigned i;
-	int prev = -1, bad = 0;
-	const X509V3_EXT_METHOD *const *tmp;
-        CRYPTO_library_init();
-	i = sizeof(standard_exts) / sizeof(X509V3_EXT_METHOD *);
-	if(i != STANDARD_EXTENSION_COUNT)
-		fprintf(stderr, "Extension number invalid expecting %d\n", i);
-	tmp = standard_exts;
-	for(i = 0; i < STANDARD_EXTENSION_COUNT; i++, tmp++) {
-		if((*tmp)->ext_nid < prev) bad = 1;
-		prev = (*tmp)->ext_nid;
-		
-	}
-	if(bad) {
-		tmp = standard_exts;
-		fprintf(stderr, "Extensions out of order!\n");
-		for(i = 0; i < STANDARD_EXTENSION_COUNT; i++, tmp++)
-			printf("%d : %s\n", (*tmp)->ext_nid, OBJ_nid2sn((*tmp)->ext_nid));
-		return 1;
-	} else {
-		printf("PASS\n");
-		return 0;
-	}
+    unsigned i;
+    int prev = -1, bad = 0;
+    const X509V3_EXT_METHOD *const *tmp;
+    CRYPTO_library_init();
+    i = sizeof(standard_exts) / sizeof(X509V3_EXT_METHOD *);
+    if (i != STANDARD_EXTENSION_COUNT)
+        fprintf(stderr, "Extension number invalid expecting %d\n", i);
+    tmp = standard_exts;
+    for (i = 0; i < STANDARD_EXTENSION_COUNT; i++, tmp++) {
+        if ((*tmp)->ext_nid < prev)
+            bad = 1;
+        prev = (*tmp)->ext_nid;
+
+    }
+    if (bad) {
+        tmp = standard_exts;
+        fprintf(stderr, "Extensions out of order!\n");
+        for (i = 0; i < STANDARD_EXTENSION_COUNT; i++, tmp++)
+            printf("%d : %s\n", (*tmp)->ext_nid, OBJ_nid2sn((*tmp)->ext_nid));
+        return 1;
+    } else {
+        printf("PASS\n");
+        return 0;
+    }
 #else
-	/* TODO(davidben): Fix this test in the shared library build. */
-	printf("PASS\n");
-	return 0;
+    /* TODO(davidben): Fix this test in the shared library build. */
+    printf("PASS\n");
+    return 0;
 #endif
 }
diff --git a/src/crypto/x509v3/v3_akey.c b/src/crypto/x509v3/v3_akey.c
index 9578a57..4503e61 100644
--- a/src/crypto/x509v3/v3_akey.c
+++ b/src/crypto/x509v3/v3_akey.c
@@ -1,6 +1,7 @@
 /* v3_akey.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
  */
 /* ====================================================================
  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
@@ -10,7 +11,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -65,148 +66,139 @@
 #include <openssl/obj.h>
 #include <openssl/x509v3.h>
 
-
 static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
-			AUTHORITY_KEYID *akeyid, STACK_OF(CONF_VALUE) *extlist);
+                                                 AUTHORITY_KEYID *akeyid,
+                                                 STACK_OF(CONF_VALUE)
+                                                 *extlist);
 static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
-			X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *values);
+                                            X509V3_CTX *ctx,
+                                            STACK_OF(CONF_VALUE) *values);
 
-const X509V3_EXT_METHOD v3_akey_id =
-	{
-	NID_authority_key_identifier,
-	X509V3_EXT_MULTILINE, ASN1_ITEM_ref(AUTHORITY_KEYID),
-	0,0,0,0,
-	0,0,
-	(X509V3_EXT_I2V)i2v_AUTHORITY_KEYID,
-	(X509V3_EXT_V2I)v2i_AUTHORITY_KEYID,
-	0,0,
-	NULL
-	};
+const X509V3_EXT_METHOD v3_akey_id = {
+    NID_authority_key_identifier,
+    X509V3_EXT_MULTILINE, ASN1_ITEM_ref(AUTHORITY_KEYID),
+    0, 0, 0, 0,
+    0, 0,
+    (X509V3_EXT_I2V) i2v_AUTHORITY_KEYID,
+    (X509V3_EXT_V2I)v2i_AUTHORITY_KEYID,
+    0, 0,
+    NULL
+};
 
 static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
-	     AUTHORITY_KEYID *akeyid, STACK_OF(CONF_VALUE) *extlist)
+                                                 AUTHORITY_KEYID *akeyid,
+                                                 STACK_OF(CONF_VALUE)
+                                                 *extlist)
 {
-	char *tmp;
-	if(akeyid->keyid) {
-		tmp = hex_to_string(akeyid->keyid->data, akeyid->keyid->length);
-		X509V3_add_value("keyid", tmp, &extlist);
-		OPENSSL_free(tmp);
-	}
-	if(akeyid->issuer) 
-		extlist = i2v_GENERAL_NAMES(NULL, akeyid->issuer, extlist);
-	if(akeyid->serial) {
-		tmp = hex_to_string(akeyid->serial->data,
-						 akeyid->serial->length);
-		X509V3_add_value("serial", tmp, &extlist);
-		OPENSSL_free(tmp);
-	}
-	return extlist;
+    char *tmp;
+    if (akeyid->keyid) {
+        tmp = hex_to_string(akeyid->keyid->data, akeyid->keyid->length);
+        X509V3_add_value("keyid", tmp, &extlist);
+        OPENSSL_free(tmp);
+    }
+    if (akeyid->issuer)
+        extlist = i2v_GENERAL_NAMES(NULL, akeyid->issuer, extlist);
+    if (akeyid->serial) {
+        tmp = hex_to_string(akeyid->serial->data, akeyid->serial->length);
+        X509V3_add_value("serial", tmp, &extlist);
+        OPENSSL_free(tmp);
+    }
+    return extlist;
 }
 
-/* Currently two options:
- * keyid: use the issuers subject keyid, the value 'always' means its is
- * an error if the issuer certificate doesn't have a key id.
- * issuer: use the issuers cert issuer and serial number. The default is
- * to only use this if keyid is not present. With the option 'always'
- * this is always included.
+/*
+ * Currently two options: keyid: use the issuers subject keyid, the value
+ * 'always' means its is an error if the issuer certificate doesn't have a
+ * key id. issuer: use the issuers cert issuer and serial number. The default
+ * is to only use this if keyid is not present. With the option 'always' this
+ * is always included.
  */
 
 static AUTHORITY_KEYID *v2i_AUTHORITY_KEYID(X509V3_EXT_METHOD *method,
-	     X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *values)
-	{
-	char keyid=0, issuer=0;
-	size_t i;
-	int j;
-	CONF_VALUE *cnf;
-	ASN1_OCTET_STRING *ikeyid = NULL;
-	X509_NAME *isname = NULL;
-	GENERAL_NAMES * gens = NULL;
-	GENERAL_NAME *gen = NULL;
-	ASN1_INTEGER *serial = NULL;
-	X509_EXTENSION *ext;
-	X509 *cert;
-	AUTHORITY_KEYID *akeyid;
+                                            X509V3_CTX *ctx,
+                                            STACK_OF(CONF_VALUE) *values)
+{
+    char keyid = 0, issuer = 0;
+    size_t i;
+    int j;
+    CONF_VALUE *cnf;
+    ASN1_OCTET_STRING *ikeyid = NULL;
+    X509_NAME *isname = NULL;
+    GENERAL_NAMES *gens = NULL;
+    GENERAL_NAME *gen = NULL;
+    ASN1_INTEGER *serial = NULL;
+    X509_EXTENSION *ext;
+    X509 *cert;
+    AUTHORITY_KEYID *akeyid;
 
-	for(i = 0; i < sk_CONF_VALUE_num(values); i++)
-		{
-		cnf = sk_CONF_VALUE_value(values, i);
-		if(!strcmp(cnf->name, "keyid"))
-			{
-			keyid = 1;
-			if(cnf->value && !strcmp(cnf->value, "always"))
-				keyid = 2;
-			}
-		else if(!strcmp(cnf->name, "issuer"))
-			{
-			issuer = 1;
-			if(cnf->value && !strcmp(cnf->value, "always"))
-				issuer = 2;
-			}
-		else
-			{
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_OPTION);
-			ERR_add_error_data(2, "name=", cnf->name);
-			return NULL;
-			}
-		}
+    for (i = 0; i < sk_CONF_VALUE_num(values); i++) {
+        cnf = sk_CONF_VALUE_value(values, i);
+        if (!strcmp(cnf->name, "keyid")) {
+            keyid = 1;
+            if (cnf->value && !strcmp(cnf->value, "always"))
+                keyid = 2;
+        } else if (!strcmp(cnf->name, "issuer")) {
+            issuer = 1;
+            if (cnf->value && !strcmp(cnf->value, "always"))
+                issuer = 2;
+        } else {
+            OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_OPTION);
+            ERR_add_error_data(2, "name=", cnf->name);
+            return NULL;
+        }
+    }
 
-	if(!ctx || !ctx->issuer_cert)
-		{
-		if(ctx && (ctx->flags==CTX_TEST))
-			return AUTHORITY_KEYID_new();
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_ISSUER_CERTIFICATE);
-		return NULL;
-		}
+    if (!ctx || !ctx->issuer_cert) {
+        if (ctx && (ctx->flags == CTX_TEST))
+            return AUTHORITY_KEYID_new();
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_ISSUER_CERTIFICATE);
+        return NULL;
+    }
 
-	cert = ctx->issuer_cert;
+    cert = ctx->issuer_cert;
 
-	if(keyid)
-		{
-		j = X509_get_ext_by_NID(cert, NID_subject_key_identifier, -1);
-		if((j >= 0)  && (ext = X509_get_ext(cert, j)))
-			ikeyid = X509V3_EXT_d2i(ext);
-		if(keyid==2 && !ikeyid)
-			{
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNABLE_TO_GET_ISSUER_KEYID);
-			return NULL;
-			}
-		}
+    if (keyid) {
+        j = X509_get_ext_by_NID(cert, NID_subject_key_identifier, -1);
+        if ((j >= 0) && (ext = X509_get_ext(cert, j)))
+            ikeyid = X509V3_EXT_d2i(ext);
+        if (keyid == 2 && !ikeyid) {
+            OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNABLE_TO_GET_ISSUER_KEYID);
+            return NULL;
+        }
+    }
 
-	if((issuer && !ikeyid) || (issuer == 2))
-		{
-		isname = X509_NAME_dup(X509_get_issuer_name(cert));
-		serial = M_ASN1_INTEGER_dup(X509_get_serialNumber(cert));
-		if(!isname || !serial)
-			{
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS);
-			goto err;
-			}
-		}
+    if ((issuer && !ikeyid) || (issuer == 2)) {
+        isname = X509_NAME_dup(X509_get_issuer_name(cert));
+        serial = M_ASN1_INTEGER_dup(X509_get_serialNumber(cert));
+        if (!isname || !serial) {
+            OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS);
+            goto err;
+        }
+    }
 
-	if(!(akeyid = AUTHORITY_KEYID_new())) goto err;
+    if (!(akeyid = AUTHORITY_KEYID_new()))
+        goto err;
 
-	if(isname)
-		{
-		if(!(gens = sk_GENERAL_NAME_new_null())
-			|| !(gen = GENERAL_NAME_new())
-			|| !sk_GENERAL_NAME_push(gens, gen))
-			{
-			OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-			goto err;
-			}
-		gen->type = GEN_DIRNAME;
-		gen->d.dirn = isname;
-		}
+    if (isname) {
+        if (!(gens = sk_GENERAL_NAME_new_null())
+            || !(gen = GENERAL_NAME_new())
+            || !sk_GENERAL_NAME_push(gens, gen)) {
+            OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+            goto err;
+        }
+        gen->type = GEN_DIRNAME;
+        gen->d.dirn = isname;
+    }
 
-	akeyid->issuer = gens;
-	akeyid->serial = serial;
-	akeyid->keyid = ikeyid;
+    akeyid->issuer = gens;
+    akeyid->serial = serial;
+    akeyid->keyid = ikeyid;
 
-	return akeyid;
+    return akeyid;
 
  err:
-	X509_NAME_free(isname);
-	M_ASN1_INTEGER_free(serial);
-	M_ASN1_OCTET_STRING_free(ikeyid);
-	return NULL;
-	}
+    X509_NAME_free(isname);
+    M_ASN1_INTEGER_free(serial);
+    M_ASN1_OCTET_STRING_free(ikeyid);
+    return NULL;
+}
diff --git a/src/crypto/x509v3/v3_akeya.c b/src/crypto/x509v3/v3_akeya.c
index 8b72cca..844dee5 100644
--- a/src/crypto/x509v3/v3_akeya.c
+++ b/src/crypto/x509v3/v3_akeya.c
@@ -1,6 +1,7 @@
 /* v3_akey_asn1.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
  */
 /* ====================================================================
  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
@@ -10,7 +11,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -63,9 +64,9 @@
 
 
 ASN1_SEQUENCE(AUTHORITY_KEYID) = {
-	ASN1_IMP_OPT(AUTHORITY_KEYID, keyid, ASN1_OCTET_STRING, 0),
-	ASN1_IMP_SEQUENCE_OF_OPT(AUTHORITY_KEYID, issuer, GENERAL_NAME, 1),
-	ASN1_IMP_OPT(AUTHORITY_KEYID, serial, ASN1_INTEGER, 2)
+        ASN1_IMP_OPT(AUTHORITY_KEYID, keyid, ASN1_OCTET_STRING, 0),
+        ASN1_IMP_SEQUENCE_OF_OPT(AUTHORITY_KEYID, issuer, GENERAL_NAME, 1),
+        ASN1_IMP_OPT(AUTHORITY_KEYID, serial, ASN1_INTEGER, 2)
 } ASN1_SEQUENCE_END(AUTHORITY_KEYID)
 
 IMPLEMENT_ASN1_FUNCTIONS(AUTHORITY_KEYID)
diff --git a/src/crypto/x509v3/v3_alt.c b/src/crypto/x509v3/v3_alt.c
index cfc1348..152bd79 100644
--- a/src/crypto/x509v3/v3_alt.c
+++ b/src/crypto/x509v3/v3_alt.c
@@ -1,5 +1,6 @@
 /* v3_alt.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project.
  */
 /* ====================================================================
@@ -10,7 +11,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -63,560 +64,551 @@
 #include <openssl/obj.h>
 #include <openssl/x509v3.h>
 
-
-static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
-static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
+static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
+                                      X509V3_CTX *ctx,
+                                      STACK_OF(CONF_VALUE) *nval);
+static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
+                                     X509V3_CTX *ctx,
+                                     STACK_OF(CONF_VALUE) *nval);
 static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p);
 static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens);
 static int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx);
 static int do_dirname(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx);
 
 const X509V3_EXT_METHOD v3_alt[] = {
-{ NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
-0,0,0,0,
-0,0,
-(X509V3_EXT_I2V)i2v_GENERAL_NAMES,
-(X509V3_EXT_V2I)v2i_subject_alt,
-NULL, NULL, NULL},
+    {NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
+     0, 0, 0, 0,
+     0, 0,
+     (X509V3_EXT_I2V) i2v_GENERAL_NAMES,
+     (X509V3_EXT_V2I)v2i_subject_alt,
+     NULL, NULL, NULL},
 
-{ NID_issuer_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
-0,0,0,0,
-0,0,
-(X509V3_EXT_I2V)i2v_GENERAL_NAMES,
-(X509V3_EXT_V2I)v2i_issuer_alt,
-NULL, NULL, NULL},
+    {NID_issuer_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
+     0, 0, 0, 0,
+     0, 0,
+     (X509V3_EXT_I2V) i2v_GENERAL_NAMES,
+     (X509V3_EXT_V2I)v2i_issuer_alt,
+     NULL, NULL, NULL},
 
-{ NID_certificate_issuer, 0, ASN1_ITEM_ref(GENERAL_NAMES),
-0,0,0,0,
-0,0,
-(X509V3_EXT_I2V)i2v_GENERAL_NAMES,
-NULL, NULL, NULL, NULL},
+    {NID_certificate_issuer, 0, ASN1_ITEM_ref(GENERAL_NAMES),
+     0, 0, 0, 0,
+     0, 0,
+     (X509V3_EXT_I2V) i2v_GENERAL_NAMES,
+     NULL, NULL, NULL, NULL},
 };
 
 STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method,
-		GENERAL_NAMES *gens, STACK_OF(CONF_VALUE) *ret)
+                                        GENERAL_NAMES *gens,
+                                        STACK_OF(CONF_VALUE) *ret)
 {
-	size_t i;
-	GENERAL_NAME *gen;
-	for(i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
-		gen = sk_GENERAL_NAME_value(gens, i);
-		ret = i2v_GENERAL_NAME(method, gen, ret);
-	}
-	if(!ret) return sk_CONF_VALUE_new_null();
-	return ret;
+    size_t i;
+    GENERAL_NAME *gen;
+    for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
+        gen = sk_GENERAL_NAME_value(gens, i);
+        ret = i2v_GENERAL_NAME(method, gen, ret);
+    }
+    if (!ret)
+        return sk_CONF_VALUE_new_null();
+    return ret;
 }
 
 STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
-				GENERAL_NAME *gen, STACK_OF(CONF_VALUE) *ret)
+                                       GENERAL_NAME *gen,
+                                       STACK_OF(CONF_VALUE) *ret)
 {
-	unsigned char *p;
-	char oline[256], htmp[5];
-	int i;
-	switch (gen->type)
-	{
-		case GEN_OTHERNAME:
-		X509V3_add_value("othername","<unsupported>", &ret);
-		break;
+    unsigned char *p;
+    char oline[256], htmp[5];
+    int i;
+    switch (gen->type) {
+    case GEN_OTHERNAME:
+        X509V3_add_value("othername", "<unsupported>", &ret);
+        break;
 
-		case GEN_X400:
-		X509V3_add_value("X400Name","<unsupported>", &ret);
-		break;
+    case GEN_X400:
+        X509V3_add_value("X400Name", "<unsupported>", &ret);
+        break;
 
-		case GEN_EDIPARTY:
-		X509V3_add_value("EdiPartyName","<unsupported>", &ret);
-		break;
+    case GEN_EDIPARTY:
+        X509V3_add_value("EdiPartyName", "<unsupported>", &ret);
+        break;
 
-		case GEN_EMAIL:
-		X509V3_add_value_uchar("email",gen->d.ia5->data, &ret);
-		break;
+    case GEN_EMAIL:
+        X509V3_add_value_uchar("email", gen->d.ia5->data, &ret);
+        break;
 
-		case GEN_DNS:
-		X509V3_add_value_uchar("DNS",gen->d.ia5->data, &ret);
-		break;
+    case GEN_DNS:
+        X509V3_add_value_uchar("DNS", gen->d.ia5->data, &ret);
+        break;
 
-		case GEN_URI:
-		X509V3_add_value_uchar("URI",gen->d.ia5->data, &ret);
-		break;
+    case GEN_URI:
+        X509V3_add_value_uchar("URI", gen->d.ia5->data, &ret);
+        break;
 
-		case GEN_DIRNAME:
-		X509_NAME_oneline(gen->d.dirn, oline, 256);
-		X509V3_add_value("DirName",oline, &ret);
-		break;
+    case GEN_DIRNAME:
+        X509_NAME_oneline(gen->d.dirn, oline, 256);
+        X509V3_add_value("DirName", oline, &ret);
+        break;
 
-		case GEN_IPADD:
-		p = gen->d.ip->data;
-		if(gen->d.ip->length == 4)
-			BIO_snprintf(oline, sizeof oline,
-				     "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
-		else if(gen->d.ip->length == 16)
-			{
-			oline[0] = 0;
-			for (i = 0; i < 8; i++)
-				{
-				BIO_snprintf(htmp, sizeof htmp,
-					     "%X", p[0] << 8 | p[1]);
-				p += 2;
-				strcat(oline, htmp);
-				if (i != 7)
-					strcat(oline, ":");
-				}
-			}
-		else
-			{
-			X509V3_add_value("IP Address","<invalid>", &ret);
-			break;
-			}
-		X509V3_add_value("IP Address",oline, &ret);
-		break;
+    case GEN_IPADD:
+        p = gen->d.ip->data;
+        if (gen->d.ip->length == 4)
+            BIO_snprintf(oline, sizeof oline,
+                         "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
+        else if (gen->d.ip->length == 16) {
+            oline[0] = 0;
+            for (i = 0; i < 8; i++) {
+                BIO_snprintf(htmp, sizeof htmp, "%X", p[0] << 8 | p[1]);
+                p += 2;
+                strcat(oline, htmp);
+                if (i != 7)
+                    strcat(oline, ":");
+            }
+        } else {
+            X509V3_add_value("IP Address", "<invalid>", &ret);
+            break;
+        }
+        X509V3_add_value("IP Address", oline, &ret);
+        break;
 
-		case GEN_RID:
-		i2t_ASN1_OBJECT(oline, 256, gen->d.rid);
-		X509V3_add_value("Registered ID",oline, &ret);
-		break;
-	}
-	return ret;
+    case GEN_RID:
+        i2t_ASN1_OBJECT(oline, 256, gen->d.rid);
+        X509V3_add_value("Registered ID", oline, &ret);
+        break;
+    }
+    return ret;
 }
 
 int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen)
 {
-	unsigned char *p;
-	int i;
-	switch (gen->type)
-	{
-		case GEN_OTHERNAME:
-		BIO_printf(out, "othername:<unsupported>");
-		break;
+    unsigned char *p;
+    int i;
+    switch (gen->type) {
+    case GEN_OTHERNAME:
+        BIO_printf(out, "othername:<unsupported>");
+        break;
 
-		case GEN_X400:
-		BIO_printf(out, "X400Name:<unsupported>");
-		break;
+    case GEN_X400:
+        BIO_printf(out, "X400Name:<unsupported>");
+        break;
 
-		case GEN_EDIPARTY:
-		/* Maybe fix this: it is supported now */
-		BIO_printf(out, "EdiPartyName:<unsupported>");
-		break;
+    case GEN_EDIPARTY:
+        /* Maybe fix this: it is supported now */
+        BIO_printf(out, "EdiPartyName:<unsupported>");
+        break;
 
-		case GEN_EMAIL:
-		BIO_printf(out, "email:%s",gen->d.ia5->data);
-		break;
+    case GEN_EMAIL:
+        BIO_printf(out, "email:%s", gen->d.ia5->data);
+        break;
 
-		case GEN_DNS:
-		BIO_printf(out, "DNS:%s",gen->d.ia5->data);
-		break;
+    case GEN_DNS:
+        BIO_printf(out, "DNS:%s", gen->d.ia5->data);
+        break;
 
-		case GEN_URI:
-		BIO_printf(out, "URI:%s",gen->d.ia5->data);
-		break;
+    case GEN_URI:
+        BIO_printf(out, "URI:%s", gen->d.ia5->data);
+        break;
 
-		case GEN_DIRNAME:
-		BIO_printf(out, "DirName: ");
-		X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE);
-		break;
+    case GEN_DIRNAME:
+        BIO_printf(out, "DirName: ");
+        X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE);
+        break;
 
-		case GEN_IPADD:
-		p = gen->d.ip->data;
-		if(gen->d.ip->length == 4)
-			BIO_printf(out, "IP Address:%d.%d.%d.%d",
-						p[0], p[1], p[2], p[3]);
-		else if(gen->d.ip->length == 16)
-			{
-			BIO_printf(out, "IP Address");
-			for (i = 0; i < 8; i++)
-				{
-				BIO_printf(out, ":%X", p[0] << 8 | p[1]);
-				p += 2;
-				}
-			BIO_puts(out, "\n");
-			}
-		else
-			{
-			BIO_printf(out,"IP Address:<invalid>");
-			break;
-			}
-		break;
+    case GEN_IPADD:
+        p = gen->d.ip->data;
+        if (gen->d.ip->length == 4)
+            BIO_printf(out, "IP Address:%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
+        else if (gen->d.ip->length == 16) {
+            BIO_printf(out, "IP Address");
+            for (i = 0; i < 8; i++) {
+                BIO_printf(out, ":%X", p[0] << 8 | p[1]);
+                p += 2;
+            }
+            BIO_puts(out, "\n");
+        } else {
+            BIO_printf(out, "IP Address:<invalid>");
+            break;
+        }
+        break;
 
-		case GEN_RID:
-		BIO_printf(out, "Registered ID");
-		i2a_ASN1_OBJECT(out, gen->d.rid);
-		break;
-	}
-	return 1;
+    case GEN_RID:
+        BIO_printf(out, "Registered ID");
+        i2a_ASN1_OBJECT(out, gen->d.rid);
+        break;
+    }
+    return 1;
 }
 
 static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
-				 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
+                                     X509V3_CTX *ctx,
+                                     STACK_OF(CONF_VALUE) *nval)
 {
-	GENERAL_NAMES *gens = NULL;
-	CONF_VALUE *cnf;
-	size_t i;
-	if(!(gens = sk_GENERAL_NAME_new_null())) {
-		OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-		return NULL;
-	}
-	for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
-		cnf = sk_CONF_VALUE_value(nval, i);
-		if(!name_cmp(cnf->name, "issuer") && cnf->value &&
-						!strcmp(cnf->value, "copy")) {
-			if(!copy_issuer(ctx, gens)) goto err;
-		} else {
-			GENERAL_NAME *gen;
-			if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
-								 goto err; 
-			sk_GENERAL_NAME_push(gens, gen);
-		}
-	}
-	return gens;
-	err:
-	sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
-	return NULL;
+    GENERAL_NAMES *gens = NULL;
+    CONF_VALUE *cnf;
+    size_t i;
+    if (!(gens = sk_GENERAL_NAME_new_null())) {
+        OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+    for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+        cnf = sk_CONF_VALUE_value(nval, i);
+        if (!name_cmp(cnf->name, "issuer") && cnf->value &&
+            !strcmp(cnf->value, "copy")) {
+            if (!copy_issuer(ctx, gens))
+                goto err;
+        } else {
+            GENERAL_NAME *gen;
+            if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
+                goto err;
+            sk_GENERAL_NAME_push(gens, gen);
+        }
+    }
+    return gens;
+ err:
+    sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
+    return NULL;
 }
 
 /* Append subject altname of issuer to issuer alt name of subject */
 
 static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens)
 {
-	GENERAL_NAMES *ialt;
-	GENERAL_NAME *gen;
-	X509_EXTENSION *ext;
-	int i;
-	size_t j;
-	if(ctx && (ctx->flags == CTX_TEST)) return 1;
-	if(!ctx || !ctx->issuer_cert) {
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_ISSUER_DETAILS);
-		goto err;
-	}
-        i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1);
-	if(i < 0) return 1;
-        if(!(ext = X509_get_ext(ctx->issuer_cert, i)) ||
-                        !(ialt = X509V3_EXT_d2i(ext)) ) {
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_ISSUER_DECODE_ERROR);
-		goto err;
-	}
+    GENERAL_NAMES *ialt;
+    GENERAL_NAME *gen;
+    X509_EXTENSION *ext;
+    int i;
+    size_t j;
+    if (ctx && (ctx->flags == CTX_TEST))
+        return 1;
+    if (!ctx || !ctx->issuer_cert) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_ISSUER_DETAILS);
+        goto err;
+    }
+    i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1);
+    if (i < 0)
+        return 1;
+    if (!(ext = X509_get_ext(ctx->issuer_cert, i)) ||
+        !(ialt = X509V3_EXT_d2i(ext))) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_ISSUER_DECODE_ERROR);
+        goto err;
+    }
 
-	for(j = 0; j < sk_GENERAL_NAME_num(ialt); j++) {
-		gen = sk_GENERAL_NAME_value(ialt, j);
-		if(!sk_GENERAL_NAME_push(gens, gen)) {
-			OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-			goto err;
-		}
-	}
-	sk_GENERAL_NAME_free(ialt);
+    for (j = 0; j < sk_GENERAL_NAME_num(ialt); j++) {
+        gen = sk_GENERAL_NAME_value(ialt, j);
+        if (!sk_GENERAL_NAME_push(gens, gen)) {
+            OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+            goto err;
+        }
+    }
+    sk_GENERAL_NAME_free(ialt);
 
-	return 1;
-		
-	err:
-	return 0;
-	
+    return 1;
+
+ err:
+    return 0;
+
 }
 
 static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
-				 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
+                                      X509V3_CTX *ctx,
+                                      STACK_OF(CONF_VALUE) *nval)
 {
-	GENERAL_NAMES *gens = NULL;
-	CONF_VALUE *cnf;
-	size_t i;
-	if(!(gens = sk_GENERAL_NAME_new_null())) {
-		OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-		return NULL;
-	}
-	for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
-		cnf = sk_CONF_VALUE_value(nval, i);
-		if(!name_cmp(cnf->name, "email") && cnf->value &&
-						!strcmp(cnf->value, "copy")) {
-			if(!copy_email(ctx, gens, 0)) goto err;
-		} else if(!name_cmp(cnf->name, "email") && cnf->value &&
-						!strcmp(cnf->value, "move")) {
-			if(!copy_email(ctx, gens, 1)) goto err;
-		} else {
-			GENERAL_NAME *gen;
-			if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
-								 goto err; 
-			sk_GENERAL_NAME_push(gens, gen);
-		}
-	}
-	return gens;
-	err:
-	sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
-	return NULL;
+    GENERAL_NAMES *gens = NULL;
+    CONF_VALUE *cnf;
+    size_t i;
+    if (!(gens = sk_GENERAL_NAME_new_null())) {
+        OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+    for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+        cnf = sk_CONF_VALUE_value(nval, i);
+        if (!name_cmp(cnf->name, "email") && cnf->value &&
+            !strcmp(cnf->value, "copy")) {
+            if (!copy_email(ctx, gens, 0))
+                goto err;
+        } else if (!name_cmp(cnf->name, "email") && cnf->value &&
+                   !strcmp(cnf->value, "move")) {
+            if (!copy_email(ctx, gens, 1))
+                goto err;
+        } else {
+            GENERAL_NAME *gen;
+            if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
+                goto err;
+            sk_GENERAL_NAME_push(gens, gen);
+        }
+    }
+    return gens;
+ err:
+    sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
+    return NULL;
 }
 
-/* Copy any email addresses in a certificate or request to 
- * GENERAL_NAMES
+/*
+ * Copy any email addresses in a certificate or request to GENERAL_NAMES
  */
 
 static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p)
 {
-	X509_NAME *nm;
-	ASN1_IA5STRING *email = NULL;
-	X509_NAME_ENTRY *ne;
-	GENERAL_NAME *gen = NULL;
-	int i;
-	if(ctx != NULL && ctx->flags == CTX_TEST)
-		return 1;
-	if(!ctx || (!ctx->subject_cert && !ctx->subject_req)) {
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_SUBJECT_DETAILS);
-		goto err;
-	}
-	/* Find the subject name */
-	if(ctx->subject_cert) nm = X509_get_subject_name(ctx->subject_cert);
-	else nm = X509_REQ_get_subject_name(ctx->subject_req);
+    X509_NAME *nm;
+    ASN1_IA5STRING *email = NULL;
+    X509_NAME_ENTRY *ne;
+    GENERAL_NAME *gen = NULL;
+    int i;
+    if (ctx != NULL && ctx->flags == CTX_TEST)
+        return 1;
+    if (!ctx || (!ctx->subject_cert && !ctx->subject_req)) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_SUBJECT_DETAILS);
+        goto err;
+    }
+    /* Find the subject name */
+    if (ctx->subject_cert)
+        nm = X509_get_subject_name(ctx->subject_cert);
+    else
+        nm = X509_REQ_get_subject_name(ctx->subject_req);
 
-	/* Now add any email address(es) to STACK */
-	i = -1;
-	while((i = X509_NAME_get_index_by_NID(nm,
-					 NID_pkcs9_emailAddress, i)) >= 0) {
-		ne = X509_NAME_get_entry(nm, i);
-		email = M_ASN1_IA5STRING_dup(X509_NAME_ENTRY_get_data(ne));
-                if (move_p)
-                        {
-                        X509_NAME_delete_entry(nm, i);
-			X509_NAME_ENTRY_free(ne);
-                        i--;
-                        }
-		if(!email || !(gen = GENERAL_NAME_new())) {
-			OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-			goto err;
-		}
-		gen->d.ia5 = email;
-		email = NULL;
-		gen->type = GEN_EMAIL;
-		if(!sk_GENERAL_NAME_push(gens, gen)) {
-			OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-			goto err;
-		}
-		gen = NULL;
-	}
+    /* Now add any email address(es) to STACK */
+    i = -1;
+    while ((i = X509_NAME_get_index_by_NID(nm,
+                                           NID_pkcs9_emailAddress, i)) >= 0) {
+        ne = X509_NAME_get_entry(nm, i);
+        email = M_ASN1_IA5STRING_dup(X509_NAME_ENTRY_get_data(ne));
+        if (move_p) {
+            X509_NAME_delete_entry(nm, i);
+            X509_NAME_ENTRY_free(ne);
+            i--;
+        }
+        if (!email || !(gen = GENERAL_NAME_new())) {
+            OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+            goto err;
+        }
+        gen->d.ia5 = email;
+        email = NULL;
+        gen->type = GEN_EMAIL;
+        if (!sk_GENERAL_NAME_push(gens, gen)) {
+            OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+            goto err;
+        }
+        gen = NULL;
+    }
 
-	
-	return 1;
-		
-	err:
-	GENERAL_NAME_free(gen);
-	M_ASN1_IA5STRING_free(email);
-	return 0;
-	
+    return 1;
+
+ err:
+    GENERAL_NAME_free(gen);
+    M_ASN1_IA5STRING_free(email);
+    return 0;
+
 }
 
 GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method,
-				 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
+                                 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
 {
-	GENERAL_NAME *gen;
-	GENERAL_NAMES *gens = NULL;
-	CONF_VALUE *cnf;
-	size_t i;
-	if(!(gens = sk_GENERAL_NAME_new_null())) {
-		OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-		return NULL;
-	}
-	for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
-		cnf = sk_CONF_VALUE_value(nval, i);
-		if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) goto err; 
-		sk_GENERAL_NAME_push(gens, gen);
-	}
-	return gens;
-	err:
-	sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
-	return NULL;
+    GENERAL_NAME *gen;
+    GENERAL_NAMES *gens = NULL;
+    CONF_VALUE *cnf;
+    size_t i;
+    if (!(gens = sk_GENERAL_NAME_new_null())) {
+        OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+    for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+        cnf = sk_CONF_VALUE_value(nval, i);
+        if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
+            goto err;
+        sk_GENERAL_NAME_push(gens, gen);
+    }
+    return gens;
+ err:
+    sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
+    return NULL;
 }
 
-GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
-			       CONF_VALUE *cnf)
-	{
-	return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0);
-	}
+GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method,
+                               X509V3_CTX *ctx, CONF_VALUE *cnf)
+{
+    return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0);
+}
 
 GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out,
-			       const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
-			       int gen_type, char *value, int is_nc)
-	{
-	char is_string = 0;
-	GENERAL_NAME *gen = NULL;
+                               const X509V3_EXT_METHOD *method,
+                               X509V3_CTX *ctx, int gen_type, char *value,
+                               int is_nc)
+{
+    char is_string = 0;
+    GENERAL_NAME *gen = NULL;
 
-	if(!value)
-		{
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_MISSING_VALUE);
-		return NULL;
-		}
+    if (!value) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_MISSING_VALUE);
+        return NULL;
+    }
 
-	if (out)
-		gen = out;
-	else
-		{
-		gen = GENERAL_NAME_new();
-		if(gen == NULL)
-			{
-			OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-			return NULL;
-			}
-		}
+    if (out)
+        gen = out;
+    else {
+        gen = GENERAL_NAME_new();
+        if (gen == NULL) {
+            OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+            return NULL;
+        }
+    }
 
-	switch (gen_type)
-		{
-		case GEN_URI:
-		case GEN_EMAIL:
-		case GEN_DNS:
-		is_string = 1;
-		break;
-		
-		case GEN_RID:
-		{
-		ASN1_OBJECT *obj;
-		if(!(obj = OBJ_txt2obj(value,0)))
-			{
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_OBJECT);
-			ERR_add_error_data(2, "value=", value);
-			goto err;
-			}
-		gen->d.rid = obj;
-		}
-		break;
+    switch (gen_type) {
+    case GEN_URI:
+    case GEN_EMAIL:
+    case GEN_DNS:
+        is_string = 1;
+        break;
 
-		case GEN_IPADD:
-		if (is_nc)
-			gen->d.ip = a2i_IPADDRESS_NC(value);
-		else
-			gen->d.ip = a2i_IPADDRESS(value);
-		if(gen->d.ip == NULL)
-			{
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_IP_ADDRESS);
-			ERR_add_error_data(2, "value=", value);
-			goto err;
-			}
-		break;
+    case GEN_RID:
+        {
+            ASN1_OBJECT *obj;
+            if (!(obj = OBJ_txt2obj(value, 0))) {
+                OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_OBJECT);
+                ERR_add_error_data(2, "value=", value);
+                goto err;
+            }
+            gen->d.rid = obj;
+        }
+        break;
 
-		case GEN_DIRNAME:
-		if (!do_dirname(gen, value, ctx))
-			{
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_DIRNAME_ERROR);
-			goto err;
-			}
-		break;
+    case GEN_IPADD:
+        if (is_nc)
+            gen->d.ip = a2i_IPADDRESS_NC(value);
+        else
+            gen->d.ip = a2i_IPADDRESS(value);
+        if (gen->d.ip == NULL) {
+            OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_IP_ADDRESS);
+            ERR_add_error_data(2, "value=", value);
+            goto err;
+        }
+        break;
 
-		case GEN_OTHERNAME:
-		if (!do_othername(gen, value, ctx))
-			{
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_OTHERNAME_ERROR);
-			goto err;
-			}
-		break;
-		default:
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNSUPPORTED_TYPE);
-		goto err;
-		}
+    case GEN_DIRNAME:
+        if (!do_dirname(gen, value, ctx)) {
+            OPENSSL_PUT_ERROR(X509V3, X509V3_R_DIRNAME_ERROR);
+            goto err;
+        }
+        break;
 
-	if(is_string)
-		{
-		if(!(gen->d.ia5 = M_ASN1_IA5STRING_new()) ||
-			      !ASN1_STRING_set(gen->d.ia5, (unsigned char*)value,
-					       strlen(value)))
-			{
-			OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-			goto err;
-			}
-		}
+    case GEN_OTHERNAME:
+        if (!do_othername(gen, value, ctx)) {
+            OPENSSL_PUT_ERROR(X509V3, X509V3_R_OTHERNAME_ERROR);
+            goto err;
+        }
+        break;
+    default:
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNSUPPORTED_TYPE);
+        goto err;
+    }
 
-	gen->type = gen_type;
+    if (is_string) {
+        if (!(gen->d.ia5 = M_ASN1_IA5STRING_new()) ||
+            !ASN1_STRING_set(gen->d.ia5, (unsigned char *)value,
+                             strlen(value))) {
+            OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+            goto err;
+        }
+    }
 
-	return gen;
+    gen->type = gen_type;
 
-	err:
-	if (!out)
-		GENERAL_NAME_free(gen);
-	return NULL;
-	}
+    return gen;
+
+ err:
+    if (!out)
+        GENERAL_NAME_free(gen);
+    return NULL;
+}
 
 GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out,
-				  const X509V3_EXT_METHOD *method,
-				  X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc)
-	{
-	int type;
+                                  const X509V3_EXT_METHOD *method,
+                                  X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc)
+{
+    int type;
 
-	char *name, *value;
+    char *name, *value;
 
-	name = cnf->name;
-	value = cnf->value;
+    name = cnf->name;
+    value = cnf->value;
 
-	if(!value)
-		{
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_MISSING_VALUE);
-		return NULL;
-		}
+    if (!value) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_MISSING_VALUE);
+        return NULL;
+    }
 
-	if(!name_cmp(name, "email"))
-		type = GEN_EMAIL;
-	else if(!name_cmp(name, "URI"))
-		type = GEN_URI;
-	else if(!name_cmp(name, "DNS"))
-		type = GEN_DNS;
-	else if(!name_cmp(name, "RID"))
-		type = GEN_RID;
-	else if(!name_cmp(name, "IP"))
-		type = GEN_IPADD;
-	else if(!name_cmp(name, "dirName"))
-		type = GEN_DIRNAME;
-	else if(!name_cmp(name, "otherName"))
-		type = GEN_OTHERNAME;
-	else
-		{
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNSUPPORTED_OPTION);
-		ERR_add_error_data(2, "name=", name);
-		return NULL;
-		}
+    if (!name_cmp(name, "email"))
+        type = GEN_EMAIL;
+    else if (!name_cmp(name, "URI"))
+        type = GEN_URI;
+    else if (!name_cmp(name, "DNS"))
+        type = GEN_DNS;
+    else if (!name_cmp(name, "RID"))
+        type = GEN_RID;
+    else if (!name_cmp(name, "IP"))
+        type = GEN_IPADD;
+    else if (!name_cmp(name, "dirName"))
+        type = GEN_DIRNAME;
+    else if (!name_cmp(name, "otherName"))
+        type = GEN_OTHERNAME;
+    else {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNSUPPORTED_OPTION);
+        ERR_add_error_data(2, "name=", name);
+        return NULL;
+    }
 
-	return a2i_GENERAL_NAME(out, method, ctx, type, value, is_nc);
+    return a2i_GENERAL_NAME(out, method, ctx, type, value, is_nc);
 
-	}
+}
 
 static int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx)
-	{
-	char *objtmp = NULL, *p;
-	int objlen;
-	if (!(p = strchr(value, ';')))
-		return 0;
-	if (!(gen->d.otherName = OTHERNAME_new()))
-		return 0;
-	/* Free this up because we will overwrite it.
-	 * no need to free type_id because it is static
-	 */
-	ASN1_TYPE_free(gen->d.otherName->value);
-	if (!(gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx)))
-		return 0;
-	objlen = p - value;
-	objtmp = OPENSSL_malloc(objlen + 1);
-	if (objtmp == NULL)
-		return 0;
-	strncpy(objtmp, value, objlen);
-	objtmp[objlen] = 0;
-	gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0);
-	OPENSSL_free(objtmp);	
-	if (!gen->d.otherName->type_id)
-		return 0;
-	return 1;
-	}
+{
+    char *objtmp = NULL, *p;
+    int objlen;
+    if (!(p = strchr(value, ';')))
+        return 0;
+    if (!(gen->d.otherName = OTHERNAME_new()))
+        return 0;
+    /*
+     * Free this up because we will overwrite it. no need to free type_id
+     * because it is static
+     */
+    ASN1_TYPE_free(gen->d.otherName->value);
+    if (!(gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx)))
+        return 0;
+    objlen = p - value;
+    objtmp = OPENSSL_malloc(objlen + 1);
+    if (objtmp == NULL)
+        return 0;
+    strncpy(objtmp, value, objlen);
+    objtmp[objlen] = 0;
+    gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0);
+    OPENSSL_free(objtmp);
+    if (!gen->d.otherName->type_id)
+        return 0;
+    return 1;
+}
 
 static int do_dirname(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx)
-	{
-	int ret = 0;
-	STACK_OF(CONF_VALUE) *sk = NULL;
-	X509_NAME *nm = X509_NAME_new();
-	if (nm == NULL)
-		goto err;
-	sk = X509V3_get_section(ctx, value);
-	if (sk == NULL)
-		{
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND);
-		ERR_add_error_data(2, "section=", value);
-		goto err;
-		}
-	/* FIXME: should allow other character types... */
-	if (!X509V3_NAME_from_section(nm, sk, MBSTRING_ASC))
-		goto err;
-	gen->d.dirn = nm;
-	ret = 1;
+{
+    int ret = 0;
+    STACK_OF(CONF_VALUE) *sk = NULL;
+    X509_NAME *nm = X509_NAME_new();
+    if (nm == NULL)
+        goto err;
+    sk = X509V3_get_section(ctx, value);
+    if (sk == NULL) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND);
+        ERR_add_error_data(2, "section=", value);
+        goto err;
+    }
+    /* FIXME: should allow other character types... */
+    if (!X509V3_NAME_from_section(nm, sk, MBSTRING_ASC))
+        goto err;
+    gen->d.dirn = nm;
+    ret = 1;
 
-err:
-	if (!ret)
-		X509_NAME_free(nm);
-	X509V3_section_free(ctx, sk);
-	return ret;
-	}
+ err:
+    if (!ret)
+        X509_NAME_free(nm);
+    X509V3_section_free(ctx, sk);
+    return ret;
+}
diff --git a/src/crypto/x509v3/v3_bcons.c b/src/crypto/x509v3/v3_bcons.c
index 73ef21e..aefefdf 100644
--- a/src/crypto/x509v3/v3_bcons.c
+++ b/src/crypto/x509v3/v3_bcons.c
@@ -1,6 +1,7 @@
 /* v3_bcons.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
  */
 /* ====================================================================
  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
@@ -10,7 +11,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -54,7 +55,6 @@
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com). */
 
-
 #include <stdio.h>
 #include <string.h>
 
@@ -65,62 +65,69 @@
 #include <openssl/obj.h>
 #include <openssl/x509v3.h>
 
-
-static STACK_OF(CONF_VALUE) *i2v_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method, BASIC_CONSTRAINTS *bcons, STACK_OF(CONF_VALUE) *extlist);
-static BASIC_CONSTRAINTS *v2i_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *values);
+static STACK_OF(CONF_VALUE) *i2v_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method,
+                                                   BASIC_CONSTRAINTS *bcons,
+                                                   STACK_OF(CONF_VALUE)
+                                                   *extlist);
+static BASIC_CONSTRAINTS *v2i_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method,
+                                                X509V3_CTX *ctx,
+                                                STACK_OF(CONF_VALUE) *values);
 
 const X509V3_EXT_METHOD v3_bcons = {
-NID_basic_constraints, 0,
-ASN1_ITEM_ref(BASIC_CONSTRAINTS),
-0,0,0,0,
-0,0,
-(X509V3_EXT_I2V)i2v_BASIC_CONSTRAINTS,
-(X509V3_EXT_V2I)v2i_BASIC_CONSTRAINTS,
-NULL,NULL,
-NULL
+    NID_basic_constraints, 0,
+    ASN1_ITEM_ref(BASIC_CONSTRAINTS),
+    0, 0, 0, 0,
+    0, 0,
+    (X509V3_EXT_I2V) i2v_BASIC_CONSTRAINTS,
+    (X509V3_EXT_V2I)v2i_BASIC_CONSTRAINTS,
+    NULL, NULL,
+    NULL
 };
 
 ASN1_SEQUENCE(BASIC_CONSTRAINTS) = {
-	ASN1_OPT(BASIC_CONSTRAINTS, ca, ASN1_FBOOLEAN),
-	ASN1_OPT(BASIC_CONSTRAINTS, pathlen, ASN1_INTEGER)
+        ASN1_OPT(BASIC_CONSTRAINTS, ca, ASN1_FBOOLEAN),
+        ASN1_OPT(BASIC_CONSTRAINTS, pathlen, ASN1_INTEGER)
 } ASN1_SEQUENCE_END(BASIC_CONSTRAINTS)
 
 IMPLEMENT_ASN1_FUNCTIONS(BASIC_CONSTRAINTS)
 
-
 static STACK_OF(CONF_VALUE) *i2v_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method,
-	     BASIC_CONSTRAINTS *bcons, STACK_OF(CONF_VALUE) *extlist)
+                                                   BASIC_CONSTRAINTS *bcons,
+                                                   STACK_OF(CONF_VALUE)
+                                                   *extlist)
 {
-	X509V3_add_value_bool("CA", bcons->ca, &extlist);
-	X509V3_add_value_int("pathlen", bcons->pathlen, &extlist);
-	return extlist;
+    X509V3_add_value_bool("CA", bcons->ca, &extlist);
+    X509V3_add_value_int("pathlen", bcons->pathlen, &extlist);
+    return extlist;
 }
 
 static BASIC_CONSTRAINTS *v2i_BASIC_CONSTRAINTS(X509V3_EXT_METHOD *method,
-	     X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *values)
+                                                X509V3_CTX *ctx,
+                                                STACK_OF(CONF_VALUE) *values)
 {
-	BASIC_CONSTRAINTS *bcons=NULL;
-	CONF_VALUE *val;
-	size_t i;
-	if(!(bcons = BASIC_CONSTRAINTS_new())) {
-		OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-		return NULL;
-	}
-	for(i = 0; i < sk_CONF_VALUE_num(values); i++) {
-		val = sk_CONF_VALUE_value(values, i);
-		if(!strcmp(val->name, "CA")) {
-			if(!X509V3_get_value_bool(val, &bcons->ca)) goto err;
-		} else if(!strcmp(val->name, "pathlen")) {
-			if(!X509V3_get_value_int(val, &bcons->pathlen)) goto err;
-		} else {
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NAME);
-			X509V3_conf_err(val);
-			goto err;
-		}
-	}
-	return bcons;
-	err:
-	BASIC_CONSTRAINTS_free(bcons);
-	return NULL;
+    BASIC_CONSTRAINTS *bcons = NULL;
+    CONF_VALUE *val;
+    size_t i;
+    if (!(bcons = BASIC_CONSTRAINTS_new())) {
+        OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+    for (i = 0; i < sk_CONF_VALUE_num(values); i++) {
+        val = sk_CONF_VALUE_value(values, i);
+        if (!strcmp(val->name, "CA")) {
+            if (!X509V3_get_value_bool(val, &bcons->ca))
+                goto err;
+        } else if (!strcmp(val->name, "pathlen")) {
+            if (!X509V3_get_value_int(val, &bcons->pathlen))
+                goto err;
+        } else {
+            OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NAME);
+            X509V3_conf_err(val);
+            goto err;
+        }
+    }
+    return bcons;
+ err:
+    BASIC_CONSTRAINTS_free(bcons);
+    return NULL;
 }
-
diff --git a/src/crypto/x509v3/v3_bitst.c b/src/crypto/x509v3/v3_bitst.c
index e1e2087..86a8c36 100644
--- a/src/crypto/x509v3/v3_bitst.c
+++ b/src/crypto/x509v3/v3_bitst.c
@@ -1,6 +1,7 @@
 /* v3_bitst.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
  */
 /* ====================================================================
  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
@@ -10,7 +11,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -62,80 +63,79 @@
 #include <openssl/obj.h>
 #include <openssl/x509v3.h>
 
-
 static const BIT_STRING_BITNAME ns_cert_type_table[] = {
-{0, "SSL Client", "client"},
-{1, "SSL Server", "server"},
-{2, "S/MIME", "email"},
-{3, "Object Signing", "objsign"},
-{4, "Unused", "reserved"},
-{5, "SSL CA", "sslCA"},
-{6, "S/MIME CA", "emailCA"},
-{7, "Object Signing CA", "objCA"},
-{-1, NULL, NULL}
+    {0, "SSL Client", "client"},
+    {1, "SSL Server", "server"},
+    {2, "S/MIME", "email"},
+    {3, "Object Signing", "objsign"},
+    {4, "Unused", "reserved"},
+    {5, "SSL CA", "sslCA"},
+    {6, "S/MIME CA", "emailCA"},
+    {7, "Object Signing CA", "objCA"},
+    {-1, NULL, NULL}
 };
 
 static const BIT_STRING_BITNAME key_usage_type_table[] = {
-{0, "Digital Signature", "digitalSignature"},
-{1, "Non Repudiation", "nonRepudiation"},
-{2, "Key Encipherment", "keyEncipherment"},
-{3, "Data Encipherment", "dataEncipherment"},
-{4, "Key Agreement", "keyAgreement"},
-{5, "Certificate Sign", "keyCertSign"},
-{6, "CRL Sign", "cRLSign"},
-{7, "Encipher Only", "encipherOnly"},
-{8, "Decipher Only", "decipherOnly"},
-{-1, NULL, NULL}
+    {0, "Digital Signature", "digitalSignature"},
+    {1, "Non Repudiation", "nonRepudiation"},
+    {2, "Key Encipherment", "keyEncipherment"},
+    {3, "Data Encipherment", "dataEncipherment"},
+    {4, "Key Agreement", "keyAgreement"},
+    {5, "Certificate Sign", "keyCertSign"},
+    {6, "CRL Sign", "cRLSign"},
+    {7, "Encipher Only", "encipherOnly"},
+    {8, "Decipher Only", "decipherOnly"},
+    {-1, NULL, NULL}
 };
 
-
-
-const X509V3_EXT_METHOD v3_nscert = EXT_BITSTRING(NID_netscape_cert_type, ns_cert_type_table);
-const X509V3_EXT_METHOD v3_key_usage = EXT_BITSTRING(NID_key_usage, key_usage_type_table);
+const X509V3_EXT_METHOD v3_nscert =
+EXT_BITSTRING(NID_netscape_cert_type, ns_cert_type_table);
+const X509V3_EXT_METHOD v3_key_usage =
+EXT_BITSTRING(NID_key_usage, key_usage_type_table);
 
 STACK_OF(CONF_VALUE) *i2v_ASN1_BIT_STRING(X509V3_EXT_METHOD *method,
-	     ASN1_BIT_STRING *bits, STACK_OF(CONF_VALUE) *ret)
+                                          ASN1_BIT_STRING *bits,
+                                          STACK_OF(CONF_VALUE) *ret)
 {
-	const BIT_STRING_BITNAME *bnam;
-	for(bnam =method->usr_data; bnam->lname; bnam++) {
-		if(ASN1_BIT_STRING_get_bit(bits, bnam->bitnum)) 
-			X509V3_add_value(bnam->lname, NULL, &ret);
-	}
-	return ret;
+    const BIT_STRING_BITNAME *bnam;
+    for (bnam = method->usr_data; bnam->lname; bnam++) {
+        if (ASN1_BIT_STRING_get_bit(bits, bnam->bitnum))
+            X509V3_add_value(bnam->lname, NULL, &ret);
+    }
+    return ret;
 }
-	
-ASN1_BIT_STRING *v2i_ASN1_BIT_STRING(X509V3_EXT_METHOD *method,
-	     X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
-{
-	CONF_VALUE *val;
-	ASN1_BIT_STRING *bs;
-	size_t i;
-	const BIT_STRING_BITNAME *bnam;
-	if(!(bs = M_ASN1_BIT_STRING_new())) {
-		OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-		return NULL;
-	}
-	for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
-		val = sk_CONF_VALUE_value(nval, i);
-		for(bnam = method->usr_data; bnam->lname; bnam++) {
-			if(!strcmp(bnam->sname, val->name) ||
-				!strcmp(bnam->lname, val->name) ) {
-				if(!ASN1_BIT_STRING_set_bit(bs, bnam->bitnum, 1)) {
-					OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-					M_ASN1_BIT_STRING_free(bs);
-					return NULL;
-				}
-				break;
-			}
-		}
-		if(!bnam->lname) {
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT);
-			X509V3_conf_err(val);
-			M_ASN1_BIT_STRING_free(bs);
-			return NULL;
-		}
-	}
-	return bs;
-}
-	
 
+ASN1_BIT_STRING *v2i_ASN1_BIT_STRING(X509V3_EXT_METHOD *method,
+                                     X509V3_CTX *ctx,
+                                     STACK_OF(CONF_VALUE) *nval)
+{
+    CONF_VALUE *val;
+    ASN1_BIT_STRING *bs;
+    size_t i;
+    const BIT_STRING_BITNAME *bnam;
+    if (!(bs = M_ASN1_BIT_STRING_new())) {
+        OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+    for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+        val = sk_CONF_VALUE_value(nval, i);
+        for (bnam = method->usr_data; bnam->lname; bnam++) {
+            if (!strcmp(bnam->sname, val->name) ||
+                !strcmp(bnam->lname, val->name)) {
+                if (!ASN1_BIT_STRING_set_bit(bs, bnam->bitnum, 1)) {
+                    OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+                    M_ASN1_BIT_STRING_free(bs);
+                    return NULL;
+                }
+                break;
+            }
+        }
+        if (!bnam->lname) {
+            OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT);
+            X509V3_conf_err(val);
+            M_ASN1_BIT_STRING_free(bs);
+            return NULL;
+        }
+    }
+    return bs;
+}
diff --git a/src/crypto/x509v3/v3_conf.c b/src/crypto/x509v3/v3_conf.c
index fe71566..ff2eae1 100644
--- a/src/crypto/x509v3/v3_conf.c
+++ b/src/crypto/x509v3/v3_conf.c
@@ -1,6 +1,7 @@
 /* v3_conf.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
  */
 /* ====================================================================
  * Copyright (c) 1999-2002 The OpenSSL Project.  All rights reserved.
@@ -10,7 +11,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -69,391 +70,393 @@
 
 #include "../internal.h"
 
-
 static int v3_check_critical(char **value);
 static int v3_check_generic(char **value);
-static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid, int crit, char *value);
-static X509_EXTENSION *v3_generic_extension(const char *ext, char *value, int crit, int type, X509V3_CTX *ctx);
-static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method, int ext_nid,
-				  int crit, void *ext_struc);
-static unsigned char *generic_asn1(char *value, X509V3_CTX *ctx, long *ext_len);
+static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid,
+                                    int crit, char *value);
+static X509_EXTENSION *v3_generic_extension(const char *ext, char *value,
+                                            int crit, int type,
+                                            X509V3_CTX *ctx);
+static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method,
+                                  int ext_nid, int crit, void *ext_struc);
+static unsigned char *generic_asn1(char *value, X509V3_CTX *ctx,
+                                   long *ext_len);
 /* CONF *conf:  Config file    */
 /* char *name:  Name    */
 /* char *value:  Value    */
 X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, char *name,
-				 char *value)
-	{
-	int crit;
-	int ext_type;
-	X509_EXTENSION *ret;
-	crit = v3_check_critical(&value);
-	if ((ext_type = v3_check_generic(&value))) 
-		return v3_generic_extension(name, value, crit, ext_type, ctx);
-	ret = do_ext_nconf(conf, ctx, OBJ_sn2nid(name), crit, value);
-	if (!ret)
-		{
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_ERROR_IN_EXTENSION);
-		ERR_add_error_data(4,"name=", name, ", value=", value);
-		}
-	return ret;
-	}
+                                 char *value)
+{
+    int crit;
+    int ext_type;
+    X509_EXTENSION *ret;
+    crit = v3_check_critical(&value);
+    if ((ext_type = v3_check_generic(&value)))
+        return v3_generic_extension(name, value, crit, ext_type, ctx);
+    ret = do_ext_nconf(conf, ctx, OBJ_sn2nid(name), crit, value);
+    if (!ret) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_ERROR_IN_EXTENSION);
+        ERR_add_error_data(4, "name=", name, ", value=", value);
+    }
+    return ret;
+}
 
 /* CONF *conf:  Config file    */
 /* char *value:  Value    */
 X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid,
-				     char *value)
-	{
-	int crit;
-	int ext_type;
-	crit = v3_check_critical(&value);
-	if ((ext_type = v3_check_generic(&value))) 
-		return v3_generic_extension(OBJ_nid2sn(ext_nid),
-						 value, crit, ext_type, ctx);
-	return do_ext_nconf(conf, ctx, ext_nid, crit, value);
-	}
+                                     char *value)
+{
+    int crit;
+    int ext_type;
+    crit = v3_check_critical(&value);
+    if ((ext_type = v3_check_generic(&value)))
+        return v3_generic_extension(OBJ_nid2sn(ext_nid),
+                                    value, crit, ext_type, ctx);
+    return do_ext_nconf(conf, ctx, ext_nid, crit, value);
+}
 
 /* CONF *conf:  Config file    */
 /* char *value:  Value    */
 static X509_EXTENSION *do_ext_nconf(CONF *conf, X509V3_CTX *ctx, int ext_nid,
-				    int crit, char *value)
-	{
-	const X509V3_EXT_METHOD *method;
-	X509_EXTENSION *ext;
-	STACK_OF(CONF_VALUE) *nval;
-	void *ext_struc;
-	if (ext_nid == NID_undef)
-		{
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION_NAME);
-		return NULL;
-		}
-	if (!(method = X509V3_EXT_get_nid(ext_nid)))
-		{
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION);
-		return NULL;
-		}
-	/* Now get internal extension representation based on type */
-	if (method->v2i)
-		{
-		if(*value == '@') nval = NCONF_get_section(conf, value + 1);
-		else nval = X509V3_parse_list(value);
-		if(sk_CONF_VALUE_num(nval) <= 0)
-			{
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_EXTENSION_STRING);
-			ERR_add_error_data(4, "name=", OBJ_nid2sn(ext_nid), ",section=", value);
-			return NULL;
-			}
-		ext_struc = method->v2i(method, ctx, nval);
-		if(*value != '@') sk_CONF_VALUE_pop_free(nval,
-							 X509V3_conf_free);
-		if(!ext_struc) return NULL;
-		}
-	else if(method->s2i)
-		{
-		if(!(ext_struc = method->s2i(method, ctx, value))) return NULL;
-		}
-	else if(method->r2i)
-		{
-		if(!ctx->db || !ctx->db_meth)
-			{
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_CONFIG_DATABASE);
-			return NULL;
-			}
-		if(!(ext_struc = method->r2i(method, ctx, value))) return NULL;
-		}
-	else
-		{
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED);
-		ERR_add_error_data(2, "name=", OBJ_nid2sn(ext_nid));
-		return NULL;
-		}
+                                    int crit, char *value)
+{
+    const X509V3_EXT_METHOD *method;
+    X509_EXTENSION *ext;
+    STACK_OF(CONF_VALUE) *nval;
+    void *ext_struc;
+    if (ext_nid == NID_undef) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION_NAME);
+        return NULL;
+    }
+    if (!(method = X509V3_EXT_get_nid(ext_nid))) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION);
+        return NULL;
+    }
+    /* Now get internal extension representation based on type */
+    if (method->v2i) {
+        if (*value == '@')
+            nval = NCONF_get_section(conf, value + 1);
+        else
+            nval = X509V3_parse_list(value);
+        if (nval == NULL || sk_CONF_VALUE_num(nval) <= 0) {
+            OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_EXTENSION_STRING);
+            ERR_add_error_data(4, "name=", OBJ_nid2sn(ext_nid), ",section=",
+                               value);
+            if (*value != '@')
+                sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
+            return NULL;
+        }
+        ext_struc = method->v2i(method, ctx, nval);
+        if (*value != '@')
+            sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
+        if (!ext_struc)
+            return NULL;
+    } else if (method->s2i) {
+        if (!(ext_struc = method->s2i(method, ctx, value)))
+            return NULL;
+    } else if (method->r2i) {
+        if (!ctx->db || !ctx->db_meth) {
+            OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_CONFIG_DATABASE);
+            return NULL;
+        }
+        if (!(ext_struc = method->r2i(method, ctx, value)))
+            return NULL;
+    } else {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED);
+        ERR_add_error_data(2, "name=", OBJ_nid2sn(ext_nid));
+        return NULL;
+    }
 
-	ext  = do_ext_i2d(method, ext_nid, crit, ext_struc);
-	if(method->it) ASN1_item_free(ext_struc, ASN1_ITEM_ptr(method->it));
-	else method->ext_free(ext_struc);
-	return ext;
+    ext = do_ext_i2d(method, ext_nid, crit, ext_struc);
+    if (method->it)
+        ASN1_item_free(ext_struc, ASN1_ITEM_ptr(method->it));
+    else
+        method->ext_free(ext_struc);
+    return ext;
 
-	}
+}
 
-static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method, int ext_nid,
-				  int crit, void *ext_struc)
-	{
-	unsigned char *ext_der;
-	int ext_len;
-	ASN1_OCTET_STRING *ext_oct;
-	X509_EXTENSION *ext;
-	/* Convert internal representation to DER */
-	if (method->it)
-		{
-		ext_der = NULL;
-		ext_len = ASN1_item_i2d(ext_struc, &ext_der, ASN1_ITEM_ptr(method->it));
-		if (ext_len < 0) goto merr;
-		}
-	 else
-		{
-		unsigned char *p;
-		ext_len = method->i2d(ext_struc, NULL);
-		if(!(ext_der = OPENSSL_malloc(ext_len))) goto merr;
-		p = ext_der;
-		method->i2d(ext_struc, &p);
-		}
-	if (!(ext_oct = M_ASN1_OCTET_STRING_new())) goto merr;
-	ext_oct->data = ext_der;
-	ext_oct->length = ext_len;
+static X509_EXTENSION *do_ext_i2d(const X509V3_EXT_METHOD *method,
+                                  int ext_nid, int crit, void *ext_struc)
+{
+    unsigned char *ext_der;
+    int ext_len;
+    ASN1_OCTET_STRING *ext_oct;
+    X509_EXTENSION *ext;
+    /* Convert internal representation to DER */
+    if (method->it) {
+        ext_der = NULL;
+        ext_len =
+            ASN1_item_i2d(ext_struc, &ext_der, ASN1_ITEM_ptr(method->it));
+        if (ext_len < 0)
+            goto merr;
+    } else {
+        unsigned char *p;
+        ext_len = method->i2d(ext_struc, NULL);
+        if (!(ext_der = OPENSSL_malloc(ext_len)))
+            goto merr;
+        p = ext_der;
+        method->i2d(ext_struc, &p);
+    }
+    if (!(ext_oct = M_ASN1_OCTET_STRING_new()))
+        goto merr;
+    ext_oct->data = ext_der;
+    ext_oct->length = ext_len;
 
-	ext = X509_EXTENSION_create_by_NID(NULL, ext_nid, crit, ext_oct);
-	if (!ext) goto merr;
-	M_ASN1_OCTET_STRING_free(ext_oct);
+    ext = X509_EXTENSION_create_by_NID(NULL, ext_nid, crit, ext_oct);
+    if (!ext)
+        goto merr;
+    M_ASN1_OCTET_STRING_free(ext_oct);
 
-	return ext;
+    return ext;
 
-	merr:
-	OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-	return NULL;
+ merr:
+    OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+    return NULL;
 
-	}
+}
 
 /* Given an internal structure, nid and critical flag create an extension */
 
 X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc)
-	{
-	const X509V3_EXT_METHOD *method;
-	if (!(method = X509V3_EXT_get_nid(ext_nid))) {
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION);
-		return NULL;
-	}
-	return do_ext_i2d(method, ext_nid, crit, ext_struc);
+{
+    const X509V3_EXT_METHOD *method;
+    if (!(method = X509V3_EXT_get_nid(ext_nid))) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNKNOWN_EXTENSION);
+        return NULL;
+    }
+    return do_ext_i2d(method, ext_nid, crit, ext_struc);
 }
 
 /* Check the extension string for critical flag */
 static int v3_check_critical(char **value)
 {
-	char *p = *value;
-	if ((strlen(p) < 9) || strncmp(p, "critical,", 9)) return 0;
-	p+=9;
-	while(isspace((unsigned char)*p)) p++;
-	*value = p;
-	return 1;
+    char *p = *value;
+    if ((strlen(p) < 9) || strncmp(p, "critical,", 9))
+        return 0;
+    p += 9;
+    while (isspace((unsigned char)*p))
+        p++;
+    *value = p;
+    return 1;
 }
 
 /* Check extension string for generic extension and return the type */
 static int v3_check_generic(char **value)
 {
-	int gen_type = 0;
-	char *p = *value;
-	if ((strlen(p) >= 4) && !strncmp(p, "DER:", 4))
-		{
-		p+=4;
-		gen_type = 1;
-		}
-	else if ((strlen(p) >= 5) && !strncmp(p, "ASN1:", 5))
-		{
-		p+=5;
-		gen_type = 2;
-		}
-	else
-		return 0;
+    int gen_type = 0;
+    char *p = *value;
+    if ((strlen(p) >= 4) && !strncmp(p, "DER:", 4)) {
+        p += 4;
+        gen_type = 1;
+    } else if ((strlen(p) >= 5) && !strncmp(p, "ASN1:", 5)) {
+        p += 5;
+        gen_type = 2;
+    } else
+        return 0;
 
-	while (isspace((unsigned char)*p)) p++;
-	*value = p;
-	return gen_type;
+    while (isspace((unsigned char)*p))
+        p++;
+    *value = p;
+    return gen_type;
 }
 
 /* Create a generic extension: for now just handle DER type */
 static X509_EXTENSION *v3_generic_extension(const char *ext, char *value,
-					    int crit, int gen_type,
-					    X509V3_CTX *ctx)
-        OPENSSL_SUPPRESS_POTENTIALLY_UNINITIALIZED_WARNINGS
-	{
-	unsigned char *ext_der=NULL;
-	long ext_len;
-	ASN1_OBJECT *obj=NULL;
-	ASN1_OCTET_STRING *oct=NULL;
-	X509_EXTENSION *extension=NULL;
-	if (!(obj = OBJ_txt2obj(ext, 0)))
-		{
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_NAME_ERROR);
-		ERR_add_error_data(2, "name=", ext);
-		goto err;
-		}
+                                            int crit, int gen_type,
+                                            X509V3_CTX *ctx)
+{
+    unsigned char *ext_der = NULL;
+    long ext_len = 0;
+    ASN1_OBJECT *obj = NULL;
+    ASN1_OCTET_STRING *oct = NULL;
+    X509_EXTENSION *extension = NULL;
+    if (!(obj = OBJ_txt2obj(ext, 0))) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_NAME_ERROR);
+        ERR_add_error_data(2, "name=", ext);
+        goto err;
+    }
 
-	if (gen_type == 1)
-		ext_der = string_to_hex(value, &ext_len);
-	else if (gen_type == 2)
-		ext_der = generic_asn1(value, ctx, &ext_len);
+    if (gen_type == 1)
+        ext_der = string_to_hex(value, &ext_len);
+    else if (gen_type == 2)
+        ext_der = generic_asn1(value, ctx, &ext_len);
 
-	if (ext_der == NULL)
-		{
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_VALUE_ERROR);
-		ERR_add_error_data(2, "value=", value);
-		goto err;
-		}
+    if (ext_der == NULL) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_VALUE_ERROR);
+        ERR_add_error_data(2, "value=", value);
+        goto err;
+    }
 
-	if (!(oct = M_ASN1_OCTET_STRING_new()))
-		{
-		OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-		goto err;
-		}
+    if (!(oct = M_ASN1_OCTET_STRING_new())) {
+        OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
 
-	oct->data = ext_der;
-	oct->length = ext_len;
-	ext_der = NULL;
+    oct->data = ext_der;
+    oct->length = ext_len;
+    ext_der = NULL;
 
-	extension = X509_EXTENSION_create_by_OBJ(NULL, obj, crit, oct);
+    extension = X509_EXTENSION_create_by_OBJ(NULL, obj, crit, oct);
 
-	err:
-	ASN1_OBJECT_free(obj);
-	M_ASN1_OCTET_STRING_free(oct);
-	if(ext_der) OPENSSL_free(ext_der);
-	return extension;
+ err:
+    ASN1_OBJECT_free(obj);
+    M_ASN1_OCTET_STRING_free(oct);
+    if (ext_der)
+        OPENSSL_free(ext_der);
+    return extension;
 
-	}
+}
 
-static unsigned char *generic_asn1(char *value, X509V3_CTX *ctx, long *ext_len)
-	{
-	ASN1_TYPE *typ;
-	unsigned char *ext_der = NULL;
-	typ = ASN1_generate_v3(value, ctx);
-	if (typ == NULL)
-		return NULL;
-	*ext_len = i2d_ASN1_TYPE(typ, &ext_der);
-	ASN1_TYPE_free(typ);
-	return ext_der;
-	}
+static unsigned char *generic_asn1(char *value, X509V3_CTX *ctx,
+                                   long *ext_len)
+{
+    ASN1_TYPE *typ;
+    unsigned char *ext_der = NULL;
+    typ = ASN1_generate_v3(value, ctx);
+    if (typ == NULL)
+        return NULL;
+    *ext_len = i2d_ASN1_TYPE(typ, &ext_der);
+    ASN1_TYPE_free(typ);
+    return ext_der;
+}
 
-/* This is the main function: add a bunch of extensions based on a config file
- * section to an extension STACK.
+/*
+ * This is the main function: add a bunch of extensions based on a config
+ * file section to an extension STACK.
  */
 
-
 int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, char *section,
-			    STACK_OF(X509_EXTENSION) **sk)
-	{
-	X509_EXTENSION *ext;
-	STACK_OF(CONF_VALUE) *nval;
-	CONF_VALUE *val;	
-	size_t i;
-	if (!(nval = NCONF_get_section(conf, section))) return 0;
-	for (i = 0; i < sk_CONF_VALUE_num(nval); i++)
-		{
-		val = sk_CONF_VALUE_value(nval, i);
-		if (!(ext = X509V3_EXT_nconf(conf, ctx, val->name, val->value)))
-								return 0;
-		if (sk) X509v3_add_ext(sk, ext, -1);
-		X509_EXTENSION_free(ext);
-		}
-	return 1;
-	}
+                            STACK_OF(X509_EXTENSION) **sk)
+{
+    X509_EXTENSION *ext;
+    STACK_OF(CONF_VALUE) *nval;
+    CONF_VALUE *val;
+    size_t i;
+    if (!(nval = NCONF_get_section(conf, section)))
+        return 0;
+    for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+        val = sk_CONF_VALUE_value(nval, i);
+        if (!(ext = X509V3_EXT_nconf(conf, ctx, val->name, val->value)))
+            return 0;
+        if (sk)
+            X509v3_add_ext(sk, ext, -1);
+        X509_EXTENSION_free(ext);
+    }
+    return 1;
+}
 
-/* Convenience functions to add extensions to a certificate, CRL and request */
+/*
+ * Convenience functions to add extensions to a certificate, CRL and request
+ */
 
 int X509V3_EXT_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section,
-			 X509 *cert)
-	{
-	STACK_OF(X509_EXTENSION) **sk = NULL;
-	if (cert)
-		sk = &cert->cert_info->extensions;
-	return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
-	}
+                         X509 *cert)
+{
+    STACK_OF(X509_EXTENSION) **sk = NULL;
+    if (cert)
+        sk = &cert->cert_info->extensions;
+    return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
+}
 
 /* Same as above but for a CRL */
 
 int X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section,
-			     X509_CRL *crl)
-	{
-	STACK_OF(X509_EXTENSION) **sk = NULL;
-	if (crl)
-		sk = &crl->crl->extensions;
-	return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
-	}
+                             X509_CRL *crl)
+{
+    STACK_OF(X509_EXTENSION) **sk = NULL;
+    if (crl)
+        sk = &crl->crl->extensions;
+    return X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
+}
 
 /* Add extensions to certificate request */
 
 int X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, char *section,
-	     X509_REQ *req)
-	{
-	STACK_OF(X509_EXTENSION) *extlist = NULL, **sk = NULL;
-	int i;
-	if (req)
-		sk = &extlist;
-	i = X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
-	if (!i || !sk)
-		return i;
-	i = X509_REQ_add_extensions(req, extlist);
-	sk_X509_EXTENSION_pop_free(extlist, X509_EXTENSION_free);
-	return i;
-	}
+                             X509_REQ *req)
+{
+    STACK_OF(X509_EXTENSION) *extlist = NULL, **sk = NULL;
+    int i;
+    if (req)
+        sk = &extlist;
+    i = X509V3_EXT_add_nconf_sk(conf, ctx, section, sk);
+    if (!i || !sk)
+        return i;
+    i = X509_REQ_add_extensions(req, extlist);
+    sk_X509_EXTENSION_pop_free(extlist, X509_EXTENSION_free);
+    return i;
+}
 
 /* Config database functions */
 
-char * X509V3_get_string(X509V3_CTX *ctx, char *name, char *section)
-	{
-	if(!ctx->db || !ctx->db_meth || !ctx->db_meth->get_string)
-		{
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_OPERATION_NOT_DEFINED);
-		return NULL;
-		}
-	if (ctx->db_meth->get_string)
-			return ctx->db_meth->get_string(ctx->db, name, section);
-	return NULL;
-	}
+char *X509V3_get_string(X509V3_CTX *ctx, char *name, char *section)
+{
+    if (!ctx->db || !ctx->db_meth || !ctx->db_meth->get_string) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_OPERATION_NOT_DEFINED);
+        return NULL;
+    }
+    if (ctx->db_meth->get_string)
+        return ctx->db_meth->get_string(ctx->db, name, section);
+    return NULL;
+}
 
-STACK_OF(CONF_VALUE) * X509V3_get_section(X509V3_CTX *ctx, char *section)
-	{
-	if(!ctx->db || !ctx->db_meth || !ctx->db_meth->get_section)
-		{
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_OPERATION_NOT_DEFINED);
-		return NULL;
-		}
-	if (ctx->db_meth->get_section)
-			return ctx->db_meth->get_section(ctx->db, section);
-	return NULL;
-	}
+STACK_OF(CONF_VALUE) *X509V3_get_section(X509V3_CTX *ctx, char *section)
+{
+    if (!ctx->db || !ctx->db_meth || !ctx->db_meth->get_section) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_OPERATION_NOT_DEFINED);
+        return NULL;
+    }
+    if (ctx->db_meth->get_section)
+        return ctx->db_meth->get_section(ctx->db, section);
+    return NULL;
+}
 
 void X509V3_string_free(X509V3_CTX *ctx, char *str)
-	{
-	if (!str) return;
-	if (ctx->db_meth->free_string)
-			ctx->db_meth->free_string(ctx->db, str);
-	}
+{
+    if (!str)
+        return;
+    if (ctx->db_meth->free_string)
+        ctx->db_meth->free_string(ctx->db, str);
+}
 
 void X509V3_section_free(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *section)
-	{
-	if (!section) return;
-	if (ctx->db_meth->free_section)
-			ctx->db_meth->free_section(ctx->db, section);
-	}
+{
+    if (!section)
+        return;
+    if (ctx->db_meth->free_section)
+        ctx->db_meth->free_section(ctx->db, section);
+}
 
 static char *nconf_get_string(void *db, char *section, char *value)
-	{
-        /* TODO(fork): this should return a const value. */
-	return (char *) NCONF_get_string(db, section, value);
-	}
+{
+    /* TODO(fork): this should return a const value. */
+    return (char *)NCONF_get_string(db, section, value);
+}
 
 static STACK_OF(CONF_VALUE) *nconf_get_section(void *db, char *section)
-	{
-	return NCONF_get_section(db, section);
-	}
+{
+    return NCONF_get_section(db, section);
+}
 
 static const X509V3_CONF_METHOD nconf_method = {
-nconf_get_string,
-nconf_get_section,
-NULL,
-NULL
+    nconf_get_string,
+    nconf_get_section,
+    NULL,
+    NULL
 };
 
 void X509V3_set_nconf(X509V3_CTX *ctx, CONF *conf)
-	{
-	ctx->db_meth = &nconf_method;
-	ctx->db = conf;
-	}
+{
+    ctx->db_meth = &nconf_method;
+    ctx->db = conf;
+}
 
 void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subj, X509_REQ *req,
-		    X509_CRL *crl, int flags)
-	{
-	ctx->issuer_cert = issuer;
-	ctx->subject_cert = subj;
-	ctx->crl = crl;
-	ctx->subject_req = req;
-	ctx->flags = flags;
-	}
-
+                    X509_CRL *crl, int flags)
+{
+    ctx->issuer_cert = issuer;
+    ctx->subject_cert = subj;
+    ctx->crl = crl;
+    ctx->subject_req = req;
+    ctx->flags = flags;
+}
diff --git a/src/crypto/x509v3/v3_cpols.c b/src/crypto/x509v3/v3_cpols.c
index 0b58676..4def530 100644
--- a/src/crypto/x509v3/v3_cpols.c
+++ b/src/crypto/x509v3/v3_cpols.c
@@ -1,6 +1,7 @@
 /* v3_cpols.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
  */
 /* ====================================================================
  * Copyright (c) 1999-2004 The OpenSSL Project.  All rights reserved.
@@ -10,7 +11,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -72,35 +73,38 @@
 
 /* Certificate policies extension support: this one is a bit complex... */
 
-static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol, BIO *out, int indent);
-static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *value);
-static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals, int indent);
+static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol,
+                       BIO *out, int indent);
+static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method,
+                                         X509V3_CTX *ctx, char *value);
+static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals,
+                             int indent);
 static void print_notice(BIO *out, USERNOTICE *notice, int indent);
 static POLICYINFO *policy_section(X509V3_CTX *ctx,
-				 STACK_OF(CONF_VALUE) *polstrs, int ia5org);
+                                  STACK_OF(CONF_VALUE) *polstrs, int ia5org);
 static POLICYQUALINFO *notice_section(X509V3_CTX *ctx,
-					STACK_OF(CONF_VALUE) *unot, int ia5org);
+                                      STACK_OF(CONF_VALUE) *unot, int ia5org);
 static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos);
 
 const X509V3_EXT_METHOD v3_cpols = {
-NID_certificate_policies, 0,ASN1_ITEM_ref(CERTIFICATEPOLICIES),
-0,0,0,0,
-0,0,
-0,0,
-(X509V3_EXT_I2R)i2r_certpol,
-(X509V3_EXT_R2I)r2i_certpol,
-NULL
+    NID_certificate_policies, 0, ASN1_ITEM_ref(CERTIFICATEPOLICIES),
+    0, 0, 0, 0,
+    0, 0,
+    0, 0,
+    (X509V3_EXT_I2R)i2r_certpol,
+    (X509V3_EXT_R2I)r2i_certpol,
+    NULL
 };
 
-ASN1_ITEM_TEMPLATE(CERTIFICATEPOLICIES) = 
-	ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CERTIFICATEPOLICIES, POLICYINFO)
+ASN1_ITEM_TEMPLATE(CERTIFICATEPOLICIES) =
+        ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CERTIFICATEPOLICIES, POLICYINFO)
 ASN1_ITEM_TEMPLATE_END(CERTIFICATEPOLICIES)
 
 IMPLEMENT_ASN1_FUNCTIONS(CERTIFICATEPOLICIES)
 
 ASN1_SEQUENCE(POLICYINFO) = {
-	ASN1_SIMPLE(POLICYINFO, policyid, ASN1_OBJECT),
-	ASN1_SEQUENCE_OF_OPT(POLICYINFO, qualifiers, POLICYQUALINFO)
+        ASN1_SIMPLE(POLICYINFO, policyid, ASN1_OBJECT),
+        ASN1_SEQUENCE_OF_OPT(POLICYINFO, qualifiers, POLICYQUALINFO)
 } ASN1_SEQUENCE_END(POLICYINFO)
 
 IMPLEMENT_ASN1_FUNCTIONS(POLICYINFO)
@@ -108,368 +112,391 @@
 ASN1_ADB_TEMPLATE(policydefault) = ASN1_SIMPLE(POLICYQUALINFO, d.other, ASN1_ANY);
 
 ASN1_ADB(POLICYQUALINFO) = {
-	ADB_ENTRY(NID_id_qt_cps, ASN1_SIMPLE(POLICYQUALINFO, d.cpsuri, ASN1_IA5STRING)),
-	ADB_ENTRY(NID_id_qt_unotice, ASN1_SIMPLE(POLICYQUALINFO, d.usernotice, USERNOTICE))
+        ADB_ENTRY(NID_id_qt_cps, ASN1_SIMPLE(POLICYQUALINFO, d.cpsuri, ASN1_IA5STRING)),
+        ADB_ENTRY(NID_id_qt_unotice, ASN1_SIMPLE(POLICYQUALINFO, d.usernotice, USERNOTICE))
 } ASN1_ADB_END(POLICYQUALINFO, 0, pqualid, 0, &policydefault_tt, NULL);
 
 ASN1_SEQUENCE(POLICYQUALINFO) = {
-	ASN1_SIMPLE(POLICYQUALINFO, pqualid, ASN1_OBJECT),
-	ASN1_ADB_OBJECT(POLICYQUALINFO)
+        ASN1_SIMPLE(POLICYQUALINFO, pqualid, ASN1_OBJECT),
+        ASN1_ADB_OBJECT(POLICYQUALINFO)
 } ASN1_SEQUENCE_END(POLICYQUALINFO)
 
 IMPLEMENT_ASN1_FUNCTIONS(POLICYQUALINFO)
 
 ASN1_SEQUENCE(USERNOTICE) = {
-	ASN1_OPT(USERNOTICE, noticeref, NOTICEREF),
-	ASN1_OPT(USERNOTICE, exptext, DISPLAYTEXT)
+        ASN1_OPT(USERNOTICE, noticeref, NOTICEREF),
+        ASN1_OPT(USERNOTICE, exptext, DISPLAYTEXT)
 } ASN1_SEQUENCE_END(USERNOTICE)
 
 IMPLEMENT_ASN1_FUNCTIONS(USERNOTICE)
 
 ASN1_SEQUENCE(NOTICEREF) = {
-	ASN1_SIMPLE(NOTICEREF, organization, DISPLAYTEXT),
-	ASN1_SEQUENCE_OF(NOTICEREF, noticenos, ASN1_INTEGER)
+        ASN1_SIMPLE(NOTICEREF, organization, DISPLAYTEXT),
+        ASN1_SEQUENCE_OF(NOTICEREF, noticenos, ASN1_INTEGER)
 } ASN1_SEQUENCE_END(NOTICEREF)
 
 IMPLEMENT_ASN1_FUNCTIONS(NOTICEREF)
 
 static STACK_OF(POLICYINFO) *r2i_certpol(X509V3_EXT_METHOD *method,
-		X509V3_CTX *ctx, char *value)
+                                         X509V3_CTX *ctx, char *value)
 {
-	STACK_OF(POLICYINFO) *pols = NULL;
-	char *pstr;
-	POLICYINFO *pol;
-	ASN1_OBJECT *pobj;
-	STACK_OF(CONF_VALUE) *vals;
-	CONF_VALUE *cnf;
-	size_t i;
-	int ia5org;
-	pols = sk_POLICYINFO_new_null();
-	if (pols == NULL) {
-		OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-		return NULL;
-	}
-	vals =  X509V3_parse_list(value);
-	if (vals == NULL) {
-		OPENSSL_PUT_ERROR(X509V3, ERR_R_X509V3_LIB);
-		goto err;
-	}
-	ia5org = 0;
-	for(i = 0; i < sk_CONF_VALUE_num(vals); i++) {
-		cnf = sk_CONF_VALUE_value(vals, i);
-		if(cnf->value || !cnf->name ) {
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_POLICY_IDENTIFIER);
-			X509V3_conf_err(cnf);
-			goto err;
-		}
-		pstr = cnf->name;
-		if(!strcmp(pstr,"ia5org")) {
-			ia5org = 1;
-			continue;
-		} else if(*pstr == '@') {
-			STACK_OF(CONF_VALUE) *polsect;
-			polsect = X509V3_get_section(ctx, pstr + 1);
-			if(!polsect) {
-				OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SECTION);
+    STACK_OF(POLICYINFO) *pols = NULL;
+    char *pstr;
+    POLICYINFO *pol;
+    ASN1_OBJECT *pobj;
+    STACK_OF(CONF_VALUE) *vals;
+    CONF_VALUE *cnf;
+    size_t i;
+    int ia5org;
+    pols = sk_POLICYINFO_new_null();
+    if (pols == NULL) {
+        OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+    vals = X509V3_parse_list(value);
+    if (vals == NULL) {
+        OPENSSL_PUT_ERROR(X509V3, ERR_R_X509V3_LIB);
+        goto err;
+    }
+    ia5org = 0;
+    for (i = 0; i < sk_CONF_VALUE_num(vals); i++) {
+        cnf = sk_CONF_VALUE_value(vals, i);
+        if (cnf->value || !cnf->name) {
+            OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_POLICY_IDENTIFIER);
+            X509V3_conf_err(cnf);
+            goto err;
+        }
+        pstr = cnf->name;
+        if (!strcmp(pstr, "ia5org")) {
+            ia5org = 1;
+            continue;
+        } else if (*pstr == '@') {
+            STACK_OF(CONF_VALUE) *polsect;
+            polsect = X509V3_get_section(ctx, pstr + 1);
+            if (!polsect) {
+                OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SECTION);
 
-				X509V3_conf_err(cnf);
-				goto err;
-			}
-			pol = policy_section(ctx, polsect, ia5org);
-			X509V3_section_free(ctx, polsect);
-			if(!pol) goto err;
-		} else {
-			if(!(pobj = OBJ_txt2obj(cnf->name, 0))) {
-				OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER);
-				X509V3_conf_err(cnf);
-				goto err;
-			}
-			pol = POLICYINFO_new();
-			pol->policyid = pobj;
-		}
-		if (!sk_POLICYINFO_push(pols, pol)){
-			POLICYINFO_free(pol);
-			OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-			goto err;
-		}
-	}
-	sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
-	return pols;
-	err:
-	sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
-	sk_POLICYINFO_pop_free(pols, POLICYINFO_free);
-	return NULL;
+                X509V3_conf_err(cnf);
+                goto err;
+            }
+            pol = policy_section(ctx, polsect, ia5org);
+            X509V3_section_free(ctx, polsect);
+            if (!pol)
+                goto err;
+        } else {
+            if (!(pobj = OBJ_txt2obj(cnf->name, 0))) {
+                OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER);
+                X509V3_conf_err(cnf);
+                goto err;
+            }
+            pol = POLICYINFO_new();
+            if (pol == NULL) {
+                OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+                ASN1_OBJECT_free(pobj);
+                goto err;
+            }
+            pol->policyid = pobj;
+        }
+        if (!sk_POLICYINFO_push(pols, pol)) {
+            POLICYINFO_free(pol);
+            OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+            goto err;
+        }
+    }
+    sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
+    return pols;
+ err:
+    sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
+    sk_POLICYINFO_pop_free(pols, POLICYINFO_free);
+    return NULL;
 }
 
 static POLICYINFO *policy_section(X509V3_CTX *ctx,
-				STACK_OF(CONF_VALUE) *polstrs, int ia5org)
+                                  STACK_OF(CONF_VALUE) *polstrs, int ia5org)
 {
-	size_t i;
-	CONF_VALUE *cnf;
-	POLICYINFO *pol;
-	POLICYQUALINFO *qual;
-	if(!(pol = POLICYINFO_new())) goto merr;
-	for(i = 0; i < sk_CONF_VALUE_num(polstrs); i++) {
-		cnf = sk_CONF_VALUE_value(polstrs, i);
-		if(!strcmp(cnf->name, "policyIdentifier")) {
-			ASN1_OBJECT *pobj;
-			if(!(pobj = OBJ_txt2obj(cnf->value, 0))) {
-				OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER);
-				X509V3_conf_err(cnf);
-				goto err;
-			}
-			pol->policyid = pobj;
+    size_t i;
+    CONF_VALUE *cnf;
+    POLICYINFO *pol;
+    POLICYQUALINFO *qual;
+    if (!(pol = POLICYINFO_new()))
+        goto merr;
+    for (i = 0; i < sk_CONF_VALUE_num(polstrs); i++) {
+        cnf = sk_CONF_VALUE_value(polstrs, i);
+        if (!strcmp(cnf->name, "policyIdentifier")) {
+            ASN1_OBJECT *pobj;
+            if (!(pobj = OBJ_txt2obj(cnf->value, 0))) {
+                OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER);
+                X509V3_conf_err(cnf);
+                goto err;
+            }
+            pol->policyid = pobj;
 
-		} else if(!name_cmp(cnf->name, "CPS")) {
-			if(!pol->qualifiers) pol->qualifiers =
-						 sk_POLICYQUALINFO_new_null();
-			if(!(qual = POLICYQUALINFO_new())) goto merr;
-			if(!sk_POLICYQUALINFO_push(pol->qualifiers, qual))
-								 goto merr;
-                        /* TODO(fork): const correctness */
-			qual->pqualid = (ASN1_OBJECT*) OBJ_nid2obj(NID_id_qt_cps);
-			if (qual->pqualid == NULL) {
-				OPENSSL_PUT_ERROR(X509V3, ERR_R_INTERNAL_ERROR);
-				goto err;
-			}
-			qual->d.cpsuri = M_ASN1_IA5STRING_new();
-			if (qual->d.cpsuri == NULL) {
-				goto err;
-			}
-			if(!ASN1_STRING_set(qual->d.cpsuri, cnf->value,
-						 strlen(cnf->value))) goto merr;
-		} else if(!name_cmp(cnf->name, "userNotice")) {
-			STACK_OF(CONF_VALUE) *unot;
-			if(*cnf->value != '@') {
-				OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXPECTED_A_SECTION_NAME);
-				X509V3_conf_err(cnf);
-				goto err;
-			}
-			unot = X509V3_get_section(ctx, cnf->value + 1);
-			if(!unot) {
-				OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SECTION);
+        } else if (!name_cmp(cnf->name, "CPS")) {
+            if (!pol->qualifiers)
+                pol->qualifiers = sk_POLICYQUALINFO_new_null();
+            if (!(qual = POLICYQUALINFO_new()))
+                goto merr;
+            if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual))
+                goto merr;
+            /* TODO(fork): const correctness */
+            qual->pqualid = (ASN1_OBJECT *)OBJ_nid2obj(NID_id_qt_cps);
+            if (qual->pqualid == NULL) {
+                OPENSSL_PUT_ERROR(X509V3, ERR_R_INTERNAL_ERROR);
+                goto err;
+            }
+            qual->d.cpsuri = M_ASN1_IA5STRING_new();
+            if (qual->d.cpsuri == NULL) {
+                goto err;
+            }
+            if (!ASN1_STRING_set(qual->d.cpsuri, cnf->value,
+                                 strlen(cnf->value)))
+                goto merr;
+        } else if (!name_cmp(cnf->name, "userNotice")) {
+            STACK_OF(CONF_VALUE) *unot;
+            if (*cnf->value != '@') {
+                OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXPECTED_A_SECTION_NAME);
+                X509V3_conf_err(cnf);
+                goto err;
+            }
+            unot = X509V3_get_section(ctx, cnf->value + 1);
+            if (!unot) {
+                OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SECTION);
 
-				X509V3_conf_err(cnf);
-				goto err;
-			}
-			qual = notice_section(ctx, unot, ia5org);
-			X509V3_section_free(ctx, unot);
-			if(!qual) goto err;
-			if(!pol->qualifiers) pol->qualifiers =
-						 sk_POLICYQUALINFO_new_null();
-			if(!sk_POLICYQUALINFO_push(pol->qualifiers, qual))
-								 goto merr;
-		} else {
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OPTION);
+                X509V3_conf_err(cnf);
+                goto err;
+            }
+            qual = notice_section(ctx, unot, ia5org);
+            X509V3_section_free(ctx, unot);
+            if (!qual)
+                goto err;
+            if (!pol->qualifiers)
+                pol->qualifiers = sk_POLICYQUALINFO_new_null();
+            if (!sk_POLICYQUALINFO_push(pol->qualifiers, qual))
+                goto merr;
+        } else {
+            OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OPTION);
 
-			X509V3_conf_err(cnf);
-			goto err;
-		}
-	}
-	if(!pol->policyid) {
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_POLICY_IDENTIFIER);
-		goto err;
-	}
+            X509V3_conf_err(cnf);
+            goto err;
+        }
+    }
+    if (!pol->policyid) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_POLICY_IDENTIFIER);
+        goto err;
+    }
 
-	return pol;
+    return pol;
 
-	merr:
-	OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ merr:
+    OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
 
-	err:
-	POLICYINFO_free(pol);
-	return NULL;
-	
-	
+ err:
+    POLICYINFO_free(pol);
+    return NULL;
+
 }
 
 static POLICYQUALINFO *notice_section(X509V3_CTX *ctx,
-					STACK_OF(CONF_VALUE) *unot, int ia5org)
+                                      STACK_OF(CONF_VALUE) *unot, int ia5org)
 {
-	size_t i;
-	int ret;
-	CONF_VALUE *cnf;
-	USERNOTICE *not;
-	POLICYQUALINFO *qual;
-	if(!(qual = POLICYQUALINFO_new())) goto merr;
-        /* TODO(fork): const correctness */
-	qual->pqualid = (ASN1_OBJECT *) OBJ_nid2obj(NID_id_qt_unotice);
-	if (qual->pqualid == NULL)
-		{
-		OPENSSL_PUT_ERROR(X509V3, ERR_R_INTERNAL_ERROR);
-		goto err;
-		}
-	if(!(not = USERNOTICE_new())) goto merr;
-	qual->d.usernotice = not;
-	for(i = 0; i < sk_CONF_VALUE_num(unot); i++) {
-		cnf = sk_CONF_VALUE_value(unot, i);
-		if(!strcmp(cnf->name, "explicitText")) {
-			not->exptext = M_ASN1_VISIBLESTRING_new();
-			if (not->exptext == NULL)
-				goto merr;
-			if(!ASN1_STRING_set(not->exptext, cnf->value,
-						 strlen(cnf->value))) goto merr;
-		} else if(!strcmp(cnf->name, "organization")) {
-			NOTICEREF *nref;
-			if(!not->noticeref) {
-				if(!(nref = NOTICEREF_new())) goto merr;
-				not->noticeref = nref;
-			} else nref = not->noticeref;
-			if(ia5org) nref->organization->type = V_ASN1_IA5STRING;
-			else nref->organization->type = V_ASN1_VISIBLESTRING;
-			if(!ASN1_STRING_set(nref->organization, cnf->value,
-						 strlen(cnf->value))) goto merr;
-		} else if(!strcmp(cnf->name, "noticeNumbers")) {
-			NOTICEREF *nref;
-			STACK_OF(CONF_VALUE) *nos;
-			if(!not->noticeref) {
-				if(!(nref = NOTICEREF_new())) goto merr;
-				not->noticeref = nref;
-			} else nref = not->noticeref;
-			nos = X509V3_parse_list(cnf->value);
-			if(!nos || !sk_CONF_VALUE_num(nos)) {
-				OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NUMBERS);
-				X509V3_conf_err(cnf);
-				goto err;
-			}
-			ret = nref_nos(nref->noticenos, nos);
-			sk_CONF_VALUE_pop_free(nos, X509V3_conf_free);
-			if (!ret)
-				goto err;
-		} else {
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OPTION);
-			X509V3_conf_err(cnf);
-			goto err;
-		}
-	}
+    size_t i;
+    int ret;
+    CONF_VALUE *cnf;
+    USERNOTICE *not;
+    POLICYQUALINFO *qual;
+    if (!(qual = POLICYQUALINFO_new()))
+        goto merr;
+    /* TODO(fork): const correctness */
+    qual->pqualid = (ASN1_OBJECT *)OBJ_nid2obj(NID_id_qt_unotice);
+    if (qual->pqualid == NULL) {
+        OPENSSL_PUT_ERROR(X509V3, ERR_R_INTERNAL_ERROR);
+        goto err;
+    }
+    if (!(not = USERNOTICE_new()))
+        goto merr;
+    qual->d.usernotice = not;
+    for (i = 0; i < sk_CONF_VALUE_num(unot); i++) {
+        cnf = sk_CONF_VALUE_value(unot, i);
+        if (!strcmp(cnf->name, "explicitText")) {
+            not->exptext = M_ASN1_VISIBLESTRING_new();
+            if (not->exptext == NULL)
+                goto merr;
+            if (!ASN1_STRING_set(not->exptext, cnf->value,
+                                 strlen(cnf->value)))
+                goto merr;
+        } else if (!strcmp(cnf->name, "organization")) {
+            NOTICEREF *nref;
+            if (!not->noticeref) {
+                if (!(nref = NOTICEREF_new()))
+                    goto merr;
+                not->noticeref = nref;
+            } else
+                nref = not->noticeref;
+            if (ia5org)
+                nref->organization->type = V_ASN1_IA5STRING;
+            else
+                nref->organization->type = V_ASN1_VISIBLESTRING;
+            if (!ASN1_STRING_set(nref->organization, cnf->value,
+                                 strlen(cnf->value)))
+                goto merr;
+        } else if (!strcmp(cnf->name, "noticeNumbers")) {
+            NOTICEREF *nref;
+            STACK_OF(CONF_VALUE) *nos;
+            if (!not->noticeref) {
+                if (!(nref = NOTICEREF_new()))
+                    goto merr;
+                not->noticeref = nref;
+            } else
+                nref = not->noticeref;
+            nos = X509V3_parse_list(cnf->value);
+            if (!nos || !sk_CONF_VALUE_num(nos)) {
+                OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NUMBERS);
+                X509V3_conf_err(cnf);
+                goto err;
+            }
+            ret = nref_nos(nref->noticenos, nos);
+            sk_CONF_VALUE_pop_free(nos, X509V3_conf_free);
+            if (!ret)
+                goto err;
+        } else {
+            OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OPTION);
+            X509V3_conf_err(cnf);
+            goto err;
+        }
+    }
 
-	if(not->noticeref && 
-	      (!not->noticeref->noticenos || !not->noticeref->organization)) {
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_NEED_ORGANIZATION_AND_NUMBERS);
-			goto err;
-	}
+    if (not->noticeref &&
+        (!not->noticeref->noticenos || !not->noticeref->organization)) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_NEED_ORGANIZATION_AND_NUMBERS);
+        goto err;
+    }
 
-	return qual;
+    return qual;
 
-	merr:
-	OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ merr:
+    OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
 
-	err:
-	POLICYQUALINFO_free(qual);
-	return NULL;
+ err:
+    POLICYQUALINFO_free(qual);
+    return NULL;
 }
 
 static int nref_nos(STACK_OF(ASN1_INTEGER) *nnums, STACK_OF(CONF_VALUE) *nos)
 {
-	CONF_VALUE *cnf;
-	ASN1_INTEGER *aint;
+    CONF_VALUE *cnf;
+    ASN1_INTEGER *aint;
 
-	size_t i;
+    size_t i;
 
-	for(i = 0; i < sk_CONF_VALUE_num(nos); i++) {
-		cnf = sk_CONF_VALUE_value(nos, i);
-		if(!(aint = s2i_ASN1_INTEGER(NULL, cnf->name))) {
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NUMBER);
-			goto err;
-		}
-		if(!sk_ASN1_INTEGER_push(nnums, aint)) goto merr;
-	}
-	return 1;
+    for (i = 0; i < sk_CONF_VALUE_num(nos); i++) {
+        cnf = sk_CONF_VALUE_value(nos, i);
+        if (!(aint = s2i_ASN1_INTEGER(NULL, cnf->name))) {
+            OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NUMBER);
+            goto err;
+        }
+        if (!sk_ASN1_INTEGER_push(nnums, aint))
+            goto merr;
+    }
+    return 1;
 
-	merr:
-	OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ merr:
+    ASN1_INTEGER_free(aint);
+    OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
 
-	err:
-	sk_ASN1_INTEGER_pop_free(nnums, ASN1_STRING_free);
-	return 0;
+ err:
+    return 0;
 }
 
-
 static int i2r_certpol(X509V3_EXT_METHOD *method, STACK_OF(POLICYINFO) *pol,
-		BIO *out, int indent)
+                       BIO *out, int indent)
 {
-	size_t i;
-	POLICYINFO *pinfo;
-	/* First print out the policy OIDs */
-	for(i = 0; i < sk_POLICYINFO_num(pol); i++) {
-		pinfo = sk_POLICYINFO_value(pol, i);
-		BIO_printf(out, "%*sPolicy: ", indent, "");
-		i2a_ASN1_OBJECT(out, pinfo->policyid);
-		BIO_puts(out, "\n");
-		if(pinfo->qualifiers)
-			 print_qualifiers(out, pinfo->qualifiers, indent + 2);
-	}
-	return 1;
+    size_t i;
+    POLICYINFO *pinfo;
+    /* First print out the policy OIDs */
+    for (i = 0; i < sk_POLICYINFO_num(pol); i++) {
+        pinfo = sk_POLICYINFO_value(pol, i);
+        BIO_printf(out, "%*sPolicy: ", indent, "");
+        i2a_ASN1_OBJECT(out, pinfo->policyid);
+        BIO_puts(out, "\n");
+        if (pinfo->qualifiers)
+            print_qualifiers(out, pinfo->qualifiers, indent + 2);
+    }
+    return 1;
 }
 
 static void print_qualifiers(BIO *out, STACK_OF(POLICYQUALINFO) *quals,
-		int indent)
+                             int indent)
 {
-	POLICYQUALINFO *qualinfo;
-	size_t i;
-	for(i = 0; i < sk_POLICYQUALINFO_num(quals); i++) {
-		qualinfo = sk_POLICYQUALINFO_value(quals, i);
-		switch(OBJ_obj2nid(qualinfo->pqualid))
-		{
-			case NID_id_qt_cps:
-			BIO_printf(out, "%*sCPS: %s\n", indent, "",
-						qualinfo->d.cpsuri->data);
-			break;
-		
-			case NID_id_qt_unotice:
-			BIO_printf(out, "%*sUser Notice:\n", indent, "");
-			print_notice(out, qualinfo->d.usernotice, indent + 2);
-			break;
+    POLICYQUALINFO *qualinfo;
+    size_t i;
+    for (i = 0; i < sk_POLICYQUALINFO_num(quals); i++) {
+        qualinfo = sk_POLICYQUALINFO_value(quals, i);
+        switch (OBJ_obj2nid(qualinfo->pqualid)) {
+        case NID_id_qt_cps:
+            BIO_printf(out, "%*sCPS: %s\n", indent, "",
+                       qualinfo->d.cpsuri->data);
+            break;
 
-			default:
-			BIO_printf(out, "%*sUnknown Qualifier: ",
-							 indent + 2, "");
-			
-			i2a_ASN1_OBJECT(out, qualinfo->pqualid);
-			BIO_puts(out, "\n");
-			break;
-		}
-	}
+        case NID_id_qt_unotice:
+            BIO_printf(out, "%*sUser Notice:\n", indent, "");
+            print_notice(out, qualinfo->d.usernotice, indent + 2);
+            break;
+
+        default:
+            BIO_printf(out, "%*sUnknown Qualifier: ", indent + 2, "");
+
+            i2a_ASN1_OBJECT(out, qualinfo->pqualid);
+            BIO_puts(out, "\n");
+            break;
+        }
+    }
 }
 
 static void print_notice(BIO *out, USERNOTICE *notice, int indent)
 {
-	size_t i;
-	if(notice->noticeref) {
-		NOTICEREF *ref;
-		ref = notice->noticeref;
-		BIO_printf(out, "%*sOrganization: %s\n", indent, "",
-						 ref->organization->data);
-		BIO_printf(out, "%*sNumber%s: ", indent, "",
-			   sk_ASN1_INTEGER_num(ref->noticenos) > 1 ? "s" : "");
-		for(i = 0; i < sk_ASN1_INTEGER_num(ref->noticenos); i++) {
-			ASN1_INTEGER *num;
-			char *tmp;
-			num = sk_ASN1_INTEGER_value(ref->noticenos, i);
-			if(i) BIO_puts(out, ", ");
-			tmp = i2s_ASN1_INTEGER(NULL, num);
-			BIO_puts(out, tmp);
-			OPENSSL_free(tmp);
-		}
-		BIO_puts(out, "\n");
-	}
-	if(notice->exptext)
-		BIO_printf(out, "%*sExplicit Text: %s\n", indent, "",
-							 notice->exptext->data);
+    size_t i;
+    if (notice->noticeref) {
+        NOTICEREF *ref;
+        ref = notice->noticeref;
+        BIO_printf(out, "%*sOrganization: %s\n", indent, "",
+                   ref->organization->data);
+        BIO_printf(out, "%*sNumber%s: ", indent, "",
+                   sk_ASN1_INTEGER_num(ref->noticenos) > 1 ? "s" : "");
+        for (i = 0; i < sk_ASN1_INTEGER_num(ref->noticenos); i++) {
+            ASN1_INTEGER *num;
+            char *tmp;
+            num = sk_ASN1_INTEGER_value(ref->noticenos, i);
+            if (i)
+                BIO_puts(out, ", ");
+            if (num == NULL)
+                BIO_puts(out, "(null)");
+            else {
+                tmp = i2s_ASN1_INTEGER(NULL, num);
+                if (tmp == NULL)
+                    return;
+                BIO_puts(out, tmp);
+                OPENSSL_free(tmp);
+            }
+        }
+        BIO_puts(out, "\n");
+    }
+    if (notice->exptext)
+        BIO_printf(out, "%*sExplicit Text: %s\n", indent, "",
+                   notice->exptext->data);
 }
 
 void X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent)
-	{
-	const X509_POLICY_DATA *dat = node->data;
+{
+    const X509_POLICY_DATA *dat = node->data;
 
-	BIO_printf(out, "%*sPolicy: ", indent, "");
-			
-	i2a_ASN1_OBJECT(out, dat->valid_policy);
-	BIO_puts(out, "\n");
-	BIO_printf(out, "%*s%s\n", indent + 2, "",
-		node_data_critical(dat) ? "Critical" : "Non Critical");
-	if (dat->qualifier_set)
-		print_qualifiers(out, dat->qualifier_set, indent + 2);
-	else
-		BIO_printf(out, "%*sNo Qualifiers\n", indent + 2, "");
-	}
+    BIO_printf(out, "%*sPolicy: ", indent, "");
+
+    i2a_ASN1_OBJECT(out, dat->valid_policy);
+    BIO_puts(out, "\n");
+    BIO_printf(out, "%*s%s\n", indent + 2, "",
+               node_data_critical(dat) ? "Critical" : "Non Critical");
+    if (dat->qualifier_set)
+        print_qualifiers(out, dat->qualifier_set, indent + 2);
+    else
+        BIO_printf(out, "%*sNo Qualifiers\n", indent + 2, "");
+}
diff --git a/src/crypto/x509v3/v3_crld.c b/src/crypto/x509v3/v3_crld.c
index 3984c31..c93c449 100644
--- a/src/crypto/x509v3/v3_crld.c
+++ b/src/crypto/x509v3/v3_crld.c
@@ -1,6 +1,7 @@
 /* v3_crld.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
  */
 /* ====================================================================
  * Copyright (c) 1999-2008 The OpenSSL Project.  All rights reserved.
@@ -10,7 +11,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -65,552 +66,496 @@
 #include <openssl/obj.h>
 #include <openssl/x509v3.h>
 
-
 static void *v2i_crld(const X509V3_EXT_METHOD *method,
-		      X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
+                      X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
 static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out,
-		     int indent);
+                     int indent);
 
-const X509V3_EXT_METHOD v3_crld =
-	{
-	NID_crl_distribution_points, 0, ASN1_ITEM_ref(CRL_DIST_POINTS),
-	0,0,0,0,
-	0,0,
-	0,
-	v2i_crld,
-	i2r_crldp,0,
-	NULL
-	};
+const X509V3_EXT_METHOD v3_crld = {
+    NID_crl_distribution_points, 0, ASN1_ITEM_ref(CRL_DIST_POINTS),
+    0, 0, 0, 0,
+    0, 0,
+    0,
+    v2i_crld,
+    i2r_crldp, 0,
+    NULL
+};
 
-const X509V3_EXT_METHOD v3_freshest_crl =
-	{
-	NID_freshest_crl, 0, ASN1_ITEM_ref(CRL_DIST_POINTS),
-	0,0,0,0,
-	0,0,
-	0,
-	v2i_crld,
-	i2r_crldp,0,
-	NULL
-	};
+const X509V3_EXT_METHOD v3_freshest_crl = {
+    NID_freshest_crl, 0, ASN1_ITEM_ref(CRL_DIST_POINTS),
+    0, 0, 0, 0,
+    0, 0,
+    0,
+    v2i_crld,
+    i2r_crldp, 0,
+    NULL
+};
 
-static STACK_OF(GENERAL_NAME) *gnames_from_sectname(X509V3_CTX *ctx, char *sect)
-	{
-	STACK_OF(CONF_VALUE) *gnsect;
-	STACK_OF(GENERAL_NAME) *gens;
-	if (*sect == '@')
-		gnsect = X509V3_get_section(ctx, sect + 1);
-	else
-		gnsect = X509V3_parse_list(sect);
-	if (!gnsect)
-		{
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND);
-		return NULL;
-		}
-	gens = v2i_GENERAL_NAMES(NULL, ctx, gnsect);
-	if (*sect == '@')
-		X509V3_section_free(ctx, gnsect);
-	else
-		sk_CONF_VALUE_pop_free(gnsect, X509V3_conf_free);
-	return gens;
-	}
+static STACK_OF(GENERAL_NAME) *gnames_from_sectname(X509V3_CTX *ctx,
+                                                    char *sect)
+{
+    STACK_OF(CONF_VALUE) *gnsect;
+    STACK_OF(GENERAL_NAME) *gens;
+    if (*sect == '@')
+        gnsect = X509V3_get_section(ctx, sect + 1);
+    else
+        gnsect = X509V3_parse_list(sect);
+    if (!gnsect) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND);
+        return NULL;
+    }
+    gens = v2i_GENERAL_NAMES(NULL, ctx, gnsect);
+    if (*sect == '@')
+        X509V3_section_free(ctx, gnsect);
+    else
+        sk_CONF_VALUE_pop_free(gnsect, X509V3_conf_free);
+    return gens;
+}
 
 static int set_dist_point_name(DIST_POINT_NAME **pdp, X509V3_CTX *ctx,
-							CONF_VALUE *cnf)
-	{
-	STACK_OF(GENERAL_NAME) *fnm = NULL;
-	STACK_OF(X509_NAME_ENTRY) *rnm = NULL;
-	if (!strncmp(cnf->name, "fullname", 9))
-		{
-		fnm = gnames_from_sectname(ctx, cnf->value);
-		if (!fnm)
-			goto err;
-		}
-	else if (!strcmp(cnf->name, "relativename"))
-		{
-		int ret;
-		STACK_OF(CONF_VALUE) *dnsect;
-		X509_NAME *nm;
-		nm = X509_NAME_new();
-		if (!nm)
-			return -1;
-		dnsect = X509V3_get_section(ctx, cnf->value);
-		if (!dnsect)
-			{
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND);
-			return -1;
-			}
-		ret = X509V3_NAME_from_section(nm, dnsect, MBSTRING_ASC);
-		X509V3_section_free(ctx, dnsect);
-		rnm = nm->entries;
-		nm->entries = NULL;
-		X509_NAME_free(nm);
-		if (!ret || sk_X509_NAME_ENTRY_num(rnm) <= 0)
-			goto err;
-		/* Since its a name fragment can't have more than one
-		 * RDNSequence
-		 */
-		if (sk_X509_NAME_ENTRY_value(rnm,
-				sk_X509_NAME_ENTRY_num(rnm) - 1)->set)
-			{
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_MULTIPLE_RDNS);
-			goto err;
-			}
-		}
-	else
-		return 0;
+                               CONF_VALUE *cnf)
+{
+    STACK_OF(GENERAL_NAME) *fnm = NULL;
+    STACK_OF(X509_NAME_ENTRY) *rnm = NULL;
+    if (!strncmp(cnf->name, "fullname", 9)) {
+        fnm = gnames_from_sectname(ctx, cnf->value);
+        if (!fnm)
+            goto err;
+    } else if (!strcmp(cnf->name, "relativename")) {
+        int ret;
+        STACK_OF(CONF_VALUE) *dnsect;
+        X509_NAME *nm;
+        nm = X509_NAME_new();
+        if (!nm)
+            return -1;
+        dnsect = X509V3_get_section(ctx, cnf->value);
+        if (!dnsect) {
+            OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND);
+            return -1;
+        }
+        ret = X509V3_NAME_from_section(nm, dnsect, MBSTRING_ASC);
+        X509V3_section_free(ctx, dnsect);
+        rnm = nm->entries;
+        nm->entries = NULL;
+        X509_NAME_free(nm);
+        if (!ret || sk_X509_NAME_ENTRY_num(rnm) <= 0)
+            goto err;
+        /*
+         * Since its a name fragment can't have more than one RDNSequence
+         */
+        if (sk_X509_NAME_ENTRY_value(rnm,
+                                     sk_X509_NAME_ENTRY_num(rnm) - 1)->set) {
+            OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_MULTIPLE_RDNS);
+            goto err;
+        }
+    } else
+        return 0;
 
-	if (*pdp)
-		{
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_DISTPOINT_ALREADY_SET);
-		goto err;
-		}
+    if (*pdp) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_DISTPOINT_ALREADY_SET);
+        goto err;
+    }
 
-	*pdp = DIST_POINT_NAME_new();
-	if (!*pdp)
-		goto err;
-	if (fnm)
-		{
-		(*pdp)->type = 0;
-		(*pdp)->name.fullname = fnm;
-		}
-	else
-		{
-		(*pdp)->type = 1;
-		(*pdp)->name.relativename = rnm;
-		}
+    *pdp = DIST_POINT_NAME_new();
+    if (!*pdp)
+        goto err;
+    if (fnm) {
+        (*pdp)->type = 0;
+        (*pdp)->name.fullname = fnm;
+    } else {
+        (*pdp)->type = 1;
+        (*pdp)->name.relativename = rnm;
+    }
 
-	return 1;
-		
-	err:
-	if (fnm)
-		sk_GENERAL_NAME_pop_free(fnm, GENERAL_NAME_free);
-	if (rnm)
-		sk_X509_NAME_ENTRY_pop_free(rnm, X509_NAME_ENTRY_free);
-	return -1;
-	}
+    return 1;
+
+ err:
+    if (fnm)
+        sk_GENERAL_NAME_pop_free(fnm, GENERAL_NAME_free);
+    if (rnm)
+        sk_X509_NAME_ENTRY_pop_free(rnm, X509_NAME_ENTRY_free);
+    return -1;
+}
 
 static const BIT_STRING_BITNAME reason_flags[] = {
-{0, "Unused", "unused"},
-{1, "Key Compromise", "keyCompromise"},
-{2, "CA Compromise", "CACompromise"},
-{3, "Affiliation Changed", "affiliationChanged"},
-{4, "Superseded", "superseded"},
-{5, "Cessation Of Operation", "cessationOfOperation"},
-{6, "Certificate Hold", "certificateHold"},
-{7, "Privilege Withdrawn", "privilegeWithdrawn"},
-{8, "AA Compromise", "AACompromise"},
-{-1, NULL, NULL}
+    {0, "Unused", "unused"},
+    {1, "Key Compromise", "keyCompromise"},
+    {2, "CA Compromise", "CACompromise"},
+    {3, "Affiliation Changed", "affiliationChanged"},
+    {4, "Superseded", "superseded"},
+    {5, "Cessation Of Operation", "cessationOfOperation"},
+    {6, "Certificate Hold", "certificateHold"},
+    {7, "Privilege Withdrawn", "privilegeWithdrawn"},
+    {8, "AA Compromise", "AACompromise"},
+    {-1, NULL, NULL}
 };
 
 static int set_reasons(ASN1_BIT_STRING **preas, char *value)
-	{
-	STACK_OF(CONF_VALUE) *rsk = NULL;
-	const BIT_STRING_BITNAME *pbn;
-	const char *bnam;
-	size_t i;
-	int ret = 0;
-	rsk = X509V3_parse_list(value);
-	if (!rsk)
-		return 0;
-	if (*preas)
-		return 0;
-	for (i = 0; i < sk_CONF_VALUE_num(rsk); i++)
-		{
-		bnam = sk_CONF_VALUE_value(rsk, i)->name;
-		if (!*preas)
-			{
-			*preas = ASN1_BIT_STRING_new();
-			if (!*preas)
-				goto err;
-			}
-		for (pbn = reason_flags; pbn->lname; pbn++)
-			{
-			if (!strcmp(pbn->sname, bnam))
-				{
-				if (!ASN1_BIT_STRING_set_bit(*preas,
-							pbn->bitnum, 1))
-					goto err;
-				break;
-				}
-			}
-		if (!pbn->lname)
-			goto err;
-		}
-	ret = 1;
+{
+    STACK_OF(CONF_VALUE) *rsk = NULL;
+    const BIT_STRING_BITNAME *pbn;
+    const char *bnam;
+    size_t i;
+    int ret = 0;
+    rsk = X509V3_parse_list(value);
+    if (!rsk)
+        return 0;
+    if (*preas)
+        return 0;
+    for (i = 0; i < sk_CONF_VALUE_num(rsk); i++) {
+        bnam = sk_CONF_VALUE_value(rsk, i)->name;
+        if (!*preas) {
+            *preas = ASN1_BIT_STRING_new();
+            if (!*preas)
+                goto err;
+        }
+        for (pbn = reason_flags; pbn->lname; pbn++) {
+            if (!strcmp(pbn->sname, bnam)) {
+                if (!ASN1_BIT_STRING_set_bit(*preas, pbn->bitnum, 1))
+                    goto err;
+                break;
+            }
+        }
+        if (!pbn->lname)
+            goto err;
+    }
+    ret = 1;
 
-	err:
-	sk_CONF_VALUE_pop_free(rsk, X509V3_conf_free);
-	return ret;
-	}
+ err:
+    sk_CONF_VALUE_pop_free(rsk, X509V3_conf_free);
+    return ret;
+}
 
 static int print_reasons(BIO *out, const char *rname,
-			ASN1_BIT_STRING *rflags, int indent)
-	{
-	int first = 1;
-	const BIT_STRING_BITNAME *pbn;
-	BIO_printf(out, "%*s%s:\n%*s", indent, "", rname, indent + 2, "");
-	for (pbn = reason_flags; pbn->lname; pbn++)
-		{
-		if (ASN1_BIT_STRING_get_bit(rflags, pbn->bitnum))
-			{
-			if (first)
-				first = 0;
-			else
-				BIO_puts(out, ", ");
-			BIO_puts(out, pbn->lname);
-			}
-		}
-	if (first)
-		BIO_puts(out, "<EMPTY>\n");
-	else
-		BIO_puts(out, "\n");
-	return 1;
-	}
+                         ASN1_BIT_STRING *rflags, int indent)
+{
+    int first = 1;
+    const BIT_STRING_BITNAME *pbn;
+    BIO_printf(out, "%*s%s:\n%*s", indent, "", rname, indent + 2, "");
+    for (pbn = reason_flags; pbn->lname; pbn++) {
+        if (ASN1_BIT_STRING_get_bit(rflags, pbn->bitnum)) {
+            if (first)
+                first = 0;
+            else
+                BIO_puts(out, ", ");
+            BIO_puts(out, pbn->lname);
+        }
+    }
+    if (first)
+        BIO_puts(out, "<EMPTY>\n");
+    else
+        BIO_puts(out, "\n");
+    return 1;
+}
 
 static DIST_POINT *crldp_from_section(X509V3_CTX *ctx,
-						STACK_OF(CONF_VALUE) *nval)
-	{
-	size_t i;
-	CONF_VALUE *cnf;
-	DIST_POINT *point = NULL;
-	point = DIST_POINT_new();
-	if (!point)
-		goto err;
-	for(i = 0; i < sk_CONF_VALUE_num(nval); i++)
-		{
-		int ret;
-		cnf = sk_CONF_VALUE_value(nval, i);
-		ret = set_dist_point_name(&point->distpoint, ctx, cnf);
-		if (ret > 0)
-			continue;
-		if (ret < 0)
-			goto err;
-		if (!strcmp(cnf->name, "reasons"))
-			{
-			if (!set_reasons(&point->reasons, cnf->value))
-				goto err;
-			}
-		else if (!strcmp(cnf->name, "CRLissuer"))
-			{
-			point->CRLissuer =
-				gnames_from_sectname(ctx, cnf->value);
-			if (!point->CRLissuer)
-				goto err;
-			}
-		}
+                                      STACK_OF(CONF_VALUE) *nval)
+{
+    size_t i;
+    CONF_VALUE *cnf;
+    DIST_POINT *point = NULL;
+    point = DIST_POINT_new();
+    if (!point)
+        goto err;
+    for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+        int ret;
+        cnf = sk_CONF_VALUE_value(nval, i);
+        ret = set_dist_point_name(&point->distpoint, ctx, cnf);
+        if (ret > 0)
+            continue;
+        if (ret < 0)
+            goto err;
+        if (!strcmp(cnf->name, "reasons")) {
+            if (!set_reasons(&point->reasons, cnf->value))
+                goto err;
+        } else if (!strcmp(cnf->name, "CRLissuer")) {
+            point->CRLissuer = gnames_from_sectname(ctx, cnf->value);
+            if (!point->CRLissuer)
+                goto err;
+        }
+    }
 
-	return point;
-			
+    return point;
 
-	err:
-	if (point)
-		DIST_POINT_free(point);
-	return NULL;
-	}
+ err:
+    if (point)
+        DIST_POINT_free(point);
+    return NULL;
+}
 
 static void *v2i_crld(const X509V3_EXT_METHOD *method,
-		      X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
-	{
-	STACK_OF(DIST_POINT) *crld = NULL;
-	GENERAL_NAMES *gens = NULL;
-	GENERAL_NAME *gen = NULL;
-	CONF_VALUE *cnf;
-	size_t i;
-	if(!(crld = sk_DIST_POINT_new_null())) goto merr;
-	for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
-		DIST_POINT *point;
-		cnf = sk_CONF_VALUE_value(nval, i);
-		if (!cnf->value)
-			{
-			STACK_OF(CONF_VALUE) *dpsect;
-			dpsect = X509V3_get_section(ctx, cnf->name);
-			if (!dpsect)
-				goto err;
-			point = crldp_from_section(ctx, dpsect);
-			X509V3_section_free(ctx, dpsect);
-			if (!point)
-				goto err;
-			if(!sk_DIST_POINT_push(crld, point))
-				{
-				DIST_POINT_free(point);
-				goto merr;
-				}
-			}
-		else
-			{
-			if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
-				goto err; 
-			if(!(gens = GENERAL_NAMES_new()))
-				goto merr;
-			if(!sk_GENERAL_NAME_push(gens, gen))
-				goto merr;
-			gen = NULL;
-			if(!(point = DIST_POINT_new()))
-				goto merr;
-			if(!sk_DIST_POINT_push(crld, point))
-				{
-				DIST_POINT_free(point);
-				goto merr;
-				}
-			if(!(point->distpoint = DIST_POINT_NAME_new()))
-				goto merr;
-			point->distpoint->name.fullname = gens;
-			point->distpoint->type = 0;
-			gens = NULL;
-			}
-	}
-	return crld;
+                      X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
+{
+    STACK_OF(DIST_POINT) *crld = NULL;
+    GENERAL_NAMES *gens = NULL;
+    GENERAL_NAME *gen = NULL;
+    CONF_VALUE *cnf;
+    size_t i;
+    if (!(crld = sk_DIST_POINT_new_null()))
+        goto merr;
+    for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+        DIST_POINT *point;
+        cnf = sk_CONF_VALUE_value(nval, i);
+        if (!cnf->value) {
+            STACK_OF(CONF_VALUE) *dpsect;
+            dpsect = X509V3_get_section(ctx, cnf->name);
+            if (!dpsect)
+                goto err;
+            point = crldp_from_section(ctx, dpsect);
+            X509V3_section_free(ctx, dpsect);
+            if (!point)
+                goto err;
+            if (!sk_DIST_POINT_push(crld, point)) {
+                DIST_POINT_free(point);
+                goto merr;
+            }
+        } else {
+            if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
+                goto err;
+            if (!(gens = GENERAL_NAMES_new()))
+                goto merr;
+            if (!sk_GENERAL_NAME_push(gens, gen))
+                goto merr;
+            gen = NULL;
+            if (!(point = DIST_POINT_new()))
+                goto merr;
+            if (!sk_DIST_POINT_push(crld, point)) {
+                DIST_POINT_free(point);
+                goto merr;
+            }
+            if (!(point->distpoint = DIST_POINT_NAME_new()))
+                goto merr;
+            point->distpoint->name.fullname = gens;
+            point->distpoint->type = 0;
+            gens = NULL;
+        }
+    }
+    return crld;
 
-	merr:
-	OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-	err:
-	GENERAL_NAME_free(gen);
-	GENERAL_NAMES_free(gens);
-	sk_DIST_POINT_pop_free(crld, DIST_POINT_free);
-	return NULL;
+ merr:
+    OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ err:
+    GENERAL_NAME_free(gen);
+    GENERAL_NAMES_free(gens);
+    sk_DIST_POINT_pop_free(crld, DIST_POINT_free);
+    return NULL;
 }
 
 IMPLEMENT_ASN1_SET_OF(DIST_POINT)
 
 static int dpn_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
-								void *exarg)
-	{
-	DIST_POINT_NAME *dpn = (DIST_POINT_NAME *)*pval;
+                  void *exarg)
+{
+    DIST_POINT_NAME *dpn = (DIST_POINT_NAME *)*pval;
 
-	switch(operation)
-		{
-		case ASN1_OP_NEW_POST:
-		dpn->dpname = NULL;
-		break;
+    switch (operation) {
+    case ASN1_OP_NEW_POST:
+        dpn->dpname = NULL;
+        break;
 
-		case ASN1_OP_FREE_POST:
-		if (dpn->dpname)
-			X509_NAME_free(dpn->dpname);
-		break;
-		}
-	return 1;
-	}
+    case ASN1_OP_FREE_POST:
+        if (dpn->dpname)
+            X509_NAME_free(dpn->dpname);
+        break;
+    }
+    return 1;
+}
 
 
 ASN1_CHOICE_cb(DIST_POINT_NAME, dpn_cb) = {
-	ASN1_IMP_SEQUENCE_OF(DIST_POINT_NAME, name.fullname, GENERAL_NAME, 0),
-	ASN1_IMP_SET_OF(DIST_POINT_NAME, name.relativename, X509_NAME_ENTRY, 1)
+        ASN1_IMP_SEQUENCE_OF(DIST_POINT_NAME, name.fullname, GENERAL_NAME, 0),
+        ASN1_IMP_SET_OF(DIST_POINT_NAME, name.relativename, X509_NAME_ENTRY, 1)
 } ASN1_CHOICE_END_cb(DIST_POINT_NAME, DIST_POINT_NAME, type)
 
 
 IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT_NAME)
 
 ASN1_SEQUENCE(DIST_POINT) = {
-	ASN1_EXP_OPT(DIST_POINT, distpoint, DIST_POINT_NAME, 0),
-	ASN1_IMP_OPT(DIST_POINT, reasons, ASN1_BIT_STRING, 1),
-	ASN1_IMP_SEQUENCE_OF_OPT(DIST_POINT, CRLissuer, GENERAL_NAME, 2)
+        ASN1_EXP_OPT(DIST_POINT, distpoint, DIST_POINT_NAME, 0),
+        ASN1_IMP_OPT(DIST_POINT, reasons, ASN1_BIT_STRING, 1),
+        ASN1_IMP_SEQUENCE_OF_OPT(DIST_POINT, CRLissuer, GENERAL_NAME, 2)
 } ASN1_SEQUENCE_END(DIST_POINT)
 
 IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT)
 
-ASN1_ITEM_TEMPLATE(CRL_DIST_POINTS) = 
-	ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CRLDistributionPoints, DIST_POINT)
+ASN1_ITEM_TEMPLATE(CRL_DIST_POINTS) =
+        ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CRLDistributionPoints, DIST_POINT)
 ASN1_ITEM_TEMPLATE_END(CRL_DIST_POINTS)
 
 IMPLEMENT_ASN1_FUNCTIONS(CRL_DIST_POINTS)
 
 ASN1_SEQUENCE(ISSUING_DIST_POINT) = {
-	ASN1_EXP_OPT(ISSUING_DIST_POINT, distpoint, DIST_POINT_NAME, 0),
-	ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyuser, ASN1_FBOOLEAN, 1),
-	ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyCA, ASN1_FBOOLEAN, 2),
-	ASN1_IMP_OPT(ISSUING_DIST_POINT, onlysomereasons, ASN1_BIT_STRING, 3),
-	ASN1_IMP_OPT(ISSUING_DIST_POINT, indirectCRL, ASN1_FBOOLEAN, 4),
-	ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyattr, ASN1_FBOOLEAN, 5)
+        ASN1_EXP_OPT(ISSUING_DIST_POINT, distpoint, DIST_POINT_NAME, 0),
+        ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyuser, ASN1_FBOOLEAN, 1),
+        ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyCA, ASN1_FBOOLEAN, 2),
+        ASN1_IMP_OPT(ISSUING_DIST_POINT, onlysomereasons, ASN1_BIT_STRING, 3),
+        ASN1_IMP_OPT(ISSUING_DIST_POINT, indirectCRL, ASN1_FBOOLEAN, 4),
+        ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyattr, ASN1_FBOOLEAN, 5)
 } ASN1_SEQUENCE_END(ISSUING_DIST_POINT)
 
 IMPLEMENT_ASN1_FUNCTIONS(ISSUING_DIST_POINT)
 
 static int i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out,
-		   int indent);
+                   int indent);
 static void *v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
-		     STACK_OF(CONF_VALUE) *nval);
+                     STACK_OF(CONF_VALUE) *nval);
 
-const X509V3_EXT_METHOD v3_idp =
-	{
-	NID_issuing_distribution_point, X509V3_EXT_MULTILINE,
-	ASN1_ITEM_ref(ISSUING_DIST_POINT),
-	0,0,0,0,
-	0,0,
-	0,
-	v2i_idp,
-	i2r_idp,0,
-	NULL
-	};
+const X509V3_EXT_METHOD v3_idp = {
+    NID_issuing_distribution_point, X509V3_EXT_MULTILINE,
+    ASN1_ITEM_ref(ISSUING_DIST_POINT),
+    0, 0, 0, 0,
+    0, 0,
+    0,
+    v2i_idp,
+    i2r_idp, 0,
+    NULL
+};
 
 static void *v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
-		     STACK_OF(CONF_VALUE) *nval)
-	{
-	ISSUING_DIST_POINT *idp = NULL;
-	CONF_VALUE *cnf;
-	char *name, *val;
-	size_t i;
-	int ret;
-	idp = ISSUING_DIST_POINT_new();
-	if (!idp)
-		goto merr;
-	for(i = 0; i < sk_CONF_VALUE_num(nval); i++)
-		{
-		cnf = sk_CONF_VALUE_value(nval, i);
-		name = cnf->name;
-		val = cnf->value;
-		ret = set_dist_point_name(&idp->distpoint, ctx, cnf);
-		if (ret > 0)
-			continue;
-		if (ret < 0)
-			goto err;
-		if (!strcmp(name, "onlyuser"))
-			{
-			if (!X509V3_get_value_bool(cnf, &idp->onlyuser))
-				goto err;
-			}
-		else if (!strcmp(name, "onlyCA"))
-			{
-			if (!X509V3_get_value_bool(cnf, &idp->onlyCA))
-				goto err;
-			}
-		else if (!strcmp(name, "onlyAA"))
-			{
-			if (!X509V3_get_value_bool(cnf, &idp->onlyattr))
-				goto err;
-			}
-		else if (!strcmp(name, "indirectCRL"))
-			{
-			if (!X509V3_get_value_bool(cnf, &idp->indirectCRL))
-				goto err;
-			}
-		else if (!strcmp(name, "onlysomereasons"))
-			{
-			if (!set_reasons(&idp->onlysomereasons, val))
-				goto err;
-			}
-		else
-			{
-                        OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NAME);
-                        X509V3_conf_err(cnf);
-                        goto err;
-			}
-		}
-	return idp;
+                     STACK_OF(CONF_VALUE) *nval)
+{
+    ISSUING_DIST_POINT *idp = NULL;
+    CONF_VALUE *cnf;
+    char *name, *val;
+    size_t i;
+    int ret;
+    idp = ISSUING_DIST_POINT_new();
+    if (!idp)
+        goto merr;
+    for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+        cnf = sk_CONF_VALUE_value(nval, i);
+        name = cnf->name;
+        val = cnf->value;
+        ret = set_dist_point_name(&idp->distpoint, ctx, cnf);
+        if (ret > 0)
+            continue;
+        if (ret < 0)
+            goto err;
+        if (!strcmp(name, "onlyuser")) {
+            if (!X509V3_get_value_bool(cnf, &idp->onlyuser))
+                goto err;
+        } else if (!strcmp(name, "onlyCA")) {
+            if (!X509V3_get_value_bool(cnf, &idp->onlyCA))
+                goto err;
+        } else if (!strcmp(name, "onlyAA")) {
+            if (!X509V3_get_value_bool(cnf, &idp->onlyattr))
+                goto err;
+        } else if (!strcmp(name, "indirectCRL")) {
+            if (!X509V3_get_value_bool(cnf, &idp->indirectCRL))
+                goto err;
+        } else if (!strcmp(name, "onlysomereasons")) {
+            if (!set_reasons(&idp->onlysomereasons, val))
+                goto err;
+        } else {
+            OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NAME);
+            X509V3_conf_err(cnf);
+            goto err;
+        }
+    }
+    return idp;
 
-	merr:
-	OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-	err:
-	ISSUING_DIST_POINT_free(idp);
-	return NULL;
-	}
+ merr:
+    OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ err:
+    ISSUING_DIST_POINT_free(idp);
+    return NULL;
+}
 
 static int print_gens(BIO *out, STACK_OF(GENERAL_NAME) *gens, int indent)
-	{
-	size_t i;
-	for (i = 0; i < sk_GENERAL_NAME_num(gens); i++)
-		{
-		BIO_printf(out, "%*s", indent + 2, "");
-		GENERAL_NAME_print(out, sk_GENERAL_NAME_value(gens, i));
-		BIO_puts(out, "\n");
-		}
-	return 1;
-	}
+{
+    size_t i;
+    for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
+        BIO_printf(out, "%*s", indent + 2, "");
+        GENERAL_NAME_print(out, sk_GENERAL_NAME_value(gens, i));
+        BIO_puts(out, "\n");
+    }
+    return 1;
+}
 
 static int print_distpoint(BIO *out, DIST_POINT_NAME *dpn, int indent)
-	{
-	if (dpn->type == 0)
-		{
-		BIO_printf(out, "%*sFull Name:\n", indent, "");
-		print_gens(out, dpn->name.fullname, indent);
-		}
-	else
-		{
-		X509_NAME ntmp;
-		ntmp.entries = dpn->name.relativename;
-		BIO_printf(out, "%*sRelative Name:\n%*s",
-						indent, "", indent + 2, "");
-		X509_NAME_print_ex(out, &ntmp, 0, XN_FLAG_ONELINE);
-		BIO_puts(out, "\n");
-		}
-	return 1;
-	}
+{
+    if (dpn->type == 0) {
+        BIO_printf(out, "%*sFull Name:\n", indent, "");
+        print_gens(out, dpn->name.fullname, indent);
+    } else {
+        X509_NAME ntmp;
+        ntmp.entries = dpn->name.relativename;
+        BIO_printf(out, "%*sRelative Name:\n%*s", indent, "", indent + 2, "");
+        X509_NAME_print_ex(out, &ntmp, 0, XN_FLAG_ONELINE);
+        BIO_puts(out, "\n");
+    }
+    return 1;
+}
 
 static int i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out,
-		   int indent)
-	{
-	ISSUING_DIST_POINT *idp = pidp;
-	if (idp->distpoint)
-		print_distpoint(out, idp->distpoint, indent);
-	if (idp->onlyuser > 0)
-		BIO_printf(out, "%*sOnly User Certificates\n", indent, "");
-	if (idp->onlyCA > 0)
-		BIO_printf(out, "%*sOnly CA Certificates\n", indent, "");
-	if (idp->indirectCRL > 0)
-		BIO_printf(out, "%*sIndirect CRL\n", indent, "");
-	if (idp->onlysomereasons)
-		print_reasons(out, "Only Some Reasons", 
-				idp->onlysomereasons, indent);
-	if (idp->onlyattr > 0)
-		BIO_printf(out, "%*sOnly Attribute Certificates\n", indent, "");
-	if (!idp->distpoint && (idp->onlyuser <= 0) && (idp->onlyCA <= 0)
-		&& (idp->indirectCRL <= 0) && !idp->onlysomereasons
-		&& (idp->onlyattr <= 0))
-		BIO_printf(out, "%*s<EMPTY>\n", indent, "");
-		
-	return 1;
-	}
+                   int indent)
+{
+    ISSUING_DIST_POINT *idp = pidp;
+    if (idp->distpoint)
+        print_distpoint(out, idp->distpoint, indent);
+    if (idp->onlyuser > 0)
+        BIO_printf(out, "%*sOnly User Certificates\n", indent, "");
+    if (idp->onlyCA > 0)
+        BIO_printf(out, "%*sOnly CA Certificates\n", indent, "");
+    if (idp->indirectCRL > 0)
+        BIO_printf(out, "%*sIndirect CRL\n", indent, "");
+    if (idp->onlysomereasons)
+        print_reasons(out, "Only Some Reasons", idp->onlysomereasons, indent);
+    if (idp->onlyattr > 0)
+        BIO_printf(out, "%*sOnly Attribute Certificates\n", indent, "");
+    if (!idp->distpoint && (idp->onlyuser <= 0) && (idp->onlyCA <= 0)
+        && (idp->indirectCRL <= 0) && !idp->onlysomereasons
+        && (idp->onlyattr <= 0))
+        BIO_printf(out, "%*s<EMPTY>\n", indent, "");
+
+    return 1;
+}
 
 static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out,
-		     int indent)
-	{
-	STACK_OF(DIST_POINT) *crld = pcrldp;
-	DIST_POINT *point;
-	size_t i;
-	for(i = 0; i < sk_DIST_POINT_num(crld); i++)
-		{
-		BIO_puts(out, "\n");
-		point = sk_DIST_POINT_value(crld, i);
-		if(point->distpoint)
-			print_distpoint(out, point->distpoint, indent);
-		if(point->reasons) 
-			print_reasons(out, "Reasons", point->reasons,
-								indent);
-		if(point->CRLissuer)
-			{
-			BIO_printf(out, "%*sCRL Issuer:\n", indent, "");
-			print_gens(out, point->CRLissuer, indent);
-			}
-		}
-	return 1;
-	}
+                     int indent)
+{
+    STACK_OF(DIST_POINT) *crld = pcrldp;
+    DIST_POINT *point;
+    size_t i;
+    for (i = 0; i < sk_DIST_POINT_num(crld); i++) {
+        BIO_puts(out, "\n");
+        point = sk_DIST_POINT_value(crld, i);
+        if (point->distpoint)
+            print_distpoint(out, point->distpoint, indent);
+        if (point->reasons)
+            print_reasons(out, "Reasons", point->reasons, indent);
+        if (point->CRLissuer) {
+            BIO_printf(out, "%*sCRL Issuer:\n", indent, "");
+            print_gens(out, point->CRLissuer, indent);
+        }
+    }
+    return 1;
+}
 
 int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, X509_NAME *iname)
-	{
-	size_t i;
-	STACK_OF(X509_NAME_ENTRY) *frag;
-	X509_NAME_ENTRY *ne;
-	if (!dpn || (dpn->type != 1))
-		return 1;
-	frag = dpn->name.relativename;
-	dpn->dpname = X509_NAME_dup(iname);
-	if (!dpn->dpname)
-		return 0;
-	for (i = 0; i < sk_X509_NAME_ENTRY_num(frag); i++)
-		{
-		ne = sk_X509_NAME_ENTRY_value(frag, i);
-		if (!X509_NAME_add_entry(dpn->dpname, ne, -1, i ? 0 : 1))
-			{
-			X509_NAME_free(dpn->dpname);
-			dpn->dpname = NULL;
-			return 0;
-			}
-		}
-	/* generate cached encoding of name */
-	if (i2d_X509_NAME(dpn->dpname, NULL) < 0)
-		{
-		X509_NAME_free(dpn->dpname);
-		dpn->dpname = NULL;
-		return 0;
-		}
-	return 1;
-	}
+{
+    size_t i;
+    STACK_OF(X509_NAME_ENTRY) *frag;
+    X509_NAME_ENTRY *ne;
+    if (!dpn || (dpn->type != 1))
+        return 1;
+    frag = dpn->name.relativename;
+    dpn->dpname = X509_NAME_dup(iname);
+    if (!dpn->dpname)
+        return 0;
+    for (i = 0; i < sk_X509_NAME_ENTRY_num(frag); i++) {
+        ne = sk_X509_NAME_ENTRY_value(frag, i);
+        if (!X509_NAME_add_entry(dpn->dpname, ne, -1, i ? 0 : 1)) {
+            X509_NAME_free(dpn->dpname);
+            dpn->dpname = NULL;
+            return 0;
+        }
+    }
+    /* generate cached encoding of name */
+    if (i2d_X509_NAME(dpn->dpname, NULL) < 0) {
+        X509_NAME_free(dpn->dpname);
+        dpn->dpname = NULL;
+        return 0;
+    }
+    return 1;
+}
diff --git a/src/crypto/x509v3/v3_enum.c b/src/crypto/x509v3/v3_enum.c
index 0fe6bb6..6bfb232 100644
--- a/src/crypto/x509v3/v3_enum.c
+++ b/src/crypto/x509v3/v3_enum.c
@@ -1,6 +1,7 @@
 /* v3_enum.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
  */
 /* ====================================================================
  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
@@ -10,7 +11,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -60,39 +61,40 @@
 #include <openssl/obj.h>
 #include <openssl/x509v3.h>
 
-
 static const ENUMERATED_NAMES crl_reasons[] = {
-{CRL_REASON_UNSPECIFIED, 	 "Unspecified", "unspecified"},
-{CRL_REASON_KEY_COMPROMISE,	 "Key Compromise", "keyCompromise"},
-{CRL_REASON_CA_COMPROMISE,	 "CA Compromise", "CACompromise"},
-{CRL_REASON_AFFILIATION_CHANGED, "Affiliation Changed", "affiliationChanged"},
-{CRL_REASON_SUPERSEDED, 	 "Superseded", "superseded"},
-{CRL_REASON_CESSATION_OF_OPERATION,
-			"Cessation Of Operation", "cessationOfOperation"},
-{CRL_REASON_CERTIFICATE_HOLD,	 "Certificate Hold", "certificateHold"},
-{CRL_REASON_REMOVE_FROM_CRL,	 "Remove From CRL", "removeFromCRL"},
-{CRL_REASON_PRIVILEGE_WITHDRAWN, "Privilege Withdrawn", "privilegeWithdrawn"},
-{CRL_REASON_AA_COMPROMISE,	 "AA Compromise", "AACompromise"},
-{-1, NULL, NULL}
+    {CRL_REASON_UNSPECIFIED, "Unspecified", "unspecified"},
+    {CRL_REASON_KEY_COMPROMISE, "Key Compromise", "keyCompromise"},
+    {CRL_REASON_CA_COMPROMISE, "CA Compromise", "CACompromise"},
+    {CRL_REASON_AFFILIATION_CHANGED, "Affiliation Changed",
+     "affiliationChanged"},
+    {CRL_REASON_SUPERSEDED, "Superseded", "superseded"},
+    {CRL_REASON_CESSATION_OF_OPERATION,
+     "Cessation Of Operation", "cessationOfOperation"},
+    {CRL_REASON_CERTIFICATE_HOLD, "Certificate Hold", "certificateHold"},
+    {CRL_REASON_REMOVE_FROM_CRL, "Remove From CRL", "removeFromCRL"},
+    {CRL_REASON_PRIVILEGE_WITHDRAWN, "Privilege Withdrawn",
+     "privilegeWithdrawn"},
+    {CRL_REASON_AA_COMPROMISE, "AA Compromise", "AACompromise"},
+    {-1, NULL, NULL}
 };
 
-const X509V3_EXT_METHOD v3_crl_reason = { 
-NID_crl_reason, 0, ASN1_ITEM_ref(ASN1_ENUMERATED),
-0,0,0,0,
-(X509V3_EXT_I2S)i2s_ASN1_ENUMERATED_TABLE,
-0,
-0,0,0,0,
-(void *)crl_reasons};
+const X509V3_EXT_METHOD v3_crl_reason = {
+    NID_crl_reason, 0, ASN1_ITEM_ref(ASN1_ENUMERATED),
+    0, 0, 0, 0,
+    (X509V3_EXT_I2S)i2s_ASN1_ENUMERATED_TABLE,
+    0,
+    0, 0, 0, 0,
+    (void *)crl_reasons
+};
 
-
-char *i2s_ASN1_ENUMERATED_TABLE(X509V3_EXT_METHOD *method,
-	     ASN1_ENUMERATED *e)
+char *i2s_ASN1_ENUMERATED_TABLE(X509V3_EXT_METHOD *method, ASN1_ENUMERATED *e)
 {
-	const ENUMERATED_NAMES *enam;
-	long strval;
-	strval = ASN1_ENUMERATED_get(e);
-	for(enam = method->usr_data; enam->lname; enam++) {
-		if(strval == enam->bitnum) return BUF_strdup(enam->lname);
-	}
-	return i2s_ASN1_ENUMERATED(method, e);
+    const ENUMERATED_NAMES *enam;
+    long strval;
+    strval = ASN1_ENUMERATED_get(e);
+    for (enam = method->usr_data; enam->lname; enam++) {
+        if (strval == enam->bitnum)
+            return BUF_strdup(enam->lname);
+    }
+    return i2s_ASN1_ENUMERATED(method, e);
 }
diff --git a/src/crypto/x509v3/v3_extku.c b/src/crypto/x509v3/v3_extku.c
index d64eb9c..952e032 100644
--- a/src/crypto/x509v3/v3_extku.c
+++ b/src/crypto/x509v3/v3_extku.c
@@ -1,6 +1,7 @@
 /* v3_extku.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
  */
 /* ====================================================================
  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
@@ -10,7 +11,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -54,7 +55,6 @@
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com). */
 
-
 #include <stdio.h>
 
 #include <openssl/asn1t.h>
@@ -63,83 +63,86 @@
 #include <openssl/obj.h>
 #include <openssl/x509v3.h>
 
-
 static void *v2i_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD *method,
-				    X509V3_CTX *ctx,
-				    STACK_OF(CONF_VALUE) *nval);
-static STACK_OF(CONF_VALUE) *i2v_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD *method,
-		void *eku, STACK_OF(CONF_VALUE) *extlist);
+                                    X509V3_CTX *ctx,
+                                    STACK_OF(CONF_VALUE) *nval);
+static STACK_OF(CONF_VALUE) *i2v_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD
+                                                    *method, void *eku, STACK_OF(CONF_VALUE)
+                                                    *extlist);
 
 const X509V3_EXT_METHOD v3_ext_ku = {
-	NID_ext_key_usage, 0,
-	ASN1_ITEM_ref(EXTENDED_KEY_USAGE),
-	0,0,0,0,
-	0,0,
-	i2v_EXTENDED_KEY_USAGE,
-	v2i_EXTENDED_KEY_USAGE,
-	0,0,
-	NULL
+    NID_ext_key_usage, 0,
+    ASN1_ITEM_ref(EXTENDED_KEY_USAGE),
+    0, 0, 0, 0,
+    0, 0,
+    i2v_EXTENDED_KEY_USAGE,
+    v2i_EXTENDED_KEY_USAGE,
+    0, 0,
+    NULL
 };
 
 /* NB OCSP acceptable responses also is a SEQUENCE OF OBJECT */
 const X509V3_EXT_METHOD v3_ocsp_accresp = {
-	NID_id_pkix_OCSP_acceptableResponses, 0,
-	ASN1_ITEM_ref(EXTENDED_KEY_USAGE),
-	0,0,0,0,
-	0,0,
-	i2v_EXTENDED_KEY_USAGE,
-	v2i_EXTENDED_KEY_USAGE,
-	0,0,
-	NULL
+    NID_id_pkix_OCSP_acceptableResponses, 0,
+    ASN1_ITEM_ref(EXTENDED_KEY_USAGE),
+    0, 0, 0, 0,
+    0, 0,
+    i2v_EXTENDED_KEY_USAGE,
+    v2i_EXTENDED_KEY_USAGE,
+    0, 0,
+    NULL
 };
 
-ASN1_ITEM_TEMPLATE(EXTENDED_KEY_USAGE) = 
-	ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, EXTENDED_KEY_USAGE, ASN1_OBJECT)
+ASN1_ITEM_TEMPLATE(EXTENDED_KEY_USAGE) =
+        ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, EXTENDED_KEY_USAGE, ASN1_OBJECT)
 ASN1_ITEM_TEMPLATE_END(EXTENDED_KEY_USAGE)
 
 IMPLEMENT_ASN1_FUNCTIONS(EXTENDED_KEY_USAGE)
 
-static STACK_OF(CONF_VALUE) *
-  i2v_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD *method, void *a,
-			 STACK_OF(CONF_VALUE) *ext_list)
+static STACK_OF(CONF_VALUE) *i2v_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD
+                                                    *method, void *a, STACK_OF(CONF_VALUE)
+                                                    *ext_list)
 {
-	EXTENDED_KEY_USAGE *eku = a;
-	size_t i;
-	ASN1_OBJECT *obj;
-	char obj_tmp[80];
-	for(i = 0; i < sk_ASN1_OBJECT_num(eku); i++) {
-		obj = sk_ASN1_OBJECT_value(eku, i);
-		i2t_ASN1_OBJECT(obj_tmp, 80, obj);
-		X509V3_add_value(NULL, obj_tmp, &ext_list);
-	}
-	return ext_list;
+    EXTENDED_KEY_USAGE *eku = a;
+    size_t i;
+    ASN1_OBJECT *obj;
+    char obj_tmp[80];
+    for (i = 0; i < sk_ASN1_OBJECT_num(eku); i++) {
+        obj = sk_ASN1_OBJECT_value(eku, i);
+        i2t_ASN1_OBJECT(obj_tmp, 80, obj);
+        X509V3_add_value(NULL, obj_tmp, &ext_list);
+    }
+    return ext_list;
 }
 
 static void *v2i_EXTENDED_KEY_USAGE(const X509V3_EXT_METHOD *method,
-				    X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
+                                    X509V3_CTX *ctx,
+                                    STACK_OF(CONF_VALUE) *nval)
 {
-	EXTENDED_KEY_USAGE *extku;
-	char *extval;
-	ASN1_OBJECT *objtmp;
-	CONF_VALUE *val;
-	size_t i;
+    EXTENDED_KEY_USAGE *extku;
+    char *extval;
+    ASN1_OBJECT *objtmp;
+    CONF_VALUE *val;
+    size_t i;
 
-	if(!(extku = sk_ASN1_OBJECT_new_null())) {
-		OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-		return NULL;
-	}
+    if (!(extku = sk_ASN1_OBJECT_new_null())) {
+        OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
 
-	for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
-		val = sk_CONF_VALUE_value(nval, i);
-		if(val->value) extval = val->value;
-		else extval = val->name;
-		if(!(objtmp = OBJ_txt2obj(extval, 0))) {
-			sk_ASN1_OBJECT_pop_free(extku, ASN1_OBJECT_free);
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER);
-			X509V3_conf_err(val);
-			return NULL;
-		}
-		sk_ASN1_OBJECT_push(extku, objtmp);
-	}
-	return extku;
+    for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+        val = sk_CONF_VALUE_value(nval, i);
+        if (val->value)
+            extval = val->value;
+        else
+            extval = val->name;
+        if (!(objtmp = OBJ_txt2obj(extval, 0))) {
+            sk_ASN1_OBJECT_pop_free(extku, ASN1_OBJECT_free);
+            OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER);
+            X509V3_conf_err(val);
+            return NULL;
+        }
+        sk_ASN1_OBJECT_push(extku, objtmp);
+    }
+    return extku;
 }
diff --git a/src/crypto/x509v3/v3_genn.c b/src/crypto/x509v3/v3_genn.c
index 8b0a68d..2331cd4 100644
--- a/src/crypto/x509v3/v3_genn.c
+++ b/src/crypto/x509v3/v3_genn.c
@@ -1,6 +1,7 @@
 /* v3_genn.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
  */
 /* ====================================================================
  * Copyright (c) 1999-2008 The OpenSSL Project.  All rights reserved.
@@ -10,7 +11,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -54,7 +55,6 @@
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com). */
 
-
 #include <stdio.h>
 
 #include <openssl/asn1t.h>
@@ -64,189 +64,187 @@
 
 
 ASN1_SEQUENCE(OTHERNAME) = {
-	ASN1_SIMPLE(OTHERNAME, type_id, ASN1_OBJECT),
-	/* Maybe have a true ANY DEFINED BY later */
-	ASN1_EXP(OTHERNAME, value, ASN1_ANY, 0)
+        ASN1_SIMPLE(OTHERNAME, type_id, ASN1_OBJECT),
+        /* Maybe have a true ANY DEFINED BY later */
+        ASN1_EXP(OTHERNAME, value, ASN1_ANY, 0)
 } ASN1_SEQUENCE_END(OTHERNAME)
 
 IMPLEMENT_ASN1_FUNCTIONS(OTHERNAME)
 
 ASN1_SEQUENCE(EDIPARTYNAME) = {
-	ASN1_IMP_OPT(EDIPARTYNAME, nameAssigner, DIRECTORYSTRING, 0),
-	ASN1_IMP_OPT(EDIPARTYNAME, partyName, DIRECTORYSTRING, 1)
+        ASN1_IMP_OPT(EDIPARTYNAME, nameAssigner, DIRECTORYSTRING, 0),
+        ASN1_IMP_OPT(EDIPARTYNAME, partyName, DIRECTORYSTRING, 1)
 } ASN1_SEQUENCE_END(EDIPARTYNAME)
 
 IMPLEMENT_ASN1_FUNCTIONS(EDIPARTYNAME)
 
 ASN1_CHOICE(GENERAL_NAME) = {
-	ASN1_IMP(GENERAL_NAME, d.otherName, OTHERNAME, GEN_OTHERNAME),
-	ASN1_IMP(GENERAL_NAME, d.rfc822Name, ASN1_IA5STRING, GEN_EMAIL),
-	ASN1_IMP(GENERAL_NAME, d.dNSName, ASN1_IA5STRING, GEN_DNS),
-	/* Don't decode this */
-	ASN1_IMP(GENERAL_NAME, d.x400Address, ASN1_SEQUENCE, GEN_X400),
-	/* X509_NAME is a CHOICE type so use EXPLICIT */
-	ASN1_EXP(GENERAL_NAME, d.directoryName, X509_NAME, GEN_DIRNAME),
-	ASN1_IMP(GENERAL_NAME, d.ediPartyName, EDIPARTYNAME, GEN_EDIPARTY),
-	ASN1_IMP(GENERAL_NAME, d.uniformResourceIdentifier, ASN1_IA5STRING, GEN_URI),
-	ASN1_IMP(GENERAL_NAME, d.iPAddress, ASN1_OCTET_STRING, GEN_IPADD),
-	ASN1_IMP(GENERAL_NAME, d.registeredID, ASN1_OBJECT, GEN_RID)
+        ASN1_IMP(GENERAL_NAME, d.otherName, OTHERNAME, GEN_OTHERNAME),
+        ASN1_IMP(GENERAL_NAME, d.rfc822Name, ASN1_IA5STRING, GEN_EMAIL),
+        ASN1_IMP(GENERAL_NAME, d.dNSName, ASN1_IA5STRING, GEN_DNS),
+        /* Don't decode this */
+        ASN1_IMP(GENERAL_NAME, d.x400Address, ASN1_SEQUENCE, GEN_X400),
+        /* X509_NAME is a CHOICE type so use EXPLICIT */
+        ASN1_EXP(GENERAL_NAME, d.directoryName, X509_NAME, GEN_DIRNAME),
+        ASN1_IMP(GENERAL_NAME, d.ediPartyName, EDIPARTYNAME, GEN_EDIPARTY),
+        ASN1_IMP(GENERAL_NAME, d.uniformResourceIdentifier, ASN1_IA5STRING, GEN_URI),
+        ASN1_IMP(GENERAL_NAME, d.iPAddress, ASN1_OCTET_STRING, GEN_IPADD),
+        ASN1_IMP(GENERAL_NAME, d.registeredID, ASN1_OBJECT, GEN_RID)
 } ASN1_CHOICE_END(GENERAL_NAME)
 
 IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAME)
 
-ASN1_ITEM_TEMPLATE(GENERAL_NAMES) = 
-	ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, GeneralNames, GENERAL_NAME)
+ASN1_ITEM_TEMPLATE(GENERAL_NAMES) =
+        ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, GeneralNames, GENERAL_NAME)
 ASN1_ITEM_TEMPLATE_END(GENERAL_NAMES)
 
 IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAMES)
 
 GENERAL_NAME *GENERAL_NAME_dup(GENERAL_NAME *a)
-	{
-	return (GENERAL_NAME *) ASN1_dup((i2d_of_void *) i2d_GENERAL_NAME,
-					 (d2i_of_void *) d2i_GENERAL_NAME,
-					 (char *) a);
-	}
+{
+    return (GENERAL_NAME *)ASN1_dup((i2d_of_void *)i2d_GENERAL_NAME,
+                                    (d2i_of_void *)d2i_GENERAL_NAME,
+                                    (char *)a);
+}
 
 /* Returns 0 if they are equal, != 0 otherwise. */
 int GENERAL_NAME_cmp(GENERAL_NAME *a, GENERAL_NAME *b)
-	{
-	int result = -1;
+{
+    int result = -1;
 
-	if (!a || !b || a->type != b->type) return -1;
-	switch(a->type)
-		{
-	case GEN_X400:
-	case GEN_EDIPARTY:
-		result = ASN1_TYPE_cmp(a->d.other, b->d.other);
-		break;
+    if (!a || !b || a->type != b->type)
+        return -1;
+    switch (a->type) {
+    case GEN_X400:
+    case GEN_EDIPARTY:
+        result = ASN1_TYPE_cmp(a->d.other, b->d.other);
+        break;
 
-	case GEN_OTHERNAME:
-		result = OTHERNAME_cmp(a->d.otherName, b->d.otherName);
-		break;
+    case GEN_OTHERNAME:
+        result = OTHERNAME_cmp(a->d.otherName, b->d.otherName);
+        break;
 
-	case GEN_EMAIL:
-	case GEN_DNS:
-	case GEN_URI:
-		result = ASN1_STRING_cmp(a->d.ia5, b->d.ia5);
-		break;
+    case GEN_EMAIL:
+    case GEN_DNS:
+    case GEN_URI:
+        result = ASN1_STRING_cmp(a->d.ia5, b->d.ia5);
+        break;
 
-	case GEN_DIRNAME:
-		result = X509_NAME_cmp(a->d.dirn, b->d.dirn);
-		break;
+    case GEN_DIRNAME:
+        result = X509_NAME_cmp(a->d.dirn, b->d.dirn);
+        break;
 
-	case GEN_IPADD:
-		result = ASN1_OCTET_STRING_cmp(a->d.ip, b->d.ip);
-		break;
-	
-	case GEN_RID:
-		result = OBJ_cmp(a->d.rid, b->d.rid);
-		break;
-		}
-	return result;
-	}
+    case GEN_IPADD:
+        result = ASN1_OCTET_STRING_cmp(a->d.ip, b->d.ip);
+        break;
+
+    case GEN_RID:
+        result = OBJ_cmp(a->d.rid, b->d.rid);
+        break;
+    }
+    return result;
+}
 
 /* Returns 0 if they are equal, != 0 otherwise. */
 int OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b)
-	{
-	int result = -1;
+{
+    int result = -1;
 
-	if (!a || !b) return -1;
-	/* Check their type first. */
-	if ((result = OBJ_cmp(a->type_id, b->type_id)) != 0)
-		return result;
-	/* Check the value. */
-	result = ASN1_TYPE_cmp(a->value, b->value);
-	return result;
-	}
+    if (!a || !b)
+        return -1;
+    /* Check their type first. */
+    if ((result = OBJ_cmp(a->type_id, b->type_id)) != 0)
+        return result;
+    /* Check the value. */
+    result = ASN1_TYPE_cmp(a->value, b->value);
+    return result;
+}
 
 void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value)
-	{
-	switch(type)
-		{
-	case GEN_X400:
-	case GEN_EDIPARTY:
-		a->d.other = value;
-		break;
+{
+    switch (type) {
+    case GEN_X400:
+    case GEN_EDIPARTY:
+        a->d.other = value;
+        break;
 
-	case GEN_OTHERNAME:
-		a->d.otherName = value;
-		break;
+    case GEN_OTHERNAME:
+        a->d.otherName = value;
+        break;
 
-	case GEN_EMAIL:
-	case GEN_DNS:
-	case GEN_URI:
-		a->d.ia5 = value;
-		break;
+    case GEN_EMAIL:
+    case GEN_DNS:
+    case GEN_URI:
+        a->d.ia5 = value;
+        break;
 
-	case GEN_DIRNAME:
-		a->d.dirn = value;
-		break;
+    case GEN_DIRNAME:
+        a->d.dirn = value;
+        break;
 
-	case GEN_IPADD:
-		a->d.ip = value;
-		break;
-	
-	case GEN_RID:
-		a->d.rid = value;
-		break;
-		}
-	a->type = type;
-	}
+    case GEN_IPADD:
+        a->d.ip = value;
+        break;
+
+    case GEN_RID:
+        a->d.rid = value;
+        break;
+    }
+    a->type = type;
+}
 
 void *GENERAL_NAME_get0_value(GENERAL_NAME *a, int *ptype)
-	{
-	if (ptype)
-		*ptype = a->type;
-	switch(a->type)
-		{
-	case GEN_X400:
-	case GEN_EDIPARTY:
-		return a->d.other;
+{
+    if (ptype)
+        *ptype = a->type;
+    switch (a->type) {
+    case GEN_X400:
+    case GEN_EDIPARTY:
+        return a->d.other;
 
-	case GEN_OTHERNAME:
-		return a->d.otherName;
+    case GEN_OTHERNAME:
+        return a->d.otherName;
 
-	case GEN_EMAIL:
-	case GEN_DNS:
-	case GEN_URI:
-		return a->d.ia5;
+    case GEN_EMAIL:
+    case GEN_DNS:
+    case GEN_URI:
+        return a->d.ia5;
 
-	case GEN_DIRNAME:
-		return a->d.dirn;
+    case GEN_DIRNAME:
+        return a->d.dirn;
 
-	case GEN_IPADD:
-		return a->d.ip;
-	
-	case GEN_RID:
-		return a->d.rid;
+    case GEN_IPADD:
+        return a->d.ip;
 
-	default:
-		return NULL;
-		}
-	}
+    case GEN_RID:
+        return a->d.rid;
+
+    default:
+        return NULL;
+    }
+}
 
 int GENERAL_NAME_set0_othername(GENERAL_NAME *gen,
-				ASN1_OBJECT *oid, ASN1_TYPE *value)
-	{
-	OTHERNAME *oth;
-	oth = OTHERNAME_new();
-	if (!oth)
-		return 0;
-	oth->type_id = oid;
-	oth->value = value;
-	GENERAL_NAME_set0_value(gen, GEN_OTHERNAME, oth);
-	return 1;
-	}
+                                ASN1_OBJECT *oid, ASN1_TYPE *value)
+{
+    OTHERNAME *oth;
+    oth = OTHERNAME_new();
+    if (!oth)
+        return 0;
+    oth->type_id = oid;
+    oth->value = value;
+    GENERAL_NAME_set0_value(gen, GEN_OTHERNAME, oth);
+    return 1;
+}
 
-int GENERAL_NAME_get0_otherName(GENERAL_NAME *gen, 
-				ASN1_OBJECT **poid, ASN1_TYPE **pvalue)
-	{
-	if (gen->type != GEN_OTHERNAME)
-		return 0;
-	if (poid)
-		*poid = gen->d.otherName->type_id;
-	if (pvalue)
-		*pvalue = gen->d.otherName->value;
-	return 1;
-	}
-
+int GENERAL_NAME_get0_otherName(GENERAL_NAME *gen,
+                                ASN1_OBJECT **poid, ASN1_TYPE **pvalue)
+{
+    if (gen->type != GEN_OTHERNAME)
+        return 0;
+    if (poid)
+        *poid = gen->d.otherName->type_id;
+    if (pvalue)
+        *pvalue = gen->d.otherName->value;
+    return 1;
+}
diff --git a/src/crypto/x509v3/v3_ia5.c b/src/crypto/x509v3/v3_ia5.c
index 5a27233..6b2056d 100644
--- a/src/crypto/x509v3/v3_ia5.c
+++ b/src/crypto/x509v3/v3_ia5.c
@@ -1,6 +1,7 @@
 /* v3_ia5.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
  */
 /* ====================================================================
  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
@@ -10,7 +11,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -66,52 +67,56 @@
 #include <openssl/obj.h>
 #include <openssl/x509v3.h>
 
-
-static char *i2s_ASN1_IA5STRING(X509V3_EXT_METHOD *method, ASN1_IA5STRING *ia5);
-static ASN1_IA5STRING *s2i_ASN1_IA5STRING(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *str);
-const X509V3_EXT_METHOD v3_ns_ia5_list[] = { 
-EXT_IA5STRING(NID_netscape_base_url),
-EXT_IA5STRING(NID_netscape_revocation_url),
-EXT_IA5STRING(NID_netscape_ca_revocation_url),
-EXT_IA5STRING(NID_netscape_renewal_url),
-EXT_IA5STRING(NID_netscape_ca_policy_url),
-EXT_IA5STRING(NID_netscape_ssl_server_name),
-EXT_IA5STRING(NID_netscape_comment),
-EXT_END
-};
+#include "../internal.h"
 
 
 static char *i2s_ASN1_IA5STRING(X509V3_EXT_METHOD *method,
-	     ASN1_IA5STRING *ia5)
+                                ASN1_IA5STRING *ia5);
+static ASN1_IA5STRING *s2i_ASN1_IA5STRING(X509V3_EXT_METHOD *method,
+                                          X509V3_CTX *ctx, char *str);
+const X509V3_EXT_METHOD v3_ns_ia5_list[] = {
+    EXT_IA5STRING(NID_netscape_base_url),
+    EXT_IA5STRING(NID_netscape_revocation_url),
+    EXT_IA5STRING(NID_netscape_ca_revocation_url),
+    EXT_IA5STRING(NID_netscape_renewal_url),
+    EXT_IA5STRING(NID_netscape_ca_policy_url),
+    EXT_IA5STRING(NID_netscape_ssl_server_name),
+    EXT_IA5STRING(NID_netscape_comment),
+    EXT_END
+};
+
+static char *i2s_ASN1_IA5STRING(X509V3_EXT_METHOD *method,
+                                ASN1_IA5STRING *ia5)
 {
-	char *tmp;
-	if(!ia5 || !ia5->length) return NULL;
-	if(!(tmp = OPENSSL_malloc(ia5->length + 1))) {
-		OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-		return NULL;
-	}
-	memcpy(tmp, ia5->data, ia5->length);
-	tmp[ia5->length] = 0;
-	return tmp;
+    char *tmp;
+    if (!ia5 || !ia5->length)
+        return NULL;
+    if (!(tmp = OPENSSL_malloc(ia5->length + 1))) {
+        OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+    OPENSSL_memcpy(tmp, ia5->data, ia5->length);
+    tmp[ia5->length] = 0;
+    return tmp;
 }
 
 static ASN1_IA5STRING *s2i_ASN1_IA5STRING(X509V3_EXT_METHOD *method,
-	     X509V3_CTX *ctx, char *str)
+                                          X509V3_CTX *ctx, char *str)
 {
-	ASN1_IA5STRING *ia5;
-	if(!str) {
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_ARGUMENT);
-		return NULL;
-	}
-	if(!(ia5 = M_ASN1_IA5STRING_new())) goto err;
-	if(!ASN1_STRING_set((ASN1_STRING *)ia5, (unsigned char*)str,
-			    strlen(str))) {
-		M_ASN1_IA5STRING_free(ia5);
-		goto err;
-	}
-	return ia5;
-	err:
-	OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-	return NULL;
+    ASN1_IA5STRING *ia5;
+    if (!str) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_ARGUMENT);
+        return NULL;
+    }
+    if (!(ia5 = M_ASN1_IA5STRING_new()))
+        goto err;
+    if (!ASN1_STRING_set((ASN1_STRING *)ia5, (unsigned char *)str,
+                         strlen(str))) {
+        M_ASN1_IA5STRING_free(ia5);
+        goto err;
+    }
+    return ia5;
+ err:
+    OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+    return NULL;
 }
-
diff --git a/src/crypto/x509v3/v3_info.c b/src/crypto/x509v3/v3_info.c
index 475c56f..482208d 100644
--- a/src/crypto/x509v3/v3_info.c
+++ b/src/crypto/x509v3/v3_info.c
@@ -1,6 +1,7 @@
 /* v3_info.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
  */
 /* ====================================================================
  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
@@ -10,7 +11,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -68,133 +69,144 @@
 #include <openssl/obj.h>
 #include <openssl/x509v3.h>
 
+static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD
+                                                       *method, AUTHORITY_INFO_ACCESS
+                                                       *ainfo, STACK_OF(CONF_VALUE)
+                                                       *ret);
+static AUTHORITY_INFO_ACCESS *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD
+                                                        *method,
+                                                        X509V3_CTX *ctx,
+                                                        STACK_OF(CONF_VALUE)
+                                                        *nval);
 
-static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD *method,
-				AUTHORITY_INFO_ACCESS *ainfo,
-						STACK_OF(CONF_VALUE) *ret);
-static AUTHORITY_INFO_ACCESS *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD *method,
-				 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
+const X509V3_EXT_METHOD v3_info = { NID_info_access, X509V3_EXT_MULTILINE,
+    ASN1_ITEM_ref(AUTHORITY_INFO_ACCESS),
+    0, 0, 0, 0,
+    0, 0,
+    (X509V3_EXT_I2V) i2v_AUTHORITY_INFO_ACCESS,
+    (X509V3_EXT_V2I)v2i_AUTHORITY_INFO_ACCESS,
+    0, 0,
+    NULL
+};
 
-const X509V3_EXT_METHOD v3_info =
-{ NID_info_access, X509V3_EXT_MULTILINE, ASN1_ITEM_ref(AUTHORITY_INFO_ACCESS),
-0,0,0,0,
-0,0,
-(X509V3_EXT_I2V)i2v_AUTHORITY_INFO_ACCESS,
-(X509V3_EXT_V2I)v2i_AUTHORITY_INFO_ACCESS,
-0,0,
-NULL};
-
-const X509V3_EXT_METHOD v3_sinfo =
-{ NID_sinfo_access, X509V3_EXT_MULTILINE, ASN1_ITEM_ref(AUTHORITY_INFO_ACCESS),
-0,0,0,0,
-0,0,
-(X509V3_EXT_I2V)i2v_AUTHORITY_INFO_ACCESS,
-(X509V3_EXT_V2I)v2i_AUTHORITY_INFO_ACCESS,
-0,0,
-NULL};
+const X509V3_EXT_METHOD v3_sinfo = { NID_sinfo_access, X509V3_EXT_MULTILINE,
+    ASN1_ITEM_ref(AUTHORITY_INFO_ACCESS),
+    0, 0, 0, 0,
+    0, 0,
+    (X509V3_EXT_I2V) i2v_AUTHORITY_INFO_ACCESS,
+    (X509V3_EXT_V2I)v2i_AUTHORITY_INFO_ACCESS,
+    0, 0,
+    NULL
+};
 
 ASN1_SEQUENCE(ACCESS_DESCRIPTION) = {
-	ASN1_SIMPLE(ACCESS_DESCRIPTION, method, ASN1_OBJECT),
-	ASN1_SIMPLE(ACCESS_DESCRIPTION, location, GENERAL_NAME)
+        ASN1_SIMPLE(ACCESS_DESCRIPTION, method, ASN1_OBJECT),
+        ASN1_SIMPLE(ACCESS_DESCRIPTION, location, GENERAL_NAME)
 } ASN1_SEQUENCE_END(ACCESS_DESCRIPTION)
 
 IMPLEMENT_ASN1_FUNCTIONS(ACCESS_DESCRIPTION)
 
-ASN1_ITEM_TEMPLATE(AUTHORITY_INFO_ACCESS) = 
-	ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, GeneralNames, ACCESS_DESCRIPTION)
+ASN1_ITEM_TEMPLATE(AUTHORITY_INFO_ACCESS) =
+        ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, GeneralNames, ACCESS_DESCRIPTION)
 ASN1_ITEM_TEMPLATE_END(AUTHORITY_INFO_ACCESS)
 
 IMPLEMENT_ASN1_FUNCTIONS(AUTHORITY_INFO_ACCESS)
 
-static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD *method,
-				AUTHORITY_INFO_ACCESS *ainfo,
-						STACK_OF(CONF_VALUE) *ret)
+static STACK_OF(CONF_VALUE) *i2v_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD
+                                                       *method, AUTHORITY_INFO_ACCESS
+                                                       *ainfo, STACK_OF(CONF_VALUE)
+                                                       *ret)
 {
-	ACCESS_DESCRIPTION *desc;
-	size_t i;
-	int nlen;
-	char objtmp[80], *ntmp;
-	CONF_VALUE *vtmp;
-	for(i = 0; i < sk_ACCESS_DESCRIPTION_num(ainfo); i++) {
-		desc = sk_ACCESS_DESCRIPTION_value(ainfo, i);
-		ret = i2v_GENERAL_NAME(method, desc->location, ret);
-		if(!ret) break;
-		vtmp = sk_CONF_VALUE_value(ret, i);
-		i2t_ASN1_OBJECT(objtmp, sizeof objtmp, desc->method);
-		nlen = strlen(objtmp) + strlen(vtmp->name) + 5;
-		ntmp = OPENSSL_malloc(nlen);
-		if(!ntmp) {
-			OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-			return NULL;
-		}
-		BUF_strlcpy(ntmp, objtmp, nlen);
-		BUF_strlcat(ntmp, " - ", nlen);
-		BUF_strlcat(ntmp, vtmp->name, nlen);
-		OPENSSL_free(vtmp->name);
-		vtmp->name = ntmp;
-		
-	}
-	if(!ret) return sk_CONF_VALUE_new_null();
-	return ret;
+    ACCESS_DESCRIPTION *desc;
+    size_t i;
+    int nlen;
+    char objtmp[80], *ntmp;
+    CONF_VALUE *vtmp;
+    for (i = 0; i < sk_ACCESS_DESCRIPTION_num(ainfo); i++) {
+        desc = sk_ACCESS_DESCRIPTION_value(ainfo, i);
+        ret = i2v_GENERAL_NAME(method, desc->location, ret);
+        if (!ret)
+            break;
+        vtmp = sk_CONF_VALUE_value(ret, i);
+        i2t_ASN1_OBJECT(objtmp, sizeof objtmp, desc->method);
+        nlen = strlen(objtmp) + strlen(vtmp->name) + 5;
+        ntmp = OPENSSL_malloc(nlen);
+        if (!ntmp) {
+            OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+            return NULL;
+        }
+        BUF_strlcpy(ntmp, objtmp, nlen);
+        BUF_strlcat(ntmp, " - ", nlen);
+        BUF_strlcat(ntmp, vtmp->name, nlen);
+        OPENSSL_free(vtmp->name);
+        vtmp->name = ntmp;
+
+    }
+    if (!ret)
+        return sk_CONF_VALUE_new_null();
+    return ret;
 }
 
-static AUTHORITY_INFO_ACCESS *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD *method,
-				 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
+static AUTHORITY_INFO_ACCESS *v2i_AUTHORITY_INFO_ACCESS(X509V3_EXT_METHOD
+                                                        *method,
+                                                        X509V3_CTX *ctx,
+                                                        STACK_OF(CONF_VALUE)
+                                                        *nval)
 {
-	AUTHORITY_INFO_ACCESS *ainfo = NULL;
-	CONF_VALUE *cnf, ctmp;
-	ACCESS_DESCRIPTION *acc;
-	size_t i;
-	int objlen;
-	char *objtmp, *ptmp;
-	if(!(ainfo = sk_ACCESS_DESCRIPTION_new_null())) {
-		OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-		return NULL;
-	}
-	for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
-		cnf = sk_CONF_VALUE_value(nval, i);
-		if(!(acc = ACCESS_DESCRIPTION_new())
-			|| !sk_ACCESS_DESCRIPTION_push(ainfo, acc)) {
-			OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-			goto err;
-		}
-		ptmp = strchr(cnf->name, ';');
-		if(!ptmp) {
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SYNTAX);
-			goto err;
-		}
-		objlen = ptmp - cnf->name;
-		ctmp.name = ptmp + 1;
-		ctmp.value = cnf->value;
-		if(!v2i_GENERAL_NAME_ex(acc->location, method, ctx, &ctmp, 0))
-								 goto err; 
-		if(!(objtmp = OPENSSL_malloc(objlen + 1))) {
-			OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-			goto err;
-		}
-		strncpy(objtmp, cnf->name, objlen);
-		objtmp[objlen] = 0;
-		acc->method = OBJ_txt2obj(objtmp, 0);
-		if(!acc->method) {
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_OBJECT);
-			ERR_add_error_data(2, "value=", objtmp);
-			OPENSSL_free(objtmp);
-			goto err;
-		}
-		OPENSSL_free(objtmp);
+    AUTHORITY_INFO_ACCESS *ainfo = NULL;
+    CONF_VALUE *cnf, ctmp;
+    ACCESS_DESCRIPTION *acc;
+    size_t i;
+    int objlen;
+    char *objtmp, *ptmp;
+    if (!(ainfo = sk_ACCESS_DESCRIPTION_new_null())) {
+        OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+    for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+        cnf = sk_CONF_VALUE_value(nval, i);
+        if (!(acc = ACCESS_DESCRIPTION_new())
+            || !sk_ACCESS_DESCRIPTION_push(ainfo, acc)) {
+            OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+            goto err;
+        }
+        ptmp = strchr(cnf->name, ';');
+        if (!ptmp) {
+            OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SYNTAX);
+            goto err;
+        }
+        objlen = ptmp - cnf->name;
+        ctmp.name = ptmp + 1;
+        ctmp.value = cnf->value;
+        if (!v2i_GENERAL_NAME_ex(acc->location, method, ctx, &ctmp, 0))
+            goto err;
+        if (!(objtmp = OPENSSL_malloc(objlen + 1))) {
+            OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+            goto err;
+        }
+        strncpy(objtmp, cnf->name, objlen);
+        objtmp[objlen] = 0;
+        acc->method = OBJ_txt2obj(objtmp, 0);
+        if (!acc->method) {
+            OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_OBJECT);
+            ERR_add_error_data(2, "value=", objtmp);
+            OPENSSL_free(objtmp);
+            goto err;
+        }
+        OPENSSL_free(objtmp);
 
-	}
-	return ainfo;
-	err:
-	sk_ACCESS_DESCRIPTION_pop_free(ainfo, ACCESS_DESCRIPTION_free);
-	return NULL;
+    }
+    return ainfo;
+ err:
+    sk_ACCESS_DESCRIPTION_pop_free(ainfo, ACCESS_DESCRIPTION_free);
+    return NULL;
 }
 
-int i2a_ACCESS_DESCRIPTION(BIO *bp, ACCESS_DESCRIPTION* a)
-        {
-	i2a_ASN1_OBJECT(bp, a->method);
+int i2a_ACCESS_DESCRIPTION(BIO *bp, ACCESS_DESCRIPTION *a)
+{
+    i2a_ASN1_OBJECT(bp, a->method);
 #ifdef UNDEF
-	i2a_GENERAL_NAME(bp, a->location);
+    i2a_GENERAL_NAME(bp, a->location);
 #endif
-	return 2;
-	}
+    return 2;
+}
diff --git a/src/crypto/x509v3/v3_int.c b/src/crypto/x509v3/v3_int.c
index 8ca23bd..7bde446 100644
--- a/src/crypto/x509v3/v3_int.c
+++ b/src/crypto/x509v3/v3_int.c
@@ -1,6 +1,7 @@
 /* v3_int.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
  */
 /* ====================================================================
  * Copyright (c) 1999-2004 The OpenSSL Project.  All rights reserved.
@@ -10,7 +11,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -59,29 +60,32 @@
 #include <openssl/obj.h>
 #include <openssl/x509v3.h>
 
+const X509V3_EXT_METHOD v3_crl_num = {
+    NID_crl_number, 0, ASN1_ITEM_ref(ASN1_INTEGER),
+    0, 0, 0, 0,
+    (X509V3_EXT_I2S)i2s_ASN1_INTEGER,
+    0,
+    0, 0, 0, 0, NULL
+};
 
-const X509V3_EXT_METHOD v3_crl_num = { 
-	NID_crl_number, 0, ASN1_ITEM_ref(ASN1_INTEGER),
-	0,0,0,0,
-	(X509V3_EXT_I2S)i2s_ASN1_INTEGER,
-	0,
-	0,0,0,0, NULL};
+const X509V3_EXT_METHOD v3_delta_crl = {
+    NID_delta_crl, 0, ASN1_ITEM_ref(ASN1_INTEGER),
+    0, 0, 0, 0,
+    (X509V3_EXT_I2S)i2s_ASN1_INTEGER,
+    0,
+    0, 0, 0, 0, NULL
+};
 
-const X509V3_EXT_METHOD v3_delta_crl = { 
-	NID_delta_crl, 0, ASN1_ITEM_ref(ASN1_INTEGER),
-	0,0,0,0,
-	(X509V3_EXT_I2S)i2s_ASN1_INTEGER,
-	0,
-	0,0,0,0, NULL};
+static void *s2i_asn1_int(X509V3_EXT_METHOD *meth, X509V3_CTX *ctx,
+                          char *value)
+{
+    return s2i_ASN1_INTEGER(meth, value);
+}
 
-static void * s2i_asn1_int(X509V3_EXT_METHOD *meth, X509V3_CTX *ctx, char *value)
-	{
-	return s2i_ASN1_INTEGER(meth, value);
-	}
-
-const X509V3_EXT_METHOD v3_inhibit_anyp = { 
-	NID_inhibit_any_policy, 0, ASN1_ITEM_ref(ASN1_INTEGER),
-	0,0,0,0,
-	(X509V3_EXT_I2S)i2s_ASN1_INTEGER,
-	(X509V3_EXT_S2I)s2i_asn1_int,
-	0,0,0,0, NULL};
+const X509V3_EXT_METHOD v3_inhibit_anyp = {
+    NID_inhibit_any_policy, 0, ASN1_ITEM_ref(ASN1_INTEGER),
+    0, 0, 0, 0,
+    (X509V3_EXT_I2S)i2s_ASN1_INTEGER,
+    (X509V3_EXT_S2I)s2i_asn1_int,
+    0, 0, 0, 0, NULL
+};
diff --git a/src/crypto/x509v3/v3_lib.c b/src/crypto/x509v3/v3_lib.c
index f8e5531..c4718e3 100644
--- a/src/crypto/x509v3/v3_lib.c
+++ b/src/crypto/x509v3/v3_lib.c
@@ -1,6 +1,7 @@
 /* v3_lib.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
  */
 /* ====================================================================
  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
@@ -10,7 +11,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -70,266 +71,292 @@
 
 static void ext_list_free(X509V3_EXT_METHOD *ext);
 
-static int ext_stack_cmp(const X509V3_EXT_METHOD **a, const X509V3_EXT_METHOD **b)
+static int ext_stack_cmp(const X509V3_EXT_METHOD **a,
+                         const X509V3_EXT_METHOD **b)
 {
-	return ((*a)->ext_nid - (*b)->ext_nid);
+    return ((*a)->ext_nid - (*b)->ext_nid);
 }
 
 int X509V3_EXT_add(X509V3_EXT_METHOD *ext)
 {
-	if(!ext_list && !(ext_list = sk_X509V3_EXT_METHOD_new(ext_stack_cmp))) {
-		OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-		ext_list_free(ext);
-		return 0;
-	}
-	if(!sk_X509V3_EXT_METHOD_push(ext_list, ext)) {
-		OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-		ext_list_free(ext);
-		return 0;
-	}
-	return 1;
+    if (!ext_list && !(ext_list = sk_X509V3_EXT_METHOD_new(ext_stack_cmp))) {
+        OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+        ext_list_free(ext);
+        return 0;
+    }
+    if (!sk_X509V3_EXT_METHOD_push(ext_list, ext)) {
+        OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+        ext_list_free(ext);
+        return 0;
+    }
+    return 1;
 }
 
-static int ext_cmp(const void *void_a,
-		   const void *void_b)
+static int ext_cmp(const void *void_a, const void *void_b)
 {
-	const X509V3_EXT_METHOD **a = (const X509V3_EXT_METHOD**) void_a;
-	const X509V3_EXT_METHOD **b = (const X509V3_EXT_METHOD**) void_b;
-	return ext_stack_cmp(a, b);
+    const X509V3_EXT_METHOD **a = (const X509V3_EXT_METHOD **)void_a;
+    const X509V3_EXT_METHOD **b = (const X509V3_EXT_METHOD **)void_b;
+    return ext_stack_cmp(a, b);
 }
 
 const X509V3_EXT_METHOD *X509V3_EXT_get_nid(int nid)
 {
-	X509V3_EXT_METHOD tmp;
-	const X509V3_EXT_METHOD *t = &tmp, * const *ret;
-	size_t idx;
+    X509V3_EXT_METHOD tmp;
+    const X509V3_EXT_METHOD *t = &tmp, *const *ret;
+    size_t idx;
 
-	if(nid < 0) return NULL;
-	tmp.ext_nid = nid;
-	ret = bsearch(&t, standard_exts, STANDARD_EXTENSION_COUNT, sizeof(X509V3_EXT_METHOD*), ext_cmp);
-	if(ret) return *ret;
-	if(!ext_list) return NULL;
+    if (nid < 0)
+        return NULL;
+    tmp.ext_nid = nid;
+    ret =
+        bsearch(&t, standard_exts, STANDARD_EXTENSION_COUNT,
+                sizeof(X509V3_EXT_METHOD *), ext_cmp);
+    if (ret)
+        return *ret;
+    if (!ext_list)
+        return NULL;
 
-	if (!sk_X509V3_EXT_METHOD_find(ext_list, &idx, &tmp))
-		return NULL;
-	return sk_X509V3_EXT_METHOD_value(ext_list, idx);
+    if (!sk_X509V3_EXT_METHOD_find(ext_list, &idx, &tmp))
+        return NULL;
+    return sk_X509V3_EXT_METHOD_value(ext_list, idx);
 }
 
 const X509V3_EXT_METHOD *X509V3_EXT_get(X509_EXTENSION *ext)
 {
-	int nid;
-	if((nid = OBJ_obj2nid(ext->object)) == NID_undef) return NULL;
-	return X509V3_EXT_get_nid(nid);
+    int nid;
+    if ((nid = OBJ_obj2nid(ext->object)) == NID_undef)
+        return NULL;
+    return X509V3_EXT_get_nid(nid);
 }
 
 int X509V3_EXT_free(int nid, void *ext_data)
 {
-	    const X509V3_EXT_METHOD *ext_method = X509V3_EXT_get_nid(nid);
-	    if (ext_method == NULL)
-	    {
-		    OPENSSL_PUT_ERROR(X509V3, X509V3_R_CANNOT_FIND_FREE_FUNCTION);
-		    return 0;
-	    }
+    const X509V3_EXT_METHOD *ext_method = X509V3_EXT_get_nid(nid);
+    if (ext_method == NULL) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_CANNOT_FIND_FREE_FUNCTION);
+        return 0;
+    }
 
-	    if (ext_method->it != NULL)
-		    ASN1_item_free(ext_data, ASN1_ITEM_ptr(ext_method->it));
-	    else if (ext_method->ext_free != NULL)
-		    ext_method->ext_free(ext_data);
-	    else
-	    {
-		    OPENSSL_PUT_ERROR(X509V3, X509V3_R_CANNOT_FIND_FREE_FUNCTION);
-		    return 0;
-	    }
+    if (ext_method->it != NULL)
+        ASN1_item_free(ext_data, ASN1_ITEM_ptr(ext_method->it));
+    else if (ext_method->ext_free != NULL)
+        ext_method->ext_free(ext_data);
+    else {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_CANNOT_FIND_FREE_FUNCTION);
+        return 0;
+    }
 
-	    return 1;
+    return 1;
 }
 
 int X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist)
 {
-	for(;extlist->ext_nid!=-1;extlist++) 
-			if(!X509V3_EXT_add(extlist)) return 0;
-	return 1;
+    for (; extlist->ext_nid != -1; extlist++)
+        if (!X509V3_EXT_add(extlist))
+            return 0;
+    return 1;
 }
 
 int X509V3_EXT_add_alias(int nid_to, int nid_from)
 {
-	const X509V3_EXT_METHOD *ext;
-	X509V3_EXT_METHOD *tmpext;
+    const X509V3_EXT_METHOD *ext;
+    X509V3_EXT_METHOD *tmpext;
 
-	if(!(ext = X509V3_EXT_get_nid(nid_from))) {
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_NOT_FOUND);
-		return 0;
-	}
-	if(!(tmpext = (X509V3_EXT_METHOD *)OPENSSL_malloc(sizeof(X509V3_EXT_METHOD)))) {
-		OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-		return 0;
-	}
-	*tmpext = *ext;
-	tmpext->ext_nid = nid_to;
-	tmpext->ext_flags |= X509V3_EXT_DYNAMIC;
-	return X509V3_EXT_add(tmpext);
+    if (!(ext = X509V3_EXT_get_nid(nid_from))) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_EXTENSION_NOT_FOUND);
+        return 0;
+    }
+    if (!
+        (tmpext =
+         (X509V3_EXT_METHOD *)OPENSSL_malloc(sizeof(X509V3_EXT_METHOD)))) {
+        OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+        return 0;
+    }
+    *tmpext = *ext;
+    tmpext->ext_nid = nid_to;
+    tmpext->ext_flags |= X509V3_EXT_DYNAMIC;
+    return X509V3_EXT_add(tmpext);
 }
 
 void X509V3_EXT_cleanup(void)
 {
-	sk_X509V3_EXT_METHOD_pop_free(ext_list, ext_list_free);
-	ext_list = NULL;
+    sk_X509V3_EXT_METHOD_pop_free(ext_list, ext_list_free);
+    ext_list = NULL;
 }
 
 static void ext_list_free(X509V3_EXT_METHOD *ext)
 {
-	if(ext->ext_flags & X509V3_EXT_DYNAMIC) OPENSSL_free(ext);
+    if (ext->ext_flags & X509V3_EXT_DYNAMIC)
+        OPENSSL_free(ext);
 }
 
-/* Legacy function: we don't need to add standard extensions
- * any more because they are now kept in ext_dat.h.
+/*
+ * Legacy function: we don't need to add standard extensions any more because
+ * they are now kept in ext_dat.h.
  */
 
 int X509V3_add_standard_extensions(void)
 {
-	return 1;
+    return 1;
 }
 
 /* Return an extension internal structure */
 
 void *X509V3_EXT_d2i(X509_EXTENSION *ext)
 {
-	const X509V3_EXT_METHOD *method;
-	const unsigned char *p;
+    const X509V3_EXT_METHOD *method;
+    const unsigned char *p;
 
-	if(!(method = X509V3_EXT_get(ext))) return NULL;
-	p = ext->value->data;
-	if(method->it) return ASN1_item_d2i(NULL, &p, ext->value->length, ASN1_ITEM_ptr(method->it));
-	return method->d2i(NULL, &p, ext->value->length);
+    if (!(method = X509V3_EXT_get(ext)))
+        return NULL;
+    p = ext->value->data;
+    if (method->it)
+        return ASN1_item_d2i(NULL, &p, ext->value->length,
+                             ASN1_ITEM_ptr(method->it));
+    return method->d2i(NULL, &p, ext->value->length);
 }
 
-/* Get critical flag and decoded version of extension from a NID.
- * The "idx" variable returns the last found extension and can
- * be used to retrieve multiple extensions of the same NID.
- * However multiple extensions with the same NID is usually
- * due to a badly encoded certificate so if idx is NULL we
- * choke if multiple extensions exist.
- * The "crit" variable is set to the critical value.
- * The return value is the decoded extension or NULL on
- * error. The actual error can have several different causes,
- * the value of *crit reflects the cause:
- * >= 0, extension found but not decoded (reflects critical value).
- * -1 extension not found.
- * -2 extension occurs more than once.
+/*
+ * Get critical flag and decoded version of extension from a NID. The "idx"
+ * variable returns the last found extension and can be used to retrieve
+ * multiple extensions of the same NID. However multiple extensions with the
+ * same NID is usually due to a badly encoded certificate so if idx is NULL
+ * we choke if multiple extensions exist. The "crit" variable is set to the
+ * critical value. The return value is the decoded extension or NULL on
+ * error. The actual error can have several different causes, the value of
+ * *crit reflects the cause: >= 0, extension found but not decoded (reflects
+ * critical value). -1 extension not found. -2 extension occurs more than
+ * once.
  */
 
-void *X509V3_get_d2i(STACK_OF(X509_EXTENSION) *x, int nid, int *crit, int *idx)
+void *X509V3_get_d2i(STACK_OF(X509_EXTENSION) *x, int nid, int *crit,
+                     int *idx)
 {
-	int lastpos;
-	size_t i;
-	X509_EXTENSION *ex, *found_ex = NULL;
-	if(!x) {
-		if(idx) *idx = -1;
-		if(crit) *crit = -1;
-		return NULL;
-	}
-	if(idx) lastpos = *idx + 1;
-	else lastpos = 0;
-	if(lastpos < 0) lastpos = 0;
-	for(i = lastpos; i < sk_X509_EXTENSION_num(x); i++)
-	{
-		ex = sk_X509_EXTENSION_value(x, i);
-		if(OBJ_obj2nid(ex->object) == nid) {
-			if(idx) {
-				*idx = i;
-				found_ex = ex;
-				break;
-			} else if(found_ex) {
-				/* Found more than one */
-				if(crit) *crit = -2;
-				return NULL;
-			}
-			found_ex = ex;
-		}
-	}
-	if(found_ex) {
-		/* Found it */
-		if(crit) *crit = X509_EXTENSION_get_critical(found_ex);
-		return X509V3_EXT_d2i(found_ex);
-	}
+    int lastpos;
+    size_t i;
+    X509_EXTENSION *ex, *found_ex = NULL;
+    if (!x) {
+        if (idx)
+            *idx = -1;
+        if (crit)
+            *crit = -1;
+        return NULL;
+    }
+    if (idx)
+        lastpos = *idx + 1;
+    else
+        lastpos = 0;
+    if (lastpos < 0)
+        lastpos = 0;
+    for (i = lastpos; i < sk_X509_EXTENSION_num(x); i++) {
+        ex = sk_X509_EXTENSION_value(x, i);
+        if (OBJ_obj2nid(ex->object) == nid) {
+            if (idx) {
+                *idx = i;
+                found_ex = ex;
+                break;
+            } else if (found_ex) {
+                /* Found more than one */
+                if (crit)
+                    *crit = -2;
+                return NULL;
+            }
+            found_ex = ex;
+        }
+    }
+    if (found_ex) {
+        /* Found it */
+        if (crit)
+            *crit = X509_EXTENSION_get_critical(found_ex);
+        return X509V3_EXT_d2i(found_ex);
+    }
 
-	/* Extension not found */
-	if(idx) *idx = -1;
-	if(crit) *crit = -1;
-	return NULL;
+    /* Extension not found */
+    if (idx)
+        *idx = -1;
+    if (crit)
+        *crit = -1;
+    return NULL;
 }
 
-/* This function is a general extension append, replace and delete utility.
+/*
+ * This function is a general extension append, replace and delete utility.
  * The precise operation is governed by the 'flags' value. The 'crit' and
  * 'value' arguments (if relevant) are the extensions internal structure.
  */
 
 int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value,
-					int crit, unsigned long flags)
+                    int crit, unsigned long flags)
 {
-	int extidx = -1;
-	int errcode;
-	X509_EXTENSION *ext, *extmp;
-	unsigned long ext_op = flags & X509V3_ADD_OP_MASK;
+    int extidx = -1;
+    int errcode;
+    X509_EXTENSION *ext, *extmp;
+    unsigned long ext_op = flags & X509V3_ADD_OP_MASK;
 
-	/* If appending we don't care if it exists, otherwise
-	 * look for existing extension.
-	 */
-	if(ext_op != X509V3_ADD_APPEND)
-		extidx = X509v3_get_ext_by_NID(*x, nid, -1);
+    /*
+     * If appending we don't care if it exists, otherwise look for existing
+     * extension.
+     */
+    if (ext_op != X509V3_ADD_APPEND)
+        extidx = X509v3_get_ext_by_NID(*x, nid, -1);
 
-	/* See if extension exists */
-	if(extidx >= 0) {
-		/* If keep existing, nothing to do */
-		if(ext_op == X509V3_ADD_KEEP_EXISTING)
-			return 1;
-		/* If default then its an error */
-		if(ext_op == X509V3_ADD_DEFAULT) {
-			errcode = X509V3_R_EXTENSION_EXISTS;
-			goto err;
-		}
-		/* If delete, just delete it */
-		if(ext_op == X509V3_ADD_DELETE) {
-			if(!sk_X509_EXTENSION_delete(*x, extidx)) return -1;
-			return 1;
-		}
-	} else {
-		/* If replace existing or delete, error since 
-		 * extension must exist
-		 */
-		if((ext_op == X509V3_ADD_REPLACE_EXISTING) ||
-		   (ext_op == X509V3_ADD_DELETE)) {
-			errcode = X509V3_R_EXTENSION_NOT_FOUND;
-			goto err;
-		}
-	}
+    /* See if extension exists */
+    if (extidx >= 0) {
+        /* If keep existing, nothing to do */
+        if (ext_op == X509V3_ADD_KEEP_EXISTING)
+            return 1;
+        /* If default then its an error */
+        if (ext_op == X509V3_ADD_DEFAULT) {
+            errcode = X509V3_R_EXTENSION_EXISTS;
+            goto err;
+        }
+        /* If delete, just delete it */
+        if (ext_op == X509V3_ADD_DELETE) {
+            if (!sk_X509_EXTENSION_delete(*x, extidx))
+                return -1;
+            return 1;
+        }
+    } else {
+        /*
+         * If replace existing or delete, error since extension must exist
+         */
+        if ((ext_op == X509V3_ADD_REPLACE_EXISTING) ||
+            (ext_op == X509V3_ADD_DELETE)) {
+            errcode = X509V3_R_EXTENSION_NOT_FOUND;
+            goto err;
+        }
+    }
 
-	/* If we get this far then we have to create an extension:
-	 * could have some flags for alternative encoding schemes...
-	 */
+    /*
+     * If we get this far then we have to create an extension: could have
+     * some flags for alternative encoding schemes...
+     */
 
-	ext = X509V3_EXT_i2d(nid, crit, value);
+    ext = X509V3_EXT_i2d(nid, crit, value);
 
-	if(!ext) {
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_ERROR_CREATING_EXTENSION);
-		return 0;
-	}
+    if (!ext) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_ERROR_CREATING_EXTENSION);
+        return 0;
+    }
 
-	/* If extension exists replace it.. */
-	if(extidx >= 0) {
-		extmp = sk_X509_EXTENSION_value(*x, extidx);
-		X509_EXTENSION_free(extmp);
-		if(!sk_X509_EXTENSION_set(*x, extidx, ext)) return -1;
-		return 1;
-	}
+    /* If extension exists replace it.. */
+    if (extidx >= 0) {
+        extmp = sk_X509_EXTENSION_value(*x, extidx);
+        X509_EXTENSION_free(extmp);
+        if (!sk_X509_EXTENSION_set(*x, extidx, ext))
+            return -1;
+        return 1;
+    }
 
-	if(!*x && !(*x = sk_X509_EXTENSION_new_null())) return -1;
-	if(!sk_X509_EXTENSION_push(*x, ext)) return -1;
+    if (!*x && !(*x = sk_X509_EXTENSION_new_null()))
+        return -1;
+    if (!sk_X509_EXTENSION_push(*x, ext))
+        return -1;
 
-	return 1;
+    return 1;
 
-	err:
-	if(!(flags & X509V3_ADD_SILENT))
-		OPENSSL_PUT_ERROR(X509V3, errcode);
-	return 0;
+ err:
+    if (!(flags & X509V3_ADD_SILENT))
+        OPENSSL_PUT_ERROR(X509V3, errcode);
+    return 0;
 }
diff --git a/src/crypto/x509v3/v3_ncons.c b/src/crypto/x509v3/v3_ncons.c
index 19f5e94..fc2843e 100644
--- a/src/crypto/x509v3/v3_ncons.c
+++ b/src/crypto/x509v3/v3_ncons.c
@@ -1,5 +1,6 @@
 /* v3_ncons.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project.
  */
 /* ====================================================================
@@ -10,7 +11,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -54,7 +55,6 @@
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com). */
 
-
 #include <stdio.h>
 #include <string.h>
 
@@ -65,14 +65,17 @@
 #include <openssl/obj.h>
 #include <openssl/x509v3.h>
 
+#include "../internal.h"
+
 
 static void *v2i_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method,
-				  X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
-static int i2r_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, 
-				void *a, BIO *bp, int ind);
+                                  X509V3_CTX *ctx,
+                                  STACK_OF(CONF_VALUE) *nval);
+static int i2r_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, void *a,
+                                BIO *bp, int ind);
 static int do_i2r_name_constraints(const X509V3_EXT_METHOD *method,
-				   STACK_OF(GENERAL_SUBTREE) *trees,
-				   BIO *bp, int ind, const char *name);
+                                   STACK_OF(GENERAL_SUBTREE) *trees, BIO *bp,
+                                   int ind, const char *name);
 static int print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip);
 
 static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc);
@@ -83,428 +86,400 @@
 static int nc_uri(ASN1_IA5STRING *uri, ASN1_IA5STRING *base);
 
 const X509V3_EXT_METHOD v3_name_constraints = {
-	NID_name_constraints, 0,
-	ASN1_ITEM_ref(NAME_CONSTRAINTS),
-	0,0,0,0,
-	0,0,
-	0, v2i_NAME_CONSTRAINTS,
-	i2r_NAME_CONSTRAINTS,0,
-	NULL
+    NID_name_constraints, 0,
+    ASN1_ITEM_ref(NAME_CONSTRAINTS),
+    0, 0, 0, 0,
+    0, 0,
+    0, v2i_NAME_CONSTRAINTS,
+    i2r_NAME_CONSTRAINTS, 0,
+    NULL
 };
 
 ASN1_SEQUENCE(GENERAL_SUBTREE) = {
-	ASN1_SIMPLE(GENERAL_SUBTREE, base, GENERAL_NAME),
-	ASN1_IMP_OPT(GENERAL_SUBTREE, minimum, ASN1_INTEGER, 0),
-	ASN1_IMP_OPT(GENERAL_SUBTREE, maximum, ASN1_INTEGER, 1)
+        ASN1_SIMPLE(GENERAL_SUBTREE, base, GENERAL_NAME),
+        ASN1_IMP_OPT(GENERAL_SUBTREE, minimum, ASN1_INTEGER, 0),
+        ASN1_IMP_OPT(GENERAL_SUBTREE, maximum, ASN1_INTEGER, 1)
 } ASN1_SEQUENCE_END(GENERAL_SUBTREE)
 
 ASN1_SEQUENCE(NAME_CONSTRAINTS) = {
-	ASN1_IMP_SEQUENCE_OF_OPT(NAME_CONSTRAINTS, permittedSubtrees,
-							GENERAL_SUBTREE, 0),
-	ASN1_IMP_SEQUENCE_OF_OPT(NAME_CONSTRAINTS, excludedSubtrees,
-							GENERAL_SUBTREE, 1),
+        ASN1_IMP_SEQUENCE_OF_OPT(NAME_CONSTRAINTS, permittedSubtrees,
+                                                        GENERAL_SUBTREE, 0),
+        ASN1_IMP_SEQUENCE_OF_OPT(NAME_CONSTRAINTS, excludedSubtrees,
+                                                        GENERAL_SUBTREE, 1),
 } ASN1_SEQUENCE_END(NAME_CONSTRAINTS)
-	
+
 
 IMPLEMENT_ASN1_ALLOC_FUNCTIONS(GENERAL_SUBTREE)
 IMPLEMENT_ASN1_ALLOC_FUNCTIONS(NAME_CONSTRAINTS)
 
 static void *v2i_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method,
-				  X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
-	{
-	size_t i;
-	CONF_VALUE tval, *val;
-	STACK_OF(GENERAL_SUBTREE) **ptree = NULL;
-	NAME_CONSTRAINTS *ncons = NULL;
-	GENERAL_SUBTREE *sub = NULL;
-	ncons = NAME_CONSTRAINTS_new();
-	if (!ncons)
-		goto memerr;
-	for(i = 0; i < sk_CONF_VALUE_num(nval); i++)
-		{
-		val = sk_CONF_VALUE_value(nval, i);
-		if (!strncmp(val->name, "permitted", 9) && val->name[9])
-			{
-			ptree = &ncons->permittedSubtrees;
-			tval.name = val->name + 10;
-			}
-		else if (!strncmp(val->name, "excluded", 8) && val->name[8])
-			{
-			ptree = &ncons->excludedSubtrees;
-			tval.name = val->name + 9;
-			}
-		else
-			{
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SYNTAX);
-			goto err;
-			}
-		tval.value = val->value;
-		sub = GENERAL_SUBTREE_new();
-		if (!v2i_GENERAL_NAME_ex(sub->base, method, ctx, &tval, 1))
-			goto err;
-		if (!*ptree)
-			*ptree = sk_GENERAL_SUBTREE_new_null();
-		if (!*ptree || !sk_GENERAL_SUBTREE_push(*ptree, sub))
-			goto memerr;
-		sub = NULL;
-		}
+                                  X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
+{
+    size_t i;
+    CONF_VALUE tval, *val;
+    STACK_OF(GENERAL_SUBTREE) **ptree = NULL;
+    NAME_CONSTRAINTS *ncons = NULL;
+    GENERAL_SUBTREE *sub = NULL;
+    ncons = NAME_CONSTRAINTS_new();
+    if (!ncons)
+        goto memerr;
+    for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+        val = sk_CONF_VALUE_value(nval, i);
+        if (!strncmp(val->name, "permitted", 9) && val->name[9]) {
+            ptree = &ncons->permittedSubtrees;
+            tval.name = val->name + 10;
+        } else if (!strncmp(val->name, "excluded", 8) && val->name[8]) {
+            ptree = &ncons->excludedSubtrees;
+            tval.name = val->name + 9;
+        } else {
+            OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SYNTAX);
+            goto err;
+        }
+        tval.value = val->value;
+        sub = GENERAL_SUBTREE_new();
+        if (!v2i_GENERAL_NAME_ex(sub->base, method, ctx, &tval, 1))
+            goto err;
+        if (!*ptree)
+            *ptree = sk_GENERAL_SUBTREE_new_null();
+        if (!*ptree || !sk_GENERAL_SUBTREE_push(*ptree, sub))
+            goto memerr;
+        sub = NULL;
+    }
 
-	return ncons;
+    return ncons;
 
-	memerr:
-	OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-	err:
-	if (ncons)
-		NAME_CONSTRAINTS_free(ncons);
-	if (sub)
-		GENERAL_SUBTREE_free(sub);
+ memerr:
+    OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+ err:
+    if (ncons)
+        NAME_CONSTRAINTS_free(ncons);
+    if (sub)
+        GENERAL_SUBTREE_free(sub);
 
-	return NULL;
-	}
-			
-
-	
+    return NULL;
+}
 
 static int i2r_NAME_CONSTRAINTS(const X509V3_EXT_METHOD *method, void *a,
-				BIO *bp, int ind)
-	{
-	NAME_CONSTRAINTS *ncons = a;
-	do_i2r_name_constraints(method, ncons->permittedSubtrees,
-					bp, ind, "Permitted");
-	do_i2r_name_constraints(method, ncons->excludedSubtrees,
-					bp, ind, "Excluded");
-	return 1;
-	}
+                                BIO *bp, int ind)
+{
+    NAME_CONSTRAINTS *ncons = a;
+    do_i2r_name_constraints(method, ncons->permittedSubtrees,
+                            bp, ind, "Permitted");
+    do_i2r_name_constraints(method, ncons->excludedSubtrees,
+                            bp, ind, "Excluded");
+    return 1;
+}
 
 static int do_i2r_name_constraints(const X509V3_EXT_METHOD *method,
-				   STACK_OF(GENERAL_SUBTREE) *trees,
-				   BIO *bp, int ind, const char *name)
-	{
-	GENERAL_SUBTREE *tree;
-	size_t i;
-	if (sk_GENERAL_SUBTREE_num(trees) > 0)
-		BIO_printf(bp, "%*s%s:\n", ind, "", name);
-	for(i = 0; i < sk_GENERAL_SUBTREE_num(trees); i++)
-		{
-		tree = sk_GENERAL_SUBTREE_value(trees, i);
-		BIO_printf(bp, "%*s", ind + 2, "");
-		if (tree->base->type == GEN_IPADD)
-			print_nc_ipadd(bp, tree->base->d.ip);
-		else
-			GENERAL_NAME_print(bp, tree->base);
-		BIO_puts(bp, "\n");
-		}
-	return 1;
-	}
+                                   STACK_OF(GENERAL_SUBTREE) *trees,
+                                   BIO *bp, int ind, const char *name)
+{
+    GENERAL_SUBTREE *tree;
+    size_t i;
+    if (sk_GENERAL_SUBTREE_num(trees) > 0)
+        BIO_printf(bp, "%*s%s:\n", ind, "", name);
+    for (i = 0; i < sk_GENERAL_SUBTREE_num(trees); i++) {
+        tree = sk_GENERAL_SUBTREE_value(trees, i);
+        BIO_printf(bp, "%*s", ind + 2, "");
+        if (tree->base->type == GEN_IPADD)
+            print_nc_ipadd(bp, tree->base->d.ip);
+        else
+            GENERAL_NAME_print(bp, tree->base);
+        BIO_puts(bp, "\n");
+    }
+    return 1;
+}
 
 static int print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip)
-	{
-	int i, len;
-	unsigned char *p;
-	p = ip->data;
-	len = ip->length;
-	BIO_puts(bp, "IP:");
-	if(len == 8)
-		{
-		BIO_printf(bp, "%d.%d.%d.%d/%d.%d.%d.%d",
-				p[0], p[1], p[2], p[3],
-				p[4], p[5], p[6], p[7]);
-		}
-	else if(len == 32)
-		{
-		for (i = 0; i < 16; i++)
-			{
-			BIO_printf(bp, "%X", p[0] << 8 | p[1]);
-			p += 2;
-			if (i == 7)
-				BIO_puts(bp, "/");
-			else if (i != 15)
-				BIO_puts(bp, ":");
-			}
-		}
-	else
-		BIO_printf(bp, "IP Address:<invalid>");
-	return 1;
-	}
+{
+    int i, len;
+    unsigned char *p;
+    p = ip->data;
+    len = ip->length;
+    BIO_puts(bp, "IP:");
+    if (len == 8) {
+        BIO_printf(bp, "%d.%d.%d.%d/%d.%d.%d.%d",
+                   p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
+    } else if (len == 32) {
+        for (i = 0; i < 16; i++) {
+            BIO_printf(bp, "%X", p[0] << 8 | p[1]);
+            p += 2;
+            if (i == 7)
+                BIO_puts(bp, "/");
+            else if (i != 15)
+                BIO_puts(bp, ":");
+        }
+    } else
+        BIO_printf(bp, "IP Address:<invalid>");
+    return 1;
+}
 
-/* Check a certificate conforms to a specified set of constraints.
- * Return values:
- *  X509_V_OK: All constraints obeyed.
- *  X509_V_ERR_PERMITTED_VIOLATION: Permitted subtree violation.
- *  X509_V_ERR_EXCLUDED_VIOLATION: Excluded subtree violation.
- *  X509_V_ERR_SUBTREE_MINMAX: Min or max values present and matching type.
- *  X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE:  Unsupported constraint type.
- *  X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX: bad unsupported constraint syntax.
- *  X509_V_ERR_UNSUPPORTED_NAME_SYNTAX: bad or unsupported syntax of name
-
+/*
+ * Check a certificate conforms to a specified set of constraints. Return
+ * values: X509_V_OK: All constraints obeyed.
+ * X509_V_ERR_PERMITTED_VIOLATION: Permitted subtree violation.
+ * X509_V_ERR_EXCLUDED_VIOLATION: Excluded subtree violation.
+ * X509_V_ERR_SUBTREE_MINMAX: Min or max values present and matching type.
+ * X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE: Unsupported constraint type.
+ * X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX: bad unsupported constraint
+ * syntax.  X509_V_ERR_UNSUPPORTED_NAME_SYNTAX: bad or unsupported syntax of
+ * name
+ *
  */
 
 int NAME_CONSTRAINTS_check(X509 *x, NAME_CONSTRAINTS *nc)
-	{
-	int r, i;
-	size_t j;
-	X509_NAME *nm;
+{
+    int r, i;
+    size_t j;
+    X509_NAME *nm;
 
-	nm = X509_get_subject_name(x);
+    nm = X509_get_subject_name(x);
 
-	if (X509_NAME_entry_count(nm) > 0)
-		{
-		GENERAL_NAME gntmp;
-		gntmp.type = GEN_DIRNAME;
-		gntmp.d.directoryName = nm;
+    if (X509_NAME_entry_count(nm) > 0) {
+        GENERAL_NAME gntmp;
+        gntmp.type = GEN_DIRNAME;
+        gntmp.d.directoryName = nm;
 
-		r = nc_match(&gntmp, nc);
+        r = nc_match(&gntmp, nc);
 
-		if (r != X509_V_OK)
-			return r;
+        if (r != X509_V_OK)
+            return r;
 
-		gntmp.type = GEN_EMAIL;
+        gntmp.type = GEN_EMAIL;
 
+        /* Process any email address attributes in subject name */
 
-		/* Process any email address attributes in subject name */
+        for (i = -1;;) {
+            X509_NAME_ENTRY *ne;
+            i = X509_NAME_get_index_by_NID(nm, NID_pkcs9_emailAddress, i);
+            if (i == -1)
+                break;
+            ne = X509_NAME_get_entry(nm, i);
+            gntmp.d.rfc822Name = X509_NAME_ENTRY_get_data(ne);
+            if (gntmp.d.rfc822Name->type != V_ASN1_IA5STRING)
+                return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
 
-		for (i = -1;;)
-			{
-			X509_NAME_ENTRY *ne;
-			i = X509_NAME_get_index_by_NID(nm,
-						       NID_pkcs9_emailAddress,
-						       i);
-			if (i == -1)
-				break;
-			ne = X509_NAME_get_entry(nm, i);
-			gntmp.d.rfc822Name = X509_NAME_ENTRY_get_data(ne);
-			if (gntmp.d.rfc822Name->type != V_ASN1_IA5STRING)
-				return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
+            r = nc_match(&gntmp, nc);
 
-			r = nc_match(&gntmp, nc);
+            if (r != X509_V_OK)
+                return r;
+        }
 
-			if (r != X509_V_OK)
-				return r;
-			}
-		
-		}
+    }
 
-	for (j = 0; j < sk_GENERAL_NAME_num(x->altname); j++)
-		{
-		GENERAL_NAME *gen = sk_GENERAL_NAME_value(x->altname, j);
-		r = nc_match(gen, nc);
-		if (r != X509_V_OK)
-			return r;
-		}
+    for (j = 0; j < sk_GENERAL_NAME_num(x->altname); j++) {
+        GENERAL_NAME *gen = sk_GENERAL_NAME_value(x->altname, j);
+        r = nc_match(gen, nc);
+        if (r != X509_V_OK)
+            return r;
+    }
 
-	return X509_V_OK;
+    return X509_V_OK;
 
-	}
+}
 
 static int nc_match(GENERAL_NAME *gen, NAME_CONSTRAINTS *nc)
-	{
-	GENERAL_SUBTREE *sub;
-	int r, match = 0;
-	size_t i;
+{
+    GENERAL_SUBTREE *sub;
+    int r, match = 0;
+    size_t i;
 
-	/* Permitted subtrees: if any subtrees exist of matching the type
-	 * at least one subtree must match.
-	 */
+    /*
+     * Permitted subtrees: if any subtrees exist of matching the type at
+     * least one subtree must match.
+     */
 
-	for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->permittedSubtrees); i++)
-		{
-		sub = sk_GENERAL_SUBTREE_value(nc->permittedSubtrees, i);
-		if (gen->type != sub->base->type)
-			continue;
-		if (sub->minimum || sub->maximum)
-			return X509_V_ERR_SUBTREE_MINMAX;
-		/* If we already have a match don't bother trying any more */
-		if (match == 2)
-			continue;
-		if (match == 0)
-			match = 1;
-		r = nc_match_single(gen, sub->base);
-		if (r == X509_V_OK)
-			match = 2;
-		else if (r != X509_V_ERR_PERMITTED_VIOLATION)
-			return r;
-		}
+    for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->permittedSubtrees); i++) {
+        sub = sk_GENERAL_SUBTREE_value(nc->permittedSubtrees, i);
+        if (gen->type != sub->base->type)
+            continue;
+        if (sub->minimum || sub->maximum)
+            return X509_V_ERR_SUBTREE_MINMAX;
+        /* If we already have a match don't bother trying any more */
+        if (match == 2)
+            continue;
+        if (match == 0)
+            match = 1;
+        r = nc_match_single(gen, sub->base);
+        if (r == X509_V_OK)
+            match = 2;
+        else if (r != X509_V_ERR_PERMITTED_VIOLATION)
+            return r;
+    }
 
-	if (match == 1)
-		return X509_V_ERR_PERMITTED_VIOLATION;
+    if (match == 1)
+        return X509_V_ERR_PERMITTED_VIOLATION;
 
-	/* Excluded subtrees: must not match any of these */
+    /* Excluded subtrees: must not match any of these */
 
-	for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->excludedSubtrees); i++)
-		{
-		sub = sk_GENERAL_SUBTREE_value(nc->excludedSubtrees, i);
-		if (gen->type != sub->base->type)
-			continue;
-		if (sub->minimum || sub->maximum)
-			return X509_V_ERR_SUBTREE_MINMAX;
+    for (i = 0; i < sk_GENERAL_SUBTREE_num(nc->excludedSubtrees); i++) {
+        sub = sk_GENERAL_SUBTREE_value(nc->excludedSubtrees, i);
+        if (gen->type != sub->base->type)
+            continue;
+        if (sub->minimum || sub->maximum)
+            return X509_V_ERR_SUBTREE_MINMAX;
 
-		r = nc_match_single(gen, sub->base);
-		if (r == X509_V_OK)
-			return X509_V_ERR_EXCLUDED_VIOLATION;
-		else if (r != X509_V_ERR_PERMITTED_VIOLATION)
-			return r;
+        r = nc_match_single(gen, sub->base);
+        if (r == X509_V_OK)
+            return X509_V_ERR_EXCLUDED_VIOLATION;
+        else if (r != X509_V_ERR_PERMITTED_VIOLATION)
+            return r;
 
-		}
+    }
 
-	return X509_V_OK;
+    return X509_V_OK;
 
-	}
+}
 
 static int nc_match_single(GENERAL_NAME *gen, GENERAL_NAME *base)
-	{
-	switch(base->type)
-		{
-		case GEN_DIRNAME:
-		return nc_dn(gen->d.directoryName, base->d.directoryName);
+{
+    switch (base->type) {
+    case GEN_DIRNAME:
+        return nc_dn(gen->d.directoryName, base->d.directoryName);
 
-		case GEN_DNS:
-		return nc_dns(gen->d.dNSName, base->d.dNSName);
+    case GEN_DNS:
+        return nc_dns(gen->d.dNSName, base->d.dNSName);
 
-		case GEN_EMAIL:
-		return nc_email(gen->d.rfc822Name, base->d.rfc822Name);
+    case GEN_EMAIL:
+        return nc_email(gen->d.rfc822Name, base->d.rfc822Name);
 
-		case GEN_URI:
-		return nc_uri(gen->d.uniformResourceIdentifier,
-					base->d.uniformResourceIdentifier);
+    case GEN_URI:
+        return nc_uri(gen->d.uniformResourceIdentifier,
+                      base->d.uniformResourceIdentifier);
 
-		default:
-		return X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE;
-		}
+    default:
+        return X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE;
+    }
 
-	}
+}
 
-/* directoryName name constraint matching.
- * The canonical encoding of X509_NAME makes this comparison easy. It is
- * matched if the subtree is a subset of the name.
+/*
+ * directoryName name constraint matching. The canonical encoding of
+ * X509_NAME makes this comparison easy. It is matched if the subtree is a
+ * subset of the name.
  */
 
 static int nc_dn(X509_NAME *nm, X509_NAME *base)
-	{
-	/* Ensure canonical encodings are up to date.  */
-	if (nm->modified && i2d_X509_NAME(nm, NULL) < 0)
-		return X509_V_ERR_OUT_OF_MEM;
-	if (base->modified && i2d_X509_NAME(base, NULL) < 0)
-		return X509_V_ERR_OUT_OF_MEM;
-	if (base->canon_enclen > nm->canon_enclen)
-		return X509_V_ERR_PERMITTED_VIOLATION;
-	if (memcmp(base->canon_enc, nm->canon_enc, base->canon_enclen))
-		return X509_V_ERR_PERMITTED_VIOLATION;
-	return X509_V_OK;
-	}
+{
+    /* Ensure canonical encodings are up to date.  */
+    if (nm->modified && i2d_X509_NAME(nm, NULL) < 0)
+        return X509_V_ERR_OUT_OF_MEM;
+    if (base->modified && i2d_X509_NAME(base, NULL) < 0)
+        return X509_V_ERR_OUT_OF_MEM;
+    if (base->canon_enclen > nm->canon_enclen)
+        return X509_V_ERR_PERMITTED_VIOLATION;
+    if (OPENSSL_memcmp(base->canon_enc, nm->canon_enc, base->canon_enclen))
+        return X509_V_ERR_PERMITTED_VIOLATION;
+    return X509_V_OK;
+}
 
 static int nc_dns(ASN1_IA5STRING *dns, ASN1_IA5STRING *base)
-	{
-	char *baseptr = (char *)base->data;
-	char *dnsptr = (char *)dns->data;
-	/* Empty matches everything */
-	if (!*baseptr)
-		return X509_V_OK;
-	/* Otherwise can add zero or more components on the left so
-	 * compare RHS and if dns is longer and expect '.' as preceding
-	 * character.
-	 */
-	if (dns->length > base->length)
-		{
-		dnsptr += dns->length - base->length;
-		if (*baseptr != '.' && dnsptr[-1] != '.')
-			return X509_V_ERR_PERMITTED_VIOLATION;
-		}
+{
+    char *baseptr = (char *)base->data;
+    char *dnsptr = (char *)dns->data;
+    /* Empty matches everything */
+    if (!*baseptr)
+        return X509_V_OK;
+    /*
+     * Otherwise can add zero or more components on the left so compare RHS
+     * and if dns is longer and expect '.' as preceding character.
+     */
+    if (dns->length > base->length) {
+        dnsptr += dns->length - base->length;
+        if (*baseptr != '.' && dnsptr[-1] != '.')
+            return X509_V_ERR_PERMITTED_VIOLATION;
+    }
 
-	if (OPENSSL_strcasecmp(baseptr, dnsptr))
-			return X509_V_ERR_PERMITTED_VIOLATION;
+    if (OPENSSL_strcasecmp(baseptr, dnsptr))
+        return X509_V_ERR_PERMITTED_VIOLATION;
 
-	return X509_V_OK;
+    return X509_V_OK;
 
-	}
+}
 
 static int nc_email(ASN1_IA5STRING *eml, ASN1_IA5STRING *base)
-	{
-	const char *baseptr = (char *)base->data;
-	const char *emlptr = (char *)eml->data;
+{
+    const char *baseptr = (char *)base->data;
+    const char *emlptr = (char *)eml->data;
 
-	const char *baseat = strchr(baseptr, '@');
-	const char *emlat = strchr(emlptr, '@');
-	if (!emlat)
-		return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
-	/* Special case: inital '.' is RHS match */
-	if (!baseat && (*baseptr == '.'))
-		{
-		if (eml->length > base->length)
-			{
-			emlptr += eml->length - base->length;
-			if (!OPENSSL_strcasecmp(baseptr, emlptr))
-				return X509_V_OK;
-			}
-		return X509_V_ERR_PERMITTED_VIOLATION;
-		}
+    const char *baseat = strchr(baseptr, '@');
+    const char *emlat = strchr(emlptr, '@');
+    if (!emlat)
+        return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
+    /* Special case: inital '.' is RHS match */
+    if (!baseat && (*baseptr == '.')) {
+        if (eml->length > base->length) {
+            emlptr += eml->length - base->length;
+            if (!OPENSSL_strcasecmp(baseptr, emlptr))
+                return X509_V_OK;
+        }
+        return X509_V_ERR_PERMITTED_VIOLATION;
+    }
 
-	/* If we have anything before '@' match local part */
+    /* If we have anything before '@' match local part */
 
-	if (baseat)
-		{
-		if (baseat != baseptr)
-			{
-			if ((baseat - baseptr) != (emlat - emlptr))
-				return X509_V_ERR_PERMITTED_VIOLATION;
-			/* Case sensitive match of local part */
-			if (strncmp(baseptr, emlptr, emlat - emlptr))
-				return X509_V_ERR_PERMITTED_VIOLATION;
-			}
-		/* Position base after '@' */
-		baseptr = baseat + 1;
-		}
-	emlptr = emlat + 1;
-	/* Just have hostname left to match: case insensitive */
-	if (OPENSSL_strcasecmp(baseptr, emlptr))
-		return X509_V_ERR_PERMITTED_VIOLATION;
+    if (baseat) {
+        if (baseat != baseptr) {
+            if ((baseat - baseptr) != (emlat - emlptr))
+                return X509_V_ERR_PERMITTED_VIOLATION;
+            /* Case sensitive match of local part */
+            if (strncmp(baseptr, emlptr, emlat - emlptr))
+                return X509_V_ERR_PERMITTED_VIOLATION;
+        }
+        /* Position base after '@' */
+        baseptr = baseat + 1;
+    }
+    emlptr = emlat + 1;
+    /* Just have hostname left to match: case insensitive */
+    if (OPENSSL_strcasecmp(baseptr, emlptr))
+        return X509_V_ERR_PERMITTED_VIOLATION;
 
-	return X509_V_OK;
+    return X509_V_OK;
 
-	}
+}
 
 static int nc_uri(ASN1_IA5STRING *uri, ASN1_IA5STRING *base)
-	{
-	const char *baseptr = (char *)base->data;
-	const char *hostptr = (char *)uri->data;
-	const char *p = strchr(hostptr, ':');
-	int hostlen;
-	/* Check for foo:// and skip past it */
-	if (!p || (p[1] != '/') || (p[2] != '/'))
-		return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
-	hostptr = p + 3;
+{
+    const char *baseptr = (char *)base->data;
+    const char *hostptr = (char *)uri->data;
+    const char *p = strchr(hostptr, ':');
+    int hostlen;
+    /* Check for foo:// and skip past it */
+    if (!p || (p[1] != '/') || (p[2] != '/'))
+        return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
+    hostptr = p + 3;
 
-	/* Determine length of hostname part of URI */
+    /* Determine length of hostname part of URI */
 
-	/* Look for a port indicator as end of hostname first */
+    /* Look for a port indicator as end of hostname first */
 
-	p = strchr(hostptr, ':');
-	/* Otherwise look for trailing slash */
-	if (!p)
-		p = strchr(hostptr, '/');
+    p = strchr(hostptr, ':');
+    /* Otherwise look for trailing slash */
+    if (!p)
+        p = strchr(hostptr, '/');
 
-	if (!p)
-		hostlen = strlen(hostptr);
-	else
-		hostlen = p - hostptr;
+    if (!p)
+        hostlen = strlen(hostptr);
+    else
+        hostlen = p - hostptr;
 
-	if (hostlen == 0)
-		return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
+    if (hostlen == 0)
+        return X509_V_ERR_UNSUPPORTED_NAME_SYNTAX;
 
-	/* Special case: inital '.' is RHS match */
-	if (*baseptr == '.')
-		{
-		if (hostlen > base->length)
-			{
-			p = hostptr + hostlen - base->length;
-			if (!OPENSSL_strncasecmp(p, baseptr, base->length))
-				return X509_V_OK;
-			}
-		return X509_V_ERR_PERMITTED_VIOLATION;
-		}
+    /* Special case: inital '.' is RHS match */
+    if (*baseptr == '.') {
+        if (hostlen > base->length) {
+            p = hostptr + hostlen - base->length;
+            if (!OPENSSL_strncasecmp(p, baseptr, base->length))
+                return X509_V_OK;
+        }
+        return X509_V_ERR_PERMITTED_VIOLATION;
+    }
 
-	if ((base->length != (int)hostlen) || OPENSSL_strncasecmp(hostptr, baseptr, hostlen))
-		return X509_V_ERR_PERMITTED_VIOLATION;
+    if ((base->length != (int)hostlen)
+        || OPENSSL_strncasecmp(hostptr, baseptr, hostlen))
+        return X509_V_ERR_PERMITTED_VIOLATION;
 
-	return X509_V_OK;
+    return X509_V_OK;
 
-	}
+}
diff --git a/src/crypto/x509v3/v3_pci.c b/src/crypto/x509v3/v3_pci.c
index f19a37a..4352abe 100644
--- a/src/crypto/x509v3/v3_pci.c
+++ b/src/crypto/x509v3/v3_pci.c
@@ -1,6 +1,7 @@
 /* v3_pci.c -*- mode:C; c-file-style: "eay" -*- */
-/* Contributed to the OpenSSL Project 2004
- * by Richard Levitte (richard@levitte.org)
+/*
+ * Contributed to the OpenSSL Project 2004 by Richard Levitte
+ * (richard@levitte.org)
  */
 /* Copyright (c) 2004 Kungliga Tekniska Högskolan
  * (Royal Institute of Technology, Stockholm, Sweden).
@@ -34,7 +35,6 @@
  * SUCH DAMAGE.
  */
 
-#include <stdio.h>
 #include <string.h>
 
 #include <openssl/conf.h>
@@ -43,293 +43,245 @@
 #include <openssl/obj.h>
 #include <openssl/x509v3.h>
 
+#include "../internal.h"
+
 
 static int i2r_pci(X509V3_EXT_METHOD *method, PROXY_CERT_INFO_EXTENSION *ext,
-	BIO *out, int indent);
+                   BIO *out, int indent);
 static PROXY_CERT_INFO_EXTENSION *r2i_pci(X509V3_EXT_METHOD *method,
-	X509V3_CTX *ctx, char *str);
+                                          X509V3_CTX *ctx, char *str);
 
 const X509V3_EXT_METHOD v3_pci =
-	{ NID_proxyCertInfo, 0, ASN1_ITEM_ref(PROXY_CERT_INFO_EXTENSION),
-	  0,0,0,0,
-	  0,0,
-	  NULL, NULL,
-	  (X509V3_EXT_I2R)i2r_pci,
-	  (X509V3_EXT_R2I)r2i_pci,
-	  NULL,
-	};
+    { NID_proxyCertInfo, 0, ASN1_ITEM_ref(PROXY_CERT_INFO_EXTENSION),
+    0, 0, 0, 0,
+    0, 0,
+    NULL, NULL,
+    (X509V3_EXT_I2R)i2r_pci,
+    (X509V3_EXT_R2I)r2i_pci,
+    NULL,
+};
 
 static int i2r_pci(X509V3_EXT_METHOD *method, PROXY_CERT_INFO_EXTENSION *pci,
-	BIO *out, int indent)
-	{
-	BIO_printf(out, "%*sPath Length Constraint: ", indent, "");
-	if (pci->pcPathLengthConstraint)
-	  i2a_ASN1_INTEGER(out, pci->pcPathLengthConstraint);
-	else
-	  BIO_printf(out, "infinite");
-	BIO_puts(out, "\n");
-	BIO_printf(out, "%*sPolicy Language: ", indent, "");
-	i2a_ASN1_OBJECT(out, pci->proxyPolicy->policyLanguage);
-	BIO_puts(out, "\n");
-	if (pci->proxyPolicy->policy && pci->proxyPolicy->policy->data)
-	  BIO_printf(out, "%*sPolicy Text: %s\n", indent, "",
-		     pci->proxyPolicy->policy->data);
-	return 1;
-	}
+                   BIO *out, int indent)
+{
+    BIO_printf(out, "%*sPath Length Constraint: ", indent, "");
+    if (pci->pcPathLengthConstraint)
+        i2a_ASN1_INTEGER(out, pci->pcPathLengthConstraint);
+    else
+        BIO_printf(out, "infinite");
+    BIO_puts(out, "\n");
+    BIO_printf(out, "%*sPolicy Language: ", indent, "");
+    i2a_ASN1_OBJECT(out, pci->proxyPolicy->policyLanguage);
+    BIO_puts(out, "\n");
+    if (pci->proxyPolicy->policy && pci->proxyPolicy->policy->data)
+        BIO_printf(out, "%*sPolicy Text: %s\n", indent, "",
+                   pci->proxyPolicy->policy->data);
+    return 1;
+}
 
 static int process_pci_value(CONF_VALUE *val,
-	ASN1_OBJECT **language, ASN1_INTEGER **pathlen,
-	ASN1_OCTET_STRING **policy)
-	{
-	int free_policy = 0;
+                             ASN1_OBJECT **language, ASN1_INTEGER **pathlen,
+                             ASN1_OCTET_STRING **policy)
+{
+    int free_policy = 0;
 
-	if (strcmp(val->name, "language") == 0)
-		{
-		if (*language)
-			{
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED);
-			X509V3_conf_err(val);
-			return 0;
-			}
-		if (!(*language = OBJ_txt2obj(val->value, 0)))
-			{
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER);
-			X509V3_conf_err(val);
-			return 0;
-			}
-		}
-	else if (strcmp(val->name, "pathlen") == 0)
-		{
-		if (*pathlen)
-			{
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED);
-			X509V3_conf_err(val);
-			return 0;
-			}
-		if (!X509V3_get_value_int(val, pathlen))
-			{
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_POLICY_PATH_LENGTH);
-			X509V3_conf_err(val);
-			return 0;
-			}
-		}
-	else if (strcmp(val->name, "policy") == 0)
-		{
-		unsigned char *tmp_data = NULL;
-		long val_len;
-		if (!*policy)
-			{
-			*policy = ASN1_OCTET_STRING_new();
-			if (!*policy)
-				{
-				OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-				X509V3_conf_err(val);
-				return 0;
-				}
-			free_policy = 1;
-			}
-		if (strncmp(val->value, "hex:", 4) == 0)
-			{
-			unsigned char *tmp_data2 =
-				string_to_hex(val->value + 4, &val_len);
+    if (strcmp(val->name, "language") == 0) {
+        if (*language) {
+            OPENSSL_PUT_ERROR(X509V3,
+                              X509V3_R_POLICY_LANGUAGE_ALREADY_DEFINED);
+            X509V3_conf_err(val);
+            return 0;
+        }
+        if (!(*language = OBJ_txt2obj(val->value, 0))) {
+            OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER);
+            X509V3_conf_err(val);
+            return 0;
+        }
+    } else if (strcmp(val->name, "pathlen") == 0) {
+        if (*pathlen) {
+            OPENSSL_PUT_ERROR(X509V3,
+                              X509V3_R_POLICY_PATH_LENGTH_ALREADY_DEFINED);
+            X509V3_conf_err(val);
+            return 0;
+        }
+        if (!X509V3_get_value_int(val, pathlen)) {
+            OPENSSL_PUT_ERROR(X509V3, X509V3_R_POLICY_PATH_LENGTH);
+            X509V3_conf_err(val);
+            return 0;
+        }
+    } else if (strcmp(val->name, "policy") == 0) {
+        unsigned char *tmp_data = NULL;
+        long val_len;
+        if (!*policy) {
+            *policy = ASN1_OCTET_STRING_new();
+            if (!*policy) {
+                OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+                X509V3_conf_err(val);
+                return 0;
+            }
+            free_policy = 1;
+        }
+        if (strncmp(val->value, "hex:", 4) == 0) {
+            unsigned char *tmp_data2 =
+                string_to_hex(val->value + 4, &val_len);
 
-			if (!tmp_data2) 
-				{
-				OPENSSL_PUT_ERROR(X509V3, X509V3_R_ILLEGAL_HEX_DIGIT);
-				X509V3_conf_err(val);
-				goto err;
-				}
+            if (!tmp_data2) {
+                OPENSSL_PUT_ERROR(X509V3, X509V3_R_ILLEGAL_HEX_DIGIT);
+                X509V3_conf_err(val);
+                goto err;
+            }
 
-			tmp_data = OPENSSL_realloc((*policy)->data,
-				(*policy)->length + val_len + 1);
-			if (tmp_data)
-				{
-				(*policy)->data = tmp_data;
-				memcpy(&(*policy)->data[(*policy)->length],
-					tmp_data2, val_len);
-				(*policy)->length += val_len;
-				(*policy)->data[(*policy)->length] = '\0';
-				}
-			else
-				{
-				OPENSSL_free(tmp_data2);
-				/* realloc failure implies the original data space is b0rked too! */
-				(*policy)->data = NULL;
-				(*policy)->length = 0;
-				OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-				X509V3_conf_err(val);
-				goto err;
-				}
-			OPENSSL_free(tmp_data2);
-			}
-		else if (strncmp(val->value, "file:", 5) == 0)
-			{
-			unsigned char buf[2048];
-			int n;
-			BIO *b = BIO_new_file(val->value + 5, "r");
-			if (!b)
-				{
-				OPENSSL_PUT_ERROR(X509V3, ERR_R_BIO_LIB);
-				X509V3_conf_err(val);
-				goto err;
-				}
-			while((n = BIO_read(b, buf, sizeof(buf))) > 0
-				|| (n == 0 && BIO_should_retry(b)))
-				{
-				if (!n) continue;
-
-				tmp_data = OPENSSL_realloc((*policy)->data,
-					(*policy)->length + n + 1);
-
-				if (!tmp_data)
-					break;
-
-				(*policy)->data = tmp_data;
-				memcpy(&(*policy)->data[(*policy)->length],
-					buf, n);
-				(*policy)->length += n;
-				(*policy)->data[(*policy)->length] = '\0';
-				}
-			BIO_free_all(b);
-
-			if (n < 0)
-				{
-				OPENSSL_PUT_ERROR(X509V3, ERR_R_BIO_LIB);
-				X509V3_conf_err(val);
-				goto err;
-				}
-			}
-		else if (strncmp(val->value, "text:", 5) == 0)
-			{
-			val_len = strlen(val->value + 5);
-			tmp_data = OPENSSL_realloc((*policy)->data,
-				(*policy)->length + val_len + 1);
-			if (tmp_data)
-				{
-				(*policy)->data = tmp_data;
-				memcpy(&(*policy)->data[(*policy)->length],
-					val->value + 5, val_len);
-				(*policy)->length += val_len;
-				(*policy)->data[(*policy)->length] = '\0';
-				}
-			else
-				{
-				/* realloc failure implies the original data space is b0rked too! */
-				(*policy)->data = NULL;
-				(*policy)->length = 0;
-				OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-				X509V3_conf_err(val);
-				goto err;
-				}
-			}
-		else
-			{
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_INCORRECT_POLICY_SYNTAX_TAG);
-			X509V3_conf_err(val);
-			goto err;
-			}
-		if (!tmp_data)
-			{
-			OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-			X509V3_conf_err(val);
-			goto err;
-			}
-		}
-	return 1;
-err:
-	if (free_policy)
-		{
-		ASN1_OCTET_STRING_free(*policy);
-		*policy = NULL;
-		}
-	return 0;
-	}
+            tmp_data = OPENSSL_realloc((*policy)->data,
+                                       (*policy)->length + val_len + 1);
+            if (tmp_data) {
+                (*policy)->data = tmp_data;
+                OPENSSL_memcpy(&(*policy)->data[(*policy)->length],
+                       tmp_data2, val_len);
+                (*policy)->length += val_len;
+                (*policy)->data[(*policy)->length] = '\0';
+            } else {
+                OPENSSL_free(tmp_data2);
+                /*
+                 * realloc failure implies the original data space is b0rked
+                 * too!
+                 */
+                (*policy)->data = NULL;
+                (*policy)->length = 0;
+                OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+                X509V3_conf_err(val);
+                goto err;
+            }
+            OPENSSL_free(tmp_data2);
+        } else if (strncmp(val->value, "text:", 5) == 0) {
+            val_len = strlen(val->value + 5);
+            tmp_data = OPENSSL_realloc((*policy)->data,
+                                       (*policy)->length + val_len + 1);
+            if (tmp_data) {
+                (*policy)->data = tmp_data;
+                OPENSSL_memcpy(&(*policy)->data[(*policy)->length],
+                       val->value + 5, val_len);
+                (*policy)->length += val_len;
+                (*policy)->data[(*policy)->length] = '\0';
+            } else {
+                /*
+                 * realloc failure implies the original data space is b0rked
+                 * too!
+                 */
+                (*policy)->data = NULL;
+                (*policy)->length = 0;
+                OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+                X509V3_conf_err(val);
+                goto err;
+            }
+        } else {
+            OPENSSL_PUT_ERROR(X509V3, X509V3_R_INCORRECT_POLICY_SYNTAX_TAG);
+            X509V3_conf_err(val);
+            goto err;
+        }
+        if (!tmp_data) {
+            OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+            X509V3_conf_err(val);
+            goto err;
+        }
+    }
+    return 1;
+ err:
+    if (free_policy) {
+        ASN1_OCTET_STRING_free(*policy);
+        *policy = NULL;
+    }
+    return 0;
+}
 
 static PROXY_CERT_INFO_EXTENSION *r2i_pci(X509V3_EXT_METHOD *method,
-	X509V3_CTX *ctx, char *value)
-	{
-	PROXY_CERT_INFO_EXTENSION *pci = NULL;
-	STACK_OF(CONF_VALUE) *vals;
-	ASN1_OBJECT *language = NULL;
-	ASN1_INTEGER *pathlen = NULL;
-	ASN1_OCTET_STRING *policy = NULL;
-	size_t i, j;
-	int nid;
+                                          X509V3_CTX *ctx, char *value)
+{
+    PROXY_CERT_INFO_EXTENSION *pci = NULL;
+    STACK_OF(CONF_VALUE) *vals;
+    ASN1_OBJECT *language = NULL;
+    ASN1_INTEGER *pathlen = NULL;
+    ASN1_OCTET_STRING *policy = NULL;
+    size_t i, j;
+    int nid;
 
-	vals = X509V3_parse_list(value);
-	for (i = 0; i < sk_CONF_VALUE_num(vals); i++)
-		{
-		CONF_VALUE *cnf = sk_CONF_VALUE_value(vals, i);
-		if (!cnf->name || (*cnf->name != '@' && !cnf->value))
-			{
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_PROXY_POLICY_SETTING);
-			X509V3_conf_err(cnf);
-			goto err;
-			}
-		if (*cnf->name == '@')
-			{
-			STACK_OF(CONF_VALUE) *sect;
-			int success_p = 1;
+    vals = X509V3_parse_list(value);
+    for (i = 0; i < sk_CONF_VALUE_num(vals); i++) {
+        CONF_VALUE *cnf = sk_CONF_VALUE_value(vals, i);
+        if (!cnf->name || (*cnf->name != '@' && !cnf->value)) {
+            OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_PROXY_POLICY_SETTING);
+            X509V3_conf_err(cnf);
+            goto err;
+        }
+        if (*cnf->name == '@') {
+            STACK_OF(CONF_VALUE) *sect;
+            int success_p = 1;
 
-			sect = X509V3_get_section(ctx, cnf->name + 1);
-			if (!sect)
-				{
-				OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SECTION);
-				X509V3_conf_err(cnf);
-				goto err;
-				}
-			for (j = 0; success_p && j < sk_CONF_VALUE_num(sect); j++)
-				{
-				success_p =
-					process_pci_value(sk_CONF_VALUE_value(sect, j),
-						&language, &pathlen, &policy);
-				}
-			X509V3_section_free(ctx, sect);
-			if (!success_p)
-				goto err;
-			}
-		else
-			{
-			if (!process_pci_value(cnf,
-					&language, &pathlen, &policy))
-				{
-				X509V3_conf_err(cnf);
-				goto err;
-				}
-			}
-		}
+            sect = X509V3_get_section(ctx, cnf->name + 1);
+            if (!sect) {
+                OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_SECTION);
+                X509V3_conf_err(cnf);
+                goto err;
+            }
+            for (j = 0; success_p && j < sk_CONF_VALUE_num(sect); j++) {
+                success_p =
+                    process_pci_value(sk_CONF_VALUE_value(sect, j),
+                                      &language, &pathlen, &policy);
+            }
+            X509V3_section_free(ctx, sect);
+            if (!success_p)
+                goto err;
+        } else {
+            if (!process_pci_value(cnf, &language, &pathlen, &policy)) {
+                X509V3_conf_err(cnf);
+                goto err;
+            }
+        }
+    }
 
-	/* Language is mandatory */
-	if (!language)
-		{
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED);
-		goto err;
-		}
-	nid = OBJ_obj2nid(language);
-	if ((nid == NID_Independent || nid == NID_id_ppl_inheritAll) && policy)
-		{
-		OPENSSL_PUT_ERROR(X509V3,
-			X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY);
-		goto err;
-		}
+    /* Language is mandatory */
+    if (!language) {
+        OPENSSL_PUT_ERROR(X509V3,
+                          X509V3_R_NO_PROXY_CERT_POLICY_LANGUAGE_DEFINED);
+        goto err;
+    }
+    nid = OBJ_obj2nid(language);
+    if ((nid == NID_Independent || nid == NID_id_ppl_inheritAll) && policy) {
+        OPENSSL_PUT_ERROR(X509V3,
+                          X509V3_R_POLICY_WHEN_PROXY_LANGUAGE_REQUIRES_NO_POLICY);
+        goto err;
+    }
 
-	pci = PROXY_CERT_INFO_EXTENSION_new();
-	if (!pci)
-		{
-		OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-		goto err;
-		}
+    pci = PROXY_CERT_INFO_EXTENSION_new();
+    if (!pci) {
+        OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
 
-	pci->proxyPolicy->policyLanguage = language; language = NULL;
-	pci->proxyPolicy->policy = policy; policy = NULL;
-	pci->pcPathLengthConstraint = pathlen; pathlen = NULL;
-	goto end;
-err:
-	if (language) { ASN1_OBJECT_free(language); language = NULL; }
-	if (pathlen) { ASN1_INTEGER_free(pathlen); pathlen = NULL; }
-	if (policy) { ASN1_OCTET_STRING_free(policy); policy = NULL; }
-	if (pci) { PROXY_CERT_INFO_EXTENSION_free(pci); pci = NULL; }
-end:
-	sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
-	return pci;
-	}
+    pci->proxyPolicy->policyLanguage = language;
+    language = NULL;
+    pci->proxyPolicy->policy = policy;
+    policy = NULL;
+    pci->pcPathLengthConstraint = pathlen;
+    pathlen = NULL;
+    goto end;
+ err:
+    if (language) {
+        ASN1_OBJECT_free(language);
+        language = NULL;
+    }
+    if (pathlen) {
+        ASN1_INTEGER_free(pathlen);
+        pathlen = NULL;
+    }
+    if (policy) {
+        ASN1_OCTET_STRING_free(policy);
+        policy = NULL;
+    }
+    if (pci) {
+        PROXY_CERT_INFO_EXTENSION_free(pci);
+        pci = NULL;
+    }
+ end:
+    sk_CONF_VALUE_pop_free(vals, X509V3_conf_free);
+    return pci;
+}
diff --git a/src/crypto/x509v3/v3_pcia.c b/src/crypto/x509v3/v3_pcia.c
index e3e3192..3f285f3 100644
--- a/src/crypto/x509v3/v3_pcia.c
+++ b/src/crypto/x509v3/v3_pcia.c
@@ -1,6 +1,7 @@
 /* v3_pcia.c -*- mode:C; c-file-style: "eay" -*- */
-/* Contributed to the OpenSSL Project 2004
- * by Richard Levitte (richard@levitte.org)
+/*
+ * Contributed to the OpenSSL Project 2004 by Richard Levitte
+ * (richard@levitte.org)
  */
 /* Copyright (c) 2004 Kungliga Tekniska Högskolan
  * (Royal Institute of Technology, Stockholm, Sweden).
@@ -40,17 +41,17 @@
 
 
 ASN1_SEQUENCE(PROXY_POLICY) =
-	{
-	ASN1_SIMPLE(PROXY_POLICY,policyLanguage,ASN1_OBJECT),
-	ASN1_OPT(PROXY_POLICY,policy,ASN1_OCTET_STRING)
+        {
+        ASN1_SIMPLE(PROXY_POLICY,policyLanguage,ASN1_OBJECT),
+        ASN1_OPT(PROXY_POLICY,policy,ASN1_OCTET_STRING)
 } ASN1_SEQUENCE_END(PROXY_POLICY)
 
 IMPLEMENT_ASN1_FUNCTIONS(PROXY_POLICY)
 
 ASN1_SEQUENCE(PROXY_CERT_INFO_EXTENSION) =
-	{
-	ASN1_OPT(PROXY_CERT_INFO_EXTENSION,pcPathLengthConstraint,ASN1_INTEGER),
-	ASN1_SIMPLE(PROXY_CERT_INFO_EXTENSION,proxyPolicy,PROXY_POLICY)
+        {
+        ASN1_OPT(PROXY_CERT_INFO_EXTENSION,pcPathLengthConstraint,ASN1_INTEGER),
+        ASN1_SIMPLE(PROXY_CERT_INFO_EXTENSION,proxyPolicy,PROXY_POLICY)
 } ASN1_SEQUENCE_END(PROXY_CERT_INFO_EXTENSION)
 
 IMPLEMENT_ASN1_FUNCTIONS(PROXY_CERT_INFO_EXTENSION)
diff --git a/src/crypto/x509v3/v3_pcons.c b/src/crypto/x509v3/v3_pcons.c
index b752290..1a46314 100644
--- a/src/crypto/x509v3/v3_pcons.c
+++ b/src/crypto/x509v3/v3_pcons.c
@@ -1,5 +1,6 @@
 /* v3_pcons.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project.
  */
 /* ====================================================================
@@ -10,7 +11,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -54,7 +55,6 @@
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com). */
 
-
 #include <stdio.h>
 #include <string.h>
 
@@ -65,78 +65,75 @@
 #include <openssl/obj.h>
 #include <openssl/x509v3.h>
 
-
-static STACK_OF(CONF_VALUE) *
-i2v_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD *method, void *bcons,
-		       STACK_OF(CONF_VALUE) *extlist);
+static STACK_OF(CONF_VALUE) *i2v_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD
+                                                    *method, void *bcons, STACK_OF(CONF_VALUE)
+                                                    *extlist);
 static void *v2i_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD *method,
-				    X509V3_CTX *ctx,
-				    STACK_OF(CONF_VALUE) *values);
+                                    X509V3_CTX *ctx,
+                                    STACK_OF(CONF_VALUE) *values);
 
 const X509V3_EXT_METHOD v3_policy_constraints = {
-NID_policy_constraints, 0,
-ASN1_ITEM_ref(POLICY_CONSTRAINTS),
-0,0,0,0,
-0,0,
-i2v_POLICY_CONSTRAINTS,
-v2i_POLICY_CONSTRAINTS,
-NULL,NULL,
-NULL
+    NID_policy_constraints, 0,
+    ASN1_ITEM_ref(POLICY_CONSTRAINTS),
+    0, 0, 0, 0,
+    0, 0,
+    i2v_POLICY_CONSTRAINTS,
+    v2i_POLICY_CONSTRAINTS,
+    NULL, NULL,
+    NULL
 };
 
 ASN1_SEQUENCE(POLICY_CONSTRAINTS) = {
-	ASN1_IMP_OPT(POLICY_CONSTRAINTS, requireExplicitPolicy, ASN1_INTEGER,0),
-	ASN1_IMP_OPT(POLICY_CONSTRAINTS, inhibitPolicyMapping, ASN1_INTEGER,1)
+        ASN1_IMP_OPT(POLICY_CONSTRAINTS, requireExplicitPolicy, ASN1_INTEGER,0),
+        ASN1_IMP_OPT(POLICY_CONSTRAINTS, inhibitPolicyMapping, ASN1_INTEGER,1)
 } ASN1_SEQUENCE_END(POLICY_CONSTRAINTS)
 
 IMPLEMENT_ASN1_ALLOC_FUNCTIONS(POLICY_CONSTRAINTS)
 
-
-static STACK_OF(CONF_VALUE) *
-i2v_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD *method, void *a,
-		       STACK_OF(CONF_VALUE) *extlist)
+static STACK_OF(CONF_VALUE) *i2v_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD
+                                                    *method, void *a, STACK_OF(CONF_VALUE)
+                                                    *extlist)
 {
-	POLICY_CONSTRAINTS *pcons = a;
-	X509V3_add_value_int("Require Explicit Policy",
-			pcons->requireExplicitPolicy, &extlist);
-	X509V3_add_value_int("Inhibit Policy Mapping",
-			pcons->inhibitPolicyMapping, &extlist);
-	return extlist;
+    POLICY_CONSTRAINTS *pcons = a;
+    X509V3_add_value_int("Require Explicit Policy",
+                         pcons->requireExplicitPolicy, &extlist);
+    X509V3_add_value_int("Inhibit Policy Mapping",
+                         pcons->inhibitPolicyMapping, &extlist);
+    return extlist;
 }
 
 static void *v2i_POLICY_CONSTRAINTS(const X509V3_EXT_METHOD *method,
-				    X509V3_CTX *ctx,
-				    STACK_OF(CONF_VALUE) *values)
+                                    X509V3_CTX *ctx,
+                                    STACK_OF(CONF_VALUE) *values)
 {
-	POLICY_CONSTRAINTS *pcons=NULL;
-	CONF_VALUE *val;
-	size_t i;
-	if(!(pcons = POLICY_CONSTRAINTS_new())) {
-		OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-		return NULL;
-	}
-	for(i = 0; i < sk_CONF_VALUE_num(values); i++) {
-		val = sk_CONF_VALUE_value(values, i);
-		if(!strcmp(val->name, "requireExplicitPolicy")) {
-			if(!X509V3_get_value_int(val,
-				&pcons->requireExplicitPolicy)) goto err;
-		} else if(!strcmp(val->name, "inhibitPolicyMapping")) {
-			if(!X509V3_get_value_int(val,
-				&pcons->inhibitPolicyMapping)) goto err;
-		} else {
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NAME);
-			X509V3_conf_err(val);
-			goto err;
-		}
-	}
-	if (!pcons->inhibitPolicyMapping && !pcons->requireExplicitPolicy) {
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_ILLEGAL_EMPTY_EXTENSION);
-		goto err;
-	}
+    POLICY_CONSTRAINTS *pcons = NULL;
+    CONF_VALUE *val;
+    size_t i;
+    if (!(pcons = POLICY_CONSTRAINTS_new())) {
+        OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+    for (i = 0; i < sk_CONF_VALUE_num(values); i++) {
+        val = sk_CONF_VALUE_value(values, i);
+        if (!strcmp(val->name, "requireExplicitPolicy")) {
+            if (!X509V3_get_value_int(val, &pcons->requireExplicitPolicy))
+                goto err;
+        } else if (!strcmp(val->name, "inhibitPolicyMapping")) {
+            if (!X509V3_get_value_int(val, &pcons->inhibitPolicyMapping))
+                goto err;
+        } else {
+            OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NAME);
+            X509V3_conf_err(val);
+            goto err;
+        }
+    }
+    if (!pcons->inhibitPolicyMapping && !pcons->requireExplicitPolicy) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_ILLEGAL_EMPTY_EXTENSION);
+        goto err;
+    }
 
-	return pcons;
-	err:
-	POLICY_CONSTRAINTS_free(pcons);
-	return NULL;
+    return pcons;
+ err:
+    POLICY_CONSTRAINTS_free(pcons);
+    return NULL;
 }
-
diff --git a/src/crypto/x509v3/v3_pku.c b/src/crypto/x509v3/v3_pku.c
index 445eda6..e4868b4 100644
--- a/src/crypto/x509v3/v3_pku.c
+++ b/src/crypto/x509v3/v3_pku.c
@@ -1,6 +1,7 @@
 /* v3_pku.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
  */
 /* ====================================================================
  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
@@ -10,7 +11,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -62,48 +63,48 @@
 #include <openssl/obj.h>
 #include <openssl/x509v3.h>
 
-
-static int i2r_PKEY_USAGE_PERIOD(X509V3_EXT_METHOD *method, PKEY_USAGE_PERIOD *usage, BIO *out, int indent);
+static int i2r_PKEY_USAGE_PERIOD(X509V3_EXT_METHOD *method,
+                                 PKEY_USAGE_PERIOD *usage, BIO *out,
+                                 int indent);
 /*
-static PKEY_USAGE_PERIOD *v2i_PKEY_USAGE_PERIOD(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *values);
-*/
+ * static PKEY_USAGE_PERIOD *v2i_PKEY_USAGE_PERIOD(X509V3_EXT_METHOD *method,
+ * X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *values);
+ */
 const X509V3_EXT_METHOD v3_pkey_usage_period = {
-NID_private_key_usage_period, 0, ASN1_ITEM_ref(PKEY_USAGE_PERIOD),
-0,0,0,0,
-0,0,0,0,
-(X509V3_EXT_I2R)i2r_PKEY_USAGE_PERIOD, NULL,
-NULL
+    NID_private_key_usage_period, 0, ASN1_ITEM_ref(PKEY_USAGE_PERIOD),
+    0, 0, 0, 0,
+    0, 0, 0, 0,
+    (X509V3_EXT_I2R)i2r_PKEY_USAGE_PERIOD, NULL,
+    NULL
 };
 
 ASN1_SEQUENCE(PKEY_USAGE_PERIOD) = {
-	ASN1_IMP_OPT(PKEY_USAGE_PERIOD, notBefore, ASN1_GENERALIZEDTIME, 0),
-	ASN1_IMP_OPT(PKEY_USAGE_PERIOD, notAfter, ASN1_GENERALIZEDTIME, 1)
+        ASN1_IMP_OPT(PKEY_USAGE_PERIOD, notBefore, ASN1_GENERALIZEDTIME, 0),
+        ASN1_IMP_OPT(PKEY_USAGE_PERIOD, notAfter, ASN1_GENERALIZEDTIME, 1)
 } ASN1_SEQUENCE_END(PKEY_USAGE_PERIOD)
 
 IMPLEMENT_ASN1_FUNCTIONS(PKEY_USAGE_PERIOD)
 
 static int i2r_PKEY_USAGE_PERIOD(X509V3_EXT_METHOD *method,
-	     PKEY_USAGE_PERIOD *usage, BIO *out, int indent)
+                                 PKEY_USAGE_PERIOD *usage, BIO *out,
+                                 int indent)
 {
-	BIO_printf(out, "%*s", indent, "");
-	if(usage->notBefore) {
-		BIO_write(out, "Not Before: ", 12);
-		ASN1_GENERALIZEDTIME_print(out, usage->notBefore);
-		if(usage->notAfter) BIO_write(out, ", ", 2);
-	}
-	if(usage->notAfter) {
-		BIO_write(out, "Not After: ", 11);
-		ASN1_GENERALIZEDTIME_print(out, usage->notAfter);
-	}
-	return 1;
+    BIO_printf(out, "%*s", indent, "");
+    if (usage->notBefore) {
+        BIO_write(out, "Not Before: ", 12);
+        ASN1_GENERALIZEDTIME_print(out, usage->notBefore);
+        if (usage->notAfter)
+            BIO_write(out, ", ", 2);
+    }
+    if (usage->notAfter) {
+        BIO_write(out, "Not After: ", 11);
+        ASN1_GENERALIZEDTIME_print(out, usage->notAfter);
+    }
+    return 1;
 }
 
 /*
-static PKEY_USAGE_PERIOD *v2i_PKEY_USAGE_PERIOD(method, ctx, values)
-X509V3_EXT_METHOD *method;
-X509V3_CTX *ctx;
-STACK_OF(CONF_VALUE) *values;
-{
-return NULL;
-}
-*/
+ * static PKEY_USAGE_PERIOD *v2i_PKEY_USAGE_PERIOD(method, ctx, values)
+ * X509V3_EXT_METHOD *method; X509V3_CTX *ctx; STACK_OF(CONF_VALUE) *values;
+ * { return NULL; }
+ */
diff --git a/src/crypto/x509v3/v3_pmaps.c b/src/crypto/x509v3/v3_pmaps.c
index 5b90977..caacdb2 100644
--- a/src/crypto/x509v3/v3_pmaps.c
+++ b/src/crypto/x509v3/v3_pmaps.c
@@ -1,5 +1,6 @@
 /* v3_pmaps.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project.
  */
 /* ====================================================================
@@ -10,7 +11,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -54,7 +55,6 @@
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com). */
 
-
 #include <stdio.h>
 
 #include <openssl/asn1t.h>
@@ -63,94 +63,92 @@
 #include <openssl/obj.h>
 #include <openssl/x509v3.h>
 
-
 static void *v2i_POLICY_MAPPINGS(const X509V3_EXT_METHOD *method,
-				 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
-static STACK_OF(CONF_VALUE) *
-i2v_POLICY_MAPPINGS(const X509V3_EXT_METHOD *method, void *pmps,
-		    STACK_OF(CONF_VALUE) *extlist);
+                                 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
+static STACK_OF(CONF_VALUE) *i2v_POLICY_MAPPINGS(const X509V3_EXT_METHOD
+                                                 *method, void *pmps, STACK_OF(CONF_VALUE)
+                                                 *extlist);
 
 const X509V3_EXT_METHOD v3_policy_mappings = {
-	NID_policy_mappings, 0,
-	ASN1_ITEM_ref(POLICY_MAPPINGS),
-	0,0,0,0,
-	0,0,
-	i2v_POLICY_MAPPINGS,
-	v2i_POLICY_MAPPINGS,
-	0,0,
-	NULL
+    NID_policy_mappings, 0,
+    ASN1_ITEM_ref(POLICY_MAPPINGS),
+    0, 0, 0, 0,
+    0, 0,
+    i2v_POLICY_MAPPINGS,
+    v2i_POLICY_MAPPINGS,
+    0, 0,
+    NULL
 };
 
 ASN1_SEQUENCE(POLICY_MAPPING) = {
-	ASN1_SIMPLE(POLICY_MAPPING, issuerDomainPolicy, ASN1_OBJECT),
-	ASN1_SIMPLE(POLICY_MAPPING, subjectDomainPolicy, ASN1_OBJECT)
+        ASN1_SIMPLE(POLICY_MAPPING, issuerDomainPolicy, ASN1_OBJECT),
+        ASN1_SIMPLE(POLICY_MAPPING, subjectDomainPolicy, ASN1_OBJECT)
 } ASN1_SEQUENCE_END(POLICY_MAPPING)
 
-ASN1_ITEM_TEMPLATE(POLICY_MAPPINGS) = 
-	ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, POLICY_MAPPINGS,
-								POLICY_MAPPING)
+ASN1_ITEM_TEMPLATE(POLICY_MAPPINGS) =
+        ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, POLICY_MAPPINGS,
+                                                                POLICY_MAPPING)
 ASN1_ITEM_TEMPLATE_END(POLICY_MAPPINGS)
 
 IMPLEMENT_ASN1_ALLOC_FUNCTIONS(POLICY_MAPPING)
 
-
-static STACK_OF(CONF_VALUE) *
-i2v_POLICY_MAPPINGS(const X509V3_EXT_METHOD *method, void *a,
-		    STACK_OF(CONF_VALUE) *ext_list)
+static STACK_OF(CONF_VALUE) *i2v_POLICY_MAPPINGS(const X509V3_EXT_METHOD
+                                                 *method, void *a, STACK_OF(CONF_VALUE)
+                                                 *ext_list)
 {
-	POLICY_MAPPINGS *pmaps = a;
-	POLICY_MAPPING *pmap;
-	size_t i;
-	char obj_tmp1[80];
-	char obj_tmp2[80];
-	for(i = 0; i < sk_POLICY_MAPPING_num(pmaps); i++) {
-		pmap = sk_POLICY_MAPPING_value(pmaps, i);
-		i2t_ASN1_OBJECT(obj_tmp1, 80, pmap->issuerDomainPolicy);
-		i2t_ASN1_OBJECT(obj_tmp2, 80, pmap->subjectDomainPolicy);
-		X509V3_add_value(obj_tmp1, obj_tmp2, &ext_list);
-	}
-	return ext_list;
+    POLICY_MAPPINGS *pmaps = a;
+    POLICY_MAPPING *pmap;
+    size_t i;
+    char obj_tmp1[80];
+    char obj_tmp2[80];
+    for (i = 0; i < sk_POLICY_MAPPING_num(pmaps); i++) {
+        pmap = sk_POLICY_MAPPING_value(pmaps, i);
+        i2t_ASN1_OBJECT(obj_tmp1, 80, pmap->issuerDomainPolicy);
+        i2t_ASN1_OBJECT(obj_tmp2, 80, pmap->subjectDomainPolicy);
+        X509V3_add_value(obj_tmp1, obj_tmp2, &ext_list);
+    }
+    return ext_list;
 }
 
 static void *v2i_POLICY_MAPPINGS(const X509V3_EXT_METHOD *method,
-				 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
+                                 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
 {
-	POLICY_MAPPINGS *pmaps;
-	POLICY_MAPPING *pmap;
-	ASN1_OBJECT *obj1, *obj2;
-	CONF_VALUE *val;
-	size_t i;
+    POLICY_MAPPINGS *pmaps;
+    POLICY_MAPPING *pmap;
+    ASN1_OBJECT *obj1, *obj2;
+    CONF_VALUE *val;
+    size_t i;
 
-	if(!(pmaps = sk_POLICY_MAPPING_new_null())) {
-		OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-		return NULL;
-	}
+    if (!(pmaps = sk_POLICY_MAPPING_new_null())) {
+        OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
 
-	for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
-		val = sk_CONF_VALUE_value(nval, i);
-		if(!val->value || !val->name) {
-			sk_POLICY_MAPPING_pop_free(pmaps, POLICY_MAPPING_free);
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER);
-			X509V3_conf_err(val);
-			return NULL;
-		}
-		obj1 = OBJ_txt2obj(val->name, 0);
-		obj2 = OBJ_txt2obj(val->value, 0);
-		if(!obj1 || !obj2) {
-			sk_POLICY_MAPPING_pop_free(pmaps, POLICY_MAPPING_free);
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER);
-			X509V3_conf_err(val);
-			return NULL;
-		}
-		pmap = POLICY_MAPPING_new();
-		if (!pmap) {
-			sk_POLICY_MAPPING_pop_free(pmaps, POLICY_MAPPING_free);
-			OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-			return NULL;
-		}
-		pmap->issuerDomainPolicy = obj1;
-		pmap->subjectDomainPolicy = obj2;
-		sk_POLICY_MAPPING_push(pmaps, pmap);
-	}
-	return pmaps;
+    for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+        val = sk_CONF_VALUE_value(nval, i);
+        if (!val->value || !val->name) {
+            sk_POLICY_MAPPING_pop_free(pmaps, POLICY_MAPPING_free);
+            OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER);
+            X509V3_conf_err(val);
+            return NULL;
+        }
+        obj1 = OBJ_txt2obj(val->name, 0);
+        obj2 = OBJ_txt2obj(val->value, 0);
+        if (!obj1 || !obj2) {
+            sk_POLICY_MAPPING_pop_free(pmaps, POLICY_MAPPING_free);
+            OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_OBJECT_IDENTIFIER);
+            X509V3_conf_err(val);
+            return NULL;
+        }
+        pmap = POLICY_MAPPING_new();
+        if (!pmap) {
+            sk_POLICY_MAPPING_pop_free(pmaps, POLICY_MAPPING_free);
+            OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+            return NULL;
+        }
+        pmap->issuerDomainPolicy = obj1;
+        pmap->subjectDomainPolicy = obj2;
+        sk_POLICY_MAPPING_push(pmaps, pmap);
+    }
+    return pmaps;
 }
diff --git a/src/crypto/x509v3/v3_prn.c b/src/crypto/x509v3/v3_prn.c
index 87aef4d..2f5efcf 100644
--- a/src/crypto/x509v3/v3_prn.c
+++ b/src/crypto/x509v3/v3_prn.c
@@ -1,6 +1,7 @@
 /* v3_prn.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
  */
 /* ====================================================================
  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
@@ -10,7 +11,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -63,145 +64,166 @@
 #include <openssl/mem.h>
 #include <openssl/x509v3.h>
 
-
 /* Extension printing routines */
 
-static int unknown_ext_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, int indent, int supported);
+static int unknown_ext_print(BIO *out, X509_EXTENSION *ext,
+                             unsigned long flag, int indent, int supported);
 
 /* Print out a name+value stack */
 
-void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent, int ml)
+void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent,
+                        int ml)
 {
-	size_t i;
-	CONF_VALUE *nval;
-	if(!val) return;
-	if(!ml || !sk_CONF_VALUE_num(val)) {
-		BIO_printf(out, "%*s", indent, "");
-		if(!sk_CONF_VALUE_num(val)) BIO_puts(out, "<EMPTY>\n");
-	}
-	for(i = 0; i < sk_CONF_VALUE_num(val); i++) {
-		if(ml) BIO_printf(out, "%*s", indent, "");
-		else if(i > 0) BIO_printf(out, ", ");
-		nval = sk_CONF_VALUE_value(val, i);
-		if(!nval->name) BIO_puts(out, nval->value);
-		else if(!nval->value) BIO_puts(out, nval->name);
-		else BIO_printf(out, "%s:%s", nval->name, nval->value);
-		if(ml) BIO_puts(out, "\n");
-	}
+    size_t i;
+    CONF_VALUE *nval;
+    if (!val)
+        return;
+    if (!ml || !sk_CONF_VALUE_num(val)) {
+        BIO_printf(out, "%*s", indent, "");
+        if (!sk_CONF_VALUE_num(val))
+            BIO_puts(out, "<EMPTY>\n");
+    }
+    for (i = 0; i < sk_CONF_VALUE_num(val); i++) {
+        if (ml)
+            BIO_printf(out, "%*s", indent, "");
+        else if (i > 0)
+            BIO_printf(out, ", ");
+        nval = sk_CONF_VALUE_value(val, i);
+        if (!nval->name)
+            BIO_puts(out, nval->value);
+        else if (!nval->value)
+            BIO_puts(out, nval->name);
+        else
+            BIO_printf(out, "%s:%s", nval->name, nval->value);
+        if (ml)
+            BIO_puts(out, "\n");
+    }
 }
 
 /* Main routine: print out a general extension */
 
-int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, int indent)
+int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag,
+                     int indent)
 {
-	void *ext_str = NULL;
-	char *value = NULL;
-	const unsigned char *p;
-	const X509V3_EXT_METHOD *method;	
-	STACK_OF(CONF_VALUE) *nval = NULL;
-	int ok = 1;
+    void *ext_str = NULL;
+    char *value = NULL;
+    const unsigned char *p;
+    const X509V3_EXT_METHOD *method;
+    STACK_OF(CONF_VALUE) *nval = NULL;
+    int ok = 1;
 
-	if(!(method = X509V3_EXT_get(ext)))
-		return unknown_ext_print(out, ext, flag, indent, 0);
-	p = ext->value->data;
-	if(method->it) ext_str = ASN1_item_d2i(NULL, &p, ext->value->length, ASN1_ITEM_ptr(method->it));
-	else ext_str = method->d2i(NULL, &p, ext->value->length);
+    if (!(method = X509V3_EXT_get(ext)))
+        return unknown_ext_print(out, ext, flag, indent, 0);
+    p = ext->value->data;
+    if (method->it)
+        ext_str =
+            ASN1_item_d2i(NULL, &p, ext->value->length,
+                          ASN1_ITEM_ptr(method->it));
+    else
+        ext_str = method->d2i(NULL, &p, ext->value->length);
 
-	if(!ext_str) return unknown_ext_print(out, ext, flag, indent, 1);
+    if (!ext_str)
+        return unknown_ext_print(out, ext, flag, indent, 1);
 
-	if(method->i2s) {
-		if(!(value = method->i2s(method, ext_str))) {
-			ok = 0;
-			goto err;
-		}
-		BIO_printf(out, "%*s%s", indent, "", value);
-	} else if(method->i2v) {
-		if(!(nval = method->i2v(method, ext_str, NULL))) {
-			ok = 0;
-			goto err;
-		}
-		X509V3_EXT_val_prn(out, nval, indent,
-				 method->ext_flags & X509V3_EXT_MULTILINE);
-	} else if(method->i2r) {
-		if(!method->i2r(method, ext_str, out, indent)) ok = 0;
-	} else ok = 0;
+    if (method->i2s) {
+        if (!(value = method->i2s(method, ext_str))) {
+            ok = 0;
+            goto err;
+        }
+        BIO_printf(out, "%*s%s", indent, "", value);
+    } else if (method->i2v) {
+        if (!(nval = method->i2v(method, ext_str, NULL))) {
+            ok = 0;
+            goto err;
+        }
+        X509V3_EXT_val_prn(out, nval, indent,
+                           method->ext_flags & X509V3_EXT_MULTILINE);
+    } else if (method->i2r) {
+        if (!method->i2r(method, ext_str, out, indent))
+            ok = 0;
+    } else
+        ok = 0;
 
-	err:
-		sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
-		if(value) OPENSSL_free(value);
-		if(method->it) ASN1_item_free(ext_str, ASN1_ITEM_ptr(method->it));
-		else method->ext_free(ext_str);
-		return ok;
+ err:
+    sk_CONF_VALUE_pop_free(nval, X509V3_conf_free);
+    if (value)
+        OPENSSL_free(value);
+    if (method->it)
+        ASN1_item_free(ext_str, ASN1_ITEM_ptr(method->it));
+    else
+        method->ext_free(ext_str);
+    return ok;
 }
 
-int X509V3_extensions_print(BIO *bp, const char *title, STACK_OF(X509_EXTENSION) *exts, unsigned long flag, int indent)
+int X509V3_extensions_print(BIO *bp, const char *title,
+                            STACK_OF(X509_EXTENSION) *exts,
+                            unsigned long flag, int indent)
 {
-	size_t i;
-	int j;
+    size_t i;
+    int j;
 
-	if(sk_X509_EXTENSION_num(exts) <= 0) return 1;
+    if (sk_X509_EXTENSION_num(exts) <= 0)
+        return 1;
 
-	if(title) 
-		{
-		BIO_printf(bp,"%*s%s:\n",indent, "", title);
-		indent += 4;
-		}
+    if (title) {
+        BIO_printf(bp, "%*s%s:\n", indent, "", title);
+        indent += 4;
+    }
 
-	for (i=0; i<sk_X509_EXTENSION_num(exts); i++)
-		{
-		ASN1_OBJECT *obj;
-		X509_EXTENSION *ex;
-		ex=sk_X509_EXTENSION_value(exts, i);
-		if (indent && BIO_printf(bp,"%*s",indent, "") <= 0) return 0;
-		obj=X509_EXTENSION_get_object(ex);
-		i2a_ASN1_OBJECT(bp,obj);
-		j=X509_EXTENSION_get_critical(ex);
-		if (BIO_printf(bp,": %s\n",j?"critical":"") <= 0)
-			return 0;
-		if(!X509V3_EXT_print(bp, ex, flag, indent + 4))
-			{
-			BIO_printf(bp, "%*s", indent + 4, "");
-			M_ASN1_OCTET_STRING_print(bp,ex->value);
-			}
-		if (BIO_write(bp,"\n",1) <= 0) return 0;
-		}
-	return 1;
+    for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
+        ASN1_OBJECT *obj;
+        X509_EXTENSION *ex;
+        ex = sk_X509_EXTENSION_value(exts, i);
+        if (indent && BIO_printf(bp, "%*s", indent, "") <= 0)
+            return 0;
+        obj = X509_EXTENSION_get_object(ex);
+        i2a_ASN1_OBJECT(bp, obj);
+        j = X509_EXTENSION_get_critical(ex);
+        if (BIO_printf(bp, ": %s\n", j ? "critical" : "") <= 0)
+            return 0;
+        if (!X509V3_EXT_print(bp, ex, flag, indent + 4)) {
+            BIO_printf(bp, "%*s", indent + 4, "");
+            M_ASN1_OCTET_STRING_print(bp, ex->value);
+        }
+        if (BIO_write(bp, "\n", 1) <= 0)
+            return 0;
+    }
+    return 1;
 }
 
-static int unknown_ext_print(BIO *out, X509_EXTENSION *ext, unsigned long flag, int indent, int supported)
+static int unknown_ext_print(BIO *out, X509_EXTENSION *ext,
+                             unsigned long flag, int indent, int supported)
 {
-	switch(flag & X509V3_EXT_UNKNOWN_MASK) {
+    switch (flag & X509V3_EXT_UNKNOWN_MASK) {
 
-		case X509V3_EXT_DEFAULT:
-		return 0;
+    case X509V3_EXT_DEFAULT:
+        return 0;
 
-		case X509V3_EXT_ERROR_UNKNOWN:
-		if(supported)
-			BIO_printf(out, "%*s<Parse Error>", indent, "");
-		else
-			BIO_printf(out, "%*s<Not Supported>", indent, "");
-		return 1;
+    case X509V3_EXT_ERROR_UNKNOWN:
+        if (supported)
+            BIO_printf(out, "%*s<Parse Error>", indent, "");
+        else
+            BIO_printf(out, "%*s<Not Supported>", indent, "");
+        return 1;
 
-		case X509V3_EXT_PARSE_UNKNOWN:
-			return ASN1_parse_dump(out,
-				ext->value->data, ext->value->length, indent, -1);
-		case X509V3_EXT_DUMP_UNKNOWN:
-			return BIO_hexdump(out, ext->value->data, ext->value->length, indent);
+    case X509V3_EXT_PARSE_UNKNOWN:
+    case X509V3_EXT_DUMP_UNKNOWN:
+        return BIO_hexdump(out, ext->value->data, ext->value->length, indent);
 
-		default:
-		return 1;
-	}
+    default:
+        return 1;
+    }
 }
-	
 
 #ifndef OPENSSL_NO_FP_API
 int X509V3_EXT_print_fp(FILE *fp, X509_EXTENSION *ext, int flag, int indent)
 {
-	BIO *bio_tmp;
-	int ret;
-	if(!(bio_tmp = BIO_new_fp(fp, BIO_NOCLOSE))) return 0;
-	ret = X509V3_EXT_print(bio_tmp, ext, flag, indent);
-	BIO_free(bio_tmp);
-	return ret;
+    BIO *bio_tmp;
+    int ret;
+    if (!(bio_tmp = BIO_new_fp(fp, BIO_NOCLOSE)))
+        return 0;
+    ret = X509V3_EXT_print(bio_tmp, ext, flag, indent);
+    BIO_free(bio_tmp);
+    return ret;
 }
 #endif
diff --git a/src/crypto/x509v3/v3_purp.c b/src/crypto/x509v3/v3_purp.c
index 9a0a7bc..324de85 100644
--- a/src/crypto/x509v3/v3_purp.c
+++ b/src/crypto/x509v3/v3_purp.c
@@ -1,6 +1,7 @@
 /* v3_purp.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 2001.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 2001.
  */
 /* ====================================================================
  * Copyright (c) 1999-2004 The OpenSSL Project.  All rights reserved.
@@ -10,7 +11,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -69,26 +70,32 @@
 
 #include "../internal.h"
 
-
 #define V1_ROOT (EXFLAG_V1|EXFLAG_SS)
 #define ku_reject(x, usage) \
-	(((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage)))
+        (((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage)))
 #define xku_reject(x, usage) \
-	(((x)->ex_flags & EXFLAG_XKUSAGE) && !((x)->ex_xkusage & (usage)))
+        (((x)->ex_flags & EXFLAG_XKUSAGE) && !((x)->ex_xkusage & (usage)))
 #define ns_reject(x, usage) \
-	(((x)->ex_flags & EXFLAG_NSCERT) && !((x)->ex_nscert & (usage)))
+        (((x)->ex_flags & EXFLAG_NSCERT) && !((x)->ex_nscert & (usage)))
 
 static void x509v3_cache_extensions(X509 *x);
 
 static int check_ssl_ca(const X509 *x);
-static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, int ca);
-static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca);
-static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca);
+static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x,
+                                    int ca);
+static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x,
+                                    int ca);
+static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x,
+                                       int ca);
 static int purpose_smime(const X509 *x, int ca);
-static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, int ca);
-static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, int ca);
-static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, int ca);
-static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x, int ca);
+static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x,
+                                    int ca);
+static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x,
+                                       int ca);
+static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x,
+                                  int ca);
+static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x,
+                                        int ca);
 static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca);
 static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca);
 
@@ -96,15 +103,29 @@
 static void xptable_free(X509_PURPOSE *p);
 
 static X509_PURPOSE xstandard[] = {
-	{X509_PURPOSE_SSL_CLIENT, X509_TRUST_SSL_CLIENT, 0, check_purpose_ssl_client, (char *) "SSL client", (char *) "sslclient", NULL},
-	{X509_PURPOSE_SSL_SERVER, X509_TRUST_SSL_SERVER, 0, check_purpose_ssl_server, (char *) "SSL server", (char *) "sslserver", NULL},
-	{X509_PURPOSE_NS_SSL_SERVER, X509_TRUST_SSL_SERVER, 0, check_purpose_ns_ssl_server, (char *) "Netscape SSL server", (char *) "nssslserver", NULL},
-	{X509_PURPOSE_SMIME_SIGN, X509_TRUST_EMAIL, 0, check_purpose_smime_sign, (char *) "S/MIME signing", (char *) "smimesign", NULL},
-	{X509_PURPOSE_SMIME_ENCRYPT, X509_TRUST_EMAIL, 0, check_purpose_smime_encrypt, (char *) "S/MIME encryption", (char *) "smimeencrypt", NULL},
-	{X509_PURPOSE_CRL_SIGN, X509_TRUST_COMPAT, 0, check_purpose_crl_sign, (char *) "CRL signing", (char *) "crlsign", NULL},
-	{X509_PURPOSE_ANY, X509_TRUST_DEFAULT, 0, no_check, (char *) "Any Purpose", (char *) "any", NULL},
-	{X509_PURPOSE_OCSP_HELPER, X509_TRUST_COMPAT, 0, ocsp_helper, (char *) "OCSP helper", (char *) "ocsphelper", NULL},
-	{X509_PURPOSE_TIMESTAMP_SIGN, X509_TRUST_TSA, 0, check_purpose_timestamp_sign, (char *) "Time Stamp signing", (char *) "timestampsign", NULL},
+    {X509_PURPOSE_SSL_CLIENT, X509_TRUST_SSL_CLIENT, 0,
+     check_purpose_ssl_client, (char *)"SSL client", (char *)"sslclient",
+     NULL},
+    {X509_PURPOSE_SSL_SERVER, X509_TRUST_SSL_SERVER, 0,
+     check_purpose_ssl_server, (char *)"SSL server", (char *)"sslserver",
+     NULL},
+    {X509_PURPOSE_NS_SSL_SERVER, X509_TRUST_SSL_SERVER, 0,
+     check_purpose_ns_ssl_server, (char *)"Netscape SSL server",
+     (char *)"nssslserver", NULL},
+    {X509_PURPOSE_SMIME_SIGN, X509_TRUST_EMAIL, 0, check_purpose_smime_sign,
+     (char *)"S/MIME signing", (char *)"smimesign", NULL},
+    {X509_PURPOSE_SMIME_ENCRYPT, X509_TRUST_EMAIL, 0,
+     check_purpose_smime_encrypt, (char *)"S/MIME encryption",
+     (char *)"smimeencrypt", NULL},
+    {X509_PURPOSE_CRL_SIGN, X509_TRUST_COMPAT, 0, check_purpose_crl_sign,
+     (char *)"CRL signing", (char *)"crlsign", NULL},
+    {X509_PURPOSE_ANY, X509_TRUST_DEFAULT, 0, no_check, (char *)"Any Purpose",
+     (char *)"any", NULL},
+    {X509_PURPOSE_OCSP_HELPER, X509_TRUST_COMPAT, 0, ocsp_helper,
+     (char *)"OCSP helper", (char *)"ocsphelper", NULL},
+    {X509_PURPOSE_TIMESTAMP_SIGN, X509_TRUST_TSA, 0,
+     check_purpose_timestamp_sign, (char *)"Time Stamp signing",
+     (char *)"timestampsign", NULL},
 };
 
 #define X509_PURPOSE_COUNT (sizeof(xstandard)/sizeof(X509_PURPOSE))
@@ -113,693 +134,733 @@
 
 static int xp_cmp(const X509_PURPOSE **a, const X509_PURPOSE **b)
 {
-	return (*a)->purpose - (*b)->purpose;
+    return (*a)->purpose - (*b)->purpose;
 }
 
-/* As much as I'd like to make X509_check_purpose use a "const" X509*
- * I really can't because it does recalculate hashes and do other non-const
- * things. */
+/*
+ * As much as I'd like to make X509_check_purpose use a "const" X509* I
+ * really can't because it does recalculate hashes and do other non-const
+ * things.
+ */
 int X509_check_purpose(X509 *x, int id, int ca)
 {
-	int idx;
-	const X509_PURPOSE *pt;
-	if(!(x->ex_flags & EXFLAG_SET)) {
-		x509v3_cache_extensions(x);
-	}
-	if(id == -1) return 1;
-	idx = X509_PURPOSE_get_by_id(id);
-	if(idx == -1) return -1;
-	pt = X509_PURPOSE_get0(idx);
-	return pt->check_purpose(pt, x, ca);
+    int idx;
+    const X509_PURPOSE *pt;
+    x509v3_cache_extensions(x);
+    if (id == -1)
+        return 1;
+    idx = X509_PURPOSE_get_by_id(id);
+    if (idx == -1)
+        return -1;
+    pt = X509_PURPOSE_get0(idx);
+    return pt->check_purpose(pt, x, ca);
 }
 
 int X509_PURPOSE_set(int *p, int purpose)
 {
-	if(X509_PURPOSE_get_by_id(purpose) == -1) {
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_PURPOSE);
-		return 0;
-	}
-	*p = purpose;
-	return 1;
+    if (X509_PURPOSE_get_by_id(purpose) == -1) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_PURPOSE);
+        return 0;
+    }
+    *p = purpose;
+    return 1;
 }
 
 int X509_PURPOSE_get_count(void)
 {
-	if(!xptable) return X509_PURPOSE_COUNT;
-	return sk_X509_PURPOSE_num(xptable) + X509_PURPOSE_COUNT;
+    if (!xptable)
+        return X509_PURPOSE_COUNT;
+    return sk_X509_PURPOSE_num(xptable) + X509_PURPOSE_COUNT;
 }
 
-X509_PURPOSE * X509_PURPOSE_get0(int idx)
+X509_PURPOSE *X509_PURPOSE_get0(int idx)
 {
-	if(idx < 0) return NULL;
-	if(idx < (int)X509_PURPOSE_COUNT) return xstandard + idx;
-	return sk_X509_PURPOSE_value(xptable, idx - X509_PURPOSE_COUNT);
+    if (idx < 0)
+        return NULL;
+    if (idx < (int)X509_PURPOSE_COUNT)
+        return xstandard + idx;
+    return sk_X509_PURPOSE_value(xptable, idx - X509_PURPOSE_COUNT);
 }
 
 int X509_PURPOSE_get_by_sname(char *sname)
 {
-	int i;
-	X509_PURPOSE *xptmp;
-	for(i = 0; i < X509_PURPOSE_get_count(); i++) {
-		xptmp = X509_PURPOSE_get0(i);
-		if(!strcmp(xptmp->sname, sname)) return i;
-	}
-	return -1;
+    int i;
+    X509_PURPOSE *xptmp;
+    for (i = 0; i < X509_PURPOSE_get_count(); i++) {
+        xptmp = X509_PURPOSE_get0(i);
+        if (!strcmp(xptmp->sname, sname))
+            return i;
+    }
+    return -1;
 }
 
 int X509_PURPOSE_get_by_id(int purpose)
 {
-	X509_PURPOSE tmp;
-	size_t idx;
+    X509_PURPOSE tmp;
+    size_t idx;
 
-	if((purpose >= X509_PURPOSE_MIN) && (purpose <= X509_PURPOSE_MAX))
-		return purpose - X509_PURPOSE_MIN;
-	tmp.purpose = purpose;
-	if(!xptable) return -1;
+    if ((purpose >= X509_PURPOSE_MIN) && (purpose <= X509_PURPOSE_MAX))
+        return purpose - X509_PURPOSE_MIN;
+    tmp.purpose = purpose;
+    if (!xptable)
+        return -1;
 
-	if (!sk_X509_PURPOSE_find(xptable, &idx, &tmp))
-		return -1;
-	return idx + X509_PURPOSE_COUNT;
+    if (!sk_X509_PURPOSE_find(xptable, &idx, &tmp))
+        return -1;
+    return idx + X509_PURPOSE_COUNT;
 }
 
 int X509_PURPOSE_add(int id, int trust, int flags,
-			int (*ck)(const X509_PURPOSE *, const X509 *, int),
-					char *name, char *sname, void *arg)
+                     int (*ck) (const X509_PURPOSE *, const X509 *, int),
+                     char *name, char *sname, void *arg)
 {
-	int idx;
-	X509_PURPOSE *ptmp;
-	char *name_dup, *sname_dup;
+    int idx;
+    X509_PURPOSE *ptmp;
+    char *name_dup, *sname_dup;
 
-	/* This is set according to what we change: application can't set it */
-	flags &= ~X509_PURPOSE_DYNAMIC;
-	/* This will always be set for application modified trust entries */
-	flags |= X509_PURPOSE_DYNAMIC_NAME;
-	/* Get existing entry if any */
-	idx = X509_PURPOSE_get_by_id(id);
-	/* Need a new entry */
-	if(idx == -1) {
-		if(!(ptmp = OPENSSL_malloc(sizeof(X509_PURPOSE)))) {
-			OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-			return 0;
-		}
-		ptmp->flags = X509_PURPOSE_DYNAMIC;
-	} else ptmp = X509_PURPOSE_get0(idx);
+    /*
+     * This is set according to what we change: application can't set it
+     */
+    flags &= ~X509_PURPOSE_DYNAMIC;
+    /* This will always be set for application modified trust entries */
+    flags |= X509_PURPOSE_DYNAMIC_NAME;
+    /* Get existing entry if any */
+    idx = X509_PURPOSE_get_by_id(id);
+    /* Need a new entry */
+    if (idx == -1) {
+        if (!(ptmp = OPENSSL_malloc(sizeof(X509_PURPOSE)))) {
+            OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+            return 0;
+        }
+        ptmp->flags = X509_PURPOSE_DYNAMIC;
+    } else
+        ptmp = X509_PURPOSE_get0(idx);
 
-	/* Duplicate the supplied names. */
-	name_dup = BUF_strdup(name);
-	sname_dup = BUF_strdup(sname);
-	if (name_dup == NULL || sname_dup == NULL) {
-		OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-		if (name_dup != NULL)
-			OPENSSL_free(name_dup);
-		if (sname_dup != NULL)
-			OPENSSL_free(sname_dup);
-		if (idx == -1)
-			OPENSSL_free(ptmp);
-		return 0;
-	}
+    /* Duplicate the supplied names. */
+    name_dup = BUF_strdup(name);
+    sname_dup = BUF_strdup(sname);
+    if (name_dup == NULL || sname_dup == NULL) {
+        OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+        if (name_dup != NULL)
+            OPENSSL_free(name_dup);
+        if (sname_dup != NULL)
+            OPENSSL_free(sname_dup);
+        if (idx == -1)
+            OPENSSL_free(ptmp);
+        return 0;
+    }
 
-	/* OPENSSL_free existing name if dynamic */
-	if(ptmp->flags & X509_PURPOSE_DYNAMIC_NAME) {
-		OPENSSL_free(ptmp->name);
-		OPENSSL_free(ptmp->sname);
-	}
-	/* dup supplied name */
-	ptmp->name = name_dup;
-	ptmp->sname = sname_dup;
-	/* Keep the dynamic flag of existing entry */
-	ptmp->flags &= X509_PURPOSE_DYNAMIC;
-	/* Set all other flags */
-	ptmp->flags |= flags;
+    /* OPENSSL_free existing name if dynamic */
+    if (ptmp->flags & X509_PURPOSE_DYNAMIC_NAME) {
+        OPENSSL_free(ptmp->name);
+        OPENSSL_free(ptmp->sname);
+    }
+    /* dup supplied name */
+    ptmp->name = name_dup;
+    ptmp->sname = sname_dup;
+    /* Keep the dynamic flag of existing entry */
+    ptmp->flags &= X509_PURPOSE_DYNAMIC;
+    /* Set all other flags */
+    ptmp->flags |= flags;
 
-	ptmp->purpose = id;
-	ptmp->trust = trust;
-	ptmp->check_purpose = ck;
-	ptmp->usr_data = arg;
+    ptmp->purpose = id;
+    ptmp->trust = trust;
+    ptmp->check_purpose = ck;
+    ptmp->usr_data = arg;
 
-	/* If its a new entry manage the dynamic table */
-	if(idx == -1) {
-		if(!xptable && !(xptable = sk_X509_PURPOSE_new(xp_cmp))) {
-			OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-			xptable_free(ptmp);
-			return 0;
-		}
-		if (!sk_X509_PURPOSE_push(xptable, ptmp)) {
-			OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-			xptable_free(ptmp);
-			return 0;
-		}
-	}
-	return 1;
+    /* If its a new entry manage the dynamic table */
+    if (idx == -1) {
+        if (!xptable && !(xptable = sk_X509_PURPOSE_new(xp_cmp))) {
+            OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+            xptable_free(ptmp);
+            return 0;
+        }
+        if (!sk_X509_PURPOSE_push(xptable, ptmp)) {
+            OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+            xptable_free(ptmp);
+            return 0;
+        }
+    }
+    return 1;
 }
 
 static void xptable_free(X509_PURPOSE *p)
-	{
-	if(!p) return;
-	if (p->flags & X509_PURPOSE_DYNAMIC) 
-		{
-		if (p->flags & X509_PURPOSE_DYNAMIC_NAME) {
-			OPENSSL_free(p->name);
-			OPENSSL_free(p->sname);
-		}
-		OPENSSL_free(p);
-		}
-	}
+{
+    if (!p)
+        return;
+    if (p->flags & X509_PURPOSE_DYNAMIC) {
+        if (p->flags & X509_PURPOSE_DYNAMIC_NAME) {
+            OPENSSL_free(p->name);
+            OPENSSL_free(p->sname);
+        }
+        OPENSSL_free(p);
+    }
+}
 
 void X509_PURPOSE_cleanup(void)
 {
-	unsigned int i;
-	sk_X509_PURPOSE_pop_free(xptable, xptable_free);
-	for(i = 0; i < X509_PURPOSE_COUNT; i++) xptable_free(xstandard + i);
-	xptable = NULL;
+    unsigned int i;
+    sk_X509_PURPOSE_pop_free(xptable, xptable_free);
+    for (i = 0; i < X509_PURPOSE_COUNT; i++)
+        xptable_free(xstandard + i);
+    xptable = NULL;
 }
 
 int X509_PURPOSE_get_id(X509_PURPOSE *xp)
 {
-	return xp->purpose;
+    return xp->purpose;
 }
 
 char *X509_PURPOSE_get0_name(X509_PURPOSE *xp)
 {
-	return xp->name;
+    return xp->name;
 }
 
 char *X509_PURPOSE_get0_sname(X509_PURPOSE *xp)
 {
-	return xp->sname;
+    return xp->sname;
 }
 
 int X509_PURPOSE_get_trust(X509_PURPOSE *xp)
 {
-	return xp->trust;
+    return xp->trust;
 }
 
 static int nid_cmp(const void *void_a, const void *void_b)
-	{
-	const int *a = void_a, *b = void_b;
+{
+    const int *a = void_a, *b = void_b;
 
-	return *a - *b;
-	}
+    return *a - *b;
+}
 
 int X509_supported_extension(X509_EXTENSION *ex)
-	{
-	/* This table is a list of the NIDs of supported extensions:
-	 * that is those which are used by the verify process. If
-	 * an extension is critical and doesn't appear in this list
-	 * then the verify process will normally reject the certificate.
-	 * The list must be kept in numerical order because it will be
-	 * searched using bsearch.
-	 */
+{
+    /*
+     * This table is a list of the NIDs of supported extensions: that is
+     * those which are used by the verify process. If an extension is
+     * critical and doesn't appear in this list then the verify process will
+     * normally reject the certificate. The list must be kept in numerical
+     * order because it will be searched using bsearch.
+     */
 
-	static const int supported_nids[] = {
-		NID_netscape_cert_type, /* 71 */
-        	NID_key_usage,		/* 83 */
-		NID_subject_alt_name,	/* 85 */
-		NID_basic_constraints,	/* 87 */
-		NID_certificate_policies, /* 89 */
-        	NID_ext_key_usage,	/* 126 */
-		NID_policy_constraints,	/* 401 */
-		NID_proxyCertInfo,	/* 663 */
-		NID_name_constraints,	/* 666 */
-		NID_policy_mappings,	/* 747 */
-		NID_inhibit_any_policy	/* 748 */
-	};
+    static const int supported_nids[] = {
+        NID_netscape_cert_type, /* 71 */
+        NID_key_usage,          /* 83 */
+        NID_subject_alt_name,   /* 85 */
+        NID_basic_constraints,  /* 87 */
+        NID_certificate_policies, /* 89 */
+        NID_ext_key_usage,      /* 126 */
+        NID_policy_constraints, /* 401 */
+        NID_proxyCertInfo,      /* 663 */
+        NID_name_constraints,   /* 666 */
+        NID_policy_mappings,    /* 747 */
+        NID_inhibit_any_policy  /* 748 */
+    };
 
-	int ex_nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex));
+    int ex_nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex));
 
-	if (ex_nid == NID_undef) 
-		return 0;
+    if (ex_nid == NID_undef)
+        return 0;
 
-	if (bsearch(&ex_nid, supported_nids, sizeof(supported_nids)/sizeof(int), sizeof(int), nid_cmp) != NULL)
-		return 1;
-	return 0;
-	}
+    if (bsearch
+        (&ex_nid, supported_nids, sizeof(supported_nids) / sizeof(int),
+         sizeof(int), nid_cmp) != NULL)
+        return 1;
+    return 0;
+}
 
 static void setup_dp(X509 *x, DIST_POINT *dp)
-	{
-	X509_NAME *iname = NULL;
-	size_t i;
-	if (dp->reasons)
-		{
-		if (dp->reasons->length > 0)
-			dp->dp_reasons = dp->reasons->data[0];
-		if (dp->reasons->length > 1)
-			dp->dp_reasons |= (dp->reasons->data[1] << 8);
-		dp->dp_reasons &= CRLDP_ALL_REASONS;
-		}
-	else
-		dp->dp_reasons = CRLDP_ALL_REASONS;
-	if (!dp->distpoint || (dp->distpoint->type != 1))
-		return;
-	for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++)
-		{
-		GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i);
-		if (gen->type == GEN_DIRNAME)
-			{
-			iname = gen->d.directoryName;
-			break;
-			}
-		}
-	if (!iname)
-		iname = X509_get_issuer_name(x);
+{
+    X509_NAME *iname = NULL;
+    size_t i;
+    if (dp->reasons) {
+        if (dp->reasons->length > 0)
+            dp->dp_reasons = dp->reasons->data[0];
+        if (dp->reasons->length > 1)
+            dp->dp_reasons |= (dp->reasons->data[1] << 8);
+        dp->dp_reasons &= CRLDP_ALL_REASONS;
+    } else
+        dp->dp_reasons = CRLDP_ALL_REASONS;
+    if (!dp->distpoint || (dp->distpoint->type != 1))
+        return;
+    for (i = 0; i < sk_GENERAL_NAME_num(dp->CRLissuer); i++) {
+        GENERAL_NAME *gen = sk_GENERAL_NAME_value(dp->CRLissuer, i);
+        if (gen->type == GEN_DIRNAME) {
+            iname = gen->d.directoryName;
+            break;
+        }
+    }
+    if (!iname)
+        iname = X509_get_issuer_name(x);
 
-	DIST_POINT_set_dpname(dp->distpoint, iname);
+    DIST_POINT_set_dpname(dp->distpoint, iname);
 
-	}
+}
 
 static void setup_crldp(X509 *x)
-	{
-	size_t i;
-	x->crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL);
-	for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++)
-		setup_dp(x, sk_DIST_POINT_value(x->crldp, i));
-	}
-
-/* g_x509_cache_extensions_lock is used to protect against concurrent calls to
- * |x509v3_cache_extensions|. Ideally this would be done with a |CRYPTO_once_t|
- * in the |X509| structure, but |CRYPTO_once_t| isn't public.
- *
- * Note: it's not entirely clear whether this lock is needed. Not all paths to
- * this function took a lock in OpenSSL. */
-static struct CRYPTO_STATIC_MUTEX g_x509_cache_extensions_lock =
-    CRYPTO_STATIC_MUTEX_INIT;
+{
+    size_t i;
+    x->crldp = X509_get_ext_d2i(x, NID_crl_distribution_points, NULL, NULL);
+    for (i = 0; i < sk_DIST_POINT_num(x->crldp); i++)
+        setup_dp(x, sk_DIST_POINT_value(x->crldp, i));
+}
 
 static void x509v3_cache_extensions(X509 *x)
 {
-	BASIC_CONSTRAINTS *bs;
-	PROXY_CERT_INFO_EXTENSION *pci;
-	ASN1_BIT_STRING *usage;
-	ASN1_BIT_STRING *ns;
-	EXTENDED_KEY_USAGE *extusage;
-	X509_EXTENSION *ex;
-	size_t i;
-	int j;
+    BASIC_CONSTRAINTS *bs;
+    PROXY_CERT_INFO_EXTENSION *pci;
+    ASN1_BIT_STRING *usage;
+    ASN1_BIT_STRING *ns;
+    EXTENDED_KEY_USAGE *extusage;
+    X509_EXTENSION *ex;
+    size_t i;
+    int j;
 
-	CRYPTO_STATIC_MUTEX_lock_write(&g_x509_cache_extensions_lock);
+    CRYPTO_MUTEX_lock_read(&x->lock);
+    const int is_set = x->ex_flags & EXFLAG_SET;
+    CRYPTO_MUTEX_unlock_read(&x->lock);
 
-	if(x->ex_flags & EXFLAG_SET)
-		{
-		CRYPTO_STATIC_MUTEX_unlock(&g_x509_cache_extensions_lock);
-		return;
-		}
+    if (is_set) {
+        return;
+    }
 
-	X509_digest(x, EVP_sha1(), x->sha1_hash, NULL);
-	/* V1 should mean no extensions ... */
-	if(!X509_get_version(x)) x->ex_flags |= EXFLAG_V1;
-	/* Handle basic constraints */
-	if((bs=X509_get_ext_d2i(x, NID_basic_constraints, NULL, NULL))) {
-		if(bs->ca) x->ex_flags |= EXFLAG_CA;
-		if(bs->pathlen) {
-			if((bs->pathlen->type == V_ASN1_NEG_INTEGER)
-						|| !bs->ca) {
-				x->ex_flags |= EXFLAG_INVALID;
-				x->ex_pathlen = 0;
-			} else x->ex_pathlen = ASN1_INTEGER_get(bs->pathlen);
-		} else x->ex_pathlen = -1;
-		BASIC_CONSTRAINTS_free(bs);
-		x->ex_flags |= EXFLAG_BCONS;
-	}
-	/* Handle proxy certificates */
-	if((pci=X509_get_ext_d2i(x, NID_proxyCertInfo, NULL, NULL))) {
-		if (x->ex_flags & EXFLAG_CA
-		    || X509_get_ext_by_NID(x, NID_subject_alt_name, -1) >= 0
-		    || X509_get_ext_by_NID(x, NID_issuer_alt_name, -1) >= 0) {
-			x->ex_flags |= EXFLAG_INVALID;
-		}
-		if (pci->pcPathLengthConstraint) {
-			x->ex_pcpathlen =
-				ASN1_INTEGER_get(pci->pcPathLengthConstraint);
-		} else x->ex_pcpathlen = -1;
-		PROXY_CERT_INFO_EXTENSION_free(pci);
-		x->ex_flags |= EXFLAG_PROXY;
-	}
-	/* Handle key usage */
-	if((usage=X509_get_ext_d2i(x, NID_key_usage, NULL, NULL))) {
-		if(usage->length > 0) {
-			x->ex_kusage = usage->data[0];
-			if(usage->length > 1) 
-				x->ex_kusage |= usage->data[1] << 8;
-		} else x->ex_kusage = 0;
-		x->ex_flags |= EXFLAG_KUSAGE;
-		ASN1_BIT_STRING_free(usage);
-	}
-	x->ex_xkusage = 0;
-	if((extusage=X509_get_ext_d2i(x, NID_ext_key_usage, NULL, NULL))) {
-		x->ex_flags |= EXFLAG_XKUSAGE;
-		for(i = 0; i < sk_ASN1_OBJECT_num(extusage); i++) {
-			switch(OBJ_obj2nid(sk_ASN1_OBJECT_value(extusage,i))) {
-				case NID_server_auth:
-				x->ex_xkusage |= XKU_SSL_SERVER;
-				break;
+    CRYPTO_MUTEX_lock_write(&x->lock);
+    if (x->ex_flags & EXFLAG_SET) {
+        CRYPTO_MUTEX_unlock_write(&x->lock);
+        return;
+    }
 
-				case NID_client_auth:
-				x->ex_xkusage |= XKU_SSL_CLIENT;
-				break;
+    X509_digest(x, EVP_sha1(), x->sha1_hash, NULL);
+    /* V1 should mean no extensions ... */
+    if (!X509_get_version(x))
+        x->ex_flags |= EXFLAG_V1;
+    /* Handle basic constraints */
+    if ((bs = X509_get_ext_d2i(x, NID_basic_constraints, NULL, NULL))) {
+        if (bs->ca)
+            x->ex_flags |= EXFLAG_CA;
+        if (bs->pathlen) {
+            if ((bs->pathlen->type == V_ASN1_NEG_INTEGER)
+                || !bs->ca) {
+                x->ex_flags |= EXFLAG_INVALID;
+                x->ex_pathlen = 0;
+            } else
+                x->ex_pathlen = ASN1_INTEGER_get(bs->pathlen);
+        } else
+            x->ex_pathlen = -1;
+        BASIC_CONSTRAINTS_free(bs);
+        x->ex_flags |= EXFLAG_BCONS;
+    }
+    /* Handle proxy certificates */
+    if ((pci = X509_get_ext_d2i(x, NID_proxyCertInfo, NULL, NULL))) {
+        if (x->ex_flags & EXFLAG_CA
+            || X509_get_ext_by_NID(x, NID_subject_alt_name, -1) >= 0
+            || X509_get_ext_by_NID(x, NID_issuer_alt_name, -1) >= 0) {
+            x->ex_flags |= EXFLAG_INVALID;
+        }
+        if (pci->pcPathLengthConstraint) {
+            x->ex_pcpathlen = ASN1_INTEGER_get(pci->pcPathLengthConstraint);
+        } else
+            x->ex_pcpathlen = -1;
+        PROXY_CERT_INFO_EXTENSION_free(pci);
+        x->ex_flags |= EXFLAG_PROXY;
+    }
+    /* Handle key usage */
+    if ((usage = X509_get_ext_d2i(x, NID_key_usage, NULL, NULL))) {
+        if (usage->length > 0) {
+            x->ex_kusage = usage->data[0];
+            if (usage->length > 1)
+                x->ex_kusage |= usage->data[1] << 8;
+        } else
+            x->ex_kusage = 0;
+        x->ex_flags |= EXFLAG_KUSAGE;
+        ASN1_BIT_STRING_free(usage);
+    }
+    x->ex_xkusage = 0;
+    if ((extusage = X509_get_ext_d2i(x, NID_ext_key_usage, NULL, NULL))) {
+        x->ex_flags |= EXFLAG_XKUSAGE;
+        for (i = 0; i < sk_ASN1_OBJECT_num(extusage); i++) {
+            switch (OBJ_obj2nid(sk_ASN1_OBJECT_value(extusage, i))) {
+            case NID_server_auth:
+                x->ex_xkusage |= XKU_SSL_SERVER;
+                break;
 
-				case NID_email_protect:
-				x->ex_xkusage |= XKU_SMIME;
-				break;
+            case NID_client_auth:
+                x->ex_xkusage |= XKU_SSL_CLIENT;
+                break;
 
-				case NID_code_sign:
-				x->ex_xkusage |= XKU_CODE_SIGN;
-				break;
+            case NID_email_protect:
+                x->ex_xkusage |= XKU_SMIME;
+                break;
 
-				case NID_ms_sgc:
-				case NID_ns_sgc:
-				x->ex_xkusage |= XKU_SGC;
-				break;
+            case NID_code_sign:
+                x->ex_xkusage |= XKU_CODE_SIGN;
+                break;
 
-				case NID_OCSP_sign:
-				x->ex_xkusage |= XKU_OCSP_SIGN;
-				break;
+            case NID_ms_sgc:
+            case NID_ns_sgc:
+                x->ex_xkusage |= XKU_SGC;
+                break;
 
-				case NID_time_stamp:
-				x->ex_xkusage |= XKU_TIMESTAMP;
-				break;
+            case NID_OCSP_sign:
+                x->ex_xkusage |= XKU_OCSP_SIGN;
+                break;
 
-				case NID_dvcs:
-				x->ex_xkusage |= XKU_DVCS;
-				break;
+            case NID_time_stamp:
+                x->ex_xkusage |= XKU_TIMESTAMP;
+                break;
 
-				case NID_anyExtendedKeyUsage:
-				x->ex_xkusage |= XKU_ANYEKU;
-				break;
-			}
-		}
-		sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free);
-	}
+            case NID_dvcs:
+                x->ex_xkusage |= XKU_DVCS;
+                break;
 
-	if((ns=X509_get_ext_d2i(x, NID_netscape_cert_type, NULL, NULL))) {
-		if(ns->length > 0) x->ex_nscert = ns->data[0];
-		else x->ex_nscert = 0;
-		x->ex_flags |= EXFLAG_NSCERT;
-		ASN1_BIT_STRING_free(ns);
-	}
-	x->skid =X509_get_ext_d2i(x, NID_subject_key_identifier, NULL, NULL);
-	x->akid =X509_get_ext_d2i(x, NID_authority_key_identifier, NULL, NULL);
-	/* Does subject name match issuer ? */
-	if(!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x)))
-			{
-			x->ex_flags |= EXFLAG_SI;
-			/* If SKID matches AKID also indicate self signed */
-			if (X509_check_akid(x, x->akid) == X509_V_OK &&
-				!ku_reject(x, KU_KEY_CERT_SIGN))
-				x->ex_flags |= EXFLAG_SS;
-			}
-	x->altname = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
-	x->nc = X509_get_ext_d2i(x, NID_name_constraints, &j, NULL);
-	if (!x->nc && (j != -1))
-		x->ex_flags |= EXFLAG_INVALID;
-	setup_crldp(x);
+            case NID_anyExtendedKeyUsage:
+                x->ex_xkusage |= XKU_ANYEKU;
+                break;
+            }
+        }
+        sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free);
+    }
 
-	for (j = 0; j < X509_get_ext_count(x); j++)
-		{
-		ex = X509_get_ext(x, j);
-		if (OBJ_obj2nid(X509_EXTENSION_get_object(ex))
-					== NID_freshest_crl)
-			x->ex_flags |= EXFLAG_FRESHEST;
-		if (!X509_EXTENSION_get_critical(ex))
-			continue;
-		if (!X509_supported_extension(ex))
-			{
-			x->ex_flags |= EXFLAG_CRITICAL;
-			break;
-			}
-		}
-	x->ex_flags |= EXFLAG_SET;
+    if ((ns = X509_get_ext_d2i(x, NID_netscape_cert_type, NULL, NULL))) {
+        if (ns->length > 0)
+            x->ex_nscert = ns->data[0];
+        else
+            x->ex_nscert = 0;
+        x->ex_flags |= EXFLAG_NSCERT;
+        ASN1_BIT_STRING_free(ns);
+    }
+    x->skid = X509_get_ext_d2i(x, NID_subject_key_identifier, NULL, NULL);
+    x->akid = X509_get_ext_d2i(x, NID_authority_key_identifier, NULL, NULL);
+    /* Does subject name match issuer ? */
+    if (!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x))) {
+        x->ex_flags |= EXFLAG_SI;
+        /* If SKID matches AKID also indicate self signed */
+        if (X509_check_akid(x, x->akid) == X509_V_OK &&
+            !ku_reject(x, KU_KEY_CERT_SIGN))
+            x->ex_flags |= EXFLAG_SS;
+    }
+    x->altname = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
+    x->nc = X509_get_ext_d2i(x, NID_name_constraints, &j, NULL);
+    if (!x->nc && (j != -1))
+        x->ex_flags |= EXFLAG_INVALID;
+    setup_crldp(x);
 
-	CRYPTO_STATIC_MUTEX_unlock(&g_x509_cache_extensions_lock);
+    for (j = 0; j < X509_get_ext_count(x); j++) {
+        ex = X509_get_ext(x, j);
+        if (OBJ_obj2nid(X509_EXTENSION_get_object(ex))
+            == NID_freshest_crl)
+            x->ex_flags |= EXFLAG_FRESHEST;
+        if (!X509_EXTENSION_get_critical(ex))
+            continue;
+        if (!X509_supported_extension(ex)) {
+            x->ex_flags |= EXFLAG_CRITICAL;
+            break;
+        }
+    }
+    x->ex_flags |= EXFLAG_SET;
+
+    CRYPTO_MUTEX_unlock_write(&x->lock);
 }
 
-/* CA checks common to all purposes
- * return codes:
- * 0 not a CA
- * 1 is a CA
- * 2 basicConstraints absent so "maybe" a CA
- * 3 basicConstraints absent but self signed V1.
- * 4 basicConstraints absent but keyUsage present and keyCertSign asserted.
+/*
+ * CA checks common to all purposes return codes: 0 not a CA 1 is a CA 2
+ * basicConstraints absent so "maybe" a CA 3 basicConstraints absent but self
+ * signed V1. 4 basicConstraints absent but keyUsage present and keyCertSign
+ * asserted.
  */
 
 static int check_ca(const X509 *x)
 {
-	/* keyUsage if present should allow cert signing */
-	if(ku_reject(x, KU_KEY_CERT_SIGN)) return 0;
-	if(x->ex_flags & EXFLAG_BCONS) {
-		if(x->ex_flags & EXFLAG_CA) return 1;
-		/* If basicConstraints says not a CA then say so */
-		else return 0;
-	} else {
-		/* we support V1 roots for...  uh, I don't really know why. */
-		if((x->ex_flags & V1_ROOT) == V1_ROOT) return 3;
-		/* If key usage present it must have certSign so tolerate it */
-		else if (x->ex_flags & EXFLAG_KUSAGE) return 4;
-		/* Older certificates could have Netscape-specific CA types */
-		else if (x->ex_flags & EXFLAG_NSCERT
-			 && x->ex_nscert & NS_ANY_CA) return 5;
-		/* can this still be regarded a CA certificate?  I doubt it */
-		return 0;
-	}
+    /* keyUsage if present should allow cert signing */
+    if (ku_reject(x, KU_KEY_CERT_SIGN))
+        return 0;
+    if (x->ex_flags & EXFLAG_BCONS) {
+        if (x->ex_flags & EXFLAG_CA)
+            return 1;
+        /* If basicConstraints says not a CA then say so */
+        else
+            return 0;
+    } else {
+        /* we support V1 roots for...  uh, I don't really know why. */
+        if ((x->ex_flags & V1_ROOT) == V1_ROOT)
+            return 3;
+        /*
+         * If key usage present it must have certSign so tolerate it
+         */
+        else if (x->ex_flags & EXFLAG_KUSAGE)
+            return 4;
+        /* Older certificates could have Netscape-specific CA types */
+        else if (x->ex_flags & EXFLAG_NSCERT && x->ex_nscert & NS_ANY_CA)
+            return 5;
+        /* can this still be regarded a CA certificate?  I doubt it */
+        return 0;
+    }
 }
 
 int X509_check_ca(X509 *x)
 {
-	if(!(x->ex_flags & EXFLAG_SET)) {
-		x509v3_cache_extensions(x);
-	}
-
-	return check_ca(x);
+    x509v3_cache_extensions(x);
+    return check_ca(x);
 }
 
 /* Check SSL CA: common checks for SSL client and server */
 static int check_ssl_ca(const X509 *x)
 {
-	int ca_ret;
-	ca_ret = check_ca(x);
-	if(!ca_ret) return 0;
-	/* check nsCertType if present */
-	if(ca_ret != 5 || x->ex_nscert & NS_SSL_CA) return ca_ret;
-	else return 0;
+    int ca_ret;
+    ca_ret = check_ca(x);
+    if (!ca_ret)
+        return 0;
+    /* check nsCertType if present */
+    if (ca_ret != 5 || x->ex_nscert & NS_SSL_CA)
+        return ca_ret;
+    else
+        return 0;
 }
 
-
-static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x, int ca)
+static int check_purpose_ssl_client(const X509_PURPOSE *xp, const X509 *x,
+                                    int ca)
 {
-	if(xku_reject(x,XKU_SSL_CLIENT)) return 0;
-	if(ca) return check_ssl_ca(x);
-	/* We need to do digital signatures or key agreement */
-	if(ku_reject(x,KU_DIGITAL_SIGNATURE|KU_KEY_AGREEMENT)) return 0;
-	/* nsCertType if present should allow SSL client use */	
-	if(ns_reject(x, NS_SSL_CLIENT)) return 0;
-	return 1;
+    if (xku_reject(x, XKU_SSL_CLIENT))
+        return 0;
+    if (ca)
+        return check_ssl_ca(x);
+    /* We need to do digital signatures or key agreement */
+    if (ku_reject(x, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT))
+        return 0;
+    /* nsCertType if present should allow SSL client use */
+    if (ns_reject(x, NS_SSL_CLIENT))
+        return 0;
+    return 1;
 }
-/* Key usage needed for TLS/SSL server: digital signature, encipherment or
+
+/*
+ * Key usage needed for TLS/SSL server: digital signature, encipherment or
  * key agreement. The ssl code can check this more thoroughly for individual
  * key types.
  */
 #define KU_TLS \
-	KU_DIGITAL_SIGNATURE|KU_KEY_ENCIPHERMENT|KU_KEY_AGREEMENT
+        (KU_DIGITAL_SIGNATURE|KU_KEY_ENCIPHERMENT|KU_KEY_AGREEMENT)
 
-static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca)
+static int check_purpose_ssl_server(const X509_PURPOSE *xp, const X509 *x,
+                                    int ca)
 {
-	if(xku_reject(x,XKU_SSL_SERVER|XKU_SGC)) return 0;
-	if(ca) return check_ssl_ca(x);
+    if (xku_reject(x, XKU_SSL_SERVER | XKU_SGC))
+        return 0;
+    if (ca)
+        return check_ssl_ca(x);
 
-	if(ns_reject(x, NS_SSL_SERVER)) return 0;
-	if(ku_reject(x, KU_TLS)) return 0;
-	
-	return 1;
+    if (ns_reject(x, NS_SSL_SERVER))
+        return 0;
+    if (ku_reject(x, KU_TLS))
+        return 0;
+
+    return 1;
 
 }
 
-static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x, int ca)
+static int check_purpose_ns_ssl_server(const X509_PURPOSE *xp, const X509 *x,
+                                       int ca)
 {
-	int ret;
-	ret = check_purpose_ssl_server(xp, x, ca);
-	if(!ret || ca) return ret;
-	/* We need to encipher or Netscape complains */
-	if(ku_reject(x, KU_KEY_ENCIPHERMENT)) return 0;
-	return ret;
+    int ret;
+    ret = check_purpose_ssl_server(xp, x, ca);
+    if (!ret || ca)
+        return ret;
+    /* We need to encipher or Netscape complains */
+    if (ku_reject(x, KU_KEY_ENCIPHERMENT))
+        return 0;
+    return ret;
 }
 
 /* common S/MIME checks */
 static int purpose_smime(const X509 *x, int ca)
 {
-	if(xku_reject(x,XKU_SMIME)) return 0;
-	if(ca) {
-		int ca_ret;
-		ca_ret = check_ca(x);
-		if(!ca_ret) return 0;
-		/* check nsCertType if present */
-		if(ca_ret != 5 || x->ex_nscert & NS_SMIME_CA) return ca_ret;
-		else return 0;
-	}
-	if(x->ex_flags & EXFLAG_NSCERT) {
-		if(x->ex_nscert & NS_SMIME) return 1;
-		/* Workaround for some buggy certificates */
-		if(x->ex_nscert & NS_SSL_CLIENT) return 2;
-		return 0;
-	}
-	return 1;
+    if (xku_reject(x, XKU_SMIME))
+        return 0;
+    if (ca) {
+        int ca_ret;
+        ca_ret = check_ca(x);
+        if (!ca_ret)
+            return 0;
+        /* check nsCertType if present */
+        if (ca_ret != 5 || x->ex_nscert & NS_SMIME_CA)
+            return ca_ret;
+        else
+            return 0;
+    }
+    if (x->ex_flags & EXFLAG_NSCERT) {
+        if (x->ex_nscert & NS_SMIME)
+            return 1;
+        /* Workaround for some buggy certificates */
+        if (x->ex_nscert & NS_SSL_CLIENT)
+            return 2;
+        return 0;
+    }
+    return 1;
 }
 
-static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x, int ca)
+static int check_purpose_smime_sign(const X509_PURPOSE *xp, const X509 *x,
+                                    int ca)
 {
-	int ret;
-	ret = purpose_smime(x, ca);
-	if(!ret || ca) return ret;
-	if(ku_reject(x, KU_DIGITAL_SIGNATURE|KU_NON_REPUDIATION)) return 0;
-	return ret;
+    int ret;
+    ret = purpose_smime(x, ca);
+    if (!ret || ca)
+        return ret;
+    if (ku_reject(x, KU_DIGITAL_SIGNATURE | KU_NON_REPUDIATION))
+        return 0;
+    return ret;
 }
 
-static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x, int ca)
+static int check_purpose_smime_encrypt(const X509_PURPOSE *xp, const X509 *x,
+                                       int ca)
 {
-	int ret;
-	ret = purpose_smime(x, ca);
-	if(!ret || ca) return ret;
-	if(ku_reject(x, KU_KEY_ENCIPHERMENT)) return 0;
-	return ret;
+    int ret;
+    ret = purpose_smime(x, ca);
+    if (!ret || ca)
+        return ret;
+    if (ku_reject(x, KU_KEY_ENCIPHERMENT))
+        return 0;
+    return ret;
 }
 
-static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x, int ca)
+static int check_purpose_crl_sign(const X509_PURPOSE *xp, const X509 *x,
+                                  int ca)
 {
-	if(ca) {
-		int ca_ret;
-		if((ca_ret = check_ca(x)) != 2) return ca_ret;
-		else return 0;
-	}
-	if(ku_reject(x, KU_CRL_SIGN)) return 0;
-	return 1;
+    if (ca) {
+        int ca_ret;
+        if ((ca_ret = check_ca(x)) != 2)
+            return ca_ret;
+        else
+            return 0;
+    }
+    if (ku_reject(x, KU_CRL_SIGN))
+        return 0;
+    return 1;
 }
 
-/* OCSP helper: this is *not* a full OCSP check. It just checks that
- * each CA is valid. Additional checks must be made on the chain.
+/*
+ * OCSP helper: this is *not* a full OCSP check. It just checks that each CA
+ * is valid. Additional checks must be made on the chain.
  */
 
 static int ocsp_helper(const X509_PURPOSE *xp, const X509 *x, int ca)
 {
-	/* Must be a valid CA.  Should we really support the "I don't know"
-	   value (2)? */
-	if(ca) return check_ca(x);
-	/* leaf certificate is checked in OCSP_verify() */
-	return 1;
+    /*
+     * Must be a valid CA.  Should we really support the "I don't know" value
+     * (2)?
+     */
+    if (ca)
+        return check_ca(x);
+    /* leaf certificate is checked in OCSP_verify() */
+    return 1;
 }
 
 static int check_purpose_timestamp_sign(const X509_PURPOSE *xp, const X509 *x,
-					int ca)
+                                        int ca)
 {
-	int i_ext;
+    int i_ext;
 
-	/* If ca is true we must return if this is a valid CA certificate. */
-	if (ca) return check_ca(x);
+    /* If ca is true we must return if this is a valid CA certificate. */
+    if (ca)
+        return check_ca(x);
 
-	/* 
-	 * Check the optional key usage field:
-	 * if Key Usage is present, it must be one of digitalSignature 
-	 * and/or nonRepudiation (other values are not consistent and shall
-	 * be rejected).
-	 */
-	if ((x->ex_flags & EXFLAG_KUSAGE)
-	    && ((x->ex_kusage & ~(KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)) ||
-		!(x->ex_kusage & (KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE))))
-		return 0;
+    /*
+     * Check the optional key usage field:
+     * if Key Usage is present, it must be one of digitalSignature
+     * and/or nonRepudiation (other values are not consistent and shall
+     * be rejected).
+     */
+    if ((x->ex_flags & EXFLAG_KUSAGE)
+        && ((x->ex_kusage & ~(KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE)) ||
+            !(x->ex_kusage & (KU_NON_REPUDIATION | KU_DIGITAL_SIGNATURE))))
+        return 0;
 
-	/* Only time stamp key usage is permitted and it's required. */
-	if (!(x->ex_flags & EXFLAG_XKUSAGE) || x->ex_xkusage != XKU_TIMESTAMP)
-		return 0;
+    /* Only time stamp key usage is permitted and it's required. */
+    if (!(x->ex_flags & EXFLAG_XKUSAGE) || x->ex_xkusage != XKU_TIMESTAMP)
+        return 0;
 
-	/* Extended Key Usage MUST be critical */
-	i_ext = X509_get_ext_by_NID((X509 *) x, NID_ext_key_usage, -1);
-	if (i_ext >= 0)
-		{
-		X509_EXTENSION *ext = X509_get_ext((X509 *) x, i_ext);
-		if (!X509_EXTENSION_get_critical(ext))
-			return 0;
-		}
+    /* Extended Key Usage MUST be critical */
+    i_ext = X509_get_ext_by_NID((X509 *)x, NID_ext_key_usage, -1);
+    if (i_ext >= 0) {
+        X509_EXTENSION *ext = X509_get_ext((X509 *)x, i_ext);
+        if (!X509_EXTENSION_get_critical(ext))
+            return 0;
+    }
 
-	return 1;
+    return 1;
 }
 
 static int no_check(const X509_PURPOSE *xp, const X509 *x, int ca)
 {
-	return 1;
+    return 1;
 }
 
-/* Various checks to see if one certificate issued the second.
- * This can be used to prune a set of possible issuer certificates
- * which have been looked up using some simple method such as by
- * subject name.
- * These are:
- * 1. Check issuer_name(subject) == subject_name(issuer)
- * 2. If akid(subject) exists check it matches issuer
- * 3. If key_usage(issuer) exists check it supports certificate signing
- * returns 0 for OK, positive for reason for mismatch, reasons match
- * codes for X509_verify_cert()
+/*
+ * Various checks to see if one certificate issued the second. This can be
+ * used to prune a set of possible issuer certificates which have been looked
+ * up using some simple method such as by subject name. These are: 1. Check
+ * issuer_name(subject) == subject_name(issuer) 2. If akid(subject) exists
+ * check it matches issuer 3. If key_usage(issuer) exists check it supports
+ * certificate signing returns 0 for OK, positive for reason for mismatch,
+ * reasons match codes for X509_verify_cert()
  */
 
 int X509_check_issued(X509 *issuer, X509 *subject)
 {
-	if(X509_NAME_cmp(X509_get_subject_name(issuer),
-			X509_get_issuer_name(subject)))
-				return X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
-	x509v3_cache_extensions(issuer);
-	x509v3_cache_extensions(subject);
+    if (X509_NAME_cmp(X509_get_subject_name(issuer),
+                      X509_get_issuer_name(subject)))
+        return X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
+    x509v3_cache_extensions(issuer);
+    x509v3_cache_extensions(subject);
 
-	if(subject->akid)
-		{
-		int ret = X509_check_akid(issuer, subject->akid);
-		if (ret != X509_V_OK)
-			return ret;
-		}
+    if (subject->akid) {
+        int ret = X509_check_akid(issuer, subject->akid);
+        if (ret != X509_V_OK)
+            return ret;
+    }
 
-	if(subject->ex_flags & EXFLAG_PROXY)
-		{
-		if(ku_reject(issuer, KU_DIGITAL_SIGNATURE))
-			return X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE;
-		}
-	else if(ku_reject(issuer, KU_KEY_CERT_SIGN))
-		return X509_V_ERR_KEYUSAGE_NO_CERTSIGN;
-	return X509_V_OK;
+    if (subject->ex_flags & EXFLAG_PROXY) {
+        if (ku_reject(issuer, KU_DIGITAL_SIGNATURE))
+            return X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE;
+    } else if (ku_reject(issuer, KU_KEY_CERT_SIGN))
+        return X509_V_ERR_KEYUSAGE_NO_CERTSIGN;
+    return X509_V_OK;
 }
 
 int X509_check_akid(X509 *issuer, AUTHORITY_KEYID *akid)
-	{
+{
 
-	if(!akid)
-		return X509_V_OK;
+    if (!akid)
+        return X509_V_OK;
 
-	/* Check key ids (if present) */
-	if(akid->keyid && issuer->skid &&
-		 ASN1_OCTET_STRING_cmp(akid->keyid, issuer->skid) )
-				return X509_V_ERR_AKID_SKID_MISMATCH;
-	/* Check serial number */
-	if(akid->serial &&
-		ASN1_INTEGER_cmp(X509_get_serialNumber(issuer), akid->serial))
-				return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH;
-	/* Check issuer name */
-	if(akid->issuer)
-		{
-		/* Ugh, for some peculiar reason AKID includes
-		 * SEQUENCE OF GeneralName. So look for a DirName.
-		 * There may be more than one but we only take any
-		 * notice of the first.
-		 */
-		GENERAL_NAMES *gens;
-		GENERAL_NAME *gen;
-		X509_NAME *nm = NULL;
-		size_t i;
-		gens = akid->issuer;
-		for(i = 0; i < sk_GENERAL_NAME_num(gens); i++)
-			{
-			gen = sk_GENERAL_NAME_value(gens, i);
-			if(gen->type == GEN_DIRNAME)
-				{
-				nm = gen->d.dirn;
-				break;
-				}
-			}
-		if(nm && X509_NAME_cmp(nm, X509_get_issuer_name(issuer)))
-			return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH;
-		}
-	return X509_V_OK;
-	}
-
+    /* Check key ids (if present) */
+    if (akid->keyid && issuer->skid &&
+        ASN1_OCTET_STRING_cmp(akid->keyid, issuer->skid))
+        return X509_V_ERR_AKID_SKID_MISMATCH;
+    /* Check serial number */
+    if (akid->serial &&
+        ASN1_INTEGER_cmp(X509_get_serialNumber(issuer), akid->serial))
+        return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH;
+    /* Check issuer name */
+    if (akid->issuer) {
+        /*
+         * Ugh, for some peculiar reason AKID includes SEQUENCE OF
+         * GeneralName. So look for a DirName. There may be more than one but
+         * we only take any notice of the first.
+         */
+        GENERAL_NAMES *gens;
+        GENERAL_NAME *gen;
+        X509_NAME *nm = NULL;
+        size_t i;
+        gens = akid->issuer;
+        for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
+            gen = sk_GENERAL_NAME_value(gens, i);
+            if (gen->type == GEN_DIRNAME) {
+                nm = gen->d.dirn;
+                break;
+            }
+        }
+        if (nm && X509_NAME_cmp(nm, X509_get_issuer_name(issuer)))
+            return X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH;
+    }
+    return X509_V_OK;
+}
diff --git a/src/crypto/x509v3/v3_skey.c b/src/crypto/x509v3/v3_skey.c
index e396f05..65f8287 100644
--- a/src/crypto/x509v3/v3_skey.c
+++ b/src/crypto/x509v3/v3_skey.c
@@ -1,6 +1,7 @@
 /* v3_skey.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
  */
 /* ====================================================================
  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
@@ -10,7 +11,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -54,7 +55,6 @@
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com). */
 
-
 #include <stdio.h>
 #include <string.h>
 
@@ -63,86 +63,90 @@
 #include <openssl/obj.h>
 #include <openssl/x509v3.h>
 
+static ASN1_OCTET_STRING *s2i_skey_id(X509V3_EXT_METHOD *method,
+                                      X509V3_CTX *ctx, char *str);
+const X509V3_EXT_METHOD v3_skey_id = {
+    NID_subject_key_identifier, 0, ASN1_ITEM_ref(ASN1_OCTET_STRING),
+    0, 0, 0, 0,
+    (X509V3_EXT_I2S)i2s_ASN1_OCTET_STRING,
+    (X509V3_EXT_S2I)s2i_skey_id,
+    0, 0, 0, 0,
+    NULL
+};
 
-static ASN1_OCTET_STRING *s2i_skey_id(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, char *str);
-const X509V3_EXT_METHOD v3_skey_id = { 
-NID_subject_key_identifier, 0, ASN1_ITEM_ref(ASN1_OCTET_STRING),
-0,0,0,0,
-(X509V3_EXT_I2S)i2s_ASN1_OCTET_STRING,
-(X509V3_EXT_S2I)s2i_skey_id,
-0,0,0,0,
-NULL};
-
-char *i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method,
-	     ASN1_OCTET_STRING *oct)
+char *i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method, ASN1_OCTET_STRING *oct)
 {
-	return hex_to_string(oct->data, oct->length);
+    return hex_to_string(oct->data, oct->length);
 }
 
 ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method,
-	     X509V3_CTX *ctx, char *str)
+                                         X509V3_CTX *ctx, char *str)
 {
-	ASN1_OCTET_STRING *oct;
-	long length;
+    ASN1_OCTET_STRING *oct;
+    long length;
 
-	if(!(oct = M_ASN1_OCTET_STRING_new())) {
-		OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-		return NULL;
-	}
+    if (!(oct = M_ASN1_OCTET_STRING_new())) {
+        OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
 
-	if(!(oct->data = string_to_hex(str, &length))) {
-		M_ASN1_OCTET_STRING_free(oct);
-		return NULL;
-	}
+    if (!(oct->data = string_to_hex(str, &length))) {
+        M_ASN1_OCTET_STRING_free(oct);
+        return NULL;
+    }
 
-	oct->length = length;
+    oct->length = length;
 
-	return oct;
+    return oct;
 
 }
 
 static ASN1_OCTET_STRING *s2i_skey_id(X509V3_EXT_METHOD *method,
-	     X509V3_CTX *ctx, char *str)
+                                      X509V3_CTX *ctx, char *str)
 {
-	ASN1_OCTET_STRING *oct;
-	ASN1_BIT_STRING *pk;
-	unsigned char pkey_dig[EVP_MAX_MD_SIZE];
-	unsigned int diglen;
+    ASN1_OCTET_STRING *oct;
+    ASN1_BIT_STRING *pk;
+    unsigned char pkey_dig[EVP_MAX_MD_SIZE];
+    unsigned int diglen;
 
-	if(strcmp(str, "hash")) return s2i_ASN1_OCTET_STRING(method, ctx, str);
+    if (strcmp(str, "hash"))
+        return s2i_ASN1_OCTET_STRING(method, ctx, str);
 
-	if(!(oct = M_ASN1_OCTET_STRING_new())) {
-		OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-		return NULL;
-	}
+    if (!(oct = M_ASN1_OCTET_STRING_new())) {
+        OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
 
-	if(ctx && (ctx->flags == CTX_TEST)) return oct;
+    if (ctx && (ctx->flags == CTX_TEST))
+        return oct;
 
-	if(!ctx || (!ctx->subject_req && !ctx->subject_cert)) {
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_PUBLIC_KEY);
-		goto err;
-	}
+    if (!ctx || (!ctx->subject_req && !ctx->subject_cert)) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_PUBLIC_KEY);
+        goto err;
+    }
 
-	if(ctx->subject_req) 
-		pk = ctx->subject_req->req_info->pubkey->public_key;
-	else pk = ctx->subject_cert->cert_info->key->public_key;
+    if (ctx->subject_req)
+        pk = ctx->subject_req->req_info->pubkey->public_key;
+    else
+        pk = ctx->subject_cert->cert_info->key->public_key;
 
-	if(!pk) {
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_PUBLIC_KEY);
-		goto err;
-	}
+    if (!pk) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_PUBLIC_KEY);
+        goto err;
+    }
 
-	if (!EVP_Digest(pk->data, pk->length, pkey_dig, &diglen, EVP_sha1(), NULL))
-		goto err;
+    if (!EVP_Digest
+        (pk->data, pk->length, pkey_dig, &diglen, EVP_sha1(), NULL))
+        goto err;
 
-	if(!M_ASN1_OCTET_STRING_set(oct, pkey_dig, diglen)) {
-		OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-		goto err;
-	}
+    if (!M_ASN1_OCTET_STRING_set(oct, pkey_dig, diglen)) {
+        OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
 
-	return oct;
-	
-	err:
-	M_ASN1_OCTET_STRING_free(oct);
-	return NULL;
+    return oct;
+
+ err:
+    M_ASN1_OCTET_STRING_free(oct);
+    return NULL;
 }
diff --git a/src/crypto/x509v3/v3_sxnet.c b/src/crypto/x509v3/v3_sxnet.c
index 4dd5bfc..51c5a67 100644
--- a/src/crypto/x509v3/v3_sxnet.c
+++ b/src/crypto/x509v3/v3_sxnet.c
@@ -1,6 +1,7 @@
 /* v3_sxnet.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
  */
 /* ====================================================================
  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
@@ -10,7 +11,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -67,200 +68,207 @@
 #include <openssl/obj.h>
 #include <openssl/x509v3.h>
 
-
 /* Support for Thawte strong extranet extension */
 
 #define SXNET_TEST
 
-static int sxnet_i2r(X509V3_EXT_METHOD *method, SXNET *sx, BIO *out, int indent);
+static int sxnet_i2r(X509V3_EXT_METHOD *method, SXNET *sx, BIO *out,
+                     int indent);
 #ifdef SXNET_TEST
-static SXNET * sxnet_v2i(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
-						STACK_OF(CONF_VALUE) *nval);
+static SXNET *sxnet_v2i(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
+                        STACK_OF(CONF_VALUE) *nval);
 #endif
 const X509V3_EXT_METHOD v3_sxnet = {
-NID_sxnet, X509V3_EXT_MULTILINE, ASN1_ITEM_ref(SXNET),
-0,0,0,0,
-0,0,
-0, 
+    NID_sxnet, X509V3_EXT_MULTILINE, ASN1_ITEM_ref(SXNET),
+    0, 0, 0, 0,
+    0, 0,
+    0,
 #ifdef SXNET_TEST
-(X509V3_EXT_V2I)sxnet_v2i,
+    (X509V3_EXT_V2I)sxnet_v2i,
 #else
-0,
+    0,
 #endif
-(X509V3_EXT_I2R)sxnet_i2r,
-0,
-NULL
+    (X509V3_EXT_I2R)sxnet_i2r,
+    0,
+    NULL
 };
 
 ASN1_SEQUENCE(SXNETID) = {
-	ASN1_SIMPLE(SXNETID, zone, ASN1_INTEGER),
-	ASN1_SIMPLE(SXNETID, user, ASN1_OCTET_STRING)
+        ASN1_SIMPLE(SXNETID, zone, ASN1_INTEGER),
+        ASN1_SIMPLE(SXNETID, user, ASN1_OCTET_STRING)
 } ASN1_SEQUENCE_END(SXNETID)
 
 IMPLEMENT_ASN1_FUNCTIONS(SXNETID)
 
 ASN1_SEQUENCE(SXNET) = {
-	ASN1_SIMPLE(SXNET, version, ASN1_INTEGER),
-	ASN1_SEQUENCE_OF(SXNET, ids, SXNETID)
+        ASN1_SIMPLE(SXNET, version, ASN1_INTEGER),
+        ASN1_SEQUENCE_OF(SXNET, ids, SXNETID)
 } ASN1_SEQUENCE_END(SXNET)
 
 IMPLEMENT_ASN1_FUNCTIONS(SXNET)
 
 static int sxnet_i2r(X509V3_EXT_METHOD *method, SXNET *sx, BIO *out,
-	     int indent)
+                     int indent)
 {
-	long v;
-	char *tmp;
-	SXNETID *id;
-	size_t i;
-	v = ASN1_INTEGER_get(sx->version);
-	BIO_printf(out, "%*sVersion: %ld (0x%lX)", indent, "", v + 1, v);
-	for(i = 0; i < sk_SXNETID_num(sx->ids); i++) {
-		id = sk_SXNETID_value(sx->ids, i);
-		tmp = i2s_ASN1_INTEGER(NULL, id->zone);
-		BIO_printf(out, "\n%*sZone: %s, User: ", indent, "", tmp);
-		OPENSSL_free(tmp);
-		M_ASN1_OCTET_STRING_print(out, id->user);
-	}
-	return 1;
+    long v;
+    char *tmp;
+    SXNETID *id;
+    size_t i;
+    v = ASN1_INTEGER_get(sx->version);
+    BIO_printf(out, "%*sVersion: %ld (0x%lX)", indent, "", v + 1, v);
+    for (i = 0; i < sk_SXNETID_num(sx->ids); i++) {
+        id = sk_SXNETID_value(sx->ids, i);
+        tmp = i2s_ASN1_INTEGER(NULL, id->zone);
+        BIO_printf(out, "\n%*sZone: %s, User: ", indent, "", tmp);
+        OPENSSL_free(tmp);
+        M_ASN1_OCTET_STRING_print(out, id->user);
+    }
+    return 1;
 }
 
 #ifdef SXNET_TEST
 
-/* NBB: this is used for testing only. It should *not* be used for anything
+/*
+ * NBB: this is used for testing only. It should *not* be used for anything
  * else because it will just take static IDs from the configuration file and
  * they should really be separate values for each user.
  */
 
-
-static SXNET * sxnet_v2i(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
-	     STACK_OF(CONF_VALUE) *nval)
+static SXNET *sxnet_v2i(X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
+                        STACK_OF(CONF_VALUE) *nval)
 {
-	CONF_VALUE *cnf;
-	SXNET *sx = NULL;
-	size_t i;
-	for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
-		cnf = sk_CONF_VALUE_value(nval, i);
-		if(!SXNET_add_id_asc(&sx, cnf->name, cnf->value, -1))
-								 return NULL;
-	}
-	return sx;
+    CONF_VALUE *cnf;
+    SXNET *sx = NULL;
+    size_t i;
+    for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
+        cnf = sk_CONF_VALUE_value(nval, i);
+        if (!SXNET_add_id_asc(&sx, cnf->name, cnf->value, -1))
+            return NULL;
+    }
+    return sx;
 }
-		
-	
+
 #endif
 
 /* Strong Extranet utility functions */
 
 /* Add an id given the zone as an ASCII number */
 
-int SXNET_add_id_asc(SXNET **psx, char *zone, char *user,
-	     int userlen)
+int SXNET_add_id_asc(SXNET **psx, char *zone, char *user, int userlen)
 {
-	ASN1_INTEGER *izone = NULL;
-	if(!(izone = s2i_ASN1_INTEGER(NULL, zone))) {
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_ERROR_CONVERTING_ZONE);
-		return 0;
-	}
-	return SXNET_add_id_INTEGER(psx, izone, user, userlen);
+    ASN1_INTEGER *izone = NULL;
+    if (!(izone = s2i_ASN1_INTEGER(NULL, zone))) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_ERROR_CONVERTING_ZONE);
+        return 0;
+    }
+    return SXNET_add_id_INTEGER(psx, izone, user, userlen);
 }
 
 /* Add an id given the zone as an unsigned long */
 
 int SXNET_add_id_ulong(SXNET **psx, unsigned long lzone, char *user,
-	     int userlen)
+                       int userlen)
 {
-	ASN1_INTEGER *izone = NULL;
-	if(!(izone = M_ASN1_INTEGER_new()) || !ASN1_INTEGER_set(izone, lzone)) {
-		OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-		M_ASN1_INTEGER_free(izone);
-		return 0;
-	}
-	return SXNET_add_id_INTEGER(psx, izone, user, userlen);
-	
+    ASN1_INTEGER *izone = NULL;
+    if (!(izone = M_ASN1_INTEGER_new()) || !ASN1_INTEGER_set(izone, lzone)) {
+        OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+        M_ASN1_INTEGER_free(izone);
+        return 0;
+    }
+    return SXNET_add_id_INTEGER(psx, izone, user, userlen);
+
 }
 
-/* Add an id given the zone as an ASN1_INTEGER.
- * Note this version uses the passed integer and doesn't make a copy so don't
- * free it up afterwards.
+/*
+ * Add an id given the zone as an ASN1_INTEGER. Note this version uses the
+ * passed integer and doesn't make a copy so don't free it up afterwards.
  */
 
 int SXNET_add_id_INTEGER(SXNET **psx, ASN1_INTEGER *zone, char *user,
-	     int userlen)
+                         int userlen)
 {
-	SXNET *sx = NULL;
-	SXNETID *id = NULL;
-	if(!psx || !zone || !user) {
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_ARGUMENT);
-		return 0;
-	}
-	if(userlen == -1) userlen = strlen(user);
-	if(userlen > 64) {
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_USER_TOO_LONG);
-		return 0;
-	}
-	if(!*psx) {
-		if(!(sx = SXNET_new())) goto err;
-		if(!ASN1_INTEGER_set(sx->version, 0)) goto err;
-		*psx = sx;
-	} else sx = *psx;
-	if(SXNET_get_id_INTEGER(sx, zone)) {
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_DUPLICATE_ZONE_ID);
-		return 0;
-	}
+    SXNET *sx = NULL;
+    SXNETID *id = NULL;
+    if (!psx || !zone || !user) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_ARGUMENT);
+        return 0;
+    }
+    if (userlen == -1)
+        userlen = strlen(user);
+    if (userlen > 64) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_USER_TOO_LONG);
+        return 0;
+    }
+    if (!*psx) {
+        if (!(sx = SXNET_new()))
+            goto err;
+        if (!ASN1_INTEGER_set(sx->version, 0))
+            goto err;
+        *psx = sx;
+    } else
+        sx = *psx;
+    if (SXNET_get_id_INTEGER(sx, zone)) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_DUPLICATE_ZONE_ID);
+        return 0;
+    }
 
-	if(!(id = SXNETID_new())) goto err;
-	if(userlen == -1) userlen = strlen(user);
-		
-	if(!M_ASN1_OCTET_STRING_set(id->user, user, userlen)) goto err;
-	if(!sk_SXNETID_push(sx->ids, id)) goto err;
-	id->zone = zone;
-	return 1;
-	
-	err:
-	OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-	SXNETID_free(id);
-	SXNET_free(sx);
-	*psx = NULL;
-	return 0;
+    if (!(id = SXNETID_new()))
+        goto err;
+    if (userlen == -1)
+        userlen = strlen(user);
+
+    if (!M_ASN1_OCTET_STRING_set(id->user, user, userlen))
+        goto err;
+    if (!sk_SXNETID_push(sx->ids, id))
+        goto err;
+    id->zone = zone;
+    return 1;
+
+ err:
+    OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+    SXNETID_free(id);
+    SXNET_free(sx);
+    *psx = NULL;
+    return 0;
 }
 
 ASN1_OCTET_STRING *SXNET_get_id_asc(SXNET *sx, char *zone)
 {
-	ASN1_INTEGER *izone = NULL;
-	ASN1_OCTET_STRING *oct;
-	if(!(izone = s2i_ASN1_INTEGER(NULL, zone))) {
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_ERROR_CONVERTING_ZONE);
-		return NULL;
-	}
-	oct = SXNET_get_id_INTEGER(sx, izone);
-	M_ASN1_INTEGER_free(izone);
-	return oct;
+    ASN1_INTEGER *izone = NULL;
+    ASN1_OCTET_STRING *oct;
+    if (!(izone = s2i_ASN1_INTEGER(NULL, zone))) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_ERROR_CONVERTING_ZONE);
+        return NULL;
+    }
+    oct = SXNET_get_id_INTEGER(sx, izone);
+    M_ASN1_INTEGER_free(izone);
+    return oct;
 }
 
 ASN1_OCTET_STRING *SXNET_get_id_ulong(SXNET *sx, unsigned long lzone)
 {
-	ASN1_INTEGER *izone = NULL;
-	ASN1_OCTET_STRING *oct;
-	if(!(izone = M_ASN1_INTEGER_new()) || !ASN1_INTEGER_set(izone, lzone)) {
-		OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-		M_ASN1_INTEGER_free(izone);
-		return NULL;
-	}
-	oct = SXNET_get_id_INTEGER(sx, izone);
-	M_ASN1_INTEGER_free(izone);
-	return oct;
+    ASN1_INTEGER *izone = NULL;
+    ASN1_OCTET_STRING *oct;
+    if (!(izone = M_ASN1_INTEGER_new()) || !ASN1_INTEGER_set(izone, lzone)) {
+        OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+        M_ASN1_INTEGER_free(izone);
+        return NULL;
+    }
+    oct = SXNET_get_id_INTEGER(sx, izone);
+    M_ASN1_INTEGER_free(izone);
+    return oct;
 }
 
 ASN1_OCTET_STRING *SXNET_get_id_INTEGER(SXNET *sx, ASN1_INTEGER *zone)
 {
-	SXNETID *id;
-	size_t i;
-	for(i = 0; i < sk_SXNETID_num(sx->ids); i++) {
-		id = sk_SXNETID_value(sx->ids, i);
-		if(!M_ASN1_INTEGER_cmp(id->zone, zone)) return id->user;
-	}
-	return NULL;
+    SXNETID *id;
+    size_t i;
+    for (i = 0; i < sk_SXNETID_num(sx->ids); i++) {
+        id = sk_SXNETID_value(sx->ids, i);
+        if (!M_ASN1_INTEGER_cmp(id->zone, zone))
+            return id->user;
+    }
+    return NULL;
 }
 
 IMPLEMENT_ASN1_SET_OF(SXNETID)
diff --git a/src/crypto/x509v3/v3_utl.c b/src/crypto/x509v3/v3_utl.c
index 6bcb6da..fe7787b 100644
--- a/src/crypto/x509v3/v3_utl.c
+++ b/src/crypto/x509v3/v3_utl.c
@@ -1,5 +1,6 @@
 /* v3_utl.c */
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project.
  */
 /* ====================================================================
@@ -10,7 +11,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -57,7 +58,6 @@
  */
 /* X509 v3 extension utilities */
 
-
 #include <ctype.h>
 #include <stdio.h>
 #include <string.h>
@@ -71,11 +71,13 @@
 #include <openssl/x509v3.h>
 
 #include "../conf/internal.h"
+#include "../internal.h"
 
 
 static char *strip_spaces(char *name);
 static int sk_strcmp(const OPENSSL_STRING *a, const OPENSSL_STRING *b);
-static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name, GENERAL_NAMES *gens);
+static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name,
+                                           GENERAL_NAMES *gens);
 static void str_free(OPENSSL_STRING str);
 static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email);
 
@@ -87,1236 +89,1225 @@
 /* Add a CONF_VALUE name value pair to stack */
 
 int X509V3_add_value(const char *name, const char *value,
-						STACK_OF(CONF_VALUE) **extlist)
+                     STACK_OF(CONF_VALUE) **extlist)
 {
-	CONF_VALUE *vtmp = NULL;
-	char *tname = NULL, *tvalue = NULL;
-	if(name && !(tname = BUF_strdup(name))) goto err;
-	if(value && !(tvalue = BUF_strdup(value))) goto err;
-	if(!(vtmp = CONF_VALUE_new())) goto err;
-	if(!*extlist && !(*extlist = sk_CONF_VALUE_new_null())) goto err;
-	vtmp->section = NULL;
-	vtmp->name = tname;
-	vtmp->value = tvalue;
-	if(!sk_CONF_VALUE_push(*extlist, vtmp)) goto err;
-	return 1;
-	err:
-	OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-	if(vtmp) OPENSSL_free(vtmp);
-	if(tname) OPENSSL_free(tname);
-	if(tvalue) OPENSSL_free(tvalue);
-	return 0;
+    CONF_VALUE *vtmp = NULL;
+    char *tname = NULL, *tvalue = NULL;
+    if (name && !(tname = BUF_strdup(name)))
+        goto err;
+    if (value && !(tvalue = BUF_strdup(value)))
+        goto err;
+    if (!(vtmp = CONF_VALUE_new()))
+        goto err;
+    if (!*extlist && !(*extlist = sk_CONF_VALUE_new_null()))
+        goto err;
+    vtmp->section = NULL;
+    vtmp->name = tname;
+    vtmp->value = tvalue;
+    if (!sk_CONF_VALUE_push(*extlist, vtmp))
+        goto err;
+    return 1;
+ err:
+    OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+    if (vtmp)
+        OPENSSL_free(vtmp);
+    if (tname)
+        OPENSSL_free(tname);
+    if (tvalue)
+        OPENSSL_free(tvalue);
+    return 0;
 }
 
 int X509V3_add_value_uchar(const char *name, const unsigned char *value,
-			   STACK_OF(CONF_VALUE) **extlist)
-    {
-    return X509V3_add_value(name,(const char *)value,extlist);
-    }
+                           STACK_OF(CONF_VALUE) **extlist)
+{
+    return X509V3_add_value(name, (const char *)value, extlist);
+}
 
 /* Free function for STACK_OF(CONF_VALUE) */
 
 void X509V3_conf_free(CONF_VALUE *conf)
 {
-	if(!conf) return;
-	if(conf->name) OPENSSL_free(conf->name);
-	if(conf->value) OPENSSL_free(conf->value);
-	if(conf->section) OPENSSL_free(conf->section);
-	OPENSSL_free(conf);
+    if (!conf)
+        return;
+    if (conf->name)
+        OPENSSL_free(conf->name);
+    if (conf->value)
+        OPENSSL_free(conf->value);
+    if (conf->section)
+        OPENSSL_free(conf->section);
+    OPENSSL_free(conf);
 }
 
 int X509V3_add_value_bool(const char *name, int asn1_bool,
-						STACK_OF(CONF_VALUE) **extlist)
+                          STACK_OF(CONF_VALUE) **extlist)
 {
-	if(asn1_bool) return X509V3_add_value(name, "TRUE", extlist);
-	return X509V3_add_value(name, "FALSE", extlist);
+    if (asn1_bool)
+        return X509V3_add_value(name, "TRUE", extlist);
+    return X509V3_add_value(name, "FALSE", extlist);
 }
 
 int X509V3_add_value_bool_nf(char *name, int asn1_bool,
-						STACK_OF(CONF_VALUE) **extlist)
+                             STACK_OF(CONF_VALUE) **extlist)
 {
-	if(asn1_bool) return X509V3_add_value(name, "TRUE", extlist);
-	return 1;
+    if (asn1_bool)
+        return X509V3_add_value(name, "TRUE", extlist);
+    return 1;
 }
 
-
 char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *method, ASN1_ENUMERATED *a)
 {
-	BIGNUM *bntmp = NULL;
-	char *strtmp = NULL;
-	if(!a) return NULL;
-	if(!(bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) ||
-	    !(strtmp = BN_bn2dec(bntmp)) )
-		OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-	BN_free(bntmp);
-	return strtmp;
+    BIGNUM *bntmp = NULL;
+    char *strtmp = NULL;
+    if (!a)
+        return NULL;
+    if (!(bntmp = ASN1_ENUMERATED_to_BN(a, NULL)) ||
+        !(strtmp = BN_bn2dec(bntmp)))
+        OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+    BN_free(bntmp);
+    return strtmp;
 }
 
 char *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *method, ASN1_INTEGER *a)
 {
-	BIGNUM *bntmp = NULL;
-	char *strtmp = NULL;
-	if(!a) return NULL;
-	if(!(bntmp = ASN1_INTEGER_to_BN(a, NULL)) ||
-	    !(strtmp = BN_bn2dec(bntmp)) )
-		OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-	BN_free(bntmp);
-	return strtmp;
+    BIGNUM *bntmp = NULL;
+    char *strtmp = NULL;
+    if (!a)
+        return NULL;
+    if (!(bntmp = ASN1_INTEGER_to_BN(a, NULL)) ||
+        !(strtmp = BN_bn2dec(bntmp)))
+        OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+    BN_free(bntmp);
+    return strtmp;
 }
 
 ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, char *value)
 {
-	BIGNUM *bn = NULL;
-	ASN1_INTEGER *aint;
-	int isneg, ishex;
-	int ret;
-	if (!value) {
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_VALUE);
-		return 0;
-	}
-	bn = BN_new();
-	if (value[0] == '-') {
-		value++;
-		isneg = 1;
-	} else isneg = 0;
+    BIGNUM *bn = NULL;
+    ASN1_INTEGER *aint;
+    int isneg, ishex;
+    int ret;
+    if (!value) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_VALUE);
+        return 0;
+    }
+    bn = BN_new();
+    if (value[0] == '-') {
+        value++;
+        isneg = 1;
+    } else
+        isneg = 0;
 
-	if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) {
-		value += 2;
-		ishex = 1;
-	} else ishex = 0;
+    if (value[0] == '0' && ((value[1] == 'x') || (value[1] == 'X'))) {
+        value += 2;
+        ishex = 1;
+    } else
+        ishex = 0;
 
-	if (ishex) ret = BN_hex2bn(&bn, value);
-	else ret = BN_dec2bn(&bn, value);
+    if (ishex)
+        ret = BN_hex2bn(&bn, value);
+    else
+        ret = BN_dec2bn(&bn, value);
 
-	if (!ret || value[ret]) {
-		BN_free(bn);
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_BN_DEC2BN_ERROR);
-		return 0;
-	}
+    if (!ret || value[ret]) {
+        BN_free(bn);
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_BN_DEC2BN_ERROR);
+        return 0;
+    }
 
-	if (isneg && BN_is_zero(bn)) isneg = 0;
+    if (isneg && BN_is_zero(bn))
+        isneg = 0;
 
-	aint = BN_to_ASN1_INTEGER(bn, NULL);
-	BN_free(bn);
-	if (!aint) {
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_BN_TO_ASN1_INTEGER_ERROR);
-		return 0;
-	}
-	if (isneg) aint->type |= V_ASN1_NEG;
-	return aint;
+    aint = BN_to_ASN1_INTEGER(bn, NULL);
+    BN_free(bn);
+    if (!aint) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_BN_TO_ASN1_INTEGER_ERROR);
+        return 0;
+    }
+    if (isneg)
+        aint->type |= V_ASN1_NEG;
+    return aint;
 }
 
 int X509V3_add_value_int(const char *name, ASN1_INTEGER *aint,
-	     STACK_OF(CONF_VALUE) **extlist)
+                         STACK_OF(CONF_VALUE) **extlist)
 {
-	char *strtmp;
-	int ret;
-	if(!aint) return 1;
-	if(!(strtmp = i2s_ASN1_INTEGER(NULL, aint))) return 0;
-	ret = X509V3_add_value(name, strtmp, extlist);
-	OPENSSL_free(strtmp);
-	return ret;
+    char *strtmp;
+    int ret;
+    if (!aint)
+        return 1;
+    if (!(strtmp = i2s_ASN1_INTEGER(NULL, aint)))
+        return 0;
+    ret = X509V3_add_value(name, strtmp, extlist);
+    OPENSSL_free(strtmp);
+    return ret;
 }
 
 int X509V3_get_value_bool(CONF_VALUE *value, int *asn1_bool)
 {
-	char *btmp;
-	if(!(btmp = value->value)) goto err;
-	if(!strcmp(btmp, "TRUE") || !strcmp(btmp, "true")
-		 || !strcmp(btmp, "Y") || !strcmp(btmp, "y")
-		|| !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) {
-		*asn1_bool = 0xff;
-		return 1;
-	} else if(!strcmp(btmp, "FALSE") || !strcmp(btmp, "false")
-		 || !strcmp(btmp, "N") || !strcmp(btmp, "n")
-		|| !strcmp(btmp, "NO") || !strcmp(btmp, "no")) {
-		*asn1_bool = 0;
-		return 1;
-	}
-	err:
-	OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_BOOLEAN_STRING);
-	X509V3_conf_err(value);
-	return 0;
+    char *btmp;
+    if (!(btmp = value->value))
+        goto err;
+    if (!strcmp(btmp, "TRUE") || !strcmp(btmp, "true")
+        || !strcmp(btmp, "Y") || !strcmp(btmp, "y")
+        || !strcmp(btmp, "YES") || !strcmp(btmp, "yes")) {
+        *asn1_bool = 0xff;
+        return 1;
+    } else if (!strcmp(btmp, "FALSE") || !strcmp(btmp, "false")
+               || !strcmp(btmp, "N") || !strcmp(btmp, "n")
+               || !strcmp(btmp, "NO") || !strcmp(btmp, "no")) {
+        *asn1_bool = 0;
+        return 1;
+    }
+ err:
+    OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_BOOLEAN_STRING);
+    X509V3_conf_err(value);
+    return 0;
 }
 
 int X509V3_get_value_int(CONF_VALUE *value, ASN1_INTEGER **aint)
 {
-	ASN1_INTEGER *itmp;
-	if(!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) {
-		X509V3_conf_err(value);
-		return 0;
-	}
-	*aint = itmp;
-	return 1;
+    ASN1_INTEGER *itmp;
+    if (!(itmp = s2i_ASN1_INTEGER(NULL, value->value))) {
+        X509V3_conf_err(value);
+        return 0;
+    }
+    *aint = itmp;
+    return 1;
 }
 
-#define HDR_NAME	1
-#define HDR_VALUE	2
+#define HDR_NAME        1
+#define HDR_VALUE       2
 
-/*#define DEBUG*/
+/*
+ * #define DEBUG
+ */
 
 STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line)
 {
-	char *p, *q, c;
-	char *ntmp, *vtmp;
-	STACK_OF(CONF_VALUE) *values = NULL;
-	char *linebuf;
-	int state;
-	/* We are going to modify the line so copy it first */
-	linebuf = BUF_strdup(line);
-	if (linebuf == NULL)
-		{
-		OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-		goto err;
-		}
-	state = HDR_NAME;
-	ntmp = NULL;
-	/* Go through all characters */
-	for(p = linebuf, q = linebuf; (c = *p) && (c!='\r') && (c!='\n'); p++) {
+    char *p, *q, c;
+    char *ntmp, *vtmp;
+    STACK_OF(CONF_VALUE) *values = NULL;
+    char *linebuf;
+    int state;
+    /* We are going to modify the line so copy it first */
+    linebuf = BUF_strdup(line);
+    if (linebuf == NULL) {
+        OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+    state = HDR_NAME;
+    ntmp = NULL;
+    /* Go through all characters */
+    for (p = linebuf, q = linebuf; (c = *p) && (c != '\r') && (c != '\n');
+         p++) {
 
-		switch(state) {
-			case HDR_NAME:
-			if(c == ':') {
-				state = HDR_VALUE;
-				*p = 0;
-				ntmp = strip_spaces(q);
-				if(!ntmp) {
-					OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_NAME);
-					goto err;
-				}
-				q = p + 1;
-			} else if(c == ',') {
-				*p = 0;
-				ntmp = strip_spaces(q);
-				q = p + 1;
+        switch (state) {
+        case HDR_NAME:
+            if (c == ':') {
+                state = HDR_VALUE;
+                *p = 0;
+                ntmp = strip_spaces(q);
+                if (!ntmp) {
+                    OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_NAME);
+                    goto err;
+                }
+                q = p + 1;
+            } else if (c == ',') {
+                *p = 0;
+                ntmp = strip_spaces(q);
+                q = p + 1;
 #if 0
-				printf("%s\n", ntmp);
+                printf("%s\n", ntmp);
 #endif
-				if(!ntmp) {
-					OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_NAME);
-					goto err;
-				}
-				X509V3_add_value(ntmp, NULL, &values);
-			}
-			break ;
+                if (!ntmp) {
+                    OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_NAME);
+                    goto err;
+                }
+                X509V3_add_value(ntmp, NULL, &values);
+            }
+            break;
 
-			case HDR_VALUE:
-			if(c == ',') {
-				state = HDR_NAME;
-				*p = 0;
-				vtmp = strip_spaces(q);
+        case HDR_VALUE:
+            if (c == ',') {
+                state = HDR_NAME;
+                *p = 0;
+                vtmp = strip_spaces(q);
 #if 0
-				printf("%s\n", ntmp);
+                printf("%s\n", ntmp);
 #endif
-				if(!vtmp) {
-					OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_VALUE);
-					goto err;
-				}
-				X509V3_add_value(ntmp, vtmp, &values);
-				ntmp = NULL;
-				q = p + 1;
-			}
+                if (!vtmp) {
+                    OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_VALUE);
+                    goto err;
+                }
+                X509V3_add_value(ntmp, vtmp, &values);
+                ntmp = NULL;
+                q = p + 1;
+            }
 
-		}
-	}
+        }
+    }
 
-	if(state == HDR_VALUE) {
-		vtmp = strip_spaces(q);
+    if (state == HDR_VALUE) {
+        vtmp = strip_spaces(q);
 #if 0
-		printf("%s=%s\n", ntmp, vtmp);
+        printf("%s=%s\n", ntmp, vtmp);
 #endif
-		if(!vtmp) {
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_VALUE);
-			goto err;
-		}
-		X509V3_add_value(ntmp, vtmp, &values);
-	} else {
-		ntmp = strip_spaces(q);
+        if (!vtmp) {
+            OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_VALUE);
+            goto err;
+        }
+        X509V3_add_value(ntmp, vtmp, &values);
+    } else {
+        ntmp = strip_spaces(q);
 #if 0
-		printf("%s\n", ntmp);
+        printf("%s\n", ntmp);
 #endif
-		if(!ntmp) {
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_NAME);
-			goto err;
-		}
-		X509V3_add_value(ntmp, NULL, &values);
-	}
-OPENSSL_free(linebuf);
-return values;
+        if (!ntmp) {
+            OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_NAME);
+            goto err;
+        }
+        X509V3_add_value(ntmp, NULL, &values);
+    }
+    OPENSSL_free(linebuf);
+    return values;
 
-err:
-OPENSSL_free(linebuf);
-sk_CONF_VALUE_pop_free(values, X509V3_conf_free);
-return NULL;
+ err:
+    OPENSSL_free(linebuf);
+    sk_CONF_VALUE_pop_free(values, X509V3_conf_free);
+    return NULL;
 
 }
 
 /* Delete leading and trailing spaces from a string */
 static char *strip_spaces(char *name)
 {
-	char *p, *q;
-	/* Skip over leading spaces */
-	p = name;
-	while(*p && isspace((unsigned char)*p)) p++;
-	if(!*p) return NULL;
-	q = p + strlen(p) - 1;
-	while((q != p) && isspace((unsigned char)*q)) q--;
-	if(p != q) q[1] = 0;
-	if(!*p) return NULL;
-	return p;
+    char *p, *q;
+    /* Skip over leading spaces */
+    p = name;
+    while (*p && isspace((unsigned char)*p))
+        p++;
+    if (!*p)
+        return NULL;
+    q = p + strlen(p) - 1;
+    while ((q != p) && isspace((unsigned char)*q))
+        q--;
+    if (p != q)
+        q[1] = 0;
+    if (!*p)
+        return NULL;
+    return p;
 }
 
 /* hex string utilities */
 
-/* Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its
- * hex representation
- * @@@ (Contents of buffer are always kept in ASCII, also on EBCDIC machines)
+/*
+ * Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its
+ * hex representation @@@ (Contents of buffer are always kept in ASCII, also
+ * on EBCDIC machines)
  */
 
 char *hex_to_string(const unsigned char *buffer, long len)
 {
-	char *tmp, *q;
-	const unsigned char *p;
-	int i;
-	static const char hexdig[] = "0123456789ABCDEF";
-	if(!buffer || !len) return NULL;
-	if(!(tmp = OPENSSL_malloc(len * 3 + 1))) {
-		OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-		return NULL;
-	}
-	q = tmp;
-	for(i = 0, p = buffer; i < len; i++,p++) {
-		*q++ = hexdig[(*p >> 4) & 0xf];
-		*q++ = hexdig[*p & 0xf];
-		*q++ = ':';
-	}
-	q[-1] = 0;
+    char *tmp, *q;
+    const unsigned char *p;
+    int i;
+    static const char hexdig[] = "0123456789ABCDEF";
+    if (!buffer || !len)
+        return NULL;
+    if (!(tmp = OPENSSL_malloc(len * 3 + 1))) {
+        OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+        return NULL;
+    }
+    q = tmp;
+    for (i = 0, p = buffer; i < len; i++, p++) {
+        *q++ = hexdig[(*p >> 4) & 0xf];
+        *q++ = hexdig[*p & 0xf];
+        *q++ = ':';
+    }
+    q[-1] = 0;
 
-	return tmp;
+    return tmp;
 }
 
-/* Give a string of hex digits convert to
- * a buffer
+/*
+ * Give a string of hex digits convert to a buffer
  */
 
 unsigned char *string_to_hex(const char *str, long *len)
 {
-	unsigned char *hexbuf, *q;
-	unsigned char ch, cl, *p;
-	if(!str) {
-		OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_ARGUMENT);
-		return NULL;
-	}
-	if(!(hexbuf = OPENSSL_malloc(strlen(str) >> 1))) goto err;
-	for(p = (unsigned char *)str, q = hexbuf; *p;) {
-		ch = *p++;
-		if(ch == ':') continue;
-		cl = *p++;
-		if(!cl) {
-			OPENSSL_PUT_ERROR(X509V3, X509V3_R_ODD_NUMBER_OF_DIGITS);
-			OPENSSL_free(hexbuf);
-			return NULL;
-		}
-		if(isupper(ch)) ch = tolower(ch);
-		if(isupper(cl)) cl = tolower(cl);
+    unsigned char *hexbuf, *q;
+    unsigned char ch, cl, *p;
+    if (!str) {
+        OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NULL_ARGUMENT);
+        return NULL;
+    }
+    if (!(hexbuf = OPENSSL_malloc(strlen(str) >> 1)))
+        goto err;
+    for (p = (unsigned char *)str, q = hexbuf; *p;) {
+        ch = *p++;
+        if (ch == ':')
+            continue;
+        cl = *p++;
+        if (!cl) {
+            OPENSSL_PUT_ERROR(X509V3, X509V3_R_ODD_NUMBER_OF_DIGITS);
+            OPENSSL_free(hexbuf);
+            return NULL;
+        }
+        if (isupper(ch))
+            ch = tolower(ch);
+        if (isupper(cl))
+            cl = tolower(cl);
 
-		if((ch >= '0') && (ch <= '9')) ch -= '0';
-		else if ((ch >= 'a') && (ch <= 'f')) ch -= 'a' - 10;
-		else goto badhex;
+        if ((ch >= '0') && (ch <= '9'))
+            ch -= '0';
+        else if ((ch >= 'a') && (ch <= 'f'))
+            ch -= 'a' - 10;
+        else
+            goto badhex;
 
-		if((cl >= '0') && (cl <= '9')) cl -= '0';
-		else if ((cl >= 'a') && (cl <= 'f')) cl -= 'a' - 10;
-		else goto badhex;
+        if ((cl >= '0') && (cl <= '9'))
+            cl -= '0';
+        else if ((cl >= 'a') && (cl <= 'f'))
+            cl -= 'a' - 10;
+        else
+            goto badhex;
 
-		*q++ = (ch << 4) | cl;
-	}
+        *q++ = (ch << 4) | cl;
+    }
 
-	if(len) *len = q - hexbuf;
+    if (len)
+        *len = q - hexbuf;
 
-	return hexbuf;
+    return hexbuf;
 
-	err:
-	if(hexbuf) OPENSSL_free(hexbuf);
-	OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
-	return NULL;
+ err:
+    if (hexbuf)
+        OPENSSL_free(hexbuf);
+    OPENSSL_PUT_ERROR(X509V3, ERR_R_MALLOC_FAILURE);
+    return NULL;
 
-	badhex:
-	OPENSSL_free(hexbuf);
-	OPENSSL_PUT_ERROR(X509V3, X509V3_R_ILLEGAL_HEX_DIGIT);
-	return NULL;
+ badhex:
+    OPENSSL_free(hexbuf);
+    OPENSSL_PUT_ERROR(X509V3, X509V3_R_ILLEGAL_HEX_DIGIT);
+    return NULL;
 
 }
 
-/* V2I name comparison function: returns zero if 'name' matches
- * cmp or cmp.*
+/*
+ * V2I name comparison function: returns zero if 'name' matches cmp or cmp.*
  */
 
 int name_cmp(const char *name, const char *cmp)
 {
-	int len, ret;
-	char c;
-	len = strlen(cmp);
-	if((ret = strncmp(name, cmp, len))) return ret;
-	c = name[len];
-	if(!c || (c=='.')) return 0;
-	return 1;
+    int len, ret;
+    char c;
+    len = strlen(cmp);
+    if ((ret = strncmp(name, cmp, len)))
+        return ret;
+    c = name[len];
+    if (!c || (c == '.'))
+        return 0;
+    return 1;
 }
 
 static int sk_strcmp(const OPENSSL_STRING *a, const OPENSSL_STRING *b)
 {
-	return strcmp(*a, *b);
+    return strcmp(*a, *b);
 }
 
 STACK_OF(OPENSSL_STRING) *X509_get1_email(X509 *x)
 {
-	GENERAL_NAMES *gens;
-	STACK_OF(OPENSSL_STRING) *ret;
+    GENERAL_NAMES *gens;
+    STACK_OF(OPENSSL_STRING) *ret;
 
-	gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
-	ret = get_email(X509_get_subject_name(x), gens);
-	sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
-	return ret;
+    gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
+    ret = get_email(X509_get_subject_name(x), gens);
+    sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
+    return ret;
 }
 
 STACK_OF(OPENSSL_STRING) *X509_get1_ocsp(X509 *x)
 {
-	AUTHORITY_INFO_ACCESS *info;
-	STACK_OF(OPENSSL_STRING) *ret = NULL;
-	size_t i;
+    AUTHORITY_INFO_ACCESS *info;
+    STACK_OF(OPENSSL_STRING) *ret = NULL;
+    size_t i;
 
-	info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL);
-	if (!info)
-		return NULL;
-	for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++)
-		{
-		ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i);
-		if (OBJ_obj2nid(ad->method) == NID_ad_OCSP)
-			{
-			if (ad->location->type == GEN_URI)
-				{
-				if (!append_ia5(&ret, ad->location->d.uniformResourceIdentifier))
-					break;
-				}
-			}
-		}
-	AUTHORITY_INFO_ACCESS_free(info);
-	return ret;
+    info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL);
+    if (!info)
+        return NULL;
+    for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) {
+        ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i);
+        if (OBJ_obj2nid(ad->method) == NID_ad_OCSP) {
+            if (ad->location->type == GEN_URI) {
+                if (!append_ia5
+                    (&ret, ad->location->d.uniformResourceIdentifier))
+                    break;
+            }
+        }
+    }
+    AUTHORITY_INFO_ACCESS_free(info);
+    return ret;
 }
 
 STACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x)
 {
-	GENERAL_NAMES *gens;
-	STACK_OF(X509_EXTENSION) *exts;
-	STACK_OF(OPENSSL_STRING) *ret;
+    GENERAL_NAMES *gens;
+    STACK_OF(X509_EXTENSION) *exts;
+    STACK_OF(OPENSSL_STRING) *ret;
 
-	exts = X509_REQ_get_extensions(x);
-	gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL);
-	ret = get_email(X509_REQ_get_subject_name(x), gens);
-	sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
-	sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
-	return ret;
+    exts = X509_REQ_get_extensions(x);
+    gens = X509V3_get_d2i(exts, NID_subject_alt_name, NULL, NULL);
+    ret = get_email(X509_REQ_get_subject_name(x), gens);
+    sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
+    sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
+    return ret;
 }
 
-
-static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name, GENERAL_NAMES *gens)
+static STACK_OF(OPENSSL_STRING) *get_email(X509_NAME *name,
+                                           GENERAL_NAMES *gens)
 {
-	STACK_OF(OPENSSL_STRING) *ret = NULL;
-	X509_NAME_ENTRY *ne;
-	ASN1_IA5STRING *email;
-	GENERAL_NAME *gen;
-	int i;
-	size_t j;
-	/* Now add any email address(es) to STACK */
-	i = -1;
-	/* First supplied X509_NAME */
-	while((i = X509_NAME_get_index_by_NID(name,
-					 NID_pkcs9_emailAddress, i)) >= 0) {
-		ne = X509_NAME_get_entry(name, i);
-		email = X509_NAME_ENTRY_get_data(ne);
-		if(!append_ia5(&ret, email)) return NULL;
-	}
-	for(j = 0; j < sk_GENERAL_NAME_num(gens); j++)
-	{
-		gen = sk_GENERAL_NAME_value(gens, j);
-		if(gen->type != GEN_EMAIL) continue;
-		if(!append_ia5(&ret, gen->d.ia5)) return NULL;
-	}
-	return ret;
+    STACK_OF(OPENSSL_STRING) *ret = NULL;
+    X509_NAME_ENTRY *ne;
+    ASN1_IA5STRING *email;
+    GENERAL_NAME *gen;
+    int i;
+    size_t j;
+    /* Now add any email address(es) to STACK */
+    i = -1;
+    /* First supplied X509_NAME */
+    while ((i = X509_NAME_get_index_by_NID(name,
+                                           NID_pkcs9_emailAddress, i)) >= 0) {
+        ne = X509_NAME_get_entry(name, i);
+        email = X509_NAME_ENTRY_get_data(ne);
+        if (!append_ia5(&ret, email))
+            return NULL;
+    }
+    for (j = 0; j < sk_GENERAL_NAME_num(gens); j++) {
+        gen = sk_GENERAL_NAME_value(gens, j);
+        if (gen->type != GEN_EMAIL)
+            continue;
+        if (!append_ia5(&ret, gen->d.ia5))
+            return NULL;
+    }
+    return ret;
 }
 
 static void str_free(OPENSSL_STRING str)
 {
-	OPENSSL_free(str);
+    OPENSSL_free(str);
 }
 
 static int append_ia5(STACK_OF(OPENSSL_STRING) **sk, ASN1_IA5STRING *email)
 {
-	char *emtmp;
-	/* First some sanity checks */
-	if(email->type != V_ASN1_IA5STRING) return 1;
-	if(!email->data || !email->length) return 1;
-	if(!*sk) *sk = sk_OPENSSL_STRING_new(sk_strcmp);
-	if(!*sk) return 0;
-	/* Don't add duplicates */
-	if(sk_OPENSSL_STRING_find(*sk, NULL, (char *)email->data)) return 1;
-	emtmp = BUF_strdup((char *)email->data);
-	if(!emtmp || !sk_OPENSSL_STRING_push(*sk, emtmp)) {
-		X509_email_free(*sk);
-		*sk = NULL;
-		return 0;
-	}
-	return 1;
+    char *emtmp;
+    /* First some sanity checks */
+    if (email->type != V_ASN1_IA5STRING)
+        return 1;
+    if (!email->data || !email->length)
+        return 1;
+    if (!*sk)
+        *sk = sk_OPENSSL_STRING_new(sk_strcmp);
+    if (!*sk)
+        return 0;
+    /* Don't add duplicates */
+    if (sk_OPENSSL_STRING_find(*sk, NULL, (char *)email->data))
+        return 1;
+    emtmp = BUF_strdup((char *)email->data);
+    if (!emtmp || !sk_OPENSSL_STRING_push(*sk, emtmp)) {
+        X509_email_free(*sk);
+        *sk = NULL;
+        return 0;
+    }
+    return 1;
 }
 
 void X509_email_free(STACK_OF(OPENSSL_STRING) *sk)
 {
-	sk_OPENSSL_STRING_pop_free(sk, str_free);
+    sk_OPENSSL_STRING_pop_free(sk, str_free);
 }
 
-typedef int (*equal_fn)(const unsigned char *pattern, size_t pattern_len,
-			const unsigned char *subject, size_t subject_len,
-			unsigned int flags);
+typedef int (*equal_fn) (const unsigned char *pattern, size_t pattern_len,
+                         const unsigned char *subject, size_t subject_len,
+                         unsigned int flags);
 
 /* Skip pattern prefix to match "wildcard" subject */
 static void skip_prefix(const unsigned char **p, size_t *plen,
-			const unsigned char *subject, size_t subject_len,
-			unsigned int flags)
-	{
-	const unsigned char *pattern = *p;
-	size_t pattern_len = *plen;
+                        const unsigned char *subject, size_t subject_len,
+                        unsigned int flags)
+{
+    const unsigned char *pattern = *p;
+    size_t pattern_len = *plen;
 
-	/*
-	 * If subject starts with a leading '.' followed by more octets, and
-	 * pattern is longer, compare just an equal-length suffix with the
-	 * full subject (starting at the '.'), provided the prefix contains
-	 * no NULs.
-	 */
-	if ((flags & _X509_CHECK_FLAG_DOT_SUBDOMAINS) == 0)
-		return;
+    /*
+     * If subject starts with a leading '.' followed by more octets, and
+     * pattern is longer, compare just an equal-length suffix with the
+     * full subject (starting at the '.'), provided the prefix contains
+     * no NULs.
+     */
+    if ((flags & _X509_CHECK_FLAG_DOT_SUBDOMAINS) == 0)
+        return;
 
-	while (pattern_len > subject_len && *pattern)
-		{
-		if ((flags & X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS) &&
-		    *pattern == '.')
-			break;
-		++pattern;
-		--pattern_len;
-		}
+    while (pattern_len > subject_len && *pattern) {
+        if ((flags & X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS) &&
+            *pattern == '.')
+            break;
+        ++pattern;
+        --pattern_len;
+    }
 
-	/* Skip if entire prefix acceptable */
-	if (pattern_len == subject_len)
-		{
-		*p = pattern;
-		*plen = pattern_len;
-		}
-	}
+    /* Skip if entire prefix acceptable */
+    if (pattern_len == subject_len) {
+        *p = pattern;
+        *plen = pattern_len;
+    }
+}
 
 /* Compare while ASCII ignoring case. */
 static int equal_nocase(const unsigned char *pattern, size_t pattern_len,
-			const unsigned char *subject, size_t subject_len,
-			unsigned int flags)
-	{
-	skip_prefix(&pattern, &pattern_len, subject, subject_len, flags);
-	if (pattern_len != subject_len)
-		return 0;
-	while (pattern_len)
-		{
-		unsigned char l = *pattern;
-		unsigned char r = *subject;
-		/* The pattern must not contain NUL characters. */
-		if (l == 0)
-			return 0;
-		if (l != r)
-			{
-			if ('A' <= l && l <= 'Z')
-				l = (l - 'A') + 'a';
-			if ('A' <= r && r <= 'Z')
-				r = (r - 'A') + 'a';
-			if (l != r)
-				return 0;
-			}
-		++pattern;
-		++subject;
-		--pattern_len;
-		}
-	return 1;
-	}
-
-/* Compare using memcmp. */
-static int equal_case(const unsigned char *pattern, size_t pattern_len,
-		      const unsigned char *subject, size_t subject_len,
-		      unsigned int flags)
+                        const unsigned char *subject, size_t subject_len,
+                        unsigned int flags)
 {
-	skip_prefix(&pattern, &pattern_len, subject, subject_len, flags);
-	if (pattern_len != subject_len)
-		return 0;
-	return !memcmp(pattern, subject, pattern_len);
+    skip_prefix(&pattern, &pattern_len, subject, subject_len, flags);
+    if (pattern_len != subject_len)
+        return 0;
+    while (pattern_len) {
+        unsigned char l = *pattern;
+        unsigned char r = *subject;
+        /* The pattern must not contain NUL characters. */
+        if (l == 0)
+            return 0;
+        if (l != r) {
+            if ('A' <= l && l <= 'Z')
+                l = (l - 'A') + 'a';
+            if ('A' <= r && r <= 'Z')
+                r = (r - 'A') + 'a';
+            if (l != r)
+                return 0;
+        }
+        ++pattern;
+        ++subject;
+        --pattern_len;
+    }
+    return 1;
 }
 
-/* RFC 5280, section 7.5, requires that only the domain is compared in
-   a case-insensitive manner. */
+/* Compare using OPENSSL_memcmp. */
+static int equal_case(const unsigned char *pattern, size_t pattern_len,
+                      const unsigned char *subject, size_t subject_len,
+                      unsigned int flags)
+{
+    skip_prefix(&pattern, &pattern_len, subject, subject_len, flags);
+    if (pattern_len != subject_len)
+        return 0;
+    return !OPENSSL_memcmp(pattern, subject, pattern_len);
+}
+
+/*
+ * RFC 5280, section 7.5, requires that only the domain is compared in a
+ * case-insensitive manner.
+ */
 static int equal_email(const unsigned char *a, size_t a_len,
-		       const unsigned char *b, size_t b_len,
-		       unsigned int unused_flags)
-	{
-	size_t i = a_len;
-	if (a_len != b_len)
-		return 0;
-	/* We search backwards for the '@' character, so that we do
-	   not have to deal with quoted local-parts.  The domain part
-	   is compared in a case-insensitive manner. */
-	while (i > 0)
-		{
-		--i;
-		if (a[i] == '@' || b[i] == '@')
-			{
-			if (!equal_nocase(a + i, a_len - i,
-					  b + i, a_len - i, 0))
-				return 0;
-			break;
-			}
-		}
-	if (i == 0)
-		i = a_len;
-	return equal_case(a, i, b, i, 0);
-	}
+                       const unsigned char *b, size_t b_len,
+                       unsigned int unused_flags)
+{
+    size_t i = a_len;
+    if (a_len != b_len)
+        return 0;
+    /*
+     * We search backwards for the '@' character, so that we do not have to
+     * deal with quoted local-parts.  The domain part is compared in a
+     * case-insensitive manner.
+     */
+    while (i > 0) {
+        --i;
+        if (a[i] == '@' || b[i] == '@') {
+            if (!equal_nocase(a + i, a_len - i, b + i, a_len - i, 0))
+                return 0;
+            break;
+        }
+    }
+    if (i == 0)
+        i = a_len;
+    return equal_case(a, i, b, i, 0);
+}
 
-/* Compare the prefix and suffix with the subject, and check that the
-   characters in-between are valid. */
+/*
+ * Compare the prefix and suffix with the subject, and check that the
+ * characters in-between are valid.
+ */
 static int wildcard_match(const unsigned char *prefix, size_t prefix_len,
-			  const unsigned char *suffix, size_t suffix_len,
-			  const unsigned char *subject, size_t subject_len,
-			  unsigned int flags)
-	{
-	const unsigned char *wildcard_start;
-	const unsigned char *wildcard_end;
-	const unsigned char *p;
-	int allow_multi = 0;
-	int allow_idna = 0;
+                          const unsigned char *suffix, size_t suffix_len,
+                          const unsigned char *subject, size_t subject_len,
+                          unsigned int flags)
+{
+    const unsigned char *wildcard_start;
+    const unsigned char *wildcard_end;
+    const unsigned char *p;
+    int allow_multi = 0;
+    int allow_idna = 0;
 
-	if (subject_len < prefix_len + suffix_len)
-		return 0;
-	if (!equal_nocase(prefix, prefix_len, subject, prefix_len, flags))
-		return 0;
-	wildcard_start = subject + prefix_len;
-	wildcard_end = subject + (subject_len - suffix_len);
-	if (!equal_nocase(wildcard_end, suffix_len, suffix, suffix_len, flags))
-		return 0;
-	/*
-	 * If the wildcard makes up the entire first label, it must match at
-	 * least one character.
-	 */
-	if (prefix_len == 0 && *suffix == '.')
-		{
-		if (wildcard_start == wildcard_end)
-			return 0;
-		allow_idna = 1;
-		if (flags & X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS)
-			allow_multi = 1;
-		}
-	/* IDNA labels cannot match partial wildcards */
-	if (!allow_idna &&
-	    subject_len >= 4 && OPENSSL_strncasecmp((char *)subject, "xn--", 4) == 0)
-		return 0;
-	/* The wildcard may match a literal '*' */
-	if (wildcard_end == wildcard_start + 1 && *wildcard_start == '*')
-		return 1;
-	/*
-	 * Check that the part matched by the wildcard contains only
-	 * permitted characters and only matches a single label unless
-	 * allow_multi is set.
-	 */
-	for (p = wildcard_start; p != wildcard_end; ++p)
-		if (!(('0' <= *p && *p <= '9') ||
-		      ('A' <= *p && *p <= 'Z') ||
-		      ('a' <= *p && *p <= 'z') ||
-		      *p == '-' || (allow_multi && *p == '.')))
-			return 0;
-	return 1;
-	}
+    if (subject_len < prefix_len + suffix_len)
+        return 0;
+    if (!equal_nocase(prefix, prefix_len, subject, prefix_len, flags))
+        return 0;
+    wildcard_start = subject + prefix_len;
+    wildcard_end = subject + (subject_len - suffix_len);
+    if (!equal_nocase(wildcard_end, suffix_len, suffix, suffix_len, flags))
+        return 0;
+    /*
+     * If the wildcard makes up the entire first label, it must match at
+     * least one character.
+     */
+    if (prefix_len == 0 && *suffix == '.') {
+        if (wildcard_start == wildcard_end)
+            return 0;
+        allow_idna = 1;
+        if (flags & X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS)
+            allow_multi = 1;
+    }
+    /* IDNA labels cannot match partial wildcards */
+    if (!allow_idna &&
+        subject_len >= 4
+        && OPENSSL_strncasecmp((char *)subject, "xn--", 4) == 0)
+        return 0;
+    /* The wildcard may match a literal '*' */
+    if (wildcard_end == wildcard_start + 1 && *wildcard_start == '*')
+        return 1;
+    /*
+     * Check that the part matched by the wildcard contains only
+     * permitted characters and only matches a single label unless
+     * allow_multi is set.
+     */
+    for (p = wildcard_start; p != wildcard_end; ++p)
+        if (!(('0' <= *p && *p <= '9') ||
+              ('A' <= *p && *p <= 'Z') ||
+              ('a' <= *p && *p <= 'z') ||
+              *p == '-' || (allow_multi && *p == '.')))
+            return 0;
+    return 1;
+}
 
-#define LABEL_START	(1 << 0)
-#define LABEL_END	(1 << 1)
-#define LABEL_HYPHEN	(1 << 2)
-#define LABEL_IDNA	(1 << 3)
+#define LABEL_START     (1 << 0)
+#define LABEL_END       (1 << 1)
+#define LABEL_HYPHEN    (1 << 2)
+#define LABEL_IDNA      (1 << 3)
 
 static const unsigned char *valid_star(const unsigned char *p, size_t len,
-						unsigned int flags)
-	{
-	const unsigned char *star = 0;
-	size_t i;
-	int state = LABEL_START;
-	int dots = 0;
-	for (i = 0; i < len; ++i)
-		{
-		/*
-		 * Locate first and only legal wildcard, either at the start
-		 * or end of a non-IDNA first and not final label.
-		 */
-		if (p[i] == '*')
-			{
-			int atstart = (state & LABEL_START);
-			int atend = (i == len - 1 || p[i+1] == '.');
-			/*
-			 * At most one wildcard per pattern.
-			 * No wildcards in IDNA labels.
-			 * No wildcards after the first label.
-			 */
-			if (star != NULL || (state & LABEL_IDNA) != 0 || dots)
-				return NULL;
-			/* Only full-label '*.example.com' wildcards? */
-			if ((flags & X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS)
-			    && (!atstart || !atend))
-				return NULL;
-			/* No 'foo*bar' wildcards */
-			if (!atstart && !atend)
-				return NULL;
-			star = &p[i];
-			state &= ~LABEL_START;
-			}
-		else if ((state & LABEL_START) != 0)
-			{
-			/*
-			 * At the start of a label, skip any "xn--" and
-			 * remain in the LABEL_START state, but set the
-			 * IDNA label state
-			 */
-			if ((state & LABEL_IDNA) == 0 && len - i >= 4
-			    && OPENSSL_strncasecmp((char *)&p[i], "xn--", 4) == 0)
-				{
-				i += 3;
-				state |= LABEL_IDNA;
-				continue;
-				}
-			/* Labels must start with a letter or digit */
-			state &= ~LABEL_START;
-			if (('a' <= p[i] && p[i] <= 'z')
-			    || ('A' <= p[i] && p[i] <= 'Z')
-			    || ('0' <= p[i] && p[i] <= '9'))
-				continue;
-			return NULL;
-			}
-		else if (('a' <= p[i] && p[i] <= 'z')
-			 || ('A' <= p[i] && p[i] <= 'Z')
-			 || ('0' <= p[i] && p[i] <= '9'))
-			{
-			state &= LABEL_IDNA;
-			continue;
-			}
-		else if (p[i] == '.')
-			{
-			if (state & (LABEL_HYPHEN | LABEL_START))
-				return NULL;
-			state = LABEL_START;
-			++dots;
-			}
-		else if (p[i] == '-')
-			{
-			if (state & LABEL_HYPHEN)
-				return NULL;
-			state |= LABEL_HYPHEN;
-			}
-		else
-			return NULL;
-		}
+                                       unsigned int flags)
+{
+    const unsigned char *star = 0;
+    size_t i;
+    int state = LABEL_START;
+    int dots = 0;
+    for (i = 0; i < len; ++i) {
+        /*
+         * Locate first and only legal wildcard, either at the start
+         * or end of a non-IDNA first and not final label.
+         */
+        if (p[i] == '*') {
+            int atstart = (state & LABEL_START);
+            int atend = (i == len - 1 || p[i + 1] == '.');
+            /*
+             * At most one wildcard per pattern.
+             * No wildcards in IDNA labels.
+             * No wildcards after the first label.
+             */
+            if (star != NULL || (state & LABEL_IDNA) != 0 || dots)
+                return NULL;
+            /* Only full-label '*.example.com' wildcards? */
+            if ((flags & X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS)
+                && (!atstart || !atend))
+                return NULL;
+            /* No 'foo*bar' wildcards */
+            if (!atstart && !atend)
+                return NULL;
+            star = &p[i];
+            state &= ~LABEL_START;
+        } else if (('a' <= p[i] && p[i] <= 'z')
+                   || ('A' <= p[i] && p[i] <= 'Z')
+                   || ('0' <= p[i] && p[i] <= '9')) {
+            if ((state & LABEL_START) != 0
+                && len - i >= 4
+                && OPENSSL_strncasecmp((char *)&p[i], "xn--", 4) == 0)
+                state |= LABEL_IDNA;
+            state &= ~(LABEL_HYPHEN | LABEL_START);
+        } else if (p[i] == '.') {
+            if ((state & (LABEL_HYPHEN | LABEL_START)) != 0)
+                return NULL;
+            state = LABEL_START;
+            ++dots;
+        } else if (p[i] == '-') {
+            /* no domain/subdomain starts with '-' */
+            if ((state & LABEL_START) != 0)
+                return NULL;
+            state |= LABEL_HYPHEN;
+        } else
+            return NULL;
+    }
 
-	/*
-	 * The final label must not end in a hyphen or ".", and
-	 * there must be at least two dots after the star.
-	 */
-	if ((state & (LABEL_START | LABEL_HYPHEN)) != 0
-	    || dots < 2)
-		return NULL;
-	return star;
-	}
+    /*
+     * The final label must not end in a hyphen or ".", and
+     * there must be at least two dots after the star.
+     */
+    if ((state & (LABEL_START | LABEL_HYPHEN)) != 0 || dots < 2)
+        return NULL;
+    return star;
+}
 
 /* Compare using wildcards. */
 static int equal_wildcard(const unsigned char *pattern, size_t pattern_len,
-			  const unsigned char *subject, size_t subject_len,
-			  unsigned int flags)
-	{
-	const unsigned char *star = NULL;
+                          const unsigned char *subject, size_t subject_len,
+                          unsigned int flags)
+{
+    const unsigned char *star = NULL;
 
-	/*
-	 * Subject names starting with '.' can only match a wildcard pattern
-	 * via a subject sub-domain pattern suffix match.
-	 */
-	if (!(subject_len > 1 && subject[0] == '.'))
-		star = valid_star(pattern, pattern_len, flags);
-	if (star == NULL)
-		return equal_nocase(pattern, pattern_len,
-				    subject, subject_len, flags);
-	return wildcard_match(pattern, star - pattern,
-			      star + 1, (pattern + pattern_len) - star - 1,
-			      subject, subject_len, flags);
-	}
+    /*
+     * Subject names starting with '.' can only match a wildcard pattern
+     * via a subject sub-domain pattern suffix match.
+     */
+    if (!(subject_len > 1 && subject[0] == '.'))
+        star = valid_star(pattern, pattern_len, flags);
+    if (star == NULL)
+        return equal_nocase(pattern, pattern_len,
+                            subject, subject_len, flags);
+    return wildcard_match(pattern, star - pattern,
+                          star + 1, (pattern + pattern_len) - star - 1,
+                          subject, subject_len, flags);
+}
 
-/* Compare an ASN1_STRING to a supplied string. If they match
- * return 1. If cmp_type > 0 only compare if string matches the
- * type, otherwise convert it to UTF8.
+/*
+ * Compare an ASN1_STRING to a supplied string. If they match return 1. If
+ * cmp_type > 0 only compare if string matches the type, otherwise convert it
+ * to UTF8.
  */
 
 static int do_check_string(ASN1_STRING *a, int cmp_type, equal_fn equal,
-				unsigned int flags, const char *b, size_t blen,
-				char **peername)
-	{
-	int rv = 0;
+                           unsigned int flags, const char *b, size_t blen,
+                           char **peername)
+{
+    int rv = 0;
 
-	if (!a->data || !a->length)
-		return 0;
-	if (cmp_type > 0)
-		{
-		if (cmp_type != a->type)
-			return 0;
-		if (cmp_type == V_ASN1_IA5STRING)
-			rv = equal(a->data, a->length,
-				   (unsigned char *)b, blen, flags);
-		else if (a->length == (int)blen && !memcmp(a->data, b, blen))
-			rv = 1;
-		if (rv > 0 && peername)
-			*peername = BUF_strndup((char *)a->data, a->length);
-		}
-	else
-		{
-		int astrlen;
-		unsigned char *astr;
-		astrlen = ASN1_STRING_to_UTF8(&astr, a);
-		if (astrlen < 0)
-			return -1;
-		rv = equal(astr, astrlen, (unsigned char *)b, blen, flags);
-		if (rv > 0 && peername)
-			*peername = BUF_strndup((char *)astr, astrlen);
-		OPENSSL_free(astr);
-		}
-	return rv;
-	}
+    if (!a->data || !a->length)
+        return 0;
+    if (cmp_type > 0) {
+        if (cmp_type != a->type)
+            return 0;
+        if (cmp_type == V_ASN1_IA5STRING)
+            rv = equal(a->data, a->length, (unsigned char *)b, blen, flags);
+        else if (a->length == (int)blen && !OPENSSL_memcmp(a->data, b, blen))
+            rv = 1;
+        if (rv > 0 && peername)
+            *peername = BUF_strndup((char *)a->data, a->length);
+    } else {
+        int astrlen;
+        unsigned char *astr;
+        astrlen = ASN1_STRING_to_UTF8(&astr, a);
+        if (astrlen < 0)
+            return -1;
+        rv = equal(astr, astrlen, (unsigned char *)b, blen, flags);
+        if (rv > 0 && peername)
+            *peername = BUF_strndup((char *)astr, astrlen);
+        OPENSSL_free(astr);
+    }
+    return rv;
+}
 
 static int do_x509_check(X509 *x, const char *chk, size_t chklen,
-					unsigned int flags, int check_type,
-					char **peername)
-	{
-	GENERAL_NAMES *gens = NULL;
-	X509_NAME *name = NULL;
-	size_t i;
-	int j;
-	int cnid = NID_undef;
-	int alt_type;
-	int san_present = 0;
-	int rv = 0;
-	equal_fn equal;
+                         unsigned int flags, int check_type, char **peername)
+{
+    GENERAL_NAMES *gens = NULL;
+    X509_NAME *name = NULL;
+    size_t i;
+    int j;
+    int cnid = NID_undef;
+    int alt_type;
+    int san_present = 0;
+    int rv = 0;
+    equal_fn equal;
 
-	/* See below, this flag is internal-only */
-	flags &= ~_X509_CHECK_FLAG_DOT_SUBDOMAINS;
-	if (check_type == GEN_EMAIL)
-		{
-		cnid = NID_pkcs9_emailAddress;
-		alt_type = V_ASN1_IA5STRING;
-		equal = equal_email;
-		}
-	else if (check_type == GEN_DNS)
-		{
-		cnid = NID_commonName;
-		/* Implicit client-side DNS sub-domain pattern */
-		if (chklen > 1 && chk[0] == '.')
-			flags |= _X509_CHECK_FLAG_DOT_SUBDOMAINS;
-		alt_type = V_ASN1_IA5STRING;
-		if (flags & X509_CHECK_FLAG_NO_WILDCARDS)
-			equal = equal_nocase;
-		else
-			equal = equal_wildcard;
-		}
-	else
-		{
-		alt_type = V_ASN1_OCTET_STRING;
-		equal = equal_case;
-		}
+    /* See below, this flag is internal-only */
+    flags &= ~_X509_CHECK_FLAG_DOT_SUBDOMAINS;
+    if (check_type == GEN_EMAIL) {
+        cnid = NID_pkcs9_emailAddress;
+        alt_type = V_ASN1_IA5STRING;
+        equal = equal_email;
+    } else if (check_type == GEN_DNS) {
+        cnid = NID_commonName;
+        /* Implicit client-side DNS sub-domain pattern */
+        if (chklen > 1 && chk[0] == '.')
+            flags |= _X509_CHECK_FLAG_DOT_SUBDOMAINS;
+        alt_type = V_ASN1_IA5STRING;
+        if (flags & X509_CHECK_FLAG_NO_WILDCARDS)
+            equal = equal_nocase;
+        else
+            equal = equal_wildcard;
+    } else {
+        alt_type = V_ASN1_OCTET_STRING;
+        equal = equal_case;
+    }
 
-	gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
-	if (gens)
-		{
-		for (i = 0; i < sk_GENERAL_NAME_num(gens); i++)
-			{
-			GENERAL_NAME *gen;
-			ASN1_STRING *cstr;
-			gen = sk_GENERAL_NAME_value(gens, i);
-			if (gen->type != check_type)
-				continue;
-			san_present = 1;
-			if (check_type == GEN_EMAIL)
-				cstr = gen->d.rfc822Name;
-			else if (check_type == GEN_DNS)
-				cstr = gen->d.dNSName;
-			else
-				cstr = gen->d.iPAddress;
-			/* Positive on success, negative on error! */
-			if ((rv = do_check_string(cstr, alt_type, equal, flags,
-						  chk, chklen, peername)) != 0)
-				break;
-			}
-		GENERAL_NAMES_free(gens);
-		if (rv != 0)
-			return rv;
-		if (cnid == NID_undef
-		    || (san_present
-		        && !(flags & X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT)))
-			return 0;
-		}
+    gens = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
+    if (gens) {
+        for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
+            GENERAL_NAME *gen;
+            ASN1_STRING *cstr;
+            gen = sk_GENERAL_NAME_value(gens, i);
+            if (gen->type != check_type)
+                continue;
+            san_present = 1;
+            if (check_type == GEN_EMAIL)
+                cstr = gen->d.rfc822Name;
+            else if (check_type == GEN_DNS)
+                cstr = gen->d.dNSName;
+            else
+                cstr = gen->d.iPAddress;
+            /* Positive on success, negative on error! */
+            if ((rv = do_check_string(cstr, alt_type, equal, flags,
+                                      chk, chklen, peername)) != 0)
+                break;
+        }
+        GENERAL_NAMES_free(gens);
+        if (rv != 0)
+            return rv;
+        if (cnid == NID_undef
+            || (san_present
+                && !(flags & X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT)))
+            return 0;
+    }
 
-	/* We're done if CN-ID is not pertinent */
-	if (cnid == NID_undef)
-		return 0;
+    /* We're done if CN-ID is not pertinent */
+    if (cnid == NID_undef)
+        return 0;
 
-	j = -1;
-	name = X509_get_subject_name(x);
-	while((j = X509_NAME_get_index_by_NID(name, cnid, j)) >= 0)
-		{
-		X509_NAME_ENTRY *ne;
-		ASN1_STRING *str;
-		ne = X509_NAME_get_entry(name, j);
-		str = X509_NAME_ENTRY_get_data(ne);
-		/* Positive on success, negative on error! */
-		if ((rv = do_check_string(str, -1, equal, flags,
-					  chk, chklen, peername)) != 0)
-			return rv;
-		}
-	return 0;
-	}
+    j = -1;
+    name = X509_get_subject_name(x);
+    while ((j = X509_NAME_get_index_by_NID(name, cnid, j)) >= 0) {
+        X509_NAME_ENTRY *ne;
+        ASN1_STRING *str;
+        ne = X509_NAME_get_entry(name, j);
+        str = X509_NAME_ENTRY_get_data(ne);
+        /* Positive on success, negative on error! */
+        if ((rv = do_check_string(str, -1, equal, flags,
+                                  chk, chklen, peername)) != 0)
+            return rv;
+    }
+    return 0;
+}
 
 int X509_check_host(X509 *x, const char *chk, size_t chklen,
-			unsigned int flags, char **peername)
-	{
-	if (chk == NULL)
-		return -2;
-	if (memchr(chk, '\0', chklen))
-		return -2;
-	return do_x509_check(x, chk, chklen, flags, GEN_DNS, peername);
-	}
+                    unsigned int flags, char **peername)
+{
+    if (chk == NULL)
+        return -2;
+    if (OPENSSL_memchr(chk, '\0', chklen))
+        return -2;
+    return do_x509_check(x, chk, chklen, flags, GEN_DNS, peername);
+}
 
 int X509_check_email(X509 *x, const char *chk, size_t chklen,
-			unsigned int flags)
-	{
-	if (chk == NULL)
-		return -2;
-	if (memchr(chk, '\0', chklen))
-		return -2;
-	return do_x509_check(x, chk, chklen, flags, GEN_EMAIL, NULL);
-	}
+                     unsigned int flags)
+{
+    if (chk == NULL)
+        return -2;
+    if (OPENSSL_memchr(chk, '\0', chklen))
+        return -2;
+    return do_x509_check(x, chk, chklen, flags, GEN_EMAIL, NULL);
+}
 
 int X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen,
-					unsigned int flags)
-	{
-	if (chk == NULL)
-		return -2;
-	return do_x509_check(x, (char *)chk, chklen, flags, GEN_IPADD, NULL);
-	}
+                  unsigned int flags)
+{
+    if (chk == NULL)
+        return -2;
+    return do_x509_check(x, (char *)chk, chklen, flags, GEN_IPADD, NULL);
+}
 
 int X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags)
-	{
-	unsigned char ipout[16];
-	size_t iplen;
+{
+    unsigned char ipout[16];
+    size_t iplen;
 
-	if (ipasc == NULL)
-		return -2;
-	iplen = (size_t) a2i_ipadd(ipout, ipasc);
-	if (iplen == 0)
-		return -2;
-	return do_x509_check(x, (char *)ipout, iplen, flags, GEN_IPADD, NULL);
-	}
+    if (ipasc == NULL)
+        return -2;
+    iplen = (size_t)a2i_ipadd(ipout, ipasc);
+    if (iplen == 0)
+        return -2;
+    return do_x509_check(x, (char *)ipout, iplen, flags, GEN_IPADD, NULL);
+}
 
-/* Convert IP addresses both IPv4 and IPv6 into an 
- * OCTET STRING compatible with RFC3280.
+/*
+ * Convert IP addresses both IPv4 and IPv6 into an OCTET STRING compatible
+ * with RFC3280.
  */
 
 ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc)
-	{
-	unsigned char ipout[16];
-	ASN1_OCTET_STRING *ret;
-	int iplen;
+{
+    unsigned char ipout[16];
+    ASN1_OCTET_STRING *ret;
+    int iplen;
 
-	/* If string contains a ':' assume IPv6 */
+    /* If string contains a ':' assume IPv6 */
 
-	iplen = a2i_ipadd(ipout, ipasc);
+    iplen = a2i_ipadd(ipout, ipasc);
 
-	if (!iplen)
-		return NULL;
+    if (!iplen)
+        return NULL;
 
-	ret = ASN1_OCTET_STRING_new();
-	if (!ret)
-		return NULL;
-	if (!ASN1_OCTET_STRING_set(ret, ipout, iplen))
-		{
-		ASN1_OCTET_STRING_free(ret);
-		return NULL;
-		}
-	return ret;
-	}
+    ret = ASN1_OCTET_STRING_new();
+    if (!ret)
+        return NULL;
+    if (!ASN1_OCTET_STRING_set(ret, ipout, iplen)) {
+        ASN1_OCTET_STRING_free(ret);
+        return NULL;
+    }
+    return ret;
+}
 
 ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc)
-	{
-	ASN1_OCTET_STRING *ret = NULL;
-	unsigned char ipout[32];
-	char *iptmp = NULL, *p;
-	int iplen1, iplen2;
-	p = strchr(ipasc,'/');
-	if (!p)
-		return NULL;
-	iptmp = BUF_strdup(ipasc);
-	if (!iptmp)
-		return NULL;
-	p = iptmp + (p - ipasc);
-	*p++ = 0;
+{
+    ASN1_OCTET_STRING *ret = NULL;
+    unsigned char ipout[32];
+    char *iptmp = NULL, *p;
+    int iplen1, iplen2;
+    p = strchr(ipasc, '/');
+    if (!p)
+        return NULL;
+    iptmp = BUF_strdup(ipasc);
+    if (!iptmp)
+        return NULL;
+    p = iptmp + (p - ipasc);
+    *p++ = 0;
 
-	iplen1 = a2i_ipadd(ipout, iptmp);
+    iplen1 = a2i_ipadd(ipout, iptmp);
 
-	if (!iplen1)
-		goto err;
+    if (!iplen1)
+        goto err;
 
-	iplen2 = a2i_ipadd(ipout + iplen1, p);
+    iplen2 = a2i_ipadd(ipout + iplen1, p);
 
-	OPENSSL_free(iptmp);
-	iptmp = NULL;
+    OPENSSL_free(iptmp);
+    iptmp = NULL;
 
-	if (!iplen2 || (iplen1 != iplen2))
-		goto err;
+    if (!iplen2 || (iplen1 != iplen2))
+        goto err;
 
-	ret = ASN1_OCTET_STRING_new();
-	if (!ret)
-		goto err;
-	if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2))
-		goto err;
+    ret = ASN1_OCTET_STRING_new();
+    if (!ret)
+        goto err;
+    if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2))
+        goto err;
 
-	return ret;
+    return ret;
 
-	err:
-	if (iptmp)
-		OPENSSL_free(iptmp);
-	if (ret)
-		ASN1_OCTET_STRING_free(ret);
-	return NULL;
-	}
-	
+ err:
+    if (iptmp)
+        OPENSSL_free(iptmp);
+    if (ret)
+        ASN1_OCTET_STRING_free(ret);
+    return NULL;
+}
 
 int a2i_ipadd(unsigned char *ipout, const char *ipasc)
-	{
-	/* If string contains a ':' assume IPv6 */
+{
+    /* If string contains a ':' assume IPv6 */
 
-	if (strchr(ipasc, ':'))
-		{
-		if (!ipv6_from_asc(ipout, ipasc))
-			return 0;
-		return 16;
-		}
-	else
-		{
-		if (!ipv4_from_asc(ipout, ipasc))
-			return 0;
-		return 4;
-		}
-	}
+    if (strchr(ipasc, ':')) {
+        if (!ipv6_from_asc(ipout, ipasc))
+            return 0;
+        return 16;
+    } else {
+        if (!ipv4_from_asc(ipout, ipasc))
+            return 0;
+        return 4;
+    }
+}
 
 static int ipv4_from_asc(unsigned char *v4, const char *in)
-	{
-	int a0, a1, a2, a3;
-	if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4)
-		return 0;
-	if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255)
-		|| (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255))
-		return 0;
-	v4[0] = a0;
-	v4[1] = a1;
-	v4[2] = a2;
-	v4[3] = a3;
-	return 1;
-	}
+{
+    int a0, a1, a2, a3;
+    if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4)
+        return 0;
+    if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255)
+        || (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255))
+        return 0;
+    v4[0] = a0;
+    v4[1] = a1;
+    v4[2] = a2;
+    v4[3] = a3;
+    return 1;
+}
 
 typedef struct {
-		/* Temporary store for IPV6 output */
-		unsigned char tmp[16];
-		/* Total number of bytes in tmp */
-		int total;
-		/* The position of a zero (corresponding to '::') */
-		int zero_pos;
-		/* Number of zeroes */
-		int zero_cnt;
-	} IPV6_STAT;
-
+    /* Temporary store for IPV6 output */
+    unsigned char tmp[16];
+    /* Total number of bytes in tmp */
+    int total;
+    /* The position of a zero (corresponding to '::') */
+    int zero_pos;
+    /* Number of zeroes */
+    int zero_cnt;
+} IPV6_STAT;
 
 static int ipv6_from_asc(unsigned char *v6, const char *in)
-	{
-	IPV6_STAT v6stat;
-	v6stat.total = 0;
-	v6stat.zero_pos = -1;
-	v6stat.zero_cnt = 0;
-	/* Treat the IPv6 representation as a list of values
-	 * separated by ':'. The presence of a '::' will parse
- 	 * as one, two or three zero length elements.
-	 */
-	if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat))
-		return 0;
+{
+    IPV6_STAT v6stat;
+    v6stat.total = 0;
+    v6stat.zero_pos = -1;
+    v6stat.zero_cnt = 0;
+    /*
+     * Treat the IPv6 representation as a list of values separated by ':'.
+     * The presence of a '::' will parse as one, two or three zero length
+     * elements.
+     */
+    if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat))
+        return 0;
 
-	/* Now for some sanity checks */
+    /* Now for some sanity checks */
 
-	if (v6stat.zero_pos == -1)
-		{
-		/* If no '::' must have exactly 16 bytes */
-		if (v6stat.total != 16)
-			return 0;
-		}
-	else 
-		{
-		/* If '::' must have less than 16 bytes */
-		if (v6stat.total == 16)
-			return 0;
-		/* More than three zeroes is an error */
-		if (v6stat.zero_cnt > 3)
-			return 0;
-		/* Can only have three zeroes if nothing else present */
-		else if (v6stat.zero_cnt == 3)
-			{
-			if (v6stat.total > 0)
-				return 0;
-			}
-		/* Can only have two zeroes if at start or end */
-		else if (v6stat.zero_cnt == 2)
-			{
-			if ((v6stat.zero_pos != 0)
-				&& (v6stat.zero_pos != v6stat.total))
-				return 0;
-			}
-		else 
-		/* Can only have one zero if *not* start or end */
-			{
-			if ((v6stat.zero_pos == 0)
-				|| (v6stat.zero_pos == v6stat.total))
-				return 0;
-			}
-		}
+    if (v6stat.zero_pos == -1) {
+        /* If no '::' must have exactly 16 bytes */
+        if (v6stat.total != 16)
+            return 0;
+    } else {
+        /* If '::' must have less than 16 bytes */
+        if (v6stat.total == 16)
+            return 0;
+        /* More than three zeroes is an error */
+        if (v6stat.zero_cnt > 3)
+            return 0;
+        /* Can only have three zeroes if nothing else present */
+        else if (v6stat.zero_cnt == 3) {
+            if (v6stat.total > 0)
+                return 0;
+        }
+        /* Can only have two zeroes if at start or end */
+        else if (v6stat.zero_cnt == 2) {
+            if ((v6stat.zero_pos != 0)
+                && (v6stat.zero_pos != v6stat.total))
+                return 0;
+        } else
+            /* Can only have one zero if *not* start or end */
+        {
+            if ((v6stat.zero_pos == 0)
+                || (v6stat.zero_pos == v6stat.total))
+                return 0;
+        }
+    }
 
-	/* Format result */
+    /* Format result */
 
-	if (v6stat.zero_pos >= 0)
-		{
-		/* Copy initial part */
-		memcpy(v6, v6stat.tmp, v6stat.zero_pos);
-		/* Zero middle */
-		memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total);
-		/* Copy final part */
-		if (v6stat.total != v6stat.zero_pos)
-			memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total,
-				v6stat.tmp + v6stat.zero_pos,
-				v6stat.total - v6stat.zero_pos);
-		}
-	else
-		memcpy(v6, v6stat.tmp, 16);
+    if (v6stat.zero_pos >= 0) {
+        /* Copy initial part */
+        OPENSSL_memcpy(v6, v6stat.tmp, v6stat.zero_pos);
+        /* Zero middle */
+        OPENSSL_memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total);
+        /* Copy final part */
+        if (v6stat.total != v6stat.zero_pos)
+            OPENSSL_memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total,
+                           v6stat.tmp + v6stat.zero_pos,
+                           v6stat.total - v6stat.zero_pos);
+    } else
+        OPENSSL_memcpy(v6, v6stat.tmp, 16);
 
-	return 1;
-	}
+    return 1;
+}
 
 static int ipv6_cb(const char *elem, int len, void *usr)
-	{
-	IPV6_STAT *s = usr;
-	/* Error if 16 bytes written */
-	if (s->total == 16)
-		return 0;
-	if (len == 0)
-		{
-		/* Zero length element, corresponds to '::' */
-		if (s->zero_pos == -1)
-			s->zero_pos = s->total;
-		/* If we've already got a :: its an error */
-		else if (s->zero_pos != s->total)
-			return 0;
-		s->zero_cnt++;
-		}
-	else 
-		{
-		/* If more than 4 characters could be final a.b.c.d form */
-		if (len > 4)
-			{
-			/* Need at least 4 bytes left */
-			if (s->total > 12)
-				return 0;
-			/* Must be end of string */
-			if (elem[len])
-				return 0;
-			if (!ipv4_from_asc(s->tmp + s->total, elem))
-				return 0;
-			s->total += 4;
-			}
-		else
-			{
-			if (!ipv6_hex(s->tmp + s->total, elem, len))
-				return 0;
-			s->total += 2;
-			}
-		}
-	return 1;
-	}
+{
+    IPV6_STAT *s = usr;
+    /* Error if 16 bytes written */
+    if (s->total == 16)
+        return 0;
+    if (len == 0) {
+        /* Zero length element, corresponds to '::' */
+        if (s->zero_pos == -1)
+            s->zero_pos = s->total;
+        /* If we've already got a :: its an error */
+        else if (s->zero_pos != s->total)
+            return 0;
+        s->zero_cnt++;
+    } else {
+        /* If more than 4 characters could be final a.b.c.d form */
+        if (len > 4) {
+            /* Need at least 4 bytes left */
+            if (s->total > 12)
+                return 0;
+            /* Must be end of string */
+            if (elem[len])
+                return 0;
+            if (!ipv4_from_asc(s->tmp + s->total, elem))
+                return 0;
+            s->total += 4;
+        } else {
+            if (!ipv6_hex(s->tmp + s->total, elem, len))
+                return 0;
+            s->total += 2;
+        }
+    }
+    return 1;
+}
 
-/* Convert a string of up to 4 hex digits into the corresponding
- * IPv6 form.
+/*
+ * Convert a string of up to 4 hex digits into the corresponding IPv6 form.
  */
 
 static int ipv6_hex(unsigned char *out, const char *in, int inlen)
-	{
-	unsigned char c;
-	unsigned int num = 0;
-	if (inlen > 4)
-		return 0;
-	while(inlen--)
-		{
-		c = *in++;
-		num <<= 4;
-		if ((c >= '0') && (c <= '9'))
-			num |= c - '0';
-		else if ((c >= 'A') && (c <= 'F'))
-			num |= c - 'A' + 10;
-		else if ((c >= 'a') && (c <= 'f'))
-			num |=  c - 'a' + 10;
-		else
-			return 0;
-		}
-	out[0] = num >> 8;
-	out[1] = num & 0xff;
-	return 1;
-	}
+{
+    unsigned char c;
+    unsigned int num = 0;
+    if (inlen > 4)
+        return 0;
+    while (inlen--) {
+        c = *in++;
+        num <<= 4;
+        if ((c >= '0') && (c <= '9'))
+            num |= c - '0';
+        else if ((c >= 'A') && (c <= 'F'))
+            num |= c - 'A' + 10;
+        else if ((c >= 'a') && (c <= 'f'))
+            num |= c - 'a' + 10;
+        else
+            return 0;
+    }
+    out[0] = num >> 8;
+    out[1] = num & 0xff;
+    return 1;
+}
 
+int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF (CONF_VALUE) * dn_sk,
+                             unsigned long chtype)
+{
+    CONF_VALUE *v;
+    int mval;
+    size_t i;
+    char *p, *type;
+    if (!nm)
+        return 0;
 
-int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE)*dn_sk,
-						unsigned long chtype)
-	{
-	CONF_VALUE *v;
-	int mval;
-	size_t i;
-	char *p, *type;
-	if (!nm)
-		return 0;
+    for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) {
+        v = sk_CONF_VALUE_value(dn_sk, i);
+        type = v->name;
+        /*
+         * Skip past any leading X. X: X, etc to allow for multiple instances
+         */
+        for (p = type; *p; p++)
+            if ((*p == ':') || (*p == ',') || (*p == '.')) {
+                p++;
+                if (*p)
+                    type = p;
+                break;
+            }
+        if (*type == '+') {
+            mval = -1;
+            type++;
+        } else
+            mval = 0;
+        if (!X509_NAME_add_entry_by_txt(nm, type, chtype,
+                                        (unsigned char *)v->value, -1, -1,
+                                        mval))
+            return 0;
 
-	for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++)
-		{
-		v=sk_CONF_VALUE_value(dn_sk,i);
-		type=v->name;
-		/* Skip past any leading X. X: X, etc to allow for
-		 * multiple instances 
-		 */
-		for(p = type; *p ; p++) 
-			if ((*p == ':') || (*p == ',') || (*p == '.'))
-				{
-				p++;
-				if(*p) type = p;
-				break;
-				}
-		if (*type == '+')
-			{
-			mval = -1;
-			type++;
-			}
-		else
-			mval = 0;
-		if (!X509_NAME_add_entry_by_txt(nm,type, chtype,
-				(unsigned char *) v->value,-1,-1,mval))
-					return 0;
-
-		}
-	return 1;
-	}
+    }
+    return 1;
+}
diff --git a/src/crypto/x509v3/v3name_test.c b/src/crypto/x509v3/v3name_test.c
index f9f7087..959b924 100644
--- a/src/crypto/x509v3/v3name_test.c
+++ b/src/crypto/x509v3/v3name_test.c
@@ -1,5 +1,7 @@
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999. */
+/*
+ * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
+ * 1999.
+ */
 /* ====================================================================
  * Copyright (c) 1999-2004 The OpenSSL Project.  All rights reserved.
  *
@@ -8,7 +10,7 @@
  * are met:
  *
  * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
+ *    notice, this list of conditions and the following disclaimer.
  *
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in
@@ -60,363 +62,352 @@
 #include <openssl/x509.h>
 #include <openssl/x509v3.h>
 
+#include "../internal.h"
 
-static const char *const names[] =
-	{
-	"a", "b", ".", "*", "@",
-	".a", "a.", ".b", "b.", ".*", "*.", "*@", "@*", "a@", "@a", "b@", "..",
-	"@@", "**", "*.com", "*com", "*.*.com", "*com", "com*", "*example.com",
-	"*@example.com", "test@*.example.com", "example.com", "www.example.com",
-	"test.www.example.com", "*.example.com", "*.www.example.com",
-	"test.*.example.com", "www.*.com",
-	".www.example.com", "*www.example.com",
-	"example.net", "xn--rger-koa.example.com",
-	"a.example.com", "b.example.com",
-	"postmaster@example.com", "Postmaster@example.com",
-	"postmaster@EXAMPLE.COM",
-	NULL
-	};
 
-static const char *const exceptions[] =
-	{
-	"set CN: host: [*.example.com] matches [a.example.com]",
-	"set CN: host: [*.example.com] matches [b.example.com]",
-	"set CN: host: [*.example.com] matches [www.example.com]",
-	"set CN: host: [*.example.com] matches [xn--rger-koa.example.com]",
-	"set CN: host: [*.www.example.com] matches [test.www.example.com]",
-	"set CN: host: [*.www.example.com] matches [.www.example.com]",
-	"set CN: host: [*www.example.com] matches [www.example.com]",
-	"set CN: host: [test.www.example.com] matches [.www.example.com]",
-	"set CN: host-no-wildcards: [*.www.example.com] matches [.www.example.com]",
-	"set CN: host-no-wildcards: [test.www.example.com] matches [.www.example.com]",
-	"set emailAddress: email: [postmaster@example.com] does not match [Postmaster@example.com]",
-	"set emailAddress: email: [postmaster@EXAMPLE.COM] does not match [Postmaster@example.com]",
-	"set emailAddress: email: [Postmaster@example.com] does not match [postmaster@example.com]",
-	"set emailAddress: email: [Postmaster@example.com] does not match [postmaster@EXAMPLE.COM]",
-	"set dnsName: host: [*.example.com] matches [www.example.com]",
-	"set dnsName: host: [*.example.com] matches [a.example.com]",
-	"set dnsName: host: [*.example.com] matches [b.example.com]",
-	"set dnsName: host: [*.example.com] matches [xn--rger-koa.example.com]",
-	"set dnsName: host: [*.www.example.com] matches [test.www.example.com]",
-	"set dnsName: host-no-wildcards: [*.www.example.com] matches [.www.example.com]",
-	"set dnsName: host-no-wildcards: [test.www.example.com] matches [.www.example.com]",
-	"set dnsName: host: [*.www.example.com] matches [.www.example.com]",
-	"set dnsName: host: [*www.example.com] matches [www.example.com]",
-	"set dnsName: host: [test.www.example.com] matches [.www.example.com]",
-	"set rfc822Name: email: [postmaster@example.com] does not match [Postmaster@example.com]",
-	"set rfc822Name: email: [Postmaster@example.com] does not match [postmaster@example.com]",
-	"set rfc822Name: email: [Postmaster@example.com] does not match [postmaster@EXAMPLE.COM]",
-	"set rfc822Name: email: [postmaster@EXAMPLE.COM] does not match [Postmaster@example.com]",
-	NULL
-	};
+static const char *const names[] = {
+    "a", "b", ".", "*", "@",
+    ".a", "a.", ".b", "b.", ".*", "*.", "*@", "@*", "a@", "@a", "b@", "..",
+    "-example.com", "example-.com",
+    "@@", "**", "*.com", "*com", "*.*.com", "*com", "com*", "*example.com",
+    "*@example.com", "test@*.example.com", "example.com", "www.example.com",
+    "test.www.example.com", "*.example.com", "*.www.example.com",
+    "test.*.example.com", "www.*.com",
+    ".www.example.com", "*www.example.com",
+    "example.net", "xn--rger-koa.example.com",
+    "*.xn--rger-koa.example.com", "www.xn--rger-koa.example.com",
+    "*.good--example.com", "www.good--example.com",
+    "*.xn--bar.com", "xn--foo.xn--bar.com",
+    "a.example.com", "b.example.com",
+    "postmaster@example.com", "Postmaster@example.com",
+    "postmaster@EXAMPLE.COM",
+    NULL
+};
+
+static const char *const exceptions[] = {
+    "set CN: host: [*.example.com] matches [a.example.com]",
+    "set CN: host: [*.example.com] matches [b.example.com]",
+    "set CN: host: [*.example.com] matches [www.example.com]",
+    "set CN: host: [*.example.com] matches [xn--rger-koa.example.com]",
+    "set CN: host: [*.www.example.com] matches [test.www.example.com]",
+    "set CN: host: [*.www.example.com] matches [.www.example.com]",
+    "set CN: host: [*www.example.com] matches [www.example.com]",
+    "set CN: host: [test.www.example.com] matches [.www.example.com]",
+    "set CN: host: [*.xn--rger-koa.example.com] matches [www.xn--rger-koa.example.com]",
+    "set CN: host: [*.xn--bar.com] matches [xn--foo.xn--bar.com]",
+    "set CN: host: [*.good--example.com] matches [www.good--example.com]",
+    "set CN: host-no-wildcards: [*.www.example.com] matches [.www.example.com]",
+    "set CN: host-no-wildcards: [test.www.example.com] matches [.www.example.com]",
+    "set emailAddress: email: [postmaster@example.com] does not match [Postmaster@example.com]",
+    "set emailAddress: email: [postmaster@EXAMPLE.COM] does not match [Postmaster@example.com]",
+    "set emailAddress: email: [Postmaster@example.com] does not match [postmaster@example.com]",
+    "set emailAddress: email: [Postmaster@example.com] does not match [postmaster@EXAMPLE.COM]",
+    "set dnsName: host: [*.example.com] matches [www.example.com]",
+    "set dnsName: host: [*.example.com] matches [a.example.com]",
+    "set dnsName: host: [*.example.com] matches [b.example.com]",
+    "set dnsName: host: [*.example.com] matches [xn--rger-koa.example.com]",
+    "set dnsName: host: [*.www.example.com] matches [test.www.example.com]",
+    "set dnsName: host-no-wildcards: [*.www.example.com] matches [.www.example.com]",
+    "set dnsName: host-no-wildcards: [test.www.example.com] matches [.www.example.com]",
+    "set dnsName: host: [*.www.example.com] matches [.www.example.com]",
+    "set dnsName: host: [*www.example.com] matches [www.example.com]",
+    "set dnsName: host: [test.www.example.com] matches [.www.example.com]",
+    "set dnsName: host: [*.xn--rger-koa.example.com] matches [www.xn--rger-koa.example.com]",
+    "set dnsName: host: [*.xn--bar.com] matches [xn--foo.xn--bar.com]",
+    "set dnsName: host: [*.good--example.com] matches [www.good--example.com]",
+    "set rfc822Name: email: [postmaster@example.com] does not match [Postmaster@example.com]",
+    "set rfc822Name: email: [Postmaster@example.com] does not match [postmaster@example.com]",
+    "set rfc822Name: email: [Postmaster@example.com] does not match [postmaster@EXAMPLE.COM]",
+    "set rfc822Name: email: [postmaster@EXAMPLE.COM] does not match [Postmaster@example.com]",
+    NULL
+};
 
 static int is_exception(const char *msg)
-	{
-	const char *const *p;
-	for (p = exceptions; *p; ++p)
-		if (strcmp(msg, *p) == 0)
-			return 1;
-	return 0;
-	}
+{
+    const char *const *p;
+    for (p = exceptions; *p; ++p)
+        if (strcmp(msg, *p) == 0)
+            return 1;
+    return 0;
+}
 
 static int set_cn(X509 *crt, ...)
-	{
-	int ret = 0;
-	X509_NAME *n = NULL;
-	va_list ap;
-	va_start(ap, crt);
-	n = X509_NAME_new();
-	if (n == NULL)
-		goto out;
-	while (1) {
-		int nid;
-		const char *name;
-		nid = va_arg(ap, int);
-		if (nid == 0)
-			break;
-		name = va_arg(ap, const char *);
-		if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_ASC,
-							(unsigned char *)name,
-						-1, -1, 1))
-			goto out;
-	}
-	if (!X509_set_subject_name(crt, n))
-		goto out;
-	ret = 1;
+{
+    int ret = 0;
+    X509_NAME *n = NULL;
+    va_list ap;
+    va_start(ap, crt);
+    n = X509_NAME_new();
+    if (n == NULL)
+        goto out;
+    while (1) {
+        int nid;
+        const char *name;
+        nid = va_arg(ap, int);
+        if (nid == 0)
+            break;
+        name = va_arg(ap, const char *);
+        if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_ASC,
+                                        (unsigned char *)name, -1, -1, 1))
+            goto out;
+    }
+    if (!X509_set_subject_name(crt, n))
+        goto out;
+    ret = 1;
  out:
-	X509_NAME_free(n);
-	va_end(ap);
-	return ret;
-	}
+    X509_NAME_free(n);
+    va_end(ap);
+    return ret;
+}
 
 /*
-int		X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc);
-X509_EXTENSION *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex,
-			int nid, int crit, ASN1_OCTET_STRING *data);
-int		X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc);
-*/
+ * int X509_add_ext(X509 *x, X509_EXTENSION *ex, int loc); X509_EXTENSION
+ * *X509_EXTENSION_create_by_NID(X509_EXTENSION **ex, int nid, int crit,
+ * ASN1_OCTET_STRING *data); int X509_add_ext(X509 *x, X509_EXTENSION *ex,
+ * int loc);
+ */
 
 static int set_altname(X509 *crt, ...)
-	{
-	int ret = 0;
-	GENERAL_NAMES *gens = NULL;
-	GENERAL_NAME *gen = NULL;
-	ASN1_IA5STRING *ia5 = NULL;
-	va_list ap;
-	va_start(ap, crt);
-	gens = sk_GENERAL_NAME_new_null();
-	if (gens == NULL)
-		goto out;
-	while (1) {
-		int type;
-		const char *name;
-		type = va_arg(ap, int);
-		if (type == 0)
-			break;
-		name = va_arg(ap, const char *);
+{
+    int ret = 0;
+    GENERAL_NAMES *gens = NULL;
+    GENERAL_NAME *gen = NULL;
+    ASN1_IA5STRING *ia5 = NULL;
+    va_list ap;
+    va_start(ap, crt);
+    gens = sk_GENERAL_NAME_new_null();
+    if (gens == NULL)
+        goto out;
+    while (1) {
+        int type;
+        const char *name;
+        type = va_arg(ap, int);
+        if (type == 0)
+            break;
+        name = va_arg(ap, const char *);
 
-		gen = GENERAL_NAME_new();
-		if (gen == NULL)
-			goto out;
-		ia5 = ASN1_IA5STRING_new();
-		if (ia5 == NULL)
-			goto out;
-		if (!ASN1_STRING_set(ia5, name, -1))
-			goto out;
-		switch (type)
-			{
-			case GEN_EMAIL:
-			case GEN_DNS:
-				GENERAL_NAME_set0_value(gen, type, ia5);
-				ia5 = NULL;
-				break;
-			default:
-				abort();
-			}
-		sk_GENERAL_NAME_push(gens, gen);
-		gen = NULL;
-	}
-	if (!X509_add1_ext_i2d(crt, NID_subject_alt_name, gens, 0, 0))
-		goto out;
-	ret = 1;
+        gen = GENERAL_NAME_new();
+        if (gen == NULL)
+            goto out;
+        ia5 = ASN1_IA5STRING_new();
+        if (ia5 == NULL)
+            goto out;
+        if (!ASN1_STRING_set(ia5, name, -1))
+            goto out;
+        switch (type) {
+        case GEN_EMAIL:
+        case GEN_DNS:
+            GENERAL_NAME_set0_value(gen, type, ia5);
+            ia5 = NULL;
+            break;
+        default:
+            abort();
+        }
+        sk_GENERAL_NAME_push(gens, gen);
+        gen = NULL;
+    }
+    if (!X509_add1_ext_i2d(crt, NID_subject_alt_name, gens, 0, 0))
+        goto out;
+    ret = 1;
  out:
-	ASN1_IA5STRING_free(ia5);
-	GENERAL_NAME_free(gen);
-	GENERAL_NAMES_free(gens);
-	va_end(ap);
-	return ret;
-	}
+    ASN1_IA5STRING_free(ia5);
+    GENERAL_NAME_free(gen);
+    GENERAL_NAMES_free(gens);
+    va_end(ap);
+    return ret;
+}
 
 static int set_cn1(X509 *crt, const char *name)
-	{
-	return set_cn(crt, NID_commonName, name, 0);
-	}
-
+{
+    return set_cn(crt, NID_commonName, name, 0);
+}
 
 static int set_cn_and_email(X509 *crt, const char *name)
-	{
-	return set_cn(crt, NID_commonName, name,
-		      NID_pkcs9_emailAddress, "dummy@example.com", 0);
-	}
+{
+    return set_cn(crt, NID_commonName, name,
+                  NID_pkcs9_emailAddress, "dummy@example.com", 0);
+}
 
 static int set_cn2(X509 *crt, const char *name)
-	{
-	return set_cn(crt, NID_commonName, "dummy value",
-		      NID_commonName, name, 0);
-	}
+{
+    return set_cn(crt, NID_commonName, "dummy value",
+                  NID_commonName, name, 0);
+}
 
 static int set_cn3(X509 *crt, const char *name)
-	{
-	return set_cn(crt, NID_commonName, name,
-		      NID_commonName, "dummy value", 0);
-	}
+{
+    return set_cn(crt, NID_commonName, name,
+                  NID_commonName, "dummy value", 0);
+}
 
 static int set_email1(X509 *crt, const char *name)
-	{
-	return set_cn(crt, NID_pkcs9_emailAddress, name, 0);
-	}
+{
+    return set_cn(crt, NID_pkcs9_emailAddress, name, 0);
+}
 
 static int set_email2(X509 *crt, const char *name)
-	{
-	return set_cn(crt, NID_pkcs9_emailAddress, "dummy@example.com",
-		      NID_pkcs9_emailAddress, name, 0);
-	}
+{
+    return set_cn(crt, NID_pkcs9_emailAddress, "dummy@example.com",
+                  NID_pkcs9_emailAddress, name, 0);
+}
 
 static int set_email3(X509 *crt, const char *name)
-	{
-	return set_cn(crt, NID_pkcs9_emailAddress, name,
-		      NID_pkcs9_emailAddress, "dummy@example.com", 0);
-	}
+{
+    return set_cn(crt, NID_pkcs9_emailAddress, name,
+                  NID_pkcs9_emailAddress, "dummy@example.com", 0);
+}
 
 static int set_email_and_cn(X509 *crt, const char *name)
-	{
-	return set_cn(crt, NID_pkcs9_emailAddress, name,
-		      NID_commonName, "www.example.org", 0);
-	}
+{
+    return set_cn(crt, NID_pkcs9_emailAddress, name,
+                  NID_commonName, "www.example.org", 0);
+}
 
 static int set_altname_dns(X509 *crt, const char *name)
-	{
-	return set_altname(crt, GEN_DNS, name, 0);
-	}
+{
+    return set_altname(crt, GEN_DNS, name, 0);
+}
 
 static int set_altname_email(X509 *crt, const char *name)
-	{
-	return set_altname(crt, GEN_EMAIL, name, 0);
-	}
+{
+    return set_altname(crt, GEN_EMAIL, name, 0);
+}
 
-struct set_name_fn
-	{
-	int (*fn)(X509 *, const char *);
-	const char *name;
-	int host;
-	int email;
-	};
+struct set_name_fn {
+    int (*fn) (X509 *, const char *);
+    const char *name;
+    int host;
+    int email;
+};
 
-static const struct set_name_fn name_fns[] =
-	{
-	{set_cn1, "set CN", 1, 0},
-	{set_cn2, "set CN", 1, 0},
-	{set_cn3, "set CN", 1, 0},
-	{set_cn_and_email, "set CN", 1, 0},
-	{set_email1, "set emailAddress", 0, 1},
-	{set_email2, "set emailAddress", 0, 1},
-	{set_email3, "set emailAddress", 0, 1},
-	{set_email_and_cn, "set emailAddress", 0, 1},
-	{set_altname_dns, "set dnsName", 1, 0},
-	{set_altname_email, "set rfc822Name", 0, 1},
-	{NULL, NULL, 0, 0},
-	};
+static const struct set_name_fn name_fns[] = {
+    {set_cn1, "set CN", 1, 0},
+    {set_cn2, "set CN", 1, 0},
+    {set_cn3, "set CN", 1, 0},
+    {set_cn_and_email, "set CN", 1, 0},
+    {set_email1, "set emailAddress", 0, 1},
+    {set_email2, "set emailAddress", 0, 1},
+    {set_email3, "set emailAddress", 0, 1},
+    {set_email_and_cn, "set emailAddress", 0, 1},
+    {set_altname_dns, "set dnsName", 1, 0},
+    {set_altname_email, "set rfc822Name", 0, 1},
+    {NULL, NULL, 0, 0},
+};
 
 static X509 *make_cert(void)
-	{
-	X509 *ret = NULL;
-	X509 *crt = NULL;
-	X509_NAME *issuer = NULL;
-	crt = X509_new();
-	if (crt == NULL)
-		goto out;
-	if (!X509_set_version(crt, 3))
-		goto out;
-	ret = crt;
-	crt = NULL;
+{
+    X509 *ret = NULL;
+    X509 *crt = NULL;
+    X509_NAME *issuer = NULL;
+    crt = X509_new();
+    if (crt == NULL)
+        goto out;
+    if (!X509_set_version(crt, 3))
+        goto out;
+    ret = crt;
+    crt = NULL;
  out:
-	X509_NAME_free(issuer);
-	return ret;
-	}
+    X509_NAME_free(issuer);
+    return ret;
+}
 
 static int errors;
 
 static void check_message(const struct set_name_fn *fn, const char *op,
-			  const char *nameincert, int match, const char *name)
-	{
-	char msg[1024];
-	if (match < 0)
-		return;
-	BIO_snprintf(msg, sizeof(msg), "%s: %s: [%s] %s [%s]",
-		 fn->name, op, nameincert,
-		 match ? "matches" : "does not match", name);
-	if (is_exception(msg))
-		return;
-	puts(msg);
-	++errors;
-	}
+                          const char *nameincert, int match, const char *name)
+{
+    char msg[1024];
+    if (match < 0)
+        return;
+    BIO_snprintf(msg, sizeof(msg), "%s: %s: [%s] %s [%s]",
+                 fn->name, op, nameincert,
+                 match ? "matches" : "does not match", name);
+    if (is_exception(msg))
+        return;
+    puts(msg);
+    ++errors;
+}
 
 static void run_cert(X509 *crt, const char *nameincert,
-		     const struct set_name_fn *fn)
-	{
-	const char *const *pname = names;
-	while (*pname)
-		{
-		int samename = OPENSSL_strcasecmp(nameincert, *pname) == 0;
-		size_t namelen = strlen(*pname);
-		char *name = malloc(namelen);
-		int match, ret;
-		memcpy(name, *pname, namelen);
+                     const struct set_name_fn *fn)
+{
+    const char *const *pname = names;
+    while (*pname) {
+        int samename = OPENSSL_strcasecmp(nameincert, *pname) == 0;
+        size_t namelen = strlen(*pname);
+        char *name = malloc(namelen);
+        int match, ret;
+        OPENSSL_memcpy(name, *pname, namelen);
 
-		ret = X509_check_host(crt, name, namelen, 0, NULL);
-		match = -1;
-		if (ret < 0)
-			{
-			fprintf(stderr, "internal error in X509_check_host");
-			++errors;
-			}
-		else if (fn->host)
-			{
-			if (ret == 1 && !samename)
-				match = 1;
-			if (ret == 0 && samename)
-				match = 0;
-			}
-		else if (ret == 1)
-			match = 1;
-		check_message(fn, "host", nameincert, match, *pname);
+        ret = X509_check_host(crt, name, namelen, 0, NULL);
+        match = -1;
+        if (ret < 0) {
+            fprintf(stderr, "internal error in X509_check_host");
+            ++errors;
+        } else if (fn->host) {
+            if (ret == 1 && !samename)
+                match = 1;
+            if (ret == 0 && samename)
+                match = 0;
+        } else if (ret == 1)
+            match = 1;
+        check_message(fn, "host", nameincert, match, *pname);
 
-		ret = X509_check_host(crt, name, namelen,
-				      X509_CHECK_FLAG_NO_WILDCARDS, NULL);
-		match = -1;
-		if (ret < 0)
-			{
-			fprintf(stderr, "internal error in X509_check_host");
-			++errors;
-			}
-		else if (fn->host)
-			{
-			if (ret == 1 && !samename)
-				match = 1;
-			if (ret == 0 && samename)
-				match = 0;
-			}
-		else if (ret == 1)
-			match = 1;
-		check_message(fn, "host-no-wildcards",
-			      nameincert, match, *pname);
+        ret = X509_check_host(crt, name, namelen,
+                              X509_CHECK_FLAG_NO_WILDCARDS, NULL);
+        match = -1;
+        if (ret < 0) {
+            fprintf(stderr, "internal error in X509_check_host");
+            ++errors;
+        } else if (fn->host) {
+            if (ret == 1 && !samename)
+                match = 1;
+            if (ret == 0 && samename)
+                match = 0;
+        } else if (ret == 1)
+            match = 1;
+        check_message(fn, "host-no-wildcards", nameincert, match, *pname);
 
-		ret = X509_check_email(crt, name, namelen, 0);
-		match = -1;
-		if (fn->email)
-			{
-			if (ret && !samename)
-				match = 1;
-			if (!ret && samename && strchr(nameincert, '@') != NULL)
-				match = 0;
-			}
-		else if (ret)
-			match = 1;
-		check_message(fn, "email", nameincert, match, *pname);
-		++pname;
-		free(name);
-		}
-	}
+        ret = X509_check_email(crt, name, namelen, 0);
+        match = -1;
+        if (fn->email) {
+            if (ret && !samename)
+                match = 1;
+            if (!ret && samename && strchr(nameincert, '@') != NULL)
+                match = 0;
+        } else if (ret)
+            match = 1;
+        check_message(fn, "email", nameincert, match, *pname);
+        ++pname;
+        free(name);
+    }
+}
 
-int
-main(void)
-	{
-	CRYPTO_library_init();
+int main(void)
+{
+    CRYPTO_library_init();
 
-	const struct set_name_fn *pfn = name_fns;
-	while (pfn->name) {
-		const char *const *pname = names;
-		while (*pname)
-			{
-			X509 *crt = make_cert();
-			if (crt == NULL)
-				{
-				fprintf(stderr, "make_cert failed\n");
-				return 1;
-				}
-			if (!pfn->fn(crt, *pname))
-				{
-				fprintf(stderr, "X509 name setting failed\n");
-				return 1;
-				}
-			run_cert(crt, *pname, pfn);
-			X509_free(crt);
-			++pname;
-			}
-		++pfn;
-	}
-	if (errors == 0) {
-	  printf("PASS\n");
-	}
-	return errors > 0 ? 1 : 0;
-	}
+    const struct set_name_fn *pfn = name_fns;
+    while (pfn->name) {
+        const char *const *pname = names;
+        while (*pname) {
+            X509 *crt = make_cert();
+            if (crt == NULL) {
+                fprintf(stderr, "make_cert failed\n");
+                return 1;
+            }
+            if (!pfn->fn(crt, *pname)) {
+                fprintf(stderr, "X509 name setting failed\n");
+                return 1;
+            }
+            run_cert(crt, *pname, pfn);
+            X509_free(crt);
+            ++pname;
+        }
+        ++pfn;
+    }
+    if (errors == 0) {
+        printf("PASS\n");
+    }
+    return errors > 0 ? 1 : 0;
+}
diff --git a/src/decrepit/CMakeLists.txt b/src/decrepit/CMakeLists.txt
index 0773f9a..a3e409b 100644
--- a/src/decrepit/CMakeLists.txt
+++ b/src/decrepit/CMakeLists.txt
@@ -1,8 +1,18 @@
+include_directories(../include)
+
 add_subdirectory(bio)
 add_subdirectory(blowfish)
 add_subdirectory(cast)
 add_subdirectory(des)
+add_subdirectory(dh)
+add_subdirectory(dsa)
+add_subdirectory(evp)
+add_subdirectory(obj)
+add_subdirectory(rc4)
+add_subdirectory(ripemd)
 add_subdirectory(rsa)
+add_subdirectory(ssl)
+add_subdirectory(x509)
 add_subdirectory(xts)
 
 add_library(
@@ -12,8 +22,31 @@
   $<TARGET_OBJECTS:blowfish>
   $<TARGET_OBJECTS:cast>
   $<TARGET_OBJECTS:des_decrepit>
+  $<TARGET_OBJECTS:dh_decrepit>
+  $<TARGET_OBJECTS:dsa_decrepit>
+  $<TARGET_OBJECTS:evp_decrepit>
+  $<TARGET_OBJECTS:obj_decrepit>
+  $<TARGET_OBJECTS:rc4_decrepit>
+  $<TARGET_OBJECTS:ripemd_decrepit>
   $<TARGET_OBJECTS:rsa_decrepit>
+  $<TARGET_OBJECTS:ssl_decrepit>
+  $<TARGET_OBJECTS:x509_decrepit>
   $<TARGET_OBJECTS:xts>
 )
 
-target_link_libraries(decrepit crypto)
+target_link_libraries(decrepit crypto ssl)
+
+add_executable(
+  decrepit_test
+
+  ripemd/ripemd_test.cc
+
+  $<TARGET_OBJECTS:gtest_main>
+  $<TARGET_OBJECTS:test_support>
+)
+
+target_link_libraries(decrepit_test crypto decrepit gtest)
+if (WIN32)
+  target_link_libraries(decrepit_test ws2_32)
+endif()
+add_dependencies(all_tests decrepit_test)
diff --git a/src/decrepit/bio/base64_bio.c b/src/decrepit/bio/base64_bio.c
index 2056138..eef4e1a 100644
--- a/src/decrepit/bio/base64_bio.c
+++ b/src/decrepit/bio/base64_bio.c
@@ -65,6 +65,8 @@
 #include <openssl/evp.h>
 #include <openssl/mem.h>
 
+#include "../../crypto/internal.h"
+
 
 #define B64_BLOCK_SIZE 1024
 #define B64_BLOCK_SIZE2 768
@@ -94,7 +96,7 @@
     return 0;
   }
 
-  memset(ctx, 0, sizeof(*ctx));
+  OPENSSL_memset(ctx, 0, sizeof(*ctx));
 
   ctx->cont = 1;
   ctx->start = 1;
@@ -147,7 +149,7 @@
       i = outl;
     }
     assert(ctx->buf_off + i < (int)sizeof(ctx->buf));
-    memcpy(out, &ctx->buf[ctx->buf_off], i);
+    OPENSSL_memcpy(out, &ctx->buf[ctx->buf_off], i);
     ret = i;
     out += i;
     outl -= i;
@@ -274,7 +276,7 @@
       }
       /* z is now number of output bytes and jj is the number consumed. */
       if (jj != i) {
-        memmove(ctx->tmp, &ctx->tmp[jj], i - jj);
+        OPENSSL_memmove(ctx->tmp, &ctx->tmp[jj], i - jj);
         ctx->tmp_len = i - jj;
       }
       ctx->buf_len = 0;
@@ -300,7 +302,7 @@
       i = outl;
     }
 
-    memcpy(out, ctx->buf, i);
+    OPENSSL_memcpy(out, ctx->buf, i);
     ret += i;
     ctx->buf_off = i;
     if (ctx->buf_off == ctx->buf_len) {
@@ -367,7 +369,7 @@
         if (n > inl) {
           n = inl;
         }
-        memcpy(&(ctx->tmp[ctx->tmp_len]), in, n);
+        OPENSSL_memcpy(&(ctx->tmp[ctx->tmp_len]), in, n);
         ctx->tmp_len += n;
         ret += n;
         if (ctx->tmp_len < 3) {
@@ -383,7 +385,7 @@
         ctx->tmp_len = 0;
       } else {
         if (n < 3) {
-          memcpy(ctx->tmp, in, n);
+          OPENSSL_memcpy(ctx->tmp, in, n);
           ctx->tmp_len = n;
           ret += n;
           break;
@@ -452,7 +454,7 @@
     case BIO_CTRL_WPENDING: /* More to write in buffer */
       assert(ctx->buf_len >= ctx->buf_off);
       ret = ctx->buf_len - ctx->buf_off;
-      if ((ret == 0) && (ctx->encode != B64_NONE) && (ctx->base64.num != 0)) {
+      if ((ret == 0) && (ctx->encode != B64_NONE) && (ctx->base64.data_used != 0)) {
         ret = 1;
       } else if (ret <= 0) {
         ret = BIO_ctrl(b->next_bio, cmd, num, ptr);
@@ -484,7 +486,7 @@
           ctx->tmp_len = 0;
           goto again;
         }
-      } else if (ctx->encode != B64_NONE && ctx->base64.num != 0) {
+      } else if (ctx->encode != B64_NONE && ctx->base64.data_used != 0) {
         ctx->buf_off = 0;
         EVP_EncodeFinal(&(ctx->base64), (uint8_t *)ctx->buf, &(ctx->buf_len));
         /* push out the bytes */
@@ -524,12 +526,8 @@
   return ret;
 }
 
-static int b64_puts(BIO *b, const char *str) {
-  return b64_write(b, str, strlen(str));
-}
-
 static const BIO_METHOD b64_method = {
-    BIO_TYPE_BASE64, "base64 encoding", b64_write, b64_read, b64_puts,
+    BIO_TYPE_BASE64, "base64 encoding", b64_write, b64_read, NULL /* puts */,
     NULL /* gets */, b64_ctrl,          b64_new,   b64_free, b64_callback_ctrl,
 };
 
diff --git a/src/decrepit/blowfish/blowfish.c b/src/decrepit/blowfish/blowfish.c
index e277f34..04b7368 100644
--- a/src/decrepit/blowfish/blowfish.c
+++ b/src/decrepit/blowfish/blowfish.c
@@ -58,6 +58,7 @@
 
 #include <string.h>
 
+#include "../../crypto/internal.h"
 #include "../macros.h"
 
 
@@ -441,7 +442,7 @@
   uint32_t *p, ri, in[2];
   const uint8_t *d, *end;
 
-  memcpy(key, &bf_init, sizeof(BF_KEY));
+  OPENSSL_memcpy(key, &bf_init, sizeof(BF_KEY));
   p = key->P;
 
   if (len > ((BF_ROUNDS + 2) * 4))
diff --git a/src/decrepit/cast/cast.c b/src/decrepit/cast/cast.c
index 94b0710..75ea656 100644
--- a/src/decrepit/cast/cast.c
+++ b/src/decrepit/cast/cast.c
@@ -57,9 +57,9 @@
 #include <openssl/cast.h>
 
 #if defined(OPENSSL_WINDOWS)
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <intrin.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
 #endif
 
 #include "internal.h"
diff --git a/src/decrepit/des/cfb64ede.c b/src/decrepit/des/cfb64ede.c
index f7e81d4..3099127 100644
--- a/src/decrepit/des/cfb64ede.c
+++ b/src/decrepit/des/cfb64ede.c
@@ -58,7 +58,8 @@
 
 #include <openssl/des.h>
 
-#include "../crypto/des/internal.h"
+#include "../../crypto/des/internal.h"
+#include "../../crypto/internal.h"
 
 
 /* The input and output encrypted as though 64bit cfb mode is being used. The
@@ -174,7 +175,7 @@
         l2c(d0, iv);
         l2c(d1, iv);
         /* shift ovec left most of the bits... */
-        memmove(ovec, ovec + num / 8, 8 + (num % 8 ? 1 : 0));
+        OPENSSL_memmove(ovec, ovec + num / 8, 8 + (num % 8 ? 1 : 0));
         /* now the remaining bits */
         if (num % 8 != 0) {
           for (i = 0; i < 8; ++i) {
@@ -210,7 +211,7 @@
         l2c(d0, iv);
         l2c(d1, iv);
         /* shift ovec left most of the bits... */
-        memmove(ovec, ovec + num / 8, 8 + (num % 8 ? 1 : 0));
+        OPENSSL_memmove(ovec, ovec + num / 8, 8 + (num % 8 ? 1 : 0));
         /* now the remaining bits */
         if (num % 8 != 0) {
           for (i = 0; i < 8; ++i) {
diff --git a/src/decrepit/dh/CMakeLists.txt b/src/decrepit/dh/CMakeLists.txt
new file mode 100644
index 0000000..fb862b5
--- /dev/null
+++ b/src/decrepit/dh/CMakeLists.txt
@@ -0,0 +1,9 @@
+include_directories(../../include)
+
+add_library(
+  dh_decrepit
+
+  OBJECT
+
+  dh_decrepit.c
+)
diff --git a/src/include/openssl/time_support.h b/src/decrepit/dh/dh_decrepit.c
similarity index 64%
rename from src/include/openssl/time_support.h
rename to src/decrepit/dh/dh_decrepit.c
index cec430d..1d38c12 100644
--- a/src/include/openssl/time_support.h
+++ b/src/decrepit/dh/dh_decrepit.c
@@ -1,10 +1,5 @@
-/* Written by Richard Levitte (richard@levitte.org) for the OpenSSL
- * project 2001.
- * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 2008.
- */
 /* ====================================================================
- * Copyright (c) 2001 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -21,12 +16,12 @@
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
- *    licensing@OpenSSL.org.
+ *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
@@ -35,7 +30,7 @@
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -55,36 +50,54 @@
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com). */
 
-#ifndef OPENSSL_HEADER_TIME_SUPPORT_H
-#define OPENSSL_HEADER_TIME_SUPPORT_H
-
-#include <openssl/base.h>
+#include <openssl/bn.h>
+#include <openssl/dh.h>
 
 
-#if defined(__cplusplus)
-extern "C" {
-#endif
+struct wrapped_callback {
+  void (*callback)(int, int, void *);
+  void *arg;
+};
 
+/* callback_wrapper converts an “old” style generation callback to the newer
+ * |BN_GENCB| form. */
+static int callback_wrapper(int event, int n, BN_GENCB *gencb) {
+  struct wrapped_callback *wrapped = (struct wrapped_callback *) gencb->arg;
+  wrapped->callback(event, n, wrapped->arg);
+  return 1;
+}
 
-/* Wrapper functions for time functions. */
+DH *DH_generate_parameters(int prime_len, int generator,
+                           void (*callback)(int, int, void *), void *cb_arg) {
+  if (prime_len < 0 || generator < 0) {
+      return NULL;
+  }
 
+  DH *ret = DH_new();
+  if (ret == NULL) {
+      return NULL;
+  }
 
-/* OPENSSL_gmtime wraps |gmtime_r|. See the manual page for that function. */
-struct tm *OPENSSL_gmtime(const time_t *timer, struct tm *result);
+  BN_GENCB gencb_storage;
+  BN_GENCB *cb = NULL;
 
-/* OPENSSL_gmtime_adj updates |tm| by adding |offset_day| days and |offset_sec|
- * seconds. */
-int OPENSSL_gmtime_adj(struct tm *tm, int offset_day, long offset_sec);
+  struct wrapped_callback wrapped;
 
-/* OPENSSL_gmtime_diff calculates the difference between |from| and |to| and
- * outputs the difference as a number of days and seconds in |*out_days| and
- * |*out_secs|. */
-int OPENSSL_gmtime_diff(int *out_days, int *out_secs, const struct tm *from,
-                        const struct tm *to);
+  if (callback != NULL) {
+    wrapped.callback = callback;
+    wrapped.arg = cb_arg;
 
+    cb = &gencb_storage;
+    BN_GENCB_set(cb, callback_wrapper, &wrapped);
+  }
 
-#if defined(__cplusplus)
-}  /* extern C */
-#endif
+  if (!DH_generate_parameters_ex(ret, prime_len, generator, cb)) {
+    goto err;
+  }
 
-#endif  /* OPENSSL_HEADER_TIME_SUPPORT_H */
+  return ret;
+
+err:
+  DH_free(ret);
+  return NULL;
+}
diff --git a/src/decrepit/dsa/CMakeLists.txt b/src/decrepit/dsa/CMakeLists.txt
new file mode 100644
index 0000000..cc64b60
--- /dev/null
+++ b/src/decrepit/dsa/CMakeLists.txt
@@ -0,0 +1,9 @@
+include_directories(../../include)
+
+add_library(
+  dsa_decrepit
+
+  OBJECT
+
+  dsa_decrepit.c
+)
diff --git a/src/crypto/pkcs8/p8_pkey.c b/src/decrepit/dsa/dsa_decrepit.c
similarity index 62%
rename from src/crypto/pkcs8/p8_pkey.c
rename to src/decrepit/dsa/dsa_decrepit.c
index c69d0fa..aef8056 100644
--- a/src/crypto/pkcs8/p8_pkey.c
+++ b/src/decrepit/dsa/dsa_decrepit.c
@@ -1,8 +1,5 @@
-/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
- * project 1999.
- */
 /* ====================================================================
- * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1998-2002 The OpenSSL Project.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -19,12 +16,12 @@
  * 3. All advertising materials mentioning features or use of this
  *    software must display the following acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  *
  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  *    endorse or promote products derived from this software without
  *    prior written permission. For written permission, please contact
- *    licensing@OpenSSL.org.
+ *    openssl-core@openssl.org.
  *
  * 5. Products derived from this software may not be called "OpenSSL"
  *    nor may "OpenSSL" appear in their names without prior written
@@ -33,7 +30,7 @@
  * 6. Redistributions of any form whatsoever must retain the following
  *    acknowledgment:
  *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  *
  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -53,33 +50,56 @@
  * (eay@cryptsoft.com).  This product includes software written by Tim
  * Hudson (tjh@cryptsoft.com). */
 
+#include <openssl/bn.h>
+#include <openssl/dsa.h>
 
-#include <stdio.h>
 
-#include <openssl/asn1t.h>
-#include <openssl/mem.h>
-#include <openssl/x509.h>
+struct wrapped_callback {
+  void (*callback)(int, int, void *);
+  void *arg;
+};
 
-/* Minor tweak to operation: zero private key data */
-static int pkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
-                   void *exarg) {
-  /* Since the structure must still be valid use ASN1_OP_FREE_PRE */
-  if (operation == ASN1_OP_FREE_PRE) {
-    PKCS8_PRIV_KEY_INFO *key = (PKCS8_PRIV_KEY_INFO *)*pval;
-    if (key->pkey && key->pkey->type == V_ASN1_OCTET_STRING &&
-        key->pkey->value.octet_string) {
-      OPENSSL_cleanse(key->pkey->value.octet_string->data,
-                      key->pkey->value.octet_string->length);
-    }
-  }
+/* callback_wrapper converts an “old” style generation callback to the newer
+ * |BN_GENCB| form. */
+static int callback_wrapper(int event, int n, BN_GENCB *gencb) {
+  struct wrapped_callback *wrapped = (struct wrapped_callback *) gencb->arg;
+  wrapped->callback(event, n, wrapped->arg);
   return 1;
 }
 
-ASN1_SEQUENCE_cb(PKCS8_PRIV_KEY_INFO, pkey_cb) = {
-  ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, version, ASN1_INTEGER),
-  ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkeyalg, X509_ALGOR),
-  ASN1_SIMPLE(PKCS8_PRIV_KEY_INFO, pkey, ASN1_ANY),
-  ASN1_IMP_SET_OF_OPT(PKCS8_PRIV_KEY_INFO, attributes, X509_ATTRIBUTE, 0)
-} ASN1_SEQUENCE_END_cb(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO);
+DSA *DSA_generate_parameters(int bits, uint8_t *seed_in, int seed_len,
+                             int *counter_ret, unsigned long *h_ret,
+                             void (*callback)(int, int, void *), void *cb_arg) {
+  if (bits < 0 || seed_len < 0) {
+      return NULL;
+  }
 
-IMPLEMENT_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO);
+  DSA *ret = DSA_new();
+  if (ret == NULL) {
+      return NULL;
+  }
+
+  BN_GENCB gencb_storage;
+  BN_GENCB *cb = NULL;
+
+  struct wrapped_callback wrapped;
+
+  if (callback != NULL) {
+    wrapped.callback = callback;
+    wrapped.arg = cb_arg;
+
+    cb = &gencb_storage;
+    BN_GENCB_set(cb, callback_wrapper, &wrapped);
+  }
+
+  if (!DSA_generate_parameters_ex(ret, bits, seed_in, seed_len, counter_ret,
+                                  h_ret, cb)) {
+    goto err;
+  }
+
+  return ret;
+
+err:
+  DSA_free(ret);
+  return NULL;
+}
diff --git a/src/decrepit/evp/CMakeLists.txt b/src/decrepit/evp/CMakeLists.txt
new file mode 100644
index 0000000..e631a9a
--- /dev/null
+++ b/src/decrepit/evp/CMakeLists.txt
@@ -0,0 +1,10 @@
+include_directories(../../include)
+
+add_library(
+  evp_decrepit
+
+  OBJECT
+
+  dss1.c
+  evp_do_all.c
+)
diff --git a/src/ssl/test/scoped_types.h b/src/decrepit/evp/dss1.c
similarity index 61%
rename from src/ssl/test/scoped_types.h
rename to src/decrepit/evp/dss1.c
index 7e92cee..9c370ac 100644
--- a/src/ssl/test/scoped_types.h
+++ b/src/decrepit/evp/dss1.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, Google Inc.
+/* Copyright (c) 2016, Google Inc.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -12,17 +12,9 @@
  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
 
-#ifndef OPENSSL_HEADER_SSL_TEST_SCOPED_TYPES_H
-#define OPENSSL_HEADER_SSL_TEST_SCOPED_TYPES_H
-
-#include <openssl/ssl.h>
-
-#include "../../crypto/test/scoped_types.h"
+#include <openssl/digest.h>
 
 
-using ScopedSSL = ScopedOpenSSLType<SSL, SSL_free>;
-using ScopedSSL_CTX = ScopedOpenSSLType<SSL_CTX, SSL_CTX_free>;
-using ScopedSSL_SESSION = ScopedOpenSSLType<SSL_SESSION, SSL_SESSION_free>;
-
-
-#endif  // OPENSSL_HEADER_SSL_TEST_SCOPED_TYPES_H
+const EVP_MD *EVP_dss1(void) {
+  return EVP_sha1();
+}
diff --git a/src/decrepit/evp/evp_do_all.c b/src/decrepit/evp/evp_do_all.c
new file mode 100644
index 0000000..621c0b1
--- /dev/null
+++ b/src/decrepit/evp/evp_do_all.c
@@ -0,0 +1,77 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/evp.h>
+
+
+void EVP_CIPHER_do_all_sorted(void (*callback)(const EVP_CIPHER *cipher,
+                                               const char *name,
+                                               const char *unused, void *arg),
+                              void *arg) {
+  callback(EVP_aes_128_cbc(), "AES-128-CBC", NULL, arg);
+  callback(EVP_aes_128_ctr(), "AES-128-CTR", NULL, arg);
+  callback(EVP_aes_128_ecb(), "AES-128-ECB", NULL, arg);
+  callback(EVP_aes_128_ofb(), "AES-128-OFB", NULL, arg);
+  callback(EVP_aes_256_cbc(), "AES-256-CBC", NULL, arg);
+  callback(EVP_aes_256_ctr(), "AES-256-CTR", NULL, arg);
+  callback(EVP_aes_256_ecb(), "AES-256-ECB", NULL, arg);
+  callback(EVP_aes_256_ofb(), "AES-256-OFB", NULL, arg);
+  callback(EVP_aes_256_xts(), "AES-256-XTS", NULL, arg);
+  callback(EVP_des_cbc(), "DES-CBC", NULL, arg);
+  callback(EVP_des_ecb(), "DES-ECB", NULL, arg);
+  callback(EVP_des_ede(), "DES-EDE", NULL, arg);
+  callback(EVP_des_ede_cbc(), "DES-EDE-CBC", NULL, arg);
+  callback(EVP_des_ede3_cbc(), "DES-EDE3-CBC", NULL, arg);
+  callback(EVP_rc2_cbc(), "RC2-CBC", NULL, arg);
+  callback(EVP_rc4(), "RC4", NULL, arg);
+
+  /* OpenSSL returns everything twice, the second time in lower case. */
+  callback(EVP_aes_128_cbc(), "aes-128-cbc", NULL, arg);
+  callback(EVP_aes_128_ctr(), "aes-128-ctr", NULL, arg);
+  callback(EVP_aes_128_ecb(), "aes-128-ecb", NULL, arg);
+  callback(EVP_aes_128_ofb(), "aes-128-ofb", NULL, arg);
+  callback(EVP_aes_256_cbc(), "aes-256-cbc", NULL, arg);
+  callback(EVP_aes_256_ctr(), "aes-256-ctr", NULL, arg);
+  callback(EVP_aes_256_ecb(), "aes-256-ecb", NULL, arg);
+  callback(EVP_aes_256_ofb(), "aes-256-ofb", NULL, arg);
+  callback(EVP_aes_256_xts(), "aes-256-xts", NULL, arg);
+  callback(EVP_des_cbc(), "des-cbc", NULL, arg);
+  callback(EVP_des_ecb(), "des-ecb", NULL, arg);
+  callback(EVP_des_ede(), "des-ede", NULL, arg);
+  callback(EVP_des_ede_cbc(), "des-ede-cbc", NULL, arg);
+  callback(EVP_des_ede3_cbc(), "des-ede3-cbc", NULL, arg);
+  callback(EVP_rc2_cbc(), "rc2-cbc", NULL, arg);
+  callback(EVP_rc4(), "rc4", NULL, arg);
+}
+
+void EVP_MD_do_all_sorted(void (*callback)(const EVP_MD *cipher,
+                                           const char *name, const char *unused,
+                                           void *arg),
+                          void *arg) {
+  callback(EVP_md4(), "MD4", NULL, arg);
+  callback(EVP_md5(), "MD5", NULL, arg);
+  callback(EVP_sha1(), "SHA1", NULL, arg);
+  callback(EVP_sha224(), "SHA224", NULL, arg);
+  callback(EVP_sha256(), "SHA256", NULL, arg);
+  callback(EVP_sha384(), "SHA384", NULL, arg);
+  callback(EVP_sha512(), "SHA512", NULL, arg);
+
+  callback(EVP_md4(), "md4", NULL, arg);
+  callback(EVP_md5(), "md5", NULL, arg);
+  callback(EVP_sha1(), "sha1", NULL, arg);
+  callback(EVP_sha224(), "sha224", NULL, arg);
+  callback(EVP_sha256(), "sha256", NULL, arg);
+  callback(EVP_sha384(), "sha384", NULL, arg);
+  callback(EVP_sha512(), "sha512", NULL, arg);
+}
diff --git a/src/decrepit/obj/CMakeLists.txt b/src/decrepit/obj/CMakeLists.txt
new file mode 100644
index 0000000..caaecd3
--- /dev/null
+++ b/src/decrepit/obj/CMakeLists.txt
@@ -0,0 +1,9 @@
+include_directories(../../include)
+
+add_library(
+  obj_decrepit
+
+  OBJECT
+
+  obj_decrepit.c
+)
diff --git a/src/decrepit/obj/obj_decrepit.c b/src/decrepit/obj/obj_decrepit.c
new file mode 100644
index 0000000..65b2b13
--- /dev/null
+++ b/src/decrepit/obj/obj_decrepit.c
@@ -0,0 +1,75 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/obj.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/evp.h>
+
+#include "../../crypto/internal.h"
+
+
+struct wrapped_callback {
+  void (*callback)(const OBJ_NAME *, void *arg);
+  void *arg;
+};
+
+static void cipher_callback(const EVP_CIPHER *cipher, const char *name,
+                            const char *unused, void *arg) {
+  const struct wrapped_callback *wrapped = (struct wrapped_callback *)arg;
+  OBJ_NAME obj_name;
+
+  OPENSSL_memset(&obj_name, 0, sizeof(obj_name));
+  obj_name.type = OBJ_NAME_TYPE_CIPHER_METH;
+  obj_name.name = name;
+  obj_name.data = (const char *)cipher;
+
+  wrapped->callback(&obj_name, wrapped->arg);
+}
+
+static void md_callback(const EVP_MD *md, const char *name, const char *unused,
+                        void *arg) {
+  const struct wrapped_callback *wrapped = (struct wrapped_callback*) arg;
+  OBJ_NAME obj_name;
+
+  OPENSSL_memset(&obj_name, 0, sizeof(obj_name));
+  obj_name.type = OBJ_NAME_TYPE_MD_METH;
+  obj_name.name = name;
+  obj_name.data = (const char *)md;
+
+  wrapped->callback(&obj_name, wrapped->arg);
+}
+
+void OBJ_NAME_do_all_sorted(int type,
+                            void (*callback)(const OBJ_NAME *, void *arg),
+                            void *arg) {
+  struct wrapped_callback wrapped;
+  wrapped.callback = callback;
+  wrapped.arg = arg;
+
+  if (type == OBJ_NAME_TYPE_CIPHER_METH) {
+    EVP_CIPHER_do_all_sorted(cipher_callback, &wrapped);
+  } else if (type == OBJ_NAME_TYPE_MD_METH) {
+    EVP_MD_do_all_sorted(md_callback, &wrapped);
+  } else {
+    assert(0);
+  }
+}
+
+void OBJ_NAME_do_all(int type, void (*callback)(const OBJ_NAME *, void *arg),
+                     void *arg) {
+  OBJ_NAME_do_all_sorted(type, callback, arg);
+}
diff --git a/src/decrepit/rc4/CMakeLists.txt b/src/decrepit/rc4/CMakeLists.txt
new file mode 100644
index 0000000..459b24e
--- /dev/null
+++ b/src/decrepit/rc4/CMakeLists.txt
@@ -0,0 +1,9 @@
+include_directories(../../include)
+
+add_library(
+  rc4_decrepit
+
+  OBJECT
+
+  rc4_decrepit.c
+)
diff --git a/src/crypto/dsa/internal.h b/src/decrepit/rc4/rc4_decrepit.c
similarity index 86%
rename from src/crypto/dsa/internal.h
rename to src/decrepit/rc4/rc4_decrepit.c
index ef99158..140e15d 100644
--- a/src/crypto/dsa/internal.h
+++ b/src/decrepit/rc4/rc4_decrepit.c
@@ -52,27 +52,11 @@
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- *
- * The DSS routines are based on patches supplied by
- * Steven Schoch <schoch@sheba.arc.nasa.gov>. */
+ * [including the GNU Public Licence.] */
 
-#ifndef OPENSSL_HEADER_DSA_INTERNAL_H
-#define OPENSSL_HEADER_DSA_INTERNAL_H
-
-#include <openssl/base.h>
-
-#include <openssl/bn.h>
-#include <openssl/ex_data.h>
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
+#include <openssl/rc4.h>
 
 
-
-#if defined(__cplusplus)
-}  /* extern C */
-#endif
-
-#endif  /* OPENSSL_HEADER_DSA_INTERNAL_H */
+const char *RC4_options(void) {
+  return "rc4(ptr,int)";
+}
diff --git a/src/decrepit/ripemd/CMakeLists.txt b/src/decrepit/ripemd/CMakeLists.txt
new file mode 100644
index 0000000..d3dd284
--- /dev/null
+++ b/src/decrepit/ripemd/CMakeLists.txt
@@ -0,0 +1,9 @@
+include_directories(../../include)
+
+add_library(
+  ripemd_decrepit
+
+  OBJECT
+
+  ripemd.c
+)
diff --git a/src/decrepit/ripemd/internal.h b/src/decrepit/ripemd/internal.h
new file mode 100644
index 0000000..cbf7a8d
--- /dev/null
+++ b/src/decrepit/ripemd/internal.h
@@ -0,0 +1,493 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#ifndef OPENSSL_HEADER_BN_INTERNAL_H
+#define OPENSSL_HEADER_BN_INTERNAL_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+static void ripemd160_block_data_order(uint32_t h[5], const uint8_t *data,
+                                       size_t num);
+
+#define DATA_ORDER_IS_LITTLE_ENDIAN
+
+#define HASH_LONG uint32_t
+#define HASH_CTX RIPEMD160_CTX
+#define HASH_CBLOCK RIPEMD160_CBLOCK
+#define HASH_UPDATE RIPEMD160_Update
+#define HASH_TRANSFORM RIPEMD160_Transform
+#define HASH_FINAL RIPEMD160_Final
+#define HASH_MAKE_STRING(c, s) \
+  do {                         \
+    unsigned long ll;          \
+    ll = (c)->h[0];            \
+    HOST_l2c(ll, (s));         \
+    ll = (c)->h[1];            \
+    HOST_l2c(ll, (s));         \
+    ll = (c)->h[2];            \
+    HOST_l2c(ll, (s));         \
+    ll = (c)->h[3];            \
+    HOST_l2c(ll, (s));         \
+    ll = (c)->h[4];            \
+    HOST_l2c(ll, (s));         \
+  } while (0)
+#define HASH_BLOCK_DATA_ORDER ripemd160_block_data_order
+
+#include "../../crypto/digest/md32_common.h"
+
+/* Transformed F2 and F4 are courtesy of Wei Dai <weidai@eskimo.com> */
+#define F1(x, y, z) ((x) ^ (y) ^ (z))
+#define F2(x, y, z) ((((y) ^ (z)) & (x)) ^ (z))
+#define F3(x, y, z) (((~(y)) | (x)) ^ (z))
+#define F4(x, y, z) ((((x) ^ (y)) & (z)) ^ (y))
+#define F5(x, y, z) (((~(z)) | (y)) ^ (x))
+
+#define RIPEMD160_A 0x67452301L
+#define RIPEMD160_B 0xEFCDAB89L
+#define RIPEMD160_C 0x98BADCFEL
+#define RIPEMD160_D 0x10325476L
+#define RIPEMD160_E 0xC3D2E1F0L
+
+#define ROTATE(a, n) (((a) << (n)) | (((a)&0xffffffff) >> (32 - (n))))
+
+#define RIP1(a, b, c, d, e, w, s) \
+  {                               \
+    a += F1(b, c, d) + X(w);      \
+    a = ROTATE(a, s) + e;         \
+    c = ROTATE(c, 10);            \
+  }
+
+#define RIP2(a, b, c, d, e, w, s, K) \
+  {                                  \
+    a += F2(b, c, d) + X(w) + K;     \
+    a = ROTATE(a, s) + e;            \
+    c = ROTATE(c, 10);               \
+  }
+
+#define RIP3(a, b, c, d, e, w, s, K) \
+  {                                  \
+    a += F3(b, c, d) + X(w) + K;     \
+    a = ROTATE(a, s) + e;            \
+    c = ROTATE(c, 10);               \
+  }
+
+#define RIP4(a, b, c, d, e, w, s, K) \
+  {                                  \
+    a += F4(b, c, d) + X(w) + K;     \
+    a = ROTATE(a, s) + e;            \
+    c = ROTATE(c, 10);               \
+  }
+
+#define RIP5(a, b, c, d, e, w, s, K) \
+  {                                  \
+    a += F5(b, c, d) + X(w) + K;     \
+    a = ROTATE(a, s) + e;            \
+    c = ROTATE(c, 10);               \
+  }
+
+#define KL0 0x00000000L
+#define KL1 0x5A827999L
+#define KL2 0x6ED9EBA1L
+#define KL3 0x8F1BBCDCL
+#define KL4 0xA953FD4EL
+
+#define KR0 0x50A28BE6L
+#define KR1 0x5C4DD124L
+#define KR2 0x6D703EF3L
+#define KR3 0x7A6D76E9L
+#define KR4 0x00000000L
+
+#define WL00  0
+#define SL00 11
+#define WL01  1
+#define SL01 14
+#define WL02  2
+#define SL02 15
+#define WL03  3
+#define SL03 12
+#define WL04  4
+#define SL04  5
+#define WL05  5
+#define SL05  8
+#define WL06  6
+#define SL06  7
+#define WL07  7
+#define SL07  9
+#define WL08  8
+#define SL08 11
+#define WL09  9
+#define SL09 13
+#define WL10 10
+#define SL10 14
+#define WL11 11
+#define SL11 15
+#define WL12 12
+#define SL12  6
+#define WL13 13
+#define SL13  7
+#define WL14 14
+#define SL14  9
+#define WL15 15
+#define SL15  8
+
+#define WL16  7
+#define SL16  7
+#define WL17  4
+#define SL17  6
+#define WL18 13
+#define SL18  8
+#define WL19  1
+#define SL19 13
+#define WL20 10
+#define SL20 11
+#define WL21  6
+#define SL21  9
+#define WL22 15
+#define SL22  7
+#define WL23  3
+#define SL23 15
+#define WL24 12
+#define SL24  7
+#define WL25  0
+#define SL25 12
+#define WL26  9
+#define SL26 15
+#define WL27  5
+#define SL27  9
+#define WL28  2
+#define SL28 11
+#define WL29 14
+#define SL29  7
+#define WL30 11
+#define SL30 13
+#define WL31  8
+#define SL31 12
+
+#define WL32  3
+#define SL32 11
+#define WL33 10
+#define SL33 13
+#define WL34 14
+#define SL34  6
+#define WL35  4
+#define SL35  7
+#define WL36  9
+#define SL36 14
+#define WL37 15
+#define SL37  9
+#define WL38  8
+#define SL38 13
+#define WL39  1
+#define SL39 15
+#define WL40  2
+#define SL40 14
+#define WL41  7
+#define SL41  8
+#define WL42  0
+#define SL42 13
+#define WL43  6
+#define SL43  6
+#define WL44 13
+#define SL44  5
+#define WL45 11
+#define SL45 12
+#define WL46  5
+#define SL46  7
+#define WL47 12
+#define SL47  5
+
+#define WL48  1
+#define SL48 11
+#define WL49  9
+#define SL49 12
+#define WL50 11
+#define SL50 14
+#define WL51 10
+#define SL51 15
+#define WL52  0
+#define SL52 14
+#define WL53  8
+#define SL53 15
+#define WL54 12
+#define SL54  9
+#define WL55  4
+#define SL55  8
+#define WL56 13
+#define SL56  9
+#define WL57  3
+#define SL57 14
+#define WL58  7
+#define SL58  5
+#define WL59 15
+#define SL59  6
+#define WL60 14
+#define SL60  8
+#define WL61  5
+#define SL61  6
+#define WL62  6
+#define SL62  5
+#define WL63  2
+#define SL63 12
+
+#define WL64  4
+#define SL64  9
+#define WL65  0
+#define SL65 15
+#define WL66  5
+#define SL66  5
+#define WL67  9
+#define SL67 11
+#define WL68  7
+#define SL68  6
+#define WL69 12
+#define SL69  8
+#define WL70  2
+#define SL70 13
+#define WL71 10
+#define SL71 12
+#define WL72 14
+#define SL72  5
+#define WL73  1
+#define SL73 12
+#define WL74  3
+#define SL74 13
+#define WL75  8
+#define SL75 14
+#define WL76 11
+#define SL76 11
+#define WL77  6
+#define SL77  8
+#define WL78 15
+#define SL78  5
+#define WL79 13
+#define SL79  6
+
+#define WR00  5
+#define SR00  8
+#define WR01 14
+#define SR01  9
+#define WR02  7
+#define SR02  9
+#define WR03  0
+#define SR03 11
+#define WR04  9
+#define SR04 13
+#define WR05  2
+#define SR05 15
+#define WR06 11
+#define SR06 15
+#define WR07  4
+#define SR07  5
+#define WR08 13
+#define SR08  7
+#define WR09  6
+#define SR09  7
+#define WR10 15
+#define SR10  8
+#define WR11  8
+#define SR11 11
+#define WR12  1
+#define SR12 14
+#define WR13 10
+#define SR13 14
+#define WR14  3
+#define SR14 12
+#define WR15 12
+#define SR15  6
+
+#define WR16  6
+#define SR16  9
+#define WR17 11
+#define SR17 13
+#define WR18  3
+#define SR18 15
+#define WR19  7
+#define SR19  7
+#define WR20  0
+#define SR20 12
+#define WR21 13
+#define SR21  8
+#define WR22  5
+#define SR22  9
+#define WR23 10
+#define SR23 11
+#define WR24 14
+#define SR24  7
+#define WR25 15
+#define SR25  7
+#define WR26  8
+#define SR26 12
+#define WR27 12
+#define SR27  7
+#define WR28  4
+#define SR28  6
+#define WR29  9
+#define SR29 15
+#define WR30  1
+#define SR30 13
+#define WR31  2
+#define SR31 11
+
+#define WR32 15
+#define SR32  9
+#define WR33  5
+#define SR33  7
+#define WR34  1
+#define SR34 15
+#define WR35  3
+#define SR35 11
+#define WR36  7
+#define SR36  8
+#define WR37 14
+#define SR37  6
+#define WR38  6
+#define SR38  6
+#define WR39  9
+#define SR39 14
+#define WR40 11
+#define SR40 12
+#define WR41  8
+#define SR41 13
+#define WR42 12
+#define SR42  5
+#define WR43  2
+#define SR43 14
+#define WR44 10
+#define SR44 13
+#define WR45  0
+#define SR45 13
+#define WR46  4
+#define SR46  7
+#define WR47 13
+#define SR47  5
+
+#define WR48  8
+#define SR48 15
+#define WR49  6
+#define SR49  5
+#define WR50  4
+#define SR50  8
+#define WR51  1
+#define SR51 11
+#define WR52  3
+#define SR52 14
+#define WR53 11
+#define SR53 14
+#define WR54 15
+#define SR54  6
+#define WR55  0
+#define SR55 14
+#define WR56  5
+#define SR56  6
+#define WR57 12
+#define SR57  9
+#define WR58  2
+#define SR58 12
+#define WR59 13
+#define SR59  9
+#define WR60  9
+#define SR60 12
+#define WR61  7
+#define SR61  5
+#define WR62 10
+#define SR62 15
+#define WR63 14
+#define SR63  8
+
+#define WR64 12
+#define SR64  8
+#define WR65 15
+#define SR65  5
+#define WR66 10
+#define SR66 12
+#define WR67  4
+#define SR67  9
+#define WR68  1
+#define SR68 12
+#define WR69  5
+#define SR69  5
+#define WR70  8
+#define SR70 14
+#define WR71  7
+#define SR71  6
+#define WR72  6
+#define SR72  8
+#define WR73  2
+#define SR73 13
+#define WR74 13
+#define SR74  6
+#define WR75 14
+#define SR75  5
+#define WR76  0
+#define SR76 15
+#define WR77  3
+#define SR77 13
+#define WR78  9
+#define SR78 11
+#define WR79 11
+#define SR79 11
+
+
+#if defined(__cplusplus)
+}  /* extern C */
+#endif
+
+#endif  /* OPENSSL_HEADER_BN_INTERNAL_H */
diff --git a/src/decrepit/ripemd/ripemd.c b/src/decrepit/ripemd/ripemd.c
new file mode 100644
index 0000000..ab9bc32
--- /dev/null
+++ b/src/decrepit/ripemd/ripemd.c
@@ -0,0 +1,324 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/ripemd.h>
+
+#include <string.h>
+
+#include "internal.h"
+
+
+int RIPEMD160_Init(RIPEMD160_CTX *ctx) {
+  OPENSSL_memset(ctx, 0, sizeof(*ctx));
+  ctx->h[0] = RIPEMD160_A;
+  ctx->h[1] = RIPEMD160_B;
+  ctx->h[2] = RIPEMD160_C;
+  ctx->h[3] = RIPEMD160_D;
+  ctx->h[4] = RIPEMD160_E;
+  return 1;
+}
+
+static void ripemd160_block_data_order(uint32_t h[5], const uint8_t *data,
+                                       size_t num) {
+  uint32_t A, B, C, D, E;
+  uint32_t a, b, c, d, e, l;
+  uint32_t XX0, XX1, XX2, XX3, XX4, XX5, XX6, XX7, XX8, XX9, XX10, XX11, XX12,
+      XX13, XX14, XX15;
+#define X(i) XX##i
+
+  for (; num--;) {
+    A = h[0];
+    B = h[1];
+    C = h[2];
+    D = h[3];
+    E = h[4];
+
+    HOST_c2l(data, l);
+    X(0) = l;
+    HOST_c2l(data, l);
+    X(1) = l;
+    RIP1(A, B, C, D, E, WL00, SL00);
+    HOST_c2l(data, l);
+    X(2) = l;
+    RIP1(E, A, B, C, D, WL01, SL01);
+    HOST_c2l(data, l);
+    X(3) = l;
+    RIP1(D, E, A, B, C, WL02, SL02);
+    HOST_c2l(data, l);
+    X(4) = l;
+    RIP1(C, D, E, A, B, WL03, SL03);
+    HOST_c2l(data, l);
+    X(5) = l;
+    RIP1(B, C, D, E, A, WL04, SL04);
+    HOST_c2l(data, l);
+    X(6) = l;
+    RIP1(A, B, C, D, E, WL05, SL05);
+    HOST_c2l(data, l);
+    X(7) = l;
+    RIP1(E, A, B, C, D, WL06, SL06);
+    HOST_c2l(data, l);
+    X(8) = l;
+    RIP1(D, E, A, B, C, WL07, SL07);
+    HOST_c2l(data, l);
+    X(9) = l;
+    RIP1(C, D, E, A, B, WL08, SL08);
+    HOST_c2l(data, l);
+    X(10) = l;
+    RIP1(B, C, D, E, A, WL09, SL09);
+    HOST_c2l(data, l);
+    X(11) = l;
+    RIP1(A, B, C, D, E, WL10, SL10);
+    HOST_c2l(data, l);
+    X(12) = l;
+    RIP1(E, A, B, C, D, WL11, SL11);
+    HOST_c2l(data, l);
+    X(13) = l;
+    RIP1(D, E, A, B, C, WL12, SL12);
+    HOST_c2l(data, l);
+    X(14) = l;
+    RIP1(C, D, E, A, B, WL13, SL13);
+    HOST_c2l(data, l);
+    X(15) = l;
+    RIP1(B, C, D, E, A, WL14, SL14);
+    RIP1(A, B, C, D, E, WL15, SL15);
+
+    RIP2(E, A, B, C, D, WL16, SL16, KL1);
+    RIP2(D, E, A, B, C, WL17, SL17, KL1);
+    RIP2(C, D, E, A, B, WL18, SL18, KL1);
+    RIP2(B, C, D, E, A, WL19, SL19, KL1);
+    RIP2(A, B, C, D, E, WL20, SL20, KL1);
+    RIP2(E, A, B, C, D, WL21, SL21, KL1);
+    RIP2(D, E, A, B, C, WL22, SL22, KL1);
+    RIP2(C, D, E, A, B, WL23, SL23, KL1);
+    RIP2(B, C, D, E, A, WL24, SL24, KL1);
+    RIP2(A, B, C, D, E, WL25, SL25, KL1);
+    RIP2(E, A, B, C, D, WL26, SL26, KL1);
+    RIP2(D, E, A, B, C, WL27, SL27, KL1);
+    RIP2(C, D, E, A, B, WL28, SL28, KL1);
+    RIP2(B, C, D, E, A, WL29, SL29, KL1);
+    RIP2(A, B, C, D, E, WL30, SL30, KL1);
+    RIP2(E, A, B, C, D, WL31, SL31, KL1);
+
+    RIP3(D, E, A, B, C, WL32, SL32, KL2);
+    RIP3(C, D, E, A, B, WL33, SL33, KL2);
+    RIP3(B, C, D, E, A, WL34, SL34, KL2);
+    RIP3(A, B, C, D, E, WL35, SL35, KL2);
+    RIP3(E, A, B, C, D, WL36, SL36, KL2);
+    RIP3(D, E, A, B, C, WL37, SL37, KL2);
+    RIP3(C, D, E, A, B, WL38, SL38, KL2);
+    RIP3(B, C, D, E, A, WL39, SL39, KL2);
+    RIP3(A, B, C, D, E, WL40, SL40, KL2);
+    RIP3(E, A, B, C, D, WL41, SL41, KL2);
+    RIP3(D, E, A, B, C, WL42, SL42, KL2);
+    RIP3(C, D, E, A, B, WL43, SL43, KL2);
+    RIP3(B, C, D, E, A, WL44, SL44, KL2);
+    RIP3(A, B, C, D, E, WL45, SL45, KL2);
+    RIP3(E, A, B, C, D, WL46, SL46, KL2);
+    RIP3(D, E, A, B, C, WL47, SL47, KL2);
+
+    RIP4(C, D, E, A, B, WL48, SL48, KL3);
+    RIP4(B, C, D, E, A, WL49, SL49, KL3);
+    RIP4(A, B, C, D, E, WL50, SL50, KL3);
+    RIP4(E, A, B, C, D, WL51, SL51, KL3);
+    RIP4(D, E, A, B, C, WL52, SL52, KL3);
+    RIP4(C, D, E, A, B, WL53, SL53, KL3);
+    RIP4(B, C, D, E, A, WL54, SL54, KL3);
+    RIP4(A, B, C, D, E, WL55, SL55, KL3);
+    RIP4(E, A, B, C, D, WL56, SL56, KL3);
+    RIP4(D, E, A, B, C, WL57, SL57, KL3);
+    RIP4(C, D, E, A, B, WL58, SL58, KL3);
+    RIP4(B, C, D, E, A, WL59, SL59, KL3);
+    RIP4(A, B, C, D, E, WL60, SL60, KL3);
+    RIP4(E, A, B, C, D, WL61, SL61, KL3);
+    RIP4(D, E, A, B, C, WL62, SL62, KL3);
+    RIP4(C, D, E, A, B, WL63, SL63, KL3);
+
+    RIP5(B, C, D, E, A, WL64, SL64, KL4);
+    RIP5(A, B, C, D, E, WL65, SL65, KL4);
+    RIP5(E, A, B, C, D, WL66, SL66, KL4);
+    RIP5(D, E, A, B, C, WL67, SL67, KL4);
+    RIP5(C, D, E, A, B, WL68, SL68, KL4);
+    RIP5(B, C, D, E, A, WL69, SL69, KL4);
+    RIP5(A, B, C, D, E, WL70, SL70, KL4);
+    RIP5(E, A, B, C, D, WL71, SL71, KL4);
+    RIP5(D, E, A, B, C, WL72, SL72, KL4);
+    RIP5(C, D, E, A, B, WL73, SL73, KL4);
+    RIP5(B, C, D, E, A, WL74, SL74, KL4);
+    RIP5(A, B, C, D, E, WL75, SL75, KL4);
+    RIP5(E, A, B, C, D, WL76, SL76, KL4);
+    RIP5(D, E, A, B, C, WL77, SL77, KL4);
+    RIP5(C, D, E, A, B, WL78, SL78, KL4);
+    RIP5(B, C, D, E, A, WL79, SL79, KL4);
+
+    a = A;
+    b = B;
+    c = C;
+    d = D;
+    e = E;
+    /* Do other half */
+    A = h[0];
+    B = h[1];
+    C = h[2];
+    D = h[3];
+    E = h[4];
+
+    RIP5(A, B, C, D, E, WR00, SR00, KR0);
+    RIP5(E, A, B, C, D, WR01, SR01, KR0);
+    RIP5(D, E, A, B, C, WR02, SR02, KR0);
+    RIP5(C, D, E, A, B, WR03, SR03, KR0);
+    RIP5(B, C, D, E, A, WR04, SR04, KR0);
+    RIP5(A, B, C, D, E, WR05, SR05, KR0);
+    RIP5(E, A, B, C, D, WR06, SR06, KR0);
+    RIP5(D, E, A, B, C, WR07, SR07, KR0);
+    RIP5(C, D, E, A, B, WR08, SR08, KR0);
+    RIP5(B, C, D, E, A, WR09, SR09, KR0);
+    RIP5(A, B, C, D, E, WR10, SR10, KR0);
+    RIP5(E, A, B, C, D, WR11, SR11, KR0);
+    RIP5(D, E, A, B, C, WR12, SR12, KR0);
+    RIP5(C, D, E, A, B, WR13, SR13, KR0);
+    RIP5(B, C, D, E, A, WR14, SR14, KR0);
+    RIP5(A, B, C, D, E, WR15, SR15, KR0);
+
+    RIP4(E, A, B, C, D, WR16, SR16, KR1);
+    RIP4(D, E, A, B, C, WR17, SR17, KR1);
+    RIP4(C, D, E, A, B, WR18, SR18, KR1);
+    RIP4(B, C, D, E, A, WR19, SR19, KR1);
+    RIP4(A, B, C, D, E, WR20, SR20, KR1);
+    RIP4(E, A, B, C, D, WR21, SR21, KR1);
+    RIP4(D, E, A, B, C, WR22, SR22, KR1);
+    RIP4(C, D, E, A, B, WR23, SR23, KR1);
+    RIP4(B, C, D, E, A, WR24, SR24, KR1);
+    RIP4(A, B, C, D, E, WR25, SR25, KR1);
+    RIP4(E, A, B, C, D, WR26, SR26, KR1);
+    RIP4(D, E, A, B, C, WR27, SR27, KR1);
+    RIP4(C, D, E, A, B, WR28, SR28, KR1);
+    RIP4(B, C, D, E, A, WR29, SR29, KR1);
+    RIP4(A, B, C, D, E, WR30, SR30, KR1);
+    RIP4(E, A, B, C, D, WR31, SR31, KR1);
+
+    RIP3(D, E, A, B, C, WR32, SR32, KR2);
+    RIP3(C, D, E, A, B, WR33, SR33, KR2);
+    RIP3(B, C, D, E, A, WR34, SR34, KR2);
+    RIP3(A, B, C, D, E, WR35, SR35, KR2);
+    RIP3(E, A, B, C, D, WR36, SR36, KR2);
+    RIP3(D, E, A, B, C, WR37, SR37, KR2);
+    RIP3(C, D, E, A, B, WR38, SR38, KR2);
+    RIP3(B, C, D, E, A, WR39, SR39, KR2);
+    RIP3(A, B, C, D, E, WR40, SR40, KR2);
+    RIP3(E, A, B, C, D, WR41, SR41, KR2);
+    RIP3(D, E, A, B, C, WR42, SR42, KR2);
+    RIP3(C, D, E, A, B, WR43, SR43, KR2);
+    RIP3(B, C, D, E, A, WR44, SR44, KR2);
+    RIP3(A, B, C, D, E, WR45, SR45, KR2);
+    RIP3(E, A, B, C, D, WR46, SR46, KR2);
+    RIP3(D, E, A, B, C, WR47, SR47, KR2);
+
+    RIP2(C, D, E, A, B, WR48, SR48, KR3);
+    RIP2(B, C, D, E, A, WR49, SR49, KR3);
+    RIP2(A, B, C, D, E, WR50, SR50, KR3);
+    RIP2(E, A, B, C, D, WR51, SR51, KR3);
+    RIP2(D, E, A, B, C, WR52, SR52, KR3);
+    RIP2(C, D, E, A, B, WR53, SR53, KR3);
+    RIP2(B, C, D, E, A, WR54, SR54, KR3);
+    RIP2(A, B, C, D, E, WR55, SR55, KR3);
+    RIP2(E, A, B, C, D, WR56, SR56, KR3);
+    RIP2(D, E, A, B, C, WR57, SR57, KR3);
+    RIP2(C, D, E, A, B, WR58, SR58, KR3);
+    RIP2(B, C, D, E, A, WR59, SR59, KR3);
+    RIP2(A, B, C, D, E, WR60, SR60, KR3);
+    RIP2(E, A, B, C, D, WR61, SR61, KR3);
+    RIP2(D, E, A, B, C, WR62, SR62, KR3);
+    RIP2(C, D, E, A, B, WR63, SR63, KR3);
+
+    RIP1(B, C, D, E, A, WR64, SR64);
+    RIP1(A, B, C, D, E, WR65, SR65);
+    RIP1(E, A, B, C, D, WR66, SR66);
+    RIP1(D, E, A, B, C, WR67, SR67);
+    RIP1(C, D, E, A, B, WR68, SR68);
+    RIP1(B, C, D, E, A, WR69, SR69);
+    RIP1(A, B, C, D, E, WR70, SR70);
+    RIP1(E, A, B, C, D, WR71, SR71);
+    RIP1(D, E, A, B, C, WR72, SR72);
+    RIP1(C, D, E, A, B, WR73, SR73);
+    RIP1(B, C, D, E, A, WR74, SR74);
+    RIP1(A, B, C, D, E, WR75, SR75);
+    RIP1(E, A, B, C, D, WR76, SR76);
+    RIP1(D, E, A, B, C, WR77, SR77);
+    RIP1(C, D, E, A, B, WR78, SR78);
+    RIP1(B, C, D, E, A, WR79, SR79);
+
+    D = h[1] + c + D;
+    h[1] = h[2] + d + E;
+    h[2] = h[3] + e + A;
+    h[3] = h[4] + a + B;
+    h[4] = h[0] + b + C;
+    h[0] = D;
+  }
+
+#undef X
+}
+
+uint8_t *RIPEMD160(const uint8_t *data, size_t len, unsigned char *out) {
+  RIPEMD160_CTX ctx;
+
+  if (!RIPEMD160_Init(&ctx)) {
+    return NULL;
+  }
+
+  RIPEMD160_Update(&ctx, data, len);
+  RIPEMD160_Final(out, &ctx);
+  return out;
+}
diff --git a/src/decrepit/ripemd/ripemd_test.cc b/src/decrepit/ripemd/ripemd_test.cc
new file mode 100644
index 0000000..5c54196
--- /dev/null
+++ b/src/decrepit/ripemd/ripemd_test.cc
@@ -0,0 +1,118 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/ripemd.h>
+
+#include <memory>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <gtest/gtest.h>
+
+#include "../../crypto/internal.h"
+#include "../../crypto/test/test_util.h"
+
+
+struct RIPEMDTestCase {
+  const char *input;
+  uint8_t expected[RIPEMD160_DIGEST_LENGTH];
+};
+
+static const RIPEMDTestCase kRIPEMDTestCases[] = {
+    {"", {0x9c, 0x11, 0x85, 0xa5, 0xc5, 0xe9, 0xfc, 0x54, 0x61, 0x28,
+          0x08, 0x97, 0x7e, 0xe8, 0xf5, 0x48, 0xb2, 0x25, 0x8d, 0x31}},
+    {"a", {0x0b, 0xdc, 0x9d, 0x2d, 0x25, 0x6b, 0x3e, 0xe9, 0xda, 0xae,
+           0x34, 0x7b, 0xe6, 0xf4, 0xdc, 0x83, 0x5a, 0x46, 0x7f, 0xfe}},
+    {"abc", {0x8e, 0xb2, 0x08, 0xf7, 0xe0, 0x5d, 0x98, 0x7a, 0x9b, 0x04,
+             0x4a, 0x8e, 0x98, 0xc6, 0xb0, 0x87, 0xf1, 0x5a, 0x0b, 0xfc}},
+    {"message digest",
+     {0x5d, 0x06, 0x89, 0xef, 0x49, 0xd2, 0xfa, 0xe5, 0x72, 0xb8,
+      0x81, 0xb1, 0x23, 0xa8, 0x5f, 0xfa, 0x21, 0x59, 0x5f, 0x36}},
+    {"abcdefghijklmnopqrstuvwxyz",
+     {0xf7, 0x1c, 0x27, 0x10, 0x9c, 0x69, 0x2c, 0x1b, 0x56, 0xbb,
+      0xdc, 0xeb, 0x5b, 0x9d, 0x28, 0x65, 0xb3, 0x70, 0x8d, 0xbc}},
+    {"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
+     {0x12, 0xa0, 0x53, 0x38, 0x4a, 0x9c, 0x0c, 0x88, 0xe4, 0x05,
+      0xa0, 0x6c, 0x27, 0xdc, 0xf4, 0x9a, 0xda, 0x62, 0xeb, 0x2b}},
+    {"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+     {0xb0, 0xe2, 0x0b, 0x6e, 0x31, 0x16, 0x64, 0x02, 0x86, 0xed,
+      0x3a, 0x87, 0xa5, 0x71, 0x30, 0x79, 0xb2, 0x1f, 0x51, 0x89}},
+    {"1234567890123456789012345678901234567890123456789012345678901234567890123"
+     "4567890",
+     {0x9b, 0x75, 0x2e, 0x45, 0x57, 0x3d, 0x4b, 0x39, 0xf4, 0xdb,
+      0xd3, 0x32, 0x3c, 0xab, 0x82, 0xbf, 0x63, 0x32, 0x6b, 0xfb}},
+};
+
+// TODO(davidben): Convert this file to GTest properly.
+TEST(RIPEMDTest, RunTest) {
+  unsigned test_num = 0;
+  int ok = 1;
+
+  for (const auto &test : kRIPEMDTestCases) {
+    test_num++;
+
+    const size_t input_len = strlen(test.input);
+
+    for (size_t stride = 0; stride <= input_len; stride++) {
+      uint8_t digest[RIPEMD160_DIGEST_LENGTH];
+
+      if (stride == 0) {
+        RIPEMD160(reinterpret_cast<const uint8_t *>(test.input), input_len,
+                  digest);
+      } else {
+        RIPEMD160_CTX ctx;
+        RIPEMD160_Init(&ctx);
+
+        for (size_t done = 0; done < input_len;) {
+          const size_t remaining = input_len - done;
+          size_t todo = stride;
+          if (todo > remaining) {
+            todo = remaining;
+          }
+
+          RIPEMD160_Update(&ctx, &test.input[done], todo);
+          done += todo;
+        }
+
+        RIPEMD160_Final(digest, &ctx);
+      }
+
+      if (OPENSSL_memcmp(digest, test.expected, sizeof(digest)) != 0) {
+        fprintf(stderr, "#%u: bad result with stride %u: ", test_num,
+                static_cast<unsigned>(stride));
+        hexdump(stderr, "", digest, sizeof(digest));
+        ok = 0;
+      }
+    }
+  }
+
+  static const size_t kLargeBufSize = 1000000;
+  std::unique_ptr<uint8_t[]> buf(new uint8_t[kLargeBufSize]);
+  OPENSSL_memset(buf.get(), 'a', kLargeBufSize);
+  uint8_t digest[RIPEMD160_DIGEST_LENGTH];
+  RIPEMD160(buf.get(), kLargeBufSize, digest);
+
+  static const uint8_t kMillionADigest[RIPEMD160_DIGEST_LENGTH] = {
+      0x52, 0x78, 0x32, 0x43, 0xc1, 0x69, 0x7b, 0xdb, 0xe1, 0x6d,
+      0x37, 0xf9, 0x7f, 0x68, 0xf0, 0x83, 0x25, 0xdc, 0x15, 0x28};
+
+  if (OPENSSL_memcmp(digest, kMillionADigest, sizeof(digest)) != 0) {
+    fprintf(stderr, "Digest incorrect for “million a's” test: ");
+    hexdump(stderr, "", digest, sizeof(digest));
+    ok = 0;
+  }
+
+  EXPECT_EQ(1, ok);
+}
diff --git a/src/decrepit/rsa/rsa_decrepit.c b/src/decrepit/rsa/rsa_decrepit.c
index c238f46..c4ef5b6 100644
--- a/src/decrepit/rsa/rsa_decrepit.c
+++ b/src/decrepit/rsa/rsa_decrepit.c
@@ -84,3 +84,20 @@
   RSA_free(rsa);
   return NULL;
 }
+
+int RSA_padding_add_PKCS1_PSS(RSA *rsa, uint8_t *EM, const uint8_t *mHash,
+                              const EVP_MD *Hash, int sLen) {
+  return RSA_padding_add_PKCS1_PSS_mgf1(rsa, EM, mHash, Hash, NULL, sLen);
+}
+
+int RSA_verify_PKCS1_PSS(RSA *rsa, const uint8_t *mHash, const EVP_MD *Hash,
+                         const uint8_t *EM, int sLen) {
+  return RSA_verify_PKCS1_PSS_mgf1(rsa, mHash, Hash, NULL, EM, sLen);
+}
+
+int RSA_padding_add_PKCS1_OAEP(uint8_t *to, size_t to_len,
+                               const uint8_t *from, size_t from_len,
+                               const uint8_t *param, size_t param_len) {
+  return RSA_padding_add_PKCS1_OAEP_mgf1(to, to_len, from, from_len, param,
+                                         param_len, NULL, NULL);
+}
diff --git a/src/decrepit/ssl/CMakeLists.txt b/src/decrepit/ssl/CMakeLists.txt
new file mode 100644
index 0000000..fba0234
--- /dev/null
+++ b/src/decrepit/ssl/CMakeLists.txt
@@ -0,0 +1,9 @@
+include_directories(../../include)
+
+add_library(
+  ssl_decrepit
+
+  OBJECT
+
+  ssl_decrepit.c
+)
diff --git a/src/decrepit/ssl/ssl_decrepit.c b/src/decrepit/ssl/ssl_decrepit.c
new file mode 100644
index 0000000..12a03da
--- /dev/null
+++ b/src/decrepit/ssl/ssl_decrepit.c
@@ -0,0 +1,165 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+#include <openssl/ssl.h>
+
+#if !defined(OPENSSL_WINDOWS) && !defined(OPENSSL_PNACL)
+
+#include <dirent.h>
+#include <errno.h>
+#include <string.h>
+
+#include <openssl/err.h>
+#include <openssl/mem.h>
+
+
+int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
+                                       const char *path) {
+  DIR *dir = opendir(path);
+  if (dir == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
+    ERR_add_error_data(3, "opendir('", dir, "')");
+    return 0;
+  }
+
+  int ret = 0;
+  for (;;) {
+    /* |readdir| may fail with or without setting |errno|. */
+    errno = 0;
+    struct dirent *dirent = readdir(dir);
+    if (dirent == NULL) {
+      if (errno) {
+        OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
+        ERR_add_error_data(3, "readdir('", path, "')");
+      } else {
+        ret = 1;
+      }
+      break;
+    }
+
+    char buf[1024];
+    if (strlen(path) + strlen(dirent->d_name) + 2 > sizeof(buf)) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_PATH_TOO_LONG);
+      break;
+    }
+
+    int r = BIO_snprintf(buf, sizeof(buf), "%s/%s", path, dirent->d_name);
+    if (r <= 0 ||
+        r >= (int)sizeof(buf) ||
+        !SSL_add_file_cert_subjects_to_stack(stack, buf)) {
+      break;
+    }
+  }
+
+  closedir(dir);
+  return ret;
+}
+
+#endif /* !WINDOWS && !PNACL */
diff --git a/src/decrepit/x509/CMakeLists.txt b/src/decrepit/x509/CMakeLists.txt
new file mode 100644
index 0000000..930912d
--- /dev/null
+++ b/src/decrepit/x509/CMakeLists.txt
@@ -0,0 +1,9 @@
+include_directories(../../include)
+
+add_library(
+  x509_decrepit
+
+  OBJECT
+
+  x509_decrepit.c
+)
diff --git a/src/decrepit/x509/x509_decrepit.c b/src/decrepit/x509/x509_decrepit.c
new file mode 100644
index 0000000..5714b40
--- /dev/null
+++ b/src/decrepit/x509/x509_decrepit.c
@@ -0,0 +1,42 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/conf.h>
+#include <openssl/x509v3.h>
+
+
+X509_EXTENSION *X509V3_EXT_conf_nid(LHASH_OF(CONF_VALUE) *conf,
+                                    X509V3_CTX *ctx, int ext_nid, char *value) {
+  CONF *nconf = NULL;
+  LHASH_OF(CONF_VALUE) *orig_data = NULL;
+
+  if (conf != NULL) {
+    nconf = NCONF_new(NULL /* no method */);
+    if (nconf == NULL) {
+      return NULL;
+    }
+
+    orig_data = nconf->data;
+    nconf->data = conf;
+  }
+
+  X509_EXTENSION *ret = X509V3_EXT_nconf_nid(nconf, ctx, ext_nid, value);
+
+  if (nconf != NULL) {
+    nconf->data = orig_data;
+    NCONF_free(nconf);
+  }
+
+  return ret;
+}
diff --git a/src/decrepit/xts/xts.c b/src/decrepit/xts/xts.c
index 10a696d..2811445 100644
--- a/src/decrepit/xts/xts.c
+++ b/src/decrepit/xts/xts.c
@@ -73,7 +73,7 @@
 
   if (len < 16) return 0;
 
-  memcpy(tweak.c, iv, 16);
+  OPENSSL_memcpy(tweak.c, iv, 16);
 
   (*ctx->block2)(tweak.c, tweak.c, ctx->key2);
 
@@ -81,7 +81,7 @@
 
   while (len >= 16) {
 #if STRICT_ALIGNMENT
-    memcpy(scratch.c, inp, 16);
+    OPENSSL_memcpy(scratch.c, inp, 16);
     scratch.u[0] ^= tweak.u[0];
     scratch.u[1] ^= tweak.u[1];
 #else
@@ -92,7 +92,7 @@
 #if STRICT_ALIGNMENT
     scratch.u[0] ^= tweak.u[0];
     scratch.u[1] ^= tweak.u[1];
-    memcpy(out, scratch.c, 16);
+    OPENSSL_memcpy(out, scratch.c, 16);
 #else
     ((uint64_t *)out)[0] = scratch.u[0] ^= tweak.u[0];
     ((uint64_t *)out)[1] = scratch.u[1] ^= tweak.u[1];
@@ -121,7 +121,7 @@
     (*ctx->block1)(scratch.c, scratch.c, ctx->key1);
     scratch.u[0] ^= tweak.u[0];
     scratch.u[1] ^= tweak.u[1];
-    memcpy(out - 16, scratch.c, 16);
+    OPENSSL_memcpy(out - 16, scratch.c, 16);
   } else {
     union {
       uint64_t u[2];
@@ -135,7 +135,7 @@
     tweak1.u[0] = (tweak.u[0] << 1) ^ res;
     tweak1.u[1] = (tweak.u[1] << 1) | carry;
 #if STRICT_ALIGNMENT
-    memcpy(scratch.c, inp, 16);
+    OPENSSL_memcpy(scratch.c, inp, 16);
     scratch.u[0] ^= tweak1.u[0];
     scratch.u[1] ^= tweak1.u[1];
 #else
@@ -157,7 +157,7 @@
 #if STRICT_ALIGNMENT
     scratch.u[0] ^= tweak.u[0];
     scratch.u[1] ^= tweak.u[1];
-    memcpy(out, scratch.c, 16);
+    OPENSSL_memcpy(out, scratch.c, 16);
 #else
     ((uint64_t *)out)[0] = scratch.u[0] ^ tweak.u[0];
     ((uint64_t *)out)[1] = scratch.u[1] ^ tweak.u[1];
@@ -200,7 +200,7 @@
 
   if (iv) {
     xctx->xts.key2 = &xctx->ks2;
-    memcpy(ctx->iv, iv, 16);
+    OPENSSL_memcpy(ctx->iv, iv, 16);
   }
 
   return 1;
diff --git a/src/include/openssl/aead.h b/src/include/openssl/aead.h
index 092d2f6..bd655d6 100644
--- a/src/include/openssl/aead.h
+++ b/src/include/openssl/aead.h
@@ -64,7 +64,7 @@
  *
  * The "seal" and "open" operations are atomic - an entire message must be
  * encrypted or decrypted in a single call. Large messages may have to be split
- * up in order to accomodate this. When doing so, be mindful of the need not to
+ * up in order to accommodate this. When doing so, be mindful of the need not to
  * repeat nonces and the possibility that an attacker could duplicate, reorder
  * or drop message chunks. For example, using a single key for a given (large)
  * message and sealing chunks with nonces counting from zero would be secure as
@@ -82,10 +82,8 @@
  * permits implicit context to be authenticated but may be empty if not needed.
  *
  * The "seal" and "open" operations may work in-place if the |out| and |in|
- * arguments are equal. They may also be used to shift the data left inside the
- * same buffer if |out| is less than |in|. However, |out| may not point inside
- * the input data otherwise the input may be overwritten before it has been
- * read. This situation will cause an error.
+ * arguments are equal. Otherwise, if |out| and |in| alias, input data may be
+ * overwritten before it is read. This situation will cause an error.
  *
  * The "seal" and "open" operations return one on success and zero on error. */
 
@@ -102,25 +100,6 @@
  * Poly1305 as described in RFC 7539. */
 OPENSSL_EXPORT const EVP_AEAD *EVP_aead_chacha20_poly1305(void);
 
-/* EVP_aead_chacha20_poly1305_old is an AEAD built from ChaCha20 and
- * Poly1305 that is used in the experimental ChaCha20-Poly1305 TLS cipher
- * suites. */
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_chacha20_poly1305_old(void);
-
-/* EVP_aead_aes_128_key_wrap is AES-128 Key Wrap mode. This should never be
- * used except to interoperate with existing systems that use this mode.
- *
- * If the nonce is empty then the default nonce will be used, otherwise it must
- * be eight bytes long. The input must be a multiple of eight bytes long. No
- * additional data can be given to this mode. */
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_key_wrap(void);
-
-/* EVP_aead_aes_256_key_wrap is AES-256 in Key Wrap mode. This should never be
- * used except to interoperate with existing systems that use this mode.
- *
- * See |EVP_aead_aes_128_key_wrap| for details. */
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_key_wrap(void);
-
 /* EVP_aead_aes_128_ctr_hmac_sha256 is AES-128 in CTR mode with HMAC-SHA256 for
  * authentication. The nonce is 12 bytes; the bottom 32-bits are used as the
  * block counter, thus the maximum plaintext size is 64GB. */
@@ -130,54 +109,19 @@
  * authentication. See |EVP_aead_aes_128_ctr_hmac_sha256| for details. */
 OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_ctr_hmac_sha256(void);
 
+/* EVP_aead_aes_128_gcm_siv is AES-128 in GCM-SIV mode. See
+ * https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-02 */
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_gcm_siv(void);
+
+/* EVP_aead_aes_256_gcm_siv is AES-256 in GCM-SIV mode. See
+ * https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-02 */
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_gcm_siv(void);
+
 /* EVP_has_aes_hardware returns one if we enable hardware support for fast and
  * constant-time AES-GCM. */
 OPENSSL_EXPORT int EVP_has_aes_hardware(void);
 
 
-/* TLS-specific AEAD algorithms.
- *
- * These AEAD primitives do not meet the definition of generic AEADs. They are
- * all specific to TLS and should not be used outside of that context. They must
- * be initialized with |EVP_AEAD_CTX_init_with_direction|, are stateful, and may
- * not be used concurrently. Any nonces are used as IVs, so they must be
- * unpredictable. They only accept an |ad| parameter of length 11 (the standard
- * TLS one with length omitted). */
-
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_rc4_md5_tls(void);
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_rc4_sha1_tls(void);
-
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_tls(void);
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_tls_implicit_iv(void);
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_cbc_sha256_tls(void);
-
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_tls(void);
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_tls_implicit_iv(void);
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha256_tls(void);
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha384_tls(void);
-
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_tls(void);
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv(void);
-
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_null_sha1_tls(void);
-
-
-/* SSLv3-specific AEAD algorithms.
- *
- * These AEAD primitives do not meet the definition of generic AEADs. They are
- * all specific to SSLv3 and should not be used outside of that context. They
- * must be initialized with |EVP_AEAD_CTX_init_with_direction|, are stateful,
- * and may not be used concurrently. They only accept an |ad| parameter of
- * length 9 (the standard TLS one with length and version omitted). */
-
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_rc4_md5_ssl3(void);
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_rc4_sha1_ssl3(void);
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_ssl3(void);
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_ssl3(void);
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_ssl3(void);
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_null_sha1_ssl3(void);
-
-
 /* Utility functions. */
 
 /* EVP_AEAD_key_length returns the length, in bytes, of the keys used by
@@ -226,12 +170,6 @@
  * be used. */
 #define EVP_AEAD_DEFAULT_TAG_LENGTH 0
 
-/* evp_aead_direction_t denotes the direction of an AEAD operation. */
-enum evp_aead_direction_t {
-  evp_aead_open,
-  evp_aead_seal,
-};
-
 /* EVP_AEAD_CTX_zero sets an uninitialized |ctx| to the zero state. It must be
  * initialized with |EVP_AEAD_CTX_init| before use. It is safe, but not
  * necessary, to call |EVP_AEAD_CTX_cleanup| in this state. This may be used for
@@ -251,13 +189,6 @@
                                      const uint8_t *key, size_t key_len,
                                      size_t tag_len, ENGINE *impl);
 
-/* EVP_AEAD_CTX_init_with_direction calls |EVP_AEAD_CTX_init| for normal
- * AEADs. For TLS-specific and SSL3-specific AEADs, it initializes |ctx| for a
- * given direction. */
-OPENSSL_EXPORT int EVP_AEAD_CTX_init_with_direction(
-    EVP_AEAD_CTX *ctx, const EVP_AEAD *aead, const uint8_t *key, size_t key_len,
-    size_t tag_len, enum evp_aead_direction_t dir);
-
 /* EVP_AEAD_CTX_cleanup frees any data allocated by |ctx|. It is a no-op to
  * call |EVP_AEAD_CTX_cleanup| on a |EVP_AEAD_CTX| that has been |memset| to
  * all zeros. */
@@ -282,7 +213,7 @@
  * insufficient, zero will be returned. (In this case, |*out_len| is set to
  * zero.)
  *
- * If |in| and |out| alias then |out| must be <= |in|. */
+ * If |in| and |out| alias then |out| must be == |in|. */
 OPENSSL_EXPORT int EVP_AEAD_CTX_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
                                      size_t *out_len, size_t max_out_len,
                                      const uint8_t *nonce, size_t nonce_len,
@@ -307,20 +238,70 @@
  * insufficient, zero will be returned. (In this case, |*out_len| is set to
  * zero.)
  *
- * If |in| and |out| alias then |out| must be <= |in|. */
+ * If |in| and |out| alias then |out| must be == |in|. */
 OPENSSL_EXPORT int EVP_AEAD_CTX_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
                                      size_t *out_len, size_t max_out_len,
                                      const uint8_t *nonce, size_t nonce_len,
                                      const uint8_t *in, size_t in_len,
                                      const uint8_t *ad, size_t ad_len);
 
+/* EVP_AEAD_CTX_aead returns the underlying AEAD for |ctx|, or NULL if one has
+ * not been set. */
+OPENSSL_EXPORT const EVP_AEAD *EVP_AEAD_CTX_aead(const EVP_AEAD_CTX *ctx);
+
+
+/* TLS-specific AEAD algorithms.
+ *
+ * These AEAD primitives do not meet the definition of generic AEADs. They are
+ * all specific to TLS and should not be used outside of that context. They must
+ * be initialized with |EVP_AEAD_CTX_init_with_direction|, are stateful, and may
+ * not be used concurrently. Any nonces are used as IVs, so they must be
+ * unpredictable. They only accept an |ad| parameter of length 11 (the standard
+ * TLS one with length omitted). */
+
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_tls(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_tls_implicit_iv(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_cbc_sha256_tls(void);
+
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_tls(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_tls_implicit_iv(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha256_tls(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha384_tls(void);
+
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_tls(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv(void);
+
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_null_sha1_tls(void);
+
+
+/* SSLv3-specific AEAD algorithms.
+ *
+ * These AEAD primitives do not meet the definition of generic AEADs. They are
+ * all specific to SSLv3 and should not be used outside of that context. They
+ * must be initialized with |EVP_AEAD_CTX_init_with_direction|, are stateful,
+ * and may not be used concurrently. They only accept an |ad| parameter of
+ * length 9 (the standard TLS one with length and version omitted). */
+
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_ssl3(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_ssl3(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_ssl3(void);
+OPENSSL_EXPORT const EVP_AEAD *EVP_aead_null_sha1_ssl3(void);
+
 
 /* Obscure functions. */
 
-/* EVP_AEAD_CTX_get_rc4_state sets |*out_key| to point to an RC4 key structure.
- * It returns one on success or zero if |ctx| doesn't have an RC4 key. */
-OPENSSL_EXPORT int EVP_AEAD_CTX_get_rc4_state(const EVP_AEAD_CTX *ctx,
-                                              const RC4_KEY **out_key);
+/* evp_aead_direction_t denotes the direction of an AEAD operation. */
+enum evp_aead_direction_t {
+  evp_aead_open,
+  evp_aead_seal,
+};
+
+/* EVP_AEAD_CTX_init_with_direction calls |EVP_AEAD_CTX_init| for normal
+ * AEADs. For TLS-specific and SSL3-specific AEADs, it initializes |ctx| for a
+ * given direction. */
+OPENSSL_EXPORT int EVP_AEAD_CTX_init_with_direction(
+    EVP_AEAD_CTX *ctx, const EVP_AEAD *aead, const uint8_t *key, size_t key_len,
+    size_t tag_len, enum evp_aead_direction_t dir);
 
 /* EVP_AEAD_CTX_get_iv sets |*out_len| to the length of the IV for |ctx| and
  * sets |*out_iv| to point to that many bytes of the current IV. This is only
@@ -331,16 +312,23 @@
                                        const uint8_t **out_iv, size_t *out_len);
 
 
-/* Deprecated functions. */
-
-/* EVP_aead_chacha20_poly1305_rfc7539 calls |EVP_aead_chacha20_poly1305|.
- *
- * TODO(davidben): Remove this. */
-OPENSSL_EXPORT const EVP_AEAD *EVP_aead_chacha20_poly1305_rfc7539(void);
-
-
 #if defined(__cplusplus)
 }  /* extern C */
+
+#if !defined(BORINGSSL_NO_CXX)
+extern "C++" {
+
+namespace bssl {
+
+using ScopedEVP_AEAD_CTX =
+    internal::StackAllocated<EVP_AEAD_CTX, void, EVP_AEAD_CTX_zero,
+                             EVP_AEAD_CTX_cleanup>;
+
+}  // namespace bssl
+
+}  // extern C++
+#endif
+
 #endif
 
 #endif  /* OPENSSL_HEADER_AEAD_H */
diff --git a/src/include/openssl/aes.h b/src/include/openssl/aes.h
index ed060ff..2aef918 100644
--- a/src/include/openssl/aes.h
+++ b/src/include/openssl/aes.h
@@ -139,16 +139,28 @@
                                        uint8_t *ivec, int *num, int enc);
 
 
-/* Android compatibility section.
+/* AES key wrap.
  *
- * These functions are declared, temporarily, for Android because
- * wpa_supplicant will take a little time to sync with upstream. Outside of
- * Android they'll have no definition. */
+ * These functions implement AES Key Wrap mode, as defined in RFC 3394. They
+ * should never be used except to interoperate with existing systems that use
+ * this mode. */
 
-OPENSSL_EXPORT int AES_wrap_key(AES_KEY *key, const uint8_t *iv, uint8_t *out,
-                                const uint8_t *in, unsigned in_len);
-OPENSSL_EXPORT int AES_unwrap_key(AES_KEY *key, const uint8_t *iv, uint8_t *out,
-                                  const uint8_t *in, unsigned in_len);
+/* AES_wrap_key performs AES key wrap on |in| which must be a multiple of 8
+ * bytes. |iv| must point to an 8 byte value or be NULL to use the default IV.
+ * |key| must have been configured for encryption. On success, it writes
+ * |in_len| + 8 bytes to |out| and returns |in_len| + 8. Otherwise, it returns
+ * -1. */
+OPENSSL_EXPORT int AES_wrap_key(const AES_KEY *key, const uint8_t *iv,
+                                uint8_t *out, const uint8_t *in, size_t in_len);
+
+/* AES_unwrap_key performs AES key unwrap on |in| which must be a multiple of 8
+ * bytes. |iv| must point to an 8 byte value or be NULL to use the default IV.
+ * |key| must have been configured for decryption. On success, it writes
+ * |in_len| - 8 bytes to |out| and returns |in_len| - 8. Otherwise, it returns
+ * -1. */
+OPENSSL_EXPORT int AES_unwrap_key(const AES_KEY *key, const uint8_t *iv,
+                                  uint8_t *out, const uint8_t *in,
+                                  size_t in_len);
 
 
 #if defined(__cplusplus)
diff --git a/src/include/openssl/arm_arch.h b/src/include/openssl/arm_arch.h
index 1471db9..e7010f4 100644
--- a/src/include/openssl/arm_arch.h
+++ b/src/include/openssl/arm_arch.h
@@ -105,12 +105,6 @@
 /* ARMV7_NEON is true when a NEON unit is present in the current CPU. */
 #define ARMV7_NEON (1 << 0)
 
-/* ARMV7_NEON_FUNCTIONAL is true when the NEON unit doesn't contain subtle bugs.
- * The Poly1305 NEON code is known to trigger bugs in the NEON units of some
- * phones. If this bit isn't set then the Poly1305 NEON code won't be used.
- * See https://code.google.com/p/chromium/issues/detail?id=341598. */
-#define ARMV7_NEON_FUNCTIONAL (1 << 10)
-
 /* ARMV8_AES indicates support for hardware AES instructions. */
 #define ARMV8_AES (1 << 2)
 
diff --git a/src/include/openssl/asn1.h b/src/include/openssl/asn1.h
index 63bde18..8a4430a 100644
--- a/src/include/openssl/asn1.h
+++ b/src/include/openssl/asn1.h
@@ -85,6 +85,9 @@
 #define V_ASN1_ANY			-4	/* used in ASN1 template code */
 
 #define V_ASN1_NEG			0x100	/* negative flag */
+/* No supported universal tags may exceed this value, to avoid ambiguity with
+ * V_ASN1_NEG. */
+#define V_ASN1_MAX_UNIVERSAL		0xff
 
 #define V_ASN1_UNDEF			-1
 #define V_ASN1_EOC			0
@@ -202,6 +205,8 @@
 	int flags;	/* Should we free this one */
 	};
 
+DECLARE_STACK_OF(ASN1_OBJECT)
+
 #define ASN1_STRING_FLAG_BITS_LEFT 0x08 /* Set if 0x07 has bits left value */
 /* This indicates that the ASN1_STRING is not a real value but just a place
  * holder for the location where indefinite length constructed data should
@@ -241,12 +246,17 @@
 	{
 	unsigned char *enc;	/* DER encoding */
 	long len;		/* Length of encoding */
-	int modified;		 /* set to 1 if 'enc' is invalid */
+	int modified;		/* set to 1 if 'enc' is invalid */
+	/* alias_only is zero if |enc| owns the buffer that it points to
+	 * (although |enc| may still be NULL). If one, |enc| points into a
+	 * buffer that is owned elsewhere. */
+	unsigned alias_only:1;
+	/* alias_only_on_next_parse is one iff the next parsing operation
+	 * should avoid taking a copy of the input and rather set
+	 * |alias_only|. */
+	unsigned alias_only_on_next_parse:1;
 	} ASN1_ENCODING;
 
-/* Used with ASN1 LONG type: if a long is set to this it is omitted */
-#define ASN1_LONG_UNDEF	0x7fffffffL
-
 #define STABLE_FLAGS_MALLOC	0x01
 #define STABLE_NO_MASK		0x02
 #define DIRSTRING_TYPE	\
@@ -472,7 +482,7 @@
 
 DECLARE_ASN1_SET_OF(ASN1_INTEGER)
 
-typedef struct asn1_type_st
+struct asn1_type_st
 	{
 	int type;
 	union	{
@@ -500,7 +510,7 @@
 		ASN1_STRING *		sequence;
 		ASN1_VALUE *		asn1_value;
 		} value;
-	} ASN1_TYPE;
+    };
 
 DECLARE_ASN1_SET_OF(ASN1_TYPE)
 
@@ -571,9 +581,6 @@
 		(const ASN1_STRING *)a,(const ASN1_STRING *)b)
 #define M_ASN1_OCTET_STRING_set(a,b,c)	ASN1_STRING_set((ASN1_STRING *)a,b,c)
 #define M_ASN1_OCTET_STRING_print(a,b)	ASN1_STRING_print(a,(ASN1_STRING *)b)
-#define M_i2d_ASN1_OCTET_STRING(a,pp) \
-		i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_OCTET_STRING,\
-		V_ASN1_UNIVERSAL)
 
 #define B_ASN1_TIME \
 			B_ASN1_UTCTIME | \
@@ -606,59 +613,26 @@
 
 #define M_ASN1_PRINTABLE_new()	ASN1_STRING_type_new(V_ASN1_T61STRING)
 #define M_ASN1_PRINTABLE_free(a)	ASN1_STRING_free((ASN1_STRING *)a)
-#define M_i2d_ASN1_PRINTABLE(a,pp) i2d_ASN1_bytes((ASN1_STRING *)a,\
-		pp,a->type,V_ASN1_UNIVERSAL)
-#define M_d2i_ASN1_PRINTABLE(a,pp,l) \
-		d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l, \
-			B_ASN1_PRINTABLE)
 
 #define M_DIRECTORYSTRING_new() ASN1_STRING_type_new(V_ASN1_PRINTABLESTRING)
 #define M_DIRECTORYSTRING_free(a)	ASN1_STRING_free((ASN1_STRING *)a)
-#define M_i2d_DIRECTORYSTRING(a,pp) i2d_ASN1_bytes((ASN1_STRING *)a,\
-						pp,a->type,V_ASN1_UNIVERSAL)
-#define M_d2i_DIRECTORYSTRING(a,pp,l) \
-		d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l, \
-			B_ASN1_DIRECTORYSTRING)
 
 #define M_DISPLAYTEXT_new() ASN1_STRING_type_new(V_ASN1_VISIBLESTRING)
 #define M_DISPLAYTEXT_free(a) ASN1_STRING_free((ASN1_STRING *)a)
-#define M_i2d_DISPLAYTEXT(a,pp) i2d_ASN1_bytes((ASN1_STRING *)a,\
-						pp,a->type,V_ASN1_UNIVERSAL)
-#define M_d2i_DISPLAYTEXT(a,pp,l) \
-		d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l, \
-			B_ASN1_DISPLAYTEXT)
 
 #define M_ASN1_PRINTABLESTRING_new() (ASN1_PRINTABLESTRING *)\
 		ASN1_STRING_type_new(V_ASN1_PRINTABLESTRING)
 #define M_ASN1_PRINTABLESTRING_free(a)	ASN1_STRING_free((ASN1_STRING *)a)
-#define M_i2d_ASN1_PRINTABLESTRING(a,pp) \
-		i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_PRINTABLESTRING,\
-		V_ASN1_UNIVERSAL)
-#define M_d2i_ASN1_PRINTABLESTRING(a,pp,l) \
-		(ASN1_PRINTABLESTRING *)d2i_ASN1_type_bytes\
-		((ASN1_STRING **)a,pp,l,B_ASN1_PRINTABLESTRING)
 
 #define M_ASN1_T61STRING_new()	(ASN1_T61STRING *)\
 		ASN1_STRING_type_new(V_ASN1_T61STRING)
 #define M_ASN1_T61STRING_free(a)	ASN1_STRING_free((ASN1_STRING *)a)
-#define M_i2d_ASN1_T61STRING(a,pp) \
-		i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_T61STRING,\
-		V_ASN1_UNIVERSAL)
-#define M_d2i_ASN1_T61STRING(a,pp,l) \
-		(ASN1_T61STRING *)d2i_ASN1_type_bytes\
-		((ASN1_STRING **)a,pp,l,B_ASN1_T61STRING)
 
 #define M_ASN1_IA5STRING_new()	(ASN1_IA5STRING *)\
 		ASN1_STRING_type_new(V_ASN1_IA5STRING)
 #define M_ASN1_IA5STRING_free(a)	ASN1_STRING_free((ASN1_STRING *)a)
 #define M_ASN1_IA5STRING_dup(a)	\
 		(ASN1_IA5STRING *)ASN1_STRING_dup((const ASN1_STRING *)a)
-#define M_i2d_ASN1_IA5STRING(a,pp) \
-		i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_IA5STRING,\
-			V_ASN1_UNIVERSAL)
-#define M_d2i_ASN1_IA5STRING(a,pp,l) \
-		(ASN1_IA5STRING *)d2i_ASN1_type_bytes((ASN1_STRING **)a,pp,l,\
-			B_ASN1_IA5STRING)
 
 #define M_ASN1_UTCTIME_new()	(ASN1_UTCTIME *)\
 		ASN1_STRING_type_new(V_ASN1_UTCTIME)
@@ -681,56 +655,22 @@
 #define M_ASN1_GENERALSTRING_new()	(ASN1_GENERALSTRING *)\
 		ASN1_STRING_type_new(V_ASN1_GENERALSTRING)
 #define M_ASN1_GENERALSTRING_free(a)	ASN1_STRING_free((ASN1_STRING *)a)
-#define M_i2d_ASN1_GENERALSTRING(a,pp) \
-		i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_GENERALSTRING,\
-			V_ASN1_UNIVERSAL)
-#define M_d2i_ASN1_GENERALSTRING(a,pp,l) \
-		(ASN1_GENERALSTRING *)d2i_ASN1_type_bytes\
-		((ASN1_STRING **)a,pp,l,B_ASN1_GENERALSTRING)
 
 #define M_ASN1_UNIVERSALSTRING_new()	(ASN1_UNIVERSALSTRING *)\
 		ASN1_STRING_type_new(V_ASN1_UNIVERSALSTRING)
 #define M_ASN1_UNIVERSALSTRING_free(a)	ASN1_STRING_free((ASN1_STRING *)a)
-#define M_i2d_ASN1_UNIVERSALSTRING(a,pp) \
-		i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_UNIVERSALSTRING,\
-			V_ASN1_UNIVERSAL)
-#define M_d2i_ASN1_UNIVERSALSTRING(a,pp,l) \
-		(ASN1_UNIVERSALSTRING *)d2i_ASN1_type_bytes\
-		((ASN1_STRING **)a,pp,l,B_ASN1_UNIVERSALSTRING)
 
 #define M_ASN1_BMPSTRING_new()	(ASN1_BMPSTRING *)\
 		ASN1_STRING_type_new(V_ASN1_BMPSTRING)
 #define M_ASN1_BMPSTRING_free(a)	ASN1_STRING_free((ASN1_STRING *)a)
-#define M_i2d_ASN1_BMPSTRING(a,pp) \
-		i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_BMPSTRING,\
-			V_ASN1_UNIVERSAL)
-#define M_d2i_ASN1_BMPSTRING(a,pp,l) \
-		(ASN1_BMPSTRING *)d2i_ASN1_type_bytes\
-		((ASN1_STRING **)a,pp,l,B_ASN1_BMPSTRING)
 
 #define M_ASN1_VISIBLESTRING_new()	(ASN1_VISIBLESTRING *)\
 		ASN1_STRING_type_new(V_ASN1_VISIBLESTRING)
 #define M_ASN1_VISIBLESTRING_free(a)	ASN1_STRING_free((ASN1_STRING *)a)
-#define M_i2d_ASN1_VISIBLESTRING(a,pp) \
-		i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_VISIBLESTRING,\
-			V_ASN1_UNIVERSAL)
-#define M_d2i_ASN1_VISIBLESTRING(a,pp,l) \
-		(ASN1_VISIBLESTRING *)d2i_ASN1_type_bytes\
-		((ASN1_STRING **)a,pp,l,B_ASN1_VISIBLESTRING)
 
 #define M_ASN1_UTF8STRING_new()	(ASN1_UTF8STRING *)\
 		ASN1_STRING_type_new(V_ASN1_UTF8STRING)
 #define M_ASN1_UTF8STRING_free(a)	ASN1_STRING_free((ASN1_STRING *)a)
-#define M_i2d_ASN1_UTF8STRING(a,pp) \
-		i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_UTF8STRING,\
-			V_ASN1_UNIVERSAL)
-#define M_d2i_ASN1_UTF8STRING(a,pp,l) \
-		(ASN1_UTF8STRING *)d2i_ASN1_type_bytes\
-		((ASN1_STRING **)a,pp,l,B_ASN1_UTF8STRING)
-
-  /* for the is_set parameter to i2d_ASN1_SET */
-#define IS_SEQUENCE	0
-#define IS_SET		1
 
 DECLARE_ASN1_FUNCTIONS_fname(ASN1_TYPE, ASN1_ANY, ASN1_TYPE)
 
@@ -839,19 +779,9 @@
 OPENSSL_EXPORT ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t, ASN1_GENERALIZEDTIME **out);
 OPENSSL_EXPORT int ASN1_TIME_set_string(ASN1_TIME *s, const char *str);
 
-OPENSSL_EXPORT int i2d_ASN1_SET(STACK_OF(OPENSSL_BLOCK) *a, unsigned char **pp, i2d_of_void *i2d, int ex_tag, int ex_class, int is_set);
-OPENSSL_EXPORT STACK_OF(OPENSSL_BLOCK) *d2i_ASN1_SET(STACK_OF(OPENSSL_BLOCK) **a,
-			      const unsigned char **pp,
-			      long length, d2i_of_void *d2i,
-			      void (*free_func)(OPENSSL_BLOCK), int ex_tag,
-			      int ex_class);
-
 OPENSSL_EXPORT int i2a_ASN1_INTEGER(BIO *bp, ASN1_INTEGER *a);
-OPENSSL_EXPORT int a2i_ASN1_INTEGER(BIO *bp,ASN1_INTEGER *bs,char *buf,int size);
 OPENSSL_EXPORT int i2a_ASN1_ENUMERATED(BIO *bp, ASN1_ENUMERATED *a);
-OPENSSL_EXPORT int a2i_ASN1_ENUMERATED(BIO *bp,ASN1_ENUMERATED *bs,char *buf,int size);
 OPENSSL_EXPORT int i2a_ASN1_OBJECT(BIO *bp,ASN1_OBJECT *a);
-OPENSSL_EXPORT int a2i_ASN1_STRING(BIO *bp,ASN1_STRING *bs,char *buf,int size);
 OPENSSL_EXPORT int i2a_ASN1_STRING(BIO *bp, ASN1_STRING *a, int type);
 OPENSSL_EXPORT int i2t_ASN1_OBJECT(char *buf,int buf_len,ASN1_OBJECT *a);
 
@@ -872,11 +802,7 @@
 /* given a string, return the correct type, max is the maximum length */
 OPENSSL_EXPORT int ASN1_PRINTABLE_type(const unsigned char *s, int max);
 
-OPENSSL_EXPORT int i2d_ASN1_bytes(ASN1_STRING *a, unsigned char **pp, int tag, int xclass);
-OPENSSL_EXPORT ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, const unsigned char **pp, long length, int Ptag, int Pclass);
 OPENSSL_EXPORT unsigned long ASN1_tag2bit(int tag);
-/* type is one or more of the B_ASN1_ values. */
-OPENSSL_EXPORT ASN1_STRING *d2i_ASN1_type_bytes(ASN1_STRING **a,const unsigned char **pp, long length,int type);
 
 /* PARSING */
 OPENSSL_EXPORT int asn1_Finish(ASN1_CTX *c);
@@ -966,9 +892,6 @@
 OPENSSL_EXPORT int ASN1_TIME_print(BIO *fp, const ASN1_TIME *a);
 OPENSSL_EXPORT int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v);
 OPENSSL_EXPORT int ASN1_STRING_print_ex(BIO *out, ASN1_STRING *str, unsigned long flags);
-OPENSSL_EXPORT int ASN1_bn_print(BIO *bp, const char *number, const BIGNUM *num, unsigned char *buf, int off);
-OPENSSL_EXPORT int ASN1_parse(BIO *bp,const unsigned char *pp,long len,int indent);
-OPENSSL_EXPORT int ASN1_parse_dump(BIO *bp,const unsigned char *pp,long len,int indent,int dump);
 OPENSSL_EXPORT const char *ASN1_tag2str(int tag);
 
 /* Used to load and write netscape format cert */
@@ -977,16 +900,7 @@
 
 int ASN1_UNIVERSALSTRING_to_string(ASN1_UNIVERSALSTRING *s);
 
-OPENSSL_EXPORT STACK_OF(OPENSSL_BLOCK) *ASN1_seq_unpack(const unsigned char *buf, int len, d2i_of_void *d2i, void (*free_func)(OPENSSL_BLOCK));
-OPENSSL_EXPORT unsigned char *ASN1_seq_pack(STACK_OF(OPENSSL_BLOCK) *safes, i2d_of_void *i2d, unsigned char **buf, int *len );
-OPENSSL_EXPORT void *ASN1_unpack_string(ASN1_STRING *oct, d2i_of_void *d2i);
 OPENSSL_EXPORT void *ASN1_item_unpack(ASN1_STRING *oct, const ASN1_ITEM *it);
-OPENSSL_EXPORT ASN1_STRING *ASN1_pack_string(void *obj, i2d_of_void *i2d, ASN1_OCTET_STRING **oct);
-
-#define ASN1_pack_string_of(type,obj,i2d,oct) \
-    (ASN1_pack_string(CHECKED_PTR_OF(type, obj), \
-		      CHECKED_I2D_OF(type, i2d), \
-		      oct))
 
 OPENSSL_EXPORT ASN1_STRING *ASN1_item_pack(void *obj, const ASN1_ITEM *it, ASN1_OCTET_STRING **oct);
 
@@ -1010,70 +924,27 @@
 OPENSSL_EXPORT int ASN1_item_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it);
 OPENSSL_EXPORT int ASN1_item_ndef_i2d(ASN1_VALUE *val, unsigned char **out, const ASN1_ITEM *it);
 
-OPENSSL_EXPORT void ASN1_add_oid_module(void);
-
 OPENSSL_EXPORT ASN1_TYPE *ASN1_generate_nconf(char *str, CONF *nconf);
 OPENSSL_EXPORT ASN1_TYPE *ASN1_generate_v3(char *str, X509V3_CTX *cnf);
 
-/* ASN1 Print flags */
-
-/* Indicate missing OPTIONAL fields */
-#define ASN1_PCTX_FLAGS_SHOW_ABSENT		0x001	
-/* Mark start and end of SEQUENCE */
-#define ASN1_PCTX_FLAGS_SHOW_SEQUENCE		0x002
-/* Mark start and end of SEQUENCE/SET OF */
-#define ASN1_PCTX_FLAGS_SHOW_SSOF		0x004
-/* Show the ASN1 type of primitives */
-#define ASN1_PCTX_FLAGS_SHOW_TYPE		0x008
-/* Don't show ASN1 type of ANY */
-#define ASN1_PCTX_FLAGS_NO_ANY_TYPE		0x010
-/* Don't show ASN1 type of MSTRINGs */
-#define ASN1_PCTX_FLAGS_NO_MSTRING_TYPE		0x020
-/* Don't show field names in SEQUENCE */
-#define ASN1_PCTX_FLAGS_NO_FIELD_NAME		0x040
-/* Show structure names of each SEQUENCE field */
-#define ASN1_PCTX_FLAGS_SHOW_FIELD_STRUCT_NAME	0x080
-/* Don't show structure name even at top level */
-#define ASN1_PCTX_FLAGS_NO_STRUCT_NAME		0x100
-
-OPENSSL_EXPORT int ASN1_item_print(BIO *out, ASN1_VALUE *ifld, int indent, const ASN1_ITEM *it, const ASN1_PCTX *pctx);
-OPENSSL_EXPORT ASN1_PCTX *ASN1_PCTX_new(void);
-OPENSSL_EXPORT void ASN1_PCTX_free(ASN1_PCTX *p);
-OPENSSL_EXPORT unsigned long ASN1_PCTX_get_flags(ASN1_PCTX *p);
-OPENSSL_EXPORT void ASN1_PCTX_set_flags(ASN1_PCTX *p, unsigned long flags);
-OPENSSL_EXPORT unsigned long ASN1_PCTX_get_nm_flags(ASN1_PCTX *p);
-OPENSSL_EXPORT void ASN1_PCTX_set_nm_flags(ASN1_PCTX *p, unsigned long flags);
-OPENSSL_EXPORT unsigned long ASN1_PCTX_get_cert_flags(ASN1_PCTX *p);
-OPENSSL_EXPORT void ASN1_PCTX_set_cert_flags(ASN1_PCTX *p, unsigned long flags);
-OPENSSL_EXPORT unsigned long ASN1_PCTX_get_oid_flags(ASN1_PCTX *p);
-OPENSSL_EXPORT void ASN1_PCTX_set_oid_flags(ASN1_PCTX *p, unsigned long flags);
-OPENSSL_EXPORT unsigned long ASN1_PCTX_get_str_flags(ASN1_PCTX *p);
-OPENSSL_EXPORT void ASN1_PCTX_set_str_flags(ASN1_PCTX *p, unsigned long flags);
-
-OPENSSL_EXPORT const BIO_METHOD *BIO_f_asn1(void);
-
-OPENSSL_EXPORT BIO *BIO_new_NDEF(BIO *out, ASN1_VALUE *val, const ASN1_ITEM *it);
-
-OPENSSL_EXPORT int i2d_ASN1_bio_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags, const ASN1_ITEM *it);
-OPENSSL_EXPORT int PEM_write_bio_ASN1_stream(BIO *out, ASN1_VALUE *val, BIO *in, int flags, const char *hdr, const ASN1_ITEM *it);
-OPENSSL_EXPORT ASN1_VALUE *SMIME_read_ASN1(BIO *bio, BIO **bcont, const ASN1_ITEM *it);
-OPENSSL_EXPORT int SMIME_crlf_copy(BIO *in, BIO *out, int flags);
-OPENSSL_EXPORT int SMIME_text(BIO *in, BIO *out);
-
-/* BEGIN ERROR CODES */
-/* The following lines are auto generated by the script mkerr.pl. Any changes
- * made after this point may be overwritten when the script is next run.
- */
-void ERR_load_ASN1_strings(void);
-
-typedef int asn1_ps_func(BIO *b, unsigned char **pbuf, int *plen, void *parg);
-OPENSSL_EXPORT int BIO_asn1_set_prefix(BIO *b, asn1_ps_func *prefix, asn1_ps_func *prefix_free);
-OPENSSL_EXPORT int BIO_asn1_get_prefix(BIO *b, asn1_ps_func **pprefix, asn1_ps_func **pprefix_free);
-OPENSSL_EXPORT int BIO_asn1_set_suffix(BIO *b, asn1_ps_func *suffix, asn1_ps_func *suffix_free);
-OPENSSL_EXPORT int BIO_asn1_get_suffix(BIO *b, asn1_ps_func **psuffix, asn1_ps_func **psuffix_free);
 
 #ifdef  __cplusplus
 }
+
+extern "C++" {
+
+namespace bssl {
+
+BORINGSSL_MAKE_STACK_DELETER(ASN1_OBJECT, ASN1_OBJECT_free)
+
+BORINGSSL_MAKE_DELETER(ASN1_OBJECT, ASN1_OBJECT_free)
+BORINGSSL_MAKE_DELETER(ASN1_STRING, ASN1_STRING_free)
+BORINGSSL_MAKE_DELETER(ASN1_TYPE, ASN1_TYPE_free)
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #define ASN1_R_ASN1_LENGTH_MISMATCH 100
@@ -1084,84 +955,89 @@
 #define ASN1_R_BN_LIB 105
 #define ASN1_R_BOOLEAN_IS_WRONG_LENGTH 106
 #define ASN1_R_BUFFER_TOO_SMALL 107
-#define ASN1_R_DECODE_ERROR 108
-#define ASN1_R_DEPTH_EXCEEDED 109
-#define ASN1_R_ENCODE_ERROR 110
-#define ASN1_R_ERROR_GETTING_TIME 111
-#define ASN1_R_EXPECTING_AN_ASN1_SEQUENCE 112
-#define ASN1_R_EXPECTING_AN_INTEGER 113
-#define ASN1_R_EXPECTING_AN_OBJECT 114
-#define ASN1_R_EXPECTING_A_BOOLEAN 115
-#define ASN1_R_EXPECTING_A_TIME 116
-#define ASN1_R_EXPLICIT_LENGTH_MISMATCH 117
-#define ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED 118
-#define ASN1_R_FIELD_MISSING 119
-#define ASN1_R_FIRST_NUM_TOO_LARGE 120
-#define ASN1_R_HEADER_TOO_LONG 121
-#define ASN1_R_ILLEGAL_BITSTRING_FORMAT 122
-#define ASN1_R_ILLEGAL_BOOLEAN 123
-#define ASN1_R_ILLEGAL_CHARACTERS 124
-#define ASN1_R_ILLEGAL_FORMAT 125
-#define ASN1_R_ILLEGAL_HEX 126
-#define ASN1_R_ILLEGAL_IMPLICIT_TAG 127
-#define ASN1_R_ILLEGAL_INTEGER 128
-#define ASN1_R_ILLEGAL_NESTED_TAGGING 129
-#define ASN1_R_ILLEGAL_NULL 130
-#define ASN1_R_ILLEGAL_NULL_VALUE 131
-#define ASN1_R_ILLEGAL_OBJECT 132
-#define ASN1_R_ILLEGAL_OPTIONAL_ANY 133
-#define ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE 134
-#define ASN1_R_ILLEGAL_TAGGED_ANY 135
-#define ASN1_R_ILLEGAL_TIME_VALUE 136
-#define ASN1_R_INTEGER_NOT_ASCII_FORMAT 137
-#define ASN1_R_INTEGER_TOO_LARGE_FOR_LONG 138
-#define ASN1_R_INVALID_BIT_STRING_BITS_LEFT 139
-#define ASN1_R_INVALID_BMPSTRING_LENGTH 140
-#define ASN1_R_INVALID_DIGIT 141
-#define ASN1_R_INVALID_MODIFIER 142
-#define ASN1_R_INVALID_NUMBER 143
-#define ASN1_R_INVALID_OBJECT_ENCODING 144
-#define ASN1_R_INVALID_SEPARATOR 145
-#define ASN1_R_INVALID_TIME_FORMAT 146
-#define ASN1_R_INVALID_UNIVERSALSTRING_LENGTH 147
-#define ASN1_R_INVALID_UTF8STRING 148
-#define ASN1_R_LIST_ERROR 149
-#define ASN1_R_MISSING_ASN1_EOS 150
-#define ASN1_R_MISSING_EOC 151
-#define ASN1_R_MISSING_SECOND_NUMBER 152
-#define ASN1_R_MISSING_VALUE 153
-#define ASN1_R_MSTRING_NOT_UNIVERSAL 154
-#define ASN1_R_MSTRING_WRONG_TAG 155
-#define ASN1_R_NESTED_ASN1_ERROR 156
-#define ASN1_R_NESTED_ASN1_STRING 157
-#define ASN1_R_NON_HEX_CHARACTERS 158
-#define ASN1_R_NOT_ASCII_FORMAT 159
-#define ASN1_R_NOT_ENOUGH_DATA 160
-#define ASN1_R_NO_MATCHING_CHOICE_TYPE 161
-#define ASN1_R_NULL_IS_WRONG_LENGTH 162
-#define ASN1_R_OBJECT_NOT_ASCII_FORMAT 163
-#define ASN1_R_ODD_NUMBER_OF_CHARS 164
-#define ASN1_R_SECOND_NUMBER_TOO_LARGE 165
-#define ASN1_R_SEQUENCE_LENGTH_MISMATCH 166
-#define ASN1_R_SEQUENCE_NOT_CONSTRUCTED 167
-#define ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG 168
-#define ASN1_R_SHORT_LINE 169
-#define ASN1_R_STREAMING_NOT_SUPPORTED 170
-#define ASN1_R_STRING_TOO_LONG 171
-#define ASN1_R_STRING_TOO_SHORT 172
-#define ASN1_R_TAG_VALUE_TOO_HIGH 173
-#define ASN1_R_TIME_NOT_ASCII_FORMAT 174
-#define ASN1_R_TOO_LONG 175
-#define ASN1_R_TYPE_NOT_CONSTRUCTED 176
-#define ASN1_R_TYPE_NOT_PRIMITIVE 177
-#define ASN1_R_UNEXPECTED_EOC 178
-#define ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH 179
-#define ASN1_R_UNKNOWN_FORMAT 180
-#define ASN1_R_UNKNOWN_TAG 181
-#define ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE 182
-#define ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE 183
-#define ASN1_R_UNSUPPORTED_TYPE 184
-#define ASN1_R_WRONG_TAG 185
-#define ASN1_R_WRONG_TYPE 186
+#define ASN1_R_CONTEXT_NOT_INITIALISED 108
+#define ASN1_R_DECODE_ERROR 109
+#define ASN1_R_DEPTH_EXCEEDED 110
+#define ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED 111
+#define ASN1_R_ENCODE_ERROR 112
+#define ASN1_R_ERROR_GETTING_TIME 113
+#define ASN1_R_EXPECTING_AN_ASN1_SEQUENCE 114
+#define ASN1_R_EXPECTING_AN_INTEGER 115
+#define ASN1_R_EXPECTING_AN_OBJECT 116
+#define ASN1_R_EXPECTING_A_BOOLEAN 117
+#define ASN1_R_EXPECTING_A_TIME 118
+#define ASN1_R_EXPLICIT_LENGTH_MISMATCH 119
+#define ASN1_R_EXPLICIT_TAG_NOT_CONSTRUCTED 120
+#define ASN1_R_FIELD_MISSING 121
+#define ASN1_R_FIRST_NUM_TOO_LARGE 122
+#define ASN1_R_HEADER_TOO_LONG 123
+#define ASN1_R_ILLEGAL_BITSTRING_FORMAT 124
+#define ASN1_R_ILLEGAL_BOOLEAN 125
+#define ASN1_R_ILLEGAL_CHARACTERS 126
+#define ASN1_R_ILLEGAL_FORMAT 127
+#define ASN1_R_ILLEGAL_HEX 128
+#define ASN1_R_ILLEGAL_IMPLICIT_TAG 129
+#define ASN1_R_ILLEGAL_INTEGER 130
+#define ASN1_R_ILLEGAL_NESTED_TAGGING 131
+#define ASN1_R_ILLEGAL_NULL 132
+#define ASN1_R_ILLEGAL_NULL_VALUE 133
+#define ASN1_R_ILLEGAL_OBJECT 134
+#define ASN1_R_ILLEGAL_OPTIONAL_ANY 135
+#define ASN1_R_ILLEGAL_OPTIONS_ON_ITEM_TEMPLATE 136
+#define ASN1_R_ILLEGAL_TAGGED_ANY 137
+#define ASN1_R_ILLEGAL_TIME_VALUE 138
+#define ASN1_R_INTEGER_NOT_ASCII_FORMAT 139
+#define ASN1_R_INTEGER_TOO_LARGE_FOR_LONG 140
+#define ASN1_R_INVALID_BIT_STRING_BITS_LEFT 141
+#define ASN1_R_INVALID_BMPSTRING_LENGTH 142
+#define ASN1_R_INVALID_DIGIT 143
+#define ASN1_R_INVALID_MODIFIER 144
+#define ASN1_R_INVALID_NUMBER 145
+#define ASN1_R_INVALID_OBJECT_ENCODING 146
+#define ASN1_R_INVALID_SEPARATOR 147
+#define ASN1_R_INVALID_TIME_FORMAT 148
+#define ASN1_R_INVALID_UNIVERSALSTRING_LENGTH 149
+#define ASN1_R_INVALID_UTF8STRING 150
+#define ASN1_R_LIST_ERROR 151
+#define ASN1_R_MISSING_ASN1_EOS 152
+#define ASN1_R_MISSING_EOC 153
+#define ASN1_R_MISSING_SECOND_NUMBER 154
+#define ASN1_R_MISSING_VALUE 155
+#define ASN1_R_MSTRING_NOT_UNIVERSAL 156
+#define ASN1_R_MSTRING_WRONG_TAG 157
+#define ASN1_R_NESTED_ASN1_ERROR 158
+#define ASN1_R_NESTED_ASN1_STRING 159
+#define ASN1_R_NON_HEX_CHARACTERS 160
+#define ASN1_R_NOT_ASCII_FORMAT 161
+#define ASN1_R_NOT_ENOUGH_DATA 162
+#define ASN1_R_NO_MATCHING_CHOICE_TYPE 163
+#define ASN1_R_NULL_IS_WRONG_LENGTH 164
+#define ASN1_R_OBJECT_NOT_ASCII_FORMAT 165
+#define ASN1_R_ODD_NUMBER_OF_CHARS 166
+#define ASN1_R_SECOND_NUMBER_TOO_LARGE 167
+#define ASN1_R_SEQUENCE_LENGTH_MISMATCH 168
+#define ASN1_R_SEQUENCE_NOT_CONSTRUCTED 169
+#define ASN1_R_SEQUENCE_OR_SET_NEEDS_CONFIG 170
+#define ASN1_R_SHORT_LINE 171
+#define ASN1_R_STREAMING_NOT_SUPPORTED 172
+#define ASN1_R_STRING_TOO_LONG 173
+#define ASN1_R_STRING_TOO_SHORT 174
+#define ASN1_R_TAG_VALUE_TOO_HIGH 175
+#define ASN1_R_TIME_NOT_ASCII_FORMAT 176
+#define ASN1_R_TOO_LONG 177
+#define ASN1_R_TYPE_NOT_CONSTRUCTED 178
+#define ASN1_R_TYPE_NOT_PRIMITIVE 179
+#define ASN1_R_UNEXPECTED_EOC 180
+#define ASN1_R_UNIVERSALSTRING_IS_WRONG_LENGTH 181
+#define ASN1_R_UNKNOWN_FORMAT 182
+#define ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM 183
+#define ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM 184
+#define ASN1_R_UNKNOWN_TAG 185
+#define ASN1_R_UNSUPPORTED_ANY_DEFINED_BY_TYPE 186
+#define ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE 187
+#define ASN1_R_UNSUPPORTED_TYPE 188
+#define ASN1_R_WRONG_PUBLIC_KEY_TYPE 189
+#define ASN1_R_WRONG_TAG 190
+#define ASN1_R_WRONG_TYPE 191
 
 #endif
diff --git a/src/include/openssl/asn1_mac.h b/src/include/openssl/asn1_mac.h
index f319bee..666e569 100644
--- a/src/include/openssl/asn1_mac.h
+++ b/src/include/openssl/asn1_mac.h
@@ -1,75 +1,18 @@
-/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
+/* Copyright (c) 2016, Google Inc.
  *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- * 
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to.  The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- * 
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- * 
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *    "This product includes cryptographic software written by
- *     Eric Young (eay@cryptsoft.com)"
- *    The word 'cryptographic' can be left out if the rouines from the library
- *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from 
- *    the apps directory (application code) you must include an acknowledgement:
- *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- * 
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * 
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed.  i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- */
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
 
-#ifndef HEADER_ASN1_MAC_H
-#define HEADER_ASN1_MAC_H
+/* This header is provided in order to make compiling against code that expects
+   OpenSSL easier. */
 
-#include <openssl/asn1.h>
-
-#ifdef  __cplusplus
-extern "C" {
-#endif
-
-
-OPENSSL_EXPORT int asn1_GetSequence(ASN1_const_CTX *c, long *length);
-
-
-#ifdef  __cplusplus
-}
-#endif
-
-#endif
+#include "asn1.h"
diff --git a/src/include/openssl/asn1t.h b/src/include/openssl/asn1t.h
index b43c332..29e2de7 100644
--- a/src/include/openssl/asn1t.h
+++ b/src/include/openssl/asn1t.h
@@ -631,6 +631,7 @@
 	ASN1_ex_free_func *asn1_ex_clear;
 	ASN1_ex_d2i *asn1_ex_d2i;
 	ASN1_ex_i2d *asn1_ex_i2d;
+	/* asn1_ex_print is unused. */
 	ASN1_ex_print_func *asn1_ex_print;
 } ASN1_EXTERN_FUNCS;
 
@@ -835,17 +836,6 @@
         return ASN1_item_dup(ASN1_ITEM_rptr(stname), x); \
         }
 
-#define IMPLEMENT_ASN1_PRINT_FUNCTION(stname) \
-	IMPLEMENT_ASN1_PRINT_FUNCTION_fname(stname, stname, stname)
-
-#define IMPLEMENT_ASN1_PRINT_FUNCTION_fname(stname, itname, fname) \
-	int fname##_print_ctx(BIO *out, stname *x, int indent, \
-						const ASN1_PCTX *pctx) \
-	{ \
-		return ASN1_item_print(out, (ASN1_VALUE *)x, indent, \
-			ASN1_ITEM_rptr(itname), pctx); \
-	} 
-
 #define IMPLEMENT_ASN1_FUNCTIONS_const(name) \
 		IMPLEMENT_ASN1_FUNCTIONS_const_fname(name, name, name)
 
@@ -859,10 +849,6 @@
 DECLARE_ASN1_ITEM(ASN1_TBOOLEAN)
 DECLARE_ASN1_ITEM(ASN1_FBOOLEAN)
 DECLARE_ASN1_ITEM(ASN1_SEQUENCE)
-DECLARE_ASN1_ITEM(CBIGNUM)
-DECLARE_ASN1_ITEM(BIGNUM)
-DECLARE_ASN1_ITEM(LONG)
-DECLARE_ASN1_ITEM(ZLONG)
 
 DECLARE_STACK_OF(ASN1_VALUE)
 
diff --git a/src/include/openssl/base.h b/src/include/openssl/base.h
index 47b3ccb..a9d1ec5 100644
--- a/src/include/openssl/base.h
+++ b/src/include/openssl/base.h
@@ -60,7 +60,16 @@
 #include <stdint.h>
 #include <sys/types.h>
 
-#include <openssl/opensslfeatures.h>
+#if defined(__MINGW32__)
+/* stdio.h is needed on MinGW for __MINGW_PRINTF_FORMAT. */
+#include <stdio.h>
+#endif
+
+#include <openssl/opensslconf.h>
+
+#if defined(BORINGSSL_PREFIX)
+#include <boringssl_prefix_symbols.h>
+#endif
 
 #if defined(__cplusplus)
 extern "C" {
@@ -79,8 +88,9 @@
 #elif defined(__arm) || defined(__arm__) || defined(_M_ARM)
 #define OPENSSL_32_BIT
 #define OPENSSL_ARM
-#elif defined(__PPC64__) || defined(__powerpc64__)
+#elif (defined(__PPC64__) || defined(__powerpc64__)) && defined(_LITTLE_ENDIAN)
 #define OPENSSL_64_BIT
+#define OPENSSL_PPC64LE
 #elif defined(__mips__) && !defined(__LP64__)
 #define OPENSSL_32_BIT
 #define OPENSSL_MIPS
@@ -90,6 +100,8 @@
 #elif defined(__pnacl__)
 #define OPENSSL_32_BIT
 #define OPENSSL_PNACL
+#elif defined(__myriad2__)
+#define OPENSSL_32_BIT
 #else
 #error "Unknown target CPU"
 #endif
@@ -102,16 +114,35 @@
 #define OPENSSL_WINDOWS
 #endif
 
+#if defined(__linux__)
+#define OPENSSL_LINUX
+#endif
+
+#if defined(__Fuchsia__)
+#define OPENSSL_FUCHSIA
+#endif
+
 #if defined(TRUSTY)
 #define OPENSSL_TRUSTY
 #define OPENSSL_NO_THREADS
 #endif
 
 #define OPENSSL_IS_BORINGSSL
-#define BORINGSSL_201510
-#define OPENSSL_VERSION_NUMBER 0x10002000
+#define BORINGSSL_201512
+#define BORINGSSL_201603
+#define OPENSSL_VERSION_NUMBER 0x100020af
 #define SSLEAY_VERSION_NUMBER OPENSSL_VERSION_NUMBER
 
+/* BORINGSSL_API_VERSION is a positive integer that increments as BoringSSL
+ * changes over time. The value itself is not meaningful. It will be incremented
+ * whenever is convenient to coordinate an API change with consumers. This will
+ * not denote any special point in development.
+ *
+ * A consumer may use this symbol in the preprocessor to temporarily build
+ * against multiple revisions of BoringSSL at the same time. It is not
+ * recommended to do so for longer than is necessary. */
+#define BORINGSSL_API_VERSION 3
+
 #if defined(BORINGSSL_SHARED_LIBRARY)
 
 #if defined(OPENSSL_WINDOWS)
@@ -138,6 +169,35 @@
 
 #endif  /* defined(BORINGSSL_SHARED_LIBRARY) */
 
+
+#if defined(__GNUC__)
+/* MinGW has two different printf implementations. Ensure the format macro
+ * matches the selected implementation. See
+ * https://sourceforge.net/p/mingw-w64/wiki2/gnu%20printf/. */
+#if defined(__MINGW_PRINTF_FORMAT)
+#define OPENSSL_PRINTF_FORMAT_FUNC(string_index, first_to_check) \
+  __attribute__(                                                 \
+      (__format__(__MINGW_PRINTF_FORMAT, string_index, first_to_check)))
+#else
+#define OPENSSL_PRINTF_FORMAT_FUNC(string_index, first_to_check) \
+  __attribute__((__format__(__printf__, string_index, first_to_check)))
+#endif
+#else
+#define OPENSSL_PRINTF_FORMAT_FUNC(string_index, first_to_check)
+#endif
+
+/* OPENSSL_MSVC_PRAGMA emits a pragma on MSVC and nothing on other compilers. */
+#if defined(_MSC_VER)
+#define OPENSSL_MSVC_PRAGMA(arg) __pragma(arg)
+#else
+#define OPENSSL_MSVC_PRAGMA(arg)
+#endif
+
+#if defined(BORINGSSL_UNSAFE_FUZZER_MODE) && \
+    !defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE)
+#define BORINGSSL_UNSAFE_DETERMINISTIC_MODE
+#endif
+
 /* CRYPTO_THREADID is a dummy value. */
 typedef int CRYPTO_THREADID;
 
@@ -162,21 +222,23 @@
 typedef struct asn1_string_st ASN1_UTCTIME;
 typedef struct asn1_string_st ASN1_UTF8STRING;
 typedef struct asn1_string_st ASN1_VISIBLESTRING;
+typedef struct asn1_type_st ASN1_TYPE;
 
 typedef struct AUTHORITY_KEYID_st AUTHORITY_KEYID;
+typedef struct BASIC_CONSTRAINTS_st BASIC_CONSTRAINTS;
 typedef struct DIST_POINT_st DIST_POINT;
+typedef struct DSA_SIG_st DSA_SIG;
 typedef struct ISSUING_DIST_POINT_st ISSUING_DIST_POINT;
 typedef struct NAME_CONSTRAINTS_st NAME_CONSTRAINTS;
 typedef struct Netscape_certificate_sequence NETSCAPE_CERT_SEQUENCE;
 typedef struct Netscape_spkac_st NETSCAPE_SPKAC;
 typedef struct Netscape_spki_st NETSCAPE_SPKI;
-typedef struct PBE2PARAM_st PBE2PARAM;
-typedef struct PBEPARAM_st PBEPARAM;
-typedef struct PBKDF2PARAM_st PBKDF2PARAM;
+typedef struct RIPEMD160state_st RIPEMD160_CTX;
 typedef struct X509_POLICY_CACHE_st X509_POLICY_CACHE;
 typedef struct X509_POLICY_LEVEL_st X509_POLICY_LEVEL;
 typedef struct X509_POLICY_NODE_st X509_POLICY_NODE;
 typedef struct X509_POLICY_TREE_st X509_POLICY_TREE;
+typedef struct X509_VERIFY_PARAM_st X509_VERIFY_PARAM;
 typedef struct X509_algor_st X509_ALGOR;
 typedef struct X509_crl_info_st X509_CRL_INFO;
 typedef struct X509_crl_st X509_CRL;
@@ -202,9 +264,13 @@
 typedef struct cmac_ctx_st CMAC_CTX;
 typedef struct conf_st CONF;
 typedef struct conf_value_st CONF_VALUE;
+typedef struct crypto_buffer_pool_st CRYPTO_BUFFER_POOL;
+typedef struct crypto_buffer_st CRYPTO_BUFFER;
 typedef struct dh_st DH;
 typedef struct dsa_st DSA;
+typedef struct ec_group_st EC_GROUP;
 typedef struct ec_key_st EC_KEY;
+typedef struct ec_point_st EC_POINT;
 typedef struct ecdsa_method_st ECDSA_METHOD;
 typedef struct ecdsa_sig_st ECDSA_SIG;
 typedef struct engine_st ENGINE;
@@ -231,13 +297,16 @@
 typedef struct sha256_state_st SHA256_CTX;
 typedef struct sha512_state_st SHA512_CTX;
 typedef struct sha_state_st SHA_CTX;
+typedef struct spake2_ctx_st SPAKE2_CTX;
 typedef struct srtp_protection_profile_st SRTP_PROTECTION_PROFILE;
 typedef struct ssl_cipher_st SSL_CIPHER;
 typedef struct ssl_ctx_st SSL_CTX;
 typedef struct ssl_custom_extension SSL_CUSTOM_EXTENSION;
 typedef struct ssl_method_st SSL_METHOD;
+typedef struct ssl_private_key_method_st SSL_PRIVATE_KEY_METHOD;
 typedef struct ssl_session_st SSL_SESSION;
 typedef struct ssl_st SSL;
+typedef struct ssl_ticket_aead_method_st SSL_TICKET_AEAD_METHOD;
 typedef struct st_ERR_FNS ERR_FNS;
 typedef struct v3_ext_ctx X509V3_CTX;
 typedef struct x509_attributes_st X509_ATTRIBUTE;
@@ -245,6 +314,7 @@
 typedef struct x509_cert_pair_st X509_CERT_PAIR;
 typedef struct x509_cinf_st X509_CINF;
 typedef struct x509_crl_method_st X509_CRL_METHOD;
+typedef struct x509_lookup_st X509_LOOKUP;
 typedef struct x509_revoked_st X509_REVOKED;
 typedef struct x509_st X509;
 typedef struct x509_store_ctx_st X509_STORE_CTX;
@@ -256,6 +326,116 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+// MSVC doesn't set __cplusplus to 201103 to indicate C++11 support (see
+// https://connect.microsoft.com/VisualStudio/feedback/details/763051/a-value-of-predefined-macro-cplusplus-is-still-199711l)
+// so MSVC is just assumed to support C++11.
+#if !defined(BORINGSSL_NO_CXX) && __cplusplus < 201103L && !defined(_MSC_VER)
+#define BORINGSSL_NO_CXX
+#endif
+
+#if !defined(BORINGSSL_NO_CXX)
+extern "C++" {
+
+#include <memory>
+
+// STLPort, used by some Android consumers, not have std::unique_ptr.
+#if defined(_STLPORT_VERSION)
+#define BORINGSSL_NO_CXX
+#endif
+
+}  // extern C++
+#endif  // !BORINGSSL_NO_CXX
+
+#if defined(BORINGSSL_NO_CXX)
+
+#define BORINGSSL_MAKE_DELETER(type, deleter)
+#define BORINGSSL_MAKE_STACK_DELETER(type, deleter)
+
+#else
+
+extern "C++" {
+
+#include <memory>
+
+namespace bssl {
+
+namespace internal {
+
+template <typename T>
+struct DeleterImpl {};
+
+template <typename T>
+struct Deleter {
+  void operator()(T *ptr) {
+    // Rather than specialize Deleter for each type, we specialize
+    // DeleterImpl. This allows bssl::UniquePtr<T> to be used while only
+    // including base.h as long as the destructor is not emitted. This matches
+    // std::unique_ptr's behavior on forward-declared types.
+    //
+    // DeleterImpl itself is specialized in the corresponding module's header
+    // and must be included to release an object. If not included, the compiler
+    // will error that DeleterImpl<T> does not have a method Free.
+    DeleterImpl<T>::Free(ptr);
+  }
+};
+
+template <typename T, typename CleanupRet, void (*init)(T *),
+          CleanupRet (*cleanup)(T *)>
+class StackAllocated {
+ public:
+  StackAllocated() { init(&ctx_); }
+  ~StackAllocated() { cleanup(&ctx_); }
+
+  StackAllocated(const StackAllocated<T, CleanupRet, init, cleanup> &) = delete;
+  T& operator=(const StackAllocated<T, CleanupRet, init, cleanup> &) = delete;
+
+  T *get() { return &ctx_; }
+  const T *get() const { return &ctx_; }
+
+  void Reset() {
+    cleanup(&ctx_);
+    init(&ctx_);
+  }
+
+ private:
+  T ctx_;
+};
+
+}  // namespace internal
+
+#define BORINGSSL_MAKE_DELETER(type, deleter)     \
+  namespace internal {                            \
+  template <>                                     \
+  struct DeleterImpl<type> {                      \
+    static void Free(type *ptr) { deleter(ptr); } \
+  };                                              \
+  }
+
+// This makes a unique_ptr to STACK_OF(type) that owns all elements on the
+// stack, i.e. it uses sk_pop_free() to clean up.
+#define BORINGSSL_MAKE_STACK_DELETER(type, deleter) \
+  namespace internal {                              \
+  template <>                                       \
+  struct DeleterImpl<STACK_OF(type)> {              \
+    static void Free(STACK_OF(type) *ptr) {         \
+      sk_##type##_pop_free(ptr, deleter);           \
+    }                                               \
+  };                                                \
+  }
+
+// Holds ownership of heap-allocated BoringSSL structures. Sample usage:
+//   bssl::UniquePtr<BIO> rsa(RSA_new());
+//   bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_mem()));
+template <typename T>
+using UniquePtr = std::unique_ptr<T, internal::Deleter<T>>;
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
+#endif  // !BORINGSSL_NO_CXX
+
 #endif
 
 #endif  /* OPENSSL_HEADER_BASE_H */
diff --git a/src/include/openssl/base64.h b/src/include/openssl/base64.h
index f28e7dd..4bf3888 100644
--- a/src/include/openssl/base64.h
+++ b/src/include/openssl/base64.h
@@ -87,15 +87,16 @@
 
 /* Decoding */
 
-/* EVP_DecodedLength sets |*out_len| to the maximum number of bytes
- * that will be needed to call |EVP_DecodeBase64| on an input of
- * length |len|. */
+/* EVP_DecodedLength sets |*out_len| to the maximum number of bytes that will
+ * be needed to call |EVP_DecodeBase64| on an input of length |len|. It returns
+ * one on success or zero if |len| is not a valid length for a base64-encoded
+ * string. */
 OPENSSL_EXPORT int EVP_DecodedLength(size_t *out_len, size_t len);
 
 /* EVP_DecodeBase64 decodes |in_len| bytes from base64 and writes
  * |*out_len| bytes to |out|. |max_out| is the size of the output
  * buffer. If it is not enough for the maximum output size, the
- * operation fails. */
+ * operation fails. It returns one on success or zero on error. */
 OPENSSL_EXPORT int EVP_DecodeBase64(uint8_t *out, size_t *out_len,
                                     size_t max_out, const uint8_t *in,
                                     size_t in_len);
@@ -105,9 +106,7 @@
  *
  * OpenSSL provides a streaming base64 implementation, however its behavior is
  * very specific to PEM. It is also very lenient of invalid input. Use of any of
- * these functions is thus deprecated.
- *
- * TODO(davidben): Import upstream's rewrite that rejects the invalid input. */
+ * these functions is thus deprecated. */
 
 /* EVP_EncodeInit initialises |*ctx|, which is typically stack
  * allocated, for an encoding operation.
@@ -159,21 +158,25 @@
  *
  * WARNING: EVP_DecodeBlock's return value does not take padding into
  * account. It also strips leading whitespace and trailing
- * whitespace. */
+ * whitespace and minuses. */
 OPENSSL_EXPORT int EVP_DecodeBlock(uint8_t *dst, const uint8_t *src,
                                    size_t src_len);
 
 
 struct evp_encode_ctx_st {
-  unsigned num;    /* number saved in a partial encode/decode */
-  unsigned length; /* The length is either the output line length
-               * (in input bytes) or the shortest input line
-               * length that is ok.  Once decoding begins,
-               * the length is adjusted up each time a longer
-               * line is decoded */
-  uint8_t enc_data[80]; /* data to encode */
-  unsigned line_num;    /* number read on current line */
-  int expect_nl;
+  /* data_used indicates the number of bytes of |data| that are valid. When
+   * encoding, |data| will be filled and encoded as a lump. When decoding, only
+   * the first four bytes of |data| will be used. */
+  unsigned data_used;
+  uint8_t data[48];
+
+  /* eof_seen indicates that the end of the base64 data has been seen when
+   * decoding. Only whitespace can follow. */
+  char eof_seen;
+
+  /* error_encountered indicates that invalid base64 data was found. This will
+   * cause all future calls to fail. */
+  char error_encountered;
 };
 
 
diff --git a/src/include/openssl/bio.h b/src/include/openssl/bio.h
index c88a3e1..a18ad1c 100644
--- a/src/include/openssl/bio.h
+++ b/src/include/openssl/bio.h
@@ -61,6 +61,7 @@
 
 #include <stdio.h>  /* For FILE */
 
+#include <openssl/buffer.h>
 #include <openssl/err.h> /* for ERR_print_errors_fp */
 #include <openssl/ex_data.h>
 #include <openssl/stack.h>
@@ -95,8 +96,8 @@
  * TODO(fork): remove. */
 OPENSSL_EXPORT void BIO_vfree(BIO *bio);
 
-/* BIO_up_ref increments the reference count of |bio| and returns it. */
-OPENSSL_EXPORT BIO *BIO_up_ref(BIO *bio);
+/* BIO_up_ref increments the reference count of |bio| and returns one. */
+OPENSSL_EXPORT int BIO_up_ref(BIO *bio);
 
 
 /* Basic I/O. */
@@ -151,6 +152,11 @@
  * otherwise. */
 OPENSSL_EXPORT int BIO_reset(BIO *bio);
 
+/* BIO_eof returns non-zero when |bio| has reached end-of-file. The precise
+ * meaning of which depends on the concrete type of |bio|. Note that in the
+ * case of BIO_pair this always returns non-zero. */
+OPENSSL_EXPORT int BIO_eof(BIO *bio);
+
 /* BIO_set_flags ORs |flags| with |bio->flags|. */
 OPENSSL_EXPORT void BIO_set_flags(BIO *bio, int flags);
 
@@ -178,22 +184,12 @@
  * |BIO_get_retry_reason|. */
 OPENSSL_EXPORT int BIO_should_io_special(const BIO *bio);
 
-/* BIO_RR_SSL_X509_LOOKUP indicates that an SSL BIO blocked because the SSL
- * library returned with SSL_ERROR_WANT_X509_LOOKUP.
- *
- * TODO(fork): remove. */
-#define BIO_RR_SSL_X509_LOOKUP 0x01
-
 /* BIO_RR_CONNECT indicates that a connect would have blocked */
 #define BIO_RR_CONNECT 0x02
 
 /* BIO_RR_ACCEPT indicates that an accept would have blocked */
 #define BIO_RR_ACCEPT 0x03
 
-/* BIO_RR_SSL_CHANNEL_ID_LOOKUP indicates that the ChannelID code cannot find
- * a private key for a TLS connection. */
-#define BIO_RR_SSL_CHANNEL_ID_LOOKUP 0x04
-
 /* BIO_get_retry_reason returns the special I/O operation that needs to be
  * retried. The return value is one of the |BIO_RR_*| values. */
 OPENSSL_EXPORT int BIO_get_retry_reason(const BIO *bio);
@@ -230,7 +226,7 @@
                             long larg, long return_value);
 
 /* BIO_callback_ctrl allows the callback function to be manipulated. The |cmd|
- * arg will generally be |BIO_CTRL_SET_CALLBACK| but arbitary command values
+ * arg will generally be |BIO_CTRL_SET_CALLBACK| but arbitrary command values
  * can be interpreted by the |BIO|. */
 OPENSSL_EXPORT long BIO_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp);
 
@@ -308,18 +304,12 @@
 OPENSSL_EXPORT void BIO_copy_next_retry(BIO *bio);
 
 
-/* Printf functions.
- *
- * These functions are versions of printf functions that output to a BIO rather
- * than a FILE. */
-#ifdef __GNUC__
-#define __bio_h__attr__ __attribute__
-#else
-#define __bio_h__attr__(x)
-#endif
+/* Printf functions. */
+
+/* BIO_printf behaves like |printf| but outputs to |bio| rather than a |FILE|.
+ * It returns the number of bytes written or a negative number on error. */
 OPENSSL_EXPORT int BIO_printf(BIO *bio, const char *format, ...)
-    __bio_h__attr__((__format__(__printf__, 2, 3)));
-#undef __bio_h__attr__
+    OPENSSL_PRINTF_FORMAT_FUNC(2, 3);
 
 
 /* Utility functions. */
@@ -333,9 +323,9 @@
 OPENSSL_EXPORT int BIO_hexdump(BIO *bio, const uint8_t *data, size_t len,
                                unsigned indent);
 
-/* BIO_print_errors prints the current contents of the error stack to |bio|
+/* ERR_print_errors prints the current contents of the error stack to |bio|
  * using human readable strings where possible. */
-OPENSSL_EXPORT void BIO_print_errors(BIO *bio);
+OPENSSL_EXPORT void ERR_print_errors(BIO *bio);
 
 /* BIO_read_asn1 reads a single ASN.1 object from |bio|. If successful it sets
  * |*out| to be an allocated buffer (that should be freed with |OPENSSL_free|),
@@ -367,19 +357,17 @@
  *
  * Memory BIOs support |BIO_gets| and |BIO_puts|.
  *
- * |BIO_eof| is true if no data is in the BIO.
- *
  * |BIO_ctrl_pending| returns the number of bytes currently stored. */
 
 /* BIO_s_mem returns a |BIO_METHOD| that uses a in-memory buffer. */
 OPENSSL_EXPORT const BIO_METHOD *BIO_s_mem(void);
 
-/* BIO_new_mem_buf creates BIO that reads and writes from |len| bytes at |buf|.
+/* BIO_new_mem_buf creates read-only BIO that reads from |len| bytes at |buf|.
  * It does not take ownership of |buf|. It returns the BIO or NULL on error.
  *
  * If |len| is negative, then |buf| is treated as a NUL-terminated string, but
  * don't depend on this in new code. */
-OPENSSL_EXPORT BIO *BIO_new_mem_buf(void *buf, int len);
+OPENSSL_EXPORT BIO *BIO_new_mem_buf(const void *buf, int len);
 
 /* BIO_mem_contents sets |*out_contents| to point to the current contents of
  * |bio| and |*out_len| to contain the length of that data. It returns one on
@@ -425,12 +413,7 @@
  * underlying file descriptor when the BIO is freed.
  *
  * |BIO_reset| attempts to seek the file pointer to the start of file using
- * |lseek|.
- *
- * |BIO_seek| sets the file pointer to position |off| from start of file using
- * |lseek|.
- *
- * |BIO_tell| returns the current file position. */
+ * |lseek|. */
 
 /* BIO_s_fd returns a |BIO_METHOD| for file descriptor fds. */
 OPENSSL_EXPORT const BIO_METHOD *BIO_s_fd(void);
@@ -441,12 +424,18 @@
 
 /* BIO_set_fd sets the file descriptor of |bio| to |fd|. If |close_flag| is
  * non-zero then |fd| will be closed when |bio| is. It returns one on success
- * or zero on error. */
+ * or zero on error.
+ *
+ * This function may also be used with socket BIOs (see |BIO_s_socket| and
+ * |BIO_new_socket|). */
 OPENSSL_EXPORT int BIO_set_fd(BIO *bio, int fd, int close_flag);
 
 /* BIO_get_fd returns the file descriptor currently in use by |bio| or -1 if
  * |bio| does not wrap a file descriptor. If there is a file descriptor and
- * |out_fd| is not NULL, it also sets |*out_fd| to the file descriptor. */
+ * |out_fd| is not NULL, it also sets |*out_fd| to the file descriptor.
+ *
+ * This function may also be used with socket BIOs (see |BIO_s_socket| and
+ * |BIO_new_socket|). */
 OPENSSL_EXPORT int BIO_get_fd(BIO *bio, int *out_fd);
 
 
@@ -459,11 +448,6 @@
  * |BIO_reset| attempts to seek the file pointer to the start of file using
  * |fseek|.
  *
- * |BIO_seek| sets the file pointer to the given position from the start of
- * file using |fseek|.
- *
- * |BIO_eof| calls |feof|.
- *
  * Setting the close flag causes |fclose| to be called on the stream when the
  * BIO is freed. */
 
@@ -485,7 +469,7 @@
 
 /* BIO_set_fp sets the |FILE| for |bio|. If |close_flag| is |BIO_CLOSE| then
  * |fclose| will be called on |file| when |bio| is closed. It returns one on
- * sucess and zero otherwise. */
+ * success and zero otherwise. */
 OPENSSL_EXPORT int BIO_set_fp(BIO *bio, FILE *file, int close_flag);
 
 /* BIO_read_filename opens |filename| for reading and sets the result as the
@@ -509,24 +493,17 @@
 OPENSSL_EXPORT int BIO_rw_filename(BIO *bio, const char *filename);
 
 
-/* Buffer BIOs.
+/* Socket BIOs.
  *
- * Buffer BIOs are a filter-type BIO, i.e. they are designed to be used in a
- * chain of BIOs. They provide buffering to reduce the number of operations on
- * the underlying BIOs. */
-
-OPENSSL_EXPORT const BIO_METHOD *BIO_f_buffer(void);
-
-/* BIO_set_read_buffer_size sets the size, in bytes, of the read buffer and
- * clears it. It returns one on success and zero on failure. */
-OPENSSL_EXPORT int BIO_set_read_buffer_size(BIO *bio, int buffer_size);
-
-/* BIO_set_write_buffer_size sets the size, in bytes, of the write buffer and
- * clears it. It returns one on success and zero on failure. */
-OPENSSL_EXPORT int BIO_set_write_buffer_size(BIO *bio, int buffer_size);
-
-
-/* Socket BIOs. */
+ * Socket BIOs behave like file descriptor BIOs but, on Windows systems, wrap
+ * the system's |recv| and |send| functions instead of |read| and |write|. On
+ * Windows, file descriptors are provided by C runtime and are not
+ * interchangeable with sockets.
+ *
+ * Socket BIOs may be used with |BIO_set_fd| and |BIO_get_fd|.
+ *
+ * TODO(davidben): Add separate APIs and fix the internals to use |SOCKET|s
+ * around rather than rely on int casts. */
 
 OPENSSL_EXPORT const BIO_METHOD *BIO_s_socket(void);
 
@@ -563,10 +540,18 @@
  * will connect to. It returns one on success and zero otherwise. */
 OPENSSL_EXPORT int BIO_set_conn_port(BIO *bio, const char *port_str);
 
+/* BIO_set_conn_int_port sets |*port| as the port that |bio| will connect to.
+ * It returns one on success and zero otherwise. */
+OPENSSL_EXPORT int BIO_set_conn_int_port(BIO *bio, const int *port);
+
 /* BIO_set_nbio sets whether |bio| will use non-blocking I/O operations. It
  * returns one on success and zero otherwise. */
 OPENSSL_EXPORT int BIO_set_nbio(BIO *bio, int on);
 
+/* BIO_do_connect connects |bio| if it has not been connected yet. It returns
+ * one on success and <= 0 otherwise. */
+OPENSSL_EXPORT int BIO_do_connect(BIO *bio);
+
 
 /* Datagram BIOs.
  *
@@ -580,8 +565,8 @@
 #define BIO_CTRL_DGRAM_MTU_EXCEEDED 43 /* check whether the MTU was exceed in
                                           the previous write operation. */
 
-#define BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT \
-  45 /* Next DTLS handshake timeout to adjust socket timeouts */
+/* BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT is unsupported as it is unused by consumers
+ * and depends on |timeval|, which is not 2038-clean on all platforms. */
 
 #define BIO_CTRL_DGRAM_GET_PEER           46
 
@@ -600,18 +585,6 @@
 OPENSSL_EXPORT int BIO_new_bio_pair(BIO **out1, size_t writebuf1, BIO **out2,
                                     size_t writebuf2);
 
-/* BIO_new_bio_pair_external_buf is the same as |BIO_new_bio_pair| with the
- * difference that the caller keeps ownership of the write buffers
- * |ext_writebuf1_len| and |ext_writebuf2_len|. This is useful when using zero
- * copy API for read and write operations, in cases where the buffers need to
- * outlive the BIO pairs. It returns one on success and zero on error. */
-OPENSSL_EXPORT int BIO_new_bio_pair_external_buf(BIO** bio1_p,
-                                                 size_t writebuf1_len,
-                                                 uint8_t* ext_writebuf1,
-                                                 BIO** bio2_p,
-                                                 size_t writebuf2_len,
-                                                 uint8_t* ext_writebuf2);
-
 /* BIO_ctrl_get_read_request returns the number of bytes that the other side of
  * |bio| tried (unsuccessfully) to read. */
 OPENSSL_EXPORT size_t BIO_ctrl_get_read_request(BIO *bio);
@@ -627,63 +600,6 @@
 OPENSSL_EXPORT int BIO_shutdown_wr(BIO *bio);
 
 
-/* Zero copy versions of BIO_read and BIO_write for BIO pairs. */
-
-/* BIO_zero_copy_get_read_buf initiates a zero copy read operation.
- * |out_read_buf| is set to the internal read buffer, and |out_buf_offset| is
- * set to the current read position of |out_read_buf|. The number of bytes
- * available for read from |out_read_buf| + |out_buf_offset| is returned in
- * |out_available_bytes|. Note that this function might report fewer bytes
- * available than |BIO_pending|, if the internal ring buffer is wrapped. It
- * returns one on success. In case of error it returns zero and pushes to the
- * error stack.
- *
- * The zero copy read operation is completed by calling
- * |BIO_zero_copy_get_read_buf_done|. Neither |BIO_zero_copy_get_read_buf| nor
- * any other I/O read operation may be called while a zero copy read operation
- * is active. */
-OPENSSL_EXPORT int BIO_zero_copy_get_read_buf(BIO* bio,
-                                              uint8_t** out_read_buf,
-                                              size_t* out_buf_offset,
-                                              size_t* out_available_bytes);
-
-/* BIO_zero_copy_get_read_buf_done must be called after reading from a BIO using
- * |BIO_zero_copy_get_read_buf| to finish the read operation. The |bytes_read|
- * argument is the number of bytes read.
- *
- * It returns one on success. In case of error it returns zero and pushes to the
- * error stack. */
-OPENSSL_EXPORT int BIO_zero_copy_get_read_buf_done(BIO* bio, size_t bytes_read);
-
-/* BIO_zero_copy_get_write_buf initiates a zero copy write operation.
- * |out_write_buf| is set to to the internal write buffer, and |out_buf_offset|
- * is set to the current write position of |out_write_buf|.
- * The number of bytes available for write from |out_write_buf| +
- * |out_buf_offset| is returned in |out_available_bytes|. Note that this
- * function might report fewer bytes available than
- * |BIO_ctrl_get_write_guarantee|, if the internal buffer is wrapped. It returns
- * one on success. In case of error it returns zero and pushes to the error
- * stack.
- *
- * The zero copy write operation is completed by calling
- * |BIO_zero_copy_get_write_buf_done|. Neither |BIO_zero_copy_get_write_buf|
- * nor any other I/O write operation may be called while a zero copy write
- * operation is active. */
-OPENSSL_EXPORT int BIO_zero_copy_get_write_buf(BIO* bio,
-                                               uint8_t** out_write_buf,
-                                               size_t* out_buf_offset,
-                                               size_t* out_available_bytes);
-
-/* BIO_zero_copy_get_write_buf_done must be called after writing to a BIO using
- * |BIO_zero_copy_get_write_buf| to finish the write operation. The
- * |bytes_written| argument gives the number of bytes written.
- *
- * It returns one on success. In case of error it returns zero and pushes to the
- * error stack. */
-OPENSSL_EXPORT int BIO_zero_copy_get_write_buf_done(BIO* bio,
-                                                    size_t bytes_written);
-
-
 /* BIO_NOCLOSE and |BIO_CLOSE| can be used as symbolic arguments when a "close
  * flag" is passed to a BIO function. */
 #define BIO_NOCLOSE 0
@@ -707,6 +623,8 @@
 #define BIO_CTRL_INFO		3  /* opt - extra tit-bits */
 #define BIO_CTRL_SET		4  /* man - set the 'IO' type */
 #define BIO_CTRL_GET		5  /* man - get the 'IO' type */
+#define BIO_CTRL_PUSH	6
+#define BIO_CTRL_POP	7
 #define BIO_CTRL_GET_CLOSE	8  /* man - set the 'close' on free */
 #define BIO_CTRL_SET_CLOSE	9  /* man - set the 'close' on free */
 #define BIO_CTRL_PENDING	10  /* opt - is their more data buffered */
@@ -717,13 +635,9 @@
 #define BIO_CTRL_GET_CALLBACK	15  /* opt - set callback function */
 #define BIO_CTRL_SET_FILENAME	30	/* BIO_s_file special */
 
-
-/* Android compatibility section.
- *
- * A previous version of BoringSSL used in Android renamed ERR_print_errors_fp
- * to BIO_print_errors_fp. It has subsequently been renamed back to
- * ERR_print_errors_fp. */
-#define BIO_print_errors_fp ERR_print_errors_fp
+/* BIO_CTRL_DUP is never used, but exists to allow code to compile more
+ * easily. */
+#define BIO_CTRL_DUP	12
 
 
 /* Deprecated functions. */
@@ -735,8 +649,10 @@
  * on one line. */
 OPENSSL_EXPORT const BIO_METHOD *BIO_f_base64(void);
 
-/* ERR_print_errors is an alias for |BIO_print_errors|. */
-OPENSSL_EXPORT void ERR_print_errors(BIO *bio);
+OPENSSL_EXPORT void BIO_set_retry_special(BIO *bio);
+
+/* BIO_set_write_buffer_size returns zero. */
+OPENSSL_EXPORT int BIO_set_write_buffer_size(BIO *bio, int buffer_size);
 
 
 /* Private functions */
@@ -879,6 +795,17 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+extern "C++" {
+
+namespace bssl {
+
+BORINGSSL_MAKE_DELETER(BIO, BIO_free)
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #define BIO_R_BAD_FOPEN_MODE 100
diff --git a/src/include/openssl/bn.h b/src/include/openssl/bn.h
index 6e971e4..a57c23a 100644
--- a/src/include/openssl/bn.h
+++ b/src/include/openssl/bn.h
@@ -134,7 +134,7 @@
 #endif
 
 
-/* BN provides support for working with arbitary sized integers. For example,
+/* BN provides support for working with arbitrary sized integers. For example,
  * although the largest integer supported by the compiler might be 64 bits, BN
  * will allow you to work with numbers until you run out of memory. */
 
@@ -148,15 +148,17 @@
 #if defined(OPENSSL_64_BIT)
 #define BN_ULONG uint64_t
 #define BN_BITS2 64
-#define BN_DEC_FMT1	"%" PRIu64
-#define BN_DEC_FMT2	"%019" PRIu64
-#define BN_HEX_FMT1	"%" PRIx64
+#define BN_DEC_FMT1 "%" PRIu64
+#define BN_DEC_FMT2 "%019" PRIu64
+#define BN_HEX_FMT1 "%" PRIx64
+#define BN_HEX_FMT2 "%016" PRIx64
 #elif defined(OPENSSL_32_BIT)
 #define BN_ULONG uint32_t
 #define BN_BITS2 32
-#define BN_DEC_FMT1	"%" PRIu32
-#define BN_DEC_FMT2	"%09" PRIu32
-#define BN_HEX_FMT1	"%" PRIx32
+#define BN_DEC_FMT1 "%" PRIu32
+#define BN_DEC_FMT2 "%09" PRIu32
+#define BN_HEX_FMT1 "%" PRIx32
+#define BN_HEX_FMT2 "%08" PRIx64
 #else
 #error "Must define either OPENSSL_32_BIT or OPENSSL_64_BIT"
 #endif
@@ -192,13 +194,6 @@
 /* BN_value_one returns a static BIGNUM with value 1. */
 OPENSSL_EXPORT const BIGNUM *BN_value_one(void);
 
-/* BN_with_flags initialises a stack allocated |BIGNUM| with pointers to the
- * contents of |in| but with |flags| ORed into the flags field.
- *
- * Note: the two BIGNUMs share state and so |out| should /not/ be passed to
- * |BN_free|. */
-OPENSSL_EXPORT void BN_with_flags(BIGNUM *out, const BIGNUM *in, int flags);
-
 
 /* Basic functions. */
 
@@ -221,18 +216,16 @@
  * allocation failure. */
 OPENSSL_EXPORT int BN_set_word(BIGNUM *bn, BN_ULONG value);
 
+/* BN_set_u64 sets |bn| to |value|. It returns one on success or zero on
+ * allocation failure. */
+OPENSSL_EXPORT int BN_set_u64(BIGNUM *bn, uint64_t value);
+
 /* BN_set_negative sets the sign of |bn|. */
 OPENSSL_EXPORT void BN_set_negative(BIGNUM *bn, int sign);
 
 /* BN_is_negative returns one if |bn| is negative and zero otherwise. */
 OPENSSL_EXPORT int BN_is_negative(const BIGNUM *bn);
 
-/* BN_get_flags returns |bn->flags| & |flags|. */
-OPENSSL_EXPORT int BN_get_flags(const BIGNUM *bn, int flags);
-
-/* BN_set_flags sets |flags| on |bn|. */
-OPENSSL_EXPORT void BN_set_flags(BIGNUM *bn, int flags);
-
 
 /* Conversion functions. */
 
@@ -247,6 +240,18 @@
  * number of bytes written. */
 OPENSSL_EXPORT size_t BN_bn2bin(const BIGNUM *in, uint8_t *out);
 
+/* BN_le2bn sets |*ret| to the value of |len| bytes from |in|, interpreted as
+ * a little-endian number, and returns |ret|. If |ret| is NULL then a fresh
+ * |BIGNUM| is allocated and returned. It returns NULL on allocation
+ * failure. */
+OPENSSL_EXPORT BIGNUM *BN_le2bn(const uint8_t *in, size_t len, BIGNUM *ret);
+
+/* BN_bn2le_padded serialises the absolute value of |in| to |out| as a
+ * little-endian integer, which must have |len| of space available, padding
+ * out the remainder of out with zeros. If |len| is smaller than |BN_num_bytes|,
+ * the function fails and returns 0. Otherwise, it returns 1. */
+OPENSSL_EXPORT int BN_bn2le_padded(uint8_t *out, size_t len, const BIGNUM *in);
+
 /* BN_bn2bin_padded serialises the absolute value of |in| to |out| as a
  * big-endian integer. The integer is padded with leading zeros up to size
  * |len|. If |len| is smaller than |BN_num_bytes|, the function fails and
@@ -300,20 +305,25 @@
  * will be returned. */
 OPENSSL_EXPORT BN_ULONG BN_get_word(const BIGNUM *bn);
 
+/* BN_get_u64 sets |*out| to the absolute value of |bn| as a |uint64_t| and
+ * returns one. If |bn| is too large to be represented as a |uint64_t|, it
+ * returns zero. */
+OPENSSL_EXPORT int BN_get_u64(const BIGNUM *bn, uint64_t *out);
+
 
 /* ASN.1 functions. */
 
-/* BN_cbs2unsigned parses a non-negative DER INTEGER from |cbs| writes the
- * result to |ret|. It returns one on success and zero on failure. */
-OPENSSL_EXPORT int BN_cbs2unsigned(CBS *cbs, BIGNUM *ret);
+/* BN_parse_asn1_unsigned parses a non-negative DER INTEGER from |cbs| writes
+ * the result to |ret|. It returns one on success and zero on failure. */
+OPENSSL_EXPORT int BN_parse_asn1_unsigned(CBS *cbs, BIGNUM *ret);
 
-/* BN_cbs2unsigned_buggy acts like |BN_cbs2unsigned| but tolerates some invalid
- * encodings. Do not use this function. */
-OPENSSL_EXPORT int BN_cbs2unsigned_buggy(CBS *cbs, BIGNUM *ret);
+/* BN_parse_asn1_unsigned_buggy acts like |BN_parse_asn1_unsigned| but tolerates
+ * some invalid encodings. Do not use this function. */
+OPENSSL_EXPORT int BN_parse_asn1_unsigned_buggy(CBS *cbs, BIGNUM *ret);
 
-/* BN_bn2cbb marshals |bn| as a non-negative DER INTEGER and appends the result
- * to |cbb|. It returns one on success and zero on failure. */
-OPENSSL_EXPORT int BN_bn2cbb(CBB *cbb, const BIGNUM *bn);
+/* BN_marshal_asn1 marshals |bn| as a non-negative DER INTEGER and appends the
+ * result to |cbb|. It returns one on success and zero on failure. */
+OPENSSL_EXPORT int BN_marshal_asn1(CBB *cbb, const BIGNUM *bn);
 
 
 /* Internal functions.
@@ -323,11 +333,11 @@
  * what you want before turning to these. */
 
 /* bn_correct_top decrements |bn->top| until |bn->d[top-1]| is non-zero or
- * until |top| is zero. */
+ * until |top| is zero. If |bn| is zero, |bn->neg| is set to zero. */
 OPENSSL_EXPORT void bn_correct_top(BIGNUM *bn);
 
 /* bn_wexpand ensures that |bn| has at least |words| works of space without
- * altering its value. It returns one on success or zero on allocation
+ * altering its value. It returns |bn| on success or NULL on allocation
  * failure. */
 OPENSSL_EXPORT BIGNUM *bn_wexpand(BIGNUM *bn, size_t words);
 
@@ -335,7 +345,7 @@
 /* BIGNUM pools.
  *
  * Certain BIGNUM operations need to use many temporary variables and
- * allocating and freeing them can be quite slow. Thus such opertions typically
+ * allocating and freeing them can be quite slow. Thus such operations typically
  * take a |BN_CTX| parameter, which contains a pool of |BIGNUMs|. The |ctx|
  * argument to a public function may be NULL, in which case a local |BN_CTX|
  * will be created just for the lifetime of that call.
@@ -383,12 +393,12 @@
 /* BN_add_word adds |w| to |a|. It returns one on success and zero otherwise. */
 OPENSSL_EXPORT int BN_add_word(BIGNUM *a, BN_ULONG w);
 
-/* BN_sub sets |r| = |a| - |b|, where |r| must be a distinct pointer from |a|
- * and |b|. It returns one on success and zero on allocation failure. */
+/* BN_sub sets |r| = |a| - |b|, where |r| may be the same pointer as either |a|
+ * or |b|. It returns one on success and zero on allocation failure. */
 OPENSSL_EXPORT int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
 
 /* BN_usub sets |r| = |a| - |b|, where |a| and |b| are non-negative integers,
- * |b| < |a| and |r| must be a distinct pointer from |a| and |b|. It returns
+ * |b| < |a| and |r| may be the same pointer as either |a| or |b|. It returns
  * one on success and zero on allocation failure. */
 OPENSSL_EXPORT int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b);
 
@@ -436,11 +446,20 @@
  * less than, equal to or greater than |b|, respectively. */
 OPENSSL_EXPORT int BN_cmp(const BIGNUM *a, const BIGNUM *b);
 
+/* BN_cmp_word is like |BN_cmp| except it takes its second argument as a
+ * |BN_ULONG| instead of a |BIGNUM|. */
+OPENSSL_EXPORT int BN_cmp_word(const BIGNUM *a, BN_ULONG b);
+
 /* BN_ucmp returns a value less than, equal to or greater than zero if the
  * absolute value of |a| is less than, equal to or greater than the absolute
  * value of |b|, respectively. */
 OPENSSL_EXPORT int BN_ucmp(const BIGNUM *a, const BIGNUM *b);
 
+/* BN_equal_consttime returns one if |a| is equal to |b|, and zero otherwise.
+ * It takes an amount of time dependent on the sizes of |a| and |b|, but
+ * independent of the contents (including the signs) of |a| and |b|. */
+OPENSSL_EXPORT int BN_equal_consttime(const BIGNUM *a, const BIGNUM *b);
+
 /* BN_abs_is_word returns one if the absolute value of |bn| equals |w| and zero
  * otherwise. */
 OPENSSL_EXPORT int BN_abs_is_word(const BIGNUM *bn, BN_ULONG w);
@@ -457,6 +476,8 @@
 /* BN_is_odd returns one if |bn| is odd and zero otherwise. */
 OPENSSL_EXPORT int BN_is_odd(const BIGNUM *bn);
 
+/* BN_is_pow2 returns 1 if |a| is a power of two, and 0 otherwise. */
+OPENSSL_EXPORT int BN_is_pow2(const BIGNUM *a);
 
 /* Bitwise operations. */
 
@@ -497,9 +518,17 @@
 
 /* Modulo arithmetic. */
 
-/* BN_mod_word returns |a| mod |w|. */
+/* BN_mod_word returns |a| mod |w| or (BN_ULONG)-1 on error. */
 OPENSSL_EXPORT BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w);
 
+/* BN_mod_pow2 sets |r| = |a| mod 2^|e|. It returns 1 on success and
+ * 0 on error. */
+OPENSSL_EXPORT int BN_mod_pow2(BIGNUM *r, const BIGNUM *a, size_t e);
+
+/* BN_nnmod_pow2 sets |r| = |a| mod 2^|e| where |r| is always positive.
+ * It returns 1 on success and 0 on error. */
+OPENSSL_EXPORT int BN_nnmod_pow2(BIGNUM *r, const BIGNUM *a, size_t e);
+
 /* BN_mod is a helper macro that calls |BN_div| and discards the quotient. */
 #define BN_mod(rem, numerator, divisor, ctx) \
   BN_div(NULL, (rem), (numerator), (divisor), (ctx))
@@ -560,31 +589,52 @@
 OPENSSL_EXPORT int BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a,
                                         const BIGNUM *m);
 
-/* BN_mod_sqrt returns a |BIGNUM|, r, such that r^2 == a (mod p). */
+/* BN_mod_sqrt returns a newly-allocated |BIGNUM|, r, such that
+ * r^2 == a (mod p). |p| must be a prime. It returns NULL on error or if |a| is
+ * not a square mod |p|. In the latter case, it will add |BN_R_NOT_A_SQUARE| to
+ * the error queue. */
 OPENSSL_EXPORT BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p,
                                    BN_CTX *ctx);
 
 
 /* Random and prime number generation. */
 
-/* BN_rand sets |rnd| to a random number of length |bits|. If |top| is zero, the
- * most-significant bit, if any, will be set. If |top| is one, the two most
- * significant bits, if any, will be set.
+/* The following are values for the |top| parameter of |BN_rand|. */
+#define BN_RAND_TOP_ANY    (-1)
+#define BN_RAND_TOP_ONE     0
+#define BN_RAND_TOP_TWO     1
+
+/* The following are values for the |bottom| parameter of |BN_rand|. */
+#define BN_RAND_BOTTOM_ANY  0
+#define BN_RAND_BOTTOM_ODD  1
+
+/* BN_rand sets |rnd| to a random number of length |bits|. It returns one on
+ * success and zero otherwise.
  *
- * If |top| is -1 then no extra action will be taken and |BN_num_bits(rnd)| may
- * not equal |bits| if the most significant bits randomly ended up as zeros.
+ * |top| must be one of the |BN_RAND_TOP_*| values. If |BN_RAND_TOP_ONE|, the
+ * most-significant bit, if any, will be set. If |BN_RAND_TOP_TWO|, the two
+ * most significant bits, if any, will be set. If |BN_RAND_TOP_ANY|, no extra
+ * action will be taken and |BN_num_bits(rnd)| may not equal |bits| if the most
+ * significant bits randomly ended up as zeros.
  *
- * If |bottom| is non-zero, the least-significant bit, if any, will be set. The
- * function returns one on success or zero otherwise. */
+ * |bottom| must be one of the |BN_RAND_BOTTOM_*| values. If
+ * |BN_RAND_BOTTOM_ODD|, the least-significant bit, if any, will be set. If
+ * |BN_RAND_BOTTOM_ANY|, no extra action will be taken. */
 OPENSSL_EXPORT int BN_rand(BIGNUM *rnd, int bits, int top, int bottom);
 
 /* BN_pseudo_rand is an alias for |BN_rand|. */
 OPENSSL_EXPORT int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom);
 
-/* BN_rand_range sets |rnd| to a random value [0..range). It returns one on
- * success and zero otherwise. */
+/* BN_rand_range is equivalent to |BN_rand_range_ex| with |min_inclusive| set
+ * to zero and |max_exclusive| set to |range|. */
 OPENSSL_EXPORT int BN_rand_range(BIGNUM *rnd, const BIGNUM *range);
 
+/* BN_rand_range_ex sets |rnd| to a random value in
+ * [min_inclusive..max_exclusive). It returns one on success and zero
+ * otherwise. */
+OPENSSL_EXPORT int BN_rand_range_ex(BIGNUM *r, BN_ULONG min_inclusive,
+                                    const BIGNUM *max_exclusive);
+
 /* BN_pseudo_rand_range is an alias for BN_rand_range. */
 OPENSSL_EXPORT int BN_pseudo_rand_range(BIGNUM *rnd, const BIGNUM *range);
 
@@ -604,7 +654,7 @@
  * |BN_GENCB| structure.
  *
  * The callback receives the address of that |BN_GENCB| structure as its last
- * argument and the user is free to put an arbitary pointer in |arg|. The other
+ * argument and the user is free to put an arbitrary pointer in |arg|. The other
  * arguments are set as follows:
  *   event=BN_GENCB_GENERATED, n=i:   after generating the i'th possible prime
  *                                    number.
@@ -706,20 +756,38 @@
 OPENSSL_EXPORT int BN_gcd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
                           BN_CTX *ctx);
 
-/* BN_mod_inverse sets |out| equal to |a|^-1, mod |n|. If either of |a| or |n|
- * have |BN_FLG_CONSTTIME| set then the operation is performed in constant
- * time. If |out| is NULL, a fresh BIGNUM is allocated. It returns the result
- * or NULL on error. */
+/* BN_mod_inverse sets |out| equal to |a|^-1, mod |n|. If |out| is NULL, a
+ * fresh BIGNUM is allocated. It returns the result or NULL on error.
+ *
+ * If |n| is even then the operation is performed using an algorithm that avoids
+ * some branches but which isn't constant-time. This function shouldn't be used
+ * for secret values; use |BN_mod_inverse_blinded| instead. Or, if |n| is
+ * guaranteed to be prime, use
+ * |BN_mod_exp_mont_consttime(out, a, m_minus_2, m, ctx, m_mont)|, taking
+ * advantage of Fermat's Little Theorem. */
 OPENSSL_EXPORT BIGNUM *BN_mod_inverse(BIGNUM *out, const BIGNUM *a,
                                       const BIGNUM *n, BN_CTX *ctx);
 
-/* BN_mod_inverse_ex acts like |BN_mod_inverse| except that, when it returns
- * zero, it will set |*out_no_inverse| to one if the failure was caused because
- * |a| has no inverse mod |n|. Otherwise it will set |*out_no_inverse| to
+/* BN_mod_inverse_blinded sets |out| equal to |a|^-1, mod |n|, where |n| is the
+ * Montgomery modulus for |mont|. |a| must be non-negative and must be less
+ * than |n|. |n| must be greater than 1. |a| is blinded (masked by a random
+ * value) to protect it against side-channel attacks. On failure, if the failure
+ * was caused by |a| having no inverse mod |n| then |*out_no_inverse| will be
+ * set to one; otherwise it will be set to zero. */
+int BN_mod_inverse_blinded(BIGNUM *out, int *out_no_inverse, const BIGNUM *a,
+                           const BN_MONT_CTX *mont, BN_CTX *ctx);
+
+/* BN_mod_inverse_odd sets |out| equal to |a|^-1, mod |n|. |a| must be
+ * non-negative and must be less than |n|. |n| must be odd. This function
+ * shouldn't be used for secret values; use |BN_mod_inverse_blinded| instead.
+ * Or, if |n| is guaranteed to be prime, use
+ * |BN_mod_exp_mont_consttime(out, a, m_minus_2, m, ctx, m_mont)|, taking
+ * advantage of Fermat's Little Theorem. It returns one on success or zero on
+ * failure. On failure, if the failure was caused by |a| having no inverse mod
+ * |n| then |*out_no_inverse| will be set to one; otherwise it will be set to
  * zero. */
-OPENSSL_EXPORT BIGNUM *BN_mod_inverse_ex(BIGNUM *out, int *out_no_inverse,
-                                         const BIGNUM *a, const BIGNUM *n,
-                                         BN_CTX *ctx);
+int BN_mod_inverse_odd(BIGNUM *out, int *out_no_inverse, const BIGNUM *a,
+                       const BIGNUM *n, BN_CTX *ctx);
 
 /* BN_kronecker returns the Kronecker symbol of |a| and |b| (which is -1, 0 or
  * 1), or -2 on error. */
@@ -749,25 +817,29 @@
 
 /* BN_MONT_CTX_set_locked takes |lock| and checks whether |*pmont| is NULL. If
  * so, it creates a new |BN_MONT_CTX| and sets the modulus for it to |mod|. It
- * then stores it as |*pmont| and returns it, or NULL on error.
+ * then stores it as |*pmont|. It returns one on success and zero on error.
  *
- * If |*pmont| is already non-NULL then the existing value is returned. */
-BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, CRYPTO_MUTEX *lock,
-                                    const BIGNUM *mod, BN_CTX *bn_ctx);
+ * If |*pmont| is already non-NULL then it does nothing and returns one. */
+int BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, CRYPTO_MUTEX *lock,
+                           const BIGNUM *mod, BN_CTX *bn_ctx);
 
-/* BN_to_montgomery sets |ret| equal to |a| in the Montgomery domain. It
- * returns one on success and zero on error. */
+/* BN_to_montgomery sets |ret| equal to |a| in the Montgomery domain. |a| is
+ * assumed to be in the range [0, n), where |n| is the Montgomery modulus. It
+ * returns one on success or zero on error. */
 OPENSSL_EXPORT int BN_to_montgomery(BIGNUM *ret, const BIGNUM *a,
                                     const BN_MONT_CTX *mont, BN_CTX *ctx);
 
-/* BN_from_montgomery sets |ret| equal to |a| * R^-1, i.e. translates values
- * out of the Montgomery domain. It returns one on success or zero on error. */
+/* BN_from_montgomery sets |ret| equal to |a| * R^-1, i.e. translates values out
+ * of the Montgomery domain. |a| is assumed to be in the range [0, n), where |n|
+ * is the Montgomery modulus. It returns one on success or zero on error. */
 OPENSSL_EXPORT int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a,
                                       const BN_MONT_CTX *mont, BN_CTX *ctx);
 
 /* BN_mod_mul_montgomery set |r| equal to |a| * |b|, in the Montgomery domain.
  * Both |a| and |b| must already be in the Montgomery domain (by
- * |BN_to_montgomery|). It returns one on success or zero on error. */
+ * |BN_to_montgomery|). In particular, |a| and |b| are assumed to be in the
+ * range [0, n), where |n| is the Montgomery modulus. It returns one on success
+ * or zero on error. */
 OPENSSL_EXPORT int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a,
                                          const BIGNUM *b,
                                          const BN_MONT_CTX *mont, BN_CTX *ctx);
@@ -782,9 +854,9 @@
                           BN_CTX *ctx);
 
 /* BN_mod_exp sets |r| equal to |a|^{|p|} mod |m|. It does so with the best
- * algorithm for the values provided and can run in constant time if
- * |BN_FLG_CONSTTIME| is set for |p|. It returns one on success or zero
- * otherwise. */
+ * algorithm for the values provided. It returns one on success or zero
+ * otherwise. The |BN_mod_exp_mont_consttime| variant must be used if the
+ * exponent is secret. */
 OPENSSL_EXPORT int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
                               const BIGNUM *m, BN_CTX *ctx);
 
@@ -797,14 +869,6 @@
                                              BN_CTX *ctx,
                                              const BN_MONT_CTX *mont);
 
-OPENSSL_EXPORT int BN_mod_exp_mont_word(BIGNUM *r, BN_ULONG a, const BIGNUM *p,
-                                        const BIGNUM *m, BN_CTX *ctx,
-                                        const BN_MONT_CTX *mont);
-OPENSSL_EXPORT int BN_mod_exp2_mont(BIGNUM *r, const BIGNUM *a1,
-                                    const BIGNUM *p1, const BIGNUM *a2,
-                                    const BIGNUM *p2, const BIGNUM *m,
-                                    BN_CTX *ctx, const BN_MONT_CTX *mont);
-
 
 /* Deprecated functions */
 
@@ -824,6 +888,20 @@
  * is updated. */
 OPENSSL_EXPORT BIGNUM *BN_mpi2bn(const uint8_t *in, size_t len, BIGNUM *out);
 
+/* BN_mod_exp_mont_word is like |BN_mod_exp_mont| except that the base |a| is
+ * given as a |BN_ULONG| instead of a |BIGNUM *|. It returns one on success
+ * or zero otherwise. */
+OPENSSL_EXPORT int BN_mod_exp_mont_word(BIGNUM *r, BN_ULONG a, const BIGNUM *p,
+                                        const BIGNUM *m, BN_CTX *ctx,
+                                        const BN_MONT_CTX *mont);
+
+/* BN_mod_exp2_mont calculates (a1^p1) * (a2^p2) mod m. It returns 1 on success
+ * or zero otherwise. */
+OPENSSL_EXPORT int BN_mod_exp2_mont(BIGNUM *r, const BIGNUM *a1,
+                                    const BIGNUM *p1, const BIGNUM *a2,
+                                    const BIGNUM *p2, const BIGNUM *m,
+                                    BN_CTX *ctx, const BN_MONT_CTX *mont);
+
 
 /* Private functions */
 
@@ -846,23 +924,28 @@
 
 #define BN_FLG_MALLOCED 0x01
 #define BN_FLG_STATIC_DATA 0x02
-/* avoid leaking exponent information through timing, BN_mod_exp_mont() will
- * call BN_mod_exp_mont_consttime, BN_div() will call BN_div_no_branch,
- * BN_mod_inverse() will call BN_mod_inverse_no_branch. */
-#define BN_FLG_CONSTTIME 0x04
-
-
-/* Android compatibility section.
- *
- * These functions are declared, temporarily, for Android because
- * wpa_supplicant will take a little time to sync with upstream. Outside of
- * Android they'll have no definition. */
-
-OPENSSL_EXPORT BIGNUM *get_rfc3526_prime_1536(BIGNUM *bn);
+/* |BN_FLG_CONSTTIME| has been removed and intentionally omitted so code relying
+ * on it will not compile. Consumers outside BoringSSL should use the
+ * higher-level cryptographic algorithms exposed by other modules. Consumers
+ * within the library should call the appropriate timing-sensitive algorithm
+ * directly. */
 
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+extern "C++" {
+
+namespace bssl {
+
+BORINGSSL_MAKE_DELETER(BIGNUM, BN_free)
+BORINGSSL_MAKE_DELETER(BN_CTX, BN_CTX_free)
+BORINGSSL_MAKE_DELETER(BN_MONT_CTX, BN_MONT_CTX_free)
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #define BN_R_ARG2_LT_ARG3 100
diff --git a/src/include/openssl/buf.h b/src/include/openssl/buf.h
index 76e3795..30f3af7 100644
--- a/src/include/openssl/buf.h
+++ b/src/include/openssl/buf.h
@@ -67,7 +67,7 @@
 /* Memory and string functions, see also mem.h. */
 
 
-/* BUF_MEM is a generic buffer object used by OpenSSL. */
+/* buf_mem_st (aka |BUF_MEM|) is a generic buffer object used by OpenSSL. */
 struct buf_mem_st {
   size_t length; /* current number of bytes */
   char *data;
@@ -80,6 +80,10 @@
 /* BUF_MEM_free frees |buf->data| if needed and then frees |buf| itself. */
 OPENSSL_EXPORT void BUF_MEM_free(BUF_MEM *buf);
 
+/* BUF_MEM_reserve ensures |buf| has capacity |cap| and allocates memory if
+ * needed. It returns one on success and zero on error. */
+OPENSSL_EXPORT int BUF_MEM_reserve(BUF_MEM *buf, size_t cap);
+
 /* BUF_MEM_grow ensures that |buf| has length |len| and allocates memory if
  * needed. If the length of |buf| increased, the new bytes are filled with
  * zeros. It returns the length of |buf|, or zero if there's an error. */
@@ -113,6 +117,17 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+extern "C++" {
+
+namespace bssl {
+
+BORINGSSL_MAKE_DELETER(BUF_MEM, BUF_MEM_free)
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #endif  /* OPENSSL_HEADER_BUFFER_H */
diff --git a/src/include/openssl/bytestring.h b/src/include/openssl/bytestring.h
index 9193e11..4aea6bf 100644
--- a/src/include/openssl/bytestring.h
+++ b/src/include/openssl/bytestring.h
@@ -95,6 +95,10 @@
  * and advances |cbs|. It returns one on success and zero on error. */
 OPENSSL_EXPORT int CBS_get_u32(CBS *cbs, uint32_t *out);
 
+/* CBS_get_last_u8 sets |*out| to the last uint8_t from |cbs| and shortens
+ * |cbs|. It returns one on success and zero on error. */
+OPENSSL_EXPORT int CBS_get_last_u8(CBS *cbs, uint8_t *out);
+
 /* CBS_get_bytes sets |*out| to the next |len| bytes from |cbs| and advances
  * |cbs|. It returns one on success and zero on error. */
 OPENSSL_EXPORT int CBS_get_bytes(CBS *cbs, CBS *out, size_t len);
@@ -121,6 +125,7 @@
 
 /* Parsing ASN.1 */
 
+/* The following values are tag numbers for UNIVERSAL elements. */
 #define CBS_ASN1_BOOLEAN 0x1
 #define CBS_ASN1_INTEGER 0x2
 #define CBS_ASN1_BITSTRING 0x3
@@ -128,12 +133,43 @@
 #define CBS_ASN1_NULL 0x5
 #define CBS_ASN1_OBJECT 0x6
 #define CBS_ASN1_ENUMERATED 0xa
+#define CBS_ASN1_UTF8STRING 0xc
 #define CBS_ASN1_SEQUENCE (0x10 | CBS_ASN1_CONSTRUCTED)
 #define CBS_ASN1_SET (0x11 | CBS_ASN1_CONSTRUCTED)
+#define CBS_ASN1_NUMERICSTRING 0x12
+#define CBS_ASN1_PRINTABLESTRING 0x13
+#define CBS_ASN1_T61STRING 0x14
+#define CBS_ASN1_VIDEOTEXSTRING 0x15
+#define CBS_ASN1_IA5STRING 0x16
+#define CBS_ASN1_UTCTIME 0x17
 #define CBS_ASN1_GENERALIZEDTIME 0x18
+#define CBS_ASN1_GRAPHICSTRING 0x19
+#define CBS_ASN1_VISIBLESTRING 0x1a
+#define CBS_ASN1_GENERALSTRING 0x1b
+#define CBS_ASN1_UNIVERSALSTRING 0x1c
+#define CBS_ASN1_BMPSTRING 0x1e
 
+/* CBS_ASN1_CONSTRUCTED may be ORed into a tag to toggle the constructed
+ * bit. |CBS| and |CBB| APIs consider the constructed bit to be part of the
+ * tag. */
 #define CBS_ASN1_CONSTRUCTED 0x20
+
+/* The following values specify the constructed bit or tag class and may be ORed
+ * into a tag number to produce the final tag. If none is used, the tag will be
+ * UNIVERSAL.
+ *
+ * Note that although they currently match the DER serialization, consumers must
+ * use these bits rather than make assumptions about the representation. This is
+ * to allow for tag numbers beyond 31 in the future. */
+#define CBS_ASN1_APPLICATION 0x40
 #define CBS_ASN1_CONTEXT_SPECIFIC 0x80
+#define CBS_ASN1_PRIVATE 0xc0
+
+/* CBS_ASN1_CLASS_MASK may be ANDed with a tag to query its class. */
+#define CBS_ASN1_CLASS_MASK 0xc0
+
+/* CBS_ASN1_TAG_NUMBER_MASK may be ANDed with a tag to query its number. */
+#define CBS_ASN1_TAG_NUMBER_MASK 0x1f
 
 /* CBS_get_asn1 sets |*out| to the contents of DER-encoded, ASN.1 element (not
  * including tag and length bytes) and advances |cbs| over it. The ASN.1
@@ -154,6 +190,14 @@
  * element is malformed. */
 OPENSSL_EXPORT int CBS_peek_asn1_tag(const CBS *cbs, unsigned tag_value);
 
+/* CBS_get_any_asn1 sets |*out| to contain the next ASN.1 element from |*cbs|
+ * (not including tag and length bytes), sets |*out_tag| to the tag number, and
+ * advances |*cbs|. It returns one on success and zero on error. Either of |out|
+ * and |out_tag| may be NULL to ignore the value.
+ *
+ * Tag numbers greater than 30 are not supported (i.e. short form only). */
+OPENSSL_EXPORT int CBS_get_any_asn1(CBS *cbs, CBS *out, unsigned *out_tag);
+
 /* CBS_get_any_asn1_element sets |*out| to contain the next ASN.1 element from
  * |*cbs| (including header bytes) and advances |*cbs|. It sets |*out_tag| to
  * the tag number and |*out_header_len| to the length of the ASN.1 header. Each
@@ -213,6 +257,15 @@
 OPENSSL_EXPORT int CBS_get_optional_asn1_bool(CBS *cbs, int *out, unsigned tag,
                                               int default_value);
 
+/* CBS_is_valid_asn1_bitstring returns one if |cbs| is a valid ASN.1 BIT STRING
+ * and zero otherwise. */
+OPENSSL_EXPORT int CBS_is_valid_asn1_bitstring(const CBS *cbs);
+
+/* CBS_asn1_bitstring_has_bit returns one if |cbs| is a valid ASN.1 BIT STRING
+ * and the specified bit is present and set. Otherwise, it returns zero. |bit|
+ * is indexed starting from zero. */
+OPENSSL_EXPORT int CBS_asn1_bitstring_has_bit(const CBS *cbs, unsigned bit);
+
 
 /* CRYPTO ByteBuilder.
  *
@@ -226,7 +279,8 @@
  * not be used again.
  *
  * If one needs to force a length prefix to be written out because a |CBB| is
- * going out of scope, use |CBB_flush|. */
+ * going out of scope, use |CBB_flush|. If an operation on a |CBB| fails, it is
+ * in an undefined state and must not be used except to call |CBB_cleanup|. */
 
 struct cbb_buffer_st {
   uint8_t *buf;
@@ -234,6 +288,8 @@
   size_t cap;      /* The size of buf. */
   char can_resize; /* One iff |buf| is owned by this object. If not then |buf|
                       cannot be resized. */
+  char error;      /* One iff there was an error writing to this CBB. All future
+                      operations will fail. */
 };
 
 struct cbb_st {
@@ -288,8 +344,10 @@
 OPENSSL_EXPORT int CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len);
 
 /* CBB_flush causes any pending length prefixes to be written out and any child
- * |CBB| objects of |cbb| to be invalidated. It returns one on success or zero
- * on error. */
+ * |CBB| objects of |cbb| to be invalidated. This allows |cbb| to continue to be
+ * used after the children go out of scope, e.g. when local |CBB| objects are
+ * added as children to a |CBB| that persists after a function returns. This
+ * function returns one on success or zero on error. */
 OPENSSL_EXPORT int CBB_flush(CBB *cbb);
 
 /* CBB_data returns a pointer to the bytes written to |cbb|. It does not flush
@@ -326,7 +384,7 @@
  * the object. Passing in |tag| number 31 will return in an error since only
  * single octet identifiers are supported. It returns one on success or zero
  * on error. */
-OPENSSL_EXPORT int CBB_add_asn1(CBB *cbb, CBB *out_contents, uint8_t tag);
+OPENSSL_EXPORT int CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned tag);
 
 /* CBB_add_bytes appends |len| bytes from |data| to |cbb|. It returns one on
  * success and zero otherwise. */
@@ -361,6 +419,10 @@
  * returns one on success and zero otherwise. */
 OPENSSL_EXPORT int CBB_add_u24(CBB *cbb, uint32_t value);
 
+/* CBB_add_u32 appends a 32-bit, big-endian number from |value| to |cbb|. It
+ * returns one on success and zero otherwise. */
+OPENSSL_EXPORT int CBB_add_u32(CBB *cbb, uint32_t value);
+
 /* CBB_discard_child discards the current unflushed child of |cbb|. Neither the
  * child's contents nor the length prefix will be included in the output. */
 OPENSSL_EXPORT void CBB_discard_child(CBB *cbb);
@@ -373,6 +435,20 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+
+#if !defined(BORINGSSL_NO_CXX)
+extern "C++" {
+
+namespace bssl {
+
+using ScopedCBB = internal::StackAllocated<CBB, void, CBB_zero, CBB_cleanup>;
+
+}  // namespace bssl
+
+}  // extern C++
+#endif
+
 #endif
 
 #endif  /* OPENSSL_HEADER_BYTESTRING_H */
diff --git a/src/include/openssl/chacha.h b/src/include/openssl/chacha.h
index 64713c2..3d035e6 100644
--- a/src/include/openssl/chacha.h
+++ b/src/include/openssl/chacha.h
@@ -23,8 +23,8 @@
 
 
 /* CRYPTO_chacha_20 encrypts |in_len| bytes from |in| with the given key and
- * nonce and writes the result to |out|, which may be equal to |in|. The
- * initial block counter is specified by |counter|. */
+ * nonce and writes the result to |out|. If |in| and |out| alias, they must be
+ * equal. The initial block counter is specified by |counter|. */
 OPENSSL_EXPORT void CRYPTO_chacha_20(uint8_t *out, const uint8_t *in,
                                      size_t in_len, const uint8_t key[32],
                                      const uint8_t nonce[12], uint32_t counter);
diff --git a/src/include/openssl/cipher.h b/src/include/openssl/cipher.h
index fb7171f..2ee74ef 100644
--- a/src/include/openssl/cipher.h
+++ b/src/include/openssl/cipher.h
@@ -191,7 +191,7 @@
  * |*out_len| to the number of bytes written. If padding is enabled (the
  * default) then padding is removed from the final block.
  *
- * WARNING: it is unsafe to call this function with unauthenticted
+ * WARNING: it is unsafe to call this function with unauthenticated
  * ciphertext if padding is enabled. */
 OPENSSL_EXPORT int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out,
                                        int *out_len);
@@ -282,12 +282,13 @@
 /* EVP_CIPHER_CTX_set_key_length sets the key length for |ctx|. This is only
  * valid for ciphers that can take a variable length key. It returns one on
  * success and zero on error. */
-OPENSSL_EXPORT int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *ctx, unsigned key_len);
+OPENSSL_EXPORT int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *ctx,
+                                                 unsigned key_len);
 
 
 /* Cipher accessors. */
 
-/* EVP_CIPHER_nid returns a NID identifing |cipher|. (For example,
+/* EVP_CIPHER_nid returns a NID identifying |cipher|. (For example,
  * |NID_aes_128_gcm|.) */
 OPENSSL_EXPORT int EVP_CIPHER_nid(const EVP_CIPHER *cipher);
 
@@ -481,7 +482,7 @@
 
   /* num contains the number of bytes of |iv| which are valid for modes that
    * manage partial blocks themselves. */
-  int num;
+  unsigned num;
 
   /* final_used is non-zero if the |final| buffer contains plaintext. */
   int final_used;
@@ -540,6 +541,23 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+#if !defined(BORINGSSL_NO_CXX)
+extern "C++" {
+
+namespace bssl {
+
+BORINGSSL_MAKE_DELETER(EVP_CIPHER_CTX, EVP_CIPHER_CTX_free)
+
+using ScopedEVP_CIPHER_CTX =
+    internal::StackAllocated<EVP_CIPHER_CTX, int, EVP_CIPHER_CTX_init,
+                             EVP_CIPHER_CTX_cleanup>;
+
+}  // namespace bssl
+
+}  // extern C++
+#endif
+
 #endif
 
 #define CIPHER_R_AES_KEY_SETUP_FAILED 100
diff --git a/src/include/openssl/cmac.h b/src/include/openssl/cmac.h
index 0bb44b9..0f05bc9 100644
--- a/src/include/openssl/cmac.h
+++ b/src/include/openssl/cmac.h
@@ -71,6 +71,17 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+extern "C++" {
+
+namespace bssl {
+
+BORINGSSL_MAKE_DELETER(CMAC_CTX, CMAC_CTX_free)
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #endif  /* OPENSSL_HEADER_CMAC_H */
diff --git a/src/include/openssl/conf.h b/src/include/openssl/conf.h
index 0d2b61d..b8ec12e 100644
--- a/src/include/openssl/conf.h
+++ b/src/include/openssl/conf.h
@@ -77,7 +77,7 @@
  *   [section_name]
  *   key2=value2
  *
- * Config files are representated by a |CONF|. */
+ * Config files are represented by a |CONF|. */
 
 struct conf_value_st {
   char *section;
@@ -92,10 +92,10 @@
 
 /* NCONF_new returns a fresh, empty |CONF|, or NULL on error. The |method|
  * argument must be NULL. */
-CONF *NCONF_new(void *method);
+OPENSSL_EXPORT CONF *NCONF_new(void *method);
 
 /* NCONF_free frees all the data owned by |conf| and then |conf| itself. */
-void NCONF_free(CONF *conf);
+OPENSSL_EXPORT void NCONF_free(CONF *conf);
 
 /* NCONF_load parses the file named |filename| and adds the values found to
  * |conf|. It returns one on success and zero on error. In the event of an
@@ -152,9 +152,26 @@
 /* CONF_modules_free does nothing. */
 OPENSSL_EXPORT void CONF_modules_free(void);
 
+/* OPENSSL_config does nothing. */
+OPENSSL_EXPORT void OPENSSL_config(CONF_MUST_BE_NULL *config_name);
+
+/* OPENSSL_no_config does nothing. */
+OPENSSL_EXPORT void OPENSSL_no_config(void);
+
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+extern "C++" {
+
+namespace bssl {
+
+BORINGSSL_MAKE_DELETER(CONF, NCONF_free)
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #define CONF_R_LIST_CANNOT_BE_NULL 100
@@ -163,5 +180,6 @@
 #define CONF_R_NO_CLOSE_BRACE 103
 #define CONF_R_UNABLE_TO_CREATE_NEW_SECTION 104
 #define CONF_R_VARIABLE_HAS_NO_VALUE 105
+#define CONF_R_VARIABLE_EXPANSION_TOO_LONG 106
 
 #endif  /* OPENSSL_HEADER_THREAD_H */
diff --git a/src/include/openssl/cpu.h b/src/include/openssl/cpu.h
index e946304..457a476 100644
--- a/src/include/openssl/cpu.h
+++ b/src/include/openssl/cpu.h
@@ -110,30 +110,23 @@
 /* CRYPTO_is_NEON_capable returns true if the current CPU has a NEON unit. If
  * this is known statically then it returns one immediately. */
 static inline int CRYPTO_is_NEON_capable(void) {
-#if defined(__ARM_NEON__)
+  /* Only statically skip the runtime lookup on aarch64. On arm, one CPU is
+   * known to have a broken NEON unit which is known to fail with on some
+   * hand-written NEON assembly. For now, continue to apply the workaround even
+   * when the compiler is instructed to freely emit NEON code. See
+   * https://crbug.com/341598 and https://crbug.com/606629. */
+#if defined(__ARM_NEON__) && !defined(OPENSSL_ARM)
   return 1;
 #else
   return CRYPTO_is_NEON_capable_at_runtime();
 #endif
 }
 
-/* CRYPTO_set_NEON_capable sets the return value of |CRYPTO_is_NEON_capable|.
- * By default, unless the code was compiled with |-mfpu=neon|, NEON is assumed
- * not to be present. It is not autodetected. Calling this with a zero
- * argument also causes |CRYPTO_is_NEON_functional| to return false. */
-OPENSSL_EXPORT void CRYPTO_set_NEON_capable(char neon_capable);
-
-/* CRYPTO_is_NEON_functional returns true if the current CPU has a /working/
- * NEON unit. Some phones have a NEON unit, but the Poly1305 NEON code causes
- * it to fail. See https://code.google.com/p/chromium/issues/detail?id=341598 */
-OPENSSL_EXPORT char CRYPTO_is_NEON_functional(void);
-
-/* CRYPTO_set_NEON_functional sets the "NEON functional" flag. For
- * |CRYPTO_is_NEON_functional| to return true, both this flag and the NEON flag
- * must be true. By default NEON is assumed to be functional if the code was
- * compiled with |-mfpu=neon| or if |CRYPTO_set_NEON_capable| has been called
- * with a non-zero argument. */
-OPENSSL_EXPORT void CRYPTO_set_NEON_functional(char neon_functional);
+#if defined(OPENSSL_ARM)
+/* CRYPTO_has_broken_NEON returns one if the current CPU is known to have a
+ * broken NEON unit. See https://crbug.com/341598. */
+OPENSSL_EXPORT int CRYPTO_has_broken_NEON(void);
+#endif
 
 /* CRYPTO_is_ARMv8_AES_capable returns true if the current CPU supports the
  * ARMv8 AES instruction. */
@@ -153,10 +146,6 @@
 #endif
 }
 
-static inline int CRYPTO_is_NEON_functional(void) {
-  return CRYPTO_is_NEON_capable();
-}
-
 static inline int CRYPTO_is_ARMv8_AES_capable(void) {
 #if defined(OPENSSL_STATIC_ARMCAP_AES)
   return 1;
@@ -174,7 +163,15 @@
 }
 
 #endif  /* OPENSSL_STATIC_ARMCAP */
-#endif  /* OPENSSL_ARM */
+#endif  /* OPENSSL_ARM || OPENSSL_AARCH64 */
+
+#if defined(OPENSSL_PPC64LE)
+
+/* CRYPTO_is_PPC64LE_vcrypto_capable returns true iff the current CPU supports
+ * the Vector.AES category of instructions. */
+int CRYPTO_is_PPC64LE_vcrypto_capable(void);
+
+#endif  /* OPENSSL_PPC64LE */
 
 
 #if defined(__cplusplus)
diff --git a/src/include/openssl/crypto.h b/src/include/openssl/crypto.h
index 193c8c3..3a7e6b1 100644
--- a/src/include/openssl/crypto.h
+++ b/src/include/openssl/crypto.h
@@ -36,13 +36,30 @@
 
 /* CRYPTO_library_init initializes the crypto library. It must be called if the
  * library is built with BORINGSSL_NO_STATIC_INITIALIZER. Otherwise, it does
- * nothing and a static initializer is used instead. */
+ * nothing and a static initializer is used instead. It is safe to call this
+ * function multiple times and concurrently from multiple threads.
+ *
+ * On some ARM configurations, this function may require filesystem access and
+ * should be called before entering a sandbox. */
 OPENSSL_EXPORT void CRYPTO_library_init(void);
 
+/* CRYPTO_is_confidential_build returns one if the linked version of BoringSSL
+ * has been built with the BORINGSSL_CONFIDENTIAL define and zero otherwise.
+ *
+ * This is used by some consumers to identify whether they are using an
+ * internal version of BoringSSL. */
+OPENSSL_EXPORT int CRYPTO_is_confidential_build(void);
+
+/* CRYPTO_has_asm returns one unless BoringSSL was built with OPENSSL_NO_ASM,
+ * in which case it returns zero. */
+OPENSSL_EXPORT int CRYPTO_has_asm(void);
+
 
 /* Deprecated functions. */
 
-#define OPENSSL_VERSION_TEXT "BoringSSL"
+/* OPENSSL_VERSION_TEXT contains a string the identifies the version of
+ * “OpenSSL”. node.js requires a version number in this text. */
+#define OPENSSL_VERSION_TEXT "OpenSSL 1.0.2 (compatible; BoringSSL)"
 
 #define SSLEAY_VERSION 0
 
@@ -60,9 +77,15 @@
 /* ENGINE_load_builtin_engines does nothing. */
 OPENSSL_EXPORT void ENGINE_load_builtin_engines(void);
 
+/* ENGINE_register_all_complete returns one. */
+OPENSSL_EXPORT int ENGINE_register_all_complete(void);
+
 /* OPENSSL_load_builtin_modules does nothing. */
 OPENSSL_EXPORT void OPENSSL_load_builtin_modules(void);
 
+/* FIPS_mode returns zero. */
+OPENSSL_EXPORT int FIPS_mode(void);
+
 
 #if defined(__cplusplus)
 }  /* extern C */
diff --git a/src/include/openssl/curve25519.h b/src/include/openssl/curve25519.h
index 30c6470..1bbb69a 100644
--- a/src/include/openssl/curve25519.h
+++ b/src/include/openssl/curve25519.h
@@ -24,16 +24,18 @@
 
 /* Curve25519.
  *
- * Curve25519 is an elliptic curve. See
- * https://tools.ietf.org/html/draft-irtf-cfrg-curves-11. */
+ * Curve25519 is an elliptic curve. See https://tools.ietf.org/html/rfc7748. */
 
 
 /* X25519.
  *
- * Curve25519 is an elliptic curve. The same name is also sometimes used for
- * the Diffie-Hellman primitive built from it but “X25519” is a more precise
- * name for that, which is the one used here. See http://cr.yp.to/ecdh.html and
- * https://tools.ietf.org/html/draft-irtf-cfrg-curves-11. */
+ * X25519 is the Diffie-Hellman primitive built from curve25519. It is
+ * sometimes referred to as “curve25519”, but “X25519” is a more precise name.
+ * See http://cr.yp.to/ecdh.html and https://tools.ietf.org/html/rfc7748. */
+
+#define X25519_PRIVATE_KEY_LEN 32
+#define X25519_PUBLIC_VALUE_LEN 32
+#define X25519_SHARED_KEY_LEN 32
 
 /* X25519_keypair sets |out_public_value| and |out_private_key| to a freshly
  * generated, public–private key pair. */
@@ -84,9 +86,111 @@
                                   const uint8_t signature[64],
                                   const uint8_t public_key[32]);
 
+/* ED25519_keypair_from_seed calculates a public and private key from an
+ * Ed25519 “seed”. Seed values are not exposed by this API (although they
+ * happen to be the first 32 bytes of a private key) so this function is for
+ * interoperating with systems that may store just a seed instead of a full
+ * private key. */
+OPENSSL_EXPORT void ED25519_keypair_from_seed(uint8_t out_public_key[32],
+                                              uint8_t out_private_key[64],
+                                              const uint8_t seed[32]);
+
+
+/* SPAKE2.
+ *
+ * SPAKE2 is a password-authenticated key-exchange. It allows two parties,
+ * who share a low-entropy secret (i.e. password), to agree on a shared key.
+ * An attacker can only make one guess of the password per execution of the
+ * protocol.
+ *
+ * See https://tools.ietf.org/html/draft-irtf-cfrg-spake2-02. */
+
+/* spake2_role_t enumerates the different “roles” in SPAKE2. The protocol
+ * requires that the symmetry of the two parties be broken so one participant
+ * must be “Alice” and the other be “Bob”. */
+enum spake2_role_t {
+  spake2_role_alice,
+  spake2_role_bob,
+};
+
+/* SPAKE2_CTX_new creates a new |SPAKE2_CTX| (which can only be used for a
+ * single execution of the protocol). SPAKE2 requires the symmetry of the two
+ * parties to be broken which is indicated via |my_role| – each party must pass
+ * a different value for this argument.
+ *
+ * The |my_name| and |their_name| arguments allow optional, opaque names to be
+ * bound into the protocol. For example MAC addresses, hostnames, usernames
+ * etc. These values are not exposed and can avoid context-confusion attacks
+ * when a password is shared between several devices. */
+OPENSSL_EXPORT SPAKE2_CTX *SPAKE2_CTX_new(
+    enum spake2_role_t my_role,
+    const uint8_t *my_name, size_t my_name_len,
+    const uint8_t *their_name, size_t their_name_len);
+
+/* SPAKE2_CTX_free frees |ctx| and all the resources that it has allocated. */
+OPENSSL_EXPORT void SPAKE2_CTX_free(SPAKE2_CTX *ctx);
+
+/* SPAKE2_MAX_MSG_SIZE is the maximum size of a SPAKE2 message. */
+#define SPAKE2_MAX_MSG_SIZE 32
+
+/* SPAKE2_generate_msg generates a SPAKE2 message given |password|, writes
+ * it to |out| and sets |*out_len| to the number of bytes written.
+ *
+ * At most |max_out_len| bytes are written to |out| and, in order to ensure
+ * success, |max_out_len| should be at least |SPAKE2_MAX_MSG_SIZE| bytes.
+ *
+ * This function can only be called once for a given |SPAKE2_CTX|.
+ *
+ * It returns one on success and zero on error. */
+OPENSSL_EXPORT int SPAKE2_generate_msg(SPAKE2_CTX *ctx, uint8_t *out,
+                                       size_t *out_len, size_t max_out_len,
+                                       const uint8_t *password,
+                                       size_t password_len);
+
+/* SPAKE2_MAX_KEY_SIZE is the maximum amount of key material that SPAKE2 will
+ * produce. */
+#define SPAKE2_MAX_KEY_SIZE 64
+
+/* SPAKE2_process_msg completes the SPAKE2 exchange given the peer's message in
+ * |their_msg|, writes at most |max_out_key_len| bytes to |out_key| and sets
+ * |*out_key_len| to the number of bytes written.
+ *
+ * The resulting keying material is suitable for:
+ *   a) Using directly in a key-confirmation step: i.e. each side could
+ *      transmit a hash of their role, a channel-binding value and the key
+ *      material to prove to the other side that they know the shared key.
+ *   b) Using as input keying material to HKDF to generate a variety of subkeys
+ *      for encryption etc.
+ *
+ * If |max_out_key_key| is smaller than the amount of key material generated
+ * then the key is silently truncated. If you want to ensure that no truncation
+ * occurs then |max_out_key| should be at least |SPAKE2_MAX_KEY_SIZE|.
+ *
+ * You must call |SPAKE2_generate_msg| on a given |SPAKE2_CTX| before calling
+ * this function. On successful return, |ctx| is complete and calling
+ * |SPAKE2_CTX_free| is the only acceptable operation on it.
+ *
+ * Returns one on success or zero on error. */
+OPENSSL_EXPORT int SPAKE2_process_msg(SPAKE2_CTX *ctx, uint8_t *out_key,
+                                      size_t *out_key_len,
+                                      size_t max_out_key_len,
+                                      const uint8_t *their_msg,
+                                      size_t their_msg_len);
+
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+extern "C++" {
+
+namespace bssl {
+
+BORINGSSL_MAKE_DELETER(SPAKE2_CTX, SPAKE2_CTX_free)
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #endif  /* OPENSSL_HEADER_CURVE25519_H */
diff --git a/src/include/openssl/dh.h b/src/include/openssl/dh.h
index 2c49fc8..ed2396d 100644
--- a/src/include/openssl/dh.h
+++ b/src/include/openssl/dh.h
@@ -81,10 +81,24 @@
  * count drops to zero. */
 OPENSSL_EXPORT void DH_free(DH *dh);
 
-/* DH_up_ref increments the reference count of |dh|. */
+/* DH_up_ref increments the reference count of |dh| and returns one. */
 OPENSSL_EXPORT int DH_up_ref(DH *dh);
 
 
+/* Properties. */
+
+/* DH_get0_key sets |*out_pub_key| and |*out_priv_key|, if non-NULL, to |dh|'s
+ * public and private key, respectively. If |dh| is a public key, the private
+ * key will be set to NULL. */
+OPENSSL_EXPORT void DH_get0_key(const DH *dh, const BIGNUM **out_pub_key,
+                                const BIGNUM **out_priv_key);
+
+/* DH_get0_pqg sets |*out_p|, |*out_q|, and |*out_g|, if non-NULL, to |dh|'s p,
+ * q, and g parameters, respectively. */
+OPENSSL_EXPORT void DH_get0_pqg(const DH *dh, const BIGNUM **out_p,
+                                const BIGNUM **out_q, const BIGNUM **out_g);
+
+
 /* Standard parameters.
  *
  * These functions return new DH objects with standard parameters. They return
@@ -96,6 +110,11 @@
 OPENSSL_EXPORT DH *DH_get_2048_224(const ENGINE *engine);
 OPENSSL_EXPORT DH *DH_get_2048_256(const ENGINE *engine);
 
+/* BN_get_rfc3526_prime_1536 sets |*ret| to the 1536-bit MODP group from RFC
+ * 3526 and returns |ret|. If |ret| is NULL then a fresh |BIGNUM| is allocated
+ * and returned. It returns NULL on allocation failure. */
+OPENSSL_EXPORT BIGNUM *BN_get_rfc3526_prime_1536(BIGNUM *ret);
+
 
 /* Parameter generation. */
 
@@ -156,8 +175,9 @@
  * Note: these checks may be quite computationally expensive. */
 OPENSSL_EXPORT int DH_check(const DH *dh, int *out_flags);
 
-#define DH_CHECK_PUBKEY_TOO_SMALL 1
-#define DH_CHECK_PUBKEY_TOO_LARGE 2
+#define DH_CHECK_PUBKEY_TOO_SMALL 0x1
+#define DH_CHECK_PUBKEY_TOO_LARGE 0x2
+#define DH_CHECK_PUBKEY_INVALID 0x4
 
 /* DH_check_pub_key checks the suitability of |pub_key| as a public key for the
  * DH group in |dh| and sets |DH_CHECK_PUBKEY_*| flags in |*out_flags| if it
@@ -173,19 +193,15 @@
 
 /* ASN.1 functions. */
 
-/* d2i_DHparams parses an ASN.1, DER encoded Diffie-Hellman parameters
- * structure from |len| bytes at |*inp|. If |ret| is not NULL then, on exit, a
- * pointer to the result is in |*ret|. If |*ret| is already non-NULL on entry
- * then the result is written directly into |*ret|, otherwise a fresh |DH| is
- * allocated. On successful exit, |*inp| is advanced past the DER structure. It
- * returns the result or NULL on error. */
-OPENSSL_EXPORT DH *d2i_DHparams(DH **ret, const unsigned char **inp, long len);
+/* DH_parse_parameters decodes a DER-encoded DHParameter structure (PKCS #3)
+ * from |cbs| and advances |cbs|. It returns a newly-allocated |DH| or NULL on
+ * error. */
+OPENSSL_EXPORT DH *DH_parse_parameters(CBS *cbs);
 
-/* i2d_DHparams marshals |in| to an ASN.1, DER structure. If |outp| is not NULL
- * then the result is written to |*outp| and |*outp| is advanced just past the
- * output. It returns the number of bytes in the result, whether written or
- * not, or a negative value on error. */
-OPENSSL_EXPORT int i2d_DHparams(const DH *in, unsigned char **outp);
+/* DH_marshal_parameters marshals |dh| as a DER-encoded DHParameter structure
+ * (PKCS #3) and appends the result to |cbb|. It returns one on success and zero
+ * on error. */
+OPENSSL_EXPORT int DH_marshal_parameters(CBB *cbb, const DH *dh);
 
 
 /* ex_data functions.
@@ -200,6 +216,36 @@
 OPENSSL_EXPORT void *DH_get_ex_data(DH *d, int idx);
 
 
+/* Deprecated functions. */
+
+/* DH_generate_parameters behaves like |DH_generate_parameters_ex|, which is
+ * what you should use instead. It returns NULL on error, or a newly-allocated
+ * |DH| on success. This function is provided for compatibility only. */
+OPENSSL_EXPORT DH *DH_generate_parameters(int prime_len, int generator,
+                                          void (*callback)(int, int, void *),
+                                          void *cb_arg);
+
+/* d2i_DHparams parses an ASN.1, DER encoded Diffie-Hellman parameters structure
+ * from |len| bytes at |*inp|. If |ret| is not NULL then, on exit, a pointer to
+ * the result is in |*ret|. Note that, even if |*ret| is already non-NULL on
+ * entry, it will not be written to. Rather, a fresh |DH| is allocated and the
+ * previous one is freed.
+ *
+ * On successful exit, |*inp| is advanced past the DER structure. It
+ * returns the result or NULL on error.
+ *
+ * Use |DH_parse_parameters| instead. */
+OPENSSL_EXPORT DH *d2i_DHparams(DH **ret, const unsigned char **inp, long len);
+
+/* i2d_DHparams marshals |in| to an ASN.1, DER structure. If |outp| is not NULL
+ * then the result is written to |*outp| and |*outp| is advanced just past the
+ * output. It returns the number of bytes in the result, whether written or
+ * not, or a negative value on error.
+ *
+ * Use |DH_marshal_parameters| instead. */
+OPENSSL_EXPORT int i2d_DHparams(const DH *in, unsigned char **outp);
+
+
 struct dh_st {
   BIGNUM *p;
   BIGNUM *g;
@@ -228,11 +274,24 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+extern "C++" {
+
+namespace bssl {
+
+BORINGSSL_MAKE_DELETER(DH, DH_free)
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #define DH_R_BAD_GENERATOR 100
 #define DH_R_INVALID_PUBKEY 101
 #define DH_R_MODULUS_TOO_LARGE 102
 #define DH_R_NO_PRIVATE_VALUE 103
+#define DH_R_DECODE_ERROR 104
+#define DH_R_ENCODE_ERROR 105
 
 #endif  /* OPENSSL_HEADER_DH_H */
diff --git a/src/include/openssl/digest.h b/src/include/openssl/digest.h
index 80028ef..2de84f7 100644
--- a/src/include/openssl/digest.h
+++ b/src/include/openssl/digest.h
@@ -102,7 +102,8 @@
  * An EVP_MD_CTX represents the state of a specific digest operation in
  * progress. */
 
-/* EVP_MD_CTX_init initialises an, already allocated, |EVP_MD_CTX|. */
+/* EVP_MD_CTX_init initialises an, already allocated, |EVP_MD_CTX|. This is the
+ * same as setting the structure to zero. */
 OPENSSL_EXPORT void EVP_MD_CTX_init(EVP_MD_CTX *ctx);
 
 /* EVP_MD_CTX_create allocates and initialises a fresh |EVP_MD_CTX| and returns
@@ -143,11 +144,16 @@
  * at least this much space. */
 #define EVP_MAX_MD_SIZE 64 /* SHA-512 is the longest so far. */
 
+/* EVP_MAX_MD_BLOCK_SIZE is the largest digest block size supported, in
+ * bytes. */
+#define EVP_MAX_MD_BLOCK_SIZE 128 /* SHA-512 is the longest so far. */
+
 /* EVP_DigestFinal_ex finishes the digest in |ctx| and writes the output to
- * |md_out|. At most |EVP_MAX_MD_SIZE| bytes are written. If |out_size| is not
- * NULL then |*out_size| is set to the number of bytes written. It returns one.
- * After this call, the hash cannot be updated or finished again until
- * |EVP_DigestInit_ex| is called to start another hashing operation. */
+ * |md_out|. |EVP_MD_CTX_size| bytes are written, which is at most
+ * |EVP_MAX_MD_SIZE|. If |out_size| is not NULL then |*out_size| is set to the
+ * number of bytes written. It returns one. After this call, the hash cannot be
+ * updated or finished again until |EVP_DigestInit_ex| is called to start
+ * another hashing operation. */
 OPENSSL_EXPORT int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, uint8_t *md_out,
                                       unsigned int *out_size);
 
@@ -156,11 +162,11 @@
 OPENSSL_EXPORT int EVP_DigestFinal(EVP_MD_CTX *ctx, uint8_t *md_out,
                                    unsigned int *out_size);
 
-/* EVP_Digest performs a complete hashing operation in one call. It hashes
- * |len| bytes from |data| and writes the digest to |md_out|. At most
- * |EVP_MAX_MD_SIZE| bytes are written. If |out_size| is not NULL then
- * |*out_size| is set to the number of bytes written. It returns one on success
- * and zero otherwise. */
+/* EVP_Digest performs a complete hashing operation in one call. It hashes |len|
+ * bytes from |data| and writes the digest to |md_out|. |EVP_MD_CTX_size| bytes
+ * are written, which is at most |EVP_MAX_MD_SIZE|. If |out_size| is not NULL
+ * then |*out_size| is set to the number of bytes written. It returns one on
+ * success and zero otherwise. */
 OPENSSL_EXPORT int EVP_Digest(const void *data, size_t len, uint8_t *md_out,
                               unsigned int *md_out_size, const EVP_MD *type,
                               ENGINE *impl);
@@ -171,7 +177,7 @@
  * These functions allow code to learn details about an abstract hash
  * function. */
 
-/* EVP_MD_type returns a NID identifing |md|. (For example, |NID_sha256|.) */
+/* EVP_MD_type returns a NID identifying |md|. (For example, |NID_sha256|.) */
 OPENSSL_EXPORT int EVP_MD_type(const EVP_MD *md);
 
 /* EVP_MD_flags returns the flags for |md|, which is a set of |EVP_MD_FLAG_*|
@@ -209,6 +215,12 @@
  * |name|, or NULL if the name is unknown. */
 OPENSSL_EXPORT const EVP_MD *EVP_get_digestbyname(const char *);
 
+/* EVP_dss1 returns the value of EVP_sha1(). This was provided by OpenSSL to
+ * specifiy the original DSA signatures, which were fixed to use SHA-1. Note,
+ * however, that attempting to sign or verify DSA signatures with the EVP
+ * interface will always fail. */
+OPENSSL_EXPORT const EVP_MD *EVP_dss1(void);
+
 
 /* Digest operation accessors. */
 
@@ -218,11 +230,11 @@
 
 /* EVP_MD_CTX_size returns the digest size of |ctx|, in bytes. It
  * will crash if a digest hasn't been set on |ctx|. */
-OPENSSL_EXPORT unsigned EVP_MD_CTX_size(const EVP_MD_CTX *ctx);
+OPENSSL_EXPORT size_t EVP_MD_CTX_size(const EVP_MD_CTX *ctx);
 
 /* EVP_MD_CTX_block_size returns the block size of the digest function used by
  * |ctx|, in bytes. It will crash if a digest hasn't been set on |ctx|. */
-OPENSSL_EXPORT unsigned EVP_MD_CTX_block_size(const EVP_MD_CTX *ctx);
+OPENSSL_EXPORT size_t EVP_MD_CTX_block_size(const EVP_MD_CTX *ctx);
 
 /* EVP_MD_CTX_type returns a NID describing the digest function used by |ctx|.
  * (For example, |NID_sha256|.) It will crash if a digest hasn't been set on
@@ -251,8 +263,27 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+#if !defined(BORINGSSL_NO_CXX)
+extern "C++" {
+
+namespace bssl {
+
+BORINGSSL_MAKE_DELETER(EVP_MD_CTX, EVP_MD_CTX_destroy)
+
+using ScopedEVP_MD_CTX =
+    internal::StackAllocated<EVP_MD_CTX, int, EVP_MD_CTX_init,
+                             EVP_MD_CTX_cleanup>;
+
+}  // namespace bssl
+
+}  // extern C++
+#endif
+
 #endif
 
 #define DIGEST_R_INPUT_NOT_INITIALIZED 100
+#define DIGEST_R_DECODE_ERROR 101
+#define DIGEST_R_UNKNOWN_HASH 102
 
 #endif  /* OPENSSL_HEADER_DIGEST_H */
diff --git a/src/include/openssl/dsa.h b/src/include/openssl/dsa.h
index 2045fe7..2988877 100644
--- a/src/include/openssl/dsa.h
+++ b/src/include/openssl/dsa.h
@@ -71,7 +71,7 @@
 #endif
 
 
-/* DSA contains functions for signing and verifing with the Digital Signature
+/* DSA contains functions for signing and verifying with the Digital Signature
  * Algorithm. */
 
 
@@ -84,10 +84,24 @@
  * reference count drops to zero. */
 OPENSSL_EXPORT void DSA_free(DSA *dsa);
 
-/* DSA_up_ref increments the reference count of |dsa|. */
+/* DSA_up_ref increments the reference count of |dsa| and returns one. */
 OPENSSL_EXPORT int DSA_up_ref(DSA *dsa);
 
 
+/* Properties. */
+
+/* DSA_get0_key sets |*out_pub_key| and |*out_priv_key|, if non-NULL, to |dsa|'s
+ * public and private key, respectively. If |dsa| is a public key, the private
+ * key will be set to NULL. */
+OPENSSL_EXPORT void DSA_get0_key(const DSA *dsa, const BIGNUM **out_pub_key,
+                                 const BIGNUM **out_priv_key);
+
+/* DSA_get0_pqg sets |*out_p|, |*out_q|, and |*out_g|, if non-NULL, to |dsa|'s
+ * p, q, and g parameters, respectively. */
+OPENSSL_EXPORT void DSA_get0_pqg(const DSA *dsa, const BIGNUM **out_p,
+                                 const BIGNUM **out_q, const BIGNUM **out_g);
+
+
 /* Parameter generation. */
 
 /* DSA_generate_parameters_ex generates a set of DSA parameters by following
@@ -128,10 +142,10 @@
 
 /* Signatures. */
 
-/* DSA_SIG contains a DSA signature as a pair of integers. */
-typedef struct DSA_SIG_st {
+/* DSA_SIG_st (aka |DSA_SIG|) contains a DSA signature as a pair of integers. */
+struct DSA_SIG_st {
   BIGNUM *r, *s;
-} DSA_SIG;
+};
 
 /* DSA_SIG_new returns a freshly allocated, DIG_SIG structure or NULL on error.
  * Both |r| and |s| in the signature will be NULL. */
@@ -218,62 +232,41 @@
 
 /* ASN.1 encoding. */
 
-/* d2i_DSA_SIG parses an ASN.1, DER-encoded, DSA signature from |len| bytes at
- * |*inp|. If |out_sig| is not NULL then, on exit, a pointer to the result is
- * in |*out_sig|. If |*out_sig| is already non-NULL on entry then the result is
- * written directly into |*out_sig|, otherwise a fresh |DSA_SIG| is allocated.
- * On successful exit, |*inp| is advanced past the DER structure. It returns
- * the result or NULL on error. */
-OPENSSL_EXPORT DSA_SIG *d2i_DSA_SIG(DSA_SIG **out_sig, const uint8_t **inp,
-                                    long len);
+/* DSA_SIG_parse parses a DER-encoded DSA-Sig-Value structure from |cbs| and
+ * advances |cbs|. It returns a newly-allocated |DSA_SIG| or NULL on error. */
+OPENSSL_EXPORT DSA_SIG *DSA_SIG_parse(CBS *cbs);
 
-/* i2d_DSA_SIG marshals |in| to an ASN.1, DER structure. If |outp| is not NULL
- * then the result is written to |*outp| and |*outp| is advanced just past the
- * output. It returns the number of bytes in the result, whether written or not,
- * or a negative value on error. */
-OPENSSL_EXPORT int i2d_DSA_SIG(const DSA_SIG *in, uint8_t **outp);
+/* DSA_SIG_marshal marshals |sig| as a DER-encoded DSA-Sig-Value and appends the
+ * result to |cbb|. It returns one on success and zero on error. */
+OPENSSL_EXPORT int DSA_SIG_marshal(CBB *cbb, const DSA_SIG *sig);
 
-/* d2i_DSAPublicKey parses an ASN.1, DER-encoded, DSA public key from |len|
- * bytes at |*inp|. If |out| is not NULL then, on exit, a pointer to the result
- * is in |*out|. If |*out| is already non-NULL on entry then the result is
- * written directly into |*out|, otherwise a fresh |DSA| is allocated. On
- * successful exit, |*inp| is advanced past the DER structure. It returns the
- * result or NULL on error. */
-OPENSSL_EXPORT DSA *d2i_DSAPublicKey(DSA **out, const uint8_t **inp, long len);
+/* DSA_parse_public_key parses a DER-encoded DSA public key from |cbs| and
+ * advances |cbs|. It returns a newly-allocated |DSA| or NULL on error. */
+OPENSSL_EXPORT DSA *DSA_parse_public_key(CBS *cbs);
 
-/* i2d_DSAPublicKey marshals a public key from |in| to an ASN.1, DER structure.
- * If |outp| is not NULL then the result is written to |*outp| and |*outp| is
- * advanced just past the output. It returns the number of bytes in the result,
- * whether written or not, or a negative value on error. */
-OPENSSL_EXPORT int i2d_DSAPublicKey(const DSA *in, unsigned char **outp);
+/* DSA_marshal_public_key marshals |dsa| as a DER-encoded DSA public key and
+ * appends the result to |cbb|. It returns one on success and zero on
+ * failure. */
+OPENSSL_EXPORT int DSA_marshal_public_key(CBB *cbb, const DSA *dsa);
 
-/* d2i_DSAPrivateKey parses an ASN.1, DER-encoded, DSA private key from |len|
- * bytes at |*inp|. If |out| is not NULL then, on exit, a pointer to the result
- * is in |*out|. If |*out| is already non-NULL on entry then the result is
- * written directly into |*out|, otherwise a fresh |DSA| is allocated. On
- * successful exit, |*inp| is advanced past the DER structure. It returns the
- * result or NULL on error. */
-OPENSSL_EXPORT DSA *d2i_DSAPrivateKey(DSA **out, const uint8_t **inp, long len);
+/* DSA_parse_private_key parses a DER-encoded DSA private key from |cbs| and
+ * advances |cbs|. It returns a newly-allocated |DSA| or NULL on error. */
+OPENSSL_EXPORT DSA *DSA_parse_private_key(CBS *cbs);
 
-/* i2d_DSAPrivateKey marshals a private key from |in| to an ASN.1, DER structure.
- * If |outp| is not NULL then the result is written to |*outp| and |*outp| is
- * advanced just past the output. It returns the number of bytes in the result,
- * whether written or not, or a negative value on error. */
-OPENSSL_EXPORT int i2d_DSAPrivateKey(const DSA *in, unsigned char **outp);
+/* DSA_marshal_private_key marshals |dsa| as a DER-encoded DSA private key and
+ * appends the result to |cbb|. It returns one on success and zero on
+ * failure. */
+OPENSSL_EXPORT int DSA_marshal_private_key(CBB *cbb, const DSA *dsa);
 
-/* d2i_DSAparams parses ASN.1, DER-encoded, DSA parameters from |len| bytes at
- * |*inp|. If |out| is not NULL then, on exit, a pointer to the result is in
- * |*out|. If |*out| is already non-NULL on entry then the result is written
- * directly into |*out|, otherwise a fresh |DSA| is allocated. On successful
- * exit, |*inp| is advanced past the DER structure. It returns the result or
- * NULL on error. */
-OPENSSL_EXPORT DSA *d2i_DSAparams(DSA **out, const uint8_t **inp, long len);
+/* DSA_parse_parameters parses a DER-encoded Dss-Parms structure (RFC 3279)
+ * from |cbs| and advances |cbs|. It returns a newly-allocated |DSA| or NULL on
+ * error. */
+OPENSSL_EXPORT DSA *DSA_parse_parameters(CBS *cbs);
 
-/* i2d_DSAparams marshals DSA parameters from |in| to an ASN.1, DER structure.
- * If |outp| is not NULL then the result is written to |*outp| and |*outp| is
- * advanced just past the output. It returns the number of bytes in the result,
- * whether written or not, or a negative value on error. */
-OPENSSL_EXPORT int i2d_DSAparams(const DSA *in, unsigned char **outp);
+/* DSA_marshal_parameters marshals |dsa| as a DER-encoded Dss-Parms structure
+ * (RFC 3447) and appends the result to |cbb|. It returns one on success and
+ * zero on failure. */
+OPENSSL_EXPORT int DSA_marshal_parameters(CBB *cbb, const DSA *dsa);
 
 
 /* Precomputation. */
@@ -309,9 +302,93 @@
 OPENSSL_EXPORT void *DSA_get_ex_data(const DSA *d, int idx);
 
 
+/* Deprecated functions. */
+
+/* d2i_DSA_SIG parses an ASN.1, DER-encoded, DSA signature from |len| bytes at
+ * |*inp|. If |out_sig| is not NULL then, on exit, a pointer to the result is
+ * in |*out_sig|. Note that, even if |*out_sig| is already non-NULL on entry, it
+ * will not be written to. Rather, a fresh |DSA_SIG| is allocated and the
+ * previous one is freed. On successful exit, |*inp| is advanced past the DER
+ * structure. It returns the result or NULL on error.
+ *
+ * Use |DSA_SIG_parse| instead. */
+OPENSSL_EXPORT DSA_SIG *d2i_DSA_SIG(DSA_SIG **out_sig, const uint8_t **inp,
+                                    long len);
+
+/* i2d_DSA_SIG marshals |in| to an ASN.1, DER structure. If |outp| is not NULL
+ * then the result is written to |*outp| and |*outp| is advanced just past the
+ * output. It returns the number of bytes in the result, whether written or not,
+ * or a negative value on error.
+ *
+ * Use |DSA_SIG_marshal| instead. */
+OPENSSL_EXPORT int i2d_DSA_SIG(const DSA_SIG *in, uint8_t **outp);
+
+/* d2i_DSAPublicKey parses an ASN.1, DER-encoded, DSA public key from |len|
+ * bytes at |*inp|. If |out| is not NULL then, on exit, a pointer to the result
+ * is in |*out|. Note that, even if |*ou| is already non-NULL on entry, it will
+ * not be written to. Rather, a fresh |DSA| is allocated and the previous one is
+ * freed. On successful exit, |*inp| is advanced past the DER structure. It
+ * returns the result or NULL on error.
+ *
+ * Use |DSA_parse_public_key| instead. */
+OPENSSL_EXPORT DSA *d2i_DSAPublicKey(DSA **out, const uint8_t **inp, long len);
+
+/* i2d_DSAPublicKey marshals a public key from |in| to an ASN.1, DER structure.
+ * If |outp| is not NULL then the result is written to |*outp| and |*outp| is
+ * advanced just past the output. It returns the number of bytes in the result,
+ * whether written or not, or a negative value on error.
+ *
+ * Use |DSA_marshal_public_key| instead. */
+OPENSSL_EXPORT int i2d_DSAPublicKey(const DSA *in, uint8_t **outp);
+
+/* d2i_DSAPrivateKey parses an ASN.1, DER-encoded, DSA private key from |len|
+ * bytes at |*inp|. If |out| is not NULL then, on exit, a pointer to the result
+ * is in |*out|. Note that, even if |*out| is already non-NULL on entry, it will
+ * not be written to. Rather, a fresh |DSA| is allocated and the previous one is
+ * freed. On successful exit, |*inp| is advanced past the DER structure. It
+ * returns the result or NULL on error.
+ *
+ * Use |DSA_parse_private_key| instead. */
+OPENSSL_EXPORT DSA *d2i_DSAPrivateKey(DSA **out, const uint8_t **inp, long len);
+
+/* i2d_DSAPrivateKey marshals a private key from |in| to an ASN.1, DER
+ * structure. If |outp| is not NULL then the result is written to |*outp| and
+ * |*outp| is advanced just past the output. It returns the number of bytes in
+ * the result, whether written or not, or a negative value on error.
+ *
+ * Use |DSA_marshal_private_key| instead. */
+OPENSSL_EXPORT int i2d_DSAPrivateKey(const DSA *in, uint8_t **outp);
+
+/* d2i_DSAparams parses ASN.1, DER-encoded, DSA parameters from |len| bytes at
+ * |*inp|. If |out| is not NULL then, on exit, a pointer to the result is in
+ * |*out|. Note that, even if |*out| is already non-NULL on entry, it will not
+ * be written to. Rather, a fresh |DSA| is allocated and the previous one is
+ * freed. On successful exit, |*inp| is advanced past the DER structure. It
+ * returns the result or NULL on error.
+ *
+ * Use |DSA_parse_parameters| instead. */
+OPENSSL_EXPORT DSA *d2i_DSAparams(DSA **out, const uint8_t **inp, long len);
+
+/* i2d_DSAparams marshals DSA parameters from |in| to an ASN.1, DER structure.
+ * If |outp| is not NULL then the result is written to |*outp| and |*outp| is
+ * advanced just past the output. It returns the number of bytes in the result,
+ * whether written or not, or a negative value on error.
+ *
+ * Use |DSA_marshal_parameters| instead. */
+OPENSSL_EXPORT int i2d_DSAparams(const DSA *in, uint8_t **outp);
+
+/* DSA_generate_parameters is a deprecated version of
+ * |DSA_generate_parameters_ex| that creates and returns a |DSA*|. Don't use
+ * it. */
+OPENSSL_EXPORT DSA *DSA_generate_parameters(int bits, unsigned char *seed,
+                                            int seed_len, int *counter_ret,
+                                            unsigned long *h_ret,
+                                            void (*callback)(int, int, void *),
+                                            void *cb_arg);
+
+
 struct dsa_st {
   long version;
-  int write_params;
   BIGNUM *p;
   BIGNUM *q; /* == 20 */
   BIGNUM *g;
@@ -324,8 +401,9 @@
 
   int flags;
   /* Normally used to cache montgomery values */
-  CRYPTO_MUTEX method_mont_p_lock;
+  CRYPTO_MUTEX method_mont_lock;
   BN_MONT_CTX *method_mont_p;
+  BN_MONT_CTX *method_mont_q;
   CRYPTO_refcount_t references;
   CRYPTO_EX_DATA ex_data;
 };
@@ -333,11 +411,26 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+extern "C++" {
+
+namespace bssl {
+
+BORINGSSL_MAKE_DELETER(DSA, DSA_free)
+BORINGSSL_MAKE_DELETER(DSA_SIG, DSA_SIG_free)
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #define DSA_R_BAD_Q_VALUE 100
 #define DSA_R_MISSING_PARAMETERS 101
 #define DSA_R_MODULUS_TOO_LARGE 102
 #define DSA_R_NEED_NEW_SETUP_VALUES 103
+#define DSA_R_BAD_VERSION 104
+#define DSA_R_DECODE_ERROR 105
+#define DSA_R_ENCODE_ERROR 106
 
 #endif  /* OPENSSL_HEADER_DSA_H */
diff --git a/src/include/openssl/ec.h b/src/include/openssl/ec.h
index 667be3b..a1cd5c7 100644
--- a/src/include/openssl/ec.h
+++ b/src/include/openssl/ec.h
@@ -78,17 +78,24 @@
 /* Low-level operations on elliptic curves. */
 
 
-typedef struct ec_group_st EC_GROUP;
-typedef struct ec_point_st EC_POINT;
-
-/** Enum for the point conversion form as defined in X9.62 (ECDSA)
- *  for the encoding of a elliptic curve point (x,y) */
+/* point_conversion_form_t enumerates forms, as defined in X9.62 (ECDSA), for
+ * the encoding of a elliptic curve point (x,y) */
 typedef enum {
-	/** the point is encoded as z||x, where the octet z specifies 
-	 *  which solution of the quadratic equation y is  */
-	POINT_CONVERSION_COMPRESSED = 2,
-	/** the point is encoded as z||x||y, where z is the octet 0x04  */
-	POINT_CONVERSION_UNCOMPRESSED = 4
+  /* POINT_CONVERSION_COMPRESSED indicates that the point is encoded as z||x,
+   * where the octet z specifies which solution of the quadratic equation y
+   * is. */
+  POINT_CONVERSION_COMPRESSED = 2,
+
+  /* POINT_CONVERSION_UNCOMPRESSED indicates that the point is encoded as
+   * z||x||y, where z is the octet 0x04. */
+  POINT_CONVERSION_UNCOMPRESSED = 4,
+
+  /* POINT_CONVERSION_HYBRID indicates that the point is encoded as z||x||y,
+   * where z specifies which solution of the quadratic equation y is. This is
+   * not supported by the code and has never been observed in use.
+   *
+   * TODO(agl): remove once node.js no longer references this. */
+  POINT_CONVERSION_HYBRID = 6,
 } point_conversion_form_t;
 
 
@@ -179,12 +186,13 @@
                                            const EC_POINT *point);
 
 /* EC_POINT_is_on_curve returns one if |point| is an element of |group| and
- * zero otheriwse. If |ctx| is non-NULL, it may be used. */
+ * and zero otherwise or when an error occurs. This is different from OpenSSL,
+ * which returns -1 on error. If |ctx| is non-NULL, it may be used. */
 OPENSSL_EXPORT int EC_POINT_is_on_curve(const EC_GROUP *group,
                                         const EC_POINT *point, BN_CTX *ctx);
 
-/* EC_POINT_cmp returns zero if |a| is equal to |b|, greater than zero is
- * non-equal and -1 on error. If |ctx| is not NULL, it may be used. */
+/* EC_POINT_cmp returns zero if |a| is equal to |b|, greater than zero if
+ * not equal and -1 on error. If |ctx| is not NULL, it may be used. */
 OPENSSL_EXPORT int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a,
                                 const EC_POINT *b, BN_CTX *ctx);
 
@@ -210,10 +218,10 @@
                                                        BIGNUM *x, BIGNUM *y,
                                                        BN_CTX *ctx);
 
-/* EC_POINT_set_affine_coordinates_GFp sets the value of |p| to be (|x|, |y|).
- * The |ctx| argument may be used if not NULL. It returns one on success or
- * zero on error. Note that, unlike with OpenSSL, it's considered an error if
- * the point is not on the curve. */
+/* EC_POINT_set_affine_coordinates_GFp sets the value of |point| to be
+ * (|x|, |y|). The |ctx| argument may be used if not NULL. It returns one
+ * on success or zero on error. Note that, unlike with OpenSSL, it's
+ * considered an error if the point is not on the curve. */
 OPENSSL_EXPORT int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group,
                                                        EC_POINT *point,
                                                        const BIGNUM *x,
@@ -229,6 +237,13 @@
                                          point_conversion_form_t form,
                                          uint8_t *buf, size_t len, BN_CTX *ctx);
 
+/* EC_POINT_point2cbb behaves like |EC_POINT_point2oct| but appends the
+ * serialised point to |cbb|. It returns one on success and zero on error. */
+OPENSSL_EXPORT int EC_POINT_point2cbb(CBB *out, const EC_GROUP *group,
+                                      const EC_POINT *point,
+                                      point_conversion_form_t form,
+                                      BN_CTX *ctx);
+
 /* EC_POINT_oct2point sets |point| from |len| bytes of X9.62 format
  * serialisation in |buf|. It returns one on success and zero otherwise. The
  * |ctx| argument may be used if not NULL. */
@@ -257,8 +272,8 @@
 OPENSSL_EXPORT int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r,
                                 const EC_POINT *a, BN_CTX *ctx);
 
-/* EC_POINT_invert sets |a| equal to minus |a|. It returns one on success and zero
- * otherwise. If |ctx| is not NULL, it may be used. */
+/* EC_POINT_invert sets |a| equal to minus |a|. It returns one on success and
+ * zero otherwise. If |ctx| is not NULL, it may be used. */
 OPENSSL_EXPORT int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a,
                                    BN_CTX *ctx);
 
@@ -275,27 +290,34 @@
  * on the equation y² = x³ + a·x + b. It returns the new group or NULL on
  * error.
  *
+ * This new group has no generator. It is an error to use a generator-less group
+ * with any functions except for |EC_GROUP_free|, |EC_POINT_new|,
+ * |EC_POINT_set_affine_coordinates_GFp|, and |EC_GROUP_set_generator|.
+ *
  * |EC_GROUP|s returned by this function will always compare as unequal via
  * |EC_GROUP_cmp| (even to themselves). |EC_GROUP_get_curve_name| will always
- * return |NID_undef|. */
+ * return |NID_undef|.
+ *
+ * Avoid using arbitrary curves and use |EC_GROUP_new_by_curve_name| instead. */
 OPENSSL_EXPORT EC_GROUP *EC_GROUP_new_curve_GFp(const BIGNUM *p,
                                                 const BIGNUM *a,
                                                 const BIGNUM *b, BN_CTX *ctx);
 
+/* EC_GROUP_set_generator sets the generator for |group| to |generator|, which
+ * must have the given order and cofactor. It may only be used with |EC_GROUP|
+ * objects returned by |EC_GROUP_new_curve_GFp| and may only be used once on
+ * each group. */
+OPENSSL_EXPORT int EC_GROUP_set_generator(EC_GROUP *group,
+                                          const EC_POINT *generator,
+                                          const BIGNUM *order,
+                                          const BIGNUM *cofactor);
+
 /* EC_GROUP_get_order sets |*order| to the order of |group|, if it's not
  * NULL. It returns one on success and zero otherwise. |ctx| is ignored. Use
  * |EC_GROUP_get0_order| instead. */
 OPENSSL_EXPORT int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order,
                                       BN_CTX *ctx);
 
-/* EC_GROUP_set_generator sets the generator for |group| to |generator|, which
- * must have the given order and cofactor. This should only be used with
- * |EC_GROUP| objects returned by |EC_GROUP_new_curve_GFp|. */
-OPENSSL_EXPORT int EC_GROUP_set_generator(EC_GROUP *group,
-                                          const EC_POINT *generator,
-                                          const BIGNUM *order,
-                                          const BIGNUM *cofactor);
-
 /* EC_GROUP_set_asn1_flag does nothing. */
 OPENSSL_EXPORT void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag);
 
@@ -314,6 +336,19 @@
 OPENSSL_EXPORT void EC_GROUP_set_point_conversion_form(
     EC_GROUP *group, point_conversion_form_t form);
 
+/* EC_builtin_curve describes a supported elliptic curve. */
+typedef struct {
+  int nid;
+  const char *comment;
+} EC_builtin_curve;
+
+/* EC_get_builtin_curves writes at most |max_num_curves| elements to
+ * |out_curves| and returns the total number that it would have written, had
+ * |max_num_curves| been large enough.
+ *
+ * The |EC_builtin_curve| items describe the supported elliptic curves. */
+OPENSSL_EXPORT size_t EC_get_builtin_curves(EC_builtin_curve *out_curves,
+                                            size_t max_num_curves);
 
 /* Old code expects to get EC_KEY from ec.h. */
 #include <openssl/ec_key.h>
@@ -321,6 +356,18 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+extern "C++" {
+
+namespace bssl {
+
+BORINGSSL_MAKE_DELETER(EC_POINT, EC_POINT_free)
+BORINGSSL_MAKE_DELETER(EC_GROUP, EC_GROUP_free)
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #define EC_R_BUFFER_TOO_SMALL 100
@@ -351,5 +398,9 @@
 #define EC_R_WRONG_ORDER 125
 #define EC_R_BIGNUM_OUT_OF_RANGE 126
 #define EC_R_WRONG_CURVE_PARAMETERS 127
+#define EC_R_DECODE_ERROR 128
+#define EC_R_ENCODE_ERROR 129
+#define EC_R_GROUP_MISMATCH 130
+#define EC_R_INVALID_COFACTOR 131
 
 #endif  /* OPENSSL_HEADER_EC_H */
diff --git a/src/include/openssl/ec_key.h b/src/include/openssl/ec_key.h
index afd95d6..1dbae62 100644
--- a/src/include/openssl/ec_key.h
+++ b/src/include/openssl/ec_key.h
@@ -105,8 +105,7 @@
 /* EC_KEY_dup returns a fresh copy of |src| or NULL on error. */
 OPENSSL_EXPORT EC_KEY *EC_KEY_dup(const EC_KEY *src);
 
-/* EC_KEY_up_ref increases the reference count of |key|. It returns one on
- * success and zero otherwise. */
+/* EC_KEY_up_ref increases the reference count of |key| and returns one. */
 OPENSSL_EXPORT int EC_KEY_up_ref(EC_KEY *key);
 
 /* EC_KEY_is_opaque returns one if |key| is opaque and doesn't expose its key
@@ -177,48 +176,37 @@
 
 /* Serialisation. */
 
-/* d2i_ECPrivateKey parses an ASN.1, DER-encoded, private key from |len| bytes
- * at |*inp|. If |out_key| is not NULL then, on exit, a pointer to the result
- * is in |*out_key|. If |*out_key| is already non-NULL on entry then the result
- * is written directly into |*out_key|, otherwise a fresh |EC_KEY| is
- * allocated. On successful exit, |*inp| is advanced past the DER structure. It
- * returns the result or NULL on error. */
-OPENSSL_EXPORT EC_KEY *d2i_ECPrivateKey(EC_KEY **out_key, const uint8_t **inp,
-                                        long len);
+/* EC_KEY_parse_private_key parses a DER-encoded ECPrivateKey structure (RFC
+ * 5915) from |cbs| and advances |cbs|. It returns a newly-allocated |EC_KEY| or
+ * NULL on error. If |group| is non-null, the parameters field of the
+ * ECPrivateKey may be omitted (but must match |group| if present). Otherwise,
+ * the parameters field is required. */
+OPENSSL_EXPORT EC_KEY *EC_KEY_parse_private_key(CBS *cbs,
+                                                const EC_GROUP *group);
 
-/* i2d_ECPrivateKey marshals an EC private key from |key| to an ASN.1, DER
- * structure. If |outp| is not NULL then the result is written to |*outp| and
- * |*outp| is advanced just past the output. It returns the number of bytes in
- * the result, whether written or not, or a negative value on error. */
-OPENSSL_EXPORT int i2d_ECPrivateKey(const EC_KEY *key, uint8_t **outp);
+/* EC_KEY_marshal_private_key marshals |key| as a DER-encoded ECPrivateKey
+ * structure (RFC 5915) and appends the result to |cbb|. It returns one on
+ * success and zero on failure. |enc_flags| is a combination of |EC_PKEY_*|
+ * values and controls whether corresponding fields are omitted. */
+OPENSSL_EXPORT int EC_KEY_marshal_private_key(CBB *cbb, const EC_KEY *key,
+                                              unsigned enc_flags);
 
-/* d2i_ECParameters parses an ASN.1, DER-encoded, set of EC parameters from
- * |len| bytes at |*inp|. If |out_key| is not NULL then, on exit, a pointer to
- * the result is in |*out_key|. If |*out_key| is already non-NULL on entry then
- * the result is written directly into |*out_key|, otherwise a fresh |EC_KEY|
- * is allocated. On successful exit, |*inp| is advanced past the DER structure.
- * It returns the result or NULL on error. */
-OPENSSL_EXPORT EC_KEY *d2i_ECParameters(EC_KEY **out_key, const uint8_t **inp,
-                                        long len);
+/* EC_KEY_parse_curve_name parses a DER-encoded OBJECT IDENTIFIER as a curve
+ * name from |cbs| and advances |cbs|. It returns a newly-allocated |EC_GROUP|
+ * or NULL on error. */
+OPENSSL_EXPORT EC_GROUP *EC_KEY_parse_curve_name(CBS *cbs);
 
-/* i2d_ECParameters marshals EC parameters from |key| to an ASN.1, DER
- * structure. If |outp| is not NULL then the result is written to |*outp| and
- * |*outp| is advanced just past the output. It returns the number of bytes in
- * the result, whether written or not, or a negative value on error. */
-OPENSSL_EXPORT int i2d_ECParameters(const EC_KEY *key, uint8_t **outp);
+/* EC_KEY_marshal_curve_name marshals |group| as a DER-encoded OBJECT IDENTIFIER
+ * and appends the result to |cbb|. It returns one on success and zero on
+ * failure. */
+OPENSSL_EXPORT int EC_KEY_marshal_curve_name(CBB *cbb, const EC_GROUP *group);
 
-/* o2i_ECPublicKey parses an EC point from |len| bytes at |*inp| into
- * |*out_key|. Note that this differs from the d2i format in that |*out_key|
- * must be non-NULL with a group set. On successful exit, |*inp| is advanced by
- * |len| bytes. It returns |*out_key| or NULL on error. */
-OPENSSL_EXPORT EC_KEY *o2i_ECPublicKey(EC_KEY **out_key, const uint8_t **inp,
-                                       long len);
-
-/* i2o_ECPublicKey marshals an EC point from |key|. If |outp| is not NULL then
- * the result is written to |*outp| and |*outp| is advanced just past the
- * output. It returns the number of bytes in the result, whether written or
- * not, or a negative value on error. */
-OPENSSL_EXPORT int i2o_ECPublicKey(const EC_KEY *key, unsigned char **outp);
+/* EC_KEY_parse_parameters parses a DER-encoded ECParameters structure (RFC
+ * 5480) from |cbs| and advances |cbs|. It returns a newly-allocated |EC_GROUP|
+ * or NULL on error. It supports the namedCurve and specifiedCurve options, but
+ * use of specifiedCurve is deprecated. Use |EC_KEY_parse_curve_name|
+ * instead. */
+OPENSSL_EXPORT EC_GROUP *EC_KEY_parse_parameters(CBS *cbs);
 
 
 /* ex_data functions.
@@ -259,7 +247,7 @@
   int (*sign)(const uint8_t *digest, size_t digest_len, uint8_t *sig,
               unsigned int *sig_len, EC_KEY *eckey);
 
-  /* verify matches the arguments and behaviour of |ECDSA_verify|. */
+  /* Ignored. Set this to NULL. */
   int (*verify)(const uint8_t *digest, size_t digest_len, const uint8_t *sig,
                 size_t sig_len, EC_KEY *eckey);
 
@@ -272,9 +260,78 @@
 /* EC_KEY_set_asn1_flag does nothing. */
 OPENSSL_EXPORT void EC_KEY_set_asn1_flag(EC_KEY *key, int flag);
 
+/* d2i_ECPrivateKey parses an ASN.1, DER-encoded, private key from |len| bytes
+ * at |*inp|. If |out_key| is not NULL then, on exit, a pointer to the result
+ * is in |*out_key|. Note that, even if |*out_key| is already non-NULL on entry,
+ * it * will not be written to. Rather, a fresh |EC_KEY| is allocated and the
+ * previous * one is freed. On successful exit, |*inp| is advanced past the DER
+ * structure. It returns the result or NULL on error.
+ *
+ * On input, if |*out_key| is non-NULL and has a group configured, the
+ * parameters field may be omitted but must match that group if present.
+ *
+ * Use |EC_KEY_parse_private_key| instead. */
+OPENSSL_EXPORT EC_KEY *d2i_ECPrivateKey(EC_KEY **out_key, const uint8_t **inp,
+                                        long len);
+
+/* i2d_ECPrivateKey marshals an EC private key from |key| to an ASN.1, DER
+ * structure. If |outp| is not NULL then the result is written to |*outp| and
+ * |*outp| is advanced just past the output. It returns the number of bytes in
+ * the result, whether written or not, or a negative value on error.
+ *
+ * Use |EC_KEY_marshal_private_key| instead. */
+OPENSSL_EXPORT int i2d_ECPrivateKey(const EC_KEY *key, uint8_t **outp);
+
+/* d2i_ECParameters parses an ASN.1, DER-encoded, set of EC parameters from
+ * |len| bytes at |*inp|. If |out_key| is not NULL then, on exit, a pointer to
+ * the result is in |*out_key|. Note that, even if |*out_key| is already
+ * non-NULL on entry, it will not be written to. Rather, a fresh |EC_KEY| is
+ * allocated and the previous one is freed. On successful exit, |*inp| is
+ * advanced past the DER structure. It returns the result or NULL on error.
+ *
+ * Use |EC_KEY_parse_parameters| or |EC_KEY_parse_curve_name| instead. */
+OPENSSL_EXPORT EC_KEY *d2i_ECParameters(EC_KEY **out_key, const uint8_t **inp,
+                                        long len);
+
+/* i2d_ECParameters marshals EC parameters from |key| to an ASN.1, DER
+ * structure. If |outp| is not NULL then the result is written to |*outp| and
+ * |*outp| is advanced just past the output. It returns the number of bytes in
+ * the result, whether written or not, or a negative value on error.
+ *
+ * Use |EC_KEY_marshal_curve_name| instead. */
+OPENSSL_EXPORT int i2d_ECParameters(const EC_KEY *key, uint8_t **outp);
+
+/* o2i_ECPublicKey parses an EC point from |len| bytes at |*inp| into
+ * |*out_key|. Note that this differs from the d2i format in that |*out_key|
+ * must be non-NULL with a group set. On successful exit, |*inp| is advanced by
+ * |len| bytes. It returns |*out_key| or NULL on error.
+ *
+ * Use |EC_POINT_oct2point| instead. */
+OPENSSL_EXPORT EC_KEY *o2i_ECPublicKey(EC_KEY **out_key, const uint8_t **inp,
+                                       long len);
+
+/* i2o_ECPublicKey marshals an EC point from |key|. If |outp| is not NULL then
+ * the result is written to |*outp| and |*outp| is advanced just past the
+ * output. It returns the number of bytes in the result, whether written or
+ * not, or a negative value on error.
+ *
+ * Use |EC_POINT_point2cbb| instead. */
+OPENSSL_EXPORT int i2o_ECPublicKey(const EC_KEY *key, unsigned char **outp);
+
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+extern "C++" {
+
+namespace bssl {
+
+BORINGSSL_MAKE_DELETER(EC_KEY, EC_KEY_free)
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #endif  /* OPENSSL_HEADER_EC_KEY_H */
diff --git a/src/include/openssl/ecdh.h b/src/include/openssl/ecdh.h
index 5fe3ae9..c167503 100644
--- a/src/include/openssl/ecdh.h
+++ b/src/include/openssl/ecdh.h
@@ -85,10 +85,9 @@
  * return value. Otherwise, as many bytes of the shared key as will fit are
  * copied directly to, at most, |outlen| bytes at |out|. It returns the number
  * of bytes written to |out|, or -1 on error. */
-OPENSSL_EXPORT int ECDH_compute_key(void *out, size_t outlen,
-                                    const EC_POINT *pub_key, EC_KEY *priv_key,
-                                    void *(*kdf)(const void *in, size_t inlen,
-                                                 void *out, size_t *outlen));
+OPENSSL_EXPORT int ECDH_compute_key(
+    void *out, size_t outlen, const EC_POINT *pub_key, const EC_KEY *priv_key,
+    void *(*kdf)(const void *in, size_t inlen, void *out, size_t *outlen));
 
 
 #if defined(__cplusplus)
diff --git a/src/include/openssl/ecdsa.h b/src/include/openssl/ecdsa.h
index f3f68eb..8a158b8 100644
--- a/src/include/openssl/ecdsa.h
+++ b/src/include/openssl/ecdsa.h
@@ -66,7 +66,7 @@
  * Algorithm over elliptic curves. */
 
 
-/* Signing and verifing. */
+/* Signing and verifying. */
 
 /* ECDSA_sign signs |digest_len| bytes from |digest| with |key| and writes the
  * resulting signature to |sig|, which must have |ECDSA_size(key)| bytes of
@@ -75,15 +75,15 @@
  * zero otherwise. */
 OPENSSL_EXPORT int ECDSA_sign(int type, const uint8_t *digest,
                               size_t digest_len, uint8_t *sig,
-                              unsigned int *sig_len, EC_KEY *key);
+                              unsigned int *sig_len, const EC_KEY *key);
 
 /* ECDSA_verify verifies that |sig_len| bytes from |sig| constitute a valid
  * signature by |key| of |digest|. (The |type| argument should be zero.) It
  * returns one on success or zero if the signature is invalid or an error
- * occured. */
+ * occurred. */
 OPENSSL_EXPORT int ECDSA_verify(int type, const uint8_t *digest,
                                 size_t digest_len, const uint8_t *sig,
-                                size_t sig_len, EC_KEY *key);
+                                size_t sig_len, const EC_KEY *key);
 
 /* ECDSA_size returns the maximum size of an ECDSA signature using |key|. It
  * returns zero on error. */
@@ -109,13 +109,13 @@
 /* ECDSA_do_sign signs |digest_len| bytes from |digest| with |key| and returns
  * the resulting signature structure, or NULL on error. */
 OPENSSL_EXPORT ECDSA_SIG *ECDSA_do_sign(const uint8_t *digest,
-                                        size_t digest_len, EC_KEY *key);
+                                        size_t digest_len, const EC_KEY *key);
 
 /* ECDSA_do_verify verifies that |sig| constitutes a valid signature by |key|
  * of |digest|. It returns one on success or zero if the signature is invalid
  * or on error. */
 OPENSSL_EXPORT int ECDSA_do_verify(const uint8_t *digest, size_t digest_len,
-                                   const ECDSA_SIG *sig, EC_KEY *key);
+                                   const ECDSA_SIG *sig, const EC_KEY *key);
 
 
 /* Signing with precomputation.
@@ -128,22 +128,22 @@
 /* ECDSA_sign_setup precomputes parts of an ECDSA signing operation. It sets
  * |*kinv| and |*rp| to the precomputed values and uses the |ctx| argument, if
  * not NULL. It returns one on success and zero otherwise. */
-OPENSSL_EXPORT int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv,
-                                    BIGNUM **rp);
+OPENSSL_EXPORT int ECDSA_sign_setup(const EC_KEY *eckey, BN_CTX *ctx,
+                                    BIGNUM **kinv, BIGNUM **rp);
 
 /* ECDSA_do_sign_ex is the same as |ECDSA_do_sign| but takes precomputed values
  * as generated by |ECDSA_sign_setup|. */
 OPENSSL_EXPORT ECDSA_SIG *ECDSA_do_sign_ex(const uint8_t *digest,
                                            size_t digest_len,
                                            const BIGNUM *kinv, const BIGNUM *rp,
-                                           EC_KEY *eckey);
+                                           const EC_KEY *eckey);
 
 /* ECDSA_sign_ex is the same as |ECDSA_sign| but takes precomputed values as
  * generated by |ECDSA_sign_setup|. */
 OPENSSL_EXPORT int ECDSA_sign_ex(int type, const uint8_t *digest,
                                  size_t digest_len, uint8_t *sig,
                                  unsigned int *sig_len, const BIGNUM *kinv,
-                                 const BIGNUM *rp, EC_KEY *eckey);
+                                 const BIGNUM *rp, const EC_KEY *eckey);
 
 
 /* ASN.1 functions. */
@@ -178,10 +178,10 @@
 
 /* d2i_ECDSA_SIG parses an ASN.1, DER-encoded, signature from |len| bytes at
  * |*inp|. If |out| is not NULL then, on exit, a pointer to the result is in
- * |*out|. If |*out| is already non-NULL on entry then the result is written
- * directly into |*out|, otherwise a fresh |ECDSA_SIG| is allocated. On
- * successful exit, |*inp| is advanced past the DER structure. It returns the
- * result or NULL on error. */
+ * |*out|. Note that, even if |*out| is already non-NULL on entry, it will not
+ * be written to. Rather, a fresh |ECDSA_SIG| is allocated and the previous one
+ * is freed. On successful exit, |*inp| is advanced past the DER structure. It
+ * returns the result or NULL on error. */
 OPENSSL_EXPORT ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **out, const uint8_t **inp,
                                         long len);
 
@@ -194,6 +194,17 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+extern "C++" {
+
+namespace bssl {
+
+BORINGSSL_MAKE_DELETER(ECDSA_SIG, ECDSA_SIG_free)
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #define ECDSA_R_BAD_SIGNATURE 100
diff --git a/src/include/openssl/engine.h b/src/include/openssl/engine.h
index 128a2ae..b029ef9 100644
--- a/src/include/openssl/engine.h
+++ b/src/include/openssl/engine.h
@@ -91,6 +91,17 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+extern "C++" {
+
+namespace bssl {
+
+BORINGSSL_MAKE_DELETER(ENGINE, ENGINE_free)
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #define ENGINE_R_OPERATION_NOT_SUPPORTED 100
diff --git a/src/include/openssl/err.h b/src/include/openssl/err.h
index 40361d7..a747b30 100644
--- a/src/include/openssl/err.h
+++ b/src/include/openssl/err.h
@@ -120,7 +120,7 @@
 
 /* Error queue handling functions.
  *
- * Errors in OpenSSL are generally signalled by the return value of a function.
+ * Errors in OpenSSL are generally signaled by the return value of a function.
  * When a function fails it may add an entry to a per-thread error queue,
  * which is managed by the functions in this header.
  *
@@ -306,7 +306,7 @@
   ERR_put_error(ERR_LIB_SYS, 0, 0, __FILE__, __LINE__);
 
 /* ERR_put_error adds an error to the error queue, dropping the least recent
- * error if neccessary for space reasons. */
+ * error if necessary for space reasons. */
 OPENSSL_EXPORT void ERR_put_error(int library, int unused, int reason,
                                   const char *file, unsigned line);
 
@@ -317,7 +317,8 @@
 
 /* ERR_add_error_dataf takes a printf-style format and arguments, and sets the
  * result as the data on the most recent error. */
-OPENSSL_EXPORT void ERR_add_error_dataf(const char *format, ...);
+OPENSSL_EXPORT void ERR_add_error_dataf(const char *format, ...)
+    OPENSSL_PRINTF_FORMAT_FUNC(1, 2);
 
 /* ERR_set_mark "marks" the most recent error for use with |ERR_pop_to_mark|.
  * It returns one if an error was marked and zero if there are no errors. */
@@ -330,14 +331,14 @@
 OPENSSL_EXPORT int ERR_pop_to_mark(void);
 
 struct err_error_st {
-  /* file contains the filename where the error occured. */
+  /* file contains the filename where the error occurred. */
   const char *file;
   /* data contains optional data. It must be freed with |OPENSSL_free| if
    * |flags&ERR_FLAG_MALLOCED|. */
   char *data;
   /* packed contains the error library and reason, as packed by ERR_PACK. */
   uint32_t packed;
-  /* line contains the line number where the error occured. */
+  /* line contains the line number where the error occurred. */
   uint16_t line;
   /* flags contains a bitwise-OR of ERR_FLAG_* values. */
   uint8_t flags;
@@ -367,7 +368,7 @@
 /* ERR_NUM_ERRORS is the limit of the number of errors in the queue. */
 #define ERR_NUM_ERRORS 16
 
-/* ERR_STATE contains the per-thread, error queue. */
+/* err_state_st (aka |ERR_STATE|) contains the per-thread, error queue. */
 typedef struct err_state_st {
   /* errors contains the ERR_NUM_ERRORS most recent errors, organised as a ring
    * buffer. */
@@ -466,7 +467,7 @@
 #define ERR_R_OVERFLOW (5 | ERR_R_FATAL)
 
 #define ERR_PACK(lib, reason)                                              \
-  (((((uint32_t)lib) & 0xff) << 24) | ((((uint32_t)reason) & 0xfff)))
+  (((((uint32_t)(lib)) & 0xff) << 24) | ((((uint32_t)(reason)) & 0xfff)))
 
 #define ERR_GET_LIB(packed_error) ((int)(((packed_error) >> 24) & 0xff))
 #define ERR_GET_FUNC(packed_error) 0
diff --git a/src/include/openssl/evp.h b/src/include/openssl/evp.h
index be2ea33..7debbc5 100644
--- a/src/include/openssl/evp.h
+++ b/src/include/openssl/evp.h
@@ -69,7 +69,7 @@
 #include <openssl/base64.h>
 #include <openssl/cipher.h>
 #include <openssl/digest.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
 
 #if defined(__cplusplus)
 extern "C" {
@@ -89,8 +89,8 @@
  * itself. */
 OPENSSL_EXPORT void EVP_PKEY_free(EVP_PKEY *pkey);
 
-/* EVP_PKEY_up_ref increments the reference count of |pkey| and returns it. */
-OPENSSL_EXPORT EVP_PKEY *EVP_PKEY_up_ref(EVP_PKEY *pkey);
+/* EVP_PKEY_up_ref increments the reference count of |pkey| and returns one. */
+OPENSSL_EXPORT int EVP_PKEY_up_ref(EVP_PKEY *pkey);
 
 /* EVP_PKEY_is_opaque returns one if |pkey| is opaque. Opaque keys are backed by
  * custom implementations which do not expose key material and parameters. It is
@@ -133,8 +133,8 @@
  * values. */
 OPENSSL_EXPORT int EVP_PKEY_id(const EVP_PKEY *pkey);
 
-/* EVP_PKEY_type returns a canonicalised form of |NID|. For example,
- * |EVP_PKEY_RSA2| will be turned into |EVP_PKEY_RSA|. */
+/* EVP_PKEY_type returns |nid| if |nid| is a known key type and |NID_undef|
+ * otherwise. */
 OPENSSL_EXPORT int EVP_PKEY_type(int nid);
 
 
@@ -165,7 +165,6 @@
 
 #define EVP_PKEY_NONE NID_undef
 #define EVP_PKEY_RSA NID_rsaEncryption
-#define EVP_PKEY_RSA2 NID_rsa
 #define EVP_PKEY_DSA NID_dsa
 #define EVP_PKEY_EC NID_X9_62_id_ecPublicKey
 
@@ -175,7 +174,7 @@
 OPENSSL_EXPORT int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key);
 
 /* EVP_PKEY_set_type sets the type of |pkey| to |type|, which should be one of
- * the |EVP_PKEY_*| values. It returns one if sucessful or zero otherwise. If
+ * the |EVP_PKEY_*| values. It returns one if successful or zero otherwise. If
  * |pkey| is NULL, it simply reports whether the type is known. */
 OPENSSL_EXPORT int EVP_PKEY_set_type(EVP_PKEY *pkey, int type);
 
@@ -189,34 +188,37 @@
 
 /* ASN.1 functions */
 
-/* d2i_PrivateKey parses an ASN.1, DER-encoded, private key from |len| bytes at
- * |*inp|. If |out| is not NULL then, on exit, a pointer to the result is in
- * |*out|. If |*out| is already non-NULL on entry then the result is written
- * directly into |*out|, otherwise a fresh |EVP_PKEY| is allocated. On
- * successful exit, |*inp| is advanced past the DER structure. It returns the
- * result or NULL on error. */
-OPENSSL_EXPORT EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **out,
-                                        const uint8_t **inp, long len);
-
-/* d2i_AutoPrivateKey acts the same as |d2i_PrivateKey|, but detects the type
- * of the private key. */
-OPENSSL_EXPORT EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **out, const uint8_t **inp,
-                                            long len);
-
-/* i2d_PrivateKey marshals a private key from |key| to an ASN.1, DER
- * structure. If |outp| is not NULL then the result is written to |*outp| and
- * |*outp| is advanced just past the output. It returns the number of bytes in
- * the result, whether written or not, or a negative value on error. */
-OPENSSL_EXPORT int i2d_PrivateKey(const EVP_PKEY *key, uint8_t **outp);
-
-/* i2d_PublicKey marshals a public key from |key| to a type-specific format.
- * If |outp| is not NULL then the result is written to |*outp| and
- * |*outp| is advanced just past the output. It returns the number of bytes in
- * the result, whether written or not, or a negative value on error.
+/* EVP_parse_public_key decodes a DER-encoded SubjectPublicKeyInfo structure
+ * (RFC 5280) from |cbs| and advances |cbs|. It returns a newly-allocated
+ * |EVP_PKEY| or NULL on error.
  *
- * RSA keys are serialized as a DER-encoded RSAPublicKey (RFC 3447) structure.
- * EC keys are serialized as an EC point per SEC 1. */
-OPENSSL_EXPORT int i2d_PublicKey(EVP_PKEY *key, uint8_t **outp);
+ * The caller must check the type of the parsed public key to ensure it is
+ * suitable and validate other desired key properties such as RSA modulus size
+ * or EC curve. */
+OPENSSL_EXPORT EVP_PKEY *EVP_parse_public_key(CBS *cbs);
+
+/* EVP_marshal_public_key marshals |key| as a DER-encoded SubjectPublicKeyInfo
+ * structure (RFC 5280) and appends the result to |cbb|. It returns one on
+ * success and zero on error. */
+OPENSSL_EXPORT int EVP_marshal_public_key(CBB *cbb, const EVP_PKEY *key);
+
+/* EVP_parse_private_key decodes a DER-encoded PrivateKeyInfo structure (RFC
+ * 5208) from |cbs| and advances |cbs|. It returns a newly-allocated |EVP_PKEY|
+ * or NULL on error.
+ *
+ * The caller must check the type of the parsed private key to ensure it is
+ * suitable and validate other desired key properties such as RSA modulus size
+ * or EC curve.
+ *
+ * A PrivateKeyInfo ends with an optional set of attributes. These are not
+ * processed and so this function will silently ignore any trailing data in the
+ * structure. */
+OPENSSL_EXPORT EVP_PKEY *EVP_parse_private_key(CBS *cbs);
+
+/* EVP_marshal_private_key marshals |key| as a DER-encoded PrivateKeyInfo
+ * structure (RFC 5208) and appends the result to |cbb|. It returns one on
+ * success and zero on error. */
+OPENSSL_EXPORT int EVP_marshal_private_key(CBB *cbb, const EVP_PKEY *key);
 
 
 /* Signing */
@@ -248,15 +250,6 @@
 OPENSSL_EXPORT int EVP_DigestSignFinal(EVP_MD_CTX *ctx, uint8_t *out_sig,
                                        size_t *out_sig_len);
 
-/* EVP_DigestSignAlgorithm encodes the signing parameters of |ctx| as an
- * AlgorithmIdentifer and saves the result in |algor|.
- *
- * It returns one on success, or zero on error.
- *
- * TODO(davidben): This API should eventually lose the dependency on
- * crypto/asn1/. */
-OPENSSL_EXPORT int EVP_DigestSignAlgorithm(EVP_MD_CTX *ctx, X509_ALGOR *algor);
-
 
 /* Verifying */
 
@@ -271,18 +264,6 @@
                                         const EVP_MD *type, ENGINE *e,
                                         EVP_PKEY *pkey);
 
-/* EVP_DigestVerifyInitFromAlgorithm sets up |ctx| for a signature verification
- * operation with public key |pkey| and parameters from |algor|. The |ctx|
- * argument must have been initialised with |EVP_MD_CTX_init|.
- *
- * It returns one on success, or zero on error.
- *
- * TODO(davidben): This API should eventually lose the dependency on
- * crypto/asn1/. */
-OPENSSL_EXPORT int EVP_DigestVerifyInitFromAlgorithm(EVP_MD_CTX *ctx,
-                                                     X509_ALGOR *algor,
-                                                     EVP_PKEY *pkey);
-
 /* EVP_DigestVerifyUpdate appends |len| bytes from |data| to the data which
  * will be verified by |EVP_DigestVerifyFinal|. It returns one. */
 OPENSSL_EXPORT int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *data,
@@ -397,9 +378,10 @@
 /* PKCS5_PBKDF2_HMAC_SHA1 is the same as PKCS5_PBKDF2_HMAC, but with |digest|
  * fixed to |EVP_sha1|. */
 OPENSSL_EXPORT int PKCS5_PBKDF2_HMAC_SHA1(const char *password,
-                                          size_t password_len, const uint8_t *salt,
-                                          size_t salt_len, unsigned iterations,
-                                          size_t key_len, uint8_t *out_key);
+                                          size_t password_len,
+                                          const uint8_t *salt, size_t salt_len,
+                                          unsigned iterations, size_t key_len,
+                                          uint8_t *out_key);
 
 
 /* Public key contexts.
@@ -427,14 +409,6 @@
 /* EVP_PKEY_CTX_get0_pkey returns the |EVP_PKEY| associated with |ctx|. */
 OPENSSL_EXPORT EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx);
 
-/* EVP_PKEY_CTX_set_app_data sets an opaque pointer on |ctx|. */
-OPENSSL_EXPORT void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data);
-
-/* EVP_PKEY_CTX_get_app_data returns the opaque pointer from |ctx| that was
- * previously set with |EVP_PKEY_CTX_set_app_data|, or NULL if none has been
- * set. */
-OPENSSL_EXPORT void *EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx);
-
 /* EVP_PKEY_sign_init initialises an |EVP_PKEY_CTX| for a signing operation. It
  * should be called before |EVP_PKEY_sign|.
  *
@@ -462,8 +436,8 @@
  * It returns one on success or zero on error. */
 OPENSSL_EXPORT int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx);
 
-/* EVP_PKEY_verify verifies that |sig_len| bytes from |sig| are a valid signature
- * for |data|.
+/* EVP_PKEY_verify verifies that |sig_len| bytes from |sig| are a valid
+ * signature for |data|.
  *
  * It returns one on success or zero on error. */
 OPENSSL_EXPORT int EVP_PKEY_verify(EVP_PKEY_CTX *ctx, const uint8_t *sig,
@@ -510,6 +484,34 @@
                                     size_t *out_len, const uint8_t *in,
                                     size_t in_len);
 
+/* EVP_PKEY_verify_recover_init initialises an |EVP_PKEY_CTX| for a public-key
+ * decryption operation. It should be called before |EVP_PKEY_verify_recover|.
+ *
+ * Public-key decryption is a very obscure operation that is only implemented
+ * by RSA keys. It is effectively a signature verification operation that
+ * returns the signed message directly. It is almost certainly not what you
+ * want.
+ *
+ * It returns one on success or zero on error. */
+OPENSSL_EXPORT int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx);
+
+/* EVP_PKEY_verify_recover decrypts |sig_len| bytes from |sig|. If |out| is
+ * NULL, the maximum size of the plaintext is written to |out_len|. Otherwise,
+ * |*out_len| must contain the number of bytes of space available at |out|. If
+ * sufficient, the ciphertext will be written to |out| and |*out_len| updated
+ * with the true length.
+ *
+ * WARNING: Setting |out| to NULL only gives the maximum size of the
+ * plaintext. The actual plaintext may be smaller.
+ *
+ * See the warning about this operation in |EVP_PKEY_verify_recover_init|. It
+ * is probably not what you want.
+ *
+ * It returns one on success or zero on error. */
+OPENSSL_EXPORT int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx, uint8_t *out,
+                                           size_t *out_len, const uint8_t *sig,
+                                           size_t siglen);
+
 /* EVP_PKEY_derive_init initialises an |EVP_PKEY_CTX| for a key derivation
  * operation. It should be called before |EVP_PKEY_derive_set_peer| and
  * |EVP_PKEY_derive|.
@@ -576,7 +578,10 @@
 /* EVP_PKEY_CTX_set_rsa_pss_saltlen sets the length of the salt in a PSS-padded
  * signature. A value of -1 cause the salt to be the same length as the digest
  * in the signature. A value of -2 causes the salt to be the maximum length
- * that will fit. Otherwise the value gives the size of the salt in bytes.
+ * that will fit when signing and recovered from the signature when verifying.
+ * Otherwise the value gives the size of the salt in bytes.
+ *
+ * If unsure, use -1.
  *
  * Returns one on success or zero on error. */
 OPENSSL_EXPORT int EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX *ctx,
@@ -628,7 +633,7 @@
  *
  * Returns one on success or zero on error. */
 OPENSSL_EXPORT int EVP_PKEY_CTX_set0_rsa_oaep_label(EVP_PKEY_CTX *ctx,
-                                                    const uint8_t *label,
+                                                    uint8_t *label,
                                                     size_t label_len);
 
 /* EVP_PKEY_CTX_get0_rsa_oaep_label sets |*out_label| to point to the internal
@@ -646,9 +651,16 @@
  * |EVP_PKEY| of that type. */
 #define EVP_PKEY_DH NID_dhKeyAgreement
 
+/* EVP_PKEY_RSA2 was historically an alternate form for RSA public keys (OID
+ * 2.5.8.1.1), but is no longer accepted. */
+#define EVP_PKEY_RSA2 NID_rsa
+
 /* OpenSSL_add_all_algorithms does nothing. */
 OPENSSL_EXPORT void OpenSSL_add_all_algorithms(void);
 
+/* OPENSSL_add_all_algorithms_conf does nothing. */
+OPENSSL_EXPORT void OPENSSL_add_all_algorithms_conf(void);
+
 /* OpenSSL_add_all_ciphers does nothing. */
 OPENSSL_EXPORT void OpenSSL_add_all_ciphers(void);
 
@@ -658,22 +670,66 @@
 /* EVP_cleanup does nothing. */
 OPENSSL_EXPORT void EVP_cleanup(void);
 
+OPENSSL_EXPORT void EVP_CIPHER_do_all_sorted(
+    void (*callback)(const EVP_CIPHER *cipher, const char *name,
+                     const char *unused, void *arg),
+    void *arg);
 
-/* Private functions */
+OPENSSL_EXPORT void EVP_MD_do_all_sorted(void (*callback)(const EVP_MD *cipher,
+                                                          const char *name,
+                                                          const char *unused,
+                                                          void *arg),
+                                         void *arg);
 
-/* EVP_PKEY_asn1_find returns the ASN.1 method table for the given |nid|, which
- * should be one of the |EVP_PKEY_*| values. It returns NULL if |nid| is
- * unknown. */
-OPENSSL_EXPORT const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pengine,
-                                                              int nid);
-
-/* EVP_PKEY_asn1_find_str returns an |EVP_PKEY_ASN1_METHOD| by matching values
- * of the |len| bytes at |name|. For example, if name equals "EC" then it will
- * return an ECC method. The |pengine| argument is ignored.
+/* i2d_PrivateKey marshals a private key from |key| to an ASN.1, DER
+ * structure. If |outp| is not NULL then the result is written to |*outp| and
+ * |*outp| is advanced just past the output. It returns the number of bytes in
+ * the result, whether written or not, or a negative value on error.
  *
- * TODO(fork): move to PEM? */
-OPENSSL_EXPORT const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(
-    ENGINE **pengine, const char *name, size_t len);
+ * RSA keys are serialized as a DER-encoded RSAPublicKey (RFC 3447) structure.
+ * EC keys are serialized as a DER-encoded ECPrivateKey (RFC 5915) structure.
+ *
+ * Use |RSA_marshal_private_key| or |EC_marshal_private_key| instead. */
+OPENSSL_EXPORT int i2d_PrivateKey(const EVP_PKEY *key, uint8_t **outp);
+
+/* i2d_PublicKey marshals a public key from |key| to a type-specific format.
+ * If |outp| is not NULL then the result is written to |*outp| and
+ * |*outp| is advanced just past the output. It returns the number of bytes in
+ * the result, whether written or not, or a negative value on error.
+ *
+ * RSA keys are serialized as a DER-encoded RSAPublicKey (RFC 3447) structure.
+ * EC keys are serialized as an EC point per SEC 1.
+ *
+ * Use |RSA_marshal_public_key| or |EC_POINT_point2cbb| instead. */
+OPENSSL_EXPORT int i2d_PublicKey(EVP_PKEY *key, uint8_t **outp);
+
+/* d2i_PrivateKey parses an ASN.1, DER-encoded, private key from |len| bytes at
+ * |*inp|. If |out| is not NULL then, on exit, a pointer to the result is in
+ * |*out|. Note that, even if |*out| is already non-NULL on entry, it will not
+ * be written to. Rather, a fresh |EVP_PKEY| is allocated and the previous one
+ * is freed. On successful exit, |*inp| is advanced past the DER structure. It
+ * returns the result or NULL on error.
+ *
+ * This function tries to detect one of several formats. Instead, use
+ * |EVP_parse_private_key| for a PrivateKeyInfo, |RSA_parse_private_key| for an
+ * RSAPrivateKey, and |EC_parse_private_key| for an ECPrivateKey. */
+OPENSSL_EXPORT EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **out,
+                                        const uint8_t **inp, long len);
+
+/* d2i_AutoPrivateKey acts the same as |d2i_PrivateKey|, but detects the type
+ * of the private key.
+ *
+ * This function tries to detect one of several formats. Instead, use
+ * |EVP_parse_private_key| for a PrivateKeyInfo, |RSA_parse_private_key| for an
+ * RSAPrivateKey, and |EC_parse_private_key| for an ECPrivateKey. */
+OPENSSL_EXPORT EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **out, const uint8_t **inp,
+                                            long len);
+
+/* EVP_PKEY_get0_DH returns NULL. */
+OPENSSL_EXPORT DH *EVP_PKEY_get0_DH(EVP_PKEY *pkey);
+
+
+/* Private structures. */
 
 struct evp_pkey_st {
   CRYPTO_refcount_t references;
@@ -698,53 +754,48 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+extern "C++" {
+namespace bssl {
+
+BORINGSSL_MAKE_DELETER(EVP_PKEY, EVP_PKEY_free)
+BORINGSSL_MAKE_DELETER(EVP_PKEY_CTX, EVP_PKEY_CTX_free)
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #define EVP_R_BUFFER_TOO_SMALL 100
 #define EVP_R_COMMAND_NOT_SUPPORTED 101
-#define EVP_R_DIFFERENT_KEY_TYPES 104
-#define EVP_R_DIFFERENT_PARAMETERS 105
-#define EVP_R_EXPECTING_AN_EC_KEY_KEY 107
-#define EVP_R_EXPECTING_A_DH_KEY 109
-#define EVP_R_EXPECTING_A_DSA_KEY 110
-#define EVP_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE 111
-#define EVP_R_INVALID_CURVE 112
-#define EVP_R_INVALID_DIGEST_LENGTH 113
-#define EVP_R_INVALID_DIGEST_TYPE 114
-#define EVP_R_INVALID_KEYBITS 115
-#define EVP_R_INVALID_MGF1_MD 116
-#define EVP_R_INVALID_PADDING_MODE 118
-#define EVP_R_INVALID_PSS_PARAMETERS 119
-#define EVP_R_INVALID_SALT_LENGTH 121
-#define EVP_R_INVALID_TRAILER 122
-#define EVP_R_KEYS_NOT_SET 123
-#define EVP_R_MISSING_PARAMETERS 124
-#define EVP_R_NO_DEFAULT_DIGEST 125
-#define EVP_R_NO_KEY_SET 126
-#define EVP_R_NO_MDC2_SUPPORT 127
-#define EVP_R_NO_NID_FOR_CURVE 128
-#define EVP_R_NO_OPERATION_SET 129
-#define EVP_R_NO_PARAMETERS_SET 130
-#define EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE 131
-#define EVP_R_OPERATON_NOT_INITIALIZED 132
-#define EVP_R_UNKNOWN_DIGEST 133
-#define EVP_R_UNKNOWN_MASK_DIGEST 134
-#define EVP_R_UNSUPPORTED_ALGORITHM 138
-#define EVP_R_UNSUPPORTED_MASK_ALGORITHM 139
-#define EVP_R_UNSUPPORTED_MASK_PARAMETER 140
-#define EVP_R_EXPECTING_AN_RSA_KEY 141
-#define EVP_R_INVALID_OPERATION 142
-#define EVP_R_DECODE_ERROR 143
-#define EVP_R_INVALID_PSS_SALTLEN 144
-#define EVP_R_UNKNOWN_PUBLIC_KEY_TYPE 145
-#define EVP_R_CONTEXT_NOT_INITIALISED 146
-#define EVP_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED 147
-#define EVP_R_WRONG_PUBLIC_KEY_TYPE 148
-#define EVP_R_UNKNOWN_SIGNATURE_ALGORITHM 149
-#define EVP_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM 150
-#define EVP_R_BN_DECODE_ERROR 151
-#define EVP_R_PARAMETER_ENCODING_ERROR 152
-#define EVP_R_UNSUPPORTED_PUBLIC_KEY_TYPE 153
-#define EVP_R_UNSUPPORTED_SIGNATURE_TYPE 154
+#define EVP_R_DECODE_ERROR 102
+#define EVP_R_DIFFERENT_KEY_TYPES 103
+#define EVP_R_DIFFERENT_PARAMETERS 104
+#define EVP_R_ENCODE_ERROR 105
+#define EVP_R_EXPECTING_AN_EC_KEY_KEY 106
+#define EVP_R_EXPECTING_AN_RSA_KEY 107
+#define EVP_R_EXPECTING_A_DSA_KEY 108
+#define EVP_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE 109
+#define EVP_R_INVALID_DIGEST_LENGTH 110
+#define EVP_R_INVALID_DIGEST_TYPE 111
+#define EVP_R_INVALID_KEYBITS 112
+#define EVP_R_INVALID_MGF1_MD 113
+#define EVP_R_INVALID_OPERATION 114
+#define EVP_R_INVALID_PADDING_MODE 115
+#define EVP_R_INVALID_PSS_SALTLEN 116
+#define EVP_R_KEYS_NOT_SET 117
+#define EVP_R_MISSING_PARAMETERS 118
+#define EVP_R_NO_DEFAULT_DIGEST 119
+#define EVP_R_NO_KEY_SET 120
+#define EVP_R_NO_MDC2_SUPPORT 121
+#define EVP_R_NO_NID_FOR_CURVE 122
+#define EVP_R_NO_OPERATION_SET 123
+#define EVP_R_NO_PARAMETERS_SET 124
+#define EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE 125
+#define EVP_R_OPERATON_NOT_INITIALIZED 126
+#define EVP_R_UNKNOWN_PUBLIC_KEY_TYPE 127
+#define EVP_R_UNSUPPORTED_ALGORITHM 128
+#define EVP_R_UNSUPPORTED_PUBLIC_KEY_TYPE 129
 
 #endif  /* OPENSSL_HEADER_EVP_H */
diff --git a/src/include/openssl/hkdf.h b/src/include/openssl/hkdf.h
index b7a0dc2..bffb01e 100644
--- a/src/include/openssl/hkdf.h
+++ b/src/include/openssl/hkdf.h
@@ -17,14 +17,17 @@
 
 #include <openssl/base.h>
 
-#ifdef  __cplusplus
+#if defined(__cplusplus)
 extern "C" {
 #endif
 
 
-/* Computes HKDF (as specified by RFC 5869) of initial keying material |secret|
- * with |salt| and |info| using |digest|, and outputs |out_len| bytes to
- * |out_key|. It returns one on success and zero on error.
+/* HKDF. */
+
+
+/* HKDF computes HKDF (as specified by RFC 5869) of initial keying material
+ * |secret| with |salt| and |info| using |digest|, and outputs |out_len| bytes
+ * to |out_key|. It returns one on success and zero on error.
  *
  * HKDF is an Extract-and-Expand algorithm. It does not do any key stretching,
  * and as such, is not suited to be used alone to generate a key from a
@@ -34,6 +37,23 @@
                         const uint8_t *salt, size_t salt_len,
                         const uint8_t *info, size_t info_len);
 
+/* HKDF_extract computes a HKDF PRK (as specified by RFC 5869) from initial
+ * keying material |secret| and salt |salt| using |digest|, and outputs
+ * |out_len| bytes to |out_key|. The maximum output size is |EVP_MAX_MD_SIZE|.
+ * It returns one on success and zero on error. */
+OPENSSL_EXPORT int HKDF_extract(uint8_t *out_key, size_t *out_len,
+                                const EVP_MD *digest, const uint8_t *secret,
+                                size_t secret_len, const uint8_t *salt,
+                                size_t salt_len);
+
+/* HKDF_expand computes a HKDF OKM (as specified by RFC 5869) of length
+ * |out_len| from the PRK |prk| and info |info| using |digest|, and outputs
+ * the result to |out_key|. It returns one on success and zero on error. */
+OPENSSL_EXPORT int HKDF_expand(uint8_t *out_key, size_t out_len,
+                               const EVP_MD *digest, const uint8_t *prk,
+                               size_t prk_len, const uint8_t *info,
+                               size_t info_len);
+
 
 #if defined(__cplusplus)
 }  /* extern C */
diff --git a/src/include/openssl/hmac.h b/src/include/openssl/hmac.h
index e521212..e4cc04e 100644
--- a/src/include/openssl/hmac.h
+++ b/src/include/openssl/hmac.h
@@ -74,8 +74,9 @@
 
 /* HMAC calculates the HMAC of |data_len| bytes of |data|, using the given key
  * and hash function, and writes the result to |out|. On entry, |out| must
- * contain |EVP_MAX_MD_SIZE| bytes of space. The actual length of the result is
- * written to |*out_len|. It returns |out| or NULL on error. */
+ * contain at least |EVP_MD_size| bytes of space. The actual length of the
+ * result is written to |*out_len|. An output size of |EVP_MAX_MD_SIZE| will
+ * always be large enough. It returns |out| or NULL on error. */
 OPENSSL_EXPORT uint8_t *HMAC(const EVP_MD *evp_md, const void *key,
                              size_t key_len, const uint8_t *data,
                              size_t data_len, uint8_t *out,
@@ -112,8 +113,9 @@
 
 /* HMAC_Final completes the HMAC operation in |ctx| and writes the result to
  * |out| and the sets |*out_len| to the length of the result. On entry, |out|
- * must contain at least |EVP_MAX_MD_SIZE| bytes of space. It returns one on
- * success or zero on error. */
+ * must contain at least |HMAC_size| bytes of space. An output size of
+ * |EVP_MAX_MD_SIZE| will always be large enough. It returns one on success or
+ * zero on error. */
 OPENSSL_EXPORT int HMAC_Final(HMAC_CTX *ctx, uint8_t *out,
                               unsigned int *out_len);
 
@@ -143,8 +145,6 @@
 
 /* Private functions */
 
-#define HMAC_MAX_MD_CBLOCK 128 /* largest known is SHA512 */
-
 struct hmac_ctx_st {
   const EVP_MD *md;
   EVP_MD_CTX md_ctx;
@@ -155,6 +155,20 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+#if !defined(BORINGSSL_NO_CXX)
+extern "C++" {
+
+namespace bssl {
+
+using ScopedHMAC_CTX =
+    internal::StackAllocated<HMAC_CTX, void, HMAC_CTX_init, HMAC_CTX_cleanup>;
+
+}  // namespace bssl
+
+}  // extern C++
+#endif
+
 #endif
 
 #endif  /* OPENSSL_HEADER_HMAC_H */
diff --git a/src/include/openssl/lhash.h b/src/include/openssl/lhash.h
index 0d6d3ae..b95d4f2 100644
--- a/src/include/openssl/lhash.h
+++ b/src/include/openssl/lhash.h
@@ -97,6 +97,7 @@
  *
  * LHASH_OF:ASN1_OBJECT
  * LHASH_OF:CONF_VALUE
+ * LHASH_OF:CRYPTO_BUFFER
  * LHASH_OF:SSL_SESSION */
 
 #define IN_LHASH_H
@@ -143,9 +144,7 @@
   lhash_hash_func hash;
 } _LHASH;
 
-/* lh_new returns a new, empty hash table or NULL on error. If |comp| is NULL,
- * |strcmp| will be used. If |hash| is NULL, a generic hash function will be
- * used. */
+/* lh_new returns a new, empty hash table or NULL on error. */
 OPENSSL_EXPORT _LHASH *lh_new(lhash_hash_func hash, lhash_cmp_func comp);
 
 /* lh_free frees the hash table itself but none of the elements. See
diff --git a/src/include/openssl/lhash_macros.h b/src/include/openssl/lhash_macros.h
index 1d98107..ca349a9 100644
--- a/src/include/openssl/lhash_macros.h
+++ b/src/include/openssl/lhash_macros.h
@@ -17,11 +17,11 @@
 #endif
 
 /* ASN1_OBJECT */
-#define lh_ASN1_OBJECT_new(hash, comp)                                        \
-  ((LHASH_OF(ASN1_OBJECT) *)lh_new(                                           \
-      CHECKED_CAST(lhash_hash_func, uint32_t (*)(const ASN1_OBJECT *), hash), \
-      CHECKED_CAST(lhash_cmp_func,                                            \
-                   int (*)(const ASN1_OBJECT *a, const ASN1_OBJECT *b),       \
+#define lh_ASN1_OBJECT_new(hash, comp)                                       \
+  ((LHASH_OF(ASN1_OBJECT) *)lh_new(                                          \
+      CHECKED_CAST(lhash_hash_func, uint32_t(*)(const ASN1_OBJECT *), hash), \
+      CHECKED_CAST(lhash_cmp_func,                                           \
+                   int (*)(const ASN1_OBJECT *a, const ASN1_OBJECT *b),      \
                    comp)))
 
 #define lh_ASN1_OBJECT_free(lh) \
@@ -55,11 +55,12 @@
                             void (*)(ASN1_OBJECT *, void *), func), \
                arg);
 
+
 /* CONF_VALUE */
-#define lh_CONF_VALUE_new(hash, comp)                                        \
-  ((LHASH_OF(CONF_VALUE) *)lh_new(                                           \
-      CHECKED_CAST(lhash_hash_func, uint32_t (*)(const CONF_VALUE *), hash), \
-      CHECKED_CAST(lhash_cmp_func,                                           \
+#define lh_CONF_VALUE_new(hash, comp)                                       \
+  ((LHASH_OF(CONF_VALUE) *)lh_new(                                          \
+      CHECKED_CAST(lhash_hash_func, uint32_t(*)(const CONF_VALUE *), hash), \
+      CHECKED_CAST(lhash_cmp_func,                                          \
                    int (*)(const CONF_VALUE *a, const CONF_VALUE *b), comp)))
 
 #define lh_CONF_VALUE_free(lh) \
@@ -92,12 +93,53 @@
                             void (*)(CONF_VALUE *, void *), func), \
                arg);
 
+
+/* CRYPTO_BUFFER */
+#define lh_CRYPTO_BUFFER_new(hash, comp)                                       \
+  ((LHASH_OF(CRYPTO_BUFFER) *)lh_new(                                          \
+      CHECKED_CAST(lhash_hash_func, uint32_t(*)(const CRYPTO_BUFFER *), hash), \
+      CHECKED_CAST(lhash_cmp_func,                                             \
+                   int (*)(const CRYPTO_BUFFER *a, const CRYPTO_BUFFER *b),    \
+                   comp)))
+
+#define lh_CRYPTO_BUFFER_free(lh) \
+  lh_free(CHECKED_CAST(_LHASH *, LHASH_OF(CRYPTO_BUFFER) *, lh));
+
+#define lh_CRYPTO_BUFFER_num_items(lh) \
+  lh_num_items(CHECKED_CAST(_LHASH *, LHASH_OF(CRYPTO_BUFFER) *, lh))
+
+#define lh_CRYPTO_BUFFER_retrieve(lh, data)                  \
+  ((CRYPTO_BUFFER *)lh_retrieve(                             \
+      CHECKED_CAST(_LHASH *, LHASH_OF(CRYPTO_BUFFER) *, lh), \
+      CHECKED_CAST(void *, CRYPTO_BUFFER *, data)))
+
+#define lh_CRYPTO_BUFFER_insert(lh, old_data, data)                \
+  lh_insert(CHECKED_CAST(_LHASH *, LHASH_OF(CRYPTO_BUFFER) *, lh), \
+            CHECKED_CAST(void **, CRYPTO_BUFFER **, old_data),     \
+            CHECKED_CAST(void *, CRYPTO_BUFFER *, data))
+
+#define lh_CRYPTO_BUFFER_delete(lh, data)                    \
+  ((CRYPTO_BUFFER *)lh_delete(                               \
+      CHECKED_CAST(_LHASH *, LHASH_OF(CRYPTO_BUFFER) *, lh), \
+      CHECKED_CAST(void *, CRYPTO_BUFFER *, data)))
+
+#define lh_CRYPTO_BUFFER_doall(lh, func)                          \
+  lh_doall(CHECKED_CAST(_LHASH *, LHASH_OF(CRYPTO_BUFFER) *, lh), \
+           CHECKED_CAST(void (*)(void *), void (*)(CRYPTO_BUFFER *), func));
+
+#define lh_CRYPTO_BUFFER_doall_arg(lh, func, arg)                     \
+  lh_doall_arg(CHECKED_CAST(_LHASH *, LHASH_OF(CRYPTO_BUFFER) *, lh), \
+               CHECKED_CAST(void (*)(void *, void *),                 \
+                            void (*)(CRYPTO_BUFFER *, void *), func), \
+               arg);
+
+
 /* SSL_SESSION */
-#define lh_SSL_SESSION_new(hash, comp)                                        \
-  ((LHASH_OF(SSL_SESSION) *)lh_new(                                           \
-      CHECKED_CAST(lhash_hash_func, uint32_t (*)(const SSL_SESSION *), hash), \
-      CHECKED_CAST(lhash_cmp_func,                                            \
-                   int (*)(const SSL_SESSION *a, const SSL_SESSION *b),       \
+#define lh_SSL_SESSION_new(hash, comp)                                       \
+  ((LHASH_OF(SSL_SESSION) *)lh_new(                                          \
+      CHECKED_CAST(lhash_hash_func, uint32_t(*)(const SSL_SESSION *), hash), \
+      CHECKED_CAST(lhash_cmp_func,                                           \
+                   int (*)(const SSL_SESSION *a, const SSL_SESSION *b),      \
                    comp)))
 
 #define lh_SSL_SESSION_free(lh) \
diff --git a/src/include/openssl/md4.h b/src/include/openssl/md4.h
index 93c7af8..b66fcb0 100644
--- a/src/include/openssl/md4.h
+++ b/src/include/openssl/md4.h
@@ -83,6 +83,10 @@
  * returns one. */
 OPENSSL_EXPORT int MD4_Final(uint8_t *md, MD4_CTX *md4);
 
+/* MD4 writes the digest of |len| bytes from |data| to |out| and returns |out|.
+ * There must be at least |MD4_DIGEST_LENGTH| bytes of space in |out|. */
+OPENSSL_EXPORT uint8_t *MD4(const uint8_t *data, size_t len, uint8_t *out);
+
 /* MD4_Transform is a low-level function that performs a single, MD4 block
  * transformation using the state from |md4| and 64 bytes from |block|. */
 OPENSSL_EXPORT void MD4_Transform(MD4_CTX *md4, const uint8_t *block);
diff --git a/src/include/openssl/mem.h b/src/include/openssl/mem.h
index c8e2b3e..5d96a2d 100644
--- a/src/include/openssl/mem.h
+++ b/src/include/openssl/mem.h
@@ -114,27 +114,37 @@
  * representation of the given type. */
 #define DECIMAL_SIZE(type)	((sizeof(type)*8+2)/3+1)
 
-/* Printf functions.
- *
- * These functions are either OpenSSL wrappers for standard functions (i.e.
- * |BIO_snprintf| and |BIO_vsnprintf|) which don't exist in C89, or are
- * versions of printf functions that output to a BIO rather than a FILE. */
-#ifdef __GNUC__
-#define __bio_h__attr__ __attribute__
-#else
-#define __bio_h__attr__(x)
-#endif
+/* BIO_snprintf has the same behavior as snprintf(3). */
 OPENSSL_EXPORT int BIO_snprintf(char *buf, size_t n, const char *format, ...)
-    __bio_h__attr__((__format__(__printf__, 3, 4)));
+    OPENSSL_PRINTF_FORMAT_FUNC(3, 4);
 
+/* BIO_vsnprintf has the same behavior as vsnprintf(3). */
 OPENSSL_EXPORT int BIO_vsnprintf(char *buf, size_t n, const char *format,
                                  va_list args)
-    __bio_h__attr__((__format__(__printf__, 3, 0)));
-#undef __bio_h__attr__
+    OPENSSL_PRINTF_FORMAT_FUNC(3, 0);
+
+
+/* Deprecated functions. */
+
+#define CRYPTO_malloc OPENSSL_malloc
+#define CRYPTO_realloc OPENSSL_realloc
+#define CRYPTO_free OPENSSL_free
 
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+extern "C++" {
+
+namespace bssl {
+
+BORINGSSL_MAKE_DELETER(char, OPENSSL_free)
+BORINGSSL_MAKE_DELETER(uint8_t, OPENSSL_free)
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #endif  /* OPENSSL_HEADER_MEM_H */
diff --git a/src/include/openssl/nid.h b/src/include/openssl/nid.h
new file mode 100644
index 0000000..4270dc1
--- /dev/null
+++ b/src/include/openssl/nid.h
@@ -0,0 +1,4199 @@
+/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+/* This file is generated by crypto/obj/objects.go. */
+
+#ifndef OPENSSL_HEADER_NID_H
+#define OPENSSL_HEADER_NID_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* The nid library provides numbered values for ASN.1 object identifiers and
+ * other symbols. These values are used by other libraries to identify
+ * cryptographic primitives.
+ *
+ * A separate objects library, obj.h, provides functions for converting between
+ * nids and object identifiers. However it depends on large internal tables with
+ * the encodings of every nid defined. Consumers concerned with binary size
+ * should instead embed the encodings of the few consumed OIDs and compare
+ * against those.
+ *
+ * These values should not be used outside of a single process; they are not
+ * stable identifiers. */
+
+#define SN_undef "UNDEF"
+#define LN_undef "undefined"
+#define NID_undef 0
+#define OBJ_undef 0L
+
+#define SN_rsadsi "rsadsi"
+#define LN_rsadsi "RSA Data Security, Inc."
+#define NID_rsadsi 1
+#define OBJ_rsadsi 1L, 2L, 840L, 113549L
+
+#define SN_pkcs "pkcs"
+#define LN_pkcs "RSA Data Security, Inc. PKCS"
+#define NID_pkcs 2
+#define OBJ_pkcs 1L, 2L, 840L, 113549L, 1L
+
+#define SN_md2 "MD2"
+#define LN_md2 "md2"
+#define NID_md2 3
+#define OBJ_md2 1L, 2L, 840L, 113549L, 2L, 2L
+
+#define SN_md5 "MD5"
+#define LN_md5 "md5"
+#define NID_md5 4
+#define OBJ_md5 1L, 2L, 840L, 113549L, 2L, 5L
+
+#define SN_rc4 "RC4"
+#define LN_rc4 "rc4"
+#define NID_rc4 5
+#define OBJ_rc4 1L, 2L, 840L, 113549L, 3L, 4L
+
+#define LN_rsaEncryption "rsaEncryption"
+#define NID_rsaEncryption 6
+#define OBJ_rsaEncryption 1L, 2L, 840L, 113549L, 1L, 1L, 1L
+
+#define SN_md2WithRSAEncryption "RSA-MD2"
+#define LN_md2WithRSAEncryption "md2WithRSAEncryption"
+#define NID_md2WithRSAEncryption 7
+#define OBJ_md2WithRSAEncryption 1L, 2L, 840L, 113549L, 1L, 1L, 2L
+
+#define SN_md5WithRSAEncryption "RSA-MD5"
+#define LN_md5WithRSAEncryption "md5WithRSAEncryption"
+#define NID_md5WithRSAEncryption 8
+#define OBJ_md5WithRSAEncryption 1L, 2L, 840L, 113549L, 1L, 1L, 4L
+
+#define SN_pbeWithMD2AndDES_CBC "PBE-MD2-DES"
+#define LN_pbeWithMD2AndDES_CBC "pbeWithMD2AndDES-CBC"
+#define NID_pbeWithMD2AndDES_CBC 9
+#define OBJ_pbeWithMD2AndDES_CBC 1L, 2L, 840L, 113549L, 1L, 5L, 1L
+
+#define SN_pbeWithMD5AndDES_CBC "PBE-MD5-DES"
+#define LN_pbeWithMD5AndDES_CBC "pbeWithMD5AndDES-CBC"
+#define NID_pbeWithMD5AndDES_CBC 10
+#define OBJ_pbeWithMD5AndDES_CBC 1L, 2L, 840L, 113549L, 1L, 5L, 3L
+
+#define SN_X500 "X500"
+#define LN_X500 "directory services (X.500)"
+#define NID_X500 11
+#define OBJ_X500 2L, 5L
+
+#define SN_X509 "X509"
+#define NID_X509 12
+#define OBJ_X509 2L, 5L, 4L
+
+#define SN_commonName "CN"
+#define LN_commonName "commonName"
+#define NID_commonName 13
+#define OBJ_commonName 2L, 5L, 4L, 3L
+
+#define SN_countryName "C"
+#define LN_countryName "countryName"
+#define NID_countryName 14
+#define OBJ_countryName 2L, 5L, 4L, 6L
+
+#define SN_localityName "L"
+#define LN_localityName "localityName"
+#define NID_localityName 15
+#define OBJ_localityName 2L, 5L, 4L, 7L
+
+#define SN_stateOrProvinceName "ST"
+#define LN_stateOrProvinceName "stateOrProvinceName"
+#define NID_stateOrProvinceName 16
+#define OBJ_stateOrProvinceName 2L, 5L, 4L, 8L
+
+#define SN_organizationName "O"
+#define LN_organizationName "organizationName"
+#define NID_organizationName 17
+#define OBJ_organizationName 2L, 5L, 4L, 10L
+
+#define SN_organizationalUnitName "OU"
+#define LN_organizationalUnitName "organizationalUnitName"
+#define NID_organizationalUnitName 18
+#define OBJ_organizationalUnitName 2L, 5L, 4L, 11L
+
+#define SN_rsa "RSA"
+#define LN_rsa "rsa"
+#define NID_rsa 19
+#define OBJ_rsa 2L, 5L, 8L, 1L, 1L
+
+#define SN_pkcs7 "pkcs7"
+#define NID_pkcs7 20
+#define OBJ_pkcs7 1L, 2L, 840L, 113549L, 1L, 7L
+
+#define LN_pkcs7_data "pkcs7-data"
+#define NID_pkcs7_data 21
+#define OBJ_pkcs7_data 1L, 2L, 840L, 113549L, 1L, 7L, 1L
+
+#define LN_pkcs7_signed "pkcs7-signedData"
+#define NID_pkcs7_signed 22
+#define OBJ_pkcs7_signed 1L, 2L, 840L, 113549L, 1L, 7L, 2L
+
+#define LN_pkcs7_enveloped "pkcs7-envelopedData"
+#define NID_pkcs7_enveloped 23
+#define OBJ_pkcs7_enveloped 1L, 2L, 840L, 113549L, 1L, 7L, 3L
+
+#define LN_pkcs7_signedAndEnveloped "pkcs7-signedAndEnvelopedData"
+#define NID_pkcs7_signedAndEnveloped 24
+#define OBJ_pkcs7_signedAndEnveloped 1L, 2L, 840L, 113549L, 1L, 7L, 4L
+
+#define LN_pkcs7_digest "pkcs7-digestData"
+#define NID_pkcs7_digest 25
+#define OBJ_pkcs7_digest 1L, 2L, 840L, 113549L, 1L, 7L, 5L
+
+#define LN_pkcs7_encrypted "pkcs7-encryptedData"
+#define NID_pkcs7_encrypted 26
+#define OBJ_pkcs7_encrypted 1L, 2L, 840L, 113549L, 1L, 7L, 6L
+
+#define SN_pkcs3 "pkcs3"
+#define NID_pkcs3 27
+#define OBJ_pkcs3 1L, 2L, 840L, 113549L, 1L, 3L
+
+#define LN_dhKeyAgreement "dhKeyAgreement"
+#define NID_dhKeyAgreement 28
+#define OBJ_dhKeyAgreement 1L, 2L, 840L, 113549L, 1L, 3L, 1L
+
+#define SN_des_ecb "DES-ECB"
+#define LN_des_ecb "des-ecb"
+#define NID_des_ecb 29
+#define OBJ_des_ecb 1L, 3L, 14L, 3L, 2L, 6L
+
+#define SN_des_cfb64 "DES-CFB"
+#define LN_des_cfb64 "des-cfb"
+#define NID_des_cfb64 30
+#define OBJ_des_cfb64 1L, 3L, 14L, 3L, 2L, 9L
+
+#define SN_des_cbc "DES-CBC"
+#define LN_des_cbc "des-cbc"
+#define NID_des_cbc 31
+#define OBJ_des_cbc 1L, 3L, 14L, 3L, 2L, 7L
+
+#define SN_des_ede_ecb "DES-EDE"
+#define LN_des_ede_ecb "des-ede"
+#define NID_des_ede_ecb 32
+#define OBJ_des_ede_ecb 1L, 3L, 14L, 3L, 2L, 17L
+
+#define SN_des_ede3_ecb "DES-EDE3"
+#define LN_des_ede3_ecb "des-ede3"
+#define NID_des_ede3_ecb 33
+
+#define SN_idea_cbc "IDEA-CBC"
+#define LN_idea_cbc "idea-cbc"
+#define NID_idea_cbc 34
+#define OBJ_idea_cbc 1L, 3L, 6L, 1L, 4L, 1L, 188L, 7L, 1L, 1L, 2L
+
+#define SN_idea_cfb64 "IDEA-CFB"
+#define LN_idea_cfb64 "idea-cfb"
+#define NID_idea_cfb64 35
+
+#define SN_idea_ecb "IDEA-ECB"
+#define LN_idea_ecb "idea-ecb"
+#define NID_idea_ecb 36
+
+#define SN_rc2_cbc "RC2-CBC"
+#define LN_rc2_cbc "rc2-cbc"
+#define NID_rc2_cbc 37
+#define OBJ_rc2_cbc 1L, 2L, 840L, 113549L, 3L, 2L
+
+#define SN_rc2_ecb "RC2-ECB"
+#define LN_rc2_ecb "rc2-ecb"
+#define NID_rc2_ecb 38
+
+#define SN_rc2_cfb64 "RC2-CFB"
+#define LN_rc2_cfb64 "rc2-cfb"
+#define NID_rc2_cfb64 39
+
+#define SN_rc2_ofb64 "RC2-OFB"
+#define LN_rc2_ofb64 "rc2-ofb"
+#define NID_rc2_ofb64 40
+
+#define SN_sha "SHA"
+#define LN_sha "sha"
+#define NID_sha 41
+#define OBJ_sha 1L, 3L, 14L, 3L, 2L, 18L
+
+#define SN_shaWithRSAEncryption "RSA-SHA"
+#define LN_shaWithRSAEncryption "shaWithRSAEncryption"
+#define NID_shaWithRSAEncryption 42
+#define OBJ_shaWithRSAEncryption 1L, 3L, 14L, 3L, 2L, 15L
+
+#define SN_des_ede_cbc "DES-EDE-CBC"
+#define LN_des_ede_cbc "des-ede-cbc"
+#define NID_des_ede_cbc 43
+
+#define SN_des_ede3_cbc "DES-EDE3-CBC"
+#define LN_des_ede3_cbc "des-ede3-cbc"
+#define NID_des_ede3_cbc 44
+#define OBJ_des_ede3_cbc 1L, 2L, 840L, 113549L, 3L, 7L
+
+#define SN_des_ofb64 "DES-OFB"
+#define LN_des_ofb64 "des-ofb"
+#define NID_des_ofb64 45
+#define OBJ_des_ofb64 1L, 3L, 14L, 3L, 2L, 8L
+
+#define SN_idea_ofb64 "IDEA-OFB"
+#define LN_idea_ofb64 "idea-ofb"
+#define NID_idea_ofb64 46
+
+#define SN_pkcs9 "pkcs9"
+#define NID_pkcs9 47
+#define OBJ_pkcs9 1L, 2L, 840L, 113549L, 1L, 9L
+
+#define LN_pkcs9_emailAddress "emailAddress"
+#define NID_pkcs9_emailAddress 48
+#define OBJ_pkcs9_emailAddress 1L, 2L, 840L, 113549L, 1L, 9L, 1L
+
+#define LN_pkcs9_unstructuredName "unstructuredName"
+#define NID_pkcs9_unstructuredName 49
+#define OBJ_pkcs9_unstructuredName 1L, 2L, 840L, 113549L, 1L, 9L, 2L
+
+#define LN_pkcs9_contentType "contentType"
+#define NID_pkcs9_contentType 50
+#define OBJ_pkcs9_contentType 1L, 2L, 840L, 113549L, 1L, 9L, 3L
+
+#define LN_pkcs9_messageDigest "messageDigest"
+#define NID_pkcs9_messageDigest 51
+#define OBJ_pkcs9_messageDigest 1L, 2L, 840L, 113549L, 1L, 9L, 4L
+
+#define LN_pkcs9_signingTime "signingTime"
+#define NID_pkcs9_signingTime 52
+#define OBJ_pkcs9_signingTime 1L, 2L, 840L, 113549L, 1L, 9L, 5L
+
+#define LN_pkcs9_countersignature "countersignature"
+#define NID_pkcs9_countersignature 53
+#define OBJ_pkcs9_countersignature 1L, 2L, 840L, 113549L, 1L, 9L, 6L
+
+#define LN_pkcs9_challengePassword "challengePassword"
+#define NID_pkcs9_challengePassword 54
+#define OBJ_pkcs9_challengePassword 1L, 2L, 840L, 113549L, 1L, 9L, 7L
+
+#define LN_pkcs9_unstructuredAddress "unstructuredAddress"
+#define NID_pkcs9_unstructuredAddress 55
+#define OBJ_pkcs9_unstructuredAddress 1L, 2L, 840L, 113549L, 1L, 9L, 8L
+
+#define LN_pkcs9_extCertAttributes "extendedCertificateAttributes"
+#define NID_pkcs9_extCertAttributes 56
+#define OBJ_pkcs9_extCertAttributes 1L, 2L, 840L, 113549L, 1L, 9L, 9L
+
+#define SN_netscape "Netscape"
+#define LN_netscape "Netscape Communications Corp."
+#define NID_netscape 57
+#define OBJ_netscape 2L, 16L, 840L, 1L, 113730L
+
+#define SN_netscape_cert_extension "nsCertExt"
+#define LN_netscape_cert_extension "Netscape Certificate Extension"
+#define NID_netscape_cert_extension 58
+#define OBJ_netscape_cert_extension 2L, 16L, 840L, 1L, 113730L, 1L
+
+#define SN_netscape_data_type "nsDataType"
+#define LN_netscape_data_type "Netscape Data Type"
+#define NID_netscape_data_type 59
+#define OBJ_netscape_data_type 2L, 16L, 840L, 1L, 113730L, 2L
+
+#define SN_des_ede_cfb64 "DES-EDE-CFB"
+#define LN_des_ede_cfb64 "des-ede-cfb"
+#define NID_des_ede_cfb64 60
+
+#define SN_des_ede3_cfb64 "DES-EDE3-CFB"
+#define LN_des_ede3_cfb64 "des-ede3-cfb"
+#define NID_des_ede3_cfb64 61
+
+#define SN_des_ede_ofb64 "DES-EDE-OFB"
+#define LN_des_ede_ofb64 "des-ede-ofb"
+#define NID_des_ede_ofb64 62
+
+#define SN_des_ede3_ofb64 "DES-EDE3-OFB"
+#define LN_des_ede3_ofb64 "des-ede3-ofb"
+#define NID_des_ede3_ofb64 63
+
+#define SN_sha1 "SHA1"
+#define LN_sha1 "sha1"
+#define NID_sha1 64
+#define OBJ_sha1 1L, 3L, 14L, 3L, 2L, 26L
+
+#define SN_sha1WithRSAEncryption "RSA-SHA1"
+#define LN_sha1WithRSAEncryption "sha1WithRSAEncryption"
+#define NID_sha1WithRSAEncryption 65
+#define OBJ_sha1WithRSAEncryption 1L, 2L, 840L, 113549L, 1L, 1L, 5L
+
+#define SN_dsaWithSHA "DSA-SHA"
+#define LN_dsaWithSHA "dsaWithSHA"
+#define NID_dsaWithSHA 66
+#define OBJ_dsaWithSHA 1L, 3L, 14L, 3L, 2L, 13L
+
+#define SN_dsa_2 "DSA-old"
+#define LN_dsa_2 "dsaEncryption-old"
+#define NID_dsa_2 67
+#define OBJ_dsa_2 1L, 3L, 14L, 3L, 2L, 12L
+
+#define SN_pbeWithSHA1AndRC2_CBC "PBE-SHA1-RC2-64"
+#define LN_pbeWithSHA1AndRC2_CBC "pbeWithSHA1AndRC2-CBC"
+#define NID_pbeWithSHA1AndRC2_CBC 68
+#define OBJ_pbeWithSHA1AndRC2_CBC 1L, 2L, 840L, 113549L, 1L, 5L, 11L
+
+#define LN_id_pbkdf2 "PBKDF2"
+#define NID_id_pbkdf2 69
+#define OBJ_id_pbkdf2 1L, 2L, 840L, 113549L, 1L, 5L, 12L
+
+#define SN_dsaWithSHA1_2 "DSA-SHA1-old"
+#define LN_dsaWithSHA1_2 "dsaWithSHA1-old"
+#define NID_dsaWithSHA1_2 70
+#define OBJ_dsaWithSHA1_2 1L, 3L, 14L, 3L, 2L, 27L
+
+#define SN_netscape_cert_type "nsCertType"
+#define LN_netscape_cert_type "Netscape Cert Type"
+#define NID_netscape_cert_type 71
+#define OBJ_netscape_cert_type 2L, 16L, 840L, 1L, 113730L, 1L, 1L
+
+#define SN_netscape_base_url "nsBaseUrl"
+#define LN_netscape_base_url "Netscape Base Url"
+#define NID_netscape_base_url 72
+#define OBJ_netscape_base_url 2L, 16L, 840L, 1L, 113730L, 1L, 2L
+
+#define SN_netscape_revocation_url "nsRevocationUrl"
+#define LN_netscape_revocation_url "Netscape Revocation Url"
+#define NID_netscape_revocation_url 73
+#define OBJ_netscape_revocation_url 2L, 16L, 840L, 1L, 113730L, 1L, 3L
+
+#define SN_netscape_ca_revocation_url "nsCaRevocationUrl"
+#define LN_netscape_ca_revocation_url "Netscape CA Revocation Url"
+#define NID_netscape_ca_revocation_url 74
+#define OBJ_netscape_ca_revocation_url 2L, 16L, 840L, 1L, 113730L, 1L, 4L
+
+#define SN_netscape_renewal_url "nsRenewalUrl"
+#define LN_netscape_renewal_url "Netscape Renewal Url"
+#define NID_netscape_renewal_url 75
+#define OBJ_netscape_renewal_url 2L, 16L, 840L, 1L, 113730L, 1L, 7L
+
+#define SN_netscape_ca_policy_url "nsCaPolicyUrl"
+#define LN_netscape_ca_policy_url "Netscape CA Policy Url"
+#define NID_netscape_ca_policy_url 76
+#define OBJ_netscape_ca_policy_url 2L, 16L, 840L, 1L, 113730L, 1L, 8L
+
+#define SN_netscape_ssl_server_name "nsSslServerName"
+#define LN_netscape_ssl_server_name "Netscape SSL Server Name"
+#define NID_netscape_ssl_server_name 77
+#define OBJ_netscape_ssl_server_name 2L, 16L, 840L, 1L, 113730L, 1L, 12L
+
+#define SN_netscape_comment "nsComment"
+#define LN_netscape_comment "Netscape Comment"
+#define NID_netscape_comment 78
+#define OBJ_netscape_comment 2L, 16L, 840L, 1L, 113730L, 1L, 13L
+
+#define SN_netscape_cert_sequence "nsCertSequence"
+#define LN_netscape_cert_sequence "Netscape Certificate Sequence"
+#define NID_netscape_cert_sequence 79
+#define OBJ_netscape_cert_sequence 2L, 16L, 840L, 1L, 113730L, 2L, 5L
+
+#define SN_desx_cbc "DESX-CBC"
+#define LN_desx_cbc "desx-cbc"
+#define NID_desx_cbc 80
+
+#define SN_id_ce "id-ce"
+#define NID_id_ce 81
+#define OBJ_id_ce 2L, 5L, 29L
+
+#define SN_subject_key_identifier "subjectKeyIdentifier"
+#define LN_subject_key_identifier "X509v3 Subject Key Identifier"
+#define NID_subject_key_identifier 82
+#define OBJ_subject_key_identifier 2L, 5L, 29L, 14L
+
+#define SN_key_usage "keyUsage"
+#define LN_key_usage "X509v3 Key Usage"
+#define NID_key_usage 83
+#define OBJ_key_usage 2L, 5L, 29L, 15L
+
+#define SN_private_key_usage_period "privateKeyUsagePeriod"
+#define LN_private_key_usage_period "X509v3 Private Key Usage Period"
+#define NID_private_key_usage_period 84
+#define OBJ_private_key_usage_period 2L, 5L, 29L, 16L
+
+#define SN_subject_alt_name "subjectAltName"
+#define LN_subject_alt_name "X509v3 Subject Alternative Name"
+#define NID_subject_alt_name 85
+#define OBJ_subject_alt_name 2L, 5L, 29L, 17L
+
+#define SN_issuer_alt_name "issuerAltName"
+#define LN_issuer_alt_name "X509v3 Issuer Alternative Name"
+#define NID_issuer_alt_name 86
+#define OBJ_issuer_alt_name 2L, 5L, 29L, 18L
+
+#define SN_basic_constraints "basicConstraints"
+#define LN_basic_constraints "X509v3 Basic Constraints"
+#define NID_basic_constraints 87
+#define OBJ_basic_constraints 2L, 5L, 29L, 19L
+
+#define SN_crl_number "crlNumber"
+#define LN_crl_number "X509v3 CRL Number"
+#define NID_crl_number 88
+#define OBJ_crl_number 2L, 5L, 29L, 20L
+
+#define SN_certificate_policies "certificatePolicies"
+#define LN_certificate_policies "X509v3 Certificate Policies"
+#define NID_certificate_policies 89
+#define OBJ_certificate_policies 2L, 5L, 29L, 32L
+
+#define SN_authority_key_identifier "authorityKeyIdentifier"
+#define LN_authority_key_identifier "X509v3 Authority Key Identifier"
+#define NID_authority_key_identifier 90
+#define OBJ_authority_key_identifier 2L, 5L, 29L, 35L
+
+#define SN_bf_cbc "BF-CBC"
+#define LN_bf_cbc "bf-cbc"
+#define NID_bf_cbc 91
+#define OBJ_bf_cbc 1L, 3L, 6L, 1L, 4L, 1L, 3029L, 1L, 2L
+
+#define SN_bf_ecb "BF-ECB"
+#define LN_bf_ecb "bf-ecb"
+#define NID_bf_ecb 92
+
+#define SN_bf_cfb64 "BF-CFB"
+#define LN_bf_cfb64 "bf-cfb"
+#define NID_bf_cfb64 93
+
+#define SN_bf_ofb64 "BF-OFB"
+#define LN_bf_ofb64 "bf-ofb"
+#define NID_bf_ofb64 94
+
+#define SN_mdc2 "MDC2"
+#define LN_mdc2 "mdc2"
+#define NID_mdc2 95
+#define OBJ_mdc2 2L, 5L, 8L, 3L, 101L
+
+#define SN_mdc2WithRSA "RSA-MDC2"
+#define LN_mdc2WithRSA "mdc2WithRSA"
+#define NID_mdc2WithRSA 96
+#define OBJ_mdc2WithRSA 2L, 5L, 8L, 3L, 100L
+
+#define SN_rc4_40 "RC4-40"
+#define LN_rc4_40 "rc4-40"
+#define NID_rc4_40 97
+
+#define SN_rc2_40_cbc "RC2-40-CBC"
+#define LN_rc2_40_cbc "rc2-40-cbc"
+#define NID_rc2_40_cbc 98
+
+#define SN_givenName "GN"
+#define LN_givenName "givenName"
+#define NID_givenName 99
+#define OBJ_givenName 2L, 5L, 4L, 42L
+
+#define SN_surname "SN"
+#define LN_surname "surname"
+#define NID_surname 100
+#define OBJ_surname 2L, 5L, 4L, 4L
+
+#define SN_initials "initials"
+#define LN_initials "initials"
+#define NID_initials 101
+#define OBJ_initials 2L, 5L, 4L, 43L
+
+#define SN_crl_distribution_points "crlDistributionPoints"
+#define LN_crl_distribution_points "X509v3 CRL Distribution Points"
+#define NID_crl_distribution_points 103
+#define OBJ_crl_distribution_points 2L, 5L, 29L, 31L
+
+#define SN_md5WithRSA "RSA-NP-MD5"
+#define LN_md5WithRSA "md5WithRSA"
+#define NID_md5WithRSA 104
+#define OBJ_md5WithRSA 1L, 3L, 14L, 3L, 2L, 3L
+
+#define LN_serialNumber "serialNumber"
+#define NID_serialNumber 105
+#define OBJ_serialNumber 2L, 5L, 4L, 5L
+
+#define SN_title "title"
+#define LN_title "title"
+#define NID_title 106
+#define OBJ_title 2L, 5L, 4L, 12L
+
+#define LN_description "description"
+#define NID_description 107
+#define OBJ_description 2L, 5L, 4L, 13L
+
+#define SN_cast5_cbc "CAST5-CBC"
+#define LN_cast5_cbc "cast5-cbc"
+#define NID_cast5_cbc 108
+#define OBJ_cast5_cbc 1L, 2L, 840L, 113533L, 7L, 66L, 10L
+
+#define SN_cast5_ecb "CAST5-ECB"
+#define LN_cast5_ecb "cast5-ecb"
+#define NID_cast5_ecb 109
+
+#define SN_cast5_cfb64 "CAST5-CFB"
+#define LN_cast5_cfb64 "cast5-cfb"
+#define NID_cast5_cfb64 110
+
+#define SN_cast5_ofb64 "CAST5-OFB"
+#define LN_cast5_ofb64 "cast5-ofb"
+#define NID_cast5_ofb64 111
+
+#define LN_pbeWithMD5AndCast5_CBC "pbeWithMD5AndCast5CBC"
+#define NID_pbeWithMD5AndCast5_CBC 112
+#define OBJ_pbeWithMD5AndCast5_CBC 1L, 2L, 840L, 113533L, 7L, 66L, 12L
+
+#define SN_dsaWithSHA1 "DSA-SHA1"
+#define LN_dsaWithSHA1 "dsaWithSHA1"
+#define NID_dsaWithSHA1 113
+#define OBJ_dsaWithSHA1 1L, 2L, 840L, 10040L, 4L, 3L
+
+#define SN_md5_sha1 "MD5-SHA1"
+#define LN_md5_sha1 "md5-sha1"
+#define NID_md5_sha1 114
+
+#define SN_sha1WithRSA "RSA-SHA1-2"
+#define LN_sha1WithRSA "sha1WithRSA"
+#define NID_sha1WithRSA 115
+#define OBJ_sha1WithRSA 1L, 3L, 14L, 3L, 2L, 29L
+
+#define SN_dsa "DSA"
+#define LN_dsa "dsaEncryption"
+#define NID_dsa 116
+#define OBJ_dsa 1L, 2L, 840L, 10040L, 4L, 1L
+
+#define SN_ripemd160 "RIPEMD160"
+#define LN_ripemd160 "ripemd160"
+#define NID_ripemd160 117
+#define OBJ_ripemd160 1L, 3L, 36L, 3L, 2L, 1L
+
+#define SN_ripemd160WithRSA "RSA-RIPEMD160"
+#define LN_ripemd160WithRSA "ripemd160WithRSA"
+#define NID_ripemd160WithRSA 119
+#define OBJ_ripemd160WithRSA 1L, 3L, 36L, 3L, 3L, 1L, 2L
+
+#define SN_rc5_cbc "RC5-CBC"
+#define LN_rc5_cbc "rc5-cbc"
+#define NID_rc5_cbc 120
+#define OBJ_rc5_cbc 1L, 2L, 840L, 113549L, 3L, 8L
+
+#define SN_rc5_ecb "RC5-ECB"
+#define LN_rc5_ecb "rc5-ecb"
+#define NID_rc5_ecb 121
+
+#define SN_rc5_cfb64 "RC5-CFB"
+#define LN_rc5_cfb64 "rc5-cfb"
+#define NID_rc5_cfb64 122
+
+#define SN_rc5_ofb64 "RC5-OFB"
+#define LN_rc5_ofb64 "rc5-ofb"
+#define NID_rc5_ofb64 123
+
+#define SN_zlib_compression "ZLIB"
+#define LN_zlib_compression "zlib compression"
+#define NID_zlib_compression 125
+#define OBJ_zlib_compression 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 3L, 8L
+
+#define SN_ext_key_usage "extendedKeyUsage"
+#define LN_ext_key_usage "X509v3 Extended Key Usage"
+#define NID_ext_key_usage 126
+#define OBJ_ext_key_usage 2L, 5L, 29L, 37L
+
+#define SN_id_pkix "PKIX"
+#define NID_id_pkix 127
+#define OBJ_id_pkix 1L, 3L, 6L, 1L, 5L, 5L, 7L
+
+#define SN_id_kp "id-kp"
+#define NID_id_kp 128
+#define OBJ_id_kp 1L, 3L, 6L, 1L, 5L, 5L, 7L, 3L
+
+#define SN_server_auth "serverAuth"
+#define LN_server_auth "TLS Web Server Authentication"
+#define NID_server_auth 129
+#define OBJ_server_auth 1L, 3L, 6L, 1L, 5L, 5L, 7L, 3L, 1L
+
+#define SN_client_auth "clientAuth"
+#define LN_client_auth "TLS Web Client Authentication"
+#define NID_client_auth 130
+#define OBJ_client_auth 1L, 3L, 6L, 1L, 5L, 5L, 7L, 3L, 2L
+
+#define SN_code_sign "codeSigning"
+#define LN_code_sign "Code Signing"
+#define NID_code_sign 131
+#define OBJ_code_sign 1L, 3L, 6L, 1L, 5L, 5L, 7L, 3L, 3L
+
+#define SN_email_protect "emailProtection"
+#define LN_email_protect "E-mail Protection"
+#define NID_email_protect 132
+#define OBJ_email_protect 1L, 3L, 6L, 1L, 5L, 5L, 7L, 3L, 4L
+
+#define SN_time_stamp "timeStamping"
+#define LN_time_stamp "Time Stamping"
+#define NID_time_stamp 133
+#define OBJ_time_stamp 1L, 3L, 6L, 1L, 5L, 5L, 7L, 3L, 8L
+
+#define SN_ms_code_ind "msCodeInd"
+#define LN_ms_code_ind "Microsoft Individual Code Signing"
+#define NID_ms_code_ind 134
+#define OBJ_ms_code_ind 1L, 3L, 6L, 1L, 4L, 1L, 311L, 2L, 1L, 21L
+
+#define SN_ms_code_com "msCodeCom"
+#define LN_ms_code_com "Microsoft Commercial Code Signing"
+#define NID_ms_code_com 135
+#define OBJ_ms_code_com 1L, 3L, 6L, 1L, 4L, 1L, 311L, 2L, 1L, 22L
+
+#define SN_ms_ctl_sign "msCTLSign"
+#define LN_ms_ctl_sign "Microsoft Trust List Signing"
+#define NID_ms_ctl_sign 136
+#define OBJ_ms_ctl_sign 1L, 3L, 6L, 1L, 4L, 1L, 311L, 10L, 3L, 1L
+
+#define SN_ms_sgc "msSGC"
+#define LN_ms_sgc "Microsoft Server Gated Crypto"
+#define NID_ms_sgc 137
+#define OBJ_ms_sgc 1L, 3L, 6L, 1L, 4L, 1L, 311L, 10L, 3L, 3L
+
+#define SN_ms_efs "msEFS"
+#define LN_ms_efs "Microsoft Encrypted File System"
+#define NID_ms_efs 138
+#define OBJ_ms_efs 1L, 3L, 6L, 1L, 4L, 1L, 311L, 10L, 3L, 4L
+
+#define SN_ns_sgc "nsSGC"
+#define LN_ns_sgc "Netscape Server Gated Crypto"
+#define NID_ns_sgc 139
+#define OBJ_ns_sgc 2L, 16L, 840L, 1L, 113730L, 4L, 1L
+
+#define SN_delta_crl "deltaCRL"
+#define LN_delta_crl "X509v3 Delta CRL Indicator"
+#define NID_delta_crl 140
+#define OBJ_delta_crl 2L, 5L, 29L, 27L
+
+#define SN_crl_reason "CRLReason"
+#define LN_crl_reason "X509v3 CRL Reason Code"
+#define NID_crl_reason 141
+#define OBJ_crl_reason 2L, 5L, 29L, 21L
+
+#define SN_invalidity_date "invalidityDate"
+#define LN_invalidity_date "Invalidity Date"
+#define NID_invalidity_date 142
+#define OBJ_invalidity_date 2L, 5L, 29L, 24L
+
+#define SN_sxnet "SXNetID"
+#define LN_sxnet "Strong Extranet ID"
+#define NID_sxnet 143
+#define OBJ_sxnet 1L, 3L, 101L, 1L, 4L, 1L
+
+#define SN_pbe_WithSHA1And128BitRC4 "PBE-SHA1-RC4-128"
+#define LN_pbe_WithSHA1And128BitRC4 "pbeWithSHA1And128BitRC4"
+#define NID_pbe_WithSHA1And128BitRC4 144
+#define OBJ_pbe_WithSHA1And128BitRC4 1L, 2L, 840L, 113549L, 1L, 12L, 1L, 1L
+
+#define SN_pbe_WithSHA1And40BitRC4 "PBE-SHA1-RC4-40"
+#define LN_pbe_WithSHA1And40BitRC4 "pbeWithSHA1And40BitRC4"
+#define NID_pbe_WithSHA1And40BitRC4 145
+#define OBJ_pbe_WithSHA1And40BitRC4 1L, 2L, 840L, 113549L, 1L, 12L, 1L, 2L
+
+#define SN_pbe_WithSHA1And3_Key_TripleDES_CBC "PBE-SHA1-3DES"
+#define LN_pbe_WithSHA1And3_Key_TripleDES_CBC "pbeWithSHA1And3-KeyTripleDES-CBC"
+#define NID_pbe_WithSHA1And3_Key_TripleDES_CBC 146
+#define OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC \
+  1L, 2L, 840L, 113549L, 1L, 12L, 1L, 3L
+
+#define SN_pbe_WithSHA1And2_Key_TripleDES_CBC "PBE-SHA1-2DES"
+#define LN_pbe_WithSHA1And2_Key_TripleDES_CBC "pbeWithSHA1And2-KeyTripleDES-CBC"
+#define NID_pbe_WithSHA1And2_Key_TripleDES_CBC 147
+#define OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC \
+  1L, 2L, 840L, 113549L, 1L, 12L, 1L, 4L
+
+#define SN_pbe_WithSHA1And128BitRC2_CBC "PBE-SHA1-RC2-128"
+#define LN_pbe_WithSHA1And128BitRC2_CBC "pbeWithSHA1And128BitRC2-CBC"
+#define NID_pbe_WithSHA1And128BitRC2_CBC 148
+#define OBJ_pbe_WithSHA1And128BitRC2_CBC 1L, 2L, 840L, 113549L, 1L, 12L, 1L, 5L
+
+#define SN_pbe_WithSHA1And40BitRC2_CBC "PBE-SHA1-RC2-40"
+#define LN_pbe_WithSHA1And40BitRC2_CBC "pbeWithSHA1And40BitRC2-CBC"
+#define NID_pbe_WithSHA1And40BitRC2_CBC 149
+#define OBJ_pbe_WithSHA1And40BitRC2_CBC 1L, 2L, 840L, 113549L, 1L, 12L, 1L, 6L
+
+#define LN_keyBag "keyBag"
+#define NID_keyBag 150
+#define OBJ_keyBag 1L, 2L, 840L, 113549L, 1L, 12L, 10L, 1L, 1L
+
+#define LN_pkcs8ShroudedKeyBag "pkcs8ShroudedKeyBag"
+#define NID_pkcs8ShroudedKeyBag 151
+#define OBJ_pkcs8ShroudedKeyBag 1L, 2L, 840L, 113549L, 1L, 12L, 10L, 1L, 2L
+
+#define LN_certBag "certBag"
+#define NID_certBag 152
+#define OBJ_certBag 1L, 2L, 840L, 113549L, 1L, 12L, 10L, 1L, 3L
+
+#define LN_crlBag "crlBag"
+#define NID_crlBag 153
+#define OBJ_crlBag 1L, 2L, 840L, 113549L, 1L, 12L, 10L, 1L, 4L
+
+#define LN_secretBag "secretBag"
+#define NID_secretBag 154
+#define OBJ_secretBag 1L, 2L, 840L, 113549L, 1L, 12L, 10L, 1L, 5L
+
+#define LN_safeContentsBag "safeContentsBag"
+#define NID_safeContentsBag 155
+#define OBJ_safeContentsBag 1L, 2L, 840L, 113549L, 1L, 12L, 10L, 1L, 6L
+
+#define LN_friendlyName "friendlyName"
+#define NID_friendlyName 156
+#define OBJ_friendlyName 1L, 2L, 840L, 113549L, 1L, 9L, 20L
+
+#define LN_localKeyID "localKeyID"
+#define NID_localKeyID 157
+#define OBJ_localKeyID 1L, 2L, 840L, 113549L, 1L, 9L, 21L
+
+#define LN_x509Certificate "x509Certificate"
+#define NID_x509Certificate 158
+#define OBJ_x509Certificate 1L, 2L, 840L, 113549L, 1L, 9L, 22L, 1L
+
+#define LN_sdsiCertificate "sdsiCertificate"
+#define NID_sdsiCertificate 159
+#define OBJ_sdsiCertificate 1L, 2L, 840L, 113549L, 1L, 9L, 22L, 2L
+
+#define LN_x509Crl "x509Crl"
+#define NID_x509Crl 160
+#define OBJ_x509Crl 1L, 2L, 840L, 113549L, 1L, 9L, 23L, 1L
+
+#define LN_pbes2 "PBES2"
+#define NID_pbes2 161
+#define OBJ_pbes2 1L, 2L, 840L, 113549L, 1L, 5L, 13L
+
+#define LN_pbmac1 "PBMAC1"
+#define NID_pbmac1 162
+#define OBJ_pbmac1 1L, 2L, 840L, 113549L, 1L, 5L, 14L
+
+#define LN_hmacWithSHA1 "hmacWithSHA1"
+#define NID_hmacWithSHA1 163
+#define OBJ_hmacWithSHA1 1L, 2L, 840L, 113549L, 2L, 7L
+
+#define SN_id_qt_cps "id-qt-cps"
+#define LN_id_qt_cps "Policy Qualifier CPS"
+#define NID_id_qt_cps 164
+#define OBJ_id_qt_cps 1L, 3L, 6L, 1L, 5L, 5L, 7L, 2L, 1L
+
+#define SN_id_qt_unotice "id-qt-unotice"
+#define LN_id_qt_unotice "Policy Qualifier User Notice"
+#define NID_id_qt_unotice 165
+#define OBJ_id_qt_unotice 1L, 3L, 6L, 1L, 5L, 5L, 7L, 2L, 2L
+
+#define SN_rc2_64_cbc "RC2-64-CBC"
+#define LN_rc2_64_cbc "rc2-64-cbc"
+#define NID_rc2_64_cbc 166
+
+#define SN_SMIMECapabilities "SMIME-CAPS"
+#define LN_SMIMECapabilities "S/MIME Capabilities"
+#define NID_SMIMECapabilities 167
+#define OBJ_SMIMECapabilities 1L, 2L, 840L, 113549L, 1L, 9L, 15L
+
+#define SN_pbeWithMD2AndRC2_CBC "PBE-MD2-RC2-64"
+#define LN_pbeWithMD2AndRC2_CBC "pbeWithMD2AndRC2-CBC"
+#define NID_pbeWithMD2AndRC2_CBC 168
+#define OBJ_pbeWithMD2AndRC2_CBC 1L, 2L, 840L, 113549L, 1L, 5L, 4L
+
+#define SN_pbeWithMD5AndRC2_CBC "PBE-MD5-RC2-64"
+#define LN_pbeWithMD5AndRC2_CBC "pbeWithMD5AndRC2-CBC"
+#define NID_pbeWithMD5AndRC2_CBC 169
+#define OBJ_pbeWithMD5AndRC2_CBC 1L, 2L, 840L, 113549L, 1L, 5L, 6L
+
+#define SN_pbeWithSHA1AndDES_CBC "PBE-SHA1-DES"
+#define LN_pbeWithSHA1AndDES_CBC "pbeWithSHA1AndDES-CBC"
+#define NID_pbeWithSHA1AndDES_CBC 170
+#define OBJ_pbeWithSHA1AndDES_CBC 1L, 2L, 840L, 113549L, 1L, 5L, 10L
+
+#define SN_ms_ext_req "msExtReq"
+#define LN_ms_ext_req "Microsoft Extension Request"
+#define NID_ms_ext_req 171
+#define OBJ_ms_ext_req 1L, 3L, 6L, 1L, 4L, 1L, 311L, 2L, 1L, 14L
+
+#define SN_ext_req "extReq"
+#define LN_ext_req "Extension Request"
+#define NID_ext_req 172
+#define OBJ_ext_req 1L, 2L, 840L, 113549L, 1L, 9L, 14L
+
+#define SN_name "name"
+#define LN_name "name"
+#define NID_name 173
+#define OBJ_name 2L, 5L, 4L, 41L
+
+#define SN_dnQualifier "dnQualifier"
+#define LN_dnQualifier "dnQualifier"
+#define NID_dnQualifier 174
+#define OBJ_dnQualifier 2L, 5L, 4L, 46L
+
+#define SN_id_pe "id-pe"
+#define NID_id_pe 175
+#define OBJ_id_pe 1L, 3L, 6L, 1L, 5L, 5L, 7L, 1L
+
+#define SN_id_ad "id-ad"
+#define NID_id_ad 176
+#define OBJ_id_ad 1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L
+
+#define SN_info_access "authorityInfoAccess"
+#define LN_info_access "Authority Information Access"
+#define NID_info_access 177
+#define OBJ_info_access 1L, 3L, 6L, 1L, 5L, 5L, 7L, 1L, 1L
+
+#define SN_ad_OCSP "OCSP"
+#define LN_ad_OCSP "OCSP"
+#define NID_ad_OCSP 178
+#define OBJ_ad_OCSP 1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L, 1L
+
+#define SN_ad_ca_issuers "caIssuers"
+#define LN_ad_ca_issuers "CA Issuers"
+#define NID_ad_ca_issuers 179
+#define OBJ_ad_ca_issuers 1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L, 2L
+
+#define SN_OCSP_sign "OCSPSigning"
+#define LN_OCSP_sign "OCSP Signing"
+#define NID_OCSP_sign 180
+#define OBJ_OCSP_sign 1L, 3L, 6L, 1L, 5L, 5L, 7L, 3L, 9L
+
+#define SN_iso "ISO"
+#define LN_iso "iso"
+#define NID_iso 181
+#define OBJ_iso 1L
+
+#define SN_member_body "member-body"
+#define LN_member_body "ISO Member Body"
+#define NID_member_body 182
+#define OBJ_member_body 1L, 2L
+
+#define SN_ISO_US "ISO-US"
+#define LN_ISO_US "ISO US Member Body"
+#define NID_ISO_US 183
+#define OBJ_ISO_US 1L, 2L, 840L
+
+#define SN_X9_57 "X9-57"
+#define LN_X9_57 "X9.57"
+#define NID_X9_57 184
+#define OBJ_X9_57 1L, 2L, 840L, 10040L
+
+#define SN_X9cm "X9cm"
+#define LN_X9cm "X9.57 CM ?"
+#define NID_X9cm 185
+#define OBJ_X9cm 1L, 2L, 840L, 10040L, 4L
+
+#define SN_pkcs1 "pkcs1"
+#define NID_pkcs1 186
+#define OBJ_pkcs1 1L, 2L, 840L, 113549L, 1L, 1L
+
+#define SN_pkcs5 "pkcs5"
+#define NID_pkcs5 187
+#define OBJ_pkcs5 1L, 2L, 840L, 113549L, 1L, 5L
+
+#define SN_SMIME "SMIME"
+#define LN_SMIME "S/MIME"
+#define NID_SMIME 188
+#define OBJ_SMIME 1L, 2L, 840L, 113549L, 1L, 9L, 16L
+
+#define SN_id_smime_mod "id-smime-mod"
+#define NID_id_smime_mod 189
+#define OBJ_id_smime_mod 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 0L
+
+#define SN_id_smime_ct "id-smime-ct"
+#define NID_id_smime_ct 190
+#define OBJ_id_smime_ct 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 1L
+
+#define SN_id_smime_aa "id-smime-aa"
+#define NID_id_smime_aa 191
+#define OBJ_id_smime_aa 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L
+
+#define SN_id_smime_alg "id-smime-alg"
+#define NID_id_smime_alg 192
+#define OBJ_id_smime_alg 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 3L
+
+#define SN_id_smime_cd "id-smime-cd"
+#define NID_id_smime_cd 193
+#define OBJ_id_smime_cd 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 4L
+
+#define SN_id_smime_spq "id-smime-spq"
+#define NID_id_smime_spq 194
+#define OBJ_id_smime_spq 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 5L
+
+#define SN_id_smime_cti "id-smime-cti"
+#define NID_id_smime_cti 195
+#define OBJ_id_smime_cti 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 6L
+
+#define SN_id_smime_mod_cms "id-smime-mod-cms"
+#define NID_id_smime_mod_cms 196
+#define OBJ_id_smime_mod_cms 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 0L, 1L
+
+#define SN_id_smime_mod_ess "id-smime-mod-ess"
+#define NID_id_smime_mod_ess 197
+#define OBJ_id_smime_mod_ess 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 0L, 2L
+
+#define SN_id_smime_mod_oid "id-smime-mod-oid"
+#define NID_id_smime_mod_oid 198
+#define OBJ_id_smime_mod_oid 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 0L, 3L
+
+#define SN_id_smime_mod_msg_v3 "id-smime-mod-msg-v3"
+#define NID_id_smime_mod_msg_v3 199
+#define OBJ_id_smime_mod_msg_v3 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 0L, 4L
+
+#define SN_id_smime_mod_ets_eSignature_88 "id-smime-mod-ets-eSignature-88"
+#define NID_id_smime_mod_ets_eSignature_88 200
+#define OBJ_id_smime_mod_ets_eSignature_88 \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 0L, 5L
+
+#define SN_id_smime_mod_ets_eSignature_97 "id-smime-mod-ets-eSignature-97"
+#define NID_id_smime_mod_ets_eSignature_97 201
+#define OBJ_id_smime_mod_ets_eSignature_97 \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 0L, 6L
+
+#define SN_id_smime_mod_ets_eSigPolicy_88 "id-smime-mod-ets-eSigPolicy-88"
+#define NID_id_smime_mod_ets_eSigPolicy_88 202
+#define OBJ_id_smime_mod_ets_eSigPolicy_88 \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 0L, 7L
+
+#define SN_id_smime_mod_ets_eSigPolicy_97 "id-smime-mod-ets-eSigPolicy-97"
+#define NID_id_smime_mod_ets_eSigPolicy_97 203
+#define OBJ_id_smime_mod_ets_eSigPolicy_97 \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 0L, 8L
+
+#define SN_id_smime_ct_receipt "id-smime-ct-receipt"
+#define NID_id_smime_ct_receipt 204
+#define OBJ_id_smime_ct_receipt 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 1L, 1L
+
+#define SN_id_smime_ct_authData "id-smime-ct-authData"
+#define NID_id_smime_ct_authData 205
+#define OBJ_id_smime_ct_authData 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 1L, 2L
+
+#define SN_id_smime_ct_publishCert "id-smime-ct-publishCert"
+#define NID_id_smime_ct_publishCert 206
+#define OBJ_id_smime_ct_publishCert 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 1L, 3L
+
+#define SN_id_smime_ct_TSTInfo "id-smime-ct-TSTInfo"
+#define NID_id_smime_ct_TSTInfo 207
+#define OBJ_id_smime_ct_TSTInfo 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 1L, 4L
+
+#define SN_id_smime_ct_TDTInfo "id-smime-ct-TDTInfo"
+#define NID_id_smime_ct_TDTInfo 208
+#define OBJ_id_smime_ct_TDTInfo 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 1L, 5L
+
+#define SN_id_smime_ct_contentInfo "id-smime-ct-contentInfo"
+#define NID_id_smime_ct_contentInfo 209
+#define OBJ_id_smime_ct_contentInfo 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 1L, 6L
+
+#define SN_id_smime_ct_DVCSRequestData "id-smime-ct-DVCSRequestData"
+#define NID_id_smime_ct_DVCSRequestData 210
+#define OBJ_id_smime_ct_DVCSRequestData \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 1L, 7L
+
+#define SN_id_smime_ct_DVCSResponseData "id-smime-ct-DVCSResponseData"
+#define NID_id_smime_ct_DVCSResponseData 211
+#define OBJ_id_smime_ct_DVCSResponseData \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 1L, 8L
+
+#define SN_id_smime_aa_receiptRequest "id-smime-aa-receiptRequest"
+#define NID_id_smime_aa_receiptRequest 212
+#define OBJ_id_smime_aa_receiptRequest \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 1L
+
+#define SN_id_smime_aa_securityLabel "id-smime-aa-securityLabel"
+#define NID_id_smime_aa_securityLabel 213
+#define OBJ_id_smime_aa_securityLabel 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 2L
+
+#define SN_id_smime_aa_mlExpandHistory "id-smime-aa-mlExpandHistory"
+#define NID_id_smime_aa_mlExpandHistory 214
+#define OBJ_id_smime_aa_mlExpandHistory \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 3L
+
+#define SN_id_smime_aa_contentHint "id-smime-aa-contentHint"
+#define NID_id_smime_aa_contentHint 215
+#define OBJ_id_smime_aa_contentHint 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 4L
+
+#define SN_id_smime_aa_msgSigDigest "id-smime-aa-msgSigDigest"
+#define NID_id_smime_aa_msgSigDigest 216
+#define OBJ_id_smime_aa_msgSigDigest 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 5L
+
+#define SN_id_smime_aa_encapContentType "id-smime-aa-encapContentType"
+#define NID_id_smime_aa_encapContentType 217
+#define OBJ_id_smime_aa_encapContentType \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 6L
+
+#define SN_id_smime_aa_contentIdentifier "id-smime-aa-contentIdentifier"
+#define NID_id_smime_aa_contentIdentifier 218
+#define OBJ_id_smime_aa_contentIdentifier \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 7L
+
+#define SN_id_smime_aa_macValue "id-smime-aa-macValue"
+#define NID_id_smime_aa_macValue 219
+#define OBJ_id_smime_aa_macValue 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 8L
+
+#define SN_id_smime_aa_equivalentLabels "id-smime-aa-equivalentLabels"
+#define NID_id_smime_aa_equivalentLabels 220
+#define OBJ_id_smime_aa_equivalentLabels \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 9L
+
+#define SN_id_smime_aa_contentReference "id-smime-aa-contentReference"
+#define NID_id_smime_aa_contentReference 221
+#define OBJ_id_smime_aa_contentReference \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 10L
+
+#define SN_id_smime_aa_encrypKeyPref "id-smime-aa-encrypKeyPref"
+#define NID_id_smime_aa_encrypKeyPref 222
+#define OBJ_id_smime_aa_encrypKeyPref \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 11L
+
+#define SN_id_smime_aa_signingCertificate "id-smime-aa-signingCertificate"
+#define NID_id_smime_aa_signingCertificate 223
+#define OBJ_id_smime_aa_signingCertificate \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 12L
+
+#define SN_id_smime_aa_smimeEncryptCerts "id-smime-aa-smimeEncryptCerts"
+#define NID_id_smime_aa_smimeEncryptCerts 224
+#define OBJ_id_smime_aa_smimeEncryptCerts \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 13L
+
+#define SN_id_smime_aa_timeStampToken "id-smime-aa-timeStampToken"
+#define NID_id_smime_aa_timeStampToken 225
+#define OBJ_id_smime_aa_timeStampToken \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 14L
+
+#define SN_id_smime_aa_ets_sigPolicyId "id-smime-aa-ets-sigPolicyId"
+#define NID_id_smime_aa_ets_sigPolicyId 226
+#define OBJ_id_smime_aa_ets_sigPolicyId \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 15L
+
+#define SN_id_smime_aa_ets_commitmentType "id-smime-aa-ets-commitmentType"
+#define NID_id_smime_aa_ets_commitmentType 227
+#define OBJ_id_smime_aa_ets_commitmentType \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 16L
+
+#define SN_id_smime_aa_ets_signerLocation "id-smime-aa-ets-signerLocation"
+#define NID_id_smime_aa_ets_signerLocation 228
+#define OBJ_id_smime_aa_ets_signerLocation \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 17L
+
+#define SN_id_smime_aa_ets_signerAttr "id-smime-aa-ets-signerAttr"
+#define NID_id_smime_aa_ets_signerAttr 229
+#define OBJ_id_smime_aa_ets_signerAttr \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 18L
+
+#define SN_id_smime_aa_ets_otherSigCert "id-smime-aa-ets-otherSigCert"
+#define NID_id_smime_aa_ets_otherSigCert 230
+#define OBJ_id_smime_aa_ets_otherSigCert \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 19L
+
+#define SN_id_smime_aa_ets_contentTimestamp "id-smime-aa-ets-contentTimestamp"
+#define NID_id_smime_aa_ets_contentTimestamp 231
+#define OBJ_id_smime_aa_ets_contentTimestamp \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 20L
+
+#define SN_id_smime_aa_ets_CertificateRefs "id-smime-aa-ets-CertificateRefs"
+#define NID_id_smime_aa_ets_CertificateRefs 232
+#define OBJ_id_smime_aa_ets_CertificateRefs \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 21L
+
+#define SN_id_smime_aa_ets_RevocationRefs "id-smime-aa-ets-RevocationRefs"
+#define NID_id_smime_aa_ets_RevocationRefs 233
+#define OBJ_id_smime_aa_ets_RevocationRefs \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 22L
+
+#define SN_id_smime_aa_ets_certValues "id-smime-aa-ets-certValues"
+#define NID_id_smime_aa_ets_certValues 234
+#define OBJ_id_smime_aa_ets_certValues \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 23L
+
+#define SN_id_smime_aa_ets_revocationValues "id-smime-aa-ets-revocationValues"
+#define NID_id_smime_aa_ets_revocationValues 235
+#define OBJ_id_smime_aa_ets_revocationValues \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 24L
+
+#define SN_id_smime_aa_ets_escTimeStamp "id-smime-aa-ets-escTimeStamp"
+#define NID_id_smime_aa_ets_escTimeStamp 236
+#define OBJ_id_smime_aa_ets_escTimeStamp \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 25L
+
+#define SN_id_smime_aa_ets_certCRLTimestamp "id-smime-aa-ets-certCRLTimestamp"
+#define NID_id_smime_aa_ets_certCRLTimestamp 237
+#define OBJ_id_smime_aa_ets_certCRLTimestamp \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 26L
+
+#define SN_id_smime_aa_ets_archiveTimeStamp "id-smime-aa-ets-archiveTimeStamp"
+#define NID_id_smime_aa_ets_archiveTimeStamp 238
+#define OBJ_id_smime_aa_ets_archiveTimeStamp \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 27L
+
+#define SN_id_smime_aa_signatureType "id-smime-aa-signatureType"
+#define NID_id_smime_aa_signatureType 239
+#define OBJ_id_smime_aa_signatureType \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 28L
+
+#define SN_id_smime_aa_dvcs_dvc "id-smime-aa-dvcs-dvc"
+#define NID_id_smime_aa_dvcs_dvc 240
+#define OBJ_id_smime_aa_dvcs_dvc 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 2L, 29L
+
+#define SN_id_smime_alg_ESDHwith3DES "id-smime-alg-ESDHwith3DES"
+#define NID_id_smime_alg_ESDHwith3DES 241
+#define OBJ_id_smime_alg_ESDHwith3DES 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 3L, 1L
+
+#define SN_id_smime_alg_ESDHwithRC2 "id-smime-alg-ESDHwithRC2"
+#define NID_id_smime_alg_ESDHwithRC2 242
+#define OBJ_id_smime_alg_ESDHwithRC2 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 3L, 2L
+
+#define SN_id_smime_alg_3DESwrap "id-smime-alg-3DESwrap"
+#define NID_id_smime_alg_3DESwrap 243
+#define OBJ_id_smime_alg_3DESwrap 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 3L, 3L
+
+#define SN_id_smime_alg_RC2wrap "id-smime-alg-RC2wrap"
+#define NID_id_smime_alg_RC2wrap 244
+#define OBJ_id_smime_alg_RC2wrap 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 3L, 4L
+
+#define SN_id_smime_alg_ESDH "id-smime-alg-ESDH"
+#define NID_id_smime_alg_ESDH 245
+#define OBJ_id_smime_alg_ESDH 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 3L, 5L
+
+#define SN_id_smime_alg_CMS3DESwrap "id-smime-alg-CMS3DESwrap"
+#define NID_id_smime_alg_CMS3DESwrap 246
+#define OBJ_id_smime_alg_CMS3DESwrap 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 3L, 6L
+
+#define SN_id_smime_alg_CMSRC2wrap "id-smime-alg-CMSRC2wrap"
+#define NID_id_smime_alg_CMSRC2wrap 247
+#define OBJ_id_smime_alg_CMSRC2wrap 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 3L, 7L
+
+#define SN_id_smime_cd_ldap "id-smime-cd-ldap"
+#define NID_id_smime_cd_ldap 248
+#define OBJ_id_smime_cd_ldap 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 4L, 1L
+
+#define SN_id_smime_spq_ets_sqt_uri "id-smime-spq-ets-sqt-uri"
+#define NID_id_smime_spq_ets_sqt_uri 249
+#define OBJ_id_smime_spq_ets_sqt_uri 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 5L, 1L
+
+#define SN_id_smime_spq_ets_sqt_unotice "id-smime-spq-ets-sqt-unotice"
+#define NID_id_smime_spq_ets_sqt_unotice 250
+#define OBJ_id_smime_spq_ets_sqt_unotice \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 5L, 2L
+
+#define SN_id_smime_cti_ets_proofOfOrigin "id-smime-cti-ets-proofOfOrigin"
+#define NID_id_smime_cti_ets_proofOfOrigin 251
+#define OBJ_id_smime_cti_ets_proofOfOrigin \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 6L, 1L
+
+#define SN_id_smime_cti_ets_proofOfReceipt "id-smime-cti-ets-proofOfReceipt"
+#define NID_id_smime_cti_ets_proofOfReceipt 252
+#define OBJ_id_smime_cti_ets_proofOfReceipt \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 6L, 2L
+
+#define SN_id_smime_cti_ets_proofOfDelivery "id-smime-cti-ets-proofOfDelivery"
+#define NID_id_smime_cti_ets_proofOfDelivery 253
+#define OBJ_id_smime_cti_ets_proofOfDelivery \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 6L, 3L
+
+#define SN_id_smime_cti_ets_proofOfSender "id-smime-cti-ets-proofOfSender"
+#define NID_id_smime_cti_ets_proofOfSender 254
+#define OBJ_id_smime_cti_ets_proofOfSender \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 6L, 4L
+
+#define SN_id_smime_cti_ets_proofOfApproval "id-smime-cti-ets-proofOfApproval"
+#define NID_id_smime_cti_ets_proofOfApproval 255
+#define OBJ_id_smime_cti_ets_proofOfApproval \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 6L, 5L
+
+#define SN_id_smime_cti_ets_proofOfCreation "id-smime-cti-ets-proofOfCreation"
+#define NID_id_smime_cti_ets_proofOfCreation 256
+#define OBJ_id_smime_cti_ets_proofOfCreation \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 6L, 6L
+
+#define SN_md4 "MD4"
+#define LN_md4 "md4"
+#define NID_md4 257
+#define OBJ_md4 1L, 2L, 840L, 113549L, 2L, 4L
+
+#define SN_id_pkix_mod "id-pkix-mod"
+#define NID_id_pkix_mod 258
+#define OBJ_id_pkix_mod 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L
+
+#define SN_id_qt "id-qt"
+#define NID_id_qt 259
+#define OBJ_id_qt 1L, 3L, 6L, 1L, 5L, 5L, 7L, 2L
+
+#define SN_id_it "id-it"
+#define NID_id_it 260
+#define OBJ_id_it 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L
+
+#define SN_id_pkip "id-pkip"
+#define NID_id_pkip 261
+#define OBJ_id_pkip 1L, 3L, 6L, 1L, 5L, 5L, 7L, 5L
+
+#define SN_id_alg "id-alg"
+#define NID_id_alg 262
+#define OBJ_id_alg 1L, 3L, 6L, 1L, 5L, 5L, 7L, 6L
+
+#define SN_id_cmc "id-cmc"
+#define NID_id_cmc 263
+#define OBJ_id_cmc 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L
+
+#define SN_id_on "id-on"
+#define NID_id_on 264
+#define OBJ_id_on 1L, 3L, 6L, 1L, 5L, 5L, 7L, 8L
+
+#define SN_id_pda "id-pda"
+#define NID_id_pda 265
+#define OBJ_id_pda 1L, 3L, 6L, 1L, 5L, 5L, 7L, 9L
+
+#define SN_id_aca "id-aca"
+#define NID_id_aca 266
+#define OBJ_id_aca 1L, 3L, 6L, 1L, 5L, 5L, 7L, 10L
+
+#define SN_id_qcs "id-qcs"
+#define NID_id_qcs 267
+#define OBJ_id_qcs 1L, 3L, 6L, 1L, 5L, 5L, 7L, 11L
+
+#define SN_id_cct "id-cct"
+#define NID_id_cct 268
+#define OBJ_id_cct 1L, 3L, 6L, 1L, 5L, 5L, 7L, 12L
+
+#define SN_id_pkix1_explicit_88 "id-pkix1-explicit-88"
+#define NID_id_pkix1_explicit_88 269
+#define OBJ_id_pkix1_explicit_88 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L, 1L
+
+#define SN_id_pkix1_implicit_88 "id-pkix1-implicit-88"
+#define NID_id_pkix1_implicit_88 270
+#define OBJ_id_pkix1_implicit_88 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L, 2L
+
+#define SN_id_pkix1_explicit_93 "id-pkix1-explicit-93"
+#define NID_id_pkix1_explicit_93 271
+#define OBJ_id_pkix1_explicit_93 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L, 3L
+
+#define SN_id_pkix1_implicit_93 "id-pkix1-implicit-93"
+#define NID_id_pkix1_implicit_93 272
+#define OBJ_id_pkix1_implicit_93 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L, 4L
+
+#define SN_id_mod_crmf "id-mod-crmf"
+#define NID_id_mod_crmf 273
+#define OBJ_id_mod_crmf 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L, 5L
+
+#define SN_id_mod_cmc "id-mod-cmc"
+#define NID_id_mod_cmc 274
+#define OBJ_id_mod_cmc 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L, 6L
+
+#define SN_id_mod_kea_profile_88 "id-mod-kea-profile-88"
+#define NID_id_mod_kea_profile_88 275
+#define OBJ_id_mod_kea_profile_88 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L, 7L
+
+#define SN_id_mod_kea_profile_93 "id-mod-kea-profile-93"
+#define NID_id_mod_kea_profile_93 276
+#define OBJ_id_mod_kea_profile_93 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L, 8L
+
+#define SN_id_mod_cmp "id-mod-cmp"
+#define NID_id_mod_cmp 277
+#define OBJ_id_mod_cmp 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L, 9L
+
+#define SN_id_mod_qualified_cert_88 "id-mod-qualified-cert-88"
+#define NID_id_mod_qualified_cert_88 278
+#define OBJ_id_mod_qualified_cert_88 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L, 10L
+
+#define SN_id_mod_qualified_cert_93 "id-mod-qualified-cert-93"
+#define NID_id_mod_qualified_cert_93 279
+#define OBJ_id_mod_qualified_cert_93 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L, 11L
+
+#define SN_id_mod_attribute_cert "id-mod-attribute-cert"
+#define NID_id_mod_attribute_cert 280
+#define OBJ_id_mod_attribute_cert 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L, 12L
+
+#define SN_id_mod_timestamp_protocol "id-mod-timestamp-protocol"
+#define NID_id_mod_timestamp_protocol 281
+#define OBJ_id_mod_timestamp_protocol 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L, 13L
+
+#define SN_id_mod_ocsp "id-mod-ocsp"
+#define NID_id_mod_ocsp 282
+#define OBJ_id_mod_ocsp 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L, 14L
+
+#define SN_id_mod_dvcs "id-mod-dvcs"
+#define NID_id_mod_dvcs 283
+#define OBJ_id_mod_dvcs 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L, 15L
+
+#define SN_id_mod_cmp2000 "id-mod-cmp2000"
+#define NID_id_mod_cmp2000 284
+#define OBJ_id_mod_cmp2000 1L, 3L, 6L, 1L, 5L, 5L, 7L, 0L, 16L
+
+#define SN_biometricInfo "biometricInfo"
+#define LN_biometricInfo "Biometric Info"
+#define NID_biometricInfo 285
+#define OBJ_biometricInfo 1L, 3L, 6L, 1L, 5L, 5L, 7L, 1L, 2L
+
+#define SN_qcStatements "qcStatements"
+#define NID_qcStatements 286
+#define OBJ_qcStatements 1L, 3L, 6L, 1L, 5L, 5L, 7L, 1L, 3L
+
+#define SN_ac_auditEntity "ac-auditEntity"
+#define NID_ac_auditEntity 287
+#define OBJ_ac_auditEntity 1L, 3L, 6L, 1L, 5L, 5L, 7L, 1L, 4L
+
+#define SN_ac_targeting "ac-targeting"
+#define NID_ac_targeting 288
+#define OBJ_ac_targeting 1L, 3L, 6L, 1L, 5L, 5L, 7L, 1L, 5L
+
+#define SN_aaControls "aaControls"
+#define NID_aaControls 289
+#define OBJ_aaControls 1L, 3L, 6L, 1L, 5L, 5L, 7L, 1L, 6L
+
+#define SN_sbgp_ipAddrBlock "sbgp-ipAddrBlock"
+#define NID_sbgp_ipAddrBlock 290
+#define OBJ_sbgp_ipAddrBlock 1L, 3L, 6L, 1L, 5L, 5L, 7L, 1L, 7L
+
+#define SN_sbgp_autonomousSysNum "sbgp-autonomousSysNum"
+#define NID_sbgp_autonomousSysNum 291
+#define OBJ_sbgp_autonomousSysNum 1L, 3L, 6L, 1L, 5L, 5L, 7L, 1L, 8L
+
+#define SN_sbgp_routerIdentifier "sbgp-routerIdentifier"
+#define NID_sbgp_routerIdentifier 292
+#define OBJ_sbgp_routerIdentifier 1L, 3L, 6L, 1L, 5L, 5L, 7L, 1L, 9L
+
+#define SN_textNotice "textNotice"
+#define NID_textNotice 293
+#define OBJ_textNotice 1L, 3L, 6L, 1L, 5L, 5L, 7L, 2L, 3L
+
+#define SN_ipsecEndSystem "ipsecEndSystem"
+#define LN_ipsecEndSystem "IPSec End System"
+#define NID_ipsecEndSystem 294
+#define OBJ_ipsecEndSystem 1L, 3L, 6L, 1L, 5L, 5L, 7L, 3L, 5L
+
+#define SN_ipsecTunnel "ipsecTunnel"
+#define LN_ipsecTunnel "IPSec Tunnel"
+#define NID_ipsecTunnel 295
+#define OBJ_ipsecTunnel 1L, 3L, 6L, 1L, 5L, 5L, 7L, 3L, 6L
+
+#define SN_ipsecUser "ipsecUser"
+#define LN_ipsecUser "IPSec User"
+#define NID_ipsecUser 296
+#define OBJ_ipsecUser 1L, 3L, 6L, 1L, 5L, 5L, 7L, 3L, 7L
+
+#define SN_dvcs "DVCS"
+#define LN_dvcs "dvcs"
+#define NID_dvcs 297
+#define OBJ_dvcs 1L, 3L, 6L, 1L, 5L, 5L, 7L, 3L, 10L
+
+#define SN_id_it_caProtEncCert "id-it-caProtEncCert"
+#define NID_id_it_caProtEncCert 298
+#define OBJ_id_it_caProtEncCert 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L, 1L
+
+#define SN_id_it_signKeyPairTypes "id-it-signKeyPairTypes"
+#define NID_id_it_signKeyPairTypes 299
+#define OBJ_id_it_signKeyPairTypes 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L, 2L
+
+#define SN_id_it_encKeyPairTypes "id-it-encKeyPairTypes"
+#define NID_id_it_encKeyPairTypes 300
+#define OBJ_id_it_encKeyPairTypes 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L, 3L
+
+#define SN_id_it_preferredSymmAlg "id-it-preferredSymmAlg"
+#define NID_id_it_preferredSymmAlg 301
+#define OBJ_id_it_preferredSymmAlg 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L, 4L
+
+#define SN_id_it_caKeyUpdateInfo "id-it-caKeyUpdateInfo"
+#define NID_id_it_caKeyUpdateInfo 302
+#define OBJ_id_it_caKeyUpdateInfo 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L, 5L
+
+#define SN_id_it_currentCRL "id-it-currentCRL"
+#define NID_id_it_currentCRL 303
+#define OBJ_id_it_currentCRL 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L, 6L
+
+#define SN_id_it_unsupportedOIDs "id-it-unsupportedOIDs"
+#define NID_id_it_unsupportedOIDs 304
+#define OBJ_id_it_unsupportedOIDs 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L, 7L
+
+#define SN_id_it_subscriptionRequest "id-it-subscriptionRequest"
+#define NID_id_it_subscriptionRequest 305
+#define OBJ_id_it_subscriptionRequest 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L, 8L
+
+#define SN_id_it_subscriptionResponse "id-it-subscriptionResponse"
+#define NID_id_it_subscriptionResponse 306
+#define OBJ_id_it_subscriptionResponse 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L, 9L
+
+#define SN_id_it_keyPairParamReq "id-it-keyPairParamReq"
+#define NID_id_it_keyPairParamReq 307
+#define OBJ_id_it_keyPairParamReq 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L, 10L
+
+#define SN_id_it_keyPairParamRep "id-it-keyPairParamRep"
+#define NID_id_it_keyPairParamRep 308
+#define OBJ_id_it_keyPairParamRep 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L, 11L
+
+#define SN_id_it_revPassphrase "id-it-revPassphrase"
+#define NID_id_it_revPassphrase 309
+#define OBJ_id_it_revPassphrase 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L, 12L
+
+#define SN_id_it_implicitConfirm "id-it-implicitConfirm"
+#define NID_id_it_implicitConfirm 310
+#define OBJ_id_it_implicitConfirm 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L, 13L
+
+#define SN_id_it_confirmWaitTime "id-it-confirmWaitTime"
+#define NID_id_it_confirmWaitTime 311
+#define OBJ_id_it_confirmWaitTime 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L, 14L
+
+#define SN_id_it_origPKIMessage "id-it-origPKIMessage"
+#define NID_id_it_origPKIMessage 312
+#define OBJ_id_it_origPKIMessage 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L, 15L
+
+#define SN_id_regCtrl "id-regCtrl"
+#define NID_id_regCtrl 313
+#define OBJ_id_regCtrl 1L, 3L, 6L, 1L, 5L, 5L, 7L, 5L, 1L
+
+#define SN_id_regInfo "id-regInfo"
+#define NID_id_regInfo 314
+#define OBJ_id_regInfo 1L, 3L, 6L, 1L, 5L, 5L, 7L, 5L, 2L
+
+#define SN_id_regCtrl_regToken "id-regCtrl-regToken"
+#define NID_id_regCtrl_regToken 315
+#define OBJ_id_regCtrl_regToken 1L, 3L, 6L, 1L, 5L, 5L, 7L, 5L, 1L, 1L
+
+#define SN_id_regCtrl_authenticator "id-regCtrl-authenticator"
+#define NID_id_regCtrl_authenticator 316
+#define OBJ_id_regCtrl_authenticator 1L, 3L, 6L, 1L, 5L, 5L, 7L, 5L, 1L, 2L
+
+#define SN_id_regCtrl_pkiPublicationInfo "id-regCtrl-pkiPublicationInfo"
+#define NID_id_regCtrl_pkiPublicationInfo 317
+#define OBJ_id_regCtrl_pkiPublicationInfo 1L, 3L, 6L, 1L, 5L, 5L, 7L, 5L, 1L, 3L
+
+#define SN_id_regCtrl_pkiArchiveOptions "id-regCtrl-pkiArchiveOptions"
+#define NID_id_regCtrl_pkiArchiveOptions 318
+#define OBJ_id_regCtrl_pkiArchiveOptions 1L, 3L, 6L, 1L, 5L, 5L, 7L, 5L, 1L, 4L
+
+#define SN_id_regCtrl_oldCertID "id-regCtrl-oldCertID"
+#define NID_id_regCtrl_oldCertID 319
+#define OBJ_id_regCtrl_oldCertID 1L, 3L, 6L, 1L, 5L, 5L, 7L, 5L, 1L, 5L
+
+#define SN_id_regCtrl_protocolEncrKey "id-regCtrl-protocolEncrKey"
+#define NID_id_regCtrl_protocolEncrKey 320
+#define OBJ_id_regCtrl_protocolEncrKey 1L, 3L, 6L, 1L, 5L, 5L, 7L, 5L, 1L, 6L
+
+#define SN_id_regInfo_utf8Pairs "id-regInfo-utf8Pairs"
+#define NID_id_regInfo_utf8Pairs 321
+#define OBJ_id_regInfo_utf8Pairs 1L, 3L, 6L, 1L, 5L, 5L, 7L, 5L, 2L, 1L
+
+#define SN_id_regInfo_certReq "id-regInfo-certReq"
+#define NID_id_regInfo_certReq 322
+#define OBJ_id_regInfo_certReq 1L, 3L, 6L, 1L, 5L, 5L, 7L, 5L, 2L, 2L
+
+#define SN_id_alg_des40 "id-alg-des40"
+#define NID_id_alg_des40 323
+#define OBJ_id_alg_des40 1L, 3L, 6L, 1L, 5L, 5L, 7L, 6L, 1L
+
+#define SN_id_alg_noSignature "id-alg-noSignature"
+#define NID_id_alg_noSignature 324
+#define OBJ_id_alg_noSignature 1L, 3L, 6L, 1L, 5L, 5L, 7L, 6L, 2L
+
+#define SN_id_alg_dh_sig_hmac_sha1 "id-alg-dh-sig-hmac-sha1"
+#define NID_id_alg_dh_sig_hmac_sha1 325
+#define OBJ_id_alg_dh_sig_hmac_sha1 1L, 3L, 6L, 1L, 5L, 5L, 7L, 6L, 3L
+
+#define SN_id_alg_dh_pop "id-alg-dh-pop"
+#define NID_id_alg_dh_pop 326
+#define OBJ_id_alg_dh_pop 1L, 3L, 6L, 1L, 5L, 5L, 7L, 6L, 4L
+
+#define SN_id_cmc_statusInfo "id-cmc-statusInfo"
+#define NID_id_cmc_statusInfo 327
+#define OBJ_id_cmc_statusInfo 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 1L
+
+#define SN_id_cmc_identification "id-cmc-identification"
+#define NID_id_cmc_identification 328
+#define OBJ_id_cmc_identification 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 2L
+
+#define SN_id_cmc_identityProof "id-cmc-identityProof"
+#define NID_id_cmc_identityProof 329
+#define OBJ_id_cmc_identityProof 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 3L
+
+#define SN_id_cmc_dataReturn "id-cmc-dataReturn"
+#define NID_id_cmc_dataReturn 330
+#define OBJ_id_cmc_dataReturn 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 4L
+
+#define SN_id_cmc_transactionId "id-cmc-transactionId"
+#define NID_id_cmc_transactionId 331
+#define OBJ_id_cmc_transactionId 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 5L
+
+#define SN_id_cmc_senderNonce "id-cmc-senderNonce"
+#define NID_id_cmc_senderNonce 332
+#define OBJ_id_cmc_senderNonce 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 6L
+
+#define SN_id_cmc_recipientNonce "id-cmc-recipientNonce"
+#define NID_id_cmc_recipientNonce 333
+#define OBJ_id_cmc_recipientNonce 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 7L
+
+#define SN_id_cmc_addExtensions "id-cmc-addExtensions"
+#define NID_id_cmc_addExtensions 334
+#define OBJ_id_cmc_addExtensions 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 8L
+
+#define SN_id_cmc_encryptedPOP "id-cmc-encryptedPOP"
+#define NID_id_cmc_encryptedPOP 335
+#define OBJ_id_cmc_encryptedPOP 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 9L
+
+#define SN_id_cmc_decryptedPOP "id-cmc-decryptedPOP"
+#define NID_id_cmc_decryptedPOP 336
+#define OBJ_id_cmc_decryptedPOP 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 10L
+
+#define SN_id_cmc_lraPOPWitness "id-cmc-lraPOPWitness"
+#define NID_id_cmc_lraPOPWitness 337
+#define OBJ_id_cmc_lraPOPWitness 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 11L
+
+#define SN_id_cmc_getCert "id-cmc-getCert"
+#define NID_id_cmc_getCert 338
+#define OBJ_id_cmc_getCert 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 15L
+
+#define SN_id_cmc_getCRL "id-cmc-getCRL"
+#define NID_id_cmc_getCRL 339
+#define OBJ_id_cmc_getCRL 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 16L
+
+#define SN_id_cmc_revokeRequest "id-cmc-revokeRequest"
+#define NID_id_cmc_revokeRequest 340
+#define OBJ_id_cmc_revokeRequest 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 17L
+
+#define SN_id_cmc_regInfo "id-cmc-regInfo"
+#define NID_id_cmc_regInfo 341
+#define OBJ_id_cmc_regInfo 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 18L
+
+#define SN_id_cmc_responseInfo "id-cmc-responseInfo"
+#define NID_id_cmc_responseInfo 342
+#define OBJ_id_cmc_responseInfo 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 19L
+
+#define SN_id_cmc_queryPending "id-cmc-queryPending"
+#define NID_id_cmc_queryPending 343
+#define OBJ_id_cmc_queryPending 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 21L
+
+#define SN_id_cmc_popLinkRandom "id-cmc-popLinkRandom"
+#define NID_id_cmc_popLinkRandom 344
+#define OBJ_id_cmc_popLinkRandom 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 22L
+
+#define SN_id_cmc_popLinkWitness "id-cmc-popLinkWitness"
+#define NID_id_cmc_popLinkWitness 345
+#define OBJ_id_cmc_popLinkWitness 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 23L
+
+#define SN_id_cmc_confirmCertAcceptance "id-cmc-confirmCertAcceptance"
+#define NID_id_cmc_confirmCertAcceptance 346
+#define OBJ_id_cmc_confirmCertAcceptance 1L, 3L, 6L, 1L, 5L, 5L, 7L, 7L, 24L
+
+#define SN_id_on_personalData "id-on-personalData"
+#define NID_id_on_personalData 347
+#define OBJ_id_on_personalData 1L, 3L, 6L, 1L, 5L, 5L, 7L, 8L, 1L
+
+#define SN_id_pda_dateOfBirth "id-pda-dateOfBirth"
+#define NID_id_pda_dateOfBirth 348
+#define OBJ_id_pda_dateOfBirth 1L, 3L, 6L, 1L, 5L, 5L, 7L, 9L, 1L
+
+#define SN_id_pda_placeOfBirth "id-pda-placeOfBirth"
+#define NID_id_pda_placeOfBirth 349
+#define OBJ_id_pda_placeOfBirth 1L, 3L, 6L, 1L, 5L, 5L, 7L, 9L, 2L
+
+#define SN_id_pda_gender "id-pda-gender"
+#define NID_id_pda_gender 351
+#define OBJ_id_pda_gender 1L, 3L, 6L, 1L, 5L, 5L, 7L, 9L, 3L
+
+#define SN_id_pda_countryOfCitizenship "id-pda-countryOfCitizenship"
+#define NID_id_pda_countryOfCitizenship 352
+#define OBJ_id_pda_countryOfCitizenship 1L, 3L, 6L, 1L, 5L, 5L, 7L, 9L, 4L
+
+#define SN_id_pda_countryOfResidence "id-pda-countryOfResidence"
+#define NID_id_pda_countryOfResidence 353
+#define OBJ_id_pda_countryOfResidence 1L, 3L, 6L, 1L, 5L, 5L, 7L, 9L, 5L
+
+#define SN_id_aca_authenticationInfo "id-aca-authenticationInfo"
+#define NID_id_aca_authenticationInfo 354
+#define OBJ_id_aca_authenticationInfo 1L, 3L, 6L, 1L, 5L, 5L, 7L, 10L, 1L
+
+#define SN_id_aca_accessIdentity "id-aca-accessIdentity"
+#define NID_id_aca_accessIdentity 355
+#define OBJ_id_aca_accessIdentity 1L, 3L, 6L, 1L, 5L, 5L, 7L, 10L, 2L
+
+#define SN_id_aca_chargingIdentity "id-aca-chargingIdentity"
+#define NID_id_aca_chargingIdentity 356
+#define OBJ_id_aca_chargingIdentity 1L, 3L, 6L, 1L, 5L, 5L, 7L, 10L, 3L
+
+#define SN_id_aca_group "id-aca-group"
+#define NID_id_aca_group 357
+#define OBJ_id_aca_group 1L, 3L, 6L, 1L, 5L, 5L, 7L, 10L, 4L
+
+#define SN_id_aca_role "id-aca-role"
+#define NID_id_aca_role 358
+#define OBJ_id_aca_role 1L, 3L, 6L, 1L, 5L, 5L, 7L, 10L, 5L
+
+#define SN_id_qcs_pkixQCSyntax_v1 "id-qcs-pkixQCSyntax-v1"
+#define NID_id_qcs_pkixQCSyntax_v1 359
+#define OBJ_id_qcs_pkixQCSyntax_v1 1L, 3L, 6L, 1L, 5L, 5L, 7L, 11L, 1L
+
+#define SN_id_cct_crs "id-cct-crs"
+#define NID_id_cct_crs 360
+#define OBJ_id_cct_crs 1L, 3L, 6L, 1L, 5L, 5L, 7L, 12L, 1L
+
+#define SN_id_cct_PKIData "id-cct-PKIData"
+#define NID_id_cct_PKIData 361
+#define OBJ_id_cct_PKIData 1L, 3L, 6L, 1L, 5L, 5L, 7L, 12L, 2L
+
+#define SN_id_cct_PKIResponse "id-cct-PKIResponse"
+#define NID_id_cct_PKIResponse 362
+#define OBJ_id_cct_PKIResponse 1L, 3L, 6L, 1L, 5L, 5L, 7L, 12L, 3L
+
+#define SN_ad_timeStamping "ad_timestamping"
+#define LN_ad_timeStamping "AD Time Stamping"
+#define NID_ad_timeStamping 363
+#define OBJ_ad_timeStamping 1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L, 3L
+
+#define SN_ad_dvcs "AD_DVCS"
+#define LN_ad_dvcs "ad dvcs"
+#define NID_ad_dvcs 364
+#define OBJ_ad_dvcs 1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L, 4L
+
+#define SN_id_pkix_OCSP_basic "basicOCSPResponse"
+#define LN_id_pkix_OCSP_basic "Basic OCSP Response"
+#define NID_id_pkix_OCSP_basic 365
+#define OBJ_id_pkix_OCSP_basic 1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L, 1L, 1L
+
+#define SN_id_pkix_OCSP_Nonce "Nonce"
+#define LN_id_pkix_OCSP_Nonce "OCSP Nonce"
+#define NID_id_pkix_OCSP_Nonce 366
+#define OBJ_id_pkix_OCSP_Nonce 1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L, 1L, 2L
+
+#define SN_id_pkix_OCSP_CrlID "CrlID"
+#define LN_id_pkix_OCSP_CrlID "OCSP CRL ID"
+#define NID_id_pkix_OCSP_CrlID 367
+#define OBJ_id_pkix_OCSP_CrlID 1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L, 1L, 3L
+
+#define SN_id_pkix_OCSP_acceptableResponses "acceptableResponses"
+#define LN_id_pkix_OCSP_acceptableResponses "Acceptable OCSP Responses"
+#define NID_id_pkix_OCSP_acceptableResponses 368
+#define OBJ_id_pkix_OCSP_acceptableResponses \
+  1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L, 1L, 4L
+
+#define SN_id_pkix_OCSP_noCheck "noCheck"
+#define LN_id_pkix_OCSP_noCheck "OCSP No Check"
+#define NID_id_pkix_OCSP_noCheck 369
+#define OBJ_id_pkix_OCSP_noCheck 1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L, 1L, 5L
+
+#define SN_id_pkix_OCSP_archiveCutoff "archiveCutoff"
+#define LN_id_pkix_OCSP_archiveCutoff "OCSP Archive Cutoff"
+#define NID_id_pkix_OCSP_archiveCutoff 370
+#define OBJ_id_pkix_OCSP_archiveCutoff 1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L, 1L, 6L
+
+#define SN_id_pkix_OCSP_serviceLocator "serviceLocator"
+#define LN_id_pkix_OCSP_serviceLocator "OCSP Service Locator"
+#define NID_id_pkix_OCSP_serviceLocator 371
+#define OBJ_id_pkix_OCSP_serviceLocator 1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L, 1L, 7L
+
+#define SN_id_pkix_OCSP_extendedStatus "extendedStatus"
+#define LN_id_pkix_OCSP_extendedStatus "Extended OCSP Status"
+#define NID_id_pkix_OCSP_extendedStatus 372
+#define OBJ_id_pkix_OCSP_extendedStatus 1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L, 1L, 8L
+
+#define SN_id_pkix_OCSP_valid "valid"
+#define NID_id_pkix_OCSP_valid 373
+#define OBJ_id_pkix_OCSP_valid 1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L, 1L, 9L
+
+#define SN_id_pkix_OCSP_path "path"
+#define NID_id_pkix_OCSP_path 374
+#define OBJ_id_pkix_OCSP_path 1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L, 1L, 10L
+
+#define SN_id_pkix_OCSP_trustRoot "trustRoot"
+#define LN_id_pkix_OCSP_trustRoot "Trust Root"
+#define NID_id_pkix_OCSP_trustRoot 375
+#define OBJ_id_pkix_OCSP_trustRoot 1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L, 1L, 11L
+
+#define SN_algorithm "algorithm"
+#define LN_algorithm "algorithm"
+#define NID_algorithm 376
+#define OBJ_algorithm 1L, 3L, 14L, 3L, 2L
+
+#define SN_rsaSignature "rsaSignature"
+#define NID_rsaSignature 377
+#define OBJ_rsaSignature 1L, 3L, 14L, 3L, 2L, 11L
+
+#define SN_X500algorithms "X500algorithms"
+#define LN_X500algorithms "directory services - algorithms"
+#define NID_X500algorithms 378
+#define OBJ_X500algorithms 2L, 5L, 8L
+
+#define SN_org "ORG"
+#define LN_org "org"
+#define NID_org 379
+#define OBJ_org 1L, 3L
+
+#define SN_dod "DOD"
+#define LN_dod "dod"
+#define NID_dod 380
+#define OBJ_dod 1L, 3L, 6L
+
+#define SN_iana "IANA"
+#define LN_iana "iana"
+#define NID_iana 381
+#define OBJ_iana 1L, 3L, 6L, 1L
+
+#define SN_Directory "directory"
+#define LN_Directory "Directory"
+#define NID_Directory 382
+#define OBJ_Directory 1L, 3L, 6L, 1L, 1L
+
+#define SN_Management "mgmt"
+#define LN_Management "Management"
+#define NID_Management 383
+#define OBJ_Management 1L, 3L, 6L, 1L, 2L
+
+#define SN_Experimental "experimental"
+#define LN_Experimental "Experimental"
+#define NID_Experimental 384
+#define OBJ_Experimental 1L, 3L, 6L, 1L, 3L
+
+#define SN_Private "private"
+#define LN_Private "Private"
+#define NID_Private 385
+#define OBJ_Private 1L, 3L, 6L, 1L, 4L
+
+#define SN_Security "security"
+#define LN_Security "Security"
+#define NID_Security 386
+#define OBJ_Security 1L, 3L, 6L, 1L, 5L
+
+#define SN_SNMPv2 "snmpv2"
+#define LN_SNMPv2 "SNMPv2"
+#define NID_SNMPv2 387
+#define OBJ_SNMPv2 1L, 3L, 6L, 1L, 6L
+
+#define LN_Mail "Mail"
+#define NID_Mail 388
+#define OBJ_Mail 1L, 3L, 6L, 1L, 7L
+
+#define SN_Enterprises "enterprises"
+#define LN_Enterprises "Enterprises"
+#define NID_Enterprises 389
+#define OBJ_Enterprises 1L, 3L, 6L, 1L, 4L, 1L
+
+#define SN_dcObject "dcobject"
+#define LN_dcObject "dcObject"
+#define NID_dcObject 390
+#define OBJ_dcObject 1L, 3L, 6L, 1L, 4L, 1L, 1466L, 344L
+
+#define SN_domainComponent "DC"
+#define LN_domainComponent "domainComponent"
+#define NID_domainComponent 391
+#define OBJ_domainComponent 0L, 9L, 2342L, 19200300L, 100L, 1L, 25L
+
+#define SN_Domain "domain"
+#define LN_Domain "Domain"
+#define NID_Domain 392
+#define OBJ_Domain 0L, 9L, 2342L, 19200300L, 100L, 4L, 13L
+
+#define SN_selected_attribute_types "selected-attribute-types"
+#define LN_selected_attribute_types "Selected Attribute Types"
+#define NID_selected_attribute_types 394
+#define OBJ_selected_attribute_types 2L, 5L, 1L, 5L
+
+#define SN_clearance "clearance"
+#define NID_clearance 395
+#define OBJ_clearance 2L, 5L, 1L, 5L, 55L
+
+#define SN_md4WithRSAEncryption "RSA-MD4"
+#define LN_md4WithRSAEncryption "md4WithRSAEncryption"
+#define NID_md4WithRSAEncryption 396
+#define OBJ_md4WithRSAEncryption 1L, 2L, 840L, 113549L, 1L, 1L, 3L
+
+#define SN_ac_proxying "ac-proxying"
+#define NID_ac_proxying 397
+#define OBJ_ac_proxying 1L, 3L, 6L, 1L, 5L, 5L, 7L, 1L, 10L
+
+#define SN_sinfo_access "subjectInfoAccess"
+#define LN_sinfo_access "Subject Information Access"
+#define NID_sinfo_access 398
+#define OBJ_sinfo_access 1L, 3L, 6L, 1L, 5L, 5L, 7L, 1L, 11L
+
+#define SN_id_aca_encAttrs "id-aca-encAttrs"
+#define NID_id_aca_encAttrs 399
+#define OBJ_id_aca_encAttrs 1L, 3L, 6L, 1L, 5L, 5L, 7L, 10L, 6L
+
+#define SN_role "role"
+#define LN_role "role"
+#define NID_role 400
+#define OBJ_role 2L, 5L, 4L, 72L
+
+#define SN_policy_constraints "policyConstraints"
+#define LN_policy_constraints "X509v3 Policy Constraints"
+#define NID_policy_constraints 401
+#define OBJ_policy_constraints 2L, 5L, 29L, 36L
+
+#define SN_target_information "targetInformation"
+#define LN_target_information "X509v3 AC Targeting"
+#define NID_target_information 402
+#define OBJ_target_information 2L, 5L, 29L, 55L
+
+#define SN_no_rev_avail "noRevAvail"
+#define LN_no_rev_avail "X509v3 No Revocation Available"
+#define NID_no_rev_avail 403
+#define OBJ_no_rev_avail 2L, 5L, 29L, 56L
+
+#define SN_ansi_X9_62 "ansi-X9-62"
+#define LN_ansi_X9_62 "ANSI X9.62"
+#define NID_ansi_X9_62 405
+#define OBJ_ansi_X9_62 1L, 2L, 840L, 10045L
+
+#define SN_X9_62_prime_field "prime-field"
+#define NID_X9_62_prime_field 406
+#define OBJ_X9_62_prime_field 1L, 2L, 840L, 10045L, 1L, 1L
+
+#define SN_X9_62_characteristic_two_field "characteristic-two-field"
+#define NID_X9_62_characteristic_two_field 407
+#define OBJ_X9_62_characteristic_two_field 1L, 2L, 840L, 10045L, 1L, 2L
+
+#define SN_X9_62_id_ecPublicKey "id-ecPublicKey"
+#define NID_X9_62_id_ecPublicKey 408
+#define OBJ_X9_62_id_ecPublicKey 1L, 2L, 840L, 10045L, 2L, 1L
+
+#define SN_X9_62_prime192v1 "prime192v1"
+#define NID_X9_62_prime192v1 409
+#define OBJ_X9_62_prime192v1 1L, 2L, 840L, 10045L, 3L, 1L, 1L
+
+#define SN_X9_62_prime192v2 "prime192v2"
+#define NID_X9_62_prime192v2 410
+#define OBJ_X9_62_prime192v2 1L, 2L, 840L, 10045L, 3L, 1L, 2L
+
+#define SN_X9_62_prime192v3 "prime192v3"
+#define NID_X9_62_prime192v3 411
+#define OBJ_X9_62_prime192v3 1L, 2L, 840L, 10045L, 3L, 1L, 3L
+
+#define SN_X9_62_prime239v1 "prime239v1"
+#define NID_X9_62_prime239v1 412
+#define OBJ_X9_62_prime239v1 1L, 2L, 840L, 10045L, 3L, 1L, 4L
+
+#define SN_X9_62_prime239v2 "prime239v2"
+#define NID_X9_62_prime239v2 413
+#define OBJ_X9_62_prime239v2 1L, 2L, 840L, 10045L, 3L, 1L, 5L
+
+#define SN_X9_62_prime239v3 "prime239v3"
+#define NID_X9_62_prime239v3 414
+#define OBJ_X9_62_prime239v3 1L, 2L, 840L, 10045L, 3L, 1L, 6L
+
+#define SN_X9_62_prime256v1 "prime256v1"
+#define NID_X9_62_prime256v1 415
+#define OBJ_X9_62_prime256v1 1L, 2L, 840L, 10045L, 3L, 1L, 7L
+
+#define SN_ecdsa_with_SHA1 "ecdsa-with-SHA1"
+#define NID_ecdsa_with_SHA1 416
+#define OBJ_ecdsa_with_SHA1 1L, 2L, 840L, 10045L, 4L, 1L
+
+#define SN_ms_csp_name "CSPName"
+#define LN_ms_csp_name "Microsoft CSP Name"
+#define NID_ms_csp_name 417
+#define OBJ_ms_csp_name 1L, 3L, 6L, 1L, 4L, 1L, 311L, 17L, 1L
+
+#define SN_aes_128_ecb "AES-128-ECB"
+#define LN_aes_128_ecb "aes-128-ecb"
+#define NID_aes_128_ecb 418
+#define OBJ_aes_128_ecb 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 1L
+
+#define SN_aes_128_cbc "AES-128-CBC"
+#define LN_aes_128_cbc "aes-128-cbc"
+#define NID_aes_128_cbc 419
+#define OBJ_aes_128_cbc 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 2L
+
+#define SN_aes_128_ofb128 "AES-128-OFB"
+#define LN_aes_128_ofb128 "aes-128-ofb"
+#define NID_aes_128_ofb128 420
+#define OBJ_aes_128_ofb128 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 3L
+
+#define SN_aes_128_cfb128 "AES-128-CFB"
+#define LN_aes_128_cfb128 "aes-128-cfb"
+#define NID_aes_128_cfb128 421
+#define OBJ_aes_128_cfb128 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 4L
+
+#define SN_aes_192_ecb "AES-192-ECB"
+#define LN_aes_192_ecb "aes-192-ecb"
+#define NID_aes_192_ecb 422
+#define OBJ_aes_192_ecb 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 21L
+
+#define SN_aes_192_cbc "AES-192-CBC"
+#define LN_aes_192_cbc "aes-192-cbc"
+#define NID_aes_192_cbc 423
+#define OBJ_aes_192_cbc 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 22L
+
+#define SN_aes_192_ofb128 "AES-192-OFB"
+#define LN_aes_192_ofb128 "aes-192-ofb"
+#define NID_aes_192_ofb128 424
+#define OBJ_aes_192_ofb128 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 23L
+
+#define SN_aes_192_cfb128 "AES-192-CFB"
+#define LN_aes_192_cfb128 "aes-192-cfb"
+#define NID_aes_192_cfb128 425
+#define OBJ_aes_192_cfb128 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 24L
+
+#define SN_aes_256_ecb "AES-256-ECB"
+#define LN_aes_256_ecb "aes-256-ecb"
+#define NID_aes_256_ecb 426
+#define OBJ_aes_256_ecb 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 41L
+
+#define SN_aes_256_cbc "AES-256-CBC"
+#define LN_aes_256_cbc "aes-256-cbc"
+#define NID_aes_256_cbc 427
+#define OBJ_aes_256_cbc 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 42L
+
+#define SN_aes_256_ofb128 "AES-256-OFB"
+#define LN_aes_256_ofb128 "aes-256-ofb"
+#define NID_aes_256_ofb128 428
+#define OBJ_aes_256_ofb128 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 43L
+
+#define SN_aes_256_cfb128 "AES-256-CFB"
+#define LN_aes_256_cfb128 "aes-256-cfb"
+#define NID_aes_256_cfb128 429
+#define OBJ_aes_256_cfb128 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 44L
+
+#define SN_hold_instruction_code "holdInstructionCode"
+#define LN_hold_instruction_code "Hold Instruction Code"
+#define NID_hold_instruction_code 430
+#define OBJ_hold_instruction_code 2L, 5L, 29L, 23L
+
+#define SN_hold_instruction_none "holdInstructionNone"
+#define LN_hold_instruction_none "Hold Instruction None"
+#define NID_hold_instruction_none 431
+#define OBJ_hold_instruction_none 1L, 2L, 840L, 10040L, 2L, 1L
+
+#define SN_hold_instruction_call_issuer "holdInstructionCallIssuer"
+#define LN_hold_instruction_call_issuer "Hold Instruction Call Issuer"
+#define NID_hold_instruction_call_issuer 432
+#define OBJ_hold_instruction_call_issuer 1L, 2L, 840L, 10040L, 2L, 2L
+
+#define SN_hold_instruction_reject "holdInstructionReject"
+#define LN_hold_instruction_reject "Hold Instruction Reject"
+#define NID_hold_instruction_reject 433
+#define OBJ_hold_instruction_reject 1L, 2L, 840L, 10040L, 2L, 3L
+
+#define SN_data "data"
+#define NID_data 434
+#define OBJ_data 0L, 9L
+
+#define SN_pss "pss"
+#define NID_pss 435
+#define OBJ_pss 0L, 9L, 2342L
+
+#define SN_ucl "ucl"
+#define NID_ucl 436
+#define OBJ_ucl 0L, 9L, 2342L, 19200300L
+
+#define SN_pilot "pilot"
+#define NID_pilot 437
+#define OBJ_pilot 0L, 9L, 2342L, 19200300L, 100L
+
+#define LN_pilotAttributeType "pilotAttributeType"
+#define NID_pilotAttributeType 438
+#define OBJ_pilotAttributeType 0L, 9L, 2342L, 19200300L, 100L, 1L
+
+#define LN_pilotAttributeSyntax "pilotAttributeSyntax"
+#define NID_pilotAttributeSyntax 439
+#define OBJ_pilotAttributeSyntax 0L, 9L, 2342L, 19200300L, 100L, 3L
+
+#define LN_pilotObjectClass "pilotObjectClass"
+#define NID_pilotObjectClass 440
+#define OBJ_pilotObjectClass 0L, 9L, 2342L, 19200300L, 100L, 4L
+
+#define LN_pilotGroups "pilotGroups"
+#define NID_pilotGroups 441
+#define OBJ_pilotGroups 0L, 9L, 2342L, 19200300L, 100L, 10L
+
+#define LN_iA5StringSyntax "iA5StringSyntax"
+#define NID_iA5StringSyntax 442
+#define OBJ_iA5StringSyntax 0L, 9L, 2342L, 19200300L, 100L, 3L, 4L
+
+#define LN_caseIgnoreIA5StringSyntax "caseIgnoreIA5StringSyntax"
+#define NID_caseIgnoreIA5StringSyntax 443
+#define OBJ_caseIgnoreIA5StringSyntax 0L, 9L, 2342L, 19200300L, 100L, 3L, 5L
+
+#define LN_pilotObject "pilotObject"
+#define NID_pilotObject 444
+#define OBJ_pilotObject 0L, 9L, 2342L, 19200300L, 100L, 4L, 3L
+
+#define LN_pilotPerson "pilotPerson"
+#define NID_pilotPerson 445
+#define OBJ_pilotPerson 0L, 9L, 2342L, 19200300L, 100L, 4L, 4L
+
+#define SN_account "account"
+#define NID_account 446
+#define OBJ_account 0L, 9L, 2342L, 19200300L, 100L, 4L, 5L
+
+#define SN_document "document"
+#define NID_document 447
+#define OBJ_document 0L, 9L, 2342L, 19200300L, 100L, 4L, 6L
+
+#define SN_room "room"
+#define NID_room 448
+#define OBJ_room 0L, 9L, 2342L, 19200300L, 100L, 4L, 7L
+
+#define LN_documentSeries "documentSeries"
+#define NID_documentSeries 449
+#define OBJ_documentSeries 0L, 9L, 2342L, 19200300L, 100L, 4L, 9L
+
+#define LN_rFC822localPart "rFC822localPart"
+#define NID_rFC822localPart 450
+#define OBJ_rFC822localPart 0L, 9L, 2342L, 19200300L, 100L, 4L, 14L
+
+#define LN_dNSDomain "dNSDomain"
+#define NID_dNSDomain 451
+#define OBJ_dNSDomain 0L, 9L, 2342L, 19200300L, 100L, 4L, 15L
+
+#define LN_domainRelatedObject "domainRelatedObject"
+#define NID_domainRelatedObject 452
+#define OBJ_domainRelatedObject 0L, 9L, 2342L, 19200300L, 100L, 4L, 17L
+
+#define LN_friendlyCountry "friendlyCountry"
+#define NID_friendlyCountry 453
+#define OBJ_friendlyCountry 0L, 9L, 2342L, 19200300L, 100L, 4L, 18L
+
+#define LN_simpleSecurityObject "simpleSecurityObject"
+#define NID_simpleSecurityObject 454
+#define OBJ_simpleSecurityObject 0L, 9L, 2342L, 19200300L, 100L, 4L, 19L
+
+#define LN_pilotOrganization "pilotOrganization"
+#define NID_pilotOrganization 455
+#define OBJ_pilotOrganization 0L, 9L, 2342L, 19200300L, 100L, 4L, 20L
+
+#define LN_pilotDSA "pilotDSA"
+#define NID_pilotDSA 456
+#define OBJ_pilotDSA 0L, 9L, 2342L, 19200300L, 100L, 4L, 21L
+
+#define LN_qualityLabelledData "qualityLabelledData"
+#define NID_qualityLabelledData 457
+#define OBJ_qualityLabelledData 0L, 9L, 2342L, 19200300L, 100L, 4L, 22L
+
+#define SN_userId "UID"
+#define LN_userId "userId"
+#define NID_userId 458
+#define OBJ_userId 0L, 9L, 2342L, 19200300L, 100L, 1L, 1L
+
+#define LN_textEncodedORAddress "textEncodedORAddress"
+#define NID_textEncodedORAddress 459
+#define OBJ_textEncodedORAddress 0L, 9L, 2342L, 19200300L, 100L, 1L, 2L
+
+#define SN_rfc822Mailbox "mail"
+#define LN_rfc822Mailbox "rfc822Mailbox"
+#define NID_rfc822Mailbox 460
+#define OBJ_rfc822Mailbox 0L, 9L, 2342L, 19200300L, 100L, 1L, 3L
+
+#define SN_info "info"
+#define NID_info 461
+#define OBJ_info 0L, 9L, 2342L, 19200300L, 100L, 1L, 4L
+
+#define LN_favouriteDrink "favouriteDrink"
+#define NID_favouriteDrink 462
+#define OBJ_favouriteDrink 0L, 9L, 2342L, 19200300L, 100L, 1L, 5L
+
+#define LN_roomNumber "roomNumber"
+#define NID_roomNumber 463
+#define OBJ_roomNumber 0L, 9L, 2342L, 19200300L, 100L, 1L, 6L
+
+#define SN_photo "photo"
+#define NID_photo 464
+#define OBJ_photo 0L, 9L, 2342L, 19200300L, 100L, 1L, 7L
+
+#define LN_userClass "userClass"
+#define NID_userClass 465
+#define OBJ_userClass 0L, 9L, 2342L, 19200300L, 100L, 1L, 8L
+
+#define SN_host "host"
+#define NID_host 466
+#define OBJ_host 0L, 9L, 2342L, 19200300L, 100L, 1L, 9L
+
+#define SN_manager "manager"
+#define NID_manager 467
+#define OBJ_manager 0L, 9L, 2342L, 19200300L, 100L, 1L, 10L
+
+#define LN_documentIdentifier "documentIdentifier"
+#define NID_documentIdentifier 468
+#define OBJ_documentIdentifier 0L, 9L, 2342L, 19200300L, 100L, 1L, 11L
+
+#define LN_documentTitle "documentTitle"
+#define NID_documentTitle 469
+#define OBJ_documentTitle 0L, 9L, 2342L, 19200300L, 100L, 1L, 12L
+
+#define LN_documentVersion "documentVersion"
+#define NID_documentVersion 470
+#define OBJ_documentVersion 0L, 9L, 2342L, 19200300L, 100L, 1L, 13L
+
+#define LN_documentAuthor "documentAuthor"
+#define NID_documentAuthor 471
+#define OBJ_documentAuthor 0L, 9L, 2342L, 19200300L, 100L, 1L, 14L
+
+#define LN_documentLocation "documentLocation"
+#define NID_documentLocation 472
+#define OBJ_documentLocation 0L, 9L, 2342L, 19200300L, 100L, 1L, 15L
+
+#define LN_homeTelephoneNumber "homeTelephoneNumber"
+#define NID_homeTelephoneNumber 473
+#define OBJ_homeTelephoneNumber 0L, 9L, 2342L, 19200300L, 100L, 1L, 20L
+
+#define SN_secretary "secretary"
+#define NID_secretary 474
+#define OBJ_secretary 0L, 9L, 2342L, 19200300L, 100L, 1L, 21L
+
+#define LN_otherMailbox "otherMailbox"
+#define NID_otherMailbox 475
+#define OBJ_otherMailbox 0L, 9L, 2342L, 19200300L, 100L, 1L, 22L
+
+#define LN_lastModifiedTime "lastModifiedTime"
+#define NID_lastModifiedTime 476
+#define OBJ_lastModifiedTime 0L, 9L, 2342L, 19200300L, 100L, 1L, 23L
+
+#define LN_lastModifiedBy "lastModifiedBy"
+#define NID_lastModifiedBy 477
+#define OBJ_lastModifiedBy 0L, 9L, 2342L, 19200300L, 100L, 1L, 24L
+
+#define LN_aRecord "aRecord"
+#define NID_aRecord 478
+#define OBJ_aRecord 0L, 9L, 2342L, 19200300L, 100L, 1L, 26L
+
+#define LN_pilotAttributeType27 "pilotAttributeType27"
+#define NID_pilotAttributeType27 479
+#define OBJ_pilotAttributeType27 0L, 9L, 2342L, 19200300L, 100L, 1L, 27L
+
+#define LN_mXRecord "mXRecord"
+#define NID_mXRecord 480
+#define OBJ_mXRecord 0L, 9L, 2342L, 19200300L, 100L, 1L, 28L
+
+#define LN_nSRecord "nSRecord"
+#define NID_nSRecord 481
+#define OBJ_nSRecord 0L, 9L, 2342L, 19200300L, 100L, 1L, 29L
+
+#define LN_sOARecord "sOARecord"
+#define NID_sOARecord 482
+#define OBJ_sOARecord 0L, 9L, 2342L, 19200300L, 100L, 1L, 30L
+
+#define LN_cNAMERecord "cNAMERecord"
+#define NID_cNAMERecord 483
+#define OBJ_cNAMERecord 0L, 9L, 2342L, 19200300L, 100L, 1L, 31L
+
+#define LN_associatedDomain "associatedDomain"
+#define NID_associatedDomain 484
+#define OBJ_associatedDomain 0L, 9L, 2342L, 19200300L, 100L, 1L, 37L
+
+#define LN_associatedName "associatedName"
+#define NID_associatedName 485
+#define OBJ_associatedName 0L, 9L, 2342L, 19200300L, 100L, 1L, 38L
+
+#define LN_homePostalAddress "homePostalAddress"
+#define NID_homePostalAddress 486
+#define OBJ_homePostalAddress 0L, 9L, 2342L, 19200300L, 100L, 1L, 39L
+
+#define LN_personalTitle "personalTitle"
+#define NID_personalTitle 487
+#define OBJ_personalTitle 0L, 9L, 2342L, 19200300L, 100L, 1L, 40L
+
+#define LN_mobileTelephoneNumber "mobileTelephoneNumber"
+#define NID_mobileTelephoneNumber 488
+#define OBJ_mobileTelephoneNumber 0L, 9L, 2342L, 19200300L, 100L, 1L, 41L
+
+#define LN_pagerTelephoneNumber "pagerTelephoneNumber"
+#define NID_pagerTelephoneNumber 489
+#define OBJ_pagerTelephoneNumber 0L, 9L, 2342L, 19200300L, 100L, 1L, 42L
+
+#define LN_friendlyCountryName "friendlyCountryName"
+#define NID_friendlyCountryName 490
+#define OBJ_friendlyCountryName 0L, 9L, 2342L, 19200300L, 100L, 1L, 43L
+
+#define LN_organizationalStatus "organizationalStatus"
+#define NID_organizationalStatus 491
+#define OBJ_organizationalStatus 0L, 9L, 2342L, 19200300L, 100L, 1L, 45L
+
+#define LN_janetMailbox "janetMailbox"
+#define NID_janetMailbox 492
+#define OBJ_janetMailbox 0L, 9L, 2342L, 19200300L, 100L, 1L, 46L
+
+#define LN_mailPreferenceOption "mailPreferenceOption"
+#define NID_mailPreferenceOption 493
+#define OBJ_mailPreferenceOption 0L, 9L, 2342L, 19200300L, 100L, 1L, 47L
+
+#define LN_buildingName "buildingName"
+#define NID_buildingName 494
+#define OBJ_buildingName 0L, 9L, 2342L, 19200300L, 100L, 1L, 48L
+
+#define LN_dSAQuality "dSAQuality"
+#define NID_dSAQuality 495
+#define OBJ_dSAQuality 0L, 9L, 2342L, 19200300L, 100L, 1L, 49L
+
+#define LN_singleLevelQuality "singleLevelQuality"
+#define NID_singleLevelQuality 496
+#define OBJ_singleLevelQuality 0L, 9L, 2342L, 19200300L, 100L, 1L, 50L
+
+#define LN_subtreeMinimumQuality "subtreeMinimumQuality"
+#define NID_subtreeMinimumQuality 497
+#define OBJ_subtreeMinimumQuality 0L, 9L, 2342L, 19200300L, 100L, 1L, 51L
+
+#define LN_subtreeMaximumQuality "subtreeMaximumQuality"
+#define NID_subtreeMaximumQuality 498
+#define OBJ_subtreeMaximumQuality 0L, 9L, 2342L, 19200300L, 100L, 1L, 52L
+
+#define LN_personalSignature "personalSignature"
+#define NID_personalSignature 499
+#define OBJ_personalSignature 0L, 9L, 2342L, 19200300L, 100L, 1L, 53L
+
+#define LN_dITRedirect "dITRedirect"
+#define NID_dITRedirect 500
+#define OBJ_dITRedirect 0L, 9L, 2342L, 19200300L, 100L, 1L, 54L
+
+#define SN_audio "audio"
+#define NID_audio 501
+#define OBJ_audio 0L, 9L, 2342L, 19200300L, 100L, 1L, 55L
+
+#define LN_documentPublisher "documentPublisher"
+#define NID_documentPublisher 502
+#define OBJ_documentPublisher 0L, 9L, 2342L, 19200300L, 100L, 1L, 56L
+
+#define LN_x500UniqueIdentifier "x500UniqueIdentifier"
+#define NID_x500UniqueIdentifier 503
+#define OBJ_x500UniqueIdentifier 2L, 5L, 4L, 45L
+
+#define SN_mime_mhs "mime-mhs"
+#define LN_mime_mhs "MIME MHS"
+#define NID_mime_mhs 504
+#define OBJ_mime_mhs 1L, 3L, 6L, 1L, 7L, 1L
+
+#define SN_mime_mhs_headings "mime-mhs-headings"
+#define LN_mime_mhs_headings "mime-mhs-headings"
+#define NID_mime_mhs_headings 505
+#define OBJ_mime_mhs_headings 1L, 3L, 6L, 1L, 7L, 1L, 1L
+
+#define SN_mime_mhs_bodies "mime-mhs-bodies"
+#define LN_mime_mhs_bodies "mime-mhs-bodies"
+#define NID_mime_mhs_bodies 506
+#define OBJ_mime_mhs_bodies 1L, 3L, 6L, 1L, 7L, 1L, 2L
+
+#define SN_id_hex_partial_message "id-hex-partial-message"
+#define LN_id_hex_partial_message "id-hex-partial-message"
+#define NID_id_hex_partial_message 507
+#define OBJ_id_hex_partial_message 1L, 3L, 6L, 1L, 7L, 1L, 1L, 1L
+
+#define SN_id_hex_multipart_message "id-hex-multipart-message"
+#define LN_id_hex_multipart_message "id-hex-multipart-message"
+#define NID_id_hex_multipart_message 508
+#define OBJ_id_hex_multipart_message 1L, 3L, 6L, 1L, 7L, 1L, 1L, 2L
+
+#define LN_generationQualifier "generationQualifier"
+#define NID_generationQualifier 509
+#define OBJ_generationQualifier 2L, 5L, 4L, 44L
+
+#define LN_pseudonym "pseudonym"
+#define NID_pseudonym 510
+#define OBJ_pseudonym 2L, 5L, 4L, 65L
+
+#define SN_id_set "id-set"
+#define LN_id_set "Secure Electronic Transactions"
+#define NID_id_set 512
+#define OBJ_id_set 2L, 23L, 42L
+
+#define SN_set_ctype "set-ctype"
+#define LN_set_ctype "content types"
+#define NID_set_ctype 513
+#define OBJ_set_ctype 2L, 23L, 42L, 0L
+
+#define SN_set_msgExt "set-msgExt"
+#define LN_set_msgExt "message extensions"
+#define NID_set_msgExt 514
+#define OBJ_set_msgExt 2L, 23L, 42L, 1L
+
+#define SN_set_attr "set-attr"
+#define NID_set_attr 515
+#define OBJ_set_attr 2L, 23L, 42L, 3L
+
+#define SN_set_policy "set-policy"
+#define NID_set_policy 516
+#define OBJ_set_policy 2L, 23L, 42L, 5L
+
+#define SN_set_certExt "set-certExt"
+#define LN_set_certExt "certificate extensions"
+#define NID_set_certExt 517
+#define OBJ_set_certExt 2L, 23L, 42L, 7L
+
+#define SN_set_brand "set-brand"
+#define NID_set_brand 518
+#define OBJ_set_brand 2L, 23L, 42L, 8L
+
+#define SN_setct_PANData "setct-PANData"
+#define NID_setct_PANData 519
+#define OBJ_setct_PANData 2L, 23L, 42L, 0L, 0L
+
+#define SN_setct_PANToken "setct-PANToken"
+#define NID_setct_PANToken 520
+#define OBJ_setct_PANToken 2L, 23L, 42L, 0L, 1L
+
+#define SN_setct_PANOnly "setct-PANOnly"
+#define NID_setct_PANOnly 521
+#define OBJ_setct_PANOnly 2L, 23L, 42L, 0L, 2L
+
+#define SN_setct_OIData "setct-OIData"
+#define NID_setct_OIData 522
+#define OBJ_setct_OIData 2L, 23L, 42L, 0L, 3L
+
+#define SN_setct_PI "setct-PI"
+#define NID_setct_PI 523
+#define OBJ_setct_PI 2L, 23L, 42L, 0L, 4L
+
+#define SN_setct_PIData "setct-PIData"
+#define NID_setct_PIData 524
+#define OBJ_setct_PIData 2L, 23L, 42L, 0L, 5L
+
+#define SN_setct_PIDataUnsigned "setct-PIDataUnsigned"
+#define NID_setct_PIDataUnsigned 525
+#define OBJ_setct_PIDataUnsigned 2L, 23L, 42L, 0L, 6L
+
+#define SN_setct_HODInput "setct-HODInput"
+#define NID_setct_HODInput 526
+#define OBJ_setct_HODInput 2L, 23L, 42L, 0L, 7L
+
+#define SN_setct_AuthResBaggage "setct-AuthResBaggage"
+#define NID_setct_AuthResBaggage 527
+#define OBJ_setct_AuthResBaggage 2L, 23L, 42L, 0L, 8L
+
+#define SN_setct_AuthRevReqBaggage "setct-AuthRevReqBaggage"
+#define NID_setct_AuthRevReqBaggage 528
+#define OBJ_setct_AuthRevReqBaggage 2L, 23L, 42L, 0L, 9L
+
+#define SN_setct_AuthRevResBaggage "setct-AuthRevResBaggage"
+#define NID_setct_AuthRevResBaggage 529
+#define OBJ_setct_AuthRevResBaggage 2L, 23L, 42L, 0L, 10L
+
+#define SN_setct_CapTokenSeq "setct-CapTokenSeq"
+#define NID_setct_CapTokenSeq 530
+#define OBJ_setct_CapTokenSeq 2L, 23L, 42L, 0L, 11L
+
+#define SN_setct_PInitResData "setct-PInitResData"
+#define NID_setct_PInitResData 531
+#define OBJ_setct_PInitResData 2L, 23L, 42L, 0L, 12L
+
+#define SN_setct_PI_TBS "setct-PI-TBS"
+#define NID_setct_PI_TBS 532
+#define OBJ_setct_PI_TBS 2L, 23L, 42L, 0L, 13L
+
+#define SN_setct_PResData "setct-PResData"
+#define NID_setct_PResData 533
+#define OBJ_setct_PResData 2L, 23L, 42L, 0L, 14L
+
+#define SN_setct_AuthReqTBS "setct-AuthReqTBS"
+#define NID_setct_AuthReqTBS 534
+#define OBJ_setct_AuthReqTBS 2L, 23L, 42L, 0L, 16L
+
+#define SN_setct_AuthResTBS "setct-AuthResTBS"
+#define NID_setct_AuthResTBS 535
+#define OBJ_setct_AuthResTBS 2L, 23L, 42L, 0L, 17L
+
+#define SN_setct_AuthResTBSX "setct-AuthResTBSX"
+#define NID_setct_AuthResTBSX 536
+#define OBJ_setct_AuthResTBSX 2L, 23L, 42L, 0L, 18L
+
+#define SN_setct_AuthTokenTBS "setct-AuthTokenTBS"
+#define NID_setct_AuthTokenTBS 537
+#define OBJ_setct_AuthTokenTBS 2L, 23L, 42L, 0L, 19L
+
+#define SN_setct_CapTokenData "setct-CapTokenData"
+#define NID_setct_CapTokenData 538
+#define OBJ_setct_CapTokenData 2L, 23L, 42L, 0L, 20L
+
+#define SN_setct_CapTokenTBS "setct-CapTokenTBS"
+#define NID_setct_CapTokenTBS 539
+#define OBJ_setct_CapTokenTBS 2L, 23L, 42L, 0L, 21L
+
+#define SN_setct_AcqCardCodeMsg "setct-AcqCardCodeMsg"
+#define NID_setct_AcqCardCodeMsg 540
+#define OBJ_setct_AcqCardCodeMsg 2L, 23L, 42L, 0L, 22L
+
+#define SN_setct_AuthRevReqTBS "setct-AuthRevReqTBS"
+#define NID_setct_AuthRevReqTBS 541
+#define OBJ_setct_AuthRevReqTBS 2L, 23L, 42L, 0L, 23L
+
+#define SN_setct_AuthRevResData "setct-AuthRevResData"
+#define NID_setct_AuthRevResData 542
+#define OBJ_setct_AuthRevResData 2L, 23L, 42L, 0L, 24L
+
+#define SN_setct_AuthRevResTBS "setct-AuthRevResTBS"
+#define NID_setct_AuthRevResTBS 543
+#define OBJ_setct_AuthRevResTBS 2L, 23L, 42L, 0L, 25L
+
+#define SN_setct_CapReqTBS "setct-CapReqTBS"
+#define NID_setct_CapReqTBS 544
+#define OBJ_setct_CapReqTBS 2L, 23L, 42L, 0L, 26L
+
+#define SN_setct_CapReqTBSX "setct-CapReqTBSX"
+#define NID_setct_CapReqTBSX 545
+#define OBJ_setct_CapReqTBSX 2L, 23L, 42L, 0L, 27L
+
+#define SN_setct_CapResData "setct-CapResData"
+#define NID_setct_CapResData 546
+#define OBJ_setct_CapResData 2L, 23L, 42L, 0L, 28L
+
+#define SN_setct_CapRevReqTBS "setct-CapRevReqTBS"
+#define NID_setct_CapRevReqTBS 547
+#define OBJ_setct_CapRevReqTBS 2L, 23L, 42L, 0L, 29L
+
+#define SN_setct_CapRevReqTBSX "setct-CapRevReqTBSX"
+#define NID_setct_CapRevReqTBSX 548
+#define OBJ_setct_CapRevReqTBSX 2L, 23L, 42L, 0L, 30L
+
+#define SN_setct_CapRevResData "setct-CapRevResData"
+#define NID_setct_CapRevResData 549
+#define OBJ_setct_CapRevResData 2L, 23L, 42L, 0L, 31L
+
+#define SN_setct_CredReqTBS "setct-CredReqTBS"
+#define NID_setct_CredReqTBS 550
+#define OBJ_setct_CredReqTBS 2L, 23L, 42L, 0L, 32L
+
+#define SN_setct_CredReqTBSX "setct-CredReqTBSX"
+#define NID_setct_CredReqTBSX 551
+#define OBJ_setct_CredReqTBSX 2L, 23L, 42L, 0L, 33L
+
+#define SN_setct_CredResData "setct-CredResData"
+#define NID_setct_CredResData 552
+#define OBJ_setct_CredResData 2L, 23L, 42L, 0L, 34L
+
+#define SN_setct_CredRevReqTBS "setct-CredRevReqTBS"
+#define NID_setct_CredRevReqTBS 553
+#define OBJ_setct_CredRevReqTBS 2L, 23L, 42L, 0L, 35L
+
+#define SN_setct_CredRevReqTBSX "setct-CredRevReqTBSX"
+#define NID_setct_CredRevReqTBSX 554
+#define OBJ_setct_CredRevReqTBSX 2L, 23L, 42L, 0L, 36L
+
+#define SN_setct_CredRevResData "setct-CredRevResData"
+#define NID_setct_CredRevResData 555
+#define OBJ_setct_CredRevResData 2L, 23L, 42L, 0L, 37L
+
+#define SN_setct_PCertReqData "setct-PCertReqData"
+#define NID_setct_PCertReqData 556
+#define OBJ_setct_PCertReqData 2L, 23L, 42L, 0L, 38L
+
+#define SN_setct_PCertResTBS "setct-PCertResTBS"
+#define NID_setct_PCertResTBS 557
+#define OBJ_setct_PCertResTBS 2L, 23L, 42L, 0L, 39L
+
+#define SN_setct_BatchAdminReqData "setct-BatchAdminReqData"
+#define NID_setct_BatchAdminReqData 558
+#define OBJ_setct_BatchAdminReqData 2L, 23L, 42L, 0L, 40L
+
+#define SN_setct_BatchAdminResData "setct-BatchAdminResData"
+#define NID_setct_BatchAdminResData 559
+#define OBJ_setct_BatchAdminResData 2L, 23L, 42L, 0L, 41L
+
+#define SN_setct_CardCInitResTBS "setct-CardCInitResTBS"
+#define NID_setct_CardCInitResTBS 560
+#define OBJ_setct_CardCInitResTBS 2L, 23L, 42L, 0L, 42L
+
+#define SN_setct_MeAqCInitResTBS "setct-MeAqCInitResTBS"
+#define NID_setct_MeAqCInitResTBS 561
+#define OBJ_setct_MeAqCInitResTBS 2L, 23L, 42L, 0L, 43L
+
+#define SN_setct_RegFormResTBS "setct-RegFormResTBS"
+#define NID_setct_RegFormResTBS 562
+#define OBJ_setct_RegFormResTBS 2L, 23L, 42L, 0L, 44L
+
+#define SN_setct_CertReqData "setct-CertReqData"
+#define NID_setct_CertReqData 563
+#define OBJ_setct_CertReqData 2L, 23L, 42L, 0L, 45L
+
+#define SN_setct_CertReqTBS "setct-CertReqTBS"
+#define NID_setct_CertReqTBS 564
+#define OBJ_setct_CertReqTBS 2L, 23L, 42L, 0L, 46L
+
+#define SN_setct_CertResData "setct-CertResData"
+#define NID_setct_CertResData 565
+#define OBJ_setct_CertResData 2L, 23L, 42L, 0L, 47L
+
+#define SN_setct_CertInqReqTBS "setct-CertInqReqTBS"
+#define NID_setct_CertInqReqTBS 566
+#define OBJ_setct_CertInqReqTBS 2L, 23L, 42L, 0L, 48L
+
+#define SN_setct_ErrorTBS "setct-ErrorTBS"
+#define NID_setct_ErrorTBS 567
+#define OBJ_setct_ErrorTBS 2L, 23L, 42L, 0L, 49L
+
+#define SN_setct_PIDualSignedTBE "setct-PIDualSignedTBE"
+#define NID_setct_PIDualSignedTBE 568
+#define OBJ_setct_PIDualSignedTBE 2L, 23L, 42L, 0L, 50L
+
+#define SN_setct_PIUnsignedTBE "setct-PIUnsignedTBE"
+#define NID_setct_PIUnsignedTBE 569
+#define OBJ_setct_PIUnsignedTBE 2L, 23L, 42L, 0L, 51L
+
+#define SN_setct_AuthReqTBE "setct-AuthReqTBE"
+#define NID_setct_AuthReqTBE 570
+#define OBJ_setct_AuthReqTBE 2L, 23L, 42L, 0L, 52L
+
+#define SN_setct_AuthResTBE "setct-AuthResTBE"
+#define NID_setct_AuthResTBE 571
+#define OBJ_setct_AuthResTBE 2L, 23L, 42L, 0L, 53L
+
+#define SN_setct_AuthResTBEX "setct-AuthResTBEX"
+#define NID_setct_AuthResTBEX 572
+#define OBJ_setct_AuthResTBEX 2L, 23L, 42L, 0L, 54L
+
+#define SN_setct_AuthTokenTBE "setct-AuthTokenTBE"
+#define NID_setct_AuthTokenTBE 573
+#define OBJ_setct_AuthTokenTBE 2L, 23L, 42L, 0L, 55L
+
+#define SN_setct_CapTokenTBE "setct-CapTokenTBE"
+#define NID_setct_CapTokenTBE 574
+#define OBJ_setct_CapTokenTBE 2L, 23L, 42L, 0L, 56L
+
+#define SN_setct_CapTokenTBEX "setct-CapTokenTBEX"
+#define NID_setct_CapTokenTBEX 575
+#define OBJ_setct_CapTokenTBEX 2L, 23L, 42L, 0L, 57L
+
+#define SN_setct_AcqCardCodeMsgTBE "setct-AcqCardCodeMsgTBE"
+#define NID_setct_AcqCardCodeMsgTBE 576
+#define OBJ_setct_AcqCardCodeMsgTBE 2L, 23L, 42L, 0L, 58L
+
+#define SN_setct_AuthRevReqTBE "setct-AuthRevReqTBE"
+#define NID_setct_AuthRevReqTBE 577
+#define OBJ_setct_AuthRevReqTBE 2L, 23L, 42L, 0L, 59L
+
+#define SN_setct_AuthRevResTBE "setct-AuthRevResTBE"
+#define NID_setct_AuthRevResTBE 578
+#define OBJ_setct_AuthRevResTBE 2L, 23L, 42L, 0L, 60L
+
+#define SN_setct_AuthRevResTBEB "setct-AuthRevResTBEB"
+#define NID_setct_AuthRevResTBEB 579
+#define OBJ_setct_AuthRevResTBEB 2L, 23L, 42L, 0L, 61L
+
+#define SN_setct_CapReqTBE "setct-CapReqTBE"
+#define NID_setct_CapReqTBE 580
+#define OBJ_setct_CapReqTBE 2L, 23L, 42L, 0L, 62L
+
+#define SN_setct_CapReqTBEX "setct-CapReqTBEX"
+#define NID_setct_CapReqTBEX 581
+#define OBJ_setct_CapReqTBEX 2L, 23L, 42L, 0L, 63L
+
+#define SN_setct_CapResTBE "setct-CapResTBE"
+#define NID_setct_CapResTBE 582
+#define OBJ_setct_CapResTBE 2L, 23L, 42L, 0L, 64L
+
+#define SN_setct_CapRevReqTBE "setct-CapRevReqTBE"
+#define NID_setct_CapRevReqTBE 583
+#define OBJ_setct_CapRevReqTBE 2L, 23L, 42L, 0L, 65L
+
+#define SN_setct_CapRevReqTBEX "setct-CapRevReqTBEX"
+#define NID_setct_CapRevReqTBEX 584
+#define OBJ_setct_CapRevReqTBEX 2L, 23L, 42L, 0L, 66L
+
+#define SN_setct_CapRevResTBE "setct-CapRevResTBE"
+#define NID_setct_CapRevResTBE 585
+#define OBJ_setct_CapRevResTBE 2L, 23L, 42L, 0L, 67L
+
+#define SN_setct_CredReqTBE "setct-CredReqTBE"
+#define NID_setct_CredReqTBE 586
+#define OBJ_setct_CredReqTBE 2L, 23L, 42L, 0L, 68L
+
+#define SN_setct_CredReqTBEX "setct-CredReqTBEX"
+#define NID_setct_CredReqTBEX 587
+#define OBJ_setct_CredReqTBEX 2L, 23L, 42L, 0L, 69L
+
+#define SN_setct_CredResTBE "setct-CredResTBE"
+#define NID_setct_CredResTBE 588
+#define OBJ_setct_CredResTBE 2L, 23L, 42L, 0L, 70L
+
+#define SN_setct_CredRevReqTBE "setct-CredRevReqTBE"
+#define NID_setct_CredRevReqTBE 589
+#define OBJ_setct_CredRevReqTBE 2L, 23L, 42L, 0L, 71L
+
+#define SN_setct_CredRevReqTBEX "setct-CredRevReqTBEX"
+#define NID_setct_CredRevReqTBEX 590
+#define OBJ_setct_CredRevReqTBEX 2L, 23L, 42L, 0L, 72L
+
+#define SN_setct_CredRevResTBE "setct-CredRevResTBE"
+#define NID_setct_CredRevResTBE 591
+#define OBJ_setct_CredRevResTBE 2L, 23L, 42L, 0L, 73L
+
+#define SN_setct_BatchAdminReqTBE "setct-BatchAdminReqTBE"
+#define NID_setct_BatchAdminReqTBE 592
+#define OBJ_setct_BatchAdminReqTBE 2L, 23L, 42L, 0L, 74L
+
+#define SN_setct_BatchAdminResTBE "setct-BatchAdminResTBE"
+#define NID_setct_BatchAdminResTBE 593
+#define OBJ_setct_BatchAdminResTBE 2L, 23L, 42L, 0L, 75L
+
+#define SN_setct_RegFormReqTBE "setct-RegFormReqTBE"
+#define NID_setct_RegFormReqTBE 594
+#define OBJ_setct_RegFormReqTBE 2L, 23L, 42L, 0L, 76L
+
+#define SN_setct_CertReqTBE "setct-CertReqTBE"
+#define NID_setct_CertReqTBE 595
+#define OBJ_setct_CertReqTBE 2L, 23L, 42L, 0L, 77L
+
+#define SN_setct_CertReqTBEX "setct-CertReqTBEX"
+#define NID_setct_CertReqTBEX 596
+#define OBJ_setct_CertReqTBEX 2L, 23L, 42L, 0L, 78L
+
+#define SN_setct_CertResTBE "setct-CertResTBE"
+#define NID_setct_CertResTBE 597
+#define OBJ_setct_CertResTBE 2L, 23L, 42L, 0L, 79L
+
+#define SN_setct_CRLNotificationTBS "setct-CRLNotificationTBS"
+#define NID_setct_CRLNotificationTBS 598
+#define OBJ_setct_CRLNotificationTBS 2L, 23L, 42L, 0L, 80L
+
+#define SN_setct_CRLNotificationResTBS "setct-CRLNotificationResTBS"
+#define NID_setct_CRLNotificationResTBS 599
+#define OBJ_setct_CRLNotificationResTBS 2L, 23L, 42L, 0L, 81L
+
+#define SN_setct_BCIDistributionTBS "setct-BCIDistributionTBS"
+#define NID_setct_BCIDistributionTBS 600
+#define OBJ_setct_BCIDistributionTBS 2L, 23L, 42L, 0L, 82L
+
+#define SN_setext_genCrypt "setext-genCrypt"
+#define LN_setext_genCrypt "generic cryptogram"
+#define NID_setext_genCrypt 601
+#define OBJ_setext_genCrypt 2L, 23L, 42L, 1L, 1L
+
+#define SN_setext_miAuth "setext-miAuth"
+#define LN_setext_miAuth "merchant initiated auth"
+#define NID_setext_miAuth 602
+#define OBJ_setext_miAuth 2L, 23L, 42L, 1L, 3L
+
+#define SN_setext_pinSecure "setext-pinSecure"
+#define NID_setext_pinSecure 603
+#define OBJ_setext_pinSecure 2L, 23L, 42L, 1L, 4L
+
+#define SN_setext_pinAny "setext-pinAny"
+#define NID_setext_pinAny 604
+#define OBJ_setext_pinAny 2L, 23L, 42L, 1L, 5L
+
+#define SN_setext_track2 "setext-track2"
+#define NID_setext_track2 605
+#define OBJ_setext_track2 2L, 23L, 42L, 1L, 7L
+
+#define SN_setext_cv "setext-cv"
+#define LN_setext_cv "additional verification"
+#define NID_setext_cv 606
+#define OBJ_setext_cv 2L, 23L, 42L, 1L, 8L
+
+#define SN_set_policy_root "set-policy-root"
+#define NID_set_policy_root 607
+#define OBJ_set_policy_root 2L, 23L, 42L, 5L, 0L
+
+#define SN_setCext_hashedRoot "setCext-hashedRoot"
+#define NID_setCext_hashedRoot 608
+#define OBJ_setCext_hashedRoot 2L, 23L, 42L, 7L, 0L
+
+#define SN_setCext_certType "setCext-certType"
+#define NID_setCext_certType 609
+#define OBJ_setCext_certType 2L, 23L, 42L, 7L, 1L
+
+#define SN_setCext_merchData "setCext-merchData"
+#define NID_setCext_merchData 610
+#define OBJ_setCext_merchData 2L, 23L, 42L, 7L, 2L
+
+#define SN_setCext_cCertRequired "setCext-cCertRequired"
+#define NID_setCext_cCertRequired 611
+#define OBJ_setCext_cCertRequired 2L, 23L, 42L, 7L, 3L
+
+#define SN_setCext_tunneling "setCext-tunneling"
+#define NID_setCext_tunneling 612
+#define OBJ_setCext_tunneling 2L, 23L, 42L, 7L, 4L
+
+#define SN_setCext_setExt "setCext-setExt"
+#define NID_setCext_setExt 613
+#define OBJ_setCext_setExt 2L, 23L, 42L, 7L, 5L
+
+#define SN_setCext_setQualf "setCext-setQualf"
+#define NID_setCext_setQualf 614
+#define OBJ_setCext_setQualf 2L, 23L, 42L, 7L, 6L
+
+#define SN_setCext_PGWYcapabilities "setCext-PGWYcapabilities"
+#define NID_setCext_PGWYcapabilities 615
+#define OBJ_setCext_PGWYcapabilities 2L, 23L, 42L, 7L, 7L
+
+#define SN_setCext_TokenIdentifier "setCext-TokenIdentifier"
+#define NID_setCext_TokenIdentifier 616
+#define OBJ_setCext_TokenIdentifier 2L, 23L, 42L, 7L, 8L
+
+#define SN_setCext_Track2Data "setCext-Track2Data"
+#define NID_setCext_Track2Data 617
+#define OBJ_setCext_Track2Data 2L, 23L, 42L, 7L, 9L
+
+#define SN_setCext_TokenType "setCext-TokenType"
+#define NID_setCext_TokenType 618
+#define OBJ_setCext_TokenType 2L, 23L, 42L, 7L, 10L
+
+#define SN_setCext_IssuerCapabilities "setCext-IssuerCapabilities"
+#define NID_setCext_IssuerCapabilities 619
+#define OBJ_setCext_IssuerCapabilities 2L, 23L, 42L, 7L, 11L
+
+#define SN_setAttr_Cert "setAttr-Cert"
+#define NID_setAttr_Cert 620
+#define OBJ_setAttr_Cert 2L, 23L, 42L, 3L, 0L
+
+#define SN_setAttr_PGWYcap "setAttr-PGWYcap"
+#define LN_setAttr_PGWYcap "payment gateway capabilities"
+#define NID_setAttr_PGWYcap 621
+#define OBJ_setAttr_PGWYcap 2L, 23L, 42L, 3L, 1L
+
+#define SN_setAttr_TokenType "setAttr-TokenType"
+#define NID_setAttr_TokenType 622
+#define OBJ_setAttr_TokenType 2L, 23L, 42L, 3L, 2L
+
+#define SN_setAttr_IssCap "setAttr-IssCap"
+#define LN_setAttr_IssCap "issuer capabilities"
+#define NID_setAttr_IssCap 623
+#define OBJ_setAttr_IssCap 2L, 23L, 42L, 3L, 3L
+
+#define SN_set_rootKeyThumb "set-rootKeyThumb"
+#define NID_set_rootKeyThumb 624
+#define OBJ_set_rootKeyThumb 2L, 23L, 42L, 3L, 0L, 0L
+
+#define SN_set_addPolicy "set-addPolicy"
+#define NID_set_addPolicy 625
+#define OBJ_set_addPolicy 2L, 23L, 42L, 3L, 0L, 1L
+
+#define SN_setAttr_Token_EMV "setAttr-Token-EMV"
+#define NID_setAttr_Token_EMV 626
+#define OBJ_setAttr_Token_EMV 2L, 23L, 42L, 3L, 2L, 1L
+
+#define SN_setAttr_Token_B0Prime "setAttr-Token-B0Prime"
+#define NID_setAttr_Token_B0Prime 627
+#define OBJ_setAttr_Token_B0Prime 2L, 23L, 42L, 3L, 2L, 2L
+
+#define SN_setAttr_IssCap_CVM "setAttr-IssCap-CVM"
+#define NID_setAttr_IssCap_CVM 628
+#define OBJ_setAttr_IssCap_CVM 2L, 23L, 42L, 3L, 3L, 3L
+
+#define SN_setAttr_IssCap_T2 "setAttr-IssCap-T2"
+#define NID_setAttr_IssCap_T2 629
+#define OBJ_setAttr_IssCap_T2 2L, 23L, 42L, 3L, 3L, 4L
+
+#define SN_setAttr_IssCap_Sig "setAttr-IssCap-Sig"
+#define NID_setAttr_IssCap_Sig 630
+#define OBJ_setAttr_IssCap_Sig 2L, 23L, 42L, 3L, 3L, 5L
+
+#define SN_setAttr_GenCryptgrm "setAttr-GenCryptgrm"
+#define LN_setAttr_GenCryptgrm "generate cryptogram"
+#define NID_setAttr_GenCryptgrm 631
+#define OBJ_setAttr_GenCryptgrm 2L, 23L, 42L, 3L, 3L, 3L, 1L
+
+#define SN_setAttr_T2Enc "setAttr-T2Enc"
+#define LN_setAttr_T2Enc "encrypted track 2"
+#define NID_setAttr_T2Enc 632
+#define OBJ_setAttr_T2Enc 2L, 23L, 42L, 3L, 3L, 4L, 1L
+
+#define SN_setAttr_T2cleartxt "setAttr-T2cleartxt"
+#define LN_setAttr_T2cleartxt "cleartext track 2"
+#define NID_setAttr_T2cleartxt 633
+#define OBJ_setAttr_T2cleartxt 2L, 23L, 42L, 3L, 3L, 4L, 2L
+
+#define SN_setAttr_TokICCsig "setAttr-TokICCsig"
+#define LN_setAttr_TokICCsig "ICC or token signature"
+#define NID_setAttr_TokICCsig 634
+#define OBJ_setAttr_TokICCsig 2L, 23L, 42L, 3L, 3L, 5L, 1L
+
+#define SN_setAttr_SecDevSig "setAttr-SecDevSig"
+#define LN_setAttr_SecDevSig "secure device signature"
+#define NID_setAttr_SecDevSig 635
+#define OBJ_setAttr_SecDevSig 2L, 23L, 42L, 3L, 3L, 5L, 2L
+
+#define SN_set_brand_IATA_ATA "set-brand-IATA-ATA"
+#define NID_set_brand_IATA_ATA 636
+#define OBJ_set_brand_IATA_ATA 2L, 23L, 42L, 8L, 1L
+
+#define SN_set_brand_Diners "set-brand-Diners"
+#define NID_set_brand_Diners 637
+#define OBJ_set_brand_Diners 2L, 23L, 42L, 8L, 30L
+
+#define SN_set_brand_AmericanExpress "set-brand-AmericanExpress"
+#define NID_set_brand_AmericanExpress 638
+#define OBJ_set_brand_AmericanExpress 2L, 23L, 42L, 8L, 34L
+
+#define SN_set_brand_JCB "set-brand-JCB"
+#define NID_set_brand_JCB 639
+#define OBJ_set_brand_JCB 2L, 23L, 42L, 8L, 35L
+
+#define SN_set_brand_Visa "set-brand-Visa"
+#define NID_set_brand_Visa 640
+#define OBJ_set_brand_Visa 2L, 23L, 42L, 8L, 4L
+
+#define SN_set_brand_MasterCard "set-brand-MasterCard"
+#define NID_set_brand_MasterCard 641
+#define OBJ_set_brand_MasterCard 2L, 23L, 42L, 8L, 5L
+
+#define SN_set_brand_Novus "set-brand-Novus"
+#define NID_set_brand_Novus 642
+#define OBJ_set_brand_Novus 2L, 23L, 42L, 8L, 6011L
+
+#define SN_des_cdmf "DES-CDMF"
+#define LN_des_cdmf "des-cdmf"
+#define NID_des_cdmf 643
+#define OBJ_des_cdmf 1L, 2L, 840L, 113549L, 3L, 10L
+
+#define SN_rsaOAEPEncryptionSET "rsaOAEPEncryptionSET"
+#define NID_rsaOAEPEncryptionSET 644
+#define OBJ_rsaOAEPEncryptionSET 1L, 2L, 840L, 113549L, 1L, 1L, 6L
+
+#define SN_itu_t "ITU-T"
+#define LN_itu_t "itu-t"
+#define NID_itu_t 645
+#define OBJ_itu_t 0L
+
+#define SN_joint_iso_itu_t "JOINT-ISO-ITU-T"
+#define LN_joint_iso_itu_t "joint-iso-itu-t"
+#define NID_joint_iso_itu_t 646
+#define OBJ_joint_iso_itu_t 2L
+
+#define SN_international_organizations "international-organizations"
+#define LN_international_organizations "International Organizations"
+#define NID_international_organizations 647
+#define OBJ_international_organizations 2L, 23L
+
+#define SN_ms_smartcard_login "msSmartcardLogin"
+#define LN_ms_smartcard_login "Microsoft Smartcardlogin"
+#define NID_ms_smartcard_login 648
+#define OBJ_ms_smartcard_login 1L, 3L, 6L, 1L, 4L, 1L, 311L, 20L, 2L, 2L
+
+#define SN_ms_upn "msUPN"
+#define LN_ms_upn "Microsoft Universal Principal Name"
+#define NID_ms_upn 649
+#define OBJ_ms_upn 1L, 3L, 6L, 1L, 4L, 1L, 311L, 20L, 2L, 3L
+
+#define SN_aes_128_cfb1 "AES-128-CFB1"
+#define LN_aes_128_cfb1 "aes-128-cfb1"
+#define NID_aes_128_cfb1 650
+
+#define SN_aes_192_cfb1 "AES-192-CFB1"
+#define LN_aes_192_cfb1 "aes-192-cfb1"
+#define NID_aes_192_cfb1 651
+
+#define SN_aes_256_cfb1 "AES-256-CFB1"
+#define LN_aes_256_cfb1 "aes-256-cfb1"
+#define NID_aes_256_cfb1 652
+
+#define SN_aes_128_cfb8 "AES-128-CFB8"
+#define LN_aes_128_cfb8 "aes-128-cfb8"
+#define NID_aes_128_cfb8 653
+
+#define SN_aes_192_cfb8 "AES-192-CFB8"
+#define LN_aes_192_cfb8 "aes-192-cfb8"
+#define NID_aes_192_cfb8 654
+
+#define SN_aes_256_cfb8 "AES-256-CFB8"
+#define LN_aes_256_cfb8 "aes-256-cfb8"
+#define NID_aes_256_cfb8 655
+
+#define SN_des_cfb1 "DES-CFB1"
+#define LN_des_cfb1 "des-cfb1"
+#define NID_des_cfb1 656
+
+#define SN_des_cfb8 "DES-CFB8"
+#define LN_des_cfb8 "des-cfb8"
+#define NID_des_cfb8 657
+
+#define SN_des_ede3_cfb1 "DES-EDE3-CFB1"
+#define LN_des_ede3_cfb1 "des-ede3-cfb1"
+#define NID_des_ede3_cfb1 658
+
+#define SN_des_ede3_cfb8 "DES-EDE3-CFB8"
+#define LN_des_ede3_cfb8 "des-ede3-cfb8"
+#define NID_des_ede3_cfb8 659
+
+#define SN_streetAddress "street"
+#define LN_streetAddress "streetAddress"
+#define NID_streetAddress 660
+#define OBJ_streetAddress 2L, 5L, 4L, 9L
+
+#define LN_postalCode "postalCode"
+#define NID_postalCode 661
+#define OBJ_postalCode 2L, 5L, 4L, 17L
+
+#define SN_id_ppl "id-ppl"
+#define NID_id_ppl 662
+#define OBJ_id_ppl 1L, 3L, 6L, 1L, 5L, 5L, 7L, 21L
+
+#define SN_proxyCertInfo "proxyCertInfo"
+#define LN_proxyCertInfo "Proxy Certificate Information"
+#define NID_proxyCertInfo 663
+#define OBJ_proxyCertInfo 1L, 3L, 6L, 1L, 5L, 5L, 7L, 1L, 14L
+
+#define SN_id_ppl_anyLanguage "id-ppl-anyLanguage"
+#define LN_id_ppl_anyLanguage "Any language"
+#define NID_id_ppl_anyLanguage 664
+#define OBJ_id_ppl_anyLanguage 1L, 3L, 6L, 1L, 5L, 5L, 7L, 21L, 0L
+
+#define SN_id_ppl_inheritAll "id-ppl-inheritAll"
+#define LN_id_ppl_inheritAll "Inherit all"
+#define NID_id_ppl_inheritAll 665
+#define OBJ_id_ppl_inheritAll 1L, 3L, 6L, 1L, 5L, 5L, 7L, 21L, 1L
+
+#define SN_name_constraints "nameConstraints"
+#define LN_name_constraints "X509v3 Name Constraints"
+#define NID_name_constraints 666
+#define OBJ_name_constraints 2L, 5L, 29L, 30L
+
+#define SN_Independent "id-ppl-independent"
+#define LN_Independent "Independent"
+#define NID_Independent 667
+#define OBJ_Independent 1L, 3L, 6L, 1L, 5L, 5L, 7L, 21L, 2L
+
+#define SN_sha256WithRSAEncryption "RSA-SHA256"
+#define LN_sha256WithRSAEncryption "sha256WithRSAEncryption"
+#define NID_sha256WithRSAEncryption 668
+#define OBJ_sha256WithRSAEncryption 1L, 2L, 840L, 113549L, 1L, 1L, 11L
+
+#define SN_sha384WithRSAEncryption "RSA-SHA384"
+#define LN_sha384WithRSAEncryption "sha384WithRSAEncryption"
+#define NID_sha384WithRSAEncryption 669
+#define OBJ_sha384WithRSAEncryption 1L, 2L, 840L, 113549L, 1L, 1L, 12L
+
+#define SN_sha512WithRSAEncryption "RSA-SHA512"
+#define LN_sha512WithRSAEncryption "sha512WithRSAEncryption"
+#define NID_sha512WithRSAEncryption 670
+#define OBJ_sha512WithRSAEncryption 1L, 2L, 840L, 113549L, 1L, 1L, 13L
+
+#define SN_sha224WithRSAEncryption "RSA-SHA224"
+#define LN_sha224WithRSAEncryption "sha224WithRSAEncryption"
+#define NID_sha224WithRSAEncryption 671
+#define OBJ_sha224WithRSAEncryption 1L, 2L, 840L, 113549L, 1L, 1L, 14L
+
+#define SN_sha256 "SHA256"
+#define LN_sha256 "sha256"
+#define NID_sha256 672
+#define OBJ_sha256 2L, 16L, 840L, 1L, 101L, 3L, 4L, 2L, 1L
+
+#define SN_sha384 "SHA384"
+#define LN_sha384 "sha384"
+#define NID_sha384 673
+#define OBJ_sha384 2L, 16L, 840L, 1L, 101L, 3L, 4L, 2L, 2L
+
+#define SN_sha512 "SHA512"
+#define LN_sha512 "sha512"
+#define NID_sha512 674
+#define OBJ_sha512 2L, 16L, 840L, 1L, 101L, 3L, 4L, 2L, 3L
+
+#define SN_sha224 "SHA224"
+#define LN_sha224 "sha224"
+#define NID_sha224 675
+#define OBJ_sha224 2L, 16L, 840L, 1L, 101L, 3L, 4L, 2L, 4L
+
+#define SN_identified_organization "identified-organization"
+#define NID_identified_organization 676
+#define OBJ_identified_organization 1L, 3L
+
+#define SN_certicom_arc "certicom-arc"
+#define NID_certicom_arc 677
+#define OBJ_certicom_arc 1L, 3L, 132L
+
+#define SN_wap "wap"
+#define NID_wap 678
+#define OBJ_wap 2L, 23L, 43L
+
+#define SN_wap_wsg "wap-wsg"
+#define NID_wap_wsg 679
+#define OBJ_wap_wsg 2L, 23L, 43L, 1L
+
+#define SN_X9_62_id_characteristic_two_basis "id-characteristic-two-basis"
+#define NID_X9_62_id_characteristic_two_basis 680
+#define OBJ_X9_62_id_characteristic_two_basis 1L, 2L, 840L, 10045L, 1L, 2L, 3L
+
+#define SN_X9_62_onBasis "onBasis"
+#define NID_X9_62_onBasis 681
+#define OBJ_X9_62_onBasis 1L, 2L, 840L, 10045L, 1L, 2L, 3L, 1L
+
+#define SN_X9_62_tpBasis "tpBasis"
+#define NID_X9_62_tpBasis 682
+#define OBJ_X9_62_tpBasis 1L, 2L, 840L, 10045L, 1L, 2L, 3L, 2L
+
+#define SN_X9_62_ppBasis "ppBasis"
+#define NID_X9_62_ppBasis 683
+#define OBJ_X9_62_ppBasis 1L, 2L, 840L, 10045L, 1L, 2L, 3L, 3L
+
+#define SN_X9_62_c2pnb163v1 "c2pnb163v1"
+#define NID_X9_62_c2pnb163v1 684
+#define OBJ_X9_62_c2pnb163v1 1L, 2L, 840L, 10045L, 3L, 0L, 1L
+
+#define SN_X9_62_c2pnb163v2 "c2pnb163v2"
+#define NID_X9_62_c2pnb163v2 685
+#define OBJ_X9_62_c2pnb163v2 1L, 2L, 840L, 10045L, 3L, 0L, 2L
+
+#define SN_X9_62_c2pnb163v3 "c2pnb163v3"
+#define NID_X9_62_c2pnb163v3 686
+#define OBJ_X9_62_c2pnb163v3 1L, 2L, 840L, 10045L, 3L, 0L, 3L
+
+#define SN_X9_62_c2pnb176v1 "c2pnb176v1"
+#define NID_X9_62_c2pnb176v1 687
+#define OBJ_X9_62_c2pnb176v1 1L, 2L, 840L, 10045L, 3L, 0L, 4L
+
+#define SN_X9_62_c2tnb191v1 "c2tnb191v1"
+#define NID_X9_62_c2tnb191v1 688
+#define OBJ_X9_62_c2tnb191v1 1L, 2L, 840L, 10045L, 3L, 0L, 5L
+
+#define SN_X9_62_c2tnb191v2 "c2tnb191v2"
+#define NID_X9_62_c2tnb191v2 689
+#define OBJ_X9_62_c2tnb191v2 1L, 2L, 840L, 10045L, 3L, 0L, 6L
+
+#define SN_X9_62_c2tnb191v3 "c2tnb191v3"
+#define NID_X9_62_c2tnb191v3 690
+#define OBJ_X9_62_c2tnb191v3 1L, 2L, 840L, 10045L, 3L, 0L, 7L
+
+#define SN_X9_62_c2onb191v4 "c2onb191v4"
+#define NID_X9_62_c2onb191v4 691
+#define OBJ_X9_62_c2onb191v4 1L, 2L, 840L, 10045L, 3L, 0L, 8L
+
+#define SN_X9_62_c2onb191v5 "c2onb191v5"
+#define NID_X9_62_c2onb191v5 692
+#define OBJ_X9_62_c2onb191v5 1L, 2L, 840L, 10045L, 3L, 0L, 9L
+
+#define SN_X9_62_c2pnb208w1 "c2pnb208w1"
+#define NID_X9_62_c2pnb208w1 693
+#define OBJ_X9_62_c2pnb208w1 1L, 2L, 840L, 10045L, 3L, 0L, 10L
+
+#define SN_X9_62_c2tnb239v1 "c2tnb239v1"
+#define NID_X9_62_c2tnb239v1 694
+#define OBJ_X9_62_c2tnb239v1 1L, 2L, 840L, 10045L, 3L, 0L, 11L
+
+#define SN_X9_62_c2tnb239v2 "c2tnb239v2"
+#define NID_X9_62_c2tnb239v2 695
+#define OBJ_X9_62_c2tnb239v2 1L, 2L, 840L, 10045L, 3L, 0L, 12L
+
+#define SN_X9_62_c2tnb239v3 "c2tnb239v3"
+#define NID_X9_62_c2tnb239v3 696
+#define OBJ_X9_62_c2tnb239v3 1L, 2L, 840L, 10045L, 3L, 0L, 13L
+
+#define SN_X9_62_c2onb239v4 "c2onb239v4"
+#define NID_X9_62_c2onb239v4 697
+#define OBJ_X9_62_c2onb239v4 1L, 2L, 840L, 10045L, 3L, 0L, 14L
+
+#define SN_X9_62_c2onb239v5 "c2onb239v5"
+#define NID_X9_62_c2onb239v5 698
+#define OBJ_X9_62_c2onb239v5 1L, 2L, 840L, 10045L, 3L, 0L, 15L
+
+#define SN_X9_62_c2pnb272w1 "c2pnb272w1"
+#define NID_X9_62_c2pnb272w1 699
+#define OBJ_X9_62_c2pnb272w1 1L, 2L, 840L, 10045L, 3L, 0L, 16L
+
+#define SN_X9_62_c2pnb304w1 "c2pnb304w1"
+#define NID_X9_62_c2pnb304w1 700
+#define OBJ_X9_62_c2pnb304w1 1L, 2L, 840L, 10045L, 3L, 0L, 17L
+
+#define SN_X9_62_c2tnb359v1 "c2tnb359v1"
+#define NID_X9_62_c2tnb359v1 701
+#define OBJ_X9_62_c2tnb359v1 1L, 2L, 840L, 10045L, 3L, 0L, 18L
+
+#define SN_X9_62_c2pnb368w1 "c2pnb368w1"
+#define NID_X9_62_c2pnb368w1 702
+#define OBJ_X9_62_c2pnb368w1 1L, 2L, 840L, 10045L, 3L, 0L, 19L
+
+#define SN_X9_62_c2tnb431r1 "c2tnb431r1"
+#define NID_X9_62_c2tnb431r1 703
+#define OBJ_X9_62_c2tnb431r1 1L, 2L, 840L, 10045L, 3L, 0L, 20L
+
+#define SN_secp112r1 "secp112r1"
+#define NID_secp112r1 704
+#define OBJ_secp112r1 1L, 3L, 132L, 0L, 6L
+
+#define SN_secp112r2 "secp112r2"
+#define NID_secp112r2 705
+#define OBJ_secp112r2 1L, 3L, 132L, 0L, 7L
+
+#define SN_secp128r1 "secp128r1"
+#define NID_secp128r1 706
+#define OBJ_secp128r1 1L, 3L, 132L, 0L, 28L
+
+#define SN_secp128r2 "secp128r2"
+#define NID_secp128r2 707
+#define OBJ_secp128r2 1L, 3L, 132L, 0L, 29L
+
+#define SN_secp160k1 "secp160k1"
+#define NID_secp160k1 708
+#define OBJ_secp160k1 1L, 3L, 132L, 0L, 9L
+
+#define SN_secp160r1 "secp160r1"
+#define NID_secp160r1 709
+#define OBJ_secp160r1 1L, 3L, 132L, 0L, 8L
+
+#define SN_secp160r2 "secp160r2"
+#define NID_secp160r2 710
+#define OBJ_secp160r2 1L, 3L, 132L, 0L, 30L
+
+#define SN_secp192k1 "secp192k1"
+#define NID_secp192k1 711
+#define OBJ_secp192k1 1L, 3L, 132L, 0L, 31L
+
+#define SN_secp224k1 "secp224k1"
+#define NID_secp224k1 712
+#define OBJ_secp224k1 1L, 3L, 132L, 0L, 32L
+
+#define SN_secp224r1 "secp224r1"
+#define NID_secp224r1 713
+#define OBJ_secp224r1 1L, 3L, 132L, 0L, 33L
+
+#define SN_secp256k1 "secp256k1"
+#define NID_secp256k1 714
+#define OBJ_secp256k1 1L, 3L, 132L, 0L, 10L
+
+#define SN_secp384r1 "secp384r1"
+#define NID_secp384r1 715
+#define OBJ_secp384r1 1L, 3L, 132L, 0L, 34L
+
+#define SN_secp521r1 "secp521r1"
+#define NID_secp521r1 716
+#define OBJ_secp521r1 1L, 3L, 132L, 0L, 35L
+
+#define SN_sect113r1 "sect113r1"
+#define NID_sect113r1 717
+#define OBJ_sect113r1 1L, 3L, 132L, 0L, 4L
+
+#define SN_sect113r2 "sect113r2"
+#define NID_sect113r2 718
+#define OBJ_sect113r2 1L, 3L, 132L, 0L, 5L
+
+#define SN_sect131r1 "sect131r1"
+#define NID_sect131r1 719
+#define OBJ_sect131r1 1L, 3L, 132L, 0L, 22L
+
+#define SN_sect131r2 "sect131r2"
+#define NID_sect131r2 720
+#define OBJ_sect131r2 1L, 3L, 132L, 0L, 23L
+
+#define SN_sect163k1 "sect163k1"
+#define NID_sect163k1 721
+#define OBJ_sect163k1 1L, 3L, 132L, 0L, 1L
+
+#define SN_sect163r1 "sect163r1"
+#define NID_sect163r1 722
+#define OBJ_sect163r1 1L, 3L, 132L, 0L, 2L
+
+#define SN_sect163r2 "sect163r2"
+#define NID_sect163r2 723
+#define OBJ_sect163r2 1L, 3L, 132L, 0L, 15L
+
+#define SN_sect193r1 "sect193r1"
+#define NID_sect193r1 724
+#define OBJ_sect193r1 1L, 3L, 132L, 0L, 24L
+
+#define SN_sect193r2 "sect193r2"
+#define NID_sect193r2 725
+#define OBJ_sect193r2 1L, 3L, 132L, 0L, 25L
+
+#define SN_sect233k1 "sect233k1"
+#define NID_sect233k1 726
+#define OBJ_sect233k1 1L, 3L, 132L, 0L, 26L
+
+#define SN_sect233r1 "sect233r1"
+#define NID_sect233r1 727
+#define OBJ_sect233r1 1L, 3L, 132L, 0L, 27L
+
+#define SN_sect239k1 "sect239k1"
+#define NID_sect239k1 728
+#define OBJ_sect239k1 1L, 3L, 132L, 0L, 3L
+
+#define SN_sect283k1 "sect283k1"
+#define NID_sect283k1 729
+#define OBJ_sect283k1 1L, 3L, 132L, 0L, 16L
+
+#define SN_sect283r1 "sect283r1"
+#define NID_sect283r1 730
+#define OBJ_sect283r1 1L, 3L, 132L, 0L, 17L
+
+#define SN_sect409k1 "sect409k1"
+#define NID_sect409k1 731
+#define OBJ_sect409k1 1L, 3L, 132L, 0L, 36L
+
+#define SN_sect409r1 "sect409r1"
+#define NID_sect409r1 732
+#define OBJ_sect409r1 1L, 3L, 132L, 0L, 37L
+
+#define SN_sect571k1 "sect571k1"
+#define NID_sect571k1 733
+#define OBJ_sect571k1 1L, 3L, 132L, 0L, 38L
+
+#define SN_sect571r1 "sect571r1"
+#define NID_sect571r1 734
+#define OBJ_sect571r1 1L, 3L, 132L, 0L, 39L
+
+#define SN_wap_wsg_idm_ecid_wtls1 "wap-wsg-idm-ecid-wtls1"
+#define NID_wap_wsg_idm_ecid_wtls1 735
+#define OBJ_wap_wsg_idm_ecid_wtls1 2L, 23L, 43L, 1L, 4L, 1L
+
+#define SN_wap_wsg_idm_ecid_wtls3 "wap-wsg-idm-ecid-wtls3"
+#define NID_wap_wsg_idm_ecid_wtls3 736
+#define OBJ_wap_wsg_idm_ecid_wtls3 2L, 23L, 43L, 1L, 4L, 3L
+
+#define SN_wap_wsg_idm_ecid_wtls4 "wap-wsg-idm-ecid-wtls4"
+#define NID_wap_wsg_idm_ecid_wtls4 737
+#define OBJ_wap_wsg_idm_ecid_wtls4 2L, 23L, 43L, 1L, 4L, 4L
+
+#define SN_wap_wsg_idm_ecid_wtls5 "wap-wsg-idm-ecid-wtls5"
+#define NID_wap_wsg_idm_ecid_wtls5 738
+#define OBJ_wap_wsg_idm_ecid_wtls5 2L, 23L, 43L, 1L, 4L, 5L
+
+#define SN_wap_wsg_idm_ecid_wtls6 "wap-wsg-idm-ecid-wtls6"
+#define NID_wap_wsg_idm_ecid_wtls6 739
+#define OBJ_wap_wsg_idm_ecid_wtls6 2L, 23L, 43L, 1L, 4L, 6L
+
+#define SN_wap_wsg_idm_ecid_wtls7 "wap-wsg-idm-ecid-wtls7"
+#define NID_wap_wsg_idm_ecid_wtls7 740
+#define OBJ_wap_wsg_idm_ecid_wtls7 2L, 23L, 43L, 1L, 4L, 7L
+
+#define SN_wap_wsg_idm_ecid_wtls8 "wap-wsg-idm-ecid-wtls8"
+#define NID_wap_wsg_idm_ecid_wtls8 741
+#define OBJ_wap_wsg_idm_ecid_wtls8 2L, 23L, 43L, 1L, 4L, 8L
+
+#define SN_wap_wsg_idm_ecid_wtls9 "wap-wsg-idm-ecid-wtls9"
+#define NID_wap_wsg_idm_ecid_wtls9 742
+#define OBJ_wap_wsg_idm_ecid_wtls9 2L, 23L, 43L, 1L, 4L, 9L
+
+#define SN_wap_wsg_idm_ecid_wtls10 "wap-wsg-idm-ecid-wtls10"
+#define NID_wap_wsg_idm_ecid_wtls10 743
+#define OBJ_wap_wsg_idm_ecid_wtls10 2L, 23L, 43L, 1L, 4L, 10L
+
+#define SN_wap_wsg_idm_ecid_wtls11 "wap-wsg-idm-ecid-wtls11"
+#define NID_wap_wsg_idm_ecid_wtls11 744
+#define OBJ_wap_wsg_idm_ecid_wtls11 2L, 23L, 43L, 1L, 4L, 11L
+
+#define SN_wap_wsg_idm_ecid_wtls12 "wap-wsg-idm-ecid-wtls12"
+#define NID_wap_wsg_idm_ecid_wtls12 745
+#define OBJ_wap_wsg_idm_ecid_wtls12 2L, 23L, 43L, 1L, 4L, 12L
+
+#define SN_any_policy "anyPolicy"
+#define LN_any_policy "X509v3 Any Policy"
+#define NID_any_policy 746
+#define OBJ_any_policy 2L, 5L, 29L, 32L, 0L
+
+#define SN_policy_mappings "policyMappings"
+#define LN_policy_mappings "X509v3 Policy Mappings"
+#define NID_policy_mappings 747
+#define OBJ_policy_mappings 2L, 5L, 29L, 33L
+
+#define SN_inhibit_any_policy "inhibitAnyPolicy"
+#define LN_inhibit_any_policy "X509v3 Inhibit Any Policy"
+#define NID_inhibit_any_policy 748
+#define OBJ_inhibit_any_policy 2L, 5L, 29L, 54L
+
+#define SN_ipsec3 "Oakley-EC2N-3"
+#define LN_ipsec3 "ipsec3"
+#define NID_ipsec3 749
+
+#define SN_ipsec4 "Oakley-EC2N-4"
+#define LN_ipsec4 "ipsec4"
+#define NID_ipsec4 750
+
+#define SN_camellia_128_cbc "CAMELLIA-128-CBC"
+#define LN_camellia_128_cbc "camellia-128-cbc"
+#define NID_camellia_128_cbc 751
+#define OBJ_camellia_128_cbc 1L, 2L, 392L, 200011L, 61L, 1L, 1L, 1L, 2L
+
+#define SN_camellia_192_cbc "CAMELLIA-192-CBC"
+#define LN_camellia_192_cbc "camellia-192-cbc"
+#define NID_camellia_192_cbc 752
+#define OBJ_camellia_192_cbc 1L, 2L, 392L, 200011L, 61L, 1L, 1L, 1L, 3L
+
+#define SN_camellia_256_cbc "CAMELLIA-256-CBC"
+#define LN_camellia_256_cbc "camellia-256-cbc"
+#define NID_camellia_256_cbc 753
+#define OBJ_camellia_256_cbc 1L, 2L, 392L, 200011L, 61L, 1L, 1L, 1L, 4L
+
+#define SN_camellia_128_ecb "CAMELLIA-128-ECB"
+#define LN_camellia_128_ecb "camellia-128-ecb"
+#define NID_camellia_128_ecb 754
+#define OBJ_camellia_128_ecb 0L, 3L, 4401L, 5L, 3L, 1L, 9L, 1L
+
+#define SN_camellia_192_ecb "CAMELLIA-192-ECB"
+#define LN_camellia_192_ecb "camellia-192-ecb"
+#define NID_camellia_192_ecb 755
+#define OBJ_camellia_192_ecb 0L, 3L, 4401L, 5L, 3L, 1L, 9L, 21L
+
+#define SN_camellia_256_ecb "CAMELLIA-256-ECB"
+#define LN_camellia_256_ecb "camellia-256-ecb"
+#define NID_camellia_256_ecb 756
+#define OBJ_camellia_256_ecb 0L, 3L, 4401L, 5L, 3L, 1L, 9L, 41L
+
+#define SN_camellia_128_cfb128 "CAMELLIA-128-CFB"
+#define LN_camellia_128_cfb128 "camellia-128-cfb"
+#define NID_camellia_128_cfb128 757
+#define OBJ_camellia_128_cfb128 0L, 3L, 4401L, 5L, 3L, 1L, 9L, 4L
+
+#define SN_camellia_192_cfb128 "CAMELLIA-192-CFB"
+#define LN_camellia_192_cfb128 "camellia-192-cfb"
+#define NID_camellia_192_cfb128 758
+#define OBJ_camellia_192_cfb128 0L, 3L, 4401L, 5L, 3L, 1L, 9L, 24L
+
+#define SN_camellia_256_cfb128 "CAMELLIA-256-CFB"
+#define LN_camellia_256_cfb128 "camellia-256-cfb"
+#define NID_camellia_256_cfb128 759
+#define OBJ_camellia_256_cfb128 0L, 3L, 4401L, 5L, 3L, 1L, 9L, 44L
+
+#define SN_camellia_128_cfb1 "CAMELLIA-128-CFB1"
+#define LN_camellia_128_cfb1 "camellia-128-cfb1"
+#define NID_camellia_128_cfb1 760
+
+#define SN_camellia_192_cfb1 "CAMELLIA-192-CFB1"
+#define LN_camellia_192_cfb1 "camellia-192-cfb1"
+#define NID_camellia_192_cfb1 761
+
+#define SN_camellia_256_cfb1 "CAMELLIA-256-CFB1"
+#define LN_camellia_256_cfb1 "camellia-256-cfb1"
+#define NID_camellia_256_cfb1 762
+
+#define SN_camellia_128_cfb8 "CAMELLIA-128-CFB8"
+#define LN_camellia_128_cfb8 "camellia-128-cfb8"
+#define NID_camellia_128_cfb8 763
+
+#define SN_camellia_192_cfb8 "CAMELLIA-192-CFB8"
+#define LN_camellia_192_cfb8 "camellia-192-cfb8"
+#define NID_camellia_192_cfb8 764
+
+#define SN_camellia_256_cfb8 "CAMELLIA-256-CFB8"
+#define LN_camellia_256_cfb8 "camellia-256-cfb8"
+#define NID_camellia_256_cfb8 765
+
+#define SN_camellia_128_ofb128 "CAMELLIA-128-OFB"
+#define LN_camellia_128_ofb128 "camellia-128-ofb"
+#define NID_camellia_128_ofb128 766
+#define OBJ_camellia_128_ofb128 0L, 3L, 4401L, 5L, 3L, 1L, 9L, 3L
+
+#define SN_camellia_192_ofb128 "CAMELLIA-192-OFB"
+#define LN_camellia_192_ofb128 "camellia-192-ofb"
+#define NID_camellia_192_ofb128 767
+#define OBJ_camellia_192_ofb128 0L, 3L, 4401L, 5L, 3L, 1L, 9L, 23L
+
+#define SN_camellia_256_ofb128 "CAMELLIA-256-OFB"
+#define LN_camellia_256_ofb128 "camellia-256-ofb"
+#define NID_camellia_256_ofb128 768
+#define OBJ_camellia_256_ofb128 0L, 3L, 4401L, 5L, 3L, 1L, 9L, 43L
+
+#define SN_subject_directory_attributes "subjectDirectoryAttributes"
+#define LN_subject_directory_attributes "X509v3 Subject Directory Attributes"
+#define NID_subject_directory_attributes 769
+#define OBJ_subject_directory_attributes 2L, 5L, 29L, 9L
+
+#define SN_issuing_distribution_point "issuingDistributionPoint"
+#define LN_issuing_distribution_point "X509v3 Issuing Distribution Point"
+#define NID_issuing_distribution_point 770
+#define OBJ_issuing_distribution_point 2L, 5L, 29L, 28L
+
+#define SN_certificate_issuer "certificateIssuer"
+#define LN_certificate_issuer "X509v3 Certificate Issuer"
+#define NID_certificate_issuer 771
+#define OBJ_certificate_issuer 2L, 5L, 29L, 29L
+
+#define SN_kisa "KISA"
+#define LN_kisa "kisa"
+#define NID_kisa 773
+#define OBJ_kisa 1L, 2L, 410L, 200004L
+
+#define SN_seed_ecb "SEED-ECB"
+#define LN_seed_ecb "seed-ecb"
+#define NID_seed_ecb 776
+#define OBJ_seed_ecb 1L, 2L, 410L, 200004L, 1L, 3L
+
+#define SN_seed_cbc "SEED-CBC"
+#define LN_seed_cbc "seed-cbc"
+#define NID_seed_cbc 777
+#define OBJ_seed_cbc 1L, 2L, 410L, 200004L, 1L, 4L
+
+#define SN_seed_ofb128 "SEED-OFB"
+#define LN_seed_ofb128 "seed-ofb"
+#define NID_seed_ofb128 778
+#define OBJ_seed_ofb128 1L, 2L, 410L, 200004L, 1L, 6L
+
+#define SN_seed_cfb128 "SEED-CFB"
+#define LN_seed_cfb128 "seed-cfb"
+#define NID_seed_cfb128 779
+#define OBJ_seed_cfb128 1L, 2L, 410L, 200004L, 1L, 5L
+
+#define SN_hmac_md5 "HMAC-MD5"
+#define LN_hmac_md5 "hmac-md5"
+#define NID_hmac_md5 780
+#define OBJ_hmac_md5 1L, 3L, 6L, 1L, 5L, 5L, 8L, 1L, 1L
+
+#define SN_hmac_sha1 "HMAC-SHA1"
+#define LN_hmac_sha1 "hmac-sha1"
+#define NID_hmac_sha1 781
+#define OBJ_hmac_sha1 1L, 3L, 6L, 1L, 5L, 5L, 8L, 1L, 2L
+
+#define SN_id_PasswordBasedMAC "id-PasswordBasedMAC"
+#define LN_id_PasswordBasedMAC "password based MAC"
+#define NID_id_PasswordBasedMAC 782
+#define OBJ_id_PasswordBasedMAC 1L, 2L, 840L, 113533L, 7L, 66L, 13L
+
+#define SN_id_DHBasedMac "id-DHBasedMac"
+#define LN_id_DHBasedMac "Diffie-Hellman based MAC"
+#define NID_id_DHBasedMac 783
+#define OBJ_id_DHBasedMac 1L, 2L, 840L, 113533L, 7L, 66L, 30L
+
+#define SN_id_it_suppLangTags "id-it-suppLangTags"
+#define NID_id_it_suppLangTags 784
+#define OBJ_id_it_suppLangTags 1L, 3L, 6L, 1L, 5L, 5L, 7L, 4L, 16L
+
+#define SN_caRepository "caRepository"
+#define LN_caRepository "CA Repository"
+#define NID_caRepository 785
+#define OBJ_caRepository 1L, 3L, 6L, 1L, 5L, 5L, 7L, 48L, 5L
+
+#define SN_id_smime_ct_compressedData "id-smime-ct-compressedData"
+#define NID_id_smime_ct_compressedData 786
+#define OBJ_id_smime_ct_compressedData \
+  1L, 2L, 840L, 113549L, 1L, 9L, 16L, 1L, 9L
+
+#define SN_id_ct_asciiTextWithCRLF "id-ct-asciiTextWithCRLF"
+#define NID_id_ct_asciiTextWithCRLF 787
+#define OBJ_id_ct_asciiTextWithCRLF 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 1L, 27L
+
+#define SN_id_aes128_wrap "id-aes128-wrap"
+#define NID_id_aes128_wrap 788
+#define OBJ_id_aes128_wrap 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 5L
+
+#define SN_id_aes192_wrap "id-aes192-wrap"
+#define NID_id_aes192_wrap 789
+#define OBJ_id_aes192_wrap 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 25L
+
+#define SN_id_aes256_wrap "id-aes256-wrap"
+#define NID_id_aes256_wrap 790
+#define OBJ_id_aes256_wrap 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 45L
+
+#define SN_ecdsa_with_Recommended "ecdsa-with-Recommended"
+#define NID_ecdsa_with_Recommended 791
+#define OBJ_ecdsa_with_Recommended 1L, 2L, 840L, 10045L, 4L, 2L
+
+#define SN_ecdsa_with_Specified "ecdsa-with-Specified"
+#define NID_ecdsa_with_Specified 792
+#define OBJ_ecdsa_with_Specified 1L, 2L, 840L, 10045L, 4L, 3L
+
+#define SN_ecdsa_with_SHA224 "ecdsa-with-SHA224"
+#define NID_ecdsa_with_SHA224 793
+#define OBJ_ecdsa_with_SHA224 1L, 2L, 840L, 10045L, 4L, 3L, 1L
+
+#define SN_ecdsa_with_SHA256 "ecdsa-with-SHA256"
+#define NID_ecdsa_with_SHA256 794
+#define OBJ_ecdsa_with_SHA256 1L, 2L, 840L, 10045L, 4L, 3L, 2L
+
+#define SN_ecdsa_with_SHA384 "ecdsa-with-SHA384"
+#define NID_ecdsa_with_SHA384 795
+#define OBJ_ecdsa_with_SHA384 1L, 2L, 840L, 10045L, 4L, 3L, 3L
+
+#define SN_ecdsa_with_SHA512 "ecdsa-with-SHA512"
+#define NID_ecdsa_with_SHA512 796
+#define OBJ_ecdsa_with_SHA512 1L, 2L, 840L, 10045L, 4L, 3L, 4L
+
+#define LN_hmacWithMD5 "hmacWithMD5"
+#define NID_hmacWithMD5 797
+#define OBJ_hmacWithMD5 1L, 2L, 840L, 113549L, 2L, 6L
+
+#define LN_hmacWithSHA224 "hmacWithSHA224"
+#define NID_hmacWithSHA224 798
+#define OBJ_hmacWithSHA224 1L, 2L, 840L, 113549L, 2L, 8L
+
+#define LN_hmacWithSHA256 "hmacWithSHA256"
+#define NID_hmacWithSHA256 799
+#define OBJ_hmacWithSHA256 1L, 2L, 840L, 113549L, 2L, 9L
+
+#define LN_hmacWithSHA384 "hmacWithSHA384"
+#define NID_hmacWithSHA384 800
+#define OBJ_hmacWithSHA384 1L, 2L, 840L, 113549L, 2L, 10L
+
+#define LN_hmacWithSHA512 "hmacWithSHA512"
+#define NID_hmacWithSHA512 801
+#define OBJ_hmacWithSHA512 1L, 2L, 840L, 113549L, 2L, 11L
+
+#define SN_dsa_with_SHA224 "dsa_with_SHA224"
+#define NID_dsa_with_SHA224 802
+#define OBJ_dsa_with_SHA224 2L, 16L, 840L, 1L, 101L, 3L, 4L, 3L, 1L
+
+#define SN_dsa_with_SHA256 "dsa_with_SHA256"
+#define NID_dsa_with_SHA256 803
+#define OBJ_dsa_with_SHA256 2L, 16L, 840L, 1L, 101L, 3L, 4L, 3L, 2L
+
+#define SN_whirlpool "whirlpool"
+#define NID_whirlpool 804
+#define OBJ_whirlpool 1L, 0L, 10118L, 3L, 0L, 55L
+
+#define SN_cryptopro "cryptopro"
+#define NID_cryptopro 805
+#define OBJ_cryptopro 1L, 2L, 643L, 2L, 2L
+
+#define SN_cryptocom "cryptocom"
+#define NID_cryptocom 806
+#define OBJ_cryptocom 1L, 2L, 643L, 2L, 9L
+
+#define SN_id_GostR3411_94_with_GostR3410_2001 \
+  "id-GostR3411-94-with-GostR3410-2001"
+#define LN_id_GostR3411_94_with_GostR3410_2001 \
+  "GOST R 34.11-94 with GOST R 34.10-2001"
+#define NID_id_GostR3411_94_with_GostR3410_2001 807
+#define OBJ_id_GostR3411_94_with_GostR3410_2001 1L, 2L, 643L, 2L, 2L, 3L
+
+#define SN_id_GostR3411_94_with_GostR3410_94 "id-GostR3411-94-with-GostR3410-94"
+#define LN_id_GostR3411_94_with_GostR3410_94 \
+  "GOST R 34.11-94 with GOST R 34.10-94"
+#define NID_id_GostR3411_94_with_GostR3410_94 808
+#define OBJ_id_GostR3411_94_with_GostR3410_94 1L, 2L, 643L, 2L, 2L, 4L
+
+#define SN_id_GostR3411_94 "md_gost94"
+#define LN_id_GostR3411_94 "GOST R 34.11-94"
+#define NID_id_GostR3411_94 809
+#define OBJ_id_GostR3411_94 1L, 2L, 643L, 2L, 2L, 9L
+
+#define SN_id_HMACGostR3411_94 "id-HMACGostR3411-94"
+#define LN_id_HMACGostR3411_94 "HMAC GOST 34.11-94"
+#define NID_id_HMACGostR3411_94 810
+#define OBJ_id_HMACGostR3411_94 1L, 2L, 643L, 2L, 2L, 10L
+
+#define SN_id_GostR3410_2001 "gost2001"
+#define LN_id_GostR3410_2001 "GOST R 34.10-2001"
+#define NID_id_GostR3410_2001 811
+#define OBJ_id_GostR3410_2001 1L, 2L, 643L, 2L, 2L, 19L
+
+#define SN_id_GostR3410_94 "gost94"
+#define LN_id_GostR3410_94 "GOST R 34.10-94"
+#define NID_id_GostR3410_94 812
+#define OBJ_id_GostR3410_94 1L, 2L, 643L, 2L, 2L, 20L
+
+#define SN_id_Gost28147_89 "gost89"
+#define LN_id_Gost28147_89 "GOST 28147-89"
+#define NID_id_Gost28147_89 813
+#define OBJ_id_Gost28147_89 1L, 2L, 643L, 2L, 2L, 21L
+
+#define SN_gost89_cnt "gost89-cnt"
+#define NID_gost89_cnt 814
+
+#define SN_id_Gost28147_89_MAC "gost-mac"
+#define LN_id_Gost28147_89_MAC "GOST 28147-89 MAC"
+#define NID_id_Gost28147_89_MAC 815
+#define OBJ_id_Gost28147_89_MAC 1L, 2L, 643L, 2L, 2L, 22L
+
+#define SN_id_GostR3411_94_prf "prf-gostr3411-94"
+#define LN_id_GostR3411_94_prf "GOST R 34.11-94 PRF"
+#define NID_id_GostR3411_94_prf 816
+#define OBJ_id_GostR3411_94_prf 1L, 2L, 643L, 2L, 2L, 23L
+
+#define SN_id_GostR3410_2001DH "id-GostR3410-2001DH"
+#define LN_id_GostR3410_2001DH "GOST R 34.10-2001 DH"
+#define NID_id_GostR3410_2001DH 817
+#define OBJ_id_GostR3410_2001DH 1L, 2L, 643L, 2L, 2L, 98L
+
+#define SN_id_GostR3410_94DH "id-GostR3410-94DH"
+#define LN_id_GostR3410_94DH "GOST R 34.10-94 DH"
+#define NID_id_GostR3410_94DH 818
+#define OBJ_id_GostR3410_94DH 1L, 2L, 643L, 2L, 2L, 99L
+
+#define SN_id_Gost28147_89_CryptoPro_KeyMeshing \
+  "id-Gost28147-89-CryptoPro-KeyMeshing"
+#define NID_id_Gost28147_89_CryptoPro_KeyMeshing 819
+#define OBJ_id_Gost28147_89_CryptoPro_KeyMeshing 1L, 2L, 643L, 2L, 2L, 14L, 1L
+
+#define SN_id_Gost28147_89_None_KeyMeshing "id-Gost28147-89-None-KeyMeshing"
+#define NID_id_Gost28147_89_None_KeyMeshing 820
+#define OBJ_id_Gost28147_89_None_KeyMeshing 1L, 2L, 643L, 2L, 2L, 14L, 0L
+
+#define SN_id_GostR3411_94_TestParamSet "id-GostR3411-94-TestParamSet"
+#define NID_id_GostR3411_94_TestParamSet 821
+#define OBJ_id_GostR3411_94_TestParamSet 1L, 2L, 643L, 2L, 2L, 30L, 0L
+
+#define SN_id_GostR3411_94_CryptoProParamSet "id-GostR3411-94-CryptoProParamSet"
+#define NID_id_GostR3411_94_CryptoProParamSet 822
+#define OBJ_id_GostR3411_94_CryptoProParamSet 1L, 2L, 643L, 2L, 2L, 30L, 1L
+
+#define SN_id_Gost28147_89_TestParamSet "id-Gost28147-89-TestParamSet"
+#define NID_id_Gost28147_89_TestParamSet 823
+#define OBJ_id_Gost28147_89_TestParamSet 1L, 2L, 643L, 2L, 2L, 31L, 0L
+
+#define SN_id_Gost28147_89_CryptoPro_A_ParamSet \
+  "id-Gost28147-89-CryptoPro-A-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_A_ParamSet 824
+#define OBJ_id_Gost28147_89_CryptoPro_A_ParamSet 1L, 2L, 643L, 2L, 2L, 31L, 1L
+
+#define SN_id_Gost28147_89_CryptoPro_B_ParamSet \
+  "id-Gost28147-89-CryptoPro-B-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_B_ParamSet 825
+#define OBJ_id_Gost28147_89_CryptoPro_B_ParamSet 1L, 2L, 643L, 2L, 2L, 31L, 2L
+
+#define SN_id_Gost28147_89_CryptoPro_C_ParamSet \
+  "id-Gost28147-89-CryptoPro-C-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_C_ParamSet 826
+#define OBJ_id_Gost28147_89_CryptoPro_C_ParamSet 1L, 2L, 643L, 2L, 2L, 31L, 3L
+
+#define SN_id_Gost28147_89_CryptoPro_D_ParamSet \
+  "id-Gost28147-89-CryptoPro-D-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_D_ParamSet 827
+#define OBJ_id_Gost28147_89_CryptoPro_D_ParamSet 1L, 2L, 643L, 2L, 2L, 31L, 4L
+
+#define SN_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet \
+  "id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet 828
+#define OBJ_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet \
+  1L, 2L, 643L, 2L, 2L, 31L, 5L
+
+#define SN_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet \
+  "id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet 829
+#define OBJ_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet \
+  1L, 2L, 643L, 2L, 2L, 31L, 6L
+
+#define SN_id_Gost28147_89_CryptoPro_RIC_1_ParamSet \
+  "id-Gost28147-89-CryptoPro-RIC-1-ParamSet"
+#define NID_id_Gost28147_89_CryptoPro_RIC_1_ParamSet 830
+#define OBJ_id_Gost28147_89_CryptoPro_RIC_1_ParamSet \
+  1L, 2L, 643L, 2L, 2L, 31L, 7L
+
+#define SN_id_GostR3410_94_TestParamSet "id-GostR3410-94-TestParamSet"
+#define NID_id_GostR3410_94_TestParamSet 831
+#define OBJ_id_GostR3410_94_TestParamSet 1L, 2L, 643L, 2L, 2L, 32L, 0L
+
+#define SN_id_GostR3410_94_CryptoPro_A_ParamSet \
+  "id-GostR3410-94-CryptoPro-A-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_A_ParamSet 832
+#define OBJ_id_GostR3410_94_CryptoPro_A_ParamSet 1L, 2L, 643L, 2L, 2L, 32L, 2L
+
+#define SN_id_GostR3410_94_CryptoPro_B_ParamSet \
+  "id-GostR3410-94-CryptoPro-B-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_B_ParamSet 833
+#define OBJ_id_GostR3410_94_CryptoPro_B_ParamSet 1L, 2L, 643L, 2L, 2L, 32L, 3L
+
+#define SN_id_GostR3410_94_CryptoPro_C_ParamSet \
+  "id-GostR3410-94-CryptoPro-C-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_C_ParamSet 834
+#define OBJ_id_GostR3410_94_CryptoPro_C_ParamSet 1L, 2L, 643L, 2L, 2L, 32L, 4L
+
+#define SN_id_GostR3410_94_CryptoPro_D_ParamSet \
+  "id-GostR3410-94-CryptoPro-D-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_D_ParamSet 835
+#define OBJ_id_GostR3410_94_CryptoPro_D_ParamSet 1L, 2L, 643L, 2L, 2L, 32L, 5L
+
+#define SN_id_GostR3410_94_CryptoPro_XchA_ParamSet \
+  "id-GostR3410-94-CryptoPro-XchA-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_XchA_ParamSet 836
+#define OBJ_id_GostR3410_94_CryptoPro_XchA_ParamSet \
+  1L, 2L, 643L, 2L, 2L, 33L, 1L
+
+#define SN_id_GostR3410_94_CryptoPro_XchB_ParamSet \
+  "id-GostR3410-94-CryptoPro-XchB-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_XchB_ParamSet 837
+#define OBJ_id_GostR3410_94_CryptoPro_XchB_ParamSet \
+  1L, 2L, 643L, 2L, 2L, 33L, 2L
+
+#define SN_id_GostR3410_94_CryptoPro_XchC_ParamSet \
+  "id-GostR3410-94-CryptoPro-XchC-ParamSet"
+#define NID_id_GostR3410_94_CryptoPro_XchC_ParamSet 838
+#define OBJ_id_GostR3410_94_CryptoPro_XchC_ParamSet \
+  1L, 2L, 643L, 2L, 2L, 33L, 3L
+
+#define SN_id_GostR3410_2001_TestParamSet "id-GostR3410-2001-TestParamSet"
+#define NID_id_GostR3410_2001_TestParamSet 839
+#define OBJ_id_GostR3410_2001_TestParamSet 1L, 2L, 643L, 2L, 2L, 35L, 0L
+
+#define SN_id_GostR3410_2001_CryptoPro_A_ParamSet \
+  "id-GostR3410-2001-CryptoPro-A-ParamSet"
+#define NID_id_GostR3410_2001_CryptoPro_A_ParamSet 840
+#define OBJ_id_GostR3410_2001_CryptoPro_A_ParamSet 1L, 2L, 643L, 2L, 2L, 35L, 1L
+
+#define SN_id_GostR3410_2001_CryptoPro_B_ParamSet \
+  "id-GostR3410-2001-CryptoPro-B-ParamSet"
+#define NID_id_GostR3410_2001_CryptoPro_B_ParamSet 841
+#define OBJ_id_GostR3410_2001_CryptoPro_B_ParamSet 1L, 2L, 643L, 2L, 2L, 35L, 2L
+
+#define SN_id_GostR3410_2001_CryptoPro_C_ParamSet \
+  "id-GostR3410-2001-CryptoPro-C-ParamSet"
+#define NID_id_GostR3410_2001_CryptoPro_C_ParamSet 842
+#define OBJ_id_GostR3410_2001_CryptoPro_C_ParamSet 1L, 2L, 643L, 2L, 2L, 35L, 3L
+
+#define SN_id_GostR3410_2001_CryptoPro_XchA_ParamSet \
+  "id-GostR3410-2001-CryptoPro-XchA-ParamSet"
+#define NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet 843
+#define OBJ_id_GostR3410_2001_CryptoPro_XchA_ParamSet \
+  1L, 2L, 643L, 2L, 2L, 36L, 0L
+
+#define SN_id_GostR3410_2001_CryptoPro_XchB_ParamSet \
+  "id-GostR3410-2001-CryptoPro-XchB-ParamSet"
+#define NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet 844
+#define OBJ_id_GostR3410_2001_CryptoPro_XchB_ParamSet \
+  1L, 2L, 643L, 2L, 2L, 36L, 1L
+
+#define SN_id_GostR3410_94_a "id-GostR3410-94-a"
+#define NID_id_GostR3410_94_a 845
+#define OBJ_id_GostR3410_94_a 1L, 2L, 643L, 2L, 2L, 20L, 1L
+
+#define SN_id_GostR3410_94_aBis "id-GostR3410-94-aBis"
+#define NID_id_GostR3410_94_aBis 846
+#define OBJ_id_GostR3410_94_aBis 1L, 2L, 643L, 2L, 2L, 20L, 2L
+
+#define SN_id_GostR3410_94_b "id-GostR3410-94-b"
+#define NID_id_GostR3410_94_b 847
+#define OBJ_id_GostR3410_94_b 1L, 2L, 643L, 2L, 2L, 20L, 3L
+
+#define SN_id_GostR3410_94_bBis "id-GostR3410-94-bBis"
+#define NID_id_GostR3410_94_bBis 848
+#define OBJ_id_GostR3410_94_bBis 1L, 2L, 643L, 2L, 2L, 20L, 4L
+
+#define SN_id_Gost28147_89_cc "id-Gost28147-89-cc"
+#define LN_id_Gost28147_89_cc "GOST 28147-89 Cryptocom ParamSet"
+#define NID_id_Gost28147_89_cc 849
+#define OBJ_id_Gost28147_89_cc 1L, 2L, 643L, 2L, 9L, 1L, 6L, 1L
+
+#define SN_id_GostR3410_94_cc "gost94cc"
+#define LN_id_GostR3410_94_cc "GOST 34.10-94 Cryptocom"
+#define NID_id_GostR3410_94_cc 850
+#define OBJ_id_GostR3410_94_cc 1L, 2L, 643L, 2L, 9L, 1L, 5L, 3L
+
+#define SN_id_GostR3410_2001_cc "gost2001cc"
+#define LN_id_GostR3410_2001_cc "GOST 34.10-2001 Cryptocom"
+#define NID_id_GostR3410_2001_cc 851
+#define OBJ_id_GostR3410_2001_cc 1L, 2L, 643L, 2L, 9L, 1L, 5L, 4L
+
+#define SN_id_GostR3411_94_with_GostR3410_94_cc \
+  "id-GostR3411-94-with-GostR3410-94-cc"
+#define LN_id_GostR3411_94_with_GostR3410_94_cc \
+  "GOST R 34.11-94 with GOST R 34.10-94 Cryptocom"
+#define NID_id_GostR3411_94_with_GostR3410_94_cc 852
+#define OBJ_id_GostR3411_94_with_GostR3410_94_cc \
+  1L, 2L, 643L, 2L, 9L, 1L, 3L, 3L
+
+#define SN_id_GostR3411_94_with_GostR3410_2001_cc \
+  "id-GostR3411-94-with-GostR3410-2001-cc"
+#define LN_id_GostR3411_94_with_GostR3410_2001_cc \
+  "GOST R 34.11-94 with GOST R 34.10-2001 Cryptocom"
+#define NID_id_GostR3411_94_with_GostR3410_2001_cc 853
+#define OBJ_id_GostR3411_94_with_GostR3410_2001_cc \
+  1L, 2L, 643L, 2L, 9L, 1L, 3L, 4L
+
+#define SN_id_GostR3410_2001_ParamSet_cc "id-GostR3410-2001-ParamSet-cc"
+#define LN_id_GostR3410_2001_ParamSet_cc \
+  "GOST R 3410-2001 Parameter Set Cryptocom"
+#define NID_id_GostR3410_2001_ParamSet_cc 854
+#define OBJ_id_GostR3410_2001_ParamSet_cc 1L, 2L, 643L, 2L, 9L, 1L, 8L, 1L
+
+#define SN_hmac "HMAC"
+#define LN_hmac "hmac"
+#define NID_hmac 855
+
+#define SN_LocalKeySet "LocalKeySet"
+#define LN_LocalKeySet "Microsoft Local Key set"
+#define NID_LocalKeySet 856
+#define OBJ_LocalKeySet 1L, 3L, 6L, 1L, 4L, 1L, 311L, 17L, 2L
+
+#define SN_freshest_crl "freshestCRL"
+#define LN_freshest_crl "X509v3 Freshest CRL"
+#define NID_freshest_crl 857
+#define OBJ_freshest_crl 2L, 5L, 29L, 46L
+
+#define SN_id_on_permanentIdentifier "id-on-permanentIdentifier"
+#define LN_id_on_permanentIdentifier "Permanent Identifier"
+#define NID_id_on_permanentIdentifier 858
+#define OBJ_id_on_permanentIdentifier 1L, 3L, 6L, 1L, 5L, 5L, 7L, 8L, 3L
+
+#define LN_searchGuide "searchGuide"
+#define NID_searchGuide 859
+#define OBJ_searchGuide 2L, 5L, 4L, 14L
+
+#define LN_businessCategory "businessCategory"
+#define NID_businessCategory 860
+#define OBJ_businessCategory 2L, 5L, 4L, 15L
+
+#define LN_postalAddress "postalAddress"
+#define NID_postalAddress 861
+#define OBJ_postalAddress 2L, 5L, 4L, 16L
+
+#define LN_postOfficeBox "postOfficeBox"
+#define NID_postOfficeBox 862
+#define OBJ_postOfficeBox 2L, 5L, 4L, 18L
+
+#define LN_physicalDeliveryOfficeName "physicalDeliveryOfficeName"
+#define NID_physicalDeliveryOfficeName 863
+#define OBJ_physicalDeliveryOfficeName 2L, 5L, 4L, 19L
+
+#define LN_telephoneNumber "telephoneNumber"
+#define NID_telephoneNumber 864
+#define OBJ_telephoneNumber 2L, 5L, 4L, 20L
+
+#define LN_telexNumber "telexNumber"
+#define NID_telexNumber 865
+#define OBJ_telexNumber 2L, 5L, 4L, 21L
+
+#define LN_teletexTerminalIdentifier "teletexTerminalIdentifier"
+#define NID_teletexTerminalIdentifier 866
+#define OBJ_teletexTerminalIdentifier 2L, 5L, 4L, 22L
+
+#define LN_facsimileTelephoneNumber "facsimileTelephoneNumber"
+#define NID_facsimileTelephoneNumber 867
+#define OBJ_facsimileTelephoneNumber 2L, 5L, 4L, 23L
+
+#define LN_x121Address "x121Address"
+#define NID_x121Address 868
+#define OBJ_x121Address 2L, 5L, 4L, 24L
+
+#define LN_internationaliSDNNumber "internationaliSDNNumber"
+#define NID_internationaliSDNNumber 869
+#define OBJ_internationaliSDNNumber 2L, 5L, 4L, 25L
+
+#define LN_registeredAddress "registeredAddress"
+#define NID_registeredAddress 870
+#define OBJ_registeredAddress 2L, 5L, 4L, 26L
+
+#define LN_destinationIndicator "destinationIndicator"
+#define NID_destinationIndicator 871
+#define OBJ_destinationIndicator 2L, 5L, 4L, 27L
+
+#define LN_preferredDeliveryMethod "preferredDeliveryMethod"
+#define NID_preferredDeliveryMethod 872
+#define OBJ_preferredDeliveryMethod 2L, 5L, 4L, 28L
+
+#define LN_presentationAddress "presentationAddress"
+#define NID_presentationAddress 873
+#define OBJ_presentationAddress 2L, 5L, 4L, 29L
+
+#define LN_supportedApplicationContext "supportedApplicationContext"
+#define NID_supportedApplicationContext 874
+#define OBJ_supportedApplicationContext 2L, 5L, 4L, 30L
+
+#define SN_member "member"
+#define NID_member 875
+#define OBJ_member 2L, 5L, 4L, 31L
+
+#define SN_owner "owner"
+#define NID_owner 876
+#define OBJ_owner 2L, 5L, 4L, 32L
+
+#define LN_roleOccupant "roleOccupant"
+#define NID_roleOccupant 877
+#define OBJ_roleOccupant 2L, 5L, 4L, 33L
+
+#define SN_seeAlso "seeAlso"
+#define NID_seeAlso 878
+#define OBJ_seeAlso 2L, 5L, 4L, 34L
+
+#define LN_userPassword "userPassword"
+#define NID_userPassword 879
+#define OBJ_userPassword 2L, 5L, 4L, 35L
+
+#define LN_userCertificate "userCertificate"
+#define NID_userCertificate 880
+#define OBJ_userCertificate 2L, 5L, 4L, 36L
+
+#define LN_cACertificate "cACertificate"
+#define NID_cACertificate 881
+#define OBJ_cACertificate 2L, 5L, 4L, 37L
+
+#define LN_authorityRevocationList "authorityRevocationList"
+#define NID_authorityRevocationList 882
+#define OBJ_authorityRevocationList 2L, 5L, 4L, 38L
+
+#define LN_certificateRevocationList "certificateRevocationList"
+#define NID_certificateRevocationList 883
+#define OBJ_certificateRevocationList 2L, 5L, 4L, 39L
+
+#define LN_crossCertificatePair "crossCertificatePair"
+#define NID_crossCertificatePair 884
+#define OBJ_crossCertificatePair 2L, 5L, 4L, 40L
+
+#define LN_enhancedSearchGuide "enhancedSearchGuide"
+#define NID_enhancedSearchGuide 885
+#define OBJ_enhancedSearchGuide 2L, 5L, 4L, 47L
+
+#define LN_protocolInformation "protocolInformation"
+#define NID_protocolInformation 886
+#define OBJ_protocolInformation 2L, 5L, 4L, 48L
+
+#define LN_distinguishedName "distinguishedName"
+#define NID_distinguishedName 887
+#define OBJ_distinguishedName 2L, 5L, 4L, 49L
+
+#define LN_uniqueMember "uniqueMember"
+#define NID_uniqueMember 888
+#define OBJ_uniqueMember 2L, 5L, 4L, 50L
+
+#define LN_houseIdentifier "houseIdentifier"
+#define NID_houseIdentifier 889
+#define OBJ_houseIdentifier 2L, 5L, 4L, 51L
+
+#define LN_supportedAlgorithms "supportedAlgorithms"
+#define NID_supportedAlgorithms 890
+#define OBJ_supportedAlgorithms 2L, 5L, 4L, 52L
+
+#define LN_deltaRevocationList "deltaRevocationList"
+#define NID_deltaRevocationList 891
+#define OBJ_deltaRevocationList 2L, 5L, 4L, 53L
+
+#define SN_dmdName "dmdName"
+#define NID_dmdName 892
+#define OBJ_dmdName 2L, 5L, 4L, 54L
+
+#define SN_id_alg_PWRI_KEK "id-alg-PWRI-KEK"
+#define NID_id_alg_PWRI_KEK 893
+#define OBJ_id_alg_PWRI_KEK 1L, 2L, 840L, 113549L, 1L, 9L, 16L, 3L, 9L
+
+#define SN_cmac "CMAC"
+#define LN_cmac "cmac"
+#define NID_cmac 894
+
+#define SN_aes_128_gcm "id-aes128-GCM"
+#define LN_aes_128_gcm "aes-128-gcm"
+#define NID_aes_128_gcm 895
+#define OBJ_aes_128_gcm 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 6L
+
+#define SN_aes_128_ccm "id-aes128-CCM"
+#define LN_aes_128_ccm "aes-128-ccm"
+#define NID_aes_128_ccm 896
+#define OBJ_aes_128_ccm 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 7L
+
+#define SN_id_aes128_wrap_pad "id-aes128-wrap-pad"
+#define NID_id_aes128_wrap_pad 897
+#define OBJ_id_aes128_wrap_pad 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 8L
+
+#define SN_aes_192_gcm "id-aes192-GCM"
+#define LN_aes_192_gcm "aes-192-gcm"
+#define NID_aes_192_gcm 898
+#define OBJ_aes_192_gcm 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 26L
+
+#define SN_aes_192_ccm "id-aes192-CCM"
+#define LN_aes_192_ccm "aes-192-ccm"
+#define NID_aes_192_ccm 899
+#define OBJ_aes_192_ccm 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 27L
+
+#define SN_id_aes192_wrap_pad "id-aes192-wrap-pad"
+#define NID_id_aes192_wrap_pad 900
+#define OBJ_id_aes192_wrap_pad 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 28L
+
+#define SN_aes_256_gcm "id-aes256-GCM"
+#define LN_aes_256_gcm "aes-256-gcm"
+#define NID_aes_256_gcm 901
+#define OBJ_aes_256_gcm 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 46L
+
+#define SN_aes_256_ccm "id-aes256-CCM"
+#define LN_aes_256_ccm "aes-256-ccm"
+#define NID_aes_256_ccm 902
+#define OBJ_aes_256_ccm 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 47L
+
+#define SN_id_aes256_wrap_pad "id-aes256-wrap-pad"
+#define NID_id_aes256_wrap_pad 903
+#define OBJ_id_aes256_wrap_pad 2L, 16L, 840L, 1L, 101L, 3L, 4L, 1L, 48L
+
+#define SN_aes_128_ctr "AES-128-CTR"
+#define LN_aes_128_ctr "aes-128-ctr"
+#define NID_aes_128_ctr 904
+
+#define SN_aes_192_ctr "AES-192-CTR"
+#define LN_aes_192_ctr "aes-192-ctr"
+#define NID_aes_192_ctr 905
+
+#define SN_aes_256_ctr "AES-256-CTR"
+#define LN_aes_256_ctr "aes-256-ctr"
+#define NID_aes_256_ctr 906
+
+#define SN_id_camellia128_wrap "id-camellia128-wrap"
+#define NID_id_camellia128_wrap 907
+#define OBJ_id_camellia128_wrap 1L, 2L, 392L, 200011L, 61L, 1L, 1L, 3L, 2L
+
+#define SN_id_camellia192_wrap "id-camellia192-wrap"
+#define NID_id_camellia192_wrap 908
+#define OBJ_id_camellia192_wrap 1L, 2L, 392L, 200011L, 61L, 1L, 1L, 3L, 3L
+
+#define SN_id_camellia256_wrap "id-camellia256-wrap"
+#define NID_id_camellia256_wrap 909
+#define OBJ_id_camellia256_wrap 1L, 2L, 392L, 200011L, 61L, 1L, 1L, 3L, 4L
+
+#define SN_anyExtendedKeyUsage "anyExtendedKeyUsage"
+#define LN_anyExtendedKeyUsage "Any Extended Key Usage"
+#define NID_anyExtendedKeyUsage 910
+#define OBJ_anyExtendedKeyUsage 2L, 5L, 29L, 37L, 0L
+
+#define SN_mgf1 "MGF1"
+#define LN_mgf1 "mgf1"
+#define NID_mgf1 911
+#define OBJ_mgf1 1L, 2L, 840L, 113549L, 1L, 1L, 8L
+
+#define SN_rsassaPss "RSASSA-PSS"
+#define LN_rsassaPss "rsassaPss"
+#define NID_rsassaPss 912
+#define OBJ_rsassaPss 1L, 2L, 840L, 113549L, 1L, 1L, 10L
+
+#define SN_aes_128_xts "AES-128-XTS"
+#define LN_aes_128_xts "aes-128-xts"
+#define NID_aes_128_xts 913
+
+#define SN_aes_256_xts "AES-256-XTS"
+#define LN_aes_256_xts "aes-256-xts"
+#define NID_aes_256_xts 914
+
+#define SN_rc4_hmac_md5 "RC4-HMAC-MD5"
+#define LN_rc4_hmac_md5 "rc4-hmac-md5"
+#define NID_rc4_hmac_md5 915
+
+#define SN_aes_128_cbc_hmac_sha1 "AES-128-CBC-HMAC-SHA1"
+#define LN_aes_128_cbc_hmac_sha1 "aes-128-cbc-hmac-sha1"
+#define NID_aes_128_cbc_hmac_sha1 916
+
+#define SN_aes_192_cbc_hmac_sha1 "AES-192-CBC-HMAC-SHA1"
+#define LN_aes_192_cbc_hmac_sha1 "aes-192-cbc-hmac-sha1"
+#define NID_aes_192_cbc_hmac_sha1 917
+
+#define SN_aes_256_cbc_hmac_sha1 "AES-256-CBC-HMAC-SHA1"
+#define LN_aes_256_cbc_hmac_sha1 "aes-256-cbc-hmac-sha1"
+#define NID_aes_256_cbc_hmac_sha1 918
+
+#define SN_rsaesOaep "RSAES-OAEP"
+#define LN_rsaesOaep "rsaesOaep"
+#define NID_rsaesOaep 919
+#define OBJ_rsaesOaep 1L, 2L, 840L, 113549L, 1L, 1L, 7L
+
+#define SN_dhpublicnumber "dhpublicnumber"
+#define LN_dhpublicnumber "X9.42 DH"
+#define NID_dhpublicnumber 920
+#define OBJ_dhpublicnumber 1L, 2L, 840L, 10046L, 2L, 1L
+
+#define SN_brainpoolP160r1 "brainpoolP160r1"
+#define NID_brainpoolP160r1 921
+#define OBJ_brainpoolP160r1 1L, 3L, 36L, 3L, 3L, 2L, 8L, 1L, 1L, 1L
+
+#define SN_brainpoolP160t1 "brainpoolP160t1"
+#define NID_brainpoolP160t1 922
+#define OBJ_brainpoolP160t1 1L, 3L, 36L, 3L, 3L, 2L, 8L, 1L, 1L, 2L
+
+#define SN_brainpoolP192r1 "brainpoolP192r1"
+#define NID_brainpoolP192r1 923
+#define OBJ_brainpoolP192r1 1L, 3L, 36L, 3L, 3L, 2L, 8L, 1L, 1L, 3L
+
+#define SN_brainpoolP192t1 "brainpoolP192t1"
+#define NID_brainpoolP192t1 924
+#define OBJ_brainpoolP192t1 1L, 3L, 36L, 3L, 3L, 2L, 8L, 1L, 1L, 4L
+
+#define SN_brainpoolP224r1 "brainpoolP224r1"
+#define NID_brainpoolP224r1 925
+#define OBJ_brainpoolP224r1 1L, 3L, 36L, 3L, 3L, 2L, 8L, 1L, 1L, 5L
+
+#define SN_brainpoolP224t1 "brainpoolP224t1"
+#define NID_brainpoolP224t1 926
+#define OBJ_brainpoolP224t1 1L, 3L, 36L, 3L, 3L, 2L, 8L, 1L, 1L, 6L
+
+#define SN_brainpoolP256r1 "brainpoolP256r1"
+#define NID_brainpoolP256r1 927
+#define OBJ_brainpoolP256r1 1L, 3L, 36L, 3L, 3L, 2L, 8L, 1L, 1L, 7L
+
+#define SN_brainpoolP256t1 "brainpoolP256t1"
+#define NID_brainpoolP256t1 928
+#define OBJ_brainpoolP256t1 1L, 3L, 36L, 3L, 3L, 2L, 8L, 1L, 1L, 8L
+
+#define SN_brainpoolP320r1 "brainpoolP320r1"
+#define NID_brainpoolP320r1 929
+#define OBJ_brainpoolP320r1 1L, 3L, 36L, 3L, 3L, 2L, 8L, 1L, 1L, 9L
+
+#define SN_brainpoolP320t1 "brainpoolP320t1"
+#define NID_brainpoolP320t1 930
+#define OBJ_brainpoolP320t1 1L, 3L, 36L, 3L, 3L, 2L, 8L, 1L, 1L, 10L
+
+#define SN_brainpoolP384r1 "brainpoolP384r1"
+#define NID_brainpoolP384r1 931
+#define OBJ_brainpoolP384r1 1L, 3L, 36L, 3L, 3L, 2L, 8L, 1L, 1L, 11L
+
+#define SN_brainpoolP384t1 "brainpoolP384t1"
+#define NID_brainpoolP384t1 932
+#define OBJ_brainpoolP384t1 1L, 3L, 36L, 3L, 3L, 2L, 8L, 1L, 1L, 12L
+
+#define SN_brainpoolP512r1 "brainpoolP512r1"
+#define NID_brainpoolP512r1 933
+#define OBJ_brainpoolP512r1 1L, 3L, 36L, 3L, 3L, 2L, 8L, 1L, 1L, 13L
+
+#define SN_brainpoolP512t1 "brainpoolP512t1"
+#define NID_brainpoolP512t1 934
+#define OBJ_brainpoolP512t1 1L, 3L, 36L, 3L, 3L, 2L, 8L, 1L, 1L, 14L
+
+#define SN_pSpecified "PSPECIFIED"
+#define LN_pSpecified "pSpecified"
+#define NID_pSpecified 935
+#define OBJ_pSpecified 1L, 2L, 840L, 113549L, 1L, 1L, 9L
+
+#define SN_dhSinglePass_stdDH_sha1kdf_scheme "dhSinglePass-stdDH-sha1kdf-scheme"
+#define NID_dhSinglePass_stdDH_sha1kdf_scheme 936
+#define OBJ_dhSinglePass_stdDH_sha1kdf_scheme \
+  1L, 3L, 133L, 16L, 840L, 63L, 0L, 2L
+
+#define SN_dhSinglePass_stdDH_sha224kdf_scheme \
+  "dhSinglePass-stdDH-sha224kdf-scheme"
+#define NID_dhSinglePass_stdDH_sha224kdf_scheme 937
+#define OBJ_dhSinglePass_stdDH_sha224kdf_scheme 1L, 3L, 132L, 1L, 11L, 0L
+
+#define SN_dhSinglePass_stdDH_sha256kdf_scheme \
+  "dhSinglePass-stdDH-sha256kdf-scheme"
+#define NID_dhSinglePass_stdDH_sha256kdf_scheme 938
+#define OBJ_dhSinglePass_stdDH_sha256kdf_scheme 1L, 3L, 132L, 1L, 11L, 1L
+
+#define SN_dhSinglePass_stdDH_sha384kdf_scheme \
+  "dhSinglePass-stdDH-sha384kdf-scheme"
+#define NID_dhSinglePass_stdDH_sha384kdf_scheme 939
+#define OBJ_dhSinglePass_stdDH_sha384kdf_scheme 1L, 3L, 132L, 1L, 11L, 2L
+
+#define SN_dhSinglePass_stdDH_sha512kdf_scheme \
+  "dhSinglePass-stdDH-sha512kdf-scheme"
+#define NID_dhSinglePass_stdDH_sha512kdf_scheme 940
+#define OBJ_dhSinglePass_stdDH_sha512kdf_scheme 1L, 3L, 132L, 1L, 11L, 3L
+
+#define SN_dhSinglePass_cofactorDH_sha1kdf_scheme \
+  "dhSinglePass-cofactorDH-sha1kdf-scheme"
+#define NID_dhSinglePass_cofactorDH_sha1kdf_scheme 941
+#define OBJ_dhSinglePass_cofactorDH_sha1kdf_scheme \
+  1L, 3L, 133L, 16L, 840L, 63L, 0L, 3L
+
+#define SN_dhSinglePass_cofactorDH_sha224kdf_scheme \
+  "dhSinglePass-cofactorDH-sha224kdf-scheme"
+#define NID_dhSinglePass_cofactorDH_sha224kdf_scheme 942
+#define OBJ_dhSinglePass_cofactorDH_sha224kdf_scheme 1L, 3L, 132L, 1L, 14L, 0L
+
+#define SN_dhSinglePass_cofactorDH_sha256kdf_scheme \
+  "dhSinglePass-cofactorDH-sha256kdf-scheme"
+#define NID_dhSinglePass_cofactorDH_sha256kdf_scheme 943
+#define OBJ_dhSinglePass_cofactorDH_sha256kdf_scheme 1L, 3L, 132L, 1L, 14L, 1L
+
+#define SN_dhSinglePass_cofactorDH_sha384kdf_scheme \
+  "dhSinglePass-cofactorDH-sha384kdf-scheme"
+#define NID_dhSinglePass_cofactorDH_sha384kdf_scheme 944
+#define OBJ_dhSinglePass_cofactorDH_sha384kdf_scheme 1L, 3L, 132L, 1L, 14L, 2L
+
+#define SN_dhSinglePass_cofactorDH_sha512kdf_scheme \
+  "dhSinglePass-cofactorDH-sha512kdf-scheme"
+#define NID_dhSinglePass_cofactorDH_sha512kdf_scheme 945
+#define OBJ_dhSinglePass_cofactorDH_sha512kdf_scheme 1L, 3L, 132L, 1L, 14L, 3L
+
+#define SN_dh_std_kdf "dh-std-kdf"
+#define NID_dh_std_kdf 946
+
+#define SN_dh_cofactor_kdf "dh-cofactor-kdf"
+#define NID_dh_cofactor_kdf 947
+
+#define SN_X25519 "X25519"
+#define NID_X25519 948
+
+#if defined(__cplusplus)
+} /* extern C */
+#endif
+
+#endif /* OPENSSL_HEADER_NID_H */
diff --git a/src/include/openssl/obj.h b/src/include/openssl/obj.h
index 32a4894..63cf866 100644
--- a/src/include/openssl/obj.h
+++ b/src/include/openssl/obj.h
@@ -60,7 +60,7 @@
 #include <openssl/base.h>
 
 #include <openssl/bytestring.h>
-#include <openssl/obj_mac.h>
+#include <openssl/nid.h>
 
 #if defined(__cplusplus)
 extern "C" {
@@ -135,7 +135,7 @@
 
 /* Dealing with textual representations of object identifiers. */
 
-/* OBJ_txt2obj returns an ASN1_OBJECT for the textual respresentation in |s|.
+/* OBJ_txt2obj returns an ASN1_OBJECT for the textual representation in |s|.
  * If |dont_search_names| is zero, then |s| will be matched against the long
  * and short names of a known objects to find a match. Otherwise |s| must
  * contain an ASCII string with a dotted sequence of numbers. The resulting
@@ -144,7 +144,7 @@
 OPENSSL_EXPORT ASN1_OBJECT *OBJ_txt2obj(const char *s, int dont_search_names);
 
 /* OBJ_obj2txt converts |obj| to a textual representation. If
- * |dont_return_name| is zero then |obj| will be matched against known objects
+ * |always_return_oid| is zero then |obj| will be matched against known objects
  * and the long (preferably) or short name will be used if found. Otherwise
  * |obj| will be converted into a dotted sequence of integers. If |out| is not
  * NULL, then at most |out_len| bytes of the textual form will be written
@@ -152,7 +152,7 @@
  * always be NUL terminated. It returns the number of characters that could
  * have been written, not including the final NUL, or -1 on error. */
 OPENSSL_EXPORT int OBJ_obj2txt(char *out, int out_len, const ASN1_OBJECT *obj,
-                               int dont_return_name);
+                               int always_return_oid);
 
 
 /* Adding objects at runtime. */
@@ -189,6 +189,34 @@
                                           int pkey_nid);
 
 
+/* Deprecated functions. */
+
+typedef struct obj_name_st {
+  int type;
+  int alias;
+  const char *name;
+  const char *data;
+} OBJ_NAME;
+
+#define OBJ_NAME_TYPE_MD_METH 1
+#define OBJ_NAME_TYPE_CIPHER_METH 2
+
+/* OBJ_NAME_do_all_sorted calls |callback| zero or more times, each time with
+ * the name of a different primitive. If |type| is |OBJ_NAME_TYPE_MD_METH| then
+ * the primitives will be hash functions, alternatively if |type| is
+ * |OBJ_NAME_TYPE_CIPHER_METH| then the primitives will be ciphers or cipher
+ * modes.
+ *
+ * This function is ill-specified and should never be used. */
+OPENSSL_EXPORT void OBJ_NAME_do_all_sorted(
+    int type, void (*callback)(const OBJ_NAME *, void *arg), void *arg);
+
+/* OBJ_NAME_do_all calls |OBJ_NAME_do_all_sorted|. */
+OPENSSL_EXPORT void OBJ_NAME_do_all(int type, void (*callback)(const OBJ_NAME *,
+                                                               void *arg),
+                                    void *arg);
+
+
 #if defined(__cplusplus)
 }  /* extern C */
 #endif
diff --git a/src/include/openssl/obj_mac.h b/src/include/openssl/obj_mac.h
index b636adc..e7ccadc 100644
--- a/src/include/openssl/obj_mac.h
+++ b/src/include/openssl/obj_mac.h
@@ -1,4144 +1,18 @@
-/* THIS FILE IS GENERATED FROM objects.txt by objects.pl via the
- * following command:
- * perl objects.pl objects.txt obj_mac.num ../../include/openssl/obj_mac.h */
-
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
+/* Copyright (c) 2016, Google Inc.
  *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- * 
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to.  The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- * 
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- * 
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *    "This product includes cryptographic software written by
- *     Eric Young (eay@cryptsoft.com)"
- *    The word 'cryptographic' can be left out if the rouines from the library
- *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from 
- *    the apps directory (application code) you must include an acknowledgement:
- *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- * 
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * 
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed.  i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- */
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
 
-#define SN_undef			"UNDEF"
-#define LN_undef			"undefined"
-#define NID_undef			0
-#define OBJ_undef			0L
+/* This header is provided in order to make compiling against code that expects
+   OpenSSL easier. */
 
-#define SN_itu_t		"ITU-T"
-#define LN_itu_t		"itu-t"
-#define NID_itu_t		645
-#define OBJ_itu_t		0L
-
-#define NID_ccitt		404
-#define OBJ_ccitt		OBJ_itu_t
-
-#define SN_iso		"ISO"
-#define LN_iso		"iso"
-#define NID_iso		181
-#define OBJ_iso		1L
-
-#define SN_joint_iso_itu_t		"JOINT-ISO-ITU-T"
-#define LN_joint_iso_itu_t		"joint-iso-itu-t"
-#define NID_joint_iso_itu_t		646
-#define OBJ_joint_iso_itu_t		2L
-
-#define NID_joint_iso_ccitt		393
-#define OBJ_joint_iso_ccitt		OBJ_joint_iso_itu_t
-
-#define SN_member_body		"member-body"
-#define LN_member_body		"ISO Member Body"
-#define NID_member_body		182
-#define OBJ_member_body		OBJ_iso,2L
-
-#define SN_identified_organization		"identified-organization"
-#define NID_identified_organization		676
-#define OBJ_identified_organization		OBJ_iso,3L
-
-#define SN_hmac_md5		"HMAC-MD5"
-#define LN_hmac_md5		"hmac-md5"
-#define NID_hmac_md5		780
-#define OBJ_hmac_md5		OBJ_identified_organization,6L,1L,5L,5L,8L,1L,1L
-
-#define SN_hmac_sha1		"HMAC-SHA1"
-#define LN_hmac_sha1		"hmac-sha1"
-#define NID_hmac_sha1		781
-#define OBJ_hmac_sha1		OBJ_identified_organization,6L,1L,5L,5L,8L,1L,2L
-
-#define SN_certicom_arc		"certicom-arc"
-#define NID_certicom_arc		677
-#define OBJ_certicom_arc		OBJ_identified_organization,132L
-
-#define SN_international_organizations		"international-organizations"
-#define LN_international_organizations		"International Organizations"
-#define NID_international_organizations		647
-#define OBJ_international_organizations		OBJ_joint_iso_itu_t,23L
-
-#define SN_wap		"wap"
-#define NID_wap		678
-#define OBJ_wap		OBJ_international_organizations,43L
-
-#define SN_wap_wsg		"wap-wsg"
-#define NID_wap_wsg		679
-#define OBJ_wap_wsg		OBJ_wap,1L
-
-#define SN_selected_attribute_types		"selected-attribute-types"
-#define LN_selected_attribute_types		"Selected Attribute Types"
-#define NID_selected_attribute_types		394
-#define OBJ_selected_attribute_types		OBJ_joint_iso_itu_t,5L,1L,5L
-
-#define SN_clearance		"clearance"
-#define NID_clearance		395
-#define OBJ_clearance		OBJ_selected_attribute_types,55L
-
-#define SN_ISO_US		"ISO-US"
-#define LN_ISO_US		"ISO US Member Body"
-#define NID_ISO_US		183
-#define OBJ_ISO_US		OBJ_member_body,840L
-
-#define SN_X9_57		"X9-57"
-#define LN_X9_57		"X9.57"
-#define NID_X9_57		184
-#define OBJ_X9_57		OBJ_ISO_US,10040L
-
-#define SN_X9cm		"X9cm"
-#define LN_X9cm		"X9.57 CM ?"
-#define NID_X9cm		185
-#define OBJ_X9cm		OBJ_X9_57,4L
-
-#define SN_dsa		"DSA"
-#define LN_dsa		"dsaEncryption"
-#define NID_dsa		116
-#define OBJ_dsa		OBJ_X9cm,1L
-
-#define SN_dsaWithSHA1		"DSA-SHA1"
-#define LN_dsaWithSHA1		"dsaWithSHA1"
-#define NID_dsaWithSHA1		113
-#define OBJ_dsaWithSHA1		OBJ_X9cm,3L
-
-#define SN_ansi_X9_62		"ansi-X9-62"
-#define LN_ansi_X9_62		"ANSI X9.62"
-#define NID_ansi_X9_62		405
-#define OBJ_ansi_X9_62		OBJ_ISO_US,10045L
-
-#define OBJ_X9_62_id_fieldType		OBJ_ansi_X9_62,1L
-
-#define SN_X9_62_prime_field		"prime-field"
-#define NID_X9_62_prime_field		406
-#define OBJ_X9_62_prime_field		OBJ_X9_62_id_fieldType,1L
-
-#define SN_X9_62_characteristic_two_field		"characteristic-two-field"
-#define NID_X9_62_characteristic_two_field		407
-#define OBJ_X9_62_characteristic_two_field		OBJ_X9_62_id_fieldType,2L
-
-#define SN_X9_62_id_characteristic_two_basis		"id-characteristic-two-basis"
-#define NID_X9_62_id_characteristic_two_basis		680
-#define OBJ_X9_62_id_characteristic_two_basis		OBJ_X9_62_characteristic_two_field,3L
-
-#define SN_X9_62_onBasis		"onBasis"
-#define NID_X9_62_onBasis		681
-#define OBJ_X9_62_onBasis		OBJ_X9_62_id_characteristic_two_basis,1L
-
-#define SN_X9_62_tpBasis		"tpBasis"
-#define NID_X9_62_tpBasis		682
-#define OBJ_X9_62_tpBasis		OBJ_X9_62_id_characteristic_two_basis,2L
-
-#define SN_X9_62_ppBasis		"ppBasis"
-#define NID_X9_62_ppBasis		683
-#define OBJ_X9_62_ppBasis		OBJ_X9_62_id_characteristic_two_basis,3L
-
-#define OBJ_X9_62_id_publicKeyType		OBJ_ansi_X9_62,2L
-
-#define SN_X9_62_id_ecPublicKey		"id-ecPublicKey"
-#define NID_X9_62_id_ecPublicKey		408
-#define OBJ_X9_62_id_ecPublicKey		OBJ_X9_62_id_publicKeyType,1L
-
-#define OBJ_X9_62_ellipticCurve		OBJ_ansi_X9_62,3L
-
-#define OBJ_X9_62_c_TwoCurve		OBJ_X9_62_ellipticCurve,0L
-
-#define SN_X9_62_c2pnb163v1		"c2pnb163v1"
-#define NID_X9_62_c2pnb163v1		684
-#define OBJ_X9_62_c2pnb163v1		OBJ_X9_62_c_TwoCurve,1L
-
-#define SN_X9_62_c2pnb163v2		"c2pnb163v2"
-#define NID_X9_62_c2pnb163v2		685
-#define OBJ_X9_62_c2pnb163v2		OBJ_X9_62_c_TwoCurve,2L
-
-#define SN_X9_62_c2pnb163v3		"c2pnb163v3"
-#define NID_X9_62_c2pnb163v3		686
-#define OBJ_X9_62_c2pnb163v3		OBJ_X9_62_c_TwoCurve,3L
-
-#define SN_X9_62_c2pnb176v1		"c2pnb176v1"
-#define NID_X9_62_c2pnb176v1		687
-#define OBJ_X9_62_c2pnb176v1		OBJ_X9_62_c_TwoCurve,4L
-
-#define SN_X9_62_c2tnb191v1		"c2tnb191v1"
-#define NID_X9_62_c2tnb191v1		688
-#define OBJ_X9_62_c2tnb191v1		OBJ_X9_62_c_TwoCurve,5L
-
-#define SN_X9_62_c2tnb191v2		"c2tnb191v2"
-#define NID_X9_62_c2tnb191v2		689
-#define OBJ_X9_62_c2tnb191v2		OBJ_X9_62_c_TwoCurve,6L
-
-#define SN_X9_62_c2tnb191v3		"c2tnb191v3"
-#define NID_X9_62_c2tnb191v3		690
-#define OBJ_X9_62_c2tnb191v3		OBJ_X9_62_c_TwoCurve,7L
-
-#define SN_X9_62_c2onb191v4		"c2onb191v4"
-#define NID_X9_62_c2onb191v4		691
-#define OBJ_X9_62_c2onb191v4		OBJ_X9_62_c_TwoCurve,8L
-
-#define SN_X9_62_c2onb191v5		"c2onb191v5"
-#define NID_X9_62_c2onb191v5		692
-#define OBJ_X9_62_c2onb191v5		OBJ_X9_62_c_TwoCurve,9L
-
-#define SN_X9_62_c2pnb208w1		"c2pnb208w1"
-#define NID_X9_62_c2pnb208w1		693
-#define OBJ_X9_62_c2pnb208w1		OBJ_X9_62_c_TwoCurve,10L
-
-#define SN_X9_62_c2tnb239v1		"c2tnb239v1"
-#define NID_X9_62_c2tnb239v1		694
-#define OBJ_X9_62_c2tnb239v1		OBJ_X9_62_c_TwoCurve,11L
-
-#define SN_X9_62_c2tnb239v2		"c2tnb239v2"
-#define NID_X9_62_c2tnb239v2		695
-#define OBJ_X9_62_c2tnb239v2		OBJ_X9_62_c_TwoCurve,12L
-
-#define SN_X9_62_c2tnb239v3		"c2tnb239v3"
-#define NID_X9_62_c2tnb239v3		696
-#define OBJ_X9_62_c2tnb239v3		OBJ_X9_62_c_TwoCurve,13L
-
-#define SN_X9_62_c2onb239v4		"c2onb239v4"
-#define NID_X9_62_c2onb239v4		697
-#define OBJ_X9_62_c2onb239v4		OBJ_X9_62_c_TwoCurve,14L
-
-#define SN_X9_62_c2onb239v5		"c2onb239v5"
-#define NID_X9_62_c2onb239v5		698
-#define OBJ_X9_62_c2onb239v5		OBJ_X9_62_c_TwoCurve,15L
-
-#define SN_X9_62_c2pnb272w1		"c2pnb272w1"
-#define NID_X9_62_c2pnb272w1		699
-#define OBJ_X9_62_c2pnb272w1		OBJ_X9_62_c_TwoCurve,16L
-
-#define SN_X9_62_c2pnb304w1		"c2pnb304w1"
-#define NID_X9_62_c2pnb304w1		700
-#define OBJ_X9_62_c2pnb304w1		OBJ_X9_62_c_TwoCurve,17L
-
-#define SN_X9_62_c2tnb359v1		"c2tnb359v1"
-#define NID_X9_62_c2tnb359v1		701
-#define OBJ_X9_62_c2tnb359v1		OBJ_X9_62_c_TwoCurve,18L
-
-#define SN_X9_62_c2pnb368w1		"c2pnb368w1"
-#define NID_X9_62_c2pnb368w1		702
-#define OBJ_X9_62_c2pnb368w1		OBJ_X9_62_c_TwoCurve,19L
-
-#define SN_X9_62_c2tnb431r1		"c2tnb431r1"
-#define NID_X9_62_c2tnb431r1		703
-#define OBJ_X9_62_c2tnb431r1		OBJ_X9_62_c_TwoCurve,20L
-
-#define OBJ_X9_62_primeCurve		OBJ_X9_62_ellipticCurve,1L
-
-#define SN_X9_62_prime192v1		"prime192v1"
-#define NID_X9_62_prime192v1		409
-#define OBJ_X9_62_prime192v1		OBJ_X9_62_primeCurve,1L
-
-#define SN_X9_62_prime192v2		"prime192v2"
-#define NID_X9_62_prime192v2		410
-#define OBJ_X9_62_prime192v2		OBJ_X9_62_primeCurve,2L
-
-#define SN_X9_62_prime192v3		"prime192v3"
-#define NID_X9_62_prime192v3		411
-#define OBJ_X9_62_prime192v3		OBJ_X9_62_primeCurve,3L
-
-#define SN_X9_62_prime239v1		"prime239v1"
-#define NID_X9_62_prime239v1		412
-#define OBJ_X9_62_prime239v1		OBJ_X9_62_primeCurve,4L
-
-#define SN_X9_62_prime239v2		"prime239v2"
-#define NID_X9_62_prime239v2		413
-#define OBJ_X9_62_prime239v2		OBJ_X9_62_primeCurve,5L
-
-#define SN_X9_62_prime239v3		"prime239v3"
-#define NID_X9_62_prime239v3		414
-#define OBJ_X9_62_prime239v3		OBJ_X9_62_primeCurve,6L
-
-#define SN_X9_62_prime256v1		"prime256v1"
-#define NID_X9_62_prime256v1		415
-#define OBJ_X9_62_prime256v1		OBJ_X9_62_primeCurve,7L
-
-#define OBJ_X9_62_id_ecSigType		OBJ_ansi_X9_62,4L
-
-#define SN_ecdsa_with_SHA1		"ecdsa-with-SHA1"
-#define NID_ecdsa_with_SHA1		416
-#define OBJ_ecdsa_with_SHA1		OBJ_X9_62_id_ecSigType,1L
-
-#define SN_ecdsa_with_Recommended		"ecdsa-with-Recommended"
-#define NID_ecdsa_with_Recommended		791
-#define OBJ_ecdsa_with_Recommended		OBJ_X9_62_id_ecSigType,2L
-
-#define SN_ecdsa_with_Specified		"ecdsa-with-Specified"
-#define NID_ecdsa_with_Specified		792
-#define OBJ_ecdsa_with_Specified		OBJ_X9_62_id_ecSigType,3L
-
-#define SN_ecdsa_with_SHA224		"ecdsa-with-SHA224"
-#define NID_ecdsa_with_SHA224		793
-#define OBJ_ecdsa_with_SHA224		OBJ_ecdsa_with_Specified,1L
-
-#define SN_ecdsa_with_SHA256		"ecdsa-with-SHA256"
-#define NID_ecdsa_with_SHA256		794
-#define OBJ_ecdsa_with_SHA256		OBJ_ecdsa_with_Specified,2L
-
-#define SN_ecdsa_with_SHA384		"ecdsa-with-SHA384"
-#define NID_ecdsa_with_SHA384		795
-#define OBJ_ecdsa_with_SHA384		OBJ_ecdsa_with_Specified,3L
-
-#define SN_ecdsa_with_SHA512		"ecdsa-with-SHA512"
-#define NID_ecdsa_with_SHA512		796
-#define OBJ_ecdsa_with_SHA512		OBJ_ecdsa_with_Specified,4L
-
-#define OBJ_secg_ellipticCurve		OBJ_certicom_arc,0L
-
-#define SN_secp112r1		"secp112r1"
-#define NID_secp112r1		704
-#define OBJ_secp112r1		OBJ_secg_ellipticCurve,6L
-
-#define SN_secp112r2		"secp112r2"
-#define NID_secp112r2		705
-#define OBJ_secp112r2		OBJ_secg_ellipticCurve,7L
-
-#define SN_secp128r1		"secp128r1"
-#define NID_secp128r1		706
-#define OBJ_secp128r1		OBJ_secg_ellipticCurve,28L
-
-#define SN_secp128r2		"secp128r2"
-#define NID_secp128r2		707
-#define OBJ_secp128r2		OBJ_secg_ellipticCurve,29L
-
-#define SN_secp160k1		"secp160k1"
-#define NID_secp160k1		708
-#define OBJ_secp160k1		OBJ_secg_ellipticCurve,9L
-
-#define SN_secp160r1		"secp160r1"
-#define NID_secp160r1		709
-#define OBJ_secp160r1		OBJ_secg_ellipticCurve,8L
-
-#define SN_secp160r2		"secp160r2"
-#define NID_secp160r2		710
-#define OBJ_secp160r2		OBJ_secg_ellipticCurve,30L
-
-#define SN_secp192k1		"secp192k1"
-#define NID_secp192k1		711
-#define OBJ_secp192k1		OBJ_secg_ellipticCurve,31L
-
-#define SN_secp224k1		"secp224k1"
-#define NID_secp224k1		712
-#define OBJ_secp224k1		OBJ_secg_ellipticCurve,32L
-
-#define SN_secp224r1		"secp224r1"
-#define NID_secp224r1		713
-#define OBJ_secp224r1		OBJ_secg_ellipticCurve,33L
-
-#define SN_secp256k1		"secp256k1"
-#define NID_secp256k1		714
-#define OBJ_secp256k1		OBJ_secg_ellipticCurve,10L
-
-#define SN_secp384r1		"secp384r1"
-#define NID_secp384r1		715
-#define OBJ_secp384r1		OBJ_secg_ellipticCurve,34L
-
-#define SN_secp521r1		"secp521r1"
-#define NID_secp521r1		716
-#define OBJ_secp521r1		OBJ_secg_ellipticCurve,35L
-
-#define SN_sect113r1		"sect113r1"
-#define NID_sect113r1		717
-#define OBJ_sect113r1		OBJ_secg_ellipticCurve,4L
-
-#define SN_sect113r2		"sect113r2"
-#define NID_sect113r2		718
-#define OBJ_sect113r2		OBJ_secg_ellipticCurve,5L
-
-#define SN_sect131r1		"sect131r1"
-#define NID_sect131r1		719
-#define OBJ_sect131r1		OBJ_secg_ellipticCurve,22L
-
-#define SN_sect131r2		"sect131r2"
-#define NID_sect131r2		720
-#define OBJ_sect131r2		OBJ_secg_ellipticCurve,23L
-
-#define SN_sect163k1		"sect163k1"
-#define NID_sect163k1		721
-#define OBJ_sect163k1		OBJ_secg_ellipticCurve,1L
-
-#define SN_sect163r1		"sect163r1"
-#define NID_sect163r1		722
-#define OBJ_sect163r1		OBJ_secg_ellipticCurve,2L
-
-#define SN_sect163r2		"sect163r2"
-#define NID_sect163r2		723
-#define OBJ_sect163r2		OBJ_secg_ellipticCurve,15L
-
-#define SN_sect193r1		"sect193r1"
-#define NID_sect193r1		724
-#define OBJ_sect193r1		OBJ_secg_ellipticCurve,24L
-
-#define SN_sect193r2		"sect193r2"
-#define NID_sect193r2		725
-#define OBJ_sect193r2		OBJ_secg_ellipticCurve,25L
-
-#define SN_sect233k1		"sect233k1"
-#define NID_sect233k1		726
-#define OBJ_sect233k1		OBJ_secg_ellipticCurve,26L
-
-#define SN_sect233r1		"sect233r1"
-#define NID_sect233r1		727
-#define OBJ_sect233r1		OBJ_secg_ellipticCurve,27L
-
-#define SN_sect239k1		"sect239k1"
-#define NID_sect239k1		728
-#define OBJ_sect239k1		OBJ_secg_ellipticCurve,3L
-
-#define SN_sect283k1		"sect283k1"
-#define NID_sect283k1		729
-#define OBJ_sect283k1		OBJ_secg_ellipticCurve,16L
-
-#define SN_sect283r1		"sect283r1"
-#define NID_sect283r1		730
-#define OBJ_sect283r1		OBJ_secg_ellipticCurve,17L
-
-#define SN_sect409k1		"sect409k1"
-#define NID_sect409k1		731
-#define OBJ_sect409k1		OBJ_secg_ellipticCurve,36L
-
-#define SN_sect409r1		"sect409r1"
-#define NID_sect409r1		732
-#define OBJ_sect409r1		OBJ_secg_ellipticCurve,37L
-
-#define SN_sect571k1		"sect571k1"
-#define NID_sect571k1		733
-#define OBJ_sect571k1		OBJ_secg_ellipticCurve,38L
-
-#define SN_sect571r1		"sect571r1"
-#define NID_sect571r1		734
-#define OBJ_sect571r1		OBJ_secg_ellipticCurve,39L
-
-#define OBJ_wap_wsg_idm_ecid		OBJ_wap_wsg,4L
-
-#define SN_wap_wsg_idm_ecid_wtls1		"wap-wsg-idm-ecid-wtls1"
-#define NID_wap_wsg_idm_ecid_wtls1		735
-#define OBJ_wap_wsg_idm_ecid_wtls1		OBJ_wap_wsg_idm_ecid,1L
-
-#define SN_wap_wsg_idm_ecid_wtls3		"wap-wsg-idm-ecid-wtls3"
-#define NID_wap_wsg_idm_ecid_wtls3		736
-#define OBJ_wap_wsg_idm_ecid_wtls3		OBJ_wap_wsg_idm_ecid,3L
-
-#define SN_wap_wsg_idm_ecid_wtls4		"wap-wsg-idm-ecid-wtls4"
-#define NID_wap_wsg_idm_ecid_wtls4		737
-#define OBJ_wap_wsg_idm_ecid_wtls4		OBJ_wap_wsg_idm_ecid,4L
-
-#define SN_wap_wsg_idm_ecid_wtls5		"wap-wsg-idm-ecid-wtls5"
-#define NID_wap_wsg_idm_ecid_wtls5		738
-#define OBJ_wap_wsg_idm_ecid_wtls5		OBJ_wap_wsg_idm_ecid,5L
-
-#define SN_wap_wsg_idm_ecid_wtls6		"wap-wsg-idm-ecid-wtls6"
-#define NID_wap_wsg_idm_ecid_wtls6		739
-#define OBJ_wap_wsg_idm_ecid_wtls6		OBJ_wap_wsg_idm_ecid,6L
-
-#define SN_wap_wsg_idm_ecid_wtls7		"wap-wsg-idm-ecid-wtls7"
-#define NID_wap_wsg_idm_ecid_wtls7		740
-#define OBJ_wap_wsg_idm_ecid_wtls7		OBJ_wap_wsg_idm_ecid,7L
-
-#define SN_wap_wsg_idm_ecid_wtls8		"wap-wsg-idm-ecid-wtls8"
-#define NID_wap_wsg_idm_ecid_wtls8		741
-#define OBJ_wap_wsg_idm_ecid_wtls8		OBJ_wap_wsg_idm_ecid,8L
-
-#define SN_wap_wsg_idm_ecid_wtls9		"wap-wsg-idm-ecid-wtls9"
-#define NID_wap_wsg_idm_ecid_wtls9		742
-#define OBJ_wap_wsg_idm_ecid_wtls9		OBJ_wap_wsg_idm_ecid,9L
-
-#define SN_wap_wsg_idm_ecid_wtls10		"wap-wsg-idm-ecid-wtls10"
-#define NID_wap_wsg_idm_ecid_wtls10		743
-#define OBJ_wap_wsg_idm_ecid_wtls10		OBJ_wap_wsg_idm_ecid,10L
-
-#define SN_wap_wsg_idm_ecid_wtls11		"wap-wsg-idm-ecid-wtls11"
-#define NID_wap_wsg_idm_ecid_wtls11		744
-#define OBJ_wap_wsg_idm_ecid_wtls11		OBJ_wap_wsg_idm_ecid,11L
-
-#define SN_wap_wsg_idm_ecid_wtls12		"wap-wsg-idm-ecid-wtls12"
-#define NID_wap_wsg_idm_ecid_wtls12		745
-#define OBJ_wap_wsg_idm_ecid_wtls12		OBJ_wap_wsg_idm_ecid,12L
-
-#define SN_cast5_cbc		"CAST5-CBC"
-#define LN_cast5_cbc		"cast5-cbc"
-#define NID_cast5_cbc		108
-#define OBJ_cast5_cbc		OBJ_ISO_US,113533L,7L,66L,10L
-
-#define SN_cast5_ecb		"CAST5-ECB"
-#define LN_cast5_ecb		"cast5-ecb"
-#define NID_cast5_ecb		109
-
-#define SN_cast5_cfb64		"CAST5-CFB"
-#define LN_cast5_cfb64		"cast5-cfb"
-#define NID_cast5_cfb64		110
-
-#define SN_cast5_ofb64		"CAST5-OFB"
-#define LN_cast5_ofb64		"cast5-ofb"
-#define NID_cast5_ofb64		111
-
-#define LN_pbeWithMD5AndCast5_CBC		"pbeWithMD5AndCast5CBC"
-#define NID_pbeWithMD5AndCast5_CBC		112
-#define OBJ_pbeWithMD5AndCast5_CBC		OBJ_ISO_US,113533L,7L,66L,12L
-
-#define SN_id_PasswordBasedMAC		"id-PasswordBasedMAC"
-#define LN_id_PasswordBasedMAC		"password based MAC"
-#define NID_id_PasswordBasedMAC		782
-#define OBJ_id_PasswordBasedMAC		OBJ_ISO_US,113533L,7L,66L,13L
-
-#define SN_id_DHBasedMac		"id-DHBasedMac"
-#define LN_id_DHBasedMac		"Diffie-Hellman based MAC"
-#define NID_id_DHBasedMac		783
-#define OBJ_id_DHBasedMac		OBJ_ISO_US,113533L,7L,66L,30L
-
-#define SN_rsadsi		"rsadsi"
-#define LN_rsadsi		"RSA Data Security, Inc."
-#define NID_rsadsi		1
-#define OBJ_rsadsi		OBJ_ISO_US,113549L
-
-#define SN_pkcs		"pkcs"
-#define LN_pkcs		"RSA Data Security, Inc. PKCS"
-#define NID_pkcs		2
-#define OBJ_pkcs		OBJ_rsadsi,1L
-
-#define SN_pkcs1		"pkcs1"
-#define NID_pkcs1		186
-#define OBJ_pkcs1		OBJ_pkcs,1L
-
-#define LN_rsaEncryption		"rsaEncryption"
-#define NID_rsaEncryption		6
-#define OBJ_rsaEncryption		OBJ_pkcs1,1L
-
-#define SN_md2WithRSAEncryption		"RSA-MD2"
-#define LN_md2WithRSAEncryption		"md2WithRSAEncryption"
-#define NID_md2WithRSAEncryption		7
-#define OBJ_md2WithRSAEncryption		OBJ_pkcs1,2L
-
-#define SN_md4WithRSAEncryption		"RSA-MD4"
-#define LN_md4WithRSAEncryption		"md4WithRSAEncryption"
-#define NID_md4WithRSAEncryption		396
-#define OBJ_md4WithRSAEncryption		OBJ_pkcs1,3L
-
-#define SN_md5WithRSAEncryption		"RSA-MD5"
-#define LN_md5WithRSAEncryption		"md5WithRSAEncryption"
-#define NID_md5WithRSAEncryption		8
-#define OBJ_md5WithRSAEncryption		OBJ_pkcs1,4L
-
-#define SN_sha1WithRSAEncryption		"RSA-SHA1"
-#define LN_sha1WithRSAEncryption		"sha1WithRSAEncryption"
-#define NID_sha1WithRSAEncryption		65
-#define OBJ_sha1WithRSAEncryption		OBJ_pkcs1,5L
-
-#define SN_rsaesOaep		"RSAES-OAEP"
-#define LN_rsaesOaep		"rsaesOaep"
-#define NID_rsaesOaep		919
-#define OBJ_rsaesOaep		OBJ_pkcs1,7L
-
-#define SN_mgf1		"MGF1"
-#define LN_mgf1		"mgf1"
-#define NID_mgf1		911
-#define OBJ_mgf1		OBJ_pkcs1,8L
-
-#define SN_pSpecified		"PSPECIFIED"
-#define LN_pSpecified		"pSpecified"
-#define NID_pSpecified		935
-#define OBJ_pSpecified		OBJ_pkcs1,9L
-
-#define SN_rsassaPss		"RSASSA-PSS"
-#define LN_rsassaPss		"rsassaPss"
-#define NID_rsassaPss		912
-#define OBJ_rsassaPss		OBJ_pkcs1,10L
-
-#define SN_sha256WithRSAEncryption		"RSA-SHA256"
-#define LN_sha256WithRSAEncryption		"sha256WithRSAEncryption"
-#define NID_sha256WithRSAEncryption		668
-#define OBJ_sha256WithRSAEncryption		OBJ_pkcs1,11L
-
-#define SN_sha384WithRSAEncryption		"RSA-SHA384"
-#define LN_sha384WithRSAEncryption		"sha384WithRSAEncryption"
-#define NID_sha384WithRSAEncryption		669
-#define OBJ_sha384WithRSAEncryption		OBJ_pkcs1,12L
-
-#define SN_sha512WithRSAEncryption		"RSA-SHA512"
-#define LN_sha512WithRSAEncryption		"sha512WithRSAEncryption"
-#define NID_sha512WithRSAEncryption		670
-#define OBJ_sha512WithRSAEncryption		OBJ_pkcs1,13L
-
-#define SN_sha224WithRSAEncryption		"RSA-SHA224"
-#define LN_sha224WithRSAEncryption		"sha224WithRSAEncryption"
-#define NID_sha224WithRSAEncryption		671
-#define OBJ_sha224WithRSAEncryption		OBJ_pkcs1,14L
-
-#define SN_pkcs3		"pkcs3"
-#define NID_pkcs3		27
-#define OBJ_pkcs3		OBJ_pkcs,3L
-
-#define LN_dhKeyAgreement		"dhKeyAgreement"
-#define NID_dhKeyAgreement		28
-#define OBJ_dhKeyAgreement		OBJ_pkcs3,1L
-
-#define SN_pkcs5		"pkcs5"
-#define NID_pkcs5		187
-#define OBJ_pkcs5		OBJ_pkcs,5L
-
-#define SN_pbeWithMD2AndDES_CBC		"PBE-MD2-DES"
-#define LN_pbeWithMD2AndDES_CBC		"pbeWithMD2AndDES-CBC"
-#define NID_pbeWithMD2AndDES_CBC		9
-#define OBJ_pbeWithMD2AndDES_CBC		OBJ_pkcs5,1L
-
-#define SN_pbeWithMD5AndDES_CBC		"PBE-MD5-DES"
-#define LN_pbeWithMD5AndDES_CBC		"pbeWithMD5AndDES-CBC"
-#define NID_pbeWithMD5AndDES_CBC		10
-#define OBJ_pbeWithMD5AndDES_CBC		OBJ_pkcs5,3L
-
-#define SN_pbeWithMD2AndRC2_CBC		"PBE-MD2-RC2-64"
-#define LN_pbeWithMD2AndRC2_CBC		"pbeWithMD2AndRC2-CBC"
-#define NID_pbeWithMD2AndRC2_CBC		168
-#define OBJ_pbeWithMD2AndRC2_CBC		OBJ_pkcs5,4L
-
-#define SN_pbeWithMD5AndRC2_CBC		"PBE-MD5-RC2-64"
-#define LN_pbeWithMD5AndRC2_CBC		"pbeWithMD5AndRC2-CBC"
-#define NID_pbeWithMD5AndRC2_CBC		169
-#define OBJ_pbeWithMD5AndRC2_CBC		OBJ_pkcs5,6L
-
-#define SN_pbeWithSHA1AndDES_CBC		"PBE-SHA1-DES"
-#define LN_pbeWithSHA1AndDES_CBC		"pbeWithSHA1AndDES-CBC"
-#define NID_pbeWithSHA1AndDES_CBC		170
-#define OBJ_pbeWithSHA1AndDES_CBC		OBJ_pkcs5,10L
-
-#define SN_pbeWithSHA1AndRC2_CBC		"PBE-SHA1-RC2-64"
-#define LN_pbeWithSHA1AndRC2_CBC		"pbeWithSHA1AndRC2-CBC"
-#define NID_pbeWithSHA1AndRC2_CBC		68
-#define OBJ_pbeWithSHA1AndRC2_CBC		OBJ_pkcs5,11L
-
-#define LN_id_pbkdf2		"PBKDF2"
-#define NID_id_pbkdf2		69
-#define OBJ_id_pbkdf2		OBJ_pkcs5,12L
-
-#define LN_pbes2		"PBES2"
-#define NID_pbes2		161
-#define OBJ_pbes2		OBJ_pkcs5,13L
-
-#define LN_pbmac1		"PBMAC1"
-#define NID_pbmac1		162
-#define OBJ_pbmac1		OBJ_pkcs5,14L
-
-#define SN_pkcs7		"pkcs7"
-#define NID_pkcs7		20
-#define OBJ_pkcs7		OBJ_pkcs,7L
-
-#define LN_pkcs7_data		"pkcs7-data"
-#define NID_pkcs7_data		21
-#define OBJ_pkcs7_data		OBJ_pkcs7,1L
-
-#define LN_pkcs7_signed		"pkcs7-signedData"
-#define NID_pkcs7_signed		22
-#define OBJ_pkcs7_signed		OBJ_pkcs7,2L
-
-#define LN_pkcs7_enveloped		"pkcs7-envelopedData"
-#define NID_pkcs7_enveloped		23
-#define OBJ_pkcs7_enveloped		OBJ_pkcs7,3L
-
-#define LN_pkcs7_signedAndEnveloped		"pkcs7-signedAndEnvelopedData"
-#define NID_pkcs7_signedAndEnveloped		24
-#define OBJ_pkcs7_signedAndEnveloped		OBJ_pkcs7,4L
-
-#define LN_pkcs7_digest		"pkcs7-digestData"
-#define NID_pkcs7_digest		25
-#define OBJ_pkcs7_digest		OBJ_pkcs7,5L
-
-#define LN_pkcs7_encrypted		"pkcs7-encryptedData"
-#define NID_pkcs7_encrypted		26
-#define OBJ_pkcs7_encrypted		OBJ_pkcs7,6L
-
-#define SN_pkcs9		"pkcs9"
-#define NID_pkcs9		47
-#define OBJ_pkcs9		OBJ_pkcs,9L
-
-#define LN_pkcs9_emailAddress		"emailAddress"
-#define NID_pkcs9_emailAddress		48
-#define OBJ_pkcs9_emailAddress		OBJ_pkcs9,1L
-
-#define LN_pkcs9_unstructuredName		"unstructuredName"
-#define NID_pkcs9_unstructuredName		49
-#define OBJ_pkcs9_unstructuredName		OBJ_pkcs9,2L
-
-#define LN_pkcs9_contentType		"contentType"
-#define NID_pkcs9_contentType		50
-#define OBJ_pkcs9_contentType		OBJ_pkcs9,3L
-
-#define LN_pkcs9_messageDigest		"messageDigest"
-#define NID_pkcs9_messageDigest		51
-#define OBJ_pkcs9_messageDigest		OBJ_pkcs9,4L
-
-#define LN_pkcs9_signingTime		"signingTime"
-#define NID_pkcs9_signingTime		52
-#define OBJ_pkcs9_signingTime		OBJ_pkcs9,5L
-
-#define LN_pkcs9_countersignature		"countersignature"
-#define NID_pkcs9_countersignature		53
-#define OBJ_pkcs9_countersignature		OBJ_pkcs9,6L
-
-#define LN_pkcs9_challengePassword		"challengePassword"
-#define NID_pkcs9_challengePassword		54
-#define OBJ_pkcs9_challengePassword		OBJ_pkcs9,7L
-
-#define LN_pkcs9_unstructuredAddress		"unstructuredAddress"
-#define NID_pkcs9_unstructuredAddress		55
-#define OBJ_pkcs9_unstructuredAddress		OBJ_pkcs9,8L
-
-#define LN_pkcs9_extCertAttributes		"extendedCertificateAttributes"
-#define NID_pkcs9_extCertAttributes		56
-#define OBJ_pkcs9_extCertAttributes		OBJ_pkcs9,9L
-
-#define SN_ext_req		"extReq"
-#define LN_ext_req		"Extension Request"
-#define NID_ext_req		172
-#define OBJ_ext_req		OBJ_pkcs9,14L
-
-#define SN_SMIMECapabilities		"SMIME-CAPS"
-#define LN_SMIMECapabilities		"S/MIME Capabilities"
-#define NID_SMIMECapabilities		167
-#define OBJ_SMIMECapabilities		OBJ_pkcs9,15L
-
-#define SN_SMIME		"SMIME"
-#define LN_SMIME		"S/MIME"
-#define NID_SMIME		188
-#define OBJ_SMIME		OBJ_pkcs9,16L
-
-#define SN_id_smime_mod		"id-smime-mod"
-#define NID_id_smime_mod		189
-#define OBJ_id_smime_mod		OBJ_SMIME,0L
-
-#define SN_id_smime_ct		"id-smime-ct"
-#define NID_id_smime_ct		190
-#define OBJ_id_smime_ct		OBJ_SMIME,1L
-
-#define SN_id_smime_aa		"id-smime-aa"
-#define NID_id_smime_aa		191
-#define OBJ_id_smime_aa		OBJ_SMIME,2L
-
-#define SN_id_smime_alg		"id-smime-alg"
-#define NID_id_smime_alg		192
-#define OBJ_id_smime_alg		OBJ_SMIME,3L
-
-#define SN_id_smime_cd		"id-smime-cd"
-#define NID_id_smime_cd		193
-#define OBJ_id_smime_cd		OBJ_SMIME,4L
-
-#define SN_id_smime_spq		"id-smime-spq"
-#define NID_id_smime_spq		194
-#define OBJ_id_smime_spq		OBJ_SMIME,5L
-
-#define SN_id_smime_cti		"id-smime-cti"
-#define NID_id_smime_cti		195
-#define OBJ_id_smime_cti		OBJ_SMIME,6L
-
-#define SN_id_smime_mod_cms		"id-smime-mod-cms"
-#define NID_id_smime_mod_cms		196
-#define OBJ_id_smime_mod_cms		OBJ_id_smime_mod,1L
-
-#define SN_id_smime_mod_ess		"id-smime-mod-ess"
-#define NID_id_smime_mod_ess		197
-#define OBJ_id_smime_mod_ess		OBJ_id_smime_mod,2L
-
-#define SN_id_smime_mod_oid		"id-smime-mod-oid"
-#define NID_id_smime_mod_oid		198
-#define OBJ_id_smime_mod_oid		OBJ_id_smime_mod,3L
-
-#define SN_id_smime_mod_msg_v3		"id-smime-mod-msg-v3"
-#define NID_id_smime_mod_msg_v3		199
-#define OBJ_id_smime_mod_msg_v3		OBJ_id_smime_mod,4L
-
-#define SN_id_smime_mod_ets_eSignature_88		"id-smime-mod-ets-eSignature-88"
-#define NID_id_smime_mod_ets_eSignature_88		200
-#define OBJ_id_smime_mod_ets_eSignature_88		OBJ_id_smime_mod,5L
-
-#define SN_id_smime_mod_ets_eSignature_97		"id-smime-mod-ets-eSignature-97"
-#define NID_id_smime_mod_ets_eSignature_97		201
-#define OBJ_id_smime_mod_ets_eSignature_97		OBJ_id_smime_mod,6L
-
-#define SN_id_smime_mod_ets_eSigPolicy_88		"id-smime-mod-ets-eSigPolicy-88"
-#define NID_id_smime_mod_ets_eSigPolicy_88		202
-#define OBJ_id_smime_mod_ets_eSigPolicy_88		OBJ_id_smime_mod,7L
-
-#define SN_id_smime_mod_ets_eSigPolicy_97		"id-smime-mod-ets-eSigPolicy-97"
-#define NID_id_smime_mod_ets_eSigPolicy_97		203
-#define OBJ_id_smime_mod_ets_eSigPolicy_97		OBJ_id_smime_mod,8L
-
-#define SN_id_smime_ct_receipt		"id-smime-ct-receipt"
-#define NID_id_smime_ct_receipt		204
-#define OBJ_id_smime_ct_receipt		OBJ_id_smime_ct,1L
-
-#define SN_id_smime_ct_authData		"id-smime-ct-authData"
-#define NID_id_smime_ct_authData		205
-#define OBJ_id_smime_ct_authData		OBJ_id_smime_ct,2L
-
-#define SN_id_smime_ct_publishCert		"id-smime-ct-publishCert"
-#define NID_id_smime_ct_publishCert		206
-#define OBJ_id_smime_ct_publishCert		OBJ_id_smime_ct,3L
-
-#define SN_id_smime_ct_TSTInfo		"id-smime-ct-TSTInfo"
-#define NID_id_smime_ct_TSTInfo		207
-#define OBJ_id_smime_ct_TSTInfo		OBJ_id_smime_ct,4L
-
-#define SN_id_smime_ct_TDTInfo		"id-smime-ct-TDTInfo"
-#define NID_id_smime_ct_TDTInfo		208
-#define OBJ_id_smime_ct_TDTInfo		OBJ_id_smime_ct,5L
-
-#define SN_id_smime_ct_contentInfo		"id-smime-ct-contentInfo"
-#define NID_id_smime_ct_contentInfo		209
-#define OBJ_id_smime_ct_contentInfo		OBJ_id_smime_ct,6L
-
-#define SN_id_smime_ct_DVCSRequestData		"id-smime-ct-DVCSRequestData"
-#define NID_id_smime_ct_DVCSRequestData		210
-#define OBJ_id_smime_ct_DVCSRequestData		OBJ_id_smime_ct,7L
-
-#define SN_id_smime_ct_DVCSResponseData		"id-smime-ct-DVCSResponseData"
-#define NID_id_smime_ct_DVCSResponseData		211
-#define OBJ_id_smime_ct_DVCSResponseData		OBJ_id_smime_ct,8L
-
-#define SN_id_smime_ct_compressedData		"id-smime-ct-compressedData"
-#define NID_id_smime_ct_compressedData		786
-#define OBJ_id_smime_ct_compressedData		OBJ_id_smime_ct,9L
-
-#define SN_id_ct_asciiTextWithCRLF		"id-ct-asciiTextWithCRLF"
-#define NID_id_ct_asciiTextWithCRLF		787
-#define OBJ_id_ct_asciiTextWithCRLF		OBJ_id_smime_ct,27L
-
-#define SN_id_smime_aa_receiptRequest		"id-smime-aa-receiptRequest"
-#define NID_id_smime_aa_receiptRequest		212
-#define OBJ_id_smime_aa_receiptRequest		OBJ_id_smime_aa,1L
-
-#define SN_id_smime_aa_securityLabel		"id-smime-aa-securityLabel"
-#define NID_id_smime_aa_securityLabel		213
-#define OBJ_id_smime_aa_securityLabel		OBJ_id_smime_aa,2L
-
-#define SN_id_smime_aa_mlExpandHistory		"id-smime-aa-mlExpandHistory"
-#define NID_id_smime_aa_mlExpandHistory		214
-#define OBJ_id_smime_aa_mlExpandHistory		OBJ_id_smime_aa,3L
-
-#define SN_id_smime_aa_contentHint		"id-smime-aa-contentHint"
-#define NID_id_smime_aa_contentHint		215
-#define OBJ_id_smime_aa_contentHint		OBJ_id_smime_aa,4L
-
-#define SN_id_smime_aa_msgSigDigest		"id-smime-aa-msgSigDigest"
-#define NID_id_smime_aa_msgSigDigest		216
-#define OBJ_id_smime_aa_msgSigDigest		OBJ_id_smime_aa,5L
-
-#define SN_id_smime_aa_encapContentType		"id-smime-aa-encapContentType"
-#define NID_id_smime_aa_encapContentType		217
-#define OBJ_id_smime_aa_encapContentType		OBJ_id_smime_aa,6L
-
-#define SN_id_smime_aa_contentIdentifier		"id-smime-aa-contentIdentifier"
-#define NID_id_smime_aa_contentIdentifier		218
-#define OBJ_id_smime_aa_contentIdentifier		OBJ_id_smime_aa,7L
-
-#define SN_id_smime_aa_macValue		"id-smime-aa-macValue"
-#define NID_id_smime_aa_macValue		219
-#define OBJ_id_smime_aa_macValue		OBJ_id_smime_aa,8L
-
-#define SN_id_smime_aa_equivalentLabels		"id-smime-aa-equivalentLabels"
-#define NID_id_smime_aa_equivalentLabels		220
-#define OBJ_id_smime_aa_equivalentLabels		OBJ_id_smime_aa,9L
-
-#define SN_id_smime_aa_contentReference		"id-smime-aa-contentReference"
-#define NID_id_smime_aa_contentReference		221
-#define OBJ_id_smime_aa_contentReference		OBJ_id_smime_aa,10L
-
-#define SN_id_smime_aa_encrypKeyPref		"id-smime-aa-encrypKeyPref"
-#define NID_id_smime_aa_encrypKeyPref		222
-#define OBJ_id_smime_aa_encrypKeyPref		OBJ_id_smime_aa,11L
-
-#define SN_id_smime_aa_signingCertificate		"id-smime-aa-signingCertificate"
-#define NID_id_smime_aa_signingCertificate		223
-#define OBJ_id_smime_aa_signingCertificate		OBJ_id_smime_aa,12L
-
-#define SN_id_smime_aa_smimeEncryptCerts		"id-smime-aa-smimeEncryptCerts"
-#define NID_id_smime_aa_smimeEncryptCerts		224
-#define OBJ_id_smime_aa_smimeEncryptCerts		OBJ_id_smime_aa,13L
-
-#define SN_id_smime_aa_timeStampToken		"id-smime-aa-timeStampToken"
-#define NID_id_smime_aa_timeStampToken		225
-#define OBJ_id_smime_aa_timeStampToken		OBJ_id_smime_aa,14L
-
-#define SN_id_smime_aa_ets_sigPolicyId		"id-smime-aa-ets-sigPolicyId"
-#define NID_id_smime_aa_ets_sigPolicyId		226
-#define OBJ_id_smime_aa_ets_sigPolicyId		OBJ_id_smime_aa,15L
-
-#define SN_id_smime_aa_ets_commitmentType		"id-smime-aa-ets-commitmentType"
-#define NID_id_smime_aa_ets_commitmentType		227
-#define OBJ_id_smime_aa_ets_commitmentType		OBJ_id_smime_aa,16L
-
-#define SN_id_smime_aa_ets_signerLocation		"id-smime-aa-ets-signerLocation"
-#define NID_id_smime_aa_ets_signerLocation		228
-#define OBJ_id_smime_aa_ets_signerLocation		OBJ_id_smime_aa,17L
-
-#define SN_id_smime_aa_ets_signerAttr		"id-smime-aa-ets-signerAttr"
-#define NID_id_smime_aa_ets_signerAttr		229
-#define OBJ_id_smime_aa_ets_signerAttr		OBJ_id_smime_aa,18L
-
-#define SN_id_smime_aa_ets_otherSigCert		"id-smime-aa-ets-otherSigCert"
-#define NID_id_smime_aa_ets_otherSigCert		230
-#define OBJ_id_smime_aa_ets_otherSigCert		OBJ_id_smime_aa,19L
-
-#define SN_id_smime_aa_ets_contentTimestamp		"id-smime-aa-ets-contentTimestamp"
-#define NID_id_smime_aa_ets_contentTimestamp		231
-#define OBJ_id_smime_aa_ets_contentTimestamp		OBJ_id_smime_aa,20L
-
-#define SN_id_smime_aa_ets_CertificateRefs		"id-smime-aa-ets-CertificateRefs"
-#define NID_id_smime_aa_ets_CertificateRefs		232
-#define OBJ_id_smime_aa_ets_CertificateRefs		OBJ_id_smime_aa,21L
-
-#define SN_id_smime_aa_ets_RevocationRefs		"id-smime-aa-ets-RevocationRefs"
-#define NID_id_smime_aa_ets_RevocationRefs		233
-#define OBJ_id_smime_aa_ets_RevocationRefs		OBJ_id_smime_aa,22L
-
-#define SN_id_smime_aa_ets_certValues		"id-smime-aa-ets-certValues"
-#define NID_id_smime_aa_ets_certValues		234
-#define OBJ_id_smime_aa_ets_certValues		OBJ_id_smime_aa,23L
-
-#define SN_id_smime_aa_ets_revocationValues		"id-smime-aa-ets-revocationValues"
-#define NID_id_smime_aa_ets_revocationValues		235
-#define OBJ_id_smime_aa_ets_revocationValues		OBJ_id_smime_aa,24L
-
-#define SN_id_smime_aa_ets_escTimeStamp		"id-smime-aa-ets-escTimeStamp"
-#define NID_id_smime_aa_ets_escTimeStamp		236
-#define OBJ_id_smime_aa_ets_escTimeStamp		OBJ_id_smime_aa,25L
-
-#define SN_id_smime_aa_ets_certCRLTimestamp		"id-smime-aa-ets-certCRLTimestamp"
-#define NID_id_smime_aa_ets_certCRLTimestamp		237
-#define OBJ_id_smime_aa_ets_certCRLTimestamp		OBJ_id_smime_aa,26L
-
-#define SN_id_smime_aa_ets_archiveTimeStamp		"id-smime-aa-ets-archiveTimeStamp"
-#define NID_id_smime_aa_ets_archiveTimeStamp		238
-#define OBJ_id_smime_aa_ets_archiveTimeStamp		OBJ_id_smime_aa,27L
-
-#define SN_id_smime_aa_signatureType		"id-smime-aa-signatureType"
-#define NID_id_smime_aa_signatureType		239
-#define OBJ_id_smime_aa_signatureType		OBJ_id_smime_aa,28L
-
-#define SN_id_smime_aa_dvcs_dvc		"id-smime-aa-dvcs-dvc"
-#define NID_id_smime_aa_dvcs_dvc		240
-#define OBJ_id_smime_aa_dvcs_dvc		OBJ_id_smime_aa,29L
-
-#define SN_id_smime_alg_ESDHwith3DES		"id-smime-alg-ESDHwith3DES"
-#define NID_id_smime_alg_ESDHwith3DES		241
-#define OBJ_id_smime_alg_ESDHwith3DES		OBJ_id_smime_alg,1L
-
-#define SN_id_smime_alg_ESDHwithRC2		"id-smime-alg-ESDHwithRC2"
-#define NID_id_smime_alg_ESDHwithRC2		242
-#define OBJ_id_smime_alg_ESDHwithRC2		OBJ_id_smime_alg,2L
-
-#define SN_id_smime_alg_3DESwrap		"id-smime-alg-3DESwrap"
-#define NID_id_smime_alg_3DESwrap		243
-#define OBJ_id_smime_alg_3DESwrap		OBJ_id_smime_alg,3L
-
-#define SN_id_smime_alg_RC2wrap		"id-smime-alg-RC2wrap"
-#define NID_id_smime_alg_RC2wrap		244
-#define OBJ_id_smime_alg_RC2wrap		OBJ_id_smime_alg,4L
-
-#define SN_id_smime_alg_ESDH		"id-smime-alg-ESDH"
-#define NID_id_smime_alg_ESDH		245
-#define OBJ_id_smime_alg_ESDH		OBJ_id_smime_alg,5L
-
-#define SN_id_smime_alg_CMS3DESwrap		"id-smime-alg-CMS3DESwrap"
-#define NID_id_smime_alg_CMS3DESwrap		246
-#define OBJ_id_smime_alg_CMS3DESwrap		OBJ_id_smime_alg,6L
-
-#define SN_id_smime_alg_CMSRC2wrap		"id-smime-alg-CMSRC2wrap"
-#define NID_id_smime_alg_CMSRC2wrap		247
-#define OBJ_id_smime_alg_CMSRC2wrap		OBJ_id_smime_alg,7L
-
-#define SN_id_alg_PWRI_KEK		"id-alg-PWRI-KEK"
-#define NID_id_alg_PWRI_KEK		893
-#define OBJ_id_alg_PWRI_KEK		OBJ_id_smime_alg,9L
-
-#define SN_id_smime_cd_ldap		"id-smime-cd-ldap"
-#define NID_id_smime_cd_ldap		248
-#define OBJ_id_smime_cd_ldap		OBJ_id_smime_cd,1L
-
-#define SN_id_smime_spq_ets_sqt_uri		"id-smime-spq-ets-sqt-uri"
-#define NID_id_smime_spq_ets_sqt_uri		249
-#define OBJ_id_smime_spq_ets_sqt_uri		OBJ_id_smime_spq,1L
-
-#define SN_id_smime_spq_ets_sqt_unotice		"id-smime-spq-ets-sqt-unotice"
-#define NID_id_smime_spq_ets_sqt_unotice		250
-#define OBJ_id_smime_spq_ets_sqt_unotice		OBJ_id_smime_spq,2L
-
-#define SN_id_smime_cti_ets_proofOfOrigin		"id-smime-cti-ets-proofOfOrigin"
-#define NID_id_smime_cti_ets_proofOfOrigin		251
-#define OBJ_id_smime_cti_ets_proofOfOrigin		OBJ_id_smime_cti,1L
-
-#define SN_id_smime_cti_ets_proofOfReceipt		"id-smime-cti-ets-proofOfReceipt"
-#define NID_id_smime_cti_ets_proofOfReceipt		252
-#define OBJ_id_smime_cti_ets_proofOfReceipt		OBJ_id_smime_cti,2L
-
-#define SN_id_smime_cti_ets_proofOfDelivery		"id-smime-cti-ets-proofOfDelivery"
-#define NID_id_smime_cti_ets_proofOfDelivery		253
-#define OBJ_id_smime_cti_ets_proofOfDelivery		OBJ_id_smime_cti,3L
-
-#define SN_id_smime_cti_ets_proofOfSender		"id-smime-cti-ets-proofOfSender"
-#define NID_id_smime_cti_ets_proofOfSender		254
-#define OBJ_id_smime_cti_ets_proofOfSender		OBJ_id_smime_cti,4L
-
-#define SN_id_smime_cti_ets_proofOfApproval		"id-smime-cti-ets-proofOfApproval"
-#define NID_id_smime_cti_ets_proofOfApproval		255
-#define OBJ_id_smime_cti_ets_proofOfApproval		OBJ_id_smime_cti,5L
-
-#define SN_id_smime_cti_ets_proofOfCreation		"id-smime-cti-ets-proofOfCreation"
-#define NID_id_smime_cti_ets_proofOfCreation		256
-#define OBJ_id_smime_cti_ets_proofOfCreation		OBJ_id_smime_cti,6L
-
-#define LN_friendlyName		"friendlyName"
-#define NID_friendlyName		156
-#define OBJ_friendlyName		OBJ_pkcs9,20L
-
-#define LN_localKeyID		"localKeyID"
-#define NID_localKeyID		157
-#define OBJ_localKeyID		OBJ_pkcs9,21L
-
-#define SN_ms_csp_name		"CSPName"
-#define LN_ms_csp_name		"Microsoft CSP Name"
-#define NID_ms_csp_name		417
-#define OBJ_ms_csp_name		1L,3L,6L,1L,4L,1L,311L,17L,1L
-
-#define SN_LocalKeySet		"LocalKeySet"
-#define LN_LocalKeySet		"Microsoft Local Key set"
-#define NID_LocalKeySet		856
-#define OBJ_LocalKeySet		1L,3L,6L,1L,4L,1L,311L,17L,2L
-
-#define OBJ_certTypes		OBJ_pkcs9,22L
-
-#define LN_x509Certificate		"x509Certificate"
-#define NID_x509Certificate		158
-#define OBJ_x509Certificate		OBJ_certTypes,1L
-
-#define LN_sdsiCertificate		"sdsiCertificate"
-#define NID_sdsiCertificate		159
-#define OBJ_sdsiCertificate		OBJ_certTypes,2L
-
-#define OBJ_crlTypes		OBJ_pkcs9,23L
-
-#define LN_x509Crl		"x509Crl"
-#define NID_x509Crl		160
-#define OBJ_x509Crl		OBJ_crlTypes,1L
-
-#define OBJ_pkcs12		OBJ_pkcs,12L
-
-#define OBJ_pkcs12_pbeids		OBJ_pkcs12,1L
-
-#define SN_pbe_WithSHA1And128BitRC4		"PBE-SHA1-RC4-128"
-#define LN_pbe_WithSHA1And128BitRC4		"pbeWithSHA1And128BitRC4"
-#define NID_pbe_WithSHA1And128BitRC4		144
-#define OBJ_pbe_WithSHA1And128BitRC4		OBJ_pkcs12_pbeids,1L
-
-#define SN_pbe_WithSHA1And40BitRC4		"PBE-SHA1-RC4-40"
-#define LN_pbe_WithSHA1And40BitRC4		"pbeWithSHA1And40BitRC4"
-#define NID_pbe_WithSHA1And40BitRC4		145
-#define OBJ_pbe_WithSHA1And40BitRC4		OBJ_pkcs12_pbeids,2L
-
-#define SN_pbe_WithSHA1And3_Key_TripleDES_CBC		"PBE-SHA1-3DES"
-#define LN_pbe_WithSHA1And3_Key_TripleDES_CBC		"pbeWithSHA1And3-KeyTripleDES-CBC"
-#define NID_pbe_WithSHA1And3_Key_TripleDES_CBC		146
-#define OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC		OBJ_pkcs12_pbeids,3L
-
-#define SN_pbe_WithSHA1And2_Key_TripleDES_CBC		"PBE-SHA1-2DES"
-#define LN_pbe_WithSHA1And2_Key_TripleDES_CBC		"pbeWithSHA1And2-KeyTripleDES-CBC"
-#define NID_pbe_WithSHA1And2_Key_TripleDES_CBC		147
-#define OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC		OBJ_pkcs12_pbeids,4L
-
-#define SN_pbe_WithSHA1And128BitRC2_CBC		"PBE-SHA1-RC2-128"
-#define LN_pbe_WithSHA1And128BitRC2_CBC		"pbeWithSHA1And128BitRC2-CBC"
-#define NID_pbe_WithSHA1And128BitRC2_CBC		148
-#define OBJ_pbe_WithSHA1And128BitRC2_CBC		OBJ_pkcs12_pbeids,5L
-
-#define SN_pbe_WithSHA1And40BitRC2_CBC		"PBE-SHA1-RC2-40"
-#define LN_pbe_WithSHA1And40BitRC2_CBC		"pbeWithSHA1And40BitRC2-CBC"
-#define NID_pbe_WithSHA1And40BitRC2_CBC		149
-#define OBJ_pbe_WithSHA1And40BitRC2_CBC		OBJ_pkcs12_pbeids,6L
-
-#define OBJ_pkcs12_Version1		OBJ_pkcs12,10L
-
-#define OBJ_pkcs12_BagIds		OBJ_pkcs12_Version1,1L
-
-#define LN_keyBag		"keyBag"
-#define NID_keyBag		150
-#define OBJ_keyBag		OBJ_pkcs12_BagIds,1L
-
-#define LN_pkcs8ShroudedKeyBag		"pkcs8ShroudedKeyBag"
-#define NID_pkcs8ShroudedKeyBag		151
-#define OBJ_pkcs8ShroudedKeyBag		OBJ_pkcs12_BagIds,2L
-
-#define LN_certBag		"certBag"
-#define NID_certBag		152
-#define OBJ_certBag		OBJ_pkcs12_BagIds,3L
-
-#define LN_crlBag		"crlBag"
-#define NID_crlBag		153
-#define OBJ_crlBag		OBJ_pkcs12_BagIds,4L
-
-#define LN_secretBag		"secretBag"
-#define NID_secretBag		154
-#define OBJ_secretBag		OBJ_pkcs12_BagIds,5L
-
-#define LN_safeContentsBag		"safeContentsBag"
-#define NID_safeContentsBag		155
-#define OBJ_safeContentsBag		OBJ_pkcs12_BagIds,6L
-
-#define SN_md2		"MD2"
-#define LN_md2		"md2"
-#define NID_md2		3
-#define OBJ_md2		OBJ_rsadsi,2L,2L
-
-#define SN_md4		"MD4"
-#define LN_md4		"md4"
-#define NID_md4		257
-#define OBJ_md4		OBJ_rsadsi,2L,4L
-
-#define SN_md5		"MD5"
-#define LN_md5		"md5"
-#define NID_md5		4
-#define OBJ_md5		OBJ_rsadsi,2L,5L
-
-#define SN_md5_sha1		"MD5-SHA1"
-#define LN_md5_sha1		"md5-sha1"
-#define NID_md5_sha1		114
-
-#define LN_hmacWithMD5		"hmacWithMD5"
-#define NID_hmacWithMD5		797
-#define OBJ_hmacWithMD5		OBJ_rsadsi,2L,6L
-
-#define LN_hmacWithSHA1		"hmacWithSHA1"
-#define NID_hmacWithSHA1		163
-#define OBJ_hmacWithSHA1		OBJ_rsadsi,2L,7L
-
-#define LN_hmacWithSHA224		"hmacWithSHA224"
-#define NID_hmacWithSHA224		798
-#define OBJ_hmacWithSHA224		OBJ_rsadsi,2L,8L
-
-#define LN_hmacWithSHA256		"hmacWithSHA256"
-#define NID_hmacWithSHA256		799
-#define OBJ_hmacWithSHA256		OBJ_rsadsi,2L,9L
-
-#define LN_hmacWithSHA384		"hmacWithSHA384"
-#define NID_hmacWithSHA384		800
-#define OBJ_hmacWithSHA384		OBJ_rsadsi,2L,10L
-
-#define LN_hmacWithSHA512		"hmacWithSHA512"
-#define NID_hmacWithSHA512		801
-#define OBJ_hmacWithSHA512		OBJ_rsadsi,2L,11L
-
-#define SN_rc2_cbc		"RC2-CBC"
-#define LN_rc2_cbc		"rc2-cbc"
-#define NID_rc2_cbc		37
-#define OBJ_rc2_cbc		OBJ_rsadsi,3L,2L
-
-#define SN_rc2_ecb		"RC2-ECB"
-#define LN_rc2_ecb		"rc2-ecb"
-#define NID_rc2_ecb		38
-
-#define SN_rc2_cfb64		"RC2-CFB"
-#define LN_rc2_cfb64		"rc2-cfb"
-#define NID_rc2_cfb64		39
-
-#define SN_rc2_ofb64		"RC2-OFB"
-#define LN_rc2_ofb64		"rc2-ofb"
-#define NID_rc2_ofb64		40
-
-#define SN_rc2_40_cbc		"RC2-40-CBC"
-#define LN_rc2_40_cbc		"rc2-40-cbc"
-#define NID_rc2_40_cbc		98
-
-#define SN_rc2_64_cbc		"RC2-64-CBC"
-#define LN_rc2_64_cbc		"rc2-64-cbc"
-#define NID_rc2_64_cbc		166
-
-#define SN_rc4		"RC4"
-#define LN_rc4		"rc4"
-#define NID_rc4		5
-#define OBJ_rc4		OBJ_rsadsi,3L,4L
-
-#define SN_rc4_40		"RC4-40"
-#define LN_rc4_40		"rc4-40"
-#define NID_rc4_40		97
-
-#define SN_des_ede3_cbc		"DES-EDE3-CBC"
-#define LN_des_ede3_cbc		"des-ede3-cbc"
-#define NID_des_ede3_cbc		44
-#define OBJ_des_ede3_cbc		OBJ_rsadsi,3L,7L
-
-#define SN_rc5_cbc		"RC5-CBC"
-#define LN_rc5_cbc		"rc5-cbc"
-#define NID_rc5_cbc		120
-#define OBJ_rc5_cbc		OBJ_rsadsi,3L,8L
-
-#define SN_rc5_ecb		"RC5-ECB"
-#define LN_rc5_ecb		"rc5-ecb"
-#define NID_rc5_ecb		121
-
-#define SN_rc5_cfb64		"RC5-CFB"
-#define LN_rc5_cfb64		"rc5-cfb"
-#define NID_rc5_cfb64		122
-
-#define SN_rc5_ofb64		"RC5-OFB"
-#define LN_rc5_ofb64		"rc5-ofb"
-#define NID_rc5_ofb64		123
-
-#define SN_ms_ext_req		"msExtReq"
-#define LN_ms_ext_req		"Microsoft Extension Request"
-#define NID_ms_ext_req		171
-#define OBJ_ms_ext_req		1L,3L,6L,1L,4L,1L,311L,2L,1L,14L
-
-#define SN_ms_code_ind		"msCodeInd"
-#define LN_ms_code_ind		"Microsoft Individual Code Signing"
-#define NID_ms_code_ind		134
-#define OBJ_ms_code_ind		1L,3L,6L,1L,4L,1L,311L,2L,1L,21L
-
-#define SN_ms_code_com		"msCodeCom"
-#define LN_ms_code_com		"Microsoft Commercial Code Signing"
-#define NID_ms_code_com		135
-#define OBJ_ms_code_com		1L,3L,6L,1L,4L,1L,311L,2L,1L,22L
-
-#define SN_ms_ctl_sign		"msCTLSign"
-#define LN_ms_ctl_sign		"Microsoft Trust List Signing"
-#define NID_ms_ctl_sign		136
-#define OBJ_ms_ctl_sign		1L,3L,6L,1L,4L,1L,311L,10L,3L,1L
-
-#define SN_ms_sgc		"msSGC"
-#define LN_ms_sgc		"Microsoft Server Gated Crypto"
-#define NID_ms_sgc		137
-#define OBJ_ms_sgc		1L,3L,6L,1L,4L,1L,311L,10L,3L,3L
-
-#define SN_ms_efs		"msEFS"
-#define LN_ms_efs		"Microsoft Encrypted File System"
-#define NID_ms_efs		138
-#define OBJ_ms_efs		1L,3L,6L,1L,4L,1L,311L,10L,3L,4L
-
-#define SN_ms_smartcard_login		"msSmartcardLogin"
-#define LN_ms_smartcard_login		"Microsoft Smartcardlogin"
-#define NID_ms_smartcard_login		648
-#define OBJ_ms_smartcard_login		1L,3L,6L,1L,4L,1L,311L,20L,2L,2L
-
-#define SN_ms_upn		"msUPN"
-#define LN_ms_upn		"Microsoft Universal Principal Name"
-#define NID_ms_upn		649
-#define OBJ_ms_upn		1L,3L,6L,1L,4L,1L,311L,20L,2L,3L
-
-#define SN_idea_cbc		"IDEA-CBC"
-#define LN_idea_cbc		"idea-cbc"
-#define NID_idea_cbc		34
-#define OBJ_idea_cbc		1L,3L,6L,1L,4L,1L,188L,7L,1L,1L,2L
-
-#define SN_idea_ecb		"IDEA-ECB"
-#define LN_idea_ecb		"idea-ecb"
-#define NID_idea_ecb		36
-
-#define SN_idea_cfb64		"IDEA-CFB"
-#define LN_idea_cfb64		"idea-cfb"
-#define NID_idea_cfb64		35
-
-#define SN_idea_ofb64		"IDEA-OFB"
-#define LN_idea_ofb64		"idea-ofb"
-#define NID_idea_ofb64		46
-
-#define SN_bf_cbc		"BF-CBC"
-#define LN_bf_cbc		"bf-cbc"
-#define NID_bf_cbc		91
-#define OBJ_bf_cbc		1L,3L,6L,1L,4L,1L,3029L,1L,2L
-
-#define SN_bf_ecb		"BF-ECB"
-#define LN_bf_ecb		"bf-ecb"
-#define NID_bf_ecb		92
-
-#define SN_bf_cfb64		"BF-CFB"
-#define LN_bf_cfb64		"bf-cfb"
-#define NID_bf_cfb64		93
-
-#define SN_bf_ofb64		"BF-OFB"
-#define LN_bf_ofb64		"bf-ofb"
-#define NID_bf_ofb64		94
-
-#define SN_id_pkix		"PKIX"
-#define NID_id_pkix		127
-#define OBJ_id_pkix		1L,3L,6L,1L,5L,5L,7L
-
-#define SN_id_pkix_mod		"id-pkix-mod"
-#define NID_id_pkix_mod		258
-#define OBJ_id_pkix_mod		OBJ_id_pkix,0L
-
-#define SN_id_pe		"id-pe"
-#define NID_id_pe		175
-#define OBJ_id_pe		OBJ_id_pkix,1L
-
-#define SN_id_qt		"id-qt"
-#define NID_id_qt		259
-#define OBJ_id_qt		OBJ_id_pkix,2L
-
-#define SN_id_kp		"id-kp"
-#define NID_id_kp		128
-#define OBJ_id_kp		OBJ_id_pkix,3L
-
-#define SN_id_it		"id-it"
-#define NID_id_it		260
-#define OBJ_id_it		OBJ_id_pkix,4L
-
-#define SN_id_pkip		"id-pkip"
-#define NID_id_pkip		261
-#define OBJ_id_pkip		OBJ_id_pkix,5L
-
-#define SN_id_alg		"id-alg"
-#define NID_id_alg		262
-#define OBJ_id_alg		OBJ_id_pkix,6L
-
-#define SN_id_cmc		"id-cmc"
-#define NID_id_cmc		263
-#define OBJ_id_cmc		OBJ_id_pkix,7L
-
-#define SN_id_on		"id-on"
-#define NID_id_on		264
-#define OBJ_id_on		OBJ_id_pkix,8L
-
-#define SN_id_pda		"id-pda"
-#define NID_id_pda		265
-#define OBJ_id_pda		OBJ_id_pkix,9L
-
-#define SN_id_aca		"id-aca"
-#define NID_id_aca		266
-#define OBJ_id_aca		OBJ_id_pkix,10L
-
-#define SN_id_qcs		"id-qcs"
-#define NID_id_qcs		267
-#define OBJ_id_qcs		OBJ_id_pkix,11L
-
-#define SN_id_cct		"id-cct"
-#define NID_id_cct		268
-#define OBJ_id_cct		OBJ_id_pkix,12L
-
-#define SN_id_ppl		"id-ppl"
-#define NID_id_ppl		662
-#define OBJ_id_ppl		OBJ_id_pkix,21L
-
-#define SN_id_ad		"id-ad"
-#define NID_id_ad		176
-#define OBJ_id_ad		OBJ_id_pkix,48L
-
-#define SN_id_pkix1_explicit_88		"id-pkix1-explicit-88"
-#define NID_id_pkix1_explicit_88		269
-#define OBJ_id_pkix1_explicit_88		OBJ_id_pkix_mod,1L
-
-#define SN_id_pkix1_implicit_88		"id-pkix1-implicit-88"
-#define NID_id_pkix1_implicit_88		270
-#define OBJ_id_pkix1_implicit_88		OBJ_id_pkix_mod,2L
-
-#define SN_id_pkix1_explicit_93		"id-pkix1-explicit-93"
-#define NID_id_pkix1_explicit_93		271
-#define OBJ_id_pkix1_explicit_93		OBJ_id_pkix_mod,3L
-
-#define SN_id_pkix1_implicit_93		"id-pkix1-implicit-93"
-#define NID_id_pkix1_implicit_93		272
-#define OBJ_id_pkix1_implicit_93		OBJ_id_pkix_mod,4L
-
-#define SN_id_mod_crmf		"id-mod-crmf"
-#define NID_id_mod_crmf		273
-#define OBJ_id_mod_crmf		OBJ_id_pkix_mod,5L
-
-#define SN_id_mod_cmc		"id-mod-cmc"
-#define NID_id_mod_cmc		274
-#define OBJ_id_mod_cmc		OBJ_id_pkix_mod,6L
-
-#define SN_id_mod_kea_profile_88		"id-mod-kea-profile-88"
-#define NID_id_mod_kea_profile_88		275
-#define OBJ_id_mod_kea_profile_88		OBJ_id_pkix_mod,7L
-
-#define SN_id_mod_kea_profile_93		"id-mod-kea-profile-93"
-#define NID_id_mod_kea_profile_93		276
-#define OBJ_id_mod_kea_profile_93		OBJ_id_pkix_mod,8L
-
-#define SN_id_mod_cmp		"id-mod-cmp"
-#define NID_id_mod_cmp		277
-#define OBJ_id_mod_cmp		OBJ_id_pkix_mod,9L
-
-#define SN_id_mod_qualified_cert_88		"id-mod-qualified-cert-88"
-#define NID_id_mod_qualified_cert_88		278
-#define OBJ_id_mod_qualified_cert_88		OBJ_id_pkix_mod,10L
-
-#define SN_id_mod_qualified_cert_93		"id-mod-qualified-cert-93"
-#define NID_id_mod_qualified_cert_93		279
-#define OBJ_id_mod_qualified_cert_93		OBJ_id_pkix_mod,11L
-
-#define SN_id_mod_attribute_cert		"id-mod-attribute-cert"
-#define NID_id_mod_attribute_cert		280
-#define OBJ_id_mod_attribute_cert		OBJ_id_pkix_mod,12L
-
-#define SN_id_mod_timestamp_protocol		"id-mod-timestamp-protocol"
-#define NID_id_mod_timestamp_protocol		281
-#define OBJ_id_mod_timestamp_protocol		OBJ_id_pkix_mod,13L
-
-#define SN_id_mod_ocsp		"id-mod-ocsp"
-#define NID_id_mod_ocsp		282
-#define OBJ_id_mod_ocsp		OBJ_id_pkix_mod,14L
-
-#define SN_id_mod_dvcs		"id-mod-dvcs"
-#define NID_id_mod_dvcs		283
-#define OBJ_id_mod_dvcs		OBJ_id_pkix_mod,15L
-
-#define SN_id_mod_cmp2000		"id-mod-cmp2000"
-#define NID_id_mod_cmp2000		284
-#define OBJ_id_mod_cmp2000		OBJ_id_pkix_mod,16L
-
-#define SN_info_access		"authorityInfoAccess"
-#define LN_info_access		"Authority Information Access"
-#define NID_info_access		177
-#define OBJ_info_access		OBJ_id_pe,1L
-
-#define SN_biometricInfo		"biometricInfo"
-#define LN_biometricInfo		"Biometric Info"
-#define NID_biometricInfo		285
-#define OBJ_biometricInfo		OBJ_id_pe,2L
-
-#define SN_qcStatements		"qcStatements"
-#define NID_qcStatements		286
-#define OBJ_qcStatements		OBJ_id_pe,3L
-
-#define SN_ac_auditEntity		"ac-auditEntity"
-#define NID_ac_auditEntity		287
-#define OBJ_ac_auditEntity		OBJ_id_pe,4L
-
-#define SN_ac_targeting		"ac-targeting"
-#define NID_ac_targeting		288
-#define OBJ_ac_targeting		OBJ_id_pe,5L
-
-#define SN_aaControls		"aaControls"
-#define NID_aaControls		289
-#define OBJ_aaControls		OBJ_id_pe,6L
-
-#define SN_sbgp_ipAddrBlock		"sbgp-ipAddrBlock"
-#define NID_sbgp_ipAddrBlock		290
-#define OBJ_sbgp_ipAddrBlock		OBJ_id_pe,7L
-
-#define SN_sbgp_autonomousSysNum		"sbgp-autonomousSysNum"
-#define NID_sbgp_autonomousSysNum		291
-#define OBJ_sbgp_autonomousSysNum		OBJ_id_pe,8L
-
-#define SN_sbgp_routerIdentifier		"sbgp-routerIdentifier"
-#define NID_sbgp_routerIdentifier		292
-#define OBJ_sbgp_routerIdentifier		OBJ_id_pe,9L
-
-#define SN_ac_proxying		"ac-proxying"
-#define NID_ac_proxying		397
-#define OBJ_ac_proxying		OBJ_id_pe,10L
-
-#define SN_sinfo_access		"subjectInfoAccess"
-#define LN_sinfo_access		"Subject Information Access"
-#define NID_sinfo_access		398
-#define OBJ_sinfo_access		OBJ_id_pe,11L
-
-#define SN_proxyCertInfo		"proxyCertInfo"
-#define LN_proxyCertInfo		"Proxy Certificate Information"
-#define NID_proxyCertInfo		663
-#define OBJ_proxyCertInfo		OBJ_id_pe,14L
-
-#define SN_id_qt_cps		"id-qt-cps"
-#define LN_id_qt_cps		"Policy Qualifier CPS"
-#define NID_id_qt_cps		164
-#define OBJ_id_qt_cps		OBJ_id_qt,1L
-
-#define SN_id_qt_unotice		"id-qt-unotice"
-#define LN_id_qt_unotice		"Policy Qualifier User Notice"
-#define NID_id_qt_unotice		165
-#define OBJ_id_qt_unotice		OBJ_id_qt,2L
-
-#define SN_textNotice		"textNotice"
-#define NID_textNotice		293
-#define OBJ_textNotice		OBJ_id_qt,3L
-
-#define SN_server_auth		"serverAuth"
-#define LN_server_auth		"TLS Web Server Authentication"
-#define NID_server_auth		129
-#define OBJ_server_auth		OBJ_id_kp,1L
-
-#define SN_client_auth		"clientAuth"
-#define LN_client_auth		"TLS Web Client Authentication"
-#define NID_client_auth		130
-#define OBJ_client_auth		OBJ_id_kp,2L
-
-#define SN_code_sign		"codeSigning"
-#define LN_code_sign		"Code Signing"
-#define NID_code_sign		131
-#define OBJ_code_sign		OBJ_id_kp,3L
-
-#define SN_email_protect		"emailProtection"
-#define LN_email_protect		"E-mail Protection"
-#define NID_email_protect		132
-#define OBJ_email_protect		OBJ_id_kp,4L
-
-#define SN_ipsecEndSystem		"ipsecEndSystem"
-#define LN_ipsecEndSystem		"IPSec End System"
-#define NID_ipsecEndSystem		294
-#define OBJ_ipsecEndSystem		OBJ_id_kp,5L
-
-#define SN_ipsecTunnel		"ipsecTunnel"
-#define LN_ipsecTunnel		"IPSec Tunnel"
-#define NID_ipsecTunnel		295
-#define OBJ_ipsecTunnel		OBJ_id_kp,6L
-
-#define SN_ipsecUser		"ipsecUser"
-#define LN_ipsecUser		"IPSec User"
-#define NID_ipsecUser		296
-#define OBJ_ipsecUser		OBJ_id_kp,7L
-
-#define SN_time_stamp		"timeStamping"
-#define LN_time_stamp		"Time Stamping"
-#define NID_time_stamp		133
-#define OBJ_time_stamp		OBJ_id_kp,8L
-
-#define SN_OCSP_sign		"OCSPSigning"
-#define LN_OCSP_sign		"OCSP Signing"
-#define NID_OCSP_sign		180
-#define OBJ_OCSP_sign		OBJ_id_kp,9L
-
-#define SN_dvcs		"DVCS"
-#define LN_dvcs		"dvcs"
-#define NID_dvcs		297
-#define OBJ_dvcs		OBJ_id_kp,10L
-
-#define SN_id_it_caProtEncCert		"id-it-caProtEncCert"
-#define NID_id_it_caProtEncCert		298
-#define OBJ_id_it_caProtEncCert		OBJ_id_it,1L
-
-#define SN_id_it_signKeyPairTypes		"id-it-signKeyPairTypes"
-#define NID_id_it_signKeyPairTypes		299
-#define OBJ_id_it_signKeyPairTypes		OBJ_id_it,2L
-
-#define SN_id_it_encKeyPairTypes		"id-it-encKeyPairTypes"
-#define NID_id_it_encKeyPairTypes		300
-#define OBJ_id_it_encKeyPairTypes		OBJ_id_it,3L
-
-#define SN_id_it_preferredSymmAlg		"id-it-preferredSymmAlg"
-#define NID_id_it_preferredSymmAlg		301
-#define OBJ_id_it_preferredSymmAlg		OBJ_id_it,4L
-
-#define SN_id_it_caKeyUpdateInfo		"id-it-caKeyUpdateInfo"
-#define NID_id_it_caKeyUpdateInfo		302
-#define OBJ_id_it_caKeyUpdateInfo		OBJ_id_it,5L
-
-#define SN_id_it_currentCRL		"id-it-currentCRL"
-#define NID_id_it_currentCRL		303
-#define OBJ_id_it_currentCRL		OBJ_id_it,6L
-
-#define SN_id_it_unsupportedOIDs		"id-it-unsupportedOIDs"
-#define NID_id_it_unsupportedOIDs		304
-#define OBJ_id_it_unsupportedOIDs		OBJ_id_it,7L
-
-#define SN_id_it_subscriptionRequest		"id-it-subscriptionRequest"
-#define NID_id_it_subscriptionRequest		305
-#define OBJ_id_it_subscriptionRequest		OBJ_id_it,8L
-
-#define SN_id_it_subscriptionResponse		"id-it-subscriptionResponse"
-#define NID_id_it_subscriptionResponse		306
-#define OBJ_id_it_subscriptionResponse		OBJ_id_it,9L
-
-#define SN_id_it_keyPairParamReq		"id-it-keyPairParamReq"
-#define NID_id_it_keyPairParamReq		307
-#define OBJ_id_it_keyPairParamReq		OBJ_id_it,10L
-
-#define SN_id_it_keyPairParamRep		"id-it-keyPairParamRep"
-#define NID_id_it_keyPairParamRep		308
-#define OBJ_id_it_keyPairParamRep		OBJ_id_it,11L
-
-#define SN_id_it_revPassphrase		"id-it-revPassphrase"
-#define NID_id_it_revPassphrase		309
-#define OBJ_id_it_revPassphrase		OBJ_id_it,12L
-
-#define SN_id_it_implicitConfirm		"id-it-implicitConfirm"
-#define NID_id_it_implicitConfirm		310
-#define OBJ_id_it_implicitConfirm		OBJ_id_it,13L
-
-#define SN_id_it_confirmWaitTime		"id-it-confirmWaitTime"
-#define NID_id_it_confirmWaitTime		311
-#define OBJ_id_it_confirmWaitTime		OBJ_id_it,14L
-
-#define SN_id_it_origPKIMessage		"id-it-origPKIMessage"
-#define NID_id_it_origPKIMessage		312
-#define OBJ_id_it_origPKIMessage		OBJ_id_it,15L
-
-#define SN_id_it_suppLangTags		"id-it-suppLangTags"
-#define NID_id_it_suppLangTags		784
-#define OBJ_id_it_suppLangTags		OBJ_id_it,16L
-
-#define SN_id_regCtrl		"id-regCtrl"
-#define NID_id_regCtrl		313
-#define OBJ_id_regCtrl		OBJ_id_pkip,1L
-
-#define SN_id_regInfo		"id-regInfo"
-#define NID_id_regInfo		314
-#define OBJ_id_regInfo		OBJ_id_pkip,2L
-
-#define SN_id_regCtrl_regToken		"id-regCtrl-regToken"
-#define NID_id_regCtrl_regToken		315
-#define OBJ_id_regCtrl_regToken		OBJ_id_regCtrl,1L
-
-#define SN_id_regCtrl_authenticator		"id-regCtrl-authenticator"
-#define NID_id_regCtrl_authenticator		316
-#define OBJ_id_regCtrl_authenticator		OBJ_id_regCtrl,2L
-
-#define SN_id_regCtrl_pkiPublicationInfo		"id-regCtrl-pkiPublicationInfo"
-#define NID_id_regCtrl_pkiPublicationInfo		317
-#define OBJ_id_regCtrl_pkiPublicationInfo		OBJ_id_regCtrl,3L
-
-#define SN_id_regCtrl_pkiArchiveOptions		"id-regCtrl-pkiArchiveOptions"
-#define NID_id_regCtrl_pkiArchiveOptions		318
-#define OBJ_id_regCtrl_pkiArchiveOptions		OBJ_id_regCtrl,4L
-
-#define SN_id_regCtrl_oldCertID		"id-regCtrl-oldCertID"
-#define NID_id_regCtrl_oldCertID		319
-#define OBJ_id_regCtrl_oldCertID		OBJ_id_regCtrl,5L
-
-#define SN_id_regCtrl_protocolEncrKey		"id-regCtrl-protocolEncrKey"
-#define NID_id_regCtrl_protocolEncrKey		320
-#define OBJ_id_regCtrl_protocolEncrKey		OBJ_id_regCtrl,6L
-
-#define SN_id_regInfo_utf8Pairs		"id-regInfo-utf8Pairs"
-#define NID_id_regInfo_utf8Pairs		321
-#define OBJ_id_regInfo_utf8Pairs		OBJ_id_regInfo,1L
-
-#define SN_id_regInfo_certReq		"id-regInfo-certReq"
-#define NID_id_regInfo_certReq		322
-#define OBJ_id_regInfo_certReq		OBJ_id_regInfo,2L
-
-#define SN_id_alg_des40		"id-alg-des40"
-#define NID_id_alg_des40		323
-#define OBJ_id_alg_des40		OBJ_id_alg,1L
-
-#define SN_id_alg_noSignature		"id-alg-noSignature"
-#define NID_id_alg_noSignature		324
-#define OBJ_id_alg_noSignature		OBJ_id_alg,2L
-
-#define SN_id_alg_dh_sig_hmac_sha1		"id-alg-dh-sig-hmac-sha1"
-#define NID_id_alg_dh_sig_hmac_sha1		325
-#define OBJ_id_alg_dh_sig_hmac_sha1		OBJ_id_alg,3L
-
-#define SN_id_alg_dh_pop		"id-alg-dh-pop"
-#define NID_id_alg_dh_pop		326
-#define OBJ_id_alg_dh_pop		OBJ_id_alg,4L
-
-#define SN_id_cmc_statusInfo		"id-cmc-statusInfo"
-#define NID_id_cmc_statusInfo		327
-#define OBJ_id_cmc_statusInfo		OBJ_id_cmc,1L
-
-#define SN_id_cmc_identification		"id-cmc-identification"
-#define NID_id_cmc_identification		328
-#define OBJ_id_cmc_identification		OBJ_id_cmc,2L
-
-#define SN_id_cmc_identityProof		"id-cmc-identityProof"
-#define NID_id_cmc_identityProof		329
-#define OBJ_id_cmc_identityProof		OBJ_id_cmc,3L
-
-#define SN_id_cmc_dataReturn		"id-cmc-dataReturn"
-#define NID_id_cmc_dataReturn		330
-#define OBJ_id_cmc_dataReturn		OBJ_id_cmc,4L
-
-#define SN_id_cmc_transactionId		"id-cmc-transactionId"
-#define NID_id_cmc_transactionId		331
-#define OBJ_id_cmc_transactionId		OBJ_id_cmc,5L
-
-#define SN_id_cmc_senderNonce		"id-cmc-senderNonce"
-#define NID_id_cmc_senderNonce		332
-#define OBJ_id_cmc_senderNonce		OBJ_id_cmc,6L
-
-#define SN_id_cmc_recipientNonce		"id-cmc-recipientNonce"
-#define NID_id_cmc_recipientNonce		333
-#define OBJ_id_cmc_recipientNonce		OBJ_id_cmc,7L
-
-#define SN_id_cmc_addExtensions		"id-cmc-addExtensions"
-#define NID_id_cmc_addExtensions		334
-#define OBJ_id_cmc_addExtensions		OBJ_id_cmc,8L
-
-#define SN_id_cmc_encryptedPOP		"id-cmc-encryptedPOP"
-#define NID_id_cmc_encryptedPOP		335
-#define OBJ_id_cmc_encryptedPOP		OBJ_id_cmc,9L
-
-#define SN_id_cmc_decryptedPOP		"id-cmc-decryptedPOP"
-#define NID_id_cmc_decryptedPOP		336
-#define OBJ_id_cmc_decryptedPOP		OBJ_id_cmc,10L
-
-#define SN_id_cmc_lraPOPWitness		"id-cmc-lraPOPWitness"
-#define NID_id_cmc_lraPOPWitness		337
-#define OBJ_id_cmc_lraPOPWitness		OBJ_id_cmc,11L
-
-#define SN_id_cmc_getCert		"id-cmc-getCert"
-#define NID_id_cmc_getCert		338
-#define OBJ_id_cmc_getCert		OBJ_id_cmc,15L
-
-#define SN_id_cmc_getCRL		"id-cmc-getCRL"
-#define NID_id_cmc_getCRL		339
-#define OBJ_id_cmc_getCRL		OBJ_id_cmc,16L
-
-#define SN_id_cmc_revokeRequest		"id-cmc-revokeRequest"
-#define NID_id_cmc_revokeRequest		340
-#define OBJ_id_cmc_revokeRequest		OBJ_id_cmc,17L
-
-#define SN_id_cmc_regInfo		"id-cmc-regInfo"
-#define NID_id_cmc_regInfo		341
-#define OBJ_id_cmc_regInfo		OBJ_id_cmc,18L
-
-#define SN_id_cmc_responseInfo		"id-cmc-responseInfo"
-#define NID_id_cmc_responseInfo		342
-#define OBJ_id_cmc_responseInfo		OBJ_id_cmc,19L
-
-#define SN_id_cmc_queryPending		"id-cmc-queryPending"
-#define NID_id_cmc_queryPending		343
-#define OBJ_id_cmc_queryPending		OBJ_id_cmc,21L
-
-#define SN_id_cmc_popLinkRandom		"id-cmc-popLinkRandom"
-#define NID_id_cmc_popLinkRandom		344
-#define OBJ_id_cmc_popLinkRandom		OBJ_id_cmc,22L
-
-#define SN_id_cmc_popLinkWitness		"id-cmc-popLinkWitness"
-#define NID_id_cmc_popLinkWitness		345
-#define OBJ_id_cmc_popLinkWitness		OBJ_id_cmc,23L
-
-#define SN_id_cmc_confirmCertAcceptance		"id-cmc-confirmCertAcceptance"
-#define NID_id_cmc_confirmCertAcceptance		346
-#define OBJ_id_cmc_confirmCertAcceptance		OBJ_id_cmc,24L
-
-#define SN_id_on_personalData		"id-on-personalData"
-#define NID_id_on_personalData		347
-#define OBJ_id_on_personalData		OBJ_id_on,1L
-
-#define SN_id_on_permanentIdentifier		"id-on-permanentIdentifier"
-#define LN_id_on_permanentIdentifier		"Permanent Identifier"
-#define NID_id_on_permanentIdentifier		858
-#define OBJ_id_on_permanentIdentifier		OBJ_id_on,3L
-
-#define SN_id_pda_dateOfBirth		"id-pda-dateOfBirth"
-#define NID_id_pda_dateOfBirth		348
-#define OBJ_id_pda_dateOfBirth		OBJ_id_pda,1L
-
-#define SN_id_pda_placeOfBirth		"id-pda-placeOfBirth"
-#define NID_id_pda_placeOfBirth		349
-#define OBJ_id_pda_placeOfBirth		OBJ_id_pda,2L
-
-#define SN_id_pda_gender		"id-pda-gender"
-#define NID_id_pda_gender		351
-#define OBJ_id_pda_gender		OBJ_id_pda,3L
-
-#define SN_id_pda_countryOfCitizenship		"id-pda-countryOfCitizenship"
-#define NID_id_pda_countryOfCitizenship		352
-#define OBJ_id_pda_countryOfCitizenship		OBJ_id_pda,4L
-
-#define SN_id_pda_countryOfResidence		"id-pda-countryOfResidence"
-#define NID_id_pda_countryOfResidence		353
-#define OBJ_id_pda_countryOfResidence		OBJ_id_pda,5L
-
-#define SN_id_aca_authenticationInfo		"id-aca-authenticationInfo"
-#define NID_id_aca_authenticationInfo		354
-#define OBJ_id_aca_authenticationInfo		OBJ_id_aca,1L
-
-#define SN_id_aca_accessIdentity		"id-aca-accessIdentity"
-#define NID_id_aca_accessIdentity		355
-#define OBJ_id_aca_accessIdentity		OBJ_id_aca,2L
-
-#define SN_id_aca_chargingIdentity		"id-aca-chargingIdentity"
-#define NID_id_aca_chargingIdentity		356
-#define OBJ_id_aca_chargingIdentity		OBJ_id_aca,3L
-
-#define SN_id_aca_group		"id-aca-group"
-#define NID_id_aca_group		357
-#define OBJ_id_aca_group		OBJ_id_aca,4L
-
-#define SN_id_aca_role		"id-aca-role"
-#define NID_id_aca_role		358
-#define OBJ_id_aca_role		OBJ_id_aca,5L
-
-#define SN_id_aca_encAttrs		"id-aca-encAttrs"
-#define NID_id_aca_encAttrs		399
-#define OBJ_id_aca_encAttrs		OBJ_id_aca,6L
-
-#define SN_id_qcs_pkixQCSyntax_v1		"id-qcs-pkixQCSyntax-v1"
-#define NID_id_qcs_pkixQCSyntax_v1		359
-#define OBJ_id_qcs_pkixQCSyntax_v1		OBJ_id_qcs,1L
-
-#define SN_id_cct_crs		"id-cct-crs"
-#define NID_id_cct_crs		360
-#define OBJ_id_cct_crs		OBJ_id_cct,1L
-
-#define SN_id_cct_PKIData		"id-cct-PKIData"
-#define NID_id_cct_PKIData		361
-#define OBJ_id_cct_PKIData		OBJ_id_cct,2L
-
-#define SN_id_cct_PKIResponse		"id-cct-PKIResponse"
-#define NID_id_cct_PKIResponse		362
-#define OBJ_id_cct_PKIResponse		OBJ_id_cct,3L
-
-#define SN_id_ppl_anyLanguage		"id-ppl-anyLanguage"
-#define LN_id_ppl_anyLanguage		"Any language"
-#define NID_id_ppl_anyLanguage		664
-#define OBJ_id_ppl_anyLanguage		OBJ_id_ppl,0L
-
-#define SN_id_ppl_inheritAll		"id-ppl-inheritAll"
-#define LN_id_ppl_inheritAll		"Inherit all"
-#define NID_id_ppl_inheritAll		665
-#define OBJ_id_ppl_inheritAll		OBJ_id_ppl,1L
-
-#define SN_Independent		"id-ppl-independent"
-#define LN_Independent		"Independent"
-#define NID_Independent		667
-#define OBJ_Independent		OBJ_id_ppl,2L
-
-#define SN_ad_OCSP		"OCSP"
-#define LN_ad_OCSP		"OCSP"
-#define NID_ad_OCSP		178
-#define OBJ_ad_OCSP		OBJ_id_ad,1L
-
-#define SN_ad_ca_issuers		"caIssuers"
-#define LN_ad_ca_issuers		"CA Issuers"
-#define NID_ad_ca_issuers		179
-#define OBJ_ad_ca_issuers		OBJ_id_ad,2L
-
-#define SN_ad_timeStamping		"ad_timestamping"
-#define LN_ad_timeStamping		"AD Time Stamping"
-#define NID_ad_timeStamping		363
-#define OBJ_ad_timeStamping		OBJ_id_ad,3L
-
-#define SN_ad_dvcs		"AD_DVCS"
-#define LN_ad_dvcs		"ad dvcs"
-#define NID_ad_dvcs		364
-#define OBJ_ad_dvcs		OBJ_id_ad,4L
-
-#define SN_caRepository		"caRepository"
-#define LN_caRepository		"CA Repository"
-#define NID_caRepository		785
-#define OBJ_caRepository		OBJ_id_ad,5L
-
-#define OBJ_id_pkix_OCSP		OBJ_ad_OCSP
-
-#define SN_id_pkix_OCSP_basic		"basicOCSPResponse"
-#define LN_id_pkix_OCSP_basic		"Basic OCSP Response"
-#define NID_id_pkix_OCSP_basic		365
-#define OBJ_id_pkix_OCSP_basic		OBJ_id_pkix_OCSP,1L
-
-#define SN_id_pkix_OCSP_Nonce		"Nonce"
-#define LN_id_pkix_OCSP_Nonce		"OCSP Nonce"
-#define NID_id_pkix_OCSP_Nonce		366
-#define OBJ_id_pkix_OCSP_Nonce		OBJ_id_pkix_OCSP,2L
-
-#define SN_id_pkix_OCSP_CrlID		"CrlID"
-#define LN_id_pkix_OCSP_CrlID		"OCSP CRL ID"
-#define NID_id_pkix_OCSP_CrlID		367
-#define OBJ_id_pkix_OCSP_CrlID		OBJ_id_pkix_OCSP,3L
-
-#define SN_id_pkix_OCSP_acceptableResponses		"acceptableResponses"
-#define LN_id_pkix_OCSP_acceptableResponses		"Acceptable OCSP Responses"
-#define NID_id_pkix_OCSP_acceptableResponses		368
-#define OBJ_id_pkix_OCSP_acceptableResponses		OBJ_id_pkix_OCSP,4L
-
-#define SN_id_pkix_OCSP_noCheck		"noCheck"
-#define LN_id_pkix_OCSP_noCheck		"OCSP No Check"
-#define NID_id_pkix_OCSP_noCheck		369
-#define OBJ_id_pkix_OCSP_noCheck		OBJ_id_pkix_OCSP,5L
-
-#define SN_id_pkix_OCSP_archiveCutoff		"archiveCutoff"
-#define LN_id_pkix_OCSP_archiveCutoff		"OCSP Archive Cutoff"
-#define NID_id_pkix_OCSP_archiveCutoff		370
-#define OBJ_id_pkix_OCSP_archiveCutoff		OBJ_id_pkix_OCSP,6L
-
-#define SN_id_pkix_OCSP_serviceLocator		"serviceLocator"
-#define LN_id_pkix_OCSP_serviceLocator		"OCSP Service Locator"
-#define NID_id_pkix_OCSP_serviceLocator		371
-#define OBJ_id_pkix_OCSP_serviceLocator		OBJ_id_pkix_OCSP,7L
-
-#define SN_id_pkix_OCSP_extendedStatus		"extendedStatus"
-#define LN_id_pkix_OCSP_extendedStatus		"Extended OCSP Status"
-#define NID_id_pkix_OCSP_extendedStatus		372
-#define OBJ_id_pkix_OCSP_extendedStatus		OBJ_id_pkix_OCSP,8L
-
-#define SN_id_pkix_OCSP_valid		"valid"
-#define NID_id_pkix_OCSP_valid		373
-#define OBJ_id_pkix_OCSP_valid		OBJ_id_pkix_OCSP,9L
-
-#define SN_id_pkix_OCSP_path		"path"
-#define NID_id_pkix_OCSP_path		374
-#define OBJ_id_pkix_OCSP_path		OBJ_id_pkix_OCSP,10L
-
-#define SN_id_pkix_OCSP_trustRoot		"trustRoot"
-#define LN_id_pkix_OCSP_trustRoot		"Trust Root"
-#define NID_id_pkix_OCSP_trustRoot		375
-#define OBJ_id_pkix_OCSP_trustRoot		OBJ_id_pkix_OCSP,11L
-
-#define SN_algorithm		"algorithm"
-#define LN_algorithm		"algorithm"
-#define NID_algorithm		376
-#define OBJ_algorithm		1L,3L,14L,3L,2L
-
-#define SN_md5WithRSA		"RSA-NP-MD5"
-#define LN_md5WithRSA		"md5WithRSA"
-#define NID_md5WithRSA		104
-#define OBJ_md5WithRSA		OBJ_algorithm,3L
-
-#define SN_des_ecb		"DES-ECB"
-#define LN_des_ecb		"des-ecb"
-#define NID_des_ecb		29
-#define OBJ_des_ecb		OBJ_algorithm,6L
-
-#define SN_des_cbc		"DES-CBC"
-#define LN_des_cbc		"des-cbc"
-#define NID_des_cbc		31
-#define OBJ_des_cbc		OBJ_algorithm,7L
-
-#define SN_des_ofb64		"DES-OFB"
-#define LN_des_ofb64		"des-ofb"
-#define NID_des_ofb64		45
-#define OBJ_des_ofb64		OBJ_algorithm,8L
-
-#define SN_des_cfb64		"DES-CFB"
-#define LN_des_cfb64		"des-cfb"
-#define NID_des_cfb64		30
-#define OBJ_des_cfb64		OBJ_algorithm,9L
-
-#define SN_rsaSignature		"rsaSignature"
-#define NID_rsaSignature		377
-#define OBJ_rsaSignature		OBJ_algorithm,11L
-
-#define SN_dsa_2		"DSA-old"
-#define LN_dsa_2		"dsaEncryption-old"
-#define NID_dsa_2		67
-#define OBJ_dsa_2		OBJ_algorithm,12L
-
-#define SN_dsaWithSHA		"DSA-SHA"
-#define LN_dsaWithSHA		"dsaWithSHA"
-#define NID_dsaWithSHA		66
-#define OBJ_dsaWithSHA		OBJ_algorithm,13L
-
-#define SN_shaWithRSAEncryption		"RSA-SHA"
-#define LN_shaWithRSAEncryption		"shaWithRSAEncryption"
-#define NID_shaWithRSAEncryption		42
-#define OBJ_shaWithRSAEncryption		OBJ_algorithm,15L
-
-#define SN_des_ede_ecb		"DES-EDE"
-#define LN_des_ede_ecb		"des-ede"
-#define NID_des_ede_ecb		32
-#define OBJ_des_ede_ecb		OBJ_algorithm,17L
-
-#define SN_des_ede3_ecb		"DES-EDE3"
-#define LN_des_ede3_ecb		"des-ede3"
-#define NID_des_ede3_ecb		33
-
-#define SN_des_ede_cbc		"DES-EDE-CBC"
-#define LN_des_ede_cbc		"des-ede-cbc"
-#define NID_des_ede_cbc		43
-
-#define SN_des_ede_cfb64		"DES-EDE-CFB"
-#define LN_des_ede_cfb64		"des-ede-cfb"
-#define NID_des_ede_cfb64		60
-
-#define SN_des_ede3_cfb64		"DES-EDE3-CFB"
-#define LN_des_ede3_cfb64		"des-ede3-cfb"
-#define NID_des_ede3_cfb64		61
-
-#define SN_des_ede_ofb64		"DES-EDE-OFB"
-#define LN_des_ede_ofb64		"des-ede-ofb"
-#define NID_des_ede_ofb64		62
-
-#define SN_des_ede3_ofb64		"DES-EDE3-OFB"
-#define LN_des_ede3_ofb64		"des-ede3-ofb"
-#define NID_des_ede3_ofb64		63
-
-#define SN_desx_cbc		"DESX-CBC"
-#define LN_desx_cbc		"desx-cbc"
-#define NID_desx_cbc		80
-
-#define SN_sha		"SHA"
-#define LN_sha		"sha"
-#define NID_sha		41
-#define OBJ_sha		OBJ_algorithm,18L
-
-#define SN_sha1		"SHA1"
-#define LN_sha1		"sha1"
-#define NID_sha1		64
-#define OBJ_sha1		OBJ_algorithm,26L
-
-#define SN_dsaWithSHA1_2		"DSA-SHA1-old"
-#define LN_dsaWithSHA1_2		"dsaWithSHA1-old"
-#define NID_dsaWithSHA1_2		70
-#define OBJ_dsaWithSHA1_2		OBJ_algorithm,27L
-
-#define SN_sha1WithRSA		"RSA-SHA1-2"
-#define LN_sha1WithRSA		"sha1WithRSA"
-#define NID_sha1WithRSA		115
-#define OBJ_sha1WithRSA		OBJ_algorithm,29L
-
-#define SN_ripemd160		"RIPEMD160"
-#define LN_ripemd160		"ripemd160"
-#define NID_ripemd160		117
-#define OBJ_ripemd160		1L,3L,36L,3L,2L,1L
-
-#define SN_ripemd160WithRSA		"RSA-RIPEMD160"
-#define LN_ripemd160WithRSA		"ripemd160WithRSA"
-#define NID_ripemd160WithRSA		119
-#define OBJ_ripemd160WithRSA		1L,3L,36L,3L,3L,1L,2L
-
-#define SN_sxnet		"SXNetID"
-#define LN_sxnet		"Strong Extranet ID"
-#define NID_sxnet		143
-#define OBJ_sxnet		1L,3L,101L,1L,4L,1L
-
-#define SN_X500		"X500"
-#define LN_X500		"directory services (X.500)"
-#define NID_X500		11
-#define OBJ_X500		2L,5L
-
-#define SN_X509		"X509"
-#define NID_X509		12
-#define OBJ_X509		OBJ_X500,4L
-
-#define SN_commonName		"CN"
-#define LN_commonName		"commonName"
-#define NID_commonName		13
-#define OBJ_commonName		OBJ_X509,3L
-
-#define SN_surname		"SN"
-#define LN_surname		"surname"
-#define NID_surname		100
-#define OBJ_surname		OBJ_X509,4L
-
-#define LN_serialNumber		"serialNumber"
-#define NID_serialNumber		105
-#define OBJ_serialNumber		OBJ_X509,5L
-
-#define SN_countryName		"C"
-#define LN_countryName		"countryName"
-#define NID_countryName		14
-#define OBJ_countryName		OBJ_X509,6L
-
-#define SN_localityName		"L"
-#define LN_localityName		"localityName"
-#define NID_localityName		15
-#define OBJ_localityName		OBJ_X509,7L
-
-#define SN_stateOrProvinceName		"ST"
-#define LN_stateOrProvinceName		"stateOrProvinceName"
-#define NID_stateOrProvinceName		16
-#define OBJ_stateOrProvinceName		OBJ_X509,8L
-
-#define SN_streetAddress		"street"
-#define LN_streetAddress		"streetAddress"
-#define NID_streetAddress		660
-#define OBJ_streetAddress		OBJ_X509,9L
-
-#define SN_organizationName		"O"
-#define LN_organizationName		"organizationName"
-#define NID_organizationName		17
-#define OBJ_organizationName		OBJ_X509,10L
-
-#define SN_organizationalUnitName		"OU"
-#define LN_organizationalUnitName		"organizationalUnitName"
-#define NID_organizationalUnitName		18
-#define OBJ_organizationalUnitName		OBJ_X509,11L
-
-#define SN_title		"title"
-#define LN_title		"title"
-#define NID_title		106
-#define OBJ_title		OBJ_X509,12L
-
-#define LN_description		"description"
-#define NID_description		107
-#define OBJ_description		OBJ_X509,13L
-
-#define LN_searchGuide		"searchGuide"
-#define NID_searchGuide		859
-#define OBJ_searchGuide		OBJ_X509,14L
-
-#define LN_businessCategory		"businessCategory"
-#define NID_businessCategory		860
-#define OBJ_businessCategory		OBJ_X509,15L
-
-#define LN_postalAddress		"postalAddress"
-#define NID_postalAddress		861
-#define OBJ_postalAddress		OBJ_X509,16L
-
-#define LN_postalCode		"postalCode"
-#define NID_postalCode		661
-#define OBJ_postalCode		OBJ_X509,17L
-
-#define LN_postOfficeBox		"postOfficeBox"
-#define NID_postOfficeBox		862
-#define OBJ_postOfficeBox		OBJ_X509,18L
-
-#define LN_physicalDeliveryOfficeName		"physicalDeliveryOfficeName"
-#define NID_physicalDeliveryOfficeName		863
-#define OBJ_physicalDeliveryOfficeName		OBJ_X509,19L
-
-#define LN_telephoneNumber		"telephoneNumber"
-#define NID_telephoneNumber		864
-#define OBJ_telephoneNumber		OBJ_X509,20L
-
-#define LN_telexNumber		"telexNumber"
-#define NID_telexNumber		865
-#define OBJ_telexNumber		OBJ_X509,21L
-
-#define LN_teletexTerminalIdentifier		"teletexTerminalIdentifier"
-#define NID_teletexTerminalIdentifier		866
-#define OBJ_teletexTerminalIdentifier		OBJ_X509,22L
-
-#define LN_facsimileTelephoneNumber		"facsimileTelephoneNumber"
-#define NID_facsimileTelephoneNumber		867
-#define OBJ_facsimileTelephoneNumber		OBJ_X509,23L
-
-#define LN_x121Address		"x121Address"
-#define NID_x121Address		868
-#define OBJ_x121Address		OBJ_X509,24L
-
-#define LN_internationaliSDNNumber		"internationaliSDNNumber"
-#define NID_internationaliSDNNumber		869
-#define OBJ_internationaliSDNNumber		OBJ_X509,25L
-
-#define LN_registeredAddress		"registeredAddress"
-#define NID_registeredAddress		870
-#define OBJ_registeredAddress		OBJ_X509,26L
-
-#define LN_destinationIndicator		"destinationIndicator"
-#define NID_destinationIndicator		871
-#define OBJ_destinationIndicator		OBJ_X509,27L
-
-#define LN_preferredDeliveryMethod		"preferredDeliveryMethod"
-#define NID_preferredDeliveryMethod		872
-#define OBJ_preferredDeliveryMethod		OBJ_X509,28L
-
-#define LN_presentationAddress		"presentationAddress"
-#define NID_presentationAddress		873
-#define OBJ_presentationAddress		OBJ_X509,29L
-
-#define LN_supportedApplicationContext		"supportedApplicationContext"
-#define NID_supportedApplicationContext		874
-#define OBJ_supportedApplicationContext		OBJ_X509,30L
-
-#define SN_member		"member"
-#define NID_member		875
-#define OBJ_member		OBJ_X509,31L
-
-#define SN_owner		"owner"
-#define NID_owner		876
-#define OBJ_owner		OBJ_X509,32L
-
-#define LN_roleOccupant		"roleOccupant"
-#define NID_roleOccupant		877
-#define OBJ_roleOccupant		OBJ_X509,33L
-
-#define SN_seeAlso		"seeAlso"
-#define NID_seeAlso		878
-#define OBJ_seeAlso		OBJ_X509,34L
-
-#define LN_userPassword		"userPassword"
-#define NID_userPassword		879
-#define OBJ_userPassword		OBJ_X509,35L
-
-#define LN_userCertificate		"userCertificate"
-#define NID_userCertificate		880
-#define OBJ_userCertificate		OBJ_X509,36L
-
-#define LN_cACertificate		"cACertificate"
-#define NID_cACertificate		881
-#define OBJ_cACertificate		OBJ_X509,37L
-
-#define LN_authorityRevocationList		"authorityRevocationList"
-#define NID_authorityRevocationList		882
-#define OBJ_authorityRevocationList		OBJ_X509,38L
-
-#define LN_certificateRevocationList		"certificateRevocationList"
-#define NID_certificateRevocationList		883
-#define OBJ_certificateRevocationList		OBJ_X509,39L
-
-#define LN_crossCertificatePair		"crossCertificatePair"
-#define NID_crossCertificatePair		884
-#define OBJ_crossCertificatePair		OBJ_X509,40L
-
-#define SN_name		"name"
-#define LN_name		"name"
-#define NID_name		173
-#define OBJ_name		OBJ_X509,41L
-
-#define SN_givenName		"GN"
-#define LN_givenName		"givenName"
-#define NID_givenName		99
-#define OBJ_givenName		OBJ_X509,42L
-
-#define SN_initials		"initials"
-#define LN_initials		"initials"
-#define NID_initials		101
-#define OBJ_initials		OBJ_X509,43L
-
-#define LN_generationQualifier		"generationQualifier"
-#define NID_generationQualifier		509
-#define OBJ_generationQualifier		OBJ_X509,44L
-
-#define LN_x500UniqueIdentifier		"x500UniqueIdentifier"
-#define NID_x500UniqueIdentifier		503
-#define OBJ_x500UniqueIdentifier		OBJ_X509,45L
-
-#define SN_dnQualifier		"dnQualifier"
-#define LN_dnQualifier		"dnQualifier"
-#define NID_dnQualifier		174
-#define OBJ_dnQualifier		OBJ_X509,46L
-
-#define LN_enhancedSearchGuide		"enhancedSearchGuide"
-#define NID_enhancedSearchGuide		885
-#define OBJ_enhancedSearchGuide		OBJ_X509,47L
-
-#define LN_protocolInformation		"protocolInformation"
-#define NID_protocolInformation		886
-#define OBJ_protocolInformation		OBJ_X509,48L
-
-#define LN_distinguishedName		"distinguishedName"
-#define NID_distinguishedName		887
-#define OBJ_distinguishedName		OBJ_X509,49L
-
-#define LN_uniqueMember		"uniqueMember"
-#define NID_uniqueMember		888
-#define OBJ_uniqueMember		OBJ_X509,50L
-
-#define LN_houseIdentifier		"houseIdentifier"
-#define NID_houseIdentifier		889
-#define OBJ_houseIdentifier		OBJ_X509,51L
-
-#define LN_supportedAlgorithms		"supportedAlgorithms"
-#define NID_supportedAlgorithms		890
-#define OBJ_supportedAlgorithms		OBJ_X509,52L
-
-#define LN_deltaRevocationList		"deltaRevocationList"
-#define NID_deltaRevocationList		891
-#define OBJ_deltaRevocationList		OBJ_X509,53L
-
-#define SN_dmdName		"dmdName"
-#define NID_dmdName		892
-#define OBJ_dmdName		OBJ_X509,54L
-
-#define LN_pseudonym		"pseudonym"
-#define NID_pseudonym		510
-#define OBJ_pseudonym		OBJ_X509,65L
-
-#define SN_role		"role"
-#define LN_role		"role"
-#define NID_role		400
-#define OBJ_role		OBJ_X509,72L
-
-#define SN_X500algorithms		"X500algorithms"
-#define LN_X500algorithms		"directory services - algorithms"
-#define NID_X500algorithms		378
-#define OBJ_X500algorithms		OBJ_X500,8L
-
-#define SN_rsa		"RSA"
-#define LN_rsa		"rsa"
-#define NID_rsa		19
-#define OBJ_rsa		OBJ_X500algorithms,1L,1L
-
-#define SN_mdc2WithRSA		"RSA-MDC2"
-#define LN_mdc2WithRSA		"mdc2WithRSA"
-#define NID_mdc2WithRSA		96
-#define OBJ_mdc2WithRSA		OBJ_X500algorithms,3L,100L
-
-#define SN_mdc2		"MDC2"
-#define LN_mdc2		"mdc2"
-#define NID_mdc2		95
-#define OBJ_mdc2		OBJ_X500algorithms,3L,101L
-
-#define SN_id_ce		"id-ce"
-#define NID_id_ce		81
-#define OBJ_id_ce		OBJ_X500,29L
-
-#define SN_subject_directory_attributes		"subjectDirectoryAttributes"
-#define LN_subject_directory_attributes		"X509v3 Subject Directory Attributes"
-#define NID_subject_directory_attributes		769
-#define OBJ_subject_directory_attributes		OBJ_id_ce,9L
-
-#define SN_subject_key_identifier		"subjectKeyIdentifier"
-#define LN_subject_key_identifier		"X509v3 Subject Key Identifier"
-#define NID_subject_key_identifier		82
-#define OBJ_subject_key_identifier		OBJ_id_ce,14L
-
-#define SN_key_usage		"keyUsage"
-#define LN_key_usage		"X509v3 Key Usage"
-#define NID_key_usage		83
-#define OBJ_key_usage		OBJ_id_ce,15L
-
-#define SN_private_key_usage_period		"privateKeyUsagePeriod"
-#define LN_private_key_usage_period		"X509v3 Private Key Usage Period"
-#define NID_private_key_usage_period		84
-#define OBJ_private_key_usage_period		OBJ_id_ce,16L
-
-#define SN_subject_alt_name		"subjectAltName"
-#define LN_subject_alt_name		"X509v3 Subject Alternative Name"
-#define NID_subject_alt_name		85
-#define OBJ_subject_alt_name		OBJ_id_ce,17L
-
-#define SN_issuer_alt_name		"issuerAltName"
-#define LN_issuer_alt_name		"X509v3 Issuer Alternative Name"
-#define NID_issuer_alt_name		86
-#define OBJ_issuer_alt_name		OBJ_id_ce,18L
-
-#define SN_basic_constraints		"basicConstraints"
-#define LN_basic_constraints		"X509v3 Basic Constraints"
-#define NID_basic_constraints		87
-#define OBJ_basic_constraints		OBJ_id_ce,19L
-
-#define SN_crl_number		"crlNumber"
-#define LN_crl_number		"X509v3 CRL Number"
-#define NID_crl_number		88
-#define OBJ_crl_number		OBJ_id_ce,20L
-
-#define SN_crl_reason		"CRLReason"
-#define LN_crl_reason		"X509v3 CRL Reason Code"
-#define NID_crl_reason		141
-#define OBJ_crl_reason		OBJ_id_ce,21L
-
-#define SN_invalidity_date		"invalidityDate"
-#define LN_invalidity_date		"Invalidity Date"
-#define NID_invalidity_date		142
-#define OBJ_invalidity_date		OBJ_id_ce,24L
-
-#define SN_delta_crl		"deltaCRL"
-#define LN_delta_crl		"X509v3 Delta CRL Indicator"
-#define NID_delta_crl		140
-#define OBJ_delta_crl		OBJ_id_ce,27L
-
-#define SN_issuing_distribution_point		"issuingDistributionPoint"
-#define LN_issuing_distribution_point		"X509v3 Issuing Distribution Point"
-#define NID_issuing_distribution_point		770
-#define OBJ_issuing_distribution_point		OBJ_id_ce,28L
-
-#define SN_certificate_issuer		"certificateIssuer"
-#define LN_certificate_issuer		"X509v3 Certificate Issuer"
-#define NID_certificate_issuer		771
-#define OBJ_certificate_issuer		OBJ_id_ce,29L
-
-#define SN_name_constraints		"nameConstraints"
-#define LN_name_constraints		"X509v3 Name Constraints"
-#define NID_name_constraints		666
-#define OBJ_name_constraints		OBJ_id_ce,30L
-
-#define SN_crl_distribution_points		"crlDistributionPoints"
-#define LN_crl_distribution_points		"X509v3 CRL Distribution Points"
-#define NID_crl_distribution_points		103
-#define OBJ_crl_distribution_points		OBJ_id_ce,31L
-
-#define SN_certificate_policies		"certificatePolicies"
-#define LN_certificate_policies		"X509v3 Certificate Policies"
-#define NID_certificate_policies		89
-#define OBJ_certificate_policies		OBJ_id_ce,32L
-
-#define SN_any_policy		"anyPolicy"
-#define LN_any_policy		"X509v3 Any Policy"
-#define NID_any_policy		746
-#define OBJ_any_policy		OBJ_certificate_policies,0L
-
-#define SN_policy_mappings		"policyMappings"
-#define LN_policy_mappings		"X509v3 Policy Mappings"
-#define NID_policy_mappings		747
-#define OBJ_policy_mappings		OBJ_id_ce,33L
-
-#define SN_authority_key_identifier		"authorityKeyIdentifier"
-#define LN_authority_key_identifier		"X509v3 Authority Key Identifier"
-#define NID_authority_key_identifier		90
-#define OBJ_authority_key_identifier		OBJ_id_ce,35L
-
-#define SN_policy_constraints		"policyConstraints"
-#define LN_policy_constraints		"X509v3 Policy Constraints"
-#define NID_policy_constraints		401
-#define OBJ_policy_constraints		OBJ_id_ce,36L
-
-#define SN_ext_key_usage		"extendedKeyUsage"
-#define LN_ext_key_usage		"X509v3 Extended Key Usage"
-#define NID_ext_key_usage		126
-#define OBJ_ext_key_usage		OBJ_id_ce,37L
-
-#define SN_freshest_crl		"freshestCRL"
-#define LN_freshest_crl		"X509v3 Freshest CRL"
-#define NID_freshest_crl		857
-#define OBJ_freshest_crl		OBJ_id_ce,46L
-
-#define SN_inhibit_any_policy		"inhibitAnyPolicy"
-#define LN_inhibit_any_policy		"X509v3 Inhibit Any Policy"
-#define NID_inhibit_any_policy		748
-#define OBJ_inhibit_any_policy		OBJ_id_ce,54L
-
-#define SN_target_information		"targetInformation"
-#define LN_target_information		"X509v3 AC Targeting"
-#define NID_target_information		402
-#define OBJ_target_information		OBJ_id_ce,55L
-
-#define SN_no_rev_avail		"noRevAvail"
-#define LN_no_rev_avail		"X509v3 No Revocation Available"
-#define NID_no_rev_avail		403
-#define OBJ_no_rev_avail		OBJ_id_ce,56L
-
-#define SN_anyExtendedKeyUsage		"anyExtendedKeyUsage"
-#define LN_anyExtendedKeyUsage		"Any Extended Key Usage"
-#define NID_anyExtendedKeyUsage		910
-#define OBJ_anyExtendedKeyUsage		OBJ_ext_key_usage,0L
-
-#define SN_netscape		"Netscape"
-#define LN_netscape		"Netscape Communications Corp."
-#define NID_netscape		57
-#define OBJ_netscape		2L,16L,840L,1L,113730L
-
-#define SN_netscape_cert_extension		"nsCertExt"
-#define LN_netscape_cert_extension		"Netscape Certificate Extension"
-#define NID_netscape_cert_extension		58
-#define OBJ_netscape_cert_extension		OBJ_netscape,1L
-
-#define SN_netscape_data_type		"nsDataType"
-#define LN_netscape_data_type		"Netscape Data Type"
-#define NID_netscape_data_type		59
-#define OBJ_netscape_data_type		OBJ_netscape,2L
-
-#define SN_netscape_cert_type		"nsCertType"
-#define LN_netscape_cert_type		"Netscape Cert Type"
-#define NID_netscape_cert_type		71
-#define OBJ_netscape_cert_type		OBJ_netscape_cert_extension,1L
-
-#define SN_netscape_base_url		"nsBaseUrl"
-#define LN_netscape_base_url		"Netscape Base Url"
-#define NID_netscape_base_url		72
-#define OBJ_netscape_base_url		OBJ_netscape_cert_extension,2L
-
-#define SN_netscape_revocation_url		"nsRevocationUrl"
-#define LN_netscape_revocation_url		"Netscape Revocation Url"
-#define NID_netscape_revocation_url		73
-#define OBJ_netscape_revocation_url		OBJ_netscape_cert_extension,3L
-
-#define SN_netscape_ca_revocation_url		"nsCaRevocationUrl"
-#define LN_netscape_ca_revocation_url		"Netscape CA Revocation Url"
-#define NID_netscape_ca_revocation_url		74
-#define OBJ_netscape_ca_revocation_url		OBJ_netscape_cert_extension,4L
-
-#define SN_netscape_renewal_url		"nsRenewalUrl"
-#define LN_netscape_renewal_url		"Netscape Renewal Url"
-#define NID_netscape_renewal_url		75
-#define OBJ_netscape_renewal_url		OBJ_netscape_cert_extension,7L
-
-#define SN_netscape_ca_policy_url		"nsCaPolicyUrl"
-#define LN_netscape_ca_policy_url		"Netscape CA Policy Url"
-#define NID_netscape_ca_policy_url		76
-#define OBJ_netscape_ca_policy_url		OBJ_netscape_cert_extension,8L
-
-#define SN_netscape_ssl_server_name		"nsSslServerName"
-#define LN_netscape_ssl_server_name		"Netscape SSL Server Name"
-#define NID_netscape_ssl_server_name		77
-#define OBJ_netscape_ssl_server_name		OBJ_netscape_cert_extension,12L
-
-#define SN_netscape_comment		"nsComment"
-#define LN_netscape_comment		"Netscape Comment"
-#define NID_netscape_comment		78
-#define OBJ_netscape_comment		OBJ_netscape_cert_extension,13L
-
-#define SN_netscape_cert_sequence		"nsCertSequence"
-#define LN_netscape_cert_sequence		"Netscape Certificate Sequence"
-#define NID_netscape_cert_sequence		79
-#define OBJ_netscape_cert_sequence		OBJ_netscape_data_type,5L
-
-#define SN_ns_sgc		"nsSGC"
-#define LN_ns_sgc		"Netscape Server Gated Crypto"
-#define NID_ns_sgc		139
-#define OBJ_ns_sgc		OBJ_netscape,4L,1L
-
-#define SN_org		"ORG"
-#define LN_org		"org"
-#define NID_org		379
-#define OBJ_org		OBJ_iso,3L
-
-#define SN_dod		"DOD"
-#define LN_dod		"dod"
-#define NID_dod		380
-#define OBJ_dod		OBJ_org,6L
-
-#define SN_iana		"IANA"
-#define LN_iana		"iana"
-#define NID_iana		381
-#define OBJ_iana		OBJ_dod,1L
-
-#define OBJ_internet		OBJ_iana
-
-#define SN_Directory		"directory"
-#define LN_Directory		"Directory"
-#define NID_Directory		382
-#define OBJ_Directory		OBJ_internet,1L
-
-#define SN_Management		"mgmt"
-#define LN_Management		"Management"
-#define NID_Management		383
-#define OBJ_Management		OBJ_internet,2L
-
-#define SN_Experimental		"experimental"
-#define LN_Experimental		"Experimental"
-#define NID_Experimental		384
-#define OBJ_Experimental		OBJ_internet,3L
-
-#define SN_Private		"private"
-#define LN_Private		"Private"
-#define NID_Private		385
-#define OBJ_Private		OBJ_internet,4L
-
-#define SN_Security		"security"
-#define LN_Security		"Security"
-#define NID_Security		386
-#define OBJ_Security		OBJ_internet,5L
-
-#define SN_SNMPv2		"snmpv2"
-#define LN_SNMPv2		"SNMPv2"
-#define NID_SNMPv2		387
-#define OBJ_SNMPv2		OBJ_internet,6L
-
-#define LN_Mail		"Mail"
-#define NID_Mail		388
-#define OBJ_Mail		OBJ_internet,7L
-
-#define SN_Enterprises		"enterprises"
-#define LN_Enterprises		"Enterprises"
-#define NID_Enterprises		389
-#define OBJ_Enterprises		OBJ_Private,1L
-
-#define SN_dcObject		"dcobject"
-#define LN_dcObject		"dcObject"
-#define NID_dcObject		390
-#define OBJ_dcObject		OBJ_Enterprises,1466L,344L
-
-#define SN_mime_mhs		"mime-mhs"
-#define LN_mime_mhs		"MIME MHS"
-#define NID_mime_mhs		504
-#define OBJ_mime_mhs		OBJ_Mail,1L
-
-#define SN_mime_mhs_headings		"mime-mhs-headings"
-#define LN_mime_mhs_headings		"mime-mhs-headings"
-#define NID_mime_mhs_headings		505
-#define OBJ_mime_mhs_headings		OBJ_mime_mhs,1L
-
-#define SN_mime_mhs_bodies		"mime-mhs-bodies"
-#define LN_mime_mhs_bodies		"mime-mhs-bodies"
-#define NID_mime_mhs_bodies		506
-#define OBJ_mime_mhs_bodies		OBJ_mime_mhs,2L
-
-#define SN_id_hex_partial_message		"id-hex-partial-message"
-#define LN_id_hex_partial_message		"id-hex-partial-message"
-#define NID_id_hex_partial_message		507
-#define OBJ_id_hex_partial_message		OBJ_mime_mhs_headings,1L
-
-#define SN_id_hex_multipart_message		"id-hex-multipart-message"
-#define LN_id_hex_multipart_message		"id-hex-multipart-message"
-#define NID_id_hex_multipart_message		508
-#define OBJ_id_hex_multipart_message		OBJ_mime_mhs_headings,2L
-
-#define SN_zlib_compression		"ZLIB"
-#define LN_zlib_compression		"zlib compression"
-#define NID_zlib_compression		125
-#define OBJ_zlib_compression		OBJ_id_smime_alg,8L
-
-#define OBJ_csor		2L,16L,840L,1L,101L,3L
-
-#define OBJ_nistAlgorithms		OBJ_csor,4L
-
-#define OBJ_aes		OBJ_nistAlgorithms,1L
-
-#define SN_aes_128_ecb		"AES-128-ECB"
-#define LN_aes_128_ecb		"aes-128-ecb"
-#define NID_aes_128_ecb		418
-#define OBJ_aes_128_ecb		OBJ_aes,1L
-
-#define SN_aes_128_cbc		"AES-128-CBC"
-#define LN_aes_128_cbc		"aes-128-cbc"
-#define NID_aes_128_cbc		419
-#define OBJ_aes_128_cbc		OBJ_aes,2L
-
-#define SN_aes_128_ofb128		"AES-128-OFB"
-#define LN_aes_128_ofb128		"aes-128-ofb"
-#define NID_aes_128_ofb128		420
-#define OBJ_aes_128_ofb128		OBJ_aes,3L
-
-#define SN_aes_128_cfb128		"AES-128-CFB"
-#define LN_aes_128_cfb128		"aes-128-cfb"
-#define NID_aes_128_cfb128		421
-#define OBJ_aes_128_cfb128		OBJ_aes,4L
-
-#define SN_id_aes128_wrap		"id-aes128-wrap"
-#define NID_id_aes128_wrap		788
-#define OBJ_id_aes128_wrap		OBJ_aes,5L
-
-#define SN_aes_128_gcm		"id-aes128-GCM"
-#define LN_aes_128_gcm		"aes-128-gcm"
-#define NID_aes_128_gcm		895
-#define OBJ_aes_128_gcm		OBJ_aes,6L
-
-#define SN_aes_128_ccm		"id-aes128-CCM"
-#define LN_aes_128_ccm		"aes-128-ccm"
-#define NID_aes_128_ccm		896
-#define OBJ_aes_128_ccm		OBJ_aes,7L
-
-#define SN_id_aes128_wrap_pad		"id-aes128-wrap-pad"
-#define NID_id_aes128_wrap_pad		897
-#define OBJ_id_aes128_wrap_pad		OBJ_aes,8L
-
-#define SN_aes_192_ecb		"AES-192-ECB"
-#define LN_aes_192_ecb		"aes-192-ecb"
-#define NID_aes_192_ecb		422
-#define OBJ_aes_192_ecb		OBJ_aes,21L
-
-#define SN_aes_192_cbc		"AES-192-CBC"
-#define LN_aes_192_cbc		"aes-192-cbc"
-#define NID_aes_192_cbc		423
-#define OBJ_aes_192_cbc		OBJ_aes,22L
-
-#define SN_aes_192_ofb128		"AES-192-OFB"
-#define LN_aes_192_ofb128		"aes-192-ofb"
-#define NID_aes_192_ofb128		424
-#define OBJ_aes_192_ofb128		OBJ_aes,23L
-
-#define SN_aes_192_cfb128		"AES-192-CFB"
-#define LN_aes_192_cfb128		"aes-192-cfb"
-#define NID_aes_192_cfb128		425
-#define OBJ_aes_192_cfb128		OBJ_aes,24L
-
-#define SN_id_aes192_wrap		"id-aes192-wrap"
-#define NID_id_aes192_wrap		789
-#define OBJ_id_aes192_wrap		OBJ_aes,25L
-
-#define SN_aes_192_gcm		"id-aes192-GCM"
-#define LN_aes_192_gcm		"aes-192-gcm"
-#define NID_aes_192_gcm		898
-#define OBJ_aes_192_gcm		OBJ_aes,26L
-
-#define SN_aes_192_ccm		"id-aes192-CCM"
-#define LN_aes_192_ccm		"aes-192-ccm"
-#define NID_aes_192_ccm		899
-#define OBJ_aes_192_ccm		OBJ_aes,27L
-
-#define SN_id_aes192_wrap_pad		"id-aes192-wrap-pad"
-#define NID_id_aes192_wrap_pad		900
-#define OBJ_id_aes192_wrap_pad		OBJ_aes,28L
-
-#define SN_aes_256_ecb		"AES-256-ECB"
-#define LN_aes_256_ecb		"aes-256-ecb"
-#define NID_aes_256_ecb		426
-#define OBJ_aes_256_ecb		OBJ_aes,41L
-
-#define SN_aes_256_cbc		"AES-256-CBC"
-#define LN_aes_256_cbc		"aes-256-cbc"
-#define NID_aes_256_cbc		427
-#define OBJ_aes_256_cbc		OBJ_aes,42L
-
-#define SN_aes_256_ofb128		"AES-256-OFB"
-#define LN_aes_256_ofb128		"aes-256-ofb"
-#define NID_aes_256_ofb128		428
-#define OBJ_aes_256_ofb128		OBJ_aes,43L
-
-#define SN_aes_256_cfb128		"AES-256-CFB"
-#define LN_aes_256_cfb128		"aes-256-cfb"
-#define NID_aes_256_cfb128		429
-#define OBJ_aes_256_cfb128		OBJ_aes,44L
-
-#define SN_id_aes256_wrap		"id-aes256-wrap"
-#define NID_id_aes256_wrap		790
-#define OBJ_id_aes256_wrap		OBJ_aes,45L
-
-#define SN_aes_256_gcm		"id-aes256-GCM"
-#define LN_aes_256_gcm		"aes-256-gcm"
-#define NID_aes_256_gcm		901
-#define OBJ_aes_256_gcm		OBJ_aes,46L
-
-#define SN_aes_256_ccm		"id-aes256-CCM"
-#define LN_aes_256_ccm		"aes-256-ccm"
-#define NID_aes_256_ccm		902
-#define OBJ_aes_256_ccm		OBJ_aes,47L
-
-#define SN_id_aes256_wrap_pad		"id-aes256-wrap-pad"
-#define NID_id_aes256_wrap_pad		903
-#define OBJ_id_aes256_wrap_pad		OBJ_aes,48L
-
-#define SN_aes_128_cfb1		"AES-128-CFB1"
-#define LN_aes_128_cfb1		"aes-128-cfb1"
-#define NID_aes_128_cfb1		650
-
-#define SN_aes_192_cfb1		"AES-192-CFB1"
-#define LN_aes_192_cfb1		"aes-192-cfb1"
-#define NID_aes_192_cfb1		651
-
-#define SN_aes_256_cfb1		"AES-256-CFB1"
-#define LN_aes_256_cfb1		"aes-256-cfb1"
-#define NID_aes_256_cfb1		652
-
-#define SN_aes_128_cfb8		"AES-128-CFB8"
-#define LN_aes_128_cfb8		"aes-128-cfb8"
-#define NID_aes_128_cfb8		653
-
-#define SN_aes_192_cfb8		"AES-192-CFB8"
-#define LN_aes_192_cfb8		"aes-192-cfb8"
-#define NID_aes_192_cfb8		654
-
-#define SN_aes_256_cfb8		"AES-256-CFB8"
-#define LN_aes_256_cfb8		"aes-256-cfb8"
-#define NID_aes_256_cfb8		655
-
-#define SN_aes_128_ctr		"AES-128-CTR"
-#define LN_aes_128_ctr		"aes-128-ctr"
-#define NID_aes_128_ctr		904
-
-#define SN_aes_192_ctr		"AES-192-CTR"
-#define LN_aes_192_ctr		"aes-192-ctr"
-#define NID_aes_192_ctr		905
-
-#define SN_aes_256_ctr		"AES-256-CTR"
-#define LN_aes_256_ctr		"aes-256-ctr"
-#define NID_aes_256_ctr		906
-
-#define SN_aes_128_xts		"AES-128-XTS"
-#define LN_aes_128_xts		"aes-128-xts"
-#define NID_aes_128_xts		913
-
-#define SN_aes_256_xts		"AES-256-XTS"
-#define LN_aes_256_xts		"aes-256-xts"
-#define NID_aes_256_xts		914
-
-#define SN_des_cfb1		"DES-CFB1"
-#define LN_des_cfb1		"des-cfb1"
-#define NID_des_cfb1		656
-
-#define SN_des_cfb8		"DES-CFB8"
-#define LN_des_cfb8		"des-cfb8"
-#define NID_des_cfb8		657
-
-#define SN_des_ede3_cfb1		"DES-EDE3-CFB1"
-#define LN_des_ede3_cfb1		"des-ede3-cfb1"
-#define NID_des_ede3_cfb1		658
-
-#define SN_des_ede3_cfb8		"DES-EDE3-CFB8"
-#define LN_des_ede3_cfb8		"des-ede3-cfb8"
-#define NID_des_ede3_cfb8		659
-
-#define OBJ_nist_hashalgs		OBJ_nistAlgorithms,2L
-
-#define SN_sha256		"SHA256"
-#define LN_sha256		"sha256"
-#define NID_sha256		672
-#define OBJ_sha256		OBJ_nist_hashalgs,1L
-
-#define SN_sha384		"SHA384"
-#define LN_sha384		"sha384"
-#define NID_sha384		673
-#define OBJ_sha384		OBJ_nist_hashalgs,2L
-
-#define SN_sha512		"SHA512"
-#define LN_sha512		"sha512"
-#define NID_sha512		674
-#define OBJ_sha512		OBJ_nist_hashalgs,3L
-
-#define SN_sha224		"SHA224"
-#define LN_sha224		"sha224"
-#define NID_sha224		675
-#define OBJ_sha224		OBJ_nist_hashalgs,4L
-
-#define OBJ_dsa_with_sha2		OBJ_nistAlgorithms,3L
-
-#define SN_dsa_with_SHA224		"dsa_with_SHA224"
-#define NID_dsa_with_SHA224		802
-#define OBJ_dsa_with_SHA224		OBJ_dsa_with_sha2,1L
-
-#define SN_dsa_with_SHA256		"dsa_with_SHA256"
-#define NID_dsa_with_SHA256		803
-#define OBJ_dsa_with_SHA256		OBJ_dsa_with_sha2,2L
-
-#define SN_hold_instruction_code		"holdInstructionCode"
-#define LN_hold_instruction_code		"Hold Instruction Code"
-#define NID_hold_instruction_code		430
-#define OBJ_hold_instruction_code		OBJ_id_ce,23L
-
-#define OBJ_holdInstruction		OBJ_X9_57,2L
-
-#define SN_hold_instruction_none		"holdInstructionNone"
-#define LN_hold_instruction_none		"Hold Instruction None"
-#define NID_hold_instruction_none		431
-#define OBJ_hold_instruction_none		OBJ_holdInstruction,1L
-
-#define SN_hold_instruction_call_issuer		"holdInstructionCallIssuer"
-#define LN_hold_instruction_call_issuer		"Hold Instruction Call Issuer"
-#define NID_hold_instruction_call_issuer		432
-#define OBJ_hold_instruction_call_issuer		OBJ_holdInstruction,2L
-
-#define SN_hold_instruction_reject		"holdInstructionReject"
-#define LN_hold_instruction_reject		"Hold Instruction Reject"
-#define NID_hold_instruction_reject		433
-#define OBJ_hold_instruction_reject		OBJ_holdInstruction,3L
-
-#define SN_data		"data"
-#define NID_data		434
-#define OBJ_data		OBJ_itu_t,9L
-
-#define SN_pss		"pss"
-#define NID_pss		435
-#define OBJ_pss		OBJ_data,2342L
-
-#define SN_ucl		"ucl"
-#define NID_ucl		436
-#define OBJ_ucl		OBJ_pss,19200300L
-
-#define SN_pilot		"pilot"
-#define NID_pilot		437
-#define OBJ_pilot		OBJ_ucl,100L
-
-#define LN_pilotAttributeType		"pilotAttributeType"
-#define NID_pilotAttributeType		438
-#define OBJ_pilotAttributeType		OBJ_pilot,1L
-
-#define LN_pilotAttributeSyntax		"pilotAttributeSyntax"
-#define NID_pilotAttributeSyntax		439
-#define OBJ_pilotAttributeSyntax		OBJ_pilot,3L
-
-#define LN_pilotObjectClass		"pilotObjectClass"
-#define NID_pilotObjectClass		440
-#define OBJ_pilotObjectClass		OBJ_pilot,4L
-
-#define LN_pilotGroups		"pilotGroups"
-#define NID_pilotGroups		441
-#define OBJ_pilotGroups		OBJ_pilot,10L
-
-#define LN_iA5StringSyntax		"iA5StringSyntax"
-#define NID_iA5StringSyntax		442
-#define OBJ_iA5StringSyntax		OBJ_pilotAttributeSyntax,4L
-
-#define LN_caseIgnoreIA5StringSyntax		"caseIgnoreIA5StringSyntax"
-#define NID_caseIgnoreIA5StringSyntax		443
-#define OBJ_caseIgnoreIA5StringSyntax		OBJ_pilotAttributeSyntax,5L
-
-#define LN_pilotObject		"pilotObject"
-#define NID_pilotObject		444
-#define OBJ_pilotObject		OBJ_pilotObjectClass,3L
-
-#define LN_pilotPerson		"pilotPerson"
-#define NID_pilotPerson		445
-#define OBJ_pilotPerson		OBJ_pilotObjectClass,4L
-
-#define SN_account		"account"
-#define NID_account		446
-#define OBJ_account		OBJ_pilotObjectClass,5L
-
-#define SN_document		"document"
-#define NID_document		447
-#define OBJ_document		OBJ_pilotObjectClass,6L
-
-#define SN_room		"room"
-#define NID_room		448
-#define OBJ_room		OBJ_pilotObjectClass,7L
-
-#define LN_documentSeries		"documentSeries"
-#define NID_documentSeries		449
-#define OBJ_documentSeries		OBJ_pilotObjectClass,9L
-
-#define SN_Domain		"domain"
-#define LN_Domain		"Domain"
-#define NID_Domain		392
-#define OBJ_Domain		OBJ_pilotObjectClass,13L
-
-#define LN_rFC822localPart		"rFC822localPart"
-#define NID_rFC822localPart		450
-#define OBJ_rFC822localPart		OBJ_pilotObjectClass,14L
-
-#define LN_dNSDomain		"dNSDomain"
-#define NID_dNSDomain		451
-#define OBJ_dNSDomain		OBJ_pilotObjectClass,15L
-
-#define LN_domainRelatedObject		"domainRelatedObject"
-#define NID_domainRelatedObject		452
-#define OBJ_domainRelatedObject		OBJ_pilotObjectClass,17L
-
-#define LN_friendlyCountry		"friendlyCountry"
-#define NID_friendlyCountry		453
-#define OBJ_friendlyCountry		OBJ_pilotObjectClass,18L
-
-#define LN_simpleSecurityObject		"simpleSecurityObject"
-#define NID_simpleSecurityObject		454
-#define OBJ_simpleSecurityObject		OBJ_pilotObjectClass,19L
-
-#define LN_pilotOrganization		"pilotOrganization"
-#define NID_pilotOrganization		455
-#define OBJ_pilotOrganization		OBJ_pilotObjectClass,20L
-
-#define LN_pilotDSA		"pilotDSA"
-#define NID_pilotDSA		456
-#define OBJ_pilotDSA		OBJ_pilotObjectClass,21L
-
-#define LN_qualityLabelledData		"qualityLabelledData"
-#define NID_qualityLabelledData		457
-#define OBJ_qualityLabelledData		OBJ_pilotObjectClass,22L
-
-#define SN_userId		"UID"
-#define LN_userId		"userId"
-#define NID_userId		458
-#define OBJ_userId		OBJ_pilotAttributeType,1L
-
-#define LN_textEncodedORAddress		"textEncodedORAddress"
-#define NID_textEncodedORAddress		459
-#define OBJ_textEncodedORAddress		OBJ_pilotAttributeType,2L
-
-#define SN_rfc822Mailbox		"mail"
-#define LN_rfc822Mailbox		"rfc822Mailbox"
-#define NID_rfc822Mailbox		460
-#define OBJ_rfc822Mailbox		OBJ_pilotAttributeType,3L
-
-#define SN_info		"info"
-#define NID_info		461
-#define OBJ_info		OBJ_pilotAttributeType,4L
-
-#define LN_favouriteDrink		"favouriteDrink"
-#define NID_favouriteDrink		462
-#define OBJ_favouriteDrink		OBJ_pilotAttributeType,5L
-
-#define LN_roomNumber		"roomNumber"
-#define NID_roomNumber		463
-#define OBJ_roomNumber		OBJ_pilotAttributeType,6L
-
-#define SN_photo		"photo"
-#define NID_photo		464
-#define OBJ_photo		OBJ_pilotAttributeType,7L
-
-#define LN_userClass		"userClass"
-#define NID_userClass		465
-#define OBJ_userClass		OBJ_pilotAttributeType,8L
-
-#define SN_host		"host"
-#define NID_host		466
-#define OBJ_host		OBJ_pilotAttributeType,9L
-
-#define SN_manager		"manager"
-#define NID_manager		467
-#define OBJ_manager		OBJ_pilotAttributeType,10L
-
-#define LN_documentIdentifier		"documentIdentifier"
-#define NID_documentIdentifier		468
-#define OBJ_documentIdentifier		OBJ_pilotAttributeType,11L
-
-#define LN_documentTitle		"documentTitle"
-#define NID_documentTitle		469
-#define OBJ_documentTitle		OBJ_pilotAttributeType,12L
-
-#define LN_documentVersion		"documentVersion"
-#define NID_documentVersion		470
-#define OBJ_documentVersion		OBJ_pilotAttributeType,13L
-
-#define LN_documentAuthor		"documentAuthor"
-#define NID_documentAuthor		471
-#define OBJ_documentAuthor		OBJ_pilotAttributeType,14L
-
-#define LN_documentLocation		"documentLocation"
-#define NID_documentLocation		472
-#define OBJ_documentLocation		OBJ_pilotAttributeType,15L
-
-#define LN_homeTelephoneNumber		"homeTelephoneNumber"
-#define NID_homeTelephoneNumber		473
-#define OBJ_homeTelephoneNumber		OBJ_pilotAttributeType,20L
-
-#define SN_secretary		"secretary"
-#define NID_secretary		474
-#define OBJ_secretary		OBJ_pilotAttributeType,21L
-
-#define LN_otherMailbox		"otherMailbox"
-#define NID_otherMailbox		475
-#define OBJ_otherMailbox		OBJ_pilotAttributeType,22L
-
-#define LN_lastModifiedTime		"lastModifiedTime"
-#define NID_lastModifiedTime		476
-#define OBJ_lastModifiedTime		OBJ_pilotAttributeType,23L
-
-#define LN_lastModifiedBy		"lastModifiedBy"
-#define NID_lastModifiedBy		477
-#define OBJ_lastModifiedBy		OBJ_pilotAttributeType,24L
-
-#define SN_domainComponent		"DC"
-#define LN_domainComponent		"domainComponent"
-#define NID_domainComponent		391
-#define OBJ_domainComponent		OBJ_pilotAttributeType,25L
-
-#define LN_aRecord		"aRecord"
-#define NID_aRecord		478
-#define OBJ_aRecord		OBJ_pilotAttributeType,26L
-
-#define LN_pilotAttributeType27		"pilotAttributeType27"
-#define NID_pilotAttributeType27		479
-#define OBJ_pilotAttributeType27		OBJ_pilotAttributeType,27L
-
-#define LN_mXRecord		"mXRecord"
-#define NID_mXRecord		480
-#define OBJ_mXRecord		OBJ_pilotAttributeType,28L
-
-#define LN_nSRecord		"nSRecord"
-#define NID_nSRecord		481
-#define OBJ_nSRecord		OBJ_pilotAttributeType,29L
-
-#define LN_sOARecord		"sOARecord"
-#define NID_sOARecord		482
-#define OBJ_sOARecord		OBJ_pilotAttributeType,30L
-
-#define LN_cNAMERecord		"cNAMERecord"
-#define NID_cNAMERecord		483
-#define OBJ_cNAMERecord		OBJ_pilotAttributeType,31L
-
-#define LN_associatedDomain		"associatedDomain"
-#define NID_associatedDomain		484
-#define OBJ_associatedDomain		OBJ_pilotAttributeType,37L
-
-#define LN_associatedName		"associatedName"
-#define NID_associatedName		485
-#define OBJ_associatedName		OBJ_pilotAttributeType,38L
-
-#define LN_homePostalAddress		"homePostalAddress"
-#define NID_homePostalAddress		486
-#define OBJ_homePostalAddress		OBJ_pilotAttributeType,39L
-
-#define LN_personalTitle		"personalTitle"
-#define NID_personalTitle		487
-#define OBJ_personalTitle		OBJ_pilotAttributeType,40L
-
-#define LN_mobileTelephoneNumber		"mobileTelephoneNumber"
-#define NID_mobileTelephoneNumber		488
-#define OBJ_mobileTelephoneNumber		OBJ_pilotAttributeType,41L
-
-#define LN_pagerTelephoneNumber		"pagerTelephoneNumber"
-#define NID_pagerTelephoneNumber		489
-#define OBJ_pagerTelephoneNumber		OBJ_pilotAttributeType,42L
-
-#define LN_friendlyCountryName		"friendlyCountryName"
-#define NID_friendlyCountryName		490
-#define OBJ_friendlyCountryName		OBJ_pilotAttributeType,43L
-
-#define LN_organizationalStatus		"organizationalStatus"
-#define NID_organizationalStatus		491
-#define OBJ_organizationalStatus		OBJ_pilotAttributeType,45L
-
-#define LN_janetMailbox		"janetMailbox"
-#define NID_janetMailbox		492
-#define OBJ_janetMailbox		OBJ_pilotAttributeType,46L
-
-#define LN_mailPreferenceOption		"mailPreferenceOption"
-#define NID_mailPreferenceOption		493
-#define OBJ_mailPreferenceOption		OBJ_pilotAttributeType,47L
-
-#define LN_buildingName		"buildingName"
-#define NID_buildingName		494
-#define OBJ_buildingName		OBJ_pilotAttributeType,48L
-
-#define LN_dSAQuality		"dSAQuality"
-#define NID_dSAQuality		495
-#define OBJ_dSAQuality		OBJ_pilotAttributeType,49L
-
-#define LN_singleLevelQuality		"singleLevelQuality"
-#define NID_singleLevelQuality		496
-#define OBJ_singleLevelQuality		OBJ_pilotAttributeType,50L
-
-#define LN_subtreeMinimumQuality		"subtreeMinimumQuality"
-#define NID_subtreeMinimumQuality		497
-#define OBJ_subtreeMinimumQuality		OBJ_pilotAttributeType,51L
-
-#define LN_subtreeMaximumQuality		"subtreeMaximumQuality"
-#define NID_subtreeMaximumQuality		498
-#define OBJ_subtreeMaximumQuality		OBJ_pilotAttributeType,52L
-
-#define LN_personalSignature		"personalSignature"
-#define NID_personalSignature		499
-#define OBJ_personalSignature		OBJ_pilotAttributeType,53L
-
-#define LN_dITRedirect		"dITRedirect"
-#define NID_dITRedirect		500
-#define OBJ_dITRedirect		OBJ_pilotAttributeType,54L
-
-#define SN_audio		"audio"
-#define NID_audio		501
-#define OBJ_audio		OBJ_pilotAttributeType,55L
-
-#define LN_documentPublisher		"documentPublisher"
-#define NID_documentPublisher		502
-#define OBJ_documentPublisher		OBJ_pilotAttributeType,56L
-
-#define SN_id_set		"id-set"
-#define LN_id_set		"Secure Electronic Transactions"
-#define NID_id_set		512
-#define OBJ_id_set		OBJ_international_organizations,42L
-
-#define SN_set_ctype		"set-ctype"
-#define LN_set_ctype		"content types"
-#define NID_set_ctype		513
-#define OBJ_set_ctype		OBJ_id_set,0L
-
-#define SN_set_msgExt		"set-msgExt"
-#define LN_set_msgExt		"message extensions"
-#define NID_set_msgExt		514
-#define OBJ_set_msgExt		OBJ_id_set,1L
-
-#define SN_set_attr		"set-attr"
-#define NID_set_attr		515
-#define OBJ_set_attr		OBJ_id_set,3L
-
-#define SN_set_policy		"set-policy"
-#define NID_set_policy		516
-#define OBJ_set_policy		OBJ_id_set,5L
-
-#define SN_set_certExt		"set-certExt"
-#define LN_set_certExt		"certificate extensions"
-#define NID_set_certExt		517
-#define OBJ_set_certExt		OBJ_id_set,7L
-
-#define SN_set_brand		"set-brand"
-#define NID_set_brand		518
-#define OBJ_set_brand		OBJ_id_set,8L
-
-#define SN_setct_PANData		"setct-PANData"
-#define NID_setct_PANData		519
-#define OBJ_setct_PANData		OBJ_set_ctype,0L
-
-#define SN_setct_PANToken		"setct-PANToken"
-#define NID_setct_PANToken		520
-#define OBJ_setct_PANToken		OBJ_set_ctype,1L
-
-#define SN_setct_PANOnly		"setct-PANOnly"
-#define NID_setct_PANOnly		521
-#define OBJ_setct_PANOnly		OBJ_set_ctype,2L
-
-#define SN_setct_OIData		"setct-OIData"
-#define NID_setct_OIData		522
-#define OBJ_setct_OIData		OBJ_set_ctype,3L
-
-#define SN_setct_PI		"setct-PI"
-#define NID_setct_PI		523
-#define OBJ_setct_PI		OBJ_set_ctype,4L
-
-#define SN_setct_PIData		"setct-PIData"
-#define NID_setct_PIData		524
-#define OBJ_setct_PIData		OBJ_set_ctype,5L
-
-#define SN_setct_PIDataUnsigned		"setct-PIDataUnsigned"
-#define NID_setct_PIDataUnsigned		525
-#define OBJ_setct_PIDataUnsigned		OBJ_set_ctype,6L
-
-#define SN_setct_HODInput		"setct-HODInput"
-#define NID_setct_HODInput		526
-#define OBJ_setct_HODInput		OBJ_set_ctype,7L
-
-#define SN_setct_AuthResBaggage		"setct-AuthResBaggage"
-#define NID_setct_AuthResBaggage		527
-#define OBJ_setct_AuthResBaggage		OBJ_set_ctype,8L
-
-#define SN_setct_AuthRevReqBaggage		"setct-AuthRevReqBaggage"
-#define NID_setct_AuthRevReqBaggage		528
-#define OBJ_setct_AuthRevReqBaggage		OBJ_set_ctype,9L
-
-#define SN_setct_AuthRevResBaggage		"setct-AuthRevResBaggage"
-#define NID_setct_AuthRevResBaggage		529
-#define OBJ_setct_AuthRevResBaggage		OBJ_set_ctype,10L
-
-#define SN_setct_CapTokenSeq		"setct-CapTokenSeq"
-#define NID_setct_CapTokenSeq		530
-#define OBJ_setct_CapTokenSeq		OBJ_set_ctype,11L
-
-#define SN_setct_PInitResData		"setct-PInitResData"
-#define NID_setct_PInitResData		531
-#define OBJ_setct_PInitResData		OBJ_set_ctype,12L
-
-#define SN_setct_PI_TBS		"setct-PI-TBS"
-#define NID_setct_PI_TBS		532
-#define OBJ_setct_PI_TBS		OBJ_set_ctype,13L
-
-#define SN_setct_PResData		"setct-PResData"
-#define NID_setct_PResData		533
-#define OBJ_setct_PResData		OBJ_set_ctype,14L
-
-#define SN_setct_AuthReqTBS		"setct-AuthReqTBS"
-#define NID_setct_AuthReqTBS		534
-#define OBJ_setct_AuthReqTBS		OBJ_set_ctype,16L
-
-#define SN_setct_AuthResTBS		"setct-AuthResTBS"
-#define NID_setct_AuthResTBS		535
-#define OBJ_setct_AuthResTBS		OBJ_set_ctype,17L
-
-#define SN_setct_AuthResTBSX		"setct-AuthResTBSX"
-#define NID_setct_AuthResTBSX		536
-#define OBJ_setct_AuthResTBSX		OBJ_set_ctype,18L
-
-#define SN_setct_AuthTokenTBS		"setct-AuthTokenTBS"
-#define NID_setct_AuthTokenTBS		537
-#define OBJ_setct_AuthTokenTBS		OBJ_set_ctype,19L
-
-#define SN_setct_CapTokenData		"setct-CapTokenData"
-#define NID_setct_CapTokenData		538
-#define OBJ_setct_CapTokenData		OBJ_set_ctype,20L
-
-#define SN_setct_CapTokenTBS		"setct-CapTokenTBS"
-#define NID_setct_CapTokenTBS		539
-#define OBJ_setct_CapTokenTBS		OBJ_set_ctype,21L
-
-#define SN_setct_AcqCardCodeMsg		"setct-AcqCardCodeMsg"
-#define NID_setct_AcqCardCodeMsg		540
-#define OBJ_setct_AcqCardCodeMsg		OBJ_set_ctype,22L
-
-#define SN_setct_AuthRevReqTBS		"setct-AuthRevReqTBS"
-#define NID_setct_AuthRevReqTBS		541
-#define OBJ_setct_AuthRevReqTBS		OBJ_set_ctype,23L
-
-#define SN_setct_AuthRevResData		"setct-AuthRevResData"
-#define NID_setct_AuthRevResData		542
-#define OBJ_setct_AuthRevResData		OBJ_set_ctype,24L
-
-#define SN_setct_AuthRevResTBS		"setct-AuthRevResTBS"
-#define NID_setct_AuthRevResTBS		543
-#define OBJ_setct_AuthRevResTBS		OBJ_set_ctype,25L
-
-#define SN_setct_CapReqTBS		"setct-CapReqTBS"
-#define NID_setct_CapReqTBS		544
-#define OBJ_setct_CapReqTBS		OBJ_set_ctype,26L
-
-#define SN_setct_CapReqTBSX		"setct-CapReqTBSX"
-#define NID_setct_CapReqTBSX		545
-#define OBJ_setct_CapReqTBSX		OBJ_set_ctype,27L
-
-#define SN_setct_CapResData		"setct-CapResData"
-#define NID_setct_CapResData		546
-#define OBJ_setct_CapResData		OBJ_set_ctype,28L
-
-#define SN_setct_CapRevReqTBS		"setct-CapRevReqTBS"
-#define NID_setct_CapRevReqTBS		547
-#define OBJ_setct_CapRevReqTBS		OBJ_set_ctype,29L
-
-#define SN_setct_CapRevReqTBSX		"setct-CapRevReqTBSX"
-#define NID_setct_CapRevReqTBSX		548
-#define OBJ_setct_CapRevReqTBSX		OBJ_set_ctype,30L
-
-#define SN_setct_CapRevResData		"setct-CapRevResData"
-#define NID_setct_CapRevResData		549
-#define OBJ_setct_CapRevResData		OBJ_set_ctype,31L
-
-#define SN_setct_CredReqTBS		"setct-CredReqTBS"
-#define NID_setct_CredReqTBS		550
-#define OBJ_setct_CredReqTBS		OBJ_set_ctype,32L
-
-#define SN_setct_CredReqTBSX		"setct-CredReqTBSX"
-#define NID_setct_CredReqTBSX		551
-#define OBJ_setct_CredReqTBSX		OBJ_set_ctype,33L
-
-#define SN_setct_CredResData		"setct-CredResData"
-#define NID_setct_CredResData		552
-#define OBJ_setct_CredResData		OBJ_set_ctype,34L
-
-#define SN_setct_CredRevReqTBS		"setct-CredRevReqTBS"
-#define NID_setct_CredRevReqTBS		553
-#define OBJ_setct_CredRevReqTBS		OBJ_set_ctype,35L
-
-#define SN_setct_CredRevReqTBSX		"setct-CredRevReqTBSX"
-#define NID_setct_CredRevReqTBSX		554
-#define OBJ_setct_CredRevReqTBSX		OBJ_set_ctype,36L
-
-#define SN_setct_CredRevResData		"setct-CredRevResData"
-#define NID_setct_CredRevResData		555
-#define OBJ_setct_CredRevResData		OBJ_set_ctype,37L
-
-#define SN_setct_PCertReqData		"setct-PCertReqData"
-#define NID_setct_PCertReqData		556
-#define OBJ_setct_PCertReqData		OBJ_set_ctype,38L
-
-#define SN_setct_PCertResTBS		"setct-PCertResTBS"
-#define NID_setct_PCertResTBS		557
-#define OBJ_setct_PCertResTBS		OBJ_set_ctype,39L
-
-#define SN_setct_BatchAdminReqData		"setct-BatchAdminReqData"
-#define NID_setct_BatchAdminReqData		558
-#define OBJ_setct_BatchAdminReqData		OBJ_set_ctype,40L
-
-#define SN_setct_BatchAdminResData		"setct-BatchAdminResData"
-#define NID_setct_BatchAdminResData		559
-#define OBJ_setct_BatchAdminResData		OBJ_set_ctype,41L
-
-#define SN_setct_CardCInitResTBS		"setct-CardCInitResTBS"
-#define NID_setct_CardCInitResTBS		560
-#define OBJ_setct_CardCInitResTBS		OBJ_set_ctype,42L
-
-#define SN_setct_MeAqCInitResTBS		"setct-MeAqCInitResTBS"
-#define NID_setct_MeAqCInitResTBS		561
-#define OBJ_setct_MeAqCInitResTBS		OBJ_set_ctype,43L
-
-#define SN_setct_RegFormResTBS		"setct-RegFormResTBS"
-#define NID_setct_RegFormResTBS		562
-#define OBJ_setct_RegFormResTBS		OBJ_set_ctype,44L
-
-#define SN_setct_CertReqData		"setct-CertReqData"
-#define NID_setct_CertReqData		563
-#define OBJ_setct_CertReqData		OBJ_set_ctype,45L
-
-#define SN_setct_CertReqTBS		"setct-CertReqTBS"
-#define NID_setct_CertReqTBS		564
-#define OBJ_setct_CertReqTBS		OBJ_set_ctype,46L
-
-#define SN_setct_CertResData		"setct-CertResData"
-#define NID_setct_CertResData		565
-#define OBJ_setct_CertResData		OBJ_set_ctype,47L
-
-#define SN_setct_CertInqReqTBS		"setct-CertInqReqTBS"
-#define NID_setct_CertInqReqTBS		566
-#define OBJ_setct_CertInqReqTBS		OBJ_set_ctype,48L
-
-#define SN_setct_ErrorTBS		"setct-ErrorTBS"
-#define NID_setct_ErrorTBS		567
-#define OBJ_setct_ErrorTBS		OBJ_set_ctype,49L
-
-#define SN_setct_PIDualSignedTBE		"setct-PIDualSignedTBE"
-#define NID_setct_PIDualSignedTBE		568
-#define OBJ_setct_PIDualSignedTBE		OBJ_set_ctype,50L
-
-#define SN_setct_PIUnsignedTBE		"setct-PIUnsignedTBE"
-#define NID_setct_PIUnsignedTBE		569
-#define OBJ_setct_PIUnsignedTBE		OBJ_set_ctype,51L
-
-#define SN_setct_AuthReqTBE		"setct-AuthReqTBE"
-#define NID_setct_AuthReqTBE		570
-#define OBJ_setct_AuthReqTBE		OBJ_set_ctype,52L
-
-#define SN_setct_AuthResTBE		"setct-AuthResTBE"
-#define NID_setct_AuthResTBE		571
-#define OBJ_setct_AuthResTBE		OBJ_set_ctype,53L
-
-#define SN_setct_AuthResTBEX		"setct-AuthResTBEX"
-#define NID_setct_AuthResTBEX		572
-#define OBJ_setct_AuthResTBEX		OBJ_set_ctype,54L
-
-#define SN_setct_AuthTokenTBE		"setct-AuthTokenTBE"
-#define NID_setct_AuthTokenTBE		573
-#define OBJ_setct_AuthTokenTBE		OBJ_set_ctype,55L
-
-#define SN_setct_CapTokenTBE		"setct-CapTokenTBE"
-#define NID_setct_CapTokenTBE		574
-#define OBJ_setct_CapTokenTBE		OBJ_set_ctype,56L
-
-#define SN_setct_CapTokenTBEX		"setct-CapTokenTBEX"
-#define NID_setct_CapTokenTBEX		575
-#define OBJ_setct_CapTokenTBEX		OBJ_set_ctype,57L
-
-#define SN_setct_AcqCardCodeMsgTBE		"setct-AcqCardCodeMsgTBE"
-#define NID_setct_AcqCardCodeMsgTBE		576
-#define OBJ_setct_AcqCardCodeMsgTBE		OBJ_set_ctype,58L
-
-#define SN_setct_AuthRevReqTBE		"setct-AuthRevReqTBE"
-#define NID_setct_AuthRevReqTBE		577
-#define OBJ_setct_AuthRevReqTBE		OBJ_set_ctype,59L
-
-#define SN_setct_AuthRevResTBE		"setct-AuthRevResTBE"
-#define NID_setct_AuthRevResTBE		578
-#define OBJ_setct_AuthRevResTBE		OBJ_set_ctype,60L
-
-#define SN_setct_AuthRevResTBEB		"setct-AuthRevResTBEB"
-#define NID_setct_AuthRevResTBEB		579
-#define OBJ_setct_AuthRevResTBEB		OBJ_set_ctype,61L
-
-#define SN_setct_CapReqTBE		"setct-CapReqTBE"
-#define NID_setct_CapReqTBE		580
-#define OBJ_setct_CapReqTBE		OBJ_set_ctype,62L
-
-#define SN_setct_CapReqTBEX		"setct-CapReqTBEX"
-#define NID_setct_CapReqTBEX		581
-#define OBJ_setct_CapReqTBEX		OBJ_set_ctype,63L
-
-#define SN_setct_CapResTBE		"setct-CapResTBE"
-#define NID_setct_CapResTBE		582
-#define OBJ_setct_CapResTBE		OBJ_set_ctype,64L
-
-#define SN_setct_CapRevReqTBE		"setct-CapRevReqTBE"
-#define NID_setct_CapRevReqTBE		583
-#define OBJ_setct_CapRevReqTBE		OBJ_set_ctype,65L
-
-#define SN_setct_CapRevReqTBEX		"setct-CapRevReqTBEX"
-#define NID_setct_CapRevReqTBEX		584
-#define OBJ_setct_CapRevReqTBEX		OBJ_set_ctype,66L
-
-#define SN_setct_CapRevResTBE		"setct-CapRevResTBE"
-#define NID_setct_CapRevResTBE		585
-#define OBJ_setct_CapRevResTBE		OBJ_set_ctype,67L
-
-#define SN_setct_CredReqTBE		"setct-CredReqTBE"
-#define NID_setct_CredReqTBE		586
-#define OBJ_setct_CredReqTBE		OBJ_set_ctype,68L
-
-#define SN_setct_CredReqTBEX		"setct-CredReqTBEX"
-#define NID_setct_CredReqTBEX		587
-#define OBJ_setct_CredReqTBEX		OBJ_set_ctype,69L
-
-#define SN_setct_CredResTBE		"setct-CredResTBE"
-#define NID_setct_CredResTBE		588
-#define OBJ_setct_CredResTBE		OBJ_set_ctype,70L
-
-#define SN_setct_CredRevReqTBE		"setct-CredRevReqTBE"
-#define NID_setct_CredRevReqTBE		589
-#define OBJ_setct_CredRevReqTBE		OBJ_set_ctype,71L
-
-#define SN_setct_CredRevReqTBEX		"setct-CredRevReqTBEX"
-#define NID_setct_CredRevReqTBEX		590
-#define OBJ_setct_CredRevReqTBEX		OBJ_set_ctype,72L
-
-#define SN_setct_CredRevResTBE		"setct-CredRevResTBE"
-#define NID_setct_CredRevResTBE		591
-#define OBJ_setct_CredRevResTBE		OBJ_set_ctype,73L
-
-#define SN_setct_BatchAdminReqTBE		"setct-BatchAdminReqTBE"
-#define NID_setct_BatchAdminReqTBE		592
-#define OBJ_setct_BatchAdminReqTBE		OBJ_set_ctype,74L
-
-#define SN_setct_BatchAdminResTBE		"setct-BatchAdminResTBE"
-#define NID_setct_BatchAdminResTBE		593
-#define OBJ_setct_BatchAdminResTBE		OBJ_set_ctype,75L
-
-#define SN_setct_RegFormReqTBE		"setct-RegFormReqTBE"
-#define NID_setct_RegFormReqTBE		594
-#define OBJ_setct_RegFormReqTBE		OBJ_set_ctype,76L
-
-#define SN_setct_CertReqTBE		"setct-CertReqTBE"
-#define NID_setct_CertReqTBE		595
-#define OBJ_setct_CertReqTBE		OBJ_set_ctype,77L
-
-#define SN_setct_CertReqTBEX		"setct-CertReqTBEX"
-#define NID_setct_CertReqTBEX		596
-#define OBJ_setct_CertReqTBEX		OBJ_set_ctype,78L
-
-#define SN_setct_CertResTBE		"setct-CertResTBE"
-#define NID_setct_CertResTBE		597
-#define OBJ_setct_CertResTBE		OBJ_set_ctype,79L
-
-#define SN_setct_CRLNotificationTBS		"setct-CRLNotificationTBS"
-#define NID_setct_CRLNotificationTBS		598
-#define OBJ_setct_CRLNotificationTBS		OBJ_set_ctype,80L
-
-#define SN_setct_CRLNotificationResTBS		"setct-CRLNotificationResTBS"
-#define NID_setct_CRLNotificationResTBS		599
-#define OBJ_setct_CRLNotificationResTBS		OBJ_set_ctype,81L
-
-#define SN_setct_BCIDistributionTBS		"setct-BCIDistributionTBS"
-#define NID_setct_BCIDistributionTBS		600
-#define OBJ_setct_BCIDistributionTBS		OBJ_set_ctype,82L
-
-#define SN_setext_genCrypt		"setext-genCrypt"
-#define LN_setext_genCrypt		"generic cryptogram"
-#define NID_setext_genCrypt		601
-#define OBJ_setext_genCrypt		OBJ_set_msgExt,1L
-
-#define SN_setext_miAuth		"setext-miAuth"
-#define LN_setext_miAuth		"merchant initiated auth"
-#define NID_setext_miAuth		602
-#define OBJ_setext_miAuth		OBJ_set_msgExt,3L
-
-#define SN_setext_pinSecure		"setext-pinSecure"
-#define NID_setext_pinSecure		603
-#define OBJ_setext_pinSecure		OBJ_set_msgExt,4L
-
-#define SN_setext_pinAny		"setext-pinAny"
-#define NID_setext_pinAny		604
-#define OBJ_setext_pinAny		OBJ_set_msgExt,5L
-
-#define SN_setext_track2		"setext-track2"
-#define NID_setext_track2		605
-#define OBJ_setext_track2		OBJ_set_msgExt,7L
-
-#define SN_setext_cv		"setext-cv"
-#define LN_setext_cv		"additional verification"
-#define NID_setext_cv		606
-#define OBJ_setext_cv		OBJ_set_msgExt,8L
-
-#define SN_set_policy_root		"set-policy-root"
-#define NID_set_policy_root		607
-#define OBJ_set_policy_root		OBJ_set_policy,0L
-
-#define SN_setCext_hashedRoot		"setCext-hashedRoot"
-#define NID_setCext_hashedRoot		608
-#define OBJ_setCext_hashedRoot		OBJ_set_certExt,0L
-
-#define SN_setCext_certType		"setCext-certType"
-#define NID_setCext_certType		609
-#define OBJ_setCext_certType		OBJ_set_certExt,1L
-
-#define SN_setCext_merchData		"setCext-merchData"
-#define NID_setCext_merchData		610
-#define OBJ_setCext_merchData		OBJ_set_certExt,2L
-
-#define SN_setCext_cCertRequired		"setCext-cCertRequired"
-#define NID_setCext_cCertRequired		611
-#define OBJ_setCext_cCertRequired		OBJ_set_certExt,3L
-
-#define SN_setCext_tunneling		"setCext-tunneling"
-#define NID_setCext_tunneling		612
-#define OBJ_setCext_tunneling		OBJ_set_certExt,4L
-
-#define SN_setCext_setExt		"setCext-setExt"
-#define NID_setCext_setExt		613
-#define OBJ_setCext_setExt		OBJ_set_certExt,5L
-
-#define SN_setCext_setQualf		"setCext-setQualf"
-#define NID_setCext_setQualf		614
-#define OBJ_setCext_setQualf		OBJ_set_certExt,6L
-
-#define SN_setCext_PGWYcapabilities		"setCext-PGWYcapabilities"
-#define NID_setCext_PGWYcapabilities		615
-#define OBJ_setCext_PGWYcapabilities		OBJ_set_certExt,7L
-
-#define SN_setCext_TokenIdentifier		"setCext-TokenIdentifier"
-#define NID_setCext_TokenIdentifier		616
-#define OBJ_setCext_TokenIdentifier		OBJ_set_certExt,8L
-
-#define SN_setCext_Track2Data		"setCext-Track2Data"
-#define NID_setCext_Track2Data		617
-#define OBJ_setCext_Track2Data		OBJ_set_certExt,9L
-
-#define SN_setCext_TokenType		"setCext-TokenType"
-#define NID_setCext_TokenType		618
-#define OBJ_setCext_TokenType		OBJ_set_certExt,10L
-
-#define SN_setCext_IssuerCapabilities		"setCext-IssuerCapabilities"
-#define NID_setCext_IssuerCapabilities		619
-#define OBJ_setCext_IssuerCapabilities		OBJ_set_certExt,11L
-
-#define SN_setAttr_Cert		"setAttr-Cert"
-#define NID_setAttr_Cert		620
-#define OBJ_setAttr_Cert		OBJ_set_attr,0L
-
-#define SN_setAttr_PGWYcap		"setAttr-PGWYcap"
-#define LN_setAttr_PGWYcap		"payment gateway capabilities"
-#define NID_setAttr_PGWYcap		621
-#define OBJ_setAttr_PGWYcap		OBJ_set_attr,1L
-
-#define SN_setAttr_TokenType		"setAttr-TokenType"
-#define NID_setAttr_TokenType		622
-#define OBJ_setAttr_TokenType		OBJ_set_attr,2L
-
-#define SN_setAttr_IssCap		"setAttr-IssCap"
-#define LN_setAttr_IssCap		"issuer capabilities"
-#define NID_setAttr_IssCap		623
-#define OBJ_setAttr_IssCap		OBJ_set_attr,3L
-
-#define SN_set_rootKeyThumb		"set-rootKeyThumb"
-#define NID_set_rootKeyThumb		624
-#define OBJ_set_rootKeyThumb		OBJ_setAttr_Cert,0L
-
-#define SN_set_addPolicy		"set-addPolicy"
-#define NID_set_addPolicy		625
-#define OBJ_set_addPolicy		OBJ_setAttr_Cert,1L
-
-#define SN_setAttr_Token_EMV		"setAttr-Token-EMV"
-#define NID_setAttr_Token_EMV		626
-#define OBJ_setAttr_Token_EMV		OBJ_setAttr_TokenType,1L
-
-#define SN_setAttr_Token_B0Prime		"setAttr-Token-B0Prime"
-#define NID_setAttr_Token_B0Prime		627
-#define OBJ_setAttr_Token_B0Prime		OBJ_setAttr_TokenType,2L
-
-#define SN_setAttr_IssCap_CVM		"setAttr-IssCap-CVM"
-#define NID_setAttr_IssCap_CVM		628
-#define OBJ_setAttr_IssCap_CVM		OBJ_setAttr_IssCap,3L
-
-#define SN_setAttr_IssCap_T2		"setAttr-IssCap-T2"
-#define NID_setAttr_IssCap_T2		629
-#define OBJ_setAttr_IssCap_T2		OBJ_setAttr_IssCap,4L
-
-#define SN_setAttr_IssCap_Sig		"setAttr-IssCap-Sig"
-#define NID_setAttr_IssCap_Sig		630
-#define OBJ_setAttr_IssCap_Sig		OBJ_setAttr_IssCap,5L
-
-#define SN_setAttr_GenCryptgrm		"setAttr-GenCryptgrm"
-#define LN_setAttr_GenCryptgrm		"generate cryptogram"
-#define NID_setAttr_GenCryptgrm		631
-#define OBJ_setAttr_GenCryptgrm		OBJ_setAttr_IssCap_CVM,1L
-
-#define SN_setAttr_T2Enc		"setAttr-T2Enc"
-#define LN_setAttr_T2Enc		"encrypted track 2"
-#define NID_setAttr_T2Enc		632
-#define OBJ_setAttr_T2Enc		OBJ_setAttr_IssCap_T2,1L
-
-#define SN_setAttr_T2cleartxt		"setAttr-T2cleartxt"
-#define LN_setAttr_T2cleartxt		"cleartext track 2"
-#define NID_setAttr_T2cleartxt		633
-#define OBJ_setAttr_T2cleartxt		OBJ_setAttr_IssCap_T2,2L
-
-#define SN_setAttr_TokICCsig		"setAttr-TokICCsig"
-#define LN_setAttr_TokICCsig		"ICC or token signature"
-#define NID_setAttr_TokICCsig		634
-#define OBJ_setAttr_TokICCsig		OBJ_setAttr_IssCap_Sig,1L
-
-#define SN_setAttr_SecDevSig		"setAttr-SecDevSig"
-#define LN_setAttr_SecDevSig		"secure device signature"
-#define NID_setAttr_SecDevSig		635
-#define OBJ_setAttr_SecDevSig		OBJ_setAttr_IssCap_Sig,2L
-
-#define SN_set_brand_IATA_ATA		"set-brand-IATA-ATA"
-#define NID_set_brand_IATA_ATA		636
-#define OBJ_set_brand_IATA_ATA		OBJ_set_brand,1L
-
-#define SN_set_brand_Diners		"set-brand-Diners"
-#define NID_set_brand_Diners		637
-#define OBJ_set_brand_Diners		OBJ_set_brand,30L
-
-#define SN_set_brand_AmericanExpress		"set-brand-AmericanExpress"
-#define NID_set_brand_AmericanExpress		638
-#define OBJ_set_brand_AmericanExpress		OBJ_set_brand,34L
-
-#define SN_set_brand_JCB		"set-brand-JCB"
-#define NID_set_brand_JCB		639
-#define OBJ_set_brand_JCB		OBJ_set_brand,35L
-
-#define SN_set_brand_Visa		"set-brand-Visa"
-#define NID_set_brand_Visa		640
-#define OBJ_set_brand_Visa		OBJ_set_brand,4L
-
-#define SN_set_brand_MasterCard		"set-brand-MasterCard"
-#define NID_set_brand_MasterCard		641
-#define OBJ_set_brand_MasterCard		OBJ_set_brand,5L
-
-#define SN_set_brand_Novus		"set-brand-Novus"
-#define NID_set_brand_Novus		642
-#define OBJ_set_brand_Novus		OBJ_set_brand,6011L
-
-#define SN_des_cdmf		"DES-CDMF"
-#define LN_des_cdmf		"des-cdmf"
-#define NID_des_cdmf		643
-#define OBJ_des_cdmf		OBJ_rsadsi,3L,10L
-
-#define SN_rsaOAEPEncryptionSET		"rsaOAEPEncryptionSET"
-#define NID_rsaOAEPEncryptionSET		644
-#define OBJ_rsaOAEPEncryptionSET		OBJ_rsadsi,1L,1L,6L
-
-#define SN_ipsec3		"Oakley-EC2N-3"
-#define LN_ipsec3		"ipsec3"
-#define NID_ipsec3		749
-
-#define SN_ipsec4		"Oakley-EC2N-4"
-#define LN_ipsec4		"ipsec4"
-#define NID_ipsec4		750
-
-#define SN_whirlpool		"whirlpool"
-#define NID_whirlpool		804
-#define OBJ_whirlpool		OBJ_iso,0L,10118L,3L,0L,55L
-
-#define SN_cryptopro		"cryptopro"
-#define NID_cryptopro		805
-#define OBJ_cryptopro		OBJ_member_body,643L,2L,2L
-
-#define SN_cryptocom		"cryptocom"
-#define NID_cryptocom		806
-#define OBJ_cryptocom		OBJ_member_body,643L,2L,9L
-
-#define SN_id_GostR3411_94_with_GostR3410_2001		"id-GostR3411-94-with-GostR3410-2001"
-#define LN_id_GostR3411_94_with_GostR3410_2001		"GOST R 34.11-94 with GOST R 34.10-2001"
-#define NID_id_GostR3411_94_with_GostR3410_2001		807
-#define OBJ_id_GostR3411_94_with_GostR3410_2001		OBJ_cryptopro,3L
-
-#define SN_id_GostR3411_94_with_GostR3410_94		"id-GostR3411-94-with-GostR3410-94"
-#define LN_id_GostR3411_94_with_GostR3410_94		"GOST R 34.11-94 with GOST R 34.10-94"
-#define NID_id_GostR3411_94_with_GostR3410_94		808
-#define OBJ_id_GostR3411_94_with_GostR3410_94		OBJ_cryptopro,4L
-
-#define SN_id_GostR3411_94		"md_gost94"
-#define LN_id_GostR3411_94		"GOST R 34.11-94"
-#define NID_id_GostR3411_94		809
-#define OBJ_id_GostR3411_94		OBJ_cryptopro,9L
-
-#define SN_id_HMACGostR3411_94		"id-HMACGostR3411-94"
-#define LN_id_HMACGostR3411_94		"HMAC GOST 34.11-94"
-#define NID_id_HMACGostR3411_94		810
-#define OBJ_id_HMACGostR3411_94		OBJ_cryptopro,10L
-
-#define SN_id_GostR3410_2001		"gost2001"
-#define LN_id_GostR3410_2001		"GOST R 34.10-2001"
-#define NID_id_GostR3410_2001		811
-#define OBJ_id_GostR3410_2001		OBJ_cryptopro,19L
-
-#define SN_id_GostR3410_94		"gost94"
-#define LN_id_GostR3410_94		"GOST R 34.10-94"
-#define NID_id_GostR3410_94		812
-#define OBJ_id_GostR3410_94		OBJ_cryptopro,20L
-
-#define SN_id_Gost28147_89		"gost89"
-#define LN_id_Gost28147_89		"GOST 28147-89"
-#define NID_id_Gost28147_89		813
-#define OBJ_id_Gost28147_89		OBJ_cryptopro,21L
-
-#define SN_gost89_cnt		"gost89-cnt"
-#define NID_gost89_cnt		814
-
-#define SN_id_Gost28147_89_MAC		"gost-mac"
-#define LN_id_Gost28147_89_MAC		"GOST 28147-89 MAC"
-#define NID_id_Gost28147_89_MAC		815
-#define OBJ_id_Gost28147_89_MAC		OBJ_cryptopro,22L
-
-#define SN_id_GostR3411_94_prf		"prf-gostr3411-94"
-#define LN_id_GostR3411_94_prf		"GOST R 34.11-94 PRF"
-#define NID_id_GostR3411_94_prf		816
-#define OBJ_id_GostR3411_94_prf		OBJ_cryptopro,23L
-
-#define SN_id_GostR3410_2001DH		"id-GostR3410-2001DH"
-#define LN_id_GostR3410_2001DH		"GOST R 34.10-2001 DH"
-#define NID_id_GostR3410_2001DH		817
-#define OBJ_id_GostR3410_2001DH		OBJ_cryptopro,98L
-
-#define SN_id_GostR3410_94DH		"id-GostR3410-94DH"
-#define LN_id_GostR3410_94DH		"GOST R 34.10-94 DH"
-#define NID_id_GostR3410_94DH		818
-#define OBJ_id_GostR3410_94DH		OBJ_cryptopro,99L
-
-#define SN_id_Gost28147_89_CryptoPro_KeyMeshing		"id-Gost28147-89-CryptoPro-KeyMeshing"
-#define NID_id_Gost28147_89_CryptoPro_KeyMeshing		819
-#define OBJ_id_Gost28147_89_CryptoPro_KeyMeshing		OBJ_cryptopro,14L,1L
-
-#define SN_id_Gost28147_89_None_KeyMeshing		"id-Gost28147-89-None-KeyMeshing"
-#define NID_id_Gost28147_89_None_KeyMeshing		820
-#define OBJ_id_Gost28147_89_None_KeyMeshing		OBJ_cryptopro,14L,0L
-
-#define SN_id_GostR3411_94_TestParamSet		"id-GostR3411-94-TestParamSet"
-#define NID_id_GostR3411_94_TestParamSet		821
-#define OBJ_id_GostR3411_94_TestParamSet		OBJ_cryptopro,30L,0L
-
-#define SN_id_GostR3411_94_CryptoProParamSet		"id-GostR3411-94-CryptoProParamSet"
-#define NID_id_GostR3411_94_CryptoProParamSet		822
-#define OBJ_id_GostR3411_94_CryptoProParamSet		OBJ_cryptopro,30L,1L
-
-#define SN_id_Gost28147_89_TestParamSet		"id-Gost28147-89-TestParamSet"
-#define NID_id_Gost28147_89_TestParamSet		823
-#define OBJ_id_Gost28147_89_TestParamSet		OBJ_cryptopro,31L,0L
-
-#define SN_id_Gost28147_89_CryptoPro_A_ParamSet		"id-Gost28147-89-CryptoPro-A-ParamSet"
-#define NID_id_Gost28147_89_CryptoPro_A_ParamSet		824
-#define OBJ_id_Gost28147_89_CryptoPro_A_ParamSet		OBJ_cryptopro,31L,1L
-
-#define SN_id_Gost28147_89_CryptoPro_B_ParamSet		"id-Gost28147-89-CryptoPro-B-ParamSet"
-#define NID_id_Gost28147_89_CryptoPro_B_ParamSet		825
-#define OBJ_id_Gost28147_89_CryptoPro_B_ParamSet		OBJ_cryptopro,31L,2L
-
-#define SN_id_Gost28147_89_CryptoPro_C_ParamSet		"id-Gost28147-89-CryptoPro-C-ParamSet"
-#define NID_id_Gost28147_89_CryptoPro_C_ParamSet		826
-#define OBJ_id_Gost28147_89_CryptoPro_C_ParamSet		OBJ_cryptopro,31L,3L
-
-#define SN_id_Gost28147_89_CryptoPro_D_ParamSet		"id-Gost28147-89-CryptoPro-D-ParamSet"
-#define NID_id_Gost28147_89_CryptoPro_D_ParamSet		827
-#define OBJ_id_Gost28147_89_CryptoPro_D_ParamSet		OBJ_cryptopro,31L,4L
-
-#define SN_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet		"id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet"
-#define NID_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet		828
-#define OBJ_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet		OBJ_cryptopro,31L,5L
-
-#define SN_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet		"id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet"
-#define NID_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet		829
-#define OBJ_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet		OBJ_cryptopro,31L,6L
-
-#define SN_id_Gost28147_89_CryptoPro_RIC_1_ParamSet		"id-Gost28147-89-CryptoPro-RIC-1-ParamSet"
-#define NID_id_Gost28147_89_CryptoPro_RIC_1_ParamSet		830
-#define OBJ_id_Gost28147_89_CryptoPro_RIC_1_ParamSet		OBJ_cryptopro,31L,7L
-
-#define SN_id_GostR3410_94_TestParamSet		"id-GostR3410-94-TestParamSet"
-#define NID_id_GostR3410_94_TestParamSet		831
-#define OBJ_id_GostR3410_94_TestParamSet		OBJ_cryptopro,32L,0L
-
-#define SN_id_GostR3410_94_CryptoPro_A_ParamSet		"id-GostR3410-94-CryptoPro-A-ParamSet"
-#define NID_id_GostR3410_94_CryptoPro_A_ParamSet		832
-#define OBJ_id_GostR3410_94_CryptoPro_A_ParamSet		OBJ_cryptopro,32L,2L
-
-#define SN_id_GostR3410_94_CryptoPro_B_ParamSet		"id-GostR3410-94-CryptoPro-B-ParamSet"
-#define NID_id_GostR3410_94_CryptoPro_B_ParamSet		833
-#define OBJ_id_GostR3410_94_CryptoPro_B_ParamSet		OBJ_cryptopro,32L,3L
-
-#define SN_id_GostR3410_94_CryptoPro_C_ParamSet		"id-GostR3410-94-CryptoPro-C-ParamSet"
-#define NID_id_GostR3410_94_CryptoPro_C_ParamSet		834
-#define OBJ_id_GostR3410_94_CryptoPro_C_ParamSet		OBJ_cryptopro,32L,4L
-
-#define SN_id_GostR3410_94_CryptoPro_D_ParamSet		"id-GostR3410-94-CryptoPro-D-ParamSet"
-#define NID_id_GostR3410_94_CryptoPro_D_ParamSet		835
-#define OBJ_id_GostR3410_94_CryptoPro_D_ParamSet		OBJ_cryptopro,32L,5L
-
-#define SN_id_GostR3410_94_CryptoPro_XchA_ParamSet		"id-GostR3410-94-CryptoPro-XchA-ParamSet"
-#define NID_id_GostR3410_94_CryptoPro_XchA_ParamSet		836
-#define OBJ_id_GostR3410_94_CryptoPro_XchA_ParamSet		OBJ_cryptopro,33L,1L
-
-#define SN_id_GostR3410_94_CryptoPro_XchB_ParamSet		"id-GostR3410-94-CryptoPro-XchB-ParamSet"
-#define NID_id_GostR3410_94_CryptoPro_XchB_ParamSet		837
-#define OBJ_id_GostR3410_94_CryptoPro_XchB_ParamSet		OBJ_cryptopro,33L,2L
-
-#define SN_id_GostR3410_94_CryptoPro_XchC_ParamSet		"id-GostR3410-94-CryptoPro-XchC-ParamSet"
-#define NID_id_GostR3410_94_CryptoPro_XchC_ParamSet		838
-#define OBJ_id_GostR3410_94_CryptoPro_XchC_ParamSet		OBJ_cryptopro,33L,3L
-
-#define SN_id_GostR3410_2001_TestParamSet		"id-GostR3410-2001-TestParamSet"
-#define NID_id_GostR3410_2001_TestParamSet		839
-#define OBJ_id_GostR3410_2001_TestParamSet		OBJ_cryptopro,35L,0L
-
-#define SN_id_GostR3410_2001_CryptoPro_A_ParamSet		"id-GostR3410-2001-CryptoPro-A-ParamSet"
-#define NID_id_GostR3410_2001_CryptoPro_A_ParamSet		840
-#define OBJ_id_GostR3410_2001_CryptoPro_A_ParamSet		OBJ_cryptopro,35L,1L
-
-#define SN_id_GostR3410_2001_CryptoPro_B_ParamSet		"id-GostR3410-2001-CryptoPro-B-ParamSet"
-#define NID_id_GostR3410_2001_CryptoPro_B_ParamSet		841
-#define OBJ_id_GostR3410_2001_CryptoPro_B_ParamSet		OBJ_cryptopro,35L,2L
-
-#define SN_id_GostR3410_2001_CryptoPro_C_ParamSet		"id-GostR3410-2001-CryptoPro-C-ParamSet"
-#define NID_id_GostR3410_2001_CryptoPro_C_ParamSet		842
-#define OBJ_id_GostR3410_2001_CryptoPro_C_ParamSet		OBJ_cryptopro,35L,3L
-
-#define SN_id_GostR3410_2001_CryptoPro_XchA_ParamSet		"id-GostR3410-2001-CryptoPro-XchA-ParamSet"
-#define NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet		843
-#define OBJ_id_GostR3410_2001_CryptoPro_XchA_ParamSet		OBJ_cryptopro,36L,0L
-
-#define SN_id_GostR3410_2001_CryptoPro_XchB_ParamSet		"id-GostR3410-2001-CryptoPro-XchB-ParamSet"
-#define NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet		844
-#define OBJ_id_GostR3410_2001_CryptoPro_XchB_ParamSet		OBJ_cryptopro,36L,1L
-
-#define SN_id_GostR3410_94_a		"id-GostR3410-94-a"
-#define NID_id_GostR3410_94_a		845
-#define OBJ_id_GostR3410_94_a		OBJ_id_GostR3410_94,1L
-
-#define SN_id_GostR3410_94_aBis		"id-GostR3410-94-aBis"
-#define NID_id_GostR3410_94_aBis		846
-#define OBJ_id_GostR3410_94_aBis		OBJ_id_GostR3410_94,2L
-
-#define SN_id_GostR3410_94_b		"id-GostR3410-94-b"
-#define NID_id_GostR3410_94_b		847
-#define OBJ_id_GostR3410_94_b		OBJ_id_GostR3410_94,3L
-
-#define SN_id_GostR3410_94_bBis		"id-GostR3410-94-bBis"
-#define NID_id_GostR3410_94_bBis		848
-#define OBJ_id_GostR3410_94_bBis		OBJ_id_GostR3410_94,4L
-
-#define SN_id_Gost28147_89_cc		"id-Gost28147-89-cc"
-#define LN_id_Gost28147_89_cc		"GOST 28147-89 Cryptocom ParamSet"
-#define NID_id_Gost28147_89_cc		849
-#define OBJ_id_Gost28147_89_cc		OBJ_cryptocom,1L,6L,1L
-
-#define SN_id_GostR3410_94_cc		"gost94cc"
-#define LN_id_GostR3410_94_cc		"GOST 34.10-94 Cryptocom"
-#define NID_id_GostR3410_94_cc		850
-#define OBJ_id_GostR3410_94_cc		OBJ_cryptocom,1L,5L,3L
-
-#define SN_id_GostR3410_2001_cc		"gost2001cc"
-#define LN_id_GostR3410_2001_cc		"GOST 34.10-2001 Cryptocom"
-#define NID_id_GostR3410_2001_cc		851
-#define OBJ_id_GostR3410_2001_cc		OBJ_cryptocom,1L,5L,4L
-
-#define SN_id_GostR3411_94_with_GostR3410_94_cc		"id-GostR3411-94-with-GostR3410-94-cc"
-#define LN_id_GostR3411_94_with_GostR3410_94_cc		"GOST R 34.11-94 with GOST R 34.10-94 Cryptocom"
-#define NID_id_GostR3411_94_with_GostR3410_94_cc		852
-#define OBJ_id_GostR3411_94_with_GostR3410_94_cc		OBJ_cryptocom,1L,3L,3L
-
-#define SN_id_GostR3411_94_with_GostR3410_2001_cc		"id-GostR3411-94-with-GostR3410-2001-cc"
-#define LN_id_GostR3411_94_with_GostR3410_2001_cc		"GOST R 34.11-94 with GOST R 34.10-2001 Cryptocom"
-#define NID_id_GostR3411_94_with_GostR3410_2001_cc		853
-#define OBJ_id_GostR3411_94_with_GostR3410_2001_cc		OBJ_cryptocom,1L,3L,4L
-
-#define SN_id_GostR3410_2001_ParamSet_cc		"id-GostR3410-2001-ParamSet-cc"
-#define LN_id_GostR3410_2001_ParamSet_cc		"GOST R 3410-2001 Parameter Set Cryptocom"
-#define NID_id_GostR3410_2001_ParamSet_cc		854
-#define OBJ_id_GostR3410_2001_ParamSet_cc		OBJ_cryptocom,1L,8L,1L
-
-#define SN_camellia_128_cbc		"CAMELLIA-128-CBC"
-#define LN_camellia_128_cbc		"camellia-128-cbc"
-#define NID_camellia_128_cbc		751
-#define OBJ_camellia_128_cbc		1L,2L,392L,200011L,61L,1L,1L,1L,2L
-
-#define SN_camellia_192_cbc		"CAMELLIA-192-CBC"
-#define LN_camellia_192_cbc		"camellia-192-cbc"
-#define NID_camellia_192_cbc		752
-#define OBJ_camellia_192_cbc		1L,2L,392L,200011L,61L,1L,1L,1L,3L
-
-#define SN_camellia_256_cbc		"CAMELLIA-256-CBC"
-#define LN_camellia_256_cbc		"camellia-256-cbc"
-#define NID_camellia_256_cbc		753
-#define OBJ_camellia_256_cbc		1L,2L,392L,200011L,61L,1L,1L,1L,4L
-
-#define SN_id_camellia128_wrap		"id-camellia128-wrap"
-#define NID_id_camellia128_wrap		907
-#define OBJ_id_camellia128_wrap		1L,2L,392L,200011L,61L,1L,1L,3L,2L
-
-#define SN_id_camellia192_wrap		"id-camellia192-wrap"
-#define NID_id_camellia192_wrap		908
-#define OBJ_id_camellia192_wrap		1L,2L,392L,200011L,61L,1L,1L,3L,3L
-
-#define SN_id_camellia256_wrap		"id-camellia256-wrap"
-#define NID_id_camellia256_wrap		909
-#define OBJ_id_camellia256_wrap		1L,2L,392L,200011L,61L,1L,1L,3L,4L
-
-#define OBJ_ntt_ds		0L,3L,4401L,5L
-
-#define OBJ_camellia		OBJ_ntt_ds,3L,1L,9L
-
-#define SN_camellia_128_ecb		"CAMELLIA-128-ECB"
-#define LN_camellia_128_ecb		"camellia-128-ecb"
-#define NID_camellia_128_ecb		754
-#define OBJ_camellia_128_ecb		OBJ_camellia,1L
-
-#define SN_camellia_128_ofb128		"CAMELLIA-128-OFB"
-#define LN_camellia_128_ofb128		"camellia-128-ofb"
-#define NID_camellia_128_ofb128		766
-#define OBJ_camellia_128_ofb128		OBJ_camellia,3L
-
-#define SN_camellia_128_cfb128		"CAMELLIA-128-CFB"
-#define LN_camellia_128_cfb128		"camellia-128-cfb"
-#define NID_camellia_128_cfb128		757
-#define OBJ_camellia_128_cfb128		OBJ_camellia,4L
-
-#define SN_camellia_192_ecb		"CAMELLIA-192-ECB"
-#define LN_camellia_192_ecb		"camellia-192-ecb"
-#define NID_camellia_192_ecb		755
-#define OBJ_camellia_192_ecb		OBJ_camellia,21L
-
-#define SN_camellia_192_ofb128		"CAMELLIA-192-OFB"
-#define LN_camellia_192_ofb128		"camellia-192-ofb"
-#define NID_camellia_192_ofb128		767
-#define OBJ_camellia_192_ofb128		OBJ_camellia,23L
-
-#define SN_camellia_192_cfb128		"CAMELLIA-192-CFB"
-#define LN_camellia_192_cfb128		"camellia-192-cfb"
-#define NID_camellia_192_cfb128		758
-#define OBJ_camellia_192_cfb128		OBJ_camellia,24L
-
-#define SN_camellia_256_ecb		"CAMELLIA-256-ECB"
-#define LN_camellia_256_ecb		"camellia-256-ecb"
-#define NID_camellia_256_ecb		756
-#define OBJ_camellia_256_ecb		OBJ_camellia,41L
-
-#define SN_camellia_256_ofb128		"CAMELLIA-256-OFB"
-#define LN_camellia_256_ofb128		"camellia-256-ofb"
-#define NID_camellia_256_ofb128		768
-#define OBJ_camellia_256_ofb128		OBJ_camellia,43L
-
-#define SN_camellia_256_cfb128		"CAMELLIA-256-CFB"
-#define LN_camellia_256_cfb128		"camellia-256-cfb"
-#define NID_camellia_256_cfb128		759
-#define OBJ_camellia_256_cfb128		OBJ_camellia,44L
-
-#define SN_camellia_128_cfb1		"CAMELLIA-128-CFB1"
-#define LN_camellia_128_cfb1		"camellia-128-cfb1"
-#define NID_camellia_128_cfb1		760
-
-#define SN_camellia_192_cfb1		"CAMELLIA-192-CFB1"
-#define LN_camellia_192_cfb1		"camellia-192-cfb1"
-#define NID_camellia_192_cfb1		761
-
-#define SN_camellia_256_cfb1		"CAMELLIA-256-CFB1"
-#define LN_camellia_256_cfb1		"camellia-256-cfb1"
-#define NID_camellia_256_cfb1		762
-
-#define SN_camellia_128_cfb8		"CAMELLIA-128-CFB8"
-#define LN_camellia_128_cfb8		"camellia-128-cfb8"
-#define NID_camellia_128_cfb8		763
-
-#define SN_camellia_192_cfb8		"CAMELLIA-192-CFB8"
-#define LN_camellia_192_cfb8		"camellia-192-cfb8"
-#define NID_camellia_192_cfb8		764
-
-#define SN_camellia_256_cfb8		"CAMELLIA-256-CFB8"
-#define LN_camellia_256_cfb8		"camellia-256-cfb8"
-#define NID_camellia_256_cfb8		765
-
-#define SN_kisa		"KISA"
-#define LN_kisa		"kisa"
-#define NID_kisa		773
-#define OBJ_kisa		OBJ_member_body,410L,200004L
-
-#define SN_seed_ecb		"SEED-ECB"
-#define LN_seed_ecb		"seed-ecb"
-#define NID_seed_ecb		776
-#define OBJ_seed_ecb		OBJ_kisa,1L,3L
-
-#define SN_seed_cbc		"SEED-CBC"
-#define LN_seed_cbc		"seed-cbc"
-#define NID_seed_cbc		777
-#define OBJ_seed_cbc		OBJ_kisa,1L,4L
-
-#define SN_seed_cfb128		"SEED-CFB"
-#define LN_seed_cfb128		"seed-cfb"
-#define NID_seed_cfb128		779
-#define OBJ_seed_cfb128		OBJ_kisa,1L,5L
-
-#define SN_seed_ofb128		"SEED-OFB"
-#define LN_seed_ofb128		"seed-ofb"
-#define NID_seed_ofb128		778
-#define OBJ_seed_ofb128		OBJ_kisa,1L,6L
-
-#define SN_hmac		"HMAC"
-#define LN_hmac		"hmac"
-#define NID_hmac		855
-
-#define SN_cmac		"CMAC"
-#define LN_cmac		"cmac"
-#define NID_cmac		894
-
-#define SN_rc4_hmac_md5		"RC4-HMAC-MD5"
-#define LN_rc4_hmac_md5		"rc4-hmac-md5"
-#define NID_rc4_hmac_md5		915
-
-#define SN_aes_128_cbc_hmac_sha1		"AES-128-CBC-HMAC-SHA1"
-#define LN_aes_128_cbc_hmac_sha1		"aes-128-cbc-hmac-sha1"
-#define NID_aes_128_cbc_hmac_sha1		916
-
-#define SN_aes_192_cbc_hmac_sha1		"AES-192-CBC-HMAC-SHA1"
-#define LN_aes_192_cbc_hmac_sha1		"aes-192-cbc-hmac-sha1"
-#define NID_aes_192_cbc_hmac_sha1		917
-
-#define SN_aes_256_cbc_hmac_sha1		"AES-256-CBC-HMAC-SHA1"
-#define LN_aes_256_cbc_hmac_sha1		"aes-256-cbc-hmac-sha1"
-#define NID_aes_256_cbc_hmac_sha1		918
-
-#define SN_dhpublicnumber		"dhpublicnumber"
-#define LN_dhpublicnumber		"X9.42 DH"
-#define NID_dhpublicnumber		920
-#define OBJ_dhpublicnumber		OBJ_ISO_US,10046L,2L,1L
-
-#define SN_brainpoolP160r1		"brainpoolP160r1"
-#define NID_brainpoolP160r1		921
-#define OBJ_brainpoolP160r1		1L,3L,36L,3L,3L,2L,8L,1L,1L,1L
-
-#define SN_brainpoolP160t1		"brainpoolP160t1"
-#define NID_brainpoolP160t1		922
-#define OBJ_brainpoolP160t1		1L,3L,36L,3L,3L,2L,8L,1L,1L,2L
-
-#define SN_brainpoolP192r1		"brainpoolP192r1"
-#define NID_brainpoolP192r1		923
-#define OBJ_brainpoolP192r1		1L,3L,36L,3L,3L,2L,8L,1L,1L,3L
-
-#define SN_brainpoolP192t1		"brainpoolP192t1"
-#define NID_brainpoolP192t1		924
-#define OBJ_brainpoolP192t1		1L,3L,36L,3L,3L,2L,8L,1L,1L,4L
-
-#define SN_brainpoolP224r1		"brainpoolP224r1"
-#define NID_brainpoolP224r1		925
-#define OBJ_brainpoolP224r1		1L,3L,36L,3L,3L,2L,8L,1L,1L,5L
-
-#define SN_brainpoolP224t1		"brainpoolP224t1"
-#define NID_brainpoolP224t1		926
-#define OBJ_brainpoolP224t1		1L,3L,36L,3L,3L,2L,8L,1L,1L,6L
-
-#define SN_brainpoolP256r1		"brainpoolP256r1"
-#define NID_brainpoolP256r1		927
-#define OBJ_brainpoolP256r1		1L,3L,36L,3L,3L,2L,8L,1L,1L,7L
-
-#define SN_brainpoolP256t1		"brainpoolP256t1"
-#define NID_brainpoolP256t1		928
-#define OBJ_brainpoolP256t1		1L,3L,36L,3L,3L,2L,8L,1L,1L,8L
-
-#define SN_brainpoolP320r1		"brainpoolP320r1"
-#define NID_brainpoolP320r1		929
-#define OBJ_brainpoolP320r1		1L,3L,36L,3L,3L,2L,8L,1L,1L,9L
-
-#define SN_brainpoolP320t1		"brainpoolP320t1"
-#define NID_brainpoolP320t1		930
-#define OBJ_brainpoolP320t1		1L,3L,36L,3L,3L,2L,8L,1L,1L,10L
-
-#define SN_brainpoolP384r1		"brainpoolP384r1"
-#define NID_brainpoolP384r1		931
-#define OBJ_brainpoolP384r1		1L,3L,36L,3L,3L,2L,8L,1L,1L,11L
-
-#define SN_brainpoolP384t1		"brainpoolP384t1"
-#define NID_brainpoolP384t1		932
-#define OBJ_brainpoolP384t1		1L,3L,36L,3L,3L,2L,8L,1L,1L,12L
-
-#define SN_brainpoolP512r1		"brainpoolP512r1"
-#define NID_brainpoolP512r1		933
-#define OBJ_brainpoolP512r1		1L,3L,36L,3L,3L,2L,8L,1L,1L,13L
-
-#define SN_brainpoolP512t1		"brainpoolP512t1"
-#define NID_brainpoolP512t1		934
-#define OBJ_brainpoolP512t1		1L,3L,36L,3L,3L,2L,8L,1L,1L,14L
-
-#define OBJ_x9_63_scheme		1L,3L,133L,16L,840L,63L,0L
-
-#define OBJ_secg_scheme		OBJ_certicom_arc,1L
-
-#define SN_dhSinglePass_stdDH_sha1kdf_scheme		"dhSinglePass-stdDH-sha1kdf-scheme"
-#define NID_dhSinglePass_stdDH_sha1kdf_scheme		936
-#define OBJ_dhSinglePass_stdDH_sha1kdf_scheme		OBJ_x9_63_scheme,2L
-
-#define SN_dhSinglePass_stdDH_sha224kdf_scheme		"dhSinglePass-stdDH-sha224kdf-scheme"
-#define NID_dhSinglePass_stdDH_sha224kdf_scheme		937
-#define OBJ_dhSinglePass_stdDH_sha224kdf_scheme		OBJ_secg_scheme,11L,0L
-
-#define SN_dhSinglePass_stdDH_sha256kdf_scheme		"dhSinglePass-stdDH-sha256kdf-scheme"
-#define NID_dhSinglePass_stdDH_sha256kdf_scheme		938
-#define OBJ_dhSinglePass_stdDH_sha256kdf_scheme		OBJ_secg_scheme,11L,1L
-
-#define SN_dhSinglePass_stdDH_sha384kdf_scheme		"dhSinglePass-stdDH-sha384kdf-scheme"
-#define NID_dhSinglePass_stdDH_sha384kdf_scheme		939
-#define OBJ_dhSinglePass_stdDH_sha384kdf_scheme		OBJ_secg_scheme,11L,2L
-
-#define SN_dhSinglePass_stdDH_sha512kdf_scheme		"dhSinglePass-stdDH-sha512kdf-scheme"
-#define NID_dhSinglePass_stdDH_sha512kdf_scheme		940
-#define OBJ_dhSinglePass_stdDH_sha512kdf_scheme		OBJ_secg_scheme,11L,3L
-
-#define SN_dhSinglePass_cofactorDH_sha1kdf_scheme		"dhSinglePass-cofactorDH-sha1kdf-scheme"
-#define NID_dhSinglePass_cofactorDH_sha1kdf_scheme		941
-#define OBJ_dhSinglePass_cofactorDH_sha1kdf_scheme		OBJ_x9_63_scheme,3L
-
-#define SN_dhSinglePass_cofactorDH_sha224kdf_scheme		"dhSinglePass-cofactorDH-sha224kdf-scheme"
-#define NID_dhSinglePass_cofactorDH_sha224kdf_scheme		942
-#define OBJ_dhSinglePass_cofactorDH_sha224kdf_scheme		OBJ_secg_scheme,14L,0L
-
-#define SN_dhSinglePass_cofactorDH_sha256kdf_scheme		"dhSinglePass-cofactorDH-sha256kdf-scheme"
-#define NID_dhSinglePass_cofactorDH_sha256kdf_scheme		943
-#define OBJ_dhSinglePass_cofactorDH_sha256kdf_scheme		OBJ_secg_scheme,14L,1L
-
-#define SN_dhSinglePass_cofactorDH_sha384kdf_scheme		"dhSinglePass-cofactorDH-sha384kdf-scheme"
-#define NID_dhSinglePass_cofactorDH_sha384kdf_scheme		944
-#define OBJ_dhSinglePass_cofactorDH_sha384kdf_scheme		OBJ_secg_scheme,14L,2L
-
-#define SN_dhSinglePass_cofactorDH_sha512kdf_scheme		"dhSinglePass-cofactorDH-sha512kdf-scheme"
-#define NID_dhSinglePass_cofactorDH_sha512kdf_scheme		945
-#define OBJ_dhSinglePass_cofactorDH_sha512kdf_scheme		OBJ_secg_scheme,14L,3L
-
-#define SN_dh_std_kdf		"dh-std-kdf"
-#define NID_dh_std_kdf		946
-
-#define SN_dh_cofactor_kdf		"dh-cofactor-kdf"
-#define NID_dh_cofactor_kdf		947
-
-#define SN_x25519		"X25519"
-#define LN_x25519		"x25519"
-#define NID_x25519		948
-
+#include "nid.h"
diff --git a/src/include/openssl/opensslfeatures.h b/src/include/openssl/opensslconf.h
similarity index 92%
rename from src/include/openssl/opensslfeatures.h
rename to src/include/openssl/opensslconf.h
index c3f97d5..bf65fc3 100644
--- a/src/include/openssl/opensslfeatures.h
+++ b/src/include/openssl/opensslconf.h
@@ -15,8 +15,8 @@
 /* This header is provided in order to make compiling against code that expects
    OpenSSL easier. */
 
-#ifndef OPENSSL_HEADER_OPENSSLFEATURES_H
-#define OPENSSL_HEADER_OPENSSLFEATURES_H
+#ifndef OPENSSL_HEADER_OPENSSLCONF_H
+#define OPENSSL_HEADER_OPENSSLCONF_H
 
 
 #define OPENSSL_NO_BF
@@ -57,4 +57,4 @@
 #define OPENSSL_NO_WHIRLPOOL
 
 
-#endif  /* OPENSSL_HEADER_OPENSSLFEATURES_H */
+#endif  /* OPENSSL_HEADER_OPENSSLCONF_H */
diff --git a/src/include/openssl/pem.h b/src/include/openssl/pem.h
index a6687a6..58aecaf 100644
--- a/src/include/openssl/pem.h
+++ b/src/include/openssl/pem.h
@@ -65,6 +65,10 @@
 #include <openssl/stack.h>
 #include <openssl/x509.h>
 
+/* For compatibility with open-iscsi, which assumes that it can get
+ * |OPENSSL_malloc| from pem.h or err.h */
+#include <openssl/crypto.h>
+
 #ifdef  __cplusplus
 extern "C" {
 #endif
@@ -120,6 +124,7 @@
 #define PEM_STRING_RSA_PUBLIC	"RSA PUBLIC KEY"
 #define PEM_STRING_DSA		"DSA PRIVATE KEY"
 #define PEM_STRING_DSA_PUBLIC	"DSA PUBLIC KEY"
+#define PEM_STRING_EC "EC PRIVATE KEY"
 #define PEM_STRING_PKCS7	"PKCS7"
 #define PEM_STRING_PKCS7_SIGNED	"PKCS #7 SIGNED DATA"
 #define PEM_STRING_PKCS8	"ENCRYPTED PRIVATE KEY"
@@ -129,7 +134,6 @@
 #define PEM_STRING_DSAPARAMS	"DSA PARAMETERS"
 #define PEM_STRING_ECDSA_PUBLIC "ECDSA PUBLIC KEY"
 #define PEM_STRING_ECPRIVATEKEY	"EC PRIVATE KEY"
-#define PEM_STRING_PARAMETERS	"PARAMETERS"
 #define PEM_STRING_CMS		"CMS"
 
   /* Note that this structure is initialised by PEM_SealInit and cleaned up
@@ -477,10 +481,6 @@
 
 OPENSSL_EXPORT int PEM_write_PKCS8PrivateKey(FILE *fp,EVP_PKEY *x,const EVP_CIPHER *enc, char *kstr,int klen, pem_password_cb *cd, void *u);
 
-OPENSSL_EXPORT EVP_PKEY *PEM_read_bio_Parameters(BIO *bp, EVP_PKEY **x);
-OPENSSL_EXPORT int PEM_write_bio_Parameters(BIO *bp, EVP_PKEY *x);
-
-
 OPENSSL_EXPORT EVP_PKEY *b2i_PrivateKey(const unsigned char **in, long length);
 OPENSSL_EXPORT EVP_PKEY *b2i_PublicKey(const unsigned char **in, long length);
 OPENSSL_EXPORT EVP_PKEY *b2i_PrivateKey_bio(BIO *in);
diff --git a/src/include/openssl/pkcs8.h b/src/include/openssl/pkcs8.h
index 6b51f85..d30ea8e 100644
--- a/src/include/openssl/pkcs8.h
+++ b/src/include/openssl/pkcs8.h
@@ -66,45 +66,57 @@
 #endif
 
 
-/* PKCS8_encrypt_pbe serializes and encrypts a PKCS8_PRIV_KEY_INFO with PBES1 or
+/* PKCS8_encrypt serializes and encrypts a PKCS8_PRIV_KEY_INFO with PBES1 or
  * PBES2 as defined in PKCS #5. Only pbeWithSHAAnd128BitRC4,
  * pbeWithSHAAnd3-KeyTripleDES-CBC and pbeWithSHA1And40BitRC2, defined in PKCS
  * #12, and PBES2, are supported.  PBES2 is selected by setting |cipher| and
  * passing -1 for |pbe_nid|.  Otherwise, PBES1 is used and |cipher| is ignored.
  *
- * The |pass_raw_len| bytes pointed to by |pass_raw| are used as the password.
- * Note that any conversions from the password as supplied in a text string
- * (such as those specified in B.1 of PKCS #12) must be performed by the caller.
+ * |pass| is used as the password. If a PBES1 scheme from PKCS #12 is used, this
+ * will be converted to a raw byte string as specified in B.1 of PKCS #12. If
+ * |pass| is NULL, it will be encoded as the empty byte string rather than two
+ * zero bytes, the PKCS #12 encoding of the empty string.
  *
  * If |salt| is NULL, a random salt of |salt_len| bytes is generated. If
  * |salt_len| is zero, a default salt length is used instead.
  *
- * The resulting structure is stored in an X509_SIG which must be freed by the
- * caller.
- *
- * TODO(davidben): Really? An X509_SIG? OpenSSL probably did that because it has
- * the same structure as EncryptedPrivateKeyInfo. */
-OPENSSL_EXPORT X509_SIG *PKCS8_encrypt_pbe(int pbe_nid,
-                                           const EVP_CIPHER *cipher,
-                                           const uint8_t *pass_raw,
-                                           size_t pass_raw_len,
-                                           uint8_t *salt, size_t salt_len,
-                                           int iterations,
-                                           PKCS8_PRIV_KEY_INFO *p8inf);
+ * The resulting structure is stored in an |X509_SIG| which must be freed by the
+ * caller. */
+OPENSSL_EXPORT X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher,
+                                       const char *pass, int pass_len,
+                                       const uint8_t *salt, size_t salt_len,
+                                       int iterations,
+                                       PKCS8_PRIV_KEY_INFO *p8inf);
 
-/* PKCS8_decrypt_pbe decrypts and decodes a PKCS8_PRIV_KEY_INFO with PBES1 or
- * PBES2 as defined in PKCS #5. Only pbeWithSHAAnd128BitRC4,
+/* PKCS8_marshal_encrypted_private_key behaves like |PKCS8_encrypt| but encrypts
+ * an |EVP_PKEY| and writes the serialized EncryptedPrivateKeyInfo to |out|. It
+ * returns one on success and zero on error. */
+OPENSSL_EXPORT int PKCS8_marshal_encrypted_private_key(
+    CBB *out, int pbe_nid, const EVP_CIPHER *cipher, const char *pass,
+    size_t pass_len, const uint8_t *salt, size_t salt_len, int iterations,
+    const EVP_PKEY *pkey);
+
+/* PKCS8_decrypt decrypts and decodes a PKCS8_PRIV_KEY_INFO with PBES1 or PBES2
+ * as defined in PKCS #5. Only pbeWithSHAAnd128BitRC4,
  * pbeWithSHAAnd3-KeyTripleDES-CBC and pbeWithSHA1And40BitRC2, and PBES2,
  * defined in PKCS #12, are supported.
  *
- * The |pass_raw_len| bytes pointed to by |pass_raw| are used as the password.
- * Note that any conversions from the password as supplied in a text string
- * (such as those specified in B.1 of PKCS #12) must be performed by the caller.
+ * |pass| is used as the password. If a PBES1 scheme from PKCS #12 is used, this
+ * will be converted to a raw byte string as specified in B.1 of PKCS #12. If
+ * |pass| is NULL, it will be encoded as the empty byte string rather than two
+ * zero bytes, the PKCS #12 encoding of the empty string.
  *
  * The resulting structure must be freed by the caller. */
-OPENSSL_EXPORT PKCS8_PRIV_KEY_INFO *PKCS8_decrypt_pbe(X509_SIG *pkcs8,
-                                                      const uint8_t *pass_raw,
-                                                      size_t pass_raw_len);
+OPENSSL_EXPORT PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(X509_SIG *pkcs8,
+                                                  const char *pass,
+                                                  int pass_len);
+
+/* PKCS8_parse_encrypted_private_key behaves like |PKCS8_decrypt| but it parses
+ * the EncryptedPrivateKeyInfo structure from |cbs| and advances |cbs|. It
+ * returns a newly-allocated |EVP_PKEY| on success and zero on error. */
+OPENSSL_EXPORT EVP_PKEY *PKCS8_parse_encrypted_private_key(CBS *cbs,
+                                                           const char *pass,
+                                                           size_t pass_len);
 
 /* PKCS12_get_key_and_certs parses a PKCS#12 structure from |in|, authenticates
  * and decrypts it using |password|, sets |*out_key| to the included private
@@ -117,34 +129,20 @@
 
 /* Deprecated functions. */
 
-/* PKCS8_encrypt calls |PKCS8_encrypt_pbe| after (in the PKCS#12 case) treating
- * |pass| as an ASCII string, appending U+0000, and converting to UCS-2. (So the
- * empty password encodes as two NUL bytes.) In the PBES2 case, the password is
- * unchanged.  */
-OPENSSL_EXPORT X509_SIG *PKCS8_encrypt(int pbe_nid, const EVP_CIPHER *cipher,
-                                       const char *pass, int pass_len,
-                                       uint8_t *salt, size_t salt_len,
-                                       int iterations,
-                                       PKCS8_PRIV_KEY_INFO *p8inf);
-
-/* PKCS8_decrypt calls PKCS8_decrypt_pbe after (in the PKCS#12 case) treating
- * |pass| as an ASCII string, appending U+0000, and converting to UCS-2. (So the
- *  empty password encodes as two NUL bytes.) In the PBES2 case, the password is
- * unchanged. */
-OPENSSL_EXPORT PKCS8_PRIV_KEY_INFO *PKCS8_decrypt(X509_SIG *pkcs8,
-                                                  const char *pass,
-                                                  int pass_len);
-
 /* PKCS12_PBE_add does nothing. It exists for compatibility with OpenSSL. */
 OPENSSL_EXPORT void PKCS12_PBE_add(void);
 
 /* d2i_PKCS12 is a dummy function that copies |*ber_bytes| into a
- * |PKCS12| structure. The |out_p12| argument must be NULL. On exit,
+ * |PKCS12| structure. The |out_p12| argument should be NULL(✝). On exit,
  * |*ber_bytes| will be advanced by |ber_len|. It returns a fresh |PKCS12|
  * structure or NULL on error.
  *
  * Note: unlike other d2i functions, |d2i_PKCS12| will always consume |ber_len|
- * bytes.*/
+ * bytes.
+ *
+ * (✝) If |out_p12| is not NULL and the function is successful, |*out_p12| will
+ * be freed if not NULL itself and the result will be written to |*out_p12|.
+ * New code should not depend on this. */
 OPENSSL_EXPORT PKCS12 *d2i_PKCS12(PKCS12 **out_p12, const uint8_t **ber_bytes,
                                   size_t ber_len);
 
@@ -183,6 +181,18 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+extern "C++" {
+
+namespace bssl {
+
+BORINGSSL_MAKE_DELETER(PKCS12, PKCS12_free)
+BORINGSSL_MAKE_DELETER(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free)
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #define PKCS8_R_BAD_PKCS12_DATA 100
diff --git a/src/include/openssl/pool.h b/src/include/openssl/pool.h
new file mode 100644
index 0000000..dc5c938
--- /dev/null
+++ b/src/include/openssl/pool.h
@@ -0,0 +1,87 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#ifndef OPENSSL_HEADER_POOL_H
+#define OPENSSL_HEADER_POOL_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+/* Buffers and buffer pools.
+ *
+ * |CRYPTO_BUFFER|s are simply reference-counted blobs. A |CRYPTO_BUFFER_POOL|
+ * is an intern table for |CRYPTO_BUFFER|s. This allows for a single copy of a
+ * given blob to be kept in memory and referenced from multiple places. */
+
+
+/* CRYPTO_BUFFER_POOL_new returns a freshly allocated |CRYPTO_BUFFER_POOL| or
+ * NULL on error. */
+OPENSSL_EXPORT CRYPTO_BUFFER_POOL* CRYPTO_BUFFER_POOL_new(void);
+
+/* CRYPTO_BUFFER_POOL_free frees |pool|, which must be empty. */
+OPENSSL_EXPORT void CRYPTO_BUFFER_POOL_free(CRYPTO_BUFFER_POOL *pool);
+
+/* CRYPTO_BUFFER_new returns a |CRYPTO_BUFFER| containing a copy of |data|, or
+ * else NULL on error. If |pool| is not NULL then the returned value may be a
+ * reference to a previously existing |CRYPTO_BUFFER| that contained the same
+ * data. Otherwise, the returned, fresh |CRYPTO_BUFFER| will be added to the
+ * pool. */
+OPENSSL_EXPORT CRYPTO_BUFFER *CRYPTO_BUFFER_new(const uint8_t *data, size_t len,
+                                                CRYPTO_BUFFER_POOL *pool);
+
+/* CRYPTO_BUFFER_new_from_CBS acts the same as |CRYPTO_BUFFER_new|. */
+OPENSSL_EXPORT CRYPTO_BUFFER *CRYPTO_BUFFER_new_from_CBS(
+    CBS *cbs, CRYPTO_BUFFER_POOL *pool);
+
+/* CRYPTO_BUFFER_free decrements the reference count of |buf|. If there are no
+ * other references, or if the only remaining reference is from a pool, then
+ * |buf| will be freed. */
+OPENSSL_EXPORT void CRYPTO_BUFFER_free(CRYPTO_BUFFER *buf);
+
+/* CRYPTO_BUFFER_up_ref increments the reference count of |buf| and returns
+ * one. */
+OPENSSL_EXPORT int CRYPTO_BUFFER_up_ref(CRYPTO_BUFFER *buf);
+
+/* CRYPTO_BUFFER_data returns a pointer to the data contained in |buf|. */
+OPENSSL_EXPORT const uint8_t *CRYPTO_BUFFER_data(const CRYPTO_BUFFER *buf);
+
+/* CRYPTO_BUFFER_len returns the length, in bytes, of the data contained in
+ * |buf|. */
+OPENSSL_EXPORT size_t CRYPTO_BUFFER_len(const CRYPTO_BUFFER *buf);
+
+/* CRYPTO_BUFFER_init_CBS initialises |out| to point at the data from |buf|. */
+OPENSSL_EXPORT void CRYPTO_BUFFER_init_CBS(const CRYPTO_BUFFER *buf, CBS *out);
+
+
+#if defined(__cplusplus)
+}  /* extern C */
+
+extern "C++" {
+
+namespace bssl {
+
+BORINGSSL_MAKE_DELETER(CRYPTO_BUFFER_POOL, CRYPTO_BUFFER_POOL_free)
+BORINGSSL_MAKE_DELETER(CRYPTO_BUFFER, CRYPTO_BUFFER_free)
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
+#endif
+
+#endif  // OPENSSL_HEADER_POOL_H
diff --git a/src/include/openssl/pqueue.h b/src/include/openssl/pqueue.h
deleted file mode 100644
index ceb1fa2..0000000
--- a/src/include/openssl/pqueue.h
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * DTLS implementation written by Nagendra Modadugu
- * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
- */
-/* ====================================================================
- * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- *    software must display the following acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- *    endorse or promote products derived from this software without
- *    prior written permission. For written permission, please contact
- *    openssl-core@OpenSSL.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- *    nor may "OpenSSL" appear in their names without prior written
- *    permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- *    acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- *
- * This product includes cryptographic software written by Eric Young
- * (eay@cryptsoft.com).  This product includes software written by Tim
- * Hudson (tjh@cryptsoft.com). */
-
-#ifndef OPENSSL_HEADER_PQUEUE_H
-#define OPENSSL_HEADER_PQUEUE_H
-
-#include <openssl/base.h>
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
-
-
-/* Priority queue.
- *
- * The priority queue maintains a linked-list of nodes, each with a unique,
- * 64-bit priority, in ascending priority order. */
-
-typedef struct _pqueue *pqueue;
-
-typedef struct _pitem {
-  uint8_t priority[8]; /* 64-bit value in big-endian encoding */
-  void *data;
-  struct _pitem *next;
-} pitem;
-
-typedef struct _pitem *piterator;
-
-
-/* Creating and freeing queues. */
-
-/* pqueue_new allocates a fresh, empty priority queue object and returns it, or
- * NULL on error. */
-OPENSSL_EXPORT pqueue pqueue_new(void);
-
-/* pqueue_free frees |pq| but not any of the items it points to. Thus |pq| must
- * be empty or a memory leak will occur. */
-OPENSSL_EXPORT void pqueue_free(pqueue pq);
-
-
-/* Creating and freeing items. */
-
-/* pitem_new allocates a fresh priority queue item that points at |data| and
- * has a priority given by |prio64be|, which is a 64-bit, unsigned number
- * expressed in big-endian form. It returns the fresh item, or NULL on
- * error. */
-OPENSSL_EXPORT pitem *pitem_new(uint8_t prio64be[8], void *data);
-
-/* pitem_free frees |item|, but not any data that it points to. */
-OPENSSL_EXPORT void pitem_free(pitem *item);
-
-
-/* Queue accessor functions */
-
-/* pqueue_peek returns the item with the smallest priority from |pq|, or NULL
- * if empty. */
-OPENSSL_EXPORT pitem *pqueue_peek(pqueue pq);
-
-/* pqueue_find returns the item whose priority matches |prio64be| or NULL if no
- * such item exists. */
-OPENSSL_EXPORT pitem *pqueue_find(pqueue pq, uint8_t *prio64be);
-
-
-/* Queue mutation functions */
-
-/* pqueue_insert inserts |item| into |pq| and returns item. */
-OPENSSL_EXPORT pitem *pqueue_insert(pqueue pq, pitem *item);
-
-/* pqueue_pop takes the item with the least priority from |pq| and returns it,
- * or NULL if |pq| is empty. */
-OPENSSL_EXPORT pitem *pqueue_pop(pqueue pq);
-
-/* pqueue_size returns the number of items in |pq|. */
-OPENSSL_EXPORT size_t pqueue_size(pqueue pq);
-
-
-/* Iterating */
-
-/* pqueue_iterator returns an iterator that can be used to iterate over the
- * contents of the queue. */
-OPENSSL_EXPORT piterator pqueue_iterator(pqueue pq);
-
-/* pqueue_next returns the current value of |iter| and advances it to the next
- * position. If the iterator has advanced over all the elements, it returns
- * NULL. */
-OPENSSL_EXPORT pitem *pqueue_next(piterator *iter);
-
-
-#if defined(__cplusplus)
-}  /* extern C */
-#endif
-
-#endif  /* OPENSSL_HEADER_PQUEUE_H */
diff --git a/src/include/openssl/rand.h b/src/include/openssl/rand.h
index 2c9c969..0e9a8cd 100644
--- a/src/include/openssl/rand.h
+++ b/src/include/openssl/rand.h
@@ -62,6 +62,12 @@
 OPENSSL_EXPORT void RAND_enable_fork_unsafe_buffering(int fd);
 #endif
 
+#if defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE)
+/* RAND_reset_for_fuzzing resets the fuzzer-only deterministic RNG. This
+ * function is only defined in the fuzzer-only build configuration. */
+OPENSSL_EXPORT void RAND_reset_for_fuzzing(void);
+#endif
+
 
 /* Deprecated functions */
 
diff --git a/src/include/openssl/rc4.h b/src/include/openssl/rc4.h
index 0619cac..68af878 100644
--- a/src/include/openssl/rc4.h
+++ b/src/include/openssl/rc4.h
@@ -83,6 +83,12 @@
                         uint8_t *out);
 
 
+/* Deprecated functions. */
+
+/* RC4_options returns the string "rc4(ptr,int)". */
+OPENSSL_EXPORT const char *RC4_options(void);
+
+
 #if defined(__cplusplus)
 }  /* extern C */
 #endif
diff --git a/src/crypto/dsa/internal.h b/src/include/openssl/ripemd.h
similarity index 67%
copy from src/crypto/dsa/internal.h
copy to src/include/openssl/ripemd.h
index ef99158..cf1e49e 100644
--- a/src/crypto/dsa/internal.h
+++ b/src/include/openssl/ripemd.h
@@ -52,27 +52,56 @@
  * The licence and distribution terms for any publically available version or
  * derivative of this code cannot be changed.  i.e. this code cannot simply be
  * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- *
- * The DSS routines are based on patches supplied by
- * Steven Schoch <schoch@sheba.arc.nasa.gov>. */
+ * [including the GNU Public Licence.] */
 
-#ifndef OPENSSL_HEADER_DSA_INTERNAL_H
-#define OPENSSL_HEADER_DSA_INTERNAL_H
+#ifndef OPENSSL_HEADER_RIPEMD_H
+#define OPENSSL_HEADER_RIPEMD_H
 
 #include <openssl/base.h>
 
-#include <openssl/bn.h>
-#include <openssl/ex_data.h>
-
-#if defined(__cplusplus)
+#ifdef  __cplusplus
 extern "C" {
 #endif
 
 
+# define RIPEMD160_CBLOCK        64
+# define RIPEMD160_LBLOCK        (RIPEMD160_CBLOCK/4)
+# define RIPEMD160_DIGEST_LENGTH 20
+
+struct RIPEMD160state_st {
+  uint32_t h[5];
+  uint32_t Nl, Nh;
+  uint8_t data[RIPEMD160_CBLOCK];
+  unsigned num;
+};
+
+/* RIPEMD160_Init initialises |ctx| and returns one. */
+OPENSSL_EXPORT int RIPEMD160_Init(RIPEMD160_CTX *ctx);
+
+/* RIPEMD160_Update adds |len| bytes from |data| to |ctx| and returns one. */
+OPENSSL_EXPORT int RIPEMD160_Update(RIPEMD160_CTX *ctx, const void *data,
+                                   size_t len);
+
+/* RIPEMD160_Final adds the final padding to |ctx| and writes the resulting
+ * digest to |md|, which must have at least |RIPEMD160_DIGEST_LENGTH| bytes of
+ * space. It returns one. */
+OPENSSL_EXPORT int RIPEMD160_Final(uint8_t *md, RIPEMD160_CTX *ctx);
+
+/* RIPEMD160 writes the digest of |len| bytes from |data| to |out| and returns
+ * |out|. There must be at least |RIPEMD160_DIGEST_LENGTH| bytes of space in
+ * |out|. */
+OPENSSL_EXPORT uint8_t *RIPEMD160(const uint8_t *data, size_t len,
+                                  uint8_t *out);
+
+/* RIPEMD160_Transform is a low-level function that performs a single,
+ * RIPEMD160 block transformation using the state from |ctx| and 64 bytes from
+ * |block|. */
+OPENSSL_EXPORT void RIPEMD160_Transform(RIPEMD160_CTX *ctx,
+                                        const uint8_t *block);
+
 
 #if defined(__cplusplus)
 }  /* extern C */
 #endif
 
-#endif  /* OPENSSL_HEADER_DSA_INTERNAL_H */
+#endif  /* OPENSSL_HEADER_RIPEMD_H */
diff --git a/src/include/openssl/rsa.h b/src/include/openssl/rsa.h
index 304c555..d8f76f0 100644
--- a/src/include/openssl/rsa.h
+++ b/src/include/openssl/rsa.h
@@ -59,7 +59,6 @@
 
 #include <openssl/base.h>
 
-#include <openssl/asn1.h>
 #include <openssl/engine.h>
 #include <openssl/ex_data.h>
 #include <openssl/thread.h>
@@ -84,10 +83,34 @@
  * reference count drops to zero. */
 OPENSSL_EXPORT void RSA_free(RSA *rsa);
 
-/* RSA_up_ref increments the reference count of |rsa|. */
+/* RSA_up_ref increments the reference count of |rsa| and returns one. */
 OPENSSL_EXPORT int RSA_up_ref(RSA *rsa);
 
 
+/* Properties. */
+
+/* RSA_get0_key sets |*out_n|, |*out_e|, and |*out_d|, if non-NULL, to |rsa|'s
+ * modulus, public exponent, and private exponent, respectively. If |rsa| is a
+ * public key, the private exponent will be set to NULL. */
+OPENSSL_EXPORT void RSA_get0_key(const RSA *rsa, const BIGNUM **out_n,
+                                 const BIGNUM **out_e, const BIGNUM **out_d);
+
+/* RSA_get0_factors sets |*out_p| and |*out_q|, if non-NULL, to |rsa|'s prime
+ * factors. If |rsa| is a public key, they will be set to NULL. If |rsa| is a
+ * multi-prime key, only the first two prime factors will be reported. */
+OPENSSL_EXPORT void RSA_get0_factors(const RSA *rsa, const BIGNUM **out_p,
+                                     const BIGNUM **out_q);
+
+/* RSA_get0_crt_params sets |*out_dmp1|, |*out_dmq1|, and |*out_iqmp|, if
+ * non-NULL, to |rsa|'s CRT parameters. These are d (mod p-1), d (mod q-1) and
+ * q^-1 (mod p), respectively. If |rsa| is a public key, each parameter will be
+ * set to NULL. If |rsa| is a multi-prime key, only the CRT parameters for the
+ * first two primes will be reported. */
+OPENSSL_EXPORT void RSA_get0_crt_params(const RSA *rsa, const BIGNUM **out_dmp1,
+                                        const BIGNUM **out_dmq1,
+                                        const BIGNUM **out_iqmp);
+
+
 /* Key generation. */
 
 /* RSA_generate_key_ex generates a new RSA key where the modulus has size
@@ -299,7 +322,9 @@
  * hash function for generating the mask. If NULL, |Hash| is used. The |sLen|
  * argument specifies the expected salt length in bytes. If |sLen| is -1 then
  * the salt length is the same as the hash length. If -2, then the salt length
- * is maximal and is taken from the size of |EM|.
+ * is recovered and all values accepted.
+ *
+ * If unsure, use -1.
  *
  * It returns one on success or zero on error. */
 OPENSSL_EXPORT int RSA_verify_PKCS1_PSS_mgf1(RSA *rsa, const uint8_t *mHash,
@@ -322,6 +347,17 @@
                                                   const EVP_MD *mgf1Hash,
                                                   int sLen);
 
+/* RSA_padding_add_PKCS1_OAEP_mgf1 writes an OAEP padding of |from| to |to|
+ * with the given parameters and hash functions. If |md| is NULL then SHA-1 is
+ * used. If |mgf1md| is NULL then the value of |md| is used (which means SHA-1
+ * if that, in turn, is NULL).
+ *
+ * It returns one on success or zero on error. */
+OPENSSL_EXPORT int RSA_padding_add_PKCS1_OAEP_mgf1(
+    uint8_t *to, size_t to_len, const uint8_t *from, size_t from_len,
+    const uint8_t *param, size_t param_len, const EVP_MD *md,
+    const EVP_MD *mgf1md);
+
 /* RSA_add_pkcs1_prefix builds a version of |msg| prefixed with the DigestInfo
  * header for the given hash function and sets |out_msg| to point to it. On
  * successful return, |*out_msg| may be allocated memory and, if so,
@@ -400,20 +436,21 @@
  * API, like a platform key store. */
 #define RSA_FLAG_OPAQUE 1
 
-/* RSA_FLAG_CACHE_PUBLIC causes a precomputed Montgomery context to be created,
- * on demand, for the public key operations. */
+/* Deprecated and ignored. */
 #define RSA_FLAG_CACHE_PUBLIC 2
 
-/* RSA_FLAG_CACHE_PRIVATE causes a precomputed Montgomery context to be
- * created, on demand, for the private key operations. */
+/* Deprecated and ignored. */
 #define RSA_FLAG_CACHE_PRIVATE 4
 
-/* RSA_FLAG_NO_BLINDING disables blinding of private operations. */
+/* RSA_FLAG_NO_BLINDING disables blinding of private operations, which is a
+ * dangerous thing to do. It is deprecated and should not be used. It will
+ * be ignored whenever possible.
+ *
+ * This flag must be used if a key without the public exponent |e| is used for
+ * private key operations; avoid using such keys whenever possible. */
 #define RSA_FLAG_NO_BLINDING 8
 
-/* RSA_FLAG_EXT_PKEY means that private key operations will be handled by
- * |mod_exp| and that they do not depend on the private key components being
- * present: for example a key stored in external hardware. */
+/* RSA_FLAG_EXT_PKEY is deprecated and ignored. */
 #define RSA_FLAG_EXT_PKEY 0x20
 
 /* RSA_FLAG_SIGN_VER causes the |sign| and |verify| functions of |rsa_meth_st|
@@ -441,10 +478,10 @@
 
 /* d2i_RSAPublicKey parses an ASN.1, DER-encoded, RSA public key from |len|
  * bytes at |*inp|. If |out| is not NULL then, on exit, a pointer to the result
- * is in |*out|. If |*out| is already non-NULL on entry then the result is
- * written directly into |*out|, otherwise a fresh |RSA| is allocated. On
- * successful exit, |*inp| is advanced past the DER structure. It returns the
- * result or NULL on error. */
+ * is in |*out|. Note that, even if |*out| is already non-NULL on entry, it
+ * will not be written to. Rather, a fresh |RSA| is allocated and the previous
+ * one is freed. On successful exit, |*inp| is advanced past the DER structure.
+ * It returns the result or NULL on error. */
 OPENSSL_EXPORT RSA *d2i_RSAPublicKey(RSA **out, const uint8_t **inp, long len);
 
 /* i2d_RSAPublicKey marshals |in| to an ASN.1, DER structure. If |outp| is not
@@ -455,10 +492,10 @@
 
 /* d2i_RSAPrivateKey parses an ASN.1, DER-encoded, RSA private key from |len|
  * bytes at |*inp|. If |out| is not NULL then, on exit, a pointer to the result
- * is in |*out|. If |*out| is already non-NULL on entry then the result is
- * written directly into |*out|, otherwise a fresh |RSA| is allocated. On
- * successful exit, |*inp| is advanced past the DER structure. It returns the
- * result or NULL on error. */
+ * is in |*out|. Note that, even if |*out| is already non-NULL on entry, it
+ * will not be written to. Rather, a fresh |RSA| is allocated and the previous
+ * one is freed. On successful exit, |*inp| is advanced past the DER structure.
+ * It returns the result or NULL on error. */
 OPENSSL_EXPORT RSA *d2i_RSAPrivateKey(RSA **out, const uint8_t **inp, long len);
 
 /* i2d_RSAPrivateKey marshals |in| to an ASN.1, DER structure. If |outp| is not
@@ -467,14 +504,26 @@
  * not, or a negative value on error. */
 OPENSSL_EXPORT int i2d_RSAPrivateKey(const RSA *in, uint8_t **outp);
 
-typedef struct rsa_pss_params_st {
-  X509_ALGOR *hashAlgorithm;
-  X509_ALGOR *maskGenAlgorithm;
-  ASN1_INTEGER *saltLength;
-  ASN1_INTEGER *trailerField;
-} RSA_PSS_PARAMS;
+/* RSA_padding_add_PKCS1_PSS acts like |RSA_padding_add_PKCS1_PSS_mgf1| but the
+ * |mgf1Hash| parameter of the latter is implicitly set to |Hash|. */
+OPENSSL_EXPORT int RSA_padding_add_PKCS1_PSS(RSA *rsa, uint8_t *EM,
+                                             const uint8_t *mHash,
+                                             const EVP_MD *Hash, int sLen);
 
-DECLARE_ASN1_FUNCTIONS(RSA_PSS_PARAMS)
+/* RSA_verify_PKCS1_PSS acts like |RSA_verify_PKCS1_PSS_mgf1| but the
+ * |mgf1Hash| parameter of the latter is implicitly set to |Hash|. */
+OPENSSL_EXPORT int RSA_verify_PKCS1_PSS(RSA *rsa, const uint8_t *mHash,
+                                        const EVP_MD *Hash, const uint8_t *EM,
+                                        int sLen);
+
+/* RSA_padding_add_PKCS1_OAEP acts like |RSA_padding_add_PKCS1_OAEP_mgf1| but
+ * the |md| and |mgf1md| parameters of the latter are implicitly set to NULL,
+ * which means SHA-1. */
+OPENSSL_EXPORT int RSA_padding_add_PKCS1_OAEP(uint8_t *to, size_t to_len,
+                                              const uint8_t *from,
+                                              size_t from_len,
+                                              const uint8_t *param,
+                                              size_t param_len);
 
 
 struct rsa_meth_st {
@@ -491,6 +540,7 @@
   int (*sign)(int type, const uint8_t *m, unsigned int m_length,
               uint8_t *sigret, unsigned int *siglen, const RSA *rsa);
 
+  /* Ignored. Set this to NULL. */
   int (*verify)(int dtype, const uint8_t *m, unsigned int m_length,
                 const uint8_t *sigbuf, unsigned int siglen, const RSA *rsa);
 
@@ -503,6 +553,7 @@
 
   int (*decrypt)(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
                  const uint8_t *in, size_t in_len, int padding);
+  /* Ignored. Set this to NULL. */
   int (*verify_raw)(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
                     const uint8_t *in, size_t in_len, int padding);
 
@@ -521,8 +572,10 @@
   int (*private_transform)(RSA *rsa, uint8_t *out, const uint8_t *in,
                            size_t len);
 
-  int (*mod_exp)(BIGNUM *r0, const BIGNUM *I, RSA *rsa,
-                 BN_CTX *ctx); /* Can be null */
+  /* mod_exp is deprecated and ignored. Set it to NULL. */
+  int (*mod_exp)(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx);
+
+  /* bn_mod_exp is deprecated and ignored. Set it to NULL. */
   int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
                     const BIGNUM *m, BN_CTX *ctx,
                     const BN_MONT_CTX *mont);
@@ -585,53 +638,64 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+extern "C++" {
+
+namespace bssl {
+
+BORINGSSL_MAKE_DELETER(RSA, RSA_free)
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
-#define RSA_R_BAD_E_VALUE 100
-#define RSA_R_BAD_FIXED_HEADER_DECRYPT 101
-#define RSA_R_BAD_PAD_BYTE_COUNT 102
-#define RSA_R_BAD_RSA_PARAMETERS 103
-#define RSA_R_BAD_SIGNATURE 104
-#define RSA_R_BLOCK_TYPE_IS_NOT_01 105
-#define RSA_R_BN_NOT_INITIALIZED 106
-#define RSA_R_CRT_PARAMS_ALREADY_GIVEN 107
-#define RSA_R_CRT_VALUES_INCORRECT 108
-#define RSA_R_DATA_LEN_NOT_EQUAL_TO_MOD_LEN 109
-#define RSA_R_DATA_TOO_LARGE 110
-#define RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE 111
-#define RSA_R_DATA_TOO_LARGE_FOR_MODULUS 112
-#define RSA_R_DATA_TOO_SMALL 113
-#define RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE 114
-#define RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY 115
-#define RSA_R_D_E_NOT_CONGRUENT_TO_1 116
-#define RSA_R_EMPTY_PUBLIC_KEY 117
-#define RSA_R_FIRST_OCTET_INVALID 118
-#define RSA_R_INCONSISTENT_SET_OF_CRT_VALUES 119
-#define RSA_R_INTERNAL_ERROR 120
-#define RSA_R_INVALID_MESSAGE_LENGTH 121
-#define RSA_R_KEY_SIZE_TOO_SMALL 122
-#define RSA_R_LAST_OCTET_INVALID 123
-#define RSA_R_MODULUS_TOO_LARGE 124
-#define RSA_R_NO_PUBLIC_EXPONENT 125
-#define RSA_R_NULL_BEFORE_BLOCK_MISSING 126
-#define RSA_R_N_NOT_EQUAL_P_Q 127
-#define RSA_R_OAEP_DECODING_ERROR 128
-#define RSA_R_ONLY_ONE_OF_P_Q_GIVEN 129
-#define RSA_R_OUTPUT_BUFFER_TOO_SMALL 130
-#define RSA_R_PADDING_CHECK_FAILED 131
-#define RSA_R_PKCS_DECODING_ERROR 132
-#define RSA_R_SLEN_CHECK_FAILED 133
-#define RSA_R_SLEN_RECOVERY_FAILED 134
-#define RSA_R_TOO_LONG 135
-#define RSA_R_TOO_MANY_ITERATIONS 136
-#define RSA_R_UNKNOWN_ALGORITHM_TYPE 137
-#define RSA_R_UNKNOWN_PADDING_TYPE 138
-#define RSA_R_VALUE_MISSING 139
-#define RSA_R_WRONG_SIGNATURE_LENGTH 140
-#define RSA_R_MUST_HAVE_AT_LEAST_TWO_PRIMES 141
-#define RSA_R_CANNOT_RECOVER_MULTI_PRIME_KEY 142
-#define RSA_R_BAD_ENCODING 143
-#define RSA_R_ENCODE_ERROR 144
-#define RSA_R_BAD_VERSION 145
+#define RSA_R_BAD_ENCODING 100
+#define RSA_R_BAD_E_VALUE 101
+#define RSA_R_BAD_FIXED_HEADER_DECRYPT 102
+#define RSA_R_BAD_PAD_BYTE_COUNT 103
+#define RSA_R_BAD_RSA_PARAMETERS 104
+#define RSA_R_BAD_SIGNATURE 105
+#define RSA_R_BAD_VERSION 106
+#define RSA_R_BLOCK_TYPE_IS_NOT_01 107
+#define RSA_R_BN_NOT_INITIALIZED 108
+#define RSA_R_CANNOT_RECOVER_MULTI_PRIME_KEY 109
+#define RSA_R_CRT_PARAMS_ALREADY_GIVEN 110
+#define RSA_R_CRT_VALUES_INCORRECT 111
+#define RSA_R_DATA_LEN_NOT_EQUAL_TO_MOD_LEN 112
+#define RSA_R_DATA_TOO_LARGE 113
+#define RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE 114
+#define RSA_R_DATA_TOO_LARGE_FOR_MODULUS 115
+#define RSA_R_DATA_TOO_SMALL 116
+#define RSA_R_DATA_TOO_SMALL_FOR_KEY_SIZE 117
+#define RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY 118
+#define RSA_R_D_E_NOT_CONGRUENT_TO_1 119
+#define RSA_R_EMPTY_PUBLIC_KEY 120
+#define RSA_R_ENCODE_ERROR 121
+#define RSA_R_FIRST_OCTET_INVALID 122
+#define RSA_R_INCONSISTENT_SET_OF_CRT_VALUES 123
+#define RSA_R_INTERNAL_ERROR 124
+#define RSA_R_INVALID_MESSAGE_LENGTH 125
+#define RSA_R_KEY_SIZE_TOO_SMALL 126
+#define RSA_R_LAST_OCTET_INVALID 127
+#define RSA_R_MODULUS_TOO_LARGE 128
+#define RSA_R_MUST_HAVE_AT_LEAST_TWO_PRIMES 129
+#define RSA_R_NO_PUBLIC_EXPONENT 130
+#define RSA_R_NULL_BEFORE_BLOCK_MISSING 131
+#define RSA_R_N_NOT_EQUAL_P_Q 132
+#define RSA_R_OAEP_DECODING_ERROR 133
+#define RSA_R_ONLY_ONE_OF_P_Q_GIVEN 134
+#define RSA_R_OUTPUT_BUFFER_TOO_SMALL 135
+#define RSA_R_PADDING_CHECK_FAILED 136
+#define RSA_R_PKCS_DECODING_ERROR 137
+#define RSA_R_SLEN_CHECK_FAILED 138
+#define RSA_R_SLEN_RECOVERY_FAILED 139
+#define RSA_R_TOO_LONG 140
+#define RSA_R_TOO_MANY_ITERATIONS 141
+#define RSA_R_UNKNOWN_ALGORITHM_TYPE 142
+#define RSA_R_UNKNOWN_PADDING_TYPE 143
+#define RSA_R_VALUE_MISSING 144
+#define RSA_R_WRONG_SIGNATURE_LENGTH 145
 
 #endif  /* OPENSSL_HEADER_RSA_H */
diff --git a/src/include/openssl/sha.h b/src/include/openssl/sha.h
index 48a52e8f..7c31097 100644
--- a/src/include/openssl/sha.h
+++ b/src/include/openssl/sha.h
@@ -73,10 +73,6 @@
 /* SHA_DIGEST_LENGTH is the length of a SHA-1 digest. */
 #define SHA_DIGEST_LENGTH 20
 
-/* TODO(fork): remove */
-#define SHA_LBLOCK 16
-#define SHA_LONG uint32_t
-
 /* SHA1_Init initialises |sha| and returns one. */
 OPENSSL_EXPORT int SHA1_Init(SHA_CTX *sha);
 
@@ -94,7 +90,8 @@
 OPENSSL_EXPORT uint8_t *SHA1(const uint8_t *data, size_t len, uint8_t *out);
 
 /* SHA1_Transform is a low-level function that performs a single, SHA-1 block
- * transformation using the state from |sha| and 64 bytes from |block|. */
+ * transformation using the state from |sha| and |SHA_CBLOCK| bytes from
+ * |block|. */
 OPENSSL_EXPORT void SHA1_Transform(SHA_CTX *sha, const uint8_t *block);
 
 struct sha_state_st {
@@ -169,9 +166,10 @@
  * |out|. */
 OPENSSL_EXPORT uint8_t *SHA256(const uint8_t *data, size_t len, uint8_t *out);
 
-/* SHA256_Transform is a low-level function that performs a single, SHA-1 block
- * transformation using the state from |sha| and 64 bytes from |block|. */
-OPENSSL_EXPORT void SHA256_Transform(SHA256_CTX *sha, const uint8_t *data);
+/* SHA256_Transform is a low-level function that performs a single, SHA-256
+ * block transformation using the state from |sha| and |SHA256_CBLOCK| bytes
+ * from |block|. */
+OPENSSL_EXPORT void SHA256_Transform(SHA256_CTX *sha, const uint8_t *block);
 
 struct sha256_state_st {
   uint32_t h[8];
@@ -205,9 +203,10 @@
  * |out|. */
 OPENSSL_EXPORT uint8_t *SHA384(const uint8_t *data, size_t len, uint8_t *out);
 
-/* SHA384_Transform is a low-level function that performs a single, SHA-1 block
- * transformation using the state from |sha| and 64 bytes from |block|. */
-OPENSSL_EXPORT void SHA384_Transform(SHA512_CTX *sha, const uint8_t *data);
+/* SHA384_Transform is a low-level function that performs a single, SHA-384
+ * block transformation using the state from |sha| and |SHA384_CBLOCK| bytes
+ * from |block|. */
+OPENSSL_EXPORT void SHA384_Transform(SHA512_CTX *sha, const uint8_t *block);
 
 
 /* SHA-512. */
@@ -234,9 +233,10 @@
  * |out|. */
 OPENSSL_EXPORT uint8_t *SHA512(const uint8_t *data, size_t len, uint8_t *out);
 
-/* SHA512_Transform is a low-level function that performs a single, SHA-1 block
- * transformation using the state from |sha| and 64 bytes from |block|. */
-OPENSSL_EXPORT void SHA512_Transform(SHA512_CTX *sha, const uint8_t *data);
+/* SHA512_Transform is a low-level function that performs a single, SHA-512
+ * block transformation using the state from |sha| and |SHA512_CBLOCK| bytes
+ * from |block|. */
+OPENSSL_EXPORT void SHA512_Transform(SHA512_CTX *sha, const uint8_t *block);
 
 struct sha512_state_st {
   uint64_t h[8];
diff --git a/src/include/openssl/ssl.h b/src/include/openssl/ssl.h
index dcfee91..5182df7 100644
--- a/src/include/openssl/ssl.h
+++ b/src/include/openssl/ssl.h
@@ -158,9 +158,6 @@
 #include <sys/time.h>
 #endif
 
-/* wpa_supplicant expects to get the version functions from ssl.h */
-#include <openssl/crypto.h>
-
 /* Forward-declare struct timeval. On Windows, it is defined in winsock2.h and
  * Windows headers define too many macros to be included in public headers.
  * However, only a forward declaration is needed. */
@@ -190,10 +187,17 @@
 /* DTLS_method is the |SSL_METHOD| used for DTLS connections. */
 OPENSSL_EXPORT const SSL_METHOD *DTLS_method(void);
 
+/* TLS_with_buffers_method is like |TLS_method|, but avoids all use of
+ * crypto/x509. */
+OPENSSL_EXPORT const SSL_METHOD *TLS_with_buffers_method(void);
+
 /* SSL_CTX_new returns a newly-allocated |SSL_CTX| with default settings or NULL
  * on error. */
 OPENSSL_EXPORT SSL_CTX *SSL_CTX_new(const SSL_METHOD *method);
 
+/* SSL_CTX_up_ref increments the reference count of |ctx|. It returns one. */
+OPENSSL_EXPORT int SSL_CTX_up_ref(SSL_CTX *ctx);
+
 /* SSL_CTX_free releases memory associated with |ctx|. */
 OPENSSL_EXPORT void SSL_CTX_free(SSL_CTX *ctx);
 
@@ -228,18 +232,45 @@
 
 /* SSL_is_server returns one if |ssl| is configured as a server and zero
  * otherwise. */
-OPENSSL_EXPORT int SSL_is_server(SSL *ssl);
+OPENSSL_EXPORT int SSL_is_server(const SSL *ssl);
+
+/* SSL_is_dtls returns one if |ssl| is a DTLS connection and zero otherwise. */
+OPENSSL_EXPORT int SSL_is_dtls(const SSL *ssl);
 
 /* SSL_set_bio configures |ssl| to read from |rbio| and write to |wbio|. |ssl|
  * takes ownership of the two |BIO|s. If |rbio| and |wbio| are the same, |ssl|
  * only takes ownership of one reference.
  *
- * In DTLS, if |rbio| is blocking, it must handle
- * |BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT| control requests to set read timeouts.
+ * In DTLS, |rbio| must be non-blocking to properly handle timeouts and
+ * retransmits.
  *
- * Calling this function on an already-configured |ssl| is deprecated. */
+ * If |rbio| is the same as the currently configured |BIO| for reading, that
+ * side is left untouched and is not freed.
+ *
+ * If |wbio| is the same as the currently configured |BIO| for writing AND |ssl|
+ * is not currently configured to read from and write to the same |BIO|, that
+ * side is left untouched and is not freed. This asymmetry is present for
+ * historical reasons.
+ *
+ * Due to the very complex historical behavior of this function, calling this
+ * function if |ssl| already has |BIO|s configured is deprecated. Prefer
+ * |SSL_set0_rbio| and |SSL_set0_wbio| instead. */
 OPENSSL_EXPORT void SSL_set_bio(SSL *ssl, BIO *rbio, BIO *wbio);
 
+/* SSL_set0_rbio configures |ssl| to write to |rbio|. It takes ownership of
+ * |rbio|.
+ *
+ * Note that, although this function and |SSL_set0_wbio| may be called on the
+ * same |BIO|, each call takes a reference. Use |BIO_up_ref| to balance this. */
+OPENSSL_EXPORT void SSL_set0_rbio(SSL *ssl, BIO *rbio);
+
+/* SSL_set0_wbio configures |ssl| to write to |wbio|. It takes ownership of
+ * |wbio|.
+ *
+ * Note that, although this function and |SSL_set0_rbio| may be called on the
+ * same |BIO|, each call takes a reference. Use |BIO_up_ref| to balance this. */
+OPENSSL_EXPORT void SSL_set0_wbio(SSL *ssl, BIO *wbio);
+
 /* SSL_get_rbio returns the |BIO| that |ssl| reads from. */
 OPENSSL_EXPORT BIO *SSL_get_rbio(const SSL *ssl);
 
@@ -251,25 +282,39 @@
 
 /* SSL_get_rfd returns the file descriptor that |ssl| is configured to read
  * from. If |ssl|'s read |BIO| is not configured or doesn't wrap a file
- * descriptor then it returns -1. */
+ * descriptor then it returns -1.
+ *
+ * Note: On Windows, this may return either a file descriptor or a socket (cast
+ * to int), depending on whether |ssl| was configured with a file descriptor or
+ * socket |BIO|. */
 OPENSSL_EXPORT int SSL_get_rfd(const SSL *ssl);
 
 /* SSL_get_wfd returns the file descriptor that |ssl| is configured to write
  * to. If |ssl|'s write |BIO| is not configured or doesn't wrap a file
- * descriptor then it returns -1. */
+ * descriptor then it returns -1.
+ *
+ * Note: On Windows, this may return either a file descriptor or a socket (cast
+ * to int), depending on whether |ssl| was configured with a file descriptor or
+ * socket |BIO|. */
 OPENSSL_EXPORT int SSL_get_wfd(const SSL *ssl);
 
 /* SSL_set_fd configures |ssl| to read from and write to |fd|. It returns one
  * on success and zero on allocation error. The caller retains ownership of
- * |fd|. */
+ * |fd|.
+ *
+ * On Windows, |fd| is cast to a |SOCKET| and used with Winsock APIs. */
 OPENSSL_EXPORT int SSL_set_fd(SSL *ssl, int fd);
 
 /* SSL_set_rfd configures |ssl| to read from |fd|. It returns one on success and
- * zero on allocation error. The caller retains ownership of |fd|. */
+ * zero on allocation error. The caller retains ownership of |fd|.
+ *
+ * On Windows, |fd| is cast to a |SOCKET| and used with Winsock APIs. */
 OPENSSL_EXPORT int SSL_set_rfd(SSL *ssl, int fd);
 
 /* SSL_set_wfd configures |ssl| to write to |fd|. It returns one on success and
- * zero on allocation error. The caller retains ownership of |fd|. */
+ * zero on allocation error. The caller retains ownership of |fd|.
+ *
+ * On Windows, |fd| is cast to a |SOCKET| and used with Winsock APIs. */
 OPENSSL_EXPORT int SSL_set_wfd(SSL *ssl, int fd);
 
 /* SSL_do_handshake continues the current handshake. If there is none or the
@@ -277,12 +322,11 @@
  * returns <= 0. The caller should pass the value into |SSL_get_error| to
  * determine how to proceed.
  *
- * In DTLS, if the read |BIO| is non-blocking, the caller must drive
- * retransmissions. Whenever |SSL_get_error| signals |SSL_ERROR_WANT_READ|, use
- * |DTLSv1_get_timeout| to determine the current timeout. If it expires before
- * the next retry, call |DTLSv1_handle_timeout|. Note that DTLS handshake
- * retransmissions use fresh sequence numbers, so it is not sufficient to replay
- * packets at the transport.
+ * In DTLS, the caller must drive retransmissions. Whenever |SSL_get_error|
+ * signals |SSL_ERROR_WANT_READ|, use |DTLSv1_get_timeout| to determine the
+ * current timeout. If it expires before the next retry, call
+ * |DTLSv1_handle_timeout|. Note that DTLS handshake retransmissions use fresh
+ * sequence numbers, so it is not sufficient to replay packets at the transport.
  *
  * TODO(davidben): Ensure 0 is only returned on transport EOF.
  * https://crbug.com/466303. */
@@ -314,7 +358,7 @@
 
 /* SSL_write writes up to |num| bytes from |buf| into |ssl|. It implicitly runs
  * any pending handshakes, including renegotiations when enabled. On success, it
- * returns the number of bytes read. Otherwise, it returns <= 0. The caller
+ * returns the number of bytes written. Otherwise, it returns <= 0. The caller
  * should pass the value into |SSL_get_error| to determine how to proceed.
  *
  * In TLS, a non-blocking |SSL_write| differs from non-blocking |write| in that
@@ -353,14 +397,7 @@
  *
  * |SSL_shutdown| returns -1 on failure. The caller should pass the return value
  * into |SSL_get_error| to determine how to proceed. If the underlying |BIO| is
- * non-blocking, both stages may require retry.
- *
- * |SSL_shutdown| must be called to retain |ssl|'s session in the session
- * cache. Use |SSL_CTX_set_quiet_shutdown| to configure |SSL_shutdown| to
- * neither send nor wait for close_notify but still retain the session.
- *
- * TODO(davidben): Is there any point in the session cache interaction? Remove
- * it? */
+ * non-blocking, both stages may require retry. */
 OPENSSL_EXPORT int SSL_shutdown(SSL *ssl);
 
 /* SSL_CTX_set_quiet_shutdown sets quiet shutdown on |ctx| to |mode|. If
@@ -415,9 +452,9 @@
  * See also |SSL_CTX_set_cert_cb| and |SSL_CTX_set_client_cert_cb|. */
 #define SSL_ERROR_WANT_X509_LOOKUP 4
 
-/* SSL_ERROR_WANT_SYSCALL indicates the operation failed externally to the
- * library. The caller should consult the system-specific error mechanism. This
- * is typically |errno| but may be something custom if using a custom |BIO|. It
+/* SSL_ERROR_SYSCALL indicates the operation failed externally to the library.
+ * The caller should consult the system-specific error mechanism. This is
+ * typically |errno| but may be something custom if using a custom |BIO|. It
  * may also be signaled if the transport returned EOF, in which case the
  * operation's return value will be zero. */
 #define SSL_ERROR_SYSCALL 5
@@ -465,13 +502,30 @@
  * a private key operation was unfinished. The caller may retry the operation
  * when the private key operation is complete.
  *
- * See also |SSL_set_private_key_method|. */
+ * See also |SSL_set_private_key_method| and
+ * |SSL_CTX_set_private_key_method|. */
 #define SSL_ERROR_WANT_PRIVATE_KEY_OPERATION 13
 
+/* SSL_ERROR_PENDING_TICKET indicates that a ticket decryption is pending. The
+ * caller may retry the operation when the decryption is ready.
+ *
+ * See also |SSL_CTX_set_ticket_aead_method|. */
+#define SSL_ERROR_PENDING_TICKET 14
+
 /* SSL_set_mtu sets the |ssl|'s MTU in DTLS to |mtu|. It returns one on success
  * and zero on failure. */
 OPENSSL_EXPORT int SSL_set_mtu(SSL *ssl, unsigned mtu);
 
+/* DTLSv1_set_initial_timeout_duration sets the initial duration for a DTLS
+ * handshake timeout.
+ *
+ * This duration overrides the default of 1 second, which is the strong
+ * recommendation of RFC 6347 (see section 4.2.4.1). However, there may exist
+ * situations where a shorter timeout would be beneficial, such as for
+ * time-sensitive applications. */
+OPENSSL_EXPORT void DTLSv1_set_initial_timeout_duration(SSL *ssl,
+                                                        unsigned duration_ms);
+
 /* DTLSv1_get_timeout queries the next DTLS handshake timeout. If there is a
  * timeout in progress, it sets |*out| to the time remaining and returns one.
  * Otherwise, it returns zero.
@@ -512,25 +566,34 @@
 #define TLS1_VERSION 0x0301
 #define TLS1_1_VERSION 0x0302
 #define TLS1_2_VERSION 0x0303
+#define TLS1_3_VERSION 0x0304
 
 #define DTLS1_VERSION 0xfeff
 #define DTLS1_2_VERSION 0xfefd
 
-/* SSL_CTX_set_min_version sets the minimum protocol version for |ctx| to
- * |version|. */
-OPENSSL_EXPORT void SSL_CTX_set_min_version(SSL_CTX *ctx, uint16_t version);
+#define TLS1_3_DRAFT_VERSION 0x7f12
 
-/* SSL_CTX_set_max_version sets the maximum protocol version for |ctx| to
- * |version|. */
-OPENSSL_EXPORT void SSL_CTX_set_max_version(SSL_CTX *ctx, uint16_t version);
+/* SSL_CTX_set_min_proto_version sets the minimum protocol version for |ctx| to
+ * |version|. If |version| is zero, the default minimum version is used. It
+ * returns one on success and zero if |version| is invalid. */
+OPENSSL_EXPORT int SSL_CTX_set_min_proto_version(SSL_CTX *ctx,
+                                                 uint16_t version);
 
-/* SSL_set_min_version sets the minimum protocol version for |ssl| to
- * |version|. */
-OPENSSL_EXPORT void SSL_set_min_version(SSL *ssl, uint16_t version);
+/* SSL_CTX_set_max_proto_version sets the maximum protocol version for |ctx| to
+ * |version|. If |version| is zero, the default maximum version is used. It
+ * returns one on success and zero if |version| is invalid. */
+OPENSSL_EXPORT int SSL_CTX_set_max_proto_version(SSL_CTX *ctx,
+                                                 uint16_t version);
 
-/* SSL_set_max_version sets the maximum protocol version for |ssl| to
- * |version|. */
-OPENSSL_EXPORT void SSL_set_max_version(SSL *ssl, uint16_t version);
+/* SSL_set_min_proto_version sets the minimum protocol version for |ssl| to
+ * |version|. If |version| is zero, the default minimum version is used. It
+ * returns one on success and zero if |version| is invalid. */
+OPENSSL_EXPORT int SSL_set_min_proto_version(SSL *ssl, uint16_t version);
+
+/* SSL_set_max_proto_version sets the maximum protocol version for |ssl| to
+ * |version|. If |version| is zero, the default maximum version is used. It
+ * returns one on success and zero if |version| is invalid. */
+OPENSSL_EXPORT int SSL_set_max_proto_version(SSL *ssl, uint16_t version);
 
 /* SSL_version returns the TLS or DTLS protocol version used by |ssl|, which is
  * one of the |*_VERSION| values. (E.g. |TLS1_2_VERSION|.) Before the version
@@ -554,10 +617,16 @@
  * client's. */
 #define SSL_OP_CIPHER_SERVER_PREFERENCE 0x00400000L
 
-/* SSL_OP_DISABLE_NPN configures an individual |SSL| to not advertise NPN,
- * despite |SSL_CTX_set_next_proto_select_cb| being configured on the
- * |SSL_CTX|. */
-#define SSL_OP_DISABLE_NPN 0x00800000L
+/* The following flags toggle individual protocol versions. This is deprecated.
+ * Use |SSL_CTX_set_min_proto_version| and |SSL_CTX_set_max_proto_version|
+ * instead. */
+#define SSL_OP_NO_SSLv3 0x02000000L
+#define SSL_OP_NO_TLSv1 0x04000000L
+#define SSL_OP_NO_TLSv1_2 0x08000000L
+#define SSL_OP_NO_TLSv1_1 0x10000000L
+#define SSL_OP_NO_TLSv1_3 0x20000000L
+#define SSL_OP_NO_DTLSv1 SSL_OP_NO_TLSv1
+#define SSL_OP_NO_DTLSv1_2 SSL_OP_NO_TLSv1_2
 
 /* SSL_CTX_set_options enables all options set in |options| (which should be one
  * or more of the |SSL_OP_*| values, ORed together) in |ctx|. It returns a
@@ -605,13 +674,14 @@
 #define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER 0x00000002L
 
 /* SSL_MODE_NO_AUTO_CHAIN disables automatically building a certificate chain
- * before sending certificates to the peer.
- * TODO(davidben): Remove this behavior. https://crbug.com/486295. */
+ * before sending certificates to the peer. This flag is set (and the feature
+ * disabled) by default.
+ * TODO(davidben): Remove this behavior. https://crbug.com/boringssl/42. */
 #define SSL_MODE_NO_AUTO_CHAIN 0x00000008L
 
 /* SSL_MODE_ENABLE_FALSE_START allows clients to send application data before
- * receipt of ChangeCipherSpec and Finished. This mode enables full-handshakes
- * to 'complete' in one RTT. See draft-bmoeller-tls-falsestart-01.
+ * receipt of ChangeCipherSpec and Finished. This mode enables full handshakes
+ * to 'complete' in one RTT. See RFC 7918.
  *
  * When False Start is enabled, |SSL_do_handshake| may succeed before the
  * handshake has completely finished. |SSL_write| will function at this point,
@@ -668,6 +738,16 @@
  * modes enabled for |ssl|. */
 OPENSSL_EXPORT uint32_t SSL_get_mode(const SSL *ssl);
 
+/* SSL_CTX_set0_buffer_pool sets a |CRYPTO_BUFFER_POOL| that will be used to
+ * store certificates. This can allow multiple connections to share
+ * certificates and thus save memory.
+ *
+ * The SSL_CTX does not take ownership of |pool| and the caller must ensure
+ * that |pool| outlives |ctx| and all objects linked to it, including |SSL|,
+ * |X509| and |SSL_SESSION| objects. Basically, don't ever free |pool|. */
+OPENSSL_EXPORT void SSL_CTX_set0_buffer_pool(SSL_CTX *ctx,
+                                             CRYPTO_BUFFER_POOL *pool);
+
 
 /* Configuring certificates and private keys.
  *
@@ -754,7 +834,10 @@
  *
  * On the client, the callback may call |SSL_get0_certificate_types| and
  * |SSL_get_client_CA_list| for information on the server's certificate
- * request. */
+ * request.
+ *
+ * On the server, the callback will be called on non-resumption handshakes,
+ * after extensions have been processed. */
 OPENSSL_EXPORT void SSL_CTX_set_cert_cb(SSL_CTX *ctx,
                                         int (*cb)(SSL *ssl, void *arg),
                                         void *arg);
@@ -830,24 +913,81 @@
                                                           const uint8_t *list,
                                                           size_t list_len);
 
-/* SSL_CTX_set_ocsp_response sets the OCSP reponse that is sent to clients
+/* SSL_set_signed_cert_timestamp_list sets the list of signed certificate
+ * timestamps that is sent to clients that request is. The same format as the
+ * one used for |SSL_CTX_set_signed_cert_timestamp_list| applies. The caller
+ * retains ownership of |list|. */
+OPENSSL_EXPORT int SSL_set_signed_cert_timestamp_list(SSL *ctx,
+                                                      const uint8_t *list,
+                                                      size_t list_len);
+
+/* SSL_CTX_set_ocsp_response sets the OCSP response that is sent to clients
  * which request it. It returns one on success and zero on error. The caller
  * retains ownership of |response|. */
 OPENSSL_EXPORT int SSL_CTX_set_ocsp_response(SSL_CTX *ctx,
                                              const uint8_t *response,
                                              size_t response_len);
 
-/* SSL_set_private_key_digest_prefs copies |num_digests| NIDs from |digest_nids|
- * into |ssl|. These digests will be used, in decreasing order of preference,
- * when signing with |ssl|'s private key. It returns one on success and zero on
- * error. */
-OPENSSL_EXPORT int SSL_set_private_key_digest_prefs(SSL *ssl,
-                                                    const int *digest_nids,
-                                                    size_t num_digests);
+/* SSL_set_ocsp_response sets the OCSP response that is sent to clients which
+ * request it. It returns one on success and zero on error. The caller retains
+ * ownership of |response|. */
+OPENSSL_EXPORT int SSL_set_ocsp_response(SSL *ssl,
+                                         const uint8_t *response,
+                                         size_t response_len);
+
+/* SSL_SIGN_* are signature algorithm values as defined in TLS 1.3. */
+#define SSL_SIGN_RSA_PKCS1_SHA1 0x0201
+#define SSL_SIGN_RSA_PKCS1_SHA256 0x0401
+#define SSL_SIGN_RSA_PKCS1_SHA384 0x0501
+#define SSL_SIGN_RSA_PKCS1_SHA512 0x0601
+#define SSL_SIGN_ECDSA_SHA1 0x0203
+#define SSL_SIGN_ECDSA_SECP256R1_SHA256 0x0403
+#define SSL_SIGN_ECDSA_SECP384R1_SHA384 0x0503
+#define SSL_SIGN_ECDSA_SECP521R1_SHA512 0x0603
+#define SSL_SIGN_RSA_PSS_SHA256 0x0804
+#define SSL_SIGN_RSA_PSS_SHA384 0x0805
+#define SSL_SIGN_RSA_PSS_SHA512 0x0806
+
+/* SSL_SIGN_RSA_PKCS1_MD5_SHA1 is an internal signature algorithm used to
+ * specify raw RSASSA-PKCS1-v1_5 with an MD5/SHA-1 concatenation, as used in TLS
+ * before TLS 1.2. */
+#define SSL_SIGN_RSA_PKCS1_MD5_SHA1 0xff01
+
+/* SSL_CTX_set_signing_algorithm_prefs configures |ctx| to use |prefs| as the
+ * preference list when signing with |ctx|'s private key. It returns one on
+ * success and zero on error. |prefs| should not include the internal-only value
+ * |SSL_SIGN_RSA_PKCS1_MD5_SHA1|. */
+OPENSSL_EXPORT int SSL_CTX_set_signing_algorithm_prefs(SSL_CTX *ctx,
+                                                       const uint16_t *prefs,
+                                                       size_t num_prefs);
+
+/* SSL_set_signing_algorithm_prefs configures |ssl| to use |prefs| as the
+ * preference list when signing with |ssl|'s private key. It returns one on
+ * success and zero on error. |prefs| should not include the internal-only value
+ * |SSL_SIGN_RSA_PKCS1_MD5_SHA1|. */
+OPENSSL_EXPORT int SSL_set_signing_algorithm_prefs(SSL *ssl,
+                                                   const uint16_t *prefs,
+                                                   size_t num_prefs);
 
 
 /* Certificate and private key convenience functions. */
 
+/* SSL_CTX_set_chain_and_key sets the certificate chain and private key for a
+ * TLS client or server. References to the given |CRYPTO_BUFFER| and |EVP_PKEY|
+ * objects are added as needed. Exactly one of |privkey| or |privkey_method|
+ * may be non-NULL. Returns one on success and zero on error. */
+OPENSSL_EXPORT int SSL_CTX_set_chain_and_key(
+    SSL_CTX *ctx, CRYPTO_BUFFER *const *certs, size_t num_certs,
+    EVP_PKEY *privkey, const SSL_PRIVATE_KEY_METHOD *privkey_method);
+
+/* SSL_set_chain_and_key sets the certificate chain and private key for a TLS
+ * client or server. References to the given |CRYPTO_BUFFER| and |EVP_PKEY|
+ * objects are added as needed. Exactly one of |privkey| or |privkey_method|
+ * may be non-NULL. Returns one on success and zero on error. */
+OPENSSL_EXPORT int SSL_set_chain_and_key(
+    SSL *ssl, CRYPTO_BUFFER *const *certs, size_t num_certs, EVP_PKEY *privkey,
+    const SSL_PRIVATE_KEY_METHOD *privkey_method);
+
 /* SSL_CTX_use_RSAPrivateKey sets |ctx|'s private key to |rsa|. It returns one
  * on success and zero on failure. */
 OPENSSL_EXPORT int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa);
@@ -927,46 +1067,63 @@
   ssl_private_key_failure,
 };
 
-/* SSL_PRIVATE_KEY_METHOD describes private key hooks. This is used to off-load
- * signing operations to a custom, potentially asynchronous, backend. */
-typedef struct ssl_private_key_method_st {
-  /* type returns either |EVP_PKEY_RSA| or |EVP_PKEY_EC| to denote the type of
-   * key used by |ssl|. */
+/* ssl_private_key_method_st (aka |SSL_PRIVATE_KEY_METHOD|) describes private
+ * key hooks. This is used to off-load signing operations to a custom,
+ * potentially asynchronous, backend. */
+struct ssl_private_key_method_st {
+  /* type returns the type of the key used by |ssl|. For RSA keys, return
+   * |NID_rsaEncryption|. For ECDSA keys, return |NID_X9_62_prime256v1|,
+   * |NID_secp384r1|, or |NID_secp521r1|, depending on the curve. */
   int (*type)(SSL *ssl);
 
   /* max_signature_len returns the maximum length of a signature signed by the
    * key used by |ssl|. This must be a constant value for a given |ssl|. */
   size_t (*max_signature_len)(SSL *ssl);
 
-  /* sign signs |in_len| bytes of digest from |in|. |md| is the hash function
-   * used to calculate |in|. On success, it returns |ssl_private_key_success|
-   * and writes at most |max_out| bytes of signature data to |out|. On failure,
-   * it returns |ssl_private_key_failure|. If the operation has not completed,
-   * it returns |ssl_private_key_retry|. |sign| should arrange for the
-   * high-level operation on |ssl| to be retried when the operation is
-   * completed. This will result in a call to |sign_complete|.
+  /* sign signs the message |in| in using the specified signature algorithm. On
+   * success, it returns |ssl_private_key_success| and writes at most |max_out|
+   * bytes of signature data to |out| and sets |*out_len| to the number of bytes
+   * written. On failure, it returns |ssl_private_key_failure|. If the operation
+   * has not completed, it returns |ssl_private_key_retry|. |sign| should
+   * arrange for the high-level operation on |ssl| to be retried when the
+   * operation is completed. This will result in a call to |complete|.
+   *
+   * |signature_algorithm| is one of the |SSL_SIGN_*| values, as defined in TLS
+   * 1.3. Note that, in TLS 1.2, ECDSA algorithms do not require that curve
+   * sizes match hash sizes, so the curve portion of |SSL_SIGN_ECDSA_*| values
+   * must be ignored. BoringSSL will internally handle the curve matching logic
+   * where appropriate.
+   *
+   * It is an error to call |sign| while another private key operation is in
+   * progress on |ssl|. */
+  enum ssl_private_key_result_t (*sign)(SSL *ssl, uint8_t *out, size_t *out_len,
+                                        size_t max_out,
+                                        uint16_t signature_algorithm,
+                                        const uint8_t *in, size_t in_len);
+
+  /* sign_digest signs |in_len| bytes of digest from |in|. |md| is the hash
+   * function used to calculate |in|. On success, it returns
+   * |ssl_private_key_success| and writes at most |max_out| bytes of signature
+   * data to |out|. On failure, it returns |ssl_private_key_failure|. If the
+   * operation has not completed, it returns |ssl_private_key_retry|. |sign|
+   * should arrange for the high-level operation on |ssl| to be retried when the
+   * operation is completed. This will result in a call to |complete|.
    *
    * If the key is an RSA key, implementations must use PKCS#1 padding. |in| is
    * the digest itself, so the DigestInfo prefix, if any, must be prepended by
    * |sign|. If |md| is |EVP_md5_sha1|, there is no prefix.
    *
-   * It is an error to call |sign| while another private key operation is in
-   * progress on |ssl|. */
-  enum ssl_private_key_result_t (*sign)(SSL *ssl, uint8_t *out, size_t *out_len,
-                                        size_t max_out, const EVP_MD *md,
-                                        const uint8_t *in, size_t in_len);
-
-  /* sign_complete completes a pending |sign| operation. If the operation has
-   * completed, it returns |ssl_private_key_success| and writes the result to
-   * |out| as in |sign|. Otherwise, it returns |ssl_private_key_failure| on
-   * failure and |ssl_private_key_retry| if the operation is still in progress.
+   * It is an error to call |sign_digest| while another private key operation is
+   * in progress on |ssl|.
    *
-   * |sign_complete| may be called arbitrarily many times before completion, but
-   * it is an error to call |sign_complete| if there is no pending |sign|
-   * operation in progress on |ssl|. */
-  enum ssl_private_key_result_t (*sign_complete)(SSL *ssl, uint8_t *out,
-                                                 size_t *out_len,
-                                                 size_t max_out);
+   * This function is deprecated. Implement |sign| instead.
+   *
+   * TODO(davidben): Remove this function. */
+  enum ssl_private_key_result_t (*sign_digest)(SSL *ssl, uint8_t *out,
+                                               size_t *out_len, size_t max_out,
+                                               const EVP_MD *md,
+                                               const uint8_t *in,
+                                               size_t in_len);
 
   /* decrypt decrypts |in_len| bytes of encrypted data from |in|. On success it
    * returns |ssl_private_key_success|, writes at most |max_out| bytes of
@@ -974,9 +1131,9 @@
    * written. On failure it returns |ssl_private_key_failure|. If the operation
    * has not completed, it returns |ssl_private_key_retry|. The caller should
    * arrange for the high-level operation on |ssl| to be retried when the
-   * operation is completed, which will result in a call to |decrypt_complete|.
-   * This function only works with RSA keys and should perform a raw RSA
-   * decryption operation with no padding.
+   * operation is completed, which will result in a call to |complete|. This
+   * function only works with RSA keys and should perform a raw RSA decryption
+   * operation with no padding.
    *
    * It is an error to call |decrypt| while another private key operation is in
    * progress on |ssl|. */
@@ -984,25 +1141,28 @@
                                            size_t *out_len, size_t max_out,
                                            const uint8_t *in, size_t in_len);
 
-  /* decrypt_complete completes a pending |decrypt| operation. If the operation
-   * has completed, it returns |ssl_private_key_success| and writes the result
-   * to |out| as in |decrypt|. Otherwise, it returns |ssl_private_key_failure|
-   * on failure and |ssl_private_key_retry| if the operation is still in
-   * progress.
+  /* complete completes a pending operation. If the operation has completed, it
+   * returns |ssl_private_key_success| and writes the result to |out| as in
+   * |sign|. Otherwise, it returns |ssl_private_key_failure| on failure and
+   * |ssl_private_key_retry| if the operation is still in progress.
    *
-   * |decrypt_complete| may be called arbitrarily many times before completion,
-   * but it is an error to call |decrypt_complete| if there is no pending
-   * |decrypt| operation in progress on |ssl|. */
-  enum ssl_private_key_result_t (*decrypt_complete)(SSL *ssl, uint8_t *out,
-                                                    size_t *out_len,
-                                                    size_t max_out);
-} SSL_PRIVATE_KEY_METHOD;
+   * |complete| may be called arbitrarily many times before completion, but it
+   * is an error to call |complete| if there is no pending operation in progress
+   * on |ssl|. */
+  enum ssl_private_key_result_t (*complete)(SSL *ssl, uint8_t *out,
+                                            size_t *out_len, size_t max_out);
+};
 
 /* SSL_set_private_key_method configures a custom private key on |ssl|.
  * |key_method| must remain valid for the lifetime of |ssl|. */
 OPENSSL_EXPORT void SSL_set_private_key_method(
     SSL *ssl, const SSL_PRIVATE_KEY_METHOD *key_method);
 
+/* SSL_CTX_set_private_key_method configures a custom private key on |ctx|.
+ * |key_method| must remain valid for the lifetime of |ctx|. */
+OPENSSL_EXPORT void SSL_CTX_set_private_key_method(
+    SSL_CTX *ctx, const SSL_PRIVATE_KEY_METHOD *key_method);
+
 
 /* Cipher suites.
  *
@@ -1023,12 +1183,15 @@
  * mode). */
 OPENSSL_EXPORT int SSL_CIPHER_is_AES(const SSL_CIPHER *cipher);
 
-/* SSL_CIPHER_has_MD5_HMAC returns one if |cipher| uses HMAC-MD5. */
-OPENSSL_EXPORT int SSL_CIPHER_has_MD5_HMAC(const SSL_CIPHER *cipher);
-
 /* SSL_CIPHER_has_SHA1_HMAC returns one if |cipher| uses HMAC-SHA1. */
 OPENSSL_EXPORT int SSL_CIPHER_has_SHA1_HMAC(const SSL_CIPHER *cipher);
 
+/* SSL_CIPHER_has_SHA256_HMAC returns one if |cipher| uses HMAC-SHA256. */
+OPENSSL_EXPORT int SSL_CIPHER_has_SHA256_HMAC(const SSL_CIPHER *cipher);
+
+/* SSL_CIPHER_is_AEAD returns one if |cipher| uses an AEAD cipher. */
+OPENSSL_EXPORT int SSL_CIPHER_is_AEAD(const SSL_CIPHER *cipher);
+
 /* SSL_CIPHER_is_AESGCM returns one if |cipher| uses AES-GCM. */
 OPENSSL_EXPORT int SSL_CIPHER_is_AESGCM(const SSL_CIPHER *cipher);
 
@@ -1044,35 +1207,43 @@
 OPENSSL_EXPORT int SSL_CIPHER_is_AES256CBC(const SSL_CIPHER *cipher);
 
 /* SSL_CIPHER_is_CHACHA20POLY1305 returns one if |cipher| uses
- * CHACHA20_POLY1305. Note this includes both the
- * draft-ietf-tls-chacha20-poly1305-04 and draft-agl-tls-chacha20poly1305-04
- * versions. */
+ * CHACHA20_POLY1305. Note this includes both the RFC 7905 and
+ * draft-agl-tls-chacha20poly1305-04 versions. */
 OPENSSL_EXPORT int SSL_CIPHER_is_CHACHA20POLY1305(const SSL_CIPHER *cipher);
 
 /* SSL_CIPHER_is_NULL returns one if |cipher| does not encrypt. */
 OPENSSL_EXPORT int SSL_CIPHER_is_NULL(const SSL_CIPHER *cipher);
 
-/* SSL_CIPHER_is_RC4 returns one if |cipher| uses RC4. */
-OPENSSL_EXPORT int SSL_CIPHER_is_RC4(const SSL_CIPHER *cipher);
-
 /* SSL_CIPHER_is_block_cipher returns one if |cipher| is a block cipher. */
 OPENSSL_EXPORT int SSL_CIPHER_is_block_cipher(const SSL_CIPHER *cipher);
 
 /* SSL_CIPHER_is_ECDSA returns one if |cipher| uses ECDSA. */
 OPENSSL_EXPORT int SSL_CIPHER_is_ECDSA(const SSL_CIPHER *cipher);
 
+/* SSL_CIPHER_is_DHE returns one if |cipher| uses DHE. */
+OPENSSL_EXPORT int SSL_CIPHER_is_DHE(const SSL_CIPHER *cipher);
+
 /* SSL_CIPHER_is_ECDHE returns one if |cipher| uses ECDHE. */
 OPENSSL_EXPORT int SSL_CIPHER_is_ECDHE(const SSL_CIPHER *cipher);
 
+/* SSL_CIPHER_is_static_RSA returns one if |cipher| uses the static RSA key
+ * exchange. */
+OPENSSL_EXPORT int SSL_CIPHER_is_static_RSA(const SSL_CIPHER *cipher);
+
 /* SSL_CIPHER_get_min_version returns the minimum protocol version required
  * for |cipher|. */
 OPENSSL_EXPORT uint16_t SSL_CIPHER_get_min_version(const SSL_CIPHER *cipher);
 
+/* SSL_CIPHER_get_max_version returns the maximum protocol version that
+ * supports |cipher|. */
+OPENSSL_EXPORT uint16_t SSL_CIPHER_get_max_version(const SSL_CIPHER *cipher);
+
 /* SSL_CIPHER_get_name returns the OpenSSL name of |cipher|. */
 OPENSSL_EXPORT const char *SSL_CIPHER_get_name(const SSL_CIPHER *cipher);
 
 /* SSL_CIPHER_get_kx_name returns a string that describes the key-exchange
- * method used by |cipher|. For example, "ECDHE_ECDSA". */
+ * method used by |cipher|. For example, "ECDHE_ECDSA". TLS 1.3 AEAD-only
+ * ciphers return the string "GENERIC". */
 OPENSSL_EXPORT const char *SSL_CIPHER_get_kx_name(const SSL_CIPHER *cipher);
 
 /* SSL_CIPHER_get_rfc_name returns a newly-allocated string with the standard
@@ -1136,11 +1307,11 @@
  *   corresponding |k*| or |a*| cipher rule. |RSA| is an alias for |kRSA|, not
  *   |aRSA|.
  *
- *   |3DES|, |RC4|, |AES128|, |AES256|, |AES|, |AESGCM|, |CHACHA20| match
- *   ciphers whose bulk cipher use the corresponding encryption scheme. Note
- *   that |AES|, |AES128|, and |AES256| match both CBC and GCM ciphers.
+ *   |3DES|, |AES128|, |AES256|, |AES|, |AESGCM|, |CHACHA20| match ciphers
+ *   whose bulk cipher use the corresponding encryption scheme. Note that
+ *   |AES|, |AES128|, and |AES256| match both CBC and GCM ciphers.
  *
- *   |MD5|, |SHA1|, |SHA256|, and |SHA384| match legacy cipher suites using the
+ *   |SHA1|, |SHA256|, and |SHA384| match legacy cipher suites using the
  *   corresponding hash function in their MAC. AEADs are matched by none of
  *   these.
  *
@@ -1154,7 +1325,7 @@
  *   |kEDH|, |EDH|, |kEECDH|, and |EECDH| are legacy aliases for |kDHE|, |DHE|,
  *   |kECDHE|, and |ECDHE|, respectively.
  *
- *   |MEDIUM| and |HIGH| match RC4-based ciphers and all others, respectively.
+ *   |HIGH| is an alias for |ALL|.
  *
  *   |FIPS| is an alias for |HIGH|.
  *
@@ -1162,7 +1333,9 @@
  *   |TLSv1_2| matches ciphers new in TLS 1.2. This is confusing and should not
  *   be used.
  *
- * Unknown rules silently match nothing.
+ * Unknown rules are silently ignored by legacy APIs, and rejected by APIs with
+ * "strict" in the name, which should be preferred. Cipher lists can be long and
+ * it's easy to commit typos.
  *
  * The special |@STRENGTH| directive will sort all enabled ciphers by strength.
  *
@@ -1180,35 +1353,47 @@
  *   [ECDHE-ECDSA-CHACHA20-POLY1305|ECDHE-ECDSA-AES128-GCM-SHA256]
  *
  * Once an equal-preference group is used, future directives must be
- * opcode-less. */
+ * opcode-less.
+ *
+ * TLS 1.3 ciphers do not participate in this mechanism and instead have a
+ * built-in preference order. Functions to set cipher lists do not affect TLS
+ * 1.3, and functions to query the cipher list do not include TLS 1.3
+ * ciphers. */
 
 /* SSL_DEFAULT_CIPHER_LIST is the default cipher suite configuration. It is
  * substituted when a cipher string starts with 'DEFAULT'. */
 #define SSL_DEFAULT_CIPHER_LIST "ALL"
 
+/* SSL_CTX_set_strict_cipher_list configures the cipher list for |ctx|,
+ * evaluating |str| as a cipher string and returning error if |str| contains
+ * anything meaningless. It returns one on success and zero on failure. */
+OPENSSL_EXPORT int SSL_CTX_set_strict_cipher_list(SSL_CTX *ctx,
+                                                  const char *str);
+
 /* SSL_CTX_set_cipher_list configures the cipher list for |ctx|, evaluating
- * |str| as a cipher string. It returns one on success and zero on failure. */
+ * |str| as a cipher string. It returns one on success and zero on failure.
+ *
+ * Prefer to use |SSL_CTX_set_strict_cipher_list|. This function tolerates
+ * garbage inputs, unless an empty cipher list results. */
 OPENSSL_EXPORT int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str);
 
-/* SSL_CTX_set_cipher_list_tls10 configures the TLS 1.0+ cipher list for |ctx|,
- * evaluating |str| as a cipher string. It returns one on success and zero on
- * failure. If set, servers will use this cipher suite list for TLS 1.0 or
- * higher. */
-OPENSSL_EXPORT int SSL_CTX_set_cipher_list_tls10(SSL_CTX *ctx, const char *str);
-
-/* SSL_CTX_set_cipher_list_tls11 configures the TLS 1.1+ cipher list for |ctx|,
- * evaluating |str| as a cipher string. It returns one on success and zero on
- * failure. If set, servers will use this cipher suite list for TLS 1.1 or
- * higher. */
-OPENSSL_EXPORT int SSL_CTX_set_cipher_list_tls11(SSL_CTX *ctx, const char *str);
+/* SSL_set_strict_cipher_list configures the cipher list for |ssl|, evaluating
+ * |str| as a cipher string and returning error if |str| contains anything
+ * meaningless. It returns one on success and zero on failure. */
+OPENSSL_EXPORT int SSL_set_strict_cipher_list(SSL *ssl, const char *str);
 
 /* SSL_set_cipher_list configures the cipher list for |ssl|, evaluating |str| as
- * a cipher string. It returns one on success and zero on failure. */
+ * a cipher string. It returns one on success and zero on failure.
+ *
+ * Prefer to use |SSL_set_strict_cipher_list|. This function tolerates garbage
+ * inputs, unless an empty cipher list results. */
 OPENSSL_EXPORT int SSL_set_cipher_list(SSL *ssl, const char *str);
 
-/* SSL_get_ciphers returns the cipher list for |ssl|, in order of preference. If
- * |SSL_CTX_set_cipher_list_tls10| or |SSL_CTX_set_cipher_list_tls11| has been
- * used, the corresponding list for the current version is returned. */
+/* SSL_CTX_get_ciphers returns the cipher list for |ctx|, in order of
+ * preference. */
+OPENSSL_EXPORT STACK_OF(SSL_CIPHER) *SSL_CTX_get_ciphers(const SSL_CTX *ctx);
+
+/* SSL_get_ciphers returns the cipher list for |ssl|, in order of preference. */
 OPENSSL_EXPORT STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *ssl);
 
 
@@ -1236,17 +1421,36 @@
 OPENSSL_EXPORT X509 *SSL_get_peer_certificate(const SSL *ssl);
 
 /* SSL_get_peer_cert_chain returns the peer's certificate chain or NULL if
- * unavailable or the peer did not use certificates. This is the unverified
- * list of certificates as sent by the peer, not the final chain built during
- * verification. For historical reasons, this value may not be available if
- * resuming a serialized |SSL_SESSION|. The caller does not take ownership of
- * the result.
+ * unavailable or the peer did not use certificates. This is the unverified list
+ * of certificates as sent by the peer, not the final chain built during
+ * verification. The caller does not take ownership of the result.
  *
  * WARNING: This function behaves differently between client and server. If
  * |ssl| is a server, the returned chain does not include the leaf certificate.
  * If a client, it does. */
 OPENSSL_EXPORT STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *ssl);
 
+/* SSL_get_peer_full_cert_chain returns the peer's certificate chain, or NULL if
+ * unavailable or the peer did not use certificates. This is the unverified list
+ * of certificates as sent by the peer, not the final chain built during
+ * verification. The caller does not take ownership of the result.
+ *
+ * This is the same as |SSL_get_peer_cert_chain| except that this function
+ * always returns the full chain, i.e. the first element of the return value
+ * (if any) will be the leaf certificate. In constrast,
+ * |SSL_get_peer_cert_chain| returns only the intermediate certificates if the
+ * |ssl| is a server. */
+OPENSSL_EXPORT STACK_OF(X509) *SSL_get_peer_full_cert_chain(const SSL *ssl);
+
+/* SSL_get0_peer_certificates returns the peer's certificate chain, or NULL if
+ * unavailable or the peer did not use certificates. This is the unverified list
+ * of certificates as sent by the peer, not the final chain built during
+ * verification. The caller does not take ownership of the result.
+ *
+ * This is the |CRYPTO_BUFFER| variant of |SSL_get_peer_full_cert_chain|. */
+OPENSSL_EXPORT STACK_OF(CRYPTO_BUFFER) *
+    SSL_get0_peer_certificates(const SSL *ssl);
+
 /* SSL_get0_signed_cert_timestamp_list sets |*out| and |*out_len| to point to
  * |*out_len| bytes of SCT information from the server. This is only valid if
  * |ssl| is a client. The SCT information is a SignedCertificateTimestampList
@@ -1287,8 +1491,8 @@
 OPENSSL_EXPORT int SSL_get_tls_unique(const SSL *ssl, uint8_t *out,
                                       size_t *out_len, size_t max_out);
 
-/* SSL_get_extms_support returns one if the Extended Master Secret
- * extension was negotiated. Otherwise, it returns zero. */
+/* SSL_get_extms_support returns one if the Extended Master Secret extension or
+ * TLS 1.3 was negotiated. Otherwise, it returns zero. */
 OPENSSL_EXPORT int SSL_get_extms_support(const SSL *ssl);
 
 /* SSL_get_current_cipher returns the cipher used in the current outgoing
@@ -1303,7 +1507,7 @@
 OPENSSL_EXPORT int SSL_session_reused(const SSL *ssl);
 
 /* SSL_get_secure_renegotiation_support returns one if the peer supports secure
- * renegotiation (RFC 5746) and zero otherwise. */
+ * renegotiation (RFC 5746) or TLS 1.3. Otherwise, it returns zero. */
 OPENSSL_EXPORT int SSL_get_secure_renegotiation_support(const SSL *ssl);
 
 /* SSL_export_keying_material exports a value derived from the master secret, as
@@ -1414,13 +1618,13 @@
 DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
 
 /* SSL_SESSION_new returns a newly-allocated blank |SSL_SESSION| or NULL on
- * error. This may be useful in writing tests but otherwise should not be
- * used outside the library. */
-OPENSSL_EXPORT SSL_SESSION *SSL_SESSION_new(void);
+ * error. This may be useful when writing tests but should otherwise not be
+ * used. */
+OPENSSL_EXPORT SSL_SESSION *SSL_SESSION_new(const SSL_CTX *ctx);
 
-/* SSL_SESSION_up_ref, if |session| is not NULL, increments the reference count
- * of |session|. It then returns |session|. */
-OPENSSL_EXPORT SSL_SESSION *SSL_SESSION_up_ref(SSL_SESSION *session);
+/* SSL_SESSION_up_ref increments the reference count of |session| and returns
+ * one. */
+OPENSSL_EXPORT int SSL_SESSION_up_ref(SSL_SESSION *session);
 
 /* SSL_SESSION_free decrements the reference count of |session|. If it reaches
  * zero, all data referenced by |session| and |session| itself are released. */
@@ -1441,47 +1645,48 @@
 
 /* SSL_SESSION_from_bytes parses |in_len| bytes from |in| as an SSL_SESSION. It
  * returns a newly-allocated |SSL_SESSION| on success or NULL on error. */
-OPENSSL_EXPORT SSL_SESSION *SSL_SESSION_from_bytes(const uint8_t *in,
-                                                   size_t in_len);
+OPENSSL_EXPORT SSL_SESSION *SSL_SESSION_from_bytes(
+    const uint8_t *in, size_t in_len, const SSL_CTX *ctx);
 
 /* SSL_SESSION_get_version returns a string describing the TLS version |session|
  * was established at. For example, "TLSv1.2" or "SSLv3". */
 OPENSSL_EXPORT const char *SSL_SESSION_get_version(const SSL_SESSION *session);
 
-/* SSL_SESSION_get_id returns a pointer to a buffer containg |session|'s session
- * ID and sets |*out_len| to its length. */
+/* SSL_SESSION_get_id returns a pointer to a buffer containing |session|'s
+ * session ID and sets |*out_len| to its length. */
 OPENSSL_EXPORT const uint8_t *SSL_SESSION_get_id(const SSL_SESSION *session,
                                                  unsigned *out_len);
 
 /* SSL_SESSION_get_time returns the time at which |session| was established in
  * seconds since the UNIX epoch. */
-OPENSSL_EXPORT long SSL_SESSION_get_time(const SSL_SESSION *session);
+OPENSSL_EXPORT uint64_t SSL_SESSION_get_time(const SSL_SESSION *session);
 
 /* SSL_SESSION_get_timeout returns the lifetime of |session| in seconds. */
-OPENSSL_EXPORT long SSL_SESSION_get_timeout(const SSL_SESSION *session);
+OPENSSL_EXPORT uint32_t SSL_SESSION_get_timeout(const SSL_SESSION *session);
 
-/* SSL_SESSION_get_key_exchange_info returns a value that describes the
- * strength of the asymmetric operation that provides confidentiality to
- * |session|. Its interpretation depends on the operation used. See the
- * documentation for this value in the |SSL_SESSION| structure. */
-OPENSSL_EXPORT uint32_t SSL_SESSION_get_key_exchange_info(
-    const SSL_SESSION *session);
-
-/* SSL_SESSION_get0_peer return's the peer leaf certificate stored in
+/* SSL_SESSION_get0_peer returns the peer leaf certificate stored in
  * |session|.
  *
  * TODO(davidben): This should return a const X509 *. */
 OPENSSL_EXPORT X509 *SSL_SESSION_get0_peer(const SSL_SESSION *session);
 
+/* SSL_SESSION_get_master_key writes up to |max_out| bytes of |session|'s master
+ * secret to |out| and returns the number of bytes written. If |max_out| is
+ * zero, it returns the size of the master secret. */
+OPENSSL_EXPORT size_t SSL_SESSION_get_master_key(const SSL_SESSION *session,
+                                                 uint8_t *out, size_t max_out);
+
 /* SSL_SESSION_set_time sets |session|'s creation time to |time| and returns
  * |time|. This function may be useful in writing tests but otherwise should not
  * be used. */
-OPENSSL_EXPORT long SSL_SESSION_set_time(SSL_SESSION *session, long time);
+OPENSSL_EXPORT uint64_t SSL_SESSION_set_time(SSL_SESSION *session,
+                                             uint64_t time);
 
 /* SSL_SESSION_set_timeout sets |session|'s timeout to |timeout| and returns
  * one. This function may be useful in writing tests but otherwise should not
  * be used. */
-OPENSSL_EXPORT long SSL_SESSION_set_timeout(SSL_SESSION *session, long timeout);
+OPENSSL_EXPORT uint32_t SSL_SESSION_set_timeout(SSL_SESSION *session,
+                                                uint32_t timeout);
 
 /* SSL_SESSION_set1_id_context sets |session|'s session ID context (see
  * |SSL_CTX_set_session_id_context|) to |sid_ctx|. It returns one on success and
@@ -1489,7 +1694,7 @@
  * should not be used. */
 OPENSSL_EXPORT int SSL_SESSION_set1_id_context(SSL_SESSION *session,
                                                const uint8_t *sid_ctx,
-                                               unsigned sid_ctx_len);
+                                               size_t sid_ctx_len);
 
 
 /* Session caching.
@@ -1511,7 +1716,7 @@
  *
  * Note that offering or accepting a session short-circuits most parameter
  * negotiation. Resuming sessions across different configurations may result in
- * surprising behavor. So, for instance, a client implementing a version
+ * surprising behavior. So, for instance, a client implementing a version
  * fallback should shard its session cache by maximum protocol version. */
 
 /* SSL_SESS_CACHE_OFF disables all session caching. */
@@ -1524,7 +1729,7 @@
 /* SSL_SESS_CACHE_SERVER enables session caching for a server. */
 #define SSL_SESS_CACHE_SERVER 0x0002
 
-/* SSL_SESS_CACHE_SERVER enables session caching for both client and server. */
+/* SSL_SESS_CACHE_BOTH enables session caching for both client and server. */
 #define SSL_SESS_CACHE_BOTH (SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_SERVER)
 
 /* SSL_SESS_CACHE_NO_AUTO_CLEAR disables automatically calling
@@ -1554,13 +1759,21 @@
 
 /* SSL_set_session, for a client, configures |ssl| to offer to resume |session|
  * in the initial handshake and returns one. The caller retains ownership of
- * |session|. */
+ * |session|.
+ *
+ * It is an error to call this function after the handshake has begun. */
 OPENSSL_EXPORT int SSL_set_session(SSL *ssl, SSL_SESSION *session);
 
-/* SSL_get_session returns a non-owning pointer to |ssl|'s session. Prior to the
- * initial handshake beginning, this is the session to be offered, set by
- * |SSL_set_session|. After a handshake has finished, this is the currently
- * active session. Its behavior is undefined while a handshake is progress. */
+/* SSL_get_session returns a non-owning pointer to |ssl|'s session. For
+ * historical reasons, which session it returns depends on |ssl|'s state.
+ *
+ * Prior to the start of the initial handshake, it returns the session the
+ * caller set with |SSL_set_session|. After the initial handshake has finished
+ * and if no additional handshakes are in progress, it returns the currently
+ * active session. Its behavior is undefined while a handshake is in progress.
+ *
+ * Using this function to add new sessions to an external session cache is
+ * deprecated. Use |SSL_CTX_sess_set_new_cb| instead. */
 OPENSSL_EXPORT SSL_SESSION *SSL_get_session(const SSL *ssl);
 
 /* SSL_get0_session is an alias for |SSL_get_session|. */
@@ -1571,16 +1784,32 @@
 OPENSSL_EXPORT SSL_SESSION *SSL_get1_session(SSL *ssl);
 
 /* SSL_DEFAULT_SESSION_TIMEOUT is the default lifetime, in seconds, of a
- * session. */
+ * session in TLS 1.2 or earlier. This is how long we are willing to use the
+ * secret to encrypt traffic without fresh key material. */
 #define SSL_DEFAULT_SESSION_TIMEOUT (2 * 60 * 60)
 
-/* SSL_CTX_set_timeout sets the lifetime, in seconds, of sessions created in
- * |ctx| to |timeout|. */
-OPENSSL_EXPORT long SSL_CTX_set_timeout(SSL_CTX *ctx, long timeout);
+/* SSL_DEFAULT_SESSION_PSK_DHE_TIMEOUT is the default lifetime, in seconds, of a
+ * session for TLS 1.3 psk_dhe_ke. This is how long we are willing to use the
+ * secret as an authenticator. */
+#define SSL_DEFAULT_SESSION_PSK_DHE_TIMEOUT (2 * 24 * 60 * 60)
 
-/* SSL_CTX_get_timeout returns the lifetime, in seconds, of sessions created in
- * |ctx|. */
-OPENSSL_EXPORT long SSL_CTX_get_timeout(const SSL_CTX *ctx);
+/* SSL_DEFAULT_SESSION_AUTH_TIMEOUT is the default non-renewable lifetime, in
+ * seconds, of a TLS 1.3 session. This is how long we are willing to trust the
+ * signature in the initial handshake. */
+#define SSL_DEFAULT_SESSION_AUTH_TIMEOUT (7 * 24 * 60 * 60)
+
+/* SSL_CTX_set_timeout sets the lifetime, in seconds, of TLS 1.2 (or earlier)
+ * sessions created in |ctx| to |timeout|. */
+OPENSSL_EXPORT uint32_t SSL_CTX_set_timeout(SSL_CTX *ctx, uint32_t timeout);
+
+/* SSL_CTX_set_session_psk_dhe_timeout sets the lifetime, in seconds, of TLS 1.3
+ * sessions created in |ctx| to |timeout|. */
+OPENSSL_EXPORT void SSL_CTX_set_session_psk_dhe_timeout(SSL_CTX *ctx,
+                                                        uint32_t timeout);
+
+/* SSL_CTX_get_timeout returns the lifetime, in seconds, of TLS 1.2 (or earlier)
+ * sessions created in |ctx|. */
+OPENSSL_EXPORT uint32_t SSL_CTX_get_timeout(const SSL_CTX *ctx);
 
 /* SSL_CTX_set_session_id_context sets |ctx|'s session ID context to |sid_ctx|.
  * It returns one on success and zero on error. The session ID context is an
@@ -1595,13 +1824,18 @@
  * relevant if a server requires client auth. */
 OPENSSL_EXPORT int SSL_CTX_set_session_id_context(SSL_CTX *ctx,
                                                   const uint8_t *sid_ctx,
-                                                  unsigned sid_ctx_len);
+                                                  size_t sid_ctx_len);
 
 /* SSL_set_session_id_context sets |ssl|'s session ID context to |sid_ctx|. It
  * returns one on success and zero on error. See also
  * |SSL_CTX_set_session_id_context|. */
 OPENSSL_EXPORT int SSL_set_session_id_context(SSL *ssl, const uint8_t *sid_ctx,
-                                              unsigned sid_ctx_len);
+                                              size_t sid_ctx_len);
+
+/* SSL_get0_session_id_context returns a pointer to |ssl|'s session ID context
+ * and sets |*out_len| to its length. */
+OPENSSL_EXPORT const uint8_t *SSL_get0_session_id_context(const SSL *ssl,
+                                                          size_t *out_len);
 
 /* SSL_SESSION_CACHE_MAX_SIZE_DEFAULT is the default maximum size of a session
  * cache. */
@@ -1634,7 +1868,7 @@
 
 /* SSL_CTX_flush_sessions removes all sessions from |ctx| which have expired as
  * of time |time|. If |time| is zero, all sessions are removed. */
-OPENSSL_EXPORT void SSL_CTX_flush_sessions(SSL_CTX *ctx, long time);
+OPENSSL_EXPORT void SSL_CTX_flush_sessions(SSL_CTX *ctx, uint64_t time);
 
 /* SSL_CTX_sess_set_new_cb sets the callback to be called when a new session is
  * established and ready to be cached. If the session cache is disabled (the
@@ -1727,7 +1961,14 @@
  * On the server, tickets are encrypted and authenticated with a secret key. By
  * default, an |SSL_CTX| generates a key on creation. Tickets are minted and
  * processed transparently. The following functions may be used to configure a
- * persistent key or implement more custom behavior. */
+ * persistent key or implement more custom behavior. There are three levels of
+ * customisation possible:
+ *
+ * 1) One can simply set the keys with |SSL_CTX_set_tlsext_ticket_keys|.
+ * 2) One can configure an |EVP_CIPHER_CTX| and |HMAC_CTX| directly for
+ *    encryption and authentication.
+ * 3) One can configure an |SSL_TICKET_ENCRYPTION_METHOD| to have more control
+ *    and the option of asynchronous decryption. */
 
 /* SSL_CTX_get_tlsext_ticket_keys writes |ctx|'s session ticket key material to
  * |len| bytes of |out|. It returns one on success and zero if |len| is not
@@ -1773,6 +2014,55 @@
                                   EVP_CIPHER_CTX *ctx, HMAC_CTX *hmac_ctx,
                                   int encrypt));
 
+/* ssl_ticket_aead_result_t enumerates the possible results from decrypting a
+ * ticket with an |SSL_TICKET_AEAD_METHOD|. */
+enum ssl_ticket_aead_result_t {
+  /* ssl_ticket_aead_success indicates that the ticket was successfully
+   * decrypted. */
+  ssl_ticket_aead_success,
+  /* ssl_ticket_aead_retry indicates that the operation could not be
+   * immediately completed and must be reattempted, via |open|, at a later
+   * point. */
+  ssl_ticket_aead_retry,
+  /* ssl_ticket_aead_ignore_ticket indicates that the ticket should be ignored
+   * (i.e. is corrupt or otherwise undecryptable). */
+  ssl_ticket_aead_ignore_ticket,
+  /* ssl_ticket_aead_error indicates that a fatal error occured and the
+   * handshake should be terminated. */
+  ssl_ticket_aead_error,
+};
+
+/* ssl_ticket_aead_method_st (aka |SSL_TICKET_ENCRYPTION_METHOD|) contains
+ * methods for encrypting and decrypting session tickets. */
+struct ssl_ticket_aead_method_st {
+  /* max_overhead returns the maximum number of bytes of overhead that |seal|
+   * may add. */
+  size_t (*max_overhead)(SSL *ssl);
+
+  /* seal encrypts and authenticates |in_len| bytes from |in|, writes, at most,
+   * |max_out_len| bytes to |out|, and puts the number of bytes written in
+   * |*out_len|. The |in| and |out| buffers may be equal but will not otherwise
+   * alias. It returns one on success or zero on error. */
+  int (*seal)(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out_len,
+              const uint8_t *in, size_t in_len);
+
+  /* open authenticates and decrypts |in_len| bytes from |in|, writes, at most,
+   * |max_out_len| bytes of plaintext to |out|, and puts the number of bytes
+   * written in |*out_len|. The |in| and |out| buffers may be equal but will
+   * not otherwise alias. See |ssl_ticket_aead_result_t| for details of the
+   * return values. In the case that a retry is indicated, the caller should
+   * arrange for the high-level operation on |ssl| to be retried when the
+   * operation is completed, which will result in another call to |open|. */
+  enum ssl_ticket_aead_result_t (*open)(SSL *ssl, uint8_t *out, size_t *out_len,
+                                        size_t max_out_len, const uint8_t *in,
+                                        size_t in_len);
+};
+
+/* SSL_CTX_set_ticket_aead_method configures a custom ticket AEAD method table
+ * on |ctx|. |aead_method| must remain valid for the lifetime of |ctx|. */
+OPENSSL_EXPORT void SSL_CTX_set_ticket_aead_method(
+    SSL_CTX *ctx, const SSL_TICKET_AEAD_METHOD *aead_method);
+
 
 /* Elliptic curve Diffie-Hellman.
  *
@@ -1781,23 +2071,54 @@
  * are supported. ECDHE is always enabled, but the curve preferences may be
  * configured with these functions.
  *
- * A client may use |SSL_SESSION_get_key_exchange_info| to determine the curve
- * selected. */
+ * Note that TLS 1.3 renames these from curves to groups. For consistency, we
+ * currently use the TLS 1.2 name in the API. */
 
 /* SSL_CTX_set1_curves sets the preferred curves for |ctx| to be |curves|. Each
  * element of |curves| should be a curve nid. It returns one on success and
- * zero on failure. */
+ * zero on failure.
+ *
+ * Note that this API uses nid values from nid.h and not the |SSL_CURVE_*|
+ * values defined below. */
 OPENSSL_EXPORT int SSL_CTX_set1_curves(SSL_CTX *ctx, const int *curves,
                                        size_t curves_len);
 
 /* SSL_set1_curves sets the preferred curves for |ssl| to be |curves|. Each
  * element of |curves| should be a curve nid. It returns one on success and
- * zero on failure. */
+ * zero on failure.
+ *
+ * Note that this API uses nid values from nid.h and not the |SSL_CURVE_*|
+ * values defined below. */
 OPENSSL_EXPORT int SSL_set1_curves(SSL *ssl, const int *curves,
                                    size_t curves_len);
 
-/* SSL_get_curve_name returns a human-readable name for the elliptic curve
- * specified by the given TLS curve id, or NULL if the curve if unknown. */
+/* SSL_CTX_set1_curves_list sets the preferred curves for |ctx| to be the
+ * colon-separated list |curves|. Each element of |curves| should be a curve
+ * name (e.g. P-256, X25519, ...). It returns one on success and zero on
+ * failure. */
+OPENSSL_EXPORT int SSL_CTX_set1_curves_list(SSL_CTX *ctx, const char *curves);
+
+/* SSL_set1_curves_list sets the preferred curves for |ssl| to be the
+ * colon-separated list |curves|. Each element of |curves| should be a curve
+ * name (e.g. P-256, X25519, ...). It returns one on success and zero on
+ * failure. */
+OPENSSL_EXPORT int SSL_set1_curves_list(SSL *ssl, const char *curves);
+
+/* SSL_CURVE_* define TLS curve IDs. */
+#define SSL_CURVE_SECP256R1 23
+#define SSL_CURVE_SECP384R1 24
+#define SSL_CURVE_SECP521R1 25
+#define SSL_CURVE_X25519 29
+
+/* SSL_get_curve_id returns the ID of the curve used by |ssl|'s most recently
+ * completed handshake or 0 if not applicable.
+ *
+ * TODO(davidben): This API currently does not work correctly if there is a
+ * renegotiation in progress. Fix this. */
+OPENSSL_EXPORT uint16_t SSL_get_curve_id(const SSL *ssl);
+
+/* SSL_get_curve_name returns a human-readable name for the curve specified by
+ * the given TLS curve id, or NULL if the curve is unknown. */
 OPENSSL_EXPORT const char *SSL_get_curve_name(uint16_t curve_id);
 
 
@@ -1805,11 +2126,7 @@
  *
  * Cipher suites using a DHE key exchange perform Diffie-Hellman over a
  * multiplicative group selected by the server. These ciphers are disabled for a
- * server unless a group is chosen with one of these functions.
- *
- * A client may use |SSL_SESSION_get_key_exchange_info| to determine the size of
- * the selected group's prime, but note that servers may select degenerate
- * groups. */
+ * server unless a group is chosen with one of these functions. */
 
 /* SSL_CTX_set_tmp_dh configures |ctx| to use the group from |dh| as the group
  * for DHE. Only the group is used, so |dh| needn't have a keypair. It returns
@@ -2012,9 +2329,6 @@
  * either |X509_V_OK| or a |X509_V_ERR_*| value. */
 OPENSSL_EXPORT long SSL_get_verify_result(const SSL *ssl);
 
-/* SSL_set_verify_result overrides the result of certificate verification. */
-OPENSSL_EXPORT void SSL_set_verify_result(SSL *ssl, long result);
-
 /* SSL_get_ex_data_X509_STORE_CTX_idx returns the ex_data index used to look up
  * the |SSL| associated with an |X509_STORE_CTX| in the verify callback. */
 OPENSSL_EXPORT int SSL_get_ex_data_X509_STORE_CTX_idx(void);
@@ -2025,20 +2339,26 @@
  * zero on fatal error. It may use |X509_STORE_CTX_set_error| to set a
  * verification result.
  *
- * The callback may use either the |arg| parameter or
- * |SSL_get_ex_data_X509_STORE_CTX_idx| to recover the associated |SSL|
- * object. */
+ * The callback may use |SSL_get_ex_data_X509_STORE_CTX_idx| to recover the
+ * |SSL| object from |store_ctx|. */
 OPENSSL_EXPORT void SSL_CTX_set_cert_verify_callback(
     SSL_CTX *ctx, int (*callback)(X509_STORE_CTX *store_ctx, void *arg),
     void *arg);
 
+/* SSL_CTX_i_promise_to_verify_certs_after_the_handshake indicates that the
+ * caller understands that the |CRYPTO_BUFFER|-based methods currently require
+ * post-handshake verification of certificates and thus it's ok to accept any
+ * certificates during the handshake. */
+OPENSSL_EXPORT void SSL_CTX_i_promise_to_verify_certs_after_the_handshake(
+    SSL_CTX *ctx);
+
 /* SSL_enable_signed_cert_timestamps causes |ssl| (which must be the client end
  * of a connection) to request SCTs from the server. See
- * https://tools.ietf.org/html/rfc6962. It returns one.
+ * https://tools.ietf.org/html/rfc6962.
  *
  * Call |SSL_get0_signed_cert_timestamp_list| to recover the SCT after the
  * handshake. */
-OPENSSL_EXPORT int SSL_enable_signed_cert_timestamps(SSL *ssl);
+OPENSSL_EXPORT void SSL_enable_signed_cert_timestamps(SSL *ssl);
 
 /* SSL_CTX_enable_signed_cert_timestamps enables SCT requests on all client SSL
  * objects created from |ctx|.
@@ -2048,12 +2368,11 @@
 OPENSSL_EXPORT void SSL_CTX_enable_signed_cert_timestamps(SSL_CTX *ctx);
 
 /* SSL_enable_ocsp_stapling causes |ssl| (which must be the client end of a
- * connection) to request a stapled OCSP response from the server. It returns
- * one.
+ * connection) to request a stapled OCSP response from the server.
  *
  * Call |SSL_get0_ocsp_response| to recover the OCSP response after the
  * handshake. */
-OPENSSL_EXPORT int SSL_enable_ocsp_stapling(SSL *ssl);
+OPENSSL_EXPORT void SSL_enable_ocsp_stapling(SSL *ssl);
 
 /* SSL_CTX_enable_ocsp_stapling enables OCSP stapling on all client SSL objects
  * created from |ctx|.
@@ -2062,6 +2381,28 @@
  * handshake. */
 OPENSSL_EXPORT void SSL_CTX_enable_ocsp_stapling(SSL_CTX *ctx);
 
+/* SSL_CTX_set0_verify_cert_store sets an |X509_STORE| that will be used
+ * exclusively for certificate verification and returns one. Ownership of
+ * |store| is transferred to the |SSL_CTX|. */
+OPENSSL_EXPORT int SSL_CTX_set0_verify_cert_store(SSL_CTX *ctx,
+                                                  X509_STORE *store);
+
+/* SSL_CTX_set1_verify_cert_store sets an |X509_STORE| that will be used
+ * exclusively for certificate verification and returns one. An additional
+ * reference to |store| will be taken. */
+OPENSSL_EXPORT int SSL_CTX_set1_verify_cert_store(SSL_CTX *ctx,
+                                                  X509_STORE *store);
+
+/* SSL_set0_verify_cert_store sets an |X509_STORE| that will be used
+ * exclusively for certificate verification and returns one. Ownership of
+ * |store| is transferred to the |SSL|. */
+OPENSSL_EXPORT int SSL_set0_verify_cert_store(SSL *ssl, X509_STORE *store);
+
+/* SSL_set1_verify_cert_store sets an |X509_STORE| that will be used
+ * exclusively for certificate verification and returns one. An additional
+ * reference to |store| will be taken. */
+OPENSSL_EXPORT int SSL_set1_verify_cert_store(SSL *ssl, X509_STORE *store);
+
 
 /* Client certificate CA list.
  *
@@ -2089,6 +2430,16 @@
  * when the handshake is paused because of them. */
 OPENSSL_EXPORT STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *ssl);
 
+/* SSL_get0_server_requested_CAs returns the CAs sent by a server to guide a
+ * client in certificate selection. They are a series of DER-encoded X.509
+ * names. This function may only be called during a callback set by
+ * |SSL_CTX_set_cert_cb| or when the handshake is paused because of it.
+ *
+ * The returned stack is owned by |ssl|, as are its contents. It should not be
+ * used past the point where the handshake is restarted after the callback. */
+OPENSSL_EXPORT STACK_OF(CRYPTO_BUFFER) *SSL_get0_server_requested_CAs(
+    const SSL *ssl);
+
 /* SSL_CTX_get_client_CA_list returns |ctx|'s client certificate CA list. */
 OPENSSL_EXPORT STACK_OF(X509_NAME) *
     SSL_CTX_get_client_CA_list(const SSL_CTX *ctx);
@@ -2118,12 +2469,6 @@
 OPENSSL_EXPORT int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *out,
                                                        const char *file);
 
-/* SSL_add_dir_cert_subjects_to_stack lists files in directory |dir|. It calls
- * |SSL_add_file_cert_subjects_to_stack| on each file and returns one on success
- * or zero on error. */
-OPENSSL_EXPORT int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *out,
-                                                      const char *dir);
-
 
 /* Server name indication.
  *
@@ -2149,14 +2494,15 @@
 
 /* SSL_CTX_set_tlsext_servername_callback configures |callback| to be called on
  * the server after ClientHello extensions have been parsed and returns one.
- * The callback may use |SSL_get_servername| to examine the server_name extension
- * and returns a |SSL_TLSEXT_ERR_*| value. The value of |arg| may be set by
- * calling |SSL_CTX_set_tlsext_servername_arg|.
+ * The callback may use |SSL_get_servername| to examine the server_name
+ * extension and returns a |SSL_TLSEXT_ERR_*| value. The value of |arg| may be
+ * set by calling |SSL_CTX_set_tlsext_servername_arg|.
  *
  * If the callback returns |SSL_TLSEXT_ERR_NOACK|, the server_name extension is
  * not acknowledged in the ServerHello. If the return value is
- * |SSL_TLSEXT_ERR_ALERT_FATAL| or |SSL_TLSEXT_ERR_ALERT_WARNING| then
- * |*out_alert| must be set to the alert value to send. */
+ * |SSL_TLSEXT_ERR_ALERT_FATAL|, then |*out_alert| is the alert to send,
+ * defaulting to |SSL_AD_UNRECOGNIZED_NAME|. |SSL_TLSEXT_ERR_ALERT_WARNING| is
+ * ignored and treated as |SSL_TLSEXT_ERR_OK|. */
 OPENSSL_EXPORT int SSL_CTX_set_tlsext_servername_callback(
     SSL_CTX *ctx, int (*callback)(SSL *ssl, int *out_alert, void *arg));
 
@@ -2170,8 +2516,23 @@
 #define SSL_TLSEXT_ERR_ALERT_FATAL 2
 #define SSL_TLSEXT_ERR_NOACK 3
 
+/* SSL_set_SSL_CTX changes |ssl|'s |SSL_CTX|. |ssl| will use the
+ * certificate-related settings from |ctx|, and |SSL_get_SSL_CTX| will report
+ * |ctx|. This function may be used during the callbacks registered by
+ * |SSL_CTX_set_select_certificate_cb|,
+ * |SSL_CTX_set_tlsext_servername_callback|, and |SSL_CTX_set_cert_cb| or when
+ * the handshake is paused from them. It is typically used to switch
+ * certificates based on SNI.
+ *
+ * Note the session cache and related settings will continue to use the initial
+ * |SSL_CTX|. Callers should use |SSL_CTX_set_session_id_context| to partition
+ * the session cache between different domains.
+ *
+ * TODO(davidben): Should other settings change after this call? */
+OPENSSL_EXPORT SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx);
 
-/* Application-layer protocol negotation.
+
+/* Application-layer protocol negotiation.
  *
  * The ALPN extension (RFC 7301) allows negotiating different application-layer
  * protocols over a single port. This is used, for example, to negotiate
@@ -2207,7 +2568,10 @@
  * |*out_len| to the selected protocol and return |SSL_TLSEXT_ERR_OK| on
  * success. It does not pass ownership of the buffer. Otherwise, it should
  * return |SSL_TLSEXT_ERR_NOACK|. Other |SSL_TLSEXT_ERR_*| values are
- * unimplemented and will be treated as |SSL_TLSEXT_ERR_NOACK|. */
+ * unimplemented and will be treated as |SSL_TLSEXT_ERR_NOACK|.
+ *
+ * The cipher suite is selected before negotiating ALPN. The callback may use
+ * |SSL_get_pending_cipher| to query the cipher suite. */
 OPENSSL_EXPORT void SSL_CTX_set_alpn_select_cb(
     SSL_CTX *ctx, int (*cb)(SSL *ssl, const uint8_t **out, uint8_t *out_len,
                             const uint8_t *in, unsigned in_len, void *arg),
@@ -2283,7 +2647,7 @@
  * or have a default application level protocol.
  *
  * 2) If the server supports NPN, but advertises an empty list then the
- * client selects the first protcol in its list, but indicates via the
+ * client selects the first protocol in its list, but indicates via the
  * API that this fallback case was enacted.
  *
  * 3) Otherwise, the client finds the first protocol in the server's list
@@ -2311,15 +2675,14 @@
  *
  * See draft-balfanz-tls-channelid-01. */
 
-/* SSL_CTX_enable_tls_channel_id either configures a TLS server to accept TLS
- * Channel IDs from clients, or configures a client to send TLS Channel IDs to
- * a server. It returns one. */
-OPENSSL_EXPORT int SSL_CTX_enable_tls_channel_id(SSL_CTX *ctx);
+/* SSL_CTX_set_tls_channel_id_enabled configures whether connections associated
+ * with |ctx| should enable Channel ID. */
+OPENSSL_EXPORT void SSL_CTX_set_tls_channel_id_enabled(SSL_CTX *ctx,
+                                                       int enabled);
 
-/* SSL_enable_tls_channel_id either configures a TLS server to accept TLS
- * Channel IDs from clients, or configures a client to send TLS Channel IDs to
- * server. It returns one. */
-OPENSSL_EXPORT int SSL_enable_tls_channel_id(SSL *ssl);
+/* SSL_set_tls_channel_id_enabled configures whether |ssl| should enable Channel
+ * ID. */
+OPENSSL_EXPORT void SSL_set_tls_channel_id_enabled(SSL *ssl, int enabled);
 
 /* SSL_CTX_set1_tls_channel_id configures a TLS client to send a TLS Channel ID
  * to compatible servers. |private_key| must be a P-256 EC key. It returns one
@@ -2359,8 +2722,8 @@
  *
  * See RFC 5764. */
 
-/* An SRTP_PROTECTION_PROFILE is an SRTP profile for use with the use_srtp
- * extension. */
+/* srtp_protection_profile_st (aka |SRTP_PROTECTION_PROFILE|) is an SRTP
+ * profile for use with the use_srtp extension. */
 struct srtp_protection_profile_st {
   const char *name;
   unsigned long id;
@@ -2526,8 +2889,10 @@
 #define SSL_AD_PROTOCOL_VERSION TLS1_AD_PROTOCOL_VERSION
 #define SSL_AD_INSUFFICIENT_SECURITY TLS1_AD_INSUFFICIENT_SECURITY
 #define SSL_AD_INTERNAL_ERROR TLS1_AD_INTERNAL_ERROR
+#define SSL_AD_INAPPROPRIATE_FALLBACK SSL3_AD_INAPPROPRIATE_FALLBACK
 #define SSL_AD_USER_CANCELLED TLS1_AD_USER_CANCELLED
 #define SSL_AD_NO_RENEGOTIATION TLS1_AD_NO_RENEGOTIATION
+#define SSL_AD_MISSING_EXTENSION TLS1_AD_MISSING_EXTENSION
 #define SSL_AD_UNSUPPORTED_EXTENSION TLS1_AD_UNSUPPORTED_EXTENSION
 #define SSL_AD_CERTIFICATE_UNOBTAINABLE TLS1_AD_CERTIFICATE_UNOBTAINABLE
 #define SSL_AD_UNRECOGNIZED_NAME TLS1_AD_UNRECOGNIZED_NAME
@@ -2535,7 +2900,7 @@
   TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE
 #define SSL_AD_BAD_CERTIFICATE_HASH_VALUE TLS1_AD_BAD_CERTIFICATE_HASH_VALUE
 #define SSL_AD_UNKNOWN_PSK_IDENTITY TLS1_AD_UNKNOWN_PSK_IDENTITY
-#define SSL_AD_INAPPROPRIATE_FALLBACK SSL3_AD_INAPPROPRIATE_FALLBACK
+#define SSL_AD_CERTIFICATE_REQUIRED TLS1_AD_CERTIFICATE_REQUIRED
 
 /* SSL_alert_type_string_long returns a string description of |value| as an
  * alert type (warning or fatal). */
@@ -2545,6 +2910,16 @@
  * alert description or "unknown" if unknown. */
 OPENSSL_EXPORT const char *SSL_alert_desc_string_long(int value);
 
+/* SSL_send_fatal_alert sends a fatal alert over |ssl| of the specified type,
+ * which should be one of the |SSL_AD_*| constants. It returns one on success
+ * and <= 0 on error. The caller should pass the return value into
+ * |SSL_get_error| to determine how to proceed. Once this function has been
+ * called, future calls to |SSL_write| will fail.
+ *
+ * If retrying a failed operation due to |SSL_ERROR_WANT_WRITE|, subsequent
+ * calls must use the same |alert| parameter. */
+OPENSSL_EXPORT int SSL_send_fatal_alert(SSL *ssl, uint8_t alert);
+
 
 /* ex_data functions.
  *
@@ -2574,13 +2949,7 @@
                                             CRYPTO_EX_free *free_func);
 
 
-/* Obscure functions. */
-
-/* SSL_get_rc4_state sets |*read_key| and |*write_key| to the RC4 states for
- * the read and write directions. It returns one on success or zero if |ssl|
- * isn't using an RC4-based cipher suite. */
-OPENSSL_EXPORT int SSL_get_rc4_state(const SSL *ssl, const RC4_KEY **read_key,
-                                     const RC4_KEY **write_key);
+/* Low-level record-layer state. */
 
 /* SSL_get_ivs sets |*out_iv_len| to the length of the IVs for the ciphers
  * underlying |ssl| and sets |*out_read_iv| and |*out_write_iv| to point to the
@@ -2592,6 +2961,28 @@
                                const uint8_t **out_write_iv,
                                size_t *out_iv_len);
 
+/* SSL_get_key_block_len returns the length of |ssl|'s key block. */
+OPENSSL_EXPORT size_t SSL_get_key_block_len(const SSL *ssl);
+
+/* SSL_generate_key_block generates |out_len| bytes of key material for |ssl|'s
+ * current connection state. */
+OPENSSL_EXPORT int SSL_generate_key_block(const SSL *ssl, uint8_t *out,
+                                          size_t out_len);
+
+/* SSL_get_read_sequence returns, in TLS, the expected sequence number of the
+ * next incoming record in the current epoch. In DTLS, it returns the maximum
+ * sequence number received in the current epoch and includes the epoch number
+ * in the two most significant bytes. */
+OPENSSL_EXPORT uint64_t SSL_get_read_sequence(const SSL *ssl);
+
+/* SSL_get_write_sequence returns the sequence number of the next outgoing
+ * record in the current epoch. In DTLS, it includes the epoch number in the
+ * two most significant bytes. */
+OPENSSL_EXPORT uint64_t SSL_get_write_sequence(const SSL *ssl);
+
+
+/* Obscure functions. */
+
 /* SSL_get_structure_sizes returns the sizes of the SSL, SSL_CTX and
  * SSL_SESSION structures so that a test can ensure that outside code agrees on
  * these values. */
@@ -2612,7 +3003,10 @@
  * For each handshake message, ChangeCipherSpec, and alert, |version| is the
  * protocol version and |content_type| is the corresponding record type. The
  * |len| bytes from |buf| contain the handshake message, one-byte
- * ChangeCipherSpec body, and two-byte alert, respectively. */
+ * ChangeCipherSpec body, and two-byte alert, respectively.
+ *
+ * For a V2ClientHello, |version| is |SSL2_VERSION|, |content_type| is zero, and
+ * the |len| bytes from |buf| contain the V2ClientHello structure. */
 OPENSSL_EXPORT void SSL_CTX_set_msg_callback(
     SSL_CTX *ctx, void (*cb)(int write_p, int version, int content_type,
                              const void *buf, size_t len, SSL *ssl, void *arg));
@@ -2640,6 +3034,18 @@
 OPENSSL_EXPORT void SSL_CTX_set_keylog_callback(
     SSL_CTX *ctx, void (*cb)(const SSL *ssl, const char *line));
 
+/* SSL_CTX_get_keylog_callback returns the callback configured by
+ * |SSL_CTX_set_keylog_callback|. */
+OPENSSL_EXPORT void (*SSL_CTX_get_keylog_callback(const SSL_CTX *ctx))(
+    const SSL *ssl, const char *line);
+
+/* SSL_CTX_set_current_time_cb configures a callback to retrieve the current
+ * time, which should be set in |*out_clock|. This can be used for testing
+ * purposes; for example, a callback can be configured that returns a time
+ * set explicitly by the test. */
+OPENSSL_EXPORT void SSL_CTX_set_current_time_cb(
+    SSL_CTX *ctx, void (*cb)(const SSL *ssl, struct timeval *out_clock));
+
 enum ssl_renegotiate_mode_t {
   ssl_renegotiate_never = 0,
   ssl_renegotiate_once,
@@ -2668,12 +3074,33 @@
 OPENSSL_EXPORT int SSL_renegotiate_pending(SSL *ssl);
 
 /* SSL_total_renegotiations returns the total number of renegotiation handshakes
- * peformed by |ssl|. This includes the pending renegotiation, if any. */
+ * performed by |ssl|. This includes the pending renegotiation, if any. */
 OPENSSL_EXPORT int SSL_total_renegotiations(const SSL *ssl);
 
+/* SSL_CTX_set_early_data_enabled sets whether early data is allowed to be used
+ * with resumptions using |ctx|.
+ *
+ * As a server, if the client's early data is accepted, |SSL_do_handshake| will
+ * complete as soon as the ClientHello is processed and server flight sent.
+ * |SSL_write| may be used to send half-RTT data. |SSL_read| will consume early
+ * data and transition to 1-RTT data as appropriate.
+ *
+ * Note early data is replayable by a network attacker. |SSL_in_init| and
+ * |SSL_is_init_finished| will report the handshake is still in progress until
+ * the client's Finished message is received. Callers may use these functions
+ * to defer some processing if desired.
+ *
+ * WARNING: This is experimental and may cause interoperability failures until
+ * fully implemented. */
+OPENSSL_EXPORT void SSL_CTX_set_early_data_enabled(SSL_CTX *ctx, int enabled);
+
+/* SSL_early_data_accepted returns whether early data was accepted on the
+ * handshake performed by |ssl|. */
+OPENSSL_EXPORT int SSL_early_data_accepted(const SSL *ssl);
+
 /* SSL_MAX_CERT_LIST_DEFAULT is the default maximum length, in bytes, of a peer
  * certificate chain. */
-#define SSL_MAX_CERT_LIST_DEFAULT 1024 * 100
+#define SSL_MAX_CERT_LIST_DEFAULT (1024 * 100)
 
 /* SSL_CTX_get_max_cert_list returns the maximum length, in bytes, of a peer
  * certificate chain accepted by |ctx|. */
@@ -2696,23 +3123,33 @@
 
 /* SSL_CTX_set_max_send_fragment sets the maximum length, in bytes, of records
  * sent by |ctx|. Beyond this length, handshake messages and application data
- * will be split into multiple records. */
-OPENSSL_EXPORT void SSL_CTX_set_max_send_fragment(SSL_CTX *ctx,
-                                                  size_t max_send_fragment);
+ * will be split into multiple records. It returns one on success or zero on
+ * error. */
+OPENSSL_EXPORT int SSL_CTX_set_max_send_fragment(SSL_CTX *ctx,
+                                                 size_t max_send_fragment);
 
-/* SSL_set_max_send_fragment sets the maximum length, in bytes, of records
- * sent by |ssl|. Beyond this length, handshake messages and application data
- * will be split into multiple records. */
-OPENSSL_EXPORT void SSL_set_max_send_fragment(SSL *ssl,
-                                              size_t max_send_fragment);
+/* SSL_set_max_send_fragment sets the maximum length, in bytes, of records sent
+ * by |ssl|. Beyond this length, handshake messages and application data will
+ * be split into multiple records. It returns one on success or zero on
+ * error. */
+OPENSSL_EXPORT int SSL_set_max_send_fragment(SSL *ssl,
+                                             size_t max_send_fragment);
 
-/* ssl_early_callback_ctx is passed to certain callbacks that are called very
- * early on during the server handshake. At this point, much of the SSL* hasn't
- * been filled out and only the ClientHello can be depended on. */
-struct ssl_early_callback_ctx {
+/* SSL_get_v2clienthello_count returns the total number of V2ClientHellos that
+ * are accepted. */
+OPENSSL_EXPORT uint64_t SSL_get_v2clienthello_count(void);
+
+/* ssl_early_callback_ctx (aka |SSL_CLIENT_HELLO|) is passed to certain
+ * callbacks that are called very early on during the server handshake. At this
+ * point, much of the SSL* hasn't been filled out and only the ClientHello can
+ * be depended on. */
+typedef struct ssl_early_callback_ctx {
   SSL *ssl;
   const uint8_t *client_hello;
   size_t client_hello_len;
+  uint16_t version;
+  const uint8_t *random;
+  size_t random_len;
   const uint8_t *session_id;
   size_t session_id_len;
   const uint8_t *cipher_suites;
@@ -2721,37 +3158,52 @@
   size_t compression_methods_len;
   const uint8_t *extensions;
   size_t extensions_len;
+} SSL_CLIENT_HELLO;
+
+/* ssl_select_cert_result_t enumerates the possible results from selecting a
+ * certificate with |select_certificate_cb|. */
+enum ssl_select_cert_result_t {
+  /* ssl_select_cert_success indicates that the certificate selection was
+   * successful. */
+  ssl_select_cert_success = 1,
+  /* ssl_select_cert_retry indicates that the operation could not be
+   * immediately completed and must be reattempted at a later point. */
+  ssl_select_cert_retry = 0,
+  /* ssl_select_cert_error indicates that a fatal error occured and the
+   * handshake should be terminated. */
+  ssl_select_cert_error = -1,
 };
 
-/* SSL_early_callback_ctx_extension_get searches the extensions in |ctx| for an
- * extension of the given type. If not found, it returns zero. Otherwise it
- * sets |out_data| to point to the extension contents (not including the type
- * and length bytes), sets |out_len| to the length of the extension contents
- * and returns one. */
+/* SSL_early_callback_ctx_extension_get searches the extensions in
+ * |client_hello| for an extension of the given type. If not found, it returns
+ * zero. Otherwise it sets |out_data| to point to the extension contents (not
+ * including the type and length bytes), sets |out_len| to the length of the
+ * extension contents and returns one. */
 OPENSSL_EXPORT int SSL_early_callback_ctx_extension_get(
-    const struct ssl_early_callback_ctx *ctx, uint16_t extension_type,
+    const SSL_CLIENT_HELLO *client_hello, uint16_t extension_type,
     const uint8_t **out_data, size_t *out_len);
 
 /* SSL_CTX_set_select_certificate_cb sets a callback that is called before most
  * ClientHello processing and before the decision whether to resume a session
  * is made. The callback may inspect the ClientHello and configure the
- * connection. It may then return one to continue the handshake or zero to
- * pause the handshake to perform an asynchronous operation. If paused,
- * |SSL_get_error| will return |SSL_ERROR_PENDING_CERTIFICATE|.
+ * connection. See |ssl_select_cert_result_t| for details of the return values.
  *
- * Note: The |ssl_early_callback_ctx| is only valid for the duration of the
- * callback and is not valid while the handshake is paused. Further, unlike with
- * most callbacks, when the handshake loop is resumed, it will not call the
- * callback a second time. The caller must finish reconfiguring the connection
- * before resuming the handshake. */
+ * In the case that a retry is indicated, |SSL_get_error| will return
+ * |SSL_ERROR_PENDING_CERTIFICATE| and the caller should arrange for the
+ * high-level operation on |ssl| to be retried at a later time, which will
+ * result in another call to |cb|.
+ *
+ * Note: The |SSL_CLIENT_HELLO| is only valid for the duration of the callback
+ * and is not valid while the handshake is paused. */
 OPENSSL_EXPORT void SSL_CTX_set_select_certificate_cb(
-    SSL_CTX *ctx, int (*cb)(const struct ssl_early_callback_ctx *));
+    SSL_CTX *ctx,
+    enum ssl_select_cert_result_t (*cb)(const SSL_CLIENT_HELLO *));
 
 /* SSL_CTX_set_dos_protection_cb sets a callback that is called once the
  * resumption decision for a ClientHello has been made. It can return one to
  * allow the handshake to continue or zero to cause the handshake to abort. */
 OPENSSL_EXPORT void SSL_CTX_set_dos_protection_cb(
-    SSL_CTX *ctx, int (*cb)(const struct ssl_early_callback_ctx *));
+    SSL_CTX *ctx, int (*cb)(const SSL_CLIENT_HELLO *));
 
 /* SSL_ST_* are possible values for |SSL_state| and the bitmasks that make them
  * up. */
@@ -2761,6 +3213,7 @@
 #define SSL_ST_INIT (SSL_ST_CONNECT | SSL_ST_ACCEPT)
 #define SSL_ST_OK 0x03
 #define SSL_ST_RENEGOTIATE (0x04 | SSL_ST_INIT)
+#define SSL_ST_TLS13 (0x05 | SSL_ST_INIT)
 
 /* SSL_CB_* are possible values for the |type| parameter in the info
  * callback and the bitmasks that make them up. */
@@ -2779,14 +3232,14 @@
 #define SSL_CB_HANDSHAKE_DONE 0x20
 
 /* SSL_CTX_set_info_callback configures a callback to be run when various
- * events occur during a connection's lifetime. The |type| argumentj determines
+ * events occur during a connection's lifetime. The |type| argument determines
  * the type of event and the meaning of the |value| argument. Callbacks must
  * ignore unexpected |type| values.
  *
  * |SSL_CB_READ_ALERT| is signaled for each alert received, warning or fatal.
  * The |value| argument is a 16-bit value where the alert level (either
- * |SSL3_AL_WARNING| or |SSL3_AL_FATAL|) is in the most-significant eight bits and
- * the alert type (one of |SSL_AD_*|) is in the least-significant eight.
+ * |SSL3_AL_WARNING| or |SSL3_AL_FATAL|) is in the most-significant eight bits
+ * and the alert type (one of |SSL_AD_*|) is in the least-significant eight.
  *
  * |SSL_CB_WRITE_ALERT| is signaled for each alert sent. The |value| argument
  * is constructed as with |SSL_CB_READ_ALERT|.
@@ -2803,8 +3256,7 @@
  *
  * |SSL_CB_ACCEPT_LOOP| (respectively, |SSL_CB_CONNECT_LOOP|) is signaled when
  * a server (respectively, client) handshake progresses. The |value| argument
- * is always one. For the duration of the callback, |SSL_state| will return the
- * previous state.
+ * is always one.
  *
  * |SSL_CB_ACCEPT_EXIT| (respectively, |SSL_CB_CONNECT_EXIT|) is signaled when
  * a server (respectively, client) handshake completes, fails, or is paused.
@@ -2833,20 +3285,6 @@
  * machine as a string. This may be useful for debugging and logging. */
 OPENSSL_EXPORT const char *SSL_state_string_long(const SSL *ssl);
 
-/* SSL_set_SSL_CTX partially changes |ssl|'s |SSL_CTX|. |ssl| will use the
- * certificate and session_id_context from |ctx|, and |SSL_get_SSL_CTX| will
- * report |ctx|. However most settings and the session cache itself will
- * continue to use the initial |SSL_CTX|. It is often used as part of SNI.
- *
- * TODO(davidben): Make a better story here and get rid of this API. Also
- * determine if there's anything else affected by |SSL_set_SSL_CTX| that
- * matters. Not as many values are affected as one might initially think. The
- * session cache explicitly selects the initial |SSL_CTX|. Most settings are
- * copied at |SSL_new| so |ctx|'s versions don't apply. This, notably, has some
- * consequences for any plans to make |SSL| copy-on-write most of its
- * configuration. */
-OPENSSL_EXPORT SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx);
-
 #define SSL_SENT_SHUTDOWN 1
 #define SSL_RECEIVED_SHUTDOWN 2
 
@@ -2855,10 +3293,54 @@
  * respectively. */
 OPENSSL_EXPORT int SSL_get_shutdown(const SSL *ssl);
 
-/* SSL_get_server_key_exchange_hash, on a client, returns the hash the server
- * used to sign the ServerKeyExchange in TLS 1.2. If not applicable, it returns
- * |TLSEXT_hash_none|. */
-OPENSSL_EXPORT uint8_t SSL_get_server_key_exchange_hash(const SSL *ssl);
+/* SSL_get_peer_signature_algorithm returns the signature algorithm used by the
+ * peer. If not applicable, it returns zero. */
+OPENSSL_EXPORT uint16_t SSL_get_peer_signature_algorithm(const SSL *ssl);
+
+/* SSL_get_client_random writes up to |max_out| bytes of the most recent
+ * handshake's client_random to |out| and returns the number of bytes written.
+ * If |max_out| is zero, it returns the size of the client_random. */
+OPENSSL_EXPORT size_t SSL_get_client_random(const SSL *ssl, uint8_t *out,
+                                            size_t max_out);
+
+/* SSL_get_server_random writes up to |max_out| bytes of the most recent
+ * handshake's server_random to |out| and returns the number of bytes written.
+ * If |max_out| is zero, it returns the size of the server_random. */
+OPENSSL_EXPORT size_t SSL_get_server_random(const SSL *ssl, uint8_t *out,
+                                            size_t max_out);
+
+/* SSL_get_pending_cipher returns the cipher suite for the current handshake or
+ * NULL if one has not been negotiated yet or there is no pending handshake. */
+OPENSSL_EXPORT const SSL_CIPHER *SSL_get_pending_cipher(const SSL *ssl);
+
+/* SSL_set_retain_only_sha256_of_client_certs, on a server, sets whether only
+ * the SHA-256 hash of peer's certificate should be saved in memory and in the
+ * session. This can save memory, ticket size and session cache space. If
+ * enabled, |SSL_get_peer_certificate| will return NULL after the handshake
+ * completes. See the |peer_sha256| field of |SSL_SESSION| for the hash. */
+OPENSSL_EXPORT void SSL_set_retain_only_sha256_of_client_certs(SSL *ssl,
+                                                               int enable);
+
+/* SSL_CTX_set_retain_only_sha256_of_client_certs, on a server, sets whether
+ * only the SHA-256 hash of peer's certificate should be saved in memory and in
+ * the session. This can save memory, ticket size and session cache space. If
+ * enabled, |SSL_get_peer_certificate| will return NULL after the handshake
+ * completes. See the |peer_sha256| field of |SSL_SESSION| for the hash. */
+OPENSSL_EXPORT void SSL_CTX_set_retain_only_sha256_of_client_certs(SSL_CTX *ctx,
+                                                                   int enable);
+
+/* SSL_CTX_set_grease_enabled configures whether sockets on |ctx| should enable
+ * GREASE. See draft-davidben-tls-grease-01. */
+OPENSSL_EXPORT void SSL_CTX_set_grease_enabled(SSL_CTX *ctx, int enabled);
+
+/* SSL_max_seal_overhead returns the maximum overhead, in bytes, of sealing a
+ * record with |ssl|. */
+OPENSSL_EXPORT size_t SSL_max_seal_overhead(const SSL *ssl);
+
+/* SSL_get_ticket_age_skew returns the difference, in seconds, between the
+ * client-sent ticket age and the server-computed value in TLS 1.3 server
+ * connections which resumed a session. */
+OPENSSL_EXPORT int32_t SSL_get_ticket_age_skew(const SSL *ssl);
 
 
 /* Deprecated functions. */
@@ -2866,11 +3348,6 @@
 /* SSL_library_init calls |CRYPTO_library_init| and returns one. */
 OPENSSL_EXPORT int SSL_library_init(void);
 
-/* SSL_set_reject_peer_renegotiations calls |SSL_set_renegotiate_mode| with
- * |ssl_never_renegotiate| if |reject| is one and |ssl_renegotiate_freely| if
- * zero. */
-OPENSSL_EXPORT void SSL_set_reject_peer_renegotiations(SSL *ssl, int reject);
-
 /* SSL_CIPHER_description writes a description of |cipher| into |buf| and
  * returns |buf|. If |buf| is NULL, it returns a newly allocated string, to be
  * freed with |OPENSSL_free|, or NULL on error.
@@ -2896,12 +3373,16 @@
 /* SSL_COMP_get_name returns NULL. */
 OPENSSL_EXPORT const char *SSL_COMP_get_name(const COMP_METHOD *comp);
 
+/* SSL_COMP_free_compression_methods does nothing. */
+OPENSSL_EXPORT void SSL_COMP_free_compression_methods(void);
+
 /* SSLv23_method calls |TLS_method|. */
 OPENSSL_EXPORT const SSL_METHOD *SSLv23_method(void);
 
 /* These version-specific methods behave exactly like |TLS_method| and
- * |DTLS_method| except they also call |SSL_CTX_set_min_version| and
- * |SSL_CTX_set_max_version| to lock connections to that protocol version. */
+ * |DTLS_method| except they also call |SSL_CTX_set_min_proto_version| and
+ * |SSL_CTX_set_max_proto_version| to lock connections to that protocol
+ * version. */
 OPENSSL_EXPORT const SSL_METHOD *SSLv3_method(void);
 OPENSSL_EXPORT const SSL_METHOD *TLSv1_method(void);
 OPENSSL_EXPORT const SSL_METHOD *TLSv1_1_method(void);
@@ -2911,6 +3392,8 @@
 
 /* These client- and server-specific methods call their corresponding generic
  * methods. */
+OPENSSL_EXPORT const SSL_METHOD *TLS_server_method(void);
+OPENSSL_EXPORT const SSL_METHOD *TLS_client_method(void);
 OPENSSL_EXPORT const SSL_METHOD *SSLv23_server_method(void);
 OPENSSL_EXPORT const SSL_METHOD *SSLv23_client_method(void);
 OPENSSL_EXPORT const SSL_METHOD *SSLv3_server_method(void);
@@ -3013,6 +3496,10 @@
 /* SSL_set_state does nothing. */
 OPENSSL_EXPORT void SSL_set_state(SSL *ssl, int state);
 
+/* SSL_get_shared_ciphers writes an empty string to |buf| and returns a
+ * pointer to |buf|, or NULL if |len| is less than or equal to zero. */
+OPENSSL_EXPORT char *SSL_get_shared_ciphers(const SSL *ssl, char *buf, int len);
+
 /* SSL_MODE_HANDSHAKE_CUTTHROUGH is the same as SSL_MODE_ENABLE_FALSE_START. */
 #define SSL_MODE_HANDSHAKE_CUTTHROUGH SSL_MODE_ENABLE_FALSE_START
 
@@ -3071,30 +3558,33 @@
 /* SSL_get_current_expansion returns NULL. */
 OPENSSL_EXPORT const COMP_METHOD *SSL_get_current_expansion(SSL *s);
 
-#define SSL_set_app_data(s, arg) (SSL_set_ex_data(s, 0, (char *)arg))
+/* SSL_get_server_tmp_key returns zero. */
+OPENSSL_EXPORT int *SSL_get_server_tmp_key(SSL *ssl, EVP_PKEY **out_key);
+
+#define SSL_set_app_data(s, arg) (SSL_set_ex_data(s, 0, (char *)(arg)))
 #define SSL_get_app_data(s) (SSL_get_ex_data(s, 0))
 #define SSL_SESSION_set_app_data(s, a) \
-  (SSL_SESSION_set_ex_data(s, 0, (char *)a))
+  (SSL_SESSION_set_ex_data(s, 0, (char *)(a)))
 #define SSL_SESSION_get_app_data(s) (SSL_SESSION_get_ex_data(s, 0))
 #define SSL_CTX_get_app_data(ctx) (SSL_CTX_get_ex_data(ctx, 0))
 #define SSL_CTX_set_app_data(ctx, arg) \
-  (SSL_CTX_set_ex_data(ctx, 0, (char *)arg))
+  (SSL_CTX_set_ex_data(ctx, 0, (char *)(arg)))
 
 #define OpenSSL_add_ssl_algorithms() SSL_library_init()
 #define SSLeay_add_ssl_algorithms() SSL_library_init()
 
 #define SSL_get_cipher(ssl) SSL_CIPHER_get_name(SSL_get_current_cipher(ssl))
 #define SSL_get_cipher_bits(ssl, out_alg_bits) \
-	  SSL_CIPHER_get_bits(SSL_get_current_cipher(ssl), out_alg_bits)
+    SSL_CIPHER_get_bits(SSL_get_current_cipher(ssl), out_alg_bits)
 #define SSL_get_cipher_version(ssl) \
-	  SSL_CIPHER_get_version(SSL_get_current_cipher(ssl))
+    SSL_CIPHER_get_version(SSL_get_current_cipher(ssl))
 #define SSL_get_cipher_name(ssl) \
-	  SSL_CIPHER_get_name(SSL_get_current_cipher(ssl))
+    SSL_CIPHER_get_name(SSL_get_current_cipher(ssl))
 #define SSL_get_time(session) SSL_SESSION_get_time(session)
 #define SSL_set_time(session, time) SSL_SESSION_set_time((session), (time))
 #define SSL_get_timeout(session) SSL_SESSION_get_timeout(session)
 #define SSL_set_timeout(session, timeout) \
-		SSL_SESSION_set_timeout((session), (timeout))
+    SSL_SESSION_set_timeout((session), (timeout))
 
 typedef struct ssl_comp_st SSL_COMP;
 
@@ -3106,15 +3596,6 @@
 
 DECLARE_STACK_OF(SSL_COMP)
 
-/* The following flags toggle individual protocol versions. This is deprecated.
- * Use |SSL_CTX_set_min_version| and |SSL_CTX_set_max_version| instead. */
-#define SSL_OP_NO_SSLv3 0x02000000L
-#define SSL_OP_NO_TLSv1 0x04000000L
-#define SSL_OP_NO_TLSv1_2 0x08000000L
-#define SSL_OP_NO_TLSv1_1 0x10000000L
-#define SSL_OP_NO_DTLSv1 SSL_OP_NO_TLSv1
-#define SSL_OP_NO_DTLSv1_2 SSL_OP_NO_TLSv1_2
-
 /* The following flags do nothing and are included only to make it easier to
  * compile code with BoringSSL. */
 #define SSL_MODE_AUTO_RETRY 0
@@ -3147,7 +3628,7 @@
 #define SSL_OP_TLS_ROLLBACK_BUG 0
 #define SSL_VERIFY_CLIENT_ONCE 0
 
-/* SSL_cache_hit calls |SSL_session_resumed|. */
+/* SSL_cache_hit calls |SSL_session_reused|. */
 OPENSSL_EXPORT int SSL_cache_hit(SSL *ssl);
 
 /* SSL_get_default_timeout returns |SSL_DEFAULT_SESSION_TIMEOUT|. */
@@ -3158,7 +3639,7 @@
 OPENSSL_EXPORT const char *SSL_get_version(const SSL *ssl);
 
 /* SSL_get_cipher_list returns the name of the |n|th cipher in the output of
- * |SSL_get_ciphers| or NULL if out of range. Use |SSL_get_ciphers| insteads. */
+ * |SSL_get_ciphers| or NULL if out of range. Use |SSL_get_ciphers| instead. */
 OPENSSL_EXPORT const char *SSL_get_cipher_list(const SSL *ssl, int n);
 
 /* SSL_CTX_set_client_cert_cb sets a callback which is called on the client if
@@ -3173,16 +3654,12 @@
  * |SSL_get_client_CA_list| for information on the server's certificate request.
  *
  * Use |SSL_CTX_set_cert_cb| instead. Configuring intermediate certificates with
- * this function is confusing. */
+ * this function is confusing. This callback may not be registered concurrently
+ * with |SSL_CTX_set_cert_cb| or |SSL_set_cert_cb|. */
 OPENSSL_EXPORT void SSL_CTX_set_client_cert_cb(
     SSL_CTX *ctx,
     int (*client_cert_cb)(SSL *ssl, X509 **out_x509, EVP_PKEY **out_pkey));
 
-/* SSL_CTX_get_client_cert_cb returns the callback set by
- * |SSL_CTX_set_client_cert_cb|. */
-OPENSSL_EXPORT int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(
-      SSL *ssl, X509 **out_x509, EVP_PKEY **out_pkey);
-
 #define SSL_NOTHING 1
 #define SSL_WRITING 2
 #define SSL_READING 3
@@ -3191,32 +3668,26 @@
 #define SSL_PENDING_SESSION 7
 #define SSL_CERTIFICATE_SELECTION_PENDING 8
 #define SSL_PRIVATE_KEY_OPERATION 9
+#define SSL_PENDING_TICKET 10
 
 /* SSL_want returns one of the above values to determine what the most recent
  * operation on |ssl| was blocked on. Use |SSL_get_error| instead. */
 OPENSSL_EXPORT int SSL_want(const SSL *ssl);
 
-#define SSL_want_nothing(ssl) (SSL_want(ssl) == SSL_NOTHING)
 #define SSL_want_read(ssl) (SSL_want(ssl) == SSL_READING)
 #define SSL_want_write(ssl) (SSL_want(ssl) == SSL_WRITING)
-#define SSL_want_x509_lookup(ssl) (SSL_want(ssl) == SSL_X509_LOOKUP)
-#define SSL_want_channel_id_lookup(ssl) (SSL_want(ssl) == SSL_CHANNEL_ID_LOOKUP)
-#define SSL_want_session(ssl) (SSL_want(ssl) == SSL_PENDING_SESSION)
-#define SSL_want_certificate(ssl) \
-  (SSL_want(ssl) == SSL_CERTIFICATE_SELECTION_PENDING)
-#define SSL_want_private_key_operation(ssl) \
-  (SSL_want(ssl) == SSL_PRIVATE_KEY_OPERATION)
 
  /* SSL_get_finished writes up to |count| bytes of the Finished message sent by
   * |ssl| to |buf|. It returns the total untruncated length or zero if none has
-  * been sent yet.
+  * been sent yet. At SSL 3.0 or TLS 1.3 and later, it returns zero.
   *
   * Use |SSL_get_tls_unique| instead. */
 OPENSSL_EXPORT size_t SSL_get_finished(const SSL *ssl, void *buf, size_t count);
 
  /* SSL_get_peer_finished writes up to |count| bytes of the Finished message
   * received from |ssl|'s peer to |buf|. It returns the total untruncated length
-  * or zero if none has been received yet.
+  * or zero if none has been received yet. At SSL 3.0 or TLS 1.3 and later, it
+  * returns zero.
   *
   * Use |SSL_get_tls_unique| instead. */
 OPENSSL_EXPORT size_t SSL_get_peer_finished(const SSL *ssl, void *buf,
@@ -3268,12 +3739,16 @@
 #define SSL_TXT_TLSV1 "TLSv1"
 #define SSL_TXT_TLSV1_1 "TLSv1.1"
 #define SSL_TXT_TLSV1_2 "TLSv1.2"
+#define SSL_TXT_TLSV1_3 "TLSv1.3"
 #define SSL_TXT_ALL "ALL"
 #define SSL_TXT_CMPDEF "COMPLEMENTOFDEFAULT"
 
 typedef struct ssl_conf_ctx_st SSL_CONF_CTX;
 
-/* SSL_state returns the current state of the handshake state machine. */
+/* SSL_state returns |SSL_ST_INIT| if a handshake is in progress and |SSL_ST_OK|
+ * otherwise.
+ *
+ * Use |SSL_is_init| instead. */
 OPENSSL_EXPORT int SSL_state(const SSL *ssl);
 
 #define SSL_get_state(ssl) SSL_state(ssl)
@@ -3303,6 +3778,68 @@
  * |ec_key|'s curve. */
 OPENSSL_EXPORT int SSL_set_tmp_ecdh(SSL *ssl, const EC_KEY *ec_key);
 
+/* SSL_add_dir_cert_subjects_to_stack lists files in directory |dir|. It calls
+ * |SSL_add_file_cert_subjects_to_stack| on each file and returns one on success
+ * or zero on error. This function is only available from the libdecrepit
+ * library. */
+OPENSSL_EXPORT int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *out,
+                                                      const char *dir);
+
+/* SSL_set_private_key_digest_prefs copies |num_digests| NIDs from |digest_nids|
+ * into |ssl|. These digests will be used, in decreasing order of preference,
+ * when signing with |ssl|'s private key. It returns one on success and zero on
+ * error.
+ *
+ * Use |SSL_set_signing_algorithm_prefs| instead.
+ *
+ * TODO(davidben): Remove this API when callers have been updated. */
+OPENSSL_EXPORT int SSL_set_private_key_digest_prefs(SSL *ssl,
+                                                    const int *digest_nids,
+                                                    size_t num_digests);
+
+/* SSL_set_verify_result calls |abort| unless |result| is |X509_V_OK|.
+ *
+ * TODO(davidben): Remove this function once it has been removed from
+ * netty-tcnative. */
+OPENSSL_EXPORT void SSL_set_verify_result(SSL *ssl, long result);
+
+/* SSL_CTX_set_min_version calls |SSL_CTX_set_min_proto_version|. */
+OPENSSL_EXPORT int SSL_CTX_set_min_version(SSL_CTX *ctx, uint16_t version);
+
+/* SSL_CTX_set_max_version calls |SSL_CTX_set_max_proto_version|. */
+OPENSSL_EXPORT int SSL_CTX_set_max_version(SSL_CTX *ctx, uint16_t version);
+
+/* SSL_set_min_version calls |SSL_set_min_proto_version|. */
+OPENSSL_EXPORT int SSL_set_min_version(SSL *ssl, uint16_t version);
+
+/* SSL_set_max_version calls |SSL_set_max_proto_version|. */
+OPENSSL_EXPORT int SSL_set_max_version(SSL *ssl, uint16_t version);
+
+/* SSL_CTX_enable_tls_channel_id calls |SSL_CTX_set_tls_channel_id_enabled|. */
+OPENSSL_EXPORT int SSL_CTX_enable_tls_channel_id(SSL_CTX *ctx);
+
+/* SSL_enable_tls_channel_id calls |SSL_set_tls_channel_id_enabled|. */
+OPENSSL_EXPORT int SSL_enable_tls_channel_id(SSL *ssl);
+
+/* BIO_f_ssl returns a |BIO_METHOD| that can wrap an |SSL*| in a |BIO*|. Note
+ * that this has quite different behaviour from the version in OpenSSL (notably
+ * that it doesn't try to auto renegotiate).
+ *
+ * IMPORTANT: if you are not curl, don't use this. */
+OPENSSL_EXPORT const BIO_METHOD *BIO_f_ssl(void);
+
+/* BIO_set_ssl sets |ssl| as the underlying connection for |bio|, which must
+ * have been created using |BIO_f_ssl|. If |take_owership| is true, |bio| will
+ * call |SSL_free| on |ssl| when closed. It returns one on success or something
+ * other than one on error. */
+OPENSSL_EXPORT long BIO_set_ssl(BIO *bio, SSL *ssl, int take_owership);
+
+/* SSL_CTX_set_ecdh_auto returns one. */
+#define SSL_CTX_set_ecdh_auto(ctx, onoff) 1
+
+/* SSL_set_ecdh_auto returns one. */
+#define SSL_set_ecdh_auto(ssl, onoff) 1
+
 
 /* Private structures.
  *
@@ -3310,8 +3847,7 @@
  * deprecated. */
 
 typedef struct ssl_protocol_method_st SSL_PROTOCOL_METHOD;
-typedef struct ssl3_enc_method SSL3_ENC_METHOD;
-typedef struct ssl_aead_ctx_st SSL_AEAD_CTX;
+typedef struct ssl_x509_method_st SSL_X509_METHOD;
 
 struct ssl_cipher_st {
   /* name is the OpenSSL name for the cipher. */
@@ -3327,12 +3863,6 @@
   uint32_t algorithm_prf;
 };
 
-typedef struct ssl_ecdh_method_st SSL_ECDH_METHOD;
-typedef struct ssl_ecdh_ctx_st {
-  const SSL_ECDH_METHOD *method;
-  void *data;
-} SSL_ECDH_CTX;
-
 #define SSL_MAX_SSL_SESSION_ID_LENGTH 32
 #define SSL_MAX_SID_CTX_LENGTH 32
 #define SSL_MAX_MASTER_KEY_LENGTH 48
@@ -3341,18 +3871,16 @@
   CRYPTO_refcount_t references;
   int ssl_version; /* what ssl version session info is being kept in here? */
 
-  /* key_exchange_info contains an indication of the size of the asymmetric
-   * primitive used in the handshake that created this session. In the event
-   * that two asymmetric operations are used, this value applies to the one
-   * that controls the confidentiality of the connection. Its interpretation
-   * depends on the primitive that was used; as specified by the cipher suite:
-   *   DHE: the size, in bits, of the multiplicative group.
-   *   RSA: the size, in bits, of the modulus.
-   *   ECDHE: the TLS id for the curve.
-   *
-   * A zero indicates that the value is unknown. */
-  uint32_t key_exchange_info;
+  /* group_id is the ID of the ECDH group used to establish this session or zero
+   * if not applicable or unknown. */
+  uint16_t group_id;
 
+  /* peer_signature_algorithm is the signature algorithm used to authenticate
+   * the peer, or zero if not applicable or unknown. */
+  uint16_t peer_signature_algorithm;
+
+  /* master_key, in TLS 1.2 and below, is the master secret associated with the
+   * session. In TLS 1.3 and up, it is the resumption secret. */
   int master_key_length;
   uint8_t master_key[SSL_MAX_MASTER_KEY_LENGTH];
 
@@ -3362,24 +3890,47 @@
   /* this is used to determine whether the session is being reused in
    * the appropriate context. It is up to the application to set this,
    * via SSL_new */
-  unsigned int sid_ctx_length;
+  uint8_t sid_ctx_length;
   uint8_t sid_ctx[SSL_MAX_SID_CTX_LENGTH];
 
   char *psk_identity;
-  /* peer is the peer's certificate. */
-  X509 *peer;
 
-  /* cert_chain is the certificate chain sent by the peer. NOTE: for historical
+  /* certs contains the certificate chain from the peer, starting with the leaf
+   * certificate. */
+  STACK_OF(CRYPTO_BUFFER) *certs;
+
+  const SSL_X509_METHOD *x509_method;
+
+  /* x509_peer is the peer's certificate. */
+  X509 *x509_peer;
+
+  /* x509_chain is the certificate chain sent by the peer. NOTE: for historical
    * reasons, when a client (so the peer is a server), the chain includes
    * |peer|, but when a server it does not. */
-  STACK_OF(X509) *cert_chain;
+  STACK_OF(X509) *x509_chain;
 
-  /* when app_verify_callback accepts a session where the peer's certificate is
-   * not ok, we must remember the error for session reuse: */
-  long verify_result; /* only for servers */
+  /* x509_chain_without_leaf is a lazily constructed copy of |x509_chain| that
+   * omits the leaf certificate. This exists because OpenSSL, historically,
+   * didn't include the leaf certificate in the chain for a server, but did for
+   * a client. The |x509_chain| always includes it and, if an API call requires
+   * a chain without, it is stored here. */
+  STACK_OF(X509) *x509_chain_without_leaf;
 
-  long timeout;
-  long time;
+  /* verify_result is the result of certificate verification in the case of
+   * non-fatal certificate errors. */
+  long verify_result;
+
+  /* timeout is the lifetime of the session in seconds, measured from |time|.
+   * This is renewable up to |auth_timeout|. */
+  uint32_t timeout;
+
+  /* auth_timeout is the non-renewable lifetime of the session in seconds,
+   * measured from |time|. */
+  uint32_t auth_timeout;
+
+  /* time is the time the session was issued, measured in seconds from the UNIX
+   * epoch. */
+  uint64_t time;
 
   const SSL_CIPHER *cipher;
 
@@ -3409,10 +3960,22 @@
    * SHA-2, depending on TLS version) for the original, full handshake that
    * created a session. This is used by Channel IDs during resumption. */
   uint8_t original_handshake_hash[EVP_MAX_MD_SIZE];
-  unsigned original_handshake_hash_len;
+  uint8_t original_handshake_hash_len;
 
   uint32_t tlsext_tick_lifetime_hint; /* Session lifetime hint in seconds */
 
+  uint32_t ticket_age_add;
+
+  /* ticket_max_early_data is the maximum amount of data allowed to be sent as
+   * early data. If zero, 0-RTT is disallowed. */
+  uint32_t ticket_max_early_data;
+
+  /* early_alpn is the ALPN protocol from the initial handshake. This is only
+   * stored for TLS 1.3 and above in order to enforce ALPN matching for 0-RTT
+   * resumptions. */
+  uint8_t *early_alpn;
+  size_t early_alpn_len;
+
   /* extended_master_secret is true if the master secret in this session was
    * generated using EMS and thus isn't vulnerable to the Triple Handshake
    * attack. */
@@ -3421,10 +3984,14 @@
   /* peer_sha256_valid is non-zero if |peer_sha256| is valid. */
   unsigned peer_sha256_valid:1; /* Non-zero if peer_sha256 is valid */
 
-  /* not_resumable is used to indicate that session resumption is not allowed.
-   * Applications can also set this bit for a new session via
-   * not_resumable_session_cb to disable session caching and tickets. */
+  /* not_resumable is used to indicate that session resumption is disallowed. */
   unsigned not_resumable:1;
+
+  /* ticket_age_add_valid is non-zero if |ticket_age_add| is valid. */
+  unsigned ticket_age_add_valid:1;
+
+  /* is_server is true if this session was created by a server. */
+  unsigned is_server:1;
 };
 
 /* ssl_cipher_preference_list_st contains a list of SSL_CIPHERs with
@@ -3463,38 +4030,24 @@
   uint8_t *in_group_flags;
 };
 
+/* ssl_ctx_st (aka |SSL_CTX|) contains configuration common to several SSL
+ * connections. */
 struct ssl_ctx_st {
   const SSL_PROTOCOL_METHOD *method;
+  const SSL_X509_METHOD *x509_method;
 
   /* lock is used to protect various operations on this object. */
   CRYPTO_MUTEX lock;
 
-  /* max_version is the maximum acceptable protocol version. If zero, the
-   * maximum supported version, currently (D)TLS 1.2, is used. */
+  /* max_version is the maximum acceptable protocol version. Note this version
+   * is normalized in DTLS. */
   uint16_t max_version;
 
-  /* min_version is the minimum acceptable protocl version. If zero, the
-   * minimum supported version, currently SSL 3.0 and DTLS 1.0, is used */
+  /* min_version is the minimum acceptable protocol version. Note this version
+   * is normalized in DTLS. */
   uint16_t min_version;
 
   struct ssl_cipher_preference_list_st *cipher_list;
-  /* same as above but sorted for lookup */
-  STACK_OF(SSL_CIPHER) *cipher_list_by_id;
-
-  /* cipher_list_tls10 is the list of ciphers when TLS 1.0 or greater is in
-   * use. This only applies to server connections as, for clients, the version
-   * number is known at connect time and so the cipher list can be set then. If
-   * |cipher_list_tls11| is non-NULL then this applies only to TLS 1.0
-   * connections.
-   *
-   * TODO(agl): this exists to assist in the death of SSLv3. It can hopefully
-   * be removed after that. */
-  struct ssl_cipher_preference_list_st *cipher_list_tls10;
-
-  /* cipher_list_tls11 is the list of ciphers when TLS 1.1 or greater is in
-   * use. This only applies to server connections as, for clients, the version
-   * number is known at connect time and so the cipher list can be set then. */
-  struct ssl_cipher_preference_list_st *cipher_list_tls11;
 
   X509_STORE *cert_store;
   LHASH_OF(SSL_SESSION) *sessions;
@@ -3515,9 +4068,13 @@
    * SSL_accept which cache SSL_SESSIONS. */
   int session_cache_mode;
 
-  /* If timeout is not 0, it is the default timeout value set when SSL_new() is
-   * called.  This has been put in to make life easier to set things up */
-  long session_timeout;
+  /* session_timeout is the default lifetime for new sessions in TLS 1.2 and
+   * earlier, in seconds. */
+  uint32_t session_timeout;
+
+  /* session_psk_dhe_timeout is the default lifetime for new sessions in TLS
+   * 1.3, in seconds. */
+  uint32_t session_psk_dhe_timeout;
 
   /* If this callback is not null, it will be called each time a session id is
    * added to the cache.  If this function returns 1, it means that the
@@ -3561,7 +4118,11 @@
   void (*info_callback)(const SSL *ssl, int type, int value);
 
   /* what we put in client cert requests */
-  STACK_OF(X509_NAME) *client_CA;
+  STACK_OF(CRYPTO_BUFFER) *client_CA;
+
+  /* cached_x509_client_CA is a cache of parsed versions of the elements of
+   * |client_CA|. */
+  STACK_OF(X509_NAME) *cached_x509_client_CA;
 
 
   /* Default values to use in SSL structures follow (these are copied by
@@ -3579,25 +4140,21 @@
   void *msg_callback_arg;
 
   int verify_mode;
-  unsigned int sid_ctx_length;
-  uint8_t sid_ctx[SSL_MAX_SID_CTX_LENGTH];
   int (*default_verify_callback)(
       int ok, X509_STORE_CTX *ctx); /* called 'verify_callback' in the SSL */
 
   X509_VERIFY_PARAM *param;
 
   /* select_certificate_cb is called before most ClientHello processing and
-   * before the decision whether to resume a session is made. It may return one
-   * to continue the handshake or zero to cause the handshake loop to return
-   * with an error and cause SSL_get_error to return
-   * SSL_ERROR_PENDING_CERTIFICATE. Note: when the handshake loop is resumed, it
-   * will not call the callback a second time. */
-  int (*select_certificate_cb)(const struct ssl_early_callback_ctx *);
+   * before the decision whether to resume a session is made. See
+   * |ssl_select_cert_result_t| for details of the return values. */
+  enum ssl_select_cert_result_t (*select_certificate_cb)(
+      const SSL_CLIENT_HELLO *);
 
   /* dos_protection_cb is called once the resumption decision for a ClientHello
    * has been made. It returns one to continue the handshake or zero to
    * abort. */
-  int (*dos_protection_cb) (const struct ssl_early_callback_ctx *);
+  int (*dos_protection_cb) (const SSL_CLIENT_HELLO *);
 
   /* Maximum amount of data to send in one fragment. actual record size can be
    * more than this due to padding and MAC overheads. */
@@ -3627,7 +4184,7 @@
 
 
   /* retain_only_sha256_of_client_certs is true if we should compute the SHA256
-   * hash of the peer's certifiate and then discard it to save memory and
+   * hash of the peer's certificate and then discard it to save memory and
    * session space. Only effective on the server side. */
   char retain_only_sha256_of_client_certs;
 
@@ -3668,33 +4225,38 @@
   /* SRTP profiles we are willing to do from RFC 5764 */
   STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles;
 
-  /* EC extension values inherited by SSL structure */
-  size_t tlsext_ellipticcurvelist_length;
-  uint16_t *tlsext_ellipticcurvelist;
+  /* Supported group values inherited by SSL structure */
+  size_t supported_group_list_len;
+  uint16_t *supported_group_list;
 
   /* The client's Channel ID private key. */
   EVP_PKEY *tlsext_channel_id_private;
 
-  /* Signed certificate timestamp list to be sent to the client, if requested */
-  uint8_t *signed_cert_timestamp_list;
-  size_t signed_cert_timestamp_list_length;
-
-  /* OCSP response to be sent to the client, if requested. */
-  uint8_t *ocsp_response;
-  size_t ocsp_response_length;
-
   /* keylog_callback, if not NULL, is the key logging callback. See
    * |SSL_CTX_set_keylog_callback|. */
   void (*keylog_callback)(const SSL *ssl, const char *line);
 
   /* current_time_cb, if not NULL, is the function to use to get the current
-   * time. It sets |*out_clock| to the current time. */
+   * time. It sets |*out_clock| to the current time. See
+   * |SSL_CTX_set_current_time_cb|. */
   void (*current_time_cb)(const SSL *ssl, struct timeval *out_clock);
 
+  /* pool is used for all |CRYPTO_BUFFER|s in case we wish to share certificate
+   * memory. */
+  CRYPTO_BUFFER_POOL *pool;
+
+  /* ticket_aead_method contains function pointers for opening and sealing
+   * session tickets. */
+  const SSL_TICKET_AEAD_METHOD *ticket_aead_method;
+
   /* quiet_shutdown is true if the connection should not send a close_notify on
    * shutdown. */
   unsigned quiet_shutdown:1;
 
+  /* If enable_early_data is non-zero, early data can be sent and accepted over
+   * new connections. */
+  unsigned enable_early_data:1;
+
   /* ocsp_stapling_enabled is only used by client connections and indicates
    * whether OCSP stapling will be requested. */
   unsigned ocsp_stapling_enabled:1;
@@ -3702,453 +4264,29 @@
   /* If true, a client will request certificate timestamps. */
   unsigned signed_cert_timestamps_enabled:1;
 
-  /* tlsext_channel_id_enabled is copied from the |SSL_CTX|. For a server,
-   * means that we'll accept Channel IDs from clients. For a client, means that
-   * we'll advertise support. */
+  /* tlsext_channel_id_enabled is one if Channel ID is enabled and zero
+   * otherwise. For a server, means that we'll accept Channel IDs from clients.
+   * For a client, means that we'll advertise support. */
   unsigned tlsext_channel_id_enabled:1;
+
+  /* grease_enabled is one if draft-davidben-tls-grease-01 is enabled and zero
+   * otherwise. */
+  unsigned grease_enabled:1;
+
+  /* i_promise_to_verify_certs_after_the_handshake indicates that the
+   * application is using the |CRYPTO_BUFFER|-based methods and understands
+   * that this currently requires post-handshake verification of
+   * certificates. */
+  unsigned i_promise_to_verify_certs_after_the_handshake:1;
 };
 
-struct ssl_st {
-  /* version is the protocol version. */
-  int version;
 
-  /* max_version is the maximum acceptable protocol version. If zero, the
-   * maximum supported version, currently (D)TLS 1.2, is used. */
-  uint16_t max_version;
-
-  /* min_version is the minimum acceptable protocl version. If zero, the
-   * minimum supported version, currently SSL 3.0 and DTLS 1.0, is used */
-  uint16_t min_version;
-
-  /* method is the method table corresponding to the current protocol (DTLS or
-   * TLS). */
-  const SSL_PROTOCOL_METHOD *method;
-
-  /* enc_method is the method table corresponding to the current protocol
-   * version. */
-  const SSL3_ENC_METHOD *enc_method;
-
-  /* There are 2 BIO's even though they are normally both the same. This is so
-   * data can be read and written to different handlers */
-
-  BIO *rbio; /* used by SSL_read */
-  BIO *wbio; /* used by SSL_write */
-
-  /* bbio, if non-NULL, is a buffer placed in front of |wbio| to pack handshake
-   * messages within one flight into a single |BIO_write|.
-   *
-   * TODO(davidben): This does not work right for DTLS. It assumes the MTU is
-   * smaller than the buffer size so that the buffer's internal flushing never
-   * kicks in. It also doesn't kick in for DTLS retransmission. Replace this
-   * with a better mechanism. */
-  BIO *bbio;
-
-  int (*handshake_func)(SSL *);
-
-  /* Imagine that here's a boolean member "init" that is switched as soon as
-   * SSL_set_{accept/connect}_state is called for the first time, so that
-   * "state" and "handshake_func" are properly initialized.  But as
-   * handshake_func is == 0 until then, we use this test instead of an "init"
-   * member. */
-
-  int shutdown; /* we have shut things down, 0x01 sent, 0x02
-                 * for received */
-  int state;    /* where we are */
-
-  BUF_MEM *init_buf; /* buffer used during init */
-  uint8_t *init_msg; /* pointer to handshake message body, set by
-                        ssl3_get_message() */
-  int init_num;      /* amount read/written */
-  int init_off;      /* amount read/written */
-
-  struct ssl3_state_st *s3;  /* SSLv3 variables */
-  struct dtls1_state_st *d1; /* DTLSv1 variables */
-
-  /* callback that allows applications to peek at protocol messages */
-  void (*msg_callback)(int write_p, int version, int content_type,
-                       const void *buf, size_t len, SSL *ssl, void *arg);
-  void *msg_callback_arg;
-
-  X509_VERIFY_PARAM *param;
-
-  /* crypto */
-  struct ssl_cipher_preference_list_st *cipher_list;
-  STACK_OF(SSL_CIPHER) *cipher_list_by_id;
-
-  SSL_AEAD_CTX *aead_read_ctx;
-  SSL_AEAD_CTX *aead_write_ctx;
-
-  /* session info */
-
-  /* client cert? */
-  /* This is used to hold the server certificate used */
-  struct cert_st /* CERT */ *cert;
-
-  /* This holds a variable that indicates what we were doing when a 0 or -1 is
-   * returned.  This is needed for non-blocking IO so we know what request
-   * needs re-doing when in SSL_accept or SSL_connect */
-  int rwstate;
-
-  /* the session_id_context is used to ensure sessions are only reused
-   * in the appropriate context */
-  unsigned int sid_ctx_length;
-  uint8_t sid_ctx[SSL_MAX_SID_CTX_LENGTH];
-
-  /* This can also be in the session once a session is established */
-  SSL_SESSION *session;
-
-  int (*verify_callback)(int ok,
-                         X509_STORE_CTX *ctx); /* fail if callback returns 0 */
-
-  void (*info_callback)(const SSL *ssl, int type, int value);
-
-  /* Server-only: psk_identity_hint is the identity hint to send in
-   * PSK-based key exchanges. */
-  char *psk_identity_hint;
-
-  unsigned int (*psk_client_callback)(SSL *ssl, const char *hint,
-                                      char *identity,
-                                      unsigned int max_identity_len,
-                                      uint8_t *psk, unsigned int max_psk_len);
-  unsigned int (*psk_server_callback)(SSL *ssl, const char *identity,
-                                      uint8_t *psk, unsigned int max_psk_len);
-
-  SSL_CTX *ctx;
-
-  /* extra application data */
-  long verify_result;
-  CRYPTO_EX_DATA ex_data;
-
-  /* for server side, keep the list of CA_dn we can use */
-  STACK_OF(X509_NAME) *client_CA;
-
-  uint32_t options; /* protocol behaviour */
-  uint32_t mode;    /* API behaviour */
-  uint32_t max_cert_list;
-  int client_version; /* what was passed, used for
-                       * SSLv3/TLS rollback check */
-  uint16_t max_send_fragment;
-  char *tlsext_hostname;
-  /* RFC4507 session ticket expected to be received or sent */
-  int tlsext_ticket_expected;
-  size_t tlsext_ellipticcurvelist_length;
-  uint16_t *tlsext_ellipticcurvelist; /* our list */
-
-  SSL_CTX *initial_ctx; /* initial ctx, used to store sessions */
-
-  /* Next protocol negotiation. For the client, this is the protocol that we
-   * sent in NextProtocol and is set when handling ServerHello extensions.
-   *
-   * For a server, this is the client's selected_protocol from NextProtocol and
-   * is set when handling the NextProtocol message, before the Finished
-   * message. */
-  uint8_t *next_proto_negotiated;
-  size_t next_proto_negotiated_len;
-
-  /* srtp_profiles is the list of configured SRTP protection profiles for
-   * DTLS-SRTP. */
-  STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles;
-
-  /* srtp_profile is the selected SRTP protection profile for
-   * DTLS-SRTP. */
-  const SRTP_PROTECTION_PROFILE *srtp_profile;
-
-  /* The client's Channel ID private key. */
-  EVP_PKEY *tlsext_channel_id_private;
-
-  /* For a client, this contains the list of supported protocols in wire
-   * format. */
-  uint8_t *alpn_client_proto_list;
-  unsigned alpn_client_proto_list_len;
-
-  /* renegotiate_mode controls how peer renegotiation attempts are handled. */
-  enum ssl_renegotiate_mode_t renegotiate_mode;
-
-  /* These fields are always NULL and exist only to keep wpa_supplicant happy
-   * about the change to EVP_AEAD. They are only needed for EAP-FAST, which we
-   * don't support. */
-  EVP_CIPHER_CTX *enc_read_ctx;
-  EVP_MD_CTX *read_hash;
-
-  /* in_handshake is non-zero when we are actually in SSL_accept() or
-   * SSL_connect() */
-  int in_handshake;
-
-  /* verify_mode is a bitmask of |SSL_VERIFY_*| values. */
-  uint8_t verify_mode;
-
-  /* hit is true if this connection is resuming a previous session. */
-  unsigned hit:1;
-
-  /* server is true iff the this SSL* is the server half. Note: before the SSL*
-   * is initialized by either SSL_set_accept_state or SSL_set_connect_state,
-   * the side is not determined. In this state, server is always false. */
-  unsigned server:1;
-
-  /* quiet_shutdown is true if the connection should not send a close_notify on
-   * shutdown. */
-  unsigned quiet_shutdown:1;
-
-  /* Enable signed certificate time stamps. Currently client only. */
-  unsigned signed_cert_timestamps_enabled:1;
-
-  /* ocsp_stapling_enabled is only used by client connections and indicates
-   * whether OCSP stapling will be requested. */
-  unsigned ocsp_stapling_enabled:1;
-
-  /* tlsext_channel_id_enabled is copied from the |SSL_CTX|. For a server,
-   * means that we'll accept Channel IDs from clients. For a client, means that
-   * we'll advertise support. */
-  unsigned tlsext_channel_id_enabled:1;
-};
-
-typedef struct ssl3_record_st {
-  /* type is the record type. */
-  uint8_t type;
-  /* length is the number of unconsumed bytes in the record. */
-  uint16_t length;
-  /* data is a non-owning pointer to the first unconsumed byte of the record. */
-  uint8_t *data;
-} SSL3_RECORD;
-
-typedef struct ssl3_buffer_st {
-  /* buf is the memory allocated for this buffer. */
-  uint8_t *buf;
-  /* offset is the offset into |buf| which the buffer contents start at. */
-  uint16_t offset;
-  /* len is the length of the buffer contents from |buf| + |offset|. */
-  uint16_t len;
-  /* cap is how much memory beyond |buf| + |offset| is available. */
-  uint16_t cap;
-} SSL3_BUFFER;
-
-typedef struct ssl3_state_st {
-  uint8_t read_sequence[8];
-  uint8_t write_sequence[8];
-
-  uint8_t server_random[SSL3_RANDOM_SIZE];
-  uint8_t client_random[SSL3_RANDOM_SIZE];
-
-  /* have_version is true if the connection's final version is known. Otherwise
-   * the version has not been negotiated yet. */
-  char have_version;
-
-  /* initial_handshake_complete is true if the initial handshake has
-   * completed. */
-  char initial_handshake_complete;
-
-  /* read_buffer holds data from the transport to be processed. */
-  SSL3_BUFFER read_buffer;
-  /* write_buffer holds data to be written to the transport. */
-  SSL3_BUFFER write_buffer;
-
-  SSL3_RECORD rrec; /* each decoded record goes in here */
-
-  /* hello_request_len is the number of bytes of HelloRequest received, possibly
-   * split over multiple records. */
-  uint8_t hello_request_len;
-
-  /* partial write - check the numbers match */
-  unsigned int wnum; /* number of bytes sent so far */
-  int wpend_tot;     /* number bytes written */
-  int wpend_type;
-  int wpend_ret; /* number of bytes submitted */
-  const uint8_t *wpend_buf;
-
-  /* handshake_buffer, if non-NULL, contains the handshake transcript. */
-  BUF_MEM *handshake_buffer;
-  /* handshake_hash, if initialized with an |EVP_MD|, maintains the handshake
-   * hash. For TLS 1.1 and below, it is the SHA-1 half. */
-  EVP_MD_CTX handshake_hash;
-  /* handshake_md5, if initialized with an |EVP_MD|, maintains the MD5 half of
-   * the handshake hash for TLS 1.1 and below. */
-  EVP_MD_CTX handshake_md5;
-
-  int warn_alert;
-  int fatal_alert;
-  /* we allow one fatal and one warning alert to be outstanding, send close
-   * alert via the warning alert */
-  int alert_dispatch;
-  uint8_t send_alert[2];
-
-  int total_renegotiations;
-
-  /* empty_record_count is the number of consecutive empty records received. */
-  uint8_t empty_record_count;
-
-  /* warning_alert_count is the number of consecutive warning alerts
-   * received. */
-  uint8_t warning_alert_count;
-
-  /* State pertaining to the pending handshake.
-   *
-   * TODO(davidben): State is current spread all over the place. Move
-   * pending handshake state here so it can be managed separately from
-   * established connection state in case of renegotiations. */
-  struct {
-    uint8_t finish_md[EVP_MAX_MD_SIZE];
-    int finish_md_len;
-    uint8_t peer_finish_md[EVP_MAX_MD_SIZE];
-    int peer_finish_md_len;
-
-    unsigned long message_size;
-    int message_type;
-
-    /* used to hold the new cipher we are going to use */
-    const SSL_CIPHER *new_cipher;
-
-    /* used when SSL_ST_FLUSH_DATA is entered */
-    int next_state;
-
-    int reuse_message;
-
-    union {
-      /* sent is a bitset where the bits correspond to elements of kExtensions
-       * in t1_lib.c. Each bit is set if that extension was sent in a
-       * ClientHello. It's not used by servers. */
-      uint32_t sent;
-      /* received is a bitset, like |sent|, but is used by servers to record
-       * which extensions were received from a client. */
-      uint32_t received;
-    } extensions;
-
-    union {
-      /* sent is a bitset where the bits correspond to elements of
-       * |client_custom_extensions| in the |SSL_CTX|. Each bit is set if that
-       * extension was sent in a ClientHello. It's not used by servers. */
-      uint16_t sent;
-      /* received is a bitset, like |sent|, but is used by servers to record
-       * which custom extensions were received from a client. The bits here
-       * correspond to |server_custom_extensions|. */
-      uint16_t received;
-    } custom_extensions;
-
-    /* SNI extension */
-
-    /* should_ack_sni is used by a server and indicates that the SNI extension
-     * should be echoed in the ServerHello. */
-    unsigned should_ack_sni:1;
-
-
-    /* Client-only: cert_req determines if a client certificate is to be sent.
-     * This is 0 if no client Certificate message is to be sent, 1 if there is
-     * a client certificate, and 2 to send an empty client Certificate
-     * message. */
-    int cert_req;
-
-    /* Client-only: ca_names contains the list of CAs received in a
-     * CertificateRequest message. */
-    STACK_OF(X509_NAME) *ca_names;
-
-    /* Client-only: certificate_types contains the set of certificate types
-     * received in a CertificateRequest message. */
-    uint8_t *certificate_types;
-    size_t num_certificate_types;
-
-    int key_block_length;
-    uint8_t *key_block;
-
-    const EVP_AEAD *new_aead;
-    uint8_t new_mac_secret_len;
-    uint8_t new_fixed_iv_len;
-    uint8_t new_variable_iv_len;
-
-    /* Server-only: cert_request is true if a client certificate was
-     * requested. */
-    int cert_request;
-
-    /* certificate_status_expected is true if OCSP stapling was negotiated and
-     * the server is expected to send a CertificateStatus message. (This is
-     * used on both the client and server sides.) */
-    unsigned certificate_status_expected:1;
-
-    /* ocsp_stapling_requested is true if a client requested OCSP stapling. */
-    unsigned ocsp_stapling_requested:1;
-
-    /* Server-only: peer_ellipticcurvelist contains the EC curve IDs advertised
-     * by the peer. This is only set on the server's end. The server does not
-     * advertise this extension to the client. */
-    uint16_t *peer_ellipticcurvelist;
-    size_t peer_ellipticcurvelist_length;
-
-    /* extended_master_secret indicates whether the extended master secret
-     * computation is used in this handshake. Note that this is different from
-     * whether it was used for the current session. If this is a resumption
-     * handshake then EMS might be negotiated in the client and server hello
-     * messages, but it doesn't matter if the session that's being resumed
-     * didn't use it to create the master secret initially. */
-    char extended_master_secret;
-
-    /* Client-only: peer_psk_identity_hint is the psk_identity_hint sent by the
-     * server when using a PSK key exchange. */
-    char *peer_psk_identity_hint;
-
-    /* new_mac_secret_size is unused and exists only until wpa_supplicant can
-     * be updated. It is only needed for EAP-FAST, which we don't support. */
-    uint8_t new_mac_secret_size;
-
-    /* Client-only: in_false_start is one if there is a pending handshake in
-     * False Start. The client may write data at this point. */
-    char in_false_start;
-
-    /* server_key_exchange_hash, on a client, is the hash the server used to
-     * sign the ServerKeyExchange in TLS 1.2. If not applicable, it is
-     * |TLSEXT_hash_none|. */
-    uint8_t server_key_exchange_hash;
-
-    /* ecdh_ctx is the current ECDH instance. */
-    SSL_ECDH_CTX ecdh_ctx;
-
-    /* peer_key is the peer's ECDH key. */
-    uint8_t *peer_key;
-    uint16_t peer_key_len;
-  } tmp;
-
-  /* Connection binding to prevent renegotiation attacks */
-  uint8_t previous_client_finished[EVP_MAX_MD_SIZE];
-  uint8_t previous_client_finished_len;
-  uint8_t previous_server_finished[EVP_MAX_MD_SIZE];
-  uint8_t previous_server_finished_len;
-  int send_connection_binding; /* TODOEKR */
-
-  /* Set if we saw the Next Protocol Negotiation extension from our peer. */
-  int next_proto_neg_seen;
-
-  /* ALPN information
-   * (we are in the process of transitioning from NPN to ALPN.) */
-
-  /* In a server these point to the selected ALPN protocol after the
-   * ClientHello has been processed. In a client these contain the protocol
-   * that the server selected once the ServerHello has been processed. */
-  uint8_t *alpn_selected;
-  size_t alpn_selected_len;
-
-  /* In a client, this means that the server supported Channel ID and that a
-   * Channel ID was sent. In a server it means that we echoed support for
-   * Channel IDs and that tlsext_channel_id will be valid after the
-   * handshake. */
-  char tlsext_channel_id_valid;
-  /* For a server:
-   *     If |tlsext_channel_id_valid| is true, then this contains the
-   *     verified Channel ID from the client: a P256 point, (x,y), where
-   *     each are big-endian values. */
-  uint8_t tlsext_channel_id[64];
-} SSL3_STATE;
-
-
-/* Android compatibility section (hidden).
+/* Nodejs compatibility section (hidden).
  *
- * These functions are declared, temporarily, for Android because
- * wpa_supplicant will take a little time to sync with upstream. Outside of
- * Android they'll have no definition. */
-
-#define SSL_F_SSL_SET_SESSION_TICKET_EXT doesnt_exist
-
-OPENSSL_EXPORT int SSL_set_session_ticket_ext(SSL *s, void *ext_data,
-                                              int ext_len);
-OPENSSL_EXPORT int SSL_set_session_secret_cb(SSL *s, void *cb, void *arg);
-OPENSSL_EXPORT int SSL_set_session_ticket_ext_cb(SSL *s, void *cb, void *arg);
-OPENSSL_EXPORT int SSL_set_ssl_method(SSL *s, const SSL_METHOD *method);
+ * These defines exist for node.js, with the hope that we can eliminate the
+ * need for them over time. */
+#define SSLerr(function, reason) \
+  ERR_put_error(ERR_LIB_SSL, 0, reason, __FILE__, __LINE__)
 
 
 /* Preprocessor compatibility section (hidden).
@@ -4159,7 +4297,12 @@
  *
  * Although using either the CTRL values or their wrapper macros in #ifdefs is
  * still supported, the CTRL values may not be passed to |SSL_ctrl| and
- * |SSL_CTX_ctrl|. Call the functions (previously wrapper macros) instead. */
+ * |SSL_CTX_ctrl|. Call the functions (previously wrapper macros) instead.
+ *
+ * See PORTING.md in the BoringSSL source tree for a table of corresponding
+ * functions.
+ * https://boringssl.googlesource.com/boringssl/+/master/PORTING.md#Replacements-for-values
+ */
 
 #define DTLS_CTRL_GET_TIMEOUT doesnt_exist
 #define DTLS_CTRL_HANDLE_TIMEOUT doesnt_exist
@@ -4187,8 +4330,9 @@
 #define SSL_CTRL_NEED_TMP_RSA doesnt_exist
 #define SSL_CTRL_OPTIONS doesnt_exist
 #define SSL_CTRL_SESS_NUMBER doesnt_exist
-#define SSL_CTRL_SET_CHANNEL_ID doesnt_exist
 #define SSL_CTRL_SET_CURVES doesnt_exist
+#define SSL_CTRL_SET_CURVES_LIST doesnt_exist
+#define SSL_CTRL_SET_ECDH_AUTO doesnt_exist
 #define SSL_CTRL_SET_MAX_CERT_LIST doesnt_exist
 #define SSL_CTRL_SET_MAX_SEND_FRAGMENT doesnt_exist
 #define SSL_CTRL_SET_MSG_CALLBACK doesnt_exist
@@ -4218,7 +4362,6 @@
 #define SSL_CTX_clear_chain_certs SSL_CTX_clear_chain_certs
 #define SSL_CTX_clear_mode SSL_CTX_clear_mode
 #define SSL_CTX_clear_options SSL_CTX_clear_options
-#define SSL_CTX_enable_tls_channel_id SSL_CTX_enable_tls_channel_id
 #define SSL_CTX_get0_chain_certs SSL_CTX_get0_chain_certs
 #define SSL_CTX_get_extra_chain_certs SSL_CTX_get_extra_chain_certs
 #define SSL_CTX_get_max_cert_list SSL_CTX_get_max_cert_list
@@ -4234,7 +4377,6 @@
 #define SSL_CTX_set0_chain SSL_CTX_set0_chain
 #define SSL_CTX_set1_chain SSL_CTX_set1_chain
 #define SSL_CTX_set1_curves SSL_CTX_set1_curves
-#define SSL_CTX_set1_tls_channel_id SSL_CTX_set1_tls_channel_id
 #define SSL_CTX_set_max_cert_list SSL_CTX_set_max_cert_list
 #define SSL_CTX_set_max_send_fragment SSL_CTX_set_max_send_fragment
 #define SSL_CTX_set_mode SSL_CTX_set_mode
@@ -4255,7 +4397,6 @@
 #define SSL_clear_chain_certs SSL_clear_chain_certs
 #define SSL_clear_mode SSL_clear_mode
 #define SSL_clear_options SSL_clear_options
-#define SSL_enable_tls_channel_id SSL_enable_tls_channel_id
 #define SSL_get0_certificate_types SSL_get0_certificate_types
 #define SSL_get0_chain_certs SSL_get0_chain_certs
 #define SSL_get_max_cert_list SSL_get_max_cert_list
@@ -4263,14 +4404,12 @@
 #define SSL_get_options SSL_get_options
 #define SSL_get_secure_renegotiation_support \
     SSL_get_secure_renegotiation_support
-#define SSL_get_tls_channel_id SSL_get_tls_channel_id
 #define SSL_need_tmp_RSA SSL_need_tmp_RSA
 #define SSL_num_renegotiations SSL_num_renegotiations
 #define SSL_session_reused SSL_session_reused
 #define SSL_set0_chain SSL_set0_chain
 #define SSL_set1_chain SSL_set1_chain
 #define SSL_set1_curves SSL_set1_curves
-#define SSL_set1_tls_channel_id SSL_set1_tls_channel_id
 #define SSL_set_max_cert_list SSL_set_max_cert_list
 #define SSL_set_max_send_fragment SSL_set_max_send_fragment
 #define SSL_set_mode SSL_set_mode
@@ -4286,6 +4425,19 @@
 
 #if defined(__cplusplus)
 } /* extern C */
+
+extern "C++" {
+
+namespace bssl {
+
+BORINGSSL_MAKE_DELETER(SSL, SSL_free)
+BORINGSSL_MAKE_DELETER(SSL_CTX, SSL_CTX_free)
+BORINGSSL_MAKE_DELETER(SSL_SESSION, SSL_SESSION_free)
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #define SSL_R_APP_DATA_IN_HANDSHAKE 100
@@ -4351,7 +4503,6 @@
 #define SSL_R_INVALID_SSL_SESSION 160
 #define SSL_R_INVALID_TICKET_KEYS_LENGTH 161
 #define SSL_R_LENGTH_MISMATCH 162
-#define SSL_R_LIBRARY_HAS_NO_CIPHERS 163
 #define SSL_R_MISSING_EXTENSION 164
 #define SSL_R_MISSING_RSA_CERTIFICATE 165
 #define SSL_R_MISSING_TMP_DH_KEY 166
@@ -4438,6 +4589,36 @@
 #define SSL_R_WRONG_VERSION_NUMBER 247
 #define SSL_R_X509_LIB 248
 #define SSL_R_X509_VERIFICATION_SETUP_PROBLEMS 249
+#define SSL_R_SHUTDOWN_WHILE_IN_INIT 250
+#define SSL_R_INVALID_OUTER_RECORD_TYPE 251
+#define SSL_R_UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY 252
+#define SSL_R_NO_COMMON_SIGNATURE_ALGORITHMS 253
+#define SSL_R_DOWNGRADE_DETECTED 254
+#define SSL_R_BUFFERED_MESSAGES_ON_CIPHER_CHANGE 255
+#define SSL_R_INVALID_COMPRESSION_LIST 256
+#define SSL_R_DUPLICATE_EXTENSION 257
+#define SSL_R_MISSING_KEY_SHARE 258
+#define SSL_R_INVALID_ALPN_PROTOCOL 259
+#define SSL_R_TOO_MANY_KEY_UPDATES 260
+#define SSL_R_BLOCK_CIPHER_PAD_IS_WRONG 261
+#define SSL_R_NO_CIPHERS_SPECIFIED 262
+#define SSL_R_RENEGOTIATION_EMS_MISMATCH 263
+#define SSL_R_DUPLICATE_KEY_SHARE 264
+#define SSL_R_NO_GROUPS_SPECIFIED 265
+#define SSL_R_NO_SHARED_GROUP 266
+#define SSL_R_PRE_SHARED_KEY_MUST_BE_LAST 267
+#define SSL_R_OLD_SESSION_PRF_HASH_MISMATCH 268
+#define SSL_R_INVALID_SCT_LIST 269
+#define SSL_R_TOO_MUCH_SKIPPED_EARLY_DATA 270
+#define SSL_R_PSK_IDENTITY_BINDER_COUNT_MISMATCH 271
+#define SSL_R_CANNOT_PARSE_LEAF_CERT 272
+#define SSL_R_SERVER_CERT_CHANGED 273
+#define SSL_R_CERTIFICATE_AND_PRIVATE_KEY_MISMATCH 274
+#define SSL_R_CANNOT_HAVE_BOTH_PRIVKEY_AND_METHOD 275
+#define SSL_R_TICKET_ENCRYPTION_FAILED 276
+#define SSL_R_ALPN_MISMATCH_ON_EARLY_DATA 277
+#define SSL_R_WRONG_VERSION_ON_EARLY_DATA 278
+#define SSL_R_CHANNEL_ID_ON_EARLY_DATA 279
 #define SSL_R_SSLV3_ALERT_CLOSE_NOTIFY 1000
 #define SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE 1010
 #define SSL_R_SSLV3_ALERT_BAD_RECORD_MAC 1020
@@ -4468,5 +4649,7 @@
 #define SSL_R_TLSV1_UNRECOGNIZED_NAME 1112
 #define SSL_R_TLSV1_BAD_CERTIFICATE_STATUS_RESPONSE 1113
 #define SSL_R_TLSV1_BAD_CERTIFICATE_HASH_VALUE 1114
+#define SSL_R_TLSV1_UNKNOWN_PSK_IDENTITY 1115
+#define SSL_R_TLSV1_CERTIFICATE_REQUIRED 1116
 
 #endif /* OPENSSL_HEADER_SSL_H */
diff --git a/src/include/openssl/ssl3.h b/src/include/openssl/ssl3.h
index 957b740..fcaeb2d 100644
--- a/src/include/openssl/ssl3.h
+++ b/src/include/openssl/ssl3.h
@@ -307,119 +307,92 @@
 #define SSL3_ST_CW_FLUSH (0x100 | SSL_ST_CONNECT)
 #define SSL3_ST_FALSE_START (0x101 | SSL_ST_CONNECT)
 #define SSL3_ST_VERIFY_SERVER_CERT (0x102 | SSL_ST_CONNECT)
+#define SSL3_ST_FINISH_CLIENT_HANDSHAKE (0x103 | SSL_ST_CONNECT)
 /* write to server */
 #define SSL3_ST_CW_CLNT_HELLO_A (0x110 | SSL_ST_CONNECT)
-#define SSL3_ST_CW_CLNT_HELLO_B (0x111 | SSL_ST_CONNECT)
 /* read from server */
 #define SSL3_ST_CR_SRVR_HELLO_A (0x120 | SSL_ST_CONNECT)
-#define SSL3_ST_CR_SRVR_HELLO_B (0x121 | SSL_ST_CONNECT)
 #define DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A (0x126 | SSL_ST_CONNECT)
-#define DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B (0x127 | SSL_ST_CONNECT)
 #define SSL3_ST_CR_CERT_A (0x130 | SSL_ST_CONNECT)
-#define SSL3_ST_CR_CERT_B (0x131 | SSL_ST_CONNECT)
 #define SSL3_ST_CR_KEY_EXCH_A (0x140 | SSL_ST_CONNECT)
 #define SSL3_ST_CR_KEY_EXCH_B (0x141 | SSL_ST_CONNECT)
 #define SSL3_ST_CR_CERT_REQ_A (0x150 | SSL_ST_CONNECT)
-#define SSL3_ST_CR_CERT_REQ_B (0x151 | SSL_ST_CONNECT)
 #define SSL3_ST_CR_SRVR_DONE_A (0x160 | SSL_ST_CONNECT)
-#define SSL3_ST_CR_SRVR_DONE_B (0x161 | SSL_ST_CONNECT)
 /* write to server */
 #define SSL3_ST_CW_CERT_A (0x170 | SSL_ST_CONNECT)
-#define SSL3_ST_CW_CERT_B (0x171 | SSL_ST_CONNECT)
-#define SSL3_ST_CW_CERT_C (0x172 | SSL_ST_CONNECT)
-#define SSL3_ST_CW_CERT_D (0x173 | SSL_ST_CONNECT)
 #define SSL3_ST_CW_KEY_EXCH_A (0x180 | SSL_ST_CONNECT)
-#define SSL3_ST_CW_KEY_EXCH_B (0x181 | SSL_ST_CONNECT)
 #define SSL3_ST_CW_CERT_VRFY_A (0x190 | SSL_ST_CONNECT)
 #define SSL3_ST_CW_CERT_VRFY_B (0x191 | SSL_ST_CONNECT)
-#define SSL3_ST_CW_CERT_VRFY_C (0x192 | SSL_ST_CONNECT)
-#define SSL3_ST_CW_CHANGE_A (0x1A0 | SSL_ST_CONNECT)
-#define SSL3_ST_CW_CHANGE_B (0x1A1 | SSL_ST_CONNECT)
+#define SSL3_ST_CW_CHANGE (0x1A0 | SSL_ST_CONNECT)
 #define SSL3_ST_CW_NEXT_PROTO_A (0x200 | SSL_ST_CONNECT)
-#define SSL3_ST_CW_NEXT_PROTO_B (0x201 | SSL_ST_CONNECT)
 #define SSL3_ST_CW_CHANNEL_ID_A (0x220 | SSL_ST_CONNECT)
-#define SSL3_ST_CW_CHANNEL_ID_B (0x221 | SSL_ST_CONNECT)
 #define SSL3_ST_CW_FINISHED_A (0x1B0 | SSL_ST_CONNECT)
-#define SSL3_ST_CW_FINISHED_B (0x1B1 | SSL_ST_CONNECT)
 /* read from server */
 #define SSL3_ST_CR_CHANGE (0x1C0 | SSL_ST_CONNECT)
 #define SSL3_ST_CR_FINISHED_A (0x1D0 | SSL_ST_CONNECT)
-#define SSL3_ST_CR_FINISHED_B (0x1D1 | SSL_ST_CONNECT)
 #define SSL3_ST_CR_SESSION_TICKET_A (0x1E0 | SSL_ST_CONNECT)
-#define SSL3_ST_CR_SESSION_TICKET_B (0x1E1 | SSL_ST_CONNECT)
 #define SSL3_ST_CR_CERT_STATUS_A (0x1F0 | SSL_ST_CONNECT)
-#define SSL3_ST_CR_CERT_STATUS_B (0x1F1 | SSL_ST_CONNECT)
+
+/* SSL3_ST_CR_SRVR_HELLO_B is a legacy alias for |SSL3_ST_CR_SRVR_HELLO_A| used
+ * by some consumers which check |SSL_state|. */
+#define SSL3_ST_CR_SRVR_HELLO_B SSL3_ST_CR_SRVR_HELLO_A
 
 /* server */
 /* extra state */
 #define SSL3_ST_SW_FLUSH (0x100 | SSL_ST_ACCEPT)
 /* read from client */
-#define SSL3_ST_SR_INITIAL_BYTES (0x240 | SSL_ST_ACCEPT)
-#define SSL3_ST_SR_V2_CLIENT_HELLO (0x241 | SSL_ST_ACCEPT)
 #define SSL3_ST_SR_CLNT_HELLO_A (0x110 | SSL_ST_ACCEPT)
 #define SSL3_ST_SR_CLNT_HELLO_B (0x111 | SSL_ST_ACCEPT)
 #define SSL3_ST_SR_CLNT_HELLO_C (0x112 | SSL_ST_ACCEPT)
-#define SSL3_ST_SR_CLNT_HELLO_D (0x115 | SSL_ST_ACCEPT)
+#define SSL3_ST_SR_CLNT_HELLO_D (0x113 | SSL_ST_ACCEPT)
 /* write to client */
-#define SSL3_ST_SW_HELLO_REQ_A (0x120 | SSL_ST_ACCEPT)
-#define SSL3_ST_SW_HELLO_REQ_B (0x121 | SSL_ST_ACCEPT)
-#define SSL3_ST_SW_HELLO_REQ_C (0x122 | SSL_ST_ACCEPT)
 #define SSL3_ST_SW_SRVR_HELLO_A (0x130 | SSL_ST_ACCEPT)
-#define SSL3_ST_SW_SRVR_HELLO_B (0x131 | SSL_ST_ACCEPT)
 #define SSL3_ST_SW_CERT_A (0x140 | SSL_ST_ACCEPT)
-#define SSL3_ST_SW_CERT_B (0x141 | SSL_ST_ACCEPT)
 #define SSL3_ST_SW_KEY_EXCH_A (0x150 | SSL_ST_ACCEPT)
 #define SSL3_ST_SW_KEY_EXCH_B (0x151 | SSL_ST_ACCEPT)
-#define SSL3_ST_SW_KEY_EXCH_C (0x152 | SSL_ST_ACCEPT)
 #define SSL3_ST_SW_CERT_REQ_A (0x160 | SSL_ST_ACCEPT)
-#define SSL3_ST_SW_CERT_REQ_B (0x161 | SSL_ST_ACCEPT)
 #define SSL3_ST_SW_SRVR_DONE_A (0x170 | SSL_ST_ACCEPT)
-#define SSL3_ST_SW_SRVR_DONE_B (0x171 | SSL_ST_ACCEPT)
 /* read from client */
 #define SSL3_ST_SR_CERT_A (0x180 | SSL_ST_ACCEPT)
-#define SSL3_ST_SR_CERT_B (0x181 | SSL_ST_ACCEPT)
 #define SSL3_ST_SR_KEY_EXCH_A (0x190 | SSL_ST_ACCEPT)
 #define SSL3_ST_SR_KEY_EXCH_B (0x191 | SSL_ST_ACCEPT)
-#define SSL3_ST_SR_KEY_EXCH_C (0x192 | SSL_ST_ACCEPT)
 #define SSL3_ST_SR_CERT_VRFY_A (0x1A0 | SSL_ST_ACCEPT)
-#define SSL3_ST_SR_CERT_VRFY_B (0x1A1 | SSL_ST_ACCEPT)
 #define SSL3_ST_SR_CHANGE (0x1B0 | SSL_ST_ACCEPT)
 #define SSL3_ST_SR_NEXT_PROTO_A (0x210 | SSL_ST_ACCEPT)
-#define SSL3_ST_SR_NEXT_PROTO_B (0x211 | SSL_ST_ACCEPT)
 #define SSL3_ST_SR_CHANNEL_ID_A (0x230 | SSL_ST_ACCEPT)
-#define SSL3_ST_SR_CHANNEL_ID_B (0x231 | SSL_ST_ACCEPT)
 #define SSL3_ST_SR_FINISHED_A (0x1C0 | SSL_ST_ACCEPT)
-#define SSL3_ST_SR_FINISHED_B (0x1C1 | SSL_ST_ACCEPT)
 
 /* write to client */
-#define SSL3_ST_SW_CHANGE_A (0x1D0 | SSL_ST_ACCEPT)
-#define SSL3_ST_SW_CHANGE_B (0x1D1 | SSL_ST_ACCEPT)
+#define SSL3_ST_SW_CHANGE (0x1D0 | SSL_ST_ACCEPT)
 #define SSL3_ST_SW_FINISHED_A (0x1E0 | SSL_ST_ACCEPT)
-#define SSL3_ST_SW_FINISHED_B (0x1E1 | SSL_ST_ACCEPT)
 #define SSL3_ST_SW_SESSION_TICKET_A (0x1F0 | SSL_ST_ACCEPT)
-#define SSL3_ST_SW_SESSION_TICKET_B (0x1F1 | SSL_ST_ACCEPT)
 #define SSL3_ST_SW_CERT_STATUS_A (0x200 | SSL_ST_ACCEPT)
-#define SSL3_ST_SW_CERT_STATUS_B (0x201 | SSL_ST_ACCEPT)
-#define SSL3_ST_SW_SUPPLEMENTAL_DATA_A (0x220 | SSL_ST_ACCEPT)
-#define SSL3_ST_SW_SUPPLEMENTAL_DATA_B (0x221 | SSL_ST_ACCEPT)
 
 #define SSL3_MT_HELLO_REQUEST 0
 #define SSL3_MT_CLIENT_HELLO 1
 #define SSL3_MT_SERVER_HELLO 2
-#define SSL3_MT_NEWSESSION_TICKET 4
+#define SSL3_MT_NEW_SESSION_TICKET 4
+#define SSL3_MT_HELLO_RETRY_REQUEST 6
+#define SSL3_MT_ENCRYPTED_EXTENSIONS 8
 #define SSL3_MT_CERTIFICATE 11
 #define SSL3_MT_SERVER_KEY_EXCHANGE 12
 #define SSL3_MT_CERTIFICATE_REQUEST 13
-#define SSL3_MT_SERVER_DONE 14
+#define SSL3_MT_SERVER_HELLO_DONE 14
 #define SSL3_MT_CERTIFICATE_VERIFY 15
 #define SSL3_MT_CLIENT_KEY_EXCHANGE 16
 #define SSL3_MT_FINISHED 20
 #define SSL3_MT_CERTIFICATE_STATUS 22
 #define SSL3_MT_SUPPLEMENTAL_DATA 23
+#define SSL3_MT_KEY_UPDATE 24
 #define SSL3_MT_NEXT_PROTO 67
-#define SSL3_MT_ENCRYPTED_EXTENSIONS 203
+#define SSL3_MT_CHANNEL_ID 203
 #define DTLS1_MT_HELLO_VERIFY_REQUEST 3
 
+/* The following are legacy aliases for consumers which use
+ * |SSL_CTX_set_msg_callback|. */
+#define SSL3_MT_SERVER_DONE SSL3_MT_SERVER_HELLO_DONE
+#define SSL3_MT_NEWSESSION_TICKET SSL3_MT_NEW_SESSION_TICKET
+
 
 #define SSL3_MT_CCS 1
 
diff --git a/src/include/openssl/stack.h b/src/include/openssl/stack.h
index 16b9f4f..c0cd0f6 100644
--- a/src/include/openssl/stack.h
+++ b/src/include/openssl/stack.h
@@ -100,7 +100,7 @@
   void **data;
   /* sorted is non-zero if the values pointed to by |data| are in ascending
    * order, based on |comp|. */
-  size_t sorted;
+  int sorted;
   /* num_alloc contains the number of pointers allocated in the buffer pointed
    * to by |data|, which may be larger than |num|. */
   size_t num_alloc;
@@ -129,6 +129,7 @@
  * STACK_OF:BY_DIR_ENTRY
  * STACK_OF:BY_DIR_HASH
  * STACK_OF:CONF_VALUE
+ * STACK_OF:CRYPTO_BUFFER
  * STACK_OF:CRYPTO_EX_DATA_FUNCS
  * STACK_OF:DIST_POINT
  * STACK_OF:GENERAL_NAME
@@ -180,14 +181,12 @@
 typedef char *OPENSSL_STRING;
 
 DEFINE_SPECIAL_STACK_OF(OPENSSL_STRING, char)
-DEFINE_SPECIAL_STACK_OF(OPENSSL_BLOCK, uint8_t)
 
 /* The make_macros.sh script in this directory parses the following lines and
  * generates the stack_macros.h file that contains macros for the following
  * types of stacks:
  *
- * SPECIAL_STACK_OF:OPENSSL_STRING
- * SPECIAL_STACK_OF:OPENSSL_BLOCK */
+ * SPECIAL_STACK_OF:OPENSSL_STRING */
 
 #define IN_STACK_H
 #include <openssl/stack_macros.h>
diff --git a/src/include/openssl/stack_macros.h b/src/include/openssl/stack_macros.h
index 809424c..a5f36fb 100644
--- a/src/include/openssl/stack_macros.h
+++ b/src/include/openssl/stack_macros.h
@@ -27,14 +27,15 @@
   ((STACK_OF(ACCESS_DESCRIPTION) *)sk_new_null())
 
 #define sk_ACCESS_DESCRIPTION_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(ACCESS_DESCRIPTION) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(ACCESS_DESCRIPTION) *, sk))
 
 #define sk_ACCESS_DESCRIPTION_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(ACCESS_DESCRIPTION) *, sk));
 
-#define sk_ACCESS_DESCRIPTION_value(sk, i) \
-  ((ACCESS_DESCRIPTION *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(ACCESS_DESCRIPTION) *, sk), (i)))
+#define sk_ACCESS_DESCRIPTION_value(sk, i)                                    \
+  ((ACCESS_DESCRIPTION *)sk_value(                                            \
+      CHECKED_CAST(const _STACK *, const STACK_OF(ACCESS_DESCRIPTION) *, sk), \
+      (i)))
 
 #define sk_ACCESS_DESCRIPTION_set(sk, i, p)                            \
   ((ACCESS_DESCRIPTION *)sk_set(                                       \
@@ -80,13 +81,14 @@
 
 #define sk_ACCESS_DESCRIPTION_dup(sk)      \
   ((STACK_OF(ACCESS_DESCRIPTION) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(ACCESS_DESCRIPTION) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(ACCESS_DESCRIPTION) *, sk)))
 
 #define sk_ACCESS_DESCRIPTION_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(ACCESS_DESCRIPTION) *, sk))
 
 #define sk_ACCESS_DESCRIPTION_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(ACCESS_DESCRIPTION) *, sk))
+  sk_is_sorted(                             \
+      CHECKED_CAST(const _STACK *, const STACK_OF(ACCESS_DESCRIPTION) *, sk))
 
 #define sk_ACCESS_DESCRIPTION_set_cmp_func(sk, comp)                           \
   ((int (*)(const ACCESS_DESCRIPTION **a, const ACCESS_DESCRIPTION **b))       \
@@ -113,14 +115,15 @@
 #define sk_ASN1_ADB_TABLE_new_null() ((STACK_OF(ASN1_ADB_TABLE) *)sk_new_null())
 
 #define sk_ASN1_ADB_TABLE_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(ASN1_ADB_TABLE) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_ADB_TABLE) *, sk))
 
 #define sk_ASN1_ADB_TABLE_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(ASN1_ADB_TABLE) *, sk));
 
-#define sk_ASN1_ADB_TABLE_value(sk, i) \
-  ((ASN1_ADB_TABLE *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(ASN1_ADB_TABLE) *, sk), (i)))
+#define sk_ASN1_ADB_TABLE_value(sk, i)                                    \
+  ((ASN1_ADB_TABLE *)sk_value(                                            \
+      CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_ADB_TABLE) *, sk), \
+      (i)))
 
 #define sk_ASN1_ADB_TABLE_set(sk, i, p)                            \
   ((ASN1_ADB_TABLE *)sk_set(                                       \
@@ -166,13 +169,14 @@
 
 #define sk_ASN1_ADB_TABLE_dup(sk)      \
   ((STACK_OF(ASN1_ADB_TABLE) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(ASN1_ADB_TABLE) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_ADB_TABLE) *, sk)))
 
 #define sk_ASN1_ADB_TABLE_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(ASN1_ADB_TABLE) *, sk))
 
 #define sk_ASN1_ADB_TABLE_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(ASN1_ADB_TABLE) *, sk))
+  sk_is_sorted(                         \
+      CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_ADB_TABLE) *, sk))
 
 #define sk_ASN1_ADB_TABLE_set_cmp_func(sk, comp)                           \
   ((int (*)(const ASN1_ADB_TABLE **a, const ASN1_ADB_TABLE **b))           \
@@ -200,14 +204,15 @@
   ((STACK_OF(ASN1_GENERALSTRING) *)sk_new_null())
 
 #define sk_ASN1_GENERALSTRING_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(ASN1_GENERALSTRING) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_GENERALSTRING) *, sk))
 
 #define sk_ASN1_GENERALSTRING_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(ASN1_GENERALSTRING) *, sk));
 
-#define sk_ASN1_GENERALSTRING_value(sk, i) \
-  ((ASN1_GENERALSTRING *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(ASN1_GENERALSTRING) *, sk), (i)))
+#define sk_ASN1_GENERALSTRING_value(sk, i)                                    \
+  ((ASN1_GENERALSTRING *)sk_value(                                            \
+      CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_GENERALSTRING) *, sk), \
+      (i)))
 
 #define sk_ASN1_GENERALSTRING_set(sk, i, p)                            \
   ((ASN1_GENERALSTRING *)sk_set(                                       \
@@ -253,13 +258,14 @@
 
 #define sk_ASN1_GENERALSTRING_dup(sk)      \
   ((STACK_OF(ASN1_GENERALSTRING) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(ASN1_GENERALSTRING) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_GENERALSTRING) *, sk)))
 
 #define sk_ASN1_GENERALSTRING_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(ASN1_GENERALSTRING) *, sk))
 
 #define sk_ASN1_GENERALSTRING_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(ASN1_GENERALSTRING) *, sk))
+  sk_is_sorted(                             \
+      CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_GENERALSTRING) *, sk))
 
 #define sk_ASN1_GENERALSTRING_set_cmp_func(sk, comp)                           \
   ((int (*)(const ASN1_GENERALSTRING **a, const ASN1_GENERALSTRING **b))       \
@@ -286,14 +292,14 @@
 #define sk_ASN1_INTEGER_new_null() ((STACK_OF(ASN1_INTEGER) *)sk_new_null())
 
 #define sk_ASN1_INTEGER_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(ASN1_INTEGER) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_INTEGER) *, sk))
 
 #define sk_ASN1_INTEGER_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(ASN1_INTEGER) *, sk));
 
 #define sk_ASN1_INTEGER_value(sk, i) \
   ((ASN1_INTEGER *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(ASN1_INTEGER) *, sk), (i)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_INTEGER) *, sk), (i)))
 
 #define sk_ASN1_INTEGER_set(sk, i, p)                            \
   ((ASN1_INTEGER *)sk_set(                                       \
@@ -338,13 +344,13 @@
 
 #define sk_ASN1_INTEGER_dup(sk)      \
   ((STACK_OF(ASN1_INTEGER) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(ASN1_INTEGER) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_INTEGER) *, sk)))
 
 #define sk_ASN1_INTEGER_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(ASN1_INTEGER) *, sk))
 
 #define sk_ASN1_INTEGER_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(ASN1_INTEGER) *, sk))
+  sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_INTEGER) *, sk))
 
 #define sk_ASN1_INTEGER_set_cmp_func(sk, comp)                               \
   ((int (*)(const ASN1_INTEGER **a, const ASN1_INTEGER **b))sk_set_cmp_func( \
@@ -369,14 +375,14 @@
 #define sk_ASN1_OBJECT_new_null() ((STACK_OF(ASN1_OBJECT) *)sk_new_null())
 
 #define sk_ASN1_OBJECT_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(ASN1_OBJECT) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_OBJECT) *, sk))
 
 #define sk_ASN1_OBJECT_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(ASN1_OBJECT) *, sk));
 
 #define sk_ASN1_OBJECT_value(sk, i) \
   ((ASN1_OBJECT *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(ASN1_OBJECT) *, sk), (i)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_OBJECT) *, sk), (i)))
 
 #define sk_ASN1_OBJECT_set(sk, i, p)                                          \
   ((ASN1_OBJECT *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(ASN1_OBJECT) *, sk), \
@@ -419,13 +425,13 @@
 
 #define sk_ASN1_OBJECT_dup(sk)      \
   ((STACK_OF(ASN1_OBJECT) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(ASN1_OBJECT) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_OBJECT) *, sk)))
 
 #define sk_ASN1_OBJECT_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(ASN1_OBJECT) *, sk))
 
 #define sk_ASN1_OBJECT_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(ASN1_OBJECT) *, sk))
+  sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_OBJECT) *, sk))
 
 #define sk_ASN1_OBJECT_set_cmp_func(sk, comp)                              \
   ((int (*)(const ASN1_OBJECT **a, const ASN1_OBJECT **b))sk_set_cmp_func( \
@@ -452,14 +458,15 @@
   ((STACK_OF(ASN1_STRING_TABLE) *)sk_new_null())
 
 #define sk_ASN1_STRING_TABLE_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(ASN1_STRING_TABLE) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_STRING_TABLE) *, sk))
 
 #define sk_ASN1_STRING_TABLE_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(ASN1_STRING_TABLE) *, sk));
 
-#define sk_ASN1_STRING_TABLE_value(sk, i) \
-  ((ASN1_STRING_TABLE *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(ASN1_STRING_TABLE) *, sk), (i)))
+#define sk_ASN1_STRING_TABLE_value(sk, i)                                    \
+  ((ASN1_STRING_TABLE *)sk_value(                                            \
+      CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_STRING_TABLE) *, sk), \
+      (i)))
 
 #define sk_ASN1_STRING_TABLE_set(sk, i, p)                            \
   ((ASN1_STRING_TABLE *)sk_set(                                       \
@@ -505,13 +512,14 @@
 
 #define sk_ASN1_STRING_TABLE_dup(sk)      \
   ((STACK_OF(ASN1_STRING_TABLE) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(ASN1_STRING_TABLE) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_STRING_TABLE) *, sk)))
 
 #define sk_ASN1_STRING_TABLE_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(ASN1_STRING_TABLE) *, sk))
 
 #define sk_ASN1_STRING_TABLE_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(ASN1_STRING_TABLE) *, sk))
+  sk_is_sorted(                            \
+      CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_STRING_TABLE) *, sk))
 
 #define sk_ASN1_STRING_TABLE_set_cmp_func(sk, comp)                           \
   ((int (*)(const ASN1_STRING_TABLE **a, const ASN1_STRING_TABLE **b))        \
@@ -538,14 +546,14 @@
 #define sk_ASN1_TYPE_new_null() ((STACK_OF(ASN1_TYPE) *)sk_new_null())
 
 #define sk_ASN1_TYPE_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(ASN1_TYPE) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_TYPE) *, sk))
 
 #define sk_ASN1_TYPE_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(ASN1_TYPE) *, sk));
 
 #define sk_ASN1_TYPE_value(sk, i) \
   ((ASN1_TYPE *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(ASN1_TYPE) *, sk), (i)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_TYPE) *, sk), (i)))
 
 #define sk_ASN1_TYPE_set(sk, i, p)                                             \
   ((ASN1_TYPE *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(ASN1_TYPE) *, sk), (i), \
@@ -588,13 +596,13 @@
 
 #define sk_ASN1_TYPE_dup(sk)      \
   ((STACK_OF(ASN1_TYPE) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(ASN1_TYPE) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_TYPE) *, sk)))
 
 #define sk_ASN1_TYPE_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(ASN1_TYPE) *, sk))
 
 #define sk_ASN1_TYPE_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(ASN1_TYPE) *, sk))
+  sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_TYPE) *, sk))
 
 #define sk_ASN1_TYPE_set_cmp_func(sk, comp)                            \
   ((int (*)(const ASN1_TYPE **a, const ASN1_TYPE **b))sk_set_cmp_func( \
@@ -617,14 +625,14 @@
 #define sk_ASN1_VALUE_new_null() ((STACK_OF(ASN1_VALUE) *)sk_new_null())
 
 #define sk_ASN1_VALUE_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(ASN1_VALUE) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_VALUE) *, sk))
 
 #define sk_ASN1_VALUE_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(ASN1_VALUE) *, sk));
 
 #define sk_ASN1_VALUE_value(sk, i) \
   ((ASN1_VALUE *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(ASN1_VALUE) *, sk), (i)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_VALUE) *, sk), (i)))
 
 #define sk_ASN1_VALUE_set(sk, i, p)                                         \
   ((ASN1_VALUE *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(ASN1_VALUE) *, sk), \
@@ -667,13 +675,13 @@
 
 #define sk_ASN1_VALUE_dup(sk)      \
   ((STACK_OF(ASN1_VALUE) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(ASN1_VALUE) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_VALUE) *, sk)))
 
 #define sk_ASN1_VALUE_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(ASN1_VALUE) *, sk))
 
 #define sk_ASN1_VALUE_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(ASN1_VALUE) *, sk))
+  sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(ASN1_VALUE) *, sk))
 
 #define sk_ASN1_VALUE_set_cmp_func(sk, comp)                             \
   ((int (*)(const ASN1_VALUE **a, const ASN1_VALUE **b))sk_set_cmp_func( \
@@ -696,12 +704,14 @@
 
 #define sk_BIO_new_null() ((STACK_OF(BIO) *)sk_new_null())
 
-#define sk_BIO_num(sk) sk_num(CHECKED_CAST(_STACK *, STACK_OF(BIO) *, sk))
+#define sk_BIO_num(sk) \
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(BIO) *, sk))
 
 #define sk_BIO_zero(sk) sk_zero(CHECKED_CAST(_STACK *, STACK_OF(BIO) *, sk));
 
-#define sk_BIO_value(sk, i) \
-  ((BIO *)sk_value(CHECKED_CAST(_STACK *, const STACK_OF(BIO) *, sk), (i)))
+#define sk_BIO_value(sk, i)                                                 \
+  ((BIO *)sk_value(CHECKED_CAST(const _STACK *, const STACK_OF(BIO) *, sk), \
+                   (i)))
 
 #define sk_BIO_set(sk, i, p)                                       \
   ((BIO *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(BIO) *, sk), (i), \
@@ -738,13 +748,14 @@
 #define sk_BIO_pop(sk) \
   ((BIO *)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(BIO) *, sk)))
 
-#define sk_BIO_dup(sk) \
-  ((STACK_OF(BIO) *)sk_dup(CHECKED_CAST(_STACK *, const STACK_OF(BIO) *, sk)))
+#define sk_BIO_dup(sk)      \
+  ((STACK_OF(BIO) *)sk_dup( \
+      CHECKED_CAST(const _STACK *, const STACK_OF(BIO) *, sk)))
 
 #define sk_BIO_sort(sk) sk_sort(CHECKED_CAST(_STACK *, STACK_OF(BIO) *, sk))
 
 #define sk_BIO_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(BIO) *, sk))
+  sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(BIO) *, sk))
 
 #define sk_BIO_set_cmp_func(sk, comp)                                     \
   ((int (*)(const BIO **a, const BIO **b))sk_set_cmp_func(                \
@@ -767,14 +778,14 @@
 #define sk_BY_DIR_ENTRY_new_null() ((STACK_OF(BY_DIR_ENTRY) *)sk_new_null())
 
 #define sk_BY_DIR_ENTRY_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_ENTRY) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(BY_DIR_ENTRY) *, sk))
 
 #define sk_BY_DIR_ENTRY_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_ENTRY) *, sk));
 
 #define sk_BY_DIR_ENTRY_value(sk, i) \
   ((BY_DIR_ENTRY *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(BY_DIR_ENTRY) *, sk), (i)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(BY_DIR_ENTRY) *, sk), (i)))
 
 #define sk_BY_DIR_ENTRY_set(sk, i, p)                            \
   ((BY_DIR_ENTRY *)sk_set(                                       \
@@ -819,13 +830,13 @@
 
 #define sk_BY_DIR_ENTRY_dup(sk)      \
   ((STACK_OF(BY_DIR_ENTRY) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(BY_DIR_ENTRY) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(BY_DIR_ENTRY) *, sk)))
 
 #define sk_BY_DIR_ENTRY_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_ENTRY) *, sk))
 
 #define sk_BY_DIR_ENTRY_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(BY_DIR_ENTRY) *, sk))
+  sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(BY_DIR_ENTRY) *, sk))
 
 #define sk_BY_DIR_ENTRY_set_cmp_func(sk, comp)                               \
   ((int (*)(const BY_DIR_ENTRY **a, const BY_DIR_ENTRY **b))sk_set_cmp_func( \
@@ -850,14 +861,14 @@
 #define sk_BY_DIR_HASH_new_null() ((STACK_OF(BY_DIR_HASH) *)sk_new_null())
 
 #define sk_BY_DIR_HASH_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_HASH) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(BY_DIR_HASH) *, sk))
 
 #define sk_BY_DIR_HASH_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_HASH) *, sk));
 
 #define sk_BY_DIR_HASH_value(sk, i) \
   ((BY_DIR_HASH *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(BY_DIR_HASH) *, sk), (i)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(BY_DIR_HASH) *, sk), (i)))
 
 #define sk_BY_DIR_HASH_set(sk, i, p)                                          \
   ((BY_DIR_HASH *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_HASH) *, sk), \
@@ -900,13 +911,13 @@
 
 #define sk_BY_DIR_HASH_dup(sk)      \
   ((STACK_OF(BY_DIR_HASH) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(BY_DIR_HASH) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(BY_DIR_HASH) *, sk)))
 
 #define sk_BY_DIR_HASH_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(BY_DIR_HASH) *, sk))
 
 #define sk_BY_DIR_HASH_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(BY_DIR_HASH) *, sk))
+  sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(BY_DIR_HASH) *, sk))
 
 #define sk_BY_DIR_HASH_set_cmp_func(sk, comp)                              \
   ((int (*)(const BY_DIR_HASH **a, const BY_DIR_HASH **b))sk_set_cmp_func( \
@@ -931,14 +942,14 @@
 #define sk_CONF_VALUE_new_null() ((STACK_OF(CONF_VALUE) *)sk_new_null())
 
 #define sk_CONF_VALUE_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(CONF_VALUE) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(CONF_VALUE) *, sk))
 
 #define sk_CONF_VALUE_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(CONF_VALUE) *, sk));
 
 #define sk_CONF_VALUE_value(sk, i) \
   ((CONF_VALUE *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(CONF_VALUE) *, sk), (i)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(CONF_VALUE) *, sk), (i)))
 
 #define sk_CONF_VALUE_set(sk, i, p)                                         \
   ((CONF_VALUE *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(CONF_VALUE) *, sk), \
@@ -981,13 +992,13 @@
 
 #define sk_CONF_VALUE_dup(sk)      \
   ((STACK_OF(CONF_VALUE) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(CONF_VALUE) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(CONF_VALUE) *, sk)))
 
 #define sk_CONF_VALUE_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(CONF_VALUE) *, sk))
 
 #define sk_CONF_VALUE_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(CONF_VALUE) *, sk))
+  sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(CONF_VALUE) *, sk))
 
 #define sk_CONF_VALUE_set_cmp_func(sk, comp)                             \
   ((int (*)(const CONF_VALUE **a, const CONF_VALUE **b))sk_set_cmp_func( \
@@ -1003,6 +1014,91 @@
                    copy_func),                                        \
       CHECKED_CAST(void (*)(void *), void (*)(CONF_VALUE *), free_func)))
 
+/* CRYPTO_BUFFER */
+#define sk_CRYPTO_BUFFER_new(comp)                 \
+  ((STACK_OF(CRYPTO_BUFFER) *)sk_new(CHECKED_CAST( \
+      stack_cmp_func,                              \
+      int (*)(const CRYPTO_BUFFER **a, const CRYPTO_BUFFER **b), comp)))
+
+#define sk_CRYPTO_BUFFER_new_null() ((STACK_OF(CRYPTO_BUFFER) *)sk_new_null())
+
+#define sk_CRYPTO_BUFFER_num(sk) \
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(CRYPTO_BUFFER) *, sk))
+
+#define sk_CRYPTO_BUFFER_zero(sk) \
+  sk_zero(CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_BUFFER) *, sk));
+
+#define sk_CRYPTO_BUFFER_value(sk, i) \
+  ((CRYPTO_BUFFER *)sk_value(         \
+      CHECKED_CAST(const _STACK *, const STACK_OF(CRYPTO_BUFFER) *, sk), (i)))
+
+#define sk_CRYPTO_BUFFER_set(sk, i, p)                            \
+  ((CRYPTO_BUFFER *)sk_set(                                       \
+      CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_BUFFER) *, sk), (i), \
+      CHECKED_CAST(void *, CRYPTO_BUFFER *, p)))
+
+#define sk_CRYPTO_BUFFER_free(sk) \
+  sk_free(CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_BUFFER) *, sk))
+
+#define sk_CRYPTO_BUFFER_pop_free(sk, free_func)             \
+  sk_pop_free(                                               \
+      CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_BUFFER) *, sk), \
+      CHECKED_CAST(void (*)(void *), void (*)(CRYPTO_BUFFER *), free_func))
+
+#define sk_CRYPTO_BUFFER_insert(sk, p, where)                      \
+  sk_insert(CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_BUFFER) *, sk), \
+            CHECKED_CAST(void *, CRYPTO_BUFFER *, p), (where))
+
+#define sk_CRYPTO_BUFFER_delete(sk, where) \
+  ((CRYPTO_BUFFER *)sk_delete(             \
+      CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_BUFFER) *, sk), (where)))
+
+#define sk_CRYPTO_BUFFER_delete_ptr(sk, p)                   \
+  ((CRYPTO_BUFFER *)sk_delete_ptr(                           \
+      CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_BUFFER) *, sk), \
+      CHECKED_CAST(void *, CRYPTO_BUFFER *, p)))
+
+#define sk_CRYPTO_BUFFER_find(sk, out_index, p)                               \
+  sk_find(CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_BUFFER) *, sk), (out_index), \
+          CHECKED_CAST(void *, CRYPTO_BUFFER *, p))
+
+#define sk_CRYPTO_BUFFER_shift(sk) \
+  ((CRYPTO_BUFFER *)sk_shift(      \
+      CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_BUFFER) *, sk)))
+
+#define sk_CRYPTO_BUFFER_push(sk, p)                             \
+  sk_push(CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_BUFFER) *, sk), \
+          CHECKED_CAST(void *, CRYPTO_BUFFER *, p))
+
+#define sk_CRYPTO_BUFFER_pop(sk) \
+  ((CRYPTO_BUFFER *)sk_pop(      \
+      CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_BUFFER) *, sk)))
+
+#define sk_CRYPTO_BUFFER_dup(sk)      \
+  ((STACK_OF(CRYPTO_BUFFER) *)sk_dup( \
+      CHECKED_CAST(const _STACK *, const STACK_OF(CRYPTO_BUFFER) *, sk)))
+
+#define sk_CRYPTO_BUFFER_sort(sk) \
+  sk_sort(CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_BUFFER) *, sk))
+
+#define sk_CRYPTO_BUFFER_is_sorted(sk) \
+  sk_is_sorted(                        \
+      CHECKED_CAST(const _STACK *, const STACK_OF(CRYPTO_BUFFER) *, sk))
+
+#define sk_CRYPTO_BUFFER_set_cmp_func(sk, comp)                                \
+  ((int (*)(const CRYPTO_BUFFER **a, const CRYPTO_BUFFER **b))sk_set_cmp_func( \
+      CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_BUFFER) *, sk),                   \
+      CHECKED_CAST(stack_cmp_func,                                             \
+                   int (*)(const CRYPTO_BUFFER **a, const CRYPTO_BUFFER **b),  \
+                   comp)))
+
+#define sk_CRYPTO_BUFFER_deep_copy(sk, copy_func, free_func)               \
+  ((STACK_OF(CRYPTO_BUFFER) *)sk_deep_copy(                                \
+      CHECKED_CAST(const _STACK *, const STACK_OF(CRYPTO_BUFFER) *, sk),   \
+      CHECKED_CAST(void *(*)(void *), CRYPTO_BUFFER *(*)(CRYPTO_BUFFER *), \
+                   copy_func),                                             \
+      CHECKED_CAST(void (*)(void *), void (*)(CRYPTO_BUFFER *), free_func)))
+
 /* CRYPTO_EX_DATA_FUNCS */
 #define sk_CRYPTO_EX_DATA_FUNCS_new(comp)                                      \
   ((STACK_OF(CRYPTO_EX_DATA_FUNCS) *)sk_new(CHECKED_CAST(                      \
@@ -1013,15 +1109,17 @@
 #define sk_CRYPTO_EX_DATA_FUNCS_new_null() \
   ((STACK_OF(CRYPTO_EX_DATA_FUNCS) *)sk_new_null())
 
-#define sk_CRYPTO_EX_DATA_FUNCS_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk))
+#define sk_CRYPTO_EX_DATA_FUNCS_num(sk)                                       \
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(CRYPTO_EX_DATA_FUNCS) *, \
+                      sk))
 
 #define sk_CRYPTO_EX_DATA_FUNCS_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk));
 
-#define sk_CRYPTO_EX_DATA_FUNCS_value(sk, i)                              \
-  ((CRYPTO_EX_DATA_FUNCS *)sk_value(                                      \
-      CHECKED_CAST(_STACK *, const STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk), \
+#define sk_CRYPTO_EX_DATA_FUNCS_value(sk, i)                               \
+  ((CRYPTO_EX_DATA_FUNCS *)sk_value(                                       \
+      CHECKED_CAST(const _STACK *, const STACK_OF(CRYPTO_EX_DATA_FUNCS) *, \
+                   sk),                                                    \
       (i)))
 
 #define sk_CRYPTO_EX_DATA_FUNCS_set(sk, i, p)                            \
@@ -1066,16 +1164,16 @@
   ((CRYPTO_EX_DATA_FUNCS *)sk_pop(      \
       CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk)))
 
-#define sk_CRYPTO_EX_DATA_FUNCS_dup(sk)      \
-  ((STACK_OF(CRYPTO_EX_DATA_FUNCS) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk)))
+#define sk_CRYPTO_EX_DATA_FUNCS_dup(sk)                   \
+  ((STACK_OF(CRYPTO_EX_DATA_FUNCS) *)sk_dup(CHECKED_CAST( \
+      const _STACK *, const STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk)))
 
 #define sk_CRYPTO_EX_DATA_FUNCS_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk))
 
 #define sk_CRYPTO_EX_DATA_FUNCS_is_sorted(sk) \
-  sk_is_sorted(                               \
-      CHECKED_CAST(_STACK *, const STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk))
+  sk_is_sorted(CHECKED_CAST(const _STACK *,   \
+                            const STACK_OF(CRYPTO_EX_DATA_FUNCS) *, sk))
 
 #define sk_CRYPTO_EX_DATA_FUNCS_set_cmp_func(sk, comp)                       \
   ((int (*)(const CRYPTO_EX_DATA_FUNCS **a, const CRYPTO_EX_DATA_FUNCS **b)) \
@@ -1105,14 +1203,14 @@
 #define sk_DIST_POINT_new_null() ((STACK_OF(DIST_POINT) *)sk_new_null())
 
 #define sk_DIST_POINT_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(DIST_POINT) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(DIST_POINT) *, sk))
 
 #define sk_DIST_POINT_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(DIST_POINT) *, sk));
 
 #define sk_DIST_POINT_value(sk, i) \
   ((DIST_POINT *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(DIST_POINT) *, sk), (i)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(DIST_POINT) *, sk), (i)))
 
 #define sk_DIST_POINT_set(sk, i, p)                                         \
   ((DIST_POINT *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(DIST_POINT) *, sk), \
@@ -1155,13 +1253,13 @@
 
 #define sk_DIST_POINT_dup(sk)      \
   ((STACK_OF(DIST_POINT) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(DIST_POINT) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(DIST_POINT) *, sk)))
 
 #define sk_DIST_POINT_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(DIST_POINT) *, sk))
 
 #define sk_DIST_POINT_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(DIST_POINT) *, sk))
+  sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(DIST_POINT) *, sk))
 
 #define sk_DIST_POINT_set_cmp_func(sk, comp)                             \
   ((int (*)(const DIST_POINT **a, const DIST_POINT **b))sk_set_cmp_func( \
@@ -1186,14 +1284,14 @@
 #define sk_GENERAL_NAME_new_null() ((STACK_OF(GENERAL_NAME) *)sk_new_null())
 
 #define sk_GENERAL_NAME_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAME) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(GENERAL_NAME) *, sk))
 
 #define sk_GENERAL_NAME_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAME) *, sk));
 
 #define sk_GENERAL_NAME_value(sk, i) \
   ((GENERAL_NAME *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(GENERAL_NAME) *, sk), (i)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(GENERAL_NAME) *, sk), (i)))
 
 #define sk_GENERAL_NAME_set(sk, i, p)                            \
   ((GENERAL_NAME *)sk_set(                                       \
@@ -1238,13 +1336,13 @@
 
 #define sk_GENERAL_NAME_dup(sk)      \
   ((STACK_OF(GENERAL_NAME) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(GENERAL_NAME) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(GENERAL_NAME) *, sk)))
 
 #define sk_GENERAL_NAME_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAME) *, sk))
 
 #define sk_GENERAL_NAME_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(GENERAL_NAME) *, sk))
+  sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(GENERAL_NAME) *, sk))
 
 #define sk_GENERAL_NAME_set_cmp_func(sk, comp)                               \
   ((int (*)(const GENERAL_NAME **a, const GENERAL_NAME **b))sk_set_cmp_func( \
@@ -1269,14 +1367,14 @@
 #define sk_GENERAL_NAMES_new_null() ((STACK_OF(GENERAL_NAMES) *)sk_new_null())
 
 #define sk_GENERAL_NAMES_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAMES) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(GENERAL_NAMES) *, sk))
 
 #define sk_GENERAL_NAMES_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAMES) *, sk));
 
 #define sk_GENERAL_NAMES_value(sk, i) \
   ((GENERAL_NAMES *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(GENERAL_NAMES) *, sk), (i)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(GENERAL_NAMES) *, sk), (i)))
 
 #define sk_GENERAL_NAMES_set(sk, i, p)                            \
   ((GENERAL_NAMES *)sk_set(                                       \
@@ -1322,13 +1420,14 @@
 
 #define sk_GENERAL_NAMES_dup(sk)      \
   ((STACK_OF(GENERAL_NAMES) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(GENERAL_NAMES) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(GENERAL_NAMES) *, sk)))
 
 #define sk_GENERAL_NAMES_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_NAMES) *, sk))
 
 #define sk_GENERAL_NAMES_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(GENERAL_NAMES) *, sk))
+  sk_is_sorted(                        \
+      CHECKED_CAST(const _STACK *, const STACK_OF(GENERAL_NAMES) *, sk))
 
 #define sk_GENERAL_NAMES_set_cmp_func(sk, comp)                                \
   ((int (*)(const GENERAL_NAMES **a, const GENERAL_NAMES **b))sk_set_cmp_func( \
@@ -1354,14 +1453,15 @@
   ((STACK_OF(GENERAL_SUBTREE) *)sk_new_null())
 
 #define sk_GENERAL_SUBTREE_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_SUBTREE) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(GENERAL_SUBTREE) *, sk))
 
 #define sk_GENERAL_SUBTREE_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_SUBTREE) *, sk));
 
-#define sk_GENERAL_SUBTREE_value(sk, i) \
-  ((GENERAL_SUBTREE *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(GENERAL_SUBTREE) *, sk), (i)))
+#define sk_GENERAL_SUBTREE_value(sk, i)                                    \
+  ((GENERAL_SUBTREE *)sk_value(                                            \
+      CHECKED_CAST(const _STACK *, const STACK_OF(GENERAL_SUBTREE) *, sk), \
+      (i)))
 
 #define sk_GENERAL_SUBTREE_set(sk, i, p)                            \
   ((GENERAL_SUBTREE *)sk_set(                                       \
@@ -1407,13 +1507,14 @@
 
 #define sk_GENERAL_SUBTREE_dup(sk)      \
   ((STACK_OF(GENERAL_SUBTREE) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(GENERAL_SUBTREE) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(GENERAL_SUBTREE) *, sk)))
 
 #define sk_GENERAL_SUBTREE_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(GENERAL_SUBTREE) *, sk))
 
 #define sk_GENERAL_SUBTREE_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(GENERAL_SUBTREE) *, sk))
+  sk_is_sorted(                          \
+      CHECKED_CAST(const _STACK *, const STACK_OF(GENERAL_SUBTREE) *, sk))
 
 #define sk_GENERAL_SUBTREE_set_cmp_func(sk, comp)                           \
   ((int (*)(const GENERAL_SUBTREE **a, const GENERAL_SUBTREE **b))          \
@@ -1439,14 +1540,14 @@
 #define sk_POLICYINFO_new_null() ((STACK_OF(POLICYINFO) *)sk_new_null())
 
 #define sk_POLICYINFO_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(POLICYINFO) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(POLICYINFO) *, sk))
 
 #define sk_POLICYINFO_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(POLICYINFO) *, sk));
 
 #define sk_POLICYINFO_value(sk, i) \
   ((POLICYINFO *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(POLICYINFO) *, sk), (i)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(POLICYINFO) *, sk), (i)))
 
 #define sk_POLICYINFO_set(sk, i, p)                                         \
   ((POLICYINFO *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(POLICYINFO) *, sk), \
@@ -1489,13 +1590,13 @@
 
 #define sk_POLICYINFO_dup(sk)      \
   ((STACK_OF(POLICYINFO) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(POLICYINFO) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(POLICYINFO) *, sk)))
 
 #define sk_POLICYINFO_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(POLICYINFO) *, sk))
 
 #define sk_POLICYINFO_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(POLICYINFO) *, sk))
+  sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(POLICYINFO) *, sk))
 
 #define sk_POLICYINFO_set_cmp_func(sk, comp)                             \
   ((int (*)(const POLICYINFO **a, const POLICYINFO **b))sk_set_cmp_func( \
@@ -1520,14 +1621,15 @@
 #define sk_POLICYQUALINFO_new_null() ((STACK_OF(POLICYQUALINFO) *)sk_new_null())
 
 #define sk_POLICYQUALINFO_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(POLICYQUALINFO) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(POLICYQUALINFO) *, sk))
 
 #define sk_POLICYQUALINFO_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(POLICYQUALINFO) *, sk));
 
-#define sk_POLICYQUALINFO_value(sk, i) \
-  ((POLICYQUALINFO *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(POLICYQUALINFO) *, sk), (i)))
+#define sk_POLICYQUALINFO_value(sk, i)                                    \
+  ((POLICYQUALINFO *)sk_value(                                            \
+      CHECKED_CAST(const _STACK *, const STACK_OF(POLICYQUALINFO) *, sk), \
+      (i)))
 
 #define sk_POLICYQUALINFO_set(sk, i, p)                            \
   ((POLICYQUALINFO *)sk_set(                                       \
@@ -1573,13 +1675,14 @@
 
 #define sk_POLICYQUALINFO_dup(sk)      \
   ((STACK_OF(POLICYQUALINFO) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(POLICYQUALINFO) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(POLICYQUALINFO) *, sk)))
 
 #define sk_POLICYQUALINFO_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(POLICYQUALINFO) *, sk))
 
 #define sk_POLICYQUALINFO_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(POLICYQUALINFO) *, sk))
+  sk_is_sorted(                         \
+      CHECKED_CAST(const _STACK *, const STACK_OF(POLICYQUALINFO) *, sk))
 
 #define sk_POLICYQUALINFO_set_cmp_func(sk, comp)                           \
   ((int (*)(const POLICYQUALINFO **a, const POLICYQUALINFO **b))           \
@@ -1605,14 +1708,15 @@
 #define sk_POLICY_MAPPING_new_null() ((STACK_OF(POLICY_MAPPING) *)sk_new_null())
 
 #define sk_POLICY_MAPPING_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(POLICY_MAPPING) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(POLICY_MAPPING) *, sk))
 
 #define sk_POLICY_MAPPING_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(POLICY_MAPPING) *, sk));
 
-#define sk_POLICY_MAPPING_value(sk, i) \
-  ((POLICY_MAPPING *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(POLICY_MAPPING) *, sk), (i)))
+#define sk_POLICY_MAPPING_value(sk, i)                                    \
+  ((POLICY_MAPPING *)sk_value(                                            \
+      CHECKED_CAST(const _STACK *, const STACK_OF(POLICY_MAPPING) *, sk), \
+      (i)))
 
 #define sk_POLICY_MAPPING_set(sk, i, p)                            \
   ((POLICY_MAPPING *)sk_set(                                       \
@@ -1658,13 +1762,14 @@
 
 #define sk_POLICY_MAPPING_dup(sk)      \
   ((STACK_OF(POLICY_MAPPING) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(POLICY_MAPPING) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(POLICY_MAPPING) *, sk)))
 
 #define sk_POLICY_MAPPING_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(POLICY_MAPPING) *, sk))
 
 #define sk_POLICY_MAPPING_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(POLICY_MAPPING) *, sk))
+  sk_is_sorted(                         \
+      CHECKED_CAST(const _STACK *, const STACK_OF(POLICY_MAPPING) *, sk))
 
 #define sk_POLICY_MAPPING_set_cmp_func(sk, comp)                           \
   ((int (*)(const POLICY_MAPPING **a, const POLICY_MAPPING **b))           \
@@ -1691,15 +1796,17 @@
 #define sk_RSA_additional_prime_new_null() \
   ((STACK_OF(RSA_additional_prime) *)sk_new_null())
 
-#define sk_RSA_additional_prime_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(RSA_additional_prime) *, sk))
+#define sk_RSA_additional_prime_num(sk)                                       \
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(RSA_additional_prime) *, \
+                      sk))
 
 #define sk_RSA_additional_prime_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(RSA_additional_prime) *, sk));
 
-#define sk_RSA_additional_prime_value(sk, i)                              \
-  ((RSA_additional_prime *)sk_value(                                      \
-      CHECKED_CAST(_STACK *, const STACK_OF(RSA_additional_prime) *, sk), \
+#define sk_RSA_additional_prime_value(sk, i)                               \
+  ((RSA_additional_prime *)sk_value(                                       \
+      CHECKED_CAST(const _STACK *, const STACK_OF(RSA_additional_prime) *, \
+                   sk),                                                    \
       (i)))
 
 #define sk_RSA_additional_prime_set(sk, i, p)                            \
@@ -1744,16 +1851,16 @@
   ((RSA_additional_prime *)sk_pop(      \
       CHECKED_CAST(_STACK *, STACK_OF(RSA_additional_prime) *, sk)))
 
-#define sk_RSA_additional_prime_dup(sk)      \
-  ((STACK_OF(RSA_additional_prime) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(RSA_additional_prime) *, sk)))
+#define sk_RSA_additional_prime_dup(sk)                   \
+  ((STACK_OF(RSA_additional_prime) *)sk_dup(CHECKED_CAST( \
+      const _STACK *, const STACK_OF(RSA_additional_prime) *, sk)))
 
 #define sk_RSA_additional_prime_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(RSA_additional_prime) *, sk))
 
 #define sk_RSA_additional_prime_is_sorted(sk) \
-  sk_is_sorted(                               \
-      CHECKED_CAST(_STACK *, const STACK_OF(RSA_additional_prime) *, sk))
+  sk_is_sorted(CHECKED_CAST(const _STACK *,   \
+                            const STACK_OF(RSA_additional_prime) *, sk))
 
 #define sk_RSA_additional_prime_set_cmp_func(sk, comp)                       \
   ((int (*)(const RSA_additional_prime **a, const RSA_additional_prime **b)) \
@@ -1782,14 +1889,14 @@
 #define sk_SSL_COMP_new_null() ((STACK_OF(SSL_COMP) *)sk_new_null())
 
 #define sk_SSL_COMP_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(SSL_COMP) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(SSL_COMP) *, sk))
 
 #define sk_SSL_COMP_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(SSL_COMP) *, sk));
 
 #define sk_SSL_COMP_value(sk, i) \
   ((SSL_COMP *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(SSL_COMP) *, sk), (i)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(SSL_COMP) *, sk), (i)))
 
 #define sk_SSL_COMP_set(sk, i, p)                                            \
   ((SSL_COMP *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(SSL_COMP) *, sk), (i), \
@@ -1830,13 +1937,13 @@
 
 #define sk_SSL_COMP_dup(sk)      \
   ((STACK_OF(SSL_COMP) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(SSL_COMP) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(SSL_COMP) *, sk)))
 
 #define sk_SSL_COMP_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(SSL_COMP) *, sk))
 
 #define sk_SSL_COMP_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(SSL_COMP) *, sk))
+  sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(SSL_COMP) *, sk))
 
 #define sk_SSL_COMP_set_cmp_func(sk, comp)                           \
   ((int (*)(const SSL_COMP **a, const SSL_COMP **b))sk_set_cmp_func( \
@@ -1860,15 +1967,17 @@
 #define sk_SSL_CUSTOM_EXTENSION_new_null() \
   ((STACK_OF(SSL_CUSTOM_EXTENSION) *)sk_new_null())
 
-#define sk_SSL_CUSTOM_EXTENSION_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(SSL_CUSTOM_EXTENSION) *, sk))
+#define sk_SSL_CUSTOM_EXTENSION_num(sk)                                       \
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(SSL_CUSTOM_EXTENSION) *, \
+                      sk))
 
 #define sk_SSL_CUSTOM_EXTENSION_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(SSL_CUSTOM_EXTENSION) *, sk));
 
-#define sk_SSL_CUSTOM_EXTENSION_value(sk, i)                              \
-  ((SSL_CUSTOM_EXTENSION *)sk_value(                                      \
-      CHECKED_CAST(_STACK *, const STACK_OF(SSL_CUSTOM_EXTENSION) *, sk), \
+#define sk_SSL_CUSTOM_EXTENSION_value(sk, i)                               \
+  ((SSL_CUSTOM_EXTENSION *)sk_value(                                       \
+      CHECKED_CAST(const _STACK *, const STACK_OF(SSL_CUSTOM_EXTENSION) *, \
+                   sk),                                                    \
       (i)))
 
 #define sk_SSL_CUSTOM_EXTENSION_set(sk, i, p)                            \
@@ -1913,16 +2022,16 @@
   ((SSL_CUSTOM_EXTENSION *)sk_pop(      \
       CHECKED_CAST(_STACK *, STACK_OF(SSL_CUSTOM_EXTENSION) *, sk)))
 
-#define sk_SSL_CUSTOM_EXTENSION_dup(sk)      \
-  ((STACK_OF(SSL_CUSTOM_EXTENSION) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(SSL_CUSTOM_EXTENSION) *, sk)))
+#define sk_SSL_CUSTOM_EXTENSION_dup(sk)                   \
+  ((STACK_OF(SSL_CUSTOM_EXTENSION) *)sk_dup(CHECKED_CAST( \
+      const _STACK *, const STACK_OF(SSL_CUSTOM_EXTENSION) *, sk)))
 
 #define sk_SSL_CUSTOM_EXTENSION_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(SSL_CUSTOM_EXTENSION) *, sk))
 
 #define sk_SSL_CUSTOM_EXTENSION_is_sorted(sk) \
-  sk_is_sorted(                               \
-      CHECKED_CAST(_STACK *, const STACK_OF(SSL_CUSTOM_EXTENSION) *, sk))
+  sk_is_sorted(CHECKED_CAST(const _STACK *,   \
+                            const STACK_OF(SSL_CUSTOM_EXTENSION) *, sk))
 
 #define sk_SSL_CUSTOM_EXTENSION_set_cmp_func(sk, comp)                       \
   ((int (*)(const SSL_CUSTOM_EXTENSION **a, const SSL_CUSTOM_EXTENSION **b)) \
@@ -1954,14 +2063,16 @@
   ((STACK_OF(STACK_OF_X509_NAME_ENTRY) *)sk_new_null())
 
 #define sk_STACK_OF_X509_NAME_ENTRY_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *,       \
+                      const STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk))
 
 #define sk_STACK_OF_X509_NAME_ENTRY_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk));
 
-#define sk_STACK_OF_X509_NAME_ENTRY_value(sk, i)                              \
-  ((STACK_OF_X509_NAME_ENTRY *)sk_value(                                      \
-      CHECKED_CAST(_STACK *, const STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk), \
+#define sk_STACK_OF_X509_NAME_ENTRY_value(sk, i)                               \
+  ((STACK_OF_X509_NAME_ENTRY *)sk_value(                                       \
+      CHECKED_CAST(const _STACK *, const STACK_OF(STACK_OF_X509_NAME_ENTRY) *, \
+                   sk),                                                        \
       (i)))
 
 #define sk_STACK_OF_X509_NAME_ENTRY_set(sk, i, p)                            \
@@ -2008,16 +2119,16 @@
   ((STACK_OF_X509_NAME_ENTRY *)sk_pop(      \
       CHECKED_CAST(_STACK *, STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk)))
 
-#define sk_STACK_OF_X509_NAME_ENTRY_dup(sk)      \
-  ((STACK_OF(STACK_OF_X509_NAME_ENTRY) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk)))
+#define sk_STACK_OF_X509_NAME_ENTRY_dup(sk)                   \
+  ((STACK_OF(STACK_OF_X509_NAME_ENTRY) *)sk_dup(CHECKED_CAST( \
+      const _STACK *, const STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk)))
 
 #define sk_STACK_OF_X509_NAME_ENTRY_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk))
 
 #define sk_STACK_OF_X509_NAME_ENTRY_is_sorted(sk) \
-  sk_is_sorted(                                   \
-      CHECKED_CAST(_STACK *, const STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk))
+  sk_is_sorted(CHECKED_CAST(const _STACK *,       \
+                            const STACK_OF(STACK_OF_X509_NAME_ENTRY) *, sk))
 
 #define sk_STACK_OF_X509_NAME_ENTRY_set_cmp_func(sk, comp)                   \
   ((int (*)(const STACK_OF_X509_NAME_ENTRY **a,                              \
@@ -2047,14 +2158,14 @@
 #define sk_SXNETID_new_null() ((STACK_OF(SXNETID) *)sk_new_null())
 
 #define sk_SXNETID_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(SXNETID) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(SXNETID) *, sk))
 
 #define sk_SXNETID_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(SXNETID) *, sk));
 
-#define sk_SXNETID_value(sk, i)                                               \
-  ((SXNETID *)sk_value(CHECKED_CAST(_STACK *, const STACK_OF(SXNETID) *, sk), \
-                       (i)))
+#define sk_SXNETID_value(sk, i) \
+  ((SXNETID *)sk_value(         \
+      CHECKED_CAST(const _STACK *, const STACK_OF(SXNETID) *, sk), (i)))
 
 #define sk_SXNETID_set(sk, i, p)                                           \
   ((SXNETID *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(SXNETID) *, sk), (i), \
@@ -2095,13 +2206,13 @@
 
 #define sk_SXNETID_dup(sk)      \
   ((STACK_OF(SXNETID) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(SXNETID) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(SXNETID) *, sk)))
 
 #define sk_SXNETID_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(SXNETID) *, sk))
 
 #define sk_SXNETID_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(SXNETID) *, sk))
+  sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(SXNETID) *, sk))
 
 #define sk_SXNETID_set_cmp_func(sk, comp)                          \
   ((int (*)(const SXNETID **a, const SXNETID **b))sk_set_cmp_func( \
@@ -2122,12 +2233,14 @@
 
 #define sk_X509_new_null() ((STACK_OF(X509) *)sk_new_null())
 
-#define sk_X509_num(sk) sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509) *, sk))
+#define sk_X509_num(sk) \
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509) *, sk))
 
 #define sk_X509_zero(sk) sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509) *, sk));
 
-#define sk_X509_value(sk, i) \
-  ((X509 *)sk_value(CHECKED_CAST(_STACK *, const STACK_OF(X509) *, sk), (i)))
+#define sk_X509_value(sk, i)                                                  \
+  ((X509 *)sk_value(CHECKED_CAST(const _STACK *, const STACK_OF(X509) *, sk), \
+                    (i)))
 
 #define sk_X509_set(sk, i, p)                                        \
   ((X509 *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(X509) *, sk), (i), \
@@ -2164,13 +2277,14 @@
 #define sk_X509_pop(sk) \
   ((X509 *)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(X509) *, sk)))
 
-#define sk_X509_dup(sk) \
-  ((STACK_OF(X509) *)sk_dup(CHECKED_CAST(_STACK *, const STACK_OF(X509) *, sk)))
+#define sk_X509_dup(sk)      \
+  ((STACK_OF(X509) *)sk_dup( \
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509) *, sk)))
 
 #define sk_X509_sort(sk) sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509) *, sk))
 
 #define sk_X509_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509) *, sk))
+  sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(X509) *, sk))
 
 #define sk_X509_set_cmp_func(sk, comp)                                      \
   ((int (*)(const X509 **a, const X509 **b))sk_set_cmp_func(                \
@@ -2195,14 +2309,15 @@
   ((STACK_OF(X509V3_EXT_METHOD) *)sk_new_null())
 
 #define sk_X509V3_EXT_METHOD_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509V3_EXT_METHOD) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509V3_EXT_METHOD) *, sk))
 
 #define sk_X509V3_EXT_METHOD_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509V3_EXT_METHOD) *, sk));
 
-#define sk_X509V3_EXT_METHOD_value(sk, i) \
-  ((X509V3_EXT_METHOD *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(X509V3_EXT_METHOD) *, sk), (i)))
+#define sk_X509V3_EXT_METHOD_value(sk, i)                                    \
+  ((X509V3_EXT_METHOD *)sk_value(                                            \
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509V3_EXT_METHOD) *, sk), \
+      (i)))
 
 #define sk_X509V3_EXT_METHOD_set(sk, i, p)                            \
   ((X509V3_EXT_METHOD *)sk_set(                                       \
@@ -2248,13 +2363,14 @@
 
 #define sk_X509V3_EXT_METHOD_dup(sk)      \
   ((STACK_OF(X509V3_EXT_METHOD) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(X509V3_EXT_METHOD) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509V3_EXT_METHOD) *, sk)))
 
 #define sk_X509V3_EXT_METHOD_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509V3_EXT_METHOD) *, sk))
 
 #define sk_X509V3_EXT_METHOD_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509V3_EXT_METHOD) *, sk))
+  sk_is_sorted(                            \
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509V3_EXT_METHOD) *, sk))
 
 #define sk_X509V3_EXT_METHOD_set_cmp_func(sk, comp)                           \
   ((int (*)(const X509V3_EXT_METHOD **a, const X509V3_EXT_METHOD **b))        \
@@ -2281,14 +2397,14 @@
 #define sk_X509_ALGOR_new_null() ((STACK_OF(X509_ALGOR) *)sk_new_null())
 
 #define sk_X509_ALGOR_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_ALGOR) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509_ALGOR) *, sk))
 
 #define sk_X509_ALGOR_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_ALGOR) *, sk));
 
 #define sk_X509_ALGOR_value(sk, i) \
   ((X509_ALGOR *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(X509_ALGOR) *, sk), (i)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_ALGOR) *, sk), (i)))
 
 #define sk_X509_ALGOR_set(sk, i, p)                                         \
   ((X509_ALGOR *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(X509_ALGOR) *, sk), \
@@ -2331,13 +2447,13 @@
 
 #define sk_X509_ALGOR_dup(sk)      \
   ((STACK_OF(X509_ALGOR) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(X509_ALGOR) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_ALGOR) *, sk)))
 
 #define sk_X509_ALGOR_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_ALGOR) *, sk))
 
 #define sk_X509_ALGOR_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_ALGOR) *, sk))
+  sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(X509_ALGOR) *, sk))
 
 #define sk_X509_ALGOR_set_cmp_func(sk, comp)                             \
   ((int (*)(const X509_ALGOR **a, const X509_ALGOR **b))sk_set_cmp_func( \
@@ -2362,14 +2478,15 @@
 #define sk_X509_ATTRIBUTE_new_null() ((STACK_OF(X509_ATTRIBUTE) *)sk_new_null())
 
 #define sk_X509_ATTRIBUTE_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_ATTRIBUTE) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509_ATTRIBUTE) *, sk))
 
 #define sk_X509_ATTRIBUTE_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_ATTRIBUTE) *, sk));
 
-#define sk_X509_ATTRIBUTE_value(sk, i) \
-  ((X509_ATTRIBUTE *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(X509_ATTRIBUTE) *, sk), (i)))
+#define sk_X509_ATTRIBUTE_value(sk, i)                                    \
+  ((X509_ATTRIBUTE *)sk_value(                                            \
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_ATTRIBUTE) *, sk), \
+      (i)))
 
 #define sk_X509_ATTRIBUTE_set(sk, i, p)                            \
   ((X509_ATTRIBUTE *)sk_set(                                       \
@@ -2415,13 +2532,14 @@
 
 #define sk_X509_ATTRIBUTE_dup(sk)      \
   ((STACK_OF(X509_ATTRIBUTE) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(X509_ATTRIBUTE) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_ATTRIBUTE) *, sk)))
 
 #define sk_X509_ATTRIBUTE_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_ATTRIBUTE) *, sk))
 
 #define sk_X509_ATTRIBUTE_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_ATTRIBUTE) *, sk))
+  sk_is_sorted(                         \
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_ATTRIBUTE) *, sk))
 
 #define sk_X509_ATTRIBUTE_set_cmp_func(sk, comp)                           \
   ((int (*)(const X509_ATTRIBUTE **a, const X509_ATTRIBUTE **b))           \
@@ -2446,14 +2564,14 @@
 #define sk_X509_CRL_new_null() ((STACK_OF(X509_CRL) *)sk_new_null())
 
 #define sk_X509_CRL_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_CRL) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509_CRL) *, sk))
 
 #define sk_X509_CRL_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_CRL) *, sk));
 
 #define sk_X509_CRL_value(sk, i) \
   ((X509_CRL *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(X509_CRL) *, sk), (i)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_CRL) *, sk), (i)))
 
 #define sk_X509_CRL_set(sk, i, p)                                            \
   ((X509_CRL *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(X509_CRL) *, sk), (i), \
@@ -2494,13 +2612,13 @@
 
 #define sk_X509_CRL_dup(sk)      \
   ((STACK_OF(X509_CRL) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(X509_CRL) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_CRL) *, sk)))
 
 #define sk_X509_CRL_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_CRL) *, sk))
 
 #define sk_X509_CRL_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_CRL) *, sk))
+  sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(X509_CRL) *, sk))
 
 #define sk_X509_CRL_set_cmp_func(sk, comp)                           \
   ((int (*)(const X509_CRL **a, const X509_CRL **b))sk_set_cmp_func( \
@@ -2523,14 +2641,15 @@
 #define sk_X509_EXTENSION_new_null() ((STACK_OF(X509_EXTENSION) *)sk_new_null())
 
 #define sk_X509_EXTENSION_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_EXTENSION) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509_EXTENSION) *, sk))
 
 #define sk_X509_EXTENSION_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_EXTENSION) *, sk));
 
-#define sk_X509_EXTENSION_value(sk, i) \
-  ((X509_EXTENSION *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(X509_EXTENSION) *, sk), (i)))
+#define sk_X509_EXTENSION_value(sk, i)                                    \
+  ((X509_EXTENSION *)sk_value(                                            \
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_EXTENSION) *, sk), \
+      (i)))
 
 #define sk_X509_EXTENSION_set(sk, i, p)                            \
   ((X509_EXTENSION *)sk_set(                                       \
@@ -2576,13 +2695,14 @@
 
 #define sk_X509_EXTENSION_dup(sk)      \
   ((STACK_OF(X509_EXTENSION) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(X509_EXTENSION) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_EXTENSION) *, sk)))
 
 #define sk_X509_EXTENSION_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_EXTENSION) *, sk))
 
 #define sk_X509_EXTENSION_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_EXTENSION) *, sk))
+  sk_is_sorted(                         \
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_EXTENSION) *, sk))
 
 #define sk_X509_EXTENSION_set_cmp_func(sk, comp)                           \
   ((int (*)(const X509_EXTENSION **a, const X509_EXTENSION **b))           \
@@ -2608,14 +2728,14 @@
 #define sk_X509_INFO_new_null() ((STACK_OF(X509_INFO) *)sk_new_null())
 
 #define sk_X509_INFO_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_INFO) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509_INFO) *, sk))
 
 #define sk_X509_INFO_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_INFO) *, sk));
 
 #define sk_X509_INFO_value(sk, i) \
   ((X509_INFO *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(X509_INFO) *, sk), (i)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_INFO) *, sk), (i)))
 
 #define sk_X509_INFO_set(sk, i, p)                                             \
   ((X509_INFO *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(X509_INFO) *, sk), (i), \
@@ -2658,13 +2778,13 @@
 
 #define sk_X509_INFO_dup(sk)      \
   ((STACK_OF(X509_INFO) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(X509_INFO) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_INFO) *, sk)))
 
 #define sk_X509_INFO_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_INFO) *, sk))
 
 #define sk_X509_INFO_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_INFO) *, sk))
+  sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(X509_INFO) *, sk))
 
 #define sk_X509_INFO_set_cmp_func(sk, comp)                            \
   ((int (*)(const X509_INFO **a, const X509_INFO **b))sk_set_cmp_func( \
@@ -2687,14 +2807,14 @@
 #define sk_X509_LOOKUP_new_null() ((STACK_OF(X509_LOOKUP) *)sk_new_null())
 
 #define sk_X509_LOOKUP_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_LOOKUP) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509_LOOKUP) *, sk))
 
 #define sk_X509_LOOKUP_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_LOOKUP) *, sk));
 
 #define sk_X509_LOOKUP_value(sk, i) \
   ((X509_LOOKUP *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(X509_LOOKUP) *, sk), (i)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_LOOKUP) *, sk), (i)))
 
 #define sk_X509_LOOKUP_set(sk, i, p)                                          \
   ((X509_LOOKUP *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(X509_LOOKUP) *, sk), \
@@ -2737,13 +2857,13 @@
 
 #define sk_X509_LOOKUP_dup(sk)      \
   ((STACK_OF(X509_LOOKUP) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(X509_LOOKUP) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_LOOKUP) *, sk)))
 
 #define sk_X509_LOOKUP_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_LOOKUP) *, sk))
 
 #define sk_X509_LOOKUP_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_LOOKUP) *, sk))
+  sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(X509_LOOKUP) *, sk))
 
 #define sk_X509_LOOKUP_set_cmp_func(sk, comp)                              \
   ((int (*)(const X509_LOOKUP **a, const X509_LOOKUP **b))sk_set_cmp_func( \
@@ -2768,14 +2888,14 @@
 #define sk_X509_NAME_new_null() ((STACK_OF(X509_NAME) *)sk_new_null())
 
 #define sk_X509_NAME_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_NAME) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509_NAME) *, sk))
 
 #define sk_X509_NAME_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_NAME) *, sk));
 
 #define sk_X509_NAME_value(sk, i) \
   ((X509_NAME *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(X509_NAME) *, sk), (i)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_NAME) *, sk), (i)))
 
 #define sk_X509_NAME_set(sk, i, p)                                             \
   ((X509_NAME *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(X509_NAME) *, sk), (i), \
@@ -2818,13 +2938,13 @@
 
 #define sk_X509_NAME_dup(sk)      \
   ((STACK_OF(X509_NAME) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(X509_NAME) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_NAME) *, sk)))
 
 #define sk_X509_NAME_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_NAME) *, sk))
 
 #define sk_X509_NAME_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_NAME) *, sk))
+  sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(X509_NAME) *, sk))
 
 #define sk_X509_NAME_set_cmp_func(sk, comp)                            \
   ((int (*)(const X509_NAME **a, const X509_NAME **b))sk_set_cmp_func( \
@@ -2848,14 +2968,15 @@
   ((STACK_OF(X509_NAME_ENTRY) *)sk_new_null())
 
 #define sk_X509_NAME_ENTRY_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_NAME_ENTRY) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509_NAME_ENTRY) *, sk))
 
 #define sk_X509_NAME_ENTRY_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_NAME_ENTRY) *, sk));
 
-#define sk_X509_NAME_ENTRY_value(sk, i) \
-  ((X509_NAME_ENTRY *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(X509_NAME_ENTRY) *, sk), (i)))
+#define sk_X509_NAME_ENTRY_value(sk, i)                                    \
+  ((X509_NAME_ENTRY *)sk_value(                                            \
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_NAME_ENTRY) *, sk), \
+      (i)))
 
 #define sk_X509_NAME_ENTRY_set(sk, i, p)                            \
   ((X509_NAME_ENTRY *)sk_set(                                       \
@@ -2901,13 +3022,14 @@
 
 #define sk_X509_NAME_ENTRY_dup(sk)      \
   ((STACK_OF(X509_NAME_ENTRY) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(X509_NAME_ENTRY) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_NAME_ENTRY) *, sk)))
 
 #define sk_X509_NAME_ENTRY_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_NAME_ENTRY) *, sk))
 
 #define sk_X509_NAME_ENTRY_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_NAME_ENTRY) *, sk))
+  sk_is_sorted(                          \
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_NAME_ENTRY) *, sk))
 
 #define sk_X509_NAME_ENTRY_set_cmp_func(sk, comp)                           \
   ((int (*)(const X509_NAME_ENTRY **a, const X509_NAME_ENTRY **b))          \
@@ -2933,14 +3055,14 @@
 #define sk_X509_OBJECT_new_null() ((STACK_OF(X509_OBJECT) *)sk_new_null())
 
 #define sk_X509_OBJECT_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_OBJECT) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509_OBJECT) *, sk))
 
 #define sk_X509_OBJECT_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_OBJECT) *, sk));
 
 #define sk_X509_OBJECT_value(sk, i) \
   ((X509_OBJECT *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(X509_OBJECT) *, sk), (i)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_OBJECT) *, sk), (i)))
 
 #define sk_X509_OBJECT_set(sk, i, p)                                          \
   ((X509_OBJECT *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(X509_OBJECT) *, sk), \
@@ -2983,13 +3105,13 @@
 
 #define sk_X509_OBJECT_dup(sk)      \
   ((STACK_OF(X509_OBJECT) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(X509_OBJECT) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_OBJECT) *, sk)))
 
 #define sk_X509_OBJECT_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_OBJECT) *, sk))
 
 #define sk_X509_OBJECT_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_OBJECT) *, sk))
+  sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(X509_OBJECT) *, sk))
 
 #define sk_X509_OBJECT_set_cmp_func(sk, comp)                              \
   ((int (*)(const X509_OBJECT **a, const X509_OBJECT **b))sk_set_cmp_func( \
@@ -3015,14 +3137,15 @@
   ((STACK_OF(X509_POLICY_DATA) *)sk_new_null())
 
 #define sk_X509_POLICY_DATA_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_DATA) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509_POLICY_DATA) *, sk))
 
 #define sk_X509_POLICY_DATA_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_DATA) *, sk));
 
-#define sk_X509_POLICY_DATA_value(sk, i) \
-  ((X509_POLICY_DATA *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(X509_POLICY_DATA) *, sk), (i)))
+#define sk_X509_POLICY_DATA_value(sk, i)                                    \
+  ((X509_POLICY_DATA *)sk_value(                                            \
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_POLICY_DATA) *, sk), \
+      (i)))
 
 #define sk_X509_POLICY_DATA_set(sk, i, p)                            \
   ((X509_POLICY_DATA *)sk_set(                                       \
@@ -3068,13 +3191,14 @@
 
 #define sk_X509_POLICY_DATA_dup(sk)      \
   ((STACK_OF(X509_POLICY_DATA) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(X509_POLICY_DATA) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_POLICY_DATA) *, sk)))
 
 #define sk_X509_POLICY_DATA_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_DATA) *, sk))
 
 #define sk_X509_POLICY_DATA_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_POLICY_DATA) *, sk))
+  sk_is_sorted(                           \
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_POLICY_DATA) *, sk))
 
 #define sk_X509_POLICY_DATA_set_cmp_func(sk, comp)                           \
   ((int (*)(const X509_POLICY_DATA **a, const X509_POLICY_DATA **b))         \
@@ -3102,14 +3226,15 @@
   ((STACK_OF(X509_POLICY_NODE) *)sk_new_null())
 
 #define sk_X509_POLICY_NODE_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_NODE) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509_POLICY_NODE) *, sk))
 
 #define sk_X509_POLICY_NODE_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_NODE) *, sk));
 
-#define sk_X509_POLICY_NODE_value(sk, i) \
-  ((X509_POLICY_NODE *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(X509_POLICY_NODE) *, sk), (i)))
+#define sk_X509_POLICY_NODE_value(sk, i)                                    \
+  ((X509_POLICY_NODE *)sk_value(                                            \
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_POLICY_NODE) *, sk), \
+      (i)))
 
 #define sk_X509_POLICY_NODE_set(sk, i, p)                            \
   ((X509_POLICY_NODE *)sk_set(                                       \
@@ -3155,13 +3280,14 @@
 
 #define sk_X509_POLICY_NODE_dup(sk)      \
   ((STACK_OF(X509_POLICY_NODE) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(X509_POLICY_NODE) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_POLICY_NODE) *, sk)))
 
 #define sk_X509_POLICY_NODE_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_POLICY_NODE) *, sk))
 
 #define sk_X509_POLICY_NODE_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_POLICY_NODE) *, sk))
+  sk_is_sorted(                           \
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_POLICY_NODE) *, sk))
 
 #define sk_X509_POLICY_NODE_set_cmp_func(sk, comp)                           \
   ((int (*)(const X509_POLICY_NODE **a, const X509_POLICY_NODE **b))         \
@@ -3188,14 +3314,14 @@
 #define sk_X509_PURPOSE_new_null() ((STACK_OF(X509_PURPOSE) *)sk_new_null())
 
 #define sk_X509_PURPOSE_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_PURPOSE) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509_PURPOSE) *, sk))
 
 #define sk_X509_PURPOSE_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_PURPOSE) *, sk));
 
 #define sk_X509_PURPOSE_value(sk, i) \
   ((X509_PURPOSE *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(X509_PURPOSE) *, sk), (i)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_PURPOSE) *, sk), (i)))
 
 #define sk_X509_PURPOSE_set(sk, i, p)                            \
   ((X509_PURPOSE *)sk_set(                                       \
@@ -3240,13 +3366,13 @@
 
 #define sk_X509_PURPOSE_dup(sk)      \
   ((STACK_OF(X509_PURPOSE) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(X509_PURPOSE) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_PURPOSE) *, sk)))
 
 #define sk_X509_PURPOSE_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_PURPOSE) *, sk))
 
 #define sk_X509_PURPOSE_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_PURPOSE) *, sk))
+  sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(X509_PURPOSE) *, sk))
 
 #define sk_X509_PURPOSE_set_cmp_func(sk, comp)                               \
   ((int (*)(const X509_PURPOSE **a, const X509_PURPOSE **b))sk_set_cmp_func( \
@@ -3271,14 +3397,14 @@
 #define sk_X509_REVOKED_new_null() ((STACK_OF(X509_REVOKED) *)sk_new_null())
 
 #define sk_X509_REVOKED_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_REVOKED) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509_REVOKED) *, sk))
 
 #define sk_X509_REVOKED_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_REVOKED) *, sk));
 
 #define sk_X509_REVOKED_value(sk, i) \
   ((X509_REVOKED *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(X509_REVOKED) *, sk), (i)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_REVOKED) *, sk), (i)))
 
 #define sk_X509_REVOKED_set(sk, i, p)                            \
   ((X509_REVOKED *)sk_set(                                       \
@@ -3323,13 +3449,13 @@
 
 #define sk_X509_REVOKED_dup(sk)      \
   ((STACK_OF(X509_REVOKED) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(X509_REVOKED) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_REVOKED) *, sk)))
 
 #define sk_X509_REVOKED_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_REVOKED) *, sk))
 
 #define sk_X509_REVOKED_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_REVOKED) *, sk))
+  sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(X509_REVOKED) *, sk))
 
 #define sk_X509_REVOKED_set_cmp_func(sk, comp)                               \
   ((int (*)(const X509_REVOKED **a, const X509_REVOKED **b))sk_set_cmp_func( \
@@ -3354,14 +3480,14 @@
 #define sk_X509_TRUST_new_null() ((STACK_OF(X509_TRUST) *)sk_new_null())
 
 #define sk_X509_TRUST_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_TRUST) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509_TRUST) *, sk))
 
 #define sk_X509_TRUST_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_TRUST) *, sk));
 
 #define sk_X509_TRUST_value(sk, i) \
   ((X509_TRUST *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(X509_TRUST) *, sk), (i)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_TRUST) *, sk), (i)))
 
 #define sk_X509_TRUST_set(sk, i, p)                                         \
   ((X509_TRUST *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(X509_TRUST) *, sk), \
@@ -3404,13 +3530,13 @@
 
 #define sk_X509_TRUST_dup(sk)      \
   ((STACK_OF(X509_TRUST) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(X509_TRUST) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_TRUST) *, sk)))
 
 #define sk_X509_TRUST_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_TRUST) *, sk))
 
 #define sk_X509_TRUST_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_TRUST) *, sk))
+  sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(X509_TRUST) *, sk))
 
 #define sk_X509_TRUST_set_cmp_func(sk, comp)                             \
   ((int (*)(const X509_TRUST **a, const X509_TRUST **b))sk_set_cmp_func( \
@@ -3437,14 +3563,15 @@
   ((STACK_OF(X509_VERIFY_PARAM) *)sk_new_null())
 
 #define sk_X509_VERIFY_PARAM_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(X509_VERIFY_PARAM) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(X509_VERIFY_PARAM) *, sk))
 
 #define sk_X509_VERIFY_PARAM_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(X509_VERIFY_PARAM) *, sk));
 
-#define sk_X509_VERIFY_PARAM_value(sk, i) \
-  ((X509_VERIFY_PARAM *)sk_value(         \
-      CHECKED_CAST(_STACK *, const STACK_OF(X509_VERIFY_PARAM) *, sk), (i)))
+#define sk_X509_VERIFY_PARAM_value(sk, i)                                    \
+  ((X509_VERIFY_PARAM *)sk_value(                                            \
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_VERIFY_PARAM) *, sk), \
+      (i)))
 
 #define sk_X509_VERIFY_PARAM_set(sk, i, p)                            \
   ((X509_VERIFY_PARAM *)sk_set(                                       \
@@ -3490,13 +3617,14 @@
 
 #define sk_X509_VERIFY_PARAM_dup(sk)      \
   ((STACK_OF(X509_VERIFY_PARAM) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(X509_VERIFY_PARAM) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_VERIFY_PARAM) *, sk)))
 
 #define sk_X509_VERIFY_PARAM_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(X509_VERIFY_PARAM) *, sk))
 
 #define sk_X509_VERIFY_PARAM_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(X509_VERIFY_PARAM) *, sk))
+  sk_is_sorted(                            \
+      CHECKED_CAST(const _STACK *, const STACK_OF(X509_VERIFY_PARAM) *, sk))
 
 #define sk_X509_VERIFY_PARAM_set_cmp_func(sk, comp)                           \
   ((int (*)(const X509_VERIFY_PARAM **a, const X509_VERIFY_PARAM **b))        \
@@ -3515,21 +3643,23 @@
                    free_func)))
 
 /* void */
-#define sk_void_new(comp)                \
-  ((STACK_OF(void)*)sk_new(CHECKED_CAST( \
+#define sk_void_new(comp)                 \
+  ((STACK_OF(void) *)sk_new(CHECKED_CAST( \
       stack_cmp_func, int (*)(const void **a, const void **b), comp)))
 
-#define sk_void_new_null() ((STACK_OF(void)*)sk_new_null())
+#define sk_void_new_null() ((STACK_OF(void) *)sk_new_null())
 
-#define sk_void_num(sk) sk_num(CHECKED_CAST(_STACK *, STACK_OF(void) *, sk))
+#define sk_void_num(sk) \
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(void) *, sk))
 
 #define sk_void_zero(sk) sk_zero(CHECKED_CAST(_STACK *, STACK_OF(void) *, sk));
 
-#define sk_void_value(sk, i) \
-  ((void *)sk_value(CHECKED_CAST(_STACK *, const STACK_OF(void) *, sk), (i)))
+#define sk_void_value(sk, i)                                                  \
+  ((void *)sk_value(CHECKED_CAST(const _STACK *, const STACK_OF(void) *, sk), \
+                    (i)))
 
-#define sk_void_set(sk, i, p)                                       \
-  ((void *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(void)*, sk), (i), \
+#define sk_void_set(sk, i, p)                                        \
+  ((void *)sk_set(CHECKED_CAST(_STACK *, STACK_OF(void) *, sk), (i), \
                   CHECKED_CAST(void *, void *, p)))
 
 #define sk_void_free(sk) sk_free(CHECKED_CAST(_STACK *, STACK_OF(void) *, sk))
@@ -3543,10 +3673,10 @@
             CHECKED_CAST(void *, void *, p), (where))
 
 #define sk_void_delete(sk, where) \
-  ((void *)sk_delete(CHECKED_CAST(_STACK *, STACK_OF(void)*, sk), (where)))
+  ((void *)sk_delete(CHECKED_CAST(_STACK *, STACK_OF(void) *, sk), (where)))
 
-#define sk_void_delete_ptr(sk, p)                                     \
-  ((void *)sk_delete_ptr(CHECKED_CAST(_STACK *, STACK_OF(void)*, sk), \
+#define sk_void_delete_ptr(sk, p)                                      \
+  ((void *)sk_delete_ptr(CHECKED_CAST(_STACK *, STACK_OF(void) *, sk), \
                          CHECKED_CAST(void *, void *, p)))
 
 #define sk_void_find(sk, out_index, p)                               \
@@ -3554,31 +3684,32 @@
           CHECKED_CAST(void *, void *, p))
 
 #define sk_void_shift(sk) \
-  ((void *)sk_shift(CHECKED_CAST(_STACK *, STACK_OF(void)*, sk)))
+  ((void *)sk_shift(CHECKED_CAST(_STACK *, STACK_OF(void) *, sk)))
 
 #define sk_void_push(sk, p)                             \
   sk_push(CHECKED_CAST(_STACK *, STACK_OF(void) *, sk), \
           CHECKED_CAST(void *, void *, p))
 
 #define sk_void_pop(sk) \
-  ((void *)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(void)*, sk)))
+  ((void *)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(void) *, sk)))
 
-#define sk_void_dup(sk) \
-  ((STACK_OF(void)*)sk_dup(CHECKED_CAST(_STACK *, const STACK_OF(void) *, sk)))
+#define sk_void_dup(sk)      \
+  ((STACK_OF(void) *)sk_dup( \
+      CHECKED_CAST(const _STACK *, const STACK_OF(void) *, sk)))
 
 #define sk_void_sort(sk) sk_sort(CHECKED_CAST(_STACK *, STACK_OF(void) *, sk))
 
 #define sk_void_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(void) *, sk))
+  sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(void) *, sk))
 
 #define sk_void_set_cmp_func(sk, comp)                                      \
   ((int (*)(const void **a, const void **b))sk_set_cmp_func(                \
-      CHECKED_CAST(_STACK *, STACK_OF(void)*, sk),                          \
+      CHECKED_CAST(_STACK *, STACK_OF(void) *, sk),                         \
       CHECKED_CAST(stack_cmp_func, int (*)(const void **a, const void **b), \
                    comp)))
 
 #define sk_void_deep_copy(sk, copy_func, free_func)                  \
-  ((STACK_OF(void)*)sk_deep_copy(                                    \
+  ((STACK_OF(void) *)sk_deep_copy(                                   \
       CHECKED_CAST(const _STACK *, const STACK_OF(void) *, sk),      \
       CHECKED_CAST(void *(*)(void *), void *(*)(void *), copy_func), \
       CHECKED_CAST(void (*)(void *), void (*)(void *), free_func)))
@@ -3594,14 +3725,16 @@
   ((STACK_OF(SRTP_PROTECTION_PROFILE) *)sk_new_null())
 
 #define sk_SRTP_PROTECTION_PROFILE_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(SRTP_PROTECTION_PROFILE) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *,      \
+                      const STACK_OF(SRTP_PROTECTION_PROFILE) *, sk))
 
 #define sk_SRTP_PROTECTION_PROFILE_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(SRTP_PROTECTION_PROFILE) *, sk));
 
-#define sk_SRTP_PROTECTION_PROFILE_value(sk, i)                              \
-  ((const SRTP_PROTECTION_PROFILE *)sk_value(                                \
-      CHECKED_CAST(_STACK *, const STACK_OF(SRTP_PROTECTION_PROFILE) *, sk), \
+#define sk_SRTP_PROTECTION_PROFILE_value(sk, i)                               \
+  ((const SRTP_PROTECTION_PROFILE *)sk_value(                                 \
+      CHECKED_CAST(const _STACK *, const STACK_OF(SRTP_PROTECTION_PROFILE) *, \
+                   sk),                                                       \
       (i)))
 
 #define sk_SRTP_PROTECTION_PROFILE_set(sk, i, p)                            \
@@ -3649,16 +3782,16 @@
   ((const SRTP_PROTECTION_PROFILE *)sk_pop( \
       CHECKED_CAST(_STACK *, STACK_OF(SRTP_PROTECTION_PROFILE) *, sk)))
 
-#define sk_SRTP_PROTECTION_PROFILE_dup(sk)      \
-  ((STACK_OF(SRTP_PROTECTION_PROFILE) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(SRTP_PROTECTION_PROFILE) *, sk)))
+#define sk_SRTP_PROTECTION_PROFILE_dup(sk)                   \
+  ((STACK_OF(SRTP_PROTECTION_PROFILE) *)sk_dup(CHECKED_CAST( \
+      const _STACK *, const STACK_OF(SRTP_PROTECTION_PROFILE) *, sk)))
 
 #define sk_SRTP_PROTECTION_PROFILE_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(SRTP_PROTECTION_PROFILE) *, sk))
 
 #define sk_SRTP_PROTECTION_PROFILE_is_sorted(sk) \
-  sk_is_sorted(                                  \
-      CHECKED_CAST(_STACK *, const STACK_OF(SRTP_PROTECTION_PROFILE) *, sk))
+  sk_is_sorted(CHECKED_CAST(const _STACK *,      \
+                            const STACK_OF(SRTP_PROTECTION_PROFILE) *, sk))
 
 #define sk_SRTP_PROTECTION_PROFILE_set_cmp_func(sk, comp)                   \
   ((int (*)(const SRTP_PROTECTION_PROFILE **a,                              \
@@ -3670,14 +3803,15 @@
                                 const SRTP_PROTECTION_PROFILE **b),         \
                         comp)))
 
-#define sk_SRTP_PROTECTION_PROFILE_deep_copy(sk, copy_func, free_func)        \
-  ((STACK_OF(SRTP_PROTECTION_PROFILE) *)sk_deep_copy(                         \
-      CHECKED_CAST(const _STACK *, const STACK_OF(SRTP_PROTECTION_PROFILE) *, \
-                   sk),                                                       \
-      CHECKED_CAST(void *(*)(void *), const SRTP_PROTECTION_PROFILE *(*)(     \
-                                          const SRTP_PROTECTION_PROFILE *),   \
-                   copy_func),                                                \
-      CHECKED_CAST(void (*)(void *),                                          \
+#define sk_SRTP_PROTECTION_PROFILE_deep_copy(sk, copy_func, free_func)         \
+  ((STACK_OF(SRTP_PROTECTION_PROFILE) *)sk_deep_copy(                          \
+      CHECKED_CAST(const _STACK *, const STACK_OF(SRTP_PROTECTION_PROFILE) *,  \
+                   sk),                                                        \
+      CHECKED_CAST(                                                            \
+          void *(*)(void *),                                                   \
+          const SRTP_PROTECTION_PROFILE *(*)(const SRTP_PROTECTION_PROFILE *), \
+          copy_func),                                                          \
+      CHECKED_CAST(void (*)(void *),                                           \
                    void (*)(const SRTP_PROTECTION_PROFILE *), free_func)))
 
 /* SSL_CIPHER */
@@ -3689,14 +3823,14 @@
 #define sk_SSL_CIPHER_new_null() ((STACK_OF(SSL_CIPHER) *)sk_new_null())
 
 #define sk_SSL_CIPHER_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(SSL_CIPHER) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(SSL_CIPHER) *, sk))
 
 #define sk_SSL_CIPHER_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(SSL_CIPHER) *, sk));
 
 #define sk_SSL_CIPHER_value(sk, i) \
   ((const SSL_CIPHER *)sk_value(   \
-      CHECKED_CAST(_STACK *, const STACK_OF(SSL_CIPHER) *, sk), (i)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(SSL_CIPHER) *, sk), (i)))
 
 #define sk_SSL_CIPHER_set(sk, i, p)                            \
   ((const SSL_CIPHER *)sk_set(                                 \
@@ -3742,13 +3876,13 @@
 
 #define sk_SSL_CIPHER_dup(sk)      \
   ((STACK_OF(SSL_CIPHER) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(SSL_CIPHER) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(SSL_CIPHER) *, sk)))
 
 #define sk_SSL_CIPHER_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(SSL_CIPHER) *, sk))
 
 #define sk_SSL_CIPHER_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(SSL_CIPHER) *, sk))
+  sk_is_sorted(CHECKED_CAST(const _STACK *, const STACK_OF(SSL_CIPHER) *, sk))
 
 #define sk_SSL_CIPHER_set_cmp_func(sk, comp)                             \
   ((int (*)(const SSL_CIPHER **a, const SSL_CIPHER **b))sk_set_cmp_func( \
@@ -3774,14 +3908,15 @@
 #define sk_OPENSSL_STRING_new_null() ((STACK_OF(OPENSSL_STRING) *)sk_new_null())
 
 #define sk_OPENSSL_STRING_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_STRING) *, sk))
+  sk_num(CHECKED_CAST(const _STACK *, const STACK_OF(OPENSSL_STRING) *, sk))
 
 #define sk_OPENSSL_STRING_zero(sk) \
   sk_zero(CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_STRING) *, sk));
 
-#define sk_OPENSSL_STRING_value(sk, i) \
-  ((OPENSSL_STRING)sk_value(           \
-      CHECKED_CAST(_STACK *, const STACK_OF(OPENSSL_STRING) *, sk), (i)))
+#define sk_OPENSSL_STRING_value(sk, i)                                    \
+  ((OPENSSL_STRING)sk_value(                                              \
+      CHECKED_CAST(const _STACK *, const STACK_OF(OPENSSL_STRING) *, sk), \
+      (i)))
 
 #define sk_OPENSSL_STRING_set(sk, i, p)                            \
   ((OPENSSL_STRING)sk_set(                                         \
@@ -3827,13 +3962,14 @@
 
 #define sk_OPENSSL_STRING_dup(sk)      \
   ((STACK_OF(OPENSSL_STRING) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(OPENSSL_STRING) *, sk)))
+      CHECKED_CAST(const _STACK *, const STACK_OF(OPENSSL_STRING) *, sk)))
 
 #define sk_OPENSSL_STRING_sort(sk) \
   sk_sort(CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_STRING) *, sk))
 
 #define sk_OPENSSL_STRING_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(OPENSSL_STRING) *, sk))
+  sk_is_sorted(                         \
+      CHECKED_CAST(const _STACK *, const STACK_OF(OPENSSL_STRING) *, sk))
 
 #define sk_OPENSSL_STRING_set_cmp_func(sk, comp)                           \
   ((int (*)(const OPENSSL_STRING **a, const OPENSSL_STRING **b))           \
@@ -3849,86 +3985,3 @@
       CHECKED_CAST(void *(*)(void *), OPENSSL_STRING (*)(OPENSSL_STRING), \
                    copy_func),                                            \
       CHECKED_CAST(void (*)(void *), void (*)(OPENSSL_STRING), free_func)))
-
-/* OPENSSL_BLOCK */
-#define sk_OPENSSL_BLOCK_new(comp)                                             \
-  ((STACK_OF(OPENSSL_BLOCK) *)sk_new(CHECKED_CAST(                             \
-      stack_cmp_func, int (*)(const OPENSSL_BLOCK *a, const OPENSSL_BLOCK *b), \
-      comp)))
-
-#define sk_OPENSSL_BLOCK_new_null() ((STACK_OF(OPENSSL_BLOCK) *)sk_new_null())
-
-#define sk_OPENSSL_BLOCK_num(sk) \
-  sk_num(CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_BLOCK) *, sk))
-
-#define sk_OPENSSL_BLOCK_zero(sk) \
-  sk_zero(CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_BLOCK) *, sk));
-
-#define sk_OPENSSL_BLOCK_value(sk, i) \
-  ((OPENSSL_BLOCK)sk_value(           \
-      CHECKED_CAST(_STACK *, const STACK_OF(OPENSSL_BLOCK) *, sk), (i)))
-
-#define sk_OPENSSL_BLOCK_set(sk, i, p)                            \
-  ((OPENSSL_BLOCK)sk_set(                                         \
-      CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_BLOCK) *, sk), (i), \
-      CHECKED_CAST(void *, OPENSSL_BLOCK, p)))
-
-#define sk_OPENSSL_BLOCK_free(sk) \
-  sk_free(CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_BLOCK) *, sk))
-
-#define sk_OPENSSL_BLOCK_pop_free(sk, free_func)             \
-  sk_pop_free(                                               \
-      CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_BLOCK) *, sk), \
-      CHECKED_CAST(void (*)(void *), void (*)(OPENSSL_BLOCK), free_func))
-
-#define sk_OPENSSL_BLOCK_insert(sk, p, where)                      \
-  sk_insert(CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_BLOCK) *, sk), \
-            CHECKED_CAST(void *, OPENSSL_BLOCK, p), (where))
-
-#define sk_OPENSSL_BLOCK_delete(sk, where) \
-  ((OPENSSL_BLOCK)sk_delete(               \
-      CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_BLOCK) *, sk), (where)))
-
-#define sk_OPENSSL_BLOCK_delete_ptr(sk, p)                   \
-  ((OPENSSL_BLOCK)sk_delete_ptr(                             \
-      CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_BLOCK) *, sk), \
-      CHECKED_CAST(void *, OPENSSL_BLOCK, p)))
-
-#define sk_OPENSSL_BLOCK_find(sk, out_index, p)                               \
-  sk_find(CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_BLOCK) *, sk), (out_index), \
-          CHECKED_CAST(void *, OPENSSL_BLOCK, p))
-
-#define sk_OPENSSL_BLOCK_shift(sk) \
-  ((OPENSSL_BLOCK)sk_shift(        \
-      CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_BLOCK) *, sk)))
-
-#define sk_OPENSSL_BLOCK_push(sk, p)                             \
-  sk_push(CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_BLOCK) *, sk), \
-          CHECKED_CAST(void *, OPENSSL_BLOCK, p))
-
-#define sk_OPENSSL_BLOCK_pop(sk) \
-  ((OPENSSL_BLOCK)sk_pop(CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_BLOCK) *, sk)))
-
-#define sk_OPENSSL_BLOCK_dup(sk)      \
-  ((STACK_OF(OPENSSL_BLOCK) *)sk_dup( \
-      CHECKED_CAST(_STACK *, const STACK_OF(OPENSSL_BLOCK) *, sk)))
-
-#define sk_OPENSSL_BLOCK_sort(sk) \
-  sk_sort(CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_BLOCK) *, sk))
-
-#define sk_OPENSSL_BLOCK_is_sorted(sk) \
-  sk_is_sorted(CHECKED_CAST(_STACK *, const STACK_OF(OPENSSL_BLOCK) *, sk))
-
-#define sk_OPENSSL_BLOCK_set_cmp_func(sk, comp)                                \
-  ((int (*)(const OPENSSL_BLOCK **a, const OPENSSL_BLOCK **b))sk_set_cmp_func( \
-      CHECKED_CAST(_STACK *, STACK_OF(OPENSSL_BLOCK) *, sk),                   \
-      CHECKED_CAST(stack_cmp_func,                                             \
-                   int (*)(const OPENSSL_BLOCK **a, const OPENSSL_BLOCK **b),  \
-                   comp)))
-
-#define sk_OPENSSL_BLOCK_deep_copy(sk, copy_func, free_func)             \
-  ((STACK_OF(OPENSSL_BLOCK) *)sk_deep_copy(                              \
-      CHECKED_CAST(const _STACK *, const STACK_OF(OPENSSL_BLOCK) *, sk), \
-      CHECKED_CAST(void *(*)(void *), OPENSSL_BLOCK (*)(OPENSSL_BLOCK),  \
-                   copy_func),                                           \
-      CHECKED_CAST(void (*)(void *), void (*)(OPENSSL_BLOCK), free_func)))
diff --git a/src/include/openssl/thread.h b/src/include/openssl/thread.h
index 568a858..8151484 100644
--- a/src/include/openssl/thread.h
+++ b/src/include/openssl/thread.h
@@ -67,14 +67,15 @@
 
 
 #if defined(OPENSSL_NO_THREADS)
-typedef struct crypto_mutex_st {} CRYPTO_MUTEX;
+typedef struct crypto_mutex_st {
+  char padding;  /* Empty structs have different sizes in C and C++. */
+} CRYPTO_MUTEX;
 #elif defined(OPENSSL_WINDOWS)
 /* CRYPTO_MUTEX can appear in public header files so we really don't want to
  * pull in windows.h. It's statically asserted that this structure is large
- * enough to contain a Windows CRITICAL_SECTION by thread_win.c. */
+ * enough to contain a Windows SRWLOCK by thread_win.c. */
 typedef union crypto_mutex_st {
-  double alignment;
-  uint8_t padding[4*sizeof(void*) + 2*sizeof(int)];
+  void *handle;
 } CRYPTO_MUTEX;
 #elif defined(__MACH__) && defined(__APPLE__)
 typedef pthread_rwlock_t CRYPTO_MUTEX;
@@ -100,7 +101,11 @@
 typedef uint32_t CRYPTO_refcount_t;
 
 
-/* Deprecated functions */
+/* Deprecated functions.
+ *
+ * Historically, OpenSSL required callers to provide locking callbacks.
+ * BoringSSL is thread-safe by default, but some old code calls these functions
+ * and so no-op implementations are provided. */
 
 /* These defines do nothing but are provided to make old code easier to
  * compile. */
@@ -122,6 +127,11 @@
 OPENSSL_EXPORT void CRYPTO_set_add_lock_callback(int (*func)(
     int *num, int amount, int lock_num, const char *file, int line));
 
+/* CRYPTO_get_locking_callback returns NULL. */
+OPENSSL_EXPORT void (*CRYPTO_get_locking_callback(void))(int mode, int lock_num,
+                                                         const char *file,
+                                                         int line);
+
 /* CRYPTO_get_lock_name returns a fixed, dummy string. */
 OPENSSL_EXPORT const char *CRYPTO_get_lock_name(int lock_num);
 
@@ -139,14 +149,7 @@
 /* CRYPTO_THREADID_current does nothing. */
 OPENSSL_EXPORT void CRYPTO_THREADID_current(CRYPTO_THREADID *id);
 
-
-/* Private functions.
- *
- * Some old code calls these functions and so no-op implementations are
- * provided.
- *
- * TODO(fork): cleanup callers and remove. */
-
+/* CRYPTO_set_id_callback does nothing. */
 OPENSSL_EXPORT void CRYPTO_set_id_callback(unsigned long (*func)(void));
 
 typedef struct {
@@ -154,17 +157,32 @@
   struct CRYPTO_dynlock_value *data;
 } CRYPTO_dynlock;
 
+/* CRYPTO_set_dynlock_create_callback does nothing. */
 OPENSSL_EXPORT void CRYPTO_set_dynlock_create_callback(
     struct CRYPTO_dynlock_value *(*dyn_create_function)(const char *file,
                                                         int line));
 
+/* CRYPTO_set_dynlock_lock_callback does nothing. */
 OPENSSL_EXPORT void CRYPTO_set_dynlock_lock_callback(void (*dyn_lock_function)(
     int mode, struct CRYPTO_dynlock_value *l, const char *file, int line));
 
+/* CRYPTO_set_dynlock_destroy_callback does nothing. */
 OPENSSL_EXPORT void CRYPTO_set_dynlock_destroy_callback(
     void (*dyn_destroy_function)(struct CRYPTO_dynlock_value *l,
                                  const char *file, int line));
 
+/* CRYPTO_get_dynlock_create_callback returns NULL. */
+OPENSSL_EXPORT struct CRYPTO_dynlock_value *(
+    *CRYPTO_get_dynlock_create_callback(void))(const char *file, int line);
+
+/* CRYPTO_get_dynlock_lock_callback returns NULL. */
+OPENSSL_EXPORT void (*CRYPTO_get_dynlock_lock_callback(void))(
+    int mode, struct CRYPTO_dynlock_value *l, const char *file, int line);
+
+/* CRYPTO_get_dynlock_destroy_callback returns NULL. */
+OPENSSL_EXPORT void (*CRYPTO_get_dynlock_destroy_callback(void))(
+    struct CRYPTO_dynlock_value *l, const char *file, int line);
+
 
 #if defined(__cplusplus)
 }  /* extern C */
diff --git a/src/include/openssl/tls1.h b/src/include/openssl/tls1.h
index 92d2752..1842ee5 100644
--- a/src/include/openssl/tls1.h
+++ b/src/include/openssl/tls1.h
@@ -157,73 +157,64 @@
 #endif
 
 
-#define TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES 0
-
+#define TLS1_AD_END_OF_EARLY_DATA 1
 #define TLS1_AD_DECRYPTION_FAILED 21
 #define TLS1_AD_RECORD_OVERFLOW 22
-#define TLS1_AD_UNKNOWN_CA 48    /* fatal */
-#define TLS1_AD_ACCESS_DENIED 49 /* fatal */
-#define TLS1_AD_DECODE_ERROR 50  /* fatal */
+#define TLS1_AD_UNKNOWN_CA 48
+#define TLS1_AD_ACCESS_DENIED 49
+#define TLS1_AD_DECODE_ERROR 50
 #define TLS1_AD_DECRYPT_ERROR 51
-#define TLS1_AD_EXPORT_RESTRICTION 60    /* fatal */
-#define TLS1_AD_PROTOCOL_VERSION 70      /* fatal */
-#define TLS1_AD_INSUFFICIENT_SECURITY 71 /* fatal */
-#define TLS1_AD_INTERNAL_ERROR 80        /* fatal */
+#define TLS1_AD_EXPORT_RESTRICTION 60
+#define TLS1_AD_PROTOCOL_VERSION 70
+#define TLS1_AD_INSUFFICIENT_SECURITY 71
+#define TLS1_AD_INTERNAL_ERROR 80
 #define TLS1_AD_USER_CANCELLED 90
 #define TLS1_AD_NO_RENEGOTIATION 100
+#define TLS1_AD_MISSING_EXTENSION 109
 /* codes 110-114 are from RFC3546 */
 #define TLS1_AD_UNSUPPORTED_EXTENSION 110
 #define TLS1_AD_CERTIFICATE_UNOBTAINABLE 111
 #define TLS1_AD_UNRECOGNIZED_NAME 112
 #define TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE 113
 #define TLS1_AD_BAD_CERTIFICATE_HASH_VALUE 114
-#define TLS1_AD_UNKNOWN_PSK_IDENTITY 115 /* fatal */
+#define TLS1_AD_UNKNOWN_PSK_IDENTITY 115
+#define TLS1_AD_CERTIFICATE_REQUIRED 116
 
-/* ExtensionType values from RFC3546 / RFC4366 / RFC6066 */
+/* ExtensionType values from RFC6066 */
 #define TLSEXT_TYPE_server_name 0
-#define TLSEXT_TYPE_max_fragment_length 1
-#define TLSEXT_TYPE_client_certificate_url 2
-#define TLSEXT_TYPE_trusted_ca_keys 3
-#define TLSEXT_TYPE_truncated_hmac 4
 #define TLSEXT_TYPE_status_request 5
-/* ExtensionType values from RFC4681 */
-#define TLSEXT_TYPE_user_mapping 6
-
-/* ExtensionType values from RFC5878 */
-#define TLSEXT_TYPE_client_authz 7
-#define TLSEXT_TYPE_server_authz 8
-
-/* ExtensionType values from RFC6091 */
-#define TLSEXT_TYPE_cert_type 9
 
 /* ExtensionType values from RFC4492 */
-#define TLSEXT_TYPE_elliptic_curves 10
 #define TLSEXT_TYPE_ec_point_formats 11
 
-/* ExtensionType value from RFC5054 */
-#define TLSEXT_TYPE_srp 12
-
 /* ExtensionType values from RFC5246 */
 #define TLSEXT_TYPE_signature_algorithms 13
 
 /* ExtensionType value from RFC5764 */
 #define TLSEXT_TYPE_srtp 14
 
-/* ExtensionType value from RFC5620 */
-#define TLSEXT_TYPE_heartbeat 15
-
 /* ExtensionType value from RFC7301 */
 #define TLSEXT_TYPE_application_layer_protocol_negotiation 16
 
 /* ExtensionType value from RFC7685 */
 #define TLSEXT_TYPE_padding 21
 
-/* https://tools.ietf.org/html/draft-ietf-tls-session-hash-01 */
+/* ExtensionType value from RFC7627 */
 #define TLSEXT_TYPE_extended_master_secret 23
 
 /* ExtensionType value from RFC4507 */
 #define TLSEXT_TYPE_session_ticket 35
 
+/* ExtensionType values from draft-ietf-tls-tls13-18 */
+#define TLSEXT_TYPE_supported_groups 10
+#define TLSEXT_TYPE_key_share 40
+#define TLSEXT_TYPE_pre_shared_key 41
+#define TLSEXT_TYPE_early_data 42
+#define TLSEXT_TYPE_supported_versions 43
+#define TLSEXT_TYPE_cookie 44
+#define TLSEXT_TYPE_psk_key_exchange_modes 45
+#define TLSEXT_TYPE_ticket_early_data_info 46
+
 /* ExtensionType value from RFC5746 */
 #define TLSEXT_TYPE_renegotiate 0xff01
 
@@ -242,7 +233,6 @@
 /* ECPointFormat values from RFC 4492 */
 #define TLSEXT_ECPOINTFORMAT_uncompressed 0
 #define TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime 1
-#define TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2 2
 
 /* Signature and hash algorithms from RFC 5246 */
 
@@ -259,15 +249,6 @@
 #define TLSEXT_hash_sha384 5
 #define TLSEXT_hash_sha512 6
 
-/* Flag set for unrecognised algorithms */
-#define TLSEXT_nid_unknown 0x1000000
-
-/* ECC curves */
-
-#define TLSEXT_curve_P_256 23
-#define TLSEXT_curve_P_384 24
-
-
 #define TLSEXT_MAXLEN_host_name 255
 
 /* PSK ciphersuites from 4279 */
@@ -427,17 +408,15 @@
 #define TLS1_CK_ECDH_RSA_WITH_AES_128_GCM_SHA256 0x0300C031
 #define TLS1_CK_ECDH_RSA_WITH_AES_256_GCM_SHA384 0x0300C032
 
-#define TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD 0x0300CC13
-#define TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD 0x0300CC14
-
+/* ChaCha20-Poly1305 cipher suites from RFC 7905. */
 #define TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 0x0300CCA8
 #define TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0x0300CCA9
 #define TLS1_CK_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 0x0300CCAC
 
-/* TODO(davidben): Remove this. Historically, the CK names for CHACHA20_POLY1305
- * were missing 'WITH' and 'SHA256'. */
-#define TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305 \
-  TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
+/* TLS 1.3 ciphersuites from draft-ietf-tls-tls13-16 */
+#define TLS1_CK_AES_128_GCM_SHA256 0x03001301
+#define TLS1_CK_AES_256_GCM_SHA384 0x03001302
+#define TLS1_CK_CHACHA20_POLY1305_SHA256 0x03001303
 
 /* XXX
  * Inconsistency alert:
@@ -599,14 +578,6 @@
 #define TLS1_TXT_ECDH_RSA_WITH_AES_128_GCM_SHA256 "ECDH-RSA-AES128-GCM-SHA256"
 #define TLS1_TXT_ECDH_RSA_WITH_AES_256_GCM_SHA384 "ECDH-RSA-AES256-GCM-SHA384"
 
-/* For convenience, the old and new CHACHA20_POLY1305 ciphers have the same
- * name. In cipher strings, both will be selected. This is temporary and will be
- * removed when the pre-standard construction is removed. */
-#define TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305_OLD \
-  "ECDHE-RSA-CHACHA20-POLY1305"
-#define TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_OLD \
-  "ECDHE-ECDSA-CHACHA20-POLY1305"
-
 #define TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 \
   "ECDHE-RSA-CHACHA20-POLY1305"
 #define TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 \
@@ -614,10 +585,11 @@
 #define TLS1_TXT_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 \
   "ECDHE-PSK-CHACHA20-POLY1305"
 
-/* TODO(davidben): Remove this. Historically, the TXT names for CHACHA20_POLY1305
- * were missing 'SHA256'. */
-#define TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305 \
-  TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
+/* TLS 1.3 ciphersuites from draft-ietf-tls-tls13-16 */
+#define TLS1_TXT_AES_128_GCM_SHA256 "AEAD-AES128-GCM-SHA256"
+#define TLS1_TXT_AES_256_GCM_SHA384 "AEAD-AES256-GCM-SHA384"
+#define TLS1_TXT_CHACHA20_POLY1305_SHA256 "AEAD-CHACHA20-POLY1305-SHA256"
+
 
 #define TLS_CT_RSA_SIGN 1
 #define TLS_CT_DSS_SIGN 2
diff --git a/src/include/openssl/type_check.h b/src/include/openssl/type_check.h
index 674913a..7e70918 100644
--- a/src/include/openssl/type_check.h
+++ b/src/include/openssl/type_check.h
@@ -78,6 +78,10 @@
 
 #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
 #define OPENSSL_COMPILE_ASSERT(cond, msg) _Static_assert(cond, #msg)
+#elif defined(__GNUC__)
+#define OPENSSL_COMPILE_ASSERT(cond, msg)                      \
+  typedef char OPENSSL_COMPILE_ASSERT_##msg[((cond) ? 1 : -1)] \
+      __attribute__((unused))
 #else
 #define OPENSSL_COMPILE_ASSERT(cond, msg) \
   typedef char OPENSSL_COMPILE_ASSERT_##msg[((cond) ? 1 : -1)]
diff --git a/src/include/openssl/x509.h b/src/include/openssl/x509.h
index a5aaf31..88455dd 100644
--- a/src/include/openssl/x509.h
+++ b/src/include/openssl/x509.h
@@ -76,6 +76,8 @@
 #include <openssl/ecdsa.h>
 #include <openssl/ec.h>
 #include <openssl/evp.h>
+#include <openssl/obj.h>
+#include <openssl/pool.h>
 #include <openssl/rsa.h>
 #include <openssl/sha.h>
 #include <openssl/stack.h>
@@ -242,7 +244,6 @@
 	X509_CINF *cert_info;
 	X509_ALGOR *sig_alg;
 	ASN1_BIT_STRING *signature;
-	int valid;
 	CRYPTO_refcount_t references;
 	char *name;
 	CRYPTO_EX_DATA ex_data;
@@ -261,6 +262,8 @@
 	NAME_CONSTRAINTS *nc;
 	unsigned char sha1_hash[SHA_DIGEST_LENGTH];
 	X509_CERT_AUX *aux;
+	CRYPTO_BUFFER *buf;
+	CRYPTO_MUTEX lock;
 	} /* X509 */;
 
 DECLARE_STACK_OF(X509)
@@ -286,7 +289,7 @@
 
 /* standard trust ids */
 
-#define X509_TRUST_DEFAULT	-1	/* Only valid in purpose settings */
+#define X509_TRUST_DEFAULT	(-1)	/* Only valid in purpose settings */
 
 #define X509_TRUST_COMPAT	1
 #define X509_TRUST_SSL_CLIENT	2
@@ -506,28 +509,6 @@
 	} CBC_PARAM;
 */
 
-/* Password based encryption structure */
-
-struct PBEPARAM_st {
-ASN1_OCTET_STRING *salt;
-ASN1_INTEGER *iter;
-} /* PBEPARAM */;
-
-/* Password based encryption V2 structures */
-
-struct PBE2PARAM_st {
-X509_ALGOR *keyfunc;
-X509_ALGOR *encryption;
-} /* PBE2PARAM */;
-
-struct PBKDF2PARAM_st {
-ASN1_TYPE *salt;	/* Usually OCTET STRING but could be anything */
-ASN1_INTEGER *iter;
-ASN1_INTEGER *keylength;
-X509_ALGOR *prf;
-} /* PBKDF2PARAM */;
-
-
 /* PKCS#8 private key info structure */
 
 struct pkcs8_priv_key_info_st
@@ -636,6 +617,12 @@
 		unsigned char *md, unsigned int *len);
 #endif
 
+/* X509_parse_from_buffer parses an X.509 structure from |buf| and returns a
+ * fresh X509 or NULL on error. There must not be any trailing data in |buf|.
+ * The returned structure (if any) holds a reference to |buf| rather than
+ * copying parts of it as a normal |d2i_X509| call would do. */
+OPENSSL_EXPORT X509 *X509_parse_from_buffer(CRYPTO_BUFFER *buf);
+
 #ifndef OPENSSL_NO_FP_API
 OPENSSL_EXPORT X509 *d2i_X509_fp(FILE *fp, X509 **x509);
 OPENSSL_EXPORT int i2d_X509_fp(FILE *fp,X509 *x509);
@@ -781,9 +768,8 @@
 
 DECLARE_ASN1_FUNCTIONS(X509_CERT_PAIR)
 
-/* X509_up_ref adds one to the reference count of |x| and returns
- * |x|. */
-OPENSSL_EXPORT X509 *X509_up_ref(X509 *x);
+/* X509_up_ref adds one to the reference count of |x| and returns one. */
+OPENSSL_EXPORT int X509_up_ref(X509 *x);
 
 OPENSSL_EXPORT int X509_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused,
 	     CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
@@ -858,6 +844,7 @@
 OPENSSL_EXPORT EVP_PKEY *	X509_get_pubkey(X509 *x);
 OPENSSL_EXPORT ASN1_BIT_STRING * X509_get0_pubkey_bitstr(const X509 *x);
 OPENSSL_EXPORT int		X509_certificate_type(X509 *x,EVP_PKEY *pubkey /* optional */);
+OPENSSL_EXPORT STACK_OF(X509_EXTENSION) *X509_get0_extensions(const X509 *x);
 
 OPENSSL_EXPORT int		X509_REQ_set_version(X509_REQ *x,long version);
 OPENSSL_EXPORT int		X509_REQ_set_subject_name(X509_REQ *req,X509_NAME *name);
@@ -893,7 +880,7 @@
 OPENSSL_EXPORT int X509_CRL_set_lastUpdate(X509_CRL *x, const ASN1_TIME *tm);
 OPENSSL_EXPORT int X509_CRL_set_nextUpdate(X509_CRL *x, const ASN1_TIME *tm);
 OPENSSL_EXPORT int X509_CRL_sort(X509_CRL *crl);
-OPENSSL_EXPORT void X509_CRL_up_ref(X509_CRL *crl);
+OPENSSL_EXPORT int X509_CRL_up_ref(X509_CRL *crl);
 
 OPENSSL_EXPORT int X509_REVOKED_set_serialNumber(X509_REVOKED *x, ASN1_INTEGER *serial);
 OPENSSL_EXPORT int X509_REVOKED_set_revocationDate(X509_REVOKED *r, ASN1_TIME *tm);
@@ -1074,24 +1061,6 @@
 OPENSSL_EXPORT ASN1_OBJECT *X509_ATTRIBUTE_get0_object(X509_ATTRIBUTE *attr);
 OPENSSL_EXPORT ASN1_TYPE *X509_ATTRIBUTE_get0_type(X509_ATTRIBUTE *attr, int idx);
 
-OPENSSL_EXPORT int EVP_PKEY_get_attr_count(const EVP_PKEY *key);
-OPENSSL_EXPORT int EVP_PKEY_get_attr_by_NID(const EVP_PKEY *key, int nid,
-			  int lastpos);
-OPENSSL_EXPORT int EVP_PKEY_get_attr_by_OBJ(const EVP_PKEY *key, ASN1_OBJECT *obj,
-			  int lastpos);
-OPENSSL_EXPORT X509_ATTRIBUTE *EVP_PKEY_get_attr(const EVP_PKEY *key, int loc);
-OPENSSL_EXPORT X509_ATTRIBUTE *EVP_PKEY_delete_attr(EVP_PKEY *key, int loc);
-OPENSSL_EXPORT int EVP_PKEY_add1_attr(EVP_PKEY *key, X509_ATTRIBUTE *attr);
-OPENSSL_EXPORT int EVP_PKEY_add1_attr_by_OBJ(EVP_PKEY *key,
-			const ASN1_OBJECT *obj, int type,
-			const unsigned char *bytes, int len);
-OPENSSL_EXPORT int EVP_PKEY_add1_attr_by_NID(EVP_PKEY *key,
-			int nid, int type,
-			const unsigned char *bytes, int len);
-OPENSSL_EXPORT int EVP_PKEY_add1_attr_by_txt(EVP_PKEY *key,
-			const char *attrname, int type,
-			const unsigned char *bytes, int len);
-
 OPENSSL_EXPORT int		X509_verify_cert(X509_STORE_CTX *ctx);
 
 /* lookup a cert from a X509 STACK */
@@ -1099,24 +1068,6 @@
 				     ASN1_INTEGER *serial);
 OPENSSL_EXPORT X509 *X509_find_by_subject(STACK_OF(X509) *sk,X509_NAME *name);
 
-DECLARE_ASN1_FUNCTIONS(PBEPARAM)
-DECLARE_ASN1_FUNCTIONS(PBE2PARAM)
-DECLARE_ASN1_FUNCTIONS(PBKDF2PARAM)
-
-OPENSSL_EXPORT int PKCS5_pbe_set0_algor(X509_ALGOR *algor, int alg, int iter,
-				const unsigned char *salt, int saltlen);
-
-OPENSSL_EXPORT X509_ALGOR *PKCS5_pbe_set(int alg, int iter,
-				const unsigned char *salt, int saltlen);
-OPENSSL_EXPORT X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter,
-					 unsigned char *salt, int saltlen);
-OPENSSL_EXPORT X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter,
-				 unsigned char *salt, int saltlen,
-				 unsigned char *aiv, int prf_nid);
-
-OPENSSL_EXPORT X509_ALGOR *PKCS5_pbkdf2_set(int iter, unsigned char *salt, int saltlen,
-				int prf_nid, int keylen);
-
 /* PKCS#8 utilities */
 
 DECLARE_ASN1_FUNCTIONS(PKCS8_PRIV_KEY_INFO)
@@ -1153,6 +1104,17 @@
 OPENSSL_EXPORT char *X509_TRUST_get0_name(X509_TRUST *xp);
 OPENSSL_EXPORT int X509_TRUST_get_trust(X509_TRUST *xp);
 
+
+typedef struct rsa_pss_params_st {
+  X509_ALGOR *hashAlgorithm;
+  X509_ALGOR *maskGenAlgorithm;
+  ASN1_INTEGER *saltLength;
+  ASN1_INTEGER *trailerField;
+} RSA_PSS_PARAMS;
+
+DECLARE_ASN1_FUNCTIONS(RSA_PSS_PARAMS)
+
+
 /* PKCS7_get_certificates parses a PKCS#7, SignedData structure from |cbs| and
  * appends the included certificates to |out_certs|. It returns one on success
  * and zero on error. */
@@ -1213,6 +1175,39 @@
 
 #ifdef  __cplusplus
 }
+
+extern "C++" {
+
+namespace bssl {
+
+BORINGSSL_MAKE_STACK_DELETER(X509, X509_free)
+BORINGSSL_MAKE_STACK_DELETER(X509_CRL, X509_CRL_free)
+BORINGSSL_MAKE_STACK_DELETER(X509_EXTENSION, X509_EXTENSION_free)
+BORINGSSL_MAKE_STACK_DELETER(X509_NAME, X509_NAME_free)
+
+BORINGSSL_MAKE_DELETER(NETSCAPE_SPKI, NETSCAPE_SPKI_free)
+BORINGSSL_MAKE_DELETER(X509, X509_free)
+BORINGSSL_MAKE_DELETER(X509_ALGOR, X509_ALGOR_free)
+BORINGSSL_MAKE_DELETER(X509_CRL, X509_CRL_free)
+BORINGSSL_MAKE_DELETER(X509_CRL_METHOD, X509_CRL_METHOD_free)
+BORINGSSL_MAKE_DELETER(X509_EXTENSION, X509_EXTENSION_free)
+BORINGSSL_MAKE_DELETER(X509_INFO, X509_INFO_free)
+BORINGSSL_MAKE_DELETER(X509_LOOKUP, X509_LOOKUP_free)
+BORINGSSL_MAKE_DELETER(X509_NAME, X509_NAME_free)
+BORINGSSL_MAKE_DELETER(X509_NAME_ENTRY, X509_NAME_ENTRY_free)
+BORINGSSL_MAKE_DELETER(X509_PKEY, X509_PKEY_free)
+BORINGSSL_MAKE_DELETER(X509_POLICY_TREE, X509_policy_tree_free)
+BORINGSSL_MAKE_DELETER(X509_REQ, X509_REQ_free)
+BORINGSSL_MAKE_DELETER(X509_REVOKED, X509_REVOKED_free)
+BORINGSSL_MAKE_DELETER(X509_SIG, X509_SIG_free)
+BORINGSSL_MAKE_DELETER(X509_STORE, X509_STORE_free)
+BORINGSSL_MAKE_DELETER(X509_STORE_CTX, X509_STORE_CTX_free)
+BORINGSSL_MAKE_DELETER(X509_VERIFY_PARAM, X509_VERIFY_PARAM_free)
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #define X509_R_AKID_MISMATCH 100
@@ -1227,30 +1222,29 @@
 #define X509_R_INVALID_BIT_STRING_BITS_LEFT 109
 #define X509_R_INVALID_DIRECTORY 110
 #define X509_R_INVALID_FIELD_NAME 111
-#define X509_R_INVALID_TRUST 112
-#define X509_R_ISSUER_MISMATCH 113
-#define X509_R_KEY_TYPE_MISMATCH 114
-#define X509_R_KEY_VALUES_MISMATCH 115
-#define X509_R_LOADING_CERT_DIR 116
-#define X509_R_LOADING_DEFAULTS 117
-#define X509_R_METHOD_NOT_SUPPORTED 118
+#define X509_R_INVALID_PSS_PARAMETERS 112
+#define X509_R_INVALID_TRUST 113
+#define X509_R_ISSUER_MISMATCH 114
+#define X509_R_KEY_TYPE_MISMATCH 115
+#define X509_R_KEY_VALUES_MISMATCH 116
+#define X509_R_LOADING_CERT_DIR 117
+#define X509_R_LOADING_DEFAULTS 118
 #define X509_R_NEWER_CRL_NOT_NEWER 119
 #define X509_R_NOT_PKCS7_SIGNED_DATA 120
 #define X509_R_NO_CERTIFICATES_INCLUDED 121
 #define X509_R_NO_CERT_SET_FOR_US_TO_VERIFY 122
-#define X509_R_NO_CRL_NUMBER 123
-#define X509_R_PUBLIC_KEY_DECODE_ERROR 124
-#define X509_R_PUBLIC_KEY_ENCODE_ERROR 125
-#define X509_R_SHOULD_RETRY 126
-#define X509_R_UNABLE_TO_FIND_PARAMETERS_IN_CHAIN 127
-#define X509_R_UNABLE_TO_GET_CERTS_PUBLIC_KEY 128
-#define X509_R_UNKNOWN_KEY_TYPE 129
-#define X509_R_UNKNOWN_NID 130
-#define X509_R_UNKNOWN_PURPOSE_ID 131
-#define X509_R_UNKNOWN_TRUST_ID 132
-#define X509_R_UNSUPPORTED_ALGORITHM 133
-#define X509_R_WRONG_LOOKUP_TYPE 134
-#define X509_R_WRONG_TYPE 135
-#define X509_R_NO_CRLS_INCLUDED 136
+#define X509_R_NO_CRLS_INCLUDED 123
+#define X509_R_NO_CRL_NUMBER 124
+#define X509_R_PUBLIC_KEY_DECODE_ERROR 125
+#define X509_R_PUBLIC_KEY_ENCODE_ERROR 126
+#define X509_R_SHOULD_RETRY 127
+#define X509_R_UNKNOWN_KEY_TYPE 128
+#define X509_R_UNKNOWN_NID 129
+#define X509_R_UNKNOWN_PURPOSE_ID 130
+#define X509_R_UNKNOWN_TRUST_ID 131
+#define X509_R_UNSUPPORTED_ALGORITHM 132
+#define X509_R_WRONG_LOOKUP_TYPE 133
+#define X509_R_WRONG_TYPE 134
+#define X509_R_NAME_TOO_LONG 135
 
 #endif
diff --git a/src/include/openssl/x509_vfy.h b/src/include/openssl/x509_vfy.h
index b39ef49..f069cb2 100644
--- a/src/include/openssl/x509_vfy.h
+++ b/src/include/openssl/x509_vfy.h
@@ -109,8 +109,10 @@
 certificate chain.
 */
 
-#define X509_LU_RETRY		-1
+/* The following are legacy constants that should not be used. */
+#define X509_LU_RETRY		(-1)
 #define X509_LU_FAIL		0
+
 #define X509_LU_X509		1
 #define X509_LU_CRL		2
 #define X509_LU_PKEY		3
@@ -127,8 +129,6 @@
 		} data;
 	} X509_OBJECT;
 
-typedef struct x509_lookup_st X509_LOOKUP;
-
 DECLARE_STACK_OF(X509_LOOKUP)
 DECLARE_STACK_OF(X509_OBJECT)
 
@@ -160,7 +160,7 @@
  * parameters used can be customized
  */
 
-typedef struct X509_VERIFY_PARAM_st
+struct X509_VERIFY_PARAM_st
 	{
 	char *name;
 	time_t check_time;	/* Time to use */
@@ -171,7 +171,7 @@
 	int depth;		/* Verify depth */
 	STACK_OF(ASN1_OBJECT) *policies;	/* Permissible policies */
 	X509_VERIFY_PARAM_ID *id;	/* opaque ID data */
-	} X509_VERIFY_PARAM;
+	};
 
 DECLARE_STACK_OF(X509_VERIFY_PARAM)
 
@@ -184,6 +184,7 @@
 	int cache; 	/* if true, stash any hits */
 	STACK_OF(X509_OBJECT) *objs;	/* Cache of all objects */
 	CRYPTO_MUTEX objs_lock;
+	STACK_OF(X509) *additional_untrusted;
 
 	/* These are external lookup methods */
 	STACK_OF(X509_LOOKUP) *get_cert_methods;
@@ -228,7 +229,6 @@
 struct x509_store_ctx_st      /* X509_STORE_CTX */
 	{
 	X509_STORE *ctx;
-	int current_method;	/* used when looking up certs */
 
 	/* The following are set by the caller */
 	X509 *cert;		/* The cert to check */
@@ -292,7 +292,7 @@
 		X509_LOOKUP_ctrl((x),X509_L_ADD_DIR,(name),(long)(type),NULL)
 
 #define		X509_V_OK					0
-/* illegal error (for uninitialized values, to avoid X509_V_OK): 1 */
+#define		X509_V_ERR_UNSPECIFIED				1
 
 #define		X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT		2
 #define		X509_V_ERR_UNABLE_TO_GET_CRL			3
@@ -347,6 +347,7 @@
 #define		X509_V_ERR_PERMITTED_VIOLATION			47
 #define		X509_V_ERR_EXCLUDED_VIOLATION			48
 #define		X509_V_ERR_SUBTREE_MINMAX			49
+#define		X509_V_ERR_APPLICATION_VERIFICATION		50
 #define		X509_V_ERR_UNSUPPORTED_CONSTRAINT_TYPE		51
 #define		X509_V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX	52
 #define		X509_V_ERR_UNSUPPORTED_NAME_SYNTAX		53
@@ -365,8 +366,10 @@
 #define		X509_V_ERR_EMAIL_MISMATCH			63
 #define		X509_V_ERR_IP_ADDRESS_MISMATCH			64
 
-/* The application is not happy */
-#define		X509_V_ERR_APPLICATION_VERIFICATION		50
+/* Caller error */
+#define		X509_V_ERR_INVALID_CALL				65
+/* Issuer lookup error */
+#define		X509_V_ERR_STORE_LOOKUP				66
 
 /* Certificate verify flags */
 
@@ -412,6 +415,11 @@
 /* Allow partial chains if at least one certificate is in trusted store */
 #define X509_V_FLAG_PARTIAL_CHAIN		0x80000
 
+/* If the initial chain is not trusted, do not attempt to build an alternative
+ * chain. Alternate chain checking was introduced in 1.0.2b. Setting this flag
+ * will force the behaviour to match that of previous versions. */
+#define X509_V_FLAG_NO_ALT_CHAINS		0x100000
+
 #define X509_VP_FLAG_DEFAULT			0x1
 #define X509_VP_FLAG_OVERWRITE			0x2
 #define X509_VP_FLAG_RESET_FLAGS		0x4
@@ -428,9 +436,10 @@
 	     X509_NAME *name);
 OPENSSL_EXPORT X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h,int type,X509_NAME *name);
 OPENSSL_EXPORT X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h, X509_OBJECT *x);
-OPENSSL_EXPORT void X509_OBJECT_up_ref_count(X509_OBJECT *a);
+OPENSSL_EXPORT int X509_OBJECT_up_ref_count(X509_OBJECT *a);
 OPENSSL_EXPORT void X509_OBJECT_free_contents(X509_OBJECT *a);
 OPENSSL_EXPORT X509_STORE *X509_STORE_new(void );
+OPENSSL_EXPORT int X509_STORE_up_ref(X509_STORE *store);
 OPENSSL_EXPORT void X509_STORE_free(X509_STORE *v);
 
 OPENSSL_EXPORT STACK_OF(X509)* X509_STORE_get1_certs(X509_STORE_CTX *st, X509_NAME *nm);
@@ -439,6 +448,11 @@
 OPENSSL_EXPORT int X509_STORE_set_purpose(X509_STORE *ctx, int purpose);
 OPENSSL_EXPORT int X509_STORE_set_trust(X509_STORE *ctx, int trust);
 OPENSSL_EXPORT int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *pm);
+/* X509_STORE_set0_additional_untrusted sets a stack of additional, untrusted
+ * certificates that are available for chain building. This function does not
+ * take ownership of the stack. */
+OPENSSL_EXPORT void X509_STORE_set0_additional_untrusted(
+    X509_STORE *ctx, STACK_OF(X509) *untrusted);
 
 OPENSSL_EXPORT void X509_STORE_set_verify_cb(X509_STORE *ctx,
 				  int (*verify_cb)(int, X509_STORE_CTX *));
@@ -608,4 +622,3 @@
 }
 #endif
 #endif
-
diff --git a/src/include/openssl/x509v3.h b/src/include/openssl/x509v3.h
index b7b8ba7..4754f71 100644
--- a/src/include/openssl/x509v3.h
+++ b/src/include/openssl/x509v3.h
@@ -146,10 +146,10 @@
 
 typedef BIT_STRING_BITNAME ENUMERATED_NAMES;
 
-typedef struct BASIC_CONSTRAINTS_st {
+struct BASIC_CONSTRAINTS_st {
 int ca;
 ASN1_INTEGER *pathlen;
-} BASIC_CONSTRAINTS;
+};
 
 
 typedef struct PKEY_USAGE_PERIOD_st {
@@ -230,7 +230,7 @@
 /* All existing reasons */
 #define CRLDP_ALL_REASONS	0x807f
 
-#define CRL_REASON_NONE				-1
+#define CRL_REASON_NONE				(-1)
 #define CRL_REASON_UNSPECIFIED			0
 #define CRL_REASON_KEY_COMPROMISE		1
 #define CRL_REASON_CA_COMPROMISE		2
@@ -376,8 +376,8 @@
 /* onlysomereasons present */
 #define IDP_REASONS	0x40
 
-#define X509V3_conf_err(val) ERR_add_error_data(6, "section:", val->section, \
-",name:", val->name, ",value:", val->value);
+#define X509V3_conf_err(val) ERR_add_error_data(6, "section:", (val)->section, \
+",name:", (val)->name, ",value:", (val)->value);
 
 #define X509V3_set_ctx_test(ctx) \
 			X509V3_set_ctx(ctx, NULL, NULL, NULL, NULL, CTX_TEST)
@@ -389,7 +389,7 @@
 			(X509V3_EXT_I2V)i2v_ASN1_BIT_STRING, \
 			(X509V3_EXT_V2I)v2i_ASN1_BIT_STRING, \
 			NULL, NULL, \
-			(void *)table}
+			(void *)(table)}
 
 #define EXT_IA5STRING(nid) { nid, 0, ASN1_ITEM_ref(ASN1_IA5STRING), \
 			0,0,0,0, \
@@ -600,6 +600,7 @@
 				  X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc);
 OPENSSL_EXPORT void X509V3_conf_free(CONF_VALUE *val);
 
+OPENSSL_EXPORT X509_EXTENSION *X509V3_EXT_conf_nid(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx, int ext_nid, char *value);
 OPENSSL_EXPORT X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid, char *value);
 OPENSSL_EXPORT X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, char *name, char *value);
 OPENSSL_EXPORT int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, char *section, STACK_OF(X509_EXTENSION) **sk);
@@ -646,6 +647,7 @@
 OPENSSL_EXPORT STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line);
 OPENSSL_EXPORT void *X509V3_EXT_d2i(X509_EXTENSION *ext);
 OPENSSL_EXPORT void *X509V3_get_d2i(STACK_OF(X509_EXTENSION) *x, int nid, int *crit, int *idx);
+OPENSSL_EXPORT int X509V3_EXT_free(int nid, void *ext_data);
 
 
 OPENSSL_EXPORT X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc);
@@ -730,7 +732,26 @@
 
 #ifdef  __cplusplus
 }
+
+extern "C++" {
+
+namespace bssl {
+
+BORINGSSL_MAKE_STACK_DELETER(DIST_POINT, DIST_POINT_free)
+BORINGSSL_MAKE_STACK_DELETER(GENERAL_NAME, GENERAL_NAME_free)
+// A STACK_OF(POLICYINFO) is also known as a CERTIFICATEPOLICIES.
+BORINGSSL_MAKE_STACK_DELETER(POLICYINFO, POLICYINFO_free)
+
+BORINGSSL_MAKE_DELETER(AUTHORITY_KEYID, AUTHORITY_KEYID_free)
+BORINGSSL_MAKE_DELETER(BASIC_CONSTRAINTS, BASIC_CONSTRAINTS_free)
+BORINGSSL_MAKE_DELETER(DIST_POINT, DIST_POINT_free)
+BORINGSSL_MAKE_DELETER(GENERAL_NAME, GENERAL_NAME_free)
+
+}  // namespace bssl
+
+}  /* extern C++ */
 #endif
+
 #define X509V3_R_BAD_IP_ADDRESS 100
 #define X509V3_R_BAD_OBJECT 101
 #define X509V3_R_BN_DEC2BN_ERROR 102
diff --git a/src/infra/config/README.md b/src/infra/config/README.md
new file mode 100644
index 0000000..fa0bbc4
--- /dev/null
+++ b/src/infra/config/README.md
@@ -0,0 +1,6 @@
+Infrastructure location.
+
+This contains Commit Queue config for automatic testing of changes before they
+are committed.
+
+Initial set up bug: http://crbug.com/618641.
diff --git a/src/infra/config/cq.cfg b/src/infra/config/cq.cfg
new file mode 100644
index 0000000..c202d33
--- /dev/null
+++ b/src/infra/config/cq.cfg
@@ -0,0 +1,56 @@
+# See http://luci-config.appspot.com/schemas/projects/refs:cq.cfg for the
+# documentation of this file format.
+version: 1
+cq_name: "boringssl"
+git_repo_url: "https://boringssl.googlesource.com/boringssl"
+cq_status_url: "https://chromium-cq-status.appspot.com"
+gerrit {
+	cq_verified_label: "CQ-Verified"
+}
+verifiers {
+  try_job {
+    buckets {
+      name: "client.boringssl"
+
+			builders {
+        name: "android_aarch64"
+        experiment_percentage: 1
+      }
+			builders {
+        name: "android_aarch64_rel"
+        experiment_percentage: 1
+      }
+			builders {
+        name: "android_arm"
+        experiment_percentage: 1
+      }
+			builders {
+        name: "android_arm_rel"
+        experiment_percentage: 1
+      }
+
+			builders { name: "linux" }
+			builders { name: "linux32" }
+			builders { name: "linux32_rel" }
+			builders { name: "linux_clang_rel" }
+			builders { name: "linux_noasm_asan" }
+			builders { name: "linux_nothreads" }
+			builders { name: "linux_rel" }
+			builders { name: "linux_shared" }
+			builders { name: "linux_small" }
+
+			builders { name: "mac" }
+			builders { name: "mac_rel" }
+			builders { name: "mac_small" }
+
+			builders { name: "win32" }
+			builders { name: "win32_rel" }
+			builders { name: "win32_small" }
+			builders { name: "win64" }
+			builders { name: "win64_rel" }
+			builders { name: "win64_small" }
+
+			builders { name: "docs" }
+    }
+  }
+}
diff --git a/src/ssl/CMakeLists.txt b/src/ssl/CMakeLists.txt
index c82cb9b..3e9cd40 100644
--- a/src/ssl/CMakeLists.txt
+++ b/src/ssl/CMakeLists.txt
@@ -1,26 +1,21 @@
 include_directories(../include)
 
-add_subdirectory(pqueue)
-
 add_library(
   ssl
 
+  bio_ssl.c
   custom_extensions.c
   d1_both.c
-  d1_clnt.c
   d1_lib.c
-  d1_meth.c
   d1_pkt.c
   d1_srtp.c
-  d1_srvr.c
+  dtls_method.c
   dtls_record.c
+  handshake_client.c
+  handshake_server.c
   s3_both.c
-  s3_clnt.c
-  s3_enc.c
   s3_lib.c
-  s3_meth.c
   s3_pkt.c
-  s3_srvr.c
   ssl_aead_ctx.c
   ssl_asn1.c
   ssl_buffer.c
@@ -29,14 +24,20 @@
   ssl_ecdh.c
   ssl_file.c
   ssl_lib.c
-  ssl_rsa.c
+  ssl_privkey.c
+  ssl_privkey_cc.cc
   ssl_session.c
   ssl_stat.c
+  ssl_transcript.c
+  ssl_x509.c
   t1_enc.c
   t1_lib.c
+  tls_method.c
   tls_record.c
-
-  $<TARGET_OBJECTS:pqueue>
+  tls13_both.c
+  tls13_client.c
+  tls13_enc.c
+  tls13_server.c
 )
 
 target_link_libraries(ssl crypto)
@@ -46,8 +47,12 @@
 
   ssl_test.cc
 
+  $<TARGET_OBJECTS:gtest_main>
   $<TARGET_OBJECTS:test_support>
 )
 
-target_link_libraries(ssl_test ssl crypto)
+target_link_libraries(ssl_test ssl crypto gtest)
+if (WIN32)
+  target_link_libraries(ssl_test ws2_32)
+endif()
 add_dependencies(all_tests ssl_test)
diff --git a/src/ssl/bio_ssl.c b/src/ssl/bio_ssl.c
new file mode 100644
index 0000000..ad8f5d8
--- /dev/null
+++ b/src/ssl/bio_ssl.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/ssl.h>
+
+#include <openssl/bio.h>
+
+
+static int ssl_read(BIO *bio, char *out, int outl) {
+  SSL *ssl = bio->ptr;
+  if (ssl == NULL) {
+    return 0;
+  }
+
+  BIO_clear_retry_flags(bio);
+
+  const int ret = SSL_read(ssl, out, outl);
+
+  switch (SSL_get_error(ssl, ret)) {
+    case SSL_ERROR_WANT_READ:
+      BIO_set_retry_read(bio);
+      break;
+
+    case SSL_ERROR_WANT_WRITE:
+      BIO_set_retry_write(bio);
+      break;
+
+    case SSL_ERROR_WANT_ACCEPT:
+      BIO_set_retry_special(bio);
+      bio->retry_reason = BIO_RR_ACCEPT;
+      break;
+
+    case SSL_ERROR_WANT_CONNECT:
+      BIO_set_retry_special(bio);
+      bio->retry_reason = BIO_RR_CONNECT;
+      break;
+
+    case SSL_ERROR_NONE:
+    case SSL_ERROR_SYSCALL:
+    case SSL_ERROR_SSL:
+    case SSL_ERROR_ZERO_RETURN:
+    default:
+      break;
+  }
+
+  return ret;
+}
+
+static int ssl_write(BIO *bio, const char *out, int outl) {
+  SSL *ssl = bio->ptr;
+  if (ssl == NULL) {
+    return 0;
+  }
+
+  BIO_clear_retry_flags(bio);
+
+  const int ret = SSL_write(ssl, out, outl);
+
+  switch (SSL_get_error(ssl, ret)) {
+    case SSL_ERROR_WANT_WRITE:
+      BIO_set_retry_write(bio);
+      break;
+
+    case SSL_ERROR_WANT_READ:
+      BIO_set_retry_read(bio);
+      break;
+
+    case SSL_ERROR_WANT_CONNECT:
+      BIO_set_retry_special(bio);
+      bio->retry_reason = BIO_RR_CONNECT;
+      break;
+
+    case SSL_ERROR_NONE:
+    case SSL_ERROR_SYSCALL:
+    case SSL_ERROR_SSL:
+    default:
+      break;
+  }
+
+  return ret;
+}
+
+static long ssl_ctrl(BIO *bio, int cmd, long num, void *ptr) {
+  SSL *ssl = bio->ptr;
+  if (ssl == NULL && cmd != BIO_C_SET_SSL) {
+    return 0;
+  }
+
+  switch (cmd) {
+    case BIO_C_SET_SSL:
+      bio->shutdown = num;
+      bio->ptr = ptr;
+      bio->init = 1;
+      return 1;
+
+    case BIO_CTRL_GET_CLOSE:
+      return bio->shutdown;
+
+    case BIO_CTRL_SET_CLOSE:
+      bio->shutdown = num;
+      return 1;
+
+    case BIO_CTRL_WPENDING:
+      return BIO_ctrl(SSL_get_wbio(ssl), cmd, num, ptr);
+
+    case BIO_CTRL_PENDING:
+      return SSL_pending(ssl);
+
+    case BIO_CTRL_FLUSH: {
+      BIO_clear_retry_flags(bio);
+      long ret = BIO_ctrl(SSL_get_wbio(ssl), cmd, num, ptr);
+      BIO_copy_next_retry(bio);
+      return ret;
+    }
+
+    case BIO_CTRL_PUSH:
+    case BIO_CTRL_POP:
+    case BIO_CTRL_DUP:
+      return -1;
+
+    default:
+      return BIO_ctrl(SSL_get_rbio(ssl), cmd, num, ptr);
+  }
+}
+
+static int ssl_new(BIO *bio) {
+  return 1;
+}
+
+static int ssl_free(BIO *bio) {
+  SSL *ssl = bio->ptr;
+
+  if (ssl == NULL) {
+    return 1;
+  }
+
+  SSL_shutdown(ssl);
+  if (bio->shutdown) {
+    SSL_free(ssl);
+  }
+
+  return 1;
+}
+
+static long ssl_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) {
+  SSL *ssl = bio->ptr;
+  if (ssl == NULL) {
+    return 0;
+  }
+
+  switch (cmd) {
+    case BIO_CTRL_SET_CALLBACK:
+      return -1;
+
+    default:
+      return BIO_callback_ctrl(SSL_get_rbio(ssl), cmd, fp);
+  }
+}
+
+static const BIO_METHOD ssl_method = {
+    BIO_TYPE_SSL, "SSL",    ssl_write, ssl_read, NULL,
+    NULL,         ssl_ctrl, ssl_new,   ssl_free, ssl_callback_ctrl,
+};
+
+const BIO_METHOD *BIO_f_ssl(void) { return &ssl_method; }
+
+long BIO_set_ssl(BIO *bio, SSL *ssl, int take_owership) {
+  return BIO_ctrl(bio, BIO_C_SET_SSL, take_owership, ssl);
+}
diff --git a/src/ssl/custom_extensions.c b/src/ssl/custom_extensions.c
index c94543d..ea57c20 100644
--- a/src/ssl/custom_extensions.c
+++ b/src/ssl/custom_extensions.c
@@ -32,8 +32,7 @@
 static const SSL_CUSTOM_EXTENSION *custom_ext_find(
     STACK_OF(SSL_CUSTOM_EXTENSION) *stack,
     unsigned *out_index, uint16_t value) {
-  size_t i;
-  for (i = 0; i < sk_SSL_CUSTOM_EXTENSION_num(stack); i++) {
+  for (size_t i = 0; i < sk_SSL_CUSTOM_EXTENSION_num(stack); i++) {
     const SSL_CUSTOM_EXTENSION *ext = sk_SSL_CUSTOM_EXTENSION_value(stack, i);
     if (ext->value == value) {
       if (out_index != NULL) {
@@ -59,7 +58,8 @@
   return 1;
 }
 
-static int custom_ext_add_hello(SSL *ssl, CBB *extensions) {
+static int custom_ext_add_hello(SSL_HANDSHAKE *hs, CBB *extensions) {
+  SSL *const ssl = hs->ssl;
   STACK_OF(SSL_CUSTOM_EXTENSION) *stack = ssl->ctx->client_custom_extensions;
   if (ssl->server) {
     stack = ssl->ctx->server_custom_extensions;
@@ -69,12 +69,19 @@
     return 1;
   }
 
-  size_t i;
-  for (i = 0; i < sk_SSL_CUSTOM_EXTENSION_num(stack); i++) {
+  if (ssl->ctx->enable_early_data) {
+    /* TODO(svaldez): Support Custom Extensions with 0-RTT. For now the caller
+     * is expected not to configure both together.
+     * https://crbug.com/boringssl/173. */
+    OPENSSL_PUT_ERROR(SSL, SSL_R_CUSTOM_EXTENSION_ERROR);
+    return 0;
+  }
+
+  for (size_t i = 0; i < sk_SSL_CUSTOM_EXTENSION_num(stack); i++) {
     const SSL_CUSTOM_EXTENSION *ext = sk_SSL_CUSTOM_EXTENSION_value(stack, i);
 
     if (ssl->server &&
-        !(ssl->s3->tmp.custom_extensions.received & (1u << i))) {
+        !(hs->custom_extensions.received & (1u << i))) {
       /* Servers cannot echo extensions that the client didn't send. */
       continue;
     }
@@ -92,7 +99,7 @@
             !CBB_add_bytes(&contents_cbb, contents, contents_len) ||
             !CBB_flush(extensions)) {
           OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-          ERR_add_error_dataf("extension: %u", (unsigned) ext->value);
+          ERR_add_error_dataf("extension %u", (unsigned) ext->value);
           if (ext->free_callback && 0 < contents_len) {
             ext->free_callback(ssl, ext->value, contents, ext->add_arg);
           }
@@ -104,8 +111,8 @@
         }
 
         if (!ssl->server) {
-          assert((ssl->s3->tmp.custom_extensions.sent & (1u << i)) == 0);
-          ssl->s3->tmp.custom_extensions.sent |= (1u << i);
+          assert((hs->custom_extensions.sent & (1u << i)) == 0);
+          hs->custom_extensions.sent |= (1u << i);
         }
         break;
 
@@ -115,7 +122,7 @@
       default:
         ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
         OPENSSL_PUT_ERROR(SSL, SSL_R_CUSTOM_EXTENSION_ERROR);
-        ERR_add_error_dataf("extension: %u", (unsigned) ext->value);
+        ERR_add_error_dataf("extension %u", (unsigned) ext->value);
         return 0;
     }
   }
@@ -123,12 +130,13 @@
   return 1;
 }
 
-int custom_ext_add_clienthello(SSL *ssl, CBB *extensions) {
-  return custom_ext_add_hello(ssl, extensions);
+int custom_ext_add_clienthello(SSL_HANDSHAKE *hs, CBB *extensions) {
+  return custom_ext_add_hello(hs, extensions);
 }
 
-int custom_ext_parse_serverhello(SSL *ssl, int *out_alert, uint16_t value,
-                                 const CBS *extension) {
+int custom_ext_parse_serverhello(SSL_HANDSHAKE *hs, int *out_alert,
+                                 uint16_t value, const CBS *extension) {
+  SSL *const ssl = hs->ssl;
   unsigned index;
   const SSL_CUSTOM_EXTENSION *ext =
       custom_ext_find(ssl->ctx->client_custom_extensions, &index, value);
@@ -136,10 +144,10 @@
   if (/* Unknown extensions are not allowed in a ServerHello. */
       ext == NULL ||
       /* Also, if we didn't send the extension, that's also unacceptable. */
-      !(ssl->s3->tmp.custom_extensions.sent & (1u << index))) {
+      !(hs->custom_extensions.sent & (1u << index))) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
-    ERR_add_error_dataf("extension: %u", (unsigned)value);
-    *out_alert = SSL_AD_DECODE_ERROR;
+    ERR_add_error_dataf("extension %u", (unsigned)value);
+    *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
     return 0;
   }
 
@@ -147,15 +155,16 @@
       !ext->parse_callback(ssl, value, CBS_data(extension), CBS_len(extension),
                            out_alert, ext->parse_arg)) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_CUSTOM_EXTENSION_ERROR);
-    ERR_add_error_dataf("extension: %u", (unsigned)ext->value);
+    ERR_add_error_dataf("extension %u", (unsigned)ext->value);
     return 0;
   }
 
   return 1;
 }
 
-int custom_ext_parse_clienthello(SSL *ssl, int *out_alert, uint16_t value,
-                                 const CBS *extension) {
+int custom_ext_parse_clienthello(SSL_HANDSHAKE *hs, int *out_alert,
+                                 uint16_t value, const CBS *extension) {
+  SSL *const ssl = hs->ssl;
   unsigned index;
   const SSL_CUSTOM_EXTENSION *ext =
       custom_ext_find(ssl->ctx->server_custom_extensions, &index, value);
@@ -164,29 +173,29 @@
     return 1;
   }
 
-  assert((ssl->s3->tmp.custom_extensions.received & (1u << index)) == 0);
-  ssl->s3->tmp.custom_extensions.received |= (1u << index);
+  assert((hs->custom_extensions.received & (1u << index)) == 0);
+  hs->custom_extensions.received |= (1u << index);
 
   if (ext->parse_callback &&
       !ext->parse_callback(ssl, value, CBS_data(extension), CBS_len(extension),
                            out_alert, ext->parse_arg)) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_CUSTOM_EXTENSION_ERROR);
-    ERR_add_error_dataf("extension: %u", (unsigned)ext->value);
+    ERR_add_error_dataf("extension %u", (unsigned)ext->value);
     return 0;
   }
 
   return 1;
 }
 
-int custom_ext_add_serverhello(SSL *ssl, CBB *extensions) {
-  return custom_ext_add_hello(ssl, extensions);
+int custom_ext_add_serverhello(SSL_HANDSHAKE *hs, CBB *extensions) {
+  return custom_ext_add_hello(hs, extensions);
 }
 
 /* MAX_NUM_CUSTOM_EXTENSIONS is the maximum number of custom extensions that
  * can be set on an |SSL_CTX|. It's determined by the size of the bitset used
  * to track when an extension has been sent. */
 #define MAX_NUM_CUSTOM_EXTENSIONS \
-  (sizeof(((struct ssl3_state_st *)NULL)->tmp.custom_extensions.sent) * 8)
+  (sizeof(((SSL_HANDSHAKE *)NULL)->custom_extensions.sent) * 8)
 
 static int custom_ext_append(STACK_OF(SSL_CUSTOM_EXTENSION) **stack,
                              unsigned extension_value,
diff --git a/src/ssl/d1_both.c b/src/ssl/d1_both.c
index ee4cbc9..44e3f2e 100644
--- a/src/ssl/d1_both.c
+++ b/src/ssl/d1_both.c
@@ -115,17 +115,16 @@
 
 #include <assert.h>
 #include <limits.h>
-#include <stdio.h>
 #include <string.h>
 
 #include <openssl/buf.h>
 #include <openssl/err.h>
 #include <openssl/evp.h>
 #include <openssl/mem.h>
-#include <openssl/obj.h>
 #include <openssl/rand.h>
-#include <openssl/x509.h>
+#include <openssl/type_check.h>
 
+#include "../crypto/internal.h"
 #include "internal.h"
 
 
@@ -141,41 +140,63 @@
  * the underlying BIO supplies one. */
 static const unsigned int kDefaultMTU = 1500 - 28;
 
-/* kMaxHandshakeBuffer is the maximum number of handshake messages ahead of the
- * current one to buffer. */
-static const unsigned int kHandshakeBufferSize = 10;
 
-static hm_fragment *dtls1_hm_fragment_new(size_t frag_len, int reassembly) {
+/* Receiving handshake messages. */
+
+static void dtls1_hm_fragment_free(hm_fragment *frag) {
+  if (frag == NULL) {
+    return;
+  }
+  OPENSSL_free(frag->data);
+  OPENSSL_free(frag->reassembly);
+  OPENSSL_free(frag);
+}
+
+static hm_fragment *dtls1_hm_fragment_new(const struct hm_header_st *msg_hdr) {
   hm_fragment *frag = OPENSSL_malloc(sizeof(hm_fragment));
   if (frag == NULL) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
     return NULL;
   }
-  memset(frag, 0, sizeof(hm_fragment));
+  OPENSSL_memset(frag, 0, sizeof(hm_fragment));
+  frag->type = msg_hdr->type;
+  frag->seq = msg_hdr->seq;
+  frag->msg_len = msg_hdr->msg_len;
 
-  /* If the handshake message is empty, |frag->fragment| and |frag->reassembly|
-   * are NULL. */
-  if (frag_len > 0) {
-    frag->fragment = OPENSSL_malloc(frag_len);
-    if (frag->fragment == NULL) {
+  /* Allocate space for the reassembled message and fill in the header. */
+  frag->data = OPENSSL_malloc(DTLS1_HM_HEADER_LENGTH + msg_hdr->msg_len);
+  if (frag->data == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+    goto err;
+  }
+
+  CBB cbb;
+  if (!CBB_init_fixed(&cbb, frag->data, DTLS1_HM_HEADER_LENGTH) ||
+      !CBB_add_u8(&cbb, msg_hdr->type) ||
+      !CBB_add_u24(&cbb, msg_hdr->msg_len) ||
+      !CBB_add_u16(&cbb, msg_hdr->seq) ||
+      !CBB_add_u24(&cbb, 0 /* frag_off */) ||
+      !CBB_add_u24(&cbb, msg_hdr->msg_len) ||
+      !CBB_finish(&cbb, NULL, NULL)) {
+    CBB_cleanup(&cbb);
+    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+    goto err;
+  }
+
+  /* If the handshake message is empty, |frag->reassembly| is NULL. */
+  if (msg_hdr->msg_len > 0) {
+    /* Initialize reassembly bitmask. */
+    if (msg_hdr->msg_len + 7 < msg_hdr->msg_len) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
+      goto err;
+    }
+    size_t bitmask_len = (msg_hdr->msg_len + 7) / 8;
+    frag->reassembly = OPENSSL_malloc(bitmask_len);
+    if (frag->reassembly == NULL) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
       goto err;
     }
-
-    if (reassembly) {
-      /* Initialize reassembly bitmask. */
-      if (frag_len + 7 < frag_len) {
-        OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
-        goto err;
-      }
-      size_t bitmask_len = (frag_len + 7) / 8;
-      frag->reassembly = OPENSSL_malloc(bitmask_len);
-      if (frag->reassembly == NULL) {
-        OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-        goto err;
-      }
-      memset(frag->reassembly, 0, bitmask_len);
-    }
+    OPENSSL_memset(frag->reassembly, 0, bitmask_len);
   }
 
   return frag;
@@ -185,22 +206,9 @@
   return NULL;
 }
 
-void dtls1_hm_fragment_free(hm_fragment *frag) {
-  if (frag == NULL) {
-    return;
-  }
-  OPENSSL_free(frag->fragment);
-  OPENSSL_free(frag->reassembly);
-  OPENSSL_free(frag);
-}
-
-#if !defined(inline)
-#define inline __inline
-#endif
-
 /* bit_range returns a |uint8_t| with bits |start|, inclusive, to |end|,
  * exclusive, set. */
-static inline uint8_t bit_range(size_t start, size_t end) {
+static uint8_t bit_range(size_t start, size_t end) {
   return (uint8_t)(~((1u << start) - 1) & ((1u << end) - 1));
 }
 
@@ -210,8 +218,7 @@
  * and |frag->reassembly| must not be NULL. */
 static void dtls1_hm_fragment_mark(hm_fragment *frag, size_t start,
                                    size_t end) {
-  size_t i;
-  size_t msg_len = frag->msg_header.msg_len;
+  size_t msg_len = frag->msg_len;
 
   if (frag->reassembly == NULL || start > end || end > msg_len) {
     assert(0);
@@ -224,7 +231,7 @@
     frag->reassembly[start >> 3] |= bit_range(start & 7, end & 7);
   } else {
     frag->reassembly[start >> 3] |= bit_range(start & 7, 8);
-    for (i = (start >> 3) + 1; i < (end >> 3); i++) {
+    for (size_t i = (start >> 3) + 1; i < (end >> 3); i++) {
       frag->reassembly[i] = 0xff;
     }
     if ((end & 7) != 0) {
@@ -233,7 +240,7 @@
   }
 
   /* Check if the fragment is complete. */
-  for (i = 0; i < (msg_len >> 3); i++) {
+  for (size_t i = 0; i < (msg_len >> 3); i++) {
     if (frag->reassembly[i] != 0xff) {
       return;
     }
@@ -247,16 +254,353 @@
   frag->reassembly = NULL;
 }
 
+/* dtls1_is_current_message_complete returns one if the current handshake
+ * message is complete and zero otherwise. */
+static int dtls1_is_current_message_complete(const SSL *ssl) {
+  hm_fragment *frag = ssl->d1->incoming_messages[ssl->d1->handshake_read_seq %
+                                                 SSL_MAX_HANDSHAKE_FLIGHT];
+  return frag != NULL && frag->reassembly == NULL;
+}
+
+/* dtls1_get_incoming_message returns the incoming message corresponding to
+ * |msg_hdr|. If none exists, it creates a new one and inserts it in the
+ * queue. Otherwise, it checks |msg_hdr| is consistent with the existing one. It
+ * returns NULL on failure. The caller does not take ownership of the result. */
+static hm_fragment *dtls1_get_incoming_message(
+    SSL *ssl, const struct hm_header_st *msg_hdr) {
+  if (msg_hdr->seq < ssl->d1->handshake_read_seq ||
+      msg_hdr->seq - ssl->d1->handshake_read_seq >= SSL_MAX_HANDSHAKE_FLIGHT) {
+    return NULL;
+  }
+
+  size_t idx = msg_hdr->seq % SSL_MAX_HANDSHAKE_FLIGHT;
+  hm_fragment *frag = ssl->d1->incoming_messages[idx];
+  if (frag != NULL) {
+    assert(frag->seq == msg_hdr->seq);
+    /* The new fragment must be compatible with the previous fragments from this
+     * message. */
+    if (frag->type != msg_hdr->type ||
+        frag->msg_len != msg_hdr->msg_len) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_FRAGMENT_MISMATCH);
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+      return NULL;
+    }
+    return frag;
+  }
+
+  /* This is the first fragment from this message. */
+  frag = dtls1_hm_fragment_new(msg_hdr);
+  if (frag == NULL) {
+    return NULL;
+  }
+  ssl->d1->incoming_messages[idx] = frag;
+  return frag;
+}
+
+/* dtls1_process_handshake_record reads a handshake record and processes it. It
+ * returns one if the record was successfully processed and 0 or -1 on error. */
+static int dtls1_process_handshake_record(SSL *ssl) {
+  SSL3_RECORD *rr = &ssl->s3->rrec;
+
+start:
+  if (rr->length == 0) {
+    int ret = dtls1_get_record(ssl);
+    if (ret <= 0) {
+      return ret;
+    }
+  }
+
+  /* Cross-epoch records are discarded, but we may receive out-of-order
+   * application data between ChangeCipherSpec and Finished or a
+   * ChangeCipherSpec before the appropriate point in the handshake. Those must
+   * be silently discarded.
+   *
+   * However, only allow the out-of-order records in the correct epoch.
+   * Application data must come in the encrypted epoch, and ChangeCipherSpec in
+   * the unencrypted epoch (we never renegotiate). Other cases fall through and
+   * fail with a fatal error. */
+  if ((rr->type == SSL3_RT_APPLICATION_DATA &&
+       ssl->s3->aead_read_ctx != NULL) ||
+      (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC &&
+       ssl->s3->aead_read_ctx == NULL)) {
+    rr->length = 0;
+    goto start;
+  }
+
+  if (rr->type != SSL3_RT_HANDSHAKE) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+    OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
+    return -1;
+  }
+
+  CBS cbs;
+  CBS_init(&cbs, rr->data, rr->length);
+
+  while (CBS_len(&cbs) > 0) {
+    /* Read a handshake fragment. */
+    struct hm_header_st msg_hdr;
+    CBS body;
+    if (!dtls1_parse_fragment(&cbs, &msg_hdr, &body)) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_HANDSHAKE_RECORD);
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+      return -1;
+    }
+
+    const size_t frag_off = msg_hdr.frag_off;
+    const size_t frag_len = msg_hdr.frag_len;
+    const size_t msg_len = msg_hdr.msg_len;
+    if (frag_off > msg_len || frag_off + frag_len < frag_off ||
+        frag_off + frag_len > msg_len ||
+        msg_len > ssl_max_handshake_message_len(ssl)) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_EXCESSIVE_MESSAGE_SIZE);
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+      return -1;
+    }
+
+    /* The encrypted epoch in DTLS has only one handshake message. */
+    if (ssl->d1->r_epoch == 1 && msg_hdr.seq != ssl->d1->handshake_read_seq) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+      return -1;
+    }
+
+    if (msg_hdr.seq < ssl->d1->handshake_read_seq ||
+        msg_hdr.seq >
+            (unsigned)ssl->d1->handshake_read_seq + SSL_MAX_HANDSHAKE_FLIGHT) {
+      /* Ignore fragments from the past, or ones too far in the future. */
+      continue;
+    }
+
+    hm_fragment *frag = dtls1_get_incoming_message(ssl, &msg_hdr);
+    if (frag == NULL) {
+      return -1;
+    }
+    assert(frag->msg_len == msg_len);
+
+    if (frag->reassembly == NULL) {
+      /* The message is already assembled. */
+      continue;
+    }
+    assert(msg_len > 0);
+
+    /* Copy the body into the fragment. */
+    OPENSSL_memcpy(frag->data + DTLS1_HM_HEADER_LENGTH + frag_off,
+                   CBS_data(&body), CBS_len(&body));
+    dtls1_hm_fragment_mark(frag, frag_off, frag_off + frag_len);
+  }
+
+  rr->length = 0;
+  ssl_read_buffer_discard(ssl);
+  return 1;
+}
+
+int dtls1_get_message(SSL *ssl) {
+  if (ssl->s3->tmp.reuse_message) {
+    /* There must be a current message. */
+    assert(ssl->init_msg != NULL);
+    ssl->s3->tmp.reuse_message = 0;
+  } else {
+    dtls1_release_current_message(ssl, 0 /* don't free buffer */);
+  }
+
+  /* Process handshake records until the current message is ready. */
+  while (!dtls1_is_current_message_complete(ssl)) {
+    int ret = dtls1_process_handshake_record(ssl);
+    if (ret <= 0) {
+      return ret;
+    }
+  }
+
+  hm_fragment *frag = ssl->d1->incoming_messages[ssl->d1->handshake_read_seq %
+                                                 SSL_MAX_HANDSHAKE_FLIGHT];
+  assert(frag != NULL);
+  assert(frag->reassembly == NULL);
+  assert(ssl->d1->handshake_read_seq == frag->seq);
+
+  /* TODO(davidben): This function has a lot of implicit outputs. Simplify the
+   * |ssl_get_message| API. */
+  ssl->s3->tmp.message_type = frag->type;
+  ssl->init_msg = frag->data + DTLS1_HM_HEADER_LENGTH;
+  ssl->init_num = frag->msg_len;
+
+  ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_HANDSHAKE, frag->data,
+                      ssl->init_num + DTLS1_HM_HEADER_LENGTH);
+  return 1;
+}
+
+void dtls1_get_current_message(const SSL *ssl, CBS *out) {
+  assert(dtls1_is_current_message_complete(ssl));
+
+  hm_fragment *frag = ssl->d1->incoming_messages[ssl->d1->handshake_read_seq %
+                                                 SSL_MAX_HANDSHAKE_FLIGHT];
+  CBS_init(out, frag->data, DTLS1_HM_HEADER_LENGTH + frag->msg_len);
+}
+
+void dtls1_release_current_message(SSL *ssl, int free_buffer) {
+  if (ssl->init_msg == NULL) {
+    return;
+  }
+
+  assert(dtls1_is_current_message_complete(ssl));
+  size_t index = ssl->d1->handshake_read_seq % SSL_MAX_HANDSHAKE_FLIGHT;
+  dtls1_hm_fragment_free(ssl->d1->incoming_messages[index]);
+  ssl->d1->incoming_messages[index] = NULL;
+  ssl->d1->handshake_read_seq++;
+
+  ssl->init_msg = NULL;
+  ssl->init_num = 0;
+}
+
+void dtls_clear_incoming_messages(SSL *ssl) {
+  for (size_t i = 0; i < SSL_MAX_HANDSHAKE_FLIGHT; i++) {
+    dtls1_hm_fragment_free(ssl->d1->incoming_messages[i]);
+    ssl->d1->incoming_messages[i] = NULL;
+  }
+}
+
+int dtls_has_incoming_messages(const SSL *ssl) {
+  size_t current = ssl->d1->handshake_read_seq % SSL_MAX_HANDSHAKE_FLIGHT;
+  for (size_t i = 0; i < SSL_MAX_HANDSHAKE_FLIGHT; i++) {
+    /* Skip the current message. */
+    if (ssl->init_msg != NULL && i == current) {
+      assert(dtls1_is_current_message_complete(ssl));
+      continue;
+    }
+    if (ssl->d1->incoming_messages[i] != NULL) {
+      return 1;
+    }
+  }
+  return 0;
+}
+
+int dtls1_parse_fragment(CBS *cbs, struct hm_header_st *out_hdr,
+                         CBS *out_body) {
+  OPENSSL_memset(out_hdr, 0x00, sizeof(struct hm_header_st));
+
+  if (!CBS_get_u8(cbs, &out_hdr->type) ||
+      !CBS_get_u24(cbs, &out_hdr->msg_len) ||
+      !CBS_get_u16(cbs, &out_hdr->seq) ||
+      !CBS_get_u24(cbs, &out_hdr->frag_off) ||
+      !CBS_get_u24(cbs, &out_hdr->frag_len) ||
+      !CBS_get_bytes(cbs, out_body, out_hdr->frag_len)) {
+    return 0;
+  }
+
+  return 1;
+}
+
+
+/* Sending handshake messages. */
+
+void dtls_clear_outgoing_messages(SSL *ssl) {
+  for (size_t i = 0; i < ssl->d1->outgoing_messages_len; i++) {
+    OPENSSL_free(ssl->d1->outgoing_messages[i].data);
+    ssl->d1->outgoing_messages[i].data = NULL;
+  }
+  ssl->d1->outgoing_messages_len = 0;
+  ssl->d1->outgoing_written = 0;
+  ssl->d1->outgoing_offset = 0;
+}
+
+int dtls1_init_message(SSL *ssl, CBB *cbb, CBB *body, uint8_t type) {
+  /* Pick a modest size hint to save most of the |realloc| calls. */
+  if (!CBB_init(cbb, 64) ||
+      !CBB_add_u8(cbb, type) ||
+      !CBB_add_u24(cbb, 0 /* length (filled in later) */) ||
+      !CBB_add_u16(cbb, ssl->d1->handshake_write_seq) ||
+      !CBB_add_u24(cbb, 0 /* offset */) ||
+      !CBB_add_u24_length_prefixed(cbb, body)) {
+    return 0;
+  }
+
+  return 1;
+}
+
+int dtls1_finish_message(SSL *ssl, CBB *cbb, uint8_t **out_msg,
+                         size_t *out_len) {
+  *out_msg = NULL;
+  if (!CBB_finish(cbb, out_msg, out_len) ||
+      *out_len < DTLS1_HM_HEADER_LENGTH) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    OPENSSL_free(*out_msg);
+    return 0;
+  }
+
+  /* Fix up the header. Copy the fragment length into the total message
+   * length. */
+  OPENSSL_memcpy(*out_msg + 1, *out_msg + DTLS1_HM_HEADER_LENGTH - 3, 3);
+  return 1;
+}
+
+/* add_outgoing adds a new handshake message or ChangeCipherSpec to the current
+ * outgoing flight. It returns one on success and zero on error. In both cases,
+ * it takes ownership of |data| and releases it with |OPENSSL_free| when
+ * done. */
+static int add_outgoing(SSL *ssl, int is_ccs, uint8_t *data, size_t len) {
+  OPENSSL_COMPILE_ASSERT(SSL_MAX_HANDSHAKE_FLIGHT <
+                             (1 << 8 * sizeof(ssl->d1->outgoing_messages_len)),
+                         outgoing_messages_len_is_too_small);
+  if (ssl->d1->outgoing_messages_len >= SSL_MAX_HANDSHAKE_FLIGHT) {
+    assert(0);
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    OPENSSL_free(data);
+    return 0;
+  }
+
+  if (!is_ccs) {
+    /* TODO(svaldez): Move this up a layer to fix abstraction for SSL_TRANSCRIPT
+     * on hs. */
+    if (ssl->s3->hs != NULL &&
+        !SSL_TRANSCRIPT_update(&ssl->s3->hs->transcript, data, len)) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+      OPENSSL_free(data);
+      return 0;
+    }
+    ssl->d1->handshake_write_seq++;
+  }
+
+  DTLS_OUTGOING_MESSAGE *msg =
+      &ssl->d1->outgoing_messages[ssl->d1->outgoing_messages_len];
+  msg->data = data;
+  msg->len = len;
+  msg->epoch = ssl->d1->w_epoch;
+  msg->is_ccs = is_ccs;
+
+  ssl->d1->outgoing_messages_len++;
+  return 1;
+}
+
+int dtls1_add_message(SSL *ssl, uint8_t *data, size_t len) {
+  return add_outgoing(ssl, 0 /* handshake */, data, len);
+}
+
+int dtls1_add_change_cipher_spec(SSL *ssl) {
+  return add_outgoing(ssl, 1 /* ChangeCipherSpec */, NULL, 0);
+}
+
+int dtls1_add_alert(SSL *ssl, uint8_t level, uint8_t desc) {
+  /* The |add_alert| path is only used for warning alerts for now, which DTLS
+   * never sends. This will be implemented later once closure alerts are
+   * converted. */
+  assert(0);
+  OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+  return 0;
+}
+
+/* dtls1_update_mtu updates the current MTU from the BIO, ensuring it is above
+ * the minimum. */
 static void dtls1_update_mtu(SSL *ssl) {
-  /* TODO(davidben): What is this code doing and do we need it? */
+  /* TODO(davidben): No consumer implements |BIO_CTRL_DGRAM_SET_MTU| and the
+   * only |BIO_CTRL_DGRAM_QUERY_MTU| implementation could use
+   * |SSL_set_mtu|. Does this need to be so complex?  */
   if (ssl->d1->mtu < dtls1_min_mtu() &&
       !(SSL_get_options(ssl) & SSL_OP_NO_QUERY_MTU)) {
-    long mtu = BIO_ctrl(SSL_get_wbio(ssl), BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
+    long mtu = BIO_ctrl(ssl->wbio, BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
     if (mtu >= 0 && mtu <= (1 << 30) && (unsigned)mtu >= dtls1_min_mtu()) {
       ssl->d1->mtu = (unsigned)mtu;
     } else {
       ssl->d1->mtu = kDefaultMTU;
-      BIO_ctrl(SSL_get_wbio(ssl), BIO_CTRL_DGRAM_SET_MTU, ssl->d1->mtu, NULL);
+      BIO_ctrl(ssl->wbio, BIO_CTRL_DGRAM_SET_MTU, ssl->d1->mtu, NULL);
     }
   }
 
@@ -264,618 +608,207 @@
   assert(ssl->d1->mtu >= dtls1_min_mtu());
 }
 
-/* dtls1_max_record_size returns the maximum record body length that may be
- * written without exceeding the MTU. It accounts for any buffering installed on
- * the write BIO. If no record may be written, it returns zero. */
-static size_t dtls1_max_record_size(SSL *ssl) {
-  size_t ret = ssl->d1->mtu;
+enum seal_result_t {
+  seal_error,
+  seal_no_progress,
+  seal_partial,
+  seal_success,
+};
 
-  size_t overhead = ssl_max_seal_overhead(ssl);
-  if (ret <= overhead) {
-    return 0;
+/* seal_next_message seals |msg|, which must be the next message, to |out|. If
+ * progress was made, it returns |seal_partial| or |seal_success| and sets
+ * |*out_len| to the number of bytes written. */
+static enum seal_result_t seal_next_message(SSL *ssl, uint8_t *out,
+                                            size_t *out_len, size_t max_out,
+                                            const DTLS_OUTGOING_MESSAGE *msg) {
+  assert(ssl->d1->outgoing_written < ssl->d1->outgoing_messages_len);
+  assert(msg == &ssl->d1->outgoing_messages[ssl->d1->outgoing_written]);
+
+  /* DTLS renegotiation is unsupported, so only epochs 0 (NULL cipher) and 1
+   * (negotiated cipher) exist. */
+  assert(ssl->d1->w_epoch == 0 || ssl->d1->w_epoch == 1);
+  assert(msg->epoch <= ssl->d1->w_epoch);
+  enum dtls1_use_epoch_t use_epoch = dtls1_use_current_epoch;
+  if (ssl->d1->w_epoch == 1 && msg->epoch == 0) {
+    use_epoch = dtls1_use_previous_epoch;
   }
-  ret -= overhead;
+  size_t overhead = dtls_max_seal_overhead(ssl, use_epoch);
+  size_t prefix = dtls_seal_prefix_len(ssl, use_epoch);
 
-  size_t pending = BIO_wpending(SSL_get_wbio(ssl));
-  if (ret <= pending) {
-    return 0;
+  if (msg->is_ccs) {
+    /* Check there is room for the ChangeCipherSpec. */
+    static const uint8_t kChangeCipherSpec[1] = {SSL3_MT_CCS};
+    if (max_out < sizeof(kChangeCipherSpec) + overhead) {
+      return seal_no_progress;
+    }
+
+    if (!dtls_seal_record(ssl, out, out_len, max_out,
+                          SSL3_RT_CHANGE_CIPHER_SPEC, kChangeCipherSpec,
+                          sizeof(kChangeCipherSpec), use_epoch)) {
+      return seal_error;
+    }
+
+    ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_CHANGE_CIPHER_SPEC,
+                        kChangeCipherSpec, sizeof(kChangeCipherSpec));
+    return seal_success;
   }
-  ret -= pending;
 
-  return ret;
+  /* DTLS messages are serialized as a single fragment in |msg|. */
+  CBS cbs, body;
+  struct hm_header_st hdr;
+  CBS_init(&cbs, msg->data, msg->len);
+  if (!dtls1_parse_fragment(&cbs, &hdr, &body) ||
+      hdr.frag_off != 0 ||
+      hdr.frag_len != CBS_len(&body) ||
+      hdr.msg_len != CBS_len(&body) ||
+      !CBS_skip(&body, ssl->d1->outgoing_offset) ||
+      CBS_len(&cbs) != 0) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    return seal_error;
+  }
+
+  /* Determine how much progress can be made. */
+  if (max_out < DTLS1_HM_HEADER_LENGTH + 1 + overhead || max_out < prefix) {
+    return seal_no_progress;
+  }
+  size_t todo = CBS_len(&body);
+  if (todo > max_out - DTLS1_HM_HEADER_LENGTH - overhead) {
+    todo = max_out - DTLS1_HM_HEADER_LENGTH - overhead;
+  }
+
+  /* Assemble a fragment, to be sealed in-place. */
+  CBB cbb;
+  uint8_t *frag = out + prefix;
+  size_t max_frag = max_out - prefix, frag_len;
+  if (!CBB_init_fixed(&cbb, frag, max_frag) ||
+      !CBB_add_u8(&cbb, hdr.type) ||
+      !CBB_add_u24(&cbb, hdr.msg_len) ||
+      !CBB_add_u16(&cbb, hdr.seq) ||
+      !CBB_add_u24(&cbb, ssl->d1->outgoing_offset) ||
+      !CBB_add_u24(&cbb, todo) ||
+      !CBB_add_bytes(&cbb, CBS_data(&body), todo) ||
+      !CBB_finish(&cbb, NULL, &frag_len)) {
+    CBB_cleanup(&cbb);
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    return seal_error;
+  }
+
+  ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HANDSHAKE, frag, frag_len);
+
+  if (!dtls_seal_record(ssl, out, out_len, max_out, SSL3_RT_HANDSHAKE,
+                        out + prefix, frag_len, use_epoch)) {
+    return seal_error;
+  }
+
+  if (todo == CBS_len(&body)) {
+    /* The next message is complete. */
+    ssl->d1->outgoing_offset = 0;
+    return seal_success;
+  }
+
+  ssl->d1->outgoing_offset += todo;
+  return seal_partial;
 }
 
-static int dtls1_write_change_cipher_spec(SSL *ssl,
-                                          enum dtls1_use_epoch_t use_epoch) {
-  dtls1_update_mtu(ssl);
+/* seal_next_packet writes as much of the next flight as possible to |out| and
+ * advances |ssl->d1->outgoing_written| and |ssl->d1->outgoing_offset| as
+ * appropriate. */
+static int seal_next_packet(SSL *ssl, uint8_t *out, size_t *out_len,
+                            size_t max_out) {
+  int made_progress = 0;
+  size_t total = 0;
+  assert(ssl->d1->outgoing_written < ssl->d1->outgoing_messages_len);
+  for (; ssl->d1->outgoing_written < ssl->d1->outgoing_messages_len;
+       ssl->d1->outgoing_written++) {
+    const DTLS_OUTGOING_MESSAGE *msg =
+        &ssl->d1->outgoing_messages[ssl->d1->outgoing_written];
+    size_t len;
+    enum seal_result_t ret = seal_next_message(ssl, out, &len, max_out, msg);
+    switch (ret) {
+      case seal_error:
+        return 0;
 
-  /* During the handshake, wbio is buffered to pack messages together. Flush the
-   * buffer if the ChangeCipherSpec would not fit in a packet. */
-  if (dtls1_max_record_size(ssl) == 0) {
-    ssl->rwstate = SSL_WRITING;
-    int ret = BIO_flush(SSL_get_wbio(ssl));
-    if (ret <= 0) {
-      return ret;
+      case seal_no_progress:
+        goto packet_full;
+
+      case seal_partial:
+      case seal_success:
+        out += len;
+        max_out -= len;
+        total += len;
+        made_progress = 1;
+
+        if (ret == seal_partial) {
+          goto packet_full;
+        }
+        break;
     }
-    ssl->rwstate = SSL_NOTHING;
   }
 
-  static const uint8_t kChangeCipherSpec[1] = {SSL3_MT_CCS};
-  int ret =
-      dtls1_write_bytes(ssl, SSL3_RT_CHANGE_CIPHER_SPEC, kChangeCipherSpec,
-                        sizeof(kChangeCipherSpec), use_epoch);
-  if (ret <= 0) {
-    return ret;
+packet_full:
+  /* The MTU was too small to make any progress. */
+  if (!made_progress) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_MTU_TOO_SMALL);
+    return 0;
   }
 
-  if (ssl->msg_callback != NULL) {
-    ssl->msg_callback(1 /* write */, ssl->version, SSL3_RT_CHANGE_CIPHER_SPEC,
-                      kChangeCipherSpec, sizeof(kChangeCipherSpec), ssl,
-                      ssl->msg_callback_arg);
-  }
-
+  *out_len = total;
   return 1;
 }
 
-int dtls1_do_handshake_write(SSL *ssl, enum dtls1_use_epoch_t use_epoch) {
+int dtls1_flush_flight(SSL *ssl) {
   dtls1_update_mtu(ssl);
 
   int ret = -1;
-  CBB cbb;
-  CBB_zero(&cbb);
-  /* Allocate a temporary buffer to hold the message fragments to avoid
-   * clobbering the message. */
-  uint8_t *buf = OPENSSL_malloc(ssl->d1->mtu);
-  if (buf == NULL) {
+  uint8_t *packet = OPENSSL_malloc(ssl->d1->mtu);
+  if (packet == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
     goto err;
   }
 
-  /* Consume the message header. Fragments will have different headers
-   * prepended. */
-  if (ssl->init_off == 0) {
-    ssl->init_off += DTLS1_HM_HEADER_LENGTH;
-    ssl->init_num -= DTLS1_HM_HEADER_LENGTH;
-  }
-  assert(ssl->init_off >= DTLS1_HM_HEADER_LENGTH);
+  while (ssl->d1->outgoing_written < ssl->d1->outgoing_messages_len) {
+    uint8_t old_written = ssl->d1->outgoing_written;
+    uint32_t old_offset = ssl->d1->outgoing_offset;
 
-  do {
-    /* During the handshake, wbio is buffered to pack messages together. Flush
-     * the buffer if there isn't enough room to make progress. */
-    if (dtls1_max_record_size(ssl) < DTLS1_HM_HEADER_LENGTH + 1) {
+    size_t packet_len;
+    if (!seal_next_packet(ssl, packet, &packet_len, ssl->d1->mtu)) {
+      goto err;
+    }
+
+    int bio_ret = BIO_write(ssl->wbio, packet, packet_len);
+    if (bio_ret <= 0) {
+      /* Retry this packet the next time around. */
+      ssl->d1->outgoing_written = old_written;
+      ssl->d1->outgoing_offset = old_offset;
       ssl->rwstate = SSL_WRITING;
-      int flush_ret = BIO_flush(SSL_get_wbio(ssl));
-      if (flush_ret <= 0) {
-        ret = flush_ret;
-        goto err;
-      }
-      ssl->rwstate = SSL_NOTHING;
-      assert(BIO_wpending(SSL_get_wbio(ssl)) == 0);
-    }
-
-    size_t todo = dtls1_max_record_size(ssl);
-    if (todo < DTLS1_HM_HEADER_LENGTH + 1) {
-      /* To make forward progress, the MTU must, at minimum, fit the handshake
-       * header and one byte of handshake body. */
-      OPENSSL_PUT_ERROR(SSL, SSL_R_MTU_TOO_SMALL);
+      ret = bio_ret;
       goto err;
     }
-    todo -= DTLS1_HM_HEADER_LENGTH;
-
-    if (todo > (size_t)ssl->init_num) {
-      todo = ssl->init_num;
-    }
-    if (todo >= (1u << 24)) {
-      todo = (1u << 24) - 1;
-    }
-
-    size_t len;
-    if (!CBB_init_fixed(&cbb, buf, ssl->d1->mtu) ||
-        !CBB_add_u8(&cbb, ssl->d1->w_msg_hdr.type) ||
-        !CBB_add_u24(&cbb, ssl->d1->w_msg_hdr.msg_len) ||
-        !CBB_add_u16(&cbb, ssl->d1->w_msg_hdr.seq) ||
-        !CBB_add_u24(&cbb, ssl->init_off - DTLS1_HM_HEADER_LENGTH) ||
-        !CBB_add_u24(&cbb, todo) ||
-        !CBB_add_bytes(
-            &cbb, (const uint8_t *)ssl->init_buf->data + ssl->init_off, todo) ||
-        !CBB_finish(&cbb, NULL, &len)) {
-      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-      goto err;
-    }
-
-    int write_ret = dtls1_write_bytes(ssl, SSL3_RT_HANDSHAKE, buf, len,
-                                      use_epoch);
-    if (write_ret <= 0) {
-      ret = write_ret;
-      goto err;
-    }
-    ssl->init_off += todo;
-    ssl->init_num -= todo;
-  } while (ssl->init_num > 0);
-
-  if (ssl->msg_callback != NULL) {
-    ssl->msg_callback(
-        1 /* write */, ssl->version, SSL3_RT_HANDSHAKE, ssl->init_buf->data,
-        (size_t)(ssl->init_off + ssl->init_num), ssl, ssl->msg_callback_arg);
   }
 
-  ssl->init_off = 0;
-  ssl->init_num = 0;
+  if (BIO_flush(ssl->wbio) <= 0) {
+    ssl->rwstate = SSL_WRITING;
+    goto err;
+  }
 
   ret = 1;
 
 err:
-  CBB_cleanup(&cbb);
-  OPENSSL_free(buf);
+  OPENSSL_free(packet);
   return ret;
 }
 
-/* dtls1_is_next_message_complete returns one if the next handshake message is
- * complete and zero otherwise. */
-static int dtls1_is_next_message_complete(SSL *ssl) {
-  pitem *item = pqueue_peek(ssl->d1->buffered_messages);
-  if (item == NULL) {
-    return 0;
-  }
+int dtls1_retransmit_outgoing_messages(SSL *ssl) {
+  /* Rewind to the start of the flight and write it again.
+   *
+   * TODO(davidben): This does not allow retransmits to be resumed on
+   * non-blocking write. */
+  ssl->d1->outgoing_written = 0;
+  ssl->d1->outgoing_offset = 0;
 
-  hm_fragment *frag = (hm_fragment *)item->data;
-  assert(ssl->d1->handshake_read_seq <= frag->msg_header.seq);
-
-  return ssl->d1->handshake_read_seq == frag->msg_header.seq &&
-         frag->reassembly == NULL;
-}
-
-/* dtls1_discard_fragment_body discards a handshake fragment body of length
- * |frag_len|. It returns one on success and zero on error.
- *
- * TODO(davidben): This function will go away when ssl_read_bytes is gone from
- * the DTLS side. */
-static int dtls1_discard_fragment_body(SSL *ssl, size_t frag_len) {
-  uint8_t discard[256];
-  while (frag_len > 0) {
-    size_t chunk = frag_len < sizeof(discard) ? frag_len : sizeof(discard);
-    int ret = dtls1_read_bytes(ssl, SSL3_RT_HANDSHAKE, discard, chunk, 0);
-    if (ret != (int) chunk) {
-      return 0;
-    }
-    frag_len -= chunk;
-  }
-  return 1;
-}
-
-/* dtls1_get_buffered_message returns the buffered message corresponding to
- * |msg_hdr|. If none exists, it creates a new one and inserts it in the
- * queue. Otherwise, it checks |msg_hdr| is consistent with the existing one. It
- * returns NULL on failure. The caller does not take ownership of the result. */
-static hm_fragment *dtls1_get_buffered_message(
-    SSL *ssl, const struct hm_header_st *msg_hdr) {
-  uint8_t seq64be[8];
-  memset(seq64be, 0, sizeof(seq64be));
-  seq64be[6] = (uint8_t)(msg_hdr->seq >> 8);
-  seq64be[7] = (uint8_t)msg_hdr->seq;
-  pitem *item = pqueue_find(ssl->d1->buffered_messages, seq64be);
-
-  hm_fragment *frag;
-  if (item == NULL) {
-    /* This is the first fragment from this message. */
-    frag = dtls1_hm_fragment_new(msg_hdr->msg_len,
-                                 1 /* reassembly buffer needed */);
-    if (frag == NULL) {
-      return NULL;
-    }
-    memcpy(&frag->msg_header, msg_hdr, sizeof(*msg_hdr));
-    item = pitem_new(seq64be, frag);
-    if (item == NULL) {
-      dtls1_hm_fragment_free(frag);
-      return NULL;
-    }
-    item = pqueue_insert(ssl->d1->buffered_messages, item);
-    /* |pqueue_insert| fails iff a duplicate item is inserted, but |item| cannot
-     * be a duplicate. */
-    assert(item != NULL);
-  } else {
-    frag = item->data;
-    assert(frag->msg_header.seq == msg_hdr->seq);
-    if (frag->msg_header.type != msg_hdr->type ||
-        frag->msg_header.msg_len != msg_hdr->msg_len) {
-      /* The new fragment must be compatible with the previous fragments from
-       * this message. */
-      OPENSSL_PUT_ERROR(SSL, SSL_R_FRAGMENT_MISMATCH);
-      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
-      return NULL;
-    }
-  }
-  return frag;
-}
-
-/* dtls1_max_handshake_message_len returns the maximum number of bytes
- * permitted in a DTLS handshake message for |ssl|. The minimum is 16KB, but may
- * be greater if the maximum certificate list size requires it. */
-static size_t dtls1_max_handshake_message_len(const SSL *ssl) {
-  size_t max_len = DTLS1_HM_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH;
-  if (max_len < ssl->max_cert_list) {
-    return ssl->max_cert_list;
-  }
-  return max_len;
-}
-
-/* dtls1_process_fragment reads a handshake fragment and processes it. It
- * returns one if a fragment was successfully processed and 0 or -1 on error. */
-static int dtls1_process_fragment(SSL *ssl) {
-  /* Read handshake message header. */
-  uint8_t header[DTLS1_HM_HEADER_LENGTH];
-  int ret = dtls1_read_bytes(ssl, SSL3_RT_HANDSHAKE, header,
-                             DTLS1_HM_HEADER_LENGTH, 0);
-  if (ret <= 0) {
-    return ret;
-  }
-  if (ret != DTLS1_HM_HEADER_LENGTH) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
-    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
-    return -1;
-  }
-
-  /* Parse the message fragment header. */
-  struct hm_header_st msg_hdr;
-  dtls1_get_message_header(header, &msg_hdr);
-
-  /* TODO(davidben): dtls1_read_bytes is the wrong abstraction for DTLS. There
-   * should be no need to reach into |ssl->s3->rrec.length|. */
-  const size_t frag_off = msg_hdr.frag_off;
-  const size_t frag_len = msg_hdr.frag_len;
-  const size_t msg_len = msg_hdr.msg_len;
-  if (frag_off > msg_len || frag_off + frag_len < frag_off ||
-      frag_off + frag_len > msg_len ||
-      msg_len > dtls1_max_handshake_message_len(ssl) ||
-      frag_len > ssl->s3->rrec.length) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_EXCESSIVE_MESSAGE_SIZE);
-    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
-    return -1;
-  }
-
-  if (msg_hdr.seq < ssl->d1->handshake_read_seq ||
-      msg_hdr.seq > (unsigned)ssl->d1->handshake_read_seq +
-                    kHandshakeBufferSize) {
-    /* Ignore fragments from the past, or ones too far in the future. */
-    if (!dtls1_discard_fragment_body(ssl, frag_len)) {
-      return -1;
-    }
-    return 1;
-  }
-
-  hm_fragment *frag = dtls1_get_buffered_message(ssl, &msg_hdr);
-  if (frag == NULL) {
-    return -1;
-  }
-  assert(frag->msg_header.msg_len == msg_len);
-
-  if (frag->reassembly == NULL) {
-    /* The message is already assembled. */
-    if (!dtls1_discard_fragment_body(ssl, frag_len)) {
-      return -1;
-    }
-    return 1;
-  }
-  assert(msg_len > 0);
-
-  /* Read the body of the fragment. */
-  ret = dtls1_read_bytes(ssl, SSL3_RT_HANDSHAKE, frag->fragment + frag_off,
-                         frag_len, 0);
-  if (ret != (int) frag_len) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-    return -1;
-  }
-  dtls1_hm_fragment_mark(frag, frag_off, frag_off + frag_len);
-
-  return 1;
-}
-
-/* dtls1_get_message reads a handshake message of message type |msg_type| (any
- * if |msg_type| == -1), maximum acceptable body length |max|. Read an entire
- * handshake message. Handshake messages arrive in fragments. */
-long dtls1_get_message(SSL *ssl, int st1, int stn, int msg_type, long max,
-                       enum ssl_hash_message_t hash_message, int *ok) {
-  pitem *item = NULL;
-  hm_fragment *frag = NULL;
-  int al;
-
-  /* s3->tmp is used to store messages that are unexpected, caused
-   * by the absence of an optional handshake message */
-  if (ssl->s3->tmp.reuse_message) {
-    /* A ssl_dont_hash_message call cannot be combined with reuse_message; the
-     * ssl_dont_hash_message would have to have been applied to the previous
-     * call. */
-    assert(hash_message == ssl_hash_message);
-    ssl->s3->tmp.reuse_message = 0;
-    if (msg_type >= 0 && ssl->s3->tmp.message_type != msg_type) {
-      al = SSL_AD_UNEXPECTED_MESSAGE;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
-      goto f_err;
-    }
-    *ok = 1;
-    ssl->init_msg = (uint8_t *)ssl->init_buf->data + DTLS1_HM_HEADER_LENGTH;
-    ssl->init_num = (int)ssl->s3->tmp.message_size;
-    return ssl->init_num;
-  }
-
-  /* Process fragments until one is found. */
-  while (!dtls1_is_next_message_complete(ssl)) {
-    int ret = dtls1_process_fragment(ssl);
-    if (ret <= 0) {
-      *ok = 0;
-      return ret;
-    }
-  }
-
-  /* Read out the next complete handshake message. */
-  item = pqueue_pop(ssl->d1->buffered_messages);
-  assert(item != NULL);
-  frag = (hm_fragment *)item->data;
-  assert(ssl->d1->handshake_read_seq == frag->msg_header.seq);
-  assert(frag->reassembly == NULL);
-
-  if (frag->msg_header.msg_len > (size_t)max) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_EXCESSIVE_MESSAGE_SIZE);
-    goto err;
-  }
-
-  /* Reconstruct the assembled message. */
-  size_t len;
-  CBB cbb;
-  CBB_zero(&cbb);
-  if (!BUF_MEM_grow(ssl->init_buf, (size_t)frag->msg_header.msg_len +
-                                       DTLS1_HM_HEADER_LENGTH) ||
-      !CBB_init_fixed(&cbb, (uint8_t *)ssl->init_buf->data,
-                      ssl->init_buf->max) ||
-      !CBB_add_u8(&cbb, frag->msg_header.type) ||
-      !CBB_add_u24(&cbb, frag->msg_header.msg_len) ||
-      !CBB_add_u16(&cbb, frag->msg_header.seq) ||
-      !CBB_add_u24(&cbb, 0 /* frag_off */) ||
-      !CBB_add_u24(&cbb, frag->msg_header.msg_len) ||
-      !CBB_add_bytes(&cbb, frag->fragment, frag->msg_header.msg_len) ||
-      !CBB_finish(&cbb, NULL, &len)) {
-    CBB_cleanup(&cbb);
-    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-    goto err;
-  }
-  assert(len == (size_t)frag->msg_header.msg_len + DTLS1_HM_HEADER_LENGTH);
-
-  ssl->d1->handshake_read_seq++;
-
-  /* TODO(davidben): This function has a lot of implicit outputs. Simplify the
-   * |ssl_get_message| API. */
-  ssl->s3->tmp.message_type = frag->msg_header.type;
-  ssl->s3->tmp.message_size = frag->msg_header.msg_len;
-  ssl->init_msg = (uint8_t *)ssl->init_buf->data + DTLS1_HM_HEADER_LENGTH;
-  ssl->init_num = frag->msg_header.msg_len;
-
-  if (msg_type >= 0 && ssl->s3->tmp.message_type != msg_type) {
-    al = SSL_AD_UNEXPECTED_MESSAGE;
-    OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
-    goto f_err;
-  }
-  if (hash_message == ssl_hash_message && !ssl3_hash_current_message(ssl)) {
-    goto err;
-  }
-  if (ssl->msg_callback) {
-    ssl->msg_callback(0, ssl->version, SSL3_RT_HANDSHAKE, ssl->init_buf->data,
-                    ssl->init_num + DTLS1_HM_HEADER_LENGTH, ssl,
-                    ssl->msg_callback_arg);
-  }
-
-  pitem_free(item);
-  dtls1_hm_fragment_free(frag);
-
-  ssl->state = stn;
-  *ok = 1;
-  return ssl->init_num;
-
-f_err:
-  ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
-err:
-  pitem_free(item);
-  dtls1_hm_fragment_free(frag);
-  *ok = 0;
-  return -1;
-}
-
-int dtls1_read_failed(SSL *ssl, int code) {
-  if (code > 0) {
-    assert(0);
-    return 1;
-  }
-
-  if (!dtls1_is_timer_expired(ssl)) {
-    /* not a timeout, none of our business, let higher layers handle this. In
-     * fact, it's probably an error */
-    return code;
-  }
-
-  if (!SSL_in_init(ssl)) {
-    /* done, no need to send a retransmit */
-    BIO_set_flags(SSL_get_rbio(ssl), BIO_FLAGS_READ);
-    return code;
-  }
-
-  return DTLSv1_handle_timeout(ssl);
-}
-
-static uint16_t dtls1_get_queue_priority(uint16_t seq, int is_ccs) {
-  assert(seq * 2 >= seq);
-
-  /* The index of the retransmission queue actually is the message sequence
-   * number, since the queue only contains messages of a single handshake.
-   * However, the ChangeCipherSpec has no message sequence number and so using
-   * only the sequence will result in the CCS and Finished having the same
-   * index. To prevent this, the sequence number is multiplied by 2. In case of
-   * a CCS 1 is subtracted. This does not only differ CSS and Finished, it also
-   * maintains the order of the index (important for priority queues) and fits
-   * in the unsigned short variable. */
-  return seq * 2 - is_ccs;
-}
-
-static int dtls1_retransmit_message(SSL *ssl, hm_fragment *frag) {
-  /* DTLS renegotiation is unsupported, so only epochs 0 (NULL cipher) and 1
-   * (negotiated cipher) exist. */
-  assert(ssl->d1->w_epoch == 0 || ssl->d1->w_epoch == 1);
-  assert(frag->msg_header.epoch <= ssl->d1->w_epoch);
-  enum dtls1_use_epoch_t use_epoch = dtls1_use_current_epoch;
-  if (ssl->d1->w_epoch == 1 && frag->msg_header.epoch == 0) {
-    use_epoch = dtls1_use_previous_epoch;
-  }
-
-  /* TODO(davidben): This cannot handle non-blocking writes. */
-  int ret;
-  if (frag->msg_header.is_ccs) {
-    ret = dtls1_write_change_cipher_spec(ssl, use_epoch);
-  } else {
-    /* Restore the message body.
-     * TODO(davidben): Make this less stateful. */
-    memcpy(ssl->init_buf->data, frag->fragment,
-           frag->msg_header.msg_len + DTLS1_HM_HEADER_LENGTH);
-    ssl->init_num = frag->msg_header.msg_len + DTLS1_HM_HEADER_LENGTH;
-
-    dtls1_set_message_header(ssl, frag->msg_header.type,
-                             frag->msg_header.msg_len, frag->msg_header.seq,
-                             0, frag->msg_header.frag_len);
-    ret = dtls1_do_handshake_write(ssl, use_epoch);
-  }
-
-  /* TODO(davidben): Check return value? */
-  (void)BIO_flush(SSL_get_wbio(ssl));
-  return ret;
-}
-
-
-int dtls1_retransmit_buffered_messages(SSL *ssl) {
-  pqueue sent = ssl->d1->sent_messages;
-  piterator iter = pqueue_iterator(sent);
-  pitem *item;
-
-  for (item = pqueue_next(&iter); item != NULL; item = pqueue_next(&iter)) {
-    hm_fragment *frag = (hm_fragment *)item->data;
-    if (dtls1_retransmit_message(ssl, frag) <= 0) {
-      return -1;
-    }
-  }
-
-  return 1;
-}
-
-/* dtls1_buffer_change_cipher_spec adds a ChangeCipherSpec to the current
- * handshake flight, ordered just before the handshake message numbered
- * |seq|. */
-static int dtls1_buffer_change_cipher_spec(SSL *ssl, uint16_t seq) {
-  hm_fragment *frag = dtls1_hm_fragment_new(0 /* frag_len */,
-                                            0 /* no reassembly */);
-  if (frag == NULL) {
-    return 0;
-  }
-  frag->msg_header.is_ccs = 1;
-  frag->msg_header.epoch = ssl->d1->w_epoch;
-
-  uint16_t priority = dtls1_get_queue_priority(seq, 1 /* is_ccs */);
-  uint8_t seq64be[8];
-  memset(seq64be, 0, sizeof(seq64be));
-  seq64be[6] = (uint8_t)(priority >> 8);
-  seq64be[7] = (uint8_t)priority;
-
-  pitem *item = pitem_new(seq64be, frag);
-  if (item == NULL) {
-    dtls1_hm_fragment_free(frag);
-    return 0;
-  }
-
-  pqueue_insert(ssl->d1->sent_messages, item);
-  return 1;
-}
-
-int dtls1_buffer_message(SSL *ssl) {
-  /* this function is called immediately after a message has
-   * been serialized */
-  assert(ssl->init_off == 0);
-
-  hm_fragment *frag = dtls1_hm_fragment_new(ssl->init_num, 0);
-  if (!frag) {
-    return 0;
-  }
-
-  memcpy(frag->fragment, ssl->init_buf->data, ssl->init_num);
-
-  assert(ssl->d1->w_msg_hdr.msg_len + DTLS1_HM_HEADER_LENGTH ==
-         (unsigned int)ssl->init_num);
-
-  frag->msg_header.msg_len = ssl->d1->w_msg_hdr.msg_len;
-  frag->msg_header.seq = ssl->d1->w_msg_hdr.seq;
-  frag->msg_header.type = ssl->d1->w_msg_hdr.type;
-  frag->msg_header.frag_off = 0;
-  frag->msg_header.frag_len = ssl->d1->w_msg_hdr.msg_len;
-  frag->msg_header.is_ccs = 0;
-  frag->msg_header.epoch = ssl->d1->w_epoch;
-
-  uint16_t priority = dtls1_get_queue_priority(frag->msg_header.seq,
-                                               0 /* handshake */);
-  uint8_t seq64be[8];
-  memset(seq64be, 0, sizeof(seq64be));
-  seq64be[6] = (uint8_t)(priority >> 8);
-  seq64be[7] = (uint8_t)priority;
-
-  pitem *item = pitem_new(seq64be, frag);
-  if (item == NULL) {
-    dtls1_hm_fragment_free(frag);
-    return 0;
-  }
-
-  pqueue_insert(ssl->d1->sent_messages, item);
-  return 1;
-}
-
-int dtls1_send_change_cipher_spec(SSL *ssl, int a, int b) {
-  if (ssl->state == a) {
-    /* Buffer the message to handle retransmits. */
-    ssl->d1->handshake_write_seq = ssl->d1->next_handshake_write_seq;
-    dtls1_buffer_change_cipher_spec(ssl, ssl->d1->handshake_write_seq);
-    ssl->state = b;
-  }
-
-  return dtls1_write_change_cipher_spec(ssl, dtls1_use_current_epoch);
-}
-
-/* call this function when the buffered messages are no longer needed */
-void dtls1_clear_record_buffer(SSL *ssl) {
-  pitem *item;
-
-  for (item = pqueue_pop(ssl->d1->sent_messages); item != NULL;
-       item = pqueue_pop(ssl->d1->sent_messages)) {
-    dtls1_hm_fragment_free((hm_fragment *)item->data);
-    pitem_free(item);
-  }
-}
-
-/* don't actually do the writing, wait till the MTU has been retrieved */
-void dtls1_set_message_header(SSL *ssl, uint8_t mt, unsigned long len,
-                              unsigned short seq_num, unsigned long frag_off,
-                              unsigned long frag_len) {
-  struct hm_header_st *msg_hdr = &ssl->d1->w_msg_hdr;
-
-  msg_hdr->type = mt;
-  msg_hdr->msg_len = len;
-  msg_hdr->seq = seq_num;
-  msg_hdr->frag_off = frag_off;
-  msg_hdr->frag_len = frag_len;
+  return dtls1_flush_flight(ssl);
 }
 
 unsigned int dtls1_min_mtu(void) {
   return kMinMTU;
 }
-
-void dtls1_get_message_header(uint8_t *data,
-                              struct hm_header_st *msg_hdr) {
-  memset(msg_hdr, 0x00, sizeof(struct hm_header_st));
-  msg_hdr->type = *(data++);
-  n2l3(data, msg_hdr->msg_len);
-
-  n2s(data, msg_hdr->seq);
-  n2l3(data, msg_hdr->frag_off);
-  n2l3(data, msg_hdr->frag_len);
-}
diff --git a/src/ssl/d1_clnt.c b/src/ssl/d1_clnt.c
deleted file mode 100644
index ad5eb50..0000000
--- a/src/ssl/d1_clnt.c
+++ /dev/null
@@ -1,566 +0,0 @@
-/*
- * DTLS implementation written by Nagendra Modadugu
- * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. 
- */
-/* ====================================================================
- * Copyright (c) 1999-2007 The OpenSSL Project.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- *    software must display the following acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- *    endorse or promote products derived from this software without
- *    prior written permission. For written permission, please contact
- *    openssl-core@OpenSSL.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- *    nor may "OpenSSL" appear in their names without prior written
- *    permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- *    acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- *
- * This product includes cryptographic software written by Eric Young
- * (eay@cryptsoft.com).  This product includes software written by Tim
- * Hudson (tjh@cryptsoft.com).
- *
- */
-/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to.  The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *    "This product includes cryptographic software written by
- *     Eric Young (eay@cryptsoft.com)"
- *    The word 'cryptographic' can be left out if the rouines from the library
- *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- *    the apps directory (application code) you must include an acknowledgement:
- *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed.  i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- */
-
-#include <openssl/ssl.h>
-
-#include <assert.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <openssl/bn.h>
-#include <openssl/buf.h>
-#include <openssl/dh.h>
-#include <openssl/evp.h>
-#include <openssl/err.h>
-#include <openssl/md5.h>
-#include <openssl/mem.h>
-#include <openssl/obj.h>
-#include <openssl/rand.h>
-
-#include "internal.h"
-
-
-static int dtls1_get_hello_verify(SSL *ssl);
-
-int dtls1_connect(SSL *ssl) {
-  BUF_MEM *buf = NULL;
-  void (*cb)(const SSL *ssl, int type, int value) = NULL;
-  int ret = -1;
-  int new_state, state, skip = 0;
-
-  assert(ssl->handshake_func == dtls1_connect);
-  assert(!ssl->server);
-  assert(SSL_IS_DTLS(ssl));
-
-  ERR_clear_error();
-  ERR_clear_system_error();
-
-  if (ssl->info_callback != NULL) {
-    cb = ssl->info_callback;
-  } else if (ssl->ctx->info_callback != NULL) {
-    cb = ssl->ctx->info_callback;
-  }
-
-  ssl->in_handshake++;
-
-  for (;;) {
-    state = ssl->state;
-
-    switch (ssl->state) {
-      case SSL_ST_CONNECT:
-        if (cb != NULL) {
-          cb(ssl, SSL_CB_HANDSHAKE_START, 1);
-        }
-
-        if (ssl->init_buf == NULL) {
-          buf = BUF_MEM_new();
-          if (buf == NULL ||
-              !BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
-            ret = -1;
-            goto end;
-          }
-          ssl->init_buf = buf;
-          buf = NULL;
-        }
-
-        if (!ssl_init_wbio_buffer(ssl, 0)) {
-          ret = -1;
-          goto end;
-        }
-
-        /* don't push the buffering BIO quite yet */
-
-        ssl->state = SSL3_ST_CW_CLNT_HELLO_A;
-        ssl->init_num = 0;
-        ssl->d1->send_cookie = 0;
-        ssl->hit = 0;
-        break;
-
-      case SSL3_ST_CW_CLNT_HELLO_A:
-      case SSL3_ST_CW_CLNT_HELLO_B:
-        ssl->shutdown = 0;
-        dtls1_start_timer(ssl);
-        ret = ssl3_send_client_hello(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-
-        if (ssl->d1->send_cookie) {
-          ssl->state = SSL3_ST_CW_FLUSH;
-          ssl->s3->tmp.next_state = SSL3_ST_CR_SRVR_HELLO_A;
-        } else {
-          ssl->state = DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A;
-        }
-
-        ssl->init_num = 0;
-        /* turn on buffering for the next lot of output */
-        if (ssl->bbio != ssl->wbio) {
-          ssl->wbio = BIO_push(ssl->bbio, ssl->wbio);
-        }
-
-        break;
-
-      case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A:
-      case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B:
-        ret = dtls1_get_hello_verify(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        if (ssl->d1->send_cookie) {
-          /* start again, with a cookie */
-          dtls1_stop_timer(ssl);
-          ssl->state = SSL3_ST_CW_CLNT_HELLO_A;
-        } else {
-          ssl->state = SSL3_ST_CR_SRVR_HELLO_A;
-        }
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_CR_SRVR_HELLO_A:
-      case SSL3_ST_CR_SRVR_HELLO_B:
-        ret = ssl3_get_server_hello(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-
-        if (ssl->hit) {
-          ssl->state = SSL3_ST_CR_CHANGE;
-          if (ssl->tlsext_ticket_expected) {
-            /* receive renewed session ticket */
-            ssl->state = SSL3_ST_CR_SESSION_TICKET_A;
-          }
-        } else {
-          ssl->state = SSL3_ST_CR_CERT_A;
-        }
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_CR_CERT_A:
-      case SSL3_ST_CR_CERT_B:
-        if (ssl_cipher_has_server_public_key(ssl->s3->tmp.new_cipher)) {
-          ret = ssl3_get_server_certificate(ssl);
-          if (ret <= 0) {
-            goto end;
-          }
-          if (ssl->s3->tmp.certificate_status_expected) {
-            ssl->state = SSL3_ST_CR_CERT_STATUS_A;
-          } else {
-            ssl->state = SSL3_ST_VERIFY_SERVER_CERT;
-          }
-        } else {
-          skip = 1;
-          ssl->state = SSL3_ST_CR_KEY_EXCH_A;
-        }
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_VERIFY_SERVER_CERT:
-        ret = ssl3_verify_server_cert(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-
-        ssl->state = SSL3_ST_CR_KEY_EXCH_A;
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_CR_KEY_EXCH_A:
-      case SSL3_ST_CR_KEY_EXCH_B:
-        ret = ssl3_get_server_key_exchange(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        ssl->state = SSL3_ST_CR_CERT_REQ_A;
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_CR_CERT_REQ_A:
-      case SSL3_ST_CR_CERT_REQ_B:
-        ret = ssl3_get_certificate_request(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        ssl->state = SSL3_ST_CR_SRVR_DONE_A;
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_CR_SRVR_DONE_A:
-      case SSL3_ST_CR_SRVR_DONE_B:
-        ret = ssl3_get_server_done(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        dtls1_stop_timer(ssl);
-        if (ssl->s3->tmp.cert_req) {
-          ssl->s3->tmp.next_state = SSL3_ST_CW_CERT_A;
-        } else {
-          ssl->s3->tmp.next_state = SSL3_ST_CW_KEY_EXCH_A;
-        }
-        ssl->init_num = 0;
-        ssl->state = ssl->s3->tmp.next_state;
-        break;
-
-      case SSL3_ST_CW_CERT_A:
-      case SSL3_ST_CW_CERT_B:
-      case SSL3_ST_CW_CERT_C:
-      case SSL3_ST_CW_CERT_D:
-        dtls1_start_timer(ssl);
-        ret = ssl3_send_client_certificate(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        ssl->state = SSL3_ST_CW_KEY_EXCH_A;
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_CW_KEY_EXCH_A:
-      case SSL3_ST_CW_KEY_EXCH_B:
-        dtls1_start_timer(ssl);
-        ret = ssl3_send_client_key_exchange(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        /* For TLS, cert_req is set to 2, so a cert chain
-         * of nothing is sent, but no verify packet is sent */
-        if (ssl->s3->tmp.cert_req == 1) {
-          ssl->state = SSL3_ST_CW_CERT_VRFY_A;
-        } else {
-          ssl->state = SSL3_ST_CW_CHANGE_A;
-        }
-
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_CW_CERT_VRFY_A:
-      case SSL3_ST_CW_CERT_VRFY_B:
-      case SSL3_ST_CW_CERT_VRFY_C:
-        dtls1_start_timer(ssl);
-        ret = ssl3_send_cert_verify(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        ssl->state = SSL3_ST_CW_CHANGE_A;
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_CW_CHANGE_A:
-      case SSL3_ST_CW_CHANGE_B:
-        if (!ssl->hit) {
-          dtls1_start_timer(ssl);
-        }
-        ret = dtls1_send_change_cipher_spec(ssl, SSL3_ST_CW_CHANGE_A,
-                                            SSL3_ST_CW_CHANGE_B);
-        if (ret <= 0) {
-          goto end;
-        }
-
-        ssl->state = SSL3_ST_CW_FINISHED_A;
-        ssl->init_num = 0;
-
-        ssl->session->cipher = ssl->s3->tmp.new_cipher;
-        if (!ssl->enc_method->setup_key_block(ssl) ||
-            !ssl->enc_method->change_cipher_state(
-                ssl, SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
-          ret = -1;
-          goto end;
-        }
-        break;
-
-      case SSL3_ST_CW_FINISHED_A:
-      case SSL3_ST_CW_FINISHED_B:
-        if (!ssl->hit) {
-          dtls1_start_timer(ssl);
-        }
-
-        ret =
-            ssl3_send_finished(ssl, SSL3_ST_CW_FINISHED_A, SSL3_ST_CW_FINISHED_B,
-                               ssl->enc_method->client_finished_label,
-                               ssl->enc_method->client_finished_label_len);
-        if (ret <= 0) {
-          goto end;
-        }
-        ssl->state = SSL3_ST_CW_FLUSH;
-
-        if (ssl->hit) {
-          ssl->s3->tmp.next_state = SSL_ST_OK;
-        } else {
-          /* Allow NewSessionTicket if ticket expected */
-          if (ssl->tlsext_ticket_expected) {
-            ssl->s3->tmp.next_state = SSL3_ST_CR_SESSION_TICKET_A;
-          } else {
-            ssl->s3->tmp.next_state = SSL3_ST_CR_CHANGE;
-          }
-        }
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_CR_SESSION_TICKET_A:
-      case SSL3_ST_CR_SESSION_TICKET_B:
-        ret = ssl3_get_new_session_ticket(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        ssl->state = SSL3_ST_CR_CHANGE;
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_CR_CERT_STATUS_A:
-      case SSL3_ST_CR_CERT_STATUS_B:
-        ret = ssl3_get_cert_status(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        ssl->state = SSL3_ST_VERIFY_SERVER_CERT;
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_CR_CHANGE:
-        ret = ssl->method->ssl_read_change_cipher_spec(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-
-        if (!ssl3_do_change_cipher_spec(ssl)) {
-          ret = -1;
-          goto end;
-        }
-        ssl->state = SSL3_ST_CR_FINISHED_A;
-        break;
-
-      case SSL3_ST_CR_FINISHED_A:
-      case SSL3_ST_CR_FINISHED_B:
-        ret =
-            ssl3_get_finished(ssl, SSL3_ST_CR_FINISHED_A, SSL3_ST_CR_FINISHED_B);
-        if (ret <= 0) {
-          goto end;
-        }
-        dtls1_stop_timer(ssl);
-
-        if (ssl->hit) {
-          ssl->state = SSL3_ST_CW_CHANGE_A;
-        } else {
-          ssl->state = SSL_ST_OK;
-        }
-
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_CW_FLUSH:
-        ssl->rwstate = SSL_WRITING;
-        if (BIO_flush(ssl->wbio) <= 0) {
-          ret = -1;
-          goto end;
-        }
-        ssl->rwstate = SSL_NOTHING;
-        ssl->state = ssl->s3->tmp.next_state;
-        break;
-
-      case SSL_ST_OK:
-        /* clean a few things up */
-        ssl3_cleanup_key_block(ssl);
-
-        /* Remove write buffering now. */
-        ssl_free_wbio_buffer(ssl);
-
-        ssl->init_num = 0;
-        ssl->s3->initial_handshake_complete = 1;
-
-        ssl_update_cache(ssl, SSL_SESS_CACHE_CLIENT);
-
-        ret = 1;
-
-        if (cb != NULL) {
-          cb(ssl, SSL_CB_HANDSHAKE_DONE, 1);
-        }
-
-        /* done with handshaking */
-        ssl->d1->handshake_read_seq = 0;
-        ssl->d1->next_handshake_write_seq = 0;
-        goto end;
-
-      default:
-        OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_STATE);
-        ret = -1;
-        goto end;
-    }
-
-    /* did we do anything? */
-    if (!ssl->s3->tmp.reuse_message && !skip) {
-      if ((cb != NULL) && (ssl->state != state)) {
-        new_state = ssl->state;
-        ssl->state = state;
-        cb(ssl, SSL_CB_CONNECT_LOOP, 1);
-        ssl->state = new_state;
-      }
-    }
-    skip = 0;
-  }
-
-end:
-  ssl->in_handshake--;
-
-  BUF_MEM_free(buf);
-  if (cb != NULL) {
-    cb(ssl, SSL_CB_CONNECT_EXIT, ret);
-  }
-  return ret;
-}
-
-static int dtls1_get_hello_verify(SSL *ssl) {
-  long n;
-  int al, ok = 0;
-  CBS hello_verify_request, cookie;
-  uint16_t server_version;
-
-  n = ssl->method->ssl_get_message(
-      ssl, DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A,
-      DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B, -1,
-      /* Use the same maximum size as ssl3_get_server_hello. */
-      20000, ssl_hash_message, &ok);
-
-  if (!ok) {
-    return n;
-  }
-
-  if (ssl->s3->tmp.message_type != DTLS1_MT_HELLO_VERIFY_REQUEST) {
-    ssl->d1->send_cookie = 0;
-    ssl->s3->tmp.reuse_message = 1;
-    return 1;
-  }
-
-  CBS_init(&hello_verify_request, ssl->init_msg, n);
-
-  if (!CBS_get_u16(&hello_verify_request, &server_version) ||
-      !CBS_get_u8_length_prefixed(&hello_verify_request, &cookie) ||
-      CBS_len(&hello_verify_request) != 0) {
-    al = SSL_AD_DECODE_ERROR;
-    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
-    goto f_err;
-  }
-
-  if (CBS_len(&cookie) > sizeof(ssl->d1->cookie)) {
-    al = SSL_AD_ILLEGAL_PARAMETER;
-    goto f_err;
-  }
-
-  memcpy(ssl->d1->cookie, CBS_data(&cookie), CBS_len(&cookie));
-  ssl->d1->cookie_len = CBS_len(&cookie);
-
-  ssl->d1->send_cookie = 1;
-  return 1;
-
-f_err:
-  ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
-  return -1;
-}
diff --git a/src/ssl/d1_lib.c b/src/ssl/d1_lib.c
index 7f08b06..ef15252 100644
--- a/src/ssl/d1_lib.c
+++ b/src/ssl/d1_lib.c
@@ -56,22 +56,17 @@
 
 #include <openssl/ssl.h>
 
+#include <assert.h>
 #include <limits.h>
-#include <stdio.h>
 #include <string.h>
 
 #include <openssl/err.h>
 #include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
 
+#include "../crypto/internal.h"
 #include "internal.h"
 
-#if defined(OPENSSL_WINDOWS)
-#include <sys/timeb.h>
-#else
-#include <sys/socket.h>
-#include <sys/time.h>
-#endif
 
 
 /* DTLS1_MTU_TIMEOUTS is the maximum number of timeouts to expire
@@ -82,8 +77,6 @@
  * before failing the DTLS handshake. */
 #define DTLS1_MAX_TIMEOUTS                     12
 
-static void get_current_time(const SSL *ssl, struct timeval *out_clock);
-
 int dtls1_new(SSL *ssl) {
   DTLS1_STATE *d1;
 
@@ -95,47 +88,19 @@
     ssl3_free(ssl);
     return 0;
   }
-  memset(d1, 0, sizeof *d1);
-
-  d1->buffered_messages = pqueue_new();
-  d1->sent_messages = pqueue_new();
-
-  if (!d1->buffered_messages || !d1->sent_messages) {
-    pqueue_free(d1->buffered_messages);
-    pqueue_free(d1->sent_messages);
-    OPENSSL_free(d1);
-    ssl3_free(ssl);
-    return 0;
-  }
+  OPENSSL_memset(d1, 0, sizeof *d1);
 
   ssl->d1 = d1;
 
-  /* Set the version to the highest version for DTLS. This controls the initial
-   * state of |ssl->enc_method| and what the API reports as the version prior to
-   * negotiation.
+  /* Set the version to the highest supported version.
    *
-   * TODO(davidben): This is fragile and confusing. */
+   * TODO(davidben): Move this field into |s3|, have it store the normalized
+   * protocol version, and implement this pre-negotiation quirk in |SSL_version|
+   * at the API boundary rather than in internal state. */
   ssl->version = DTLS1_2_VERSION;
   return 1;
 }
 
-static void dtls1_clear_queues(SSL *ssl) {
-  pitem *item = NULL;
-  hm_fragment *frag = NULL;
-
-  while ((item = pqueue_pop(ssl->d1->buffered_messages)) != NULL) {
-    frag = (hm_fragment *)item->data;
-    dtls1_hm_fragment_free(frag);
-    pitem_free(item);
-  }
-
-  while ((item = pqueue_pop(ssl->d1->sent_messages)) != NULL) {
-    frag = (hm_fragment *)item->data;
-    dtls1_hm_fragment_free(frag);
-    pitem_free(item);
-  }
-}
-
 void dtls1_free(SSL *ssl) {
   ssl3_free(ssl);
 
@@ -143,38 +108,37 @@
     return;
   }
 
-  dtls1_clear_queues(ssl);
-
-  pqueue_free(ssl->d1->buffered_messages);
-  pqueue_free(ssl->d1->sent_messages);
+  dtls_clear_incoming_messages(ssl);
+  dtls_clear_outgoing_messages(ssl);
 
   OPENSSL_free(ssl->d1);
   ssl->d1 = NULL;
 }
 
-int dtls1_supports_cipher(const SSL_CIPHER *cipher) {
-  /* DTLS does not support stream ciphers. The NULL cipher is rejected because
-   * it's not needed. */
-  return cipher->algorithm_enc != SSL_RC4 && cipher->algorithm_enc != SSL_eNULL;
+void DTLSv1_set_initial_timeout_duration(SSL *ssl, unsigned int duration_ms) {
+  ssl->initial_timeout_duration_ms = duration_ms;
 }
 
 void dtls1_start_timer(SSL *ssl) {
-  /* If timer is not set, initialize duration with 1 second */
+  /* If timer is not set, initialize duration (by default, 1 second) */
   if (ssl->d1->next_timeout.tv_sec == 0 && ssl->d1->next_timeout.tv_usec == 0) {
-    ssl->d1->timeout_duration = 1;
+    ssl->d1->timeout_duration_ms = ssl->initial_timeout_duration_ms;
   }
 
   /* Set timeout to current time */
-  get_current_time(ssl, &ssl->d1->next_timeout);
+  ssl_get_current_time(ssl, &ssl->d1->next_timeout);
 
   /* Add duration to current time */
-  ssl->d1->next_timeout.tv_sec += ssl->d1->timeout_duration;
-  BIO_ctrl(SSL_get_rbio(ssl), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
-           &ssl->d1->next_timeout);
+  ssl->d1->next_timeout.tv_sec += ssl->d1->timeout_duration_ms / 1000;
+  ssl->d1->next_timeout.tv_usec += (ssl->d1->timeout_duration_ms % 1000) * 1000;
+  if (ssl->d1->next_timeout.tv_usec >= 1000000) {
+    ssl->d1->next_timeout.tv_sec++;
+    ssl->d1->next_timeout.tv_usec -= 1000000;
+  }
 }
 
 int DTLSv1_get_timeout(const SSL *ssl, struct timeval *out) {
-  if (!SSL_IS_DTLS(ssl)) {
+  if (!SSL_is_dtls(ssl)) {
     return 0;
   }
 
@@ -183,33 +147,43 @@
     return 0;
   }
 
-  /* Get current time */
-  struct timeval timenow;
-  get_current_time(ssl, &timenow);
+  struct OPENSSL_timeval timenow;
+  ssl_get_current_time(ssl, &timenow);
 
   /* If timer already expired, set remaining time to 0 */
   if (ssl->d1->next_timeout.tv_sec < timenow.tv_sec ||
       (ssl->d1->next_timeout.tv_sec == timenow.tv_sec &&
        ssl->d1->next_timeout.tv_usec <= timenow.tv_usec)) {
-    memset(out, 0, sizeof(struct timeval));
+    OPENSSL_memset(out, 0, sizeof(*out));
     return 1;
   }
 
   /* Calculate time left until timer expires */
-  memcpy(out, &ssl->d1->next_timeout, sizeof(struct timeval));
-  out->tv_sec -= timenow.tv_sec;
-  out->tv_usec -= timenow.tv_usec;
-  if (out->tv_usec < 0) {
-    out->tv_sec--;
-    out->tv_usec += 1000000;
+  struct OPENSSL_timeval ret;
+  OPENSSL_memcpy(&ret, &ssl->d1->next_timeout, sizeof(ret));
+  ret.tv_sec -= timenow.tv_sec;
+  if (ret.tv_usec >= timenow.tv_usec) {
+    ret.tv_usec -= timenow.tv_usec;
+  } else {
+    ret.tv_usec = 1000000 + ret.tv_usec - timenow.tv_usec;
+    ret.tv_sec--;
   }
 
   /* If remaining time is less than 15 ms, set it to 0 to prevent issues
-   * because of small devergences with socket timeouts. */
-  if (out->tv_sec == 0 && out->tv_usec < 15000) {
-    memset(out, 0, sizeof(struct timeval));
+   * because of small divergences with socket timeouts. */
+  if (ret.tv_sec == 0 && ret.tv_usec < 15000) {
+    OPENSSL_memset(&ret, 0, sizeof(ret));
   }
 
+  /* Clamp the result in case of overflow. */
+  if (ret.tv_sec > INT_MAX) {
+    assert(0);
+    out->tv_sec = INT_MAX;
+  } else {
+    out->tv_sec = ret.tv_sec;
+  }
+
+  out->tv_usec = ret.tv_usec;
   return 1;
 }
 
@@ -231,9 +205,9 @@
 }
 
 void dtls1_double_timeout(SSL *ssl) {
-  ssl->d1->timeout_duration *= 2;
-  if (ssl->d1->timeout_duration > 60) {
-    ssl->d1->timeout_duration = 60;
+  ssl->d1->timeout_duration_ms *= 2;
+  if (ssl->d1->timeout_duration_ms > 60000) {
+    ssl->d1->timeout_duration_ms = 60000;
   }
   dtls1_start_timer(ssl);
 }
@@ -241,12 +215,11 @@
 void dtls1_stop_timer(SSL *ssl) {
   /* Reset everything */
   ssl->d1->num_timeouts = 0;
-  memset(&ssl->d1->next_timeout, 0, sizeof(struct timeval));
-  ssl->d1->timeout_duration = 1;
-  BIO_ctrl(SSL_get_rbio(ssl), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0,
-           &ssl->d1->next_timeout);
+  OPENSSL_memset(&ssl->d1->next_timeout, 0, sizeof(ssl->d1->next_timeout));
+  ssl->d1->timeout_duration_ms = ssl->initial_timeout_duration_ms;
+
   /* Clear retransmission buffer */
-  dtls1_clear_record_buffer(ssl);
+  dtls_clear_outgoing_messages(ssl);
 }
 
 int dtls1_check_timeout_num(SSL *ssl) {
@@ -255,8 +228,7 @@
   /* Reduce MTU after 2 unsuccessful retransmissions */
   if (ssl->d1->num_timeouts > DTLS1_MTU_TIMEOUTS &&
       !(SSL_get_options(ssl) & SSL_OP_NO_QUERY_MTU)) {
-    long mtu = BIO_ctrl(SSL_get_wbio(ssl), BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0,
-                        NULL);
+    long mtu = BIO_ctrl(ssl->wbio, BIO_CTRL_DGRAM_GET_FALLBACK_MTU, 0, NULL);
     if (mtu >= 0 && mtu <= (1 << 30) && (unsigned)mtu >= dtls1_min_mtu()) {
       ssl->d1->mtu = (unsigned)mtu;
     }
@@ -272,7 +244,9 @@
 }
 
 int DTLSv1_handle_timeout(SSL *ssl) {
-  if (!SSL_IS_DTLS(ssl)) {
+  ssl_reset_error_state(ssl);
+
+  if (!SSL_is_dtls(ssl)) {
     return -1;
   }
 
@@ -288,54 +262,5 @@
   }
 
   dtls1_start_timer(ssl);
-  return dtls1_retransmit_buffered_messages(ssl);
-}
-
-static void get_current_time(const SSL *ssl, struct timeval *out_clock) {
-  if (ssl->ctx->current_time_cb != NULL) {
-    ssl->ctx->current_time_cb(ssl, out_clock);
-    return;
-  }
-
-#if defined(OPENSSL_WINDOWS)
-  struct _timeb time;
-  _ftime(&time);
-  out_clock->tv_sec = time.time;
-  out_clock->tv_usec = time.millitm * 1000;
-#else
-  gettimeofday(out_clock, NULL);
-#endif
-}
-
-int dtls1_set_handshake_header(SSL *ssl, int htype, unsigned long len) {
-  uint8_t *message = (uint8_t *)ssl->init_buf->data;
-  const struct hm_header_st *msg_hdr = &ssl->d1->w_msg_hdr;
-  uint8_t serialised_header[DTLS1_HM_HEADER_LENGTH];
-  uint8_t *p = serialised_header;
-
-  ssl->d1->handshake_write_seq = ssl->d1->next_handshake_write_seq;
-  ssl->d1->next_handshake_write_seq++;
-
-  dtls1_set_message_header(ssl, htype, len, ssl->d1->handshake_write_seq, 0,
-                           len);
-  ssl->init_num = (int)len + DTLS1_HM_HEADER_LENGTH;
-  ssl->init_off = 0;
-
-  /* Buffer the message to handle re-xmits */
-  dtls1_buffer_message(ssl);
-
-  /* Add the new message to the handshake hash. Serialize the message
-   * header as if it were a single fragment. */
-  *p++ = msg_hdr->type;
-  l2n3(msg_hdr->msg_len, p);
-  s2n(msg_hdr->seq, p);
-  l2n3(0, p);
-  l2n3(msg_hdr->msg_len, p);
-  return ssl3_update_handshake_hash(ssl, serialised_header,
-                                    sizeof(serialised_header)) &&
-         ssl3_update_handshake_hash(ssl, message + DTLS1_HM_HEADER_LENGTH, len);
-}
-
-int dtls1_handshake_write(SSL *ssl) {
-  return dtls1_do_handshake_write(ssl, dtls1_use_current_epoch);
+  return dtls1_retransmit_outgoing_messages(ssl);
 }
diff --git a/src/ssl/d1_meth.c b/src/ssl/d1_meth.c
deleted file mode 100644
index 49a2595..0000000
--- a/src/ssl/d1_meth.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * DTLS implementation written by Nagendra Modadugu
- * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. 
- */
-/* ====================================================================
- * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- *    software must display the following acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- *    endorse or promote products derived from this software without
- *    prior written permission. For written permission, please contact
- *    openssl-core@OpenSSL.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- *    nor may "OpenSSL" appear in their names without prior written
- *    permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- *    acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- *
- * This product includes cryptographic software written by Eric Young
- * (eay@cryptsoft.com).  This product includes software written by Tim
- * Hudson (tjh@cryptsoft.com). */
-
-#include <openssl/ssl.h>
-
-#include "internal.h"
-
-
-static const SSL_PROTOCOL_METHOD DTLS_protocol_method = {
-    1 /* is_dtls */,
-    dtls1_new,
-    dtls1_free,
-    dtls1_accept,
-    dtls1_connect,
-    dtls1_get_message,
-    dtls1_read_app_data,
-    dtls1_read_change_cipher_spec,
-    dtls1_read_close_notify,
-    dtls1_write_app_data,
-    dtls1_dispatch_alert,
-    dtls1_supports_cipher,
-    DTLS1_HM_HEADER_LENGTH,
-    dtls1_set_handshake_header,
-    dtls1_handshake_write,
-};
-
-const SSL_METHOD *DTLS_method(void) {
-  static const SSL_METHOD method = {
-      0,
-      &DTLS_protocol_method,
-  };
-  return &method;
-}
-
-/* Legacy version-locked methods. */
-
-const SSL_METHOD *DTLSv1_2_method(void) {
-  static const SSL_METHOD method = {
-      DTLS1_2_VERSION,
-      &DTLS_protocol_method,
-  };
-  return &method;
-}
-
-const SSL_METHOD *DTLSv1_method(void) {
-  static const SSL_METHOD method = {
-      DTLS1_VERSION,
-      &DTLS_protocol_method,
-  };
-  return &method;
-}
-
-/* Legacy side-specific methods. */
-
-const SSL_METHOD *DTLSv1_2_server_method(void) {
-  return DTLSv1_2_method();
-}
-
-const SSL_METHOD *DTLSv1_server_method(void) {
-  return DTLSv1_method();
-}
-
-const SSL_METHOD *DTLSv1_2_client_method(void) {
-  return DTLSv1_2_method();
-}
-
-const SSL_METHOD *DTLSv1_client_method(void) {
-  return DTLSv1_method();
-}
-
-const SSL_METHOD *DTLS_server_method(void) {
-  return DTLS_method();
-}
-
-const SSL_METHOD *DTLS_client_method(void) {
-  return DTLS_method();
-}
diff --git a/src/ssl/d1_pkt.c b/src/ssl/d1_pkt.c
index f2ade3a..3444825 100644
--- a/src/ssl/d1_pkt.c
+++ b/src/ssl/d1_pkt.c
@@ -112,72 +112,89 @@
 #include <openssl/ssl.h>
 
 #include <assert.h>
-#include <stdio.h>
 #include <string.h>
 
+#include <openssl/bio.h>
 #include <openssl/buf.h>
+#include <openssl/bytestring.h>
 #include <openssl/mem.h>
 #include <openssl/evp.h>
 #include <openssl/err.h>
 #include <openssl/rand.h>
 
+#include "../crypto/internal.h"
 #include "internal.h"
 
 
-static int do_dtls1_write(SSL *ssl, int type, const uint8_t *buf,
-                          unsigned int len, enum dtls1_use_epoch_t use_epoch);
-
-/* dtls1_get_record reads a new input record. On success, it places it in
- * |ssl->s3->rrec| and returns one. Otherwise it returns <= 0 on error or if
- * more data is needed. */
-static int dtls1_get_record(SSL *ssl) {
+int dtls1_get_record(SSL *ssl) {
 again:
+  switch (ssl->s3->recv_shutdown) {
+    case ssl_shutdown_none:
+      break;
+    case ssl_shutdown_fatal_alert:
+      OPENSSL_PUT_ERROR(SSL, SSL_R_PROTOCOL_IS_SHUTDOWN);
+      return -1;
+    case ssl_shutdown_close_notify:
+      return 0;
+  }
+
   /* Read a new packet if there is no unconsumed one. */
   if (ssl_read_buffer_len(ssl) == 0) {
-    int ret = ssl_read_buffer_extend_to(ssl, 0 /* unused */);
-    if (ret <= 0) {
-      return ret;
+    int read_ret = ssl_read_buffer_extend_to(ssl, 0 /* unused */);
+    if (read_ret < 0 && dtls1_is_timer_expired(ssl)) {
+      /* Historically, timeouts were handled implicitly if the caller did not
+       * handle them.
+       *
+       * TODO(davidben): This was to support blocking sockets but affected
+       * non-blocking sockets. Can it be removed? */
+      int timeout_ret = DTLSv1_handle_timeout(ssl);
+      if (timeout_ret <= 0) {
+        return timeout_ret;
+      }
+      goto again;
+    }
+    if (read_ret <= 0) {
+      return read_ret;
     }
   }
   assert(ssl_read_buffer_len(ssl) > 0);
 
-  /* Ensure the packet is large enough to decrypt in-place. */
-  if (ssl_read_buffer_len(ssl) < ssl_record_prefix_len(ssl)) {
-    ssl_read_buffer_clear(ssl);
-    goto again;
-  }
-
-  uint8_t *out = ssl_read_buffer(ssl) + ssl_record_prefix_len(ssl);
-  size_t max_out = ssl_read_buffer_len(ssl) - ssl_record_prefix_len(ssl);
+  CBS body;
   uint8_t type, alert;
-  size_t len, consumed;
-  switch (dtls_open_record(ssl, &type, out, &len, &consumed, &alert, max_out,
-                           ssl_read_buffer(ssl), ssl_read_buffer_len(ssl))) {
-    case ssl_open_record_success:
-      ssl_read_buffer_consume(ssl, consumed);
+  size_t consumed;
+  enum ssl_open_record_t open_ret =
+      dtls_open_record(ssl, &type, &body, &consumed, &alert,
+                       ssl_read_buffer(ssl), ssl_read_buffer_len(ssl));
+  ssl_read_buffer_consume(ssl, consumed);
+  switch (open_ret) {
+    case ssl_open_record_partial:
+      /* Impossible in DTLS. */
+      break;
 
-      if (len > 0xffff) {
+    case ssl_open_record_success:
+      if (CBS_len(&body) > 0xffff) {
         OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
         return -1;
       }
 
       SSL3_RECORD *rr = &ssl->s3->rrec;
       rr->type = type;
-      rr->length = (uint16_t)len;
-      rr->data = out;
+      rr->length = (uint16_t)CBS_len(&body);
+      rr->data = (uint8_t *)CBS_data(&body);
       return 1;
 
     case ssl_open_record_discard:
-      ssl_read_buffer_consume(ssl, consumed);
       goto again;
 
+    case ssl_open_record_close_notify:
+      return 0;
+
+    case ssl_open_record_fatal_alert:
+      return -1;
+
     case ssl_open_record_error:
       ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
       return -1;
-
-    case ssl_open_record_partial:
-      /* Impossible in DTLS. */
-      break;
   }
 
   assert(0);
@@ -185,251 +202,36 @@
   return -1;
 }
 
-int dtls1_read_app_data(SSL *ssl, uint8_t *buf, int len, int peek) {
-  return dtls1_read_bytes(ssl, SSL3_RT_APPLICATION_DATA, buf, len, peek);
-}
+int dtls1_read_app_data(SSL *ssl, int *out_got_handshake, uint8_t *buf, int len,
+                        int peek) {
+  assert(!SSL_in_init(ssl));
 
-int dtls1_read_change_cipher_spec(SSL *ssl) {
-  uint8_t byte;
-  int ret = dtls1_read_bytes(ssl, SSL3_RT_CHANGE_CIPHER_SPEC, &byte,
-                             1 /* len */, 0 /* no peek */);
-  if (ret <= 0) {
-    return ret;
-  }
-  assert(ret == 1);
+  *out_got_handshake = 0;
+  SSL3_RECORD *rr = &ssl->s3->rrec;
 
-  if (ssl->s3->rrec.length != 0 || byte != SSL3_MT_CCS) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_CHANGE_CIPHER_SPEC);
-    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
-    return -1;
-  }
-
-  if (ssl->msg_callback != NULL) {
-    ssl->msg_callback(0, ssl->version, SSL3_RT_CHANGE_CIPHER_SPEC, &byte, 1,
-                      ssl, ssl->msg_callback_arg);
-  }
-
-  return 1;
-}
-
-void dtls1_read_close_notify(SSL *ssl) {
-  /* Bidirectional shutdown doesn't make sense for an unordered transport. DTLS
-   * alerts also aren't delivered reliably, so we may even time out because the
-   * peer never received our close_notify. Report to the caller that the channel
-   * has fully shut down. */
-  ssl->shutdown |= SSL_RECEIVED_SHUTDOWN;
-}
-
-/* Return up to 'len' payload bytes received in 'type' records.
- * 'type' is one of the following:
- *
- *   -  SSL3_RT_HANDSHAKE (when dtls1_get_message calls us)
- *   -  SSL3_RT_CHANGE_CIPHER_SPEC (when dtls1_read_change_cipher_spec calls us)
- *   -  SSL3_RT_APPLICATION_DATA (when dtls1_read_app_data calls us)
- *
- * If we don't have stored data to work from, read a DTLS record first (possibly
- * multiple records if we still don't have anything to return).
- *
- * This function must handle any surprises the peer may have for us, such as
- * Alert records (e.g. close_notify) and out of records. */
-int dtls1_read_bytes(SSL *ssl, int type, unsigned char *buf, int len, int peek) {
-  int al, i, ret;
-  unsigned int n;
-  SSL3_RECORD *rr;
-  void (*cb)(const SSL *ssl, int type, int value) = NULL;
-
-  if ((type != SSL3_RT_APPLICATION_DATA && type != SSL3_RT_HANDSHAKE &&
-       type != SSL3_RT_CHANGE_CIPHER_SPEC) ||
-      (peek && type != SSL3_RT_APPLICATION_DATA)) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    return -1;
-  }
-
-  if (!ssl->in_handshake && SSL_in_init(ssl)) {
-    /* type == SSL3_RT_APPLICATION_DATA */
-    i = ssl->handshake_func(ssl);
-    if (i < 0) {
-      return i;
-    }
-    if (i == 0) {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_HANDSHAKE_FAILURE);
-      return -1;
-    }
-  }
-
-start:
-  ssl->rwstate = SSL_NOTHING;
-
-  /* ssl->s3->rrec.type     - is the type of record
-   * ssl->s3->rrec.data     - data
-   * ssl->s3->rrec.off      - offset into 'data' for next read
-   * ssl->s3->rrec.length   - number of bytes. */
-  rr = &ssl->s3->rrec;
-
-  /* Check for timeout */
-  if (DTLSv1_handle_timeout(ssl) > 0) {
-    goto start;
-  }
-
-  /* get new packet if necessary */
+again:
   if (rr->length == 0) {
-    ret = dtls1_get_record(ssl);
+    int ret = dtls1_get_record(ssl);
     if (ret <= 0) {
-      ret = dtls1_read_failed(ssl, ret);
-      /* anything other than a timeout is an error */
-      if (ret <= 0) {
-        return ret;
-      } else {
-        goto start;
-      }
+      return ret;
     }
   }
 
-  /* we now have a packet which can be read and processed */
-
-  /* If the other end has shut down, throw anything we read away (even in
-   * 'peek' mode) */
-  if (ssl->shutdown & SSL_RECEIVED_SHUTDOWN) {
-    rr->length = 0;
-    ssl->rwstate = SSL_NOTHING;
-    return 0;
-  }
-
-
-  if (type == rr->type) {
-    /* Make sure that we are not getting application data when we
-     * are doing a handshake for the first time. */
-    if (SSL_in_init(ssl) && (type == SSL3_RT_APPLICATION_DATA) &&
-        (ssl->aead_read_ctx == NULL)) {
-      /* TODO(davidben): Is this check redundant with the handshake_func
-       * check? */
-      al = SSL_AD_UNEXPECTED_MESSAGE;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_APP_DATA_IN_HANDSHAKE);
-      goto f_err;
-    }
-
-    /* Discard empty records. */
-    if (rr->length == 0) {
-      goto start;
-    }
-
-    if (len <= 0) {
-      return len;
-    }
-
-    if ((unsigned int)len > rr->length) {
-      n = rr->length;
-    } else {
-      n = (unsigned int)len;
-    }
-
-    memcpy(buf, rr->data, n);
-    if (!peek) {
-      rr->length -= n;
-      rr->data += n;
-      if (rr->length == 0) {
-        /* The record has been consumed, so we may now clear the buffer. */
-        ssl_read_buffer_discard(ssl);
-      }
-    }
-
-    return n;
-  }
-
-  /* If we get here, then type != rr->type. */
-
-  /* If an alert record, process one alert out of the record. Note that we allow
-   * a single record to contain multiple alerts. */
-  if (rr->type == SSL3_RT_ALERT) {
-    /* Alerts may not be fragmented. */
-    if (rr->length < 2) {
-      al = SSL_AD_DECODE_ERROR;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ALERT);
-      goto f_err;
-    }
-
-    if (ssl->msg_callback) {
-      ssl->msg_callback(0, ssl->version, SSL3_RT_ALERT, rr->data, 2, ssl,
-                      ssl->msg_callback_arg);
-    }
-    const uint8_t alert_level = rr->data[0];
-    const uint8_t alert_descr = rr->data[1];
-    rr->length -= 2;
-    rr->data += 2;
-
-    if (ssl->info_callback != NULL) {
-      cb = ssl->info_callback;
-    } else if (ssl->ctx->info_callback != NULL) {
-      cb = ssl->ctx->info_callback;
-    }
-
-    if (cb != NULL) {
-      uint16_t alert = (alert_level << 8) | alert_descr;
-      cb(ssl, SSL_CB_READ_ALERT, alert);
-    }
-
-    if (alert_level == SSL3_AL_WARNING) {
-      ssl->s3->warn_alert = alert_descr;
-      if (alert_descr == SSL_AD_CLOSE_NOTIFY) {
-        ssl->shutdown |= SSL_RECEIVED_SHUTDOWN;
-        return 0;
-      }
-    } else if (alert_level == SSL3_AL_FATAL) {
-      char tmp[16];
-
-      ssl->rwstate = SSL_NOTHING;
-      ssl->s3->fatal_alert = alert_descr;
-      OPENSSL_PUT_ERROR(SSL, SSL_AD_REASON_OFFSET + alert_descr);
-      BIO_snprintf(tmp, sizeof tmp, "%d", alert_descr);
-      ERR_add_error_data(2, "SSL alert number ", tmp);
-      ssl->shutdown |= SSL_RECEIVED_SHUTDOWN;
-      SSL_CTX_remove_session(ssl->ctx, ssl->session);
-      return 0;
-    } else {
-      al = SSL_AD_ILLEGAL_PARAMETER;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_ALERT_TYPE);
-      goto f_err;
-    }
-
-    goto start;
-  }
-
-  /* Cross-epoch records are discarded, but we may receive out-of-order
-   * application data between ChangeCipherSpec and Finished or a ChangeCipherSpec
-   * before the appropriate point in the handshake. Those must be silently
-   * discarded.
-   *
-   * However, only allow the out-of-order records in the correct epoch.
-   * Application data must come in the encrypted epoch, and ChangeCipherSpec in
-   * the unencrypted epoch (we never renegotiate). Other cases fall through and
-   * fail with a fatal error. */
-  if ((rr->type == SSL3_RT_APPLICATION_DATA && ssl->aead_read_ctx != NULL) ||
-      (rr->type == SSL3_RT_CHANGE_CIPHER_SPEC && ssl->aead_read_ctx == NULL)) {
-    rr->length = 0;
-    goto start;
-  }
-
   if (rr->type == SSL3_RT_HANDSHAKE) {
-    if (type != SSL3_RT_APPLICATION_DATA) {
-      /* Out-of-order handshake record while looking for ChangeCipherSpec. Drop
-       * it silently. */
-      assert(type == SSL3_RT_CHANGE_CIPHER_SPEC);
-      rr->length = 0;
-      goto start;
-    }
-
     /* Parse the first fragment header to determine if this is a pre-CCS or
      * post-CCS handshake record. DTLS resets handshake message numbers on each
      * handshake, so renegotiations and retransmissions are ambiguous. */
-    if (rr->length < DTLS1_HM_HEADER_LENGTH) {
-      al = SSL_AD_DECODE_ERROR;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_HANDSHAKE_RECORD);
-      goto f_err;
-    }
+    CBS cbs, body;
     struct hm_header_st msg_hdr;
-    dtls1_get_message_header(rr->data, &msg_hdr);
+    CBS_init(&cbs, rr->data, rr->length);
+    if (!dtls1_parse_fragment(&cbs, &msg_hdr, &body)) {
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+      OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_HANDSHAKE_RECORD);
+      return -1;
+    }
 
-    if (msg_hdr.type == SSL3_MT_FINISHED) {
+    if (msg_hdr.type == SSL3_MT_FINISHED &&
+        msg_hdr.seq == ssl->d1->handshake_read_seq - 1) {
       if (msg_hdr.frag_off == 0) {
         /* Retransmit our last flight of messages. If the peer sends the second
          * Finished, they may not have received ours. Only do this for the
@@ -438,79 +240,111 @@
           return -1;
         }
 
-        dtls1_retransmit_buffered_messages(ssl);
+        dtls1_retransmit_outgoing_messages(ssl);
       }
 
       rr->length = 0;
-      goto start;
+      goto again;
     }
 
     /* Otherwise, this is a pre-CCS handshake message from an unsupported
      * renegotiation attempt. Fall through to the error path. */
   }
 
-  al = SSL_AD_UNEXPECTED_MESSAGE;
-  OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
+  if (rr->type != SSL3_RT_APPLICATION_DATA) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+    OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
+    return -1;
+  }
 
-f_err:
-  ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
-  return -1;
-}
+  /* Discard empty records. */
+  if (rr->length == 0) {
+    goto again;
+  }
 
-int dtls1_write_app_data(SSL *ssl, const void *buf_, int len) {
-  int i;
+  if (len <= 0) {
+    return len;
+  }
 
-  if (SSL_in_init(ssl) && !ssl->in_handshake) {
-    i = ssl->handshake_func(ssl);
-    if (i < 0) {
-      return i;
-    }
-    if (i == 0) {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_HANDSHAKE_FAILURE);
-      return -1;
+  if ((unsigned)len > rr->length) {
+    len = rr->length;
+  }
+
+  OPENSSL_memcpy(buf, rr->data, len);
+  if (!peek) {
+    /* TODO(davidben): Should the record be truncated instead? This is a
+     * datagram transport. See https://crbug.com/boringssl/65. */
+    rr->length -= len;
+    rr->data += len;
+    if (rr->length == 0) {
+      /* The record has been consumed, so we may now clear the buffer. */
+      ssl_read_buffer_discard(ssl);
     }
   }
 
+  return len;
+}
+
+int dtls1_read_change_cipher_spec(SSL *ssl) {
+  SSL3_RECORD *rr = &ssl->s3->rrec;
+
+again:
+  if (rr->length == 0) {
+    int ret = dtls1_get_record(ssl);
+    if (ret <= 0) {
+      return ret;
+    }
+  }
+
+  /* Drop handshake records silently. The epochs match, so this must be a
+   * retransmit of a message we already received. */
+  if (rr->type == SSL3_RT_HANDSHAKE) {
+    rr->length = 0;
+    goto again;
+  }
+
+  /* Other record types are illegal in this epoch. Note all application data
+   * records come in the encrypted epoch. */
+  if (rr->type != SSL3_RT_CHANGE_CIPHER_SPEC) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+    OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
+    return -1;
+  }
+
+  if (rr->length != 1 || rr->data[0] != SSL3_MT_CCS) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_CHANGE_CIPHER_SPEC);
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+    return -1;
+  }
+
+  ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_CHANGE_CIPHER_SPEC, rr->data,
+                      rr->length);
+
+  rr->length = 0;
+  ssl_read_buffer_discard(ssl);
+  return 1;
+}
+
+void dtls1_read_close_notify(SSL *ssl) {
+  /* Bidirectional shutdown doesn't make sense for an unordered transport. DTLS
+   * alerts also aren't delivered reliably, so we may even time out because the
+   * peer never received our close_notify. Report to the caller that the channel
+   * has fully shut down. */
+  if (ssl->s3->recv_shutdown == ssl_shutdown_none) {
+    ssl->s3->recv_shutdown = ssl_shutdown_close_notify;
+  }
+}
+
+int dtls1_write_app_data(SSL *ssl, const uint8_t *buf, int len) {
+  assert(!SSL_in_init(ssl));
+
   if (len > SSL3_RT_MAX_PLAIN_LENGTH) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_DTLS_MESSAGE_TOO_BIG);
     return -1;
   }
 
-  i = dtls1_write_bytes(ssl, SSL3_RT_APPLICATION_DATA, buf_, len,
-                        dtls1_use_current_epoch);
-  return i;
-}
-
-/* Call this to write data in records of type 'type' It will return <= 0 if not
- * all data has been sent or non-blocking IO. */
-int dtls1_write_bytes(SSL *ssl, int type, const void *buf, int len,
-                      enum dtls1_use_epoch_t use_epoch) {
-  int i;
-
-  assert(len <= SSL3_RT_MAX_PLAIN_LENGTH);
-  ssl->rwstate = SSL_NOTHING;
-  i = do_dtls1_write(ssl, type, buf, len, use_epoch);
-  return i;
-}
-
-static int do_dtls1_write(SSL *ssl, int type, const uint8_t *buf,
-                          unsigned int len, enum dtls1_use_epoch_t use_epoch) {
-  /* There should never be a pending write buffer in DTLS. One can't write half
-   * a datagram, so the write buffer is always dropped in
-   * |ssl_write_buffer_flush|. */
-  assert(!ssl_write_buffer_is_pending(ssl));
-
-  /* If we have an alert to send, lets send it */
-  if (ssl->s3->alert_dispatch) {
-    int ret = ssl->method->ssl_dispatch_alert(ssl);
-    if (ret <= 0) {
-      return ret;
-    }
-    /* if it went, fall through and send more stuff */
-  }
-
-  if (len > SSL3_RT_MAX_PLAIN_LENGTH) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+  if (len < 0) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_LENGTH);
     return -1;
   }
 
@@ -518,7 +352,28 @@
     return 0;
   }
 
-  size_t max_out = len + ssl_max_seal_overhead(ssl);
+  int ret = dtls1_write_record(ssl, SSL3_RT_APPLICATION_DATA, buf, (size_t)len,
+                               dtls1_use_current_epoch);
+  if (ret <= 0) {
+    return ret;
+  }
+  return len;
+}
+
+int dtls1_write_record(SSL *ssl, int type, const uint8_t *buf, size_t len,
+                       enum dtls1_use_epoch_t use_epoch) {
+  assert(len <= SSL3_RT_MAX_PLAIN_LENGTH);
+  /* There should never be a pending write buffer in DTLS. One can't write half
+   * a datagram, so the write buffer is always dropped in
+   * |ssl_write_buffer_flush|. */
+  assert(!ssl_write_buffer_is_pending(ssl));
+
+  if (len > SSL3_RT_MAX_PLAIN_LENGTH) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    return -1;
+  }
+
+  size_t max_out = len + SSL_max_seal_overhead(ssl);
   uint8_t *out;
   size_t ciphertext_len;
   if (!ssl_write_buffer_init(ssl, &out, max_out) ||
@@ -533,46 +388,27 @@
   if (ret <= 0) {
     return ret;
   }
-  return (int)len;
+  return 1;
 }
 
 int dtls1_dispatch_alert(SSL *ssl) {
-  int i, j;
-  void (*cb)(const SSL *ssl, int type, int value) = NULL;
-  uint8_t buf[DTLS1_AL_HEADER_LENGTH];
-  uint8_t *ptr = &buf[0];
-
+  int ret = dtls1_write_record(ssl, SSL3_RT_ALERT, &ssl->s3->send_alert[0], 2,
+                               dtls1_use_current_epoch);
+  if (ret <= 0) {
+    return ret;
+  }
   ssl->s3->alert_dispatch = 0;
 
-  memset(buf, 0x00, sizeof(buf));
-  *ptr++ = ssl->s3->send_alert[0];
-  *ptr++ = ssl->s3->send_alert[1];
-
-  i = do_dtls1_write(ssl, SSL3_RT_ALERT, &buf[0], sizeof(buf),
-                     dtls1_use_current_epoch);
-  if (i <= 0) {
-    ssl->s3->alert_dispatch = 1;
-  } else {
-    if (ssl->s3->send_alert[0] == SSL3_AL_FATAL) {
-      (void)BIO_flush(ssl->wbio);
-    }
-
-    if (ssl->msg_callback) {
-      ssl->msg_callback(1, ssl->version, SSL3_RT_ALERT, ssl->s3->send_alert, 2,
-                        ssl, ssl->msg_callback_arg);
-    }
-
-    if (ssl->info_callback != NULL) {
-      cb = ssl->info_callback;
-    } else if (ssl->ctx->info_callback != NULL) {
-      cb = ssl->ctx->info_callback;
-    }
-
-    if (cb != NULL) {
-      j = (ssl->s3->send_alert[0] << 8) | ssl->s3->send_alert[1];
-      cb(ssl, SSL_CB_WRITE_ALERT, j);
-    }
+  /* If the alert is fatal, flush the BIO now. */
+  if (ssl->s3->send_alert[0] == SSL3_AL_FATAL) {
+    BIO_flush(ssl->wbio);
   }
 
-  return i;
+  ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_ALERT, ssl->s3->send_alert,
+                      2);
+
+  int alert = (ssl->s3->send_alert[0] << 8) | ssl->s3->send_alert[1];
+  ssl_do_info_callback(ssl, SSL_CB_WRITE_ALERT, alert);
+
+  return 1;
 }
diff --git a/src/ssl/d1_srtp.c b/src/ssl/d1_srtp.c
index 5dba8ef..1085377 100644
--- a/src/ssl/d1_srtp.c
+++ b/src/ssl/d1_srtp.c
@@ -116,17 +116,15 @@
 
 #include <openssl/ssl.h>
 
-#include <stdio.h>
 #include <string.h>
 
 #include <openssl/bytestring.h>
 #include <openssl/err.h>
-#include <openssl/obj.h>
 
 #include "internal.h"
 
 
-const SRTP_PROTECTION_PROFILE kSRTPProfiles[] = {
+static const SRTP_PROTECTION_PROFILE kSRTPProfiles[] = {
     {
         "SRTP_AES128_CM_SHA1_80", SRTP_AES128_CM_SHA1_80,
     },
@@ -162,27 +160,27 @@
 
 static int ssl_ctx_make_profiles(const char *profiles_string,
                                  STACK_OF(SRTP_PROTECTION_PROFILE) **out) {
-  STACK_OF(SRTP_PROTECTION_PROFILE) *profiles;
-
-  const char *col;
-  const char *ptr = profiles_string;
-
-  profiles = sk_SRTP_PROTECTION_PROFILE_new_null();
+  STACK_OF(SRTP_PROTECTION_PROFILE) *profiles =
+      sk_SRTP_PROTECTION_PROFILE_new_null();
   if (profiles == NULL) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_SRTP_COULD_NOT_ALLOCATE_PROFILES);
     return 0;
   }
 
+  const char *col;
+  const char *ptr = profiles_string;
   do {
-    const SRTP_PROTECTION_PROFILE *p;
-
     col = strchr(ptr, ':');
-    if (find_profile_by_name(ptr, &p,
-                             col ? (size_t)(col - ptr) : strlen(ptr))) {
-      sk_SRTP_PROTECTION_PROFILE_push(profiles, p);
-    } else {
+
+    const SRTP_PROTECTION_PROFILE *profile;
+    if (!find_profile_by_name(ptr, &profile,
+                              col ? (size_t)(col - ptr) : strlen(ptr))) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_SRTP_UNKNOWN_PROTECTION_PROFILE);
-      return 0;
+      goto err;
+    }
+
+    if (!sk_SRTP_PROTECTION_PROFILE_push(profiles, profile)) {
+      goto err;
     }
 
     if (col) {
@@ -190,9 +188,13 @@
     }
   } while (col);
 
+  sk_SRTP_PROTECTION_PROFILE_free(*out);
   *out = profiles;
-
   return 1;
+
+err:
+  sk_SRTP_PROTECTION_PROFILE_free(profiles);
+  return 0;
 }
 
 int SSL_CTX_set_srtp_profiles(SSL_CTX *ctx, const char *profiles) {
@@ -212,7 +214,7 @@
     return ssl->srtp_profiles;
   }
 
-  if (ssl->ctx != NULL && ssl->ctx->srtp_profiles != NULL) {
+  if (ssl->ctx->srtp_profiles != NULL) {
     return ssl->ctx->srtp_profiles;
   }
 
diff --git a/src/ssl/d1_srvr.c b/src/ssl/d1_srvr.c
deleted file mode 100644
index 3ba9411..0000000
--- a/src/ssl/d1_srvr.c
+++ /dev/null
@@ -1,485 +0,0 @@
-/*
- * DTLS implementation written by Nagendra Modadugu
- * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. 
- */
-/* ====================================================================
- * Copyright (c) 1999-2007 The OpenSSL Project.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- *    software must display the following acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- *    endorse or promote products derived from this software without
- *    prior written permission. For written permission, please contact
- *    openssl-core@OpenSSL.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- *    nor may "OpenSSL" appear in their names without prior written
- *    permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- *    acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- *
- * This product includes cryptographic software written by Eric Young
- * (eay@cryptsoft.com).  This product includes software written by Tim
- * Hudson (tjh@cryptsoft.com).
- *
- */
-/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to.  The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *    "This product includes cryptographic software written by
- *     Eric Young (eay@cryptsoft.com)"
- *    The word 'cryptographic' can be left out if the rouines from the library
- *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- *    the apps directory (application code) you must include an acknowledgement:
- *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed.  i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- */
-
-#include <openssl/ssl.h>
-
-#include <assert.h>
-#include <stdio.h>
-
-#include <openssl/bn.h>
-#include <openssl/buf.h>
-#include <openssl/dh.h>
-#include <openssl/err.h>
-#include <openssl/evp.h>
-#include <openssl/md5.h>
-#include <openssl/obj.h>
-#include <openssl/rand.h>
-#include <openssl/x509.h>
-
-#include "internal.h"
-
-
-int dtls1_accept(SSL *ssl) {
-  BUF_MEM *buf = NULL;
-  void (*cb)(const SSL *ssl, int type, int value) = NULL;
-  uint32_t alg_a;
-  int ret = -1;
-  int new_state, state, skip = 0;
-
-  assert(ssl->handshake_func == dtls1_accept);
-  assert(ssl->server);
-  assert(SSL_IS_DTLS(ssl));
-
-  ERR_clear_error();
-  ERR_clear_system_error();
-
-  if (ssl->info_callback != NULL) {
-    cb = ssl->info_callback;
-  } else if (ssl->ctx->info_callback != NULL) {
-    cb = ssl->ctx->info_callback;
-  }
-
-  ssl->in_handshake++;
-
-  for (;;) {
-    state = ssl->state;
-
-    switch (ssl->state) {
-      case SSL_ST_ACCEPT:
-        if (cb != NULL) {
-          cb(ssl, SSL_CB_HANDSHAKE_START, 1);
-        }
-
-        if (ssl->init_buf == NULL) {
-          buf = BUF_MEM_new();
-          if (buf == NULL || !BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
-            ret = -1;
-            goto end;
-          }
-          ssl->init_buf = buf;
-          buf = NULL;
-        }
-
-        ssl->init_num = 0;
-
-        if (!ssl_init_wbio_buffer(ssl, 1)) {
-          ret = -1;
-          goto end;
-        }
-
-        if (!ssl3_init_handshake_buffer(ssl)) {
-          OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-          ret = -1;
-          goto end;
-        }
-
-        ssl->state = SSL3_ST_SR_CLNT_HELLO_A;
-        break;
-
-      case SSL3_ST_SR_CLNT_HELLO_A:
-      case SSL3_ST_SR_CLNT_HELLO_B:
-      case SSL3_ST_SR_CLNT_HELLO_C:
-      case SSL3_ST_SR_CLNT_HELLO_D:
-        ssl->shutdown = 0;
-        ret = ssl3_get_client_hello(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        dtls1_stop_timer(ssl);
-        ssl->state = SSL3_ST_SW_SRVR_HELLO_A;
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_SW_SRVR_HELLO_A:
-      case SSL3_ST_SW_SRVR_HELLO_B:
-        dtls1_start_timer(ssl);
-        ret = ssl3_send_server_hello(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-
-        if (ssl->hit) {
-          if (ssl->tlsext_ticket_expected) {
-            ssl->state = SSL3_ST_SW_SESSION_TICKET_A;
-          } else {
-            ssl->state = SSL3_ST_SW_CHANGE_A;
-          }
-        } else {
-          ssl->state = SSL3_ST_SW_CERT_A;
-        }
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_SW_CERT_A:
-      case SSL3_ST_SW_CERT_B:
-        if (ssl_cipher_has_server_public_key(ssl->s3->tmp.new_cipher)) {
-          dtls1_start_timer(ssl);
-          ret = ssl3_send_server_certificate(ssl);
-          if (ret <= 0) {
-            goto end;
-          }
-          if (ssl->s3->tmp.certificate_status_expected) {
-            ssl->state = SSL3_ST_SW_CERT_STATUS_A;
-          } else {
-            ssl->state = SSL3_ST_SW_KEY_EXCH_A;
-          }
-        } else {
-          skip = 1;
-          ssl->state = SSL3_ST_SW_KEY_EXCH_A;
-        }
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_SW_CERT_STATUS_A:
-      case SSL3_ST_SW_CERT_STATUS_B:
-        ret = ssl3_send_certificate_status(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        ssl->state = SSL3_ST_SW_KEY_EXCH_A;
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_SW_KEY_EXCH_A:
-      case SSL3_ST_SW_KEY_EXCH_B:
-      case SSL3_ST_SW_KEY_EXCH_C:
-        alg_a = ssl->s3->tmp.new_cipher->algorithm_auth;
-
-        /* Send a ServerKeyExchange message if:
-         * - The key exchange is ephemeral or anonymous
-         *   Diffie-Hellman.
-         * - There is a PSK identity hint.
-         *
-         * TODO(davidben): This logic is currently duplicated
-         * in s3_srvr.c. Fix this. In the meantime, keep them
-         * in sync. */
-        if (ssl_cipher_requires_server_key_exchange(ssl->s3->tmp.new_cipher) ||
-            ((alg_a & SSL_aPSK) && ssl->psk_identity_hint)) {
-          dtls1_start_timer(ssl);
-          ret = ssl3_send_server_key_exchange(ssl);
-          if (ret <= 0) {
-            goto end;
-          }
-        } else {
-          skip = 1;
-        }
-
-        ssl->state = SSL3_ST_SW_CERT_REQ_A;
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_SW_CERT_REQ_A:
-      case SSL3_ST_SW_CERT_REQ_B:
-        if (ssl->s3->tmp.cert_request) {
-          dtls1_start_timer(ssl);
-          ret = ssl3_send_certificate_request(ssl);
-          if (ret <= 0) {
-            goto end;
-          }
-        } else {
-          skip = 1;
-        }
-        ssl->state = SSL3_ST_SW_SRVR_DONE_A;
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_SW_SRVR_DONE_A:
-      case SSL3_ST_SW_SRVR_DONE_B:
-        dtls1_start_timer(ssl);
-        ret = ssl3_send_server_done(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        ssl->s3->tmp.next_state = SSL3_ST_SR_CERT_A;
-        ssl->state = SSL3_ST_SW_FLUSH;
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_SW_FLUSH:
-        ssl->rwstate = SSL_WRITING;
-        if (BIO_flush(ssl->wbio) <= 0) {
-          ret = -1;
-          goto end;
-        }
-        ssl->rwstate = SSL_NOTHING;
-        ssl->state = ssl->s3->tmp.next_state;
-        break;
-
-      case SSL3_ST_SR_CERT_A:
-      case SSL3_ST_SR_CERT_B:
-        if (ssl->s3->tmp.cert_request) {
-          ret = ssl3_get_client_certificate(ssl);
-          if (ret <= 0) {
-            goto end;
-          }
-        }
-        ssl->init_num = 0;
-        ssl->state = SSL3_ST_SR_KEY_EXCH_A;
-        break;
-
-      case SSL3_ST_SR_KEY_EXCH_A:
-      case SSL3_ST_SR_KEY_EXCH_B:
-      case SSL3_ST_SR_KEY_EXCH_C:
-        ret = ssl3_get_client_key_exchange(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        ssl->state = SSL3_ST_SR_CERT_VRFY_A;
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_SR_CERT_VRFY_A:
-      case SSL3_ST_SR_CERT_VRFY_B:
-        ret = ssl3_get_cert_verify(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        ssl->state = SSL3_ST_SR_CHANGE;
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_SR_CHANGE:
-        ret = ssl->method->ssl_read_change_cipher_spec(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-
-        if (!ssl3_do_change_cipher_spec(ssl)) {
-          ret = -1;
-          goto end;
-        }
-
-        ssl->state = SSL3_ST_SR_FINISHED_A;
-        break;
-
-      case SSL3_ST_SR_FINISHED_A:
-      case SSL3_ST_SR_FINISHED_B:
-        ret = ssl3_get_finished(ssl, SSL3_ST_SR_FINISHED_A,
-                                SSL3_ST_SR_FINISHED_B);
-        if (ret <= 0) {
-          goto end;
-        }
-        dtls1_stop_timer(ssl);
-        if (ssl->hit) {
-          ssl->state = SSL_ST_OK;
-        } else if (ssl->tlsext_ticket_expected) {
-          ssl->state = SSL3_ST_SW_SESSION_TICKET_A;
-        } else {
-          ssl->state = SSL3_ST_SW_CHANGE_A;
-        }
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_SW_SESSION_TICKET_A:
-      case SSL3_ST_SW_SESSION_TICKET_B:
-        ret = ssl3_send_new_session_ticket(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        ssl->state = SSL3_ST_SW_CHANGE_A;
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_SW_CHANGE_A:
-      case SSL3_ST_SW_CHANGE_B:
-        ssl->session->cipher = ssl->s3->tmp.new_cipher;
-        if (!ssl->enc_method->setup_key_block(ssl)) {
-          ret = -1;
-          goto end;
-        }
-
-        ret = dtls1_send_change_cipher_spec(ssl, SSL3_ST_SW_CHANGE_A,
-                                            SSL3_ST_SW_CHANGE_B);
-
-        if (ret <= 0) {
-          goto end;
-        }
-
-        ssl->state = SSL3_ST_SW_FINISHED_A;
-        ssl->init_num = 0;
-
-        if (!ssl->enc_method->change_cipher_state(
-                ssl, SSL3_CHANGE_CIPHER_SERVER_WRITE)) {
-          ret = -1;
-          goto end;
-        }
-        break;
-
-      case SSL3_ST_SW_FINISHED_A:
-      case SSL3_ST_SW_FINISHED_B:
-        ret = ssl3_send_finished(ssl, SSL3_ST_SW_FINISHED_A,
-                                 SSL3_ST_SW_FINISHED_B,
-                                 ssl->enc_method->server_finished_label,
-                                 ssl->enc_method->server_finished_label_len);
-        if (ret <= 0) {
-          goto end;
-        }
-        ssl->state = SSL3_ST_SW_FLUSH;
-        if (ssl->hit) {
-          ssl->s3->tmp.next_state = SSL3_ST_SR_CHANGE;
-        } else {
-          ssl->s3->tmp.next_state = SSL_ST_OK;
-        }
-        ssl->init_num = 0;
-        break;
-
-      case SSL_ST_OK:
-        ssl3_cleanup_key_block(ssl);
-
-        /* remove buffering on output */
-        ssl_free_wbio_buffer(ssl);
-
-        ssl->init_num = 0;
-        ssl->s3->initial_handshake_complete = 1;
-
-        ssl_update_cache(ssl, SSL_SESS_CACHE_SERVER);
-
-        if (cb != NULL) {
-          cb(ssl, SSL_CB_HANDSHAKE_DONE, 1);
-        }
-
-        ret = 1;
-
-        /* done handshaking, next message is client hello */
-        ssl->d1->handshake_read_seq = 0;
-        /* next message is server hello */
-        ssl->d1->handshake_write_seq = 0;
-        ssl->d1->next_handshake_write_seq = 0;
-        goto end;
-
-      default:
-        OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_STATE);
-        ret = -1;
-        goto end;
-    }
-
-    if (!ssl->s3->tmp.reuse_message && !skip) {
-      if (cb != NULL && ssl->state != state) {
-        new_state = ssl->state;
-        ssl->state = state;
-        cb(ssl, SSL_CB_ACCEPT_LOOP, 1);
-        ssl->state = new_state;
-      }
-    }
-    skip = 0;
-  }
-
-end:
-  ssl->in_handshake--;
-  BUF_MEM_free(buf);
-  if (cb != NULL) {
-    cb(ssl, SSL_CB_ACCEPT_EXIT, ret);
-  }
-  return ret;
-}
diff --git a/src/ssl/dtls_method.c b/src/ssl/dtls_method.c
new file mode 100644
index 0000000..6084789
--- /dev/null
+++ b/src/ssl/dtls_method.c
@@ -0,0 +1,217 @@
+/*
+ * DTLS implementation written by Nagendra Modadugu
+ * (nagendra@cs.stanford.edu) for the OpenSSL project 2005. 
+ */
+/* ====================================================================
+ * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@OpenSSL.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com). */
+
+#include <openssl/ssl.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/buf.h>
+#include <openssl/err.h>
+
+#include "../crypto/internal.h"
+#include "internal.h"
+
+
+static int dtls1_version_from_wire(uint16_t *out_version,
+                                   uint16_t wire_version) {
+  switch (wire_version) {
+    case DTLS1_VERSION:
+      /* DTLS 1.0 maps to TLS 1.1, not TLS 1.0. */
+      *out_version = TLS1_1_VERSION;
+      return 1;
+    case DTLS1_2_VERSION:
+      *out_version = TLS1_2_VERSION;
+      return 1;
+  }
+
+  return 0;
+}
+
+static uint16_t dtls1_version_to_wire(uint16_t version) {
+  switch (version) {
+    case TLS1_1_VERSION:
+      /* DTLS 1.0 maps to TLS 1.1, not TLS 1.0. */
+      return DTLS1_VERSION;
+    case TLS1_2_VERSION:
+      return DTLS1_2_VERSION;
+  }
+
+  /* It is an error to use this function with an invalid version. */
+  assert(0);
+  return 0;
+}
+
+static int dtls1_supports_cipher(const SSL_CIPHER *cipher) {
+  return cipher->algorithm_enc != SSL_eNULL;
+}
+
+static void dtls1_expect_flight(SSL *ssl) { dtls1_start_timer(ssl); }
+
+static void dtls1_received_flight(SSL *ssl) { dtls1_stop_timer(ssl); }
+
+static int dtls1_set_read_state(SSL *ssl, SSL_AEAD_CTX *aead_ctx) {
+  /* Cipher changes are illegal when there are buffered incoming messages. */
+  if (dtls_has_incoming_messages(ssl)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFERED_MESSAGES_ON_CIPHER_CHANGE);
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+    SSL_AEAD_CTX_free(aead_ctx);
+    return 0;
+  }
+
+  ssl->d1->r_epoch++;
+  OPENSSL_memset(&ssl->d1->bitmap, 0, sizeof(ssl->d1->bitmap));
+  OPENSSL_memset(ssl->s3->read_sequence, 0, sizeof(ssl->s3->read_sequence));
+
+  SSL_AEAD_CTX_free(ssl->s3->aead_read_ctx);
+  ssl->s3->aead_read_ctx = aead_ctx;
+  return 1;
+}
+
+static int dtls1_set_write_state(SSL *ssl, SSL_AEAD_CTX *aead_ctx) {
+  ssl->d1->w_epoch++;
+  OPENSSL_memcpy(ssl->d1->last_write_sequence, ssl->s3->write_sequence,
+                 sizeof(ssl->s3->write_sequence));
+  OPENSSL_memset(ssl->s3->write_sequence, 0, sizeof(ssl->s3->write_sequence));
+
+  SSL_AEAD_CTX_free(ssl->s3->aead_write_ctx);
+  ssl->s3->aead_write_ctx = aead_ctx;
+  return 1;
+}
+
+static const SSL_PROTOCOL_METHOD kDTLSProtocolMethod = {
+    1 /* is_dtls */,
+    TLS1_1_VERSION,
+    TLS1_2_VERSION,
+    dtls1_version_from_wire,
+    dtls1_version_to_wire,
+    dtls1_new,
+    dtls1_free,
+    dtls1_get_message,
+    dtls1_get_current_message,
+    dtls1_release_current_message,
+    dtls1_read_app_data,
+    dtls1_read_change_cipher_spec,
+    dtls1_read_close_notify,
+    dtls1_write_app_data,
+    dtls1_dispatch_alert,
+    dtls1_supports_cipher,
+    dtls1_init_message,
+    dtls1_finish_message,
+    dtls1_add_message,
+    dtls1_add_change_cipher_spec,
+    dtls1_add_alert,
+    dtls1_flush_flight,
+    dtls1_expect_flight,
+    dtls1_received_flight,
+    dtls1_set_read_state,
+    dtls1_set_write_state,
+};
+
+const SSL_METHOD *DTLS_method(void) {
+  static const SSL_METHOD kMethod = {
+      0,
+      &kDTLSProtocolMethod,
+      &ssl_crypto_x509_method,
+  };
+  return &kMethod;
+}
+
+/* Legacy version-locked methods. */
+
+const SSL_METHOD *DTLSv1_2_method(void) {
+  static const SSL_METHOD kMethod = {
+      DTLS1_2_VERSION,
+      &kDTLSProtocolMethod,
+      &ssl_crypto_x509_method,
+  };
+  return &kMethod;
+}
+
+const SSL_METHOD *DTLSv1_method(void) {
+  static const SSL_METHOD kMethod = {
+      DTLS1_VERSION,
+      &kDTLSProtocolMethod,
+      &ssl_crypto_x509_method,
+  };
+  return &kMethod;
+}
+
+/* Legacy side-specific methods. */
+
+const SSL_METHOD *DTLSv1_2_server_method(void) {
+  return DTLSv1_2_method();
+}
+
+const SSL_METHOD *DTLSv1_server_method(void) {
+  return DTLSv1_method();
+}
+
+const SSL_METHOD *DTLSv1_2_client_method(void) {
+  return DTLSv1_2_method();
+}
+
+const SSL_METHOD *DTLSv1_client_method(void) {
+  return DTLSv1_method();
+}
+
+const SSL_METHOD *DTLS_server_method(void) {
+  return DTLS_method();
+}
+
+const SSL_METHOD *DTLS_client_method(void) {
+  return DTLS_method();
+}
diff --git a/src/ssl/dtls_record.c b/src/ssl/dtls_record.c
index 940494a..879706d 100644
--- a/src/ssl/dtls_record.c
+++ b/src/ssl/dtls_record.c
@@ -118,6 +118,7 @@
 #include <openssl/err.h>
 
 #include "internal.h"
+#include "../crypto/internal.h"
 
 
 /* to_u64_be treats |in| as a 8-byte big-endian integer and returns the value as
@@ -171,10 +172,12 @@
   }
 }
 
-enum ssl_open_record_t dtls_open_record(
-    SSL *ssl, uint8_t *out_type, uint8_t *out, size_t *out_len,
-    size_t *out_consumed, uint8_t *out_alert, size_t max_out, const uint8_t *in,
-    size_t in_len) {
+enum ssl_open_record_t dtls_open_record(SSL *ssl, uint8_t *out_type, CBS *out,
+                                        size_t *out_consumed,
+                                        uint8_t *out_alert, uint8_t *in,
+                                        size_t in_len) {
+  *out_consumed = 0;
+
   CBS cbs;
   CBS_init(&cbs, in, in_len);
 
@@ -195,10 +198,8 @@
     return ssl_open_record_discard;
   }
 
-  if (ssl->msg_callback != NULL) {
-    ssl->msg_callback(0 /* read */, 0, SSL3_RT_HEADER, in,
-                      DTLS1_RT_HEADER_LENGTH, ssl, ssl->msg_callback_arg);
-  }
+  ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_HEADER, in,
+                      DTLS1_RT_HEADER_LENGTH);
 
   uint16_t epoch = (((uint16_t)sequence[0]) << 8) | sequence[1];
   if (epoch != ssl->d1->r_epoch ||
@@ -211,11 +212,9 @@
     return ssl_open_record_discard;
   }
 
-  /* Decrypt the body. */
-  size_t plaintext_len;
-  if (!SSL_AEAD_CTX_open(ssl->aead_read_ctx, out, &plaintext_len, max_out,
-                         type, version, sequence, CBS_data(&body),
-                         CBS_len(&body))) {
+  /* Decrypt the body in-place. */
+  if (!SSL_AEAD_CTX_open(ssl->s3->aead_read_ctx, out, type, version, sequence,
+                         (uint8_t *)CBS_data(&body), CBS_len(&body))) {
     /* Bad packets are silently dropped in DTLS. See section 4.2.1 of RFC 6347.
      * Clear the error queue of any errors decryption may have added. Drop the
      * entire packet as it must not have come from the peer.
@@ -226,9 +225,10 @@
     *out_consumed = in_len - CBS_len(&cbs);
     return ssl_open_record_discard;
   }
+  *out_consumed = in_len - CBS_len(&cbs);
 
   /* Check the plaintext length. */
-  if (plaintext_len > SSL3_RT_MAX_PLAIN_LENGTH) {
+  if (CBS_len(out) > SSL3_RT_MAX_PLAIN_LENGTH) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG);
     *out_alert = SSL_AD_RECORD_OVERFLOW;
     return ssl_open_record_error;
@@ -239,18 +239,52 @@
   /* TODO(davidben): Limit the number of empty records as in TLS? This is only
    * useful if we also limit discarded packets. */
 
+  if (type == SSL3_RT_ALERT) {
+    return ssl_process_alert(ssl, out_alert, CBS_data(out), CBS_len(out));
+  }
+
+  ssl->s3->warning_alert_count = 0;
+
   *out_type = type;
-  *out_len = plaintext_len;
-  *out_consumed = in_len - CBS_len(&cbs);
   return ssl_open_record_success;
 }
 
+static const SSL_AEAD_CTX *get_write_aead(const SSL *ssl,
+                                          enum dtls1_use_epoch_t use_epoch) {
+  if (use_epoch == dtls1_use_previous_epoch) {
+    /* DTLS renegotiation is unsupported, so only epochs 0 (NULL cipher) and 1
+     * (negotiated cipher) exist. */
+    assert(ssl->d1->w_epoch == 1);
+    return NULL;
+  }
+
+  return ssl->s3->aead_write_ctx;
+}
+
+size_t dtls_max_seal_overhead(const SSL *ssl,
+                              enum dtls1_use_epoch_t use_epoch) {
+  return DTLS1_RT_HEADER_LENGTH +
+         SSL_AEAD_CTX_max_overhead(get_write_aead(ssl, use_epoch));
+}
+
+size_t dtls_seal_prefix_len(const SSL *ssl, enum dtls1_use_epoch_t use_epoch) {
+  return DTLS1_RT_HEADER_LENGTH +
+         SSL_AEAD_CTX_explicit_nonce_len(get_write_aead(ssl, use_epoch));
+}
+
 int dtls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
                      uint8_t type, const uint8_t *in, size_t in_len,
                      enum dtls1_use_epoch_t use_epoch) {
+  const size_t prefix = dtls_seal_prefix_len(ssl, use_epoch);
+  if (buffers_alias(in, in_len, out, max_out) &&
+      (max_out < prefix || out + prefix != in)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_OUTPUT_ALIASES_INPUT);
+    return 0;
+  }
+
   /* Determine the parameters for the current epoch. */
   uint16_t epoch = ssl->d1->w_epoch;
-  SSL_AEAD_CTX *aead = ssl->aead_write_ctx;
+  SSL_AEAD_CTX *aead = ssl->s3->aead_write_ctx;
   uint8_t *seq = ssl->s3->write_sequence;
   if (use_epoch == dtls1_use_previous_epoch) {
     /* DTLS renegotiation is unsupported, so only epochs 0 (NULL cipher) and 1
@@ -265,12 +299,6 @@
     OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL);
     return 0;
   }
-  /* Check the record header does not alias any part of the input.
-   * |SSL_AEAD_CTX_seal| will internally enforce other aliasing requirements. */
-  if (in < out + DTLS1_RT_HEADER_LENGTH && out < in + in_len) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_OUTPUT_ALIASES_INPUT);
-    return 0;
-  }
 
   out[0] = type;
 
@@ -280,13 +308,13 @@
 
   out[3] = epoch >> 8;
   out[4] = epoch & 0xff;
-  memcpy(&out[5], &seq[2], 6);
+  OPENSSL_memcpy(&out[5], &seq[2], 6);
 
   size_t ciphertext_len;
   if (!SSL_AEAD_CTX_seal(aead, out + DTLS1_RT_HEADER_LENGTH, &ciphertext_len,
                          max_out - DTLS1_RT_HEADER_LENGTH, type, wire_version,
                          &out[3] /* seq */, in, in_len) ||
-      !ssl3_record_sequence_update(&seq[2], 6)) {
+      !ssl_record_sequence_update(&seq[2], 6)) {
     return 0;
   }
 
@@ -299,10 +327,8 @@
 
   *out_len = DTLS1_RT_HEADER_LENGTH + ciphertext_len;
 
-  if (ssl->msg_callback) {
-    ssl->msg_callback(1 /* write */, 0, SSL3_RT_HEADER, out,
-                      DTLS1_RT_HEADER_LENGTH, ssl, ssl->msg_callback_arg);
-  }
+  ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HEADER, out,
+                      DTLS1_RT_HEADER_LENGTH);
 
   return 1;
 }
diff --git a/src/ssl/handshake_client.c b/src/ssl/handshake_client.c
new file mode 100644
index 0000000..7eddd35
--- /dev/null
+++ b/src/ssl/handshake_client.c
@@ -0,0 +1,1936 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * Portions of the attached software ("Contribution") are developed by 
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the OpenSSL open source
+ * license provided above.
+ *
+ * ECC cipher suite support in OpenSSL originally written by
+ * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
+ *
+ */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE.
+ */
+
+#include <openssl/ssl.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/aead.h>
+#include <openssl/bn.h>
+#include <openssl/buf.h>
+#include <openssl/bytestring.h>
+#include <openssl/dh.h>
+#include <openssl/ec_key.h>
+#include <openssl/ecdsa.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/md5.h>
+#include <openssl/mem.h>
+#include <openssl/rand.h>
+
+#include "../crypto/internal.h"
+#include "internal.h"
+
+
+static int ssl3_send_client_hello(SSL_HANDSHAKE *hs);
+static int dtls1_get_hello_verify(SSL_HANDSHAKE *hs);
+static int ssl3_get_server_hello(SSL_HANDSHAKE *hs);
+static int ssl3_get_server_certificate(SSL_HANDSHAKE *hs);
+static int ssl3_get_cert_status(SSL_HANDSHAKE *hs);
+static int ssl3_verify_server_cert(SSL_HANDSHAKE *hs);
+static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs);
+static int ssl3_get_certificate_request(SSL_HANDSHAKE *hs);
+static int ssl3_get_server_hello_done(SSL_HANDSHAKE *hs);
+static int ssl3_send_client_certificate(SSL_HANDSHAKE *hs);
+static int ssl3_send_client_key_exchange(SSL_HANDSHAKE *hs);
+static int ssl3_send_cert_verify(SSL_HANDSHAKE *hs);
+static int ssl3_send_next_proto(SSL_HANDSHAKE *hs);
+static int ssl3_send_channel_id(SSL_HANDSHAKE *hs);
+static int ssl3_get_new_session_ticket(SSL_HANDSHAKE *hs);
+
+int ssl3_connect(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  int ret = -1;
+
+  assert(ssl->handshake_func == ssl3_connect);
+  assert(!ssl->server);
+
+  for (;;) {
+    int state = hs->state;
+
+    switch (hs->state) {
+      case SSL_ST_INIT:
+        ssl_do_info_callback(ssl, SSL_CB_HANDSHAKE_START, 1);
+        hs->state = SSL3_ST_CW_CLNT_HELLO_A;
+        break;
+
+      case SSL3_ST_CW_CLNT_HELLO_A:
+        ret = ssl3_send_client_hello(hs);
+        if (ret <= 0) {
+          goto end;
+        }
+
+        if (!SSL_is_dtls(ssl) || ssl->d1->send_cookie) {
+          if (hs->early_data_offered) {
+            if (!tls13_init_early_key_schedule(hs) ||
+                !tls13_advance_key_schedule(hs, ssl->session->master_key,
+                                            ssl->session->master_key_length) ||
+                !tls13_derive_early_secrets(hs) ||
+                !tls13_set_traffic_key(ssl, evp_aead_seal,
+                                       hs->early_traffic_secret,
+                                       hs->hash_len)) {
+              ret = -1;
+              goto end;
+            }
+          }
+          hs->next_state = SSL3_ST_CR_SRVR_HELLO_A;
+        } else {
+          hs->next_state = DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A;
+        }
+        hs->state = SSL3_ST_CW_FLUSH;
+        break;
+
+      case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A:
+        assert(SSL_is_dtls(ssl));
+        ret = dtls1_get_hello_verify(hs);
+        if (ret <= 0) {
+          goto end;
+        }
+        if (ssl->d1->send_cookie) {
+          ssl->method->received_flight(ssl);
+          hs->state = SSL3_ST_CW_CLNT_HELLO_A;
+        } else {
+          hs->state = SSL3_ST_CR_SRVR_HELLO_A;
+        }
+        break;
+
+      case SSL3_ST_CR_SRVR_HELLO_A:
+        ret = ssl3_get_server_hello(hs);
+        if (hs->state == SSL_ST_TLS13) {
+          break;
+        }
+        if (ret <= 0) {
+          goto end;
+        }
+
+        if (ssl->session != NULL) {
+          hs->state = SSL3_ST_CR_SESSION_TICKET_A;
+        } else {
+          hs->state = SSL3_ST_CR_CERT_A;
+        }
+        break;
+
+      case SSL3_ST_CR_CERT_A:
+        if (ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
+          ret = ssl3_get_server_certificate(hs);
+          if (ret <= 0) {
+            goto end;
+          }
+        }
+        hs->state = SSL3_ST_CR_CERT_STATUS_A;
+        break;
+
+      case SSL3_ST_CR_CERT_STATUS_A:
+        if (hs->certificate_status_expected) {
+          ret = ssl3_get_cert_status(hs);
+          if (ret <= 0) {
+            goto end;
+          }
+        }
+        hs->state = SSL3_ST_VERIFY_SERVER_CERT;
+        break;
+
+      case SSL3_ST_VERIFY_SERVER_CERT:
+        if (ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
+          ret = ssl3_verify_server_cert(hs);
+          if (ret <= 0) {
+            goto end;
+          }
+        }
+        hs->state = SSL3_ST_CR_KEY_EXCH_A;
+        break;
+
+      case SSL3_ST_CR_KEY_EXCH_A:
+        ret = ssl3_get_server_key_exchange(hs);
+        if (ret <= 0) {
+          goto end;
+        }
+        hs->state = SSL3_ST_CR_CERT_REQ_A;
+        break;
+
+      case SSL3_ST_CR_CERT_REQ_A:
+        if (ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
+          ret = ssl3_get_certificate_request(hs);
+          if (ret <= 0) {
+            goto end;
+          }
+        }
+        hs->state = SSL3_ST_CR_SRVR_DONE_A;
+        break;
+
+      case SSL3_ST_CR_SRVR_DONE_A:
+        ret = ssl3_get_server_hello_done(hs);
+        if (ret <= 0) {
+          goto end;
+        }
+        ssl->method->received_flight(ssl);
+        hs->state = SSL3_ST_CW_CERT_A;
+        break;
+
+      case SSL3_ST_CW_CERT_A:
+        if (hs->cert_request) {
+          ret = ssl3_send_client_certificate(hs);
+          if (ret <= 0) {
+            goto end;
+          }
+        }
+        hs->state = SSL3_ST_CW_KEY_EXCH_A;
+        break;
+
+      case SSL3_ST_CW_KEY_EXCH_A:
+        ret = ssl3_send_client_key_exchange(hs);
+        if (ret <= 0) {
+          goto end;
+        }
+        hs->state = SSL3_ST_CW_CERT_VRFY_A;
+        break;
+
+      case SSL3_ST_CW_CERT_VRFY_A:
+      case SSL3_ST_CW_CERT_VRFY_B:
+        if (hs->cert_request && ssl_has_certificate(ssl)) {
+          ret = ssl3_send_cert_verify(hs);
+          if (ret <= 0) {
+            goto end;
+          }
+        }
+        hs->state = SSL3_ST_CW_CHANGE;
+        break;
+
+      case SSL3_ST_CW_CHANGE:
+        if (!ssl->method->add_change_cipher_spec(ssl) ||
+            !tls1_change_cipher_state(hs, SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
+          ret = -1;
+          goto end;
+        }
+
+        hs->state = SSL3_ST_CW_NEXT_PROTO_A;
+        break;
+
+      case SSL3_ST_CW_NEXT_PROTO_A:
+        if (hs->next_proto_neg_seen) {
+          ret = ssl3_send_next_proto(hs);
+          if (ret <= 0) {
+            goto end;
+          }
+        }
+        hs->state = SSL3_ST_CW_CHANNEL_ID_A;
+        break;
+
+      case SSL3_ST_CW_CHANNEL_ID_A:
+        if (ssl->s3->tlsext_channel_id_valid) {
+          ret = ssl3_send_channel_id(hs);
+          if (ret <= 0) {
+            goto end;
+          }
+        }
+        hs->state = SSL3_ST_CW_FINISHED_A;
+        break;
+
+      case SSL3_ST_CW_FINISHED_A:
+        ret = ssl3_send_finished(hs);
+        if (ret <= 0) {
+          goto end;
+        }
+        hs->state = SSL3_ST_CW_FLUSH;
+
+        if (ssl->session != NULL) {
+          hs->next_state = SSL3_ST_FINISH_CLIENT_HANDSHAKE;
+        } else {
+          /* This is a non-resumption handshake. If it involves ChannelID, then
+           * record the handshake hashes at this point in the session so that
+           * any resumption of this session with ChannelID can sign those
+           * hashes. */
+          ret = tls1_record_handshake_hashes_for_channel_id(hs);
+          if (ret <= 0) {
+            goto end;
+          }
+          if ((SSL_get_mode(ssl) & SSL_MODE_ENABLE_FALSE_START) &&
+              ssl3_can_false_start(ssl) &&
+              /* No False Start on renegotiation (would complicate the state
+               * machine). */
+              !ssl->s3->initial_handshake_complete) {
+            hs->next_state = SSL3_ST_FALSE_START;
+          } else {
+            hs->next_state = SSL3_ST_CR_SESSION_TICKET_A;
+          }
+        }
+        break;
+
+      case SSL3_ST_FALSE_START:
+        hs->state = SSL3_ST_CR_SESSION_TICKET_A;
+        hs->in_false_start = 1;
+        hs->can_early_write = 1;
+        ret = 1;
+        goto end;
+
+      case SSL3_ST_CR_SESSION_TICKET_A:
+        if (hs->ticket_expected) {
+          ret = ssl3_get_new_session_ticket(hs);
+          if (ret <= 0) {
+            goto end;
+          }
+        }
+        hs->state = SSL3_ST_CR_CHANGE;
+        break;
+
+      case SSL3_ST_CR_CHANGE:
+        ret = ssl->method->read_change_cipher_spec(ssl);
+        if (ret <= 0) {
+          goto end;
+        }
+
+        if (!tls1_change_cipher_state(hs, SSL3_CHANGE_CIPHER_CLIENT_READ)) {
+          ret = -1;
+          goto end;
+        }
+        hs->state = SSL3_ST_CR_FINISHED_A;
+        break;
+
+      case SSL3_ST_CR_FINISHED_A:
+        ret = ssl3_get_finished(hs);
+        if (ret <= 0) {
+          goto end;
+        }
+        ssl->method->received_flight(ssl);
+
+        if (ssl->session != NULL) {
+          hs->state = SSL3_ST_CW_CHANGE;
+        } else {
+          hs->state = SSL3_ST_FINISH_CLIENT_HANDSHAKE;
+        }
+        break;
+
+      case SSL3_ST_CW_FLUSH:
+        ret = ssl->method->flush_flight(ssl);
+        if (ret <= 0) {
+          goto end;
+        }
+        hs->state = hs->next_state;
+        if (hs->state != SSL3_ST_FINISH_CLIENT_HANDSHAKE) {
+          ssl->method->expect_flight(ssl);
+        }
+        break;
+
+      case SSL_ST_TLS13: {
+        int early_return = 0;
+        ret = tls13_handshake(hs, &early_return);
+        if (ret <= 0) {
+          goto end;
+        }
+
+        if (early_return) {
+          ret = 1;
+          goto end;
+        }
+
+        hs->state = SSL3_ST_FINISH_CLIENT_HANDSHAKE;
+        break;
+      }
+
+      case SSL3_ST_FINISH_CLIENT_HANDSHAKE:
+        ssl->method->release_current_message(ssl, 1 /* free_buffer */);
+
+        SSL_SESSION_free(ssl->s3->established_session);
+        if (ssl->session != NULL) {
+          SSL_SESSION_up_ref(ssl->session);
+          ssl->s3->established_session = ssl->session;
+        } else {
+          /* We make a copy of the session in order to maintain the immutability
+           * of the new established_session due to False Start. The caller may
+           * have taken a reference to the temporary session. */
+          ssl->s3->established_session =
+              SSL_SESSION_dup(hs->new_session, SSL_SESSION_DUP_ALL);
+          if (ssl->s3->established_session == NULL) {
+            ret = -1;
+            goto end;
+          }
+          ssl->s3->established_session->not_resumable = 0;
+
+          SSL_SESSION_free(hs->new_session);
+          hs->new_session = NULL;
+        }
+
+        hs->state = SSL_ST_OK;
+        break;
+
+      case SSL_ST_OK: {
+        const int is_initial_handshake = !ssl->s3->initial_handshake_complete;
+        ssl->s3->initial_handshake_complete = 1;
+        if (is_initial_handshake) {
+          /* Renegotiations do not participate in session resumption. */
+          ssl_update_cache(hs, SSL_SESS_CACHE_CLIENT);
+        }
+
+        ret = 1;
+        ssl_do_info_callback(ssl, SSL_CB_HANDSHAKE_DONE, 1);
+        goto end;
+      }
+
+      default:
+        OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_STATE);
+        ret = -1;
+        goto end;
+    }
+
+    if (hs->state != state) {
+      ssl_do_info_callback(ssl, SSL_CB_CONNECT_LOOP, 1);
+    }
+  }
+
+end:
+  ssl_do_info_callback(ssl, SSL_CB_CONNECT_EXIT, ret);
+  return ret;
+}
+
+uint16_t ssl_get_grease_value(const SSL *ssl, enum ssl_grease_index_t index) {
+  /* Use the client_random for entropy. This both avoids calling |RAND_bytes| on
+   * a single byte repeatedly and ensures the values are deterministic. This
+   * allows the same ClientHello be sent twice for a HelloRetryRequest or the
+   * same group be advertised in both supported_groups and key_shares. */
+  uint16_t ret = ssl->s3->client_random[index];
+  /* This generates a random value of the form 0xωaωa, for all 0 ≤ ω < 16. */
+  ret = (ret & 0xf0) | 0x0a;
+  ret |= ret << 8;
+  return ret;
+}
+
+/* ssl_get_client_disabled sets |*out_mask_a| and |*out_mask_k| to masks of
+ * disabled algorithms. */
+static void ssl_get_client_disabled(SSL *ssl, uint32_t *out_mask_a,
+                                    uint32_t *out_mask_k) {
+  int have_rsa = 0, have_ecdsa = 0;
+  *out_mask_a = 0;
+  *out_mask_k = 0;
+
+  /* Now go through all signature algorithms seeing if we support any for RSA or
+   * ECDSA. Do this for all versions not just TLS 1.2. */
+  const uint16_t *sigalgs;
+  size_t num_sigalgs = tls12_get_verify_sigalgs(ssl, &sigalgs);
+  for (size_t i = 0; i < num_sigalgs; i++) {
+    switch (sigalgs[i]) {
+      case SSL_SIGN_RSA_PSS_SHA512:
+      case SSL_SIGN_RSA_PSS_SHA384:
+      case SSL_SIGN_RSA_PSS_SHA256:
+      case SSL_SIGN_RSA_PKCS1_SHA512:
+      case SSL_SIGN_RSA_PKCS1_SHA384:
+      case SSL_SIGN_RSA_PKCS1_SHA256:
+      case SSL_SIGN_RSA_PKCS1_SHA1:
+        have_rsa = 1;
+        break;
+
+      case SSL_SIGN_ECDSA_SECP521R1_SHA512:
+      case SSL_SIGN_ECDSA_SECP384R1_SHA384:
+      case SSL_SIGN_ECDSA_SECP256R1_SHA256:
+      case SSL_SIGN_ECDSA_SHA1:
+        have_ecdsa = 1;
+        break;
+    }
+  }
+
+  /* Disable auth if we don't include any appropriate signature algorithms. */
+  if (!have_rsa) {
+    *out_mask_a |= SSL_aRSA;
+  }
+  if (!have_ecdsa) {
+    *out_mask_a |= SSL_aECDSA;
+  }
+
+  /* PSK requires a client callback. */
+  if (ssl->psk_client_callback == NULL) {
+    *out_mask_a |= SSL_aPSK;
+    *out_mask_k |= SSL_kPSK;
+  }
+}
+
+static int ssl_write_client_cipher_list(SSL *ssl, CBB *out,
+                                        uint16_t min_version,
+                                        uint16_t max_version) {
+  uint32_t mask_a, mask_k;
+  ssl_get_client_disabled(ssl, &mask_a, &mask_k);
+
+  CBB child;
+  if (!CBB_add_u16_length_prefixed(out, &child)) {
+    return 0;
+  }
+
+  /* Add a fake cipher suite. See draft-davidben-tls-grease-01. */
+  if (ssl->ctx->grease_enabled &&
+      !CBB_add_u16(&child, ssl_get_grease_value(ssl, ssl_grease_cipher))) {
+    return 0;
+  }
+
+  /* Add TLS 1.3 ciphers. Order ChaCha20-Poly1305 relative to AES-GCM based on
+   * hardware support. */
+  if (max_version >= TLS1_3_VERSION) {
+    if (!EVP_has_aes_hardware() &&
+        !CBB_add_u16(&child, TLS1_CK_CHACHA20_POLY1305_SHA256 & 0xffff)) {
+      return 0;
+    }
+    if (!CBB_add_u16(&child, TLS1_CK_AES_128_GCM_SHA256 & 0xffff) ||
+        !CBB_add_u16(&child, TLS1_CK_AES_256_GCM_SHA384 & 0xffff)) {
+      return 0;
+    }
+    if (EVP_has_aes_hardware() &&
+        !CBB_add_u16(&child, TLS1_CK_CHACHA20_POLY1305_SHA256 & 0xffff)) {
+      return 0;
+    }
+  }
+
+  if (min_version < TLS1_3_VERSION) {
+    STACK_OF(SSL_CIPHER) *ciphers = SSL_get_ciphers(ssl);
+    int any_enabled = 0;
+    for (size_t i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) {
+      const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(ciphers, i);
+      /* Skip disabled ciphers */
+      if ((cipher->algorithm_mkey & mask_k) ||
+          (cipher->algorithm_auth & mask_a)) {
+        continue;
+      }
+      if (SSL_CIPHER_get_min_version(cipher) > max_version ||
+          SSL_CIPHER_get_max_version(cipher) < min_version) {
+        continue;
+      }
+      any_enabled = 1;
+      if (!CBB_add_u16(&child, ssl_cipher_get_value(cipher))) {
+        return 0;
+      }
+    }
+
+    /* If all ciphers were disabled, return the error to the caller. */
+    if (!any_enabled && max_version < TLS1_3_VERSION) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CIPHERS_AVAILABLE);
+      return 0;
+    }
+  }
+
+  /* For SSLv3, the SCSV is added. Otherwise the renegotiation extension is
+   * added. */
+  if (max_version == SSL3_VERSION &&
+      !ssl->s3->initial_handshake_complete) {
+    if (!CBB_add_u16(&child, SSL3_CK_SCSV & 0xffff)) {
+      return 0;
+    }
+  }
+
+  if (ssl->mode & SSL_MODE_SEND_FALLBACK_SCSV) {
+    if (!CBB_add_u16(&child, SSL3_CK_FALLBACK_SCSV & 0xffff)) {
+      return 0;
+    }
+  }
+
+  return CBB_flush(out);
+}
+
+int ssl_write_client_hello(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  uint16_t min_version, max_version;
+  if (!ssl_get_version_range(ssl, &min_version, &max_version)) {
+    return 0;
+  }
+
+  CBB cbb, body;
+  if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_CLIENT_HELLO)) {
+    goto err;
+  }
+
+  /* Renegotiations do not participate in session resumption. */
+  int has_session = ssl->session != NULL &&
+                    !ssl->s3->initial_handshake_complete;
+
+  CBB child;
+  if (!CBB_add_u16(&body, hs->client_version) ||
+      !CBB_add_bytes(&body, ssl->s3->client_random, SSL3_RANDOM_SIZE) ||
+      !CBB_add_u8_length_prefixed(&body, &child) ||
+      (has_session &&
+       !CBB_add_bytes(&child, ssl->session->session_id,
+                      ssl->session->session_id_length))) {
+    goto err;
+  }
+
+  if (SSL_is_dtls(ssl)) {
+    if (!CBB_add_u8_length_prefixed(&body, &child) ||
+        !CBB_add_bytes(&child, ssl->d1->cookie, ssl->d1->cookie_len)) {
+      goto err;
+    }
+  }
+
+  size_t header_len =
+      SSL_is_dtls(ssl) ? DTLS1_HM_HEADER_LENGTH : SSL3_HM_HEADER_LENGTH;
+  if (!ssl_write_client_cipher_list(ssl, &body, min_version, max_version) ||
+      !CBB_add_u8(&body, 1 /* one compression method */) ||
+      !CBB_add_u8(&body, 0 /* null compression */) ||
+      !ssl_add_clienthello_tlsext(hs, &body, header_len + CBB_len(&body))) {
+    goto err;
+  }
+
+  uint8_t *msg = NULL;
+  size_t len;
+  if (!ssl->method->finish_message(ssl, &cbb, &msg, &len)) {
+    goto err;
+  }
+
+  /* Now that the length prefixes have been computed, fill in the placeholder
+   * PSK binder. */
+  if (hs->needs_psk_binder &&
+      !tls13_write_psk_binder(hs, msg, len)) {
+    OPENSSL_free(msg);
+    goto err;
+  }
+
+  return ssl->method->add_message(ssl, msg, len);
+
+ err:
+  CBB_cleanup(&cbb);
+  return 0;
+}
+
+static int ssl3_send_client_hello(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  /* The handshake buffer is reset on every ClientHello. Notably, in DTLS, we
+   * may send multiple ClientHellos if we receive HelloVerifyRequest. */
+  if (!SSL_TRANSCRIPT_init(&hs->transcript)) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    return -1;
+  }
+
+  uint16_t min_version, max_version;
+  if (!ssl_get_version_range(ssl, &min_version, &max_version)) {
+    return -1;
+  }
+
+  uint16_t max_wire_version = ssl->method->version_to_wire(max_version);
+  assert(hs->state == SSL3_ST_CW_CLNT_HELLO_A);
+  if (!ssl->s3->have_version) {
+    ssl->version = max_wire_version;
+  }
+
+  /* Always advertise the ClientHello version from the original maximum version,
+   * even on renegotiation. The static RSA key exchange uses this field, and
+   * some servers fail when it changes across handshakes. */
+  hs->client_version = max_wire_version;
+  if (max_version >= TLS1_3_VERSION) {
+    hs->client_version = ssl->method->version_to_wire(TLS1_2_VERSION);
+  }
+
+  /* If the configured session has expired or was created at a disabled
+   * version, drop it. */
+  if (ssl->session != NULL) {
+    uint16_t session_version;
+    if (ssl->session->is_server ||
+        !ssl->method->version_from_wire(&session_version,
+                                        ssl->session->ssl_version) ||
+        (session_version < TLS1_3_VERSION &&
+         ssl->session->session_id_length == 0) ||
+        ssl->session->not_resumable ||
+        !ssl_session_is_time_valid(ssl, ssl->session) ||
+        session_version < min_version || session_version > max_version) {
+      ssl_set_session(ssl, NULL);
+    }
+  }
+
+  /* If resending the ClientHello in DTLS after a HelloVerifyRequest, don't
+   * renegerate the client_random. The random must be reused. */
+  if ((!SSL_is_dtls(ssl) || !ssl->d1->send_cookie) &&
+      !RAND_bytes(ssl->s3->client_random, sizeof(ssl->s3->client_random))) {
+    return -1;
+  }
+
+  if (!ssl_write_client_hello(hs)) {
+    return -1;
+  }
+
+  return 1;
+}
+
+static int dtls1_get_hello_verify(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  int al;
+  CBS hello_verify_request, cookie;
+  uint16_t server_version;
+
+  int ret = ssl->method->ssl_get_message(ssl);
+  if (ret <= 0) {
+    return ret;
+  }
+
+  if (ssl->s3->tmp.message_type != DTLS1_MT_HELLO_VERIFY_REQUEST) {
+    ssl->d1->send_cookie = 0;
+    ssl->s3->tmp.reuse_message = 1;
+    return 1;
+  }
+
+  CBS_init(&hello_verify_request, ssl->init_msg, ssl->init_num);
+  if (!CBS_get_u16(&hello_verify_request, &server_version) ||
+      !CBS_get_u8_length_prefixed(&hello_verify_request, &cookie) ||
+      CBS_len(&hello_verify_request) != 0) {
+    al = SSL_AD_DECODE_ERROR;
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    goto f_err;
+  }
+
+  if (CBS_len(&cookie) > sizeof(ssl->d1->cookie)) {
+    al = SSL_AD_ILLEGAL_PARAMETER;
+    goto f_err;
+  }
+
+  OPENSSL_memcpy(ssl->d1->cookie, CBS_data(&cookie), CBS_len(&cookie));
+  ssl->d1->cookie_len = CBS_len(&cookie);
+
+  ssl->d1->send_cookie = 1;
+  return 1;
+
+f_err:
+  ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
+  return -1;
+}
+
+static int ssl3_get_server_hello(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  int al = SSL_AD_INTERNAL_ERROR;
+  CBS server_hello, server_random, session_id;
+  uint16_t server_wire_version, cipher_suite;
+  uint8_t compression_method;
+
+  int ret = ssl->method->ssl_get_message(ssl);
+  if (ret <= 0) {
+    uint32_t err = ERR_peek_error();
+    if (ERR_GET_LIB(err) == ERR_LIB_SSL &&
+        ERR_GET_REASON(err) == SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE) {
+      /* Add a dedicated error code to the queue for a handshake_failure alert
+       * in response to ClientHello. This matches NSS's client behavior and
+       * gives a better error on a (probable) failure to negotiate initial
+       * parameters. Note: this error code comes after the original one.
+       *
+       * See https://crbug.com/446505. */
+      OPENSSL_PUT_ERROR(SSL, SSL_R_HANDSHAKE_FAILURE_ON_CLIENT_HELLO);
+    }
+    return ret;
+  }
+
+  if (ssl->s3->tmp.message_type != SSL3_MT_SERVER_HELLO &&
+      ssl->s3->tmp.message_type != SSL3_MT_HELLO_RETRY_REQUEST) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+    OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
+    return -1;
+  }
+
+  CBS_init(&server_hello, ssl->init_msg, ssl->init_num);
+
+  if (!CBS_get_u16(&server_hello, &server_wire_version)) {
+    al = SSL_AD_DECODE_ERROR;
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    goto f_err;
+  }
+
+  uint16_t min_version, max_version, server_version;
+  if (!ssl_get_version_range(ssl, &min_version, &max_version) ||
+      !ssl->method->version_from_wire(&server_version, server_wire_version) ||
+      server_version < min_version || server_version > max_version) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL);
+    al = SSL_AD_PROTOCOL_VERSION;
+    goto f_err;
+  }
+
+  assert(ssl->s3->have_version == ssl->s3->initial_handshake_complete);
+  if (!ssl->s3->have_version) {
+    ssl->version = server_wire_version;
+    /* At this point, the connection's version is known and ssl->version is
+     * fixed. Begin enforcing the record-layer version. */
+    ssl->s3->have_version = 1;
+  } else if (server_wire_version != ssl->version) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SSL_VERSION);
+    al = SSL_AD_PROTOCOL_VERSION;
+    goto f_err;
+  }
+
+  if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
+    hs->state = SSL_ST_TLS13;
+    hs->do_tls13_handshake = tls13_client_handshake;
+    return 1;
+  }
+
+  if (hs->early_data_offered) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_VERSION_ON_EARLY_DATA);
+    al = SSL_AD_PROTOCOL_VERSION;
+    goto f_err;
+  }
+
+  ssl_clear_tls13_state(hs);
+
+  if (!ssl_check_message_type(ssl, SSL3_MT_SERVER_HELLO)) {
+    return -1;
+  }
+
+  if (!CBS_get_bytes(&server_hello, &server_random, SSL3_RANDOM_SIZE) ||
+      !CBS_get_u8_length_prefixed(&server_hello, &session_id) ||
+      CBS_len(&session_id) > SSL3_SESSION_ID_SIZE ||
+      !CBS_get_u16(&server_hello, &cipher_suite) ||
+      !CBS_get_u8(&server_hello, &compression_method)) {
+    al = SSL_AD_DECODE_ERROR;
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    goto f_err;
+  }
+
+  /* Copy over the server random. */
+  OPENSSL_memcpy(ssl->s3->server_random, CBS_data(&server_random), SSL3_RANDOM_SIZE);
+
+  /* TODO(davidben): Implement the TLS 1.1 and 1.2 downgrade sentinels once TLS
+   * 1.3 is finalized and we are not implementing a draft version. */
+
+  if (!ssl->s3->initial_handshake_complete && ssl->session != NULL &&
+      ssl->session->session_id_length != 0 &&
+      CBS_mem_equal(&session_id, ssl->session->session_id,
+                    ssl->session->session_id_length)) {
+    ssl->s3->session_reused = 1;
+  } else {
+    /* The session wasn't resumed. Create a fresh SSL_SESSION to
+     * fill out. */
+    ssl_set_session(ssl, NULL);
+    if (!ssl_get_new_session(hs, 0 /* client */)) {
+      goto f_err;
+    }
+    /* Note: session_id could be empty. */
+    hs->new_session->session_id_length = CBS_len(&session_id);
+    OPENSSL_memcpy(hs->new_session->session_id, CBS_data(&session_id),
+                   CBS_len(&session_id));
+  }
+
+  const SSL_CIPHER *c = SSL_get_cipher_by_value(cipher_suite);
+  if (c == NULL) {
+    /* unknown cipher */
+    al = SSL_AD_ILLEGAL_PARAMETER;
+    OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CIPHER_RETURNED);
+    goto f_err;
+  }
+
+  /* The cipher must be allowed in the selected version and enabled. */
+  uint32_t mask_a, mask_k;
+  ssl_get_client_disabled(ssl, &mask_a, &mask_k);
+  if ((c->algorithm_mkey & mask_k) || (c->algorithm_auth & mask_a) ||
+      SSL_CIPHER_get_min_version(c) > ssl3_protocol_version(ssl) ||
+      SSL_CIPHER_get_max_version(c) < ssl3_protocol_version(ssl) ||
+      !sk_SSL_CIPHER_find(SSL_get_ciphers(ssl), NULL, c)) {
+    al = SSL_AD_ILLEGAL_PARAMETER;
+    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED);
+    goto f_err;
+  }
+
+  if (ssl->session != NULL) {
+    if (ssl->session->ssl_version != ssl->version) {
+      al = SSL_AD_ILLEGAL_PARAMETER;
+      OPENSSL_PUT_ERROR(SSL, SSL_R_OLD_SESSION_VERSION_NOT_RETURNED);
+      goto f_err;
+    }
+    if (ssl->session->cipher != c) {
+      al = SSL_AD_ILLEGAL_PARAMETER;
+      OPENSSL_PUT_ERROR(SSL, SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED);
+      goto f_err;
+    }
+    if (!ssl_session_is_context_valid(ssl, ssl->session)) {
+      /* This is actually a client application bug. */
+      al = SSL_AD_ILLEGAL_PARAMETER;
+      OPENSSL_PUT_ERROR(SSL,
+                        SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
+      goto f_err;
+    }
+  } else {
+    hs->new_session->cipher = c;
+  }
+  hs->new_cipher = c;
+
+  /* Now that the cipher is known, initialize the handshake hash and hash the
+   * ServerHello. */
+  if (!SSL_TRANSCRIPT_init_hash(&hs->transcript, ssl3_protocol_version(ssl),
+                                c->algorithm_prf) ||
+      !ssl_hash_current_message(hs)) {
+    goto f_err;
+  }
+
+  /* If doing a full handshake, the server may request a client certificate
+   * which requires hashing the handshake transcript. Otherwise, the handshake
+   * buffer may be released. */
+  if (ssl->session != NULL ||
+      !ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
+    SSL_TRANSCRIPT_free_buffer(&hs->transcript);
+  }
+
+  /* Only the NULL compression algorithm is supported. */
+  if (compression_method != 0) {
+    al = SSL_AD_ILLEGAL_PARAMETER;
+    OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
+    goto f_err;
+  }
+
+  /* TLS extensions */
+  if (!ssl_parse_serverhello_tlsext(hs, &server_hello)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
+    goto err;
+  }
+
+  /* There should be nothing left over in the record. */
+  if (CBS_len(&server_hello) != 0) {
+    /* wrong packet length */
+    al = SSL_AD_DECODE_ERROR;
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    goto f_err;
+  }
+
+  if (ssl->session != NULL &&
+      hs->extended_master_secret != ssl->session->extended_master_secret) {
+    al = SSL_AD_HANDSHAKE_FAILURE;
+    if (ssl->session->extended_master_secret) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION);
+    } else {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION);
+    }
+    goto f_err;
+  }
+
+  return 1;
+
+f_err:
+  ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
+err:
+  return -1;
+}
+
+static int ssl3_get_server_certificate(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  int ret = ssl->method->ssl_get_message(ssl);
+  if (ret <= 0) {
+    return ret;
+  }
+
+  if (!ssl_check_message_type(ssl, SSL3_MT_CERTIFICATE) ||
+      !ssl_hash_current_message(hs)) {
+    return -1;
+  }
+
+  CBS cbs;
+  CBS_init(&cbs, ssl->init_msg, ssl->init_num);
+
+  uint8_t alert = SSL_AD_DECODE_ERROR;
+  sk_CRYPTO_BUFFER_pop_free(hs->new_session->certs, CRYPTO_BUFFER_free);
+  EVP_PKEY_free(hs->peer_pubkey);
+  hs->peer_pubkey = NULL;
+  hs->new_session->certs = ssl_parse_cert_chain(&alert, &hs->peer_pubkey, NULL,
+                                                &cbs, ssl->ctx->pool);
+  if (hs->new_session->certs == NULL) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
+    return -1;
+  }
+
+  if (sk_CRYPTO_BUFFER_num(hs->new_session->certs) == 0 ||
+      CBS_len(&cbs) != 0 ||
+      !ssl->ctx->x509_method->session_cache_objects(hs->new_session)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+    return -1;
+  }
+
+  if (!ssl_check_leaf_certificate(
+          hs, hs->peer_pubkey,
+          sk_CRYPTO_BUFFER_value(hs->new_session->certs, 0))) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+    return -1;
+  }
+
+  /* Disallow the server certificate from changing during a renegotiation. See
+   * https://mitls.org/pages/attacks/3SHAKE. We never resume on renegotiation,
+   * so this check is sufficient. */
+  if (ssl->s3->established_session != NULL) {
+    if (sk_CRYPTO_BUFFER_num(ssl->s3->established_session->certs) !=
+        sk_CRYPTO_BUFFER_num(hs->new_session->certs)) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_SERVER_CERT_CHANGED);
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+      return -1;
+    }
+
+    for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(hs->new_session->certs); i++) {
+      const CRYPTO_BUFFER *old_cert =
+          sk_CRYPTO_BUFFER_value(ssl->s3->established_session->certs, i);
+      const CRYPTO_BUFFER *new_cert =
+          sk_CRYPTO_BUFFER_value(hs->new_session->certs, i);
+      if (CRYPTO_BUFFER_len(old_cert) != CRYPTO_BUFFER_len(new_cert) ||
+          OPENSSL_memcmp(CRYPTO_BUFFER_data(old_cert),
+                         CRYPTO_BUFFER_data(new_cert),
+                         CRYPTO_BUFFER_len(old_cert)) != 0) {
+        OPENSSL_PUT_ERROR(SSL, SSL_R_SERVER_CERT_CHANGED);
+        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+        return -1;
+      }
+    }
+  }
+
+  return 1;
+}
+
+static int ssl3_get_cert_status(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  int al;
+  CBS certificate_status, ocsp_response;
+  uint8_t status_type;
+
+  int ret = ssl->method->ssl_get_message(ssl);
+  if (ret <= 0) {
+    return ret;
+  }
+
+  if (ssl->s3->tmp.message_type != SSL3_MT_CERTIFICATE_STATUS) {
+    /* A server may send status_request in ServerHello and then change
+     * its mind about sending CertificateStatus. */
+    ssl->s3->tmp.reuse_message = 1;
+    return 1;
+  }
+
+  if (!ssl_hash_current_message(hs)) {
+    return -1;
+  }
+
+  CBS_init(&certificate_status, ssl->init_msg, ssl->init_num);
+  if (!CBS_get_u8(&certificate_status, &status_type) ||
+      status_type != TLSEXT_STATUSTYPE_ocsp ||
+      !CBS_get_u24_length_prefixed(&certificate_status, &ocsp_response) ||
+      CBS_len(&ocsp_response) == 0 ||
+      CBS_len(&certificate_status) != 0) {
+    al = SSL_AD_DECODE_ERROR;
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    goto f_err;
+  }
+
+  if (!CBS_stow(&ocsp_response, &hs->new_session->ocsp_response,
+                &hs->new_session->ocsp_response_length)) {
+    al = SSL_AD_INTERNAL_ERROR;
+    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+    goto f_err;
+  }
+  return 1;
+
+f_err:
+  ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
+  return -1;
+}
+
+static int ssl3_verify_server_cert(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  if (!ssl->ctx->x509_method->session_verify_cert_chain(hs->new_session, ssl)) {
+    return -1;
+  }
+
+  return 1;
+}
+
+static int ssl3_get_server_key_exchange(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  int al;
+  DH *dh = NULL;
+  EC_KEY *ecdh = NULL;
+  EC_POINT *srvr_ecpoint = NULL;
+
+  int ret = ssl->method->ssl_get_message(ssl);
+  if (ret <= 0) {
+    return ret;
+  }
+
+  if (ssl->s3->tmp.message_type != SSL3_MT_SERVER_KEY_EXCHANGE) {
+    /* Some ciphers (pure PSK) have an optional ServerKeyExchange message. */
+    if (ssl_cipher_requires_server_key_exchange(hs->new_cipher)) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+      return -1;
+    }
+
+    ssl->s3->tmp.reuse_message = 1;
+    return 1;
+  }
+
+  if (!ssl_hash_current_message(hs)) {
+    return -1;
+  }
+
+  /* Retain a copy of the original CBS to compute the signature over. */
+  CBS server_key_exchange;
+  CBS_init(&server_key_exchange, ssl->init_msg, ssl->init_num);
+  CBS server_key_exchange_orig = server_key_exchange;
+
+  uint32_t alg_k = hs->new_cipher->algorithm_mkey;
+  uint32_t alg_a = hs->new_cipher->algorithm_auth;
+
+  if (alg_a & SSL_aPSK) {
+    CBS psk_identity_hint;
+
+    /* Each of the PSK key exchanges begins with a psk_identity_hint. */
+    if (!CBS_get_u16_length_prefixed(&server_key_exchange,
+                                     &psk_identity_hint)) {
+      al = SSL_AD_DECODE_ERROR;
+      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+      goto f_err;
+    }
+
+    /* Store PSK identity hint for later use, hint is used in
+     * ssl3_send_client_key_exchange.  Assume that the maximum length of a PSK
+     * identity hint can be as long as the maximum length of a PSK identity.
+     * Also do not allow NULL characters; identities are saved as C strings.
+     *
+     * TODO(davidben): Should invalid hints be ignored? It's a hint rather than
+     * a specific identity. */
+    if (CBS_len(&psk_identity_hint) > PSK_MAX_IDENTITY_LEN ||
+        CBS_contains_zero_byte(&psk_identity_hint)) {
+      al = SSL_AD_HANDSHAKE_FAILURE;
+      OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG);
+      goto f_err;
+    }
+
+    /* Save non-empty identity hints as a C string. Empty identity hints we
+     * treat as missing. Plain PSK makes it possible to send either no hint
+     * (omit ServerKeyExchange) or an empty hint, while ECDHE_PSK can only spell
+     * empty hint. Having different capabilities is odd, so we interpret empty
+     * and missing as identical. */
+    if (CBS_len(&psk_identity_hint) != 0 &&
+        !CBS_strdup(&psk_identity_hint, &hs->peer_psk_identity_hint)) {
+      al = SSL_AD_INTERNAL_ERROR;
+      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+      goto f_err;
+    }
+  }
+
+  if (alg_k & SSL_kDHE) {
+    CBS dh_p, dh_g, dh_Ys;
+    if (!CBS_get_u16_length_prefixed(&server_key_exchange, &dh_p) ||
+        CBS_len(&dh_p) == 0 ||
+        !CBS_get_u16_length_prefixed(&server_key_exchange, &dh_g) ||
+        CBS_len(&dh_g) == 0 ||
+        !CBS_get_u16_length_prefixed(&server_key_exchange, &dh_Ys) ||
+        CBS_len(&dh_Ys) == 0) {
+      al = SSL_AD_DECODE_ERROR;
+      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+      goto f_err;
+    }
+
+    dh = DH_new();
+    if (dh == NULL) {
+      goto err;
+    }
+
+    dh->p = BN_bin2bn(CBS_data(&dh_p), CBS_len(&dh_p), NULL);
+    dh->g = BN_bin2bn(CBS_data(&dh_g), CBS_len(&dh_g), NULL);
+    if (dh->p == NULL || dh->g == NULL) {
+      goto err;
+    }
+
+    unsigned bits = DH_num_bits(dh);
+    if (bits < 1024) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_DH_P_LENGTH);
+      goto err;
+    } else if (bits > 4096) {
+      /* Overly large DHE groups are prohibitively expensive, so enforce a limit
+       * to prevent a server from causing us to perform too expensive of a
+       * computation. */
+      OPENSSL_PUT_ERROR(SSL, SSL_R_DH_P_TOO_LONG);
+      goto err;
+    }
+
+    SSL_ECDH_CTX_init_for_dhe(&hs->ecdh_ctx, dh);
+    dh = NULL;
+
+    /* Save the peer public key for later. */
+    if (!CBS_stow(&dh_Ys, &hs->peer_key, &hs->peer_key_len)) {
+      goto err;
+    }
+  } else if (alg_k & SSL_kECDHE) {
+    /* Parse the server parameters. */
+    uint8_t group_type;
+    uint16_t group_id;
+    CBS point;
+    if (!CBS_get_u8(&server_key_exchange, &group_type) ||
+        group_type != NAMED_CURVE_TYPE ||
+        !CBS_get_u16(&server_key_exchange, &group_id) ||
+        !CBS_get_u8_length_prefixed(&server_key_exchange, &point)) {
+      al = SSL_AD_DECODE_ERROR;
+      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+      goto f_err;
+    }
+    hs->new_session->group_id = group_id;
+
+    /* Ensure the group is consistent with preferences. */
+    if (!tls1_check_group_id(ssl, group_id)) {
+      al = SSL_AD_ILLEGAL_PARAMETER;
+      OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
+      goto f_err;
+    }
+
+    /* Initialize ECDH and save the peer public key for later. */
+    if (!SSL_ECDH_CTX_init(&hs->ecdh_ctx, group_id) ||
+        !CBS_stow(&point, &hs->peer_key, &hs->peer_key_len)) {
+      goto err;
+    }
+  } else if (!(alg_k & SSL_kPSK)) {
+    al = SSL_AD_UNEXPECTED_MESSAGE;
+    OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
+    goto f_err;
+  }
+
+  /* At this point, |server_key_exchange| contains the signature, if any, while
+   * |server_key_exchange_orig| contains the entire message. From that, derive
+   * a CBS containing just the parameter. */
+  CBS parameter;
+  CBS_init(&parameter, CBS_data(&server_key_exchange_orig),
+           CBS_len(&server_key_exchange_orig) - CBS_len(&server_key_exchange));
+
+  /* ServerKeyExchange should be signed by the server's public key. */
+  if (ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
+    uint16_t signature_algorithm = 0;
+    if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
+      if (!CBS_get_u16(&server_key_exchange, &signature_algorithm)) {
+        al = SSL_AD_DECODE_ERROR;
+        OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+        goto f_err;
+      }
+      if (!tls12_check_peer_sigalg(ssl, &al, signature_algorithm)) {
+        goto f_err;
+      }
+      hs->new_session->peer_signature_algorithm = signature_algorithm;
+    } else if (hs->peer_pubkey->type == EVP_PKEY_RSA) {
+      signature_algorithm = SSL_SIGN_RSA_PKCS1_MD5_SHA1;
+    } else if (hs->peer_pubkey->type == EVP_PKEY_EC) {
+      signature_algorithm = SSL_SIGN_ECDSA_SHA1;
+    } else {
+      al = SSL_AD_UNSUPPORTED_CERTIFICATE;
+      OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE);
+      goto f_err;
+    }
+
+    /* The last field in |server_key_exchange| is the signature. */
+    CBS signature;
+    if (!CBS_get_u16_length_prefixed(&server_key_exchange, &signature) ||
+        CBS_len(&server_key_exchange) != 0) {
+      al = SSL_AD_DECODE_ERROR;
+      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+      goto f_err;
+    }
+
+    CBB transcript;
+    uint8_t *transcript_data;
+    size_t transcript_len;
+    if (!CBB_init(&transcript, 2*SSL3_RANDOM_SIZE + CBS_len(&parameter)) ||
+        !CBB_add_bytes(&transcript, ssl->s3->client_random, SSL3_RANDOM_SIZE) ||
+        !CBB_add_bytes(&transcript, ssl->s3->server_random, SSL3_RANDOM_SIZE) ||
+        !CBB_add_bytes(&transcript, CBS_data(&parameter), CBS_len(&parameter)) ||
+        !CBB_finish(&transcript, &transcript_data, &transcript_len)) {
+      CBB_cleanup(&transcript);
+      al = SSL_AD_INTERNAL_ERROR;
+      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+      goto f_err;
+    }
+
+    int sig_ok = ssl_public_key_verify(
+        ssl, CBS_data(&signature), CBS_len(&signature), signature_algorithm,
+        hs->peer_pubkey, transcript_data, transcript_len);
+    OPENSSL_free(transcript_data);
+
+#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
+    sig_ok = 1;
+    ERR_clear_error();
+#endif
+    if (!sig_ok) {
+      /* bad signature */
+      al = SSL_AD_DECRYPT_ERROR;
+      OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SIGNATURE);
+      goto f_err;
+    }
+  } else {
+    /* PSK ciphers are the only supported certificate-less ciphers. */
+    assert(alg_a == SSL_aPSK);
+
+    if (CBS_len(&server_key_exchange) > 0) {
+      al = SSL_AD_DECODE_ERROR;
+      OPENSSL_PUT_ERROR(SSL, SSL_R_EXTRA_DATA_IN_MESSAGE);
+      goto f_err;
+    }
+  }
+  return 1;
+
+f_err:
+  ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
+err:
+  DH_free(dh);
+  EC_POINT_free(srvr_ecpoint);
+  EC_KEY_free(ecdh);
+  return -1;
+}
+
+static int ssl3_get_certificate_request(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  int msg_ret = ssl->method->ssl_get_message(ssl);
+  if (msg_ret <= 0) {
+    return msg_ret;
+  }
+
+  if (ssl->s3->tmp.message_type == SSL3_MT_SERVER_HELLO_DONE) {
+    ssl->s3->tmp.reuse_message = 1;
+    /* If we get here we don't need the handshake buffer as we won't be doing
+     * client auth. */
+    SSL_TRANSCRIPT_free_buffer(&hs->transcript);
+    return 1;
+  }
+
+  if (!ssl_check_message_type(ssl, SSL3_MT_CERTIFICATE_REQUEST) ||
+      !ssl_hash_current_message(hs)) {
+    return -1;
+  }
+
+  CBS cbs;
+  CBS_init(&cbs, ssl->init_msg, ssl->init_num);
+
+  /* Get the certificate types. */
+  CBS certificate_types;
+  if (!CBS_get_u8_length_prefixed(&cbs, &certificate_types)) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    return -1;
+  }
+
+  if (!CBS_stow(&certificate_types, &hs->certificate_types,
+                &hs->num_certificate_types)) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+    return -1;
+  }
+
+  if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
+    CBS supported_signature_algorithms;
+    if (!CBS_get_u16_length_prefixed(&cbs, &supported_signature_algorithms) ||
+        !tls1_parse_peer_sigalgs(hs, &supported_signature_algorithms)) {
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+      return -1;
+    }
+  }
+
+  uint8_t alert = SSL_AD_DECODE_ERROR;
+  STACK_OF(CRYPTO_BUFFER) *ca_names =
+      ssl_parse_client_CA_list(ssl, &alert, &cbs);
+  if (ca_names == NULL) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
+    return -1;
+  }
+
+  if (CBS_len(&cbs) != 0) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+    sk_CRYPTO_BUFFER_pop_free(ca_names, CRYPTO_BUFFER_free);
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    return -1;
+  }
+
+  hs->cert_request = 1;
+  sk_CRYPTO_BUFFER_pop_free(hs->ca_names, CRYPTO_BUFFER_free);
+  hs->ca_names = ca_names;
+  ssl->ctx->x509_method->hs_flush_cached_ca_names(hs);
+  return 1;
+}
+
+static int ssl3_get_server_hello_done(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  int ret = ssl->method->ssl_get_message(ssl);
+  if (ret <= 0) {
+    return ret;
+  }
+
+  if (!ssl_check_message_type(ssl, SSL3_MT_SERVER_HELLO_DONE) ||
+      !ssl_hash_current_message(hs)) {
+    return -1;
+  }
+
+  /* ServerHelloDone is empty. */
+  if (ssl->init_num > 0) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    return -1;
+  }
+
+  return 1;
+}
+
+static int ssl3_send_client_certificate(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  /* Call cert_cb to update the certificate. */
+  if (ssl->cert->cert_cb) {
+    int ret = ssl->cert->cert_cb(ssl, ssl->cert->cert_cb_arg);
+    if (ret < 0) {
+      ssl->rwstate = SSL_X509_LOOKUP;
+      return -1;
+    }
+    if (ret == 0) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_CB_ERROR);
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+      return -1;
+    }
+  }
+
+  if (!ssl_has_certificate(ssl)) {
+    /* Without a client certificate, the handshake buffer may be released. */
+    SSL_TRANSCRIPT_free_buffer(&hs->transcript);
+
+    /* In SSL 3.0, the Certificate message is replaced with a warning alert. */
+    if (ssl->version == SSL3_VERSION) {
+      if (!ssl->method->add_alert(ssl, SSL3_AL_WARNING,
+                                  SSL_AD_NO_CERTIFICATE)) {
+        return -1;
+      }
+      return 1;
+    }
+  }
+
+  if (!ssl->ctx->x509_method->ssl_auto_chain_if_needed(ssl) ||
+      !ssl3_output_cert_chain(ssl)) {
+    return -1;
+  }
+  return 1;
+}
+
+OPENSSL_COMPILE_ASSERT(sizeof(size_t) >= sizeof(unsigned),
+                       SIZE_T_IS_SMALLER_THAN_UNSIGNED);
+
+static int ssl3_send_client_key_exchange(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  uint8_t *pms = NULL;
+  size_t pms_len = 0;
+  CBB cbb, body;
+  if (!ssl->method->init_message(ssl, &cbb, &body,
+                                 SSL3_MT_CLIENT_KEY_EXCHANGE)) {
+    goto err;
+  }
+
+  uint32_t alg_k = hs->new_cipher->algorithm_mkey;
+  uint32_t alg_a = hs->new_cipher->algorithm_auth;
+
+  /* If using a PSK key exchange, prepare the pre-shared key. */
+  unsigned psk_len = 0;
+  uint8_t psk[PSK_MAX_PSK_LEN];
+  if (alg_a & SSL_aPSK) {
+    if (ssl->psk_client_callback == NULL) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_NO_CLIENT_CB);
+      goto err;
+    }
+
+    char identity[PSK_MAX_IDENTITY_LEN + 1];
+    OPENSSL_memset(identity, 0, sizeof(identity));
+    psk_len =
+        ssl->psk_client_callback(ssl, hs->peer_psk_identity_hint, identity,
+                                 sizeof(identity), psk, sizeof(psk));
+    if (psk_len == 0) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_NOT_FOUND);
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+      goto err;
+    }
+    assert(psk_len <= PSK_MAX_PSK_LEN);
+
+    OPENSSL_free(hs->new_session->psk_identity);
+    hs->new_session->psk_identity = BUF_strdup(identity);
+    if (hs->new_session->psk_identity == NULL) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+      goto err;
+    }
+
+    /* Write out psk_identity. */
+    CBB child;
+    if (!CBB_add_u16_length_prefixed(&body, &child) ||
+        !CBB_add_bytes(&child, (const uint8_t *)identity,
+                       OPENSSL_strnlen(identity, sizeof(identity))) ||
+        !CBB_flush(&body)) {
+      goto err;
+    }
+  }
+
+  /* Depending on the key exchange method, compute |pms| and |pms_len|. */
+  if (alg_k & SSL_kRSA) {
+    pms_len = SSL_MAX_MASTER_KEY_LENGTH;
+    pms = OPENSSL_malloc(pms_len);
+    if (pms == NULL) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+      goto err;
+    }
+
+    RSA *rsa = EVP_PKEY_get0_RSA(hs->peer_pubkey);
+    if (rsa == NULL) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+      goto err;
+    }
+
+    pms[0] = hs->client_version >> 8;
+    pms[1] = hs->client_version & 0xff;
+    if (!RAND_bytes(&pms[2], SSL_MAX_MASTER_KEY_LENGTH - 2)) {
+      goto err;
+    }
+
+    CBB child, *enc_pms = &body;
+    size_t enc_pms_len;
+    /* In TLS, there is a length prefix. */
+    if (ssl->version > SSL3_VERSION) {
+      if (!CBB_add_u16_length_prefixed(&body, &child)) {
+        goto err;
+      }
+      enc_pms = &child;
+    }
+
+    uint8_t *ptr;
+    if (!CBB_reserve(enc_pms, &ptr, RSA_size(rsa)) ||
+        !RSA_encrypt(rsa, &enc_pms_len, ptr, RSA_size(rsa), pms, pms_len,
+                     RSA_PKCS1_PADDING) ||
+        !CBB_did_write(enc_pms, enc_pms_len) ||
+        !CBB_flush(&body)) {
+      goto err;
+    }
+  } else if (alg_k & (SSL_kECDHE|SSL_kDHE)) {
+    /* Generate a keypair and serialize the public half. */
+    CBB child;
+    if (!SSL_ECDH_CTX_add_key(&hs->ecdh_ctx, &body, &child)) {
+      goto err;
+    }
+
+    /* Compute the premaster. */
+    uint8_t alert = SSL_AD_DECODE_ERROR;
+    if (!SSL_ECDH_CTX_accept(&hs->ecdh_ctx, &child, &pms, &pms_len, &alert,
+                             hs->peer_key, hs->peer_key_len)) {
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
+      goto err;
+    }
+    if (!CBB_flush(&body)) {
+      goto err;
+    }
+
+    /* The key exchange state may now be discarded. */
+    SSL_ECDH_CTX_cleanup(&hs->ecdh_ctx);
+    OPENSSL_free(hs->peer_key);
+    hs->peer_key = NULL;
+    hs->peer_key_len = 0;
+  } else if (alg_k & SSL_kPSK) {
+    /* For plain PSK, other_secret is a block of 0s with the same length as
+     * the pre-shared key. */
+    pms_len = psk_len;
+    pms = OPENSSL_malloc(pms_len);
+    if (pms == NULL) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+      goto err;
+    }
+    OPENSSL_memset(pms, 0, pms_len);
+  } else {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    goto err;
+  }
+
+  /* For a PSK cipher suite, other_secret is combined with the pre-shared
+   * key. */
+  if (alg_a & SSL_aPSK) {
+    CBB pms_cbb, child;
+    uint8_t *new_pms;
+    size_t new_pms_len;
+
+    CBB_zero(&pms_cbb);
+    if (!CBB_init(&pms_cbb, 2 + psk_len + 2 + pms_len) ||
+        !CBB_add_u16_length_prefixed(&pms_cbb, &child) ||
+        !CBB_add_bytes(&child, pms, pms_len) ||
+        !CBB_add_u16_length_prefixed(&pms_cbb, &child) ||
+        !CBB_add_bytes(&child, psk, psk_len) ||
+        !CBB_finish(&pms_cbb, &new_pms, &new_pms_len)) {
+      CBB_cleanup(&pms_cbb);
+      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+      goto err;
+    }
+    OPENSSL_cleanse(pms, pms_len);
+    OPENSSL_free(pms);
+    pms = new_pms;
+    pms_len = new_pms_len;
+  }
+
+  /* The message must be added to the finished hash before calculating the
+   * master secret. */
+  if (!ssl_add_message_cbb(ssl, &cbb)) {
+    goto err;
+  }
+
+  hs->new_session->master_key_length = tls1_generate_master_secret(
+      hs, hs->new_session->master_key, pms, pms_len);
+  if (hs->new_session->master_key_length == 0) {
+    goto err;
+  }
+  hs->new_session->extended_master_secret = hs->extended_master_secret;
+  OPENSSL_cleanse(pms, pms_len);
+  OPENSSL_free(pms);
+
+  return 1;
+
+err:
+  CBB_cleanup(&cbb);
+  if (pms != NULL) {
+    OPENSSL_cleanse(pms, pms_len);
+    OPENSSL_free(pms);
+  }
+  return -1;
+}
+
+static int ssl3_send_cert_verify(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  assert(ssl_has_private_key(ssl));
+
+  CBB cbb, body, child;
+  if (!ssl->method->init_message(ssl, &cbb, &body,
+                                 SSL3_MT_CERTIFICATE_VERIFY)) {
+    goto err;
+  }
+
+  uint16_t signature_algorithm;
+  if (!tls1_choose_signature_algorithm(hs, &signature_algorithm)) {
+    goto err;
+  }
+  if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
+    /* Write out the digest type in TLS 1.2. */
+    if (!CBB_add_u16(&body, signature_algorithm)) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+      goto err;
+    }
+  }
+
+  /* Set aside space for the signature. */
+  const size_t max_sig_len = ssl_private_key_max_signature_len(ssl);
+  uint8_t *ptr;
+  if (!CBB_add_u16_length_prefixed(&body, &child) ||
+      !CBB_reserve(&child, &ptr, max_sig_len)) {
+    goto err;
+  }
+
+  size_t sig_len = max_sig_len;
+  enum ssl_private_key_result_t sign_result;
+  if (hs->state == SSL3_ST_CW_CERT_VRFY_A) {
+    /* The SSL3 construction for CertificateVerify does not decompose into a
+     * single final digest and signature, and must be special-cased. */
+    if (ssl3_protocol_version(ssl) == SSL3_VERSION) {
+      if (ssl->cert->key_method != NULL) {
+        OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY);
+        goto err;
+      }
+
+      uint8_t digest[EVP_MAX_MD_SIZE];
+      size_t digest_len;
+      if (!SSL_TRANSCRIPT_ssl3_cert_verify_hash(&hs->transcript, digest,
+                                                &digest_len, hs->new_session,
+                                                signature_algorithm)) {
+        goto err;
+      }
+
+      sign_result = ssl_private_key_success;
+
+      EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(ssl->cert->privatekey, NULL);
+      if (pctx == NULL ||
+          !EVP_PKEY_sign_init(pctx) ||
+          !EVP_PKEY_sign(pctx, ptr, &sig_len, digest, digest_len)) {
+        EVP_PKEY_CTX_free(pctx);
+        sign_result = ssl_private_key_failure;
+        goto err;
+      }
+      EVP_PKEY_CTX_free(pctx);
+    } else {
+      sign_result = ssl_private_key_sign(
+          ssl, ptr, &sig_len, max_sig_len, signature_algorithm,
+          (const uint8_t *)hs->transcript.buffer->data,
+          hs->transcript.buffer->length);
+    }
+
+    /* The handshake buffer is no longer necessary. */
+    SSL_TRANSCRIPT_free_buffer(&hs->transcript);
+  } else {
+    assert(hs->state == SSL3_ST_CW_CERT_VRFY_B);
+    sign_result = ssl_private_key_complete(ssl, ptr, &sig_len, max_sig_len);
+  }
+
+  switch (sign_result) {
+    case ssl_private_key_success:
+      break;
+    case ssl_private_key_failure:
+      goto err;
+    case ssl_private_key_retry:
+      ssl->rwstate = SSL_PRIVATE_KEY_OPERATION;
+      hs->state = SSL3_ST_CW_CERT_VRFY_B;
+      goto err;
+  }
+
+  if (!CBB_did_write(&child, sig_len) ||
+      !ssl_add_message_cbb(ssl, &cbb)) {
+    goto err;
+  }
+
+  return 1;
+
+err:
+  CBB_cleanup(&cbb);
+  return -1;
+}
+
+static int ssl3_send_next_proto(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  static const uint8_t kZero[32] = {0};
+  size_t padding_len = 32 - ((ssl->s3->next_proto_negotiated_len + 2) % 32);
+
+  CBB cbb, body, child;
+  if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_NEXT_PROTO) ||
+      !CBB_add_u8_length_prefixed(&body, &child) ||
+      !CBB_add_bytes(&child, ssl->s3->next_proto_negotiated,
+                     ssl->s3->next_proto_negotiated_len) ||
+      !CBB_add_u8_length_prefixed(&body, &child) ||
+      !CBB_add_bytes(&child, kZero, padding_len) ||
+      !ssl_add_message_cbb(ssl, &cbb)) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    CBB_cleanup(&cbb);
+    return -1;
+  }
+
+  return 1;
+}
+
+static int ssl3_send_channel_id(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  if (!ssl_do_channel_id_callback(ssl)) {
+    return -1;
+  }
+
+  if (ssl->tlsext_channel_id_private == NULL) {
+    ssl->rwstate = SSL_CHANNEL_ID_LOOKUP;
+    return -1;
+  }
+
+  CBB cbb, body;
+  if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_CHANNEL_ID) ||
+      !tls1_write_channel_id(hs, &body) ||
+      !ssl_add_message_cbb(ssl, &cbb)) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    CBB_cleanup(&cbb);
+    return -1;
+  }
+
+  return 1;
+}
+
+static int ssl3_get_new_session_ticket(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  int ret = ssl->method->ssl_get_message(ssl);
+  if (ret <= 0) {
+    return ret;
+  }
+
+  if (!ssl_check_message_type(ssl, SSL3_MT_NEW_SESSION_TICKET) ||
+      !ssl_hash_current_message(hs)) {
+    return -1;
+  }
+
+  CBS new_session_ticket, ticket;
+  uint32_t tlsext_tick_lifetime_hint;
+  CBS_init(&new_session_ticket, ssl->init_msg, ssl->init_num);
+  if (!CBS_get_u32(&new_session_ticket, &tlsext_tick_lifetime_hint) ||
+      !CBS_get_u16_length_prefixed(&new_session_ticket, &ticket) ||
+      CBS_len(&new_session_ticket) != 0) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    return -1;
+  }
+
+  if (CBS_len(&ticket) == 0) {
+    /* RFC 5077 allows a server to change its mind and send no ticket after
+     * negotiating the extension. The value of |ticket_expected| is checked in
+     * |ssl_update_cache| so is cleared here to avoid an unnecessary update. */
+    hs->ticket_expected = 0;
+    return 1;
+  }
+
+  int session_renewed = ssl->session != NULL;
+  SSL_SESSION *session = hs->new_session;
+  if (session_renewed) {
+    /* The server is sending a new ticket for an existing session. Sessions are
+     * immutable once established, so duplicate all but the ticket of the
+     * existing session. */
+    session = SSL_SESSION_dup(ssl->session, SSL_SESSION_INCLUDE_NONAUTH);
+    if (session == NULL) {
+      /* This should never happen. */
+      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+      goto err;
+    }
+  }
+
+  /* |tlsext_tick_lifetime_hint| is measured from when the ticket was issued. */
+  ssl_session_rebase_time(ssl, session);
+
+  if (!CBS_stow(&ticket, &session->tlsext_tick, &session->tlsext_ticklen)) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+    goto err;
+  }
+  session->tlsext_tick_lifetime_hint = tlsext_tick_lifetime_hint;
+
+  /* Generate a session ID for this session based on the session ticket. We use
+   * the session ID mechanism for detecting ticket resumption. This also fits in
+   * with assumptions elsewhere in OpenSSL.*/
+  if (!EVP_Digest(CBS_data(&ticket), CBS_len(&ticket),
+                  session->session_id, &session->session_id_length,
+                  EVP_sha256(), NULL)) {
+    goto err;
+  }
+
+  if (session_renewed) {
+    session->not_resumable = 0;
+    SSL_SESSION_free(ssl->session);
+    ssl->session = session;
+  }
+
+  return 1;
+
+err:
+  if (session_renewed) {
+    SSL_SESSION_free(session);
+  }
+  return -1;
+}
diff --git a/src/ssl/handshake_server.c b/src/ssl/handshake_server.c
new file mode 100644
index 0000000..a1341d6
--- /dev/null
+++ b/src/ssl/handshake_server.c
@@ -0,0 +1,1961 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ * 
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ * 
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from 
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ * 
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * 
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ *
+ * Portions of the attached software ("Contribution") are developed by 
+ * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
+ *
+ * The Contribution is licensed pursuant to the OpenSSL open source
+ * license provided above.
+ *
+ * ECC cipher suite support in OpenSSL originally written by
+ * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
+ *
+ */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE. */
+
+#include <openssl/ssl.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/bn.h>
+#include <openssl/buf.h>
+#include <openssl/bytestring.h>
+#include <openssl/cipher.h>
+#include <openssl/dh.h>
+#include <openssl/ec.h>
+#include <openssl/ecdsa.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/hmac.h>
+#include <openssl/md5.h>
+#include <openssl/mem.h>
+#include <openssl/nid.h>
+#include <openssl/rand.h>
+#include <openssl/x509.h>
+
+#include "internal.h"
+#include "../crypto/internal.h"
+
+
+static int ssl3_process_client_hello(SSL_HANDSHAKE *hs);
+static int ssl3_select_certificate(SSL_HANDSHAKE *hs);
+static int ssl3_select_parameters(SSL_HANDSHAKE *hs);
+static int ssl3_send_server_hello(SSL_HANDSHAKE *hs);
+static int ssl3_send_server_certificate(SSL_HANDSHAKE *hs);
+static int ssl3_send_certificate_status(SSL_HANDSHAKE *hs);
+static int ssl3_send_server_key_exchange(SSL_HANDSHAKE *hs);
+static int ssl3_send_certificate_request(SSL_HANDSHAKE *hs);
+static int ssl3_send_server_hello_done(SSL_HANDSHAKE *hs);
+static int ssl3_get_client_certificate(SSL_HANDSHAKE *hs);
+static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs);
+static int ssl3_get_cert_verify(SSL_HANDSHAKE *hs);
+static int ssl3_get_next_proto(SSL_HANDSHAKE *hs);
+static int ssl3_get_channel_id(SSL_HANDSHAKE *hs);
+static int ssl3_send_new_session_ticket(SSL_HANDSHAKE *hs);
+
+static struct CRYPTO_STATIC_MUTEX g_v2clienthello_lock =
+    CRYPTO_STATIC_MUTEX_INIT;
+static uint64_t g_v2clienthello_count = 0;
+
+uint64_t SSL_get_v2clienthello_count(void) {
+  CRYPTO_STATIC_MUTEX_lock_read(&g_v2clienthello_lock);
+  uint64_t ret = g_v2clienthello_count;
+  CRYPTO_STATIC_MUTEX_unlock_read(&g_v2clienthello_lock);
+  return ret;
+}
+
+int ssl3_accept(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  uint32_t alg_a;
+  int ret = -1;
+
+  assert(ssl->handshake_func == ssl3_accept);
+  assert(ssl->server);
+
+  for (;;) {
+    int state = hs->state;
+
+    switch (hs->state) {
+      case SSL_ST_INIT:
+        ssl_do_info_callback(ssl, SSL_CB_HANDSHAKE_START, 1);
+        hs->state = SSL3_ST_SR_CLNT_HELLO_A;
+        break;
+
+      case SSL3_ST_SR_CLNT_HELLO_A:
+        ret = ssl->method->ssl_get_message(ssl);
+        if (ret <= 0) {
+          goto end;
+        }
+        hs->state = SSL3_ST_SR_CLNT_HELLO_B;
+        break;
+
+      case SSL3_ST_SR_CLNT_HELLO_B:
+        ret = ssl3_process_client_hello(hs);
+        if (ret <= 0) {
+          goto end;
+        }
+        hs->state = SSL3_ST_SR_CLNT_HELLO_C;
+        break;
+
+      case SSL3_ST_SR_CLNT_HELLO_C:
+        ret = ssl3_select_certificate(hs);
+        if (ret <= 0) {
+          goto end;
+        }
+        if (hs->state != SSL_ST_TLS13) {
+          hs->state = SSL3_ST_SR_CLNT_HELLO_D;
+        }
+        break;
+
+      case SSL3_ST_SR_CLNT_HELLO_D:
+        ret = ssl3_select_parameters(hs);
+        if (ret <= 0) {
+          goto end;
+        }
+        ssl->method->received_flight(ssl);
+        hs->state = SSL3_ST_SW_SRVR_HELLO_A;
+        break;
+
+      case SSL3_ST_SW_SRVR_HELLO_A:
+        ret = ssl3_send_server_hello(hs);
+        if (ret <= 0) {
+          goto end;
+        }
+        if (ssl->session != NULL) {
+          hs->state = SSL3_ST_SW_SESSION_TICKET_A;
+        } else {
+          hs->state = SSL3_ST_SW_CERT_A;
+        }
+        break;
+
+      case SSL3_ST_SW_CERT_A:
+        if (ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
+          ret = ssl3_send_server_certificate(hs);
+          if (ret <= 0) {
+            goto end;
+          }
+        }
+        hs->state = SSL3_ST_SW_CERT_STATUS_A;
+        break;
+
+      case SSL3_ST_SW_CERT_STATUS_A:
+        if (hs->certificate_status_expected) {
+          ret = ssl3_send_certificate_status(hs);
+          if (ret <= 0) {
+            goto end;
+          }
+        }
+        hs->state = SSL3_ST_SW_KEY_EXCH_A;
+        break;
+
+      case SSL3_ST_SW_KEY_EXCH_A:
+      case SSL3_ST_SW_KEY_EXCH_B:
+        alg_a = hs->new_cipher->algorithm_auth;
+
+        /* PSK ciphers send ServerKeyExchange if there is an identity hint. */
+        if (ssl_cipher_requires_server_key_exchange(hs->new_cipher) ||
+            ((alg_a & SSL_aPSK) && ssl->psk_identity_hint)) {
+          ret = ssl3_send_server_key_exchange(hs);
+          if (ret <= 0) {
+            goto end;
+          }
+        }
+
+        hs->state = SSL3_ST_SW_CERT_REQ_A;
+        break;
+
+      case SSL3_ST_SW_CERT_REQ_A:
+        if (hs->cert_request) {
+          ret = ssl3_send_certificate_request(hs);
+          if (ret <= 0) {
+            goto end;
+          }
+        }
+        hs->state = SSL3_ST_SW_SRVR_DONE_A;
+        break;
+
+      case SSL3_ST_SW_SRVR_DONE_A:
+        ret = ssl3_send_server_hello_done(hs);
+        if (ret <= 0) {
+          goto end;
+        }
+        hs->next_state = SSL3_ST_SR_CERT_A;
+        hs->state = SSL3_ST_SW_FLUSH;
+        break;
+
+      case SSL3_ST_SR_CERT_A:
+        if (hs->cert_request) {
+          ret = ssl3_get_client_certificate(hs);
+          if (ret <= 0) {
+            goto end;
+          }
+        }
+        hs->state = SSL3_ST_SR_KEY_EXCH_A;
+        break;
+
+      case SSL3_ST_SR_KEY_EXCH_A:
+      case SSL3_ST_SR_KEY_EXCH_B:
+        ret = ssl3_get_client_key_exchange(hs);
+        if (ret <= 0) {
+          goto end;
+        }
+        hs->state = SSL3_ST_SR_CERT_VRFY_A;
+        break;
+
+      case SSL3_ST_SR_CERT_VRFY_A:
+        ret = ssl3_get_cert_verify(hs);
+        if (ret <= 0) {
+          goto end;
+        }
+
+        hs->state = SSL3_ST_SR_CHANGE;
+        break;
+
+      case SSL3_ST_SR_CHANGE:
+        ret = ssl->method->read_change_cipher_spec(ssl);
+        if (ret <= 0) {
+          goto end;
+        }
+
+        if (!tls1_change_cipher_state(hs, SSL3_CHANGE_CIPHER_SERVER_READ)) {
+          ret = -1;
+          goto end;
+        }
+
+        hs->state = SSL3_ST_SR_NEXT_PROTO_A;
+        break;
+
+      case SSL3_ST_SR_NEXT_PROTO_A:
+        if (hs->next_proto_neg_seen) {
+          ret = ssl3_get_next_proto(hs);
+          if (ret <= 0) {
+            goto end;
+          }
+        }
+        hs->state = SSL3_ST_SR_CHANNEL_ID_A;
+        break;
+
+      case SSL3_ST_SR_CHANNEL_ID_A:
+        if (ssl->s3->tlsext_channel_id_valid) {
+          ret = ssl3_get_channel_id(hs);
+          if (ret <= 0) {
+            goto end;
+          }
+        }
+        hs->state = SSL3_ST_SR_FINISHED_A;
+        break;
+
+      case SSL3_ST_SR_FINISHED_A:
+        ret = ssl3_get_finished(hs);
+        if (ret <= 0) {
+          goto end;
+        }
+
+        ssl->method->received_flight(ssl);
+        if (ssl->session != NULL) {
+          hs->state = SSL_ST_OK;
+        } else {
+          hs->state = SSL3_ST_SW_SESSION_TICKET_A;
+        }
+
+        /* If this is a full handshake with ChannelID then record the handshake
+         * hashes in |hs->new_session| in case we need them to verify a
+         * ChannelID signature on a resumption of this session in the future. */
+        if (ssl->session == NULL && ssl->s3->tlsext_channel_id_valid) {
+          ret = tls1_record_handshake_hashes_for_channel_id(hs);
+          if (ret <= 0) {
+            goto end;
+          }
+        }
+        break;
+
+      case SSL3_ST_SW_SESSION_TICKET_A:
+        if (hs->ticket_expected) {
+          ret = ssl3_send_new_session_ticket(hs);
+          if (ret <= 0) {
+            goto end;
+          }
+        }
+        hs->state = SSL3_ST_SW_CHANGE;
+        break;
+
+      case SSL3_ST_SW_CHANGE:
+        if (!ssl->method->add_change_cipher_spec(ssl) ||
+            !tls1_change_cipher_state(hs, SSL3_CHANGE_CIPHER_SERVER_WRITE)) {
+          ret = -1;
+          goto end;
+        }
+
+        hs->state = SSL3_ST_SW_FINISHED_A;
+        break;
+
+      case SSL3_ST_SW_FINISHED_A:
+        ret = ssl3_send_finished(hs);
+        if (ret <= 0) {
+          goto end;
+        }
+        hs->state = SSL3_ST_SW_FLUSH;
+        if (ssl->session != NULL) {
+          hs->next_state = SSL3_ST_SR_CHANGE;
+        } else {
+          hs->next_state = SSL_ST_OK;
+        }
+        break;
+
+      case SSL3_ST_SW_FLUSH:
+        ret = ssl->method->flush_flight(ssl);
+        if (ret <= 0) {
+          goto end;
+        }
+
+        hs->state = hs->next_state;
+        if (hs->state != SSL_ST_OK) {
+          ssl->method->expect_flight(ssl);
+        }
+        break;
+
+      case SSL_ST_TLS13: {
+        int early_return = 0;
+        ret = tls13_handshake(hs, &early_return);
+        if (ret <= 0) {
+          goto end;
+        }
+
+        if (early_return) {
+          ret = 1;
+          goto end;
+        }
+
+        hs->state = SSL_ST_OK;
+        break;
+      }
+
+      case SSL_ST_OK:
+        ssl->method->release_current_message(ssl, 1 /* free_buffer */);
+
+        /* If we aren't retaining peer certificates then we can discard it
+         * now. */
+        if (hs->new_session != NULL &&
+            ssl->retain_only_sha256_of_client_certs) {
+          sk_CRYPTO_BUFFER_pop_free(hs->new_session->certs, CRYPTO_BUFFER_free);
+          hs->new_session->certs = NULL;
+          ssl->ctx->x509_method->session_clear(hs->new_session);
+        }
+
+        SSL_SESSION_free(ssl->s3->established_session);
+        if (ssl->session != NULL) {
+          SSL_SESSION_up_ref(ssl->session);
+          ssl->s3->established_session = ssl->session;
+        } else {
+          ssl->s3->established_session = hs->new_session;
+          ssl->s3->established_session->not_resumable = 0;
+          hs->new_session = NULL;
+        }
+
+        if (hs->v2_clienthello) {
+          CRYPTO_STATIC_MUTEX_lock_write(&g_v2clienthello_lock);
+          g_v2clienthello_count++;
+          CRYPTO_STATIC_MUTEX_unlock_write(&g_v2clienthello_lock);
+        }
+
+        ssl->s3->initial_handshake_complete = 1;
+        ssl_update_cache(hs, SSL_SESS_CACHE_SERVER);
+
+        ssl_do_info_callback(ssl, SSL_CB_HANDSHAKE_DONE, 1);
+        ret = 1;
+        goto end;
+
+      default:
+        OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_STATE);
+        ret = -1;
+        goto end;
+    }
+
+    if (hs->state != state) {
+      ssl_do_info_callback(ssl, SSL_CB_ACCEPT_LOOP, 1);
+    }
+  }
+
+end:
+  ssl_do_info_callback(ssl, SSL_CB_ACCEPT_EXIT, ret);
+  return ret;
+}
+
+int ssl_client_cipher_list_contains_cipher(const SSL_CLIENT_HELLO *client_hello,
+                                           uint16_t id) {
+  CBS cipher_suites;
+  CBS_init(&cipher_suites, client_hello->cipher_suites,
+           client_hello->cipher_suites_len);
+
+  while (CBS_len(&cipher_suites) > 0) {
+    uint16_t got_id;
+    if (!CBS_get_u16(&cipher_suites, &got_id)) {
+      return 0;
+    }
+
+    if (got_id == id) {
+      return 1;
+    }
+  }
+
+  return 0;
+}
+
+static int negotiate_version(SSL_HANDSHAKE *hs, uint8_t *out_alert,
+                             const SSL_CLIENT_HELLO *client_hello) {
+  SSL *const ssl = hs->ssl;
+  assert(!ssl->s3->have_version);
+  uint16_t min_version, max_version;
+  if (!ssl_get_version_range(ssl, &min_version, &max_version)) {
+    *out_alert = SSL_AD_PROTOCOL_VERSION;
+    return 0;
+  }
+
+  uint16_t version = 0;
+  /* Check supported_versions extension if it is present. */
+  CBS supported_versions;
+  if (ssl_client_hello_get_extension(client_hello, &supported_versions,
+                                     TLSEXT_TYPE_supported_versions)) {
+    CBS versions;
+    if (!CBS_get_u8_length_prefixed(&supported_versions, &versions) ||
+        CBS_len(&supported_versions) != 0 ||
+        CBS_len(&versions) == 0) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+      *out_alert = SSL_AD_DECODE_ERROR;
+      return 0;
+    }
+
+    /* Choose the newest commonly-supported version advertised by the client.
+     * The client orders the versions according to its preferences, but we're
+     * not required to honor the client's preferences. */
+    int found_version = 0;
+    while (CBS_len(&versions) != 0) {
+      uint16_t ext_version;
+      if (!CBS_get_u16(&versions, &ext_version)) {
+        OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+        *out_alert = SSL_AD_DECODE_ERROR;
+        return 0;
+      }
+      if (!ssl->method->version_from_wire(&ext_version, ext_version)) {
+        continue;
+      }
+      if (min_version <= ext_version &&
+          ext_version <= max_version &&
+          (!found_version || version < ext_version)) {
+        version = ext_version;
+        found_version = 1;
+      }
+    }
+
+    if (!found_version) {
+      goto unsupported_protocol;
+    }
+  } else {
+    /* Process ClientHello.version instead. Note that versions beyond (D)TLS 1.2
+     * do not use this mechanism. */
+    if (SSL_is_dtls(ssl)) {
+      if (client_hello->version <= DTLS1_2_VERSION) {
+        version = TLS1_2_VERSION;
+      } else if (client_hello->version <= DTLS1_VERSION) {
+        version = TLS1_1_VERSION;
+      } else {
+        goto unsupported_protocol;
+      }
+    } else {
+      if (client_hello->version >= TLS1_2_VERSION) {
+        version = TLS1_2_VERSION;
+      } else if (client_hello->version >= TLS1_1_VERSION) {
+        version = TLS1_1_VERSION;
+      } else if (client_hello->version >= TLS1_VERSION) {
+        version = TLS1_VERSION;
+      } else if (client_hello->version >= SSL3_VERSION) {
+        version = SSL3_VERSION;
+      } else {
+        goto unsupported_protocol;
+      }
+    }
+
+    /* Apply our minimum and maximum version. */
+    if (version > max_version) {
+      version = max_version;
+    }
+
+    if (version < min_version) {
+      goto unsupported_protocol;
+    }
+  }
+
+  /* Handle FALLBACK_SCSV. */
+  if (ssl_client_cipher_list_contains_cipher(client_hello,
+                                             SSL3_CK_FALLBACK_SCSV & 0xffff) &&
+      version < max_version) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_INAPPROPRIATE_FALLBACK);
+    *out_alert = SSL3_AD_INAPPROPRIATE_FALLBACK;
+    return 0;
+  }
+
+  hs->client_version = client_hello->version;
+  ssl->version = ssl->method->version_to_wire(version);
+
+  /* At this point, the connection's version is known and |ssl->version| is
+   * fixed. Begin enforcing the record-layer version. */
+  ssl->s3->have_version = 1;
+
+  return 1;
+
+unsupported_protocol:
+  OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL);
+  *out_alert = SSL_AD_PROTOCOL_VERSION;
+  return 0;
+}
+
+static STACK_OF(SSL_CIPHER) *
+    ssl_parse_client_cipher_list(const SSL_CLIENT_HELLO *client_hello) {
+  CBS cipher_suites;
+  CBS_init(&cipher_suites, client_hello->cipher_suites,
+           client_hello->cipher_suites_len);
+
+  STACK_OF(SSL_CIPHER) *sk = sk_SSL_CIPHER_new_null();
+  if (sk == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+    goto err;
+  }
+
+  while (CBS_len(&cipher_suites) > 0) {
+    uint16_t cipher_suite;
+
+    if (!CBS_get_u16(&cipher_suites, &cipher_suite)) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST);
+      goto err;
+    }
+
+    const SSL_CIPHER *c = SSL_get_cipher_by_value(cipher_suite);
+    if (c != NULL && !sk_SSL_CIPHER_push(sk, c)) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+      goto err;
+    }
+  }
+
+  return sk;
+
+err:
+  sk_SSL_CIPHER_free(sk);
+  return NULL;
+}
+
+/* ssl_get_compatible_server_ciphers determines the key exchange and
+ * authentication cipher suite masks compatible with the server configuration
+ * and current ClientHello parameters of |hs|. It sets |*out_mask_k| to the key
+ * exchange mask and |*out_mask_a| to the authentication mask. */
+static void ssl_get_compatible_server_ciphers(SSL_HANDSHAKE *hs,
+                                              uint32_t *out_mask_k,
+                                              uint32_t *out_mask_a) {
+  SSL *const ssl = hs->ssl;
+  if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
+    *out_mask_k = SSL_kGENERIC;
+    *out_mask_a = SSL_aGENERIC;
+    return;
+  }
+
+  uint32_t mask_k = 0;
+  uint32_t mask_a = 0;
+
+  if (ssl_has_certificate(ssl)) {
+    int type = ssl_private_key_type(ssl);
+    if (type == NID_rsaEncryption) {
+      mask_k |= SSL_kRSA;
+      mask_a |= SSL_aRSA;
+    } else if (ssl_is_ecdsa_key_type(type)) {
+      mask_a |= SSL_aECDSA;
+    }
+  }
+
+  if (ssl->cert->dh_tmp != NULL || ssl->cert->dh_tmp_cb != NULL) {
+    mask_k |= SSL_kDHE;
+  }
+
+  /* Check for a shared group to consider ECDHE ciphers. */
+  uint16_t unused;
+  if (tls1_get_shared_group(hs, &unused)) {
+    mask_k |= SSL_kECDHE;
+  }
+
+  /* PSK requires a server callback. */
+  if (ssl->psk_server_callback != NULL) {
+    mask_k |= SSL_kPSK;
+    mask_a |= SSL_aPSK;
+  }
+
+  *out_mask_k = mask_k;
+  *out_mask_a = mask_a;
+}
+
+static const SSL_CIPHER *ssl3_choose_cipher(
+    SSL_HANDSHAKE *hs, const SSL_CLIENT_HELLO *client_hello,
+    const struct ssl_cipher_preference_list_st *server_pref) {
+  SSL *const ssl = hs->ssl;
+  const SSL_CIPHER *c, *ret = NULL;
+  STACK_OF(SSL_CIPHER) *srvr = server_pref->ciphers, *prio, *allow;
+  int ok;
+  size_t cipher_index;
+  uint32_t alg_k, alg_a, mask_k, mask_a;
+  /* in_group_flags will either be NULL, or will point to an array of bytes
+   * which indicate equal-preference groups in the |prio| stack. See the
+   * comment about |in_group_flags| in the |ssl_cipher_preference_list_st|
+   * struct. */
+  const uint8_t *in_group_flags;
+  /* group_min contains the minimal index so far found in a group, or -1 if no
+   * such value exists yet. */
+  int group_min = -1;
+
+  STACK_OF(SSL_CIPHER) *clnt = ssl_parse_client_cipher_list(client_hello);
+  if (clnt == NULL) {
+    return NULL;
+  }
+
+  if (ssl->options & SSL_OP_CIPHER_SERVER_PREFERENCE) {
+    prio = srvr;
+    in_group_flags = server_pref->in_group_flags;
+    allow = clnt;
+  } else {
+    prio = clnt;
+    in_group_flags = NULL;
+    allow = srvr;
+  }
+
+  ssl_get_compatible_server_ciphers(hs, &mask_k, &mask_a);
+
+  for (size_t i = 0; i < sk_SSL_CIPHER_num(prio); i++) {
+    c = sk_SSL_CIPHER_value(prio, i);
+
+    ok = 1;
+
+    /* Check the TLS version. */
+    if (SSL_CIPHER_get_min_version(c) > ssl3_protocol_version(ssl) ||
+        SSL_CIPHER_get_max_version(c) < ssl3_protocol_version(ssl)) {
+      ok = 0;
+    }
+
+    alg_k = c->algorithm_mkey;
+    alg_a = c->algorithm_auth;
+
+    ok = ok && (alg_k & mask_k) && (alg_a & mask_a);
+
+    if (ok && sk_SSL_CIPHER_find(allow, &cipher_index, c)) {
+      if (in_group_flags != NULL && in_group_flags[i] == 1) {
+        /* This element of |prio| is in a group. Update the minimum index found
+         * so far and continue looking. */
+        if (group_min == -1 || (size_t)group_min > cipher_index) {
+          group_min = cipher_index;
+        }
+      } else {
+        if (group_min != -1 && (size_t)group_min < cipher_index) {
+          cipher_index = group_min;
+        }
+        ret = sk_SSL_CIPHER_value(allow, cipher_index);
+        break;
+      }
+    }
+
+    if (in_group_flags != NULL && in_group_flags[i] == 0 && group_min != -1) {
+      /* We are about to leave a group, but we found a match in it, so that's
+       * our answer. */
+      ret = sk_SSL_CIPHER_value(allow, group_min);
+      break;
+    }
+  }
+
+  sk_SSL_CIPHER_free(clnt);
+  return ret;
+}
+
+static int ssl3_process_client_hello(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  if (!ssl_check_message_type(ssl, SSL3_MT_CLIENT_HELLO)) {
+    return -1;
+  }
+
+  SSL_CLIENT_HELLO client_hello;
+  if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg,
+                             ssl->init_num)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+    return -1;
+  }
+
+  /* Run the early callback. */
+  if (ssl->ctx->select_certificate_cb != NULL) {
+    switch (ssl->ctx->select_certificate_cb(&client_hello)) {
+      case ssl_select_cert_retry:
+        ssl->rwstate = SSL_CERTIFICATE_SELECTION_PENDING;
+        return -1;
+
+      case ssl_select_cert_error:
+        /* Connection rejected. */
+        OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_REJECTED);
+        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+        return -1;
+
+      default:
+        /* fallthrough */;
+    }
+  }
+
+  uint8_t alert = SSL_AD_DECODE_ERROR;
+  if (!negotiate_version(hs, &alert, &client_hello)) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
+    return -1;
+  }
+
+  /* Load the client random. */
+  if (client_hello.random_len != SSL3_RANDOM_SIZE) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    return -1;
+  }
+  OPENSSL_memcpy(ssl->s3->client_random, client_hello.random,
+                 client_hello.random_len);
+
+  /* Only null compression is supported. TLS 1.3 further requires the peer
+   * advertise no other compression. */
+  if (OPENSSL_memchr(client_hello.compression_methods, 0,
+                     client_hello.compression_methods_len) == NULL ||
+      (ssl3_protocol_version(ssl) >= TLS1_3_VERSION &&
+       client_hello.compression_methods_len != 1)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_COMPRESSION_LIST);
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+    return -1;
+  }
+
+  /* TLS extensions. */
+  if (!ssl_parse_clienthello_tlsext(hs, &client_hello)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
+    return -1;
+  }
+
+  return 1;
+}
+
+static int ssl3_select_certificate(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  /* Call |cert_cb| to update server certificates if required. */
+  if (ssl->cert->cert_cb != NULL) {
+    int rv = ssl->cert->cert_cb(ssl, ssl->cert->cert_cb_arg);
+    if (rv == 0) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_CB_ERROR);
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+      return -1;
+    }
+    if (rv < 0) {
+      ssl->rwstate = SSL_X509_LOOKUP;
+      return -1;
+    }
+  }
+
+  if (!ssl->ctx->x509_method->ssl_auto_chain_if_needed(ssl)) {
+    return -1;
+  }
+
+  if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
+    /* Jump to the TLS 1.3 state machine. */
+    hs->state = SSL_ST_TLS13;
+    hs->do_tls13_handshake = tls13_server_handshake;
+    return 1;
+  }
+
+  SSL_CLIENT_HELLO client_hello;
+  if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg,
+                             ssl->init_num)) {
+    return -1;
+  }
+
+  /* Negotiate the cipher suite. This must be done after |cert_cb| so the
+   * certificate is finalized. */
+  hs->new_cipher =
+      ssl3_choose_cipher(hs, &client_hello, ssl_get_cipher_preferences(ssl));
+  if (hs->new_cipher == NULL) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_NO_SHARED_CIPHER);
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+    return -1;
+  }
+
+  return 1;
+}
+
+static int ssl3_select_parameters(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  uint8_t al = SSL_AD_INTERNAL_ERROR;
+  int ret = -1;
+  SSL_SESSION *session = NULL;
+
+  SSL_CLIENT_HELLO client_hello;
+  if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg,
+                             ssl->init_num)) {
+    return -1;
+  }
+
+  /* Determine whether we are doing session resumption. */
+  int tickets_supported = 0, renew_ticket = 0;
+  switch (ssl_get_prev_session(ssl, &session, &tickets_supported, &renew_ticket,
+                               &client_hello)) {
+    case ssl_session_success:
+      break;
+    case ssl_session_error:
+      goto err;
+    case ssl_session_retry:
+      ssl->rwstate = SSL_PENDING_SESSION;
+      goto err;
+    case ssl_session_ticket_retry:
+      ssl->rwstate = SSL_PENDING_TICKET;
+      goto err;
+  }
+
+  if (session != NULL) {
+    if (session->extended_master_secret && !hs->extended_master_secret) {
+      /* A ClientHello without EMS that attempts to resume a session with EMS
+       * is fatal to the connection. */
+      al = SSL_AD_HANDSHAKE_FAILURE;
+      OPENSSL_PUT_ERROR(SSL, SSL_R_RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION);
+      goto f_err;
+    }
+
+    if (!ssl_session_is_resumable(hs, session) ||
+        /* If the client offers the EMS extension, but the previous session
+         * didn't use it, then negotiate a new session. */
+        hs->extended_master_secret != session->extended_master_secret) {
+      SSL_SESSION_free(session);
+      session = NULL;
+    }
+  }
+
+  if (session != NULL) {
+    /* Use the old session. */
+    hs->ticket_expected = renew_ticket;
+    ssl->session = session;
+    session = NULL;
+    ssl->s3->session_reused = 1;
+  } else {
+    hs->ticket_expected = tickets_supported;
+    ssl_set_session(ssl, NULL);
+    if (!ssl_get_new_session(hs, 1 /* server */)) {
+      goto err;
+    }
+
+    /* Clear the session ID if we want the session to be single-use. */
+    if (!(ssl->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER)) {
+      hs->new_session->session_id_length = 0;
+    }
+  }
+
+  if (ssl->ctx->dos_protection_cb != NULL &&
+      ssl->ctx->dos_protection_cb(&client_hello) == 0) {
+    /* Connection rejected for DOS reasons. */
+    al = SSL_AD_INTERNAL_ERROR;
+    OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_REJECTED);
+    goto f_err;
+  }
+
+  if (ssl->session == NULL) {
+    hs->new_session->cipher = hs->new_cipher;
+
+    /* On new sessions, stash the SNI value in the session. */
+    if (hs->hostname != NULL) {
+      OPENSSL_free(hs->new_session->tlsext_hostname);
+      hs->new_session->tlsext_hostname = BUF_strdup(hs->hostname);
+      if (hs->new_session->tlsext_hostname == NULL) {
+        al = SSL_AD_INTERNAL_ERROR;
+        goto f_err;
+      }
+    }
+
+    /* Determine whether to request a client certificate. */
+    hs->cert_request = !!(ssl->verify_mode & SSL_VERIFY_PEER);
+    /* Only request a certificate if Channel ID isn't negotiated. */
+    if ((ssl->verify_mode & SSL_VERIFY_PEER_IF_NO_OBC) &&
+        ssl->s3->tlsext_channel_id_valid) {
+      hs->cert_request = 0;
+    }
+    /* CertificateRequest may only be sent in certificate-based ciphers. */
+    if (!ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
+      hs->cert_request = 0;
+    }
+
+    if (!hs->cert_request) {
+      /* OpenSSL returns X509_V_OK when no certificates are requested. This is
+       * classed by them as a bug, but it's assumed by at least NGINX. */
+      hs->new_session->verify_result = X509_V_OK;
+    }
+  }
+
+  /* HTTP/2 negotiation depends on the cipher suite, so ALPN negotiation was
+   * deferred. Complete it now. */
+  if (!ssl_negotiate_alpn(hs, &al, &client_hello)) {
+    goto f_err;
+  }
+
+  /* Now that all parameters are known, initialize the handshake hash and hash
+   * the ClientHello. */
+  if (!SSL_TRANSCRIPT_init_hash(&hs->transcript, ssl3_protocol_version(ssl),
+                                hs->new_cipher->algorithm_prf) ||
+      !ssl_hash_current_message(hs)) {
+    goto f_err;
+  }
+
+  /* Release the handshake buffer if client authentication isn't required. */
+  if (!hs->cert_request) {
+    SSL_TRANSCRIPT_free_buffer(&hs->transcript);
+  }
+
+  ret = 1;
+
+  if (0) {
+  f_err:
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
+  }
+
+err:
+  SSL_SESSION_free(session);
+  return ret;
+}
+
+static int ssl3_send_server_hello(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+
+  /* We only accept ChannelIDs on connections with ECDHE in order to avoid a
+   * known attack while we fix ChannelID itself. */
+  if (ssl->s3->tlsext_channel_id_valid &&
+      (hs->new_cipher->algorithm_mkey & SSL_kECDHE) == 0) {
+    ssl->s3->tlsext_channel_id_valid = 0;
+  }
+
+  /* If this is a resumption and the original handshake didn't support
+   * ChannelID then we didn't record the original handshake hashes in the
+   * session and so cannot resume with ChannelIDs. */
+  if (ssl->session != NULL &&
+      ssl->session->original_handshake_hash_len == 0) {
+    ssl->s3->tlsext_channel_id_valid = 0;
+  }
+
+  struct OPENSSL_timeval now;
+  ssl_get_current_time(ssl, &now);
+  ssl->s3->server_random[0] = now.tv_sec >> 24;
+  ssl->s3->server_random[1] = now.tv_sec >> 16;
+  ssl->s3->server_random[2] = now.tv_sec >> 8;
+  ssl->s3->server_random[3] = now.tv_sec;
+  if (!RAND_bytes(ssl->s3->server_random + 4, SSL3_RANDOM_SIZE - 4)) {
+    return -1;
+  }
+
+  /* TODO(davidben): Implement the TLS 1.1 and 1.2 downgrade sentinels once TLS
+   * 1.3 is finalized and we are not implementing a draft version. */
+
+  const SSL_SESSION *session = hs->new_session;
+  if (ssl->session != NULL) {
+    session = ssl->session;
+  }
+
+  CBB cbb, body, session_id;
+  if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_SERVER_HELLO) ||
+      !CBB_add_u16(&body, ssl->version) ||
+      !CBB_add_bytes(&body, ssl->s3->server_random, SSL3_RANDOM_SIZE) ||
+      !CBB_add_u8_length_prefixed(&body, &session_id) ||
+      !CBB_add_bytes(&session_id, session->session_id,
+                     session->session_id_length) ||
+      !CBB_add_u16(&body, ssl_cipher_get_value(hs->new_cipher)) ||
+      !CBB_add_u8(&body, 0 /* no compression */) ||
+      !ssl_add_serverhello_tlsext(hs, &body) ||
+      !ssl_add_message_cbb(ssl, &cbb)) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    CBB_cleanup(&cbb);
+    return -1;
+  }
+
+  return 1;
+}
+
+static int ssl3_send_server_certificate(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  if (!ssl_has_certificate(ssl)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET);
+    return -1;
+  }
+
+  if (!ssl3_output_cert_chain(ssl)) {
+    return -1;
+  }
+  return 1;
+}
+
+static int ssl3_send_certificate_status(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  CBB cbb, body, ocsp_response;
+  if (!ssl->method->init_message(ssl, &cbb, &body,
+                                 SSL3_MT_CERTIFICATE_STATUS) ||
+      !CBB_add_u8(&body, TLSEXT_STATUSTYPE_ocsp) ||
+      !CBB_add_u24_length_prefixed(&body, &ocsp_response) ||
+      !CBB_add_bytes(&ocsp_response,
+                     CRYPTO_BUFFER_data(ssl->cert->ocsp_response),
+                     CRYPTO_BUFFER_len(ssl->cert->ocsp_response)) ||
+      !ssl_add_message_cbb(ssl, &cbb)) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    CBB_cleanup(&cbb);
+    return -1;
+  }
+
+  return 1;
+}
+
+static int ssl3_send_server_key_exchange(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  CBB cbb, child;
+  CBB_zero(&cbb);
+
+  /* Put together the parameters. */
+  if (hs->state == SSL3_ST_SW_KEY_EXCH_A) {
+    uint32_t alg_k = hs->new_cipher->algorithm_mkey;
+    uint32_t alg_a = hs->new_cipher->algorithm_auth;
+
+    /* Pre-allocate enough room to comfortably fit an ECDHE public key. */
+    if (!CBB_init(&cbb, 128)) {
+      goto err;
+    }
+
+    /* PSK ciphers begin with an identity hint. */
+    if (alg_a & SSL_aPSK) {
+      size_t len =
+          (ssl->psk_identity_hint == NULL) ? 0 : strlen(ssl->psk_identity_hint);
+      if (!CBB_add_u16_length_prefixed(&cbb, &child) ||
+          !CBB_add_bytes(&child, (const uint8_t *)ssl->psk_identity_hint,
+                         len)) {
+        goto err;
+      }
+    }
+
+    if (alg_k & SSL_kDHE) {
+      /* Determine the group to use. */
+      DH *params = ssl->cert->dh_tmp;
+      if (params == NULL && ssl->cert->dh_tmp_cb != NULL) {
+        params = ssl->cert->dh_tmp_cb(ssl, 0, 1024);
+      }
+      if (params == NULL) {
+        OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_TMP_DH_KEY);
+        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+        goto err;
+      }
+
+      /* Set up DH, generate a key, and emit the public half. */
+      DH *dh = DHparams_dup(params);
+      if (dh == NULL) {
+        goto err;
+      }
+
+      SSL_ECDH_CTX_init_for_dhe(&hs->ecdh_ctx, dh);
+      if (!CBB_add_u16_length_prefixed(&cbb, &child) ||
+          !BN_bn2cbb_padded(&child, BN_num_bytes(params->p), params->p) ||
+          !CBB_add_u16_length_prefixed(&cbb, &child) ||
+          !BN_bn2cbb_padded(&child, BN_num_bytes(params->g), params->g) ||
+          !CBB_add_u16_length_prefixed(&cbb, &child) ||
+          !SSL_ECDH_CTX_offer(&hs->ecdh_ctx, &child)) {
+        goto err;
+      }
+    } else if (alg_k & SSL_kECDHE) {
+      /* Determine the group to use. */
+      uint16_t group_id;
+      if (!tls1_get_shared_group(hs, &group_id)) {
+        OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_TMP_ECDH_KEY);
+        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+        goto err;
+      }
+      hs->new_session->group_id = group_id;
+
+      /* Set up ECDH, generate a key, and emit the public half. */
+      if (!SSL_ECDH_CTX_init(&hs->ecdh_ctx, group_id) ||
+          !CBB_add_u8(&cbb, NAMED_CURVE_TYPE) ||
+          !CBB_add_u16(&cbb, group_id) ||
+          !CBB_add_u8_length_prefixed(&cbb, &child) ||
+          !SSL_ECDH_CTX_offer(&hs->ecdh_ctx, &child)) {
+        goto err;
+      }
+    } else {
+      assert(alg_k & SSL_kPSK);
+    }
+
+    if (!CBB_finish(&cbb, &hs->server_params, &hs->server_params_len)) {
+      goto err;
+    }
+  }
+
+  /* Assemble the message. */
+  CBB body;
+  if (!ssl->method->init_message(ssl, &cbb, &body,
+                                 SSL3_MT_SERVER_KEY_EXCHANGE) ||
+      !CBB_add_bytes(&body, hs->server_params, hs->server_params_len)) {
+    goto err;
+  }
+
+  /* Add a signature. */
+  if (ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
+    if (!ssl_has_private_key(ssl)) {
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+      goto err;
+    }
+
+    /* Determine the signature algorithm. */
+    uint16_t signature_algorithm;
+    if (!tls1_choose_signature_algorithm(hs, &signature_algorithm)) {
+      goto err;
+    }
+    if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
+      if (!CBB_add_u16(&body, signature_algorithm)) {
+        OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+        goto err;
+      }
+    }
+
+    /* Add space for the signature. */
+    const size_t max_sig_len = ssl_private_key_max_signature_len(ssl);
+    uint8_t *ptr;
+    if (!CBB_add_u16_length_prefixed(&body, &child) ||
+        !CBB_reserve(&child, &ptr, max_sig_len)) {
+      goto err;
+    }
+
+    size_t sig_len;
+    enum ssl_private_key_result_t sign_result;
+    if (hs->state == SSL3_ST_SW_KEY_EXCH_A) {
+      CBB transcript;
+      uint8_t *transcript_data;
+      size_t transcript_len;
+      if (!CBB_init(&transcript,
+                    2 * SSL3_RANDOM_SIZE + hs->server_params_len) ||
+          !CBB_add_bytes(&transcript, ssl->s3->client_random,
+                         SSL3_RANDOM_SIZE) ||
+          !CBB_add_bytes(&transcript, ssl->s3->server_random,
+                         SSL3_RANDOM_SIZE) ||
+          !CBB_add_bytes(&transcript, hs->server_params,
+                         hs->server_params_len) ||
+          !CBB_finish(&transcript, &transcript_data, &transcript_len)) {
+        CBB_cleanup(&transcript);
+        OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+        goto err;
+      }
+
+      sign_result = ssl_private_key_sign(ssl, ptr, &sig_len, max_sig_len,
+                                         signature_algorithm, transcript_data,
+                                         transcript_len);
+      OPENSSL_free(transcript_data);
+    } else {
+      assert(hs->state == SSL3_ST_SW_KEY_EXCH_B);
+      sign_result = ssl_private_key_complete(ssl, ptr, &sig_len, max_sig_len);
+    }
+
+    switch (sign_result) {
+      case ssl_private_key_success:
+        if (!CBB_did_write(&child, sig_len)) {
+          goto err;
+        }
+        break;
+      case ssl_private_key_failure:
+        goto err;
+      case ssl_private_key_retry:
+        ssl->rwstate = SSL_PRIVATE_KEY_OPERATION;
+        hs->state = SSL3_ST_SW_KEY_EXCH_B;
+        goto err;
+    }
+  }
+
+  if (!ssl_add_message_cbb(ssl, &cbb)) {
+    goto err;
+  }
+
+  OPENSSL_free(hs->server_params);
+  hs->server_params = NULL;
+  hs->server_params_len = 0;
+
+  return 1;
+
+err:
+  CBB_cleanup(&cbb);
+  return -1;
+}
+
+static int add_cert_types(SSL *ssl, CBB *cbb) {
+  /* Get configured signature algorithms. */
+  int have_rsa_sign = 0;
+  int have_ecdsa_sign = 0;
+  const uint16_t *sig_algs;
+  size_t num_sig_algs = tls12_get_verify_sigalgs(ssl, &sig_algs);
+  for (size_t i = 0; i < num_sig_algs; i++) {
+    switch (sig_algs[i]) {
+      case SSL_SIGN_RSA_PKCS1_SHA512:
+      case SSL_SIGN_RSA_PKCS1_SHA384:
+      case SSL_SIGN_RSA_PKCS1_SHA256:
+      case SSL_SIGN_RSA_PKCS1_SHA1:
+        have_rsa_sign = 1;
+        break;
+
+      case SSL_SIGN_ECDSA_SECP521R1_SHA512:
+      case SSL_SIGN_ECDSA_SECP384R1_SHA384:
+      case SSL_SIGN_ECDSA_SECP256R1_SHA256:
+      case SSL_SIGN_ECDSA_SHA1:
+        have_ecdsa_sign = 1;
+        break;
+    }
+  }
+
+  if (have_rsa_sign && !CBB_add_u8(cbb, SSL3_CT_RSA_SIGN)) {
+    return 0;
+  }
+
+  /* ECDSA certs can be used with RSA cipher suites as well so we don't need to
+   * check for SSL_kECDH or SSL_kECDHE. */
+  if (ssl->version >= TLS1_VERSION && have_ecdsa_sign &&
+      !CBB_add_u8(cbb, TLS_CT_ECDSA_SIGN)) {
+    return 0;
+  }
+
+  return 1;
+}
+
+static int ssl3_send_certificate_request(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  CBB cbb, body, cert_types, sigalgs_cbb;
+  if (!ssl->method->init_message(ssl, &cbb, &body,
+                                 SSL3_MT_CERTIFICATE_REQUEST) ||
+      !CBB_add_u8_length_prefixed(&body, &cert_types) ||
+      !add_cert_types(ssl, &cert_types)) {
+    goto err;
+  }
+
+  if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
+    const uint16_t *sigalgs;
+    size_t num_sigalgs = tls12_get_verify_sigalgs(ssl, &sigalgs);
+    if (!CBB_add_u16_length_prefixed(&body, &sigalgs_cbb)) {
+      goto err;
+    }
+
+    for (size_t i = 0; i < num_sigalgs; i++) {
+      if (!CBB_add_u16(&sigalgs_cbb, sigalgs[i])) {
+        goto err;
+      }
+    }
+  }
+
+  if (!ssl_add_client_CA_list(ssl, &body) ||
+      !ssl_add_message_cbb(ssl, &cbb)) {
+    goto err;
+  }
+
+  return 1;
+
+err:
+  OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+  CBB_cleanup(&cbb);
+  return -1;
+}
+
+static int ssl3_send_server_hello_done(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  CBB cbb, body;
+  if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_SERVER_HELLO_DONE) ||
+      !ssl_add_message_cbb(ssl, &cbb)) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    CBB_cleanup(&cbb);
+    return -1;
+  }
+
+  return 1;
+}
+
+static int ssl3_get_client_certificate(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  assert(hs->cert_request);
+
+  int msg_ret = ssl->method->ssl_get_message(ssl);
+  if (msg_ret <= 0) {
+    return msg_ret;
+  }
+
+  if (ssl->s3->tmp.message_type != SSL3_MT_CERTIFICATE) {
+    if (ssl->version == SSL3_VERSION &&
+        ssl->s3->tmp.message_type == SSL3_MT_CLIENT_KEY_EXCHANGE) {
+      /* In SSL 3.0, the Certificate message is omitted to signal no
+       * certificate. */
+      if (ssl->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) {
+        OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
+        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+        return -1;
+      }
+
+      /* OpenSSL returns X509_V_OK when no certificates are received. This is
+       * classed by them as a bug, but it's assumed by at least NGINX. */
+      hs->new_session->verify_result = X509_V_OK;
+      ssl->s3->tmp.reuse_message = 1;
+      return 1;
+    }
+
+    OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+    return -1;
+  }
+
+  if (!ssl_hash_current_message(hs)) {
+    return -1;
+  }
+
+  CBS certificate_msg;
+  CBS_init(&certificate_msg, ssl->init_msg, ssl->init_num);
+
+  sk_CRYPTO_BUFFER_pop_free(hs->new_session->certs, CRYPTO_BUFFER_free);
+  EVP_PKEY_free(hs->peer_pubkey);
+  hs->peer_pubkey = NULL;
+  uint8_t alert = SSL_AD_DECODE_ERROR;
+  hs->new_session->certs = ssl_parse_cert_chain(
+      &alert, &hs->peer_pubkey,
+      ssl->retain_only_sha256_of_client_certs ? hs->new_session->peer_sha256
+                                              : NULL,
+      &certificate_msg, ssl->ctx->pool);
+  if (hs->new_session->certs == NULL) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
+    return -1;
+  }
+
+  if (CBS_len(&certificate_msg) != 0 ||
+      !ssl->ctx->x509_method->session_cache_objects(hs->new_session)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+    return -1;
+  }
+
+  if (sk_CRYPTO_BUFFER_num(hs->new_session->certs) == 0) {
+    /* No client certificate so the handshake buffer may be discarded. */
+    SSL_TRANSCRIPT_free_buffer(&hs->transcript);
+
+    /* In SSL 3.0, sending no certificate is signaled by omitting the
+     * Certificate message. */
+    if (ssl->version == SSL3_VERSION) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATES_RETURNED);
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+      return -1;
+    }
+
+    if (ssl->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) {
+      /* Fail for TLS only if we required a certificate */
+      OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+      return -1;
+    }
+
+    /* OpenSSL returns X509_V_OK when no certificates are received. This is
+     * classed by them as a bug, but it's assumed by at least NGINX. */
+    hs->new_session->verify_result = X509_V_OK;
+    return 1;
+  }
+
+  /* The hash will have been filled in. */
+  if (ssl->retain_only_sha256_of_client_certs) {
+    hs->new_session->peer_sha256_valid = 1;
+  }
+
+  if (!ssl->ctx->x509_method->session_verify_cert_chain(hs->new_session, ssl)) {
+    return -1;
+  }
+
+  return 1;
+}
+
+static int ssl3_get_client_key_exchange(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  int al;
+  CBS client_key_exchange;
+  uint32_t alg_k;
+  uint32_t alg_a;
+  uint8_t *premaster_secret = NULL;
+  size_t premaster_secret_len = 0;
+  uint8_t *decrypt_buf = NULL;
+
+  unsigned psk_len = 0;
+  uint8_t psk[PSK_MAX_PSK_LEN];
+
+  if (hs->state == SSL3_ST_SR_KEY_EXCH_A) {
+    int ret = ssl->method->ssl_get_message(ssl);
+    if (ret <= 0) {
+      return ret;
+    }
+
+    if (!ssl_check_message_type(ssl, SSL3_MT_CLIENT_KEY_EXCHANGE) ||
+        !ssl_hash_current_message(hs)) {
+      return -1;
+    }
+  }
+
+  CBS_init(&client_key_exchange, ssl->init_msg, ssl->init_num);
+  alg_k = hs->new_cipher->algorithm_mkey;
+  alg_a = hs->new_cipher->algorithm_auth;
+
+  /* If using a PSK key exchange, prepare the pre-shared key. */
+  if (alg_a & SSL_aPSK) {
+    CBS psk_identity;
+
+    /* If using PSK, the ClientKeyExchange contains a psk_identity. If PSK,
+     * then this is the only field in the message. */
+    if (!CBS_get_u16_length_prefixed(&client_key_exchange, &psk_identity) ||
+        ((alg_k & SSL_kPSK) && CBS_len(&client_key_exchange) != 0)) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+      al = SSL_AD_DECODE_ERROR;
+      goto f_err;
+    }
+
+    if (ssl->psk_server_callback == NULL) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_NO_SERVER_CB);
+      al = SSL_AD_INTERNAL_ERROR;
+      goto f_err;
+    }
+
+    if (CBS_len(&psk_identity) > PSK_MAX_IDENTITY_LEN ||
+        CBS_contains_zero_byte(&psk_identity)) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG);
+      al = SSL_AD_ILLEGAL_PARAMETER;
+      goto f_err;
+    }
+
+    if (!CBS_strdup(&psk_identity, &hs->new_session->psk_identity)) {
+      al = SSL_AD_INTERNAL_ERROR;
+      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+      goto f_err;
+    }
+
+    /* Look up the key for the identity. */
+    psk_len = ssl->psk_server_callback(ssl, hs->new_session->psk_identity, psk,
+                                       sizeof(psk));
+    if (psk_len > PSK_MAX_PSK_LEN) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+      al = SSL_AD_INTERNAL_ERROR;
+      goto f_err;
+    } else if (psk_len == 0) {
+      /* PSK related to the given identity not found */
+      OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_NOT_FOUND);
+      al = SSL_AD_UNKNOWN_PSK_IDENTITY;
+      goto f_err;
+    }
+  }
+
+  /* Depending on the key exchange method, compute |premaster_secret| and
+   * |premaster_secret_len|. */
+  if (alg_k & SSL_kRSA) {
+    /* Allocate a buffer large enough for an RSA decryption. */
+    const size_t rsa_size = ssl_private_key_max_signature_len(ssl);
+    decrypt_buf = OPENSSL_malloc(rsa_size);
+    if (decrypt_buf == NULL) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+      goto err;
+    }
+
+    enum ssl_private_key_result_t decrypt_result;
+    size_t decrypt_len;
+    if (hs->state == SSL3_ST_SR_KEY_EXCH_A) {
+      if (!ssl_has_private_key(ssl) ||
+          ssl_private_key_type(ssl) != NID_rsaEncryption) {
+        al = SSL_AD_HANDSHAKE_FAILURE;
+        OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_RSA_CERTIFICATE);
+        goto f_err;
+      }
+      CBS encrypted_premaster_secret;
+      if (ssl->version > SSL3_VERSION) {
+        if (!CBS_get_u16_length_prefixed(&client_key_exchange,
+                                         &encrypted_premaster_secret) ||
+            CBS_len(&client_key_exchange) != 0) {
+          al = SSL_AD_DECODE_ERROR;
+          OPENSSL_PUT_ERROR(SSL,
+                            SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG);
+          goto f_err;
+        }
+      } else {
+        encrypted_premaster_secret = client_key_exchange;
+      }
+
+      /* Decrypt with no padding. PKCS#1 padding will be removed as part of the
+       * timing-sensitive code below. */
+      decrypt_result = ssl_private_key_decrypt(
+          ssl, decrypt_buf, &decrypt_len, rsa_size,
+          CBS_data(&encrypted_premaster_secret),
+          CBS_len(&encrypted_premaster_secret));
+    } else {
+      assert(hs->state == SSL3_ST_SR_KEY_EXCH_B);
+      /* Complete async decrypt. */
+      decrypt_result =
+          ssl_private_key_complete(ssl, decrypt_buf, &decrypt_len, rsa_size);
+    }
+
+    switch (decrypt_result) {
+      case ssl_private_key_success:
+        break;
+      case ssl_private_key_failure:
+        goto err;
+      case ssl_private_key_retry:
+        ssl->rwstate = SSL_PRIVATE_KEY_OPERATION;
+        hs->state = SSL3_ST_SR_KEY_EXCH_B;
+        goto err;
+    }
+
+    if (decrypt_len != rsa_size) {
+      al = SSL_AD_DECRYPT_ERROR;
+      OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED);
+      goto f_err;
+    }
+
+    /* Prepare a random premaster, to be used on invalid padding. See RFC 5246,
+     * section 7.4.7.1. */
+    premaster_secret_len = SSL_MAX_MASTER_KEY_LENGTH;
+    premaster_secret = OPENSSL_malloc(premaster_secret_len);
+    if (premaster_secret == NULL) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+      goto err;
+    }
+    if (!RAND_bytes(premaster_secret, premaster_secret_len)) {
+      goto err;
+    }
+
+    /* The smallest padded premaster is 11 bytes of overhead. Small keys are
+     * publicly invalid. */
+    if (decrypt_len < 11 + premaster_secret_len) {
+      al = SSL_AD_DECRYPT_ERROR;
+      OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED);
+      goto f_err;
+    }
+
+    /* Check the padding. See RFC 3447, section 7.2.2. */
+    size_t padding_len = decrypt_len - premaster_secret_len;
+    uint8_t good = constant_time_eq_int_8(decrypt_buf[0], 0) &
+                   constant_time_eq_int_8(decrypt_buf[1], 2);
+    for (size_t i = 2; i < padding_len - 1; i++) {
+      good &= ~constant_time_is_zero_8(decrypt_buf[i]);
+    }
+    good &= constant_time_is_zero_8(decrypt_buf[padding_len - 1]);
+
+    /* The premaster secret must begin with |client_version|. This too must be
+     * checked in constant time (http://eprint.iacr.org/2003/052/). */
+    good &= constant_time_eq_8(decrypt_buf[padding_len],
+                               (unsigned)(hs->client_version >> 8));
+    good &= constant_time_eq_8(decrypt_buf[padding_len + 1],
+                               (unsigned)(hs->client_version & 0xff));
+
+    /* Select, in constant time, either the decrypted premaster or the random
+     * premaster based on |good|. */
+    for (size_t i = 0; i < premaster_secret_len; i++) {
+      premaster_secret[i] = constant_time_select_8(
+          good, decrypt_buf[padding_len + i], premaster_secret[i]);
+    }
+
+    OPENSSL_free(decrypt_buf);
+    decrypt_buf = NULL;
+  } else if (alg_k & (SSL_kECDHE|SSL_kDHE)) {
+    /* Parse the ClientKeyExchange. */
+    CBS peer_key;
+    if (!SSL_ECDH_CTX_get_key(&hs->ecdh_ctx, &client_key_exchange, &peer_key) ||
+        CBS_len(&client_key_exchange) != 0) {
+      al = SSL_AD_DECODE_ERROR;
+      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+      goto f_err;
+    }
+
+    /* Compute the premaster. */
+    uint8_t alert = SSL_AD_DECODE_ERROR;
+    if (!SSL_ECDH_CTX_finish(&hs->ecdh_ctx, &premaster_secret,
+                             &premaster_secret_len, &alert, CBS_data(&peer_key),
+                             CBS_len(&peer_key))) {
+      al = alert;
+      goto f_err;
+    }
+
+    /* The key exchange state may now be discarded. */
+    SSL_ECDH_CTX_cleanup(&hs->ecdh_ctx);
+  } else if (alg_k & SSL_kPSK) {
+    /* For plain PSK, other_secret is a block of 0s with the same length as the
+     * pre-shared key. */
+    premaster_secret_len = psk_len;
+    premaster_secret = OPENSSL_malloc(premaster_secret_len);
+    if (premaster_secret == NULL) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+      goto err;
+    }
+    OPENSSL_memset(premaster_secret, 0, premaster_secret_len);
+  } else {
+    al = SSL_AD_HANDSHAKE_FAILURE;
+    OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CIPHER_TYPE);
+    goto f_err;
+  }
+
+  /* For a PSK cipher suite, the actual pre-master secret is combined with the
+   * pre-shared key. */
+  if (alg_a & SSL_aPSK) {
+    CBB new_premaster, child;
+    uint8_t *new_data;
+    size_t new_len;
+
+    CBB_zero(&new_premaster);
+    if (!CBB_init(&new_premaster, 2 + psk_len + 2 + premaster_secret_len) ||
+        !CBB_add_u16_length_prefixed(&new_premaster, &child) ||
+        !CBB_add_bytes(&child, premaster_secret, premaster_secret_len) ||
+        !CBB_add_u16_length_prefixed(&new_premaster, &child) ||
+        !CBB_add_bytes(&child, psk, psk_len) ||
+        !CBB_finish(&new_premaster, &new_data, &new_len)) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+      CBB_cleanup(&new_premaster);
+      goto err;
+    }
+
+    OPENSSL_cleanse(premaster_secret, premaster_secret_len);
+    OPENSSL_free(premaster_secret);
+    premaster_secret = new_data;
+    premaster_secret_len = new_len;
+  }
+
+  /* Compute the master secret */
+  hs->new_session->master_key_length = tls1_generate_master_secret(
+      hs, hs->new_session->master_key, premaster_secret, premaster_secret_len);
+  if (hs->new_session->master_key_length == 0) {
+    goto err;
+  }
+  hs->new_session->extended_master_secret = hs->extended_master_secret;
+
+  OPENSSL_cleanse(premaster_secret, premaster_secret_len);
+  OPENSSL_free(premaster_secret);
+  return 1;
+
+f_err:
+  ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
+err:
+  if (premaster_secret != NULL) {
+    OPENSSL_cleanse(premaster_secret, premaster_secret_len);
+    OPENSSL_free(premaster_secret);
+  }
+  OPENSSL_free(decrypt_buf);
+
+  return -1;
+}
+
+static int ssl3_get_cert_verify(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  int al;
+  CBS certificate_verify, signature;
+
+  /* Only RSA and ECDSA client certificates are supported, so a
+   * CertificateVerify is required if and only if there's a client certificate.
+   * */
+  if (hs->peer_pubkey == NULL) {
+    SSL_TRANSCRIPT_free_buffer(&hs->transcript);
+    return 1;
+  }
+
+  int msg_ret = ssl->method->ssl_get_message(ssl);
+  if (msg_ret <= 0) {
+    return msg_ret;
+  }
+
+  if (!ssl_check_message_type(ssl, SSL3_MT_CERTIFICATE_VERIFY)) {
+    return -1;
+  }
+
+  CBS_init(&certificate_verify, ssl->init_msg, ssl->init_num);
+
+  /* Determine the digest type if needbe. */
+  uint16_t signature_algorithm = 0;
+  if (ssl3_protocol_version(ssl) >= TLS1_2_VERSION) {
+    if (!CBS_get_u16(&certificate_verify, &signature_algorithm)) {
+      al = SSL_AD_DECODE_ERROR;
+      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+      goto f_err;
+    }
+    if (!tls12_check_peer_sigalg(ssl, &al, signature_algorithm)) {
+      goto f_err;
+    }
+    hs->new_session->peer_signature_algorithm = signature_algorithm;
+  } else if (hs->peer_pubkey->type == EVP_PKEY_RSA) {
+    signature_algorithm = SSL_SIGN_RSA_PKCS1_MD5_SHA1;
+  } else if (hs->peer_pubkey->type == EVP_PKEY_EC) {
+    signature_algorithm = SSL_SIGN_ECDSA_SHA1;
+  } else {
+    al = SSL_AD_UNSUPPORTED_CERTIFICATE;
+    OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE);
+    goto f_err;
+  }
+
+  /* Parse and verify the signature. */
+  if (!CBS_get_u16_length_prefixed(&certificate_verify, &signature) ||
+      CBS_len(&certificate_verify) != 0) {
+    al = SSL_AD_DECODE_ERROR;
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    goto f_err;
+  }
+
+  int sig_ok;
+  /* The SSL3 construction for CertificateVerify does not decompose into a
+   * single final digest and signature, and must be special-cased. */
+  if (ssl3_protocol_version(ssl) == SSL3_VERSION) {
+    uint8_t digest[EVP_MAX_MD_SIZE];
+    size_t digest_len;
+    if (!SSL_TRANSCRIPT_ssl3_cert_verify_hash(&hs->transcript, digest,
+                                              &digest_len, hs->new_session,
+                                              signature_algorithm)) {
+      goto err;
+    }
+
+    EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new(hs->peer_pubkey, NULL);
+    sig_ok = pctx != NULL &&
+             EVP_PKEY_verify_init(pctx) &&
+             EVP_PKEY_verify(pctx, CBS_data(&signature), CBS_len(&signature),
+                             digest, digest_len);
+    EVP_PKEY_CTX_free(pctx);
+  } else {
+    sig_ok = ssl_public_key_verify(
+        ssl, CBS_data(&signature), CBS_len(&signature), signature_algorithm,
+        hs->peer_pubkey, (const uint8_t *)hs->transcript.buffer->data,
+        hs->transcript.buffer->length);
+  }
+
+#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
+  sig_ok = 1;
+  ERR_clear_error();
+#endif
+  if (!sig_ok) {
+    al = SSL_AD_DECRYPT_ERROR;
+    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SIGNATURE);
+    goto f_err;
+  }
+
+  /* The handshake buffer is no longer necessary, and we may hash the current
+   * message.*/
+  SSL_TRANSCRIPT_free_buffer(&hs->transcript);
+  if (!ssl_hash_current_message(hs)) {
+    goto err;
+  }
+
+  return 1;
+
+f_err:
+  ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
+err:
+  return 0;
+}
+
+/* ssl3_get_next_proto reads a Next Protocol Negotiation handshake message. It
+ * sets the next_proto member in s if found */
+static int ssl3_get_next_proto(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  int ret = ssl->method->ssl_get_message(ssl);
+  if (ret <= 0) {
+    return ret;
+  }
+
+  if (!ssl_check_message_type(ssl, SSL3_MT_NEXT_PROTO) ||
+      !ssl_hash_current_message(hs)) {
+    return -1;
+  }
+
+  CBS next_protocol, selected_protocol, padding;
+  CBS_init(&next_protocol, ssl->init_msg, ssl->init_num);
+  if (!CBS_get_u8_length_prefixed(&next_protocol, &selected_protocol) ||
+      !CBS_get_u8_length_prefixed(&next_protocol, &padding) ||
+      CBS_len(&next_protocol) != 0) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+    return 0;
+  }
+
+  if (!CBS_stow(&selected_protocol, &ssl->s3->next_proto_negotiated,
+                &ssl->s3->next_proto_negotiated_len)) {
+    return 0;
+  }
+
+  return 1;
+}
+
+/* ssl3_get_channel_id reads and verifies a ClientID handshake message. */
+static int ssl3_get_channel_id(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  int msg_ret = ssl->method->ssl_get_message(ssl);
+  if (msg_ret <= 0) {
+    return msg_ret;
+  }
+
+  if (!ssl_check_message_type(ssl, SSL3_MT_CHANNEL_ID) ||
+      !tls1_verify_channel_id(hs) ||
+      !ssl_hash_current_message(hs)) {
+    return -1;
+  }
+  return 1;
+}
+
+static int ssl3_send_new_session_ticket(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  const SSL_SESSION *session;
+  SSL_SESSION *session_copy = NULL;
+  if (ssl->session == NULL) {
+    /* Fix the timeout to measure from the ticket issuance time. */
+    ssl_session_rebase_time(ssl, hs->new_session);
+    session = hs->new_session;
+  } else {
+    /* We are renewing an existing session. Duplicate the session to adjust the
+     * timeout. */
+    session_copy = SSL_SESSION_dup(ssl->session, SSL_SESSION_INCLUDE_NONAUTH);
+    if (session_copy == NULL) {
+      return -1;
+    }
+
+    ssl_session_rebase_time(ssl, session_copy);
+    session = session_copy;
+  }
+
+  CBB cbb, body, ticket;
+  int ok =
+      ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_NEW_SESSION_TICKET) &&
+      CBB_add_u32(&body, session->timeout) &&
+      CBB_add_u16_length_prefixed(&body, &ticket) &&
+      ssl_encrypt_ticket(ssl, &ticket, session) &&
+      ssl_add_message_cbb(ssl, &cbb);
+
+  SSL_SESSION_free(session_copy);
+  CBB_cleanup(&cbb);
+
+  if (!ok) {
+    return -1;
+  }
+
+  return 1;
+}
diff --git a/src/ssl/internal.h b/src/ssl/internal.h
index 5acb598..ded5ba8 100644
--- a/src/ssl/internal.h
+++ b/src/ssl/internal.h
@@ -145,19 +145,23 @@
 #include <openssl/base.h>
 
 #include <openssl/aead.h>
-#include <openssl/pqueue.h>
 #include <openssl/ssl.h>
 #include <openssl/stack.h>
 
+
 #if defined(OPENSSL_WINDOWS)
 /* Windows defines struct timeval in winsock2.h. */
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <winsock2.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
 #else
 #include <sys/time.h>
 #endif
 
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
 
 /* Cipher suites. */
 
@@ -167,33 +171,34 @@
 #define SSL_kECDHE 0x00000004L
 /* SSL_kPSK is only set for plain PSK, not ECDHE_PSK. */
 #define SSL_kPSK 0x00000008L
+#define SSL_kGENERIC 0x00000010L
 
 /* Bits for |algorithm_auth| (server authentication). */
 #define SSL_aRSA 0x00000001L
 #define SSL_aECDSA 0x00000002L
 /* SSL_aPSK is set for both PSK and ECDHE_PSK. */
 #define SSL_aPSK 0x00000004L
+#define SSL_aGENERIC 0x00000008L
+
+#define SSL_aCERT (SSL_aRSA | SSL_aECDSA)
 
 /* Bits for |algorithm_enc| (symmetric encryption). */
-#define SSL_3DES 0x00000001L
-#define SSL_RC4 0x00000002L
-#define SSL_AES128 0x00000004L
-#define SSL_AES256 0x00000008L
-#define SSL_AES128GCM 0x00000010L
-#define SSL_AES256GCM 0x00000020L
-#define SSL_CHACHA20POLY1305_OLD 0x00000040L
-#define SSL_eNULL 0x00000080L
-#define SSL_CHACHA20POLY1305 0x00000100L
+#define SSL_3DES                 0x00000001L
+#define SSL_AES128               0x00000002L
+#define SSL_AES256               0x00000004L
+#define SSL_AES128GCM            0x00000008L
+#define SSL_AES256GCM            0x00000010L
+#define SSL_eNULL                0x00000020L
+#define SSL_CHACHA20POLY1305     0x00000040L
 
 #define SSL_AES (SSL_AES128 | SSL_AES256 | SSL_AES128GCM | SSL_AES256GCM)
 
 /* Bits for |algorithm_mac| (symmetric authentication). */
-#define SSL_MD5 0x00000001L
-#define SSL_SHA1 0x00000002L
-#define SSL_SHA256 0x00000004L
-#define SSL_SHA384 0x00000008L
+#define SSL_SHA1 0x00000001L
+#define SSL_SHA256 0x00000002L
+#define SSL_SHA384 0x00000004L
 /* SSL_AEAD is set for all AEADs. */
-#define SSL_AEAD 0x00000010L
+#define SSL_AEAD 0x00000008L
 
 /* Bits for |algorithm_prf| (handshake digest). */
 #define SSL_HANDSHAKE_MAC_DEFAULT 0x1
@@ -215,22 +220,20 @@
                             const SSL_CIPHER *cipher, uint16_t version);
 
 /* ssl_get_handshake_digest returns the |EVP_MD| corresponding to
- * |algorithm_prf|. It returns SHA-1 for |SSL_HANDSHAKE_DEFAULT|. The caller is
- * responsible for maintaining the additional MD5 digest and switching to
- * SHA-256 in TLS 1.2. */
-const EVP_MD *ssl_get_handshake_digest(uint32_t algorithm_prf);
+ * |algorithm_prf| and the |version|. */
+const EVP_MD *ssl_get_handshake_digest(uint32_t algorithm_prf,
+                                       uint16_t version);
 
 /* ssl_create_cipher_list evaluates |rule_str| according to the ciphers in
  * |ssl_method|. It sets |*out_cipher_list| to a newly-allocated
- * |ssl_cipher_preference_list_st| containing the result.
- * |*out_cipher_list_by_id| is set to a list of selected ciphers sorted by
- * id. It returns |(*out_cipher_list)->ciphers| on success and NULL on
- * failure. */
-STACK_OF(SSL_CIPHER) *
-ssl_create_cipher_list(const SSL_PROTOCOL_METHOD *ssl_method,
-                       struct ssl_cipher_preference_list_st **out_cipher_list,
-                       STACK_OF(SSL_CIPHER) **out_cipher_list_by_id,
-                       const char *rule_str);
+ * |ssl_cipher_preference_list_st| containing the result. It returns 1 on
+ * success and 0 on failure. If |strict| is true, nonsense will be rejected. If
+ * false, nonsense will be silently ignored. An empty result is considered an
+ * error regardless of |strict|. */
+int ssl_create_cipher_list(
+    const SSL_PROTOCOL_METHOD *ssl_method,
+    struct ssl_cipher_preference_list_st **out_cipher_list,
+    const char *rule_str, int strict);
 
 /* ssl_cipher_get_value returns the cipher suite id of |cipher|. */
 uint16_t ssl_cipher_get_value(const SSL_CIPHER *cipher);
@@ -239,17 +242,16 @@
  * server key used in |cipher| or |EVP_PKEY_NONE| if there is none. */
 int ssl_cipher_get_key_type(const SSL_CIPHER *cipher);
 
-/* ssl_cipher_has_server_public_key returns 1 if |cipher| involves a server
- * public key in the key exchange, sent in a server Certificate message.
- * Otherwise it returns 0. */
-int ssl_cipher_has_server_public_key(const SSL_CIPHER *cipher);
+/* ssl_cipher_uses_certificate_auth returns one if |cipher| authenticates the
+ * server and, optionally, the client with a certificate. Otherwise it returns
+ * zero. */
+int ssl_cipher_uses_certificate_auth(const SSL_CIPHER *cipher);
 
 /* ssl_cipher_requires_server_key_exchange returns 1 if |cipher| requires a
  * ServerKeyExchange message. Otherwise it returns 0.
  *
- * Unlike |ssl_cipher_has_server_public_key|, this function may return zero
- * while still allowing |cipher| an optional ServerKeyExchange. This is the
- * case for plain PSK ciphers. */
+ * This function may return zero while still allowing |cipher| an optional
+ * ServerKeyExchange. This is the case for plain PSK ciphers. */
 int ssl_cipher_requires_server_key_exchange(const SSL_CIPHER *cipher);
 
 /* ssl_cipher_get_record_split_len, for TLS 1.0 CBC mode ciphers, returns the
@@ -258,34 +260,119 @@
 size_t ssl_cipher_get_record_split_len(const SSL_CIPHER *cipher);
 
 
+/* Transcript layer. */
+
+/* SSL_TRANSCRIPT maintains the handshake transcript as a combination of a
+ * buffer and running hash. */
+typedef struct ssl_transcript_st {
+  /* buffer, if non-NULL, contains the handshake transcript. */
+  BUF_MEM *buffer;
+  /* hash, if initialized with an |EVP_MD|, maintains the handshake hash. For
+   * TLS 1.1 and below, it is the SHA-1 half. */
+  EVP_MD_CTX hash;
+  /* md5, if initialized with an |EVP_MD|, maintains the MD5 half of the
+   * handshake hash for TLS 1.1 and below. */
+  EVP_MD_CTX md5;
+} SSL_TRANSCRIPT;
+
+/* SSL_TRANSCRIPT_init initializes the handshake transcript. If called on an
+ * existing transcript, it resets the transcript and hash. It returns one on
+ * success and zero on failure. */
+int SSL_TRANSCRIPT_init(SSL_TRANSCRIPT *transcript);
+
+/* SSL_TRANSCRIPT_init_hash initializes the handshake hash based on the PRF and
+ * contents of the handshake transcript. Subsequent calls to
+ * |SSL_TRANSCRIPT_update| will update the rolling hash. It returns one on
+ * success and zero on failure. It is an error to call this function after the
+ * handshake buffer is released. */
+int SSL_TRANSCRIPT_init_hash(SSL_TRANSCRIPT *transcript, uint16_t version,
+                             int algorithm_prf);
+
+/* SSL_TRANSCRIPT_cleanup cleans up the hash and transcript. */
+void SSL_TRANSCRIPT_cleanup(SSL_TRANSCRIPT *transcript);
+
+/* SSL_TRANSCRIPT_free_buffer releases the handshake buffer. Subsequent calls to
+ * |SSL_TRANSCRIPT_update| will not update the handshake buffer. */
+void SSL_TRANSCRIPT_free_buffer(SSL_TRANSCRIPT *transcript);
+
+/* SSL_TRANSCRIPT_digest_len returns the length of the PRF hash. */
+size_t SSL_TRANSCRIPT_digest_len(const SSL_TRANSCRIPT *transcript);
+
+/* SSL_TRANSCRIPT_md returns the PRF hash. For TLS 1.1 and below, this is
+ * |EVP_md5_sha1|. */
+const EVP_MD *SSL_TRANSCRIPT_md(const SSL_TRANSCRIPT *transcript);
+
+/* SSL_TRANSCRIPT_update adds |in| to the handshake buffer and handshake hash,
+ * whichever is enabled. It returns one on success and zero on failure. */
+int SSL_TRANSCRIPT_update(SSL_TRANSCRIPT *transcript, const uint8_t *in,
+                          size_t in_len);
+
+/* SSL_TRANSCRIPT_get_hash writes the handshake hash to |out| which must have
+ * room for at least |SSL_TRANSCRIPT_digest_len| bytes. On success, it returns
+ * one and sets |*out_len| to the number of bytes written. Otherwise, it returns
+ * zero. */
+int SSL_TRANSCRIPT_get_hash(const SSL_TRANSCRIPT *transcript, uint8_t *out,
+                            size_t *out_len);
+
+/* SSL_TRANSCRIPT_ssl3_cert_verify_hash writes the SSL 3.0 CertificateVerify
+ * hash into the bytes pointed to by |out| and writes the number of bytes to
+ * |*out_len|. |out| must have room for |EVP_MAX_MD_SIZE| bytes. It returns one
+ * on success and zero on failure. */
+int SSL_TRANSCRIPT_ssl3_cert_verify_hash(SSL_TRANSCRIPT *transcript,
+                                         uint8_t *out, size_t *out_len,
+                                         const SSL_SESSION *session,
+                                         int signature_algorithm);
+
+/* SSL_TRANSCRIPT_finish_mac computes the MAC for the Finished message into the
+ * bytes pointed by |out| and writes the number of bytes to |*out_len|. |out|
+ * must have room for |EVP_MAX_MD_SIZE| bytes. It returns one on success and
+ * zero on failure. */
+int SSL_TRANSCRIPT_finish_mac(SSL_TRANSCRIPT *transcript, uint8_t *out,
+                              size_t *out_len, const SSL_SESSION *session,
+                              int from_server, uint16_t version);
+
+/* tls1_prf computes the PRF function for |ssl|. It writes |out_len| bytes to
+ * |out|, using |secret| as the secret and |label| as the label. |seed1| and
+ * |seed2| are concatenated to form the seed parameter. It returns one on
+ * success and zero on failure. */
+int tls1_prf(const EVP_MD *digest, uint8_t *out, size_t out_len,
+             const uint8_t *secret, size_t secret_len, const char *label,
+             size_t label_len, const uint8_t *seed1, size_t seed1_len,
+             const uint8_t *seed2, size_t seed2_len);
+
+
 /* Encryption layer. */
 
 /* SSL_AEAD_CTX contains information about an AEAD that is being used to encrypt
  * an SSL connection. */
-struct ssl_aead_ctx_st {
+typedef struct ssl_aead_ctx_st {
   const SSL_CIPHER *cipher;
   EVP_AEAD_CTX ctx;
   /* fixed_nonce contains any bytes of the nonce that are fixed for all
    * records. */
   uint8_t fixed_nonce[12];
   uint8_t fixed_nonce_len, variable_nonce_len;
+  /* version is the protocol version that should be used with this AEAD. */
+  uint16_t version;
   /* variable_nonce_included_in_record is non-zero if the variable nonce
    * for a record is included as a prefix before the ciphertext. */
-  char variable_nonce_included_in_record;
+  unsigned variable_nonce_included_in_record : 1;
   /* random_variable_nonce is non-zero if the variable nonce is
    * randomly generated, rather than derived from the sequence
    * number. */
-  char random_variable_nonce;
+  unsigned random_variable_nonce : 1;
   /* omit_length_in_ad is non-zero if the length should be omitted in the
    * AEAD's ad parameter. */
-  char omit_length_in_ad;
+  unsigned omit_length_in_ad : 1;
   /* omit_version_in_ad is non-zero if the version should be omitted
    * in the AEAD's ad parameter. */
-  char omit_version_in_ad;
+  unsigned omit_version_in_ad : 1;
+  /* omit_ad is non-zero if the AEAD's ad parameter should be omitted. */
+  unsigned omit_ad : 1;
   /* xor_fixed_nonce is non-zero if the fixed nonce should be XOR'd into the
    * variable nonce rather than prepended. */
-  char xor_fixed_nonce;
-} /* SSL_AEAD_CTX */;
+  unsigned xor_fixed_nonce : 1;
+} SSL_AEAD_CTX;
 
 /* SSL_AEAD_CTX_new creates a newly-allocated |SSL_AEAD_CTX| using the supplied
  * key material. It returns NULL on error. Only one of |SSL_AEAD_CTX_open| or
@@ -303,27 +390,25 @@
 
 /* SSL_AEAD_CTX_explicit_nonce_len returns the length of the explicit nonce for
  * |ctx|, if any. |ctx| may be NULL to denote the null cipher. */
-size_t SSL_AEAD_CTX_explicit_nonce_len(SSL_AEAD_CTX *ctx);
+size_t SSL_AEAD_CTX_explicit_nonce_len(const SSL_AEAD_CTX *ctx);
 
 /* SSL_AEAD_CTX_max_overhead returns the maximum overhead of calling
  * |SSL_AEAD_CTX_seal|. |ctx| may be NULL to denote the null cipher. */
-size_t SSL_AEAD_CTX_max_overhead(SSL_AEAD_CTX *ctx);
+size_t SSL_AEAD_CTX_max_overhead(const SSL_AEAD_CTX *ctx);
 
-/* SSL_AEAD_CTX_open authenticates and decrypts |in_len| bytes from |in| and
- * writes the result to |out|. It returns one on success and zero on
- * error. |ctx| may be NULL to denote the null cipher.
- *
- * If |in| and |out| alias then |out| must be <= |in| + |explicit_nonce_len|. */
-int SSL_AEAD_CTX_open(SSL_AEAD_CTX *ctx, uint8_t *out, size_t *out_len,
-                      size_t max_out, uint8_t type, uint16_t wire_version,
-                      const uint8_t seqnum[8], const uint8_t *in,
-                      size_t in_len);
+/* SSL_AEAD_CTX_open authenticates and decrypts |in_len| bytes from |in|
+ * in-place. On success, it sets |*out| to the plaintext in |in| and returns
+ * one. Otherwise, it returns zero. |ctx| may be NULL to denote the null cipher.
+ * The output will always be |explicit_nonce_len| bytes ahead of |in|. */
+int SSL_AEAD_CTX_open(SSL_AEAD_CTX *ctx, CBS *out, uint8_t type,
+                      uint16_t wire_version, const uint8_t seqnum[8],
+                      uint8_t *in, size_t in_len);
 
 /* SSL_AEAD_CTX_seal encrypts and authenticates |in_len| bytes from |in| and
  * writes the result to |out|. It returns one on success and zero on
  * error. |ctx| may be NULL to denote the null cipher.
  *
- * If |in| and |out| alias then |out| + |explicit_nonce_len| must be <= |in| */
+ * If |in| and |out| alias then |out| + |explicit_nonce_len| must be == |in|. */
 int SSL_AEAD_CTX_seal(SSL_AEAD_CTX *ctx, uint8_t *out, size_t *out_len,
                       size_t max_out, uint8_t type, uint16_t wire_version,
                       const uint8_t seqnum[8], const uint8_t *in,
@@ -346,6 +431,10 @@
 
 /* Record layer. */
 
+/* ssl_record_sequence_update increments the sequence number in |seq|. It
+ * returns one on success and zero on wraparound. */
+int ssl_record_sequence_update(uint8_t *seq, size_t seq_len);
+
 /* ssl_record_prefix_len returns the length of the prefix before the ciphertext
  * of a record for |ssl|.
  *
@@ -357,67 +446,68 @@
   ssl_open_record_success,
   ssl_open_record_discard,
   ssl_open_record_partial,
+  ssl_open_record_close_notify,
+  ssl_open_record_fatal_alert,
   ssl_open_record_error,
 };
 
-/* tls_open_record decrypts a record from |in|.
- *
- * On success, it returns |ssl_open_record_success|. It sets |*out_type| to the
- * record type, |*out_len| to the plaintext length, and writes the record body
- * to |out|. It sets |*out_consumed| to the number of bytes of |in| consumed.
- * Note that |*out_len| may be zero.
- *
- * If a record was successfully processed but should be discarded, it returns
- * |ssl_open_record_discard| and sets |*out_consumed| to the number of bytes
- * consumed.
+/* tls_open_record decrypts a record from |in| in-place.
  *
  * If the input did not contain a complete record, it returns
  * |ssl_open_record_partial|. It sets |*out_consumed| to the total number of
  * bytes necessary. It is guaranteed that a successful call to |tls_open_record|
  * will consume at least that many bytes.
  *
- * On failure, it returns |ssl_open_record_error| and sets |*out_alert| to an
- * alert to emit.
+ * Otherwise, it sets |*out_consumed| to the number of bytes of input
+ * consumed. Note that input may be consumed on all return codes if a record was
+ * decrypted.
  *
- * If |in| and |out| alias, |out| must be <= |in| + |ssl_record_prefix_len|. */
-enum ssl_open_record_t tls_open_record(
-    SSL *ssl, uint8_t *out_type, uint8_t *out, size_t *out_len,
-    size_t *out_consumed, uint8_t *out_alert, size_t max_out, const uint8_t *in,
-    size_t in_len);
+ * On success, it returns |ssl_open_record_success|. It sets |*out_type| to the
+ * record type and |*out| to the record body in |in|. Note that |*out| may be
+ * empty.
+ *
+ * If a record was successfully processed but should be discarded, it returns
+ * |ssl_open_record_discard|.
+ *
+ * If a record was successfully processed but is a close_notify or fatal alert,
+ * it returns |ssl_open_record_close_notify| or |ssl_open_record_fatal_alert|.
+ *
+ * On failure, it returns |ssl_open_record_error| and sets |*out_alert| to an
+ * alert to emit. */
+enum ssl_open_record_t tls_open_record(SSL *ssl, uint8_t *out_type, CBS *out,
+                                       size_t *out_consumed, uint8_t *out_alert,
+                                       uint8_t *in, size_t in_len);
 
 /* dtls_open_record implements |tls_open_record| for DTLS. It never returns
  * |ssl_open_record_partial| but otherwise behaves analogously. */
-enum ssl_open_record_t dtls_open_record(
-    SSL *ssl, uint8_t *out_type, uint8_t *out, size_t *out_len,
-    size_t *out_consumed, uint8_t *out_alert, size_t max_out, const uint8_t *in,
-    size_t in_len);
+enum ssl_open_record_t dtls_open_record(SSL *ssl, uint8_t *out_type, CBS *out,
+                                        size_t *out_consumed,
+                                        uint8_t *out_alert, uint8_t *in,
+                                        size_t in_len);
 
-/* ssl_seal_prefix_len returns the length of the prefix before the ciphertext
- * when sealing a record with |ssl|. Note that this value may differ from
- * |ssl_record_prefix_len| when TLS 1.0 CBC record-splitting is enabled. Sealing
- * a small record may also result in a smaller output than this value.
+/* ssl_seal_align_prefix_len returns the length of the prefix before the start
+ * of the bulk of the ciphertext when sealing a record with |ssl|. Callers may
+ * use this to align buffers.
  *
- * TODO(davidben): Expose this as part of public API once the high-level
- * buffer-free APIs are available. */
-size_t ssl_seal_prefix_len(const SSL *ssl);
-
-/* ssl_max_seal_overhead returns the maximum overhead of sealing a record with
- * |ssl|. This includes |ssl_seal_prefix_len|.
+ * Note when TLS 1.0 CBC record-splitting is enabled, this includes the one byte
+ * record and is the offset into second record's ciphertext. Thus sealing a
+ * small record may result in a smaller output than this value.
  *
- * TODO(davidben): Expose this as part of public API once the high-level
- * buffer-free APIs are available. */
-size_t ssl_max_seal_overhead(const SSL *ssl);
+ * TODO(davidben): Is this alignment valuable? Record-splitting makes this a
+ * mess. */
+size_t ssl_seal_align_prefix_len(const SSL *ssl);
 
 /* tls_seal_record seals a new record of type |type| and body |in| and writes it
  * to |out|. At most |max_out| bytes will be written. It returns one on success
  * and zero on error. If enabled, |tls_seal_record| implements TLS 1.0 CBC 1/n-1
  * record splitting and may write two records concatenated.
  *
- * For a large record, the ciphertext will begin |ssl_seal_prefix_len| bytes
- * into out. Aligning |out| appropriately may improve performance. It writes at
- * most |in_len| + |ssl_max_seal_overhead| bytes to |out|.
+ * For a large record, the bulk of the ciphertext will begin
+ * |ssl_seal_align_prefix_len| bytes into out. Aligning |out| appropriately may
+ * improve performance. It writes at most |in_len| + |SSL_max_seal_overhead|
+ * bytes to |out|.
  *
- * If |in| and |out| alias, |out| + |ssl_seal_prefix_len| must be <= |in|. */
+ * |in| and |out| may not alias. */
 int tls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
                     uint8_t type, const uint8_t *in, size_t in_len);
 
@@ -426,18 +516,39 @@
   dtls1_use_current_epoch,
 };
 
+/* dtls_max_seal_overhead returns the maximum overhead, in bytes, of sealing a
+ * record. */
+size_t dtls_max_seal_overhead(const SSL *ssl, enum dtls1_use_epoch_t use_epoch);
+
+/* dtls_seal_prefix_len returns the number of bytes of prefix to reserve in
+ * front of the plaintext when sealing a record in-place. */
+size_t dtls_seal_prefix_len(const SSL *ssl, enum dtls1_use_epoch_t use_epoch);
+
 /* dtls_seal_record implements |tls_seal_record| for DTLS. |use_epoch| selects
- * which epoch's cipher state to use. */
+ * which epoch's cipher state to use. Unlike |tls_seal_record|, |in| and |out|
+ * may alias but, if they do, |in| must be exactly |dtls_seal_prefix_len| bytes
+ * ahead of |out|. */
 int dtls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
                      uint8_t type, const uint8_t *in, size_t in_len,
                      enum dtls1_use_epoch_t use_epoch);
 
+/* ssl_process_alert processes |in| as an alert and updates |ssl|'s shutdown
+ * state. It returns one of |ssl_open_record_discard|, |ssl_open_record_error|,
+ * |ssl_open_record_close_notify|, or |ssl_open_record_fatal_alert| as
+ * appropriate. */
+enum ssl_open_record_t ssl_process_alert(SSL *ssl, uint8_t *out_alert,
+                                         const uint8_t *in, size_t in_len);
+
 
 /* Private key operations. */
 
 /* ssl_has_private_key returns one if |ssl| has a private key
  * configured and zero otherwise. */
-int ssl_has_private_key(SSL *ssl);
+int ssl_has_private_key(const SSL *ssl);
+
+/* ssl_is_ecdsa_key_type returns one if |type| is an ECDSA key type and zero
+ * otherwise. */
+int ssl_is_ecdsa_key_type(int type);
 
 /* ssl_private_key_* call the corresponding function on the
  * |SSL_PRIVATE_KEY_METHOD| for |ssl|, if configured. Otherwise, they implement
@@ -448,22 +559,34 @@
 size_t ssl_private_key_max_signature_len(SSL *ssl);
 
 enum ssl_private_key_result_t ssl_private_key_sign(
-    SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out, const EVP_MD *md,
-    const uint8_t *in, size_t in_len);
-
-enum ssl_private_key_result_t ssl_private_key_sign_complete(
-    SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out);
+    SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
+    uint16_t signature_algorithm, const uint8_t *in, size_t in_len);
 
 enum ssl_private_key_result_t ssl_private_key_decrypt(
     SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
     const uint8_t *in, size_t in_len);
 
-enum ssl_private_key_result_t ssl_private_key_decrypt_complete(
-    SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out);
+enum ssl_private_key_result_t ssl_private_key_complete(SSL *ssl, uint8_t *out,
+                                                       size_t *out_len,
+                                                       size_t max_out);
+
+/* ssl_private_key_supports_signature_algorithm returns one if |ssl|'s private
+ * key supports |signature_algorithm| and zero otherwise. */
+int ssl_private_key_supports_signature_algorithm(SSL *ssl,
+                                                 uint16_t signature_algorithm);
+
+/* ssl_public_key_verify verifies that the |signature| is valid for the public
+ * key |pkey| and input |in|, using the |signature_algorithm| specified. */
+int ssl_public_key_verify(
+    SSL *ssl, const uint8_t *signature, size_t signature_len,
+    uint16_t signature_algorithm, EVP_PKEY *pkey,
+    const uint8_t *in, size_t in_len);
 
 
 /* Custom extensions */
 
+typedef struct ssl_handshake_st SSL_HANDSHAKE;
+
 /* ssl_custom_extension (a.k.a. SSL_CUSTOM_EXTENSION) is a structure that
  * contains information about custom-extension callbacks. */
 struct ssl_custom_extension {
@@ -477,82 +600,80 @@
 
 void SSL_CUSTOM_EXTENSION_free(SSL_CUSTOM_EXTENSION *custom_extension);
 
-int custom_ext_add_clienthello(SSL *ssl, CBB *extensions);
-int custom_ext_parse_serverhello(SSL *ssl, int *out_alert, uint16_t value,
-                                 const CBS *extension);
-int custom_ext_parse_clienthello(SSL *ssl, int *out_alert, uint16_t value,
-                                 const CBS *extension);
-int custom_ext_add_serverhello(SSL *ssl, CBB *extensions);
+int custom_ext_add_clienthello(SSL_HANDSHAKE *hs, CBB *extensions);
+int custom_ext_parse_serverhello(SSL_HANDSHAKE *hs, int *out_alert,
+                                 uint16_t value, const CBS *extension);
+int custom_ext_parse_clienthello(SSL_HANDSHAKE *hs, int *out_alert,
+                                 uint16_t value, const CBS *extension);
+int custom_ext_add_serverhello(SSL_HANDSHAKE *hs, CBB *extensions);
 
 
-/* Handshake hash.
- *
- * The TLS handshake maintains a transcript of all handshake messages. At
- * various points in the protocol, this is either a handshake buffer, a rolling
- * hash (selected by cipher suite) or both. */
+/* ECDH groups. */
 
-/* ssl3_init_handshake_buffer initializes the handshake buffer and resets the
- * handshake hash. It returns one success and zero on failure. */
-int ssl3_init_handshake_buffer(SSL *ssl);
-
-/* ssl3_init_handshake_hash initializes the handshake hash based on the pending
- * cipher and the contents of the handshake buffer. Subsequent calls to
- * |ssl3_update_handshake_hash| will update the rolling hash. It returns one on
- * success and zero on failure. It is an error to call this function after the
- * handshake buffer is released. */
-int ssl3_init_handshake_hash(SSL *ssl);
-
-/* ssl3_free_handshake_buffer releases the handshake buffer. Subsequent calls
- * to |ssl3_update_handshake_hash| will not update the handshake buffer. */
-void ssl3_free_handshake_buffer(SSL *ssl);
-
-/* ssl3_free_handshake_hash releases the handshake hash. */
-void ssl3_free_handshake_hash(SSL *ssl);
-
-/* ssl3_update_handshake_hash adds |in| to the handshake buffer and handshake
- * hash, whichever is enabled. It returns one on success and zero on failure. */
-int ssl3_update_handshake_hash(SSL *ssl, const uint8_t *in, size_t in_len);
-
-
-/* ECDH curves. */
-
-#define SSL_CURVE_SECP256R1 23
-#define SSL_CURVE_SECP384R1 24
-#define SSL_CURVE_SECP521R1 25
-#define SSL_CURVE_ECDH_X25519 29
+typedef struct ssl_ecdh_ctx_st SSL_ECDH_CTX;
 
 /* An SSL_ECDH_METHOD is an implementation of ECDH-like key exchanges for
  * TLS. */
-struct ssl_ecdh_method_st {
+typedef struct ssl_ecdh_method_st {
   int nid;
-  uint16_t curve_id;
+  uint16_t group_id;
   const char name[8];
 
   /* cleanup releases state in |ctx|. */
   void (*cleanup)(SSL_ECDH_CTX *ctx);
 
-  /* generate_keypair generates a keypair and writes the public value to
+  /* offer generates a keypair and writes the public value to
    * |out_public_key|. It returns one on success and zero on error. */
-  int (*generate_keypair)(SSL_ECDH_CTX *ctx, CBB *out_public_key);
+  int (*offer)(SSL_ECDH_CTX *ctx, CBB *out_public_key);
 
-  /* compute_secret performs a key exchange against |peer_key| and, on
-   * success, returns one and sets |*out_secret| and |*out_secret_len| to
-   * a newly-allocated buffer containing the shared secret. The caller must
-   * release this buffer with |OPENSSL_free|. Otherwise, it returns zero and
-   * sets |*out_alert| to an alert to send to the peer. */
-  int (*compute_secret)(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
-                        size_t *out_secret_len, uint8_t *out_alert,
-                        const uint8_t *peer_key, size_t peer_key_len);
-} /* SSL_ECDH_METHOD */;
+  /* accept performs a key exchange against the |peer_key| generated by |offer|.
+   * On success, it returns one, writes the public value to |out_public_key|,
+   * and sets |*out_secret| and |*out_secret_len| to a newly-allocated buffer
+   * containing the shared secret. The caller must release this buffer with
+   * |OPENSSL_free|. On failure, it returns zero and sets |*out_alert| to an
+   * alert to send to the peer. */
+  int (*accept)(SSL_ECDH_CTX *ctx, CBB *out_public_key, uint8_t **out_secret,
+                size_t *out_secret_len, uint8_t *out_alert,
+                const uint8_t *peer_key, size_t peer_key_len);
 
-/* ssl_nid_to_curve_id looks up the curve corresponding to |nid|. On success, it
- * sets |*out_curve_id| to the curve ID and returns one. Otherwise, it returns
+  /* finish performs a key exchange against the |peer_key| generated by
+   * |accept|. On success, it returns one and sets |*out_secret| and
+   * |*out_secret_len| to a newly-allocated buffer containing the shared
+   * secret. The caller must release this buffer with |OPENSSL_free|. On
+   * failure, it returns zero and sets |*out_alert| to an alert to send to the
+   * peer. */
+  int (*finish)(SSL_ECDH_CTX *ctx, uint8_t **out_secret, size_t *out_secret_len,
+                uint8_t *out_alert, const uint8_t *peer_key,
+                size_t peer_key_len);
+
+  /* get_key initializes |out| with a length-prefixed key from |cbs|. It returns
+   * one on success and zero on error. */
+  int (*get_key)(CBS *cbs, CBS *out);
+
+  /* add_key initializes |out_contents| to receive a key. Typically it will then
+   * be passed to |offer| or |accept|. It returns one on success and zero on
+   * error. */
+  int (*add_key)(CBB *cbb, CBB *out_contents);
+} SSL_ECDH_METHOD;
+
+struct ssl_ecdh_ctx_st {
+  const SSL_ECDH_METHOD *method;
+  void *data;
+};
+
+/* ssl_nid_to_group_id looks up the group corresponding to |nid|. On success, it
+ * sets |*out_group_id| to the group ID and returns one. Otherwise, it returns
  * zero. */
-int ssl_nid_to_curve_id(uint16_t *out_curve_id, int nid);
+int ssl_nid_to_group_id(uint16_t *out_group_id, int nid);
 
-/* SSL_ECDH_CTX_init sets up |ctx| for use with curve |curve_id|. It returns one
+/* ssl_name_to_group_id looks up the group corresponding to the |name| string
+ * of length |len|. On success, it sets |*out_group_id| to the group ID and
+ * returns one. Otherwise, it returns zero. */
+int ssl_name_to_group_id(uint16_t *out_group_id, const char *name, size_t len);
+
+/* SSL_ECDH_CTX_init sets up |ctx| for use with curve |group_id|. It returns one
  * on success and zero on error. */
-int SSL_ECDH_CTX_init(SSL_ECDH_CTX *ctx, uint16_t curve_id);
+int SSL_ECDH_CTX_init(SSL_ECDH_CTX *ctx, uint16_t group_id);
 
 /* SSL_ECDH_CTX_init_for_dhe sets up |ctx| for use with legacy DHE-based ciphers
  * where the server specifies a group. It takes ownership of |params|. */
@@ -562,12 +683,67 @@
  * call it in the zero state. */
 void SSL_ECDH_CTX_cleanup(SSL_ECDH_CTX *ctx);
 
-/* The following functions call the corresponding method of
- * |SSL_ECDH_METHOD|. */
-int SSL_ECDH_CTX_generate_keypair(SSL_ECDH_CTX *ctx, CBB *out_public_key);
-int SSL_ECDH_CTX_compute_secret(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
-                                size_t *out_secret_len, uint8_t *out_alert,
-                                const uint8_t *peer_key, size_t peer_key_len);
+/* SSL_ECDH_CTX_get_id returns the group ID for |ctx|. */
+uint16_t SSL_ECDH_CTX_get_id(const SSL_ECDH_CTX *ctx);
+
+/* SSL_ECDH_CTX_get_key calls the |get_key| method of |SSL_ECDH_METHOD|. */
+int SSL_ECDH_CTX_get_key(SSL_ECDH_CTX *ctx, CBS *cbs, CBS *out);
+
+/* SSL_ECDH_CTX_add_key calls the |add_key| method of |SSL_ECDH_METHOD|. */
+int SSL_ECDH_CTX_add_key(SSL_ECDH_CTX *ctx, CBB *cbb, CBB *out_contents);
+
+/* SSL_ECDH_CTX_offer calls the |offer| method of |SSL_ECDH_METHOD|. */
+int SSL_ECDH_CTX_offer(SSL_ECDH_CTX *ctx, CBB *out_public_key);
+
+/* SSL_ECDH_CTX_accept calls the |accept| method of |SSL_ECDH_METHOD|. */
+int SSL_ECDH_CTX_accept(SSL_ECDH_CTX *ctx, CBB *out_public_key,
+                        uint8_t **out_secret, size_t *out_secret_len,
+                        uint8_t *out_alert, const uint8_t *peer_key,
+                        size_t peer_key_len);
+
+/* SSL_ECDH_CTX_finish the |finish| method of |SSL_ECDH_METHOD|. */
+int SSL_ECDH_CTX_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
+                        size_t *out_secret_len, uint8_t *out_alert,
+                        const uint8_t *peer_key, size_t peer_key_len);
+
+/* Handshake messages. */
+
+/* SSL_MAX_HANDSHAKE_FLIGHT is the number of messages, including
+ * ChangeCipherSpec, in the longest handshake flight. Currently this is the
+ * client's second leg in a full handshake when client certificates, NPN, and
+ * Channel ID, are all enabled. */
+#define SSL_MAX_HANDSHAKE_FLIGHT 7
+
+/* ssl_max_handshake_message_len returns the maximum number of bytes permitted
+ * in a handshake message for |ssl|. */
+size_t ssl_max_handshake_message_len(const SSL *ssl);
+
+/* dtls_clear_incoming_messages releases all buffered incoming messages. */
+void dtls_clear_incoming_messages(SSL *ssl);
+
+/* dtls_has_incoming_messages returns one if there are buffered incoming
+ * messages ahead of the current message and zero otherwise. */
+int dtls_has_incoming_messages(const SSL *ssl);
+
+typedef struct dtls_outgoing_message_st {
+  uint8_t *data;
+  uint32_t len;
+  uint16_t epoch;
+  char is_ccs;
+} DTLS_OUTGOING_MESSAGE;
+
+/* dtls_clear_outgoing_messages releases all buffered outgoing messages. */
+void dtls_clear_outgoing_messages(SSL *ssl);
+
+
+/* Callbacks. */
+
+/* ssl_do_info_callback calls |ssl|'s info callback, if set. */
+void ssl_do_info_callback(const SSL *ssl, int type, int value);
+
+/* ssl_do_msg_callback calls |ssl|'s message callback, if set. */
+void ssl_do_msg_callback(SSL *ssl, int is_write, int content_type,
+                         const void *buf, size_t len);
 
 
 /* Transport buffers. */
@@ -625,169 +801,552 @@
 void ssl_write_buffer_clear(SSL *ssl);
 
 
+/* Certificate functions. */
+
+/* ssl_has_certificate returns one if a certificate and private key are
+ * configured and zero otherwise. */
+int ssl_has_certificate(const SSL *ssl);
+
+/* ssl_parse_cert_chain parses a certificate list from |cbs| in the format used
+ * by a TLS Certificate message. On success, it returns a newly-allocated
+ * |CRYPTO_BUFFER| list and advances |cbs|. Otherwise, it returns NULL and sets
+ * |*out_alert| to an alert to send to the peer.
+ *
+ * If the list is non-empty then |*out_pubkey| will be set to a freshly
+ * allocated public-key from the leaf certificate.
+ *
+ * If the list is non-empty and |out_leaf_sha256| is non-NULL, it writes the
+ * SHA-256 hash of the leaf to |out_leaf_sha256|. */
+STACK_OF(CRYPTO_BUFFER) *ssl_parse_cert_chain(uint8_t *out_alert,
+                                              EVP_PKEY **out_pubkey,
+                                              uint8_t *out_leaf_sha256,
+                                              CBS *cbs,
+                                              CRYPTO_BUFFER_POOL *pool);
+
+/* ssl_add_cert_chain adds |ssl|'s certificate chain to |cbb| in the format used
+ * by a TLS Certificate message. If there is no certificate chain, it emits an
+ * empty certificate list. It returns one on success and zero on error. */
+int ssl_add_cert_chain(SSL *ssl, CBB *cbb);
+
+/* ssl_cert_check_digital_signature_key_usage parses the DER-encoded, X.509
+ * certificate in |in| and returns one if doesn't specify a key usage or, if it
+ * does, if it includes digitalSignature. Otherwise it pushes to the error
+ * queue and returns zero. */
+int ssl_cert_check_digital_signature_key_usage(const CBS *in);
+
+/* ssl_cert_parse_pubkey extracts the public key from the DER-encoded, X.509
+ * certificate in |in|. It returns an allocated |EVP_PKEY| or else returns NULL
+ * and pushes to the error queue. */
+EVP_PKEY *ssl_cert_parse_pubkey(const CBS *in);
+
+/* ssl_parse_client_CA_list parses a CA list from |cbs| in the format used by a
+ * TLS CertificateRequest message. On success, it returns a newly-allocated
+ * |CRYPTO_BUFFER| list and advances |cbs|. Otherwise, it returns NULL and sets
+ * |*out_alert| to an alert to send to the peer. */
+STACK_OF(CRYPTO_BUFFER) *
+    ssl_parse_client_CA_list(SSL *ssl, uint8_t *out_alert, CBS *cbs);
+
+/* ssl_add_client_CA_list adds the configured CA list to |cbb| in the format
+ * used by a TLS CertificateRequest message. It returns one on success and zero
+ * on error. */
+int ssl_add_client_CA_list(SSL *ssl, CBB *cbb);
+
+/* ssl_check_leaf_certificate returns one if |pkey| and |leaf| are suitable as
+ * a server's leaf certificate for |hs|. Otherwise, it returns zero and pushes
+ * an error on the error queue. */
+int ssl_check_leaf_certificate(SSL_HANDSHAKE *hs, EVP_PKEY *pkey,
+                               const CRYPTO_BUFFER *leaf);
+
+
+/* TLS 1.3 key derivation. */
+
+/* tls13_init_key_schedule initializes the handshake hash and key derivation
+ * state. The cipher suite and PRF hash must have been selected at this point.
+ * It returns one on success and zero on error. */
+int tls13_init_key_schedule(SSL_HANDSHAKE *hs);
+
+/* tls13_init_early_key_schedule initializes the handshake hash and key
+ * derivation state from the resumption secret to derive the early secrets. It
+ * returns one on success and zero on error. */
+int tls13_init_early_key_schedule(SSL_HANDSHAKE *hs);
+
+/* tls13_advance_key_schedule incorporates |in| into the key schedule with
+ * HKDF-Extract. It returns one on success and zero on error. */
+int tls13_advance_key_schedule(SSL_HANDSHAKE *hs, const uint8_t *in,
+                               size_t len);
+
+/* tls13_set_traffic_key sets the read or write traffic keys to
+ * |traffic_secret|. It returns one on success and zero on error. */
+int tls13_set_traffic_key(SSL *ssl, enum evp_aead_direction_t direction,
+                          const uint8_t *traffic_secret,
+                          size_t traffic_secret_len);
+
+/* tls13_derive_early_secrets derives the early traffic secret. It returns one
+ * on success and zero on error. */
+int tls13_derive_early_secrets(SSL_HANDSHAKE *hs);
+
+/* tls13_derive_handshake_secrets derives the handshake traffic secret. It
+ * returns one on success and zero on error. */
+int tls13_derive_handshake_secrets(SSL_HANDSHAKE *hs);
+
+/* tls13_rotate_traffic_key derives the next read or write traffic secret. It
+ * returns one on success and zero on error. */
+int tls13_rotate_traffic_key(SSL *ssl, enum evp_aead_direction_t direction);
+
+/* tls13_derive_application_secrets derives the initial application data traffic
+ * and exporter secrets based on the handshake transcripts and |master_secret|.
+ * It returns one on success and zero on error. */
+int tls13_derive_application_secrets(SSL_HANDSHAKE *hs);
+
+/* tls13_derive_resumption_secret derives the |resumption_secret|. */
+int tls13_derive_resumption_secret(SSL_HANDSHAKE *hs);
+
+/* tls13_export_keying_material provides an exporter interface to use the
+ * |exporter_secret|. */
+int tls13_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len,
+                                 const char *label, size_t label_len,
+                                 const uint8_t *context, size_t context_len,
+                                 int use_context);
+
+/* tls13_finished_mac calculates the MAC of the handshake transcript to verify
+ * the integrity of the Finished message, and stores the result in |out| and
+ * length in |out_len|. |is_server| is 1 if this is for the Server Finished and
+ * 0 for the Client Finished. */
+int tls13_finished_mac(SSL_HANDSHAKE *hs, uint8_t *out,
+                       size_t *out_len, int is_server);
+
+/* tls13_write_psk_binder calculates the PSK binder value and replaces the last
+ * bytes of |msg| with the resulting value. It returns 1 on success, and 0 on
+ * failure. */
+int tls13_write_psk_binder(SSL_HANDSHAKE *hs, uint8_t *msg, size_t len);
+
+/* tls13_verify_psk_binder verifies that the handshake transcript, truncated
+ * up to the binders has a valid signature using the value of |session|'s
+ * resumption secret. It returns 1 on success, and 0 on failure. */
+int tls13_verify_psk_binder(SSL_HANDSHAKE *hs, SSL_SESSION *session,
+                            CBS *binders);
+
+
+/* Handshake functions. */
+
+enum ssl_hs_wait_t {
+  ssl_hs_error,
+  ssl_hs_ok,
+  ssl_hs_read_message,
+  ssl_hs_flush,
+  ssl_hs_flush_and_read_message,
+  ssl_hs_x509_lookup,
+  ssl_hs_channel_id_lookup,
+  ssl_hs_private_key_operation,
+  ssl_hs_pending_ticket,
+  ssl_hs_read_end_of_early_data,
+};
+
+struct ssl_handshake_st {
+  /* ssl is a non-owning pointer to the parent |SSL| object. */
+  SSL *ssl;
+
+  /* do_tls13_handshake runs the TLS 1.3 handshake. On completion, it returns
+   * |ssl_hs_ok|. Otherwise, it returns a value corresponding to what operation
+   * is needed to progress. */
+  enum ssl_hs_wait_t (*do_tls13_handshake)(SSL_HANDSHAKE *hs);
+
+  /* wait contains the operation |do_tls13_handshake| is currently blocking on
+   * or |ssl_hs_ok| if none. */
+  enum ssl_hs_wait_t wait;
+
+  /* state contains one of the SSL3_ST_* values. */
+  int state;
+
+  /* next_state is used when SSL_ST_FLUSH_DATA is entered */
+  int next_state;
+
+  /* tls13_state is the internal state for the TLS 1.3 handshake. Its values
+   * depend on |do_tls13_handshake| but the starting state is always zero. */
+  int tls13_state;
+
+  size_t hash_len;
+  uint8_t secret[EVP_MAX_MD_SIZE];
+  uint8_t early_traffic_secret[EVP_MAX_MD_SIZE];
+  uint8_t client_handshake_secret[EVP_MAX_MD_SIZE];
+  uint8_t server_handshake_secret[EVP_MAX_MD_SIZE];
+  uint8_t client_traffic_secret_0[EVP_MAX_MD_SIZE];
+  uint8_t server_traffic_secret_0[EVP_MAX_MD_SIZE];
+  uint8_t expected_client_finished[EVP_MAX_MD_SIZE];
+
+  union {
+    /* sent is a bitset where the bits correspond to elements of kExtensions
+     * in t1_lib.c. Each bit is set if that extension was sent in a
+     * ClientHello. It's not used by servers. */
+    uint32_t sent;
+    /* received is a bitset, like |sent|, but is used by servers to record
+     * which extensions were received from a client. */
+    uint32_t received;
+  } extensions;
+
+  union {
+    /* sent is a bitset where the bits correspond to elements of
+     * |client_custom_extensions| in the |SSL_CTX|. Each bit is set if that
+     * extension was sent in a ClientHello. It's not used by servers. */
+    uint16_t sent;
+    /* received is a bitset, like |sent|, but is used by servers to record
+     * which custom extensions were received from a client. The bits here
+     * correspond to |server_custom_extensions|. */
+    uint16_t received;
+  } custom_extensions;
+
+  /* retry_group is the group ID selected by the server in HelloRetryRequest in
+   * TLS 1.3. */
+  uint16_t retry_group;
+
+  /* ecdh_ctx is the current ECDH instance. */
+  SSL_ECDH_CTX ecdh_ctx;
+
+  /* transcript is the current handshake transcript. */
+  SSL_TRANSCRIPT transcript;
+
+  /* cookie is the value of the cookie received from the server, if any. */
+  uint8_t *cookie;
+  size_t cookie_len;
+
+  /* key_share_bytes is the value of the previously sent KeyShare extension by
+   * the client in TLS 1.3. */
+  uint8_t *key_share_bytes;
+  size_t key_share_bytes_len;
+
+  /* public_key, for servers, is the key share to be sent to the client in TLS
+   * 1.3. */
+  uint8_t *public_key;
+  size_t public_key_len;
+
+  /* peer_sigalgs are the signature algorithms that the peer supports. These are
+   * taken from the contents of the signature algorithms extension for a server
+   * or from the CertificateRequest for a client. */
+  uint16_t *peer_sigalgs;
+  /* num_peer_sigalgs is the number of entries in |peer_sigalgs|. */
+  size_t num_peer_sigalgs;
+
+  /* peer_supported_group_list contains the supported group IDs advertised by
+   * the peer. This is only set on the server's end. The server does not
+   * advertise this extension to the client. */
+  uint16_t *peer_supported_group_list;
+  size_t peer_supported_group_list_len;
+
+  /* peer_key is the peer's ECDH key for a TLS 1.2 client. */
+  uint8_t *peer_key;
+  size_t peer_key_len;
+
+  /* server_params, in TLS 1.2, stores the ServerKeyExchange parameters to be
+   * signed while the signature is being computed. */
+  uint8_t *server_params;
+  size_t server_params_len;
+
+  /* peer_psk_identity_hint, on the client, is the psk_identity_hint sent by the
+   * server when using a TLS 1.2 PSK key exchange. */
+  char *peer_psk_identity_hint;
+
+  /* ca_names, on the client, contains the list of CAs received in a
+   * CertificateRequest message. */
+  STACK_OF(CRYPTO_BUFFER) *ca_names;
+
+  /* cached_x509_ca_names contains a cache of parsed versions of the elements
+   * of |ca_names|. */
+  STACK_OF(X509_NAME) *cached_x509_ca_names;
+
+  /* certificate_types, on the client, contains the set of certificate types
+   * received in a CertificateRequest message. */
+  uint8_t *certificate_types;
+  size_t num_certificate_types;
+
+  /* hostname, on the server, is the value of the SNI extension. */
+  char *hostname;
+
+  /* peer_pubkey is the public key parsed from the peer's leaf certificate. */
+  EVP_PKEY *peer_pubkey;
+
+  /* new_session is the new mutable session being established by the current
+   * handshake. It should not be cached. */
+  SSL_SESSION *new_session;
+
+  /* new_cipher is the cipher being negotiated in this handshake. */
+  const SSL_CIPHER *new_cipher;
+
+  /* key_block is the record-layer key block for TLS 1.2 and earlier. */
+  uint8_t *key_block;
+  uint8_t key_block_len;
+
+  /* scts_requested is one if the SCT extension is in the ClientHello. */
+  unsigned scts_requested:1;
+
+  /* needs_psk_binder if the ClientHello has a placeholder PSK binder to be
+   * filled in. */
+  unsigned needs_psk_binder:1;
+
+  unsigned received_hello_retry_request:1;
+
+  /* accept_psk_mode stores whether the client's PSK mode is compatible with our
+   * preferences. */
+  unsigned accept_psk_mode:1;
+
+  /* cert_request is one if a client certificate was requested and zero
+   * otherwise. */
+  unsigned cert_request:1;
+
+  /* certificate_status_expected is one if OCSP stapling was negotiated and the
+   * server is expected to send a CertificateStatus message. (This is used on
+   * both the client and server sides.) */
+  unsigned certificate_status_expected:1;
+
+  /* ocsp_stapling_requested is one if a client requested OCSP stapling. */
+  unsigned ocsp_stapling_requested:1;
+
+  /* should_ack_sni is used by a server and indicates that the SNI extension
+   * should be echoed in the ServerHello. */
+  unsigned should_ack_sni:1;
+
+  /* in_false_start is one if there is a pending client handshake in False
+   * Start. The client may write data at this point. */
+  unsigned in_false_start:1;
+
+  /* early_data_offered is one if the client sent the early_data extension. */
+  unsigned early_data_offered:1;
+
+  /* can_early_read is one if application data may be read at this point in the
+   * handshake. */
+  unsigned can_early_read:1;
+
+  /* can_early_write is one if application data may be written at this point in
+   * the handshake. */
+  unsigned can_early_write:1;
+
+  /* next_proto_neg_seen is one of NPN was negotiated. */
+  unsigned next_proto_neg_seen:1;
+
+  /* ticket_expected is one if a TLS 1.2 NewSessionTicket message is to be sent
+   * or received. */
+  unsigned ticket_expected:1;
+
+  /* v2_clienthello is one if we received a V2ClientHello. */
+  unsigned v2_clienthello:1;
+
+  /* extended_master_secret is one if the extended master secret extension is
+   * negotiated in this handshake. */
+  unsigned extended_master_secret:1;
+
+  /* client_version is the value sent or received in the ClientHello version. */
+  uint16_t client_version;
+} /* SSL_HANDSHAKE */;
+
+SSL_HANDSHAKE *ssl_handshake_new(SSL *ssl);
+
+/* ssl_handshake_free releases all memory associated with |hs|. */
+void ssl_handshake_free(SSL_HANDSHAKE *hs);
+
+/* ssl_check_message_type checks if the current message has type |type|. If so
+ * it returns one. Otherwise, it sends an alert and returns zero. */
+int ssl_check_message_type(SSL *ssl, int type);
+
+/* tls13_handshake runs the TLS 1.3 handshake. It returns one on success and <=
+ * 0 on error. It sets |out_early_return| to one if we've completed the
+ * handshake early. */
+int tls13_handshake(SSL_HANDSHAKE *hs, int *out_early_return);
+
+/* The following are implementations of |do_tls13_handshake| for the client and
+ * server. */
+enum ssl_hs_wait_t tls13_client_handshake(SSL_HANDSHAKE *hs);
+enum ssl_hs_wait_t tls13_server_handshake(SSL_HANDSHAKE *hs);
+
+/* tls13_post_handshake processes a post-handshake message. It returns one on
+ * success and zero on failure. */
+int tls13_post_handshake(SSL *ssl);
+
+int tls13_process_certificate(SSL_HANDSHAKE *hs, int allow_anonymous);
+int tls13_process_certificate_verify(SSL_HANDSHAKE *hs);
+
+/* tls13_process_finished processes the current message as a Finished message
+ * from the peer. If |use_saved_value| is one, the verify_data is compared
+ * against |hs->expected_client_finished| rather than computed fresh. */
+int tls13_process_finished(SSL_HANDSHAKE *hs, int use_saved_value);
+
+int tls13_add_certificate(SSL_HANDSHAKE *hs);
+enum ssl_private_key_result_t tls13_add_certificate_verify(SSL_HANDSHAKE *hs,
+                                                           int is_first_run);
+int tls13_add_finished(SSL_HANDSHAKE *hs);
+int tls13_process_new_session_ticket(SSL *ssl);
+
+int ssl_ext_key_share_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t **out_secret,
+                                        size_t *out_secret_len,
+                                        uint8_t *out_alert, CBS *contents);
+int ssl_ext_key_share_parse_clienthello(SSL_HANDSHAKE *hs, int *out_found,
+                                        uint8_t **out_secret,
+                                        size_t *out_secret_len,
+                                        uint8_t *out_alert, CBS *contents);
+int ssl_ext_key_share_add_serverhello(SSL_HANDSHAKE *hs, CBB *out);
+
+int ssl_ext_pre_shared_key_parse_serverhello(SSL_HANDSHAKE *hs,
+                                             uint8_t *out_alert, CBS *contents);
+int ssl_ext_pre_shared_key_parse_clienthello(
+    SSL_HANDSHAKE *hs, CBS *out_ticket, CBS *out_binders,
+    uint32_t *out_obfuscated_ticket_age, uint8_t *out_alert, CBS *contents);
+int ssl_ext_pre_shared_key_add_serverhello(SSL_HANDSHAKE *hs, CBB *out);
+
+/* ssl_is_sct_list_valid does a shallow parse of the SCT list in |contents| and
+ * returns one iff it's valid. */
+int ssl_is_sct_list_valid(const CBS *contents);
+
+int ssl_write_client_hello(SSL_HANDSHAKE *hs);
+
+/* ssl_clear_tls13_state releases client state only needed for TLS 1.3. It
+ * should be called once the version is known to be TLS 1.2 or earlier. */
+void ssl_clear_tls13_state(SSL_HANDSHAKE *hs);
+
+enum ssl_cert_verify_context_t {
+  ssl_cert_verify_server,
+  ssl_cert_verify_client,
+  ssl_cert_verify_channel_id,
+};
+
+/* tls13_get_cert_verify_signature_input generates the message to be signed for
+ * TLS 1.3's CertificateVerify message. |cert_verify_context| determines the
+ * type of signature. It sets |*out| and |*out_len| to a newly allocated buffer
+ * containing the result. The caller must free it with |OPENSSL_free| to release
+ * it. This function returns one on success and zero on failure. */
+int tls13_get_cert_verify_signature_input(
+    SSL_HANDSHAKE *hs, uint8_t **out, size_t *out_len,
+    enum ssl_cert_verify_context_t cert_verify_context);
+
+/* ssl_negotiate_alpn negotiates the ALPN extension, if applicable. It returns
+ * one on successful negotiation or if nothing was negotiated. It returns zero
+ * and sets |*out_alert| to an alert on error. */
+int ssl_negotiate_alpn(SSL_HANDSHAKE *hs, uint8_t *out_alert,
+                       const SSL_CLIENT_HELLO *client_hello);
+
+typedef struct {
+  uint16_t type;
+  int *out_present;
+  CBS *out_data;
+} SSL_EXTENSION_TYPE;
+
+/* ssl_parse_extensions parses a TLS extensions block out of |cbs| and advances
+ * it. It writes the parsed extensions to pointers denoted by |ext_types|. On
+ * success, it fills in the |out_present| and |out_data| fields and returns one.
+ * Otherwise, it sets |*out_alert| to an alert to send and returns zero. Unknown
+ * extensions are rejected unless |ignore_unknown| is 1. */
+int ssl_parse_extensions(const CBS *cbs, uint8_t *out_alert,
+                         const SSL_EXTENSION_TYPE *ext_types,
+                         size_t num_ext_types, int ignore_unknown);
+
+
+/* SSLKEYLOGFILE functions. */
+
+/* ssl_log_secret logs |secret| with label |label|, if logging is enabled for
+ * |ssl|. It returns one on success and zero on failure. */
+int ssl_log_secret(const SSL *ssl, const char *label, const uint8_t *secret,
+                   size_t secret_len);
+
+
+/* ClientHello functions. */
+
+int ssl_client_hello_init(SSL *ssl, SSL_CLIENT_HELLO *out, const uint8_t *in,
+                          size_t in_len);
+
+int ssl_client_hello_get_extension(const SSL_CLIENT_HELLO *client_hello,
+                                   CBS *out, uint16_t extension_type);
+
+int ssl_client_cipher_list_contains_cipher(const SSL_CLIENT_HELLO *client_hello,
+                                           uint16_t id);
+
+
+/* GREASE. */
+
+enum ssl_grease_index_t {
+  ssl_grease_cipher = 0,
+  ssl_grease_group,
+  ssl_grease_extension1,
+  ssl_grease_extension2,
+  ssl_grease_version,
+  ssl_grease_ticket_extension,
+};
+
+/* ssl_get_grease_value returns a GREASE value for |ssl|. For a given
+ * connection, the values for each index will be deterministic. This allows the
+ * same ClientHello be sent twice for a HelloRetryRequest or the same group be
+ * advertised in both supported_groups and key_shares. */
+uint16_t ssl_get_grease_value(const SSL *ssl, enum ssl_grease_index_t index);
+
+
+/* Signature algorithms. */
+
+/* tls1_parse_peer_sigalgs parses |sigalgs| as the list of peer signature
+ * algorithms and saves them on |hs|. It returns one on success and zero on
+ * error. */
+int tls1_parse_peer_sigalgs(SSL_HANDSHAKE *hs, const CBS *sigalgs);
+
+/* tls1_choose_signature_algorithm sets |*out| to a signature algorithm for use
+ * with |hs|'s private key based on the peer's preferences and the algorithms
+ * supported. It returns one on success and zero on error. */
+int tls1_choose_signature_algorithm(SSL_HANDSHAKE *hs, uint16_t *out);
+
+/* tls12_get_verify_sigalgs sets |*out| to the signature algorithms acceptable
+ * for the peer signature and returns the length of the list. */
+size_t tls12_get_verify_sigalgs(const SSL *ssl, const uint16_t **out);
+
+/* tls12_check_peer_sigalg checks if |sigalg| is acceptable for the peer
+ * signature. It returns one on success and zero on error, setting |*out_alert|
+ * to an alert to send. */
+int tls12_check_peer_sigalg(SSL *ssl, int *out_alert, uint16_t sigalg);
+
+
 /* Underdocumented functions.
  *
  * Functions below here haven't been touched up and may be underdocumented. */
 
-#define c2l(c, l)                                                            \
-  (l = ((unsigned long)(*((c)++))), l |= (((unsigned long)(*((c)++))) << 8), \
-   l |= (((unsigned long)(*((c)++))) << 16),                                 \
-   l |= (((unsigned long)(*((c)++))) << 24))
-
-/* NOTE - c is not incremented as per c2l */
-#define c2ln(c, l1, l2, n)                       \
-  {                                              \
-    c += n;                                      \
-    l1 = l2 = 0;                                 \
-    switch (n) {                                 \
-      case 8:                                    \
-        l2 = ((unsigned long)(*(--(c)))) << 24;  \
-      case 7:                                    \
-        l2 |= ((unsigned long)(*(--(c)))) << 16; \
-      case 6:                                    \
-        l2 |= ((unsigned long)(*(--(c)))) << 8;  \
-      case 5:                                    \
-        l2 |= ((unsigned long)(*(--(c))));       \
-      case 4:                                    \
-        l1 = ((unsigned long)(*(--(c)))) << 24;  \
-      case 3:                                    \
-        l1 |= ((unsigned long)(*(--(c)))) << 16; \
-      case 2:                                    \
-        l1 |= ((unsigned long)(*(--(c)))) << 8;  \
-      case 1:                                    \
-        l1 |= ((unsigned long)(*(--(c))));       \
-    }                                            \
-  }
-
-#define l2c(l, c)                            \
-  (*((c)++) = (uint8_t)(((l)) & 0xff),       \
-   *((c)++) = (uint8_t)(((l) >> 8) & 0xff),  \
-   *((c)++) = (uint8_t)(((l) >> 16) & 0xff), \
-   *((c)++) = (uint8_t)(((l) >> 24) & 0xff))
-
-#define n2l(c, l)                          \
-  (l = ((unsigned long)(*((c)++))) << 24,  \
-   l |= ((unsigned long)(*((c)++))) << 16, \
-   l |= ((unsigned long)(*((c)++))) << 8, l |= ((unsigned long)(*((c)++))))
-
-#define l2n(l, c)                            \
-  (*((c)++) = (uint8_t)(((l) >> 24) & 0xff), \
-   *((c)++) = (uint8_t)(((l) >> 16) & 0xff), \
-   *((c)++) = (uint8_t)(((l) >> 8) & 0xff),  \
-   *((c)++) = (uint8_t)(((l)) & 0xff))
-
-#define l2n8(l, c)                           \
-  (*((c)++) = (uint8_t)(((l) >> 56) & 0xff), \
-   *((c)++) = (uint8_t)(((l) >> 48) & 0xff), \
-   *((c)++) = (uint8_t)(((l) >> 40) & 0xff), \
-   *((c)++) = (uint8_t)(((l) >> 32) & 0xff), \
-   *((c)++) = (uint8_t)(((l) >> 24) & 0xff), \
-   *((c)++) = (uint8_t)(((l) >> 16) & 0xff), \
-   *((c)++) = (uint8_t)(((l) >> 8) & 0xff),  \
-   *((c)++) = (uint8_t)(((l)) & 0xff))
-
-/* NOTE - c is not incremented as per l2c */
-#define l2cn(l1, l2, c, n)                               \
-  {                                                      \
-    c += n;                                              \
-    switch (n) {                                         \
-      case 8:                                            \
-        *(--(c)) = (uint8_t)(((l2) >> 24) & 0xff); \
-      case 7:                                            \
-        *(--(c)) = (uint8_t)(((l2) >> 16) & 0xff); \
-      case 6:                                            \
-        *(--(c)) = (uint8_t)(((l2) >> 8) & 0xff);  \
-      case 5:                                            \
-        *(--(c)) = (uint8_t)(((l2)) & 0xff);       \
-      case 4:                                            \
-        *(--(c)) = (uint8_t)(((l1) >> 24) & 0xff); \
-      case 3:                                            \
-        *(--(c)) = (uint8_t)(((l1) >> 16) & 0xff); \
-      case 2:                                            \
-        *(--(c)) = (uint8_t)(((l1) >> 8) & 0xff);  \
-      case 1:                                            \
-        *(--(c)) = (uint8_t)(((l1)) & 0xff);       \
-    }                                                    \
-  }
-
-#define n2s(c, s) \
-  ((s = (((unsigned int)(c[0])) << 8) | (((unsigned int)(c[1])))), c += 2)
-
-#define s2n(s, c)                              \
-  ((c[0] = (uint8_t)(((s) >> 8) & 0xff), \
-    c[1] = (uint8_t)(((s)) & 0xff)),     \
-   c += 2)
-
-#define n2l3(c, l)                                                         \
-  ((l = (((unsigned long)(c[0])) << 16) | (((unsigned long)(c[1])) << 8) | \
-        (((unsigned long)(c[2])))),                                        \
-   c += 3)
-
-#define l2n3(l, c)                              \
-  ((c[0] = (uint8_t)(((l) >> 16) & 0xff), \
-    c[1] = (uint8_t)(((l) >> 8) & 0xff),  \
-    c[2] = (uint8_t)(((l)) & 0xff)),      \
-   c += 3)
-
-/* LOCAL STUFF */
-
 #define TLSEXT_CHANNEL_ID_SIZE 128
 
-/* Check if an SSL structure is using DTLS */
-#define SSL_IS_DTLS(ssl) (ssl->method->is_dtls)
-/* See if we need explicit IV */
-#define SSL_USE_EXPLICIT_IV(ssl) \
-  (ssl->enc_method->enc_flags & SSL_ENC_FLAG_EXPLICIT_IV)
-/* See if we use signature algorithms extension and signature algorithm before
- * signatures. */
-#define SSL_USE_SIGALGS(ssl) (ssl->enc_method->enc_flags & SSL_ENC_FLAG_SIGALGS)
-
 /* From RFC4492, used in encoding the curve type in ECParameters */
 #define NAMED_CURVE_TYPE 3
 
-enum ssl_hash_message_t {
-  ssl_dont_hash_message,
-  ssl_hash_message,
-};
-
-/* Structure containing decoded values of signature algorithms extension */
-typedef struct tls_sigalgs_st {
-  uint8_t rsign;
-  uint8_t rhash;
-} TLS_SIGALGS;
-
 typedef struct cert_st {
-  X509 *x509;
   EVP_PKEY *privatekey;
-  /* Chain for this certificate */
-  STACK_OF(X509) *chain;
+
+  /* chain contains the certificate chain, with the leaf at the beginning. The
+   * first element of |chain| may be NULL to indicate that the leaf certificate
+   * has not yet been set.
+   *   If |chain| != NULL -> len(chain) >= 1
+   *   If |chain[0]| == NULL -> len(chain) >= 2.
+   *   |chain[1..]| != NULL */
+  STACK_OF(CRYPTO_BUFFER) *chain;
+
+  /* x509_chain may contain a parsed copy of |chain[1..]|. This is only used as
+   * a cache in order to implement “get0” functions that return a non-owning
+   * pointer to the certificate chain. */
+  STACK_OF(X509) *x509_chain;
+
+  /* x509_leaf may contain a parsed copy of the first element of |chain|. This
+   * is only used as a cache in order to implement “get0” functions that return
+   * a non-owning pointer to the certificate chain. */
+  X509 *x509_leaf;
+
+  /* x509_stash contains the last |X509| object append to the chain. This is a
+   * workaround for some third-party code that continue to use an |X509| object
+   * even after passing ownership with an “add0” function. */
+  X509 *x509_stash;
 
   /* key_method, if non-NULL, is a set of callbacks to call for private key
    * operations. */
   const SSL_PRIVATE_KEY_METHOD *key_method;
 
-  /* For clients the following masks are of *disabled* key and auth algorithms
-   * based on the current configuration.
-   *
-   * TODO(davidben): Remove these. They get checked twice: when sending the
-   * ClientHello and when processing the ServerHello. */
-  uint32_t mask_k;
-  uint32_t mask_a;
+  /* x509_method contains pointers to functions that might deal with |X509|
+   * compatibility, or might be a no-op, depending on the application. */
+  const SSL_X509_METHOD *x509_method;
 
   DH *dh_tmp;
   DH *(*dh_tmp_cb)(SSL *ssl, int is_export, int keysize);
 
-  /* peer_sigalgs are the algorithm/hash pairs that the peer supports. These
-   * are taken from the contents of signature algorithms extension for a server
-   * or from the CertificateRequest for a client. */
-  TLS_SIGALGS *peer_sigalgs;
-  /* peer_sigalgslen is the number of entries in |peer_sigalgs|. */
-  size_t peer_sigalgslen;
-
-  /* digest_nids, if non-NULL, is the set of digests supported by |privatekey|
-   * in decreasing order of preference. */
-  int *digest_nids;
-  size_t num_digest_nids;
+  /* sigalgs, if non-NULL, is the set of signature algorithms supported by
+   * |privatekey| in decreasing order of preference. */
+  uint16_t *sigalgs;
+  size_t num_sigalgs;
 
   /* Certificate setup callback: if set is called whenever a
    * certificate may be required (client or server). the callback
@@ -797,6 +1356,21 @@
    * supported signature algorithms or curves. */
   int (*cert_cb)(SSL *ssl, void *arg);
   void *cert_cb_arg;
+
+  /* Optional X509_STORE for certificate validation. If NULL the parent SSL_CTX
+   * store is used instead. */
+  X509_STORE *verify_store;
+
+  /* Signed certificate timestamp list to be sent to the client, if requested */
+  CRYPTO_BUFFER *signed_cert_timestamp_list;
+
+  /* OCSP response to be sent to the client, if requested. */
+  CRYPTO_BUFFER *ocsp_response;
+
+  /* sid_ctx partitions the session space within a shared session cache or
+   * ticket key. Only sessions with a matching value will be accepted. */
+  uint8_t sid_ctx_length;
+  uint8_t sid_ctx[SSL_MAX_SID_CTX_LENGTH];
 } CERT;
 
 /* SSL_METHOD is a compatibility structure to support the legacy version-locked
@@ -808,71 +1382,337 @@
   /* method is the underlying SSL_PROTOCOL_METHOD that initializes the
    * SSL_CTX. */
   const SSL_PROTOCOL_METHOD *method;
+  /* x509_method contains pointers to functions that might deal with |X509|
+   * compatibility, or might be a no-op, depending on the application. */
+  const SSL_X509_METHOD *x509_method;
 };
 
 /* Used to hold functions for SSLv2 or SSLv3/TLSv1 functions */
 struct ssl_protocol_method_st {
   /* is_dtls is one if the protocol is DTLS and zero otherwise. */
   char is_dtls;
+  /* min_version is the minimum implemented version. */
+  uint16_t min_version;
+  /* max_version is the maximum implemented version. */
+  uint16_t max_version;
+  /* version_from_wire maps |wire_version| to a protocol version. On success, it
+   * sets |*out_version| to the result and returns one. If the version is
+   * unknown, it returns zero. */
+  int (*version_from_wire)(uint16_t *out_version, uint16_t wire_version);
+  /* version_to_wire maps |version| to the wire representation. It is an error
+   * to call it with an invalid version. */
+  uint16_t (*version_to_wire)(uint16_t version);
   int (*ssl_new)(SSL *ssl);
   void (*ssl_free)(SSL *ssl);
-  int (*ssl_accept)(SSL *ssl);
-  int (*ssl_connect)(SSL *ssl);
-  long (*ssl_get_message)(SSL *ssl, int header_state, int body_state,
-                          int msg_type, long max,
-                          enum ssl_hash_message_t hash_message, int *ok);
-  int (*ssl_read_app_data)(SSL *ssl, uint8_t *buf, int len, int peek);
-  int (*ssl_read_change_cipher_spec)(SSL *ssl);
-  void (*ssl_read_close_notify)(SSL *ssl);
-  int (*ssl_write_app_data)(SSL *ssl, const void *buf_, int len);
-  int (*ssl_dispatch_alert)(SSL *ssl);
+  /* ssl_get_message reads the next handshake message. On success, it returns
+   * one and sets |ssl->s3->tmp.message_type|, |ssl->init_msg|, and
+   * |ssl->init_num|. Otherwise, it returns <= 0. */
+  int (*ssl_get_message)(SSL *ssl);
+  /* get_current_message sets |*out| to the current handshake message. This
+   * includes the protocol-specific message header. */
+  void (*get_current_message)(const SSL *ssl, CBS *out);
+  /* release_current_message is called to release the current handshake message.
+   * If |free_buffer| is one, buffers will also be released. */
+  void (*release_current_message)(SSL *ssl, int free_buffer);
+  /* read_app_data reads up to |len| bytes of application data into |buf|. On
+   * success, it returns the number of bytes read. Otherwise, it returns <= 0
+   * and sets |*out_got_handshake| to whether the failure was due to a
+   * post-handshake handshake message. If so, it fills in the current message as
+   * in |ssl_get_message|. */
+  int (*read_app_data)(SSL *ssl, int *out_got_handshake, uint8_t *buf, int len,
+                       int peek);
+  int (*read_change_cipher_spec)(SSL *ssl);
+  void (*read_close_notify)(SSL *ssl);
+  int (*write_app_data)(SSL *ssl, const uint8_t *buf, int len);
+  int (*dispatch_alert)(SSL *ssl);
   /* supports_cipher returns one if |cipher| is supported by this protocol and
    * zero otherwise. */
   int (*supports_cipher)(const SSL_CIPHER *cipher);
-  /* Handshake header length */
-  unsigned int hhlen;
-  /* Set the handshake header */
-  int (*set_handshake_header)(SSL *ssl, int type, unsigned long len);
-  /* Write out handshake message */
-  int (*do_write)(SSL *ssl);
+  /* init_message begins a new handshake message of type |type|. |cbb| is the
+   * root CBB to be passed into |finish_message|. |*body| is set to a child CBB
+   * the caller should write to. It returns one on success and zero on error. */
+  int (*init_message)(SSL *ssl, CBB *cbb, CBB *body, uint8_t type);
+  /* finish_message finishes a handshake message. It sets |*out_msg| to a
+   * newly-allocated buffer with the serialized message. The caller must
+   * release it with |OPENSSL_free| when done. It returns one on success and
+   * zero on error. */
+  int (*finish_message)(SSL *ssl, CBB *cbb, uint8_t **out_msg, size_t *out_len);
+  /* add_message adds a handshake message to the pending flight. It returns one
+   * on success and zero on error. In either case, it takes ownership of |msg|
+   * and releases it with |OPENSSL_free| when done. */
+  int (*add_message)(SSL *ssl, uint8_t *msg, size_t len);
+  /* add_change_cipher_spec adds a ChangeCipherSpec record to the pending
+   * flight. It returns one on success and zero on error. */
+  int (*add_change_cipher_spec)(SSL *ssl);
+  /* add_alert adds an alert to the pending flight. It returns one on success
+   * and zero on error. */
+  int (*add_alert)(SSL *ssl, uint8_t level, uint8_t desc);
+  /* flush_flight flushes the pending flight to the transport. It returns one on
+   * success and <= 0 on error. */
+  int (*flush_flight)(SSL *ssl);
+  /* expect_flight is called when the handshake expects a flight of messages from
+   * the peer. */
+  void (*expect_flight)(SSL *ssl);
+  /* received_flight is called when the handshake has received a flight of
+   * messages from the peer. */
+  void (*received_flight)(SSL *ssl);
+  /* set_read_state sets |ssl|'s read cipher state to |aead_ctx|. It takes
+   * ownership of |aead_ctx|. It returns one on success and zero if changing the
+   * read state is forbidden at this point. */
+  int (*set_read_state)(SSL *ssl, SSL_AEAD_CTX *aead_ctx);
+  /* set_write_state sets |ssl|'s write cipher state to |aead_ctx|. It takes
+   * ownership of |aead_ctx|. It returns one on success and zero if changing the
+   * write state is forbidden at this point. */
+  int (*set_write_state)(SSL *ssl, SSL_AEAD_CTX *aead_ctx);
 };
 
-/* This is for the SSLv3/TLSv1.0 differences in crypto/hash stuff It is a bit
- * of a mess of functions, but hell, think of it as an opaque structure. */
-struct ssl3_enc_method {
-  int (*prf)(SSL *, uint8_t *, size_t, const uint8_t *, size_t, const char *,
-             size_t, const uint8_t *, size_t, const uint8_t *, size_t);
-  int (*setup_key_block)(SSL *);
-  int (*generate_master_secret)(SSL *, uint8_t *, const uint8_t *, size_t);
-  int (*change_cipher_state)(SSL *, int);
-  int (*final_finish_mac)(SSL *, const char *, int, uint8_t *);
-  int (*cert_verify_mac)(SSL *, int, uint8_t *);
-  const char *client_finished_label;
-  int client_finished_label_len;
-  const char *server_finished_label;
-  int server_finished_label_len;
-  int (*alert_value)(int);
-  int (*export_keying_material)(SSL *, uint8_t *, size_t, const char *, size_t,
-                                const uint8_t *, size_t, int use_context);
-  /* Various flags indicating protocol version requirements */
-  unsigned int enc_flags;
+struct ssl_x509_method_st {
+  /* check_client_CA_list returns one if |names| is a good list of X.509
+   * distinguished names and zero otherwise. This is used to ensure that we can
+   * reject unparsable values at handshake time when using crypto/x509. */
+  int (*check_client_CA_list)(STACK_OF(CRYPTO_BUFFER) *names);
+
+  /* cert_clear frees and NULLs all X509 certificate-related state. */
+  void (*cert_clear)(CERT *cert);
+  /* cert_free frees all X509-related state. */
+  void (*cert_free)(CERT *cert);
+  /* cert_flush_cached_chain drops any cached |X509|-based certificate chain
+   * from |cert|. */
+  /* cert_dup duplicates any needed fields from |cert| to |new_cert|. */
+  void (*cert_dup)(CERT *new_cert, const CERT *cert);
+  void (*cert_flush_cached_chain)(CERT *cert);
+  /* cert_flush_cached_chain drops any cached |X509|-based leaf certificate
+   * from |cert|. */
+  void (*cert_flush_cached_leaf)(CERT *cert);
+
+  /* session_cache_objects fills out |sess->x509_peer| and |sess->x509_chain|
+   * from |sess->certs| and erases |sess->x509_chain_without_leaf|. It returns
+   * one on success or zero on error. */
+  int (*session_cache_objects)(SSL_SESSION *session);
+  /* session_dup duplicates any needed fields from |session| to |new_session|.
+   * It returns one on success or zero on error. */
+  int (*session_dup)(SSL_SESSION *new_session, const SSL_SESSION *session);
+  /* session_clear frees any X509-related state from |session|. */
+  void (*session_clear)(SSL_SESSION *session);
+  /* session_verify_cert_chain verifies the certificate chain in |session|,
+   * sets |session->verify_result| and returns one on success or zero on
+   * error. */
+  int (*session_verify_cert_chain)(SSL_SESSION *session, SSL *ssl);
+
+  /* hs_flush_cached_ca_names drops any cached |X509_NAME|s from |hs|. */
+  void (*hs_flush_cached_ca_names)(SSL_HANDSHAKE *hs);
+  /* ssl_new does any neccessary initialisation of |ssl|. It returns one on
+   * success or zero on error. */
+  int (*ssl_new)(SSL *ssl);
+  /* ssl_free frees anything created by |ssl_new|. */
+  void (*ssl_free)(SSL *ssl);
+  /* ssl_flush_cached_client_CA drops any cached |X509_NAME|s from |ssl|. */
+  void (*ssl_flush_cached_client_CA)(SSL *ssl);
+  /* ssl_auto_chain_if_needed runs the deprecated auto-chaining logic if
+   * necessary. On success, it updates |ssl|'s certificate configuration as
+   * needed and returns one. Otherwise, it returns zero. */
+  int (*ssl_auto_chain_if_needed)(SSL *ssl);
+  /* ssl_ctx_new does any neccessary initialisation of |ctx|. It returns one on
+   * success or zero on error. */
+  int (*ssl_ctx_new)(SSL_CTX *ctx);
+  /* ssl_ctx_free frees anything created by |ssl_ctx_new|. */
+  void (*ssl_ctx_free)(SSL_CTX *ctx);
+  /* ssl_ctx_flush_cached_client_CA drops any cached |X509_NAME|s from |ctx|. */
+  void (*ssl_ctx_flush_cached_client_CA)(SSL_CTX *ssl);
 };
 
-#define SSL_HM_HEADER_LENGTH(ssl) ssl->method->hhlen
-#define ssl_handshake_start(ssl) \
-  (((uint8_t *)ssl->init_buf->data) + ssl->method->hhlen)
-#define ssl_set_handshake_header(ssl, htype, len) \
-  ssl->method->set_handshake_header(ssl, htype, len)
-#define ssl_do_write(ssl) ssl->method->do_write(ssl)
+/* ssl_crypto_x509_method provides the |ssl_x509_method_st| functions using
+ * crypto/x509. */
+extern const struct ssl_x509_method_st ssl_crypto_x509_method;
 
-/* Values for enc_flags */
+typedef struct ssl3_record_st {
+  /* type is the record type. */
+  uint8_t type;
+  /* length is the number of unconsumed bytes in the record. */
+  uint16_t length;
+  /* data is a non-owning pointer to the first unconsumed byte of the record. */
+  uint8_t *data;
+} SSL3_RECORD;
 
-/* Uses explicit IV for CBC mode */
-#define SSL_ENC_FLAG_EXPLICIT_IV 0x1
-/* Uses signature algorithms extension */
-#define SSL_ENC_FLAG_SIGALGS 0x2
-/* Uses SHA256 default PRF */
-#define SSL_ENC_FLAG_SHA256_PRF 0x4
+typedef struct ssl3_buffer_st {
+  /* buf is the memory allocated for this buffer. */
+  uint8_t *buf;
+  /* offset is the offset into |buf| which the buffer contents start at. */
+  uint16_t offset;
+  /* len is the length of the buffer contents from |buf| + |offset|. */
+  uint16_t len;
+  /* cap is how much memory beyond |buf| + |offset| is available. */
+  uint16_t cap;
+} SSL3_BUFFER;
+
+/* An ssl_shutdown_t describes the shutdown state of one end of the connection,
+ * whether it is alive or has been shutdown via close_notify or fatal alert. */
+enum ssl_shutdown_t {
+  ssl_shutdown_none = 0,
+  ssl_shutdown_close_notify = 1,
+  ssl_shutdown_fatal_alert = 2,
+};
+
+typedef struct ssl3_state_st {
+  uint8_t read_sequence[8];
+  uint8_t write_sequence[8];
+
+  uint8_t server_random[SSL3_RANDOM_SIZE];
+  uint8_t client_random[SSL3_RANDOM_SIZE];
+
+  /* read_buffer holds data from the transport to be processed. */
+  SSL3_BUFFER read_buffer;
+  /* write_buffer holds data to be written to the transport. */
+  SSL3_BUFFER write_buffer;
+
+  SSL3_RECORD rrec; /* each decoded record goes in here */
+
+  /* partial write - check the numbers match */
+  unsigned int wnum; /* number of bytes sent so far */
+  int wpend_tot;     /* number bytes written */
+  int wpend_type;
+  int wpend_ret; /* number of bytes submitted */
+  const uint8_t *wpend_buf;
+
+  /* recv_shutdown is the shutdown state for the receive half of the
+   * connection. */
+  enum ssl_shutdown_t recv_shutdown;
+
+  /* recv_shutdown is the shutdown state for the send half of the connection. */
+  enum ssl_shutdown_t send_shutdown;
+
+  int alert_dispatch;
+
+  int total_renegotiations;
+
+  /* early_data_skipped is the amount of early data that has been skipped by the
+   * record layer. */
+  uint16_t early_data_skipped;
+
+  /* empty_record_count is the number of consecutive empty records received. */
+  uint8_t empty_record_count;
+
+  /* warning_alert_count is the number of consecutive warning alerts
+   * received. */
+  uint8_t warning_alert_count;
+
+  /* key_update_count is the number of consecutive KeyUpdates received. */
+  uint8_t key_update_count;
+
+  /* skip_early_data instructs the record layer to skip unexpected early data
+   * messages when 0RTT is rejected. */
+  unsigned skip_early_data:1;
+
+  /* have_version is true if the connection's final version is known. Otherwise
+   * the version has not been negotiated yet. */
+  unsigned have_version:1;
+
+  /* v2_hello_done is true if the peer's V2ClientHello, if any, has been handled
+   * and future messages should use the record layer. */
+  unsigned v2_hello_done:1;
+
+  /* is_v2_hello is true if the current handshake message was derived from a
+   * V2ClientHello rather than received from the peer directly. */
+  unsigned is_v2_hello:1;
+
+  /* initial_handshake_complete is true if the initial handshake has
+   * completed. */
+  unsigned initial_handshake_complete:1;
+
+  /* session_reused indicates whether a session was resumed. */
+  unsigned session_reused:1;
+
+  unsigned send_connection_binding:1;
+
+  /* In a client, this means that the server supported Channel ID and that a
+   * Channel ID was sent. In a server it means that we echoed support for
+   * Channel IDs and that tlsext_channel_id will be valid after the
+   * handshake. */
+  unsigned tlsext_channel_id_valid:1;
+
+  uint8_t send_alert[2];
+
+  /* pending_flight is the pending outgoing flight. This is used to flush each
+   * handshake flight in a single write. */
+  BUF_MEM *pending_flight;
+
+  /* pending_flight_offset is the number of bytes of |pending_flight| which have
+   * been successfully written. */
+  uint32_t pending_flight_offset;
+
+  /* aead_read_ctx is the current read cipher state. */
+  SSL_AEAD_CTX *aead_read_ctx;
+
+  /* aead_write_ctx is the current write cipher state. */
+  SSL_AEAD_CTX *aead_write_ctx;
+
+  /* hs is the handshake state for the current handshake or NULL if there isn't
+   * one. */
+  SSL_HANDSHAKE *hs;
+
+  uint8_t write_traffic_secret[EVP_MAX_MD_SIZE];
+  uint8_t read_traffic_secret[EVP_MAX_MD_SIZE];
+  uint8_t exporter_secret[EVP_MAX_MD_SIZE];
+  uint8_t early_exporter_secret[EVP_MAX_MD_SIZE];
+  uint8_t write_traffic_secret_len;
+  uint8_t read_traffic_secret_len;
+  uint8_t exporter_secret_len;
+  uint8_t early_exporter_secret_len;
+
+  /* Connection binding to prevent renegotiation attacks */
+  uint8_t previous_client_finished[12];
+  uint8_t previous_client_finished_len;
+  uint8_t previous_server_finished_len;
+  uint8_t previous_server_finished[12];
+
+  /* State pertaining to the pending handshake.
+   *
+   * TODO(davidben): Move everything not needed after the handshake completes to
+   * |hs| and remove this. */
+  struct {
+    int message_type;
+
+    int reuse_message;
+
+    uint8_t new_mac_secret_len;
+    uint8_t new_key_len;
+    uint8_t new_fixed_iv_len;
+  } tmp;
+
+  /* established_session is the session established by the connection. This
+   * session is only filled upon the completion of the handshake and is
+   * immutable. */
+  SSL_SESSION *established_session;
+
+  /* Next protocol negotiation. For the client, this is the protocol that we
+   * sent in NextProtocol and is set when handling ServerHello extensions.
+   *
+   * For a server, this is the client's selected_protocol from NextProtocol and
+   * is set when handling the NextProtocol message, before the Finished
+   * message. */
+  uint8_t *next_proto_negotiated;
+  size_t next_proto_negotiated_len;
+
+  /* ALPN information
+   * (we are in the process of transitioning from NPN to ALPN.) */
+
+  /* In a server these point to the selected ALPN protocol after the
+   * ClientHello has been processed. In a client these contain the protocol
+   * that the server selected once the ServerHello has been processed. */
+  uint8_t *alpn_selected;
+  size_t alpn_selected_len;
+
+  /* For a server:
+   *     If |tlsext_channel_id_valid| is true, then this contains the
+   *     verified Channel ID from the client: a P256 point, (x,y), where
+   *     each are big-endian values. */
+  uint8_t tlsext_channel_id[64];
+
+  /* ticket_age_skew is the difference, in seconds, between the client-sent
+   * ticket age and the server-computed value in TLS 1.3 server connections
+   * which resumed a session. */
+  int32_t ticket_age_skew;
+} SSL3_STATE;
 
 /* lengths of messages */
 #define DTLS1_COOKIE_LENGTH 256
@@ -885,30 +1725,35 @@
 
 #define DTLS1_AL_HEADER_LENGTH 2
 
-/* TODO(davidben): This structure is used for both incoming messages and
- * outgoing messages. |is_ccs| and |epoch| are only used in the latter and
- * should be moved elsewhere. */
 struct hm_header_st {
   uint8_t type;
   uint32_t msg_len;
   uint16_t seq;
   uint32_t frag_off;
   uint32_t frag_len;
-  int is_ccs;
-  /* epoch, for buffered outgoing messages, is the epoch the message was
-   * originally sent in. */
-  uint16_t epoch;
 };
 
-/* TODO(davidben): This structure is used for both incoming messages and
- * outgoing messages. |fragment| and |reassembly| are only used in the former
- * and should be moved elsewhere. */
+/* An hm_fragment is an incoming DTLS message, possibly not yet assembled. */
 typedef struct hm_fragment_st {
-  struct hm_header_st msg_header;
-  uint8_t *fragment;
+  /* type is the type of the message. */
+  uint8_t type;
+  /* seq is the sequence number of this message. */
+  uint16_t seq;
+  /* msg_len is the length of the message body. */
+  uint32_t msg_len;
+  /* data is a pointer to the message, including message header. It has length
+   * |DTLS1_HM_HEADER_LENGTH| + |msg_len|. */
+  uint8_t *data;
+  /* reassembly is a bitmask of |msg_len| bits corresponding to which parts of
+   * the message have been received. It is NULL if the message is complete. */
   uint8_t *reassembly;
 } hm_fragment;
 
+struct OPENSSL_timeval {
+  uint64_t tv_sec;
+  uint32_t tv_usec;
+};
+
 typedef struct dtls1_state_st {
   /* send_cookie is true if we are resending the ClientHello
    * with a cookie from a HelloVerifyRequest. */
@@ -925,392 +1770,497 @@
   /* records being received in the current epoch */
   DTLS1_BITMAP bitmap;
 
-  /* handshake message numbers.
-   * TODO(davidben): It doesn't make much sense to store both of these. Only
-   * store one. */
   uint16_t handshake_write_seq;
-  uint16_t next_handshake_write_seq;
-
   uint16_t handshake_read_seq;
 
   /* save last sequence number for retransmissions */
   uint8_t last_write_sequence[8];
 
-  /* buffered_messages is a priority queue of incoming handshake messages that
-   * have yet to be processed.
-   *
-   * TODO(davidben): This data structure may as well be a ring buffer of fixed
-   * size. */
-  pqueue buffered_messages;
+  /* incoming_messages is a ring buffer of incoming handshake messages that have
+   * yet to be processed. The front of the ring buffer is message number
+   * |handshake_read_seq|, at position |handshake_read_seq| %
+   * |SSL_MAX_HANDSHAKE_FLIGHT|. */
+  hm_fragment *incoming_messages[SSL_MAX_HANDSHAKE_FLIGHT];
 
-  /* send_messages is a priority queue of outgoing handshake messages sent in
-   * the most recent handshake flight.
-   *
-   * TODO(davidben): This data structure may as well be a STACK_OF(T). */
-  pqueue sent_messages;
+  /* outgoing_messages is the queue of outgoing messages from the last handshake
+   * flight. */
+  DTLS_OUTGOING_MESSAGE outgoing_messages[SSL_MAX_HANDSHAKE_FLIGHT];
+  uint8_t outgoing_messages_len;
+
+  /* outgoing_written is the number of outgoing messages that have been
+   * written. */
+  uint8_t outgoing_written;
+  /* outgoing_offset is the number of bytes of the next outgoing message have
+   * been written. */
+  uint32_t outgoing_offset;
 
   unsigned int mtu; /* max DTLS packet size */
 
-  struct hm_header_st w_msg_hdr;
-
   /* num_timeouts is the number of times the retransmit timer has fired since
    * the last time it was reset. */
   unsigned int num_timeouts;
 
   /* Indicates when the last handshake msg or heartbeat sent will
    * timeout. */
-  struct timeval next_timeout;
+  struct OPENSSL_timeval next_timeout;
 
-  /* Timeout duration */
-  unsigned short timeout_duration;
+  /* timeout_duration_ms is the timeout duration in milliseconds. */
+  unsigned timeout_duration_ms;
 } DTLS1_STATE;
 
-extern const SSL3_ENC_METHOD TLSv1_enc_data;
-extern const SSL3_ENC_METHOD TLSv1_1_enc_data;
-extern const SSL3_ENC_METHOD TLSv1_2_enc_data;
-extern const SSL3_ENC_METHOD SSLv3_enc_data;
-extern const SRTP_PROTECTION_PROFILE kSRTPProfiles[];
+struct ssl_st {
+  /* method is the method table corresponding to the current protocol (DTLS or
+   * TLS). */
+  const SSL_PROTOCOL_METHOD *method;
 
-void ssl_clear_cipher_ctx(SSL *ssl);
-int ssl_clear_bad_session(SSL *ssl);
-CERT *ssl_cert_new(void);
+  /* version is the protocol version. */
+  int version;
+
+  /* max_version is the maximum acceptable protocol version. Note this version
+   * is normalized in DTLS. */
+  uint16_t max_version;
+
+  /* min_version is the minimum acceptable protocol version. Note this version
+   * is normalized in DTLS. */
+  uint16_t min_version;
+
+  uint16_t max_send_fragment;
+
+  /* There are 2 BIO's even though they are normally both the same. This is so
+   * data can be read and written to different handlers */
+
+  BIO *rbio; /* used by SSL_read */
+  BIO *wbio; /* used by SSL_write */
+
+  int (*handshake_func)(SSL_HANDSHAKE *hs);
+
+  BUF_MEM *init_buf; /* buffer used during init */
+
+  /* init_msg is a pointer to the current handshake message body. */
+  const uint8_t *init_msg;
+  /* init_num is the length of the current handshake message body. */
+  uint32_t init_num;
+
+  struct ssl3_state_st *s3;  /* SSLv3 variables */
+  struct dtls1_state_st *d1; /* DTLSv1 variables */
+
+  /* callback that allows applications to peek at protocol messages */
+  void (*msg_callback)(int write_p, int version, int content_type,
+                       const void *buf, size_t len, SSL *ssl, void *arg);
+  void *msg_callback_arg;
+
+  X509_VERIFY_PARAM *param;
+
+  /* crypto */
+  struct ssl_cipher_preference_list_st *cipher_list;
+
+  /* session info */
+
+  /* client cert? */
+  /* This is used to hold the server certificate used */
+  struct cert_st /* CERT */ *cert;
+
+  /* This holds a variable that indicates what we were doing when a 0 or -1 is
+   * returned.  This is needed for non-blocking IO so we know what request
+   * needs re-doing when in SSL_accept or SSL_connect */
+  int rwstate;
+
+  /* initial_timeout_duration_ms is the default DTLS timeout duration in
+   * milliseconds. It's used to initialize the timer any time it's restarted. */
+  unsigned initial_timeout_duration_ms;
+
+  /* session is the configured session to be offered by the client. This session
+   * is immutable. */
+  SSL_SESSION *session;
+
+  int (*verify_callback)(int ok,
+                         X509_STORE_CTX *ctx); /* fail if callback returns 0 */
+
+  void (*info_callback)(const SSL *ssl, int type, int value);
+
+  /* Server-only: psk_identity_hint is the identity hint to send in
+   * PSK-based key exchanges. */
+  char *psk_identity_hint;
+
+  unsigned int (*psk_client_callback)(SSL *ssl, const char *hint,
+                                      char *identity,
+                                      unsigned int max_identity_len,
+                                      uint8_t *psk, unsigned int max_psk_len);
+  unsigned int (*psk_server_callback)(SSL *ssl, const char *identity,
+                                      uint8_t *psk, unsigned int max_psk_len);
+
+  SSL_CTX *ctx;
+
+  /* extra application data */
+  CRYPTO_EX_DATA ex_data;
+
+  /* for server side, keep the list of CA_dn we can use */
+  STACK_OF(CRYPTO_BUFFER) *client_CA;
+
+  /* cached_x509_client_CA is a cache of parsed versions of the elements of
+   * |client_CA|. */
+  STACK_OF(X509_NAME) *cached_x509_client_CA;
+
+  uint32_t options; /* protocol behaviour */
+  uint32_t mode;    /* API behaviour */
+  uint32_t max_cert_list;
+  char *tlsext_hostname;
+  size_t supported_group_list_len;
+  uint16_t *supported_group_list; /* our list */
+
+  /* session_ctx is the |SSL_CTX| used for the session cache and related
+   * settings. */
+  SSL_CTX *session_ctx;
+
+  /* srtp_profiles is the list of configured SRTP protection profiles for
+   * DTLS-SRTP. */
+  STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles;
+
+  /* srtp_profile is the selected SRTP protection profile for
+   * DTLS-SRTP. */
+  const SRTP_PROTECTION_PROFILE *srtp_profile;
+
+  /* The client's Channel ID private key. */
+  EVP_PKEY *tlsext_channel_id_private;
+
+  /* For a client, this contains the list of supported protocols in wire
+   * format. */
+  uint8_t *alpn_client_proto_list;
+  unsigned alpn_client_proto_list_len;
+
+  /* renegotiate_mode controls how peer renegotiation attempts are handled. */
+  enum ssl_renegotiate_mode_t renegotiate_mode;
+
+  /* verify_mode is a bitmask of |SSL_VERIFY_*| values. */
+  uint8_t verify_mode;
+
+  /* server is true iff the this SSL* is the server half. Note: before the SSL*
+   * is initialized by either SSL_set_accept_state or SSL_set_connect_state,
+   * the side is not determined. In this state, server is always false. */
+  unsigned server:1;
+
+  /* quiet_shutdown is true if the connection should not send a close_notify on
+   * shutdown. */
+  unsigned quiet_shutdown:1;
+
+  /* Enable signed certificate time stamps. Currently client only. */
+  unsigned signed_cert_timestamps_enabled:1;
+
+  /* ocsp_stapling_enabled is only used by client connections and indicates
+   * whether OCSP stapling will be requested. */
+  unsigned ocsp_stapling_enabled:1;
+
+  /* tlsext_channel_id_enabled is copied from the |SSL_CTX|. For a server,
+   * means that we'll accept Channel IDs from clients. For a client, means that
+   * we'll advertise support. */
+  unsigned tlsext_channel_id_enabled:1;
+
+  /* retain_only_sha256_of_client_certs is true if we should compute the SHA256
+   * hash of the peer's certificate and then discard it to save memory and
+   * session space. Only effective on the server side. */
+  unsigned retain_only_sha256_of_client_certs:1;
+
+  /* early_data_accepted is true if early data was accepted by the server. */
+  unsigned early_data_accepted:1;
+};
+
+/* From draft-ietf-tls-tls13-18, used in determining PSK modes. */
+#define SSL_PSK_KE     0x0
+#define SSL_PSK_DHE_KE 0x1
+
+/* From draft-ietf-tls-tls13-16, used in determining whether to respond with a
+ * KeyUpdate. */
+#define SSL_KEY_UPDATE_NOT_REQUESTED 0
+#define SSL_KEY_UPDATE_REQUESTED 1
+
+CERT *ssl_cert_new(const SSL_X509_METHOD *x509_method);
 CERT *ssl_cert_dup(CERT *cert);
 void ssl_cert_clear_certs(CERT *c);
 void ssl_cert_free(CERT *c);
-int ssl_get_new_session(SSL *ssl, int is_server);
+int ssl_set_cert(CERT *cert, CRYPTO_BUFFER *buffer);
+int ssl_is_key_type_supported(int key_type);
+/* ssl_compare_public_and_private_key returns one if |pubkey| is the public
+ * counterpart to |privkey|. Otherwise it returns zero and pushes a helpful
+ * message on the error queue. */
+int ssl_compare_public_and_private_key(const EVP_PKEY *pubkey,
+                                       const EVP_PKEY *privkey);
+int ssl_cert_check_private_key(const CERT *cert, const EVP_PKEY *privkey);
+int ssl_get_new_session(SSL_HANDSHAKE *hs, int is_server);
+int ssl_encrypt_ticket(SSL *ssl, CBB *out, const SSL_SESSION *session);
+
+/* ssl_session_new returns a newly-allocated blank |SSL_SESSION| or NULL on
+ * error. */
+SSL_SESSION *ssl_session_new(const SSL_X509_METHOD *x509_method);
+
+/* SSL_SESSION_parse parses an |SSL_SESSION| from |cbs| and advances |cbs| over
+ * the parsed data. */
+SSL_SESSION *SSL_SESSION_parse(CBS *cbs, const SSL_X509_METHOD *x509_method,
+                               CRYPTO_BUFFER_POOL *pool);
+
+/* ssl_session_is_context_valid returns one if |session|'s session ID context
+ * matches the one set on |ssl| and zero otherwise. */
+int ssl_session_is_context_valid(const SSL *ssl, const SSL_SESSION *session);
+
+/* ssl_session_is_time_valid returns one if |session| is still valid and zero if
+ * it has expired. */
+int ssl_session_is_time_valid(const SSL *ssl, const SSL_SESSION *session);
+
+/* ssl_session_is_resumable returns one if |session| is resumable for |hs| and
+ * zero otherwise. */
+int ssl_session_is_resumable(const SSL_HANDSHAKE *hs,
+                             const SSL_SESSION *session);
+
+/* SSL_SESSION_get_digest returns the digest used in |session|. If the digest is
+ * invalid, it returns NULL. */
+const EVP_MD *SSL_SESSION_get_digest(const SSL_SESSION *session,
+                                     const SSL *ssl);
+
+void ssl_set_session(SSL *ssl, SSL_SESSION *session);
 
 enum ssl_session_result_t {
   ssl_session_success,
   ssl_session_error,
   ssl_session_retry,
+  ssl_session_ticket_retry,
 };
 
-/* ssl_get_prev_session looks up the previous session based on |ctx|. On
- * success, it sets |*out_session| to the session or NULL if none was found. It
- * sets |*out_send_ticket| to whether a ticket should be sent at the end of the
- * handshake. If the session could not be looked up synchronously, it returns
- * |ssl_session_retry| and should be called again. Otherwise, it returns
- * |ssl_session_error|.  */
+/* ssl_get_prev_session looks up the previous session based on |client_hello|.
+ * On success, it sets |*out_session| to the session or NULL if none was found.
+ * If the session could not be looked up synchronously, it returns
+ * |ssl_session_retry| and should be called again. If a ticket could not be
+ * decrypted immediately it returns |ssl_session_ticket_retry| and should also
+ * be called again. Otherwise, it returns |ssl_session_error|.  */
 enum ssl_session_result_t ssl_get_prev_session(
-    SSL *ssl, SSL_SESSION **out_session, int *out_send_ticket,
-    const struct ssl_early_callback_ctx *ctx);
+    SSL *ssl, SSL_SESSION **out_session, int *out_tickets_supported,
+    int *out_renew_ticket, const SSL_CLIENT_HELLO *client_hello);
 
-STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *ssl, const CBS *cbs);
+/* The following flags determine which parts of the session are duplicated. */
+#define SSL_SESSION_DUP_AUTH_ONLY 0x0
+#define SSL_SESSION_INCLUDE_TICKET 0x1
+#define SSL_SESSION_INCLUDE_NONAUTH 0x2
+#define SSL_SESSION_DUP_ALL \
+  (SSL_SESSION_INCLUDE_TICKET | SSL_SESSION_INCLUDE_NONAUTH)
+
+/* SSL_SESSION_dup returns a newly-allocated |SSL_SESSION| with a copy of the
+ * fields in |session| or NULL on error. The new session is non-resumable and
+ * must be explicitly marked resumable once it has been filled in. */
+OPENSSL_EXPORT SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *session,
+                                            int dup_flags);
+
+/* ssl_session_rebase_time updates |session|'s start time to the current time,
+ * adjusting the timeout so the expiration time is unchanged. */
+void ssl_session_rebase_time(SSL *ssl, SSL_SESSION *session);
+
+/* ssl_session_renew_timeout calls |ssl_session_rebase_time| and renews
+ * |session|'s timeout to |timeout| (measured from the current time). The
+ * renewal is clamped to the session's auth_timeout. */
+void ssl_session_renew_timeout(SSL *ssl, SSL_SESSION *session,
+                               uint32_t timeout);
+
 void ssl_cipher_preference_list_free(
     struct ssl_cipher_preference_list_st *cipher_list);
-struct ssl_cipher_preference_list_st *ssl_get_cipher_preferences(SSL *ssl);
 
-int ssl_cert_set0_chain(CERT *cert, STACK_OF(X509) *chain);
-int ssl_cert_set1_chain(CERT *cert, STACK_OF(X509) *chain);
-int ssl_cert_add0_chain_cert(CERT *cert, X509 *x509);
-int ssl_cert_add1_chain_cert(CERT *cert, X509 *x509);
-void ssl_cert_set_cert_cb(CERT *cert,
-                          int (*cb)(SSL *ssl, void *arg), void *arg);
+/* ssl_get_cipher_preferences returns the cipher preference list for TLS 1.2 and
+ * below. */
+const struct ssl_cipher_preference_list_st *ssl_get_cipher_preferences(
+    const SSL *ssl);
 
-int ssl_verify_cert_chain(SSL *ssl, STACK_OF(X509) *cert_chain);
-int ssl_add_cert_chain(SSL *ssl, unsigned long *l);
-void ssl_update_cache(SSL *ssl, int mode);
+void ssl_update_cache(SSL_HANDSHAKE *hs, int mode);
 
-/* ssl_get_compatible_server_ciphers determines the key exchange and
- * authentication cipher suite masks compatible with the server configuration
- * and current ClientHello parameters of |ssl|. It sets |*out_mask_k| to the key
- * exchange mask and |*out_mask_a| to the authentication mask. */
-void ssl_get_compatible_server_ciphers(SSL *ssl, uint32_t *out_mask_k,
-                                       uint32_t *out_mask_a);
-
-STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *ssl);
-int ssl_verify_alarm_type(long type);
-
-/* ssl_fill_hello_random fills a client_random or server_random field of length
- * |len|. It returns one on success and zero on failure. */
-int ssl_fill_hello_random(uint8_t *out, size_t len, int is_server);
-
-int ssl3_send_server_certificate(SSL *ssl);
-int ssl3_send_new_session_ticket(SSL *ssl);
-int ssl3_send_certificate_status(SSL *ssl);
-int ssl3_get_finished(SSL *ssl, int state_a, int state_b);
-int ssl3_send_change_cipher_spec(SSL *ssl, int state_a, int state_b);
-int ssl3_prf(SSL *ssl, uint8_t *out, size_t out_len, const uint8_t *secret,
-             size_t secret_len, const char *label, size_t label_len,
-             const uint8_t *seed1, size_t seed1_len,
-             const uint8_t *seed2, size_t seed2_len);
-void ssl3_cleanup_key_block(SSL *ssl);
-int ssl3_do_write(SSL *ssl, int type);
+int ssl3_get_finished(SSL_HANDSHAKE *hs);
 int ssl3_send_alert(SSL *ssl, int level, int desc);
-int ssl3_get_req_cert_type(SSL *ssl, uint8_t *p);
-long ssl3_get_message(SSL *ssl, int header_state, int body_state, int msg_type,
-                      long max, enum ssl_hash_message_t hash_message, int *ok);
+int ssl3_get_message(SSL *ssl);
+void ssl3_get_current_message(const SSL *ssl, CBS *out);
+void ssl3_release_current_message(SSL *ssl, int free_buffer);
 
-/* ssl3_hash_current_message incorporates the current handshake message into the
- * handshake hash. It returns one on success and zero on allocation failure. */
-int ssl3_hash_current_message(SSL *ssl);
-
-/* ssl3_cert_verify_hash writes the CertificateVerify hash into the bytes
- * pointed to by |out| and writes the number of bytes to |*out_len|. |out| must
- * have room for EVP_MAX_MD_SIZE bytes. For TLS 1.2 and up, |*out_md| is used
- * for the hash function, otherwise the hash function depends on |pkey_type|
- * and is written to |*out_md|. It returns one on success and zero on
- * failure. */
-int ssl3_cert_verify_hash(SSL *ssl, uint8_t *out, size_t *out_len,
-                          const EVP_MD **out_md, int pkey_type);
-
-int ssl3_send_finished(SSL *ssl, int a, int b, const char *sender, int slen);
-int ssl3_supports_cipher(const SSL_CIPHER *cipher);
+int ssl3_send_finished(SSL_HANDSHAKE *hs);
 int ssl3_dispatch_alert(SSL *ssl);
-int ssl3_read_app_data(SSL *ssl, uint8_t *buf, int len, int peek);
+int ssl3_read_app_data(SSL *ssl, int *out_got_handshake, uint8_t *buf, int len,
+                       int peek);
 int ssl3_read_change_cipher_spec(SSL *ssl);
 void ssl3_read_close_notify(SSL *ssl);
-int ssl3_read_bytes(SSL *ssl, int type, uint8_t *buf, int len, int peek);
-int ssl3_write_app_data(SSL *ssl, const void *buf, int len);
-int ssl3_write_bytes(SSL *ssl, int type, const void *buf, int len);
-int ssl3_final_finish_mac(SSL *ssl, const char *sender, int slen, uint8_t *p);
-int ssl3_cert_verify_mac(SSL *ssl, int md_nid, uint8_t *p);
+int ssl3_read_handshake_bytes(SSL *ssl, uint8_t *buf, int len);
+int ssl3_write_app_data(SSL *ssl, const uint8_t *buf, int len);
 int ssl3_output_cert_chain(SSL *ssl);
-const SSL_CIPHER *ssl3_choose_cipher(
-    SSL *ssl, STACK_OF(SSL_CIPHER) *clnt,
-    struct ssl_cipher_preference_list_st *srvr);
 
 int ssl3_new(SSL *ssl);
 void ssl3_free(SSL *ssl);
-int ssl3_accept(SSL *ssl);
-int ssl3_connect(SSL *ssl);
+int ssl3_accept(SSL_HANDSHAKE *hs);
+int ssl3_connect(SSL_HANDSHAKE *hs);
 
-/* ssl3_record_sequence_update increments the sequence number in |seq|. It
- * returns one on success and zero on wraparound. */
-int ssl3_record_sequence_update(uint8_t *seq, size_t seq_len);
+int ssl3_init_message(SSL *ssl, CBB *cbb, CBB *body, uint8_t type);
+int ssl3_finish_message(SSL *ssl, CBB *cbb, uint8_t **out_msg, size_t *out_len);
+int ssl3_add_message(SSL *ssl, uint8_t *msg, size_t len);
+int ssl3_add_change_cipher_spec(SSL *ssl);
+int ssl3_add_alert(SSL *ssl, uint8_t level, uint8_t desc);
+int ssl3_flush_flight(SSL *ssl);
 
-int ssl3_do_change_cipher_spec(SSL *ssl);
+int dtls1_init_message(SSL *ssl, CBB *cbb, CBB *body, uint8_t type);
+int dtls1_finish_message(SSL *ssl, CBB *cbb, uint8_t **out_msg,
+                         size_t *out_len);
+int dtls1_add_message(SSL *ssl, uint8_t *msg, size_t len);
+int dtls1_add_change_cipher_spec(SSL *ssl);
+int dtls1_add_alert(SSL *ssl, uint8_t level, uint8_t desc);
+int dtls1_flush_flight(SSL *ssl);
 
-int ssl3_set_handshake_header(SSL *ssl, int htype, unsigned long len);
-int ssl3_handshake_write(SSL *ssl);
+/* ssl_add_message_cbb finishes the handshake message in |cbb| and adds it to
+ * the pending flight. It returns one on success and zero on error. */
+int ssl_add_message_cbb(SSL *ssl, CBB *cbb);
 
-int dtls1_do_handshake_write(SSL *ssl, enum dtls1_use_epoch_t use_epoch);
-int dtls1_read_app_data(SSL *ssl, uint8_t *buf, int len, int peek);
+/* ssl_hash_current_message incorporates the current handshake message into the
+ * handshake hash. It returns one on success and zero on allocation failure. */
+int ssl_hash_current_message(SSL_HANDSHAKE *hs);
+
+/* dtls1_get_record reads a new input record. On success, it places it in
+ * |ssl->s3->rrec| and returns one. Otherwise it returns <= 0 on error or if
+ * more data is needed. */
+int dtls1_get_record(SSL *ssl);
+
+int dtls1_read_app_data(SSL *ssl, int *out_got_handshake, uint8_t *buf, int len,
+                        int peek);
 int dtls1_read_change_cipher_spec(SSL *ssl);
 void dtls1_read_close_notify(SSL *ssl);
-int dtls1_read_bytes(SSL *ssl, int type, uint8_t *buf, int len, int peek);
-void dtls1_set_message_header(SSL *ssl, uint8_t mt, unsigned long len,
-                              unsigned short seq_num, unsigned long frag_off,
-                              unsigned long frag_len);
 
-int dtls1_write_app_data(SSL *ssl, const void *buf, int len);
-int dtls1_write_bytes(SSL *ssl, int type, const void *buf, int len,
-                      enum dtls1_use_epoch_t use_epoch);
+int dtls1_write_app_data(SSL *ssl, const uint8_t *buf, int len);
 
-int dtls1_send_change_cipher_spec(SSL *ssl, int a, int b);
+/* dtls1_write_record sends a record. It returns one on success and <= 0 on
+ * error. */
+int dtls1_write_record(SSL *ssl, int type, const uint8_t *buf, size_t len,
+                       enum dtls1_use_epoch_t use_epoch);
+
 int dtls1_send_finished(SSL *ssl, int a, int b, const char *sender, int slen);
-int dtls1_read_failed(SSL *ssl, int code);
-int dtls1_buffer_message(SSL *ssl);
-int dtls1_retransmit_buffered_messages(SSL *ssl);
+int dtls1_retransmit_outgoing_messages(SSL *ssl);
 void dtls1_clear_record_buffer(SSL *ssl);
-void dtls1_get_message_header(uint8_t *data, struct hm_header_st *msg_hdr);
+int dtls1_parse_fragment(CBS *cbs, struct hm_header_st *out_hdr,
+                         CBS *out_body);
 int dtls1_check_timeout_num(SSL *ssl);
-int dtls1_set_handshake_header(SSL *ssl, int type, unsigned long len);
 int dtls1_handshake_write(SSL *ssl);
 
-int dtls1_supports_cipher(const SSL_CIPHER *cipher);
 void dtls1_start_timer(SSL *ssl);
 void dtls1_stop_timer(SSL *ssl);
 int dtls1_is_timer_expired(SSL *ssl);
 void dtls1_double_timeout(SSL *ssl);
 unsigned int dtls1_min_mtu(void);
-void dtls1_hm_fragment_free(hm_fragment *frag);
-
-/* some client-only functions */
-int ssl3_send_client_hello(SSL *ssl);
-int ssl3_get_server_hello(SSL *ssl);
-int ssl3_get_certificate_request(SSL *ssl);
-int ssl3_get_new_session_ticket(SSL *ssl);
-int ssl3_get_cert_status(SSL *ssl);
-int ssl3_get_server_done(SSL *ssl);
-int ssl3_send_cert_verify(SSL *ssl);
-int ssl3_send_client_certificate(SSL *ssl);
-int ssl_do_client_cert_cb(SSL *ssl, X509 **px509, EVP_PKEY **ppkey);
-int ssl3_send_client_key_exchange(SSL *ssl);
-int ssl3_get_server_key_exchange(SSL *ssl);
-int ssl3_get_server_certificate(SSL *ssl);
-int ssl3_send_next_proto(SSL *ssl);
-int ssl3_send_channel_id(SSL *ssl);
-int ssl3_verify_server_cert(SSL *ssl);
-
-/* some server-only functions */
-int ssl3_get_initial_bytes(SSL *ssl);
-int ssl3_get_v2_client_hello(SSL *ssl);
-int ssl3_get_client_hello(SSL *ssl);
-int ssl3_send_server_hello(SSL *ssl);
-int ssl3_send_server_key_exchange(SSL *ssl);
-int ssl3_send_certificate_request(SSL *ssl);
-int ssl3_send_server_done(SSL *ssl);
-int ssl3_get_client_certificate(SSL *ssl);
-int ssl3_get_client_key_exchange(SSL *ssl);
-int ssl3_get_cert_verify(SSL *ssl);
-int ssl3_get_next_proto(SSL *ssl);
-int ssl3_get_channel_id(SSL *ssl);
 
 int dtls1_new(SSL *ssl);
 int dtls1_accept(SSL *ssl);
 int dtls1_connect(SSL *ssl);
 void dtls1_free(SSL *ssl);
 
-long dtls1_get_message(SSL *ssl, int st1, int stn, int mt, long max,
-                       enum ssl_hash_message_t hash_message, int *ok);
+int dtls1_get_message(SSL *ssl);
+void dtls1_get_current_message(const SSL *ssl, CBS *out);
+void dtls1_release_current_message(SSL *ssl, int free_buffer);
 int dtls1_dispatch_alert(SSL *ssl);
 
-int ssl_init_wbio_buffer(SSL *ssl, int push);
-void ssl_free_wbio_buffer(SSL *ssl);
+int tls1_change_cipher_state(SSL_HANDSHAKE *hs, int which);
+int tls1_generate_master_secret(SSL_HANDSHAKE *hs, uint8_t *out,
+                                const uint8_t *premaster, size_t premaster_len);
 
-/* tls1_prf computes the TLS PRF function for |ssl| as described in RFC 5246,
- * section 5 and RFC 2246 section 5. It writes |out_len| bytes to |out|, using
- * |secret| as the secret and |label| as the label. |seed1| and |seed2| are
- * concatenated to form the seed parameter. It returns one on success and zero
- * on failure. */
-int tls1_prf(SSL *ssl, uint8_t *out, size_t out_len, const uint8_t *secret,
-             size_t secret_len, const char *label, size_t label_len,
-             const uint8_t *seed1, size_t seed1_len,
-             const uint8_t *seed2, size_t seed2_len);
+/* tls1_get_grouplist sets |*out_group_ids| and |*out_group_ids_len| to the
+ * locally-configured group preference list. */
+void tls1_get_grouplist(SSL *ssl, const uint16_t **out_group_ids,
+                        size_t *out_group_ids_len);
 
-int tls1_change_cipher_state(SSL *ssl, int which);
-int tls1_setup_key_block(SSL *ssl);
-int tls1_handshake_digest(SSL *ssl, uint8_t *out, size_t out_len);
-int tls1_final_finish_mac(SSL *ssl, const char *str, int slen, uint8_t *p);
-int tls1_cert_verify_mac(SSL *ssl, int md_nid, uint8_t *p);
-int tls1_generate_master_secret(SSL *ssl, uint8_t *out, const uint8_t *premaster,
-                                size_t premaster_len);
-int tls1_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len,
-                                const char *label, size_t label_len,
-                                const uint8_t *context, size_t context_len,
-                                int use_context);
-int tls1_alert_code(int code);
-int ssl3_alert_code(int code);
+/* tls1_check_group_id returns one if |group_id| is consistent with
+ * locally-configured group preferences. */
+int tls1_check_group_id(SSL *ssl, uint16_t group_id);
 
-char ssl_early_callback_init(struct ssl_early_callback_ctx *ctx);
-
-/* tls1_check_curve_id returns one if |curve_id| is consistent with both our
- * and the peer's curve preferences. Note: if called as the client, only our
- * preferences are checked; the peer (the server) does not send preferences. */
-int tls1_check_curve_id(SSL *ssl, uint16_t curve_id);
-
-/* tls1_get_shared_curve sets |*out_curve_id| to the first preferred shared
- * curve between client and server preferences and returns one. If none may be
+/* tls1_get_shared_group sets |*out_group_id| to the first preferred shared
+ * group between client and server preferences and returns one. If none may be
  * found, it returns zero. */
-int tls1_get_shared_curve(SSL *ssl, uint16_t *out_curve_id);
+int tls1_get_shared_group(SSL_HANDSHAKE *hs, uint16_t *out_group_id);
 
 /* tls1_set_curves converts the array of |ncurves| NIDs pointed to by |curves|
- * into a newly allocated array of TLS curve IDs. On success, the function
- * returns one and writes the array to |*out_curve_ids| and its size to
- * |*out_curve_ids_len|. Otherwise, it returns zero. */
-int tls1_set_curves(uint16_t **out_curve_ids, size_t *out_curve_ids_len,
+ * into a newly allocated array of TLS group IDs. On success, the function
+ * returns one and writes the array to |*out_group_ids| and its size to
+ * |*out_group_ids_len|. Otherwise, it returns zero. */
+int tls1_set_curves(uint16_t **out_group_ids, size_t *out_group_ids_len,
                     const int *curves, size_t ncurves);
 
-/* tls1_check_ec_cert returns one if |x| is an ECC certificate with curve and
- * point format compatible with the client's preferences. Otherwise it returns
- * zero. */
-int tls1_check_ec_cert(SSL *ssl, X509 *x);
+/* tls1_set_curves_list converts the string of curves pointed to by |curves|
+ * into a newly allocated array of TLS group IDs. On success, the function
+ * returns one and writes the array to |*out_group_ids| and its size to
+ * |*out_group_ids_len|. Otherwise, it returns zero. */
+int tls1_set_curves_list(uint16_t **out_group_ids, size_t *out_group_ids_len,
+                         const char *curves);
 
 /* ssl_add_clienthello_tlsext writes ClientHello extensions to |out|. It
  * returns one on success and zero on failure. The |header_len| argument is the
  * length of the ClientHello written so far and is used to compute the padding
  * length. (It does not include the record header.) */
-int ssl_add_clienthello_tlsext(SSL *ssl, CBB *out, size_t header_len);
+int ssl_add_clienthello_tlsext(SSL_HANDSHAKE *hs, CBB *out, size_t header_len);
 
-int ssl_add_serverhello_tlsext(SSL *ssl, CBB *out);
-int ssl_parse_clienthello_tlsext(SSL *ssl, CBS *cbs);
-int ssl_parse_serverhello_tlsext(SSL *ssl, CBS *cbs);
+int ssl_add_serverhello_tlsext(SSL_HANDSHAKE *hs, CBB *out);
+int ssl_parse_clienthello_tlsext(SSL_HANDSHAKE *hs,
+                                 const SSL_CLIENT_HELLO *client_hello);
+int ssl_parse_serverhello_tlsext(SSL_HANDSHAKE *hs, CBS *cbs);
 
 #define tlsext_tick_md EVP_sha256
 
-/* tls_process_ticket processes the session ticket extension. On success, it
- * sets |*out_session| to the decrypted session or NULL if the ticket was
- * rejected. It sets |*out_send_ticket| to whether a new ticket should be sent
- * at the end of the handshake. It returns one on success and zero on fatal
- * error. */
-int tls_process_ticket(SSL *ssl, SSL_SESSION **out_session,
-                       int *out_send_ticket, const uint8_t *ticket,
-                       size_t ticket_len, const uint8_t *session_id,
-                       size_t session_id_len);
+/* ssl_process_ticket processes a session ticket from the client. It returns
+ * one of:
+ *   |ssl_ticket_aead_success|: |*out_session| is set to the parsed session and
+ *       |*out_renew_ticket| is set to whether the ticket should be renewed.
+ *   |ssl_ticket_aead_ignore_ticket|: |*out_renew_ticket| is set to whether a
+ *       fresh ticket should be sent, but the given ticket cannot be used.
+ *   |ssl_ticket_aead_retry|: the ticket could not be immediately decrypted.
+ *       Retry later.
+ *   |ssl_ticket_aead_error|: an error occured that is fatal to the connection. */
+enum ssl_ticket_aead_result_t ssl_process_ticket(
+    SSL *ssl, SSL_SESSION **out_session, int *out_renew_ticket,
+    const uint8_t *ticket, size_t ticket_len, const uint8_t *session_id,
+    size_t session_id_len);
 
-/* tls12_add_sigandhash assembles the SignatureAndHashAlgorithm corresponding to
- * |ssl|'s private key and |md|. The two-byte value is written to |out|. It
- * returns one on success and zero on failure. */
-int tls12_add_sigandhash(SSL *ssl, CBB *out, const EVP_MD *md);
+/* tls1_verify_channel_id processes the current message as a Channel ID message,
+ * and verifies the signature. If the key is valid, it saves the Channel ID and
+ * returns one. Otherwise, it returns zero. */
+int tls1_verify_channel_id(SSL_HANDSHAKE *hs);
 
-int tls12_get_sigid(int pkey_type);
-const EVP_MD *tls12_get_hash(uint8_t hash_alg);
+/* tls1_write_channel_id generates a Channel ID message and puts the output in
+ * |cbb|. |ssl->tlsext_channel_id_private| must already be set before calling.
+ * This function returns one on success and zero on error. */
+int tls1_write_channel_id(SSL_HANDSHAKE *hs, CBB *cbb);
 
 /* tls1_channel_id_hash computes the hash to be signed by Channel ID and writes
  * it to |out|, which must contain at least |EVP_MAX_MD_SIZE| bytes. It returns
  * one on success and zero on failure. */
-int tls1_channel_id_hash(SSL *ssl, uint8_t *out, size_t *out_len);
+int tls1_channel_id_hash(SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len);
 
-int tls1_record_handshake_hashes_for_channel_id(SSL *ssl);
+int tls1_record_handshake_hashes_for_channel_id(SSL_HANDSHAKE *hs);
 
-/* ssl_log_rsa_client_key_exchange logs |premaster|, if logging is enabled for
- * |ssl|. It returns one on success and zero on failure. The entry is identified
- * by the first 8 bytes of |encrypted_premaster|. */
-int ssl_log_rsa_client_key_exchange(const SSL *ssl,
-                                    const uint8_t *encrypted_premaster,
-                                    size_t encrypted_premaster_len,
-                                    const uint8_t *premaster,
-                                    size_t premaster_len);
-
-/* ssl_log_master_secret logs |master|, if logging is enabled for |ssl|. It
- * returns one on success and zero on failure. The entry is identified by
- * |client_random|. */
-int ssl_log_master_secret(const SSL *ssl, const uint8_t *client_random,
-                          size_t client_random_len, const uint8_t *master,
-                          size_t master_len);
+/* ssl_do_channel_id_callback checks runs |ssl->ctx->channel_id_cb| if
+ * necessary. It returns one on success and zero on fatal error. Note that, on
+ * success, |ssl->tlsext_channel_id_private| may be unset, in which case the
+ * operation should be retried later. */
+int ssl_do_channel_id_callback(SSL *ssl);
 
 /* ssl3_can_false_start returns one if |ssl| is allowed to False Start and zero
  * otherwise. */
 int ssl3_can_false_start(const SSL *ssl);
 
-/* ssl3_get_enc_method returns the SSL3_ENC_METHOD corresponding to
- * |version|. */
-const SSL3_ENC_METHOD *ssl3_get_enc_method(uint16_t version);
+/* ssl_can_write returns one if |ssl| is allowed to write and zero otherwise. */
+int ssl_can_write(const SSL *ssl);
 
-/* ssl3_get_max_server_version returns the maximum SSL/TLS version number
- * supported by |ssl| as a server, or zero if all versions are disabled. */
-uint16_t ssl3_get_max_server_version(const SSL *ssl);
+/* ssl_can_read returns one if |ssl| is allowed to read and zero otherwise. */
+int ssl_can_read(const SSL *ssl);
 
-/* ssl3_get_mutual_version selects the protocol version on |ssl| for a client
- * which advertises |client_version|. If no suitable version exists, it returns
- * zero. */
-uint16_t ssl3_get_mutual_version(SSL *ssl, uint16_t client_version);
+/* ssl_get_version_range sets |*out_min_version| and |*out_max_version| to the
+ * minimum and maximum enabled protocol versions, respectively. */
+int ssl_get_version_range(const SSL *ssl, uint16_t *out_min_version,
+                          uint16_t *out_max_version);
 
-/* ssl3_get_max_client_version returns the maximum protocol version configured
- * for the client. It is guaranteed that the set of allowed versions at or below
- * this maximum version is contiguous. If all versions are disabled, it returns
- * zero. */
-uint16_t ssl3_get_max_client_version(SSL *ssl);
+/* ssl3_protocol_version returns |ssl|'s protocol version. It is an error to
+ * call this function before the version is determined. */
+uint16_t ssl3_protocol_version(const SSL *ssl);
 
-/* ssl3_is_version_enabled returns one if |version| is an enabled protocol
- * version for |ssl| and zero otherwise. */
-int ssl3_is_version_enabled(SSL *ssl, uint16_t version);
+void ssl_get_current_time(const SSL *ssl, struct OPENSSL_timeval *out_clock);
 
-/* ssl3_version_from_wire maps |wire_version| to a protocol version. For
- * SSLv3/TLS, the version is returned as-is. For DTLS, the corresponding TLS
- * version is used. Note that this mapping is not injective but preserves
- * comparisons.
- *
- * TODO(davidben): To normalize some DTLS-specific code, move away from using
- * the wire version except at API boundaries. */
-uint16_t ssl3_version_from_wire(SSL *ssl, uint16_t wire_version);
+/* ssl_reset_error_state resets state for |SSL_get_error|. */
+void ssl_reset_error_state(SSL *ssl);
 
-uint32_t ssl_get_algorithm_prf(SSL *ssl);
-int tls1_parse_peer_sigalgs(SSL *ssl, const CBS *sigalgs);
 
-/* tls1_choose_signing_digest returns a digest for use with |ssl|'s private key
- * based on the peer's preferences the digests supported. */
-const EVP_MD *tls1_choose_signing_digest(SSL *ssl);
-
-size_t tls12_get_psigalgs(SSL *ssl, const uint8_t **psigs);
-
-/* tls12_check_peer_sigalg checks that |hash| and |signature| are consistent
- * with |pkey| and |ssl|'s sent, supported signature algorithms and, if so,
- * writes the relevant digest into |*out_md| and returns 1. Otherwise it
- * returns 0 and writes an alert into |*out_alert|. */
-int tls12_check_peer_sigalg(SSL *ssl, const EVP_MD **out_md, int *out_alert,
-                            uint8_t hash, uint8_t signature, EVP_PKEY *pkey);
-void ssl_set_client_disabled(SSL *ssl);
+#if defined(__cplusplus)
+} /* extern C */
+#endif
 
 #endif /* OPENSSL_HEADER_SSL_INTERNAL_H */
diff --git a/src/ssl/pqueue/CMakeLists.txt b/src/ssl/pqueue/CMakeLists.txt
deleted file mode 100644
index 3a8b82b..0000000
--- a/src/ssl/pqueue/CMakeLists.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-include_directories(../../include)
-
-add_library(
-  pqueue
-
-  OBJECT
-
-  pqueue.c
-)
-
-add_executable(
-  pqueue_test
-
-  pqueue_test.c
-
-  $<TARGET_OBJECTS:test_support>
-)
-
-target_link_libraries(pqueue_test ssl crypto)
-add_dependencies(all_tests pqueue_test)
diff --git a/src/ssl/pqueue/pqueue.c b/src/ssl/pqueue/pqueue.c
deleted file mode 100644
index 14bd9b6..0000000
--- a/src/ssl/pqueue/pqueue.c
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * DTLS implementation written by Nagendra Modadugu
- * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.
- */
-/* ====================================================================
- * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- *    software must display the following acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- *    endorse or promote products derived from this software without
- *    prior written permission. For written permission, please contact
- *    openssl-core@OpenSSL.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- *    nor may "OpenSSL" appear in their names without prior written
- *    permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- *    acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- *
- * This product includes cryptographic software written by Eric Young
- * (eay@cryptsoft.com).  This product includes software written by Tim
- * Hudson (tjh@cryptsoft.com). */
-
-#include <openssl/pqueue.h>
-
-#include <assert.h>
-#include <string.h>
-
-#include <openssl/mem.h>
-
-
-typedef struct _pqueue {
-  pitem *items;
-  unsigned count;
-} pqueue_s;
-
-
-pitem *pitem_new(uint8_t prio64be[8], void *data) {
-  pitem *item = (pitem *)OPENSSL_malloc(sizeof(pitem));
-  if (item == NULL) {
-    return NULL;
-  }
-
-  memcpy(item->priority, prio64be, sizeof(item->priority));
-
-  item->data = data;
-  item->next = NULL;
-
-  return item;
-}
-
-void pitem_free(pitem *item) {
-  if (item == NULL) {
-    return;
-  }
-
-  OPENSSL_free(item);
-}
-
-pqueue pqueue_new(void) {
-  pqueue_s *pq = (pqueue_s *)OPENSSL_malloc(sizeof(pqueue_s));
-  if (pq == NULL) {
-    return NULL;
-  }
-
-  memset(pq, 0, sizeof(pqueue_s));
-  return pq;
-}
-
-void pqueue_free(pqueue_s *pq) {
-  if (pq == NULL) {
-    return;
-  }
-
-  /* The queue must be empty. */
-  assert(pq->items == NULL);
-  OPENSSL_free(pq);
-}
-
-pitem *pqueue_peek(pqueue_s *pq) { return pq->items; }
-
-pitem *pqueue_find(pqueue_s *pq, uint8_t *prio64be) {
-  pitem *curr;
-
-  for (curr = pq->items; curr; curr = curr->next) {
-    if (memcmp(curr->priority, prio64be, sizeof(curr->priority)) == 0) {
-      return curr;
-    }
-  }
-
-  return NULL;
-}
-
-size_t pqueue_size(pqueue_s *pq) {
-  pitem *item = pq->items;
-  size_t count = 0;
-
-  while (item != NULL) {
-    count++;
-    item = item->next;
-  }
-  return count;
-}
-
-piterator pqueue_iterator(pqueue_s *pq) { return pq->items; }
-
-pitem *pqueue_next(piterator *item) {
-  pitem *ret;
-
-  if (item == NULL || *item == NULL) {
-    return NULL;
-  }
-
-  ret = *item;
-  *item = (*item)->next;
-
-  return ret;
-}
-
-pitem *pqueue_insert(pqueue_s *pq, pitem *item) {
-  pitem *curr, *next;
-
-  if (pq->items == NULL) {
-    pq->items = item;
-    return item;
-  }
-
-  for (curr = NULL, next = pq->items; next != NULL;
-       curr = next, next = next->next) {
-    /* we can compare 64-bit value in big-endian encoding with memcmp. */
-    int cmp = memcmp(next->priority, item->priority, sizeof(item->priority));
-    if (cmp > 0) {
-      /* next > item */
-      item->next = next;
-
-      if (curr == NULL) {
-        pq->items = item;
-      } else {
-        curr->next = item;
-      }
-
-      return item;
-    } else if (cmp == 0) {
-      /* duplicates not allowed */
-      return NULL;
-    }
-  }
-
-  item->next = NULL;
-  curr->next = item;
-
-  return item;
-}
-
-
-pitem *pqueue_pop(pqueue_s *pq) {
-  pitem *item = pq->items;
-
-  if (pq->items != NULL) {
-    pq->items = pq->items->next;
-  }
-
-  return item;
-}
diff --git a/src/ssl/pqueue/pqueue_test.c b/src/ssl/pqueue/pqueue_test.c
deleted file mode 100644
index f76e4a3..0000000
--- a/src/ssl/pqueue/pqueue_test.c
+++ /dev/null
@@ -1,129 +0,0 @@
-/* Copyright (c) 2014, Google Inc.
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
-
-#include <stdio.h>
-#include <string.h>
-
-#include <openssl/crypto.h>
-#include <openssl/pqueue.h>
-#include <openssl/ssl.h>
-
-
-static void clear_and_free_queue(pqueue q) {
-  for (;;) {
-    pitem *item = pqueue_pop(q);
-    if (item == NULL) {
-      break;
-    }
-    pitem_free(item);
-  }
-  pqueue_free(q);
-}
-
-static int trivial(void) {
-  pqueue q = pqueue_new();
-  if (q == NULL) {
-    return 0;
-  }
-  int32_t data = 0xdeadbeef;
-  uint8_t priority[8] = {0};
-  pitem *item = pitem_new(priority, &data);
-  if (item == NULL ||
-      pqueue_insert(q, item) != item ||
-      pqueue_size(q) != 1 ||
-      pqueue_peek(q) != item ||
-      pqueue_pop(q) != item ||
-      pqueue_size(q) != 0 ||
-      pqueue_pop(q) != NULL) {
-    return 0;
-  }
-  pitem_free(item);
-  clear_and_free_queue(q);
-  return 1;
-}
-
-#define NUM_ITEMS 10
-
-static int fixed_random(void) {
-  /* Random order of 10 elements, chosen by
-   * random.choice(list(itertools.permutations(range(10)))) */
-  int ordering[NUM_ITEMS] = {9, 6, 3, 4, 0, 2, 7, 1, 8, 5};
-  int i;
-  pqueue q = pqueue_new();
-  uint8_t priority[8] = {0};
-  piterator iter;
-  pitem *curr, *item;
-
-  if (q == NULL) {
-    return 0;
-  }
-
-  /* Insert the elements */
-  for (i = 0; i < NUM_ITEMS; i++) {
-    priority[7] = ordering[i];
-    item = pitem_new(priority, &ordering[i]);
-    if (item == NULL || pqueue_insert(q, item) != item) {
-      return 0;
-    }
-  }
-
-  /* Insert the elements again. This inserts duplicates and should
-   * fail. */
-  for (i = 0; i < NUM_ITEMS; i++) {
-    priority[7] = ordering[i];
-    item = pitem_new(priority, &ordering[i]);
-    if (item == NULL || pqueue_insert(q, item) != NULL) {
-      return 0;
-    }
-    pitem_free(item);
-  }
-
-  if (pqueue_size(q) != NUM_ITEMS) {
-    return 0;
-  }
-
-  /* Iterate over the elements. */
-  iter = pqueue_iterator(q);
-  curr = pqueue_next(&iter);
-  if (curr == NULL) {
-    return 0;
-  }
-  while (1) {
-    pitem *next = pqueue_next(&iter);
-    int *curr_data, *next_data;
-
-    if (next == NULL) {
-      break;
-    }
-    curr_data = (int*)curr->data;
-    next_data = (int*)next->data;
-    if (*curr_data >= *next_data) {
-      return 0;
-    }
-    curr = next;
-  }
-  clear_and_free_queue(q);
-  return 1;
-}
-
-int main(void) {
-  CRYPTO_library_init();
-
-  if (!trivial() || !fixed_random()) {
-    return 1;
-  }
-
-  printf("PASS\n");
-  return 0;
-}
diff --git a/src/ssl/s3_both.c b/src/ssl/s3_both.c
index 01a7e8c..7ef400a 100644
--- a/src/ssl/s3_both.c
+++ b/src/ssl/s3_both.c
@@ -114,373 +114,138 @@
 
 #include <assert.h>
 #include <limits.h>
-#include <stdio.h>
 #include <string.h>
 
 #include <openssl/buf.h>
+#include <openssl/bytestring.h>
 #include <openssl/err.h>
 #include <openssl/evp.h>
 #include <openssl/mem.h>
 #include <openssl/md5.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
 #include <openssl/rand.h>
 #include <openssl/sha.h>
-#include <openssl/x509.h>
 
+#include "../crypto/internal.h"
 #include "internal.h"
 
 
-/* ssl3_do_write sends |ssl->init_buf| in records of type 'type'
- * (SSL3_RT_HANDSHAKE or SSL3_RT_CHANGE_CIPHER_SPEC). It returns -1 on error, 1
- * on success or zero if the transmission is still incomplete. */
-int ssl3_do_write(SSL *ssl, int type) {
-  int n;
-
-  n = ssl3_write_bytes(ssl, type, &ssl->init_buf->data[ssl->init_off],
-                       ssl->init_num);
-  if (n < 0) {
-    return -1;
+SSL_HANDSHAKE *ssl_handshake_new(SSL *ssl) {
+  SSL_HANDSHAKE *hs = OPENSSL_malloc(sizeof(SSL_HANDSHAKE));
+  if (hs == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+    return NULL;
   }
-
-  if (n == ssl->init_num) {
-    if (ssl->msg_callback) {
-      ssl->msg_callback(1, ssl->version, type, ssl->init_buf->data,
-                      (size_t)(ssl->init_off + ssl->init_num), ssl,
-                      ssl->msg_callback_arg);
-    }
-    return 1;
+  OPENSSL_memset(hs, 0, sizeof(SSL_HANDSHAKE));
+  hs->ssl = ssl;
+  hs->wait = ssl_hs_ok;
+  hs->state = SSL_ST_INIT;
+  if (!SSL_TRANSCRIPT_init(&hs->transcript)) {
+    ssl_handshake_free(hs);
+    return NULL;
   }
-
-  ssl->init_off += n;
-  ssl->init_num -= n;
-  return 0;
+  return hs;
 }
 
-int ssl3_send_finished(SSL *ssl, int a, int b, const char *sender, int slen) {
-  uint8_t *p;
-  int n;
-
-  if (ssl->state == a) {
-    p = ssl_handshake_start(ssl);
-
-    n = ssl->enc_method->final_finish_mac(ssl, sender, slen,
-                                          ssl->s3->tmp.finish_md);
-    if (n == 0) {
-      return 0;
-    }
-    ssl->s3->tmp.finish_md_len = n;
-    memcpy(p, ssl->s3->tmp.finish_md, n);
-
-    /* Log the master secret, if logging is enabled. */
-    if (!ssl_log_master_secret(ssl, ssl->s3->client_random, SSL3_RANDOM_SIZE,
-                               ssl->session->master_key,
-                               ssl->session->master_key_length)) {
-      return 0;
-    }
-
-    /* Copy the finished so we can use it for renegotiation checks */
-    if (ssl->server) {
-      assert(n <= EVP_MAX_MD_SIZE);
-      memcpy(ssl->s3->previous_server_finished, ssl->s3->tmp.finish_md, n);
-      ssl->s3->previous_server_finished_len = n;
-    } else {
-      assert(n <= EVP_MAX_MD_SIZE);
-      memcpy(ssl->s3->previous_client_finished, ssl->s3->tmp.finish_md, n);
-      ssl->s3->previous_client_finished_len = n;
-    }
-
-    if (!ssl_set_handshake_header(ssl, SSL3_MT_FINISHED, n)) {
-      return 0;
-    }
-    ssl->state = b;
-  }
-
-  /* SSL3_ST_SEND_xxxxxx_HELLO_B */
-  return ssl_do_write(ssl);
-}
-
-/* ssl3_take_mac calculates the Finished MAC for the handshakes messages seen
- * so far. */
-static void ssl3_take_mac(SSL *ssl) {
-  const char *sender;
-  int slen;
-
-  /* If no new cipher setup then return immediately: other functions will set
-   * the appropriate error. */
-  if (ssl->s3->tmp.new_cipher == NULL) {
+void ssl_handshake_free(SSL_HANDSHAKE *hs) {
+  if (hs == NULL) {
     return;
   }
 
-  if (ssl->state & SSL_ST_CONNECT) {
-    sender = ssl->enc_method->server_finished_label;
-    slen = ssl->enc_method->server_finished_label_len;
-  } else {
-    sender = ssl->enc_method->client_finished_label;
-    slen = ssl->enc_method->client_finished_label_len;
+  OPENSSL_cleanse(hs->secret, sizeof(hs->secret));
+  OPENSSL_cleanse(hs->early_traffic_secret, sizeof(hs->early_traffic_secret));
+  OPENSSL_cleanse(hs->client_handshake_secret,
+                  sizeof(hs->client_handshake_secret));
+  OPENSSL_cleanse(hs->server_handshake_secret,
+                  sizeof(hs->server_handshake_secret));
+  OPENSSL_cleanse(hs->client_traffic_secret_0,
+                  sizeof(hs->client_traffic_secret_0));
+  OPENSSL_cleanse(hs->server_traffic_secret_0,
+                  sizeof(hs->server_traffic_secret_0));
+  SSL_ECDH_CTX_cleanup(&hs->ecdh_ctx);
+  SSL_TRANSCRIPT_cleanup(&hs->transcript);
+  OPENSSL_free(hs->cookie);
+  OPENSSL_free(hs->key_share_bytes);
+  OPENSSL_free(hs->public_key);
+  SSL_SESSION_free(hs->new_session);
+  OPENSSL_free(hs->peer_sigalgs);
+  OPENSSL_free(hs->peer_supported_group_list);
+  OPENSSL_free(hs->peer_key);
+  OPENSSL_free(hs->server_params);
+  OPENSSL_free(hs->peer_psk_identity_hint);
+  sk_CRYPTO_BUFFER_pop_free(hs->ca_names, CRYPTO_BUFFER_free);
+  hs->ssl->ctx->x509_method->hs_flush_cached_ca_names(hs);
+  OPENSSL_free(hs->certificate_types);
+
+  if (hs->key_block != NULL) {
+    OPENSSL_cleanse(hs->key_block, hs->key_block_len);
+    OPENSSL_free(hs->key_block);
   }
 
-  ssl->s3->tmp.peer_finish_md_len = ssl->enc_method->final_finish_mac(
-      ssl, sender, slen, ssl->s3->tmp.peer_finish_md);
+  OPENSSL_free(hs->hostname);
+  EVP_PKEY_free(hs->peer_pubkey);
+  OPENSSL_free(hs);
 }
 
-int ssl3_get_finished(SSL *ssl, int a, int b) {
-  int al, finished_len, ok;
-  long message_len;
-  uint8_t *p;
-
-  message_len = ssl->method->ssl_get_message(
-      ssl, a, b, SSL3_MT_FINISHED, EVP_MAX_MD_SIZE, ssl_dont_hash_message, &ok);
-
-  if (!ok) {
-    return message_len;
-  }
-
-  /* Snapshot the finished hash before incorporating the new message. */
-  ssl3_take_mac(ssl);
-  if (!ssl3_hash_current_message(ssl)) {
-    goto err;
-  }
-
-  p = ssl->init_msg;
-  finished_len = ssl->s3->tmp.peer_finish_md_len;
-
-  if (finished_len != message_len) {
-    al = SSL_AD_DECODE_ERROR;
-    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_DIGEST_LENGTH);
-    goto f_err;
-  }
-
-  if (CRYPTO_memcmp(p, ssl->s3->tmp.peer_finish_md, finished_len) != 0) {
-    al = SSL_AD_DECRYPT_ERROR;
-    OPENSSL_PUT_ERROR(SSL, SSL_R_DIGEST_CHECK_FAILED);
-    goto f_err;
-  }
-
-  /* Copy the finished so we can use it for renegotiation checks */
-  if (ssl->server) {
-    assert(finished_len <= EVP_MAX_MD_SIZE);
-    memcpy(ssl->s3->previous_client_finished, ssl->s3->tmp.peer_finish_md,
-           finished_len);
-    ssl->s3->previous_client_finished_len = finished_len;
-  } else {
-    assert(finished_len <= EVP_MAX_MD_SIZE);
-    memcpy(ssl->s3->previous_server_finished, ssl->s3->tmp.peer_finish_md,
-           finished_len);
-    ssl->s3->previous_server_finished_len = finished_len;
-  }
-
-  return 1;
-
-f_err:
-  ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
-err:
-  return 0;
-}
-
-/* for these 2 messages, we need to
- * ssl->enc_read_ctx      re-init
- * ssl->s3->read_sequence   zero
- * ssl->s3->read_mac_secret   re-init
- * ssl->session->read_sym_enc   assign
- * ssl->session->read_compression assign
- * ssl->session->read_hash    assign */
-int ssl3_send_change_cipher_spec(SSL *ssl, int a, int b) {
-  if (ssl->state == a) {
-    *((uint8_t *)ssl->init_buf->data) = SSL3_MT_CCS;
-    ssl->init_num = 1;
-    ssl->init_off = 0;
-
-    ssl->state = b;
-  }
-
-  /* SSL3_ST_CW_CHANGE_B */
-  return ssl3_do_write(ssl, SSL3_RT_CHANGE_CIPHER_SPEC);
-}
-
-int ssl3_output_cert_chain(SSL *ssl) {
-  uint8_t *p;
-  unsigned long l = 3 + SSL_HM_HEADER_LENGTH(ssl);
-
-  if (!ssl_add_cert_chain(ssl, &l)) {
+int ssl_check_message_type(SSL *ssl, int type) {
+  if (ssl->s3->tmp.message_type != type) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+    OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
+    ERR_add_error_dataf("got type %d, wanted type %d",
+                        ssl->s3->tmp.message_type, type);
     return 0;
   }
 
-  l -= 3 + SSL_HM_HEADER_LENGTH(ssl);
-  p = ssl_handshake_start(ssl);
-  l2n3(l, p);
-  l += 3;
-  return ssl_set_handshake_header(ssl, SSL3_MT_CERTIFICATE, l);
+  return 1;
 }
 
-/* Obtain handshake message of message type |msg_type| (any if |msg_type| == -1),
- * maximum acceptable body length |max|. The first four bytes (msg_type and
- * length) are read in state |header_state|, the body is read in state
- * |body_state|. */
-long ssl3_get_message(SSL *ssl, int header_state, int body_state, int msg_type,
-                      long max, enum ssl_hash_message_t hash_message, int *ok) {
-  uint8_t *p;
-  unsigned long l;
-  long n;
-  int al;
+static int add_record_to_flight(SSL *ssl, uint8_t type, const uint8_t *in,
+                                size_t in_len) {
+  /* We'll never add a flight while in the process of writing it out. */
+  assert(ssl->s3->pending_flight_offset == 0);
 
-  if (ssl->s3->tmp.reuse_message) {
-    /* A ssl_dont_hash_message call cannot be combined with reuse_message; the
-     * ssl_dont_hash_message would have to have been applied to the previous
-     * call. */
-    assert(hash_message == ssl_hash_message);
-    ssl->s3->tmp.reuse_message = 0;
-    if (msg_type >= 0 && ssl->s3->tmp.message_type != msg_type) {
-      al = SSL_AD_UNEXPECTED_MESSAGE;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
-      goto f_err;
+  if (ssl->s3->pending_flight == NULL) {
+    ssl->s3->pending_flight = BUF_MEM_new();
+    if (ssl->s3->pending_flight == NULL) {
+      return 0;
     }
-    *ok = 1;
-    ssl->state = body_state;
-    ssl->init_msg = (uint8_t *)ssl->init_buf->data + 4;
-    ssl->init_num = (int)ssl->s3->tmp.message_size;
-    return ssl->init_num;
   }
 
-  p = (uint8_t *)ssl->init_buf->data;
-
-  if (ssl->state == header_state) {
-    assert(ssl->init_num < 4);
-
-    for (;;) {
-      while (ssl->init_num < 4) {
-        int bytes_read = ssl3_read_bytes(
-            ssl, SSL3_RT_HANDSHAKE, &p[ssl->init_num], 4 - ssl->init_num, 0);
-        if (bytes_read <= 0) {
-          *ok = 0;
-          return bytes_read;
-        }
-        ssl->init_num += bytes_read;
-      }
-
-      static const uint8_t kHelloRequest[4] = {SSL3_MT_HELLO_REQUEST, 0, 0, 0};
-      if (ssl->server || memcmp(p, kHelloRequest, sizeof(kHelloRequest)) != 0) {
-        break;
-      }
-
-      /* The server may always send 'Hello Request' messages -- we are doing
-       * a handshake anyway now, so ignore them if their format is correct.
-       * Does not count for 'Finished' MAC. */
-      ssl->init_num = 0;
-
-      if (ssl->msg_callback) {
-        ssl->msg_callback(0, ssl->version, SSL3_RT_HANDSHAKE, p, 4, ssl,
-                        ssl->msg_callback_arg);
-      }
-    }
-
-    /* ssl->init_num == 4 */
-
-    if (msg_type >= 0 && *p != msg_type) {
-      al = SSL_AD_UNEXPECTED_MESSAGE;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
-      goto f_err;
-    }
-    ssl->s3->tmp.message_type = *(p++);
-
-    n2l3(p, l);
-    if (l > (unsigned long)max) {
-      al = SSL_AD_ILLEGAL_PARAMETER;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_EXCESSIVE_MESSAGE_SIZE);
-      goto f_err;
-    }
-
-    if (l && !BUF_MEM_grow_clean(ssl->init_buf, l + 4)) {
-      OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
-      goto err;
-    }
-    ssl->s3->tmp.message_size = l;
-    ssl->state = body_state;
-
-    ssl->init_msg = (uint8_t *)ssl->init_buf->data + 4;
-    ssl->init_num = 0;
+  size_t max_out = in_len + SSL_max_seal_overhead(ssl);
+  size_t new_cap = ssl->s3->pending_flight->length + max_out;
+  if (max_out < in_len || new_cap < max_out) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
+    return 0;
   }
 
-  /* next state (body_state) */
-  p = ssl->init_msg;
-  n = ssl->s3->tmp.message_size - ssl->init_num;
-  while (n > 0) {
-    int bytes_read =
-        ssl3_read_bytes(ssl, SSL3_RT_HANDSHAKE, &p[ssl->init_num], n, 0);
-    if (bytes_read <= 0) {
-      ssl->rwstate = SSL_READING;
-      *ok = 0;
-      return bytes_read;
-    }
-    ssl->init_num += bytes_read;
-    n -= bytes_read;
+  size_t len;
+  if (!BUF_MEM_reserve(ssl->s3->pending_flight, new_cap) ||
+      !tls_seal_record(ssl, (uint8_t *)ssl->s3->pending_flight->data +
+                                ssl->s3->pending_flight->length,
+                       &len, max_out, type, in, in_len)) {
+    return 0;
   }
 
-  /* Feed this message into MAC computation. */
-  if (hash_message == ssl_hash_message && !ssl3_hash_current_message(ssl)) {
-    goto err;
-  }
-  if (ssl->msg_callback) {
-    ssl->msg_callback(0, ssl->version, SSL3_RT_HANDSHAKE, ssl->init_buf->data,
-                    (size_t)ssl->init_num + 4, ssl, ssl->msg_callback_arg);
-  }
-  *ok = 1;
-  return ssl->init_num;
-
-f_err:
-  ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
-
-err:
-  *ok = 0;
-  return -1;
+  ssl->s3->pending_flight->length += len;
+  return 1;
 }
 
-int ssl3_hash_current_message(SSL *ssl) {
-  /* The handshake header (different size between DTLS and TLS) is included in
-   * the hash. */
-  size_t header_len = ssl->init_msg - (uint8_t *)ssl->init_buf->data;
-  return ssl3_update_handshake_hash(ssl, (uint8_t *)ssl->init_buf->data,
-                                    ssl->init_num + header_len);
+int ssl3_init_message(SSL *ssl, CBB *cbb, CBB *body, uint8_t type) {
+  /* Pick a modest size hint to save most of the |realloc| calls. */
+  if (!CBB_init(cbb, 64) ||
+      !CBB_add_u8(cbb, type) ||
+      !CBB_add_u24_length_prefixed(cbb, body)) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    CBB_cleanup(cbb);
+    return 0;
+  }
+
+  return 1;
 }
 
-/* ssl3_cert_verify_hash is documented as needing EVP_MAX_MD_SIZE because that
- * is sufficient pre-TLS1.2 as well. */
-OPENSSL_COMPILE_ASSERT(EVP_MAX_MD_SIZE > MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH,
-                       combined_tls_hash_fits_in_max);
-
-int ssl3_cert_verify_hash(SSL *ssl, uint8_t *out, size_t *out_len,
-                          const EVP_MD **out_md, int pkey_type) {
-  /* For TLS v1.2 send signature algorithm and signature using
-   * agreed digest and cached handshake records. Otherwise, use
-   * SHA1 or MD5 + SHA1 depending on key type.  */
-  if (SSL_USE_SIGALGS(ssl)) {
-    EVP_MD_CTX mctx;
-    unsigned len;
-
-    EVP_MD_CTX_init(&mctx);
-    if (!EVP_DigestInit_ex(&mctx, *out_md, NULL) ||
-        !EVP_DigestUpdate(&mctx, ssl->s3->handshake_buffer->data,
-                          ssl->s3->handshake_buffer->length) ||
-        !EVP_DigestFinal(&mctx, out, &len)) {
-      OPENSSL_PUT_ERROR(SSL, ERR_R_EVP_LIB);
-      EVP_MD_CTX_cleanup(&mctx);
-      return 0;
-    }
-    *out_len = len;
-  } else if (pkey_type == EVP_PKEY_RSA) {
-    if (ssl->enc_method->cert_verify_mac(ssl, NID_md5, out) == 0 ||
-        ssl->enc_method->cert_verify_mac(ssl, NID_sha1,
-                                         out + MD5_DIGEST_LENGTH) == 0) {
-      return 0;
-    }
-    *out_len = MD5_DIGEST_LENGTH + SHA_DIGEST_LENGTH;
-    *out_md = EVP_md5_sha1();
-  } else if (pkey_type == EVP_PKEY_EC) {
-    if (ssl->enc_method->cert_verify_mac(ssl, NID_sha1, out) == 0) {
-      return 0;
-    }
-    *out_len = SHA_DIGEST_LENGTH;
-    *out_md = EVP_sha1();
-  } else {
+int ssl3_finish_message(SSL *ssl, CBB *cbb, uint8_t **out_msg,
+                        size_t *out_len) {
+  if (!CBB_finish(cbb, out_msg, out_len)) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
     return 0;
   }
@@ -488,88 +253,570 @@
   return 1;
 }
 
-int ssl_verify_alarm_type(long type) {
-  int al;
+int ssl3_add_message(SSL *ssl, uint8_t *msg, size_t len) {
+  /* Add the message to the current flight, splitting into several records if
+   * needed. */
+  int ret = 0;
+  size_t added = 0;
+  do {
+    size_t todo = len - added;
+    if (todo > ssl->max_send_fragment) {
+      todo = ssl->max_send_fragment;
+    }
 
-  switch (type) {
-    case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
-    case X509_V_ERR_UNABLE_TO_GET_CRL:
-    case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER:
-      al = SSL_AD_UNKNOWN_CA;
-      break;
+    if (!add_record_to_flight(ssl, SSL3_RT_HANDSHAKE, msg + added, todo)) {
+      goto err;
+    }
+    added += todo;
+  } while (added < len);
 
-    case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
-    case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
-    case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
-    case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
-    case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
-    case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
-    case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
-    case X509_V_ERR_CERT_NOT_YET_VALID:
-    case X509_V_ERR_CRL_NOT_YET_VALID:
-    case X509_V_ERR_CERT_UNTRUSTED:
-    case X509_V_ERR_CERT_REJECTED:
-      al = SSL_AD_BAD_CERTIFICATE;
-      break;
-
-    case X509_V_ERR_CERT_SIGNATURE_FAILURE:
-    case X509_V_ERR_CRL_SIGNATURE_FAILURE:
-      al = SSL_AD_DECRYPT_ERROR;
-      break;
-
-    case X509_V_ERR_CERT_HAS_EXPIRED:
-    case X509_V_ERR_CRL_HAS_EXPIRED:
-      al = SSL_AD_CERTIFICATE_EXPIRED;
-      break;
-
-    case X509_V_ERR_CERT_REVOKED:
-      al = SSL_AD_CERTIFICATE_REVOKED;
-      break;
-
-    case X509_V_ERR_OUT_OF_MEM:
-      al = SSL_AD_INTERNAL_ERROR;
-      break;
-
-    case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
-    case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
-    case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
-    case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
-    case X509_V_ERR_CERT_CHAIN_TOO_LONG:
-    case X509_V_ERR_PATH_LENGTH_EXCEEDED:
-    case X509_V_ERR_INVALID_CA:
-      al = SSL_AD_UNKNOWN_CA;
-      break;
-
-    case X509_V_ERR_APPLICATION_VERIFICATION:
-      al = SSL_AD_HANDSHAKE_FAILURE;
-      break;
-
-    case X509_V_ERR_INVALID_PURPOSE:
-      al = SSL_AD_UNSUPPORTED_CERTIFICATE;
-      break;
-
-    default:
-      al = SSL_AD_CERTIFICATE_UNKNOWN;
-      break;
+  ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HANDSHAKE, msg, len);
+  /* TODO(svaldez): Move this up a layer to fix abstraction for SSL_TRANSCRIPT
+   * on hs. */
+  if (ssl->s3->hs != NULL &&
+      !SSL_TRANSCRIPT_update(&ssl->s3->hs->transcript, msg, len)) {
+    goto err;
   }
+  ret = 1;
 
-  return al;
+err:
+  OPENSSL_free(msg);
+  return ret;
 }
 
-int ssl_fill_hello_random(uint8_t *out, size_t len, int is_server) {
-  if (is_server) {
-    const uint32_t current_time = time(NULL);
-    uint8_t *p = out;
+int ssl3_add_change_cipher_spec(SSL *ssl) {
+  static const uint8_t kChangeCipherSpec[1] = {SSL3_MT_CCS};
 
-    if (len < 4) {
+  if (!add_record_to_flight(ssl, SSL3_RT_CHANGE_CIPHER_SPEC, kChangeCipherSpec,
+                            sizeof(kChangeCipherSpec))) {
+    return 0;
+  }
+
+  ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_CHANGE_CIPHER_SPEC,
+                      kChangeCipherSpec, sizeof(kChangeCipherSpec));
+  return 1;
+}
+
+int ssl3_add_alert(SSL *ssl, uint8_t level, uint8_t desc) {
+  uint8_t alert[2] = {level, desc};
+  if (!add_record_to_flight(ssl, SSL3_RT_ALERT, alert, sizeof(alert))) {
+    return 0;
+  }
+
+  ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_ALERT, alert, sizeof(alert));
+  ssl_do_info_callback(ssl, SSL_CB_WRITE_ALERT, ((int)level << 8) | desc);
+  return 1;
+}
+
+int ssl_add_message_cbb(SSL *ssl, CBB *cbb) {
+  uint8_t *msg;
+  size_t len;
+  if (!ssl->method->finish_message(ssl, cbb, &msg, &len) ||
+      !ssl->method->add_message(ssl, msg, len)) {
+    return 0;
+  }
+
+  return 1;
+}
+
+int ssl3_flush_flight(SSL *ssl) {
+  if (ssl->s3->pending_flight == NULL) {
+    return 1;
+  }
+
+  if (ssl->s3->pending_flight->length > 0xffffffff ||
+      ssl->s3->pending_flight->length > INT_MAX) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    return -1;
+  }
+
+  /* The handshake flight buffer is mutually exclusive with application data.
+   *
+   * TODO(davidben): This will not be true when closure alerts use this. */
+  if (ssl_write_buffer_is_pending(ssl)) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    return -1;
+  }
+
+  /* Write the pending flight. */
+  while (ssl->s3->pending_flight_offset < ssl->s3->pending_flight->length) {
+    int ret = BIO_write(
+        ssl->wbio,
+        ssl->s3->pending_flight->data + ssl->s3->pending_flight_offset,
+        ssl->s3->pending_flight->length - ssl->s3->pending_flight_offset);
+    if (ret <= 0) {
+      ssl->rwstate = SSL_WRITING;
+      return ret;
+    }
+
+    ssl->s3->pending_flight_offset += ret;
+  }
+
+  if (BIO_flush(ssl->wbio) <= 0) {
+    ssl->rwstate = SSL_WRITING;
+    return -1;
+  }
+
+  BUF_MEM_free(ssl->s3->pending_flight);
+  ssl->s3->pending_flight = NULL;
+  ssl->s3->pending_flight_offset = 0;
+  return 1;
+}
+
+int ssl3_send_finished(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  const SSL_SESSION *session = SSL_get_session(ssl);
+
+  uint8_t finished[EVP_MAX_MD_SIZE];
+  size_t finished_len;
+  if (!SSL_TRANSCRIPT_finish_mac(&hs->transcript, finished, &finished_len,
+                                 session, ssl->server,
+                                 ssl3_protocol_version(ssl))) {
+    return 0;
+  }
+
+  /* Log the master secret, if logging is enabled. */
+  if (!ssl_log_secret(ssl, "CLIENT_RANDOM",
+                      session->master_key,
+                      session->master_key_length)) {
+    return 0;
+  }
+
+  /* Copy the Finished so we can use it for renegotiation checks. */
+  if (ssl->version != SSL3_VERSION) {
+    if (finished_len > sizeof(ssl->s3->previous_client_finished) ||
+        finished_len > sizeof(ssl->s3->previous_server_finished)) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+      return -1;
+    }
+
+    if (ssl->server) {
+      OPENSSL_memcpy(ssl->s3->previous_server_finished, finished, finished_len);
+      ssl->s3->previous_server_finished_len = finished_len;
+    } else {
+      OPENSSL_memcpy(ssl->s3->previous_client_finished, finished, finished_len);
+      ssl->s3->previous_client_finished_len = finished_len;
+    }
+  }
+
+  CBB cbb, body;
+  if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_FINISHED) ||
+      !CBB_add_bytes(&body, finished, finished_len) ||
+      !ssl_add_message_cbb(ssl, &cbb)) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    CBB_cleanup(&cbb);
+    return -1;
+  }
+
+  return 1;
+}
+
+int ssl3_get_finished(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  int ret = ssl->method->ssl_get_message(ssl);
+  if (ret <= 0) {
+    return ret;
+  }
+
+  if (!ssl_check_message_type(ssl, SSL3_MT_FINISHED)) {
+    return -1;
+  }
+
+  /* Snapshot the finished hash before incorporating the new message. */
+  uint8_t finished[EVP_MAX_MD_SIZE];
+  size_t finished_len;
+  if (!SSL_TRANSCRIPT_finish_mac(&hs->transcript, finished, &finished_len,
+                                 SSL_get_session(ssl), !ssl->server,
+                                 ssl3_protocol_version(ssl)) ||
+      !ssl_hash_current_message(hs)) {
+    return -1;
+  }
+
+  int finished_ok = ssl->init_num == finished_len &&
+                    CRYPTO_memcmp(ssl->init_msg, finished, finished_len) == 0;
+#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
+  finished_ok = 1;
+#endif
+  if (!finished_ok) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR);
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DIGEST_CHECK_FAILED);
+    return -1;
+  }
+
+  /* Copy the Finished so we can use it for renegotiation checks. */
+  if (ssl->version != SSL3_VERSION) {
+    if (finished_len > sizeof(ssl->s3->previous_client_finished) ||
+        finished_len > sizeof(ssl->s3->previous_server_finished)) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+      return -1;
+    }
+
+    if (ssl->server) {
+      OPENSSL_memcpy(ssl->s3->previous_client_finished, finished, finished_len);
+      ssl->s3->previous_client_finished_len = finished_len;
+    } else {
+      OPENSSL_memcpy(ssl->s3->previous_server_finished, finished, finished_len);
+      ssl->s3->previous_server_finished_len = finished_len;
+    }
+  }
+
+  return 1;
+}
+
+int ssl3_output_cert_chain(SSL *ssl) {
+  CBB cbb, body;
+  if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_CERTIFICATE) ||
+      !ssl_add_cert_chain(ssl, &body) ||
+      !ssl_add_message_cbb(ssl, &cbb)) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    CBB_cleanup(&cbb);
+    return 0;
+  }
+
+  return 1;
+}
+
+size_t ssl_max_handshake_message_len(const SSL *ssl) {
+  /* kMaxMessageLen is the default maximum message size for handshakes which do
+   * not accept peer certificate chains. */
+  static const size_t kMaxMessageLen = 16384;
+
+  if (SSL_in_init(ssl)) {
+    if ((!ssl->server || (ssl->verify_mode & SSL_VERIFY_PEER)) &&
+        kMaxMessageLen < ssl->max_cert_list) {
+      return ssl->max_cert_list;
+    }
+    return kMaxMessageLen;
+  }
+
+  if (ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
+    /* In TLS 1.2 and below, the largest acceptable post-handshake message is
+     * a HelloRequest. */
+    return 0;
+  }
+
+  if (ssl->server) {
+    /* The largest acceptable post-handshake message for a server is a
+     * KeyUpdate. We will never initiate post-handshake auth. */
+    return 1;
+  }
+
+  /* Clients must accept NewSessionTicket and CertificateRequest, so allow the
+   * default size. */
+  return kMaxMessageLen;
+}
+
+static int extend_handshake_buffer(SSL *ssl, size_t length) {
+  if (!BUF_MEM_reserve(ssl->init_buf, length)) {
+    return -1;
+  }
+  while (ssl->init_buf->length < length) {
+    int ret = ssl3_read_handshake_bytes(
+        ssl, (uint8_t *)ssl->init_buf->data + ssl->init_buf->length,
+        length - ssl->init_buf->length);
+    if (ret <= 0) {
+      return ret;
+    }
+    ssl->init_buf->length += (size_t)ret;
+  }
+  return 1;
+}
+
+static int read_v2_client_hello(SSL *ssl) {
+  /* Read the first 5 bytes, the size of the TLS record header. This is
+   * sufficient to detect a V2ClientHello and ensures that we never read beyond
+   * the first record. */
+  int ret = ssl_read_buffer_extend_to(ssl, SSL3_RT_HEADER_LENGTH);
+  if (ret <= 0) {
+    return ret;
+  }
+  const uint8_t *p = ssl_read_buffer(ssl);
+
+  /* Some dedicated error codes for protocol mixups should the application wish
+   * to interpret them differently. (These do not overlap with ClientHello or
+   * V2ClientHello.) */
+  if (strncmp("GET ", (const char *)p, 4) == 0 ||
+      strncmp("POST ", (const char *)p, 5) == 0 ||
+      strncmp("HEAD ", (const char *)p, 5) == 0 ||
+      strncmp("PUT ", (const char *)p, 4) == 0) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_HTTP_REQUEST);
+    return -1;
+  }
+  if (strncmp("CONNE", (const char *)p, 5) == 0) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_HTTPS_PROXY_REQUEST);
+    return -1;
+  }
+
+  if ((p[0] & 0x80) == 0 || p[2] != SSL2_MT_CLIENT_HELLO ||
+      p[3] != SSL3_VERSION_MAJOR) {
+    /* Not a V2ClientHello. */
+    return 1;
+  }
+
+  /* Determine the length of the V2ClientHello. */
+  size_t msg_length = ((p[0] & 0x7f) << 8) | p[1];
+  if (msg_length > (1024 * 4)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_RECORD_TOO_LARGE);
+    return -1;
+  }
+  if (msg_length < SSL3_RT_HEADER_LENGTH - 2) {
+    /* Reject lengths that are too short early. We have already read
+     * |SSL3_RT_HEADER_LENGTH| bytes, so we should not attempt to process an
+     * (invalid) V2ClientHello which would be shorter than that. */
+    OPENSSL_PUT_ERROR(SSL, SSL_R_RECORD_LENGTH_MISMATCH);
+    return -1;
+  }
+
+  /* Read the remainder of the V2ClientHello. */
+  ret = ssl_read_buffer_extend_to(ssl, 2 + msg_length);
+  if (ret <= 0) {
+    return ret;
+  }
+
+  CBS v2_client_hello;
+  CBS_init(&v2_client_hello, ssl_read_buffer(ssl) + 2, msg_length);
+
+  /* The V2ClientHello without the length is incorporated into the handshake
+   * hash. This is only ever called at the start of the handshake, so hs is
+   * guaranteed to be non-NULL. */
+  if (!SSL_TRANSCRIPT_update(&ssl->s3->hs->transcript,
+                             CBS_data(&v2_client_hello),
+                             CBS_len(&v2_client_hello))) {
+    return -1;
+  }
+
+  ssl_do_msg_callback(ssl, 0 /* read */, 0 /* V2ClientHello */,
+                      CBS_data(&v2_client_hello), CBS_len(&v2_client_hello));
+
+  uint8_t msg_type;
+  uint16_t version, cipher_spec_length, session_id_length, challenge_length;
+  CBS cipher_specs, session_id, challenge;
+  if (!CBS_get_u8(&v2_client_hello, &msg_type) ||
+      !CBS_get_u16(&v2_client_hello, &version) ||
+      !CBS_get_u16(&v2_client_hello, &cipher_spec_length) ||
+      !CBS_get_u16(&v2_client_hello, &session_id_length) ||
+      !CBS_get_u16(&v2_client_hello, &challenge_length) ||
+      !CBS_get_bytes(&v2_client_hello, &cipher_specs, cipher_spec_length) ||
+      !CBS_get_bytes(&v2_client_hello, &session_id, session_id_length) ||
+      !CBS_get_bytes(&v2_client_hello, &challenge, challenge_length) ||
+      CBS_len(&v2_client_hello) != 0) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    return -1;
+  }
+
+  /* msg_type has already been checked. */
+  assert(msg_type == SSL2_MT_CLIENT_HELLO);
+
+  /* The client_random is the V2ClientHello challenge. Truncate or
+   * left-pad with zeros as needed. */
+  size_t rand_len = CBS_len(&challenge);
+  if (rand_len > SSL3_RANDOM_SIZE) {
+    rand_len = SSL3_RANDOM_SIZE;
+  }
+  uint8_t random[SSL3_RANDOM_SIZE];
+  OPENSSL_memset(random, 0, SSL3_RANDOM_SIZE);
+  OPENSSL_memcpy(random + (SSL3_RANDOM_SIZE - rand_len), CBS_data(&challenge),
+                 rand_len);
+
+  /* Write out an equivalent SSLv3 ClientHello. */
+  size_t max_v3_client_hello = SSL3_HM_HEADER_LENGTH + 2 /* version */ +
+                               SSL3_RANDOM_SIZE + 1 /* session ID length */ +
+                               2 /* cipher list length */ +
+                               CBS_len(&cipher_specs) / 3 * 2 +
+                               1 /* compression length */ + 1 /* compression */;
+  CBB client_hello, hello_body, cipher_suites;
+  CBB_zero(&client_hello);
+  if (!BUF_MEM_reserve(ssl->init_buf, max_v3_client_hello) ||
+      !CBB_init_fixed(&client_hello, (uint8_t *)ssl->init_buf->data,
+                      ssl->init_buf->max) ||
+      !CBB_add_u8(&client_hello, SSL3_MT_CLIENT_HELLO) ||
+      !CBB_add_u24_length_prefixed(&client_hello, &hello_body) ||
+      !CBB_add_u16(&hello_body, version) ||
+      !CBB_add_bytes(&hello_body, random, SSL3_RANDOM_SIZE) ||
+      /* No session id. */
+      !CBB_add_u8(&hello_body, 0) ||
+      !CBB_add_u16_length_prefixed(&hello_body, &cipher_suites)) {
+    CBB_cleanup(&client_hello);
+    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+    return -1;
+  }
+
+  /* Copy the cipher suites. */
+  while (CBS_len(&cipher_specs) > 0) {
+    uint32_t cipher_spec;
+    if (!CBS_get_u24(&cipher_specs, &cipher_spec)) {
+      CBB_cleanup(&client_hello);
+      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+      return -1;
+    }
+
+    /* Skip SSLv2 ciphers. */
+    if ((cipher_spec & 0xff0000) != 0) {
+      continue;
+    }
+    if (!CBB_add_u16(&cipher_suites, cipher_spec)) {
+      CBB_cleanup(&client_hello);
+      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+      return -1;
+    }
+  }
+
+  /* Add the null compression scheme and finish. */
+  if (!CBB_add_u8(&hello_body, 1) || !CBB_add_u8(&hello_body, 0) ||
+      !CBB_finish(&client_hello, NULL, &ssl->init_buf->length)) {
+    CBB_cleanup(&client_hello);
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    return -1;
+  }
+
+  /* Consume and discard the V2ClientHello. */
+  ssl_read_buffer_consume(ssl, 2 + msg_length);
+  ssl_read_buffer_discard(ssl);
+
+  ssl->s3->is_v2_hello = 1;
+  /* This is the first message, so hs must be non-NULL. */
+  ssl->s3->hs->v2_clienthello = 1;
+  return 1;
+}
+
+int ssl3_get_message(SSL *ssl) {
+  /* Re-create the handshake buffer if needed. */
+  if (ssl->init_buf == NULL) {
+    ssl->init_buf = BUF_MEM_new();
+    if (ssl->init_buf == NULL) {
+      return -1;
+    }
+  }
+
+  if (ssl->server && !ssl->s3->v2_hello_done) {
+    /* Bypass the record layer for the first message to handle V2ClientHello. */
+    int ret = read_v2_client_hello(ssl);
+    if (ret <= 0) {
+      return ret;
+    }
+    ssl->s3->v2_hello_done = 1;
+  }
+
+  if (ssl->s3->tmp.reuse_message) {
+    /* There must be a current message. */
+    assert(ssl->init_msg != NULL);
+    ssl->s3->tmp.reuse_message = 0;
+  } else {
+    ssl3_release_current_message(ssl, 0 /* don't free buffer */);
+  }
+
+  /* Read the message header, if we haven't yet. */
+  int ret = extend_handshake_buffer(ssl, SSL3_HM_HEADER_LENGTH);
+  if (ret <= 0) {
+    return ret;
+  }
+
+  /* Parse out the length. Cap it so the peer cannot force us to buffer up to
+   * 2^24 bytes. */
+  const uint8_t *p = (uint8_t *)ssl->init_buf->data;
+  size_t msg_len = (((uint32_t)p[1]) << 16) | (((uint32_t)p[2]) << 8) | p[3];
+  if (msg_len > ssl_max_handshake_message_len(ssl)) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+    OPENSSL_PUT_ERROR(SSL, SSL_R_EXCESSIVE_MESSAGE_SIZE);
+    return -1;
+  }
+
+  /* Read the message body, if we haven't yet. */
+  ret = extend_handshake_buffer(ssl, SSL3_HM_HEADER_LENGTH + msg_len);
+  if (ret <= 0) {
+    return ret;
+  }
+
+  /* We have now received a complete message. */
+  ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_HANDSHAKE, ssl->init_buf->data,
+                      ssl->init_buf->length);
+
+  ssl->s3->tmp.message_type = ((const uint8_t *)ssl->init_buf->data)[0];
+  ssl->init_msg = (uint8_t*)ssl->init_buf->data + SSL3_HM_HEADER_LENGTH;
+  ssl->init_num = ssl->init_buf->length - SSL3_HM_HEADER_LENGTH;
+  return 1;
+}
+
+void ssl3_get_current_message(const SSL *ssl, CBS *out) {
+  CBS_init(out, (uint8_t *)ssl->init_buf->data, ssl->init_buf->length);
+}
+
+int ssl_hash_current_message(SSL_HANDSHAKE *hs) {
+  /* V2ClientHellos are hashed implicitly. */
+  if (hs->ssl->s3->is_v2_hello) {
+    return 1;
+  }
+
+  CBS cbs;
+  hs->ssl->method->get_current_message(hs->ssl, &cbs);
+  return SSL_TRANSCRIPT_update(&hs->transcript, CBS_data(&cbs), CBS_len(&cbs));
+}
+
+void ssl3_release_current_message(SSL *ssl, int free_buffer) {
+  if (ssl->init_msg != NULL) {
+    /* |init_buf| never contains data beyond the current message. */
+    assert(SSL3_HM_HEADER_LENGTH + ssl->init_num == ssl->init_buf->length);
+
+    /* Clear the current message. */
+    ssl->init_msg = NULL;
+    ssl->init_num = 0;
+    ssl->init_buf->length = 0;
+    ssl->s3->is_v2_hello = 0;
+  }
+
+  if (free_buffer) {
+    BUF_MEM_free(ssl->init_buf);
+    ssl->init_buf = NULL;
+  }
+}
+
+int ssl_parse_extensions(const CBS *cbs, uint8_t *out_alert,
+                         const SSL_EXTENSION_TYPE *ext_types,
+                         size_t num_ext_types, int ignore_unknown) {
+  /* Reset everything. */
+  for (size_t i = 0; i < num_ext_types; i++) {
+    *ext_types[i].out_present = 0;
+    CBS_init(ext_types[i].out_data, NULL, 0);
+  }
+
+  CBS copy = *cbs;
+  while (CBS_len(&copy) != 0) {
+    uint16_t type;
+    CBS data;
+    if (!CBS_get_u16(&copy, &type) ||
+        !CBS_get_u16_length_prefixed(&copy, &data)) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
+      *out_alert = SSL_AD_DECODE_ERROR;
       return 0;
     }
-    p[0] = current_time >> 24;
-    p[1] = current_time >> 16;
-    p[2] = current_time >> 8;
-    p[3] = current_time;
-    return RAND_bytes(p + 4, len - 4);
-  } else {
-    return RAND_bytes(out, len);
+
+    const SSL_EXTENSION_TYPE *ext_type = NULL;
+    for (size_t i = 0; i < num_ext_types; i++) {
+      if (type == ext_types[i].type) {
+        ext_type = &ext_types[i];
+        break;
+      }
+    }
+
+    if (ext_type == NULL) {
+      if (ignore_unknown) {
+        continue;
+      }
+      OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
+      *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
+      return 0;
+    }
+
+    /* Duplicate ext_types are forbidden. */
+    if (*ext_type->out_present) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_DUPLICATE_EXTENSION);
+      *out_alert = SSL_AD_ILLEGAL_PARAMETER;
+      return 0;
+    }
+
+    *ext_type->out_present = 1;
+    *ext_type->out_data = data;
   }
+
+  return 1;
 }
diff --git a/src/ssl/s3_clnt.c b/src/ssl/s3_clnt.c
deleted file mode 100644
index 5f68037..0000000
--- a/src/ssl/s3_clnt.c
+++ /dev/null
@@ -1,2093 +0,0 @@
-/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- * 
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to.  The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- * 
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- * 
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *    "This product includes cryptographic software written by
- *     Eric Young (eay@cryptsoft.com)"
- *    The word 'cryptographic' can be left out if the rouines from the library
- *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from 
- *    the apps directory (application code) you must include an acknowledgement:
- *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- * 
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * 
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed.  i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- */
-/* ====================================================================
- * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- *    software must display the following acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- *    endorse or promote products derived from this software without
- *    prior written permission. For written permission, please contact
- *    openssl-core@openssl.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- *    nor may "OpenSSL" appear in their names without prior written
- *    permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- *    acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- *
- * This product includes cryptographic software written by Eric Young
- * (eay@cryptsoft.com).  This product includes software written by Tim
- * Hudson (tjh@cryptsoft.com).
- *
- */
-/* ====================================================================
- * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
- *
- * Portions of the attached software ("Contribution") are developed by 
- * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
- *
- * The Contribution is licensed pursuant to the OpenSSL open source
- * license provided above.
- *
- * ECC cipher suite support in OpenSSL originally written by
- * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
- *
- */
-/* ====================================================================
- * Copyright 2005 Nokia. All rights reserved.
- *
- * The portions of the attached software ("Contribution") is developed by
- * Nokia Corporation and is licensed pursuant to the OpenSSL open source
- * license.
- *
- * The Contribution, originally written by Mika Kousa and Pasi Eronen of
- * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
- * support (see RFC 4279) to OpenSSL.
- *
- * No patent licenses or other rights except those expressly stated in
- * the OpenSSL open source license shall be deemed granted or received
- * expressly, by implication, estoppel, or otherwise.
- *
- * No assurances are provided by Nokia that the Contribution does not
- * infringe the patent or other intellectual property rights of any third
- * party or that the license provides you with all the necessary rights
- * to make use of the Contribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
- * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
- * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
- * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
- * OTHERWISE.
- */
-
-#include <openssl/ssl.h>
-
-#include <assert.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <openssl/bn.h>
-#include <openssl/buf.h>
-#include <openssl/bytestring.h>
-#include <openssl/dh.h>
-#include <openssl/ec_key.h>
-#include <openssl/ecdsa.h>
-#include <openssl/err.h>
-#include <openssl/evp.h>
-#include <openssl/md5.h>
-#include <openssl/mem.h>
-#include <openssl/obj.h>
-#include <openssl/rand.h>
-#include <openssl/x509.h>
-#include <openssl/x509v3.h>
-
-#include "internal.h"
-#include "../crypto/dh/internal.h"
-
-
-int ssl3_connect(SSL *ssl) {
-  BUF_MEM *buf = NULL;
-  void (*cb)(const SSL *ssl, int type, int value) = NULL;
-  int ret = -1;
-  int new_state, state, skip = 0;
-
-  assert(ssl->handshake_func == ssl3_connect);
-  assert(!ssl->server);
-  assert(!SSL_IS_DTLS(ssl));
-
-  ERR_clear_error();
-  ERR_clear_system_error();
-
-  if (ssl->info_callback != NULL) {
-    cb = ssl->info_callback;
-  } else if (ssl->ctx->info_callback != NULL) {
-    cb = ssl->ctx->info_callback;
-  }
-
-  ssl->in_handshake++;
-
-  for (;;) {
-    state = ssl->state;
-
-    switch (ssl->state) {
-      case SSL_ST_CONNECT:
-        if (cb != NULL) {
-          cb(ssl, SSL_CB_HANDSHAKE_START, 1);
-        }
-
-        if (ssl->init_buf == NULL) {
-          buf = BUF_MEM_new();
-          if (buf == NULL ||
-              !BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
-            ret = -1;
-            goto end;
-          }
-
-          ssl->init_buf = buf;
-          buf = NULL;
-        }
-
-        if (!ssl_init_wbio_buffer(ssl, 0)) {
-          ret = -1;
-          goto end;
-        }
-
-        /* don't push the buffering BIO quite yet */
-
-        if (!ssl3_init_handshake_buffer(ssl)) {
-          OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-          ret = -1;
-          goto end;
-        }
-
-        ssl->state = SSL3_ST_CW_CLNT_HELLO_A;
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_CW_CLNT_HELLO_A:
-      case SSL3_ST_CW_CLNT_HELLO_B:
-        ssl->shutdown = 0;
-        ret = ssl3_send_client_hello(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        ssl->state = SSL3_ST_CR_SRVR_HELLO_A;
-        ssl->init_num = 0;
-
-        /* turn on buffering for the next lot of output */
-        if (ssl->bbio != ssl->wbio) {
-          ssl->wbio = BIO_push(ssl->bbio, ssl->wbio);
-        }
-
-        break;
-
-      case SSL3_ST_CR_SRVR_HELLO_A:
-      case SSL3_ST_CR_SRVR_HELLO_B:
-        ret = ssl3_get_server_hello(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-
-        if (ssl->hit) {
-          ssl->state = SSL3_ST_CR_CHANGE;
-          if (ssl->tlsext_ticket_expected) {
-            /* receive renewed session ticket */
-            ssl->state = SSL3_ST_CR_SESSION_TICKET_A;
-          }
-        } else {
-          ssl->state = SSL3_ST_CR_CERT_A;
-        }
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_CR_CERT_A:
-      case SSL3_ST_CR_CERT_B:
-        if (ssl_cipher_has_server_public_key(ssl->s3->tmp.new_cipher)) {
-          ret = ssl3_get_server_certificate(ssl);
-          if (ret <= 0) {
-            goto end;
-          }
-          if (ssl->s3->tmp.certificate_status_expected) {
-            ssl->state = SSL3_ST_CR_CERT_STATUS_A;
-          } else {
-            ssl->state = SSL3_ST_VERIFY_SERVER_CERT;
-          }
-        } else {
-          skip = 1;
-          ssl->state = SSL3_ST_CR_KEY_EXCH_A;
-        }
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_VERIFY_SERVER_CERT:
-        ret = ssl3_verify_server_cert(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-
-        ssl->state = SSL3_ST_CR_KEY_EXCH_A;
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_CR_KEY_EXCH_A:
-      case SSL3_ST_CR_KEY_EXCH_B:
-        ret = ssl3_get_server_key_exchange(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        ssl->state = SSL3_ST_CR_CERT_REQ_A;
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_CR_CERT_REQ_A:
-      case SSL3_ST_CR_CERT_REQ_B:
-        ret = ssl3_get_certificate_request(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        ssl->state = SSL3_ST_CR_SRVR_DONE_A;
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_CR_SRVR_DONE_A:
-      case SSL3_ST_CR_SRVR_DONE_B:
-        ret = ssl3_get_server_done(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        if (ssl->s3->tmp.cert_req) {
-          ssl->state = SSL3_ST_CW_CERT_A;
-        } else {
-          ssl->state = SSL3_ST_CW_KEY_EXCH_A;
-        }
-        ssl->init_num = 0;
-
-        break;
-
-      case SSL3_ST_CW_CERT_A:
-      case SSL3_ST_CW_CERT_B:
-      case SSL3_ST_CW_CERT_C:
-      case SSL3_ST_CW_CERT_D:
-        ret = ssl3_send_client_certificate(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        ssl->state = SSL3_ST_CW_KEY_EXCH_A;
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_CW_KEY_EXCH_A:
-      case SSL3_ST_CW_KEY_EXCH_B:
-        ret = ssl3_send_client_key_exchange(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        /* For TLS, cert_req is set to 2, so a cert chain
-         * of nothing is sent, but no verify packet is sent */
-        if (ssl->s3->tmp.cert_req == 1) {
-          ssl->state = SSL3_ST_CW_CERT_VRFY_A;
-        } else {
-          ssl->state = SSL3_ST_CW_CHANGE_A;
-        }
-
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_CW_CERT_VRFY_A:
-      case SSL3_ST_CW_CERT_VRFY_B:
-      case SSL3_ST_CW_CERT_VRFY_C:
-        ret = ssl3_send_cert_verify(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        ssl->state = SSL3_ST_CW_CHANGE_A;
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_CW_CHANGE_A:
-      case SSL3_ST_CW_CHANGE_B:
-        ret = ssl3_send_change_cipher_spec(ssl, SSL3_ST_CW_CHANGE_A,
-                                           SSL3_ST_CW_CHANGE_B);
-        if (ret <= 0) {
-          goto end;
-        }
-
-        ssl->state = SSL3_ST_CW_FINISHED_A;
-        if (ssl->s3->tlsext_channel_id_valid) {
-          ssl->state = SSL3_ST_CW_CHANNEL_ID_A;
-        }
-        if (ssl->s3->next_proto_neg_seen) {
-          ssl->state = SSL3_ST_CW_NEXT_PROTO_A;
-        }
-        ssl->init_num = 0;
-
-        ssl->session->cipher = ssl->s3->tmp.new_cipher;
-        if (!ssl->enc_method->setup_key_block(ssl) ||
-            !ssl->enc_method->change_cipher_state(
-                ssl, SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
-          ret = -1;
-          goto end;
-        }
-
-        break;
-
-      case SSL3_ST_CW_NEXT_PROTO_A:
-      case SSL3_ST_CW_NEXT_PROTO_B:
-        ret = ssl3_send_next_proto(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-
-        if (ssl->s3->tlsext_channel_id_valid) {
-          ssl->state = SSL3_ST_CW_CHANNEL_ID_A;
-        } else {
-          ssl->state = SSL3_ST_CW_FINISHED_A;
-        }
-        break;
-
-      case SSL3_ST_CW_CHANNEL_ID_A:
-      case SSL3_ST_CW_CHANNEL_ID_B:
-        ret = ssl3_send_channel_id(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        ssl->state = SSL3_ST_CW_FINISHED_A;
-        break;
-
-      case SSL3_ST_CW_FINISHED_A:
-      case SSL3_ST_CW_FINISHED_B:
-        ret = ssl3_send_finished(ssl, SSL3_ST_CW_FINISHED_A,
-                                 SSL3_ST_CW_FINISHED_B,
-                                 ssl->enc_method->client_finished_label,
-                                 ssl->enc_method->client_finished_label_len);
-        if (ret <= 0) {
-          goto end;
-        }
-        ssl->state = SSL3_ST_CW_FLUSH;
-
-        if (ssl->hit) {
-          ssl->s3->tmp.next_state = SSL_ST_OK;
-        } else {
-          /* This is a non-resumption handshake. If it involves ChannelID, then
-           * record the handshake hashes at this point in the session so that
-           * any resumption of this session with ChannelID can sign those
-           * hashes. */
-          ret = tls1_record_handshake_hashes_for_channel_id(ssl);
-          if (ret <= 0) {
-            goto end;
-          }
-          if ((SSL_get_mode(ssl) & SSL_MODE_ENABLE_FALSE_START) &&
-              ssl3_can_false_start(ssl) &&
-              /* No False Start on renegotiation (would complicate the state
-               * machine). */
-              !ssl->s3->initial_handshake_complete) {
-            ssl->s3->tmp.next_state = SSL3_ST_FALSE_START;
-          } else {
-            /* Allow NewSessionTicket if ticket expected */
-            if (ssl->tlsext_ticket_expected) {
-              ssl->s3->tmp.next_state = SSL3_ST_CR_SESSION_TICKET_A;
-            } else {
-              ssl->s3->tmp.next_state = SSL3_ST_CR_CHANGE;
-            }
-          }
-        }
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_CR_SESSION_TICKET_A:
-      case SSL3_ST_CR_SESSION_TICKET_B:
-        ret = ssl3_get_new_session_ticket(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        ssl->state = SSL3_ST_CR_CHANGE;
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_CR_CERT_STATUS_A:
-      case SSL3_ST_CR_CERT_STATUS_B:
-        ret = ssl3_get_cert_status(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        ssl->state = SSL3_ST_VERIFY_SERVER_CERT;
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_CR_CHANGE:
-        ret = ssl->method->ssl_read_change_cipher_spec(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-
-        if (!ssl3_do_change_cipher_spec(ssl)) {
-          ret = -1;
-          goto end;
-        }
-        ssl->state = SSL3_ST_CR_FINISHED_A;
-        break;
-
-      case SSL3_ST_CR_FINISHED_A:
-      case SSL3_ST_CR_FINISHED_B:
-        ret = ssl3_get_finished(ssl, SSL3_ST_CR_FINISHED_A,
-                                SSL3_ST_CR_FINISHED_B);
-        if (ret <= 0) {
-          goto end;
-        }
-
-        if (ssl->hit) {
-          ssl->state = SSL3_ST_CW_CHANGE_A;
-        } else {
-          ssl->state = SSL_ST_OK;
-        }
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_CW_FLUSH:
-        ssl->rwstate = SSL_WRITING;
-        if (BIO_flush(ssl->wbio) <= 0) {
-          ret = -1;
-          goto end;
-        }
-        ssl->rwstate = SSL_NOTHING;
-        ssl->state = ssl->s3->tmp.next_state;
-        break;
-
-      case SSL3_ST_FALSE_START:
-        /* Allow NewSessionTicket if ticket expected */
-        if (ssl->tlsext_ticket_expected) {
-          ssl->state = SSL3_ST_CR_SESSION_TICKET_A;
-        } else {
-          ssl->state = SSL3_ST_CR_CHANGE;
-        }
-        ssl->s3->tmp.in_false_start = 1;
-
-        ssl_free_wbio_buffer(ssl);
-        ret = 1;
-        goto end;
-
-      case SSL_ST_OK:
-        /* clean a few things up */
-        ssl3_cleanup_key_block(ssl);
-
-        BUF_MEM_free(ssl->init_buf);
-        ssl->init_buf = NULL;
-
-        /* Remove write buffering now. */
-        ssl_free_wbio_buffer(ssl);
-
-        const int is_initial_handshake = !ssl->s3->initial_handshake_complete;
-
-        ssl->init_num = 0;
-        ssl->s3->tmp.in_false_start = 0;
-        ssl->s3->initial_handshake_complete = 1;
-
-        if (is_initial_handshake) {
-          /* Renegotiations do not participate in session resumption. */
-          ssl_update_cache(ssl, SSL_SESS_CACHE_CLIENT);
-        }
-
-        ret = 1;
-        /* ssl->server=0; */
-
-        if (cb != NULL) {
-          cb(ssl, SSL_CB_HANDSHAKE_DONE, 1);
-        }
-
-        goto end;
-
-      default:
-        OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_STATE);
-        ret = -1;
-        goto end;
-    }
-
-    if (!ssl->s3->tmp.reuse_message && !skip) {
-      if (cb != NULL && ssl->state != state) {
-        new_state = ssl->state;
-        ssl->state = state;
-        cb(ssl, SSL_CB_CONNECT_LOOP, 1);
-        ssl->state = new_state;
-      }
-    }
-    skip = 0;
-  }
-
-end:
-  ssl->in_handshake--;
-  BUF_MEM_free(buf);
-  if (cb != NULL) {
-    cb(ssl, SSL_CB_CONNECT_EXIT, ret);
-  }
-  return ret;
-}
-
-static int ssl3_write_client_cipher_list(SSL *ssl, CBB *out) {
-  /* Prepare disabled cipher masks. */
-  ssl_set_client_disabled(ssl);
-
-  CBB child;
-  if (!CBB_add_u16_length_prefixed(out, &child)) {
-    return 0;
-  }
-
-  STACK_OF(SSL_CIPHER) *ciphers = SSL_get_ciphers(ssl);
-
-  int any_enabled = 0;
-  size_t i;
-  for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) {
-    const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(ciphers, i);
-    /* Skip disabled ciphers */
-    if ((cipher->algorithm_mkey & ssl->cert->mask_k) ||
-        (cipher->algorithm_auth & ssl->cert->mask_a)) {
-      continue;
-    }
-    if (SSL_CIPHER_get_min_version(cipher) >
-        ssl3_version_from_wire(ssl, ssl->client_version)) {
-      continue;
-    }
-    any_enabled = 1;
-    if (!CBB_add_u16(&child, ssl_cipher_get_value(cipher))) {
-      return 0;
-    }
-  }
-
-  /* If all ciphers were disabled, return the error to the caller. */
-  if (!any_enabled) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CIPHERS_AVAILABLE);
-    return 0;
-  }
-
-  /* For SSLv3, the SCSV is added. Otherwise the renegotiation extension is
-   * added. */
-  if (ssl->client_version == SSL3_VERSION &&
-      !ssl->s3->initial_handshake_complete) {
-    if (!CBB_add_u16(&child, SSL3_CK_SCSV & 0xffff)) {
-      return 0;
-    }
-    /* The renegotiation extension is required to be at index zero. */
-    ssl->s3->tmp.extensions.sent |= (1u << 0);
-  }
-
-  if ((ssl->mode & SSL_MODE_SEND_FALLBACK_SCSV) &&
-      !CBB_add_u16(&child, SSL3_CK_FALLBACK_SCSV & 0xffff)) {
-    return 0;
-  }
-
-  return CBB_flush(out);
-}
-
-int ssl3_send_client_hello(SSL *ssl) {
-  if (ssl->state == SSL3_ST_CW_CLNT_HELLO_B) {
-    return ssl_do_write(ssl);
-  }
-
-  /* In DTLS, reset the handshake buffer each time a new ClientHello is
-   * assembled. We may send multiple if we receive HelloVerifyRequest. */
-  if (SSL_IS_DTLS(ssl) && !ssl3_init_handshake_buffer(ssl)) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    return -1;
-  }
-
-  CBB cbb;
-  CBB_zero(&cbb);
-
-  assert(ssl->state == SSL3_ST_CW_CLNT_HELLO_A);
-  if (!ssl->s3->have_version) {
-    uint16_t max_version = ssl3_get_max_client_version(ssl);
-    /* Disabling all versions is silly: return an error. */
-    if (max_version == 0) {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SSL_VERSION);
-      goto err;
-    }
-
-    ssl->version = max_version;
-    /* Only set |ssl->client_version| on the initial handshake. Renegotiations,
-     * although locked to a version, reuse the value. When using the plain RSA
-     * key exchange, the ClientHello version is checked in the premaster secret.
-     * Some servers fail when this value changes. */
-    ssl->client_version = max_version;
-  }
-
-  /* If the configured session has expired or was created at a version higher
-   * than our maximum version, drop it. */
-  if (ssl->session != NULL &&
-      (ssl->session->session_id_length == 0 || ssl->session->not_resumable ||
-       ssl->session->timeout < (long)(time(NULL) - ssl->session->time) ||
-       (!SSL_IS_DTLS(ssl) && ssl->session->ssl_version > ssl->version) ||
-       (SSL_IS_DTLS(ssl) && ssl->session->ssl_version < ssl->version))) {
-    SSL_set_session(ssl, NULL);
-  }
-
-  /* If resending the ClientHello in DTLS after a HelloVerifyRequest, don't
-   * renegerate the client_random. The random must be reused. */
-  if ((!SSL_IS_DTLS(ssl) || !ssl->d1->send_cookie) &&
-      !ssl_fill_hello_random(ssl->s3->client_random,
-                             sizeof(ssl->s3->client_random), 0 /* client */)) {
-    goto err;
-  }
-
-  /* Renegotiations do not participate in session resumption. */
-  int has_session = ssl->session != NULL &&
-                    !ssl->s3->initial_handshake_complete;
-
-  CBB child;
-  if (!CBB_init_fixed(&cbb, ssl_handshake_start(ssl),
-                      ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl)) ||
-      !CBB_add_u16(&cbb, ssl->client_version) ||
-      !CBB_add_bytes(&cbb, ssl->s3->client_random, SSL3_RANDOM_SIZE) ||
-      !CBB_add_u8_length_prefixed(&cbb, &child) ||
-      (has_session &&
-       !CBB_add_bytes(&child, ssl->session->session_id,
-                      ssl->session->session_id_length))) {
-    goto err;
-  }
-
-  if (SSL_IS_DTLS(ssl)) {
-    if (!CBB_add_u8_length_prefixed(&cbb, &child) ||
-        !CBB_add_bytes(&child, ssl->d1->cookie, ssl->d1->cookie_len)) {
-      goto err;
-    }
-  }
-
-  size_t length;
-  if (!ssl3_write_client_cipher_list(ssl, &cbb) ||
-      !CBB_add_u8(&cbb, 1 /* one compression method */) ||
-      !CBB_add_u8(&cbb, 0 /* null compression */) ||
-      !ssl_add_clienthello_tlsext(ssl, &cbb,
-                                  CBB_len(&cbb) + SSL_HM_HEADER_LENGTH(ssl)) ||
-      !CBB_finish(&cbb, NULL, &length) ||
-      !ssl_set_handshake_header(ssl, SSL3_MT_CLIENT_HELLO, length)) {
-    goto err;
-  }
-
-  ssl->state = SSL3_ST_CW_CLNT_HELLO_B;
-  return ssl_do_write(ssl);
-
-err:
-  CBB_cleanup(&cbb);
-  return -1;
-}
-
-int ssl3_get_server_hello(SSL *ssl) {
-  STACK_OF(SSL_CIPHER) *sk;
-  const SSL_CIPHER *c;
-  CERT *ct = ssl->cert;
-  int al = SSL_AD_INTERNAL_ERROR, ok;
-  long n;
-  CBS server_hello, server_random, session_id;
-  uint16_t server_version, cipher_suite;
-  uint8_t compression_method;
-
-  n = ssl->method->ssl_get_message(ssl, SSL3_ST_CR_SRVR_HELLO_A,
-                                 SSL3_ST_CR_SRVR_HELLO_B, SSL3_MT_SERVER_HELLO,
-                                 20000, /* ?? */
-                                 ssl_hash_message, &ok);
-
-  if (!ok) {
-    uint32_t err = ERR_peek_error();
-    if (ERR_GET_LIB(err) == ERR_LIB_SSL &&
-        ERR_GET_REASON(err) == SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE) {
-      /* Add a dedicated error code to the queue for a handshake_failure alert
-       * in response to ClientHello. This matches NSS's client behavior and
-       * gives a better error on a (probable) failure to negotiate initial
-       * parameters. Note: this error code comes after the original one.
-       *
-       * See https://crbug.com/446505. */
-      OPENSSL_PUT_ERROR(SSL, SSL_R_HANDSHAKE_FAILURE_ON_CLIENT_HELLO);
-    }
-    return n;
-  }
-
-  CBS_init(&server_hello, ssl->init_msg, n);
-
-  if (!CBS_get_u16(&server_hello, &server_version) ||
-      !CBS_get_bytes(&server_hello, &server_random, SSL3_RANDOM_SIZE) ||
-      !CBS_get_u8_length_prefixed(&server_hello, &session_id) ||
-      CBS_len(&session_id) > SSL3_SESSION_ID_SIZE ||
-      !CBS_get_u16(&server_hello, &cipher_suite) ||
-      !CBS_get_u8(&server_hello, &compression_method)) {
-    al = SSL_AD_DECODE_ERROR;
-    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
-    goto f_err;
-  }
-
-  assert(ssl->s3->have_version == ssl->s3->initial_handshake_complete);
-  if (!ssl->s3->have_version) {
-    if (!ssl3_is_version_enabled(ssl, server_version)) {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL);
-      ssl->version = server_version;
-      /* Mark the version as fixed so the record-layer version is not clamped
-       * to TLS 1.0. */
-      ssl->s3->have_version = 1;
-      al = SSL_AD_PROTOCOL_VERSION;
-      goto f_err;
-    }
-    ssl->version = server_version;
-    ssl->enc_method = ssl3_get_enc_method(server_version);
-    assert(ssl->enc_method != NULL);
-    /* At this point, the connection's version is known and ssl->version is
-     * fixed. Begin enforcing the record-layer version. */
-    ssl->s3->have_version = 1;
-  } else if (server_version != ssl->version) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SSL_VERSION);
-    al = SSL_AD_PROTOCOL_VERSION;
-    goto f_err;
-  }
-
-  /* Copy over the server random. */
-  memcpy(ssl->s3->server_random, CBS_data(&server_random), SSL3_RANDOM_SIZE);
-
-  assert(ssl->session == NULL || ssl->session->session_id_length > 0);
-  if (!ssl->s3->initial_handshake_complete && ssl->session != NULL &&
-      CBS_mem_equal(&session_id, ssl->session->session_id,
-                    ssl->session->session_id_length)) {
-    if (ssl->sid_ctx_length != ssl->session->sid_ctx_length ||
-        memcmp(ssl->session->sid_ctx, ssl->sid_ctx, ssl->sid_ctx_length)) {
-      /* actually a client application bug */
-      al = SSL_AD_ILLEGAL_PARAMETER;
-      OPENSSL_PUT_ERROR(SSL,
-                        SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
-      goto f_err;
-    }
-    ssl->hit = 1;
-  } else {
-    /* The session wasn't resumed. Create a fresh SSL_SESSION to
-     * fill out. */
-    ssl->hit = 0;
-    if (!ssl_get_new_session(ssl, 0 /* client */)) {
-      goto f_err;
-    }
-    /* Note: session_id could be empty. */
-    ssl->session->session_id_length = CBS_len(&session_id);
-    memcpy(ssl->session->session_id, CBS_data(&session_id),
-           CBS_len(&session_id));
-  }
-
-  c = SSL_get_cipher_by_value(cipher_suite);
-  if (c == NULL) {
-    /* unknown cipher */
-    al = SSL_AD_ILLEGAL_PARAMETER;
-    OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CIPHER_RETURNED);
-    goto f_err;
-  }
-  /* If the cipher is disabled then we didn't sent it in the ClientHello, so if
-   * the server selected it, it's an error. */
-  if ((c->algorithm_mkey & ct->mask_k) || (c->algorithm_auth & ct->mask_a) ||
-      SSL_CIPHER_get_min_version(c) >
-          ssl3_version_from_wire(ssl, ssl->version)) {
-    al = SSL_AD_ILLEGAL_PARAMETER;
-    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED);
-    goto f_err;
-  }
-
-  sk = ssl_get_ciphers_by_id(ssl);
-  if (!sk_SSL_CIPHER_find(sk, NULL, c)) {
-    /* we did not say we would use this cipher */
-    al = SSL_AD_ILLEGAL_PARAMETER;
-    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED);
-    goto f_err;
-  }
-
-  if (ssl->hit) {
-    if (ssl->session->cipher != c) {
-      al = SSL_AD_ILLEGAL_PARAMETER;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED);
-      goto f_err;
-    }
-    if (ssl->session->ssl_version != ssl->version) {
-      al = SSL_AD_ILLEGAL_PARAMETER;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_OLD_SESSION_VERSION_NOT_RETURNED);
-      goto f_err;
-    }
-  }
-  ssl->s3->tmp.new_cipher = c;
-
-  /* Now that the cipher is known, initialize the handshake hash. */
-  if (!ssl3_init_handshake_hash(ssl)) {
-    goto f_err;
-  }
-
-  /* If doing a full handshake with TLS 1.2, the server may request a client
-   * certificate which requires hashing the handshake transcript under a
-   * different hash. Otherwise, the handshake buffer may be released. */
-  if (!SSL_USE_SIGALGS(ssl) || ssl->hit) {
-    ssl3_free_handshake_buffer(ssl);
-  }
-
-  /* Only the NULL compression algorithm is supported. */
-  if (compression_method != 0) {
-    al = SSL_AD_ILLEGAL_PARAMETER;
-    OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
-    goto f_err;
-  }
-
-  /* TLS extensions */
-  if (!ssl_parse_serverhello_tlsext(ssl, &server_hello)) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
-    goto err;
-  }
-
-  /* There should be nothing left over in the record. */
-  if (CBS_len(&server_hello) != 0) {
-    /* wrong packet length */
-    al = SSL_AD_DECODE_ERROR;
-    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_PACKET_LENGTH);
-    goto f_err;
-  }
-
-  if (ssl->hit &&
-      ssl->s3->tmp.extended_master_secret !=
-          ssl->session->extended_master_secret) {
-    al = SSL_AD_HANDSHAKE_FAILURE;
-    if (ssl->session->extended_master_secret) {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION);
-    } else {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_RESUMED_NON_EMS_SESSION_WITH_EMS_EXTENSION);
-    }
-    goto f_err;
-  }
-
-  return 1;
-
-f_err:
-  ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
-err:
-  return -1;
-}
-
-/* ssl3_check_leaf_certificate returns one if |leaf| is a suitable leaf server
- * certificate for |ssl|. Otherwise, it returns zero and pushes an error on the
- * error queue. */
-static int ssl3_check_leaf_certificate(SSL *ssl, X509 *leaf) {
-  int ret = 0;
-  EVP_PKEY *pkey = X509_get_pubkey(leaf);
-  if (pkey == NULL) {
-    goto err;
-  }
-
-  /* Check the certificate's type matches the cipher. */
-  const SSL_CIPHER *cipher = ssl->s3->tmp.new_cipher;
-  int expected_type = ssl_cipher_get_key_type(cipher);
-  assert(expected_type != EVP_PKEY_NONE);
-  if (pkey->type != expected_type) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CERTIFICATE_TYPE);
-    goto err;
-  }
-
-  if (cipher->algorithm_auth & SSL_aECDSA) {
-    /* TODO(davidben): This behavior is preserved from upstream. Should key
-     * usages be checked in other cases as well? */
-    /* This call populates the ex_flags field correctly */
-    X509_check_purpose(leaf, -1, 0);
-    if ((leaf->ex_flags & EXFLAG_KUSAGE) &&
-        !(leaf->ex_kusage & X509v3_KU_DIGITAL_SIGNATURE)) {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_ECC_CERT_NOT_FOR_SIGNING);
-      goto err;
-    }
-
-    if (!tls1_check_ec_cert(ssl, leaf)) {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECC_CERT);
-      goto err;
-    }
-  }
-
-  ret = 1;
-
-err:
-  EVP_PKEY_free(pkey);
-  return ret;
-}
-
-int ssl3_get_server_certificate(SSL *ssl) {
-  int al, ok, ret = -1;
-  unsigned long n;
-  X509 *x = NULL;
-  STACK_OF(X509) *sk = NULL;
-  EVP_PKEY *pkey = NULL;
-  CBS cbs, certificate_list;
-  const uint8_t *data;
-
-  n = ssl->method->ssl_get_message(ssl, SSL3_ST_CR_CERT_A, SSL3_ST_CR_CERT_B,
-                                 SSL3_MT_CERTIFICATE, (long)ssl->max_cert_list,
-                                 ssl_hash_message, &ok);
-
-  if (!ok) {
-    return n;
-  }
-
-  CBS_init(&cbs, ssl->init_msg, n);
-
-  sk = sk_X509_new_null();
-  if (sk == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-    goto err;
-  }
-
-  if (!CBS_get_u24_length_prefixed(&cbs, &certificate_list) ||
-      CBS_len(&certificate_list) == 0 ||
-      CBS_len(&cbs) != 0) {
-    al = SSL_AD_DECODE_ERROR;
-    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
-    goto f_err;
-  }
-
-  while (CBS_len(&certificate_list) > 0) {
-    CBS certificate;
-    if (!CBS_get_u24_length_prefixed(&certificate_list, &certificate)) {
-      al = SSL_AD_DECODE_ERROR;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_LENGTH_MISMATCH);
-      goto f_err;
-    }
-    /* A u24 length cannot overflow a long. */
-    data = CBS_data(&certificate);
-    x = d2i_X509(NULL, &data, (long)CBS_len(&certificate));
-    if (x == NULL) {
-      al = SSL_AD_BAD_CERTIFICATE;
-      OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
-      goto f_err;
-    }
-    if (data != CBS_data(&certificate) + CBS_len(&certificate)) {
-      al = SSL_AD_DECODE_ERROR;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_LENGTH_MISMATCH);
-      goto f_err;
-    }
-    if (!sk_X509_push(sk, x)) {
-      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      goto err;
-    }
-    x = NULL;
-  }
-
-  X509 *leaf = sk_X509_value(sk, 0);
-  if (!ssl3_check_leaf_certificate(ssl, leaf)) {
-    al = SSL_AD_ILLEGAL_PARAMETER;
-    goto f_err;
-  }
-
-  /* NOTE: Unlike the server half, the client's copy of |cert_chain| includes
-   * the leaf. */
-  sk_X509_pop_free(ssl->session->cert_chain, X509_free);
-  ssl->session->cert_chain = sk;
-  sk = NULL;
-
-  X509_free(ssl->session->peer);
-  ssl->session->peer = X509_up_ref(leaf);
-
-  ssl->session->verify_result = ssl->verify_result;
-
-  ret = 1;
-
-  if (0) {
-  f_err:
-    ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
-  }
-
-err:
-  EVP_PKEY_free(pkey);
-  X509_free(x);
-  sk_X509_pop_free(sk, X509_free);
-  return ret;
-}
-
-int ssl3_get_server_key_exchange(SSL *ssl) {
-  EVP_MD_CTX md_ctx;
-  int al, ok;
-  long n, alg_k, alg_a;
-  EVP_PKEY *pkey = NULL;
-  const EVP_MD *md = NULL;
-  DH *dh = NULL;
-  EC_KEY *ecdh = NULL;
-  EC_POINT *srvr_ecpoint = NULL;
-  CBS server_key_exchange, server_key_exchange_orig, parameter;
-
-  /* use same message size as in ssl3_get_certificate_request() as
-   * ServerKeyExchange message may be skipped */
-  n = ssl->method->ssl_get_message(ssl, SSL3_ST_CR_KEY_EXCH_A,
-                                 SSL3_ST_CR_KEY_EXCH_B, -1, ssl->max_cert_list,
-                                 ssl_hash_message, &ok);
-  if (!ok) {
-    return n;
-  }
-
-  if (ssl->s3->tmp.message_type != SSL3_MT_SERVER_KEY_EXCHANGE) {
-    if (ssl_cipher_requires_server_key_exchange(ssl->s3->tmp.new_cipher)) {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
-      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
-      return -1;
-    }
-
-    /* In plain PSK ciphersuite, ServerKeyExchange may be omitted to send no
-     * identity hint. */
-    if (ssl->s3->tmp.new_cipher->algorithm_auth & SSL_aPSK) {
-      /* TODO(davidben): This should be reset in one place with the rest of the
-       * handshake state. */
-      OPENSSL_free(ssl->s3->tmp.peer_psk_identity_hint);
-      ssl->s3->tmp.peer_psk_identity_hint = NULL;
-    }
-    ssl->s3->tmp.reuse_message = 1;
-    return 1;
-  }
-
-  /* Retain a copy of the original CBS to compute the signature over. */
-  CBS_init(&server_key_exchange, ssl->init_msg, n);
-  server_key_exchange_orig = server_key_exchange;
-
-  alg_k = ssl->s3->tmp.new_cipher->algorithm_mkey;
-  alg_a = ssl->s3->tmp.new_cipher->algorithm_auth;
-  EVP_MD_CTX_init(&md_ctx);
-
-  if (alg_a & SSL_aPSK) {
-    CBS psk_identity_hint;
-
-    /* Each of the PSK key exchanges begins with a psk_identity_hint. */
-    if (!CBS_get_u16_length_prefixed(&server_key_exchange,
-                                     &psk_identity_hint)) {
-      al = SSL_AD_DECODE_ERROR;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
-      goto f_err;
-    }
-
-    /* Store PSK identity hint for later use, hint is used in
-     * ssl3_send_client_key_exchange.  Assume that the maximum length of a PSK
-     * identity hint can be as long as the maximum length of a PSK identity.
-     * Also do not allow NULL characters; identities are saved as C strings.
-     *
-     * TODO(davidben): Should invalid hints be ignored? It's a hint rather than
-     * a specific identity. */
-    if (CBS_len(&psk_identity_hint) > PSK_MAX_IDENTITY_LEN ||
-        CBS_contains_zero_byte(&psk_identity_hint)) {
-      al = SSL_AD_HANDSHAKE_FAILURE;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG);
-      goto f_err;
-    }
-
-    /* Save the identity hint as a C string. */
-    if (!CBS_strdup(&psk_identity_hint, &ssl->s3->tmp.peer_psk_identity_hint)) {
-      al = SSL_AD_INTERNAL_ERROR;
-      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      goto f_err;
-    }
-  }
-
-  if (alg_k & SSL_kDHE) {
-    CBS dh_p, dh_g, dh_Ys;
-    if (!CBS_get_u16_length_prefixed(&server_key_exchange, &dh_p) ||
-        CBS_len(&dh_p) == 0 ||
-        !CBS_get_u16_length_prefixed(&server_key_exchange, &dh_g) ||
-        CBS_len(&dh_g) == 0 ||
-        !CBS_get_u16_length_prefixed(&server_key_exchange, &dh_Ys) ||
-        CBS_len(&dh_Ys) == 0) {
-      al = SSL_AD_DECODE_ERROR;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
-      goto f_err;
-    }
-
-    dh = DH_new();
-    if (dh == NULL) {
-      goto err;
-    }
-
-    dh->p = BN_bin2bn(CBS_data(&dh_p), CBS_len(&dh_p), NULL);
-    dh->g = BN_bin2bn(CBS_data(&dh_g), CBS_len(&dh_g), NULL);
-    if (dh->p == NULL || dh->g == NULL) {
-      goto err;
-    }
-
-    ssl->session->key_exchange_info = DH_num_bits(dh);
-    if (ssl->session->key_exchange_info < 1024) {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_DH_P_LENGTH);
-      goto err;
-    } else if (ssl->session->key_exchange_info > 4096) {
-      /* Overly large DHE groups are prohibitively expensive, so enforce a limit
-       * to prevent a server from causing us to perform too expensive of a
-       * computation. */
-      OPENSSL_PUT_ERROR(SSL, SSL_R_DH_P_TOO_LONG);
-      goto err;
-    }
-
-    SSL_ECDH_CTX_init_for_dhe(&ssl->s3->tmp.ecdh_ctx, dh);
-    dh = NULL;
-
-    /* Save the peer public key for later. */
-    size_t peer_key_len;
-    if (!CBS_stow(&dh_Ys, &ssl->s3->tmp.peer_key, &peer_key_len)) {
-      goto err;
-    }
-    /* |dh_Ys| has a u16 length prefix, so this fits in a |uint16_t|. */
-    assert(sizeof(ssl->s3->tmp.peer_key_len) == 2 && peer_key_len <= 0xffff);
-    ssl->s3->tmp.peer_key_len = (uint16_t)peer_key_len;
-  } else if (alg_k & SSL_kECDHE) {
-    /* Parse the server parameters. */
-    uint8_t curve_type;
-    uint16_t curve_id;
-    CBS point;
-    if (!CBS_get_u8(&server_key_exchange, &curve_type) ||
-        curve_type != NAMED_CURVE_TYPE ||
-        !CBS_get_u16(&server_key_exchange, &curve_id) ||
-        !CBS_get_u8_length_prefixed(&server_key_exchange, &point)) {
-      al = SSL_AD_DECODE_ERROR;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
-      goto f_err;
-    }
-    ssl->session->key_exchange_info = curve_id;
-
-    /* Ensure the curve is consistent with preferences. */
-    if (!tls1_check_curve_id(ssl, curve_id)) {
-      al = SSL_AD_ILLEGAL_PARAMETER;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
-      goto f_err;
-    }
-
-    /* Initialize ECDH and save the peer public key for later. */
-    size_t peer_key_len;
-    if (!SSL_ECDH_CTX_init(&ssl->s3->tmp.ecdh_ctx, curve_id) ||
-        !CBS_stow(&point, &ssl->s3->tmp.peer_key, &peer_key_len)) {
-      goto err;
-    }
-    /* |point| has a u8 length prefix, so this fits in a |uint16_t|. */
-    assert(sizeof(ssl->s3->tmp.peer_key_len) == 2 && peer_key_len <= 0xffff);
-    ssl->s3->tmp.peer_key_len = (uint16_t)peer_key_len;
-  } else if (!(alg_k & SSL_kPSK)) {
-    al = SSL_AD_UNEXPECTED_MESSAGE;
-    OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
-    goto f_err;
-  }
-
-  /* At this point, |server_key_exchange| contains the signature, if any, while
-   * |server_key_exchange_orig| contains the entire message. From that, derive
-   * a CBS containing just the parameter. */
-  CBS_init(&parameter, CBS_data(&server_key_exchange_orig),
-           CBS_len(&server_key_exchange_orig) - CBS_len(&server_key_exchange));
-
-  /* ServerKeyExchange should be signed by the server's public key. */
-  if (ssl_cipher_has_server_public_key(ssl->s3->tmp.new_cipher)) {
-    pkey = X509_get_pubkey(ssl->session->peer);
-    if (pkey == NULL) {
-      goto err;
-    }
-
-    if (SSL_USE_SIGALGS(ssl)) {
-      uint8_t hash, signature;
-      if (!CBS_get_u8(&server_key_exchange, &hash) ||
-          !CBS_get_u8(&server_key_exchange, &signature)) {
-        al = SSL_AD_DECODE_ERROR;
-        OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
-        goto f_err;
-      }
-      if (!tls12_check_peer_sigalg(ssl, &md, &al, hash, signature, pkey)) {
-        goto f_err;
-      }
-      ssl->s3->tmp.server_key_exchange_hash = hash;
-    } else if (pkey->type == EVP_PKEY_RSA) {
-      md = EVP_md5_sha1();
-    } else {
-      md = EVP_sha1();
-    }
-
-    /* The last field in |server_key_exchange| is the signature. */
-    CBS signature;
-    if (!CBS_get_u16_length_prefixed(&server_key_exchange, &signature) ||
-        CBS_len(&server_key_exchange) != 0) {
-      al = SSL_AD_DECODE_ERROR;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
-      goto f_err;
-    }
-
-    if (!EVP_DigestVerifyInit(&md_ctx, NULL, md, NULL, pkey) ||
-        !EVP_DigestVerifyUpdate(&md_ctx, ssl->s3->client_random,
-                                SSL3_RANDOM_SIZE) ||
-        !EVP_DigestVerifyUpdate(&md_ctx, ssl->s3->server_random,
-                                SSL3_RANDOM_SIZE) ||
-        !EVP_DigestVerifyUpdate(&md_ctx, CBS_data(&parameter),
-                                CBS_len(&parameter)) ||
-        !EVP_DigestVerifyFinal(&md_ctx, CBS_data(&signature),
-                               CBS_len(&signature))) {
-      /* bad signature */
-      al = SSL_AD_DECRYPT_ERROR;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SIGNATURE);
-      goto f_err;
-    }
-  } else {
-    /* PSK ciphers are the only supported certificate-less ciphers. */
-    assert(alg_a == SSL_aPSK);
-
-    if (CBS_len(&server_key_exchange) > 0) {
-      al = SSL_AD_DECODE_ERROR;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_EXTRA_DATA_IN_MESSAGE);
-      goto f_err;
-    }
-  }
-  EVP_PKEY_free(pkey);
-  EVP_MD_CTX_cleanup(&md_ctx);
-  return 1;
-
-f_err:
-  ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
-err:
-  EVP_PKEY_free(pkey);
-  DH_free(dh);
-  EC_POINT_free(srvr_ecpoint);
-  EC_KEY_free(ecdh);
-  EVP_MD_CTX_cleanup(&md_ctx);
-  return -1;
-}
-
-static int ca_dn_cmp(const X509_NAME **a, const X509_NAME **b) {
-  return X509_NAME_cmp(*a, *b);
-}
-
-int ssl3_get_certificate_request(SSL *ssl) {
-  int ok, ret = 0;
-  unsigned long n;
-  X509_NAME *xn = NULL;
-  STACK_OF(X509_NAME) *ca_sk = NULL;
-  CBS cbs;
-  CBS certificate_types;
-  CBS certificate_authorities;
-  const uint8_t *data;
-
-  n = ssl->method->ssl_get_message(ssl, SSL3_ST_CR_CERT_REQ_A,
-                                 SSL3_ST_CR_CERT_REQ_B, -1, ssl->max_cert_list,
-                                 ssl_hash_message, &ok);
-
-  if (!ok) {
-    return n;
-  }
-
-  ssl->s3->tmp.cert_req = 0;
-
-  if (ssl->s3->tmp.message_type == SSL3_MT_SERVER_DONE) {
-    ssl->s3->tmp.reuse_message = 1;
-    /* If we get here we don't need the handshake buffer as we won't be doing
-     * client auth. */
-    ssl3_free_handshake_buffer(ssl);
-    return 1;
-  }
-
-  if (ssl->s3->tmp.message_type != SSL3_MT_CERTIFICATE_REQUEST) {
-    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
-    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_MESSAGE_TYPE);
-    goto err;
-  }
-
-  CBS_init(&cbs, ssl->init_msg, n);
-
-  ca_sk = sk_X509_NAME_new(ca_dn_cmp);
-  if (ca_sk == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-    goto err;
-  }
-
-  /* get the certificate types */
-  if (!CBS_get_u8_length_prefixed(&cbs, &certificate_types)) {
-    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
-    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
-    goto err;
-  }
-
-  if (!CBS_stow(&certificate_types, &ssl->s3->tmp.certificate_types,
-                &ssl->s3->tmp.num_certificate_types)) {
-    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-    goto err;
-  }
-
-  if (SSL_USE_SIGALGS(ssl)) {
-    CBS supported_signature_algorithms;
-    if (!CBS_get_u16_length_prefixed(&cbs, &supported_signature_algorithms) ||
-        !tls1_parse_peer_sigalgs(ssl, &supported_signature_algorithms)) {
-      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
-      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
-      goto err;
-    }
-  }
-
-  /* get the CA RDNs */
-  if (!CBS_get_u16_length_prefixed(&cbs, &certificate_authorities)) {
-    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
-    OPENSSL_PUT_ERROR(SSL, SSL_R_LENGTH_MISMATCH);
-    goto err;
-  }
-
-  while (CBS_len(&certificate_authorities) > 0) {
-    CBS distinguished_name;
-    if (!CBS_get_u16_length_prefixed(&certificate_authorities,
-                                     &distinguished_name)) {
-      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
-      OPENSSL_PUT_ERROR(SSL, SSL_R_CA_DN_TOO_LONG);
-      goto err;
-    }
-
-    data = CBS_data(&distinguished_name);
-
-    /* A u16 length cannot overflow a long. */
-    xn = d2i_X509_NAME(NULL, &data, (long)CBS_len(&distinguished_name));
-    if (xn == NULL) {
-      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
-      OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
-      goto err;
-    }
-
-    if (!CBS_skip(&distinguished_name, data - CBS_data(&distinguished_name))) {
-      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
-      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-      goto err;
-    }
-
-    if (CBS_len(&distinguished_name) != 0) {
-      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
-      OPENSSL_PUT_ERROR(SSL, SSL_R_CA_DN_LENGTH_MISMATCH);
-      goto err;
-    }
-
-    if (!sk_X509_NAME_push(ca_sk, xn)) {
-      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      goto err;
-    }
-  }
-
-  /* we should setup a certificate to return.... */
-  ssl->s3->tmp.cert_req = 1;
-  sk_X509_NAME_pop_free(ssl->s3->tmp.ca_names, X509_NAME_free);
-  ssl->s3->tmp.ca_names = ca_sk;
-  ca_sk = NULL;
-
-  ret = 1;
-
-err:
-  sk_X509_NAME_pop_free(ca_sk, X509_NAME_free);
-  return ret;
-}
-
-int ssl3_get_new_session_ticket(SSL *ssl) {
-  int ok, al;
-  long n = ssl->method->ssl_get_message(
-      ssl, SSL3_ST_CR_SESSION_TICKET_A, SSL3_ST_CR_SESSION_TICKET_B,
-      SSL3_MT_NEWSESSION_TICKET, 16384, ssl_hash_message, &ok);
-
-  if (!ok) {
-    return n;
-  }
-
-  CBS new_session_ticket, ticket;
-  uint32_t ticket_lifetime_hint;
-  CBS_init(&new_session_ticket, ssl->init_msg, n);
-  if (!CBS_get_u32(&new_session_ticket, &ticket_lifetime_hint) ||
-      !CBS_get_u16_length_prefixed(&new_session_ticket, &ticket) ||
-      CBS_len(&new_session_ticket) != 0) {
-    al = SSL_AD_DECODE_ERROR;
-    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
-    goto f_err;
-  }
-
-  if (CBS_len(&ticket) == 0) {
-    /* RFC 5077 allows a server to change its mind and send no ticket after
-     * negotiating the extension. The value of |tlsext_ticket_expected| is
-     * checked in |ssl_update_cache| so is cleared here to avoid an unnecessary
-     * update. */
-    ssl->tlsext_ticket_expected = 0;
-    return 1;
-  }
-
-  if (ssl->hit) {
-    /* The server is sending a new ticket for an existing session. Sessions are
-     * immutable once established, so duplicate all but the ticket of the
-     * existing session. */
-    uint8_t *bytes;
-    size_t bytes_len;
-    if (!SSL_SESSION_to_bytes_for_ticket(ssl->session, &bytes, &bytes_len)) {
-      goto err;
-    }
-    SSL_SESSION *new_session = SSL_SESSION_from_bytes(bytes, bytes_len);
-    OPENSSL_free(bytes);
-    if (new_session == NULL) {
-      /* This should never happen. */
-      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-      goto err;
-    }
-
-    SSL_SESSION_free(ssl->session);
-    ssl->session = new_session;
-  }
-
-  if (!CBS_stow(&ticket, &ssl->session->tlsext_tick,
-                &ssl->session->tlsext_ticklen)) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-    goto err;
-  }
-  ssl->session->tlsext_tick_lifetime_hint = ticket_lifetime_hint;
-
-  /* Generate a session ID for this session based on the session ticket. We use
-   * the session ID mechanism for detecting ticket resumption. This also fits in
-   * with assumptions elsewhere in OpenSSL.*/
-  if (!EVP_Digest(CBS_data(&ticket), CBS_len(&ticket), ssl->session->session_id,
-                  &ssl->session->session_id_length, EVP_sha256(), NULL)) {
-    goto err;
-  }
-
-  return 1;
-
-f_err:
-  ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
-err:
-  return -1;
-}
-
-int ssl3_get_cert_status(SSL *ssl) {
-  int ok, al;
-  long n;
-  CBS certificate_status, ocsp_response;
-  uint8_t status_type;
-
-  n = ssl->method->ssl_get_message(
-      ssl, SSL3_ST_CR_CERT_STATUS_A, SSL3_ST_CR_CERT_STATUS_B,
-      -1, 16384, ssl_hash_message, &ok);
-
-  if (!ok) {
-    return n;
-  }
-
-  if (ssl->s3->tmp.message_type != SSL3_MT_CERTIFICATE_STATUS) {
-    /* A server may send status_request in ServerHello and then change
-     * its mind about sending CertificateStatus. */
-    ssl->s3->tmp.reuse_message = 1;
-    return 1;
-  }
-
-  CBS_init(&certificate_status, ssl->init_msg, n);
-  if (!CBS_get_u8(&certificate_status, &status_type) ||
-      status_type != TLSEXT_STATUSTYPE_ocsp ||
-      !CBS_get_u24_length_prefixed(&certificate_status, &ocsp_response) ||
-      CBS_len(&ocsp_response) == 0 ||
-      CBS_len(&certificate_status) != 0) {
-    al = SSL_AD_DECODE_ERROR;
-    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
-    goto f_err;
-  }
-
-  if (!CBS_stow(&ocsp_response, &ssl->session->ocsp_response,
-                &ssl->session->ocsp_response_length)) {
-    al = SSL_AD_INTERNAL_ERROR;
-    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-    goto f_err;
-  }
-  return 1;
-
-f_err:
-  ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
-  return -1;
-}
-
-int ssl3_get_server_done(SSL *ssl) {
-  int ok;
-  long n;
-
-  n = ssl->method->ssl_get_message(ssl, SSL3_ST_CR_SRVR_DONE_A,
-                                 SSL3_ST_CR_SRVR_DONE_B, SSL3_MT_SERVER_DONE,
-                                 30, /* should be very small, like 0 :-) */
-                                 ssl_hash_message, &ok);
-
-  if (!ok) {
-    return n;
-  }
-
-  if (n > 0) {
-    /* should contain no data */
-    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
-    OPENSSL_PUT_ERROR(SSL, SSL_R_LENGTH_MISMATCH);
-    return -1;
-  }
-
-  return 1;
-}
-
-OPENSSL_COMPILE_ASSERT(sizeof(size_t) >= sizeof(unsigned),
-                       SIZE_T_IS_SMALLER_THAN_UNSIGNED);
-
-int ssl3_send_client_key_exchange(SSL *ssl) {
-  if (ssl->state == SSL3_ST_CW_KEY_EXCH_B) {
-    return ssl_do_write(ssl);
-  }
-  assert(ssl->state == SSL3_ST_CW_KEY_EXCH_A);
-
-  uint8_t *pms = NULL;
-  size_t pms_len = 0;
-  CBB cbb;
-  if (!CBB_init_fixed(&cbb, ssl_handshake_start(ssl),
-                      ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl))) {
-    goto err;
-  }
-
-  uint32_t alg_k = ssl->s3->tmp.new_cipher->algorithm_mkey;
-  uint32_t alg_a = ssl->s3->tmp.new_cipher->algorithm_auth;
-
-  /* If using a PSK key exchange, prepare the pre-shared key. */
-  unsigned psk_len = 0;
-  uint8_t psk[PSK_MAX_PSK_LEN];
-  if (alg_a & SSL_aPSK) {
-    if (ssl->psk_client_callback == NULL) {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_NO_CLIENT_CB);
-      goto err;
-    }
-
-    char identity[PSK_MAX_IDENTITY_LEN + 1];
-    memset(identity, 0, sizeof(identity));
-    psk_len = ssl->psk_client_callback(
-        ssl, ssl->s3->tmp.peer_psk_identity_hint, identity, sizeof(identity),
-        psk, sizeof(psk));
-    if (psk_len == 0) {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_NOT_FOUND);
-      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
-      goto err;
-    }
-    assert(psk_len <= PSK_MAX_PSK_LEN);
-
-    OPENSSL_free(ssl->session->psk_identity);
-    ssl->session->psk_identity = BUF_strdup(identity);
-    if (ssl->session->psk_identity == NULL) {
-      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      goto err;
-    }
-
-    /* Write out psk_identity. */
-    CBB child;
-    if (!CBB_add_u16_length_prefixed(&cbb, &child) ||
-        !CBB_add_bytes(&child, (const uint8_t *)identity,
-                       OPENSSL_strnlen(identity, sizeof(identity))) ||
-        !CBB_flush(&cbb)) {
-      goto err;
-    }
-  }
-
-  /* Depending on the key exchange method, compute |pms| and |pms_len|. */
-  if (alg_k & SSL_kRSA) {
-    pms_len = SSL_MAX_MASTER_KEY_LENGTH;
-    pms = OPENSSL_malloc(pms_len);
-    if (pms == NULL) {
-      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      goto err;
-    }
-
-    EVP_PKEY *pkey = X509_get_pubkey(ssl->session->peer);
-    if (pkey == NULL) {
-      goto err;
-    }
-
-    RSA *rsa = EVP_PKEY_get0_RSA(pkey);
-    if (rsa == NULL) {
-      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-      EVP_PKEY_free(pkey);
-      goto err;
-    }
-
-    ssl->session->key_exchange_info = EVP_PKEY_bits(pkey);
-    EVP_PKEY_free(pkey);
-
-    pms[0] = ssl->client_version >> 8;
-    pms[1] = ssl->client_version & 0xff;
-    if (!RAND_bytes(&pms[2], SSL_MAX_MASTER_KEY_LENGTH - 2)) {
-      goto err;
-    }
-
-    CBB child, *enc_pms = &cbb;
-    size_t enc_pms_len;
-    /* In TLS, there is a length prefix. */
-    if (ssl->version > SSL3_VERSION) {
-      if (!CBB_add_u16_length_prefixed(&cbb, &child)) {
-        goto err;
-      }
-      enc_pms = &child;
-    }
-
-    uint8_t *ptr;
-    if (!CBB_reserve(enc_pms, &ptr, RSA_size(rsa)) ||
-        !RSA_encrypt(rsa, &enc_pms_len, ptr, RSA_size(rsa), pms, pms_len,
-                     RSA_PKCS1_PADDING) ||
-        /* Log the premaster secret, if logging is enabled. */
-        !ssl_log_rsa_client_key_exchange(ssl, ptr, enc_pms_len, pms, pms_len) ||
-        !CBB_did_write(enc_pms, enc_pms_len) ||
-        !CBB_flush(&cbb)) {
-      goto err;
-    }
-  } else if (alg_k & (SSL_kECDHE|SSL_kDHE)) {
-    /* Generate a keypair and serialize the public half. ECDHE uses a u8 length
-     * prefix while DHE uses u16. */
-    CBB child;
-    int child_ok;
-    if (alg_k & SSL_kECDHE) {
-      child_ok = CBB_add_u8_length_prefixed(&cbb, &child);
-    } else {
-      child_ok = CBB_add_u16_length_prefixed(&cbb, &child);
-    }
-
-    if (!child_ok ||
-        !SSL_ECDH_CTX_generate_keypair(&ssl->s3->tmp.ecdh_ctx, &child) ||
-        !CBB_flush(&cbb)) {
-      goto err;
-    }
-
-    /* Compute the premaster. */
-    uint8_t alert;
-    if (!SSL_ECDH_CTX_compute_secret(&ssl->s3->tmp.ecdh_ctx, &pms, &pms_len,
-                                     &alert, ssl->s3->tmp.peer_key,
-                                     ssl->s3->tmp.peer_key_len)) {
-      ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
-      goto err;
-    }
-
-    /* The key exchange state may now be discarded. */
-    SSL_ECDH_CTX_cleanup(&ssl->s3->tmp.ecdh_ctx);
-    OPENSSL_free(ssl->s3->tmp.peer_key);
-    ssl->s3->tmp.peer_key = NULL;
-  } else if (alg_k & SSL_kPSK) {
-    /* For plain PSK, other_secret is a block of 0s with the same length as
-     * the pre-shared key. */
-    pms_len = psk_len;
-    pms = OPENSSL_malloc(pms_len);
-    if (pms == NULL) {
-      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      goto err;
-    }
-    memset(pms, 0, pms_len);
-  } else {
-    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
-    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    goto err;
-  }
-
-  /* For a PSK cipher suite, other_secret is combined with the pre-shared
-   * key. */
-  if (alg_a & SSL_aPSK) {
-    CBB pms_cbb, child;
-    uint8_t *new_pms;
-    size_t new_pms_len;
-
-    CBB_zero(&pms_cbb);
-    if (!CBB_init(&pms_cbb, 2 + psk_len + 2 + pms_len) ||
-        !CBB_add_u16_length_prefixed(&pms_cbb, &child) ||
-        !CBB_add_bytes(&child, pms, pms_len) ||
-        !CBB_add_u16_length_prefixed(&pms_cbb, &child) ||
-        !CBB_add_bytes(&child, psk, psk_len) ||
-        !CBB_finish(&pms_cbb, &new_pms, &new_pms_len)) {
-      CBB_cleanup(&pms_cbb);
-      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      goto err;
-    }
-    OPENSSL_cleanse(pms, pms_len);
-    OPENSSL_free(pms);
-    pms = new_pms;
-    pms_len = new_pms_len;
-  }
-
-  /* The message must be added to the finished hash before calculating the
-   * master secret. */
-  size_t length;
-  if (!CBB_finish(&cbb, NULL, &length) ||
-      !ssl_set_handshake_header(ssl, SSL3_MT_CLIENT_KEY_EXCHANGE, length)) {
-    goto err;
-  }
-  ssl->state = SSL3_ST_CW_KEY_EXCH_B;
-
-  ssl->session->master_key_length = ssl->enc_method->generate_master_secret(
-      ssl, ssl->session->master_key, pms, pms_len);
-  if (ssl->session->master_key_length == 0) {
-    goto err;
-  }
-  ssl->session->extended_master_secret = ssl->s3->tmp.extended_master_secret;
-  OPENSSL_cleanse(pms, pms_len);
-  OPENSSL_free(pms);
-
-  /* SSL3_ST_CW_KEY_EXCH_B */
-  return ssl_do_write(ssl);
-
-err:
-  if (pms != NULL) {
-    OPENSSL_cleanse(pms, pms_len);
-    OPENSSL_free(pms);
-  }
-  return -1;
-}
-
-int ssl3_send_cert_verify(SSL *ssl) {
-  if (ssl->state == SSL3_ST_CW_CERT_VRFY_C) {
-    return ssl_do_write(ssl);
-  }
-
-  CBB cbb, child;
-  if (!CBB_init_fixed(&cbb, ssl_handshake_start(ssl),
-                      ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl))) {
-    goto err;
-  }
-
-  assert(ssl_has_private_key(ssl));
-
-  const size_t max_sig_len = ssl_private_key_max_signature_len(ssl);
-  size_t sig_len;
-  enum ssl_private_key_result_t sign_result;
-  if (ssl->state == SSL3_ST_CW_CERT_VRFY_A) {
-    /* Select and write out the digest type in TLS 1.2. */
-    const EVP_MD *md = NULL;
-    if (SSL_USE_SIGALGS(ssl)) {
-      md = tls1_choose_signing_digest(ssl);
-      if (!tls12_add_sigandhash(ssl, &cbb, md)) {
-        OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-        goto err;
-      }
-    }
-
-    /* Compute the digest. In TLS 1.1 and below, the digest type is also
-     * selected here. */
-    uint8_t digest[EVP_MAX_MD_SIZE];
-    size_t digest_len;
-    if (!ssl3_cert_verify_hash(ssl, digest, &digest_len, &md,
-                               ssl_private_key_type(ssl))) {
-      goto err;
-    }
-
-    /* The handshake buffer is no longer necessary. */
-    ssl3_free_handshake_buffer(ssl);
-
-    /* Sign the digest. */
-    uint8_t *ptr;
-    if (!CBB_add_u16_length_prefixed(&cbb, &child) ||
-        !CBB_reserve(&child, &ptr, max_sig_len)) {
-      goto err;
-    }
-    sign_result = ssl_private_key_sign(ssl, ptr, &sig_len, max_sig_len, md,
-                                       digest, digest_len);
-  } else {
-    assert(ssl->state == SSL3_ST_CW_CERT_VRFY_B);
-
-    /* Skip over the already written signature algorithm and retry the
-     * signature. */
-    uint8_t *ptr;
-    if ((SSL_USE_SIGALGS(ssl) && !CBB_did_write(&cbb, 2)) ||
-        !CBB_add_u16_length_prefixed(&cbb, &child) ||
-        !CBB_reserve(&child, &ptr, max_sig_len)) {
-      goto err;
-    }
-    sign_result =
-        ssl_private_key_sign_complete(ssl, ptr, &sig_len, max_sig_len);
-  }
-
-  switch (sign_result) {
-    case ssl_private_key_success:
-      ssl->rwstate = SSL_NOTHING;
-      break;
-    case ssl_private_key_failure:
-      ssl->rwstate = SSL_NOTHING;
-      goto err;
-    case ssl_private_key_retry:
-      ssl->rwstate = SSL_PRIVATE_KEY_OPERATION;
-      ssl->state = SSL3_ST_CW_CERT_VRFY_B;
-      goto err;
-  }
-
-  size_t length;
-  if (!CBB_did_write(&child, sig_len) ||
-      !CBB_finish(&cbb, NULL, &length) ||
-      !ssl_set_handshake_header(ssl, SSL3_MT_CERTIFICATE_VERIFY, length)) {
-    goto err;
-  }
-
-  ssl->state = SSL3_ST_CW_CERT_VRFY_C;
-  return ssl_do_write(ssl);
-
-err:
-  CBB_cleanup(&cbb);
-  return -1;
-}
-
-/* ssl3_has_client_certificate returns true if a client certificate is
- * configured. */
-static int ssl3_has_client_certificate(SSL *ssl) {
-  return ssl->cert && ssl->cert->x509 && ssl_has_private_key(ssl);
-}
-
-int ssl3_send_client_certificate(SSL *ssl) {
-  X509 *x509 = NULL;
-  EVP_PKEY *pkey = NULL;
-  int i;
-
-  if (ssl->state == SSL3_ST_CW_CERT_A) {
-    /* Let cert callback update client certificates if required */
-    if (ssl->cert->cert_cb) {
-      i = ssl->cert->cert_cb(ssl, ssl->cert->cert_cb_arg);
-      if (i < 0) {
-        ssl->rwstate = SSL_X509_LOOKUP;
-        return -1;
-      }
-      if (i == 0) {
-        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-        return 0;
-      }
-      ssl->rwstate = SSL_NOTHING;
-    }
-
-    if (ssl3_has_client_certificate(ssl)) {
-      ssl->state = SSL3_ST_CW_CERT_C;
-    } else {
-      ssl->state = SSL3_ST_CW_CERT_B;
-    }
-  }
-
-  /* We need to get a client cert */
-  if (ssl->state == SSL3_ST_CW_CERT_B) {
-    /* If we get an error, we need to:
-     *   ssl->rwstate=SSL_X509_LOOKUP; return(-1);
-     * We then get retried later */
-    i = ssl_do_client_cert_cb(ssl, &x509, &pkey);
-    if (i < 0) {
-      ssl->rwstate = SSL_X509_LOOKUP;
-      return -1;
-    }
-    ssl->rwstate = SSL_NOTHING;
-    if (i == 1 && pkey != NULL && x509 != NULL) {
-      ssl->state = SSL3_ST_CW_CERT_B;
-      if (!SSL_use_certificate(ssl, x509) || !SSL_use_PrivateKey(ssl, pkey)) {
-        i = 0;
-      }
-    } else if (i == 1) {
-      i = 0;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_DATA_RETURNED_BY_CALLBACK);
-    }
-
-    X509_free(x509);
-    EVP_PKEY_free(pkey);
-    if (i && !ssl3_has_client_certificate(ssl)) {
-      i = 0;
-    }
-    if (i == 0) {
-      if (ssl->version == SSL3_VERSION) {
-        ssl->s3->tmp.cert_req = 0;
-        ssl3_send_alert(ssl, SSL3_AL_WARNING, SSL_AD_NO_CERTIFICATE);
-        return 1;
-      } else {
-        ssl->s3->tmp.cert_req = 2;
-        /* There is no client certificate, so the handshake buffer may be
-         * released. */
-        ssl3_free_handshake_buffer(ssl);
-      }
-    }
-
-    /* Ok, we have a cert */
-    ssl->state = SSL3_ST_CW_CERT_C;
-  }
-
-  if (ssl->state == SSL3_ST_CW_CERT_C) {
-    if (ssl->s3->tmp.cert_req == 2) {
-      /* Send an empty Certificate message. */
-      uint8_t *p = ssl_handshake_start(ssl);
-      l2n3(0, p);
-      if (!ssl_set_handshake_header(ssl, SSL3_MT_CERTIFICATE, 3)) {
-        return -1;
-      }
-    } else if (!ssl3_output_cert_chain(ssl)) {
-      return -1;
-    }
-    ssl->state = SSL3_ST_CW_CERT_D;
-  }
-
-  /* SSL3_ST_CW_CERT_D */
-  return ssl_do_write(ssl);
-}
-
-int ssl3_send_next_proto(SSL *ssl) {
-  if (ssl->state == SSL3_ST_CW_NEXT_PROTO_B) {
-    return ssl_do_write(ssl);
-  }
-
-  assert(ssl->state == SSL3_ST_CW_NEXT_PROTO_A);
-
-  static const uint8_t kZero[32] = {0};
-  size_t padding_len = 32 - ((ssl->next_proto_negotiated_len + 2) % 32);
-
-  CBB cbb, child;
-  size_t length;
-  CBB_zero(&cbb);
-  if (!CBB_init_fixed(&cbb, ssl_handshake_start(ssl),
-                      ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl)) ||
-      !CBB_add_u8_length_prefixed(&cbb, &child) ||
-      !CBB_add_bytes(&child, ssl->next_proto_negotiated,
-                     ssl->next_proto_negotiated_len) ||
-      !CBB_add_u8_length_prefixed(&cbb, &child) ||
-      !CBB_add_bytes(&child, kZero, padding_len) ||
-      !CBB_finish(&cbb, NULL, &length) ||
-      !ssl_set_handshake_header(ssl, SSL3_MT_NEXT_PROTO, length)) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    CBB_cleanup(&cbb);
-    return -1;
-  }
-
-  ssl->state = SSL3_ST_CW_NEXT_PROTO_B;
-  return ssl_do_write(ssl);
-}
-
-int ssl3_send_channel_id(SSL *ssl) {
-  if (ssl->state == SSL3_ST_CW_CHANNEL_ID_B) {
-    return ssl_do_write(ssl);
-  }
-
-  assert(ssl->state == SSL3_ST_CW_CHANNEL_ID_A);
-
-  if (ssl->tlsext_channel_id_private == NULL &&
-      ssl->ctx->channel_id_cb != NULL) {
-    EVP_PKEY *key = NULL;
-    ssl->ctx->channel_id_cb(ssl, &key);
-    if (key != NULL &&
-        !SSL_set1_tls_channel_id(ssl, key)) {
-      EVP_PKEY_free(key);
-      return -1;
-    }
-    EVP_PKEY_free(key);
-  }
-
-  if (ssl->tlsext_channel_id_private == NULL) {
-    ssl->rwstate = SSL_CHANNEL_ID_LOOKUP;
-    return -1;
-  }
-  ssl->rwstate = SSL_NOTHING;
-
-  EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(ssl->tlsext_channel_id_private);
-  if (ec_key == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    return -1;
-  }
-
-  int ret = -1;
-  BIGNUM *x = BN_new();
-  BIGNUM *y = BN_new();
-  ECDSA_SIG *sig = NULL;
-  if (x == NULL || y == NULL ||
-      !EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec_key),
-                                           EC_KEY_get0_public_key(ec_key),
-                                           x, y, NULL)) {
-    goto err;
-  }
-
-  uint8_t digest[EVP_MAX_MD_SIZE];
-  size_t digest_len;
-  if (!tls1_channel_id_hash(ssl, digest, &digest_len)) {
-    goto err;
-  }
-
-  sig = ECDSA_do_sign(digest, digest_len, ec_key);
-  if (sig == NULL) {
-    goto err;
-  }
-
-  CBB cbb, child;
-  size_t length;
-  CBB_zero(&cbb);
-  if (!CBB_init_fixed(&cbb, ssl_handshake_start(ssl),
-                      ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl)) ||
-      !CBB_add_u16(&cbb, TLSEXT_TYPE_channel_id) ||
-      !CBB_add_u16_length_prefixed(&cbb, &child) ||
-      !BN_bn2cbb_padded(&child, 32, x) ||
-      !BN_bn2cbb_padded(&child, 32, y) ||
-      !BN_bn2cbb_padded(&child, 32, sig->r) ||
-      !BN_bn2cbb_padded(&child, 32, sig->s) ||
-      !CBB_finish(&cbb, NULL, &length) ||
-      !ssl_set_handshake_header(ssl, SSL3_MT_ENCRYPTED_EXTENSIONS, length)) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    CBB_cleanup(&cbb);
-    goto err;
-  }
-
-  ssl->state = SSL3_ST_CW_CHANNEL_ID_B;
-  ret = ssl_do_write(ssl);
-
-err:
-  BN_free(x);
-  BN_free(y);
-  ECDSA_SIG_free(sig);
-  return ret;
-}
-
-int ssl_do_client_cert_cb(SSL *ssl, X509 **out_x509, EVP_PKEY **out_pkey) {
-  if (ssl->ctx->client_cert_cb == NULL) {
-    return 0;
-  }
-  return ssl->ctx->client_cert_cb(ssl, out_x509, out_pkey);
-}
-
-int ssl3_verify_server_cert(SSL *ssl) {
-  int ret = ssl_verify_cert_chain(ssl, ssl->session->cert_chain);
-  if (ssl->verify_mode != SSL_VERIFY_NONE && ret <= 0) {
-    int al = ssl_verify_alarm_type(ssl->verify_result);
-    ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
-    OPENSSL_PUT_ERROR(SSL, SSL_R_CERTIFICATE_VERIFY_FAILED);
-  } else {
-    ret = 1;
-    ERR_clear_error(); /* but we keep ssl->verify_result */
-  }
-
-  return ret;
-}
diff --git a/src/ssl/s3_enc.c b/src/ssl/s3_enc.c
deleted file mode 100644
index 89d861a..0000000
--- a/src/ssl/s3_enc.c
+++ /dev/null
@@ -1,496 +0,0 @@
-/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to.  The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *    "This product includes cryptographic software written by
- *     Eric Young (eay@cryptsoft.com)"
- *    The word 'cryptographic' can be left out if the rouines from the library
- *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- *    the apps directory (application code) you must include an acknowledgement:
- *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed.  i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- */
-/* ====================================================================
- * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- *    software must display the following acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- *    endorse or promote products derived from this software without
- *    prior written permission. For written permission, please contact
- *    openssl-core@openssl.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- *    nor may "OpenSSL" appear in their names without prior written
- *    permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- *    acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- *
- * This product includes cryptographic software written by Eric Young
- * (eay@cryptsoft.com).  This product includes software written by Tim
- * Hudson (tjh@cryptsoft.com).
- *
- */
-/* ====================================================================
- * Copyright 2005 Nokia. All rights reserved.
- *
- * The portions of the attached software ("Contribution") is developed by
- * Nokia Corporation and is licensed pursuant to the OpenSSL open source
- * license.
- *
- * The Contribution, originally written by Mika Kousa and Pasi Eronen of
- * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
- * support (see RFC 4279) to OpenSSL.
- *
- * No patent licenses or other rights except those expressly stated in
- * the OpenSSL open source license shall be deemed granted or received
- * expressly, by implication, estoppel, or otherwise.
- *
- * No assurances are provided by Nokia that the Contribution does not
- * infringe the patent or other intellectual property rights of any third
- * party or that the license provides you with all the necessary rights
- * to make use of the Contribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
- * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
- * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
- * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
- * OTHERWISE. */
-
-#include <openssl/ssl.h>
-
-#include <assert.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <openssl/err.h>
-#include <openssl/evp.h>
-#include <openssl/mem.h>
-#include <openssl/md5.h>
-#include <openssl/obj.h>
-
-#include "internal.h"
-
-
-static const uint8_t ssl3_pad_1[48] = {
-    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
-    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
-    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
-    0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
-};
-
-static const uint8_t ssl3_pad_2[48] = {
-    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
-    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
-    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
-    0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
-};
-
-static int ssl3_handshake_mac(SSL *ssl, int md_nid, const char *sender, int len,
-                              uint8_t *p);
-
-int ssl3_prf(SSL *ssl, uint8_t *out, size_t out_len, const uint8_t *secret,
-             size_t secret_len, const char *label, size_t label_len,
-             const uint8_t *seed1, size_t seed1_len,
-             const uint8_t *seed2, size_t seed2_len) {
-  EVP_MD_CTX md5;
-  EVP_MD_CTX sha1;
-  uint8_t buf[16], smd[SHA_DIGEST_LENGTH];
-  uint8_t c = 'A';
-  size_t i, j, k;
-
-  k = 0;
-  EVP_MD_CTX_init(&md5);
-  EVP_MD_CTX_init(&sha1);
-  for (i = 0; i < out_len; i += MD5_DIGEST_LENGTH) {
-    k++;
-    if (k > sizeof(buf)) {
-      /* bug: 'buf' is too small for this ciphersuite */
-      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-      return 0;
-    }
-
-    for (j = 0; j < k; j++) {
-      buf[j] = c;
-    }
-    c++;
-    if (!EVP_DigestInit_ex(&sha1, EVP_sha1(), NULL)) {
-      OPENSSL_PUT_ERROR(SSL, ERR_LIB_EVP);
-      return 0;
-    }
-    EVP_DigestUpdate(&sha1, buf, k);
-    EVP_DigestUpdate(&sha1, secret, secret_len);
-    /* |label| is ignored for SSLv3. */
-    if (seed1_len) {
-      EVP_DigestUpdate(&sha1, seed1, seed1_len);
-    }
-    if (seed2_len) {
-      EVP_DigestUpdate(&sha1, seed2, seed2_len);
-    }
-    EVP_DigestFinal_ex(&sha1, smd, NULL);
-
-    if (!EVP_DigestInit_ex(&md5, EVP_md5(), NULL)) {
-      OPENSSL_PUT_ERROR(SSL, ERR_LIB_EVP);
-      return 0;
-    }
-    EVP_DigestUpdate(&md5, secret, secret_len);
-    EVP_DigestUpdate(&md5, smd, SHA_DIGEST_LENGTH);
-    if (i + MD5_DIGEST_LENGTH > out_len) {
-      EVP_DigestFinal_ex(&md5, smd, NULL);
-      memcpy(out, smd, out_len - i);
-    } else {
-      EVP_DigestFinal_ex(&md5, out, NULL);
-    }
-
-    out += MD5_DIGEST_LENGTH;
-  }
-
-  OPENSSL_cleanse(smd, SHA_DIGEST_LENGTH);
-  EVP_MD_CTX_cleanup(&md5);
-  EVP_MD_CTX_cleanup(&sha1);
-
-  return 1;
-}
-
-void ssl3_cleanup_key_block(SSL *ssl) {
-  if (ssl->s3->tmp.key_block != NULL) {
-    OPENSSL_cleanse(ssl->s3->tmp.key_block, ssl->s3->tmp.key_block_length);
-    OPENSSL_free(ssl->s3->tmp.key_block);
-    ssl->s3->tmp.key_block = NULL;
-  }
-  ssl->s3->tmp.key_block_length = 0;
-}
-
-int ssl3_init_handshake_buffer(SSL *ssl) {
-  ssl3_free_handshake_buffer(ssl);
-  ssl3_free_handshake_hash(ssl);
-  ssl->s3->handshake_buffer = BUF_MEM_new();
-  return ssl->s3->handshake_buffer != NULL;
-}
-
-/* init_digest_with_data calls |EVP_DigestInit_ex| on |ctx| with |md| and then
- * writes the data in |buf| to it. */
-static int init_digest_with_data(EVP_MD_CTX *ctx, const EVP_MD *md,
-                                 const BUF_MEM *buf) {
-  if (!EVP_DigestInit_ex(ctx, md, NULL)) {
-    return 0;
-  }
-  EVP_DigestUpdate(ctx, buf->data, buf->length);
-  return 1;
-}
-
-int ssl3_init_handshake_hash(SSL *ssl) {
-  ssl3_free_handshake_hash(ssl);
-
-  uint32_t algorithm_prf = ssl_get_algorithm_prf(ssl);
-  if (!init_digest_with_data(&ssl->s3->handshake_hash,
-                             ssl_get_handshake_digest(algorithm_prf),
-                             ssl->s3->handshake_buffer)) {
-    return 0;
-  }
-
-  if (algorithm_prf == SSL_HANDSHAKE_MAC_DEFAULT &&
-      !init_digest_with_data(&ssl->s3->handshake_md5, EVP_md5(),
-                             ssl->s3->handshake_buffer)) {
-    return 0;
-  }
-
-  return 1;
-}
-
-void ssl3_free_handshake_hash(SSL *ssl) {
-  EVP_MD_CTX_cleanup(&ssl->s3->handshake_hash);
-  EVP_MD_CTX_cleanup(&ssl->s3->handshake_md5);
-}
-
-void ssl3_free_handshake_buffer(SSL *ssl) {
-  BUF_MEM_free(ssl->s3->handshake_buffer);
-  ssl->s3->handshake_buffer = NULL;
-}
-
-int ssl3_update_handshake_hash(SSL *ssl, const uint8_t *in, size_t in_len) {
-  /* Depending on the state of the handshake, either the handshake buffer may be
-   * active, the rolling hash, or both. */
-
-  if (ssl->s3->handshake_buffer != NULL) {
-    size_t new_len = ssl->s3->handshake_buffer->length + in_len;
-    if (new_len < in_len) {
-      OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
-      return 0;
-    }
-    if (!BUF_MEM_grow(ssl->s3->handshake_buffer, new_len)) {
-      return 0;
-    }
-    memcpy(ssl->s3->handshake_buffer->data + new_len - in_len, in, in_len);
-  }
-
-  if (EVP_MD_CTX_md(&ssl->s3->handshake_hash) != NULL) {
-    EVP_DigestUpdate(&ssl->s3->handshake_hash, in, in_len);
-  }
-  if (EVP_MD_CTX_md(&ssl->s3->handshake_md5) != NULL) {
-    EVP_DigestUpdate(&ssl->s3->handshake_md5, in, in_len);
-  }
-  return 1;
-}
-
-int ssl3_cert_verify_mac(SSL *ssl, int md_nid, uint8_t *p) {
-  return ssl3_handshake_mac(ssl, md_nid, NULL, 0, p);
-}
-
-int ssl3_final_finish_mac(SSL *ssl, const char *sender, int len, uint8_t *p) {
-  int ret, sha1len;
-  ret = ssl3_handshake_mac(ssl, NID_md5, sender, len, p);
-  if (ret == 0) {
-    return 0;
-  }
-
-  p += ret;
-
-  sha1len = ssl3_handshake_mac(ssl, NID_sha1, sender, len, p);
-  if (sha1len == 0) {
-    return 0;
-  }
-
-  ret += sha1len;
-  return ret;
-}
-
-static int ssl3_handshake_mac(SSL *ssl, int md_nid, const char *sender, int len,
-                              uint8_t *p) {
-  unsigned int ret;
-  size_t npad, n;
-  unsigned int i;
-  uint8_t md_buf[EVP_MAX_MD_SIZE];
-  EVP_MD_CTX ctx;
-  const EVP_MD_CTX *ctx_template;
-
-  if (md_nid == NID_md5) {
-    ctx_template = &ssl->s3->handshake_md5;
-  } else if (md_nid == EVP_MD_CTX_type(&ssl->s3->handshake_hash)) {
-    ctx_template = &ssl->s3->handshake_hash;
-  } else {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_NO_REQUIRED_DIGEST);
-    return 0;
-  }
-
-  EVP_MD_CTX_init(&ctx);
-  if (!EVP_MD_CTX_copy_ex(&ctx, ctx_template)) {
-    EVP_MD_CTX_cleanup(&ctx);
-    OPENSSL_PUT_ERROR(SSL, ERR_LIB_EVP);
-    return 0;
-  }
-
-  n = EVP_MD_CTX_size(&ctx);
-
-  npad = (48 / n) * n;
-  if (sender != NULL) {
-    EVP_DigestUpdate(&ctx, sender, len);
-  }
-  EVP_DigestUpdate(&ctx, ssl->session->master_key,
-                   ssl->session->master_key_length);
-  EVP_DigestUpdate(&ctx, ssl3_pad_1, npad);
-  EVP_DigestFinal_ex(&ctx, md_buf, &i);
-
-  if (!EVP_DigestInit_ex(&ctx, EVP_MD_CTX_md(&ctx), NULL)) {
-    EVP_MD_CTX_cleanup(&ctx);
-    OPENSSL_PUT_ERROR(SSL, ERR_LIB_EVP);
-    return 0;
-  }
-  EVP_DigestUpdate(&ctx, ssl->session->master_key,
-                   ssl->session->master_key_length);
-  EVP_DigestUpdate(&ctx, ssl3_pad_2, npad);
-  EVP_DigestUpdate(&ctx, md_buf, i);
-  EVP_DigestFinal_ex(&ctx, p, &ret);
-
-  EVP_MD_CTX_cleanup(&ctx);
-
-  return ret;
-}
-
-int ssl3_record_sequence_update(uint8_t *seq, size_t seq_len) {
-  size_t i;
-  for (i = seq_len - 1; i < seq_len; i--) {
-    ++seq[i];
-    if (seq[i] != 0) {
-      return 1;
-    }
-  }
-  OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
-  return 0;
-}
-
-int ssl3_alert_code(int code) {
-  switch (code) {
-    case SSL_AD_CLOSE_NOTIFY:
-      return SSL3_AD_CLOSE_NOTIFY;
-
-    case SSL_AD_UNEXPECTED_MESSAGE:
-      return SSL3_AD_UNEXPECTED_MESSAGE;
-
-    case SSL_AD_BAD_RECORD_MAC:
-      return SSL3_AD_BAD_RECORD_MAC;
-
-    case SSL_AD_DECRYPTION_FAILED:
-      return SSL3_AD_BAD_RECORD_MAC;
-
-    case SSL_AD_RECORD_OVERFLOW:
-      return SSL3_AD_BAD_RECORD_MAC;
-
-    case SSL_AD_DECOMPRESSION_FAILURE:
-      return SSL3_AD_DECOMPRESSION_FAILURE;
-
-    case SSL_AD_HANDSHAKE_FAILURE:
-      return SSL3_AD_HANDSHAKE_FAILURE;
-
-    case SSL_AD_NO_CERTIFICATE:
-      return SSL3_AD_NO_CERTIFICATE;
-
-    case SSL_AD_BAD_CERTIFICATE:
-      return SSL3_AD_BAD_CERTIFICATE;
-
-    case SSL_AD_UNSUPPORTED_CERTIFICATE:
-      return SSL3_AD_UNSUPPORTED_CERTIFICATE;
-
-    case SSL_AD_CERTIFICATE_REVOKED:
-      return SSL3_AD_CERTIFICATE_REVOKED;
-
-    case SSL_AD_CERTIFICATE_EXPIRED:
-      return SSL3_AD_CERTIFICATE_EXPIRED;
-
-    case SSL_AD_CERTIFICATE_UNKNOWN:
-      return SSL3_AD_CERTIFICATE_UNKNOWN;
-
-    case SSL_AD_ILLEGAL_PARAMETER:
-      return SSL3_AD_ILLEGAL_PARAMETER;
-
-    case SSL_AD_UNKNOWN_CA:
-      return SSL3_AD_BAD_CERTIFICATE;
-
-    case SSL_AD_ACCESS_DENIED:
-      return SSL3_AD_HANDSHAKE_FAILURE;
-
-    case SSL_AD_DECODE_ERROR:
-      return SSL3_AD_HANDSHAKE_FAILURE;
-
-    case SSL_AD_DECRYPT_ERROR:
-      return SSL3_AD_HANDSHAKE_FAILURE;
-
-    case SSL_AD_EXPORT_RESTRICTION:
-      return SSL3_AD_HANDSHAKE_FAILURE;
-
-    case SSL_AD_PROTOCOL_VERSION:
-      return SSL3_AD_HANDSHAKE_FAILURE;
-
-    case SSL_AD_INSUFFICIENT_SECURITY:
-      return SSL3_AD_HANDSHAKE_FAILURE;
-
-    case SSL_AD_INTERNAL_ERROR:
-      return SSL3_AD_HANDSHAKE_FAILURE;
-
-    case SSL_AD_USER_CANCELLED:
-      return SSL3_AD_HANDSHAKE_FAILURE;
-
-    case SSL_AD_NO_RENEGOTIATION:
-      return -1; /* Don't send it. */
-
-    case SSL_AD_UNSUPPORTED_EXTENSION:
-      return SSL3_AD_HANDSHAKE_FAILURE;
-
-    case SSL_AD_CERTIFICATE_UNOBTAINABLE:
-      return SSL3_AD_HANDSHAKE_FAILURE;
-
-    case SSL_AD_UNRECOGNIZED_NAME:
-      return SSL3_AD_HANDSHAKE_FAILURE;
-
-    case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE:
-      return SSL3_AD_HANDSHAKE_FAILURE;
-
-    case SSL_AD_BAD_CERTIFICATE_HASH_VALUE:
-      return SSL3_AD_HANDSHAKE_FAILURE;
-
-    case SSL_AD_UNKNOWN_PSK_IDENTITY:
-      return TLS1_AD_UNKNOWN_PSK_IDENTITY;
-
-    case SSL_AD_INAPPROPRIATE_FALLBACK:
-      return SSL3_AD_INAPPROPRIATE_FALLBACK;
-
-    default:
-      return -1;
-  }
-}
diff --git a/src/ssl/s3_lib.c b/src/ssl/s3_lib.c
index 64f9f8c..57a27c7 100644
--- a/src/ssl/s3_lib.c
+++ b/src/ssl/s3_lib.c
@@ -149,7 +149,6 @@
 #include <openssl/ssl.h>
 
 #include <assert.h>
-#include <stdio.h>
 #include <string.h>
 
 #include <openssl/buf.h>
@@ -158,68 +157,36 @@
 #include <openssl/err.h>
 #include <openssl/md5.h>
 #include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
 
+#include "../crypto/internal.h"
 #include "internal.h"
 
 
-const SSL3_ENC_METHOD SSLv3_enc_data = {
-    ssl3_prf,
-    tls1_setup_key_block,
-    tls1_generate_master_secret,
-    tls1_change_cipher_state,
-    ssl3_final_finish_mac,
-    ssl3_cert_verify_mac,
-    SSL3_MD_CLIENT_FINISHED_CONST, 4,
-    SSL3_MD_SERVER_FINISHED_CONST, 4,
-    ssl3_alert_code,
-    tls1_export_keying_material,
-    0,
-};
-
-int ssl3_supports_cipher(const SSL_CIPHER *cipher) {
-  return 1;
-}
-
-int ssl3_set_handshake_header(SSL *ssl, int htype, unsigned long len) {
-  uint8_t *p = (uint8_t *)ssl->init_buf->data;
-  *(p++) = htype;
-  l2n3(len, p);
-  ssl->init_num = (int)len + SSL3_HM_HEADER_LENGTH;
-  ssl->init_off = 0;
-
-  /* Add the message to the handshake hash. */
-  return ssl3_update_handshake_hash(ssl, (uint8_t *)ssl->init_buf->data,
-                                    ssl->init_num);
-}
-
-int ssl3_handshake_write(SSL *ssl) {
-  return ssl3_do_write(ssl, SSL3_RT_HANDSHAKE);
-}
-
 int ssl3_new(SSL *ssl) {
   SSL3_STATE *s3;
 
   s3 = OPENSSL_malloc(sizeof *s3);
   if (s3 == NULL) {
-    goto err;
+    return 0;
   }
-  memset(s3, 0, sizeof *s3);
+  OPENSSL_memset(s3, 0, sizeof *s3);
 
-  EVP_MD_CTX_init(&s3->handshake_hash);
-  EVP_MD_CTX_init(&s3->handshake_md5);
+  s3->hs = ssl_handshake_new(ssl);
+  if (s3->hs == NULL) {
+    OPENSSL_free(s3);
+    return 0;
+  }
 
   ssl->s3 = s3;
 
-  /* Set the version to the highest supported version for TLS. This controls the
-   * initial state of |ssl->enc_method| and what the API reports as the version
-   * prior to negotiation.
+  /* Set the version to the highest supported version.
    *
-   * TODO(davidben): This is fragile and confusing. */
+   * TODO(davidben): Move this field into |s3|, have it store the normalized
+   * protocol version, and implement this pre-negotiation quirk in |SSL_version|
+   * at the API boundary rather than in internal state. */
   ssl->version = TLS1_2_VERSION;
   return 1;
-err:
-  return 0;
 }
 
 void ssl3_free(SSL *ssl) {
@@ -227,362 +194,27 @@
     return;
   }
 
-  ssl3_cleanup_key_block(ssl);
   ssl_read_buffer_clear(ssl);
   ssl_write_buffer_clear(ssl);
-  SSL_ECDH_CTX_cleanup(&ssl->s3->tmp.ecdh_ctx);
-  OPENSSL_free(ssl->s3->tmp.peer_key);
 
-  sk_X509_NAME_pop_free(ssl->s3->tmp.ca_names, X509_NAME_free);
-  OPENSSL_free(ssl->s3->tmp.certificate_types);
-  OPENSSL_free(ssl->s3->tmp.peer_ellipticcurvelist);
-  OPENSSL_free(ssl->s3->tmp.peer_psk_identity_hint);
-  ssl3_free_handshake_buffer(ssl);
-  ssl3_free_handshake_hash(ssl);
+  SSL_SESSION_free(ssl->s3->established_session);
+  ssl_handshake_free(ssl->s3->hs);
+  OPENSSL_free(ssl->s3->next_proto_negotiated);
   OPENSSL_free(ssl->s3->alpn_selected);
+  SSL_AEAD_CTX_free(ssl->s3->aead_read_ctx);
+  SSL_AEAD_CTX_free(ssl->s3->aead_write_ctx);
+  BUF_MEM_free(ssl->s3->pending_flight);
 
   OPENSSL_cleanse(ssl->s3, sizeof *ssl->s3);
   OPENSSL_free(ssl->s3);
   ssl->s3 = NULL;
 }
 
-int SSL_session_reused(const SSL *ssl) {
-  return ssl->hit;
-}
-
-int SSL_total_renegotiations(const SSL *ssl) {
-  return ssl->s3->total_renegotiations;
-}
-
-int SSL_num_renegotiations(const SSL *ssl) {
-  return SSL_total_renegotiations(ssl);
-}
-
-int SSL_CTX_need_tmp_RSA(const SSL_CTX *ctx) {
-  return 0;
-}
-
-int SSL_need_rsa(const SSL *ssl) {
-  return 0;
-}
-
-int SSL_CTX_set_tmp_rsa(SSL_CTX *ctx, const RSA *rsa) {
-  return 1;
-}
-
-int SSL_set_tmp_rsa(SSL *ssl, const RSA *rsa) {
-  return 1;
-}
-
-int SSL_CTX_set_tmp_dh(SSL_CTX *ctx, const DH *dh) {
-  DH_free(ctx->cert->dh_tmp);
-  ctx->cert->dh_tmp = DHparams_dup(dh);
-  if (ctx->cert->dh_tmp == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_DH_LIB);
-    return 0;
-  }
-  return 1;
-}
-
-int SSL_set_tmp_dh(SSL *ssl, const DH *dh) {
-  DH_free(ssl->cert->dh_tmp);
-  ssl->cert->dh_tmp = DHparams_dup(dh);
-  if (ssl->cert->dh_tmp == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_DH_LIB);
-    return 0;
-  }
-  return 1;
-}
-
-int SSL_CTX_set_tmp_ecdh(SSL_CTX *ctx, const EC_KEY *ec_key) {
-  if (ec_key == NULL || EC_KEY_get0_group(ec_key) == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
-    return 0;
-  }
-  int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key));
-  return SSL_CTX_set1_curves(ctx, &nid, 1);
-}
-
-int SSL_set_tmp_ecdh(SSL *ssl, const EC_KEY *ec_key) {
-  if (ec_key == NULL || EC_KEY_get0_group(ec_key) == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
-    return 0;
-  }
-  int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key));
-  return SSL_set1_curves(ssl, &nid, 1);
-}
-
-int SSL_CTX_enable_tls_channel_id(SSL_CTX *ctx) {
-  ctx->tlsext_channel_id_enabled = 1;
-  return 1;
-}
-
-int SSL_enable_tls_channel_id(SSL *ssl) {
-  ssl->tlsext_channel_id_enabled = 1;
-  return 1;
-}
-
-int SSL_CTX_set1_tls_channel_id(SSL_CTX *ctx, EVP_PKEY *private_key) {
-  ctx->tlsext_channel_id_enabled = 1;
-  if (EVP_PKEY_id(private_key) != EVP_PKEY_EC ||
-      EVP_PKEY_bits(private_key) != 256) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_CHANNEL_ID_NOT_P256);
-    return 0;
-  }
-  EVP_PKEY_free(ctx->tlsext_channel_id_private);
-  ctx->tlsext_channel_id_private = EVP_PKEY_up_ref(private_key);
-  return 1;
-}
-
-int SSL_set1_tls_channel_id(SSL *ssl, EVP_PKEY *private_key) {
-  EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(private_key);
-  if (ec_key == NULL ||
-      EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key)) !=
-          NID_X9_62_prime256v1) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_CHANNEL_ID_NOT_P256);
-    return 0;
-  }
-
-  EVP_PKEY_free(ssl->tlsext_channel_id_private);
-  ssl->tlsext_channel_id_private = EVP_PKEY_up_ref(private_key);
-  ssl->tlsext_channel_id_enabled = 1;
-
-  return 1;
-}
-
-size_t SSL_get_tls_channel_id(SSL *ssl, uint8_t *out, size_t max_out) {
-  if (!ssl->s3->tlsext_channel_id_valid) {
-    return 0;
-  }
-  memcpy(out, ssl->s3->tlsext_channel_id, (max_out < 64) ? max_out : 64);
-  return 64;
-}
-
-int SSL_set_tlsext_host_name(SSL *ssl, const char *name) {
-  OPENSSL_free(ssl->tlsext_hostname);
-  ssl->tlsext_hostname = NULL;
-
-  if (name == NULL) {
-    return 1;
-  }
-  if (strlen(name) > TLSEXT_MAXLEN_host_name) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_SSL3_EXT_INVALID_SERVERNAME);
-    return 0;
-  }
-  ssl->tlsext_hostname = BUF_strdup(name);
-  if (ssl->tlsext_hostname == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-    return 0;
-  }
-  return 1;
-}
-
-size_t SSL_get0_certificate_types(SSL *ssl, const uint8_t **out_types) {
-  if (ssl->server || !ssl->s3->tmp.cert_req) {
-    *out_types = NULL;
-    return 0;
-  }
-  *out_types = ssl->s3->tmp.certificate_types;
-  return ssl->s3->tmp.num_certificate_types;
-}
-
-int SSL_CTX_set1_curves(SSL_CTX *ctx, const int *curves, size_t curves_len) {
-  return tls1_set_curves(&ctx->tlsext_ellipticcurvelist,
-                         &ctx->tlsext_ellipticcurvelist_length, curves,
-                         curves_len);
-}
-
-int SSL_set1_curves(SSL *ssl, const int *curves, size_t curves_len) {
-  return tls1_set_curves(&ssl->tlsext_ellipticcurvelist,
-                         &ssl->tlsext_ellipticcurvelist_length, curves,
-                         curves_len);
-}
-
-int SSL_CTX_set_tlsext_servername_callback(
-    SSL_CTX *ctx, int (*callback)(SSL *ssl, int *out_alert, void *arg)) {
-  ctx->tlsext_servername_callback = callback;
-  return 1;
-}
-
-int SSL_CTX_set_tlsext_servername_arg(SSL_CTX *ctx, void *arg) {
-  ctx->tlsext_servername_arg = arg;
-  return 1;
-}
-
-int SSL_CTX_get_tlsext_ticket_keys(SSL_CTX *ctx, void *out, size_t len) {
-  if (out == NULL) {
-    return 48;
-  }
-  if (len != 48) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_TICKET_KEYS_LENGTH);
-    return 0;
-  }
-  uint8_t *out_bytes = out;
-  memcpy(out_bytes, ctx->tlsext_tick_key_name, 16);
-  memcpy(out_bytes + 16, ctx->tlsext_tick_hmac_key, 16);
-  memcpy(out_bytes + 32, ctx->tlsext_tick_aes_key, 16);
-  return 1;
-}
-
-int SSL_CTX_set_tlsext_ticket_keys(SSL_CTX *ctx, const void *in, size_t len) {
-  if (in == NULL) {
-    return 48;
-  }
-  if (len != 48) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_TICKET_KEYS_LENGTH);
-    return 0;
-  }
-  const uint8_t *in_bytes = in;
-  memcpy(ctx->tlsext_tick_key_name, in_bytes, 16);
-  memcpy(ctx->tlsext_tick_hmac_key, in_bytes + 16, 16);
-  memcpy(ctx->tlsext_tick_aes_key, in_bytes + 32, 16);
-  return 1;
-}
-
-int SSL_CTX_set_tlsext_ticket_key_cb(
-    SSL_CTX *ctx, int (*callback)(SSL *ssl, uint8_t *key_name, uint8_t *iv,
-                                  EVP_CIPHER_CTX *ctx, HMAC_CTX *hmac_ctx,
-                                  int encrypt)) {
-  ctx->tlsext_ticket_key_cb = callback;
-  return 1;
-}
-
-struct ssl_cipher_preference_list_st *ssl_get_cipher_preferences(SSL *ssl) {
+const struct ssl_cipher_preference_list_st *ssl_get_cipher_preferences(
+    const SSL *ssl) {
   if (ssl->cipher_list != NULL) {
     return ssl->cipher_list;
   }
 
-  if (ssl->version >= TLS1_1_VERSION && ssl->ctx != NULL &&
-      ssl->ctx->cipher_list_tls11 != NULL) {
-    return ssl->ctx->cipher_list_tls11;
-  }
-
-  if (ssl->version >= TLS1_VERSION && ssl->ctx != NULL &&
-      ssl->ctx->cipher_list_tls10 != NULL) {
-    return ssl->ctx->cipher_list_tls10;
-  }
-
-  if (ssl->ctx != NULL && ssl->ctx->cipher_list != NULL) {
-    return ssl->ctx->cipher_list;
-  }
-
-  return NULL;
-}
-
-const SSL_CIPHER *ssl3_choose_cipher(
-    SSL *ssl, STACK_OF(SSL_CIPHER) *clnt,
-    struct ssl_cipher_preference_list_st *server_pref) {
-  const SSL_CIPHER *c, *ret = NULL;
-  STACK_OF(SSL_CIPHER) *srvr = server_pref->ciphers, *prio, *allow;
-  size_t i;
-  int ok;
-  size_t cipher_index;
-  uint32_t alg_k, alg_a, mask_k, mask_a;
-  /* in_group_flags will either be NULL, or will point to an array of bytes
-   * which indicate equal-preference groups in the |prio| stack. See the
-   * comment about |in_group_flags| in the |ssl_cipher_preference_list_st|
-   * struct. */
-  const uint8_t *in_group_flags;
-  /* group_min contains the minimal index so far found in a group, or -1 if no
-   * such value exists yet. */
-  int group_min = -1;
-
-  if (ssl->options & SSL_OP_CIPHER_SERVER_PREFERENCE) {
-    prio = srvr;
-    in_group_flags = server_pref->in_group_flags;
-    allow = clnt;
-  } else {
-    prio = clnt;
-    in_group_flags = NULL;
-    allow = srvr;
-  }
-
-  ssl_get_compatible_server_ciphers(ssl, &mask_k, &mask_a);
-
-  for (i = 0; i < sk_SSL_CIPHER_num(prio); i++) {
-    c = sk_SSL_CIPHER_value(prio, i);
-
-    ok = 1;
-
-    /* Check the TLS version. */
-    if (SSL_CIPHER_get_min_version(c) >
-        ssl3_version_from_wire(ssl, ssl->version)) {
-      ok = 0;
-    }
-
-    alg_k = c->algorithm_mkey;
-    alg_a = c->algorithm_auth;
-
-    ok = ok && (alg_k & mask_k) && (alg_a & mask_a);
-
-    if (ok && sk_SSL_CIPHER_find(allow, &cipher_index, c)) {
-      if (in_group_flags != NULL && in_group_flags[i] == 1) {
-        /* This element of |prio| is in a group. Update the minimum index found
-         * so far and continue looking. */
-        if (group_min == -1 || (size_t)group_min > cipher_index) {
-          group_min = cipher_index;
-        }
-      } else {
-        if (group_min != -1 && (size_t)group_min < cipher_index) {
-          cipher_index = group_min;
-        }
-        ret = sk_SSL_CIPHER_value(allow, cipher_index);
-        break;
-      }
-    }
-
-    if (in_group_flags != NULL && in_group_flags[i] == 0 && group_min != -1) {
-      /* We are about to leave a group, but we found a match in it, so that's
-       * our answer. */
-      ret = sk_SSL_CIPHER_value(allow, group_min);
-      break;
-    }
-  }
-
-  return ret;
-}
-
-int ssl3_get_req_cert_type(SSL *ssl, uint8_t *p) {
-  int ret = 0;
-  const uint8_t *sig;
-  size_t i, siglen;
-  int have_rsa_sign = 0;
-  int have_ecdsa_sign = 0;
-
-  /* get configured sigalgs */
-  siglen = tls12_get_psigalgs(ssl, &sig);
-  for (i = 0; i < siglen; i += 2, sig += 2) {
-    switch (sig[1]) {
-      case TLSEXT_signature_rsa:
-        have_rsa_sign = 1;
-        break;
-
-      case TLSEXT_signature_ecdsa:
-        have_ecdsa_sign = 1;
-        break;
-    }
-  }
-
-  if (have_rsa_sign) {
-    p[ret++] = SSL3_CT_RSA_SIGN;
-  }
-
-  /* ECDSA certs can be used with RSA cipher suites as well so we don't need to
-   * check for SSL_kECDH or SSL_kECDHE. */
-  if (ssl->version >= TLS1_VERSION && have_ecdsa_sign) {
-      p[ret++] = TLS_CT_ECDSA_SIGN;
-  }
-
-  return ret;
-}
-
-/* If we are using default SHA1+MD5 algorithms switch to new SHA256 PRF and
- * handshake macs if required. */
-uint32_t ssl_get_algorithm_prf(SSL *ssl) {
-  uint32_t algorithm_prf = ssl->s3->tmp.new_cipher->algorithm_prf;
-  if (ssl->enc_method->enc_flags & SSL_ENC_FLAG_SHA256_PRF &&
-      algorithm_prf == SSL_HANDSHAKE_MAC_DEFAULT) {
-    return SSL_HANDSHAKE_MAC_SHA256;
-  }
-  return algorithm_prf;
+  return ssl->ctx->cipher_list;
 }
diff --git a/src/ssl/s3_meth.c b/src/ssl/s3_meth.c
deleted file mode 100644
index b60b5f2..0000000
--- a/src/ssl/s3_meth.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to.  The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *    "This product includes cryptographic software written by
- *     Eric Young (eay@cryptsoft.com)"
- *    The word 'cryptographic' can be left out if the rouines from the library
- *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- *    the apps directory (application code) you must include an acknowledgement:
- *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed.  i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.] */
-
-#include <openssl/ssl.h>
-
-#include "internal.h"
-
-
-static const SSL_PROTOCOL_METHOD TLS_protocol_method = {
-    0 /* is_dtls */,
-    ssl3_new,
-    ssl3_free,
-    ssl3_accept,
-    ssl3_connect,
-    ssl3_get_message,
-    ssl3_read_app_data,
-    ssl3_read_change_cipher_spec,
-    ssl3_read_close_notify,
-    ssl3_write_app_data,
-    ssl3_dispatch_alert,
-    ssl3_supports_cipher,
-    SSL3_HM_HEADER_LENGTH,
-    ssl3_set_handshake_header,
-    ssl3_handshake_write,
-};
-
-const SSL_METHOD *TLS_method(void) {
-  static const SSL_METHOD method = {
-      0,
-      &TLS_protocol_method,
-  };
-  return &method;
-}
-
-const SSL_METHOD *SSLv23_method(void) {
-  return TLS_method();
-}
-
-/* Legacy version-locked methods. */
-
-const SSL_METHOD *TLSv1_2_method(void) {
-  static const SSL_METHOD method = {
-      TLS1_2_VERSION,
-      &TLS_protocol_method,
-  };
-  return &method;
-}
-
-const SSL_METHOD *TLSv1_1_method(void) {
-  static const SSL_METHOD method = {
-      TLS1_1_VERSION,
-      &TLS_protocol_method,
-  };
-  return &method;
-}
-
-const SSL_METHOD *TLSv1_method(void) {
-  static const SSL_METHOD method = {
-      TLS1_VERSION,
-      &TLS_protocol_method,
-  };
-  return &method;
-}
-
-const SSL_METHOD *SSLv3_method(void) {
-  static const SSL_METHOD method = {
-      SSL3_VERSION,
-      &TLS_protocol_method,
-  };
-  return &method;
-}
-
-/* Legacy side-specific methods. */
-
-const SSL_METHOD *TLSv1_2_server_method(void) {
-  return TLSv1_2_method();
-}
-
-const SSL_METHOD *TLSv1_1_server_method(void) {
-  return TLSv1_1_method();
-}
-
-const SSL_METHOD *TLSv1_server_method(void) {
-  return TLSv1_method();
-}
-
-const SSL_METHOD *SSLv3_server_method(void) {
-  return SSLv3_method();
-}
-
-const SSL_METHOD *TLSv1_2_client_method(void) {
-  return TLSv1_2_method();
-}
-
-const SSL_METHOD *TLSv1_1_client_method(void) {
-  return TLSv1_1_method();
-}
-
-const SSL_METHOD *TLSv1_client_method(void) {
-  return TLSv1_method();
-}
-
-const SSL_METHOD *SSLv3_client_method(void) {
-  return SSLv3_method();
-}
-
-const SSL_METHOD *SSLv23_server_method(void) {
-  return SSLv23_method();
-}
-
-const SSL_METHOD *SSLv23_client_method(void) {
-  return SSLv23_method();
-}
diff --git a/src/ssl/s3_pkt.c b/src/ssl/s3_pkt.c
index 4c1133c..c2d30ca 100644
--- a/src/ssl/s3_pkt.c
+++ b/src/ssl/s3_pkt.c
@@ -110,7 +110,6 @@
 
 #include <assert.h>
 #include <limits.h>
-#include <stdio.h>
 #include <string.h>
 
 #include <openssl/buf.h>
@@ -119,58 +118,65 @@
 #include <openssl/mem.h>
 #include <openssl/rand.h>
 
+#include "../crypto/internal.h"
 #include "internal.h"
 
 
 static int do_ssl3_write(SSL *ssl, int type, const uint8_t *buf, unsigned len);
 
-/* kMaxWarningAlerts is the number of consecutive warning alerts that will be
- * processed. */
-static const uint8_t kMaxWarningAlerts = 4;
-
 /* ssl3_get_record reads a new input record. On success, it places it in
  * |ssl->s3->rrec| and returns one. Otherwise it returns <= 0 on error or if
  * more data is needed. */
 static int ssl3_get_record(SSL *ssl) {
-  int ret;
 again:
-  /* Ensure the buffer is large enough to decrypt in-place. */
-  ret = ssl_read_buffer_extend_to(ssl, ssl_record_prefix_len(ssl));
-  if (ret <= 0) {
-    return ret;
+  switch (ssl->s3->recv_shutdown) {
+    case ssl_shutdown_none:
+      break;
+    case ssl_shutdown_fatal_alert:
+      OPENSSL_PUT_ERROR(SSL, SSL_R_PROTOCOL_IS_SHUTDOWN);
+      return -1;
+    case ssl_shutdown_close_notify:
+      return 0;
   }
-  assert(ssl_read_buffer_len(ssl) >= ssl_record_prefix_len(ssl));
 
-  uint8_t *out = ssl_read_buffer(ssl) + ssl_record_prefix_len(ssl);
-  size_t max_out = ssl_read_buffer_len(ssl) - ssl_record_prefix_len(ssl);
-  uint8_t type, alert;
-  size_t len, consumed;
-  switch (tls_open_record(ssl, &type, out, &len, &consumed, &alert, max_out,
-                          ssl_read_buffer(ssl), ssl_read_buffer_len(ssl))) {
+  CBS body;
+  uint8_t type, alert = SSL_AD_DECODE_ERROR;
+  size_t consumed;
+  enum ssl_open_record_t open_ret =
+      tls_open_record(ssl, &type, &body, &consumed, &alert,
+                      ssl_read_buffer(ssl), ssl_read_buffer_len(ssl));
+  if (open_ret != ssl_open_record_partial) {
+    ssl_read_buffer_consume(ssl, consumed);
+  }
+  switch (open_ret) {
+    case ssl_open_record_partial: {
+      int read_ret = ssl_read_buffer_extend_to(ssl, consumed);
+      if (read_ret <= 0) {
+        return read_ret;
+      }
+      goto again;
+    }
+
     case ssl_open_record_success:
-      ssl_read_buffer_consume(ssl, consumed);
-
-      if (len > 0xffff) {
+      if (CBS_len(&body) > 0xffff) {
         OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
         return -1;
       }
 
       SSL3_RECORD *rr = &ssl->s3->rrec;
       rr->type = type;
-      rr->length = (uint16_t)len;
-      rr->data = out;
+      rr->length = (uint16_t)CBS_len(&body);
+      rr->data = (uint8_t *)CBS_data(&body);
       return 1;
 
-    case ssl_open_record_partial:
-      ret = ssl_read_buffer_extend_to(ssl, consumed);
-      if (ret <= 0) {
-        return ret;
-      }
+    case ssl_open_record_discard:
       goto again;
 
-    case ssl_open_record_discard:
-      ssl_read_buffer_consume(ssl, consumed);
-      goto again;
+    case ssl_open_record_close_notify:
+      return 0;
+
+    case ssl_open_record_fatal_alert:
+      return -1;
 
     case ssl_open_record_error:
       ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
@@ -182,33 +188,15 @@
   return -1;
 }
 
-int ssl3_write_app_data(SSL *ssl, const void *buf, int len) {
-  return ssl3_write_bytes(ssl, SSL3_RT_APPLICATION_DATA, buf, len);
-}
+int ssl3_write_app_data(SSL *ssl, const uint8_t *buf, int len) {
+  assert(ssl_can_write(ssl));
 
-/* Call this to write data in records of type |type|. It will return <= 0 if
- * not all data has been sent or non-blocking IO. */
-int ssl3_write_bytes(SSL *ssl, int type, const void *buf_, int len) {
-  const uint8_t *buf = buf_;
-  unsigned int tot, n, nw;
-  int i;
+  unsigned tot, n, nw;
 
-  ssl->rwstate = SSL_NOTHING;
   assert(ssl->s3->wnum <= INT_MAX);
   tot = ssl->s3->wnum;
   ssl->s3->wnum = 0;
 
-  if (!ssl->in_handshake && SSL_in_init(ssl) && !SSL_in_false_start(ssl)) {
-    i = ssl->handshake_func(ssl);
-    if (i < 0) {
-      return i;
-    }
-    if (i == 0) {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_HANDSHAKE_FAILURE);
-      return -1;
-    }
-  }
-
   /* Ensure that if we end up with a smaller value of data to write out than
    * the the original len from a write which didn't complete for non-blocking
    * I/O and also somehow ended up avoiding the check for this in
@@ -221,7 +209,7 @@
     return -1;
   }
 
-  n = (len - tot);
+  n = len - tot;
   for (;;) {
     /* max contains the maximum number of bytes that we can put into a
      * record. */
@@ -232,27 +220,26 @@
       nw = n;
     }
 
-    i = do_ssl3_write(ssl, type, &buf[tot], nw);
-    if (i <= 0) {
+    int ret = do_ssl3_write(ssl, SSL3_RT_APPLICATION_DATA, &buf[tot], nw);
+    if (ret <= 0) {
       ssl->s3->wnum = tot;
-      return i;
+      return ret;
     }
 
-    if (i == (int)n || (type == SSL3_RT_APPLICATION_DATA &&
-                        (ssl->mode & SSL_MODE_ENABLE_PARTIAL_WRITE))) {
-      return tot + i;
+    if (ret == (int)n || (ssl->mode & SSL_MODE_ENABLE_PARTIAL_WRITE)) {
+      return tot + ret;
     }
 
-    n -= i;
-    tot += i;
+    n -= ret;
+    tot += ret;
   }
 }
 
 static int ssl3_write_pending(SSL *ssl, int type, const uint8_t *buf,
                               unsigned int len) {
   if (ssl->s3->wpend_tot > (int)len ||
-      (ssl->s3->wpend_buf != buf &&
-       !(ssl->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER)) ||
+      (!(ssl->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER) &&
+       ssl->s3->wpend_buf != buf) ||
       ssl->s3->wpend_type != type) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_WRITE_RETRY);
     return -1;
@@ -272,13 +259,12 @@
     return ssl3_write_pending(ssl, type, buf, len);
   }
 
-  /* If we have an alert to send, lets send it */
-  if (ssl->s3->alert_dispatch) {
-    int ret = ssl->method->ssl_dispatch_alert(ssl);
-    if (ret <= 0) {
-      return ret;
-    }
-    /* if it went, fall through and send more stuff */
+  /* The handshake flight buffer is mutually exclusive with application data.
+   *
+   * TODO(davidben): This will not be true when closure alerts use this. */
+  if (ssl->s3->pending_flight != NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    return -1;
   }
 
   if (len > SSL3_RT_MAX_PLAIN_LENGTH) {
@@ -290,7 +276,7 @@
     return 0;
   }
 
-  size_t max_out = len + ssl_max_seal_overhead(ssl);
+  size_t max_out = len + SSL_max_seal_overhead(ssl);
   if (max_out < len) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
     return -1;
@@ -314,372 +300,185 @@
   return ssl3_write_pending(ssl, type, buf, len);
 }
 
-int ssl3_read_app_data(SSL *ssl, uint8_t *buf, int len, int peek) {
-  return ssl3_read_bytes(ssl, SSL3_RT_APPLICATION_DATA, buf, len, peek);
+static int consume_record(SSL *ssl, uint8_t *out, int len, int peek) {
+  SSL3_RECORD *rr = &ssl->s3->rrec;
+
+  if (len <= 0) {
+    return len;
+  }
+
+  if (len > (int)rr->length) {
+    len = (int)rr->length;
+  }
+
+  OPENSSL_memcpy(out, rr->data, len);
+  if (!peek) {
+    rr->length -= len;
+    rr->data += len;
+    if (rr->length == 0) {
+      /* The record has been consumed, so we may now clear the buffer. */
+      ssl_read_buffer_discard(ssl);
+    }
+  }
+  return len;
+}
+
+int ssl3_read_app_data(SSL *ssl, int *out_got_handshake, uint8_t *buf, int len,
+                       int peek) {
+  assert(ssl_can_read(ssl));
+  *out_got_handshake = 0;
+
+  ssl->method->release_current_message(ssl, 0 /* don't free buffer */);
+
+  SSL3_RECORD *rr = &ssl->s3->rrec;
+
+  for (;;) {
+    /* A previous iteration may have read a partial handshake message. Do not
+     * allow more app data in that case. */
+    int has_hs_data = ssl->init_buf != NULL && ssl->init_buf->length > 0;
+
+    /* Get new packet if necessary. */
+    if (rr->length == 0 && !has_hs_data) {
+      int ret = ssl3_get_record(ssl);
+      if (ret <= 0) {
+        return ret;
+      }
+    }
+
+    if (has_hs_data || rr->type == SSL3_RT_HANDSHAKE) {
+      /* If reading 0-RTT data, reject handshake data. 0-RTT data is terminated
+       * by an alert. */
+      if (SSL_in_init(ssl)) {
+        OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
+        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+        return -1;
+      }
+
+      /* Post-handshake data prior to TLS 1.3 is always renegotiation, which we
+       * never accept as a server. Otherwise |ssl3_get_message| will send
+       * |SSL_R_EXCESSIVE_MESSAGE_SIZE|. */
+      if (ssl->server && ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
+        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_NO_RENEGOTIATION);
+        OPENSSL_PUT_ERROR(SSL, SSL_R_NO_RENEGOTIATION);
+        return -1;
+      }
+
+      /* Parse post-handshake handshake messages. */
+      int ret = ssl3_get_message(ssl);
+      if (ret <= 0) {
+        return ret;
+      }
+      *out_got_handshake = 1;
+      return -1;
+    }
+
+    /* Handle the end_of_early_data alert. */
+    if (rr->type == SSL3_RT_ALERT &&
+        rr->length == 2 &&
+        rr->data[0] == SSL3_AL_WARNING &&
+        rr->data[1] == TLS1_AD_END_OF_EARLY_DATA &&
+        ssl->server &&
+        ssl->s3->hs != NULL &&
+        ssl->s3->hs->can_early_read &&
+        ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
+      /* Consume the record. */
+      rr->length = 0;
+      ssl_read_buffer_discard(ssl);
+      /* Stop accepting early data. */
+      ssl->s3->hs->can_early_read = 0;
+      *out_got_handshake = 1;
+      return -1;
+    }
+
+    if (rr->type != SSL3_RT_APPLICATION_DATA) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+      return -1;
+    }
+
+    if (rr->length != 0) {
+      return consume_record(ssl, buf, len, peek);
+    }
+
+    /* Discard empty records and loop again. */
+  }
 }
 
 int ssl3_read_change_cipher_spec(SSL *ssl) {
-  uint8_t byte;
-  int ret = ssl3_read_bytes(ssl, SSL3_RT_CHANGE_CIPHER_SPEC, &byte, 1 /* len */,
-                            0 /* no peek */);
-  if (ret <= 0) {
-    return ret;
-  }
-  assert(ret == 1);
+  SSL3_RECORD *rr = &ssl->s3->rrec;
 
-  if (ssl->s3->rrec.length != 0 || byte != SSL3_MT_CCS) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_CHANGE_CIPHER_SPEC);
-    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
-    return -1;
-  }
-
-  if (ssl->msg_callback != NULL) {
-    ssl->msg_callback(0, ssl->version, SSL3_RT_CHANGE_CIPHER_SPEC, &byte, 1,
-                      ssl, ssl->msg_callback_arg);
-  }
-
-  return 1;
-}
-
-void ssl3_read_close_notify(SSL *ssl) {
-  ssl3_read_bytes(ssl, 0, NULL, 0, 0);
-}
-
-static int ssl3_can_renegotiate(SSL *ssl) {
-  switch (ssl->renegotiate_mode) {
-    case ssl_renegotiate_never:
-      return 0;
-    case ssl_renegotiate_once:
-      return ssl->s3->total_renegotiations == 0;
-    case ssl_renegotiate_freely:
-      return 1;
-    case ssl_renegotiate_ignore:
-      return 1;
-  }
-
-  assert(0);
-  return 0;
-}
-
-/* Return up to 'len' payload bytes received in 'type' records.
- * 'type' is one of the following:
- *
- *   -  SSL3_RT_HANDSHAKE (when ssl3_get_message calls us)
- *   -  SSL3_RT_CHANGE_CIPHER_SPEC (when ssl3_read_change_cipher_spec calls us)
- *   -  SSL3_RT_APPLICATION_DATA (when ssl3_read_app_data calls us)
- *   -  0 (during a shutdown, no data has to be returned)
- *
- * If we don't have stored data to work from, read a SSL/TLS record first
- * (possibly multiple records if we still don't have anything to return).
- *
- * This function must handle any surprises the peer may have for us, such as
- * Alert records (e.g. close_notify) or renegotiation requests. */
-int ssl3_read_bytes(SSL *ssl, int type, uint8_t *buf, int len, int peek) {
-  int al, i, ret;
-  unsigned int n;
-  SSL3_RECORD *rr;
-  void (*cb)(const SSL *ssl, int type, int value) = NULL;
-
-  if ((type && type != SSL3_RT_APPLICATION_DATA && type != SSL3_RT_HANDSHAKE &&
-       type != SSL3_RT_CHANGE_CIPHER_SPEC) ||
-      (peek && type != SSL3_RT_APPLICATION_DATA)) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    return -1;
-  }
-
-  /* This may require multiple iterations. False Start will cause
-   * |ssl->handshake_func| to signal success one step early, but the handshake
-   * must be completely finished before other modes are accepted.
-   *
-   * TODO(davidben): Move this check up to a higher level. */
-  while (!ssl->in_handshake && SSL_in_init(ssl)) {
-    assert(type == SSL3_RT_APPLICATION_DATA);
-    i = ssl->handshake_func(ssl);
-    if (i < 0) {
-      return i;
-    }
-    if (i == 0) {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_HANDSHAKE_FAILURE);
-      return -1;
-    }
-  }
-
-start:
-  ssl->rwstate = SSL_NOTHING;
-
-  /* ssl->s3->rrec.type    - is the type of record
-   * ssl->s3->rrec.data    - data
-   * ssl->s3->rrec.off     - offset into 'data' for next read
-   * ssl->s3->rrec.length  - number of bytes. */
-  rr = &ssl->s3->rrec;
-
-  /* get new packet if necessary */
   if (rr->length == 0) {
-    ret = ssl3_get_record(ssl);
+    int ret = ssl3_get_record(ssl);
     if (ret <= 0) {
       return ret;
     }
   }
 
-  /* we now have a packet which can be read and processed */
-
-  /* If the other end has shut down, throw anything we read away (even in
-   * 'peek' mode) */
-  if (ssl->shutdown & SSL_RECEIVED_SHUTDOWN) {
-    rr->length = 0;
-    ssl->rwstate = SSL_NOTHING;
-    return 0;
-  }
-
-  if (type != 0 && type == rr->type) {
-    ssl->s3->warning_alert_count = 0;
-
-    /* Make sure that we are not getting application data when we are doing a
-     * handshake for the first time. */
-    if (SSL_in_init(ssl) && type == SSL3_RT_APPLICATION_DATA &&
-        ssl->aead_read_ctx == NULL) {
-      /* TODO(davidben): Is this check redundant with the handshake_func
-       * check? */
-      al = SSL_AD_UNEXPECTED_MESSAGE;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_APP_DATA_IN_HANDSHAKE);
-      goto f_err;
-    }
-
-    /* Discard empty records. */
-    if (rr->length == 0) {
-      goto start;
-    }
-
-    if (len <= 0) {
-      return len;
-    }
-
-    if ((unsigned int)len > rr->length) {
-      n = rr->length;
-    } else {
-      n = (unsigned int)len;
-    }
-
-    memcpy(buf, rr->data, n);
-    if (!peek) {
-      rr->length -= n;
-      rr->data += n;
-      if (rr->length == 0) {
-        /* The record has been consumed, so we may now clear the buffer. */
-        ssl_read_buffer_discard(ssl);
-      }
-    }
-
-    return n;
-  }
-
-  /* Process unexpected records. */
-
-  if (type == SSL3_RT_APPLICATION_DATA && rr->type == SSL3_RT_HANDSHAKE) {
-    /* If peer renegotiations are disabled, all out-of-order handshake records
-     * are fatal. Renegotiations as a server are never supported. */
-    if (ssl->server || !ssl3_can_renegotiate(ssl)) {
-      al = SSL_AD_NO_RENEGOTIATION;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_NO_RENEGOTIATION);
-      goto f_err;
-    }
-
-    /* This must be a HelloRequest, possibly fragmented over multiple records.
-     * Consume data from the handshake protocol until it is complete. */
-    static const uint8_t kHelloRequest[] = {SSL3_MT_HELLO_REQUEST, 0, 0, 0};
-    while (ssl->s3->hello_request_len < sizeof(kHelloRequest)) {
-      if (rr->length == 0) {
-        /* Get a new record. */
-        goto start;
-      }
-      if (rr->data[0] != kHelloRequest[ssl->s3->hello_request_len]) {
-        al = SSL_AD_DECODE_ERROR;
-        OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_HELLO_REQUEST);
-        goto f_err;
-      }
-      rr->data++;
-      rr->length--;
-      ssl->s3->hello_request_len++;
-    }
-    ssl->s3->hello_request_len = 0;
-
-    if (ssl->msg_callback) {
-      ssl->msg_callback(0, ssl->version, SSL3_RT_HANDSHAKE, kHelloRequest,
-                      sizeof(kHelloRequest), ssl, ssl->msg_callback_arg);
-    }
-
-    if (!SSL_is_init_finished(ssl) || !ssl->s3->initial_handshake_complete) {
-      /* This cannot happen. If a handshake is in progress, |type| must be
-       * |SSL3_RT_HANDSHAKE|. */
-      assert(0);
-      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-      goto err;
-    }
-
-    if (ssl->renegotiate_mode == ssl_renegotiate_ignore) {
-      goto start;
-    }
-
-    /* Renegotiation is only supported at quiescent points in the application
-     * protocol, namely in HTTPS, just before reading the HTTP response. Require
-     * the record-layer be idle and avoid complexities of sending a handshake
-     * record while an application_data record is being written. */
-    if (ssl_write_buffer_is_pending(ssl)) {
-      al = SSL_AD_NO_RENEGOTIATION;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_NO_RENEGOTIATION);
-      goto f_err;
-    }
-
-    /* Begin a new handshake. */
-    ssl->s3->total_renegotiations++;
-    ssl->state = SSL_ST_CONNECT;
-    i = ssl->handshake_func(ssl);
-    if (i < 0) {
-      return i;
-    }
-    if (i == 0) {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_HANDSHAKE_FAILURE);
-      return -1;
-    }
-
-    /* The handshake completed synchronously. Continue reading records. */
-    goto start;
-  }
-
-  /* If an alert record, process one alert out of the record. Note that we allow
-   * a single record to contain multiple alerts. */
-  if (rr->type == SSL3_RT_ALERT) {
-    /* Alerts may not be fragmented. */
-    if (rr->length < 2) {
-      al = SSL_AD_DECODE_ERROR;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ALERT);
-      goto f_err;
-    }
-
-    if (ssl->msg_callback) {
-      ssl->msg_callback(0, ssl->version, SSL3_RT_ALERT, rr->data, 2, ssl,
-                        ssl->msg_callback_arg);
-    }
-    const uint8_t alert_level = rr->data[0];
-    const uint8_t alert_descr = rr->data[1];
-    rr->length -= 2;
-    rr->data += 2;
-
-    if (ssl->info_callback != NULL) {
-      cb = ssl->info_callback;
-    } else if (ssl->ctx->info_callback != NULL) {
-      cb = ssl->ctx->info_callback;
-    }
-
-    if (cb != NULL) {
-      uint16_t alert = (alert_level << 8) | alert_descr;
-      cb(ssl, SSL_CB_READ_ALERT, alert);
-    }
-
-    if (alert_level == SSL3_AL_WARNING) {
-      ssl->s3->warn_alert = alert_descr;
-      if (alert_descr == SSL_AD_CLOSE_NOTIFY) {
-        ssl->shutdown |= SSL_RECEIVED_SHUTDOWN;
-        return 0;
-      }
-
-      /* This is a warning but we receive it if we requested renegotiation and
-       * the peer denied it. Terminate with a fatal alert because if
-       * application tried to renegotiatie it presumably had a good reason and
-       * expects it to succeed.
-       *
-       * In future we might have a renegotiation where we don't care if the
-       * peer refused it where we carry on. */
-      else if (alert_descr == SSL_AD_NO_RENEGOTIATION) {
-        al = SSL_AD_HANDSHAKE_FAILURE;
-        OPENSSL_PUT_ERROR(SSL, SSL_R_NO_RENEGOTIATION);
-        goto f_err;
-      }
-
-      ssl->s3->warning_alert_count++;
-      if (ssl->s3->warning_alert_count > kMaxWarningAlerts) {
-        al = SSL_AD_UNEXPECTED_MESSAGE;
-        OPENSSL_PUT_ERROR(SSL, SSL_R_TOO_MANY_WARNING_ALERTS);
-        goto f_err;
-      }
-    } else if (alert_level == SSL3_AL_FATAL) {
-      char tmp[16];
-
-      ssl->rwstate = SSL_NOTHING;
-      ssl->s3->fatal_alert = alert_descr;
-      OPENSSL_PUT_ERROR(SSL, SSL_AD_REASON_OFFSET + alert_descr);
-      BIO_snprintf(tmp, sizeof(tmp), "%d", alert_descr);
-      ERR_add_error_data(2, "SSL alert number ", tmp);
-      ssl->shutdown |= SSL_RECEIVED_SHUTDOWN;
-      SSL_CTX_remove_session(ssl->ctx, ssl->session);
-      return 0;
-    } else {
-      al = SSL_AD_ILLEGAL_PARAMETER;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_ALERT_TYPE);
-      goto f_err;
-    }
-
-    goto start;
-  }
-
-  if (ssl->shutdown & SSL_SENT_SHUTDOWN) {
-    /* close_notify has been sent, so discard all records other than alerts. */
-    rr->length = 0;
-    goto start;
-  }
-
-  al = SSL_AD_UNEXPECTED_MESSAGE;
-  OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
-
-f_err:
-  ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
-err:
-  return -1;
-}
-
-int ssl3_do_change_cipher_spec(SSL *ssl) {
-  int i;
-
-  if (ssl->state & SSL_ST_ACCEPT) {
-    i = SSL3_CHANGE_CIPHER_SERVER_READ;
-  } else {
-    i = SSL3_CHANGE_CIPHER_CLIENT_READ;
-  }
-
-  if (ssl->s3->tmp.key_block == NULL) {
-    if (ssl->session == NULL || ssl->session->master_key_length == 0) {
-      /* might happen if dtls1_read_bytes() calls this */
-      OPENSSL_PUT_ERROR(SSL, SSL_R_CCS_RECEIVED_EARLY);
-      return 0;
-    }
-
-    ssl->session->cipher = ssl->s3->tmp.new_cipher;
-    if (!ssl->enc_method->setup_key_block(ssl)) {
-      return 0;
-    }
-  }
-
-  if (!ssl->enc_method->change_cipher_state(ssl, i)) {
-    return 0;
-  }
-
-  return 1;
-}
-
-int ssl3_send_alert(SSL *ssl, int level, int desc) {
-  /* Map tls/ssl alert value to correct one */
-  desc = ssl->enc_method->alert_value(desc);
-  if (ssl->version == SSL3_VERSION && desc == SSL_AD_PROTOCOL_VERSION) {
-    /* SSL 3.0 does not have protocol_version alerts */
-    desc = SSL_AD_HANDSHAKE_FAILURE;
-  }
-  if (desc < 0) {
+  if (rr->type != SSL3_RT_CHANGE_CIPHER_SPEC) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+    OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
     return -1;
   }
 
-  /* If a fatal one, remove from cache */
-  if (level == 2 && ssl->session != NULL) {
-    SSL_CTX_remove_session(ssl->ctx, ssl->session);
+  if (rr->length != 1 || rr->data[0] != SSL3_MT_CCS) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_CHANGE_CIPHER_SPEC);
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+    return -1;
+  }
+
+  ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_CHANGE_CIPHER_SPEC, rr->data,
+                      rr->length);
+
+  rr->length = 0;
+  ssl_read_buffer_discard(ssl);
+  return 1;
+}
+
+void ssl3_read_close_notify(SSL *ssl) {
+  /* Read records until an error or close_notify. */
+  while (ssl3_get_record(ssl) > 0) {
+    ;
+  }
+}
+
+int ssl3_read_handshake_bytes(SSL *ssl, uint8_t *buf, int len) {
+  SSL3_RECORD *rr = &ssl->s3->rrec;
+
+  for (;;) {
+    /* Get new packet if necessary. */
+    if (rr->length == 0) {
+      int ret = ssl3_get_record(ssl);
+      if (ret <= 0) {
+        return ret;
+      }
+    }
+
+    if (rr->type != SSL3_RT_HANDSHAKE) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_RECORD);
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+      return -1;
+    }
+
+    if (rr->length != 0) {
+      return consume_record(ssl, buf, len, 0 /* consume data */);
+    }
+
+    /* Discard empty records and loop again. */
+  }
+}
+
+int ssl3_send_alert(SSL *ssl, int level, int desc) {
+  /* It is illegal to send an alert when we've already sent a closing one. */
+  if (ssl->s3->send_shutdown != ssl_shutdown_none) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_PROTOCOL_IS_SHUTDOWN);
+    return -1;
+  }
+
+  if (level == SSL3_AL_WARNING && desc == SSL_AD_CLOSE_NOTIFY) {
+    ssl->s3->send_shutdown = ssl_shutdown_close_notify;
+  } else {
+    assert(level == SSL3_AL_FATAL);
+    ssl->s3->send_shutdown = ssl_shutdown_fatal_alert;
   }
 
   ssl->s3->alert_dispatch = 1;
@@ -688,45 +487,30 @@
   if (!ssl_write_buffer_is_pending(ssl)) {
     /* Nothing is being written out, so the alert may be dispatched
      * immediately. */
-    return ssl->method->ssl_dispatch_alert(ssl);
+    return ssl->method->dispatch_alert(ssl);
   }
 
-  /* else data is still being written out, we will get written some time in the
-   * future */
+  /* The alert will be dispatched later. */
   return -1;
 }
 
 int ssl3_dispatch_alert(SSL *ssl) {
-  int i, j;
-  void (*cb)(const SSL *ssl, int type, int value) = NULL;
-
+  int ret = do_ssl3_write(ssl, SSL3_RT_ALERT, &ssl->s3->send_alert[0], 2);
+  if (ret <= 0) {
+    return ret;
+  }
   ssl->s3->alert_dispatch = 0;
-  i = do_ssl3_write(ssl, SSL3_RT_ALERT, &ssl->s3->send_alert[0], 2);
-  if (i <= 0) {
-    ssl->s3->alert_dispatch = 1;
-  } else {
-    /* Alert sent to BIO.  If it is important, flush it now. If the message
-     * does not get sent due to non-blocking IO, we will not worry too much. */
-    if (ssl->s3->send_alert[0] == SSL3_AL_FATAL) {
-      BIO_flush(ssl->wbio);
-    }
 
-    if (ssl->msg_callback) {
-      ssl->msg_callback(1, ssl->version, SSL3_RT_ALERT, ssl->s3->send_alert, 2,
-                        ssl, ssl->msg_callback_arg);
-    }
-
-    if (ssl->info_callback != NULL) {
-      cb = ssl->info_callback;
-    } else if (ssl->ctx->info_callback != NULL) {
-      cb = ssl->ctx->info_callback;
-    }
-
-    if (cb != NULL) {
-      j = (ssl->s3->send_alert[0] << 8) | ssl->s3->send_alert[1];
-      cb(ssl, SSL_CB_WRITE_ALERT, j);
-    }
+  /* If the alert is fatal, flush the BIO now. */
+  if (ssl->s3->send_alert[0] == SSL3_AL_FATAL) {
+    BIO_flush(ssl->wbio);
   }
 
-  return i;
+  ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_ALERT, ssl->s3->send_alert,
+                      2);
+
+  int alert = (ssl->s3->send_alert[0] << 8) | ssl->s3->send_alert[1];
+  ssl_do_info_callback(ssl, SSL_CB_WRITE_ALERT, alert);
+
+  return 1;
 }
diff --git a/src/ssl/s3_srvr.c b/src/ssl/s3_srvr.c
deleted file mode 100644
index 49a1a95..0000000
--- a/src/ssl/s3_srvr.c
+++ /dev/null
@@ -1,2279 +0,0 @@
-/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- * 
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to.  The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- * 
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- * 
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *    "This product includes cryptographic software written by
- *     Eric Young (eay@cryptsoft.com)"
- *    The word 'cryptographic' can be left out if the rouines from the library
- *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from 
- *    the apps directory (application code) you must include an acknowledgement:
- *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- * 
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * 
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed.  i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.]
- */
-/* ====================================================================
- * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer. 
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- *    software must display the following acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- *    endorse or promote products derived from this software without
- *    prior written permission. For written permission, please contact
- *    openssl-core@openssl.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- *    nor may "OpenSSL" appear in their names without prior written
- *    permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- *    acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
- *
- * This product includes cryptographic software written by Eric Young
- * (eay@cryptsoft.com).  This product includes software written by Tim
- * Hudson (tjh@cryptsoft.com).
- *
- */
-/* ====================================================================
- * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
- *
- * Portions of the attached software ("Contribution") are developed by 
- * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
- *
- * The Contribution is licensed pursuant to the OpenSSL open source
- * license provided above.
- *
- * ECC cipher suite support in OpenSSL originally written by
- * Vipul Gupta and Sumit Gupta of Sun Microsystems Laboratories.
- *
- */
-/* ====================================================================
- * Copyright 2005 Nokia. All rights reserved.
- *
- * The portions of the attached software ("Contribution") is developed by
- * Nokia Corporation and is licensed pursuant to the OpenSSL open source
- * license.
- *
- * The Contribution, originally written by Mika Kousa and Pasi Eronen of
- * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
- * support (see RFC 4279) to OpenSSL.
- *
- * No patent licenses or other rights except those expressly stated in
- * the OpenSSL open source license shall be deemed granted or received
- * expressly, by implication, estoppel, or otherwise.
- *
- * No assurances are provided by Nokia that the Contribution does not
- * infringe the patent or other intellectual property rights of any third
- * party or that the license provides you with all the necessary rights
- * to make use of the Contribution.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
- * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
- * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
- * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
- * OTHERWISE. */
-
-#include <openssl/ssl.h>
-
-#include <assert.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <openssl/bn.h>
-#include <openssl/buf.h>
-#include <openssl/bytestring.h>
-#include <openssl/cipher.h>
-#include <openssl/dh.h>
-#include <openssl/ec.h>
-#include <openssl/ecdsa.h>
-#include <openssl/err.h>
-#include <openssl/evp.h>
-#include <openssl/hmac.h>
-#include <openssl/md5.h>
-#include <openssl/mem.h>
-#include <openssl/obj.h>
-#include <openssl/rand.h>
-#include <openssl/sha.h>
-#include <openssl/x509.h>
-
-#include "internal.h"
-#include "../crypto/internal.h"
-#include "../crypto/dh/internal.h"
-
-
-int ssl3_accept(SSL *ssl) {
-  BUF_MEM *buf = NULL;
-  uint32_t alg_a;
-  void (*cb)(const SSL *ssl, int type, int value) = NULL;
-  int ret = -1;
-  int new_state, state, skip = 0;
-
-  assert(ssl->handshake_func == ssl3_accept);
-  assert(ssl->server);
-  assert(!SSL_IS_DTLS(ssl));
-
-  ERR_clear_error();
-  ERR_clear_system_error();
-
-  if (ssl->info_callback != NULL) {
-    cb = ssl->info_callback;
-  } else if (ssl->ctx->info_callback != NULL) {
-    cb = ssl->ctx->info_callback;
-  }
-
-  ssl->in_handshake++;
-
-  if (ssl->cert == NULL) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET);
-    return -1;
-  }
-
-  for (;;) {
-    state = ssl->state;
-
-    switch (ssl->state) {
-      case SSL_ST_ACCEPT:
-        if (cb != NULL) {
-          cb(ssl, SSL_CB_HANDSHAKE_START, 1);
-        }
-
-        if (ssl->init_buf == NULL) {
-          buf = BUF_MEM_new();
-          if (!buf || !BUF_MEM_grow(buf, SSL3_RT_MAX_PLAIN_LENGTH)) {
-            ret = -1;
-            goto end;
-          }
-          ssl->init_buf = buf;
-          buf = NULL;
-        }
-        ssl->init_num = 0;
-
-        /* Enable a write buffer. This groups handshake messages within a flight
-         * into a single write. */
-        if (!ssl_init_wbio_buffer(ssl, 1)) {
-          ret = -1;
-          goto end;
-        }
-
-        if (!ssl3_init_handshake_buffer(ssl)) {
-          OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-          ret = -1;
-          goto end;
-        }
-
-        if (!ssl->s3->have_version) {
-          ssl->state = SSL3_ST_SR_INITIAL_BYTES;
-        } else {
-          ssl->state = SSL3_ST_SR_CLNT_HELLO_A;
-        }
-        break;
-
-      case SSL3_ST_SR_INITIAL_BYTES:
-        ret = ssl3_get_initial_bytes(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        /* ssl3_get_initial_bytes sets ssl->state to one of
-         * SSL3_ST_SR_V2_CLIENT_HELLO or SSL3_ST_SR_CLNT_HELLO_A on success. */
-        break;
-
-      case SSL3_ST_SR_V2_CLIENT_HELLO:
-        ret = ssl3_get_v2_client_hello(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        ssl->state = SSL3_ST_SR_CLNT_HELLO_A;
-        break;
-
-      case SSL3_ST_SR_CLNT_HELLO_A:
-      case SSL3_ST_SR_CLNT_HELLO_B:
-      case SSL3_ST_SR_CLNT_HELLO_C:
-      case SSL3_ST_SR_CLNT_HELLO_D:
-        ssl->shutdown = 0;
-        ret = ssl3_get_client_hello(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        ssl->state = SSL3_ST_SW_SRVR_HELLO_A;
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_SW_SRVR_HELLO_A:
-      case SSL3_ST_SW_SRVR_HELLO_B:
-        ret = ssl3_send_server_hello(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        if (ssl->hit) {
-          if (ssl->tlsext_ticket_expected) {
-            ssl->state = SSL3_ST_SW_SESSION_TICKET_A;
-          } else {
-            ssl->state = SSL3_ST_SW_CHANGE_A;
-          }
-        } else {
-          ssl->state = SSL3_ST_SW_CERT_A;
-        }
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_SW_CERT_A:
-      case SSL3_ST_SW_CERT_B:
-        if (ssl_cipher_has_server_public_key(ssl->s3->tmp.new_cipher)) {
-          ret = ssl3_send_server_certificate(ssl);
-          if (ret <= 0) {
-            goto end;
-          }
-          if (ssl->s3->tmp.certificate_status_expected) {
-            ssl->state = SSL3_ST_SW_CERT_STATUS_A;
-          } else {
-            ssl->state = SSL3_ST_SW_KEY_EXCH_A;
-          }
-        } else {
-          skip = 1;
-          ssl->state = SSL3_ST_SW_KEY_EXCH_A;
-        }
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_SW_CERT_STATUS_A:
-      case SSL3_ST_SW_CERT_STATUS_B:
-        ret = ssl3_send_certificate_status(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        ssl->state = SSL3_ST_SW_KEY_EXCH_A;
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_SW_KEY_EXCH_A:
-      case SSL3_ST_SW_KEY_EXCH_B:
-      case SSL3_ST_SW_KEY_EXCH_C:
-        alg_a = ssl->s3->tmp.new_cipher->algorithm_auth;
-
-        /* Send a ServerKeyExchange message if:
-         * - The key exchange is ephemeral or anonymous
-         *   Diffie-Hellman.
-         * - There is a PSK identity hint.
-         *
-         * TODO(davidben): This logic is currently duplicated in d1_srvr.c. Fix
-         * this. In the meantime, keep them in sync. */
-        if (ssl_cipher_requires_server_key_exchange(ssl->s3->tmp.new_cipher) ||
-            ((alg_a & SSL_aPSK) && ssl->psk_identity_hint)) {
-          ret = ssl3_send_server_key_exchange(ssl);
-          if (ret <= 0) {
-            goto end;
-          }
-        } else {
-          skip = 1;
-        }
-
-        ssl->state = SSL3_ST_SW_CERT_REQ_A;
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_SW_CERT_REQ_A:
-      case SSL3_ST_SW_CERT_REQ_B:
-        if (ssl->s3->tmp.cert_request) {
-          ret = ssl3_send_certificate_request(ssl);
-          if (ret <= 0) {
-            goto end;
-          }
-        } else {
-          skip = 1;
-        }
-        ssl->state = SSL3_ST_SW_SRVR_DONE_A;
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_SW_SRVR_DONE_A:
-      case SSL3_ST_SW_SRVR_DONE_B:
-        ret = ssl3_send_server_done(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        ssl->s3->tmp.next_state = SSL3_ST_SR_CERT_A;
-        ssl->state = SSL3_ST_SW_FLUSH;
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_SW_FLUSH:
-        /* This code originally checked to see if any data was pending using
-         * BIO_CTRL_INFO and then flushed. This caused problems as documented
-         * in PR#1939. The proposed fix doesn't completely resolve this issue
-         * as buggy implementations of BIO_CTRL_PENDING still exist. So instead
-         * we just flush unconditionally. */
-        ssl->rwstate = SSL_WRITING;
-        if (BIO_flush(ssl->wbio) <= 0) {
-          ret = -1;
-          goto end;
-        }
-        ssl->rwstate = SSL_NOTHING;
-
-        ssl->state = ssl->s3->tmp.next_state;
-        break;
-
-      case SSL3_ST_SR_CERT_A:
-      case SSL3_ST_SR_CERT_B:
-        if (ssl->s3->tmp.cert_request) {
-          ret = ssl3_get_client_certificate(ssl);
-          if (ret <= 0) {
-            goto end;
-          }
-        }
-        ssl->init_num = 0;
-        ssl->state = SSL3_ST_SR_KEY_EXCH_A;
-        break;
-
-      case SSL3_ST_SR_KEY_EXCH_A:
-      case SSL3_ST_SR_KEY_EXCH_B:
-      case SSL3_ST_SR_KEY_EXCH_C:
-        ret = ssl3_get_client_key_exchange(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        ssl->state = SSL3_ST_SR_CERT_VRFY_A;
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_SR_CERT_VRFY_A:
-      case SSL3_ST_SR_CERT_VRFY_B:
-        ret = ssl3_get_cert_verify(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-
-        ssl->state = SSL3_ST_SR_CHANGE;
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_SR_CHANGE:
-        ret = ssl->method->ssl_read_change_cipher_spec(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-
-        if (!ssl3_do_change_cipher_spec(ssl)) {
-          ret = -1;
-          goto end;
-        }
-
-        if (ssl->s3->next_proto_neg_seen) {
-          ssl->state = SSL3_ST_SR_NEXT_PROTO_A;
-        } else if (ssl->s3->tlsext_channel_id_valid) {
-          ssl->state = SSL3_ST_SR_CHANNEL_ID_A;
-        } else {
-          ssl->state = SSL3_ST_SR_FINISHED_A;
-        }
-        break;
-
-      case SSL3_ST_SR_NEXT_PROTO_A:
-      case SSL3_ST_SR_NEXT_PROTO_B:
-        ret = ssl3_get_next_proto(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        ssl->init_num = 0;
-        if (ssl->s3->tlsext_channel_id_valid) {
-          ssl->state = SSL3_ST_SR_CHANNEL_ID_A;
-        } else {
-          ssl->state = SSL3_ST_SR_FINISHED_A;
-        }
-        break;
-
-      case SSL3_ST_SR_CHANNEL_ID_A:
-      case SSL3_ST_SR_CHANNEL_ID_B:
-        ret = ssl3_get_channel_id(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        ssl->init_num = 0;
-        ssl->state = SSL3_ST_SR_FINISHED_A;
-        break;
-
-      case SSL3_ST_SR_FINISHED_A:
-      case SSL3_ST_SR_FINISHED_B:
-        ret = ssl3_get_finished(ssl, SSL3_ST_SR_FINISHED_A,
-                                SSL3_ST_SR_FINISHED_B);
-        if (ret <= 0) {
-          goto end;
-        }
-
-        if (ssl->hit) {
-          ssl->state = SSL_ST_OK;
-        } else if (ssl->tlsext_ticket_expected) {
-          ssl->state = SSL3_ST_SW_SESSION_TICKET_A;
-        } else {
-          ssl->state = SSL3_ST_SW_CHANGE_A;
-        }
-        /* If this is a full handshake with ChannelID then record the hashshake
-         * hashes in |ssl->session| in case we need them to verify a ChannelID
-         * signature on a resumption of this session in the future. */
-        if (!ssl->hit && ssl->s3->tlsext_channel_id_valid) {
-          ret = tls1_record_handshake_hashes_for_channel_id(ssl);
-          if (ret <= 0) {
-            goto end;
-          }
-        }
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_SW_SESSION_TICKET_A:
-      case SSL3_ST_SW_SESSION_TICKET_B:
-        ret = ssl3_send_new_session_ticket(ssl);
-        if (ret <= 0) {
-          goto end;
-        }
-        ssl->state = SSL3_ST_SW_CHANGE_A;
-        ssl->init_num = 0;
-        break;
-
-      case SSL3_ST_SW_CHANGE_A:
-      case SSL3_ST_SW_CHANGE_B:
-        ssl->session->cipher = ssl->s3->tmp.new_cipher;
-        if (!ssl->enc_method->setup_key_block(ssl)) {
-          ret = -1;
-          goto end;
-        }
-
-        ret = ssl3_send_change_cipher_spec(ssl, SSL3_ST_SW_CHANGE_A,
-                                           SSL3_ST_SW_CHANGE_B);
-        if (ret <= 0) {
-          goto end;
-        }
-        ssl->state = SSL3_ST_SW_FINISHED_A;
-        ssl->init_num = 0;
-
-        if (!ssl->enc_method->change_cipher_state(
-                ssl, SSL3_CHANGE_CIPHER_SERVER_WRITE)) {
-          ret = -1;
-          goto end;
-        }
-        break;
-
-      case SSL3_ST_SW_FINISHED_A:
-      case SSL3_ST_SW_FINISHED_B:
-        ret = ssl3_send_finished(ssl, SSL3_ST_SW_FINISHED_A,
-                                 SSL3_ST_SW_FINISHED_B,
-                                 ssl->enc_method->server_finished_label,
-                                 ssl->enc_method->server_finished_label_len);
-        if (ret <= 0) {
-          goto end;
-        }
-        ssl->state = SSL3_ST_SW_FLUSH;
-        if (ssl->hit) {
-          ssl->s3->tmp.next_state = SSL3_ST_SR_CHANGE;
-        } else {
-          ssl->s3->tmp.next_state = SSL_ST_OK;
-        }
-        ssl->init_num = 0;
-        break;
-
-      case SSL_ST_OK:
-        /* clean a few things up */
-        ssl3_cleanup_key_block(ssl);
-
-        BUF_MEM_free(ssl->init_buf);
-        ssl->init_buf = NULL;
-
-        /* remove buffering on output */
-        ssl_free_wbio_buffer(ssl);
-
-        ssl->init_num = 0;
-
-        /* If we aren't retaining peer certificates then we can discard it
-         * now. */
-        if (ssl->ctx->retain_only_sha256_of_client_certs) {
-          X509_free(ssl->session->peer);
-          ssl->session->peer = NULL;
-          sk_X509_pop_free(ssl->session->cert_chain, X509_free);
-          ssl->session->cert_chain = NULL;
-        }
-
-        ssl->s3->initial_handshake_complete = 1;
-
-        ssl_update_cache(ssl, SSL_SESS_CACHE_SERVER);
-
-        if (cb != NULL) {
-          cb(ssl, SSL_CB_HANDSHAKE_DONE, 1);
-        }
-
-        ret = 1;
-        goto end;
-
-      default:
-        OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_STATE);
-        ret = -1;
-        goto end;
-    }
-
-    if (!ssl->s3->tmp.reuse_message && !skip && cb != NULL &&
-        ssl->state != state) {
-      new_state = ssl->state;
-      ssl->state = state;
-      cb(ssl, SSL_CB_ACCEPT_LOOP, 1);
-      ssl->state = new_state;
-    }
-    skip = 0;
-  }
-
-end:
-  ssl->in_handshake--;
-  BUF_MEM_free(buf);
-  if (cb != NULL) {
-    cb(ssl, SSL_CB_ACCEPT_EXIT, ret);
-  }
-  return ret;
-}
-
-int ssl3_get_initial_bytes(SSL *ssl) {
-  /* Read the first 5 bytes, the size of the TLS record header. This is
-   * sufficient to detect a V2ClientHello and ensures that we never read beyond
-   * the first record. */
-  int ret = ssl_read_buffer_extend_to(ssl, SSL3_RT_HEADER_LENGTH);
-  if (ret <= 0) {
-    return ret;
-  }
-  assert(ssl_read_buffer_len(ssl) == SSL3_RT_HEADER_LENGTH);
-  const uint8_t *p = ssl_read_buffer(ssl);
-
-  /* Some dedicated error codes for protocol mixups should the application wish
-   * to interpret them differently. (These do not overlap with ClientHello or
-   * V2ClientHello.) */
-  if (strncmp("GET ", (const char *)p, 4) == 0 ||
-      strncmp("POST ", (const char *)p, 5) == 0 ||
-      strncmp("HEAD ", (const char *)p, 5) == 0 ||
-      strncmp("PUT ", (const char *)p, 4) == 0) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_HTTP_REQUEST);
-    return -1;
-  }
-  if (strncmp("CONNE", (const char *)p, 5) == 0) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_HTTPS_PROXY_REQUEST);
-    return -1;
-  }
-
-  /* Determine if this is a V2ClientHello. */
-  if ((p[0] & 0x80) && p[2] == SSL2_MT_CLIENT_HELLO &&
-      p[3] >= SSL3_VERSION_MAJOR) {
-    /* This is a V2ClientHello. */
-    ssl->state = SSL3_ST_SR_V2_CLIENT_HELLO;
-    return 1;
-  }
-
-  /* Fall through to the standard logic. */
-  ssl->state = SSL3_ST_SR_CLNT_HELLO_A;
-  return 1;
-}
-
-int ssl3_get_v2_client_hello(SSL *ssl) {
-  const uint8_t *p;
-  int ret;
-  CBS v2_client_hello, cipher_specs, session_id, challenge;
-  size_t msg_length, rand_len, len;
-  uint8_t msg_type;
-  uint16_t version, cipher_spec_length, session_id_length, challenge_length;
-  CBB client_hello, hello_body, cipher_suites;
-  uint8_t random[SSL3_RANDOM_SIZE];
-
-  /* Determine the length of the V2ClientHello. */
-  assert(ssl_read_buffer_len(ssl) >= SSL3_RT_HEADER_LENGTH);
-  p = ssl_read_buffer(ssl);
-  msg_length = ((p[0] & 0x7f) << 8) | p[1];
-  if (msg_length > (1024 * 4)) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_RECORD_TOO_LARGE);
-    return -1;
-  }
-  if (msg_length < SSL3_RT_HEADER_LENGTH - 2) {
-    /* Reject lengths that are too short early. We have already read
-     * |SSL3_RT_HEADER_LENGTH| bytes, so we should not attempt to process an
-     * (invalid) V2ClientHello which would be shorter than that. */
-    OPENSSL_PUT_ERROR(SSL, SSL_R_RECORD_LENGTH_MISMATCH);
-    return -1;
-  }
-
-  /* Read the remainder of the V2ClientHello. */
-  ret = ssl_read_buffer_extend_to(ssl, 2 + msg_length);
-  if (ret <= 0) {
-    return ret;
-  }
-  assert(ssl_read_buffer_len(ssl) == msg_length + 2);
-  CBS_init(&v2_client_hello, ssl_read_buffer(ssl) + 2, msg_length);
-
-  /* The V2ClientHello without the length is incorporated into the handshake
-   * hash. */
-  if (!ssl3_update_handshake_hash(ssl, CBS_data(&v2_client_hello),
-                                  CBS_len(&v2_client_hello))) {
-    return -1;
-  }
-  if (ssl->msg_callback) {
-    ssl->msg_callback(0, SSL2_VERSION, 0, CBS_data(&v2_client_hello),
-                    CBS_len(&v2_client_hello), ssl, ssl->msg_callback_arg);
-  }
-
-  if (!CBS_get_u8(&v2_client_hello, &msg_type) ||
-      !CBS_get_u16(&v2_client_hello, &version) ||
-      !CBS_get_u16(&v2_client_hello, &cipher_spec_length) ||
-      !CBS_get_u16(&v2_client_hello, &session_id_length) ||
-      !CBS_get_u16(&v2_client_hello, &challenge_length) ||
-      !CBS_get_bytes(&v2_client_hello, &cipher_specs, cipher_spec_length) ||
-      !CBS_get_bytes(&v2_client_hello, &session_id, session_id_length) ||
-      !CBS_get_bytes(&v2_client_hello, &challenge, challenge_length) ||
-      CBS_len(&v2_client_hello) != 0) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
-    return -1;
-  }
-
-  /* msg_type has already been checked. */
-  assert(msg_type == SSL2_MT_CLIENT_HELLO);
-
-  /* The client_random is the V2ClientHello challenge. Truncate or
-   * left-pad with zeros as needed. */
-  memset(random, 0, SSL3_RANDOM_SIZE);
-  rand_len = CBS_len(&challenge);
-  if (rand_len > SSL3_RANDOM_SIZE) {
-    rand_len = SSL3_RANDOM_SIZE;
-  }
-  memcpy(random + (SSL3_RANDOM_SIZE - rand_len), CBS_data(&challenge),
-         rand_len);
-
-  /* Write out an equivalent SSLv3 ClientHello. */
-  CBB_zero(&client_hello);
-  if (!CBB_init_fixed(&client_hello, (uint8_t *)ssl->init_buf->data,
-                      ssl->init_buf->max) ||
-      !CBB_add_u8(&client_hello, SSL3_MT_CLIENT_HELLO) ||
-      !CBB_add_u24_length_prefixed(&client_hello, &hello_body) ||
-      !CBB_add_u16(&hello_body, version) ||
-      !CBB_add_bytes(&hello_body, random, SSL3_RANDOM_SIZE) ||
-      /* No session id. */
-      !CBB_add_u8(&hello_body, 0) ||
-      !CBB_add_u16_length_prefixed(&hello_body, &cipher_suites)) {
-    CBB_cleanup(&client_hello);
-    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-    return -1;
-  }
-
-  /* Copy the cipher suites. */
-  while (CBS_len(&cipher_specs) > 0) {
-    uint32_t cipher_spec;
-    if (!CBS_get_u24(&cipher_specs, &cipher_spec)) {
-      CBB_cleanup(&client_hello);
-      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
-      return -1;
-    }
-
-    /* Skip SSLv2 ciphers. */
-    if ((cipher_spec & 0xff0000) != 0) {
-      continue;
-    }
-    if (!CBB_add_u16(&cipher_suites, cipher_spec)) {
-      CBB_cleanup(&client_hello);
-      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-      return -1;
-    }
-  }
-
-  /* Add the null compression scheme and finish. */
-  if (!CBB_add_u8(&hello_body, 1) || !CBB_add_u8(&hello_body, 0) ||
-      !CBB_finish(&client_hello, NULL, &len)) {
-    CBB_cleanup(&client_hello);
-    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    return -1;
-  }
-
-  /* Mark the message for "re"-use by the version-specific method. */
-  ssl->s3->tmp.reuse_message = 1;
-  ssl->s3->tmp.message_type = SSL3_MT_CLIENT_HELLO;
-  /* The handshake message header is 4 bytes. */
-  ssl->s3->tmp.message_size = len - 4;
-
-  /* Consume and discard the V2ClientHello. */
-  ssl_read_buffer_consume(ssl, 2 + msg_length);
-  ssl_read_buffer_discard(ssl);
-
-  return 1;
-}
-
-int ssl3_get_client_hello(SSL *ssl) {
-  int ok, al = SSL_AD_INTERNAL_ERROR, ret = -1;
-  long n;
-  const SSL_CIPHER *c;
-  STACK_OF(SSL_CIPHER) *ciphers = NULL;
-  struct ssl_early_callback_ctx early_ctx;
-  CBS client_hello;
-  uint16_t client_version;
-  CBS client_random, session_id, cipher_suites, compression_methods;
-  SSL_SESSION *session = NULL;
-
-  /* We do this so that we will respond with our native type. If we are TLSv1
-   * and we get SSLv3, we will respond with TLSv1, This down switching should
-   * be handled by a different method. If we are SSLv3, we will respond with
-   * SSLv3, even if prompted with TLSv1. */
-  switch (ssl->state) {
-    case SSL3_ST_SR_CLNT_HELLO_A:
-    case SSL3_ST_SR_CLNT_HELLO_B:
-      n = ssl->method->ssl_get_message(
-          ssl, SSL3_ST_SR_CLNT_HELLO_A, SSL3_ST_SR_CLNT_HELLO_B,
-          SSL3_MT_CLIENT_HELLO, SSL3_RT_MAX_PLAIN_LENGTH,
-          ssl_hash_message, &ok);
-
-      if (!ok) {
-        return n;
-      }
-
-      ssl->state = SSL3_ST_SR_CLNT_HELLO_C;
-      /* fallthrough */
-    case SSL3_ST_SR_CLNT_HELLO_C:
-    case SSL3_ST_SR_CLNT_HELLO_D:
-      /* We have previously parsed the ClientHello message, and can't call
-       * ssl_get_message again without hashing the message into the Finished
-       * digest again. */
-      n = ssl->init_num;
-
-      memset(&early_ctx, 0, sizeof(early_ctx));
-      early_ctx.ssl = ssl;
-      early_ctx.client_hello = ssl->init_msg;
-      early_ctx.client_hello_len = n;
-      if (!ssl_early_callback_init(&early_ctx)) {
-        al = SSL_AD_DECODE_ERROR;
-        OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED);
-        goto f_err;
-      }
-
-      if (ssl->state == SSL3_ST_SR_CLNT_HELLO_C &&
-          ssl->ctx->select_certificate_cb != NULL) {
-        ssl->state = SSL3_ST_SR_CLNT_HELLO_D;
-        switch (ssl->ctx->select_certificate_cb(&early_ctx)) {
-          case 0:
-            ssl->rwstate = SSL_CERTIFICATE_SELECTION_PENDING;
-            goto err;
-
-          case -1:
-            /* Connection rejected. */
-            al = SSL_AD_ACCESS_DENIED;
-            OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_REJECTED);
-            goto f_err;
-
-          default:
-            /* fallthrough */;
-        }
-      }
-      ssl->state = SSL3_ST_SR_CLNT_HELLO_D;
-      break;
-
-    default:
-      OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_STATE);
-      return -1;
-  }
-
-  CBS_init(&client_hello, ssl->init_msg, n);
-  if (!CBS_get_u16(&client_hello, &client_version) ||
-      !CBS_get_bytes(&client_hello, &client_random, SSL3_RANDOM_SIZE) ||
-      !CBS_get_u8_length_prefixed(&client_hello, &session_id) ||
-      CBS_len(&session_id) > SSL_MAX_SSL_SESSION_ID_LENGTH) {
-    al = SSL_AD_DECODE_ERROR;
-    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
-    goto f_err;
-  }
-
-  /* use version from inside client hello, not from record header (may differ:
-   * see RFC 2246, Appendix E, second paragraph) */
-  ssl->client_version = client_version;
-
-  /* Load the client random. */
-  memcpy(ssl->s3->client_random, CBS_data(&client_random), SSL3_RANDOM_SIZE);
-
-  if (SSL_IS_DTLS(ssl)) {
-    CBS cookie;
-
-    if (!CBS_get_u8_length_prefixed(&client_hello, &cookie) ||
-        CBS_len(&cookie) > DTLS1_COOKIE_LENGTH) {
-      al = SSL_AD_DECODE_ERROR;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
-      goto f_err;
-    }
-  }
-
-  /* Note: This codepath may run twice if |ssl_get_prev_session| completes
-   * asynchronously.
-   *
-   * TODO(davidben): Clean up the order of events around ClientHello
-   * processing. */
-  if (!ssl->s3->have_version) {
-    /* Select version to use */
-    uint16_t version = ssl3_get_mutual_version(ssl, client_version);
-    if (version == 0) {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL);
-      ssl->version = ssl->client_version;
-      al = SSL_AD_PROTOCOL_VERSION;
-      goto f_err;
-    }
-    ssl->version = version;
-    ssl->enc_method = ssl3_get_enc_method(version);
-    assert(ssl->enc_method != NULL);
-    /* At this point, the connection's version is known and |ssl->version| is
-     * fixed. Begin enforcing the record-layer version. */
-    ssl->s3->have_version = 1;
-  } else if (SSL_IS_DTLS(ssl) ? (ssl->client_version > ssl->version)
-                            : (ssl->client_version < ssl->version)) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_VERSION_NUMBER);
-    al = SSL_AD_PROTOCOL_VERSION;
-    goto f_err;
-  }
-
-  ssl->hit = 0;
-  int send_new_ticket = 0;
-  switch (ssl_get_prev_session(ssl, &session, &send_new_ticket, &early_ctx)) {
-    case ssl_session_success:
-      break;
-    case ssl_session_error:
-      goto err;
-    case ssl_session_retry:
-      ssl->rwstate = SSL_PENDING_SESSION;
-      goto err;
-  }
-  ssl->tlsext_ticket_expected = send_new_ticket;
-
-  /* The EMS state is needed when making the resumption decision, but
-   * extensions are not normally parsed until later. This detects the EMS
-   * extension for the resumption decision and it's checked against the result
-   * of the normal parse later in this function. */
-  const uint8_t *ems_data;
-  size_t ems_len;
-  int have_extended_master_secret =
-      ssl->version != SSL3_VERSION &&
-      SSL_early_callback_ctx_extension_get(&early_ctx,
-                                           TLSEXT_TYPE_extended_master_secret,
-                                           &ems_data, &ems_len) &&
-      ems_len == 0;
-
-  if (session != NULL) {
-    if (session->extended_master_secret &&
-        !have_extended_master_secret) {
-      /* A ClientHello without EMS that attempts to resume a session with EMS
-       * is fatal to the connection. */
-      al = SSL_AD_HANDSHAKE_FAILURE;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_RESUMED_EMS_SESSION_WITHOUT_EMS_EXTENSION);
-      goto f_err;
-    }
-
-    ssl->hit =
-        /* Only resume if the session's version matches the negotiated version:
-         * most clients do not accept a mismatch. */
-        ssl->version == session->ssl_version &&
-        /* If the client offers the EMS extension, but the previous session
-         * didn't use it, then negotiate a new session. */
-        have_extended_master_secret == session->extended_master_secret;
-  }
-
-  if (ssl->hit) {
-    /* Use the new session. */
-    SSL_SESSION_free(ssl->session);
-    ssl->session = session;
-    session = NULL;
-
-    ssl->verify_result = ssl->session->verify_result;
-  } else {
-    if (!ssl_get_new_session(ssl, 1 /* server */)) {
-      goto err;
-    }
-
-    /* Clear the session ID if we want the session to be single-use. */
-    if (!(ssl->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER)) {
-      ssl->session->session_id_length = 0;
-    }
-  }
-
-  if (ssl->ctx->dos_protection_cb != NULL &&
-      ssl->ctx->dos_protection_cb(&early_ctx) == 0) {
-    /* Connection rejected for DOS reasons. */
-    al = SSL_AD_ACCESS_DENIED;
-    OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_REJECTED);
-    goto f_err;
-  }
-
-  if (!CBS_get_u16_length_prefixed(&client_hello, &cipher_suites) ||
-      CBS_len(&cipher_suites) == 0 ||
-      CBS_len(&cipher_suites) % 2 != 0 ||
-      !CBS_get_u8_length_prefixed(&client_hello, &compression_methods) ||
-      CBS_len(&compression_methods) == 0) {
-    al = SSL_AD_DECODE_ERROR;
-    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
-    goto f_err;
-  }
-
-  ciphers = ssl_bytes_to_cipher_list(ssl, &cipher_suites);
-  if (ciphers == NULL) {
-    goto err;
-  }
-
-  /* If it is a hit, check that the cipher is in the list. */
-  if (ssl->hit) {
-    size_t j;
-    int found_cipher = 0;
-    uint32_t id = ssl->session->cipher->id;
-
-    for (j = 0; j < sk_SSL_CIPHER_num(ciphers); j++) {
-      c = sk_SSL_CIPHER_value(ciphers, j);
-      if (c->id == id) {
-        found_cipher = 1;
-        break;
-      }
-    }
-
-    if (!found_cipher) {
-      /* we need to have the cipher in the cipher list if we are asked to reuse
-       * it */
-      al = SSL_AD_ILLEGAL_PARAMETER;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_REQUIRED_CIPHER_MISSING);
-      goto f_err;
-    }
-  }
-
-  /* Only null compression is supported. */
-  if (memchr(CBS_data(&compression_methods), 0,
-             CBS_len(&compression_methods)) == NULL) {
-    al = SSL_AD_ILLEGAL_PARAMETER;
-    OPENSSL_PUT_ERROR(SSL, SSL_R_NO_COMPRESSION_SPECIFIED);
-    goto f_err;
-  }
-
-  /* TLS extensions. */
-  if (ssl->version >= SSL3_VERSION &&
-      !ssl_parse_clienthello_tlsext(ssl, &client_hello)) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
-    goto err;
-  }
-
-  /* There should be nothing left over in the record. */
-  if (CBS_len(&client_hello) != 0) {
-    /* wrong packet length */
-    al = SSL_AD_DECODE_ERROR;
-    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_PACKET_LENGTH);
-    goto f_err;
-  }
-
-  if (have_extended_master_secret != ssl->s3->tmp.extended_master_secret) {
-    al = SSL_AD_INTERNAL_ERROR;
-    OPENSSL_PUT_ERROR(SSL, SSL_R_EMS_STATE_INCONSISTENT);
-    goto f_err;
-  }
-
-  /* Given ciphers and SSL_get_ciphers, we must pick a cipher */
-  if (!ssl->hit) {
-    if (ciphers == NULL) {
-      al = SSL_AD_ILLEGAL_PARAMETER;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CIPHERS_PASSED);
-      goto f_err;
-    }
-
-    /* Let cert callback update server certificates if required */
-    if (ssl->cert->cert_cb) {
-      int rv = ssl->cert->cert_cb(ssl, ssl->cert->cert_cb_arg);
-      if (rv == 0) {
-        al = SSL_AD_INTERNAL_ERROR;
-        OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_CB_ERROR);
-        goto f_err;
-      }
-      if (rv < 0) {
-        ssl->rwstate = SSL_X509_LOOKUP;
-        goto err;
-      }
-      ssl->rwstate = SSL_NOTHING;
-    }
-    c = ssl3_choose_cipher(ssl, ciphers, ssl_get_cipher_preferences(ssl));
-
-    if (c == NULL) {
-      al = SSL_AD_HANDSHAKE_FAILURE;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_NO_SHARED_CIPHER);
-      goto f_err;
-    }
-    ssl->s3->tmp.new_cipher = c;
-
-    /* Determine whether to request a client certificate. */
-    ssl->s3->tmp.cert_request = !!(ssl->verify_mode & SSL_VERIFY_PEER);
-    /* Only request a certificate if Channel ID isn't negotiated. */
-    if ((ssl->verify_mode & SSL_VERIFY_PEER_IF_NO_OBC) &&
-        ssl->s3->tlsext_channel_id_valid) {
-      ssl->s3->tmp.cert_request = 0;
-    }
-    /* Plain PSK forbids Certificate and CertificateRequest. */
-    if (ssl->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK) {
-      ssl->s3->tmp.cert_request = 0;
-    }
-  } else {
-    /* Session-id reuse */
-    ssl->s3->tmp.new_cipher = ssl->session->cipher;
-    ssl->s3->tmp.cert_request = 0;
-  }
-
-  /* Now that the cipher is known, initialize the handshake hash. */
-  if (!ssl3_init_handshake_hash(ssl)) {
-    goto f_err;
-  }
-
-  /* In TLS 1.2, client authentication requires hashing the handshake transcript
-   * under a different hash. Otherwise, release the handshake buffer. */
-  if (!SSL_USE_SIGALGS(ssl) || !ssl->s3->tmp.cert_request) {
-    ssl3_free_handshake_buffer(ssl);
-  }
-
-  /* we now have the following setup;
-   * client_random
-   * cipher_list        - our prefered list of ciphers
-   * ciphers            - the clients prefered list of ciphers
-   * compression        - basically ignored right now
-   * ssl version is set - sslv3
-   * ssl->session         - The ssl session has been setup.
-   * ssl->hit             - session reuse flag
-   * ssl->tmp.new_cipher  - the new cipher to use. */
-
-  ret = 1;
-
-  if (0) {
-  f_err:
-    ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
-  }
-
-err:
-  sk_SSL_CIPHER_free(ciphers);
-  SSL_SESSION_free(session);
-  return ret;
-}
-
-int ssl3_send_server_hello(SSL *ssl) {
-  if (ssl->state == SSL3_ST_SW_SRVR_HELLO_B) {
-    return ssl_do_write(ssl);
-  }
-
-  assert(ssl->state == SSL3_ST_SW_SRVR_HELLO_A);
-
-  /* We only accept ChannelIDs on connections with ECDHE in order to avoid a
-   * known attack while we fix ChannelID itself. */
-  if (ssl->s3->tlsext_channel_id_valid &&
-      (ssl->s3->tmp.new_cipher->algorithm_mkey & SSL_kECDHE) == 0) {
-    ssl->s3->tlsext_channel_id_valid = 0;
-  }
-
-  /* If this is a resumption and the original handshake didn't support
-   * ChannelID then we didn't record the original handshake hashes in the
-   * session and so cannot resume with ChannelIDs. */
-  if (ssl->hit && ssl->session->original_handshake_hash_len == 0) {
-    ssl->s3->tlsext_channel_id_valid = 0;
-  }
-
-  if (!ssl_fill_hello_random(ssl->s3->server_random, SSL3_RANDOM_SIZE,
-                             1 /* server */)) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    return -1;
-  }
-
-  CBB cbb, session_id;
-  size_t length;
-  CBB_zero(&cbb);
-  if (!CBB_init_fixed(&cbb, ssl_handshake_start(ssl),
-                      ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl)) ||
-      !CBB_add_u16(&cbb, ssl->version) ||
-      !CBB_add_bytes(&cbb, ssl->s3->server_random, SSL3_RANDOM_SIZE) ||
-      !CBB_add_u8_length_prefixed(&cbb, &session_id) ||
-      !CBB_add_bytes(&session_id, ssl->session->session_id,
-                     ssl->session->session_id_length) ||
-      !CBB_add_u16(&cbb, ssl_cipher_get_value(ssl->s3->tmp.new_cipher)) ||
-      !CBB_add_u8(&cbb, 0 /* no compression */) ||
-      !ssl_add_serverhello_tlsext(ssl, &cbb) ||
-      !CBB_finish(&cbb, NULL, &length) ||
-      !ssl_set_handshake_header(ssl, SSL3_MT_SERVER_HELLO, length)) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    CBB_cleanup(&cbb);
-    return -1;
-  }
-
-  ssl->state = SSL3_ST_SW_SRVR_HELLO_B;
-  return ssl_do_write(ssl);
-}
-
-int ssl3_send_certificate_status(SSL *ssl) {
-  if (ssl->state == SSL3_ST_SW_CERT_STATUS_A) {
-    CBB out, ocsp_response;
-    size_t length;
-
-    CBB_zero(&out);
-    if (!CBB_init_fixed(&out, ssl_handshake_start(ssl),
-                        ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl)) ||
-        !CBB_add_u8(&out, TLSEXT_STATUSTYPE_ocsp) ||
-        !CBB_add_u24_length_prefixed(&out, &ocsp_response) ||
-        !CBB_add_bytes(&ocsp_response, ssl->ctx->ocsp_response,
-                       ssl->ctx->ocsp_response_length) ||
-        !CBB_finish(&out, NULL, &length) ||
-        !ssl_set_handshake_header(ssl, SSL3_MT_CERTIFICATE_STATUS, length)) {
-      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-      CBB_cleanup(&out);
-      return -1;
-    }
-
-    ssl->state = SSL3_ST_SW_CERT_STATUS_B;
-  }
-
-  /* SSL3_ST_SW_CERT_STATUS_B */
-  return ssl_do_write(ssl);
-}
-
-int ssl3_send_server_done(SSL *ssl) {
-  if (ssl->state == SSL3_ST_SW_SRVR_DONE_A) {
-    if (!ssl_set_handshake_header(ssl, SSL3_MT_SERVER_DONE, 0)) {
-      return -1;
-    }
-    ssl->state = SSL3_ST_SW_SRVR_DONE_B;
-  }
-
-  /* SSL3_ST_SW_SRVR_DONE_B */
-  return ssl_do_write(ssl);
-}
-
-int ssl3_send_server_key_exchange(SSL *ssl) {
-  if (ssl->state == SSL3_ST_SW_KEY_EXCH_C) {
-    return ssl_do_write(ssl);
-  }
-
-  CBB cbb, child;
-  if (!CBB_init_fixed(&cbb, ssl_handshake_start(ssl),
-                      ssl->init_buf->max - SSL_HM_HEADER_LENGTH(ssl))) {
-    goto err;
-  }
-
-  if (ssl->state == SSL3_ST_SW_KEY_EXCH_A) {
-    /* This is the first iteration, so write parameters. */
-    uint32_t alg_k = ssl->s3->tmp.new_cipher->algorithm_mkey;
-    uint32_t alg_a = ssl->s3->tmp.new_cipher->algorithm_auth;
-
-    /* PSK ciphers begin with an identity hint. */
-    if (alg_a & SSL_aPSK) {
-      size_t len =
-          (ssl->psk_identity_hint == NULL) ? 0 : strlen(ssl->psk_identity_hint);
-      if (!CBB_add_u16_length_prefixed(&cbb, &child) ||
-          !CBB_add_bytes(&child, (const uint8_t *)ssl->psk_identity_hint,
-                         len)) {
-        goto err;
-      }
-    }
-
-    if (alg_k & SSL_kDHE) {
-      /* Determine the group to use. */
-      DH *params = ssl->cert->dh_tmp;
-      if (params == NULL && ssl->cert->dh_tmp_cb != NULL) {
-        params = ssl->cert->dh_tmp_cb(ssl, 0, 1024);
-      }
-      if (params == NULL) {
-        OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_TMP_DH_KEY);
-        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
-        goto err;
-      }
-      ssl->session->key_exchange_info = DH_num_bits(params);
-
-      /* Set up DH, generate a key, and emit the public half. */
-      DH *dh = DHparams_dup(params);
-      if (dh == NULL) {
-        goto err;
-      }
-
-      SSL_ECDH_CTX_init_for_dhe(&ssl->s3->tmp.ecdh_ctx, dh);
-      if (!CBB_add_u16_length_prefixed(&cbb, &child) ||
-          !BN_bn2cbb_padded(&child, BN_num_bytes(params->p), params->p) ||
-          !CBB_add_u16_length_prefixed(&cbb, &child) ||
-          !BN_bn2cbb_padded(&child, BN_num_bytes(params->g), params->g) ||
-          !CBB_add_u16_length_prefixed(&cbb, &child) ||
-          !SSL_ECDH_CTX_generate_keypair(&ssl->s3->tmp.ecdh_ctx, &child)) {
-        goto err;
-      }
-    } else if (alg_k & SSL_kECDHE) {
-      /* Determine the curve to use. */
-      uint16_t curve_id;
-      if (!tls1_get_shared_curve(ssl, &curve_id)) {
-        OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_TMP_ECDH_KEY);
-        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
-        goto err;
-      }
-      ssl->session->key_exchange_info = curve_id;
-
-      /* Set up ECDH, generate a key, and emit the public half. */
-      if (!SSL_ECDH_CTX_init(&ssl->s3->tmp.ecdh_ctx, curve_id) ||
-          !CBB_add_u8(&cbb, NAMED_CURVE_TYPE) ||
-          !CBB_add_u16(&cbb, curve_id) ||
-          !CBB_add_u8_length_prefixed(&cbb, &child) ||
-          !SSL_ECDH_CTX_generate_keypair(&ssl->s3->tmp.ecdh_ctx, &child)) {
-        goto err;
-      }
-    } else {
-      assert(alg_k & SSL_kPSK);
-    }
-
-    /* Otherwise, restore |cbb| from the previous iteration.
-     * TODO(davidben): When |ssl->init_buf| is gone, come up with a simpler
-     * pattern. Probably keep the |CBB| around in the handshake state. */
-  } else if (!CBB_did_write(&cbb, ssl->init_num - SSL_HM_HEADER_LENGTH(ssl))) {
-    goto err;
-  }
-
-  /* Add a signature. */
-  if (ssl_cipher_has_server_public_key(ssl->s3->tmp.new_cipher)) {
-    if (!ssl_has_private_key(ssl)) {
-      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-      goto err;
-    }
-
-    const size_t max_sig_len = ssl_private_key_max_signature_len(ssl);
-    size_t sig_len;
-    enum ssl_private_key_result_t sign_result;
-    if (ssl->state == SSL3_ST_SW_KEY_EXCH_A) {
-      /* This is the first iteration, so set up the signature. Sample the
-       * parameter length before adding a signature algorithm. */
-      if (!CBB_flush(&cbb)) {
-        goto err;
-      }
-      size_t params_len = CBB_len(&cbb);
-
-      /* Determine signature algorithm. */
-      const EVP_MD *md;
-      if (SSL_USE_SIGALGS(ssl)) {
-        md = tls1_choose_signing_digest(ssl);
-        if (!tls12_add_sigandhash(ssl, &cbb, md)) {
-          OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-          ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
-          goto err;
-        }
-      } else if (ssl_private_key_type(ssl) == EVP_PKEY_RSA) {
-        md = EVP_md5_sha1();
-      } else {
-        md = EVP_sha1();
-      }
-
-      /* Compute the digest and sign it. */
-      uint8_t digest[EVP_MAX_MD_SIZE];
-      unsigned digest_len = 0;
-      EVP_MD_CTX md_ctx;
-      EVP_MD_CTX_init(&md_ctx);
-      int digest_ret =
-          EVP_DigestInit_ex(&md_ctx, md, NULL) &&
-          EVP_DigestUpdate(&md_ctx, ssl->s3->client_random, SSL3_RANDOM_SIZE) &&
-          EVP_DigestUpdate(&md_ctx, ssl->s3->server_random, SSL3_RANDOM_SIZE) &&
-          EVP_DigestUpdate(&md_ctx, CBB_data(&cbb), params_len) &&
-          EVP_DigestFinal_ex(&md_ctx, digest, &digest_len);
-      EVP_MD_CTX_cleanup(&md_ctx);
-      uint8_t *ptr;
-      if (!digest_ret ||
-          !CBB_add_u16_length_prefixed(&cbb, &child) ||
-          !CBB_reserve(&child, &ptr, max_sig_len)) {
-        goto err;
-      }
-      sign_result = ssl_private_key_sign(ssl, ptr, &sig_len, max_sig_len, md,
-                                         digest, digest_len);
-    } else {
-      assert(ssl->state == SSL3_ST_SW_KEY_EXCH_B);
-
-      /* Retry the signature. */
-      uint8_t *ptr;
-      if (!CBB_add_u16_length_prefixed(&cbb, &child) ||
-          !CBB_reserve(&child, &ptr, max_sig_len)) {
-        goto err;
-      }
-      sign_result =
-          ssl_private_key_sign_complete(ssl, ptr, &sig_len, max_sig_len);
-    }
-
-    switch (sign_result) {
-      case ssl_private_key_success:
-        ssl->rwstate = SSL_NOTHING;
-        if (!CBB_did_write(&child, sig_len)) {
-          goto err;
-        }
-        break;
-      case ssl_private_key_failure:
-        ssl->rwstate = SSL_NOTHING;
-        goto err;
-      case ssl_private_key_retry:
-        /* Discard the unfinished signature and save the state of |cbb| for the
-         * next iteration. */
-        CBB_discard_child(&cbb);
-        ssl->init_num = SSL_HM_HEADER_LENGTH(ssl) + CBB_len(&cbb);
-        ssl->rwstate = SSL_PRIVATE_KEY_OPERATION;
-        ssl->state = SSL3_ST_SW_KEY_EXCH_B;
-        goto err;
-    }
-  }
-
-  size_t length;
-  if (!CBB_finish(&cbb, NULL, &length) ||
-      !ssl_set_handshake_header(ssl, SSL3_MT_SERVER_KEY_EXCHANGE, length)) {
-    goto err;
-  }
-  ssl->state = SSL3_ST_SW_KEY_EXCH_C;
-  return ssl_do_write(ssl);
-
-err:
-  CBB_cleanup(&cbb);
-  return -1;
-}
-
-int ssl3_send_certificate_request(SSL *ssl) {
-  uint8_t *p, *d;
-  size_t i;
-  int j, nl, off, n;
-  STACK_OF(X509_NAME) *sk = NULL;
-  X509_NAME *name;
-  BUF_MEM *buf;
-
-  if (ssl->state == SSL3_ST_SW_CERT_REQ_A) {
-    buf = ssl->init_buf;
-
-    d = p = ssl_handshake_start(ssl);
-
-    /* get the list of acceptable cert types */
-    p++;
-    n = ssl3_get_req_cert_type(ssl, p);
-    d[0] = n;
-    p += n;
-    n++;
-
-    if (SSL_USE_SIGALGS(ssl)) {
-      const uint8_t *psigs;
-      nl = tls12_get_psigalgs(ssl, &psigs);
-      s2n(nl, p);
-      memcpy(p, psigs, nl);
-      p += nl;
-      n += nl + 2;
-    }
-
-    off = n;
-    p += 2;
-    n += 2;
-
-    sk = SSL_get_client_CA_list(ssl);
-    nl = 0;
-    if (sk != NULL) {
-      for (i = 0; i < sk_X509_NAME_num(sk); i++) {
-        name = sk_X509_NAME_value(sk, i);
-        j = i2d_X509_NAME(name, NULL);
-        if (!BUF_MEM_grow_clean(buf, SSL_HM_HEADER_LENGTH(ssl) + n + j + 2)) {
-          OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
-          goto err;
-        }
-        p = ssl_handshake_start(ssl) + n;
-        s2n(j, p);
-        i2d_X509_NAME(name, &p);
-        n += 2 + j;
-        nl += 2 + j;
-      }
-    }
-
-    /* else no CA names */
-    p = ssl_handshake_start(ssl) + off;
-    s2n(nl, p);
-
-    if (!ssl_set_handshake_header(ssl, SSL3_MT_CERTIFICATE_REQUEST, n)) {
-      goto err;
-    }
-    ssl->state = SSL3_ST_SW_CERT_REQ_B;
-  }
-
-  /* SSL3_ST_SW_CERT_REQ_B */
-  return ssl_do_write(ssl);
-
-err:
-  return -1;
-}
-
-int ssl3_get_client_key_exchange(SSL *ssl) {
-  int al;
-  CBS client_key_exchange;
-  uint32_t alg_k;
-  uint32_t alg_a;
-  uint8_t *premaster_secret = NULL;
-  size_t premaster_secret_len = 0;
-  uint8_t *decrypt_buf = NULL;
-
-  unsigned psk_len = 0;
-  uint8_t psk[PSK_MAX_PSK_LEN];
-
-  if (ssl->state == SSL3_ST_SR_KEY_EXCH_A ||
-      ssl->state == SSL3_ST_SR_KEY_EXCH_B) {
-    int ok;
-    const long n = ssl->method->ssl_get_message(
-        ssl, SSL3_ST_SR_KEY_EXCH_A, SSL3_ST_SR_KEY_EXCH_B,
-        SSL3_MT_CLIENT_KEY_EXCHANGE, 2048 /* ??? */, ssl_hash_message, &ok);
-    if (!ok) {
-      return n;
-    }
-  }
-
-  CBS_init(&client_key_exchange, ssl->init_msg, ssl->init_num);
-  alg_k = ssl->s3->tmp.new_cipher->algorithm_mkey;
-  alg_a = ssl->s3->tmp.new_cipher->algorithm_auth;
-
-  /* If using a PSK key exchange, prepare the pre-shared key. */
-  if (alg_a & SSL_aPSK) {
-    CBS psk_identity;
-
-    /* If using PSK, the ClientKeyExchange contains a psk_identity. If PSK,
-     * then this is the only field in the message. */
-    if (!CBS_get_u16_length_prefixed(&client_key_exchange, &psk_identity) ||
-        ((alg_k & SSL_kPSK) && CBS_len(&client_key_exchange) != 0)) {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
-      al = SSL_AD_DECODE_ERROR;
-      goto f_err;
-    }
-
-    if (ssl->psk_server_callback == NULL) {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_NO_SERVER_CB);
-      al = SSL_AD_INTERNAL_ERROR;
-      goto f_err;
-    }
-
-    if (CBS_len(&psk_identity) > PSK_MAX_IDENTITY_LEN ||
-        CBS_contains_zero_byte(&psk_identity)) {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG);
-      al = SSL_AD_ILLEGAL_PARAMETER;
-      goto f_err;
-    }
-
-    if (!CBS_strdup(&psk_identity, &ssl->session->psk_identity)) {
-      al = SSL_AD_INTERNAL_ERROR;
-      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      goto f_err;
-    }
-
-    /* Look up the key for the identity. */
-    psk_len = ssl->psk_server_callback(ssl, ssl->session->psk_identity, psk,
-                                       sizeof(psk));
-    if (psk_len > PSK_MAX_PSK_LEN) {
-      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-      al = SSL_AD_INTERNAL_ERROR;
-      goto f_err;
-    } else if (psk_len == 0) {
-      /* PSK related to the given identity not found */
-      OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_NOT_FOUND);
-      al = SSL_AD_UNKNOWN_PSK_IDENTITY;
-      goto f_err;
-    }
-  }
-
-  /* Depending on the key exchange method, compute |premaster_secret| and
-   * |premaster_secret_len|. */
-  if (alg_k & SSL_kRSA) {
-    /* Allocate a buffer large enough for an RSA decryption. */
-    const size_t rsa_size = ssl_private_key_max_signature_len(ssl);
-    decrypt_buf = OPENSSL_malloc(rsa_size);
-    if (decrypt_buf == NULL) {
-      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      goto err;
-    }
-
-    enum ssl_private_key_result_t decrypt_result;
-    size_t decrypt_len;
-    if (ssl->state == SSL3_ST_SR_KEY_EXCH_B) {
-      if (!ssl_has_private_key(ssl) ||
-          ssl_private_key_type(ssl) != EVP_PKEY_RSA) {
-        al = SSL_AD_HANDSHAKE_FAILURE;
-        OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_RSA_CERTIFICATE);
-        goto f_err;
-      }
-      CBS encrypted_premaster_secret;
-      if (ssl->version > SSL3_VERSION) {
-        if (!CBS_get_u16_length_prefixed(&client_key_exchange,
-                                         &encrypted_premaster_secret) ||
-            CBS_len(&client_key_exchange) != 0) {
-          al = SSL_AD_DECODE_ERROR;
-          OPENSSL_PUT_ERROR(SSL,
-                            SSL_R_TLS_RSA_ENCRYPTED_VALUE_LENGTH_IS_WRONG);
-          goto f_err;
-        }
-      } else {
-        encrypted_premaster_secret = client_key_exchange;
-      }
-
-      /* Decrypt with no padding. PKCS#1 padding will be removed as part of the
-       * timing-sensitive code below. */
-      decrypt_result = ssl_private_key_decrypt(
-          ssl, decrypt_buf, &decrypt_len, rsa_size,
-          CBS_data(&encrypted_premaster_secret),
-          CBS_len(&encrypted_premaster_secret));
-    } else {
-      assert(ssl->state == SSL3_ST_SR_KEY_EXCH_C);
-      /* Complete async decrypt. */
-      decrypt_result = ssl_private_key_decrypt_complete(
-          ssl, decrypt_buf, &decrypt_len, rsa_size);
-    }
-
-    switch (decrypt_result) {
-      case ssl_private_key_success:
-        ssl->rwstate = SSL_NOTHING;
-        break;
-      case ssl_private_key_failure:
-        ssl->rwstate = SSL_NOTHING;
-        goto err;
-      case ssl_private_key_retry:
-        ssl->rwstate = SSL_PRIVATE_KEY_OPERATION;
-        ssl->state = SSL3_ST_SR_KEY_EXCH_C;
-        goto err;
-    }
-
-    assert(decrypt_len == rsa_size);
-
-    /* Prepare a random premaster, to be used on invalid padding. See RFC 5246,
-     * section 7.4.7.1. */
-    premaster_secret_len = SSL_MAX_MASTER_KEY_LENGTH;
-    premaster_secret = OPENSSL_malloc(premaster_secret_len);
-    if (premaster_secret == NULL) {
-      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      goto err;
-    }
-    if (!RAND_bytes(premaster_secret, premaster_secret_len)) {
-      goto err;
-    }
-
-    /* The smallest padded premaster is 11 bytes of overhead. Small keys are
-     * publicly invalid. */
-    if (decrypt_len < 11 + premaster_secret_len) {
-      al = SSL_AD_DECRYPT_ERROR;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED);
-      goto f_err;
-    }
-
-    /* Check the padding. See RFC 3447, section 7.2.2. */
-    size_t padding_len = decrypt_len - premaster_secret_len;
-    uint8_t good = constant_time_eq_int_8(decrypt_buf[0], 0) &
-                   constant_time_eq_int_8(decrypt_buf[1], 2);
-    size_t i;
-    for (i = 2; i < padding_len - 1; i++) {
-      good &= ~constant_time_is_zero_8(decrypt_buf[i]);
-    }
-    good &= constant_time_is_zero_8(decrypt_buf[padding_len - 1]);
-
-    /* The premaster secret must begin with |client_version|. This too must be
-     * checked in constant time (http://eprint.iacr.org/2003/052/). */
-    good &= constant_time_eq_8(decrypt_buf[padding_len],
-                               (unsigned)(ssl->client_version >> 8));
-    good &= constant_time_eq_8(decrypt_buf[padding_len + 1],
-                               (unsigned)(ssl->client_version & 0xff));
-
-    /* Select, in constant time, either the decrypted premaster or the random
-     * premaster based on |good|. */
-    for (i = 0; i < premaster_secret_len; i++) {
-      premaster_secret[i] = constant_time_select_8(
-          good, decrypt_buf[padding_len + i], premaster_secret[i]);
-    }
-
-    OPENSSL_free(decrypt_buf);
-    decrypt_buf = NULL;
-  } else if (alg_k & (SSL_kECDHE|SSL_kDHE)) {
-    /* Parse the ClientKeyExchange. ECDHE uses a u8 length prefix while DHE uses
-     * u16. */
-    CBS peer_key;
-    int peer_key_ok;
-    if (alg_k & SSL_kECDHE) {
-      peer_key_ok = CBS_get_u8_length_prefixed(&client_key_exchange, &peer_key);
-    } else {
-      peer_key_ok =
-          CBS_get_u16_length_prefixed(&client_key_exchange, &peer_key);
-    }
-
-    if (!peer_key_ok || CBS_len(&client_key_exchange) != 0) {
-      al = SSL_AD_DECODE_ERROR;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
-      goto f_err;
-    }
-
-    /* Compute the premaster. */
-    uint8_t alert;
-    if (!SSL_ECDH_CTX_compute_secret(&ssl->s3->tmp.ecdh_ctx, &premaster_secret,
-                                     &premaster_secret_len, &alert,
-                                     CBS_data(&peer_key), CBS_len(&peer_key))) {
-      al = alert;
-      goto f_err;
-    }
-
-    /* The key exchange state may now be discarded. */
-    SSL_ECDH_CTX_cleanup(&ssl->s3->tmp.ecdh_ctx);
-  } else if (alg_k & SSL_kPSK) {
-    /* For plain PSK, other_secret is a block of 0s with the same length as the
-     * pre-shared key. */
-    premaster_secret_len = psk_len;
-    premaster_secret = OPENSSL_malloc(premaster_secret_len);
-    if (premaster_secret == NULL) {
-      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      goto err;
-    }
-    memset(premaster_secret, 0, premaster_secret_len);
-  } else {
-    al = SSL_AD_HANDSHAKE_FAILURE;
-    OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CIPHER_TYPE);
-    goto f_err;
-  }
-
-  /* For a PSK cipher suite, the actual pre-master secret is combined with the
-   * pre-shared key. */
-  if (alg_a & SSL_aPSK) {
-    CBB new_premaster, child;
-    uint8_t *new_data;
-    size_t new_len;
-
-    CBB_zero(&new_premaster);
-    if (!CBB_init(&new_premaster, 2 + psk_len + 2 + premaster_secret_len) ||
-        !CBB_add_u16_length_prefixed(&new_premaster, &child) ||
-        !CBB_add_bytes(&child, premaster_secret, premaster_secret_len) ||
-        !CBB_add_u16_length_prefixed(&new_premaster, &child) ||
-        !CBB_add_bytes(&child, psk, psk_len) ||
-        !CBB_finish(&new_premaster, &new_data, &new_len)) {
-      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      CBB_cleanup(&new_premaster);
-      goto err;
-    }
-
-    OPENSSL_cleanse(premaster_secret, premaster_secret_len);
-    OPENSSL_free(premaster_secret);
-    premaster_secret = new_data;
-    premaster_secret_len = new_len;
-  }
-
-  /* Compute the master secret */
-  ssl->session->master_key_length = ssl->enc_method->generate_master_secret(
-      ssl, ssl->session->master_key, premaster_secret, premaster_secret_len);
-  if (ssl->session->master_key_length == 0) {
-    goto err;
-  }
-  ssl->session->extended_master_secret = ssl->s3->tmp.extended_master_secret;
-
-  OPENSSL_cleanse(premaster_secret, premaster_secret_len);
-  OPENSSL_free(premaster_secret);
-  return 1;
-
-f_err:
-  ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
-err:
-  if (premaster_secret != NULL) {
-    OPENSSL_cleanse(premaster_secret, premaster_secret_len);
-    OPENSSL_free(premaster_secret);
-  }
-  OPENSSL_free(decrypt_buf);
-
-  return -1;
-}
-
-int ssl3_get_cert_verify(SSL *ssl) {
-  int al, ok, ret = 0;
-  long n;
-  CBS certificate_verify, signature;
-  X509 *peer = ssl->session->peer;
-  EVP_PKEY *pkey = NULL;
-  const EVP_MD *md = NULL;
-  uint8_t digest[EVP_MAX_MD_SIZE];
-  size_t digest_length;
-  EVP_PKEY_CTX *pctx = NULL;
-
-  /* Only RSA and ECDSA client certificates are supported, so a
-   * CertificateVerify is required if and only if there's a client certificate.
-   * */
-  if (peer == NULL) {
-    ssl3_free_handshake_buffer(ssl);
-    return 1;
-  }
-
-  n = ssl->method->ssl_get_message(
-      ssl, SSL3_ST_SR_CERT_VRFY_A, SSL3_ST_SR_CERT_VRFY_B,
-      SSL3_MT_CERTIFICATE_VERIFY, SSL3_RT_MAX_PLAIN_LENGTH,
-      ssl_dont_hash_message, &ok);
-
-  if (!ok) {
-    return n;
-  }
-
-  /* Filter out unsupported certificate types. */
-  pkey = X509_get_pubkey(peer);
-  if (pkey == NULL) {
-    goto err;
-  }
-  if (!(X509_certificate_type(peer, pkey) & EVP_PKT_SIGN) ||
-      (pkey->type != EVP_PKEY_RSA && pkey->type != EVP_PKEY_EC)) {
-    al = SSL_AD_UNSUPPORTED_CERTIFICATE;
-    OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_ERROR_UNSUPPORTED_CERTIFICATE_TYPE);
-    goto f_err;
-  }
-
-  CBS_init(&certificate_verify, ssl->init_msg, n);
-
-  /* Determine the digest type if needbe. */
-  if (SSL_USE_SIGALGS(ssl)) {
-    uint8_t hash, signature_type;
-    if (!CBS_get_u8(&certificate_verify, &hash) ||
-        !CBS_get_u8(&certificate_verify, &signature_type)) {
-      al = SSL_AD_DECODE_ERROR;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
-      goto f_err;
-    }
-    if (!tls12_check_peer_sigalg(ssl, &md, &al, hash, signature_type, pkey)) {
-      goto f_err;
-    }
-  }
-
-  /* Compute the digest. */
-  if (!ssl3_cert_verify_hash(ssl, digest, &digest_length, &md, pkey->type)) {
-    goto err;
-  }
-
-  /* The handshake buffer is no longer necessary, and we may hash the current
-   * message.*/
-  ssl3_free_handshake_buffer(ssl);
-  if (!ssl3_hash_current_message(ssl)) {
-    goto err;
-  }
-
-  /* Parse and verify the signature. */
-  if (!CBS_get_u16_length_prefixed(&certificate_verify, &signature) ||
-      CBS_len(&certificate_verify) != 0) {
-    al = SSL_AD_DECODE_ERROR;
-    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
-    goto f_err;
-  }
-
-  pctx = EVP_PKEY_CTX_new(pkey, NULL);
-  if (pctx == NULL) {
-    goto err;
-  }
-  if (!EVP_PKEY_verify_init(pctx) ||
-      !EVP_PKEY_CTX_set_signature_md(pctx, md) ||
-      !EVP_PKEY_verify(pctx, CBS_data(&signature), CBS_len(&signature), digest,
-                       digest_length)) {
-    al = SSL_AD_DECRYPT_ERROR;
-    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SIGNATURE);
-    goto f_err;
-  }
-
-  ret = 1;
-
-  if (0) {
-  f_err:
-    ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
-  }
-
-err:
-  EVP_PKEY_CTX_free(pctx);
-  EVP_PKEY_free(pkey);
-
-  return ret;
-}
-
-int ssl3_get_client_certificate(SSL *ssl) {
-  int i, ok, al, ret = -1;
-  X509 *x = NULL;
-  unsigned long n;
-  STACK_OF(X509) *sk = NULL;
-  SHA256_CTX sha256;
-  CBS certificate_msg, certificate_list;
-  int is_first_certificate = 1;
-
-  n = ssl->method->ssl_get_message(ssl, SSL3_ST_SR_CERT_A, SSL3_ST_SR_CERT_B,
-                                   -1, (long)ssl->max_cert_list,
-                                   ssl_hash_message, &ok);
-
-  if (!ok) {
-    return n;
-  }
-
-  if (ssl->s3->tmp.message_type == SSL3_MT_CLIENT_KEY_EXCHANGE) {
-    if ((ssl->verify_mode & SSL_VERIFY_PEER) &&
-        (ssl->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
-      al = SSL_AD_HANDSHAKE_FAILURE;
-      goto f_err;
-    }
-
-    /* If tls asked for a client cert, the client must return a 0 list */
-    if (ssl->version > SSL3_VERSION && ssl->s3->tmp.cert_request) {
-      OPENSSL_PUT_ERROR(SSL,
-                        SSL_R_TLS_PEER_DID_NOT_RESPOND_WITH_CERTIFICATE_LIST);
-      al = SSL_AD_UNEXPECTED_MESSAGE;
-      goto f_err;
-    }
-    ssl->s3->tmp.reuse_message = 1;
-
-    return 1;
-  }
-
-  if (ssl->s3->tmp.message_type != SSL3_MT_CERTIFICATE) {
-    al = SSL_AD_UNEXPECTED_MESSAGE;
-    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_MESSAGE_TYPE);
-    goto f_err;
-  }
-
-  CBS_init(&certificate_msg, ssl->init_msg, n);
-
-  sk = sk_X509_new_null();
-  if (sk == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-    goto err;
-  }
-
-  if (!CBS_get_u24_length_prefixed(&certificate_msg, &certificate_list) ||
-      CBS_len(&certificate_msg) != 0) {
-    al = SSL_AD_DECODE_ERROR;
-    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
-    goto f_err;
-  }
-
-  while (CBS_len(&certificate_list) > 0) {
-    CBS certificate;
-    const uint8_t *data;
-
-    if (!CBS_get_u24_length_prefixed(&certificate_list, &certificate)) {
-      al = SSL_AD_DECODE_ERROR;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
-      goto f_err;
-    }
-
-    if (is_first_certificate && ssl->ctx->retain_only_sha256_of_client_certs) {
-      /* If this is the first certificate, and we don't want to keep peer
-       * certificates in memory, then we hash it right away. */
-      SHA256_Init(&sha256);
-      SHA256_Update(&sha256, CBS_data(&certificate), CBS_len(&certificate));
-      SHA256_Final(ssl->session->peer_sha256, &sha256);
-      ssl->session->peer_sha256_valid = 1;
-    }
-    is_first_certificate = 0;
-
-    /* A u24 length cannot overflow a long. */
-    data = CBS_data(&certificate);
-    x = d2i_X509(NULL, &data, (long)CBS_len(&certificate));
-    if (x == NULL) {
-      al = SSL_AD_BAD_CERTIFICATE;
-      OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
-      goto f_err;
-    }
-    if (data != CBS_data(&certificate) + CBS_len(&certificate)) {
-      al = SSL_AD_DECODE_ERROR;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_LENGTH_MISMATCH);
-      goto f_err;
-    }
-    if (!sk_X509_push(sk, x)) {
-      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      goto err;
-    }
-    x = NULL;
-  }
-
-  if (sk_X509_num(sk) <= 0) {
-    /* No client certificate so the handshake buffer may be discarded. */
-    ssl3_free_handshake_buffer(ssl);
-
-    /* TLS does not mind 0 certs returned */
-    if (ssl->version == SSL3_VERSION) {
-      al = SSL_AD_HANDSHAKE_FAILURE;
-      OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATES_RETURNED);
-      goto f_err;
-    } else if ((ssl->verify_mode & SSL_VERIFY_PEER) &&
-             (ssl->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) {
-      /* Fail for TLS only if we required a certificate */
-      OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
-      al = SSL_AD_HANDSHAKE_FAILURE;
-      goto f_err;
-    }
-  } else {
-    i = ssl_verify_cert_chain(ssl, sk);
-    if (i <= 0) {
-      al = ssl_verify_alarm_type(ssl->verify_result);
-      OPENSSL_PUT_ERROR(SSL, SSL_R_CERTIFICATE_VERIFY_FAILED);
-      goto f_err;
-    }
-  }
-
-  X509_free(ssl->session->peer);
-  ssl->session->peer = sk_X509_shift(sk);
-  ssl->session->verify_result = ssl->verify_result;
-
-  sk_X509_pop_free(ssl->session->cert_chain, X509_free);
-  ssl->session->cert_chain = sk;
-  /* Inconsistency alert: cert_chain does *not* include the peer's own
-   * certificate, while we do include it in s3_clnt.c */
-
-  sk = NULL;
-
-  ret = 1;
-
-  if (0) {
-  f_err:
-    ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
-  }
-
-err:
-  X509_free(x);
-  sk_X509_pop_free(sk, X509_free);
-  return ret;
-}
-
-int ssl3_send_server_certificate(SSL *ssl) {
-  if (ssl->state == SSL3_ST_SW_CERT_A) {
-    if (!ssl3_output_cert_chain(ssl)) {
-      return 0;
-    }
-    ssl->state = SSL3_ST_SW_CERT_B;
-  }
-
-  /* SSL3_ST_SW_CERT_B */
-  return ssl_do_write(ssl);
-}
-
-/* send a new session ticket (not necessarily for a new session) */
-int ssl3_send_new_session_ticket(SSL *ssl) {
-  int ret = -1;
-  uint8_t *session = NULL;
-  size_t session_len;
-  EVP_CIPHER_CTX ctx;
-  HMAC_CTX hctx;
-
-  EVP_CIPHER_CTX_init(&ctx);
-  HMAC_CTX_init(&hctx);
-
-  if (ssl->state == SSL3_ST_SW_SESSION_TICKET_A) {
-    uint8_t *p, *macstart;
-    int len;
-    unsigned int hlen;
-    SSL_CTX *tctx = ssl->initial_ctx;
-    uint8_t iv[EVP_MAX_IV_LENGTH];
-    uint8_t key_name[16];
-    /* The maximum overhead of encrypting the session is 16 (key name) + IV +
-     * one block of encryption overhead + HMAC.  */
-    const size_t max_ticket_overhead =
-        16 + EVP_MAX_IV_LENGTH + EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE;
-
-    /* Serialize the SSL_SESSION to be encoded into the ticket. */
-    if (!SSL_SESSION_to_bytes_for_ticket(ssl->session, &session,
-                                         &session_len)) {
-      goto err;
-    }
-
-    /* If the session is too long, emit a dummy value rather than abort the
-     * connection. */
-    if (session_len > 0xFFFF - max_ticket_overhead) {
-      static const char kTicketPlaceholder[] = "TICKET TOO LARGE";
-      const size_t placeholder_len = strlen(kTicketPlaceholder);
-
-      OPENSSL_free(session);
-      session = NULL;
-
-      p = ssl_handshake_start(ssl);
-      /* Emit ticket_lifetime_hint. */
-      l2n(0, p);
-      /* Emit ticket. */
-      s2n(placeholder_len, p);
-      memcpy(p, kTicketPlaceholder, placeholder_len);
-      p += placeholder_len;
-
-      len = p - ssl_handshake_start(ssl);
-      if (!ssl_set_handshake_header(ssl, SSL3_MT_NEWSESSION_TICKET, len)) {
-        goto err;
-      }
-      ssl->state = SSL3_ST_SW_SESSION_TICKET_B;
-      return ssl_do_write(ssl);
-    }
-
-    /* Grow buffer if need be: the length calculation is as follows:
-     * handshake_header_length + 4 (ticket lifetime hint) + 2 (ticket length) +
-     * max_ticket_overhead + * session_length */
-    if (!BUF_MEM_grow(ssl->init_buf, SSL_HM_HEADER_LENGTH(ssl) + 6 +
-                                       max_ticket_overhead + session_len)) {
-      goto err;
-    }
-    p = ssl_handshake_start(ssl);
-    /* Initialize HMAC and cipher contexts. If callback present it does all the
-     * work otherwise use generated values from parent ctx. */
-    if (tctx->tlsext_ticket_key_cb) {
-      if (tctx->tlsext_ticket_key_cb(ssl, key_name, iv, &ctx, &hctx,
-                                     1 /* encrypt */) < 0) {
-        goto err;
-      }
-    } else {
-      if (!RAND_bytes(iv, 16) ||
-          !EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
-                              tctx->tlsext_tick_aes_key, iv) ||
-          !HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16, tlsext_tick_md(),
-                        NULL)) {
-        goto err;
-      }
-      memcpy(key_name, tctx->tlsext_tick_key_name, 16);
-    }
-
-    /* Ticket lifetime hint (advisory only): We leave this unspecified for
-     * resumed session (for simplicity), and guess that tickets for new
-     * sessions will live as long as their sessions. */
-    l2n(ssl->hit ? 0 : ssl->session->timeout, p);
-
-    /* Skip ticket length for now */
-    p += 2;
-    /* Output key name */
-    macstart = p;
-    memcpy(p, key_name, 16);
-    p += 16;
-    /* output IV */
-    memcpy(p, iv, EVP_CIPHER_CTX_iv_length(&ctx));
-    p += EVP_CIPHER_CTX_iv_length(&ctx);
-    /* Encrypt session data */
-    if (!EVP_EncryptUpdate(&ctx, p, &len, session, session_len)) {
-      goto err;
-    }
-    p += len;
-    if (!EVP_EncryptFinal_ex(&ctx, p, &len)) {
-      goto err;
-    }
-    p += len;
-
-    if (!HMAC_Update(&hctx, macstart, p - macstart) ||
-        !HMAC_Final(&hctx, p, &hlen)) {
-      goto err;
-    }
-
-    p += hlen;
-    /* Now write out lengths: p points to end of data written */
-    /* Total length */
-    len = p - ssl_handshake_start(ssl);
-    /* Skip ticket lifetime hint */
-    p = ssl_handshake_start(ssl) + 4;
-    s2n(len - 6, p);
-    if (!ssl_set_handshake_header(ssl, SSL3_MT_NEWSESSION_TICKET, len)) {
-      goto err;
-    }
-    ssl->state = SSL3_ST_SW_SESSION_TICKET_B;
-  }
-
-  /* SSL3_ST_SW_SESSION_TICKET_B */
-  ret = ssl_do_write(ssl);
-
-err:
-  OPENSSL_free(session);
-  EVP_CIPHER_CTX_cleanup(&ctx);
-  HMAC_CTX_cleanup(&hctx);
-  return ret;
-}
-
-/* ssl3_get_next_proto reads a Next Protocol Negotiation handshake message. It
- * sets the next_proto member in s if found */
-int ssl3_get_next_proto(SSL *ssl) {
-  int ok;
-  long n;
-  CBS next_protocol, selected_protocol, padding;
-
-  /* Clients cannot send a NextProtocol message if we didn't see the extension
-   * in their ClientHello */
-  if (!ssl->s3->next_proto_neg_seen) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_GOT_NEXT_PROTO_WITHOUT_EXTENSION);
-    return -1;
-  }
-
-  n = ssl->method->ssl_get_message(ssl, SSL3_ST_SR_NEXT_PROTO_A,
-                                 SSL3_ST_SR_NEXT_PROTO_B, SSL3_MT_NEXT_PROTO,
-                                 514, /* See the payload format below */
-                                 ssl_hash_message, &ok);
-
-  if (!ok) {
-    return n;
-  }
-
-  CBS_init(&next_protocol, ssl->init_msg, n);
-
-  /* The payload looks like:
-   *   uint8 proto_len;
-   *   uint8 proto[proto_len];
-   *   uint8 padding_len;
-   *   uint8 padding[padding_len]; */
-  if (!CBS_get_u8_length_prefixed(&next_protocol, &selected_protocol) ||
-      !CBS_get_u8_length_prefixed(&next_protocol, &padding) ||
-      CBS_len(&next_protocol) != 0 ||
-      !CBS_stow(&selected_protocol, &ssl->next_proto_negotiated,
-                &ssl->next_proto_negotiated_len)) {
-    return 0;
-  }
-
-  return 1;
-}
-
-/* ssl3_get_channel_id reads and verifies a ClientID handshake message. */
-int ssl3_get_channel_id(SSL *ssl) {
-  int ret = -1, ok;
-  long n;
-  uint8_t channel_id_hash[EVP_MAX_MD_SIZE];
-  size_t channel_id_hash_len;
-  const uint8_t *p;
-  uint16_t extension_type;
-  EC_GROUP *p256 = NULL;
-  EC_KEY *key = NULL;
-  EC_POINT *point = NULL;
-  ECDSA_SIG sig;
-  BIGNUM x, y;
-  CBS encrypted_extensions, extension;
-
-  n = ssl->method->ssl_get_message(
-      ssl, SSL3_ST_SR_CHANNEL_ID_A, SSL3_ST_SR_CHANNEL_ID_B,
-      SSL3_MT_ENCRYPTED_EXTENSIONS, 2 + 2 + TLSEXT_CHANNEL_ID_SIZE,
-      ssl_dont_hash_message, &ok);
-
-  if (!ok) {
-    return n;
-  }
-
-  /* Before incorporating the EncryptedExtensions message to the handshake
-   * hash, compute the hash that should have been signed. */
-  if (!tls1_channel_id_hash(ssl, channel_id_hash, &channel_id_hash_len)) {
-    return -1;
-  }
-  assert(channel_id_hash_len == SHA256_DIGEST_LENGTH);
-
-  if (!ssl3_hash_current_message(ssl)) {
-    return -1;
-  }
-
-  CBS_init(&encrypted_extensions, ssl->init_msg, n);
-
-  /* EncryptedExtensions could include multiple extensions, but the only
-   * extension that could be negotiated is ChannelID, so there can only be one
-   * entry.
-   *
-   * The payload looks like:
-   *   uint16 extension_type
-   *   uint16 extension_len;
-   *   uint8 x[32];
-   *   uint8 y[32];
-   *   uint8 r[32];
-   *   uint8 s[32]; */
-
-  if (!CBS_get_u16(&encrypted_extensions, &extension_type) ||
-      !CBS_get_u16_length_prefixed(&encrypted_extensions, &extension) ||
-      CBS_len(&encrypted_extensions) != 0 ||
-      extension_type != TLSEXT_TYPE_channel_id ||
-      CBS_len(&extension) != TLSEXT_CHANNEL_ID_SIZE) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_MESSAGE);
-    return -1;
-  }
-
-  p256 = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
-  if (!p256) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_NO_P256_SUPPORT);
-    return -1;
-  }
-
-  BN_init(&x);
-  BN_init(&y);
-  sig.r = BN_new();
-  sig.s = BN_new();
-  if (sig.r == NULL || sig.s == NULL) {
-    goto err;
-  }
-
-  p = CBS_data(&extension);
-  if (BN_bin2bn(p + 0, 32, &x) == NULL ||
-      BN_bin2bn(p + 32, 32, &y) == NULL ||
-      BN_bin2bn(p + 64, 32, sig.r) == NULL ||
-      BN_bin2bn(p + 96, 32, sig.s) == NULL) {
-    goto err;
-  }
-
-  point = EC_POINT_new(p256);
-  if (!point ||
-      !EC_POINT_set_affine_coordinates_GFp(p256, point, &x, &y, NULL)) {
-    goto err;
-  }
-
-  key = EC_KEY_new();
-  if (!key || !EC_KEY_set_group(key, p256) ||
-      !EC_KEY_set_public_key(key, point)) {
-    goto err;
-  }
-
-  /* We stored the handshake hash in |tlsext_channel_id| the first time that we
-   * were called. */
-  if (!ECDSA_do_verify(channel_id_hash, channel_id_hash_len, &sig, key)) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_CHANNEL_ID_SIGNATURE_INVALID);
-    ssl->s3->tlsext_channel_id_valid = 0;
-    goto err;
-  }
-
-  memcpy(ssl->s3->tlsext_channel_id, p, 64);
-  ret = 1;
-
-err:
-  BN_free(&x);
-  BN_free(&y);
-  BN_free(sig.r);
-  BN_free(sig.s);
-  EC_KEY_free(key);
-  EC_POINT_free(point);
-  EC_GROUP_free(p256);
-  return ret;
-}
diff --git a/src/ssl/ssl_aead_ctx.c b/src/ssl/ssl_aead_ctx.c
index 8829679..1af4a5a 100644
--- a/src/ssl/ssl_aead_ctx.c
+++ b/src/ssl/ssl_aead_ctx.c
@@ -22,20 +22,22 @@
 #include <openssl/rand.h>
 #include <openssl/type_check.h>
 
+#include "../crypto/internal.h"
 #include "internal.h"
 
 
-OPENSSL_COMPILE_ASSERT(EVP_AEAD_MAX_NONCE_LENGTH < 256,
-                       variable_nonce_len_doesnt_fit_in_uint8_t);
-
 SSL_AEAD_CTX *SSL_AEAD_CTX_new(enum evp_aead_direction_t direction,
                                uint16_t version, const SSL_CIPHER *cipher,
                                const uint8_t *enc_key, size_t enc_key_len,
                                const uint8_t *mac_key, size_t mac_key_len,
                                const uint8_t *fixed_iv, size_t fixed_iv_len) {
   const EVP_AEAD *aead;
-  size_t discard;
-  if (!ssl_cipher_get_evp_aead(&aead, &discard, &discard, cipher, version)) {
+  size_t expected_mac_key_len, expected_fixed_iv_len;
+  if (!ssl_cipher_get_evp_aead(&aead, &expected_mac_key_len,
+                               &expected_fixed_iv_len, cipher, version) ||
+      /* Ensure the caller returned correct key sizes. */
+      expected_fixed_iv_len != fixed_iv_len ||
+      expected_mac_key_len != mac_key_len) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
     return 0;
   }
@@ -48,21 +50,23 @@
       OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
       return 0;
     }
-    memcpy(merged_key, mac_key, mac_key_len);
-    memcpy(merged_key + mac_key_len, enc_key, enc_key_len);
-    memcpy(merged_key + mac_key_len + enc_key_len, fixed_iv, fixed_iv_len);
+    OPENSSL_memcpy(merged_key, mac_key, mac_key_len);
+    OPENSSL_memcpy(merged_key + mac_key_len, enc_key, enc_key_len);
+    OPENSSL_memcpy(merged_key + mac_key_len + enc_key_len, fixed_iv,
+                   fixed_iv_len);
     enc_key = merged_key;
     enc_key_len += mac_key_len;
     enc_key_len += fixed_iv_len;
   }
 
-  SSL_AEAD_CTX *aead_ctx = (SSL_AEAD_CTX *)OPENSSL_malloc(sizeof(SSL_AEAD_CTX));
+  SSL_AEAD_CTX *aead_ctx = OPENSSL_malloc(sizeof(SSL_AEAD_CTX));
   if (aead_ctx == NULL) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
     return NULL;
   }
-  memset(aead_ctx, 0, sizeof(SSL_AEAD_CTX));
+  OPENSSL_memset(aead_ctx, 0, sizeof(SSL_AEAD_CTX));
   aead_ctx->cipher = cipher;
+  aead_ctx->version = version;
 
   if (!EVP_AEAD_CTX_init_with_direction(
           &aead_ctx->ctx, aead, enc_key, enc_key_len,
@@ -72,10 +76,12 @@
   }
 
   assert(EVP_AEAD_nonce_length(aead) <= EVP_AEAD_MAX_NONCE_LENGTH);
+  OPENSSL_COMPILE_ASSERT(EVP_AEAD_MAX_NONCE_LENGTH < 256,
+                         variable_nonce_len_doesnt_fit_in_uint8_t);
   aead_ctx->variable_nonce_len = (uint8_t)EVP_AEAD_nonce_length(aead);
   if (mac_key_len == 0) {
     assert(fixed_iv_len <= sizeof(aead_ctx->fixed_nonce));
-    memcpy(aead_ctx->fixed_nonce, fixed_iv, fixed_iv_len);
+    OPENSSL_memcpy(aead_ctx->fixed_nonce, fixed_iv, fixed_iv_len);
     aead_ctx->fixed_nonce_len = fixed_iv_len;
 
     if (cipher->algorithm_enc & SSL_CHACHA20POLY1305) {
@@ -92,7 +98,18 @@
     if (cipher->algorithm_enc & (SSL_AES128GCM | SSL_AES256GCM)) {
       aead_ctx->variable_nonce_included_in_record = 1;
     }
+
+    /* The TLS 1.3 construction XORs the fixed nonce into the sequence number
+     * and omits the additional data. */
+    if (version >= TLS1_3_VERSION) {
+      aead_ctx->xor_fixed_nonce = 1;
+      aead_ctx->variable_nonce_len = 8;
+      aead_ctx->variable_nonce_included_in_record = 0;
+      aead_ctx->omit_ad = 1;
+      assert(fixed_iv_len >= aead_ctx->variable_nonce_len);
+    }
   } else {
+    assert(version < TLS1_3_VERSION);
     aead_ctx->variable_nonce_included_in_record = 1;
     aead_ctx->random_variable_nonce = 1;
     aead_ctx->omit_length_in_ad = 1;
@@ -110,19 +127,27 @@
   OPENSSL_free(aead);
 }
 
-size_t SSL_AEAD_CTX_explicit_nonce_len(SSL_AEAD_CTX *aead) {
+size_t SSL_AEAD_CTX_explicit_nonce_len(const SSL_AEAD_CTX *aead) {
+#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
+  aead = NULL;
+#endif
+
   if (aead != NULL && aead->variable_nonce_included_in_record) {
     return aead->variable_nonce_len;
   }
   return 0;
 }
 
-size_t SSL_AEAD_CTX_max_overhead(SSL_AEAD_CTX *aead) {
+size_t SSL_AEAD_CTX_max_overhead(const SSL_AEAD_CTX *aead) {
+#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
+  aead = NULL;
+#endif
+
   if (aead == NULL) {
     return 0;
   }
   return EVP_AEAD_max_overhead(aead->ctx.aead) +
-      SSL_AEAD_CTX_explicit_nonce_len(aead);
+         SSL_AEAD_CTX_explicit_nonce_len(aead);
 }
 
 /* ssl_aead_ctx_get_ad writes the additional data for |aead| into |out| and
@@ -131,7 +156,11 @@
                                   uint8_t type, uint16_t wire_version,
                                   const uint8_t seqnum[8],
                                   size_t plaintext_len) {
-  memcpy(out, seqnum, 8);
+  if (aead->omit_ad) {
+    return 0;
+  }
+
+  OPENSSL_memcpy(out, seqnum, 8);
   size_t len = 8;
   out[len++] = type;
   if (!aead->omit_version_in_ad) {
@@ -145,18 +174,16 @@
   return len;
 }
 
-int SSL_AEAD_CTX_open(SSL_AEAD_CTX *aead, uint8_t *out, size_t *out_len,
-                      size_t max_out, uint8_t type, uint16_t wire_version,
-                      const uint8_t seqnum[8], const uint8_t *in,
-                      size_t in_len) {
+int SSL_AEAD_CTX_open(SSL_AEAD_CTX *aead, CBS *out, uint8_t type,
+                      uint16_t wire_version, const uint8_t seqnum[8],
+                      uint8_t *in, size_t in_len) {
+#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
+  aead = NULL;
+#endif
+
   if (aead == NULL) {
     /* Handle the initial NULL cipher. */
-    if (in_len > max_out) {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL);
-      return 0;
-    }
-    memmove(out, in, in_len);
-    *out_len = in_len;
+    CBS_init(out, in, in_len);
     return 1;
   }
 
@@ -183,9 +210,9 @@
   /* Prepend the fixed nonce, or left-pad with zeros if XORing. */
   if (aead->xor_fixed_nonce) {
     nonce_len = aead->fixed_nonce_len - aead->variable_nonce_len;
-    memset(nonce, 0, nonce_len);
+    OPENSSL_memset(nonce, 0, nonce_len);
   } else {
-    memcpy(nonce, aead->fixed_nonce, aead->fixed_nonce_len);
+    OPENSSL_memcpy(nonce, aead->fixed_nonce, aead->fixed_nonce_len);
     nonce_len += aead->fixed_nonce_len;
   }
 
@@ -196,39 +223,48 @@
       OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_PACKET_LENGTH);
       return 0;
     }
-    memcpy(nonce + nonce_len, in, aead->variable_nonce_len);
+    OPENSSL_memcpy(nonce + nonce_len, in, aead->variable_nonce_len);
     in += aead->variable_nonce_len;
     in_len -= aead->variable_nonce_len;
   } else {
     assert(aead->variable_nonce_len == 8);
-    memcpy(nonce + nonce_len, seqnum, aead->variable_nonce_len);
+    OPENSSL_memcpy(nonce + nonce_len, seqnum, aead->variable_nonce_len);
   }
   nonce_len += aead->variable_nonce_len;
 
   /* XOR the fixed nonce, if necessary. */
   if (aead->xor_fixed_nonce) {
     assert(nonce_len == aead->fixed_nonce_len);
-    size_t i;
-    for (i = 0; i < aead->fixed_nonce_len; i++) {
+    for (size_t i = 0; i < aead->fixed_nonce_len; i++) {
       nonce[i] ^= aead->fixed_nonce[i];
     }
   }
 
-  return EVP_AEAD_CTX_open(&aead->ctx, out, out_len, max_out, nonce, nonce_len,
-                           in, in_len, ad, ad_len);
+  /* Decrypt in-place. */
+  size_t len;
+  if (!EVP_AEAD_CTX_open(&aead->ctx, in, &len, in_len, nonce, nonce_len,
+                         in, in_len, ad, ad_len)) {
+    return 0;
+  }
+  CBS_init(out, in, len);
+  return 1;
 }
 
 int SSL_AEAD_CTX_seal(SSL_AEAD_CTX *aead, uint8_t *out, size_t *out_len,
                       size_t max_out, uint8_t type, uint16_t wire_version,
                       const uint8_t seqnum[8], const uint8_t *in,
                       size_t in_len) {
+#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
+  aead = NULL;
+#endif
+
   if (aead == NULL) {
     /* Handle the initial NULL cipher. */
     if (in_len > max_out) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL);
       return 0;
     }
-    memmove(out, in, in_len);
+    OPENSSL_memmove(out, in, in_len);
     *out_len = in_len;
     return 1;
   }
@@ -244,9 +280,9 @@
   /* Prepend the fixed nonce, or left-pad with zeros if XORing. */
   if (aead->xor_fixed_nonce) {
     nonce_len = aead->fixed_nonce_len - aead->variable_nonce_len;
-    memset(nonce, 0, nonce_len);
+    OPENSSL_memset(nonce, 0, nonce_len);
   } else {
-    memcpy(nonce, aead->fixed_nonce, aead->fixed_nonce_len);
+    OPENSSL_memcpy(nonce, aead->fixed_nonce, aead->fixed_nonce_len);
     nonce_len += aead->fixed_nonce_len;
   }
 
@@ -260,7 +296,7 @@
     /* When sending we use the sequence number as the variable part of the
      * nonce. */
     assert(aead->variable_nonce_len == 8);
-    memcpy(nonce + nonce_len, seqnum, aead->variable_nonce_len);
+    OPENSSL_memcpy(nonce + nonce_len, seqnum, aead->variable_nonce_len);
   }
   nonce_len += aead->variable_nonce_len;
 
@@ -276,7 +312,8 @@
       OPENSSL_PUT_ERROR(SSL, SSL_R_OUTPUT_ALIASES_INPUT);
       return 0;
     }
-    memcpy(out, nonce + aead->fixed_nonce_len, aead->variable_nonce_len);
+    OPENSSL_memcpy(out, nonce + aead->fixed_nonce_len,
+                   aead->variable_nonce_len);
     extra_len = aead->variable_nonce_len;
     out += aead->variable_nonce_len;
     max_out -= aead->variable_nonce_len;
@@ -285,8 +322,7 @@
   /* XOR the fixed nonce, if necessary. */
   if (aead->xor_fixed_nonce) {
     assert(nonce_len == aead->fixed_nonce_len);
-    size_t i;
-    for (i = 0; i < aead->fixed_nonce_len; i++) {
+    for (size_t i = 0; i < aead->fixed_nonce_len; i++) {
       nonce[i] ^= aead->fixed_nonce[i];
     }
   }
diff --git a/src/ssl/ssl_asn1.c b/src/ssl/ssl_asn1.c
index 5ec33eb..cfcc12a 100644
--- a/src/ssl/ssl_asn1.c
+++ b/src/ssl/ssl_asn1.c
@@ -85,24 +85,26 @@
 #include <limits.h>
 #include <string.h>
 
+#include <openssl/buf.h>
 #include <openssl/bytestring.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
 #include <openssl/x509.h>
 
+#include "../crypto/internal.h"
 #include "internal.h"
 
 
 /* An SSL_SESSION is serialized as the following ASN.1 structure:
  *
  * SSLSession ::= SEQUENCE {
- *     version                     INTEGER (1),  -- ignored
+ *     version                     INTEGER (1),  -- session structure version
  *     sslVersion                  INTEGER,      -- protocol version number
  *     cipher                      OCTET STRING, -- two bytes long
  *     sessionID                   OCTET STRING,
  *     masterKey                   OCTET STRING,
- *     time                    [1] INTEGER OPTIONAL, -- seconds since UNIX epoch
- *     timeout                 [2] INTEGER OPTIONAL, -- in seconds
+ *     time                    [1] INTEGER, -- seconds since UNIX epoch
+ *     timeout                 [2] INTEGER, -- in seconds
  *     peer                    [3] Certificate OPTIONAL,
  *     sessionIDContext        [4] OCTET STRING OPTIONAL,
  *     verifyResult            [5] INTEGER OPTIONAL,  -- one of X509_V_* codes
@@ -118,17 +120,28 @@
  *     ocspResponse            [16] OCTET STRING OPTIONAL,
  *                                  -- stapled OCSP response from the server
  *     extendedMasterSecret    [17] BOOLEAN OPTIONAL,
- *     keyExchangeInfo         [18] INTEGER OPTIONAL,
+ *     groupID                 [18] INTEGER OPTIONAL,
+ *                                  -- For historical reasons, for legacy DHE or
+ *                                  -- static RSA ciphers, this field contains
+ *                                  -- another value to be discarded.
  *     certChain               [19] SEQUENCE OF Certificate OPTIONAL,
+ *     ticketAgeAdd            [21] OCTET STRING OPTIONAL,
+ *     isServer                [22] BOOLEAN DEFAULT TRUE,
+ *     peerSignatureAlgorithm  [23] INTEGER OPTIONAL,
+ *     ticketMaxEarlyData      [24] INTEGER OPTIONAL,
+ *     authTimeout             [25] INTEGER OPTIONAL, -- defaults to timeout
+ *     earlyALPN               [26] OCTET STRING OPTIONAL,
  * }
  *
  * Note: historically this serialization has included other optional
- * fields. Their presense is currently treated as a parse error:
+ * fields. Their presence is currently treated as a parse error:
  *
  *     keyArg                  [0] IMPLICIT OCTET STRING OPTIONAL,
  *     pskIdentityHint         [7] OCTET STRING OPTIONAL,
  *     compressionMethod       [11] OCTET STRING OPTIONAL,
- *     srpUsername             [12] OCTET STRING OPTIONAL, */
+ *     srpUsername             [12] OCTET STRING OPTIONAL,
+ *     ticketFlags             [20] INTEGER OPTIONAL,
+ */
 
 static const unsigned kVersion = 1;
 
@@ -160,26 +173,22 @@
     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 16;
 static const int kExtendedMasterSecretTag =
     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 17;
-static const int kKeyExchangeInfoTag =
+static const int kGroupIDTag =
     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 18;
 static const int kCertChainTag =
     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 19;
-
-static int add_X509(CBB *cbb, X509 *x509) {
-  int len = i2d_X509(x509, NULL);
-  if (len < 0) {
-    return 0;
-  }
-  uint8_t *buf;
-  if (!CBB_add_space(cbb, &buf, len)) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-    return 0;
-  }
-  if (buf != NULL && i2d_X509(x509, &buf) < 0) {
-    return 0;
-  }
-  return 1;
-}
+static const int kTicketAgeAddTag =
+    CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 21;
+static const int kIsServerTag =
+    CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 22;
+static const int kPeerSignatureAlgorithmTag =
+    CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 23;
+static const int kTicketMaxEarlyDataTag =
+    CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 24;
+static const int kAuthTimeoutTag =
+    CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 25;
+static const int kEarlyALPNTag =
+    CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 26;
 
 static int SSL_SESSION_to_bytes_full(const SSL_SESSION *in, uint8_t **out_data,
                                      size_t *out_len, int for_ticket) {
@@ -201,37 +210,25 @@
       !CBB_add_bytes(&child, in->session_id,
                      for_ticket ? 0 : in->session_id_length) ||
       !CBB_add_asn1(&session, &child, CBS_ASN1_OCTETSTRING) ||
-      !CBB_add_bytes(&child, in->master_key, in->master_key_length)) {
+      !CBB_add_bytes(&child, in->master_key, in->master_key_length) ||
+      !CBB_add_asn1(&session, &child, kTimeTag) ||
+      !CBB_add_asn1_uint64(&child, in->time) ||
+      !CBB_add_asn1(&session, &child, kTimeoutTag) ||
+      !CBB_add_asn1_uint64(&child, in->timeout)) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
     goto err;
   }
 
-  if (in->time != 0) {
-    if (!CBB_add_asn1(&session, &child, kTimeTag) ||
-        !CBB_add_asn1_uint64(&child, in->time)) {
-      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      goto err;
-    }
-  }
-
-  if (in->timeout != 0) {
-    if (!CBB_add_asn1(&session, &child, kTimeoutTag) ||
-        !CBB_add_asn1_uint64(&child, in->timeout)) {
-      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      goto err;
-    }
-  }
-
   /* The peer certificate is only serialized if the SHA-256 isn't
    * serialized instead. */
-  if (in->peer && !in->peer_sha256_valid) {
-    if (!CBB_add_asn1(&session, &child, kPeerTag)) {
+  if (sk_CRYPTO_BUFFER_num(in->certs) > 0 && !in->peer_sha256_valid) {
+    const CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(in->certs, 0);
+    if (!CBB_add_asn1(&session, &child, kPeerTag) ||
+        !CBB_add_bytes(&child, CRYPTO_BUFFER_data(buffer),
+                       CRYPTO_BUFFER_len(buffer))) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
       goto err;
     }
-    if (!add_X509(&child, in->peer)) {
-      goto err;
-    }
   }
 
   /* Although it is OPTIONAL and usually empty, OpenSSL has
@@ -335,28 +332,81 @@
     }
   }
 
-  if (in->key_exchange_info > 0 &&
-      (!CBB_add_asn1(&session, &child, kKeyExchangeInfoTag) ||
-       !CBB_add_asn1_uint64(&child, in->key_exchange_info))) {
+  if (in->group_id > 0 &&
+      (!CBB_add_asn1(&session, &child, kGroupIDTag) ||
+       !CBB_add_asn1_uint64(&child, in->group_id))) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
     goto err;
   }
 
   /* The certificate chain is only serialized if the leaf's SHA-256 isn't
    * serialized instead. */
-  if (in->cert_chain != NULL && !in->peer_sha256_valid) {
+  if (in->certs != NULL &&
+      !in->peer_sha256_valid &&
+      sk_CRYPTO_BUFFER_num(in->certs) >= 2) {
     if (!CBB_add_asn1(&session, &child, kCertChainTag)) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
       goto err;
     }
-    size_t i;
-    for (i = 0; i < sk_X509_num(in->cert_chain); i++) {
-      if (!add_X509(&child, sk_X509_value(in->cert_chain, i))) {
+    for (size_t i = 1; i < sk_CRYPTO_BUFFER_num(in->certs); i++) {
+      const CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(in->certs, i);
+      if (!CBB_add_bytes(&child, CRYPTO_BUFFER_data(buffer),
+                         CRYPTO_BUFFER_len(buffer))) {
+        OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
         goto err;
       }
     }
   }
 
+  if (in->ticket_age_add_valid) {
+    if (!CBB_add_asn1(&session, &child, kTicketAgeAddTag) ||
+        !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
+        !CBB_add_u32(&child2, in->ticket_age_add)) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+      goto err;
+    }
+  }
+
+  if (!in->is_server) {
+    if (!CBB_add_asn1(&session, &child, kIsServerTag) ||
+        !CBB_add_asn1(&child, &child2, CBS_ASN1_BOOLEAN) ||
+        !CBB_add_u8(&child2, 0x00)) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+      goto err;
+    }
+  }
+
+  if (in->peer_signature_algorithm != 0 &&
+      (!CBB_add_asn1(&session, &child, kPeerSignatureAlgorithmTag) ||
+       !CBB_add_asn1_uint64(&child, in->peer_signature_algorithm))) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+    goto err;
+  }
+
+  if (in->ticket_max_early_data != 0 &&
+      (!CBB_add_asn1(&session, &child, kTicketMaxEarlyDataTag) ||
+       !CBB_add_asn1_uint64(&child, in->ticket_max_early_data))) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+    goto err;
+  }
+
+  if (in->timeout != in->auth_timeout &&
+      (!CBB_add_asn1(&session, &child, kAuthTimeoutTag) ||
+       !CBB_add_asn1_uint64(&child, in->auth_timeout))) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+    goto err;
+  }
+
+  if (in->early_alpn) {
+    if (!CBB_add_asn1(&session, &child, kEarlyALPNTag) ||
+        !CBB_add_asn1(&child, &child2, CBS_ASN1_OCTETSTRING) ||
+        !CBB_add_bytes(&child2, (const uint8_t *)in->early_alpn,
+                       in->early_alpn_len)) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+      goto err;
+    }
+  }
+
   if (!CBB_finish(&cbb, out_data, out_len)) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
     goto err;
@@ -370,6 +420,22 @@
 
 int SSL_SESSION_to_bytes(const SSL_SESSION *in, uint8_t **out_data,
                          size_t *out_len) {
+  if (in->not_resumable) {
+    /* If the caller has an unresumable session, e.g. if |SSL_get_session| were
+     * called on a TLS 1.3 or False Started connection, serialize with a
+     * placeholder value so it is not accidentally deserialized into a resumable
+     * one. */
+    static const char kNotResumableSession[] = "NOT RESUMABLE";
+
+    *out_len = strlen(kNotResumableSession);
+    *out_data = BUF_memdup(kNotResumableSession, *out_len);
+    if (*out_data == NULL) {
+      return 0;
+    }
+
+    return 1;
+  }
+
   return SSL_SESSION_to_bytes_full(in, out_data, out_len, 0);
 }
 
@@ -393,7 +459,7 @@
   }
 
   if (pp) {
-    memcpy(*pp, out, len);
+    OPENSSL_memcpy(*pp, out, len);
     *pp += len;
   }
   OPENSSL_free(out);
@@ -453,15 +519,15 @@
 /* SSL_SESSION_parse_bounded_octet_string parses an optional ASN.1 OCTET STRING
  * explicitly tagged with |tag| of size at most |max_out|. */
 static int SSL_SESSION_parse_bounded_octet_string(
-    CBS *cbs, uint8_t *out, unsigned *out_len, unsigned max_out, unsigned tag) {
+    CBS *cbs, uint8_t *out, uint8_t *out_len, uint8_t max_out, unsigned tag) {
   CBS value;
   if (!CBS_get_optional_asn1_octet_string(cbs, &value, NULL, tag) ||
       CBS_len(&value) > max_out) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
     return 0;
   }
-  memcpy(out, CBS_data(&value), CBS_len(&value));
-  *out_len = (unsigned)CBS_len(&value);
+  OPENSSL_memcpy(out, CBS_data(&value), CBS_len(&value));
+  *out_len = (uint8_t)CBS_len(&value);
   return 1;
 }
 
@@ -491,22 +557,22 @@
   return 1;
 }
 
-static X509 *parse_x509(CBS *cbs) {
-  if (CBS_len(cbs) > LONG_MAX) {
+static int SSL_SESSION_parse_u16(CBS *cbs, uint16_t *out, unsigned tag,
+                                 uint16_t default_value) {
+  uint64_t value;
+  if (!CBS_get_optional_asn1_uint64(cbs, &value, tag,
+                                    (uint64_t)default_value) ||
+      value > 0xffff) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
-    return NULL;
+    return 0;
   }
-  const uint8_t *ptr = CBS_data(cbs);
-  X509 *ret = d2i_X509(NULL, &ptr, (long)CBS_len(cbs));
-  if (ret == NULL) {
-    return NULL;
-  }
-  CBS_skip(cbs, ptr - CBS_data(cbs));
-  return ret;
+  *out = (uint16_t)value;
+  return 1;
 }
 
-static SSL_SESSION *SSL_SESSION_parse(CBS *cbs) {
-  SSL_SESSION *ret = SSL_SESSION_new();
+SSL_SESSION *SSL_SESSION_parse(CBS *cbs, const SSL_X509_METHOD *x509_method,
+                               CRYPTO_BUFFER_POOL *pool) {
+  SSL_SESSION *ret = ssl_session_new(x509_method);
   if (ret == NULL) {
     goto err;
   }
@@ -520,12 +586,6 @@
     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
     goto err;
   }
-  /* Only support SSLv3/TLS and DTLS. */
-  if ((ssl_version >> 8) != SSL3_VERSION_MAJOR &&
-      (ssl_version >> 8) != (DTLS1_VERSION >> 8)) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_SSL_VERSION);
-    goto err;
-  }
   ret->ssl_version = ssl_version;
 
   CBS cipher;
@@ -550,35 +610,32 @@
     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
     goto err;
   }
-  memcpy(ret->session_id, CBS_data(&session_id), CBS_len(&session_id));
+  OPENSSL_memcpy(ret->session_id, CBS_data(&session_id), CBS_len(&session_id));
   ret->session_id_length = CBS_len(&session_id);
-  memcpy(ret->master_key, CBS_data(&master_key), CBS_len(&master_key));
+  OPENSSL_memcpy(ret->master_key, CBS_data(&master_key), CBS_len(&master_key));
   ret->master_key_length = CBS_len(&master_key);
 
-  if (!SSL_SESSION_parse_long(&session, &ret->time, kTimeTag, time(NULL)) ||
-      !SSL_SESSION_parse_long(&session, &ret->timeout, kTimeoutTag, 3)) {
+  CBS child;
+  uint64_t timeout;
+  if (!CBS_get_asn1(&session, &child, kTimeTag) ||
+      !CBS_get_asn1_uint64(&child, &ret->time) ||
+      !CBS_get_asn1(&session, &child, kTimeoutTag) ||
+      !CBS_get_asn1_uint64(&child, &timeout) ||
+      timeout > UINT32_MAX) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
     goto err;
   }
 
+  ret->timeout = (uint32_t)timeout;
+
   CBS peer;
   int has_peer;
-  if (!CBS_get_optional_asn1(&session, &peer, &has_peer, kPeerTag)) {
+  if (!CBS_get_optional_asn1(&session, &peer, &has_peer, kPeerTag) ||
+      (has_peer && CBS_len(&peer) == 0)) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
     goto err;
   }
-  X509_free(ret->peer);
-  ret->peer = NULL;
-  if (has_peer) {
-    ret->peer = parse_x509(&peer);
-    if (ret->peer == NULL) {
-      goto err;
-    }
-    if (CBS_len(&peer) != 0) {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
-      goto err;
-    }
-  }
+  /* |peer| is processed with the certificate chain. */
 
   if (!SSL_SESSION_parse_bounded_octet_string(
           &session, ret->sid_ctx, &ret->sid_ctx_length, sizeof(ret->sid_ctx),
@@ -597,7 +654,7 @@
   }
 
   if (CBS_peek_asn1_tag(&session, kPeerSHA256Tag)) {
-    CBS child, peer_sha256;
+    CBS peer_sha256;
     if (!CBS_get_asn1(&session, &child, kPeerSHA256Tag) ||
         !CBS_get_asn1(&child, &peer_sha256, CBS_ASN1_OCTETSTRING) ||
         CBS_len(&peer_sha256) != sizeof(ret->peer_sha256) ||
@@ -605,7 +662,8 @@
       OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
       goto err;
     }
-    memcpy(ret->peer_sha256, CBS_data(&peer_sha256), sizeof(ret->peer_sha256));
+    OPENSSL_memcpy(ret->peer_sha256, CBS_data(&peer_sha256),
+                   sizeof(ret->peer_sha256));
     ret->peer_sha256_valid = 1;
   } else {
     ret->peer_sha256_valid = 0;
@@ -634,41 +692,110 @@
   }
   ret->extended_master_secret = !!extended_master_secret;
 
-  if (!SSL_SESSION_parse_u32(&session, &ret->key_exchange_info,
-                             kKeyExchangeInfoTag, 0)) {
+  uint32_t value;
+  if (!SSL_SESSION_parse_u32(&session, &value, kGroupIDTag, 0)) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
     goto err;
   }
 
-  CBS cert_chain;
-  int has_cert_chain;
-  if (!CBS_get_optional_asn1(&session, &cert_chain, &has_cert_chain,
-                             kCertChainTag)) {
+  /* Historically, the group_id field was used for key-exchange-specific
+   * information. Discard all but the group ID. */
+  if (ret->cipher->algorithm_mkey & (SSL_kRSA | SSL_kDHE)) {
+    value = 0;
+  }
+
+  if (value > 0xffff) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
     goto err;
   }
-  sk_X509_pop_free(ret->cert_chain, X509_free);
-  ret->cert_chain = NULL;
-  if (has_cert_chain) {
-    ret->cert_chain = sk_X509_new_null();
-    if (ret->cert_chain == NULL) {
+  ret->group_id = (uint16_t)value;
+
+  CBS cert_chain;
+  CBS_init(&cert_chain, NULL, 0);
+  int has_cert_chain;
+  if (!CBS_get_optional_asn1(&session, &cert_chain, &has_cert_chain,
+                             kCertChainTag) ||
+      (has_cert_chain && CBS_len(&cert_chain) == 0)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
+    goto err;
+  }
+  if (has_cert_chain && !has_peer) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
+    goto err;
+  }
+  if (has_peer || has_cert_chain) {
+    ret->certs = sk_CRYPTO_BUFFER_new_null();
+    if (ret->certs == NULL) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
       goto err;
     }
-    while (CBS_len(&cert_chain) > 0) {
-      X509 *x509 = parse_x509(&cert_chain);
-      if (x509 == NULL) {
+
+    if (has_peer) {
+      /* TODO(agl): this should use the |SSL_CTX|'s pool. */
+      CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new_from_CBS(&peer, pool);
+      if (buffer == NULL ||
+          !sk_CRYPTO_BUFFER_push(ret->certs, buffer)) {
+        CRYPTO_BUFFER_free(buffer);
+        OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
         goto err;
       }
-      if (!sk_X509_push(ret->cert_chain, x509)) {
+    }
+
+    while (CBS_len(&cert_chain) > 0) {
+      CBS cert;
+      if (!CBS_get_any_asn1_element(&cert_chain, &cert, NULL, NULL) ||
+          CBS_len(&cert) == 0) {
+        OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
+        goto err;
+      }
+
+      /* TODO(agl): this should use the |SSL_CTX|'s pool. */
+      CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new_from_CBS(&cert, pool);
+      if (buffer == NULL ||
+          !sk_CRYPTO_BUFFER_push(ret->certs, buffer)) {
+        CRYPTO_BUFFER_free(buffer);
         OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-        X509_free(x509);
         goto err;
       }
     }
   }
 
-  if (CBS_len(&session) != 0) {
+  if (!x509_method->session_cache_objects(ret)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
+    goto err;
+  }
+
+  CBS age_add;
+  int age_add_present;
+  if (!CBS_get_optional_asn1_octet_string(&session, &age_add, &age_add_present,
+                                          kTicketAgeAddTag) ||
+      (age_add_present &&
+       !CBS_get_u32(&age_add, &ret->ticket_age_add)) ||
+      CBS_len(&age_add) != 0) {
+    goto err;
+  }
+  ret->ticket_age_add_valid = age_add_present;
+
+  int is_server;
+  if (!CBS_get_optional_asn1_bool(&session, &is_server, kIsServerTag,
+                                  1 /* default to true */)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
+    goto err;
+  }
+  /* TODO: in time we can include |is_server| for servers too, then we can
+     enforce that client and server sessions are never mixed up. */
+
+  ret->is_server = is_server;
+
+  if (!SSL_SESSION_parse_u16(&session, &ret->peer_signature_algorithm,
+                             kPeerSignatureAlgorithmTag, 0) ||
+      !SSL_SESSION_parse_u32(&session, &ret->ticket_max_early_data,
+                             kTicketMaxEarlyDataTag, 0) ||
+      !SSL_SESSION_parse_u32(&session, &ret->auth_timeout, kAuthTimeoutTag,
+                             ret->timeout) ||
+      !SSL_SESSION_parse_octet_string(&session, &ret->early_alpn,
+                                      &ret->early_alpn_len, kEarlyALPNTag) ||
+      CBS_len(&session) != 0) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SSL_SESSION);
     goto err;
   }
@@ -680,10 +807,11 @@
   return NULL;
 }
 
-SSL_SESSION *SSL_SESSION_from_bytes(const uint8_t *in, size_t in_len) {
+SSL_SESSION *SSL_SESSION_from_bytes(const uint8_t *in, size_t in_len,
+                                    const SSL_CTX *ctx) {
   CBS cbs;
   CBS_init(&cbs, in, in_len);
-  SSL_SESSION *ret = SSL_SESSION_parse(&cbs);
+  SSL_SESSION *ret = SSL_SESSION_parse(&cbs, ctx->x509_method, ctx->pool);
   if (ret == NULL) {
     return NULL;
   }
@@ -694,25 +822,3 @@
   }
   return ret;
 }
-
-SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const uint8_t **pp, long length) {
-  if (length < 0) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    return NULL;
-  }
-
-  CBS cbs;
-  CBS_init(&cbs, *pp, length);
-
-  SSL_SESSION *ret = SSL_SESSION_parse(&cbs);
-  if (ret == NULL) {
-    return NULL;
-  }
-
-  if (a) {
-    SSL_SESSION_free(*a);
-    *a = ret;
-  }
-  *pp = CBS_data(&cbs);
-  return ret;
-}
diff --git a/src/ssl/ssl_buffer.c b/src/ssl/ssl_buffer.c
index 7fd74e4..c27db8b 100644
--- a/src/ssl/ssl_buffer.c
+++ b/src/ssl/ssl_buffer.c
@@ -24,6 +24,7 @@
 #include <openssl/mem.h>
 #include <openssl/type_check.h>
 
+#include "../crypto/internal.h"
 #include "internal.h"
 
 
@@ -67,7 +68,7 @@
 
 static void clear_buffer(SSL3_BUFFER *buf) {
   OPENSSL_free(buf->buf);
-  memset(buf, 0, sizeof(SSL3_BUFFER));
+  OPENSSL_memset(buf, 0, sizeof(SSL3_BUFFER));
 }
 
 OPENSSL_COMPILE_ASSERT(DTLS1_RT_HEADER_LENGTH + SSL3_RT_MAX_ENCRYPTED_LENGTH <=
@@ -85,7 +86,7 @@
 
   size_t header_len = ssl_record_prefix_len(ssl);
   size_t cap = SSL3_RT_MAX_ENCRYPTED_LENGTH;
-  if (SSL_IS_DTLS(ssl)) {
+  if (SSL_is_dtls(ssl)) {
     cap += DTLS1_RT_HEADER_LENGTH;
   } else {
     cap += SSL3_RT_HEADER_LENGTH;
@@ -113,12 +114,11 @@
   }
 
   /* Read a single packet from |ssl->rbio|. |buf->cap| must fit in an int. */
-  ssl->rwstate = SSL_READING;
   int ret = BIO_read(ssl->rbio, buf->buf + buf->offset, (int)buf->cap);
   if (ret <= 0) {
+    ssl->rwstate = SSL_READING;
     return ret;
   }
-  ssl->rwstate = SSL_NOTHING;
   /* |BIO_read| was bound by |buf->cap|, so this cannot overflow. */
   buf->len = (uint16_t)ret;
   return 1;
@@ -136,13 +136,12 @@
   while (buf->len < len) {
     /* The amount of data to read is bounded by |buf->cap|, which must fit in an
      * int. */
-    ssl->rwstate = SSL_READING;
     int ret = BIO_read(ssl->rbio, buf->buf + buf->offset + buf->len,
                        (int)(len - buf->len));
     if (ret <= 0) {
+      ssl->rwstate = SSL_READING;
       return ret;
     }
-    ssl->rwstate = SSL_NOTHING;
     /* |BIO_read| was bound by |buf->cap - buf->len|, so this cannot
      * overflow. */
     buf->len += (uint16_t)ret;
@@ -164,10 +163,8 @@
     return -1;
   }
 
-  ERR_clear_system_error();
-
   int ret;
-  if (SSL_IS_DTLS(ssl)) {
+  if (SSL_is_dtls(ssl)) {
     /* |len| is ignored for a datagram transport. */
     ret = dtls_read_buffer_next_packet(ssl);
   } else {
@@ -186,14 +183,13 @@
   SSL3_BUFFER *buf = &ssl->s3->read_buffer;
 
   consume_buffer(buf, len);
-  if (!SSL_IS_DTLS(ssl)) {
-    /* The TLS stack never reads beyond the current record, so there will never
-     * be unconsumed data. If read-ahead is ever reimplemented,
-     * |ssl_read_buffer_discard| will require a |memcpy| to shift the excess
-     * back to the front of the buffer, to ensure there is enough space for the
-     * next record. */
-     assert(buf->len == 0);
-  }
+
+  /* The TLS stack never reads beyond the current record, so there will never be
+   * unconsumed data. If read-ahead is ever reimplemented,
+   * |ssl_read_buffer_discard| will require a |memcpy| to shift the excess back
+   * to the front of the buffer, to ensure there is enough space for the next
+   * record. */
+  assert(SSL_is_dtls(ssl) || len == 0 || buf->len == 0);
 }
 
 void ssl_read_buffer_discard(SSL *ssl) {
@@ -229,12 +225,12 @@
     return 0;
   }
 
-  size_t header_len = ssl_seal_prefix_len(ssl);
+  size_t header_len = ssl_seal_align_prefix_len(ssl);
 
   /* TODO(davidben): This matches the original behavior in keeping the malloc
    * size consistent. Does this matter? |cap| could just be |max_len|. */
   size_t cap = SSL3_RT_MAX_PLAIN_LENGTH + SSL3_RT_SEND_MAX_ENCRYPTED_OVERHEAD;
-  if (SSL_IS_DTLS(ssl)) {
+  if (SSL_is_dtls(ssl)) {
     cap += DTLS1_RT_HEADER_LENGTH;
   } else {
     cap += SSL3_RT_HEADER_LENGTH;
@@ -268,12 +264,11 @@
   SSL3_BUFFER *buf = &ssl->s3->write_buffer;
 
   while (buf->len > 0) {
-    ssl->rwstate = SSL_WRITING;
     int ret = BIO_write(ssl->wbio, buf->buf + buf->offset, buf->len);
     if (ret <= 0) {
+      ssl->rwstate = SSL_WRITING;
       return ret;
     }
-    ssl->rwstate = SSL_NOTHING;
     consume_buffer(buf, (size_t)ret);
   }
   ssl_write_buffer_clear(ssl);
@@ -286,16 +281,15 @@
     return 1;
   }
 
-  ssl->rwstate = SSL_WRITING;
   int ret = BIO_write(ssl->wbio, buf->buf + buf->offset, buf->len);
   if (ret <= 0) {
+    ssl->rwstate = SSL_WRITING;
     /* If the write failed, drop the write buffer anyway. Datagram transports
      * can't write half a packet, so the caller is expected to retry from the
      * top. */
     ssl_write_buffer_clear(ssl);
     return ret;
   }
-  ssl->rwstate = SSL_NOTHING;
   ssl_write_buffer_clear(ssl);
   return 1;
 }
@@ -305,9 +299,8 @@
     OPENSSL_PUT_ERROR(SSL, SSL_R_BIO_NOT_SET);
     return -1;
   }
-  ERR_clear_system_error();
 
-  if (SSL_IS_DTLS(ssl)) {
+  if (SSL_is_dtls(ssl)) {
     return dtls_write_buffer_flush(ssl);
   } else {
     return tls_write_buffer_flush(ssl);
diff --git a/src/ssl/ssl_cert.c b/src/ssl/ssl_cert.c
index 4952cfd..5013b20 100644
--- a/src/ssl/ssl_cert.c
+++ b/src/ssl/ssl_cert.c
@@ -114,51 +114,59 @@
 
 #include <openssl/ssl.h>
 
+#include <assert.h>
+#include <limits.h>
 #include <string.h>
 
 #include <openssl/bn.h>
 #include <openssl/buf.h>
-#include <openssl/ec_key.h>
+#include <openssl/bytestring.h>
 #include <openssl/dh.h>
+#include <openssl/ec_key.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
+#include <openssl/sha.h>
 #include <openssl/x509.h>
-#include <openssl/x509v3.h>
 
-#include "../crypto/dh/internal.h"
 #include "../crypto/internal.h"
 #include "internal.h"
 
 
-int SSL_get_ex_data_X509_STORE_CTX_idx(void) {
-  /* The ex_data index to go from |X509_STORE_CTX| to |SSL| always uses the
-   * reserved app_data slot. Before ex_data was introduced, app_data was used.
-   * Avoid breaking any software which assumes |X509_STORE_CTX_get_app_data|
-   * works. */
-  return 0;
-}
-
-CERT *ssl_cert_new(void) {
-  CERT *ret = (CERT *)OPENSSL_malloc(sizeof(CERT));
+CERT *ssl_cert_new(const SSL_X509_METHOD *x509_method) {
+  CERT *ret = OPENSSL_malloc(sizeof(CERT));
   if (ret == NULL) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
     return NULL;
   }
-  memset(ret, 0, sizeof(CERT));
+  OPENSSL_memset(ret, 0, sizeof(CERT));
+  ret->x509_method = x509_method;
 
   return ret;
 }
 
+static CRYPTO_BUFFER *buffer_up_ref(CRYPTO_BUFFER *buffer) {
+  CRYPTO_BUFFER_up_ref(buffer);
+  return buffer;
+}
+
 CERT *ssl_cert_dup(CERT *cert) {
-  CERT *ret = (CERT *)OPENSSL_malloc(sizeof(CERT));
+  CERT *ret = OPENSSL_malloc(sizeof(CERT));
   if (ret == NULL) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
     return NULL;
   }
-  memset(ret, 0, sizeof(CERT));
+  OPENSSL_memset(ret, 0, sizeof(CERT));
 
-  ret->mask_k = cert->mask_k;
-  ret->mask_a = cert->mask_a;
+  ret->chain = sk_CRYPTO_BUFFER_deep_copy(cert->chain, buffer_up_ref,
+                                          CRYPTO_BUFFER_free);
+
+  if (cert->privatekey != NULL) {
+    EVP_PKEY_up_ref(cert->privatekey);
+    ret->privatekey = cert->privatekey;
+  }
+
+  ret->key_method = cert->key_method;
+  ret->x509_method = cert->x509_method;
 
   if (cert->dh_tmp != NULL) {
     ret->dh_tmp = DHparams_dup(cert->dh_tmp);
@@ -169,25 +177,33 @@
   }
   ret->dh_tmp_cb = cert->dh_tmp_cb;
 
-  if (cert->x509 != NULL) {
-    ret->x509 = X509_up_ref(cert->x509);
-  }
-
-  if (cert->privatekey != NULL) {
-    ret->privatekey = EVP_PKEY_up_ref(cert->privatekey);
-  }
-
-  if (cert->chain) {
-    ret->chain = X509_chain_up_ref(cert->chain);
-    if (!ret->chain) {
-      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+  if (cert->sigalgs != NULL) {
+    ret->sigalgs =
+        BUF_memdup(cert->sigalgs, cert->num_sigalgs * sizeof(cert->sigalgs[0]));
+    if (ret->sigalgs == NULL) {
       goto err;
     }
   }
+  ret->num_sigalgs = cert->num_sigalgs;
 
   ret->cert_cb = cert->cert_cb;
   ret->cert_cb_arg = cert->cert_cb_arg;
 
+  ret->x509_method->cert_dup(ret, cert);
+
+  if (cert->signed_cert_timestamp_list != NULL) {
+    CRYPTO_BUFFER_up_ref(cert->signed_cert_timestamp_list);
+    ret->signed_cert_timestamp_list = cert->signed_cert_timestamp_list;
+  }
+
+  if (cert->ocsp_response != NULL) {
+    CRYPTO_BUFFER_up_ref(cert->ocsp_response);
+    ret->ocsp_response = cert->ocsp_response;
+  }
+
+  ret->sid_ctx_length = cert->sid_ctx_length;
+  OPENSSL_memcpy(ret->sid_ctx, cert->sid_ctx, sizeof(ret->sid_ctx));
+
   return ret;
 
 err:
@@ -201,12 +217,12 @@
     return;
   }
 
-  X509_free(cert->x509);
-  cert->x509 = NULL;
+  cert->x509_method->cert_clear(cert);
+
+  sk_CRYPTO_BUFFER_pop_free(cert->chain, CRYPTO_BUFFER_free);
+  cert->chain = NULL;
   EVP_PKEY_free(cert->privatekey);
   cert->privatekey = NULL;
-  sk_X509_pop_free(cert->chain, X509_free);
-  cert->chain = NULL;
   cert->key_method = NULL;
 }
 
@@ -218,322 +234,666 @@
   DH_free(c->dh_tmp);
 
   ssl_cert_clear_certs(c);
-  OPENSSL_free(c->peer_sigalgs);
-  OPENSSL_free(c->digest_nids);
+  c->x509_method->cert_free(c);
+  OPENSSL_free(c->sigalgs);
+  CRYPTO_BUFFER_free(c->signed_cert_timestamp_list);
+  CRYPTO_BUFFER_free(c->ocsp_response);
 
   OPENSSL_free(c);
 }
 
-int ssl_cert_set0_chain(CERT *cert, STACK_OF(X509) *chain) {
-  sk_X509_pop_free(cert->chain, X509_free);
-  cert->chain = chain;
-  return 1;
-}
-
-int ssl_cert_set1_chain(CERT *cert, STACK_OF(X509) *chain) {
-  STACK_OF(X509) *dchain;
-  if (chain == NULL) {
-    return ssl_cert_set0_chain(cert, NULL);
-  }
-
-  dchain = X509_chain_up_ref(chain);
-  if (dchain == NULL) {
-    return 0;
-  }
-
-  if (!ssl_cert_set0_chain(cert, dchain)) {
-    sk_X509_pop_free(dchain, X509_free);
-    return 0;
-  }
-
-  return 1;
-}
-
-int ssl_cert_add0_chain_cert(CERT *cert, X509 *x509) {
-  if (cert->chain == NULL) {
-    cert->chain = sk_X509_new_null();
-  }
-  if (cert->chain == NULL || !sk_X509_push(cert->chain, x509)) {
-    return 0;
-  }
-
-  return 1;
-}
-
-int ssl_cert_add1_chain_cert(CERT *cert, X509 *x509) {
-  if (!ssl_cert_add0_chain_cert(cert, x509)) {
-    return 0;
-  }
-
-  X509_up_ref(x509);
-  return 1;
-}
-
-void ssl_cert_set_cert_cb(CERT *c, int (*cb)(SSL *ssl, void *arg), void *arg) {
+static void ssl_cert_set_cert_cb(CERT *c, int (*cb)(SSL *ssl, void *arg),
+                                 void *arg) {
   c->cert_cb = cb;
   c->cert_cb_arg = arg;
 }
 
-int ssl_verify_cert_chain(SSL *ssl, STACK_OF(X509) *cert_chain) {
-  if (cert_chain == NULL || sk_X509_num(cert_chain) == 0) {
-    return 0;
+enum leaf_cert_and_privkey_result_t {
+  leaf_cert_and_privkey_error,
+  leaf_cert_and_privkey_ok,
+  leaf_cert_and_privkey_mismatch,
+};
+
+/* check_leaf_cert_and_privkey checks whether the certificate in |leaf_buffer|
+ * and the private key in |privkey| are suitable and coherent. It returns
+ * |leaf_cert_and_privkey_error| and pushes to the error queue if a problem is
+ * found. If the certificate and private key are valid, but incoherent, it
+ * returns |leaf_cert_and_privkey_mismatch|. Otherwise it returns
+ * |leaf_cert_and_privkey_ok|. */
+static enum leaf_cert_and_privkey_result_t check_leaf_cert_and_privkey(
+    CRYPTO_BUFFER *leaf_buffer, EVP_PKEY *privkey) {
+  enum leaf_cert_and_privkey_result_t ret = leaf_cert_and_privkey_error;
+
+  CBS cert_cbs;
+  CRYPTO_BUFFER_init_CBS(leaf_buffer, &cert_cbs);
+  EVP_PKEY *pubkey = ssl_cert_parse_pubkey(&cert_cbs);
+  if (pubkey == NULL) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    goto out;
   }
 
-  X509 *leaf = sk_X509_value(cert_chain, 0);
-  int ret = 0;
-  X509_STORE_CTX ctx;
-  if (!X509_STORE_CTX_init(&ctx, ssl->ctx->cert_store, leaf, cert_chain)) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_X509_LIB);
-    return 0;
-  }
-  if (!X509_STORE_CTX_set_ex_data(&ctx, SSL_get_ex_data_X509_STORE_CTX_idx(),
-                                  ssl)) {
-    goto err;
+  if (!ssl_is_key_type_supported(pubkey->type)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+    goto out;
   }
 
-  /* We need to inherit the verify parameters. These can be determined by the
-   * context: if its a server it will verify SSL client certificates or vice
-   * versa. */
-  X509_STORE_CTX_set_default(&ctx, ssl->server ? "ssl_client" : "ssl_server");
-
-  /* Anything non-default in "param" should overwrite anything in the ctx. */
-  X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(&ctx), ssl->param);
-
-  if (ssl->verify_callback) {
-    X509_STORE_CTX_set_verify_cb(&ctx, ssl->verify_callback);
+  /* An ECC certificate may be usable for ECDH or ECDSA. We only support ECDSA
+   * certificates, so sanity-check the key usage extension. */
+  if (pubkey->type == EVP_PKEY_EC &&
+      !ssl_cert_check_digital_signature_key_usage(&cert_cbs)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+    goto out;
   }
 
-  if (ssl->ctx->app_verify_callback != NULL) {
-    ret = ssl->ctx->app_verify_callback(&ctx, ssl->ctx->app_verify_arg);
-  } else {
-    ret = X509_verify_cert(&ctx);
+  if (privkey != NULL &&
+      /* Sanity-check that the private key and the certificate match. */
+      !ssl_compare_public_and_private_key(pubkey, privkey)) {
+    ERR_clear_error();
+    ret = leaf_cert_and_privkey_mismatch;
+    goto out;
   }
 
-  ssl->verify_result = ctx.error;
+  ret = leaf_cert_and_privkey_ok;
 
-err:
-  X509_STORE_CTX_cleanup(&ctx);
+out:
+  EVP_PKEY_free(pubkey);
   return ret;
 }
 
-static void set_client_CA_list(STACK_OF(X509_NAME) **ca_list,
-                               STACK_OF(X509_NAME) *name_list) {
-  sk_X509_NAME_pop_free(*ca_list, X509_NAME_free);
-  *ca_list = name_list;
+static int cert_set_chain_and_key(
+    CERT *cert, CRYPTO_BUFFER *const *certs, size_t num_certs,
+    EVP_PKEY *privkey, const SSL_PRIVATE_KEY_METHOD *privkey_method) {
+  if (num_certs == 0 ||
+      (privkey == NULL && privkey_method == NULL)) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
+    return 0;
+  }
+
+  if (privkey != NULL && privkey_method != NULL) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_CANNOT_HAVE_BOTH_PRIVKEY_AND_METHOD);
+    return 0;
+  }
+
+  switch (check_leaf_cert_and_privkey(certs[0], privkey)) {
+    case leaf_cert_and_privkey_error:
+      return 0;
+    case leaf_cert_and_privkey_mismatch:
+      OPENSSL_PUT_ERROR(SSL, SSL_R_CERTIFICATE_AND_PRIVATE_KEY_MISMATCH);
+      return 0;
+    case leaf_cert_and_privkey_ok:
+      break;
+  }
+
+  STACK_OF(CRYPTO_BUFFER) *certs_sk = sk_CRYPTO_BUFFER_new_null();
+  if (certs_sk == NULL) {
+    return 0;
+  }
+
+  for (size_t i = 0; i < num_certs; i++) {
+    if (!sk_CRYPTO_BUFFER_push(certs_sk, certs[i])) {
+      sk_CRYPTO_BUFFER_pop_free(certs_sk, CRYPTO_BUFFER_free);
+      return 0;
+    }
+    CRYPTO_BUFFER_up_ref(certs[i]);
+  }
+
+  EVP_PKEY_free(cert->privatekey);
+  cert->privatekey = privkey;
+  if (privkey != NULL) {
+    EVP_PKEY_up_ref(privkey);
+  }
+  cert->key_method = privkey_method;
+
+  sk_CRYPTO_BUFFER_pop_free(cert->chain, CRYPTO_BUFFER_free);
+  cert->chain = certs_sk;
+
+  return 1;
 }
 
-STACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *list) {
-  STACK_OF(X509_NAME) *ret = sk_X509_NAME_new_null();
+int SSL_set_chain_and_key(SSL *ssl, CRYPTO_BUFFER *const *certs,
+                          size_t num_certs, EVP_PKEY *privkey,
+                          const SSL_PRIVATE_KEY_METHOD *privkey_method) {
+  return cert_set_chain_and_key(ssl->cert, certs, num_certs, privkey,
+                                privkey_method);
+}
+
+int SSL_CTX_set_chain_and_key(SSL_CTX *ctx, CRYPTO_BUFFER *const *certs,
+                              size_t num_certs, EVP_PKEY *privkey,
+                              const SSL_PRIVATE_KEY_METHOD *privkey_method) {
+  return cert_set_chain_and_key(ctx->cert, certs, num_certs, privkey,
+                                privkey_method);
+}
+
+int ssl_set_cert(CERT *cert, CRYPTO_BUFFER *buffer) {
+  switch (check_leaf_cert_and_privkey(buffer, cert->privatekey)) {
+    case leaf_cert_and_privkey_error:
+      return 0;
+    case leaf_cert_and_privkey_mismatch:
+      /* don't fail for a cert/key mismatch, just free current private key
+       * (when switching to a different cert & key, first this function should
+       * be used, then |ssl_set_pkey|. */
+      EVP_PKEY_free(cert->privatekey);
+      cert->privatekey = NULL;
+      break;
+    case leaf_cert_and_privkey_ok:
+      break;
+  }
+
+  cert->x509_method->cert_flush_cached_leaf(cert);
+
+  if (cert->chain != NULL) {
+    CRYPTO_BUFFER_free(sk_CRYPTO_BUFFER_value(cert->chain, 0));
+    sk_CRYPTO_BUFFER_set(cert->chain, 0, buffer);
+    CRYPTO_BUFFER_up_ref(buffer);
+    return 1;
+  }
+
+  cert->chain = sk_CRYPTO_BUFFER_new_null();
+  if (cert->chain == NULL) {
+    return 0;
+  }
+
+  if (!sk_CRYPTO_BUFFER_push(cert->chain, buffer)) {
+    sk_CRYPTO_BUFFER_free(cert->chain);
+    cert->chain = NULL;
+    return 0;
+  }
+  CRYPTO_BUFFER_up_ref(buffer);
+
+  return 1;
+}
+
+int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, size_t der_len,
+                                 const uint8_t *der) {
+  CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new(der, der_len, NULL);
+  if (buffer == NULL) {
+    return 0;
+  }
+
+  const int ok = ssl_set_cert(ctx->cert, buffer);
+  CRYPTO_BUFFER_free(buffer);
+  return ok;
+}
+
+int SSL_use_certificate_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) {
+  CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new(der, der_len, NULL);
+  if (buffer == NULL) {
+    return 0;
+  }
+
+  const int ok = ssl_set_cert(ssl->cert, buffer);
+  CRYPTO_BUFFER_free(buffer);
+  return ok;
+}
+
+int ssl_has_certificate(const SSL *ssl) {
+  return ssl->cert->chain != NULL &&
+         sk_CRYPTO_BUFFER_value(ssl->cert->chain, 0) != NULL &&
+         ssl_has_private_key(ssl);
+}
+
+STACK_OF(CRYPTO_BUFFER) *ssl_parse_cert_chain(uint8_t *out_alert,
+                                              EVP_PKEY **out_pubkey,
+                                              uint8_t *out_leaf_sha256,
+                                              CBS *cbs,
+                                              CRYPTO_BUFFER_POOL *pool) {
+  *out_pubkey = NULL;
+
+  STACK_OF(CRYPTO_BUFFER) *ret = sk_CRYPTO_BUFFER_new_null();
   if (ret == NULL) {
+    *out_alert = SSL_AD_INTERNAL_ERROR;
+    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
     return NULL;
   }
 
-  size_t i;
-  for (i = 0; i < sk_X509_NAME_num(list); i++) {
-      X509_NAME *name = X509_NAME_dup(sk_X509_NAME_value(list, i));
-    if (name == NULL || !sk_X509_NAME_push(ret, name)) {
-      X509_NAME_free(name);
-      sk_X509_NAME_pop_free(ret, X509_NAME_free);
-      return NULL;
+  CBS certificate_list;
+  if (!CBS_get_u24_length_prefixed(cbs, &certificate_list)) {
+    *out_alert = SSL_AD_DECODE_ERROR;
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    goto err;
+  }
+
+  while (CBS_len(&certificate_list) > 0) {
+    CBS certificate;
+    if (!CBS_get_u24_length_prefixed(&certificate_list, &certificate) ||
+        CBS_len(&certificate) == 0) {
+      *out_alert = SSL_AD_DECODE_ERROR;
+      OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_LENGTH_MISMATCH);
+      goto err;
     }
+
+    if (sk_CRYPTO_BUFFER_num(ret) == 0) {
+      *out_pubkey = ssl_cert_parse_pubkey(&certificate);
+      if (*out_pubkey == NULL) {
+        *out_alert = SSL_AD_DECODE_ERROR;
+        goto err;
+      }
+
+      /* Retain the hash of the leaf certificate if requested. */
+      if (out_leaf_sha256 != NULL) {
+        SHA256(CBS_data(&certificate), CBS_len(&certificate), out_leaf_sha256);
+      }
+    }
+
+    CRYPTO_BUFFER *buf =
+        CRYPTO_BUFFER_new_from_CBS(&certificate, pool);
+    if (buf == NULL) {
+      *out_alert = SSL_AD_DECODE_ERROR;
+      goto err;
+    }
+
+    if (!sk_CRYPTO_BUFFER_push(ret, buf)) {
+      *out_alert = SSL_AD_INTERNAL_ERROR;
+      CRYPTO_BUFFER_free(buf);
+      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+      goto err;
+    }
+  }
+
+  return ret;
+
+err:
+  EVP_PKEY_free(*out_pubkey);
+  *out_pubkey = NULL;
+  sk_CRYPTO_BUFFER_pop_free(ret, CRYPTO_BUFFER_free);
+  return NULL;
+}
+
+int ssl_add_cert_chain(SSL *ssl, CBB *cbb) {
+  if (!ssl_has_certificate(ssl)) {
+    return CBB_add_u24(cbb, 0);
+  }
+
+  CBB certs;
+  if (!CBB_add_u24_length_prefixed(cbb, &certs)) {
+    goto err;
+  }
+
+  STACK_OF(CRYPTO_BUFFER) *chain = ssl->cert->chain;
+  for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(chain); i++) {
+    CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(chain, i);
+    CBB child;
+    if (!CBB_add_u24_length_prefixed(&certs, &child) ||
+        !CBB_add_bytes(&child, CRYPTO_BUFFER_data(buffer),
+                       CRYPTO_BUFFER_len(buffer)) ||
+        !CBB_flush(&certs)) {
+      goto err;
+    }
+  }
+
+  return CBB_flush(cbb);
+
+err:
+  OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+  return 0;
+}
+
+/* ssl_cert_skip_to_spki parses a DER-encoded, X.509 certificate from |in| and
+ * positions |*out_tbs_cert| to cover the TBSCertificate, starting at the
+ * subjectPublicKeyInfo. */
+static int ssl_cert_skip_to_spki(const CBS *in, CBS *out_tbs_cert) {
+  /* From RFC 5280, section 4.1
+   *    Certificate  ::=  SEQUENCE  {
+   *      tbsCertificate       TBSCertificate,
+   *      signatureAlgorithm   AlgorithmIdentifier,
+   *      signatureValue       BIT STRING  }
+
+   * TBSCertificate  ::=  SEQUENCE  {
+   *      version         [0]  EXPLICIT Version DEFAULT v1,
+   *      serialNumber         CertificateSerialNumber,
+   *      signature            AlgorithmIdentifier,
+   *      issuer               Name,
+   *      validity             Validity,
+   *      subject              Name,
+   *      subjectPublicKeyInfo SubjectPublicKeyInfo,
+   *      ... } */
+  CBS buf = *in;
+
+  CBS toplevel;
+  if (!CBS_get_asn1(&buf, &toplevel, CBS_ASN1_SEQUENCE) ||
+      CBS_len(&buf) != 0 ||
+      !CBS_get_asn1(&toplevel, out_tbs_cert, CBS_ASN1_SEQUENCE) ||
+      /* version */
+      !CBS_get_optional_asn1(
+          out_tbs_cert, NULL, NULL,
+          CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0) ||
+      /* serialNumber */
+      !CBS_get_asn1(out_tbs_cert, NULL, CBS_ASN1_INTEGER) ||
+      /* signature algorithm */
+      !CBS_get_asn1(out_tbs_cert, NULL, CBS_ASN1_SEQUENCE) ||
+      /* issuer */
+      !CBS_get_asn1(out_tbs_cert, NULL, CBS_ASN1_SEQUENCE) ||
+      /* validity */
+      !CBS_get_asn1(out_tbs_cert, NULL, CBS_ASN1_SEQUENCE) ||
+      /* subject */
+      !CBS_get_asn1(out_tbs_cert, NULL, CBS_ASN1_SEQUENCE)) {
+    return 0;
+  }
+
+  return 1;
+}
+
+EVP_PKEY *ssl_cert_parse_pubkey(const CBS *in) {
+  CBS buf = *in, tbs_cert;
+  if (!ssl_cert_skip_to_spki(&buf, &tbs_cert)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_CANNOT_PARSE_LEAF_CERT);
+    return NULL;
+  }
+
+  return EVP_parse_public_key(&tbs_cert);
+}
+
+int ssl_compare_public_and_private_key(const EVP_PKEY *pubkey,
+                                       const EVP_PKEY *privkey) {
+  if (EVP_PKEY_is_opaque(privkey)) {
+    /* We cannot check an opaque private key and have to trust that it
+     * matches. */
+    return 1;
+  }
+
+  int ret = 0;
+
+  switch (EVP_PKEY_cmp(pubkey, privkey)) {
+    case 1:
+      ret = 1;
+      break;
+    case 0:
+      OPENSSL_PUT_ERROR(X509, X509_R_KEY_VALUES_MISMATCH);
+      break;
+    case -1:
+      OPENSSL_PUT_ERROR(X509, X509_R_KEY_TYPE_MISMATCH);
+      break;
+    case -2:
+      OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_KEY_TYPE);
+    default:
+      assert(0);
+      break;
   }
 
   return ret;
 }
 
-void SSL_set_client_CA_list(SSL *ssl, STACK_OF(X509_NAME) *name_list) {
-  set_client_CA_list(&ssl->client_CA, name_list);
-}
-
-void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list) {
-  set_client_CA_list(&ctx->client_CA, name_list);
-}
-
-STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *ctx) {
-  return ctx->client_CA;
-}
-
-STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *ssl) {
-  /* For historical reasons, this function is used both to query configuration
-   * state on a server as well as handshake state on a client. However, whether
-   * |ssl| is a client or server is not known until explicitly configured with
-   * |SSL_set_connect_state|. If |handshake_func| is NULL, |ssl| is in an
-   * indeterminate mode and |ssl->server| is unset. */
-  if (ssl->handshake_func != NULL && !ssl->server) {
-    return ssl->s3->tmp.ca_names;
-  }
-
-  if (ssl->client_CA != NULL) {
-    return ssl->client_CA;
-  }
-  return ssl->ctx->client_CA;
-}
-
-static int add_client_CA(STACK_OF(X509_NAME) **sk, X509 *x509) {
-  X509_NAME *name;
-
-  if (x509 == NULL) {
+int ssl_cert_check_private_key(const CERT *cert, const EVP_PKEY *privkey) {
+  if (privkey == NULL) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_NO_PRIVATE_KEY_ASSIGNED);
     return 0;
   }
-  if (*sk == NULL) {
-    *sk = sk_X509_NAME_new_null();
-    if (*sk == NULL) {
+
+  if (cert->chain == NULL ||
+      sk_CRYPTO_BUFFER_value(cert->chain, 0) == NULL) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_ASSIGNED);
+    return 0;
+  }
+
+  CBS cert_cbs;
+  CRYPTO_BUFFER_init_CBS(sk_CRYPTO_BUFFER_value(cert->chain, 0), &cert_cbs);
+  EVP_PKEY *pubkey = ssl_cert_parse_pubkey(&cert_cbs);
+  if (!pubkey) {
+    OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_KEY_TYPE);
+    return 0;
+  }
+
+  const int ok = ssl_compare_public_and_private_key(pubkey, privkey);
+  EVP_PKEY_free(pubkey);
+  return ok;
+}
+
+int ssl_cert_check_digital_signature_key_usage(const CBS *in) {
+  CBS buf = *in;
+
+  CBS tbs_cert, outer_extensions;
+  int has_extensions;
+  if (!ssl_cert_skip_to_spki(&buf, &tbs_cert) ||
+      /* subjectPublicKeyInfo */
+      !CBS_get_asn1(&tbs_cert, NULL, CBS_ASN1_SEQUENCE) ||
+      /* issuerUniqueID */
+      !CBS_get_optional_asn1(
+          &tbs_cert, NULL, NULL,
+          CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 1) ||
+      /* subjectUniqueID */
+      !CBS_get_optional_asn1(
+          &tbs_cert, NULL, NULL,
+          CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 2) ||
+      !CBS_get_optional_asn1(
+          &tbs_cert, &outer_extensions, &has_extensions,
+          CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 3)) {
+    goto parse_err;
+  }
+
+  if (!has_extensions) {
+    return 1;
+  }
+
+  CBS extensions;
+  if (!CBS_get_asn1(&outer_extensions, &extensions, CBS_ASN1_SEQUENCE)) {
+    goto parse_err;
+  }
+
+  while (CBS_len(&extensions) > 0) {
+    CBS extension, oid, contents;
+    if (!CBS_get_asn1(&extensions, &extension, CBS_ASN1_SEQUENCE) ||
+        !CBS_get_asn1(&extension, &oid, CBS_ASN1_OBJECT) ||
+        (CBS_peek_asn1_tag(&extension, CBS_ASN1_BOOLEAN) &&
+         !CBS_get_asn1(&extension, NULL, CBS_ASN1_BOOLEAN)) ||
+        !CBS_get_asn1(&extension, &contents, CBS_ASN1_OCTETSTRING) ||
+        CBS_len(&extension) != 0) {
+      goto parse_err;
+    }
+
+    static const uint8_t kKeyUsageOID[3] = {0x55, 0x1d, 0x0f};
+    if (CBS_len(&oid) != sizeof(kKeyUsageOID) ||
+        OPENSSL_memcmp(CBS_data(&oid), kKeyUsageOID, sizeof(kKeyUsageOID)) !=
+            0) {
+      continue;
+    }
+
+    CBS bit_string;
+    if (!CBS_get_asn1(&contents, &bit_string, CBS_ASN1_BITSTRING) ||
+        CBS_len(&contents) != 0) {
+      goto parse_err;
+    }
+
+    /* This is the KeyUsage extension. See
+     * https://tools.ietf.org/html/rfc5280#section-4.2.1.3 */
+    if (!CBS_is_valid_asn1_bitstring(&bit_string)) {
+      goto parse_err;
+    }
+
+    if (!CBS_asn1_bitstring_has_bit(&bit_string, 0)) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_ECC_CERT_NOT_FOR_SIGNING);
+      return 0;
+    }
+
+    return 1;
+  }
+
+  /* No KeyUsage extension found. */
+  return 1;
+
+parse_err:
+  OPENSSL_PUT_ERROR(SSL, SSL_R_CANNOT_PARSE_LEAF_CERT);
+  return 0;
+}
+
+STACK_OF(CRYPTO_BUFFER) *
+    ssl_parse_client_CA_list(SSL *ssl, uint8_t *out_alert, CBS *cbs) {
+  CRYPTO_BUFFER_POOL *const pool = ssl->ctx->pool;
+
+  STACK_OF(CRYPTO_BUFFER) *ret = sk_CRYPTO_BUFFER_new_null();
+  if (ret == NULL) {
+    *out_alert = SSL_AD_INTERNAL_ERROR;
+    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+    return NULL;
+  }
+
+  CBS child;
+  if (!CBS_get_u16_length_prefixed(cbs, &child)) {
+    *out_alert = SSL_AD_DECODE_ERROR;
+    OPENSSL_PUT_ERROR(SSL, SSL_R_LENGTH_MISMATCH);
+    goto err;
+  }
+
+  while (CBS_len(&child) > 0) {
+    CBS distinguished_name;
+    if (!CBS_get_u16_length_prefixed(&child, &distinguished_name)) {
+      *out_alert = SSL_AD_DECODE_ERROR;
+      OPENSSL_PUT_ERROR(SSL, SSL_R_CA_DN_TOO_LONG);
+      goto err;
+    }
+
+    CRYPTO_BUFFER *buffer =
+        CRYPTO_BUFFER_new_from_CBS(&distinguished_name, pool);
+    if (buffer == NULL ||
+        !sk_CRYPTO_BUFFER_push(ret, buffer)) {
+      CRYPTO_BUFFER_free(buffer);
+      *out_alert = SSL_AD_INTERNAL_ERROR;
+      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+      goto err;
+    }
+  }
+
+  if (!ssl->ctx->x509_method->check_client_CA_list(ret)) {
+    *out_alert = SSL_AD_INTERNAL_ERROR;
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    goto err;
+  }
+
+  return ret;
+
+err:
+  sk_CRYPTO_BUFFER_pop_free(ret, CRYPTO_BUFFER_free);
+  return NULL;
+}
+
+int ssl_add_client_CA_list(SSL *ssl, CBB *cbb) {
+  CBB child, name_cbb;
+  if (!CBB_add_u16_length_prefixed(cbb, &child)) {
+    return 0;
+  }
+
+  STACK_OF(CRYPTO_BUFFER) *names = ssl->client_CA;
+  if (names == NULL) {
+    names = ssl->ctx->client_CA;
+  }
+  if (names == NULL) {
+    return CBB_flush(cbb);
+  }
+
+  for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(names); i++) {
+    const CRYPTO_BUFFER *name = sk_CRYPTO_BUFFER_value(names, i);
+
+    if (!CBB_add_u16_length_prefixed(&child, &name_cbb) ||
+        !CBB_add_bytes(&name_cbb, CRYPTO_BUFFER_data(name),
+                       CRYPTO_BUFFER_len(name))) {
       return 0;
     }
   }
 
-  name = X509_NAME_dup(X509_get_subject_name(x509));
-  if (name == NULL) {
+  return CBB_flush(cbb);
+}
+
+void SSL_CTX_set_cert_cb(SSL_CTX *ctx, int (*cb)(SSL *ssl, void *arg),
+                         void *arg) {
+  ssl_cert_set_cert_cb(ctx->cert, cb, arg);
+}
+
+void SSL_set_cert_cb(SSL *ssl, int (*cb)(SSL *ssl, void *arg), void *arg) {
+  ssl_cert_set_cert_cb(ssl->cert, cb, arg);
+}
+
+STACK_OF(CRYPTO_BUFFER) *SSL_get0_peer_certificates(const SSL *ssl) {
+  SSL_SESSION *session = SSL_get_session(ssl);
+  if (session == NULL) {
+    return NULL;
+  }
+
+  return session->certs;
+}
+
+STACK_OF(CRYPTO_BUFFER) *SSL_get0_server_requested_CAs(const SSL *ssl) {
+  if (ssl->s3->hs == NULL) {
+    return NULL;
+  }
+  return ssl->s3->hs->ca_names;
+}
+
+int ssl_check_leaf_certificate(SSL_HANDSHAKE *hs, EVP_PKEY *pkey,
+                               const CRYPTO_BUFFER *leaf) {
+  SSL *const ssl = hs->ssl;
+  assert(ssl3_protocol_version(ssl) < TLS1_3_VERSION);
+
+  /* Check the certificate's type matches the cipher. */
+  int expected_type = ssl_cipher_get_key_type(hs->new_cipher);
+  assert(expected_type != EVP_PKEY_NONE);
+  if (pkey->type != expected_type) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CERTIFICATE_TYPE);
     return 0;
   }
 
-  if (!sk_X509_NAME_push(*sk, name)) {
-    X509_NAME_free(name);
-    return 0;
-  }
-
-  return 1;
-}
-
-int SSL_add_client_CA(SSL *ssl, X509 *x509) {
-  return add_client_CA(&ssl->client_CA, x509);
-}
-
-int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x509) {
-  return add_client_CA(&ctx->client_CA, x509);
-}
-
-/* Add a certificate to a BUF_MEM structure */
-static int ssl_add_cert_to_buf(BUF_MEM *buf, unsigned long *l, X509 *x) {
-  int n;
-  uint8_t *p;
-
-  n = i2d_X509(x, NULL);
-  if (!BUF_MEM_grow_clean(buf, (int)(n + (*l) + 3))) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
-    return 0;
-  }
-  p = (uint8_t *)&(buf->data[*l]);
-  l2n3(n, p);
-  i2d_X509(x, &p);
-  *l += n + 3;
-
-  return 1;
-}
-
-/* Add certificate chain to internal SSL BUF_MEM structure. */
-int ssl_add_cert_chain(SSL *ssl, unsigned long *l) {
-  CERT *cert = ssl->cert;
-  BUF_MEM *buf = ssl->init_buf;
-  int no_chain = 0;
-  size_t i;
-
-  X509 *x = cert->x509;
-  STACK_OF(X509) *chain = cert->chain;
-
-  if (x == NULL) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET);
-    return 0;
-  }
-
-  if ((ssl->mode & SSL_MODE_NO_AUTO_CHAIN) || chain != NULL) {
-    no_chain = 1;
-  }
-
-  if (no_chain) {
-    if (!ssl_add_cert_to_buf(buf, l, x)) {
+  if (hs->new_cipher->algorithm_auth & SSL_aECDSA) {
+    CBS leaf_cbs;
+    CBS_init(&leaf_cbs, CRYPTO_BUFFER_data(leaf), CRYPTO_BUFFER_len(leaf));
+    /* ECDSA and ECDH certificates use the same public key format. Instead,
+     * they are distinguished by the key usage extension in the certificate. */
+    if (!ssl_cert_check_digital_signature_key_usage(&leaf_cbs)) {
       return 0;
     }
 
-    for (i = 0; i < sk_X509_num(chain); i++) {
-      x = sk_X509_value(chain, i);
-      if (!ssl_add_cert_to_buf(buf, l, x)) {
-        return 0;
-      }
-    }
-  } else {
-    X509_STORE_CTX xs_ctx;
-
-    if (!X509_STORE_CTX_init(&xs_ctx, ssl->ctx->cert_store, x, NULL)) {
-      OPENSSL_PUT_ERROR(SSL, ERR_R_X509_LIB);
+    EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey);
+    if (ec_key == NULL) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECC_CERT);
       return 0;
     }
-    X509_verify_cert(&xs_ctx);
-    /* Don't leave errors in the queue */
-    ERR_clear_error();
-    for (i = 0; i < sk_X509_num(xs_ctx.chain); i++) {
-      x = sk_X509_value(xs_ctx.chain, i);
 
-      if (!ssl_add_cert_to_buf(buf, l, x)) {
-        X509_STORE_CTX_cleanup(&xs_ctx);
-        return 0;
-      }
+    /* Check the key's group and point format are acceptable. */
+    uint16_t group_id;
+    if (!ssl_nid_to_group_id(
+            &group_id, EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key))) ||
+        !tls1_check_group_id(ssl, group_id) ||
+        EC_KEY_get_conv_form(ec_key) != POINT_CONVERSION_UNCOMPRESSED) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ECC_CERT);
+      return 0;
     }
-    X509_STORE_CTX_cleanup(&xs_ctx);
   }
 
   return 1;
 }
 
-int SSL_CTX_set0_chain(SSL_CTX *ctx, STACK_OF(X509) *chain) {
-  return ssl_cert_set0_chain(ctx->cert, chain);
+static int set_signed_cert_timestamp_list(CERT *cert, const uint8_t *list,
+                                           size_t list_len) {
+  CBS sct_list;
+  CBS_init(&sct_list, list, list_len);
+  if (!ssl_is_sct_list_valid(&sct_list)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_SCT_LIST);
+    return 0;
+  }
+
+  CRYPTO_BUFFER_free(cert->signed_cert_timestamp_list);
+  cert->signed_cert_timestamp_list =
+      CRYPTO_BUFFER_new(CBS_data(&sct_list), CBS_len(&sct_list), NULL);
+  return cert->signed_cert_timestamp_list != NULL;
 }
 
-int SSL_CTX_set1_chain(SSL_CTX *ctx, STACK_OF(X509) *chain) {
-  return ssl_cert_set1_chain(ctx->cert, chain);
+int SSL_CTX_set_signed_cert_timestamp_list(SSL_CTX *ctx, const uint8_t *list,
+                                           size_t list_len) {
+  return set_signed_cert_timestamp_list(ctx->cert, list, list_len);
 }
 
-int SSL_set0_chain(SSL *ssl, STACK_OF(X509) *chain) {
-  return ssl_cert_set0_chain(ssl->cert, chain);
+int SSL_set_signed_cert_timestamp_list(SSL *ssl, const uint8_t *list,
+                                       size_t list_len) {
+  return set_signed_cert_timestamp_list(ssl->cert, list, list_len);
 }
 
-int SSL_set1_chain(SSL *ssl, STACK_OF(X509) *chain) {
-  return ssl_cert_set1_chain(ssl->cert, chain);
+int SSL_CTX_set_ocsp_response(SSL_CTX *ctx, const uint8_t *response,
+                              size_t response_len) {
+  CRYPTO_BUFFER_free(ctx->cert->ocsp_response);
+  ctx->cert->ocsp_response = CRYPTO_BUFFER_new(response, response_len, NULL);
+  return ctx->cert->ocsp_response != NULL;
 }
 
-int SSL_CTX_add0_chain_cert(SSL_CTX *ctx, X509 *x509) {
-  return ssl_cert_add0_chain_cert(ctx->cert, x509);
-}
-
-int SSL_CTX_add1_chain_cert(SSL_CTX *ctx, X509 *x509) {
-  return ssl_cert_add1_chain_cert(ctx->cert, x509);
-}
-
-int SSL_CTX_add_extra_chain_cert(SSL_CTX *ctx, X509 *x509) {
-  return SSL_CTX_add0_chain_cert(ctx, x509);
-}
-
-int SSL_add0_chain_cert(SSL *ssl, X509 *x509) {
-  return ssl_cert_add0_chain_cert(ssl->cert, x509);
-}
-
-int SSL_add1_chain_cert(SSL *ssl, X509 *x509) {
-  return ssl_cert_add1_chain_cert(ssl->cert, x509);
-}
-
-int SSL_CTX_clear_chain_certs(SSL_CTX *ctx) {
-  return SSL_CTX_set0_chain(ctx, NULL);
-}
-
-int SSL_CTX_clear_extra_chain_certs(SSL_CTX *ctx) {
-  return SSL_CTX_clear_chain_certs(ctx);
-}
-
-int SSL_clear_chain_certs(SSL *ssl) {
-  return SSL_set0_chain(ssl, NULL);
-}
-
-int SSL_CTX_get0_chain_certs(const SSL_CTX *ctx, STACK_OF(X509) **out_chain) {
-  *out_chain = ctx->cert->chain;
-  return 1;
-}
-
-int SSL_CTX_get_extra_chain_certs(const SSL_CTX *ctx,
-                                  STACK_OF(X509) **out_chain) {
-  return SSL_CTX_get0_chain_certs(ctx, out_chain);
-}
-
-int SSL_get0_chain_certs(const SSL *ssl, STACK_OF(X509) **out_chain) {
-  *out_chain = ssl->cert->chain;
-  return 1;
+int SSL_set_ocsp_response(SSL *ssl, const uint8_t *response,
+                          size_t response_len) {
+  CRYPTO_BUFFER_free(ssl->cert->ocsp_response);
+  ssl->cert->ocsp_response = CRYPTO_BUFFER_new(response, response_len, NULL);
+  return ssl->cert->ocsp_response != NULL;
 }
diff --git a/src/ssl/ssl_cipher.c b/src/ssl/ssl_cipher.c
index 77fa8fa..a72b541 100644
--- a/src/ssl/ssl_cipher.c
+++ b/src/ssl/ssl_cipher.c
@@ -141,7 +141,6 @@
 #include <openssl/ssl.h>
 
 #include <assert.h>
-#include <stdio.h>
 #include <string.h>
 
 #include <openssl/buf.h>
@@ -152,6 +151,7 @@
 #include <openssl/stack.h>
 
 #include "internal.h"
+#include "../crypto/internal.h"
 
 
 /* kCiphers is an array of all supported ciphers, sorted by id. */
@@ -168,28 +168,6 @@
      SSL_HANDSHAKE_MAC_DEFAULT,
     },
 
-    /* Cipher 04 */
-    {
-     SSL3_TXT_RSA_RC4_128_MD5,
-     SSL3_CK_RSA_RC4_128_MD5,
-     SSL_kRSA,
-     SSL_aRSA,
-     SSL_RC4,
-     SSL_MD5,
-     SSL_HANDSHAKE_MAC_DEFAULT,
-    },
-
-    /* Cipher 05 */
-    {
-     SSL3_TXT_RSA_RC4_128_SHA,
-     SSL3_CK_RSA_RC4_128_SHA,
-     SSL_kRSA,
-     SSL_aRSA,
-     SSL_RC4,
-     SSL_SHA1,
-     SSL_HANDSHAKE_MAC_DEFAULT,
-    },
-
     /* Cipher 0A */
     {
      SSL3_TXT_RSA_DES_192_CBC3_SHA,
@@ -215,6 +193,7 @@
      SSL_HANDSHAKE_MAC_DEFAULT,
     },
 
+#ifdef BORINGSSL_ENABLE_DHE_TLS
     /* Cipher 33 */
     {
      TLS1_TXT_DHE_RSA_WITH_AES_128_SHA,
@@ -225,6 +204,7 @@
      SSL_SHA1,
      SSL_HANDSHAKE_MAC_DEFAULT,
     },
+#endif
 
     /* Cipher 35 */
     {
@@ -237,6 +217,7 @@
      SSL_HANDSHAKE_MAC_DEFAULT,
     },
 
+#ifdef BORINGSSL_ENABLE_DHE_TLS
     /* Cipher 39 */
     {
      TLS1_TXT_DHE_RSA_WITH_AES_256_SHA,
@@ -247,6 +228,7 @@
      SSL_SHA1,
      SSL_HANDSHAKE_MAC_DEFAULT,
     },
+#endif
 
 
     /* TLS v1.2 ciphersuites */
@@ -273,6 +255,7 @@
      SSL_HANDSHAKE_MAC_SHA256,
     },
 
+#ifdef BORINGSSL_ENABLE_DHE_TLS
     /* Cipher 67 */
     {
      TLS1_TXT_DHE_RSA_WITH_AES_128_SHA256,
@@ -294,20 +277,10 @@
      SSL_SHA256,
      SSL_HANDSHAKE_MAC_SHA256,
     },
+#endif
 
     /* PSK cipher suites. */
 
-    /* Cipher 8A */
-    {
-     TLS1_TXT_PSK_WITH_RC4_128_SHA,
-     TLS1_CK_PSK_WITH_RC4_128_SHA,
-     SSL_kPSK,
-     SSL_aPSK,
-     SSL_RC4,
-     SSL_SHA1,
-     SSL_HANDSHAKE_MAC_DEFAULT,
-    },
-
     /* Cipher 8C */
     {
      TLS1_TXT_PSK_WITH_AES_128_CBC_SHA,
@@ -354,6 +327,7 @@
      SSL_HANDSHAKE_MAC_SHA384,
     },
 
+#ifdef BORINGSSL_ENABLE_DHE_TLS
     /* Cipher 9E */
     {
      TLS1_TXT_DHE_RSA_WITH_AES_128_GCM_SHA256,
@@ -375,16 +349,41 @@
      SSL_AEAD,
      SSL_HANDSHAKE_MAC_SHA384,
     },
+#endif
 
-    /* Cipher C007 */
+    /* TLS 1.3 suites. */
+
+    /* Cipher 1301 */
     {
-     TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA,
-     TLS1_CK_ECDHE_ECDSA_WITH_RC4_128_SHA,
-     SSL_kECDHE,
-     SSL_aECDSA,
-     SSL_RC4,
-     SSL_SHA1,
-     SSL_HANDSHAKE_MAC_DEFAULT,
+      TLS1_TXT_AES_128_GCM_SHA256,
+      TLS1_CK_AES_128_GCM_SHA256,
+      SSL_kGENERIC,
+      SSL_aGENERIC,
+      SSL_AES128GCM,
+      SSL_AEAD,
+      SSL_HANDSHAKE_MAC_SHA256,
+    },
+
+    /* Cipher 1302 */
+    {
+      TLS1_TXT_AES_256_GCM_SHA384,
+      TLS1_CK_AES_256_GCM_SHA384,
+      SSL_kGENERIC,
+      SSL_aGENERIC,
+      SSL_AES256GCM,
+      SSL_AEAD,
+      SSL_HANDSHAKE_MAC_SHA384,
+    },
+
+    /* Cipher 1303 */
+    {
+      TLS1_TXT_CHACHA20_POLY1305_SHA256,
+      TLS1_CK_CHACHA20_POLY1305_SHA256,
+      SSL_kGENERIC,
+      SSL_aGENERIC,
+      SSL_CHACHA20POLY1305,
+      SSL_AEAD,
+      SSL_HANDSHAKE_MAC_SHA256,
     },
 
     /* Cipher C009 */
@@ -409,17 +408,6 @@
      SSL_HANDSHAKE_MAC_DEFAULT,
     },
 
-    /* Cipher C011 */
-    {
-     TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA,
-     TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA,
-     SSL_kECDHE,
-     SSL_aRSA,
-     SSL_RC4,
-     SSL_SHA1,
-     SSL_HANDSHAKE_MAC_DEFAULT,
-    },
-
     /* Cipher C013 */
     {
      TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA,
@@ -562,28 +550,6 @@
 
     /* ChaCha20-Poly1305 cipher suites. */
 
-#if !defined(BORINGSSL_ANDROID_SYSTEM)
-    {
-     TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305_OLD,
-     TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD,
-     SSL_kECDHE,
-     SSL_aRSA,
-     SSL_CHACHA20POLY1305_OLD,
-     SSL_AEAD,
-     SSL_HANDSHAKE_MAC_SHA256,
-    },
-
-    {
-     TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_OLD,
-     TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD,
-     SSL_kECDHE,
-     SSL_aECDSA,
-     SSL_CHACHA20POLY1305_OLD,
-     SSL_AEAD,
-     SSL_HANDSHAKE_MAC_SHA256,
-    },
-#endif
-
     /* Cipher CCA8 */
     {
      TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
@@ -616,9 +582,10 @@
      SSL_AEAD,
      SSL_HANDSHAKE_MAC_SHA256,
     },
+
 };
 
-static const size_t kCiphersLen = sizeof(kCiphers) / sizeof(kCiphers[0]);
+static const size_t kCiphersLen = OPENSSL_ARRAY_SIZE(kCiphers);
 
 #define CIPHER_ADD 1
 #define CIPHER_KILL 2
@@ -652,7 +619,7 @@
 } CIPHER_ALIAS;
 
 static const CIPHER_ALIAS kCipherAliases[] = {
-    /* "ALL" doesn't include eNULL (must be specifically enabled) */
+    /* "ALL" doesn't include eNULL. It must be explicitly enabled. */
     {"ALL", ~0u, ~0u, ~SSL_eNULL, ~0u, 0},
 
     /* The "COMPLEMENTOFDEFAULT" rule is omitted. It matches nothing. */
@@ -663,9 +630,11 @@
      * e.g. kEDH combines DHE_DSS and DHE_RSA) */
     {"kRSA", SSL_kRSA, ~0u, ~0u, ~0u, 0},
 
+#ifdef BORINGSSL_ENABLE_DHE_TLS
     {"kDHE", SSL_kDHE, ~0u, ~0u, ~0u, 0},
     {"kEDH", SSL_kDHE, ~0u, ~0u, ~0u, 0},
     {"DH", SSL_kDHE, ~0u, ~0u, ~0u, 0},
+#endif
 
     {"kECDHE", SSL_kECDHE, ~0u, ~0u, ~0u, 0},
     {"kEECDH", SSL_kECDHE, ~0u, ~0u, ~0u, 0},
@@ -680,8 +649,10 @@
     {"aPSK", ~0u, SSL_aPSK, ~0u, ~0u, 0},
 
     /* aliases combining key exchange and server authentication */
+#ifdef BORINGSSL_ENABLE_DHE_TLS
     {"DHE", SSL_kDHE, ~0u, ~0u, ~0u, 0},
     {"EDH", SSL_kDHE, ~0u, ~0u, ~0u, 0},
+#endif
     {"ECDHE", SSL_kECDHE, ~0u, ~0u, ~0u, 0},
     {"EECDH", SSL_kECDHE, ~0u, ~0u, ~0u, 0},
     {"RSA", SSL_kRSA, SSL_aRSA, ~SSL_eNULL, ~0u, 0},
@@ -689,16 +660,13 @@
 
     /* symmetric encryption aliases */
     {"3DES", ~0u, ~0u, SSL_3DES, ~0u, 0},
-    {"RC4", ~0u, ~0u, SSL_RC4, ~0u, 0},
     {"AES128", ~0u, ~0u, SSL_AES128 | SSL_AES128GCM, ~0u, 0},
     {"AES256", ~0u, ~0u, SSL_AES256 | SSL_AES256GCM, ~0u, 0},
     {"AES", ~0u, ~0u, SSL_AES, ~0u, 0},
     {"AESGCM", ~0u, ~0u, SSL_AES128GCM | SSL_AES256GCM, ~0u, 0},
-    {"CHACHA20", ~0u, ~0u, SSL_CHACHA20POLY1305 | SSL_CHACHA20POLY1305_OLD, ~0u,
-     0},
+    {"CHACHA20", ~0u, ~0u, SSL_CHACHA20POLY1305, ~0u, 0},
 
     /* MAC aliases */
-    {"MD5", ~0u, ~0u, ~0u, SSL_MD5, 0},
     {"SHA1", ~0u, ~0u, ~SSL_eNULL, SSL_SHA1, 0},
     {"SHA", ~0u, ~0u, ~SSL_eNULL, SSL_SHA1, 0},
     {"SHA256", ~0u, ~0u, ~0u, SSL_SHA256, 0},
@@ -711,13 +679,11 @@
     {"TLSv1.2", ~0u, ~0u, ~SSL_eNULL, ~0u, TLS1_2_VERSION},
 
     /* Legacy strength classes. */
-    {"MEDIUM", ~0u, ~0u, SSL_RC4, ~0u, 0},
-    {"HIGH", ~0u, ~0u, ~(SSL_eNULL|SSL_RC4), ~0u, 0},
-    {"FIPS", ~0u, ~0u, ~(SSL_eNULL|SSL_RC4), ~0u, 0},
+    {"HIGH", ~0u, ~0u, ~SSL_eNULL, ~0u, 0},
+    {"FIPS", ~0u, ~0u, ~SSL_eNULL, ~0u, 0},
 };
 
-static const size_t kCipherAliasesLen =
-    sizeof(kCipherAliases) / sizeof(kCipherAliases[0]);
+static const size_t kCipherAliasesLen = OPENSSL_ARRAY_SIZE(kCipherAliases);
 
 static int ssl_cipher_id_cmp(const void *in_a, const void *in_b) {
   const SSL_CIPHER *a = in_a;
@@ -732,10 +698,6 @@
   }
 }
 
-static int ssl_cipher_ptr_id_cmp(const SSL_CIPHER **a, const SSL_CIPHER **b) {
-  return ssl_cipher_id_cmp(*a, *b);
-}
-
 const SSL_CIPHER *SSL_get_cipher_by_value(uint16_t value) {
   SSL_CIPHER c;
 
@@ -752,140 +714,96 @@
   *out_mac_secret_len = 0;
   *out_fixed_iv_len = 0;
 
-  switch (cipher->algorithm_enc) {
-    case SSL_AES128GCM:
+  if (cipher->algorithm_mac == SSL_AEAD) {
+    if (cipher->algorithm_enc == SSL_AES128GCM) {
       *out_aead = EVP_aead_aes_128_gcm();
       *out_fixed_iv_len = 4;
-      return 1;
-
-    case SSL_AES256GCM:
+    } else if (cipher->algorithm_enc == SSL_AES256GCM) {
       *out_aead = EVP_aead_aes_256_gcm();
       *out_fixed_iv_len = 4;
-      return 1;
-
-#if !defined(BORINGSSL_ANDROID_SYSTEM)
-    case SSL_CHACHA20POLY1305_OLD:
-      *out_aead = EVP_aead_chacha20_poly1305_old();
-      *out_fixed_iv_len = 0;
-      return 1;
-#endif
-
-    case SSL_CHACHA20POLY1305:
+    } else if (cipher->algorithm_enc == SSL_CHACHA20POLY1305) {
       *out_aead = EVP_aead_chacha20_poly1305();
       *out_fixed_iv_len = 12;
-      return 1;
-
-    case SSL_RC4:
-      switch (cipher->algorithm_mac) {
-        case SSL_MD5:
-          if (version == SSL3_VERSION) {
-            *out_aead = EVP_aead_rc4_md5_ssl3();
-          } else {
-            *out_aead = EVP_aead_rc4_md5_tls();
-          }
-          *out_mac_secret_len = MD5_DIGEST_LENGTH;
-          return 1;
-        case SSL_SHA1:
-          if (version == SSL3_VERSION) {
-            *out_aead = EVP_aead_rc4_sha1_ssl3();
-          } else {
-            *out_aead = EVP_aead_rc4_sha1_tls();
-          }
-          *out_mac_secret_len = SHA_DIGEST_LENGTH;
-          return 1;
-        default:
-          return 0;
-      }
-
-    case SSL_AES128:
-      switch (cipher->algorithm_mac) {
-        case SSL_SHA1:
-          if (version == SSL3_VERSION) {
-            *out_aead = EVP_aead_aes_128_cbc_sha1_ssl3();
-            *out_fixed_iv_len = 16;
-          } else if (version == TLS1_VERSION) {
-            *out_aead = EVP_aead_aes_128_cbc_sha1_tls_implicit_iv();
-            *out_fixed_iv_len = 16;
-          } else {
-            *out_aead = EVP_aead_aes_128_cbc_sha1_tls();
-          }
-          *out_mac_secret_len = SHA_DIGEST_LENGTH;
-          return 1;
-        case SSL_SHA256:
-          *out_aead = EVP_aead_aes_128_cbc_sha256_tls();
-          *out_mac_secret_len = SHA256_DIGEST_LENGTH;
-          return 1;
-        default:
-          return 0;
-      }
-
-    case SSL_AES256:
-      switch (cipher->algorithm_mac) {
-        case SSL_SHA1:
-          if (version == SSL3_VERSION) {
-            *out_aead = EVP_aead_aes_256_cbc_sha1_ssl3();
-            *out_fixed_iv_len = 16;
-          } else if (version == TLS1_VERSION) {
-            *out_aead = EVP_aead_aes_256_cbc_sha1_tls_implicit_iv();
-            *out_fixed_iv_len = 16;
-          } else {
-            *out_aead = EVP_aead_aes_256_cbc_sha1_tls();
-          }
-          *out_mac_secret_len = SHA_DIGEST_LENGTH;
-          return 1;
-        case SSL_SHA256:
-          *out_aead = EVP_aead_aes_256_cbc_sha256_tls();
-          *out_mac_secret_len = SHA256_DIGEST_LENGTH;
-          return 1;
-        case SSL_SHA384:
-          *out_aead = EVP_aead_aes_256_cbc_sha384_tls();
-          *out_mac_secret_len = SHA384_DIGEST_LENGTH;
-          return 1;
-        default:
-          return 0;
-      }
-
-    case SSL_3DES:
-      switch (cipher->algorithm_mac) {
-        case SSL_SHA1:
-          if (version == SSL3_VERSION) {
-            *out_aead = EVP_aead_des_ede3_cbc_sha1_ssl3();
-            *out_fixed_iv_len = 8;
-          } else if (version == TLS1_VERSION) {
-            *out_aead = EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv();
-            *out_fixed_iv_len = 8;
-          } else {
-            *out_aead = EVP_aead_des_ede3_cbc_sha1_tls();
-          }
-          *out_mac_secret_len = SHA_DIGEST_LENGTH;
-          return 1;
-        default:
-          return 0;
-      }
-
-    case SSL_eNULL:
-      switch (cipher->algorithm_mac) {
-        case SSL_SHA1:
-          if (version == SSL3_VERSION) {
-            *out_aead = EVP_aead_null_sha1_ssl3();
-          } else {
-            *out_aead = EVP_aead_null_sha1_tls();
-          }
-          *out_mac_secret_len = SHA_DIGEST_LENGTH;
-          return 1;
-        default:
-          return 0;
-      }
-
-    default:
+    } else {
       return 0;
+    }
+
+    /* In TLS 1.3, the iv_len is equal to the AEAD nonce length whereas the code
+     * above computes the TLS 1.2 construction. */
+    if (version >= TLS1_3_VERSION) {
+      *out_fixed_iv_len = EVP_AEAD_nonce_length(*out_aead);
+    }
+  } else if (cipher->algorithm_mac == SSL_SHA1) {
+    if (cipher->algorithm_enc == SSL_eNULL) {
+      if (version == SSL3_VERSION) {
+        *out_aead = EVP_aead_null_sha1_ssl3();
+      } else {
+        *out_aead = EVP_aead_null_sha1_tls();
+      }
+    } else if (cipher->algorithm_enc == SSL_3DES) {
+      if (version == SSL3_VERSION) {
+        *out_aead = EVP_aead_des_ede3_cbc_sha1_ssl3();
+        *out_fixed_iv_len = 8;
+      } else if (version == TLS1_VERSION) {
+        *out_aead = EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv();
+        *out_fixed_iv_len = 8;
+      } else {
+        *out_aead = EVP_aead_des_ede3_cbc_sha1_tls();
+      }
+    } else if (cipher->algorithm_enc == SSL_AES128) {
+      if (version == SSL3_VERSION) {
+        *out_aead = EVP_aead_aes_128_cbc_sha1_ssl3();
+        *out_fixed_iv_len = 16;
+      } else if (version == TLS1_VERSION) {
+        *out_aead = EVP_aead_aes_128_cbc_sha1_tls_implicit_iv();
+        *out_fixed_iv_len = 16;
+      } else {
+        *out_aead = EVP_aead_aes_128_cbc_sha1_tls();
+      }
+    } else if (cipher->algorithm_enc == SSL_AES256) {
+      if (version == SSL3_VERSION) {
+        *out_aead = EVP_aead_aes_256_cbc_sha1_ssl3();
+        *out_fixed_iv_len = 16;
+      } else if (version == TLS1_VERSION) {
+        *out_aead = EVP_aead_aes_256_cbc_sha1_tls_implicit_iv();
+        *out_fixed_iv_len = 16;
+      } else {
+        *out_aead = EVP_aead_aes_256_cbc_sha1_tls();
+      }
+    } else {
+      return 0;
+    }
+
+    *out_mac_secret_len = SHA_DIGEST_LENGTH;
+  } else if (cipher->algorithm_mac == SSL_SHA256) {
+    if (cipher->algorithm_enc == SSL_AES128) {
+      *out_aead = EVP_aead_aes_128_cbc_sha256_tls();
+    } else if (cipher->algorithm_enc == SSL_AES256) {
+      *out_aead = EVP_aead_aes_256_cbc_sha256_tls();
+    } else {
+      return 0;
+    }
+
+    *out_mac_secret_len = SHA256_DIGEST_LENGTH;
+  } else if (cipher->algorithm_mac == SSL_SHA384) {
+      if (cipher->algorithm_enc != SSL_AES256) {
+        return 0;
+      }
+
+      *out_aead = EVP_aead_aes_256_cbc_sha384_tls();
+      *out_mac_secret_len = SHA384_DIGEST_LENGTH;
+  } else {
+    return 0;
   }
+
+  return 1;
 }
 
-const EVP_MD *ssl_get_handshake_digest(uint32_t algorithm_prf) {
+const EVP_MD *ssl_get_handshake_digest(uint32_t algorithm_prf,
+                                       uint16_t version) {
   switch (algorithm_prf) {
     case SSL_HANDSHAKE_MAC_DEFAULT:
-      return EVP_sha1();
+      return version >= TLS1_2_VERSION ? EVP_sha256() : EVP_md5_sha1();
     case SSL_HANDSHAKE_MAC_SHA256:
       return EVP_sha256();
     case SSL_HANDSHAKE_MAC_SHA384:
@@ -952,10 +870,11 @@
   /* The set of ciphers is static, but some subset may be unsupported by
    * |ssl_method|, so the list may be smaller. */
   size_t co_list_num = 0;
-  size_t i;
-  for (i = 0; i < kCiphersLen; i++) {
+  for (size_t i = 0; i < kCiphersLen; i++) {
     const SSL_CIPHER *cipher = &kCiphers[i];
-    if (ssl_method->supports_cipher(cipher)) {
+    if (ssl_method->supports_cipher(cipher) &&
+        /* TLS 1.3 ciphers do not participate in this mechanism. */
+        cipher->algorithm_mkey != SSL_kGENERIC) {
       co_list[co_list_num].cipher = cipher;
       co_list[co_list_num].next = NULL;
       co_list[co_list_num].prev = NULL;
@@ -972,7 +891,7 @@
     if (co_list_num > 1) {
       co_list[0].next = &co_list[1];
 
-      for (i = 1; i < co_list_num - 1; i++) {
+      for (size_t i = 1; i < co_list_num - 1; i++) {
         co_list[i].prev = &co_list[i - 1];
         co_list[i].next = &co_list[i + 1];
       }
@@ -1051,13 +970,14 @@
       if (strength_bits != SSL_CIPHER_get_bits(cp, NULL)) {
         continue;
       }
-    } else if (!(alg_mkey & cp->algorithm_mkey) ||
-               !(alg_auth & cp->algorithm_auth) ||
-               !(alg_enc & cp->algorithm_enc) ||
-               !(alg_mac & cp->algorithm_mac) ||
-               (min_version != 0 &&
-                SSL_CIPHER_get_min_version(cp) != min_version)) {
-      continue;
+    } else {
+      if (!(alg_mkey & cp->algorithm_mkey) ||
+          !(alg_auth & cp->algorithm_auth) ||
+          !(alg_enc & cp->algorithm_enc) ||
+          !(alg_mac & cp->algorithm_mac) ||
+          (min_version != 0 && SSL_CIPHER_get_min_version(cp) != min_version)) {
+        continue;
+      }
     }
 
     /* add the cipher if it has not been added yet. */
@@ -1137,7 +1057,7 @@
     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
     return 0;
   }
-  memset(number_uses, 0, (max_strength_bits + 1) * sizeof(int));
+  OPENSSL_memset(number_uses, 0, (max_strength_bits + 1) * sizeof(int));
 
   /* Now find the strength_bits values actually used. */
   curr = *head_p;
@@ -1162,16 +1082,15 @@
 static int ssl_cipher_process_rulestr(const SSL_PROTOCOL_METHOD *ssl_method,
                                       const char *rule_str,
                                       CIPHER_ORDER **head_p,
-                                      CIPHER_ORDER **tail_p) {
+                                      CIPHER_ORDER **tail_p, int strict) {
   uint32_t alg_mkey, alg_auth, alg_enc, alg_mac;
   uint16_t min_version;
   const char *l, *buf;
-  int multi, skip_rule, rule, retval, ok, in_group = 0, has_group = 0;
+  int multi, skip_rule, rule, ok, in_group = 0, has_group = 0;
   size_t j, buf_len;
   uint32_t cipher_id;
   char ch;
 
-  retval = 1;
   l = rule_str;
   for (;;) {
     ch = *l;
@@ -1197,8 +1116,7 @@
       } else if (!(ch >= 'a' && ch <= 'z') && !(ch >= 'A' && ch <= 'Z') &&
                  !(ch >= '0' && ch <= '9')) {
         OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_OPERATOR_IN_GROUP);
-        retval = in_group = 0;
-        break;
+        return 0;
       } else {
         rule = CIPHER_ADD;
       }
@@ -1217,8 +1135,7 @@
     } else if (ch == '[') {
       if (in_group) {
         OPENSSL_PUT_ERROR(SSL, SSL_R_NESTED_GROUP);
-        retval = in_group = 0;
-        break;
+        return 0;
       }
       in_group = 1;
       has_group = 1;
@@ -1232,8 +1149,7 @@
      * Otherwise the in_group bits will get mixed up. */
     if (has_group && rule != CIPHER_ADD) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS);
-      retval = in_group = 0;
-      break;
+      return 0;
     }
 
     if (ITEM_SEP(ch)) {
@@ -1264,9 +1180,7 @@
         /* We hit something we cannot deal with, it is no command or separator
          * nor alphanumeric, so we call this an error. */
         OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_COMMAND);
-        retval = in_group = 0;
-        l++;
-        break;
+        return 0;
       }
 
       if (rule == CIPHER_SPECIAL) {
@@ -1304,6 +1218,10 @@
         }
         if (j == kCipherAliasesLen) {
           skip_rule = 1;
+          if (strict) {
+            OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_COMMAND);
+            return 0;
+          }
         }
       }
 
@@ -1315,29 +1233,6 @@
       multi = 1;
     }
 
-    /* If one of the CHACHA20_POLY1305 variants is selected, include the other
-     * as well. They have the same name to avoid requiring changes in
-     * configuration. Apply this transformation late so that the cipher name
-     * still behaves as an exact name and not an alias in multipart rules.
-     *
-     * This is temporary and will be removed when the pre-standard construction
-     * is removed. */
-    if (cipher_id == TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD ||
-        cipher_id == TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256) {
-      cipher_id = 0;
-      alg_mkey = SSL_kECDHE;
-      alg_auth = SSL_aRSA;
-      alg_enc = SSL_CHACHA20POLY1305|SSL_CHACHA20POLY1305_OLD;
-      alg_mac = SSL_AEAD;
-    } else if (cipher_id == TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD ||
-               cipher_id == TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256) {
-      cipher_id = 0;
-      alg_mkey = SSL_kECDHE;
-      alg_auth = SSL_aECDSA;
-      alg_enc = SSL_CHACHA20POLY1305|SSL_CHACHA20POLY1305_OLD;
-      alg_mac = SSL_AEAD;
-    }
-
     /* Ok, we have the rule, now apply it. */
     if (rule == CIPHER_SPECIAL) {
       /* special command */
@@ -1349,7 +1244,7 @@
       }
 
       if (ok == 0) {
-        retval = 0;
+        return 0;
       }
 
       /* We do not support any "multi" options together with "@", so throw away
@@ -1365,20 +1260,17 @@
 
   if (in_group) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_COMMAND);
-    retval = 0;
+    return 0;
   }
 
-  return retval;
+  return 1;
 }
 
-STACK_OF(SSL_CIPHER) *
-ssl_create_cipher_list(const SSL_PROTOCOL_METHOD *ssl_method,
-                       struct ssl_cipher_preference_list_st **out_cipher_list,
-                       STACK_OF(SSL_CIPHER) **out_cipher_list_by_id,
-                       const char *rule_str) {
-  int ok;
-  STACK_OF(SSL_CIPHER) *cipherstack = NULL, *tmp_cipher_list = NULL;
-  const char *rule_p;
+int ssl_create_cipher_list(
+    const SSL_PROTOCOL_METHOD *ssl_method,
+    struct ssl_cipher_preference_list_st **out_cipher_list,
+    const char *rule_str, int strict) {
+  STACK_OF(SSL_CIPHER) *cipherstack = NULL;
   CIPHER_ORDER *co_list = NULL, *head = NULL, *tail = NULL, *curr;
   uint8_t *in_group_flags = NULL;
   unsigned int num_in_group_flags = 0;
@@ -1386,16 +1278,16 @@
 
   /* Return with error if nothing to do. */
   if (rule_str == NULL || out_cipher_list == NULL) {
-    return NULL;
+    return 0;
   }
 
   /* Now we have to collect the available ciphers from the compiled in ciphers.
    * We cannot get more than the number compiled in, so it is used for
    * allocation. */
-  co_list = (CIPHER_ORDER *)OPENSSL_malloc(sizeof(CIPHER_ORDER) * kCiphersLen);
+  co_list = OPENSSL_malloc(sizeof(CIPHER_ORDER) * kCiphersLen);
   if (co_list == NULL) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-    return NULL;
+    return 0;
   }
 
   ssl_cipher_collect_ciphers(ssl_method, co_list, &head, &tail);
@@ -1403,48 +1295,40 @@
   /* Now arrange all ciphers by preference:
    * TODO(davidben): Compute this order once and copy it. */
 
-  /* Everything else being equal, prefer ECDHE_ECDSA then ECDHE_RSA over other
+  /* Everything else being equal, prefer ECDHE_ECDSA and ECDHE_RSA over other
    * key exchange mechanisms */
   ssl_cipher_apply_rule(0, SSL_kECDHE, SSL_aECDSA, ~0u, ~0u, 0, CIPHER_ADD, -1,
                         0, &head, &tail);
   ssl_cipher_apply_rule(0, SSL_kECDHE, ~0u, ~0u, ~0u, 0, CIPHER_ADD, -1, 0,
                         &head, &tail);
-  ssl_cipher_apply_rule(0, SSL_kECDHE, ~0u, ~0u, ~0u, 0, CIPHER_DEL, -1, 0,
-                        &head, &tail);
+  ssl_cipher_apply_rule(0, ~0u, ~0u, ~0u, ~0u, 0, CIPHER_DEL, -1, 0, &head,
+                        &tail);
 
   /* Order the bulk ciphers. First the preferred AEAD ciphers. We prefer
    * CHACHA20 unless there is hardware support for fast and constant-time
    * AES_GCM. Of the two CHACHA20 variants, the new one is preferred over the
    * old one. */
   if (EVP_has_aes_hardware()) {
-    ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES256GCM, ~0u, 0, CIPHER_ADD, -1, 0,
-                          &head, &tail);
     ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES128GCM, ~0u, 0, CIPHER_ADD, -1, 0,
                           &head, &tail);
+    ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES256GCM, ~0u, 0, CIPHER_ADD, -1, 0,
+                          &head, &tail);
     ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_CHACHA20POLY1305, ~0u, 0, CIPHER_ADD,
                           -1, 0, &head, &tail);
-    ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_CHACHA20POLY1305_OLD, ~0u, 0,
-                          CIPHER_ADD, -1, 0, &head, &tail);
   } else {
     ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_CHACHA20POLY1305, ~0u, 0, CIPHER_ADD,
                           -1, 0, &head, &tail);
-    ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_CHACHA20POLY1305_OLD, ~0u, 0,
-                          CIPHER_ADD, -1, 0, &head, &tail);
-    ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES256GCM, ~0u, 0, CIPHER_ADD, -1, 0,
-                          &head, &tail);
     ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES128GCM, ~0u, 0, CIPHER_ADD, -1, 0,
                           &head, &tail);
+    ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES256GCM, ~0u, 0, CIPHER_ADD, -1, 0,
+                          &head, &tail);
   }
 
-  /* Then the legacy non-AEAD ciphers: AES_256_CBC, AES-128_CBC, RC4_128_SHA,
-   * RC4_128_MD5, 3DES_EDE_CBC_SHA. */
-  ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES256, ~0u, 0, CIPHER_ADD, -1, 0,
-                        &head, &tail);
+  /* Then the legacy non-AEAD ciphers: AES_128_CBC, AES_256_CBC,
+   * 3DES_EDE_CBC_SHA. */
   ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES128, ~0u, 0, CIPHER_ADD, -1, 0,
                         &head, &tail);
-  ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_RC4, ~SSL_MD5, 0, CIPHER_ADD, -1, 0,
-                        &head, &tail);
-  ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_RC4, SSL_MD5, 0, CIPHER_ADD, -1, 0,
+  ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_AES256, ~0u, 0, CIPHER_ADD, -1, 0,
                         &head, &tail);
   ssl_cipher_apply_rule(0, ~0u, ~0u, SSL_3DES, ~0u, 0, CIPHER_ADD, -1, 0, &head,
                         &tail);
@@ -1454,7 +1338,7 @@
                         &tail);
 
   /* Move ciphers without forward secrecy to the end. */
-  ssl_cipher_apply_rule(0, ~(SSL_kDHE | SSL_kECDHE), ~0u, ~0u, ~0u, 0,
+  ssl_cipher_apply_rule(0, (SSL_kRSA | SSL_kPSK), ~0u, ~0u, ~0u, 0,
                         CIPHER_ORD, -1, 0, &head, &tail);
 
   /* Now disable everything (maintaining the ordering!) */
@@ -1463,22 +1347,20 @@
 
   /* If the rule_string begins with DEFAULT, apply the default rule before
    * using the (possibly available) additional rules. */
-  ok = 1;
-  rule_p = rule_str;
+  const char *rule_p = rule_str;
   if (strncmp(rule_str, "DEFAULT", 7) == 0) {
-    ok = ssl_cipher_process_rulestr(ssl_method, SSL_DEFAULT_CIPHER_LIST, &head,
-                                    &tail);
+    if (!ssl_cipher_process_rulestr(ssl_method, SSL_DEFAULT_CIPHER_LIST, &head,
+                                    &tail, strict)) {
+      goto err;
+    }
     rule_p += 7;
     if (*rule_p == ':') {
       rule_p++;
     }
   }
 
-  if (ok && strlen(rule_p) > 0) {
-    ok = ssl_cipher_process_rulestr(ssl_method, rule_p, &head, &tail);
-  }
-
-  if (!ok) {
+  if (*rule_p != '\0' &&
+      !ssl_cipher_process_rulestr(ssl_method, rule_p, &head, &tail, strict)) {
     goto err;
   }
 
@@ -1507,10 +1389,6 @@
   OPENSSL_free(co_list); /* Not needed any longer */
   co_list = NULL;
 
-  tmp_cipher_list = sk_SSL_CIPHER_dup(cipherstack);
-  if (tmp_cipher_list == NULL) {
-    goto err;
-  }
   pref_list = OPENSSL_malloc(sizeof(struct ssl_cipher_preference_list_st));
   if (!pref_list) {
     goto err;
@@ -1520,7 +1398,7 @@
   if (!pref_list->in_group_flags) {
     goto err;
   }
-  memcpy(pref_list->in_group_flags, in_group_flags, num_in_group_flags);
+  OPENSSL_memcpy(pref_list->in_group_flags, in_group_flags, num_in_group_flags);
   OPENSSL_free(in_group_flags);
   in_group_flags = NULL;
   if (*out_cipher_list != NULL) {
@@ -1529,31 +1407,24 @@
   *out_cipher_list = pref_list;
   pref_list = NULL;
 
-  if (out_cipher_list_by_id != NULL) {
-    sk_SSL_CIPHER_free(*out_cipher_list_by_id);
-    *out_cipher_list_by_id = tmp_cipher_list;
-    tmp_cipher_list = NULL;
-    (void) sk_SSL_CIPHER_set_cmp_func(*out_cipher_list_by_id,
-                                      ssl_cipher_ptr_id_cmp);
-
-    sk_SSL_CIPHER_sort(*out_cipher_list_by_id);
-  } else {
-    sk_SSL_CIPHER_free(tmp_cipher_list);
-    tmp_cipher_list = NULL;
+  /* Configuring an empty cipher list is an error but still updates the
+   * output. */
+  if (sk_SSL_CIPHER_num((*out_cipher_list)->ciphers) == 0) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CIPHER_MATCH);
+    return 0;
   }
 
-  return cipherstack;
+  return 1;
 
 err:
   OPENSSL_free(co_list);
   OPENSSL_free(in_group_flags);
   sk_SSL_CIPHER_free(cipherstack);
-  sk_SSL_CIPHER_free(tmp_cipher_list);
   if (pref_list) {
     OPENSSL_free(pref_list->in_group_flags);
   }
   OPENSSL_free(pref_list);
-  return NULL;
+  return 0;
 }
 
 uint32_t SSL_CIPHER_get_id(const SSL_CIPHER *cipher) { return cipher->id; }
@@ -1569,14 +1440,18 @@
   return (cipher->algorithm_enc & SSL_AES) != 0;
 }
 
-int SSL_CIPHER_has_MD5_HMAC(const SSL_CIPHER *cipher) {
-  return (cipher->algorithm_mac & SSL_MD5) != 0;
-}
-
 int SSL_CIPHER_has_SHA1_HMAC(const SSL_CIPHER *cipher) {
   return (cipher->algorithm_mac & SSL_SHA1) != 0;
 }
 
+int SSL_CIPHER_has_SHA256_HMAC(const SSL_CIPHER *cipher) {
+  return (cipher->algorithm_mac & SSL_SHA256) != 0;
+}
+
+int SSL_CIPHER_is_AEAD(const SSL_CIPHER *cipher) {
+  return (cipher->algorithm_mac & SSL_AEAD) != 0;
+}
+
 int SSL_CIPHER_is_AESGCM(const SSL_CIPHER *cipher) {
   return (cipher->algorithm_enc & (SSL_AES128GCM | SSL_AES256GCM)) != 0;
 }
@@ -1594,21 +1469,15 @@
 }
 
 int SSL_CIPHER_is_CHACHA20POLY1305(const SSL_CIPHER *cipher) {
-  return (cipher->algorithm_enc &
-          (SSL_CHACHA20POLY1305 | SSL_CHACHA20POLY1305_OLD)) != 0;
+  return (cipher->algorithm_enc & SSL_CHACHA20POLY1305) != 0;
 }
 
 int SSL_CIPHER_is_NULL(const SSL_CIPHER *cipher) {
   return (cipher->algorithm_enc & SSL_eNULL) != 0;
 }
 
-int SSL_CIPHER_is_RC4(const SSL_CIPHER *cipher) {
-  return (cipher->algorithm_enc & SSL_RC4) != 0;
-}
-
 int SSL_CIPHER_is_block_cipher(const SSL_CIPHER *cipher) {
-  /* Neither stream cipher nor AEAD. */
-  return (cipher->algorithm_enc & (SSL_RC4 | SSL_eNULL)) == 0 &&
+  return (cipher->algorithm_enc & SSL_eNULL) == 0 &&
       cipher->algorithm_mac != SSL_AEAD;
 }
 
@@ -1616,11 +1485,24 @@
   return (cipher->algorithm_auth & SSL_aECDSA) != 0;
 }
 
+int SSL_CIPHER_is_DHE(const SSL_CIPHER *cipher) {
+  return (cipher->algorithm_mkey & SSL_kDHE) != 0;
+}
+
 int SSL_CIPHER_is_ECDHE(const SSL_CIPHER *cipher) {
   return (cipher->algorithm_mkey & SSL_kECDHE) != 0;
 }
 
+int SSL_CIPHER_is_static_RSA(const SSL_CIPHER *cipher) {
+  return (cipher->algorithm_mkey & SSL_kRSA) != 0;
+}
+
 uint16_t SSL_CIPHER_get_min_version(const SSL_CIPHER *cipher) {
+  if (cipher->algorithm_mkey == SSL_kGENERIC ||
+      cipher->algorithm_auth == SSL_aGENERIC) {
+    return TLS1_3_VERSION;
+  }
+
   if (cipher->algorithm_prf != SSL_HANDSHAKE_MAC_DEFAULT) {
     /* Cipher suites before TLS 1.2 use the default PRF, while all those added
      * afterwards specify a particular hash. */
@@ -1629,6 +1511,14 @@
   return SSL3_VERSION;
 }
 
+uint16_t SSL_CIPHER_get_max_version(const SSL_CIPHER *cipher) {
+  if (cipher->algorithm_mkey == SSL_kGENERIC ||
+      cipher->algorithm_auth == SSL_aGENERIC) {
+    return TLS1_3_VERSION;
+  }
+  return TLS1_2_VERSION;
+}
+
 /* return the actual cipher being used */
 const char *SSL_CIPHER_get_name(const SSL_CIPHER *cipher) {
   if (cipher != NULL) {
@@ -1673,6 +1563,10 @@
       assert(cipher->algorithm_auth == SSL_aPSK);
       return "PSK";
 
+    case SSL_kGENERIC:
+      assert(cipher->algorithm_auth == SSL_aGENERIC);
+      return "GENERIC";
+
     default:
       assert(0);
       return "UNKNOWN";
@@ -1683,8 +1577,6 @@
   switch (cipher->algorithm_enc) {
     case SSL_3DES:
       return "3DES_EDE_CBC";
-    case SSL_RC4:
-      return "RC4";
     case SSL_AES128:
       return "AES_128_CBC";
     case SSL_AES256:
@@ -1694,7 +1586,6 @@
     case SSL_AES256GCM:
       return "AES_256_GCM";
     case SSL_CHACHA20POLY1305:
-    case SSL_CHACHA20POLY1305_OLD:
       return "CHACHA20_POLY1305";
       break;
     default:
@@ -1706,15 +1597,10 @@
 static const char *ssl_cipher_get_prf_name(const SSL_CIPHER *cipher) {
   switch (cipher->algorithm_prf) {
     case SSL_HANDSHAKE_MAC_DEFAULT:
-      /* Before TLS 1.2, the PRF component is the hash used in the HMAC, which is
-       * only ever MD5 or SHA-1. */
-      switch (cipher->algorithm_mac) {
-        case SSL_MD5:
-          return "MD5";
-        case SSL_SHA1:
-          return "SHA";
-      }
-      break;
+      /* Before TLS 1.2, the PRF component is the hash used in the HMAC, which
+       * is SHA-1 for all supported ciphers. */
+      assert(cipher->algorithm_mac == SSL_SHA1);
+      return "SHA";
     case SSL_HANDSHAKE_MAC_SHA256:
       return "SHA256";
     case SSL_HANDSHAKE_MAC_SHA384:
@@ -1733,16 +1619,23 @@
   const char *enc_name = ssl_cipher_get_enc_name(cipher);
   const char *prf_name = ssl_cipher_get_prf_name(cipher);
 
-  /* The final name is TLS_{kx_name}_WITH_{enc_name}_{prf_name}. */
-  size_t len = 4 + strlen(kx_name) + 6 + strlen(enc_name) + 1 +
-      strlen(prf_name) + 1;
+  /* The final name is TLS_{kx_name}_WITH_{enc_name}_{prf_name} or
+   * TLS_{enc_name}_{prf_name} depending on whether the cipher is AEAD-only. */
+  size_t len = 4 + strlen(enc_name) + 1 + strlen(prf_name) + 1;
+
+  if (cipher->algorithm_mkey != SSL_kGENERIC) {
+    len += strlen(kx_name) + 6;
+  }
+
   char *ret = OPENSSL_malloc(len);
   if (ret == NULL) {
     return NULL;
   }
+
   if (BUF_strlcpy(ret, "TLS_", len) >= len ||
-      BUF_strlcat(ret, kx_name, len) >= len ||
-      BUF_strlcat(ret, "_WITH_", len) >= len ||
+      (cipher->algorithm_mkey != SSL_kGENERIC &&
+       (BUF_strlcat(ret, kx_name, len) >= len ||
+        BUF_strlcat(ret, "_WITH_", len) >= len)) ||
       BUF_strlcat(ret, enc_name, len) >= len ||
       BUF_strlcat(ret, "_", len) >= len ||
       BUF_strlcat(ret, prf_name, len) >= len) {
@@ -1750,6 +1643,7 @@
     OPENSSL_free(ret);
     return NULL;
   }
+
   assert(strlen(ret) + 1 == len);
   return ret;
 }
@@ -1763,16 +1657,12 @@
   switch (cipher->algorithm_enc) {
     case SSL_AES128:
     case SSL_AES128GCM:
-    case SSL_RC4:
       alg_bits = 128;
       strength_bits = 128;
       break;
 
     case SSL_AES256:
     case SSL_AES256GCM:
-#if !defined(BORINGSSL_ANDROID_SYSTEM)
-    case SSL_CHACHA20POLY1305_OLD:
-#endif
     case SSL_CHACHA20POLY1305:
       alg_bits = 256;
       strength_bits = 256;
@@ -1804,7 +1694,6 @@
                                    int len) {
   const char *kx, *au, *enc, *mac;
   uint32_t alg_mkey, alg_auth, alg_enc, alg_mac;
-  static const char *format = "%-23s Kx=%-8s Au=%-4s Enc=%-9s Mac=%-4s\n";
 
   alg_mkey = cipher->algorithm_mkey;
   alg_auth = cipher->algorithm_auth;
@@ -1828,6 +1717,10 @@
       kx = "PSK";
       break;
 
+    case SSL_kGENERIC:
+      kx = "GENERIC";
+      break;
+
     default:
       kx = "unknown";
   }
@@ -1845,6 +1738,10 @@
       au = "PSK";
       break;
 
+    case SSL_aGENERIC:
+      au = "GENERIC";
+      break;
+
     default:
       au = "unknown";
       break;
@@ -1855,10 +1752,6 @@
       enc = "3DES(168)";
       break;
 
-    case SSL_RC4:
-      enc = "RC4(128)";
-      break;
-
     case SSL_AES128:
       enc = "AES(128)";
       break;
@@ -1875,10 +1768,6 @@
       enc = "AESGCM(256)";
       break;
 
-    case SSL_CHACHA20POLY1305_OLD:
-      enc = "ChaCha20-Poly1305-Old";
-      break;
-
     case SSL_CHACHA20POLY1305:
       enc = "ChaCha20-Poly1305";
       break;
@@ -1893,10 +1782,6 @@
   }
 
   switch (alg_mac) {
-    case SSL_MD5:
-      mac = "MD5";
-      break;
-
     case SSL_SHA1:
       mac = "SHA1";
       break;
@@ -1928,7 +1813,8 @@
     return "Buffer too small";
   }
 
-  BIO_snprintf(buf, len, format, cipher->name, kx, au, enc, mac);
+  BIO_snprintf(buf, len, "%-23s Kx=%-8s Au=%-4s Enc=%-9s Mac=%-4s\n",
+               cipher->name, kx, au, enc, mac);
   return buf;
 }
 
@@ -1942,6 +1828,8 @@
 
 const char *SSL_COMP_get_name(const COMP_METHOD *comp) { return NULL; }
 
+void SSL_COMP_free_compression_methods(void) {}
+
 int ssl_cipher_get_key_type(const SSL_CIPHER *cipher) {
   uint32_t alg_a = cipher->algorithm_auth;
 
@@ -1954,20 +1842,14 @@
   return EVP_PKEY_NONE;
 }
 
-int ssl_cipher_has_server_public_key(const SSL_CIPHER *cipher) {
-  /* PSK-authenticated ciphers do not use a certificate. (RSA_PSK is not
-   * supported.) */
-  if (cipher->algorithm_auth & SSL_aPSK) {
-    return 0;
-  }
-
-  /* All other ciphers include it. */
-  return 1;
+int ssl_cipher_uses_certificate_auth(const SSL_CIPHER *cipher) {
+  return (cipher->algorithm_auth & SSL_aCERT) != 0;
 }
 
 int ssl_cipher_requires_server_key_exchange(const SSL_CIPHER *cipher) {
   /* Ephemeral Diffie-Hellman key exchanges require a ServerKeyExchange. */
-  if (cipher->algorithm_mkey & SSL_kDHE || cipher->algorithm_mkey & SSL_kECDHE) {
+  if (cipher->algorithm_mkey & SSL_kDHE ||
+      cipher->algorithm_mkey & SSL_kECDHE) {
     return 1;
   }
 
@@ -1989,19 +1871,9 @@
       return 0;
   }
 
-  size_t mac_len;
-  switch (cipher->algorithm_mac) {
-    case SSL_MD5:
-      mac_len = MD5_DIGEST_LENGTH;
-      break;
-    case SSL_SHA1:
-      mac_len = SHA_DIGEST_LENGTH;
-      break;
-    default:
-      return 0;
-  }
-
-  size_t ret = 1 + mac_len;
+  /* All supported TLS 1.0 ciphers use SHA-1. */
+  assert(cipher->algorithm_mac == SSL_SHA1);
+  size_t ret = 1 + SHA_DIGEST_LENGTH;
   ret += block_size - (ret % block_size);
   return ret;
 }
diff --git a/src/ssl/ssl_ecdh.c b/src/ssl/ssl_ecdh.c
index 45c5b26..f49d566 100644
--- a/src/ssl/ssl_ecdh.c
+++ b/src/ssl/ssl_ecdh.c
@@ -23,9 +23,10 @@
 #include <openssl/ec.h>
 #include <openssl/err.h>
 #include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
 
 #include "internal.h"
+#include "../crypto/internal.h"
 
 
 /* |EC_POINT| implementation. */
@@ -35,7 +36,7 @@
   BN_clear_free(private_key);
 }
 
-static int ssl_ec_point_generate_keypair(SSL_ECDH_CTX *ctx, CBB *out) {
+static int ssl_ec_point_offer(SSL_ECDH_CTX *ctx, CBB *out) {
   assert(ctx->data == NULL);
   BIGNUM *private_key = BN_new();
   if (private_key == NULL) {
@@ -58,28 +59,16 @@
   }
 
   /* Generate a private key. */
-  const BIGNUM *order = EC_GROUP_get0_order(group);
-  do {
-    if (!BN_rand_range(private_key, order)) {
-      goto err;
-    }
-  } while (BN_is_zero(private_key));
-
-  /* Compute the corresponding public key. */
-  public_key = EC_POINT_new(group);
-  if (public_key == NULL ||
-      !EC_POINT_mul(group, public_key, private_key, NULL, NULL, bn_ctx)) {
+  if (!BN_rand_range_ex(private_key, 1, EC_GROUP_get0_order(group))) {
     goto err;
   }
 
-  /* Serialize the public key. */
-  size_t len = EC_POINT_point2oct(
-      group, public_key, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, bn_ctx);
-  uint8_t *ptr;
-  if (len == 0 ||
-      !CBB_add_space(out, &ptr, len) ||
-      EC_POINT_point2oct(group, public_key, POINT_CONVERSION_UNCOMPRESSED, ptr,
-                         len, bn_ctx) != len) {
+  /* Compute the corresponding public key and serialize it. */
+  public_key = EC_POINT_new(group);
+  if (public_key == NULL ||
+      !EC_POINT_mul(group, public_key, private_key, NULL, NULL, bn_ctx) ||
+      !EC_POINT_point2cbb(out, group, public_key, POINT_CONVERSION_UNCOMPRESSED,
+                          bn_ctx)) {
     goto err;
   }
 
@@ -93,9 +82,9 @@
   return ret;
 }
 
-int ssl_ec_point_compute_secret(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
-                                size_t *out_secret_len, uint8_t *out_alert,
-                                const uint8_t *peer_key, size_t peer_key_len) {
+static int ssl_ec_point_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
+                               size_t *out_secret_len, uint8_t *out_alert,
+                               const uint8_t *peer_key, size_t peer_key_len) {
   BIGNUM *private_key = (BIGNUM *)ctx->data;
   assert(private_key != NULL);
   *out_alert = SSL_AD_INTERNAL_ERROR;
@@ -156,6 +145,18 @@
   return ret;
 }
 
+static int ssl_ec_point_accept(SSL_ECDH_CTX *ctx, CBB *out_public_key,
+                               uint8_t **out_secret, size_t *out_secret_len,
+                               uint8_t *out_alert, const uint8_t *peer_key,
+                               size_t peer_key_len) {
+  *out_alert = SSL_AD_INTERNAL_ERROR;
+  if (!ssl_ec_point_offer(ctx, out_public_key) ||
+      !ssl_ec_point_finish(ctx, out_secret, out_secret_len, out_alert, peer_key,
+                           peer_key_len)) {
+    return 0;
+  }
+  return 1;
+}
 
 /* X25119 implementation. */
 
@@ -167,7 +168,7 @@
   OPENSSL_free(ctx->data);
 }
 
-static int ssl_x25519_generate_keypair(SSL_ECDH_CTX *ctx, CBB *out) {
+static int ssl_x25519_offer(SSL_ECDH_CTX *ctx, CBB *out) {
   assert(ctx->data == NULL);
 
   ctx->data = OPENSSL_malloc(32);
@@ -180,10 +181,9 @@
   return CBB_add_bytes(out, public_key, sizeof(public_key));
 }
 
-static int ssl_x25519_compute_secret(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
-                                     size_t *out_secret_len, uint8_t *out_alert,
-                                     const uint8_t *peer_key,
-                                     size_t peer_key_len) {
+static int ssl_x25519_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
+                             size_t *out_secret_len, uint8_t *out_alert,
+                             const uint8_t *peer_key, size_t peer_key_len) {
   assert(ctx->data != NULL);
   *out_alert = SSL_AD_INTERNAL_ERROR;
 
@@ -205,6 +205,19 @@
   return 1;
 }
 
+static int ssl_x25519_accept(SSL_ECDH_CTX *ctx, CBB *out_public_key,
+                             uint8_t **out_secret, size_t *out_secret_len,
+                             uint8_t *out_alert, const uint8_t *peer_key,
+                             size_t peer_key_len) {
+  *out_alert = SSL_AD_INTERNAL_ERROR;
+  if (!ssl_x25519_offer(ctx, out_public_key) ||
+      !ssl_x25519_finish(ctx, out_secret, out_secret_len, out_alert, peer_key,
+                         peer_key_len)) {
+    return 0;
+  }
+  return 1;
+}
+
 
 /* Legacy DHE-based implementation. */
 
@@ -212,7 +225,7 @@
   DH_free((DH *)ctx->data);
 }
 
-static int ssl_dhe_generate_keypair(SSL_ECDH_CTX *ctx, CBB *out) {
+static int ssl_dhe_offer(SSL_ECDH_CTX *ctx, CBB *out) {
   DH *dh = (DH *)ctx->data;
   /* The group must have been initialized already, but not the key. */
   assert(dh != NULL);
@@ -224,10 +237,9 @@
          BN_bn2cbb_padded(out, BN_num_bytes(dh->p), dh->pub_key);
 }
 
-static int ssl_dhe_compute_secret(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
-                                  size_t *out_secret_len, uint8_t *out_alert,
-                                  const uint8_t *peer_key,
-                                  size_t peer_key_len) {
+static int ssl_dhe_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
+                          size_t *out_secret_len, uint8_t *out_alert,
+                          const uint8_t *peer_key, size_t peer_key_len) {
   DH *dh = (DH *)ctx->data;
   assert(dh != NULL);
   assert(dh->priv_key != NULL);
@@ -263,53 +275,79 @@
   return 0;
 }
 
+static int ssl_dhe_accept(SSL_ECDH_CTX *ctx, CBB *out_public_key,
+                          uint8_t **out_secret, size_t *out_secret_len,
+                          uint8_t *out_alert, const uint8_t *peer_key,
+                          size_t peer_key_len) {
+  *out_alert = SSL_AD_INTERNAL_ERROR;
+  if (!ssl_dhe_offer(ctx, out_public_key) ||
+      !ssl_dhe_finish(ctx, out_secret, out_secret_len, out_alert, peer_key,
+                      peer_key_len)) {
+    return 0;
+  }
+  return 1;
+}
+
 static const SSL_ECDH_METHOD kDHEMethod = {
     NID_undef, 0, "",
     ssl_dhe_cleanup,
-    ssl_dhe_generate_keypair,
-    ssl_dhe_compute_secret,
+    ssl_dhe_offer,
+    ssl_dhe_accept,
+    ssl_dhe_finish,
+    CBS_get_u16_length_prefixed,
+    CBB_add_u16_length_prefixed,
 };
 
-
 static const SSL_ECDH_METHOD kMethods[] = {
     {
         NID_X9_62_prime256v1,
         SSL_CURVE_SECP256R1,
         "P-256",
         ssl_ec_point_cleanup,
-        ssl_ec_point_generate_keypair,
-        ssl_ec_point_compute_secret,
+        ssl_ec_point_offer,
+        ssl_ec_point_accept,
+        ssl_ec_point_finish,
+        CBS_get_u8_length_prefixed,
+        CBB_add_u8_length_prefixed,
     },
     {
         NID_secp384r1,
         SSL_CURVE_SECP384R1,
         "P-384",
         ssl_ec_point_cleanup,
-        ssl_ec_point_generate_keypair,
-        ssl_ec_point_compute_secret,
+        ssl_ec_point_offer,
+        ssl_ec_point_accept,
+        ssl_ec_point_finish,
+        CBS_get_u8_length_prefixed,
+        CBB_add_u8_length_prefixed,
     },
     {
         NID_secp521r1,
         SSL_CURVE_SECP521R1,
         "P-521",
         ssl_ec_point_cleanup,
-        ssl_ec_point_generate_keypair,
-        ssl_ec_point_compute_secret,
+        ssl_ec_point_offer,
+        ssl_ec_point_accept,
+        ssl_ec_point_finish,
+        CBS_get_u8_length_prefixed,
+        CBB_add_u8_length_prefixed,
     },
     {
-        NID_x25519,
-        SSL_CURVE_ECDH_X25519,
+        NID_X25519,
+        SSL_CURVE_X25519,
         "X25519",
         ssl_x25519_cleanup,
-        ssl_x25519_generate_keypair,
-        ssl_x25519_compute_secret,
+        ssl_x25519_offer,
+        ssl_x25519_accept,
+        ssl_x25519_finish,
+        CBS_get_u8_length_prefixed,
+        CBB_add_u8_length_prefixed,
     },
 };
 
-static const SSL_ECDH_METHOD *method_from_curve_id(uint16_t curve_id) {
-  size_t i;
-  for (i = 0; i < sizeof(kMethods) / sizeof(kMethods[0]); i++) {
-    if (kMethods[i].curve_id == curve_id) {
+static const SSL_ECDH_METHOD *method_from_group_id(uint16_t group_id) {
+  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kMethods); i++) {
+    if (kMethods[i].group_id == group_id) {
       return &kMethods[i];
     }
   }
@@ -317,8 +355,7 @@
 }
 
 static const SSL_ECDH_METHOD *method_from_nid(int nid) {
-  size_t i;
-  for (i = 0; i < sizeof(kMethods) / sizeof(kMethods[0]); i++) {
+  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kMethods); i++) {
     if (kMethods[i].nid == nid) {
       return &kMethods[i];
     }
@@ -326,27 +363,46 @@
   return NULL;
 }
 
-const char* SSL_get_curve_name(uint16_t curve_id) {
-  const SSL_ECDH_METHOD *method = method_from_curve_id(curve_id);
+static const SSL_ECDH_METHOD *method_from_name(const char *name, size_t len) {
+  for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kMethods); i++) {
+    if (len == strlen(kMethods[i].name) &&
+        !strncmp(kMethods[i].name, name, len)) {
+      return &kMethods[i];
+    }
+  }
+  return NULL;
+}
+
+const char* SSL_get_curve_name(uint16_t group_id) {
+  const SSL_ECDH_METHOD *method = method_from_group_id(group_id);
   if (method == NULL) {
     return NULL;
   }
   return method->name;
 }
 
-int ssl_nid_to_curve_id(uint16_t *out_curve_id, int nid) {
+int ssl_nid_to_group_id(uint16_t *out_group_id, int nid) {
   const SSL_ECDH_METHOD *method = method_from_nid(nid);
   if (method == NULL) {
     return 0;
   }
-  *out_curve_id = method->curve_id;
+  *out_group_id = method->group_id;
   return 1;
 }
 
-int SSL_ECDH_CTX_init(SSL_ECDH_CTX *ctx, uint16_t curve_id) {
+int ssl_name_to_group_id(uint16_t *out_group_id, const char *name, size_t len) {
+  const SSL_ECDH_METHOD *method = method_from_name(name, len);
+  if (method == NULL) {
+    return 0;
+  }
+  *out_group_id = method->group_id;
+  return 1;
+}
+
+int SSL_ECDH_CTX_init(SSL_ECDH_CTX *ctx, uint16_t group_id) {
   SSL_ECDH_CTX_cleanup(ctx);
 
-  const SSL_ECDH_METHOD *method = method_from_curve_id(curve_id);
+  const SSL_ECDH_METHOD *method = method_from_group_id(group_id);
   if (method == NULL) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_ELLIPTIC_CURVE);
     return 0;
@@ -371,13 +427,39 @@
   ctx->data = NULL;
 }
 
-int SSL_ECDH_CTX_generate_keypair(SSL_ECDH_CTX *ctx, CBB *out_public_key) {
-  return ctx->method->generate_keypair(ctx, out_public_key);
+uint16_t SSL_ECDH_CTX_get_id(const SSL_ECDH_CTX *ctx) {
+  return ctx->method->group_id;
 }
 
-int SSL_ECDH_CTX_compute_secret(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
-                                size_t *out_secret_len, uint8_t *out_alert,
-                                const uint8_t *peer_key, size_t peer_key_len) {
-  return ctx->method->compute_secret(ctx, out_secret, out_secret_len, out_alert,
-                                     peer_key, peer_key_len);
+int SSL_ECDH_CTX_get_key(SSL_ECDH_CTX *ctx, CBS *cbs, CBS *out) {
+  if (ctx->method == NULL) {
+    return 0;
+  }
+  return ctx->method->get_key(cbs, out);
+}
+
+int SSL_ECDH_CTX_add_key(SSL_ECDH_CTX *ctx, CBB *cbb, CBB *out_contents) {
+  if (ctx->method == NULL) {
+    return 0;
+  }
+  return ctx->method->add_key(cbb, out_contents);
+}
+
+int SSL_ECDH_CTX_offer(SSL_ECDH_CTX *ctx, CBB *out_public_key) {
+  return ctx->method->offer(ctx, out_public_key);
+}
+
+int SSL_ECDH_CTX_accept(SSL_ECDH_CTX *ctx, CBB *out_public_key,
+                        uint8_t **out_secret, size_t *out_secret_len,
+                        uint8_t *out_alert, const uint8_t *peer_key,
+                        size_t peer_key_len) {
+  return ctx->method->accept(ctx, out_public_key, out_secret, out_secret_len,
+                             out_alert, peer_key, peer_key_len);
+}
+
+int SSL_ECDH_CTX_finish(SSL_ECDH_CTX *ctx, uint8_t **out_secret,
+                        size_t *out_secret_len, uint8_t *out_alert,
+                        const uint8_t *peer_key, size_t peer_key_len) {
+  return ctx->method->finish(ctx, out_secret, out_secret_len, out_alert,
+                             peer_key, peer_key_len);
 }
diff --git a/src/ssl/ssl_file.c b/src/ssl/ssl_file.c
index 42cf800..59351a3 100644
--- a/src/ssl/ssl_file.c
+++ b/src/ssl/ssl_file.c
@@ -121,7 +121,6 @@
 #include <openssl/stack.h>
 #include <openssl/x509.h>
 
-#include "../crypto/directory.h"
 #include "internal.h"
 
 
@@ -165,16 +164,17 @@
       goto err;
     }
 
-    /* check for duplicates */
-    xn = X509_NAME_dup(xn);
-    if (xn == NULL) {
-      goto err;
-    }
+    /* Check for duplicates. */
     if (sk_X509_NAME_find(sk, NULL, xn)) {
+      continue;
+    }
+
+    xn = X509_NAME_dup(xn);
+    if (xn == NULL ||
+        !sk_X509_NAME_push(sk /* non-owning */, xn) ||
+        !sk_X509_NAME_push(ret /* owning */, xn)) {
       X509_NAME_free(xn);
-    } else {
-      sk_X509_NAME_push(sk, xn);
-      sk_X509_NAME_push(ret, xn);
+      goto err;
     }
   }
 
@@ -198,7 +198,7 @@
   BIO *in;
   X509 *x = NULL;
   X509_NAME *xn = NULL;
-  int ret = 1;
+  int ret = 0;
   int (*oldcmp)(const X509_NAME **a, const X509_NAME **b);
 
   oldcmp = sk_X509_NAME_set_cmp_func(stack, xname_cmp);
@@ -221,24 +221,24 @@
     if (xn == NULL) {
       goto err;
     }
-    xn = X509_NAME_dup(xn);
-    if (xn == NULL) {
-      goto err;
-    }
+
+    /* Check for duplicates. */
     if (sk_X509_NAME_find(stack, NULL, xn)) {
+      continue;
+    }
+
+    xn = X509_NAME_dup(xn);
+    if (xn == NULL ||
+        !sk_X509_NAME_push(stack, xn)) {
       X509_NAME_free(xn);
-    } else {
-      sk_X509_NAME_push(stack, xn);
+      goto err;
     }
   }
 
   ERR_clear_error();
+  ret = 1;
 
-  if (0) {
-  err:
-    ret = 0;
-  }
-
+err:
   BIO_free(in);
   X509_free(x);
 
@@ -247,53 +247,6 @@
   return ret;
 }
 
-/* Add a directory of certs to a stack.
- *
- * \param stack the stack to append to.
- * \param dir the directory to append from. All files in this directory will be
- *     examined as potential certs. Any that are acceptable to
- *     SSL_add_dir_cert_subjects_to_stack() that are not already in the stack will
- *     be included.
- * \return 1 for success, 0 for failure. Note that in the case of failure some
- *     certs may have been added to \c stack. */
-int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stack,
-                                       const char *dir) {
-  OPENSSL_DIR_CTX *d = NULL;
-  const char *filename;
-  int ret = 0;
-
-  /* Note that a side effect is that the CAs will be sorted by name */
-  while ((filename = OPENSSL_DIR_read(&d, dir))) {
-    char buf[1024];
-    int r;
-
-    if (strlen(dir) + strlen(filename) + 2 > sizeof(buf)) {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_PATH_TOO_LONG);
-      goto err;
-    }
-
-    r = BIO_snprintf(buf, sizeof buf, "%s/%s", dir, filename);
-    if (r <= 0 || r >= (int)sizeof(buf) ||
-        !SSL_add_file_cert_subjects_to_stack(stack, buf)) {
-      goto err;
-    }
-  }
-
-  if (errno) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_SYS_LIB);
-    ERR_add_error_data(3, "OPENSSL_DIR_read(&ctx, '", dir, "')");
-    goto err;
-  }
-
-  ret = 1;
-
-err:
-  if (d) {
-    OPENSSL_DIR_end(&d);
-  }
-  return ret;
-}
-
 int SSL_use_certificate_file(SSL *ssl, const char *file, int type) {
   int reason_code;
   BIO *in;
@@ -620,14 +573,3 @@
 void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *data) {
   ctx->default_passwd_callback_userdata = data;
 }
-
-SSL_SESSION *d2i_SSL_SESSION_bio(BIO *bio, SSL_SESSION **out) {
-  return ASN1_d2i_bio_of(SSL_SESSION, SSL_SESSION_new, d2i_SSL_SESSION, bio,
-                         out);
-}
-
-int i2d_SSL_SESSION_bio(BIO *bio, const SSL_SESSION *session) {
-  return ASN1_i2d_bio_of(SSL_SESSION, i2d_SSL_SESSION, bio, session);
-}
-
-IMPLEMENT_PEM_rw(SSL_SESSION, SSL_SESSION, PEM_STRING_SSL_SESSION, SSL_SESSION)
diff --git a/src/ssl/ssl_lib.c b/src/ssl/ssl_lib.c
index 08578a6..d01f6a2 100644
--- a/src/ssl/ssl_lib.c
+++ b/src/ssl/ssl_lib.c
@@ -141,7 +141,7 @@
 #include <openssl/ssl.h>
 
 #include <assert.h>
-#include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include <openssl/bytestring.h>
@@ -150,18 +150,28 @@
 #include <openssl/err.h>
 #include <openssl/lhash.h>
 #include <openssl/mem.h>
-#include <openssl/obj.h>
 #include <openssl/rand.h>
-#include <openssl/x509v3.h>
 
 #include "internal.h"
 #include "../crypto/internal.h"
 
+#if defined(OPENSSL_WINDOWS)
+#include <sys/timeb.h>
+#else
+#include <sys/socket.h>
+#include <sys/time.h>
+#endif
+
 
 /* |SSL_R_UNKNOWN_PROTOCOL| is no longer emitted, but continue to define it
  * to avoid downstream churn. */
 OPENSSL_DECLARE_ERROR_REASON(SSL, UNKNOWN_PROTOCOL)
 
+/* The following errors are no longer emitted, but are used in nginx without
+ * #ifdefs. */
+OPENSSL_DECLARE_ERROR_REASON(SSL, BLOCK_CIPHER_PAD_IS_WRONG)
+OPENSSL_DECLARE_ERROR_REASON(SSL, NO_CIPHERS_SPECIFIED)
+
 /* Some error codes are special. Ensure the make_errors.go script never
  * regresses this. */
 OPENSSL_COMPILE_ASSERT(SSL_R_TLSV1_ALERT_NO_RENEGOTIATION ==
@@ -181,12 +191,21 @@
   return 1;
 }
 
-static uint32_t ssl_session_hash(const SSL_SESSION *a) {
+static uint32_t ssl_session_hash(const SSL_SESSION *sess) {
+  const uint8_t *session_id = sess->session_id;
+
+  uint8_t tmp_storage[sizeof(uint32_t)];
+  if (sess->session_id_length < sizeof(tmp_storage)) {
+    OPENSSL_memset(tmp_storage, 0, sizeof(tmp_storage));
+    OPENSSL_memcpy(tmp_storage, sess->session_id, sess->session_id_length);
+    session_id = tmp_storage;
+  }
+
   uint32_t hash =
-      ((uint32_t)a->session_id[0]) |
-      ((uint32_t)a->session_id[1] << 8) |
-      ((uint32_t)a->session_id[2] << 16) |
-      ((uint32_t)a->session_id[3] << 24);
+      ((uint32_t)session_id[0]) |
+      ((uint32_t)session_id[1] << 8) |
+      ((uint32_t)session_id[2] << 16) |
+      ((uint32_t)session_id[3] << 24);
 
   return hash;
 }
@@ -205,7 +224,7 @@
     return 1;
   }
 
-  return memcmp(a->session_id, b->session_id, a->session_id_length);
+  return OPENSSL_memcmp(a->session_id, b->session_id, a->session_id_length);
 }
 
 SSL_CTX *SSL_CTX_new(const SSL_METHOD *method) {
@@ -216,33 +235,29 @@
     return NULL;
   }
 
-  if (SSL_get_ex_data_X509_STORE_CTX_idx() < 0) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_X509_VERIFICATION_SETUP_PROBLEMS);
-    goto err;
-  }
-
-  ret = (SSL_CTX *)OPENSSL_malloc(sizeof(SSL_CTX));
+  ret = OPENSSL_malloc(sizeof(SSL_CTX));
   if (ret == NULL) {
     goto err;
   }
 
-  memset(ret, 0, sizeof(SSL_CTX));
+  OPENSSL_memset(ret, 0, sizeof(SSL_CTX));
 
   ret->method = method->method;
+  ret->x509_method = method->x509_method;
 
   CRYPTO_MUTEX_init(&ret->lock);
 
   ret->session_cache_mode = SSL_SESS_CACHE_SERVER;
   ret->session_cache_size = SSL_SESSION_CACHE_MAX_SIZE_DEFAULT;
 
-  /* We take the system default */
   ret->session_timeout = SSL_DEFAULT_SESSION_TIMEOUT;
+  ret->session_psk_dhe_timeout = SSL_DEFAULT_SESSION_PSK_DHE_TIMEOUT;
 
   ret->references = 1;
 
   ret->max_cert_list = SSL_MAX_CERT_LIST_DEFAULT;
   ret->verify_mode = SSL_VERIFY_NONE;
-  ret->cert = ssl_cert_new();
+  ret->cert = ssl_cert_new(method->x509_method);
   if (ret->cert == NULL) {
     goto err;
   }
@@ -251,25 +266,16 @@
   if (ret->sessions == NULL) {
     goto err;
   }
-  ret->cert_store = X509_STORE_new();
-  if (ret->cert_store == NULL) {
+
+  if (!ret->x509_method->ssl_ctx_new(ret)) {
     goto err;
   }
 
-  ssl_create_cipher_list(ret->method, &ret->cipher_list,
-                         &ret->cipher_list_by_id, SSL_DEFAULT_CIPHER_LIST);
-  if (ret->cipher_list == NULL ||
-      sk_SSL_CIPHER_num(ret->cipher_list->ciphers) <= 0) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_LIBRARY_HAS_NO_CIPHERS);
+  if (!SSL_CTX_set_strict_cipher_list(ret, SSL_DEFAULT_CIPHER_LIST)) {
     goto err2;
   }
 
-  ret->param = X509_VERIFY_PARAM_new();
-  if (!ret->param) {
-    goto err;
-  }
-
-  ret->client_CA = sk_X509_NAME_new_null();
+  ret->client_CA = sk_CRYPTO_BUFFER_new_null();
   if (ret->client_CA == NULL) {
     goto err;
   }
@@ -285,11 +291,16 @@
     ret->options |= SSL_OP_NO_TICKET;
   }
 
+  /* Disable the auto-chaining feature by default. Once this has stuck without
+   * problems, the feature will be removed entirely. */
+  ret->mode = SSL_MODE_NO_AUTO_CHAIN;
+
   /* Lock the SSL_CTX to the specified version, for compatibility with legacy
    * uses of SSL_METHOD. */
-  if (method->version != 0) {
-    SSL_CTX_set_max_version(ret, method->version);
-    SSL_CTX_set_min_version(ret, method->version);
+  if (!SSL_CTX_set_max_proto_version(ret, method->version) ||
+      !SSL_CTX_set_min_proto_version(ret, method->version)) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    goto err2;
   }
 
   return ret;
@@ -301,14 +312,17 @@
   return NULL;
 }
 
+int SSL_CTX_up_ref(SSL_CTX *ctx) {
+  CRYPTO_refcount_inc(&ctx->references);
+  return 1;
+}
+
 void SSL_CTX_free(SSL_CTX *ctx) {
   if (ctx == NULL ||
       !CRYPTO_refcount_dec_and_test_zero(&ctx->references)) {
     return;
   }
 
-  X509_VERIFY_PARAM_free(ctx->param);
-
   /* Free internal session cache. However: the remove_cb() may reference the
    * ex_data of SSL_CTX, thus the ex_data store can only be removed after the
    * sessions were flushed. As the ex_data handling routines might also touch
@@ -321,23 +335,18 @@
 
   CRYPTO_MUTEX_cleanup(&ctx->lock);
   lh_SSL_SESSION_free(ctx->sessions);
-  X509_STORE_free(ctx->cert_store);
   ssl_cipher_preference_list_free(ctx->cipher_list);
-  sk_SSL_CIPHER_free(ctx->cipher_list_by_id);
-  ssl_cipher_preference_list_free(ctx->cipher_list_tls10);
-  ssl_cipher_preference_list_free(ctx->cipher_list_tls11);
   ssl_cert_free(ctx->cert);
   sk_SSL_CUSTOM_EXTENSION_pop_free(ctx->client_custom_extensions,
                                    SSL_CUSTOM_EXTENSION_free);
   sk_SSL_CUSTOM_EXTENSION_pop_free(ctx->server_custom_extensions,
                                    SSL_CUSTOM_EXTENSION_free);
-  sk_X509_NAME_pop_free(ctx->client_CA, X509_NAME_free);
+  sk_CRYPTO_BUFFER_pop_free(ctx->client_CA, CRYPTO_BUFFER_free);
+  ctx->x509_method->ssl_ctx_free(ctx);
   sk_SRTP_PROTECTION_PROFILE_free(ctx->srtp_profiles);
   OPENSSL_free(ctx->psk_identity_hint);
-  OPENSSL_free(ctx->tlsext_ellipticcurvelist);
+  OPENSSL_free(ctx->supported_group_list);
   OPENSSL_free(ctx->alpn_client_proto_list);
-  OPENSSL_free(ctx->ocsp_response);
-  OPENSSL_free(ctx->signed_cert_timestamp_list);
   EVP_PKEY_free(ctx->tlsext_channel_id_private);
 
   OPENSSL_free(ctx);
@@ -353,15 +362,19 @@
     return NULL;
   }
 
-  SSL *ssl = (SSL *)OPENSSL_malloc(sizeof(SSL));
+  SSL *ssl = OPENSSL_malloc(sizeof(SSL));
   if (ssl == NULL) {
     goto err;
   }
-  memset(ssl, 0, sizeof(SSL));
+  OPENSSL_memset(ssl, 0, sizeof(SSL));
 
   ssl->min_version = ctx->min_version;
   ssl->max_version = ctx->max_version;
 
+  /* RFC 6347 states that implementations SHOULD use an initial timer value of
+   * 1 second. */
+  ssl->initial_timeout_duration_ms = 1000;
+
   ssl->options = ctx->options;
   ssl->mode = ctx->mode;
   ssl->max_cert_list = ctx->max_cert_list;
@@ -374,51 +387,45 @@
   ssl->msg_callback = ctx->msg_callback;
   ssl->msg_callback_arg = ctx->msg_callback_arg;
   ssl->verify_mode = ctx->verify_mode;
-  ssl->sid_ctx_length = ctx->sid_ctx_length;
-  assert(ssl->sid_ctx_length <= sizeof ssl->sid_ctx);
-  memcpy(&ssl->sid_ctx, &ctx->sid_ctx, sizeof(ssl->sid_ctx));
   ssl->verify_callback = ctx->default_verify_callback;
+  ssl->retain_only_sha256_of_client_certs =
+      ctx->retain_only_sha256_of_client_certs;
 
-  ssl->param = X509_VERIFY_PARAM_new();
-  if (!ssl->param) {
-    goto err;
-  }
-  X509_VERIFY_PARAM_inherit(ssl->param, ctx->param);
   ssl->quiet_shutdown = ctx->quiet_shutdown;
   ssl->max_send_fragment = ctx->max_send_fragment;
 
-  CRYPTO_refcount_inc(&ctx->references);
+  SSL_CTX_up_ref(ctx);
   ssl->ctx = ctx;
-  CRYPTO_refcount_inc(&ctx->references);
-  ssl->initial_ctx = ctx;
+  SSL_CTX_up_ref(ctx);
+  ssl->session_ctx = ctx;
 
-  if (ctx->tlsext_ellipticcurvelist) {
-    ssl->tlsext_ellipticcurvelist =
-        BUF_memdup(ctx->tlsext_ellipticcurvelist,
-                   ctx->tlsext_ellipticcurvelist_length * 2);
-    if (!ssl->tlsext_ellipticcurvelist) {
-      goto err;
-    }
-    ssl->tlsext_ellipticcurvelist_length = ctx->tlsext_ellipticcurvelist_length;
+  if (!ssl->ctx->x509_method->ssl_new(ssl)) {
+    goto err;
   }
 
-  if (ssl->ctx->alpn_client_proto_list) {
-    ssl->alpn_client_proto_list = BUF_memdup(
-        ssl->ctx->alpn_client_proto_list, ssl->ctx->alpn_client_proto_list_len);
+  if (ctx->supported_group_list) {
+    ssl->supported_group_list = BUF_memdup(ctx->supported_group_list,
+                                           ctx->supported_group_list_len * 2);
+    if (!ssl->supported_group_list) {
+      goto err;
+    }
+    ssl->supported_group_list_len = ctx->supported_group_list_len;
+  }
+
+  if (ctx->alpn_client_proto_list) {
+    ssl->alpn_client_proto_list = BUF_memdup(ctx->alpn_client_proto_list,
+                                             ctx->alpn_client_proto_list_len);
     if (ssl->alpn_client_proto_list == NULL) {
       goto err;
     }
-    ssl->alpn_client_proto_list_len = ssl->ctx->alpn_client_proto_list_len;
+    ssl->alpn_client_proto_list_len = ctx->alpn_client_proto_list_len;
   }
 
-  ssl->verify_result = X509_V_OK;
   ssl->method = ctx->method;
 
   if (!ssl->method->ssl_new(ssl)) {
     goto err;
   }
-  ssl->enc_method = ssl3_get_enc_method(ssl->version);
-  assert(ssl->enc_method != NULL);
 
   ssl->rwstate = SSL_NOTHING;
 
@@ -436,13 +443,12 @@
 
   ssl->tlsext_channel_id_enabled = ctx->tlsext_channel_id_enabled;
   if (ctx->tlsext_channel_id_private) {
-    ssl->tlsext_channel_id_private =
-        EVP_PKEY_up_ref(ctx->tlsext_channel_id_private);
+    EVP_PKEY_up_ref(ctx->tlsext_channel_id_private);
+    ssl->tlsext_channel_id_private = ctx->tlsext_channel_id_private;
   }
 
-  ssl->signed_cert_timestamps_enabled =
-      ssl->ctx->signed_cert_timestamps_enabled;
-  ssl->ocsp_stapling_enabled = ssl->ctx->ocsp_stapling_enabled;
+  ssl->signed_cert_timestamps_enabled = ctx->signed_cert_timestamps_enabled;
+  ssl->ocsp_stapling_enabled = ctx->ocsp_stapling_enabled;
 
   return ssl;
 
@@ -458,46 +464,28 @@
     return;
   }
 
-  X509_VERIFY_PARAM_free(ssl->param);
-
+  ssl->ctx->x509_method->ssl_free(ssl);
   CRYPTO_free_ex_data(&g_ex_data_class_ssl, ssl, &ssl->ex_data);
 
-  if (ssl->bbio != NULL) {
-    /* If the buffering BIO is in place, pop it off */
-    if (ssl->bbio == ssl->wbio) {
-      ssl->wbio = BIO_pop(ssl->wbio);
-    }
-    BIO_free(ssl->bbio);
-    ssl->bbio = NULL;
-  }
-
-  int free_wbio = ssl->wbio != ssl->rbio;
   BIO_free_all(ssl->rbio);
-  if (free_wbio) {
-    BIO_free_all(ssl->wbio);
-  }
+  BIO_free_all(ssl->wbio);
 
   BUF_MEM_free(ssl->init_buf);
 
   /* add extra stuff */
   ssl_cipher_preference_list_free(ssl->cipher_list);
-  sk_SSL_CIPHER_free(ssl->cipher_list_by_id);
 
-  ssl_clear_bad_session(ssl);
   SSL_SESSION_free(ssl->session);
 
-  ssl_clear_cipher_ctx(ssl);
-
   ssl_cert_free(ssl->cert);
 
   OPENSSL_free(ssl->tlsext_hostname);
-  SSL_CTX_free(ssl->initial_ctx);
-  OPENSSL_free(ssl->tlsext_ellipticcurvelist);
+  SSL_CTX_free(ssl->session_ctx);
+  OPENSSL_free(ssl->supported_group_list);
   OPENSSL_free(ssl->alpn_client_proto_list);
   EVP_PKEY_free(ssl->tlsext_channel_id_private);
   OPENSSL_free(ssl->psk_identity_hint);
-  sk_X509_NAME_pop_free(ssl->client_CA, X509_NAME_free);
-  OPENSSL_free(ssl->next_proto_negotiated);
+  sk_CRYPTO_BUFFER_pop_free(ssl->client_CA, CRYPTO_BUFFER_free);
   sk_SRTP_PROTECTION_PROFILE_free(ssl->srtp_profiles);
 
   if (ssl->method != NULL) {
@@ -510,46 +498,73 @@
 
 void SSL_set_connect_state(SSL *ssl) {
   ssl->server = 0;
-  ssl->shutdown = 0;
-  ssl->state = SSL_ST_CONNECT;
-  ssl->handshake_func = ssl->method->ssl_connect;
-  /* clear the current cipher */
-  ssl_clear_cipher_ctx(ssl);
+  ssl->handshake_func = ssl3_connect;
 }
 
 void SSL_set_accept_state(SSL *ssl) {
   ssl->server = 1;
-  ssl->shutdown = 0;
-  ssl->state = SSL_ST_ACCEPT;
-  ssl->handshake_func = ssl->method->ssl_accept;
-  /* clear the current cipher */
-  ssl_clear_cipher_ctx(ssl);
+  ssl->handshake_func = ssl3_accept;
+}
+
+void SSL_set0_rbio(SSL *ssl, BIO *rbio) {
+  BIO_free_all(ssl->rbio);
+  ssl->rbio = rbio;
+}
+
+void SSL_set0_wbio(SSL *ssl, BIO *wbio) {
+  BIO_free_all(ssl->wbio);
+  ssl->wbio = wbio;
 }
 
 void SSL_set_bio(SSL *ssl, BIO *rbio, BIO *wbio) {
-  /* If the output buffering BIO is still in place, remove it. */
-  if (ssl->bbio != NULL) {
-    if (ssl->wbio == ssl->bbio) {
-      ssl->wbio = ssl->wbio->next_bio;
-      ssl->bbio->next_bio = NULL;
-    }
+  /* For historical reasons, this function has many different cases in ownership
+   * handling. */
+
+  /* If nothing has changed, do nothing */
+  if (rbio == SSL_get_rbio(ssl) && wbio == SSL_get_wbio(ssl)) {
+    return;
   }
 
-  if (ssl->rbio != rbio) {
-    BIO_free_all(ssl->rbio);
+  /* If the two arguments are equal, one fewer reference is granted than
+   * taken. */
+  if (rbio != NULL && rbio == wbio) {
+    BIO_up_ref(rbio);
   }
-  if (ssl->wbio != wbio && ssl->rbio != ssl->wbio) {
-    BIO_free_all(ssl->wbio);
+
+  /* If only the wbio is changed, adopt only one reference. */
+  if (rbio == SSL_get_rbio(ssl)) {
+    SSL_set0_wbio(ssl, wbio);
+    return;
   }
-  ssl->rbio = rbio;
-  ssl->wbio = wbio;
+
+  /* There is an asymmetry here for historical reasons. If only the rbio is
+   * changed AND the rbio and wbio were originally different, then we only adopt
+   * one reference. */
+  if (wbio == SSL_get_wbio(ssl) && SSL_get_rbio(ssl) != SSL_get_wbio(ssl)) {
+    SSL_set0_rbio(ssl, rbio);
+    return;
+  }
+
+  /* Otherwise, adopt both references. */
+  SSL_set0_rbio(ssl, rbio);
+  SSL_set0_wbio(ssl, wbio);
 }
 
 BIO *SSL_get_rbio(const SSL *ssl) { return ssl->rbio; }
 
 BIO *SSL_get_wbio(const SSL *ssl) { return ssl->wbio; }
 
+void ssl_reset_error_state(SSL *ssl) {
+  /* Functions which use |SSL_get_error| must reset I/O and error state on
+   * entry. */
+  ssl->rwstate = SSL_NOTHING;
+  ERR_clear_error();
+  ERR_clear_system_error();
+}
+
 int SSL_do_handshake(SSL *ssl) {
+  ssl_reset_error_state(ssl);
+
   if (ssl->handshake_func == NULL) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_TYPE_NOT_SET);
     return -1;
@@ -559,149 +574,290 @@
     return 1;
   }
 
-  return ssl->handshake_func(ssl);
+  if (ssl->s3->hs == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    return -1;
+  }
+
+  /* Run the handshake. */
+  assert(ssl->s3->hs != NULL);
+  int ret = ssl->handshake_func(ssl->s3->hs);
+  if (ret <= 0) {
+    return ret;
+  }
+
+  /* Destroy the handshake object if the handshake has completely finished. */
+  if (!SSL_in_init(ssl)) {
+    ssl_handshake_free(ssl->s3->hs);
+    ssl->s3->hs = NULL;
+  }
+
+  return 1;
 }
 
 int SSL_connect(SSL *ssl) {
-  if (ssl->handshake_func == 0) {
+  if (ssl->handshake_func == NULL) {
     /* Not properly initialized yet */
     SSL_set_connect_state(ssl);
   }
 
-  if (ssl->handshake_func != ssl->method->ssl_connect) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    return -1;
-  }
-
-  return ssl->handshake_func(ssl);
+  return SSL_do_handshake(ssl);
 }
 
 int SSL_accept(SSL *ssl) {
-  if (ssl->handshake_func == 0) {
+  if (ssl->handshake_func == NULL) {
     /* Not properly initialized yet */
     SSL_set_accept_state(ssl);
   }
 
-  if (ssl->handshake_func != ssl->method->ssl_accept) {
+  return SSL_do_handshake(ssl);
+}
+
+int ssl_can_write(const SSL *ssl) {
+  return !SSL_in_init(ssl) || ssl->s3->hs->can_early_write;
+}
+
+int ssl_can_read(const SSL *ssl) {
+  return !SSL_in_init(ssl) || ssl->s3->hs->can_early_read;
+}
+
+static int ssl_do_renegotiate(SSL *ssl) {
+  /* We do not accept renegotiations as a server or SSL 3.0. SSL 3.0 will be
+   * removed entirely in the future and requires retaining more data for
+   * renegotiation_info. */
+  if (ssl->server || ssl->version == SSL3_VERSION) {
+    goto no_renegotiation;
+  }
+
+  if (ssl->s3->tmp.message_type != SSL3_MT_HELLO_REQUEST ||
+      ssl->init_num != 0) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_HELLO_REQUEST);
+    return 0;
+  }
+
+  switch (ssl->renegotiate_mode) {
+    case ssl_renegotiate_ignore:
+      /* Ignore the HelloRequest. */
+      return 1;
+
+    case ssl_renegotiate_once:
+      if (ssl->s3->total_renegotiations != 0) {
+        goto no_renegotiation;
+      }
+      break;
+
+    case ssl_renegotiate_never:
+      goto no_renegotiation;
+
+    case ssl_renegotiate_freely:
+      break;
+  }
+
+  /* Renegotiation is only supported at quiescent points in the application
+   * protocol, namely in HTTPS, just before reading the HTTP response. Require
+   * the record-layer be idle and avoid complexities of sending a handshake
+   * record while an application_data record is being written. */
+  if (ssl_write_buffer_is_pending(ssl)) {
+    goto no_renegotiation;
+  }
+
+  /* Begin a new handshake. */
+  if (ssl->s3->hs != NULL) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    return 0;
+  }
+  ssl->s3->hs = ssl_handshake_new(ssl);
+  if (ssl->s3->hs == NULL) {
+    return 0;
+  }
+
+  ssl->s3->total_renegotiations++;
+  return 1;
+
+no_renegotiation:
+  ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_NO_RENEGOTIATION);
+  OPENSSL_PUT_ERROR(SSL, SSL_R_NO_RENEGOTIATION);
+  return 0;
+}
+
+static int ssl_do_post_handshake(SSL *ssl) {
+  if (ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
+    return ssl_do_renegotiate(ssl);
+  }
+
+  return tls13_post_handshake(ssl);
+}
+
+static int ssl_read_impl(SSL *ssl, void *buf, int num, int peek) {
+  ssl_reset_error_state(ssl);
+
+  if (ssl->handshake_func == NULL) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_UNINITIALIZED);
     return -1;
   }
 
-  return ssl->handshake_func(ssl);
+  for (;;) {
+    /* Complete the current handshake, if any. False Start will cause
+     * |SSL_do_handshake| to return mid-handshake, so this may require multiple
+     * iterations. */
+    while (!ssl_can_read(ssl)) {
+      int ret = SSL_do_handshake(ssl);
+      if (ret < 0) {
+        return ret;
+      }
+      if (ret == 0) {
+        OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_HANDSHAKE_FAILURE);
+        return -1;
+      }
+    }
+
+    int got_handshake;
+    int ret = ssl->method->read_app_data(ssl, &got_handshake, buf, num, peek);
+    if (ret > 0 || !got_handshake) {
+      ssl->s3->key_update_count = 0;
+      return ret;
+    }
+
+    /* If we received an interrupt in early read (the end_of_early_data alert),
+     * loop again for the handshake to process it. */
+    if (SSL_in_init(ssl)) {
+      continue;
+    }
+
+    /* Handle the post-handshake message and try again. */
+    if (!ssl_do_post_handshake(ssl)) {
+      return -1;
+    }
+    ssl->method->release_current_message(ssl, 1 /* free buffer */);
+  }
 }
 
 int SSL_read(SSL *ssl, void *buf, int num) {
-  if (ssl->handshake_func == 0) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_UNINITIALIZED);
-    return -1;
-  }
-
-  if (ssl->shutdown & SSL_RECEIVED_SHUTDOWN) {
-    ssl->rwstate = SSL_NOTHING;
-    return 0;
-  }
-
-  ERR_clear_system_error();
-  return ssl->method->ssl_read_app_data(ssl, buf, num, 0);
+  return ssl_read_impl(ssl, buf, num, 0 /* consume bytes */);
 }
 
 int SSL_peek(SSL *ssl, void *buf, int num) {
-  if (ssl->handshake_func == 0) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_UNINITIALIZED);
-    return -1;
-  }
-
-  if (ssl->shutdown & SSL_RECEIVED_SHUTDOWN) {
-    return 0;
-  }
-
-  ERR_clear_system_error();
-  return ssl->method->ssl_read_app_data(ssl, buf, num, 1);
+  return ssl_read_impl(ssl, buf, num, 1 /* peek */);
 }
 
 int SSL_write(SSL *ssl, const void *buf, int num) {
-  if (ssl->handshake_func == 0) {
+  ssl_reset_error_state(ssl);
+
+  if (ssl->handshake_func == NULL) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_UNINITIALIZED);
     return -1;
   }
 
-  if (ssl->shutdown & SSL_SENT_SHUTDOWN) {
-    ssl->rwstate = SSL_NOTHING;
+  if (ssl->s3->send_shutdown != ssl_shutdown_none) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_PROTOCOL_IS_SHUTDOWN);
     return -1;
   }
 
-  ERR_clear_system_error();
-  return ssl->method->ssl_write_app_data(ssl, buf, num);
+  /* If necessary, complete the handshake implicitly. */
+  if (!ssl_can_write(ssl)) {
+    int ret = SSL_do_handshake(ssl);
+    if (ret < 0) {
+      return ret;
+    }
+    if (ret == 0) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_HANDSHAKE_FAILURE);
+      return -1;
+    }
+  }
+
+  return ssl->method->write_app_data(ssl, buf, num);
 }
 
 int SSL_shutdown(SSL *ssl) {
-  /* Note that this function behaves differently from what one might expect.
-   * Return values are 0 for no success (yet), 1 for success; but calling it
-   * once is usually not enough, even if blocking I/O is used (see
-   * ssl3_shutdown). */
+  ssl_reset_error_state(ssl);
 
-  if (ssl->handshake_func == 0) {
+  if (ssl->handshake_func == NULL) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_UNINITIALIZED);
     return -1;
   }
 
+  /* If we are in the middle of a handshake, silently succeed. Consumers often
+   * call this function before |SSL_free|, whether the handshake succeeded or
+   * not. We assume the caller has already handled failed handshakes. */
   if (SSL_in_init(ssl)) {
     return 1;
   }
 
-  /* Do nothing if configured not to send a close_notify. */
   if (ssl->quiet_shutdown) {
-    ssl->shutdown = SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN;
+    /* Do nothing if configured not to send a close_notify. */
+    ssl->s3->send_shutdown = ssl_shutdown_close_notify;
+    ssl->s3->recv_shutdown = ssl_shutdown_close_notify;
     return 1;
   }
 
-  if (!(ssl->shutdown & SSL_SENT_SHUTDOWN)) {
-    ssl->shutdown |= SSL_SENT_SHUTDOWN;
-    ssl3_send_alert(ssl, SSL3_AL_WARNING, SSL_AD_CLOSE_NOTIFY);
+  /* This function completes in two stages. It sends a close_notify and then it
+   * waits for a close_notify to come in. Perform exactly one action and return
+   * whether or not it succeeds. */
 
-    /* our shutdown alert has been sent now, and if it still needs to be
-     * written, ssl->s3->alert_dispatch will be true */
-    if (ssl->s3->alert_dispatch) {
-      return -1; /* return WANT_WRITE */
+  if (ssl->s3->send_shutdown != ssl_shutdown_close_notify) {
+    /* Send a close_notify. */
+    if (ssl3_send_alert(ssl, SSL3_AL_WARNING, SSL_AD_CLOSE_NOTIFY) <= 0) {
+      return -1;
     }
   } else if (ssl->s3->alert_dispatch) {
-    /* resend it if not sent */
-    int ret = ssl->method->ssl_dispatch_alert(ssl);
-    if (ret == -1) {
-      /* we only get to return -1 here the 2nd/Nth invocation, we must  have
-       * already signalled return 0 upon a previous invoation, return
-       * WANT_WRITE */
-      return ret;
+    /* Finish sending the close_notify. */
+    if (ssl->method->dispatch_alert(ssl) <= 0) {
+      return -1;
     }
-  } else if (!(ssl->shutdown & SSL_RECEIVED_SHUTDOWN)) {
-    /* If we are waiting for a close from our peer, we are closed */
-    ssl->method->ssl_read_close_notify(ssl);
-    if (!(ssl->shutdown & SSL_RECEIVED_SHUTDOWN)) {
-      return -1; /* return WANT_READ */
+  } else if (ssl->s3->recv_shutdown != ssl_shutdown_close_notify) {
+    /* Wait for the peer's close_notify. */
+    ssl->method->read_close_notify(ssl);
+    if (ssl->s3->recv_shutdown != ssl_shutdown_close_notify) {
+      return -1;
     }
   }
 
-  if (ssl->shutdown == (SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN) &&
-      !ssl->s3->alert_dispatch) {
-    return 1;
-  } else {
-    return 0;
+  /* Return 0 for unidirectional shutdown and 1 for bidirectional shutdown. */
+  return ssl->s3->recv_shutdown == ssl_shutdown_close_notify;
+}
+
+int SSL_send_fatal_alert(SSL *ssl, uint8_t alert) {
+  if (ssl->s3->alert_dispatch) {
+    if (ssl->s3->send_alert[0] != SSL3_AL_FATAL ||
+        ssl->s3->send_alert[1] != alert) {
+      /* We are already attempting to write a different alert. */
+      OPENSSL_PUT_ERROR(SSL, SSL_R_PROTOCOL_IS_SHUTDOWN);
+      return -1;
+    }
+    return ssl->method->dispatch_alert(ssl);
+  }
+
+  return ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
+}
+
+void SSL_CTX_set_early_data_enabled(SSL_CTX *ctx, int enabled) {
+  ctx->enable_early_data = !!enabled;
+}
+
+int SSL_early_data_accepted(const SSL *ssl) {
+  return ssl->early_data_accepted;
+}
+
+static int bio_retry_reason_to_error(int reason) {
+  switch (reason) {
+    case BIO_RR_CONNECT:
+      return SSL_ERROR_WANT_CONNECT;
+    case BIO_RR_ACCEPT:
+      return SSL_ERROR_WANT_ACCEPT;
+    default:
+      return SSL_ERROR_SYSCALL;
   }
 }
 
 int SSL_get_error(const SSL *ssl, int ret_code) {
-  int reason;
-  uint32_t err;
-  BIO *bio;
-
   if (ret_code > 0) {
     return SSL_ERROR_NONE;
   }
 
   /* Make things return SSL_ERROR_SYSCALL when doing SSL_do_handshake etc,
    * where we do encode the error */
-  err = ERR_peek_error();
+  uint32_t err = ERR_peek_error();
   if (err != 0) {
     if (ERR_GET_LIB(err) == ERR_LIB_SYS) {
       return SSL_ERROR_SYSCALL;
@@ -710,9 +866,7 @@
   }
 
   if (ret_code == 0) {
-    if ((ssl->shutdown & SSL_RECEIVED_SHUTDOWN) &&
-        (ssl->s3->warn_alert == SSL_AD_CLOSE_NOTIFY)) {
-      /* The socket was cleanly shut down with a close_notify. */
+    if (ssl->s3->recv_shutdown == ssl_shutdown_close_notify) {
       return SSL_ERROR_ZERO_RETURN;
     }
     /* An EOF was observed which violates the protocol, and the underlying
@@ -721,98 +875,115 @@
     return SSL_ERROR_SYSCALL;
   }
 
-  if (SSL_want_session(ssl)) {
-    return SSL_ERROR_PENDING_SESSION;
-  }
+  switch (ssl->rwstate) {
+    case SSL_PENDING_SESSION:
+      return SSL_ERROR_PENDING_SESSION;
 
-  if (SSL_want_certificate(ssl)) {
-    return SSL_ERROR_PENDING_CERTIFICATE;
-  }
+    case SSL_CERTIFICATE_SELECTION_PENDING:
+      return SSL_ERROR_PENDING_CERTIFICATE;
 
-  if (SSL_want_read(ssl)) {
-    bio = SSL_get_rbio(ssl);
-    if (BIO_should_read(bio)) {
-      return SSL_ERROR_WANT_READ;
-    }
-
-    if (BIO_should_write(bio)) {
-      /* This one doesn't make too much sense ... We never try to write to the
-       * rbio, and an application program where rbio and wbio are separate
-       * couldn't even know what it should wait for. However if we ever set
-       * ssl->rwstate incorrectly (so that we have SSL_want_read(ssl) instead of
-       * SSL_want_write(ssl)) and rbio and wbio *are* the same, this test works
-       * around that bug; so it might be safer to keep it. */
-      return SSL_ERROR_WANT_WRITE;
-    }
-
-    if (BIO_should_io_special(bio)) {
-      reason = BIO_get_retry_reason(bio);
-      if (reason == BIO_RR_CONNECT) {
-        return SSL_ERROR_WANT_CONNECT;
+    case SSL_READING: {
+      BIO *bio = SSL_get_rbio(ssl);
+      if (BIO_should_read(bio)) {
+        return SSL_ERROR_WANT_READ;
       }
 
-      if (reason == BIO_RR_ACCEPT) {
-        return SSL_ERROR_WANT_ACCEPT;
+      if (BIO_should_write(bio)) {
+        /* TODO(davidben): OpenSSL historically checked for writes on the read
+         * BIO. Can this be removed? */
+        return SSL_ERROR_WANT_WRITE;
       }
 
-      return SSL_ERROR_SYSCALL; /* unknown */
-    }
-  }
-
-  if (SSL_want_write(ssl)) {
-    bio = SSL_get_wbio(ssl);
-    if (BIO_should_write(bio)) {
-      return SSL_ERROR_WANT_WRITE;
-    }
-
-    if (BIO_should_read(bio)) {
-      /* See above (SSL_want_read(ssl) with BIO_should_write(bio)) */
-      return SSL_ERROR_WANT_READ;
-    }
-
-    if (BIO_should_io_special(bio)) {
-      reason = BIO_get_retry_reason(bio);
-      if (reason == BIO_RR_CONNECT) {
-        return SSL_ERROR_WANT_CONNECT;
+      if (BIO_should_io_special(bio)) {
+        return bio_retry_reason_to_error(BIO_get_retry_reason(bio));
       }
 
-      if (reason == BIO_RR_ACCEPT) {
-        return SSL_ERROR_WANT_ACCEPT;
+      break;
+    }
+
+    case SSL_WRITING: {
+      BIO *bio = SSL_get_wbio(ssl);
+      if (BIO_should_write(bio)) {
+        return SSL_ERROR_WANT_WRITE;
       }
 
-      return SSL_ERROR_SYSCALL;
+      if (BIO_should_read(bio)) {
+        /* TODO(davidben): OpenSSL historically checked for reads on the write
+         * BIO. Can this be removed? */
+        return SSL_ERROR_WANT_READ;
+      }
+
+      if (BIO_should_io_special(bio)) {
+        return bio_retry_reason_to_error(BIO_get_retry_reason(bio));
+      }
+
+      break;
     }
-  }
 
-  if (SSL_want_x509_lookup(ssl)) {
-    return SSL_ERROR_WANT_X509_LOOKUP;
-  }
+    case SSL_X509_LOOKUP:
+      return SSL_ERROR_WANT_X509_LOOKUP;
 
-  if (SSL_want_channel_id_lookup(ssl)) {
-    return SSL_ERROR_WANT_CHANNEL_ID_LOOKUP;
-  }
+    case SSL_CHANNEL_ID_LOOKUP:
+      return SSL_ERROR_WANT_CHANNEL_ID_LOOKUP;
 
-  if (SSL_want_private_key_operation(ssl)) {
-    return SSL_ERROR_WANT_PRIVATE_KEY_OPERATION;
+    case SSL_PRIVATE_KEY_OPERATION:
+      return SSL_ERROR_WANT_PRIVATE_KEY_OPERATION;
+
+    case SSL_PENDING_TICKET:
+      return SSL_ERROR_PENDING_TICKET;
   }
 
   return SSL_ERROR_SYSCALL;
 }
 
-void SSL_CTX_set_min_version(SSL_CTX *ctx, uint16_t version) {
-  ctx->min_version = version;
+static int set_min_version(const SSL_PROTOCOL_METHOD *method, uint16_t *out,
+                           uint16_t version) {
+  /* Zero is interpreted as the default minimum version. */
+  if (version == 0) {
+    *out = method->min_version;
+    return 1;
+  }
+
+  if (version == TLS1_3_VERSION) {
+    version = TLS1_3_DRAFT_VERSION;
+  }
+
+  return method->version_from_wire(out, version);
 }
 
-void SSL_CTX_set_max_version(SSL_CTX *ctx, uint16_t version) {
-  ctx->max_version = version;
+static int set_max_version(const SSL_PROTOCOL_METHOD *method, uint16_t *out,
+                           uint16_t version) {
+  /* Zero is interpreted as the default maximum version. */
+  if (version == 0) {
+    *out = method->max_version;
+    /* TODO(svaldez): Enable TLS 1.3 by default once fully implemented. */
+    if (*out > TLS1_2_VERSION) {
+      *out = TLS1_2_VERSION;
+    }
+    return 1;
+  }
+
+  if (version == TLS1_3_VERSION) {
+    version = TLS1_3_DRAFT_VERSION;
+  }
+
+  return method->version_from_wire(out, version);
 }
 
-void SSL_set_min_version(SSL *ssl, uint16_t version) {
-  ssl->min_version = version;
+int SSL_CTX_set_min_proto_version(SSL_CTX *ctx, uint16_t version) {
+  return set_min_version(ctx->method, &ctx->min_version, version);
 }
 
-void SSL_set_max_version(SSL *ssl, uint16_t version) {
-  ssl->max_version = version;
+int SSL_CTX_set_max_proto_version(SSL_CTX *ctx, uint16_t version) {
+  return set_max_version(ctx->method, &ctx->max_version, version);
+}
+
+int SSL_set_min_proto_version(SSL *ssl, uint16_t version) {
+  return set_min_version(ssl->method, &ssl->min_version, version);
+}
+
+int SSL_set_max_proto_version(SSL *ssl, uint16_t version) {
+  return set_max_version(ssl->method, &ssl->max_version, version);
 }
 
 uint32_t SSL_CTX_set_options(SSL_CTX *ctx, uint32_t options) {
@@ -863,28 +1034,25 @@
 
 uint32_t SSL_get_mode(const SSL *ssl) { return ssl->mode; }
 
-X509 *SSL_get_peer_certificate(const SSL *ssl) {
-  if (ssl == NULL || ssl->session == NULL || ssl->session->peer == NULL) {
-    return NULL;
-  }
-  return X509_up_ref(ssl->session->peer);
-}
-
-STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *ssl) {
-  if (ssl == NULL || ssl->session == NULL) {
-    return NULL;
-  }
-  return ssl->session->cert_chain;
+void SSL_CTX_set0_buffer_pool(SSL_CTX *ctx, CRYPTO_BUFFER_POOL *pool) {
+  ctx->pool = pool;
 }
 
 int SSL_get_tls_unique(const SSL *ssl, uint8_t *out, size_t *out_len,
                        size_t max_out) {
+  /* tls-unique is not defined for SSL 3.0 or TLS 1.3. */
+  if (!ssl->s3->initial_handshake_complete ||
+      ssl3_protocol_version(ssl) < TLS1_VERSION ||
+      ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
+    goto err;
+  }
+
   /* The tls-unique value is the first Finished message in the handshake, which
    * is the client's in a full handshake and the server's for a resumption. See
    * https://tools.ietf.org/html/rfc5929#section-3.1. */
   const uint8_t *finished = ssl->s3->previous_client_finished;
   size_t finished_len = ssl->s3->previous_client_finished_len;
-  if (ssl->hit) {
+  if (ssl->session != NULL) {
     /* tls-unique is broken for resumed sessions unless EMS is used. */
     if (!ssl->session->extended_master_secret) {
       goto err;
@@ -893,71 +1061,46 @@
     finished_len = ssl->s3->previous_server_finished_len;
   }
 
-  if (!ssl->s3->initial_handshake_complete ||
-      ssl->version < TLS1_VERSION) {
-    goto err;
-  }
-
   *out_len = finished_len;
   if (finished_len > max_out) {
     *out_len = max_out;
   }
 
-  memcpy(out, finished, *out_len);
+  OPENSSL_memcpy(out, finished, *out_len);
   return 1;
 
 err:
   *out_len = 0;
-  memset(out, 0, max_out);
+  OPENSSL_memset(out, 0, max_out);
   return 0;
 }
 
-int SSL_CTX_set_session_id_context(SSL_CTX *ctx, const uint8_t *sid_ctx,
-                                   unsigned sid_ctx_len) {
-  if (sid_ctx_len > sizeof(ctx->sid_ctx)) {
+static int set_session_id_context(CERT *cert, const uint8_t *sid_ctx,
+                                   size_t sid_ctx_len) {
+  if (sid_ctx_len > sizeof(cert->sid_ctx)) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
     return 0;
   }
-  ctx->sid_ctx_length = sid_ctx_len;
-  memcpy(ctx->sid_ctx, sid_ctx, sid_ctx_len);
 
+  OPENSSL_COMPILE_ASSERT(sizeof(cert->sid_ctx) < 256, sid_ctx_too_large);
+  cert->sid_ctx_length = (uint8_t)sid_ctx_len;
+  OPENSSL_memcpy(cert->sid_ctx, sid_ctx, sid_ctx_len);
   return 1;
 }
 
+int SSL_CTX_set_session_id_context(SSL_CTX *ctx, const uint8_t *sid_ctx,
+                                   size_t sid_ctx_len) {
+  return set_session_id_context(ctx->cert, sid_ctx, sid_ctx_len);
+}
+
 int SSL_set_session_id_context(SSL *ssl, const uint8_t *sid_ctx,
-                               unsigned sid_ctx_len) {
-  if (sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
-    return 0;
-  }
-  ssl->sid_ctx_length = sid_ctx_len;
-  memcpy(ssl->sid_ctx, sid_ctx, sid_ctx_len);
-
-  return 1;
+                               size_t sid_ctx_len) {
+  return set_session_id_context(ssl->cert, sid_ctx, sid_ctx_len);
 }
 
-int SSL_CTX_set_purpose(SSL_CTX *ctx, int purpose) {
-  return X509_VERIFY_PARAM_set_purpose(ctx->param, purpose);
-}
-
-int SSL_set_purpose(SSL *ssl, int purpose) {
-  return X509_VERIFY_PARAM_set_purpose(ssl->param, purpose);
-}
-
-int SSL_CTX_set_trust(SSL_CTX *ctx, int trust) {
-  return X509_VERIFY_PARAM_set_trust(ctx->param, trust);
-}
-
-int SSL_set_trust(SSL *ssl, int trust) {
-  return X509_VERIFY_PARAM_set_trust(ssl->param, trust);
-}
-
-int SSL_CTX_set1_param(SSL_CTX *ctx, const X509_VERIFY_PARAM *param) {
-  return X509_VERIFY_PARAM_set1(ctx->param, param);
-}
-
-int SSL_set1_param(SSL *ssl, const X509_VERIFY_PARAM *param) {
-  return X509_VERIFY_PARAM_set1(ssl->param, param);
+const uint8_t *SSL_get0_session_id_context(const SSL *ssl, size_t *out_len) {
+  *out_len = ssl->cert->sid_ctx_length;
+  return ssl->cert->sid_ctx;
 }
 
 void ssl_cipher_preference_list_free(
@@ -970,10 +1113,6 @@
   OPENSSL_free(cipher_list);
 }
 
-X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx) { return ctx->param; }
-
-X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl) { return ssl->param; }
-
 void SSL_certs_clear(SSL *ssl) { ssl_cert_clear_certs(ssl->cert); }
 
 int SSL_get_fd(const SSL *ssl) { return SSL_get_rfd(ssl); }
@@ -997,7 +1136,7 @@
 }
 
 int SSL_set_fd(SSL *ssl, int fd) {
-  BIO *bio = BIO_new(BIO_s_fd());
+  BIO *bio = BIO_new(BIO_s_socket());
   if (bio == NULL) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
     return 0;
@@ -1008,102 +1147,108 @@
 }
 
 int SSL_set_wfd(SSL *ssl, int fd) {
-  if (ssl->rbio == NULL ||
-      BIO_method_type(ssl->rbio) != BIO_TYPE_FD ||
-      BIO_get_fd(ssl->rbio, NULL) != fd) {
-    BIO *bio = BIO_new(BIO_s_fd());
+  BIO *rbio = SSL_get_rbio(ssl);
+  if (rbio == NULL || BIO_method_type(rbio) != BIO_TYPE_SOCKET ||
+      BIO_get_fd(rbio, NULL) != fd) {
+    BIO *bio = BIO_new(BIO_s_socket());
     if (bio == NULL) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
       return 0;
     }
     BIO_set_fd(bio, fd, BIO_NOCLOSE);
-    SSL_set_bio(ssl, SSL_get_rbio(ssl), bio);
+    SSL_set0_wbio(ssl, bio);
   } else {
-    SSL_set_bio(ssl, SSL_get_rbio(ssl), SSL_get_rbio(ssl));
+    /* Copy the rbio over to the wbio. */
+    BIO_up_ref(rbio);
+    SSL_set0_wbio(ssl, rbio);
   }
 
   return 1;
 }
 
 int SSL_set_rfd(SSL *ssl, int fd) {
-  if (ssl->wbio == NULL || BIO_method_type(ssl->wbio) != BIO_TYPE_FD ||
-      BIO_get_fd(ssl->wbio, NULL) != fd) {
-    BIO *bio = BIO_new(BIO_s_fd());
+  BIO *wbio = SSL_get_wbio(ssl);
+  if (wbio == NULL || BIO_method_type(wbio) != BIO_TYPE_SOCKET ||
+      BIO_get_fd(wbio, NULL) != fd) {
+    BIO *bio = BIO_new(BIO_s_socket());
     if (bio == NULL) {
       OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
       return 0;
     }
     BIO_set_fd(bio, fd, BIO_NOCLOSE);
-    SSL_set_bio(ssl, bio, SSL_get_wbio(ssl));
+    SSL_set0_rbio(ssl, bio);
   } else {
-    SSL_set_bio(ssl, SSL_get_wbio(ssl), SSL_get_wbio(ssl));
+    /* Copy the wbio over to the rbio. */
+    BIO_up_ref(wbio);
+    SSL_set0_rbio(ssl, wbio);
   }
   return 1;
 }
 
-size_t SSL_get_finished(const SSL *ssl, void *buf, size_t count) {
-  size_t ret = 0;
+static size_t copy_finished(void *out, size_t out_len, const uint8_t *in,
+                            size_t in_len) {
+  if (out_len > in_len) {
+    out_len = in_len;
+  }
+  OPENSSL_memcpy(out, in, out_len);
+  return in_len;
+}
 
-  if (ssl->s3 != NULL) {
-    ret = ssl->s3->tmp.finish_md_len;
-    if (count > ret) {
-      count = ret;
-    }
-    memcpy(buf, ssl->s3->tmp.finish_md, count);
+size_t SSL_get_finished(const SSL *ssl, void *buf, size_t count) {
+  if (!ssl->s3->initial_handshake_complete ||
+      ssl3_protocol_version(ssl) < TLS1_VERSION ||
+      ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
+    return 0;
   }
 
-  return ret;
+  if (ssl->server) {
+    return copy_finished(buf, count, ssl->s3->previous_server_finished,
+                         ssl->s3->previous_server_finished_len);
+  }
+
+  return copy_finished(buf, count, ssl->s3->previous_client_finished,
+                       ssl->s3->previous_client_finished_len);
 }
 
 size_t SSL_get_peer_finished(const SSL *ssl, void *buf, size_t count) {
-  size_t ret = 0;
-
-  if (ssl->s3 != NULL) {
-    ret = ssl->s3->tmp.peer_finish_md_len;
-    if (count > ret) {
-      count = ret;
-    }
-    memcpy(buf, ssl->s3->tmp.peer_finish_md, count);
+  if (!ssl->s3->initial_handshake_complete ||
+      ssl3_protocol_version(ssl) < TLS1_VERSION ||
+      ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
+    return 0;
   }
 
-  return ret;
+  if (ssl->server) {
+    return copy_finished(buf, count, ssl->s3->previous_client_finished,
+                         ssl->s3->previous_client_finished_len);
+  }
+
+  return copy_finished(buf, count, ssl->s3->previous_server_finished,
+                       ssl->s3->previous_server_finished_len);
 }
 
 int SSL_get_verify_mode(const SSL *ssl) { return ssl->verify_mode; }
 
-int SSL_get_verify_depth(const SSL *ssl) {
-  return X509_VERIFY_PARAM_get_depth(ssl->param);
-}
-
 int SSL_get_extms_support(const SSL *ssl) {
-  return ssl->s3->tmp.extended_master_secret == 1;
-}
-
-int (*SSL_get_verify_callback(const SSL *ssl))(int, X509_STORE_CTX *) {
-  return ssl->verify_callback;
-}
-
-int SSL_CTX_get_verify_mode(const SSL_CTX *ctx) { return ctx->verify_mode; }
-
-int SSL_CTX_get_verify_depth(const SSL_CTX *ctx) {
-  return X509_VERIFY_PARAM_get_depth(ctx->param);
-}
-
-int (*SSL_CTX_get_verify_callback(const SSL_CTX *ctx))(
-    int ok, X509_STORE_CTX *store_ctx) {
-  return ctx->default_verify_callback;
-}
-
-void SSL_set_verify(SSL *ssl, int mode,
-                    int (*callback)(int ok, X509_STORE_CTX *store_ctx)) {
-  ssl->verify_mode = mode;
-  if (callback != NULL) {
-    ssl->verify_callback = callback;
+  /* TLS 1.3 does not require extended master secret and always reports as
+   * supporting it. */
+  if (!ssl->s3->have_version) {
+    return 0;
   }
-}
+  if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
+    return 1;
+  }
 
-void SSL_set_verify_depth(SSL *ssl, int depth) {
-  X509_VERIFY_PARAM_set_depth(ssl->param, depth);
+  /* If the initial handshake completed, query the established session. */
+  if (ssl->s3->established_session != NULL) {
+    return ssl->s3->established_session->extended_master_secret;
+  }
+
+  /* Otherwise, query the in-progress handshake. */
+  if (ssl->s3->hs != NULL) {
+    return ssl->s3->hs->extended_master_secret;
+  }
+  assert(0);
+  return 0;
 }
 
 int SSL_CTX_get_read_ahead(const SSL_CTX *ctx) { return 0; }
@@ -1123,32 +1268,12 @@
 
 /* Fix this so it checks all the valid key/cert options */
 int SSL_CTX_check_private_key(const SSL_CTX *ctx) {
-  if (ctx->cert->x509 == NULL) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_ASSIGNED);
-    return 0;
-  }
-
-  if (ctx->cert->privatekey == NULL) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_NO_PRIVATE_KEY_ASSIGNED);
-    return 0;
-  }
-
-  return X509_check_private_key(ctx->cert->x509, ctx->cert->privatekey);
+  return ssl_cert_check_private_key(ctx->cert, ctx->cert->privatekey);
 }
 
 /* Fix this function so that it takes an optional type parameter */
 int SSL_check_private_key(const SSL *ssl) {
-  if (ssl->cert->x509 == NULL) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_ASSIGNED);
-    return 0;
-  }
-
-  if (ssl->cert->privatekey == NULL) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_NO_PRIVATE_KEY_ASSIGNED);
-    return 0;
-  }
-
-  return X509_check_private_key(ssl->cert->x509, ssl->cert->privatekey);
+  return ssl_cert_check_private_key(ssl->cert, ssl->cert->privatekey);
 }
 
 long SSL_get_default_timeout(const SSL *ssl) {
@@ -1165,6 +1290,10 @@
   return SSL_in_init(ssl) && ssl->s3->initial_handshake_complete;
 }
 
+int SSL_total_renegotiations(const SSL *ssl) {
+  return ssl->s3->total_renegotiations;
+}
+
 size_t SSL_CTX_get_max_cert_list(const SSL_CTX *ctx) {
   return ctx->max_cert_list;
 }
@@ -1187,7 +1316,7 @@
   ssl->max_cert_list = (uint32_t)max_cert_list;
 }
 
-void SSL_CTX_set_max_send_fragment(SSL_CTX *ctx, size_t max_send_fragment) {
+int SSL_CTX_set_max_send_fragment(SSL_CTX *ctx, size_t max_send_fragment) {
   if (max_send_fragment < 512) {
     max_send_fragment = 512;
   }
@@ -1195,9 +1324,11 @@
     max_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH;
   }
   ctx->max_send_fragment = (uint16_t)max_send_fragment;
+
+  return 1;
 }
 
-void SSL_set_max_send_fragment(SSL *ssl, size_t max_send_fragment) {
+int SSL_set_max_send_fragment(SSL *ssl, size_t max_send_fragment) {
   if (max_send_fragment < 512) {
     max_send_fragment = 512;
   }
@@ -1205,10 +1336,12 @@
     max_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH;
   }
   ssl->max_send_fragment = (uint16_t)max_send_fragment;
+
+  return 1;
 }
 
 int SSL_set_mtu(SSL *ssl, unsigned mtu) {
-  if (!SSL_IS_DTLS(ssl) || mtu < dtls1_min_mtu()) {
+  if (!SSL_is_dtls(ssl) || mtu < dtls1_min_mtu()) {
     return 0;
   }
   ssl->d1->mtu = mtu;
@@ -1216,7 +1349,11 @@
 }
 
 int SSL_get_secure_renegotiation_support(const SSL *ssl) {
-  return ssl->s3->send_connection_binding;
+  if (!ssl->s3->have_version) {
+    return 0;
+  }
+  return ssl3_protocol_version(ssl) >= TLS1_3_VERSION ||
+         ssl->s3->send_connection_binding;
 }
 
 LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx) { return ctx->sessions; }
@@ -1245,64 +1382,127 @@
   return ctx->session_cache_mode;
 }
 
+
+int SSL_CTX_get_tlsext_ticket_keys(SSL_CTX *ctx, void *out, size_t len) {
+  if (out == NULL) {
+    return 48;
+  }
+  if (len != 48) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_TICKET_KEYS_LENGTH);
+    return 0;
+  }
+  uint8_t *out_bytes = out;
+  OPENSSL_memcpy(out_bytes, ctx->tlsext_tick_key_name, 16);
+  OPENSSL_memcpy(out_bytes + 16, ctx->tlsext_tick_hmac_key, 16);
+  OPENSSL_memcpy(out_bytes + 32, ctx->tlsext_tick_aes_key, 16);
+  return 1;
+}
+
+int SSL_CTX_set_tlsext_ticket_keys(SSL_CTX *ctx, const void *in, size_t len) {
+  if (in == NULL) {
+    return 48;
+  }
+  if (len != 48) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_TICKET_KEYS_LENGTH);
+    return 0;
+  }
+  const uint8_t *in_bytes = in;
+  OPENSSL_memcpy(ctx->tlsext_tick_key_name, in_bytes, 16);
+  OPENSSL_memcpy(ctx->tlsext_tick_hmac_key, in_bytes + 16, 16);
+  OPENSSL_memcpy(ctx->tlsext_tick_aes_key, in_bytes + 32, 16);
+  return 1;
+}
+
+int SSL_CTX_set_tlsext_ticket_key_cb(
+    SSL_CTX *ctx, int (*callback)(SSL *ssl, uint8_t *key_name, uint8_t *iv,
+                                  EVP_CIPHER_CTX *ctx, HMAC_CTX *hmac_ctx,
+                                  int encrypt)) {
+  ctx->tlsext_ticket_key_cb = callback;
+  return 1;
+}
+
+int SSL_CTX_set1_curves(SSL_CTX *ctx, const int *curves, size_t curves_len) {
+  return tls1_set_curves(&ctx->supported_group_list,
+                         &ctx->supported_group_list_len, curves,
+                         curves_len);
+}
+
+int SSL_set1_curves(SSL *ssl, const int *curves, size_t curves_len) {
+  return tls1_set_curves(&ssl->supported_group_list,
+                         &ssl->supported_group_list_len, curves,
+                         curves_len);
+}
+
+int SSL_CTX_set1_curves_list(SSL_CTX *ctx, const char *curves) {
+  return tls1_set_curves_list(&ctx->supported_group_list,
+                              &ctx->supported_group_list_len, curves);
+}
+
+int SSL_set1_curves_list(SSL *ssl, const char *curves) {
+  return tls1_set_curves_list(&ssl->supported_group_list,
+                              &ssl->supported_group_list_len, curves);
+}
+
+uint16_t SSL_get_curve_id(const SSL *ssl) {
+  /* TODO(davidben): This checks the wrong session if there is a renegotiation in
+   * progress. */
+  SSL_SESSION *session = SSL_get_session(ssl);
+  if (session == NULL) {
+    return 0;
+  }
+
+  return session->group_id;
+}
+
+int SSL_CTX_set_tmp_dh(SSL_CTX *ctx, const DH *dh) {
+  DH_free(ctx->cert->dh_tmp);
+  ctx->cert->dh_tmp = DHparams_dup(dh);
+  if (ctx->cert->dh_tmp == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_DH_LIB);
+    return 0;
+  }
+  return 1;
+}
+
+int SSL_set_tmp_dh(SSL *ssl, const DH *dh) {
+  DH_free(ssl->cert->dh_tmp);
+  ssl->cert->dh_tmp = DHparams_dup(dh);
+  if (ssl->cert->dh_tmp == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_DH_LIB);
+    return 0;
+  }
+  return 1;
+}
+
+OPENSSL_EXPORT STACK_OF(SSL_CIPHER) *SSL_CTX_get_ciphers(const SSL_CTX *ctx) {
+  return ctx->cipher_list->ciphers;
+}
+
 STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *ssl) {
   if (ssl == NULL) {
     return NULL;
   }
 
-  if (ssl->cipher_list != NULL) {
-    return ssl->cipher_list->ciphers;
-  }
-
-  if (ssl->version >= TLS1_1_VERSION && ssl->ctx != NULL &&
-      ssl->ctx->cipher_list_tls11 != NULL) {
-    return ssl->ctx->cipher_list_tls11->ciphers;
-  }
-
-  if (ssl->version >= TLS1_VERSION && ssl->ctx != NULL &&
-      ssl->ctx->cipher_list_tls10 != NULL) {
-    return ssl->ctx->cipher_list_tls10->ciphers;
-  }
-
-  if (ssl->ctx != NULL && ssl->ctx->cipher_list != NULL) {
-    return ssl->ctx->cipher_list->ciphers;
-  }
-
-  return NULL;
-}
-
-/* return a STACK of the ciphers available for the SSL and in order of
- * algorithm id */
-STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *ssl) {
-  if (ssl == NULL) {
+  const struct ssl_cipher_preference_list_st *prefs =
+      ssl_get_cipher_preferences(ssl);
+  if (prefs == NULL) {
     return NULL;
   }
 
-  if (ssl->cipher_list_by_id != NULL) {
-    return ssl->cipher_list_by_id;
-  }
-
-  if (ssl->ctx != NULL && ssl->ctx->cipher_list_by_id != NULL) {
-    return ssl->ctx->cipher_list_by_id;
-  }
-
-  return NULL;
+  return prefs->ciphers;
 }
 
 const char *SSL_get_cipher_list(const SSL *ssl, int n) {
-  const SSL_CIPHER *c;
-  STACK_OF(SSL_CIPHER) *sk;
-
   if (ssl == NULL) {
     return NULL;
   }
 
-  sk = SSL_get_ciphers(ssl);
+  STACK_OF(SSL_CIPHER) *sk = SSL_get_ciphers(ssl);
   if (sk == NULL || n < 0 || (size_t)n >= sk_SSL_CIPHER_num(sk)) {
     return NULL;
   }
 
-  c = sk_SSL_CIPHER_value(sk, n);
+  const SSL_CIPHER *c = sk_SSL_CIPHER_value(sk, n);
   if (c == NULL) {
     return NULL;
   }
@@ -1311,133 +1511,23 @@
 }
 
 int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str) {
-  STACK_OF(SSL_CIPHER) *cipher_list = ssl_create_cipher_list(
-      ctx->method, &ctx->cipher_list, &ctx->cipher_list_by_id, str);
-  if (cipher_list == NULL) {
-    return 0;
-  }
-
-  /* |ssl_create_cipher_list| may succeed but return an empty cipher list. */
-  if (sk_SSL_CIPHER_num(cipher_list) == 0) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CIPHER_MATCH);
-    return 0;
-  }
-
-  return 1;
+  return ssl_create_cipher_list(ctx->method, &ctx->cipher_list, str,
+                                0 /* not strict */);
 }
 
-int SSL_CTX_set_cipher_list_tls10(SSL_CTX *ctx, const char *str) {
-  STACK_OF(SSL_CIPHER) *cipher_list = ssl_create_cipher_list(
-      ctx->method, &ctx->cipher_list_tls10, NULL, str);
-  if (cipher_list == NULL) {
-    return 0;
-  }
-
-  /* |ssl_create_cipher_list| may succeed but return an empty cipher list. */
-  if (sk_SSL_CIPHER_num(cipher_list) == 0) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CIPHER_MATCH);
-    return 0;
-  }
-
-  return 1;
-}
-
-int SSL_CTX_set_cipher_list_tls11(SSL_CTX *ctx, const char *str) {
-  STACK_OF(SSL_CIPHER) *cipher_list = ssl_create_cipher_list(
-      ctx->method, &ctx->cipher_list_tls11, NULL, str);
-  if (cipher_list == NULL) {
-    return 0;
-  }
-
-  /* |ssl_create_cipher_list| may succeed but return an empty cipher list. */
-  if (sk_SSL_CIPHER_num(cipher_list) == 0) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CIPHER_MATCH);
-    return 0;
-  }
-
-  return 1;
+int SSL_CTX_set_strict_cipher_list(SSL_CTX *ctx, const char *str) {
+  return ssl_create_cipher_list(ctx->method, &ctx->cipher_list, str,
+                                1 /* strict */);
 }
 
 int SSL_set_cipher_list(SSL *ssl, const char *str) {
-  STACK_OF(SSL_CIPHER) *cipher_list = ssl_create_cipher_list(
-      ssl->ctx->method, &ssl->cipher_list, &ssl->cipher_list_by_id, str);
-  if (cipher_list == NULL) {
-    return 0;
-  }
-
-  /* |ssl_create_cipher_list| may succeed but return an empty cipher list. */
-  if (sk_SSL_CIPHER_num(cipher_list) == 0) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CIPHER_MATCH);
-    return 0;
-  }
-
-  return 1;
+  return ssl_create_cipher_list(ssl->ctx->method, &ssl->cipher_list, str,
+                                0 /* not strict */);
 }
 
-STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *ssl, const CBS *cbs) {
-  CBS cipher_suites = *cbs;
-  const SSL_CIPHER *c;
-  STACK_OF(SSL_CIPHER) *sk;
-
-  if (ssl->s3) {
-    ssl->s3->send_connection_binding = 0;
-  }
-
-  if (CBS_len(&cipher_suites) % 2 != 0) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST);
-    return NULL;
-  }
-
-  sk = sk_SSL_CIPHER_new_null();
-  if (sk == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-    goto err;
-  }
-
-  while (CBS_len(&cipher_suites) > 0) {
-    uint16_t cipher_suite;
-
-    if (!CBS_get_u16(&cipher_suites, &cipher_suite)) {
-      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-      goto err;
-    }
-
-    /* Check for SCSV. */
-    if (ssl->s3 && cipher_suite == (SSL3_CK_SCSV & 0xffff)) {
-      /* SCSV is fatal if renegotiating. */
-      if (ssl->s3->initial_handshake_complete) {
-        OPENSSL_PUT_ERROR(SSL, SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING);
-        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
-        goto err;
-      }
-      ssl->s3->send_connection_binding = 1;
-      continue;
-    }
-
-    /* Check for FALLBACK_SCSV. */
-    if (ssl->s3 && cipher_suite == (SSL3_CK_FALLBACK_SCSV & 0xffff)) {
-      uint16_t max_version = ssl3_get_max_server_version(ssl);
-      if (SSL_IS_DTLS(ssl) ? (uint16_t)ssl->version > max_version
-                         : (uint16_t)ssl->version < max_version) {
-        OPENSSL_PUT_ERROR(SSL, SSL_R_INAPPROPRIATE_FALLBACK);
-        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL3_AD_INAPPROPRIATE_FALLBACK);
-        goto err;
-      }
-      continue;
-    }
-
-    c = SSL_get_cipher_by_value(cipher_suite);
-    if (c != NULL && !sk_SSL_CIPHER_push(sk, c)) {
-      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-      goto err;
-    }
-  }
-
-  return sk;
-
-err:
-  sk_SSL_CIPHER_free(sk);
-  return NULL;
+int SSL_set_strict_cipher_list(SSL *ssl, const char *str) {
+  return ssl_create_cipher_list(ssl->ctx->method, &ssl->cipher_list, str,
+                                1 /* strict */);
 }
 
 const char *SSL_get_servername(const SSL *ssl, const int type) {
@@ -1451,41 +1541,53 @@
     return ssl->tlsext_hostname;
   }
 
-  if (ssl->session == NULL) {
+  /* During the handshake, report the handshake value. */
+  if (ssl->s3->hs != NULL) {
+    return ssl->s3->hs->hostname;
+  }
+
+  /* SSL_get_servername may also be called after the handshake to look up the
+   * SNI value.
+   *
+   * TODO(davidben): This is almost unused. Can we remove it? */
+  SSL_SESSION *session = SSL_get_session(ssl);
+  if (session == NULL) {
     return NULL;
   }
-  return ssl->session->tlsext_hostname;
+  return session->tlsext_hostname;
 }
 
 int SSL_get_servername_type(const SSL *ssl) {
-  if (ssl->session != NULL && ssl->session->tlsext_hostname != NULL) {
-    return TLSEXT_NAMETYPE_host_name;
+  SSL_SESSION *session = SSL_get_session(ssl);
+  if (session == NULL || session->tlsext_hostname == NULL) {
+    return -1;
   }
-
-  return -1;
+  return TLSEXT_NAMETYPE_host_name;
 }
 
 void SSL_CTX_enable_signed_cert_timestamps(SSL_CTX *ctx) {
   ctx->signed_cert_timestamps_enabled = 1;
 }
 
-int SSL_enable_signed_cert_timestamps(SSL *ssl) {
+void SSL_CTX_i_promise_to_verify_certs_after_the_handshake(SSL_CTX *ctx) {
+  ctx->i_promise_to_verify_certs_after_the_handshake = 1;
+}
+
+void SSL_enable_signed_cert_timestamps(SSL *ssl) {
   ssl->signed_cert_timestamps_enabled = 1;
-  return 1;
 }
 
 void SSL_CTX_enable_ocsp_stapling(SSL_CTX *ctx) {
   ctx->ocsp_stapling_enabled = 1;
 }
 
-int SSL_enable_ocsp_stapling(SSL *ssl) {
+void SSL_enable_ocsp_stapling(SSL *ssl) {
   ssl->ocsp_stapling_enabled = 1;
-  return 1;
 }
 
 void SSL_get0_signed_cert_timestamp_list(const SSL *ssl, const uint8_t **out,
                                          size_t *out_len) {
-  SSL_SESSION *session = ssl->session;
+  SSL_SESSION *session = SSL_get_session(ssl);
 
   *out_len = 0;
   *out = NULL;
@@ -1499,7 +1601,7 @@
 
 void SSL_get0_ocsp_response(const SSL *ssl, const uint8_t **out,
                             size_t *out_len) {
-  SSL_SESSION *session = ssl->session;
+  SSL_SESSION *session = SSL_get_session(ssl);
 
   *out_len = 0;
   *out = NULL;
@@ -1510,31 +1612,35 @@
   *out_len = session->ocsp_response_length;
 }
 
-int SSL_CTX_set_signed_cert_timestamp_list(SSL_CTX *ctx, const uint8_t *list,
-                                           size_t list_len) {
-  OPENSSL_free(ctx->signed_cert_timestamp_list);
-  ctx->signed_cert_timestamp_list_length = 0;
+int SSL_set_tlsext_host_name(SSL *ssl, const char *name) {
+  OPENSSL_free(ssl->tlsext_hostname);
+  ssl->tlsext_hostname = NULL;
 
-  ctx->signed_cert_timestamp_list = BUF_memdup(list, list_len);
-  if (ctx->signed_cert_timestamp_list == NULL) {
+  if (name == NULL) {
+    return 1;
+  }
+
+  size_t len = strlen(name);
+  if (len == 0 || len > TLSEXT_MAXLEN_host_name) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_SSL3_EXT_INVALID_SERVERNAME);
     return 0;
   }
-  ctx->signed_cert_timestamp_list_length = list_len;
-
+  ssl->tlsext_hostname = BUF_strdup(name);
+  if (ssl->tlsext_hostname == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+    return 0;
+  }
   return 1;
 }
 
-int SSL_CTX_set_ocsp_response(SSL_CTX *ctx, const uint8_t *response,
-                              size_t response_len) {
-  OPENSSL_free(ctx->ocsp_response);
-  ctx->ocsp_response_length = 0;
+int SSL_CTX_set_tlsext_servername_callback(
+    SSL_CTX *ctx, int (*callback)(SSL *ssl, int *out_alert, void *arg)) {
+  ctx->tlsext_servername_callback = callback;
+  return 1;
+}
 
-  ctx->ocsp_response = BUF_memdup(response, response_len);
-  if (ctx->ocsp_response == NULL) {
-    return 0;
-  }
-  ctx->ocsp_response_length = response_len;
-
+int SSL_CTX_set_tlsext_servername_arg(SSL_CTX *ctx, void *arg) {
+  ctx->tlsext_servername_arg = arg;
   return 1;
 }
 
@@ -1549,7 +1655,7 @@
   for (i = 0; i < server_len;) {
     for (j = 0; j < client_len;) {
       if (server[i] == client[j] &&
-          memcmp(&server[i + 1], &client[j + 1], server[i]) == 0) {
+          OPENSSL_memcmp(&server[i + 1], &client[j + 1], server[i]) == 0) {
         /* We found a match */
         result = &server[i];
         status = OPENSSL_NPN_NEGOTIATED;
@@ -1574,11 +1680,11 @@
 
 void SSL_get0_next_proto_negotiated(const SSL *ssl, const uint8_t **out_data,
                                     unsigned *out_len) {
-  *out_data = ssl->next_proto_negotiated;
+  *out_data = ssl->s3->next_proto_negotiated;
   if (*out_data == NULL) {
     *out_len = 0;
   } else {
-    *out_len = ssl->next_proto_negotiated_len;
+    *out_len = ssl->s3->next_proto_negotiated_len;
   }
 }
 
@@ -1643,112 +1749,83 @@
   }
 }
 
-int SSL_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len,
-                               const char *label, size_t label_len,
-                               const uint8_t *context, size_t context_len,
-                               int use_context) {
-  if (ssl->version < TLS1_VERSION) {
+
+void SSL_CTX_set_tls_channel_id_enabled(SSL_CTX *ctx, int enabled) {
+  ctx->tlsext_channel_id_enabled = !!enabled;
+}
+
+int SSL_CTX_enable_tls_channel_id(SSL_CTX *ctx) {
+  SSL_CTX_set_tls_channel_id_enabled(ctx, 1);
+  return 1;
+}
+
+void SSL_set_tls_channel_id_enabled(SSL *ssl, int enabled) {
+  ssl->tlsext_channel_id_enabled = !!enabled;
+}
+
+int SSL_enable_tls_channel_id(SSL *ssl) {
+  SSL_set_tls_channel_id_enabled(ssl, 1);
+  return 1;
+}
+
+static int is_p256_key(EVP_PKEY *private_key) {
+  const EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(private_key);
+  return ec_key != NULL &&
+         EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key)) ==
+             NID_X9_62_prime256v1;
+}
+
+int SSL_CTX_set1_tls_channel_id(SSL_CTX *ctx, EVP_PKEY *private_key) {
+  if (!is_p256_key(private_key)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_CHANNEL_ID_NOT_P256);
     return 0;
   }
 
-  return ssl->enc_method->export_keying_material(
-      ssl, out, out_len, label, label_len, context, context_len, use_context);
+  EVP_PKEY_free(ctx->tlsext_channel_id_private);
+  EVP_PKEY_up_ref(private_key);
+  ctx->tlsext_channel_id_private = private_key;
+  ctx->tlsext_channel_id_enabled = 1;
+
+  return 1;
 }
 
-void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx,
-                                      int (*cb)(X509_STORE_CTX *store_ctx,
-                                                void *arg),
-                                      void *arg) {
-  ctx->app_verify_callback = cb;
-  ctx->app_verify_arg = arg;
-}
-
-void SSL_CTX_set_verify(SSL_CTX *ctx, int mode,
-                        int (*cb)(int, X509_STORE_CTX *)) {
-  ctx->verify_mode = mode;
-  ctx->default_verify_callback = cb;
-}
-
-void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth) {
-  X509_VERIFY_PARAM_set_depth(ctx->param, depth);
-}
-
-void SSL_CTX_set_cert_cb(SSL_CTX *ctx, int (*cb)(SSL *ssl, void *arg),
-                         void *arg) {
-  ssl_cert_set_cert_cb(ctx->cert, cb, arg);
-}
-
-void SSL_set_cert_cb(SSL *ssl, int (*cb)(SSL *ssl, void *arg), void *arg) {
-  ssl_cert_set_cert_cb(ssl->cert, cb, arg);
-}
-
-void ssl_get_compatible_server_ciphers(SSL *ssl, uint32_t *out_mask_k,
-                                       uint32_t *out_mask_a) {
-  CERT *c = ssl->cert;
-  int have_rsa_cert = 0, dh_tmp;
-  uint32_t mask_k, mask_a;
-  int have_ecc_cert = 0, ecdsa_ok;
-  X509 *x;
-
-  dh_tmp = (c->dh_tmp != NULL || c->dh_tmp_cb != NULL);
-
-  if (ssl->cert->x509 != NULL && ssl_has_private_key(ssl)) {
-    if (ssl_private_key_type(ssl) == EVP_PKEY_RSA) {
-      have_rsa_cert = 1;
-    } else if (ssl_private_key_type(ssl) == EVP_PKEY_EC) {
-      have_ecc_cert = 1;
-    }
+int SSL_set1_tls_channel_id(SSL *ssl, EVP_PKEY *private_key) {
+  if (!is_p256_key(private_key)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_CHANNEL_ID_NOT_P256);
+    return 0;
   }
 
-  mask_k = 0;
-  mask_a = 0;
+  EVP_PKEY_free(ssl->tlsext_channel_id_private);
+  EVP_PKEY_up_ref(private_key);
+  ssl->tlsext_channel_id_private = private_key;
+  ssl->tlsext_channel_id_enabled = 1;
 
-  if (dh_tmp) {
-    mask_k |= SSL_kDHE;
-  }
-  if (have_rsa_cert) {
-    mask_k |= SSL_kRSA;
-    mask_a |= SSL_aRSA;
-  }
-
-  /* An ECC certificate may be usable for ECDSA cipher suites depending on the
-   * key usage extension and on the client's curve preferences. */
-  if (have_ecc_cert) {
-    x = c->x509;
-    /* This call populates extension flags (ex_flags). */
-    X509_check_purpose(x, -1, 0);
-    ecdsa_ok = (x->ex_flags & EXFLAG_KUSAGE)
-                   ? (x->ex_kusage & X509v3_KU_DIGITAL_SIGNATURE)
-                   : 1;
-    if (!tls1_check_ec_cert(ssl, x)) {
-      ecdsa_ok = 0;
-    }
-    if (ecdsa_ok) {
-      mask_a |= SSL_aECDSA;
-    }
-  }
-
-  /* If we are considering an ECC cipher suite that uses an ephemeral EC
-   * key, check for a shared curve. */
-  uint16_t unused;
-  if (tls1_get_shared_curve(ssl, &unused)) {
-    mask_k |= SSL_kECDHE;
-  }
-
-  /* PSK requires a server callback. */
-  if (ssl->psk_server_callback != NULL) {
-    mask_k |= SSL_kPSK;
-    mask_a |= SSL_aPSK;
-  }
-
-  *out_mask_k = mask_k;
-  *out_mask_a = mask_a;
+  return 1;
 }
 
-void ssl_update_cache(SSL *ssl, int mode) {
-  SSL_CTX *ctx = ssl->initial_ctx;
+size_t SSL_get_tls_channel_id(SSL *ssl, uint8_t *out, size_t max_out) {
+  if (!ssl->s3->tlsext_channel_id_valid) {
+    return 0;
+  }
+  OPENSSL_memcpy(out, ssl->s3->tlsext_channel_id,
+                 (max_out < 64) ? max_out : 64);
+  return 64;
+}
+
+size_t SSL_get0_certificate_types(SSL *ssl, const uint8_t **out_types) {
+  if (ssl->server || ssl->s3->hs == NULL) {
+    *out_types = NULL;
+    return 0;
+  }
+  *out_types = ssl->s3->hs->certificate_types;
+  return ssl->s3->hs->num_certificate_types;
+}
+
+void ssl_update_cache(SSL_HANDSHAKE *hs, int mode) {
+  SSL *const ssl = hs->ssl;
+  SSL_CTX *ctx = ssl->session_ctx;
   /* Never cache sessions with empty session IDs. */
-  if (ssl->session->session_id_length == 0 ||
+  if (ssl->s3->established_session->session_id_length == 0 ||
       (ctx->session_cache_mode & mode) != mode) {
     return;
   }
@@ -1760,14 +1837,17 @@
   /* A client may see new sessions on abbreviated handshakes if the server
    * decides to renew the ticket. Once the handshake is completed, it should be
    * inserted into the cache. */
-  if (!ssl->hit || (!ssl->server && ssl->tlsext_ticket_expected)) {
+  if (ssl->s3->established_session != ssl->session ||
+      (!ssl->server && hs->ticket_expected)) {
     if (use_internal_cache) {
-      SSL_CTX_add_session(ctx, ssl->session);
+      SSL_CTX_add_session(ctx, ssl->s3->established_session);
     }
-    if (ctx->new_session_cb != NULL &&
-        !ctx->new_session_cb(ssl, SSL_SESSION_up_ref(ssl->session))) {
-      /* |new_session_cb|'s return value signals whether it took ownership. */
-      SSL_SESSION_free(ssl->session);
+    if (ctx->new_session_cb != NULL) {
+      SSL_SESSION_up_ref(ssl->s3->established_session);
+      if (!ctx->new_session_cb(ssl, ssl->s3->established_session)) {
+        /* |new_session_cb|'s return value signals whether it took ownership. */
+        SSL_SESSION_free(ssl->s3->established_session);
+      }
     }
   }
 
@@ -1781,16 +1861,22 @@
       flush_cache = 1;
       ctx->handshakes_since_cache_flush = 0;
     }
-    CRYPTO_MUTEX_unlock(&ctx->lock);
+    CRYPTO_MUTEX_unlock_write(&ctx->lock);
 
     if (flush_cache) {
-      SSL_CTX_flush_sessions(ctx, (unsigned long)time(NULL));
+      struct OPENSSL_timeval now;
+      ssl_get_current_time(ssl, &now);
+      SSL_CTX_flush_sessions(ctx, now.tv_sec);
     }
   }
 }
 
 static const char *ssl_get_version(int version) {
   switch (version) {
+    /* Report TLS 1.3 draft version as TLS 1.3 in the public API. */
+    case TLS1_3_DRAFT_VERSION:
+      return "TLSv1.3";
+
     case TLS1_2_VERSION:
       return "TLSv1.2";
 
@@ -1822,21 +1908,6 @@
   return ssl_get_version(session->ssl_version);
 }
 
-void ssl_clear_cipher_ctx(SSL *ssl) {
-  SSL_AEAD_CTX_free(ssl->aead_read_ctx);
-  ssl->aead_read_ctx = NULL;
-  SSL_AEAD_CTX_free(ssl->aead_write_ctx);
-  ssl->aead_write_ctx = NULL;
-}
-
-X509 *SSL_get_certificate(const SSL *ssl) {
-  if (ssl->cert != NULL) {
-    return ssl->cert->x509;
-  }
-
-  return NULL;
-}
-
 EVP_PKEY *SSL_get_privatekey(const SSL *ssl) {
   if (ssl->cert != NULL) {
     return ssl->cert->privatekey;
@@ -1845,14 +1916,6 @@
   return NULL;
 }
 
-X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx) {
-  if (ctx->cert != NULL) {
-    return ctx->cert->x509;
-  }
-
-  return NULL;
-}
-
 EVP_PKEY *SSL_CTX_get0_privatekey(const SSL_CTX *ctx) {
   if (ctx->cert != NULL) {
     return ctx->cert->privatekey;
@@ -1862,64 +1925,21 @@
 }
 
 const SSL_CIPHER *SSL_get_current_cipher(const SSL *ssl) {
-  if (ssl->aead_write_ctx == NULL) {
+  if (ssl->s3->aead_write_ctx == NULL) {
     return NULL;
   }
-  return ssl->aead_write_ctx->cipher;
+  return ssl->s3->aead_write_ctx->cipher;
+}
+
+int SSL_session_reused(const SSL *ssl) {
+  return ssl->s3->session_reused;
 }
 
 const COMP_METHOD *SSL_get_current_compression(SSL *ssl) { return NULL; }
 
 const COMP_METHOD *SSL_get_current_expansion(SSL *ssl) { return NULL; }
 
-int ssl_init_wbio_buffer(SSL *ssl, int push) {
-  BIO *bbio;
-
-  if (ssl->bbio == NULL) {
-    bbio = BIO_new(BIO_f_buffer());
-    if (bbio == NULL) {
-      return 0;
-    }
-    ssl->bbio = bbio;
-  } else {
-    bbio = ssl->bbio;
-    if (ssl->bbio == ssl->wbio) {
-      ssl->wbio = BIO_pop(ssl->wbio);
-    }
-  }
-
-  BIO_reset(bbio);
-  if (!BIO_set_read_buffer_size(bbio, 1)) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_BUF_LIB);
-    return 0;
-  }
-
-  if (push) {
-    if (ssl->wbio != bbio) {
-      ssl->wbio = BIO_push(bbio, ssl->wbio);
-    }
-  } else {
-    if (ssl->wbio == bbio) {
-      ssl->wbio = BIO_pop(bbio);
-    }
-  }
-
-  return 1;
-}
-
-void ssl_free_wbio_buffer(SSL *ssl) {
-  if (ssl->bbio == NULL) {
-    return;
-  }
-
-  if (ssl->bbio == ssl->wbio) {
-    /* remove buffering */
-    ssl->wbio = BIO_pop(ssl->wbio);
-  }
-
-  BIO_free(ssl->bbio);
-  ssl->bbio = NULL;
-}
+int *SSL_get_server_tmp_key(SSL *ssl, EVP_PKEY **out_key) { return 0; }
 
 void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx, int mode) {
   ctx->quiet_shutdown = (mode != 0);
@@ -1938,14 +1958,41 @@
 void SSL_set_shutdown(SSL *ssl, int mode) {
   /* It is an error to clear any bits that have already been set. (We can't try
    * to get a second close_notify or send two.) */
-  assert((ssl->shutdown & mode) == ssl->shutdown);
+  assert((SSL_get_shutdown(ssl) & mode) == SSL_get_shutdown(ssl));
 
-  ssl->shutdown |= mode;
+  if (mode & SSL_RECEIVED_SHUTDOWN &&
+      ssl->s3->recv_shutdown == ssl_shutdown_none) {
+    ssl->s3->recv_shutdown = ssl_shutdown_close_notify;
+  }
+
+  if (mode & SSL_SENT_SHUTDOWN &&
+      ssl->s3->send_shutdown == ssl_shutdown_none) {
+    ssl->s3->send_shutdown = ssl_shutdown_close_notify;
+  }
 }
 
-int SSL_get_shutdown(const SSL *ssl) { return ssl->shutdown; }
+int SSL_get_shutdown(const SSL *ssl) {
+  int ret = 0;
+  if (ssl->s3->recv_shutdown != ssl_shutdown_none) {
+    /* Historically, OpenSSL set |SSL_RECEIVED_SHUTDOWN| on both close_notify
+     * and fatal alert. */
+    ret |= SSL_RECEIVED_SHUTDOWN;
+  }
+  if (ssl->s3->send_shutdown == ssl_shutdown_close_notify) {
+    /* Historically, OpenSSL set |SSL_SENT_SHUTDOWN| on only close_notify. */
+    ret |= SSL_SENT_SHUTDOWN;
+  }
+  return ret;
+}
 
-int SSL_version(const SSL *ssl) { return ssl->version; }
+int SSL_version(const SSL *ssl) {
+  /* Report TLS 1.3 draft version as TLS 1.3 in the public API. */
+  if (ssl->version == TLS1_3_DRAFT_VERSION) {
+    return TLS1_3_VERSION;
+  }
+
+  return ssl->version;
+}
 
 SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl) { return ssl->ctx; }
 
@@ -1954,33 +2001,26 @@
     return ssl->ctx;
   }
 
+  /* One cannot change the X.509 callbacks during a connection. */
+  if (ssl->ctx->x509_method != ctx->x509_method) {
+    assert(0);
+    return NULL;
+  }
+
   if (ctx == NULL) {
-    ctx = ssl->initial_ctx;
+    ctx = ssl->session_ctx;
   }
 
   ssl_cert_free(ssl->cert);
   ssl->cert = ssl_cert_dup(ctx->cert);
 
-  CRYPTO_refcount_inc(&ctx->references);
-  SSL_CTX_free(ssl->ctx); /* decrement reference count */
+  SSL_CTX_up_ref(ctx);
+  SSL_CTX_free(ssl->ctx);
   ssl->ctx = ctx;
 
-  ssl->sid_ctx_length = ctx->sid_ctx_length;
-  assert(ssl->sid_ctx_length <= sizeof(ssl->sid_ctx));
-  memcpy(ssl->sid_ctx, ctx->sid_ctx, sizeof(ssl->sid_ctx));
-
   return ssl->ctx;
 }
 
-int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx) {
-  return X509_STORE_set_default_paths(ctx->cert_store);
-}
-
-int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *ca_file,
-                                  const char *ca_dir) {
-  return X509_STORE_load_locations(ctx->cert_store, ca_file, ca_dir);
-}
-
 void SSL_set_info_callback(SSL *ssl,
                            void (*cb)(const SSL *ssl, int type, int value)) {
   ssl->info_callback = cb;
@@ -1991,16 +2031,20 @@
   return ssl->info_callback;
 }
 
-int SSL_state(const SSL *ssl) { return ssl->state; }
+int SSL_state(const SSL *ssl) {
+  return SSL_in_init(ssl) ? SSL_ST_INIT : SSL_ST_OK;
+}
 
 void SSL_set_state(SSL *ssl, int state) { }
 
-void SSL_set_verify_result(SSL *ssl, long result) {
-  ssl->verify_result = result;
+char *SSL_get_shared_ciphers(const SSL *ssl, char *buf, int len) {
+  if (len <= 0) {
+    return NULL;
+  }
+  buf[0] = '\0';
+  return buf;
 }
 
-long SSL_get_verify_result(const SSL *ssl) { return ssl->verify_result; }
-
 int SSL_get_ex_new_index(long argl, void *argp, CRYPTO_EX_unused *unused,
                          CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func) {
   int index;
@@ -2038,15 +2082,6 @@
   return CRYPTO_get_ex_data(&ctx->ex_data, idx);
 }
 
-X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *ctx) {
-  return ctx->cert_store;
-}
-
-void SSL_CTX_set_cert_store(SSL_CTX *ctx, X509_STORE *store) {
-  X509_STORE_free(ctx->cert_store);
-  ctx->cert_store = store;
-}
-
 int SSL_want(const SSL *ssl) { return ssl->rwstate; }
 
 void SSL_CTX_set_tmp_rsa_callback(SSL_CTX *ctx,
@@ -2103,7 +2138,11 @@
   OPENSSL_free(ssl->psk_identity_hint);
   ssl->psk_identity_hint = NULL;
 
-  if (identity_hint != NULL) {
+  /* Treat the empty hint as not supplying one. Plain PSK makes it possible to
+   * send either no hint (omit ServerKeyExchange) or an empty hint, while
+   * ECDHE_PSK can only spell empty hint. Having different capabilities is odd,
+   * so we interpret empty and missing as identical. */
+  if (identity_hint != NULL && identity_hint[0] != '\0') {
     ssl->psk_identity_hint = BUF_strdup(identity_hint);
     if (ssl->psk_identity_hint == NULL) {
       return 0;
@@ -2121,11 +2160,14 @@
 }
 
 const char *SSL_get_psk_identity(const SSL *ssl) {
-  if (ssl == NULL || ssl->session == NULL) {
+  if (ssl == NULL) {
     return NULL;
   }
-
-  return ssl->session->psk_identity;
+  SSL_SESSION *session = SSL_get_session(ssl);
+  if (session == NULL) {
+    return NULL;
+  }
+  return session->psk_identity;
 }
 
 void SSL_set_psk_client_callback(
@@ -2181,16 +2223,26 @@
   ctx->keylog_callback = cb;
 }
 
+void (*SSL_CTX_get_keylog_callback(const SSL_CTX *ctx))(const SSL *ssl,
+                                                        const char *line) {
+  return ctx->keylog_callback;
+}
+
+void SSL_CTX_set_current_time_cb(SSL_CTX *ctx,
+                                 void (*cb)(const SSL *ssl,
+                                            struct timeval *out_clock)) {
+  ctx->current_time_cb = cb;
+}
+
 static int cbb_add_hex(CBB *cbb, const uint8_t *in, size_t in_len) {
   static const char hextable[] = "0123456789abcdef";
   uint8_t *out;
-  size_t i;
 
   if (!CBB_add_space(cbb, &out, in_len * 2)) {
     return 0;
   }
 
-  for (i = 0; i < in_len; i++) {
+  for (size_t i = 0; i < in_len; i++) {
     *(out++) = (uint8_t)hextable[in[i] >> 4];
     *(out++) = (uint8_t)hextable[in[i] & 0xf];
   }
@@ -2198,61 +2250,22 @@
   return 1;
 }
 
-int ssl_log_rsa_client_key_exchange(const SSL *ssl,
-                                    const uint8_t *encrypted_premaster,
-                                    size_t encrypted_premaster_len,
-                                    const uint8_t *premaster,
-                                    size_t premaster_len) {
+int ssl_log_secret(const SSL *ssl, const char *label, const uint8_t *secret,
+                   size_t secret_len) {
   if (ssl->ctx->keylog_callback == NULL) {
     return 1;
   }
 
-  if (encrypted_premaster_len < 8) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    return 0;
-  }
-
   CBB cbb;
   uint8_t *out;
   size_t out_len;
-  if (!CBB_init(&cbb, 4 + 16 + 1 + premaster_len * 2 + 1) ||
-      !CBB_add_bytes(&cbb, (const uint8_t *)"RSA ", 4) ||
-      /* Only the first 8 bytes of the encrypted premaster secret are
-       * logged. */
-      !cbb_add_hex(&cbb, encrypted_premaster, 8) ||
+  if (!CBB_init(&cbb, strlen(label) + 1 + SSL3_RANDOM_SIZE * 2 + 1 +
+                          secret_len * 2 + 1) ||
+      !CBB_add_bytes(&cbb, (const uint8_t *)label, strlen(label)) ||
       !CBB_add_bytes(&cbb, (const uint8_t *)" ", 1) ||
-      !cbb_add_hex(&cbb, premaster, premaster_len) ||
-      !CBB_add_u8(&cbb, 0 /* NUL */) ||
-      !CBB_finish(&cbb, &out, &out_len)) {
-    CBB_cleanup(&cbb);
-    return 0;
-  }
-
-  ssl->ctx->keylog_callback(ssl, (const char *)out);
-  OPENSSL_free(out);
-  return 1;
-}
-
-int ssl_log_master_secret(const SSL *ssl, const uint8_t *client_random,
-                          size_t client_random_len, const uint8_t *master,
-                          size_t master_len) {
-  if (ssl->ctx->keylog_callback == NULL) {
-    return 1;
-  }
-
-  if (client_random_len != 32) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    return 0;
-  }
-
-  CBB cbb;
-  uint8_t *out;
-  size_t out_len;
-  if (!CBB_init(&cbb, 14 + 64 + 1 + master_len * 2 + 1) ||
-      !CBB_add_bytes(&cbb, (const uint8_t *)"CLIENT_RANDOM ", 14) ||
-      !cbb_add_hex(&cbb, client_random, 32) ||
+      !cbb_add_hex(&cbb, ssl->s3->client_random, SSL3_RANDOM_SIZE) ||
       !CBB_add_bytes(&cbb, (const uint8_t *)" ", 1) ||
-      !cbb_add_hex(&cbb, master, master_len) ||
+      !cbb_add_hex(&cbb, secret, secret_len) ||
       !CBB_add_u8(&cbb, 0 /* NUL */) ||
       !CBB_finish(&cbb, &out, &out_len)) {
     CBB_cleanup(&cbb);
@@ -2265,15 +2278,19 @@
 }
 
 int SSL_is_init_finished(const SSL *ssl) {
-  return ssl->state == SSL_ST_OK;
+  return !SSL_in_init(ssl);
 }
 
 int SSL_in_init(const SSL *ssl) {
-  return (ssl->state & SSL_ST_INIT) != 0;
+  SSL_HANDSHAKE *hs = ssl->s3->hs;
+  return hs != NULL && hs->state != SSL_ST_OK;
 }
 
 int SSL_in_false_start(const SSL *ssl) {
-  return ssl->s3->tmp.in_false_start;
+  if (ssl->s3->hs == NULL) {
+    return 0;
+  }
+  return ssl->s3->hs->in_false_start;
 }
 
 int SSL_cutthrough_complete(const SSL *ssl) {
@@ -2291,119 +2308,50 @@
   const SSL_CIPHER *const cipher = SSL_get_current_cipher(ssl);
 
   /* False Start only for TLS 1.2 with an ECDHE+AEAD cipher and ALPN or NPN. */
-  return !SSL_IS_DTLS(ssl) &&
-      SSL_version(ssl) >= TLS1_2_VERSION &&
-      (ssl->s3->alpn_selected || ssl->s3->next_proto_neg_seen) &&
+  return !SSL_is_dtls(ssl) &&
+      SSL_version(ssl) == TLS1_2_VERSION &&
+      (ssl->s3->alpn_selected != NULL ||
+       ssl->s3->next_proto_negotiated != NULL) &&
       cipher != NULL &&
       cipher->algorithm_mkey == SSL_kECDHE &&
       cipher->algorithm_mac == SSL_AEAD;
 }
 
-const SSL3_ENC_METHOD *ssl3_get_enc_method(uint16_t version) {
-  switch (version) {
-    case SSL3_VERSION:
-      return &SSLv3_enc_data;
+const struct {
+  uint16_t version;
+  uint32_t flag;
+} kVersions[] = {
+    {SSL3_VERSION, SSL_OP_NO_SSLv3},
+    {TLS1_VERSION, SSL_OP_NO_TLSv1},
+    {TLS1_1_VERSION, SSL_OP_NO_TLSv1_1},
+    {TLS1_2_VERSION, SSL_OP_NO_TLSv1_2},
+    {TLS1_3_VERSION, SSL_OP_NO_TLSv1_3},
+};
 
-    case TLS1_VERSION:
-      return &TLSv1_enc_data;
+static const size_t kVersionsLen = OPENSSL_ARRAY_SIZE(kVersions);
 
-    case DTLS1_VERSION:
-    case TLS1_1_VERSION:
-      return &TLSv1_1_enc_data;
-
-    case DTLS1_2_VERSION:
-    case TLS1_2_VERSION:
-      return &TLSv1_2_enc_data;
-
-    default:
-      return NULL;
-  }
-}
-
-uint16_t ssl3_get_max_server_version(const SSL *ssl) {
-  uint16_t max_version;
-
-  if (SSL_IS_DTLS(ssl)) {
-    max_version = (ssl->max_version != 0) ? ssl->max_version : DTLS1_2_VERSION;
-    if (!(ssl->options & SSL_OP_NO_DTLSv1_2) &&
-        DTLS1_2_VERSION >= max_version) {
-      return DTLS1_2_VERSION;
-    }
-    if (!(ssl->options & SSL_OP_NO_DTLSv1) && DTLS1_VERSION >= max_version) {
-      return DTLS1_VERSION;
-    }
-    return 0;
-  }
-
-  max_version = (ssl->max_version != 0) ? ssl->max_version : TLS1_2_VERSION;
-  if (!(ssl->options & SSL_OP_NO_TLSv1_2) && TLS1_2_VERSION <= max_version) {
-    return TLS1_2_VERSION;
-  }
-  if (!(ssl->options & SSL_OP_NO_TLSv1_1) && TLS1_1_VERSION <= max_version) {
-    return TLS1_1_VERSION;
-  }
-  if (!(ssl->options & SSL_OP_NO_TLSv1) && TLS1_VERSION <= max_version) {
-    return TLS1_VERSION;
-  }
-  if (!(ssl->options & SSL_OP_NO_SSLv3) && SSL3_VERSION <= max_version) {
-    return SSL3_VERSION;
-  }
-  return 0;
-}
-
-uint16_t ssl3_get_mutual_version(SSL *ssl, uint16_t client_version) {
-  uint16_t version = 0;
-
-  if (SSL_IS_DTLS(ssl)) {
-    /* Clamp client_version to max_version. */
-    if (ssl->max_version != 0 && client_version < ssl->max_version) {
-      client_version = ssl->max_version;
-    }
-
-    if (client_version <= DTLS1_2_VERSION &&
-        !(ssl->options & SSL_OP_NO_DTLSv1_2)) {
-      version = DTLS1_2_VERSION;
-    } else if (client_version <= DTLS1_VERSION &&
-               !(ssl->options & SSL_OP_NO_DTLSv1)) {
-      version = DTLS1_VERSION;
-    }
-
-    /* Check against min_version. */
-    if (version != 0 && ssl->min_version != 0 && version > ssl->min_version) {
-      return 0;
-    }
-    return version;
-  } else {
-    /* Clamp client_version to max_version. */
-    if (ssl->max_version != 0 && client_version > ssl->max_version) {
-      client_version = ssl->max_version;
-    }
-
-    if (client_version >= TLS1_2_VERSION &&
-        !(ssl->options & SSL_OP_NO_TLSv1_2)) {
-      version = TLS1_2_VERSION;
-    } else if (client_version >= TLS1_1_VERSION &&
-               !(ssl->options & SSL_OP_NO_TLSv1_1)) {
-      version = TLS1_1_VERSION;
-    } else if (client_version >= TLS1_VERSION &&
-               !(ssl->options & SSL_OP_NO_TLSv1)) {
-      version = TLS1_VERSION;
-    } else if (client_version >= SSL3_VERSION &&
-               !(ssl->options & SSL_OP_NO_SSLv3)) {
-      version = SSL3_VERSION;
-    }
-
-    /* Check against min_version. */
-    if (version != 0 && ssl->min_version != 0 && version < ssl->min_version) {
-      return 0;
-    }
-    return version;
-  }
-}
-
-uint16_t ssl3_get_max_client_version(SSL *ssl) {
+int ssl_get_version_range(const SSL *ssl, uint16_t *out_min_version,
+                          uint16_t *out_max_version) {
+  /* For historical reasons, |SSL_OP_NO_DTLSv1| aliases |SSL_OP_NO_TLSv1|, but
+   * DTLS 1.0 should be mapped to TLS 1.1. */
   uint32_t options = ssl->options;
-  uint16_t version = 0;
+  if (SSL_is_dtls(ssl)) {
+    options &= ~SSL_OP_NO_TLSv1_1;
+    if (options & SSL_OP_NO_DTLSv1) {
+      options |= SSL_OP_NO_TLSv1_1;
+    }
+  }
+
+  uint16_t min_version = ssl->min_version;
+  uint16_t max_version = ssl->max_version;
+
+  /* Bound the range to only those implemented in this protocol. */
+  if (min_version < ssl->method->min_version) {
+    min_version = ssl->method->min_version;
+  }
+  if (max_version > ssl->method->max_version) {
+    max_version = ssl->method->max_version;
+  }
 
   /* OpenSSL's API for controlling versions entails blacklisting individual
    * protocols. This has two problems. First, on the client, the protocol can
@@ -2414,119 +2362,69 @@
    * To account for both of these, OpenSSL interprets the client-side bitmask
    * as a min/max range by picking the lowest contiguous non-empty range of
    * enabled protocols. Note that this means it is impossible to set a maximum
-   * version of TLS 1.2 in a future-proof way.
-   *
-   * By this scheme, the maximum version is the lowest version V such that V is
-   * enabled and V+1 is disabled or unimplemented. */
-  if (SSL_IS_DTLS(ssl)) {
-    if (!(options & SSL_OP_NO_DTLSv1_2)) {
-      version = DTLS1_2_VERSION;
+   * version of the higest supported TLS version in a future-proof way. */
+  int any_enabled = 0;
+  for (size_t i = 0; i < kVersionsLen; i++) {
+    /* Only look at the versions already enabled. */
+    if (min_version > kVersions[i].version) {
+      continue;
     }
-    if (!(options & SSL_OP_NO_DTLSv1) && (options & SSL_OP_NO_DTLSv1_2)) {
-      version = DTLS1_VERSION;
+    if (max_version < kVersions[i].version) {
+      break;
     }
-    if (ssl->max_version != 0 && version < ssl->max_version) {
-      version = ssl->max_version;
+
+    if (!(options & kVersions[i].flag)) {
+      /* The minimum version is the first enabled version. */
+      if (!any_enabled) {
+        any_enabled = 1;
+        min_version = kVersions[i].version;
+      }
+      continue;
     }
-  } else {
-    if (!(options & SSL_OP_NO_TLSv1_2)) {
-      version = TLS1_2_VERSION;
+
+    /* If there is a disabled version after the first enabled one, all versions
+     * after it are implicitly disabled. */
+    if (any_enabled) {
+      max_version = kVersions[i-1].version;
+      break;
     }
-    if (!(options & SSL_OP_NO_TLSv1_1) && (options & SSL_OP_NO_TLSv1_2)) {
-      version = TLS1_1_VERSION;
-    }
-    if (!(options & SSL_OP_NO_TLSv1) && (options & SSL_OP_NO_TLSv1_1)) {
-      version = TLS1_VERSION;
-    }
-    if (!(options & SSL_OP_NO_SSLv3) && (options & SSL_OP_NO_TLSv1)) {
-      version = SSL3_VERSION;
-    }
-    if (ssl->max_version != 0 && version > ssl->max_version) {
-      version = ssl->max_version;
-    }
+  }
+
+  if (!any_enabled) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SSL_VERSION);
+    return 0;
+  }
+
+  *out_min_version = min_version;
+  *out_max_version = max_version;
+  return 1;
+}
+
+uint16_t ssl3_protocol_version(const SSL *ssl) {
+  assert(ssl->s3->have_version);
+  uint16_t version;
+  if (!ssl->method->version_from_wire(&version, ssl->version)) {
+    /* TODO(davidben): Use the internal version representation for ssl->version
+     * and map to the public API representation at API boundaries. */
+    assert(0);
+    return 0;
   }
 
   return version;
 }
 
-int ssl3_is_version_enabled(SSL *ssl, uint16_t version) {
-  if (SSL_IS_DTLS(ssl)) {
-    if (ssl->max_version != 0 && version < ssl->max_version) {
-      return 0;
-    }
-    if (ssl->min_version != 0 && version > ssl->min_version) {
-      return 0;
-    }
+int SSL_is_server(const SSL *ssl) { return ssl->server; }
 
-    switch (version) {
-      case DTLS1_VERSION:
-        return !(ssl->options & SSL_OP_NO_DTLSv1);
-
-      case DTLS1_2_VERSION:
-        return !(ssl->options & SSL_OP_NO_DTLSv1_2);
-
-      default:
-        return 0;
-    }
-  } else {
-    if (ssl->max_version != 0 && version > ssl->max_version) {
-      return 0;
-    }
-    if (ssl->min_version != 0 && version < ssl->min_version) {
-      return 0;
-    }
-
-    switch (version) {
-      case SSL3_VERSION:
-        return !(ssl->options & SSL_OP_NO_SSLv3);
-
-      case TLS1_VERSION:
-        return !(ssl->options & SSL_OP_NO_TLSv1);
-
-      case TLS1_1_VERSION:
-        return !(ssl->options & SSL_OP_NO_TLSv1_1);
-
-      case TLS1_2_VERSION:
-        return !(ssl->options & SSL_OP_NO_TLSv1_2);
-
-      default:
-        return 0;
-    }
-  }
-}
-
-uint16_t ssl3_version_from_wire(SSL *ssl, uint16_t wire_version) {
-  if (!SSL_IS_DTLS(ssl)) {
-    return wire_version;
-  }
-
-  uint16_t tls_version = ~wire_version;
-  uint16_t version = tls_version + 0x0201;
-  /* If either component overflowed, clamp it so comparisons still work. */
-  if ((version >> 8) < (tls_version >> 8)) {
-    version = 0xff00 | (version & 0xff);
-  }
-  if ((version & 0xff) < (tls_version & 0xff)) {
-    version = (version & 0xff00) | 0xff;
-  }
-  /* DTLS 1.0 maps to TLS 1.1, not TLS 1.0. */
-  if (version == TLS1_VERSION) {
-    version = TLS1_1_VERSION;
-  }
-  return version;
-}
-
-int SSL_cache_hit(SSL *ssl) { return SSL_session_reused(ssl); }
-
-int SSL_is_server(SSL *ssl) { return ssl->server; }
+int SSL_is_dtls(const SSL *ssl) { return ssl->method->is_dtls; }
 
 void SSL_CTX_set_select_certificate_cb(
-    SSL_CTX *ctx, int (*cb)(const struct ssl_early_callback_ctx *)) {
+    SSL_CTX *ctx,
+    enum ssl_select_cert_result_t (*cb)(const SSL_CLIENT_HELLO *)) {
   ctx->select_certificate_cb = cb;
 }
 
-void SSL_CTX_set_dos_protection_cb(
-    SSL_CTX *ctx, int (*cb)(const struct ssl_early_callback_ctx *)) {
+void SSL_CTX_set_dos_protection_cb(SSL_CTX *ctx,
+                                   int (*cb)(const SSL_CLIENT_HELLO *)) {
   ctx->dos_protection_cb = cb;
 }
 
@@ -2534,30 +2432,16 @@
   ssl->renegotiate_mode = mode;
 }
 
-void SSL_set_reject_peer_renegotiations(SSL *ssl, int reject) {
-  SSL_set_renegotiate_mode(
-      ssl, reject ? ssl_renegotiate_never : ssl_renegotiate_freely);
-}
-
-int SSL_get_rc4_state(const SSL *ssl, const RC4_KEY **read_key,
-                      const RC4_KEY **write_key) {
-  if (ssl->aead_read_ctx == NULL || ssl->aead_write_ctx == NULL) {
-    return 0;
-  }
-
-  return EVP_AEAD_CTX_get_rc4_state(&ssl->aead_read_ctx->ctx, read_key) &&
-         EVP_AEAD_CTX_get_rc4_state(&ssl->aead_write_ctx->ctx, write_key);
-}
-
 int SSL_get_ivs(const SSL *ssl, const uint8_t **out_read_iv,
                 const uint8_t **out_write_iv, size_t *out_iv_len) {
-  if (ssl->aead_read_ctx == NULL || ssl->aead_write_ctx == NULL) {
+  if (ssl->s3->aead_read_ctx == NULL || ssl->s3->aead_write_ctx == NULL) {
     return 0;
   }
 
   size_t write_iv_len;
-  if (!EVP_AEAD_CTX_get_iv(&ssl->aead_read_ctx->ctx, out_read_iv, out_iv_len) ||
-      !EVP_AEAD_CTX_get_iv(&ssl->aead_write_ctx->ctx, out_write_iv,
+  if (!EVP_AEAD_CTX_get_iv(&ssl->s3->aead_read_ctx->ctx, out_read_iv,
+                           out_iv_len) ||
+      !EVP_AEAD_CTX_get_iv(&ssl->s3->aead_write_ctx->ctx, out_write_iv,
                            &write_iv_len) ||
       *out_iv_len != write_iv_len) {
     return 0;
@@ -2566,35 +2450,97 @@
   return 1;
 }
 
-uint8_t SSL_get_server_key_exchange_hash(const SSL *ssl) {
-  return ssl->s3->tmp.server_key_exchange_hash;
+static uint64_t be_to_u64(const uint8_t in[8]) {
+  return (((uint64_t)in[0]) << 56) | (((uint64_t)in[1]) << 48) |
+         (((uint64_t)in[2]) << 40) | (((uint64_t)in[3]) << 32) |
+         (((uint64_t)in[4]) << 24) | (((uint64_t)in[5]) << 16) |
+         (((uint64_t)in[6]) << 8) | ((uint64_t)in[7]);
 }
 
-int SSL_clear(SSL *ssl) {
-  if (ssl->method == NULL) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_NO_METHOD_SPECIFIED);
+uint64_t SSL_get_read_sequence(const SSL *ssl) {
+  /* TODO(davidben): Internally represent sequence numbers as uint64_t. */
+  if (SSL_is_dtls(ssl)) {
+    /* max_seq_num already includes the epoch. */
+    assert(ssl->d1->r_epoch == (ssl->d1->bitmap.max_seq_num >> 48));
+    return ssl->d1->bitmap.max_seq_num;
+  }
+  return be_to_u64(ssl->s3->read_sequence);
+}
+
+uint64_t SSL_get_write_sequence(const SSL *ssl) {
+  uint64_t ret = be_to_u64(ssl->s3->write_sequence);
+  if (SSL_is_dtls(ssl)) {
+    assert((ret >> 48) == 0);
+    ret |= ((uint64_t)ssl->d1->w_epoch) << 48;
+  }
+  return ret;
+}
+
+uint16_t SSL_get_peer_signature_algorithm(const SSL *ssl) {
+  /* TODO(davidben): This checks the wrong session if there is a renegotiation
+   * in progress. */
+  SSL_SESSION *session = SSL_get_session(ssl);
+  if (session == NULL) {
     return 0;
   }
 
-  if (ssl_clear_bad_session(ssl)) {
-    SSL_SESSION_free(ssl->session);
-    ssl->session = NULL;
+  return session->peer_signature_algorithm;
+}
+
+size_t SSL_get_client_random(const SSL *ssl, uint8_t *out, size_t max_out) {
+  if (max_out == 0) {
+    return sizeof(ssl->s3->client_random);
   }
+  if (max_out > sizeof(ssl->s3->client_random)) {
+    max_out = sizeof(ssl->s3->client_random);
+  }
+  OPENSSL_memcpy(out, ssl->s3->client_random, max_out);
+  return max_out;
+}
 
-  ssl->hit = 0;
-  ssl->shutdown = 0;
+size_t SSL_get_server_random(const SSL *ssl, uint8_t *out, size_t max_out) {
+  if (max_out == 0) {
+    return sizeof(ssl->s3->server_random);
+  }
+  if (max_out > sizeof(ssl->s3->server_random)) {
+    max_out = sizeof(ssl->s3->server_random);
+  }
+  OPENSSL_memcpy(out, ssl->s3->server_random, max_out);
+  return max_out;
+}
 
-  /* SSL_clear may be called before or after the |ssl| is initialized in either
-   * accept or connect state. In the latter case, SSL_clear should preserve the
-   * half and reset |ssl->state| accordingly. */
-  if (ssl->handshake_func != NULL) {
-    if (ssl->server) {
-      SSL_set_accept_state(ssl);
-    } else {
-      SSL_set_connect_state(ssl);
-    }
-  } else {
-    assert(ssl->state == 0);
+const SSL_CIPHER *SSL_get_pending_cipher(const SSL *ssl) {
+  SSL_HANDSHAKE *hs = ssl->s3->hs;
+  if (hs == NULL) {
+    return NULL;
+  }
+  return hs->new_cipher;
+}
+
+void SSL_set_retain_only_sha256_of_client_certs(SSL *ssl, int enabled) {
+  ssl->retain_only_sha256_of_client_certs = !!enabled;
+}
+
+void SSL_CTX_set_retain_only_sha256_of_client_certs(SSL_CTX *ctx, int enabled) {
+  ctx->retain_only_sha256_of_client_certs = !!enabled;
+}
+
+void SSL_CTX_set_grease_enabled(SSL_CTX *ctx, int enabled) {
+  ctx->grease_enabled = !!enabled;
+}
+
+int32_t SSL_get_ticket_age_skew(const SSL *ssl) {
+  return ssl->s3->ticket_age_skew;
+}
+
+int SSL_clear(SSL *ssl) {
+  /* In OpenSSL, reusing a client |SSL| with |SSL_clear| causes the previously
+   * established session to be offered the next time around. wpa_supplicant
+   * depends on this behavior, so emulate it. */
+  SSL_SESSION *session = NULL;
+  if (!ssl->server && ssl->s3->established_session != NULL) {
+    session = ssl->s3->established_session;
+    SSL_SESSION_up_ref(session);
   }
 
   /* TODO(davidben): Some state on |ssl| is reset both in |SSL_new| and
@@ -2607,12 +2553,8 @@
 
   BUF_MEM_free(ssl->init_buf);
   ssl->init_buf = NULL;
-
-  ssl_clear_cipher_ctx(ssl);
-
-  OPENSSL_free(ssl->next_proto_negotiated);
-  ssl->next_proto_negotiated = NULL;
-  ssl->next_proto_negotiated_len = 0;
+  ssl->init_msg = NULL;
+  ssl->init_num = 0;
 
   /* The ssl->d1->mtu is simultaneously configuration (preserved across
    * clear) and connection-specific state (gets reset).
@@ -2625,20 +2567,60 @@
 
   ssl->method->ssl_free(ssl);
   if (!ssl->method->ssl_new(ssl)) {
+    SSL_SESSION_free(session);
     return 0;
   }
-  ssl->enc_method = ssl3_get_enc_method(ssl->version);
-  assert(ssl->enc_method != NULL);
 
-  if (SSL_IS_DTLS(ssl) && (SSL_get_options(ssl) & SSL_OP_NO_QUERY_MTU)) {
+  if (SSL_is_dtls(ssl) && (SSL_get_options(ssl) & SSL_OP_NO_QUERY_MTU)) {
     ssl->d1->mtu = mtu;
   }
 
-  ssl->client_version = ssl->version;
+  if (session != NULL) {
+    SSL_set_session(ssl, session);
+    SSL_SESSION_free(session);
+  }
 
   return 1;
 }
 
+void ssl_do_info_callback(const SSL *ssl, int type, int value) {
+  void (*cb)(const SSL *ssl, int type, int value) = NULL;
+  if (ssl->info_callback != NULL) {
+    cb = ssl->info_callback;
+  } else if (ssl->ctx->info_callback != NULL) {
+    cb = ssl->ctx->info_callback;
+  }
+
+  if (cb != NULL) {
+    cb(ssl, type, value);
+  }
+}
+
+void ssl_do_msg_callback(SSL *ssl, int is_write, int content_type,
+                         const void *buf, size_t len) {
+  if (ssl->msg_callback == NULL) {
+    return;
+  }
+
+  /* |version| is zero when calling for |SSL3_RT_HEADER| and |SSL2_VERSION| for
+   * a V2ClientHello. */
+  int version;
+  switch (content_type) {
+    case 0:
+      /* V2ClientHello */
+      version = SSL2_VERSION;
+      break;
+    case SSL3_RT_HEADER:
+      version = 0;
+      break;
+    default:
+      version = SSL_version(ssl);
+  }
+
+  ssl->msg_callback(is_write, version, content_type, buf, len, ssl,
+                    ssl->msg_callback_arg);
+}
+
 int SSL_CTX_sess_connect(const SSL_CTX *ctx) { return 0; }
 int SSL_CTX_sess_connect_good(const SSL_CTX *ctx) { return 0; }
 int SSL_CTX_sess_connect_renegotiate(const SSL_CTX *ctx) { return 0; }
@@ -2650,5 +2632,99 @@
 int SSL_CTX_sess_misses(const SSL_CTX *ctx) { return 0; }
 int SSL_CTX_sess_timeouts(const SSL_CTX *ctx) { return 0; }
 int SSL_CTX_sess_cache_full(const SSL_CTX *ctx) { return 0; }
+
+int SSL_num_renegotiations(const SSL *ssl) {
+  return SSL_total_renegotiations(ssl);
+}
+
+int SSL_CTX_need_tmp_RSA(const SSL_CTX *ctx) { return 0; }
+int SSL_need_tmp_RSA(const SSL *ssl) { return 0; }
+int SSL_CTX_set_tmp_rsa(SSL_CTX *ctx, const RSA *rsa) { return 1; }
+int SSL_set_tmp_rsa(SSL *ssl, const RSA *rsa) { return 1; }
 void ERR_load_SSL_strings(void) {}
 void SSL_load_error_strings(void) {}
+int SSL_cache_hit(SSL *ssl) { return SSL_session_reused(ssl); }
+
+int SSL_CTX_set_tmp_ecdh(SSL_CTX *ctx, const EC_KEY *ec_key) {
+  if (ec_key == NULL || EC_KEY_get0_group(ec_key) == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
+    return 0;
+  }
+  int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key));
+  return SSL_CTX_set1_curves(ctx, &nid, 1);
+}
+
+int SSL_set_tmp_ecdh(SSL *ssl, const EC_KEY *ec_key) {
+  if (ec_key == NULL || EC_KEY_get0_group(ec_key) == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
+    return 0;
+  }
+  int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key));
+  return SSL_set1_curves(ssl, &nid, 1);
+}
+
+void ssl_get_current_time(const SSL *ssl, struct OPENSSL_timeval *out_clock) {
+  if (ssl->ctx->current_time_cb != NULL) {
+    /* TODO(davidben): Update current_time_cb to use OPENSSL_timeval. See
+     * https://crbug.com/boringssl/155. */
+    struct timeval clock;
+    ssl->ctx->current_time_cb(ssl, &clock);
+    if (clock.tv_sec < 0) {
+      assert(0);
+      out_clock->tv_sec = 0;
+      out_clock->tv_usec = 0;
+    } else {
+      out_clock->tv_sec = (uint64_t)clock.tv_sec;
+      out_clock->tv_usec = (uint32_t)clock.tv_usec;
+    }
+    return;
+  }
+
+#if defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE)
+  out_clock->tv_sec = 1234;
+  out_clock->tv_usec = 1234;
+#elif defined(OPENSSL_WINDOWS)
+  struct _timeb time;
+  _ftime(&time);
+  if (time.time < 0) {
+    assert(0);
+    out_clock->tv_sec = 0;
+    out_clock->tv_usec = 0;
+  } else {
+    out_clock->tv_sec = time.time;
+    out_clock->tv_usec = time.millitm * 1000;
+  }
+#else
+  struct timeval clock;
+  gettimeofday(&clock, NULL);
+  if (clock.tv_sec < 0) {
+    assert(0);
+    out_clock->tv_sec = 0;
+    out_clock->tv_usec = 0;
+  } else {
+    out_clock->tv_sec = (uint64_t)clock.tv_sec;
+    out_clock->tv_usec = (uint32_t)clock.tv_usec;
+  }
+#endif
+}
+
+int SSL_CTX_set_min_version(SSL_CTX *ctx, uint16_t version) {
+  return SSL_CTX_set_min_proto_version(ctx, version);
+}
+
+int SSL_CTX_set_max_version(SSL_CTX *ctx, uint16_t version) {
+  return SSL_CTX_set_max_proto_version(ctx, version);
+}
+
+int SSL_set_min_version(SSL *ssl, uint16_t version) {
+  return SSL_set_min_proto_version(ssl, version);
+}
+
+int SSL_set_max_version(SSL *ssl, uint16_t version) {
+  return SSL_set_max_proto_version(ssl, version);
+}
+
+void SSL_CTX_set_ticket_aead_method(SSL_CTX *ctx,
+                                    const SSL_TICKET_AEAD_METHOD *aead_method) {
+  ctx->ticket_aead_method = aead_method;
+}
diff --git a/src/ssl/ssl_privkey.c b/src/ssl/ssl_privkey.c
new file mode 100644
index 0000000..e988827
--- /dev/null
+++ b/src/ssl/ssl_privkey.c
@@ -0,0 +1,678 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/ssl.h>
+
+#include <limits.h>
+
+#include <openssl/ec.h>
+#include <openssl/ec_key.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+#include <openssl/type_check.h>
+
+#include "internal.h"
+
+
+int ssl_is_key_type_supported(int key_type) {
+  return key_type == EVP_PKEY_RSA || key_type == EVP_PKEY_EC;
+}
+
+static int ssl_set_pkey(CERT *cert, EVP_PKEY *pkey) {
+  if (!ssl_is_key_type_supported(pkey->type)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
+    return 0;
+  }
+
+  if (cert->chain != NULL &&
+      sk_CRYPTO_BUFFER_value(cert->chain, 0) != NULL &&
+      /* Sanity-check that the private key and the certificate match. */
+      !ssl_cert_check_private_key(cert, pkey)) {
+    return 0;
+  }
+
+  EVP_PKEY_free(cert->privatekey);
+  EVP_PKEY_up_ref(pkey);
+  cert->privatekey = pkey;
+
+  return 1;
+}
+
+int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) {
+  EVP_PKEY *pkey;
+  int ret;
+
+  if (rsa == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
+    return 0;
+  }
+
+  pkey = EVP_PKEY_new();
+  if (pkey == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_EVP_LIB);
+    return 0;
+  }
+
+  RSA_up_ref(rsa);
+  EVP_PKEY_assign_RSA(pkey, rsa);
+
+  ret = ssl_set_pkey(ssl->cert, pkey);
+  EVP_PKEY_free(pkey);
+
+  return ret;
+}
+
+int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey) {
+  if (pkey == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
+    return 0;
+  }
+
+  return ssl_set_pkey(ssl->cert, pkey);
+}
+
+int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const uint8_t *der,
+                            size_t der_len) {
+  if (der_len > LONG_MAX) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
+    return 0;
+  }
+
+  const uint8_t *p = der;
+  EVP_PKEY *pkey = d2i_PrivateKey(type, NULL, &p, (long)der_len);
+  if (pkey == NULL || p != der + der_len) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
+    EVP_PKEY_free(pkey);
+    return 0;
+  }
+
+  int ret = SSL_use_PrivateKey(ssl, pkey);
+  EVP_PKEY_free(pkey);
+  return ret;
+}
+
+int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa) {
+  int ret;
+  EVP_PKEY *pkey;
+
+  if (rsa == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
+    return 0;
+  }
+
+  pkey = EVP_PKEY_new();
+  if (pkey == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_EVP_LIB);
+    return 0;
+  }
+
+  RSA_up_ref(rsa);
+  EVP_PKEY_assign_RSA(pkey, rsa);
+
+  ret = ssl_set_pkey(ctx->cert, pkey);
+  EVP_PKEY_free(pkey);
+  return ret;
+}
+
+int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const uint8_t *der,
+                                   size_t der_len) {
+  RSA *rsa = RSA_private_key_from_bytes(der, der_len);
+  if (rsa == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
+    return 0;
+  }
+
+  int ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa);
+  RSA_free(rsa);
+  return ret;
+}
+
+int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) {
+  if (pkey == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
+    return 0;
+  }
+
+  return ssl_set_pkey(ctx->cert, pkey);
+}
+
+int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, const uint8_t *der,
+                                size_t der_len) {
+  if (der_len > LONG_MAX) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
+    return 0;
+  }
+
+  const uint8_t *p = der;
+  EVP_PKEY *pkey = d2i_PrivateKey(type, NULL, &p, (long)der_len);
+  if (pkey == NULL || p != der + der_len) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
+    EVP_PKEY_free(pkey);
+    return 0;
+  }
+
+  int ret = SSL_CTX_use_PrivateKey(ctx, pkey);
+  EVP_PKEY_free(pkey);
+  return ret;
+}
+
+void SSL_set_private_key_method(SSL *ssl,
+                                const SSL_PRIVATE_KEY_METHOD *key_method) {
+  ssl->cert->key_method = key_method;
+}
+
+void SSL_CTX_set_private_key_method(SSL_CTX *ctx,
+                                    const SSL_PRIVATE_KEY_METHOD *key_method) {
+  ctx->cert->key_method = key_method;
+}
+
+static int set_signing_algorithm_prefs(CERT *cert, const uint16_t *prefs,
+                                       size_t num_prefs) {
+  OPENSSL_free(cert->sigalgs);
+
+  cert->num_sigalgs = 0;
+  cert->sigalgs = BUF_memdup(prefs, num_prefs * sizeof(prefs[0]));
+  if (cert->sigalgs == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+    return 0;
+  }
+  cert->num_sigalgs = num_prefs;
+
+  return 1;
+}
+
+int SSL_CTX_set_signing_algorithm_prefs(SSL_CTX *ctx, const uint16_t *prefs,
+                                        size_t num_prefs) {
+  return set_signing_algorithm_prefs(ctx->cert, prefs, num_prefs);
+}
+
+
+int SSL_set_signing_algorithm_prefs(SSL *ssl, const uint16_t *prefs,
+                                    size_t num_prefs) {
+  return set_signing_algorithm_prefs(ssl->cert, prefs, num_prefs);
+}
+
+int SSL_set_private_key_digest_prefs(SSL *ssl, const int *digest_nids,
+                                     size_t num_digests) {
+  OPENSSL_free(ssl->cert->sigalgs);
+
+  OPENSSL_COMPILE_ASSERT(sizeof(int) >= 2 * sizeof(uint16_t),
+                         digest_list_conversion_cannot_overflow);
+
+  ssl->cert->num_sigalgs = 0;
+  ssl->cert->sigalgs = OPENSSL_malloc(sizeof(uint16_t) * 2 * num_digests);
+  if (ssl->cert->sigalgs == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+    return 0;
+  }
+
+  /* Convert the digest list to a signature algorithms list.
+   *
+   * TODO(davidben): Replace this API with one that can express RSA-PSS, etc. */
+  for (size_t i = 0; i < num_digests; i++) {
+    switch (digest_nids[i]) {
+      case NID_sha1:
+        ssl->cert->sigalgs[ssl->cert->num_sigalgs] = SSL_SIGN_RSA_PKCS1_SHA1;
+        ssl->cert->sigalgs[ssl->cert->num_sigalgs + 1] = SSL_SIGN_ECDSA_SHA1;
+        ssl->cert->num_sigalgs += 2;
+        break;
+      case NID_sha256:
+        ssl->cert->sigalgs[ssl->cert->num_sigalgs] = SSL_SIGN_RSA_PKCS1_SHA256;
+        ssl->cert->sigalgs[ssl->cert->num_sigalgs + 1] =
+            SSL_SIGN_ECDSA_SECP256R1_SHA256;
+        ssl->cert->num_sigalgs += 2;
+        break;
+      case NID_sha384:
+        ssl->cert->sigalgs[ssl->cert->num_sigalgs] = SSL_SIGN_RSA_PKCS1_SHA384;
+        ssl->cert->sigalgs[ssl->cert->num_sigalgs + 1] =
+            SSL_SIGN_ECDSA_SECP384R1_SHA384;
+        ssl->cert->num_sigalgs += 2;
+        break;
+      case NID_sha512:
+        ssl->cert->sigalgs[ssl->cert->num_sigalgs] = SSL_SIGN_RSA_PKCS1_SHA512;
+        ssl->cert->sigalgs[ssl->cert->num_sigalgs + 1] =
+            SSL_SIGN_ECDSA_SECP521R1_SHA512;
+        ssl->cert->num_sigalgs += 2;
+        break;
+    }
+  }
+
+  return 1;
+}
+
+int ssl_has_private_key(const SSL *ssl) {
+  return ssl->cert->privatekey != NULL || ssl->cert->key_method != NULL;
+}
+
+int ssl_is_ecdsa_key_type(int type) {
+  switch (type) {
+    case NID_secp224r1:
+    case NID_X9_62_prime256v1:
+    case NID_secp384r1:
+    case NID_secp521r1:
+      return 1;
+    default:
+      return 0;
+  }
+}
+
+int ssl_private_key_type(SSL *ssl) {
+  if (ssl->cert->key_method != NULL) {
+    return ssl->cert->key_method->type(ssl);
+  }
+  switch (EVP_PKEY_id(ssl->cert->privatekey)) {
+    case EVP_PKEY_RSA:
+      return NID_rsaEncryption;
+    case EVP_PKEY_EC:
+      return EC_GROUP_get_curve_name(
+          EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(ssl->cert->privatekey)));
+    default:
+      return NID_undef;
+  }
+}
+
+size_t ssl_private_key_max_signature_len(SSL *ssl) {
+  if (ssl->cert->key_method != NULL) {
+    return ssl->cert->key_method->max_signature_len(ssl);
+  }
+  return EVP_PKEY_size(ssl->cert->privatekey);
+}
+
+/* TODO(davidben): Forbid RSA-PKCS1 in TLS 1.3. For now we allow it because NSS
+ * has yet to start doing RSA-PSS, so enforcing it would complicate interop
+ * testing. */
+static int is_rsa_pkcs1(const EVP_MD **out_md, uint16_t sigalg) {
+  switch (sigalg) {
+    case SSL_SIGN_RSA_PKCS1_MD5_SHA1:
+      *out_md = EVP_md5_sha1();
+      return 1;
+    case SSL_SIGN_RSA_PKCS1_SHA1:
+      *out_md = EVP_sha1();
+      return 1;
+    case SSL_SIGN_RSA_PKCS1_SHA256:
+      *out_md = EVP_sha256();
+      return 1;
+    case SSL_SIGN_RSA_PKCS1_SHA384:
+      *out_md = EVP_sha384();
+      return 1;
+    case SSL_SIGN_RSA_PKCS1_SHA512:
+      *out_md = EVP_sha512();
+      return 1;
+    default:
+      return 0;
+  }
+}
+
+static int ssl_sign_rsa_pkcs1(SSL *ssl, uint8_t *out, size_t *out_len,
+                              size_t max_out, const EVP_MD *md,
+                              const uint8_t *in, size_t in_len) {
+  EVP_MD_CTX ctx;
+  EVP_MD_CTX_init(&ctx);
+  *out_len = max_out;
+  int ret = EVP_DigestSignInit(&ctx, NULL, md, NULL, ssl->cert->privatekey) &&
+            EVP_DigestSignUpdate(&ctx, in, in_len) &&
+            EVP_DigestSignFinal(&ctx, out, out_len);
+  EVP_MD_CTX_cleanup(&ctx);
+  return ret;
+}
+
+static int ssl_verify_rsa_pkcs1(SSL *ssl, const uint8_t *signature,
+                                size_t signature_len, const EVP_MD *md,
+                                EVP_PKEY *pkey, const uint8_t *in,
+                                size_t in_len) {
+  if (pkey->type != EVP_PKEY_RSA) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
+    return 0;
+  }
+
+  EVP_MD_CTX md_ctx;
+  EVP_MD_CTX_init(&md_ctx);
+  int ret = EVP_DigestVerifyInit(&md_ctx, NULL, md, NULL, pkey) &&
+            EVP_DigestVerifyUpdate(&md_ctx, in, in_len) &&
+            EVP_DigestVerifyFinal(&md_ctx, signature, signature_len);
+  EVP_MD_CTX_cleanup(&md_ctx);
+  return ret;
+}
+
+static int is_ecdsa(int *out_curve, const EVP_MD **out_md, uint16_t sigalg) {
+  switch (sigalg) {
+    case SSL_SIGN_ECDSA_SHA1:
+      *out_curve = NID_undef;
+      *out_md = EVP_sha1();
+      return 1;
+    case SSL_SIGN_ECDSA_SECP256R1_SHA256:
+      *out_curve = NID_X9_62_prime256v1;
+      *out_md = EVP_sha256();
+      return 1;
+    case SSL_SIGN_ECDSA_SECP384R1_SHA384:
+      *out_curve = NID_secp384r1;
+      *out_md = EVP_sha384();
+      return 1;
+    case SSL_SIGN_ECDSA_SECP521R1_SHA512:
+      *out_curve = NID_secp521r1;
+      *out_md = EVP_sha512();
+      return 1;
+    default:
+      return 0;
+  }
+}
+
+static int ssl_sign_ecdsa(SSL *ssl, uint8_t *out, size_t *out_len,
+                          size_t max_out, int curve, const EVP_MD *md,
+                          const uint8_t *in, size_t in_len) {
+  EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(ssl->cert->privatekey);
+  if (ec_key == NULL) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
+    return 0;
+  }
+
+  /* In TLS 1.3, the curve is also specified by the signature algorithm. */
+  if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION &&
+      (curve == NID_undef ||
+       EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key)) != curve)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
+    return 0;
+  }
+
+  EVP_MD_CTX ctx;
+  EVP_MD_CTX_init(&ctx);
+  *out_len = max_out;
+  int ret = EVP_DigestSignInit(&ctx, NULL, md, NULL, ssl->cert->privatekey) &&
+            EVP_DigestSignUpdate(&ctx, in, in_len) &&
+            EVP_DigestSignFinal(&ctx, out, out_len);
+  EVP_MD_CTX_cleanup(&ctx);
+  return ret;
+}
+
+static int ssl_verify_ecdsa(SSL *ssl, const uint8_t *signature,
+                            size_t signature_len, int curve, const EVP_MD *md,
+                            EVP_PKEY *pkey, const uint8_t *in, size_t in_len) {
+  EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey);
+  if (ec_key == NULL) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
+    return 0;
+  }
+
+  /* In TLS 1.3, the curve is also specified by the signature algorithm. */
+  if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION &&
+      (curve == NID_undef ||
+       EC_GROUP_get_curve_name(EC_KEY_get0_group(ec_key)) != curve)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
+    return 0;
+  }
+
+  EVP_MD_CTX md_ctx;
+  EVP_MD_CTX_init(&md_ctx);
+  int ret = EVP_DigestVerifyInit(&md_ctx, NULL, md, NULL, pkey) &&
+            EVP_DigestVerifyUpdate(&md_ctx, in, in_len) &&
+            EVP_DigestVerifyFinal(&md_ctx, signature, signature_len);
+  EVP_MD_CTX_cleanup(&md_ctx);
+  return ret;
+}
+
+static int is_rsa_pss(const EVP_MD **out_md, uint16_t sigalg) {
+  switch (sigalg) {
+    case SSL_SIGN_RSA_PSS_SHA256:
+      *out_md = EVP_sha256();
+      return 1;
+    case SSL_SIGN_RSA_PSS_SHA384:
+      *out_md = EVP_sha384();
+      return 1;
+    case SSL_SIGN_RSA_PSS_SHA512:
+      *out_md = EVP_sha512();
+      return 1;
+    default:
+      return 0;
+  }
+}
+
+static int ssl_sign_rsa_pss(SSL *ssl, uint8_t *out, size_t *out_len,
+                              size_t max_out, const EVP_MD *md,
+                              const uint8_t *in, size_t in_len) {
+  EVP_MD_CTX ctx;
+  EVP_MD_CTX_init(&ctx);
+  *out_len = max_out;
+  EVP_PKEY_CTX *pctx;
+  int ret =
+      EVP_DigestSignInit(&ctx, &pctx, md, NULL, ssl->cert->privatekey) &&
+      EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) &&
+      EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1 /* salt len = hash len */) &&
+      EVP_DigestSignUpdate(&ctx, in, in_len) &&
+      EVP_DigestSignFinal(&ctx, out, out_len);
+  EVP_MD_CTX_cleanup(&ctx);
+  return ret;
+}
+
+static int ssl_verify_rsa_pss(SSL *ssl, const uint8_t *signature,
+                                size_t signature_len, const EVP_MD *md,
+                                EVP_PKEY *pkey, const uint8_t *in,
+                                size_t in_len) {
+  if (pkey->type != EVP_PKEY_RSA) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
+    return 0;
+  }
+
+  EVP_MD_CTX md_ctx;
+  EVP_MD_CTX_init(&md_ctx);
+  EVP_PKEY_CTX *pctx;
+  int ret =
+      EVP_DigestVerifyInit(&md_ctx, &pctx, md, NULL, pkey) &&
+      EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) &&
+      EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, -1 /* salt len = hash len */) &&
+      EVP_DigestVerifyUpdate(&md_ctx, in, in_len) &&
+      EVP_DigestVerifyFinal(&md_ctx, signature, signature_len);
+  EVP_MD_CTX_cleanup(&md_ctx);
+  return ret;
+}
+
+enum ssl_private_key_result_t ssl_private_key_sign(
+    SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
+    uint16_t signature_algorithm, const uint8_t *in, size_t in_len) {
+  if (ssl->cert->key_method != NULL) {
+    if (ssl->cert->key_method->sign != NULL) {
+      return ssl->cert->key_method->sign(ssl, out, out_len, max_out,
+                                         signature_algorithm, in, in_len);
+    }
+
+    /* TODO(davidben): Remove support for |sign_digest|-only
+     * |SSL_PRIVATE_KEY_METHOD|s. */
+    const EVP_MD *md;
+    int curve;
+    if (!is_rsa_pkcs1(&md, signature_algorithm) &&
+        !is_ecdsa(&curve, &md, signature_algorithm)) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY);
+      return ssl_private_key_failure;
+    }
+
+    uint8_t hash[EVP_MAX_MD_SIZE];
+    unsigned hash_len;
+    if (!EVP_Digest(in, in_len, hash, &hash_len, md, NULL)) {
+      return ssl_private_key_failure;
+    }
+
+    return ssl->cert->key_method->sign_digest(ssl, out, out_len, max_out, md,
+                                              hash, hash_len);
+  }
+
+  const EVP_MD *md;
+  if (is_rsa_pkcs1(&md, signature_algorithm) &&
+      ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
+    return ssl_sign_rsa_pkcs1(ssl, out, out_len, max_out, md, in, in_len)
+               ? ssl_private_key_success
+               : ssl_private_key_failure;
+  }
+
+  int curve;
+  if (is_ecdsa(&curve, &md, signature_algorithm)) {
+    return ssl_sign_ecdsa(ssl, out, out_len, max_out, curve, md, in, in_len)
+               ? ssl_private_key_success
+               : ssl_private_key_failure;
+  }
+
+  if (is_rsa_pss(&md, signature_algorithm)) {
+    return ssl_sign_rsa_pss(ssl, out, out_len, max_out, md, in, in_len)
+               ? ssl_private_key_success
+               : ssl_private_key_failure;
+  }
+
+  OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
+  return ssl_private_key_failure;
+}
+
+int ssl_public_key_verify(SSL *ssl, const uint8_t *signature,
+                          size_t signature_len, uint16_t signature_algorithm,
+                          EVP_PKEY *pkey, const uint8_t *in, size_t in_len) {
+  const EVP_MD *md;
+  if (is_rsa_pkcs1(&md, signature_algorithm) &&
+      ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
+    return ssl_verify_rsa_pkcs1(ssl, signature, signature_len, md, pkey, in,
+                                in_len);
+  }
+
+  int curve;
+  if (is_ecdsa(&curve, &md, signature_algorithm)) {
+    return ssl_verify_ecdsa(ssl, signature, signature_len, curve, md, pkey, in,
+                            in_len);
+  }
+
+  if (is_rsa_pss(&md, signature_algorithm)) {
+    return ssl_verify_rsa_pss(ssl, signature, signature_len, md, pkey, in,
+                              in_len);
+  }
+
+  OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
+  return 0;
+}
+
+enum ssl_private_key_result_t ssl_private_key_decrypt(
+    SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
+    const uint8_t *in, size_t in_len) {
+  if (ssl->cert->key_method != NULL) {
+    return ssl->cert->key_method->decrypt(ssl, out, out_len, max_out, in,
+                                          in_len);
+  }
+
+  RSA *rsa = EVP_PKEY_get0_RSA(ssl->cert->privatekey);
+  if (rsa == NULL) {
+    /* Decrypt operations are only supported for RSA keys. */
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    return ssl_private_key_failure;
+  }
+
+  /* Decrypt with no padding. PKCS#1 padding will be removed as part
+   * of the timing-sensitive code by the caller. */
+  if (!RSA_decrypt(rsa, out_len, out, max_out, in, in_len, RSA_NO_PADDING)) {
+    return ssl_private_key_failure;
+  }
+  return ssl_private_key_success;
+}
+
+enum ssl_private_key_result_t ssl_private_key_complete(SSL *ssl, uint8_t *out,
+                                                       size_t *out_len,
+                                                       size_t max_out) {
+  /* Only custom keys may be asynchronous. */
+  return ssl->cert->key_method->complete(ssl, out, out_len, max_out);
+}
+
+int ssl_private_key_supports_signature_algorithm(SSL *ssl,
+                                                 uint16_t signature_algorithm) {
+  const EVP_MD *md;
+  if (is_rsa_pkcs1(&md, signature_algorithm) &&
+      ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
+    return ssl_private_key_type(ssl) == NID_rsaEncryption;
+  }
+
+  int curve;
+  if (is_ecdsa(&curve, &md, signature_algorithm)) {
+    int type = ssl_private_key_type(ssl);
+    if (!ssl_is_ecdsa_key_type(type)) {
+      return 0;
+    }
+
+    /* Prior to TLS 1.3, ECDSA curves did not match the signature algorithm. */
+    if (ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
+      return 1;
+    }
+
+    return curve != NID_undef && type == curve;
+  }
+
+  if (is_rsa_pss(&md, signature_algorithm)) {
+    if (ssl_private_key_type(ssl) != NID_rsaEncryption) {
+      return 0;
+    }
+
+    /* Ensure the RSA key is large enough for the hash. RSASSA-PSS requires that
+     * emLen be at least hLen + sLen + 2. Both hLen and sLen are the size of the
+     * hash in TLS. Reasonable RSA key sizes are large enough for the largest
+     * defined RSASSA-PSS algorithm, but 1024-bit RSA is slightly too large for
+     * SHA-512. 1024-bit RSA is sometimes used for test credentials, so check
+     * the size to fall back to another algorithm. */
+    if (ssl_private_key_max_signature_len(ssl) < 2 * EVP_MD_size(md) + 2) {
+      return 0;
+    }
+
+    /* RSA-PSS is only supported by message-based private keys. */
+    if (ssl->cert->key_method != NULL && ssl->cert->key_method->sign == NULL) {
+      return 0;
+    }
+
+    return 1;
+  }
+
+  return 0;
+}
diff --git a/src/crypto/dh/internal.h b/src/ssl/ssl_privkey_cc.cc
similarity index 83%
rename from src/crypto/dh/internal.h
rename to src/ssl/ssl_privkey_cc.cc
index 81b9c90..653308c 100644
--- a/src/crypto/dh/internal.h
+++ b/src/ssl/ssl_privkey_cc.cc
@@ -54,27 +54,23 @@
  * copied and put under another distribution licence
  * [including the GNU Public Licence.] */
 
-#ifndef OPENSSL_HEADER_DH_INTERNAL_H
-#define OPENSSL_HEADER_DH_INTERNAL_H
+#include <openssl/ssl.h>
 
-#include <openssl/base.h>
-
-#include <openssl/bn.h>
-#include <openssl/ex_data.h>
-
-#if defined(__cplusplus)
-extern "C" {
-#endif
+#include <openssl/err.h>
+#include <openssl/rsa.h>
 
 
-/* DH_check_standard_parameters checks if the parameters in |dh| are well
- * known and safe. If so, it sets |dh->priv_length| to an appropriately smaller
- * value than the default. */
-void DH_check_standard_parameters(DH *dh);
+/* This function has been converted to C++ to check if all of libssl's
+ * consumers' toolchains are capable of handling C++11. Once all problems in
+ * consumer toolchains are found and fixed, we will convert the rest of
+ * libssl. */
 
+int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) {
+  bssl::UniquePtr<RSA> rsa(RSA_private_key_from_bytes(der, der_len));
+  if (!rsa) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
+    return 0;
+  }
 
-#if defined(__cplusplus)
-}  /* extern C */
-#endif
-
-#endif  /* OPENSSL_HEADER_DH_INTERNAL_H */
+  return SSL_use_RSAPrivateKey(ssl, rsa.get());
+}
diff --git a/src/ssl/ssl_rsa.c b/src/ssl/ssl_rsa.c
deleted file mode 100644
index 990979b..0000000
--- a/src/ssl/ssl_rsa.c
+++ /dev/null
@@ -1,423 +0,0 @@
-/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
- * All rights reserved.
- *
- * This package is an SSL implementation written
- * by Eric Young (eay@cryptsoft.com).
- * The implementation was written so as to conform with Netscapes SSL.
- *
- * This library is free for commercial and non-commercial use as long as
- * the following conditions are aheared to.  The following conditions
- * apply to all code found in this distribution, be it the RC4, RSA,
- * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
- * included with this distribution is covered by the same copyright terms
- * except that the holder is Tim Hudson (tjh@cryptsoft.com).
- *
- * Copyright remains Eric Young's, and as such any Copyright notices in
- * the code are not to be removed.
- * If this package is used in a product, Eric Young should be given attribution
- * as the author of the parts of the library used.
- * This can be in the form of a textual message at program startup or
- * in documentation (online or textual) provided with the package.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *    "This product includes cryptographic software written by
- *     Eric Young (eay@cryptsoft.com)"
- *    The word 'cryptographic' can be left out if the rouines from the library
- *    being used are not cryptographic related :-).
- * 4. If you include any Windows specific code (or a derivative thereof) from
- *    the apps directory (application code) you must include an acknowledgement:
- *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
- *
- * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * The licence and distribution terms for any publically available version or
- * derivative of this code cannot be changed.  i.e. this code cannot simply be
- * copied and put under another distribution licence
- * [including the GNU Public Licence.] */
-
-#include <openssl/ssl.h>
-
-#include <limits.h>
-
-#include <openssl/err.h>
-#include <openssl/evp.h>
-#include <openssl/mem.h>
-#include <openssl/x509.h>
-
-#include "internal.h"
-
-
-static int ssl_set_cert(CERT *c, X509 *x509);
-static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey);
-
-static int is_key_type_supported(int key_type) {
-  return key_type == EVP_PKEY_RSA || key_type == EVP_PKEY_EC;
-}
-
-int SSL_use_certificate(SSL *ssl, X509 *x) {
-  if (x == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
-    return 0;
-  }
-  return ssl_set_cert(ssl->cert, x);
-}
-
-int SSL_use_certificate_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) {
-  if (der_len > LONG_MAX) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
-    return 0;
-  }
-
-  const uint8_t *p = der;
-  X509 *x509 = d2i_X509(NULL, &p, (long)der_len);
-  if (x509 == NULL || p != der + der_len) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
-    X509_free(x509);
-    return 0;
-  }
-
-  int ret = SSL_use_certificate(ssl, x509);
-  X509_free(x509);
-  return ret;
-}
-
-int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa) {
-  EVP_PKEY *pkey;
-  int ret;
-
-  if (rsa == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
-    return 0;
-  }
-
-  pkey = EVP_PKEY_new();
-  if (pkey == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_EVP_LIB);
-    return 0;
-  }
-
-  RSA_up_ref(rsa);
-  EVP_PKEY_assign_RSA(pkey, rsa);
-
-  ret = ssl_set_pkey(ssl->cert, pkey);
-  EVP_PKEY_free(pkey);
-
-  return ret;
-}
-
-static int ssl_set_pkey(CERT *c, EVP_PKEY *pkey) {
-  if (!is_key_type_supported(pkey->type)) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
-    return 0;
-  }
-
-  if (c->x509 != NULL) {
-    /* Sanity-check that the private key and the certificate match, unless the
-     * key is opaque (in case of, say, a smartcard). */
-    if (!EVP_PKEY_is_opaque(pkey) &&
-        !X509_check_private_key(c->x509, pkey)) {
-      X509_free(c->x509);
-      c->x509 = NULL;
-      return 0;
-    }
-  }
-
-  EVP_PKEY_free(c->privatekey);
-  c->privatekey = EVP_PKEY_up_ref(pkey);
-
-  return 1;
-}
-
-int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const uint8_t *der, size_t der_len) {
-  RSA *rsa = RSA_private_key_from_bytes(der, der_len);
-  if (rsa == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
-    return 0;
-  }
-
-  int ret = SSL_use_RSAPrivateKey(ssl, rsa);
-  RSA_free(rsa);
-  return ret;
-}
-
-int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey) {
-  int ret;
-
-  if (pkey == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
-    return 0;
-  }
-
-  ret = ssl_set_pkey(ssl->cert, pkey);
-  return ret;
-}
-
-int SSL_use_PrivateKey_ASN1(int type, SSL *ssl, const uint8_t *der,
-                            size_t der_len) {
-  if (der_len > LONG_MAX) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
-    return 0;
-  }
-
-  const uint8_t *p = der;
-  EVP_PKEY *pkey = d2i_PrivateKey(type, NULL, &p, (long)der_len);
-  if (pkey == NULL || p != der + der_len) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
-    EVP_PKEY_free(pkey);
-    return 0;
-  }
-
-  int ret = SSL_use_PrivateKey(ssl, pkey);
-  EVP_PKEY_free(pkey);
-  return ret;
-}
-
-int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) {
-  if (x == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
-    return 0;
-  }
-
-  return ssl_set_cert(ctx->cert, x);
-}
-
-static int ssl_set_cert(CERT *c, X509 *x) {
-  EVP_PKEY *pkey = X509_get_pubkey(x);
-  if (pkey == NULL) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_X509_LIB);
-    return 0;
-  }
-
-  if (!is_key_type_supported(pkey->type)) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CERTIFICATE_TYPE);
-    EVP_PKEY_free(pkey);
-    return 0;
-  }
-
-  if (c->privatekey != NULL) {
-    /* Sanity-check that the private key and the certificate match, unless the
-     * key is opaque (in case of, say, a smartcard). */
-    if (!EVP_PKEY_is_opaque(c->privatekey) &&
-        !X509_check_private_key(x, c->privatekey)) {
-      /* don't fail for a cert/key mismatch, just free current private key
-       * (when switching to a different cert & key, first this function should
-       * be used, then ssl_set_pkey */
-      EVP_PKEY_free(c->privatekey);
-      c->privatekey = NULL;
-      /* clear error queue */
-      ERR_clear_error();
-    }
-  }
-
-  EVP_PKEY_free(pkey);
-
-  X509_free(c->x509);
-  c->x509 = X509_up_ref(x);
-
-  return 1;
-}
-
-int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, size_t der_len,
-                                 const uint8_t *der) {
-  if (der_len > LONG_MAX) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
-    return 0;
-  }
-
-  const uint8_t *p = der;
-  X509 *x509 = d2i_X509(NULL, &p, (long)der_len);
-  if (x509 == NULL || p != der + der_len) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
-    X509_free(x509);
-    return 0;
-  }
-
-  int ret = SSL_CTX_use_certificate(ctx, x509);
-  X509_free(x509);
-  return ret;
-}
-
-int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa) {
-  int ret;
-  EVP_PKEY *pkey;
-
-  if (rsa == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
-    return 0;
-  }
-
-  pkey = EVP_PKEY_new();
-  if (pkey == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_EVP_LIB);
-    return 0;
-  }
-
-  RSA_up_ref(rsa);
-  EVP_PKEY_assign_RSA(pkey, rsa);
-
-  ret = ssl_set_pkey(ctx->cert, pkey);
-  EVP_PKEY_free(pkey);
-  return ret;
-}
-
-int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const uint8_t *der,
-                                   size_t der_len) {
-  RSA *rsa = RSA_private_key_from_bytes(der, der_len);
-  if (rsa == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
-    return 0;
-  }
-
-  int ret = SSL_CTX_use_RSAPrivateKey(ctx, rsa);
-  RSA_free(rsa);
-  return ret;
-}
-
-int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey) {
-  if (pkey == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
-    return 0;
-  }
-
-  return ssl_set_pkey(ctx->cert, pkey);
-}
-
-int SSL_CTX_use_PrivateKey_ASN1(int type, SSL_CTX *ctx, const uint8_t *der,
-                                size_t der_len) {
-  if (der_len > LONG_MAX) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
-    return 0;
-  }
-
-  const uint8_t *p = der;
-  EVP_PKEY *pkey = d2i_PrivateKey(type, NULL, &p, (long)der_len);
-  if (pkey == NULL || p != der + der_len) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_ASN1_LIB);
-    EVP_PKEY_free(pkey);
-    return 0;
-  }
-
-  int ret = SSL_CTX_use_PrivateKey(ctx, pkey);
-  EVP_PKEY_free(pkey);
-  return ret;
-}
-
-void SSL_set_private_key_method(SSL *ssl,
-                                const SSL_PRIVATE_KEY_METHOD *key_method) {
-  ssl->cert->key_method = key_method;
-}
-
-int SSL_set_private_key_digest_prefs(SSL *ssl, const int *digest_nids,
-                                     size_t num_digests) {
-  OPENSSL_free(ssl->cert->digest_nids);
-
-  ssl->cert->num_digest_nids = 0;
-  ssl->cert->digest_nids = BUF_memdup(digest_nids, num_digests*sizeof(int));
-  if (ssl->cert->digest_nids == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-    return 0;
-  }
-
-  ssl->cert->num_digest_nids = num_digests;
-  return 1;
-}
-
-int ssl_has_private_key(SSL *ssl) {
-  return ssl->cert->privatekey != NULL || ssl->cert->key_method != NULL;
-}
-
-int ssl_private_key_type(SSL *ssl) {
-  if (ssl->cert->key_method != NULL) {
-    return ssl->cert->key_method->type(ssl);
-  }
-  return EVP_PKEY_id(ssl->cert->privatekey);
-}
-
-size_t ssl_private_key_max_signature_len(SSL *ssl) {
-  if (ssl->cert->key_method != NULL) {
-    return ssl->cert->key_method->max_signature_len(ssl);
-  }
-  return EVP_PKEY_size(ssl->cert->privatekey);
-}
-
-enum ssl_private_key_result_t ssl_private_key_sign(
-    SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out, const EVP_MD *md,
-    const uint8_t *in, size_t in_len) {
-  if (ssl->cert->key_method != NULL) {
-    return ssl->cert->key_method->sign(ssl, out, out_len, max_out, md, in,
-                                       in_len);
-  }
-
-  enum ssl_private_key_result_t ret = ssl_private_key_failure;
-  EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(ssl->cert->privatekey, NULL);
-  if (ctx == NULL) {
-    goto end;
-  }
-
-  size_t len = max_out;
-  if (!EVP_PKEY_sign_init(ctx) ||
-      !EVP_PKEY_CTX_set_signature_md(ctx, md) ||
-      !EVP_PKEY_sign(ctx, out, &len, in, in_len)) {
-    goto end;
-  }
-  *out_len = len;
-  ret = ssl_private_key_success;
-
-end:
-  EVP_PKEY_CTX_free(ctx);
-  return ret;
-}
-
-enum ssl_private_key_result_t ssl_private_key_sign_complete(
-    SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out) {
-  /* Only custom keys may be asynchronous. */
-  return ssl->cert->key_method->sign_complete(ssl, out, out_len, max_out);
-}
-
-enum ssl_private_key_result_t ssl_private_key_decrypt(
-    SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
-    const uint8_t *in, size_t in_len) {
-  if (ssl->cert->key_method != NULL) {
-    return ssl->cert->key_method->decrypt(ssl, out, out_len, max_out, in,
-                                          in_len);
-  }
-
-  RSA *rsa = EVP_PKEY_get0_RSA(ssl->cert->privatekey);
-  if (rsa == NULL) {
-    /* Decrypt operations are only supported for RSA keys. */
-    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    return ssl_private_key_failure;
-  }
-
-  /* Decrypt with no padding. PKCS#1 padding will be removed as part
-   * of the timing-sensitive code by the caller. */
-  if (!RSA_decrypt(rsa, out_len, out, max_out, in, in_len, RSA_NO_PADDING)) {
-    return ssl_private_key_failure;
-  }
-  return ssl_private_key_success;
-}
-
-enum ssl_private_key_result_t ssl_private_key_decrypt_complete(
-    SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out) {
-  /* Only custom keys may be asynchronous. */
-  return ssl->cert->key_method->decrypt_complete(ssl, out, out_len, max_out);
-}
diff --git a/src/ssl/ssl_session.c b/src/ssl/ssl_session.c
index 3d59bc3..05ae059 100644
--- a/src/ssl/ssl_session.c
+++ b/src/ssl/ssl_session.c
@@ -136,7 +136,7 @@
 #include <openssl/ssl.h>
 
 #include <assert.h>
-#include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include <openssl/err.h>
@@ -160,27 +160,208 @@
 static void SSL_SESSION_list_add(SSL_CTX *ctx, SSL_SESSION *session);
 static int remove_session_lock(SSL_CTX *ctx, SSL_SESSION *session, int lock);
 
-SSL_SESSION *SSL_SESSION_new(void) {
-  SSL_SESSION *session = (SSL_SESSION *)OPENSSL_malloc(sizeof(SSL_SESSION));
+SSL_SESSION *ssl_session_new(const SSL_X509_METHOD *x509_method) {
+  SSL_SESSION *session = OPENSSL_malloc(sizeof(SSL_SESSION));
   if (session == NULL) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
     return 0;
   }
-  memset(session, 0, sizeof(SSL_SESSION));
+  OPENSSL_memset(session, 0, sizeof(SSL_SESSION));
 
-  session->verify_result = 1; /* avoid 0 (= X509_V_OK) just in case */
+  session->x509_method = x509_method;
+  session->verify_result = X509_V_ERR_INVALID_CALL;
   session->references = 1;
   session->timeout = SSL_DEFAULT_SESSION_TIMEOUT;
-  session->time = (unsigned long)time(NULL);
+  session->auth_timeout = SSL_DEFAULT_SESSION_TIMEOUT;
+  session->time = time(NULL);
   CRYPTO_new_ex_data(&session->ex_data);
   return session;
 }
 
-SSL_SESSION *SSL_SESSION_up_ref(SSL_SESSION *session) {
-  if (session != NULL) {
-    CRYPTO_refcount_inc(&session->references);
+SSL_SESSION *SSL_SESSION_new(const SSL_CTX *ctx) {
+  return ssl_session_new(ctx->x509_method);
+}
+
+SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *session, int dup_flags) {
+  SSL_SESSION *new_session = ssl_session_new(session->x509_method);
+  if (new_session == NULL) {
+    goto err;
   }
-  return session;
+
+  new_session->is_server = session->is_server;
+  new_session->ssl_version = session->ssl_version;
+  new_session->sid_ctx_length = session->sid_ctx_length;
+  OPENSSL_memcpy(new_session->sid_ctx, session->sid_ctx, session->sid_ctx_length);
+
+  /* Copy the key material. */
+  new_session->master_key_length = session->master_key_length;
+  OPENSSL_memcpy(new_session->master_key, session->master_key,
+         session->master_key_length);
+  new_session->cipher = session->cipher;
+
+  /* Copy authentication state. */
+  if (session->psk_identity != NULL) {
+    new_session->psk_identity = BUF_strdup(session->psk_identity);
+    if (new_session->psk_identity == NULL) {
+      goto err;
+    }
+  }
+  if (session->certs != NULL) {
+    new_session->certs = sk_CRYPTO_BUFFER_new_null();
+    if (new_session->certs == NULL) {
+      goto err;
+    }
+    for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(session->certs); i++) {
+      CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(session->certs, i);
+      if (!sk_CRYPTO_BUFFER_push(new_session->certs, buffer)) {
+        goto err;
+      }
+      CRYPTO_BUFFER_up_ref(buffer);
+    }
+  }
+
+  if (!session->x509_method->session_dup(new_session, session)) {
+    goto err;
+  }
+
+  new_session->verify_result = session->verify_result;
+
+  new_session->ocsp_response_length = session->ocsp_response_length;
+  if (session->ocsp_response != NULL) {
+    new_session->ocsp_response = BUF_memdup(session->ocsp_response,
+                                            session->ocsp_response_length);
+    if (new_session->ocsp_response == NULL) {
+      goto err;
+    }
+  }
+
+  new_session->tlsext_signed_cert_timestamp_list_length =
+      session->tlsext_signed_cert_timestamp_list_length;
+  if (session->tlsext_signed_cert_timestamp_list != NULL) {
+    new_session->tlsext_signed_cert_timestamp_list =
+        BUF_memdup(session->tlsext_signed_cert_timestamp_list,
+                   session->tlsext_signed_cert_timestamp_list_length);
+    if (new_session->tlsext_signed_cert_timestamp_list == NULL) {
+      goto err;
+    }
+  }
+
+  OPENSSL_memcpy(new_session->peer_sha256, session->peer_sha256,
+                 SHA256_DIGEST_LENGTH);
+  new_session->peer_sha256_valid = session->peer_sha256_valid;
+
+  if (session->tlsext_hostname != NULL) {
+    new_session->tlsext_hostname = BUF_strdup(session->tlsext_hostname);
+    if (new_session->tlsext_hostname == NULL) {
+      goto err;
+    }
+  }
+
+  new_session->peer_signature_algorithm = session->peer_signature_algorithm;
+
+  new_session->timeout = session->timeout;
+  new_session->auth_timeout = session->auth_timeout;
+  new_session->time = session->time;
+
+  /* Copy non-authentication connection properties. */
+  if (dup_flags & SSL_SESSION_INCLUDE_NONAUTH) {
+    new_session->session_id_length = session->session_id_length;
+    OPENSSL_memcpy(new_session->session_id, session->session_id,
+                   session->session_id_length);
+
+    new_session->group_id = session->group_id;
+
+    OPENSSL_memcpy(new_session->original_handshake_hash,
+                   session->original_handshake_hash,
+                   session->original_handshake_hash_len);
+    new_session->original_handshake_hash_len =
+        session->original_handshake_hash_len;
+    new_session->tlsext_tick_lifetime_hint = session->tlsext_tick_lifetime_hint;
+    new_session->ticket_age_add = session->ticket_age_add;
+    new_session->ticket_max_early_data = session->ticket_max_early_data;
+    new_session->extended_master_secret = session->extended_master_secret;
+
+    if (session->early_alpn != NULL) {
+      new_session->early_alpn =
+          BUF_memdup(session->early_alpn, session->early_alpn_len);
+      if (new_session->early_alpn == NULL) {
+        goto err;
+      }
+    }
+    new_session->early_alpn_len = session->early_alpn_len;
+  }
+
+  /* Copy the ticket. */
+  if (dup_flags & SSL_SESSION_INCLUDE_TICKET) {
+    if (session->tlsext_tick != NULL) {
+      new_session->tlsext_tick =
+          BUF_memdup(session->tlsext_tick, session->tlsext_ticklen);
+      if (new_session->tlsext_tick == NULL) {
+        goto err;
+      }
+    }
+    new_session->tlsext_ticklen = session->tlsext_ticklen;
+  }
+
+  /* The new_session does not get a copy of the ex_data. */
+
+  new_session->not_resumable = 1;
+  return new_session;
+
+err:
+  SSL_SESSION_free(new_session);
+  OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+  return 0;
+}
+
+void ssl_session_rebase_time(SSL *ssl, SSL_SESSION *session) {
+  struct OPENSSL_timeval now;
+  ssl_get_current_time(ssl, &now);
+
+  /* To avoid overflows and underflows, if we've gone back in time, update the
+   * time, but mark the session expired. */
+  if (session->time > now.tv_sec) {
+    session->time = now.tv_sec;
+    session->timeout = 0;
+    session->auth_timeout = 0;
+    return;
+  }
+
+  /* Adjust the session time and timeouts. If the session has already expired,
+   * clamp the timeouts at zero. */
+  uint64_t delta = now.tv_sec - session->time;
+  session->time = now.tv_sec;
+  if (session->timeout < delta) {
+    session->timeout = 0;
+  } else {
+    session->timeout -= delta;
+  }
+  if (session->auth_timeout < delta) {
+    session->auth_timeout = 0;
+  } else {
+    session->auth_timeout -= delta;
+  }
+}
+
+void ssl_session_renew_timeout(SSL *ssl, SSL_SESSION *session,
+                               uint32_t timeout) {
+  /* Rebase the timestamp relative to the current time so |timeout| is measured
+   * correctly. */
+  ssl_session_rebase_time(ssl, session);
+
+  if (session->timeout > timeout) {
+    return;
+  }
+
+  session->timeout = timeout;
+  if (session->timeout > session->auth_timeout) {
+    session->timeout = session->auth_timeout;
+  }
+}
+
+int SSL_SESSION_up_ref(SSL_SESSION *session) {
+  CRYPTO_refcount_inc(&session->references);
+  return 1;
 }
 
 void SSL_SESSION_free(SSL_SESSION *session) {
@@ -193,13 +374,14 @@
 
   OPENSSL_cleanse(session->master_key, sizeof(session->master_key));
   OPENSSL_cleanse(session->session_id, sizeof(session->session_id));
-  X509_free(session->peer);
-  sk_X509_pop_free(session->cert_chain, X509_free);
+  sk_CRYPTO_BUFFER_pop_free(session->certs, CRYPTO_BUFFER_free);
+  session->x509_method->session_clear(session);
   OPENSSL_free(session->tlsext_hostname);
   OPENSSL_free(session->tlsext_tick);
   OPENSSL_free(session->tlsext_signed_cert_timestamp_list);
   OPENSSL_free(session->ocsp_response);
   OPENSSL_free(session->psk_identity);
+  OPENSSL_free(session->early_alpn);
   OPENSSL_cleanse(session, sizeof(*session));
   OPENSSL_free(session);
 }
@@ -212,11 +394,11 @@
   return session->session_id;
 }
 
-long SSL_SESSION_get_timeout(const SSL_SESSION *session) {
+uint32_t SSL_SESSION_get_timeout(const SSL_SESSION *session) {
   return session->timeout;
 }
 
-long SSL_SESSION_get_time(const SSL_SESSION *session) {
+uint64_t SSL_SESSION_get_time(const SSL_SESSION *session) {
   if (session == NULL) {
     /* NULL should crash, but silently accept it here for compatibility. */
     return 0;
@@ -224,15 +406,24 @@
   return session->time;
 }
 
-uint32_t SSL_SESSION_get_key_exchange_info(const SSL_SESSION *session) {
-  return session->key_exchange_info;
-}
-
 X509 *SSL_SESSION_get0_peer(const SSL_SESSION *session) {
-  return session->peer;
+  return session->x509_peer;
 }
 
-long SSL_SESSION_set_time(SSL_SESSION *session, long time) {
+size_t SSL_SESSION_get_master_key(const SSL_SESSION *session, uint8_t *out,
+                                  size_t max_out) {
+  /* TODO(davidben): Fix master_key_length's type and remove these casts. */
+  if (max_out == 0) {
+    return (size_t)session->master_key_length;
+  }
+  if (max_out > (size_t)session->master_key_length) {
+    max_out = (size_t)session->master_key_length;
+  }
+  OPENSSL_memcpy(out, session->master_key, max_out);
+  return max_out;
+}
+
+uint64_t SSL_SESSION_set_time(SSL_SESSION *session, uint64_t time) {
   if (session == NULL) {
     return 0;
   }
@@ -241,24 +432,26 @@
   return time;
 }
 
-long SSL_SESSION_set_timeout(SSL_SESSION *session, long timeout) {
+uint32_t SSL_SESSION_set_timeout(SSL_SESSION *session, uint32_t timeout) {
   if (session == NULL) {
     return 0;
   }
 
   session->timeout = timeout;
+  session->auth_timeout = timeout;
   return 1;
 }
 
 int SSL_SESSION_set1_id_context(SSL_SESSION *session, const uint8_t *sid_ctx,
-                                unsigned sid_ctx_len) {
-  if (sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) {
+                                size_t sid_ctx_len) {
+  if (sid_ctx_len > sizeof(session->sid_ctx)) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
     return 0;
   }
 
-  session->sid_ctx_length = sid_ctx_len;
-  memcpy(session->sid_ctx, sid_ctx, sid_ctx_len);
+  assert(sizeof(session->sid_ctx) < 256);
+  session->sid_ctx_length = (uint8_t)sid_ctx_len;
+  OPENSSL_memcpy(session->sid_ctx, sid_ctx, sid_ctx_len);
 
   return 1;
 }
@@ -267,15 +460,25 @@
   return (SSL_SESSION *)&g_pending_session_magic;
 }
 
-SSL_SESSION *SSL_get_session(const SSL *ssl)
-{
-  /* aka SSL_get0_session; gets 0 objects, just returns a copy of the pointer */
+SSL_SESSION *SSL_get_session(const SSL *ssl) {
+  /* Once the handshake completes we return the established session. Otherwise
+   * we return the intermediate session, either |session| (for resumption) or
+   * |new_session| if doing a full handshake. */
+  if (!SSL_in_init(ssl)) {
+    return ssl->s3->established_session;
+  }
+  if (ssl->s3->hs->new_session != NULL) {
+    return ssl->s3->hs->new_session;
+  }
   return ssl->session;
 }
 
 SSL_SESSION *SSL_get1_session(SSL *ssl) {
-  /* variant of SSL_get_session: caller really gets something */
-  return SSL_SESSION_up_ref(ssl->session);
+  SSL_SESSION *ret = SSL_get_session(ssl);
+  if (ret != NULL) {
+    SSL_SESSION_up_ref(ret);
+  }
+  return ret;
 }
 
 int SSL_SESSION_get_ex_new_index(long argl, void *argp,
@@ -298,26 +501,51 @@
   return CRYPTO_get_ex_data(&session->ex_data, idx);
 }
 
-int ssl_get_new_session(SSL *ssl, int is_server) {
+const EVP_MD *SSL_SESSION_get_digest(const SSL_SESSION *session,
+                                     const SSL *ssl) {
+  uint16_t version;
+  if (!ssl->method->version_from_wire(&version, session->ssl_version)) {
+    return NULL;
+  }
+
+  return ssl_get_handshake_digest(session->cipher->algorithm_prf, version);
+}
+
+int ssl_get_new_session(SSL_HANDSHAKE *hs, int is_server) {
+  SSL *const ssl = hs->ssl;
   if (ssl->mode & SSL_MODE_NO_SESSION_CREATION) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_SESSION_MAY_NOT_BE_CREATED);
     return 0;
   }
 
-  SSL_SESSION *session = SSL_SESSION_new();
+  SSL_SESSION *session = ssl_session_new(ssl->ctx->x509_method);
   if (session == NULL) {
     return 0;
   }
 
-  /* If the context has a default timeout, use it over the default. */
-  if (ssl->initial_ctx->session_timeout != 0) {
-    session->timeout = ssl->initial_ctx->session_timeout;
-  }
-
+  session->is_server = is_server;
   session->ssl_version = ssl->version;
 
+  /* Fill in the time from the |SSL_CTX|'s clock. */
+  struct OPENSSL_timeval now;
+  ssl_get_current_time(ssl, &now);
+  session->time = now.tv_sec;
+
+  uint16_t version = ssl3_protocol_version(ssl);
+  if (version >= TLS1_3_VERSION) {
+    /* TLS 1.3 uses tickets as authenticators, so we are willing to use them for
+     * longer. */
+    session->timeout = ssl->session_ctx->session_psk_dhe_timeout;
+    session->auth_timeout = SSL_DEFAULT_SESSION_AUTH_TIMEOUT;
+  } else {
+    /* TLS 1.2 resumption does not incorporate new key material, so we use a
+     * much shorter timeout. */
+    session->timeout = ssl->session_ctx->session_timeout;
+    session->auth_timeout = ssl->session_ctx->session_timeout;
+  }
+
   if (is_server) {
-    if (ssl->tlsext_ticket_expected) {
+    if (hs->ticket_expected || version >= TLS1_3_VERSION) {
       /* Don't set session IDs for sessions resumed with tickets. This will keep
        * them out of the session cache. */
       session->session_id_length = 0;
@@ -327,29 +555,25 @@
         goto err;
       }
     }
-
-    if (ssl->tlsext_hostname != NULL) {
-      session->tlsext_hostname = BUF_strdup(ssl->tlsext_hostname);
-      if (session->tlsext_hostname == NULL) {
-        OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-        goto err;
-      }
-    }
   } else {
     session->session_id_length = 0;
   }
 
-  if (ssl->sid_ctx_length > sizeof(session->sid_ctx)) {
+  if (ssl->cert->sid_ctx_length > sizeof(session->sid_ctx)) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
     goto err;
   }
-  memcpy(session->sid_ctx, ssl->sid_ctx, ssl->sid_ctx_length);
-  session->sid_ctx_length = ssl->sid_ctx_length;
+  OPENSSL_memcpy(session->sid_ctx, ssl->cert->sid_ctx,
+                 ssl->cert->sid_ctx_length);
+  session->sid_ctx_length = ssl->cert->sid_ctx_length;
 
-  session->verify_result = X509_V_OK;
+  /* The session is marked not resumable until it is completely filled in. */
+  session->not_resumable = 1;
+  session->verify_result = X509_V_ERR_INVALID_CALL;
 
-  SSL_SESSION_free(ssl->session);
-  ssl->session = session;
+  SSL_SESSION_free(hs->new_session);
+  hs->new_session = session;
+  ssl_set_session(ssl, NULL);
   return 1;
 
 err:
@@ -357,6 +581,190 @@
   return 0;
 }
 
+static int ssl_encrypt_ticket_with_cipher_ctx(SSL *ssl, CBB *out,
+                                              const uint8_t *session_buf,
+                                              size_t session_len) {
+  int ret = 0;
+
+  EVP_CIPHER_CTX ctx;
+  EVP_CIPHER_CTX_init(&ctx);
+  HMAC_CTX hctx;
+  HMAC_CTX_init(&hctx);
+
+  /* If the session is too long, emit a dummy value rather than abort the
+   * connection. */
+  static const size_t kMaxTicketOverhead =
+      16 + EVP_MAX_IV_LENGTH + EVP_MAX_BLOCK_LENGTH + EVP_MAX_MD_SIZE;
+  if (session_len > 0xffff - kMaxTicketOverhead) {
+    static const char kTicketPlaceholder[] = "TICKET TOO LARGE";
+    if (CBB_add_bytes(out, (const uint8_t *)kTicketPlaceholder,
+                      strlen(kTicketPlaceholder))) {
+      ret = 1;
+    }
+    goto err;
+  }
+
+  /* Initialize HMAC and cipher contexts. If callback present it does all the
+   * work otherwise use generated values from parent ctx. */
+  SSL_CTX *tctx = ssl->session_ctx;
+  uint8_t iv[EVP_MAX_IV_LENGTH];
+  uint8_t key_name[16];
+  if (tctx->tlsext_ticket_key_cb != NULL) {
+    if (tctx->tlsext_ticket_key_cb(ssl, key_name, iv, &ctx, &hctx,
+                                   1 /* encrypt */) < 0) {
+      goto err;
+    }
+  } else {
+    if (!RAND_bytes(iv, 16) ||
+        !EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
+                            tctx->tlsext_tick_aes_key, iv) ||
+        !HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16, tlsext_tick_md(),
+                      NULL)) {
+      goto err;
+    }
+    OPENSSL_memcpy(key_name, tctx->tlsext_tick_key_name, 16);
+  }
+
+  uint8_t *ptr;
+  if (!CBB_add_bytes(out, key_name, 16) ||
+      !CBB_add_bytes(out, iv, EVP_CIPHER_CTX_iv_length(&ctx)) ||
+      !CBB_reserve(out, &ptr, session_len + EVP_MAX_BLOCK_LENGTH)) {
+    goto err;
+  }
+
+  size_t total = 0;
+#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
+  OPENSSL_memcpy(ptr, session_buf, session_len);
+  total = session_len;
+#else
+  int len;
+  if (!EVP_EncryptUpdate(&ctx, ptr + total, &len, session_buf, session_len)) {
+    goto err;
+  }
+  total += len;
+  if (!EVP_EncryptFinal_ex(&ctx, ptr + total, &len)) {
+    goto err;
+  }
+  total += len;
+#endif
+  if (!CBB_did_write(out, total)) {
+    goto err;
+  }
+
+  unsigned hlen;
+  if (!HMAC_Update(&hctx, CBB_data(out), CBB_len(out)) ||
+      !CBB_reserve(out, &ptr, EVP_MAX_MD_SIZE) ||
+      !HMAC_Final(&hctx, ptr, &hlen) ||
+      !CBB_did_write(out, hlen)) {
+    goto err;
+  }
+
+  ret = 1;
+
+err:
+  EVP_CIPHER_CTX_cleanup(&ctx);
+  HMAC_CTX_cleanup(&hctx);
+  return ret;
+}
+
+static int ssl_encrypt_ticket_with_method(SSL *ssl, CBB *out,
+                                          const uint8_t *session_buf,
+                                          size_t session_len) {
+  const SSL_TICKET_AEAD_METHOD *method = ssl->session_ctx->ticket_aead_method;
+  const size_t max_overhead = method->max_overhead(ssl);
+  const size_t max_out = session_len + max_overhead;
+  if (max_out < max_overhead) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
+    return 0;
+  }
+
+  uint8_t *ptr;
+  if (!CBB_reserve(out, &ptr, max_out)) {
+    return 0;
+  }
+
+  size_t out_len;
+  if (!method->seal(ssl, ptr, &out_len, max_out, session_buf, session_len)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_TICKET_ENCRYPTION_FAILED);
+    return 0;
+  }
+
+  if (!CBB_did_write(out, out_len)) {
+    return 0;
+  }
+
+  return 1;
+}
+
+int ssl_encrypt_ticket(SSL *ssl, CBB *out, const SSL_SESSION *session) {
+  /* Serialize the SSL_SESSION to be encoded into the ticket. */
+  uint8_t *session_buf = NULL;
+  size_t session_len;
+  if (!SSL_SESSION_to_bytes_for_ticket(session, &session_buf, &session_len)) {
+    return -1;
+  }
+
+  int ret = 0;
+  if (ssl->session_ctx->ticket_aead_method) {
+    ret = ssl_encrypt_ticket_with_method(ssl, out, session_buf, session_len);
+  } else {
+    ret =
+        ssl_encrypt_ticket_with_cipher_ctx(ssl, out, session_buf, session_len);
+  }
+
+  OPENSSL_free(session_buf);
+  return ret;
+}
+
+int ssl_session_is_context_valid(const SSL *ssl, const SSL_SESSION *session) {
+  if (session == NULL) {
+    return 0;
+  }
+
+  return session->sid_ctx_length == ssl->cert->sid_ctx_length &&
+         OPENSSL_memcmp(session->sid_ctx, ssl->cert->sid_ctx,
+                        ssl->cert->sid_ctx_length) == 0;
+}
+
+int ssl_session_is_time_valid(const SSL *ssl, const SSL_SESSION *session) {
+  if (session == NULL) {
+    return 0;
+  }
+
+  struct OPENSSL_timeval now;
+  ssl_get_current_time(ssl, &now);
+
+  /* Reject tickets from the future to avoid underflow. */
+  if (now.tv_sec < session->time) {
+    return 0;
+  }
+
+  return session->timeout > now.tv_sec - session->time;
+}
+
+int ssl_session_is_resumable(const SSL_HANDSHAKE *hs,
+                             const SSL_SESSION *session) {
+  const SSL *const ssl = hs->ssl;
+  return ssl_session_is_context_valid(ssl, session) &&
+         /* The session must have been created by the same type of end point as
+          * we're now using it with. */
+         ssl->server == session->is_server &&
+         /* The session must not be expired. */
+         ssl_session_is_time_valid(ssl, session) &&
+         /* Only resume if the session's version matches the negotiated
+           * version. */
+         ssl->version == session->ssl_version &&
+         /* Only resume if the session's cipher matches the negotiated one. */
+         hs->new_cipher == session->cipher &&
+         /* If the session contains a client certificate (either the full
+          * certificate or just the hash) then require that the form of the
+          * certificate matches the current configuration. */
+         ((sk_CRYPTO_BUFFER_num(session->certs) == 0 &&
+           !session->peer_sha256_valid) ||
+          session->peer_sha256_valid ==
+              ssl->retain_only_sha256_of_client_certs);
+}
+
 /* ssl_lookup_session looks up |session_id| in the session cache and sets
  * |*out_session| to an |SSL_SESSION| object if found. The caller takes
  * ownership of the result. */
@@ -369,55 +777,60 @@
     return ssl_session_success;
   }
 
-  SSL_SESSION *session;
+  SSL_SESSION *session = NULL;
   /* Try the internal cache, if it exists. */
-  if (!(ssl->initial_ctx->session_cache_mode &
+  if (!(ssl->session_ctx->session_cache_mode &
         SSL_SESS_CACHE_NO_INTERNAL_LOOKUP)) {
     SSL_SESSION data;
     data.ssl_version = ssl->version;
     data.session_id_length = session_id_len;
-    memcpy(data.session_id, session_id, session_id_len);
+    OPENSSL_memcpy(data.session_id, session_id, session_id_len);
 
-    CRYPTO_MUTEX_lock_read(&ssl->initial_ctx->lock);
-    session = lh_SSL_SESSION_retrieve(ssl->initial_ctx->sessions, &data);
+    CRYPTO_MUTEX_lock_read(&ssl->session_ctx->lock);
+    session = lh_SSL_SESSION_retrieve(ssl->session_ctx->sessions, &data);
     if (session != NULL) {
       SSL_SESSION_up_ref(session);
     }
     /* TODO(davidben): This should probably move it to the front of the list. */
-    CRYPTO_MUTEX_unlock(&ssl->initial_ctx->lock);
-
-    if (session != NULL) {
-      *out_session = session;
-      return ssl_session_success;
-    }
+    CRYPTO_MUTEX_unlock_read(&ssl->session_ctx->lock);
   }
 
   /* Fall back to the external cache, if it exists. */
-  if (ssl->initial_ctx->get_session_cb == NULL) {
-    return ssl_session_success;
-  }
-  int copy = 1;
-  session = ssl->initial_ctx->get_session_cb(ssl, (uint8_t *)session_id,
-                                             session_id_len, &copy);
-  if (session == NULL) {
-    return ssl_session_success;
-  }
-  if (session == SSL_magic_pending_session_ptr()) {
-    return ssl_session_retry;
+  if (session == NULL &&
+      ssl->session_ctx->get_session_cb != NULL) {
+    int copy = 1;
+    session = ssl->session_ctx->get_session_cb(ssl, (uint8_t *)session_id,
+                                               session_id_len, &copy);
+
+    if (session == NULL) {
+      return ssl_session_success;
+    }
+
+    if (session == SSL_magic_pending_session_ptr()) {
+      return ssl_session_retry;
+    }
+
+    /* Increment reference count now if the session callback asks us to do so
+     * (note that if the session structures returned by the callback are shared
+     * between threads, it must handle the reference count itself [i.e. copy ==
+     * 0], or things won't be thread-safe). */
+    if (copy) {
+      SSL_SESSION_up_ref(session);
+    }
+
+    /* Add the externally cached session to the internal cache if necessary. */
+    if (!(ssl->session_ctx->session_cache_mode &
+          SSL_SESS_CACHE_NO_INTERNAL_STORE)) {
+      SSL_CTX_add_session(ssl->session_ctx, session);
+    }
   }
 
-  /* Increment reference count now if the session callback asks us to do so
-   * (note that if the session structures returned by the callback are shared
-   * between threads, it must handle the reference count itself [i.e. copy ==
-   * 0], or things won't be thread-safe). */
-  if (copy) {
-    SSL_SESSION_up_ref(session);
-  }
-
-  /* Add the externally cached session to the internal cache if necessary. */
-  if (!(ssl->initial_ctx->session_cache_mode &
-        SSL_SESS_CACHE_NO_INTERNAL_STORE)) {
-    SSL_CTX_add_session(ssl->initial_ctx, session);
+  if (session != NULL &&
+      !ssl_session_is_time_valid(ssl, session)) {
+    /* The session was from the cache, so remove it. */
+    SSL_CTX_remove_session(ssl->session_ctx, session);
+    SSL_SESSION_free(session);
+    session = NULL;
   }
 
   *out_session = session;
@@ -425,12 +838,12 @@
 }
 
 enum ssl_session_result_t ssl_get_prev_session(
-    SSL *ssl, SSL_SESSION **out_session, int *out_send_ticket,
-    const struct ssl_early_callback_ctx *ctx) {
+    SSL *ssl, SSL_SESSION **out_session, int *out_tickets_supported,
+    int *out_renew_ticket, const SSL_CLIENT_HELLO *client_hello) {
   /* This is used only by servers. */
   assert(ssl->server);
   SSL_SESSION *session = NULL;
-  int send_ticket = 0;
+  int renew_ticket = 0;
 
   /* If tickets are disabled, always behave as if no tickets are present. */
   const uint8_t *ticket = NULL;
@@ -438,62 +851,34 @@
   const int tickets_supported =
       !(SSL_get_options(ssl) & SSL_OP_NO_TICKET) &&
       ssl->version > SSL3_VERSION &&
-      SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_session_ticket,
-                                           &ticket, &ticket_len);
-  if (tickets_supported) {
-    if (!tls_process_ticket(ssl, &session, &send_ticket, ticket, ticket_len,
-                            ctx->session_id, ctx->session_id_len)) {
-      return ssl_session_error;
+      SSL_early_callback_ctx_extension_get(
+          client_hello, TLSEXT_TYPE_session_ticket, &ticket, &ticket_len);
+  if (tickets_supported && ticket_len > 0) {
+    switch (ssl_process_ticket(ssl, &session, &renew_ticket, ticket, ticket_len,
+                               client_hello->session_id,
+                               client_hello->session_id_len)) {
+      case ssl_ticket_aead_success:
+        break;
+      case ssl_ticket_aead_ignore_ticket:
+        assert(session == NULL);
+        break;
+      case ssl_ticket_aead_error:
+        return ssl_session_error;
+      case ssl_ticket_aead_retry:
+        return ssl_session_ticket_retry;
     }
   } else {
-    /* The client does not support session tickets, so the session ID should be
-     * used instead. */
+    /* The client didn't send a ticket, so the session ID is a real ID. */
     enum ssl_session_result_t lookup_ret = ssl_lookup_session(
-        ssl, &session, ctx->session_id, ctx->session_id_len);
+        ssl, &session, client_hello->session_id, client_hello->session_id_len);
     if (lookup_ret != ssl_session_success) {
       return lookup_ret;
     }
   }
 
-  if (session == NULL ||
-      session->sid_ctx_length != ssl->sid_ctx_length ||
-      memcmp(session->sid_ctx, ssl->sid_ctx, ssl->sid_ctx_length) != 0) {
-    goto no_session;
-  }
-
-  if ((ssl->verify_mode & SSL_VERIFY_PEER) && ssl->sid_ctx_length == 0) {
-    /* We can't be sure if this session is being used out of context, which is
-     * especially important for SSL_VERIFY_PEER. The application should have
-     * used SSL[_CTX]_set_session_id_context.
-     *
-     * For this error case, we generate an error instead of treating the event
-     * like a cache miss (otherwise it would be easy for applications to
-     * effectively disable the session cache by accident without anyone
-     * noticing). */
-    OPENSSL_PUT_ERROR(SSL, SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED);
-    goto fatal_error;
-  }
-
-  if (session->timeout < (long)(time(NULL) - session->time)) {
-    if (!tickets_supported) {
-      /* The session was from the cache, so remove it. */
-      SSL_CTX_remove_session(ssl->initial_ctx, session);
-    }
-    goto no_session;
-  }
-
   *out_session = session;
-  *out_send_ticket = send_ticket;
-  return ssl_session_success;
-
-fatal_error:
-  SSL_SESSION_free(session);
-  return ssl_session_error;
-
-no_session:
-  *out_session = NULL;
-  *out_send_ticket = tickets_supported;
-  SSL_SESSION_free(session);
+  *out_tickets_supported = tickets_supported;
+  *out_renew_ticket = renew_ticket;
   return ssl_session_success;
 }
 
@@ -505,7 +890,7 @@
   SSL_SESSION *old_session;
   CRYPTO_MUTEX_lock_write(&ctx->lock);
   if (!lh_SSL_SESSION_insert(ctx->sessions, &old_session, session)) {
-    CRYPTO_MUTEX_unlock(&ctx->lock);
+    CRYPTO_MUTEX_unlock_write(&ctx->lock);
     SSL_SESSION_free(session);
     return 0;
   }
@@ -513,7 +898,7 @@
   if (old_session != NULL) {
     if (old_session == session) {
       /* |session| was already in the cache. */
-      CRYPTO_MUTEX_unlock(&ctx->lock);
+      CRYPTO_MUTEX_unlock_write(&ctx->lock);
       SSL_SESSION_free(old_session);
       return 0;
     }
@@ -535,7 +920,7 @@
     }
   }
 
-  CRYPTO_MUTEX_unlock(&ctx->lock);
+  CRYPTO_MUTEX_unlock_write(&ctx->lock);
   return 1;
 }
 
@@ -559,7 +944,7 @@
     }
 
     if (lock) {
-      CRYPTO_MUTEX_unlock(&ctx->lock);
+      CRYPTO_MUTEX_unlock_write(&ctx->lock);
     }
 
     if (ret) {
@@ -575,31 +960,45 @@
 }
 
 int SSL_set_session(SSL *ssl, SSL_SESSION *session) {
+  /* SSL_set_session may only be called before the handshake has started. */
+  if (ssl->s3->initial_handshake_complete ||
+      ssl->s3->hs == NULL ||
+      ssl->s3->hs->state != SSL_ST_INIT) {
+    abort();
+  }
+
+  ssl_set_session(ssl, session);
+  return 1;
+}
+
+void ssl_set_session(SSL *ssl, SSL_SESSION *session) {
   if (ssl->session == session) {
-    return 1;
+    return;
   }
 
   SSL_SESSION_free(ssl->session);
   ssl->session = session;
   if (session != NULL) {
     SSL_SESSION_up_ref(session);
-    ssl->verify_result = session->verify_result;
   }
-
-  return 1;
 }
 
-long SSL_CTX_set_timeout(SSL_CTX *ctx, long timeout) {
+uint32_t SSL_CTX_set_timeout(SSL_CTX *ctx, uint32_t timeout) {
   if (ctx == NULL) {
     return 0;
   }
 
-  long old_timeout = ctx->session_timeout;
+  /* Historically, zero was treated as |SSL_DEFAULT_SESSION_TIMEOUT|. */
+  if (timeout == 0) {
+    timeout = SSL_DEFAULT_SESSION_TIMEOUT;
+  }
+
+  uint32_t old_timeout = ctx->session_timeout;
   ctx->session_timeout = timeout;
   return old_timeout;
 }
 
-long SSL_CTX_get_timeout(const SSL_CTX *ctx) {
+uint32_t SSL_CTX_get_timeout(const SSL_CTX *ctx) {
   if (ctx == NULL) {
     return 0;
   }
@@ -607,9 +1006,13 @@
   return ctx->session_timeout;
 }
 
+void SSL_CTX_set_session_psk_dhe_timeout(SSL_CTX *ctx, uint32_t timeout) {
+  ctx->session_psk_dhe_timeout = timeout;
+}
+
 typedef struct timeout_param_st {
   SSL_CTX *ctx;
-  long time;
+  uint64_t time;
   LHASH_OF(SSL_SESSION) *cache;
 } TIMEOUT_PARAM;
 
@@ -617,6 +1020,7 @@
   TIMEOUT_PARAM *param = void_param;
 
   if (param->time == 0 ||
+      session->time + session->timeout < session->time ||
       param->time > (session->time + session->timeout)) {
     /* timeout */
     /* The reason we don't call SSL_CTX_remove_session() is to
@@ -631,7 +1035,7 @@
   }
 }
 
-void SSL_CTX_flush_sessions(SSL_CTX *ctx, long time) {
+void SSL_CTX_flush_sessions(SSL_CTX *ctx, uint64_t time) {
   TIMEOUT_PARAM tp;
 
   tp.ctx = ctx;
@@ -642,17 +1046,7 @@
   tp.time = time;
   CRYPTO_MUTEX_lock_write(&ctx->lock);
   lh_SSL_SESSION_doall_arg(tp.cache, timeout_doall_arg, &tp);
-  CRYPTO_MUTEX_unlock(&ctx->lock);
-}
-
-int ssl_clear_bad_session(SSL *ssl) {
-  if (ssl->session != NULL && !(ssl->shutdown & SSL_SENT_SHUTDOWN) &&
-      !SSL_in_init(ssl)) {
-    SSL_CTX_remove_session(ssl->ctx, ssl->session);
-    return 1;
-  }
-
-  return 0;
+  CRYPTO_MUTEX_unlock_write(&ctx->lock);
 }
 
 /* locked by SSL_CTX in the calling function */
@@ -743,17 +1137,6 @@
   return ctx->info_callback;
 }
 
-void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, int (*cb)(SSL *ssl,
-                                                        X509 **out_x509,
-                                                        EVP_PKEY **out_pkey)) {
-  ctx->client_cert_cb = cb;
-}
-
-int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx))(SSL *ssl, X509 **out_x509,
-                                                EVP_PKEY **out_pkey) {
-  return ctx->client_cert_cb;
-}
-
 void SSL_CTX_set_channel_id_cb(SSL_CTX *ctx,
                                void (*cb)(SSL *ssl, EVP_PKEY **pkey)) {
   ctx->channel_id_cb = cb;
diff --git a/src/ssl/ssl_stat.c b/src/ssl/ssl_stat.c
index 8fa197d..571b4a9 100644
--- a/src/ssl/ssl_stat.c
+++ b/src/ssl/ssl_stat.c
@@ -83,11 +83,22 @@
 
 #include <openssl/ssl.h>
 
+#include <assert.h>
+
 #include "internal.h"
 
 
+static int ssl_state(const SSL *ssl) {
+  if (ssl->s3->hs == NULL) {
+    assert(ssl->s3->initial_handshake_complete);
+    return SSL_ST_OK;
+  }
+
+  return ssl->s3->hs->state;
+}
+
 const char *SSL_state_string_long(const SSL *ssl) {
-  switch (ssl->state) {
+  switch (ssl_state(ssl)) {
     case SSL_ST_ACCEPT:
       return "before accept initialization";
 
@@ -104,85 +115,44 @@
     case SSL3_ST_CW_CLNT_HELLO_A:
       return "SSLv3 write client hello A";
 
-    case SSL3_ST_CW_CLNT_HELLO_B:
-      return "SSLv3 write client hello B";
-
     case SSL3_ST_CR_SRVR_HELLO_A:
       return "SSLv3 read server hello A";
 
-    case SSL3_ST_CR_SRVR_HELLO_B:
-      return "SSLv3 read server hello B";
-
     case SSL3_ST_CR_CERT_A:
       return "SSLv3 read server certificate A";
 
-    case SSL3_ST_CR_CERT_B:
-      return "SSLv3 read server certificate B";
-
     case SSL3_ST_CR_KEY_EXCH_A:
       return "SSLv3 read server key exchange A";
 
-    case SSL3_ST_CR_KEY_EXCH_B:
-      return "SSLv3 read server key exchange B";
-
     case SSL3_ST_CR_CERT_REQ_A:
       return "SSLv3 read server certificate request A";
 
-    case SSL3_ST_CR_CERT_REQ_B:
-      return "SSLv3 read server certificate request B";
-
     case SSL3_ST_CR_SESSION_TICKET_A:
       return "SSLv3 read server session ticket A";
 
-    case SSL3_ST_CR_SESSION_TICKET_B:
-      return "SSLv3 read server session ticket B";
-
     case SSL3_ST_CR_SRVR_DONE_A:
       return "SSLv3 read server done A";
 
-    case SSL3_ST_CR_SRVR_DONE_B:
-      return "SSLv3 read server done B";
-
     case SSL3_ST_CW_CERT_A:
       return "SSLv3 write client certificate A";
 
-    case SSL3_ST_CW_CERT_B:
-      return "SSLv3 write client certificate B";
-
-    case SSL3_ST_CW_CERT_C:
-      return "SSLv3 write client certificate C";
-
-    case SSL3_ST_CW_CERT_D:
-      return "SSLv3 write client certificate D";
-
     case SSL3_ST_CW_KEY_EXCH_A:
       return "SSLv3 write client key exchange A";
 
-    case SSL3_ST_CW_KEY_EXCH_B:
-      return "SSLv3 write client key exchange B";
-
     case SSL3_ST_CW_CERT_VRFY_A:
       return "SSLv3 write certificate verify A";
 
     case SSL3_ST_CW_CERT_VRFY_B:
       return "SSLv3 write certificate verify B";
 
-    case SSL3_ST_CW_CHANGE_A:
-    case SSL3_ST_SW_CHANGE_A:
-      return "SSLv3 write change cipher spec A";
-
-    case SSL3_ST_CW_CHANGE_B:
-    case SSL3_ST_SW_CHANGE_B:
-      return "SSLv3 write change cipher spec B";
+    case SSL3_ST_CW_CHANGE:
+    case SSL3_ST_SW_CHANGE:
+      return "SSLv3 write change cipher spec";
 
     case SSL3_ST_CW_FINISHED_A:
     case SSL3_ST_SW_FINISHED_A:
       return "SSLv3 write finished A";
 
-    case SSL3_ST_CW_FINISHED_B:
-    case SSL3_ST_SW_FINISHED_B:
-      return "SSLv3 write finished B";
-
     case SSL3_ST_CR_CHANGE:
     case SSL3_ST_SR_CHANGE:
       return "SSLv3 read change cipher spec";
@@ -191,10 +161,6 @@
     case SSL3_ST_SR_FINISHED_A:
       return "SSLv3 read finished A";
 
-    case SSL3_ST_CR_FINISHED_B:
-    case SSL3_ST_SR_FINISHED_B:
-      return "SSLv3 read finished B";
-
     case SSL3_ST_CW_FLUSH:
     case SSL3_ST_SW_FLUSH:
       return "SSLv3 flush data";
@@ -208,60 +174,27 @@
     case SSL3_ST_SR_CLNT_HELLO_C:
       return "SSLv3 read client hello C";
 
-    case SSL3_ST_SR_CLNT_HELLO_D:
-      return "SSLv3 read client hello D";
-
-    case SSL3_ST_SW_HELLO_REQ_A:
-      return "SSLv3 write hello request A";
-
-    case SSL3_ST_SW_HELLO_REQ_B:
-      return "SSLv3 write hello request B";
-
-    case SSL3_ST_SW_HELLO_REQ_C:
-      return "SSLv3 write hello request C";
-
     case SSL3_ST_SW_SRVR_HELLO_A:
       return "SSLv3 write server hello A";
 
-    case SSL3_ST_SW_SRVR_HELLO_B:
-      return "SSLv3 write server hello B";
-
     case SSL3_ST_SW_CERT_A:
       return "SSLv3 write certificate A";
 
-    case SSL3_ST_SW_CERT_B:
-      return "SSLv3 write certificate B";
-
     case SSL3_ST_SW_KEY_EXCH_A:
       return "SSLv3 write key exchange A";
 
-    case SSL3_ST_SW_KEY_EXCH_B:
-      return "SSLv3 write key exchange B";
-
     case SSL3_ST_SW_CERT_REQ_A:
       return "SSLv3 write certificate request A";
 
-    case SSL3_ST_SW_CERT_REQ_B:
-      return "SSLv3 write certificate request B";
-
     case SSL3_ST_SW_SESSION_TICKET_A:
       return "SSLv3 write session ticket A";
 
-    case SSL3_ST_SW_SESSION_TICKET_B:
-      return "SSLv3 write session ticket B";
-
     case SSL3_ST_SW_SRVR_DONE_A:
       return "SSLv3 write server done A";
 
-    case SSL3_ST_SW_SRVR_DONE_B:
-      return "SSLv3 write server done B";
-
     case SSL3_ST_SR_CERT_A:
       return "SSLv3 read client certificate A";
 
-    case SSL3_ST_SR_CERT_B:
-      return "SSLv3 read client certificate B";
-
     case SSL3_ST_SR_KEY_EXCH_A:
       return "SSLv3 read client key exchange A";
 
@@ -271,23 +204,17 @@
     case SSL3_ST_SR_CERT_VRFY_A:
       return "SSLv3 read certificate verify A";
 
-    case SSL3_ST_SR_CERT_VRFY_B:
-      return "SSLv3 read certificate verify B";
-
     /* DTLS */
     case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A:
       return "DTLS1 read hello verify request A";
 
-    case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B:
-      return "DTLS1 read hello verify request B";
-
     default:
       return "unknown state";
   }
 }
 
 const char *SSL_state_string(const SSL *ssl) {
-  switch (ssl->state) {
+  switch (ssl_state(ssl)) {
     case SSL_ST_ACCEPT:
       return "AINIT ";
 
@@ -305,79 +232,41 @@
     case SSL3_ST_CW_CLNT_HELLO_A:
       return "3WCH_A";
 
-    case SSL3_ST_CW_CLNT_HELLO_B:
-      return "3WCH_B";
-
     case SSL3_ST_CR_SRVR_HELLO_A:
       return "3RSH_A";
 
-    case SSL3_ST_CR_SRVR_HELLO_B:
-      return "3RSH_B";
-
     case SSL3_ST_CR_CERT_A:
       return "3RSC_A";
 
-    case SSL3_ST_CR_CERT_B:
-      return "3RSC_B";
-
     case SSL3_ST_CR_KEY_EXCH_A:
       return "3RSKEA";
 
-    case SSL3_ST_CR_KEY_EXCH_B:
-      return "3RSKEB";
-
     case SSL3_ST_CR_CERT_REQ_A:
       return "3RCR_A";
 
-    case SSL3_ST_CR_CERT_REQ_B:
-      return "3RCR_B";
-
     case SSL3_ST_CR_SRVR_DONE_A:
       return "3RSD_A";
 
-    case SSL3_ST_CR_SRVR_DONE_B:
-      return "3RSD_B";
-
     case SSL3_ST_CW_CERT_A:
       return "3WCC_A";
 
-    case SSL3_ST_CW_CERT_B:
-      return "3WCC_B";
-
-    case SSL3_ST_CW_CERT_C:
-      return "3WCC_C";
-
-    case SSL3_ST_CW_CERT_D:
-      return "3WCC_D";
-
     case SSL3_ST_CW_KEY_EXCH_A:
       return "3WCKEA";
 
-    case SSL3_ST_CW_KEY_EXCH_B:
-      return "3WCKEB";
-
     case SSL3_ST_CW_CERT_VRFY_A:
       return "3WCV_A";
 
     case SSL3_ST_CW_CERT_VRFY_B:
       return "3WCV_B";
 
-    case SSL3_ST_SW_CHANGE_A:
-    case SSL3_ST_CW_CHANGE_A:
-      return "3WCCSA";
-
-    case SSL3_ST_SW_CHANGE_B:
-    case SSL3_ST_CW_CHANGE_B:
-      return "3WCCSB";
+    case SSL3_ST_SW_CHANGE:
+    case SSL3_ST_CW_CHANGE:
+      return "3WCCS_";
 
     case SSL3_ST_SW_FINISHED_A:
     case SSL3_ST_CW_FINISHED_A:
       return "3WFINA";
 
-    case SSL3_ST_SW_FINISHED_B:
-    case SSL3_ST_CW_FINISHED_B:
-      return "3WFINB";
-
     case SSL3_ST_CR_CHANGE:
     case SSL3_ST_SR_CHANGE:
       return "3RCCS_";
@@ -386,19 +275,6 @@
     case SSL3_ST_CR_FINISHED_A:
       return "3RFINA";
 
-    case SSL3_ST_SR_FINISHED_B:
-    case SSL3_ST_CR_FINISHED_B:
-      return "3RFINB";
-
-    case SSL3_ST_SW_HELLO_REQ_A:
-      return "3WHR_A";
-
-    case SSL3_ST_SW_HELLO_REQ_B:
-      return "3WHR_B";
-
-    case SSL3_ST_SW_HELLO_REQ_C:
-      return "3WHR_C";
-
     case SSL3_ST_SR_CLNT_HELLO_A:
       return "3RCH_A";
 
@@ -408,21 +284,12 @@
     case SSL3_ST_SR_CLNT_HELLO_C:
       return "3RCH_C";
 
-    case SSL3_ST_SR_CLNT_HELLO_D:
-      return "3RCH_D";
-
     case SSL3_ST_SW_SRVR_HELLO_A:
       return "3WSH_A";
 
-    case SSL3_ST_SW_SRVR_HELLO_B:
-      return "3WSH_B";
-
     case SSL3_ST_SW_CERT_A:
       return "3WSC_A";
 
-    case SSL3_ST_SW_CERT_B:
-      return "3WSC_B";
-
     case SSL3_ST_SW_KEY_EXCH_A:
       return "3WSKEA";
 
@@ -432,40 +299,22 @@
     case SSL3_ST_SW_CERT_REQ_A:
       return "3WCR_A";
 
-    case SSL3_ST_SW_CERT_REQ_B:
-      return "3WCR_B";
-
     case SSL3_ST_SW_SRVR_DONE_A:
       return "3WSD_A";
 
-    case SSL3_ST_SW_SRVR_DONE_B:
-      return "3WSD_B";
-
     case SSL3_ST_SR_CERT_A:
       return "3RCC_A";
 
-    case SSL3_ST_SR_CERT_B:
-      return "3RCC_B";
-
     case SSL3_ST_SR_KEY_EXCH_A:
       return "3RCKEA";
 
-    case SSL3_ST_SR_KEY_EXCH_B:
-      return "3RCKEB";
-
     case SSL3_ST_SR_CERT_VRFY_A:
       return "3RCV_A";
 
-    case SSL3_ST_SR_CERT_VRFY_B:
-      return "3RCV_B";
-
     /* DTLS */
     case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_A:
       return "DRCHVA";
 
-    case DTLS1_ST_CR_HELLO_VERIFY_REQUEST_B:
-      return "DRCHVB";
-
     default:
       return "UNKWN ";
   }
@@ -558,6 +407,9 @@
     case TLS1_AD_INTERNAL_ERROR:
       return "internal error";
 
+    case SSL3_AD_INAPPROPRIATE_FALLBACK:
+      return "inappropriate fallback";
+
     case TLS1_AD_USER_CANCELLED:
       return "user canceled";
 
@@ -582,8 +434,8 @@
     case TLS1_AD_UNKNOWN_PSK_IDENTITY:
       return "unknown PSK identity";
 
-    case SSL3_AD_INAPPROPRIATE_FALLBACK:
-      return "inappropriate fallback";
+    case TLS1_AD_CERTIFICATE_REQUIRED:
+      return "certificate required";
 
     default:
       return "unknown";
diff --git a/src/ssl/ssl_test.cc b/src/ssl/ssl_test.cc
index 9558f1c..6678b57 100644
--- a/src/ssl/ssl_test.cc
+++ b/src/ssl/ssl_test.cc
@@ -18,17 +18,36 @@
 
 #include <algorithm>
 #include <string>
+#include <utility>
 #include <vector>
 
+#include <gtest/gtest.h>
+
 #include <openssl/base64.h>
 #include <openssl/bio.h>
+#include <openssl/cipher.h>
 #include <openssl/crypto.h>
 #include <openssl/err.h>
+#include <openssl/hmac.h>
+#include <openssl/pem.h>
+#include <openssl/sha.h>
 #include <openssl/ssl.h>
+#include <openssl/rand.h>
+#include <openssl/x509.h>
 
-#include "test/scoped_types.h"
+#include "internal.h"
+#include "../crypto/internal.h"
 #include "../crypto/test/test_util.h"
 
+#if defined(OPENSSL_WINDOWS)
+/* Windows defines struct timeval in winsock2.h. */
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
+#include <winsock2.h>
+OPENSSL_MSVC_PRAGMA(warning(pop))
+#else
+#include <sys/time.h>
+#endif
+
 
 struct ExpectedCipher {
   unsigned long id;
@@ -38,215 +57,197 @@
 struct CipherTest {
   // The rule string to apply.
   const char *rule;
-  // The list of expected ciphers, in order, terminated with -1.
-  const ExpectedCipher *expected;
+  // The list of expected ciphers, in order.
+  std::vector<ExpectedCipher> expected;
+  // True if this cipher list should fail in strict mode.
+  bool strict_fail;
 };
 
-// Selecting individual ciphers should work.
-static const char kRule1[] =
-    "ECDHE-ECDSA-CHACHA20-POLY1305:"
-    "ECDHE-RSA-CHACHA20-POLY1305:"
-    "ECDHE-ECDSA-AES128-GCM-SHA256:"
-    "ECDHE-RSA-AES128-GCM-SHA256";
-
-static const ExpectedCipher kExpected1[] = {
-  { TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0 },
-  { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0 },
-  { TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0 },
-  { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0 },
-  { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0 },
-  { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0 },
-  { 0, 0 },
+struct CurveTest {
+  // The rule string to apply.
+  const char *rule;
+  // The list of expected curves, in order.
+  std::vector<uint16_t> expected;
 };
 
-// + reorders selected ciphers to the end, keeping their relative
-// order.
-static const char kRule2[] =
-    "ECDHE-ECDSA-CHACHA20-POLY1305:"
-    "ECDHE-RSA-CHACHA20-POLY1305:"
-    "ECDHE-ECDSA-AES128-GCM-SHA256:"
-    "ECDHE-RSA-AES128-GCM-SHA256:"
-    "+aRSA";
-
-static const ExpectedCipher kExpected2[] = {
-  { TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0 },
-  { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0 },
-  { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0 },
-  { TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0 },
-  { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0 },
-  { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0 },
-  { 0, 0 },
-};
-
-// ! banishes ciphers from future selections.
-static const char kRule3[] =
-    "!aRSA:"
-    "ECDHE-ECDSA-CHACHA20-POLY1305:"
-    "ECDHE-RSA-CHACHA20-POLY1305:"
-    "ECDHE-ECDSA-AES128-GCM-SHA256:"
-    "ECDHE-RSA-AES128-GCM-SHA256";
-
-static const ExpectedCipher kExpected3[] = {
-  { TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0 },
-  { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0 },
-  { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0 },
-  { 0, 0 },
-};
-
-// Multiple masks can be ANDed in a single rule.
-static const char kRule4[] = "kRSA+AESGCM+AES128";
-
-static const ExpectedCipher kExpected4[] = {
-  { TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, 0 },
-  { 0, 0 },
-};
-
-// - removes selected ciphers, but preserves their order for future
-// selections. Select AES_128_GCM, but order the key exchanges RSA,
-// DHE_RSA, ECDHE_RSA.
-static const char kRule5[] =
-    "ALL:-kECDHE:-kDHE:-kRSA:-ALL:"
-    "AESGCM+AES128+aRSA";
-
-static const ExpectedCipher kExpected5[] = {
-  { TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, 0 },
-  { TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256, 0 },
-  { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0 },
-  { 0, 0 },
-};
-
-// Unknown selectors are no-ops.
-static const char kRule6[] =
-    "ECDHE-ECDSA-CHACHA20-POLY1305:"
-    "ECDHE-RSA-CHACHA20-POLY1305:"
-    "ECDHE-ECDSA-AES128-GCM-SHA256:"
-    "ECDHE-RSA-AES128-GCM-SHA256:"
-    "BOGUS1:-BOGUS2:+BOGUS3:!BOGUS4";
-
-static const ExpectedCipher kExpected6[] = {
-  { TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0 },
-  { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0 },
-  { TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0 },
-  { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0 },
-  { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0 },
-  { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0 },
-  { 0, 0 },
-};
-
-// Square brackets specify equi-preference groups.
-static const char kRule7[] =
-    "[ECDHE-ECDSA-CHACHA20-POLY1305|ECDHE-ECDSA-AES128-GCM-SHA256]:"
-    "[ECDHE-RSA-CHACHA20-POLY1305]:"
-    "ECDHE-RSA-AES128-GCM-SHA256";
-
-static const ExpectedCipher kExpected7[] = {
-  { TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 1 },
-  { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 1 },
-  { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0 },
-  { TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 1 },
-  { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0 },
-  { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0 },
-  { 0, 0 },
-};
-
-// @STRENGTH performs a stable strength-sort of the selected
-// ciphers and only the selected ciphers.
-static const char kRule8[] =
-    // To simplify things, banish all but {ECDHE_RSA,RSA} x
-    // {CHACHA20,AES_256_CBC,AES_128_CBC,RC4} x SHA1.
-    "!kEDH:!AESGCM:!3DES:!SHA256:!MD5:!SHA384:"
-    // Order some ciphers backwards by strength.
-    "ALL:-CHACHA20:-AES256:-AES128:-RC4:-ALL:"
-    // Select ECDHE ones and sort them by strength. Ties should resolve
-    // based on the order above.
-    "kECDHE:@STRENGTH:-ALL:"
-    // Now bring back everything uses RSA. ECDHE_RSA should be first,
-    // sorted by strength. Then RSA, backwards by strength.
-    "aRSA";
-
-static const ExpectedCipher kExpected8[] = {
-  { TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA, 0 },
-  { TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0 },
-  { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0 },
-  { TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA, 0 },
-  { TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA, 0 },
-  { SSL3_CK_RSA_RC4_128_SHA, 0 },
-  { TLS1_CK_RSA_WITH_AES_128_SHA, 0 },
-  { TLS1_CK_RSA_WITH_AES_256_SHA, 0 },
-  { 0, 0 },
-};
-
-// Exact ciphers may not be used in multi-part rules; they are treated
-// as unknown aliases.
-static const char kRule9[] =
-    "ECDHE-ECDSA-AES128-GCM-SHA256:"
-    "ECDHE-RSA-AES128-GCM-SHA256:"
-    "!ECDHE-RSA-AES128-GCM-SHA256+RSA:"
-    "!ECDSA+ECDHE-ECDSA-AES128-GCM-SHA256";
-
-static const ExpectedCipher kExpected9[] = {
-  { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0 },
-  { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0 },
-  { 0, 0 },
-};
-
-// SSLv3 matches everything that existed before TLS 1.2.
-static const char kRule10[] = "AES128-SHA:AES128-SHA256:!SSLv3";
-
-static const ExpectedCipher kExpected10[] = {
-  { TLS1_CK_RSA_WITH_AES_128_SHA256, 0 },
-  { 0, 0 },
-};
-
-// TLSv1.2 matches everything added in TLS 1.2.
-static const char kRule11[] = "AES128-SHA:AES128-SHA256:!TLSv1.2";
-
-static const ExpectedCipher kExpected11[] = {
-  { TLS1_CK_RSA_WITH_AES_128_SHA, 0 },
-  { 0, 0 },
-};
-
-// The two directives have no intersection.
-static const char kRule12[] = "AES128-SHA:AES128-SHA256:!TLSv1.2+SSLv3";
-
-static const ExpectedCipher kExpected12[] = {
-  { TLS1_CK_RSA_WITH_AES_128_SHA, 0 },
-  { TLS1_CK_RSA_WITH_AES_128_SHA256, 0 },
-  { 0, 0 },
-};
-
-// The shared name of the CHACHA20_POLY1305 variants behaves like a cipher name
-// and not an alias. It may not be used in a multipart rule. (That the shared
-// name works is covered by the standard tests.)
-static const char kRule13[] =
-    "ECDHE-ECDSA-CHACHA20-POLY1305:"
-    "ECDHE-RSA-CHACHA20-POLY1305:"
-    "!ECDHE-RSA-CHACHA20-POLY1305+RSA:"
-    "!ECDSA+ECDHE-ECDSA-CHACHA20-POLY1305";
-
-static const ExpectedCipher kExpected13[] = {
-  { TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0 },
-  { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD, 0 },
-  { TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0 },
-  { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD, 0 },
-  { 0, 0 },
-};
-
-static CipherTest kCipherTests[] = {
-  { kRule1, kExpected1 },
-  { kRule2, kExpected2 },
-  { kRule3, kExpected3 },
-  { kRule4, kExpected4 },
-  { kRule5, kExpected5 },
-  { kRule6, kExpected6 },
-  { kRule7, kExpected7 },
-  { kRule8, kExpected8 },
-  { kRule9, kExpected9 },
-  { kRule10, kExpected10 },
-  { kRule11, kExpected11 },
-  { kRule12, kExpected12 },
-  { kRule13, kExpected13 },
-  { NULL, NULL },
+static const CipherTest kCipherTests[] = {
+    // Selecting individual ciphers should work.
+    {
+        "ECDHE-ECDSA-CHACHA20-POLY1305:"
+        "ECDHE-RSA-CHACHA20-POLY1305:"
+        "ECDHE-ECDSA-AES128-GCM-SHA256:"
+        "ECDHE-RSA-AES128-GCM-SHA256",
+        {
+            {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0},
+            {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0},
+            {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
+            {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
+        },
+        false,
+    },
+    // + reorders selected ciphers to the end, keeping their relative order.
+    {
+        "ECDHE-ECDSA-CHACHA20-POLY1305:"
+        "ECDHE-RSA-CHACHA20-POLY1305:"
+        "ECDHE-ECDSA-AES128-GCM-SHA256:"
+        "ECDHE-RSA-AES128-GCM-SHA256:"
+        "+aRSA",
+        {
+            {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0},
+            {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
+            {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0},
+            {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
+        },
+        false,
+    },
+    // ! banishes ciphers from future selections.
+    {
+        "!aRSA:"
+        "ECDHE-ECDSA-CHACHA20-POLY1305:"
+        "ECDHE-RSA-CHACHA20-POLY1305:"
+        "ECDHE-ECDSA-AES128-GCM-SHA256:"
+        "ECDHE-RSA-AES128-GCM-SHA256",
+        {
+            {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0},
+            {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
+        },
+        false,
+    },
+    // Multiple masks can be ANDed in a single rule.
+    {
+        "kRSA+AESGCM+AES128",
+        {
+            {TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, 0},
+        },
+        false,
+    },
+    // - removes selected ciphers, but preserves their order for future
+    // selections. Select AES_128_GCM, but order the key exchanges RSA,
+    // ECDHE_RSA.
+    {
+        "ALL:-kECDHE:"
+#ifdef BORINGSSL_ENABLE_DHE_TLS
+        "-kDHE:"
+#endif
+        "-kRSA:-ALL:"
+        "AESGCM+AES128+aRSA",
+        {
+            {TLS1_CK_RSA_WITH_AES_128_GCM_SHA256, 0},
+#ifdef BORINGSSL_ENABLE_DHE_TLS
+            {TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256, 0},
+#endif
+            {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
+        },
+        false,
+    },
+    // Unknown selectors are no-ops, except in strict mode.
+    {
+        "ECDHE-ECDSA-CHACHA20-POLY1305:"
+        "ECDHE-RSA-CHACHA20-POLY1305:"
+        "ECDHE-ECDSA-AES128-GCM-SHA256:"
+        "ECDHE-RSA-AES128-GCM-SHA256:"
+        "BOGUS1",
+        {
+            {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0},
+            {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0},
+            {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
+            {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
+        },
+        true,
+    },
+    // Unknown selectors are no-ops, except in strict mode.
+    {
+        "ECDHE-ECDSA-CHACHA20-POLY1305:"
+        "ECDHE-RSA-CHACHA20-POLY1305:"
+        "ECDHE-ECDSA-AES128-GCM-SHA256:"
+        "ECDHE-RSA-AES128-GCM-SHA256:"
+        "-BOGUS2:+BOGUS3:!BOGUS4",
+        {
+            {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0},
+            {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0},
+            {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
+            {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
+        },
+        true,
+    },
+    // Square brackets specify equi-preference groups.
+    {
+        "[ECDHE-ECDSA-CHACHA20-POLY1305|ECDHE-ECDSA-AES128-GCM-SHA256]:"
+        "[ECDHE-RSA-CHACHA20-POLY1305]:"
+        "ECDHE-RSA-AES128-GCM-SHA256",
+        {
+            {TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 1},
+            {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
+            {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0},
+            {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
+        },
+        false,
+    },
+    // @STRENGTH performs a stable strength-sort of the selected ciphers and
+    // only the selected ciphers.
+    {
+        // To simplify things, banish all but {ECDHE_RSA,RSA} x
+        // {CHACHA20,AES_256_CBC,AES_128_CBC} x SHA1.
+#ifdef BORINGSSL_ENABLE_DHE_TLS
+        "!kEDH:"
+#endif
+        "!AESGCM:!3DES:!SHA256:!SHA384:"
+        // Order some ciphers backwards by strength.
+        "ALL:-CHACHA20:-AES256:-AES128:-ALL:"
+        // Select ECDHE ones and sort them by strength. Ties should resolve
+        // based on the order above.
+        "kECDHE:@STRENGTH:-ALL:"
+        // Now bring back everything uses RSA. ECDHE_RSA should be first, sorted
+        // by strength. Then RSA, backwards by strength.
+        "aRSA",
+        {
+            {TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA, 0},
+            {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 0},
+            {TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA, 0},
+            {TLS1_CK_RSA_WITH_AES_128_SHA, 0},
+            {TLS1_CK_RSA_WITH_AES_256_SHA, 0},
+        },
+        false,
+    },
+    // Exact ciphers may not be used in multi-part rules; they are treated
+    // as unknown aliases.
+    {
+        "ECDHE-ECDSA-AES128-GCM-SHA256:"
+        "ECDHE-RSA-AES128-GCM-SHA256:"
+        "!ECDHE-RSA-AES128-GCM-SHA256+RSA:"
+        "!ECDSA+ECDHE-ECDSA-AES128-GCM-SHA256",
+        {
+            {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 0},
+            {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 0},
+        },
+        true,
+    },
+    // SSLv3 matches everything that existed before TLS 1.2.
+    {
+        "AES128-SHA:AES128-SHA256:!SSLv3",
+        {
+            {TLS1_CK_RSA_WITH_AES_128_SHA256, 0},
+        },
+        false,
+    },
+    // TLSv1.2 matches everything added in TLS 1.2.
+    {
+        "AES128-SHA:AES128-SHA256:!TLSv1.2",
+        {
+            {TLS1_CK_RSA_WITH_AES_128_SHA, 0},
+        },
+        false,
+    },
+    // The two directives have no intersection.  But each component is valid, so
+    // even in strict mode it is accepted.
+    {
+        "AES128-SHA:AES128-SHA256:!TLSv1.2+SSLv3",
+        {
+            {TLS1_CK_RSA_WITH_AES_128_SHA, 0},
+            {TLS1_CK_RSA_WITH_AES_128_SHA256, 0},
+        },
+        false,
+    },
 };
 
 static const char *kBadRules[] = {
@@ -270,15 +271,13 @@
   "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:!FOO",
   "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:-FOO",
   "[ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256]:@STRENGTH",
-  NULL,
+  // Opcode supplied, but missing selector.
+  "+",
 };
 
 static const char *kMustNotIncludeNull[] = {
   "ALL",
   "DEFAULT",
-  "ALL:!eNULL",
-  "ALL:!NULL",
-  "MEDIUM",
   "HIGH",
   "FIPS",
   "SHA",
@@ -287,7 +286,33 @@
   "SSLv3",
   "TLSv1",
   "TLSv1.2",
-  NULL
+};
+
+static const CurveTest kCurveTests[] = {
+  {
+    "P-256",
+    { SSL_CURVE_SECP256R1 },
+  },
+  {
+    "P-256:P-384:P-521:X25519",
+    {
+      SSL_CURVE_SECP256R1,
+      SSL_CURVE_SECP384R1,
+      SSL_CURVE_SECP521R1,
+      SSL_CURVE_X25519,
+    },
+  },
+};
+
+static const char *kBadCurvesLists[] = {
+  "",
+  ":",
+  "::",
+  "P-256::X25519",
+  "RSA:P-256",
+  "P-256:RSA",
+  "X25519:P-256:",
+  ":X25519:P-256",
 };
 
 static void PrintCipherPreferenceList(ssl_cipher_preference_list_st *list) {
@@ -310,45 +335,50 @@
   }
 }
 
-static bool TestCipherRule(CipherTest *t) {
-  ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
+static bool TestCipherRule(const CipherTest &t) {
+  bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
   if (!ctx) {
     return false;
   }
 
-  if (!SSL_CTX_set_cipher_list(ctx.get(), t->rule)) {
-    fprintf(stderr, "Error testing cipher rule '%s'\n", t->rule);
+  if (!SSL_CTX_set_cipher_list(ctx.get(), t.rule)) {
+    fprintf(stderr, "Error testing cipher rule '%s'\n", t.rule);
+    return false;
+  }
+
+  if (!SSL_CTX_set_strict_cipher_list(ctx.get(), t.rule) != t.strict_fail) {
+    fprintf(stderr, "Unexpected strict failure result testing cipher rule '%s':"
+            " expected %d\n", t.rule, t.strict_fail);
     return false;
   }
 
   // Compare the two lists.
-  size_t i;
-  for (i = 0; i < sk_SSL_CIPHER_num(ctx->cipher_list->ciphers); i++) {
+  if (sk_SSL_CIPHER_num(ctx->cipher_list->ciphers) != t.expected.size()) {
+    fprintf(stderr, "Error: cipher rule '%s' evaluated to:\n", t.rule);
+    PrintCipherPreferenceList(ctx->cipher_list);
+    return false;
+  }
+
+  for (size_t i = 0; i < t.expected.size(); i++) {
     const SSL_CIPHER *cipher =
         sk_SSL_CIPHER_value(ctx->cipher_list->ciphers, i);
-    if (t->expected[i].id != SSL_CIPHER_get_id(cipher) ||
-        t->expected[i].in_group_flag != ctx->cipher_list->in_group_flags[i]) {
-      fprintf(stderr, "Error: cipher rule '%s' evaluated to:\n", t->rule);
+    if (t.expected[i].id != SSL_CIPHER_get_id(cipher) ||
+        t.expected[i].in_group_flag != ctx->cipher_list->in_group_flags[i]) {
+      fprintf(stderr, "Error: cipher rule '%s' evaluated to:\n", t.rule);
       PrintCipherPreferenceList(ctx->cipher_list);
       return false;
     }
   }
 
-  if (t->expected[i].id != 0) {
-    fprintf(stderr, "Error: cipher rule '%s' evaluated to:\n", t->rule);
-    PrintCipherPreferenceList(ctx->cipher_list);
-    return false;
-  }
-
   return true;
 }
 
 static bool TestRuleDoesNotIncludeNull(const char *rule) {
-  ScopedSSL_CTX ctx(SSL_CTX_new(SSLv23_server_method()));
+  bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(SSLv23_server_method()));
   if (!ctx) {
     return false;
   }
-  if (!SSL_CTX_set_cipher_list(ctx.get(), rule)) {
+  if (!SSL_CTX_set_strict_cipher_list(ctx.get(), rule)) {
     fprintf(stderr, "Error: cipher rule '%s' failed\n", rule);
     return false;
   }
@@ -362,26 +392,26 @@
 }
 
 static bool TestCipherRules() {
-  for (size_t i = 0; kCipherTests[i].rule != NULL; i++) {
-    if (!TestCipherRule(&kCipherTests[i])) {
+  for (const CipherTest &test : kCipherTests) {
+    if (!TestCipherRule(test)) {
       return false;
     }
   }
 
-  for (size_t i = 0; kBadRules[i] != NULL; i++) {
-    ScopedSSL_CTX ctx(SSL_CTX_new(SSLv23_server_method()));
+  for (const char *rule : kBadRules) {
+    bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(SSLv23_server_method()));
     if (!ctx) {
       return false;
     }
-    if (SSL_CTX_set_cipher_list(ctx.get(), kBadRules[i])) {
-      fprintf(stderr, "Cipher rule '%s' unexpectedly succeeded\n", kBadRules[i]);
+    if (SSL_CTX_set_cipher_list(ctx.get(), rule)) {
+      fprintf(stderr, "Cipher rule '%s' unexpectedly succeeded\n", rule);
       return false;
     }
     ERR_clear_error();
   }
 
-  for (size_t i = 0; kMustNotIncludeNull[i] != NULL; i++) {
-    if (!TestRuleDoesNotIncludeNull(kMustNotIncludeNull[i])) {
+  for (const char *rule : kMustNotIncludeNull) {
+    if (!TestRuleDoesNotIncludeNull(rule)) {
       return false;
     }
   }
@@ -389,10 +419,58 @@
   return true;
 }
 
-// kOpenSSLSession is a serialized SSL_SESSION generated from openssl
-// s_client -sess_out.
+static bool TestCurveRule(const CurveTest &t) {
+  bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
+  if (!ctx) {
+    return false;
+  }
+
+  if (!SSL_CTX_set1_curves_list(ctx.get(), t.rule)) {
+    fprintf(stderr, "Error testing curves list '%s'\n", t.rule);
+    return false;
+  }
+
+  // Compare the two lists.
+  if (ctx->supported_group_list_len != t.expected.size()) {
+    fprintf(stderr, "Error testing curves list '%s': length\n", t.rule);
+    return false;
+  }
+
+  for (size_t i = 0; i < t.expected.size(); i++) {
+    if (t.expected[i] != ctx->supported_group_list[i]) {
+      fprintf(stderr, "Error testing curves list '%s': mismatch\n", t.rule);
+      return false;
+    }
+  }
+
+  return true;
+}
+
+static bool TestCurveRules() {
+  for (const CurveTest &test : kCurveTests) {
+    if (!TestCurveRule(test)) {
+      return false;
+    }
+  }
+
+  for (const char *rule : kBadCurvesLists) {
+    bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(SSLv23_server_method()));
+    if (!ctx) {
+      return false;
+    }
+    if (SSL_CTX_set1_curves_list(ctx.get(), rule)) {
+      fprintf(stderr, "Curves list '%s' unexpectedly succeeded\n", rule);
+      return false;
+    }
+    ERR_clear_error();
+  }
+
+  return true;
+}
+
+// kOpenSSLSession is a serialized SSL_SESSION.
 static const char kOpenSSLSession[] =
-    "MIIFpQIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
+    "MIIFqgIBAQICAwMEAsAvBCAG5Q1ndq4Yfmbeo1zwLkNRKmCXGdNgWvGT3cskV0yQ"
     "kAQwJlrlzkAWBOWiLj/jJ76D7l+UXoizP2KI2C7I2FccqMmIfFmmkUy32nIJ0mZH"
     "IWoJoQYCBFRDO46iBAICASyjggR6MIIEdjCCA16gAwIBAgIIK9dUvsPWSlUwDQYJ"
     "KoZIhvcNAQEFBQAwSTELMAkGA1UEBhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMx"
@@ -422,7 +500,7 @@
     "YTcLEkXqKwOBfF9vE4KX0NxeLwjcDTpsuh3qXEaZ992r1N38VDcyS6P7I6HBYN9B"
     "sNHM362zZnY27GpTw+Kwd751CLoXFPoaMOe57dbBpXoro6Pd3BTbf/Tzr88K06yE"
     "OTDKPNj3+inbMaVigtK4PLyPq+Topyzvx9USFgRvyuoxn0Hgb+R0A3j6SLRuyOdA"
-    "i4gv7Y5oliyn";
+    "i4gv7Y5oliyntgMBAQA=";
 
 // kCustomSession is a custom serialized SSL_SESSION generated by
 // filling in missing fields from |kOpenSSLSession|. This includes
@@ -599,7 +677,12 @@
   }
 
   // Verify the SSL_SESSION decodes.
-  ScopedSSL_SESSION session(SSL_SESSION_from_bytes(input.data(), input.size()));
+  bssl::UniquePtr<SSL_CTX> ssl_ctx(SSL_CTX_new(TLS_method()));
+  if (!ssl_ctx) {
+    return false;
+  }
+  bssl::UniquePtr<SSL_SESSION> session(
+      SSL_SESSION_from_bytes(input.data(), input.size(), ssl_ctx.get()));
   if (!session) {
     fprintf(stderr, "SSL_SESSION_from_bytes failed\n");
     return false;
@@ -607,7 +690,7 @@
 
   // Verify the SSL_SESSION encoding round-trips.
   size_t encoded_len;
-  ScopedOpenSSLBytes encoded;
+  bssl::UniquePtr<uint8_t> encoded;
   uint8_t *encoded_raw;
   if (!SSL_SESSION_to_bytes(session.get(), &encoded_raw, &encoded_len)) {
     fprintf(stderr, "SSL_SESSION_to_bytes failed\n");
@@ -615,7 +698,7 @@
   }
   encoded.reset(encoded_raw);
   if (encoded_len != input.size() ||
-      memcmp(input.data(), encoded.get(), input.size()) != 0) {
+      OPENSSL_memcmp(input.data(), encoded.get(), input.size()) != 0) {
     fprintf(stderr, "SSL_SESSION_to_bytes did not round-trip\n");
     hexdump(stderr, "Before: ", input.data(), input.size());
     hexdump(stderr, "After:  ", encoded_raw, encoded_len);
@@ -653,7 +736,7 @@
     fprintf(stderr, "i2d_SSL_SESSION did not advance ptr correctly\n");
     return false;
   }
-  if (memcmp(input.data(), encoded.get(), input.size()) != 0) {
+  if (OPENSSL_memcmp(input.data(), encoded.get(), input.size()) != 0) {
     fprintf(stderr, "i2d_SSL_SESSION did not round-trip\n");
     return false;
   }
@@ -668,7 +751,12 @@
   }
 
   // Verify that the SSL_SESSION fails to decode.
-  ScopedSSL_SESSION session(SSL_SESSION_from_bytes(input.data(), input.size()));
+  bssl::UniquePtr<SSL_CTX> ssl_ctx(SSL_CTX_new(TLS_method()));
+  if (!ssl_ctx) {
+    return false;
+  }
+  bssl::UniquePtr<SSL_SESSION> session(
+      SSL_SESSION_from_bytes(input.data(), input.size(), ssl_ctx.get()));
   if (session) {
     fprintf(stderr, "SSL_SESSION_from_bytes unexpectedly succeeded\n");
     return false;
@@ -677,13 +765,18 @@
   return true;
 }
 
-static bool TestDefaultVersion(uint16_t version,
+static bool TestDefaultVersion(uint16_t min_version, uint16_t max_version,
                                const SSL_METHOD *(*method)(void)) {
-  ScopedSSL_CTX ctx(SSL_CTX_new(method()));
+  bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(method()));
   if (!ctx) {
     return false;
   }
-  return ctx->min_version == version && ctx->max_version == version;
+  if (ctx->min_version != min_version || ctx->max_version != max_version) {
+    fprintf(stderr, "Got min %04x, max %04x; wanted min %04x, max %04x\n",
+            ctx->min_version, ctx->max_version, min_version, max_version);
+    return false;
+  }
+  return true;
 }
 
 static bool CipherGetRFCName(std::string *out, uint16_t value) {
@@ -691,7 +784,7 @@
   if (cipher == NULL) {
     return false;
   }
-  ScopedOpenSSLString rfc_name(SSL_CIPHER_get_rfc_name(cipher));
+  bssl::UniquePtr<char> rfc_name(SSL_CIPHER_get_rfc_name(cipher));
   if (!rfc_name) {
     return false;
   }
@@ -705,37 +798,35 @@
 } CIPHER_RFC_NAME_TEST;
 
 static const CIPHER_RFC_NAME_TEST kCipherRFCNameTests[] = {
-  { SSL3_CK_RSA_DES_192_CBC3_SHA, "TLS_RSA_WITH_3DES_EDE_CBC_SHA" },
-  { SSL3_CK_RSA_RC4_128_MD5, "TLS_RSA_WITH_RC4_MD5" },
-  { TLS1_CK_RSA_WITH_AES_128_SHA, "TLS_RSA_WITH_AES_128_CBC_SHA" },
-  { TLS1_CK_DHE_RSA_WITH_AES_256_SHA, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA" },
-  { TLS1_CK_DHE_RSA_WITH_AES_256_SHA256,
-    "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256" },
-  { TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256,
-    "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256" },
-  { TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384,
-    "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384" },
-  { TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
-    "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256" },
-  { TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
-    "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" },
-  { TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
-    "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384" },
-  { TLS1_CK_PSK_WITH_RC4_128_SHA, "TLS_PSK_WITH_RC4_SHA" },
-  { TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA,
-    "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA" },
-  { TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
-    "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" },
-  // These names are non-standard:
-  { TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305_OLD,
-    "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256" },
-  { TLS1_CK_ECDHE_ECDSA_CHACHA20_POLY1305_OLD,
-    "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256" },
+    {SSL3_CK_RSA_DES_192_CBC3_SHA, "TLS_RSA_WITH_3DES_EDE_CBC_SHA"},
+    {TLS1_CK_RSA_WITH_AES_128_SHA, "TLS_RSA_WITH_AES_128_CBC_SHA"},
+#ifdef BORINGSSL_ENABLE_DHE_TLS
+    {TLS1_CK_DHE_RSA_WITH_AES_256_SHA, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"},
+    {TLS1_CK_DHE_RSA_WITH_AES_256_SHA256,
+     "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"},
+#endif
+    {TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256,
+     "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"},
+    {TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384,
+     "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"},
+    {TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+     "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"},
+    {TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+     "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"},
+    {TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
+     "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384"},
+    {TLS1_CK_ECDHE_PSK_WITH_AES_128_CBC_SHA,
+     "TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA"},
+    {TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
+     "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"},
+    {TLS1_CK_AES_256_GCM_SHA384, "TLS_AES_256_GCM_SHA384"},
+    {TLS1_CK_AES_128_GCM_SHA256, "TLS_AES_128_GCM_SHA256"},
+    {TLS1_CK_CHACHA20_POLY1305_SHA256, "TLS_CHACHA20_POLY1305_SHA256"},
 };
 
 static bool TestCipherGetRFCName(void) {
   for (size_t i = 0;
-       i < sizeof(kCipherRFCNameTests) / sizeof(kCipherRFCNameTests[0]); i++) {
+       i < OPENSSL_ARRAY_SIZE(kCipherRFCNameTests); i++) {
     const CIPHER_RFC_NAME_TEST *test = &kCipherRFCNameTests[i];
     std::string rfc_name;
     if (!CipherGetRFCName(&rfc_name, test->id & 0xffff)) {
@@ -751,62 +842,96 @@
   return true;
 }
 
-// CreateSessionWithTicket returns a sample |SSL_SESSION| with the ticket
-// replaced for one of length |ticket_len| or nullptr on failure.
-static ScopedSSL_SESSION CreateSessionWithTicket(size_t ticket_len) {
+// CreateSessionWithTicket returns a sample |SSL_SESSION| with the specified
+// version and ticket length or nullptr on failure.
+static bssl::UniquePtr<SSL_SESSION> CreateSessionWithTicket(uint16_t version,
+                                                            size_t ticket_len) {
   std::vector<uint8_t> der;
   if (!DecodeBase64(&der, kOpenSSLSession)) {
     return nullptr;
   }
-  ScopedSSL_SESSION session(SSL_SESSION_from_bytes(der.data(), der.size()));
+
+  bssl::UniquePtr<SSL_CTX> ssl_ctx(SSL_CTX_new(TLS_method()));
+  if (!ssl_ctx) {
+    return nullptr;
+  }
+  bssl::UniquePtr<SSL_SESSION> session(
+      SSL_SESSION_from_bytes(der.data(), der.size(), ssl_ctx.get()));
   if (!session) {
     return nullptr;
   }
 
+  session->ssl_version = version;
+
   // Swap out the ticket for a garbage one.
   OPENSSL_free(session->tlsext_tick);
   session->tlsext_tick = reinterpret_cast<uint8_t*>(OPENSSL_malloc(ticket_len));
   if (session->tlsext_tick == nullptr) {
     return nullptr;
   }
-  memset(session->tlsext_tick, 'a', ticket_len);
+  OPENSSL_memset(session->tlsext_tick, 'a', ticket_len);
   session->tlsext_ticklen = ticket_len;
 
   // Fix up the timeout.
+#if defined(BORINGSSL_UNSAFE_DETERMINISTIC_MODE)
+  session->time = 1234;
+#else
   session->time = time(NULL);
+#endif
   return session;
 }
 
-// GetClientHelloLen creates a client SSL connection with a ticket of length
-// |ticket_len| and records the ClientHello. It returns the length of the
-// ClientHello, not including the record header, on success and zero on error.
-static size_t GetClientHelloLen(size_t ticket_len) {
-  ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
-  ScopedSSL_SESSION session = CreateSessionWithTicket(ticket_len);
-  if (!ctx || !session) {
-    return 0;
-  }
-  ScopedSSL ssl(SSL_new(ctx.get()));
-  ScopedBIO bio(BIO_new(BIO_s_mem()));
-  if (!ssl || !bio || !SSL_set_session(ssl.get(), session.get())) {
-    return 0;
+static bool GetClientHello(SSL *ssl, std::vector<uint8_t> *out) {
+  bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_mem()));
+  if (!bio) {
+    return false;
   }
   // Do not configure a reading BIO, but record what's written to a memory BIO.
-  SSL_set_bio(ssl.get(), nullptr /* rbio */, BIO_up_ref(bio.get()));
-  int ret = SSL_connect(ssl.get());
+  BIO_up_ref(bio.get());
+  SSL_set_bio(ssl, nullptr /* rbio */, bio.get());
+  int ret = SSL_connect(ssl);
   if (ret > 0) {
     // SSL_connect should fail without a BIO to write to.
-    return 0;
+    return false;
   }
   ERR_clear_error();
 
-  const uint8_t *unused;
+  const uint8_t *client_hello;
   size_t client_hello_len;
-  if (!BIO_mem_contents(bio.get(), &unused, &client_hello_len) ||
-      client_hello_len <= SSL3_RT_HEADER_LENGTH) {
+  if (!BIO_mem_contents(bio.get(), &client_hello, &client_hello_len)) {
+    return false;
+  }
+  *out = std::vector<uint8_t>(client_hello, client_hello + client_hello_len);
+  return true;
+}
+
+// GetClientHelloLen creates a client SSL connection with the specified version
+// and ticket length. It returns the length of the ClientHello, not including
+// the record header, on success and zero on error.
+static size_t GetClientHelloLen(uint16_t max_version, uint16_t session_version,
+                                size_t ticket_len) {
+  bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
+  bssl::UniquePtr<SSL_SESSION> session =
+      CreateSessionWithTicket(session_version, ticket_len);
+  if (!ctx || !session) {
     return 0;
   }
-  return client_hello_len - SSL3_RT_HEADER_LENGTH;
+
+  // Set a one-element cipher list so the baseline ClientHello is unpadded.
+  bssl::UniquePtr<SSL> ssl(SSL_new(ctx.get()));
+  if (!ssl || !SSL_set_session(ssl.get(), session.get()) ||
+      !SSL_set_strict_cipher_list(ssl.get(), "ECDHE-RSA-AES128-GCM-SHA256") ||
+      !SSL_set_max_proto_version(ssl.get(), max_version)) {
+    return 0;
+  }
+
+  std::vector<uint8_t> client_hello;
+  if (!GetClientHello(ssl.get(), &client_hello) ||
+      client_hello.size() <= SSL3_RT_HEADER_LENGTH) {
+    return 0;
+  }
+
+  return client_hello.size() - SSL3_RT_HEADER_LENGTH;
 }
 
 struct PaddingTest {
@@ -834,51 +959,67 @@
     {0x201, 0x201},
 };
 
-static bool TestPaddingExtension() {
+static bool TestPaddingExtension(uint16_t max_version,
+                                 uint16_t session_version) {
   // Sample a baseline length.
-  size_t base_len = GetClientHelloLen(1);
+  size_t base_len = GetClientHelloLen(max_version, session_version, 1);
   if (base_len == 0) {
     return false;
   }
 
   for (const PaddingTest &test : kPaddingTests) {
     if (base_len > test.input_len) {
-      fprintf(stderr, "Baseline ClientHello too long.\n");
+      fprintf(stderr,
+              "Baseline ClientHello too long (max_version = %04x, "
+              "session_version = %04x).\n",
+              max_version, session_version);
       return false;
     }
 
-    size_t padded_len = GetClientHelloLen(1 + test.input_len - base_len);
+    size_t padded_len = GetClientHelloLen(max_version, session_version,
+                                          1 + test.input_len - base_len);
     if (padded_len != test.padded_len) {
-      fprintf(stderr, "%u-byte ClientHello padded to %u bytes, not %u.\n",
+      fprintf(stderr,
+              "%u-byte ClientHello padded to %u bytes, not %u (max_version = "
+              "%04x, session_version = %04x).\n",
               static_cast<unsigned>(test.input_len),
               static_cast<unsigned>(padded_len),
-              static_cast<unsigned>(test.padded_len));
+              static_cast<unsigned>(test.padded_len), max_version,
+              session_version);
       return false;
     }
   }
+
   return true;
 }
 
 // Test that |SSL_get_client_CA_list| echoes back the configured parameter even
 // before configuring as a server.
-static bool TestClientCAList() {
-  ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
-  if (!ctx) {
-    return false;
-  }
-  ScopedSSL ssl(SSL_new(ctx.get()));
-  if (!ssl) {
-    return false;
-  }
+TEST(SSLTest, ClientCAList) {
+  bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
+  ASSERT_TRUE(ctx);
+  bssl::UniquePtr<SSL> ssl(SSL_new(ctx.get()));
+  ASSERT_TRUE(ssl);
 
-  STACK_OF(X509_NAME) *stack = sk_X509_NAME_new_null();
-  if (stack == nullptr) {
-    return false;
-  }
+  bssl::UniquePtr<X509_NAME> name(X509_NAME_new());
+  ASSERT_TRUE(name);
+
+  bssl::UniquePtr<X509_NAME> name_dup(X509_NAME_dup(name.get()));
+  ASSERT_TRUE(name_dup);
+
+  bssl::UniquePtr<STACK_OF(X509_NAME)> stack(sk_X509_NAME_new_null());
+  ASSERT_TRUE(stack);
+
+  ASSERT_TRUE(sk_X509_NAME_push(stack.get(), name_dup.get()));
+  name_dup.release();
+
   // |SSL_set_client_CA_list| takes ownership.
-  SSL_set_client_CA_list(ssl.get(), stack);
+  SSL_set_client_CA_list(ssl.get(), stack.release());
 
-  return SSL_get_client_CA_list(ssl.get()) == stack;
+  STACK_OF(X509_NAME) *result = SSL_get_client_CA_list(ssl.get());
+  ASSERT_TRUE(result);
+  ASSERT_EQ(1u, sk_X509_NAME_num(result));
+  EXPECT_EQ(0, X509_NAME_cmp(sk_X509_NAME_value(result, 0), name.get()));
 }
 
 static void AppendSession(SSL_SESSION *session, void *arg) {
@@ -920,111 +1061,100 @@
   return actual == expected_copy;
 }
 
-static ScopedSSL_SESSION CreateTestSession(uint32_t number) {
-  ScopedSSL_SESSION ret(SSL_SESSION_new());
+static bssl::UniquePtr<SSL_SESSION> CreateTestSession(uint32_t number) {
+  bssl::UniquePtr<SSL_CTX> ssl_ctx(SSL_CTX_new(TLS_method()));
+  if (!ssl_ctx) {
+    return nullptr;
+  }
+  bssl::UniquePtr<SSL_SESSION> ret(SSL_SESSION_new(ssl_ctx.get()));
   if (!ret) {
     return nullptr;
   }
 
   ret->session_id_length = SSL3_SSL_SESSION_ID_LENGTH;
-  memset(ret->session_id, 0, ret->session_id_length);
-  memcpy(ret->session_id, &number, sizeof(number));
+  OPENSSL_memset(ret->session_id, 0, ret->session_id_length);
+  OPENSSL_memcpy(ret->session_id, &number, sizeof(number));
   return ret;
 }
 
-// TODO(davidben): Switch this to a |std::vector<ScopedSSL_SESSION>| once we can
-// rely on a move-aware |std::vector|.
-class ScopedSessionVector {
- public:
-  explicit ScopedSessionVector(std::vector<SSL_SESSION*> *sessions)
-      : sessions_(sessions) {}
-
-  ~ScopedSessionVector() {
-    for (SSL_SESSION *session : *sessions_) {
-      SSL_SESSION_free(session);
-    }
-  }
-
- private:
-  std::vector<SSL_SESSION*> *const sessions_;
-};
-
 // Test that the internal session cache behaves as expected.
 static bool TestInternalSessionCache() {
-  ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
+  bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
   if (!ctx) {
     return false;
   }
 
   // Prepare 10 test sessions.
-  std::vector<SSL_SESSION*> sessions;
-  ScopedSessionVector cleanup(&sessions);
+  std::vector<bssl::UniquePtr<SSL_SESSION>> sessions;
   for (int i = 0; i < 10; i++) {
-    ScopedSSL_SESSION session = CreateTestSession(i);
+    bssl::UniquePtr<SSL_SESSION> session = CreateTestSession(i);
     if (!session) {
       return false;
     }
-    sessions.push_back(session.release());
+    sessions.push_back(std::move(session));
   }
 
   SSL_CTX_sess_set_cache_size(ctx.get(), 5);
 
   // Insert all the test sessions.
-  for (SSL_SESSION *session : sessions) {
-    if (!SSL_CTX_add_session(ctx.get(), session)) {
+  for (const auto &session : sessions) {
+    if (!SSL_CTX_add_session(ctx.get(), session.get())) {
       return false;
     }
   }
 
   // Only the last five should be in the list.
-  std::vector<SSL_SESSION*> expected;
-  expected.push_back(sessions[9]);
-  expected.push_back(sessions[8]);
-  expected.push_back(sessions[7]);
-  expected.push_back(sessions[6]);
-  expected.push_back(sessions[5]);
+  std::vector<SSL_SESSION*> expected = {
+      sessions[9].get(),
+      sessions[8].get(),
+      sessions[7].get(),
+      sessions[6].get(),
+      sessions[5].get(),
+  };
   if (!ExpectCache(ctx.get(), expected)) {
     return false;
   }
 
   // Inserting an element already in the cache should fail.
-  if (SSL_CTX_add_session(ctx.get(), sessions[7]) ||
+  if (SSL_CTX_add_session(ctx.get(), sessions[7].get()) ||
       !ExpectCache(ctx.get(), expected)) {
     return false;
   }
 
   // Although collisions should be impossible (256-bit session IDs), the cache
   // must handle them gracefully.
-  ScopedSSL_SESSION collision(CreateTestSession(7));
+  bssl::UniquePtr<SSL_SESSION> collision(CreateTestSession(7));
   if (!collision || !SSL_CTX_add_session(ctx.get(), collision.get())) {
     return false;
   }
-  expected.clear();
-  expected.push_back(collision.get());
-  expected.push_back(sessions[9]);
-  expected.push_back(sessions[8]);
-  expected.push_back(sessions[6]);
-  expected.push_back(sessions[5]);
+  expected = {
+      collision.get(),
+      sessions[9].get(),
+      sessions[8].get(),
+      sessions[6].get(),
+      sessions[5].get(),
+  };
   if (!ExpectCache(ctx.get(), expected)) {
     return false;
   }
 
   // Removing sessions behaves correctly.
-  if (!SSL_CTX_remove_session(ctx.get(), sessions[6])) {
+  if (!SSL_CTX_remove_session(ctx.get(), sessions[6].get())) {
     return false;
   }
-  expected.clear();
-  expected.push_back(collision.get());
-  expected.push_back(sessions[9]);
-  expected.push_back(sessions[8]);
-  expected.push_back(sessions[5]);
+  expected = {
+      collision.get(),
+      sessions[9].get(),
+      sessions[8].get(),
+      sessions[5].get(),
+  };
   if (!ExpectCache(ctx.get(), expected)) {
     return false;
   }
 
   // Removing sessions requires an exact match.
-  if (SSL_CTX_remove_session(ctx.get(), sessions[0]) ||
-      SSL_CTX_remove_session(ctx.get(), sessions[7]) ||
+  if (SSL_CTX_remove_session(ctx.get(), sessions[0].get()) ||
+      SSL_CTX_remove_session(ctx.get(), sessions[7].get()) ||
       !ExpectCache(ctx.get(), expected)) {
     return false;
   }
@@ -1032,32 +1162,2403 @@
   return true;
 }
 
-int main() {
-  CRYPTO_library_init();
+static uint16_t EpochFromSequence(uint64_t seq) {
+  return static_cast<uint16_t>(seq >> 48);
+}
 
+static bssl::UniquePtr<X509> GetTestCertificate() {
+  static const char kCertPEM[] =
+      "-----BEGIN CERTIFICATE-----\n"
+      "MIICWDCCAcGgAwIBAgIJAPuwTC6rEJsMMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV\n"
+      "BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX\n"
+      "aWRnaXRzIFB0eSBMdGQwHhcNMTQwNDIzMjA1MDQwWhcNMTcwNDIyMjA1MDQwWjBF\n"
+      "MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50\n"
+      "ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB\n"
+      "gQDYK8imMuRi/03z0K1Zi0WnvfFHvwlYeyK9Na6XJYaUoIDAtB92kWdGMdAQhLci\n"
+      "HnAjkXLI6W15OoV3gA/ElRZ1xUpxTMhjP6PyY5wqT5r6y8FxbiiFKKAnHmUcrgfV\n"
+      "W28tQ+0rkLGMryRtrukXOgXBv7gcrmU7G1jC2a7WqmeI8QIDAQABo1AwTjAdBgNV\n"
+      "HQ4EFgQUi3XVrMsIvg4fZbf6Vr5sp3Xaha8wHwYDVR0jBBgwFoAUi3XVrMsIvg4f\n"
+      "Zbf6Vr5sp3Xaha8wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQA76Hht\n"
+      "ldY9avcTGSwbwoiuIqv0jTL1fHFnzy3RHMLDh+Lpvolc5DSrSJHCP5WuK0eeJXhr\n"
+      "T5oQpHL9z/cCDLAKCKRa4uV0fhEdOWBqyR9p8y5jJtye72t6CuFUV5iqcpF4BH4f\n"
+      "j2VNHwsSrJwkD4QUGlUtH7vwnQmyCFxZMmWAJg==\n"
+      "-----END CERTIFICATE-----\n";
+  bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(kCertPEM, strlen(kCertPEM)));
+  return bssl::UniquePtr<X509>(
+      PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr));
+}
+
+static bssl::UniquePtr<EVP_PKEY> GetTestKey() {
+  static const char kKeyPEM[] =
+      "-----BEGIN RSA PRIVATE KEY-----\n"
+      "MIICXgIBAAKBgQDYK8imMuRi/03z0K1Zi0WnvfFHvwlYeyK9Na6XJYaUoIDAtB92\n"
+      "kWdGMdAQhLciHnAjkXLI6W15OoV3gA/ElRZ1xUpxTMhjP6PyY5wqT5r6y8FxbiiF\n"
+      "KKAnHmUcrgfVW28tQ+0rkLGMryRtrukXOgXBv7gcrmU7G1jC2a7WqmeI8QIDAQAB\n"
+      "AoGBAIBy09Fd4DOq/Ijp8HeKuCMKTHqTW1xGHshLQ6jwVV2vWZIn9aIgmDsvkjCe\n"
+      "i6ssZvnbjVcwzSoByhjN8ZCf/i15HECWDFFh6gt0P5z0MnChwzZmvatV/FXCT0j+\n"
+      "WmGNB/gkehKjGXLLcjTb6dRYVJSCZhVuOLLcbWIV10gggJQBAkEA8S8sGe4ezyyZ\n"
+      "m4e9r95g6s43kPqtj5rewTsUxt+2n4eVodD+ZUlCULWVNAFLkYRTBCASlSrm9Xhj\n"
+      "QpmWAHJUkQJBAOVzQdFUaewLtdOJoPCtpYoY1zd22eae8TQEmpGOR11L6kbxLQsk\n"
+      "aMly/DOnOaa82tqAGTdqDEZgSNmCeKKknmECQAvpnY8GUOVAubGR6c+W90iBuQLj\n"
+      "LtFp/9ihd2w/PoDwrHZaoUYVcT4VSfJQog/k7kjE4MYXYWL8eEKg3WTWQNECQQDk\n"
+      "104Wi91Umd1PzF0ijd2jXOERJU1wEKe6XLkYYNHWQAe5l4J4MWj9OdxFXAxIuuR/\n"
+      "tfDwbqkta4xcux67//khAkEAvvRXLHTaa6VFzTaiiO8SaFsHV3lQyXOtMrBpB5jd\n"
+      "moZWgjHvB2W9Ckn7sDqsPB+U2tyX0joDdQEyuiMECDY8oQ==\n"
+      "-----END RSA PRIVATE KEY-----\n";
+  bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(kKeyPEM, strlen(kKeyPEM)));
+  return bssl::UniquePtr<EVP_PKEY>(
+      PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr, nullptr));
+}
+
+static bssl::UniquePtr<X509> GetECDSATestCertificate() {
+  static const char kCertPEM[] =
+      "-----BEGIN CERTIFICATE-----\n"
+      "MIIBzzCCAXagAwIBAgIJANlMBNpJfb/rMAkGByqGSM49BAEwRTELMAkGA1UEBhMC\n"
+      "QVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoMGEludGVybmV0IFdpZGdp\n"
+      "dHMgUHR5IEx0ZDAeFw0xNDA0MjMyMzIxNTdaFw0xNDA1MjMyMzIxNTdaMEUxCzAJ\n"
+      "BgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5l\n"
+      "dCBXaWRnaXRzIFB0eSBMdGQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATmK2ni\n"
+      "v2Wfl74vHg2UikzVl2u3qR4NRvvdqakendy6WgHn1peoChj5w8SjHlbifINI2xYa\n"
+      "HPUdfvGULUvPciLBo1AwTjAdBgNVHQ4EFgQUq4TSrKuV8IJOFngHVVdf5CaNgtEw\n"
+      "HwYDVR0jBBgwFoAUq4TSrKuV8IJOFngHVVdf5CaNgtEwDAYDVR0TBAUwAwEB/zAJ\n"
+      "BgcqhkjOPQQBA0gAMEUCIQDyoDVeUTo2w4J5m+4nUIWOcAZ0lVfSKXQA9L4Vh13E\n"
+      "BwIgfB55FGohg/B6dGh5XxSZmmi08cueFV7mHzJSYV51yRQ=\n"
+      "-----END CERTIFICATE-----\n";
+  bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(kCertPEM, strlen(kCertPEM)));
+  return bssl::UniquePtr<X509>(PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr));
+}
+
+static bssl::UniquePtr<EVP_PKEY> GetECDSATestKey() {
+  static const char kKeyPEM[] =
+      "-----BEGIN PRIVATE KEY-----\n"
+      "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgBw8IcnrUoEqc3VnJ\n"
+      "TYlodwi1b8ldMHcO6NHJzgqLtGqhRANCAATmK2niv2Wfl74vHg2UikzVl2u3qR4N\n"
+      "Rvvdqakendy6WgHn1peoChj5w8SjHlbifINI2xYaHPUdfvGULUvPciLB\n"
+      "-----END PRIVATE KEY-----\n";
+  bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(kKeyPEM, strlen(kKeyPEM)));
+  return bssl::UniquePtr<EVP_PKEY>(
+      PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr, nullptr));
+}
+
+static bssl::UniquePtr<CRYPTO_BUFFER> BufferFromPEM(const char *pem) {
+  bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(pem, strlen(pem)));
+  char *name, *header;
+  uint8_t *data;
+  long data_len;
+  if (!PEM_read_bio(bio.get(), &name, &header, &data,
+                    &data_len)) {
+    return nullptr;
+  }
+  OPENSSL_free(name);
+  OPENSSL_free(header);
+
+  auto ret = bssl::UniquePtr<CRYPTO_BUFFER>(
+      CRYPTO_BUFFER_new(data, data_len, nullptr));
+  OPENSSL_free(data);
+  return ret;
+}
+
+static bssl::UniquePtr<CRYPTO_BUFFER> GetChainTestCertificateBuffer() {
+  static const char kCertPEM[] =
+      "-----BEGIN CERTIFICATE-----\n"
+      "MIIC0jCCAbqgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwDzENMAsGA1UEAwwEQiBD\n"
+      "QTAeFw0xNjAyMjgyMDI3MDNaFw0yNjAyMjUyMDI3MDNaMBgxFjAUBgNVBAMMDUNs\n"
+      "aWVudCBDZXJ0IEEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDRvaz8\n"
+      "CC/cshpCafJo4jLkHEoBqDLhdgFelJoAiQUyIqyWl2O7YHPnpJH+TgR7oelzNzt/\n"
+      "kLRcH89M/TszB6zqyLTC4aqmvzKL0peD/jL2LWBucR0WXIvjA3zoRuF/x86+rYH3\n"
+      "tHb+xs2PSs8EGL/Ev+ss+qTzTGEn26fuGNHkNw6tOwPpc+o8+wUtzf/kAthamo+c\n"
+      "IDs2rQ+lP7+aLZTLeU/q4gcLutlzcK5imex5xy2jPkweq48kijK0kIzl1cPlA5d1\n"
+      "z7C8jU50Pj9X9sQDJTN32j7UYRisJeeYQF8GaaN8SbrDI6zHgKzrRLyxDt/KQa9V\n"
+      "iLeXANgZi+Xx9KgfAgMBAAGjLzAtMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYwFAYI\n"
+      "KwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQBFEVbmYl+2RtNw\n"
+      "rDftRDF1v2QUbcN2ouSnQDHxeDQdSgasLzT3ui8iYu0Rw2WWcZ0DV5e0ztGPhWq7\n"
+      "AO0B120aFRMOY+4+bzu9Q2FFkQqc7/fKTvTDzIJI5wrMnFvUfzzvxh3OHWMYSs/w\n"
+      "giq33hTKeHEq6Jyk3btCny0Ycecyc3yGXH10sizUfiHlhviCkDuESk8mFDwDDzqW\n"
+      "ZF0IipzFbEDHoIxLlm3GQxpiLoEV4k8KYJp3R5KBLFyxM6UGPz8h72mIPCJp2RuK\n"
+      "MYgF91UDvVzvnYm6TfseM2+ewKirC00GOrZ7rEcFvtxnKSqYf4ckqfNdSU1Y+RRC\n"
+      "1ngWZ7Ih\n"
+      "-----END CERTIFICATE-----\n";
+  return BufferFromPEM(kCertPEM);
+}
+
+static bssl::UniquePtr<X509> X509FromBuffer(
+    bssl::UniquePtr<CRYPTO_BUFFER> buffer) {
+  if (!buffer) {
+    return nullptr;
+  }
+  const uint8_t *derp = CRYPTO_BUFFER_data(buffer.get());
+  return bssl::UniquePtr<X509>(
+      d2i_X509(NULL, &derp, CRYPTO_BUFFER_len(buffer.get())));
+}
+
+static bssl::UniquePtr<X509> GetChainTestCertificate() {
+  return X509FromBuffer(GetChainTestCertificateBuffer());
+}
+
+static bssl::UniquePtr<CRYPTO_BUFFER> GetChainTestIntermediateBuffer() {
+  static const char kCertPEM[] =
+      "-----BEGIN CERTIFICATE-----\n"
+      "MIICwjCCAaqgAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwFDESMBAGA1UEAwwJQyBS\n"
+      "b290IENBMB4XDTE2MDIyODIwMjcwM1oXDTI2MDIyNTIwMjcwM1owDzENMAsGA1UE\n"
+      "AwwEQiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALsSCYmDip2D\n"
+      "GkjFxw7ykz26JSjELkl6ArlYjFJ3aT/SCh8qbS4gln7RH8CPBd78oFdfhIKQrwtZ\n"
+      "3/q21ykD9BAS3qHe2YdcJfm8/kWAy5DvXk6NXU4qX334KofBAEpgdA/igEFq1P1l\n"
+      "HAuIfZCpMRfT+i5WohVsGi8f/NgpRvVaMONLNfgw57mz1lbtFeBEISmX0kbsuJxF\n"
+      "Qj/Bwhi5/0HAEXG8e7zN4cEx0yPRvmOATRdVb/8dW2pwOHRJq9R5M0NUkIsTSnL7\n"
+      "6N/z8hRAHMsV3IudC5Yd7GXW1AGu9a+iKU+Q4xcZCoj0DC99tL4VKujrV1kAeqsM\n"
+      "cz5/dKzi6+cCAwEAAaMjMCEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC\n"
+      "AQYwDQYJKoZIhvcNAQELBQADggEBAIIeZiEeNhWWQ8Y4D+AGDwqUUeG8NjCbKrXQ\n"
+      "BlHg5wZ8xftFaiP1Dp/UAezmx2LNazdmuwrYB8lm3FVTyaPDTKEGIPS4wJKHgqH1\n"
+      "QPDhqNm85ey7TEtI9oYjsNim/Rb+iGkIAMXaxt58SzxbjvP0kMr1JfJIZbic9vye\n"
+      "NwIspMFIpP3FB8ywyu0T0hWtCQgL4J47nigCHpOu58deP88fS/Nyz/fyGVWOZ76b\n"
+      "WhWwgM3P3X95fQ3d7oFPR/bVh0YV+Cf861INwplokXgXQ3/TCQ+HNXeAMWn3JLWv\n"
+      "XFwk8owk9dq/kQGdndGgy3KTEW4ctPX5GNhf3LJ9Q7dLji4ReQ4=\n"
+      "-----END CERTIFICATE-----\n";
+  return BufferFromPEM(kCertPEM);
+}
+
+static bssl::UniquePtr<X509> GetChainTestIntermediate() {
+  return X509FromBuffer(GetChainTestIntermediateBuffer());
+}
+
+static bssl::UniquePtr<EVP_PKEY> GetChainTestKey() {
+  static const char kKeyPEM[] =
+      "-----BEGIN PRIVATE KEY-----\n"
+      "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDRvaz8CC/cshpC\n"
+      "afJo4jLkHEoBqDLhdgFelJoAiQUyIqyWl2O7YHPnpJH+TgR7oelzNzt/kLRcH89M\n"
+      "/TszB6zqyLTC4aqmvzKL0peD/jL2LWBucR0WXIvjA3zoRuF/x86+rYH3tHb+xs2P\n"
+      "Ss8EGL/Ev+ss+qTzTGEn26fuGNHkNw6tOwPpc+o8+wUtzf/kAthamo+cIDs2rQ+l\n"
+      "P7+aLZTLeU/q4gcLutlzcK5imex5xy2jPkweq48kijK0kIzl1cPlA5d1z7C8jU50\n"
+      "Pj9X9sQDJTN32j7UYRisJeeYQF8GaaN8SbrDI6zHgKzrRLyxDt/KQa9ViLeXANgZ\n"
+      "i+Xx9KgfAgMBAAECggEBAK0VjSJzkyPaamcyTVSWjo7GdaBGcK60lk657RjR+lK0\n"
+      "YJ7pkej4oM2hdsVZFsP8Cs4E33nXLa/0pDsRov/qrp0WQm2skwqGMC1I/bZ0WRPk\n"
+      "wHaDrBBfESWnJDX/AGpVtlyOjPmgmK6J2usMPihQUDkKdAYrVWJePrMIxt1q6BMe\n"
+      "iczs3qriMmtY3bUc4UyUwJ5fhDLjshHvfuIpYQyI6EXZM6dZksn9LylXJnigY6QJ\n"
+      "HxOYO0BDwOsZ8yQ8J8afLk88i0GizEkgE1z3REtQUwgWfxr1WV/ud+T6/ZhSAgH9\n"
+      "042mQvSFZnIUSEsmCvjhWuAunfxHKCTcAoYISWfzWpkCgYEA7gpf3HHU5Tn+CgUn\n"
+      "1X5uGpG3DmcMgfeGgs2r2f/IIg/5Ac1dfYILiybL1tN9zbyLCJfcbFpWBc9hJL6f\n"
+      "CPc5hUiwWFJqBJewxQkC1Ae/HakHbip+IZ+Jr0842O4BAArvixk4Lb7/N2Ct9sTE\n"
+      "NJO6RtK9lbEZ5uK61DglHy8CS2UCgYEA4ZC1o36kPAMQBggajgnucb2yuUEelk0f\n"
+      "AEr+GI32MGE+93xMr7rAhBoqLg4AITyIfEnOSQ5HwagnIHonBbv1LV/Gf9ursx8Z\n"
+      "YOGbvT8zzzC+SU1bkDzdjAYnFQVGIjMtKOBJ3K07++ypwX1fr4QsQ8uKL8WSOWwt\n"
+      "Z3Bym6XiZzMCgYADnhy+2OwHX85AkLt+PyGlPbmuelpyTzS4IDAQbBa6jcuW/2wA\n"
+      "UE2km75VUXmD+u2R/9zVuLm99NzhFhSMqlUxdV1YukfqMfP5yp1EY6m/5aW7QuIP\n"
+      "2MDa7TVL9rIFMiVZ09RKvbBbQxjhuzPQKL6X/PPspnhiTefQ+dl2k9xREQKBgHDS\n"
+      "fMfGNEeAEKezrfSVqxphE9/tXms3L+ZpnCaT+yu/uEr5dTIAawKoQ6i9f/sf1/Sy\n"
+      "xedsqR+IB+oKrzIDDWMgoJybN4pkZ8E5lzhVQIjFjKgFdWLzzqyW9z1gYfABQPlN\n"
+      "FiS20WX0vgP1vcKAjdNrHzc9zyHBpgQzDmAj3NZZAoGBAI8vKCKdH7w3aL5CNkZQ\n"
+      "2buIeWNA2HZazVwAGG5F2TU/LmXfRKnG6dX5bkU+AkBZh56jNZy//hfFSewJB4Kk\n"
+      "buB7ERSdaNbO21zXt9FEA3+z0RfMd/Zv2vlIWOSB5nzl/7UKti3sribK6s9ZVLfi\n"
+      "SxpiPQ8d/hmSGwn4ksrWUsJD\n"
+      "-----END PRIVATE KEY-----\n";
+  bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(kKeyPEM, strlen(kKeyPEM)));
+  return bssl::UniquePtr<EVP_PKEY>(
+      PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr, nullptr));
+}
+
+static bool CompleteHandshakes(SSL *client, SSL *server) {
+  // Drive both their handshakes to completion.
+  for (;;) {
+    int client_ret = SSL_do_handshake(client);
+    int client_err = SSL_get_error(client, client_ret);
+    if (client_err != SSL_ERROR_NONE &&
+        client_err != SSL_ERROR_WANT_READ &&
+        client_err != SSL_ERROR_WANT_WRITE &&
+        client_err != SSL_ERROR_PENDING_TICKET) {
+      fprintf(stderr, "Client error: %d\n", client_err);
+      return false;
+    }
+
+    int server_ret = SSL_do_handshake(server);
+    int server_err = SSL_get_error(server, server_ret);
+    if (server_err != SSL_ERROR_NONE &&
+        server_err != SSL_ERROR_WANT_READ &&
+        server_err != SSL_ERROR_WANT_WRITE &&
+        server_err != SSL_ERROR_PENDING_TICKET) {
+      fprintf(stderr, "Server error: %d\n", server_err);
+      return false;
+    }
+
+    if (client_ret == 1 && server_ret == 1) {
+      break;
+    }
+  }
+
+  return true;
+}
+
+static bool ConnectClientAndServer(bssl::UniquePtr<SSL> *out_client,
+                                   bssl::UniquePtr<SSL> *out_server,
+                                   SSL_CTX *client_ctx, SSL_CTX *server_ctx,
+                                   SSL_SESSION *session) {
+  bssl::UniquePtr<SSL> client(SSL_new(client_ctx)), server(SSL_new(server_ctx));
+  if (!client || !server) {
+    return false;
+  }
+  SSL_set_connect_state(client.get());
+  SSL_set_accept_state(server.get());
+
+  SSL_set_session(client.get(), session);
+
+  BIO *bio1, *bio2;
+  if (!BIO_new_bio_pair(&bio1, 0, &bio2, 0)) {
+    return false;
+  }
+  // SSL_set_bio takes ownership.
+  SSL_set_bio(client.get(), bio1, bio1);
+  SSL_set_bio(server.get(), bio2, bio2);
+
+  if (!CompleteHandshakes(client.get(), server.get())) {
+    return false;
+  }
+
+  *out_client = std::move(client);
+  *out_server = std::move(server);
+  return true;
+}
+
+static bool TestSequenceNumber(bool is_dtls, const SSL_METHOD *method,
+                               uint16_t version) {
+  bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(method));
+  bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(method));
+  if (!server_ctx || !client_ctx ||
+      !SSL_CTX_set_min_proto_version(client_ctx.get(), version) ||
+      !SSL_CTX_set_max_proto_version(client_ctx.get(), version) ||
+      !SSL_CTX_set_min_proto_version(server_ctx.get(), version) ||
+      !SSL_CTX_set_max_proto_version(server_ctx.get(), version)) {
+    return false;
+  }
+
+  bssl::UniquePtr<X509> cert = GetTestCertificate();
+  bssl::UniquePtr<EVP_PKEY> key = GetTestKey();
+  if (!cert || !key || !SSL_CTX_use_certificate(server_ctx.get(), cert.get()) ||
+      !SSL_CTX_use_PrivateKey(server_ctx.get(), key.get())) {
+    return false;
+  }
+
+  bssl::UniquePtr<SSL> client, server;
+  if (!ConnectClientAndServer(&client, &server, client_ctx.get(),
+                              server_ctx.get(), nullptr /* no session */)) {
+    return false;
+  }
+
+  // Drain any post-handshake messages to ensure there are no unread records
+  // on either end.
+  uint8_t byte = 0;
+  if (SSL_read(client.get(), &byte, 1) > 0 ||
+      SSL_read(server.get(), &byte, 1) > 0) {
+    fprintf(stderr, "Received unexpected data.\n");
+    return false;
+  }
+
+  uint64_t client_read_seq = SSL_get_read_sequence(client.get());
+  uint64_t client_write_seq = SSL_get_write_sequence(client.get());
+  uint64_t server_read_seq = SSL_get_read_sequence(server.get());
+  uint64_t server_write_seq = SSL_get_write_sequence(server.get());
+
+  if (is_dtls) {
+    // Both client and server must be at epoch 1.
+    if (EpochFromSequence(client_read_seq) != 1 ||
+        EpochFromSequence(client_write_seq) != 1 ||
+        EpochFromSequence(server_read_seq) != 1 ||
+        EpochFromSequence(server_write_seq) != 1) {
+      fprintf(stderr, "Bad epochs.\n");
+      return false;
+    }
+
+    // The next record to be written should exceed the largest received.
+    if (client_write_seq <= server_read_seq ||
+        server_write_seq <= client_read_seq) {
+      fprintf(stderr, "Inconsistent sequence numbers.\n");
+      return false;
+    }
+  } else {
+    // The next record to be written should equal the next to be received.
+    if (client_write_seq != server_read_seq ||
+        server_write_seq != client_read_seq) {
+      fprintf(stderr, "Inconsistent sequence numbers.\n");
+      return false;
+    }
+  }
+
+  // Send a record from client to server.
+  if (SSL_write(client.get(), &byte, 1) != 1 ||
+      SSL_read(server.get(), &byte, 1) != 1) {
+    fprintf(stderr, "Could not send byte.\n");
+    return false;
+  }
+
+  // The client write and server read sequence numbers should have
+  // incremented.
+  if (client_write_seq + 1 != SSL_get_write_sequence(client.get()) ||
+      server_read_seq + 1 != SSL_get_read_sequence(server.get())) {
+    fprintf(stderr, "Sequence numbers did not increment.\n");
+    return false;
+  }
+
+  return true;
+}
+
+static bool TestOneSidedShutdown(bool is_dtls, const SSL_METHOD *method,
+                                 uint16_t version) {
+  // SSL_shutdown is a no-op in DTLS.
+  if (is_dtls) {
+    return true;
+  }
+
+  bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(method));
+  bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(method));
+  bssl::UniquePtr<X509> cert = GetTestCertificate();
+  bssl::UniquePtr<EVP_PKEY> key = GetTestKey();
+  if (!client_ctx || !server_ctx || !cert || !key ||
+      !SSL_CTX_set_min_proto_version(server_ctx.get(), version) ||
+      !SSL_CTX_set_max_proto_version(server_ctx.get(), version) ||
+      !SSL_CTX_set_min_proto_version(client_ctx.get(), version) ||
+      !SSL_CTX_set_max_proto_version(client_ctx.get(), version) ||
+      !SSL_CTX_use_certificate(server_ctx.get(), cert.get()) ||
+      !SSL_CTX_use_PrivateKey(server_ctx.get(), key.get())) {
+    return false;
+  }
+
+  bssl::UniquePtr<SSL> client, server;
+  if (!ConnectClientAndServer(&client, &server, client_ctx.get(),
+                              server_ctx.get(), nullptr /* no session */)) {
+    return false;
+  }
+
+  // Shut down half the connection. SSL_shutdown will return 0 to signal only
+  // one side has shut down.
+  if (SSL_shutdown(client.get()) != 0) {
+    fprintf(stderr, "Could not shutdown.\n");
+    return false;
+  }
+
+  // Reading from the server should consume the EOF.
+  uint8_t byte;
+  if (SSL_read(server.get(), &byte, 1) != 0 ||
+      SSL_get_error(server.get(), 0) != SSL_ERROR_ZERO_RETURN) {
+    fprintf(stderr, "Connection was not shut down cleanly.\n");
+    return false;
+  }
+
+  // However, the server may continue to write data and then shut down the
+  // connection.
+  byte = 42;
+  if (SSL_write(server.get(), &byte, 1) != 1 ||
+      SSL_read(client.get(), &byte, 1) != 1 ||
+      byte != 42) {
+    fprintf(stderr, "Could not send byte.\n");
+    return false;
+  }
+
+  // The server may then shutdown the connection.
+  if (SSL_shutdown(server.get()) != 1 ||
+      SSL_shutdown(client.get()) != 1) {
+    fprintf(stderr, "Could not complete shutdown.\n");
+    return false;
+  }
+
+  return true;
+}
+
+TEST(SSLTest, SessionDuplication) {
+  bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(TLS_method()));
+  bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(TLS_method()));
+  ASSERT_TRUE(client_ctx);
+  ASSERT_TRUE(server_ctx);
+
+  bssl::UniquePtr<X509> cert = GetTestCertificate();
+  bssl::UniquePtr<EVP_PKEY> key = GetTestKey();
+  ASSERT_TRUE(cert);
+  ASSERT_TRUE(key);
+  ASSERT_TRUE(SSL_CTX_use_certificate(server_ctx.get(), cert.get()));
+  ASSERT_TRUE(SSL_CTX_use_PrivateKey(server_ctx.get(), key.get()));
+
+  bssl::UniquePtr<SSL> client, server;
+  ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
+                                     server_ctx.get(),
+                                     nullptr /* no session */));
+
+  SSL_SESSION *session0 = SSL_get_session(client.get());
+  bssl::UniquePtr<SSL_SESSION> session1(
+      SSL_SESSION_dup(session0, SSL_SESSION_DUP_ALL));
+  ASSERT_TRUE(session1);
+
+  session1->not_resumable = 0;
+
+  uint8_t *s0_bytes, *s1_bytes;
+  size_t s0_len, s1_len;
+
+  ASSERT_TRUE(SSL_SESSION_to_bytes(session0, &s0_bytes, &s0_len));
+  bssl::UniquePtr<uint8_t> free_s0(s0_bytes);
+
+  ASSERT_TRUE(SSL_SESSION_to_bytes(session1.get(), &s1_bytes, &s1_len));
+  bssl::UniquePtr<uint8_t> free_s1(s1_bytes);
+
+  EXPECT_EQ(Bytes(s0_bytes, s0_len), Bytes(s1_bytes, s1_len));
+}
+
+static void ExpectFDs(const SSL *ssl, int rfd, int wfd) {
+  EXPECT_EQ(rfd, SSL_get_rfd(ssl));
+  EXPECT_EQ(wfd, SSL_get_wfd(ssl));
+
+  // The wrapper BIOs are always equal when fds are equal, even if set
+  // individually.
+  if (rfd == wfd) {
+    EXPECT_EQ(SSL_get_rbio(ssl), SSL_get_wbio(ssl));
+  }
+}
+
+TEST(SSLTest, SetFD) {
+  bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
+  ASSERT_TRUE(ctx);
+
+  // Test setting different read and write FDs.
+  bssl::UniquePtr<SSL> ssl(SSL_new(ctx.get()));
+  ASSERT_TRUE(ssl);
+  EXPECT_TRUE(SSL_set_rfd(ssl.get(), 1));
+  EXPECT_TRUE(SSL_set_wfd(ssl.get(), 2));
+  ExpectFDs(ssl.get(), 1, 2);
+
+  // Test setting the same FD.
+  ssl.reset(SSL_new(ctx.get()));
+  ASSERT_TRUE(ssl);
+  EXPECT_TRUE(SSL_set_fd(ssl.get(), 1));
+  ExpectFDs(ssl.get(), 1, 1);
+
+  // Test setting the same FD one side at a time.
+  ssl.reset(SSL_new(ctx.get()));
+  ASSERT_TRUE(ssl);
+  EXPECT_TRUE(SSL_set_rfd(ssl.get(), 1));
+  EXPECT_TRUE(SSL_set_wfd(ssl.get(), 1));
+  ExpectFDs(ssl.get(), 1, 1);
+
+  // Test setting the same FD in the other order.
+  ssl.reset(SSL_new(ctx.get()));
+  ASSERT_TRUE(ssl);
+  EXPECT_TRUE(SSL_set_wfd(ssl.get(), 1));
+  EXPECT_TRUE(SSL_set_rfd(ssl.get(), 1));
+  ExpectFDs(ssl.get(), 1, 1);
+
+  // Test changing the read FD partway through.
+  ssl.reset(SSL_new(ctx.get()));
+  ASSERT_TRUE(ssl);
+  EXPECT_TRUE(SSL_set_fd(ssl.get(), 1));
+  EXPECT_TRUE(SSL_set_rfd(ssl.get(), 2));
+  ExpectFDs(ssl.get(), 2, 1);
+
+  // Test changing the write FD partway through.
+  ssl.reset(SSL_new(ctx.get()));
+  ASSERT_TRUE(ssl);
+  EXPECT_TRUE(SSL_set_fd(ssl.get(), 1));
+  EXPECT_TRUE(SSL_set_wfd(ssl.get(), 2));
+  ExpectFDs(ssl.get(), 1, 2);
+
+  // Test a no-op change to the read FD partway through.
+  ssl.reset(SSL_new(ctx.get()));
+  ASSERT_TRUE(ssl);
+  EXPECT_TRUE(SSL_set_fd(ssl.get(), 1));
+  EXPECT_TRUE(SSL_set_rfd(ssl.get(), 1));
+  ExpectFDs(ssl.get(), 1, 1);
+
+  // Test a no-op change to the write FD partway through.
+  ssl.reset(SSL_new(ctx.get()));
+  ASSERT_TRUE(ssl);
+  EXPECT_TRUE(SSL_set_fd(ssl.get(), 1));
+  EXPECT_TRUE(SSL_set_wfd(ssl.get(), 1));
+  ExpectFDs(ssl.get(), 1, 1);
+
+  // ASan builds will implicitly test that the internal |BIO| reference-counting
+  // is correct.
+}
+
+TEST(SSLTest, SetBIO) {
+  bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
+  ASSERT_TRUE(ctx);
+
+  bssl::UniquePtr<SSL> ssl(SSL_new(ctx.get()));
+  bssl::UniquePtr<BIO> bio1(BIO_new(BIO_s_mem())), bio2(BIO_new(BIO_s_mem())),
+      bio3(BIO_new(BIO_s_mem()));
+  ASSERT_TRUE(ssl);
+  ASSERT_TRUE(bio1);
+  ASSERT_TRUE(bio2);
+  ASSERT_TRUE(bio3);
+
+  // SSL_set_bio takes one reference when the parameters are the same.
+  BIO_up_ref(bio1.get());
+  SSL_set_bio(ssl.get(), bio1.get(), bio1.get());
+
+  // Repeating the call does nothing.
+  SSL_set_bio(ssl.get(), bio1.get(), bio1.get());
+
+  // It takes one reference each when the parameters are different.
+  BIO_up_ref(bio2.get());
+  BIO_up_ref(bio3.get());
+  SSL_set_bio(ssl.get(), bio2.get(), bio3.get());
+
+  // Repeating the call does nothing.
+  SSL_set_bio(ssl.get(), bio2.get(), bio3.get());
+
+  // It takes one reference when changing only wbio.
+  BIO_up_ref(bio1.get());
+  SSL_set_bio(ssl.get(), bio2.get(), bio1.get());
+
+  // It takes one reference when changing only rbio and the two are different.
+  BIO_up_ref(bio3.get());
+  SSL_set_bio(ssl.get(), bio3.get(), bio1.get());
+
+  // If setting wbio to rbio, it takes no additional references.
+  SSL_set_bio(ssl.get(), bio3.get(), bio3.get());
+
+  // From there, wbio may be switched to something else.
+  BIO_up_ref(bio1.get());
+  SSL_set_bio(ssl.get(), bio3.get(), bio1.get());
+
+  // If setting rbio to wbio, it takes no additional references.
+  SSL_set_bio(ssl.get(), bio1.get(), bio1.get());
+
+  // From there, rbio may be switched to something else, but, for historical
+  // reasons, it takes a reference to both parameters.
+  BIO_up_ref(bio1.get());
+  BIO_up_ref(bio2.get());
+  SSL_set_bio(ssl.get(), bio2.get(), bio1.get());
+
+  // ASAN builds will implicitly test that the internal |BIO| reference-counting
+  // is correct.
+}
+
+static int VerifySucceed(X509_STORE_CTX *store_ctx, void *arg) { return 1; }
+
+static bool TestGetPeerCertificate(bool is_dtls, const SSL_METHOD *method,
+                                   uint16_t version) {
+  bssl::UniquePtr<X509> cert = GetTestCertificate();
+  bssl::UniquePtr<EVP_PKEY> key = GetTestKey();
+  if (!cert || !key) {
+    return false;
+  }
+
+  // Configure both client and server to accept any certificate.
+  bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(method));
+  if (!ctx ||
+      !SSL_CTX_use_certificate(ctx.get(), cert.get()) ||
+      !SSL_CTX_use_PrivateKey(ctx.get(), key.get()) ||
+      !SSL_CTX_set_min_proto_version(ctx.get(), version) ||
+      !SSL_CTX_set_max_proto_version(ctx.get(), version)) {
+    return false;
+  }
+  SSL_CTX_set_verify(
+      ctx.get(), SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr);
+  SSL_CTX_set_cert_verify_callback(ctx.get(), VerifySucceed, NULL);
+
+  bssl::UniquePtr<SSL> client, server;
+  if (!ConnectClientAndServer(&client, &server, ctx.get(), ctx.get(),
+                              nullptr /* no session */)) {
+    return false;
+  }
+
+  // Client and server should both see the leaf certificate.
+  bssl::UniquePtr<X509> peer(SSL_get_peer_certificate(server.get()));
+  if (!peer || X509_cmp(cert.get(), peer.get()) != 0) {
+    fprintf(stderr, "Server peer certificate did not match.\n");
+    return false;
+  }
+
+  peer.reset(SSL_get_peer_certificate(client.get()));
+  if (!peer || X509_cmp(cert.get(), peer.get()) != 0) {
+    fprintf(stderr, "Client peer certificate did not match.\n");
+    return false;
+  }
+
+  // However, for historical reasons, the chain includes the leaf on the
+  // client, but does not on the server.
+  if (sk_X509_num(SSL_get_peer_cert_chain(client.get())) != 1) {
+    fprintf(stderr, "Client peer chain was incorrect.\n");
+    return false;
+  }
+
+  if (sk_X509_num(SSL_get_peer_cert_chain(server.get())) != 0) {
+    fprintf(stderr, "Server peer chain was incorrect.\n");
+    return false;
+  }
+
+  return true;
+}
+
+static bool TestRetainOnlySHA256OfCerts(bool is_dtls, const SSL_METHOD *method,
+                                        uint16_t version) {
+  bssl::UniquePtr<X509> cert = GetTestCertificate();
+  bssl::UniquePtr<EVP_PKEY> key = GetTestKey();
+  if (!cert || !key) {
+    return false;
+  }
+
+  uint8_t *cert_der = NULL;
+  int cert_der_len = i2d_X509(cert.get(), &cert_der);
+  if (cert_der_len < 0) {
+    return false;
+  }
+  bssl::UniquePtr<uint8_t> free_cert_der(cert_der);
+
+  uint8_t cert_sha256[SHA256_DIGEST_LENGTH];
+  SHA256(cert_der, cert_der_len, cert_sha256);
+
+  // Configure both client and server to accept any certificate, but the
+  // server must retain only the SHA-256 of the peer.
+  bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(method));
+  if (!ctx ||
+      !SSL_CTX_use_certificate(ctx.get(), cert.get()) ||
+      !SSL_CTX_use_PrivateKey(ctx.get(), key.get()) ||
+      !SSL_CTX_set_min_proto_version(ctx.get(), version) ||
+      !SSL_CTX_set_max_proto_version(ctx.get(), version)) {
+    return false;
+  }
+  SSL_CTX_set_verify(
+      ctx.get(), SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr);
+  SSL_CTX_set_cert_verify_callback(ctx.get(), VerifySucceed, NULL);
+  SSL_CTX_set_retain_only_sha256_of_client_certs(ctx.get(), 1);
+
+  bssl::UniquePtr<SSL> client, server;
+  if (!ConnectClientAndServer(&client, &server, ctx.get(), ctx.get(),
+                              nullptr /* no session */)) {
+    return false;
+  }
+
+  // The peer certificate has been dropped.
+  bssl::UniquePtr<X509> peer(SSL_get_peer_certificate(server.get()));
+  if (peer) {
+    fprintf(stderr, "Peer certificate was retained.\n");
+    return false;
+  }
+
+  SSL_SESSION *session = SSL_get_session(server.get());
+  if (!session->peer_sha256_valid) {
+    fprintf(stderr, "peer_sha256_valid was not set.\n");
+    return false;
+  }
+
+  if (OPENSSL_memcmp(cert_sha256, session->peer_sha256, SHA256_DIGEST_LENGTH) !=
+      0) {
+    fprintf(stderr, "peer_sha256 did not match.\n");
+    return false;
+  }
+
+  return true;
+}
+
+static bool ClientHelloMatches(uint16_t version, const uint8_t *expected,
+                               size_t expected_len) {
+  bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
+  // Our default cipher list varies by CPU capabilities, so manually place the
+  // ChaCha20 ciphers in front.
+  const char* cipher_list =
+#ifdef BORINGSSL_ENABLE_DHE_TLS
+      "!DHE:CHACHA20:ALL";
+#else
+      "CHACHA20:ALL";
+#endif
+  if (!ctx ||
+      !SSL_CTX_set_max_proto_version(ctx.get(), version) ||
+      !SSL_CTX_set_strict_cipher_list(ctx.get(), cipher_list)) {
+    return false;
+  }
+
+  bssl::UniquePtr<SSL> ssl(SSL_new(ctx.get()));
+  if (!ssl) {
+    return false;
+  }
+  std::vector<uint8_t> client_hello;
+  if (!GetClientHello(ssl.get(), &client_hello)) {
+    return false;
+  }
+
+  // Zero the client_random.
+  constexpr size_t kRandomOffset = 1 + 2 + 2 +  // record header
+                                   1 + 3 +      // handshake message header
+                                   2;           // client_version
+  if (client_hello.size() < kRandomOffset + SSL3_RANDOM_SIZE) {
+    fprintf(stderr, "ClientHello for version %04x too short.\n", version);
+    return false;
+  }
+  OPENSSL_memset(client_hello.data() + kRandomOffset, 0, SSL3_RANDOM_SIZE);
+
+  if (client_hello.size() != expected_len ||
+      OPENSSL_memcmp(client_hello.data(), expected, expected_len) != 0) {
+    fprintf(stderr, "ClientHello for version %04x did not match:\n", version);
+    fprintf(stderr, "Got:\n\t");
+    for (size_t i = 0; i < client_hello.size(); i++) {
+      fprintf(stderr, "0x%02x, ", client_hello[i]);
+    }
+    fprintf(stderr, "\nWanted:\n\t");
+    for (size_t i = 0; i < expected_len; i++) {
+      fprintf(stderr, "0x%02x, ", expected[i]);
+    }
+    fprintf(stderr, "\n");
+    return false;
+  }
+
+  return true;
+}
+
+// Tests that our ClientHellos do not change unexpectedly.
+static bool TestClientHello() {
+  static const uint8_t kSSL3ClientHello[] = {
+    0x16,
+    0x03, 0x00,
+    0x00, 0x3b,
+    0x01,
+    0x00, 0x00, 0x37,
+    0x03, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00,
+    0x00, 0x10,
+    0xc0, 0x09,
+    0xc0, 0x13,
+    0xc0, 0x0a,
+    0xc0, 0x14,
+    0x00, 0x2f,
+    0x00, 0x35,
+    0x00, 0x0a,
+    0x00, 0xff, 0x01, 0x00,
+  };
+  if (!ClientHelloMatches(SSL3_VERSION, kSSL3ClientHello,
+                          sizeof(kSSL3ClientHello))) {
+    return false;
+  }
+
+  static const uint8_t kTLS1ClientHello[] = {
+      0x16,
+      0x03, 0x01,
+      0x00, 0x5a,
+      0x01,
+      0x00, 0x00, 0x56,
+      0x03, 0x01,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00,
+      0x00, 0x0e,
+      0xc0, 0x09,
+      0xc0, 0x13,
+      0xc0, 0x0a,
+      0xc0, 0x14,
+      0x00, 0x2f,
+      0x00, 0x35,
+      0x00, 0x0a,
+      0x01, 0x00, 0x00, 0x1f, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x17, 0x00,
+      0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00,
+      0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18,
+  };
+  if (!ClientHelloMatches(TLS1_VERSION, kTLS1ClientHello,
+                          sizeof(kTLS1ClientHello))) {
+    return false;
+  }
+
+  static const uint8_t kTLS11ClientHello[] = {
+      0x16,
+      0x03, 0x01,
+      0x00, 0x5a,
+      0x01,
+      0x00, 0x00, 0x56,
+      0x03, 0x02,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00,
+      0x00, 0x0e,
+      0xc0, 0x09,
+      0xc0, 0x13,
+      0xc0, 0x0a,
+      0xc0, 0x14,
+      0x00, 0x2f,
+      0x00, 0x35,
+      0x00, 0x0a,
+      0x01, 0x00, 0x00, 0x1f, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x17, 0x00,
+      0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00,
+      0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18,
+  };
+  if (!ClientHelloMatches(TLS1_1_VERSION, kTLS11ClientHello,
+                          sizeof(kTLS11ClientHello))) {
+    return false;
+  }
+
+  // kTLS12ClientHello assumes RSA-PSS, which is disabled for Android system
+  // builds.
+#if defined(BORINGSSL_ANDROID_SYSTEM)
+  return true;
+#endif
+
+  static const uint8_t kTLS12ClientHello[] = {
+      0x16,
+      0x03, 0x01,
+      0x00, 0x8e,
+      0x01,
+      0x00, 0x00, 0x8a,
+      0x03, 0x03,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+      0x00, 0x2a,
+      0xcc, 0xa9,
+      0xcc, 0xa8,
+      0xc0, 0x2b,
+      0xc0, 0x2f,
+      0xc0, 0x2c,
+      0xc0, 0x30,
+      0xc0, 0x09,
+      0xc0, 0x23,
+      0xc0, 0x13,
+      0xc0, 0x27,
+      0xc0, 0x0a,
+      0xc0, 0x24,
+      0xc0, 0x14,
+      0xc0, 0x28,
+      0x00, 0x9c,
+      0x00, 0x9d,
+      0x00, 0x2f,
+      0x00, 0x3c,
+      0x00, 0x35,
+      0x00, 0x3d,
+      0x00, 0x0a,
+      0x01, 0x00, 0x00, 0x37, 0xff, 0x01, 0x00, 0x01, 0x00, 0x00, 0x17, 0x00,
+      0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x14, 0x00, 0x12, 0x04,
+      0x03, 0x08, 0x04, 0x04, 0x01, 0x05, 0x03, 0x08, 0x05, 0x05, 0x01, 0x08,
+      0x06, 0x06, 0x01, 0x02, 0x01, 0x00, 0x0b, 0x00, 0x02, 0x01, 0x00, 0x00,
+      0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x1d, 0x00, 0x17, 0x00, 0x18,
+  };
+  if (!ClientHelloMatches(TLS1_2_VERSION, kTLS12ClientHello,
+                          sizeof(kTLS12ClientHello))) {
+    return false;
+  }
+
+  // TODO(davidben): Add a change detector for TLS 1.3 once the spec and our
+  // implementation has settled enough that it won't change.
+
+  return true;
+}
+
+static bssl::UniquePtr<SSL_SESSION> g_last_session;
+
+static int SaveLastSession(SSL *ssl, SSL_SESSION *session) {
+  // Save the most recent session.
+  g_last_session.reset(session);
+  return 1;
+}
+
+static bssl::UniquePtr<SSL_SESSION> CreateClientSession(SSL_CTX *client_ctx,
+                                             SSL_CTX *server_ctx) {
+  g_last_session = nullptr;
+  SSL_CTX_sess_set_new_cb(client_ctx, SaveLastSession);
+
+  // Connect client and server to get a session.
+  bssl::UniquePtr<SSL> client, server;
+  if (!ConnectClientAndServer(&client, &server, client_ctx, server_ctx,
+                              nullptr /* no session */)) {
+    fprintf(stderr, "Failed to connect client and server.\n");
+    return nullptr;
+  }
+
+  // Run the read loop to account for post-handshake tickets in TLS 1.3.
+  SSL_read(client.get(), nullptr, 0);
+
+  SSL_CTX_sess_set_new_cb(client_ctx, nullptr);
+
+  if (!g_last_session) {
+    fprintf(stderr, "Client did not receive a session.\n");
+    return nullptr;
+  }
+  return std::move(g_last_session);
+}
+
+static bool ExpectSessionReused(SSL_CTX *client_ctx, SSL_CTX *server_ctx,
+                                SSL_SESSION *session,
+                                bool reused) {
+  bssl::UniquePtr<SSL> client, server;
+  if (!ConnectClientAndServer(&client, &server, client_ctx,
+                              server_ctx, session)) {
+    fprintf(stderr, "Failed to connect client and server.\n");
+    return false;
+  }
+
+  if (SSL_session_reused(client.get()) != SSL_session_reused(server.get())) {
+    fprintf(stderr, "Client and server were inconsistent.\n");
+    return false;
+  }
+
+  bool was_reused = !!SSL_session_reused(client.get());
+  if (was_reused != reused) {
+    fprintf(stderr, "Session was%s reused, but we expected the opposite.\n",
+            was_reused ? "" : " not");
+    return false;
+  }
+
+  return true;
+}
+
+static bssl::UniquePtr<SSL_SESSION> ExpectSessionRenewed(SSL_CTX *client_ctx,
+                                                         SSL_CTX *server_ctx,
+                                                         SSL_SESSION *session) {
+  g_last_session = nullptr;
+  SSL_CTX_sess_set_new_cb(client_ctx, SaveLastSession);
+
+  bssl::UniquePtr<SSL> client, server;
+  if (!ConnectClientAndServer(&client, &server, client_ctx,
+                              server_ctx, session)) {
+    fprintf(stderr, "Failed to connect client and server.\n");
+    return nullptr;
+  }
+
+  if (SSL_session_reused(client.get()) != SSL_session_reused(server.get())) {
+    fprintf(stderr, "Client and server were inconsistent.\n");
+    return nullptr;
+  }
+
+  if (!SSL_session_reused(client.get())) {
+    fprintf(stderr, "Session was not reused.\n");
+    return nullptr;
+  }
+
+  // Run the read loop to account for post-handshake tickets in TLS 1.3.
+  SSL_read(client.get(), nullptr, 0);
+
+  SSL_CTX_sess_set_new_cb(client_ctx, nullptr);
+
+  if (!g_last_session) {
+    fprintf(stderr, "Client did not receive a renewed session.\n");
+    return nullptr;
+  }
+  return std::move(g_last_session);
+}
+
+static int SwitchSessionIDContextSNI(SSL *ssl, int *out_alert, void *arg) {
+  static const uint8_t kContext[] = {3};
+
+  if (!SSL_set_session_id_context(ssl, kContext, sizeof(kContext))) {
+    return SSL_TLSEXT_ERR_ALERT_FATAL;
+  }
+
+  return SSL_TLSEXT_ERR_OK;
+}
+
+static bool TestSessionIDContext(bool is_dtls, const SSL_METHOD *method,
+                                 uint16_t version) {
+  bssl::UniquePtr<X509> cert = GetTestCertificate();
+  bssl::UniquePtr<EVP_PKEY> key = GetTestKey();
+  if (!cert || !key) {
+    return false;
+  }
+
+  static const uint8_t kContext1[] = {1};
+  static const uint8_t kContext2[] = {2};
+
+  bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(method));
+  bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(method));
+  if (!server_ctx || !client_ctx ||
+      !SSL_CTX_use_certificate(server_ctx.get(), cert.get()) ||
+      !SSL_CTX_use_PrivateKey(server_ctx.get(), key.get()) ||
+      !SSL_CTX_set_session_id_context(server_ctx.get(), kContext1,
+                                      sizeof(kContext1)) ||
+      !SSL_CTX_set_min_proto_version(client_ctx.get(), version) ||
+      !SSL_CTX_set_max_proto_version(client_ctx.get(), version) ||
+      !SSL_CTX_set_min_proto_version(server_ctx.get(), version) ||
+      !SSL_CTX_set_max_proto_version(server_ctx.get(), version)) {
+    return false;
+  }
+
+  SSL_CTX_set_session_cache_mode(client_ctx.get(), SSL_SESS_CACHE_BOTH);
+  SSL_CTX_set_session_cache_mode(server_ctx.get(), SSL_SESS_CACHE_BOTH);
+
+  bssl::UniquePtr<SSL_SESSION> session =
+      CreateClientSession(client_ctx.get(), server_ctx.get());
+  if (!session) {
+    fprintf(stderr, "Error getting session.\n");
+    return false;
+  }
+
+  if (!ExpectSessionReused(client_ctx.get(), server_ctx.get(), session.get(),
+                           true /* expect session reused */)) {
+    fprintf(stderr, "Error resuming session.\n");
+    return false;
+  }
+
+  // Change the session ID context.
+  if (!SSL_CTX_set_session_id_context(server_ctx.get(), kContext2,
+                                      sizeof(kContext2))) {
+    return false;
+  }
+
+  if (!ExpectSessionReused(client_ctx.get(), server_ctx.get(), session.get(),
+                           false /* expect session not reused */)) {
+    fprintf(stderr, "Error connecting with a different context.\n");
+    return false;
+  }
+
+  // Change the session ID context back and install an SNI callback to switch
+  // it.
+  if (!SSL_CTX_set_session_id_context(server_ctx.get(), kContext1,
+                                      sizeof(kContext1))) {
+    return false;
+  }
+
+  SSL_CTX_set_tlsext_servername_callback(server_ctx.get(),
+                                         SwitchSessionIDContextSNI);
+
+  if (!ExpectSessionReused(client_ctx.get(), server_ctx.get(), session.get(),
+                           false /* expect session not reused */)) {
+    fprintf(stderr, "Error connecting with a context switch on SNI callback.\n");
+    return false;
+  }
+
+  // Switch the session ID context with the early callback instead.
+  SSL_CTX_set_tlsext_servername_callback(server_ctx.get(), nullptr);
+  SSL_CTX_set_select_certificate_cb(
+      server_ctx.get(),
+      [](const SSL_CLIENT_HELLO *client_hello) -> ssl_select_cert_result_t {
+        static const uint8_t kContext[] = {3};
+
+        if (!SSL_set_session_id_context(client_hello->ssl, kContext,
+                                        sizeof(kContext))) {
+          return ssl_select_cert_error;
+        }
+
+        return ssl_select_cert_success;
+      });
+
+  if (!ExpectSessionReused(client_ctx.get(), server_ctx.get(), session.get(),
+                           false /* expect session not reused */)) {
+    fprintf(stderr,
+            "Error connecting with a context switch on early callback.\n");
+    return false;
+  }
+
+  return true;
+}
+
+static timeval g_current_time;
+
+static void CurrentTimeCallback(const SSL *ssl, timeval *out_clock) {
+  *out_clock = g_current_time;
+}
+
+static void FrozenTimeCallback(const SSL *ssl, timeval *out_clock) {
+  out_clock->tv_sec = 1000;
+  out_clock->tv_usec = 0;
+}
+
+static int RenewTicketCallback(SSL *ssl, uint8_t *key_name, uint8_t *iv,
+                               EVP_CIPHER_CTX *ctx, HMAC_CTX *hmac_ctx,
+                               int encrypt) {
+  static const uint8_t kZeros[16] = {0};
+
+  if (encrypt) {
+    OPENSSL_memcpy(key_name, kZeros, sizeof(kZeros));
+    RAND_bytes(iv, 16);
+  } else if (OPENSSL_memcmp(key_name, kZeros, 16) != 0) {
+    return 0;
+  }
+
+  if (!HMAC_Init_ex(hmac_ctx, kZeros, sizeof(kZeros), EVP_sha256(), NULL) ||
+      !EVP_CipherInit_ex(ctx, EVP_aes_128_cbc(), NULL, kZeros, iv, encrypt)) {
+    return -1;
+  }
+
+  // Returning two from the callback in decrypt mode renews the
+  // session in TLS 1.2 and below.
+  return encrypt ? 1 : 2;
+}
+
+static bool GetServerTicketTime(long *out, const SSL_SESSION *session) {
+  if (session->tlsext_ticklen < 16 + 16 + SHA256_DIGEST_LENGTH) {
+    return false;
+  }
+
+  const uint8_t *ciphertext = session->tlsext_tick + 16 + 16;
+  size_t len = session->tlsext_ticklen - 16 - 16 - SHA256_DIGEST_LENGTH;
+  std::unique_ptr<uint8_t[]> plaintext(new uint8_t[len]);
+
+#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
+  // Fuzzer-mode tickets are unencrypted.
+  OPENSSL_memcpy(plaintext.get(), ciphertext, len);
+#else
+  static const uint8_t kZeros[16] = {0};
+  const uint8_t *iv = session->tlsext_tick + 16;
+  bssl::ScopedEVP_CIPHER_CTX ctx;
+  int len1, len2;
+  if (!EVP_DecryptInit_ex(ctx.get(), EVP_aes_128_cbc(), nullptr, kZeros, iv) ||
+      !EVP_DecryptUpdate(ctx.get(), plaintext.get(), &len1, ciphertext, len) ||
+      !EVP_DecryptFinal_ex(ctx.get(), plaintext.get() + len1, &len2)) {
+    return false;
+  }
+
+  len = static_cast<size_t>(len1 + len2);
+#endif
+
+  bssl::UniquePtr<SSL_CTX> ssl_ctx(SSL_CTX_new(TLS_method()));
+  if (!ssl_ctx) {
+    return false;
+  }
+  bssl::UniquePtr<SSL_SESSION> server_session(
+      SSL_SESSION_from_bytes(plaintext.get(), len, ssl_ctx.get()));
+  if (!server_session) {
+    return false;
+  }
+
+  *out = server_session->time;
+  return true;
+}
+
+static bool TestSessionTimeout(bool is_dtls, const SSL_METHOD *method,
+                               uint16_t version) {
+  bssl::UniquePtr<X509> cert = GetTestCertificate();
+  bssl::UniquePtr<EVP_PKEY> key = GetTestKey();
+  if (!cert || !key) {
+    return false;
+  }
+
+  for (bool server_test : std::vector<bool>{false, true}) {
+    static const time_t kStartTime = 1000;
+    g_current_time.tv_sec = kStartTime;
+
+    // We are willing to use a longer lifetime for TLS 1.3 sessions as
+    // resumptions still perform ECDHE.
+    const time_t timeout = version == TLS1_3_VERSION
+                               ? SSL_DEFAULT_SESSION_PSK_DHE_TIMEOUT
+                               : SSL_DEFAULT_SESSION_TIMEOUT;
+
+    bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(method));
+    bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(method));
+    if (!server_ctx || !client_ctx ||
+        !SSL_CTX_use_certificate(server_ctx.get(), cert.get()) ||
+        !SSL_CTX_use_PrivateKey(server_ctx.get(), key.get()) ||
+        !SSL_CTX_set_min_proto_version(client_ctx.get(), version) ||
+        !SSL_CTX_set_max_proto_version(client_ctx.get(), version) ||
+        !SSL_CTX_set_min_proto_version(server_ctx.get(), version) ||
+        !SSL_CTX_set_max_proto_version(server_ctx.get(), version)) {
+      return false;
+    }
+
+    SSL_CTX_set_session_cache_mode(client_ctx.get(), SSL_SESS_CACHE_BOTH);
+    SSL_CTX_set_session_cache_mode(server_ctx.get(), SSL_SESS_CACHE_BOTH);
+
+    // Both client and server must enforce session timeouts. We configure the
+    // other side with a frozen clock so it never expires tickets.
+    if (server_test) {
+      SSL_CTX_set_current_time_cb(client_ctx.get(), FrozenTimeCallback);
+      SSL_CTX_set_current_time_cb(server_ctx.get(), CurrentTimeCallback);
+    } else {
+      SSL_CTX_set_current_time_cb(client_ctx.get(), CurrentTimeCallback);
+      SSL_CTX_set_current_time_cb(server_ctx.get(), FrozenTimeCallback);
+    }
+
+    // Configure a ticket callback which renews tickets.
+    SSL_CTX_set_tlsext_ticket_key_cb(server_ctx.get(), RenewTicketCallback);
+
+    bssl::UniquePtr<SSL_SESSION> session =
+        CreateClientSession(client_ctx.get(), server_ctx.get());
+    if (!session) {
+      fprintf(stderr, "Error getting session.\n");
+      return false;
+    }
+
+    // Advance the clock just behind the timeout.
+    g_current_time.tv_sec += timeout - 1;
+
+    if (!ExpectSessionReused(client_ctx.get(), server_ctx.get(), session.get(),
+                             true /* expect session reused */)) {
+      fprintf(stderr, "Error resuming session.\n");
+      return false;
+    }
+
+    // Advance the clock one more second.
+    g_current_time.tv_sec++;
+
+    if (!ExpectSessionReused(client_ctx.get(), server_ctx.get(), session.get(),
+                             false /* expect session not reused */)) {
+      fprintf(stderr, "Error resuming session.\n");
+      return false;
+    }
+
+    // Rewind the clock to before the session was minted.
+    g_current_time.tv_sec = kStartTime - 1;
+
+    if (!ExpectSessionReused(client_ctx.get(), server_ctx.get(), session.get(),
+                             false /* expect session not reused */)) {
+      fprintf(stderr, "Error resuming session.\n");
+      return false;
+    }
+
+    // SSL 3.0 cannot renew sessions.
+    if (version == SSL3_VERSION) {
+      continue;
+    }
+
+    // Renew the session 10 seconds before expiration.
+    time_t new_start_time = kStartTime + timeout - 10;
+    g_current_time.tv_sec = new_start_time;
+    bssl::UniquePtr<SSL_SESSION> new_session =
+        ExpectSessionRenewed(client_ctx.get(), server_ctx.get(), session.get());
+    if (!new_session) {
+      fprintf(stderr, "Error renewing session.\n");
+      return false;
+    }
+
+    // This new session is not the same object as before.
+    if (session.get() == new_session.get()) {
+      fprintf(stderr, "New and old sessions alias.\n");
+      return false;
+    }
+
+    // Check the sessions have timestamps measured from issuance.
+    long session_time = 0;
+    if (server_test) {
+      if (!GetServerTicketTime(&session_time, new_session.get())) {
+        fprintf(stderr, "Failed to decode session ticket.\n");
+        return false;
+      }
+    } else {
+      session_time = new_session->time;
+    }
+
+    if (session_time != g_current_time.tv_sec) {
+      fprintf(stderr, "New session is not measured from issuance.\n");
+      return false;
+    }
+
+    if (version == TLS1_3_VERSION) {
+      // Renewal incorporates fresh key material in TLS 1.3, so we extend the
+      // lifetime TLS 1.3.
+      g_current_time.tv_sec = new_start_time + timeout - 1;
+      if (!ExpectSessionReused(client_ctx.get(), server_ctx.get(),
+                               new_session.get(),
+                               true /* expect session reused */)) {
+        fprintf(stderr, "Error resuming renewed session.\n");
+        return false;
+      }
+
+      // The new session expires after the new timeout.
+      g_current_time.tv_sec = new_start_time + timeout + 1;
+      if (!ExpectSessionReused(client_ctx.get(), server_ctx.get(),
+                               new_session.get(),
+                               false /* expect session ot reused */)) {
+        fprintf(stderr, "Renewed session's lifetime is too long.\n");
+        return false;
+      }
+
+      // Renew the session until it begins just past the auth timeout.
+      time_t auth_end_time = kStartTime + SSL_DEFAULT_SESSION_AUTH_TIMEOUT;
+      while (new_start_time < auth_end_time - 1000) {
+        // Get as close as possible to target start time.
+        new_start_time =
+            std::min(auth_end_time - 1000, new_start_time + timeout - 1);
+        g_current_time.tv_sec = new_start_time;
+        new_session = ExpectSessionRenewed(client_ctx.get(), server_ctx.get(),
+                                           new_session.get());
+        if (!new_session) {
+          fprintf(stderr, "Error renewing session.\n");
+          return false;
+        }
+      }
+
+      // Now the session's lifetime is bound by the auth timeout.
+      g_current_time.tv_sec = auth_end_time - 1;
+      if (!ExpectSessionReused(client_ctx.get(), server_ctx.get(),
+                               new_session.get(),
+                               true /* expect session reused */)) {
+        fprintf(stderr, "Error resuming renewed session.\n");
+        return false;
+      }
+
+      g_current_time.tv_sec = auth_end_time + 1;
+      if (!ExpectSessionReused(client_ctx.get(), server_ctx.get(),
+                               new_session.get(),
+                               false /* expect session ot reused */)) {
+        fprintf(stderr, "Renewed session's lifetime is too long.\n");
+        return false;
+      }
+    } else {
+      // The new session is usable just before the old expiration.
+      g_current_time.tv_sec = kStartTime + timeout - 1;
+      if (!ExpectSessionReused(client_ctx.get(), server_ctx.get(),
+                               new_session.get(),
+                               true /* expect session reused */)) {
+        fprintf(stderr, "Error resuming renewed session.\n");
+        return false;
+      }
+
+      // Renewal does not extend the lifetime, so it is not usable beyond the
+      // old expiration.
+      g_current_time.tv_sec = kStartTime + timeout + 1;
+      if (!ExpectSessionReused(client_ctx.get(), server_ctx.get(),
+                               new_session.get(),
+                               false /* expect session not reused */)) {
+        fprintf(stderr, "Renewed session's lifetime is too long.\n");
+        return false;
+      }
+    }
+  }
+
+  return true;
+}
+
+static int SwitchContext(SSL *ssl, int *out_alert, void *arg) {
+  SSL_CTX *ctx = reinterpret_cast<SSL_CTX*>(arg);
+  SSL_set_SSL_CTX(ssl, ctx);
+  return SSL_TLSEXT_ERR_OK;
+}
+
+static bool TestSNICallback(bool is_dtls, const SSL_METHOD *method,
+                            uint16_t version) {
+  // SSL 3.0 lacks extensions.
+  if (version == SSL3_VERSION) {
+    return true;
+  }
+
+  bssl::UniquePtr<X509> cert = GetTestCertificate();
+  bssl::UniquePtr<EVP_PKEY> key = GetTestKey();
+  bssl::UniquePtr<X509> cert2 = GetECDSATestCertificate();
+  bssl::UniquePtr<EVP_PKEY> key2 = GetECDSATestKey();
+  if (!cert || !key || !cert2 || !key2) {
+    return false;
+  }
+
+  // Test that switching the |SSL_CTX| at the SNI callback behaves correctly.
+  static const uint16_t kECDSAWithSHA256 = SSL_SIGN_ECDSA_SECP256R1_SHA256;
+
+  static const uint8_t kSCTList[] = {0, 6, 0, 4, 5, 6, 7, 8};
+  static const uint8_t kOCSPResponse[] = {1, 2, 3, 4};
+
+  bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(method));
+  bssl::UniquePtr<SSL_CTX> server_ctx2(SSL_CTX_new(method));
+  bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(method));
+  if (!server_ctx || !server_ctx2 || !client_ctx ||
+      !SSL_CTX_use_certificate(server_ctx.get(), cert.get()) ||
+      !SSL_CTX_use_PrivateKey(server_ctx.get(), key.get()) ||
+      !SSL_CTX_use_certificate(server_ctx2.get(), cert2.get()) ||
+      !SSL_CTX_use_PrivateKey(server_ctx2.get(), key2.get()) ||
+      !SSL_CTX_set_signed_cert_timestamp_list(server_ctx2.get(), kSCTList,
+                                              sizeof(kSCTList)) ||
+      !SSL_CTX_set_ocsp_response(server_ctx2.get(), kOCSPResponse,
+                                 sizeof(kOCSPResponse)) ||
+      // Historically signing preferences would be lost in some cases with the
+      // SNI callback, which triggers the TLS 1.2 SHA-1 default. To ensure
+      // this doesn't happen when |version| is TLS 1.2, configure the private
+      // key to only sign SHA-256.
+      !SSL_CTX_set_signing_algorithm_prefs(server_ctx2.get(), &kECDSAWithSHA256,
+                                           1) ||
+      !SSL_CTX_set_min_proto_version(client_ctx.get(), version) ||
+      !SSL_CTX_set_max_proto_version(client_ctx.get(), version) ||
+      !SSL_CTX_set_min_proto_version(server_ctx.get(), version) ||
+      !SSL_CTX_set_max_proto_version(server_ctx.get(), version) ||
+      !SSL_CTX_set_min_proto_version(server_ctx2.get(), version) ||
+      !SSL_CTX_set_max_proto_version(server_ctx2.get(), version)) {
+    return false;
+  }
+
+  SSL_CTX_set_tlsext_servername_callback(server_ctx.get(), SwitchContext);
+  SSL_CTX_set_tlsext_servername_arg(server_ctx.get(), server_ctx2.get());
+
+  SSL_CTX_enable_signed_cert_timestamps(client_ctx.get());
+  SSL_CTX_enable_ocsp_stapling(client_ctx.get());
+
+  bssl::UniquePtr<SSL> client, server;
+  if (!ConnectClientAndServer(&client, &server, client_ctx.get(),
+                              server_ctx.get(), nullptr)) {
+    fprintf(stderr, "Handshake failed.\n");
+    return false;
+  }
+
+  // The client should have received |cert2|.
+  bssl::UniquePtr<X509> peer(SSL_get_peer_certificate(client.get()));
+  if (!peer || X509_cmp(peer.get(), cert2.get()) != 0) {
+    fprintf(stderr, "Incorrect certificate received.\n");
+    return false;
+  }
+
+  // The client should have received |server_ctx2|'s SCT list.
+  const uint8_t *data;
+  size_t len;
+  SSL_get0_signed_cert_timestamp_list(client.get(), &data, &len);
+  if (Bytes(kSCTList) != Bytes(data, len)) {
+    fprintf(stderr, "Incorrect SCT list received.\n");
+    return false;
+  }
+
+  // The client should have received |server_ctx2|'s OCSP response.
+  SSL_get0_ocsp_response(client.get(), &data, &len);
+  if (Bytes(kOCSPResponse) != Bytes(data, len)) {
+    fprintf(stderr, "Incorrect OCSP response received.\n");
+    return false;
+  }
+
+  return true;
+}
+
+// Test that the early callback can swap the maximum version.
+TEST(SSLTest, EarlyCallbackVersionSwitch) {
+  bssl::UniquePtr<X509> cert = GetTestCertificate();
+  bssl::UniquePtr<EVP_PKEY> key = GetTestKey();
+  bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(TLS_method()));
+  bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(TLS_method()));
+  ASSERT_TRUE(cert);
+  ASSERT_TRUE(key);
+  ASSERT_TRUE(server_ctx);
+  ASSERT_TRUE(client_ctx);
+  ASSERT_TRUE(SSL_CTX_use_certificate(server_ctx.get(), cert.get()));
+  ASSERT_TRUE(SSL_CTX_use_PrivateKey(server_ctx.get(), key.get()));
+  ASSERT_TRUE(SSL_CTX_set_max_proto_version(client_ctx.get(), TLS1_3_VERSION));
+  ASSERT_TRUE(SSL_CTX_set_max_proto_version(server_ctx.get(), TLS1_3_VERSION));
+
+  SSL_CTX_set_select_certificate_cb(
+      server_ctx.get(),
+      [](const SSL_CLIENT_HELLO *client_hello) -> ssl_select_cert_result_t {
+        if (!SSL_set_max_proto_version(client_hello->ssl, TLS1_2_VERSION)) {
+          return ssl_select_cert_error;
+        }
+
+        return ssl_select_cert_success;
+      });
+
+  bssl::UniquePtr<SSL> client, server;
+  ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
+                                     server_ctx.get(), nullptr));
+  EXPECT_EQ(TLS1_2_VERSION, SSL_version(client.get()));
+}
+
+TEST(SSLTest, SetVersion) {
+  bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
+  ASSERT_TRUE(ctx);
+
+  // Set valid TLS versions.
+  EXPECT_TRUE(SSL_CTX_set_max_proto_version(ctx.get(), TLS1_VERSION));
+  EXPECT_TRUE(SSL_CTX_set_max_proto_version(ctx.get(), TLS1_1_VERSION));
+  EXPECT_TRUE(SSL_CTX_set_min_proto_version(ctx.get(), TLS1_VERSION));
+  EXPECT_TRUE(SSL_CTX_set_min_proto_version(ctx.get(), TLS1_1_VERSION));
+
+  // Invalid TLS versions are rejected.
+  EXPECT_FALSE(SSL_CTX_set_max_proto_version(ctx.get(), DTLS1_VERSION));
+  EXPECT_FALSE(SSL_CTX_set_max_proto_version(ctx.get(), 0x0200));
+  EXPECT_FALSE(SSL_CTX_set_max_proto_version(ctx.get(), 0x1234));
+  EXPECT_FALSE(SSL_CTX_set_min_proto_version(ctx.get(), DTLS1_VERSION));
+  EXPECT_FALSE(SSL_CTX_set_min_proto_version(ctx.get(), 0x0200));
+  EXPECT_FALSE(SSL_CTX_set_min_proto_version(ctx.get(), 0x1234));
+
+  // Zero is the default version.
+  EXPECT_TRUE(SSL_CTX_set_max_proto_version(ctx.get(), 0));
+  EXPECT_EQ(TLS1_2_VERSION, ctx->max_version);
+  EXPECT_TRUE(SSL_CTX_set_min_proto_version(ctx.get(), 0));
+  EXPECT_EQ(SSL3_VERSION, ctx->min_version);
+
+  ctx.reset(SSL_CTX_new(DTLS_method()));
+  ASSERT_TRUE(ctx);
+
+  EXPECT_TRUE(SSL_CTX_set_max_proto_version(ctx.get(), DTLS1_VERSION));
+  EXPECT_TRUE(SSL_CTX_set_max_proto_version(ctx.get(), DTLS1_2_VERSION));
+  EXPECT_TRUE(SSL_CTX_set_min_proto_version(ctx.get(), DTLS1_VERSION));
+  EXPECT_TRUE(SSL_CTX_set_min_proto_version(ctx.get(), DTLS1_2_VERSION));
+
+  EXPECT_FALSE(SSL_CTX_set_max_proto_version(ctx.get(), TLS1_VERSION));
+  EXPECT_FALSE(SSL_CTX_set_max_proto_version(ctx.get(), 0xfefe /* DTLS 1.1 */));
+  EXPECT_FALSE(SSL_CTX_set_max_proto_version(ctx.get(), 0xfffe /* DTLS 0.1 */));
+  EXPECT_FALSE(SSL_CTX_set_max_proto_version(ctx.get(), 0x1234));
+  EXPECT_FALSE(SSL_CTX_set_min_proto_version(ctx.get(), TLS1_VERSION));
+  EXPECT_FALSE(SSL_CTX_set_min_proto_version(ctx.get(), 0xfefe /* DTLS 1.1 */));
+  EXPECT_FALSE(SSL_CTX_set_min_proto_version(ctx.get(), 0xfffe /* DTLS 0.1 */));
+  EXPECT_FALSE(SSL_CTX_set_min_proto_version(ctx.get(), 0x1234));
+
+  EXPECT_TRUE(SSL_CTX_set_max_proto_version(ctx.get(), 0));
+  EXPECT_EQ(TLS1_2_VERSION, ctx->max_version);
+  EXPECT_TRUE(SSL_CTX_set_min_proto_version(ctx.get(), 0));
+  EXPECT_EQ(TLS1_1_VERSION, ctx->min_version);
+}
+
+static const char *GetVersionName(uint16_t version) {
+  switch (version) {
+    case SSL3_VERSION:
+      return "SSLv3";
+    case TLS1_VERSION:
+      return "TLSv1";
+    case TLS1_1_VERSION:
+      return "TLSv1.1";
+    case TLS1_2_VERSION:
+      return "TLSv1.2";
+    case TLS1_3_VERSION:
+      return "TLSv1.3";
+    case DTLS1_VERSION:
+      return "DTLSv1";
+    case DTLS1_2_VERSION:
+      return "DTLSv1.2";
+    default:
+      return "???";
+  }
+}
+
+static bool TestVersion(bool is_dtls, const SSL_METHOD *method,
+                        uint16_t version) {
+  bssl::UniquePtr<X509> cert = GetTestCertificate();
+  bssl::UniquePtr<EVP_PKEY> key = GetTestKey();
+  if (!cert || !key) {
+    return false;
+  }
+
+  bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(method));
+  bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(method));
+  bssl::UniquePtr<SSL> client, server;
+  if (!server_ctx || !client_ctx ||
+      !SSL_CTX_use_certificate(server_ctx.get(), cert.get()) ||
+      !SSL_CTX_use_PrivateKey(server_ctx.get(), key.get()) ||
+      !SSL_CTX_set_min_proto_version(client_ctx.get(), version) ||
+      !SSL_CTX_set_max_proto_version(client_ctx.get(), version) ||
+      !SSL_CTX_set_min_proto_version(server_ctx.get(), version) ||
+      !SSL_CTX_set_max_proto_version(server_ctx.get(), version) ||
+      !ConnectClientAndServer(&client, &server, client_ctx.get(),
+                              server_ctx.get(), nullptr /* no session */)) {
+    fprintf(stderr, "Failed to connect.\n");
+    return false;
+  }
+
+  if (SSL_version(client.get()) != version ||
+      SSL_version(server.get()) != version) {
+    fprintf(stderr, "Version mismatch. Got %04x and %04x, wanted %04x.\n",
+            SSL_version(client.get()), SSL_version(server.get()), version);
+    return false;
+  }
+
+  // Test the version name is reported as expected.
+  const char *version_name = GetVersionName(version);
+  if (strcmp(version_name, SSL_get_version(client.get())) != 0 ||
+      strcmp(version_name, SSL_get_version(server.get())) != 0) {
+    fprintf(stderr, "Version name mismatch. Got '%s' and '%s', wanted '%s'.\n",
+            SSL_get_version(client.get()), SSL_get_version(server.get()),
+            version_name);
+    return false;
+  }
+
+  // Test SSL_SESSION reports the same name.
+  const char *client_name =
+      SSL_SESSION_get_version(SSL_get_session(client.get()));
+  const char *server_name =
+      SSL_SESSION_get_version(SSL_get_session(server.get()));
+  if (strcmp(version_name, client_name) != 0 ||
+      strcmp(version_name, server_name) != 0) {
+    fprintf(stderr,
+            "Session version name mismatch. Got '%s' and '%s', wanted '%s'.\n",
+            client_name, server_name, version_name);
+    return false;
+  }
+
+  return true;
+}
+
+// Tests that that |SSL_get_pending_cipher| is available during the ALPN
+// selection callback.
+static bool TestALPNCipherAvailable(bool is_dtls, const SSL_METHOD *method,
+                                    uint16_t version) {
+  // SSL 3.0 lacks extensions.
+  if (version == SSL3_VERSION) {
+    return true;
+  }
+
+  static const uint8_t kALPNProtos[] = {0x03, 'f', 'o', 'o'};
+
+  bssl::UniquePtr<X509> cert = GetTestCertificate();
+  bssl::UniquePtr<EVP_PKEY> key = GetTestKey();
+  if (!cert || !key) {
+    return false;
+  }
+
+  bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(method));
+  if (!ctx || !SSL_CTX_use_certificate(ctx.get(), cert.get()) ||
+      !SSL_CTX_use_PrivateKey(ctx.get(), key.get()) ||
+      !SSL_CTX_set_min_proto_version(ctx.get(), version) ||
+      !SSL_CTX_set_max_proto_version(ctx.get(), version) ||
+      SSL_CTX_set_alpn_protos(ctx.get(), kALPNProtos, sizeof(kALPNProtos)) !=
+          0) {
+    return false;
+  }
+
+  // The ALPN callback does not fail the handshake on error, so have the
+  // callback write a boolean.
+  std::pair<uint16_t, bool> callback_state(version, false);
+  SSL_CTX_set_alpn_select_cb(
+      ctx.get(),
+      [](SSL *ssl, const uint8_t **out, uint8_t *out_len, const uint8_t *in,
+         unsigned in_len, void *arg) -> int {
+        auto state = reinterpret_cast<std::pair<uint16_t, bool> *>(arg);
+        if (SSL_get_pending_cipher(ssl) != nullptr &&
+            SSL_version(ssl) == state->first) {
+          state->second = true;
+        }
+        return SSL_TLSEXT_ERR_NOACK;
+      },
+      &callback_state);
+
+  bssl::UniquePtr<SSL> client, server;
+  if (!ConnectClientAndServer(&client, &server, ctx.get(), ctx.get(),
+                              nullptr /* no session */)) {
+    return false;
+  }
+
+  if (!callback_state.second) {
+    fprintf(stderr, "The pending cipher was not known in the ALPN callback.\n");
+    return false;
+  }
+
+  return true;
+}
+
+static bool TestSSLClearSessionResumption(bool is_dtls,
+                                          const SSL_METHOD *method,
+                                          uint16_t version) {
+  // Skip this for TLS 1.3. TLS 1.3's ticket mechanism is incompatible with this
+  // API pattern.
+  if (version == TLS1_3_VERSION) {
+    return true;
+  }
+
+  bssl::UniquePtr<X509> cert = GetTestCertificate();
+  bssl::UniquePtr<EVP_PKEY> key = GetTestKey();
+  bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(method));
+  bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(method));
+  if (!cert || !key || !server_ctx || !client_ctx ||
+      !SSL_CTX_use_certificate(server_ctx.get(), cert.get()) ||
+      !SSL_CTX_use_PrivateKey(server_ctx.get(), key.get()) ||
+      !SSL_CTX_set_min_proto_version(client_ctx.get(), version) ||
+      !SSL_CTX_set_max_proto_version(client_ctx.get(), version) ||
+      !SSL_CTX_set_min_proto_version(server_ctx.get(), version) ||
+      !SSL_CTX_set_max_proto_version(server_ctx.get(), version)) {
+    return false;
+  }
+
+  // Connect a client and a server.
+  bssl::UniquePtr<SSL> client, server;
+  if (!ConnectClientAndServer(&client, &server, client_ctx.get(),
+                              server_ctx.get(), nullptr /* no session */)) {
+    return false;
+  }
+
+  if (SSL_session_reused(client.get()) ||
+      SSL_session_reused(server.get())) {
+    fprintf(stderr, "Session unexpectedly reused.\n");
+    return false;
+  }
+
+  // Reset everything.
+  if (!SSL_clear(client.get()) ||
+      !SSL_clear(server.get())) {
+    fprintf(stderr, "SSL_clear failed.\n");
+    return false;
+  }
+
+  // Attempt to connect a second time.
+  if (!CompleteHandshakes(client.get(), server.get())) {
+    fprintf(stderr, "Could not reuse SSL objects.\n");
+    return false;
+  }
+
+  // |SSL_clear| should implicitly offer the previous session to the server.
+  if (!SSL_session_reused(client.get()) ||
+      !SSL_session_reused(server.get())) {
+    fprintf(stderr, "Session was not reused in second try.\n");
+    return false;
+  }
+
+  return true;
+}
+
+static bool ChainsEqual(STACK_OF(X509) *chain,
+                         const std::vector<X509 *> &expected) {
+  if (sk_X509_num(chain) != expected.size()) {
+    return false;
+  }
+
+  for (size_t i = 0; i < expected.size(); i++) {
+    if (X509_cmp(sk_X509_value(chain, i), expected[i]) != 0) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+static bool TestAutoChain(bool is_dtls, const SSL_METHOD *method,
+                          uint16_t version) {
+  bssl::UniquePtr<X509> cert = GetChainTestCertificate();
+  bssl::UniquePtr<X509> intermediate = GetChainTestIntermediate();
+  bssl::UniquePtr<EVP_PKEY> key = GetChainTestKey();
+  if (!cert || !intermediate || !key) {
+    return false;
+  }
+
+  // Configure both client and server to accept any certificate. Add
+  // |intermediate| to the cert store.
+  bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(method));
+  if (!ctx ||
+      !SSL_CTX_use_certificate(ctx.get(), cert.get()) ||
+      !SSL_CTX_use_PrivateKey(ctx.get(), key.get()) ||
+      !SSL_CTX_set_min_proto_version(ctx.get(), version) ||
+      !SSL_CTX_set_max_proto_version(ctx.get(), version) ||
+      !X509_STORE_add_cert(SSL_CTX_get_cert_store(ctx.get()),
+                           intermediate.get())) {
+    return false;
+  }
+  SSL_CTX_set_verify(
+      ctx.get(), SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr);
+  SSL_CTX_set_cert_verify_callback(ctx.get(), VerifySucceed, NULL);
+
+  // By default, the client and server should each only send the leaf.
+  bssl::UniquePtr<SSL> client, server;
+  if (!ConnectClientAndServer(&client, &server, ctx.get(), ctx.get(),
+                              nullptr /* no session */)) {
+    return false;
+  }
+
+  if (!ChainsEqual(SSL_get_peer_full_cert_chain(client.get()), {cert.get()})) {
+    fprintf(stderr, "Client-received chain did not match.\n");
+    return false;
+  }
+
+  if (!ChainsEqual(SSL_get_peer_full_cert_chain(server.get()), {cert.get()})) {
+    fprintf(stderr, "Server-received chain did not match.\n");
+    return false;
+  }
+
+  // If auto-chaining is enabled, then the intermediate is sent.
+  SSL_CTX_clear_mode(ctx.get(), SSL_MODE_NO_AUTO_CHAIN);
+  if (!ConnectClientAndServer(&client, &server, ctx.get(), ctx.get(),
+                              nullptr /* no session */)) {
+    return false;
+  }
+
+  if (!ChainsEqual(SSL_get_peer_full_cert_chain(client.get()),
+                   {cert.get(), intermediate.get()})) {
+    fprintf(stderr, "Client-received chain did not match (auto-chaining).\n");
+    return false;
+  }
+
+  if (!ChainsEqual(SSL_get_peer_full_cert_chain(server.get()),
+                   {cert.get(), intermediate.get()})) {
+    fprintf(stderr, "Server-received chain did not match (auto-chaining).\n");
+    return false;
+  }
+
+  // Auto-chaining does not override explicitly-configured intermediates.
+  if (!SSL_CTX_add1_chain_cert(ctx.get(), cert.get()) ||
+      !ConnectClientAndServer(&client, &server, ctx.get(), ctx.get(),
+                              nullptr /* no session */)) {
+    return false;
+  }
+
+  if (!ChainsEqual(SSL_get_peer_full_cert_chain(client.get()),
+                   {cert.get(), cert.get()})) {
+    fprintf(stderr,
+            "Client-received chain did not match (auto-chaining, explicit "
+            "intermediate).\n");
+    return false;
+  }
+
+  if (!ChainsEqual(SSL_get_peer_full_cert_chain(server.get()),
+                   {cert.get(), cert.get()})) {
+    fprintf(stderr,
+            "Server-received chain did not match (auto-chaining, explicit "
+            "intermediate).\n");
+    return false;
+  }
+
+  return true;
+}
+
+static bool ExpectBadWriteRetry() {
+  int err = ERR_get_error();
+  if (ERR_GET_LIB(err) != ERR_LIB_SSL ||
+      ERR_GET_REASON(err) != SSL_R_BAD_WRITE_RETRY) {
+    char buf[ERR_ERROR_STRING_BUF_LEN];
+    ERR_error_string_n(err, buf, sizeof(buf));
+    fprintf(stderr, "Wanted SSL_R_BAD_WRITE_RETRY, got: %s.\n", buf);
+    return false;
+  }
+
+  if (ERR_peek_error() != 0) {
+    fprintf(stderr, "Unexpected error following SSL_R_BAD_WRITE_RETRY.\n");
+    return false;
+  }
+
+  return true;
+}
+
+static bool TestSSLWriteRetry(bool is_dtls, const SSL_METHOD *method,
+                              uint16_t version) {
+  if (is_dtls) {
+    return true;
+  }
+
+  for (bool enable_partial_write : std::vector<bool>{false, true}) {
+    // Connect a client and server.
+    bssl::UniquePtr<X509> cert = GetTestCertificate();
+    bssl::UniquePtr<EVP_PKEY> key = GetTestKey();
+    bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(method));
+    bssl::UniquePtr<SSL> client, server;
+    if (!cert || !key || !ctx ||
+        !SSL_CTX_use_certificate(ctx.get(), cert.get()) ||
+        !SSL_CTX_use_PrivateKey(ctx.get(), key.get()) ||
+        !SSL_CTX_set_min_proto_version(ctx.get(), version) ||
+        !SSL_CTX_set_max_proto_version(ctx.get(), version) ||
+        !ConnectClientAndServer(&client, &server, ctx.get(), ctx.get(),
+                                nullptr /* no session */)) {
+      return false;
+    }
+
+    if (enable_partial_write) {
+      SSL_set_mode(client.get(), SSL_MODE_ENABLE_PARTIAL_WRITE);
+    }
+
+    // Write without reading until the buffer is full and we have an unfinished
+    // write. Keep a count so we may reread it again later. "hello!" will be
+    // written in two chunks, "hello" and "!".
+    char data[] = "hello!";
+    static const int kChunkLen = 5;  // The length of "hello".
+    unsigned count = 0;
+    for (;;) {
+      int ret = SSL_write(client.get(), data, kChunkLen);
+      if (ret <= 0) {
+        int err = SSL_get_error(client.get(), ret);
+        if (SSL_get_error(client.get(), ret) == SSL_ERROR_WANT_WRITE) {
+          break;
+        }
+        fprintf(stderr, "SSL_write failed in unexpected way: %d\n", err);
+        return false;
+      }
+
+      if (ret != 5) {
+        fprintf(stderr, "SSL_write wrote %d bytes, expected 5.\n", ret);
+        return false;
+      }
+
+      count++;
+    }
+
+    // Retrying with the same parameters is legal.
+    if (SSL_get_error(client.get(), SSL_write(client.get(), data, kChunkLen)) !=
+        SSL_ERROR_WANT_WRITE) {
+      fprintf(stderr, "SSL_write retry unexpectedly failed.\n");
+      return false;
+    }
+
+    // Retrying with the same buffer but shorter length is not legal.
+    if (SSL_get_error(client.get(),
+                      SSL_write(client.get(), data, kChunkLen - 1)) !=
+            SSL_ERROR_SSL ||
+        !ExpectBadWriteRetry()) {
+      fprintf(stderr, "SSL_write retry did not fail as expected.\n");
+      return false;
+    }
+
+    // Retrying with a different buffer pointer is not legal.
+    char data2[] = "hello";
+    if (SSL_get_error(client.get(), SSL_write(client.get(), data2,
+                                              kChunkLen)) != SSL_ERROR_SSL ||
+        !ExpectBadWriteRetry()) {
+      fprintf(stderr, "SSL_write retry did not fail as expected.\n");
+      return false;
+    }
+
+    // With |SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER|, the buffer may move.
+    SSL_set_mode(client.get(), SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
+    if (SSL_get_error(client.get(),
+                      SSL_write(client.get(), data2, kChunkLen)) !=
+        SSL_ERROR_WANT_WRITE) {
+      fprintf(stderr, "SSL_write retry unexpectedly failed.\n");
+      return false;
+    }
+
+    // |SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER| does not disable length checks.
+    if (SSL_get_error(client.get(),
+                      SSL_write(client.get(), data2, kChunkLen - 1)) !=
+            SSL_ERROR_SSL ||
+        !ExpectBadWriteRetry()) {
+      fprintf(stderr, "SSL_write retry did not fail as expected.\n");
+      return false;
+    }
+
+    // Retrying with a larger buffer is legal.
+    if (SSL_get_error(client.get(),
+                      SSL_write(client.get(), data, kChunkLen + 1)) !=
+        SSL_ERROR_WANT_WRITE) {
+      fprintf(stderr, "SSL_write retry unexpectedly failed.\n");
+      return false;
+    }
+
+    // Drain the buffer.
+    char buf[20];
+    for (unsigned i = 0; i < count; i++) {
+      if (SSL_read(server.get(), buf, sizeof(buf)) != kChunkLen ||
+          OPENSSL_memcmp(buf, "hello", kChunkLen) != 0) {
+        fprintf(stderr, "Failed to read initial records.\n");
+        return false;
+      }
+    }
+
+    // Now that there is space, a retry with a larger buffer should flush the
+    // pending record, skip over that many bytes of input (on assumption they
+    // are the same), and write the remainder. If SSL_MODE_ENABLE_PARTIAL_WRITE
+    // is set, this will complete in two steps.
+    char data3[] = "_____!";
+    if (enable_partial_write) {
+      if (SSL_write(client.get(), data3, kChunkLen + 1) != kChunkLen ||
+          SSL_write(client.get(), data3 + kChunkLen, 1) != 1) {
+        fprintf(stderr, "SSL_write retry failed.\n");
+        return false;
+      }
+    } else if (SSL_write(client.get(), data3, kChunkLen + 1) != kChunkLen + 1) {
+      fprintf(stderr, "SSL_write retry failed.\n");
+      return false;
+    }
+
+    // Check the last write was correct. The data will be spread over two
+    // records, so SSL_read returns twice.
+    if (SSL_read(server.get(), buf, sizeof(buf)) != kChunkLen ||
+        OPENSSL_memcmp(buf, "hello", kChunkLen) != 0 ||
+        SSL_read(server.get(), buf, sizeof(buf)) != 1 ||
+        buf[0] != '!') {
+      fprintf(stderr, "Failed to read write retry.\n");
+      return false;
+    }
+  }
+
+  return true;
+}
+
+static bool ForEachVersion(bool (*test_func)(bool is_dtls,
+                                             const SSL_METHOD *method,
+                                             uint16_t version)) {
+  static uint16_t kTLSVersions[] = {
+      SSL3_VERSION,
+      TLS1_VERSION,
+      TLS1_1_VERSION,
+      TLS1_2_VERSION,
+// TLS 1.3 requires RSA-PSS, which is disabled for Android system builds.
+#if !defined(BORINGSSL_ANDROID_SYSTEM)
+      TLS1_3_VERSION,
+#endif
+  };
+
+  static uint16_t kDTLSVersions[] = {
+      DTLS1_VERSION, DTLS1_2_VERSION,
+  };
+
+  for (uint16_t version : kTLSVersions) {
+    if (!test_func(false, TLS_method(), version)) {
+      fprintf(stderr, "Test failed at TLS version %04x.\n", version);
+      return false;
+    }
+  }
+
+  for (uint16_t version : kDTLSVersions) {
+    if (!test_func(true, DTLS_method(), version)) {
+      fprintf(stderr, "Test failed at DTLS version %04x.\n", version);
+      return false;
+    }
+  }
+
+  return true;
+}
+
+TEST(SSLTest, AddChainCertHack) {
+  // Ensure that we don't accidently break the hack that we have in place to
+  // keep curl and serf happy when they use an |X509| even after transfering
+  // ownership.
+
+  bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
+  ASSERT_TRUE(ctx);
+  X509 *cert = GetTestCertificate().release();
+  ASSERT_TRUE(cert);
+  SSL_CTX_add0_chain_cert(ctx.get(), cert);
+
+  // This should not trigger a use-after-free.
+  X509_cmp(cert, cert);
+}
+
+TEST(SSLTest, GetCertificate) {
+  bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
+  ASSERT_TRUE(ctx);
+  bssl::UniquePtr<X509> cert = GetTestCertificate();
+  ASSERT_TRUE(cert);
+  ASSERT_TRUE(SSL_CTX_use_certificate(ctx.get(), cert.get()));
+  bssl::UniquePtr<SSL> ssl(SSL_new(ctx.get()));
+  ASSERT_TRUE(ssl);
+
+  X509 *cert2 = SSL_CTX_get0_certificate(ctx.get());
+  ASSERT_TRUE(cert2);
+  X509 *cert3 = SSL_get_certificate(ssl.get());
+  ASSERT_TRUE(cert3);
+
+  // The old and new certificates must be identical.
+  EXPECT_EQ(0, X509_cmp(cert.get(), cert2));
+  EXPECT_EQ(0, X509_cmp(cert.get(), cert3));
+
+  uint8_t *der = nullptr;
+  long der_len = i2d_X509(cert.get(), &der);
+  ASSERT_LT(0, der_len);
+  bssl::UniquePtr<uint8_t> free_der(der);
+
+  uint8_t *der2 = nullptr;
+  long der2_len = i2d_X509(cert2, &der2);
+  ASSERT_LT(0, der2_len);
+  bssl::UniquePtr<uint8_t> free_der2(der2);
+
+  uint8_t *der3 = nullptr;
+  long der3_len = i2d_X509(cert3, &der3);
+  ASSERT_LT(0, der3_len);
+  bssl::UniquePtr<uint8_t> free_der3(der3);
+
+  // They must also encode identically.
+  EXPECT_EQ(Bytes(der, der_len), Bytes(der2, der2_len));
+  EXPECT_EQ(Bytes(der, der_len), Bytes(der3, der3_len));
+}
+
+TEST(SSLTest, SetChainAndKeyMismatch) {
+  bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_with_buffers_method()));
+  ASSERT_TRUE(ctx);
+
+  bssl::UniquePtr<EVP_PKEY> key = GetTestKey();
+  ASSERT_TRUE(key);
+  bssl::UniquePtr<CRYPTO_BUFFER> leaf = GetChainTestCertificateBuffer();
+  ASSERT_TRUE(leaf);
+  std::vector<CRYPTO_BUFFER*> chain = {
+      leaf.get(),
+  };
+
+  // Should fail because |GetTestKey| doesn't match the chain-test certificate.
+  ASSERT_FALSE(SSL_CTX_set_chain_and_key(ctx.get(), &chain[0], chain.size(),
+                                         key.get(), nullptr));
+  ERR_clear_error();
+}
+
+TEST(SSLTest, SetChainAndKey) {
+  bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(TLS_with_buffers_method()));
+  ASSERT_TRUE(client_ctx);
+  bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(TLS_with_buffers_method()));
+  ASSERT_TRUE(server_ctx);
+
+  bssl::UniquePtr<EVP_PKEY> key = GetChainTestKey();
+  ASSERT_TRUE(key);
+  bssl::UniquePtr<CRYPTO_BUFFER> leaf = GetChainTestCertificateBuffer();
+  ASSERT_TRUE(leaf);
+  bssl::UniquePtr<CRYPTO_BUFFER> intermediate =
+      GetChainTestIntermediateBuffer();
+  ASSERT_TRUE(intermediate);
+  std::vector<CRYPTO_BUFFER*> chain = {
+      leaf.get(), intermediate.get(),
+  };
+  ASSERT_TRUE(SSL_CTX_set_chain_and_key(server_ctx.get(), &chain[0],
+                                        chain.size(), key.get(), nullptr));
+
+  SSL_CTX_i_promise_to_verify_certs_after_the_handshake(client_ctx.get());
+
+  bssl::UniquePtr<SSL> client, server;
+  ASSERT_TRUE(ConnectClientAndServer(&client, &server, client_ctx.get(),
+                                     server_ctx.get(),
+                                     nullptr /* no session */));
+}
+
+// Configuring the empty cipher list, though an error, should still modify the
+// configuration.
+TEST(SSLTest, EmptyCipherList) {
+  bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
+  ASSERT_TRUE(ctx);
+
+  // Initially, the cipher list is not empty.
+  EXPECT_NE(0u, sk_SSL_CIPHER_num(SSL_CTX_get_ciphers(ctx.get())));
+
+  // Configuring the empty cipher list fails.
+  EXPECT_FALSE(SSL_CTX_set_cipher_list(ctx.get(), ""));
+  ERR_clear_error();
+
+  // But the cipher list is still updated to empty.
+  EXPECT_EQ(0u, sk_SSL_CIPHER_num(SSL_CTX_get_ciphers(ctx.get())));
+}
+
+// ssl_test_ticket_aead_failure_mode enumerates the possible ways in which the
+// test |SSL_TICKET_AEAD_METHOD| can fail.
+enum ssl_test_ticket_aead_failure_mode {
+  ssl_test_ticket_aead_ok = 0,
+  ssl_test_ticket_aead_seal_fail,
+  ssl_test_ticket_aead_open_soft_fail,
+  ssl_test_ticket_aead_open_hard_fail,
+};
+
+struct ssl_test_ticket_aead_state {
+  unsigned retry_count;
+  ssl_test_ticket_aead_failure_mode failure_mode;
+};
+
+static int ssl_test_ticket_aead_ex_index_dup(CRYPTO_EX_DATA *to,
+                                             const CRYPTO_EX_DATA *from,
+                                             void **from_d, int index,
+                                             long argl, void *argp) {
+  abort();
+}
+
+static void ssl_test_ticket_aead_ex_index_free(void *parent, void *ptr,
+                                               CRYPTO_EX_DATA *ad, int index,
+                                               long argl, void *argp) {
+  auto state = reinterpret_cast<ssl_test_ticket_aead_state*>(ptr);
+  if (state == nullptr) {
+    return;
+  }
+
+  OPENSSL_free(state);
+}
+
+static CRYPTO_once_t g_ssl_test_ticket_aead_ex_index_once = CRYPTO_ONCE_INIT;
+static int g_ssl_test_ticket_aead_ex_index;
+
+static int ssl_test_ticket_aead_get_ex_index() {
+  CRYPTO_once(&g_ssl_test_ticket_aead_ex_index_once, [] {
+    g_ssl_test_ticket_aead_ex_index = SSL_get_ex_new_index(
+        0, nullptr, nullptr, ssl_test_ticket_aead_ex_index_dup,
+        ssl_test_ticket_aead_ex_index_free);
+  });
+  return g_ssl_test_ticket_aead_ex_index;
+}
+
+static size_t ssl_test_ticket_aead_max_overhead(SSL *ssl) {
+  return 1;
+}
+
+static int ssl_test_ticket_aead_seal(SSL *ssl, uint8_t *out, size_t *out_len,
+                                     size_t max_out_len, const uint8_t *in,
+                                     size_t in_len) {
+  auto state = reinterpret_cast<ssl_test_ticket_aead_state *>(
+      SSL_get_ex_data(ssl, ssl_test_ticket_aead_get_ex_index()));
+
+  if (state->failure_mode == ssl_test_ticket_aead_seal_fail ||
+      max_out_len < in_len + 1) {
+    return 0;
+  }
+
+  OPENSSL_memmove(out, in, in_len);
+  out[in_len] = 0xff;
+  *out_len = in_len + 1;
+
+  return 1;
+}
+
+static ssl_ticket_aead_result_t ssl_test_ticket_aead_open(
+    SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out_len,
+    const uint8_t *in, size_t in_len) {
+  auto state = reinterpret_cast<ssl_test_ticket_aead_state *>(
+      SSL_get_ex_data(ssl, ssl_test_ticket_aead_get_ex_index()));
+
+  if (state->retry_count > 0) {
+    state->retry_count--;
+    return ssl_ticket_aead_retry;
+  }
+
+  switch (state->failure_mode) {
+    case ssl_test_ticket_aead_ok:
+      break;
+    case ssl_test_ticket_aead_seal_fail:
+      // If |seal| failed then there shouldn't be any ticket to try and
+      // decrypt.
+      abort();
+      break;
+    case ssl_test_ticket_aead_open_soft_fail:
+      return ssl_ticket_aead_ignore_ticket;
+    case ssl_test_ticket_aead_open_hard_fail:
+      return ssl_ticket_aead_error;
+  }
+
+  if (in_len == 0 || in[in_len - 1] != 0xff) {
+    return ssl_ticket_aead_ignore_ticket;
+  }
+
+  if (max_out_len < in_len - 1) {
+    return ssl_ticket_aead_error;
+  }
+
+  OPENSSL_memmove(out, in, in_len - 1);
+  *out_len = in_len - 1;
+  return ssl_ticket_aead_success;
+}
+
+static const SSL_TICKET_AEAD_METHOD kSSLTestTicketMethod = {
+  ssl_test_ticket_aead_max_overhead,
+  ssl_test_ticket_aead_seal,
+  ssl_test_ticket_aead_open,
+};
+
+static void ConnectClientAndServerWithTicketMethod(
+    bssl::UniquePtr<SSL> *out_client, bssl::UniquePtr<SSL> *out_server,
+    SSL_CTX *client_ctx, SSL_CTX *server_ctx, unsigned retry_count,
+    ssl_test_ticket_aead_failure_mode failure_mode, SSL_SESSION *session) {
+  bssl::UniquePtr<SSL> client(SSL_new(client_ctx)), server(SSL_new(server_ctx));
+  ASSERT_TRUE(client);
+  ASSERT_TRUE(server);
+  SSL_set_connect_state(client.get());
+  SSL_set_accept_state(server.get());
+
+  auto state = reinterpret_cast<ssl_test_ticket_aead_state *>(
+      OPENSSL_malloc(sizeof(ssl_test_ticket_aead_state)));
+  ASSERT_TRUE(state);
+  OPENSSL_memset(state, 0, sizeof(ssl_test_ticket_aead_state));
+  state->retry_count = retry_count;
+  state->failure_mode = failure_mode;
+
+  ASSERT_TRUE(SSL_set_ex_data(server.get(), ssl_test_ticket_aead_get_ex_index(),
+                              state));
+
+  SSL_set_session(client.get(), session);
+
+  BIO *bio1, *bio2;
+  ASSERT_TRUE(BIO_new_bio_pair(&bio1, 0, &bio2, 0));
+
+  // SSL_set_bio takes ownership.
+  SSL_set_bio(client.get(), bio1, bio1);
+  SSL_set_bio(server.get(), bio2, bio2);
+
+  if (CompleteHandshakes(client.get(), server.get())) {
+    *out_client = std::move(client);
+    *out_server = std::move(server);
+  } else {
+    out_client->reset();
+    out_server->reset();
+  }
+}
+
+class TicketAEADMethodTest
+    : public ::testing::TestWithParam<testing::tuple<
+          uint16_t, unsigned, ssl_test_ticket_aead_failure_mode>> {};
+
+TEST_P(TicketAEADMethodTest, Resume) {
+  bssl::UniquePtr<X509> cert = GetTestCertificate();
+  ASSERT_TRUE(cert);
+  bssl::UniquePtr<EVP_PKEY> key = GetTestKey();
+  ASSERT_TRUE(key);
+
+  bssl::UniquePtr<SSL_CTX> server_ctx(SSL_CTX_new(TLS_method()));
+  ASSERT_TRUE(server_ctx);
+  bssl::UniquePtr<SSL_CTX> client_ctx(SSL_CTX_new(TLS_method()));
+  ASSERT_TRUE(client_ctx);
+
+  const uint16_t version = testing::get<0>(GetParam());
+  const unsigned retry_count = testing::get<1>(GetParam());
+  const ssl_test_ticket_aead_failure_mode failure_mode =
+      testing::get<2>(GetParam());
+
+  ASSERT_TRUE(SSL_CTX_use_certificate(server_ctx.get(), cert.get()));
+  ASSERT_TRUE(SSL_CTX_use_PrivateKey(server_ctx.get(), key.get()));
+  ASSERT_TRUE(SSL_CTX_set_min_proto_version(client_ctx.get(), version));
+  ASSERT_TRUE(SSL_CTX_set_max_proto_version(client_ctx.get(), version));
+  ASSERT_TRUE(SSL_CTX_set_min_proto_version(server_ctx.get(), version));
+  ASSERT_TRUE(SSL_CTX_set_max_proto_version(server_ctx.get(), version));
+
+  SSL_CTX_set_session_cache_mode(client_ctx.get(), SSL_SESS_CACHE_BOTH);
+  SSL_CTX_set_session_cache_mode(server_ctx.get(), SSL_SESS_CACHE_BOTH);
+  SSL_CTX_set_current_time_cb(client_ctx.get(), FrozenTimeCallback);
+  SSL_CTX_set_current_time_cb(server_ctx.get(), FrozenTimeCallback);
+  SSL_CTX_sess_set_new_cb(client_ctx.get(), SaveLastSession);
+
+  SSL_CTX_set_ticket_aead_method(server_ctx.get(), &kSSLTestTicketMethod);
+
+  bssl::UniquePtr<SSL> client, server;
+  ConnectClientAndServerWithTicketMethod(&client, &server, client_ctx.get(),
+                                         server_ctx.get(), retry_count,
+                                         failure_mode, nullptr);
+  switch (failure_mode) {
+    case ssl_test_ticket_aead_ok:
+    case ssl_test_ticket_aead_open_hard_fail:
+    case ssl_test_ticket_aead_open_soft_fail:
+      ASSERT_TRUE(client);
+      break;
+    case ssl_test_ticket_aead_seal_fail:
+      EXPECT_FALSE(client);
+      return;
+  }
+  EXPECT_FALSE(SSL_session_reused(client.get()));
+  EXPECT_FALSE(SSL_session_reused(server.get()));
+
+  // Run the read loop to account for post-handshake tickets in TLS 1.3.
+  SSL_read(client.get(), nullptr, 0);
+
+  bssl::UniquePtr<SSL_SESSION> session = std::move(g_last_session);
+  ConnectClientAndServerWithTicketMethod(&client, &server, client_ctx.get(),
+                                         server_ctx.get(), retry_count,
+                                         failure_mode, session.get());
+  switch (failure_mode) {
+    case ssl_test_ticket_aead_ok:
+      ASSERT_TRUE(client);
+      EXPECT_TRUE(SSL_session_reused(client.get()));
+      EXPECT_TRUE(SSL_session_reused(server.get()));
+      break;
+    case ssl_test_ticket_aead_seal_fail:
+      abort();
+      break;
+    case ssl_test_ticket_aead_open_hard_fail:
+      EXPECT_FALSE(client);
+      break;
+    case ssl_test_ticket_aead_open_soft_fail:
+      ASSERT_TRUE(client);
+      EXPECT_FALSE(SSL_session_reused(client.get()));
+      EXPECT_FALSE(SSL_session_reused(server.get()));
+  }
+}
+
+INSTANTIATE_TEST_CASE_P(
+    TicketAEADMethodTests, TicketAEADMethodTest,
+    testing::Combine(
+        testing::Values(TLS1_2_VERSION, TLS1_3_VERSION),
+        testing::Values(0, 1, 2),
+        testing::Values(ssl_test_ticket_aead_ok,
+                        ssl_test_ticket_aead_seal_fail,
+                        ssl_test_ticket_aead_open_soft_fail,
+                        ssl_test_ticket_aead_open_hard_fail)));
+
+// TODO(davidben): Convert this file to GTest properly.
+TEST(SSLTest, AllTests) {
   if (!TestCipherRules() ||
+      !TestCurveRules() ||
       !TestSSL_SESSIONEncoding(kOpenSSLSession) ||
       !TestSSL_SESSIONEncoding(kCustomSession) ||
       !TestSSL_SESSIONEncoding(kBoringSSLSession) ||
       !TestBadSSL_SESSIONEncoding(kBadSessionExtraField) ||
       !TestBadSSL_SESSIONEncoding(kBadSessionVersion) ||
       !TestBadSSL_SESSIONEncoding(kBadSessionTrailingData) ||
-      !TestDefaultVersion(0, &TLS_method) ||
-      !TestDefaultVersion(SSL3_VERSION, &SSLv3_method) ||
-      !TestDefaultVersion(TLS1_VERSION, &TLSv1_method) ||
-      !TestDefaultVersion(TLS1_1_VERSION, &TLSv1_1_method) ||
-      !TestDefaultVersion(TLS1_2_VERSION, &TLSv1_2_method) ||
-      !TestDefaultVersion(0, &DTLS_method) ||
-      !TestDefaultVersion(DTLS1_VERSION, &DTLSv1_method) ||
-      !TestDefaultVersion(DTLS1_2_VERSION, &DTLSv1_2_method) ||
+      // TODO(svaldez): Update this when TLS 1.3 is enabled by default.
+      !TestDefaultVersion(SSL3_VERSION, TLS1_2_VERSION, &TLS_method) ||
+      !TestDefaultVersion(SSL3_VERSION, SSL3_VERSION, &SSLv3_method) ||
+      !TestDefaultVersion(TLS1_VERSION, TLS1_VERSION, &TLSv1_method) ||
+      !TestDefaultVersion(TLS1_1_VERSION, TLS1_1_VERSION, &TLSv1_1_method) ||
+      !TestDefaultVersion(TLS1_2_VERSION, TLS1_2_VERSION, &TLSv1_2_method) ||
+      !TestDefaultVersion(TLS1_1_VERSION, TLS1_2_VERSION, &DTLS_method) ||
+      !TestDefaultVersion(TLS1_1_VERSION, TLS1_1_VERSION, &DTLSv1_method) ||
+      !TestDefaultVersion(TLS1_2_VERSION, TLS1_2_VERSION, &DTLSv1_2_method) ||
       !TestCipherGetRFCName() ||
-      !TestPaddingExtension() ||
-      !TestClientCAList() ||
-      !TestInternalSessionCache()) {
-    ERR_print_errors_fp(stderr);
-    return 1;
+      // Test the padding extension at TLS 1.2.
+      !TestPaddingExtension(TLS1_2_VERSION, TLS1_2_VERSION) ||
+      // Test the padding extension at TLS 1.3 with a TLS 1.2 session, so there
+      // will be no PSK binder after the padding extension.
+      !TestPaddingExtension(TLS1_3_VERSION, TLS1_2_VERSION) ||
+      // Test the padding extension at TLS 1.3 with a TLS 1.3 session, so there
+      // will be a PSK binder after the padding extension.
+      !TestPaddingExtension(TLS1_3_VERSION, TLS1_3_DRAFT_VERSION) ||
+      !TestInternalSessionCache() ||
+      !ForEachVersion(TestSequenceNumber) ||
+      !ForEachVersion(TestOneSidedShutdown) ||
+      !ForEachVersion(TestGetPeerCertificate) ||
+      !ForEachVersion(TestRetainOnlySHA256OfCerts) ||
+      !TestClientHello() ||
+      !ForEachVersion(TestSessionIDContext) ||
+      !ForEachVersion(TestSessionTimeout) ||
+      !ForEachVersion(TestSNICallback) ||
+      !ForEachVersion(TestVersion) ||
+      !ForEachVersion(TestALPNCipherAvailable) ||
+      !ForEachVersion(TestSSLClearSessionResumption) ||
+      !ForEachVersion(TestAutoChain) ||
+      !ForEachVersion(TestSSLWriteRetry)) {
+    ADD_FAILURE() << "Tests failed";
   }
-
-  printf("PASS\n");
-  return 0;
 }
diff --git a/src/ssl/ssl_transcript.c b/src/ssl/ssl_transcript.c
new file mode 100644
index 0000000..9cc3777
--- /dev/null
+++ b/src/ssl/ssl_transcript.c
@@ -0,0 +1,405 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE. */
+
+#include <openssl/ssl.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/buf.h>
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/md5.h>
+#include <openssl/nid.h>
+#include <openssl/sha.h>
+
+#include "../crypto/internal.h"
+#include "internal.h"
+
+
+int SSL_TRANSCRIPT_init(SSL_TRANSCRIPT *transcript) {
+  SSL_TRANSCRIPT_cleanup(transcript);
+  transcript->buffer = BUF_MEM_new();
+  return transcript->buffer != NULL;
+}
+
+/* init_digest_with_data calls |EVP_DigestInit_ex| on |ctx| with |md| and then
+ * writes the data in |buf| to it. */
+static int init_digest_with_data(EVP_MD_CTX *ctx, const EVP_MD *md,
+                                 const BUF_MEM *buf) {
+  if (!EVP_DigestInit_ex(ctx, md, NULL)) {
+    return 0;
+  }
+  EVP_DigestUpdate(ctx, buf->data, buf->length);
+  return 1;
+}
+
+int SSL_TRANSCRIPT_init_hash(SSL_TRANSCRIPT *transcript, uint16_t version,
+                             int algorithm_prf) {
+  const EVP_MD *md = ssl_get_handshake_digest(algorithm_prf, version);
+
+  /* To support SSL 3.0's Finished and CertificateVerify constructions,
+   * EVP_md5_sha1() is split into MD5 and SHA-1 halves. When SSL 3.0 is removed,
+   * we can simplify this. */
+  if (md == EVP_md5_sha1()) {
+    if (!init_digest_with_data(&transcript->md5, EVP_md5(),
+                               transcript->buffer)) {
+      return 0;
+    }
+    md = EVP_sha1();
+  }
+
+  if (!init_digest_with_data(&transcript->hash, md, transcript->buffer)) {
+    return 0;
+  }
+
+  return 1;
+}
+
+void SSL_TRANSCRIPT_cleanup(SSL_TRANSCRIPT *transcript) {
+  SSL_TRANSCRIPT_free_buffer(transcript);
+  EVP_MD_CTX_cleanup(&transcript->hash);
+  EVP_MD_CTX_cleanup(&transcript->md5);
+}
+
+void SSL_TRANSCRIPT_free_buffer(SSL_TRANSCRIPT *transcript) {
+  BUF_MEM_free(transcript->buffer);
+  transcript->buffer = NULL;
+}
+
+size_t SSL_TRANSCRIPT_digest_len(const SSL_TRANSCRIPT *transcript) {
+  return EVP_MD_size(SSL_TRANSCRIPT_md(transcript));
+}
+
+const EVP_MD *SSL_TRANSCRIPT_md(const SSL_TRANSCRIPT *transcript) {
+  if (EVP_MD_CTX_md(&transcript->md5) != NULL) {
+    return EVP_md5_sha1();
+  }
+  return EVP_MD_CTX_md(&transcript->hash);
+}
+
+int SSL_TRANSCRIPT_update(SSL_TRANSCRIPT *transcript, const uint8_t *in,
+                          size_t in_len) {
+  /* Depending on the state of the handshake, either the handshake buffer may be
+   * active, the rolling hash, or both. */
+  if (transcript->buffer != NULL) {
+    size_t new_len = transcript->buffer->length + in_len;
+    if (new_len < in_len) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
+      return 0;
+    }
+    if (!BUF_MEM_grow(transcript->buffer, new_len)) {
+      return 0;
+    }
+    OPENSSL_memcpy(transcript->buffer->data + new_len - in_len, in, in_len);
+  }
+
+  if (EVP_MD_CTX_md(&transcript->hash) != NULL) {
+    EVP_DigestUpdate(&transcript->hash, in, in_len);
+  }
+  if (EVP_MD_CTX_md(&transcript->md5) != NULL) {
+    EVP_DigestUpdate(&transcript->md5, in, in_len);
+  }
+
+  return 1;
+}
+
+int SSL_TRANSCRIPT_get_hash(const SSL_TRANSCRIPT *transcript, uint8_t *out,
+                            size_t *out_len) {
+  int ret = 0;
+  EVP_MD_CTX ctx;
+  EVP_MD_CTX_init(&ctx);
+  unsigned md5_len = 0;
+  if (EVP_MD_CTX_md(&transcript->md5) != NULL) {
+    if (!EVP_MD_CTX_copy_ex(&ctx, &transcript->md5) ||
+        !EVP_DigestFinal_ex(&ctx, out, &md5_len)) {
+      goto err;
+    }
+  }
+
+  unsigned len;
+  if (!EVP_MD_CTX_copy_ex(&ctx, &transcript->hash) ||
+      !EVP_DigestFinal_ex(&ctx, out + md5_len, &len)) {
+    goto err;
+  }
+
+  *out_len = md5_len + len;
+  ret = 1;
+
+err:
+  EVP_MD_CTX_cleanup(&ctx);
+  return ret;
+}
+
+static int ssl3_handshake_mac(SSL_TRANSCRIPT *transcript,
+                              const SSL_SESSION *session,
+                              const EVP_MD_CTX *ctx_template,
+                              const char *sender, size_t sender_len,
+                              uint8_t *p, size_t *out_len) {
+  unsigned int len;
+  size_t npad, n;
+  unsigned int i;
+  uint8_t md_buf[EVP_MAX_MD_SIZE];
+  EVP_MD_CTX ctx;
+
+  EVP_MD_CTX_init(&ctx);
+  if (!EVP_MD_CTX_copy_ex(&ctx, ctx_template)) {
+    EVP_MD_CTX_cleanup(&ctx);
+    OPENSSL_PUT_ERROR(SSL, ERR_LIB_EVP);
+    return 0;
+  }
+
+  static const uint8_t kPad1[48] = {
+      0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+      0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+      0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+      0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
+  };
+
+  static const uint8_t kPad2[48] = {
+      0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+      0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+      0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+      0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
+  };
+
+  n = EVP_MD_CTX_size(&ctx);
+
+  npad = (48 / n) * n;
+  if (sender != NULL) {
+    EVP_DigestUpdate(&ctx, sender, sender_len);
+  }
+  EVP_DigestUpdate(&ctx, session->master_key, session->master_key_length);
+  EVP_DigestUpdate(&ctx, kPad1, npad);
+  EVP_DigestFinal_ex(&ctx, md_buf, &i);
+
+  if (!EVP_DigestInit_ex(&ctx, EVP_MD_CTX_md(&ctx), NULL)) {
+    EVP_MD_CTX_cleanup(&ctx);
+    OPENSSL_PUT_ERROR(SSL, ERR_LIB_EVP);
+    return 0;
+  }
+  EVP_DigestUpdate(&ctx, session->master_key, session->master_key_length);
+  EVP_DigestUpdate(&ctx, kPad2, npad);
+  EVP_DigestUpdate(&ctx, md_buf, i);
+  EVP_DigestFinal_ex(&ctx, p, &len);
+
+  EVP_MD_CTX_cleanup(&ctx);
+
+  *out_len = len;
+  return 1;
+}
+
+int SSL_TRANSCRIPT_ssl3_cert_verify_hash(SSL_TRANSCRIPT *transcript,
+                                         uint8_t *out, size_t *out_len,
+                                         const SSL_SESSION *session,
+                                         int signature_algorithm) {
+  if (SSL_TRANSCRIPT_md(transcript) != EVP_md5_sha1()) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    return 0;
+  }
+
+  if (signature_algorithm == SSL_SIGN_RSA_PKCS1_MD5_SHA1) {
+    size_t md5_len, len;
+    if (!ssl3_handshake_mac(transcript, session, &transcript->md5, NULL, 0, out,
+                            &md5_len) ||
+        !ssl3_handshake_mac(transcript, session, &transcript->hash, NULL, 0,
+                            out + md5_len, &len)) {
+      return 0;
+    }
+    *out_len = md5_len + len;
+    return 1;
+  }
+
+  if (signature_algorithm == SSL_SIGN_ECDSA_SHA1) {
+    return ssl3_handshake_mac(transcript, session, &transcript->hash, NULL, 0,
+                              out, out_len);
+  }
+
+  OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+  return 0;
+}
+
+int SSL_TRANSCRIPT_finish_mac(SSL_TRANSCRIPT *transcript, uint8_t *out,
+                              size_t *out_len, const SSL_SESSION *session,
+                              int from_server, uint16_t version) {
+  if (version == SSL3_VERSION) {
+    if (SSL_TRANSCRIPT_md(transcript) != EVP_md5_sha1()) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+      return 0;
+    }
+
+    const char *sender = from_server ? SSL3_MD_SERVER_FINISHED_CONST
+                                     : SSL3_MD_CLIENT_FINISHED_CONST;
+    const size_t sender_len = 4;
+    size_t md5_len, len;
+    if (!ssl3_handshake_mac(transcript, session, &transcript->md5, sender,
+                            sender_len, out, &md5_len) ||
+        !ssl3_handshake_mac(transcript, session, &transcript->hash, sender,
+                            sender_len, out + md5_len, &len)) {
+      return 0;
+    }
+
+    *out_len = md5_len + len;
+    return 1;
+  }
+
+  /* At this point, the handshake should have released the handshake buffer on
+   * its own. */
+  assert(transcript->buffer == NULL);
+
+  const char *label = TLS_MD_CLIENT_FINISH_CONST;
+  size_t label_len = TLS_MD_SERVER_FINISH_CONST_SIZE;
+  if (from_server) {
+    label = TLS_MD_SERVER_FINISH_CONST;
+    label_len = TLS_MD_SERVER_FINISH_CONST_SIZE;
+  }
+
+  uint8_t digests[EVP_MAX_MD_SIZE];
+  size_t digests_len;
+  if (!SSL_TRANSCRIPT_get_hash(transcript, digests, &digests_len)) {
+    return 0;
+  }
+
+  static const size_t kFinishedLen = 12;
+  if (!tls1_prf(SSL_TRANSCRIPT_md(transcript), out, kFinishedLen,
+                session->master_key, session->master_key_length, label,
+                label_len, digests, digests_len, NULL, 0)) {
+    return 0;
+  }
+
+  *out_len = kFinishedLen;
+  return 1;
+}
diff --git a/src/ssl/ssl_x509.c b/src/ssl/ssl_x509.c
new file mode 100644
index 0000000..65405aa
--- /dev/null
+++ b/src/ssl/ssl_x509.c
@@ -0,0 +1,1344 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+/* ====================================================================
+ * Copyright (c) 1998-2007 The OpenSSL Project.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ *    software must display the following acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ *    endorse or promote products derived from this software without
+ *    prior written permission. For written permission, please contact
+ *    openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ *    nor may "OpenSSL" appear in their names without prior written
+ *    permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ *    acknowledgment:
+ *    "This product includes software developed by the OpenSSL Project
+ *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com).  This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+/* ====================================================================
+ * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
+ * ECC cipher suite support in OpenSSL originally developed by
+ * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
+ */
+/* ====================================================================
+ * Copyright 2005 Nokia. All rights reserved.
+ *
+ * The portions of the attached software ("Contribution") is developed by
+ * Nokia Corporation and is licensed pursuant to the OpenSSL open source
+ * license.
+ *
+ * The Contribution, originally written by Mika Kousa and Pasi Eronen of
+ * Nokia Corporation, consists of the "PSK" (Pre-Shared Key) ciphersuites
+ * support (see RFC 4279) to OpenSSL.
+ *
+ * No patent licenses or other rights except those expressly stated in
+ * the OpenSSL open source license shall be deemed granted or received
+ * expressly, by implication, estoppel, or otherwise.
+ *
+ * No assurances are provided by Nokia that the Contribution does not
+ * infringe the patent or other intellectual property rights of any third
+ * party or that the license provides you with all the necessary rights
+ * to make use of the Contribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. IN
+ * ADDITION TO THE DISCLAIMERS INCLUDED IN THE LICENSE, NOKIA
+ * SPECIFICALLY DISCLAIMS ANY LIABILITY FOR CLAIMS BROUGHT BY YOU OR ANY
+ * OTHER ENTITY BASED ON INFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS OR
+ * OTHERWISE. */
+
+#include <openssl/ssl.h>
+
+#include <assert.h>
+
+#include <openssl/asn1.h>
+#include <openssl/bytestring.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/stack.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/x509_vfy.h>
+
+#include "internal.h"
+#include "../crypto/internal.h"
+
+
+/* check_ssl_x509_method asserts that |ssl| has the X509-based method
+ * installed. Calling an X509-based method on an |ssl| with a different method
+ * will likely misbehave and possibly crash or leak memory. */
+static void check_ssl_x509_method(const SSL *ssl) {
+  assert(ssl == NULL || ssl->ctx->x509_method == &ssl_crypto_x509_method);
+}
+
+/* check_ssl_ctx_x509_method acts like |check_ssl_x509_method|, but for an
+ * |SSL_CTX|. */
+static void check_ssl_ctx_x509_method(const SSL_CTX *ctx) {
+  assert(ctx == NULL || ctx->x509_method == &ssl_crypto_x509_method);
+}
+
+X509 *SSL_get_peer_certificate(const SSL *ssl) {
+  check_ssl_x509_method(ssl);
+  if (ssl == NULL) {
+    return NULL;
+  }
+  SSL_SESSION *session = SSL_get_session(ssl);
+  if (session == NULL || session->x509_peer == NULL) {
+    return NULL;
+  }
+  X509_up_ref(session->x509_peer);
+  return session->x509_peer;
+}
+
+STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *ssl) {
+  check_ssl_x509_method(ssl);
+  if (ssl == NULL) {
+    return NULL;
+  }
+  SSL_SESSION *session = SSL_get_session(ssl);
+  if (session == NULL ||
+      session->x509_chain == NULL) {
+    return NULL;
+  }
+
+  if (!ssl->server) {
+    return session->x509_chain;
+  }
+
+  /* OpenSSL historically didn't include the leaf certificate in the returned
+   * certificate chain, but only for servers. */
+  if (session->x509_chain_without_leaf == NULL) {
+    session->x509_chain_without_leaf = sk_X509_new_null();
+    if (session->x509_chain_without_leaf == NULL) {
+      return NULL;
+    }
+
+    for (size_t i = 1; i < sk_X509_num(session->x509_chain); i++) {
+      X509 *cert = sk_X509_value(session->x509_chain, i);
+      if (!sk_X509_push(session->x509_chain_without_leaf, cert)) {
+        sk_X509_pop_free(session->x509_chain_without_leaf, X509_free);
+        session->x509_chain_without_leaf = NULL;
+        return NULL;
+      }
+      X509_up_ref(cert);
+    }
+  }
+
+  return session->x509_chain_without_leaf;
+}
+
+STACK_OF(X509) *SSL_get_peer_full_cert_chain(const SSL *ssl) {
+  check_ssl_x509_method(ssl);
+  SSL_SESSION *session = SSL_get_session(ssl);
+  if (session == NULL) {
+    return NULL;
+  }
+
+  return session->x509_chain;
+}
+
+int SSL_CTX_set_purpose(SSL_CTX *ctx, int purpose) {
+  check_ssl_ctx_x509_method(ctx);
+  return X509_VERIFY_PARAM_set_purpose(ctx->param, purpose);
+}
+
+int SSL_set_purpose(SSL *ssl, int purpose) {
+  check_ssl_x509_method(ssl);
+  return X509_VERIFY_PARAM_set_purpose(ssl->param, purpose);
+}
+
+int SSL_CTX_set_trust(SSL_CTX *ctx, int trust) {
+  check_ssl_ctx_x509_method(ctx);
+  return X509_VERIFY_PARAM_set_trust(ctx->param, trust);
+}
+
+int SSL_set_trust(SSL *ssl, int trust) {
+  check_ssl_x509_method(ssl);
+  return X509_VERIFY_PARAM_set_trust(ssl->param, trust);
+}
+
+int SSL_CTX_set1_param(SSL_CTX *ctx, const X509_VERIFY_PARAM *param) {
+  check_ssl_ctx_x509_method(ctx);
+  return X509_VERIFY_PARAM_set1(ctx->param, param);
+}
+
+int SSL_set1_param(SSL *ssl, const X509_VERIFY_PARAM *param) {
+  check_ssl_x509_method(ssl);
+  return X509_VERIFY_PARAM_set1(ssl->param, param);
+}
+
+X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx) {
+  check_ssl_ctx_x509_method(ctx);
+  return ctx->param;
+}
+
+X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl) {
+  check_ssl_x509_method(ssl);
+  return ssl->param;
+}
+
+int SSL_get_verify_depth(const SSL *ssl) {
+  check_ssl_x509_method(ssl);
+  return X509_VERIFY_PARAM_get_depth(ssl->param);
+}
+
+int (*SSL_get_verify_callback(const SSL *ssl))(int, X509_STORE_CTX *) {
+  check_ssl_x509_method(ssl);
+  return ssl->verify_callback;
+}
+
+int SSL_CTX_get_verify_mode(const SSL_CTX *ctx) {
+  check_ssl_ctx_x509_method(ctx);
+  return ctx->verify_mode;
+}
+
+int SSL_CTX_get_verify_depth(const SSL_CTX *ctx) {
+  check_ssl_ctx_x509_method(ctx);
+  return X509_VERIFY_PARAM_get_depth(ctx->param);
+}
+
+int (*SSL_CTX_get_verify_callback(const SSL_CTX *ctx))(
+    int ok, X509_STORE_CTX *store_ctx) {
+  check_ssl_ctx_x509_method(ctx);
+  return ctx->default_verify_callback;
+}
+
+void SSL_set_verify(SSL *ssl, int mode,
+                    int (*callback)(int ok, X509_STORE_CTX *store_ctx)) {
+  check_ssl_x509_method(ssl);
+  ssl->verify_mode = mode;
+  if (callback != NULL) {
+    ssl->verify_callback = callback;
+  }
+}
+
+void SSL_set_verify_depth(SSL *ssl, int depth) {
+  check_ssl_x509_method(ssl);
+  X509_VERIFY_PARAM_set_depth(ssl->param, depth);
+}
+
+void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx,
+                                      int (*cb)(X509_STORE_CTX *store_ctx,
+                                                void *arg),
+                                      void *arg) {
+  check_ssl_ctx_x509_method(ctx);
+  ctx->app_verify_callback = cb;
+  ctx->app_verify_arg = arg;
+}
+
+void SSL_CTX_set_verify(SSL_CTX *ctx, int mode,
+                        int (*cb)(int, X509_STORE_CTX *)) {
+  check_ssl_ctx_x509_method(ctx);
+  ctx->verify_mode = mode;
+  ctx->default_verify_callback = cb;
+}
+
+void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth) {
+  check_ssl_ctx_x509_method(ctx);
+  X509_VERIFY_PARAM_set_depth(ctx->param, depth);
+}
+
+int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx) {
+  check_ssl_ctx_x509_method(ctx);
+  return X509_STORE_set_default_paths(ctx->cert_store);
+}
+
+int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *ca_file,
+                                  const char *ca_dir) {
+  check_ssl_ctx_x509_method(ctx);
+  return X509_STORE_load_locations(ctx->cert_store, ca_file, ca_dir);
+}
+
+void SSL_set_verify_result(SSL *ssl, long result) {
+  check_ssl_x509_method(ssl);
+  if (result != X509_V_OK) {
+    abort();
+  }
+}
+
+long SSL_get_verify_result(const SSL *ssl) {
+  check_ssl_x509_method(ssl);
+  SSL_SESSION *session = SSL_get_session(ssl);
+  if (session == NULL) {
+    return X509_V_ERR_INVALID_CALL;
+  }
+  return session->verify_result;
+}
+
+X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *ctx) {
+  check_ssl_ctx_x509_method(ctx);
+  return ctx->cert_store;
+}
+
+void SSL_CTX_set_cert_store(SSL_CTX *ctx, X509_STORE *store) {
+  check_ssl_ctx_x509_method(ctx);
+  X509_STORE_free(ctx->cert_store);
+  ctx->cert_store = store;
+}
+
+/* x509_to_buffer returns a |CRYPTO_BUFFER| that contains the serialised
+ * contents of |x509|. */
+static CRYPTO_BUFFER *x509_to_buffer(X509 *x509) {
+  uint8_t *buf = NULL;
+  int cert_len = i2d_X509(x509, &buf);
+  if (cert_len <= 0) {
+    return 0;
+  }
+
+  CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new(buf, cert_len, NULL);
+  OPENSSL_free(buf);
+
+  return buffer;
+}
+
+/* new_leafless_chain returns a fresh stack of buffers set to {NULL}. */
+static STACK_OF(CRYPTO_BUFFER) *new_leafless_chain(void) {
+  STACK_OF(CRYPTO_BUFFER) *chain = sk_CRYPTO_BUFFER_new_null();
+  if (chain == NULL) {
+    return NULL;
+  }
+
+  if (!sk_CRYPTO_BUFFER_push(chain, NULL)) {
+    sk_CRYPTO_BUFFER_free(chain);
+    return NULL;
+  }
+
+  return chain;
+}
+
+/* ssl_cert_set_chain sets elements 1.. of |cert->chain| to the serialised
+ * forms of elements of |chain|. It returns one on success or zero on error, in
+ * which case no change to |cert->chain| is made. It preverses the existing
+ * leaf from |cert->chain|, if any. */
+static int ssl_cert_set_chain(CERT *cert, STACK_OF(X509) *chain) {
+  STACK_OF(CRYPTO_BUFFER) *new_chain = NULL;
+
+  if (cert->chain != NULL) {
+    new_chain = sk_CRYPTO_BUFFER_new_null();
+    if (new_chain == NULL) {
+      return 0;
+    }
+
+    CRYPTO_BUFFER *leaf = sk_CRYPTO_BUFFER_value(cert->chain, 0);
+    if (!sk_CRYPTO_BUFFER_push(new_chain, leaf)) {
+      goto err;
+    }
+    /* |leaf| might be NULL if it's a “leafless” chain. */
+    if (leaf != NULL) {
+      CRYPTO_BUFFER_up_ref(leaf);
+    }
+  }
+
+  for (size_t i = 0; i < sk_X509_num(chain); i++) {
+    if (new_chain == NULL) {
+      new_chain = new_leafless_chain();
+      if (new_chain == NULL) {
+        goto err;
+      }
+    }
+
+    CRYPTO_BUFFER *buffer = x509_to_buffer(sk_X509_value(chain, i));
+    if (buffer == NULL ||
+        !sk_CRYPTO_BUFFER_push(new_chain, buffer)) {
+      CRYPTO_BUFFER_free(buffer);
+      goto err;
+    }
+  }
+
+  sk_CRYPTO_BUFFER_pop_free(cert->chain, CRYPTO_BUFFER_free);
+  cert->chain = new_chain;
+
+  return 1;
+
+err:
+  sk_CRYPTO_BUFFER_pop_free(new_chain, CRYPTO_BUFFER_free);
+  return 0;
+}
+
+static void ssl_crypto_x509_cert_flush_cached_leaf(CERT *cert) {
+  X509_free(cert->x509_leaf);
+  cert->x509_leaf = NULL;
+}
+
+static void ssl_crypto_x509_cert_flush_cached_chain(CERT *cert) {
+  sk_X509_pop_free(cert->x509_chain, X509_free);
+  cert->x509_chain = NULL;
+}
+
+static int ssl_crypto_x509_check_client_CA_list(
+    STACK_OF(CRYPTO_BUFFER) *names) {
+  for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(names); i++) {
+    const CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(names, i);
+    const uint8_t *inp = CRYPTO_BUFFER_data(buffer);
+    X509_NAME *name = d2i_X509_NAME(NULL, &inp, CRYPTO_BUFFER_len(buffer));
+    const int ok = name != NULL && inp == CRYPTO_BUFFER_data(buffer) +
+                                              CRYPTO_BUFFER_len(buffer);
+    X509_NAME_free(name);
+    if (!ok) {
+      return 0;
+    }
+  }
+
+  return 1;
+}
+
+static void ssl_crypto_x509_cert_clear(CERT *cert) {
+  ssl_crypto_x509_cert_flush_cached_leaf(cert);
+  ssl_crypto_x509_cert_flush_cached_chain(cert);
+
+  X509_free(cert->x509_stash);
+  cert->x509_stash = NULL;
+}
+
+static void ssl_crypto_x509_cert_free(CERT *cert) {
+  ssl_crypto_x509_cert_clear(cert);
+  X509_STORE_free(cert->verify_store);
+}
+
+static void ssl_crypto_x509_cert_dup(CERT *new_cert, const CERT *cert) {
+  if (cert->verify_store != NULL) {
+    X509_STORE_up_ref(cert->verify_store);
+    new_cert->verify_store = cert->verify_store;
+  }
+}
+
+static int ssl_crypto_x509_session_cache_objects(SSL_SESSION *sess) {
+  STACK_OF(X509) *chain = NULL;
+  const size_t num_certs = sk_CRYPTO_BUFFER_num(sess->certs);
+
+  if (num_certs > 0) {
+    chain = sk_X509_new_null();
+    if (chain == NULL) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+      goto err;
+    }
+  }
+
+  X509 *leaf = NULL;
+  for (size_t i = 0; i < num_certs; i++) {
+    X509 *x509 = X509_parse_from_buffer(sk_CRYPTO_BUFFER_value(sess->certs, i));
+    if (x509 == NULL) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+      goto err;
+    }
+    if (!sk_X509_push(chain, x509)) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+      X509_free(x509);
+      goto err;
+    }
+    if (i == 0) {
+      leaf = x509;
+    }
+  }
+
+  sk_X509_pop_free(sess->x509_chain, X509_free);
+  sess->x509_chain = chain;
+  sk_X509_pop_free(sess->x509_chain_without_leaf, X509_free);
+  sess->x509_chain_without_leaf = NULL;
+
+  X509_free(sess->x509_peer);
+  if (leaf != NULL) {
+    X509_up_ref(leaf);
+  }
+  sess->x509_peer = leaf;
+
+  return 1;
+
+err:
+  sk_X509_pop_free(chain, X509_free);
+  return 0;
+}
+
+static int ssl_crypto_x509_session_dup(SSL_SESSION *new_session,
+                                       const SSL_SESSION *session) {
+  if (session->x509_peer != NULL) {
+    X509_up_ref(session->x509_peer);
+    new_session->x509_peer = session->x509_peer;
+  }
+  if (session->x509_chain != NULL) {
+    new_session->x509_chain = X509_chain_up_ref(session->x509_chain);
+    if (new_session->x509_chain == NULL) {
+      return 0;
+    }
+  }
+
+  return 1;
+}
+
+static void ssl_crypto_x509_session_clear(SSL_SESSION *session) {
+  X509_free(session->x509_peer);
+  session->x509_peer = NULL;
+  sk_X509_pop_free(session->x509_chain, X509_free);
+  session->x509_chain = NULL;
+  sk_X509_pop_free(session->x509_chain_without_leaf, X509_free);
+  session->x509_chain_without_leaf = NULL;
+}
+
+static int ssl_verify_alarm_type(long type) {
+  switch (type) {
+    case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
+    case X509_V_ERR_UNABLE_TO_GET_CRL:
+    case X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER:
+      return SSL_AD_UNKNOWN_CA;
+
+    case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
+    case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
+    case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
+    case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
+    case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
+    case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
+    case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
+    case X509_V_ERR_CERT_NOT_YET_VALID:
+    case X509_V_ERR_CRL_NOT_YET_VALID:
+    case X509_V_ERR_CERT_UNTRUSTED:
+    case X509_V_ERR_CERT_REJECTED:
+    case X509_V_ERR_HOSTNAME_MISMATCH:
+    case X509_V_ERR_EMAIL_MISMATCH:
+    case X509_V_ERR_IP_ADDRESS_MISMATCH:
+      return SSL_AD_BAD_CERTIFICATE;
+
+    case X509_V_ERR_CERT_SIGNATURE_FAILURE:
+    case X509_V_ERR_CRL_SIGNATURE_FAILURE:
+      return SSL_AD_DECRYPT_ERROR;
+
+    case X509_V_ERR_CERT_HAS_EXPIRED:
+    case X509_V_ERR_CRL_HAS_EXPIRED:
+      return SSL_AD_CERTIFICATE_EXPIRED;
+
+    case X509_V_ERR_CERT_REVOKED:
+      return SSL_AD_CERTIFICATE_REVOKED;
+
+    case X509_V_ERR_UNSPECIFIED:
+    case X509_V_ERR_OUT_OF_MEM:
+    case X509_V_ERR_INVALID_CALL:
+    case X509_V_ERR_STORE_LOOKUP:
+      return SSL_AD_INTERNAL_ERROR;
+
+    case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
+    case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
+    case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
+    case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
+    case X509_V_ERR_CERT_CHAIN_TOO_LONG:
+    case X509_V_ERR_PATH_LENGTH_EXCEEDED:
+    case X509_V_ERR_INVALID_CA:
+      return SSL_AD_UNKNOWN_CA;
+
+    case X509_V_ERR_APPLICATION_VERIFICATION:
+      return SSL_AD_HANDSHAKE_FAILURE;
+
+    case X509_V_ERR_INVALID_PURPOSE:
+      return SSL_AD_UNSUPPORTED_CERTIFICATE;
+
+    default:
+      return SSL_AD_CERTIFICATE_UNKNOWN;
+  }
+}
+
+static int ssl_crypto_x509_session_verify_cert_chain(SSL_SESSION *session,
+                                                     SSL *ssl) {
+  STACK_OF(X509) *const cert_chain = session->x509_chain;
+  if (cert_chain == NULL || sk_X509_num(cert_chain) == 0) {
+    return 0;
+  }
+
+  X509_STORE *verify_store = ssl->ctx->cert_store;
+  if (ssl->cert->verify_store != NULL) {
+    verify_store = ssl->cert->verify_store;
+  }
+
+  X509 *leaf = sk_X509_value(cert_chain, 0);
+  int ret = 0;
+  X509_STORE_CTX ctx;
+  if (!X509_STORE_CTX_init(&ctx, verify_store, leaf, cert_chain)) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_X509_LIB);
+    return 0;
+  }
+  if (!X509_STORE_CTX_set_ex_data(&ctx, SSL_get_ex_data_X509_STORE_CTX_idx(),
+                                  ssl)) {
+    goto err;
+  }
+
+  /* We need to inherit the verify parameters. These can be determined by the
+   * context: if its a server it will verify SSL client certificates or vice
+   * versa. */
+  X509_STORE_CTX_set_default(&ctx, ssl->server ? "ssl_client" : "ssl_server");
+
+  /* Anything non-default in "param" should overwrite anything in the ctx. */
+  X509_VERIFY_PARAM_set1(X509_STORE_CTX_get0_param(&ctx), ssl->param);
+
+  if (ssl->verify_callback) {
+    X509_STORE_CTX_set_verify_cb(&ctx, ssl->verify_callback);
+  }
+
+  int verify_ret;
+  if (ssl->ctx->app_verify_callback != NULL) {
+    verify_ret = ssl->ctx->app_verify_callback(&ctx, ssl->ctx->app_verify_arg);
+  } else {
+    verify_ret = X509_verify_cert(&ctx);
+  }
+
+  session->verify_result = ctx.error;
+
+  /* If |SSL_VERIFY_NONE|, the error is non-fatal, but we keep the result. */
+  if (verify_ret <= 0 && ssl->verify_mode != SSL_VERIFY_NONE) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, ssl_verify_alarm_type(ctx.error));
+    OPENSSL_PUT_ERROR(SSL, SSL_R_CERTIFICATE_VERIFY_FAILED);
+    goto err;
+  }
+
+  ERR_clear_error();
+  ret = 1;
+
+err:
+  X509_STORE_CTX_cleanup(&ctx);
+  return ret;
+}
+
+static void ssl_crypto_x509_hs_flush_cached_ca_names(SSL_HANDSHAKE *hs) {
+  sk_X509_NAME_pop_free(hs->cached_x509_ca_names, X509_NAME_free);
+  hs->cached_x509_ca_names = NULL;
+}
+
+static int ssl_crypto_x509_ssl_new(SSL *ssl) {
+  ssl->param = X509_VERIFY_PARAM_new();
+  if (ssl->param == NULL) {
+    return 0;
+  }
+  X509_VERIFY_PARAM_inherit(ssl->param, ssl->ctx->param);
+  return 1;
+}
+
+static void ssl_crypto_x509_ssl_flush_cached_client_CA(SSL *ssl) {
+  sk_X509_NAME_pop_free(ssl->cached_x509_client_CA, X509_NAME_free);
+  ssl->cached_x509_client_CA = NULL;
+}
+
+static void ssl_crypto_x509_ssl_free(SSL *ssl) {
+  ssl_crypto_x509_ssl_flush_cached_client_CA(ssl);
+  X509_VERIFY_PARAM_free(ssl->param);
+}
+
+static int ssl_crypto_x509_ssl_auto_chain_if_needed(SSL *ssl) {
+  /* Only build a chain if there are no intermediates configured and the feature
+   * isn't disabled. */
+  if ((ssl->mode & SSL_MODE_NO_AUTO_CHAIN) ||
+      !ssl_has_certificate(ssl) ||
+      ssl->cert->chain == NULL ||
+      sk_CRYPTO_BUFFER_num(ssl->cert->chain) > 1) {
+    return 1;
+  }
+
+  X509 *leaf =
+      X509_parse_from_buffer(sk_CRYPTO_BUFFER_value(ssl->cert->chain, 0));
+  if (!leaf) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_X509_LIB);
+    return 0;
+  }
+
+  X509_STORE_CTX ctx;
+  if (!X509_STORE_CTX_init(&ctx, ssl->ctx->cert_store, leaf, NULL)) {
+    X509_free(leaf);
+    OPENSSL_PUT_ERROR(SSL, ERR_R_X509_LIB);
+    return 0;
+  }
+
+  /* Attempt to build a chain, ignoring the result. */
+  X509_verify_cert(&ctx);
+  X509_free(leaf);
+  ERR_clear_error();
+
+  /* Remove the leaf from the generated chain. */
+  X509_free(sk_X509_shift(ctx.chain));
+
+  const int ok = ssl_cert_set_chain(ssl->cert, ctx.chain);
+  X509_STORE_CTX_cleanup(&ctx);
+  if (!ok) {
+    return 0;
+  }
+
+  ssl_crypto_x509_cert_flush_cached_chain(ssl->cert);
+
+  return 1;
+}
+
+static void ssl_crypto_x509_ssl_ctx_flush_cached_client_CA(SSL_CTX *ctx) {
+  sk_X509_NAME_pop_free(ctx->cached_x509_client_CA, X509_NAME_free);
+  ctx->cached_x509_client_CA = NULL;
+}
+
+static int ssl_crypto_x509_ssl_ctx_new(SSL_CTX *ctx) {
+  ctx->cert_store = X509_STORE_new();
+  ctx->param = X509_VERIFY_PARAM_new();
+  return (ctx->cert_store != NULL && ctx->param != NULL);
+}
+
+static void ssl_crypto_x509_ssl_ctx_free(SSL_CTX *ctx) {
+  ssl_crypto_x509_ssl_ctx_flush_cached_client_CA(ctx);
+  X509_VERIFY_PARAM_free(ctx->param);
+  X509_STORE_free(ctx->cert_store);
+}
+
+const SSL_X509_METHOD ssl_crypto_x509_method = {
+  ssl_crypto_x509_check_client_CA_list,
+  ssl_crypto_x509_cert_clear,
+  ssl_crypto_x509_cert_free,
+  ssl_crypto_x509_cert_dup,
+  ssl_crypto_x509_cert_flush_cached_chain,
+  ssl_crypto_x509_cert_flush_cached_leaf,
+  ssl_crypto_x509_session_cache_objects,
+  ssl_crypto_x509_session_dup,
+  ssl_crypto_x509_session_clear,
+  ssl_crypto_x509_session_verify_cert_chain,
+  ssl_crypto_x509_hs_flush_cached_ca_names,
+  ssl_crypto_x509_ssl_new,
+  ssl_crypto_x509_ssl_free,
+  ssl_crypto_x509_ssl_flush_cached_client_CA,
+  ssl_crypto_x509_ssl_auto_chain_if_needed,
+  ssl_crypto_x509_ssl_ctx_new,
+  ssl_crypto_x509_ssl_ctx_free,
+  ssl_crypto_x509_ssl_ctx_flush_cached_client_CA,
+};
+
+static int ssl_use_certificate(CERT *cert, X509 *x) {
+  if (x == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_PASSED_NULL_PARAMETER);
+    return 0;
+  }
+
+  CRYPTO_BUFFER *buffer = x509_to_buffer(x);
+  if (buffer == NULL) {
+    return 0;
+  }
+
+  const int ok = ssl_set_cert(cert, buffer);
+  CRYPTO_BUFFER_free(buffer);
+  return ok;
+}
+
+int SSL_use_certificate(SSL *ssl, X509 *x) {
+  check_ssl_x509_method(ssl);
+  return ssl_use_certificate(ssl->cert, x);
+}
+
+int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x) {
+  check_ssl_ctx_x509_method(ctx);
+  return ssl_use_certificate(ctx->cert, x);
+}
+
+/* ssl_cert_cache_leaf_cert sets |cert->x509_leaf|, if currently NULL, from the
+ * first element of |cert->chain|. */
+static int ssl_cert_cache_leaf_cert(CERT *cert) {
+  assert(cert->x509_method);
+
+  if (cert->x509_leaf != NULL ||
+      cert->chain == NULL) {
+    return 1;
+  }
+
+  CRYPTO_BUFFER *leaf = sk_CRYPTO_BUFFER_value(cert->chain, 0);
+  if (!leaf) {
+    return 1;
+  }
+
+  cert->x509_leaf = X509_parse_from_buffer(leaf);
+  return cert->x509_leaf != NULL;
+}
+
+static X509 *ssl_cert_get0_leaf(CERT *cert) {
+  if (cert->x509_leaf == NULL &&
+      !ssl_cert_cache_leaf_cert(cert)) {
+    return NULL;
+  }
+
+  return cert->x509_leaf;
+}
+
+X509 *SSL_get_certificate(const SSL *ssl) {
+  check_ssl_x509_method(ssl);
+  return ssl_cert_get0_leaf(ssl->cert);
+}
+
+X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx) {
+  check_ssl_ctx_x509_method(ctx);
+  CRYPTO_MUTEX_lock_write((CRYPTO_MUTEX *) &ctx->lock);
+  X509 *ret = ssl_cert_get0_leaf(ctx->cert);
+  CRYPTO_MUTEX_unlock_write((CRYPTO_MUTEX *) &ctx->lock);
+  return ret;
+}
+
+static int ssl_cert_set0_chain(CERT *cert, STACK_OF(X509) *chain) {
+  if (!ssl_cert_set_chain(cert, chain)) {
+    return 0;
+  }
+
+  sk_X509_pop_free(chain, X509_free);
+  ssl_crypto_x509_cert_flush_cached_chain(cert);
+  return 1;
+}
+
+static int ssl_cert_set1_chain(CERT *cert, STACK_OF(X509) *chain) {
+  if (!ssl_cert_set_chain(cert, chain)) {
+    return 0;
+  }
+
+  ssl_crypto_x509_cert_flush_cached_chain(cert);
+  return 1;
+}
+
+static int ssl_cert_append_cert(CERT *cert, X509 *x509) {
+  assert(cert->x509_method);
+
+  CRYPTO_BUFFER *buffer = x509_to_buffer(x509);
+  if (buffer == NULL) {
+    return 0;
+  }
+
+  if (cert->chain != NULL) {
+    if (!sk_CRYPTO_BUFFER_push(cert->chain, buffer)) {
+      CRYPTO_BUFFER_free(buffer);
+      return 0;
+    }
+
+    return 1;
+  }
+
+  cert->chain = new_leafless_chain();
+  if (cert->chain == NULL ||
+      !sk_CRYPTO_BUFFER_push(cert->chain, buffer)) {
+    CRYPTO_BUFFER_free(buffer);
+    sk_CRYPTO_BUFFER_free(cert->chain);
+    cert->chain = NULL;
+    return 0;
+  }
+
+  return 1;
+}
+
+static int ssl_cert_add0_chain_cert(CERT *cert, X509 *x509) {
+  if (!ssl_cert_append_cert(cert, x509)) {
+    return 0;
+  }
+
+  X509_free(cert->x509_stash);
+  cert->x509_stash = x509;
+  ssl_crypto_x509_cert_flush_cached_chain(cert);
+  return 1;
+}
+
+static int ssl_cert_add1_chain_cert(CERT *cert, X509 *x509) {
+  if (!ssl_cert_append_cert(cert, x509)) {
+    return 0;
+  }
+
+  ssl_crypto_x509_cert_flush_cached_chain(cert);
+  return 1;
+}
+
+int SSL_CTX_set0_chain(SSL_CTX *ctx, STACK_OF(X509) *chain) {
+  check_ssl_ctx_x509_method(ctx);
+  return ssl_cert_set0_chain(ctx->cert, chain);
+}
+
+int SSL_CTX_set1_chain(SSL_CTX *ctx, STACK_OF(X509) *chain) {
+  check_ssl_ctx_x509_method(ctx);
+  return ssl_cert_set1_chain(ctx->cert, chain);
+}
+
+int SSL_set0_chain(SSL *ssl, STACK_OF(X509) *chain) {
+  check_ssl_x509_method(ssl);
+  return ssl_cert_set0_chain(ssl->cert, chain);
+}
+
+int SSL_set1_chain(SSL *ssl, STACK_OF(X509) *chain) {
+  check_ssl_x509_method(ssl);
+  return ssl_cert_set1_chain(ssl->cert, chain);
+}
+
+int SSL_CTX_add0_chain_cert(SSL_CTX *ctx, X509 *x509) {
+  check_ssl_ctx_x509_method(ctx);
+  return ssl_cert_add0_chain_cert(ctx->cert, x509);
+}
+
+int SSL_CTX_add1_chain_cert(SSL_CTX *ctx, X509 *x509) {
+  check_ssl_ctx_x509_method(ctx);
+  return ssl_cert_add1_chain_cert(ctx->cert, x509);
+}
+
+int SSL_CTX_add_extra_chain_cert(SSL_CTX *ctx, X509 *x509) {
+  check_ssl_ctx_x509_method(ctx);
+  return SSL_CTX_add0_chain_cert(ctx, x509);
+}
+
+int SSL_add0_chain_cert(SSL *ssl, X509 *x509) {
+  check_ssl_x509_method(ssl);
+  return ssl_cert_add0_chain_cert(ssl->cert, x509);
+}
+
+int SSL_add1_chain_cert(SSL *ssl, X509 *x509) {
+  check_ssl_x509_method(ssl);
+  return ssl_cert_add1_chain_cert(ssl->cert, x509);
+}
+
+int SSL_CTX_clear_chain_certs(SSL_CTX *ctx) {
+  check_ssl_ctx_x509_method(ctx);
+  return SSL_CTX_set0_chain(ctx, NULL);
+}
+
+int SSL_CTX_clear_extra_chain_certs(SSL_CTX *ctx) {
+  check_ssl_ctx_x509_method(ctx);
+  return SSL_CTX_clear_chain_certs(ctx);
+}
+
+int SSL_clear_chain_certs(SSL *ssl) {
+  check_ssl_x509_method(ssl);
+  return SSL_set0_chain(ssl, NULL);
+}
+
+/* ssl_cert_cache_chain_certs fills in |cert->x509_chain| from elements 1.. of
+ * |cert->chain|. */
+static int ssl_cert_cache_chain_certs(CERT *cert) {
+  assert(cert->x509_method);
+
+  if (cert->x509_chain != NULL ||
+      cert->chain == NULL ||
+      sk_CRYPTO_BUFFER_num(cert->chain) < 2) {
+    return 1;
+  }
+
+  STACK_OF(X509) *chain = sk_X509_new_null();
+  if (chain == NULL) {
+    return 0;
+  }
+
+  for (size_t i = 1; i < sk_CRYPTO_BUFFER_num(cert->chain); i++) {
+    CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(cert->chain, i);
+    X509 *x509 = X509_parse_from_buffer(buffer);
+    if (x509 == NULL ||
+        !sk_X509_push(chain, x509)) {
+      X509_free(x509);
+      goto err;
+    }
+  }
+
+  cert->x509_chain = chain;
+  return 1;
+
+err:
+  sk_X509_pop_free(chain, X509_free);
+  return 0;
+}
+
+int SSL_CTX_get0_chain_certs(const SSL_CTX *ctx, STACK_OF(X509) **out_chain) {
+  check_ssl_ctx_x509_method(ctx);
+  CRYPTO_MUTEX_lock_write((CRYPTO_MUTEX *) &ctx->lock);
+  const int ret = ssl_cert_cache_chain_certs(ctx->cert);
+  CRYPTO_MUTEX_unlock_write((CRYPTO_MUTEX *) &ctx->lock);
+
+  if (!ret) {
+    *out_chain = NULL;
+    return 0;
+  }
+
+  *out_chain = ctx->cert->x509_chain;
+  return 1;
+}
+
+int SSL_CTX_get_extra_chain_certs(const SSL_CTX *ctx,
+                                  STACK_OF(X509) **out_chain) {
+  return SSL_CTX_get0_chain_certs(ctx, out_chain);
+}
+
+int SSL_get0_chain_certs(const SSL *ssl, STACK_OF(X509) **out_chain) {
+  check_ssl_x509_method(ssl);
+  if (!ssl_cert_cache_chain_certs(ssl->cert)) {
+    *out_chain = NULL;
+    return 0;
+  }
+
+  *out_chain = ssl->cert->x509_chain;
+  return 1;
+}
+
+static SSL_SESSION *ssl_session_new_with_crypto_x509(void) {
+  return ssl_session_new(&ssl_crypto_x509_method);
+}
+
+SSL_SESSION *d2i_SSL_SESSION_bio(BIO *bio, SSL_SESSION **out) {
+  return ASN1_d2i_bio_of(SSL_SESSION, ssl_session_new_with_crypto_x509,
+                         d2i_SSL_SESSION, bio, out);
+}
+
+int i2d_SSL_SESSION_bio(BIO *bio, const SSL_SESSION *session) {
+  return ASN1_i2d_bio_of(SSL_SESSION, i2d_SSL_SESSION, bio, session);
+}
+
+IMPLEMENT_PEM_rw(SSL_SESSION, SSL_SESSION, PEM_STRING_SSL_SESSION, SSL_SESSION)
+
+SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const uint8_t **pp, long length) {
+  if (length < 0) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    return NULL;
+  }
+
+  CBS cbs;
+  CBS_init(&cbs, *pp, length);
+
+  SSL_SESSION *ret = SSL_SESSION_parse(&cbs, &ssl_crypto_x509_method,
+                                       NULL /* no buffer pool */);
+  if (ret == NULL) {
+    return NULL;
+  }
+
+  if (a) {
+    SSL_SESSION_free(*a);
+    *a = ret;
+  }
+  *pp = CBS_data(&cbs);
+  return ret;
+}
+
+STACK_OF(X509_NAME) *SSL_dup_CA_list(STACK_OF(X509_NAME) *list) {
+  return sk_X509_NAME_deep_copy(list, X509_NAME_dup, X509_NAME_free);
+}
+
+static void set_client_CA_list(STACK_OF(CRYPTO_BUFFER) **ca_list,
+                               const STACK_OF(X509_NAME) *name_list,
+                               CRYPTO_BUFFER_POOL *pool) {
+  STACK_OF(CRYPTO_BUFFER) *buffers = sk_CRYPTO_BUFFER_new_null();
+  if (buffers == NULL) {
+    return;
+  }
+
+  for (size_t i = 0; i < sk_X509_NAME_num(name_list); i++) {
+    X509_NAME *name = sk_X509_NAME_value(name_list, i);
+    uint8_t *outp = NULL;
+    int len = i2d_X509_NAME(name, &outp);
+    if (len < 0) {
+      goto err;
+    }
+
+    CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new(outp, len, pool);
+    OPENSSL_free(outp);
+    if (buffer == NULL ||
+        !sk_CRYPTO_BUFFER_push(buffers, buffer)) {
+      CRYPTO_BUFFER_free(buffer);
+      goto err;
+    }
+  }
+
+  sk_CRYPTO_BUFFER_pop_free(*ca_list, CRYPTO_BUFFER_free);
+  *ca_list = buffers;
+  return;
+
+err:
+  sk_CRYPTO_BUFFER_pop_free(buffers, CRYPTO_BUFFER_free);
+}
+
+void SSL_set_client_CA_list(SSL *ssl, STACK_OF(X509_NAME) *name_list) {
+  check_ssl_x509_method(ssl);
+  ssl->ctx->x509_method->ssl_flush_cached_client_CA(ssl);
+  set_client_CA_list(&ssl->client_CA, name_list, ssl->ctx->pool);
+  sk_X509_NAME_pop_free(name_list, X509_NAME_free);
+}
+
+void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list) {
+  check_ssl_ctx_x509_method(ctx);
+  ctx->x509_method->ssl_ctx_flush_cached_client_CA(ctx);
+  set_client_CA_list(&ctx->client_CA, name_list, ctx->pool);
+  sk_X509_NAME_pop_free(name_list, X509_NAME_free);
+}
+
+static STACK_OF(X509_NAME) *
+    buffer_names_to_x509(const STACK_OF(CRYPTO_BUFFER) *names,
+                         STACK_OF(X509_NAME) **cached) {
+  if (names == NULL) {
+    return NULL;
+  }
+
+  if (*cached != NULL) {
+    return *cached;
+  }
+
+  STACK_OF(X509_NAME) *new_cache = sk_X509_NAME_new_null();
+  if (new_cache == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+    return NULL;
+  }
+
+  for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(names); i++) {
+    const CRYPTO_BUFFER *buffer = sk_CRYPTO_BUFFER_value(names, i);
+    const uint8_t *inp = CRYPTO_BUFFER_data(buffer);
+    X509_NAME *name = d2i_X509_NAME(NULL, &inp, CRYPTO_BUFFER_len(buffer));
+    if (name == NULL ||
+        inp != CRYPTO_BUFFER_data(buffer) + CRYPTO_BUFFER_len(buffer) ||
+        !sk_X509_NAME_push(new_cache, name)) {
+      X509_NAME_free(name);
+      goto err;
+    }
+  }
+
+  *cached = new_cache;
+  return new_cache;
+
+err:
+  sk_X509_NAME_pop_free(new_cache, X509_NAME_free);
+  return NULL;
+}
+
+STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *ssl) {
+  check_ssl_x509_method(ssl);
+  /* For historical reasons, this function is used both to query configuration
+   * state on a server as well as handshake state on a client. However, whether
+   * |ssl| is a client or server is not known until explicitly configured with
+   * |SSL_set_connect_state|. If |handshake_func| is NULL, |ssl| is in an
+   * indeterminate mode and |ssl->server| is unset. */
+  if (ssl->handshake_func != NULL && !ssl->server) {
+    if (ssl->s3->hs != NULL) {
+      return buffer_names_to_x509(ssl->s3->hs->ca_names,
+                                  &ssl->s3->hs->cached_x509_ca_names);
+    }
+
+    return NULL;
+  }
+
+  if (ssl->client_CA != NULL) {
+    return buffer_names_to_x509(
+        ssl->client_CA, (STACK_OF(X509_NAME) **)&ssl->cached_x509_client_CA);
+  }
+  return buffer_names_to_x509(ssl->ctx->client_CA,
+                              &ssl->ctx->cached_x509_client_CA);
+}
+
+STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *ctx) {
+  check_ssl_ctx_x509_method(ctx);
+  CRYPTO_MUTEX_lock_write((CRYPTO_MUTEX *) &ctx->lock);
+  STACK_OF(X509_NAME) *ret = buffer_names_to_x509(
+      ctx->client_CA, (STACK_OF(X509_NAME) **)&ctx->cached_x509_client_CA);
+  CRYPTO_MUTEX_unlock_write((CRYPTO_MUTEX *) &ctx->lock);
+  return ret;
+}
+
+static int add_client_CA(STACK_OF(CRYPTO_BUFFER) **names, X509 *x509,
+                         CRYPTO_BUFFER_POOL *pool) {
+  if (x509 == NULL) {
+    return 0;
+  }
+
+  uint8_t *outp = NULL;
+  int len = i2d_X509_NAME(X509_get_subject_name(x509), &outp);
+  if (len < 0) {
+    return 0;
+  }
+
+  CRYPTO_BUFFER *buffer = CRYPTO_BUFFER_new(outp, len, pool);
+  OPENSSL_free(outp);
+  if (buffer == NULL) {
+    return 0;
+  }
+
+  int alloced = 0;
+  if (*names == NULL) {
+    *names = sk_CRYPTO_BUFFER_new_null();
+    alloced = 1;
+
+    if (*names == NULL) {
+      CRYPTO_BUFFER_free(buffer);
+      return 0;
+    }
+  }
+
+  if (!sk_CRYPTO_BUFFER_push(*names, buffer)) {
+    CRYPTO_BUFFER_free(buffer);
+    if (alloced) {
+      sk_CRYPTO_BUFFER_pop_free(*names, CRYPTO_BUFFER_free);
+      *names = NULL;
+    }
+    return 0;
+  }
+
+  return 1;
+}
+
+int SSL_add_client_CA(SSL *ssl, X509 *x509) {
+  check_ssl_x509_method(ssl);
+  if (!add_client_CA(&ssl->client_CA, x509, ssl->ctx->pool)) {
+    return 0;
+  }
+
+  ssl_crypto_x509_ssl_flush_cached_client_CA(ssl);
+  return 1;
+}
+
+int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x509) {
+  check_ssl_ctx_x509_method(ctx);
+  if (!add_client_CA(&ctx->client_CA, x509, ctx->pool)) {
+    return 0;
+  }
+
+  ssl_crypto_x509_ssl_ctx_flush_cached_client_CA(ctx);
+  return 1;
+}
+
+static int do_client_cert_cb(SSL *ssl, void *arg) {
+  if (ssl_has_certificate(ssl) || ssl->ctx->client_cert_cb == NULL) {
+    return 1;
+  }
+
+  X509 *x509 = NULL;
+  EVP_PKEY *pkey = NULL;
+  int ret = ssl->ctx->client_cert_cb(ssl, &x509, &pkey);
+  if (ret < 0) {
+    return -1;
+  }
+
+  if (ret != 0) {
+    if (!SSL_use_certificate(ssl, x509) ||
+        !SSL_use_PrivateKey(ssl, pkey)) {
+      return 0;
+    }
+  }
+
+  X509_free(x509);
+  EVP_PKEY_free(pkey);
+  return 1;
+}
+
+void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx, int (*cb)(SSL *ssl,
+                                                        X509 **out_x509,
+                                                        EVP_PKEY **out_pkey)) {
+  check_ssl_ctx_x509_method(ctx);
+  /* Emulate the old client certificate callback with the new one. */
+  SSL_CTX_set_cert_cb(ctx, do_client_cert_cb, NULL);
+  ctx->client_cert_cb = cb;
+}
+
+static int set_cert_store(X509_STORE **store_ptr, X509_STORE *new_store,
+                          int take_ref) {
+  X509_STORE_free(*store_ptr);
+  *store_ptr = new_store;
+
+  if (new_store != NULL && take_ref) {
+    X509_STORE_up_ref(new_store);
+  }
+
+  return 1;
+}
+
+int SSL_get_ex_data_X509_STORE_CTX_idx(void) {
+  /* The ex_data index to go from |X509_STORE_CTX| to |SSL| always uses the
+   * reserved app_data slot. Before ex_data was introduced, app_data was used.
+   * Avoid breaking any software which assumes |X509_STORE_CTX_get_app_data|
+   * works. */
+  return 0;
+}
+
+int SSL_CTX_set0_verify_cert_store(SSL_CTX *ctx, X509_STORE *store) {
+  check_ssl_ctx_x509_method(ctx);
+  return set_cert_store(&ctx->cert->verify_store, store, 0);
+}
+
+int SSL_CTX_set1_verify_cert_store(SSL_CTX *ctx, X509_STORE *store) {
+  check_ssl_ctx_x509_method(ctx);
+  return set_cert_store(&ctx->cert->verify_store, store, 1);
+}
+
+int SSL_set0_verify_cert_store(SSL *ssl, X509_STORE *store) {
+  check_ssl_x509_method(ssl);
+  return set_cert_store(&ssl->cert->verify_store, store, 0);
+}
+
+int SSL_set1_verify_cert_store(SSL *ssl, X509_STORE *store) {
+  check_ssl_x509_method(ssl);
+  return set_cert_store(&ssl->cert->verify_store, store, 1);
+}
diff --git a/src/ssl/t1_enc.c b/src/ssl/t1_enc.c
index 0f1d683..9f11e05 100644
--- a/src/ssl/t1_enc.c
+++ b/src/ssl/t1_enc.c
@@ -136,7 +136,6 @@
 #include <openssl/ssl.h>
 
 #include <assert.h>
-#include <stdio.h>
 #include <string.h>
 
 #include <openssl/err.h>
@@ -144,9 +143,10 @@
 #include <openssl/hmac.h>
 #include <openssl/md5.h>
 #include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
 #include <openssl/rand.h>
 
+#include "../crypto/internal.h"
 #include "internal.h"
 
 
@@ -224,19 +224,17 @@
   return ret;
 }
 
-int tls1_prf(SSL *ssl, uint8_t *out, size_t out_len, const uint8_t *secret,
-             size_t secret_len, const char *label, size_t label_len,
-             const uint8_t *seed1, size_t seed1_len,
+int tls1_prf(const EVP_MD *digest, uint8_t *out, size_t out_len,
+             const uint8_t *secret, size_t secret_len, const char *label,
+             size_t label_len, const uint8_t *seed1, size_t seed1_len,
              const uint8_t *seed2, size_t seed2_len) {
-
   if (out_len == 0) {
     return 1;
   }
 
-  memset(out, 0, out_len);
+  OPENSSL_memset(out, 0, out_len);
 
-  uint32_t algorithm_prf = ssl_get_algorithm_prf(ssl);
-  if (algorithm_prf == SSL_HANDSHAKE_MAC_DEFAULT) {
+  if (digest == EVP_md5_sha1()) {
     /* If using the MD5/SHA1 PRF, |secret| is partitioned between SHA-1 and
      * MD5, MD5 first. */
     size_t secret_half = secret_len - (secret_len / 2);
@@ -249,26 +247,147 @@
     /* Note that, if |secret_len| is odd, the two halves share a byte. */
     secret = secret + (secret_len - secret_half);
     secret_len = secret_half;
+
+    digest = EVP_sha1();
   }
 
-  if (!tls1_P_hash(out, out_len, ssl_get_handshake_digest(algorithm_prf),
-                   secret, secret_len, (const uint8_t *)label, label_len,
-                   seed1, seed1_len, seed2, seed2_len)) {
+  if (!tls1_P_hash(out, out_len, digest, secret, secret_len,
+                   (const uint8_t *)label, label_len, seed1, seed1_len, seed2,
+                   seed2_len)) {
     return 0;
   }
 
   return 1;
 }
 
-static int tls1_generate_key_block(SSL *ssl, uint8_t *out, size_t out_len) {
-  return ssl->enc_method->prf(
-      ssl, out, out_len, ssl->session->master_key,
-      ssl->session->master_key_length, TLS_MD_KEY_EXPANSION_CONST,
-      TLS_MD_KEY_EXPANSION_CONST_SIZE, ssl->s3->server_random, SSL3_RANDOM_SIZE,
-      ssl->s3->client_random, SSL3_RANDOM_SIZE);
+static int ssl3_prf(uint8_t *out, size_t out_len, const uint8_t *secret,
+                    size_t secret_len, const char *label, size_t label_len,
+                    const uint8_t *seed1, size_t seed1_len,
+                    const uint8_t *seed2, size_t seed2_len) {
+  EVP_MD_CTX md5;
+  EVP_MD_CTX sha1;
+  uint8_t buf[16], smd[SHA_DIGEST_LENGTH];
+  uint8_t c = 'A';
+  size_t i, j, k;
+
+  k = 0;
+  EVP_MD_CTX_init(&md5);
+  EVP_MD_CTX_init(&sha1);
+  for (i = 0; i < out_len; i += MD5_DIGEST_LENGTH) {
+    k++;
+    if (k > sizeof(buf)) {
+      /* bug: 'buf' is too small for this ciphersuite */
+      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+      return 0;
+    }
+
+    for (j = 0; j < k; j++) {
+      buf[j] = c;
+    }
+    c++;
+    if (!EVP_DigestInit_ex(&sha1, EVP_sha1(), NULL)) {
+      OPENSSL_PUT_ERROR(SSL, ERR_LIB_EVP);
+      return 0;
+    }
+    EVP_DigestUpdate(&sha1, buf, k);
+    EVP_DigestUpdate(&sha1, secret, secret_len);
+    /* |label| is ignored for SSLv3. */
+    if (seed1_len) {
+      EVP_DigestUpdate(&sha1, seed1, seed1_len);
+    }
+    if (seed2_len) {
+      EVP_DigestUpdate(&sha1, seed2, seed2_len);
+    }
+    EVP_DigestFinal_ex(&sha1, smd, NULL);
+
+    if (!EVP_DigestInit_ex(&md5, EVP_md5(), NULL)) {
+      OPENSSL_PUT_ERROR(SSL, ERR_LIB_EVP);
+      return 0;
+    }
+    EVP_DigestUpdate(&md5, secret, secret_len);
+    EVP_DigestUpdate(&md5, smd, SHA_DIGEST_LENGTH);
+    if (i + MD5_DIGEST_LENGTH > out_len) {
+      EVP_DigestFinal_ex(&md5, smd, NULL);
+      OPENSSL_memcpy(out, smd, out_len - i);
+    } else {
+      EVP_DigestFinal_ex(&md5, out, NULL);
+    }
+
+    out += MD5_DIGEST_LENGTH;
+  }
+
+  OPENSSL_cleanse(smd, SHA_DIGEST_LENGTH);
+  EVP_MD_CTX_cleanup(&md5);
+  EVP_MD_CTX_cleanup(&sha1);
+
+  return 1;
 }
 
-int tls1_change_cipher_state(SSL *ssl, int which) {
+static int tls1_setup_key_block(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  if (hs->key_block_len != 0) {
+    return 1;
+  }
+
+  SSL_SESSION *session = ssl->session;
+  if (hs->new_session != NULL) {
+    session = hs->new_session;
+  }
+
+  const EVP_AEAD *aead = NULL;
+  size_t mac_secret_len, fixed_iv_len;
+  if (session->cipher == NULL ||
+      !ssl_cipher_get_evp_aead(&aead, &mac_secret_len, &fixed_iv_len,
+                               session->cipher, ssl3_protocol_version(ssl))) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
+    return 0;
+  }
+  size_t key_len = EVP_AEAD_key_length(aead);
+  if (mac_secret_len > 0) {
+    /* For "stateful" AEADs (i.e. compatibility with pre-AEAD cipher suites) the
+     * key length reported by |EVP_AEAD_key_length| will include the MAC key
+     * bytes and initial implicit IV. */
+    if (key_len < mac_secret_len + fixed_iv_len) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+      return 0;
+    }
+    key_len -= mac_secret_len + fixed_iv_len;
+  }
+
+  assert(mac_secret_len < 256);
+  assert(key_len < 256);
+  assert(fixed_iv_len < 256);
+
+  ssl->s3->tmp.new_mac_secret_len = (uint8_t)mac_secret_len;
+  ssl->s3->tmp.new_key_len = (uint8_t)key_len;
+  ssl->s3->tmp.new_fixed_iv_len = (uint8_t)fixed_iv_len;
+
+  size_t key_block_len = SSL_get_key_block_len(ssl);
+
+  uint8_t *keyblock = OPENSSL_malloc(key_block_len);
+  if (keyblock == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+    return 0;
+  }
+
+  if (!SSL_generate_key_block(ssl, keyblock, key_block_len)) {
+    OPENSSL_free(keyblock);
+    return 0;
+  }
+
+  assert(key_block_len < 256);
+  hs->key_block_len = (uint8_t)key_block_len;
+  hs->key_block = keyblock;
+  return 1;
+}
+
+int tls1_change_cipher_state(SSL_HANDSHAKE *hs, int which) {
+  SSL *const ssl = hs->ssl;
+  /* Ensure the key block is set up. */
+  if (!tls1_setup_key_block(hs)) {
+    return 0;
+  }
+
   /* is_read is true if we have just read a ChangeCipherSpec message - i.e. we
    * need to update the read cipherspec. Otherwise we have just written one. */
   const char is_read = (which & SSL3_CC_READ) != 0;
@@ -277,63 +396,27 @@
    * or a server reading a client's ChangeCipherSpec. */
   const char use_client_keys = which == SSL3_CHANGE_CIPHER_CLIENT_WRITE ||
                                which == SSL3_CHANGE_CIPHER_SERVER_READ;
-  const uint8_t *client_write_mac_secret, *server_write_mac_secret, *mac_secret;
-  const uint8_t *client_write_key, *server_write_key, *key;
-  const uint8_t *client_write_iv, *server_write_iv, *iv;
-  const EVP_AEAD *aead = ssl->s3->tmp.new_aead;
-  size_t key_len, iv_len, mac_secret_len;
-  const uint8_t *key_data;
 
-  /* Reset sequence number to zero. */
-  if (is_read) {
-    if (SSL_IS_DTLS(ssl)) {
-      ssl->d1->r_epoch++;
-      memset(&ssl->d1->bitmap, 0, sizeof(ssl->d1->bitmap));
-    }
-    memset(ssl->s3->read_sequence, 0, sizeof(ssl->s3->read_sequence));
-  } else {
-    if (SSL_IS_DTLS(ssl)) {
-      ssl->d1->w_epoch++;
-      memcpy(ssl->d1->last_write_sequence, ssl->s3->write_sequence,
-             sizeof(ssl->s3->write_sequence));
-    }
-    memset(ssl->s3->write_sequence, 0, sizeof(ssl->s3->write_sequence));
-  }
+  size_t mac_secret_len = ssl->s3->tmp.new_mac_secret_len;
+  size_t key_len = ssl->s3->tmp.new_key_len;
+  size_t iv_len = ssl->s3->tmp.new_fixed_iv_len;
+  assert((mac_secret_len + key_len + iv_len) * 2 == hs->key_block_len);
 
-  mac_secret_len = ssl->s3->tmp.new_mac_secret_len;
-  iv_len = ssl->s3->tmp.new_fixed_iv_len;
-
-  if (aead == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    return 0;
-  }
-
-  key_len = EVP_AEAD_key_length(aead);
-  if (mac_secret_len > 0) {
-    /* For "stateful" AEADs (i.e. compatibility with pre-AEAD cipher
-     * suites) the key length reported by |EVP_AEAD_key_length| will
-     * include the MAC and IV key bytes. */
-    if (key_len < mac_secret_len + iv_len) {
-      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-      return 0;
-    }
-    key_len -= mac_secret_len + iv_len;
-  }
-
-  key_data = ssl->s3->tmp.key_block;
-  client_write_mac_secret = key_data;
+  const uint8_t *key_data = hs->key_block;
+  const uint8_t *client_write_mac_secret = key_data;
   key_data += mac_secret_len;
-  server_write_mac_secret = key_data;
+  const uint8_t *server_write_mac_secret = key_data;
   key_data += mac_secret_len;
-  client_write_key = key_data;
+  const uint8_t *client_write_key = key_data;
   key_data += key_len;
-  server_write_key = key_data;
+  const uint8_t *server_write_key = key_data;
   key_data += key_len;
-  client_write_iv = key_data;
+  const uint8_t *client_write_iv = key_data;
   key_data += iv_len;
-  server_write_iv = key_data;
+  const uint8_t *server_write_iv = key_data;
   key_data += iv_len;
 
+  const uint8_t *mac_secret, *key, *iv;
   if (use_client_keys) {
     mac_secret = client_write_mac_secret;
     key = client_write_key;
@@ -344,241 +427,103 @@
     iv = server_write_iv;
   }
 
-  if (key_data - ssl->s3->tmp.key_block != ssl->s3->tmp.key_block_length) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+  SSL_AEAD_CTX *aead_ctx = SSL_AEAD_CTX_new(
+      is_read ? evp_aead_open : evp_aead_seal, ssl3_protocol_version(ssl),
+      hs->new_cipher, key, key_len, mac_secret, mac_secret_len, iv, iv_len);
+  if (aead_ctx == NULL) {
     return 0;
   }
 
   if (is_read) {
-    SSL_AEAD_CTX_free(ssl->aead_read_ctx);
-    ssl->aead_read_ctx = SSL_AEAD_CTX_new(
-        evp_aead_open, ssl3_version_from_wire(ssl, ssl->version),
-        ssl->s3->tmp.new_cipher, key, key_len, mac_secret, mac_secret_len, iv,
-        iv_len);
-    return ssl->aead_read_ctx != NULL;
+    return ssl->method->set_read_state(ssl, aead_ctx);
   }
 
-  SSL_AEAD_CTX_free(ssl->aead_write_ctx);
-  ssl->aead_write_ctx = SSL_AEAD_CTX_new(
-      evp_aead_seal, ssl3_version_from_wire(ssl, ssl->version),
-      ssl->s3->tmp.new_cipher, key, key_len, mac_secret, mac_secret_len, iv,
-      iv_len);
-  return ssl->aead_write_ctx != NULL;
+  return ssl->method->set_write_state(ssl, aead_ctx);
 }
 
-int tls1_setup_key_block(SSL *ssl) {
-  uint8_t *p;
-  const EVP_AEAD *aead = NULL;
-  int ret = 0;
-  size_t mac_secret_len, fixed_iv_len, variable_iv_len, key_len;
-  size_t key_block_len;
-
-  if (ssl->s3->tmp.key_block_length != 0) {
-    return 1;
-  }
-
-  if (ssl->session->cipher == NULL) {
-    goto cipher_unavailable_err;
-  }
-
-  if (!ssl_cipher_get_evp_aead(&aead, &mac_secret_len, &fixed_iv_len,
-                               ssl->session->cipher,
-                               ssl3_version_from_wire(ssl, ssl->version))) {
-    goto cipher_unavailable_err;
-  }
-  key_len = EVP_AEAD_key_length(aead);
-  variable_iv_len = EVP_AEAD_nonce_length(aead);
-  if (mac_secret_len > 0) {
-    /* For "stateful" AEADs (i.e. compatibility with pre-AEAD cipher suites) the
-     * key length reported by |EVP_AEAD_key_length| will include the MAC key
-     * bytes and initial implicit IV. */
-    if (key_len < mac_secret_len + fixed_iv_len) {
-      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-      return 0;
-    }
-    key_len -= mac_secret_len + fixed_iv_len;
-  } else {
-    /* The nonce is split into a fixed portion and a variable portion. */
-    if (variable_iv_len < fixed_iv_len) {
-      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-      return 0;
-    }
-    variable_iv_len -= fixed_iv_len;
-  }
-
-  assert(mac_secret_len < 256);
-  assert(fixed_iv_len < 256);
-  assert(variable_iv_len < 256);
-
-  ssl->s3->tmp.new_aead = aead;
-  ssl->s3->tmp.new_mac_secret_len = (uint8_t)mac_secret_len;
-  ssl->s3->tmp.new_fixed_iv_len = (uint8_t)fixed_iv_len;
-  ssl->s3->tmp.new_variable_iv_len = (uint8_t)variable_iv_len;
-
-  key_block_len = key_len + mac_secret_len + fixed_iv_len;
-  key_block_len *= 2;
-
-  ssl3_cleanup_key_block(ssl);
-
-  p = (uint8_t *)OPENSSL_malloc(key_block_len);
-  if (p == NULL) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
-    goto err;
-  }
-
-  ssl->s3->tmp.key_block_length = key_block_len;
-  ssl->s3->tmp.key_block = p;
-
-  if (!tls1_generate_key_block(ssl, p, key_block_len)) {
-    goto err;
-  }
-
-  ret = 1;
-
-err:
-  return ret;
-
-cipher_unavailable_err:
-  OPENSSL_PUT_ERROR(SSL, SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
-  return 0;
+size_t SSL_get_key_block_len(const SSL *ssl) {
+  return 2 * ((size_t)ssl->s3->tmp.new_mac_secret_len +
+              (size_t)ssl->s3->tmp.new_key_len +
+              (size_t)ssl->s3->tmp.new_fixed_iv_len);
 }
 
-int tls1_cert_verify_mac(SSL *ssl, int md_nid, uint8_t *out) {
-  const EVP_MD_CTX *ctx_template;
-  if (md_nid == NID_md5) {
-    ctx_template = &ssl->s3->handshake_md5;
-  } else if (md_nid == EVP_MD_CTX_type(&ssl->s3->handshake_hash)) {
-    ctx_template = &ssl->s3->handshake_hash;
-  } else {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_NO_REQUIRED_DIGEST);
+int SSL_generate_key_block(const SSL *ssl, uint8_t *out, size_t out_len) {
+  if (ssl3_protocol_version(ssl) == SSL3_VERSION) {
+    return ssl3_prf(out, out_len, SSL_get_session(ssl)->master_key,
+                    SSL_get_session(ssl)->master_key_length,
+                    TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE,
+                    ssl->s3->server_random, SSL3_RANDOM_SIZE,
+                    ssl->s3->client_random, SSL3_RANDOM_SIZE);
+  }
+
+  const EVP_MD *digest = ssl_get_handshake_digest(
+      SSL_get_session(ssl)->cipher->algorithm_prf, ssl3_protocol_version(ssl));
+  if (digest == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
     return 0;
   }
-
-  EVP_MD_CTX ctx;
-  EVP_MD_CTX_init(&ctx);
-  if (!EVP_MD_CTX_copy_ex(&ctx, ctx_template)) {
-    EVP_MD_CTX_cleanup(&ctx);
-    return 0;
-  }
-  unsigned ret;
-  EVP_DigestFinal_ex(&ctx, out, &ret);
-  EVP_MD_CTX_cleanup(&ctx);
-  return ret;
+  return tls1_prf(digest, out, out_len, SSL_get_session(ssl)->master_key,
+                  SSL_get_session(ssl)->master_key_length,
+                  TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE,
+                  ssl->s3->server_random, SSL3_RANDOM_SIZE,
+                  ssl->s3->client_random, SSL3_RANDOM_SIZE);
 }
 
-static int append_digest(const EVP_MD_CTX *ctx, uint8_t *out, size_t *out_len,
-                         size_t max_out) {
-  int ret = 0;
-  EVP_MD_CTX ctx_copy;
-  EVP_MD_CTX_init(&ctx_copy);
-
-  if (EVP_MD_CTX_size(ctx) > max_out) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL);
-    goto err;
-  }
-  unsigned len;
-  if (!EVP_MD_CTX_copy_ex(&ctx_copy, ctx) ||
-      !EVP_DigestFinal_ex(&ctx_copy, out, &len)) {
-    goto err;
-  }
-  assert(len == EVP_MD_CTX_size(ctx));
-
-  *out_len = len;
-  ret = 1;
-
-err:
-  EVP_MD_CTX_cleanup(&ctx_copy);
-  return ret;
-}
-
-/* tls1_handshake_digest calculates the current handshake hash and writes it to
- * |out|, which has space for |out_len| bytes. It returns the number of bytes
- * written or -1 in the event of an error. This function works on a copy of the
- * underlying digests so can be called multiple times and prior to the final
- * update etc. */
-int tls1_handshake_digest(SSL *ssl, uint8_t *out, size_t out_len) {
-  size_t md5_len = 0;
-  if (EVP_MD_CTX_md(&ssl->s3->handshake_md5) != NULL &&
-      !append_digest(&ssl->s3->handshake_md5, out, &md5_len, out_len)) {
-    return -1;
-  }
-
-  size_t len;
-  if (!append_digest(&ssl->s3->handshake_hash, out + md5_len, &len,
-                     out_len - md5_len)) {
-    return -1;
-  }
-
-  return (int)(md5_len + len);
-}
-
-int tls1_final_finish_mac(SSL *ssl, const char *str, int slen, uint8_t *out) {
-  uint8_t buf[2 * EVP_MAX_MD_SIZE];
-  int err = 0;
-  int digests_len;
-
-  /* At this point, the handshake should have released the handshake buffer on
-   * its own. */
-  assert(ssl->s3->handshake_buffer == NULL);
-
-  digests_len = tls1_handshake_digest(ssl, buf, sizeof(buf));
-  if (digests_len < 0) {
-    err = 1;
-    digests_len = 0;
-  }
-
-  if (!ssl->enc_method->prf(ssl, out, 12, ssl->session->master_key,
-                            ssl->session->master_key_length, str, slen, buf,
-                            digests_len, NULL, 0)) {
-    err = 1;
-  }
-
-  if (err) {
-    return 0;
-  } else {
-    return 12;
-  }
-}
-
-int tls1_generate_master_secret(SSL *ssl, uint8_t *out,
+int tls1_generate_master_secret(SSL_HANDSHAKE *hs, uint8_t *out,
                                 const uint8_t *premaster,
                                 size_t premaster_len) {
-  if (ssl->s3->tmp.extended_master_secret) {
-    uint8_t digests[2 * EVP_MAX_MD_SIZE];
-    int digests_len = tls1_handshake_digest(ssl, digests, sizeof(digests));
-    if (digests_len == -1) {
-      return 0;
-    }
-
-    if (!ssl->enc_method->prf(ssl, out, SSL3_MASTER_SECRET_SIZE, premaster,
-                              premaster_len,
-                              TLS_MD_EXTENDED_MASTER_SECRET_CONST,
-                              TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE, digests,
-                              digests_len, NULL, 0)) {
+  const SSL *ssl = hs->ssl;
+  if (hs->extended_master_secret) {
+    uint8_t digests[EVP_MAX_MD_SIZE];
+    size_t digests_len;
+    if (!SSL_TRANSCRIPT_get_hash(&hs->transcript, digests, &digests_len) ||
+        !tls1_prf(SSL_TRANSCRIPT_md(&hs->transcript), out,
+                  SSL3_MASTER_SECRET_SIZE, premaster, premaster_len,
+                  TLS_MD_EXTENDED_MASTER_SECRET_CONST,
+                  TLS_MD_EXTENDED_MASTER_SECRET_CONST_SIZE, digests,
+                  digests_len, NULL, 0)) {
       return 0;
     }
   } else {
-    if (!ssl->enc_method->prf(ssl, out, SSL3_MASTER_SECRET_SIZE, premaster,
-                              premaster_len, TLS_MD_MASTER_SECRET_CONST,
-                              TLS_MD_MASTER_SECRET_CONST_SIZE,
-                              ssl->s3->client_random, SSL3_RANDOM_SIZE,
-                              ssl->s3->server_random, SSL3_RANDOM_SIZE)) {
-      return 0;
+    if (ssl3_protocol_version(ssl) == SSL3_VERSION) {
+      if (!ssl3_prf(out, SSL3_MASTER_SECRET_SIZE, premaster, premaster_len,
+                    TLS_MD_MASTER_SECRET_CONST, TLS_MD_MASTER_SECRET_CONST_SIZE,
+                    ssl->s3->client_random, SSL3_RANDOM_SIZE,
+                    ssl->s3->server_random, SSL3_RANDOM_SIZE)) {
+        return 0;
+      }
+    } else {
+      if (!tls1_prf(SSL_TRANSCRIPT_md(&hs->transcript), out,
+                    SSL3_MASTER_SECRET_SIZE, premaster, premaster_len,
+                    TLS_MD_MASTER_SECRET_CONST, TLS_MD_MASTER_SECRET_CONST_SIZE,
+                    ssl->s3->client_random, SSL3_RANDOM_SIZE,
+                    ssl->s3->server_random, SSL3_RANDOM_SIZE)) {
+        return 0;
+      }
     }
   }
 
   return SSL3_MASTER_SECRET_SIZE;
 }
 
-int tls1_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len,
-                                const char *label, size_t label_len,
-                                const uint8_t *context, size_t context_len,
-                                int use_context) {
+int SSL_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len,
+                               const char *label, size_t label_len,
+                               const uint8_t *context, size_t context_len,
+                               int use_context) {
   if (!ssl->s3->have_version || ssl->version == SSL3_VERSION) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
     return 0;
   }
 
+  /* Exporters may not be used in the middle of a renegotiation. */
+  if (SSL_in_init(ssl) && !SSL_in_false_start(ssl)) {
+    return 0;
+  }
+
+  if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
+    return tls13_export_keying_material(ssl, out, out_len, label, label_len,
+                                        context, context_len, use_context);
+  }
+
   size_t seed_len = 2 * SSL3_RANDOM_SIZE;
   if (use_context) {
     if (context_len >= 1u << 16) {
@@ -593,116 +538,24 @@
     return 0;
   }
 
-  memcpy(seed, ssl->s3->client_random, SSL3_RANDOM_SIZE);
-  memcpy(seed + SSL3_RANDOM_SIZE, ssl->s3->server_random, SSL3_RANDOM_SIZE);
+  OPENSSL_memcpy(seed, ssl->s3->client_random, SSL3_RANDOM_SIZE);
+  OPENSSL_memcpy(seed + SSL3_RANDOM_SIZE, ssl->s3->server_random,
+                 SSL3_RANDOM_SIZE);
   if (use_context) {
     seed[2 * SSL3_RANDOM_SIZE] = (uint8_t)(context_len >> 8);
     seed[2 * SSL3_RANDOM_SIZE + 1] = (uint8_t)context_len;
-    memcpy(seed + 2 * SSL3_RANDOM_SIZE + 2, context, context_len);
+    OPENSSL_memcpy(seed + 2 * SSL3_RANDOM_SIZE + 2, context, context_len);
   }
 
-  int ret = ssl->enc_method->prf(ssl, out, out_len, ssl->session->master_key,
-                                 ssl->session->master_key_length, label,
-                                 label_len, seed, seed_len, NULL, 0);
+  const EVP_MD *digest = ssl_get_handshake_digest(
+      SSL_get_session(ssl)->cipher->algorithm_prf, ssl3_protocol_version(ssl));
+  if (digest == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    return 0;
+  }
+  int ret = tls1_prf(digest, out, out_len, SSL_get_session(ssl)->master_key,
+                     SSL_get_session(ssl)->master_key_length, label, label_len,
+                     seed, seed_len, NULL, 0);
   OPENSSL_free(seed);
   return ret;
 }
-
-int tls1_alert_code(int code) {
-  switch (code) {
-    case SSL_AD_CLOSE_NOTIFY:
-      return SSL3_AD_CLOSE_NOTIFY;
-
-    case SSL_AD_UNEXPECTED_MESSAGE:
-      return SSL3_AD_UNEXPECTED_MESSAGE;
-
-    case SSL_AD_BAD_RECORD_MAC:
-      return SSL3_AD_BAD_RECORD_MAC;
-
-    case SSL_AD_DECRYPTION_FAILED:
-      return TLS1_AD_DECRYPTION_FAILED;
-
-    case SSL_AD_RECORD_OVERFLOW:
-      return TLS1_AD_RECORD_OVERFLOW;
-
-    case SSL_AD_DECOMPRESSION_FAILURE:
-      return SSL3_AD_DECOMPRESSION_FAILURE;
-
-    case SSL_AD_HANDSHAKE_FAILURE:
-      return SSL3_AD_HANDSHAKE_FAILURE;
-
-    case SSL_AD_NO_CERTIFICATE:
-      return -1;
-
-    case SSL_AD_BAD_CERTIFICATE:
-      return SSL3_AD_BAD_CERTIFICATE;
-
-    case SSL_AD_UNSUPPORTED_CERTIFICATE:
-      return SSL3_AD_UNSUPPORTED_CERTIFICATE;
-
-    case SSL_AD_CERTIFICATE_REVOKED:
-      return SSL3_AD_CERTIFICATE_REVOKED;
-
-    case SSL_AD_CERTIFICATE_EXPIRED:
-      return SSL3_AD_CERTIFICATE_EXPIRED;
-
-    case SSL_AD_CERTIFICATE_UNKNOWN:
-      return SSL3_AD_CERTIFICATE_UNKNOWN;
-
-    case SSL_AD_ILLEGAL_PARAMETER:
-      return SSL3_AD_ILLEGAL_PARAMETER;
-
-    case SSL_AD_UNKNOWN_CA:
-      return TLS1_AD_UNKNOWN_CA;
-
-    case SSL_AD_ACCESS_DENIED:
-      return TLS1_AD_ACCESS_DENIED;
-
-    case SSL_AD_DECODE_ERROR:
-      return TLS1_AD_DECODE_ERROR;
-
-    case SSL_AD_DECRYPT_ERROR:
-      return TLS1_AD_DECRYPT_ERROR;
-    case SSL_AD_EXPORT_RESTRICTION:
-      return TLS1_AD_EXPORT_RESTRICTION;
-
-    case SSL_AD_PROTOCOL_VERSION:
-      return TLS1_AD_PROTOCOL_VERSION;
-
-    case SSL_AD_INSUFFICIENT_SECURITY:
-      return TLS1_AD_INSUFFICIENT_SECURITY;
-
-    case SSL_AD_INTERNAL_ERROR:
-      return TLS1_AD_INTERNAL_ERROR;
-
-    case SSL_AD_USER_CANCELLED:
-      return TLS1_AD_USER_CANCELLED;
-
-    case SSL_AD_NO_RENEGOTIATION:
-      return TLS1_AD_NO_RENEGOTIATION;
-
-    case SSL_AD_UNSUPPORTED_EXTENSION:
-      return TLS1_AD_UNSUPPORTED_EXTENSION;
-
-    case SSL_AD_CERTIFICATE_UNOBTAINABLE:
-      return TLS1_AD_CERTIFICATE_UNOBTAINABLE;
-
-    case SSL_AD_UNRECOGNIZED_NAME:
-      return TLS1_AD_UNRECOGNIZED_NAME;
-
-    case SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE:
-      return TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE;
-
-    case SSL_AD_BAD_CERTIFICATE_HASH_VALUE:
-      return TLS1_AD_BAD_CERTIFICATE_HASH_VALUE;
-
-    case SSL_AD_UNKNOWN_PSK_IDENTITY:
-      return TLS1_AD_UNKNOWN_PSK_IDENTITY;
-
-    case SSL_AD_INAPPROPRIATE_FALLBACK:
-      return SSL3_AD_INAPPROPRIATE_FALLBACK;
-
-    default:
-      return -1;
-  }
-}
diff --git a/src/ssl/t1_lib.c b/src/ssl/t1_lib.c
index 5aea08b..014432e 100644
--- a/src/ssl/t1_lib.c
+++ b/src/ssl/t1_lib.c
@@ -110,7 +110,6 @@
 
 #include <assert.h>
 #include <limits.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -120,57 +119,15 @@
 #include <openssl/evp.h>
 #include <openssl/hmac.h>
 #include <openssl/mem.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
 #include <openssl/rand.h>
 #include <openssl/type_check.h>
 
 #include "internal.h"
+#include "../crypto/internal.h"
 
 
-static int ssl_check_clienthello_tlsext(SSL *ssl);
-static int ssl_check_serverhello_tlsext(SSL *ssl);
-
-const SSL3_ENC_METHOD TLSv1_enc_data = {
-    tls1_prf,
-    tls1_setup_key_block,
-    tls1_generate_master_secret,
-    tls1_change_cipher_state,
-    tls1_final_finish_mac,
-    tls1_cert_verify_mac,
-    TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE,
-    TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE,
-    tls1_alert_code,
-    tls1_export_keying_material,
-    0,
-};
-
-const SSL3_ENC_METHOD TLSv1_1_enc_data = {
-    tls1_prf,
-    tls1_setup_key_block,
-    tls1_generate_master_secret,
-    tls1_change_cipher_state,
-    tls1_final_finish_mac,
-    tls1_cert_verify_mac,
-    TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE,
-    TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE,
-    tls1_alert_code,
-    tls1_export_keying_material,
-    SSL_ENC_FLAG_EXPLICIT_IV,
-};
-
-const SSL3_ENC_METHOD TLSv1_2_enc_data = {
-    tls1_prf,
-    tls1_setup_key_block,
-    tls1_generate_master_secret,
-    tls1_change_cipher_state,
-    tls1_final_finish_mac,
-    tls1_cert_verify_mac,
-    TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE,
-    TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE,
-    tls1_alert_code,
-    tls1_export_keying_material,
-    SSL_ENC_FLAG_EXPLICIT_IV|SSL_ENC_FLAG_SIGALGS|SSL_ENC_FLAG_SHA256_PRF,
-};
+static int ssl_check_clienthello_tlsext(SSL_HANDSHAKE *hs);
 
 static int compare_uint16_t(const void *p1, const void *p2) {
   uint16_t u1 = *((const uint16_t *)p1);
@@ -211,8 +168,7 @@
     return 1;
   }
 
-  extension_types =
-      (uint16_t *)OPENSSL_malloc(sizeof(uint16_t) * num_extensions);
+  extension_types = OPENSSL_malloc(sizeof(uint16_t) * num_extensions);
   if (extension_types == NULL) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
     goto done;
@@ -246,88 +202,86 @@
   return ret;
 }
 
-char ssl_early_callback_init(struct ssl_early_callback_ctx *ctx) {
-  CBS client_hello, session_id, cipher_suites, compression_methods, extensions;
+int ssl_client_hello_init(SSL *ssl, SSL_CLIENT_HELLO *out, const uint8_t *in,
+                          size_t in_len) {
+  OPENSSL_memset(out, 0, sizeof(*out));
+  out->ssl = ssl;
+  out->client_hello = in;
+  out->client_hello_len = in_len;
 
-  CBS_init(&client_hello, ctx->client_hello, ctx->client_hello_len);
-
-  if (/* Skip client version. */
-      !CBS_skip(&client_hello, 2) ||
-      /* Skip client nonce. */
-      !CBS_skip(&client_hello, 32) ||
-      /* Extract session_id. */
-      !CBS_get_u8_length_prefixed(&client_hello, &session_id)) {
+  CBS client_hello, random, session_id;
+  CBS_init(&client_hello, out->client_hello, out->client_hello_len);
+  if (!CBS_get_u16(&client_hello, &out->version) ||
+      !CBS_get_bytes(&client_hello, &random, SSL3_RANDOM_SIZE) ||
+      !CBS_get_u8_length_prefixed(&client_hello, &session_id) ||
+      CBS_len(&session_id) > SSL_MAX_SSL_SESSION_ID_LENGTH) {
     return 0;
   }
 
-  ctx->session_id = CBS_data(&session_id);
-  ctx->session_id_len = CBS_len(&session_id);
+  out->random = CBS_data(&random);
+  out->random_len = CBS_len(&random);
+  out->session_id = CBS_data(&session_id);
+  out->session_id_len = CBS_len(&session_id);
 
   /* Skip past DTLS cookie */
-  if (SSL_IS_DTLS(ctx->ssl)) {
+  if (SSL_is_dtls(out->ssl)) {
     CBS cookie;
-
-    if (!CBS_get_u8_length_prefixed(&client_hello, &cookie)) {
+    if (!CBS_get_u8_length_prefixed(&client_hello, &cookie) ||
+        CBS_len(&cookie) > DTLS1_COOKIE_LENGTH) {
       return 0;
     }
   }
 
-  /* Extract cipher_suites. */
+  CBS cipher_suites, compression_methods;
   if (!CBS_get_u16_length_prefixed(&client_hello, &cipher_suites) ||
-      CBS_len(&cipher_suites) < 2 || (CBS_len(&cipher_suites) & 1) != 0) {
-    return 0;
-  }
-  ctx->cipher_suites = CBS_data(&cipher_suites);
-  ctx->cipher_suites_len = CBS_len(&cipher_suites);
-
-  /* Extract compression_methods. */
-  if (!CBS_get_u8_length_prefixed(&client_hello, &compression_methods) ||
+      CBS_len(&cipher_suites) < 2 || (CBS_len(&cipher_suites) & 1) != 0 ||
+      !CBS_get_u8_length_prefixed(&client_hello, &compression_methods) ||
       CBS_len(&compression_methods) < 1) {
     return 0;
   }
-  ctx->compression_methods = CBS_data(&compression_methods);
-  ctx->compression_methods_len = CBS_len(&compression_methods);
+
+  out->cipher_suites = CBS_data(&cipher_suites);
+  out->cipher_suites_len = CBS_len(&cipher_suites);
+  out->compression_methods = CBS_data(&compression_methods);
+  out->compression_methods_len = CBS_len(&compression_methods);
 
   /* If the ClientHello ends here then it's valid, but doesn't have any
    * extensions. (E.g. SSLv3.) */
   if (CBS_len(&client_hello) == 0) {
-    ctx->extensions = NULL;
-    ctx->extensions_len = 0;
+    out->extensions = NULL;
+    out->extensions_len = 0;
     return 1;
   }
 
   /* Extract extensions and check it is valid. */
+  CBS extensions;
   if (!CBS_get_u16_length_prefixed(&client_hello, &extensions) ||
       !tls1_check_duplicate_extensions(&extensions) ||
       CBS_len(&client_hello) != 0) {
     return 0;
   }
-  ctx->extensions = CBS_data(&extensions);
-  ctx->extensions_len = CBS_len(&extensions);
+
+  out->extensions = CBS_data(&extensions);
+  out->extensions_len = CBS_len(&extensions);
 
   return 1;
 }
 
-int SSL_early_callback_ctx_extension_get(
-    const struct ssl_early_callback_ctx *ctx, uint16_t extension_type,
-    const uint8_t **out_data, size_t *out_len) {
+int ssl_client_hello_get_extension(const SSL_CLIENT_HELLO *client_hello,
+                                   CBS *out, uint16_t extension_type) {
   CBS extensions;
-
-  CBS_init(&extensions, ctx->extensions, ctx->extensions_len);
-
+  CBS_init(&extensions, client_hello->extensions, client_hello->extensions_len);
   while (CBS_len(&extensions) != 0) {
+    /* Decode the next extension. */
     uint16_t type;
     CBS extension;
-
-    /* Decode the next extension. */
     if (!CBS_get_u16(&extensions, &type) ||
         !CBS_get_u16_length_prefixed(&extensions, &extension)) {
       return 0;
     }
 
     if (type == extension_type) {
-      *out_data = CBS_data(&extension);
-      *out_len = CBS_len(&extension);
+      *out = extension;
       return 1;
     }
   }
@@ -335,76 +289,69 @@
   return 0;
 }
 
-static const uint16_t eccurves_default[] = {
-    SSL_CURVE_SECP256R1,
-    SSL_CURVE_SECP384R1,
-#if defined(BORINGSSL_ANDROID_SYSTEM)
-    SSL_CURVE_SECP521R1,
-#endif
-};
-
-/* tls1_get_curvelist sets |*out_curve_ids| and |*out_curve_ids_len| to the
- * list of allowed curve IDs. If |get_peer_curves| is non-zero, return the
- * peer's curve list. Otherwise, return the preferred list. */
-static void tls1_get_curvelist(SSL *ssl, int get_peer_curves,
-                               const uint16_t **out_curve_ids,
-                               size_t *out_curve_ids_len) {
-  if (get_peer_curves) {
-    /* Only clients send a curve list, so this function is only called
-     * on the server. */
-    assert(ssl->server);
-    *out_curve_ids = ssl->s3->tmp.peer_ellipticcurvelist;
-    *out_curve_ids_len = ssl->s3->tmp.peer_ellipticcurvelist_length;
-    return;
+int SSL_early_callback_ctx_extension_get(const SSL_CLIENT_HELLO *client_hello,
+                                         uint16_t extension_type,
+                                         const uint8_t **out_data,
+                                         size_t *out_len) {
+  CBS cbs;
+  if (!ssl_client_hello_get_extension(client_hello, &cbs, extension_type)) {
+    return 0;
   }
 
-  *out_curve_ids = ssl->tlsext_ellipticcurvelist;
-  *out_curve_ids_len = ssl->tlsext_ellipticcurvelist_length;
-  if (!*out_curve_ids) {
-    *out_curve_ids = eccurves_default;
-    *out_curve_ids_len = sizeof(eccurves_default) / sizeof(eccurves_default[0]);
+  *out_data = CBS_data(&cbs);
+  *out_len = CBS_len(&cbs);
+  return 1;
+}
+
+static const uint16_t kDefaultGroups[] = {
+    SSL_CURVE_X25519,
+    SSL_CURVE_SECP256R1,
+    SSL_CURVE_SECP384R1,
+};
+
+void tls1_get_grouplist(SSL *ssl, const uint16_t **out_group_ids,
+                        size_t *out_group_ids_len) {
+  *out_group_ids = ssl->supported_group_list;
+  *out_group_ids_len = ssl->supported_group_list_len;
+  if (!*out_group_ids) {
+    *out_group_ids = kDefaultGroups;
+    *out_group_ids_len = OPENSSL_ARRAY_SIZE(kDefaultGroups);
   }
 }
 
-int tls1_get_shared_curve(SSL *ssl, uint16_t *out_curve_id) {
-  const uint16_t *curves, *peer_curves, *pref, *supp;
-  size_t curves_len, peer_curves_len, pref_len, supp_len, i, j;
+int tls1_get_shared_group(SSL_HANDSHAKE *hs, uint16_t *out_group_id) {
+  SSL *const ssl = hs->ssl;
+  assert(ssl->server);
 
-  /* Can't do anything on client side */
-  if (ssl->server == 0) {
-    return 0;
-  }
+  const uint16_t *groups, *pref, *supp;
+  size_t groups_len, pref_len, supp_len;
+  tls1_get_grouplist(ssl, &groups, &groups_len);
 
-  tls1_get_curvelist(ssl, 0 /* local curves */, &curves, &curves_len);
-  tls1_get_curvelist(ssl, 1 /* peer curves */, &peer_curves, &peer_curves_len);
-
-  if (peer_curves_len == 0) {
-    /* Clients are not required to send a supported_curves extension. In this
-     * case, the server is free to pick any curve it likes. See RFC 4492,
-     * section 4, paragraph 3.
-     *
-     * However, in the interests of compatibility, we will skip ECDH if the
-     * client didn't send an extension because we can't be sure that they'll
-     * support our favoured curve. */
-    return 0;
-  }
+  /* Clients are not required to send a supported_groups extension. In this
+   * case, the server is free to pick any group it likes. See RFC 4492,
+   * section 4, paragraph 3.
+   *
+   * However, in the interests of compatibility, we will skip ECDH if the
+   * client didn't send an extension because we can't be sure that they'll
+   * support our favoured group. Thus we do not special-case an emtpy
+   * |peer_supported_group_list|. */
 
   if (ssl->options & SSL_OP_CIPHER_SERVER_PREFERENCE) {
-    pref = curves;
-    pref_len = curves_len;
-    supp = peer_curves;
-    supp_len = peer_curves_len;
+    pref = groups;
+    pref_len = groups_len;
+    supp = hs->peer_supported_group_list;
+    supp_len = hs->peer_supported_group_list_len;
   } else {
-    pref = peer_curves;
-    pref_len = peer_curves_len;
-    supp = curves;
-    supp_len = curves_len;
+    pref = hs->peer_supported_group_list;
+    pref_len = hs->peer_supported_group_list_len;
+    supp = groups;
+    supp_len = groups_len;
   }
 
-  for (i = 0; i < pref_len; i++) {
-    for (j = 0; j < supp_len; j++) {
+  for (size_t i = 0; i < pref_len; i++) {
+    for (size_t j = 0; j < supp_len; j++) {
       if (pref[i] == supp[j]) {
-        *out_curve_id = pref[i];
+        *out_group_id = pref[i];
         return 1;
       }
     }
@@ -413,237 +360,171 @@
   return 0;
 }
 
-int tls1_set_curves(uint16_t **out_curve_ids, size_t *out_curve_ids_len,
+int tls1_set_curves(uint16_t **out_group_ids, size_t *out_group_ids_len,
                     const int *curves, size_t ncurves) {
-  uint16_t *curve_ids;
-  size_t i;
+  uint16_t *group_ids;
 
-  curve_ids = (uint16_t *)OPENSSL_malloc(ncurves * sizeof(uint16_t));
-  if (curve_ids == NULL) {
+  group_ids = OPENSSL_malloc(ncurves * sizeof(uint16_t));
+  if (group_ids == NULL) {
     return 0;
   }
 
-  for (i = 0; i < ncurves; i++) {
-    if (!ssl_nid_to_curve_id(&curve_ids[i], curves[i])) {
-      OPENSSL_free(curve_ids);
+  for (size_t i = 0; i < ncurves; i++) {
+    if (!ssl_nid_to_group_id(&group_ids[i], curves[i])) {
+      OPENSSL_free(group_ids);
       return 0;
     }
   }
 
-  OPENSSL_free(*out_curve_ids);
-  *out_curve_ids = curve_ids;
-  *out_curve_ids_len = ncurves;
+  OPENSSL_free(*out_group_ids);
+  *out_group_ids = group_ids;
+  *out_group_ids_len = ncurves;
 
   return 1;
 }
 
-/* tls1_curve_params_from_ec_key sets |*out_curve_id| and |*out_comp_id| to the
- * TLS curve ID and point format, respectively, for |ec|. It returns one on
- * success and zero on failure. */
-static int tls1_curve_params_from_ec_key(uint16_t *out_curve_id,
-                                         uint8_t *out_comp_id, EC_KEY *ec) {
-  int nid;
-  uint16_t id;
-  const EC_GROUP *grp;
+int tls1_set_curves_list(uint16_t **out_group_ids, size_t *out_group_ids_len,
+                         const char *curves) {
+  uint16_t *group_ids = NULL;
+  size_t ncurves = 0;
 
-  if (ec == NULL) {
-    return 0;
-  }
+  const char *col;
+  const char *ptr = curves;
 
-  grp = EC_KEY_get0_group(ec);
-  if (grp == NULL) {
-    return 0;
-  }
+  do {
+    col = strchr(ptr, ':');
 
-  /* Determine curve ID */
-  nid = EC_GROUP_get_curve_name(grp);
-  if (!ssl_nid_to_curve_id(&id, nid)) {
-    return 0;
-  }
-
-  /* Set the named curve ID. Arbitrary explicit curves are not supported. */
-  *out_curve_id = id;
-
-  if (out_comp_id) {
-    if (EC_KEY_get0_public_key(ec) == NULL) {
-      return 0;
+    uint16_t group_id;
+    if (!ssl_name_to_group_id(&group_id, ptr,
+                              col ? (size_t)(col - ptr) : strlen(ptr))) {
+      goto err;
     }
-    if (EC_KEY_get_conv_form(ec) == POINT_CONVERSION_COMPRESSED) {
-      *out_comp_id = TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime;
-    } else {
-      *out_comp_id = TLSEXT_ECPOINTFORMAT_uncompressed;
+
+    uint16_t *new_group_ids = OPENSSL_realloc(group_ids,
+                                              (ncurves + 1) * sizeof(uint16_t));
+    if (new_group_ids == NULL) {
+      goto err;
     }
-  }
+    group_ids = new_group_ids;
+
+    group_ids[ncurves] = group_id;
+    ncurves++;
+
+    if (col) {
+      ptr = col + 1;
+    }
+  } while (col);
+
+  OPENSSL_free(*out_group_ids);
+  *out_group_ids = group_ids;
+  *out_group_ids_len = ncurves;
 
   return 1;
+
+err:
+  OPENSSL_free(group_ids);
+  return 0;
 }
 
-/* tls1_check_curve_id returns one if |curve_id| is consistent with both our
- * and the peer's curve preferences. Note: if called as the client, only our
- * preferences are checked; the peer (the server) does not send preferences. */
-int tls1_check_curve_id(SSL *ssl, uint16_t curve_id) {
-  const uint16_t *curves;
-  size_t curves_len, i, get_peer_curves;
-
-  /* Check against our list, then the peer's list. */
-  for (get_peer_curves = 0; get_peer_curves <= 1; get_peer_curves++) {
-    if (get_peer_curves && !ssl->server) {
-      /* Servers do not present a preference list so, if we are a client, only
-       * check our list. */
-      continue;
-    }
-
-    tls1_get_curvelist(ssl, get_peer_curves, &curves, &curves_len);
-    if (get_peer_curves && curves_len == 0) {
-      /* Clients are not required to send a supported_curves extension. In this
-       * case, the server is free to pick any curve it likes. See RFC 4492,
-       * section 4, paragraph 3. */
-      continue;
-    }
-    for (i = 0; i < curves_len; i++) {
-      if (curves[i] == curve_id) {
-        break;
-      }
-    }
-
-    if (i == curves_len) {
-      return 0;
+int tls1_check_group_id(SSL *ssl, uint16_t group_id) {
+  const uint16_t *groups;
+  size_t groups_len;
+  tls1_get_grouplist(ssl, &groups, &groups_len);
+  for (size_t i = 0; i < groups_len; i++) {
+    if (groups[i] == group_id) {
+      return 1;
     }
   }
 
-  return 1;
+  return 0;
 }
 
-int tls1_check_ec_cert(SSL *ssl, X509 *x) {
-  int ret = 0;
-  EVP_PKEY *pkey = X509_get_pubkey(x);
-  uint16_t curve_id;
-  uint8_t comp_id;
+/* kVerifySignatureAlgorithms is the default list of accepted signature
+ * algorithms for verifying.
+ *
+ * For now, RSA-PSS signature algorithms are not enabled on Android's system
+ * BoringSSL. Once the change in Chrome has stuck and the values are finalized,
+ * restore them. */
+static const uint16_t kVerifySignatureAlgorithms[] = {
+    /* Prefer SHA-256 algorithms. */
+    SSL_SIGN_ECDSA_SECP256R1_SHA256,
+#if !defined(BORINGSSL_ANDROID_SYSTEM)
+    SSL_SIGN_RSA_PSS_SHA256,
+#endif
+    SSL_SIGN_RSA_PKCS1_SHA256,
 
-  if (!pkey) {
-    goto done;
-  }
-  EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(pkey);
-  if (ec_key == NULL ||
-      !tls1_curve_params_from_ec_key(&curve_id, &comp_id, ec_key) ||
-      !tls1_check_curve_id(ssl, curve_id) ||
-      comp_id != TLSEXT_ECPOINTFORMAT_uncompressed) {
-    goto done;
-  }
+    /* Larger hashes are acceptable. */
+    SSL_SIGN_ECDSA_SECP384R1_SHA384,
+#if !defined(BORINGSSL_ANDROID_SYSTEM)
+    SSL_SIGN_RSA_PSS_SHA384,
+#endif
+    SSL_SIGN_RSA_PKCS1_SHA384,
 
-  ret = 1;
+    /* TODO(davidben): Remove this. */
+#if defined(BORINGSSL_ANDROID_SYSTEM)
+    SSL_SIGN_ECDSA_SECP521R1_SHA512,
+#endif
+#if !defined(BORINGSSL_ANDROID_SYSTEM)
+    SSL_SIGN_RSA_PSS_SHA512,
+#endif
+    SSL_SIGN_RSA_PKCS1_SHA512,
 
-done:
-  EVP_PKEY_free(pkey);
-  return ret;
-}
+    /* For now, SHA-1 is still accepted but least preferable. */
+    SSL_SIGN_RSA_PKCS1_SHA1,
 
-/* List of supported signature algorithms and hashes. Should make this
- * customisable at some point, for now include everything we support. */
-
-#define tlsext_sigalg_rsa(md) md, TLSEXT_signature_rsa,
-
-#define tlsext_sigalg_ecdsa(md) md, TLSEXT_signature_ecdsa,
-
-#define tlsext_sigalg(md) tlsext_sigalg_rsa(md) tlsext_sigalg_ecdsa(md)
-
-static const uint8_t tls12_sigalgs[] = {
-    tlsext_sigalg(TLSEXT_hash_sha512)
-    tlsext_sigalg(TLSEXT_hash_sha384)
-    tlsext_sigalg(TLSEXT_hash_sha256)
-    tlsext_sigalg(TLSEXT_hash_sha224)
-    tlsext_sigalg(TLSEXT_hash_sha1)
 };
 
-size_t tls12_get_psigalgs(SSL *ssl, const uint8_t **psigs) {
-  *psigs = tls12_sigalgs;
-  return sizeof(tls12_sigalgs);
+/* kSignSignatureAlgorithms is the default list of supported signature
+ * algorithms for signing.
+ *
+ * For now, RSA-PSS signature algorithms are not enabled on Android's system
+ * BoringSSL. Once the change in Chrome has stuck and the values are finalized,
+ * restore them. */
+static const uint16_t kSignSignatureAlgorithms[] = {
+    /* Prefer SHA-256 algorithms. */
+    SSL_SIGN_ECDSA_SECP256R1_SHA256,
+#if !defined(BORINGSSL_ANDROID_SYSTEM)
+    SSL_SIGN_RSA_PSS_SHA256,
+#endif
+    SSL_SIGN_RSA_PKCS1_SHA256,
+
+    /* If needed, sign larger hashes.
+     *
+     * TODO(davidben): Determine which of these may be pruned. */
+    SSL_SIGN_ECDSA_SECP384R1_SHA384,
+#if !defined(BORINGSSL_ANDROID_SYSTEM)
+    SSL_SIGN_RSA_PSS_SHA384,
+#endif
+    SSL_SIGN_RSA_PKCS1_SHA384,
+
+    SSL_SIGN_ECDSA_SECP521R1_SHA512,
+#if !defined(BORINGSSL_ANDROID_SYSTEM)
+    SSL_SIGN_RSA_PSS_SHA512,
+#endif
+    SSL_SIGN_RSA_PKCS1_SHA512,
+
+    /* If the peer supports nothing else, sign with SHA-1. */
+    SSL_SIGN_ECDSA_SHA1,
+    SSL_SIGN_RSA_PKCS1_SHA1,
+};
+
+size_t tls12_get_verify_sigalgs(const SSL *ssl, const uint16_t **out) {
+  *out = kVerifySignatureAlgorithms;
+  return OPENSSL_ARRAY_SIZE(kVerifySignatureAlgorithms);
 }
 
-int tls12_check_peer_sigalg(SSL *ssl, const EVP_MD **out_md, int *out_alert,
-                            uint8_t hash, uint8_t signature, EVP_PKEY *pkey) {
-  const uint8_t *sent_sigs;
-  size_t sent_sigslen, i;
-  int sigalg = tls12_get_sigid(pkey->type);
-
-  /* Should never happen */
-  if (sigalg == -1) {
-    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-    *out_alert = SSL_AD_INTERNAL_ERROR;
-    return 0;
-  }
-
-  /* Check key type is consistent with signature */
-  if (sigalg != signature) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
-    *out_alert = SSL_AD_ILLEGAL_PARAMETER;
-    return 0;
-  }
-
-  /* Check signature matches a type we sent */
-  sent_sigslen = tls12_get_psigalgs(ssl, &sent_sigs);
-  for (i = 0; i < sent_sigslen; i += 2, sent_sigs += 2) {
-    if (hash == sent_sigs[0] && signature == sent_sigs[1]) {
-      break;
+int tls12_check_peer_sigalg(SSL *ssl, int *out_alert, uint16_t sigalg) {
+  const uint16_t *verify_sigalgs;
+  size_t num_verify_sigalgs = tls12_get_verify_sigalgs(ssl, &verify_sigalgs);
+  for (size_t i = 0; i < num_verify_sigalgs; i++) {
+    if (sigalg == verify_sigalgs[i]) {
+      return 1;
     }
   }
 
-  if (i == sent_sigslen) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
-    *out_alert = SSL_AD_ILLEGAL_PARAMETER;
-    return 0;
-  }
-
-  *out_md = tls12_get_hash(hash);
-  if (*out_md == NULL) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_DIGEST);
-    *out_alert = SSL_AD_ILLEGAL_PARAMETER;
-    return 0;
-  }
-
-  return 1;
-}
-
-/* Get a mask of disabled algorithms: an algorithm is disabled if it isn't
- * supported or doesn't appear in supported signature algorithms. Unlike
- * ssl_cipher_get_disabled this applies to a specific session and not global
- * settings. */
-void ssl_set_client_disabled(SSL *ssl) {
-  CERT *c = ssl->cert;
-  const uint8_t *sigalgs;
-  size_t i, sigalgslen;
-  int have_rsa = 0, have_ecdsa = 0;
-  c->mask_a = 0;
-  c->mask_k = 0;
-
-  /* Now go through all signature algorithms seeing if we support any for RSA,
-   * DSA, ECDSA. Do this for all versions not just TLS 1.2. */
-  sigalgslen = tls12_get_psigalgs(ssl, &sigalgs);
-  for (i = 0; i < sigalgslen; i += 2, sigalgs += 2) {
-    switch (sigalgs[1]) {
-      case TLSEXT_signature_rsa:
-        have_rsa = 1;
-        break;
-
-      case TLSEXT_signature_ecdsa:
-        have_ecdsa = 1;
-        break;
-    }
-  }
-
-  /* Disable auth if we don't include any appropriate signature algorithms. */
-  if (!have_rsa) {
-    c->mask_a |= SSL_aRSA;
-  }
-  if (!have_ecdsa) {
-    c->mask_a |= SSL_aECDSA;
-  }
-
-  /* with PSK there must be client callback set */
-  if (!ssl->psk_client_callback) {
-    c->mask_a |= SSL_aPSK;
-    c->mask_k |= SSL_kPSK;
-  }
+  OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_SIGNATURE_TYPE);
+  *out_alert = SSL_AD_ILLEGAL_PARAMETER;
+  return 0;
 }
 
 /* tls_extension represents a TLS extension that is handled internally. The
@@ -663,25 +544,45 @@
  * |*out_alert| isn't set, then a |decode_error| alert will be sent. */
 struct tls_extension {
   uint16_t value;
-  void (*init)(SSL *ssl);
+  void (*init)(SSL_HANDSHAKE *hs);
 
-  int (*add_clienthello)(SSL *ssl, CBB *out);
-  int (*parse_serverhello)(SSL *ssl, uint8_t *out_alert, CBS *contents);
+  int (*add_clienthello)(SSL_HANDSHAKE *hs, CBB *out);
+  int (*parse_serverhello)(SSL_HANDSHAKE *hs, uint8_t *out_alert,
+                           CBS *contents);
 
-  int (*parse_clienthello)(SSL *ssl, uint8_t *out_alert, CBS *contents);
-  int (*add_serverhello)(SSL *ssl, CBB *out);
+  int (*parse_clienthello)(SSL_HANDSHAKE *hs, uint8_t *out_alert,
+                           CBS *contents);
+  int (*add_serverhello)(SSL_HANDSHAKE *hs, CBB *out);
 };
 
+static int forbid_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
+                                    CBS *contents) {
+  if (contents != NULL) {
+    /* Servers MUST NOT send this extension. */
+    *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
+    OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
+    return 0;
+  }
+
+  return 1;
+}
+
+static int ignore_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
+                                    CBS *contents) {
+  /* This extension from the client is handled elsewhere. */
+  return 1;
+}
+
+static int dont_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
+  return 1;
+}
 
 /* Server name indication (SNI).
  *
  * https://tools.ietf.org/html/rfc6066#section-3. */
 
-static void ext_sni_init(SSL *ssl) {
-  ssl->s3->tmp.should_ack_sni = 0;
-}
-
-static int ext_sni_add_clienthello(SSL *ssl, CBB *out) {
+static int ext_sni_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+  SSL *const ssl = hs->ssl;
   if (ssl->tlsext_hostname == NULL) {
     return 1;
   }
@@ -701,8 +602,9 @@
   return 1;
 }
 
-static int ext_sni_parse_serverhello(SSL *ssl, uint8_t *out_alert,
+static int ext_sni_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
                                      CBS *contents) {
+  SSL *const ssl = hs->ssl;
   if (contents == NULL) {
     return 1;
   }
@@ -713,10 +615,10 @@
 
   assert(ssl->tlsext_hostname != NULL);
 
-  if (!ssl->hit) {
-    assert(ssl->session->tlsext_hostname == NULL);
-    ssl->session->tlsext_hostname = BUF_strdup(ssl->tlsext_hostname);
-    if (!ssl->session->tlsext_hostname) {
+  if (ssl->session == NULL) {
+    OPENSSL_free(hs->new_session->tlsext_hostname);
+    hs->new_session->tlsext_hostname = BUF_strdup(ssl->tlsext_hostname);
+    if (!hs->new_session->tlsext_hostname) {
       *out_alert = SSL_AD_INTERNAL_ERROR;
       return 0;
     }
@@ -725,97 +627,50 @@
   return 1;
 }
 
-static int ext_sni_parse_clienthello(SSL *ssl, uint8_t *out_alert,
+static int ext_sni_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
                                      CBS *contents) {
   if (contents == NULL) {
     return 1;
   }
 
-  /* The servername extension is treated as follows:
-   *
-   * - Only the hostname type is supported with a maximum length of 255.
-   * - The servername is rejected if too long or if it contains zeros, in
-   *   which case an fatal alert is generated.
-   * - The servername field is maintained together with the session cache.
-   * - When a session is resumed, the servername callback is invoked in order
-   *   to allow the application to position itself to the right context.
-   * - The servername is acknowledged if it is new for a session or when
-   *   it is identical to a previously used for the same session.
-   *   Applications can control the behaviour.  They can at any time
-   *   set a 'desirable' servername for a new SSL object. This can be the
-   *   case for example with HTTPS when a Host: header field is received and
-   *   a renegotiation is requested. In this case, a possible servername
-   *   presented in the new client hello is only acknowledged if it matches
-   *   the value of the Host: field.
-   * - Applications must  use SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
-   *   if they provide for changing an explicit servername context for the
-   *   session,
-   *   i.e. when the session has been established with a servername extension.
-   */
-
-  CBS server_name_list;
-  char have_seen_host_name = 0;
-
+  CBS server_name_list, host_name;
+  uint8_t name_type;
   if (!CBS_get_u16_length_prefixed(contents, &server_name_list) ||
-      CBS_len(&server_name_list) == 0 ||
+      !CBS_get_u8(&server_name_list, &name_type) ||
+      /* Although the server_name extension was intended to be extensible to
+       * new name types and multiple names, OpenSSL 1.0.x had a bug which meant
+       * different name types will cause an error. Further, RFC 4366 originally
+       * defined syntax inextensibly. RFC 6066 corrected this mistake, but
+       * adding new name types is no longer feasible.
+       *
+       * Act as if the extensibility does not exist to simplify parsing. */
+      !CBS_get_u16_length_prefixed(&server_name_list, &host_name) ||
+      CBS_len(&server_name_list) != 0 ||
       CBS_len(contents) != 0) {
     return 0;
   }
 
-  /* Decode each ServerName in the extension. */
-  while (CBS_len(&server_name_list) > 0) {
-    uint8_t name_type;
-    CBS host_name;
-
-    if (!CBS_get_u8(&server_name_list, &name_type) ||
-        !CBS_get_u16_length_prefixed(&server_name_list, &host_name)) {
-      return 0;
-    }
-
-    /* Only host_name is supported. */
-    if (name_type != TLSEXT_NAMETYPE_host_name) {
-      continue;
-    }
-
-    if (have_seen_host_name) {
-      /* The ServerNameList MUST NOT contain more than one name of the same
-       * name_type. */
-      return 0;
-    }
-
-    have_seen_host_name = 1;
-
-    if (CBS_len(&host_name) == 0 ||
-        CBS_len(&host_name) > TLSEXT_MAXLEN_host_name ||
-        CBS_contains_zero_byte(&host_name)) {
-      *out_alert = SSL_AD_UNRECOGNIZED_NAME;
-      return 0;
-    }
-
-    if (!ssl->hit) {
-      assert(ssl->session->tlsext_hostname == NULL);
-      if (ssl->session->tlsext_hostname) {
-        /* This should be impossible. */
-        return 0;
-      }
-
-      /* Copy the hostname as a string. */
-      if (!CBS_strdup(&host_name, &ssl->session->tlsext_hostname)) {
-        *out_alert = SSL_AD_INTERNAL_ERROR;
-        return 0;
-      }
-
-      ssl->s3->tmp.should_ack_sni = 1;
-    }
+  if (name_type != TLSEXT_NAMETYPE_host_name ||
+      CBS_len(&host_name) == 0 ||
+      CBS_len(&host_name) > TLSEXT_MAXLEN_host_name ||
+      CBS_contains_zero_byte(&host_name)) {
+    *out_alert = SSL_AD_UNRECOGNIZED_NAME;
+    return 0;
   }
 
+  /* Copy the hostname as a string. */
+  if (!CBS_strdup(&host_name, &hs->hostname)) {
+    *out_alert = SSL_AD_INTERNAL_ERROR;
+    return 0;
+  }
+
+  hs->should_ack_sni = 1;
   return 1;
 }
 
-static int ext_sni_add_serverhello(SSL *ssl, CBB *out) {
-  if (ssl->hit ||
-      !ssl->s3->tmp.should_ack_sni ||
-      ssl->session->tlsext_hostname == NULL) {
+static int ext_sni_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
+  if (hs->ssl->s3->session_reused ||
+      !hs->should_ack_sni) {
     return 1;
   }
 
@@ -832,7 +687,21 @@
  *
  * https://tools.ietf.org/html/rfc5746 */
 
-static int ext_ri_add_clienthello(SSL *ssl, CBB *out) {
+static int ext_ri_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+  SSL *const ssl = hs->ssl;
+  uint16_t min_version, max_version;
+  if (!ssl_get_version_range(ssl, &min_version, &max_version)) {
+    return 0;
+  }
+
+  /* Renegotiation indication is not necessary in TLS 1.3. */
+  if (min_version >= TLS1_3_VERSION) {
+    return 1;
+  }
+
+  assert(ssl->s3->initial_handshake_complete ==
+         (ssl->s3->previous_client_finished_len != 0));
+
   CBB contents, prev_finished;
   if (!CBB_add_u16(out, TLSEXT_TYPE_renegotiate) ||
       !CBB_add_u16_length_prefixed(out, &contents) ||
@@ -846,8 +715,14 @@
   return 1;
 }
 
-static int ext_ri_parse_serverhello(SSL *ssl, uint8_t *out_alert,
+static int ext_ri_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
                                     CBS *contents) {
+  SSL *const ssl = hs->ssl;
+  if (contents != NULL && ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
+    *out_alert = SSL_AD_ILLEGAL_PARAMETER;
+    return 0;
+  }
+
   /* Servers may not switch between omitting the extension and supporting it.
    * See RFC 5746, sections 3.5 and 4.2. */
   if (ssl->s3->initial_handshake_complete &&
@@ -874,6 +749,10 @@
   /* Check for logic errors */
   assert(!expected_len || ssl->s3->previous_client_finished_len);
   assert(!expected_len || ssl->s3->previous_server_finished_len);
+  assert(ssl->s3->initial_handshake_complete ==
+         (ssl->s3->previous_client_finished_len != 0));
+  assert(ssl->s3->initial_handshake_complete ==
+         (ssl->s3->previous_server_finished_len != 0));
 
   /* Parse out the extension contents. */
   CBS renegotiated_connection;
@@ -911,41 +790,31 @@
   return 1;
 }
 
-static int ext_ri_parse_clienthello(SSL *ssl, uint8_t *out_alert,
+static int ext_ri_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
                                     CBS *contents) {
+  SSL *const ssl = hs->ssl;
   /* Renegotiation isn't supported as a server so this function should never be
    * called after the initial handshake. */
   assert(!ssl->s3->initial_handshake_complete);
 
-  CBS fake_contents;
-  static const uint8_t kFakeExtension[] = {0};
+  if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
+    return 1;
+  }
 
   if (contents == NULL) {
-    if (ssl->s3->send_connection_binding) {
-      /* The renegotiation SCSV was received so pretend that we received a
-       * renegotiation extension. */
-      CBS_init(&fake_contents, kFakeExtension, sizeof(kFakeExtension));
-      contents = &fake_contents;
-      /* We require that the renegotiation extension is at index zero of
-       * kExtensions. */
-      ssl->s3->tmp.extensions.received |= (1u << 0);
-    } else {
-      return 1;
-    }
+    return 1;
   }
 
   CBS renegotiated_connection;
-
   if (!CBS_get_u8_length_prefixed(contents, &renegotiated_connection) ||
       CBS_len(contents) != 0) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_ENCODING_ERR);
     return 0;
   }
 
-  /* Check that the extension matches */
-  if (!CBS_mem_equal(&renegotiated_connection,
-                     ssl->s3->previous_client_finished,
-                     ssl->s3->previous_client_finished_len)) {
+  /* Check that the extension matches. We do not support renegotiation as a
+   * server, so this must be empty. */
+  if (CBS_len(&renegotiated_connection) != 0) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_MISMATCH);
     *out_alert = SSL_AD_HANDSHAKE_FAILURE;
     return 0;
@@ -956,16 +825,19 @@
   return 1;
 }
 
-static int ext_ri_add_serverhello(SSL *ssl, CBB *out) {
-  CBB contents, prev_finished;
+static int ext_ri_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
+  SSL *const ssl = hs->ssl;
+  /* Renegotiation isn't supported as a server so this function should never be
+   * called after the initial handshake. */
+  assert(!ssl->s3->initial_handshake_complete);
+
+  if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
+    return 1;
+  }
+
   if (!CBB_add_u16(out, TLSEXT_TYPE_renegotiate) ||
-      !CBB_add_u16_length_prefixed(out, &contents) ||
-      !CBB_add_u8_length_prefixed(&contents, &prev_finished) ||
-      !CBB_add_bytes(&prev_finished, ssl->s3->previous_client_finished,
-                     ssl->s3->previous_client_finished_len) ||
-      !CBB_add_bytes(&prev_finished, ssl->s3->previous_server_finished,
-                     ssl->s3->previous_server_finished_len) ||
-      !CBB_flush(out)) {
+      !CBB_add_u16(out, 1 /* length */) ||
+      !CBB_add_u8(out, 0 /* empty renegotiation info */)) {
     return 0;
   }
 
@@ -975,14 +847,16 @@
 
 /* Extended Master Secret.
  *
- * https://tools.ietf.org/html/draft-ietf-tls-session-hash-05 */
+ * https://tools.ietf.org/html/rfc7627 */
 
-static void ext_ems_init(SSL *ssl) {
-  ssl->s3->tmp.extended_master_secret = 0;
-}
+static int ext_ems_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+  uint16_t min_version, max_version;
+  if (!ssl_get_version_range(hs->ssl, &min_version, &max_version)) {
+    return 0;
+  }
 
-static int ext_ems_add_clienthello(SSL *ssl, CBB *out) {
-  if (ssl->version == SSL3_VERSION) {
+  /* Extended master secret is not necessary in TLS 1.3. */
+  if (min_version >= TLS1_3_VERSION || max_version <= SSL3_VERSION) {
     return 1;
   }
 
@@ -994,23 +868,41 @@
   return 1;
 }
 
-static int ext_ems_parse_serverhello(SSL *ssl, uint8_t *out_alert,
+static int ext_ems_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
                                      CBS *contents) {
-  if (contents == NULL) {
-    return 1;
+  SSL *const ssl = hs->ssl;
+
+  if (contents != NULL) {
+    if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION ||
+        ssl->version == SSL3_VERSION ||
+        CBS_len(contents) != 0) {
+      return 0;
+    }
+
+    hs->extended_master_secret = 1;
   }
 
-  if (ssl->version == SSL3_VERSION || CBS_len(contents) != 0) {
+  /* Whether EMS is negotiated may not change on renegotiation. */
+  if (ssl->s3->established_session != NULL &&
+      hs->extended_master_secret !=
+          ssl->s3->established_session->extended_master_secret) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_RENEGOTIATION_EMS_MISMATCH);
+    *out_alert = SSL_AD_ILLEGAL_PARAMETER;
     return 0;
   }
 
-  ssl->s3->tmp.extended_master_secret = 1;
   return 1;
 }
 
-static int ext_ems_parse_clienthello(SSL *ssl, uint8_t *out_alert,
+static int ext_ems_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
                                      CBS *contents) {
-  if (ssl->version == SSL3_VERSION || contents == NULL) {
+  uint16_t version = ssl3_protocol_version(hs->ssl);
+  if (version >= TLS1_3_VERSION ||
+      version == SSL3_VERSION) {
+    return 1;
+  }
+
+  if (contents == NULL) {
     return 1;
   }
 
@@ -1018,12 +910,12 @@
     return 0;
   }
 
-  ssl->s3->tmp.extended_master_secret = 1;
+  hs->extended_master_secret = 1;
   return 1;
 }
 
-static int ext_ems_add_serverhello(SSL *ssl, CBB *out) {
-  if (!ssl->s3->tmp.extended_master_secret) {
+static int ext_ems_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
+  if (!hs->extended_master_secret) {
     return 1;
   }
 
@@ -1040,8 +932,16 @@
  *
  * https://tools.ietf.org/html/rfc5077 */
 
-static int ext_ticket_add_clienthello(SSL *ssl, CBB *out) {
-  if (SSL_get_options(ssl) & SSL_OP_NO_TICKET) {
+static int ext_ticket_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+  SSL *const ssl = hs->ssl;
+  uint16_t min_version, max_version;
+  if (!ssl_get_version_range(ssl, &min_version, &max_version)) {
+    return 0;
+  }
+
+  /* TLS 1.3 uses a different ticket extension. */
+  if (min_version >= TLS1_3_VERSION ||
+      SSL_get_options(ssl) & SSL_OP_NO_TICKET) {
     return 1;
   }
 
@@ -1052,9 +952,14 @@
    * advertise the extension to avoid potentially breaking servers which carry
    * over the state from the previous handshake, such as OpenSSL servers
    * without upstream's 3c3f0259238594d77264a78944d409f2127642c4. */
+  uint16_t session_version;
   if (!ssl->s3->initial_handshake_complete &&
       ssl->session != NULL &&
-      ssl->session->tlsext_tick != NULL) {
+      ssl->session->tlsext_tick != NULL &&
+      /* Don't send TLS 1.3 session tickets in the ticket extension. */
+      ssl->method->version_from_wire(&session_version,
+                                     ssl->session->ssl_version) &&
+      session_version < TLS1_3_VERSION) {
     ticket_data = ssl->session->tlsext_tick;
     ticket_len = ssl->session->tlsext_ticklen;
   }
@@ -1070,14 +975,17 @@
   return 1;
 }
 
-static int ext_ticket_parse_serverhello(SSL *ssl, uint8_t *out_alert,
+static int ext_ticket_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
                                         CBS *contents) {
-  ssl->tlsext_ticket_expected = 0;
-
+  SSL *const ssl = hs->ssl;
   if (contents == NULL) {
     return 1;
   }
 
+  if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
+    return 0;
+  }
+
   /* If |SSL_OP_NO_TICKET| is set then no extension will have been sent and
    * this function should never be called, even if the server tries to send the
    * extension. */
@@ -1087,25 +995,17 @@
     return 0;
   }
 
-  ssl->tlsext_ticket_expected = 1;
+  hs->ticket_expected = 1;
   return 1;
 }
 
-static int ext_ticket_parse_clienthello(SSL *ssl, uint8_t *out_alert,
-                                        CBS *contents) {
-  /* This function isn't used because the ticket extension from the client is
-   * handled in ssl_session.c. */
-  return 1;
-}
-
-static int ext_ticket_add_serverhello(SSL *ssl, CBB *out) {
-  if (!ssl->tlsext_ticket_expected) {
+static int ext_ticket_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
+  if (!hs->ticket_expected) {
     return 1;
   }
 
-  /* If |SSL_OP_NO_TICKET| is set, |tlsext_ticket_expected| should never be
-   * true. */
-  assert((SSL_get_options(ssl) & SSL_OP_NO_TICKET) == 0);
+  /* If |SSL_OP_NO_TICKET| is set, |ticket_expected| should never be true. */
+  assert((SSL_get_options(hs->ssl) & SSL_OP_NO_TICKET) == 0);
 
   if (!CBB_add_u16(out, TLSEXT_TYPE_session_ticket) ||
       !CBB_add_u16(out, 0 /* length */)) {
@@ -1120,43 +1020,45 @@
  *
  * https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */
 
-static int ext_sigalgs_add_clienthello(SSL *ssl, CBB *out) {
-  if (ssl3_version_from_wire(ssl, ssl->client_version) < TLS1_2_VERSION) {
+static int ext_sigalgs_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+  SSL *const ssl = hs->ssl;
+  uint16_t min_version, max_version;
+  if (!ssl_get_version_range(ssl, &min_version, &max_version)) {
+    return 0;
+  }
+
+  if (max_version < TLS1_2_VERSION) {
     return 1;
   }
 
-  const uint8_t *sigalgs_data;
-  const size_t sigalgs_len = tls12_get_psigalgs(ssl, &sigalgs_data);
+  const uint16_t *sigalgs;
+  const size_t num_sigalgs = tls12_get_verify_sigalgs(ssl, &sigalgs);
 
-  CBB contents, sigalgs;
+  CBB contents, sigalgs_cbb;
   if (!CBB_add_u16(out, TLSEXT_TYPE_signature_algorithms) ||
       !CBB_add_u16_length_prefixed(out, &contents) ||
-      !CBB_add_u16_length_prefixed(&contents, &sigalgs) ||
-      !CBB_add_bytes(&sigalgs, sigalgs_data, sigalgs_len) ||
-      !CBB_flush(out)) {
+      !CBB_add_u16_length_prefixed(&contents, &sigalgs_cbb)) {
+    return 0;
+  }
+
+  for (size_t i = 0; i < num_sigalgs; i++) {
+    if (!CBB_add_u16(&sigalgs_cbb, sigalgs[i])) {
+      return 0;
+    }
+  }
+
+  if (!CBB_flush(out)) {
     return 0;
   }
 
   return 1;
 }
 
-static int ext_sigalgs_parse_serverhello(SSL *ssl, uint8_t *out_alert,
+static int ext_sigalgs_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
                                          CBS *contents) {
-  if (contents != NULL) {
-    /* Servers MUST NOT send this extension. */
-    *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
-    OPENSSL_PUT_ERROR(SSL, SSL_R_SIGNATURE_ALGORITHMS_EXTENSION_SENT_BY_SERVER);
-    return 0;
-  }
-
-  return 1;
-}
-
-static int ext_sigalgs_parse_clienthello(SSL *ssl, uint8_t *out_alert,
-                                         CBS *contents) {
-  OPENSSL_free(ssl->cert->peer_sigalgs);
-  ssl->cert->peer_sigalgs = NULL;
-  ssl->cert->peer_sigalgslen = 0;
+  OPENSSL_free(hs->peer_sigalgs);
+  hs->peer_sigalgs = NULL;
+  hs->num_peer_sigalgs = 0;
 
   if (contents == NULL) {
     return 1;
@@ -1166,28 +1068,20 @@
   if (!CBS_get_u16_length_prefixed(contents, &supported_signature_algorithms) ||
       CBS_len(contents) != 0 ||
       CBS_len(&supported_signature_algorithms) == 0 ||
-      !tls1_parse_peer_sigalgs(ssl, &supported_signature_algorithms)) {
+      !tls1_parse_peer_sigalgs(hs, &supported_signature_algorithms)) {
     return 0;
   }
 
   return 1;
 }
 
-static int ext_sigalgs_add_serverhello(SSL *ssl, CBB *out) {
-  /* Servers MUST NOT send this extension. */
-  return 1;
-}
-
 
 /* OCSP Stapling.
  *
  * https://tools.ietf.org/html/rfc6066#section-8 */
 
-static void ext_ocsp_init(SSL *ssl) {
-  ssl->s3->tmp.certificate_status_expected = 0;
-}
-
-static int ext_ocsp_add_clienthello(SSL *ssl, CBB *out) {
+static int ext_ocsp_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+  SSL *const ssl = hs->ssl;
   if (!ssl->ocsp_stapling_enabled) {
     return 1;
   }
@@ -1205,21 +1099,33 @@
   return 1;
 }
 
-static int ext_ocsp_parse_serverhello(SSL *ssl, uint8_t *out_alert,
+static int ext_ocsp_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
                                       CBS *contents) {
+  SSL *const ssl = hs->ssl;
   if (contents == NULL) {
     return 1;
   }
 
-  if (CBS_len(contents) != 0) {
+  /* TLS 1.3 OCSP responses are included in the Certificate extensions. */
+  if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
     return 0;
   }
 
-  ssl->s3->tmp.certificate_status_expected = 1;
+  /* OCSP stapling is forbidden on non-certificate ciphers. */
+  if (CBS_len(contents) != 0 ||
+      !ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
+    return 0;
+  }
+
+  /* Note this does not check for resumption in TLS 1.2. Sending
+   * status_request here does not make sense, but OpenSSL does so and the
+   * specification does not say anything. Tolerate it but ignore it. */
+
+  hs->certificate_status_expected = 1;
   return 1;
 }
 
-static int ext_ocsp_parse_clienthello(SSL *ssl, uint8_t *out_alert,
+static int ext_ocsp_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
                                       CBS *contents) {
   if (contents == NULL) {
     return 1;
@@ -1232,20 +1138,22 @@
 
   /* We cannot decide whether OCSP stapling will occur yet because the correct
    * SSL_CTX might not have been selected. */
-  ssl->s3->tmp.ocsp_stapling_requested = status_type == TLSEXT_STATUSTYPE_ocsp;
+  hs->ocsp_stapling_requested = status_type == TLSEXT_STATUSTYPE_ocsp;
 
   return 1;
 }
 
-static int ext_ocsp_add_serverhello(SSL *ssl, CBB *out) {
-  /* The extension shouldn't be sent when resuming sessions. */
-  if (ssl->hit ||
-      !ssl->s3->tmp.ocsp_stapling_requested ||
-      ssl->ctx->ocsp_response_length == 0) {
+static int ext_ocsp_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
+  SSL *const ssl = hs->ssl;
+  if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION ||
+      !hs->ocsp_stapling_requested ||
+      ssl->cert->ocsp_response == NULL ||
+      ssl->s3->session_reused ||
+      !ssl_cipher_uses_certificate_auth(hs->new_cipher)) {
     return 1;
   }
 
-  ssl->s3->tmp.certificate_status_expected = 1;
+  hs->certificate_status_expected = 1;
 
   return CBB_add_u16(out, TLSEXT_TYPE_status_request) &&
          CBB_add_u16(out, 0 /* length */);
@@ -1256,15 +1164,11 @@
  *
  * https://htmlpreview.github.io/?https://github.com/agl/technotes/blob/master/nextprotoneg.html */
 
-static void ext_npn_init(SSL *ssl) {
-  ssl->s3->next_proto_neg_seen = 0;
-}
-
-static int ext_npn_add_clienthello(SSL *ssl, CBB *out) {
+static int ext_npn_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+  SSL *const ssl = hs->ssl;
   if (ssl->s3->initial_handshake_complete ||
       ssl->ctx->next_proto_select_cb == NULL ||
-      (ssl->options & SSL_OP_DISABLE_NPN) ||
-      SSL_IS_DTLS(ssl)) {
+      SSL_is_dtls(ssl)) {
     return 1;
   }
 
@@ -1276,19 +1180,23 @@
   return 1;
 }
 
-static int ext_npn_parse_serverhello(SSL *ssl, uint8_t *out_alert,
+static int ext_npn_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
                                      CBS *contents) {
+  SSL *const ssl = hs->ssl;
   if (contents == NULL) {
     return 1;
   }
 
+  if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
+    return 0;
+  }
+
   /* If any of these are false then we should never have sent the NPN
    * extension in the ClientHello and thus this function should never have been
    * called. */
   assert(!ssl->s3->initial_handshake_complete);
-  assert(!SSL_IS_DTLS(ssl));
+  assert(!SSL_is_dtls(ssl));
   assert(ssl->ctx->next_proto_select_cb != NULL);
-  assert(!(ssl->options & SSL_OP_DISABLE_NPN));
 
   if (ssl->s3->alpn_selected != NULL) {
     /* NPN and ALPN may not be negotiated in the same connection. */
@@ -1317,44 +1225,46 @@
     return 0;
   }
 
-  OPENSSL_free(ssl->next_proto_negotiated);
-  ssl->next_proto_negotiated = BUF_memdup(selected, selected_len);
-  if (ssl->next_proto_negotiated == NULL) {
+  OPENSSL_free(ssl->s3->next_proto_negotiated);
+  ssl->s3->next_proto_negotiated = BUF_memdup(selected, selected_len);
+  if (ssl->s3->next_proto_negotiated == NULL) {
     *out_alert = SSL_AD_INTERNAL_ERROR;
     return 0;
   }
 
-  ssl->next_proto_negotiated_len = selected_len;
-  ssl->s3->next_proto_neg_seen = 1;
+  ssl->s3->next_proto_negotiated_len = selected_len;
+  hs->next_proto_neg_seen = 1;
 
   return 1;
 }
 
-static int ext_npn_parse_clienthello(SSL *ssl, uint8_t *out_alert,
+static int ext_npn_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
                                      CBS *contents) {
+  SSL *const ssl = hs->ssl;
+  if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
+    return 1;
+  }
+
   if (contents != NULL && CBS_len(contents) != 0) {
     return 0;
   }
 
   if (contents == NULL ||
       ssl->s3->initial_handshake_complete ||
-      /* If the ALPN extension is seen before NPN, ignore it. (If ALPN is seen
-       * afterwards, parsing the ALPN extension will clear
-       * |next_proto_neg_seen|. */
-      ssl->s3->alpn_selected != NULL ||
       ssl->ctx->next_protos_advertised_cb == NULL ||
-      SSL_IS_DTLS(ssl)) {
+      SSL_is_dtls(ssl)) {
     return 1;
   }
 
-  ssl->s3->next_proto_neg_seen = 1;
+  hs->next_proto_neg_seen = 1;
   return 1;
 }
 
-static int ext_npn_add_serverhello(SSL *ssl, CBB *out) {
+static int ext_npn_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
+  SSL *const ssl = hs->ssl;
   /* |next_proto_neg_seen| might have been cleared when an ALPN extension was
    * parsed. */
-  if (!ssl->s3->next_proto_neg_seen) {
+  if (!hs->next_proto_neg_seen) {
     return 1;
   }
 
@@ -1364,7 +1274,7 @@
   if (ssl->ctx->next_protos_advertised_cb(
           ssl, &npa, &npa_len, ssl->ctx->next_protos_advertised_cb_arg) !=
       SSL_TLSEXT_ERR_OK) {
-    ssl->s3->next_proto_neg_seen = 0;
+    hs->next_proto_neg_seen = 0;
     return 1;
   }
 
@@ -1384,7 +1294,8 @@
  *
  * https://tools.ietf.org/html/rfc6962#section-3.3.1 */
 
-static int ext_sct_add_clienthello(SSL *ssl, CBB *out) {
+static int ext_sct_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+  SSL *const ssl = hs->ssl;
   if (!ssl->signed_cert_timestamps_enabled) {
     return 1;
   }
@@ -1397,25 +1308,36 @@
   return 1;
 }
 
-static int ext_sct_parse_serverhello(SSL *ssl, uint8_t *out_alert,
+static int ext_sct_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
                                      CBS *contents) {
+  SSL *const ssl = hs->ssl;
   if (contents == NULL) {
     return 1;
   }
 
+  /* TLS 1.3 SCTs are included in the Certificate extensions. */
+  if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
+    *out_alert = SSL_AD_DECODE_ERROR;
+    return 0;
+  }
+
   /* If this is false then we should never have sent the SCT extension in the
    * ClientHello and thus this function should never have been called. */
   assert(ssl->signed_cert_timestamps_enabled);
 
-  if (CBS_len(contents) == 0) {
+  if (!ssl_is_sct_list_valid(contents)) {
     *out_alert = SSL_AD_DECODE_ERROR;
     return 0;
   }
 
-  /* Session resumption uses the original session information. */
-  if (!ssl->hit &&
-      !CBS_stow(contents, &ssl->session->tlsext_signed_cert_timestamp_list,
-                &ssl->session->tlsext_signed_cert_timestamp_list_length)) {
+  /* Session resumption uses the original session information. The extension
+   * should not be sent on resumption, but RFC 6962 did not make it a
+   * requirement, so tolerate this.
+   *
+   * TODO(davidben): Enforce this anyway. */
+  if (!ssl->s3->session_reused &&
+      !CBS_stow(contents, &hs->new_session->tlsext_signed_cert_timestamp_list,
+                &hs->new_session->tlsext_signed_cert_timestamp_list_length)) {
     *out_alert = SSL_AD_INTERNAL_ERROR;
     return 0;
   }
@@ -1423,23 +1345,36 @@
   return 1;
 }
 
-static int ext_sct_parse_clienthello(SSL *ssl, uint8_t *out_alert,
+static int ext_sct_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
                                      CBS *contents) {
-  return contents == NULL || CBS_len(contents) == 0;
+  if (contents == NULL) {
+    return 1;
+  }
+
+  if (CBS_len(contents) != 0) {
+    return 0;
+  }
+
+  hs->scts_requested = 1;
+  return 1;
 }
 
-static int ext_sct_add_serverhello(SSL *ssl, CBB *out) {
+static int ext_sct_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
+  SSL *const ssl = hs->ssl;
   /* The extension shouldn't be sent when resuming sessions. */
-  if (ssl->hit ||
-      ssl->ctx->signed_cert_timestamp_list_length == 0) {
+  if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION ||
+      ssl->s3->session_reused ||
+      ssl->cert->signed_cert_timestamp_list == NULL) {
     return 1;
   }
 
   CBB contents;
   return CBB_add_u16(out, TLSEXT_TYPE_certificate_timestamp) &&
          CBB_add_u16_length_prefixed(out, &contents) &&
-         CBB_add_bytes(&contents, ssl->ctx->signed_cert_timestamp_list,
-                       ssl->ctx->signed_cert_timestamp_list_length) &&
+         CBB_add_bytes(
+             &contents,
+             CRYPTO_BUFFER_data(ssl->cert->signed_cert_timestamp_list),
+             CRYPTO_BUFFER_len(ssl->cert->signed_cert_timestamp_list)) &&
          CBB_flush(out);
 }
 
@@ -1448,12 +1383,8 @@
  *
  * https://tools.ietf.org/html/rfc7301 */
 
-static void ext_alpn_init(SSL *ssl) {
-  OPENSSL_free(ssl->s3->alpn_selected);
-  ssl->s3->alpn_selected = NULL;
-}
-
-static int ext_alpn_add_clienthello(SSL *ssl, CBB *out) {
+static int ext_alpn_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+  SSL *const ssl = hs->ssl;
   if (ssl->alpn_client_proto_list == NULL ||
       ssl->s3->initial_handshake_complete) {
     return 1;
@@ -1472,8 +1403,9 @@
   return 1;
 }
 
-static int ext_alpn_parse_serverhello(SSL *ssl, uint8_t *out_alert,
+static int ext_alpn_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
                                       CBS *contents) {
+  SSL *const ssl = hs->ssl;
   if (contents == NULL) {
     return 1;
   }
@@ -1481,7 +1413,7 @@
   assert(!ssl->s3->initial_handshake_complete);
   assert(ssl->alpn_client_proto_list != NULL);
 
-  if (ssl->s3->next_proto_neg_seen) {
+  if (hs->next_proto_neg_seen) {
     /* NPN and ALPN may not be negotiated in the same connection. */
     *out_alert = SSL_AD_ILLEGAL_PARAMETER;
     OPENSSL_PUT_ERROR(SSL, SSL_R_NEGOTIATED_BOTH_NPN_AND_ALPN);
@@ -1500,6 +1432,33 @@
     return 0;
   }
 
+  /* Check that the protcol name is one of the ones we advertised. */
+  int protocol_ok = 0;
+  CBS client_protocol_name_list, client_protocol_name;
+  CBS_init(&client_protocol_name_list, ssl->alpn_client_proto_list,
+           ssl->alpn_client_proto_list_len);
+  while (CBS_len(&client_protocol_name_list) > 0) {
+    if (!CBS_get_u8_length_prefixed(&client_protocol_name_list,
+                                    &client_protocol_name)) {
+      *out_alert = SSL_AD_INTERNAL_ERROR;
+      return 0;
+    }
+
+    if (CBS_len(&client_protocol_name) == CBS_len(&protocol_name) &&
+        OPENSSL_memcmp(CBS_data(&client_protocol_name),
+                       CBS_data(&protocol_name),
+                       CBS_len(&protocol_name)) == 0) {
+      protocol_ok = 1;
+      break;
+    }
+  }
+
+  if (!protocol_ok) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_ALPN_PROTOCOL);
+    *out_alert = SSL_AD_ILLEGAL_PARAMETER;
+    return 0;
+  }
+
   if (!CBS_stow(&protocol_name, &ssl->s3->alpn_selected,
                 &ssl->s3->alpn_selected_len)) {
     *out_alert = SSL_AD_INTERNAL_ERROR;
@@ -1509,24 +1468,27 @@
   return 1;
 }
 
-static int ext_alpn_parse_clienthello(SSL *ssl, uint8_t *out_alert,
-                                      CBS *contents) {
-  if (contents == NULL) {
-    return 1;
-  }
-
+int ssl_negotiate_alpn(SSL_HANDSHAKE *hs, uint8_t *out_alert,
+                       const SSL_CLIENT_HELLO *client_hello) {
+  SSL *const ssl = hs->ssl;
+  CBS contents;
   if (ssl->ctx->alpn_select_cb == NULL ||
-      ssl->s3->initial_handshake_complete) {
+      !ssl_client_hello_get_extension(
+          client_hello, &contents,
+          TLSEXT_TYPE_application_layer_protocol_negotiation)) {
+    /* Ignore ALPN if not configured or no extension was supplied. */
     return 1;
   }
 
   /* ALPN takes precedence over NPN. */
-  ssl->s3->next_proto_neg_seen = 0;
+  hs->next_proto_neg_seen = 0;
 
   CBS protocol_name_list;
-  if (!CBS_get_u16_length_prefixed(contents, &protocol_name_list) ||
-      CBS_len(contents) != 0 ||
+  if (!CBS_get_u16_length_prefixed(&contents, &protocol_name_list) ||
+      CBS_len(&contents) != 0 ||
       CBS_len(&protocol_name_list) < 2) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
+    *out_alert = SSL_AD_DECODE_ERROR;
     return 0;
   }
 
@@ -1538,6 +1500,8 @@
     if (!CBS_get_u8_length_prefixed(&protocol_name_list_copy, &protocol_name) ||
         /* Empty protocol names are forbidden. */
         CBS_len(&protocol_name) == 0) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
+      *out_alert = SSL_AD_DECODE_ERROR;
       return 0;
     }
   }
@@ -1560,7 +1524,8 @@
   return 1;
 }
 
-static int ext_alpn_add_serverhello(SSL *ssl, CBB *out) {
+static int ext_alpn_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
+  SSL *const ssl = hs->ssl;
   if (ssl->s3->alpn_selected == NULL) {
     return 1;
   }
@@ -1584,13 +1549,14 @@
  *
  * https://tools.ietf.org/html/draft-balfanz-tls-channelid-01 */
 
-static void ext_channel_id_init(SSL *ssl) {
-  ssl->s3->tlsext_channel_id_valid = 0;
+static void ext_channel_id_init(SSL_HANDSHAKE *hs) {
+  hs->ssl->s3->tlsext_channel_id_valid = 0;
 }
 
-static int ext_channel_id_add_clienthello(SSL *ssl, CBB *out) {
+static int ext_channel_id_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+  SSL *const ssl = hs->ssl;
   if (!ssl->tlsext_channel_id_enabled ||
-      SSL_IS_DTLS(ssl)) {
+      SSL_is_dtls(ssl)) {
     return 1;
   }
 
@@ -1602,13 +1568,14 @@
   return 1;
 }
 
-static int ext_channel_id_parse_serverhello(SSL *ssl, uint8_t *out_alert,
-                                            CBS *contents) {
+static int ext_channel_id_parse_serverhello(SSL_HANDSHAKE *hs,
+                                            uint8_t *out_alert, CBS *contents) {
+  SSL *const ssl = hs->ssl;
   if (contents == NULL) {
     return 1;
   }
 
-  assert(!SSL_IS_DTLS(ssl));
+  assert(!SSL_is_dtls(ssl));
   assert(ssl->tlsext_channel_id_enabled);
 
   if (CBS_len(contents) != 0) {
@@ -1619,11 +1586,12 @@
   return 1;
 }
 
-static int ext_channel_id_parse_clienthello(SSL *ssl, uint8_t *out_alert,
-                                            CBS *contents) {
+static int ext_channel_id_parse_clienthello(SSL_HANDSHAKE *hs,
+                                            uint8_t *out_alert, CBS *contents) {
+  SSL *const ssl = hs->ssl;
   if (contents == NULL ||
       !ssl->tlsext_channel_id_enabled ||
-      SSL_IS_DTLS(ssl)) {
+      SSL_is_dtls(ssl)) {
     return 1;
   }
 
@@ -1635,7 +1603,8 @@
   return 1;
 }
 
-static int ext_channel_id_add_serverhello(SSL *ssl, CBB *out) {
+static int ext_channel_id_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
+  SSL *const ssl = hs->ssl;
   if (!ssl->s3->tlsext_channel_id_valid) {
     return 1;
   }
@@ -1654,11 +1623,12 @@
  * https://tools.ietf.org/html/rfc5764 */
 
 
-static void ext_srtp_init(SSL *ssl) {
-  ssl->srtp_profile = NULL;
+static void ext_srtp_init(SSL_HANDSHAKE *hs) {
+  hs->ssl->srtp_profile = NULL;
 }
 
-static int ext_srtp_add_clienthello(SSL *ssl, CBB *out) {
+static int ext_srtp_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+  SSL *const ssl = hs->ssl;
   STACK_OF(SRTP_PROTECTION_PROFILE) *profiles = SSL_get_srtp_profiles(ssl);
   if (profiles == NULL) {
     return 1;
@@ -1675,8 +1645,7 @@
     return 0;
   }
 
-  size_t i;
-  for (i = 0; i < num_profiles; i++) {
+  for (size_t i = 0; i < num_profiles; i++) {
     if (!CBB_add_u16(&profile_ids,
                      sk_SRTP_PROTECTION_PROFILE_value(profiles, i)->id)) {
       return 0;
@@ -1691,8 +1660,9 @@
   return 1;
 }
 
-static int ext_srtp_parse_serverhello(SSL *ssl, uint8_t *out_alert,
+static int ext_srtp_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
                                       CBS *contents) {
+  SSL *const ssl = hs->ssl;
   if (contents == NULL) {
     return 1;
   }
@@ -1723,8 +1693,7 @@
 
   /* Check to see if the server gave us something we support (and presumably
    * offered). */
-  size_t i;
-  for (i = 0; i < sk_SRTP_PROTECTION_PROFILE_num(profiles); i++) {
+  for (size_t i = 0; i < sk_SRTP_PROTECTION_PROFILE_num(profiles); i++) {
     const SRTP_PROTECTION_PROFILE *profile =
         sk_SRTP_PROTECTION_PROFILE_value(profiles, i);
 
@@ -1739,8 +1708,9 @@
   return 0;
 }
 
-static int ext_srtp_parse_clienthello(SSL *ssl, uint8_t *out_alert,
+static int ext_srtp_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
                                       CBS *contents) {
+  SSL *const ssl = hs->ssl;
   if (contents == NULL) {
     return 1;
   }
@@ -1759,8 +1729,7 @@
       SSL_get_srtp_profiles(ssl);
 
   /* Pick the server's most preferred profile. */
-  size_t i;
-  for (i = 0; i < sk_SRTP_PROTECTION_PROFILE_num(server_profiles); i++) {
+  for (size_t i = 0; i < sk_SRTP_PROTECTION_PROFILE_num(server_profiles); i++) {
     const SRTP_PROTECTION_PROFILE *server_profile =
         sk_SRTP_PROTECTION_PROFILE_value(server_profiles, i);
 
@@ -1783,7 +1752,8 @@
   return 1;
 }
 
-static int ext_srtp_add_serverhello(SSL *ssl, CBB *out) {
+static int ext_srtp_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
+  SSL *const ssl = hs->ssl;
   if (ssl->srtp_profile == NULL) {
     return 1;
   }
@@ -1806,28 +1776,7 @@
  *
  * https://tools.ietf.org/html/rfc4492#section-5.1.2 */
 
-static int ssl_any_ec_cipher_suites_enabled(const SSL *ssl) {
-  if (ssl->version < TLS1_VERSION && !SSL_IS_DTLS(ssl)) {
-    return 0;
-  }
-
-  const STACK_OF(SSL_CIPHER) *cipher_stack = SSL_get_ciphers(ssl);
-
-  size_t i;
-  for (i = 0; i < sk_SSL_CIPHER_num(cipher_stack); i++) {
-    const SSL_CIPHER *cipher = sk_SSL_CIPHER_value(cipher_stack, i);
-
-    const uint32_t alg_k = cipher->algorithm_mkey;
-    const uint32_t alg_a = cipher->algorithm_auth;
-    if ((alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA)) {
-      return 1;
-    }
-  }
-
-  return 0;
-}
-
-static int ext_ec_point_add_extension(SSL *ssl, CBB *out) {
+static int ext_ec_point_add_extension(SSL_HANDSHAKE *hs, CBB *out) {
   CBB contents, formats;
   if (!CBB_add_u16(out, TLSEXT_TYPE_ec_point_formats) ||
       !CBB_add_u16_length_prefixed(out, &contents) ||
@@ -1840,20 +1789,30 @@
   return 1;
 }
 
-static int ext_ec_point_add_clienthello(SSL *ssl, CBB *out) {
-  if (!ssl_any_ec_cipher_suites_enabled(ssl)) {
+static int ext_ec_point_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+  uint16_t min_version, max_version;
+  if (!ssl_get_version_range(hs->ssl, &min_version, &max_version)) {
+    return 0;
+  }
+
+  /* The point format extension is unneccessary in TLS 1.3. */
+  if (min_version >= TLS1_3_VERSION) {
     return 1;
   }
 
-  return ext_ec_point_add_extension(ssl, out);
+  return ext_ec_point_add_extension(hs, out);
 }
 
-static int ext_ec_point_parse_serverhello(SSL *ssl, uint8_t *out_alert,
+static int ext_ec_point_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
                                           CBS *contents) {
   if (contents == NULL) {
     return 1;
   }
 
+  if (ssl3_protocol_version(hs->ssl) >= TLS1_3_VERSION) {
+    return 0;
+  }
+
   CBS ec_point_format_list;
   if (!CBS_get_u8_length_prefixed(contents, &ec_point_format_list) ||
       CBS_len(contents) != 0) {
@@ -1862,8 +1821,9 @@
 
   /* Per RFC 4492, section 5.1.2, implementations MUST support the uncompressed
    * point format. */
-  if (memchr(CBS_data(&ec_point_format_list), TLSEXT_ECPOINTFORMAT_uncompressed,
-             CBS_len(&ec_point_format_list)) == NULL) {
+  if (OPENSSL_memchr(CBS_data(&ec_point_format_list),
+                     TLSEXT_ECPOINTFORMAT_uncompressed,
+                     CBS_len(&ec_point_format_list)) == NULL) {
     *out_alert = SSL_AD_ILLEGAL_PARAMETER;
     return 0;
   }
@@ -1871,53 +1831,413 @@
   return 1;
 }
 
-static int ext_ec_point_parse_clienthello(SSL *ssl, uint8_t *out_alert,
+static int ext_ec_point_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert,
                                           CBS *contents) {
-  return ext_ec_point_parse_serverhello(ssl, out_alert, contents);
+  if (ssl3_protocol_version(hs->ssl) >= TLS1_3_VERSION) {
+    return 1;
+  }
+
+  return ext_ec_point_parse_serverhello(hs, out_alert, contents);
 }
 
-static int ext_ec_point_add_serverhello(SSL *ssl, CBB *out) {
-  const uint32_t alg_k = ssl->s3->tmp.new_cipher->algorithm_mkey;
-  const uint32_t alg_a = ssl->s3->tmp.new_cipher->algorithm_auth;
+static int ext_ec_point_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
+  SSL *const ssl = hs->ssl;
+  if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
+    return 1;
+  }
+
+  const uint32_t alg_k = hs->new_cipher->algorithm_mkey;
+  const uint32_t alg_a = hs->new_cipher->algorithm_auth;
   const int using_ecc = (alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA);
 
   if (!using_ecc) {
     return 1;
   }
 
-  return ext_ec_point_add_extension(ssl, out);
+  return ext_ec_point_add_extension(hs, out);
 }
 
 
-/* EC supported curves.
+/* Pre Shared Key
  *
- * https://tools.ietf.org/html/rfc4492#section-5.1.2 */
+ * https://tools.ietf.org/html/draft-ietf-tls-tls13-18#section-4.2.6 */
 
-static void ext_ec_curves_init(SSL *ssl) {
-  OPENSSL_free(ssl->s3->tmp.peer_ellipticcurvelist);
-  ssl->s3->tmp.peer_ellipticcurvelist = NULL;
-  ssl->s3->tmp.peer_ellipticcurvelist_length = 0;
-}
-
-static int ext_ec_curves_add_clienthello(SSL *ssl, CBB *out) {
-  if (!ssl_any_ec_cipher_suites_enabled(ssl)) {
-    return 1;
-  }
-
-  CBB contents, curves_bytes;
-  if (!CBB_add_u16(out, TLSEXT_TYPE_elliptic_curves) ||
-      !CBB_add_u16_length_prefixed(out, &contents) ||
-      !CBB_add_u16_length_prefixed(&contents, &curves_bytes)) {
+static size_t ext_pre_shared_key_clienthello_length(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  uint16_t min_version, max_version;
+  if (!ssl_get_version_range(ssl, &min_version, &max_version)) {
     return 0;
   }
 
-  const uint16_t *curves;
-  size_t curves_len;
-  tls1_get_curvelist(ssl, 0, &curves, &curves_len);
+  uint16_t session_version;
+  if (max_version < TLS1_3_VERSION || ssl->session == NULL ||
+      !ssl->method->version_from_wire(&session_version,
+                                      ssl->session->ssl_version) ||
+      session_version < TLS1_3_VERSION) {
+    return 0;
+  }
 
-  size_t i;
-  for (i = 0; i < curves_len; i++) {
-    if (!CBB_add_u16(&curves_bytes, curves[i])) {
+  const EVP_MD *digest = SSL_SESSION_get_digest(ssl->session, ssl);
+  if (digest == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    return 0;
+  }
+
+  size_t binder_len = EVP_MD_size(digest);
+  return 15 + ssl->session->tlsext_ticklen + binder_len;
+}
+
+static int ext_pre_shared_key_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+  SSL *const ssl = hs->ssl;
+  uint16_t min_version, max_version;
+  if (!ssl_get_version_range(ssl, &min_version, &max_version)) {
+    return 0;
+  }
+
+  uint16_t session_version;
+  if (max_version < TLS1_3_VERSION || ssl->session == NULL ||
+      !ssl->method->version_from_wire(&session_version,
+                                      ssl->session->ssl_version) ||
+      session_version < TLS1_3_VERSION) {
+    return 1;
+  }
+
+  struct OPENSSL_timeval now;
+  ssl_get_current_time(ssl, &now);
+  uint32_t ticket_age = 1000 * (now.tv_sec - ssl->session->time);
+  uint32_t obfuscated_ticket_age = ticket_age + ssl->session->ticket_age_add;
+
+  /* Fill in a placeholder zero binder of the appropriate length. It will be
+   * computed and filled in later after length prefixes are computed. */
+  uint8_t zero_binder[EVP_MAX_MD_SIZE] = {0};
+
+  const EVP_MD *digest = SSL_SESSION_get_digest(ssl->session, ssl);
+  if (digest == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    return 0;
+  }
+
+  size_t binder_len = EVP_MD_size(digest);
+
+  CBB contents, identity, ticket, binders, binder;
+  if (!CBB_add_u16(out, TLSEXT_TYPE_pre_shared_key) ||
+      !CBB_add_u16_length_prefixed(out, &contents) ||
+      !CBB_add_u16_length_prefixed(&contents, &identity) ||
+      !CBB_add_u16_length_prefixed(&identity, &ticket) ||
+      !CBB_add_bytes(&ticket, ssl->session->tlsext_tick,
+                     ssl->session->tlsext_ticklen) ||
+      !CBB_add_u32(&identity, obfuscated_ticket_age) ||
+      !CBB_add_u16_length_prefixed(&contents, &binders) ||
+      !CBB_add_u8_length_prefixed(&binders, &binder) ||
+      !CBB_add_bytes(&binder, zero_binder, binder_len)) {
+    return 0;
+  }
+
+  hs->needs_psk_binder = 1;
+  return CBB_flush(out);
+}
+
+int ssl_ext_pre_shared_key_parse_serverhello(SSL_HANDSHAKE *hs,
+                                             uint8_t *out_alert,
+                                             CBS *contents) {
+  uint16_t psk_id;
+  if (!CBS_get_u16(contents, &psk_id) ||
+      CBS_len(contents) != 0) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    *out_alert = SSL_AD_DECODE_ERROR;
+    return 0;
+  }
+
+  /* We only advertise one PSK identity, so the only legal index is zero. */
+  if (psk_id != 0) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_NOT_FOUND);
+    *out_alert = SSL_AD_UNKNOWN_PSK_IDENTITY;
+    return 0;
+  }
+
+  return 1;
+}
+
+int ssl_ext_pre_shared_key_parse_clienthello(
+    SSL_HANDSHAKE *hs, CBS *out_ticket, CBS *out_binders,
+    uint32_t *out_obfuscated_ticket_age, uint8_t *out_alert, CBS *contents) {
+  /* We only process the first PSK identity since we don't support pure PSK. */
+  CBS identities, binders;
+  if (!CBS_get_u16_length_prefixed(contents, &identities) ||
+      !CBS_get_u16_length_prefixed(&identities, out_ticket) ||
+      !CBS_get_u32(&identities, out_obfuscated_ticket_age) ||
+      !CBS_get_u16_length_prefixed(contents, &binders) ||
+      CBS_len(&binders) == 0 ||
+      CBS_len(contents) != 0) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    *out_alert = SSL_AD_DECODE_ERROR;
+    return 0;
+  }
+
+  *out_binders = binders;
+
+  /* Check the syntax of the remaining identities, but do not process them. */
+  size_t num_identities = 1;
+  while (CBS_len(&identities) != 0) {
+    CBS unused_ticket;
+    uint32_t unused_obfuscated_ticket_age;
+    if (!CBS_get_u16_length_prefixed(&identities, &unused_ticket) ||
+        !CBS_get_u32(&identities, &unused_obfuscated_ticket_age)) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+      *out_alert = SSL_AD_DECODE_ERROR;
+      return 0;
+    }
+
+    num_identities++;
+  }
+
+  /* Check the syntax of the binders. The value will be checked later if
+   * resuming. */
+  size_t num_binders = 0;
+  while (CBS_len(&binders) != 0) {
+    CBS binder;
+    if (!CBS_get_u8_length_prefixed(&binders, &binder)) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+      *out_alert = SSL_AD_DECODE_ERROR;
+      return 0;
+    }
+
+    num_binders++;
+  }
+
+  if (num_identities != num_binders) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_PSK_IDENTITY_BINDER_COUNT_MISMATCH);
+    *out_alert = SSL_AD_ILLEGAL_PARAMETER;
+    return 0;
+  }
+
+  return 1;
+}
+
+int ssl_ext_pre_shared_key_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
+  if (!hs->ssl->s3->session_reused) {
+    return 1;
+  }
+
+  CBB contents;
+  if (!CBB_add_u16(out, TLSEXT_TYPE_pre_shared_key) ||
+      !CBB_add_u16_length_prefixed(out, &contents) ||
+      /* We only consider the first identity for resumption */
+      !CBB_add_u16(&contents, 0) ||
+      !CBB_flush(out)) {
+    return 0;
+  }
+
+  return 1;
+}
+
+
+/* Pre-Shared Key Exchange Modes
+ *
+ * https://tools.ietf.org/html/draft-ietf-tls-tls13-18#section-4.2.7 */
+
+static int ext_psk_key_exchange_modes_add_clienthello(SSL_HANDSHAKE *hs,
+                                                      CBB *out) {
+  SSL *const ssl = hs->ssl;
+  uint16_t min_version, max_version;
+  if (!ssl_get_version_range(ssl, &min_version, &max_version)) {
+    return 0;
+  }
+
+  if (max_version < TLS1_3_VERSION) {
+    return 1;
+  }
+
+  CBB contents, ke_modes;
+  if (!CBB_add_u16(out, TLSEXT_TYPE_psk_key_exchange_modes) ||
+      !CBB_add_u16_length_prefixed(out, &contents) ||
+      !CBB_add_u8_length_prefixed(&contents, &ke_modes) ||
+      !CBB_add_u8(&ke_modes, SSL_PSK_DHE_KE)) {
+    return 0;
+  }
+
+  return CBB_flush(out);
+}
+
+static int ext_psk_key_exchange_modes_parse_clienthello(SSL_HANDSHAKE *hs,
+                                                        uint8_t *out_alert,
+                                                        CBS *contents) {
+  if (contents == NULL) {
+    return 1;
+  }
+
+  CBS ke_modes;
+  if (!CBS_get_u8_length_prefixed(contents, &ke_modes) ||
+      CBS_len(&ke_modes) == 0 ||
+      CBS_len(contents) != 0) {
+    *out_alert = SSL_AD_DECODE_ERROR;
+    return 0;
+  }
+
+  /* We only support tickets with PSK_DHE_KE. */
+  hs->accept_psk_mode = OPENSSL_memchr(CBS_data(&ke_modes), SSL_PSK_DHE_KE,
+                                       CBS_len(&ke_modes)) != NULL;
+
+  return 1;
+}
+
+
+/* Early Data Indication
+ *
+ * https://tools.ietf.org/html/draft-ietf-tls-tls13-18#section-4.2.8 */
+
+static int ext_early_data_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+  SSL *const ssl = hs->ssl;
+  uint16_t session_version;
+  if (ssl->session == NULL ||
+      !ssl->method->version_from_wire(&session_version,
+                                      ssl->session->ssl_version) ||
+      session_version < TLS1_3_VERSION ||
+      ssl->session->ticket_max_early_data == 0 ||
+      hs->received_hello_retry_request ||
+      !ssl->ctx->enable_early_data) {
+    return 1;
+  }
+
+  hs->early_data_offered = 1;
+
+  if (!CBB_add_u16(out, TLSEXT_TYPE_early_data) ||
+      !CBB_add_u16(out, 0) ||
+      !CBB_flush(out)) {
+    return 0;
+  }
+
+  return 1;
+}
+
+static int ext_early_data_parse_serverhello(SSL_HANDSHAKE *hs,
+                                            uint8_t *out_alert, CBS *contents) {
+  SSL *const ssl = hs->ssl;
+  if (contents == NULL) {
+    return 1;
+  }
+
+  if (CBS_len(contents) != 0) {
+    *out_alert = SSL_AD_DECODE_ERROR;
+    return 0;
+  }
+
+  if (!ssl->s3->session_reused) {
+    *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
+    OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
+    return 0;
+  }
+
+  ssl->early_data_accepted = 1;
+  return 1;
+}
+
+static int ext_early_data_parse_clienthello(SSL_HANDSHAKE *hs,
+                                            uint8_t *out_alert, CBS *contents) {
+  SSL *const ssl = hs->ssl;
+  if (contents == NULL ||
+      ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
+    return 1;
+  }
+
+  if (CBS_len(contents) != 0) {
+    *out_alert = SSL_AD_DECODE_ERROR;
+    return 0;
+  }
+
+  hs->early_data_offered = 1;
+  return 1;
+}
+
+static int ext_early_data_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
+  if (!hs->ssl->early_data_accepted) {
+    return 1;
+  }
+
+  if (!CBB_add_u16(out, TLSEXT_TYPE_early_data) ||
+      !CBB_add_u16(out, 0) ||
+      !CBB_flush(out)) {
+    return 0;
+  }
+
+  return 1;
+}
+
+
+/* Key Share
+ *
+ * https://tools.ietf.org/html/draft-ietf-tls-tls13-16#section-4.2.5 */
+
+static int ext_key_share_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+  SSL *const ssl = hs->ssl;
+  uint16_t min_version, max_version;
+  if (!ssl_get_version_range(ssl, &min_version, &max_version)) {
+    return 0;
+  }
+
+  if (max_version < TLS1_3_VERSION) {
+    return 1;
+  }
+
+  CBB contents, kse_bytes;
+  if (!CBB_add_u16(out, TLSEXT_TYPE_key_share) ||
+      !CBB_add_u16_length_prefixed(out, &contents) ||
+      !CBB_add_u16_length_prefixed(&contents, &kse_bytes)) {
+    return 0;
+  }
+
+  uint16_t group_id = hs->retry_group;
+  if (hs->received_hello_retry_request) {
+    /* We received a HelloRetryRequest without a new curve, so there is no new
+     * share to append. Leave |ecdh_ctx| as-is. */
+    if (group_id == 0 &&
+        !CBB_add_bytes(&kse_bytes, hs->key_share_bytes,
+                       hs->key_share_bytes_len)) {
+      return 0;
+    }
+    OPENSSL_free(hs->key_share_bytes);
+    hs->key_share_bytes = NULL;
+    hs->key_share_bytes_len = 0;
+    if (group_id == 0) {
+      return CBB_flush(out);
+    }
+  } else {
+    /* Add a fake group. See draft-davidben-tls-grease-01. */
+    if (ssl->ctx->grease_enabled &&
+        (!CBB_add_u16(&kse_bytes,
+                      ssl_get_grease_value(ssl, ssl_grease_group)) ||
+         !CBB_add_u16(&kse_bytes, 1 /* length */) ||
+         !CBB_add_u8(&kse_bytes, 0 /* one byte key share */))) {
+      return 0;
+    }
+
+    /* Predict the most preferred group. */
+    const uint16_t *groups;
+    size_t groups_len;
+    tls1_get_grouplist(ssl, &groups, &groups_len);
+    if (groups_len == 0) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_NO_GROUPS_SPECIFIED);
+      return 0;
+    }
+
+    group_id = groups[0];
+  }
+
+  CBB key_exchange;
+  if (!CBB_add_u16(&kse_bytes, group_id) ||
+      !CBB_add_u16_length_prefixed(&kse_bytes, &key_exchange) ||
+      !SSL_ECDH_CTX_init(&hs->ecdh_ctx, group_id) ||
+      !SSL_ECDH_CTX_offer(&hs->ecdh_ctx, &key_exchange) ||
+      !CBB_flush(&kse_bytes)) {
+    return 0;
+  }
+
+  if (!hs->received_hello_retry_request) {
+    /* Save the contents of the extension to repeat it in the second
+     * ClientHello. */
+    hs->key_share_bytes_len = CBB_len(&kse_bytes);
+    hs->key_share_bytes = BUF_memdup(CBB_data(&kse_bytes), CBB_len(&kse_bytes));
+    if (hs->key_share_bytes == NULL) {
       return 0;
     }
   }
@@ -1925,56 +2245,286 @@
   return CBB_flush(out);
 }
 
-static int ext_ec_curves_parse_serverhello(SSL *ssl, uint8_t *out_alert,
-                                           CBS *contents) {
-  /* This extension is not expected to be echoed by servers and is ignored. */
-  return 1;
-}
-
-static int ext_ec_curves_parse_clienthello(SSL *ssl, uint8_t *out_alert,
-                                           CBS *contents) {
-  if (contents == NULL) {
-    return 1;
-  }
-
-  CBS elliptic_curve_list;
-  if (!CBS_get_u16_length_prefixed(contents, &elliptic_curve_list) ||
-      CBS_len(&elliptic_curve_list) == 0 ||
-      (CBS_len(&elliptic_curve_list) & 1) != 0 ||
+int ssl_ext_key_share_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t **out_secret,
+                                        size_t *out_secret_len,
+                                        uint8_t *out_alert, CBS *contents) {
+  CBS peer_key;
+  uint16_t group_id;
+  if (!CBS_get_u16(contents, &group_id) ||
+      !CBS_get_u16_length_prefixed(contents, &peer_key) ||
       CBS_len(contents) != 0) {
+    *out_alert = SSL_AD_DECODE_ERROR;
     return 0;
   }
 
-  ssl->s3->tmp.peer_ellipticcurvelist =
-      (uint16_t *)OPENSSL_malloc(CBS_len(&elliptic_curve_list));
+  if (SSL_ECDH_CTX_get_id(&hs->ecdh_ctx) != group_id) {
+    *out_alert = SSL_AD_ILLEGAL_PARAMETER;
+    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
+    return 0;
+  }
 
-  if (ssl->s3->tmp.peer_ellipticcurvelist == NULL) {
+  if (!SSL_ECDH_CTX_finish(&hs->ecdh_ctx, out_secret, out_secret_len, out_alert,
+                           CBS_data(&peer_key), CBS_len(&peer_key))) {
     *out_alert = SSL_AD_INTERNAL_ERROR;
     return 0;
   }
 
-  const size_t num_curves = CBS_len(&elliptic_curve_list) / 2;
-  size_t i;
-  for (i = 0; i < num_curves; i++) {
-    if (!CBS_get_u16(&elliptic_curve_list,
-                     &ssl->s3->tmp.peer_ellipticcurvelist[i])) {
+  hs->new_session->group_id = group_id;
+  SSL_ECDH_CTX_cleanup(&hs->ecdh_ctx);
+  return 1;
+}
+
+int ssl_ext_key_share_parse_clienthello(SSL_HANDSHAKE *hs, int *out_found,
+                                        uint8_t **out_secret,
+                                        size_t *out_secret_len,
+                                        uint8_t *out_alert, CBS *contents) {
+  uint16_t group_id;
+  CBS key_shares;
+  if (!tls1_get_shared_group(hs, &group_id)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_NO_SHARED_GROUP);
+    *out_alert = SSL_AD_HANDSHAKE_FAILURE;
+    return 0;
+  }
+
+  if (!CBS_get_u16_length_prefixed(contents, &key_shares) ||
+      CBS_len(contents) != 0) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    return 0;
+  }
+
+  /* Find the corresponding key share. */
+  int found = 0;
+  CBS peer_key;
+  while (CBS_len(&key_shares) > 0) {
+    uint16_t id;
+    CBS peer_key_tmp;
+    if (!CBS_get_u16(&key_shares, &id) ||
+        !CBS_get_u16_length_prefixed(&key_shares, &peer_key_tmp)) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+      return 0;
+    }
+
+    if (id == group_id) {
+      if (found) {
+        OPENSSL_PUT_ERROR(SSL, SSL_R_DUPLICATE_KEY_SHARE);
+        *out_alert = SSL_AD_ILLEGAL_PARAMETER;
+        return 0;
+      }
+
+      found = 1;
+      peer_key = peer_key_tmp;
+      /* Continue parsing the structure to keep peers honest. */
+    }
+  }
+
+  if (!found) {
+    *out_found = 0;
+    *out_secret = NULL;
+    *out_secret_len = 0;
+    return 1;
+  }
+
+  /* Compute the DH secret. */
+  uint8_t *secret = NULL;
+  size_t secret_len;
+  SSL_ECDH_CTX group;
+  OPENSSL_memset(&group, 0, sizeof(SSL_ECDH_CTX));
+  CBB public_key;
+  if (!CBB_init(&public_key, 32) ||
+      !SSL_ECDH_CTX_init(&group, group_id) ||
+      !SSL_ECDH_CTX_accept(&group, &public_key, &secret, &secret_len, out_alert,
+                           CBS_data(&peer_key), CBS_len(&peer_key)) ||
+      !CBB_finish(&public_key, &hs->public_key, &hs->public_key_len)) {
+    OPENSSL_free(secret);
+    SSL_ECDH_CTX_cleanup(&group);
+    CBB_cleanup(&public_key);
+    *out_alert = SSL_AD_ILLEGAL_PARAMETER;
+    return 0;
+  }
+
+  SSL_ECDH_CTX_cleanup(&group);
+
+  *out_secret = secret;
+  *out_secret_len = secret_len;
+  *out_found = 1;
+  return 1;
+}
+
+int ssl_ext_key_share_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
+  uint16_t group_id;
+  CBB kse_bytes, public_key;
+  if (!tls1_get_shared_group(hs, &group_id) ||
+      !CBB_add_u16(out, TLSEXT_TYPE_key_share) ||
+      !CBB_add_u16_length_prefixed(out, &kse_bytes) ||
+      !CBB_add_u16(&kse_bytes, group_id) ||
+      !CBB_add_u16_length_prefixed(&kse_bytes, &public_key) ||
+      !CBB_add_bytes(&public_key, hs->public_key, hs->public_key_len) ||
+      !CBB_flush(out)) {
+    return 0;
+  }
+
+  OPENSSL_free(hs->public_key);
+  hs->public_key = NULL;
+  hs->public_key_len = 0;
+
+  hs->new_session->group_id = group_id;
+  return 1;
+}
+
+
+/* Supported Versions
+ *
+ * https://tools.ietf.org/html/draft-ietf-tls-tls13-16#section-4.2.1 */
+
+static int ext_supported_versions_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+  SSL *const ssl = hs->ssl;
+  uint16_t min_version, max_version;
+  if (!ssl_get_version_range(ssl, &min_version, &max_version)) {
+    return 0;
+  }
+
+  if (max_version <= TLS1_2_VERSION) {
+    return 1;
+  }
+
+  CBB contents, versions;
+  if (!CBB_add_u16(out, TLSEXT_TYPE_supported_versions) ||
+      !CBB_add_u16_length_prefixed(out, &contents) ||
+      !CBB_add_u8_length_prefixed(&contents, &versions)) {
+    return 0;
+  }
+
+  /* Add a fake version. See draft-davidben-tls-grease-01. */
+  if (ssl->ctx->grease_enabled &&
+      !CBB_add_u16(&versions, ssl_get_grease_value(ssl, ssl_grease_version))) {
+    return 0;
+  }
+
+  for (uint16_t version = max_version; version >= min_version; version--) {
+    if (!CBB_add_u16(&versions, ssl->method->version_to_wire(version))) {
+      return 0;
+    }
+  }
+
+  if (!CBB_flush(out)) {
+    return 0;
+  }
+
+  return 1;
+}
+
+
+/* Cookie
+ *
+ * https://tools.ietf.org/html/draft-ietf-tls-tls13-16#section-4.2.2 */
+
+static int ext_cookie_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+  if (hs->cookie == NULL) {
+    return 1;
+  }
+
+  CBB contents, cookie;
+  if (!CBB_add_u16(out, TLSEXT_TYPE_cookie) ||
+      !CBB_add_u16_length_prefixed(out, &contents) ||
+      !CBB_add_u16_length_prefixed(&contents, &cookie) ||
+      !CBB_add_bytes(&cookie, hs->cookie, hs->cookie_len) ||
+      !CBB_flush(out)) {
+    return 0;
+  }
+
+  /* The cookie is no longer needed in memory. */
+  OPENSSL_free(hs->cookie);
+  hs->cookie = NULL;
+  hs->cookie_len = 0;
+  return 1;
+}
+
+
+/* Negotiated Groups
+ *
+ * https://tools.ietf.org/html/rfc4492#section-5.1.2
+ * https://tools.ietf.org/html/draft-ietf-tls-tls13-16#section-4.2.4 */
+
+static int ext_supported_groups_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) {
+  SSL *const ssl = hs->ssl;
+  CBB contents, groups_bytes;
+  if (!CBB_add_u16(out, TLSEXT_TYPE_supported_groups) ||
+      !CBB_add_u16_length_prefixed(out, &contents) ||
+      !CBB_add_u16_length_prefixed(&contents, &groups_bytes)) {
+    return 0;
+  }
+
+  /* Add a fake group. See draft-davidben-tls-grease-01. */
+  if (ssl->ctx->grease_enabled &&
+      !CBB_add_u16(&groups_bytes,
+                   ssl_get_grease_value(ssl, ssl_grease_group))) {
+    return 0;
+  }
+
+  const uint16_t *groups;
+  size_t groups_len;
+  tls1_get_grouplist(ssl, &groups, &groups_len);
+
+  for (size_t i = 0; i < groups_len; i++) {
+    if (!CBB_add_u16(&groups_bytes, groups[i])) {
+      return 0;
+    }
+  }
+
+  return CBB_flush(out);
+}
+
+static int ext_supported_groups_parse_serverhello(SSL_HANDSHAKE *hs,
+                                                  uint8_t *out_alert,
+                                                  CBS *contents) {
+  /* This extension is not expected to be echoed by servers in TLS 1.2, but some
+   * BigIP servers send it nonetheless, so do not enforce this. */
+  return 1;
+}
+
+static int ext_supported_groups_parse_clienthello(SSL_HANDSHAKE *hs,
+                                                  uint8_t *out_alert,
+                                                  CBS *contents) {
+  if (contents == NULL) {
+    return 1;
+  }
+
+  CBS supported_group_list;
+  if (!CBS_get_u16_length_prefixed(contents, &supported_group_list) ||
+      CBS_len(&supported_group_list) == 0 ||
+      (CBS_len(&supported_group_list) & 1) != 0 ||
+      CBS_len(contents) != 0) {
+    return 0;
+  }
+
+  hs->peer_supported_group_list =
+      OPENSSL_malloc(CBS_len(&supported_group_list));
+  if (hs->peer_supported_group_list == NULL) {
+    *out_alert = SSL_AD_INTERNAL_ERROR;
+    return 0;
+  }
+
+  const size_t num_groups = CBS_len(&supported_group_list) / 2;
+  for (size_t i = 0; i < num_groups; i++) {
+    if (!CBS_get_u16(&supported_group_list,
+                     &hs->peer_supported_group_list[i])) {
       goto err;
     }
   }
 
-  assert(CBS_len(&elliptic_curve_list) == 0);
-  ssl->s3->tmp.peer_ellipticcurvelist_length = num_curves;
+  assert(CBS_len(&supported_group_list) == 0);
+  hs->peer_supported_group_list_len = num_groups;
 
   return 1;
 
 err:
-  OPENSSL_free(ssl->s3->tmp.peer_ellipticcurvelist);
-  ssl->s3->tmp.peer_ellipticcurvelist = NULL;
+  OPENSSL_free(hs->peer_supported_group_list);
+  hs->peer_supported_group_list = NULL;
   *out_alert = SSL_AD_INTERNAL_ERROR;
   return 0;
 }
 
-static int ext_ec_curves_add_serverhello(SSL *ssl, CBB *out) {
+static int ext_supported_groups_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) {
   /* Servers don't echo this extension. */
   return 1;
 }
@@ -1983,9 +2533,6 @@
 /* kExtensions contains all the supported extensions. */
 static const struct tls_extension kExtensions[] = {
   {
-    /* The renegotiation extension must always be at index zero because the
-     * |received| and |sent| bitsets need to be tweaked when the "extension" is
-     * sent as an SCSV. */
     TLSEXT_TYPE_renegotiate,
     NULL,
     ext_ri_add_clienthello,
@@ -1995,7 +2542,7 @@
   },
   {
     TLSEXT_TYPE_server_name,
-    ext_sni_init,
+    NULL,
     ext_sni_add_clienthello,
     ext_sni_parse_serverhello,
     ext_sni_parse_clienthello,
@@ -2003,7 +2550,7 @@
   },
   {
     TLSEXT_TYPE_extended_master_secret,
-    ext_ems_init,
+    NULL,
     ext_ems_add_clienthello,
     ext_ems_parse_serverhello,
     ext_ems_parse_clienthello,
@@ -2014,20 +2561,21 @@
     NULL,
     ext_ticket_add_clienthello,
     ext_ticket_parse_serverhello,
-    ext_ticket_parse_clienthello,
+    /* Ticket extension client parsing is handled in ssl_session.c */
+    ignore_parse_clienthello,
     ext_ticket_add_serverhello,
   },
   {
     TLSEXT_TYPE_signature_algorithms,
     NULL,
     ext_sigalgs_add_clienthello,
-    ext_sigalgs_parse_serverhello,
+    forbid_parse_serverhello,
     ext_sigalgs_parse_clienthello,
-    ext_sigalgs_add_serverhello,
+    dont_add_serverhello,
   },
   {
     TLSEXT_TYPE_status_request,
-    ext_ocsp_init,
+    NULL,
     ext_ocsp_add_clienthello,
     ext_ocsp_parse_serverhello,
     ext_ocsp_parse_clienthello,
@@ -2035,7 +2583,7 @@
   },
   {
     TLSEXT_TYPE_next_proto_neg,
-    ext_npn_init,
+    NULL,
     ext_npn_add_clienthello,
     ext_npn_parse_serverhello,
     ext_npn_parse_clienthello,
@@ -2051,10 +2599,11 @@
   },
   {
     TLSEXT_TYPE_application_layer_protocol_negotiation,
-    ext_alpn_init,
+    NULL,
     ext_alpn_add_clienthello,
     ext_alpn_parse_serverhello,
-    ext_alpn_parse_clienthello,
+    /* ALPN is negotiated late in |ssl_negotiate_alpn|. */
+    ignore_parse_clienthello,
     ext_alpn_add_serverhello,
   },
   {
@@ -2082,24 +2631,66 @@
     ext_ec_point_add_serverhello,
   },
   {
-    TLSEXT_TYPE_elliptic_curves,
-    ext_ec_curves_init,
-    ext_ec_curves_add_clienthello,
-    ext_ec_curves_parse_serverhello,
-    ext_ec_curves_parse_clienthello,
-    ext_ec_curves_add_serverhello,
+    TLSEXT_TYPE_key_share,
+    NULL,
+    ext_key_share_add_clienthello,
+    forbid_parse_serverhello,
+    ignore_parse_clienthello,
+    dont_add_serverhello,
+  },
+  {
+    TLSEXT_TYPE_psk_key_exchange_modes,
+    NULL,
+    ext_psk_key_exchange_modes_add_clienthello,
+    forbid_parse_serverhello,
+    ext_psk_key_exchange_modes_parse_clienthello,
+    dont_add_serverhello,
+  },
+  {
+    TLSEXT_TYPE_early_data,
+    NULL,
+    ext_early_data_add_clienthello,
+    ext_early_data_parse_serverhello,
+    ext_early_data_parse_clienthello,
+    ext_early_data_add_serverhello,
+  },
+  {
+    TLSEXT_TYPE_supported_versions,
+    NULL,
+    ext_supported_versions_add_clienthello,
+    forbid_parse_serverhello,
+    ignore_parse_clienthello,
+    dont_add_serverhello,
+  },
+  {
+    TLSEXT_TYPE_cookie,
+    NULL,
+    ext_cookie_add_clienthello,
+    forbid_parse_serverhello,
+    ignore_parse_clienthello,
+    dont_add_serverhello,
+  },
+  /* The final extension must be non-empty. WebSphere Application Server 7.0 is
+   * intolerant to the last extension being zero-length. See
+   * https://crbug.com/363583. */
+  {
+    TLSEXT_TYPE_supported_groups,
+    NULL,
+    ext_supported_groups_add_clienthello,
+    ext_supported_groups_parse_serverhello,
+    ext_supported_groups_parse_clienthello,
+    ext_supported_groups_add_serverhello,
   },
 };
 
 #define kNumExtensions (sizeof(kExtensions) / sizeof(struct tls_extension))
 
 OPENSSL_COMPILE_ASSERT(kNumExtensions <=
-                           sizeof(((SSL *)NULL)->s3->tmp.extensions.sent) * 8,
+                           sizeof(((SSL_HANDSHAKE *)NULL)->extensions.sent) * 8,
                        too_many_extensions_for_sent_bitset);
-OPENSSL_COMPILE_ASSERT(kNumExtensions <=
-                           sizeof(((SSL *)NULL)->s3->tmp.extensions.received) *
-                               8,
-                       too_many_extensions_for_received_bitset);
+OPENSSL_COMPILE_ASSERT(
+    kNumExtensions <= sizeof(((SSL_HANDSHAKE *)NULL)->extensions.received) * 8,
+    too_many_extensions_for_received_bitset);
 
 static const struct tls_extension *tls_extension_find(uint32_t *out_index,
                                                       uint16_t value) {
@@ -2120,9 +2711,10 @@
          tls_extension_find(&index, extension_value) != NULL;
 }
 
-int ssl_add_clienthello_tlsext(SSL *ssl, CBB *out, size_t header_len) {
-  /* don't add extensions for SSLv3 unless doing secure renegotiation */
-  if (ssl->client_version == SSL3_VERSION &&
+int ssl_add_clienthello_tlsext(SSL_HANDSHAKE *hs, CBB *out, size_t header_len) {
+  SSL *const ssl = hs->ssl;
+  /* Don't add extensions for SSLv3 unless doing secure renegotiation. */
+  if (hs->client_version == SSL3_VERSION &&
       !ssl->s3->send_connection_binding) {
     return 1;
   }
@@ -2132,44 +2724,73 @@
     goto err;
   }
 
-  ssl->s3->tmp.extensions.sent = 0;
-  ssl->s3->tmp.custom_extensions.sent = 0;
+  hs->extensions.sent = 0;
+  hs->custom_extensions.sent = 0;
 
-  size_t i;
-  for (i = 0; i < kNumExtensions; i++) {
+  for (size_t i = 0; i < kNumExtensions; i++) {
     if (kExtensions[i].init != NULL) {
-      kExtensions[i].init(ssl);
+      kExtensions[i].init(hs);
     }
   }
 
-  for (i = 0; i < kNumExtensions; i++) {
+  uint16_t grease_ext1 = 0;
+  if (ssl->ctx->grease_enabled) {
+    /* Add a fake empty extension. See draft-davidben-tls-grease-01. */
+    grease_ext1 = ssl_get_grease_value(ssl, ssl_grease_extension1);
+    if (!CBB_add_u16(&extensions, grease_ext1) ||
+        !CBB_add_u16(&extensions, 0 /* zero length */)) {
+      goto err;
+    }
+  }
+
+  for (size_t i = 0; i < kNumExtensions; i++) {
     const size_t len_before = CBB_len(&extensions);
-    if (!kExtensions[i].add_clienthello(ssl, &extensions)) {
+    if (!kExtensions[i].add_clienthello(hs, &extensions)) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_ADDING_EXTENSION);
-      ERR_add_error_dataf("extension: %u", (unsigned)kExtensions[i].value);
+      ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value);
       goto err;
     }
 
     if (CBB_len(&extensions) != len_before) {
-      ssl->s3->tmp.extensions.sent |= (1u << i);
+      hs->extensions.sent |= (1u << i);
     }
   }
 
-  if (!custom_ext_add_clienthello(ssl, &extensions)) {
+  if (!custom_ext_add_clienthello(hs, &extensions)) {
     goto err;
   }
 
-  if (!SSL_IS_DTLS(ssl)) {
-    header_len += 2 + CBB_len(&extensions);
+  if (ssl->ctx->grease_enabled) {
+    /* Add a fake non-empty extension. See draft-davidben-tls-grease-01. */
+    uint16_t grease_ext2 = ssl_get_grease_value(ssl, ssl_grease_extension2);
+
+    /* The two fake extensions must not have the same value. GREASE values are
+     * of the form 0x1a1a, 0x2a2a, 0x3a3a, etc., so XOR to generate a different
+     * one. */
+    if (grease_ext1 == grease_ext2) {
+      grease_ext2 ^= 0x1010;
+    }
+
+    if (!CBB_add_u16(&extensions, grease_ext2) ||
+        !CBB_add_u16(&extensions, 1 /* one byte length */) ||
+        !CBB_add_u8(&extensions, 0 /* single zero byte as contents */)) {
+      goto err;
+    }
+  }
+
+  if (!SSL_is_dtls(ssl)) {
+    size_t psk_extension_len = ext_pre_shared_key_clienthello_length(hs);
+    header_len += 2 + CBB_len(&extensions) + psk_extension_len;
     if (header_len > 0xff && header_len < 0x200) {
       /* Add padding to workaround bugs in F5 terminators. See RFC 7685.
        *
        * NB: because this code works out the length of all existing extensions
        * it MUST always appear last. */
       size_t padding_len = 0x200 - header_len;
-      /* Extensions take at least four bytes to encode. Always include least
+      /* Extensions take at least four bytes to encode. Always include at least
        * one byte of data if including the extension. WebSphere Application
-       * Server 7.0 is intolerant to the last extension being zero-length. */
+       * Server 7.0 is intolerant to the last extension being zero-length. See
+       * https://crbug.com/363583. */
       if (padding_len >= 4 + 1) {
         padding_len -= 4;
       } else {
@@ -2183,10 +2804,15 @@
         goto err;
       }
 
-      memset(padding_bytes, 0, padding_len);
+      OPENSSL_memset(padding_bytes, 0, padding_len);
     }
   }
 
+  /* The PSK extension must be last, including after the padding. */
+  if (!ext_pre_shared_key_add_clienthello(hs, &extensions)) {
+    goto err;
+  }
+
   /* Discard empty extensions blocks. */
   if (CBB_len(&extensions) == 0) {
     CBB_discard_child(out);
@@ -2199,32 +2825,33 @@
   return 0;
 }
 
-int ssl_add_serverhello_tlsext(SSL *ssl, CBB *out) {
+int ssl_add_serverhello_tlsext(SSL_HANDSHAKE *hs, CBB *out) {
+  SSL *const ssl = hs->ssl;
   CBB extensions;
   if (!CBB_add_u16_length_prefixed(out, &extensions)) {
     goto err;
   }
 
-  unsigned i;
-  for (i = 0; i < kNumExtensions; i++) {
-    if (!(ssl->s3->tmp.extensions.received & (1u << i))) {
+  for (unsigned i = 0; i < kNumExtensions; i++) {
+    if (!(hs->extensions.received & (1u << i))) {
       /* Don't send extensions that were not received. */
       continue;
     }
 
-    if (!kExtensions[i].add_serverhello(ssl, &extensions)) {
+    if (!kExtensions[i].add_serverhello(hs, &extensions)) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_ADDING_EXTENSION);
-      ERR_add_error_dataf("extension: %u", (unsigned)kExtensions[i].value);
+      ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value);
       goto err;
     }
   }
 
-  if (!custom_ext_add_serverhello(ssl, &extensions)) {
+  if (!custom_ext_add_serverhello(hs, &extensions)) {
     goto err;
   }
 
-  /* Discard empty extensions blocks. */
-  if (CBB_len(&extensions) == 0) {
+  /* Discard empty extensions blocks before TLS 1.3. */
+  if (ssl3_protocol_version(ssl) < TLS1_3_VERSION &&
+      CBB_len(&extensions) == 0) {
     CBB_discard_child(out);
   }
 
@@ -2235,96 +2862,102 @@
   return 0;
 }
 
-static int ssl_scan_clienthello_tlsext(SSL *ssl, CBS *cbs, int *out_alert) {
-  size_t i;
-  for (i = 0; i < kNumExtensions; i++) {
+static int ssl_scan_clienthello_tlsext(SSL_HANDSHAKE *hs,
+                                       const SSL_CLIENT_HELLO *client_hello,
+                                       int *out_alert) {
+  SSL *const ssl = hs->ssl;
+  for (size_t i = 0; i < kNumExtensions; i++) {
     if (kExtensions[i].init != NULL) {
-      kExtensions[i].init(ssl);
+      kExtensions[i].init(hs);
     }
   }
 
-  ssl->s3->tmp.extensions.received = 0;
-  ssl->s3->tmp.custom_extensions.received = 0;
-  /* The renegotiation extension must always be at index zero because the
-   * |received| and |sent| bitsets need to be tweaked when the "extension" is
-   * sent as an SCSV. */
-  assert(kExtensions[0].value == TLSEXT_TYPE_renegotiate);
+  hs->extensions.received = 0;
+  hs->custom_extensions.received = 0;
 
-  /* There may be no extensions. */
-  if (CBS_len(cbs) != 0) {
-    /* Decode the extensions block and check it is valid. */
-    CBS extensions;
-    if (!CBS_get_u16_length_prefixed(cbs, &extensions) ||
-        !tls1_check_duplicate_extensions(&extensions)) {
+  CBS extensions;
+  CBS_init(&extensions, client_hello->extensions, client_hello->extensions_len);
+  while (CBS_len(&extensions) != 0) {
+    uint16_t type;
+    CBS extension;
+
+    /* Decode the next extension. */
+    if (!CBS_get_u16(&extensions, &type) ||
+        !CBS_get_u16_length_prefixed(&extensions, &extension)) {
       *out_alert = SSL_AD_DECODE_ERROR;
       return 0;
     }
 
-    while (CBS_len(&extensions) != 0) {
-      uint16_t type;
-      CBS extension;
+    /* RFC 5746 made the existence of extensions in SSL 3.0 somewhat
+     * ambiguous. Ignore all but the renegotiation_info extension. */
+    if (ssl->version == SSL3_VERSION && type != TLSEXT_TYPE_renegotiate) {
+      continue;
+    }
 
-      /* Decode the next extension. */
-      if (!CBS_get_u16(&extensions, &type) ||
-          !CBS_get_u16_length_prefixed(&extensions, &extension)) {
-        *out_alert = SSL_AD_DECODE_ERROR;
-        return 0;
-      }
+    unsigned ext_index;
+    const struct tls_extension *const ext =
+        tls_extension_find(&ext_index, type);
 
-      /* RFC 5746 made the existence of extensions in SSL 3.0 somewhat
-       * ambiguous. Ignore all but the renegotiation_info extension. */
-      if (ssl->version == SSL3_VERSION && type != TLSEXT_TYPE_renegotiate) {
-        continue;
-      }
-
-      unsigned ext_index;
-      const struct tls_extension *const ext =
-          tls_extension_find(&ext_index, type);
-
-      if (ext == NULL) {
-        if (!custom_ext_parse_clienthello(ssl, out_alert, type, &extension)) {
-          OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION);
-          return 0;
-        }
-        continue;
-      }
-
-      ssl->s3->tmp.extensions.received |= (1u << ext_index);
-      uint8_t alert = SSL_AD_DECODE_ERROR;
-      if (!ext->parse_clienthello(ssl, &alert, &extension)) {
-        *out_alert = alert;
+    if (ext == NULL) {
+      if (!custom_ext_parse_clienthello(hs, out_alert, type, &extension)) {
         OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION);
-        ERR_add_error_dataf("extension: %u", (unsigned)type);
         return 0;
       }
+      continue;
+    }
+
+    hs->extensions.received |= (1u << ext_index);
+    uint8_t alert = SSL_AD_DECODE_ERROR;
+    if (!ext->parse_clienthello(hs, &alert, &extension)) {
+      *out_alert = alert;
+      OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION);
+      ERR_add_error_dataf("extension %u", (unsigned)type);
+      return 0;
     }
   }
 
-  for (i = 0; i < kNumExtensions; i++) {
-    if (!(ssl->s3->tmp.extensions.received & (1u << i))) {
-      /* Extension wasn't observed so call the callback with a NULL
-       * parameter. */
-      uint8_t alert = SSL_AD_DECODE_ERROR;
-      if (!kExtensions[i].parse_clienthello(ssl, &alert, NULL)) {
-        OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_EXTENSION);
-        ERR_add_error_dataf("extension: %u", (unsigned)kExtensions[i].value);
-        *out_alert = alert;
-        return 0;
-      }
+  for (size_t i = 0; i < kNumExtensions; i++) {
+    if (hs->extensions.received & (1u << i)) {
+      continue;
+    }
+
+    CBS *contents = NULL, fake_contents;
+    static const uint8_t kFakeRenegotiateExtension[] = {0};
+    if (kExtensions[i].value == TLSEXT_TYPE_renegotiate &&
+        ssl_client_cipher_list_contains_cipher(client_hello,
+                                               SSL3_CK_SCSV & 0xffff)) {
+      /* The renegotiation SCSV was received so pretend that we received a
+       * renegotiation extension. */
+      CBS_init(&fake_contents, kFakeRenegotiateExtension,
+               sizeof(kFakeRenegotiateExtension));
+      contents = &fake_contents;
+      hs->extensions.received |= (1u << i);
+    }
+
+    /* Extension wasn't observed so call the callback with a NULL
+     * parameter. */
+    uint8_t alert = SSL_AD_DECODE_ERROR;
+    if (!kExtensions[i].parse_clienthello(hs, &alert, contents)) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_EXTENSION);
+      ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value);
+      *out_alert = alert;
+      return 0;
     }
   }
 
   return 1;
 }
 
-int ssl_parse_clienthello_tlsext(SSL *ssl, CBS *cbs) {
-  int alert = -1;
-  if (ssl_scan_clienthello_tlsext(ssl, cbs, &alert) <= 0) {
+int ssl_parse_clienthello_tlsext(SSL_HANDSHAKE *hs,
+                                 const SSL_CLIENT_HELLO *client_hello) {
+  SSL *const ssl = hs->ssl;
+  int alert = SSL_AD_DECODE_ERROR;
+  if (ssl_scan_clienthello_tlsext(hs, client_hello, &alert) <= 0) {
     ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
     return 0;
   }
 
-  if (ssl_check_clienthello_tlsext(ssl) <= 0) {
+  if (ssl_check_clienthello_tlsext(hs) <= 0) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_TLSEXT);
     return 0;
   }
@@ -2332,72 +2965,77 @@
   return 1;
 }
 
-OPENSSL_COMPILE_ASSERT(kNumExtensions <= sizeof(uint32_t) * 8, too_many_bits);
+static int ssl_scan_serverhello_tlsext(SSL_HANDSHAKE *hs, CBS *cbs,
+                                       int *out_alert) {
+  SSL *const ssl = hs->ssl;
+  /* Before TLS 1.3, ServerHello extensions blocks may be omitted if empty. */
+  if (CBS_len(cbs) == 0 && ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
+    return 1;
+  }
 
-static int ssl_scan_serverhello_tlsext(SSL *ssl, CBS *cbs, int *out_alert) {
+  /* Decode the extensions block and check it is valid. */
+  CBS extensions;
+  if (!CBS_get_u16_length_prefixed(cbs, &extensions) ||
+      !tls1_check_duplicate_extensions(&extensions)) {
+    *out_alert = SSL_AD_DECODE_ERROR;
+    return 0;
+  }
+
   uint32_t received = 0;
+  while (CBS_len(&extensions) != 0) {
+    uint16_t type;
+    CBS extension;
 
-  if (CBS_len(cbs) != 0) {
-    /* Decode the extensions block and check it is valid. */
-    CBS extensions;
-    if (!CBS_get_u16_length_prefixed(cbs, &extensions) ||
-        !tls1_check_duplicate_extensions(&extensions)) {
+    /* Decode the next extension. */
+    if (!CBS_get_u16(&extensions, &type) ||
+        !CBS_get_u16_length_prefixed(&extensions, &extension)) {
       *out_alert = SSL_AD_DECODE_ERROR;
       return 0;
     }
 
+    unsigned ext_index;
+    const struct tls_extension *const ext =
+        tls_extension_find(&ext_index, type);
 
-    while (CBS_len(&extensions) != 0) {
-      uint16_t type;
-      CBS extension;
-
-      /* Decode the next extension. */
-      if (!CBS_get_u16(&extensions, &type) ||
-          !CBS_get_u16_length_prefixed(&extensions, &extension)) {
-        *out_alert = SSL_AD_DECODE_ERROR;
+    if (ext == NULL) {
+      if (!custom_ext_parse_serverhello(hs, out_alert, type, &extension)) {
         return 0;
       }
+      continue;
+    }
 
-      unsigned ext_index;
-      const struct tls_extension *const ext =
-          tls_extension_find(&ext_index, type);
+    OPENSSL_COMPILE_ASSERT(kNumExtensions <= sizeof(hs->extensions.sent) * 8,
+                           too_many_bits);
 
-      if (ext == NULL) {
-        if (!custom_ext_parse_serverhello(ssl, out_alert, type, &extension)) {
-          return 0;
-        }
-        continue;
-      }
+    if (!(hs->extensions.sent & (1u << ext_index)) &&
+        type != TLSEXT_TYPE_renegotiate) {
+      /* If the extension was never sent then it is illegal, except for the
+       * renegotiation extension which, in SSL 3.0, is signaled via SCSV. */
+      OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
+      ERR_add_error_dataf("extension :%u", (unsigned)type);
+      *out_alert = SSL_AD_UNSUPPORTED_EXTENSION;
+      return 0;
+    }
 
-      if (!(ssl->s3->tmp.extensions.sent & (1u << ext_index))) {
-        /* If the extension was never sent then it is illegal. */
-        OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
-        ERR_add_error_dataf("extension :%u", (unsigned)type);
-        *out_alert = SSL_AD_DECODE_ERROR;
-        return 0;
-      }
+    received |= (1u << ext_index);
 
-      received |= (1u << ext_index);
-
-      uint8_t alert = SSL_AD_DECODE_ERROR;
-      if (!ext->parse_serverhello(ssl, &alert, &extension)) {
-        OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION);
-        ERR_add_error_dataf("extension: %u", (unsigned)type);
-        *out_alert = alert;
-        return 0;
-      }
+    uint8_t alert = SSL_AD_DECODE_ERROR;
+    if (!ext->parse_serverhello(hs, &alert, &extension)) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION);
+      ERR_add_error_dataf("extension %u", (unsigned)type);
+      *out_alert = alert;
+      return 0;
     }
   }
 
-  size_t i;
-  for (i = 0; i < kNumExtensions; i++) {
+  for (size_t i = 0; i < kNumExtensions; i++) {
     if (!(received & (1u << i))) {
       /* Extension wasn't observed so call the callback with a NULL
        * parameter. */
       uint8_t alert = SSL_AD_DECODE_ERROR;
-      if (!kExtensions[i].parse_serverhello(ssl, &alert, NULL)) {
+      if (!kExtensions[i].parse_serverhello(hs, &alert, NULL)) {
         OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_EXTENSION);
-        ERR_add_error_dataf("extension: %u", (unsigned)kExtensions[i].value);
+        ERR_add_error_dataf("extension %u", (unsigned)kExtensions[i].value);
         *out_alert = alert;
         return 0;
       }
@@ -2407,20 +3045,17 @@
   return 1;
 }
 
-static int ssl_check_clienthello_tlsext(SSL *ssl) {
+static int ssl_check_clienthello_tlsext(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   int ret = SSL_TLSEXT_ERR_NOACK;
   int al = SSL_AD_UNRECOGNIZED_NAME;
 
-  /* The handling of the ECPointFormats extension is done elsewhere, namely in
-   * ssl3_choose_cipher in s3_lib.c. */
-
-  if (ssl->ctx != NULL && ssl->ctx->tlsext_servername_callback != 0) {
+  if (ssl->ctx->tlsext_servername_callback != 0) {
     ret = ssl->ctx->tlsext_servername_callback(ssl, &al,
-                                             ssl->ctx->tlsext_servername_arg);
-  } else if (ssl->initial_ctx != NULL &&
-             ssl->initial_ctx->tlsext_servername_callback != 0) {
-    ret = ssl->initial_ctx->tlsext_servername_callback(
-        ssl, &al, ssl->initial_ctx->tlsext_servername_arg);
+                                               ssl->ctx->tlsext_servername_arg);
+  } else if (ssl->session_ctx->tlsext_servername_callback != 0) {
+    ret = ssl->session_ctx->tlsext_servername_callback(
+        ssl, &al, ssl->session_ctx->tlsext_servername_arg);
   }
 
   switch (ret) {
@@ -2428,12 +3063,8 @@
       ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
       return -1;
 
-    case SSL_TLSEXT_ERR_ALERT_WARNING:
-      ssl3_send_alert(ssl, SSL3_AL_WARNING, al);
-      return 1;
-
     case SSL_TLSEXT_ERR_NOACK:
-      ssl->s3->tmp.should_ack_sni = 0;
+      hs->should_ack_sni = 0;
       return 1;
 
     default:
@@ -2441,54 +3072,23 @@
   }
 }
 
-static int ssl_check_serverhello_tlsext(SSL *ssl) {
-  int ret = SSL_TLSEXT_ERR_OK;
-  int al = SSL_AD_UNRECOGNIZED_NAME;
-
-  if (ssl->ctx != NULL && ssl->ctx->tlsext_servername_callback != 0) {
-    ret = ssl->ctx->tlsext_servername_callback(ssl, &al,
-                                             ssl->ctx->tlsext_servername_arg);
-  } else if (ssl->initial_ctx != NULL &&
-             ssl->initial_ctx->tlsext_servername_callback != 0) {
-    ret = ssl->initial_ctx->tlsext_servername_callback(
-        ssl, &al, ssl->initial_ctx->tlsext_servername_arg);
-  }
-
-  switch (ret) {
-    case SSL_TLSEXT_ERR_ALERT_FATAL:
-      ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
-      return -1;
-
-    case SSL_TLSEXT_ERR_ALERT_WARNING:
-      ssl3_send_alert(ssl, SSL3_AL_WARNING, al);
-      return 1;
-
-    default:
-      return 1;
-  }
-}
-
-int ssl_parse_serverhello_tlsext(SSL *ssl, CBS *cbs) {
-  int alert = -1;
-  if (ssl_scan_serverhello_tlsext(ssl, cbs, &alert) <= 0) {
+int ssl_parse_serverhello_tlsext(SSL_HANDSHAKE *hs, CBS *cbs) {
+  SSL *const ssl = hs->ssl;
+  int alert = SSL_AD_DECODE_ERROR;
+  if (ssl_scan_serverhello_tlsext(hs, cbs, &alert) <= 0) {
     ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
     return 0;
   }
 
-  if (ssl_check_serverhello_tlsext(ssl) <= 0) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_SERVERHELLO_TLSEXT);
-    return 0;
-  }
-
   return 1;
 }
 
-int tls_process_ticket(SSL *ssl, SSL_SESSION **out_session,
-                       int *out_send_ticket, const uint8_t *ticket,
-                       size_t ticket_len, const uint8_t *session_id,
-                       size_t session_id_len) {
-  int ret = 1; /* Most errors are non-fatal. */
-  SSL_CTX *ssl_ctx = ssl->initial_ctx;
+static enum ssl_ticket_aead_result_t
+ssl_decrypt_ticket_with_cipher_ctx(SSL *ssl, uint8_t **out, size_t *out_len,
+                                   int *out_renew_ticket, const uint8_t *ticket,
+                                   size_t ticket_len) {
+  enum ssl_ticket_aead_result_t ret = ssl_ticket_aead_ignore_ticket;
+  const SSL_CTX *const ssl_ctx = ssl->session_ctx;
   uint8_t *plaintext = NULL;
 
   HMAC_CTX hmac_ctx;
@@ -2496,25 +3096,12 @@
   EVP_CIPHER_CTX cipher_ctx;
   EVP_CIPHER_CTX_init(&cipher_ctx);
 
-  *out_send_ticket = 0;
-  *out_session = NULL;
-
-  if (session_id_len > SSL_MAX_SSL_SESSION_ID_LENGTH) {
-    goto done;
-  }
-
-  if (ticket_len == 0) {
-    /* The client will accept a ticket but doesn't currently have one. */
-    *out_send_ticket = 1;
-    goto done;
-  }
-
   /* Ensure there is room for the key name and the largest IV
    * |tlsext_ticket_key_cb| may try to consume. The real limit may be lower, but
    * the maximum IV length should be well under the minimum size for the
    * session material and HMAC. */
   if (ticket_len < SSL_TICKET_KEY_NAME_LEN + EVP_MAX_IV_LENGTH) {
-    goto done;
+    goto out;
   }
   const uint8_t *iv = ticket + SSL_TICKET_KEY_NAME_LEN;
 
@@ -2523,28 +3110,26 @@
         ssl, (uint8_t *)ticket /* name */, (uint8_t *)iv, &cipher_ctx,
         &hmac_ctx, 0 /* decrypt */);
     if (cb_ret < 0) {
-      ret = 0;
-      goto done;
-    }
-    if (cb_ret == 0) {
-      goto done;
-    }
-    if (cb_ret == 2) {
-      *out_send_ticket = 1;
+      ret = ssl_ticket_aead_error;
+      goto out;
+    } else if (cb_ret == 0) {
+      goto out;
+    } else if (cb_ret == 2) {
+      *out_renew_ticket = 1;
     }
   } else {
     /* Check the key name matches. */
-    if (memcmp(ticket, ssl_ctx->tlsext_tick_key_name,
-               SSL_TICKET_KEY_NAME_LEN) != 0) {
-      goto done;
+    if (OPENSSL_memcmp(ticket, ssl_ctx->tlsext_tick_key_name,
+                       SSL_TICKET_KEY_NAME_LEN) != 0) {
+      goto out;
     }
     if (!HMAC_Init_ex(&hmac_ctx, ssl_ctx->tlsext_tick_hmac_key,
                       sizeof(ssl_ctx->tlsext_tick_hmac_key), tlsext_tick_md(),
                       NULL) ||
         !EVP_DecryptInit_ex(&cipher_ctx, EVP_aes_128_cbc(), NULL,
                             ssl_ctx->tlsext_tick_aes_key, iv)) {
-      ret = 0;
-      goto done;
+      ret = ssl_ticket_aead_error;
+      goto out;
     }
   }
   size_t iv_len = EVP_CIPHER_CTX_iv_length(&cipher_ctx);
@@ -2554,12 +3139,17 @@
   size_t mac_len = HMAC_size(&hmac_ctx);
   if (ticket_len < SSL_TICKET_KEY_NAME_LEN + iv_len + 1 + mac_len) {
     /* The ticket must be large enough for key name, IV, data, and MAC. */
-    goto done;
+    goto out;
   }
   HMAC_Update(&hmac_ctx, ticket, ticket_len - mac_len);
   HMAC_Final(&hmac_ctx, mac, NULL);
-  if (CRYPTO_memcmp(mac, ticket + (ticket_len - mac_len), mac_len) != 0) {
-    goto done;
+  int mac_ok =
+      CRYPTO_memcmp(mac, ticket + (ticket_len - mac_len), mac_len) == 0;
+#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
+  mac_ok = 1;
+#endif
+  if (!mac_ok) {
+    goto out;
   }
 
   /* Decrypt the session data. */
@@ -2568,140 +3158,120 @@
                           mac_len;
   plaintext = OPENSSL_malloc(ciphertext_len);
   if (plaintext == NULL) {
-    ret = 0;
-    goto done;
+    ret = ssl_ticket_aead_error;
+    goto out;
   }
+  size_t plaintext_len;
+#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
+  OPENSSL_memcpy(plaintext, ciphertext, ciphertext_len);
+  plaintext_len = ciphertext_len;
+#else
   if (ciphertext_len >= INT_MAX) {
-    goto done;
+    goto out;
   }
   int len1, len2;
   if (!EVP_DecryptUpdate(&cipher_ctx, plaintext, &len1, ciphertext,
                          (int)ciphertext_len) ||
       !EVP_DecryptFinal_ex(&cipher_ctx, plaintext + len1, &len2)) {
-    ERR_clear_error(); /* Don't leave an error on the queue. */
-    goto done;
+    ERR_clear_error();
+    goto out;
   }
+  plaintext_len = (size_t)(len1) + len2;
+#endif
 
-  /* Decode the session. */
-  SSL_SESSION *session = SSL_SESSION_from_bytes(plaintext, len1 + len2);
-  if (session == NULL) {
-    ERR_clear_error(); /* Don't leave an error on the queue. */
-    goto done;
-  }
+  *out = plaintext;
+  plaintext = NULL;
+  *out_len = plaintext_len;
+  ret = ssl_ticket_aead_success;
 
-  /* Copy the client's session ID into the new session, to denote the ticket has
-   * been accepted. */
-  memcpy(session->session_id, session_id, session_id_len);
-  session->session_id_length = session_id_len;
-
-  *out_session = session;
-
-done:
+out:
   OPENSSL_free(plaintext);
   HMAC_CTX_cleanup(&hmac_ctx);
   EVP_CIPHER_CTX_cleanup(&cipher_ctx);
   return ret;
 }
 
-/* Tables to translate from NIDs to TLS v1.2 ids */
-typedef struct {
-  int nid;
-  int id;
-} tls12_lookup;
-
-static const tls12_lookup tls12_md[] = {{NID_md5, TLSEXT_hash_md5},
-                                        {NID_sha1, TLSEXT_hash_sha1},
-                                        {NID_sha224, TLSEXT_hash_sha224},
-                                        {NID_sha256, TLSEXT_hash_sha256},
-                                        {NID_sha384, TLSEXT_hash_sha384},
-                                        {NID_sha512, TLSEXT_hash_sha512}};
-
-static const tls12_lookup tls12_sig[] = {{EVP_PKEY_RSA, TLSEXT_signature_rsa},
-                                         {EVP_PKEY_EC, TLSEXT_signature_ecdsa}};
-
-static int tls12_find_id(int nid, const tls12_lookup *table, size_t tlen) {
-  size_t i;
-  for (i = 0; i < tlen; i++) {
-    if (table[i].nid == nid) {
-      return table[i].id;
-    }
+static enum ssl_ticket_aead_result_t ssl_decrypt_ticket_with_method(
+    SSL *ssl, uint8_t **out, size_t *out_len, int *out_renew_ticket,
+    const uint8_t *ticket, size_t ticket_len) {
+  uint8_t *plaintext = OPENSSL_malloc(ticket_len);
+  if (plaintext == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+    return ssl_ticket_aead_error;
   }
 
-  return -1;
-}
+  size_t plaintext_len;
+  const enum ssl_ticket_aead_result_t result =
+      ssl->session_ctx->ticket_aead_method->open(
+          ssl, plaintext, &plaintext_len, ticket_len, ticket, ticket_len);
 
-int tls12_get_sigid(int pkey_type) {
-  return tls12_find_id(pkey_type, tls12_sig,
-                       sizeof(tls12_sig) / sizeof(tls12_lookup));
-}
-
-int tls12_add_sigandhash(SSL *ssl, CBB *out, const EVP_MD *md) {
-  int md_id = tls12_find_id(EVP_MD_type(md), tls12_md,
-                            sizeof(tls12_md) / sizeof(tls12_lookup));
-  int sig_id = tls12_get_sigid(ssl_private_key_type(ssl));
-
-  return md_id != -1 &&
-         sig_id != -1 &&
-         CBB_add_u8(out, (uint8_t)md_id) &&
-         CBB_add_u8(out, (uint8_t)sig_id);
-}
-
-const EVP_MD *tls12_get_hash(uint8_t hash_alg) {
-  switch (hash_alg) {
-    case TLSEXT_hash_md5:
-      return EVP_md5();
-
-    case TLSEXT_hash_sha1:
-      return EVP_sha1();
-
-    case TLSEXT_hash_sha224:
-      return EVP_sha224();
-
-    case TLSEXT_hash_sha256:
-      return EVP_sha256();
-
-    case TLSEXT_hash_sha384:
-      return EVP_sha384();
-
-    case TLSEXT_hash_sha512:
-      return EVP_sha512();
-
-    default:
-      return NULL;
+  if (result == ssl_ticket_aead_success) {
+    *out = plaintext;
+    plaintext = NULL;
+    *out_len = plaintext_len;
   }
+
+  OPENSSL_free(plaintext);
+  return result;
 }
 
-/* tls12_get_pkey_type returns the EVP_PKEY type corresponding to TLS signature
- * algorithm |sig_alg|. It returns -1 if the type is unknown. */
-static int tls12_get_pkey_type(uint8_t sig_alg) {
-  switch (sig_alg) {
-    case TLSEXT_signature_rsa:
-      return EVP_PKEY_RSA;
+enum ssl_ticket_aead_result_t ssl_process_ticket(
+    SSL *ssl, SSL_SESSION **out_session, int *out_renew_ticket,
+    const uint8_t *ticket, size_t ticket_len, const uint8_t *session_id,
+    size_t session_id_len) {
+  *out_renew_ticket = 0;
+  *out_session = NULL;
 
-    case TLSEXT_signature_ecdsa:
-      return EVP_PKEY_EC;
-
-    default:
-      return -1;
+  if ((SSL_get_options(ssl) & SSL_OP_NO_TICKET) ||
+      session_id_len > SSL_MAX_SSL_SESSION_ID_LENGTH) {
+    return ssl_ticket_aead_ignore_ticket;
   }
+
+  uint8_t *plaintext = NULL;
+  size_t plaintext_len;
+  enum ssl_ticket_aead_result_t result;
+  if (ssl->session_ctx->ticket_aead_method != NULL) {
+    result = ssl_decrypt_ticket_with_method(
+        ssl, &plaintext, &plaintext_len, out_renew_ticket, ticket, ticket_len);
+  } else {
+    result = ssl_decrypt_ticket_with_cipher_ctx(
+        ssl, &plaintext, &plaintext_len, out_renew_ticket, ticket, ticket_len);
+  }
+
+  if (result != ssl_ticket_aead_success) {
+    return result;
+  }
+
+  /* Decode the session. */
+  SSL_SESSION *session =
+      SSL_SESSION_from_bytes(plaintext, plaintext_len, ssl->ctx);
+  OPENSSL_free(plaintext);
+
+  if (session == NULL) {
+    ERR_clear_error(); /* Don't leave an error on the queue. */
+    return ssl_ticket_aead_ignore_ticket;
+  }
+
+  /* Copy the client's session ID into the new session, to denote the ticket has
+   * been accepted. */
+  OPENSSL_memcpy(session->session_id, session_id, session_id_len);
+  session->session_id_length = session_id_len;
+
+  *out_session = session;
+  return ssl_ticket_aead_success;
 }
 
-OPENSSL_COMPILE_ASSERT(sizeof(TLS_SIGALGS) == 2,
-    sizeof_tls_sigalgs_is_not_two);
-
-int tls1_parse_peer_sigalgs(SSL *ssl, const CBS *in_sigalgs) {
+int tls1_parse_peer_sigalgs(SSL_HANDSHAKE *hs, const CBS *in_sigalgs) {
   /* Extension ignored for inappropriate versions */
-  if (!SSL_USE_SIGALGS(ssl)) {
+  if (ssl3_protocol_version(hs->ssl) < TLS1_2_VERSION) {
     return 1;
   }
 
-  CERT *const cert = ssl->cert;
-  OPENSSL_free(cert->peer_sigalgs);
-  cert->peer_sigalgs = NULL;
-  cert->peer_sigalgslen = 0;
+  OPENSSL_free(hs->peer_sigalgs);
+  hs->peer_sigalgs = NULL;
+  hs->num_peer_sigalgs = 0;
 
   size_t num_sigalgs = CBS_len(in_sigalgs);
-
   if (num_sigalgs % 2 != 0) {
     return 0;
   }
@@ -2713,22 +3283,18 @@
     return 1;
   }
 
-  /* This multiplication doesn't overflow because sizeof(TLS_SIGALGS) is two
-   * (statically asserted above) and we just divided |num_sigalgs| by two. */
-  cert->peer_sigalgs = OPENSSL_malloc(num_sigalgs * sizeof(TLS_SIGALGS));
-  if (cert->peer_sigalgs == NULL) {
+  /* This multiplication doesn't overflow because sizeof(uint16_t) is two
+   * and we just divided |num_sigalgs| by two. */
+  hs->peer_sigalgs = OPENSSL_malloc(num_sigalgs * sizeof(uint16_t));
+  if (hs->peer_sigalgs == NULL) {
     return 0;
   }
-  cert->peer_sigalgslen = num_sigalgs;
+  hs->num_peer_sigalgs = num_sigalgs;
 
   CBS sigalgs;
   CBS_init(&sigalgs, CBS_data(in_sigalgs), CBS_len(in_sigalgs));
-
-  size_t i;
-  for (i = 0; i < num_sigalgs; i++) {
-    TLS_SIGALGS *const sigalg = &cert->peer_sigalgs[i];
-    if (!CBS_get_u8(&sigalgs, &sigalg->rhash) ||
-        !CBS_get_u8(&sigalgs, &sigalg->rsign)) {
+  for (size_t i = 0; i < num_sigalgs; i++) {
+    if (!CBS_get_u16(&sigalgs, &hs->peer_sigalgs[i])) {
       return 0;
     }
   }
@@ -2736,101 +3302,314 @@
   return 1;
 }
 
-const EVP_MD *tls1_choose_signing_digest(SSL *ssl) {
+int tls1_choose_signature_algorithm(SSL_HANDSHAKE *hs, uint16_t *out) {
+  SSL *const ssl = hs->ssl;
   CERT *cert = ssl->cert;
-  int type = ssl_private_key_type(ssl);
-  size_t i, j;
 
-  static const int kDefaultDigestList[] = {NID_sha256, NID_sha384, NID_sha512,
-                                           NID_sha224, NID_sha1};
-
-  const int *digest_nids = kDefaultDigestList;
-  size_t num_digest_nids =
-      sizeof(kDefaultDigestList) / sizeof(kDefaultDigestList[0]);
-  if (cert->digest_nids != NULL) {
-    digest_nids = cert->digest_nids;
-    num_digest_nids = cert->num_digest_nids;
+  /* Before TLS 1.2, the signature algorithm isn't negotiated as part of the
+   * handshake. It is fixed at MD5-SHA1 for RSA and SHA1 for ECDSA. */
+  if (ssl3_protocol_version(ssl) < TLS1_2_VERSION) {
+    int type = ssl_private_key_type(ssl);
+    if (type == NID_rsaEncryption) {
+      *out = SSL_SIGN_RSA_PKCS1_MD5_SHA1;
+      return 1;
+    }
+    if (ssl_is_ecdsa_key_type(type)) {
+      *out = SSL_SIGN_ECDSA_SHA1;
+      return 1;
+    }
+    OPENSSL_PUT_ERROR(SSL, SSL_R_NO_COMMON_SIGNATURE_ALGORITHMS);
+    return 0;
   }
 
-  for (i = 0; i < num_digest_nids; i++) {
-    const int digest_nid = digest_nids[i];
-    for (j = 0; j < cert->peer_sigalgslen; j++) {
-      const EVP_MD *md = tls12_get_hash(cert->peer_sigalgs[j].rhash);
-      if (md == NULL ||
-          digest_nid != EVP_MD_type(md) ||
-          tls12_get_pkey_type(cert->peer_sigalgs[j].rsign) != type) {
-        continue;
-      }
+  const uint16_t *sigalgs = cert->sigalgs;
+  size_t num_sigalgs = cert->num_sigalgs;
+  if (sigalgs == NULL) {
+    sigalgs = kSignSignatureAlgorithms;
+    num_sigalgs = OPENSSL_ARRAY_SIZE(kSignSignatureAlgorithms);
+  }
 
-      return md;
+  const uint16_t *peer_sigalgs = hs->peer_sigalgs;
+  size_t num_peer_sigalgs = hs->num_peer_sigalgs;
+  if (num_peer_sigalgs == 0 && ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
+    /* If the client didn't specify any signature_algorithms extension then
+     * we can assume that it supports SHA1. See
+     * http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1 */
+    static const uint16_t kDefaultPeerAlgorithms[] = {SSL_SIGN_RSA_PKCS1_SHA1,
+                                                      SSL_SIGN_ECDSA_SHA1};
+    peer_sigalgs = kDefaultPeerAlgorithms;
+    num_peer_sigalgs = OPENSSL_ARRAY_SIZE(kDefaultPeerAlgorithms);
+  }
+
+  for (size_t i = 0; i < num_sigalgs; i++) {
+    uint16_t sigalg = sigalgs[i];
+    /* SSL_SIGN_RSA_PKCS1_MD5_SHA1 is an internal value and should never be
+     * negotiated. */
+    if (sigalg == SSL_SIGN_RSA_PKCS1_MD5_SHA1 ||
+        !ssl_private_key_supports_signature_algorithm(ssl, sigalgs[i])) {
+      continue;
+    }
+
+    for (size_t j = 0; j < num_peer_sigalgs; j++) {
+      if (sigalg == peer_sigalgs[j]) {
+        *out = sigalg;
+        return 1;
+      }
     }
   }
 
-  /* If no suitable digest may be found, default to SHA-1. */
-  return EVP_sha1();
+  OPENSSL_PUT_ERROR(SSL, SSL_R_NO_COMMON_SIGNATURE_ALGORITHMS);
+  return 0;
 }
 
-int tls1_channel_id_hash(SSL *ssl, uint8_t *out, size_t *out_len) {
+int tls1_verify_channel_id(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   int ret = 0;
-  EVP_MD_CTX ctx;
+  uint16_t extension_type;
+  CBS extension, channel_id;
 
-  EVP_MD_CTX_init(&ctx);
-  if (!EVP_DigestInit_ex(&ctx, EVP_sha256(), NULL)) {
+  /* A Channel ID handshake message is structured to contain multiple
+   * extensions, but the only one that can be present is Channel ID. */
+  CBS_init(&channel_id, ssl->init_msg, ssl->init_num);
+  if (!CBS_get_u16(&channel_id, &extension_type) ||
+      !CBS_get_u16_length_prefixed(&channel_id, &extension) ||
+      CBS_len(&channel_id) != 0 ||
+      extension_type != TLSEXT_TYPE_channel_id ||
+      CBS_len(&extension) != TLSEXT_CHANNEL_ID_SIZE) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+    return 0;
+  }
+
+  EC_GROUP *p256 = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
+  if (!p256) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_NO_P256_SUPPORT);
+    return 0;
+  }
+
+  EC_KEY *key = NULL;
+  EC_POINT *point = NULL;
+  BIGNUM x, y;
+  ECDSA_SIG sig;
+  BN_init(&x);
+  BN_init(&y);
+  sig.r = BN_new();
+  sig.s = BN_new();
+  if (sig.r == NULL || sig.s == NULL) {
     goto err;
   }
 
-  static const char kClientIDMagic[] = "TLS Channel ID signature";
-  EVP_DigestUpdate(&ctx, kClientIDMagic, sizeof(kClientIDMagic));
-
-  if (ssl->hit) {
-    static const char kResumptionMagic[] = "Resumption";
-    EVP_DigestUpdate(&ctx, kResumptionMagic, sizeof(kResumptionMagic));
-    if (ssl->session->original_handshake_hash_len == 0) {
-      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
-      goto err;
-    }
-    EVP_DigestUpdate(&ctx, ssl->session->original_handshake_hash,
-                     ssl->session->original_handshake_hash_len);
-  }
-
-  uint8_t handshake_hash[EVP_MAX_MD_SIZE];
-  int handshake_hash_len = tls1_handshake_digest(ssl, handshake_hash,
-                                                 sizeof(handshake_hash));
-  if (handshake_hash_len < 0) {
+  const uint8_t *p = CBS_data(&extension);
+  if (BN_bin2bn(p + 0, 32, &x) == NULL ||
+      BN_bin2bn(p + 32, 32, &y) == NULL ||
+      BN_bin2bn(p + 64, 32, sig.r) == NULL ||
+      BN_bin2bn(p + 96, 32, sig.s) == NULL) {
     goto err;
   }
-  EVP_DigestUpdate(&ctx, handshake_hash, (size_t)handshake_hash_len);
-  unsigned len_u;
-  EVP_DigestFinal_ex(&ctx, out, &len_u);
-  *out_len = len_u;
+
+  point = EC_POINT_new(p256);
+  if (point == NULL ||
+      !EC_POINT_set_affine_coordinates_GFp(p256, point, &x, &y, NULL)) {
+    goto err;
+  }
+
+  key = EC_KEY_new();
+  if (key == NULL ||
+      !EC_KEY_set_group(key, p256) ||
+      !EC_KEY_set_public_key(key, point)) {
+    goto err;
+  }
+
+  uint8_t digest[EVP_MAX_MD_SIZE];
+  size_t digest_len;
+  if (!tls1_channel_id_hash(hs, digest, &digest_len)) {
+    goto err;
+  }
+
+  int sig_ok = ECDSA_do_verify(digest, digest_len, &sig, key);
+#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
+  sig_ok = 1;
+#endif
+  if (!sig_ok) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_CHANNEL_ID_SIGNATURE_INVALID);
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR);
+    ssl->s3->tlsext_channel_id_valid = 0;
+    goto err;
+  }
+
+  OPENSSL_memcpy(ssl->s3->tlsext_channel_id, p, 64);
+  ret = 1;
+
+err:
+  BN_free(&x);
+  BN_free(&y);
+  BN_free(sig.r);
+  BN_free(sig.s);
+  EC_KEY_free(key);
+  EC_POINT_free(point);
+  EC_GROUP_free(p256);
+  return ret;
+}
+
+int tls1_write_channel_id(SSL_HANDSHAKE *hs, CBB *cbb) {
+  SSL *const ssl = hs->ssl;
+  uint8_t digest[EVP_MAX_MD_SIZE];
+  size_t digest_len;
+  if (!tls1_channel_id_hash(hs, digest, &digest_len)) {
+    return 0;
+  }
+
+  EC_KEY *ec_key = EVP_PKEY_get0_EC_KEY(ssl->tlsext_channel_id_private);
+  if (ec_key == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    return 0;
+  }
+
+  int ret = 0;
+  BIGNUM *x = BN_new();
+  BIGNUM *y = BN_new();
+  ECDSA_SIG *sig = NULL;
+  if (x == NULL || y == NULL ||
+      !EC_POINT_get_affine_coordinates_GFp(EC_KEY_get0_group(ec_key),
+                                           EC_KEY_get0_public_key(ec_key),
+                                           x, y, NULL)) {
+    goto err;
+  }
+
+  sig = ECDSA_do_sign(digest, digest_len, ec_key);
+  if (sig == NULL) {
+    goto err;
+  }
+
+  CBB child;
+  if (!CBB_add_u16(cbb, TLSEXT_TYPE_channel_id) ||
+      !CBB_add_u16_length_prefixed(cbb, &child) ||
+      !BN_bn2cbb_padded(&child, 32, x) ||
+      !BN_bn2cbb_padded(&child, 32, y) ||
+      !BN_bn2cbb_padded(&child, 32, sig->r) ||
+      !BN_bn2cbb_padded(&child, 32, sig->s) ||
+      !CBB_flush(cbb)) {
+    goto err;
+  }
 
   ret = 1;
 
 err:
-  EVP_MD_CTX_cleanup(&ctx);
+  BN_free(x);
+  BN_free(y);
+  ECDSA_SIG_free(sig);
   return ret;
 }
 
+int tls1_channel_id_hash(SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len) {
+  SSL *const ssl = hs->ssl;
+  if (ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
+    uint8_t *msg;
+    size_t msg_len;
+    if (!tls13_get_cert_verify_signature_input(hs, &msg, &msg_len,
+                                               ssl_cert_verify_channel_id)) {
+      return 0;
+    }
+    SHA256(msg, msg_len, out);
+    *out_len = SHA256_DIGEST_LENGTH;
+    OPENSSL_free(msg);
+    return 1;
+  }
+
+  SHA256_CTX ctx;
+
+  SHA256_Init(&ctx);
+  static const char kClientIDMagic[] = "TLS Channel ID signature";
+  SHA256_Update(&ctx, kClientIDMagic, sizeof(kClientIDMagic));
+
+  if (ssl->session != NULL) {
+    static const char kResumptionMagic[] = "Resumption";
+    SHA256_Update(&ctx, kResumptionMagic, sizeof(kResumptionMagic));
+    if (ssl->session->original_handshake_hash_len == 0) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+      return 0;
+    }
+    SHA256_Update(&ctx, ssl->session->original_handshake_hash,
+                  ssl->session->original_handshake_hash_len);
+  }
+
+  uint8_t hs_hash[EVP_MAX_MD_SIZE];
+  size_t hs_hash_len;
+  if (!SSL_TRANSCRIPT_get_hash(&hs->transcript, hs_hash, &hs_hash_len)) {
+    return 0;
+  }
+  SHA256_Update(&ctx, hs_hash, (size_t)hs_hash_len);
+  SHA256_Final(out, &ctx);
+  *out_len = SHA256_DIGEST_LENGTH;
+  return 1;
+}
+
 /* tls1_record_handshake_hashes_for_channel_id records the current handshake
- * hashes in |ssl->session| so that Channel ID resumptions can sign that
+ * hashes in |hs->new_session| so that Channel ID resumptions can sign that
  * data. */
-int tls1_record_handshake_hashes_for_channel_id(SSL *ssl) {
-  int digest_len;
+int tls1_record_handshake_hashes_for_channel_id(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
   /* This function should never be called for a resumed session because the
    * handshake hashes that we wish to record are for the original, full
    * handshake. */
-  if (ssl->hit) {
+  if (ssl->session != NULL) {
     return -1;
   }
 
-  digest_len =
-      tls1_handshake_digest(ssl, ssl->session->original_handshake_hash,
-                            sizeof(ssl->session->original_handshake_hash));
-  if (digest_len < 0) {
+  OPENSSL_COMPILE_ASSERT(
+      sizeof(hs->new_session->original_handshake_hash) == EVP_MAX_MD_SIZE,
+      original_handshake_hash_is_too_small);
+
+  size_t digest_len;
+  if (!SSL_TRANSCRIPT_get_hash(&hs->transcript,
+                               hs->new_session->original_handshake_hash,
+                               &digest_len)) {
     return -1;
   }
 
-  ssl->session->original_handshake_hash_len = digest_len;
+  OPENSSL_COMPILE_ASSERT(EVP_MAX_MD_SIZE <= 0xff, max_md_size_is_too_large);
+  hs->new_session->original_handshake_hash_len = (uint8_t)digest_len;
+
+  return 1;
+}
+
+int ssl_do_channel_id_callback(SSL *ssl) {
+  if (ssl->tlsext_channel_id_private != NULL ||
+      ssl->ctx->channel_id_cb == NULL) {
+    return 1;
+  }
+
+  EVP_PKEY *key = NULL;
+  ssl->ctx->channel_id_cb(ssl, &key);
+  if (key == NULL) {
+    /* The caller should try again later. */
+    return 1;
+  }
+
+  int ret = SSL_set1_tls_channel_id(ssl, key);
+  EVP_PKEY_free(key);
+  return ret;
+}
+
+int ssl_is_sct_list_valid(const CBS *contents) {
+  /* Shallow parse the SCT list for sanity. By the RFC
+   * (https://tools.ietf.org/html/rfc6962#section-3.3) neither the list nor any
+   * of the SCTs may be empty. */
+  CBS copy = *contents;
+  CBS sct_list;
+  if (!CBS_get_u16_length_prefixed(&copy, &sct_list) ||
+      CBS_len(&copy) != 0 ||
+      CBS_len(&sct_list) == 0) {
+    return 0;
+  }
+
+  while (CBS_len(&sct_list) > 0) {
+    CBS sct;
+    if (!CBS_get_u16_length_prefixed(&sct_list, &sct) ||
+        CBS_len(&sct) == 0) {
+      return 0;
+    }
+  }
 
   return 1;
 }
diff --git a/src/ssl/test/PORTING.md b/src/ssl/test/PORTING.md
new file mode 100644
index 0000000..86ad24d
--- /dev/null
+++ b/src/ssl/test/PORTING.md
@@ -0,0 +1,109 @@
+# Porting to Other Implementations
+
+## Introduction
+
+This document provides an overview of the test runner and how to
+integrate it with other stacks.  So far we have it working with
+BoringSSL and some incomplete integrations with NSS and OpenSSL.
+
+Note that supporting non-BoringSSL implementations is a work in
+progress and interfaces may change in the future. Consumers should pin
+to a particular revision rather than using BoringSSL’s master branch
+directly. As we gain experience with other implementations, we hope to
+make further improvements to portability, so please contact
+davidben@google.com and ekr@rtfm.com if implementing a new shim.
+
+
+## Integration Architecture
+
+The test runner integrates with the TLS stack under test through a
+“shim”: a command line program which encapsulates the stack. By
+default, the shim points to the BoringSSL shim in the same source
+tree, but any program can be supplied via the `-shim-path` flag. The
+runner opens up a server socket and provides the shim with a `-port`
+argument that points to that socket. The shim always connects to the
+runner as a TCP client even when acting as a TLS server. For DTLS,
+there is a small framing layer that gives packet boundaries over
+TCP. The shim can also pass a variety of command line arguments which
+are used to configure the stack under test. These can be found at
+`test_config.cc`.
+
+
+The shim reports success by exiting with a `0` error code and failure by
+reporting a non-zero error code and generally sending a textual error
+value to stderr. Many of the tests expect specific error string (such
+as `NO_SHARED_CIPHER`) that indicates what went wrong.
+
+
+## Compatibility Issues
+
+There are a number of situations in which the runner might succeed
+with some tests and not others:
+
+* Defects in the stack under test
+* Features which haven’t yet been implemented
+* Failure to implement one or more of the command line flags the runner uses with the shim
+* Disagreement about the right behavior/interpretation of the spec
+
+
+We have implemented several features which allow implementations to ease these compatibility issues.
+
+### Configuration File
+
+The runner can be supplied with a JSON configuration file which is
+intended to allow for a per-stack mapping. This file currently takes
+two directives:
+
+
+* `DisabledTests`: A JSON map consisting of the pattern matching the
+  tests to be disabled as the key and some sort of reason why it was
+  disabled as the value. The key is used as a match against the test
+  name. The value is ignored and is just used for documentation
+  purposes so you can remember why you disabled a
+  test. `-include-disabled` overrides this filter.
+
+* `ErrorMap`: A JSON map from the internal errors the runner expects to
+  the error strings that your implementation spits out. Generally
+  you’ll need to map every error, but if you also provide the
+ ` -loose-errors` flag, then every un-mapped error just gets mapped to
+  the empty string and treated as if it matched every error the runner
+  expects.
+
+
+The `-shim-config` flag is used to provide the config file.
+
+
+### Unimplemented Features
+If the shim encounters some request from the runner that it knows it
+can’t fulfill (e.g., a command line flag that it doesn’t recognize),
+then it can exit with the special code `89`. Shims are recommended to
+use this exit code on unknown command-line arguments.
+
+The test runner interprets this as “unimplemented” and skips the
+test. If run normally, this will cause the test runner to report that
+the entire test suite failed. The `-allow-unimplemented` flag suppresses
+this behavior and causes the test runner to ignore these tests for the
+purpose of evaluating the success or failure of the test suite.
+
+
+### Malloc Tests
+
+The test runner can also be used to stress malloc failure
+codepaths. If passed `-malloc-test=0`, the runner will run each test
+repeatedly with an incrementing `MALLOC_NUMBER_TO_FAIL` environment
+variable. The shim should then replace the malloc implementation with
+one which fails at the specified number of calls. If there are not
+enough calls to reach the number, the shim should fail with exit code
+`88`. This signals to the runner that the test has completed.
+
+See `crypto/test/malloc.cc` for an example malloc implementation.
+
+Note these tests are slow and will hit Go's test timeout. Pass `-timeout 72h` to
+avoid crashing after 10 minutes.
+
+
+## Example: Running Against NSS
+
+```
+DYLD_LIBRARY_PATH=~/dev/nss-dev/nss-sandbox/dist/Darwin15.6.0_64_DBG.OBJ/lib go test -shim-path ~/dev/nss-dev/nss-sandbox/dist/Darwin15.6.0_64_DBG.OBJ/bin/nss_bogo_shim -loose-errors -allow-unimplemented -shim-config ~/dev/nss-dev/nss-sandbox/nss/external_tests/nss_bogo_shim/config.json
+```
diff --git a/src/ssl/test/README.md b/src/ssl/test/README.md
new file mode 100644
index 0000000..7da29eb
--- /dev/null
+++ b/src/ssl/test/README.md
@@ -0,0 +1,38 @@
+# BoringSSL SSL Tests
+
+This directory contains BoringSSL's protocol-level test suite.
+
+Testing a TLS implementation can be difficult. We need to produce invalid but
+sufficiently correct handshakes to get our implementation close to its edge
+cases. TLS's cryptographic steps mean we cannot use a transcript and effectively
+need a TLS implementation on the other end. But we do not wish to litter
+BoringSSL with options for bugs to test against.
+
+Instead, we use a fork of the Go `crypto/tls` package, heavily patched with
+configurable bugs. This code, along with a test suite and harness written in Go,
+lives in the `runner` directory. The harness runs BoringSSL via a C/C++ shim
+binary which lives in this directory. All communication with the shim binary
+occurs with command-line flags, sockets, and standard I/O.
+
+This strategy also ensures we always test against a second implementation. All
+features should be implemented twice, once in C for BoringSSL and once in Go for
+testing. If possible, the Go code should be suitable for potentially
+upstreaming. However, sometimes test code has different needs. For example, our
+test DTLS code enforces strict ordering on sequence numbers and has controlled
+packet drop simulation.
+
+To run the tests manually, run `go test` from the `runner` directory. It takes
+command-line flags found at the top of `runner/runner.go`. The `-help` option
+also works after using `go test -c` to make a `runner.test` binary first.
+
+If adding a new test, these files may be a good starting point:
+
+ * `runner/runner.go`: the test harness and all the individual tests.
+ * `runner/common.go`: contains the `Config` and `ProtocolBugs` struct which
+   control the Go TLS implementation's behavior.
+ * `test_config.h`, `test_config.cc`: the command-line flags which control the
+   shim's behavior.
+ * `bssl_shim.cc`: the shim binary itself.
+
+For porting the test suite to a different implementation see
+[PORTING.md](./PORTING.md).
diff --git a/src/ssl/test/async_bio.cc b/src/ssl/test/async_bio.cc
index 7a5737b..fd35176 100644
--- a/src/ssl/test/async_bio.cc
+++ b/src/ssl/test/async_bio.cc
@@ -17,8 +17,11 @@
 #include <errno.h>
 #include <string.h>
 
+#include <openssl/bio.h>
 #include <openssl/mem.h>
 
+#include "../../crypto/internal.h"
+
 
 namespace {
 
@@ -109,7 +112,7 @@
   if (a == NULL) {
     return 0;
   }
-  memset(a, 0, sizeof(*a));
+  OPENSSL_memset(a, 0, sizeof(*a));
   a->enforce_write_quota = true;
   bio->init = 1;
   bio->ptr = (char *)a;
@@ -150,12 +153,12 @@
 
 }  // namespace
 
-ScopedBIO AsyncBioCreate() {
-  return ScopedBIO(BIO_new(&g_async_bio_method));
+bssl::UniquePtr<BIO> AsyncBioCreate() {
+  return bssl::UniquePtr<BIO>(BIO_new(&g_async_bio_method));
 }
 
-ScopedBIO AsyncBioCreateDatagram() {
-  ScopedBIO ret(BIO_new(&g_async_bio_method));
+bssl::UniquePtr<BIO> AsyncBioCreateDatagram() {
+  bssl::UniquePtr<BIO> ret(BIO_new(&g_async_bio_method));
   if (!ret) {
     return nullptr;
   }
diff --git a/src/ssl/test/async_bio.h b/src/ssl/test/async_bio.h
index fbc4016..9974139 100644
--- a/src/ssl/test/async_bio.h
+++ b/src/ssl/test/async_bio.h
@@ -17,20 +17,18 @@
 
 #include <openssl/bio.h>
 
-#include "../../crypto/test/scoped_types.h"
-
 
 // AsyncBioCreate creates a filter BIO for testing asynchronous state
 // machines which consume a stream socket. Reads and writes will fail
 // and return EAGAIN unless explicitly allowed. Each async BIO has a
 // read quota and a write quota. Initially both are zero. As each is
 // incremented, bytes are allowed to flow through the BIO.
-ScopedBIO AsyncBioCreate();
+bssl::UniquePtr<BIO> AsyncBioCreate();
 
 // AsyncBioCreateDatagram creates a filter BIO for testing for
 // asynchronous state machines which consume datagram sockets. The read
 // and write quota count in packets rather than bytes.
-ScopedBIO AsyncBioCreateDatagram();
+bssl::UniquePtr<BIO> AsyncBioCreateDatagram();
 
 // AsyncBioAllowRead increments |bio|'s read quota by |count|.
 void AsyncBioAllowRead(BIO *bio, size_t count);
diff --git a/src/ssl/test/bssl_shim.cc b/src/ssl/test/bssl_shim.cc
index 74674a4..21497fd 100644
--- a/src/ssl/test/bssl_shim.cc
+++ b/src/ssl/test/bssl_shim.cc
@@ -28,39 +28,46 @@
 #include <unistd.h>
 #else
 #include <io.h>
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <winsock2.h>
 #include <ws2tcpip.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
 
-#pragma comment(lib, "Ws2_32.lib")
+OPENSSL_MSVC_PRAGMA(comment(lib, "Ws2_32.lib"))
 #endif
 
+#include <assert.h>
 #include <inttypes.h>
 #include <string.h>
 
+#include <openssl/aead.h>
 #include <openssl/bio.h>
 #include <openssl/buf.h>
 #include <openssl/bytestring.h>
 #include <openssl/cipher.h>
 #include <openssl/crypto.h>
+#include <openssl/dh.h>
+#include <openssl/digest.h>
 #include <openssl/err.h>
+#include <openssl/evp.h>
 #include <openssl/hmac.h>
-#include <openssl/obj.h>
+#include <openssl/nid.h>
 #include <openssl/rand.h>
 #include <openssl/ssl.h>
+#include <openssl/x509.h>
 
 #include <memory>
 #include <string>
 #include <vector>
 
-#include "../../crypto/test/scoped_types.h"
+#include "../../crypto/internal.h"
 #include "async_bio.h"
 #include "packeted_bio.h"
-#include "scoped_types.h"
 #include "test_config.h"
 
 
+static CRYPTO_BUFFER_POOL *g_pool = nullptr;
+
 #if !defined(OPENSSL_WINDOWS)
 static int closesocket(int sock) {
   return close(sock);
@@ -81,32 +88,28 @@
 }
 
 struct TestState {
-  TestState() {
-    // MSVC cannot initialize these inline.
-    memset(&clock, 0, sizeof(clock));
-    memset(&clock_delta, 0, sizeof(clock_delta));
-  }
-
   // async_bio is async BIO which pauses reads and writes.
   BIO *async_bio = nullptr;
-  // clock is the current time for the SSL connection.
-  timeval clock;
-  // clock_delta is how far the clock advanced in the most recent failed
-  // |BIO_read|.
-  timeval clock_delta;
-  ScopedEVP_PKEY channel_id;
+  // packeted_bio is the packeted BIO which simulates read timeouts.
+  BIO *packeted_bio = nullptr;
+  bssl::UniquePtr<EVP_PKEY> channel_id;
   bool cert_ready = false;
-  ScopedSSL_SESSION session;
-  ScopedSSL_SESSION pending_session;
+  bssl::UniquePtr<SSL_SESSION> session;
+  bssl::UniquePtr<SSL_SESSION> pending_session;
   bool early_callback_called = false;
   bool handshake_done = false;
   // private_key is the underlying private key used when testing custom keys.
-  ScopedEVP_PKEY private_key;
+  bssl::UniquePtr<EVP_PKEY> private_key;
   std::vector<uint8_t> private_key_result;
   // private_key_retries is the number of times an asynchronous private key
   // operation has been retried.
   unsigned private_key_retries = 0;
   bool got_new_session = false;
+  bssl::UniquePtr<SSL_SESSION> new_session;
+  bool ticket_decrypt_done = false;
+  bool alpn_select_done = false;
+  bool is_resume = false;
+  bool early_callback_ready = false;
 };
 
 static void TestStateExFree(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
@@ -117,11 +120,11 @@
 static int g_config_index = 0;
 static int g_state_index = 0;
 
-static bool SetConfigPtr(SSL *ssl, const TestConfig *config) {
+static bool SetTestConfig(SSL *ssl, const TestConfig *config) {
   return SSL_set_ex_data(ssl, g_config_index, (void *)config) == 1;
 }
 
-static const TestConfig *GetConfigPtr(const SSL *ssl) {
+static const TestConfig *GetTestConfig(const SSL *ssl) {
   return (const TestConfig *)SSL_get_ex_data(ssl, g_config_index);
 }
 
@@ -138,17 +141,162 @@
   return (TestState *)SSL_get_ex_data(ssl, g_state_index);
 }
 
-static ScopedEVP_PKEY LoadPrivateKey(const std::string &file) {
-  ScopedBIO bio(BIO_new(BIO_s_file()));
+static bool LoadCertificate(bssl::UniquePtr<X509> *out_x509,
+                            bssl::UniquePtr<STACK_OF(X509)> *out_chain,
+                            const std::string &file) {
+  bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_file()));
+  if (!bio || !BIO_read_filename(bio.get(), file.c_str())) {
+    return false;
+  }
+
+  out_x509->reset(PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr));
+  if (!*out_x509) {
+    return false;
+  }
+
+  out_chain->reset(sk_X509_new_null());
+  if (!*out_chain) {
+    return false;
+  }
+
+  // Keep reading the certificate chain.
+  for (;;) {
+    bssl::UniquePtr<X509> cert(
+        PEM_read_bio_X509(bio.get(), nullptr, nullptr, nullptr));
+    if (!cert) {
+      break;
+    }
+
+    if (!sk_X509_push(out_chain->get(), cert.get())) {
+      return false;
+    }
+    cert.release();  // sk_X509_push takes ownership.
+  }
+
+  uint32_t err = ERR_peek_last_error();
+  if (ERR_GET_LIB(err) != ERR_LIB_PEM ||
+      ERR_GET_REASON(err) != PEM_R_NO_START_LINE) {
+    return false;
+}
+
+  ERR_clear_error();
+  return true;
+}
+
+static bssl::UniquePtr<EVP_PKEY> LoadPrivateKey(const std::string &file) {
+  bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_file()));
   if (!bio || !BIO_read_filename(bio.get(), file.c_str())) {
     return nullptr;
   }
-  ScopedEVP_PKEY pkey(PEM_read_bio_PrivateKey(bio.get(), NULL, NULL, NULL));
-  return pkey;
+  return bssl::UniquePtr<EVP_PKEY>(
+      PEM_read_bio_PrivateKey(bio.get(), NULL, NULL, NULL));
+}
+
+static bool FromHexDigit(uint8_t *out, char c) {
+  if ('0' <= c && c <= '9') {
+    *out = c - '0';
+    return true;
+  }
+  if ('a' <= c && c <= 'f') {
+    *out = c - 'a' + 10;
+    return true;
+  }
+  if ('A' <= c && c <= 'F') {
+    *out = c - 'A' + 10;
+    return true;
+  }
+  return false;
+}
+
+static bool HexDecode(std::string *out, const std::string &in) {
+  if ((in.size() & 1) != 0) {
+    return false;
+  }
+
+  std::unique_ptr<uint8_t[]> buf(new uint8_t[in.size() / 2]);
+  for (size_t i = 0; i < in.size() / 2; i++) {
+    uint8_t high, low;
+    if (!FromHexDigit(&high, in[i*2]) ||
+        !FromHexDigit(&low, in[i*2+1])) {
+      return false;
+    }
+    buf[i] = (high << 4) | low;
+  }
+
+  out->assign(reinterpret_cast<const char *>(buf.get()), in.size() / 2);
+  return true;
+}
+
+static std::vector<std::string> SplitParts(const std::string &in,
+                                           const char delim) {
+  std::vector<std::string> ret;
+  size_t start = 0;
+
+  for (size_t i = 0; i < in.size(); i++) {
+    if (in[i] == delim) {
+      ret.push_back(in.substr(start, i - start));
+      start = i + 1;
+    }
+  }
+
+  ret.push_back(in.substr(start, std::string::npos));
+  return ret;
+}
+
+static std::vector<std::string> DecodeHexStrings(
+    const std::string &hex_strings) {
+  std::vector<std::string> ret;
+  const std::vector<std::string> parts = SplitParts(hex_strings, ',');
+
+  for (const auto &part : parts) {
+    std::string binary;
+    if (!HexDecode(&binary, part)) {
+      fprintf(stderr, "Bad hex string: %s\n", part.c_str());
+      return ret;
+    }
+
+    ret.push_back(binary);
+  }
+
+  return ret;
+}
+
+static bssl::UniquePtr<STACK_OF(X509_NAME)> DecodeHexX509Names(
+    const std::string &hex_names) {
+  const std::vector<std::string> der_names = DecodeHexStrings(hex_names);
+  bssl::UniquePtr<STACK_OF(X509_NAME)> ret(sk_X509_NAME_new_null());
+
+  for (const auto &der_name : der_names) {
+    const uint8_t *const data =
+        reinterpret_cast<const uint8_t *>(der_name.data());
+    const uint8_t *derp = data;
+    bssl::UniquePtr<X509_NAME> name(
+        d2i_X509_NAME(nullptr, &derp, der_name.size()));
+    if (!name || derp != data + der_name.size()) {
+      fprintf(stderr, "Failed to parse X509_NAME.\n");
+      return nullptr;
+    }
+
+    if (!sk_X509_NAME_push(ret.get(), name.get())) {
+      return nullptr;
+    }
+    name.release();
+  }
+
+  return ret;
 }
 
 static int AsyncPrivateKeyType(SSL *ssl) {
-  return EVP_PKEY_id(GetTestState(ssl)->private_key.get());
+  EVP_PKEY *key = GetTestState(ssl)->private_key.get();
+  switch (EVP_PKEY_id(key)) {
+    case EVP_PKEY_RSA:
+      return NID_rsaEncryption;
+    case EVP_PKEY_EC:
+      return EC_GROUP_get_curve_name(
+          EC_KEY_get0_group(EVP_PKEY_get0_EC_KEY(key)));
+    default:
+      return NID_undef;
+  }
 }
 
 static size_t AsyncPrivateKeyMaxSignatureLen(SSL *ssl) {
@@ -157,66 +305,80 @@
 
 static ssl_private_key_result_t AsyncPrivateKeySign(
     SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
-    const EVP_MD *md, const uint8_t *in, size_t in_len) {
+    uint16_t signature_algorithm, const uint8_t *in, size_t in_len) {
   TestState *test_state = GetTestState(ssl);
   if (!test_state->private_key_result.empty()) {
     fprintf(stderr, "AsyncPrivateKeySign called with operation pending.\n");
     abort();
   }
 
-  ScopedEVP_PKEY_CTX ctx(EVP_PKEY_CTX_new(test_state->private_key.get(),
-                                          nullptr));
-  if (!ctx) {
+  // Determine the hash.
+  const EVP_MD *md;
+  switch (signature_algorithm) {
+    case SSL_SIGN_RSA_PKCS1_SHA1:
+    case SSL_SIGN_ECDSA_SHA1:
+      md = EVP_sha1();
+      break;
+    case SSL_SIGN_RSA_PKCS1_SHA256:
+    case SSL_SIGN_ECDSA_SECP256R1_SHA256:
+    case SSL_SIGN_RSA_PSS_SHA256:
+      md = EVP_sha256();
+      break;
+    case SSL_SIGN_RSA_PKCS1_SHA384:
+    case SSL_SIGN_ECDSA_SECP384R1_SHA384:
+    case SSL_SIGN_RSA_PSS_SHA384:
+      md = EVP_sha384();
+      break;
+    case SSL_SIGN_RSA_PKCS1_SHA512:
+    case SSL_SIGN_ECDSA_SECP521R1_SHA512:
+    case SSL_SIGN_RSA_PSS_SHA512:
+      md = EVP_sha512();
+      break;
+    case SSL_SIGN_RSA_PKCS1_MD5_SHA1:
+      md = EVP_md5_sha1();
+      break;
+    default:
+      fprintf(stderr, "Unknown signature algorithm %04x.\n",
+              signature_algorithm);
+      return ssl_private_key_failure;
+  }
+
+  bssl::ScopedEVP_MD_CTX ctx;
+  EVP_PKEY_CTX *pctx;
+  if (!EVP_DigestSignInit(ctx.get(), &pctx, md, nullptr,
+                          test_state->private_key.get())) {
     return ssl_private_key_failure;
   }
 
+  // Configure additional signature parameters.
+  switch (signature_algorithm) {
+    case SSL_SIGN_RSA_PSS_SHA256:
+    case SSL_SIGN_RSA_PSS_SHA384:
+    case SSL_SIGN_RSA_PSS_SHA512:
+      if (!EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) ||
+          !EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx,
+                                            -1 /* salt len = hash len */)) {
+        return ssl_private_key_failure;
+      }
+  }
+
   // Write the signature into |test_state|.
   size_t len = 0;
-  if (!EVP_PKEY_sign_init(ctx.get()) ||
-      !EVP_PKEY_CTX_set_signature_md(ctx.get(), md) ||
-      !EVP_PKEY_sign(ctx.get(), nullptr, &len, in, in_len)) {
+  if (!EVP_DigestSignUpdate(ctx.get(), in, in_len) ||
+      !EVP_DigestSignFinal(ctx.get(), nullptr, &len)) {
     return ssl_private_key_failure;
   }
   test_state->private_key_result.resize(len);
-  if (!EVP_PKEY_sign(ctx.get(), test_state->private_key_result.data(), &len, in,
-                     in_len)) {
+  if (!EVP_DigestSignFinal(ctx.get(), test_state->private_key_result.data(),
+                           &len)) {
     return ssl_private_key_failure;
   }
   test_state->private_key_result.resize(len);
 
-  // The signature will be released asynchronously in
-  // |AsyncPrivateKeySignComplete|.
+  // The signature will be released asynchronously in |AsyncPrivateKeyComplete|.
   return ssl_private_key_retry;
 }
 
-static ssl_private_key_result_t AsyncPrivateKeySignComplete(
-    SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out) {
-  TestState *test_state = GetTestState(ssl);
-  if (test_state->private_key_result.empty()) {
-    fprintf(stderr,
-            "AsyncPrivateKeySignComplete called without operation pending.\n");
-    abort();
-  }
-
-  if (test_state->private_key_retries < 2) {
-    // Only return the signature on the second attempt, to test both incomplete
-    // |sign| and |sign_complete|.
-    return ssl_private_key_retry;
-  }
-
-  if (max_out < test_state->private_key_result.size()) {
-    fprintf(stderr, "Output buffer too small.\n");
-    return ssl_private_key_failure;
-  }
-  memcpy(out, test_state->private_key_result.data(),
-         test_state->private_key_result.size());
-  *out_len = test_state->private_key_result.size();
-
-  test_state->private_key_result.clear();
-  test_state->private_key_retries = 0;
-  return ssl_private_key_success;
-}
-
 static ssl_private_key_result_t AsyncPrivateKeyDecrypt(
     SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
     const uint8_t *in, size_t in_len) {
@@ -241,18 +403,16 @@
 
   test_state->private_key_result.resize(*out_len);
 
-  // The decryption will be released asynchronously in
-  // |AsyncPrivateKeyDecryptComplete|.
+  // The decryption will be released asynchronously in |AsyncPrivateComplete|.
   return ssl_private_key_retry;
 }
 
-static ssl_private_key_result_t AsyncPrivateKeyDecryptComplete(
+static ssl_private_key_result_t AsyncPrivateKeyComplete(
     SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out) {
   TestState *test_state = GetTestState(ssl);
   if (test_state->private_key_result.empty()) {
     fprintf(stderr,
-            "AsyncPrivateKeyDecryptComplete called without operation "
-            "pending.\n");
+            "AsyncPrivateKeyComplete called without operation pending.\n");
     abort();
   }
 
@@ -266,8 +426,8 @@
     fprintf(stderr, "Output buffer too small.\n");
     return ssl_private_key_failure;
   }
-  memcpy(out, test_state->private_key_result.data(),
-         test_state->private_key_result.size());
+  OPENSSL_memcpy(out, test_state->private_key_result.data(),
+                 test_state->private_key_result.size());
   *out_len = test_state->private_key_result.size();
 
   test_state->private_key_result.clear();
@@ -279,9 +439,9 @@
     AsyncPrivateKeyType,
     AsyncPrivateKeyMaxSignatureLen,
     AsyncPrivateKeySign,
-    AsyncPrivateKeySignComplete,
+    nullptr /* sign_digest */,
     AsyncPrivateKeyDecrypt,
-    AsyncPrivateKeyDecryptComplete
+    AsyncPrivateKeyComplete,
 };
 
 template<typename T>
@@ -291,9 +451,10 @@
   }
 };
 
-static bool InstallCertificate(SSL *ssl) {
-  const TestConfig *config = GetConfigPtr(ssl);
-  TestState *test_state = GetTestState(ssl);
+static bool GetCertificate(SSL *ssl, bssl::UniquePtr<X509> *out_x509,
+                           bssl::UniquePtr<STACK_OF(X509)> *out_chain,
+                           bssl::UniquePtr<EVP_PKEY> *out_pkey) {
+  const TestConfig *config = GetTestConfig(ssl);
 
   if (!config->digest_prefs.empty()) {
     std::unique_ptr<char, Free<char>> digest_prefs(
@@ -316,35 +477,67 @@
     }
   }
 
+  if (!config->signing_prefs.empty()) {
+    std::vector<uint16_t> u16s(config->signing_prefs.begin(),
+                               config->signing_prefs.end());
+    if (!SSL_set_signing_algorithm_prefs(ssl, u16s.data(), u16s.size())) {
+      return false;
+    }
+  }
+
   if (!config->key_file.empty()) {
-    if (config->async) {
-      test_state->private_key = LoadPrivateKey(config->key_file.c_str());
-      if (!test_state->private_key) {
-        return false;
-      }
-      SSL_set_private_key_method(ssl, &g_async_private_key_method);
-    } else if (!SSL_use_PrivateKey_file(ssl, config->key_file.c_str(),
-                                        SSL_FILETYPE_PEM)) {
+    *out_pkey = LoadPrivateKey(config->key_file.c_str());
+    if (!*out_pkey) {
       return false;
     }
   }
   if (!config->cert_file.empty() &&
-      !SSL_use_certificate_file(ssl, config->cert_file.c_str(),
-                                SSL_FILETYPE_PEM)) {
+      !LoadCertificate(out_x509, out_chain, config->cert_file.c_str())) {
     return false;
   }
   if (!config->ocsp_response.empty() &&
-      !SSL_CTX_set_ocsp_response(ssl->ctx,
-                                 (const uint8_t *)config->ocsp_response.data(),
-                                 config->ocsp_response.size())) {
+      !SSL_set_ocsp_response(ssl, (const uint8_t *)config->ocsp_response.data(),
+                             config->ocsp_response.size())) {
     return false;
   }
   return true;
 }
 
-static int SelectCertificateCallback(const struct ssl_early_callback_ctx *ctx) {
-  const TestConfig *config = GetConfigPtr(ctx->ssl);
-  GetTestState(ctx->ssl)->early_callback_called = true;
+static bool InstallCertificate(SSL *ssl) {
+  bssl::UniquePtr<X509> x509;
+  bssl::UniquePtr<STACK_OF(X509)> chain;
+  bssl::UniquePtr<EVP_PKEY> pkey;
+  if (!GetCertificate(ssl, &x509, &chain, &pkey)) {
+    return false;
+  }
+
+  if (pkey) {
+    TestState *test_state = GetTestState(ssl);
+    const TestConfig *config = GetTestConfig(ssl);
+    if (config->async) {
+      test_state->private_key = std::move(pkey);
+      SSL_set_private_key_method(ssl, &g_async_private_key_method);
+    } else if (!SSL_use_PrivateKey(ssl, pkey.get())) {
+      return false;
+    }
+  }
+
+  if (x509 && !SSL_use_certificate(ssl, x509.get())) {
+    return false;
+  }
+
+  if (sk_X509_num(chain.get()) > 0 &&
+      !SSL_set1_chain(ssl, chain.get())) {
+    return false;
+  }
+
+  return true;
+}
+
+static enum ssl_select_cert_result_t SelectCertificateCallback(
+    const SSL_CLIENT_HELLO *client_hello) {
+  const TestConfig *config = GetTestConfig(client_hello->ssl);
+  GetTestState(client_hello->ssl)->early_callback_called = true;
 
   if (!config->expected_server_name.empty()) {
     const uint8_t *extension_data;
@@ -352,11 +545,11 @@
     CBS extension, server_name_list, host_name;
     uint8_t name_type;
 
-    if (!SSL_early_callback_ctx_extension_get(ctx, TLSEXT_TYPE_server_name,
-                                              &extension_data,
-                                              &extension_len)) {
+    if (!SSL_early_callback_ctx_extension_get(
+            client_hello, TLSEXT_TYPE_server_name, &extension_data,
+            &extension_len)) {
       fprintf(stderr, "Could not find server_name extension.\n");
-      return -1;
+      return ssl_select_cert_error;
     }
 
     CBS_init(&extension, extension_data, extension_len);
@@ -367,7 +560,7 @@
         !CBS_get_u16_length_prefixed(&server_name_list, &host_name) ||
         CBS_len(&server_name_list) != 0) {
       fprintf(stderr, "Could not decode server_name extension.\n");
-      return -1;
+      return ssl_select_cert_error;
     }
 
     if (!CBS_mem_equal(&host_name,
@@ -378,26 +571,133 @@
   }
 
   if (config->fail_early_callback) {
-    return -1;
+    return ssl_select_cert_error;
   }
 
   // Install the certificate in the early callback.
   if (config->use_early_callback) {
-    if (config->async) {
+    bool early_callback_ready =
+        GetTestState(client_hello->ssl)->early_callback_ready;
+    if (config->async && !early_callback_ready) {
       // Install the certificate asynchronously.
-      return 0;
+      return ssl_select_cert_retry;
     }
-    if (!InstallCertificate(ctx->ssl)) {
-      return -1;
+    if (!InstallCertificate(client_hello->ssl)) {
+      return ssl_select_cert_error;
     }
   }
+  return ssl_select_cert_success;
+}
+
+static bool CheckCertificateRequest(SSL *ssl) {
+  const TestConfig *config = GetTestConfig(ssl);
+
+  if (!config->expected_certificate_types.empty()) {
+    const uint8_t *certificate_types;
+    size_t certificate_types_len =
+        SSL_get0_certificate_types(ssl, &certificate_types);
+    if (certificate_types_len != config->expected_certificate_types.size() ||
+        OPENSSL_memcmp(certificate_types,
+                       config->expected_certificate_types.data(),
+                       certificate_types_len) != 0) {
+      fprintf(stderr, "certificate types mismatch\n");
+      return false;
+    }
+  }
+
+  if (!config->expected_client_ca_list.empty()) {
+    bssl::UniquePtr<STACK_OF(X509_NAME)> expected =
+        DecodeHexX509Names(config->expected_client_ca_list);
+    const size_t num_expected = sk_X509_NAME_num(expected.get());
+
+    const STACK_OF(X509_NAME) *received = SSL_get_client_CA_list(ssl);
+    const size_t num_received = sk_X509_NAME_num(received);
+
+    if (num_received != num_expected) {
+      fprintf(stderr, "expected %u names in CertificateRequest but got %u\n",
+              static_cast<unsigned>(num_expected),
+              static_cast<unsigned>(num_received));
+      return false;
+    }
+
+    for (size_t i = 0; i < num_received; i++) {
+      if (X509_NAME_cmp(sk_X509_NAME_value(received, i),
+                        sk_X509_NAME_value(expected.get(), i)) != 0) {
+        fprintf(stderr, "names in CertificateRequest differ at index #%d\n",
+                static_cast<unsigned>(i));
+        return false;
+      }
+    }
+
+    STACK_OF(CRYPTO_BUFFER) *buffers = SSL_get0_server_requested_CAs(ssl);
+    if (sk_CRYPTO_BUFFER_num(buffers) != num_received) {
+      fprintf(stderr,
+              "Mismatch between SSL_get_server_requested_CAs and "
+              "SSL_get_client_CA_list.\n");
+      return false;
+    }
+  }
+
+  return true;
+}
+
+static int ClientCertCallback(SSL *ssl, X509 **out_x509, EVP_PKEY **out_pkey) {
+  if (!CheckCertificateRequest(ssl)) {
+    return -1;
+  }
+
+  if (GetTestConfig(ssl)->async && !GetTestState(ssl)->cert_ready) {
+    return -1;
+  }
+
+  bssl::UniquePtr<X509> x509;
+  bssl::UniquePtr<STACK_OF(X509)> chain;
+  bssl::UniquePtr<EVP_PKEY> pkey;
+  if (!GetCertificate(ssl, &x509, &chain, &pkey)) {
+    return -1;
+  }
+
+  // Return zero for no certificate.
+  if (!x509) {
+    return 0;
+  }
+
+  // Chains and asynchronous private keys are not supported with client_cert_cb.
+  *out_x509 = x509.release();
+  *out_pkey = pkey.release();
+  return 1;
+}
+
+static int CertCallback(SSL *ssl, void *arg) {
+  const TestConfig *config = GetTestConfig(ssl);
+
+  // Check the CertificateRequest metadata is as expected.
+  if (!SSL_is_server(ssl) && !CheckCertificateRequest(ssl)) {
+    return -1;
+  }
+
+  if (config->fail_cert_callback) {
+    return 0;
+  }
+
+  // The certificate will be installed via other means.
+  if (!config->async || config->use_early_callback) {
+    return 1;
+  }
+
+  if (!GetTestState(ssl)->cert_ready) {
+    return -1;
+  }
+  if (!InstallCertificate(ssl)) {
+    return 0;
+  }
   return 1;
 }
 
 static int VerifySucceed(X509_STORE_CTX *store_ctx, void *arg) {
   SSL* ssl = (SSL*)X509_STORE_CTX_get_ex_data(store_ctx,
       SSL_get_ex_data_X509_STORE_CTX_idx());
-  const TestConfig *config = GetConfigPtr(ssl);
+  const TestConfig *config = GetTestConfig(ssl);
 
   if (!config->expected_ocsp_response.empty()) {
     const uint8_t *data;
@@ -419,7 +719,7 @@
 
 static int NextProtosAdvertisedCallback(SSL *ssl, const uint8_t **out,
                                         unsigned int *out_len, void *arg) {
-  const TestConfig *config = GetConfigPtr(ssl);
+  const TestConfig *config = GetTestConfig(ssl);
   if (config->advertise_npn.empty()) {
     return SSL_TLSEXT_ERR_NOACK;
   }
@@ -431,7 +731,7 @@
 
 static int NextProtoSelectCallback(SSL* ssl, uint8_t** out, uint8_t* outlen,
                                    const uint8_t* in, unsigned inlen, void* arg) {
-  const TestConfig *config = GetConfigPtr(ssl);
+  const TestConfig *config = GetTestConfig(ssl);
   if (config->select_next_proto.empty()) {
     return SSL_TLSEXT_ERR_NOACK;
   }
@@ -443,21 +743,32 @@
 
 static int AlpnSelectCallback(SSL* ssl, const uint8_t** out, uint8_t* outlen,
                               const uint8_t* in, unsigned inlen, void* arg) {
-  const TestConfig *config = GetConfigPtr(ssl);
-  if (config->select_alpn.empty()) {
+  if (GetTestState(ssl)->alpn_select_done) {
+    fprintf(stderr, "AlpnSelectCallback called after completion.\n");
+    exit(1);
+  }
+
+  GetTestState(ssl)->alpn_select_done = true;
+
+  const TestConfig *config = GetTestConfig(ssl);
+  if (config->decline_alpn) {
     return SSL_TLSEXT_ERR_NOACK;
   }
 
   if (!config->expected_advertised_alpn.empty() &&
       (config->expected_advertised_alpn.size() != inlen ||
-       memcmp(config->expected_advertised_alpn.data(),
-              in, inlen) != 0)) {
+       OPENSSL_memcmp(config->expected_advertised_alpn.data(), in, inlen) !=
+           0)) {
     fprintf(stderr, "bad ALPN select callback inputs\n");
     exit(1);
   }
 
   *out = (const uint8_t*)config->select_alpn.data();
   *outlen = config->select_alpn.size();
+  if (GetTestState(ssl)->is_resume && config->select_resume_alpn.size() > 0) {
+    *out = (const uint8_t*)config->select_resume_alpn.data();
+    *outlen = config->select_resume_alpn.size();
+  }
   return SSL_TLSEXT_ERR_OK;
 }
 
@@ -465,9 +776,15 @@
                                   char *out_identity,
                                   unsigned max_identity_len,
                                   uint8_t *out_psk, unsigned max_psk_len) {
-  const TestConfig *config = GetConfigPtr(ssl);
+  const TestConfig *config = GetTestConfig(ssl);
 
-  if (strcmp(hint ? hint : "", config->psk_identity.c_str()) != 0) {
+  if (config->psk_identity.empty()) {
+    if (hint != nullptr) {
+      fprintf(stderr, "Server PSK hint was non-null.\n");
+      return 0;
+    }
+  } else if (hint == nullptr ||
+             strcmp(hint, config->psk_identity.c_str()) != 0) {
     fprintf(stderr, "Server PSK hint did not match.\n");
     return 0;
   }
@@ -481,13 +798,13 @@
 
   BUF_strlcpy(out_identity, config->psk_identity.c_str(),
               max_identity_len);
-  memcpy(out_psk, config->psk.data(), config->psk.size());
+  OPENSSL_memcpy(out_psk, config->psk.data(), config->psk.size());
   return config->psk.size();
 }
 
 static unsigned PskServerCallback(SSL *ssl, const char *identity,
                                   uint8_t *out_psk, unsigned max_psk_len) {
-  const TestConfig *config = GetConfigPtr(ssl);
+  const TestConfig *config = GetTestConfig(ssl);
 
   if (strcmp(identity, config->psk_identity.c_str()) != 0) {
     fprintf(stderr, "Client PSK identity did not match.\n");
@@ -499,28 +816,20 @@
     return 0;
   }
 
-  memcpy(out_psk, config->psk.data(), config->psk.size());
+  OPENSSL_memcpy(out_psk, config->psk.data(), config->psk.size());
   return config->psk.size();
 }
 
+static timeval g_clock;
+
 static void CurrentTimeCallback(const SSL *ssl, timeval *out_clock) {
-  *out_clock = GetTestState(ssl)->clock;
+  *out_clock = g_clock;
 }
 
 static void ChannelIdCallback(SSL *ssl, EVP_PKEY **out_pkey) {
   *out_pkey = GetTestState(ssl)->channel_id.release();
 }
 
-static int CertCallback(SSL *ssl, void *arg) {
-  if (!GetTestState(ssl)->cert_ready) {
-    return -1;
-  }
-  if (!InstallCertificate(ssl)) {
-    return 0;
-  }
-  return 1;
-}
-
 static SSL_SESSION *GetSessionCallback(SSL *ssl, uint8_t *data, int len,
                                        int *copy) {
   TestState *async_state = GetTestState(ssl);
@@ -534,8 +843,8 @@
   }
 }
 
-static int DDoSCallback(const struct ssl_early_callback_ctx *early_context) {
-  const TestConfig *config = GetConfigPtr(early_context->ssl);
+static int DDoSCallback(const SSL_CLIENT_HELLO *client_hello) {
+  const TestConfig *config = GetTestConfig(client_hello->ssl);
   static int callback_num = 0;
 
   callback_num++;
@@ -548,33 +857,45 @@
 
 static void InfoCallback(const SSL *ssl, int type, int val) {
   if (type == SSL_CB_HANDSHAKE_DONE) {
-    if (GetConfigPtr(ssl)->handshake_never_done) {
-      fprintf(stderr, "handshake completed\n");
+    if (GetTestConfig(ssl)->handshake_never_done) {
+      fprintf(stderr, "Handshake unexpectedly completed.\n");
       // Abort before any expected error code is printed, to ensure the overall
       // test fails.
       abort();
     }
     GetTestState(ssl)->handshake_done = true;
+
+    // Callbacks may be called again on a new handshake.
+    GetTestState(ssl)->ticket_decrypt_done = false;
+    GetTestState(ssl)->alpn_select_done = false;
   }
 }
 
 static int NewSessionCallback(SSL *ssl, SSL_SESSION *session) {
   GetTestState(ssl)->got_new_session = true;
-  // BoringSSL passes a reference to |session|.
-  SSL_SESSION_free(session);
+  GetTestState(ssl)->new_session.reset(session);
   return 1;
 }
 
 static int TicketKeyCallback(SSL *ssl, uint8_t *key_name, uint8_t *iv,
                              EVP_CIPHER_CTX *ctx, HMAC_CTX *hmac_ctx,
                              int encrypt) {
+  if (!encrypt) {
+    if (GetTestState(ssl)->ticket_decrypt_done) {
+      fprintf(stderr, "TicketKeyCallback called after completion.\n");
+      return -1;
+    }
+
+    GetTestState(ssl)->ticket_decrypt_done = true;
+  }
+
   // This is just test code, so use the all-zeros key.
   static const uint8_t kZeros[16] = {0};
 
   if (encrypt) {
-    memcpy(key_name, kZeros, sizeof(kZeros));
+    OPENSSL_memcpy(key_name, kZeros, sizeof(kZeros));
     RAND_bytes(iv, 16);
-  } else if (memcmp(key_name, kZeros, 16) != 0) {
+  } else if (OPENSSL_memcmp(key_name, kZeros, 16) != 0) {
     return 0;
   }
 
@@ -584,7 +905,7 @@
   }
 
   if (!encrypt) {
-    return GetConfigPtr(ssl)->renew_ticket ? 2 : 1;
+    return GetTestConfig(ssl)->renew_ticket ? 2 : 1;
   }
   return 1;
 }
@@ -606,10 +927,10 @@
     abort();
   }
 
-  if (GetConfigPtr(ssl)->custom_extension_skip) {
+  if (GetTestConfig(ssl)->custom_extension_skip) {
     return 0;
   }
-  if (GetConfigPtr(ssl)->custom_extension_fail_add) {
+  if (GetTestConfig(ssl)->custom_extension_fail_add) {
     return -1;
   }
 
@@ -638,7 +959,7 @@
   }
 
   if (contents_len != sizeof(kCustomExtensionContents) - 1 ||
-      memcmp(contents, kCustomExtensionContents, contents_len) != 0) {
+      OPENSSL_memcmp(contents, kCustomExtensionContents, contents_len) != 0) {
     *out_alert_value = SSL_AD_DECODE_ERROR;
     return 0;
   }
@@ -646,6 +967,20 @@
   return 1;
 }
 
+static int ServerNameCallback(SSL *ssl, int *out_alert, void *arg) {
+  // SNI must be accessible from the SNI callback.
+  const TestConfig *config = GetTestConfig(ssl);
+  const char *server_name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
+  if (server_name == nullptr ||
+      std::string(server_name) != config->expected_server_name) {
+    fprintf(stderr, "servername mismatch (got %s; want %s)\n", server_name,
+            config->expected_server_name.c_str());
+    return SSL_TLSEXT_ERR_ALERT_FATAL;
+  }
+
+  return SSL_TLSEXT_ERR_OK;
+}
+
 // Connect returns a new socket connected to localhost on |port| or -1 on
 // error.
 static int Connect(uint16_t port) {
@@ -662,7 +997,7 @@
     return -1;
   }
   sockaddr_in sin;
-  memset(&sin, 0, sizeof(sin));
+  OPENSSL_memset(&sin, 0, sizeof(sin));
   sin.sin_family = AF_INET;
   sin.sin_port = htons(port);
   if (!inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr)) {
@@ -704,34 +1039,34 @@
   const int sock_;
 };
 
-static ScopedSSL_CTX SetupCtx(const TestConfig *config) {
-  ScopedSSL_CTX ssl_ctx(SSL_CTX_new(
+static bssl::UniquePtr<SSL_CTX> SetupCtx(const TestConfig *config) {
+  bssl::UniquePtr<SSL_CTX> ssl_ctx(SSL_CTX_new(
       config->is_dtls ? DTLS_method() : TLS_method()));
   if (!ssl_ctx) {
     return nullptr;
   }
 
+  SSL_CTX_set0_buffer_pool(ssl_ctx.get(), g_pool);
+
+  // Enable TLS 1.3 for tests.
+  if (!config->is_dtls &&
+      !SSL_CTX_set_max_proto_version(ssl_ctx.get(), TLS1_3_VERSION)) {
+    return nullptr;
+  }
+
   std::string cipher_list = "ALL";
   if (!config->cipher.empty()) {
     cipher_list = config->cipher;
     SSL_CTX_set_options(ssl_ctx.get(), SSL_OP_CIPHER_SERVER_PREFERENCE);
   }
-  if (!SSL_CTX_set_cipher_list(ssl_ctx.get(), cipher_list.c_str())) {
+  if (!SSL_CTX_set_strict_cipher_list(ssl_ctx.get(), cipher_list.c_str())) {
     return nullptr;
   }
 
-  if (!config->cipher_tls10.empty() &&
-      !SSL_CTX_set_cipher_list_tls10(ssl_ctx.get(),
-                                     config->cipher_tls10.c_str())) {
+  bssl::UniquePtr<DH> dh(DH_get_2048_256(NULL));
+  if (!dh) {
     return nullptr;
   }
-  if (!config->cipher_tls11.empty() &&
-      !SSL_CTX_set_cipher_list_tls11(ssl_ctx.get(),
-                                     config->cipher_tls11.c_str())) {
-    return nullptr;
-  }
-
-  ScopedDH dh(DH_get_2048_256(NULL));
 
   if (config->use_sparse_dh_prime) {
     // This prime number is 2^1024 + 643 – a value just above a power of two.
@@ -747,10 +1082,12 @@
         !BN_set_word(dh->g, 2)) {
       return nullptr;
     }
+    BN_free(dh->q);
+    dh->q = NULL;
     dh->priv_length = 0;
   }
 
-  if (!dh || !SSL_CTX_set_tmp_dh(ssl_ctx.get(), dh.get())) {
+  if (!SSL_CTX_set_tmp_dh(ssl_ctx.get(), dh.get())) {
     return nullptr;
   }
 
@@ -766,6 +1103,10 @@
 
   SSL_CTX_set_select_certificate_cb(ssl_ctx.get(), SelectCertificateCallback);
 
+  if (config->use_old_client_cert_callback) {
+    SSL_CTX_set_client_cert_cb(ssl_ctx.get(), ClientCertCallback);
+  }
+
   SSL_CTX_set_next_protos_advertised_cb(
       ssl_ctx.get(), NextProtosAdvertisedCallback, NULL);
   if (!config->select_next_proto.empty()) {
@@ -773,14 +1114,14 @@
                                      NULL);
   }
 
-  if (!config->select_alpn.empty()) {
+  if (!config->select_alpn.empty() || !config->select_resume_alpn.empty() ||
+      config->decline_alpn) {
     SSL_CTX_set_alpn_select_cb(ssl_ctx.get(), AlpnSelectCallback, NULL);
   }
 
-  SSL_CTX_enable_tls_channel_id(ssl_ctx.get());
   SSL_CTX_set_channel_id_cb(ssl_ctx.get(), ChannelIdCallback);
 
-  ssl_ctx->current_time_cb = CurrentTimeCallback;
+  SSL_CTX_set_current_time_cb(ssl_ctx.get(), CurrentTimeCallback);
 
   SSL_CTX_set_info_callback(ssl_ctx.get(), InfoCallback);
   SSL_CTX_sess_set_new_cb(ssl_ctx.get(), NewSessionCallback);
@@ -818,6 +1159,34 @@
     return nullptr;
   }
 
+  if (!config->use_client_ca_list.empty()) {
+    if (config->use_client_ca_list == "<NULL>") {
+      SSL_CTX_set_client_CA_list(ssl_ctx.get(), nullptr);
+    } else {
+      bssl::UniquePtr<STACK_OF(X509_NAME)> names =
+          DecodeHexX509Names(config->use_client_ca_list);
+      SSL_CTX_set_client_CA_list(ssl_ctx.get(), names.release());
+    }
+  }
+
+  if (config->enable_grease) {
+    SSL_CTX_set_grease_enabled(ssl_ctx.get(), 1);
+  }
+
+  if (!config->expected_server_name.empty()) {
+    SSL_CTX_set_tlsext_servername_callback(ssl_ctx.get(), ServerNameCallback);
+  }
+
+  if (!config->ticket_key.empty() &&
+      !SSL_CTX_set_tlsext_ticket_keys(ssl_ctx.get(), config->ticket_key.data(),
+                                      config->ticket_key.size())) {
+    return nullptr;
+  }
+
+  if (config->enable_early_data) {
+    SSL_CTX_set_early_data_enabled(ssl_ctx.get(), 1);
+  }
+
   return ssl_ctx;
 }
 
@@ -830,26 +1199,16 @@
     return false;
   }
 
-  const TestConfig *config = GetConfigPtr(ssl);
   TestState *test_state = GetTestState(ssl);
-  if (test_state->clock_delta.tv_usec != 0 ||
-      test_state->clock_delta.tv_sec != 0) {
-    // Process the timeout and retry.
-    test_state->clock.tv_usec += test_state->clock_delta.tv_usec;
-    test_state->clock.tv_sec += test_state->clock.tv_usec / 1000000;
-    test_state->clock.tv_usec %= 1000000;
-    test_state->clock.tv_sec += test_state->clock_delta.tv_sec;
-    memset(&test_state->clock_delta, 0, sizeof(test_state->clock_delta));
+  assert(GetTestConfig(ssl)->async);
 
+  if (test_state->packeted_bio != nullptr &&
+      PacketedBioAdvanceClock(test_state->packeted_bio)) {
     // The DTLS retransmit logic silently ignores write failures. So the test
     // may progress, allow writes through synchronously.
-    if (config->async) {
-      AsyncBioEnforceWriteQuota(test_state->async_bio, false);
-    }
+    AsyncBioEnforceWriteQuota(test_state->async_bio, false);
     int timeout_ret = DTLSv1_handle_timeout(ssl);
-    if (config->async) {
-      AsyncBioEnforceWriteQuota(test_state->async_bio, true);
-    }
+    AsyncBioEnforceWriteQuota(test_state->async_bio, true);
 
     if (timeout_ret < 0) {
       fprintf(stderr, "Error retransmitting.\n");
@@ -868,7 +1227,8 @@
       AsyncBioAllowWrite(test_state->async_bio, 1);
       return true;
     case SSL_ERROR_WANT_CHANNEL_ID_LOOKUP: {
-      ScopedEVP_PKEY pkey = LoadPrivateKey(GetConfigPtr(ssl)->send_channel_id);
+      bssl::UniquePtr<EVP_PKEY> pkey =
+          LoadPrivateKey(GetTestConfig(ssl)->send_channel_id);
       if (!pkey) {
         return false;
       }
@@ -882,8 +1242,8 @@
       test_state->session = std::move(test_state->pending_session);
       return true;
     case SSL_ERROR_PENDING_CERTIFICATE:
-      // The handshake will resume without a second call to the early callback.
-      return InstallCertificate(ssl);
+      test_state->early_callback_ready = true;
+      return true;
     case SSL_ERROR_WANT_PRIVATE_KEY_OPERATION:
       test_state->private_key_retries++;
       return true;
@@ -895,7 +1255,7 @@
 // DoRead reads from |ssl|, resolving any asynchronous operations. It returns
 // the result value of the final |SSL_read| call.
 static int DoRead(SSL *ssl, uint8_t *out, size_t max_out) {
-  const TestConfig *config = GetConfigPtr(ssl);
+  const TestConfig *config = GetTestConfig(ssl);
   TestState *test_state = GetTestState(ssl);
   int ret;
   do {
@@ -905,18 +1265,50 @@
       // trigger a retransmit, so disconnect the write quota.
       AsyncBioEnforceWriteQuota(test_state->async_bio, false);
     }
-    ret = SSL_read(ssl, out, max_out);
+    ret = config->peek_then_read ? SSL_peek(ssl, out, max_out)
+                                 : SSL_read(ssl, out, max_out);
     if (config->async) {
       AsyncBioEnforceWriteQuota(test_state->async_bio, true);
     }
+
+    // Run the exporter after each read. This is to test that the exporter fails
+    // during a renegotiation.
+    if (config->use_exporter_between_reads) {
+      uint8_t buf;
+      if (!SSL_export_keying_material(ssl, &buf, 1, NULL, 0, NULL, 0, 0)) {
+        fprintf(stderr, "failed to export keying material\n");
+        return -1;
+      }
+    }
   } while (config->async && RetryAsync(ssl, ret));
+
+  if (config->peek_then_read && ret > 0) {
+    std::unique_ptr<uint8_t[]> buf(new uint8_t[static_cast<size_t>(ret)]);
+
+    // SSL_peek should synchronously return the same data.
+    int ret2 = SSL_peek(ssl, buf.get(), ret);
+    if (ret2 != ret ||
+        OPENSSL_memcmp(buf.get(), out, ret) != 0) {
+      fprintf(stderr, "First and second SSL_peek did not match.\n");
+      return -1;
+    }
+
+    // SSL_read should synchronously return the same data and consume it.
+    ret2 = SSL_read(ssl, buf.get(), ret);
+    if (ret2 != ret ||
+        OPENSSL_memcmp(buf.get(), out, ret) != 0) {
+      fprintf(stderr, "SSL_peek and SSL_read did not match.\n");
+      return -1;
+    }
+  }
+
   return ret;
 }
 
 // WriteAll writes |in_len| bytes from |in| to |ssl|, resolving any asynchronous
 // operations. It returns the result of the final |SSL_write| call.
 static int WriteAll(SSL *ssl, const uint8_t *in, size_t in_len) {
-  const TestConfig *config = GetConfigPtr(ssl);
+  const TestConfig *config = GetTestConfig(ssl);
   int ret;
   do {
     ret = SSL_write(ssl, in, in_len);
@@ -931,7 +1323,7 @@
 // DoShutdown calls |SSL_shutdown|, resolving any asynchronous operations. It
 // returns the result of the final |SSL_shutdown| call.
 static int DoShutdown(SSL *ssl) {
-  const TestConfig *config = GetConfigPtr(ssl);
+  const TestConfig *config = GetTestConfig(ssl);
   int ret;
   do {
     ret = SSL_shutdown(ssl);
@@ -939,11 +1331,30 @@
   return ret;
 }
 
+// DoSendFatalAlert calls |SSL_send_fatal_alert|, resolving any asynchronous
+// operations. It returns the result of the final |SSL_send_fatal_alert| call.
+static int DoSendFatalAlert(SSL *ssl, uint8_t alert) {
+  const TestConfig *config = GetTestConfig(ssl);
+  int ret;
+  do {
+    ret = SSL_send_fatal_alert(ssl, alert);
+  } while (config->async && RetryAsync(ssl, ret));
+  return ret;
+}
+
+static uint16_t GetProtocolVersion(const SSL *ssl) {
+  uint16_t version = SSL_version(ssl);
+  if (!SSL_is_dtls(ssl)) {
+    return version;
+  }
+  return 0x0201 + ~version;
+}
+
 // CheckHandshakeProperties checks, immediately after |ssl| completes its
 // initial handshake (or False Starts), whether all the properties are
 // consistent with the test configuration and invariants.
 static bool CheckHandshakeProperties(SSL *ssl, bool is_resume) {
-  const TestConfig *config = GetConfigPtr(ssl);
+  const TestConfig *config = GetTestConfig(ssl);
 
   if (SSL_get_current_cipher(ssl) == nullptr) {
     fprintf(stderr, "null cipher after handshake\n");
@@ -957,7 +1368,9 @@
     return false;
   }
 
-  bool expect_handshake_done = is_resume || !config->false_start;
+  bool expect_handshake_done =
+      (is_resume || !config->false_start) &&
+      !(config->is_server && SSL_early_data_accepted(ssl));
   if (expect_handshake_done != GetTestState(ssl)->handshake_done) {
     fprintf(stderr, "handshake was%s completed\n",
             GetTestState(ssl)->handshake_done ? "" : " not");
@@ -967,7 +1380,9 @@
   if (expect_handshake_done && !config->is_server) {
     bool expect_new_session =
         !config->expect_no_session &&
-        (!SSL_session_reused(ssl) || config->expect_ticket_renewal);
+        (!SSL_session_reused(ssl) || config->expect_ticket_renewal) &&
+        // Session tickets are sent post-handshake in TLS 1.3.
+        GetProtocolVersion(ssl) < TLS1_3_VERSION;
     if (expect_new_session != GetTestState(ssl)->got_new_session) {
       fprintf(stderr,
               "new session was%s cached, but we expected the opposite\n",
@@ -976,6 +1391,17 @@
     }
   }
 
+  if (!is_resume) {
+    if (config->expect_session_id && !GetTestState(ssl)->got_new_session) {
+      fprintf(stderr, "session was not cached on the server.\n");
+      return false;
+    }
+    if (config->expect_no_session_id && GetTestState(ssl)->got_new_session) {
+      fprintf(stderr, "session was unexpectedly cached on the server.\n");
+      return false;
+    }
+  }
+
   if (config->is_server && !GetTestState(ssl)->early_callback_called) {
     fprintf(stderr, "early callback not called\n");
     return false;
@@ -984,45 +1410,42 @@
   if (!config->expected_server_name.empty()) {
     const char *server_name =
         SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
-    if (server_name != config->expected_server_name) {
+    if (server_name == nullptr ||
+        server_name != config->expected_server_name) {
       fprintf(stderr, "servername mismatch (got %s; want %s)\n",
               server_name, config->expected_server_name.c_str());
       return false;
     }
   }
 
-  if (!config->expected_certificate_types.empty()) {
-    const uint8_t *certificate_types;
-    size_t certificate_types_len =
-        SSL_get0_certificate_types(ssl, &certificate_types);
-    if (certificate_types_len != config->expected_certificate_types.size() ||
-        memcmp(certificate_types,
-               config->expected_certificate_types.data(),
-               certificate_types_len) != 0) {
-      fprintf(stderr, "certificate types mismatch\n");
-      return false;
-    }
-  }
-
   if (!config->expected_next_proto.empty()) {
     const uint8_t *next_proto;
     unsigned next_proto_len;
     SSL_get0_next_proto_negotiated(ssl, &next_proto, &next_proto_len);
     if (next_proto_len != config->expected_next_proto.size() ||
-        memcmp(next_proto, config->expected_next_proto.data(),
-               next_proto_len) != 0) {
+        OPENSSL_memcmp(next_proto, config->expected_next_proto.data(),
+                       next_proto_len) != 0) {
       fprintf(stderr, "negotiated next proto mismatch\n");
       return false;
     }
   }
 
-  if (!config->expected_alpn.empty()) {
+  std::string expected_alpn = config->expected_alpn;
+  if (is_resume && !config->expected_resume_alpn.empty()) {
+    expected_alpn = config->expected_resume_alpn;
+  }
+  bool expect_no_alpn = (!is_resume && config->expect_no_alpn) ||
+      (is_resume && config->expect_no_resume_alpn);
+  if (expect_no_alpn) {
+    expected_alpn.clear();
+  }
+
+  if (!expected_alpn.empty() || expect_no_alpn) {
     const uint8_t *alpn_proto;
     unsigned alpn_proto_len;
     SSL_get0_alpn_selected(ssl, &alpn_proto, &alpn_proto_len);
-    if (alpn_proto_len != config->expected_alpn.size() ||
-        memcmp(alpn_proto, config->expected_alpn.data(),
-               alpn_proto_len) != 0) {
+    if (alpn_proto_len != expected_alpn.size() ||
+        OPENSSL_memcmp(alpn_proto, expected_alpn.data(), alpn_proto_len) != 0) {
       fprintf(stderr, "negotiated alpn proto mismatch\n");
       return false;
     }
@@ -1035,18 +1458,29 @@
       return false;
     }
     if (config->expected_channel_id.size() != 64 ||
-        memcmp(config->expected_channel_id.data(),
-               channel_id, 64) != 0) {
+        OPENSSL_memcmp(config->expected_channel_id.data(), channel_id, 64) !=
+            0) {
       fprintf(stderr, "channel id mismatch\n");
       return false;
     }
   }
 
-  if (config->expect_extended_master_secret) {
-    if (!ssl->session->extended_master_secret) {
-      fprintf(stderr, "No EMS for session when expected");
-      return false;
-    }
+  if (config->expect_extended_master_secret && !SSL_get_extms_support(ssl)) {
+    fprintf(stderr, "No EMS for connection when expected\n");
+    return false;
+  }
+
+  if (config->expect_secure_renegotiation &&
+      !SSL_get_secure_renegotiation_support(ssl)) {
+    fprintf(stderr, "No secure renegotiation for connection when expected\n");
+    return false;
+  }
+
+  if (config->expect_no_secure_renegotiation &&
+      SSL_get_secure_renegotiation_support(ssl)) {
+    fprintf(stderr,
+            "Secure renegotiation unexpectedly negotiated for connection\n");
+    return false;
   }
 
   if (!config->expected_ocsp_response.empty()) {
@@ -1054,7 +1488,7 @@
     size_t len;
     SSL_get0_ocsp_response(ssl, &data, &len);
     if (config->expected_ocsp_response.size() != len ||
-        memcmp(config->expected_ocsp_response.data(), data, len) != 0) {
+        OPENSSL_memcmp(config->expected_ocsp_response.data(), data, len) != 0) {
       fprintf(stderr, "OCSP response mismatch\n");
       return false;
     }
@@ -1065,8 +1499,8 @@
     size_t len;
     SSL_get0_signed_cert_timestamp_list(ssl, &data, &len);
     if (config->expected_signed_cert_timestamps.size() != len ||
-        memcmp(config->expected_signed_cert_timestamps.data(),
-               data, len) != 0) {
+        OPENSSL_memcmp(config->expected_signed_cert_timestamps.data(), data,
+                       len) != 0) {
       fprintf(stderr, "SCT list mismatch\n");
       return false;
     }
@@ -1083,37 +1517,134 @@
     }
   }
 
-  if (config->expect_server_key_exchange_hash != 0 &&
-      config->expect_server_key_exchange_hash !=
-          SSL_get_server_key_exchange_hash(ssl)) {
-    fprintf(stderr, "ServerKeyExchange hash was %d, wanted %d.\n",
-            SSL_get_server_key_exchange_hash(ssl),
-            config->expect_server_key_exchange_hash);
+  if (config->expect_peer_signature_algorithm != 0 &&
+      config->expect_peer_signature_algorithm !=
+          SSL_get_peer_signature_algorithm(ssl)) {
+    fprintf(stderr, "Peer signature algorithm was %04x, wanted %04x.\n",
+            SSL_get_peer_signature_algorithm(ssl),
+            config->expect_peer_signature_algorithm);
     return false;
   }
 
-  if (config->expect_key_exchange_info != 0) {
-    uint32_t info = SSL_SESSION_get_key_exchange_info(SSL_get_session(ssl));
-    if (static_cast<uint32_t>(config->expect_key_exchange_info) != info) {
-      fprintf(stderr, "key_exchange_info was %" PRIu32 ", wanted %" PRIu32 "\n",
-              info, static_cast<uint32_t>(config->expect_key_exchange_info));
+  int expect_curve_id = config->expect_curve_id;
+  if (is_resume && config->expect_resume_curve_id != 0) {
+    expect_curve_id = config->expect_resume_curve_id;
+  }
+  if (expect_curve_id != 0) {
+    uint16_t curve_id = SSL_get_curve_id(ssl);
+    if (static_cast<uint16_t>(expect_curve_id) != curve_id) {
+      fprintf(stderr, "curve_id was %04x, wanted %04x\n", curve_id,
+              static_cast<uint16_t>(expect_curve_id));
       return false;
     }
   }
 
-  if (!config->is_server) {
-    /* Clients should expect a peer certificate chain iff this was not a PSK
-     * cipher suite. */
-    if (config->psk.empty()) {
-      if (SSL_get_peer_cert_chain(ssl) == nullptr) {
-        fprintf(stderr, "Missing peer certificate chain!\n");
-        return false;
-      }
-    } else if (SSL_get_peer_cert_chain(ssl) != nullptr) {
-      fprintf(stderr, "Unexpected peer certificate chain!\n");
+  uint16_t cipher_id =
+      static_cast<uint16_t>(SSL_CIPHER_get_id(SSL_get_current_cipher(ssl)));
+  if (config->expect_cipher_aes != 0 &&
+      EVP_has_aes_hardware() &&
+      static_cast<uint16_t>(config->expect_cipher_aes) != cipher_id) {
+    fprintf(stderr, "Cipher ID was %04x, wanted %04x (has AES hardware)\n",
+            cipher_id, static_cast<uint16_t>(config->expect_cipher_aes));
+    return false;
+  }
+
+  if (config->expect_cipher_no_aes != 0 &&
+      !EVP_has_aes_hardware() &&
+      static_cast<uint16_t>(config->expect_cipher_no_aes) != cipher_id) {
+    fprintf(stderr, "Cipher ID was %04x, wanted %04x (no AES hardware)\n",
+            cipher_id, static_cast<uint16_t>(config->expect_cipher_no_aes));
+    return false;
+  }
+
+  if (is_resume) {
+    if ((config->expect_accept_early_data && !SSL_early_data_accepted(ssl)) ||
+        (config->expect_reject_early_data && SSL_early_data_accepted(ssl))) {
+      fprintf(stderr,
+              "Early data was%s accepted, but we expected the opposite\n",
+              SSL_early_data_accepted(ssl) ? "" : " not");
       return false;
     }
   }
+
+  if (!config->psk.empty()) {
+    if (SSL_get_peer_cert_chain(ssl) != nullptr) {
+      fprintf(stderr, "Received peer certificate on a PSK cipher.\n");
+      return false;
+    }
+  } else if (!config->is_server || config->require_any_client_certificate) {
+    if (SSL_get_peer_cert_chain(ssl) == nullptr) {
+      fprintf(stderr, "Received no peer certificate but expected one.\n");
+      return false;
+    }
+  }
+
+  if (!config->expect_peer_cert_file.empty()) {
+    bssl::UniquePtr<X509> expect_leaf;
+    bssl::UniquePtr<STACK_OF(X509)> expect_chain;
+    if (!LoadCertificate(&expect_leaf, &expect_chain,
+                         config->expect_peer_cert_file)) {
+      return false;
+    }
+
+    // For historical reasons, clients report a chain with a leaf and servers
+    // without.
+    if (!config->is_server) {
+      if (!sk_X509_insert(expect_chain.get(), expect_leaf.get(), 0)) {
+        return false;
+      }
+      X509_up_ref(expect_leaf.get());  // sk_X509_push takes ownership.
+    }
+
+    bssl::UniquePtr<X509> leaf(SSL_get_peer_certificate(ssl));
+    STACK_OF(X509) *chain = SSL_get_peer_cert_chain(ssl);
+    if (X509_cmp(leaf.get(), expect_leaf.get()) != 0) {
+      fprintf(stderr, "Received a different leaf certificate than expected.\n");
+      return false;
+    }
+
+    if (sk_X509_num(chain) != sk_X509_num(expect_chain.get())) {
+      fprintf(stderr, "Received a chain of length %zu instead of %zu.\n",
+              sk_X509_num(chain), sk_X509_num(expect_chain.get()));
+      return false;
+    }
+
+    for (size_t i = 0; i < sk_X509_num(chain); i++) {
+      if (X509_cmp(sk_X509_value(chain, i),
+                   sk_X509_value(expect_chain.get(), i)) != 0) {
+        fprintf(stderr, "Chain certificate %zu did not match.\n",
+                i + 1);
+        return false;
+      }
+    }
+  }
+
+  bool expected_sha256_client_cert = config->expect_sha256_client_cert_initial;
+  if (is_resume) {
+    expected_sha256_client_cert = config->expect_sha256_client_cert_resume;
+  }
+
+  if (SSL_get_session(ssl)->peer_sha256_valid != expected_sha256_client_cert) {
+    fprintf(stderr,
+            "Unexpected SHA-256 client cert state: expected:%d is_resume:%d.\n",
+            expected_sha256_client_cert, is_resume);
+    return false;
+  }
+
+  if (expected_sha256_client_cert &&
+      SSL_get_session(ssl)->certs != nullptr) {
+    fprintf(stderr, "Have both client cert and SHA-256 hash: is_resume:%d.\n",
+            is_resume);
+    return false;
+  }
+
+  if (is_resume && config->expect_ticket_age_skew != 0 &&
+      SSL_get_ticket_age_skew(ssl) != config->expect_ticket_age_skew) {
+    fprintf(stderr, "Ticket age skew was %" PRId32 ", wanted %d\n",
+            SSL_get_ticket_age_skew(ssl), config->expect_ticket_age_skew);
+    return false;
+  }
+
   return true;
 }
 
@@ -1121,30 +1652,38 @@
 // true and sets |*out_session| to the negotiated SSL session. If the test is a
 // resumption attempt, |is_resume| is true and |session| is the session from the
 // previous exchange.
-static bool DoExchange(ScopedSSL_SESSION *out_session, SSL_CTX *ssl_ctx,
-                       const TestConfig *config, bool is_resume,
-                       SSL_SESSION *session) {
-  ScopedSSL ssl(SSL_new(ssl_ctx));
+static bool DoExchange(bssl::UniquePtr<SSL_SESSION> *out_session,
+                       SSL_CTX *ssl_ctx, const TestConfig *config,
+                       bool is_resume, SSL_SESSION *session) {
+  if (is_resume && config->enable_resume_early_data) {
+    SSL_CTX_set_early_data_enabled(ssl_ctx, 1);
+  }
+
+  bssl::UniquePtr<SSL> ssl(SSL_new(ssl_ctx));
   if (!ssl) {
     return false;
   }
 
-  if (!SetConfigPtr(ssl.get(), config) ||
+  if (!SetTestConfig(ssl.get(), config) ||
       !SetTestState(ssl.get(), std::unique_ptr<TestState>(new TestState))) {
     return false;
   }
 
+  GetTestState(ssl.get())->is_resume = is_resume;
+
   if (config->fallback_scsv &&
       !SSL_set_mode(ssl.get(), SSL_MODE_SEND_FALLBACK_SCSV)) {
     return false;
   }
-  if (!config->use_early_callback) {
-    if (config->async) {
-      // TODO(davidben): Also test |s->ctx->client_cert_cb| on the client.
-      SSL_set_cert_cb(ssl.get(), CertCallback, NULL);
-    } else if (!InstallCertificate(ssl.get())) {
-      return false;
-    }
+  // Install the certificate synchronously if nothing else will handle it.
+  if (!config->use_early_callback &&
+      !config->use_old_client_cert_callback &&
+      !config->async &&
+      !InstallCertificate(ssl.get())) {
+    return false;
+  }
+  if (!config->use_old_client_cert_callback) {
+    SSL_set_cert_cb(ssl.get(), CertCallback, nullptr);
   }
   if (config->require_any_client_certificate) {
     SSL_set_verify(ssl.get(), SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
@@ -1162,6 +1701,9 @@
   if (config->partial_write) {
     SSL_set_mode(ssl.get(), SSL_MODE_ENABLE_PARTIAL_WRITE);
   }
+  if (config->no_tls13) {
+    SSL_set_options(ssl.get(), SSL_OP_NO_TLSv1_3);
+  }
   if (config->no_tls12) {
     SSL_set_options(ssl.get(), SSL_OP_NO_TLSv1_2);
   }
@@ -1174,14 +1716,15 @@
   if (config->no_ssl3) {
     SSL_set_options(ssl.get(), SSL_OP_NO_SSLv3);
   }
-  if (!config->expected_channel_id.empty()) {
-    SSL_enable_tls_channel_id(ssl.get());
+  if (!config->expected_channel_id.empty() ||
+      config->enable_channel_id) {
+    SSL_set_tls_channel_id_enabled(ssl.get(), 1);
   }
   if (!config->send_channel_id.empty()) {
-    SSL_enable_tls_channel_id(ssl.get());
+    SSL_set_tls_channel_id_enabled(ssl.get(), 1);
     if (!config->async) {
       // The async case will be supplied by |ChannelIdCallback|.
-      ScopedEVP_PKEY pkey = LoadPrivateKey(config->send_channel_id);
+      bssl::UniquePtr<EVP_PKEY> pkey = LoadPrivateKey(config->send_channel_id);
       if (!pkey || !SSL_set1_tls_channel_id(ssl.get(), pkey.get())) {
         return false;
       }
@@ -1209,20 +1752,20 @@
       !SSL_set_srtp_profiles(ssl.get(), config->srtp_profiles.c_str())) {
     return false;
   }
-  if (config->enable_ocsp_stapling &&
-      !SSL_enable_ocsp_stapling(ssl.get())) {
+  if (config->enable_ocsp_stapling) {
+    SSL_enable_ocsp_stapling(ssl.get());
+  }
+  if (config->enable_signed_cert_timestamps) {
+    SSL_enable_signed_cert_timestamps(ssl.get());
+  }
+  if (config->min_version != 0 &&
+      !SSL_set_min_proto_version(ssl.get(), (uint16_t)config->min_version)) {
     return false;
   }
-  if (config->enable_signed_cert_timestamps &&
-      !SSL_enable_signed_cert_timestamps(ssl.get())) {
+  if (config->max_version != 0 &&
+      !SSL_set_max_proto_version(ssl.get(), (uint16_t)config->max_version)) {
     return false;
   }
-  if (config->min_version != 0) {
-    SSL_set_min_version(ssl.get(), (uint16_t)config->min_version);
-  }
-  if (config->max_version != 0) {
-    SSL_set_max_version(ssl.get(), (uint16_t)config->max_version);
-  }
   if (config->mtu != 0) {
     SSL_set_options(ssl.get(), SSL_OP_NO_QUERY_MTU);
     SSL_set_mtu(ssl.get(), config->mtu);
@@ -1242,9 +1785,6 @@
   if (!config->check_close_notify) {
     SSL_set_quiet_shutdown(ssl.get(), 1);
   }
-  if (config->disable_npn) {
-    SSL_set_options(ssl.get(), SSL_OP_DISABLE_NPN);
-  }
   if (config->p384_only) {
     int nid = NID_secp384r1;
     if (!SSL_set1_curves(ssl.get(), &nid, 1)) {
@@ -1253,13 +1793,29 @@
   }
   if (config->enable_all_curves) {
     static const int kAllCurves[] = {
-        NID_X9_62_prime256v1, NID_secp384r1, NID_secp521r1, NID_x25519,
+      NID_X9_62_prime256v1, NID_secp384r1, NID_secp521r1, NID_X25519,
     };
     if (!SSL_set1_curves(ssl.get(), kAllCurves,
-                         sizeof(kAllCurves) / sizeof(kAllCurves[0]))) {
+                         OPENSSL_ARRAY_SIZE(kAllCurves))) {
       return false;
     }
   }
+  if (config->initial_timeout_duration_ms > 0) {
+    DTLSv1_set_initial_timeout_duration(ssl.get(),
+                                        config->initial_timeout_duration_ms);
+  }
+  if (config->max_cert_list > 0) {
+    SSL_set_max_cert_list(ssl.get(), config->max_cert_list);
+  }
+  if (!is_resume && config->retain_only_sha256_client_cert_initial) {
+    SSL_set_retain_only_sha256_of_client_certs(ssl.get(), 1);
+  }
+  if (is_resume && config->retain_only_sha256_client_cert_resume) {
+    SSL_set_retain_only_sha256_of_client_certs(ssl.get(), 1);
+  }
+  if (config->max_send_fragment > 0) {
+    SSL_set_max_send_fragment(ssl.get(), config->max_send_fragment);
+  }
 
   int sock = Connect(config->port);
   if (sock == -1) {
@@ -1267,19 +1823,25 @@
   }
   SocketCloser closer(sock);
 
-  ScopedBIO bio(BIO_new_socket(sock, BIO_NOCLOSE));
+  bssl::UniquePtr<BIO> bio(BIO_new_socket(sock, BIO_NOCLOSE));
   if (!bio) {
     return false;
   }
   if (config->is_dtls) {
-    ScopedBIO packeted =
-        PacketedBioCreate(&GetTestState(ssl.get())->clock_delta);
+    bssl::UniquePtr<BIO> packeted = PacketedBioCreate(&g_clock);
+    if (!packeted) {
+      return false;
+    }
+    GetTestState(ssl.get())->packeted_bio = packeted.get();
     BIO_push(packeted.get(), bio.release());
     bio = std::move(packeted);
   }
   if (config->async) {
-    ScopedBIO async_scoped =
+    bssl::UniquePtr<BIO> async_scoped =
         config->is_dtls ? AsyncBioCreateDatagram() : AsyncBioCreate();
+    if (!async_scoped) {
+      return false;
+    }
     BIO_push(async_scoped.get(), bio.release());
     GetTestState(ssl.get())->async_bio = async_scoped.get();
     bio = std::move(async_scoped);
@@ -1295,8 +1857,8 @@
     } else if (config->async) {
       // The internal session cache is disabled, so install the session
       // manually.
-      GetTestState(ssl.get())->pending_session.reset(
-          SSL_SESSION_up_ref(session));
+      SSL_SESSION_up_ref(session);
+      GetTestState(ssl.get())->pending_session.reset(session);
     }
   }
 
@@ -1305,20 +1867,16 @@
     return false;
   }
 
-  int ret;
-  if (config->implicit_handshake) {
-    if (config->is_server) {
-      SSL_set_accept_state(ssl.get());
-    } else {
-      SSL_set_connect_state(ssl.get());
-    }
+  if (config->is_server) {
+    SSL_set_accept_state(ssl.get());
   } else {
+    SSL_set_connect_state(ssl.get());
+  }
+
+  int ret;
+  if (!config->implicit_handshake) {
     do {
-      if (config->is_server) {
-        ret = SSL_accept(ssl.get());
-      } else {
-        ret = SSL_connect(ssl.get());
-      }
+      ret = SSL_do_handshake(ssl.get());
     } while (config->async && RetryAsync(ssl.get(), ret));
     if (ret != 1 ||
         !CheckHandshakeProperties(ssl.get(), is_resume)) {
@@ -1366,6 +1924,13 @@
     }
   }
 
+  if (config->send_alert) {
+    if (DoSendFatalAlert(ssl.get(), SSL_AD_DECOMPRESSION_FAILURE) < 0) {
+      return false;
+    }
+    return true;
+  }
+
   if (config->write_different_record_sizes) {
     if (config->is_dtls) {
       fprintf(stderr, "write_different_record_sizes not supported for DTLS\n");
@@ -1375,11 +1940,10 @@
     // trip up the CBC record splitting code.
     static const size_t kBufLen = 32769;
     std::unique_ptr<uint8_t[]> buf(new uint8_t[kBufLen]);
-    memset(buf.get(), 0x42, kBufLen);
+    OPENSSL_memset(buf.get(), 0x42, kBufLen);
     static const size_t kRecordSizes[] = {
         0, 1, 255, 256, 257, 16383, 16384, 16385, 32767, 32768, 32769};
-    for (size_t i = 0; i < sizeof(kRecordSizes) / sizeof(kRecordSizes[0]);
-         i++) {
+    for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kRecordSizes); i++) {
       const size_t len = kRecordSizes[i];
       if (len > kBufLen) {
         fprintf(stderr, "Bad kRecordSizes value.\n");
@@ -1390,6 +1954,19 @@
       }
     }
   } else {
+    if (config->read_with_unfinished_write) {
+      if (!config->async) {
+        fprintf(stderr, "-read-with-unfinished-write requires -async.\n");
+        return false;
+      }
+
+      int write_ret = SSL_write(ssl.get(),
+                          reinterpret_cast<const uint8_t *>("unfinished"), 10);
+      if (SSL_get_error(ssl.get(), write_ret) != SSL_ERROR_WANT_WRITE) {
+        fprintf(stderr, "Failed to leave unfinished write.\n");
+        return false;
+      }
+    }
     if (config->shim_writes_first) {
       if (WriteAll(ssl.get(), reinterpret_cast<const uint8_t *>("hello"),
                    5) < 0) {
@@ -1398,12 +1975,15 @@
     }
     if (!config->shim_shuts_down) {
       for (;;) {
-        static const size_t kBufLen = 16384;
-        std::unique_ptr<uint8_t[]> buf(new uint8_t[kBufLen]);
-
         // Read only 512 bytes at a time in TLS to ensure records may be
         // returned in multiple reads.
-        int n = DoRead(ssl.get(), buf.get(), config->is_dtls ? kBufLen : 512);
+        size_t read_size = config->is_dtls ? 16384 : 512;
+        if (config->read_size > 0) {
+          read_size = config->read_size;
+        }
+        std::unique_ptr<uint8_t[]> buf(new uint8_t[read_size]);
+
+        int n = DoRead(ssl.get(), buf.get(), read_size);
         int err = SSL_get_error(ssl.get(), n);
         if (err == SSL_ERROR_ZERO_RETURN ||
             (n == 0 && err == SSL_ERROR_SYSCALL)) {
@@ -1427,8 +2007,9 @@
         }
 
         // After a successful read, with or without False Start, the handshake
-        // must be complete.
-        if (!GetTestState(ssl.get())->handshake_done) {
+        // must be complete unless we are doing early data.
+        if (!GetTestState(ssl.get())->handshake_done &&
+            !SSL_early_data_accepted(ssl.get())) {
           fprintf(stderr, "handshake was not completed after SSL_read\n");
           return false;
         }
@@ -1445,13 +2026,39 @@
 
   if (!config->is_server && !config->false_start &&
       !config->implicit_handshake &&
+      // Session tickets are sent post-handshake in TLS 1.3.
+      GetProtocolVersion(ssl.get()) < TLS1_3_VERSION &&
       GetTestState(ssl.get())->got_new_session) {
     fprintf(stderr, "new session was established after the handshake\n");
     return false;
   }
 
+  if (GetProtocolVersion(ssl.get()) >= TLS1_3_VERSION && !config->is_server) {
+    bool expect_new_session =
+        !config->expect_no_session && !config->shim_shuts_down;
+    if (expect_new_session != GetTestState(ssl.get())->got_new_session) {
+      fprintf(stderr,
+              "new session was%s cached, but we expected the opposite\n",
+              GetTestState(ssl.get())->got_new_session ? "" : " not");
+      return false;
+    }
+
+    if (expect_new_session) {
+      bool got_early_data_info =
+          GetTestState(ssl.get())->new_session->ticket_max_early_data != 0;
+      if (config->expect_early_data_info != got_early_data_info) {
+        fprintf(
+            stderr,
+            "new session did%s include ticket_early_data_info, but we expected "
+            "the opposite\n",
+            got_early_data_info ? "" : " not");
+        return false;
+      }
+    }
+  }
+
   if (out_session) {
-    out_session->reset(SSL_get1_session(ssl.get()));
+    *out_session = std::move(GetTestState(ssl.get())->new_session);
   }
 
   ret = DoShutdown(ssl.get());
@@ -1483,7 +2090,16 @@
   return true;
 }
 
+class StderrDelimiter {
+ public:
+  ~StderrDelimiter() { fprintf(stderr, "--- DONE ---\n"); }
+};
+
 int main(int argc, char **argv) {
+  // To distinguish ASan's output from ours, add a trailing message to stderr.
+  // Anything following this line will be considered an error.
+  StderrDelimiter delimiter;
+
 #if defined(OPENSSL_WINDOWS)
   /* Initialize Winsock. */
   WORD wsa_version = MAKEWORD(2, 2);
@@ -1513,24 +2129,38 @@
     return Usage(argv[0]);
   }
 
-  ScopedSSL_CTX ssl_ctx = SetupCtx(&config);
+  g_pool = CRYPTO_BUFFER_POOL_new();
+
+  // Some code treats the zero time special, so initialize the clock to a
+  // non-zero time.
+  g_clock.tv_sec = 1234;
+  g_clock.tv_usec = 1234;
+
+  bssl::UniquePtr<SSL_CTX> ssl_ctx = SetupCtx(&config);
   if (!ssl_ctx) {
     ERR_print_errors_fp(stderr);
     return 1;
   }
 
-  ScopedSSL_SESSION session;
-  if (!DoExchange(&session, ssl_ctx.get(), &config, false /* is_resume */,
-                  NULL /* session */)) {
-    ERR_print_errors_fp(stderr);
-    return 1;
-  }
+  bssl::UniquePtr<SSL_SESSION> session;
+  for (int i = 0; i < config.resume_count + 1; i++) {
+    bool is_resume = i > 0;
+    if (is_resume && !config.is_server && !session) {
+      fprintf(stderr, "No session to offer.\n");
+      return 1;
+    }
 
-  if (config.resume &&
-      !DoExchange(NULL, ssl_ctx.get(), &config, true /* is_resume */,
-                  session.get())) {
-    ERR_print_errors_fp(stderr);
-    return 1;
+    bssl::UniquePtr<SSL_SESSION> offer_session = std::move(session);
+    if (!DoExchange(&session, ssl_ctx.get(), &config, is_resume,
+                    offer_session.get())) {
+      fprintf(stderr, "Connection %d failed.\n", i + 1);
+      ERR_print_errors_fp(stderr);
+      return 1;
+    }
+
+    if (config.resumption_delay != 0) {
+      g_clock.tv_sec += config.resumption_delay;
+    }
   }
 
   return 0;
diff --git a/src/ssl/test/packeted_bio.cc b/src/ssl/test/packeted_bio.cc
index e831082..835dbfb 100644
--- a/src/ssl/test/packeted_bio.cc
+++ b/src/ssl/test/packeted_bio.cc
@@ -21,6 +21,8 @@
 
 #include <openssl/mem.h>
 
+#include "../../crypto/internal.h"
+
 
 namespace {
 
@@ -30,6 +32,27 @@
 const uint8_t kOpcodeTimeout = 'T';
 const uint8_t kOpcodeTimeoutAck = 't';
 
+struct PacketedBio {
+  explicit PacketedBio(timeval *clock_arg)
+      : clock(clock_arg) {
+    OPENSSL_memset(&timeout, 0, sizeof(timeout));
+  }
+
+  bool HasTimeout() const {
+    return timeout.tv_sec != 0 || timeout.tv_usec != 0;
+  }
+
+  timeval timeout;
+  timeval *clock;
+};
+
+PacketedBio *GetData(BIO *bio) {
+  if (bio->method != &g_packeted_bio_method) {
+    return NULL;
+  }
+  return (PacketedBio *)bio->ptr;
+}
+
 // ReadAll reads |len| bytes from |bio| into |out|. It returns 1 on success and
 // 0 or -1 on error.
 static int ReadAll(BIO *bio, uint8_t *out, size_t len) {
@@ -79,6 +102,7 @@
 }
 
 static int PacketedRead(BIO *bio, char *out, int outl) {
+  PacketedBio *data = GetData(bio);
   if (bio->next_bio == NULL) {
     return 0;
   }
@@ -94,6 +118,12 @@
   }
 
   if (opcode == kOpcodeTimeout) {
+    // The caller is required to advance any pending timeouts before continuing.
+    if (data->HasTimeout()) {
+      fprintf(stderr, "Unprocessed timeout!\n");
+      return -1;
+    }
+
     // Process the timeout.
     uint8_t buf[8];
     ret = ReadAll(bio->next_bio, buf, sizeof(buf));
@@ -102,19 +132,17 @@
       return ret;
     }
     uint64_t timeout = (static_cast<uint64_t>(buf[0]) << 56) |
-        (static_cast<uint64_t>(buf[1]) << 48) |
-        (static_cast<uint64_t>(buf[2]) << 40) |
-        (static_cast<uint64_t>(buf[3]) << 32) |
-        (static_cast<uint64_t>(buf[4]) << 24) |
-        (static_cast<uint64_t>(buf[5]) << 16) |
-        (static_cast<uint64_t>(buf[6]) << 8) |
-        static_cast<uint64_t>(buf[7]);
+                       (static_cast<uint64_t>(buf[1]) << 48) |
+                       (static_cast<uint64_t>(buf[2]) << 40) |
+                       (static_cast<uint64_t>(buf[3]) << 32) |
+                       (static_cast<uint64_t>(buf[4]) << 24) |
+                       (static_cast<uint64_t>(buf[5]) << 16) |
+                       (static_cast<uint64_t>(buf[6]) << 8) |
+                       static_cast<uint64_t>(buf[7]);
     timeout /= 1000;  // Convert nanoseconds to microseconds.
-    timeval *out_timeout = reinterpret_cast<timeval *>(bio->ptr);
-    assert(out_timeout->tv_usec == 0);
-    assert(out_timeout->tv_sec == 0);
-    out_timeout->tv_usec = timeout % 1000000;
-    out_timeout->tv_sec = timeout / 1000000;
+
+    data->timeout.tv_usec = timeout % 1000000;
+    data->timeout.tv_sec = timeout / 1000000;
 
     // Send an ACK to the peer.
     ret = BIO_write(bio->next_bio, &kOpcodeTimeoutAck, 1);
@@ -123,8 +151,7 @@
     }
     assert(ret == 1);
 
-    // Signal to the caller to retry the read, after processing the
-    // new clock.
+    // Signal to the caller to retry the read, after advancing the clock.
     BIO_set_retry_read(bio);
     return -1;
   }
@@ -143,7 +170,7 @@
   }
 
   uint32_t len = (len_bytes[0] << 24) | (len_bytes[1] << 16) |
-      (len_bytes[2] << 8) | len_bytes[3];
+                 (len_bytes[2] << 8) | len_bytes[3];
   uint8_t *buf = (uint8_t *)OPENSSL_malloc(len);
   if (buf == NULL) {
     return -1;
@@ -157,7 +184,7 @@
   if (outl > (int)len) {
     outl = len;
   }
-  memcpy(out, buf, outl);
+  OPENSSL_memcpy(out, buf, outl);
   OPENSSL_free(buf);
   return outl;
 }
@@ -166,6 +193,7 @@
   if (bio->next_bio == NULL) {
     return 0;
   }
+
   BIO_clear_retry_flags(bio);
   int ret = BIO_ctrl(bio->next_bio, cmd, num, ptr);
   BIO_copy_next_retry(bio);
@@ -182,6 +210,7 @@
     return 0;
   }
 
+  delete GetData(bio);
   bio->init = 0;
   return 1;
 }
@@ -208,11 +237,29 @@
 
 }  // namespace
 
-ScopedBIO PacketedBioCreate(timeval *out_timeout) {
-  ScopedBIO bio(BIO_new(&g_packeted_bio_method));
+bssl::UniquePtr<BIO> PacketedBioCreate(timeval *clock) {
+  bssl::UniquePtr<BIO> bio(BIO_new(&g_packeted_bio_method));
   if (!bio) {
     return nullptr;
   }
-  bio->ptr = out_timeout;
+  bio->ptr = new PacketedBio(clock);
   return bio;
 }
+
+bool PacketedBioAdvanceClock(BIO *bio) {
+  PacketedBio *data = GetData(bio);
+  if (data == nullptr) {
+    return false;
+  }
+
+  if (!data->HasTimeout()) {
+    return false;
+  }
+
+  data->clock->tv_usec += data->timeout.tv_usec;
+  data->clock->tv_sec += data->clock->tv_usec / 1000000;
+  data->clock->tv_usec %= 1000000;
+  data->clock->tv_sec += data->timeout.tv_sec;
+  OPENSSL_memset(&data->timeout, 0, sizeof(data->timeout));
+  return true;
+}
diff --git a/src/ssl/test/packeted_bio.h b/src/ssl/test/packeted_bio.h
index 75cfa13..7f07fcb 100644
--- a/src/ssl/test/packeted_bio.h
+++ b/src/ssl/test/packeted_bio.h
@@ -18,27 +18,26 @@
 #include <openssl/base.h>
 #include <openssl/bio.h>
 
-#include "../../crypto/test/scoped_types.h"
-
 #if defined(OPENSSL_WINDOWS)
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <winsock2.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
 #else
 #include <sys/time.h>
 #endif
 
 
 // PacketedBioCreate creates a filter BIO which implements a reliable in-order
-// blocking datagram socket. The resulting BIO, on |BIO_read|, may simulate a
-// timeout which sets |*out_timeout| to the timeout and fails the read.
-// |*out_timeout| must be zero on entry to |BIO_read|; it is an error to not
-// apply the timeout before the next |BIO_read|.
+// blocking datagram socket. It uses the value of |*clock| as the clock.
 //
-// Note: The read timeout simulation is intended to be used with the async BIO
-// wrapper. It doesn't simulate BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, used in DTLS's
-// blocking mode.
-ScopedBIO PacketedBioCreate(timeval *out_timeout);
+// During a |BIO_read|, the peer may signal the filter BIO to simulate a
+// timeout. The operation will fail immediately. The caller must then call
+// |PacketedBioAdvanceClock| before retrying |BIO_read|.
+bssl::UniquePtr<BIO> PacketedBioCreate(timeval *clock);
+
+// PacketedBioAdvanceClock advances |bio|'s clock and returns true if there is a
+// pending timeout. Otherwise, it returns false.
+bool PacketedBioAdvanceClock(BIO *bio);
 
 
 #endif  // HEADER_PACKETED_BIO
diff --git a/src/ssl/test/runner/alert.go b/src/ssl/test/runner/alert.go
index 541216e..652e9ee 100644
--- a/src/ssl/test/runner/alert.go
+++ b/src/ssl/test/runner/alert.go
@@ -16,12 +16,14 @@
 
 const (
 	alertCloseNotify            alert = 0
+	alertEndOfEarlyData         alert = 1
 	alertUnexpectedMessage      alert = 10
 	alertBadRecordMAC           alert = 20
 	alertDecryptionFailed       alert = 21
 	alertRecordOverflow         alert = 22
 	alertDecompressionFailure   alert = 30
 	alertHandshakeFailure       alert = 40
+	alertNoCertificate          alert = 41
 	alertBadCertificate         alert = 42
 	alertUnsupportedCertificate alert = 43
 	alertCertificateRevoked     alert = 44
@@ -35,18 +37,26 @@
 	alertProtocolVersion        alert = 70
 	alertInsufficientSecurity   alert = 71
 	alertInternalError          alert = 80
+	alertInappropriateFallback  alert = 86
 	alertUserCanceled           alert = 90
 	alertNoRenegotiation        alert = 100
+	alertMissingExtension       alert = 109
+	alertUnsupportedExtension   alert = 110
+	alertUnrecognizedName       alert = 112
+	alertUnknownPSKIdentity     alert = 115
+	alertCertificateRequired    alert = 116
 )
 
 var alertText = map[alert]string{
 	alertCloseNotify:            "close notify",
+	alertEndOfEarlyData:         "end of early data",
 	alertUnexpectedMessage:      "unexpected message",
 	alertBadRecordMAC:           "bad record MAC",
 	alertDecryptionFailed:       "decryption failed",
 	alertRecordOverflow:         "record overflow",
 	alertDecompressionFailure:   "decompression failure",
 	alertHandshakeFailure:       "handshake failure",
+	alertNoCertificate:          "no certificate",
 	alertBadCertificate:         "bad certificate",
 	alertUnsupportedCertificate: "unsupported certificate",
 	alertCertificateRevoked:     "revoked certificate",
@@ -60,8 +70,14 @@
 	alertProtocolVersion:        "protocol version not supported",
 	alertInsufficientSecurity:   "insufficient security level",
 	alertInternalError:          "internal error",
+	alertInappropriateFallback:  "inappropriate fallback",
 	alertUserCanceled:           "user canceled",
 	alertNoRenegotiation:        "no renegotiation",
+	alertMissingExtension:       "missing extension",
+	alertUnsupportedExtension:   "unsupported extension",
+	alertUnrecognizedName:       "unrecognized name",
+	alertUnknownPSKIdentity:     "unknown PSK identity",
+	alertCertificateRequired:    "certificate required",
 }
 
 func (e alert) String() string {
diff --git a/src/ssl/test/runner/cert.pem b/src/ssl/test/runner/cert.pem
index 4de4f49..c360dc7 100644
--- a/src/ssl/test/runner/cert.pem
+++ b/src/ssl/test/runner/cert.pem
@@ -1,15 +1,22 @@
 -----BEGIN CERTIFICATE-----
-MIICWDCCAcGgAwIBAgIJAPuwTC6rEJsMMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
-BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
-aWRnaXRzIFB0eSBMdGQwHhcNMTQwNDIzMjA1MDQwWhcNMTcwNDIyMjA1MDQwWjBF
-MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
-ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
-gQDYK8imMuRi/03z0K1Zi0WnvfFHvwlYeyK9Na6XJYaUoIDAtB92kWdGMdAQhLci
-HnAjkXLI6W15OoV3gA/ElRZ1xUpxTMhjP6PyY5wqT5r6y8FxbiiFKKAnHmUcrgfV
-W28tQ+0rkLGMryRtrukXOgXBv7gcrmU7G1jC2a7WqmeI8QIDAQABo1AwTjAdBgNV
-HQ4EFgQUi3XVrMsIvg4fZbf6Vr5sp3Xaha8wHwYDVR0jBBgwFoAUi3XVrMsIvg4f
-Zbf6Vr5sp3Xaha8wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQA76Hht
-ldY9avcTGSwbwoiuIqv0jTL1fHFnzy3RHMLDh+Lpvolc5DSrSJHCP5WuK0eeJXhr
-T5oQpHL9z/cCDLAKCKRa4uV0fhEdOWBqyR9p8y5jJtye72t6CuFUV5iqcpF4BH4f
-j2VNHwsSrJwkD4QUGlUtH7vwnQmyCFxZMmWAJg==
+MIIDtTCCAp2gAwIBAgIJALW2IrlaBKUhMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQwHhcNMTYwNzA5MDQzODA5WhcNMTYwODA4MDQzODA5WjBF
+MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50
+ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAugvahBkSAUF1fC49vb1bvlPrcl80kop1iLpiuYoz4Qptwy57+EWssZBc
+HprZ5BkWf6PeGZ7F5AX1PyJbGHZLqvMCvViP6pd4MFox/igESISEHEixoiXCzepB
+rhtp5UQSjHD4D4hKtgdMgVxX+LRtwgW3mnu/vBu7rzpr/DS8io99p3lqZ1Aky+aN
+lcMj6MYy8U+YFEevb/V0lRY9oqwmW7BHnXikm/vi6sjIS350U8zb/mRzYeIs2R65
+LUduTL50+UMgat9ocewI2dv8aO9Dph+8NdGtg8LFYyTTHcUxJoMr1PTOgnmET19W
+JH4PrFwk7ZE1QJQQ1L4iKmPeQistuQIDAQABo4GnMIGkMB0GA1UdDgQWBBT5m6Vv
+zYjVYHG30iBE+j2XDhUE8jB1BgNVHSMEbjBsgBT5m6VvzYjVYHG30iBE+j2XDhUE
+8qFJpEcwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNV
+BAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJALW2IrlaBKUhMAwGA1UdEwQF
+MAMBAf8wDQYJKoZIhvcNAQELBQADggEBAD7Jg68SArYWlcoHfZAB90Pmyrt5H6D8
+LRi+W2Ri1fBNxREELnezWJ2scjl4UMcsKYp4Pi950gVN+62IgrImcCNvtb5I1Cfy
+/MNNur9ffas6X334D0hYVIQTePyFk3umI+2mJQrtZZyMPIKSY/sYGQHhGGX6wGK+
+GO/og0PQk/Vu6D+GU2XRnDV0YZg1lsAsHd21XryK6fDmNkEMwbIWrts4xc7scRrG
+HWy+iMf6/7p/Ak/SIicM4XSwmlQ8pPxAZPr+E2LoVd9pMpWUwpW2UbtO5wsGTrY5
+sO45tFNN/y+jtUheB1C2ijObG/tXELaiyCdM+S/waeuv0MXtI4xnn1A=
 -----END CERTIFICATE-----
diff --git a/src/ssl/test/runner/chacha20_poly1305.go b/src/ssl/test/runner/chacha20_poly1305.go
index 3c6ad82..866f724 100644
--- a/src/ssl/test/runner/chacha20_poly1305.go
+++ b/src/ssl/test/runner/chacha20_poly1305.go
@@ -1,3 +1,17 @@
+// Copyright (c) 2016, Google Inc.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
 package runner
 
 import (
@@ -105,9 +119,6 @@
 // RFC 7539 and draft-agl-tls-chacha20poly1305-04.
 type chaCha20Poly1305 struct {
 	key [32]byte
-	// oldMode, if true, indicates that the draft spec should be
-	// implemented rather than the final, RFC version.
-	oldMode bool
 }
 
 func newChaCha20Poly1305(key []byte) (cipher.AEAD, error) {
@@ -119,23 +130,8 @@
 	return aead, nil
 }
 
-func newChaCha20Poly1305Old(key []byte) (cipher.AEAD, error) {
-	if len(key) != 32 {
-		return nil, errors.New("bad key length")
-	}
-	aead := &chaCha20Poly1305{
-		oldMode: true,
-	}
-	copy(aead.key[:], key)
-	return aead, nil
-}
-
 func (c *chaCha20Poly1305) NonceSize() int {
-	if c.oldMode {
-		return 8
-	} else {
-		return 12
-	}
+	return 12
 }
 
 func (c *chaCha20Poly1305) Overhead() int { return 16 }
@@ -162,21 +158,6 @@
 	poly1305.Sum(tag, input, &poly1305Key)
 }
 
-func (c *chaCha20Poly1305) poly1305Old(tag *[16]byte, nonce, ciphertext, additionalData []byte) {
-	input := make([]byte, 0, len(additionalData)+8+len(ciphertext)+8)
-	input = append(input, additionalData...)
-	input, out := sliceForAppend(input, 8)
-	binary.LittleEndian.PutUint64(out, uint64(len(additionalData)))
-	input = append(input, ciphertext...)
-	input, out = sliceForAppend(input, 8)
-	binary.LittleEndian.PutUint64(out, uint64(len(ciphertext)))
-
-	var poly1305Key [32]byte
-	chaCha20(poly1305Key[:], poly1305Key[:], c.key[:], nonce, 0)
-
-	poly1305.Sum(tag, input, &poly1305Key)
-}
-
 func (c *chaCha20Poly1305) Seal(dst, nonce, plaintext, additionalData []byte) []byte {
 	if len(nonce) != c.NonceSize() {
 		panic("Bad nonce length")
@@ -186,11 +167,7 @@
 	chaCha20(out[:len(plaintext)], plaintext, c.key[:], nonce, 1)
 
 	var tag [16]byte
-	if c.oldMode {
-		c.poly1305Old(&tag, nonce, out[:len(plaintext)], additionalData)
-	} else {
-		c.poly1305(&tag, nonce, out[:len(plaintext)], additionalData)
-	}
+	c.poly1305(&tag, nonce, out[:len(plaintext)], additionalData)
 	copy(out[len(plaintext):], tag[:])
 
 	return ret
@@ -206,11 +183,7 @@
 	plaintextLen := len(ciphertext) - 16
 
 	var tag [16]byte
-	if c.oldMode {
-		c.poly1305Old(&tag, nonce, ciphertext[:plaintextLen], additionalData)
-	} else {
-		c.poly1305(&tag, nonce, ciphertext[:plaintextLen], additionalData)
-	}
+	c.poly1305(&tag, nonce, ciphertext[:plaintextLen], additionalData)
 	if subtle.ConstantTimeCompare(tag[:], ciphertext[plaintextLen:]) != 1 {
 		return nil, errors.New("chacha20: message authentication failed")
 	}
diff --git a/src/ssl/test/runner/chacha20_poly1305_test.go b/src/ssl/test/runner/chacha20_poly1305_test.go
index 4d19b8c..38c4b70 100644
--- a/src/ssl/test/runner/chacha20_poly1305_test.go
+++ b/src/ssl/test/runner/chacha20_poly1305_test.go
@@ -1,3 +1,17 @@
+// Copyright (c) 2016, Google Inc.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
 package runner
 
 import (
@@ -74,38 +88,6 @@
 	return out
 }
 
-// See draft-agl-tls-chacha20poly1305-04, section 7.
-func TestChaCha20Poly1305Old(t *testing.T) {
-	key := decodeHexOrPanic("4290bcb154173531f314af57f3be3b5006da371ece272afa1b5dbdd1100a1007")
-	input := decodeHexOrPanic("86d09974840bded2a5ca")
-	nonce := decodeHexOrPanic("cd7cf67be39c794a")
-	ad := decodeHexOrPanic("87e229d4500845a079c0")
-	output := decodeHexOrPanic("e3e446f7ede9a19b62a4677dabf4e3d24b876bb284753896e1d6")
-
-	aead, err := newChaCha20Poly1305Old(key)
-	if err != nil {
-		t.Fatal(err)
-	}
-
-	out, err := aead.Open(nil, nonce, output, ad)
-	if err != nil {
-		t.Errorf("Open failed: %s", err)
-	} else if !bytes.Equal(out, input) {
-		t.Errorf("Open gave %x, wanted %x", out, input)
-	}
-
-	out = aead.Seal(nil, nonce, input, ad)
-	if !bytes.Equal(out, output) {
-		t.Errorf("Open gave %x, wanted %x", out, output)
-	}
-
-	out[0]++
-	_, err = aead.Open(nil, nonce, out, ad)
-	if err == nil {
-		t.Errorf("Open on malformed data unexpectedly succeeded")
-	}
-}
-
 var chaCha20Poly1305TestVectors = []struct {
 	key, input, nonce, ad, output string
 }{
diff --git a/src/ssl/test/runner/cipher_suites.go b/src/ssl/test/runner/cipher_suites.go
index bfd31a5..3b2298e 100644
--- a/src/ssl/test/runner/cipher_suites.go
+++ b/src/ssl/test/runner/cipher_suites.go
@@ -5,6 +5,7 @@
 package runner
 
 import (
+	"crypto"
 	"crypto/aes"
 	"crypto/cipher"
 	"crypto/des"
@@ -35,6 +36,10 @@
 	// ServerKeyExchange message.
 	processServerKeyExchange(*Config, *clientHelloMsg, *serverHelloMsg, *x509.Certificate, *serverKeyExchangeMsg) error
 	generateClientKeyExchange(*Config, *clientHelloMsg, *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error)
+
+	// peerSignatureAlgorithm returns the signature algorithm used by the
+	// peer, or zero if not applicable.
+	peerSignatureAlgorithm() signatureAlgorithm
 }
 
 const (
@@ -43,14 +48,19 @@
 	// client indicates that it supports ECC with a curve and point format
 	// that we're happy with.
 	suiteECDHE = 1 << iota
+	// suiteDHE indicates that the cipher suite involves Diffie-Hellman.
+	suiteDHE
 	// suiteECDSA indicates that the cipher suite involves an ECDSA
 	// signature and therefore may only be selected when the server's
 	// certificate is ECDSA. If this is not set then the cipher suite is
 	// RSA based.
 	suiteECDSA
 	// suiteTLS12 indicates that the cipher suite should only be advertised
-	// and accepted when using TLS 1.2.
+	// and accepted when using TLS 1.2 or greater.
 	suiteTLS12
+	// suiteTLS13 indicates that the cipher suite can be used with TLS 1.3.
+	// Cipher suites lacking this flag may not be used with TLS 1.3.
+	suiteTLS13
 	// suiteSHA384 indicates that the cipher suite uses SHA384 as the
 	// handshake hash.
 	suiteSHA384
@@ -74,60 +84,91 @@
 	// the lengths, in bytes, of the key material needed for each component.
 	keyLen int
 	macLen int
-	ivLen  int
+	ivLen  func(version uint16) int
 	ka     func(version uint16) keyAgreement
 	// flags is a bitmask of the suite* values, above.
 	flags  int
 	cipher func(key, iv []byte, isRead bool) interface{}
 	mac    func(version uint16, macKey []byte) macFunction
-	aead   func(key, fixedNonce []byte) *tlsAead
+	aead   func(version uint16, key, fixedNonce []byte) *tlsAead
+}
+
+func (cs cipherSuite) hash() crypto.Hash {
+	if cs.flags&suiteSHA384 != 0 {
+		return crypto.SHA384
+	}
+	return crypto.SHA256
 }
 
 var cipherSuites = []*cipherSuite{
 	// Ciphersuite order is chosen so that ECDHE comes before plain RSA
 	// and RC4 comes before AES (because of the Lucky13 attack).
-	{TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 32, 0, 12, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, nil, nil, aeadCHACHA20POLY1305},
-	{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 32, 0, 12, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadCHACHA20POLY1305},
-	{TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256_OLD, 32, 0, 0, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, nil, nil, aeadCHACHA20POLY1305Old},
-	{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256_OLD, 32, 0, 0, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadCHACHA20POLY1305Old},
-	{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadAESGCM},
-	{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, nil, nil, aeadAESGCM},
-	{TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
-	{TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
-	{TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheRSAKA, suiteECDHE | suiteNoDTLS, cipherRC4, macSHA1, nil},
-	{TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 16, 20, 0, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteNoDTLS, cipherRC4, macSHA1, nil},
-	{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheRSAKA, suiteECDHE | suiteTLS12, cipherAES, macSHA256, nil},
-	{TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, cipherAES, macSHA256, nil},
-	{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
-	{TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil},
-	{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, 32, 48, 16, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteSHA384, cipherAES, macSHA384, nil},
-	{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, 32, 48, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12 | suiteSHA384, cipherAES, macSHA384, nil},
-	{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
-	{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil},
-	{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, dheRSAKA, suiteTLS12, nil, nil, aeadAESGCM},
-	{TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, dheRSAKA, suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
-	{TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, dheRSAKA, suiteTLS12, cipherAES, macSHA256, nil},
-	{TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, 32, 32, 16, dheRSAKA, suiteTLS12, cipherAES, macSHA256, nil},
-	{TLS_DHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, dheRSAKA, 0, cipherAES, macSHA1, nil},
-	{TLS_DHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, dheRSAKA, 0, cipherAES, macSHA1, nil},
-	{TLS_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, rsaKA, suiteTLS12, nil, nil, aeadAESGCM},
-	{TLS_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, rsaKA, suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
-	{TLS_RSA_WITH_RC4_128_SHA, 16, 20, 0, rsaKA, suiteNoDTLS, cipherRC4, macSHA1, nil},
-	{TLS_RSA_WITH_RC4_128_MD5, 16, 16, 0, rsaKA, suiteNoDTLS, cipherRC4, macMD5, nil},
-	{TLS_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, rsaKA, suiteTLS12, cipherAES, macSHA256, nil},
-	{TLS_RSA_WITH_AES_256_CBC_SHA256, 32, 32, 16, rsaKA, suiteTLS12, cipherAES, macSHA256, nil},
-	{TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil},
-	{TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, rsaKA, 0, cipherAES, macSHA1, nil},
-	{TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, ecdheRSAKA, suiteECDHE, cipher3DES, macSHA1, nil},
-	{TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, dheRSAKA, 0, cipher3DES, macSHA1, nil},
-	{TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, 8, rsaKA, 0, cipher3DES, macSHA1, nil},
-	{TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, 32, 0, 12, ecdhePSKKA, suiteECDHE | suitePSK | suiteTLS12, nil, nil, aeadCHACHA20POLY1305},
-	{TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, 16, 20, 16, ecdhePSKKA, suiteECDHE | suitePSK, cipherAES, macSHA1, nil},
-	{TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdhePSKKA, suiteECDHE | suitePSK, cipherAES, macSHA1, nil},
-	{TLS_PSK_WITH_RC4_128_SHA, 16, 20, 0, pskKA, suiteNoDTLS | suitePSK, cipherRC4, macSHA1, nil},
-	{TLS_PSK_WITH_AES_128_CBC_SHA, 16, 20, 16, pskKA, suitePSK, cipherAES, macSHA1, nil},
-	{TLS_PSK_WITH_AES_256_CBC_SHA, 32, 20, 16, pskKA, suitePSK, cipherAES, macSHA1, nil},
-	{TLS_RSA_WITH_NULL_SHA, 0, 20, 0, rsaKA, suiteNoDTLS, cipherNull, macSHA1, nil},
+	{TLS_CHACHA20_POLY1305_SHA256, 32, 0, ivLenChaCha20Poly1305, nil, suiteTLS13, nil, nil, aeadCHACHA20POLY1305},
+	{TLS_AES_128_GCM_SHA256, 16, 0, ivLenAESGCM, nil, suiteTLS13, nil, nil, aeadAESGCM},
+	{TLS_AES_256_GCM_SHA384, 32, 0, ivLenAESGCM, nil, suiteTLS13 | suiteSHA384, nil, nil, aeadAESGCM},
+	{TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 32, 0, ivLenChaCha20Poly1305, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, nil, nil, aeadCHACHA20POLY1305},
+	{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, 32, 0, ivLenChaCha20Poly1305, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadCHACHA20POLY1305},
+	{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, ivLenAESGCM, ecdheRSAKA, suiteECDHE | suiteTLS12, nil, nil, aeadAESGCM},
+	{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, 16, 0, ivLenAESGCM, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, nil, nil, aeadAESGCM},
+	{TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, ivLenAESGCM, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
+	{TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, 32, 0, ivLenAESGCM, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
+	{TLS_ECDHE_RSA_WITH_RC4_128_SHA, 16, 20, noIV, ecdheRSAKA, suiteECDHE | suiteNoDTLS, cipherRC4, macSHA1, nil},
+	{TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, 16, 20, noIV, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteNoDTLS, cipherRC4, macSHA1, nil},
+	{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, 16, 32, ivLenAES, ecdheRSAKA, suiteECDHE | suiteTLS12, cipherAES, macSHA256, nil},
+	{TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, 16, 32, ivLenAES, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12, cipherAES, macSHA256, nil},
+	{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, ivLenAES, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
+	{TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, 16, 20, ivLenAES, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil},
+	{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, 32, 48, ivLenAES, ecdheRSAKA, suiteECDHE | suiteTLS12 | suiteSHA384, cipherAES, macSHA384, nil},
+	{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, 32, 48, ivLenAES, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12 | suiteSHA384, cipherAES, macSHA384, nil},
+	{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, ivLenAES, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
+	{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 32, 20, ivLenAES, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil},
+	{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, ivLenAESGCM, dheRSAKA, suiteTLS12 | suiteDHE, nil, nil, aeadAESGCM},
+	{TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, ivLenAESGCM, dheRSAKA, suiteTLS12 | suiteSHA384 | suiteDHE, nil, nil, aeadAESGCM},
+	{TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, 16, 32, ivLenAES, dheRSAKA, suiteTLS12 | suiteDHE, cipherAES, macSHA256, nil},
+	{TLS_DHE_RSA_WITH_AES_256_CBC_SHA256, 32, 32, ivLenAES, dheRSAKA, suiteTLS12 | suiteDHE, cipherAES, macSHA256, nil},
+	{TLS_DHE_RSA_WITH_AES_128_CBC_SHA, 16, 20, ivLenAES, dheRSAKA, suiteDHE, cipherAES, macSHA1, nil},
+	{TLS_DHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, ivLenAES, dheRSAKA, suiteDHE, cipherAES, macSHA1, nil},
+	{TLS_RSA_WITH_AES_128_GCM_SHA256, 16, 0, ivLenAESGCM, rsaKA, suiteTLS12, nil, nil, aeadAESGCM},
+	{TLS_RSA_WITH_AES_256_GCM_SHA384, 32, 0, ivLenAESGCM, rsaKA, suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
+	{TLS_RSA_WITH_RC4_128_SHA, 16, 20, noIV, rsaKA, suiteNoDTLS, cipherRC4, macSHA1, nil},
+	{TLS_RSA_WITH_RC4_128_MD5, 16, 16, noIV, rsaKA, suiteNoDTLS, cipherRC4, macMD5, nil},
+	{TLS_RSA_WITH_AES_128_CBC_SHA256, 16, 32, ivLenAES, rsaKA, suiteTLS12, cipherAES, macSHA256, nil},
+	{TLS_RSA_WITH_AES_256_CBC_SHA256, 32, 32, ivLenAES, rsaKA, suiteTLS12, cipherAES, macSHA256, nil},
+	{TLS_RSA_WITH_AES_128_CBC_SHA, 16, 20, ivLenAES, rsaKA, 0, cipherAES, macSHA1, nil},
+	{TLS_RSA_WITH_AES_256_CBC_SHA, 32, 20, ivLenAES, rsaKA, 0, cipherAES, macSHA1, nil},
+	{TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, ivLen3DES, ecdheRSAKA, suiteECDHE, cipher3DES, macSHA1, nil},
+	{TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, ivLen3DES, dheRSAKA, suiteDHE, cipher3DES, macSHA1, nil},
+	{TLS_RSA_WITH_3DES_EDE_CBC_SHA, 24, 20, ivLen3DES, rsaKA, 0, cipher3DES, macSHA1, nil},
+	{TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, 32, 0, ivLenChaCha20Poly1305, ecdhePSKKA, suiteECDHE | suitePSK | suiteTLS12, nil, nil, aeadCHACHA20POLY1305},
+	{TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, 16, 20, ivLenAES, ecdhePSKKA, suiteECDHE | suitePSK, cipherAES, macSHA1, nil},
+	{TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA, 32, 20, ivLenAES, ecdhePSKKA, suiteECDHE | suitePSK, cipherAES, macSHA1, nil},
+	{TLS_PSK_WITH_RC4_128_SHA, 16, 20, noIV, pskKA, suiteNoDTLS | suitePSK, cipherRC4, macSHA1, nil},
+	{TLS_PSK_WITH_AES_128_CBC_SHA, 16, 20, ivLenAES, pskKA, suitePSK, cipherAES, macSHA1, nil},
+	{TLS_PSK_WITH_AES_256_CBC_SHA, 32, 20, ivLenAES, pskKA, suitePSK, cipherAES, macSHA1, nil},
+	{TLS_RSA_WITH_NULL_SHA, 0, 20, noIV, rsaKA, suiteNoDTLS, cipherNull, macSHA1, nil},
+}
+
+func noIV(vers uint16) int {
+	return 0
+}
+
+func ivLenChaCha20Poly1305(vers uint16) int {
+	return 12
+}
+
+func ivLenAESGCM(vers uint16) int {
+	if vers >= VersionTLS13 {
+		return 12
+	}
+	return 4
+}
+
+func ivLenAES(vers uint16) int {
+	return 16
+}
+
+func ivLen3DES(vers uint16) int {
+	return 8
 }
 
 type nullCipher struct{}
@@ -234,7 +275,7 @@
 	return f.aead.Open(out, f.openNonce, plaintext, additionalData)
 }
 
-func aeadAESGCM(key, fixedNonce []byte) *tlsAead {
+func aeadAESGCM(version uint16, key, fixedNonce []byte) *tlsAead {
 	aes, err := aes.NewCipher(key)
 	if err != nil {
 		panic(err)
@@ -248,15 +289,11 @@
 	copy(nonce1, fixedNonce)
 	copy(nonce2, fixedNonce)
 
-	return &tlsAead{&fixedNonceAEAD{nonce1, nonce2, aead}, true}
-}
-
-func aeadCHACHA20POLY1305Old(key, fixedNonce []byte) *tlsAead {
-	aead, err := newChaCha20Poly1305Old(key)
-	if err != nil {
-		panic(err)
+	if version >= VersionTLS13 {
+		return &tlsAead{&xorNonceAEAD{nonce1, nonce2, aead}, false}
 	}
-	return &tlsAead{aead, false}
+
+	return &tlsAead{&fixedNonceAEAD{nonce1, nonce2, aead}, true}
 }
 
 func xorSlice(out, in []byte) {
@@ -292,7 +329,7 @@
 	return ret, err
 }
 
-func aeadCHACHA20POLY1305(key, fixedNonce []byte) *tlsAead {
+func aeadCHACHA20POLY1305(version uint16, key, fixedNonce []byte) *tlsAead {
 	aead, err := newChaCha20Poly1305(key)
 	if err != nil {
 		panic(err)
@@ -367,7 +404,7 @@
 func ecdheECDSAKA(version uint16) keyAgreement {
 	return &ecdheKeyAgreement{
 		auth: &signedKeyAgreement{
-			sigType: signatureECDSA,
+			keyType: keyTypeECDSA,
 			version: version,
 		},
 	}
@@ -376,7 +413,7 @@
 func ecdheRSAKA(version uint16) keyAgreement {
 	return &ecdheKeyAgreement{
 		auth: &signedKeyAgreement{
-			sigType: signatureRSA,
+			keyType: keyTypeRSA,
 			version: version,
 		},
 	}
@@ -385,7 +422,7 @@
 func dheRSAKA(version uint16) keyAgreement {
 	return &dheKeyAgreement{
 		auth: &signedKeyAgreement{
-			sigType: signatureRSA,
+			keyType: keyTypeRSA,
 			version: version,
 		},
 	}
@@ -410,12 +447,16 @@
 func mutualCipherSuite(have []uint16, want uint16) *cipherSuite {
 	for _, id := range have {
 		if id == want {
-			for _, suite := range cipherSuites {
-				if suite.id == want {
-					return suite
-				}
-			}
-			return nil
+			return cipherSuiteFromID(id)
+		}
+	}
+	return nil
+}
+
+func cipherSuiteFromID(id uint16) *cipherSuite {
+	for _, suite := range cipherSuites {
+		if suite.id == id {
+			return suite
 		}
 	}
 	return nil
@@ -470,6 +511,7 @@
 
 // Additional cipher suite IDs, not IANA-assigned.
 const (
-	TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256_OLD   uint16 = 0xcc13
-	TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256_OLD uint16 = 0xcc14
+	TLS_AES_128_GCM_SHA256       uint16 = 0x1301
+	TLS_AES_256_GCM_SHA384       uint16 = 0x1302
+	TLS_CHACHA20_POLY1305_SHA256 uint16 = 0x1303
 )
diff --git a/src/ssl/test/runner/common.go b/src/ssl/test/runner/common.go
index db3c675..95dcbd0 100644
--- a/src/ssl/test/runner/common.go
+++ b/src/ssl/test/runner/common.go
@@ -23,8 +23,12 @@
 	VersionTLS10 = 0x0301
 	VersionTLS11 = 0x0302
 	VersionTLS12 = 0x0303
+	VersionTLS13 = 0x0304
 )
 
+// A draft version of TLS 1.3 that is sent over the wire for the current draft.
+const tls13DraftVersion = 0x7f12
+
 const (
 	maxPlaintext        = 16384        // maximum plaintext payload length
 	maxCiphertext       = 16384 + 2048 // maximum ciphertext payload length
@@ -33,7 +37,7 @@
 	maxHandshake        = 65536 // maximum handshake we support (protocol max is 16 MB)
 
 	minVersion = VersionSSL30
-	maxVersion = VersionTLS12
+	maxVersion = VersionTLS13
 )
 
 // TLS record types.
@@ -53,6 +57,8 @@
 	typeServerHello         uint8 = 2
 	typeHelloVerifyRequest  uint8 = 3
 	typeNewSessionTicket    uint8 = 4
+	typeHelloRetryRequest   uint8 = 6 // draft-ietf-tls-tls13-16
+	typeEncryptedExtensions uint8 = 8 // draft-ietf-tls-tls13-16
 	typeCertificate         uint8 = 11
 	typeServerKeyExchange   uint8 = 12
 	typeCertificateRequest  uint8 = 13
@@ -61,8 +67,9 @@
 	typeClientKeyExchange   uint8 = 16
 	typeFinished            uint8 = 20
 	typeCertificateStatus   uint8 = 22
+	typeKeyUpdate           uint8 = 24  // draft-ietf-tls-tls13-16
 	typeNextProtocol        uint8 = 67  // Not IANA assigned
-	typeEncryptedExtensions uint8 = 203 // Not IANA assigned
+	typeChannelID           uint8 = 203 // Not IANA assigned
 )
 
 // TLS compression types.
@@ -82,6 +89,13 @@
 	extensionSignedCertificateTimestamp uint16 = 18
 	extensionExtendedMasterSecret       uint16 = 23
 	extensionSessionTicket              uint16 = 35
+	extensionKeyShare                   uint16 = 40    // draft-ietf-tls-tls13-16
+	extensionPreSharedKey               uint16 = 41    // draft-ietf-tls-tls13-16
+	extensionEarlyData                  uint16 = 42    // draft-ietf-tls-tls13-16
+	extensionSupportedVersions          uint16 = 43    // draft-ietf-tls-tls13-16
+	extensionCookie                     uint16 = 44    // draft-ietf-tls-tls13-16
+	extensionPSKKeyExchangeModes        uint16 = 45    // draft-ietf-tls-tls13-18
+	extensionTicketEarlyDataInfo        uint16 = 46    // draft-ietf-tls-tls13-18
 	extensionCustom                     uint16 = 1234  // not IANA assigned
 	extensionNextProtoNeg               uint16 = 13172 // not IANA assigned
 	extensionRenegotiationInfo          uint16 = 0xff01
@@ -108,7 +122,8 @@
 // TLS Elliptic Curve Point Formats
 // http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-9
 const (
-	pointFormatUncompressed uint8 = 0
+	pointFormatUncompressed    uint8 = 0
+	pointFormatCompressedPrime uint8 = 1
 )
 
 // TLS CertificateStatusType (RFC 3546)
@@ -131,43 +146,44 @@
 	// Rest of these are reserved by the TLS spec
 )
 
-// Hash functions for TLS 1.2 (See RFC 5246, section A.4.1)
+// signatureAlgorithm corresponds to a SignatureScheme value from TLS 1.3. Note
+// that TLS 1.3 names the production 'SignatureScheme' to avoid colliding with
+// TLS 1.2's SignatureAlgorithm but otherwise refers to them as 'signature
+// algorithms' throughout. We match the latter.
+type signatureAlgorithm uint16
+
 const (
-	hashMD5    uint8 = 1
-	hashSHA1   uint8 = 2
-	hashSHA224 uint8 = 3
-	hashSHA256 uint8 = 4
-	hashSHA384 uint8 = 5
-	hashSHA512 uint8 = 6
+	// RSASSA-PKCS1-v1_5 algorithms
+	signatureRSAPKCS1WithMD5    signatureAlgorithm = 0x0101
+	signatureRSAPKCS1WithSHA1   signatureAlgorithm = 0x0201
+	signatureRSAPKCS1WithSHA256 signatureAlgorithm = 0x0401
+	signatureRSAPKCS1WithSHA384 signatureAlgorithm = 0x0501
+	signatureRSAPKCS1WithSHA512 signatureAlgorithm = 0x0601
+
+	// ECDSA algorithms
+	signatureECDSAWithSHA1          signatureAlgorithm = 0x0203
+	signatureECDSAWithP256AndSHA256 signatureAlgorithm = 0x0403
+	signatureECDSAWithP384AndSHA384 signatureAlgorithm = 0x0503
+	signatureECDSAWithP521AndSHA512 signatureAlgorithm = 0x0603
+
+	// RSASSA-PSS algorithms
+	signatureRSAPSSWithSHA256 signatureAlgorithm = 0x0804
+	signatureRSAPSSWithSHA384 signatureAlgorithm = 0x0805
+	signatureRSAPSSWithSHA512 signatureAlgorithm = 0x0806
+
+	// EdDSA algorithms
+	signatureEd25519 signatureAlgorithm = 0x0807
+	signatureEd448   signatureAlgorithm = 0x0808
 )
 
-// Signature algorithms for TLS 1.2 (See RFC 5246, section A.4.1)
-const (
-	signatureRSA   uint8 = 1
-	signatureECDSA uint8 = 3
-)
-
-// signatureAndHash mirrors the TLS 1.2, SignatureAndHashAlgorithm struct. See
-// RFC 5246, section A.4.1.
-type signatureAndHash struct {
-	signature, hash uint8
-}
-
-// supportedSKXSignatureAlgorithms contains the signature and hash algorithms
-// that the code advertises as supported in a TLS 1.2 ClientHello.
-var supportedSKXSignatureAlgorithms = []signatureAndHash{
-	{signatureRSA, hashSHA256},
-	{signatureECDSA, hashSHA256},
-	{signatureRSA, hashSHA1},
-	{signatureECDSA, hashSHA1},
-}
-
-// supportedClientCertSignatureAlgorithms contains the signature and hash
-// algorithms that the code advertises as supported in a TLS 1.2
-// CertificateRequest.
-var supportedClientCertSignatureAlgorithms = []signatureAndHash{
-	{signatureRSA, hashSHA256},
-	{signatureECDSA, hashSHA256},
+// supportedSignatureAlgorithms contains the default supported signature
+// algorithms.
+var supportedSignatureAlgorithms = []signatureAlgorithm{
+	signatureRSAPSSWithSHA256,
+	signatureRSAPKCS1WithSHA256,
+	signatureECDSAWithP256AndSHA256,
+	signatureRSAPKCS1WithSHA1,
+	signatureECDSAWithSHA1,
 }
 
 // SRTP protection profiles (See RFC 5764, section 4.1.2)
@@ -176,6 +192,18 @@
 	SRTP_AES128_CM_HMAC_SHA1_32        = 0x0002
 )
 
+// PskKeyExchangeMode values (see draft-ietf-tls-tls13-16)
+const (
+	pskKEMode    = 0
+	pskDHEKEMode = 1
+)
+
+// KeyUpdateRequest values (see draft-ietf-tls-tls13-16, section 4.5.3)
+const (
+	keyUpdateNotRequested = 0
+	keyUpdateRequested    = 1
+)
+
 // ConnectionState records basic TLS details about the connection.
 type ConnectionState struct {
 	Version                    uint16                // TLS version used by the connection (e.g. VersionTLS12)
@@ -192,7 +220,8 @@
 	SRTPProtectionProfile      uint16                // the negotiated DTLS-SRTP protection profile
 	TLSUnique                  []byte                // the tls-unique channel binding
 	SCTList                    []byte                // signed certificate timestamp list
-	ClientCertSignatureHash    uint8                 // TLS id of the hash used by the client to sign the handshake
+	PeerSignatureAlgorithm     signatureAlgorithm    // algorithm used by the peer in the handshake
+	CurveID                    CurveID               // the curve used in ECDHE
 }
 
 // ClientAuthType declares the policy the server will follow for
@@ -220,6 +249,11 @@
 	extendedMasterSecret bool                // Whether an extended master secret was used to generate the session
 	sctList              []byte
 	ocspResponse         []byte
+	earlyALPN            string
+	ticketCreationTime   time.Time
+	ticketExpiration     time.Time
+	ticketAgeAdd         uint32
+	maxEarlyDataSize     uint32
 }
 
 // ClientSessionCache is a cache of ClientSessionState objects that can be used
@@ -356,6 +390,12 @@
 	// be used.
 	CurvePreferences []CurveID
 
+	// DefaultCurves contains the elliptic curves for which public values will
+	// be sent in the ClientHello's KeyShare extension. If this value is nil,
+	// all supported curves will have public values sent. This field is ignored
+	// on servers.
+	DefaultCurves []CurveID
+
 	// ChannelID contains the ECDSA key for the client to use as
 	// its TLS Channel ID.
 	ChannelID *ecdsa.PrivateKey
@@ -373,14 +413,24 @@
 	// with the PSK cipher suites.
 	PreSharedKeyIdentity string
 
+	// MaxEarlyDataSize controls the maximum number of bytes that the
+	// server will accept in early data and advertise in a
+	// NewSessionTicketMsg. If 0, no early data will be accepted and
+	// the TicketEarlyDataInfo extension in the NewSessionTicketMsg
+	// will be omitted.
+	MaxEarlyDataSize uint32
+
 	// SRTPProtectionProfiles, if not nil, is the list of SRTP
 	// protection profiles to offer in DTLS-SRTP.
 	SRTPProtectionProfiles []uint16
 
-	// SignatureAndHashes, if not nil, overrides the default set of
-	// supported signature and hash algorithms to advertise in
-	// CertificateRequest.
-	SignatureAndHashes []signatureAndHash
+	// SignSignatureAlgorithms, if not nil, overrides the default set of
+	// supported signature algorithms to sign with.
+	SignSignatureAlgorithms []signatureAlgorithm
+
+	// VerifySignatureAlgorithms, if not nil, overrides the default set of
+	// supported signature algorithms that are accepted.
+	VerifySignatureAlgorithms []signatureAlgorithm
 
 	// Bugs specifies optional misbehaviour to be used for testing other
 	// implementations.
@@ -412,17 +462,18 @@
 )
 
 type ProtocolBugs struct {
-	// InvalidSKXSignature specifies that the signature in a
-	// ServerKeyExchange message should be invalid.
-	InvalidSKXSignature bool
+	// InvalidSignature specifies that the signature in a ServerKeyExchange
+	// or CertificateVerify message should be invalid.
+	InvalidSignature bool
 
-	// InvalidCertVerifySignature specifies that the signature in a
-	// CertificateVerify message should be invalid.
-	InvalidCertVerifySignature bool
+	// SendCurve, if non-zero, causes the server to send the specified curve
+	// ID in ServerKeyExchange (TLS 1.2) or ServerHello (TLS 1.3) rather
+	// than the negotiated one.
+	SendCurve CurveID
 
-	// InvalidSKXCurve causes the curve ID in the ServerKeyExchange message
-	// to be wrong.
-	InvalidSKXCurve bool
+	// InvalidECDHPoint, if true, causes the ECC points in
+	// ServerKeyExchange or ClientKeyExchange messages to be invalid.
+	InvalidECDHPoint bool
 
 	// BadECDSAR controls ways in which the 'r' value of an ECDSA signature
 	// can be invalid.
@@ -469,6 +520,10 @@
 	// NewSessionTicket message despite promising to in ServerHello.
 	SkipNewSessionTicket bool
 
+	// SkipClientCertificate causes the client to skip the Certificate
+	// message.
+	SkipClientCertificate bool
+
 	// SkipChangeCipherSpec causes the implementation to skip
 	// sending the ChangeCipherSpec message (and adjusting cipher
 	// state accordingly for the Finished message).
@@ -478,17 +533,40 @@
 	// message.
 	SkipFinished bool
 
+	// SkipEndOfEarlyData causes the implementation to skip the
+	// end_of_early_data alert.
+	SkipEndOfEarlyData bool
+
 	// EarlyChangeCipherSpec causes the client to send an early
 	// ChangeCipherSpec message before the ClientKeyExchange. A value of
 	// zero disables this behavior. One and two configure variants for 0.9.8
 	// and 1.0.1 modes, respectively.
 	EarlyChangeCipherSpec int
 
+	// StrayChangeCipherSpec causes every pre-ChangeCipherSpec handshake
+	// message in DTLS to be prefaced by stray ChangeCipherSpec record. This
+	// may be used to test DTLS's handling of reordered ChangeCipherSpec.
+	StrayChangeCipherSpec bool
+
 	// FragmentAcrossChangeCipherSpec causes the implementation to fragment
 	// the Finished (or NextProto) message around the ChangeCipherSpec
 	// messages.
 	FragmentAcrossChangeCipherSpec bool
 
+	// SendUnencryptedFinished, if true, causes the Finished message to be
+	// send unencrypted before ChangeCipherSpec rather than after it.
+	SendUnencryptedFinished bool
+
+	// PartialEncryptedExtensionsWithServerHello, if true, causes the TLS
+	// 1.3 server to send part of EncryptedExtensions unencrypted
+	// in the same record as ServerHello.
+	PartialEncryptedExtensionsWithServerHello bool
+
+	// PartialClientFinishedWithClientHello, if true, causes the TLS 1.3
+	// client to send part of Finished unencrypted in the same record as
+	// ClientHello.
+	PartialClientFinishedWithClientHello bool
+
 	// SendV2ClientHello causes the client to send a V2ClientHello
 	// instead of a normal ClientHello.
 	SendV2ClientHello bool
@@ -517,6 +595,10 @@
 	// two records.
 	FragmentAlert bool
 
+	// DoubleAlert will cause all alerts to be sent as two copies packed
+	// within one record.
+	DoubleAlert bool
+
 	// SendSpuriousAlert, if non-zero, will cause an spurious, unwanted
 	// alert to be sent.
 	SendSpuriousAlert alert
@@ -529,10 +611,27 @@
 	// send a NewSessionTicket message during an abbreviated handshake.
 	RenewTicketOnResume bool
 
-	// SendClientVersion, if non-zero, causes the client to send a different
-	// TLS version in the ClientHello than the maximum supported version.
+	// SendClientVersion, if non-zero, causes the client to send the
+	// specified value in the ClientHello version field.
 	SendClientVersion uint16
 
+	// OmitSupportedVersions, if true, causes the client to omit the
+	// supported versions extension.
+	OmitSupportedVersions bool
+
+	// SendSupportedVersions, if non-empty, causes the client to send a
+	// supported versions extension with the values from array.
+	SendSupportedVersions []uint16
+
+	// NegotiateVersion, if non-zero, causes the server to negotiate the
+	// specifed TLS version rather than the version supported by either
+	// peer.
+	NegotiateVersion uint16
+
+	// NegotiateVersionOnRenego, if non-zero, causes the server to negotiate
+	// the specified TLS version on renegotiation rather than retaining it.
+	NegotiateVersionOnRenego uint16
+
 	// ExpectFalseStart causes the server to, on full handshakes,
 	// expect the peer to False Start; the server Finished message
 	// isn't sent until we receive an application data record
@@ -546,10 +645,6 @@
 	// closed the connection) before or after sending app data.
 	AlertBeforeFalseStartTest alert
 
-	// SkipCipherVersionCheck causes the server to negotiate
-	// TLS 1.2 ciphers in earlier versions of TLS.
-	SkipCipherVersionCheck bool
-
 	// ExpectServerName, if not empty, is the hostname the client
 	// must specify in the server_name extension.
 	ExpectServerName string
@@ -562,26 +657,53 @@
 	// return.
 	ALPNProtocol *string
 
-	// AllowSessionVersionMismatch causes the server to resume sessions
-	// regardless of the version associated with the session.
-	AllowSessionVersionMismatch bool
+	// AcceptAnySession causes the server to resume sessions regardless of
+	// the version associated with the session or cipher suite. It also
+	// causes the server to look in both TLS 1.2 and 1.3 extensions to
+	// process a ticket.
+	AcceptAnySession bool
 
-	// CorruptTicket causes a client to corrupt a session ticket before
-	// sending it in a resume handshake.
-	CorruptTicket bool
+	// SendBothTickets, if true, causes the client to send tickets in both
+	// TLS 1.2 and 1.3 extensions.
+	SendBothTickets bool
 
-	// OversizedSessionId causes the session id that is sent with a ticket
-	// resumption attempt to be too large (33 bytes).
-	OversizedSessionId bool
+	// FilterTicket, if not nil, causes the client to modify a session
+	// ticket before sending it in a resume handshake.
+	FilterTicket func([]byte) ([]byte, error)
+
+	// TicketSessionIDLength, if non-zero, is the length of the session ID
+	// to send with a ticket resumption offer.
+	TicketSessionIDLength int
+
+	// EmptyTicketSessionID, if true, causes the client to send an empty
+	// session ID with a ticket resumption offer. For simplicity, this will
+	// also cause the client to interpret a ServerHello with empty session
+	// ID as a resumption. (A client which sends empty session ID is
+	// normally expected to look ahead for ChangeCipherSpec.)
+	EmptyTicketSessionID bool
+
+	// ExpectNoTLS12Session, if true, causes the server to fail the
+	// connection if either a session ID or TLS 1.2 ticket is offered.
+	ExpectNoTLS12Session bool
+
+	// ExpectNoTLS13PSK, if true, causes the server to fail the connection
+	// if a TLS 1.3 PSK is offered.
+	ExpectNoTLS13PSK bool
 
 	// RequireExtendedMasterSecret, if true, requires that the peer support
 	// the extended master secret option.
 	RequireExtendedMasterSecret bool
 
 	// NoExtendedMasterSecret causes the client and server to behave as if
-	// they didn't support an extended master secret.
+	// they didn't support an extended master secret in the initial
+	// handshake.
 	NoExtendedMasterSecret bool
 
+	// NoExtendedMasterSecretOnRenegotiation causes the client and server to
+	// behave as if they didn't support an extended master secret in
+	// renegotiation handshakes.
+	NoExtendedMasterSecretOnRenegotiation bool
+
 	// EmptyRenegotiationInfo causes the renegotiation extension to be
 	// empty in a renegotiation handshake.
 	EmptyRenegotiationInfo bool
@@ -626,13 +748,13 @@
 	// server sends in the ServerHello instead of the negotiated one.
 	SendSRTPProtectionProfile uint16
 
-	// NoSignatureAndHashes, if true, causes the client to omit the
+	// NoSignatureAlgorithms, if true, causes the client to omit the
 	// signature and hashes extension.
 	//
 	// For a server, it will cause an empty list to be sent in the
 	// CertificateRequest message. None the less, the configured set will
 	// still be enforced.
-	NoSignatureAndHashes bool
+	NoSignatureAlgorithms bool
 
 	// NoSupportedCurves, if true, causes the client to omit the
 	// supported_curves extension.
@@ -643,10 +765,18 @@
 	// across a renego.
 	RequireSameRenegoClientVersion bool
 
-	// ExpectInitialRecordVersion, if non-zero, is the expected
-	// version of the records before the version is determined.
+	// ExpectInitialRecordVersion, if non-zero, is the expected value of
+	// record-layer version field before the protocol version is determined.
 	ExpectInitialRecordVersion uint16
 
+	// SendRecordVersion, if non-zero, is the value to send as the
+	// record-layer version.
+	SendRecordVersion uint16
+
+	// SendInitialRecordVersion, if non-zero, is the value to send as the
+	// record-layer version before the protocol version is determined.
+	SendInitialRecordVersion uint16
+
 	// MaxPacketLength, if non-zero, is the maximum acceptable size for a
 	// packet.
 	MaxPacketLength int
@@ -656,6 +786,11 @@
 	// the server believes it has actually negotiated.
 	SendCipherSuite uint16
 
+	// SendCipherSuites, if not nil, is the cipher suite list that the
+	// client will send in the ClientHello. This does not affect the cipher
+	// the client believes it has actually offered.
+	SendCipherSuites []uint16
+
 	// AppDataBeforeHandshake, if not nil, causes application data to be
 	// sent immediately before the first handshake message.
 	AppDataBeforeHandshake []byte
@@ -681,6 +816,10 @@
 	// Finished and will trigger a spurious retransmit.)
 	ReorderHandshakeFragments bool
 
+	// ReverseHandshakeFragments, if true, causes handshake fragments in
+	// DTLS to be reversed within a flight.
+	ReverseHandshakeFragments bool
+
 	// MixCompleteMessageWithFragments, if true, causes handshake
 	// messages in DTLS to redundantly both fragment the message
 	// and include a copy of the full one.
@@ -690,9 +829,13 @@
 	// content type to be sent immediately following the handshake.
 	SendInvalidRecordType bool
 
-	// WrongCertificateMessageType, if true, causes Certificate message to
-	// be sent with the wrong message type.
-	WrongCertificateMessageType bool
+	// SendWrongMessageType, if non-zero, causes messages of the specified
+	// type to be sent with the wrong value.
+	SendWrongMessageType byte
+
+	// SendTrailingMessageData, if non-zero, causes messages of the
+	// specified type to be sent with trailing data.
+	SendTrailingMessageData byte
 
 	// FragmentMessageTypeMismatch, if true, causes all non-initial
 	// handshake fragments in DTLS to have the wrong message type.
@@ -739,17 +882,22 @@
 	// Diffie-Hellman group. The generator used is always two.
 	DHGroupPrime *big.Int
 
-	// PackHandshakeFragments, if true, causes handshake fragments to be
-	// packed into individual handshake records, up to the specified record
-	// size.
+	// PackHandshakeFragments, if true, causes handshake fragments in DTLS
+	// to be packed into individual handshake records, up to the specified
+	// record size.
 	PackHandshakeFragments int
 
-	// PackHandshakeRecords, if true, causes handshake records to be packed
-	// into individual packets, up to the specified packet size.
+	// PackHandshakeRecords, if true, causes handshake records in DTLS to be
+	// packed into individual packets, up to the specified packet size.
 	PackHandshakeRecords int
 
-	// EnableAllCiphersInDTLS, if true, causes RC4 to be enabled in DTLS.
-	EnableAllCiphersInDTLS bool
+	// PackHandshakeFlight, if true, causes each handshake flight in TLS to
+	// be packed into records, up to the largest size record available.
+	PackHandshakeFlight bool
+
+	// AdvertiseAllConfiguredCiphers, if true, causes the client to
+	// advertise all configured cipher suite values.
+	AdvertiseAllConfiguredCiphers bool
 
 	// EmptyCertificateList, if true, causes the server to send an empty
 	// certificate list in the Certificate message.
@@ -767,14 +915,30 @@
 	// that will be added to client/server hellos.
 	CustomExtension string
 
+	// CustomUnencryptedExtension, if not empty, contains the contents of
+	// an extension that will be added to ServerHello in TLS 1.3.
+	CustomUnencryptedExtension string
+
 	// ExpectedCustomExtension, if not nil, contains the expected contents
 	// of a custom extension.
 	ExpectedCustomExtension *string
 
+	// CustomTicketExtension, if not empty, contains the contents of an
+	// extension what will be added to NewSessionTicket in TLS 1.3.
+	CustomTicketExtension string
+
+	// CustomTicketExtension, if not empty, contains the contents of an
+	// extension what will be added to HelloRetryRequest in TLS 1.3.
+	CustomHelloRetryRequestExtension string
+
 	// NoCloseNotify, if true, causes the close_notify alert to be skipped
 	// on connection shutdown.
 	NoCloseNotify bool
 
+	// SendAlertOnShutdown, if non-zero, is the alert to send instead of
+	// close_notify on shutdown.
+	SendAlertOnShutdown alert
+
 	// ExpectCloseNotify, if true, requires a close_notify from the peer on
 	// shutdown. Records from the peer received after close_notify is sent
 	// are not discard.
@@ -788,10 +952,43 @@
 	// ALPN and NPN in the same connetion.
 	NegotiateALPNAndNPN bool
 
+	// SendALPN, if non-empty, causes the server to send the specified
+	// string in the ALPN extension regardless of the content or presence of
+	// the client offer.
+	SendALPN string
+
+	// SendUnencryptedALPN, if non-empty, causes the server to send the
+	// specified string in a ServerHello ALPN extension in TLS 1.3.
+	SendUnencryptedALPN string
+
 	// SendEmptySessionTicket, if true, causes the server to send an empty
 	// session ticket.
 	SendEmptySessionTicket bool
 
+	// SendPSKKeyExchangeModes, if present, determines the PSK key exchange modes
+	// to send.
+	SendPSKKeyExchangeModes []byte
+
+	// ExpectNoNewSessionTicket, if present, means that the client will fail upon
+	// receipt of a NewSessionTicket message.
+	ExpectNoNewSessionTicket bool
+
+	// DuplicateTicketEarlyDataInfo causes an extra empty extension of
+	// ticket_early_data_info to be sent in NewSessionTicket.
+	DuplicateTicketEarlyDataInfo bool
+
+	// ExpectTicketEarlyDataInfo, if true, means that the client will fail upon
+	// absence of the ticket_early_data_info extension.
+	ExpectTicketEarlyDataInfo bool
+
+	// ExpectTicketAge, if non-zero, is the expected age of the ticket that the
+	// server receives from the client.
+	ExpectTicketAge time.Duration
+
+	// SendTicketAge, if non-zero, is the ticket age to be sent by the
+	// client.
+	SendTicketAge time.Duration
+
 	// FailIfSessionOffered, if true, causes the server to fail any
 	// connections where the client offers a non-empty session ID or session
 	// ticket.
@@ -802,6 +999,11 @@
 	// data record. This only makes sense for a server.
 	SendHelloRequestBeforeEveryAppDataRecord bool
 
+	// SendHelloRequestBeforeEveryHandshakeMessage, if true, causes a
+	// HelloRequest handshake message to be sent before each handshake
+	// message. This only makes sense for a server.
+	SendHelloRequestBeforeEveryHandshakeMessage bool
+
 	// RequireDHPublicValueLen causes a fatal error if the length (in
 	// bytes) of the server's Diffie-Hellman public value is not equal to
 	// this.
@@ -814,6 +1016,315 @@
 	// BadHelloRequest, if not nil, is what to send instead of a
 	// HelloRequest.
 	BadHelloRequest []byte
+
+	// RequireSessionTickets, if true, causes the client to require new
+	// sessions use session tickets instead of session IDs.
+	RequireSessionTickets bool
+
+	// NullAllCiphers, if true, causes every cipher to behave like the null
+	// cipher.
+	NullAllCiphers bool
+
+	// SendSCTListOnResume, if not nil, causes the server to send the
+	// supplied SCT list in resumption handshakes.
+	SendSCTListOnResume []byte
+
+	// SendOCSPResponseOnResume, if not nil, causes the server to advertise
+	// OCSP stapling in resumption handshakes and, if applicable, send the
+	// supplied stapled response.
+	SendOCSPResponseOnResume []byte
+
+	// SendExtensionOnCertificate, if not nil, causes the runner to send the
+	// supplied bytes in the extensions on the Certificate message.
+	SendExtensionOnCertificate []byte
+
+	// SendOCSPOnIntermediates, if not nil, causes the server to send the
+	// supplied OCSP on intermediate certificates in the Certificate message.
+	SendOCSPOnIntermediates []byte
+
+	// SendSCTOnIntermediates, if not nil, causes the server to send the
+	// supplied SCT on intermediate certificates in the Certificate message.
+	SendSCTOnIntermediates []byte
+
+	// SendDuplicateCertExtensions, if true, causes the server to send an extra
+	// copy of the OCSP/SCT extensions in the Certificate message.
+	SendDuplicateCertExtensions bool
+
+	// ExpectNoExtensionsOnIntermediate, if true, causes the client to
+	// reject extensions on intermediate certificates.
+	ExpectNoExtensionsOnIntermediate bool
+
+	// RecordPadding is the number of bytes of padding to add to each
+	// encrypted record in TLS 1.3.
+	RecordPadding int
+
+	// OmitRecordContents, if true, causes encrypted records in TLS 1.3 to
+	// be missing their body and content type. Padding, if configured, is
+	// still added.
+	OmitRecordContents bool
+
+	// OuterRecordType, if non-zero, is the outer record type to use instead
+	// of application data.
+	OuterRecordType recordType
+
+	// SendSignatureAlgorithm, if non-zero, causes all signatures to be sent
+	// with the given signature algorithm rather than the one negotiated.
+	SendSignatureAlgorithm signatureAlgorithm
+
+	// SkipECDSACurveCheck, if true, causes all ECDSA curve checks to be
+	// skipped.
+	SkipECDSACurveCheck bool
+
+	// IgnoreSignatureVersionChecks, if true, causes all signature
+	// algorithms to be enabled at all TLS versions.
+	IgnoreSignatureVersionChecks bool
+
+	// NegotiateRenegotiationInfoAtAllVersions, if true, causes
+	// Renegotiation Info to be negotiated at all versions.
+	NegotiateRenegotiationInfoAtAllVersions bool
+
+	// NegotiateNPNAtAllVersions, if true, causes NPN to be negotiated at
+	// all versions.
+	NegotiateNPNAtAllVersions bool
+
+	// NegotiateEMSAtAllVersions, if true, causes EMS to be negotiated at
+	// all versions.
+	NegotiateEMSAtAllVersions bool
+
+	// AdvertiseTicketExtension, if true, causes the ticket extension to be
+	// advertised in server extensions
+	AdvertiseTicketExtension bool
+
+	// NegotiatePSKResumption, if true, causes the server to attempt pure PSK
+	// resumption.
+	NegotiatePSKResumption bool
+
+	// AlwaysSelectPSKIdentity, if true, causes the server in TLS 1.3 to
+	// always acknowledge a session, regardless of one was offered.
+	AlwaysSelectPSKIdentity bool
+
+	// SelectPSKIdentityOnResume, if non-zero, causes the server to select
+	// the specified PSK identity index rather than the actual value.
+	SelectPSKIdentityOnResume uint16
+
+	// ExtraPSKIdentity, if true, causes the client to send an extra PSK
+	// identity.
+	ExtraPSKIdentity bool
+
+	// MissingKeyShare, if true, causes the TLS 1.3 implementation to skip
+	// sending a key_share extension and use the zero ECDHE secret
+	// instead.
+	MissingKeyShare bool
+
+	// SecondClientHelloMissingKeyShare, if true, causes the second TLS 1.3
+	// ClientHello to skip sending a key_share extension and use the zero
+	// ECDHE secret instead.
+	SecondClientHelloMissingKeyShare bool
+
+	// MisinterpretHelloRetryRequestCurve, if non-zero, causes the TLS 1.3
+	// client to pretend the server requested a HelloRetryRequest with the
+	// given curve rather than the actual one.
+	MisinterpretHelloRetryRequestCurve CurveID
+
+	// DuplicateKeyShares, if true, causes the TLS 1.3 client to send two
+	// copies of each KeyShareEntry.
+	DuplicateKeyShares bool
+
+	// SendEarlyAlert, if true, sends a fatal alert after the ClientHello.
+	SendEarlyAlert bool
+
+	// SendFakeEarlyDataLength, if non-zero, is the amount of early data to
+	// send after the ClientHello.
+	SendFakeEarlyDataLength int
+
+	// SendStrayEarlyHandshake, if non-zero, causes the client to send a stray
+	// handshake record before sending end of early data.
+	SendStrayEarlyHandshake bool
+
+	// OmitEarlyDataExtension, if true, causes the early data extension to
+	// be omitted in the ClientHello.
+	OmitEarlyDataExtension bool
+
+	// SendEarlyDataOnSecondClientHello, if true, causes the TLS 1.3 client to
+	// send early data after the second ClientHello.
+	SendEarlyDataOnSecondClientHello bool
+
+	// InterleaveEarlyData, if true, causes the TLS 1.3 client to send early
+	// data interleaved with the second ClientHello and the client Finished.
+	InterleaveEarlyData bool
+
+	// SendEarlyData causes a TLS 1.3 client to send the provided data
+	// in application data records immediately after the ClientHello,
+	// provided that the client offers a TLS 1.3 session. It will do this
+	// whether or not the server advertised early data for the ticket.
+	SendEarlyData [][]byte
+
+	// ExpectEarlyDataAccepted causes a TLS 1.3 client to check that early data
+	// was accepted by the server.
+	ExpectEarlyDataAccepted bool
+
+	// AlwaysAcceptEarlyData causes a TLS 1.3 server to always accept early data
+	// regardless of ALPN mismatch.
+	AlwaysAcceptEarlyData bool
+
+	// AlwaysRejectEarlyData causes a TLS 1.3 server to always reject early data.
+	AlwaysRejectEarlyData bool
+
+	// SendEarlyDataExtension, if true, causes a TLS 1.3 server to send the
+	// early_data extension in EncryptedExtensions, independent of whether
+	// it was accepted.
+	SendEarlyDataExtension bool
+
+	// ExpectEarlyData causes a TLS 1.3 server to read application
+	// data after the ClientHello (assuming the server is able to
+	// derive the key under which the data is encrypted) before it
+	// sends a ServerHello. It checks that the application data it
+	// reads matches what is provided in ExpectEarlyData and errors if
+	// the number of records or their content do not match.
+	ExpectEarlyData [][]byte
+
+	// SendHalfRTTData causes a TLS 1.3 server to send the provided
+	// data in application data records before reading the client's
+	// Finished message.
+	SendHalfRTTData [][]byte
+
+	// ExpectHalfRTTData causes a TLS 1.3 client, if 0-RTT was accepted, to
+	// read application data after reading the server's Finished message and
+	// before sending any subsequent handshake messages. It checks that the
+	// application data it reads matches what is provided in
+	// ExpectHalfRTTData and errors if the number of records or their
+	// content do not match.
+	ExpectHalfRTTData [][]byte
+
+	// EmptyEncryptedExtensions, if true, causes the TLS 1.3 server to
+	// emit an empty EncryptedExtensions block.
+	EmptyEncryptedExtensions bool
+
+	// EncryptedExtensionsWithKeyShare, if true, causes the TLS 1.3 server to
+	// include the KeyShare extension in the EncryptedExtensions block.
+	EncryptedExtensionsWithKeyShare bool
+
+	// AlwaysSendHelloRetryRequest, if true, causes a HelloRetryRequest to
+	// be sent by the server, even if empty.
+	AlwaysSendHelloRetryRequest bool
+
+	// SecondHelloRetryRequest, if true, causes the TLS 1.3 server to send
+	// two HelloRetryRequests instead of one.
+	SecondHelloRetryRequest bool
+
+	// SendHelloRetryRequestCurve, if non-zero, causes the server to send
+	// the specified curve in a HelloRetryRequest.
+	SendHelloRetryRequestCurve CurveID
+
+	// SendHelloRetryRequestCookie, if not nil, contains a cookie to be
+	// sent by the server in HelloRetryRequest.
+	SendHelloRetryRequestCookie []byte
+
+	// DuplicateHelloRetryRequestExtensions, if true, causes all
+	// HelloRetryRequest extensions to be sent twice.
+	DuplicateHelloRetryRequestExtensions bool
+
+	// SendServerHelloVersion, if non-zero, causes the server to send the
+	// specified value in ServerHello version field.
+	SendServerHelloVersion uint16
+
+	// SkipHelloRetryRequest, if true, causes the TLS 1.3 server to not send
+	// HelloRetryRequest.
+	SkipHelloRetryRequest bool
+
+	// PackHelloRequestWithFinished, if true, causes the TLS server to send
+	// HelloRequest in the same record as Finished.
+	PackHelloRequestWithFinished bool
+
+	// ExpectMissingKeyShare, if true, causes the TLS server to fail the
+	// connection if the selected curve appears in the client's initial
+	// ClientHello. That is, it requires that a HelloRetryRequest be sent.
+	ExpectMissingKeyShare bool
+
+	// SendExtraFinished, if true, causes an extra Finished message to be
+	// sent.
+	SendExtraFinished bool
+
+	// SendRequestContext, if not empty, is the request context to send in
+	// a TLS 1.3 CertificateRequest.
+	SendRequestContext []byte
+
+	// SendSNIWarningAlert, if true, causes the server to send an
+	// unrecognized_name alert before the ServerHello.
+	SendSNIWarningAlert bool
+
+	// SendCompressionMethods, if not nil, is the compression method list to
+	// send in the ClientHello.
+	SendCompressionMethods []byte
+
+	// AlwaysSendPreSharedKeyIdentityHint, if true, causes the server to
+	// always send a ServerKeyExchange for PSK ciphers, even if the identity
+	// hint is empty.
+	AlwaysSendPreSharedKeyIdentityHint bool
+
+	// TrailingKeyShareData, if true, causes the client key share list to
+	// include a trailing byte.
+	TrailingKeyShareData bool
+
+	// InvalidChannelIDSignature, if true, causes the client to generate an
+	// invalid Channel ID signature.
+	InvalidChannelIDSignature bool
+
+	// ExpectGREASE, if true, causes messages without GREASE values to be
+	// rejected. See draft-davidben-tls-grease-01.
+	ExpectGREASE bool
+
+	// SendShortPSKBinder, if true, causes the client to send a PSK binder
+	// that is one byte shorter than it should be.
+	SendShortPSKBinder bool
+
+	// SendInvalidPSKBinder, if true, causes the client to send an invalid
+	// PSK binder.
+	SendInvalidPSKBinder bool
+
+	// SendNoPSKBinder, if true, causes the client to send no PSK binders.
+	SendNoPSKBinder bool
+
+	// SendExtraPSKBinder, if true, causes the client to send an extra PSK
+	// binder.
+	SendExtraPSKBinder bool
+
+	// PSKBinderFirst, if true, causes the client to send the PSK Binder
+	// extension as the first extension instead of the last extension.
+	PSKBinderFirst bool
+
+	// NoOCSPStapling, if true, causes the client to not request OCSP
+	// stapling.
+	NoOCSPStapling bool
+
+	// NoSignedCertificateTimestamps, if true, causes the client to not
+	// request signed certificate timestamps.
+	NoSignedCertificateTimestamps bool
+
+	// SendSupportedPointFormats, if not nil, is the list of supported point
+	// formats to send in ClientHello or ServerHello. If set to a non-nil
+	// empty slice, no extension will be sent.
+	SendSupportedPointFormats []byte
+
+	// MaxReceivePlaintext, if non-zero, is the maximum plaintext record
+	// length accepted from the peer.
+	MaxReceivePlaintext int
+
+	// SendTicketLifetime, if non-zero, is the ticket lifetime to send in
+	// NewSessionTicket messages.
+	SendTicketLifetime time.Duration
+
+	// SendServerNameAck, if true, causes the server to acknowledge the SNI
+	// extension.
+	SendServerNameAck bool
+
+	// ExpectCertificateReqNames, if not nil, contains the list of X.509
+	// names that must be sent in a CertificateRequest from the server.
+	ExpectCertificateReqNames [][]byte
+
+	// RenegotiationCertificate, if not nil, is the certificate to use on
+	// renegotiation handshakes.
+	RenegotiationCertificate *Certificate
 }
 
 func (c *Config) serverInit() {
@@ -857,18 +1368,40 @@
 	return s
 }
 
-func (c *Config) minVersion() uint16 {
-	if c == nil || c.MinVersion == 0 {
-		return minVersion
+func (c *Config) minVersion(isDTLS bool) uint16 {
+	ret := uint16(minVersion)
+	if c != nil && c.MinVersion != 0 {
+		ret = c.MinVersion
 	}
-	return c.MinVersion
+	if isDTLS {
+		// The lowest version of DTLS is 1.0. There is no DSSL 3.0.
+		if ret < VersionTLS10 {
+			return VersionTLS10
+		}
+		// There is no such thing as DTLS 1.1.
+		if ret == VersionTLS11 {
+			return VersionTLS12
+		}
+	}
+	return ret
 }
 
-func (c *Config) maxVersion() uint16 {
-	if c == nil || c.MaxVersion == 0 {
-		return maxVersion
+func (c *Config) maxVersion(isDTLS bool) uint16 {
+	ret := uint16(maxVersion)
+	if c != nil && c.MaxVersion != 0 {
+		ret = c.MaxVersion
 	}
-	return c.MaxVersion
+	if isDTLS {
+		// We only implement up to DTLS 1.2.
+		if ret > VersionTLS12 {
+			return VersionTLS12
+		}
+		// There is no such thing as DTLS 1.1.
+		if ret == VersionTLS11 {
+			return VersionTLS10
+		}
+	}
+	return ret
 }
 
 var defaultCurvePreferences = []CurveID{CurveX25519, CurveP256, CurveP384, CurveP521}
@@ -880,19 +1413,22 @@
 	return c.CurvePreferences
 }
 
-// mutualVersion returns the protocol version to use given the advertised
-// version of the peer.
-func (c *Config) mutualVersion(vers uint16) (uint16, bool) {
-	minVersion := c.minVersion()
-	maxVersion := c.maxVersion()
+func (c *Config) defaultCurves() map[CurveID]bool {
+	defaultCurves := make(map[CurveID]bool)
+	curves := c.DefaultCurves
+	if c == nil || c.DefaultCurves == nil {
+		curves = c.curvePreferences()
+	}
+	for _, curveID := range curves {
+		defaultCurves[curveID] = true
+	}
+	return defaultCurves
+}
 
-	if vers < minVersion {
-		return 0, false
-	}
-	if vers > maxVersion {
-		vers = maxVersion
-	}
-	return vers, true
+// isSupportedVersion returns true if the specified protocol version is
+// acceptable.
+func (c *Config) isSupportedVersion(vers uint16, isDTLS bool) bool {
+	return c.minVersion(isDTLS) <= vers && vers <= c.maxVersion(isDTLS)
 }
 
 // getCertificateForName returns the best certificate for the given name,
@@ -928,18 +1464,18 @@
 	return &c.Certificates[0]
 }
 
-func (c *Config) signatureAndHashesForServer() []signatureAndHash {
-	if c != nil && c.SignatureAndHashes != nil {
-		return c.SignatureAndHashes
+func (c *Config) signSignatureAlgorithms() []signatureAlgorithm {
+	if c != nil && c.SignSignatureAlgorithms != nil {
+		return c.SignSignatureAlgorithms
 	}
-	return supportedClientCertSignatureAlgorithms
+	return supportedSignatureAlgorithms
 }
 
-func (c *Config) signatureAndHashesForClient() []signatureAndHash {
-	if c != nil && c.SignatureAndHashes != nil {
-		return c.SignatureAndHashes
+func (c *Config) verifySignatureAlgorithms() []signatureAlgorithm {
+	if c != nil && c.VerifySignatureAlgorithms != nil {
+		return c.VerifySignatureAlgorithms
 	}
-	return supportedSKXSignatureAlgorithms
+	return supportedSignatureAlgorithms
 }
 
 // BuildNameToCertificate parses c.Certificates and builds c.NameToCertificate
@@ -1154,11 +1690,17 @@
 	return fmt.Errorf("tls: received unexpected handshake message of type %T when waiting for %T", got, wanted)
 }
 
-func isSupportedSignatureAndHash(sigHash signatureAndHash, sigHashes []signatureAndHash) bool {
-	for _, s := range sigHashes {
-		if s == sigHash {
+func isSupportedSignatureAlgorithm(sigAlg signatureAlgorithm, sigAlgs []signatureAlgorithm) bool {
+	for _, s := range sigAlgs {
+		if s == sigAlg {
 			return true
 		}
 	}
 	return false
 }
+
+var (
+	// See draft-ietf-tls-tls13-16, section 6.3.1.2.
+	downgradeTLS13 = []byte{0x44, 0x4f, 0x57, 0x4e, 0x47, 0x52, 0x44, 0x01}
+	downgradeTLS12 = []byte{0x44, 0x4f, 0x57, 0x4e, 0x47, 0x52, 0x44, 0x00}
+)
diff --git a/src/ssl/test/runner/conn.go b/src/ssl/test/runner/conn.go
index cb60a92..830977d 100644
--- a/src/ssl/test/runner/conn.go
+++ b/src/ssl/test/runner/conn.go
@@ -21,6 +21,9 @@
 	"time"
 )
 
+var errNoCertificateAlert = errors.New("tls: no certificate alert")
+var errEndOfEarlyDataAlert = errors.New("tls: end of early data alert")
+
 // A Conn represents a secured connection.
 // It implements the net.Conn interface.
 type Conn struct {
@@ -36,6 +39,7 @@
 	haveVers             bool       // version has been negotiated
 	config               *Config    // configuration passed to constructor
 	handshakeComplete    bool
+	skipEarlyData        bool // On a server, indicates that the client is sending early data that must be skipped over.
 	didResume            bool // whether this connection was a session resumption
 	extendedMasterSecret bool // whether this session used an extended master secret
 	cipherSuite          *cipherSuite
@@ -50,14 +54,16 @@
 	// firstFinished contains the first Finished hash sent during the
 	// handshake. This is the "tls-unique" channel binding value.
 	firstFinished [12]byte
-	// clientCertSignatureHash contains the TLS hash id for the hash that
-	// was used by the client to sign the handshake with a client
-	// certificate. This is only set by a server and is zero if no client
-	// certificates were used.
-	clientCertSignatureHash uint8
+	// peerSignatureAlgorithm contains the signature algorithm that was used
+	// by the peer in the handshake, or zero if not applicable.
+	peerSignatureAlgorithm signatureAlgorithm
+	// curveID contains the curve that was used in the handshake, or zero if
+	// not applicable.
+	curveID CurveID
 
 	clientRandom, serverRandom [32]byte
-	masterSecret               [48]byte
+	exporterSecret             []byte
+	resumptionSecret           []byte
 
 	clientProtocol         string
 	clientProtocolFallback bool
@@ -79,6 +85,10 @@
 	input    *block       // application record waiting to be read
 	hand     bytes.Buffer // handshake record waiting to be read
 
+	// pendingFlight, if PackHandshakeFlight is enabled, is the buffer of
+	// handshake data to be split into records at the end of the flight.
+	pendingFlight bytes.Buffer
+
 	// DTLS state
 	sendHandshakeSeq uint16
 	recvHandshakeSeq uint16
@@ -86,6 +96,8 @@
 	handMsgLen       int      // handshake message length, not including the header
 	pendingFragments [][]byte // pending outgoing handshake fragments.
 
+	keyUpdateRequested bool
+
 	tmp [16]byte
 }
 
@@ -153,6 +165,8 @@
 	// used to save allocating a new buffer for each MAC.
 	inDigestBuf, outDigestBuf []byte
 
+	trafficSecret []byte
+
 	config *Config
 }
 
@@ -189,9 +203,41 @@
 	hc.nextMac = nil
 	hc.config = config
 	hc.incEpoch()
+
+	if config.Bugs.NullAllCiphers {
+		hc.cipher = nullCipher{}
+		hc.mac = nil
+	}
 	return nil
 }
 
+// useTrafficSecret sets the current cipher state for TLS 1.3.
+func (hc *halfConn) useTrafficSecret(version uint16, suite *cipherSuite, secret []byte, side trafficDirection) {
+	hc.version = version
+	hc.cipher = deriveTrafficAEAD(version, suite, secret, side)
+	if hc.config.Bugs.NullAllCiphers {
+		hc.cipher = nullCipher{}
+	}
+	hc.trafficSecret = secret
+	hc.incEpoch()
+}
+
+// resetCipher changes the cipher state back to no encryption to be able
+// to send an unencrypted ClientHello in response to HelloRetryRequest
+// after 0-RTT data was rejected.
+func (hc *halfConn) resetCipher() {
+	hc.cipher = nil
+	hc.incEpoch()
+}
+
+func (hc *halfConn) doKeyUpdate(c *Conn, isOutgoing bool) {
+	side := serverWrite
+	if c.isClient == isOutgoing {
+		side = clientWrite
+	}
+	hc.useTrafficSecret(hc.version, c.cipherSuite, updateTrafficSecret(c.cipherSuite.hash(), hc.trafficSecret), side)
+}
+
 // incSeq increments the sequence number.
 func (hc *halfConn) incSeq(isOutgoing bool) {
 	limit := 0
@@ -340,8 +386,9 @@
 
 // decrypt checks and strips the mac and decrypts the data in b. Returns a
 // success boolean, the number of bytes to skip from the start of the record in
-// order to get the application payload, and an optional alert value.
-func (hc *halfConn) decrypt(b *block) (ok bool, prefixLen int, alertValue alert) {
+// order to get the application payload, the encrypted record type (or 0
+// if there is none), and an optional alert value.
+func (hc *halfConn) decrypt(b *block) (ok bool, prefixLen int, contentType recordType, alertValue alert) {
 	recordHeaderLen := hc.recordHeaderLen()
 
 	// pull out payload
@@ -371,22 +418,25 @@
 			if c.explicitNonce {
 				explicitIVLen = 8
 				if len(payload) < explicitIVLen {
-					return false, 0, alertBadRecordMAC
+					return false, 0, 0, alertBadRecordMAC
 				}
 				nonce = payload[:8]
 				payload = payload[8:]
 			}
 
-			var additionalData [13]byte
-			copy(additionalData[:], seq)
-			copy(additionalData[8:], b.data[:3])
-			n := len(payload) - c.Overhead()
-			additionalData[11] = byte(n >> 8)
-			additionalData[12] = byte(n)
+			var additionalData []byte
+			if hc.version < VersionTLS13 {
+				additionalData = make([]byte, 13)
+				copy(additionalData, seq)
+				copy(additionalData[8:], b.data[:3])
+				n := len(payload) - c.Overhead()
+				additionalData[11] = byte(n >> 8)
+				additionalData[12] = byte(n)
+			}
 			var err error
-			payload, err = c.Open(payload[:0], nonce, payload, additionalData[:])
+			payload, err = c.Open(payload[:0], nonce, payload, additionalData)
 			if err != nil {
-				return false, 0, alertBadRecordMAC
+				return false, 0, 0, alertBadRecordMAC
 			}
 			b.resize(recordHeaderLen + explicitIVLen + len(payload))
 		case cbcMode:
@@ -396,7 +446,7 @@
 			}
 
 			if len(payload)%blockSize != 0 || len(payload) < roundUp(explicitIVLen+macSize+1, blockSize) {
-				return false, 0, alertBadRecordMAC
+				return false, 0, 0, alertBadRecordMAC
 			}
 
 			if explicitIVLen > 0 {
@@ -426,12 +476,26 @@
 		default:
 			panic("unknown cipher type")
 		}
+
+		if hc.version >= VersionTLS13 {
+			i := len(payload)
+			for i > 0 && payload[i-1] == 0 {
+				i--
+			}
+			payload = payload[:i]
+			if len(payload) == 0 {
+				return false, 0, 0, alertUnexpectedMessage
+			}
+			contentType = recordType(payload[len(payload)-1])
+			payload = payload[:len(payload)-1]
+			b.resize(recordHeaderLen + len(payload))
+		}
 	}
 
 	// check, strip mac
 	if hc.mac != nil {
 		if len(payload) < macSize {
-			return false, 0, alertBadRecordMAC
+			return false, 0, 0, alertBadRecordMAC
 		}
 
 		// strip mac off payload, b.data
@@ -443,13 +507,13 @@
 		localMAC := hc.mac.MAC(hc.inDigestBuf, seq, b.data[:3], b.data[recordHeaderLen-2:recordHeaderLen], payload[:n])
 
 		if subtle.ConstantTimeCompare(localMAC, remoteMAC) != 1 || paddingGood != 255 {
-			return false, 0, alertBadRecordMAC
+			return false, 0, 0, alertBadRecordMAC
 		}
 		hc.inDigestBuf = localMAC
 	}
 	hc.incSeq(false)
 
-	return true, recordHeaderLen + explicitIVLen, 0
+	return true, recordHeaderLen + explicitIVLen, contentType, 0
 }
 
 // padToBlockSize calculates the needed padding block, if any, for a payload.
@@ -481,7 +545,7 @@
 }
 
 // encrypt encrypts and macs the data in b.
-func (hc *halfConn) encrypt(b *block, explicitIVLen int) (bool, alert) {
+func (hc *halfConn) encrypt(b *block, explicitIVLen int, typ recordType) (bool, alert) {
 	recordHeaderLen := hc.recordHeaderLen()
 
 	// mac
@@ -498,6 +562,20 @@
 
 	// encrypt
 	if hc.cipher != nil {
+		// Add TLS 1.3 padding.
+		if hc.version >= VersionTLS13 {
+			paddingLen := hc.config.Bugs.RecordPadding
+			if hc.config.Bugs.OmitRecordContents {
+				b.resize(recordHeaderLen + paddingLen)
+			} else {
+				b.resize(len(b.data) + 1 + paddingLen)
+				b.data[len(b.data)-paddingLen-1] = byte(typ)
+			}
+			for i := 0; i < paddingLen; i++ {
+				b.data[len(b.data)-paddingLen+i] = 0
+			}
+		}
+
 		switch c := hc.cipher.(type) {
 		case cipher.Stream:
 			c.XORKeyStream(payload, payload)
@@ -511,13 +589,16 @@
 			payload := b.data[recordHeaderLen+explicitIVLen:]
 			payload = payload[:payloadLen]
 
-			var additionalData [13]byte
-			copy(additionalData[:], hc.outSeq[:])
-			copy(additionalData[8:], b.data[:3])
-			additionalData[11] = byte(payloadLen >> 8)
-			additionalData[12] = byte(payloadLen)
+			var additionalData []byte
+			if hc.version < VersionTLS13 {
+				additionalData = make([]byte, 13)
+				copy(additionalData, hc.outSeq[:])
+				copy(additionalData[8:], b.data[:3])
+				additionalData[11] = byte(payloadLen >> 8)
+				additionalData[12] = byte(payloadLen)
+			}
 
-			c.Seal(payload[:0], nonce, payload, additionalData[:])
+			c.Seal(payload[:0], nonce, payload, additionalData)
 		case cbcMode:
 			blockSize := c.BlockSize()
 			if explicitIVLen > 0 {
@@ -643,11 +724,12 @@
 }
 
 func (c *Conn) doReadRecord(want recordType) (recordType, *block, error) {
+RestartReadRecord:
 	if c.isDTLS {
 		return c.dtlsDoReadRecord(want)
 	}
 
-	recordHeaderLen := tlsRecordHeaderLen
+	recordHeaderLen := c.in.recordHeaderLen()
 
 	if c.rawInput == nil {
 		c.rawInput = c.in.newBlock()
@@ -667,6 +749,7 @@
 		}
 		return 0, nil, err
 	}
+
 	typ := recordType(b.data[0])
 
 	// No valid TLS record has a type of 0x80, however SSLv2 handshakes
@@ -680,13 +763,21 @@
 
 	vers := uint16(b.data[1])<<8 | uint16(b.data[2])
 	n := int(b.data[3])<<8 | int(b.data[4])
-	if c.haveVers {
-		if vers != c.vers {
-			c.sendAlert(alertProtocolVersion)
-			return 0, nil, c.in.setErrorLocked(fmt.Errorf("tls: received record with version %x when expecting version %x", vers, c.vers))
+
+	// Alerts sent near version negotiation do not have a well-defined
+	// record-layer version prior to TLS 1.3. (In TLS 1.3, the record-layer
+	// version is irrelevant.)
+	if typ != recordTypeAlert {
+		var expect uint16
+		if c.haveVers {
+			expect = c.vers
+			if c.vers >= VersionTLS13 {
+				expect = VersionTLS10
+			}
+		} else {
+			expect = c.config.Bugs.ExpectInitialRecordVersion
 		}
-	} else {
-		if expect := c.config.Bugs.ExpectInitialRecordVersion; expect != 0 && vers != expect {
+		if expect != 0 && vers != expect {
 			c.sendAlert(alertProtocolVersion)
 			return 0, nil, c.in.setErrorLocked(fmt.Errorf("tls: received record with version %x when expecting version %x", vers, expect))
 		}
@@ -721,11 +812,32 @@
 
 	// Process message.
 	b, c.rawInput = c.in.splitBlock(b, recordHeaderLen+n)
-	ok, off, err := c.in.decrypt(b)
+	ok, off, encTyp, alertValue := c.in.decrypt(b)
+
+	// Handle skipping over early data.
+	if !ok && c.skipEarlyData {
+		goto RestartReadRecord
+	}
+
+	// If the server is expecting a second ClientHello (in response to
+	// a HelloRetryRequest) and the client sends early data, there
+	// won't be a decryption failure but it still needs to be skipped.
+	if c.in.cipher == nil && typ == recordTypeApplicationData && c.skipEarlyData {
+		goto RestartReadRecord
+	}
+
 	if !ok {
-		c.in.setErrorLocked(c.sendAlert(err))
+		return 0, nil, c.in.setErrorLocked(c.sendAlert(alertValue))
 	}
 	b.off = off
+	c.skipEarlyData = false
+
+	if c.vers >= VersionTLS13 && c.in.cipher != nil {
+		if typ != recordTypeApplicationData {
+			return 0, nil, c.in.setErrorLocked(fmt.Errorf("tls: outer record type is not application data"))
+		}
+		typ = encTyp
+	}
 	return typ, b, nil
 }
 
@@ -746,7 +858,7 @@
 			return c.in.setErrorLocked(errors.New("tls: handshake or ChangeCipherSpec requested after handshake complete"))
 		}
 	case recordTypeApplicationData:
-		if !c.handshakeComplete && !c.config.Bugs.ExpectFalseStart {
+		if !c.handshakeComplete && !c.config.Bugs.ExpectFalseStart && len(c.config.Bugs.ExpectHalfRTTData) == 0 && len(c.config.Bugs.ExpectEarlyData) == 0 {
 			c.sendAlert(alertInternalError)
 			return c.in.setErrorLocked(errors.New("tls: application data record requested before handshake complete"))
 		}
@@ -762,7 +874,11 @@
 		return err
 	}
 	data := b.data[b.off:]
-	if len(data) > maxPlaintext {
+	max := maxPlaintext
+	if c.config.Bugs.MaxReceivePlaintext != 0 {
+		max = c.config.Bugs.MaxReceivePlaintext
+	}
+	if len(data) > max {
 		err := c.sendAlert(alertRecordOverflow)
 		c.in.freeBlock(b)
 		return c.in.setErrorLocked(err)
@@ -783,6 +899,15 @@
 		}
 		switch data[0] {
 		case alertLevelWarning:
+			if alert(data[1]) == alertNoCertificate {
+				c.in.freeBlock(b)
+				return errNoCertificateAlert
+			}
+			if alert(data[1]) == alertEndOfEarlyData {
+				c.in.freeBlock(b)
+				return errEndOfEarlyDataAlert
+			}
+
 			// drop on the floor
 			c.in.freeBlock(b)
 			goto Again
@@ -811,14 +936,11 @@
 		b = nil
 
 	case recordTypeHandshake:
+		// Allow handshake data while reading application data to
+		// trigger post-handshake messages.
 		// TODO(rsc): Should at least pick off connection close.
-		if typ != want {
-			// A client might need to process a HelloRequest from
-			// the server, thus receiving a handshake message when
-			// application data is expected is ok.
-			if !c.isClient || want != recordTypeApplicationData {
-				return c.in.setErrorLocked(c.sendAlert(alertNoRenegotiation))
-			}
+		if typ != want && want != recordTypeApplicationData {
+			return c.in.setErrorLocked(c.sendAlert(alertNoRenegotiation))
 		}
 		c.hand.Write(data)
 	}
@@ -837,6 +959,9 @@
 	if c.config.Bugs.FragmentAlert {
 		c.writeRecord(recordTypeAlert, c.tmp[0:1])
 		c.writeRecord(recordTypeAlert, c.tmp[1:2])
+	} else if c.config.Bugs.DoubleAlert {
+		copy(c.tmp[2:4], c.tmp[0:2])
+		c.writeRecord(recordTypeAlert, c.tmp[0:4])
 	} else {
 		c.writeRecord(recordTypeAlert, c.tmp[0:2])
 	}
@@ -851,7 +976,7 @@
 // L < c.out.Mutex.
 func (c *Conn) sendAlert(err alert) error {
 	level := byte(alertLevelError)
-	if err == alertNoRenegotiation || err == alertCloseNotify {
+	if err == alertNoRenegotiation || err == alertCloseNotify || err == alertNoCertificate || err == alertEndOfEarlyData {
 		level = alertLevelWarning
 	}
 	return c.SendAlert(level, err)
@@ -876,11 +1001,55 @@
 // to the connection and updates the record layer state.
 // c.out.Mutex <= L.
 func (c *Conn) writeRecord(typ recordType, data []byte) (n int, err error) {
+	if msgType := c.config.Bugs.SendWrongMessageType; msgType != 0 {
+		if typ == recordTypeHandshake && data[0] == msgType {
+			newData := make([]byte, len(data))
+			copy(newData, data)
+			newData[0] += 42
+			data = newData
+		}
+	}
+
+	if msgType := c.config.Bugs.SendTrailingMessageData; msgType != 0 {
+		if typ == recordTypeHandshake && data[0] == msgType {
+			newData := make([]byte, len(data))
+			copy(newData, data)
+
+			// Add a 0 to the body.
+			newData = append(newData, 0)
+			// Fix the header.
+			newLen := len(newData) - 4
+			newData[1] = byte(newLen >> 16)
+			newData[2] = byte(newLen >> 8)
+			newData[3] = byte(newLen)
+
+			data = newData
+		}
+	}
+
 	if c.isDTLS {
 		return c.dtlsWriteRecord(typ, data)
 	}
 
-	recordHeaderLen := tlsRecordHeaderLen
+	if typ == recordTypeHandshake {
+		if c.config.Bugs.SendHelloRequestBeforeEveryHandshakeMessage {
+			newData := make([]byte, 0, 4+len(data))
+			newData = append(newData, typeHelloRequest, 0, 0, 0)
+			newData = append(newData, data...)
+			data = newData
+		}
+
+		if c.config.Bugs.PackHandshakeFlight {
+			c.pendingFlight.Write(data)
+			return len(data), nil
+		}
+	}
+
+	return c.doWriteRecord(typ, data)
+}
+
+func (c *Conn) doWriteRecord(typ recordType, data []byte) (n int, err error) {
+	recordHeaderLen := c.out.recordHeaderLen()
 	b := c.out.newBlock()
 	first := true
 	isClientHello := typ == recordTypeHandshake && len(data) > 0 && data[0] == typeClientHello
@@ -923,12 +1092,27 @@
 		}
 		b.resize(recordHeaderLen + explicitIVLen + m)
 		b.data[0] = byte(typ)
+		if c.vers >= VersionTLS13 && c.out.cipher != nil {
+			b.data[0] = byte(recordTypeApplicationData)
+			if outerType := c.config.Bugs.OuterRecordType; outerType != 0 {
+				b.data[0] = byte(outerType)
+			}
+		}
 		vers := c.vers
-		if vers == 0 {
+		if vers == 0 || vers >= VersionTLS13 {
 			// Some TLS servers fail if the record version is
 			// greater than TLS 1.0 for the initial ClientHello.
+			//
+			// TLS 1.3 fixes the version number in the record
+			// layer to {3, 1}.
 			vers = VersionTLS10
 		}
+		if c.config.Bugs.SendRecordVersion != 0 {
+			vers = c.config.Bugs.SendRecordVersion
+		}
+		if c.vers == 0 && c.config.Bugs.SendInitialRecordVersion != 0 {
+			vers = c.config.Bugs.SendInitialRecordVersion
+		}
 		b.data[1] = byte(vers >> 8)
 		b.data[2] = byte(vers)
 		b.data[3] = byte(m >> 8)
@@ -944,7 +1128,7 @@
 			}
 		}
 		copy(b.data[recordHeaderLen+explicitIVLen:], data)
-		c.out.encrypt(b, explicitIVLen)
+		c.out.encrypt(b, explicitIVLen, typ)
 		_, err = c.conn.Write(b.data)
 		if err != nil {
 			break
@@ -968,6 +1152,23 @@
 	return
 }
 
+func (c *Conn) flushHandshake() error {
+	if c.isDTLS {
+		return c.dtlsFlushHandshake()
+	}
+
+	for c.pendingFlight.Len() > 0 {
+		var buf [maxPlaintext]byte
+		n, _ := c.pendingFlight.Read(buf[:])
+		if _, err := c.doWriteRecord(recordTypeHandshake, buf[:n]); err != nil {
+			return err
+		}
+	}
+
+	c.pendingFlight.Reset()
+	return nil
+}
+
 func (c *Conn) doReadHandshake() ([]byte, error) {
 	if c.isDTLS {
 		return c.dtlsDoReadHandshake()
@@ -1003,6 +1204,13 @@
 // c.in.Mutex < L; c.out.Mutex < L.
 func (c *Conn) readHandshake() (interface{}, error) {
 	data, err := c.doReadHandshake()
+	if err == errNoCertificateAlert {
+		if c.hand.Len() != 0 {
+			// The warning alert may not interleave with a handshake message.
+			return nil, c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
+		}
+		return new(ssl3NoCertificateMsg), nil
+	}
 	if err != nil {
 		return nil, err
 	}
@@ -1019,13 +1227,22 @@
 		m = &serverHelloMsg{
 			isDTLS: c.isDTLS,
 		}
+	case typeHelloRetryRequest:
+		m = new(helloRetryRequestMsg)
 	case typeNewSessionTicket:
-		m = new(newSessionTicketMsg)
+		m = &newSessionTicketMsg{
+			version: c.vers,
+		}
+	case typeEncryptedExtensions:
+		m = new(encryptedExtensionsMsg)
 	case typeCertificate:
-		m = new(certificateMsg)
+		m = &certificateMsg{
+			hasRequestContext: c.vers >= VersionTLS13,
+		}
 	case typeCertificateRequest:
 		m = &certificateRequestMsg{
-			hasSignatureAndHash: c.vers >= VersionTLS12,
+			hasSignatureAlgorithm: c.vers >= VersionTLS12,
+			hasRequestContext:     c.vers >= VersionTLS13,
 		}
 	case typeCertificateStatus:
 		m = new(certificateStatusMsg)
@@ -1037,7 +1254,7 @@
 		m = new(clientKeyExchangeMsg)
 	case typeCertificateVerify:
 		m = &certificateVerifyMsg{
-			hasSignatureAndHash: c.vers >= VersionTLS12,
+			hasSignatureAlgorithm: c.vers >= VersionTLS12,
 		}
 	case typeNextProtocol:
 		m = new(nextProtoMsg)
@@ -1045,8 +1262,10 @@
 		m = new(finishedMsg)
 	case typeHelloVerifyRequest:
 		m = new(helloVerifyRequestMsg)
-	case typeEncryptedExtensions:
-		m = new(encryptedExtensionsMsg)
+	case typeChannelID:
+		m = new(channelIDMsg)
+	case typeKeyUpdate:
+		m = new(keyUpdateMsg)
 	default:
 		return nil, c.in.setErrorLocked(c.sendAlert(alertUnexpectedMessage))
 	}
@@ -1131,6 +1350,20 @@
 	return nil
 }
 
+func (c *Conn) SendHalfHelloRequest() error {
+	if err := c.Handshake(); err != nil {
+		return err
+	}
+
+	c.out.Lock()
+	defer c.out.Unlock()
+
+	if _, err := c.writeRecord(recordTypeHandshake, []byte{typeHelloRequest, 0}); err != nil {
+		return err
+	}
+	return c.flushHandshake()
+}
+
 // Write writes data to the connection.
 func (c *Conn) Write(b []byte) (int, error) {
 	if err := c.Handshake(); err != nil {
@@ -1140,6 +1373,10 @@
 	c.out.Lock()
 	defer c.out.Unlock()
 
+	// Flush any pending handshake data. PackHelloRequestWithFinished may
+	// have been set and the handshake not followed by Renegotiate.
+	c.flushHandshake()
+
 	if err := c.out.err; err != nil {
 		return 0, err
 	}
@@ -1148,12 +1385,20 @@
 		return 0, alertInternalError
 	}
 
+	if c.keyUpdateRequested {
+		if err := c.sendKeyUpdateLocked(keyUpdateNotRequested); err != nil {
+			return 0, err
+		}
+		c.keyUpdateRequested = false
+	}
+
 	if c.config.Bugs.SendSpuriousAlert != 0 {
 		c.sendAlertLocked(alertLevelError, c.config.Bugs.SendSpuriousAlert)
 	}
 
 	if c.config.Bugs.SendHelloRequestBeforeEveryAppDataRecord {
 		c.writeRecord(recordTypeHandshake, []byte{typeHelloRequest, 0, 0, 0})
+		c.flushHandshake()
 	}
 
 	// SSL 3.0 and TLS 1.0 are susceptible to a chosen-plaintext
@@ -1180,23 +1425,82 @@
 	return n + m, c.out.setErrorLocked(err)
 }
 
-func (c *Conn) handleRenegotiation() error {
-	c.handshakeComplete = false
-	if !c.isClient {
-		panic("renegotiation should only happen for a client")
+func (c *Conn) processTLS13NewSessionTicket(newSessionTicket *newSessionTicketMsg, cipherSuite *cipherSuite) error {
+	if c.config.Bugs.ExpectGREASE && !newSessionTicket.hasGREASEExtension {
+		return errors.New("tls: no GREASE ticket extension found")
 	}
 
+	if c.config.Bugs.ExpectTicketEarlyDataInfo && newSessionTicket.maxEarlyDataSize == 0 {
+		return errors.New("tls: no ticket_early_data_info extension found")
+	}
+
+	if c.config.Bugs.ExpectNoNewSessionTicket {
+		return errors.New("tls: received unexpected NewSessionTicket")
+	}
+
+	if c.config.ClientSessionCache == nil || newSessionTicket.ticketLifetime == 0 {
+		return nil
+	}
+
+	session := &ClientSessionState{
+		sessionTicket:      newSessionTicket.ticket,
+		vers:               c.vers,
+		cipherSuite:        cipherSuite.id,
+		masterSecret:       c.resumptionSecret,
+		serverCertificates: c.peerCertificates,
+		sctList:            c.sctList,
+		ocspResponse:       c.ocspResponse,
+		ticketCreationTime: c.config.time(),
+		ticketExpiration:   c.config.time().Add(time.Duration(newSessionTicket.ticketLifetime) * time.Second),
+		ticketAgeAdd:       newSessionTicket.ticketAgeAdd,
+		maxEarlyDataSize:   newSessionTicket.maxEarlyDataSize,
+		earlyALPN:          c.clientProtocol,
+	}
+
+	cacheKey := clientSessionCacheKey(c.conn.RemoteAddr(), c.config)
+	c.config.ClientSessionCache.Put(cacheKey, session)
+	return nil
+}
+
+func (c *Conn) handlePostHandshakeMessage() error {
 	msg, err := c.readHandshake()
 	if err != nil {
 		return err
 	}
-	_, ok := msg.(*helloRequestMsg)
-	if !ok {
-		c.sendAlert(alertUnexpectedMessage)
-		return alertUnexpectedMessage
+
+	if c.vers < VersionTLS13 {
+		if !c.isClient {
+			c.sendAlert(alertUnexpectedMessage)
+			return errors.New("tls: unexpected post-handshake message")
+		}
+
+		_, ok := msg.(*helloRequestMsg)
+		if !ok {
+			c.sendAlert(alertUnexpectedMessage)
+			return alertUnexpectedMessage
+		}
+
+		c.handshakeComplete = false
+		return c.Handshake()
 	}
 
-	return c.Handshake()
+	if c.isClient {
+		if newSessionTicket, ok := msg.(*newSessionTicketMsg); ok {
+			return c.processTLS13NewSessionTicket(newSessionTicket, c.cipherSuite)
+		}
+	}
+
+	if keyUpdate, ok := msg.(*keyUpdateMsg); ok {
+		c.in.doKeyUpdate(c, false)
+		if keyUpdate.keyUpdateRequest == keyUpdateRequested {
+			c.keyUpdateRequested = true
+		}
+		return nil
+	}
+
+	// TODO(davidben): Add support for KeyUpdate.
+	c.sendAlert(alertUnexpectedMessage)
+	return alertUnexpectedMessage
 }
 
 func (c *Conn) Renegotiate() error {
@@ -1206,6 +1510,7 @@
 			helloReq = c.config.Bugs.BadHelloRequest
 		}
 		c.writeRecord(recordTypeHandshake, helloReq)
+		c.flushHandshake()
 	}
 
 	c.handshakeComplete = false
@@ -1232,9 +1537,9 @@
 				return 0, err
 			}
 			if c.hand.Len() > 0 {
-				// We received handshake bytes, indicating the
-				// start of a renegotiation.
-				if err := c.handleRenegotiation(); err != nil {
+				// We received handshake bytes, indicating a
+				// post-handshake message.
+				if err := c.handlePostHandshakeMessage(); err != nil {
 					return 0, err
 				}
 				continue
@@ -1284,7 +1589,16 @@
 	c.handshakeMutex.Lock()
 	defer c.handshakeMutex.Unlock()
 	if c.handshakeComplete && !c.config.Bugs.NoCloseNotify {
-		alertErr = c.sendAlert(alertCloseNotify)
+		alert := alertCloseNotify
+		if c.config.Bugs.SendAlertOnShutdown != 0 {
+			alert = c.config.Bugs.SendAlertOnShutdown
+		}
+		alertErr = c.sendAlert(alert)
+		// Clear local alerts when sending alerts so we continue to wait
+		// for the peer rather than closing the socket early.
+		if opErr, ok := alertErr.(*net.OpError); ok && opErr.Op == "local error" {
+			alertErr = nil
+		}
 	}
 
 	// Consume a close_notify from the peer if one hasn't been received
@@ -1363,7 +1677,8 @@
 		state.SRTPProtectionProfile = c.srtpProtectionProfile
 		state.TLSUnique = c.firstFinished[:]
 		state.SCTList = c.sctList
-		state.ClientCertSignatureHash = c.clientCertSignatureHash
+		state.PeerSignatureAlgorithm = c.peerSignatureAlgorithm
+		state.CurveID = c.curveID
 	}
 
 	return state
@@ -1402,6 +1717,12 @@
 		return nil, errors.New("tls: handshake has not yet been performed")
 	}
 
+	if c.vers >= VersionTLS13 {
+		// TODO(davidben): What should we do with useContext? See
+		// https://github.com/tlswg/tls13-spec/issues/546
+		return hkdfExpandLabel(c.cipherSuite.hash(), c.exporterSecret, label, context, length), nil
+	}
+
 	seedLen := len(c.clientRandom) + len(c.serverRandom)
 	if useContext {
 		seedLen += 2 + len(context)
@@ -1414,7 +1735,7 @@
 		seed = append(seed, context...)
 	}
 	result := make([]byte, length)
-	prfForVersion(c.vers, c.cipherSuite)(result, c.masterSecret[:], label, seed)
+	prfForVersion(c.vers, c.cipherSuite)(result, c.exporterSecret, label, seed)
 	return result, nil
 }
 
@@ -1432,3 +1753,96 @@
 	}
 	return false
 }
+
+func (c *Conn) SendNewSessionTicket() error {
+	if c.isClient || c.vers < VersionTLS13 {
+		return errors.New("tls: cannot send post-handshake NewSessionTicket")
+	}
+
+	var peerCertificatesRaw [][]byte
+	for _, cert := range c.peerCertificates {
+		peerCertificatesRaw = append(peerCertificatesRaw, cert.Raw)
+	}
+
+	addBuffer := make([]byte, 4)
+	_, err := io.ReadFull(c.config.rand(), addBuffer)
+	if err != nil {
+		c.sendAlert(alertInternalError)
+		return errors.New("tls: short read from Rand: " + err.Error())
+	}
+	ticketAgeAdd := uint32(addBuffer[3])<<24 | uint32(addBuffer[2])<<16 | uint32(addBuffer[1])<<8 | uint32(addBuffer[0])
+
+	// TODO(davidben): Allow configuring these values.
+	m := &newSessionTicketMsg{
+		version:                c.vers,
+		ticketLifetime:         uint32(24 * time.Hour / time.Second),
+		duplicateEarlyDataInfo: c.config.Bugs.DuplicateTicketEarlyDataInfo,
+		customExtension:        c.config.Bugs.CustomTicketExtension,
+		ticketAgeAdd:           ticketAgeAdd,
+		maxEarlyDataSize:       c.config.MaxEarlyDataSize,
+	}
+
+	if c.config.Bugs.SendTicketLifetime != 0 {
+		m.ticketLifetime = uint32(c.config.Bugs.SendTicketLifetime / time.Second)
+	}
+
+	state := sessionState{
+		vers:               c.vers,
+		cipherSuite:        c.cipherSuite.id,
+		masterSecret:       c.resumptionSecret,
+		certificates:       peerCertificatesRaw,
+		ticketCreationTime: c.config.time(),
+		ticketExpiration:   c.config.time().Add(time.Duration(m.ticketLifetime) * time.Second),
+		ticketAgeAdd:       uint32(addBuffer[3])<<24 | uint32(addBuffer[2])<<16 | uint32(addBuffer[1])<<8 | uint32(addBuffer[0]),
+		earlyALPN:          []byte(c.clientProtocol),
+	}
+
+	if !c.config.Bugs.SendEmptySessionTicket {
+		var err error
+		m.ticket, err = c.encryptTicket(&state)
+		if err != nil {
+			return err
+		}
+	}
+	c.out.Lock()
+	defer c.out.Unlock()
+	_, err = c.writeRecord(recordTypeHandshake, m.marshal())
+	return err
+}
+
+func (c *Conn) SendKeyUpdate(keyUpdateRequest byte) error {
+	c.out.Lock()
+	defer c.out.Unlock()
+	return c.sendKeyUpdateLocked(keyUpdateRequest)
+}
+
+func (c *Conn) sendKeyUpdateLocked(keyUpdateRequest byte) error {
+	if c.vers < VersionTLS13 {
+		return errors.New("tls: attempted to send KeyUpdate before TLS 1.3")
+	}
+
+	m := keyUpdateMsg{
+		keyUpdateRequest: keyUpdateRequest,
+	}
+	if _, err := c.writeRecord(recordTypeHandshake, m.marshal()); err != nil {
+		return err
+	}
+	if err := c.flushHandshake(); err != nil {
+		return err
+	}
+	c.out.doKeyUpdate(c, true)
+	return nil
+}
+
+func (c *Conn) sendFakeEarlyData(len int) error {
+	// Assemble a fake early data record. This does not use writeRecord
+	// because the record layer may be using different keys at this point.
+	payload := make([]byte, 5+len)
+	payload[0] = byte(recordTypeApplicationData)
+	payload[1] = 3
+	payload[2] = 1
+	payload[3] = byte(len >> 8)
+	payload[4] = byte(len)
+	_, err := c.conn.Write(payload)
+	return err
+}
diff --git a/src/ssl/test/runner/deterministic.go b/src/ssl/test/runner/deterministic.go
new file mode 100644
index 0000000..2b71076
--- /dev/null
+++ b/src/ssl/test/runner/deterministic.go
@@ -0,0 +1,37 @@
+// Copyright (c) 2016, Google Inc.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+package runner
+
+import (
+	"encoding/binary"
+)
+
+// Use a different key from crypto/rand/deterministic.c.
+var deterministicRandKey = []byte("runner deterministic key 0123456")
+
+type deterministicRand struct {
+	numCalls uint64
+}
+
+func (d *deterministicRand) Read(buf []byte) (int, error) {
+	for i := range buf {
+		buf[i] = 0
+	}
+	var nonce [12]byte
+	binary.LittleEndian.PutUint64(nonce[:8], d.numCalls)
+	chaCha20(buf, buf, deterministicRandKey, nonce[:], 0)
+	d.numCalls++
+	return len(buf), nil
+}
diff --git a/src/ssl/test/runner/dtls.go b/src/ssl/test/runner/dtls.go
index c3ee521..e273bc7 100644
--- a/src/ssl/test/runner/dtls.go
+++ b/src/ssl/test/runner/dtls.go
@@ -25,16 +25,42 @@
 
 func versionToWire(vers uint16, isDTLS bool) uint16 {
 	if isDTLS {
-		return ^(vers - 0x0201)
+		switch vers {
+		case VersionTLS12:
+			return 0xfefd
+		case VersionTLS10:
+			return 0xfeff
+		}
+	} else {
+		switch vers {
+		case VersionSSL30, VersionTLS10, VersionTLS11, VersionTLS12:
+			return vers
+		case VersionTLS13:
+			return tls13DraftVersion
+		}
 	}
-	return vers
+
+	panic("unknown version")
 }
 
-func wireToVersion(vers uint16, isDTLS bool) uint16 {
+func wireToVersion(vers uint16, isDTLS bool) (uint16, bool) {
 	if isDTLS {
-		return ^vers + 0x0201
+		switch vers {
+		case 0xfefd:
+			return VersionTLS12, true
+		case 0xfeff:
+			return VersionTLS10, true
+		}
+	} else {
+		switch vers {
+		case VersionSSL30, VersionTLS10, VersionTLS11, VersionTLS12:
+			return vers, true
+		case tls13DraftVersion:
+			return VersionTLS13, true
+		}
 	}
-	return vers
+
+	return 0, false
 }
 
 func (c *Conn) dtlsDoReadRecord(want recordType) (recordType, *block, error) {
@@ -46,6 +72,7 @@
 	b := c.rawInput
 
 	// Read a new packet only if the current one is empty.
+	var newPacket bool
 	if len(b.data) == 0 {
 		// Pick some absurdly large buffer size.
 		b.resize(maxCiphertext + recordHeaderLen)
@@ -57,6 +84,7 @@
 			return 0, nil, fmt.Errorf("dtls: exceeded maximum packet length")
 		}
 		c.rawInput.resize(n)
+		newPacket = true
 	}
 
 	// Read out one record.
@@ -68,16 +96,22 @@
 		return 0, nil, errors.New("dtls: failed to read record header")
 	}
 	typ := recordType(b.data[0])
-	vers := wireToVersion(uint16(b.data[1])<<8|uint16(b.data[2]), c.isDTLS)
-	if c.haveVers {
-		if vers != c.vers {
-			c.sendAlert(alertProtocolVersion)
-			return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: received record with version %x when expecting version %x", vers, c.vers))
-		}
-	} else {
-		if expect := c.config.Bugs.ExpectInitialRecordVersion; expect != 0 && vers != expect {
-			c.sendAlert(alertProtocolVersion)
-			return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: received record with version %x when expecting version %x", vers, expect))
+	vers := uint16(b.data[1])<<8 | uint16(b.data[2])
+	// Alerts sent near version negotiation do not have a well-defined
+	// record-layer version prior to TLS 1.3. (In TLS 1.3, the record-layer
+	// version is irrelevant.)
+	if typ != recordTypeAlert {
+		if c.haveVers {
+			if wireVers := versionToWire(c.vers, c.isDTLS); vers != wireVers {
+				c.sendAlert(alertProtocolVersion)
+				return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: received record with version %x when expecting version %x", vers, wireVers))
+			}
+		} else {
+			// Pre-version-negotiation alerts may be sent with any version.
+			if expect := c.config.Bugs.ExpectInitialRecordVersion; expect != 0 && vers != expect {
+				c.sendAlert(alertProtocolVersion)
+				return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: received record with version %x when expecting version %x", vers, expect))
+			}
 		}
 	}
 	epoch := b.data[3:5]
@@ -103,11 +137,24 @@
 
 	// Process message.
 	b, c.rawInput = c.in.splitBlock(b, recordHeaderLen+n)
-	ok, off, err := c.in.decrypt(b)
+	ok, off, _, alertValue := c.in.decrypt(b)
 	if !ok {
-		c.in.setErrorLocked(c.sendAlert(err))
+		// A real DTLS implementation would silently ignore bad records,
+		// but we want to notice errors from the implementation under
+		// test.
+		return 0, nil, c.in.setErrorLocked(c.sendAlert(alertValue))
 	}
 	b.off = off
+
+	// TODO(nharper): Once DTLS 1.3 is defined, handle the extra
+	// parameter from decrypt.
+
+	// Require that ChangeCipherSpec always share a packet with either the
+	// previous or next handshake message.
+	if newPacket && typ == recordTypeChangeCipherSpec && c.rawInput == nil {
+		return 0, nil, c.in.setErrorLocked(fmt.Errorf("dtls: ChangeCipherSpec not packed together with Finished"))
+	}
+
 	return typ, b, nil
 }
 
@@ -124,7 +171,30 @@
 func (c *Conn) dtlsWriteRecord(typ recordType, data []byte) (n int, err error) {
 	if typ != recordTypeHandshake {
 		// Only handshake messages are fragmented.
-		return c.dtlsWriteRawRecord(typ, data)
+		n, err = c.dtlsWriteRawRecord(typ, data)
+		if err != nil {
+			return
+		}
+
+		if typ == recordTypeChangeCipherSpec {
+			err = c.out.changeCipherSpec(c.config)
+			if err != nil {
+				// Cannot call sendAlert directly,
+				// because we already hold c.out.Mutex.
+				c.tmp[0] = alertLevelError
+				c.tmp[1] = byte(err.(alert))
+				c.writeRecord(recordTypeAlert, c.tmp[0:2])
+				return n, c.out.setErrorLocked(&net.OpError{Op: "local error", Err: err})
+			}
+		}
+		return
+	}
+
+	if c.out.cipher == nil && c.config.Bugs.StrayChangeCipherSpec {
+		_, err = c.dtlsWriteRawRecord(recordTypeChangeCipherSpec, []byte{1})
+		if err != nil {
+			return
+		}
 	}
 
 	maxLen := c.config.Bugs.MaxHandshakeRecordLength
@@ -198,10 +268,6 @@
 }
 
 func (c *Conn) dtlsFlushHandshake() error {
-	if !c.isDTLS {
-		return nil
-	}
-
 	// This is a test-only DTLS implementation, so there is no need to
 	// retain |c.pendingFragments| for a future retransmit.
 	var fragments [][]byte
@@ -214,6 +280,12 @@
 			tmp[i] = fragments[perm[i]]
 		}
 		fragments = tmp
+	} else if c.config.Bugs.ReverseHandshakeFragments {
+		tmp := make([][]byte, len(fragments))
+		for i := range tmp {
+			tmp[i] = fragments[len(fragments)-i-1]
+		}
+		fragments = tmp
 	}
 
 	maxRecordLen := c.config.Bugs.PackHandshakeFragments
@@ -289,10 +361,12 @@
 			// use the sequence number as the nonce.
 			explicitIVIsSeq = true
 		}
-	} else if c.out.cipher != nil {
+	} else if _, ok := c.out.cipher.(nullCipher); !ok && c.out.cipher != nil {
 		panic("Unknown cipher")
 	}
 	b.resize(recordHeaderLen + explicitIVLen + len(data))
+	// TODO(nharper): DTLS 1.3 will likely need to set this to
+	// recordTypeApplicationData if c.out.cipher != nil.
 	b.data[0] = byte(typ)
 	vers := c.vers
 	if vers == 0 {
@@ -318,7 +392,7 @@
 		}
 	}
 	copy(b.data[recordHeaderLen+explicitIVLen:], data)
-	c.out.encrypt(b, explicitIVLen)
+	c.out.encrypt(b, explicitIVLen, typ)
 	return
 }
 
@@ -335,18 +409,6 @@
 	n = len(data)
 
 	c.out.freeBlock(b)
-
-	if typ == recordTypeChangeCipherSpec {
-		err = c.out.changeCipherSpec(c.config)
-		if err != nil {
-			// Cannot call sendAlert directly,
-			// because we already hold c.out.Mutex.
-			c.tmp[0] = alertLevelError
-			c.tmp[1] = byte(err.(alert))
-			c.writeRecord(recordTypeAlert, c.tmp[0:2])
-			return n, c.out.setErrorLocked(&net.OpError{Op: "local error", Err: err})
-		}
-	}
 	return
 }
 
diff --git a/src/ssl/test/runner/ecdsa_key.pem b/src/ssl/test/runner/ecdsa_key.pem
deleted file mode 100644
index b9116f0..0000000
--- a/src/ssl/test/runner/ecdsa_key.pem
+++ /dev/null
@@ -1,8 +0,0 @@
------BEGIN EC PARAMETERS-----
-BggqhkjOPQMBBw==
------END EC PARAMETERS-----
------BEGIN EC PRIVATE KEY-----
-MHcCAQEEIAcPCHJ61KBKnN1ZyU2JaHcItW/JXTB3DujRyc4Ki7RqoAoGCCqGSM49
-AwEHoUQDQgAE5itp4r9ln5e+Lx4NlIpM1Zdrt6keDUb73ampHp3culoB59aXqAoY
-+cPEox5W4nyDSNsWGhz1HX7xlC1Lz3IiwQ==
------END EC PRIVATE KEY-----
diff --git a/src/ssl/test/runner/ecdsa_p224_cert.pem b/src/ssl/test/runner/ecdsa_p224_cert.pem
new file mode 100644
index 0000000..29246a2
--- /dev/null
+++ b/src/ssl/test/runner/ecdsa_p224_cert.pem
@@ -0,0 +1,12 @@
+-----BEGIN CERTIFICATE-----
+MIIBvjCCAWygAwIBAgIJAPlkrPTq4HgnMAoGCCqGSM49BAMCMEUxCzAJBgNVBAYT
+AkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRn
+aXRzIFB0eSBMdGQwHhcNMTcwMjI3MjAxOTIzWhcNMTkwMjI3MjAxOTIzWjBFMQsw
+CQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50ZXJu
+ZXQgV2lkZ2l0cyBQdHkgTHRkME4wEAYHKoZIzj0CAQYFK4EEACEDOgAE6dul6dL0
++CyooFiKK4V+EYNYPbMZoLTxRcjRgrw3db6QzBAviDSxKADTVuyRmaVC74Mf6boB
+HDmjUDBOMB0GA1UdDgQWBBSMtlkUJ7SCZ4zRqkjXMWvOebSgpTAfBgNVHSMEGDAW
+gBSMtlkUJ7SCZ4zRqkjXMWvOebSgpTAMBgNVHRMEBTADAQH/MAoGCCqGSM49BAMC
+A0AAMD0CHHolWPktSLbVMy9ukQUb2E7+Jb3hcNFqAXh47pYCHQC+jv2EE6oOEZ9F
+tLkFLtap71+83P0NUEJX4Etu
+-----END CERTIFICATE-----
diff --git a/src/ssl/test/runner/ecdsa_p224_key.pem b/src/ssl/test/runner/ecdsa_p224_key.pem
new file mode 100644
index 0000000..cfe411b
--- /dev/null
+++ b/src/ssl/test/runner/ecdsa_p224_key.pem
@@ -0,0 +1,5 @@
+-----BEGIN EC PRIVATE KEY-----
+MGgCAQEEHGi+rNLi+gHJqmRRtdlLBOw1WYv7H/VnlYGAZ0+gBwYFK4EEACGhPAM6
+AATp26Xp0vT4LKigWIorhX4Rg1g9sxmgtPFFyNGCvDd1vpDMEC+INLEoANNW7JGZ
+pULvgx/pugEcOQ==
+-----END EC PRIVATE KEY-----
diff --git a/src/ssl/test/runner/ecdsa_cert.pem b/src/ssl/test/runner/ecdsa_p256_cert.pem
similarity index 100%
rename from src/ssl/test/runner/ecdsa_cert.pem
rename to src/ssl/test/runner/ecdsa_p256_cert.pem
diff --git a/src/ssl/test/runner/ecdsa_p256_key.pem b/src/ssl/test/runner/ecdsa_p256_key.pem
new file mode 100644
index 0000000..bce6a1e
--- /dev/null
+++ b/src/ssl/test/runner/ecdsa_p256_key.pem
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgBw8IcnrUoEqc3VnJ
+TYlodwi1b8ldMHcO6NHJzgqLtGqhRANCAATmK2niv2Wfl74vHg2UikzVl2u3qR4N
+Rvvdqakendy6WgHn1peoChj5w8SjHlbifINI2xYaHPUdfvGULUvPciLB
+-----END PRIVATE KEY-----
diff --git a/src/ssl/test/runner/ecdsa_p384_cert.pem b/src/ssl/test/runner/ecdsa_p384_cert.pem
new file mode 100644
index 0000000..1fd3fec
--- /dev/null
+++ b/src/ssl/test/runner/ecdsa_p384_cert.pem
@@ -0,0 +1,15 @@
+-----BEGIN CERTIFICATE-----
+MIICZTCCAeugAwIBAgIJAN+/LubpDwxNMAkGByqGSM49BAEwRTELMAkGA1UEBhMC
+QVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdp
+dHMgUHR5IEx0ZDAeFw0xNjA3MDkwMDAxMzJaFw0xNjA4MDgwMDAxMzJaMEUxCzAJ
+BgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5l
+dCBXaWRnaXRzIFB0eSBMdGQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQOdTJNqxiZ
++B68tCZV4GEJwDJ18jK9gFzvefcEAQluBijjrMjflL+RZAT64ExWzedRMp9PD9CW
+Tz9hG/Kz4q/l952YsIhy7LTGXzwy7549WUOi+N3aW8psDjtwzWNZXqWjgacwgaQw
+HQYDVR0OBBYEFKmYPjADcOlogOMU6D9wlftIWMj6MHUGA1UdIwRuMGyAFKmYPjAD
+cOlogOMU6D9wlftIWMj6oUmkRzBFMQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29t
+ZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkggkA378u
+5ukPDE0wDAYDVR0TBAUwAwEB/zAJBgcqhkjOPQQBA2kAMGYCMQDTfL0OkRGnS5Ze
+tsxagAuZqM2Zyv5a2g7u6eFLCx2rpTuQndWOtEnmVo3wjTDtkDcCMQCg+05XSqEF
+cqxdXMZJMhqj2jS+tWucdgDstp/1KzJkbsupSjBzIycjVBKLdRwtNg8=
+-----END CERTIFICATE-----
diff --git a/src/ssl/test/runner/ecdsa_p384_key.pem b/src/ssl/test/runner/ecdsa_p384_key.pem
new file mode 100644
index 0000000..d72e104
--- /dev/null
+++ b/src/ssl/test/runner/ecdsa_p384_key.pem
@@ -0,0 +1,6 @@
+-----BEGIN PRIVATE KEY-----
+MIG2AgEAMBAGByqGSM49AgEGBSuBBAAiBIGeMIGbAgEBBDCVFIFNZ6y5EijVMUuD
+W+WJsQRAVxsZ+6ge1Nez2IoOr3+APs6+fj130OJinFATXa2hZANiAAQOdTJNqxiZ
++B68tCZV4GEJwDJ18jK9gFzvefcEAQluBijjrMjflL+RZAT64ExWzedRMp9PD9CW
+Tz9hG/Kz4q/l952YsIhy7LTGXzwy7549WUOi+N3aW8psDjtwzWNZXqU=
+-----END PRIVATE KEY-----
diff --git a/src/ssl/test/runner/ecdsa_p521_cert.pem b/src/ssl/test/runner/ecdsa_p521_cert.pem
new file mode 100644
index 0000000..8b9a1e8
--- /dev/null
+++ b/src/ssl/test/runner/ecdsa_p521_cert.pem
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrzCCAhGgAwIBAgIJAMZT7oSqTg/lMAkGByqGSM49BAEwRTELMAkGA1UEBhMC
+QVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdp
+dHMgUHR5IEx0ZDAeFw0xNjA3MDkwMDAwNTBaFw0xNjA4MDgwMDAwNTBaMEUxCzAJ
+BgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5l
+dCBXaWRnaXRzIFB0eSBMdGQwgZswEAYHKoZIzj0CAQYFK4EEACMDgYYABAFD0TiZ
+InCoCYDI66FvoaZ0tniUhaNk2YnjEPikfmYHDwstbqkTEqnGAq3pKF2y/MHTBXFd
+E0KcFOPs5Ju8EgIcqwGvCkwHPmZtvvOrf+nJNHdm1gZfBUy09f3fVe/mHwfM2++H
+dz54nHKxtQqvdafhmMV77R/rBuI24MLKbMihxRgQKaOBpzCBpDAdBgNVHQ4EFgQU
+mLWm6ZtGfvih6iFx0+duYfHjGsYwdQYDVR0jBG4wbIAUmLWm6ZtGfvih6iFx0+du
+YfHjGsahSaRHMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEw
+HwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGSCCQDGU+6Eqk4P5TAMBgNV
+HRMEBTADAQH/MAkGByqGSM49BAEDgYwAMIGIAkIBL/oEXMMQH9fefVd8onvgQbWI
+/CJXYE+kLO15gO8satasGutVpXtYGeP8gZeuHrq+jWxzj7dGM7YzkW0pAu+wOAkC
+QgFJSvKFcmbreLIjuwYik5aXeaUnTCvTQumG07cF0hZRgCf/kTxxmu2ffRoGCDTz
+XoPqlxwaO7K+gaAS//CvR0E3lw==
+-----END CERTIFICATE-----
diff --git a/src/ssl/test/runner/ecdsa_p521_key.pem b/src/ssl/test/runner/ecdsa_p521_key.pem
new file mode 100644
index 0000000..a8b1006
--- /dev/null
+++ b/src/ssl/test/runner/ecdsa_p521_key.pem
@@ -0,0 +1,7 @@
+-----BEGIN PRIVATE KEY-----
+MIHtAgEAMBAGByqGSM49AgEGBSuBBAAjBIHVMIHSAgEBBEFqpd7S4UQqO2MJSylA
+8Ufq/qbUuebEJY6t1Oz76JZ0u0k+NdmmujWjULcP4thAhX+xitUap+r86ud8FQCv
+dawUnKGBiQOBhgAEAUPROJkicKgJgMjroW+hpnS2eJSFo2TZieMQ+KR+ZgcPCy1u
+qRMSqcYCrekoXbL8wdMFcV0TQpwU4+zkm7wSAhyrAa8KTAc+Zm2+86t/6ck0d2bW
+Bl8FTLT1/d9V7+YfB8zb74d3PniccrG1Cq91p+GYxXvtH+sG4jbgwspsyKHFGBAp
+-----END PRIVATE KEY-----
diff --git a/src/ssl/test/runner/fuzzer_mode.json b/src/ssl/test/runner/fuzzer_mode.json
new file mode 100644
index 0000000..80a9bf1
--- /dev/null
+++ b/src/ssl/test/runner/fuzzer_mode.json
@@ -0,0 +1,39 @@
+{
+  "DisabledTests": {
+    "BadCBCPadding*": "Fuzzer mode has no CBC padding.",
+
+    "BadFinished-*": "Fuzzer mode ignores Finished checks.",
+    "FalseStart-BadFinished": "Fuzzer mode ignores Finished checks.",
+    "TrailingMessageData-*Finished*": "Fuzzer mode ignores Finished checks.",
+
+    "DTLSIgnoreBadPackets*": "Fuzzer mode has no bad packets.",
+    "TLSFatalBadPackets": "Fuzzer mode has no bad packets.",
+    "*-BadRecord": "Fuzzer mode has no bad packets.",
+
+    "BadRSAClientKeyExchange*": "Fuzzer mode does not notice a bad premaster secret.",
+
+    "TrailingMessageData-TLS13-ServerHello": "Fuzzer mode will not read the peer's alert as a MAC error",
+    "UnexpectedUnencryptedExtension-Client-TLS13": "Fuzzer mode will not read the peer's alert as a MAC error",
+    "UnknownUnencryptedExtension-Client-TLS13": "Fuzzer mode will not read the peer's alert as a MAC error",
+    "WrongMessageType-TLS13-ServerHello": "Fuzzer mode will not read the peer's alert as a MAC error",
+
+    "BadECDSA-*": "Fuzzer mode always accepts a signature.",
+    "*-InvalidSignature-*": "Fuzzer mode always accepts a signature.",
+    "*Auth-Verify-RSA-PKCS1-*-TLS13": "Fuzzer mode always accepts a signature.",
+    "*Auth-Verify-ECDSA-SHA1-TLS13": "Fuzzer mode always accepts a signature.",
+    "Verify-*Auth-SignatureType*": "Fuzzer mode always accepts a signature.",
+    "ECDSACurveMismatch-Verify-TLS13": "Fuzzer mode always accepts a signature.",
+    "InvalidChannelIDSignature-*": "Fuzzer mode always accepts a signature.",
+
+    "Resume-Server-CipherNotPreferred*": "Fuzzer mode does not encrypt tickets.",
+    "Resume-Server-DeclineBadCipher*": "Fuzzer mode does not encrypt tickets.",
+    "Resume-Server-DeclineCrossVersion*": "Fuzzer mode does not encrypt tickets.",
+    "TicketCallback-SingleCall-*": "Fuzzer mode does not encrypt tickets.",
+    "CorruptTicket-*": "Fuzzer mode does not encrypt tickets.",
+    "ShimTicketRewritable": "Fuzzer mode does not encrypt tickets.",
+
+    "Resume-Server-*Binder*": "Fuzzer mode does not check binders.",
+
+    "SkipEarlyData*": "Trial decryption does not work with the NULL cipher."
+  }
+}
diff --git a/src/ssl/test/runner/handshake_client.go b/src/ssl/test/runner/handshake_client.go
index 64630ba..d73722c 100644
--- a/src/ssl/test/runner/handshake_client.go
+++ b/src/ssl/test/runner/handshake_client.go
@@ -6,18 +6,19 @@
 
 import (
 	"bytes"
+	"crypto"
 	"crypto/ecdsa"
 	"crypto/elliptic"
 	"crypto/rsa"
 	"crypto/subtle"
 	"crypto/x509"
-	"encoding/asn1"
 	"errors"
 	"fmt"
 	"io"
 	"math/big"
 	"net"
 	"strconv"
+	"time"
 )
 
 type clientHandshakeState struct {
@@ -26,6 +27,7 @@
 	hello         *clientHelloMsg
 	suite         *cipherSuite
 	finishedHash  finishedHash
+	keyShares     map[CurveID]ecdhCurve
 	masterSecret  []byte
 	session       *ClientSessionState
 	finishedBytes []byte
@@ -55,33 +57,38 @@
 		return errors.New("tls: NextProtos values too large")
 	}
 
+	minVersion := c.config.minVersion(c.isDTLS)
+	maxVersion := c.config.maxVersion(c.isDTLS)
 	hello := &clientHelloMsg{
 		isDTLS:                  c.isDTLS,
-		vers:                    c.config.maxVersion(),
+		vers:                    versionToWire(maxVersion, c.isDTLS),
 		compressionMethods:      []uint8{compressionNone},
 		random:                  make([]byte, 32),
-		ocspStapling:            true,
-		sctListSupported:        true,
+		ocspStapling:            !c.config.Bugs.NoOCSPStapling,
+		sctListSupported:        !c.config.Bugs.NoSignedCertificateTimestamps,
 		serverName:              c.config.ServerName,
 		supportedCurves:         c.config.curvePreferences(),
+		pskKEModes:              []byte{pskDHEKEMode},
 		supportedPoints:         []uint8{pointFormatUncompressed},
 		nextProtoNeg:            len(c.config.NextProtos) > 0,
 		secureRenegotiation:     []byte{},
 		alpnProtocols:           c.config.NextProtos,
 		duplicateExtension:      c.config.Bugs.DuplicateExtension,
 		channelIDSupported:      c.config.ChannelID != nil,
-		npnLast:                 c.config.Bugs.SwapNPNAndALPN,
-		extendedMasterSecret:    c.config.maxVersion() >= VersionTLS10,
+		npnAfterAlpn:            c.config.Bugs.SwapNPNAndALPN,
+		extendedMasterSecret:    maxVersion >= VersionTLS10,
 		srtpProtectionProfiles:  c.config.SRTPProtectionProfiles,
 		srtpMasterKeyIdentifier: c.config.Bugs.SRTPMasterKeyIdentifer,
 		customExtension:         c.config.Bugs.CustomExtension,
+		pskBinderFirst:          c.config.Bugs.PSKBinderFirst,
 	}
 
-	if c.config.Bugs.SendClientVersion != 0 {
-		hello.vers = c.config.Bugs.SendClientVersion
+	disableEMS := c.config.Bugs.NoExtendedMasterSecret
+	if c.cipherSuite != nil {
+		disableEMS = c.config.Bugs.NoExtendedMasterSecretOnRenegotiation
 	}
 
-	if c.config.Bugs.NoExtendedMasterSecret {
+	if disableEMS {
 		hello.extendedMasterSecret = false
 	}
 
@@ -89,6 +96,18 @@
 		hello.supportedCurves = nil
 	}
 
+	if len(c.config.Bugs.SendPSKKeyExchangeModes) != 0 {
+		hello.pskKEModes = c.config.Bugs.SendPSKKeyExchangeModes
+	}
+
+	if c.config.Bugs.SendCompressionMethods != nil {
+		hello.compressionMethods = c.config.Bugs.SendCompressionMethods
+	}
+
+	if c.config.Bugs.SendSupportedPointFormats != nil {
+		hello.supportedPoints = c.config.Bugs.SendSupportedPointFormats
+	}
+
 	if len(c.clientVerify) > 0 && !c.config.Bugs.EmptyRenegotiationInfo {
 		if c.config.Bugs.BadRenegotiationInfo {
 			hello.secureRenegotiation = append(hello.secureRenegotiation, c.clientVerify...)
@@ -102,6 +121,48 @@
 		hello.secureRenegotiation = nil
 	}
 
+	var keyShares map[CurveID]ecdhCurve
+	if maxVersion >= VersionTLS13 {
+		keyShares = make(map[CurveID]ecdhCurve)
+		hello.hasKeyShares = true
+		hello.trailingKeyShareData = c.config.Bugs.TrailingKeyShareData
+		curvesToSend := c.config.defaultCurves()
+		for _, curveID := range hello.supportedCurves {
+			if !curvesToSend[curveID] {
+				continue
+			}
+			curve, ok := curveForCurveID(curveID)
+			if !ok {
+				continue
+			}
+			publicKey, err := curve.offer(c.config.rand())
+			if err != nil {
+				return err
+			}
+
+			if c.config.Bugs.SendCurve != 0 {
+				curveID = c.config.Bugs.SendCurve
+			}
+			if c.config.Bugs.InvalidECDHPoint {
+				publicKey[0] ^= 0xff
+			}
+
+			hello.keyShares = append(hello.keyShares, keyShareEntry{
+				group:       curveID,
+				keyExchange: publicKey,
+			})
+			keyShares[curveID] = curve
+
+			if c.config.Bugs.DuplicateKeyShares {
+				hello.keyShares = append(hello.keyShares, hello.keyShares[len(hello.keyShares)-1])
+			}
+		}
+
+		if c.config.Bugs.MissingKeyShare {
+			hello.hasKeyShares = false
+		}
+	}
+
 	possibleCipherSuites := c.config.cipherSuites()
 	hello.cipherSuites = make([]uint16, 0, len(possibleCipherSuites))
 
@@ -113,11 +174,11 @@
 			}
 			// Don't advertise TLS 1.2-only cipher suites unless
 			// we're attempting TLS 1.2.
-			if hello.vers < VersionTLS12 && suite.flags&suiteTLS12 != 0 {
+			if maxVersion < VersionTLS12 && suite.flags&suiteTLS12 != 0 {
 				continue
 			}
-			// Don't advertise non-DTLS cipher suites on DTLS.
-			if c.isDTLS && suite.flags&suiteNoDTLS != 0 && !c.config.Bugs.EnableAllCiphersInDTLS {
+			// Don't advertise non-DTLS cipher suites in DTLS.
+			if c.isDTLS && suite.flags&suiteNoDTLS != 0 {
 				continue
 			}
 			hello.cipherSuites = append(hello.cipherSuites, suiteId)
@@ -125,6 +186,10 @@
 		}
 	}
 
+	if c.config.Bugs.AdvertiseAllConfiguredCiphers {
+		hello.cipherSuites = possibleCipherSuites
+	}
+
 	if c.config.Bugs.SendRenegotiationSCSV {
 		hello.cipherSuites = append(hello.cipherSuites, renegotiationSCSV)
 	}
@@ -139,8 +204,8 @@
 		return errors.New("tls: short read from Rand: " + err.Error())
 	}
 
-	if hello.vers >= VersionTLS12 && !c.config.Bugs.NoSignatureAndHashes {
-		hello.signatureAndHashes = c.config.signatureAndHashesForClient()
+	if maxVersion >= VersionTLS12 && !c.config.Bugs.NoSignatureAlgorithms {
+		hello.signatureAlgorithms = c.config.verifySignatureAlgorithms()
 	}
 
 	var session *ClientSessionState
@@ -153,6 +218,8 @@
 		// Try to resume a previously negotiated TLS session, if
 		// available.
 		cacheKey = clientSessionCacheKey(c.conn.RemoteAddr(), c.config)
+		// TODO(nharper): Support storing more than one session
+		// ticket for TLS 1.3.
 		candidateSession, ok := sessionCache.Get(cacheKey)
 		if ok {
 			ticketOk := !c.config.SessionTicketsDisabled || candidateSession.sessionTicket == nil
@@ -160,50 +227,118 @@
 			// Check that the ciphersuite/version used for the
 			// previous session are still valid.
 			cipherSuiteOk := false
-			for _, id := range hello.cipherSuites {
-				if id == candidateSession.cipherSuite {
-					cipherSuiteOk = true
-					break
+			if candidateSession.vers <= VersionTLS12 {
+				for _, id := range hello.cipherSuites {
+					if id == candidateSession.cipherSuite {
+						cipherSuiteOk = true
+						break
+					}
 				}
+			} else {
+				// TLS 1.3 allows the cipher to change on
+				// resumption.
+				cipherSuiteOk = true
 			}
 
-			versOk := candidateSession.vers >= c.config.minVersion() &&
-				candidateSession.vers <= c.config.maxVersion()
+			versOk := candidateSession.vers >= minVersion &&
+				candidateSession.vers <= maxVersion
 			if ticketOk && versOk && cipherSuiteOk {
 				session = candidateSession
 			}
 		}
 	}
 
-	if session != nil {
-		if session.sessionTicket != nil {
-			hello.sessionTicket = session.sessionTicket
-			if c.config.Bugs.CorruptTicket {
-				hello.sessionTicket = make([]byte, len(session.sessionTicket))
-				copy(hello.sessionTicket, session.sessionTicket)
-				if len(hello.sessionTicket) > 0 {
-					offset := 40
-					if offset > len(hello.sessionTicket) {
-						offset = len(hello.sessionTicket) - 1
-					}
-					hello.sessionTicket[offset] ^= 0x40
-				}
+	var pskCipherSuite *cipherSuite
+	if session != nil && c.config.time().Before(session.ticketExpiration) {
+		ticket := session.sessionTicket
+		if c.config.Bugs.FilterTicket != nil && len(ticket) > 0 {
+			// Copy the ticket so FilterTicket may act in-place.
+			ticket = make([]byte, len(session.sessionTicket))
+			copy(ticket, session.sessionTicket)
+
+			ticket, err = c.config.Bugs.FilterTicket(ticket)
+			if err != nil {
+				return err
 			}
-			// A random session ID is used to detect when the
-			// server accepted the ticket and is resuming a session
-			// (see RFC 5077).
-			sessionIdLen := 16
-			if c.config.Bugs.OversizedSessionId {
-				sessionIdLen = 33
-			}
-			hello.sessionId = make([]byte, sessionIdLen)
-			if _, err := io.ReadFull(c.config.rand(), hello.sessionId); err != nil {
-				c.sendAlert(alertInternalError)
-				return errors.New("tls: short read from Rand: " + err.Error())
-			}
-		} else {
-			hello.sessionId = session.sessionId
 		}
+
+		if session.vers >= VersionTLS13 || c.config.Bugs.SendBothTickets {
+			pskCipherSuite = cipherSuiteFromID(session.cipherSuite)
+			if pskCipherSuite == nil {
+				return errors.New("tls: client session cache has invalid cipher suite")
+			}
+			// TODO(nharper): Support sending more
+			// than one PSK identity.
+			ticketAge := uint32(c.config.time().Sub(session.ticketCreationTime) / time.Millisecond)
+			if c.config.Bugs.SendTicketAge != 0 {
+				ticketAge = uint32(c.config.Bugs.SendTicketAge / time.Millisecond)
+			}
+			psk := pskIdentity{
+				ticket:              ticket,
+				obfuscatedTicketAge: session.ticketAgeAdd + ticketAge,
+			}
+			hello.pskIdentities = []pskIdentity{psk}
+
+			if c.config.Bugs.ExtraPSKIdentity {
+				hello.pskIdentities = append(hello.pskIdentities, psk)
+			}
+		}
+
+		if session.vers < VersionTLS13 || c.config.Bugs.SendBothTickets {
+			if ticket != nil {
+				hello.sessionTicket = ticket
+				// A random session ID is used to detect when the
+				// server accepted the ticket and is resuming a session
+				// (see RFC 5077).
+				sessionIdLen := 16
+				if c.config.Bugs.TicketSessionIDLength != 0 {
+					sessionIdLen = c.config.Bugs.TicketSessionIDLength
+				}
+				if c.config.Bugs.EmptyTicketSessionID {
+					sessionIdLen = 0
+				}
+				hello.sessionId = make([]byte, sessionIdLen)
+				if _, err := io.ReadFull(c.config.rand(), hello.sessionId); err != nil {
+					c.sendAlert(alertInternalError)
+					return errors.New("tls: short read from Rand: " + err.Error())
+				}
+			} else {
+				hello.sessionId = session.sessionId
+			}
+		}
+	}
+
+	if maxVersion == VersionTLS13 && !c.config.Bugs.OmitSupportedVersions {
+		if hello.vers >= VersionTLS13 {
+			hello.vers = VersionTLS12
+		}
+		for version := maxVersion; version >= minVersion; version-- {
+			hello.supportedVersions = append(hello.supportedVersions, versionToWire(version, c.isDTLS))
+		}
+	}
+
+	if len(c.config.Bugs.SendSupportedVersions) > 0 {
+		hello.supportedVersions = c.config.Bugs.SendSupportedVersions
+	}
+
+	if c.config.Bugs.SendClientVersion != 0 {
+		hello.vers = c.config.Bugs.SendClientVersion
+	}
+
+	if c.config.Bugs.SendCipherSuites != nil {
+		hello.cipherSuites = c.config.Bugs.SendCipherSuites
+	}
+
+	var sendEarlyData bool
+	if len(hello.pskIdentities) > 0 && c.config.Bugs.SendEarlyData != nil {
+		hello.hasEarlyData = true
+		sendEarlyData = true
+	}
+	if c.config.Bugs.SendFakeEarlyDataLength > 0 {
+		hello.hasEarlyData = true
+	}
+	if c.config.Bugs.OmitEarlyDataExtension {
+		hello.hasEarlyData = false
 	}
 
 	var helloBytes []byte
@@ -220,14 +355,50 @@
 		helloBytes = v2Hello.marshal()
 		c.writeV2Record(helloBytes)
 	} else {
+		if len(hello.pskIdentities) > 0 {
+			generatePSKBinders(hello, pskCipherSuite, session.masterSecret, []byte{}, c.config)
+		}
 		helloBytes = hello.marshal()
-		c.writeRecord(recordTypeHandshake, helloBytes)
+
+		if c.config.Bugs.PartialClientFinishedWithClientHello {
+			// Include one byte of Finished. We can compute it
+			// without completing the handshake. This assumes we
+			// negotiate TLS 1.3 with no HelloRetryRequest or
+			// CertificateRequest.
+			toWrite := make([]byte, 0, len(helloBytes)+1)
+			toWrite = append(toWrite, helloBytes...)
+			toWrite = append(toWrite, typeFinished)
+			c.writeRecord(recordTypeHandshake, toWrite)
+		} else {
+			c.writeRecord(recordTypeHandshake, helloBytes)
+		}
 	}
-	c.dtlsFlushHandshake()
+	c.flushHandshake()
 
 	if err := c.simulatePacketLoss(nil); err != nil {
 		return err
 	}
+	if c.config.Bugs.SendEarlyAlert {
+		c.sendAlert(alertHandshakeFailure)
+	}
+	if c.config.Bugs.SendFakeEarlyDataLength > 0 {
+		c.sendFakeEarlyData(c.config.Bugs.SendFakeEarlyDataLength)
+	}
+
+	// Derive early write keys and set Conn state to allow early writes.
+	if sendEarlyData {
+		finishedHash := newFinishedHash(session.vers, pskCipherSuite)
+		finishedHash.addEntropy(session.masterSecret)
+		finishedHash.Write(helloBytes)
+		earlyTrafficSecret := finishedHash.deriveSecret(earlyTrafficLabel)
+		c.out.useTrafficSecret(session.vers, pskCipherSuite, earlyTrafficSecret, clientWrite)
+		for _, earlyData := range c.config.Bugs.SendEarlyData {
+			if _, err := c.writeRecord(recordTypeApplicationData, earlyData); err != nil {
+				return err
+			}
+		}
+	}
+
 	msg, err := c.readHandshake()
 	if err != nil {
 		return err
@@ -236,7 +407,7 @@
 	if c.isDTLS {
 		helloVerifyRequest, ok := msg.(*helloVerifyRequestMsg)
 		if ok {
-			if helloVerifyRequest.vers != VersionTLS10 {
+			if helloVerifyRequest.vers != versionToWire(VersionTLS10, c.isDTLS) {
 				// Per RFC 6347, the version field in
 				// HelloVerifyRequest SHOULD be always DTLS
 				// 1.0. Enforce this for testing purposes.
@@ -247,7 +418,7 @@
 			hello.cookie = helloVerifyRequest.cookie
 			helloBytes = hello.marshal()
 			c.writeRecord(recordTypeHandshake, helloBytes)
-			c.dtlsFlushHandshake()
+			c.flushHandshake()
 
 			if err := c.simulatePacketLoss(nil); err != nil {
 				return err
@@ -259,43 +430,135 @@
 		}
 	}
 
+	var serverWireVersion uint16
+	switch m := msg.(type) {
+	case *helloRetryRequestMsg:
+		serverWireVersion = m.vers
+	case *serverHelloMsg:
+		serverWireVersion = m.vers
+	default:
+		c.sendAlert(alertUnexpectedMessage)
+		return fmt.Errorf("tls: received unexpected message of type %T when waiting for HelloRetryRequest or ServerHello", msg)
+	}
+
+	serverVersion, ok := wireToVersion(serverWireVersion, c.isDTLS)
+	if ok {
+		ok = c.config.isSupportedVersion(serverVersion, c.isDTLS)
+	}
+	if !ok {
+		c.sendAlert(alertProtocolVersion)
+		return fmt.Errorf("tls: server selected unsupported protocol version %x", c.vers)
+	}
+	c.vers = serverVersion
+	c.haveVers = true
+
+	helloRetryRequest, haveHelloRetryRequest := msg.(*helloRetryRequestMsg)
+	var secondHelloBytes []byte
+	if haveHelloRetryRequest {
+		c.out.resetCipher()
+		if len(helloRetryRequest.cookie) > 0 {
+			hello.tls13Cookie = helloRetryRequest.cookie
+		}
+
+		if c.config.Bugs.MisinterpretHelloRetryRequestCurve != 0 {
+			helloRetryRequest.hasSelectedGroup = true
+			helloRetryRequest.selectedGroup = c.config.Bugs.MisinterpretHelloRetryRequestCurve
+		}
+		if helloRetryRequest.hasSelectedGroup {
+			var hrrCurveFound bool
+			group := helloRetryRequest.selectedGroup
+			for _, curveID := range hello.supportedCurves {
+				if group == curveID {
+					hrrCurveFound = true
+					break
+				}
+			}
+			if !hrrCurveFound || keyShares[group] != nil {
+				c.sendAlert(alertHandshakeFailure)
+				return errors.New("tls: received invalid HelloRetryRequest")
+			}
+			curve, ok := curveForCurveID(group)
+			if !ok {
+				return errors.New("tls: Unable to get curve requested in HelloRetryRequest")
+			}
+			publicKey, err := curve.offer(c.config.rand())
+			if err != nil {
+				return err
+			}
+			keyShares[group] = curve
+			hello.keyShares = []keyShareEntry{{
+				group:       group,
+				keyExchange: publicKey,
+			}}
+		}
+
+		if c.config.Bugs.SecondClientHelloMissingKeyShare {
+			hello.hasKeyShares = false
+		}
+
+		hello.hasEarlyData = c.config.Bugs.SendEarlyDataOnSecondClientHello
+		hello.raw = nil
+
+		if len(hello.pskIdentities) > 0 {
+			generatePSKBinders(hello, pskCipherSuite, session.masterSecret, append(helloBytes, helloRetryRequest.marshal()...), c.config)
+		}
+		secondHelloBytes = hello.marshal()
+
+		if c.config.Bugs.InterleaveEarlyData {
+			c.sendFakeEarlyData(4)
+			c.writeRecord(recordTypeHandshake, secondHelloBytes[:16])
+			c.sendFakeEarlyData(4)
+			c.writeRecord(recordTypeHandshake, secondHelloBytes[16:])
+		} else {
+			c.writeRecord(recordTypeHandshake, secondHelloBytes)
+		}
+		c.flushHandshake()
+
+		if c.config.Bugs.SendEarlyDataOnSecondClientHello {
+			c.sendFakeEarlyData(4)
+		}
+
+		msg, err = c.readHandshake()
+		if err != nil {
+			return err
+		}
+	}
+
 	serverHello, ok := msg.(*serverHelloMsg)
 	if !ok {
 		c.sendAlert(alertUnexpectedMessage)
 		return unexpectedMessageError(serverHello, msg)
 	}
 
-	c.vers, ok = c.config.mutualVersion(serverHello.vers)
-	if !ok {
+	if serverWireVersion != serverHello.vers {
 		c.sendAlert(alertProtocolVersion)
-		return fmt.Errorf("tls: server selected unsupported protocol version %x", serverHello.vers)
+		return fmt.Errorf("tls: server sent non-matching version %x vs %x", serverWireVersion, serverHello.vers)
 	}
-	c.haveVers = true
 
-	suite := mutualCipherSuite(c.config.cipherSuites(), serverHello.cipherSuite)
+	// Check for downgrade signals in the server random, per
+	// draft-ietf-tls-tls13-16, section 4.1.3.
+	if c.vers <= VersionTLS12 && c.config.maxVersion(c.isDTLS) >= VersionTLS13 {
+		if bytes.Equal(serverHello.random[len(serverHello.random)-8:], downgradeTLS13) {
+			c.sendAlert(alertProtocolVersion)
+			return errors.New("tls: downgrade from TLS 1.3 detected")
+		}
+	}
+	if c.vers <= VersionTLS11 && c.config.maxVersion(c.isDTLS) >= VersionTLS12 {
+		if bytes.Equal(serverHello.random[len(serverHello.random)-8:], downgradeTLS12) {
+			c.sendAlert(alertProtocolVersion)
+			return errors.New("tls: downgrade from TLS 1.2 detected")
+		}
+	}
+
+	suite := mutualCipherSuite(hello.cipherSuites, serverHello.cipherSuite)
 	if suite == nil {
 		c.sendAlert(alertHandshakeFailure)
 		return fmt.Errorf("tls: server selected an unsupported cipher suite")
 	}
 
-	if c.config.Bugs.RequireRenegotiationInfo && serverHello.secureRenegotiation == nil {
-		return errors.New("tls: renegotiation extension missing")
-	}
-
-	if len(c.clientVerify) > 0 && !c.noRenegotiationInfo() {
-		var expectedRenegInfo []byte
-		expectedRenegInfo = append(expectedRenegInfo, c.clientVerify...)
-		expectedRenegInfo = append(expectedRenegInfo, c.serverVerify...)
-		if !bytes.Equal(serverHello.secureRenegotiation, expectedRenegInfo) {
-			c.sendAlert(alertHandshakeFailure)
-			return fmt.Errorf("tls: renegotiation mismatch")
-		}
-	}
-
-	if expected := c.config.Bugs.ExpectedCustomExtension; expected != nil {
-		if serverHello.customExtension != *expected {
-			return fmt.Errorf("tls: bad custom extension contents %q", serverHello.customExtension)
-		}
+	if haveHelloRetryRequest && helloRetryRequest.hasSelectedGroup && helloRetryRequest.selectedGroup != serverHello.keyShare.group {
+		c.sendAlert(alertHandshakeFailure)
+		return errors.New("tls: ServerHello parameters did not match HelloRetryRequest")
 	}
 
 	hs := &clientHandshakeState{
@@ -304,78 +567,426 @@
 		hello:        hello,
 		suite:        suite,
 		finishedHash: newFinishedHash(c.vers, suite),
+		keyShares:    keyShares,
 		session:      session,
 	}
 
 	hs.writeHash(helloBytes, hs.c.sendHandshakeSeq-1)
+	if haveHelloRetryRequest {
+		hs.writeServerHash(helloRetryRequest.marshal())
+		hs.writeClientHash(secondHelloBytes)
+	}
 	hs.writeServerHash(hs.serverHello.marshal())
 
-	if c.config.Bugs.EarlyChangeCipherSpec > 0 {
-		hs.establishKeys()
-		c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
-	}
-
-	isResume, err := hs.processServerHello()
-	if err != nil {
-		return err
-	}
-
-	if isResume {
-		if c.config.Bugs.EarlyChangeCipherSpec == 0 {
-			if err := hs.establishKeys(); err != nil {
-				return err
-			}
-		}
-		if err := hs.readSessionTicket(); err != nil {
-			return err
-		}
-		if err := hs.readFinished(c.firstFinished[:]); err != nil {
-			return err
-		}
-		if err := hs.sendFinished(nil, isResume); err != nil {
+	if c.vers >= VersionTLS13 {
+		if err := hs.doTLS13Handshake(); err != nil {
 			return err
 		}
 	} else {
-		if err := hs.doFullHandshake(); err != nil {
+		if c.config.Bugs.EarlyChangeCipherSpec > 0 {
+			hs.establishKeys()
+			c.writeRecord(recordTypeChangeCipherSpec, []byte{1})
+		}
+
+		if hs.serverHello.compressionMethod != compressionNone {
+			c.sendAlert(alertUnexpectedMessage)
+			return errors.New("tls: server selected unsupported compression format")
+		}
+
+		err = hs.processServerExtensions(&serverHello.extensions)
+		if err != nil {
 			return err
 		}
-		if err := hs.establishKeys(); err != nil {
+
+		isResume, err := hs.processServerHello()
+		if err != nil {
 			return err
 		}
-		if err := hs.sendFinished(c.firstFinished[:], isResume); err != nil {
-			return err
+
+		if isResume {
+			if c.config.Bugs.EarlyChangeCipherSpec == 0 {
+				if err := hs.establishKeys(); err != nil {
+					return err
+				}
+			}
+			if err := hs.readSessionTicket(); err != nil {
+				return err
+			}
+			if err := hs.readFinished(c.firstFinished[:]); err != nil {
+				return err
+			}
+			if err := hs.sendFinished(nil, isResume); err != nil {
+				return err
+			}
+		} else {
+			if err := hs.doFullHandshake(); err != nil {
+				return err
+			}
+			if err := hs.establishKeys(); err != nil {
+				return err
+			}
+			if err := hs.sendFinished(c.firstFinished[:], isResume); err != nil {
+				return err
+			}
+			// Most retransmits are triggered by a timeout, but the final
+			// leg of the handshake is retransmited upon re-receiving a
+			// Finished.
+			if err := c.simulatePacketLoss(func() {
+				c.sendHandshakeSeq--
+				c.writeRecord(recordTypeHandshake, hs.finishedBytes)
+				c.flushHandshake()
+			}); err != nil {
+				return err
+			}
+			if err := hs.readSessionTicket(); err != nil {
+				return err
+			}
+			if err := hs.readFinished(nil); err != nil {
+				return err
+			}
 		}
-		// Most retransmits are triggered by a timeout, but the final
-		// leg of the handshake is retransmited upon re-receiving a
-		// Finished.
-		if err := c.simulatePacketLoss(func() {
-			c.writeRecord(recordTypeHandshake, hs.finishedBytes)
-			c.dtlsFlushHandshake()
-		}); err != nil {
-			return err
+
+		if sessionCache != nil && hs.session != nil && session != hs.session {
+			if c.config.Bugs.RequireSessionTickets && len(hs.session.sessionTicket) == 0 {
+				return errors.New("tls: new session used session IDs instead of tickets")
+			}
+			sessionCache.Put(cacheKey, hs.session)
 		}
-		if err := hs.readSessionTicket(); err != nil {
-			return err
-		}
-		if err := hs.readFinished(nil); err != nil {
-			return err
-		}
+
+		c.didResume = isResume
+		c.exporterSecret = hs.masterSecret
 	}
 
-	if sessionCache != nil && hs.session != nil && session != hs.session {
-		sessionCache.Put(cacheKey, hs.session)
-	}
-
-	c.didResume = isResume
 	c.handshakeComplete = true
 	c.cipherSuite = suite
 	copy(c.clientRandom[:], hs.hello.random)
 	copy(c.serverRandom[:], hs.serverHello.random)
-	copy(c.masterSecret[:], hs.masterSecret)
 
 	return nil
 }
 
+func (hs *clientHandshakeState) doTLS13Handshake() error {
+	c := hs.c
+
+	// Once the PRF hash is known, TLS 1.3 does not require a handshake
+	// buffer.
+	hs.finishedHash.discardHandshakeBuffer()
+
+	zeroSecret := hs.finishedHash.zeroSecret()
+
+	// Resolve PSK and compute the early secret.
+	//
+	// TODO(davidben): This will need to be handled slightly earlier once
+	// 0-RTT is implemented.
+	if hs.serverHello.hasPSKIdentity {
+		// We send at most one PSK identity.
+		if hs.session == nil || hs.serverHello.pskIdentity != 0 {
+			c.sendAlert(alertUnknownPSKIdentity)
+			return errors.New("tls: server sent unknown PSK identity")
+		}
+		sessionCipher := cipherSuiteFromID(hs.session.cipherSuite)
+		if sessionCipher == nil || sessionCipher.hash() != hs.suite.hash() {
+			c.sendAlert(alertHandshakeFailure)
+			return errors.New("tls: server resumed an invalid session for the cipher suite")
+		}
+		hs.finishedHash.addEntropy(hs.session.masterSecret)
+		c.didResume = true
+	} else {
+		hs.finishedHash.addEntropy(zeroSecret)
+	}
+
+	if !hs.serverHello.hasKeyShare {
+		c.sendAlert(alertUnsupportedExtension)
+		return errors.New("tls: server omitted KeyShare on resumption.")
+	}
+
+	// Resolve ECDHE and compute the handshake secret.
+	if !c.config.Bugs.MissingKeyShare && !c.config.Bugs.SecondClientHelloMissingKeyShare {
+		curve, ok := hs.keyShares[hs.serverHello.keyShare.group]
+		if !ok {
+			c.sendAlert(alertHandshakeFailure)
+			return errors.New("tls: server selected an unsupported group")
+		}
+		c.curveID = hs.serverHello.keyShare.group
+
+		ecdheSecret, err := curve.finish(hs.serverHello.keyShare.keyExchange)
+		if err != nil {
+			return err
+		}
+		hs.finishedHash.addEntropy(ecdheSecret)
+	} else {
+		hs.finishedHash.addEntropy(zeroSecret)
+	}
+
+	// Derive handshake traffic keys and switch read key to handshake
+	// traffic key.
+	clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(clientHandshakeTrafficLabel)
+	serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(serverHandshakeTrafficLabel)
+	c.in.useTrafficSecret(c.vers, hs.suite, serverHandshakeTrafficSecret, serverWrite)
+
+	msg, err := c.readHandshake()
+	if err != nil {
+		return err
+	}
+
+	encryptedExtensions, ok := msg.(*encryptedExtensionsMsg)
+	if !ok {
+		c.sendAlert(alertUnexpectedMessage)
+		return unexpectedMessageError(encryptedExtensions, msg)
+	}
+	hs.writeServerHash(encryptedExtensions.marshal())
+
+	err = hs.processServerExtensions(&encryptedExtensions.extensions)
+	if err != nil {
+		return err
+	}
+
+	var chainToSend *Certificate
+	var certReq *certificateRequestMsg
+	if c.didResume {
+		// Copy over authentication from the session.
+		c.peerCertificates = hs.session.serverCertificates
+		c.sctList = hs.session.sctList
+		c.ocspResponse = hs.session.ocspResponse
+	} else {
+		msg, err := c.readHandshake()
+		if err != nil {
+			return err
+		}
+
+		var ok bool
+		certReq, ok = msg.(*certificateRequestMsg)
+		if ok {
+			if len(certReq.requestContext) != 0 {
+				return errors.New("tls: non-empty certificate request context sent in handshake")
+			}
+
+			if c.config.Bugs.IgnorePeerSignatureAlgorithmPreferences {
+				certReq.signatureAlgorithms = c.config.signSignatureAlgorithms()
+			}
+
+			hs.writeServerHash(certReq.marshal())
+
+			chainToSend, err = selectClientCertificate(c, certReq)
+			if err != nil {
+				return err
+			}
+
+			msg, err = c.readHandshake()
+			if err != nil {
+				return err
+			}
+		}
+
+		certMsg, ok := msg.(*certificateMsg)
+		if !ok {
+			c.sendAlert(alertUnexpectedMessage)
+			return unexpectedMessageError(certMsg, msg)
+		}
+		hs.writeServerHash(certMsg.marshal())
+
+		// Check for unsolicited extensions.
+		for i, cert := range certMsg.certificates {
+			if c.config.Bugs.NoOCSPStapling && cert.ocspResponse != nil {
+				c.sendAlert(alertUnsupportedExtension)
+				return errors.New("tls: unexpected OCSP response in the server certificate")
+			}
+			if c.config.Bugs.NoSignedCertificateTimestamps && cert.sctList != nil {
+				c.sendAlert(alertUnsupportedExtension)
+				return errors.New("tls: unexpected SCT list in the server certificate")
+			}
+			if i > 0 && c.config.Bugs.ExpectNoExtensionsOnIntermediate && (cert.ocspResponse != nil || cert.sctList != nil) {
+				c.sendAlert(alertUnsupportedExtension)
+				return errors.New("tls: unexpected extensions in the server certificate")
+			}
+		}
+
+		if err := hs.verifyCertificates(certMsg); err != nil {
+			return err
+		}
+		leaf := c.peerCertificates[0]
+		c.ocspResponse = certMsg.certificates[0].ocspResponse
+		c.sctList = certMsg.certificates[0].sctList
+
+		msg, err = c.readHandshake()
+		if err != nil {
+			return err
+		}
+		certVerifyMsg, ok := msg.(*certificateVerifyMsg)
+		if !ok {
+			c.sendAlert(alertUnexpectedMessage)
+			return unexpectedMessageError(certVerifyMsg, msg)
+		}
+
+		c.peerSignatureAlgorithm = certVerifyMsg.signatureAlgorithm
+		input := hs.finishedHash.certificateVerifyInput(serverCertificateVerifyContextTLS13)
+		err = verifyMessage(c.vers, leaf.PublicKey, c.config, certVerifyMsg.signatureAlgorithm, input, certVerifyMsg.signature)
+		if err != nil {
+			return err
+		}
+
+		hs.writeServerHash(certVerifyMsg.marshal())
+	}
+
+	msg, err = c.readHandshake()
+	if err != nil {
+		return err
+	}
+	serverFinished, ok := msg.(*finishedMsg)
+	if !ok {
+		c.sendAlert(alertUnexpectedMessage)
+		return unexpectedMessageError(serverFinished, msg)
+	}
+
+	verify := hs.finishedHash.serverSum(serverHandshakeTrafficSecret)
+	if len(verify) != len(serverFinished.verifyData) ||
+		subtle.ConstantTimeCompare(verify, serverFinished.verifyData) != 1 {
+		c.sendAlert(alertHandshakeFailure)
+		return errors.New("tls: server's Finished message was incorrect")
+	}
+
+	hs.writeServerHash(serverFinished.marshal())
+
+	// The various secrets do not incorporate the client's final leg, so
+	// derive them now before updating the handshake context.
+	hs.finishedHash.addEntropy(zeroSecret)
+	clientTrafficSecret := hs.finishedHash.deriveSecret(clientApplicationTrafficLabel)
+	serverTrafficSecret := hs.finishedHash.deriveSecret(serverApplicationTrafficLabel)
+	c.exporterSecret = hs.finishedHash.deriveSecret(exporterLabel)
+
+	// Switch to application data keys on read. In particular, any alerts
+	// from the client certificate are read over these keys.
+	c.in.useTrafficSecret(c.vers, hs.suite, serverTrafficSecret, serverWrite)
+
+	// If we're expecting 0.5-RTT messages from the server, read them
+	// now.
+	if encryptedExtensions.extensions.hasEarlyData {
+		// BoringSSL will always send two tickets half-RTT when
+		// negotiating 0-RTT.
+		for i := 0; i < shimConfig.HalfRTTTickets; i++ {
+			msg, err := c.readHandshake()
+			if err != nil {
+				return fmt.Errorf("tls: error reading half-RTT ticket: %s", err)
+			}
+			newSessionTicket, ok := msg.(*newSessionTicketMsg)
+			if !ok {
+				return errors.New("tls: expected half-RTT ticket")
+			}
+			if err := c.processTLS13NewSessionTicket(newSessionTicket, hs.suite); err != nil {
+				return err
+			}
+		}
+		for _, expectedMsg := range c.config.Bugs.ExpectHalfRTTData {
+			if err := c.readRecord(recordTypeApplicationData); err != nil {
+				return err
+			}
+			if !bytes.Equal(c.input.data[c.input.off:], expectedMsg) {
+				return errors.New("ExpectHalfRTTData: did not get expected message")
+			}
+			c.in.freeBlock(c.input)
+			c.input = nil
+		}
+	}
+
+	// Send EndOfEarlyData and then switch write key to handshake
+	// traffic key.
+	if c.out.cipher != nil && !c.config.Bugs.SkipEndOfEarlyData {
+		if c.config.Bugs.SendStrayEarlyHandshake {
+			helloRequest := new(helloRequestMsg)
+			c.writeRecord(recordTypeHandshake, helloRequest.marshal())
+		}
+		c.sendAlert(alertEndOfEarlyData)
+	}
+	c.out.useTrafficSecret(c.vers, hs.suite, clientHandshakeTrafficSecret, clientWrite)
+
+	if certReq != nil && !c.config.Bugs.SkipClientCertificate {
+		certMsg := &certificateMsg{
+			hasRequestContext: true,
+			requestContext:    certReq.requestContext,
+		}
+		if chainToSend != nil {
+			for _, certData := range chainToSend.Certificate {
+				certMsg.certificates = append(certMsg.certificates, certificateEntry{
+					data:           certData,
+					extraExtension: c.config.Bugs.SendExtensionOnCertificate,
+				})
+			}
+		}
+		hs.writeClientHash(certMsg.marshal())
+		c.writeRecord(recordTypeHandshake, certMsg.marshal())
+
+		if chainToSend != nil {
+			certVerify := &certificateVerifyMsg{
+				hasSignatureAlgorithm: true,
+			}
+
+			// Determine the hash to sign.
+			privKey := chainToSend.PrivateKey
+
+			var err error
+			certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.vers, privKey, c.config, certReq.signatureAlgorithms)
+			if err != nil {
+				c.sendAlert(alertInternalError)
+				return err
+			}
+
+			input := hs.finishedHash.certificateVerifyInput(clientCertificateVerifyContextTLS13)
+			certVerify.signature, err = signMessage(c.vers, privKey, c.config, certVerify.signatureAlgorithm, input)
+			if err != nil {
+				c.sendAlert(alertInternalError)
+				return err
+			}
+			if c.config.Bugs.SendSignatureAlgorithm != 0 {
+				certVerify.signatureAlgorithm = c.config.Bugs.SendSignatureAlgorithm
+			}
+
+			hs.writeClientHash(certVerify.marshal())
+			c.writeRecord(recordTypeHandshake, certVerify.marshal())
+		}
+	}
+
+	if encryptedExtensions.extensions.channelIDRequested {
+		channelIDHash := crypto.SHA256.New()
+		channelIDHash.Write(hs.finishedHash.certificateVerifyInput(channelIDContextTLS13))
+		channelIDMsgBytes, err := hs.writeChannelIDMessage(channelIDHash.Sum(nil))
+		if err != nil {
+			return err
+		}
+		hs.writeClientHash(channelIDMsgBytes)
+		c.writeRecord(recordTypeHandshake, channelIDMsgBytes)
+	}
+
+	// Send a client Finished message.
+	finished := new(finishedMsg)
+	finished.verifyData = hs.finishedHash.clientSum(clientHandshakeTrafficSecret)
+	if c.config.Bugs.BadFinished {
+		finished.verifyData[0]++
+	}
+	hs.writeClientHash(finished.marshal())
+	if c.config.Bugs.PartialClientFinishedWithClientHello {
+		// The first byte has already been sent.
+		c.writeRecord(recordTypeHandshake, finished.marshal()[1:])
+	} else if c.config.Bugs.InterleaveEarlyData {
+		finishedBytes := finished.marshal()
+		c.sendFakeEarlyData(4)
+		c.writeRecord(recordTypeHandshake, finishedBytes[:1])
+		c.sendFakeEarlyData(4)
+		c.writeRecord(recordTypeHandshake, finishedBytes[1:])
+	} else {
+		c.writeRecord(recordTypeHandshake, finished.marshal())
+	}
+	if c.config.Bugs.SendExtraFinished {
+		c.writeRecord(recordTypeHandshake, finished.marshal())
+	}
+	c.flushHandshake()
+
+	// Switch to application data keys.
+	c.out.useTrafficSecret(c.vers, hs.suite, clientTrafficSecret, clientWrite)
+
+	c.resumptionSecret = hs.finishedHash.deriveSecret(resumptionLabel)
+	return nil
+}
+
 func (hs *clientHandshakeState) doFullHandshake() error {
 	c := hs.c
 
@@ -387,56 +998,19 @@
 		}
 
 		certMsg, ok := msg.(*certificateMsg)
-		if !ok || len(certMsg.certificates) == 0 {
+		if !ok {
 			c.sendAlert(alertUnexpectedMessage)
 			return unexpectedMessageError(certMsg, msg)
 		}
 		hs.writeServerHash(certMsg.marshal())
 
-		certs := make([]*x509.Certificate, len(certMsg.certificates))
-		for i, asn1Data := range certMsg.certificates {
-			cert, err := x509.ParseCertificate(asn1Data)
-			if err != nil {
-				c.sendAlert(alertBadCertificate)
-				return errors.New("tls: failed to parse certificate from server: " + err.Error())
-			}
-			certs[i] = cert
+		if err := hs.verifyCertificates(certMsg); err != nil {
+			return err
 		}
-		leaf = certs[0]
-
-		if !c.config.InsecureSkipVerify {
-			opts := x509.VerifyOptions{
-				Roots:         c.config.RootCAs,
-				CurrentTime:   c.config.time(),
-				DNSName:       c.config.ServerName,
-				Intermediates: x509.NewCertPool(),
-			}
-
-			for i, cert := range certs {
-				if i == 0 {
-					continue
-				}
-				opts.Intermediates.AddCert(cert)
-			}
-			c.verifiedChains, err = leaf.Verify(opts)
-			if err != nil {
-				c.sendAlert(alertBadCertificate)
-				return err
-			}
-		}
-
-		switch leaf.PublicKey.(type) {
-		case *rsa.PublicKey, *ecdsa.PublicKey:
-			break
-		default:
-			c.sendAlert(alertUnsupportedCertificate)
-			return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", leaf.PublicKey)
-		}
-
-		c.peerCertificates = certs
+		leaf = c.peerCertificates[0]
 	}
 
-	if hs.serverHello.ocspStapling {
+	if hs.serverHello.extensions.ocspStapling {
 		msg, err := c.readHandshake()
 		if err != nil {
 			return err
@@ -468,6 +1042,11 @@
 			c.sendAlert(alertUnexpectedMessage)
 			return err
 		}
+		if ecdhe, ok := keyAgreement.(*ecdheKeyAgreement); ok {
+			c.curveID = ecdhe.curveID
+		}
+
+		c.peerSignatureAlgorithm = keyAgreement.peerSignatureAlgorithm()
 
 		msg, err = c.readHandshake()
 		if err != nil {
@@ -480,71 +1059,15 @@
 	certReq, ok := msg.(*certificateRequestMsg)
 	if ok {
 		certRequested = true
-
-		// RFC 4346 on the certificateAuthorities field:
-		// A list of the distinguished names of acceptable certificate
-		// authorities. These distinguished names may specify a desired
-		// distinguished name for a root CA or for a subordinate CA;
-		// thus, this message can be used to describe both known roots
-		// and a desired authorization space. If the
-		// certificate_authorities list is empty then the client MAY
-		// send any certificate of the appropriate
-		// ClientCertificateType, unless there is some external
-		// arrangement to the contrary.
+		if c.config.Bugs.IgnorePeerSignatureAlgorithmPreferences {
+			certReq.signatureAlgorithms = c.config.signSignatureAlgorithms()
+		}
 
 		hs.writeServerHash(certReq.marshal())
 
-		var rsaAvail, ecdsaAvail bool
-		for _, certType := range certReq.certificateTypes {
-			switch certType {
-			case CertTypeRSASign:
-				rsaAvail = true
-			case CertTypeECDSASign:
-				ecdsaAvail = true
-			}
-		}
-
-		// We need to search our list of client certs for one
-		// where SignatureAlgorithm is RSA and the Issuer is in
-		// certReq.certificateAuthorities
-	findCert:
-		for i, chain := range c.config.Certificates {
-			if !rsaAvail && !ecdsaAvail {
-				continue
-			}
-
-			for j, cert := range chain.Certificate {
-				x509Cert := chain.Leaf
-				// parse the certificate if this isn't the leaf
-				// node, or if chain.Leaf was nil
-				if j != 0 || x509Cert == nil {
-					if x509Cert, err = x509.ParseCertificate(cert); err != nil {
-						c.sendAlert(alertInternalError)
-						return errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error())
-					}
-				}
-
-				switch {
-				case rsaAvail && x509Cert.PublicKeyAlgorithm == x509.RSA:
-				case ecdsaAvail && x509Cert.PublicKeyAlgorithm == x509.ECDSA:
-				default:
-					continue findCert
-				}
-
-				if len(certReq.certificateAuthorities) == 0 {
-					// they gave us an empty list, so just take the
-					// first RSA cert from c.config.Certificates
-					chainToSend = &chain
-					break findCert
-				}
-
-				for _, ca := range certReq.certificateAuthorities {
-					if bytes.Equal(x509Cert.RawIssuer, ca) {
-						chainToSend = &chain
-						break findCert
-					}
-				}
-			}
+		chainToSend, err = selectClientCertificate(c, certReq)
+		if err != nil {
+			return err
 		}
 
 		msg, err = c.readHandshake()
@@ -561,15 +1084,24 @@
 	hs.writeServerHash(shd.marshal())
 
 	// If the server requested a certificate then we have to send a
-	// Certificate message, even if it's empty because we don't have a
-	// certificate to send.
+	// Certificate message in TLS, even if it's empty because we don't have
+	// a certificate to send. In SSL 3.0, skip the message and send a
+	// no_certificate warning alert.
 	if certRequested {
-		certMsg := new(certificateMsg)
-		if chainToSend != nil {
-			certMsg.certificates = chainToSend.Certificate
+		if c.vers == VersionSSL30 && chainToSend == nil {
+			c.sendAlert(alertNoCertificate)
+		} else if !c.config.Bugs.SkipClientCertificate {
+			certMsg := new(certificateMsg)
+			if chainToSend != nil {
+				for _, certData := range chainToSend.Certificate {
+					certMsg.certificates = append(certMsg.certificates, certificateEntry{
+						data: certData,
+					})
+				}
+			}
+			hs.writeClientHash(certMsg.marshal())
+			c.writeRecord(recordTypeHandshake, certMsg.marshal())
 		}
-		hs.writeClientHash(certMsg.marshal())
-		c.writeRecord(recordTypeHandshake, certMsg.marshal())
 	}
 
 	preMasterSecret, ckx, err := keyAgreement.generateClientKeyExchange(c.config, hs.hello, leaf)
@@ -584,7 +1116,7 @@
 		c.writeRecord(recordTypeHandshake, ckx.marshal())
 	}
 
-	if hs.serverHello.extendedMasterSecret && c.vers >= VersionTLS10 {
+	if hs.serverHello.extensions.extendedMasterSecret && c.vers >= VersionTLS10 {
 		hs.masterSecret = extendedMasterFromPreMasterSecret(c.vers, hs.suite, preMasterSecret, hs.finishedHash)
 		c.extendedMasterSecret = true
 	} else {
@@ -595,72 +1127,112 @@
 	}
 
 	if chainToSend != nil {
-		var signed []byte
 		certVerify := &certificateVerifyMsg{
-			hasSignatureAndHash: c.vers >= VersionTLS12,
+			hasSignatureAlgorithm: c.vers >= VersionTLS12,
 		}
 
 		// Determine the hash to sign.
-		var signatureType uint8
-		switch c.config.Certificates[0].PrivateKey.(type) {
-		case *ecdsa.PrivateKey:
-			signatureType = signatureECDSA
-		case *rsa.PrivateKey:
-			signatureType = signatureRSA
-		default:
-			c.sendAlert(alertInternalError)
-			return errors.New("unknown private key type")
-		}
-		if c.config.Bugs.IgnorePeerSignatureAlgorithmPreferences {
-			certReq.signatureAndHashes = c.config.signatureAndHashesForClient()
-		}
-		certVerify.signatureAndHash, err = hs.finishedHash.selectClientCertSignatureAlgorithm(certReq.signatureAndHashes, c.config.signatureAndHashesForClient(), signatureType)
-		if err != nil {
-			c.sendAlert(alertInternalError)
-			return err
-		}
-		digest, hashFunc, err := hs.finishedHash.hashForClientCertificate(certVerify.signatureAndHash, hs.masterSecret)
-		if err != nil {
-			c.sendAlert(alertInternalError)
-			return err
-		}
-		if c.config.Bugs.InvalidCertVerifySignature {
-			digest[0] ^= 0x80
+		privKey := c.config.Certificates[0].PrivateKey
+
+		if certVerify.hasSignatureAlgorithm {
+			certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.vers, privKey, c.config, certReq.signatureAlgorithms)
+			if err != nil {
+				c.sendAlert(alertInternalError)
+				return err
+			}
 		}
 
-		switch key := c.config.Certificates[0].PrivateKey.(type) {
-		case *ecdsa.PrivateKey:
-			var r, s *big.Int
-			r, s, err = ecdsa.Sign(c.config.rand(), key, digest)
-			if err == nil {
-				signed, err = asn1.Marshal(ecdsaSignature{r, s})
+		if c.vers > VersionSSL30 {
+			certVerify.signature, err = signMessage(c.vers, privKey, c.config, certVerify.signatureAlgorithm, hs.finishedHash.buffer)
+			if err == nil && c.config.Bugs.SendSignatureAlgorithm != 0 {
+				certVerify.signatureAlgorithm = c.config.Bugs.SendSignatureAlgorithm
 			}
-		case *rsa.PrivateKey:
-			signed, err = rsa.SignPKCS1v15(c.config.rand(), key, hashFunc, digest)
-		default:
-			err = errors.New("unknown private key type")
+		} else {
+			// SSL 3.0's client certificate construction is
+			// incompatible with signatureAlgorithm.
+			rsaKey, ok := privKey.(*rsa.PrivateKey)
+			if !ok {
+				err = errors.New("unsupported signature type for client certificate")
+			} else {
+				digest := hs.finishedHash.hashForClientCertificateSSL3(hs.masterSecret)
+				if c.config.Bugs.InvalidSignature {
+					digest[0] ^= 0x80
+				}
+				certVerify.signature, err = rsa.SignPKCS1v15(c.config.rand(), rsaKey, crypto.MD5SHA1, digest)
+			}
 		}
 		if err != nil {
 			c.sendAlert(alertInternalError)
 			return errors.New("tls: failed to sign handshake with client certificate: " + err.Error())
 		}
-		certVerify.signature = signed
 
 		hs.writeClientHash(certVerify.marshal())
 		c.writeRecord(recordTypeHandshake, certVerify.marshal())
 	}
-	c.dtlsFlushHandshake()
+	// flushHandshake will be called in sendFinished.
 
 	hs.finishedHash.discardHandshakeBuffer()
 
 	return nil
 }
 
+func (hs *clientHandshakeState) verifyCertificates(certMsg *certificateMsg) error {
+	c := hs.c
+
+	if len(certMsg.certificates) == 0 {
+		c.sendAlert(alertIllegalParameter)
+		return errors.New("tls: no certificates sent")
+	}
+
+	certs := make([]*x509.Certificate, len(certMsg.certificates))
+	for i, certEntry := range certMsg.certificates {
+		cert, err := x509.ParseCertificate(certEntry.data)
+		if err != nil {
+			c.sendAlert(alertBadCertificate)
+			return errors.New("tls: failed to parse certificate from server: " + err.Error())
+		}
+		certs[i] = cert
+	}
+
+	if !c.config.InsecureSkipVerify {
+		opts := x509.VerifyOptions{
+			Roots:         c.config.RootCAs,
+			CurrentTime:   c.config.time(),
+			DNSName:       c.config.ServerName,
+			Intermediates: x509.NewCertPool(),
+		}
+
+		for i, cert := range certs {
+			if i == 0 {
+				continue
+			}
+			opts.Intermediates.AddCert(cert)
+		}
+		var err error
+		c.verifiedChains, err = certs[0].Verify(opts)
+		if err != nil {
+			c.sendAlert(alertBadCertificate)
+			return err
+		}
+	}
+
+	switch certs[0].PublicKey.(type) {
+	case *rsa.PublicKey, *ecdsa.PublicKey:
+		break
+	default:
+		c.sendAlert(alertUnsupportedCertificate)
+		return fmt.Errorf("tls: server's certificate contains an unsupported type of public key: %T", certs[0].PublicKey)
+	}
+
+	c.peerCertificates = certs
+	return nil
+}
+
 func (hs *clientHandshakeState) establishKeys() error {
 	c := hs.c
 
 	clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
-		keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.hello.random, hs.serverHello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen)
+		keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.hello.random, hs.serverHello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen(c.vers))
 	var clientCipher, serverCipher interface{}
 	var clientHash, serverHash macFunction
 	if hs.suite.cipher != nil {
@@ -669,8 +1241,8 @@
 		serverCipher = hs.suite.cipher(serverKey, serverIV, true /* for reading */)
 		serverHash = hs.suite.mac(c.vers, serverMAC)
 	} else {
-		clientCipher = hs.suite.aead(clientKey, clientIV)
-		serverCipher = hs.suite.aead(serverKey, serverIV)
+		clientCipher = hs.suite.aead(c.vers, clientKey, clientIV)
+		serverCipher = hs.suite.aead(c.vers, serverKey, serverIV)
 	}
 
 	c.in.prepareCipherSpec(c.vers, serverCipher, serverHash)
@@ -678,9 +1250,134 @@
 	return nil
 }
 
+func (hs *clientHandshakeState) processServerExtensions(serverExtensions *serverExtensions) error {
+	c := hs.c
+
+	if c.vers < VersionTLS13 {
+		if c.config.Bugs.RequireRenegotiationInfo && serverExtensions.secureRenegotiation == nil {
+			return errors.New("tls: renegotiation extension missing")
+		}
+
+		if len(c.clientVerify) > 0 && !c.noRenegotiationInfo() {
+			var expectedRenegInfo []byte
+			expectedRenegInfo = append(expectedRenegInfo, c.clientVerify...)
+			expectedRenegInfo = append(expectedRenegInfo, c.serverVerify...)
+			if !bytes.Equal(serverExtensions.secureRenegotiation, expectedRenegInfo) {
+				c.sendAlert(alertHandshakeFailure)
+				return fmt.Errorf("tls: renegotiation mismatch")
+			}
+		}
+	} else if serverExtensions.secureRenegotiation != nil {
+		return errors.New("tls: renegotiation info sent in TLS 1.3")
+	}
+
+	if expected := c.config.Bugs.ExpectedCustomExtension; expected != nil {
+		if serverExtensions.customExtension != *expected {
+			return fmt.Errorf("tls: bad custom extension contents %q", serverExtensions.customExtension)
+		}
+	}
+
+	clientDidNPN := hs.hello.nextProtoNeg
+	clientDidALPN := len(hs.hello.alpnProtocols) > 0
+	serverHasNPN := serverExtensions.nextProtoNeg
+	serverHasALPN := len(serverExtensions.alpnProtocol) > 0
+
+	if !clientDidNPN && serverHasNPN {
+		c.sendAlert(alertHandshakeFailure)
+		return errors.New("server advertised unrequested NPN extension")
+	}
+
+	if !clientDidALPN && serverHasALPN {
+		c.sendAlert(alertHandshakeFailure)
+		return errors.New("server advertised unrequested ALPN extension")
+	}
+
+	if serverHasNPN && serverHasALPN {
+		c.sendAlert(alertHandshakeFailure)
+		return errors.New("server advertised both NPN and ALPN extensions")
+	}
+
+	if serverHasALPN {
+		c.clientProtocol = serverExtensions.alpnProtocol
+		c.clientProtocolFallback = false
+		c.usedALPN = true
+	}
+
+	if serverHasNPN && c.vers >= VersionTLS13 {
+		c.sendAlert(alertHandshakeFailure)
+		return errors.New("server advertised NPN over TLS 1.3")
+	}
+
+	if !hs.hello.channelIDSupported && serverExtensions.channelIDRequested {
+		c.sendAlert(alertHandshakeFailure)
+		return errors.New("server advertised unrequested Channel ID extension")
+	}
+
+	if serverExtensions.extendedMasterSecret && c.vers >= VersionTLS13 {
+		return errors.New("tls: server advertised extended master secret over TLS 1.3")
+	}
+
+	if serverExtensions.ticketSupported && c.vers >= VersionTLS13 {
+		return errors.New("tls: server advertised ticket extension over TLS 1.3")
+	}
+
+	if serverExtensions.ocspStapling && c.vers >= VersionTLS13 {
+		return errors.New("tls: server advertised OCSP in ServerHello over TLS 1.3")
+	}
+
+	if serverExtensions.ocspStapling && c.config.Bugs.NoOCSPStapling {
+		return errors.New("tls: server advertised unrequested OCSP extension")
+	}
+
+	if len(serverExtensions.sctList) > 0 && c.vers >= VersionTLS13 {
+		return errors.New("tls: server advertised SCTs in ServerHello over TLS 1.3")
+	}
+
+	if len(serverExtensions.sctList) > 0 && c.config.Bugs.NoSignedCertificateTimestamps {
+		return errors.New("tls: server advertised unrequested SCTs")
+	}
+
+	if serverExtensions.srtpProtectionProfile != 0 {
+		if serverExtensions.srtpMasterKeyIdentifier != "" {
+			return errors.New("tls: server selected SRTP MKI value")
+		}
+
+		found := false
+		for _, p := range c.config.SRTPProtectionProfiles {
+			if p == serverExtensions.srtpProtectionProfile {
+				found = true
+				break
+			}
+		}
+		if !found {
+			return errors.New("tls: server advertised unsupported SRTP profile")
+		}
+
+		c.srtpProtectionProfile = serverExtensions.srtpProtectionProfile
+	}
+
+	if c.vers >= VersionTLS13 && c.didResume {
+		if c.config.Bugs.ExpectEarlyDataAccepted && !serverExtensions.hasEarlyData {
+			c.sendAlert(alertHandshakeFailure)
+			return errors.New("tls: server did not accept early data when expected")
+		}
+
+		if !c.config.Bugs.ExpectEarlyDataAccepted && serverExtensions.hasEarlyData {
+			c.sendAlert(alertHandshakeFailure)
+			return errors.New("tls: server accepted early data when not expected")
+		}
+	}
+
+	return nil
+}
+
 func (hs *clientHandshakeState) serverResumedSession() bool {
 	// If the server responded with the same sessionId then it means the
 	// sessionTicket is being used to resume a TLS session.
+	//
+	// Note that, if hs.hello.sessionId is a non-nil empty array, this will
+	// accept an empty session ID from the server as resumption. See
+	// EmptyTicketSessionID.
 	return hs.session != nil && hs.hello.sessionId != nil &&
 		bytes.Equal(hs.serverHello.sessionId, hs.hello.sessionId)
 }
@@ -688,61 +1385,6 @@
 func (hs *clientHandshakeState) processServerHello() (bool, error) {
 	c := hs.c
 
-	if hs.serverHello.compressionMethod != compressionNone {
-		c.sendAlert(alertUnexpectedMessage)
-		return false, errors.New("tls: server selected unsupported compression format")
-	}
-
-	clientDidNPN := hs.hello.nextProtoNeg
-	clientDidALPN := len(hs.hello.alpnProtocols) > 0
-	serverHasNPN := hs.serverHello.nextProtoNeg
-	serverHasALPN := len(hs.serverHello.alpnProtocol) > 0
-
-	if !clientDidNPN && serverHasNPN {
-		c.sendAlert(alertHandshakeFailure)
-		return false, errors.New("server advertised unrequested NPN extension")
-	}
-
-	if !clientDidALPN && serverHasALPN {
-		c.sendAlert(alertHandshakeFailure)
-		return false, errors.New("server advertised unrequested ALPN extension")
-	}
-
-	if serverHasNPN && serverHasALPN {
-		c.sendAlert(alertHandshakeFailure)
-		return false, errors.New("server advertised both NPN and ALPN extensions")
-	}
-
-	if serverHasALPN {
-		c.clientProtocol = hs.serverHello.alpnProtocol
-		c.clientProtocolFallback = false
-		c.usedALPN = true
-	}
-
-	if !hs.hello.channelIDSupported && hs.serverHello.channelIDRequested {
-		c.sendAlert(alertHandshakeFailure)
-		return false, errors.New("server advertised unrequested Channel ID extension")
-	}
-
-	if hs.serverHello.srtpProtectionProfile != 0 {
-		if hs.serverHello.srtpMasterKeyIdentifier != "" {
-			return false, errors.New("tls: server selected SRTP MKI value")
-		}
-
-		found := false
-		for _, p := range c.config.SRTPProtectionProfiles {
-			if p == hs.serverHello.srtpProtectionProfile {
-				found = true
-				break
-			}
-		}
-		if !found {
-			return false, errors.New("tls: server advertised unsupported SRTP profile")
-		}
-
-		c.srtpProtectionProfile = hs.serverHello.srtpProtectionProfile
-	}
-
 	if hs.serverResumedSession() {
 		// For test purposes, assert that the server never accepts the
 		// resumption offer on renegotiation.
@@ -750,11 +1392,11 @@
 			return false, errors.New("tls: server resumed session on renegotiation")
 		}
 
-		if hs.serverHello.sctList != nil {
+		if hs.serverHello.extensions.sctList != nil {
 			return false, errors.New("tls: server sent SCT extension on session resumption")
 		}
 
-		if hs.serverHello.ocspStapling {
+		if hs.serverHello.extensions.ocspStapling {
 			return false, errors.New("tls: server sent OCSP extension on session resumption")
 		}
 
@@ -768,8 +1410,8 @@
 		return true, nil
 	}
 
-	if hs.serverHello.sctList != nil {
-		c.sctList = hs.serverHello.sctList
+	if hs.serverHello.extensions.sctList != nil {
+		c.sctList = hs.serverHello.extensions.sctList
 	}
 
 	return false, nil
@@ -816,13 +1458,14 @@
 		vers:               c.vers,
 		cipherSuite:        hs.suite.id,
 		masterSecret:       hs.masterSecret,
-		handshakeHash:      hs.finishedHash.server.Sum(nil),
+		handshakeHash:      hs.finishedHash.Sum(),
 		serverCertificates: c.peerCertificates,
 		sctList:            c.sctList,
 		ocspResponse:       c.ocspResponse,
+		ticketExpiration:   c.config.time().Add(time.Duration(7 * 24 * time.Hour)),
 	}
 
-	if !hs.serverHello.ticketSupported {
+	if !hs.serverHello.extensions.ticketSupported {
 		if c.config.Bugs.ExpectNewTicket {
 			return errors.New("tls: expected new ticket")
 		}
@@ -858,11 +1501,11 @@
 func (hs *clientHandshakeState) sendFinished(out []byte, isResume bool) error {
 	c := hs.c
 
-	var postCCSBytes []byte
+	var postCCSMsgs [][]byte
 	seqno := hs.c.sendHandshakeSeq
-	if hs.serverHello.nextProtoNeg {
+	if hs.serverHello.extensions.nextProtoNeg {
 		nextProto := new(nextProtoMsg)
-		proto, fallback := mutualProtocol(c.config.NextProtos, hs.serverHello.nextProtos)
+		proto, fallback := mutualProtocol(c.config.NextProtos, hs.serverHello.extensions.nextProtos)
 		nextProto.proto = proto
 		c.clientProtocol = proto
 		c.clientProtocolFallback = fallback
@@ -870,35 +1513,21 @@
 		nextProtoBytes := nextProto.marshal()
 		hs.writeHash(nextProtoBytes, seqno)
 		seqno++
-		postCCSBytes = append(postCCSBytes, nextProtoBytes...)
+		postCCSMsgs = append(postCCSMsgs, nextProtoBytes)
 	}
 
-	if hs.serverHello.channelIDRequested {
-		encryptedExtensions := new(encryptedExtensionsMsg)
-		if c.config.ChannelID.Curve != elliptic.P256() {
-			return fmt.Errorf("tls: Channel ID is not on P-256.")
-		}
+	if hs.serverHello.extensions.channelIDRequested {
 		var resumeHash []byte
 		if isResume {
 			resumeHash = hs.session.handshakeHash
 		}
-		r, s, err := ecdsa.Sign(c.config.rand(), c.config.ChannelID, hs.finishedHash.hashForChannelID(resumeHash))
+		channelIDMsgBytes, err := hs.writeChannelIDMessage(hs.finishedHash.hashForChannelID(resumeHash))
 		if err != nil {
 			return err
 		}
-		channelID := make([]byte, 128)
-		writeIntPadded(channelID[0:32], c.config.ChannelID.X)
-		writeIntPadded(channelID[32:64], c.config.ChannelID.Y)
-		writeIntPadded(channelID[64:96], r)
-		writeIntPadded(channelID[96:128], s)
-		encryptedExtensions.channelID = channelID
-
-		c.channelID = &c.config.ChannelID.PublicKey
-
-		encryptedExtensionsBytes := encryptedExtensions.marshal()
-		hs.writeHash(encryptedExtensionsBytes, seqno)
+		hs.writeHash(channelIDMsgBytes, seqno)
 		seqno++
-		postCCSBytes = append(postCCSBytes, encryptedExtensionsBytes...)
+		postCCSMsgs = append(postCCSMsgs, channelIDMsgBytes)
 	}
 
 	finished := new(finishedMsg)
@@ -914,13 +1543,16 @@
 	c.clientVerify = append(c.clientVerify[:0], finished.verifyData...)
 	hs.finishedBytes = finished.marshal()
 	hs.writeHash(hs.finishedBytes, seqno)
-	postCCSBytes = append(postCCSBytes, hs.finishedBytes...)
+	postCCSMsgs = append(postCCSMsgs, hs.finishedBytes)
 
 	if c.config.Bugs.FragmentAcrossChangeCipherSpec {
-		c.writeRecord(recordTypeHandshake, postCCSBytes[:5])
-		postCCSBytes = postCCSBytes[5:]
+		c.writeRecord(recordTypeHandshake, postCCSMsgs[0][:5])
+		postCCSMsgs[0] = postCCSMsgs[0][5:]
+	} else if c.config.Bugs.SendUnencryptedFinished {
+		c.writeRecord(recordTypeHandshake, postCCSMsgs[0])
+		postCCSMsgs = postCCSMsgs[1:]
 	}
-	c.dtlsFlushHandshake()
+	c.flushHandshake()
 
 	if !c.config.Bugs.SkipChangeCipherSpec &&
 		c.config.Bugs.EarlyChangeCipherSpec == 0 {
@@ -940,12 +1572,44 @@
 	}
 
 	if !c.config.Bugs.SkipFinished {
-		c.writeRecord(recordTypeHandshake, postCCSBytes)
-		c.dtlsFlushHandshake()
+		for _, msg := range postCCSMsgs {
+			c.writeRecord(recordTypeHandshake, msg)
+		}
+
+		if c.config.Bugs.SendExtraFinished {
+			c.writeRecord(recordTypeHandshake, finished.marshal())
+		}
+
+		c.flushHandshake()
 	}
 	return nil
 }
 
+func (hs *clientHandshakeState) writeChannelIDMessage(channelIDHash []byte) ([]byte, error) {
+	c := hs.c
+	channelIDMsg := new(channelIDMsg)
+	if c.config.ChannelID.Curve != elliptic.P256() {
+		return nil, fmt.Errorf("tls: Channel ID is not on P-256.")
+	}
+	r, s, err := ecdsa.Sign(c.config.rand(), c.config.ChannelID, channelIDHash)
+	if err != nil {
+		return nil, err
+	}
+	channelID := make([]byte, 128)
+	writeIntPadded(channelID[0:32], c.config.ChannelID.X)
+	writeIntPadded(channelID[32:64], c.config.ChannelID.Y)
+	writeIntPadded(channelID[64:96], r)
+	writeIntPadded(channelID[96:128], s)
+	if c.config.Bugs.InvalidChannelIDSignature {
+		channelID[64] ^= 1
+	}
+	channelIDMsg.channelID = channelID
+
+	c.channelID = &c.config.ChannelID.PublicKey
+
+	return channelIDMsg.marshal(), nil
+}
+
 func (hs *clientHandshakeState) writeClientHash(msg []byte) {
 	// writeClientHash is called before writeRecord.
 	hs.writeHash(msg, hs.c.sendHandshakeSeq)
@@ -972,6 +1636,83 @@
 	}
 }
 
+// selectClientCertificate selects a certificate for use with the given
+// certificate, or none if none match. It may return a particular certificate or
+// nil on success, or an error on internal error.
+func selectClientCertificate(c *Conn, certReq *certificateRequestMsg) (*Certificate, error) {
+	// RFC 4346 on the certificateAuthorities field:
+	// A list of the distinguished names of acceptable certificate
+	// authorities. These distinguished names may specify a desired
+	// distinguished name for a root CA or for a subordinate CA; thus, this
+	// message can be used to describe both known roots and a desired
+	// authorization space. If the certificate_authorities list is empty
+	// then the client MAY send any certificate of the appropriate
+	// ClientCertificateType, unless there is some external arrangement to
+	// the contrary.
+
+	var rsaAvail, ecdsaAvail bool
+	if !certReq.hasRequestContext {
+		for _, certType := range certReq.certificateTypes {
+			switch certType {
+			case CertTypeRSASign:
+				rsaAvail = true
+			case CertTypeECDSASign:
+				ecdsaAvail = true
+			}
+		}
+	}
+
+	// We need to search our list of client certs for one
+	// where SignatureAlgorithm is RSA and the Issuer is in
+	// certReq.certificateAuthorities
+findCert:
+	for i, chain := range c.config.Certificates {
+		if !certReq.hasRequestContext && !rsaAvail && !ecdsaAvail {
+			continue
+		}
+
+		// Ensure the private key supports one of the advertised
+		// signature algorithms.
+		if certReq.hasSignatureAlgorithm {
+			if _, err := selectSignatureAlgorithm(c.vers, chain.PrivateKey, c.config, certReq.signatureAlgorithms); err != nil {
+				continue
+			}
+		}
+
+		for j, cert := range chain.Certificate {
+			x509Cert := chain.Leaf
+			// parse the certificate if this isn't the leaf
+			// node, or if chain.Leaf was nil
+			if j != 0 || x509Cert == nil {
+				var err error
+				if x509Cert, err = x509.ParseCertificate(cert); err != nil {
+					c.sendAlert(alertInternalError)
+					return nil, errors.New("tls: failed to parse client certificate #" + strconv.Itoa(i) + ": " + err.Error())
+				}
+			}
+
+			if !certReq.hasRequestContext {
+				switch {
+				case rsaAvail && x509Cert.PublicKeyAlgorithm == x509.RSA:
+				case ecdsaAvail && x509Cert.PublicKeyAlgorithm == x509.ECDSA:
+				default:
+					continue findCert
+				}
+			}
+
+			if expected := c.config.Bugs.ExpectCertificateReqNames; expected != nil {
+				if !eqByteSlices(expected, certReq.certificateAuthorities) {
+					return nil, fmt.Errorf("tls: CertificateRequest names differed, got %#v but expected %#v", certReq.certificateAuthorities, expected)
+				}
+			}
+
+			return &chain, nil
+		}
+	}
+
+	return nil, nil
+}
+
 // clientSessionCacheKey returns a key used to cache sessionTickets that could
 // be used to resume previously negotiated TLS sessions with a server.
 func clientSessionCacheKey(serverAddr net.Addr, config *Config) string {
@@ -1006,3 +1747,44 @@
 	xb := x.Bytes()
 	copy(b[len(b)-len(xb):], xb)
 }
+
+func generatePSKBinders(hello *clientHelloMsg, pskCipherSuite *cipherSuite, psk, transcript []byte, config *Config) {
+	if config.Bugs.SendNoPSKBinder {
+		return
+	}
+
+	binderLen := pskCipherSuite.hash().Size()
+	if config.Bugs.SendShortPSKBinder {
+		binderLen--
+	}
+
+	numBinders := 1
+	if config.Bugs.SendExtraPSKBinder {
+		numBinders++
+	}
+
+	// Fill hello.pskBinders with appropriate length arrays of zeros so the
+	// length prefixes are correct when computing the binder over the truncated
+	// ClientHello message.
+	hello.pskBinders = make([][]byte, numBinders)
+	for i := range hello.pskBinders {
+		hello.pskBinders[i] = make([]byte, binderLen)
+	}
+
+	helloBytes := hello.marshal()
+	binderSize := len(hello.pskBinders)*(binderLen+1) + 2
+	truncatedHello := helloBytes[:len(helloBytes)-binderSize]
+	binder := computePSKBinder(psk, resumptionPSKBinderLabel, pskCipherSuite, transcript, truncatedHello)
+	if config.Bugs.SendShortPSKBinder {
+		binder = binder[:binderLen]
+	}
+	if config.Bugs.SendInvalidPSKBinder {
+		binder[0] ^= 1
+	}
+
+	for i := range hello.pskBinders {
+		hello.pskBinders[i] = binder
+	}
+
+	hello.raw = nil
+}
diff --git a/src/ssl/test/runner/handshake_messages.go b/src/ssl/test/runner/handshake_messages.go
index 530ddbc..86e2821 100644
--- a/src/ssl/test/runner/handshake_messages.go
+++ b/src/ssl/test/runner/handshake_messages.go
@@ -4,7 +4,130 @@
 
 package runner
 
-import "bytes"
+import (
+	"bytes"
+	"encoding/binary"
+)
+
+func writeLen(buf []byte, v, size int) {
+	for i := 0; i < size; i++ {
+		buf[size-i-1] = byte(v)
+		v >>= 8
+	}
+	if v != 0 {
+		panic("length is too long")
+	}
+}
+
+type byteBuilder struct {
+	buf       *[]byte
+	start     int
+	prefixLen int
+	child     *byteBuilder
+}
+
+func newByteBuilder() *byteBuilder {
+	buf := make([]byte, 0, 32)
+	return &byteBuilder{buf: &buf}
+}
+
+func (bb *byteBuilder) len() int {
+	return len(*bb.buf) - bb.start - bb.prefixLen
+}
+
+func (bb *byteBuilder) flush() {
+	if bb.child == nil {
+		return
+	}
+	bb.child.flush()
+	writeLen((*bb.buf)[bb.child.start:], bb.child.len(), bb.child.prefixLen)
+	bb.child = nil
+	return
+}
+
+func (bb *byteBuilder) finish() []byte {
+	bb.flush()
+	return *bb.buf
+}
+
+func (bb *byteBuilder) addU8(u uint8) {
+	bb.flush()
+	*bb.buf = append(*bb.buf, u)
+}
+
+func (bb *byteBuilder) addU16(u uint16) {
+	bb.flush()
+	*bb.buf = append(*bb.buf, byte(u>>8), byte(u))
+}
+
+func (bb *byteBuilder) addU24(u int) {
+	bb.flush()
+	*bb.buf = append(*bb.buf, byte(u>>16), byte(u>>8), byte(u))
+}
+
+func (bb *byteBuilder) addU32(u uint32) {
+	bb.flush()
+	*bb.buf = append(*bb.buf, byte(u>>24), byte(u>>16), byte(u>>8), byte(u))
+}
+
+func (bb *byteBuilder) addU64(u uint64) {
+	bb.flush()
+	var b [8]byte
+	binary.BigEndian.PutUint64(b[:], u)
+	*bb.buf = append(*bb.buf, b[:]...)
+}
+
+func (bb *byteBuilder) addU8LengthPrefixed() *byteBuilder {
+	return bb.createChild(1)
+}
+
+func (bb *byteBuilder) addU16LengthPrefixed() *byteBuilder {
+	return bb.createChild(2)
+}
+
+func (bb *byteBuilder) addU24LengthPrefixed() *byteBuilder {
+	return bb.createChild(3)
+}
+
+func (bb *byteBuilder) addU32LengthPrefixed() *byteBuilder {
+	return bb.createChild(4)
+}
+
+func (bb *byteBuilder) addBytes(b []byte) {
+	bb.flush()
+	*bb.buf = append(*bb.buf, b...)
+}
+
+func (bb *byteBuilder) createChild(lengthPrefixSize int) *byteBuilder {
+	bb.flush()
+	bb.child = &byteBuilder{
+		buf:       bb.buf,
+		start:     len(*bb.buf),
+		prefixLen: lengthPrefixSize,
+	}
+	for i := 0; i < lengthPrefixSize; i++ {
+		*bb.buf = append(*bb.buf, 0)
+	}
+	return bb.child
+}
+
+func (bb *byteBuilder) discardChild() {
+	if bb.child != nil {
+		return
+	}
+	bb.child = nil
+	*bb.buf = (*bb.buf)[:bb.start]
+}
+
+type keyShareEntry struct {
+	group       CurveID
+	keyExchange []byte
+}
+
+type pskIdentity struct {
+	ticket              []uint8
+	obfuscatedTicketAge uint32
+}
 
 type clientHelloMsg struct {
 	raw                     []byte
@@ -20,19 +143,30 @@
 	ocspStapling            bool
 	supportedCurves         []CurveID
 	supportedPoints         []uint8
+	hasKeyShares            bool
+	keyShares               []keyShareEntry
+	trailingKeyShareData    bool
+	pskIdentities           []pskIdentity
+	pskKEModes              []byte
+	pskBinders              [][]uint8
+	hasEarlyData            bool
+	tls13Cookie             []byte
 	ticketSupported         bool
 	sessionTicket           []uint8
-	signatureAndHashes      []signatureAndHash
+	signatureAlgorithms     []signatureAlgorithm
+	supportedVersions       []uint16
 	secureRenegotiation     []byte
 	alpnProtocols           []string
 	duplicateExtension      bool
 	channelIDSupported      bool
-	npnLast                 bool
+	npnAfterAlpn            bool
 	extendedMasterSecret    bool
 	srtpProtectionProfiles  []uint16
 	srtpMasterKeyIdentifier string
 	sctListSupported        bool
 	customExtension         string
+	hasGREASEExtension      bool
+	pskBinderFirst          bool
 }
 
 func (m *clientHelloMsg) equal(i interface{}) bool {
@@ -54,20 +188,31 @@
 		m.ocspStapling == m1.ocspStapling &&
 		eqCurveIDs(m.supportedCurves, m1.supportedCurves) &&
 		bytes.Equal(m.supportedPoints, m1.supportedPoints) &&
+		m.hasKeyShares == m1.hasKeyShares &&
+		eqKeyShareEntryLists(m.keyShares, m1.keyShares) &&
+		m.trailingKeyShareData == m1.trailingKeyShareData &&
+		eqPSKIdentityLists(m.pskIdentities, m1.pskIdentities) &&
+		bytes.Equal(m.pskKEModes, m1.pskKEModes) &&
+		eqByteSlices(m.pskBinders, m1.pskBinders) &&
+		m.hasEarlyData == m1.hasEarlyData &&
+		bytes.Equal(m.tls13Cookie, m1.tls13Cookie) &&
 		m.ticketSupported == m1.ticketSupported &&
 		bytes.Equal(m.sessionTicket, m1.sessionTicket) &&
-		eqSignatureAndHashes(m.signatureAndHashes, m1.signatureAndHashes) &&
+		eqSignatureAlgorithms(m.signatureAlgorithms, m1.signatureAlgorithms) &&
+		eqUint16s(m.supportedVersions, m1.supportedVersions) &&
 		bytes.Equal(m.secureRenegotiation, m1.secureRenegotiation) &&
 		(m.secureRenegotiation == nil) == (m1.secureRenegotiation == nil) &&
 		eqStrings(m.alpnProtocols, m1.alpnProtocols) &&
 		m.duplicateExtension == m1.duplicateExtension &&
 		m.channelIDSupported == m1.channelIDSupported &&
-		m.npnLast == m1.npnLast &&
+		m.npnAfterAlpn == m1.npnAfterAlpn &&
 		m.extendedMasterSecret == m1.extendedMasterSecret &&
 		eqUint16s(m.srtpProtectionProfiles, m1.srtpProtectionProfiles) &&
 		m.srtpMasterKeyIdentifier == m1.srtpMasterKeyIdentifier &&
 		m.sctListSupported == m1.sctListSupported &&
-		m.customExtension == m1.customExtension
+		m.customExtension == m1.customExtension &&
+		m.hasGREASEExtension == m1.hasGREASEExtension &&
+		m.pskBinderFirst == m1.pskBinderFirst
 }
 
 func (m *clientHelloMsg) marshal() []byte {
@@ -75,132 +220,51 @@
 		return m.raw
 	}
 
-	length := 2 + 32 + 1 + len(m.sessionId) + 2 + len(m.cipherSuites)*2 + 1 + len(m.compressionMethods)
+	handshakeMsg := newByteBuilder()
+	handshakeMsg.addU8(typeClientHello)
+	hello := handshakeMsg.addU24LengthPrefixed()
+	hello.addU16(m.vers)
+	hello.addBytes(m.random)
+	sessionId := hello.addU8LengthPrefixed()
+	sessionId.addBytes(m.sessionId)
 	if m.isDTLS {
-		length += 1 + len(m.cookie)
+		cookie := hello.addU8LengthPrefixed()
+		cookie.addBytes(m.cookie)
 	}
-	numExtensions := 0
-	extensionsLength := 0
-	if m.nextProtoNeg {
-		numExtensions++
+	cipherSuites := hello.addU16LengthPrefixed()
+	for _, suite := range m.cipherSuites {
+		cipherSuites.addU16(suite)
 	}
-	if m.ocspStapling {
-		extensionsLength += 1 + 2 + 2
-		numExtensions++
-	}
-	if len(m.serverName) > 0 {
-		extensionsLength += 5 + len(m.serverName)
-		numExtensions++
-	}
-	if len(m.supportedCurves) > 0 {
-		extensionsLength += 2 + 2*len(m.supportedCurves)
-		numExtensions++
-	}
-	if len(m.supportedPoints) > 0 {
-		extensionsLength += 1 + len(m.supportedPoints)
-		numExtensions++
-	}
-	if m.ticketSupported {
-		extensionsLength += len(m.sessionTicket)
-		numExtensions++
-	}
-	if len(m.signatureAndHashes) > 0 {
-		extensionsLength += 2 + 2*len(m.signatureAndHashes)
-		numExtensions++
-	}
-	if m.secureRenegotiation != nil {
-		extensionsLength += 1 + len(m.secureRenegotiation)
-		numExtensions++
-	}
-	if m.duplicateExtension {
-		numExtensions += 2
-	}
-	if m.channelIDSupported {
-		numExtensions++
-	}
-	if len(m.alpnProtocols) > 0 {
-		extensionsLength += 2
-		for _, s := range m.alpnProtocols {
-			if l := len(s); l > 255 {
-				panic("invalid ALPN protocol")
-			}
-			extensionsLength++
-			extensionsLength += len(s)
+	compressionMethods := hello.addU8LengthPrefixed()
+	compressionMethods.addBytes(m.compressionMethods)
+
+	extensions := hello.addU16LengthPrefixed()
+	if len(m.pskIdentities) > 0 && m.pskBinderFirst {
+		extensions.addU16(extensionPreSharedKey)
+		pskExtension := extensions.addU16LengthPrefixed()
+
+		pskIdentities := pskExtension.addU16LengthPrefixed()
+		for _, psk := range m.pskIdentities {
+			pskIdentities.addU16LengthPrefixed().addBytes(psk.ticket)
+			pskIdentities.addU32(psk.obfuscatedTicketAge)
 		}
-		numExtensions++
-	}
-	if m.extendedMasterSecret {
-		numExtensions++
-	}
-	if len(m.srtpProtectionProfiles) > 0 {
-		extensionsLength += 2 + 2*len(m.srtpProtectionProfiles)
-		extensionsLength += 1 + len(m.srtpMasterKeyIdentifier)
-		numExtensions++
-	}
-	if m.sctListSupported {
-		numExtensions++
-	}
-	if l := len(m.customExtension); l > 0 {
-		extensionsLength += l
-		numExtensions++
-	}
-	if numExtensions > 0 {
-		extensionsLength += 4 * numExtensions
-		length += 2 + extensionsLength
-	}
-
-	x := make([]byte, 4+length)
-	x[0] = typeClientHello
-	x[1] = uint8(length >> 16)
-	x[2] = uint8(length >> 8)
-	x[3] = uint8(length)
-	vers := versionToWire(m.vers, m.isDTLS)
-	x[4] = uint8(vers >> 8)
-	x[5] = uint8(vers)
-	copy(x[6:38], m.random)
-	x[38] = uint8(len(m.sessionId))
-	copy(x[39:39+len(m.sessionId)], m.sessionId)
-	y := x[39+len(m.sessionId):]
-	if m.isDTLS {
-		y[0] = uint8(len(m.cookie))
-		copy(y[1:], m.cookie)
-		y = y[1+len(m.cookie):]
-	}
-	y[0] = uint8(len(m.cipherSuites) >> 7)
-	y[1] = uint8(len(m.cipherSuites) << 1)
-	for i, suite := range m.cipherSuites {
-		y[2+i*2] = uint8(suite >> 8)
-		y[3+i*2] = uint8(suite)
-	}
-	z := y[2+len(m.cipherSuites)*2:]
-	z[0] = uint8(len(m.compressionMethods))
-	copy(z[1:], m.compressionMethods)
-
-	z = z[1+len(m.compressionMethods):]
-	if numExtensions > 0 {
-		z[0] = byte(extensionsLength >> 8)
-		z[1] = byte(extensionsLength)
-		z = z[2:]
+		pskBinders := pskExtension.addU16LengthPrefixed()
+		for _, binder := range m.pskBinders {
+			pskBinders.addU8LengthPrefixed().addBytes(binder)
+		}
 	}
 	if m.duplicateExtension {
 		// Add a duplicate bogus extension at the beginning and end.
-		z[0] = 0xff
-		z[1] = 0xff
-		z = z[4:]
+		extensions.addU16(0xffff)
+		extensions.addU16(0) // 0-length for empty extension
 	}
-	if m.nextProtoNeg && !m.npnLast {
-		z[0] = byte(extensionNextProtoNeg >> 8)
-		z[1] = byte(extensionNextProtoNeg & 0xff)
-		// The length is always 0
-		z = z[4:]
+	if m.nextProtoNeg && !m.npnAfterAlpn {
+		extensions.addU16(extensionNextProtoNeg)
+		extensions.addU16(0) // The length is always 0
 	}
 	if len(m.serverName) > 0 {
-		z[0] = byte(extensionServerName >> 8)
-		z[1] = byte(extensionServerName & 0xff)
-		l := len(m.serverName) + 5
-		z[2] = byte(l >> 8)
-		z[3] = byte(l)
-		z = z[4:]
+		extensions.addU16(extensionServerName)
+		serverNameList := extensions.addU16LengthPrefixed()
 
 		// RFC 3546, section 3.1
 		//
@@ -221,179 +285,171 @@
 		//     ServerName server_name_list<1..2^16-1>
 		// } ServerNameList;
 
-		z[0] = byte((len(m.serverName) + 3) >> 8)
-		z[1] = byte(len(m.serverName) + 3)
-		z[3] = byte(len(m.serverName) >> 8)
-		z[4] = byte(len(m.serverName))
-		copy(z[5:], []byte(m.serverName))
-		z = z[l:]
+		serverName := serverNameList.addU16LengthPrefixed()
+		serverName.addU8(0) // NameType host_name(0)
+		hostName := serverName.addU16LengthPrefixed()
+		hostName.addBytes([]byte(m.serverName))
 	}
 	if m.ocspStapling {
+		extensions.addU16(extensionStatusRequest)
+		certificateStatusRequest := extensions.addU16LengthPrefixed()
+
 		// RFC 4366, section 3.6
-		z[0] = byte(extensionStatusRequest >> 8)
-		z[1] = byte(extensionStatusRequest)
-		z[2] = 0
-		z[3] = 5
-		z[4] = 1 // OCSP type
+		certificateStatusRequest.addU8(1) // OCSP type
 		// Two zero valued uint16s for the two lengths.
-		z = z[9:]
+		certificateStatusRequest.addU16(0) // ResponderID length
+		certificateStatusRequest.addU16(0) // Extensions length
 	}
 	if len(m.supportedCurves) > 0 {
-		// http://tools.ietf.org/html/rfc4492#section-5.5.1
-		z[0] = byte(extensionSupportedCurves >> 8)
-		z[1] = byte(extensionSupportedCurves)
-		l := 2 + 2*len(m.supportedCurves)
-		z[2] = byte(l >> 8)
-		z[3] = byte(l)
-		l -= 2
-		z[4] = byte(l >> 8)
-		z[5] = byte(l)
-		z = z[6:]
+		// http://tools.ietf.org/html/rfc4492#section-5.1.1
+		extensions.addU16(extensionSupportedCurves)
+		supportedCurvesList := extensions.addU16LengthPrefixed()
+		supportedCurves := supportedCurvesList.addU16LengthPrefixed()
 		for _, curve := range m.supportedCurves {
-			z[0] = byte(curve >> 8)
-			z[1] = byte(curve)
-			z = z[2:]
+			supportedCurves.addU16(uint16(curve))
 		}
 	}
 	if len(m.supportedPoints) > 0 {
-		// http://tools.ietf.org/html/rfc4492#section-5.5.2
-		z[0] = byte(extensionSupportedPoints >> 8)
-		z[1] = byte(extensionSupportedPoints)
-		l := 1 + len(m.supportedPoints)
-		z[2] = byte(l >> 8)
-		z[3] = byte(l)
-		l--
-		z[4] = byte(l)
-		z = z[5:]
-		for _, pointFormat := range m.supportedPoints {
-			z[0] = byte(pointFormat)
-			z = z[1:]
+		// http://tools.ietf.org/html/rfc4492#section-5.1.2
+		extensions.addU16(extensionSupportedPoints)
+		supportedPointsList := extensions.addU16LengthPrefixed()
+		supportedPoints := supportedPointsList.addU8LengthPrefixed()
+		supportedPoints.addBytes(m.supportedPoints)
+	}
+	if m.hasKeyShares {
+		extensions.addU16(extensionKeyShare)
+		keyShareList := extensions.addU16LengthPrefixed()
+
+		keyShares := keyShareList.addU16LengthPrefixed()
+		for _, keyShare := range m.keyShares {
+			keyShares.addU16(uint16(keyShare.group))
+			keyExchange := keyShares.addU16LengthPrefixed()
+			keyExchange.addBytes(keyShare.keyExchange)
 		}
+
+		if m.trailingKeyShareData {
+			keyShares.addU8(0)
+		}
+	}
+	if len(m.pskKEModes) > 0 {
+		extensions.addU16(extensionPSKKeyExchangeModes)
+		pskModesExtension := extensions.addU16LengthPrefixed()
+		pskModesExtension.addU8LengthPrefixed().addBytes(m.pskKEModes)
+	}
+	if m.hasEarlyData {
+		extensions.addU16(extensionEarlyData)
+		extensions.addU16(0) // The length is zero.
+	}
+	if len(m.tls13Cookie) > 0 {
+		extensions.addU16(extensionCookie)
+		body := extensions.addU16LengthPrefixed()
+		body.addU16LengthPrefixed().addBytes(m.tls13Cookie)
 	}
 	if m.ticketSupported {
 		// http://tools.ietf.org/html/rfc5077#section-3.2
-		z[0] = byte(extensionSessionTicket >> 8)
-		z[1] = byte(extensionSessionTicket)
-		l := len(m.sessionTicket)
-		z[2] = byte(l >> 8)
-		z[3] = byte(l)
-		z = z[4:]
-		copy(z, m.sessionTicket)
-		z = z[len(m.sessionTicket):]
+		extensions.addU16(extensionSessionTicket)
+		sessionTicketExtension := extensions.addU16LengthPrefixed()
+		sessionTicketExtension.addBytes(m.sessionTicket)
 	}
-	if len(m.signatureAndHashes) > 0 {
+	if len(m.signatureAlgorithms) > 0 {
 		// https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
-		z[0] = byte(extensionSignatureAlgorithms >> 8)
-		z[1] = byte(extensionSignatureAlgorithms)
-		l := 2 + 2*len(m.signatureAndHashes)
-		z[2] = byte(l >> 8)
-		z[3] = byte(l)
-		z = z[4:]
-
-		l -= 2
-		z[0] = byte(l >> 8)
-		z[1] = byte(l)
-		z = z[2:]
-		for _, sigAndHash := range m.signatureAndHashes {
-			z[0] = sigAndHash.hash
-			z[1] = sigAndHash.signature
-			z = z[2:]
+		extensions.addU16(extensionSignatureAlgorithms)
+		signatureAlgorithmsExtension := extensions.addU16LengthPrefixed()
+		signatureAlgorithms := signatureAlgorithmsExtension.addU16LengthPrefixed()
+		for _, sigAlg := range m.signatureAlgorithms {
+			signatureAlgorithms.addU16(uint16(sigAlg))
+		}
+	}
+	if len(m.supportedVersions) > 0 {
+		extensions.addU16(extensionSupportedVersions)
+		supportedVersionsExtension := extensions.addU16LengthPrefixed()
+		supportedVersions := supportedVersionsExtension.addU8LengthPrefixed()
+		for _, version := range m.supportedVersions {
+			supportedVersions.addU16(uint16(version))
 		}
 	}
 	if m.secureRenegotiation != nil {
-		z[0] = byte(extensionRenegotiationInfo >> 8)
-		z[1] = byte(extensionRenegotiationInfo & 0xff)
-		z[2] = 0
-		z[3] = byte(1 + len(m.secureRenegotiation))
-		z[4] = byte(len(m.secureRenegotiation))
-		z = z[5:]
-		copy(z, m.secureRenegotiation)
-		z = z[len(m.secureRenegotiation):]
+		extensions.addU16(extensionRenegotiationInfo)
+		secureRenegoExt := extensions.addU16LengthPrefixed()
+		secureRenego := secureRenegoExt.addU8LengthPrefixed()
+		secureRenego.addBytes(m.secureRenegotiation)
 	}
 	if len(m.alpnProtocols) > 0 {
-		z[0] = byte(extensionALPN >> 8)
-		z[1] = byte(extensionALPN & 0xff)
-		lengths := z[2:]
-		z = z[6:]
+		// https://tools.ietf.org/html/rfc7301#section-3.1
+		extensions.addU16(extensionALPN)
+		alpnExtension := extensions.addU16LengthPrefixed()
 
-		stringsLength := 0
+		protocolNameList := alpnExtension.addU16LengthPrefixed()
 		for _, s := range m.alpnProtocols {
-			l := len(s)
-			z[0] = byte(l)
-			copy(z[1:], s)
-			z = z[1+l:]
-			stringsLength += 1 + l
+			protocolName := protocolNameList.addU8LengthPrefixed()
+			protocolName.addBytes([]byte(s))
 		}
-
-		lengths[2] = byte(stringsLength >> 8)
-		lengths[3] = byte(stringsLength)
-		stringsLength += 2
-		lengths[0] = byte(stringsLength >> 8)
-		lengths[1] = byte(stringsLength)
 	}
 	if m.channelIDSupported {
-		z[0] = byte(extensionChannelID >> 8)
-		z[1] = byte(extensionChannelID & 0xff)
-		z = z[4:]
+		extensions.addU16(extensionChannelID)
+		extensions.addU16(0) // Length is always 0
 	}
-	if m.nextProtoNeg && m.npnLast {
-		z[0] = byte(extensionNextProtoNeg >> 8)
-		z[1] = byte(extensionNextProtoNeg & 0xff)
-		// The length is always 0
-		z = z[4:]
+	if m.nextProtoNeg && m.npnAfterAlpn {
+		extensions.addU16(extensionNextProtoNeg)
+		extensions.addU16(0) // Length is always 0
 	}
 	if m.duplicateExtension {
 		// Add a duplicate bogus extension at the beginning and end.
-		z[0] = 0xff
-		z[1] = 0xff
-		z = z[4:]
+		extensions.addU16(0xffff)
+		extensions.addU16(0)
 	}
 	if m.extendedMasterSecret {
-		// https://tools.ietf.org/html/draft-ietf-tls-session-hash-01
-		z[0] = byte(extensionExtendedMasterSecret >> 8)
-		z[1] = byte(extensionExtendedMasterSecret & 0xff)
-		z = z[4:]
+		// https://tools.ietf.org/html/rfc7627
+		extensions.addU16(extensionExtendedMasterSecret)
+		extensions.addU16(0) // Length is always 0
 	}
 	if len(m.srtpProtectionProfiles) > 0 {
-		z[0] = byte(extensionUseSRTP >> 8)
-		z[1] = byte(extensionUseSRTP & 0xff)
+		// https://tools.ietf.org/html/rfc5764#section-4.1.1
+		extensions.addU16(extensionUseSRTP)
+		useSrtpExt := extensions.addU16LengthPrefixed()
 
-		profilesLen := 2 * len(m.srtpProtectionProfiles)
-		mkiLen := len(m.srtpMasterKeyIdentifier)
-		l := 2 + profilesLen + 1 + mkiLen
-		z[2] = byte(l >> 8)
-		z[3] = byte(l & 0xff)
-
-		z[4] = byte(profilesLen >> 8)
-		z[5] = byte(profilesLen & 0xff)
-		z = z[6:]
+		srtpProtectionProfiles := useSrtpExt.addU16LengthPrefixed()
 		for _, p := range m.srtpProtectionProfiles {
-			z[0] = byte(p >> 8)
-			z[1] = byte(p & 0xff)
-			z = z[2:]
+			// An SRTPProtectionProfile is defined as uint8[2],
+			// not uint16. For some reason, we're storing it
+			// as a uint16.
+			srtpProtectionProfiles.addU8(byte(p >> 8))
+			srtpProtectionProfiles.addU8(byte(p))
 		}
-
-		z[0] = byte(mkiLen)
-		copy(z[1:], []byte(m.srtpMasterKeyIdentifier))
-		z = z[1+mkiLen:]
+		srtpMki := useSrtpExt.addU8LengthPrefixed()
+		srtpMki.addBytes([]byte(m.srtpMasterKeyIdentifier))
 	}
 	if m.sctListSupported {
-		z[0] = byte(extensionSignedCertificateTimestamp >> 8)
-		z[1] = byte(extensionSignedCertificateTimestamp & 0xff)
-		z = z[4:]
+		extensions.addU16(extensionSignedCertificateTimestamp)
+		extensions.addU16(0) // Length is always 0
 	}
 	if l := len(m.customExtension); l > 0 {
-		z[0] = byte(extensionCustom >> 8)
-		z[1] = byte(extensionCustom & 0xff)
-		z[2] = byte(l >> 8)
-		z[3] = byte(l & 0xff)
-		copy(z[4:], []byte(m.customExtension))
-		z = z[4+l:]
+		extensions.addU16(extensionCustom)
+		customExt := extensions.addU16LengthPrefixed()
+		customExt.addBytes([]byte(m.customExtension))
+	}
+	// The PSK extension must be last (draft-ietf-tls-tls13-18 section 4.2.6).
+	if len(m.pskIdentities) > 0 && !m.pskBinderFirst {
+		extensions.addU16(extensionPreSharedKey)
+		pskExtension := extensions.addU16LengthPrefixed()
+
+		pskIdentities := pskExtension.addU16LengthPrefixed()
+		for _, psk := range m.pskIdentities {
+			pskIdentities.addU16LengthPrefixed().addBytes(psk.ticket)
+			pskIdentities.addU32(psk.obfuscatedTicketAge)
+		}
+		pskBinders := pskExtension.addU16LengthPrefixed()
+		for _, binder := range m.pskBinders {
+			pskBinders.addU8LengthPrefixed().addBytes(binder)
+		}
 	}
 
-	m.raw = x
+	if extensions.len() == 0 {
+		hello.discardChild()
+	}
 
-	return x
+	m.raw = handshakeMsg.finish()
+	return m.raw
 }
 
 func (m *clientHelloMsg) unmarshal(data []byte) bool {
@@ -401,7 +457,7 @@
 		return false
 	}
 	m.raw = data
-	m.vers = wireToVersion(uint16(data[4])<<8|uint16(data[5]), m.isDTLS)
+	m.vers = uint16(data[4])<<8 | uint16(data[5])
 	m.random = data[6:38]
 	sessionIdLen := int(data[38])
 	if sessionIdLen > 32 || len(data) < 39+sessionIdLen {
@@ -452,9 +508,13 @@
 	m.nextProtoNeg = false
 	m.serverName = ""
 	m.ocspStapling = false
+	m.keyShares = nil
+	m.pskIdentities = nil
+	m.hasEarlyData = false
 	m.ticketSupported = false
 	m.sessionTicket = nil
-	m.signatureAndHashes = nil
+	m.signatureAlgorithms = nil
+	m.supportedVersions = nil
 	m.alpnProtocols = nil
 	m.extendedMasterSecret = false
 	m.customExtension = ""
@@ -539,12 +599,118 @@
 			if length != l+1 {
 				return false
 			}
-			m.supportedPoints = make([]uint8, l)
-			copy(m.supportedPoints, data[1:])
+			m.supportedPoints = data[1 : 1+l]
 		case extensionSessionTicket:
 			// http://tools.ietf.org/html/rfc5077#section-3.2
 			m.ticketSupported = true
 			m.sessionTicket = data[:length]
+		case extensionKeyShare:
+			// draft-ietf-tls-tls13 section 6.3.2.3
+			if length < 2 {
+				return false
+			}
+			l := int(data[0])<<8 | int(data[1])
+			if l != length-2 {
+				return false
+			}
+			d := data[2:length]
+			m.hasKeyShares = true
+			for len(d) > 0 {
+				// The next KeyShareEntry contains a NamedGroup (2 bytes) and a
+				// key_exchange (2-byte length prefix with at least 1 byte of content).
+				if len(d) < 5 {
+					return false
+				}
+				entry := keyShareEntry{}
+				entry.group = CurveID(d[0])<<8 | CurveID(d[1])
+				keyExchLen := int(d[2])<<8 | int(d[3])
+				d = d[4:]
+				if len(d) < keyExchLen {
+					return false
+				}
+				entry.keyExchange = d[:keyExchLen]
+				d = d[keyExchLen:]
+				m.keyShares = append(m.keyShares, entry)
+			}
+		case extensionPreSharedKey:
+			// draft-ietf-tls-tls13-18 section 4.2.6
+			if length < 2 {
+				return false
+			}
+			l := int(data[0])<<8 | int(data[1])
+			d := data[2 : l+2]
+			// Parse PSK identities.
+			for len(d) > 0 {
+				if len(d) < 2 {
+					return false
+				}
+				pskLen := int(d[0])<<8 | int(d[1])
+				d = d[2:]
+
+				if len(d) < pskLen+4 {
+					return false
+				}
+				ticket := d[:pskLen]
+				obfuscatedTicketAge := uint32(d[pskLen])<<24 | uint32(d[pskLen+1])<<16 | uint32(d[pskLen+2])<<8 | uint32(d[pskLen+3])
+				psk := pskIdentity{
+					ticket:              ticket,
+					obfuscatedTicketAge: obfuscatedTicketAge,
+				}
+				m.pskIdentities = append(m.pskIdentities, psk)
+				d = d[pskLen+4:]
+			}
+			d = data[l+2:]
+			if len(d) < 2 {
+				return false
+			}
+			l = int(d[0])<<8 | int(d[1])
+			d = d[2:]
+			if l != len(d) {
+				return false
+			}
+			// Parse PSK binders.
+			for len(d) > 0 {
+				if len(d) < 1 {
+					return false
+				}
+				binderLen := int(d[0])
+				d = d[1:]
+				if binderLen > len(d) {
+					return false
+				}
+				m.pskBinders = append(m.pskBinders, d[:binderLen])
+				d = d[binderLen:]
+			}
+
+			// There must be the same number of identities as binders.
+			if len(m.pskIdentities) != len(m.pskBinders) {
+				return false
+			}
+		case extensionPSKKeyExchangeModes:
+			// draft-ietf-tls-tls13-18 section 4.2.7
+			if length < 1 {
+				return false
+			}
+			l := int(data[0])
+			if l != length-1 {
+				return false
+			}
+			m.pskKEModes = data[1:length]
+		case extensionEarlyData:
+			// draft-ietf-tls-tls13 section 6.3.2.5
+			if length != 0 {
+				return false
+			}
+			m.hasEarlyData = true
+		case extensionCookie:
+			if length < 2 {
+				return false
+			}
+			l := int(data[0])<<8 | int(data[1])
+			if l != length-2 || l == 0 {
+				return false
+			}
+			m.tls13Cookie = data[2 : 2+l]
 		case extensionSignatureAlgorithms:
 			// https://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
 			if length < 2 || length&1 != 0 {
@@ -556,10 +722,24 @@
 			}
 			n := l / 2
 			d := data[2:]
-			m.signatureAndHashes = make([]signatureAndHash, n)
-			for i := range m.signatureAndHashes {
-				m.signatureAndHashes[i].hash = d[0]
-				m.signatureAndHashes[i].signature = d[1]
+			m.signatureAlgorithms = make([]signatureAlgorithm, n)
+			for i := range m.signatureAlgorithms {
+				m.signatureAlgorithms[i] = signatureAlgorithm(d[0])<<8 | signatureAlgorithm(d[1])
+				d = d[2:]
+			}
+		case extensionSupportedVersions:
+			if length < 1+2 {
+				return false
+			}
+			l := int(data[0])
+			if l != length-1 || l%2 == 1 || l < 2 {
+				return false
+			}
+			n := l / 2
+			d := data[1:]
+			m.supportedVersions = make([]uint16, n)
+			for i := range m.supportedVersions {
+				m.supportedVersions[i] = uint16(d[0])<<8 | uint16(d[1])
 				d = d[2:]
 			}
 		case extensionRenegotiationInfo:
@@ -623,19 +803,244 @@
 			m.customExtension = string(data[:length])
 		}
 		data = data[length:]
+
+		if isGREASEValue(extension) {
+			m.hasGREASEExtension = true
+		}
 	}
 
 	return true
 }
 
 type serverHelloMsg struct {
-	raw                     []byte
-	isDTLS                  bool
-	vers                    uint16
-	random                  []byte
-	sessionId               []byte
-	cipherSuite             uint16
-	compressionMethod       uint8
+	raw               []byte
+	isDTLS            bool
+	vers              uint16
+	versOverride      uint16
+	random            []byte
+	sessionId         []byte
+	cipherSuite       uint16
+	hasKeyShare       bool
+	keyShare          keyShareEntry
+	hasPSKIdentity    bool
+	pskIdentity       uint16
+	compressionMethod uint8
+	customExtension   string
+	unencryptedALPN   string
+	extensions        serverExtensions
+}
+
+func (m *serverHelloMsg) marshal() []byte {
+	if m.raw != nil {
+		return m.raw
+	}
+
+	handshakeMsg := newByteBuilder()
+	handshakeMsg.addU8(typeServerHello)
+	hello := handshakeMsg.addU24LengthPrefixed()
+
+	// m.vers is used both to determine the format of the rest of the
+	// ServerHello and to override the value, so include a second version
+	// field.
+	vers, ok := wireToVersion(m.vers, m.isDTLS)
+	if !ok {
+		panic("unknown version")
+	}
+	if m.versOverride != 0 {
+		hello.addU16(m.versOverride)
+	} else {
+		hello.addU16(m.vers)
+	}
+
+	hello.addBytes(m.random)
+	if vers < VersionTLS13 {
+		sessionId := hello.addU8LengthPrefixed()
+		sessionId.addBytes(m.sessionId)
+	}
+	hello.addU16(m.cipherSuite)
+	if vers < VersionTLS13 {
+		hello.addU8(m.compressionMethod)
+	}
+
+	extensions := hello.addU16LengthPrefixed()
+
+	if vers >= VersionTLS13 {
+		if m.hasKeyShare {
+			extensions.addU16(extensionKeyShare)
+			keyShare := extensions.addU16LengthPrefixed()
+			keyShare.addU16(uint16(m.keyShare.group))
+			keyExchange := keyShare.addU16LengthPrefixed()
+			keyExchange.addBytes(m.keyShare.keyExchange)
+		}
+		if m.hasPSKIdentity {
+			extensions.addU16(extensionPreSharedKey)
+			extensions.addU16(2) // Length
+			extensions.addU16(m.pskIdentity)
+		}
+		if len(m.customExtension) > 0 {
+			extensions.addU16(extensionCustom)
+			customExt := extensions.addU16LengthPrefixed()
+			customExt.addBytes([]byte(m.customExtension))
+		}
+		if len(m.unencryptedALPN) > 0 {
+			extensions.addU16(extensionALPN)
+			extension := extensions.addU16LengthPrefixed()
+
+			protocolNameList := extension.addU16LengthPrefixed()
+			protocolName := protocolNameList.addU8LengthPrefixed()
+			protocolName.addBytes([]byte(m.unencryptedALPN))
+		}
+	} else {
+		m.extensions.marshal(extensions)
+		if extensions.len() == 0 {
+			hello.discardChild()
+		}
+	}
+
+	m.raw = handshakeMsg.finish()
+	return m.raw
+}
+
+func (m *serverHelloMsg) unmarshal(data []byte) bool {
+	if len(data) < 42 {
+		return false
+	}
+	m.raw = data
+	m.vers = uint16(data[4])<<8 | uint16(data[5])
+	vers, ok := wireToVersion(m.vers, m.isDTLS)
+	if !ok {
+		return false
+	}
+	m.random = data[6:38]
+	data = data[38:]
+	if vers < VersionTLS13 {
+		sessionIdLen := int(data[0])
+		if sessionIdLen > 32 || len(data) < 1+sessionIdLen {
+			return false
+		}
+		m.sessionId = data[1 : 1+sessionIdLen]
+		data = data[1+sessionIdLen:]
+	}
+	if len(data) < 2 {
+		return false
+	}
+	m.cipherSuite = uint16(data[0])<<8 | uint16(data[1])
+	data = data[2:]
+	if vers < VersionTLS13 {
+		if len(data) < 1 {
+			return false
+		}
+		m.compressionMethod = data[0]
+		data = data[1:]
+	}
+
+	if len(data) == 0 && m.vers < VersionTLS13 {
+		// Extension data is optional before TLS 1.3.
+		m.extensions = serverExtensions{}
+		return true
+	}
+	if len(data) < 2 {
+		return false
+	}
+
+	extensionsLength := int(data[0])<<8 | int(data[1])
+	data = data[2:]
+	if len(data) != extensionsLength {
+		return false
+	}
+
+	if vers >= VersionTLS13 {
+		for len(data) != 0 {
+			if len(data) < 4 {
+				return false
+			}
+			extension := uint16(data[0])<<8 | uint16(data[1])
+			length := int(data[2])<<8 | int(data[3])
+			data = data[4:]
+
+			if len(data) < length {
+				return false
+			}
+			d := data[:length]
+			data = data[length:]
+
+			switch extension {
+			case extensionKeyShare:
+				m.hasKeyShare = true
+				if len(d) < 4 {
+					return false
+				}
+				m.keyShare.group = CurveID(uint16(d[0])<<8 | uint16(d[1]))
+				keyExchLen := int(d[2])<<8 | int(d[3])
+				if keyExchLen != len(d)-4 {
+					return false
+				}
+				m.keyShare.keyExchange = make([]byte, keyExchLen)
+				copy(m.keyShare.keyExchange, d[4:])
+			case extensionPreSharedKey:
+				if len(d) != 2 {
+					return false
+				}
+				m.pskIdentity = uint16(d[0])<<8 | uint16(d[1])
+				m.hasPSKIdentity = true
+			default:
+				// Only allow the 3 extensions that are sent in
+				// the clear in TLS 1.3.
+				return false
+			}
+		}
+	} else if !m.extensions.unmarshal(data, vers) {
+		return false
+	}
+
+	return true
+}
+
+type encryptedExtensionsMsg struct {
+	raw        []byte
+	extensions serverExtensions
+	empty      bool
+}
+
+func (m *encryptedExtensionsMsg) marshal() []byte {
+	if m.raw != nil {
+		return m.raw
+	}
+
+	encryptedExtensionsMsg := newByteBuilder()
+	encryptedExtensionsMsg.addU8(typeEncryptedExtensions)
+	encryptedExtensions := encryptedExtensionsMsg.addU24LengthPrefixed()
+	if !m.empty {
+		extensions := encryptedExtensions.addU16LengthPrefixed()
+		m.extensions.marshal(extensions)
+	}
+
+	m.raw = encryptedExtensionsMsg.finish()
+	return m.raw
+}
+
+func (m *encryptedExtensionsMsg) unmarshal(data []byte) bool {
+	m.raw = data
+	if len(data) < 6 {
+		return false
+	}
+	if data[0] != typeEncryptedExtensions {
+		return false
+	}
+	msgLen := int(data[1])<<16 | int(data[2])<<8 | int(data[3])
+	data = data[4:]
+	if len(data) != msgLen {
+		return false
+	}
+	extLen := int(data[0])<<8 | int(data[1])
+	data = data[2:]
+	if extLen != len(data) {
+		return false
+	}
+	return m.extensions.unmarshal(data, VersionTLS13)
+}
+
+type serverExtensions struct {
 	nextProtoNeg            bool
 	nextProtos              []string
 	ocspStapling            bool
@@ -650,263 +1055,126 @@
 	srtpMasterKeyIdentifier string
 	sctList                 []byte
 	customExtension         string
-	npnLast                 bool
+	npnAfterAlpn            bool
+	hasKeyShare             bool
+	hasEarlyData            bool
+	keyShare                keyShareEntry
+	supportedPoints         []uint8
+	serverNameAck           bool
 }
 
-func (m *serverHelloMsg) marshal() []byte {
-	if m.raw != nil {
-		return m.raw
-	}
-
-	length := 38 + len(m.sessionId)
-	numExtensions := 0
-	extensionsLength := 0
-
-	nextProtoLen := 0
-	if m.nextProtoNeg {
-		numExtensions++
-		for _, v := range m.nextProtos {
-			nextProtoLen += len(v)
-		}
-		nextProtoLen += len(m.nextProtos)
-		extensionsLength += nextProtoLen
-	}
-	if m.ocspStapling {
-		numExtensions++
-	}
-	if m.ticketSupported {
-		numExtensions++
-	}
-	if m.secureRenegotiation != nil {
-		extensionsLength += 1 + len(m.secureRenegotiation)
-		numExtensions++
-	}
-	if m.duplicateExtension {
-		numExtensions += 2
-	}
-	if m.channelIDRequested {
-		numExtensions++
-	}
-	if alpnLen := len(m.alpnProtocol); alpnLen > 0 || m.alpnProtocolEmpty {
-		if alpnLen >= 256 {
-			panic("invalid ALPN protocol")
-		}
-		extensionsLength += 2 + 1 + alpnLen
-		numExtensions++
-	}
-	if m.extendedMasterSecret {
-		numExtensions++
-	}
-	if m.srtpProtectionProfile != 0 {
-		extensionsLength += 2 + 2 + 1 + len(m.srtpMasterKeyIdentifier)
-		numExtensions++
-	}
-	if m.sctList != nil {
-		extensionsLength += len(m.sctList)
-		numExtensions++
-	}
-	if l := len(m.customExtension); l > 0 {
-		extensionsLength += l
-		numExtensions++
-	}
-
-	if numExtensions > 0 {
-		extensionsLength += 4 * numExtensions
-		length += 2 + extensionsLength
-	}
-
-	x := make([]byte, 4+length)
-	x[0] = typeServerHello
-	x[1] = uint8(length >> 16)
-	x[2] = uint8(length >> 8)
-	x[3] = uint8(length)
-	vers := versionToWire(m.vers, m.isDTLS)
-	x[4] = uint8(vers >> 8)
-	x[5] = uint8(vers)
-	copy(x[6:38], m.random)
-	x[38] = uint8(len(m.sessionId))
-	copy(x[39:39+len(m.sessionId)], m.sessionId)
-	z := x[39+len(m.sessionId):]
-	z[0] = uint8(m.cipherSuite >> 8)
-	z[1] = uint8(m.cipherSuite)
-	z[2] = uint8(m.compressionMethod)
-
-	z = z[3:]
-	if numExtensions > 0 {
-		z[0] = byte(extensionsLength >> 8)
-		z[1] = byte(extensionsLength)
-		z = z[2:]
-	}
+func (m *serverExtensions) marshal(extensions *byteBuilder) {
 	if m.duplicateExtension {
 		// Add a duplicate bogus extension at the beginning and end.
-		z[0] = 0xff
-		z[1] = 0xff
-		z = z[4:]
+		extensions.addU16(0xffff)
+		extensions.addU16(0) // length = 0 for empty extension
 	}
-	if m.nextProtoNeg && !m.npnLast {
-		z[0] = byte(extensionNextProtoNeg >> 8)
-		z[1] = byte(extensionNextProtoNeg & 0xff)
-		z[2] = byte(nextProtoLen >> 8)
-		z[3] = byte(nextProtoLen)
-		z = z[4:]
+	if m.nextProtoNeg && !m.npnAfterAlpn {
+		extensions.addU16(extensionNextProtoNeg)
+		extension := extensions.addU16LengthPrefixed()
 
 		for _, v := range m.nextProtos {
-			l := len(v)
-			if l > 255 {
-				l = 255
+			if len(v) > 255 {
+				v = v[:255]
 			}
-			z[0] = byte(l)
-			copy(z[1:], []byte(v[0:l]))
-			z = z[1+l:]
+			npn := extension.addU8LengthPrefixed()
+			npn.addBytes([]byte(v))
 		}
 	}
 	if m.ocspStapling {
-		z[0] = byte(extensionStatusRequest >> 8)
-		z[1] = byte(extensionStatusRequest)
-		z = z[4:]
+		extensions.addU16(extensionStatusRequest)
+		extensions.addU16(0)
 	}
 	if m.ticketSupported {
-		z[0] = byte(extensionSessionTicket >> 8)
-		z[1] = byte(extensionSessionTicket)
-		z = z[4:]
+		extensions.addU16(extensionSessionTicket)
+		extensions.addU16(0)
 	}
 	if m.secureRenegotiation != nil {
-		z[0] = byte(extensionRenegotiationInfo >> 8)
-		z[1] = byte(extensionRenegotiationInfo & 0xff)
-		z[2] = 0
-		z[3] = byte(1 + len(m.secureRenegotiation))
-		z[4] = byte(len(m.secureRenegotiation))
-		z = z[5:]
-		copy(z, m.secureRenegotiation)
-		z = z[len(m.secureRenegotiation):]
+		extensions.addU16(extensionRenegotiationInfo)
+		extension := extensions.addU16LengthPrefixed()
+		secureRenego := extension.addU8LengthPrefixed()
+		secureRenego.addBytes(m.secureRenegotiation)
 	}
-	if alpnLen := len(m.alpnProtocol); alpnLen > 0 || m.alpnProtocolEmpty {
-		z[0] = byte(extensionALPN >> 8)
-		z[1] = byte(extensionALPN & 0xff)
-		l := 2 + 1 + alpnLen
-		z[2] = byte(l >> 8)
-		z[3] = byte(l)
-		l -= 2
-		z[4] = byte(l >> 8)
-		z[5] = byte(l)
-		l -= 1
-		z[6] = byte(l)
-		copy(z[7:], []byte(m.alpnProtocol))
-		z = z[7+alpnLen:]
+	if len(m.alpnProtocol) > 0 || m.alpnProtocolEmpty {
+		extensions.addU16(extensionALPN)
+		extension := extensions.addU16LengthPrefixed()
+
+		protocolNameList := extension.addU16LengthPrefixed()
+		protocolName := protocolNameList.addU8LengthPrefixed()
+		protocolName.addBytes([]byte(m.alpnProtocol))
 	}
 	if m.channelIDRequested {
-		z[0] = byte(extensionChannelID >> 8)
-		z[1] = byte(extensionChannelID & 0xff)
-		z = z[4:]
+		extensions.addU16(extensionChannelID)
+		extensions.addU16(0)
 	}
 	if m.duplicateExtension {
 		// Add a duplicate bogus extension at the beginning and end.
-		z[0] = 0xff
-		z[1] = 0xff
-		z = z[4:]
+		extensions.addU16(0xffff)
+		extensions.addU16(0)
 	}
 	if m.extendedMasterSecret {
-		z[0] = byte(extensionExtendedMasterSecret >> 8)
-		z[1] = byte(extensionExtendedMasterSecret & 0xff)
-		z = z[4:]
+		extensions.addU16(extensionExtendedMasterSecret)
+		extensions.addU16(0)
 	}
 	if m.srtpProtectionProfile != 0 {
-		z[0] = byte(extensionUseSRTP >> 8)
-		z[1] = byte(extensionUseSRTP & 0xff)
-		l := 2 + 2 + 1 + len(m.srtpMasterKeyIdentifier)
-		z[2] = byte(l >> 8)
-		z[3] = byte(l & 0xff)
-		z[4] = 0
-		z[5] = 2
-		z[6] = byte(m.srtpProtectionProfile >> 8)
-		z[7] = byte(m.srtpProtectionProfile & 0xff)
-		l = len(m.srtpMasterKeyIdentifier)
-		z[8] = byte(l)
-		copy(z[9:], []byte(m.srtpMasterKeyIdentifier))
-		z = z[9+l:]
+		extensions.addU16(extensionUseSRTP)
+		extension := extensions.addU16LengthPrefixed()
+
+		srtpProtectionProfiles := extension.addU16LengthPrefixed()
+		srtpProtectionProfiles.addU8(byte(m.srtpProtectionProfile >> 8))
+		srtpProtectionProfiles.addU8(byte(m.srtpProtectionProfile))
+		srtpMki := extension.addU8LengthPrefixed()
+		srtpMki.addBytes([]byte(m.srtpMasterKeyIdentifier))
 	}
 	if m.sctList != nil {
-		z[0] = byte(extensionSignedCertificateTimestamp >> 8)
-		z[1] = byte(extensionSignedCertificateTimestamp & 0xff)
-		l := len(m.sctList)
-		z[2] = byte(l >> 8)
-		z[3] = byte(l & 0xff)
-		copy(z[4:], m.sctList)
-		z = z[4+l:]
+		extensions.addU16(extensionSignedCertificateTimestamp)
+		extension := extensions.addU16LengthPrefixed()
+		extension.addBytes(m.sctList)
 	}
 	if l := len(m.customExtension); l > 0 {
-		z[0] = byte(extensionCustom >> 8)
-		z[1] = byte(extensionCustom & 0xff)
-		z[2] = byte(l >> 8)
-		z[3] = byte(l & 0xff)
-		copy(z[4:], []byte(m.customExtension))
-		z = z[4+l:]
+		extensions.addU16(extensionCustom)
+		customExt := extensions.addU16LengthPrefixed()
+		customExt.addBytes([]byte(m.customExtension))
 	}
-	if m.nextProtoNeg && m.npnLast {
-		z[0] = byte(extensionNextProtoNeg >> 8)
-		z[1] = byte(extensionNextProtoNeg & 0xff)
-		z[2] = byte(nextProtoLen >> 8)
-		z[3] = byte(nextProtoLen)
-		z = z[4:]
+	if m.nextProtoNeg && m.npnAfterAlpn {
+		extensions.addU16(extensionNextProtoNeg)
+		extension := extensions.addU16LengthPrefixed()
 
 		for _, v := range m.nextProtos {
-			l := len(v)
-			if l > 255 {
-				l = 255
+			if len(v) > 255 {
+				v = v[0:255]
 			}
-			z[0] = byte(l)
-			copy(z[1:], []byte(v[0:l]))
-			z = z[1+l:]
+			npn := extension.addU8LengthPrefixed()
+			npn.addBytes([]byte(v))
 		}
 	}
-
-	m.raw = x
-
-	return x
+	if m.hasKeyShare {
+		extensions.addU16(extensionKeyShare)
+		keyShare := extensions.addU16LengthPrefixed()
+		keyShare.addU16(uint16(m.keyShare.group))
+		keyExchange := keyShare.addU16LengthPrefixed()
+		keyExchange.addBytes(m.keyShare.keyExchange)
+	}
+	if len(m.supportedPoints) > 0 {
+		// http://tools.ietf.org/html/rfc4492#section-5.1.2
+		extensions.addU16(extensionSupportedPoints)
+		supportedPointsList := extensions.addU16LengthPrefixed()
+		supportedPoints := supportedPointsList.addU8LengthPrefixed()
+		supportedPoints.addBytes(m.supportedPoints)
+	}
+	if m.hasEarlyData {
+		extensions.addU16(extensionEarlyData)
+		extensions.addBytes([]byte{0, 0})
+	}
+	if m.serverNameAck {
+		extensions.addU16(extensionServerName)
+		extensions.addU16(0) // zero length
+	}
 }
 
-func (m *serverHelloMsg) unmarshal(data []byte) bool {
-	if len(data) < 42 {
-		return false
-	}
-	m.raw = data
-	m.vers = wireToVersion(uint16(data[4])<<8|uint16(data[5]), m.isDTLS)
-	m.random = data[6:38]
-	sessionIdLen := int(data[38])
-	if sessionIdLen > 32 || len(data) < 39+sessionIdLen {
-		return false
-	}
-	m.sessionId = data[39 : 39+sessionIdLen]
-	data = data[39+sessionIdLen:]
-	if len(data) < 3 {
-		return false
-	}
-	m.cipherSuite = uint16(data[0])<<8 | uint16(data[1])
-	m.compressionMethod = data[2]
-	data = data[3:]
-
-	m.nextProtoNeg = false
-	m.nextProtos = nil
-	m.ocspStapling = false
-	m.ticketSupported = false
-	m.alpnProtocol = ""
-	m.alpnProtocolEmpty = false
-	m.extendedMasterSecret = false
-	m.customExtension = ""
-
-	if len(data) == 0 {
-		// ServerHello is optionally followed by extension data
-		return true
-	}
-	if len(data) < 2 {
-		return false
-	}
-
-	extensionsLength := int(data[0])<<8 | int(data[1])
-	data = data[2:]
-	if len(data) != extensionsLength {
-		return false
-	}
+func (m *serverExtensions) unmarshal(data []byte, version uint16) bool {
+	// Reset all fields.
+	*m = serverExtensions{}
 
 	for len(data) != 0 {
 		if len(data) < 4 {
@@ -992,6 +1260,38 @@
 			m.sctList = data[:length]
 		case extensionCustom:
 			m.customExtension = string(data[:length])
+		case extensionServerName:
+			if length != 0 {
+				return false
+			}
+			m.serverNameAck = true
+		case extensionSupportedPoints:
+			// supported_points is illegal in TLS 1.3.
+			if version >= VersionTLS13 {
+				return false
+			}
+			// http://tools.ietf.org/html/rfc4492#section-5.5.2
+			if length < 1 {
+				return false
+			}
+			l := int(data[0])
+			if length != l+1 {
+				return false
+			}
+			m.supportedPoints = data[1 : 1+l]
+		case extensionSupportedCurves:
+			// The server can only send supported_curves in TLS 1.3.
+			if version < VersionTLS13 {
+				return false
+			}
+		case extensionEarlyData:
+			if version < VersionTLS13 || length != 0 {
+				return false
+			}
+			m.hasEarlyData = true
+		default:
+			// Unknown extensions are illegal from the server.
+			return false
 		}
 		data = data[length:]
 	}
@@ -999,9 +1299,113 @@
 	return true
 }
 
+type helloRetryRequestMsg struct {
+	raw                 []byte
+	vers                uint16
+	hasSelectedGroup    bool
+	selectedGroup       CurveID
+	cookie              []byte
+	customExtension     string
+	duplicateExtensions bool
+}
+
+func (m *helloRetryRequestMsg) marshal() []byte {
+	if m.raw != nil {
+		return m.raw
+	}
+
+	retryRequestMsg := newByteBuilder()
+	retryRequestMsg.addU8(typeHelloRetryRequest)
+	retryRequest := retryRequestMsg.addU24LengthPrefixed()
+	retryRequest.addU16(m.vers)
+	extensions := retryRequest.addU16LengthPrefixed()
+
+	count := 1
+	if m.duplicateExtensions {
+		count = 2
+	}
+
+	for i := 0; i < count; i++ {
+		if m.hasSelectedGroup {
+			extensions.addU16(extensionKeyShare)
+			extensions.addU16(2) // length
+			extensions.addU16(uint16(m.selectedGroup))
+		}
+		if len(m.cookie) > 0 {
+			extensions.addU16(extensionCookie)
+			body := extensions.addU16LengthPrefixed()
+			body.addU16LengthPrefixed().addBytes(m.cookie)
+		}
+		if len(m.customExtension) > 0 {
+			extensions.addU16(extensionCustom)
+			extensions.addU16LengthPrefixed().addBytes([]byte(m.customExtension))
+		}
+	}
+
+	m.raw = retryRequestMsg.finish()
+	return m.raw
+}
+
+func (m *helloRetryRequestMsg) unmarshal(data []byte) bool {
+	m.raw = data
+	if len(data) < 8 {
+		return false
+	}
+	m.vers = uint16(data[4])<<8 | uint16(data[5])
+	extLen := int(data[6])<<8 | int(data[7])
+	data = data[8:]
+	if len(data) != extLen || len(data) == 0 {
+		return false
+	}
+	for len(data) > 0 {
+		if len(data) < 4 {
+			return false
+		}
+		extension := uint16(data[0])<<8 | uint16(data[1])
+		length := int(data[2])<<8 | int(data[3])
+		data = data[4:]
+		if len(data) < length {
+			return false
+		}
+
+		switch extension {
+		case extensionKeyShare:
+			if length != 2 {
+				return false
+			}
+			m.hasSelectedGroup = true
+			m.selectedGroup = CurveID(data[0])<<8 | CurveID(data[1])
+		case extensionCookie:
+			if length < 2 {
+				return false
+			}
+			cookieLen := int(data[0])<<8 | int(data[1])
+			if 2+cookieLen != length {
+				return false
+			}
+			m.cookie = data[2 : 2+cookieLen]
+		default:
+			// Unknown extensions are illegal from the server.
+			return false
+		}
+		data = data[length:]
+	}
+	return true
+}
+
+type certificateEntry struct {
+	data                []byte
+	ocspResponse        []byte
+	sctList             []byte
+	duplicateExtensions bool
+	extraExtension      []byte
+}
+
 type certificateMsg struct {
-	raw          []byte
-	certificates [][]byte
+	raw               []byte
+	hasRequestContext bool
+	requestContext    []byte
+	certificates      []certificateEntry
 }
 
 func (m *certificateMsg) marshal() (x []byte) {
@@ -1009,68 +1413,135 @@
 		return m.raw
 	}
 
-	var i int
-	for _, slice := range m.certificates {
-		i += len(slice)
+	certMsg := newByteBuilder()
+	certMsg.addU8(typeCertificate)
+	certificate := certMsg.addU24LengthPrefixed()
+	if m.hasRequestContext {
+		context := certificate.addU8LengthPrefixed()
+		context.addBytes(m.requestContext)
+	}
+	certificateList := certificate.addU24LengthPrefixed()
+	for _, cert := range m.certificates {
+		certEntry := certificateList.addU24LengthPrefixed()
+		certEntry.addBytes(cert.data)
+		if m.hasRequestContext {
+			extensions := certificateList.addU16LengthPrefixed()
+			count := 1
+			if cert.duplicateExtensions {
+				count = 2
+			}
+
+			for i := 0; i < count; i++ {
+				if cert.ocspResponse != nil {
+					extensions.addU16(extensionStatusRequest)
+					body := extensions.addU16LengthPrefixed()
+					body.addU8(statusTypeOCSP)
+					response := body.addU24LengthPrefixed()
+					response.addBytes(cert.ocspResponse)
+				}
+
+				if cert.sctList != nil {
+					extensions.addU16(extensionSignedCertificateTimestamp)
+					extension := extensions.addU16LengthPrefixed()
+					extension.addBytes(cert.sctList)
+				}
+			}
+			if cert.extraExtension != nil {
+				extensions.addBytes(cert.extraExtension)
+			}
+		}
 	}
 
-	length := 3 + 3*len(m.certificates) + i
-	x = make([]byte, 4+length)
-	x[0] = typeCertificate
-	x[1] = uint8(length >> 16)
-	x[2] = uint8(length >> 8)
-	x[3] = uint8(length)
-
-	certificateOctets := length - 3
-	x[4] = uint8(certificateOctets >> 16)
-	x[5] = uint8(certificateOctets >> 8)
-	x[6] = uint8(certificateOctets)
-
-	y := x[7:]
-	for _, slice := range m.certificates {
-		y[0] = uint8(len(slice) >> 16)
-		y[1] = uint8(len(slice) >> 8)
-		y[2] = uint8(len(slice))
-		copy(y[3:], slice)
-		y = y[3+len(slice):]
-	}
-
-	m.raw = x
-	return
+	m.raw = certMsg.finish()
+	return m.raw
 }
 
 func (m *certificateMsg) unmarshal(data []byte) bool {
-	if len(data) < 7 {
+	if len(data) < 4 {
 		return false
 	}
 
 	m.raw = data
-	certsLen := uint32(data[4])<<16 | uint32(data[5])<<8 | uint32(data[6])
-	if uint32(len(data)) != certsLen+7 {
+	data = data[4:]
+
+	if m.hasRequestContext {
+		if len(data) == 0 {
+			return false
+		}
+		contextLen := int(data[0])
+		if len(data) < 1+contextLen {
+			return false
+		}
+		m.requestContext = make([]byte, contextLen)
+		copy(m.requestContext, data[1:])
+		data = data[1+contextLen:]
+	}
+
+	if len(data) < 3 {
+		return false
+	}
+	certsLen := int(data[0])<<16 | int(data[1])<<8 | int(data[2])
+	data = data[3:]
+	if len(data) != certsLen {
 		return false
 	}
 
-	numCerts := 0
-	d := data[7:]
-	for certsLen > 0 {
-		if len(d) < 4 {
+	m.certificates = nil
+	for len(data) != 0 {
+		if len(data) < 3 {
 			return false
 		}
-		certLen := uint32(d[0])<<16 | uint32(d[1])<<8 | uint32(d[2])
-		if uint32(len(d)) < 3+certLen {
+		certLen := int(data[0])<<16 | int(data[1])<<8 | int(data[2])
+		if len(data) < 3+certLen {
 			return false
 		}
-		d = d[3+certLen:]
-		certsLen -= 3 + certLen
-		numCerts++
-	}
+		cert := certificateEntry{
+			data: data[3 : 3+certLen],
+		}
+		data = data[3+certLen:]
+		if m.hasRequestContext {
+			if len(data) < 2 {
+				return false
+			}
+			extensionsLen := int(data[0])<<8 | int(data[1])
+			if len(data) < 2+extensionsLen {
+				return false
+			}
+			extensions := data[2 : 2+extensionsLen]
+			data = data[2+extensionsLen:]
+			for len(extensions) != 0 {
+				if len(extensions) < 4 {
+					return false
+				}
+				extension := uint16(extensions[0])<<8 | uint16(extensions[1])
+				length := int(extensions[2])<<8 | int(extensions[3])
+				if len(extensions) < 4+length {
+					return false
+				}
+				contents := extensions[4 : 4+length]
+				extensions = extensions[4+length:]
 
-	m.certificates = make([][]byte, numCerts)
-	d = data[7:]
-	for i := 0; i < numCerts; i++ {
-		certLen := uint32(d[0])<<16 | uint32(d[1])<<8 | uint32(d[2])
-		m.certificates[i] = d[3 : 3+certLen]
-		d = d[3+certLen:]
+				switch extension {
+				case extensionStatusRequest:
+					if length < 4 {
+						return false
+					}
+					if contents[0] != statusTypeOCSP {
+						return false
+					}
+					respLen := int(contents[1])<<16 | int(contents[2])<<8 | int(contents[3])
+					if respLen+4 != len(contents) || respLen == 0 {
+						return false
+					}
+					cert.ocspResponse = contents[4:]
+				case extensionSignedCertificateTimestamp:
+					cert.sctList = contents
+				default:
+					return false
+				}
+			}
+		}
+		m.certificates = append(m.certificates, cert)
 	}
 
 	return true
@@ -1296,69 +1767,59 @@
 
 type certificateRequestMsg struct {
 	raw []byte
-	// hasSignatureAndHash indicates whether this message includes a list
+	// hasSignatureAlgorithm indicates whether this message includes a list
 	// of signature and hash functions. This change was introduced with TLS
 	// 1.2.
-	hasSignatureAndHash bool
+	hasSignatureAlgorithm bool
+	// hasRequestContext indicates whether this message includes a context
+	// field instead of certificateTypes. This change was introduced with
+	// TLS 1.3.
+	hasRequestContext bool
 
 	certificateTypes       []byte
-	signatureAndHashes     []signatureAndHash
+	requestContext         []byte
+	signatureAlgorithms    []signatureAlgorithm
 	certificateAuthorities [][]byte
 }
 
-func (m *certificateRequestMsg) marshal() (x []byte) {
+func (m *certificateRequestMsg) marshal() []byte {
 	if m.raw != nil {
 		return m.raw
 	}
 
 	// See http://tools.ietf.org/html/rfc4346#section-7.4.4
-	length := 1 + len(m.certificateTypes) + 2
-	casLength := 0
-	for _, ca := range m.certificateAuthorities {
-		casLength += 2 + len(ca)
-	}
-	length += casLength
+	builder := newByteBuilder()
+	builder.addU8(typeCertificateRequest)
+	body := builder.addU24LengthPrefixed()
 
-	if m.hasSignatureAndHash {
-		length += 2 + 2*len(m.signatureAndHashes)
+	if m.hasRequestContext {
+		requestContext := body.addU8LengthPrefixed()
+		requestContext.addBytes(m.requestContext)
+	} else {
+		certificateTypes := body.addU8LengthPrefixed()
+		certificateTypes.addBytes(m.certificateTypes)
 	}
 
-	x = make([]byte, 4+length)
-	x[0] = typeCertificateRequest
-	x[1] = uint8(length >> 16)
-	x[2] = uint8(length >> 8)
-	x[3] = uint8(length)
-
-	x[4] = uint8(len(m.certificateTypes))
-
-	copy(x[5:], m.certificateTypes)
-	y := x[5+len(m.certificateTypes):]
-
-	if m.hasSignatureAndHash {
-		n := len(m.signatureAndHashes) * 2
-		y[0] = uint8(n >> 8)
-		y[1] = uint8(n)
-		y = y[2:]
-		for _, sigAndHash := range m.signatureAndHashes {
-			y[0] = sigAndHash.hash
-			y[1] = sigAndHash.signature
-			y = y[2:]
+	if m.hasSignatureAlgorithm {
+		signatureAlgorithms := body.addU16LengthPrefixed()
+		for _, sigAlg := range m.signatureAlgorithms {
+			signatureAlgorithms.addU16(uint16(sigAlg))
 		}
 	}
 
-	y[0] = uint8(casLength >> 8)
-	y[1] = uint8(casLength)
-	y = y[2:]
+	certificateAuthorities := body.addU16LengthPrefixed()
 	for _, ca := range m.certificateAuthorities {
-		y[0] = uint8(len(ca) >> 8)
-		y[1] = uint8(len(ca))
-		y = y[2:]
-		copy(y, ca)
-		y = y[len(ca):]
+		caEntry := certificateAuthorities.addU16LengthPrefixed()
+		caEntry.addBytes(ca)
 	}
 
-	m.raw = x
-	return
+	if m.hasRequestContext {
+		// Emit no certificate extensions.
+		body.addU16(0)
+	}
+
+	m.raw = builder.finish()
+	return m.raw
 }
 
 func (m *certificateRequestMsg) unmarshal(data []byte) bool {
@@ -1367,42 +1828,42 @@
 	if len(data) < 5 {
 		return false
 	}
+	data = data[4:]
 
-	length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
-	if uint32(len(data))-4 != length {
-		return false
+	if m.hasRequestContext {
+		contextLen := int(data[0])
+		if len(data) < 1+contextLen {
+			return false
+		}
+		m.requestContext = make([]byte, contextLen)
+		copy(m.requestContext, data[1:])
+		data = data[1+contextLen:]
+	} else {
+		numCertTypes := int(data[0])
+		if len(data) < 1+numCertTypes {
+			return false
+		}
+		m.certificateTypes = make([]byte, numCertTypes)
+		copy(m.certificateTypes, data[1:])
+		data = data[1+numCertTypes:]
 	}
 
-	numCertTypes := int(data[4])
-	data = data[5:]
-	if numCertTypes == 0 || len(data) <= numCertTypes {
-		return false
-	}
-
-	m.certificateTypes = make([]byte, numCertTypes)
-	if copy(m.certificateTypes, data) != numCertTypes {
-		return false
-	}
-
-	data = data[numCertTypes:]
-
-	if m.hasSignatureAndHash {
+	if m.hasSignatureAlgorithm {
 		if len(data) < 2 {
 			return false
 		}
-		sigAndHashLen := uint16(data[0])<<8 | uint16(data[1])
+		sigAlgsLen := uint16(data[0])<<8 | uint16(data[1])
 		data = data[2:]
-		if sigAndHashLen&1 != 0 {
+		if sigAlgsLen&1 != 0 {
 			return false
 		}
-		if len(data) < int(sigAndHashLen) {
+		if len(data) < int(sigAlgsLen) {
 			return false
 		}
-		numSigAndHash := sigAndHashLen / 2
-		m.signatureAndHashes = make([]signatureAndHash, numSigAndHash)
-		for i := range m.signatureAndHashes {
-			m.signatureAndHashes[i].hash = data[0]
-			m.signatureAndHashes[i].signature = data[1]
+		numSigAlgs := sigAlgsLen / 2
+		m.signatureAlgorithms = make([]signatureAlgorithm, numSigAlgs)
+		for i := range m.signatureAlgorithms {
+			m.signatureAlgorithms[i] = signatureAlgorithm(data[0])<<8 | signatureAlgorithm(data[1])
 			data = data[2:]
 		}
 	}
@@ -1434,6 +1895,19 @@
 		m.certificateAuthorities = append(m.certificateAuthorities, cas[:caLen])
 		cas = cas[caLen:]
 	}
+
+	if m.hasRequestContext {
+		// Ignore certificate extensions.
+		if len(data) < 2 {
+			return false
+		}
+		extsLength := int(data[0])<<8 | int(data[1])
+		if len(data) < 2+extsLength {
+			return false
+		}
+		data = data[2+extsLength:]
+	}
+
 	if len(data) > 0 {
 		return false
 	}
@@ -1442,10 +1916,10 @@
 }
 
 type certificateVerifyMsg struct {
-	raw                 []byte
-	hasSignatureAndHash bool
-	signatureAndHash    signatureAndHash
-	signature           []byte
+	raw                   []byte
+	hasSignatureAlgorithm bool
+	signatureAlgorithm    signatureAlgorithm
+	signature             []byte
 }
 
 func (m *certificateVerifyMsg) marshal() (x []byte) {
@@ -1456,7 +1930,7 @@
 	// See http://tools.ietf.org/html/rfc4346#section-7.4.8
 	siglength := len(m.signature)
 	length := 2 + siglength
-	if m.hasSignatureAndHash {
+	if m.hasSignatureAlgorithm {
 		length += 2
 	}
 	x = make([]byte, 4+length)
@@ -1465,9 +1939,9 @@
 	x[2] = uint8(length >> 8)
 	x[3] = uint8(length)
 	y := x[4:]
-	if m.hasSignatureAndHash {
-		y[0] = m.signatureAndHash.hash
-		y[1] = m.signatureAndHash.signature
+	if m.hasSignatureAlgorithm {
+		y[0] = byte(m.signatureAlgorithm >> 8)
+		y[1] = byte(m.signatureAlgorithm)
 		y = y[2:]
 	}
 	y[0] = uint8(siglength >> 8)
@@ -1492,9 +1966,8 @@
 	}
 
 	data = data[4:]
-	if m.hasSignatureAndHash {
-		m.signatureAndHash.hash = data[0]
-		m.signatureAndHash.signature = data[1]
+	if m.hasSignatureAlgorithm {
+		m.signatureAlgorithm = signatureAlgorithm(data[0])<<8 | signatureAlgorithm(data[1])
 		data = data[2:]
 	}
 
@@ -1513,50 +1986,128 @@
 }
 
 type newSessionTicketMsg struct {
-	raw    []byte
-	ticket []byte
+	raw                    []byte
+	version                uint16
+	ticketLifetime         uint32
+	ticketAgeAdd           uint32
+	ticket                 []byte
+	maxEarlyDataSize       uint32
+	customExtension        string
+	duplicateEarlyDataInfo bool
+	hasGREASEExtension     bool
 }
 
-func (m *newSessionTicketMsg) marshal() (x []byte) {
+func (m *newSessionTicketMsg) marshal() []byte {
 	if m.raw != nil {
 		return m.raw
 	}
 
 	// See http://tools.ietf.org/html/rfc5077#section-3.3
-	ticketLen := len(m.ticket)
-	length := 2 + 4 + ticketLen
-	x = make([]byte, 4+length)
-	x[0] = typeNewSessionTicket
-	x[1] = uint8(length >> 16)
-	x[2] = uint8(length >> 8)
-	x[3] = uint8(length)
-	x[8] = uint8(ticketLen >> 8)
-	x[9] = uint8(ticketLen)
-	copy(x[10:], m.ticket)
+	ticketMsg := newByteBuilder()
+	ticketMsg.addU8(typeNewSessionTicket)
+	body := ticketMsg.addU24LengthPrefixed()
+	body.addU32(m.ticketLifetime)
+	if m.version >= VersionTLS13 {
+		body.addU32(m.ticketAgeAdd)
+	}
 
-	m.raw = x
+	ticket := body.addU16LengthPrefixed()
+	ticket.addBytes(m.ticket)
 
-	return
+	if m.version >= VersionTLS13 {
+		extensions := body.addU16LengthPrefixed()
+		if m.maxEarlyDataSize > 0 {
+			extensions.addU16(extensionTicketEarlyDataInfo)
+			extensions.addU16LengthPrefixed().addU32(m.maxEarlyDataSize)
+			if m.duplicateEarlyDataInfo {
+				extensions.addU16(extensionTicketEarlyDataInfo)
+				extensions.addU16LengthPrefixed().addU32(m.maxEarlyDataSize)
+			}
+		}
+		if len(m.customExtension) > 0 {
+			extensions.addU16(extensionCustom)
+			extensions.addU16LengthPrefixed().addBytes([]byte(m.customExtension))
+		}
+	}
+
+	m.raw = ticketMsg.finish()
+	return m.raw
 }
 
 func (m *newSessionTicketMsg) unmarshal(data []byte) bool {
 	m.raw = data
 
-	if len(data) < 10 {
+	if len(data) < 8 {
+		return false
+	}
+	m.ticketLifetime = uint32(data[4])<<24 | uint32(data[5])<<16 | uint32(data[6])<<8 | uint32(data[7])
+	data = data[8:]
+
+	if m.version >= VersionTLS13 {
+		if len(data) < 4 {
+			return false
+		}
+		m.ticketAgeAdd = uint32(data[0])<<24 | uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
+		data = data[4:]
+	}
+
+	if len(data) < 2 {
+		return false
+	}
+	ticketLen := int(data[0])<<8 + int(data[1])
+	data = data[2:]
+	if len(data) < ticketLen {
 		return false
 	}
 
-	length := uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
-	if uint32(len(data))-4 != length {
+	if m.version >= VersionTLS13 && ticketLen == 0 {
 		return false
 	}
 
-	ticketLen := int(data[8])<<8 + int(data[9])
-	if len(data)-10 != ticketLen {
-		return false
+	m.ticket = data[:ticketLen]
+	data = data[ticketLen:]
+
+	if m.version >= VersionTLS13 {
+		if len(data) < 2 {
+			return false
+		}
+
+		extensionsLength := int(data[0])<<8 | int(data[1])
+		data = data[2:]
+		if extensionsLength != len(data) {
+			return false
+		}
+
+		for len(data) != 0 {
+			if len(data) < 4 {
+				return false
+			}
+			extension := uint16(data[0])<<8 | uint16(data[1])
+			length := int(data[2])<<8 | int(data[3])
+			data = data[4:]
+			if len(data) < length {
+				return false
+			}
+
+			switch extension {
+			case extensionTicketEarlyDataInfo:
+				if length != 4 {
+					return false
+				}
+				m.maxEarlyDataSize = uint32(data[0])<<24 | uint32(data[1])<<16 | uint32(data[2])<<8 | uint32(data[3])
+			default:
+				if isGREASEValue(extension) {
+					m.hasGREASEExtension = true
+				}
+			}
+
+			data = data[length:]
+		}
 	}
 
-	m.ticket = data[10:]
+	if len(data) > 0 {
+		return false
+	}
 
 	return true
 }
@@ -1620,7 +2171,7 @@
 	x[1] = uint8(length >> 16)
 	x[2] = uint8(length >> 8)
 	x[3] = uint8(length)
-	vers := versionToWire(m.vers, true)
+	vers := m.vers
 	x[4] = uint8(vers >> 8)
 	x[5] = uint8(vers)
 	x[6] = uint8(len(m.cookie))
@@ -1634,7 +2185,7 @@
 		return false
 	}
 	m.raw = data
-	m.vers = wireToVersion(uint16(data[4])<<8|uint16(data[5]), true)
+	m.vers = uint16(data[4])<<8 | uint16(data[5])
 	cookieLen := int(data[6])
 	if cookieLen > 32 || len(data) != 7+cookieLen {
 		return false
@@ -1644,12 +2195,12 @@
 	return true
 }
 
-type encryptedExtensionsMsg struct {
+type channelIDMsg struct {
 	raw       []byte
 	channelID []byte
 }
 
-func (m *encryptedExtensionsMsg) marshal() []byte {
+func (m *channelIDMsg) marshal() []byte {
 	if m.raw != nil {
 		return m.raw
 	}
@@ -1657,7 +2208,7 @@
 	length := 2 + 2 + len(m.channelID)
 
 	x := make([]byte, 4+length)
-	x[0] = typeEncryptedExtensions
+	x[0] = typeChannelID
 	x[1] = uint8(length >> 16)
 	x[2] = uint8(length >> 8)
 	x[3] = uint8(length)
@@ -1670,7 +2221,7 @@
 	return x
 }
 
-func (m *encryptedExtensionsMsg) unmarshal(data []byte) bool {
+func (m *channelIDMsg) unmarshal(data []byte) bool {
 	if len(data) != 4+2+2+128 {
 		return false
 	}
@@ -1697,6 +2248,39 @@
 	return len(data) == 4
 }
 
+type keyUpdateMsg struct {
+	raw              []byte
+	keyUpdateRequest byte
+}
+
+func (m *keyUpdateMsg) marshal() []byte {
+	if m.raw != nil {
+		return m.raw
+	}
+
+	return []byte{typeKeyUpdate, 0, 0, 1, m.keyUpdateRequest}
+}
+
+func (m *keyUpdateMsg) unmarshal(data []byte) bool {
+	m.raw = data
+
+	if len(data) != 5 {
+		return false
+	}
+
+	length := int(data[1])<<16 | int(data[2])<<8 | int(data[3])
+	if len(data)-4 != length {
+		return false
+	}
+
+	m.keyUpdateRequest = data[4]
+	return m.keyUpdateRequest == keyUpdateNotRequested || m.keyUpdateRequest == keyUpdateRequested
+}
+
+// ssl3NoCertificateMsg is a dummy message to handle SSL 3.0 using a warning
+// alert in the handshake.
+type ssl3NoCertificateMsg struct{}
+
 func eqUint16s(x, y []uint16) bool {
 	if len(x) != len(y) {
 		return false
@@ -1745,15 +2329,41 @@
 	return true
 }
 
-func eqSignatureAndHashes(x, y []signatureAndHash) bool {
+func eqSignatureAlgorithms(x, y []signatureAlgorithm) bool {
 	if len(x) != len(y) {
 		return false
 	}
 	for i, v := range x {
 		v2 := y[i]
-		if v.hash != v2.hash || v.signature != v2.signature {
+		if v != v2 {
 			return false
 		}
 	}
 	return true
 }
+
+func eqKeyShareEntryLists(x, y []keyShareEntry) bool {
+	if len(x) != len(y) {
+		return false
+	}
+	for i, v := range x {
+		if y[i].group != v.group || !bytes.Equal(y[i].keyExchange, v.keyExchange) {
+			return false
+		}
+	}
+	return true
+
+}
+
+func eqPSKIdentityLists(x, y []pskIdentity) bool {
+	if len(x) != len(y) {
+		return false
+	}
+	for i, v := range x {
+		if !bytes.Equal(y[i].ticket, v.ticket) || y[i].obfuscatedTicketAge != v.obfuscatedTicketAge {
+			return false
+		}
+	}
+	return true
+
+}
diff --git a/src/ssl/test/runner/handshake_server.go b/src/ssl/test/runner/handshake_server.go
index 0232772..ef144c3 100644
--- a/src/ssl/test/runner/handshake_server.go
+++ b/src/ssl/test/runner/handshake_server.go
@@ -12,11 +12,11 @@
 	"crypto/rsa"
 	"crypto/subtle"
 	"crypto/x509"
-	"encoding/asn1"
 	"errors"
 	"fmt"
 	"io"
 	"math/big"
+	"time"
 )
 
 // serverHandshakeState contains details of a server handshake in progress.
@@ -50,127 +50,139 @@
 	hs := serverHandshakeState{
 		c: c,
 	}
-	isResume, err := hs.readClientHello()
-	if err != nil {
+	if err := hs.readClientHello(); err != nil {
 		return err
 	}
 
-	// For an overview of TLS handshaking, see https://tools.ietf.org/html/rfc5246#section-7.3
-	if isResume {
-		// The client has included a session ticket and so we do an abbreviated handshake.
-		if err := hs.doResumeHandshake(); err != nil {
+	if c.vers >= VersionTLS13 {
+		if err := hs.doTLS13Handshake(); err != nil {
 			return err
 		}
-		if err := hs.establishKeys(); err != nil {
+	} else {
+		isResume, err := hs.processClientHello()
+		if err != nil {
 			return err
 		}
-		if c.config.Bugs.RenewTicketOnResume {
+
+		// For an overview of TLS handshaking, see https://tools.ietf.org/html/rfc5246#section-7.3
+		if isResume {
+			// The client has included a session ticket and so we do an abbreviated handshake.
+			if err := hs.doResumeHandshake(); err != nil {
+				return err
+			}
+			if err := hs.establishKeys(); err != nil {
+				return err
+			}
+			if c.config.Bugs.RenewTicketOnResume {
+				if err := hs.sendSessionTicket(); err != nil {
+					return err
+				}
+			}
+			if err := hs.sendFinished(c.firstFinished[:]); err != nil {
+				return err
+			}
+			// Most retransmits are triggered by a timeout, but the final
+			// leg of the handshake is retransmited upon re-receiving a
+			// Finished.
+			if err := c.simulatePacketLoss(func() {
+				c.sendHandshakeSeq--
+				c.writeRecord(recordTypeHandshake, hs.finishedBytes)
+				c.flushHandshake()
+			}); err != nil {
+				return err
+			}
+			if err := hs.readFinished(nil, isResume); err != nil {
+				return err
+			}
+			c.didResume = true
+		} else {
+			// The client didn't include a session ticket, or it wasn't
+			// valid so we do a full handshake.
+			if err := hs.doFullHandshake(); err != nil {
+				return err
+			}
+			if err := hs.establishKeys(); err != nil {
+				return err
+			}
+			if err := hs.readFinished(c.firstFinished[:], isResume); err != nil {
+				return err
+			}
+			if c.config.Bugs.AlertBeforeFalseStartTest != 0 {
+				c.sendAlert(c.config.Bugs.AlertBeforeFalseStartTest)
+			}
+			if c.config.Bugs.ExpectFalseStart {
+				if err := c.readRecord(recordTypeApplicationData); err != nil {
+					return fmt.Errorf("tls: peer did not false start: %s", err)
+				}
+			}
 			if err := hs.sendSessionTicket(); err != nil {
 				return err
 			}
-		}
-		if err := hs.sendFinished(c.firstFinished[:]); err != nil {
-			return err
-		}
-		// Most retransmits are triggered by a timeout, but the final
-		// leg of the handshake is retransmited upon re-receiving a
-		// Finished.
-		if err := c.simulatePacketLoss(func() {
-			c.writeRecord(recordTypeHandshake, hs.finishedBytes)
-			c.dtlsFlushHandshake()
-		}); err != nil {
-			return err
-		}
-		if err := hs.readFinished(nil, isResume); err != nil {
-			return err
-		}
-		c.didResume = true
-	} else {
-		// The client didn't include a session ticket, or it wasn't
-		// valid so we do a full handshake.
-		if err := hs.doFullHandshake(); err != nil {
-			return err
-		}
-		if err := hs.establishKeys(); err != nil {
-			return err
-		}
-		if err := hs.readFinished(c.firstFinished[:], isResume); err != nil {
-			return err
-		}
-		if c.config.Bugs.AlertBeforeFalseStartTest != 0 {
-			c.sendAlert(c.config.Bugs.AlertBeforeFalseStartTest)
-		}
-		if c.config.Bugs.ExpectFalseStart {
-			if err := c.readRecord(recordTypeApplicationData); err != nil {
-				return fmt.Errorf("tls: peer did not false start: %s", err)
+			if err := hs.sendFinished(nil); err != nil {
+				return err
 			}
 		}
-		if err := hs.sendSessionTicket(); err != nil {
-			return err
-		}
-		if err := hs.sendFinished(nil); err != nil {
-			return err
-		}
+
+		c.exporterSecret = hs.masterSecret
 	}
 	c.handshakeComplete = true
 	copy(c.clientRandom[:], hs.clientHello.random)
 	copy(c.serverRandom[:], hs.hello.random)
-	copy(c.masterSecret[:], hs.masterSecret)
 
 	return nil
 }
 
-// readClientHello reads a ClientHello message from the client and decides
-// whether we will perform session resumption.
-func (hs *serverHandshakeState) readClientHello() (isResume bool, err error) {
+// readClientHello reads a ClientHello message from the client and determines
+// the protocol version.
+func (hs *serverHandshakeState) readClientHello() error {
 	config := hs.c.config
 	c := hs.c
 
 	if err := c.simulatePacketLoss(nil); err != nil {
-		return false, err
+		return err
 	}
 	msg, err := c.readHandshake()
 	if err != nil {
-		return false, err
+		return err
 	}
 	var ok bool
 	hs.clientHello, ok = msg.(*clientHelloMsg)
 	if !ok {
 		c.sendAlert(alertUnexpectedMessage)
-		return false, unexpectedMessageError(hs.clientHello, msg)
+		return unexpectedMessageError(hs.clientHello, msg)
 	}
 	if size := config.Bugs.RequireClientHelloSize; size != 0 && len(hs.clientHello.raw) != size {
-		return false, fmt.Errorf("tls: ClientHello record size is %d, but expected %d", len(hs.clientHello.raw), size)
+		return fmt.Errorf("tls: ClientHello record size is %d, but expected %d", len(hs.clientHello.raw), size)
 	}
 
 	if c.isDTLS && !config.Bugs.SkipHelloVerifyRequest {
 		// Per RFC 6347, the version field in HelloVerifyRequest SHOULD
 		// be always DTLS 1.0
 		helloVerifyRequest := &helloVerifyRequestMsg{
-			vers:   VersionTLS10,
+			vers:   versionToWire(VersionTLS10, c.isDTLS),
 			cookie: make([]byte, 32),
 		}
 		if _, err := io.ReadFull(c.config.rand(), helloVerifyRequest.cookie); err != nil {
 			c.sendAlert(alertInternalError)
-			return false, errors.New("dtls: short read from Rand: " + err.Error())
+			return errors.New("dtls: short read from Rand: " + err.Error())
 		}
 		c.writeRecord(recordTypeHandshake, helloVerifyRequest.marshal())
-		c.dtlsFlushHandshake()
+		c.flushHandshake()
 
 		if err := c.simulatePacketLoss(nil); err != nil {
-			return false, err
+			return err
 		}
 		msg, err := c.readHandshake()
 		if err != nil {
-			return false, err
+			return err
 		}
 		newClientHello, ok := msg.(*clientHelloMsg)
 		if !ok {
 			c.sendAlert(alertUnexpectedMessage)
-			return false, unexpectedMessageError(hs.clientHello, msg)
+			return unexpectedMessageError(hs.clientHello, msg)
 		}
 		if !bytes.Equal(newClientHello.cookie, helloVerifyRequest.cookie) {
-			return false, errors.New("dtls: invalid cookie")
+			return errors.New("dtls: invalid cookie")
 		}
 
 		// Apart from the cookie, the two ClientHellos must
@@ -183,53 +195,886 @@
 		newClientHelloCopy.raw = nil
 		newClientHelloCopy.cookie = nil
 		if !oldClientHelloCopy.equal(&newClientHelloCopy) {
-			return false, errors.New("dtls: retransmitted ClientHello does not match")
+			return errors.New("dtls: retransmitted ClientHello does not match")
 		}
 		hs.clientHello = newClientHello
 	}
 
 	if config.Bugs.RequireSameRenegoClientVersion && c.clientVersion != 0 {
 		if c.clientVersion != hs.clientHello.vers {
-			return false, fmt.Errorf("tls: client offered different version on renego")
+			return fmt.Errorf("tls: client offered different version on renego")
 		}
 	}
+
 	c.clientVersion = hs.clientHello.vers
 
-	// Reject < 1.2 ClientHellos with signature_algorithms.
-	if c.clientVersion < VersionTLS12 && len(hs.clientHello.signatureAndHashes) > 0 {
-		return false, fmt.Errorf("tls: client included signature_algorithms before TLS 1.2")
+	// Convert the ClientHello wire version to a protocol version.
+	var clientVersion uint16
+	if c.isDTLS {
+		if hs.clientHello.vers <= 0xfefd {
+			clientVersion = VersionTLS12
+		} else if hs.clientHello.vers <= 0xfeff {
+			clientVersion = VersionTLS10
+		}
+	} else {
+		if hs.clientHello.vers >= VersionTLS12 {
+			clientVersion = VersionTLS12
+		} else if hs.clientHello.vers >= VersionTLS11 {
+			clientVersion = VersionTLS11
+		} else if hs.clientHello.vers >= VersionTLS10 {
+			clientVersion = VersionTLS10
+		} else if hs.clientHello.vers >= VersionSSL30 {
+			clientVersion = VersionSSL30
+		}
 	}
-	if config.Bugs.IgnorePeerSignatureAlgorithmPreferences {
-		hs.clientHello.signatureAndHashes = config.signatureAndHashesForServer()
+
+	if config.Bugs.NegotiateVersion != 0 {
+		c.vers = config.Bugs.NegotiateVersion
+	} else if c.haveVers && config.Bugs.NegotiateVersionOnRenego != 0 {
+		c.vers = config.Bugs.NegotiateVersionOnRenego
+	} else if len(hs.clientHello.supportedVersions) > 0 {
+		// Use the versions extension if supplied.
+		var foundVersion, foundGREASE bool
+		for _, extVersion := range hs.clientHello.supportedVersions {
+			if isGREASEValue(extVersion) {
+				foundGREASE = true
+			}
+			extVersion, ok = wireToVersion(extVersion, c.isDTLS)
+			if !ok {
+				continue
+			}
+			if config.isSupportedVersion(extVersion, c.isDTLS) && !foundVersion {
+				c.vers = extVersion
+				foundVersion = true
+				break
+			}
+		}
+		if !foundVersion {
+			c.sendAlert(alertProtocolVersion)
+			return errors.New("tls: client did not offer any supported protocol versions")
+		}
+		if config.Bugs.ExpectGREASE && !foundGREASE {
+			return errors.New("tls: no GREASE version value found")
+		}
+	} else {
+		// Otherwise, use the legacy ClientHello version.
+		version := clientVersion
+		if maxVersion := config.maxVersion(c.isDTLS); version > maxVersion {
+			version = maxVersion
+		}
+		if version == 0 || !config.isSupportedVersion(version, c.isDTLS) {
+			return fmt.Errorf("tls: client offered an unsupported, maximum protocol version of %x", hs.clientHello.vers)
+		}
+		c.vers = version
+	}
+	c.haveVers = true
+
+	// Reject < 1.2 ClientHellos with signature_algorithms.
+	if clientVersion < VersionTLS12 && len(hs.clientHello.signatureAlgorithms) > 0 {
+		return fmt.Errorf("tls: client included signature_algorithms before TLS 1.2")
 	}
 
 	// Check the client cipher list is consistent with the version.
-	if hs.clientHello.vers < VersionTLS12 {
+	if clientVersion < VersionTLS12 {
 		for _, id := range hs.clientHello.cipherSuites {
 			if isTLS12Cipher(id) {
-				return false, fmt.Errorf("tls: client offered TLS 1.2 cipher before TLS 1.2")
+				return fmt.Errorf("tls: client offered TLS 1.2 cipher before TLS 1.2")
 			}
 		}
 	}
 
-	c.vers, ok = config.mutualVersion(hs.clientHello.vers)
-	if !ok {
-		c.sendAlert(alertProtocolVersion)
-		return false, fmt.Errorf("tls: client offered an unsupported, maximum protocol version of %x", hs.clientHello.vers)
+	if config.Bugs.ExpectNoTLS12Session {
+		if len(hs.clientHello.sessionId) > 0 {
+			return fmt.Errorf("tls: client offered an unexpected session ID")
+		}
+		if len(hs.clientHello.sessionTicket) > 0 {
+			return fmt.Errorf("tls: client offered an unexpected session ticket")
+		}
 	}
-	c.haveVers = true
+
+	if config.Bugs.ExpectNoTLS13PSK && len(hs.clientHello.pskIdentities) > 0 {
+		return fmt.Errorf("tls: client offered unexpected PSK identities")
+	}
+
+	var scsvFound, greaseFound bool
+	for _, cipherSuite := range hs.clientHello.cipherSuites {
+		if cipherSuite == fallbackSCSV {
+			scsvFound = true
+		}
+		if isGREASEValue(cipherSuite) {
+			greaseFound = true
+		}
+	}
+
+	if !scsvFound && config.Bugs.FailIfNotFallbackSCSV {
+		return errors.New("tls: no fallback SCSV found when expected")
+	} else if scsvFound && !config.Bugs.FailIfNotFallbackSCSV {
+		return errors.New("tls: fallback SCSV found when not expected")
+	}
+
+	if !greaseFound && config.Bugs.ExpectGREASE {
+		return errors.New("tls: no GREASE cipher suite value found")
+	}
+
+	greaseFound = false
+	for _, curve := range hs.clientHello.supportedCurves {
+		if isGREASEValue(uint16(curve)) {
+			greaseFound = true
+			break
+		}
+	}
+
+	if !greaseFound && config.Bugs.ExpectGREASE {
+		return errors.New("tls: no GREASE curve value found")
+	}
+
+	if len(hs.clientHello.keyShares) > 0 {
+		greaseFound = false
+		for _, keyShare := range hs.clientHello.keyShares {
+			if isGREASEValue(uint16(keyShare.group)) {
+				greaseFound = true
+				break
+			}
+		}
+
+		if !greaseFound && config.Bugs.ExpectGREASE {
+			return errors.New("tls: no GREASE curve value found")
+		}
+	}
+
+	applyBugsToClientHello(hs.clientHello, config)
+
+	return nil
+}
+
+func applyBugsToClientHello(clientHello *clientHelloMsg, config *Config) {
+	if config.Bugs.IgnorePeerSignatureAlgorithmPreferences {
+		clientHello.signatureAlgorithms = config.signSignatureAlgorithms()
+	}
+	if config.Bugs.IgnorePeerCurvePreferences {
+		clientHello.supportedCurves = config.curvePreferences()
+	}
+	if config.Bugs.IgnorePeerCipherPreferences {
+		clientHello.cipherSuites = config.cipherSuites()
+	}
+}
+
+func (hs *serverHandshakeState) doTLS13Handshake() error {
+	c := hs.c
+	config := c.config
 
 	hs.hello = &serverHelloMsg{
 		isDTLS:          c.isDTLS,
-		customExtension: config.Bugs.CustomExtension,
-		npnLast:         config.Bugs.SwapNPNAndALPN,
+		vers:            versionToWire(c.vers, c.isDTLS),
+		versOverride:    config.Bugs.SendServerHelloVersion,
+		customExtension: config.Bugs.CustomUnencryptedExtension,
+		unencryptedALPN: config.Bugs.SendUnencryptedALPN,
+	}
+
+	hs.hello.random = make([]byte, 32)
+	if _, err := io.ReadFull(config.rand(), hs.hello.random); err != nil {
+		c.sendAlert(alertInternalError)
+		return err
+	}
+
+	// TLS 1.3 forbids clients from advertising any non-null compression.
+	if len(hs.clientHello.compressionMethods) != 1 || hs.clientHello.compressionMethods[0] != compressionNone {
+		return errors.New("tls: client sent compression method other than null for TLS 1.3")
+	}
+
+	// Prepare an EncryptedExtensions message, but do not send it yet.
+	encryptedExtensions := new(encryptedExtensionsMsg)
+	encryptedExtensions.empty = config.Bugs.EmptyEncryptedExtensions
+	if err := hs.processClientExtensions(&encryptedExtensions.extensions); err != nil {
+		return err
+	}
+
+	// Select the cipher suite.
+	var preferenceList, supportedList []uint16
+	if config.PreferServerCipherSuites {
+		preferenceList = config.cipherSuites()
+		supportedList = hs.clientHello.cipherSuites
+	} else {
+		preferenceList = hs.clientHello.cipherSuites
+		supportedList = config.cipherSuites()
+	}
+
+	for _, id := range preferenceList {
+		if hs.suite = c.tryCipherSuite(id, supportedList, c.vers, true, true); hs.suite != nil {
+			break
+		}
+	}
+
+	if hs.suite == nil {
+		c.sendAlert(alertHandshakeFailure)
+		return errors.New("tls: no cipher suite supported by both client and server")
+	}
+
+	hs.hello.cipherSuite = hs.suite.id
+	if c.config.Bugs.SendCipherSuite != 0 {
+		hs.hello.cipherSuite = c.config.Bugs.SendCipherSuite
+	}
+
+	hs.finishedHash = newFinishedHash(c.vers, hs.suite)
+	hs.finishedHash.discardHandshakeBuffer()
+	hs.writeClientHash(hs.clientHello.marshal())
+
+	supportedCurve := false
+	var selectedCurve CurveID
+	preferredCurves := config.curvePreferences()
+Curves:
+	for _, curve := range hs.clientHello.supportedCurves {
+		for _, supported := range preferredCurves {
+			if supported == curve {
+				supportedCurve = true
+				selectedCurve = curve
+				break Curves
+			}
+		}
+	}
+
+	if !supportedCurve {
+		c.sendAlert(alertHandshakeFailure)
+		return errors.New("tls: no curve supported by both client and server")
+	}
+
+	pskIdentities := hs.clientHello.pskIdentities
+	pskKEModes := hs.clientHello.pskKEModes
+
+	if len(pskIdentities) == 0 && len(hs.clientHello.sessionTicket) > 0 && c.config.Bugs.AcceptAnySession {
+		psk := pskIdentity{
+			ticket: hs.clientHello.sessionTicket,
+		}
+		pskIdentities = []pskIdentity{psk}
+		pskKEModes = []byte{pskDHEKEMode}
+	}
+
+	var pskIndex int
+	foundKEMode := bytes.IndexByte(pskKEModes, pskDHEKEMode) >= 0
+	if foundKEMode && !config.SessionTicketsDisabled {
+		for i, pskIdentity := range pskIdentities {
+			// TODO(svaldez): Check the obfuscatedTicketAge before accepting 0-RTT.
+			sessionState, ok := c.decryptTicket(pskIdentity.ticket)
+			if !ok {
+				continue
+			}
+
+			if !config.Bugs.AcceptAnySession {
+				if sessionState.vers != c.vers {
+					continue
+				}
+				if sessionState.ticketExpiration.Before(c.config.time()) {
+					continue
+				}
+				sessionCipher := cipherSuiteFromID(sessionState.cipherSuite)
+				if sessionCipher == nil || sessionCipher.hash() != hs.suite.hash() {
+					continue
+				}
+			}
+
+			clientTicketAge := time.Duration(uint32(pskIdentity.obfuscatedTicketAge-sessionState.ticketAgeAdd)) * time.Millisecond
+			if config.Bugs.ExpectTicketAge != 0 && clientTicketAge != config.Bugs.ExpectTicketAge {
+				c.sendAlert(alertHandshakeFailure)
+				return errors.New("tls: invalid ticket age")
+			}
+
+			hs.sessionState = sessionState
+			hs.hello.hasPSKIdentity = true
+			hs.hello.pskIdentity = uint16(i)
+			pskIndex = i
+			if config.Bugs.SelectPSKIdentityOnResume != 0 {
+				hs.hello.pskIdentity = config.Bugs.SelectPSKIdentityOnResume
+			}
+			c.didResume = true
+			break
+		}
+	}
+
+	if config.Bugs.AlwaysSelectPSKIdentity {
+		hs.hello.hasPSKIdentity = true
+		hs.hello.pskIdentity = 0
+	}
+
+	// Verify the PSK binder. Note there may not be a PSK binder if
+	// AcceptAnyBinder is set. See https://crbug.com/boringssl/115.
+	if hs.sessionState != nil && !config.Bugs.AcceptAnySession {
+		binderToVerify := hs.clientHello.pskBinders[pskIndex]
+		if err := verifyPSKBinder(hs.clientHello, hs.sessionState, binderToVerify, []byte{}); err != nil {
+			return err
+		}
+	}
+
+	// Resolve PSK and compute the early secret.
+	if hs.sessionState != nil {
+		hs.finishedHash.addEntropy(hs.sessionState.masterSecret)
+	} else {
+		hs.finishedHash.addEntropy(hs.finishedHash.zeroSecret())
+	}
+
+	hs.hello.hasKeyShare = true
+	if hs.sessionState != nil && config.Bugs.NegotiatePSKResumption {
+		hs.hello.hasKeyShare = false
+	}
+	if config.Bugs.MissingKeyShare {
+		hs.hello.hasKeyShare = false
+	}
+
+	firstHelloRetryRequest := true
+
+ResendHelloRetryRequest:
+	var sendHelloRetryRequest bool
+	helloRetryRequest := &helloRetryRequestMsg{
+		vers:                versionToWire(c.vers, c.isDTLS),
+		duplicateExtensions: config.Bugs.DuplicateHelloRetryRequestExtensions,
+	}
+
+	if config.Bugs.AlwaysSendHelloRetryRequest {
+		sendHelloRetryRequest = true
+	}
+
+	if config.Bugs.SendHelloRetryRequestCookie != nil {
+		sendHelloRetryRequest = true
+		helloRetryRequest.cookie = config.Bugs.SendHelloRetryRequestCookie
+	}
+
+	if len(config.Bugs.CustomHelloRetryRequestExtension) > 0 {
+		sendHelloRetryRequest = true
+		helloRetryRequest.customExtension = config.Bugs.CustomHelloRetryRequestExtension
+	}
+
+	var selectedKeyShare *keyShareEntry
+	if hs.hello.hasKeyShare {
+		// Look for the key share corresponding to our selected curve.
+		for i := range hs.clientHello.keyShares {
+			if hs.clientHello.keyShares[i].group == selectedCurve {
+				selectedKeyShare = &hs.clientHello.keyShares[i]
+				break
+			}
+		}
+
+		if config.Bugs.ExpectMissingKeyShare && selectedKeyShare != nil {
+			return errors.New("tls: expected missing key share")
+		}
+
+		if selectedKeyShare == nil {
+			helloRetryRequest.hasSelectedGroup = true
+			helloRetryRequest.selectedGroup = selectedCurve
+			sendHelloRetryRequest = true
+		}
+	}
+
+	if config.Bugs.SendHelloRetryRequestCurve != 0 {
+		helloRetryRequest.hasSelectedGroup = true
+		helloRetryRequest.selectedGroup = config.Bugs.SendHelloRetryRequestCurve
+		sendHelloRetryRequest = true
+	}
+
+	if config.Bugs.SkipHelloRetryRequest {
+		sendHelloRetryRequest = false
+	}
+
+	if sendHelloRetryRequest {
+		oldClientHelloBytes := hs.clientHello.marshal()
+		hs.writeServerHash(helloRetryRequest.marshal())
+		c.writeRecord(recordTypeHandshake, helloRetryRequest.marshal())
+		c.flushHandshake()
+
+		if hs.clientHello.hasEarlyData {
+			c.skipEarlyData = true
+		}
+
+		// Read new ClientHello.
+		newMsg, err := c.readHandshake()
+		if err != nil {
+			return err
+		}
+		newClientHello, ok := newMsg.(*clientHelloMsg)
+		if !ok {
+			c.sendAlert(alertUnexpectedMessage)
+			return unexpectedMessageError(newClientHello, newMsg)
+		}
+		hs.writeClientHash(newClientHello.marshal())
+
+		if newClientHello.hasEarlyData {
+			return errors.New("tls: EarlyData sent in new ClientHello")
+		}
+
+		applyBugsToClientHello(newClientHello, config)
+
+		// Check that the new ClientHello matches the old ClientHello,
+		// except for relevant modifications.
+		//
+		// TODO(davidben): Make this check more precise.
+		oldClientHelloCopy := *hs.clientHello
+		oldClientHelloCopy.raw = nil
+		oldClientHelloCopy.hasEarlyData = false
+		newClientHelloCopy := *newClientHello
+		newClientHelloCopy.raw = nil
+
+		if helloRetryRequest.hasSelectedGroup {
+			newKeyShares := newClientHelloCopy.keyShares
+			if len(newKeyShares) != 1 || newKeyShares[0].group != helloRetryRequest.selectedGroup {
+				return errors.New("tls: KeyShare from HelloRetryRequest not in new ClientHello")
+			}
+			selectedKeyShare = &newKeyShares[0]
+			newClientHelloCopy.keyShares = oldClientHelloCopy.keyShares
+		}
+
+		if len(helloRetryRequest.cookie) > 0 {
+			if !bytes.Equal(newClientHelloCopy.tls13Cookie, helloRetryRequest.cookie) {
+				return errors.New("tls: cookie from HelloRetryRequest not present in new ClientHello")
+			}
+			newClientHelloCopy.tls13Cookie = nil
+		}
+
+		// PSK binders and obfuscated ticket age are both updated in the
+		// second ClientHello.
+		if len(oldClientHelloCopy.pskIdentities) != len(newClientHelloCopy.pskIdentities) {
+			return errors.New("tls: PSK identity count from old and new ClientHello do not match")
+		}
+		for i, identity := range oldClientHelloCopy.pskIdentities {
+			newClientHelloCopy.pskIdentities[i].obfuscatedTicketAge = identity.obfuscatedTicketAge
+		}
+		newClientHelloCopy.pskBinders = oldClientHelloCopy.pskBinders
+		newClientHelloCopy.hasEarlyData = oldClientHelloCopy.hasEarlyData
+
+		if !oldClientHelloCopy.equal(&newClientHelloCopy) {
+			return errors.New("tls: new ClientHello does not match")
+		}
+
+		if firstHelloRetryRequest && config.Bugs.SecondHelloRetryRequest {
+			firstHelloRetryRequest = false
+			goto ResendHelloRetryRequest
+		}
+
+		// Verify the PSK binder. Note there may not be a PSK binder if
+		// AcceptAnyBinder is set. See https://crbug.com/115.
+		if hs.sessionState != nil && !config.Bugs.AcceptAnySession {
+			binderToVerify := newClientHello.pskBinders[pskIndex]
+			err := verifyPSKBinder(newClientHello, hs.sessionState, binderToVerify, append(oldClientHelloBytes, helloRetryRequest.marshal()...))
+			if err != nil {
+				return err
+			}
+		}
+	}
+
+	// Decide whether or not to accept early data.
+	if !sendHelloRetryRequest && hs.clientHello.hasEarlyData {
+		if !config.Bugs.AlwaysRejectEarlyData && hs.sessionState != nil {
+			if c.clientProtocol == string(hs.sessionState.earlyALPN) || config.Bugs.AlwaysAcceptEarlyData {
+				encryptedExtensions.extensions.hasEarlyData = true
+			}
+		}
+		if encryptedExtensions.extensions.hasEarlyData {
+			earlyTrafficSecret := hs.finishedHash.deriveSecret(earlyTrafficLabel)
+			c.in.useTrafficSecret(c.vers, hs.suite, earlyTrafficSecret, clientWrite)
+
+			for _, expectedMsg := range config.Bugs.ExpectEarlyData {
+				if err := c.readRecord(recordTypeApplicationData); err != nil {
+					return err
+				}
+				if !bytes.Equal(c.input.data[c.input.off:], expectedMsg) {
+					return errors.New("ExpectEarlyData: did not get expected message")
+				}
+				c.in.freeBlock(c.input)
+				c.input = nil
+
+			}
+		} else {
+			c.skipEarlyData = true
+		}
+	}
+
+	if config.Bugs.SendEarlyDataExtension {
+		encryptedExtensions.extensions.hasEarlyData = true
+	}
+
+	// Resolve ECDHE and compute the handshake secret.
+	if hs.hello.hasKeyShare {
+		// Once a curve has been selected and a key share identified,
+		// the server needs to generate a public value and send it in
+		// the ServerHello.
+		curve, ok := curveForCurveID(selectedCurve)
+		if !ok {
+			panic("tls: server failed to look up curve ID")
+		}
+		c.curveID = selectedCurve
+
+		var peerKey []byte
+		if config.Bugs.SkipHelloRetryRequest {
+			// If skipping HelloRetryRequest, use a random key to
+			// avoid crashing.
+			curve2, _ := curveForCurveID(selectedCurve)
+			var err error
+			peerKey, err = curve2.offer(config.rand())
+			if err != nil {
+				return err
+			}
+		} else {
+			peerKey = selectedKeyShare.keyExchange
+		}
+
+		publicKey, ecdheSecret, err := curve.accept(config.rand(), peerKey)
+		if err != nil {
+			c.sendAlert(alertHandshakeFailure)
+			return err
+		}
+		hs.finishedHash.addEntropy(ecdheSecret)
+		hs.hello.hasKeyShare = true
+
+		curveID := selectedCurve
+		if c.config.Bugs.SendCurve != 0 {
+			curveID = config.Bugs.SendCurve
+		}
+		if c.config.Bugs.InvalidECDHPoint {
+			publicKey[0] ^= 0xff
+		}
+
+		hs.hello.keyShare = keyShareEntry{
+			group:       curveID,
+			keyExchange: publicKey,
+		}
+
+		if config.Bugs.EncryptedExtensionsWithKeyShare {
+			encryptedExtensions.extensions.hasKeyShare = true
+			encryptedExtensions.extensions.keyShare = keyShareEntry{
+				group:       curveID,
+				keyExchange: publicKey,
+			}
+		}
+	} else {
+		hs.finishedHash.addEntropy(hs.finishedHash.zeroSecret())
+	}
+
+	// Send unencrypted ServerHello.
+	hs.writeServerHash(hs.hello.marshal())
+	if config.Bugs.PartialEncryptedExtensionsWithServerHello {
+		helloBytes := hs.hello.marshal()
+		toWrite := make([]byte, 0, len(helloBytes)+1)
+		toWrite = append(toWrite, helloBytes...)
+		toWrite = append(toWrite, typeEncryptedExtensions)
+		c.writeRecord(recordTypeHandshake, toWrite)
+	} else {
+		c.writeRecord(recordTypeHandshake, hs.hello.marshal())
+	}
+	c.flushHandshake()
+
+	// Switch to handshake traffic keys.
+	serverHandshakeTrafficSecret := hs.finishedHash.deriveSecret(serverHandshakeTrafficLabel)
+	c.out.useTrafficSecret(c.vers, hs.suite, serverHandshakeTrafficSecret, serverWrite)
+	// Derive handshake traffic read key, but don't switch yet.
+	clientHandshakeTrafficSecret := hs.finishedHash.deriveSecret(clientHandshakeTrafficLabel)
+
+	// Send EncryptedExtensions.
+	hs.writeServerHash(encryptedExtensions.marshal())
+	if config.Bugs.PartialEncryptedExtensionsWithServerHello {
+		// The first byte has already been sent.
+		c.writeRecord(recordTypeHandshake, encryptedExtensions.marshal()[1:])
+	} else {
+		c.writeRecord(recordTypeHandshake, encryptedExtensions.marshal())
+	}
+
+	if hs.sessionState == nil {
+		if config.ClientAuth >= RequestClientCert {
+			// Request a client certificate
+			certReq := &certificateRequestMsg{
+				hasSignatureAlgorithm: true,
+				hasRequestContext:     true,
+				requestContext:        config.Bugs.SendRequestContext,
+			}
+			if !config.Bugs.NoSignatureAlgorithms {
+				certReq.signatureAlgorithms = config.verifySignatureAlgorithms()
+			}
+
+			// An empty list of certificateAuthorities signals to
+			// the client that it may send any certificate in response
+			// to our request. When we know the CAs we trust, then
+			// we can send them down, so that the client can choose
+			// an appropriate certificate to give to us.
+			if config.ClientCAs != nil {
+				certReq.certificateAuthorities = config.ClientCAs.Subjects()
+			}
+			hs.writeServerHash(certReq.marshal())
+			c.writeRecord(recordTypeHandshake, certReq.marshal())
+		}
+
+		certMsg := &certificateMsg{
+			hasRequestContext: true,
+		}
+		if !config.Bugs.EmptyCertificateList {
+			for i, certData := range hs.cert.Certificate {
+				cert := certificateEntry{
+					data: certData,
+				}
+				if i == 0 {
+					if hs.clientHello.ocspStapling {
+						cert.ocspResponse = hs.cert.OCSPStaple
+					}
+					if hs.clientHello.sctListSupported {
+						cert.sctList = hs.cert.SignedCertificateTimestampList
+					}
+					cert.duplicateExtensions = config.Bugs.SendDuplicateCertExtensions
+					cert.extraExtension = config.Bugs.SendExtensionOnCertificate
+				} else {
+					if config.Bugs.SendOCSPOnIntermediates != nil {
+						cert.ocspResponse = config.Bugs.SendOCSPOnIntermediates
+					}
+					if config.Bugs.SendSCTOnIntermediates != nil {
+						cert.sctList = config.Bugs.SendSCTOnIntermediates
+					}
+				}
+				certMsg.certificates = append(certMsg.certificates, cert)
+			}
+		}
+		certMsgBytes := certMsg.marshal()
+		hs.writeServerHash(certMsgBytes)
+		c.writeRecord(recordTypeHandshake, certMsgBytes)
+
+		certVerify := &certificateVerifyMsg{
+			hasSignatureAlgorithm: true,
+		}
+
+		// Determine the hash to sign.
+		privKey := hs.cert.PrivateKey
+
+		var err error
+		certVerify.signatureAlgorithm, err = selectSignatureAlgorithm(c.vers, privKey, config, hs.clientHello.signatureAlgorithms)
+		if err != nil {
+			c.sendAlert(alertInternalError)
+			return err
+		}
+
+		input := hs.finishedHash.certificateVerifyInput(serverCertificateVerifyContextTLS13)
+		certVerify.signature, err = signMessage(c.vers, privKey, c.config, certVerify.signatureAlgorithm, input)
+		if err != nil {
+			c.sendAlert(alertInternalError)
+			return err
+		}
+
+		if config.Bugs.SendSignatureAlgorithm != 0 {
+			certVerify.signatureAlgorithm = config.Bugs.SendSignatureAlgorithm
+		}
+
+		hs.writeServerHash(certVerify.marshal())
+		c.writeRecord(recordTypeHandshake, certVerify.marshal())
+	} else if hs.sessionState != nil {
+		// Pick up certificates from the session instead.
+		if len(hs.sessionState.certificates) > 0 {
+			if _, err := hs.processCertsFromClient(hs.sessionState.certificates); err != nil {
+				return err
+			}
+		}
+	}
+
+	finished := new(finishedMsg)
+	finished.verifyData = hs.finishedHash.serverSum(serverHandshakeTrafficSecret)
+	if config.Bugs.BadFinished {
+		finished.verifyData[0]++
+	}
+	hs.writeServerHash(finished.marshal())
+	c.writeRecord(recordTypeHandshake, finished.marshal())
+	if c.config.Bugs.SendExtraFinished {
+		c.writeRecord(recordTypeHandshake, finished.marshal())
+	}
+	c.flushHandshake()
+
+	// The various secrets do not incorporate the client's final leg, so
+	// derive them now before updating the handshake context.
+	hs.finishedHash.addEntropy(hs.finishedHash.zeroSecret())
+	clientTrafficSecret := hs.finishedHash.deriveSecret(clientApplicationTrafficLabel)
+	serverTrafficSecret := hs.finishedHash.deriveSecret(serverApplicationTrafficLabel)
+	c.exporterSecret = hs.finishedHash.deriveSecret(exporterLabel)
+
+	// Switch to application data keys on write. In particular, any alerts
+	// from the client certificate are sent over these keys.
+	c.out.useTrafficSecret(c.vers, hs.suite, serverTrafficSecret, serverWrite)
+
+	// Send 0.5-RTT messages.
+	for _, halfRTTMsg := range config.Bugs.SendHalfRTTData {
+		if _, err := c.writeRecord(recordTypeApplicationData, halfRTTMsg); err != nil {
+			return err
+		}
+	}
+
+	// Read end_of_early_data alert.
+	if encryptedExtensions.extensions.hasEarlyData {
+		if err := c.readRecord(recordTypeAlert); err != errEndOfEarlyDataAlert {
+			if err == nil {
+				panic("readRecord(recordTypeAlert) returned nil")
+			}
+			return err
+		}
+	}
+
+	// Switch input stream to handshake traffic keys.
+	c.in.useTrafficSecret(c.vers, hs.suite, clientHandshakeTrafficSecret, clientWrite)
+
+	// If we requested a client certificate, then the client must send a
+	// certificate message, even if it's empty.
+	if config.ClientAuth >= RequestClientCert {
+		msg, err := c.readHandshake()
+		if err != nil {
+			return err
+		}
+
+		certMsg, ok := msg.(*certificateMsg)
+		if !ok {
+			c.sendAlert(alertUnexpectedMessage)
+			return unexpectedMessageError(certMsg, msg)
+		}
+		hs.writeClientHash(certMsg.marshal())
+
+		if len(certMsg.certificates) == 0 {
+			// The client didn't actually send a certificate
+			switch config.ClientAuth {
+			case RequireAnyClientCert, RequireAndVerifyClientCert:
+				c.sendAlert(alertCertificateRequired)
+				return errors.New("tls: client didn't provide a certificate")
+			}
+		}
+
+		var certs [][]byte
+		for _, cert := range certMsg.certificates {
+			certs = append(certs, cert.data)
+			// OCSP responses and SCT lists are not negotiated in
+			// client certificates.
+			if cert.ocspResponse != nil || cert.sctList != nil {
+				c.sendAlert(alertUnsupportedExtension)
+				return errors.New("tls: unexpected extensions in the client certificate")
+			}
+		}
+		pub, err := hs.processCertsFromClient(certs)
+		if err != nil {
+			return err
+		}
+
+		if len(c.peerCertificates) > 0 {
+			msg, err = c.readHandshake()
+			if err != nil {
+				return err
+			}
+
+			certVerify, ok := msg.(*certificateVerifyMsg)
+			if !ok {
+				c.sendAlert(alertUnexpectedMessage)
+				return unexpectedMessageError(certVerify, msg)
+			}
+
+			c.peerSignatureAlgorithm = certVerify.signatureAlgorithm
+			input := hs.finishedHash.certificateVerifyInput(clientCertificateVerifyContextTLS13)
+			if err := verifyMessage(c.vers, pub, config, certVerify.signatureAlgorithm, input, certVerify.signature); err != nil {
+				c.sendAlert(alertBadCertificate)
+				return err
+			}
+			hs.writeClientHash(certVerify.marshal())
+		}
+	}
+
+	if encryptedExtensions.extensions.channelIDRequested {
+		msg, err := c.readHandshake()
+		if err != nil {
+			return err
+		}
+		channelIDMsg, ok := msg.(*channelIDMsg)
+		if !ok {
+			c.sendAlert(alertUnexpectedMessage)
+			return unexpectedMessageError(channelIDMsg, msg)
+		}
+		channelIDHash := crypto.SHA256.New()
+		channelIDHash.Write(hs.finishedHash.certificateVerifyInput(channelIDContextTLS13))
+		channelID, err := verifyChannelIDMessage(channelIDMsg, channelIDHash.Sum(nil))
+		if err != nil {
+			return err
+		}
+		c.channelID = channelID
+
+		hs.writeClientHash(channelIDMsg.marshal())
+	}
+
+	// Read the client Finished message.
+	msg, err := c.readHandshake()
+	if err != nil {
+		return err
+	}
+	clientFinished, ok := msg.(*finishedMsg)
+	if !ok {
+		c.sendAlert(alertUnexpectedMessage)
+		return unexpectedMessageError(clientFinished, msg)
+	}
+
+	verify := hs.finishedHash.clientSum(clientHandshakeTrafficSecret)
+	if len(verify) != len(clientFinished.verifyData) ||
+		subtle.ConstantTimeCompare(verify, clientFinished.verifyData) != 1 {
+		c.sendAlert(alertHandshakeFailure)
+		return errors.New("tls: client's Finished message was incorrect")
+	}
+	hs.writeClientHash(clientFinished.marshal())
+
+	// Switch to application data keys on read.
+	c.in.useTrafficSecret(c.vers, hs.suite, clientTrafficSecret, clientWrite)
+
+	c.cipherSuite = hs.suite
+	c.resumptionSecret = hs.finishedHash.deriveSecret(resumptionLabel)
+
+	// TODO(davidben): Allow configuring the number of tickets sent for
+	// testing.
+	if !c.config.SessionTicketsDisabled && foundKEMode {
+		ticketCount := 2
+		for i := 0; i < ticketCount; i++ {
+			c.SendNewSessionTicket()
+		}
+	}
+	return nil
+}
+
+// processClientHello processes the ClientHello message from the client and
+// decides whether we will perform session resumption.
+func (hs *serverHandshakeState) processClientHello() (isResume bool, err error) {
+	config := hs.c.config
+	c := hs.c
+
+	hs.hello = &serverHelloMsg{
+		isDTLS:            c.isDTLS,
+		vers:              versionToWire(c.vers, c.isDTLS),
+		versOverride:      config.Bugs.SendServerHelloVersion,
+		compressionMethod: compressionNone,
+	}
+
+	hs.hello.random = make([]byte, 32)
+	_, err = io.ReadFull(config.rand(), hs.hello.random)
+	if err != nil {
+		c.sendAlert(alertInternalError)
+		return false, err
+	}
+	// Signal downgrades in the server random, per draft-ietf-tls-tls13-16,
+	// section 4.1.3.
+	if c.vers <= VersionTLS12 && config.maxVersion(c.isDTLS) >= VersionTLS13 {
+		copy(hs.hello.random[len(hs.hello.random)-8:], downgradeTLS13)
+	}
+	if c.vers <= VersionTLS11 && config.maxVersion(c.isDTLS) == VersionTLS12 {
+		copy(hs.hello.random[len(hs.hello.random)-8:], downgradeTLS12)
+	}
+
+	foundCompression := false
+	// We only support null compression, so check that the client offered it.
+	for _, compression := range hs.clientHello.compressionMethods {
+		if compression == compressionNone {
+			foundCompression = true
+			break
+		}
+	}
+
+	if !foundCompression {
+		c.sendAlert(alertHandshakeFailure)
+		return false, errors.New("tls: client does not support uncompressed connections")
+	}
+
+	if err := hs.processClientExtensions(&hs.hello.extensions); err != nil {
+		return false, err
 	}
 
 	supportedCurve := false
 	preferredCurves := config.curvePreferences()
-	if config.Bugs.IgnorePeerCurvePreferences {
-		hs.clientHello.supportedCurves = preferredCurves
-	}
 Curves:
 	for _, curve := range hs.clientHello.supportedCurves {
 		for _, supported := range preferredCurves {
@@ -249,116 +1094,6 @@
 	}
 	hs.ellipticOk = supportedCurve && supportedPointFormat
 
-	foundCompression := false
-	// We only support null compression, so check that the client offered it.
-	for _, compression := range hs.clientHello.compressionMethods {
-		if compression == compressionNone {
-			foundCompression = true
-			break
-		}
-	}
-
-	if !foundCompression {
-		c.sendAlert(alertHandshakeFailure)
-		return false, errors.New("tls: client does not support uncompressed connections")
-	}
-
-	hs.hello.vers = c.vers
-	hs.hello.random = make([]byte, 32)
-	_, err = io.ReadFull(config.rand(), hs.hello.random)
-	if err != nil {
-		c.sendAlert(alertInternalError)
-		return false, err
-	}
-
-	if !bytes.Equal(c.clientVerify, hs.clientHello.secureRenegotiation) {
-		c.sendAlert(alertHandshakeFailure)
-		return false, errors.New("tls: renegotiation mismatch")
-	}
-
-	if len(c.clientVerify) > 0 && !c.config.Bugs.EmptyRenegotiationInfo {
-		hs.hello.secureRenegotiation = append(hs.hello.secureRenegotiation, c.clientVerify...)
-		hs.hello.secureRenegotiation = append(hs.hello.secureRenegotiation, c.serverVerify...)
-		if c.config.Bugs.BadRenegotiationInfo {
-			hs.hello.secureRenegotiation[0] ^= 0x80
-		}
-	} else {
-		hs.hello.secureRenegotiation = hs.clientHello.secureRenegotiation
-	}
-
-	if c.noRenegotiationInfo() {
-		hs.hello.secureRenegotiation = nil
-	}
-
-	hs.hello.compressionMethod = compressionNone
-	hs.hello.duplicateExtension = c.config.Bugs.DuplicateExtension
-	if len(hs.clientHello.serverName) > 0 {
-		c.serverName = hs.clientHello.serverName
-	}
-
-	if len(hs.clientHello.alpnProtocols) > 0 {
-		if proto := c.config.Bugs.ALPNProtocol; proto != nil {
-			hs.hello.alpnProtocol = *proto
-			hs.hello.alpnProtocolEmpty = len(*proto) == 0
-			c.clientProtocol = *proto
-			c.usedALPN = true
-		} else if selectedProto, fallback := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos); !fallback {
-			hs.hello.alpnProtocol = selectedProto
-			c.clientProtocol = selectedProto
-			c.usedALPN = true
-		}
-	}
-	if len(hs.clientHello.alpnProtocols) == 0 || c.config.Bugs.NegotiateALPNAndNPN {
-		// Although sending an empty NPN extension is reasonable, Firefox has
-		// had a bug around this. Best to send nothing at all if
-		// config.NextProtos is empty. See
-		// https://code.google.com/p/go/issues/detail?id=5445.
-		if hs.clientHello.nextProtoNeg && len(config.NextProtos) > 0 {
-			hs.hello.nextProtoNeg = true
-			hs.hello.nextProtos = config.NextProtos
-		}
-	}
-	hs.hello.extendedMasterSecret = c.vers >= VersionTLS10 && hs.clientHello.extendedMasterSecret && !c.config.Bugs.NoExtendedMasterSecret
-
-	if len(config.Certificates) == 0 {
-		c.sendAlert(alertInternalError)
-		return false, errors.New("tls: no certificates configured")
-	}
-	hs.cert = &config.Certificates[0]
-	if len(hs.clientHello.serverName) > 0 {
-		hs.cert = config.getCertificateForName(hs.clientHello.serverName)
-	}
-	if expected := c.config.Bugs.ExpectServerName; expected != "" && expected != hs.clientHello.serverName {
-		return false, errors.New("tls: unexpected server name")
-	}
-
-	if hs.clientHello.channelIDSupported && config.RequestChannelID {
-		hs.hello.channelIDRequested = true
-	}
-
-	if hs.clientHello.srtpProtectionProfiles != nil {
-	SRTPLoop:
-		for _, p1 := range c.config.SRTPProtectionProfiles {
-			for _, p2 := range hs.clientHello.srtpProtectionProfiles {
-				if p1 == p2 {
-					hs.hello.srtpProtectionProfile = p1
-					c.srtpProtectionProfile = p1
-					break SRTPLoop
-				}
-			}
-		}
-	}
-
-	if c.config.Bugs.SendSRTPProtectionProfile != 0 {
-		hs.hello.srtpProtectionProfile = c.config.Bugs.SendSRTPProtectionProfile
-	}
-
-	if expected := c.config.Bugs.ExpectedCustomExtension; expected != nil {
-		if hs.clientHello.customExtension != *expected {
-			return false, fmt.Errorf("tls: bad custom extension contents %q", hs.clientHello.customExtension)
-		}
-	}
-
 	_, hs.ecdsaOk = hs.cert.PrivateKey.(*ecdsa.PrivateKey)
 
 	// For test purposes, check that the peer never offers a session when
@@ -375,24 +1110,6 @@
 		return true, nil
 	}
 
-	var scsvFound bool
-
-	for _, cipherSuite := range hs.clientHello.cipherSuites {
-		if cipherSuite == fallbackSCSV {
-			scsvFound = true
-			break
-		}
-	}
-
-	if !scsvFound && config.Bugs.FailIfNotFallbackSCSV {
-		return false, errors.New("tls: no fallback SCSV found when expected")
-	} else if scsvFound && !config.Bugs.FailIfNotFallbackSCSV {
-		return false, errors.New("tls: fallback SCSV found when not expected")
-	}
-
-	if config.Bugs.IgnorePeerCipherPreferences {
-		hs.clientHello.cipherSuites = c.config.cipherSuites()
-	}
 	var preferenceList, supportedList []uint16
 	if c.config.PreferServerCipherSuites {
 		preferenceList = c.config.cipherSuites()
@@ -416,17 +1133,158 @@
 	return false, nil
 }
 
+// processClientExtensions processes all ClientHello extensions not directly
+// related to cipher suite negotiation and writes responses in serverExtensions.
+func (hs *serverHandshakeState) processClientExtensions(serverExtensions *serverExtensions) error {
+	config := hs.c.config
+	c := hs.c
+
+	if c.vers < VersionTLS13 || config.Bugs.NegotiateRenegotiationInfoAtAllVersions {
+		if !bytes.Equal(c.clientVerify, hs.clientHello.secureRenegotiation) {
+			c.sendAlert(alertHandshakeFailure)
+			return errors.New("tls: renegotiation mismatch")
+		}
+
+		if len(c.clientVerify) > 0 && !c.config.Bugs.EmptyRenegotiationInfo {
+			serverExtensions.secureRenegotiation = append(serverExtensions.secureRenegotiation, c.clientVerify...)
+			serverExtensions.secureRenegotiation = append(serverExtensions.secureRenegotiation, c.serverVerify...)
+			if c.config.Bugs.BadRenegotiationInfo {
+				serverExtensions.secureRenegotiation[0] ^= 0x80
+			}
+		} else {
+			serverExtensions.secureRenegotiation = hs.clientHello.secureRenegotiation
+		}
+
+		if c.noRenegotiationInfo() {
+			serverExtensions.secureRenegotiation = nil
+		}
+	}
+
+	serverExtensions.duplicateExtension = c.config.Bugs.DuplicateExtension
+
+	if len(hs.clientHello.serverName) > 0 {
+		c.serverName = hs.clientHello.serverName
+	}
+	if len(config.Certificates) == 0 {
+		c.sendAlert(alertInternalError)
+		return errors.New("tls: no certificates configured")
+	}
+	hs.cert = &config.Certificates[0]
+	if len(hs.clientHello.serverName) > 0 {
+		hs.cert = config.getCertificateForName(hs.clientHello.serverName)
+	}
+	if expected := c.config.Bugs.ExpectServerName; expected != "" && expected != hs.clientHello.serverName {
+		return errors.New("tls: unexpected server name")
+	}
+
+	if cert := config.Bugs.RenegotiationCertificate; c.cipherSuite != nil && cert != nil {
+		hs.cert = cert
+	}
+
+	if len(hs.clientHello.alpnProtocols) > 0 {
+		// We will never offer ALPN as a client on renegotiation
+		// handshakes.
+		if len(c.clientVerify) > 0 {
+			return errors.New("tls: offered ALPN on renegotiation")
+		}
+		if proto := c.config.Bugs.ALPNProtocol; proto != nil {
+			serverExtensions.alpnProtocol = *proto
+			serverExtensions.alpnProtocolEmpty = len(*proto) == 0
+			c.clientProtocol = *proto
+			c.usedALPN = true
+		} else if selectedProto, fallback := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos); !fallback {
+			serverExtensions.alpnProtocol = selectedProto
+			c.clientProtocol = selectedProto
+			c.usedALPN = true
+		}
+	}
+
+	if len(c.config.Bugs.SendALPN) > 0 {
+		serverExtensions.alpnProtocol = c.config.Bugs.SendALPN
+	}
+
+	if c.vers < VersionTLS13 || config.Bugs.NegotiateNPNAtAllVersions {
+		if len(hs.clientHello.alpnProtocols) == 0 || c.config.Bugs.NegotiateALPNAndNPN {
+			// Although sending an empty NPN extension is reasonable, Firefox has
+			// had a bug around this. Best to send nothing at all if
+			// config.NextProtos is empty. See
+			// https://code.google.com/p/go/issues/detail?id=5445.
+			if hs.clientHello.nextProtoNeg && len(config.NextProtos) > 0 {
+				serverExtensions.nextProtoNeg = true
+				serverExtensions.nextProtos = config.NextProtos
+				serverExtensions.npnAfterAlpn = config.Bugs.SwapNPNAndALPN
+			}
+		}
+	}
+
+	if c.vers < VersionTLS13 || config.Bugs.NegotiateEMSAtAllVersions {
+		disableEMS := config.Bugs.NoExtendedMasterSecret
+		if c.cipherSuite != nil {
+			disableEMS = config.Bugs.NoExtendedMasterSecretOnRenegotiation
+		}
+		serverExtensions.extendedMasterSecret = c.vers >= VersionTLS10 && hs.clientHello.extendedMasterSecret && !disableEMS
+	}
+
+	if hs.clientHello.channelIDSupported && config.RequestChannelID {
+		serverExtensions.channelIDRequested = true
+	}
+
+	if hs.clientHello.srtpProtectionProfiles != nil {
+	SRTPLoop:
+		for _, p1 := range c.config.SRTPProtectionProfiles {
+			for _, p2 := range hs.clientHello.srtpProtectionProfiles {
+				if p1 == p2 {
+					serverExtensions.srtpProtectionProfile = p1
+					c.srtpProtectionProfile = p1
+					break SRTPLoop
+				}
+			}
+		}
+	}
+
+	if c.config.Bugs.SendSRTPProtectionProfile != 0 {
+		serverExtensions.srtpProtectionProfile = c.config.Bugs.SendSRTPProtectionProfile
+	}
+
+	if expected := c.config.Bugs.ExpectedCustomExtension; expected != nil {
+		if hs.clientHello.customExtension != *expected {
+			return fmt.Errorf("tls: bad custom extension contents %q", hs.clientHello.customExtension)
+		}
+	}
+	serverExtensions.customExtension = config.Bugs.CustomExtension
+
+	if c.config.Bugs.AdvertiseTicketExtension {
+		serverExtensions.ticketSupported = true
+	}
+
+	if c.config.Bugs.SendSupportedPointFormats != nil {
+		serverExtensions.supportedPoints = c.config.Bugs.SendSupportedPointFormats
+	}
+
+	if !hs.clientHello.hasGREASEExtension && config.Bugs.ExpectGREASE {
+		return errors.New("tls: no GREASE extension found")
+	}
+
+	serverExtensions.serverNameAck = c.config.Bugs.SendServerNameAck
+
+	return nil
+}
+
 // checkForResumption returns true if we should perform resumption on this connection.
 func (hs *serverHandshakeState) checkForResumption() bool {
 	c := hs.c
 
-	if len(hs.clientHello.sessionTicket) > 0 {
+	ticket := hs.clientHello.sessionTicket
+	if len(ticket) == 0 && len(hs.clientHello.pskIdentities) > 0 && c.config.Bugs.AcceptAnySession {
+		ticket = hs.clientHello.pskIdentities[0].ticket
+	}
+	if len(ticket) > 0 {
 		if c.config.SessionTicketsDisabled {
 			return false
 		}
 
 		var ok bool
-		if hs.sessionState, ok = c.decryptTicket(hs.clientHello.sessionTicket); !ok {
+		if hs.sessionState, ok = c.decryptTicket(ticket); !ok {
 			return false
 		}
 	} else {
@@ -441,25 +1299,32 @@
 		}
 	}
 
-	// Never resume a session for a different SSL version.
-	if !c.config.Bugs.AllowSessionVersionMismatch && c.vers != hs.sessionState.vers {
-		return false
-	}
-
-	cipherSuiteOk := false
-	// Check that the client is still offering the ciphersuite in the session.
-	for _, id := range hs.clientHello.cipherSuites {
-		if id == hs.sessionState.cipherSuite {
-			cipherSuiteOk = true
-			break
+	if c.config.Bugs.AcceptAnySession {
+		// Replace the cipher suite with one known to work, to test
+		// cross-version resumption attempts.
+		hs.sessionState.cipherSuite = TLS_RSA_WITH_AES_128_CBC_SHA
+	} else {
+		// Never resume a session for a different SSL version.
+		if c.vers != hs.sessionState.vers {
+			return false
 		}
-	}
-	if !cipherSuiteOk {
-		return false
+
+		cipherSuiteOk := false
+		// Check that the client is still offering the ciphersuite in the session.
+		for _, id := range hs.clientHello.cipherSuites {
+			if id == hs.sessionState.cipherSuite {
+				cipherSuiteOk = true
+				break
+			}
+		}
+		if !cipherSuiteOk {
+			return false
+		}
 	}
 
 	// Check that we also support the ciphersuite from the session.
-	hs.suite = c.tryCipherSuite(hs.sessionState.cipherSuite, c.config.cipherSuites(), hs.sessionState.vers, hs.ellipticOk, hs.ecdsaOk)
+	hs.suite = c.tryCipherSuite(hs.sessionState.cipherSuite, c.config.cipherSuites(), c.vers, hs.ellipticOk, hs.ecdsaOk)
+
 	if hs.suite == nil {
 		return false
 	}
@@ -486,7 +1351,17 @@
 	// We echo the client's session ID in the ServerHello to let it know
 	// that we're doing a resumption.
 	hs.hello.sessionId = hs.clientHello.sessionId
-	hs.hello.ticketSupported = c.config.Bugs.RenewTicketOnResume
+	hs.hello.extensions.ticketSupported = c.config.Bugs.RenewTicketOnResume
+
+	if c.config.Bugs.SendSCTListOnResume != nil {
+		hs.hello.extensions.sctList = c.config.Bugs.SendSCTListOnResume
+	}
+
+	if c.config.Bugs.SendOCSPResponseOnResume != nil {
+		// There is no way, syntactically, to send an OCSP response on a
+		// resumption handshake.
+		hs.hello.extensions.ocspStapling = true
+	}
 
 	hs.finishedHash = newFinishedHash(c.vers, hs.suite)
 	hs.finishedHash.discardHandshakeBuffer()
@@ -513,22 +1388,22 @@
 
 	isPSK := hs.suite.flags&suitePSK != 0
 	if !isPSK && hs.clientHello.ocspStapling && len(hs.cert.OCSPStaple) > 0 {
-		hs.hello.ocspStapling = true
+		hs.hello.extensions.ocspStapling = true
 	}
 
 	if hs.clientHello.sctListSupported && len(hs.cert.SignedCertificateTimestampList) > 0 {
-		hs.hello.sctList = hs.cert.SignedCertificateTimestampList
+		hs.hello.extensions.sctList = hs.cert.SignedCertificateTimestampList
 	}
 
-	hs.hello.ticketSupported = hs.clientHello.ticketSupported && !config.SessionTicketsDisabled && c.vers > VersionSSL30
+	hs.hello.extensions.ticketSupported = hs.clientHello.ticketSupported && !config.SessionTicketsDisabled && c.vers > VersionSSL30
 	hs.hello.cipherSuite = hs.suite.id
 	if config.Bugs.SendCipherSuite != 0 {
 		hs.hello.cipherSuite = config.Bugs.SendCipherSuite
 	}
-	c.extendedMasterSecret = hs.hello.extendedMasterSecret
+	c.extendedMasterSecret = hs.hello.extensions.extendedMasterSecret
 
 	// Generate a session ID if we're to save the session.
-	if !hs.hello.ticketSupported && config.ServerSessionCache != nil {
+	if !hs.hello.extensions.ticketSupported && config.ServerSessionCache != nil {
 		hs.hello.sessionId = make([]byte, 32)
 		if _, err := io.ReadFull(config.rand(), hs.hello.sessionId); err != nil {
 			c.sendAlert(alertInternalError)
@@ -540,24 +1415,29 @@
 	hs.writeClientHash(hs.clientHello.marshal())
 	hs.writeServerHash(hs.hello.marshal())
 
+	if config.Bugs.SendSNIWarningAlert {
+		c.SendAlert(alertLevelWarning, alertUnrecognizedName)
+	}
+
 	c.writeRecord(recordTypeHandshake, hs.hello.marshal())
 
 	if !isPSK {
 		certMsg := new(certificateMsg)
 		if !config.Bugs.EmptyCertificateList {
-			certMsg.certificates = hs.cert.Certificate
+			for _, certData := range hs.cert.Certificate {
+				certMsg.certificates = append(certMsg.certificates, certificateEntry{
+					data: certData,
+				})
+			}
 		}
 		if !config.Bugs.UnauthenticatedECDH {
 			certMsgBytes := certMsg.marshal()
-			if config.Bugs.WrongCertificateMessageType {
-				certMsgBytes[0] += 42
-			}
 			hs.writeServerHash(certMsgBytes)
 			c.writeRecord(recordTypeHandshake, certMsgBytes)
 		}
 	}
 
-	if hs.hello.ocspStapling && !c.config.Bugs.SkipCertificateStatus {
+	if hs.hello.extensions.ocspStapling && !c.config.Bugs.SkipCertificateStatus {
 		certStatus := new(certificateStatusMsg)
 		certStatus.statusType = statusTypeOCSP
 		certStatus.response = hs.cert.OCSPStaple
@@ -571,6 +1451,9 @@
 		c.sendAlert(alertHandshakeFailure)
 		return err
 	}
+	if ecdhe, ok := keyAgreement.(*ecdheKeyAgreement); ok {
+		c.curveID = ecdhe.curveID
+	}
 	if skx != nil && !config.Bugs.SkipServerKeyExchange {
 		hs.writeServerHash(skx.marshal())
 		c.writeRecord(recordTypeHandshake, skx.marshal())
@@ -588,9 +1471,9 @@
 			}
 		}
 		if c.vers >= VersionTLS12 {
-			certReq.hasSignatureAndHash = true
-			if !config.Bugs.NoSignatureAndHashes {
-				certReq.signatureAndHashes = config.signatureAndHashesForServer()
+			certReq.hasSignatureAlgorithm = true
+			if !config.Bugs.NoSignatureAlgorithms {
+				certReq.signatureAlgorithms = config.verifySignatureAlgorithms()
 			}
 		}
 
@@ -609,7 +1492,7 @@
 	helloDone := new(serverHelloDoneMsg)
 	hs.writeServerHash(helloDone.marshal())
 	c.writeRecord(recordTypeHandshake, helloDone.marshal())
-	c.dtlsFlushHandshake()
+	c.flushHandshake()
 
 	var pub crypto.PublicKey // public key for client auth, if any
 
@@ -626,13 +1509,30 @@
 	// certificate message, even if it's empty.
 	if config.ClientAuth >= RequestClientCert {
 		var certMsg *certificateMsg
-		if certMsg, ok = msg.(*certificateMsg); !ok {
+		var certificates [][]byte
+		if certMsg, ok = msg.(*certificateMsg); ok {
+			if c.vers == VersionSSL30 && len(certMsg.certificates) == 0 {
+				return errors.New("tls: empty certificate message in SSL 3.0")
+			}
+
+			hs.writeClientHash(certMsg.marshal())
+			for _, cert := range certMsg.certificates {
+				certificates = append(certificates, cert.data)
+			}
+		} else if c.vers == VersionSSL30 {
+			// In SSL 3.0, no certificate is signaled by a warning
+			// alert which we translate to ssl3NoCertificateMsg.
+			if _, ok := msg.(*ssl3NoCertificateMsg); !ok {
+				return errors.New("tls: client provided neither a certificate nor no_certificate warning alert")
+			}
+		} else {
+			// In TLS, the Certificate message is required. In SSL
+			// 3.0, the peer skips it when sending no certificates.
 			c.sendAlert(alertUnexpectedMessage)
 			return unexpectedMessageError(certMsg, msg)
 		}
-		hs.writeClientHash(certMsg.marshal())
 
-		if len(certMsg.certificates) == 0 {
+		if len(certificates) == 0 {
 			// The client didn't actually send a certificate
 			switch config.ClientAuth {
 			case RequireAnyClientCert, RequireAndVerifyClientCert:
@@ -641,7 +1541,7 @@
 			}
 		}
 
-		pub, err = hs.processCertsFromClient(certMsg.certificates)
+		pub, err = hs.processCertsFromClient(certificates)
 		if err != nil {
 			return err
 		}
@@ -692,60 +1592,24 @@
 		}
 
 		// Determine the signature type.
-		var signatureAndHash signatureAndHash
-		if certVerify.hasSignatureAndHash {
-			signatureAndHash = certVerify.signatureAndHash
-			if !isSupportedSignatureAndHash(signatureAndHash, config.signatureAndHashesForServer()) {
-				return errors.New("tls: unsupported hash function for client certificate")
-			}
-			c.clientCertSignatureHash = signatureAndHash.hash
-		} else {
-			// Before TLS 1.2 the signature algorithm was implicit
-			// from the key type, and only one hash per signature
-			// algorithm was possible. Leave the hash as zero.
-			switch pub.(type) {
-			case *ecdsa.PublicKey:
-				signatureAndHash.signature = signatureECDSA
-			case *rsa.PublicKey:
-				signatureAndHash.signature = signatureRSA
-			}
+		var sigAlg signatureAlgorithm
+		if certVerify.hasSignatureAlgorithm {
+			sigAlg = certVerify.signatureAlgorithm
+			c.peerSignatureAlgorithm = sigAlg
 		}
 
-		switch key := pub.(type) {
-		case *ecdsa.PublicKey:
-			if signatureAndHash.signature != signatureECDSA {
-				err = errors.New("tls: bad signature type for client's ECDSA certificate")
-				break
+		if c.vers > VersionSSL30 {
+			err = verifyMessage(c.vers, pub, c.config, sigAlg, hs.finishedHash.buffer, certVerify.signature)
+		} else {
+			// SSL 3.0's client certificate construction is
+			// incompatible with signatureAlgorithm.
+			rsaPub, ok := pub.(*rsa.PublicKey)
+			if !ok {
+				err = errors.New("unsupported key type for client certificate")
+			} else {
+				digest := hs.finishedHash.hashForClientCertificateSSL3(hs.masterSecret)
+				err = rsa.VerifyPKCS1v15(rsaPub, crypto.MD5SHA1, digest, certVerify.signature)
 			}
-			ecdsaSig := new(ecdsaSignature)
-			if _, err = asn1.Unmarshal(certVerify.signature, ecdsaSig); err != nil {
-				break
-			}
-			if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
-				err = errors.New("ECDSA signature contained zero or negative values")
-				break
-			}
-			var digest []byte
-			digest, _, err = hs.finishedHash.hashForClientCertificate(signatureAndHash, hs.masterSecret)
-			if err != nil {
-				break
-			}
-			if !ecdsa.Verify(key, digest, ecdsaSig.R, ecdsaSig.S) {
-				err = errors.New("ECDSA verification failure")
-				break
-			}
-		case *rsa.PublicKey:
-			if signatureAndHash.signature != signatureRSA {
-				err = errors.New("tls: bad signature type for client's RSA certificate")
-				break
-			}
-			var digest []byte
-			var hashFunc crypto.Hash
-			digest, hashFunc, err = hs.finishedHash.hashForClientCertificate(signatureAndHash, hs.masterSecret)
-			if err != nil {
-				break
-			}
-			err = rsa.VerifyPKCS1v15(key, hashFunc, digest, certVerify.signature)
 		}
 		if err != nil {
 			c.sendAlert(alertBadCertificate)
@@ -764,7 +1628,7 @@
 	c := hs.c
 
 	clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV :=
-		keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.clientHello.random, hs.hello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen)
+		keysFromMasterSecret(c.vers, hs.suite, hs.masterSecret, hs.clientHello.random, hs.hello.random, hs.suite.macLen, hs.suite.keyLen, hs.suite.ivLen(c.vers))
 
 	var clientCipher, serverCipher interface{}
 	var clientHash, serverHash macFunction
@@ -775,8 +1639,8 @@
 		serverCipher = hs.suite.cipher(serverKey, serverIV, false /* not for reading */)
 		serverHash = hs.suite.mac(c.vers, serverMAC)
 	} else {
-		clientCipher = hs.suite.aead(clientKey, clientIV)
-		serverCipher = hs.suite.aead(serverKey, serverIV)
+		clientCipher = hs.suite.aead(c.vers, clientKey, clientIV)
+		serverCipher = hs.suite.aead(c.vers, serverKey, serverIV)
 	}
 
 	c.in.prepareCipherSpec(c.vers, clientCipher, clientHash)
@@ -793,7 +1657,7 @@
 		return err
 	}
 
-	if hs.hello.nextProtoNeg {
+	if hs.hello.extensions.nextProtoNeg {
 		msg, err := c.readHandshake()
 		if err != nil {
 			return err
@@ -807,34 +1671,27 @@
 		c.clientProtocol = nextProto.proto
 	}
 
-	if hs.hello.channelIDRequested {
+	if hs.hello.extensions.channelIDRequested {
 		msg, err := c.readHandshake()
 		if err != nil {
 			return err
 		}
-		encryptedExtensions, ok := msg.(*encryptedExtensionsMsg)
+		channelIDMsg, ok := msg.(*channelIDMsg)
 		if !ok {
 			c.sendAlert(alertUnexpectedMessage)
-			return unexpectedMessageError(encryptedExtensions, msg)
+			return unexpectedMessageError(channelIDMsg, msg)
 		}
-		x := new(big.Int).SetBytes(encryptedExtensions.channelID[0:32])
-		y := new(big.Int).SetBytes(encryptedExtensions.channelID[32:64])
-		r := new(big.Int).SetBytes(encryptedExtensions.channelID[64:96])
-		s := new(big.Int).SetBytes(encryptedExtensions.channelID[96:128])
-		if !elliptic.P256().IsOnCurve(x, y) {
-			return errors.New("tls: invalid channel ID public key")
-		}
-		channelID := &ecdsa.PublicKey{elliptic.P256(), x, y}
 		var resumeHash []byte
 		if isResume {
 			resumeHash = hs.sessionState.handshakeHash
 		}
-		if !ecdsa.Verify(channelID, hs.finishedHash.hashForChannelID(resumeHash), r, s) {
-			return errors.New("tls: invalid channel ID signature")
+		channelID, err := verifyChannelIDMessage(channelIDMsg, hs.finishedHash.hashForChannelID(resumeHash))
+		if err != nil {
+			return err
 		}
 		c.channelID = channelID
 
-		hs.writeClientHash(encryptedExtensions.marshal())
+		hs.writeClientHash(channelIDMsg.marshal())
 	}
 
 	msg, err := c.readHandshake()
@@ -867,10 +1724,10 @@
 		cipherSuite:   hs.suite.id,
 		masterSecret:  hs.masterSecret,
 		certificates:  hs.certsFromClient,
-		handshakeHash: hs.finishedHash.server.Sum(nil),
+		handshakeHash: hs.finishedHash.Sum(),
 	}
 
-	if !hs.hello.ticketSupported || hs.c.config.Bugs.SkipNewSessionTicket {
+	if !hs.hello.extensions.ticketSupported || hs.c.config.Bugs.SkipNewSessionTicket {
 		if c.config.ServerSessionCache != nil && len(hs.hello.sessionId) != 0 {
 			c.config.ServerSessionCache.Put(string(hs.hello.sessionId), &state)
 		}
@@ -878,6 +1735,9 @@
 	}
 
 	m := new(newSessionTicketMsg)
+	if c.config.Bugs.SendTicketLifetime != 0 {
+		m.ticketLifetime = uint32(c.config.Bugs.SendTicketLifetime / time.Second)
+	}
 
 	if !c.config.Bugs.SendEmptySessionTicket {
 		var err error
@@ -910,8 +1770,11 @@
 	if c.config.Bugs.FragmentAcrossChangeCipherSpec {
 		c.writeRecord(recordTypeHandshake, postCCSBytes[:5])
 		postCCSBytes = postCCSBytes[5:]
+	} else if c.config.Bugs.SendUnencryptedFinished {
+		c.writeRecord(recordTypeHandshake, postCCSBytes)
+		postCCSBytes = nil
 	}
-	c.dtlsFlushHandshake()
+	c.flushHandshake()
 
 	if !c.config.Bugs.SkipChangeCipherSpec {
 		ccs := []byte{1}
@@ -929,9 +1792,16 @@
 		return errors.New("tls: simulating post-CCS alert")
 	}
 
-	if !c.config.Bugs.SkipFinished {
+	if !c.config.Bugs.SkipFinished && len(postCCSBytes) > 0 {
 		c.writeRecord(recordTypeHandshake, postCCSBytes)
-		c.dtlsFlushHandshake()
+		if c.config.Bugs.SendExtraFinished {
+			c.writeRecord(recordTypeHandshake, finished.marshal())
+		}
+
+		if !c.config.Bugs.PackHelloRequestWithFinished {
+			// Defer flushing until renegotiation.
+			c.flushHandshake()
+		}
 	}
 
 	c.cipherSuite = hs.suite
@@ -1004,6 +1874,21 @@
 	return nil, nil
 }
 
+func verifyChannelIDMessage(channelIDMsg *channelIDMsg, channelIDHash []byte) (*ecdsa.PublicKey, error) {
+	x := new(big.Int).SetBytes(channelIDMsg.channelID[0:32])
+	y := new(big.Int).SetBytes(channelIDMsg.channelID[32:64])
+	r := new(big.Int).SetBytes(channelIDMsg.channelID[64:96])
+	s := new(big.Int).SetBytes(channelIDMsg.channelID[96:128])
+	if !elliptic.P256().IsOnCurve(x, y) {
+		return nil, errors.New("tls: invalid channel ID public key")
+	}
+	channelID := &ecdsa.PublicKey{elliptic.P256(), x, y}
+	if !ecdsa.Verify(channelID, channelIDHash, r, s) {
+		return nil, errors.New("tls: invalid channel ID signature")
+	}
+	return channelID, nil
+}
+
 func (hs *serverHandshakeState) writeServerHash(msg []byte) {
 	// writeServerHash is called before writeRecord.
 	hs.writeHash(msg, hs.c.sendHandshakeSeq)
@@ -1046,15 +1931,22 @@
 			if candidate == nil {
 				continue
 			}
+
 			// Don't select a ciphersuite which we can't
 			// support for this client.
+			if version >= VersionTLS13 || candidate.flags&suiteTLS13 != 0 {
+				if version < VersionTLS13 || candidate.flags&suiteTLS13 == 0 {
+					continue
+				}
+				return candidate
+			}
 			if (candidate.flags&suiteECDHE != 0) && !ellipticOk {
 				continue
 			}
 			if (candidate.flags&suiteECDSA != 0) != ecdsaOk {
 				continue
 			}
-			if !c.config.Bugs.SkipCipherVersionCheck && version < VersionTLS12 && candidate.flags&suiteTLS12 != 0 {
+			if version < VersionTLS12 && candidate.flags&suiteTLS12 != 0 {
 				continue
 			}
 			if c.isDTLS && candidate.flags&suiteNoDTLS != 0 {
@@ -1077,3 +1969,28 @@
 	// Unknown cipher.
 	return false
 }
+
+func isGREASEValue(val uint16) bool {
+	return val&0x0f0f == 0x0a0a && val&0xff == val>>8
+}
+
+func verifyPSKBinder(clientHello *clientHelloMsg, sessionState *sessionState, binderToVerify, transcript []byte) error {
+	binderLen := 2
+	for _, binder := range clientHello.pskBinders {
+		binderLen += 1 + len(binder)
+	}
+
+	truncatedHello := clientHello.marshal()
+	truncatedHello = truncatedHello[:len(truncatedHello)-binderLen]
+	pskCipherSuite := cipherSuiteFromID(sessionState.cipherSuite)
+	if pskCipherSuite == nil {
+		return errors.New("tls: Unknown cipher suite for PSK in session")
+	}
+
+	binder := computePSKBinder(sessionState.masterSecret, resumptionPSKBinderLabel, pskCipherSuite, transcript, truncatedHello)
+	if !bytes.Equal(binder, binderToVerify) {
+		return errors.New("tls: PSK binder does not verify")
+	}
+
+	return nil
+}
diff --git a/src/ssl/test/runner/hkdf.go b/src/ssl/test/runner/hkdf.go
new file mode 100644
index 0000000..c60e4cc
--- /dev/null
+++ b/src/ssl/test/runner/hkdf.go
@@ -0,0 +1,57 @@
+// Copyright (c) 2016, Google Inc.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+package runner
+
+import (
+	"crypto/hmac"
+	"hash"
+)
+
+// hkdfExtract implements HKDF-Extract from RFC 5869.
+func hkdfExtract(hash func() hash.Hash, salt, ikm []byte) []byte {
+	if salt == nil {
+		salt = make([]byte, hash().Size())
+	}
+	hmac := hmac.New(hash, salt)
+	hmac.Write(ikm)
+	return hmac.Sum(nil)
+}
+
+// hkdfExpand implements HKDF-Expand from RFC 5869.
+func hkdfExpand(hash func() hash.Hash, prk, info []byte, length int) []byte {
+	hashSize := hash().Size()
+	if length > 255*hashSize {
+		panic("hkdfExpand: length too long")
+	}
+	if len(prk) < hashSize {
+		panic("hkdfExpand: prk too short")
+	}
+	var lastBlock []byte
+	counter := byte(0)
+	okm := make([]byte, length)
+	hmac := hmac.New(hash, prk)
+	for length > 0 {
+		hmac.Reset()
+		counter++
+		hmac.Write(lastBlock)
+		hmac.Write(info)
+		hmac.Write([]byte{counter})
+		block := hmac.Sum(nil)
+		lastBlock = block
+		copy(okm[(int(counter)-1)*hashSize:], block)
+		length -= hashSize
+	}
+	return okm
+}
diff --git a/src/ssl/test/runner/hkdf_test.go b/src/ssl/test/runner/hkdf_test.go
new file mode 100644
index 0000000..4e6958e
--- /dev/null
+++ b/src/ssl/test/runner/hkdf_test.go
@@ -0,0 +1,101 @@
+// Copyright (c) 2016, Google Inc.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+package runner
+
+import (
+	"bytes"
+	"crypto"
+	_ "crypto/sha1"
+	_ "crypto/sha256"
+	"testing"
+)
+
+var hkdfTests = []struct {
+	hash                      crypto.Hash
+	ikm, salt, info, prk, okm []byte
+}{
+	{
+		crypto.SHA256,
+		[]byte{0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b},
+		[]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c},
+		[]byte{0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9},
+		[]byte{0x07, 0x77, 0x09, 0x36, 0x2c, 0x2e, 0x32, 0xdf, 0x0d, 0xdc, 0x3f, 0x0d, 0xc4, 0x7b, 0xba, 0x63, 0x90, 0xb6, 0xc7, 0x3b, 0xb5, 0x0f, 0x9c, 0x31, 0x22, 0xec, 0x84, 0x4a, 0xd7, 0xc2, 0xb3, 0xe5},
+		[]byte{0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, 0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a, 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, 0x5a, 0x4c, 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf, 0x34, 0x00, 0x72, 0x08, 0xd5, 0xb8, 0x87, 0x18, 0x58, 0x65},
+	},
+	{
+		crypto.SHA256,
+		[]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f},
+		[]byte{0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf},
+		[]byte{0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff},
+		[]byte{0x06, 0xa6, 0xb8, 0x8c, 0x58, 0x53, 0x36, 0x1a, 0x06, 0x10, 0x4c, 0x9c, 0xeb, 0x35, 0xb4, 0x5c, 0xef, 0x76, 0x00, 0x14, 0x90, 0x46, 0x71, 0x01, 0x4a, 0x19, 0x3f, 0x40, 0xc1, 0x5f, 0xc2, 0x44},
+		[]byte{0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1, 0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a, 0x49, 0x34, 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8, 0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c, 0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7, 0x82, 0x72, 0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09, 0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8, 0x36, 0x77, 0x93, 0xa9, 0xac, 0xa3, 0xdb, 0x71, 0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87, 0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f, 0x1d, 0x87},
+	},
+	{
+		crypto.SHA256,
+		[]byte{
+			0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+			0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b},
+		[]byte{},
+		[]byte{},
+		[]byte{0x19, 0xef, 0x24, 0xa3, 0x2c, 0x71, 0x7b, 0x16, 0x7f, 0x33, 0xa9, 0x1d, 0x6f, 0x64, 0x8b, 0xdf, 0x96, 0x59, 0x67, 0x76, 0xaf, 0xdb, 0x63, 0x77, 0xac, 0x43, 0x4c, 0x1c, 0x29, 0x3c, 0xcb, 0x04},
+		[]byte{0x8d, 0xa4, 0xe7, 0x75, 0xa5, 0x63, 0xc1, 0x8f, 0x71, 0x5f, 0x80, 0x2a, 0x06, 0x3c, 0x5a, 0x31, 0xb8, 0xa1, 0x1f, 0x5c, 0x5e, 0xe1, 0x87, 0x9e, 0xc3, 0x45, 0x4e, 0x5f, 0x3c, 0x73, 0x8d, 0x2d, 0x9d, 0x20, 0x13, 0x95, 0xfa, 0xa4, 0xb6, 0x1a, 0x96, 0xc8},
+	},
+	{
+		crypto.SHA1,
+		[]byte{0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b},
+		[]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c},
+		[]byte{0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9},
+		[]byte{0x9b, 0x6c, 0x18, 0xc4, 0x32, 0xa7, 0xbf, 0x8f, 0x0e, 0x71, 0xc8, 0xeb, 0x88, 0xf4, 0xb3, 0x0b, 0xaa, 0x2b, 0xa2, 0x43},
+		[]byte{0x08, 0x5a, 0x01, 0xea, 0x1b, 0x10, 0xf3, 0x69, 0x33, 0x06, 0x8b, 0x56, 0xef, 0xa5, 0xad, 0x81, 0xa4, 0xf1, 0x4b, 0x82, 0x2f, 0x5b, 0x09, 0x15, 0x68, 0xa9, 0xcd, 0xd4, 0xf1, 0x55, 0xfd, 0xa2, 0xc2, 0x2e, 0x42, 0x24, 0x78, 0xd3, 0x05, 0xf3, 0xf8, 0x96},
+	},
+	{
+		crypto.SHA1,
+		[]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f},
+		[]byte{0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf},
+		[]byte{0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff},
+		[]byte{0x8a, 0xda, 0xe0, 0x9a, 0x2a, 0x30, 0x70, 0x59, 0x47, 0x8d, 0x30, 0x9b, 0x26, 0xc4, 0x11, 0x5a, 0x22, 0x4c, 0xfa, 0xf6},
+		[]byte{0x0b, 0xd7, 0x70, 0xa7, 0x4d, 0x11, 0x60, 0xf7, 0xc9, 0xf1, 0x2c, 0xd5, 0x91, 0x2a, 0x06, 0xeb, 0xff, 0x6a, 0xdc, 0xae, 0x89, 0x9d, 0x92, 0x19, 0x1f, 0xe4, 0x30, 0x56, 0x73, 0xba, 0x2f, 0xfe, 0x8f, 0xa3, 0xf1, 0xa4, 0xe5, 0xad, 0x79, 0xf3, 0xf3, 0x34, 0xb3, 0xb2, 0x02, 0xb2, 0x17, 0x3c, 0x48, 0x6e, 0xa3, 0x7c, 0xe3, 0xd3, 0x97, 0xed, 0x03, 0x4c, 0x7f, 0x9d, 0xfe, 0xb1, 0x5c, 0x5e, 0x92, 0x73, 0x36, 0xd0, 0x44, 0x1f, 0x4c, 0x43, 0x00, 0xe2, 0xcf, 0xf0, 0xd0, 0x90, 0x0b, 0x52, 0xd3, 0xb4},
+	},
+	{
+		crypto.SHA1,
+		[]byte{0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b},
+		[]byte{},
+		[]byte{},
+		[]byte{0xda, 0x8c, 0x8a, 0x73, 0xc7, 0xfa, 0x77, 0x28, 0x8e, 0xc6, 0xf5, 0xe7, 0xc2, 0x97, 0x78, 0x6a, 0xa0, 0xd3, 0x2d, 0x01},
+		[]byte{0x0a, 0xc1, 0xaf, 0x70, 0x02, 0xb3, 0xd7, 0x61, 0xd1, 0xe5, 0x52, 0x98, 0xda, 0x9d, 0x05, 0x06, 0xb9, 0xae, 0x52, 0x05, 0x72, 0x20, 0xa3, 0x06, 0xe0, 0x7b, 0x6b, 0x87, 0xe8, 0xdf, 0x21, 0xd0, 0xea, 0x00, 0x03, 0x3d, 0xe0, 0x39, 0x84, 0xd3, 0x49, 0x18},
+	},
+	{
+		crypto.SHA1,
+		[]byte{0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c},
+		[]byte{},
+		[]byte{},
+		[]byte{0x2a, 0xdc, 0xca, 0xda, 0x18, 0x77, 0x9e, 0x7c, 0x20, 0x77, 0xad, 0x2e, 0xb1, 0x9d, 0x3f, 0x3e, 0x73, 0x13, 0x85, 0xdd},
+		[]byte{0x2c, 0x91, 0x11, 0x72, 0x04, 0xd7, 0x45, 0xf3, 0x50, 0x0d, 0x63, 0x6a, 0x62, 0xf6, 0x4f, 0x0a, 0xb3, 0xba, 0xe5, 0x48, 0xaa, 0x53, 0xd4, 0x23, 0xb0, 0xd1, 0xf2, 0x7e, 0xbb, 0xa6, 0xf5, 0xe5, 0x67, 0x3a, 0x08, 0x1d, 0x70, 0xcc, 0xe7, 0xac, 0xfc, 0x48},
+	},
+}
+
+func TestHKDF(t *testing.T) {
+	for i, tt := range hkdfTests {
+		prk := hkdfExtract(tt.hash.New, tt.salt, tt.ikm)
+		if !bytes.Equal(prk, tt.prk) {
+			t.Errorf("%d. got hkdfExtract(%x, %x) = %x; wanted %x", i+1, tt.salt, tt.ikm, prk, tt.prk)
+		}
+
+		okm := hkdfExpand(tt.hash.New, tt.prk, tt.info, len(tt.okm))
+		if !bytes.Equal(okm, tt.okm) {
+			t.Errorf("%d. got hkdfExpand(%x, %x, %d) = %x; wanted %x", i+1, tt.prk, tt.info, len(tt.okm), okm, tt.okm)
+		}
+	}
+}
diff --git a/src/ssl/test/runner/key.pem b/src/ssl/test/runner/key.pem
index e9107bf..aeba186 100644
--- a/src/ssl/test/runner/key.pem
+++ b/src/ssl/test/runner/key.pem
@@ -1,15 +1,28 @@
------BEGIN RSA PRIVATE KEY-----
-MIICXgIBAAKBgQDYK8imMuRi/03z0K1Zi0WnvfFHvwlYeyK9Na6XJYaUoIDAtB92
-kWdGMdAQhLciHnAjkXLI6W15OoV3gA/ElRZ1xUpxTMhjP6PyY5wqT5r6y8FxbiiF
-KKAnHmUcrgfVW28tQ+0rkLGMryRtrukXOgXBv7gcrmU7G1jC2a7WqmeI8QIDAQAB
-AoGBAIBy09Fd4DOq/Ijp8HeKuCMKTHqTW1xGHshLQ6jwVV2vWZIn9aIgmDsvkjCe
-i6ssZvnbjVcwzSoByhjN8ZCf/i15HECWDFFh6gt0P5z0MnChwzZmvatV/FXCT0j+
-WmGNB/gkehKjGXLLcjTb6dRYVJSCZhVuOLLcbWIV10gggJQBAkEA8S8sGe4ezyyZ
-m4e9r95g6s43kPqtj5rewTsUxt+2n4eVodD+ZUlCULWVNAFLkYRTBCASlSrm9Xhj
-QpmWAHJUkQJBAOVzQdFUaewLtdOJoPCtpYoY1zd22eae8TQEmpGOR11L6kbxLQsk
-aMly/DOnOaa82tqAGTdqDEZgSNmCeKKknmECQAvpnY8GUOVAubGR6c+W90iBuQLj
-LtFp/9ihd2w/PoDwrHZaoUYVcT4VSfJQog/k7kjE4MYXYWL8eEKg3WTWQNECQQDk
-104Wi91Umd1PzF0ijd2jXOERJU1wEKe6XLkYYNHWQAe5l4J4MWj9OdxFXAxIuuR/
-tfDwbqkta4xcux67//khAkEAvvRXLHTaa6VFzTaiiO8SaFsHV3lQyXOtMrBpB5jd
-moZWgjHvB2W9Ckn7sDqsPB+U2tyX0joDdQEyuiMECDY8oQ==
------END RSA PRIVATE KEY-----
+-----BEGIN PRIVATE KEY-----
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC6C9qEGRIBQXV8
+Lj29vVu+U+tyXzSSinWIumK5ijPhCm3DLnv4RayxkFwemtnkGRZ/o94ZnsXkBfU/
+IlsYdkuq8wK9WI/ql3gwWjH+KARIhIQcSLGiJcLN6kGuG2nlRBKMcPgPiEq2B0yB
+XFf4tG3CBbeae7+8G7uvOmv8NLyKj32neWpnUCTL5o2VwyPoxjLxT5gUR69v9XSV
+Fj2irCZbsEedeKSb++LqyMhLfnRTzNv+ZHNh4izZHrktR25MvnT5QyBq32hx7AjZ
+2/xo70OmH7w10a2DwsVjJNMdxTEmgyvU9M6CeYRPX1Ykfg+sXCTtkTVAlBDUviIq
+Y95CKy25AgMBAAECggEAHPvvxRiqx2tNRFVn5QF1I4erbJwMcrADc5OmAcXYIz0e
+sIOzaJBiQR9+Wn5BZ9nIuYXr+g3UQpvzAyz1CDCVxUIqsRj1AtUqMk4675+IW0vZ
+0RY6Jkq/uJjANsGqk78xLJQE8VaIXSdx8c1THznsx4dgfT6+Ni4T5U6yuA33OZaw
+4NdYZYtEkqNiqK6VYe4mAxxVh5qscihVVMGkBVqJNiiEotctm1lph8ow+7o8ggXO
+W9xm+RHHPcH7Epx7hjkb/helANcYOK950W5/R+2zWV9R6kxo6R+/hfGFFmCvl4k5
++i8Y0IlEv3fze1E0Lwyf379i3C/cKcuaE5gwR54BAQKBgQDxlsNy9M37HgguglHt
+8W+cuPNtxNjFCWIjNR9dSvdr1Oi28Z1AY+BBPSv6UBKnT5PpOFjqxfMY/j/zoKdI
+aYX1phgeQHXcHrB1pS8yoaF/pTJSN2Yb8v9kl/Ch1yeYXaNVGmeBLkH9H6wIcUxD
+Mas1i8VUzshzhcluCNGoJj9wUQKBgQDFJOoWncssfWCrsuDWEoeU71Zh3+bD96GF
+s29CdIbHpcbxhWYjA9RM8yxbGPopexzoGcV1HX6j8E1s0xfYZJV23rxoM9Zj9l5D
+mZAJQPxYXIdu3h4PslhZLd3p+DEHjbsLC/avk3M4iZim1FMPBJMswKSL23ysqXoY
+/ynor+W06QKBgHYeu6M6NHgCYAe1ai+Hq4WaHFNgOohkJRqHv7USkVSkvb+s9LDl
+5GChcx4pBmXNj8ko5rirXkerEEOjGgdaqMfJlOM9qyKb0rVCtYfw5RCPCcKPGZqy
+vdJGQ74tf0uNBO34QgE0R8lmMevS0XHNGCPPGgV0MSfikvD82N15De1xAoGAbsZM
+RsMJfAlDPZc4oPEuf/BwMHTYPTsy5map2MSTSzGKdQHJH1myfD6TqOiDALXtyzlX
+63PUShfn2YNPvcbe+Tk00rR1/htcYk2yUpDSenAbpZ9ncth6rjmInURZgG4SMKXb
+SlLnBljCjtN1jFW8wQPKMc/14SslsVAHY3ka8KkCgYB58QNT1YfH3jS62+mT2pXq
+qLjLqvsD742VYnFoHR+HBOnN8ry0dda4lgwM106L5FgSg9DOZvASZ+QGFk+QVQv+
+c77ASWpuhmBmamZCrwZXrq9Xc92RDPkKFqnP9MVv06hYKNp0moSdM8dIaM6uSows
+/r/aDs4oudubz26o5GDKmA==
+-----END PRIVATE KEY-----
diff --git a/src/ssl/test/runner/key_agreement.go b/src/ssl/test/runner/key_agreement.go
index 4f399d9..2a3e924 100644
--- a/src/ssl/test/runner/key_agreement.go
+++ b/src/ssl/test/runner/key_agreement.go
@@ -5,16 +5,12 @@
 package runner
 
 import (
-	"crypto"
 	"crypto/ecdsa"
 	"crypto/elliptic"
-	"crypto/md5"
 	"crypto/rand"
 	"crypto/rsa"
-	"crypto/sha1"
 	"crypto/subtle"
 	"crypto/x509"
-	"encoding/asn1"
 	"errors"
 	"fmt"
 	"io"
@@ -23,6 +19,13 @@
 	"./curve25519"
 )
 
+type keyType int
+
+const (
+	keyTypeRSA keyType = iota + 1
+	keyTypeECDSA
+)
+
 var errClientKeyExchange = errors.New("tls: invalid ClientKeyExchange message")
 var errServerKeyExchange = errors.New("tls: invalid ServerKeyExchange message")
 
@@ -36,7 +39,7 @@
 
 func (ka *rsaKeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
 	// Save the client version for comparison later.
-	ka.clientVersion = versionToWire(clientHello.vers, clientHello.isDTLS)
+	ka.clientVersion = clientHello.vers
 
 	if !config.Bugs.RSAEphemeralKey {
 		return nil, nil
@@ -58,37 +61,30 @@
 	serverRSAParams = append(serverRSAParams, byte(len(exponent)>>8), byte(len(exponent)))
 	serverRSAParams = append(serverRSAParams, exponent...)
 
-	var tls12HashId uint8
+	var sigAlg signatureAlgorithm
 	if ka.version >= VersionTLS12 {
-		if tls12HashId, err = pickTLS12HashForSignature(signatureRSA, clientHello.signatureAndHashes, config.signatureAndHashesForServer()); err != nil {
+		sigAlg, err = selectSignatureAlgorithm(ka.version, cert.PrivateKey, config, clientHello.signatureAlgorithms)
+		if err != nil {
 			return nil, err
 		}
 	}
 
-	digest, hashFunc, err := hashForServerKeyExchange(signatureRSA, tls12HashId, ka.version, clientHello.random, hello.random, serverRSAParams)
-	if err != nil {
-		return nil, err
-	}
-	privKey, ok := cert.PrivateKey.(*rsa.PrivateKey)
-	if !ok {
-		return nil, errors.New("RSA ephemeral key requires an RSA server private key")
-	}
-	sig, err := rsa.SignPKCS1v15(config.rand(), privKey, hashFunc, digest)
+	sig, err := signMessage(ka.version, cert.PrivateKey, config, sigAlg, serverRSAParams)
 	if err != nil {
 		return nil, errors.New("failed to sign RSA parameters: " + err.Error())
 	}
 
 	skx := new(serverKeyExchangeMsg)
-	sigAndHashLen := 0
+	sigAlgsLen := 0
 	if ka.version >= VersionTLS12 {
-		sigAndHashLen = 2
+		sigAlgsLen = 2
 	}
-	skx.key = make([]byte, len(serverRSAParams)+sigAndHashLen+2+len(sig))
+	skx.key = make([]byte, len(serverRSAParams)+sigAlgsLen+2+len(sig))
 	copy(skx.key, serverRSAParams)
 	k := skx.key[len(serverRSAParams):]
 	if ka.version >= VersionTLS12 {
-		k[0] = tls12HashId
-		k[1] = signatureRSA
+		k[0] = byte(sigAlg >> 8)
+		k[1] = byte(sigAlg)
 		k = k[2:]
 	}
 	k[0] = byte(len(sig) >> 8)
@@ -131,7 +127,7 @@
 	// RFC 4346.
 	vers := uint16(preMasterSecret[0])<<8 | uint16(preMasterSecret[1])
 	if ka.clientVersion != vers {
-		return nil, errors.New("tls: invalid version in RSA premaster")
+		return nil, fmt.Errorf("tls: invalid version in RSA premaster (got %04x, wanted %04x)", vers, ka.clientVersion)
 	}
 	return preMasterSecret, nil
 }
@@ -147,7 +143,6 @@
 	if bad == RSABadValueWrongVersion {
 		vers ^= 1
 	}
-	vers = versionToWire(vers, clientHello.isDTLS)
 	preMasterSecret[0] = byte(vers >> 8)
 	preMasterSecret[1] = byte(vers)
 	_, err := io.ReadFull(config.rand(), preMasterSecret[2:])
@@ -173,7 +168,7 @@
 		encrypted[0] = 0
 	}
 	ckx := new(clientKeyExchangeMsg)
-	if clientHello.vers != VersionSSL30 {
+	if ka.version != VersionSSL30 {
 		ckx.ciphertext = make([]byte, len(encrypted)+2)
 		ckx.ciphertext[0] = byte(len(encrypted) >> 8)
 		ckx.ciphertext[1] = byte(len(encrypted))
@@ -184,81 +179,22 @@
 	return preMasterSecret, ckx, nil
 }
 
-// sha1Hash calculates a SHA1 hash over the given byte slices.
-func sha1Hash(slices [][]byte) []byte {
-	hsha1 := sha1.New()
-	for _, slice := range slices {
-		hsha1.Write(slice)
-	}
-	return hsha1.Sum(nil)
-}
-
-// md5SHA1Hash implements TLS 1.0's hybrid hash function which consists of the
-// concatenation of an MD5 and SHA1 hash.
-func md5SHA1Hash(slices [][]byte) []byte {
-	md5sha1 := make([]byte, md5.Size+sha1.Size)
-	hmd5 := md5.New()
-	for _, slice := range slices {
-		hmd5.Write(slice)
-	}
-	copy(md5sha1, hmd5.Sum(nil))
-	copy(md5sha1[md5.Size:], sha1Hash(slices))
-	return md5sha1
-}
-
-// hashForServerKeyExchange hashes the given slices and returns their digest
-// and the identifier of the hash function used. The hashFunc argument is only
-// used for >= TLS 1.2 and precisely identifies the hash function to use.
-func hashForServerKeyExchange(sigType, hashFunc uint8, version uint16, slices ...[]byte) ([]byte, crypto.Hash, error) {
-	if version >= VersionTLS12 {
-		hash, err := lookupTLSHash(hashFunc)
-		if err != nil {
-			return nil, 0, err
-		}
-		h := hash.New()
-		for _, slice := range slices {
-			h.Write(slice)
-		}
-		return h.Sum(nil), hash, nil
-	}
-	if sigType == signatureECDSA {
-		return sha1Hash(slices), crypto.SHA1, nil
-	}
-	return md5SHA1Hash(slices), crypto.MD5SHA1, nil
-}
-
-// pickTLS12HashForSignature returns a TLS 1.2 hash identifier for signing a
-// ServerKeyExchange given the signature type being used and the client's
-// advertized list of supported signature and hash combinations.
-func pickTLS12HashForSignature(sigType uint8, clientList, serverList []signatureAndHash) (uint8, error) {
-	if len(clientList) == 0 {
-		// If the client didn't specify any signature_algorithms
-		// extension then we can assume that it supports SHA1. See
-		// http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
-		return hashSHA1, nil
-	}
-
-	for _, sigAndHash := range clientList {
-		if sigAndHash.signature != sigType {
-			continue
-		}
-		if isSupportedSignatureAndHash(sigAndHash, serverList) {
-			return sigAndHash.hash, nil
-		}
-	}
-
-	return 0, errors.New("tls: client doesn't support any common hash functions")
+func (ka *rsaKeyAgreement) peerSignatureAlgorithm() signatureAlgorithm {
+	return 0
 }
 
 // A ecdhCurve is an instance of ECDH-style key agreement for TLS.
 type ecdhCurve interface {
-	// generateKeypair generates a keypair using rand. It returns the
-	// encoded public key.
-	generateKeypair(rand io.Reader) (publicKey []byte, err error)
+	// offer generates a keypair using rand. It returns the encoded |publicKey|.
+	offer(rand io.Reader) (publicKey []byte, err error)
 
-	// computeSecret performs a key exchange against peerKey and returns
-	// the resulting shared secret.
-	computeSecret(peerKey []byte) (preMasterSecret []byte, err error)
+	// accept responds to the |peerKey| generated by |offer| with the acceptor's
+	// |publicKey|, and returns agreed-upon |preMasterSecret| to the acceptor.
+	accept(rand io.Reader, peerKey []byte) (publicKey []byte, preMasterSecret []byte, err error)
+
+	// finish returns the computed |preMasterSecret|, given the |peerKey|
+	// generated by |accept|.
+	finish(peerKey []byte) (preMasterSecret []byte, err error)
 }
 
 // ellipticECDHCurve implements ecdhCurve with an elliptic.Curve.
@@ -267,7 +203,7 @@
 	privateKey []byte
 }
 
-func (e *ellipticECDHCurve) generateKeypair(rand io.Reader) (publicKey []byte, err error) {
+func (e *ellipticECDHCurve) offer(rand io.Reader) (publicKey []byte, err error) {
 	var x, y *big.Int
 	e.privateKey, x, y, err = elliptic.GenerateKey(e.curve, rand)
 	if err != nil {
@@ -276,7 +212,19 @@
 	return elliptic.Marshal(e.curve, x, y), nil
 }
 
-func (e *ellipticECDHCurve) computeSecret(peerKey []byte) (preMasterSecret []byte, err error) {
+func (e *ellipticECDHCurve) accept(rand io.Reader, peerKey []byte) (publicKey []byte, preMasterSecret []byte, err error) {
+	publicKey, err = e.offer(rand)
+	if err != nil {
+		return nil, nil, err
+	}
+	preMasterSecret, err = e.finish(peerKey)
+	if err != nil {
+		return nil, nil, err
+	}
+	return
+}
+
+func (e *ellipticECDHCurve) finish(peerKey []byte) (preMasterSecret []byte, err error) {
 	x, y := elliptic.Unmarshal(e.curve, peerKey)
 	if x == nil {
 		return nil, errors.New("tls: invalid peer key")
@@ -294,7 +242,7 @@
 	privateKey [32]byte
 }
 
-func (e *x25519ECDHCurve) generateKeypair(rand io.Reader) (publicKey []byte, err error) {
+func (e *x25519ECDHCurve) offer(rand io.Reader) (publicKey []byte, err error) {
 	_, err = io.ReadFull(rand, e.privateKey[:])
 	if err != nil {
 		return
@@ -304,7 +252,19 @@
 	return out[:], nil
 }
 
-func (e *x25519ECDHCurve) computeSecret(peerKey []byte) (preMasterSecret []byte, err error) {
+func (e *x25519ECDHCurve) accept(rand io.Reader, peerKey []byte) (publicKey []byte, preMasterSecret []byte, err error) {
+	publicKey, err = e.offer(rand)
+	if err != nil {
+		return nil, nil, err
+	}
+	preMasterSecret, err = e.finish(peerKey)
+	if err != nil {
+		return nil, nil, err
+	}
+	return
+}
+
+func (e *x25519ECDHCurve) finish(peerKey []byte) (preMasterSecret []byte, err error) {
 	if len(peerKey) != 32 {
 		return nil, errors.New("tls: invalid peer key")
 	}
@@ -312,8 +272,7 @@
 	copy(peerKeyCopy[:], peerKey)
 	curve25519.ScalarMult(&out, &e.privateKey, &peerKeyCopy)
 
-	// Per draft-irtf-cfrg-curves-11, reject the all-zero value in constant
-	// time.
+	// Per RFC 7748, reject the all-zero value in constant time.
 	var zeros [32]byte
 	if subtle.ConstantTimeCompare(zeros[:], out[:]) == 1 {
 		return nil, errors.New("tls: X25519 value with wrong order")
@@ -361,91 +320,52 @@
 	return nil
 }
 
-func maybeCorruptECDSAValue(n *big.Int, typeOfCorruption BadValue, limit *big.Int) *big.Int {
-	switch typeOfCorruption {
-	case BadValueNone:
-		return n
-	case BadValueNegative:
-		return new(big.Int).Neg(n)
-	case BadValueZero:
-		return big.NewInt(0)
-	case BadValueLimit:
-		return limit
-	case BadValueLarge:
-		bad := new(big.Int).Set(limit)
-		return bad.Lsh(bad, 20)
-	default:
-		panic("unknown BadValue type")
-	}
-}
-
 // signedKeyAgreement signs the ServerKeyExchange parameters with the
 // server's private key.
 type signedKeyAgreement struct {
-	version uint16
-	sigType uint8
+	keyType                keyType
+	version                uint16
+	peerSignatureAlgorithm signatureAlgorithm
 }
 
 func (ka *signedKeyAgreement) signParameters(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg, params []byte) (*serverKeyExchangeMsg, error) {
-	var tls12HashId uint8
+	// The message to be signed is prepended by the randoms.
+	var msg []byte
+	msg = append(msg, clientHello.random...)
+	msg = append(msg, hello.random...)
+	msg = append(msg, params...)
+
+	var sigAlg signatureAlgorithm
 	var err error
 	if ka.version >= VersionTLS12 {
-		if tls12HashId, err = pickTLS12HashForSignature(ka.sigType, clientHello.signatureAndHashes, config.signatureAndHashesForServer()); err != nil {
+		sigAlg, err = selectSignatureAlgorithm(ka.version, cert.PrivateKey, config, clientHello.signatureAlgorithms)
+		if err != nil {
 			return nil, err
 		}
 	}
 
-	digest, hashFunc, err := hashForServerKeyExchange(ka.sigType, tls12HashId, ka.version, clientHello.random, hello.random, params)
+	sig, err := signMessage(ka.version, cert.PrivateKey, config, sigAlg, msg)
 	if err != nil {
 		return nil, err
 	}
-
-	if config.Bugs.InvalidSKXSignature {
-		digest[0] ^= 0x80
-	}
-
-	var sig []byte
-	switch ka.sigType {
-	case signatureECDSA:
-		privKey, ok := cert.PrivateKey.(*ecdsa.PrivateKey)
-		if !ok {
-			return nil, errors.New("ECDHE ECDSA requires an ECDSA server private key")
-		}
-		r, s, err := ecdsa.Sign(config.rand(), privKey, digest)
-		if err != nil {
-			return nil, errors.New("failed to sign ECDHE parameters: " + err.Error())
-		}
-		order := privKey.Curve.Params().N
-		r = maybeCorruptECDSAValue(r, config.Bugs.BadECDSAR, order)
-		s = maybeCorruptECDSAValue(s, config.Bugs.BadECDSAS, order)
-		sig, err = asn1.Marshal(ecdsaSignature{r, s})
-	case signatureRSA:
-		privKey, ok := cert.PrivateKey.(*rsa.PrivateKey)
-		if !ok {
-			return nil, errors.New("ECDHE RSA requires a RSA server private key")
-		}
-		sig, err = rsa.SignPKCS1v15(config.rand(), privKey, hashFunc, digest)
-		if err != nil {
-			return nil, errors.New("failed to sign ECDHE parameters: " + err.Error())
-		}
-	default:
-		return nil, errors.New("unknown ECDHE signature algorithm")
+	if config.Bugs.SendSignatureAlgorithm != 0 {
+		sigAlg = config.Bugs.SendSignatureAlgorithm
 	}
 
 	skx := new(serverKeyExchangeMsg)
 	if config.Bugs.UnauthenticatedECDH {
 		skx.key = params
 	} else {
-		sigAndHashLen := 0
+		sigAlgsLen := 0
 		if ka.version >= VersionTLS12 {
-			sigAndHashLen = 2
+			sigAlgsLen = 2
 		}
-		skx.key = make([]byte, len(params)+sigAndHashLen+2+len(sig))
+		skx.key = make([]byte, len(params)+sigAlgsLen+2+len(sig))
 		copy(skx.key, params)
 		k := skx.key[len(params):]
 		if ka.version >= VersionTLS12 {
-			k[0] = tls12HashId
-			k[1] = ka.sigType
+			k[0] = byte(sigAlg >> 8)
+			k[1] = byte(sigAlg)
 			k = k[2:]
 		}
 		k[0] = byte(len(sig) >> 8)
@@ -457,26 +377,41 @@
 }
 
 func (ka *signedKeyAgreement) verifyParameters(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, params []byte, sig []byte) error {
-	if len(sig) < 2 {
-		return errServerKeyExchange
+	// The peer's key must match the cipher type.
+	switch ka.keyType {
+	case keyTypeECDSA:
+		_, ok := cert.PublicKey.(*ecdsa.PublicKey)
+		if !ok {
+			return errors.New("tls: ECDHE ECDSA requires a ECDSA server public key")
+		}
+	case keyTypeRSA:
+		_, ok := cert.PublicKey.(*rsa.PublicKey)
+		if !ok {
+			return errors.New("tls: ECDHE RSA requires a RSA server public key")
+		}
+	default:
+		return errors.New("tls: unknown key type")
 	}
 
-	var tls12HashId uint8
+	// The message to be signed is prepended by the randoms.
+	var msg []byte
+	msg = append(msg, clientHello.random...)
+	msg = append(msg, serverHello.random...)
+	msg = append(msg, params...)
+
+	var sigAlg signatureAlgorithm
 	if ka.version >= VersionTLS12 {
-		// handle SignatureAndHashAlgorithm
-		var sigAndHash []uint8
-		sigAndHash, sig = sig[:2], sig[2:]
-		if sigAndHash[1] != ka.sigType {
-			return errServerKeyExchange
-		}
-		tls12HashId = sigAndHash[0]
 		if len(sig) < 2 {
 			return errServerKeyExchange
 		}
+		sigAlg = signatureAlgorithm(sig[0])<<8 | signatureAlgorithm(sig[1])
+		sig = sig[2:]
+		// Stash the signature algorithm to be extracted by the handshake.
+		ka.peerSignatureAlgorithm = sigAlg
+	}
 
-		if !isSupportedSignatureAndHash(signatureAndHash{ka.sigType, tls12HashId}, config.signatureAndHashesForClient()) {
-			return errors.New("tls: unsupported hash function for ServerKeyExchange")
-		}
+	if len(sig) < 2 {
+		return errServerKeyExchange
 	}
 	sigLen := int(sig[0])<<8 | int(sig[1])
 	if sigLen+2 != len(sig) {
@@ -484,48 +419,17 @@
 	}
 	sig = sig[2:]
 
-	digest, hashFunc, err := hashForServerKeyExchange(ka.sigType, tls12HashId, ka.version, clientHello.random, serverHello.random, params)
-	if err != nil {
-		return err
-	}
-	switch ka.sigType {
-	case signatureECDSA:
-		pubKey, ok := cert.PublicKey.(*ecdsa.PublicKey)
-		if !ok {
-			return errors.New("ECDHE ECDSA requires a ECDSA server public key")
-		}
-		ecdsaSig := new(ecdsaSignature)
-		if _, err := asn1.Unmarshal(sig, ecdsaSig); err != nil {
-			return err
-		}
-		if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
-			return errors.New("ECDSA signature contained zero or negative values")
-		}
-		if !ecdsa.Verify(pubKey, digest, ecdsaSig.R, ecdsaSig.S) {
-			return errors.New("ECDSA verification failure")
-		}
-	case signatureRSA:
-		pubKey, ok := cert.PublicKey.(*rsa.PublicKey)
-		if !ok {
-			return errors.New("ECDHE RSA requires a RSA server public key")
-		}
-		if err := rsa.VerifyPKCS1v15(pubKey, hashFunc, digest, sig); err != nil {
-			return err
-		}
-	default:
-		return errors.New("unknown ECDHE signature algorithm")
-	}
-
-	return nil
+	return verifyMessage(ka.version, cert.PublicKey, config, sigAlg, msg, sig)
 }
 
-// ecdheRSAKeyAgreement implements a TLS key agreement where the server
+// ecdheKeyAgreement implements a TLS key agreement where the server
 // generates a ephemeral EC public/private key pair and signs it. The
 // pre-master secret is then calculated using ECDH. The signature may
 // either be ECDSA or RSA.
 type ecdheKeyAgreement struct {
 	auth    keyAgreementAuthentication
 	curve   ecdhCurve
+	curveID CurveID
 	peerKey []byte
 }
 
@@ -551,8 +455,9 @@
 	if ka.curve, ok = curveForCurveID(curveid); !ok {
 		return nil, errors.New("tls: preferredCurves includes unsupported curve")
 	}
+	ka.curveID = curveid
 
-	publicKey, err := ka.curve.generateKeypair(config.rand())
+	publicKey, err := ka.curve.offer(config.rand())
 	if err != nil {
 		return nil, err
 	}
@@ -560,13 +465,16 @@
 	// http://tools.ietf.org/html/rfc4492#section-5.4
 	serverECDHParams := make([]byte, 1+2+1+len(publicKey))
 	serverECDHParams[0] = 3 // named curve
+	if config.Bugs.SendCurve != 0 {
+		curveid = config.Bugs.SendCurve
+	}
 	serverECDHParams[1] = byte(curveid >> 8)
 	serverECDHParams[2] = byte(curveid)
-	if config.Bugs.InvalidSKXCurve {
-		serverECDHParams[2] ^= 0xff
-	}
 	serverECDHParams[3] = byte(len(publicKey))
 	copy(serverECDHParams[4:], publicKey)
+	if config.Bugs.InvalidECDHPoint {
+		serverECDHParams[4] ^= 0xff
+	}
 
 	return ka.auth.signParameters(config, cert, clientHello, hello, serverECDHParams)
 }
@@ -575,7 +483,7 @@
 	if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 {
 		return nil, errClientKeyExchange
 	}
-	return ka.curve.computeSecret(ckx.ciphertext[1:])
+	return ka.curve.finish(ckx.ciphertext[1:])
 }
 
 func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
@@ -586,6 +494,7 @@
 		return errors.New("tls: server selected unsupported curve")
 	}
 	curveid := CurveID(skx.key[1])<<8 | CurveID(skx.key[2])
+	ka.curveID = curveid
 
 	var ok bool
 	if ka.curve, ok = curveForCurveID(curveid); !ok {
@@ -610,11 +519,7 @@
 		return nil, nil, errors.New("missing ServerKeyExchange message")
 	}
 
-	publicKey, err := ka.curve.generateKeypair(config.rand())
-	if err != nil {
-		return nil, nil, err
-	}
-	preMasterSecret, err := ka.curve.computeSecret(ka.peerKey)
+	publicKey, preMasterSecret, err := ka.curve.accept(config.rand(), ka.peerKey)
 	if err != nil {
 		return nil, nil, err
 	}
@@ -623,10 +528,20 @@
 	ckx.ciphertext = make([]byte, 1+len(publicKey))
 	ckx.ciphertext[0] = byte(len(publicKey))
 	copy(ckx.ciphertext[1:], publicKey)
+	if config.Bugs.InvalidECDHPoint {
+		ckx.ciphertext[1] ^= 0xff
+	}
 
 	return preMasterSecret, ckx, nil
 }
 
+func (ka *ecdheKeyAgreement) peerSignatureAlgorithm() signatureAlgorithm {
+	if auth, ok := ka.auth.(*signedKeyAgreement); ok {
+		return auth.peerSignatureAlgorithm
+	}
+	return 0
+}
+
 // dheRSAKeyAgreement implements a TLS key agreement where the server generates
 // an ephemeral Diffie-Hellman public/private key pair and signs it. The
 // pre-master secret is then calculated using Diffie-Hellman.
@@ -761,6 +676,13 @@
 	return preMasterSecret, ckx, nil
 }
 
+func (ka *dheKeyAgreement) peerSignatureAlgorithm() signatureAlgorithm {
+	if auth, ok := ka.auth.(*signedKeyAgreement); ok {
+		return auth.peerSignatureAlgorithm
+	}
+	return 0
+}
+
 // nilKeyAgreement is a fake key agreement used to implement the plain PSK key
 // exchange.
 type nilKeyAgreement struct{}
@@ -796,6 +718,10 @@
 	return nil, &clientKeyExchangeMsg{}, nil
 }
 
+func (ka *nilKeyAgreement) peerSignatureAlgorithm() signatureAlgorithm {
+	return 0
+}
+
 // makePSKPremaster formats a PSK pre-master secret based on otherSecret from
 // the base key exchange and psk.
 func makePSKPremaster(otherSecret, psk []byte) []byte {
@@ -829,7 +755,7 @@
 
 	if baseSkx != nil {
 		bytes = append(bytes, baseSkx.key...)
-	} else if config.PreSharedKeyIdentity == "" {
+	} else if config.PreSharedKeyIdentity == "" && !config.Bugs.AlwaysSendPreSharedKeyIdentityHint {
 		// ServerKeyExchange is optional if the identity hint is empty
 		// and there would otherwise be no ServerKeyExchange.
 		return nil, nil
@@ -921,3 +847,7 @@
 	}
 	return makePSKPremaster(otherSecret, config.PreSharedKey), ckx, nil
 }
+
+func (ka *pskKeyAgreement) peerSignatureAlgorithm() signatureAlgorithm {
+	return 0
+}
diff --git a/src/ssl/test/runner/prf.go b/src/ssl/test/runner/prf.go
index 8521aba..cfc383d 100644
--- a/src/ssl/test/runner/prf.go
+++ b/src/ssl/test/runner/prf.go
@@ -10,8 +10,6 @@
 	"crypto/md5"
 	"crypto/sha1"
 	"crypto/sha256"
-	"crypto/sha512"
-	"errors"
 	"hash"
 )
 
@@ -121,6 +119,7 @@
 var keyExpansionLabel = []byte("key expansion")
 var clientFinishedLabel = []byte("client finished")
 var serverFinishedLabel = []byte("server finished")
+var finishedLabel = []byte("finished")
 var channelIDLabel = []byte("TLS Channel ID signature\x00")
 var channelIDResumeLabel = []byte("Resumption\x00")
 
@@ -131,13 +130,9 @@
 	case VersionTLS10, VersionTLS11:
 		return prf10
 	case VersionTLS12:
-		if suite.flags&suiteSHA384 != 0 {
-			return prf12(sha512.New384)
-		}
-		return prf12(sha256.New)
-	default:
-		panic("unknown version")
+		return prf12(suite.hash().New)
 	}
+	panic("unknown version")
 }
 
 // masterFromPreMasterSecret generates the master secret from the pre-master
@@ -153,7 +148,7 @@
 
 // extendedMasterFromPreMasterSecret generates the master secret from the
 // pre-master secret when the Triple Handshake fix is in effect. See
-// https://tools.ietf.org/html/draft-ietf-tls-session-hash-01
+// https://tools.ietf.org/html/rfc7627
 func extendedMasterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret []byte, h finishedHash) []byte {
 	masterSecret := make([]byte, masterSecretLength)
 	prfForVersion(version, suite)(masterSecret, preMasterSecret, extendedMasterSecretLabel, h.Sum())
@@ -185,42 +180,41 @@
 	return
 }
 
-// lookupTLSHash looks up the corresponding crypto.Hash for a given
-// TLS hash identifier.
-func lookupTLSHash(hash uint8) (crypto.Hash, error) {
-	switch hash {
-	case hashMD5:
-		return crypto.MD5, nil
-	case hashSHA1:
-		return crypto.SHA1, nil
-	case hashSHA224:
-		return crypto.SHA224, nil
-	case hashSHA256:
-		return crypto.SHA256, nil
-	case hashSHA384:
-		return crypto.SHA384, nil
-	case hashSHA512:
-		return crypto.SHA512, nil
-	default:
-		return 0, errors.New("tls: unsupported hash algorithm")
-	}
-}
-
 func newFinishedHash(version uint16, cipherSuite *cipherSuite) finishedHash {
-	if version >= VersionTLS12 {
-		newHash := sha256.New
-		if cipherSuite.flags&suiteSHA384 != 0 {
-			newHash = sha512.New384
-		}
+	var ret finishedHash
 
-		return finishedHash{newHash(), newHash(), nil, nil, []byte{}, version, prf12(newHash)}
+	if version >= VersionTLS12 {
+		ret.hash = cipherSuite.hash()
+
+		ret.client = ret.hash.New()
+		ret.server = ret.hash.New()
+
+		if version == VersionTLS12 {
+			ret.prf = prf12(ret.hash.New)
+		} else {
+			ret.secret = make([]byte, ret.hash.Size())
+		}
+	} else {
+		ret.hash = crypto.MD5SHA1
+
+		ret.client = sha1.New()
+		ret.server = sha1.New()
+		ret.clientMD5 = md5.New()
+		ret.serverMD5 = md5.New()
+
+		ret.prf = prf10
 	}
-	return finishedHash{sha1.New(), sha1.New(), md5.New(), md5.New(), []byte{}, version, prf10}
+
+	ret.buffer = []byte{}
+	ret.version = version
+	return ret
 }
 
 // A finishedHash calculates the hash of a set of handshake messages suitable
 // for including in a Finished message.
 type finishedHash struct {
+	hash crypto.Hash
+
 	client hash.Hash
 	server hash.Hash
 
@@ -234,6 +228,9 @@
 
 	version uint16
 	prf     func(result, secret, label, seed []byte)
+
+	// secret, in TLS 1.3, is the running input secret.
+	secret []byte
 }
 
 func (h *finishedHash) Write(msg []byte) (n int, err error) {
@@ -299,72 +296,50 @@
 
 // clientSum returns the contents of the verify_data member of a client's
 // Finished message.
-func (h finishedHash) clientSum(masterSecret []byte) []byte {
+func (h finishedHash) clientSum(baseKey []byte) []byte {
 	if h.version == VersionSSL30 {
-		return finishedSum30(h.clientMD5, h.client, masterSecret, ssl3ClientFinishedMagic[:])
+		return finishedSum30(h.clientMD5, h.client, baseKey, ssl3ClientFinishedMagic[:])
 	}
 
-	out := make([]byte, finishedVerifyLength)
-	h.prf(out, masterSecret, clientFinishedLabel, h.Sum())
-	return out
+	if h.version < VersionTLS13 {
+		out := make([]byte, finishedVerifyLength)
+		h.prf(out, baseKey, clientFinishedLabel, h.Sum())
+		return out
+	}
+
+	clientFinishedKey := hkdfExpandLabel(h.hash, baseKey, finishedLabel, nil, h.hash.Size())
+	finishedHMAC := hmac.New(h.hash.New, clientFinishedKey)
+	finishedHMAC.Write(h.appendContextHashes(nil))
+	return finishedHMAC.Sum(nil)
 }
 
 // serverSum returns the contents of the verify_data member of a server's
 // Finished message.
-func (h finishedHash) serverSum(masterSecret []byte) []byte {
+func (h finishedHash) serverSum(baseKey []byte) []byte {
 	if h.version == VersionSSL30 {
-		return finishedSum30(h.serverMD5, h.server, masterSecret, ssl3ServerFinishedMagic[:])
+		return finishedSum30(h.serverMD5, h.server, baseKey, ssl3ServerFinishedMagic[:])
 	}
 
-	out := make([]byte, finishedVerifyLength)
-	h.prf(out, masterSecret, serverFinishedLabel, h.Sum())
-	return out
+	if h.version < VersionTLS13 {
+		out := make([]byte, finishedVerifyLength)
+		h.prf(out, baseKey, serverFinishedLabel, h.Sum())
+		return out
+	}
+
+	serverFinishedKey := hkdfExpandLabel(h.hash, baseKey, finishedLabel, nil, h.hash.Size())
+	finishedHMAC := hmac.New(h.hash.New, serverFinishedKey)
+	finishedHMAC.Write(h.appendContextHashes(nil))
+	return finishedHMAC.Sum(nil)
 }
 
-// selectClientCertSignatureAlgorithm returns a signatureAndHash to sign a
-// client's CertificateVerify with, or an error if none can be found.
-func (h finishedHash) selectClientCertSignatureAlgorithm(serverList, clientList []signatureAndHash, sigType uint8) (signatureAndHash, error) {
-	if h.version < VersionTLS12 {
-		// Nothing to negotiate before TLS 1.2.
-		return signatureAndHash{signature: sigType}, nil
-	}
-
-	for _, v := range serverList {
-		if v.signature == sigType && isSupportedSignatureAndHash(v, clientList) {
-			return v, nil
-		}
-	}
-	return signatureAndHash{}, errors.New("tls: no supported signature algorithm found for signing client certificate")
-}
-
-// hashForClientCertificate returns a digest, hash function, and TLS 1.2 hash
-// id suitable for signing by a TLS client certificate.
-func (h finishedHash) hashForClientCertificate(signatureAndHash signatureAndHash, masterSecret []byte) ([]byte, crypto.Hash, error) {
-	if h.version == VersionSSL30 {
-		if signatureAndHash.signature != signatureRSA {
-			return nil, 0, errors.New("tls: unsupported signature type for client certificate")
-		}
-
-		md5Hash := md5.New()
-		md5Hash.Write(h.buffer)
-		sha1Hash := sha1.New()
-		sha1Hash.Write(h.buffer)
-		return finishedSum30(md5Hash, sha1Hash, masterSecret, nil), crypto.MD5SHA1, nil
-	}
-	if h.version >= VersionTLS12 {
-		hashAlg, err := lookupTLSHash(signatureAndHash.hash)
-		if err != nil {
-			return nil, 0, err
-		}
-		hash := hashAlg.New()
-		hash.Write(h.buffer)
-		return hash.Sum(nil), hashAlg, nil
-	}
-	if signatureAndHash.signature == signatureECDSA {
-		return h.server.Sum(nil), crypto.SHA1, nil
-	}
-
-	return h.Sum(), crypto.MD5SHA1, nil
+// hashForClientCertificateSSL3 returns the hash to be signed for client
+// certificates in SSL 3.0.
+func (h finishedHash) hashForClientCertificateSSL3(masterSecret []byte) []byte {
+	md5Hash := md5.New()
+	md5Hash.Write(h.buffer)
+	sha1Hash := sha1.New()
+	sha1Hash.Write(h.buffer)
+	return finishedSum30(md5Hash, sha1Hash, masterSecret, nil)
 }
 
 // hashForChannelID returns the hash to be signed for TLS Channel
@@ -377,7 +352,7 @@
 		hash.Write(channelIDResumeLabel)
 		hash.Write(resumeHash)
 	}
-	hash.Write(h.server.Sum(nil))
+	hash.Write(h.Sum())
 	return hash.Sum(nil)
 }
 
@@ -386,3 +361,118 @@
 func (h *finishedHash) discardHandshakeBuffer() {
 	h.buffer = nil
 }
+
+// zeroSecretTLS13 returns the default all zeros secret for TLS 1.3, used when a
+// given secret is not available in the handshake. See draft-ietf-tls-tls13-16,
+// section 7.1.
+func (h *finishedHash) zeroSecret() []byte {
+	return make([]byte, h.hash.Size())
+}
+
+// addEntropy incorporates ikm into the running TLS 1.3 secret with HKDF-Expand.
+func (h *finishedHash) addEntropy(ikm []byte) {
+	h.secret = hkdfExtract(h.hash.New, h.secret, ikm)
+}
+
+// hkdfExpandLabel implements TLS 1.3's HKDF-Expand-Label function, as defined
+// in section 7.1 of draft-ietf-tls-tls13-16.
+func hkdfExpandLabel(hash crypto.Hash, secret, label, hashValue []byte, length int) []byte {
+	if len(label) > 255 || len(hashValue) > 255 {
+		panic("hkdfExpandLabel: label or hashValue too long")
+	}
+	hkdfLabel := make([]byte, 3+9+len(label)+1+len(hashValue))
+	x := hkdfLabel
+	x[0] = byte(length >> 8)
+	x[1] = byte(length)
+	x[2] = byte(9 + len(label))
+	x = x[3:]
+	copy(x, []byte("TLS 1.3, "))
+	x = x[9:]
+	copy(x, label)
+	x = x[len(label):]
+	x[0] = byte(len(hashValue))
+	copy(x[1:], hashValue)
+	return hkdfExpand(hash.New, secret, hkdfLabel, length)
+}
+
+// appendContextHashes returns the concatenation of the handshake hash and the
+// resumption context hash, as used in TLS 1.3.
+func (h *finishedHash) appendContextHashes(b []byte) []byte {
+	b = h.client.Sum(b)
+	return b
+}
+
+// The following are labels for traffic secret derivation in TLS 1.3.
+var (
+	externalPSKBinderLabel        = []byte("external psk binder key")
+	resumptionPSKBinderLabel      = []byte("resumption psk binder key")
+	earlyTrafficLabel             = []byte("client early traffic secret")
+	clientHandshakeTrafficLabel   = []byte("client handshake traffic secret")
+	serverHandshakeTrafficLabel   = []byte("server handshake traffic secret")
+	clientApplicationTrafficLabel = []byte("client application traffic secret")
+	serverApplicationTrafficLabel = []byte("server application traffic secret")
+	applicationTrafficLabel       = []byte("application traffic secret")
+	exporterLabel                 = []byte("exporter master secret")
+	resumptionLabel               = []byte("resumption master secret")
+)
+
+// deriveSecret implements TLS 1.3's Derive-Secret function, as defined in
+// section 7.1 of draft ietf-tls-tls13-16.
+func (h *finishedHash) deriveSecret(label []byte) []byte {
+	return hkdfExpandLabel(h.hash, h.secret, label, h.appendContextHashes(nil), h.hash.Size())
+}
+
+// The following are context strings for CertificateVerify in TLS 1.3.
+var (
+	clientCertificateVerifyContextTLS13 = []byte("TLS 1.3, client CertificateVerify")
+	serverCertificateVerifyContextTLS13 = []byte("TLS 1.3, server CertificateVerify")
+	channelIDContextTLS13               = []byte("TLS 1.3, Channel ID")
+)
+
+// certificateVerifyMessage returns the input to be signed for CertificateVerify
+// in TLS 1.3.
+func (h *finishedHash) certificateVerifyInput(context []byte) []byte {
+	const paddingLen = 64
+	b := make([]byte, paddingLen, paddingLen+len(context)+1+2*h.hash.Size())
+	for i := 0; i < paddingLen; i++ {
+		b[i] = 32
+	}
+	b = append(b, context...)
+	b = append(b, 0)
+	b = h.appendContextHashes(b)
+	return b
+}
+
+type trafficDirection int
+
+const (
+	clientWrite trafficDirection = iota
+	serverWrite
+)
+
+var (
+	keyTLS13 = []byte("key")
+	ivTLS13  = []byte("iv")
+)
+
+// deriveTrafficAEAD derives traffic keys and constructs an AEAD given a traffic
+// secret.
+func deriveTrafficAEAD(version uint16, suite *cipherSuite, secret []byte, side trafficDirection) interface{} {
+	key := hkdfExpandLabel(suite.hash(), secret, keyTLS13, nil, suite.keyLen)
+	iv := hkdfExpandLabel(suite.hash(), secret, ivTLS13, nil, suite.ivLen(version))
+
+	return suite.aead(version, key, iv)
+}
+
+func updateTrafficSecret(hash crypto.Hash, secret []byte) []byte {
+	return hkdfExpandLabel(hash, secret, applicationTrafficLabel, nil, hash.Size())
+}
+
+func computePSKBinder(psk, label []byte, cipherSuite *cipherSuite, transcript, truncatedHello []byte) []byte {
+	finishedHash := newFinishedHash(VersionTLS13, cipherSuite)
+	finishedHash.addEntropy(psk)
+	binderKey := finishedHash.deriveSecret(label)
+	finishedHash.Write(transcript)
+	finishedHash.Write(truncatedHello)
+	return finishedHash.clientSum(binderKey)
+}
diff --git a/src/ssl/test/runner/recordingconn.go b/src/ssl/test/runner/recordingconn.go
index 39deb19..4dae435 100644
--- a/src/ssl/test/runner/recordingconn.go
+++ b/src/ssl/test/runner/recordingconn.go
@@ -1,3 +1,17 @@
+// Copyright (c) 2016, Google Inc.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
 package runner
 
 import (
@@ -92,6 +106,17 @@
 	}
 }
 
+func (r *recordingConn) Transcript() []byte {
+	var ret []byte
+	for _, flow := range r.flows {
+		if flow.flowType != writeFlow {
+			continue
+		}
+		ret = append(ret, flow.data...)
+	}
+	return ret
+}
+
 func parseTestData(r io.Reader) (flows [][]byte, err error) {
 	var currentFlow []byte
 
diff --git a/src/ssl/test/runner/rsa_1024_cert.pem b/src/ssl/test/runner/rsa_1024_cert.pem
new file mode 100644
index 0000000..4de4f49
--- /dev/null
+++ b/src/ssl/test/runner/rsa_1024_cert.pem
@@ -0,0 +1,15 @@
+-----BEGIN CERTIFICATE-----
+MIICWDCCAcGgAwIBAgIJAPuwTC6rEJsMMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQwHhcNMTQwNDIzMjA1MDQwWhcNMTcwNDIyMjA1MDQwWjBF
+MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
+ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
+gQDYK8imMuRi/03z0K1Zi0WnvfFHvwlYeyK9Na6XJYaUoIDAtB92kWdGMdAQhLci
+HnAjkXLI6W15OoV3gA/ElRZ1xUpxTMhjP6PyY5wqT5r6y8FxbiiFKKAnHmUcrgfV
+W28tQ+0rkLGMryRtrukXOgXBv7gcrmU7G1jC2a7WqmeI8QIDAQABo1AwTjAdBgNV
+HQ4EFgQUi3XVrMsIvg4fZbf6Vr5sp3Xaha8wHwYDVR0jBBgwFoAUi3XVrMsIvg4f
+Zbf6Vr5sp3Xaha8wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQA76Hht
+ldY9avcTGSwbwoiuIqv0jTL1fHFnzy3RHMLDh+Lpvolc5DSrSJHCP5WuK0eeJXhr
+T5oQpHL9z/cCDLAKCKRa4uV0fhEdOWBqyR9p8y5jJtye72t6CuFUV5iqcpF4BH4f
+j2VNHwsSrJwkD4QUGlUtH7vwnQmyCFxZMmWAJg==
+-----END CERTIFICATE-----
diff --git a/src/ssl/test/runner/rsa_1024_key.pem b/src/ssl/test/runner/rsa_1024_key.pem
new file mode 100644
index 0000000..2a3b9de
--- /dev/null
+++ b/src/ssl/test/runner/rsa_1024_key.pem
@@ -0,0 +1,16 @@
+-----BEGIN PRIVATE KEY-----
+MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBANgryKYy5GL/TfPQ
+rVmLRae98Ue/CVh7Ir01rpclhpSggMC0H3aRZ0Yx0BCEtyIecCORcsjpbXk6hXeA
+D8SVFnXFSnFMyGM/o/JjnCpPmvrLwXFuKIUooCceZRyuB9Vbby1D7SuQsYyvJG2u
+6Rc6BcG/uByuZTsbWMLZrtaqZ4jxAgMBAAECgYEAgHLT0V3gM6r8iOnwd4q4IwpM
+epNbXEYeyEtDqPBVXa9Zkif1oiCYOy+SMJ6Lqyxm+duNVzDNKgHKGM3xkJ/+LXkc
+QJYMUWHqC3Q/nPQycKHDNma9q1X8VcJPSP5aYY0H+CR6EqMZcstyNNvp1FhUlIJm
+FW44stxtYhXXSCCAlAECQQDxLywZ7h7PLJmbh72v3mDqzjeQ+q2Pmt7BOxTG37af
+h5Wh0P5lSUJQtZU0AUuRhFMEIBKVKub1eGNCmZYAclSRAkEA5XNB0VRp7Au104mg
+8K2lihjXN3bZ5p7xNASakY5HXUvqRvEtCyRoyXL8M6c5prza2oAZN2oMRmBI2YJ4
+oqSeYQJAC+mdjwZQ5UC5sZHpz5b3SIG5AuMu0Wn/2KF3bD8+gPCsdlqhRhVxPhVJ
+8lCiD+TuSMTgxhdhYvx4QqDdZNZA0QJBAOTXThaL3VSZ3U/MXSKN3aNc4RElTXAQ
+p7pcuRhg0dZAB7mXgngxaP053EVcDEi65H+18PBuqS1rjFy7Hrv/+SECQQC+9Fcs
+dNprpUXNNqKI7xJoWwdXeVDJc60ysGkHmN2ahlaCMe8HZb0KSfuwOqw8H5Ta3JfS
+OgN1ATK6IwQINjyh
+-----END PRIVATE KEY-----
diff --git a/src/ssl/test/runner/rsa_chain_cert.pem b/src/ssl/test/runner/rsa_chain_cert.pem
new file mode 100644
index 0000000..8eb6e60
--- /dev/null
+++ b/src/ssl/test/runner/rsa_chain_cert.pem
@@ -0,0 +1,35 @@
+-----BEGIN CERTIFICATE-----
+MIIC0jCCAbqgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwDzENMAsGA1UEAwwEQiBD
+QTAeFw0xNjAyMjgyMDI3MDNaFw0yNjAyMjUyMDI3MDNaMBgxFjAUBgNVBAMMDUNs
+aWVudCBDZXJ0IEEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDRvaz8
+CC/cshpCafJo4jLkHEoBqDLhdgFelJoAiQUyIqyWl2O7YHPnpJH+TgR7oelzNzt/
+kLRcH89M/TszB6zqyLTC4aqmvzKL0peD/jL2LWBucR0WXIvjA3zoRuF/x86+rYH3
+tHb+xs2PSs8EGL/Ev+ss+qTzTGEn26fuGNHkNw6tOwPpc+o8+wUtzf/kAthamo+c
+IDs2rQ+lP7+aLZTLeU/q4gcLutlzcK5imex5xy2jPkweq48kijK0kIzl1cPlA5d1
+z7C8jU50Pj9X9sQDJTN32j7UYRisJeeYQF8GaaN8SbrDI6zHgKzrRLyxDt/KQa9V
+iLeXANgZi+Xx9KgfAgMBAAGjLzAtMAwGA1UdEwEB/wQCMAAwHQYDVR0lBBYwFAYI
+KwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQBFEVbmYl+2RtNw
+rDftRDF1v2QUbcN2ouSnQDHxeDQdSgasLzT3ui8iYu0Rw2WWcZ0DV5e0ztGPhWq7
+AO0B120aFRMOY+4+bzu9Q2FFkQqc7/fKTvTDzIJI5wrMnFvUfzzvxh3OHWMYSs/w
+giq33hTKeHEq6Jyk3btCny0Ycecyc3yGXH10sizUfiHlhviCkDuESk8mFDwDDzqW
+ZF0IipzFbEDHoIxLlm3GQxpiLoEV4k8KYJp3R5KBLFyxM6UGPz8h72mIPCJp2RuK
+MYgF91UDvVzvnYm6TfseM2+ewKirC00GOrZ7rEcFvtxnKSqYf4ckqfNdSU1Y+RRC
+1ngWZ7Ih
+-----END CERTIFICATE-----
+-----BEGIN CERTIFICATE-----
+MIICwjCCAaqgAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwFDESMBAGA1UEAwwJQyBS
+b290IENBMB4XDTE2MDIyODIwMjcwM1oXDTI2MDIyNTIwMjcwM1owDzENMAsGA1UE
+AwwEQiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALsSCYmDip2D
+GkjFxw7ykz26JSjELkl6ArlYjFJ3aT/SCh8qbS4gln7RH8CPBd78oFdfhIKQrwtZ
+3/q21ykD9BAS3qHe2YdcJfm8/kWAy5DvXk6NXU4qX334KofBAEpgdA/igEFq1P1l
+HAuIfZCpMRfT+i5WohVsGi8f/NgpRvVaMONLNfgw57mz1lbtFeBEISmX0kbsuJxF
+Qj/Bwhi5/0HAEXG8e7zN4cEx0yPRvmOATRdVb/8dW2pwOHRJq9R5M0NUkIsTSnL7
+6N/z8hRAHMsV3IudC5Yd7GXW1AGu9a+iKU+Q4xcZCoj0DC99tL4VKujrV1kAeqsM
+cz5/dKzi6+cCAwEAAaMjMCEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQELBQADggEBAIIeZiEeNhWWQ8Y4D+AGDwqUUeG8NjCbKrXQ
+BlHg5wZ8xftFaiP1Dp/UAezmx2LNazdmuwrYB8lm3FVTyaPDTKEGIPS4wJKHgqH1
+QPDhqNm85ey7TEtI9oYjsNim/Rb+iGkIAMXaxt58SzxbjvP0kMr1JfJIZbic9vye
+NwIspMFIpP3FB8ywyu0T0hWtCQgL4J47nigCHpOu58deP88fS/Nyz/fyGVWOZ76b
+WhWwgM3P3X95fQ3d7oFPR/bVh0YV+Cf861INwplokXgXQ3/TCQ+HNXeAMWn3JLWv
+XFwk8owk9dq/kQGdndGgy3KTEW4ctPX5GNhf3LJ9Q7dLji4ReQ4=
+-----END CERTIFICATE-----
diff --git a/src/ssl/test/runner/rsa_chain_key.pem b/src/ssl/test/runner/rsa_chain_key.pem
new file mode 100644
index 0000000..d94d704
--- /dev/null
+++ b/src/ssl/test/runner/rsa_chain_key.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDRvaz8CC/cshpC
+afJo4jLkHEoBqDLhdgFelJoAiQUyIqyWl2O7YHPnpJH+TgR7oelzNzt/kLRcH89M
+/TszB6zqyLTC4aqmvzKL0peD/jL2LWBucR0WXIvjA3zoRuF/x86+rYH3tHb+xs2P
+Ss8EGL/Ev+ss+qTzTGEn26fuGNHkNw6tOwPpc+o8+wUtzf/kAthamo+cIDs2rQ+l
+P7+aLZTLeU/q4gcLutlzcK5imex5xy2jPkweq48kijK0kIzl1cPlA5d1z7C8jU50
+Pj9X9sQDJTN32j7UYRisJeeYQF8GaaN8SbrDI6zHgKzrRLyxDt/KQa9ViLeXANgZ
+i+Xx9KgfAgMBAAECggEBAK0VjSJzkyPaamcyTVSWjo7GdaBGcK60lk657RjR+lK0
+YJ7pkej4oM2hdsVZFsP8Cs4E33nXLa/0pDsRov/qrp0WQm2skwqGMC1I/bZ0WRPk
+wHaDrBBfESWnJDX/AGpVtlyOjPmgmK6J2usMPihQUDkKdAYrVWJePrMIxt1q6BMe
+iczs3qriMmtY3bUc4UyUwJ5fhDLjshHvfuIpYQyI6EXZM6dZksn9LylXJnigY6QJ
+HxOYO0BDwOsZ8yQ8J8afLk88i0GizEkgE1z3REtQUwgWfxr1WV/ud+T6/ZhSAgH9
+042mQvSFZnIUSEsmCvjhWuAunfxHKCTcAoYISWfzWpkCgYEA7gpf3HHU5Tn+CgUn
+1X5uGpG3DmcMgfeGgs2r2f/IIg/5Ac1dfYILiybL1tN9zbyLCJfcbFpWBc9hJL6f
+CPc5hUiwWFJqBJewxQkC1Ae/HakHbip+IZ+Jr0842O4BAArvixk4Lb7/N2Ct9sTE
+NJO6RtK9lbEZ5uK61DglHy8CS2UCgYEA4ZC1o36kPAMQBggajgnucb2yuUEelk0f
+AEr+GI32MGE+93xMr7rAhBoqLg4AITyIfEnOSQ5HwagnIHonBbv1LV/Gf9ursx8Z
+YOGbvT8zzzC+SU1bkDzdjAYnFQVGIjMtKOBJ3K07++ypwX1fr4QsQ8uKL8WSOWwt
+Z3Bym6XiZzMCgYADnhy+2OwHX85AkLt+PyGlPbmuelpyTzS4IDAQbBa6jcuW/2wA
+UE2km75VUXmD+u2R/9zVuLm99NzhFhSMqlUxdV1YukfqMfP5yp1EY6m/5aW7QuIP
+2MDa7TVL9rIFMiVZ09RKvbBbQxjhuzPQKL6X/PPspnhiTefQ+dl2k9xREQKBgHDS
+fMfGNEeAEKezrfSVqxphE9/tXms3L+ZpnCaT+yu/uEr5dTIAawKoQ6i9f/sf1/Sy
+xedsqR+IB+oKrzIDDWMgoJybN4pkZ8E5lzhVQIjFjKgFdWLzzqyW9z1gYfABQPlN
+FiS20WX0vgP1vcKAjdNrHzc9zyHBpgQzDmAj3NZZAoGBAI8vKCKdH7w3aL5CNkZQ
+2buIeWNA2HZazVwAGG5F2TU/LmXfRKnG6dX5bkU+AkBZh56jNZy//hfFSewJB4Kk
+buB7ERSdaNbO21zXt9FEA3+z0RfMd/Zv2vlIWOSB5nzl/7UKti3sribK6s9ZVLfi
+SxpiPQ8d/hmSGwn4ksrWUsJD
+-----END PRIVATE KEY-----
diff --git a/src/ssl/test/runner/runner.go b/src/ssl/test/runner/runner.go
index 45bb0b7..3aa2c46 100644
--- a/src/ssl/test/runner/runner.go
+++ b/src/ssl/test/runner/runner.go
@@ -1,12 +1,31 @@
+// Copyright (c) 2016, Google Inc.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
 package runner
 
 import (
 	"bytes"
 	"crypto/ecdsa"
 	"crypto/elliptic"
+	"crypto/rand"
 	"crypto/x509"
+	"crypto/x509/pkix"
 	"encoding/base64"
+	"encoding/hex"
+	"encoding/json"
 	"encoding/pem"
+	"errors"
 	"flag"
 	"fmt"
 	"io"
@@ -16,6 +35,7 @@
 	"os"
 	"os/exec"
 	"path"
+	"path/filepath"
 	"runtime"
 	"strconv"
 	"strings"
@@ -25,53 +45,166 @@
 )
 
 var (
-	useValgrind     = flag.Bool("valgrind", false, "If true, run code under valgrind")
-	useGDB          = flag.Bool("gdb", false, "If true, run BoringSSL code under gdb")
-	useLLDB         = flag.Bool("lldb", false, "If true, run BoringSSL code under lldb")
-	flagDebug       = flag.Bool("debug", false, "Hexdump the contents of the connection")
-	mallocTest      = flag.Int64("malloc-test", -1, "If non-negative, run each test with each malloc in turn failing from the given number onwards.")
-	mallocTestDebug = flag.Bool("malloc-test-debug", false, "If true, ask bssl_shim to abort rather than fail a malloc. This can be used with a specific value for --malloc-test to identity the malloc failing that is causing problems.")
-	jsonOutput      = flag.String("json-output", "", "The file to output JSON results to.")
-	pipe            = flag.Bool("pipe", false, "If true, print status output suitable for piping into another program.")
-	testToRun       = flag.String("test", "", "The name of a test to run, or empty to run all tests")
-	numWorkers      = flag.Int("num-workers", runtime.NumCPU(), "The number of workers to run in parallel.")
-	shimPath        = flag.String("shim-path", "../../../build/ssl/test/bssl_shim", "The location of the shim binary.")
-	resourceDir     = flag.String("resource-dir", ".", "The directory in which to find certificate and key files.")
+	useValgrind        = flag.Bool("valgrind", false, "If true, run code under valgrind")
+	useGDB             = flag.Bool("gdb", false, "If true, run BoringSSL code under gdb")
+	useLLDB            = flag.Bool("lldb", false, "If true, run BoringSSL code under lldb")
+	flagDebug          = flag.Bool("debug", false, "Hexdump the contents of the connection")
+	mallocTest         = flag.Int64("malloc-test", -1, "If non-negative, run each test with each malloc in turn failing from the given number onwards.")
+	mallocTestDebug    = flag.Bool("malloc-test-debug", false, "If true, ask bssl_shim to abort rather than fail a malloc. This can be used with a specific value for --malloc-test to identity the malloc failing that is causing problems.")
+	jsonOutput         = flag.String("json-output", "", "The file to output JSON results to.")
+	pipe               = flag.Bool("pipe", false, "If true, print status output suitable for piping into another program.")
+	testToRun          = flag.String("test", "", "The pattern to filter tests to run, or empty to run all tests")
+	numWorkers         = flag.Int("num-workers", runtime.NumCPU(), "The number of workers to run in parallel.")
+	shimPath           = flag.String("shim-path", "../../../build/ssl/test/bssl_shim", "The location of the shim binary.")
+	resourceDir        = flag.String("resource-dir", ".", "The directory in which to find certificate and key files.")
+	fuzzer             = flag.Bool("fuzzer", false, "If true, tests against a BoringSSL built in fuzzer mode.")
+	transcriptDir      = flag.String("transcript-dir", "", "The directory in which to write transcripts.")
+	idleTimeout        = flag.Duration("idle-timeout", 15*time.Second, "The number of seconds to wait for a read or write to bssl_shim.")
+	deterministic      = flag.Bool("deterministic", false, "If true, uses a deterministic PRNG in the runner.")
+	allowUnimplemented = flag.Bool("allow-unimplemented", false, "If true, report pass even if some tests are unimplemented.")
+	looseErrors        = flag.Bool("loose-errors", false, "If true, allow shims to report an untranslated error code.")
+	shimConfigFile     = flag.String("shim-config", "", "A config file to use to configure the tests for this shim.")
+	includeDisabled    = flag.Bool("include-disabled", false, "If true, also runs disabled tests.")
+	includeDHE         = flag.Bool("include-dhe", false, "If true, test DHE ciphersuites.")
+	repeatUntilFailure = flag.Bool("repeat-until-failure", false, "If true, the first selected test will be run repeatedly until failure.")
+)
+
+// ShimConfigurations is used with the “json” package and represents a shim
+// config file.
+type ShimConfiguration struct {
+	// DisabledTests maps from a glob-based pattern to a freeform string.
+	// The glob pattern is used to exclude tests from being run and the
+	// freeform string is unparsed but expected to explain why the test is
+	// disabled.
+	DisabledTests map[string]string
+
+	// ErrorMap maps from expected error strings to the correct error
+	// string for the shim in question. For example, it might map
+	// “:NO_SHARED_CIPHER:” (a BoringSSL error string) to something
+	// like “SSL_ERROR_NO_CYPHER_OVERLAP”.
+	ErrorMap map[string]string
+
+	// HalfRTTTickets is the number of half-RTT tickets the client should
+	// expect before half-RTT data when testing 0-RTT.
+	HalfRTTTickets int
+}
+
+// Setup shimConfig defaults aligning with BoringSSL.
+var shimConfig ShimConfiguration = ShimConfiguration{
+	HalfRTTTickets: 2,
+}
+
+type testCert int
+
+const (
+	testCertRSA testCert = iota
+	testCertRSA1024
+	testCertRSAChain
+	testCertECDSAP224
+	testCertECDSAP256
+	testCertECDSAP384
+	testCertECDSAP521
 )
 
 const (
-	rsaCertificateFile   = "cert.pem"
-	ecdsaCertificateFile = "ecdsa_cert.pem"
+	rsaCertificateFile       = "cert.pem"
+	rsa1024CertificateFile   = "rsa_1024_cert.pem"
+	rsaChainCertificateFile  = "rsa_chain_cert.pem"
+	ecdsaP224CertificateFile = "ecdsa_p224_cert.pem"
+	ecdsaP256CertificateFile = "ecdsa_p256_cert.pem"
+	ecdsaP384CertificateFile = "ecdsa_p384_cert.pem"
+	ecdsaP521CertificateFile = "ecdsa_p521_cert.pem"
 )
 
 const (
 	rsaKeyFile       = "key.pem"
-	ecdsaKeyFile     = "ecdsa_key.pem"
+	rsa1024KeyFile   = "rsa_1024_key.pem"
+	rsaChainKeyFile  = "rsa_chain_key.pem"
+	ecdsaP224KeyFile = "ecdsa_p224_key.pem"
+	ecdsaP256KeyFile = "ecdsa_p256_key.pem"
+	ecdsaP384KeyFile = "ecdsa_p384_key.pem"
+	ecdsaP521KeyFile = "ecdsa_p521_key.pem"
 	channelIDKeyFile = "channel_id_key.pem"
 )
 
-var rsaCertificate, ecdsaCertificate Certificate
+var (
+	rsaCertificate       Certificate
+	rsa1024Certificate   Certificate
+	rsaChainCertificate  Certificate
+	ecdsaP224Certificate Certificate
+	ecdsaP256Certificate Certificate
+	ecdsaP384Certificate Certificate
+	ecdsaP521Certificate Certificate
+)
+
+var testCerts = []struct {
+	id                testCert
+	certFile, keyFile string
+	cert              *Certificate
+}{
+	{
+		id:       testCertRSA,
+		certFile: rsaCertificateFile,
+		keyFile:  rsaKeyFile,
+		cert:     &rsaCertificate,
+	},
+	{
+		id:       testCertRSA1024,
+		certFile: rsa1024CertificateFile,
+		keyFile:  rsa1024KeyFile,
+		cert:     &rsa1024Certificate,
+	},
+	{
+		id:       testCertRSAChain,
+		certFile: rsaChainCertificateFile,
+		keyFile:  rsaChainKeyFile,
+		cert:     &rsaChainCertificate,
+	},
+	{
+		id:       testCertECDSAP224,
+		certFile: ecdsaP224CertificateFile,
+		keyFile:  ecdsaP224KeyFile,
+		cert:     &ecdsaP224Certificate,
+	},
+	{
+		id:       testCertECDSAP256,
+		certFile: ecdsaP256CertificateFile,
+		keyFile:  ecdsaP256KeyFile,
+		cert:     &ecdsaP256Certificate,
+	},
+	{
+		id:       testCertECDSAP384,
+		certFile: ecdsaP384CertificateFile,
+		keyFile:  ecdsaP384KeyFile,
+		cert:     &ecdsaP384Certificate,
+	},
+	{
+		id:       testCertECDSAP521,
+		certFile: ecdsaP521CertificateFile,
+		keyFile:  ecdsaP521KeyFile,
+		cert:     &ecdsaP521Certificate,
+	},
+}
+
 var channelIDKey *ecdsa.PrivateKey
 var channelIDBytes []byte
 
 var testOCSPResponse = []byte{1, 2, 3, 4}
-var testSCTList = []byte{5, 6, 7, 8}
+var testSCTList = []byte{0, 6, 0, 4, 5, 6, 7, 8}
+
+var testOCSPExtension = append([]byte{byte(extensionStatusRequest) >> 8, byte(extensionStatusRequest), 0, 8, statusTypeOCSP, 0, 0, 4}, testOCSPResponse...)
+var testSCTExtension = append([]byte{byte(extensionSignedCertificateTimestamp) >> 8, byte(extensionSignedCertificateTimestamp), 0, byte(len(testSCTList))}, testSCTList...)
 
 func initCertificates() {
-	var err error
-	rsaCertificate, err = LoadX509KeyPair(path.Join(*resourceDir, rsaCertificateFile), path.Join(*resourceDir, rsaKeyFile))
-	if err != nil {
-		panic(err)
+	for i := range testCerts {
+		cert, err := LoadX509KeyPair(path.Join(*resourceDir, testCerts[i].certFile), path.Join(*resourceDir, testCerts[i].keyFile))
+		if err != nil {
+			panic(err)
+		}
+		cert.OCSPStaple = testOCSPResponse
+		cert.SignedCertificateTimestampList = testSCTList
+		*testCerts[i].cert = cert
 	}
-	rsaCertificate.OCSPStaple = testOCSPResponse
-	rsaCertificate.SignedCertificateTimestampList = testSCTList
-
-	ecdsaCertificate, err = LoadX509KeyPair(path.Join(*resourceDir, ecdsaCertificateFile), path.Join(*resourceDir, ecdsaKeyFile))
-	if err != nil {
-		panic(err)
-	}
-	ecdsaCertificate.OCSPStaple = testOCSPResponse
-	ecdsaCertificate.SignedCertificateTimestampList = testSCTList
 
 	channelIDPEMBlock, err := ioutil.ReadFile(path.Join(*resourceDir, channelIDKeyFile))
 	if err != nil {
@@ -94,16 +227,44 @@
 	writeIntPadded(channelIDBytes[32:], channelIDKey.Y)
 }
 
-var certificateOnce sync.Once
-
-func getRSACertificate() Certificate {
-	certificateOnce.Do(initCertificates)
-	return rsaCertificate
+func getRunnerCertificate(t testCert) Certificate {
+	for _, cert := range testCerts {
+		if cert.id == t {
+			return *cert.cert
+		}
+	}
+	panic("Unknown test certificate")
 }
 
-func getECDSACertificate() Certificate {
-	certificateOnce.Do(initCertificates)
-	return ecdsaCertificate
+func getShimCertificate(t testCert) string {
+	for _, cert := range testCerts {
+		if cert.id == t {
+			return cert.certFile
+		}
+	}
+	panic("Unknown test certificate")
+}
+
+func getShimKey(t testCert) string {
+	for _, cert := range testCerts {
+		if cert.id == t {
+			return cert.keyFile
+		}
+	}
+	panic("Unknown test certificate")
+}
+
+// encodeDERValues encodes a series of bytestrings in comma-separated-hex form.
+func encodeDERValues(values [][]byte) string {
+	var ret string
+	for i, v := range values {
+		if i > 0 {
+			ret += ","
+		}
+		ret += hex.EncodeToString(v)
+	}
+
+	return ret
 }
 
 type testType int
@@ -163,17 +324,17 @@
 	expectedOCSPResponse []uint8
 	// expectedSCTList, if not nil, is the expected SCT list to be received.
 	expectedSCTList []uint8
-	// expectedClientCertSignatureHash, if not zero, is the TLS id of the
-	// hash function that the client should have used when signing the
-	// handshake with a client certificate.
-	expectedClientCertSignatureHash uint8
+	// expectedPeerSignatureAlgorithm, if not zero, is the signature
+	// algorithm that the peer should have used in the handshake.
+	expectedPeerSignatureAlgorithm signatureAlgorithm
+	// expectedCurveID, if not zero, is the curve that the handshake should
+	// have used.
+	expectedCurveID CurveID
 	// messageLen is the length, in bytes, of the test message that will be
 	// sent.
 	messageLen int
 	// messageCount is the number of test messages that will be sent.
 	messageCount int
-	// digestPrefs is the list of digest preferences from the client.
-	digestPrefs string
 	// certFile is the path to the certificate to use for the server.
 	certFile string
 	// keyFile is the path to the private key to use for the server.
@@ -181,6 +342,9 @@
 	// resumeSession controls whether a second connection should be tested
 	// which attempts to resume the first session.
 	resumeSession bool
+	// resumeRenewedSession controls whether a third connection should be
+	// tested which attempts to resume the second connection's session.
+	resumeRenewedSession bool
 	// expectResumeRejected, if true, specifies that the attempted
 	// resumption must be rejected by the client. This is only valid for a
 	// serverTest.
@@ -210,6 +374,9 @@
 	// renegotiate indicates the number of times the connection should be
 	// renegotiated during the exchange.
 	renegotiate int
+	// sendHalfHelloRequest, if true, causes the server to send half a
+	// HelloRequest when the handshake completes.
+	sendHalfHelloRequest bool
 	// renegotiateCiphers is a list of ciphersuite ids that will be
 	// switched in just before renegotiation.
 	renegotiateCiphers []uint16
@@ -237,22 +404,103 @@
 	// sendWarningAlerts is the number of consecutive warning alerts to send
 	// before and after the test message.
 	sendWarningAlerts int
+	// sendKeyUpdates is the number of consecutive key updates to send
+	// before and after the test message.
+	sendKeyUpdates int
+	// keyUpdateRequest is the KeyUpdateRequest value to send in KeyUpdate messages.
+	keyUpdateRequest byte
 	// expectMessageDropped, if true, means the test message is expected to
 	// be dropped by the client rather than echoed back.
 	expectMessageDropped bool
+	// expectPeerCertificate, if not nil, is the certificate chain the peer
+	// is expected to send.
+	expectPeerCertificate *Certificate
 }
 
 var testCases []testCase
 
-func doExchange(test *testCase, config *Config, conn net.Conn, isResume bool) error {
-	var connDamage *damageAdaptor
+func writeTranscript(test *testCase, num int, data []byte) {
+	if len(data) == 0 {
+		return
+	}
+
+	protocol := "tls"
+	if test.protocol == dtls {
+		protocol = "dtls"
+	}
+
+	side := "client"
+	if test.testType == serverTest {
+		side = "server"
+	}
+
+	dir := path.Join(*transcriptDir, protocol, side)
+	if err := os.MkdirAll(dir, 0755); err != nil {
+		fmt.Fprintf(os.Stderr, "Error making %s: %s\n", dir, err)
+		return
+	}
+
+	name := fmt.Sprintf("%s-%d", test.name, num)
+	if err := ioutil.WriteFile(path.Join(dir, name), data, 0644); err != nil {
+		fmt.Fprintf(os.Stderr, "Error writing %s: %s\n", name, err)
+	}
+}
+
+// A timeoutConn implements an idle timeout on each Read and Write operation.
+type timeoutConn struct {
+	net.Conn
+	timeout time.Duration
+}
+
+func (t *timeoutConn) Read(b []byte) (int, error) {
+	if err := t.SetReadDeadline(time.Now().Add(t.timeout)); err != nil {
+		return 0, err
+	}
+	return t.Conn.Read(b)
+}
+
+func (t *timeoutConn) Write(b []byte) (int, error) {
+	if err := t.SetWriteDeadline(time.Now().Add(t.timeout)); err != nil {
+		return 0, err
+	}
+	return t.Conn.Write(b)
+}
+
+func doExchange(test *testCase, config *Config, conn net.Conn, isResume bool, num int) error {
+	if !test.noSessionCache {
+		if config.ClientSessionCache == nil {
+			config.ClientSessionCache = NewLRUClientSessionCache(1)
+		}
+		if config.ServerSessionCache == nil {
+			config.ServerSessionCache = NewLRUServerSessionCache(1)
+		}
+	}
+	if test.testType == clientTest {
+		if len(config.Certificates) == 0 {
+			config.Certificates = []Certificate{rsaCertificate}
+		}
+	} else {
+		// Supply a ServerName to ensure a constant session cache key,
+		// rather than falling back to net.Conn.RemoteAddr.
+		if len(config.ServerName) == 0 {
+			config.ServerName = "test"
+		}
+	}
+	if *fuzzer {
+		config.Bugs.NullAllCiphers = true
+	}
+	if *deterministic {
+		config.Time = func() time.Time { return time.Unix(1234, 1234) }
+	}
+
+	conn = &timeoutConn{conn, *idleTimeout}
 
 	if test.protocol == dtls {
 		config.Bugs.PacketAdaptor = newPacketAdaptor(conn)
 		conn = config.Bugs.PacketAdaptor
 	}
 
-	if *flagDebug {
+	if *flagDebug || len(*transcriptDir) != 0 {
 		local, peer := "client", "server"
 		if test.testType == clientTest {
 			local, peer = peer, local
@@ -264,9 +512,14 @@
 			peer:       peer,
 		}
 		conn = connDebug
-		defer func() {
-			connDebug.WriteTo(os.Stdout)
-		}()
+		if *flagDebug {
+			defer connDebug.WriteTo(os.Stdout)
+		}
+		if len(*transcriptDir) != 0 {
+			defer func() {
+				writeTranscript(test, num, connDebug.Transcript())
+			}()
+		}
 
 		if config.Bugs.PacketAdaptor != nil {
 			config.Bugs.PacketAdaptor.debug = connDebug
@@ -277,6 +530,7 @@
 		conn = newReplayAdaptor(conn)
 	}
 
+	var connDamage *damageAdaptor
 	if test.damageFirstWrite {
 		connDamage = newDamageAdaptor(conn)
 		conn = connDamage
@@ -363,15 +617,30 @@
 	}
 
 	if test.expectedOCSPResponse != nil && !bytes.Equal(test.expectedOCSPResponse, tlsConn.OCSPResponse()) {
-		return fmt.Errorf("OCSP Response mismatch")
+		return fmt.Errorf("OCSP Response mismatch: got %x, wanted %x", tlsConn.OCSPResponse(), test.expectedOCSPResponse)
 	}
 
 	if test.expectedSCTList != nil && !bytes.Equal(test.expectedSCTList, connState.SCTList) {
 		return fmt.Errorf("SCT list mismatch")
 	}
 
-	if expected := test.expectedClientCertSignatureHash; expected != 0 && expected != connState.ClientCertSignatureHash {
-		return fmt.Errorf("expected client to sign handshake with hash %d, but got %d", expected, connState.ClientCertSignatureHash)
+	if expected := test.expectedPeerSignatureAlgorithm; expected != 0 && expected != connState.PeerSignatureAlgorithm {
+		return fmt.Errorf("expected peer to use signature algorithm %04x, but got %04x", expected, connState.PeerSignatureAlgorithm)
+	}
+
+	if expected := test.expectedCurveID; expected != 0 && expected != connState.CurveID {
+		return fmt.Errorf("expected peer to use curve %04x, but got %04x", expected, connState.CurveID)
+	}
+
+	if test.expectPeerCertificate != nil {
+		if len(connState.PeerCertificates) != len(test.expectPeerCertificate.Certificate) {
+			return fmt.Errorf("expected peer to send %d certificates, but got %d", len(connState.PeerCertificates), len(test.expectPeerCertificate.Certificate))
+		}
+		for i, cert := range connState.PeerCertificates {
+			if !bytes.Equal(cert.Raw, test.expectPeerCertificate.Certificate[i]) {
+				return fmt.Errorf("peer certificate %d did not match", i+1)
+			}
+		}
 	}
 
 	if test.exportKeyingMaterial > 0 {
@@ -410,6 +679,12 @@
 		}
 	}
 
+	for i := 0; i < test.sendKeyUpdates; i++ {
+		if err := tlsConn.SendKeyUpdate(test.keyUpdateRequest); err != nil {
+			return err
+		}
+	}
+
 	for i := 0; i < test.sendEmptyRecords; i++ {
 		tlsConn.Write(nil)
 	}
@@ -418,6 +693,10 @@
 		tlsConn.SendAlert(alertLevelWarning, alertUnexpectedMessage)
 	}
 
+	if test.sendHalfHelloRequest {
+		tlsConn.SendHalfHelloRequest()
+	}
+
 	if test.renegotiate > 0 {
 		if test.renegotiateCiphers != nil {
 			config.CipherSuites = test.renegotiateCiphers
@@ -462,6 +741,10 @@
 		}
 		tlsConn.Write(testMessage)
 
+		for i := 0; i < test.sendKeyUpdates; i++ {
+			tlsConn.SendKeyUpdate(test.keyUpdateRequest)
+		}
+
 		for i := 0; i < test.sendEmptyRecords; i++ {
 			tlsConn.Write(nil)
 		}
@@ -504,7 +787,7 @@
 }
 
 func valgrindOf(dbAttach bool, path string, args ...string) *exec.Cmd {
-	valgrindArgs := []string{"--error-exitcode=99", "--track-origins=yes", "--leak-check=full"}
+	valgrindArgs := []string{"--error-exitcode=99", "--track-origins=yes", "--leak-check=full", "--quiet"}
 	if dbAttach {
 		valgrindArgs = append(valgrindArgs, "--db-attach=yes", "--db-command=xterm -e gdb -nw %f %p")
 	}
@@ -530,13 +813,10 @@
 	return exec.Command("xterm", xtermArgs...)
 }
 
-type moreMallocsError struct{}
-
-func (moreMallocsError) Error() string {
-	return "child process did not exhaust all allocation calls"
-}
-
-var errMoreMallocs = moreMallocsError{}
+var (
+	errMoreMallocs   = errors.New("child process did not exhaust all allocation calls")
+	errUnimplemented = errors.New("child process does not implement needed flags")
+)
 
 // accept accepts a connection from listener, unless waitChan signals a process
 // exit first.
@@ -560,7 +840,27 @@
 	}
 }
 
+func translateExpectedError(errorStr string) string {
+	if translated, ok := shimConfig.ErrorMap[errorStr]; ok {
+		return translated
+	}
+
+	if *looseErrors {
+		return ""
+	}
+
+	return errorStr
+}
+
 func runTest(test *testCase, shimPath string, mallocNumToFail int64) error {
+	// Help debugging panics on the Go side.
+	defer func() {
+		if r := recover(); r != nil {
+			fmt.Fprintf(os.Stderr, "Test '%s' panicked.\n", test.name)
+			panic(r)
+		}
+	}()
+
 	if !test.shouldFail && (len(test.expectedError) > 0 || len(test.expectedLocalError) > 0) {
 		panic("Error expected without shouldFail in " + test.name)
 	}
@@ -569,8 +869,16 @@
 		panic("expectResumeRejected without resumeSession in " + test.name)
 	}
 
-	if test.testType != clientTest && test.expectedClientCertSignatureHash != 0 {
-		panic("expectedClientCertSignatureHash non-zero with serverTest in " + test.name)
+	for _, ver := range tlsVersions {
+		if !strings.Contains("-"+test.name+"-", "-"+ver.name+"-") {
+			continue
+		}
+
+		if test.config.MaxVersion != 0 || test.config.MinVersion != 0 || test.expectedVersion != 0 {
+			continue
+		}
+
+		panic(fmt.Sprintf("The name of test %q suggests that it's version specific, but min/max version in the Config is %x/%x. One of them should probably be %x", test.name, test.config.MinVersion, test.config.MaxVersion, ver.version))
 	}
 
 	listener, err := net.ListenTCP("tcp4", &net.TCPAddr{IP: net.IP{127, 0, 0, 1}})
@@ -602,17 +910,20 @@
 		}
 	}
 
-	if test.digestPrefs != "" {
-		flags = append(flags, "-digest-prefs")
-		flags = append(flags, test.digestPrefs)
-	}
-
 	if test.protocol == dtls {
 		flags = append(flags, "-dtls")
 	}
 
+	var resumeCount int
 	if test.resumeSession {
-		flags = append(flags, "-resume")
+		resumeCount++
+		if test.resumeRenewedSession {
+			resumeCount++
+		}
+	}
+
+	if resumeCount > 0 {
+		flags = append(flags, "-resume-count", strconv.Itoa(resumeCount))
 	}
 
 	if test.shimWritesFirst {
@@ -671,55 +982,34 @@
 	go func() { waitChan <- shim.Wait() }()
 
 	config := test.config
-	if !test.noSessionCache {
-		config.ClientSessionCache = NewLRUClientSessionCache(1)
-		config.ServerSessionCache = NewLRUServerSessionCache(1)
-	}
-	if test.testType == clientTest {
-		if len(config.Certificates) == 0 {
-			config.Certificates = []Certificate{getRSACertificate()}
-		}
-	} else {
-		// Supply a ServerName to ensure a constant session cache key,
-		// rather than falling back to net.Conn.RemoteAddr.
-		if len(config.ServerName) == 0 {
-			config.ServerName = "test"
-		}
+
+	if *deterministic {
+		config.Rand = &deterministicRand{}
 	}
 
 	conn, err := acceptOrWait(listener, waitChan)
 	if err == nil {
-		err = doExchange(test, &config, conn, false /* not a resumption */)
+		err = doExchange(test, &config, conn, false /* not a resumption */, 0)
 		conn.Close()
 	}
 
-	if err == nil && test.resumeSession {
+	for i := 0; err == nil && i < resumeCount; i++ {
 		var resumeConfig Config
 		if test.resumeConfig != nil {
 			resumeConfig = *test.resumeConfig
-			if len(resumeConfig.ServerName) == 0 {
-				resumeConfig.ServerName = config.ServerName
-			}
-			if len(resumeConfig.Certificates) == 0 {
-				resumeConfig.Certificates = []Certificate{getRSACertificate()}
-			}
-			if test.newSessionsOnResume {
-				if !test.noSessionCache {
-					resumeConfig.ClientSessionCache = NewLRUClientSessionCache(1)
-					resumeConfig.ServerSessionCache = NewLRUServerSessionCache(1)
-				}
-			} else {
+			if !test.newSessionsOnResume {
 				resumeConfig.SessionTicketKey = config.SessionTicketKey
 				resumeConfig.ClientSessionCache = config.ClientSessionCache
 				resumeConfig.ServerSessionCache = config.ServerSessionCache
 			}
+			resumeConfig.Rand = config.Rand
 		} else {
 			resumeConfig = config
 		}
 		var connResume net.Conn
 		connResume, err = acceptOrWait(listener, waitChan)
 		if err == nil {
-			err = doExchange(test, &resumeConfig, connResume, true /* resumption */)
+			err = doExchange(test, &resumeConfig, connResume, true /* resumption */, i+1)
 			connResume.Close()
 		}
 	}
@@ -730,16 +1020,34 @@
 	listener = nil
 
 	childErr := <-waitChan
+	var isValgrindError bool
 	if exitError, ok := childErr.(*exec.ExitError); ok {
-		if exitError.Sys().(syscall.WaitStatus).ExitStatus() == 88 {
+		switch exitError.Sys().(syscall.WaitStatus).ExitStatus() {
+		case 88:
 			return errMoreMallocs
+		case 89:
+			return errUnimplemented
+		case 99:
+			isValgrindError = true
 		}
 	}
 
-	stdout := string(stdoutBuf.Bytes())
-	stderr := string(stderrBuf.Bytes())
+	// Account for Windows line endings.
+	stdout := strings.Replace(string(stdoutBuf.Bytes()), "\r\n", "\n", -1)
+	stderr := strings.Replace(string(stderrBuf.Bytes()), "\r\n", "\n", -1)
+
+	// Separate the errors from the shim and those from tools like
+	// AddressSanitizer.
+	var extraStderr string
+	if stderrParts := strings.SplitN(stderr, "--- DONE ---\n", 2); len(stderrParts) == 2 {
+		stderr = stderrParts[0]
+		extraStderr = stderrParts[1]
+	}
+
 	failed := err != nil || childErr != nil
-	correctFailure := len(test.expectedError) == 0 || strings.Contains(stderr, test.expectedError)
+	expectedError := translateExpectedError(test.expectedError)
+	correctFailure := len(expectedError) == 0 || strings.Contains(stderr, expectedError)
+
 	localError := "none"
 	if err != nil {
 		localError = err.Error()
@@ -761,37 +1069,46 @@
 		case !failed && test.shouldFail:
 			msg = "unexpected success"
 		case failed && !correctFailure:
-			msg = "bad error (wanted '" + test.expectedError + "' / '" + test.expectedLocalError + "')"
+			msg = "bad error (wanted '" + expectedError + "' / '" + test.expectedLocalError + "')"
 		default:
 			panic("internal error")
 		}
 
-		return fmt.Errorf("%s: local error '%s', child error '%s', stdout:\n%s\nstderr:\n%s", msg, localError, childError, stdout, stderr)
+		return fmt.Errorf("%s: local error '%s', child error '%s', stdout:\n%s\nstderr:\n%s\n%s", msg, localError, childError, stdout, stderr, extraStderr)
 	}
 
-	if !*useValgrind && !failed && len(stderr) > 0 {
-		println(stderr)
+	if len(extraStderr) > 0 || (!failed && len(stderr) > 0) {
+		return fmt.Errorf("unexpected error output:\n%s\n%s", stderr, extraStderr)
+	}
+
+	if *useValgrind && isValgrindError {
+		return fmt.Errorf("valgrind error:\n%s\n%s", stderr, extraStderr)
 	}
 
 	return nil
 }
 
-var tlsVersions = []struct {
+type tlsVersion struct {
 	name    string
 	version uint16
 	flag    string
 	hasDTLS bool
-}{
+}
+
+var tlsVersions = []tlsVersion{
 	{"SSL3", VersionSSL30, "-no-ssl3", false},
 	{"TLS1", VersionTLS10, "-no-tls1", true},
 	{"TLS11", VersionTLS11, "-no-tls11", false},
 	{"TLS12", VersionTLS12, "-no-tls12", true},
+	{"TLS13", VersionTLS13, "-no-tls13", false},
 }
 
-var testCipherSuites = []struct {
+type testCipherSuite struct {
 	name string
 	id   uint16
-}{
+}
+
+var testCipherSuites = []testCipherSuite{
 	{"3DES-SHA", TLS_RSA_WITH_3DES_EDE_CBC_SHA},
 	{"AES128-GCM", TLS_RSA_WITH_AES_128_GCM_SHA256},
 	{"AES128-SHA", TLS_RSA_WITH_AES_128_CBC_SHA},
@@ -799,12 +1116,6 @@
 	{"AES256-GCM", TLS_RSA_WITH_AES_256_GCM_SHA384},
 	{"AES256-SHA", TLS_RSA_WITH_AES_256_CBC_SHA},
 	{"AES256-SHA256", TLS_RSA_WITH_AES_256_CBC_SHA256},
-	{"DHE-RSA-AES128-GCM", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
-	{"DHE-RSA-AES128-SHA", TLS_DHE_RSA_WITH_AES_128_CBC_SHA},
-	{"DHE-RSA-AES128-SHA256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256},
-	{"DHE-RSA-AES256-GCM", TLS_DHE_RSA_WITH_AES_256_GCM_SHA384},
-	{"DHE-RSA-AES256-SHA", TLS_DHE_RSA_WITH_AES_256_CBC_SHA},
-	{"DHE-RSA-AES256-SHA256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256},
 	{"ECDHE-ECDSA-AES128-GCM", TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
 	{"ECDHE-ECDSA-AES128-SHA", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA},
 	{"ECDHE-ECDSA-AES128-SHA256", TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256},
@@ -812,8 +1123,6 @@
 	{"ECDHE-ECDSA-AES256-SHA", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA},
 	{"ECDHE-ECDSA-AES256-SHA384", TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384},
 	{"ECDHE-ECDSA-CHACHA20-POLY1305", TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256},
-	{"ECDHE-ECDSA-CHACHA20-POLY1305-OLD", TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256_OLD},
-	{"ECDHE-ECDSA-RC4-SHA", TLS_ECDHE_ECDSA_WITH_RC4_128_SHA},
 	{"ECDHE-RSA-AES128-GCM", TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
 	{"ECDHE-RSA-AES128-SHA", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
 	{"ECDHE-RSA-AES128-SHA256", TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256},
@@ -821,16 +1130,14 @@
 	{"ECDHE-RSA-AES256-SHA", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA},
 	{"ECDHE-RSA-AES256-SHA384", TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384},
 	{"ECDHE-RSA-CHACHA20-POLY1305", TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
-	{"ECDHE-RSA-CHACHA20-POLY1305-OLD", TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256_OLD},
-	{"ECDHE-RSA-RC4-SHA", TLS_ECDHE_RSA_WITH_RC4_128_SHA},
 	{"PSK-AES128-CBC-SHA", TLS_PSK_WITH_AES_128_CBC_SHA},
 	{"PSK-AES256-CBC-SHA", TLS_PSK_WITH_AES_256_CBC_SHA},
 	{"ECDHE-PSK-AES128-CBC-SHA", TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
 	{"ECDHE-PSK-AES256-CBC-SHA", TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA},
 	{"ECDHE-PSK-CHACHA20-POLY1305", TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256},
-	{"PSK-RC4-SHA", TLS_PSK_WITH_RC4_128_SHA},
-	{"RC4-MD5", TLS_RSA_WITH_RC4_128_MD5},
-	{"RC4-SHA", TLS_RSA_WITH_RC4_128_SHA},
+	{"AEAD-CHACHA20-POLY1305", TLS_CHACHA20_POLY1305_SHA256},
+	{"AEAD-AES128-GCM-SHA256", TLS_AES_128_GCM_SHA256},
+	{"AEAD-AES256-GCM-SHA384", TLS_AES_256_GCM_SHA384},
 	{"NULL-SHA", TLS_RSA_WITH_NULL_SHA},
 }
 
@@ -838,12 +1145,6 @@
 	return strings.Contains("-"+suiteName+"-", "-"+component+"-")
 }
 
-func isTLSOnly(suiteName string) bool {
-	// BoringSSL doesn't support ECDHE without a curves extension, and
-	// SSLv3 doesn't contain extensions.
-	return hasComponent(suiteName, "ECDHE") || isTLS12Only(suiteName)
-}
-
 func isTLS12Only(suiteName string) bool {
 	return hasComponent(suiteName, "GCM") ||
 		hasComponent(suiteName, "SHA256") ||
@@ -851,6 +1152,10 @@
 		hasComponent(suiteName, "POLY1305")
 }
 
+func isTLS13Suite(suiteName string) bool {
+	return strings.HasPrefix(suiteName, "AEAD-")
+}
+
 func isDTLSCipher(suiteName string) bool {
 	return !hasComponent(suiteName, "RC4") && !hasComponent(suiteName, "NULL")
 }
@@ -866,67 +1171,6 @@
 func addBasicTests() {
 	basicTests := []testCase{
 		{
-			name: "BadRSASignature",
-			config: Config{
-				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-				Bugs: ProtocolBugs{
-					InvalidSKXSignature: true,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":BAD_SIGNATURE:",
-		},
-		{
-			name: "BadECDSASignature",
-			config: Config{
-				CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
-				Bugs: ProtocolBugs{
-					InvalidSKXSignature: true,
-				},
-				Certificates: []Certificate{getECDSACertificate()},
-			},
-			shouldFail:    true,
-			expectedError: ":BAD_SIGNATURE:",
-		},
-		{
-			testType: serverTest,
-			name:     "BadRSASignature-ClientAuth",
-			config: Config{
-				Bugs: ProtocolBugs{
-					InvalidCertVerifySignature: true,
-				},
-				Certificates: []Certificate{getRSACertificate()},
-			},
-			shouldFail:    true,
-			expectedError: ":BAD_SIGNATURE:",
-			flags:         []string{"-require-any-client-certificate"},
-		},
-		{
-			testType: serverTest,
-			name:     "BadECDSASignature-ClientAuth",
-			config: Config{
-				Bugs: ProtocolBugs{
-					InvalidCertVerifySignature: true,
-				},
-				Certificates: []Certificate{getECDSACertificate()},
-			},
-			shouldFail:    true,
-			expectedError: ":BAD_SIGNATURE:",
-			flags:         []string{"-require-any-client-certificate"},
-		},
-		{
-			name: "BadECDSACurve",
-			config: Config{
-				CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
-				Bugs: ProtocolBugs{
-					InvalidSKXCurve: true,
-				},
-				Certificates: []Certificate{getECDSACertificate()},
-			},
-			shouldFail:    true,
-			expectedError: ":WRONG_CURVE:",
-		},
-		{
 			name: "NoFallbackSCSV",
 			config: Config{
 				Bugs: ProtocolBugs{
@@ -948,6 +1192,7 @@
 		{
 			name: "ClientCertificateTypes",
 			config: Config{
+				MaxVersion: VersionTLS12,
 				ClientAuth: RequestClientCert,
 				ClientCertificateTypes: []byte{
 					CertTypeDSSSign,
@@ -965,16 +1210,9 @@
 			},
 		},
 		{
-			name: "NoClientCertificate",
-			config: Config{
-				ClientAuth: RequireAnyClientCert,
-			},
-			shouldFail:         true,
-			expectedLocalError: "client didn't provide a certificate",
-		},
-		{
 			name: "UnauthenticatedECDH",
 			config: Config{
+				MaxVersion:   VersionTLS12,
 				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
 				Bugs: ProtocolBugs{
 					UnauthenticatedECDH: true,
@@ -986,6 +1224,7 @@
 		{
 			name: "SkipCertificateStatus",
 			config: Config{
+				MaxVersion:   VersionTLS12,
 				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
 				Bugs: ProtocolBugs{
 					SkipCertificateStatus: true,
@@ -998,6 +1237,7 @@
 		{
 			name: "SkipServerKeyExchange",
 			config: Config{
+				MaxVersion:   VersionTLS12,
 				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
 				Bugs: ProtocolBugs{
 					SkipServerKeyExchange: true,
@@ -1007,78 +1247,6 @@
 			expectedError: ":UNEXPECTED_MESSAGE:",
 		},
 		{
-			name: "SkipChangeCipherSpec-Client",
-			config: Config{
-				Bugs: ProtocolBugs{
-					SkipChangeCipherSpec: true,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":UNEXPECTED_RECORD:",
-		},
-		{
-			testType: serverTest,
-			name:     "SkipChangeCipherSpec-Server",
-			config: Config{
-				Bugs: ProtocolBugs{
-					SkipChangeCipherSpec: true,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":UNEXPECTED_RECORD:",
-		},
-		{
-			testType: serverTest,
-			name:     "SkipChangeCipherSpec-Server-NPN",
-			config: Config{
-				NextProtos: []string{"bar"},
-				Bugs: ProtocolBugs{
-					SkipChangeCipherSpec: true,
-				},
-			},
-			flags: []string{
-				"-advertise-npn", "\x03foo\x03bar\x03baz",
-			},
-			shouldFail:    true,
-			expectedError: ":UNEXPECTED_RECORD:",
-		},
-		{
-			name: "FragmentAcrossChangeCipherSpec-Client",
-			config: Config{
-				Bugs: ProtocolBugs{
-					FragmentAcrossChangeCipherSpec: true,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":UNEXPECTED_RECORD:",
-		},
-		{
-			testType: serverTest,
-			name:     "FragmentAcrossChangeCipherSpec-Server",
-			config: Config{
-				Bugs: ProtocolBugs{
-					FragmentAcrossChangeCipherSpec: true,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":UNEXPECTED_RECORD:",
-		},
-		{
-			testType: serverTest,
-			name:     "FragmentAcrossChangeCipherSpec-Server-NPN",
-			config: Config{
-				NextProtos: []string{"bar"},
-				Bugs: ProtocolBugs{
-					FragmentAcrossChangeCipherSpec: true,
-				},
-			},
-			flags: []string{
-				"-advertise-npn", "\x03foo\x03bar\x03baz",
-			},
-			shouldFail:    true,
-			expectedError: ":UNEXPECTED_RECORD:",
-		},
-		{
 			testType: serverTest,
 			name:     "Alert",
 			config: Config{
@@ -1128,29 +1296,33 @@
 		},
 		{
 			testType: serverTest,
-			name:     "EarlyChangeCipherSpec-server-1",
+			name:     "DoubleAlert",
 			config: Config{
 				Bugs: ProtocolBugs{
-					EarlyChangeCipherSpec: 1,
+					DoubleAlert:       true,
+					SendSpuriousAlert: alertRecordOverflow,
 				},
 			},
 			shouldFail:    true,
-			expectedError: ":UNEXPECTED_RECORD:",
+			expectedError: ":BAD_ALERT:",
 		},
 		{
+			protocol: dtls,
 			testType: serverTest,
-			name:     "EarlyChangeCipherSpec-server-2",
+			name:     "DoubleAlert-DTLS",
 			config: Config{
 				Bugs: ProtocolBugs{
-					EarlyChangeCipherSpec: 2,
+					DoubleAlert:       true,
+					SendSpuriousAlert: alertRecordOverflow,
 				},
 			},
 			shouldFail:    true,
-			expectedError: ":UNEXPECTED_RECORD:",
+			expectedError: ":BAD_ALERT:",
 		},
 		{
 			name: "SkipNewSessionTicket",
 			config: Config{
+				MaxVersion: VersionTLS12,
 				Bugs: ProtocolBugs{
 					SkipNewSessionTicket: true,
 				},
@@ -1167,13 +1339,15 @@
 					SendFallbackSCSV: true,
 				},
 			},
-			shouldFail:    true,
-			expectedError: ":INAPPROPRIATE_FALLBACK:",
+			shouldFail:         true,
+			expectedError:      ":INAPPROPRIATE_FALLBACK:",
+			expectedLocalError: "remote error: inappropriate fallback",
 		},
 		{
 			testType: serverTest,
-			name:     "FallbackSCSV-VersionMatch",
+			name:     "FallbackSCSV-VersionMatch-TLS13",
 			config: Config{
+				MaxVersion: VersionTLS13,
 				Bugs: ProtocolBugs{
 					SendFallbackSCSV: true,
 				},
@@ -1181,6 +1355,17 @@
 		},
 		{
 			testType: serverTest,
+			name:     "FallbackSCSV-VersionMatch-TLS12",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					SendFallbackSCSV: true,
+				},
+			},
+			flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
+		},
+		{
+			testType: serverTest,
 			name:     "FragmentedClientVersion",
 			config: Config{
 				Bugs: ProtocolBugs{
@@ -1188,38 +1373,7 @@
 					FragmentClientVersion:    true,
 				},
 			},
-			expectedVersion: VersionTLS12,
-		},
-		{
-			testType: serverTest,
-			name:     "MinorVersionTolerance",
-			config: Config{
-				Bugs: ProtocolBugs{
-					SendClientVersion: 0x03ff,
-				},
-			},
-			expectedVersion: VersionTLS12,
-		},
-		{
-			testType: serverTest,
-			name:     "MajorVersionTolerance",
-			config: Config{
-				Bugs: ProtocolBugs{
-					SendClientVersion: 0x0400,
-				},
-			},
-			expectedVersion: VersionTLS12,
-		},
-		{
-			testType: serverTest,
-			name:     "VersionTooLow",
-			config: Config{
-				Bugs: ProtocolBugs{
-					SendClientVersion: 0x0200,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":UNSUPPORTED_PROTOCOL:",
+			expectedVersion: VersionTLS13,
 		},
 		{
 			testType:      serverTest,
@@ -1264,20 +1418,9 @@
 			expectedError: ":WRONG_VERSION_NUMBER:",
 		},
 		{
-			name: "SkipCipherVersionCheck",
-			config: Config{
-				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
-				MaxVersion:   VersionTLS11,
-				Bugs: ProtocolBugs{
-					SkipCipherVersionCheck: true,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":WRONG_CIPHER_RETURNED:",
-		},
-		{
 			name: "RSAEphemeralKey",
 			config: Config{
+				MaxVersion:   VersionTLS12,
 				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
 				Bugs: ProtocolBugs{
 					RSAEphemeralKey: true,
@@ -1288,7 +1431,7 @@
 		},
 		{
 			name:          "DisableEverything",
-			flags:         []string{"-no-tls12", "-no-tls11", "-no-tls1", "-no-ssl3"},
+			flags:         []string{"-no-tls13", "-no-tls12", "-no-tls11", "-no-tls1", "-no-ssl3"},
 			shouldFail:    true,
 			expectedError: ":WRONG_SSL_VERSION:",
 		},
@@ -1300,14 +1443,6 @@
 			expectedError: ":WRONG_SSL_VERSION:",
 		},
 		{
-			name: "NoSharedCipher",
-			config: Config{
-				CipherSuites: []uint16{},
-			},
-			shouldFail:    true,
-			expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:",
-		},
-		{
 			protocol: dtls,
 			testType: serverTest,
 			name:     "MTU",
@@ -1334,8 +1469,9 @@
 		{
 			name: "CertMismatchRSA",
 			config: Config{
+				MaxVersion:   VersionTLS12,
 				CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
-				Certificates: []Certificate{getECDSACertificate()},
+				Certificates: []Certificate{ecdsaP256Certificate},
 				Bugs: ProtocolBugs{
 					SendCipherSuite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
 				},
@@ -1346,8 +1482,9 @@
 		{
 			name: "CertMismatchECDSA",
 			config: Config{
+				MaxVersion:   VersionTLS12,
 				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-				Certificates: []Certificate{getRSACertificate()},
+				Certificates: []Certificate{rsaCertificate},
 				Bugs: ProtocolBugs{
 					SendCipherSuite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
 				},
@@ -1358,7 +1495,7 @@
 		{
 			name: "EmptyCertificateList",
 			config: Config{
-				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+				MaxVersion: VersionTLS12,
 				Bugs: ProtocolBugs{
 					EmptyCertificateList: true,
 				},
@@ -1367,6 +1504,17 @@
 			expectedError: ":DECODE_ERROR:",
 		},
 		{
+			name: "EmptyCertificateList-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					EmptyCertificateList: true,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
+		},
+		{
 			name:             "TLSFatalBadPackets",
 			damageFirstWrite: true,
 			shouldFail:       true,
@@ -1428,6 +1576,7 @@
 		{
 			name: "AppDataAfterChangeCipherSpec",
 			config: Config{
+				MaxVersion: VersionTLS12,
 				Bugs: ProtocolBugs{
 					AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
 				},
@@ -1438,6 +1587,7 @@
 		{
 			name: "AppDataAfterChangeCipherSpec-Empty",
 			config: Config{
+				MaxVersion: VersionTLS12,
 				Bugs: ProtocolBugs{
 					AppDataAfterChangeCipherSpec: []byte{},
 				},
@@ -1449,6 +1599,7 @@
 			protocol: dtls,
 			name:     "AppDataAfterChangeCipherSpec-DTLS",
 			config: Config{
+				MaxVersion: VersionTLS12,
 				Bugs: ProtocolBugs{
 					AppDataAfterChangeCipherSpec: []byte("TEST MESSAGE"),
 				},
@@ -1460,6 +1611,7 @@
 			protocol: dtls,
 			name:     "AppDataAfterChangeCipherSpec-DTLS-Empty",
 			config: Config{
+				MaxVersion: VersionTLS12,
 				Bugs: ProtocolBugs{
 					AppDataAfterChangeCipherSpec: []byte{},
 				},
@@ -1470,6 +1622,7 @@
 		{
 			name: "AlertAfterChangeCipherSpec",
 			config: Config{
+				MaxVersion: VersionTLS12,
 				Bugs: ProtocolBugs{
 					AlertAfterChangeCipherSpec: alertRecordOverflow,
 				},
@@ -1481,6 +1634,7 @@
 			protocol: dtls,
 			name:     "AlertAfterChangeCipherSpec-DTLS",
 			config: Config{
+				MaxVersion: VersionTLS12,
 				Bugs: ProtocolBugs{
 					AlertAfterChangeCipherSpec: alertRecordOverflow,
 				},
@@ -1547,6 +1701,7 @@
 		{
 			name: "FalseStart-SkipServerSecondLeg",
 			config: Config{
+				MaxVersion:   VersionTLS12,
 				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
 				NextProtos:   []string{"foo"},
 				Bugs: ProtocolBugs{
@@ -1568,6 +1723,7 @@
 		{
 			name: "FalseStart-SkipServerSecondLeg-Implicit",
 			config: Config{
+				MaxVersion:   VersionTLS12,
 				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
 				NextProtos:   []string{"foo"},
 				Bugs: ProtocolBugs{
@@ -1591,30 +1747,51 @@
 			flags:              []string{"-fail-early-callback"},
 			shouldFail:         true,
 			expectedError:      ":CONNECTION_REJECTED:",
-			expectedLocalError: "remote error: access denied",
+			expectedLocalError: "remote error: handshake failure",
 		},
 		{
-			name: "WrongMessageType",
+			name: "FailCertCallback-Client-TLS12",
 			config: Config{
-				Bugs: ProtocolBugs{
-					WrongCertificateMessageType: true,
-				},
+				MaxVersion: VersionTLS12,
+				ClientAuth: RequestClientCert,
 			},
+			flags:              []string{"-fail-cert-callback"},
 			shouldFail:         true,
-			expectedError:      ":UNEXPECTED_MESSAGE:",
-			expectedLocalError: "remote error: unexpected message",
+			expectedError:      ":CERT_CB_ERROR:",
+			expectedLocalError: "remote error: internal error",
 		},
 		{
-			protocol: dtls,
-			name:     "WrongMessageType-DTLS",
+			testType: serverTest,
+			name:     "FailCertCallback-Server-TLS12",
 			config: Config{
-				Bugs: ProtocolBugs{
-					WrongCertificateMessageType: true,
-				},
+				MaxVersion: VersionTLS12,
 			},
+			flags:              []string{"-fail-cert-callback"},
 			shouldFail:         true,
-			expectedError:      ":UNEXPECTED_MESSAGE:",
-			expectedLocalError: "remote error: unexpected message",
+			expectedError:      ":CERT_CB_ERROR:",
+			expectedLocalError: "remote error: internal error",
+		},
+		{
+			name: "FailCertCallback-Client-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				ClientAuth: RequestClientCert,
+			},
+			flags:              []string{"-fail-cert-callback"},
+			shouldFail:         true,
+			expectedError:      ":CERT_CB_ERROR:",
+			expectedLocalError: "remote error: internal error",
+		},
+		{
+			testType: serverTest,
+			name:     "FailCertCallback-Server-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
+			},
+			flags:              []string{"-fail-cert-callback"},
+			shouldFail:         true,
+			expectedError:      ":CERT_CB_ERROR:",
+			expectedLocalError: "remote error: internal error",
 		},
 		{
 			protocol: dtls,
@@ -1649,7 +1826,7 @@
 				},
 			},
 			shouldFail:    true,
-			expectedError: ":UNEXPECTED_MESSAGE:",
+			expectedError: ":BAD_HANDSHAKE_RECORD:",
 		},
 		{
 			protocol: dtls,
@@ -1660,7 +1837,7 @@
 				},
 			},
 			shouldFail:    true,
-			expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
+			expectedError: ":BAD_HANDSHAKE_RECORD:",
 		},
 		{
 			protocol: dtls,
@@ -1671,7 +1848,7 @@
 				},
 			},
 			shouldFail:    true,
-			expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
+			expectedError: ":BAD_HANDSHAKE_RECORD:",
 		},
 		{
 			protocol: dtls,
@@ -1683,33 +1860,44 @@
 			},
 		},
 		{
-			name: "UnsupportedCipherSuite",
+			name: "BadFinished-Client",
 			config: Config{
-				CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
+				MaxVersion: VersionTLS12,
 				Bugs: ProtocolBugs{
-					IgnorePeerCipherPreferences: true,
+					BadFinished: true,
 				},
 			},
-			flags:         []string{"-cipher", "DEFAULT:!RC4"},
 			shouldFail:    true,
-			expectedError: ":WRONG_CIPHER_RETURNED:",
+			expectedError: ":DIGEST_CHECK_FAILED:",
 		},
 		{
-			name: "UnsupportedCurve",
+			name: "BadFinished-Client-TLS13",
 			config: Config{
-				CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-				CurvePreferences: []CurveID{CurveP256},
+				MaxVersion: VersionTLS13,
 				Bugs: ProtocolBugs{
-					IgnorePeerCurvePreferences: true,
+					BadFinished: true,
 				},
 			},
-			flags:         []string{"-p384-only"},
 			shouldFail:    true,
-			expectedError: ":WRONG_CURVE:",
+			expectedError: ":DIGEST_CHECK_FAILED:",
 		},
 		{
-			name: "BadFinished",
+			testType: serverTest,
+			name:     "BadFinished-Server",
 			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					BadFinished: true,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":DIGEST_CHECK_FAILED:",
+		},
+		{
+			testType: serverTest,
+			name:     "BadFinished-Server-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
 				Bugs: ProtocolBugs{
 					BadFinished: true,
 				},
@@ -1720,6 +1908,7 @@
 		{
 			name: "FalseStart-BadFinished",
 			config: Config{
+				MaxVersion:   VersionTLS12,
 				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
 				NextProtos:   []string{"foo"},
 				Bugs: ProtocolBugs{
@@ -1739,6 +1928,7 @@
 		{
 			name: "NoFalseStart-NoALPN",
 			config: Config{
+				MaxVersion:   VersionTLS12,
 				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
 				Bugs: ProtocolBugs{
 					ExpectFalseStart:          true,
@@ -1756,6 +1946,7 @@
 		{
 			name: "NoFalseStart-NoAEAD",
 			config: Config{
+				MaxVersion:   VersionTLS12,
 				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
 				NextProtos:   []string{"foo"},
 				Bugs: ProtocolBugs{
@@ -1775,6 +1966,7 @@
 		{
 			name: "NoFalseStart-RSA",
 			config: Config{
+				MaxVersion:   VersionTLS12,
 				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
 				NextProtos:   []string{"foo"},
 				Bugs: ProtocolBugs{
@@ -1792,49 +1984,6 @@
 			expectedLocalError: "tls: peer did not false start: EOF",
 		},
 		{
-			name: "NoFalseStart-DHE_RSA",
-			config: Config{
-				CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
-				NextProtos:   []string{"foo"},
-				Bugs: ProtocolBugs{
-					ExpectFalseStart:          true,
-					AlertBeforeFalseStartTest: alertAccessDenied,
-				},
-			},
-			flags: []string{
-				"-false-start",
-				"-advertise-alpn", "\x03foo",
-			},
-			shimWritesFirst:    true,
-			shouldFail:         true,
-			expectedError:      ":TLSV1_ALERT_ACCESS_DENIED:",
-			expectedLocalError: "tls: peer did not false start: EOF",
-		},
-		{
-			testType: serverTest,
-			name:     "NoSupportedCurves",
-			config: Config{
-				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-				Bugs: ProtocolBugs{
-					NoSupportedCurves: true,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":NO_SHARED_CIPHER:",
-		},
-		{
-			testType: serverTest,
-			name:     "NoCommonCurves",
-			config: Config{
-				CipherSuites: []uint16{
-					TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
-					TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
-				},
-				CurvePreferences: []CurveID{CurveP224},
-			},
-			expectedCipher: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
-		},
-		{
 			protocol: dtls,
 			name:     "SendSplitAlert-Sync",
 			config: Config{
@@ -1865,19 +2014,6 @@
 			},
 		},
 		{
-			testType: serverTest,
-			protocol: dtls,
-			name:     "NoRC4-DTLS",
-			config: Config{
-				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_RC4_128_SHA},
-				Bugs: ProtocolBugs{
-					EnableAllCiphersInDTLS: true,
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":NO_SHARED_CIPHER:",
-		},
-		{
 			name:             "SendEmptyRecords-Pass",
 			sendEmptyRecords: 32,
 		},
@@ -1895,30 +2031,63 @@
 			expectedError:    ":TOO_MANY_EMPTY_FRAGMENTS:",
 		},
 		{
-			name:              "SendWarningAlerts-Pass",
+			name: "SendWarningAlerts-Pass",
+			config: Config{
+				MaxVersion: VersionTLS12,
+			},
 			sendWarningAlerts: 4,
 		},
 		{
-			protocol:          dtls,
-			name:              "SendWarningAlerts-DTLS-Pass",
+			protocol: dtls,
+			name:     "SendWarningAlerts-DTLS-Pass",
+			config: Config{
+				MaxVersion: VersionTLS12,
+			},
 			sendWarningAlerts: 4,
 		},
 		{
-			name:              "SendWarningAlerts",
+			name: "SendWarningAlerts-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
+			},
+			sendWarningAlerts:  4,
+			shouldFail:         true,
+			expectedError:      ":BAD_ALERT:",
+			expectedLocalError: "remote error: error decoding message",
+		},
+		{
+			name: "SendWarningAlerts",
+			config: Config{
+				MaxVersion: VersionTLS12,
+			},
 			sendWarningAlerts: 5,
 			shouldFail:        true,
 			expectedError:     ":TOO_MANY_WARNING_ALERTS:",
 		},
 		{
-			name:              "SendWarningAlerts-Async",
+			name: "SendWarningAlerts-Async",
+			config: Config{
+				MaxVersion: VersionTLS12,
+			},
 			sendWarningAlerts: 5,
 			flags:             []string{"-async"},
 			shouldFail:        true,
 			expectedError:     ":TOO_MANY_WARNING_ALERTS:",
 		},
 		{
+			name: "TooManyKeyUpdates",
+			config: Config{
+				MaxVersion: VersionTLS13,
+			},
+			sendKeyUpdates:   33,
+			keyUpdateRequest: keyUpdateNotRequested,
+			shouldFail:       true,
+			expectedError:    ":TOO_MANY_KEY_UPDATES:",
+		},
+		{
 			name: "EmptySessionID",
 			config: Config{
+				MaxVersion:             VersionTLS12,
 				SessionTicketsDisabled: true,
 			},
 			noSessionCache: true,
@@ -1947,6 +2116,19 @@
 			shimShutsDown: true,
 		},
 		{
+			name: "Unclean-Shutdown-Alert",
+			config: Config{
+				Bugs: ProtocolBugs{
+					SendAlertOnShutdown: alertDecompressionFailure,
+					ExpectCloseNotify:   true,
+				},
+			},
+			shimShutsDown: true,
+			flags:         []string{"-check-close-notify"},
+			shouldFail:    true,
+			expectedError: ":SSLV3_ALERT_DECOMPRESSION_FAILURE:",
+		},
+		{
 			name: "LargePlaintext",
 			config: Config{
 				Bugs: ProtocolBugs{
@@ -1995,73 +2177,10 @@
 			expectMessageDropped: true,
 		},
 		{
-			name: "SendEmptySessionTicket",
-			config: Config{
-				Bugs: ProtocolBugs{
-					SendEmptySessionTicket: true,
-					FailIfSessionOffered:   true,
-				},
-			},
-			flags:                []string{"-expect-no-session"},
-			resumeSession:        true,
-			expectResumeRejected: true,
-		},
-		{
-			name: "CheckLeafCurve",
-			config: Config{
-				CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
-				Certificates: []Certificate{getECDSACertificate()},
-			},
-			flags:         []string{"-p384-only"},
-			shouldFail:    true,
-			expectedError: ":BAD_ECC_CERT:",
-		},
-		{
-			name: "BadChangeCipherSpec-1",
-			config: Config{
-				Bugs: ProtocolBugs{
-					BadChangeCipherSpec: []byte{2},
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
-		},
-		{
-			name: "BadChangeCipherSpec-2",
-			config: Config{
-				Bugs: ProtocolBugs{
-					BadChangeCipherSpec: []byte{1, 1},
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
-		},
-		{
-			protocol: dtls,
-			name:     "BadChangeCipherSpec-DTLS-1",
-			config: Config{
-				Bugs: ProtocolBugs{
-					BadChangeCipherSpec: []byte{2},
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
-		},
-		{
-			protocol: dtls,
-			name:     "BadChangeCipherSpec-DTLS-2",
-			config: Config{
-				Bugs: ProtocolBugs{
-					BadChangeCipherSpec: []byte{1, 1},
-				},
-			},
-			shouldFail:    true,
-			expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
-		},
-		{
 			name:        "BadHelloRequest-1",
 			renegotiate: 1,
 			config: Config{
+				MaxVersion: VersionTLS12,
 				Bugs: ProtocolBugs{
 					BadHelloRequest: []byte{typeHelloRequest, 0, 0, 1, 1},
 				},
@@ -2071,12 +2190,13 @@
 				"-expect-total-renegotiations", "1",
 			},
 			shouldFail:    true,
-			expectedError: ":BAD_HELLO_REQUEST:",
+			expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
 		},
 		{
 			name:        "BadHelloRequest-2",
 			renegotiate: 1,
 			config: Config{
+				MaxVersion: VersionTLS12,
 				Bugs: ProtocolBugs{
 					BadHelloRequest: []byte{typeServerKeyExchange, 0, 0, 0},
 				},
@@ -2088,285 +2208,665 @@
 			shouldFail:    true,
 			expectedError: ":BAD_HELLO_REQUEST:",
 		},
+		{
+			testType: serverTest,
+			name:     "SupportTicketsWithSessionID",
+			config: Config{
+				MaxVersion:             VersionTLS12,
+				SessionTicketsDisabled: true,
+			},
+			resumeConfig: &Config{
+				MaxVersion: VersionTLS12,
+			},
+			resumeSession: true,
+		},
+		{
+			protocol: dtls,
+			name:     "DTLS-SendExtraFinished",
+			config: Config{
+				Bugs: ProtocolBugs{
+					SendExtraFinished: true,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":UNEXPECTED_RECORD:",
+		},
+		{
+			protocol: dtls,
+			name:     "DTLS-SendExtraFinished-Reordered",
+			config: Config{
+				Bugs: ProtocolBugs{
+					MaxHandshakeRecordLength:  2,
+					ReorderHandshakeFragments: true,
+					SendExtraFinished:         true,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":UNEXPECTED_RECORD:",
+		},
+		{
+			testType: serverTest,
+			name:     "V2ClientHello-EmptyRecordPrefix",
+			config: Config{
+				// Choose a cipher suite that does not involve
+				// elliptic curves, so no extensions are
+				// involved.
+				MaxVersion:   VersionTLS12,
+				CipherSuites: []uint16{TLS_RSA_WITH_3DES_EDE_CBC_SHA},
+				Bugs: ProtocolBugs{
+					SendV2ClientHello: true,
+				},
+			},
+			sendPrefix: string([]byte{
+				byte(recordTypeHandshake),
+				3, 1, // version
+				0, 0, // length
+			}),
+			// A no-op empty record may not be sent before V2ClientHello.
+			shouldFail:    true,
+			expectedError: ":WRONG_VERSION_NUMBER:",
+		},
+		{
+			testType: serverTest,
+			name:     "V2ClientHello-WarningAlertPrefix",
+			config: Config{
+				// Choose a cipher suite that does not involve
+				// elliptic curves, so no extensions are
+				// involved.
+				MaxVersion:   VersionTLS12,
+				CipherSuites: []uint16{TLS_RSA_WITH_3DES_EDE_CBC_SHA},
+				Bugs: ProtocolBugs{
+					SendV2ClientHello: true,
+				},
+			},
+			sendPrefix: string([]byte{
+				byte(recordTypeAlert),
+				3, 1, // version
+				0, 2, // length
+				alertLevelWarning, byte(alertDecompressionFailure),
+			}),
+			// A no-op warning alert may not be sent before V2ClientHello.
+			shouldFail:    true,
+			expectedError: ":WRONG_VERSION_NUMBER:",
+		},
+		{
+			name: "KeyUpdate-Client",
+			config: Config{
+				MaxVersion: VersionTLS13,
+			},
+			sendKeyUpdates:   1,
+			keyUpdateRequest: keyUpdateNotRequested,
+		},
+		{
+			testType: serverTest,
+			name:     "KeyUpdate-Server",
+			config: Config{
+				MaxVersion: VersionTLS13,
+			},
+			sendKeyUpdates:   1,
+			keyUpdateRequest: keyUpdateNotRequested,
+		},
+		{
+			name: "KeyUpdate-InvalidRequestMode",
+			config: Config{
+				MaxVersion: VersionTLS13,
+			},
+			sendKeyUpdates:   1,
+			keyUpdateRequest: 42,
+			shouldFail:       true,
+			expectedError:    ":DECODE_ERROR:",
+		},
+		{
+			name: "SendSNIWarningAlert",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					SendSNIWarningAlert: true,
+				},
+			},
+		},
+		{
+			testType: serverTest,
+			name:     "ExtraCompressionMethods-TLS12",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					SendCompressionMethods: []byte{1, 2, 3, compressionNone, 4, 5, 6},
+				},
+			},
+		},
+		{
+			testType: serverTest,
+			name:     "ExtraCompressionMethods-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					SendCompressionMethods: []byte{1, 2, 3, compressionNone, 4, 5, 6},
+				},
+			},
+			shouldFail:         true,
+			expectedError:      ":INVALID_COMPRESSION_LIST:",
+			expectedLocalError: "remote error: illegal parameter",
+		},
+		{
+			testType: serverTest,
+			name:     "NoNullCompression-TLS12",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					SendCompressionMethods: []byte{1, 2, 3, 4, 5, 6},
+				},
+			},
+			shouldFail:         true,
+			expectedError:      ":INVALID_COMPRESSION_LIST:",
+			expectedLocalError: "remote error: illegal parameter",
+		},
+		{
+			testType: serverTest,
+			name:     "NoNullCompression-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					SendCompressionMethods: []byte{1, 2, 3, 4, 5, 6},
+				},
+			},
+			shouldFail:         true,
+			expectedError:      ":INVALID_COMPRESSION_LIST:",
+			expectedLocalError: "remote error: illegal parameter",
+		},
+		{
+			name: "GREASE-Client-TLS12",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					ExpectGREASE: true,
+				},
+			},
+			flags: []string{"-enable-grease"},
+		},
+		{
+			name: "GREASE-Client-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					ExpectGREASE: true,
+				},
+			},
+			flags: []string{"-enable-grease"},
+		},
+		{
+			testType: serverTest,
+			name:     "GREASE-Server-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					// TLS 1.3 servers are expected to
+					// always enable GREASE. TLS 1.3 is new,
+					// so there is no existing ecosystem to
+					// worry about.
+					ExpectGREASE: true,
+				},
+			},
+		},
+		{
+			// Test the server so there is a large certificate as
+			// well as application data.
+			testType: serverTest,
+			name:     "MaxSendFragment",
+			config: Config{
+				Bugs: ProtocolBugs{
+					MaxReceivePlaintext: 512,
+				},
+			},
+			messageLen: 1024,
+			flags: []string{
+				"-max-send-fragment", "512",
+				"-read-size", "1024",
+			},
+		},
+		{
+			// Test the server so there is a large certificate as
+			// well as application data.
+			testType: serverTest,
+			name:     "MaxSendFragment-TooLarge",
+			config: Config{
+				Bugs: ProtocolBugs{
+					// Ensure that some of the records are
+					// 512.
+					MaxReceivePlaintext: 511,
+				},
+			},
+			messageLen: 1024,
+			flags: []string{
+				"-max-send-fragment", "512",
+				"-read-size", "1024",
+			},
+			shouldFail:         true,
+			expectedLocalError: "local error: record overflow",
+		},
 	}
 	testCases = append(testCases, basicTests...)
+
+	if *includeDHE {
+		testCases = append(testCases, testCase{
+			name: "NoFalseStart-DHE_RSA",
+			config: Config{
+				MaxVersion:   VersionTLS12,
+				CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
+				NextProtos:   []string{"foo"},
+				Bugs: ProtocolBugs{
+					ExpectFalseStart:          true,
+					AlertBeforeFalseStartTest: alertAccessDenied,
+				},
+			},
+			flags: []string{
+				"-false-start",
+				"-advertise-alpn", "\x03foo",
+			},
+			shimWritesFirst:    true,
+			shouldFail:         true,
+			expectedError:      ":TLSV1_ALERT_ACCESS_DENIED:",
+			expectedLocalError: "tls: peer did not false start: EOF",
+		})
+	}
+
+	// Test that very large messages can be received.
+	cert := rsaCertificate
+	for i := 0; i < 50; i++ {
+		cert.Certificate = append(cert.Certificate, cert.Certificate[0])
+	}
+	testCases = append(testCases, testCase{
+		name: "LargeMessage",
+		config: Config{
+			Certificates: []Certificate{cert},
+		},
+	})
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		name:     "LargeMessage-DTLS",
+		config: Config{
+			Certificates: []Certificate{cert},
+		},
+	})
+
+	// They are rejected if the maximum certificate chain length is capped.
+	testCases = append(testCases, testCase{
+		name: "LargeMessage-Reject",
+		config: Config{
+			Certificates: []Certificate{cert},
+		},
+		flags:         []string{"-max-cert-list", "16384"},
+		shouldFail:    true,
+		expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
+	})
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		name:     "LargeMessage-Reject-DTLS",
+		config: Config{
+			Certificates: []Certificate{cert},
+		},
+		flags:         []string{"-max-cert-list", "16384"},
+		shouldFail:    true,
+		expectedError: ":EXCESSIVE_MESSAGE_SIZE:",
+	})
+}
+
+func addTestForCipherSuite(suite testCipherSuite, ver tlsVersion, protocol protocol) {
+	const psk = "12345"
+	const pskIdentity = "luggage combo"
+
+	var prefix string
+	if protocol == dtls {
+		if !ver.hasDTLS {
+			return
+		}
+		prefix = "D"
+	}
+
+	var cert Certificate
+	var certFile string
+	var keyFile string
+	if hasComponent(suite.name, "ECDSA") {
+		cert = ecdsaP256Certificate
+		certFile = ecdsaP256CertificateFile
+		keyFile = ecdsaP256KeyFile
+	} else {
+		cert = rsaCertificate
+		certFile = rsaCertificateFile
+		keyFile = rsaKeyFile
+	}
+
+	var flags []string
+	if hasComponent(suite.name, "PSK") {
+		flags = append(flags,
+			"-psk", psk,
+			"-psk-identity", pskIdentity)
+	}
+	if hasComponent(suite.name, "NULL") {
+		// NULL ciphers must be explicitly enabled.
+		flags = append(flags, "-cipher", "DEFAULT:NULL-SHA")
+	}
+
+	var shouldServerFail, shouldClientFail bool
+	if hasComponent(suite.name, "ECDHE") && ver.version == VersionSSL30 {
+		// BoringSSL clients accept ECDHE on SSLv3, but
+		// a BoringSSL server will never select it
+		// because the extension is missing.
+		shouldServerFail = true
+	}
+	if isTLS12Only(suite.name) && ver.version < VersionTLS12 {
+		shouldClientFail = true
+		shouldServerFail = true
+	}
+	if !isTLS13Suite(suite.name) && ver.version >= VersionTLS13 {
+		shouldClientFail = true
+		shouldServerFail = true
+	}
+	if isTLS13Suite(suite.name) && ver.version < VersionTLS13 {
+		shouldClientFail = true
+		shouldServerFail = true
+	}
+	if !isDTLSCipher(suite.name) && protocol == dtls {
+		shouldClientFail = true
+		shouldServerFail = true
+	}
+
+	var sendCipherSuite uint16
+	var expectedServerError, expectedClientError string
+	serverCipherSuites := []uint16{suite.id}
+	if shouldServerFail {
+		expectedServerError = ":NO_SHARED_CIPHER:"
+	}
+	if shouldClientFail {
+		expectedClientError = ":WRONG_CIPHER_RETURNED:"
+		// Configure the server to select ciphers as normal but
+		// select an incompatible cipher in ServerHello.
+		serverCipherSuites = nil
+		sendCipherSuite = suite.id
+	}
+
+	// For cipher suites and versions where exporters are defined, verify
+	// that they interoperate.
+	var exportKeyingMaterial int
+	if ver.version > VersionSSL30 {
+		exportKeyingMaterial = 1024
+	}
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		protocol: protocol,
+		name:     prefix + ver.name + "-" + suite.name + "-server",
+		config: Config{
+			MinVersion:           ver.version,
+			MaxVersion:           ver.version,
+			CipherSuites:         []uint16{suite.id},
+			Certificates:         []Certificate{cert},
+			PreSharedKey:         []byte(psk),
+			PreSharedKeyIdentity: pskIdentity,
+			Bugs: ProtocolBugs{
+				AdvertiseAllConfiguredCiphers: true,
+			},
+		},
+		certFile:             certFile,
+		keyFile:              keyFile,
+		flags:                flags,
+		resumeSession:        true,
+		shouldFail:           shouldServerFail,
+		expectedError:        expectedServerError,
+		exportKeyingMaterial: exportKeyingMaterial,
+	})
+
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		protocol: protocol,
+		name:     prefix + ver.name + "-" + suite.name + "-client",
+		config: Config{
+			MinVersion:           ver.version,
+			MaxVersion:           ver.version,
+			CipherSuites:         serverCipherSuites,
+			Certificates:         []Certificate{cert},
+			PreSharedKey:         []byte(psk),
+			PreSharedKeyIdentity: pskIdentity,
+			Bugs: ProtocolBugs{
+				IgnorePeerCipherPreferences: shouldClientFail,
+				SendCipherSuite:             sendCipherSuite,
+			},
+		},
+		flags:                flags,
+		resumeSession:        true,
+		shouldFail:           shouldClientFail,
+		expectedError:        expectedClientError,
+		exportKeyingMaterial: exportKeyingMaterial,
+	})
+
+	if shouldClientFail {
+		return
+	}
+
+	// Ensure the maximum record size is accepted.
+	testCases = append(testCases, testCase{
+		protocol: protocol,
+		name:     prefix + ver.name + "-" + suite.name + "-LargeRecord",
+		config: Config{
+			MinVersion:           ver.version,
+			MaxVersion:           ver.version,
+			CipherSuites:         []uint16{suite.id},
+			Certificates:         []Certificate{cert},
+			PreSharedKey:         []byte(psk),
+			PreSharedKeyIdentity: pskIdentity,
+		},
+		flags:      flags,
+		messageLen: maxPlaintext,
+	})
+
+	// Test bad records for all ciphers. Bad records are fatal in TLS
+	// and ignored in DTLS.
+	var shouldFail bool
+	var expectedError string
+	if protocol == tls {
+		shouldFail = true
+		expectedError = ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:"
+	}
+
+	testCases = append(testCases, testCase{
+		protocol: protocol,
+		name:     prefix + ver.name + "-" + suite.name + "-BadRecord",
+		config: Config{
+			MinVersion:           ver.version,
+			MaxVersion:           ver.version,
+			CipherSuites:         []uint16{suite.id},
+			Certificates:         []Certificate{cert},
+			PreSharedKey:         []byte(psk),
+			PreSharedKeyIdentity: pskIdentity,
+		},
+		flags:            flags,
+		damageFirstWrite: true,
+		messageLen:       maxPlaintext,
+		shouldFail:       shouldFail,
+		expectedError:    expectedError,
+	})
 }
 
 func addCipherSuiteTests() {
+	const bogusCipher = 0xfe00
+
+	if *includeDHE {
+		testCipherSuites = append(testCipherSuites, []testCipherSuite{
+			{"DHE-RSA-AES128-GCM", TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
+			{"DHE-RSA-AES128-SHA", TLS_DHE_RSA_WITH_AES_128_CBC_SHA},
+			{"DHE-RSA-AES128-SHA256", TLS_DHE_RSA_WITH_AES_128_CBC_SHA256},
+			{"DHE-RSA-AES256-GCM", TLS_DHE_RSA_WITH_AES_256_GCM_SHA384},
+			{"DHE-RSA-AES256-SHA", TLS_DHE_RSA_WITH_AES_256_CBC_SHA},
+			{"DHE-RSA-AES256-SHA256", TLS_DHE_RSA_WITH_AES_256_CBC_SHA256},
+		}...)
+	}
+
 	for _, suite := range testCipherSuites {
-		const psk = "12345"
-		const pskIdentity = "luggage combo"
-
-		var cert Certificate
-		var certFile string
-		var keyFile string
-		if hasComponent(suite.name, "ECDSA") {
-			cert = getECDSACertificate()
-			certFile = ecdsaCertificateFile
-			keyFile = ecdsaKeyFile
-		} else {
-			cert = getRSACertificate()
-			certFile = rsaCertificateFile
-			keyFile = rsaKeyFile
-		}
-
-		var flags []string
-		if hasComponent(suite.name, "PSK") {
-			flags = append(flags,
-				"-psk", psk,
-				"-psk-identity", pskIdentity)
-		}
-		if hasComponent(suite.name, "NULL") {
-			// NULL ciphers must be explicitly enabled.
-			flags = append(flags, "-cipher", "DEFAULT:NULL-SHA")
-		}
-
 		for _, ver := range tlsVersions {
-			if ver.version < VersionTLS12 && isTLS12Only(suite.name) {
-				continue
+			for _, protocol := range []protocol{tls, dtls} {
+				addTestForCipherSuite(suite, ver, protocol)
 			}
-
-			shouldFail := isTLSOnly(suite.name) && ver.version == VersionSSL30
-
-			expectedError := ""
-			if shouldFail {
-				expectedError = ":NO_SHARED_CIPHER:"
-			}
-
-			testCases = append(testCases, testCase{
-				testType: serverTest,
-				name:     ver.name + "-" + suite.name + "-server",
-				config: Config{
-					MinVersion:           ver.version,
-					MaxVersion:           ver.version,
-					CipherSuites:         []uint16{suite.id},
-					Certificates:         []Certificate{cert},
-					PreSharedKey:         []byte(psk),
-					PreSharedKeyIdentity: pskIdentity,
-				},
-				certFile:      certFile,
-				keyFile:       keyFile,
-				flags:         flags,
-				resumeSession: true,
-				shouldFail:    shouldFail,
-				expectedError: expectedError,
-			})
-
-			if shouldFail {
-				continue
-			}
-
-			testCases = append(testCases, testCase{
-				testType: clientTest,
-				name:     ver.name + "-" + suite.name + "-client",
-				config: Config{
-					MinVersion:           ver.version,
-					MaxVersion:           ver.version,
-					CipherSuites:         []uint16{suite.id},
-					Certificates:         []Certificate{cert},
-					PreSharedKey:         []byte(psk),
-					PreSharedKeyIdentity: pskIdentity,
-				},
-				flags:         flags,
-				resumeSession: true,
-			})
-
-			if ver.hasDTLS && isDTLSCipher(suite.name) {
-				testCases = append(testCases, testCase{
-					testType: clientTest,
-					protocol: dtls,
-					name:     "D" + ver.name + "-" + suite.name + "-client",
-					config: Config{
-						MinVersion:           ver.version,
-						MaxVersion:           ver.version,
-						CipherSuites:         []uint16{suite.id},
-						Certificates:         []Certificate{cert},
-						PreSharedKey:         []byte(psk),
-						PreSharedKeyIdentity: pskIdentity,
-					},
-					flags:         flags,
-					resumeSession: true,
-				})
-				testCases = append(testCases, testCase{
-					testType: serverTest,
-					protocol: dtls,
-					name:     "D" + ver.name + "-" + suite.name + "-server",
-					config: Config{
-						MinVersion:           ver.version,
-						MaxVersion:           ver.version,
-						CipherSuites:         []uint16{suite.id},
-						Certificates:         []Certificate{cert},
-						PreSharedKey:         []byte(psk),
-						PreSharedKeyIdentity: pskIdentity,
-					},
-					certFile:      certFile,
-					keyFile:       keyFile,
-					flags:         flags,
-					resumeSession: true,
-				})
-			}
-		}
-
-		// Ensure both TLS and DTLS accept their maximum record sizes.
-		testCases = append(testCases, testCase{
-			name: suite.name + "-LargeRecord",
-			config: Config{
-				CipherSuites:         []uint16{suite.id},
-				Certificates:         []Certificate{cert},
-				PreSharedKey:         []byte(psk),
-				PreSharedKeyIdentity: pskIdentity,
-			},
-			flags:      flags,
-			messageLen: maxPlaintext,
-		})
-		if isDTLSCipher(suite.name) {
-			testCases = append(testCases, testCase{
-				protocol: dtls,
-				name:     suite.name + "-LargeRecord-DTLS",
-				config: Config{
-					CipherSuites:         []uint16{suite.id},
-					Certificates:         []Certificate{cert},
-					PreSharedKey:         []byte(psk),
-					PreSharedKeyIdentity: pskIdentity,
-				},
-				flags:      flags,
-				messageLen: maxPlaintext,
-			})
 		}
 	}
 
 	testCases = append(testCases, testCase{
-		name: "WeakDH",
+		name: "NoSharedCipher",
 		config: Config{
-			CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
-			Bugs: ProtocolBugs{
-				// This is a 1023-bit prime number, generated
-				// with:
-				// openssl gendh 1023 | openssl asn1parse -i
-				DHGroupPrime: bigFromHex("518E9B7930CE61C6E445C8360584E5FC78D9137C0FFDC880B495D5338ADF7689951A6821C17A76B3ACB8E0156AEA607B7EC406EBEDBB84D8376EB8FE8F8BA1433488BEE0C3EDDFD3A32DBB9481980A7AF6C96BFCF490A094CFFB2B8192C1BB5510B77B658436E27C2D4D023FE3718222AB0CA1273995B51F6D625A4944D0DD4B"),
-			},
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{},
 		},
 		shouldFail:    true,
-		expectedError: ":BAD_DH_P_LENGTH:",
+		expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:",
 	})
 
 	testCases = append(testCases, testCase{
-		name: "SillyDH",
+		name: "NoSharedCipher-TLS13",
 		config: Config{
-			CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
+			MaxVersion:   VersionTLS13,
+			CipherSuites: []uint16{},
+		},
+		shouldFail:    true,
+		expectedError: ":HANDSHAKE_FAILURE_ON_CLIENT_HELLO:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "UnsupportedCipherSuite",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
 			Bugs: ProtocolBugs{
-				// This is a 4097-bit prime number, generated
-				// with:
-				// openssl gendh 4097 | openssl asn1parse -i
-				DHGroupPrime: bigFromHex("01D366FA64A47419B0CD4A45918E8D8C8430F674621956A9F52B0CA592BC104C6E38D60C58F2CA66792A2B7EBDC6F8FFE75AB7D6862C261F34E96A2AEEF53AB7C21365C2E8FB0582F71EB57B1C227C0E55AE859E9904A25EFECD7B435C4D4357BD840B03649D4A1F8037D89EA4E1967DBEEF1CC17A6111C48F12E9615FFF336D3F07064CB17C0B765A012C850B9E3AA7A6984B96D8C867DDC6D0F4AB52042572244796B7ECFF681CD3B3E2E29AAECA391A775BEE94E502FB15881B0F4AC60314EA947C0C82541C3D16FD8C0E09BB7F8F786582032859D9C13187CE6C0CB6F2D3EE6C3C9727C15F14B21D3CD2E02BDB9D119959B0E03DC9E5A91E2578762300B1517D2352FC1D0BB934A4C3E1B20CE9327DB102E89A6C64A8C3148EDFC5A94913933853442FA84451B31FD21E492F92DD5488E0D871AEBFE335A4B92431DEC69591548010E76A5B365D346786E9A2D3E589867D796AA5E25211201D757560D318A87DFB27F3E625BC373DB48BF94A63161C674C3D4265CB737418441B7650EABC209CF675A439BEB3E9D1AA1B79F67198A40CEFD1C89144F7D8BAF61D6AD36F466DA546B4174A0E0CAF5BD788C8243C7C2DDDCC3DB6FC89F12F17D19FBD9B0BC76FE92891CD6BA07BEA3B66EF12D0D85E788FD58675C1B0FBD16029DCC4D34E7A1A41471BDEDF78BF591A8B4E96D88BEC8EDC093E616292BFC096E69A916E8D624B"),
+				IgnorePeerCipherPreferences: true,
+			},
+		},
+		flags:         []string{"-cipher", "DEFAULT:!AES"},
+		shouldFail:    true,
+		expectedError: ":WRONG_CIPHER_RETURNED:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "ServerHelloBogusCipher",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				SendCipherSuite: bogusCipher,
 			},
 		},
 		shouldFail:    true,
-		expectedError: ":DH_P_TOO_LONG:",
+		expectedError: ":UNKNOWN_CIPHER_RETURNED:",
+	})
+	testCases = append(testCases, testCase{
+		name: "ServerHelloBogusCipher-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendCipherSuite: bogusCipher,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNKNOWN_CIPHER_RETURNED:",
 	})
 
-	// This test ensures that Diffie-Hellman public values are padded with
-	// zeros so that they're the same length as the prime. This is to avoid
-	// hitting a bug in yaSSL.
+	if *includeDHE {
+		testCases = append(testCases, testCase{
+			name: "WeakDH",
+			config: Config{
+				MaxVersion:   VersionTLS12,
+				CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
+				Bugs: ProtocolBugs{
+					// This is a 1023-bit prime number, generated
+					// with:
+					// openssl gendh 1023 | openssl asn1parse -i
+					DHGroupPrime: bigFromHex("518E9B7930CE61C6E445C8360584E5FC78D9137C0FFDC880B495D5338ADF7689951A6821C17A76B3ACB8E0156AEA607B7EC406EBEDBB84D8376EB8FE8F8BA1433488BEE0C3EDDFD3A32DBB9481980A7AF6C96BFCF490A094CFFB2B8192C1BB5510B77B658436E27C2D4D023FE3718222AB0CA1273995B51F6D625A4944D0DD4B"),
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":BAD_DH_P_LENGTH:",
+		})
+
+		testCases = append(testCases, testCase{
+			name: "SillyDH",
+			config: Config{
+				MaxVersion:   VersionTLS12,
+				CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
+				Bugs: ProtocolBugs{
+					// This is a 4097-bit prime number, generated
+					// with:
+					// openssl gendh 4097 | openssl asn1parse -i
+					DHGroupPrime: bigFromHex("01D366FA64A47419B0CD4A45918E8D8C8430F674621956A9F52B0CA592BC104C6E38D60C58F2CA66792A2B7EBDC6F8FFE75AB7D6862C261F34E96A2AEEF53AB7C21365C2E8FB0582F71EB57B1C227C0E55AE859E9904A25EFECD7B435C4D4357BD840B03649D4A1F8037D89EA4E1967DBEEF1CC17A6111C48F12E9615FFF336D3F07064CB17C0B765A012C850B9E3AA7A6984B96D8C867DDC6D0F4AB52042572244796B7ECFF681CD3B3E2E29AAECA391A775BEE94E502FB15881B0F4AC60314EA947C0C82541C3D16FD8C0E09BB7F8F786582032859D9C13187CE6C0CB6F2D3EE6C3C9727C15F14B21D3CD2E02BDB9D119959B0E03DC9E5A91E2578762300B1517D2352FC1D0BB934A4C3E1B20CE9327DB102E89A6C64A8C3148EDFC5A94913933853442FA84451B31FD21E492F92DD5488E0D871AEBFE335A4B92431DEC69591548010E76A5B365D346786E9A2D3E589867D796AA5E25211201D757560D318A87DFB27F3E625BC373DB48BF94A63161C674C3D4265CB737418441B7650EABC209CF675A439BEB3E9D1AA1B79F67198A40CEFD1C89144F7D8BAF61D6AD36F466DA546B4174A0E0CAF5BD788C8243C7C2DDDCC3DB6FC89F12F17D19FBD9B0BC76FE92891CD6BA07BEA3B66EF12D0D85E788FD58675C1B0FBD16029DCC4D34E7A1A41471BDEDF78BF591A8B4E96D88BEC8EDC093E616292BFC096E69A916E8D624B"),
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":DH_P_TOO_LONG:",
+		})
+
+		// This test ensures that Diffie-Hellman public values are padded with
+		// zeros so that they're the same length as the prime. This is to avoid
+		// hitting a bug in yaSSL.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "DHPublicValuePadded",
+			config: Config{
+				MaxVersion:   VersionTLS12,
+				CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
+				Bugs: ProtocolBugs{
+					RequireDHPublicValueLen: (1025 + 7) / 8,
+				},
+			},
+			flags: []string{"-use-sparse-dh-prime"},
+		})
+	}
+
+	// The server must be tolerant to bogus ciphers.
 	testCases = append(testCases, testCase{
 		testType: serverTest,
-		name:     "DHPublicValuePadded",
+		name:     "UnknownCipher",
 		config: Config{
-			CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{bogusCipher, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
 			Bugs: ProtocolBugs{
-				RequireDHPublicValueLen: (1025 + 7) / 8,
+				AdvertiseAllConfiguredCiphers: true,
 			},
 		},
-		flags: []string{"-use-sparse-dh-prime"},
 	})
 
-	// versionSpecificCiphersTest specifies a test for the TLS 1.0 and TLS
-	// 1.1 specific cipher suite settings. A server is setup with the given
-	// cipher lists and then a connection is made for each member of
-	// expectations. The cipher suite that the server selects must match
-	// the specified one.
-	var versionSpecificCiphersTest = []struct {
-		ciphersDefault, ciphersTLS10, ciphersTLS11 string
-		// expectations is a map from TLS version to cipher suite id.
-		expectations map[uint16]uint16
-	}{
-		{
-			// Test that the null case (where no version-specific ciphers are set)
-			// works as expected.
-			"RC4-SHA:AES128-SHA", // default ciphers
-			"",                   // no ciphers specifically for TLS ≥ 1.0
-			"",                   // no ciphers specifically for TLS ≥ 1.1
-			map[uint16]uint16{
-				VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
-				VersionTLS10: TLS_RSA_WITH_RC4_128_SHA,
-				VersionTLS11: TLS_RSA_WITH_RC4_128_SHA,
-				VersionTLS12: TLS_RSA_WITH_RC4_128_SHA,
+	// The server must be tolerant to bogus ciphers.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "UnknownCipher-TLS13",
+		config: Config{
+			MaxVersion:   VersionTLS13,
+			CipherSuites: []uint16{bogusCipher, TLS_AES_128_GCM_SHA256},
+			Bugs: ProtocolBugs{
+				AdvertiseAllConfiguredCiphers: true,
 			},
 		},
-		{
-			// With ciphers_tls10 set, TLS 1.0, 1.1 and 1.2 should get a different
-			// cipher.
-			"RC4-SHA:AES128-SHA", // default
-			"AES128-SHA",         // these ciphers for TLS ≥ 1.0
-			"",                   // no ciphers specifically for TLS ≥ 1.1
-			map[uint16]uint16{
-				VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
-				VersionTLS10: TLS_RSA_WITH_AES_128_CBC_SHA,
-				VersionTLS11: TLS_RSA_WITH_AES_128_CBC_SHA,
-				VersionTLS12: TLS_RSA_WITH_AES_128_CBC_SHA,
-			},
-		},
-		{
-			// With ciphers_tls11 set, TLS 1.1 and 1.2 should get a different
-			// cipher.
-			"RC4-SHA:AES128-SHA", // default
-			"",                   // no ciphers specifically for TLS ≥ 1.0
-			"AES128-SHA",         // these ciphers for TLS ≥ 1.1
-			map[uint16]uint16{
-				VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
-				VersionTLS10: TLS_RSA_WITH_RC4_128_SHA,
-				VersionTLS11: TLS_RSA_WITH_AES_128_CBC_SHA,
-				VersionTLS12: TLS_RSA_WITH_AES_128_CBC_SHA,
-			},
-		},
-		{
-			// With both ciphers_tls10 and ciphers_tls11 set, ciphers_tls11 should
-			// mask ciphers_tls10 for TLS 1.1 and 1.2.
-			"RC4-SHA:AES128-SHA", // default
-			"AES128-SHA",         // these ciphers for TLS ≥ 1.0
-			"AES256-SHA",         // these ciphers for TLS ≥ 1.1
-			map[uint16]uint16{
-				VersionSSL30: TLS_RSA_WITH_RC4_128_SHA,
-				VersionTLS10: TLS_RSA_WITH_AES_128_CBC_SHA,
-				VersionTLS11: TLS_RSA_WITH_AES_256_CBC_SHA,
-				VersionTLS12: TLS_RSA_WITH_AES_256_CBC_SHA,
-			},
-		},
-	}
+	})
 
-	for i, test := range versionSpecificCiphersTest {
-		for version, expectedCipherSuite := range test.expectations {
-			flags := []string{"-cipher", test.ciphersDefault}
-			if len(test.ciphersTLS10) > 0 {
-				flags = append(flags, "-cipher-tls10", test.ciphersTLS10)
-			}
-			if len(test.ciphersTLS11) > 0 {
-				flags = append(flags, "-cipher-tls11", test.ciphersTLS11)
-			}
+	// Test empty ECDHE_PSK identity hints work as expected.
+	testCases = append(testCases, testCase{
+		name: "EmptyECDHEPSKHint",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
+			PreSharedKey: []byte("secret"),
+		},
+		flags: []string{"-psk", "secret"},
+	})
 
-			testCases = append(testCases, testCase{
-				testType: serverTest,
-				name:     fmt.Sprintf("VersionSpecificCiphersTest-%d-%x", i, version),
-				config: Config{
-					MaxVersion:   version,
-					MinVersion:   version,
-					CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA},
-				},
-				flags:          flags,
-				expectedCipher: expectedCipherSuite,
-			})
-		}
-	}
+	// Test empty PSK identity hints work as expected, even if an explicit
+	// ServerKeyExchange is sent.
+	testCases = append(testCases, testCase{
+		name: "ExplicitEmptyPSKHint",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
+			PreSharedKey: []byte("secret"),
+			Bugs: ProtocolBugs{
+				AlwaysSendPreSharedKeyIdentityHint: true,
+			},
+		},
+		flags: []string{"-psk", "secret"},
+	})
 }
 
 func addBadECDSASignatureTests() {
@@ -2375,15 +2875,29 @@
 			testCases = append(testCases, testCase{
 				name: fmt.Sprintf("BadECDSA-%d-%d", badR, badS),
 				config: Config{
+					MaxVersion:   VersionTLS12,
 					CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
-					Certificates: []Certificate{getECDSACertificate()},
+					Certificates: []Certificate{ecdsaP256Certificate},
 					Bugs: ProtocolBugs{
 						BadECDSAR: badR,
 						BadECDSAS: badS,
 					},
 				},
 				shouldFail:    true,
-				expectedError: "SIGNATURE",
+				expectedError: ":BAD_SIGNATURE:",
+			})
+			testCases = append(testCases, testCase{
+				name: fmt.Sprintf("BadECDSA-%d-%d-TLS13", badR, badS),
+				config: Config{
+					MaxVersion:   VersionTLS13,
+					Certificates: []Certificate{ecdsaP256Certificate},
+					Bugs: ProtocolBugs{
+						BadECDSAR: badR,
+						BadECDSAS: badS,
+					},
+				},
+				shouldFail:    true,
+				expectedError: ":BAD_SIGNATURE:",
 			})
 		}
 	}
@@ -2393,6 +2907,7 @@
 	testCases = append(testCases, testCase{
 		name: "MaxCBCPadding",
 		config: Config{
+			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
 			Bugs: ProtocolBugs{
 				MaxPadding: true,
@@ -2403,19 +2918,21 @@
 	testCases = append(testCases, testCase{
 		name: "BadCBCPadding",
 		config: Config{
+			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
 			Bugs: ProtocolBugs{
 				PaddingFirstByteBad: true,
 			},
 		},
 		shouldFail:    true,
-		expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
+		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
 	})
 	// OpenSSL previously had an issue where the first byte of padding in
 	// 255 bytes of padding wasn't checked.
 	testCases = append(testCases, testCase{
 		name: "BadCBCPadding255",
 		config: Config{
+			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA},
 			Bugs: ProtocolBugs{
 				MaxPadding:               true,
@@ -2424,7 +2941,7 @@
 		},
 		messageLen:    12, // 20 bytes of SHA-1 + 12 == 0 % block size
 		shouldFail:    true,
-		expectedError: "DECRYPTION_FAILED_OR_BAD_RECORD_MAC",
+		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
 	})
 }
 
@@ -2463,13 +2980,15 @@
 
 func addClientAuthTests() {
 	// Add a dummy cert pool to stress certificate authority parsing.
-	// TODO(davidben): Add tests that those values parse out correctly.
 	certPool := x509.NewCertPool()
-	cert, err := x509.ParseCertificate(rsaCertificate.Certificate[0])
-	if err != nil {
-		panic(err)
+	for _, cert := range []Certificate{rsaCertificate, rsa1024Certificate} {
+		cert, err := x509.ParseCertificate(cert.Certificate[0])
+		if err != nil {
+			panic(err)
+		}
+		certPool.AddCert(cert)
 	}
-	certPool.AddCert(cert)
+	caNames := certPool.Subjects()
 
 	for _, ver := range tlsVersions {
 		testCases = append(testCases, testCase{
@@ -2503,7 +3022,7 @@
 				config: Config{
 					MinVersion:   ver.version,
 					MaxVersion:   ver.version,
-					Certificates: []Certificate{ecdsaCertificate},
+					Certificates: []Certificate{ecdsaP256Certificate},
 				},
 				flags: []string{"-require-any-client-certificate"},
 			})
@@ -2517,12 +3036,179 @@
 					ClientCAs:  certPool,
 				},
 				flags: []string{
-					"-cert-file", path.Join(*resourceDir, ecdsaCertificateFile),
-					"-key-file", path.Join(*resourceDir, ecdsaKeyFile),
+					"-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
+					"-key-file", path.Join(*resourceDir, ecdsaP256KeyFile),
 				},
 			})
 		}
+
+		testCases = append(testCases, testCase{
+			name: "NoClientCertificate-" + ver.name,
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				ClientAuth: RequireAnyClientCert,
+			},
+			shouldFail:         true,
+			expectedLocalError: "client didn't provide a certificate",
+		})
+
+		testCases = append(testCases, testCase{
+			// Even if not configured to expect a certificate, OpenSSL will
+			// return X509_V_OK as the verify_result.
+			testType: serverTest,
+			name:     "NoClientCertificateRequested-Server-" + ver.name,
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+			},
+			flags: []string{
+				"-expect-verify-result",
+			},
+			resumeSession: true,
+		})
+
+		testCases = append(testCases, testCase{
+			// If a client certificate is not provided, OpenSSL will still
+			// return X509_V_OK as the verify_result.
+			testType: serverTest,
+			name:     "NoClientCertificate-Server-" + ver.name,
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+			},
+			flags: []string{
+				"-expect-verify-result",
+				"-verify-peer",
+			},
+			resumeSession: true,
+		})
+
+		certificateRequired := "remote error: certificate required"
+		if ver.version < VersionTLS13 {
+			// Prior to TLS 1.3, the generic handshake_failure alert
+			// was used.
+			certificateRequired = "remote error: handshake failure"
+		}
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "RequireAnyClientCertificate-" + ver.name,
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+			},
+			flags:              []string{"-require-any-client-certificate"},
+			shouldFail:         true,
+			expectedError:      ":PEER_DID_NOT_RETURN_A_CERTIFICATE:",
+			expectedLocalError: certificateRequired,
+		})
+
+		if ver.version != VersionSSL30 {
+			testCases = append(testCases, testCase{
+				testType: serverTest,
+				name:     "SkipClientCertificate-" + ver.name,
+				config: Config{
+					MinVersion: ver.version,
+					MaxVersion: ver.version,
+					Bugs: ProtocolBugs{
+						SkipClientCertificate: true,
+					},
+				},
+				// Setting SSL_VERIFY_PEER allows anonymous clients.
+				flags:         []string{"-verify-peer"},
+				shouldFail:    true,
+				expectedError: ":UNEXPECTED_MESSAGE:",
+			})
+		}
+
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     ver.name + "-Server-CertReq-CA-List",
+			config: Config{
+				MinVersion:   ver.version,
+				MaxVersion:   ver.version,
+				Certificates: []Certificate{rsaCertificate},
+				Bugs: ProtocolBugs{
+					ExpectCertificateReqNames: caNames,
+				},
+			},
+			flags: []string{
+				"-require-any-client-certificate",
+				"-use-client-ca-list", encodeDERValues(caNames),
+			},
+		})
+
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			name:     ver.name + "-Client-CertReq-CA-List",
+			config: Config{
+				MinVersion:   ver.version,
+				MaxVersion:   ver.version,
+				Certificates: []Certificate{rsaCertificate},
+				ClientAuth:   RequireAnyClientCert,
+				ClientCAs:    certPool,
+			},
+			flags: []string{
+				"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+				"-key-file", path.Join(*resourceDir, rsaKeyFile),
+				"-expect-client-ca-list", encodeDERValues(caNames),
+			},
+		})
 	}
+
+	// Client auth is only legal in certificate-based ciphers.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "ClientAuth-PSK",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
+			PreSharedKey: []byte("secret"),
+			ClientAuth:   RequireAnyClientCert,
+		},
+		flags: []string{
+			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+			"-key-file", path.Join(*resourceDir, rsaKeyFile),
+			"-psk", "secret",
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_MESSAGE:",
+	})
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "ClientAuth-ECDHE_PSK",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
+			PreSharedKey: []byte("secret"),
+			ClientAuth:   RequireAnyClientCert,
+		},
+		flags: []string{
+			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+			"-key-file", path.Join(*resourceDir, rsaKeyFile),
+			"-psk", "secret",
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_MESSAGE:",
+	})
+
+	// Regression test for a bug where the client CA list, if explicitly
+	// set to NULL, was mis-encoded.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "Null-Client-CA-List",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			Certificates: []Certificate{rsaCertificate},
+			Bugs: ProtocolBugs{
+				ExpectCertificateReqNames: [][]byte{},
+			},
+		},
+		flags: []string{
+			"-require-any-client-certificate",
+			"-use-client-ca-list", "<NULL>",
+		},
+	})
 }
 
 func addExtendedMasterSecretTests() {
@@ -2530,10 +3216,8 @@
 
 	for _, with := range []bool{false, true} {
 		prefix := "No"
-		var flags []string
 		if with {
 			prefix = ""
-			flags = []string{expectEMSFlag}
 		}
 
 		for _, isClient := range []bool{false, true} {
@@ -2545,6 +3229,13 @@
 			}
 
 			for _, ver := range tlsVersions {
+				// In TLS 1.3, the extension is irrelevant and
+				// always reports as enabled.
+				var flags []string
+				if with || ver.version >= VersionTLS13 {
+					flags = []string{expectEMSFlag}
+				}
+
 				test := testCase{
 					testType: testType,
 					name:     prefix + "ExtendedMasterSecret-" + ver.name + suffix,
@@ -2584,12 +3275,14 @@
 				}
 
 				supportedConfig := Config{
+					MaxVersion: VersionTLS12,
 					Bugs: ProtocolBugs{
 						RequireExtendedMasterSecret: true,
 					},
 				}
 
 				noSupportConfig := Config{
+					MaxVersion: VersionTLS12,
 					Bugs: ProtocolBugs{
 						NoExtendedMasterSecret: true,
 					},
@@ -2654,73 +3347,328 @@
 			}
 		}
 	}
+
+	// Switching EMS on renegotiation is forbidden.
+	testCases = append(testCases, testCase{
+		name: "ExtendedMasterSecret-Renego-NoEMS",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				NoExtendedMasterSecret:                true,
+				NoExtendedMasterSecretOnRenegotiation: true,
+			},
+		},
+		renegotiate: 1,
+		flags: []string{
+			"-renegotiate-freely",
+			"-expect-total-renegotiations", "1",
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		name: "ExtendedMasterSecret-Renego-Upgrade",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				NoExtendedMasterSecret: true,
+			},
+		},
+		renegotiate: 1,
+		flags: []string{
+			"-renegotiate-freely",
+			"-expect-total-renegotiations", "1",
+		},
+		shouldFail:    true,
+		expectedError: ":RENEGOTIATION_EMS_MISMATCH:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "ExtendedMasterSecret-Renego-Downgrade",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				NoExtendedMasterSecretOnRenegotiation: true,
+			},
+		},
+		renegotiate: 1,
+		flags: []string{
+			"-renegotiate-freely",
+			"-expect-total-renegotiations", "1",
+		},
+		shouldFail:    true,
+		expectedError: ":RENEGOTIATION_EMS_MISMATCH:",
+	})
+}
+
+type stateMachineTestConfig struct {
+	protocol            protocol
+	async               bool
+	splitHandshake      bool
+	packHandshakeFlight bool
+	implicitHandshake   bool
 }
 
 // Adds tests that try to cover the range of the handshake state machine, under
 // various conditions. Some of these are redundant with other tests, but they
 // only cover the synchronous case.
-func addStateMachineCoverageTests(async, splitHandshake bool, protocol protocol) {
+func addAllStateMachineCoverageTests() {
+	for _, async := range []bool{false, true} {
+		for _, protocol := range []protocol{tls, dtls} {
+			addStateMachineCoverageTests(stateMachineTestConfig{
+				protocol: protocol,
+				async:    async,
+			})
+			addStateMachineCoverageTests(stateMachineTestConfig{
+				protocol:          protocol,
+				async:             async,
+				implicitHandshake: true,
+			})
+			addStateMachineCoverageTests(stateMachineTestConfig{
+				protocol:       protocol,
+				async:          async,
+				splitHandshake: true,
+			})
+			if protocol == tls {
+				addStateMachineCoverageTests(stateMachineTestConfig{
+					protocol:            protocol,
+					async:               async,
+					packHandshakeFlight: true,
+				})
+			}
+		}
+	}
+}
+
+func addStateMachineCoverageTests(config stateMachineTestConfig) {
 	var tests []testCase
 
 	// Basic handshake, with resumption. Client and server,
 	// session ID and session ticket.
 	tests = append(tests, testCase{
-		name:          "Basic-Client",
+		name: "Basic-Client",
+		config: Config{
+			MaxVersion: VersionTLS12,
+		},
 		resumeSession: true,
+		// Ensure session tickets are used, not session IDs.
+		noSessionCache: true,
 	})
 	tests = append(tests, testCase{
 		name: "Basic-Client-RenewTicket",
 		config: Config{
+			MaxVersion: VersionTLS12,
 			Bugs: ProtocolBugs{
 				RenewTicketOnResume: true,
 			},
 		},
-		flags:         []string{"-expect-ticket-renewal"},
-		resumeSession: true,
+		flags:                []string{"-expect-ticket-renewal"},
+		resumeSession:        true,
+		resumeRenewedSession: true,
 	})
 	tests = append(tests, testCase{
 		name: "Basic-Client-NoTicket",
 		config: Config{
+			MaxVersion:             VersionTLS12,
 			SessionTicketsDisabled: true,
 		},
 		resumeSession: true,
 	})
 	tests = append(tests, testCase{
-		name:          "Basic-Client-Implicit",
-		flags:         []string{"-implicit-handshake"},
+		testType: serverTest,
+		name:     "Basic-Server",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				RequireSessionTickets: true,
+			},
+		},
 		resumeSession: true,
-	})
-	tests = append(tests, testCase{
-		testType:      serverTest,
-		name:          "Basic-Server",
-		resumeSession: true,
+		flags:         []string{"-expect-no-session-id"},
 	})
 	tests = append(tests, testCase{
 		testType: serverTest,
 		name:     "Basic-Server-NoTickets",
 		config: Config{
+			MaxVersion:             VersionTLS12,
 			SessionTicketsDisabled: true,
 		},
 		resumeSession: true,
+		flags:         []string{"-expect-session-id"},
 	})
 	tests = append(tests, testCase{
-		testType:      serverTest,
-		name:          "Basic-Server-Implicit",
-		flags:         []string{"-implicit-handshake"},
-		resumeSession: true,
-	})
-	tests = append(tests, testCase{
-		testType:      serverTest,
-		name:          "Basic-Server-EarlyCallback",
+		testType: serverTest,
+		name:     "Basic-Server-EarlyCallback",
+		config: Config{
+			MaxVersion: VersionTLS12,
+		},
 		flags:         []string{"-use-early-callback"},
 		resumeSession: true,
 	})
 
+	// TLS 1.3 basic handshake shapes.
+	if config.protocol == tls {
+		tests = append(tests, testCase{
+			name: "TLS13-1RTT-Client",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				MinVersion: VersionTLS13,
+			},
+			resumeSession:        true,
+			resumeRenewedSession: true,
+		})
+
+		tests = append(tests, testCase{
+			testType: serverTest,
+			name:     "TLS13-1RTT-Server",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				MinVersion: VersionTLS13,
+			},
+			resumeSession:        true,
+			resumeRenewedSession: true,
+			// TLS 1.3 uses tickets, so the session should not be
+			// cached statefully.
+			flags: []string{"-expect-no-session-id"},
+		})
+
+		tests = append(tests, testCase{
+			name: "TLS13-HelloRetryRequest-Client",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				MinVersion: VersionTLS13,
+				// P-384 requires a HelloRetryRequest against BoringSSL's default
+				// configuration. Assert this with ExpectMissingKeyShare.
+				CurvePreferences: []CurveID{CurveP384},
+				Bugs: ProtocolBugs{
+					ExpectMissingKeyShare: true,
+				},
+			},
+			// Cover HelloRetryRequest during an ECDHE-PSK resumption.
+			resumeSession: true,
+		})
+
+		tests = append(tests, testCase{
+			testType: serverTest,
+			name:     "TLS13-HelloRetryRequest-Server",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				MinVersion: VersionTLS13,
+				// Require a HelloRetryRequest for every curve.
+				DefaultCurves: []CurveID{},
+			},
+			// Cover HelloRetryRequest during an ECDHE-PSK resumption.
+			resumeSession: true,
+		})
+
+		// TODO(svaldez): Send data on early data once implemented.
+		tests = append(tests, testCase{
+			testType: clientTest,
+			name:     "TLS13-EarlyData-Client",
+			config: Config{
+				MaxVersion:       VersionTLS13,
+				MinVersion:       VersionTLS13,
+				MaxEarlyDataSize: 16384,
+			},
+			resumeSession: true,
+			flags: []string{
+				"-enable-early-data",
+				"-expect-early-data-info",
+				"-expect-accept-early-data",
+			},
+		})
+
+		tests = append(tests, testCase{
+			testType: serverTest,
+			name:     "TLS13-EarlyData-Server",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				MinVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					SendEarlyData:           [][]byte{{1, 2, 3, 4}},
+					ExpectEarlyDataAccepted: true,
+					ExpectHalfRTTData:       [][]byte{{254, 253, 252, 251}},
+				},
+			},
+			messageCount:  2,
+			resumeSession: true,
+			flags: []string{
+				"-enable-early-data",
+				"-expect-accept-early-data",
+			},
+		})
+	}
+
 	// TLS client auth.
 	tests = append(tests, testCase{
 		testType: clientTest,
+		name:     "ClientAuth-NoCertificate-Client",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			ClientAuth: RequestClientCert,
+		},
+	})
+	tests = append(tests, testCase{
+		testType: serverTest,
+		name:     "ClientAuth-NoCertificate-Server",
+		config: Config{
+			MaxVersion: VersionTLS12,
+		},
+		// Setting SSL_VERIFY_PEER allows anonymous clients.
+		flags: []string{"-verify-peer"},
+	})
+	if config.protocol == tls {
+		tests = append(tests, testCase{
+			testType: clientTest,
+			name:     "ClientAuth-NoCertificate-Client-SSL3",
+			config: Config{
+				MaxVersion: VersionSSL30,
+				ClientAuth: RequestClientCert,
+			},
+		})
+		tests = append(tests, testCase{
+			testType: serverTest,
+			name:     "ClientAuth-NoCertificate-Server-SSL3",
+			config: Config{
+				MaxVersion: VersionSSL30,
+			},
+			// Setting SSL_VERIFY_PEER allows anonymous clients.
+			flags: []string{"-verify-peer"},
+		})
+		tests = append(tests, testCase{
+			testType: clientTest,
+			name:     "ClientAuth-NoCertificate-Client-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				ClientAuth: RequestClientCert,
+			},
+		})
+		tests = append(tests, testCase{
+			testType: serverTest,
+			name:     "ClientAuth-NoCertificate-Server-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
+			},
+			// Setting SSL_VERIFY_PEER allows anonymous clients.
+			flags: []string{"-verify-peer"},
+		})
+	}
+	tests = append(tests, testCase{
+		testType: clientTest,
 		name:     "ClientAuth-RSA-Client",
 		config: Config{
+			MaxVersion: VersionTLS12,
+			ClientAuth: RequireAnyClientCert,
+		},
+		flags: []string{
+			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+			"-key-file", path.Join(*resourceDir, rsaKeyFile),
+		},
+	})
+	tests = append(tests, testCase{
+		testType: clientTest,
+		name:     "ClientAuth-RSA-Client-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
 			ClientAuth: RequireAnyClientCert,
 		},
 		flags: []string{
@@ -2732,62 +3680,132 @@
 		testType: clientTest,
 		name:     "ClientAuth-ECDSA-Client",
 		config: Config{
+			MaxVersion: VersionTLS12,
 			ClientAuth: RequireAnyClientCert,
 		},
 		flags: []string{
-			"-cert-file", path.Join(*resourceDir, ecdsaCertificateFile),
-			"-key-file", path.Join(*resourceDir, ecdsaKeyFile),
+			"-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
+			"-key-file", path.Join(*resourceDir, ecdsaP256KeyFile),
 		},
 	})
-	if async {
-		// Test async keys against each key exchange.
-		tests = append(tests, testCase{
-			testType: serverTest,
-			name:     "Basic-Server-RSA",
-			config: Config{
-				CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
-			},
-			flags: []string{
-				"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
-				"-key-file", path.Join(*resourceDir, rsaKeyFile),
-			},
-		})
-		tests = append(tests, testCase{
-			testType: serverTest,
-			name:     "Basic-Server-ECDHE-RSA",
-			config: Config{
-				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-			},
-			flags: []string{
-				"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
-				"-key-file", path.Join(*resourceDir, rsaKeyFile),
-			},
-		})
-		tests = append(tests, testCase{
-			testType: serverTest,
-			name:     "Basic-Server-ECDHE-ECDSA",
-			config: Config{
-				CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
-			},
-			flags: []string{
-				"-cert-file", path.Join(*resourceDir, ecdsaCertificateFile),
-				"-key-file", path.Join(*resourceDir, ecdsaKeyFile),
-			},
-		})
-	}
+	tests = append(tests, testCase{
+		testType: clientTest,
+		name:     "ClientAuth-ECDSA-Client-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			ClientAuth: RequireAnyClientCert,
+		},
+		flags: []string{
+			"-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
+			"-key-file", path.Join(*resourceDir, ecdsaP256KeyFile),
+		},
+	})
+	tests = append(tests, testCase{
+		testType: clientTest,
+		name:     "ClientAuth-NoCertificate-OldCallback",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			ClientAuth: RequestClientCert,
+		},
+		flags: []string{"-use-old-client-cert-callback"},
+	})
+	tests = append(tests, testCase{
+		testType: clientTest,
+		name:     "ClientAuth-NoCertificate-OldCallback-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			ClientAuth: RequestClientCert,
+		},
+		flags: []string{"-use-old-client-cert-callback"},
+	})
+	tests = append(tests, testCase{
+		testType: clientTest,
+		name:     "ClientAuth-OldCallback",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			ClientAuth: RequireAnyClientCert,
+		},
+		flags: []string{
+			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+			"-key-file", path.Join(*resourceDir, rsaKeyFile),
+			"-use-old-client-cert-callback",
+		},
+	})
+	tests = append(tests, testCase{
+		testType: clientTest,
+		name:     "ClientAuth-OldCallback-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			ClientAuth: RequireAnyClientCert,
+		},
+		flags: []string{
+			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+			"-key-file", path.Join(*resourceDir, rsaKeyFile),
+			"-use-old-client-cert-callback",
+		},
+	})
 	tests = append(tests, testCase{
 		testType: serverTest,
 		name:     "ClientAuth-Server",
 		config: Config{
+			MaxVersion:   VersionTLS12,
 			Certificates: []Certificate{rsaCertificate},
 		},
 		flags: []string{"-require-any-client-certificate"},
 	})
+	tests = append(tests, testCase{
+		testType: serverTest,
+		name:     "ClientAuth-Server-TLS13",
+		config: Config{
+			MaxVersion:   VersionTLS13,
+			Certificates: []Certificate{rsaCertificate},
+		},
+		flags: []string{"-require-any-client-certificate"},
+	})
+
+	// Test each key exchange on the server side for async keys.
+	tests = append(tests, testCase{
+		testType: serverTest,
+		name:     "Basic-Server-RSA",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
+		},
+		flags: []string{
+			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+			"-key-file", path.Join(*resourceDir, rsaKeyFile),
+		},
+	})
+	tests = append(tests, testCase{
+		testType: serverTest,
+		name:     "Basic-Server-ECDHE-RSA",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+		},
+		flags: []string{
+			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+			"-key-file", path.Join(*resourceDir, rsaKeyFile),
+		},
+	})
+	tests = append(tests, testCase{
+		testType: serverTest,
+		name:     "Basic-Server-ECDHE-ECDSA",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
+		},
+		flags: []string{
+			"-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
+			"-key-file", path.Join(*resourceDir, ecdsaP256KeyFile),
+		},
+	})
 
 	// No session ticket support; server doesn't send NewSessionTicket.
 	tests = append(tests, testCase{
 		name: "SessionTicketsDisabled-Client",
 		config: Config{
+			MaxVersion:             VersionTLS12,
 			SessionTicketsDisabled: true,
 		},
 	})
@@ -2795,6 +3813,7 @@
 		testType: serverTest,
 		name:     "SessionTicketsDisabled-Server",
 		config: Config{
+			MaxVersion:             VersionTLS12,
 			SessionTicketsDisabled: true,
 		},
 	})
@@ -2804,6 +3823,7 @@
 	tests = append(tests, testCase{
 		name: "EmptyPSKHint-Client",
 		config: Config{
+			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
 			PreSharedKey: []byte("secret"),
 		},
@@ -2813,15 +3833,20 @@
 		testType: serverTest,
 		name:     "EmptyPSKHint-Server",
 		config: Config{
+			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_PSK_WITH_AES_128_CBC_SHA},
 			PreSharedKey: []byte("secret"),
 		},
 		flags: []string{"-psk", "secret"},
 	})
 
+	// OCSP stapling tests.
 	tests = append(tests, testCase{
 		testType: clientTest,
 		name:     "OCSPStapling-Client",
+		config: Config{
+			MaxVersion: VersionTLS12,
+		},
 		flags: []string{
 			"-enable-ocsp-stapling",
 			"-expect-ocsp-response",
@@ -2830,10 +3855,39 @@
 		},
 		resumeSession: true,
 	})
-
 	tests = append(tests, testCase{
-		testType:             serverTest,
-		name:                 "OCSPStapling-Server",
+		testType: serverTest,
+		name:     "OCSPStapling-Server",
+		config: Config{
+			MaxVersion: VersionTLS12,
+		},
+		expectedOCSPResponse: testOCSPResponse,
+		flags: []string{
+			"-ocsp-response",
+			base64.StdEncoding.EncodeToString(testOCSPResponse),
+		},
+		resumeSession: true,
+	})
+	tests = append(tests, testCase{
+		testType: clientTest,
+		name:     "OCSPStapling-Client-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		flags: []string{
+			"-enable-ocsp-stapling",
+			"-expect-ocsp-response",
+			base64.StdEncoding.EncodeToString(testOCSPResponse),
+			"-verify-peer",
+		},
+		resumeSession: true,
+	})
+	tests = append(tests, testCase{
+		testType: serverTest,
+		name:     "OCSPStapling-Server-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
 		expectedOCSPResponse: testOCSPResponse,
 		flags: []string{
 			"-ocsp-response",
@@ -2842,50 +3896,113 @@
 		resumeSession: true,
 	})
 
-	tests = append(tests, testCase{
-		testType: clientTest,
-		name:     "CertificateVerificationSucceed",
-		flags: []string{
-			"-verify-peer",
-		},
-	})
+	// Certificate verification tests.
+	for _, vers := range tlsVersions {
+		if config.protocol == dtls && !vers.hasDTLS {
+			continue
+		}
+		for _, testType := range []testType{clientTest, serverTest} {
+			suffix := "-Client"
+			if testType == serverTest {
+				suffix = "-Server"
+			}
+			suffix += "-" + vers.name
 
-	tests = append(tests, testCase{
-		testType: clientTest,
-		name:     "CertificateVerificationFail",
-		flags: []string{
-			"-verify-fail",
-			"-verify-peer",
-		},
-		shouldFail:    true,
-		expectedError: ":CERTIFICATE_VERIFY_FAILED:",
-	})
+			flag := "-verify-peer"
+			if testType == serverTest {
+				flag = "-require-any-client-certificate"
+			}
 
-	tests = append(tests, testCase{
-		testType: clientTest,
-		name:     "CertificateVerificationSoftFail",
-		flags: []string{
-			"-verify-fail",
-			"-expect-verify-result",
-		},
-	})
+			tests = append(tests, testCase{
+				testType: testType,
+				name:     "CertificateVerificationSucceed" + suffix,
+				config: Config{
+					MaxVersion:   vers.version,
+					Certificates: []Certificate{rsaCertificate},
+				},
+				flags: []string{
+					flag,
+					"-expect-verify-result",
+				},
+				resumeSession: true,
+			})
+			tests = append(tests, testCase{
+				testType: testType,
+				name:     "CertificateVerificationFail" + suffix,
+				config: Config{
+					MaxVersion:   vers.version,
+					Certificates: []Certificate{rsaCertificate},
+				},
+				flags: []string{
+					flag,
+					"-verify-fail",
+				},
+				shouldFail:    true,
+				expectedError: ":CERTIFICATE_VERIFY_FAILED:",
+			})
+		}
 
-	if protocol == tls {
+		// By default, the client is in a soft fail mode where the peer
+		// certificate is verified but failures are non-fatal.
 		tests = append(tests, testCase{
-			name:        "Renegotiate-Client",
+			testType: clientTest,
+			name:     "CertificateVerificationSoftFail-" + vers.name,
+			config: Config{
+				MaxVersion:   vers.version,
+				Certificates: []Certificate{rsaCertificate},
+			},
+			flags: []string{
+				"-verify-fail",
+				"-expect-verify-result",
+			},
+			resumeSession: true,
+		})
+	}
+
+	tests = append(tests, testCase{
+		name:               "ShimSendAlert",
+		flags:              []string{"-send-alert"},
+		shimWritesFirst:    true,
+		shouldFail:         true,
+		expectedLocalError: "remote error: decompression failure",
+	})
+
+	if config.protocol == tls {
+		tests = append(tests, testCase{
+			name: "Renegotiate-Client",
+			config: Config{
+				MaxVersion: VersionTLS12,
+			},
 			renegotiate: 1,
 			flags: []string{
 				"-renegotiate-freely",
 				"-expect-total-renegotiations", "1",
 			},
 		})
+
+		tests = append(tests, testCase{
+			name: "SendHalfHelloRequest",
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					PackHelloRequestWithFinished: config.packHandshakeFlight,
+				},
+			},
+			sendHalfHelloRequest: true,
+			flags:                []string{"-renegotiate-ignore"},
+			shouldFail:           true,
+			expectedError:        ":UNEXPECTED_RECORD:",
+		})
+
 		// NPN on client and server; results in post-handshake message.
 		tests = append(tests, testCase{
 			name: "NPN-Client",
 			config: Config{
+				MaxVersion: VersionTLS12,
 				NextProtos: []string{"foo"},
 			},
 			flags:                 []string{"-select-next-proto", "foo"},
+			resumeSession:         true,
 			expectedNextProto:     "foo",
 			expectedNextProtoType: npn,
 		})
@@ -2893,12 +4010,14 @@
 			testType: serverTest,
 			name:     "NPN-Server",
 			config: Config{
+				MaxVersion: VersionTLS12,
 				NextProtos: []string{"bar"},
 			},
 			flags: []string{
 				"-advertise-npn", "\x03foo\x03bar\x03baz",
 				"-expect-next-proto", "bar",
 			},
+			resumeSession:         true,
 			expectedNextProto:     "bar",
 			expectedNextProtoType: npn,
 		})
@@ -2909,6 +4028,7 @@
 		tests = append(tests, testCase{
 			name: "FalseStart",
 			config: Config{
+				MaxVersion:   VersionTLS12,
 				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
 				NextProtos:   []string{"foo"},
 				Bugs: ProtocolBugs{
@@ -2927,6 +4047,7 @@
 		tests = append(tests, testCase{
 			name: "FalseStart-ALPN",
 			config: Config{
+				MaxVersion:   VersionTLS12,
 				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
 				NextProtos:   []string{"foo"},
 				Bugs: ProtocolBugs{
@@ -2941,25 +4062,11 @@
 			resumeSession:   true,
 		})
 
-		// Client does False Start but doesn't explicitly call
-		// SSL_connect.
-		tests = append(tests, testCase{
-			name: "FalseStart-Implicit",
-			config: Config{
-				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-				NextProtos:   []string{"foo"},
-			},
-			flags: []string{
-				"-implicit-handshake",
-				"-false-start",
-				"-advertise-alpn", "\x03foo",
-			},
-		})
-
 		// False Start without session tickets.
 		tests = append(tests, testCase{
 			name: "FalseStart-SessionTicketsDisabled",
 			config: Config{
+				MaxVersion:             VersionTLS12,
 				CipherSuites:           []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
 				NextProtos:             []string{"foo"},
 				SessionTicketsDisabled: true,
@@ -2982,37 +4089,99 @@
 				// Choose a cipher suite that does not involve
 				// elliptic curves, so no extensions are
 				// involved.
-				CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
+				MaxVersion:   VersionTLS12,
+				CipherSuites: []uint16{TLS_RSA_WITH_3DES_EDE_CBC_SHA},
 				Bugs: ProtocolBugs{
 					SendV2ClientHello: true,
 				},
 			},
 		})
 
-		// Client sends a Channel ID.
-		tests = append(tests, testCase{
-			name: "ChannelID-Client",
-			config: Config{
-				RequestChannelID: true,
-			},
-			flags:           []string{"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile)},
-			resumeSession:   true,
-			expectChannelID: true,
-		})
+		// Test Channel ID
+		for _, ver := range tlsVersions {
+			if ver.version < VersionTLS10 {
+				continue
+			}
+			// Client sends a Channel ID.
+			tests = append(tests, testCase{
+				name: "ChannelID-Client-" + ver.name,
+				config: Config{
+					MaxVersion:       ver.version,
+					RequestChannelID: true,
+				},
+				flags:           []string{"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile)},
+				resumeSession:   true,
+				expectChannelID: true,
+			})
 
-		// Server accepts a Channel ID.
+			// Server accepts a Channel ID.
+			tests = append(tests, testCase{
+				testType: serverTest,
+				name:     "ChannelID-Server-" + ver.name,
+				config: Config{
+					MaxVersion: ver.version,
+					ChannelID:  channelIDKey,
+				},
+				flags: []string{
+					"-expect-channel-id",
+					base64.StdEncoding.EncodeToString(channelIDBytes),
+				},
+				resumeSession:   true,
+				expectChannelID: true,
+			})
+
+			tests = append(tests, testCase{
+				testType: serverTest,
+				name:     "InvalidChannelIDSignature-" + ver.name,
+				config: Config{
+					MaxVersion: ver.version,
+					ChannelID:  channelIDKey,
+					Bugs: ProtocolBugs{
+						InvalidChannelIDSignature: true,
+					},
+				},
+				flags:         []string{"-enable-channel-id"},
+				shouldFail:    true,
+				expectedError: ":CHANNEL_ID_SIGNATURE_INVALID:",
+			})
+		}
+
+		// Channel ID and NPN at the same time, to ensure their relative
+		// ordering is correct.
+		tests = append(tests, testCase{
+			name: "ChannelID-NPN-Client",
+			config: Config{
+				MaxVersion:       VersionTLS12,
+				RequestChannelID: true,
+				NextProtos:       []string{"foo"},
+			},
+			flags: []string{
+				"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile),
+				"-select-next-proto", "foo",
+			},
+			resumeSession:         true,
+			expectChannelID:       true,
+			expectedNextProto:     "foo",
+			expectedNextProtoType: npn,
+		})
 		tests = append(tests, testCase{
 			testType: serverTest,
-			name:     "ChannelID-Server",
+			name:     "ChannelID-NPN-Server",
 			config: Config{
-				ChannelID: channelIDKey,
+				MaxVersion: VersionTLS12,
+				ChannelID:  channelIDKey,
+				NextProtos: []string{"bar"},
 			},
 			flags: []string{
 				"-expect-channel-id",
 				base64.StdEncoding.EncodeToString(channelIDBytes),
+				"-advertise-npn", "\x03foo\x03bar\x03baz",
+				"-expect-next-proto", "bar",
 			},
-			resumeSession:   true,
-			expectChannelID: true,
+			resumeSession:         true,
+			expectChannelID:       true,
+			expectedNextProto:     "bar",
+			expectedNextProtoType: npn,
 		})
 
 		// Bidirectional shutdown with the runner initiating.
@@ -3026,25 +4195,32 @@
 			flags: []string{"-check-close-notify"},
 		})
 
-		// Bidirectional shutdown with the shim initiating. The runner,
-		// in the meantime, sends garbage before the close_notify which
-		// the shim must ignore.
-		tests = append(tests, testCase{
-			name: "Shutdown-Shim",
-			config: Config{
-				Bugs: ProtocolBugs{
-					ExpectCloseNotify: true,
+		if !config.implicitHandshake {
+			// Bidirectional shutdown with the shim initiating. The runner,
+			// in the meantime, sends garbage before the close_notify which
+			// the shim must ignore. This test is disabled under implicit
+			// handshake tests because the shim never reads or writes.
+			tests = append(tests, testCase{
+				name: "Shutdown-Shim",
+				config: Config{
+					MaxVersion: VersionTLS12,
+					Bugs: ProtocolBugs{
+						ExpectCloseNotify: true,
+					},
 				},
-			},
-			shimShutsDown:     true,
-			sendEmptyRecords:  1,
-			sendWarningAlerts: 1,
-			flags:             []string{"-check-close-notify"},
-		})
+				shimShutsDown:     true,
+				sendEmptyRecords:  1,
+				sendWarningAlerts: 1,
+				flags:             []string{"-check-close-notify"},
+			})
+		}
 	} else {
+		// TODO(davidben): DTLS 1.3 will want a similar thing for
+		// HelloRetryRequest.
 		tests = append(tests, testCase{
 			name: "SkipHelloVerifyRequest",
 			config: Config{
+				MaxVersion: VersionTLS12,
 				Bugs: ProtocolBugs{
 					SkipHelloVerifyRequest: true,
 				},
@@ -3053,31 +4229,38 @@
 	}
 
 	for _, test := range tests {
-		test.protocol = protocol
-		if protocol == dtls {
+		test.protocol = config.protocol
+		if config.protocol == dtls {
 			test.name += "-DTLS"
 		}
-		if async {
+		if config.async {
 			test.name += "-Async"
 			test.flags = append(test.flags, "-async")
 		} else {
 			test.name += "-Sync"
 		}
-		if splitHandshake {
+		if config.splitHandshake {
 			test.name += "-SplitHandshakeRecords"
 			test.config.Bugs.MaxHandshakeRecordLength = 1
-			if protocol == dtls {
+			if config.protocol == dtls {
 				test.config.Bugs.MaxPacketLength = 256
 				test.flags = append(test.flags, "-mtu", "256")
 			}
 		}
+		if config.packHandshakeFlight {
+			test.name += "-PackHandshakeFlight"
+			test.config.Bugs.PackHandshakeFlight = true
+		}
+		if config.implicitHandshake {
+			test.name += "-ImplicitHandshake"
+			test.flags = append(test.flags, "-implicit-handshake")
+		}
 		testCases = append(testCases, test)
 	}
 }
 
 func addDDoSCallbackTests() {
 	// DDoS callback.
-
 	for _, resume := range []bool{false, true} {
 		suffix := "Resume"
 		if resume {
@@ -3085,8 +4268,20 @@
 		}
 
 		testCases = append(testCases, testCase{
-			testType:      serverTest,
-			name:          "Server-DDoS-OK-" + suffix,
+			testType: serverTest,
+			name:     "Server-DDoS-OK-" + suffix,
+			config: Config{
+				MaxVersion: VersionTLS12,
+			},
+			flags:         []string{"-install-ddos-callback"},
+			resumeSession: resume,
+		})
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "Server-DDoS-OK-" + suffix + "-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
+			},
 			flags:         []string{"-install-ddos-callback"},
 			resumeSession: resume,
 		})
@@ -3096,12 +4291,28 @@
 			failFlag = "-fail-second-ddos-callback"
 		}
 		testCases = append(testCases, testCase{
-			testType:      serverTest,
-			name:          "Server-DDoS-Reject-" + suffix,
-			flags:         []string{"-install-ddos-callback", failFlag},
-			resumeSession: resume,
-			shouldFail:    true,
-			expectedError: ":CONNECTION_REJECTED:",
+			testType: serverTest,
+			name:     "Server-DDoS-Reject-" + suffix,
+			config: Config{
+				MaxVersion: VersionTLS12,
+			},
+			flags:              []string{"-install-ddos-callback", failFlag},
+			resumeSession:      resume,
+			shouldFail:         true,
+			expectedError:      ":CONNECTION_REJECTED:",
+			expectedLocalError: "remote error: internal error",
+		})
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "Server-DDoS-Reject-" + suffix + "-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
+			},
+			flags:              []string{"-install-ddos-callback", failFlag},
+			resumeSession:      resume,
+			shouldFail:         true,
+			expectedError:      ":CONNECTION_REJECTED:",
+			expectedLocalError: "remote error: internal error",
 		})
 	}
 }
@@ -3114,6 +4325,7 @@
 			flags = append(flags, vers.flag)
 		}
 
+		// Test configuring the runner's maximum version.
 		for _, runnerVers := range tlsVersions {
 			protocols := []protocol{tls}
 			if runnerVers.hasDTLS && shimVers.hasDTLS {
@@ -3132,10 +4344,18 @@
 
 				shimVersFlag := strconv.Itoa(int(versionToWire(shimVers.version, protocol == dtls)))
 
+				// Determine the expected initial record-layer versions.
 				clientVers := shimVers.version
 				if clientVers > VersionTLS10 {
 					clientVers = VersionTLS10
 				}
+				clientVers = versionToWire(clientVers, protocol == dtls)
+				serverVers := expectedVersion
+				if expectedVersion >= VersionTLS13 {
+					serverVers = VersionTLS10
+				}
+				serverVers = versionToWire(serverVers, protocol == dtls)
+
 				testCases = append(testCases, testCase{
 					protocol: protocol,
 					testType: clientTest,
@@ -3170,7 +4390,7 @@
 					config: Config{
 						MaxVersion: runnerVers.version,
 						Bugs: ProtocolBugs{
-							ExpectInitialRecordVersion: expectedVersion,
+							ExpectInitialRecordVersion: serverVers,
 						},
 					},
 					flags:           flags,
@@ -3183,7 +4403,7 @@
 					config: Config{
 						MaxVersion: runnerVers.version,
 						Bugs: ProtocolBugs{
-							ExpectInitialRecordVersion: expectedVersion,
+							ExpectInitialRecordVersion: serverVers,
 						},
 					},
 					flags:           []string{"-max-version", shimVersFlag},
@@ -3192,6 +4412,250 @@
 			}
 		}
 	}
+
+	// Test the version extension at all versions.
+	for _, vers := range tlsVersions {
+		protocols := []protocol{tls}
+		if vers.hasDTLS {
+			protocols = append(protocols, dtls)
+		}
+		for _, protocol := range protocols {
+			suffix := vers.name
+			if protocol == dtls {
+				suffix += "-DTLS"
+			}
+
+			wireVersion := versionToWire(vers.version, protocol == dtls)
+			testCases = append(testCases, testCase{
+				protocol: protocol,
+				testType: serverTest,
+				name:     "VersionNegotiationExtension-" + suffix,
+				config: Config{
+					Bugs: ProtocolBugs{
+						SendSupportedVersions: []uint16{0x1111, wireVersion, 0x2222},
+					},
+				},
+				expectedVersion: vers.version,
+			})
+		}
+
+	}
+
+	// If all versions are unknown, negotiation fails.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "NoSupportedVersions",
+		config: Config{
+			Bugs: ProtocolBugs{
+				SendSupportedVersions: []uint16{0x1111},
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNSUPPORTED_PROTOCOL:",
+	})
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		testType: serverTest,
+		name:     "NoSupportedVersions-DTLS",
+		config: Config{
+			Bugs: ProtocolBugs{
+				SendSupportedVersions: []uint16{0x1111},
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNSUPPORTED_PROTOCOL:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ClientHelloVersionTooHigh",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendClientVersion:     0x0304,
+				OmitSupportedVersions: true,
+			},
+		},
+		expectedVersion: VersionTLS12,
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ConflictingVersionNegotiation",
+		config: Config{
+			Bugs: ProtocolBugs{
+				SendClientVersion:     VersionTLS12,
+				SendSupportedVersions: []uint16{VersionTLS11},
+			},
+		},
+		// The extension takes precedence over the ClientHello version.
+		expectedVersion: VersionTLS11,
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ConflictingVersionNegotiation-2",
+		config: Config{
+			Bugs: ProtocolBugs{
+				SendClientVersion:     VersionTLS11,
+				SendSupportedVersions: []uint16{VersionTLS12},
+			},
+		},
+		// The extension takes precedence over the ClientHello version.
+		expectedVersion: VersionTLS12,
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "RejectFinalTLS13",
+		config: Config{
+			Bugs: ProtocolBugs{
+				SendSupportedVersions: []uint16{VersionTLS13, VersionTLS12},
+			},
+		},
+		// We currently implement a draft TLS 1.3 version. Ensure that
+		// the true TLS 1.3 value is ignored for now.
+		expectedVersion: VersionTLS12,
+	})
+
+	// Test that the maximum version is selected regardless of the
+	// client-sent order.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "IgnoreClientVersionOrder",
+		config: Config{
+			Bugs: ProtocolBugs{
+				SendSupportedVersions: []uint16{VersionTLS12, tls13DraftVersion},
+			},
+		},
+		expectedVersion: VersionTLS13,
+	})
+
+	// Test for version tolerance.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "MinorVersionTolerance",
+		config: Config{
+			Bugs: ProtocolBugs{
+				SendClientVersion:     0x03ff,
+				OmitSupportedVersions: true,
+			},
+		},
+		expectedVersion: VersionTLS12,
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "MajorVersionTolerance",
+		config: Config{
+			Bugs: ProtocolBugs{
+				SendClientVersion:     0x0400,
+				OmitSupportedVersions: true,
+			},
+		},
+		// TLS 1.3 must be negotiated with the supported_versions
+		// extension, not ClientHello.version.
+		expectedVersion: VersionTLS12,
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "VersionTolerance-TLS13",
+		config: Config{
+			Bugs: ProtocolBugs{
+				// Although TLS 1.3 does not use
+				// ClientHello.version, it still tolerates high
+				// values there.
+				SendClientVersion: 0x0400,
+			},
+		},
+		expectedVersion: VersionTLS13,
+	})
+
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		testType: serverTest,
+		name:     "MinorVersionTolerance-DTLS",
+		config: Config{
+			Bugs: ProtocolBugs{
+				SendClientVersion:     0xfe00,
+				OmitSupportedVersions: true,
+			},
+		},
+		expectedVersion: VersionTLS12,
+	})
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		testType: serverTest,
+		name:     "MajorVersionTolerance-DTLS",
+		config: Config{
+			Bugs: ProtocolBugs{
+				SendClientVersion:     0xfdff,
+				OmitSupportedVersions: true,
+			},
+		},
+		expectedVersion: VersionTLS12,
+	})
+
+	// Test that versions below 3.0 are rejected.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "VersionTooLow",
+		config: Config{
+			Bugs: ProtocolBugs{
+				SendClientVersion:     0x0200,
+				OmitSupportedVersions: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNSUPPORTED_PROTOCOL:",
+	})
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		testType: serverTest,
+		name:     "VersionTooLow-DTLS",
+		config: Config{
+			Bugs: ProtocolBugs{
+				SendClientVersion: 0xffff,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNSUPPORTED_PROTOCOL:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "ServerBogusVersion",
+		config: Config{
+			Bugs: ProtocolBugs{
+				SendServerHelloVersion: 0x1234,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNSUPPORTED_PROTOCOL:",
+	})
+
+	// Test TLS 1.3's downgrade signal.
+	testCases = append(testCases, testCase{
+		name: "Downgrade-TLS12-Client",
+		config: Config{
+			Bugs: ProtocolBugs{
+				NegotiateVersion: VersionTLS12,
+			},
+		},
+		expectedVersion: VersionTLS12,
+		// TODO(davidben): This test should fail once TLS 1.3 is final
+		// and the fallback signal restored.
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "Downgrade-TLS12-Server",
+		config: Config{
+			Bugs: ProtocolBugs{
+				SendSupportedVersions: []uint16{VersionTLS12},
+			},
+		},
+		expectedVersion: VersionTLS12,
+		// TODO(davidben): This test should fail once TLS 1.3 is final
+		// and the fallback signal restored.
+	})
 }
 
 func addMinimumVersionTests() {
@@ -3216,18 +4680,13 @@
 
 				var expectedVersion uint16
 				var shouldFail bool
-				var expectedError string
-				var expectedLocalError string
+				var expectedError, expectedLocalError string
 				if runnerVers.version >= shimVers.version {
 					expectedVersion = runnerVers.version
 				} else {
 					shouldFail = true
 					expectedError = ":UNSUPPORTED_PROTOCOL:"
-					if runnerVers.version > VersionSSL30 {
-						expectedLocalError = "remote error: protocol version not supported"
-					} else {
-						expectedLocalError = "remote error: handshake failure"
-					}
+					expectedLocalError = "remote error: protocol version not supported"
 				}
 
 				testCases = append(testCases, testCase{
@@ -3236,6 +4695,13 @@
 					name:     "MinimumVersion-Client-" + suffix,
 					config: Config{
 						MaxVersion: runnerVers.version,
+						Bugs: ProtocolBugs{
+							// Ensure the server does not decline to
+							// select a version (versions extension) or
+							// cipher (some ciphers depend on versions).
+							NegotiateVersion:            runnerVers.version,
+							IgnorePeerCipherPreferences: shouldFail,
+						},
 					},
 					flags:              flags,
 					expectedVersion:    expectedVersion,
@@ -3249,6 +4715,13 @@
 					name:     "MinimumVersion-Client2-" + suffix,
 					config: Config{
 						MaxVersion: runnerVers.version,
+						Bugs: ProtocolBugs{
+							// Ensure the server does not decline to
+							// select a version (versions extension) or
+							// cipher (some ciphers depend on versions).
+							NegotiateVersion:            runnerVers.version,
+							IgnorePeerCipherPreferences: shouldFail,
+						},
 					},
 					flags:              []string{"-min-version", shimVersFlag},
 					expectedVersion:    expectedVersion,
@@ -3289,348 +4762,611 @@
 }
 
 func addExtensionTests() {
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "DuplicateExtensionClient",
-		config: Config{
-			Bugs: ProtocolBugs{
-				DuplicateExtension: true,
+	// TODO(davidben): Extensions, where applicable, all move their server
+	// halves to EncryptedExtensions in TLS 1.3. Duplicate each of these
+	// tests for both. Also test interaction with 0-RTT when implemented.
+
+	// Repeat extensions tests all versions except SSL 3.0.
+	for _, ver := range tlsVersions {
+		if ver.version == VersionSSL30 {
+			continue
+		}
+
+		// Test that duplicate extensions are rejected.
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			name:     "DuplicateExtensionClient-" + ver.name,
+			config: Config{
+				MaxVersion: ver.version,
+				Bugs: ProtocolBugs{
+					DuplicateExtension: true,
+				},
 			},
-		},
-		shouldFail:         true,
-		expectedLocalError: "remote error: error decoding message",
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "DuplicateExtensionServer",
-		config: Config{
-			Bugs: ProtocolBugs{
-				DuplicateExtension: true,
+			shouldFail:         true,
+			expectedLocalError: "remote error: error decoding message",
+		})
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "DuplicateExtensionServer-" + ver.name,
+			config: Config{
+				MaxVersion: ver.version,
+				Bugs: ProtocolBugs{
+					DuplicateExtension: true,
+				},
 			},
-		},
-		shouldFail:         true,
-		expectedLocalError: "remote error: error decoding message",
-	})
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "ServerNameExtensionClient",
-		config: Config{
-			Bugs: ProtocolBugs{
-				ExpectServerName: "example.com",
+			shouldFail:         true,
+			expectedLocalError: "remote error: error decoding message",
+		})
+
+		// Test SNI.
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			name:     "ServerNameExtensionClient-" + ver.name,
+			config: Config{
+				MaxVersion: ver.version,
+				Bugs: ProtocolBugs{
+					ExpectServerName: "example.com",
+				},
 			},
-		},
-		flags: []string{"-host-name", "example.com"},
-	})
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "ServerNameExtensionClientMismatch",
-		config: Config{
-			Bugs: ProtocolBugs{
-				ExpectServerName: "mismatch.com",
+			flags: []string{"-host-name", "example.com"},
+		})
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			name:     "ServerNameExtensionClientMismatch-" + ver.name,
+			config: Config{
+				MaxVersion: ver.version,
+				Bugs: ProtocolBugs{
+					ExpectServerName: "mismatch.com",
+				},
 			},
-		},
-		flags:              []string{"-host-name", "example.com"},
-		shouldFail:         true,
-		expectedLocalError: "tls: unexpected server name",
-	})
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "ServerNameExtensionClientMissing",
-		config: Config{
-			Bugs: ProtocolBugs{
-				ExpectServerName: "missing.com",
+			flags:              []string{"-host-name", "example.com"},
+			shouldFail:         true,
+			expectedLocalError: "tls: unexpected server name",
+		})
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			name:     "ServerNameExtensionClientMissing-" + ver.name,
+			config: Config{
+				MaxVersion: ver.version,
+				Bugs: ProtocolBugs{
+					ExpectServerName: "missing.com",
+				},
 			},
-		},
-		shouldFail:         true,
-		expectedLocalError: "tls: unexpected server name",
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "ServerNameExtensionServer",
-		config: Config{
-			ServerName: "example.com",
-		},
-		flags:         []string{"-expect-server-name", "example.com"},
-		resumeSession: true,
-	})
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "ALPNClient",
-		config: Config{
-			NextProtos: []string{"foo"},
-		},
-		flags: []string{
-			"-advertise-alpn", "\x03foo\x03bar\x03baz",
-			"-expect-alpn", "foo",
-		},
-		expectedNextProto:     "foo",
-		expectedNextProtoType: alpn,
-		resumeSession:         true,
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "ALPNServer",
-		config: Config{
-			NextProtos: []string{"foo", "bar", "baz"},
-		},
-		flags: []string{
-			"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
-			"-select-alpn", "foo",
-		},
-		expectedNextProto:     "foo",
-		expectedNextProtoType: alpn,
-		resumeSession:         true,
-	})
-	// Test that the server prefers ALPN over NPN.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "ALPNServer-Preferred",
-		config: Config{
-			NextProtos: []string{"foo", "bar", "baz"},
-		},
-		flags: []string{
-			"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
-			"-select-alpn", "foo",
-			"-advertise-npn", "\x03foo\x03bar\x03baz",
-		},
-		expectedNextProto:     "foo",
-		expectedNextProtoType: alpn,
-		resumeSession:         true,
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "ALPNServer-Preferred-Swapped",
-		config: Config{
-			NextProtos: []string{"foo", "bar", "baz"},
-			Bugs: ProtocolBugs{
-				SwapNPNAndALPN: true,
+			shouldFail:         true,
+			expectedLocalError: "tls: unexpected server name",
+		})
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			name:     "TolerateServerNameAck-" + ver.name,
+			config: Config{
+				MaxVersion: ver.version,
+				Bugs: ProtocolBugs{
+					SendServerNameAck: true,
+				},
 			},
-		},
-		flags: []string{
-			"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
-			"-select-alpn", "foo",
-			"-advertise-npn", "\x03foo\x03bar\x03baz",
-		},
-		expectedNextProto:     "foo",
-		expectedNextProtoType: alpn,
-		resumeSession:         true,
-	})
-	var emptyString string
-	testCases = append(testCases, testCase{
-		testType: clientTest,
-		name:     "ALPNClient-EmptyProtocolName",
-		config: Config{
-			NextProtos: []string{""},
-			Bugs: ProtocolBugs{
-				// A server returning an empty ALPN protocol
+			flags:         []string{"-host-name", "example.com"},
+			resumeSession: true,
+		})
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			name:     "UnsolicitedServerNameAck-" + ver.name,
+			config: Config{
+				MaxVersion: ver.version,
+				Bugs: ProtocolBugs{
+					SendServerNameAck: true,
+				},
+			},
+			shouldFail:         true,
+			expectedError:      ":UNEXPECTED_EXTENSION:",
+			expectedLocalError: "remote error: unsupported extension",
+		})
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "ServerNameExtensionServer-" + ver.name,
+			config: Config{
+				MaxVersion: ver.version,
+				ServerName: "example.com",
+			},
+			flags:         []string{"-expect-server-name", "example.com"},
+			resumeSession: true,
+		})
+
+		// Test ALPN.
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			name:     "ALPNClient-" + ver.name,
+			config: Config{
+				MaxVersion: ver.version,
+				NextProtos: []string{"foo"},
+			},
+			flags: []string{
+				"-advertise-alpn", "\x03foo\x03bar\x03baz",
+				"-expect-alpn", "foo",
+			},
+			expectedNextProto:     "foo",
+			expectedNextProtoType: alpn,
+			resumeSession:         true,
+		})
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			name:     "ALPNClient-Mismatch-" + ver.name,
+			config: Config{
+				MaxVersion: ver.version,
+				Bugs: ProtocolBugs{
+					SendALPN: "baz",
+				},
+			},
+			flags: []string{
+				"-advertise-alpn", "\x03foo\x03bar",
+			},
+			shouldFail:         true,
+			expectedError:      ":INVALID_ALPN_PROTOCOL:",
+			expectedLocalError: "remote error: illegal parameter",
+		})
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "ALPNServer-" + ver.name,
+			config: Config{
+				MaxVersion: ver.version,
+				NextProtos: []string{"foo", "bar", "baz"},
+			},
+			flags: []string{
+				"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
+				"-select-alpn", "foo",
+			},
+			expectedNextProto:     "foo",
+			expectedNextProtoType: alpn,
+			resumeSession:         true,
+		})
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "ALPNServer-Decline-" + ver.name,
+			config: Config{
+				MaxVersion: ver.version,
+				NextProtos: []string{"foo", "bar", "baz"},
+			},
+			flags:             []string{"-decline-alpn"},
+			expectNoNextProto: true,
+			resumeSession:     true,
+		})
+
+		// Test ALPN in async mode as well to ensure that extensions callbacks are only
+		// called once.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "ALPNServer-Async-" + ver.name,
+			config: Config{
+				MaxVersion: ver.version,
+				NextProtos: []string{"foo", "bar", "baz"},
+				// Prior to TLS 1.3, exercise the asynchronous session callback.
+				SessionTicketsDisabled: ver.version < VersionTLS13,
+			},
+			flags: []string{
+				"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
+				"-select-alpn", "foo",
+				"-async",
+			},
+			expectedNextProto:     "foo",
+			expectedNextProtoType: alpn,
+			resumeSession:         true,
+		})
+
+		var emptyString string
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			name:     "ALPNClient-EmptyProtocolName-" + ver.name,
+			config: Config{
+				MaxVersion: ver.version,
+				NextProtos: []string{""},
+				Bugs: ProtocolBugs{
+					// A server returning an empty ALPN protocol
+					// should be rejected.
+					ALPNProtocol: &emptyString,
+				},
+			},
+			flags: []string{
+				"-advertise-alpn", "\x03foo",
+			},
+			shouldFail:    true,
+			expectedError: ":PARSE_TLSEXT:",
+		})
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "ALPNServer-EmptyProtocolName-" + ver.name,
+			config: Config{
+				MaxVersion: ver.version,
+				// A ClientHello containing an empty ALPN protocol
 				// should be rejected.
-				ALPNProtocol: &emptyString,
+				NextProtos: []string{"foo", "", "baz"},
 			},
-		},
-		flags: []string{
-			"-advertise-alpn", "\x03foo",
-		},
-		shouldFail:    true,
-		expectedError: ":PARSE_TLSEXT:",
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "ALPNServer-EmptyProtocolName",
-		config: Config{
-			// A ClientHello containing an empty ALPN protocol
-			// should be rejected.
-			NextProtos: []string{"foo", "", "baz"},
-		},
-		flags: []string{
-			"-select-alpn", "foo",
-		},
-		shouldFail:    true,
-		expectedError: ":PARSE_TLSEXT:",
-	})
-	// Test that negotiating both NPN and ALPN is forbidden.
-	testCases = append(testCases, testCase{
-		name: "NegotiateALPNAndNPN",
-		config: Config{
-			NextProtos: []string{"foo", "bar", "baz"},
-			Bugs: ProtocolBugs{
-				NegotiateALPNAndNPN: true,
+			flags: []string{
+				"-select-alpn", "foo",
 			},
-		},
-		flags: []string{
-			"-advertise-alpn", "\x03foo",
-			"-select-next-proto", "foo",
-		},
-		shouldFail:    true,
-		expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
-	})
-	testCases = append(testCases, testCase{
-		name: "NegotiateALPNAndNPN-Swapped",
-		config: Config{
-			NextProtos: []string{"foo", "bar", "baz"},
-			Bugs: ProtocolBugs{
-				NegotiateALPNAndNPN: true,
-				SwapNPNAndALPN:      true,
+			shouldFail:    true,
+			expectedError: ":PARSE_TLSEXT:",
+		})
+
+		// Test NPN and the interaction with ALPN.
+		if ver.version < VersionTLS13 {
+			// Test that the server prefers ALPN over NPN.
+			testCases = append(testCases, testCase{
+				testType: serverTest,
+				name:     "ALPNServer-Preferred-" + ver.name,
+				config: Config{
+					MaxVersion: ver.version,
+					NextProtos: []string{"foo", "bar", "baz"},
+				},
+				flags: []string{
+					"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
+					"-select-alpn", "foo",
+					"-advertise-npn", "\x03foo\x03bar\x03baz",
+				},
+				expectedNextProto:     "foo",
+				expectedNextProtoType: alpn,
+				resumeSession:         true,
+			})
+			testCases = append(testCases, testCase{
+				testType: serverTest,
+				name:     "ALPNServer-Preferred-Swapped-" + ver.name,
+				config: Config{
+					MaxVersion: ver.version,
+					NextProtos: []string{"foo", "bar", "baz"},
+					Bugs: ProtocolBugs{
+						SwapNPNAndALPN: true,
+					},
+				},
+				flags: []string{
+					"-expect-advertised-alpn", "\x03foo\x03bar\x03baz",
+					"-select-alpn", "foo",
+					"-advertise-npn", "\x03foo\x03bar\x03baz",
+				},
+				expectedNextProto:     "foo",
+				expectedNextProtoType: alpn,
+				resumeSession:         true,
+			})
+
+			// Test that negotiating both NPN and ALPN is forbidden.
+			testCases = append(testCases, testCase{
+				name: "NegotiateALPNAndNPN-" + ver.name,
+				config: Config{
+					MaxVersion: ver.version,
+					NextProtos: []string{"foo", "bar", "baz"},
+					Bugs: ProtocolBugs{
+						NegotiateALPNAndNPN: true,
+					},
+				},
+				flags: []string{
+					"-advertise-alpn", "\x03foo",
+					"-select-next-proto", "foo",
+				},
+				shouldFail:    true,
+				expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
+			})
+			testCases = append(testCases, testCase{
+				name: "NegotiateALPNAndNPN-Swapped-" + ver.name,
+				config: Config{
+					MaxVersion: ver.version,
+					NextProtos: []string{"foo", "bar", "baz"},
+					Bugs: ProtocolBugs{
+						NegotiateALPNAndNPN: true,
+						SwapNPNAndALPN:      true,
+					},
+				},
+				flags: []string{
+					"-advertise-alpn", "\x03foo",
+					"-select-next-proto", "foo",
+				},
+				shouldFail:    true,
+				expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
+			})
+		}
+
+		// Test ticket behavior.
+
+		// Resume with a corrupt ticket.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "CorruptTicket-" + ver.name,
+			config: Config{
+				MaxVersion: ver.version,
+				Bugs: ProtocolBugs{
+					FilterTicket: func(in []byte) ([]byte, error) {
+						in[len(in)-1] ^= 1
+						return in, nil
+					},
+				},
 			},
-		},
-		flags: []string{
-			"-advertise-alpn", "\x03foo",
-			"-select-next-proto", "foo",
-		},
-		shouldFail:    true,
-		expectedError: ":NEGOTIATED_BOTH_NPN_AND_ALPN:",
-	})
-	// Test that NPN can be disabled with SSL_OP_DISABLE_NPN.
-	testCases = append(testCases, testCase{
-		name: "DisableNPN",
-		config: Config{
-			NextProtos: []string{"foo"},
-		},
-		flags: []string{
-			"-select-next-proto", "foo",
-			"-disable-npn",
-		},
-		expectNoNextProto: true,
-	})
-	// Resume with a corrupt ticket.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "CorruptTicket",
-		config: Config{
-			Bugs: ProtocolBugs{
-				CorruptTicket: true,
+			resumeSession:        true,
+			expectResumeRejected: true,
+		})
+		// Test the ticket callback, with and without renewal.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "TicketCallback-" + ver.name,
+			config: Config{
+				MaxVersion: ver.version,
 			},
-		},
-		resumeSession:        true,
-		expectResumeRejected: true,
-	})
-	// Test the ticket callback, with and without renewal.
-	testCases = append(testCases, testCase{
-		testType:      serverTest,
-		name:          "TicketCallback",
-		resumeSession: true,
-		flags:         []string{"-use-ticket-callback"},
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "TicketCallback-Renew",
-		config: Config{
-			Bugs: ProtocolBugs{
-				ExpectNewTicket: true,
+			resumeSession: true,
+			flags:         []string{"-use-ticket-callback"},
+		})
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "TicketCallback-Renew-" + ver.name,
+			config: Config{
+				MaxVersion: ver.version,
+				Bugs: ProtocolBugs{
+					ExpectNewTicket: true,
+				},
 			},
-		},
-		flags:         []string{"-use-ticket-callback", "-renew-ticket"},
-		resumeSession: true,
-	})
-	// Resume with an oversized session id.
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "OversizedSessionId",
-		config: Config{
-			Bugs: ProtocolBugs{
-				OversizedSessionId: true,
+			flags:         []string{"-use-ticket-callback", "-renew-ticket"},
+			resumeSession: true,
+		})
+
+		// Test that the ticket callback is only called once when everything before
+		// it in the ClientHello is asynchronous. This corrupts the ticket so
+		// certificate selection callbacks run.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "TicketCallback-SingleCall-" + ver.name,
+			config: Config{
+				MaxVersion: ver.version,
+				Bugs: ProtocolBugs{
+					FilterTicket: func(in []byte) ([]byte, error) {
+						in[len(in)-1] ^= 1
+						return in, nil
+					},
+				},
 			},
-		},
-		resumeSession: true,
-		shouldFail:    true,
-		expectedError: ":DECODE_ERROR:",
-	})
-	// Basic DTLS-SRTP tests. Include fake profiles to ensure they
-	// are ignored.
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		name:     "SRTP-Client",
-		config: Config{
-			SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
-		},
-		flags: []string{
-			"-srtp-profiles",
-			"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
-		},
-		expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
-	})
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		testType: serverTest,
-		name:     "SRTP-Server",
-		config: Config{
-			SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
-		},
-		flags: []string{
-			"-srtp-profiles",
-			"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
-		},
-		expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
-	})
-	// Test that the MKI is ignored.
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		testType: serverTest,
-		name:     "SRTP-Server-IgnoreMKI",
-		config: Config{
-			SRTPProtectionProfiles: []uint16{SRTP_AES128_CM_HMAC_SHA1_80},
-			Bugs: ProtocolBugs{
-				SRTPMasterKeyIdentifer: "bogus",
+			resumeSession:        true,
+			expectResumeRejected: true,
+			flags: []string{
+				"-use-ticket-callback",
+				"-async",
 			},
-		},
-		flags: []string{
-			"-srtp-profiles",
-			"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
-		},
-		expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
-	})
-	// Test that SRTP isn't negotiated on the server if there were
-	// no matching profiles.
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		testType: serverTest,
-		name:     "SRTP-Server-NoMatch",
-		config: Config{
-			SRTPProtectionProfiles: []uint16{100, 101, 102},
-		},
-		flags: []string{
-			"-srtp-profiles",
-			"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
-		},
-		expectedSRTPProtectionProfile: 0,
-	})
-	// Test that the server returning an invalid SRTP profile is
-	// flagged as an error by the client.
-	testCases = append(testCases, testCase{
-		protocol: dtls,
-		name:     "SRTP-Client-NoMatch",
-		config: Config{
-			Bugs: ProtocolBugs{
-				SendSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_32,
+		})
+
+		// Resume with various lengths of ticket session id.
+		if ver.version < VersionTLS13 {
+			testCases = append(testCases, testCase{
+				testType: serverTest,
+				name:     "TicketSessionIDLength-0-" + ver.name,
+				config: Config{
+					MaxVersion: ver.version,
+					Bugs: ProtocolBugs{
+						EmptyTicketSessionID: true,
+					},
+				},
+				resumeSession: true,
+			})
+			testCases = append(testCases, testCase{
+				testType: serverTest,
+				name:     "TicketSessionIDLength-16-" + ver.name,
+				config: Config{
+					MaxVersion: ver.version,
+					Bugs: ProtocolBugs{
+						TicketSessionIDLength: 16,
+					},
+				},
+				resumeSession: true,
+			})
+			testCases = append(testCases, testCase{
+				testType: serverTest,
+				name:     "TicketSessionIDLength-32-" + ver.name,
+				config: Config{
+					MaxVersion: ver.version,
+					Bugs: ProtocolBugs{
+						TicketSessionIDLength: 32,
+					},
+				},
+				resumeSession: true,
+			})
+			testCases = append(testCases, testCase{
+				testType: serverTest,
+				name:     "TicketSessionIDLength-33-" + ver.name,
+				config: Config{
+					MaxVersion: ver.version,
+					Bugs: ProtocolBugs{
+						TicketSessionIDLength: 33,
+					},
+				},
+				resumeSession: true,
+				shouldFail:    true,
+				// The maximum session ID length is 32.
+				expectedError: ":DECODE_ERROR:",
+			})
+		}
+
+		// Basic DTLS-SRTP tests. Include fake profiles to ensure they
+		// are ignored.
+		if ver.hasDTLS {
+			testCases = append(testCases, testCase{
+				protocol: dtls,
+				name:     "SRTP-Client-" + ver.name,
+				config: Config{
+					MaxVersion:             ver.version,
+					SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
+				},
+				flags: []string{
+					"-srtp-profiles",
+					"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
+				},
+				expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
+			})
+			testCases = append(testCases, testCase{
+				protocol: dtls,
+				testType: serverTest,
+				name:     "SRTP-Server-" + ver.name,
+				config: Config{
+					MaxVersion:             ver.version,
+					SRTPProtectionProfiles: []uint16{40, SRTP_AES128_CM_HMAC_SHA1_80, 42},
+				},
+				flags: []string{
+					"-srtp-profiles",
+					"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
+				},
+				expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
+			})
+			// Test that the MKI is ignored.
+			testCases = append(testCases, testCase{
+				protocol: dtls,
+				testType: serverTest,
+				name:     "SRTP-Server-IgnoreMKI-" + ver.name,
+				config: Config{
+					MaxVersion:             ver.version,
+					SRTPProtectionProfiles: []uint16{SRTP_AES128_CM_HMAC_SHA1_80},
+					Bugs: ProtocolBugs{
+						SRTPMasterKeyIdentifer: "bogus",
+					},
+				},
+				flags: []string{
+					"-srtp-profiles",
+					"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
+				},
+				expectedSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_80,
+			})
+			// Test that SRTP isn't negotiated on the server if there were
+			// no matching profiles.
+			testCases = append(testCases, testCase{
+				protocol: dtls,
+				testType: serverTest,
+				name:     "SRTP-Server-NoMatch-" + ver.name,
+				config: Config{
+					MaxVersion:             ver.version,
+					SRTPProtectionProfiles: []uint16{100, 101, 102},
+				},
+				flags: []string{
+					"-srtp-profiles",
+					"SRTP_AES128_CM_SHA1_80:SRTP_AES128_CM_SHA1_32",
+				},
+				expectedSRTPProtectionProfile: 0,
+			})
+			// Test that the server returning an invalid SRTP profile is
+			// flagged as an error by the client.
+			testCases = append(testCases, testCase{
+				protocol: dtls,
+				name:     "SRTP-Client-NoMatch-" + ver.name,
+				config: Config{
+					MaxVersion: ver.version,
+					Bugs: ProtocolBugs{
+						SendSRTPProtectionProfile: SRTP_AES128_CM_HMAC_SHA1_32,
+					},
+				},
+				flags: []string{
+					"-srtp-profiles",
+					"SRTP_AES128_CM_SHA1_80",
+				},
+				shouldFail:    true,
+				expectedError: ":BAD_SRTP_PROTECTION_PROFILE_LIST:",
+			})
+		}
+
+		// Test SCT list.
+		testCases = append(testCases, testCase{
+			name:     "SignedCertificateTimestampList-Client-" + ver.name,
+			testType: clientTest,
+			config: Config{
+				MaxVersion: ver.version,
 			},
-		},
-		flags: []string{
-			"-srtp-profiles",
-			"SRTP_AES128_CM_SHA1_80",
-		},
-		shouldFail:    true,
-		expectedError: ":BAD_SRTP_PROTECTION_PROFILE_LIST:",
-	})
-	// Test SCT list.
-	testCases = append(testCases, testCase{
-		name:     "SignedCertificateTimestampList-Client",
-		testType: clientTest,
-		flags: []string{
-			"-enable-signed-cert-timestamps",
-			"-expect-signed-cert-timestamps",
-			base64.StdEncoding.EncodeToString(testSCTList),
-		},
-		resumeSession: true,
-	})
-	testCases = append(testCases, testCase{
-		name:     "SignedCertificateTimestampList-Server",
-		testType: serverTest,
-		flags: []string{
-			"-signed-cert-timestamps",
-			base64.StdEncoding.EncodeToString(testSCTList),
-		},
-		expectedSCTList: testSCTList,
-		resumeSession:   true,
-	})
+			flags: []string{
+				"-enable-signed-cert-timestamps",
+				"-expect-signed-cert-timestamps",
+				base64.StdEncoding.EncodeToString(testSCTList),
+			},
+			resumeSession: true,
+		})
+
+		var differentSCTList []byte
+		differentSCTList = append(differentSCTList, testSCTList...)
+		differentSCTList[len(differentSCTList)-1] ^= 1
+
+		// The SCT extension did not specify that it must only be sent on resumption as it
+		// should have, so test that we tolerate but ignore it.
+		testCases = append(testCases, testCase{
+			name: "SendSCTListOnResume-" + ver.name,
+			config: Config{
+				MaxVersion: ver.version,
+				Bugs: ProtocolBugs{
+					SendSCTListOnResume: differentSCTList,
+				},
+			},
+			flags: []string{
+				"-enable-signed-cert-timestamps",
+				"-expect-signed-cert-timestamps",
+				base64.StdEncoding.EncodeToString(testSCTList),
+			},
+			resumeSession: true,
+		})
+
+		testCases = append(testCases, testCase{
+			name:     "SignedCertificateTimestampList-Server-" + ver.name,
+			testType: serverTest,
+			config: Config{
+				MaxVersion: ver.version,
+			},
+			flags: []string{
+				"-signed-cert-timestamps",
+				base64.StdEncoding.EncodeToString(testSCTList),
+			},
+			expectedSCTList: testSCTList,
+			resumeSession:   true,
+		})
+
+		emptySCTListCert := *testCerts[0].cert
+		emptySCTListCert.SignedCertificateTimestampList = []byte{0, 0}
+
+		// Test empty SCT list.
+		testCases = append(testCases, testCase{
+			name:     "SignedCertificateTimestampListEmpty-Client-" + ver.name,
+			testType: clientTest,
+			config: Config{
+				MaxVersion:   ver.version,
+				Certificates: []Certificate{emptySCTListCert},
+			},
+			flags: []string{
+				"-enable-signed-cert-timestamps",
+			},
+			shouldFail:    true,
+			expectedError: ":ERROR_PARSING_EXTENSION:",
+		})
+
+		emptySCTCert := *testCerts[0].cert
+		emptySCTCert.SignedCertificateTimestampList = []byte{0, 6, 0, 2, 1, 2, 0, 0}
+
+		// Test empty SCT in non-empty list.
+		testCases = append(testCases, testCase{
+			name:     "SignedCertificateTimestampListEmptySCT-Client-" + ver.name,
+			testType: clientTest,
+			config: Config{
+				MaxVersion:   ver.version,
+				Certificates: []Certificate{emptySCTCert},
+			},
+			flags: []string{
+				"-enable-signed-cert-timestamps",
+			},
+			shouldFail:    true,
+			expectedError: ":ERROR_PARSING_EXTENSION:",
+		})
+
+		// Test that certificate-related extensions are not sent unsolicited.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "UnsolicitedCertificateExtensions-" + ver.name,
+			config: Config{
+				MaxVersion: ver.version,
+				Bugs: ProtocolBugs{
+					NoOCSPStapling:                true,
+					NoSignedCertificateTimestamps: true,
+				},
+			},
+			flags: []string{
+				"-ocsp-response",
+				base64.StdEncoding.EncodeToString(testOCSPResponse),
+				"-signed-cert-timestamps",
+				base64.StdEncoding.EncodeToString(testSCTList),
+			},
+		})
+	}
+
 	testCases = append(testCases, testCase{
 		testType: clientTest,
 		name:     "ClientHelloPadding",
@@ -3693,6 +5429,7 @@
 				RequireRenegotiationInfo: true,
 			},
 		},
+		flags: []string{"-expect-secure-renegotiation"},
 	})
 	testCases = append(testCases, testCase{
 		testType: serverTest,
@@ -3705,12 +5442,256 @@
 				RequireRenegotiationInfo: true,
 			},
 		},
+		flags: []string{"-expect-secure-renegotiation"},
+	})
+
+	// Test that illegal extensions in TLS 1.3 are rejected by the client if
+	// in ServerHello.
+	testCases = append(testCases, testCase{
+		name: "NPN-Forbidden-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			NextProtos: []string{"foo"},
+			Bugs: ProtocolBugs{
+				NegotiateNPNAtAllVersions: true,
+			},
+		},
+		flags:         []string{"-select-next-proto", "foo"},
+		shouldFail:    true,
+		expectedError: ":ERROR_PARSING_EXTENSION:",
+	})
+	testCases = append(testCases, testCase{
+		name: "EMS-Forbidden-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				NegotiateEMSAtAllVersions: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":ERROR_PARSING_EXTENSION:",
+	})
+	testCases = append(testCases, testCase{
+		name: "RenegotiationInfo-Forbidden-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				NegotiateRenegotiationInfoAtAllVersions: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":ERROR_PARSING_EXTENSION:",
+	})
+	testCases = append(testCases, testCase{
+		name: "Ticket-Forbidden-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS12,
+		},
+		resumeConfig: &Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				AdvertiseTicketExtension: true,
+			},
+		},
+		resumeSession: true,
+		shouldFail:    true,
+		expectedError: ":ERROR_PARSING_EXTENSION:",
+	})
+
+	// Test that illegal extensions in TLS 1.3 are declined by the server if
+	// offered in ClientHello. The runner's server will fail if this occurs,
+	// so we exercise the offering path. (EMS and Renegotiation Info are
+	// implicit in every test.)
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "NPN-Declined-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			NextProtos: []string{"bar"},
+		},
+		flags: []string{"-advertise-npn", "\x03foo\x03bar\x03baz"},
+	})
+
+	// OpenSSL sends the status_request extension on resumption in TLS 1.2. Test that this is
+	// tolerated.
+	testCases = append(testCases, testCase{
+		name: "SendOCSPResponseOnResume-TLS12",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				SendOCSPResponseOnResume: []byte("bogus"),
+			},
+		},
+		flags: []string{
+			"-enable-ocsp-stapling",
+			"-expect-ocsp-response",
+			base64.StdEncoding.EncodeToString(testOCSPResponse),
+		},
+		resumeSession: true,
+	})
+
+	testCases = append(testCases, testCase{
+		name: "SendUnsolicitedOCSPOnCertificate-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendExtensionOnCertificate: testOCSPExtension,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_EXTENSION:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "SendUnsolicitedSCTOnCertificate-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendExtensionOnCertificate: testSCTExtension,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_EXTENSION:",
+	})
+
+	// Test that extensions on client certificates are never accepted.
+	testCases = append(testCases, testCase{
+		name:     "SendExtensionOnClientCertificate-TLS13",
+		testType: serverTest,
+		config: Config{
+			MaxVersion:   VersionTLS13,
+			Certificates: []Certificate{rsaCertificate},
+			Bugs: ProtocolBugs{
+				SendExtensionOnCertificate: testOCSPExtension,
+			},
+		},
+		flags: []string{
+			"-enable-ocsp-stapling",
+			"-require-any-client-certificate",
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_EXTENSION:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "SendUnknownExtensionOnCertificate-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendExtensionOnCertificate: []byte{0x00, 0x7f, 0, 0},
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_EXTENSION:",
+	})
+
+	var differentSCTList []byte
+	differentSCTList = append(differentSCTList, testSCTList...)
+	differentSCTList[len(differentSCTList)-1] ^= 1
+
+	// Test that extensions on intermediates are allowed but ignored.
+	testCases = append(testCases, testCase{
+		name: "IgnoreExtensionsOnIntermediates-TLS13",
+		config: Config{
+			MaxVersion:   VersionTLS13,
+			Certificates: []Certificate{rsaChainCertificate},
+			Bugs: ProtocolBugs{
+				// Send different values on the intermediate. This tests
+				// the intermediate's extensions do not override the
+				// leaf's.
+				SendOCSPOnIntermediates: []byte{1, 3, 3, 7},
+				SendSCTOnIntermediates:  differentSCTList,
+			},
+		},
+		flags: []string{
+			"-enable-ocsp-stapling",
+			"-expect-ocsp-response",
+			base64.StdEncoding.EncodeToString(testOCSPResponse),
+			"-enable-signed-cert-timestamps",
+			"-expect-signed-cert-timestamps",
+			base64.StdEncoding.EncodeToString(testSCTList),
+		},
+		resumeSession: true,
+	})
+
+	// Test that extensions are not sent on intermediates when configured
+	// only for a leaf.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SendNoExtensionsOnIntermediate-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				ExpectNoExtensionsOnIntermediate: true,
+			},
+		},
+		flags: []string{
+			"-cert-file", path.Join(*resourceDir, rsaChainCertificateFile),
+			"-key-file", path.Join(*resourceDir, rsaChainKeyFile),
+			"-ocsp-response",
+			base64.StdEncoding.EncodeToString(testOCSPResponse),
+			"-signed-cert-timestamps",
+			base64.StdEncoding.EncodeToString(testSCTList),
+		},
+	})
+
+	// Test that extensions are not sent on client certificates.
+	testCases = append(testCases, testCase{
+		name: "SendNoClientCertificateExtensions-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			ClientAuth: RequireAnyClientCert,
+		},
+		flags: []string{
+			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+			"-key-file", path.Join(*resourceDir, rsaKeyFile),
+			"-ocsp-response",
+			base64.StdEncoding.EncodeToString(testOCSPResponse),
+			"-signed-cert-timestamps",
+			base64.StdEncoding.EncodeToString(testSCTList),
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		name: "SendDuplicateExtensionsOnCerts-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendDuplicateCertExtensions: true,
+			},
+		},
+		flags: []string{
+			"-enable-ocsp-stapling",
+			"-enable-signed-cert-timestamps",
+		},
+		resumeSession: true,
+		shouldFail:    true,
+		expectedError: ":DUPLICATE_EXTENSION:",
+	})
+
+	testCases = append(testCases, testCase{
+		name:     "SignedCertificateTimestampListInvalid-Server",
+		testType: serverTest,
+		flags: []string{
+			"-signed-cert-timestamps",
+			base64.StdEncoding.EncodeToString([]byte{0, 0}),
+		},
+		shouldFail:    true,
+		expectedError: ":INVALID_SCT_LIST:",
 	})
 }
 
 func addResumptionVersionTests() {
 	for _, sessionVers := range tlsVersions {
 		for _, resumeVers := range tlsVersions {
+			// SSL 3.0 does not have tickets and TLS 1.3 does not
+			// have session IDs, so skip their cross-resumption
+			// tests.
+			if (sessionVers.version >= VersionTLS13 && resumeVers.version == VersionSSL30) ||
+				(resumeVers.version >= VersionTLS13 && sessionVers.version == VersionSSL30) {
+				continue
+			}
+
 			protocols := []protocol{tls}
 			if sessionVers.hasDTLS && resumeVers.hasDTLS {
 				protocols = append(protocols, dtls)
@@ -3727,32 +5708,43 @@
 						name:          "Resume-Client" + suffix,
 						resumeSession: true,
 						config: Config{
-							MaxVersion:   sessionVers.version,
-							CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+							MaxVersion: sessionVers.version,
+							Bugs: ProtocolBugs{
+								ExpectNoTLS12Session: sessionVers.version >= VersionTLS13,
+								ExpectNoTLS13PSK:     sessionVers.version < VersionTLS13,
+							},
 						},
 						expectedVersion:       sessionVers.version,
 						expectedResumeVersion: resumeVers.version,
 					})
 				} else {
+					error := ":OLD_SESSION_VERSION_NOT_RETURNED:"
+
+					// Offering a TLS 1.3 session sends an empty session ID, so
+					// there is no way to convince a non-lookahead client the
+					// session was resumed. It will appear to the client that a
+					// stray ChangeCipherSpec was sent.
+					if resumeVers.version < VersionTLS13 && sessionVers.version >= VersionTLS13 {
+						error = ":UNEXPECTED_RECORD:"
+					}
+
 					testCases = append(testCases, testCase{
 						protocol:      protocol,
 						name:          "Resume-Client-Mismatch" + suffix,
 						resumeSession: true,
 						config: Config{
-							MaxVersion:   sessionVers.version,
-							CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+							MaxVersion: sessionVers.version,
 						},
 						expectedVersion: sessionVers.version,
 						resumeConfig: &Config{
-							MaxVersion:   resumeVers.version,
-							CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+							MaxVersion: resumeVers.version,
 							Bugs: ProtocolBugs{
-								AllowSessionVersionMismatch: true,
+								AcceptAnySession: true,
 							},
 						},
 						expectedResumeVersion: resumeVers.version,
 						shouldFail:            true,
-						expectedError:         ":OLD_SESSION_VERSION_NOT_RETURNED:",
+						expectedError:         error,
 					})
 				}
 
@@ -3761,13 +5753,11 @@
 					name:          "Resume-Client-NoResume" + suffix,
 					resumeSession: true,
 					config: Config{
-						MaxVersion:   sessionVers.version,
-						CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+						MaxVersion: sessionVers.version,
 					},
 					expectedVersion: sessionVers.version,
 					resumeConfig: &Config{
-						MaxVersion:   resumeVers.version,
-						CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+						MaxVersion: resumeVers.version,
 					},
 					newSessionsOnResume:   true,
 					expectResumeRejected:  true,
@@ -3780,14 +5770,15 @@
 					name:          "Resume-Server" + suffix,
 					resumeSession: true,
 					config: Config{
-						MaxVersion:   sessionVers.version,
-						CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+						MaxVersion: sessionVers.version,
 					},
 					expectedVersion:      sessionVers.version,
 					expectResumeRejected: sessionVers.version != resumeVers.version,
 					resumeConfig: &Config{
-						MaxVersion:   resumeVers.version,
-						CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+						MaxVersion: resumeVers.version,
+						Bugs: ProtocolBugs{
+							SendBothTickets: true,
+						},
 					},
 					expectedResumeVersion: resumeVers.version,
 				})
@@ -3795,13 +5786,232 @@
 		}
 	}
 
+	// Make sure shim ticket mutations are functional.
+	testCases = append(testCases, testCase{
+		testType:      serverTest,
+		name:          "ShimTicketRewritable",
+		resumeSession: true,
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+			Bugs: ProtocolBugs{
+				FilterTicket: func(in []byte) ([]byte, error) {
+					in, err := SetShimTicketVersion(in, VersionTLS12)
+					if err != nil {
+						return nil, err
+					}
+					return SetShimTicketCipherSuite(in, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
+				},
+			},
+		},
+		flags: []string{
+			"-ticket-key",
+			base64.StdEncoding.EncodeToString(TestShimTicketKey),
+		},
+	})
+
+	// Resumptions are declined if the version does not match.
+	testCases = append(testCases, testCase{
+		testType:      serverTest,
+		name:          "Resume-Server-DeclineCrossVersion",
+		resumeSession: true,
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				ExpectNewTicket: true,
+				FilterTicket: func(in []byte) ([]byte, error) {
+					return SetShimTicketVersion(in, VersionTLS13)
+				},
+			},
+		},
+		flags: []string{
+			"-ticket-key",
+			base64.StdEncoding.EncodeToString(TestShimTicketKey),
+		},
+		expectResumeRejected: true,
+	})
+
+	testCases = append(testCases, testCase{
+		testType:      serverTest,
+		name:          "Resume-Server-DeclineCrossVersion-TLS13",
+		resumeSession: true,
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				FilterTicket: func(in []byte) ([]byte, error) {
+					return SetShimTicketVersion(in, VersionTLS12)
+				},
+			},
+		},
+		flags: []string{
+			"-ticket-key",
+			base64.StdEncoding.EncodeToString(TestShimTicketKey),
+		},
+		expectResumeRejected: true,
+	})
+
+	// Resumptions are declined if the cipher is invalid or disabled.
+	testCases = append(testCases, testCase{
+		testType:      serverTest,
+		name:          "Resume-Server-DeclineBadCipher",
+		resumeSession: true,
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				ExpectNewTicket: true,
+				FilterTicket: func(in []byte) ([]byte, error) {
+					return SetShimTicketCipherSuite(in, TLS_AES_128_GCM_SHA256)
+				},
+			},
+		},
+		flags: []string{
+			"-ticket-key",
+			base64.StdEncoding.EncodeToString(TestShimTicketKey),
+		},
+		expectResumeRejected: true,
+	})
+
+	testCases = append(testCases, testCase{
+		testType:      serverTest,
+		name:          "Resume-Server-DeclineBadCipher-2",
+		resumeSession: true,
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				ExpectNewTicket: true,
+				FilterTicket: func(in []byte) ([]byte, error) {
+					return SetShimTicketCipherSuite(in, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384)
+				},
+			},
+		},
+		flags: []string{
+			"-cipher", "AES128",
+			"-ticket-key",
+			base64.StdEncoding.EncodeToString(TestShimTicketKey),
+		},
+		expectResumeRejected: true,
+	})
+
+	// Sessions are not resumed if they do not use the preferred cipher.
+	testCases = append(testCases, testCase{
+		testType:      serverTest,
+		name:          "Resume-Server-CipherNotPreferred",
+		resumeSession: true,
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				ExpectNewTicket: true,
+				FilterTicket: func(in []byte) ([]byte, error) {
+					return SetShimTicketCipherSuite(in, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA)
+				},
+			},
+		},
+		flags: []string{
+			"-ticket-key",
+			base64.StdEncoding.EncodeToString(TestShimTicketKey),
+		},
+		shouldFail:           false,
+		expectResumeRejected: true,
+	})
+
+	// TLS 1.3 allows sessions to be resumed at a different cipher if their
+	// PRF hashes match, but BoringSSL will always decline such resumptions.
+	testCases = append(testCases, testCase{
+		testType:      serverTest,
+		name:          "Resume-Server-CipherNotPreferred-TLS13",
+		resumeSession: true,
+		config: Config{
+			MaxVersion:   VersionTLS13,
+			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256, TLS_AES_128_GCM_SHA256},
+			Bugs: ProtocolBugs{
+				FilterTicket: func(in []byte) ([]byte, error) {
+					// If the client (runner) offers ChaCha20-Poly1305 first, the
+					// server (shim) always prefers it. Switch it to AES-GCM.
+					return SetShimTicketCipherSuite(in, TLS_AES_128_GCM_SHA256)
+				},
+			},
+		},
+		flags: []string{
+			"-ticket-key",
+			base64.StdEncoding.EncodeToString(TestShimTicketKey),
+		},
+		shouldFail:           false,
+		expectResumeRejected: true,
+	})
+
+	// Sessions may not be resumed if they contain another version's cipher.
+	testCases = append(testCases, testCase{
+		testType:      serverTest,
+		name:          "Resume-Server-DeclineBadCipher-TLS13",
+		resumeSession: true,
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				FilterTicket: func(in []byte) ([]byte, error) {
+					return SetShimTicketCipherSuite(in, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
+				},
+			},
+		},
+		flags: []string{
+			"-ticket-key",
+			base64.StdEncoding.EncodeToString(TestShimTicketKey),
+		},
+		expectResumeRejected: true,
+	})
+
+	// If the client does not offer the cipher from the session, decline to
+	// resume. Clients are forbidden from doing this, but BoringSSL selects
+	// the cipher first, so we only decline.
+	testCases = append(testCases, testCase{
+		testType:      serverTest,
+		name:          "Resume-Server-UnofferedCipher",
+		resumeSession: true,
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
+		},
+		resumeConfig: &Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
+			Bugs: ProtocolBugs{
+				SendCipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+			},
+		},
+		expectResumeRejected: true,
+	})
+
+	// In TLS 1.3, clients may advertise a cipher list which does not
+	// include the selected cipher. Test that we tolerate this. Servers may
+	// resume at another cipher if the PRF matches and are not doing 0-RTT, but
+	// BoringSSL will always decline.
+	testCases = append(testCases, testCase{
+		testType:      serverTest,
+		name:          "Resume-Server-UnofferedCipher-TLS13",
+		resumeSession: true,
+		config: Config{
+			MaxVersion:   VersionTLS13,
+			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256},
+		},
+		resumeConfig: &Config{
+			MaxVersion:   VersionTLS13,
+			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256},
+			Bugs: ProtocolBugs{
+				SendCipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
+			},
+		},
+		expectResumeRejected: true,
+	})
+
+	// Sessions may not be resumed at a different cipher.
 	testCases = append(testCases, testCase{
 		name:          "Resume-Client-CipherMismatch",
 		resumeSession: true,
 		config: Config{
+			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
 		},
 		resumeConfig: &Config{
+			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
 			Bugs: ProtocolBugs{
 				SendCipherSuite: TLS_RSA_WITH_AES_128_CBC_SHA,
@@ -3810,13 +6020,140 @@
 		shouldFail:    true,
 		expectedError: ":OLD_SESSION_CIPHER_NOT_RETURNED:",
 	})
+
+	// Session resumption in TLS 1.3 may change the cipher suite if the PRF
+	// matches.
+	testCases = append(testCases, testCase{
+		name:          "Resume-Client-CipherMismatch-TLS13",
+		resumeSession: true,
+		config: Config{
+			MaxVersion:   VersionTLS13,
+			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
+		},
+		resumeConfig: &Config{
+			MaxVersion:   VersionTLS13,
+			CipherSuites: []uint16{TLS_CHACHA20_POLY1305_SHA256},
+		},
+	})
+
+	// Session resumption in TLS 1.3 is forbidden if the PRF does not match.
+	testCases = append(testCases, testCase{
+		name:          "Resume-Client-PRFMismatch-TLS13",
+		resumeSession: true,
+		config: Config{
+			MaxVersion:   VersionTLS13,
+			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
+		},
+		resumeConfig: &Config{
+			MaxVersion:   VersionTLS13,
+			CipherSuites: []uint16{TLS_AES_128_GCM_SHA256},
+			Bugs: ProtocolBugs{
+				SendCipherSuite: TLS_AES_256_GCM_SHA384,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":OLD_SESSION_PRF_HASH_MISMATCH:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType:      serverTest,
+		name:          "Resume-Server-BinderWrongLength",
+		resumeSession: true,
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendShortPSKBinder: true,
+			},
+		},
+		shouldFail:         true,
+		expectedLocalError: "remote error: error decrypting message",
+		expectedError:      ":DIGEST_CHECK_FAILED:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType:      serverTest,
+		name:          "Resume-Server-NoPSKBinder",
+		resumeSession: true,
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendNoPSKBinder: true,
+			},
+		},
+		shouldFail:         true,
+		expectedLocalError: "remote error: error decoding message",
+		expectedError:      ":DECODE_ERROR:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType:      serverTest,
+		name:          "Resume-Server-ExtraPSKBinder",
+		resumeSession: true,
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendExtraPSKBinder: true,
+			},
+		},
+		shouldFail:         true,
+		expectedLocalError: "remote error: illegal parameter",
+		expectedError:      ":PSK_IDENTITY_BINDER_COUNT_MISMATCH:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType:      serverTest,
+		name:          "Resume-Server-ExtraIdentityNoBinder",
+		resumeSession: true,
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				ExtraPSKIdentity: true,
+			},
+		},
+		shouldFail:         true,
+		expectedLocalError: "remote error: illegal parameter",
+		expectedError:      ":PSK_IDENTITY_BINDER_COUNT_MISMATCH:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType:      serverTest,
+		name:          "Resume-Server-InvalidPSKBinder",
+		resumeSession: true,
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendInvalidPSKBinder: true,
+			},
+		},
+		shouldFail:         true,
+		expectedLocalError: "remote error: error decrypting message",
+		expectedError:      ":DIGEST_CHECK_FAILED:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType:      serverTest,
+		name:          "Resume-Server-PSKBinderFirstExtension",
+		resumeSession: true,
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				PSKBinderFirst: true,
+			},
+		},
+		shouldFail:         true,
+		expectedLocalError: "remote error: illegal parameter",
+		expectedError:      ":PRE_SHARED_KEY_MUST_BE_LAST:",
+	})
 }
 
 func addRenegotiationTests() {
 	// Servers cannot renegotiate.
 	testCases = append(testCases, testCase{
-		testType:           serverTest,
-		name:               "Renegotiate-Server-Forbidden",
+		testType: serverTest,
+		name:     "Renegotiate-Server-Forbidden",
+		config: Config{
+			MaxVersion: VersionTLS12,
+		},
 		renegotiate:        1,
 		shouldFail:         true,
 		expectedError:      ":NO_RENEGOTIATION:",
@@ -3828,6 +6165,7 @@
 		testType: serverTest,
 		name:     "Renegotiate-Server-NoExt",
 		config: Config{
+			MaxVersion: VersionTLS12,
 			Bugs: ProtocolBugs{
 				NoRenegotiationInfo:      true,
 				RequireRenegotiationInfo: true,
@@ -3842,6 +6180,7 @@
 		testType: serverTest,
 		name:     "Renegotiate-Server-NoExt-SCSV",
 		config: Config{
+			MaxVersion: VersionTLS12,
 			Bugs: ProtocolBugs{
 				NoRenegotiationInfo:      true,
 				SendRenegotiationSCSV:    true,
@@ -3852,6 +6191,7 @@
 	testCases = append(testCases, testCase{
 		name: "Renegotiate-Client",
 		config: Config{
+			MaxVersion: VersionTLS12,
 			Bugs: ProtocolBugs{
 				FailIfResumeOnRenego: true,
 			},
@@ -3860,12 +6200,14 @@
 		flags: []string{
 			"-renegotiate-freely",
 			"-expect-total-renegotiations", "1",
+			"-expect-secure-renegotiation",
 		},
 	})
 	testCases = append(testCases, testCase{
 		name:        "Renegotiate-Client-EmptyExt",
 		renegotiate: 1,
 		config: Config{
+			MaxVersion: VersionTLS12,
 			Bugs: ProtocolBugs{
 				EmptyRenegotiationInfo: true,
 			},
@@ -3878,6 +6220,7 @@
 		name:        "Renegotiate-Client-BadExt",
 		renegotiate: 1,
 		config: Config{
+			MaxVersion: VersionTLS12,
 			Bugs: ProtocolBugs{
 				BadRenegotiationInfo: true,
 			},
@@ -3890,6 +6233,7 @@
 		name:        "Renegotiate-Client-Downgrade",
 		renegotiate: 1,
 		config: Config{
+			MaxVersion: VersionTLS12,
 			Bugs: ProtocolBugs{
 				NoRenegotiationInfoAfterInitial: true,
 			},
@@ -3902,6 +6246,7 @@
 		name:        "Renegotiate-Client-Upgrade",
 		renegotiate: 1,
 		config: Config{
+			MaxVersion: VersionTLS12,
 			Bugs: ProtocolBugs{
 				NoRenegotiationInfoInInitial: true,
 			},
@@ -3914,6 +6259,7 @@
 		name:        "Renegotiate-Client-NoExt-Allowed",
 		renegotiate: 1,
 		config: Config{
+			MaxVersion: VersionTLS12,
 			Bugs: ProtocolBugs{
 				NoRenegotiationInfo: true,
 			},
@@ -3921,13 +6267,18 @@
 		flags: []string{
 			"-renegotiate-freely",
 			"-expect-total-renegotiations", "1",
+			"-expect-no-secure-renegotiation",
 		},
 	})
+
+	// Test that the server may switch ciphers on renegotiation without
+	// problems.
 	testCases = append(testCases, testCase{
 		name:        "Renegotiate-Client-SwitchCiphers",
 		renegotiate: 1,
 		config: Config{
-			CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_RSA_WITH_3DES_EDE_CBC_SHA},
 		},
 		renegotiateCiphers: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
 		flags: []string{
@@ -3939,14 +6290,38 @@
 		name:        "Renegotiate-Client-SwitchCiphers2",
 		renegotiate: 1,
 		config: Config{
+			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
 		},
-		renegotiateCiphers: []uint16{TLS_RSA_WITH_RC4_128_SHA},
+		renegotiateCiphers: []uint16{TLS_RSA_WITH_3DES_EDE_CBC_SHA},
 		flags: []string{
 			"-renegotiate-freely",
 			"-expect-total-renegotiations", "1",
 		},
 	})
+
+	// Test that the server may not switch versions on renegotiation.
+	testCases = append(testCases, testCase{
+		name: "Renegotiate-Client-SwitchVersion",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			// Pick a cipher which exists at both versions.
+			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_CBC_SHA},
+			Bugs: ProtocolBugs{
+				NegotiateVersionOnRenego: VersionTLS11,
+				// Avoid failing early at the record layer.
+				SendRecordVersion: VersionTLS12,
+			},
+		},
+		renegotiate: 1,
+		flags: []string{
+			"-renegotiate-freely",
+			"-expect-total-renegotiations", "1",
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_SSL_VERSION:",
+	})
+
 	testCases = append(testCases, testCase{
 		name:        "Renegotiate-SameClientVersion",
 		renegotiate: 1,
@@ -3965,6 +6340,7 @@
 		name:        "Renegotiate-FalseStart",
 		renegotiate: 1,
 		config: Config{
+			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
 			NextProtos:   []string{"foo"},
 		},
@@ -3979,14 +6355,20 @@
 
 	// Client-side renegotiation controls.
 	testCases = append(testCases, testCase{
-		name:               "Renegotiate-Client-Forbidden-1",
+		name: "Renegotiate-Client-Forbidden-1",
+		config: Config{
+			MaxVersion: VersionTLS12,
+		},
 		renegotiate:        1,
 		shouldFail:         true,
 		expectedError:      ":NO_RENEGOTIATION:",
 		expectedLocalError: "remote error: no renegotiation",
 	})
 	testCases = append(testCases, testCase{
-		name:        "Renegotiate-Client-Once-1",
+		name: "Renegotiate-Client-Once-1",
+		config: Config{
+			MaxVersion: VersionTLS12,
+		},
 		renegotiate: 1,
 		flags: []string{
 			"-renegotiate-once",
@@ -3994,7 +6376,10 @@
 		},
 	})
 	testCases = append(testCases, testCase{
-		name:        "Renegotiate-Client-Freely-1",
+		name: "Renegotiate-Client-Freely-1",
+		config: Config{
+			MaxVersion: VersionTLS12,
+		},
 		renegotiate: 1,
 		flags: []string{
 			"-renegotiate-freely",
@@ -4002,7 +6387,10 @@
 		},
 	})
 	testCases = append(testCases, testCase{
-		name:               "Renegotiate-Client-Once-2",
+		name: "Renegotiate-Client-Once-2",
+		config: Config{
+			MaxVersion: VersionTLS12,
+		},
 		renegotiate:        2,
 		flags:              []string{"-renegotiate-once"},
 		shouldFail:         true,
@@ -4010,7 +6398,10 @@
 		expectedLocalError: "remote error: no renegotiation",
 	})
 	testCases = append(testCases, testCase{
-		name:        "Renegotiate-Client-Freely-2",
+		name: "Renegotiate-Client-Freely-2",
+		config: Config{
+			MaxVersion: VersionTLS12,
+		},
 		renegotiate: 2,
 		flags: []string{
 			"-renegotiate-freely",
@@ -4020,6 +6411,7 @@
 	testCases = append(testCases, testCase{
 		name: "Renegotiate-Client-NoIgnore",
 		config: Config{
+			MaxVersion: VersionTLS12,
 			Bugs: ProtocolBugs{
 				SendHelloRequestBeforeEveryAppDataRecord: true,
 			},
@@ -4030,6 +6422,7 @@
 	testCases = append(testCases, testCase{
 		name: "Renegotiate-Client-Ignore",
 		config: Config{
+			MaxVersion: VersionTLS12,
 			Bugs: ProtocolBugs{
 				SendHelloRequestBeforeEveryAppDataRecord: true,
 			},
@@ -4039,6 +6432,183 @@
 			"-expect-total-renegotiations", "0",
 		},
 	})
+
+	// Renegotiation is not allowed at SSL 3.0.
+	testCases = append(testCases, testCase{
+		name: "Renegotiate-Client-SSL3",
+		config: Config{
+			MaxVersion: VersionSSL30,
+		},
+		renegotiate: 1,
+		flags: []string{
+			"-renegotiate-freely",
+			"-expect-total-renegotiations", "1",
+		},
+		shouldFail:         true,
+		expectedError:      ":NO_RENEGOTIATION:",
+		expectedLocalError: "remote error: no renegotiation",
+	})
+
+	// Renegotiation is not allowed when there is an unfinished write.
+	testCases = append(testCases, testCase{
+		name: "Renegotiate-Client-UnfinishedWrite",
+		config: Config{
+			MaxVersion: VersionTLS12,
+		},
+		renegotiate: 1,
+		flags: []string{
+			"-async",
+			"-renegotiate-freely",
+			"-read-with-unfinished-write",
+		},
+		shouldFail:    true,
+		expectedError: ":NO_RENEGOTIATION:",
+		// We do not successfully send the no_renegotiation alert in
+		// this case. https://crbug.com/boringssl/130
+	})
+
+	// We reject stray HelloRequests during the handshake in TLS 1.2.
+	testCases = append(testCases, testCase{
+		name: "StrayHelloRequest",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				SendHelloRequestBeforeEveryHandshakeMessage: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_MESSAGE:",
+	})
+	testCases = append(testCases, testCase{
+		name: "StrayHelloRequest-Packed",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				PackHandshakeFlight:                         true,
+				SendHelloRequestBeforeEveryHandshakeMessage: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_MESSAGE:",
+	})
+
+	// Test renegotiation works if HelloRequest and server Finished come in
+	// the same record.
+	testCases = append(testCases, testCase{
+		name: "Renegotiate-Client-Packed",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				PackHandshakeFlight:          true,
+				PackHelloRequestWithFinished: true,
+			},
+		},
+		renegotiate: 1,
+		flags: []string{
+			"-renegotiate-freely",
+			"-expect-total-renegotiations", "1",
+		},
+	})
+
+	// Renegotiation is forbidden in TLS 1.3.
+	testCases = append(testCases, testCase{
+		name: "Renegotiate-Client-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendHelloRequestBeforeEveryAppDataRecord: true,
+			},
+		},
+		flags: []string{
+			"-renegotiate-freely",
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_MESSAGE:",
+	})
+
+	// Stray HelloRequests during the handshake are forbidden in TLS 1.3.
+	testCases = append(testCases, testCase{
+		name: "StrayHelloRequest-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendHelloRequestBeforeEveryHandshakeMessage: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_MESSAGE:",
+	})
+
+	// The renegotiation_info extension is not sent in TLS 1.3, but TLS 1.3
+	// always reads as supporting it, regardless of whether it was
+	// negotiated.
+	testCases = append(testCases, testCase{
+		name: "AlwaysReportRenegotiationInfo-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				NoRenegotiationInfo: true,
+			},
+		},
+		flags: []string{
+			"-expect-secure-renegotiation",
+		},
+	})
+
+	// Certificates may not change on renegotiation.
+	testCases = append(testCases, testCase{
+		name: "Renegotiation-CertificateChange",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			Certificates: []Certificate{rsaCertificate},
+			Bugs: ProtocolBugs{
+				RenegotiationCertificate: &rsaChainCertificate,
+			},
+		},
+		renegotiate:   1,
+		flags:         []string{"-renegotiate-freely"},
+		shouldFail:    true,
+		expectedError: ":SERVER_CERT_CHANGED:",
+	})
+	testCases = append(testCases, testCase{
+		name: "Renegotiation-CertificateChange-2",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			Certificates: []Certificate{rsaCertificate},
+			Bugs: ProtocolBugs{
+				RenegotiationCertificate: &rsa1024Certificate,
+			},
+		},
+		renegotiate:   1,
+		flags:         []string{"-renegotiate-freely"},
+		shouldFail:    true,
+		expectedError: ":SERVER_CERT_CHANGED:",
+	})
+
+	// We do not negotiate ALPN after the initial handshake. This is
+	// error-prone and only risks bugs in consumers.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "Renegotiation-ForbidALPN",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				// Forcibly negotiate ALPN on both initial and
+				// renegotiation handshakes. The test stack will
+				// internally check the client does not offer
+				// it.
+				SendALPN: "foo",
+			},
+		},
+		flags: []string{
+			"-advertise-alpn", "\x03foo\x03bar\x03baz",
+			"-expect-alpn", "foo",
+			"-renegotiate-freely",
+		},
+		renegotiate:   1,
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_EXTENSION:",
+	})
 }
 
 func addDTLSReplayTests() {
@@ -4082,140 +6652,534 @@
 	})
 }
 
-var testHashes = []struct {
+var testSignatureAlgorithms = []struct {
 	name string
-	id   uint8
+	id   signatureAlgorithm
+	cert testCert
 }{
-	{"SHA1", hashSHA1},
-	{"SHA224", hashSHA224},
-	{"SHA256", hashSHA256},
-	{"SHA384", hashSHA384},
-	{"SHA512", hashSHA512},
+	{"RSA-PKCS1-SHA1", signatureRSAPKCS1WithSHA1, testCertRSA},
+	{"RSA-PKCS1-SHA256", signatureRSAPKCS1WithSHA256, testCertRSA},
+	{"RSA-PKCS1-SHA384", signatureRSAPKCS1WithSHA384, testCertRSA},
+	{"RSA-PKCS1-SHA512", signatureRSAPKCS1WithSHA512, testCertRSA},
+	{"ECDSA-SHA1", signatureECDSAWithSHA1, testCertECDSAP256},
+	{"ECDSA-P256-SHA256", signatureECDSAWithP256AndSHA256, testCertECDSAP256},
+	{"ECDSA-P384-SHA384", signatureECDSAWithP384AndSHA384, testCertECDSAP384},
+	{"ECDSA-P521-SHA512", signatureECDSAWithP521AndSHA512, testCertECDSAP521},
+	{"RSA-PSS-SHA256", signatureRSAPSSWithSHA256, testCertRSA},
+	{"RSA-PSS-SHA384", signatureRSAPSSWithSHA384, testCertRSA},
+	{"RSA-PSS-SHA512", signatureRSAPSSWithSHA512, testCertRSA},
+	// Tests for key types prior to TLS 1.2.
+	{"RSA", 0, testCertRSA},
+	{"ECDSA", 0, testCertECDSAP256},
 }
 
-func addSigningHashTests() {
-	// Make sure each hash works. Include some fake hashes in the list and
-	// ensure they're ignored.
-	for _, hash := range testHashes {
-		testCases = append(testCases, testCase{
-			name: "SigningHash-ClientAuth-" + hash.name,
-			config: Config{
-				ClientAuth: RequireAnyClientCert,
-				SignatureAndHashes: []signatureAndHash{
-					{signatureRSA, 42},
-					{signatureRSA, hash.id},
-					{signatureRSA, 255},
-				},
-			},
-			flags: []string{
-				"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
-				"-key-file", path.Join(*resourceDir, rsaKeyFile),
-			},
-		})
+const fakeSigAlg1 signatureAlgorithm = 0x2a01
+const fakeSigAlg2 signatureAlgorithm = 0xff01
 
-		testCases = append(testCases, testCase{
-			testType: serverTest,
-			name:     "SigningHash-ServerKeyExchange-Sign-" + hash.name,
-			config: Config{
-				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-				SignatureAndHashes: []signatureAndHash{
-					{signatureRSA, 42},
-					{signatureRSA, hash.id},
-					{signatureRSA, 255},
-				},
-			},
-		})
-
-		testCases = append(testCases, testCase{
-			name: "SigningHash-ServerKeyExchange-Verify-" + hash.name,
-			config: Config{
-				CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-				SignatureAndHashes: []signatureAndHash{
-					{signatureRSA, 42},
-					{signatureRSA, hash.id},
-					{signatureRSA, 255},
-				},
-			},
-			flags: []string{"-expect-server-key-exchange-hash", strconv.Itoa(int(hash.id))},
-		})
+func addSignatureAlgorithmTests() {
+	// Not all ciphers involve a signature. Advertise a list which gives all
+	// versions a signing cipher.
+	signingCiphers := []uint16{
+		TLS_AES_128_GCM_SHA256,
+		TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
+		TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+		TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+		TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+	}
+	if *includeDHE {
+		signingCiphers = append(signingCiphers, TLS_DHE_RSA_WITH_AES_128_CBC_SHA)
 	}
 
-	// Test that hash resolution takes the signature type into account.
+	var allAlgorithms []signatureAlgorithm
+	for _, alg := range testSignatureAlgorithms {
+		if alg.id != 0 {
+			allAlgorithms = append(allAlgorithms, alg.id)
+		}
+	}
+
+	// Make sure each signature algorithm works. Include some fake values in
+	// the list and ensure they're ignored.
+	for _, alg := range testSignatureAlgorithms {
+		for _, ver := range tlsVersions {
+			if (ver.version < VersionTLS12) != (alg.id == 0) {
+				continue
+			}
+
+			// TODO(davidben): Support ECDSA in SSL 3.0 in Go for testing
+			// or remove it in C.
+			if ver.version == VersionSSL30 && alg.cert != testCertRSA {
+				continue
+			}
+
+			var shouldSignFail, shouldVerifyFail bool
+			// ecdsa_sha1 does not exist in TLS 1.3.
+			if ver.version >= VersionTLS13 && alg.id == signatureECDSAWithSHA1 {
+				shouldSignFail = true
+				shouldVerifyFail = true
+			}
+			// RSA-PKCS1 does not exist in TLS 1.3.
+			if ver.version == VersionTLS13 && hasComponent(alg.name, "PKCS1") {
+				shouldSignFail = true
+				shouldVerifyFail = true
+			}
+
+			// BoringSSL will sign SHA-1 and SHA-512 with ECDSA but not accept them.
+			if alg.id == signatureECDSAWithSHA1 || alg.id == signatureECDSAWithP521AndSHA512 {
+				shouldVerifyFail = true
+			}
+
+			var signError, verifyError string
+			if shouldSignFail {
+				signError = ":NO_COMMON_SIGNATURE_ALGORITHMS:"
+			}
+			if shouldVerifyFail {
+				verifyError = ":WRONG_SIGNATURE_TYPE:"
+			}
+
+			suffix := "-" + alg.name + "-" + ver.name
+
+			testCases = append(testCases, testCase{
+				name: "ClientAuth-Sign" + suffix,
+				config: Config{
+					MaxVersion: ver.version,
+					ClientAuth: RequireAnyClientCert,
+					VerifySignatureAlgorithms: []signatureAlgorithm{
+						fakeSigAlg1,
+						alg.id,
+						fakeSigAlg2,
+					},
+				},
+				flags: []string{
+					"-cert-file", path.Join(*resourceDir, getShimCertificate(alg.cert)),
+					"-key-file", path.Join(*resourceDir, getShimKey(alg.cert)),
+					"-enable-all-curves",
+				},
+				shouldFail:                     shouldSignFail,
+				expectedError:                  signError,
+				expectedPeerSignatureAlgorithm: alg.id,
+			})
+
+			testCases = append(testCases, testCase{
+				testType: serverTest,
+				name:     "ClientAuth-Verify" + suffix,
+				config: Config{
+					MaxVersion:   ver.version,
+					Certificates: []Certificate{getRunnerCertificate(alg.cert)},
+					SignSignatureAlgorithms: []signatureAlgorithm{
+						alg.id,
+					},
+					Bugs: ProtocolBugs{
+						SkipECDSACurveCheck:          shouldVerifyFail,
+						IgnoreSignatureVersionChecks: shouldVerifyFail,
+						// Some signature algorithms may not be advertised.
+						IgnorePeerSignatureAlgorithmPreferences: shouldVerifyFail,
+					},
+				},
+				flags: []string{
+					"-require-any-client-certificate",
+					"-expect-peer-signature-algorithm", strconv.Itoa(int(alg.id)),
+					"-enable-all-curves",
+				},
+				// Resume the session to assert the peer signature
+				// algorithm is reported on both handshakes.
+				resumeSession: !shouldVerifyFail,
+				shouldFail:    shouldVerifyFail,
+				expectedError: verifyError,
+			})
+
+			// No signing cipher for SSL 3.0.
+			if *includeDHE || ver.version > VersionSSL30 {
+				testCases = append(testCases, testCase{
+					testType: serverTest,
+					name:     "ServerAuth-Sign" + suffix,
+					config: Config{
+						MaxVersion:   ver.version,
+						CipherSuites: signingCiphers,
+						VerifySignatureAlgorithms: []signatureAlgorithm{
+							fakeSigAlg1,
+							alg.id,
+							fakeSigAlg2,
+						},
+					},
+					flags: []string{
+						"-cert-file", path.Join(*resourceDir, getShimCertificate(alg.cert)),
+						"-key-file", path.Join(*resourceDir, getShimKey(alg.cert)),
+						"-enable-all-curves",
+					},
+					shouldFail:                     shouldSignFail,
+					expectedError:                  signError,
+					expectedPeerSignatureAlgorithm: alg.id,
+				})
+			}
+
+			testCases = append(testCases, testCase{
+				name: "ServerAuth-Verify" + suffix,
+				config: Config{
+					MaxVersion:   ver.version,
+					Certificates: []Certificate{getRunnerCertificate(alg.cert)},
+					CipherSuites: signingCiphers,
+					SignSignatureAlgorithms: []signatureAlgorithm{
+						alg.id,
+					},
+					Bugs: ProtocolBugs{
+						SkipECDSACurveCheck:          shouldVerifyFail,
+						IgnoreSignatureVersionChecks: shouldVerifyFail,
+						// Some signature algorithms may not be advertised.
+						IgnorePeerSignatureAlgorithmPreferences: shouldVerifyFail,
+					},
+				},
+				flags: []string{
+					"-expect-peer-signature-algorithm", strconv.Itoa(int(alg.id)),
+					"-enable-all-curves",
+				},
+				// Resume the session to assert the peer signature
+				// algorithm is reported on both handshakes.
+				resumeSession: !shouldVerifyFail,
+				shouldFail:    shouldVerifyFail,
+				expectedError: verifyError,
+			})
+
+			if !shouldVerifyFail {
+				testCases = append(testCases, testCase{
+					testType: serverTest,
+					name:     "ClientAuth-InvalidSignature" + suffix,
+					config: Config{
+						MaxVersion:   ver.version,
+						Certificates: []Certificate{getRunnerCertificate(alg.cert)},
+						SignSignatureAlgorithms: []signatureAlgorithm{
+							alg.id,
+						},
+						Bugs: ProtocolBugs{
+							InvalidSignature: true,
+						},
+					},
+					flags: []string{
+						"-require-any-client-certificate",
+						"-enable-all-curves",
+					},
+					shouldFail:    true,
+					expectedError: ":BAD_SIGNATURE:",
+				})
+
+				testCases = append(testCases, testCase{
+					name: "ServerAuth-InvalidSignature" + suffix,
+					config: Config{
+						MaxVersion:   ver.version,
+						Certificates: []Certificate{getRunnerCertificate(alg.cert)},
+						CipherSuites: signingCiphers,
+						SignSignatureAlgorithms: []signatureAlgorithm{
+							alg.id,
+						},
+						Bugs: ProtocolBugs{
+							InvalidSignature: true,
+						},
+					},
+					flags:         []string{"-enable-all-curves"},
+					shouldFail:    true,
+					expectedError: ":BAD_SIGNATURE:",
+				})
+			}
+
+			if ver.version >= VersionTLS12 && !shouldSignFail {
+				testCases = append(testCases, testCase{
+					name: "ClientAuth-Sign-Negotiate" + suffix,
+					config: Config{
+						MaxVersion:                ver.version,
+						ClientAuth:                RequireAnyClientCert,
+						VerifySignatureAlgorithms: allAlgorithms,
+					},
+					flags: []string{
+						"-cert-file", path.Join(*resourceDir, getShimCertificate(alg.cert)),
+						"-key-file", path.Join(*resourceDir, getShimKey(alg.cert)),
+						"-enable-all-curves",
+						"-signing-prefs", strconv.Itoa(int(alg.id)),
+					},
+					expectedPeerSignatureAlgorithm: alg.id,
+				})
+
+				testCases = append(testCases, testCase{
+					testType: serverTest,
+					name:     "ServerAuth-Sign-Negotiate" + suffix,
+					config: Config{
+						MaxVersion:                ver.version,
+						CipherSuites:              signingCiphers,
+						VerifySignatureAlgorithms: allAlgorithms,
+					},
+					flags: []string{
+						"-cert-file", path.Join(*resourceDir, getShimCertificate(alg.cert)),
+						"-key-file", path.Join(*resourceDir, getShimKey(alg.cert)),
+						"-enable-all-curves",
+						"-signing-prefs", strconv.Itoa(int(alg.id)),
+					},
+					expectedPeerSignatureAlgorithm: alg.id,
+				})
+			}
+		}
+	}
+
+	// Test that algorithm selection takes the key type into account.
 	testCases = append(testCases, testCase{
-		name: "SigningHash-ClientAuth-SignatureType",
+		name: "ClientAuth-SignatureType",
 		config: Config{
 			ClientAuth: RequireAnyClientCert,
-			SignatureAndHashes: []signatureAndHash{
-				{signatureECDSA, hashSHA512},
-				{signatureRSA, hashSHA384},
-				{signatureECDSA, hashSHA1},
+			MaxVersion: VersionTLS12,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureECDSAWithP521AndSHA512,
+				signatureRSAPKCS1WithSHA384,
+				signatureECDSAWithSHA1,
 			},
 		},
 		flags: []string{
 			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
 			"-key-file", path.Join(*resourceDir, rsaKeyFile),
 		},
+		expectedPeerSignatureAlgorithm: signatureRSAPKCS1WithSHA384,
 	})
 
 	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "SigningHash-ServerKeyExchange-SignatureType",
-		config: Config{
-			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-			SignatureAndHashes: []signatureAndHash{
-				{signatureECDSA, hashSHA512},
-				{signatureRSA, hashSHA384},
-				{signatureECDSA, hashSHA1},
-			},
-		},
-	})
-
-	// Test that, if the list is missing, the peer falls back to SHA-1.
-	testCases = append(testCases, testCase{
-		name: "SigningHash-ClientAuth-Fallback",
+		name: "ClientAuth-SignatureType-TLS13",
 		config: Config{
 			ClientAuth: RequireAnyClientCert,
-			SignatureAndHashes: []signatureAndHash{
-				{signatureRSA, hashSHA1},
-			},
-			Bugs: ProtocolBugs{
-				NoSignatureAndHashes: true,
+			MaxVersion: VersionTLS13,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureECDSAWithP521AndSHA512,
+				signatureRSAPKCS1WithSHA384,
+				signatureRSAPSSWithSHA384,
+				signatureECDSAWithSHA1,
 			},
 		},
 		flags: []string{
 			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
 			"-key-file", path.Join(*resourceDir, rsaKeyFile),
 		},
+		expectedPeerSignatureAlgorithm: signatureRSAPSSWithSHA384,
 	})
 
 	testCases = append(testCases, testCase{
 		testType: serverTest,
-		name:     "SigningHash-ServerKeyExchange-Fallback",
+		name:     "ServerAuth-SignatureType",
 		config: Config{
+			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-			SignatureAndHashes: []signatureAndHash{
-				{signatureRSA, hashSHA1},
-			},
-			Bugs: ProtocolBugs{
-				NoSignatureAndHashes: true,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureECDSAWithP521AndSHA512,
+				signatureRSAPKCS1WithSHA384,
+				signatureECDSAWithSHA1,
 			},
 		},
+		expectedPeerSignatureAlgorithm: signatureRSAPKCS1WithSHA384,
 	})
 
-	// Test that hash preferences are enforced. BoringSSL defaults to
-	// rejecting MD5 signatures.
 	testCases = append(testCases, testCase{
 		testType: serverTest,
-		name:     "SigningHash-ClientAuth-Enforced",
+		name:     "ServerAuth-SignatureType-TLS13",
 		config: Config{
+			MaxVersion: VersionTLS13,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureECDSAWithP521AndSHA512,
+				signatureRSAPKCS1WithSHA384,
+				signatureRSAPSSWithSHA384,
+				signatureECDSAWithSHA1,
+			},
+		},
+		expectedPeerSignatureAlgorithm: signatureRSAPSSWithSHA384,
+	})
+
+	// Test that signature verification takes the key type into account.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "Verify-ClientAuth-SignatureType",
+		config: Config{
+			MaxVersion:   VersionTLS12,
 			Certificates: []Certificate{rsaCertificate},
-			SignatureAndHashes: []signatureAndHash{
-				{signatureRSA, hashMD5},
-				// Advertise SHA-1 so the handshake will
-				// proceed, but the shim's preferences will be
-				// ignored in CertificateVerify generation, so
-				// MD5 will be chosen.
-				{signatureRSA, hashSHA1},
+			SignSignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPKCS1WithSHA256,
+			},
+			Bugs: ProtocolBugs{
+				SendSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
+			},
+		},
+		flags: []string{
+			"-require-any-client-certificate",
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_SIGNATURE_TYPE:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "Verify-ClientAuth-SignatureType-TLS13",
+		config: Config{
+			MaxVersion:   VersionTLS13,
+			Certificates: []Certificate{rsaCertificate},
+			SignSignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPSSWithSHA256,
+			},
+			Bugs: ProtocolBugs{
+				SendSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
+			},
+		},
+		flags: []string{
+			"-require-any-client-certificate",
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_SIGNATURE_TYPE:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "Verify-ServerAuth-SignatureType",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+			SignSignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPKCS1WithSHA256,
+			},
+			Bugs: ProtocolBugs{
+				SendSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_SIGNATURE_TYPE:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "Verify-ServerAuth-SignatureType-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			SignSignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPSSWithSHA256,
+			},
+			Bugs: ProtocolBugs{
+				SendSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_SIGNATURE_TYPE:",
+	})
+
+	// Test that, if the list is missing, the peer falls back to SHA-1 in
+	// TLS 1.2, but not TLS 1.3.
+	testCases = append(testCases, testCase{
+		name: "ClientAuth-SHA1-Fallback-RSA",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			ClientAuth: RequireAnyClientCert,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPKCS1WithSHA1,
+			},
+			Bugs: ProtocolBugs{
+				NoSignatureAlgorithms: true,
+			},
+		},
+		flags: []string{
+			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+			"-key-file", path.Join(*resourceDir, rsaKeyFile),
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ServerAuth-SHA1-Fallback-RSA",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPKCS1WithSHA1,
+			},
+			Bugs: ProtocolBugs{
+				NoSignatureAlgorithms: true,
+			},
+		},
+		flags: []string{
+			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+			"-key-file", path.Join(*resourceDir, rsaKeyFile),
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		name: "ClientAuth-SHA1-Fallback-ECDSA",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			ClientAuth: RequireAnyClientCert,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureECDSAWithSHA1,
+			},
+			Bugs: ProtocolBugs{
+				NoSignatureAlgorithms: true,
+			},
+		},
+		flags: []string{
+			"-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
+			"-key-file", path.Join(*resourceDir, ecdsaP256KeyFile),
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ServerAuth-SHA1-Fallback-ECDSA",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureECDSAWithSHA1,
+			},
+			Bugs: ProtocolBugs{
+				NoSignatureAlgorithms: true,
+			},
+		},
+		flags: []string{
+			"-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
+			"-key-file", path.Join(*resourceDir, ecdsaP256KeyFile),
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		name: "ClientAuth-NoFallback-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			ClientAuth: RequireAnyClientCert,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPKCS1WithSHA1,
+			},
+			Bugs: ProtocolBugs{
+				NoSignatureAlgorithms: true,
+			},
+		},
+		flags: []string{
+			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+			"-key-file", path.Join(*resourceDir, rsaKeyFile),
+		},
+		shouldFail: true,
+		// An empty CertificateRequest signature algorithm list is a
+		// syntax error in TLS 1.3.
+		expectedError:      ":DECODE_ERROR:",
+		expectedLocalError: "remote error: error decoding message",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ServerAuth-NoFallback-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPKCS1WithSHA1,
+			},
+			Bugs: ProtocolBugs{
+				NoSignatureAlgorithms: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
+	})
+
+	// Test that hash preferences are enforced. BoringSSL does not implement
+	// MD5 signatures.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ClientAuth-Enforced",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			Certificates: []Certificate{rsaCertificate},
+			SignSignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPKCS1WithMD5,
 			},
 			Bugs: ProtocolBugs{
 				IgnorePeerSignatureAlgorithmPreferences: true,
@@ -4227,11 +7191,12 @@
 	})
 
 	testCases = append(testCases, testCase{
-		name: "SigningHash-ServerKeyExchange-Enforced",
+		name: "ServerAuth-Enforced",
 		config: Config{
+			MaxVersion:   VersionTLS12,
 			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-			SignatureAndHashes: []signatureAndHash{
-				{signatureRSA, hashMD5},
+			SignSignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPKCS1WithMD5,
 			},
 			Bugs: ProtocolBugs{
 				IgnorePeerSignatureAlgorithmPreferences: true,
@@ -4240,72 +7205,311 @@
 		shouldFail:    true,
 		expectedError: ":WRONG_SIGNATURE_TYPE:",
 	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ClientAuth-Enforced-TLS13",
+		config: Config{
+			MaxVersion:   VersionTLS13,
+			Certificates: []Certificate{rsaCertificate},
+			SignSignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPKCS1WithMD5,
+			},
+			Bugs: ProtocolBugs{
+				IgnorePeerSignatureAlgorithmPreferences: true,
+				IgnoreSignatureVersionChecks:            true,
+			},
+		},
+		flags:         []string{"-require-any-client-certificate"},
+		shouldFail:    true,
+		expectedError: ":WRONG_SIGNATURE_TYPE:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "ServerAuth-Enforced-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			SignSignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPKCS1WithMD5,
+			},
+			Bugs: ProtocolBugs{
+				IgnorePeerSignatureAlgorithmPreferences: true,
+				IgnoreSignatureVersionChecks:            true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_SIGNATURE_TYPE:",
+	})
 
 	// Test that the agreed upon digest respects the client preferences and
 	// the server digests.
 	testCases = append(testCases, testCase{
-		name: "Agree-Digest-Fallback",
+		name: "NoCommonAlgorithms-Digests",
 		config: Config{
+			MaxVersion: VersionTLS12,
 			ClientAuth: RequireAnyClientCert,
-			SignatureAndHashes: []signatureAndHash{
-				{signatureRSA, hashSHA512},
-				{signatureRSA, hashSHA1},
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPKCS1WithSHA512,
+				signatureRSAPKCS1WithSHA1,
 			},
 		},
 		flags: []string{
 			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
 			"-key-file", path.Join(*resourceDir, rsaKeyFile),
+			"-digest-prefs", "SHA256",
 		},
-		digestPrefs:                     "SHA256",
-		expectedClientCertSignatureHash: hashSHA1,
+		shouldFail:    true,
+		expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
+	})
+	testCases = append(testCases, testCase{
+		name: "NoCommonAlgorithms",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			ClientAuth: RequireAnyClientCert,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPKCS1WithSHA512,
+				signatureRSAPKCS1WithSHA1,
+			},
+		},
+		flags: []string{
+			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+			"-key-file", path.Join(*resourceDir, rsaKeyFile),
+			"-signing-prefs", strconv.Itoa(int(signatureRSAPKCS1WithSHA256)),
+		},
+		shouldFail:    true,
+		expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
+	})
+	testCases = append(testCases, testCase{
+		name: "NoCommonAlgorithms-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			ClientAuth: RequireAnyClientCert,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPSSWithSHA512,
+				signatureRSAPSSWithSHA384,
+			},
+		},
+		flags: []string{
+			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+			"-key-file", path.Join(*resourceDir, rsaKeyFile),
+			"-signing-prefs", strconv.Itoa(int(signatureRSAPSSWithSHA256)),
+		},
+		shouldFail:    true,
+		expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
 	})
 	testCases = append(testCases, testCase{
 		name: "Agree-Digest-SHA256",
 		config: Config{
+			MaxVersion: VersionTLS12,
 			ClientAuth: RequireAnyClientCert,
-			SignatureAndHashes: []signatureAndHash{
-				{signatureRSA, hashSHA1},
-				{signatureRSA, hashSHA256},
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPKCS1WithSHA1,
+				signatureRSAPKCS1WithSHA256,
 			},
 		},
 		flags: []string{
 			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
 			"-key-file", path.Join(*resourceDir, rsaKeyFile),
+			"-digest-prefs", "SHA256,SHA1",
 		},
-		digestPrefs:                     "SHA256,SHA1",
-		expectedClientCertSignatureHash: hashSHA256,
+		expectedPeerSignatureAlgorithm: signatureRSAPKCS1WithSHA256,
 	})
 	testCases = append(testCases, testCase{
 		name: "Agree-Digest-SHA1",
 		config: Config{
+			MaxVersion: VersionTLS12,
 			ClientAuth: RequireAnyClientCert,
-			SignatureAndHashes: []signatureAndHash{
-				{signatureRSA, hashSHA1},
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPKCS1WithSHA1,
 			},
 		},
 		flags: []string{
 			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
 			"-key-file", path.Join(*resourceDir, rsaKeyFile),
+			"-digest-prefs", "SHA512,SHA256,SHA1",
 		},
-		digestPrefs:                     "SHA512,SHA256,SHA1",
-		expectedClientCertSignatureHash: hashSHA1,
+		expectedPeerSignatureAlgorithm: signatureRSAPKCS1WithSHA1,
 	})
 	testCases = append(testCases, testCase{
 		name: "Agree-Digest-Default",
 		config: Config{
+			MaxVersion: VersionTLS12,
 			ClientAuth: RequireAnyClientCert,
-			SignatureAndHashes: []signatureAndHash{
-				{signatureRSA, hashSHA256},
-				{signatureECDSA, hashSHA256},
-				{signatureRSA, hashSHA1},
-				{signatureECDSA, hashSHA1},
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPKCS1WithSHA256,
+				signatureECDSAWithP256AndSHA256,
+				signatureRSAPKCS1WithSHA1,
+				signatureECDSAWithSHA1,
 			},
 		},
 		flags: []string{
 			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
 			"-key-file", path.Join(*resourceDir, rsaKeyFile),
 		},
-		expectedClientCertSignatureHash: hashSHA256,
+		expectedPeerSignatureAlgorithm: signatureRSAPKCS1WithSHA256,
+	})
+
+	// Test that the signing preference list may include extra algorithms
+	// without negotiation problems.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "FilterExtraAlgorithms",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPKCS1WithSHA256,
+			},
+		},
+		flags: []string{
+			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+			"-key-file", path.Join(*resourceDir, rsaKeyFile),
+			"-signing-prefs", strconv.Itoa(int(fakeSigAlg1)),
+			"-signing-prefs", strconv.Itoa(int(signatureECDSAWithP256AndSHA256)),
+			"-signing-prefs", strconv.Itoa(int(signatureRSAPKCS1WithSHA256)),
+			"-signing-prefs", strconv.Itoa(int(fakeSigAlg2)),
+		},
+		expectedPeerSignatureAlgorithm: signatureRSAPKCS1WithSHA256,
+	})
+
+	// In TLS 1.2 and below, ECDSA uses the curve list rather than the
+	// signature algorithms.
+	testCases = append(testCases, testCase{
+		name: "CheckLeafCurve",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
+			Certificates: []Certificate{ecdsaP256Certificate},
+		},
+		flags:         []string{"-p384-only"},
+		shouldFail:    true,
+		expectedError: ":BAD_ECC_CERT:",
+	})
+
+	// In TLS 1.3, ECDSA does not use the ECDHE curve list.
+	testCases = append(testCases, testCase{
+		name: "CheckLeafCurve-TLS13",
+		config: Config{
+			MaxVersion:   VersionTLS13,
+			Certificates: []Certificate{ecdsaP256Certificate},
+		},
+		flags: []string{"-p384-only"},
+	})
+
+	// In TLS 1.2, the ECDSA curve is not in the signature algorithm.
+	testCases = append(testCases, testCase{
+		name: "ECDSACurveMismatch-Verify-TLS12",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256},
+			Certificates: []Certificate{ecdsaP256Certificate},
+			SignSignatureAlgorithms: []signatureAlgorithm{
+				signatureECDSAWithP384AndSHA384,
+			},
+		},
+	})
+
+	// In TLS 1.3, the ECDSA curve comes from the signature algorithm.
+	testCases = append(testCases, testCase{
+		name: "ECDSACurveMismatch-Verify-TLS13",
+		config: Config{
+			MaxVersion:   VersionTLS13,
+			Certificates: []Certificate{ecdsaP256Certificate},
+			SignSignatureAlgorithms: []signatureAlgorithm{
+				signatureECDSAWithP384AndSHA384,
+			},
+			Bugs: ProtocolBugs{
+				SkipECDSACurveCheck: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_SIGNATURE_TYPE:",
+	})
+
+	// Signature algorithm selection in TLS 1.3 should take the curve into
+	// account.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "ECDSACurveMismatch-Sign-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureECDSAWithP384AndSHA384,
+				signatureECDSAWithP256AndSHA256,
+			},
+		},
+		flags: []string{
+			"-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile),
+			"-key-file", path.Join(*resourceDir, ecdsaP256KeyFile),
+		},
+		expectedPeerSignatureAlgorithm: signatureECDSAWithP256AndSHA256,
+	})
+
+	// RSASSA-PSS with SHA-512 is too large for 1024-bit RSA. Test that the
+	// server does not attempt to sign in that case.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "RSA-PSS-Large",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPSSWithSHA512,
+			},
+		},
+		flags: []string{
+			"-cert-file", path.Join(*resourceDir, rsa1024CertificateFile),
+			"-key-file", path.Join(*resourceDir, rsa1024KeyFile),
+		},
+		shouldFail:    true,
+		expectedError: ":NO_COMMON_SIGNATURE_ALGORITHMS:",
+	})
+
+	// Test that RSA-PSS is enabled by default for TLS 1.2.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "RSA-PSS-Default-Verify",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			SignSignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPSSWithSHA256,
+			},
+		},
+		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "RSA-PSS-Default-Sign",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				signatureRSAPSSWithSHA256,
+			},
+		},
+		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
+	})
+
+	// A server certificate with a P-224 key will only work up to TLS 1.2
+	// and we only test it with BoringSSL acting as a server because that's
+	// all Alphabet requires with it.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "P224-Server",
+		config: Config{
+			VerifySignatureAlgorithms: []signatureAlgorithm{
+				// TLS 1.2 does not require that the curve
+				// match the hash, thus P-256 with SHA-256 is
+				// the same signature algorithm value as P-224
+				// with SHA-256.
+				signatureECDSAWithP256AndSHA256,
+			},
+			// P-256 must be offered as well because ECDHE requires
+			// it.
+			CurvePreferences: []CurveID{CurveP224, CurveP256},
+		},
+		flags: []string{
+			"-max-version", strconv.Itoa(VersionTLS12),
+			"-cert-file", path.Join(*resourceDir, ecdsaP224CertificateFile),
+			"-key-file", path.Join(*resourceDir, ecdsaP224KeyFile),
+		},
 	})
 }
 
@@ -4327,7 +7531,50 @@
 	60 * time.Second,
 }
 
+// shortTimeouts is an alternate set of timeouts which would occur if the
+// initial timeout duration was set to 250ms.
+var shortTimeouts = []time.Duration{
+	250 * time.Millisecond,
+	500 * time.Millisecond,
+	1 * time.Second,
+	2 * time.Second,
+	4 * time.Second,
+	8 * time.Second,
+	16 * time.Second,
+	32 * time.Second,
+	60 * time.Second,
+	60 * time.Second,
+	60 * time.Second,
+	60 * time.Second,
+	60 * time.Second,
+}
+
 func addDTLSRetransmitTests() {
+	// These tests work by coordinating some behavior on both the shim and
+	// the runner.
+	//
+	// TimeoutSchedule configures the runner to send a series of timeout
+	// opcodes to the shim (see packetAdaptor) immediately before reading
+	// each peer handshake flight N. The timeout opcode both simulates a
+	// timeout in the shim and acts as a synchronization point to help the
+	// runner bracket each handshake flight.
+	//
+	// We assume the shim does not read from the channel eagerly. It must
+	// first wait until it has sent flight N and is ready to receive
+	// handshake flight N+1. At this point, it will process the timeout
+	// opcode. It must then immediately respond with a timeout ACK and act
+	// as if the shim was idle for the specified amount of time.
+	//
+	// The runner then drops all packets received before the ACK and
+	// continues waiting for flight N. This ordering results in one attempt
+	// at sending flight N to be dropped. For the test to complete, the
+	// shim must send flight N again, testing that the shim implements DTLS
+	// retransmit on a timeout.
+
+	// TODO(davidben): Add DTLS 1.3 versions of these tests. There will
+	// likely be more epochs to cross and the final message's retransmit may
+	// be more complex.
+
 	// Test that this is indeed the timeout schedule. Stress all
 	// four patterns of handshake.
 	for i := 1; i < len(timeouts); i++ {
@@ -4336,6 +7583,7 @@
 			protocol: dtls,
 			name:     "DTLS-Retransmit-Client-" + number,
 			config: Config{
+				MaxVersion: VersionTLS12,
 				Bugs: ProtocolBugs{
 					TimeoutSchedule: timeouts[:i],
 				},
@@ -4348,6 +7596,7 @@
 			testType: serverTest,
 			name:     "DTLS-Retransmit-Server-" + number,
 			config: Config{
+				MaxVersion: VersionTLS12,
 				Bugs: ProtocolBugs{
 					TimeoutSchedule: timeouts[:i],
 				},
@@ -4363,6 +7612,7 @@
 		protocol: dtls,
 		name:     "DTLS-Retransmit-Timeout",
 		config: Config{
+			MaxVersion: VersionTLS12,
 			Bugs: ProtocolBugs{
 				TimeoutSchedule: timeouts,
 			},
@@ -4379,6 +7629,7 @@
 		protocol: dtls,
 		name:     "DTLS-Retransmit-Fudge",
 		config: Config{
+			MaxVersion: VersionTLS12,
 			Bugs: ProtocolBugs{
 				TimeoutSchedule: []time.Duration{
 					timeouts[0] - 10*time.Millisecond,
@@ -4396,6 +7647,7 @@
 		protocol: dtls,
 		name:     "DTLS-Retransmit-Fragmented",
 		config: Config{
+			MaxVersion: VersionTLS12,
 			Bugs: ProtocolBugs{
 				TimeoutSchedule:          []time.Duration{timeouts[0]},
 				MaxHandshakeRecordLength: 2,
@@ -4403,6 +7655,39 @@
 		},
 		flags: []string{"-async"},
 	})
+
+	// Test the timeout schedule when a shorter initial timeout duration is set.
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		name:     "DTLS-Retransmit-Short-Client",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				TimeoutSchedule: shortTimeouts[:len(shortTimeouts)-1],
+			},
+		},
+		resumeSession: true,
+		flags: []string{
+			"-async",
+			"-initial-timeout-duration-ms", "250",
+		},
+	})
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		testType: serverTest,
+		name:     "DTLS-Retransmit-Short-Server",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				TimeoutSchedule: shortTimeouts[:len(shortTimeouts)-1],
+			},
+		},
+		resumeSession: true,
+		flags: []string{
+			"-async",
+			"-initial-timeout-duration-ms", "250",
+		},
+	})
 }
 
 func addExportKeyingMaterialTests() {
@@ -4446,6 +7731,7 @@
 			useExportContext:     true,
 		})
 	}
+
 	testCases = append(testCases, testCase{
 		name: "ExportKeyingMaterial-SSL3",
 		config: Config{
@@ -4458,6 +7744,47 @@
 		shouldFail:           true,
 		expectedError:        "failed to export keying material",
 	})
+
+	// Exporters work during a False Start.
+	testCases = append(testCases, testCase{
+		name: "ExportKeyingMaterial-FalseStart",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+			NextProtos:   []string{"foo"},
+			Bugs: ProtocolBugs{
+				ExpectFalseStart: true,
+			},
+		},
+		flags: []string{
+			"-false-start",
+			"-advertise-alpn", "\x03foo",
+		},
+		shimWritesFirst:      true,
+		exportKeyingMaterial: 1024,
+		exportLabel:          "label",
+		exportContext:        "context",
+		useExportContext:     true,
+	})
+
+	// Exporters do not work in the middle of a renegotiation. Test this by
+	// triggering the exporter after every SSL_read call and configuring the
+	// shim to run asynchronously.
+	testCases = append(testCases, testCase{
+		name: "ExportKeyingMaterial-Renegotiate",
+		config: Config{
+			MaxVersion: VersionTLS12,
+		},
+		renegotiate: 1,
+		flags: []string{
+			"-async",
+			"-use-exporter-between-reads",
+			"-renegotiate-freely",
+			"-expect-total-renegotiations", "1",
+		},
+		shouldFail:    true,
+		expectedError: "failed to export keying material",
+	})
 }
 
 func addTLSUniqueTests() {
@@ -4487,6 +7814,7 @@
 					name:          "TLSUnique-" + suffix,
 					testTLSUnique: true,
 					config: Config{
+						MaxVersion: VersionTLS12,
 						Bugs: ProtocolBugs{
 							NoExtendedMasterSecret: !hasEMS,
 						},
@@ -4496,6 +7824,7 @@
 				if isResumption {
 					test.resumeSession = true
 					test.resumeConfig = &Config{
+						MaxVersion: VersionTLS12,
 						Bugs: ProtocolBugs{
 							NoExtendedMasterSecret: !hasEMS,
 						},
@@ -4531,6 +7860,19 @@
 			testType: testType,
 			name:     "CustomExtensions-" + suffix,
 			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					CustomExtension:         expectedContents,
+					ExpectedCustomExtension: &expectedContents,
+				},
+			},
+			flags: []string{flag},
+		})
+		testCases = append(testCases, testCase{
+			testType: testType,
+			name:     "CustomExtensions-" + suffix + "-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
 				Bugs: ProtocolBugs{
 					CustomExtension:         expectedContents,
 					ExpectedCustomExtension: &expectedContents,
@@ -4539,11 +7881,42 @@
 			flags: []string{flag},
 		})
 
+		// 0-RTT is not currently supported with Custom Extensions.
+		testCases = append(testCases, testCase{
+			testType: testType,
+			name:     "CustomExtensions-" + suffix + "-EarlyData",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				Bugs: ProtocolBugs{
+					CustomExtension:         expectedContents,
+					ExpectedCustomExtension: &expectedContents,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":CUSTOM_EXTENSION_ERROR:",
+			flags:         []string{flag, "-enable-early-data"},
+		})
+
 		// If the parse callback fails, the handshake should also fail.
 		testCases = append(testCases, testCase{
 			testType: testType,
 			name:     "CustomExtensions-ParseError-" + suffix,
 			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					CustomExtension:         expectedContents + "foo",
+					ExpectedCustomExtension: &expectedContents,
+				},
+			},
+			flags:         []string{flag},
+			shouldFail:    true,
+			expectedError: ":CUSTOM_EXTENSION_ERROR:",
+		})
+		testCases = append(testCases, testCase{
+			testType: testType,
+			name:     "CustomExtensions-ParseError-" + suffix + "-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
 				Bugs: ProtocolBugs{
 					CustomExtension:         expectedContents + "foo",
 					ExpectedCustomExtension: &expectedContents,
@@ -4559,6 +7932,21 @@
 			testType: testType,
 			name:     "CustomExtensions-FailAdd-" + suffix,
 			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					CustomExtension:         expectedContents,
+					ExpectedCustomExtension: &expectedContents,
+				},
+			},
+			flags:         []string{flag, "-custom-extension-fail-add"},
+			shouldFail:    true,
+			expectedError: ":CUSTOM_EXTENSION_ERROR:",
+		})
+		testCases = append(testCases, testCase{
+			testType: testType,
+			name:     "CustomExtensions-FailAdd-" + suffix + "-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
 				Bugs: ProtocolBugs{
 					CustomExtension:         expectedContents,
 					ExpectedCustomExtension: &expectedContents,
@@ -4581,6 +7969,19 @@
 			testType: testType,
 			name:     "CustomExtensions-Skip-" + suffix,
 			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					CustomExtension:         skipCustomExtension,
+					ExpectedCustomExtension: &emptyString,
+				},
+			},
+			flags: []string{flag, "-custom-extension-skip"},
+		})
+		testCases = append(testCases, testCase{
+			testType: testType,
+			name:     "CustomExtensions-Skip-" + suffix + "-TLS13",
+			config: Config{
+				MaxVersion: VersionTLS13,
 				Bugs: ProtocolBugs{
 					CustomExtension:         skipCustomExtension,
 					ExpectedCustomExtension: &emptyString,
@@ -4596,6 +7997,19 @@
 		testType: serverTest,
 		name:     "CustomExtensions-NotCalled-Server",
 		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				ExpectedCustomExtension: &emptyString,
+			},
+		},
+		flags: []string{"-enable-server-custom-extension", "-custom-extension-fail-add"},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "CustomExtensions-NotCalled-Server-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
 			Bugs: ProtocolBugs{
 				ExpectedCustomExtension: &emptyString,
 			},
@@ -4608,12 +8022,88 @@
 		testType: clientTest,
 		name:     "UnknownExtension-Client",
 		config: Config{
+			MaxVersion: VersionTLS12,
 			Bugs: ProtocolBugs{
 				CustomExtension: expectedContents,
 			},
 		},
+		shouldFail:         true,
+		expectedError:      ":UNEXPECTED_EXTENSION:",
+		expectedLocalError: "remote error: unsupported extension",
+	})
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "UnknownExtension-Client-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				CustomExtension: expectedContents,
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":UNEXPECTED_EXTENSION:",
+		expectedLocalError: "remote error: unsupported extension",
+	})
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "UnknownUnencryptedExtension-Client-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				CustomUnencryptedExtension: expectedContents,
+			},
+		},
 		shouldFail:    true,
 		expectedError: ":UNEXPECTED_EXTENSION:",
+		// The shim must send an alert, but alerts at this point do not
+		// get successfully decrypted by the runner.
+		expectedLocalError: "local error: bad record MAC",
+	})
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "UnexpectedUnencryptedExtension-Client-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendUnencryptedALPN: "foo",
+			},
+		},
+		flags: []string{
+			"-advertise-alpn", "\x03foo\x03bar",
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_EXTENSION:",
+		// The shim must send an alert, but alerts at this point do not
+		// get successfully decrypted by the runner.
+		expectedLocalError: "local error: bad record MAC",
+	})
+
+	// Test a known but unoffered extension from the server.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "UnofferedExtension-Client",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				SendALPN: "alpn",
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":UNEXPECTED_EXTENSION:",
+		expectedLocalError: "remote error: unsupported extension",
+	})
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "UnofferedExtension-Client-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendALPN: "alpn",
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":UNEXPECTED_EXTENSION:",
+		expectedLocalError: "remote error: unsupported extension",
 	})
 }
 
@@ -4627,7 +8117,7 @@
 				// version are different, to detect if the
 				// server uses the wrong one.
 				MaxVersion:   VersionTLS11,
-				CipherSuites: []uint16{TLS_RSA_WITH_RC4_128_SHA},
+				CipherSuites: []uint16{TLS_RSA_WITH_3DES_EDE_CBC_SHA},
 				Bugs: ProtocolBugs{
 					BadRSAClientKeyExchange: bad,
 				},
@@ -4636,6 +8126,20 @@
 			expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
 		})
 	}
+
+	// The server must compare whatever was in ClientHello.version for the
+	// RSA premaster.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SendClientVersion-RSA",
+		config: Config{
+			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
+			Bugs: ProtocolBugs{
+				SendClientVersion: 0x1234,
+			},
+		},
+		flags: []string{"-max-version", strconv.Itoa(VersionTLS12)},
+	})
 }
 
 var testCurves = []struct {
@@ -4648,81 +8152,2592 @@
 	{"X25519", CurveX25519},
 }
 
+const bogusCurve = 0x1234
+
 func addCurveTests() {
 	for _, curve := range testCurves {
 		testCases = append(testCases, testCase{
 			name: "CurveTest-Client-" + curve.name,
 			config: Config{
+				MaxVersion:       VersionTLS12,
 				CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
 				CurvePreferences: []CurveID{curve.id},
 			},
-			flags: []string{"-enable-all-curves"},
+			flags: []string{
+				"-enable-all-curves",
+				"-expect-curve-id", strconv.Itoa(int(curve.id)),
+			},
+			expectedCurveID: curve.id,
+		})
+		testCases = append(testCases, testCase{
+			name: "CurveTest-Client-" + curve.name + "-TLS13",
+			config: Config{
+				MaxVersion:       VersionTLS13,
+				CurvePreferences: []CurveID{curve.id},
+			},
+			flags: []string{
+				"-enable-all-curves",
+				"-expect-curve-id", strconv.Itoa(int(curve.id)),
+			},
+			expectedCurveID: curve.id,
 		})
 		testCases = append(testCases, testCase{
 			testType: serverTest,
 			name:     "CurveTest-Server-" + curve.name,
 			config: Config{
+				MaxVersion:       VersionTLS12,
 				CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
 				CurvePreferences: []CurveID{curve.id},
 			},
-			flags: []string{"-enable-all-curves"},
+			flags: []string{
+				"-enable-all-curves",
+				"-expect-curve-id", strconv.Itoa(int(curve.id)),
+			},
+			expectedCurveID: curve.id,
+		})
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "CurveTest-Server-" + curve.name + "-TLS13",
+			config: Config{
+				MaxVersion:       VersionTLS13,
+				CurvePreferences: []CurveID{curve.id},
+			},
+			flags: []string{
+				"-enable-all-curves",
+				"-expect-curve-id", strconv.Itoa(int(curve.id)),
+			},
+			expectedCurveID: curve.id,
+		})
+	}
+
+	// The server must be tolerant to bogus curves.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "UnknownCurve",
+		config: Config{
+			MaxVersion:       VersionTLS12,
+			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+			CurvePreferences: []CurveID{bogusCurve, CurveP256},
+		},
+	})
+
+	// The server must be tolerant to bogus curves.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "UnknownCurve-TLS13",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			CurvePreferences: []CurveID{bogusCurve, CurveP256},
+		},
+	})
+
+	// The server must not consider ECDHE ciphers when there are no
+	// supported curves.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "NoSupportedCurves",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+			Bugs: ProtocolBugs{
+				NoSupportedCurves: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":NO_SHARED_CIPHER:",
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "NoSupportedCurves-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				NoSupportedCurves: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":NO_SHARED_GROUP:",
+	})
+
+	// The server must fall back to another cipher when there are no
+	// supported curves.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "NoCommonCurves",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			CipherSuites: []uint16{
+				TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
+				TLS_RSA_WITH_AES_128_GCM_SHA256,
+			},
+			CurvePreferences: []CurveID{CurveP224},
+		},
+		expectedCipher: TLS_RSA_WITH_AES_128_GCM_SHA256,
+	})
+
+	// The client must reject bogus curves and disabled curves.
+	testCases = append(testCases, testCase{
+		name: "BadECDHECurve",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+			Bugs: ProtocolBugs{
+				SendCurve: bogusCurve,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_CURVE:",
+	})
+	testCases = append(testCases, testCase{
+		name: "BadECDHECurve-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendCurve: bogusCurve,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_CURVE:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "UnsupportedCurve",
+		config: Config{
+			MaxVersion:       VersionTLS12,
+			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+			CurvePreferences: []CurveID{CurveP256},
+			Bugs: ProtocolBugs{
+				IgnorePeerCurvePreferences: true,
+			},
+		},
+		flags:         []string{"-p384-only"},
+		shouldFail:    true,
+		expectedError: ":WRONG_CURVE:",
+	})
+
+	testCases = append(testCases, testCase{
+		// TODO(davidben): Add a TLS 1.3 version where
+		// HelloRetryRequest requests an unsupported curve.
+		name: "UnsupportedCurve-ServerHello-TLS13",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			CurvePreferences: []CurveID{CurveP384},
+			Bugs: ProtocolBugs{
+				SendCurve: CurveP256,
+			},
+		},
+		flags:         []string{"-p384-only"},
+		shouldFail:    true,
+		expectedError: ":WRONG_CURVE:",
+	})
+
+	// Test invalid curve points.
+	testCases = append(testCases, testCase{
+		name: "InvalidECDHPoint-Client",
+		config: Config{
+			MaxVersion:       VersionTLS12,
+			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+			CurvePreferences: []CurveID{CurveP256},
+			Bugs: ProtocolBugs{
+				InvalidECDHPoint: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":INVALID_ENCODING:",
+	})
+	testCases = append(testCases, testCase{
+		name: "InvalidECDHPoint-Client-TLS13",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			CurvePreferences: []CurveID{CurveP256},
+			Bugs: ProtocolBugs{
+				InvalidECDHPoint: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":INVALID_ENCODING:",
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "InvalidECDHPoint-Server",
+		config: Config{
+			MaxVersion:       VersionTLS12,
+			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+			CurvePreferences: []CurveID{CurveP256},
+			Bugs: ProtocolBugs{
+				InvalidECDHPoint: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":INVALID_ENCODING:",
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "InvalidECDHPoint-Server-TLS13",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			CurvePreferences: []CurveID{CurveP256},
+			Bugs: ProtocolBugs{
+				InvalidECDHPoint: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":INVALID_ENCODING:",
+	})
+
+	// The previous curve ID should be reported on TLS 1.2 resumption.
+	testCases = append(testCases, testCase{
+		name: "CurveID-Resume-Client",
+		config: Config{
+			MaxVersion:       VersionTLS12,
+			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+			CurvePreferences: []CurveID{CurveX25519},
+		},
+		flags:         []string{"-expect-curve-id", strconv.Itoa(int(CurveX25519))},
+		resumeSession: true,
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "CurveID-Resume-Server",
+		config: Config{
+			MaxVersion:       VersionTLS12,
+			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+			CurvePreferences: []CurveID{CurveX25519},
+		},
+		flags:         []string{"-expect-curve-id", strconv.Itoa(int(CurveX25519))},
+		resumeSession: true,
+	})
+
+	// TLS 1.3 allows resuming at a differet curve. If this happens, the new
+	// one should be reported.
+	testCases = append(testCases, testCase{
+		name: "CurveID-Resume-Client-TLS13",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			CurvePreferences: []CurveID{CurveX25519},
+		},
+		resumeConfig: &Config{
+			MaxVersion:       VersionTLS13,
+			CurvePreferences: []CurveID{CurveP256},
+		},
+		flags: []string{
+			"-expect-curve-id", strconv.Itoa(int(CurveX25519)),
+			"-expect-resume-curve-id", strconv.Itoa(int(CurveP256)),
+		},
+		resumeSession: true,
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "CurveID-Resume-Server-TLS13",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			CurvePreferences: []CurveID{CurveX25519},
+		},
+		resumeConfig: &Config{
+			MaxVersion:       VersionTLS13,
+			CurvePreferences: []CurveID{CurveP256},
+		},
+		flags: []string{
+			"-expect-curve-id", strconv.Itoa(int(CurveX25519)),
+			"-expect-resume-curve-id", strconv.Itoa(int(CurveP256)),
+		},
+		resumeSession: true,
+	})
+
+	// Server-sent point formats are legal in TLS 1.2, but not in TLS 1.3.
+	testCases = append(testCases, testCase{
+		name: "PointFormat-ServerHello-TLS12",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				SendSupportedPointFormats: []byte{pointFormatUncompressed},
+			},
+		},
+	})
+	testCases = append(testCases, testCase{
+		name: "PointFormat-EncryptedExtensions-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendSupportedPointFormats: []byte{pointFormatUncompressed},
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":ERROR_PARSING_EXTENSION:",
+	})
+
+	// Test that we tolerate unknown point formats, as long as
+	// pointFormatUncompressed is present. Limit ciphers to ECDHE ciphers to
+	// check they are still functional.
+	testCases = append(testCases, testCase{
+		name: "PointFormat-Client-Tolerance",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				SendSupportedPointFormats: []byte{42, pointFormatUncompressed, 99, pointFormatCompressedPrime},
+			},
+		},
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "PointFormat-Server-Tolerance",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
+			Bugs: ProtocolBugs{
+				SendSupportedPointFormats: []byte{42, pointFormatUncompressed, 99, pointFormatCompressedPrime},
+			},
+		},
+	})
+
+	// Test TLS 1.2 does not require the point format extension to be
+	// present.
+	testCases = append(testCases, testCase{
+		name: "PointFormat-Client-Missing",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
+			Bugs: ProtocolBugs{
+				SendSupportedPointFormats: []byte{},
+			},
+		},
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "PointFormat-Server-Missing",
+		config: Config{
+			MaxVersion:   VersionTLS12,
+			CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
+			Bugs: ProtocolBugs{
+				SendSupportedPointFormats: []byte{},
+			},
+		},
+	})
+
+	// If the point format extension is present, uncompressed points must be
+	// offered. BoringSSL requires this whether or not ECDHE is used.
+	testCases = append(testCases, testCase{
+		name: "PointFormat-Client-MissingUncompressed",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				SendSupportedPointFormats: []byte{pointFormatCompressedPrime},
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":ERROR_PARSING_EXTENSION:",
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "PointFormat-Server-MissingUncompressed",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				SendSupportedPointFormats: []byte{pointFormatCompressedPrime},
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":ERROR_PARSING_EXTENSION:",
+	})
+}
+
+func addTLS13RecordTests() {
+	testCases = append(testCases, testCase{
+		name: "TLS13-RecordPadding",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			MinVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				RecordPadding: 10,
+			},
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		name: "TLS13-EmptyRecords",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			MinVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				OmitRecordContents: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "TLS13-OnlyPadding",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			MinVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				OmitRecordContents: true,
+				RecordPadding:      10,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "TLS13-WrongOuterRecord",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			MinVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				OuterRecordType: recordTypeHandshake,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":INVALID_OUTER_RECORD_TYPE:",
+	})
+}
+
+func addSessionTicketTests() {
+	testCases = append(testCases, testCase{
+		// In TLS 1.2 and below, empty NewSessionTicket messages
+		// mean the server changed its mind on sending a ticket.
+		name: "SendEmptySessionTicket",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				SendEmptySessionTicket: true,
+			},
+		},
+		flags: []string{"-expect-no-session"},
+	})
+
+	// Test that the server ignores unknown PSK modes.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TLS13-SendUnknownModeSessionTicket-Server",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendPSKKeyExchangeModes: []byte{0x1a, pskDHEKEMode, 0x2a},
+			},
+		},
+		resumeSession:         true,
+		expectedResumeVersion: VersionTLS13,
+	})
+
+	// Test that the server does not send session tickets with no matching key exchange mode.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TLS13-ExpectNoSessionTicketOnBadKEMode-Server",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendPSKKeyExchangeModes:  []byte{0x1a},
+				ExpectNoNewSessionTicket: true,
+			},
+		},
+	})
+
+	// Test that the server does not accept a session with no matching key exchange mode.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TLS13-SendBadKEModeSessionTicket-Server",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		resumeConfig: &Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendPSKKeyExchangeModes: []byte{0x1a},
+			},
+		},
+		resumeSession:        true,
+		expectResumeRejected: true,
+	})
+
+	// Test that the client ticket age is sent correctly.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "TLS13-TestValidTicketAge-Client",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				ExpectTicketAge: 10 * time.Second,
+			},
+		},
+		resumeSession: true,
+		flags: []string{
+			"-resumption-delay", "10",
+		},
+	})
+
+	// Test that the client ticket age is enforced.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "TLS13-TestBadTicketAge-Client",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				ExpectTicketAge: 1000 * time.Second,
+			},
+		},
+		resumeSession:      true,
+		shouldFail:         true,
+		expectedLocalError: "tls: invalid ticket age",
+	})
+
+	// Test that the server's ticket age skew reporting works.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TLS13-TicketAgeSkew-Forward",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendTicketAge: 15 * time.Second,
+			},
+		},
+		resumeSession:        true,
+		resumeRenewedSession: true,
+		flags: []string{
+			"-resumption-delay", "10",
+			"-expect-ticket-age-skew", "5",
+		},
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TLS13-TicketAgeSkew-Backward",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendTicketAge: 5 * time.Second,
+			},
+		},
+		resumeSession:        true,
+		resumeRenewedSession: true,
+		flags: []string{
+			"-resumption-delay", "10",
+			"-expect-ticket-age-skew", "-5",
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "TLS13-SendTicketEarlyDataInfo",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			MaxEarlyDataSize: 16384,
+		},
+		flags: []string{
+			"-enable-early-data",
+			"-expect-early-data-info",
+		},
+	})
+
+	// Test that 0-RTT tickets are ignored in clients unless opted in.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "TLS13-SendTicketEarlyDataInfo-Disabled",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			MaxEarlyDataSize: 16384,
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "TLS13-DuplicateTicketEarlyDataInfo",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			MaxEarlyDataSize: 16384,
+			Bugs: ProtocolBugs{
+				DuplicateTicketEarlyDataInfo: true,
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":DUPLICATE_EXTENSION:",
+		expectedLocalError: "remote error: illegal parameter",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TLS13-ExpectTicketEarlyDataInfo",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				ExpectTicketEarlyDataInfo: true,
+			},
+		},
+		flags: []string{
+			"-enable-early-data",
+		},
+	})
+
+	// Test that, in TLS 1.3, the server-offered NewSessionTicket lifetime
+	// is honored.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "TLS13-HonorServerSessionTicketLifetime",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendTicketLifetime: 20 * time.Second,
+			},
+		},
+		flags: []string{
+			"-resumption-delay", "19",
+		},
+		resumeSession: true,
+	})
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "TLS13-HonorServerSessionTicketLifetime-2",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendTicketLifetime: 20 * time.Second,
+				// The client should not offer the expired session.
+				ExpectNoTLS13PSK: true,
+			},
+		},
+		flags: []string{
+			"-resumption-delay", "21",
+		},
+		resumeSession:        true,
+		expectResumeRejected: true,
+	})
+}
+
+func addChangeCipherSpecTests() {
+	// Test missing ChangeCipherSpecs.
+	testCases = append(testCases, testCase{
+		name: "SkipChangeCipherSpec-Client",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				SkipChangeCipherSpec: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_RECORD:",
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SkipChangeCipherSpec-Server",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				SkipChangeCipherSpec: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_RECORD:",
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SkipChangeCipherSpec-Server-NPN",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			NextProtos: []string{"bar"},
+			Bugs: ProtocolBugs{
+				SkipChangeCipherSpec: true,
+			},
+		},
+		flags: []string{
+			"-advertise-npn", "\x03foo\x03bar\x03baz",
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_RECORD:",
+	})
+
+	// Test synchronization between the handshake and ChangeCipherSpec.
+	// Partial post-CCS handshake messages before ChangeCipherSpec should be
+	// rejected. Test both with and without handshake packing to handle both
+	// when the partial post-CCS message is in its own record and when it is
+	// attached to the pre-CCS message.
+	for _, packed := range []bool{false, true} {
+		var suffix string
+		if packed {
+			suffix = "-Packed"
+		}
+
+		testCases = append(testCases, testCase{
+			name: "FragmentAcrossChangeCipherSpec-Client" + suffix,
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					FragmentAcrossChangeCipherSpec: true,
+					PackHandshakeFlight:            packed,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":UNEXPECTED_RECORD:",
+		})
+		testCases = append(testCases, testCase{
+			name: "FragmentAcrossChangeCipherSpec-Client-Resume" + suffix,
+			config: Config{
+				MaxVersion: VersionTLS12,
+			},
+			resumeSession: true,
+			resumeConfig: &Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					FragmentAcrossChangeCipherSpec: true,
+					PackHandshakeFlight:            packed,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":UNEXPECTED_RECORD:",
+		})
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "FragmentAcrossChangeCipherSpec-Server" + suffix,
+			config: Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					FragmentAcrossChangeCipherSpec: true,
+					PackHandshakeFlight:            packed,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":UNEXPECTED_RECORD:",
+		})
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "FragmentAcrossChangeCipherSpec-Server-Resume" + suffix,
+			config: Config{
+				MaxVersion: VersionTLS12,
+			},
+			resumeSession: true,
+			resumeConfig: &Config{
+				MaxVersion: VersionTLS12,
+				Bugs: ProtocolBugs{
+					FragmentAcrossChangeCipherSpec: true,
+					PackHandshakeFlight:            packed,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":UNEXPECTED_RECORD:",
+		})
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "FragmentAcrossChangeCipherSpec-Server-NPN" + suffix,
+			config: Config{
+				MaxVersion: VersionTLS12,
+				NextProtos: []string{"bar"},
+				Bugs: ProtocolBugs{
+					FragmentAcrossChangeCipherSpec: true,
+					PackHandshakeFlight:            packed,
+				},
+			},
+			flags: []string{
+				"-advertise-npn", "\x03foo\x03bar\x03baz",
+			},
+			shouldFail:    true,
+			expectedError: ":UNEXPECTED_RECORD:",
+		})
+	}
+
+	// Test that, in DTLS, ChangeCipherSpec is not allowed when there are
+	// messages in the handshake queue. Do this by testing the server
+	// reading the client Finished, reversing the flight so Finished comes
+	// first.
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		testType: serverTest,
+		name:     "SendUnencryptedFinished-DTLS",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				SendUnencryptedFinished:   true,
+				ReverseHandshakeFragments: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":BUFFERED_MESSAGES_ON_CIPHER_CHANGE:",
+	})
+
+	// Test synchronization between encryption changes and the handshake in
+	// TLS 1.3, where ChangeCipherSpec is implicit.
+	testCases = append(testCases, testCase{
+		name: "PartialEncryptedExtensionsWithServerHello",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				PartialEncryptedExtensionsWithServerHello: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":BUFFERED_MESSAGES_ON_CIPHER_CHANGE:",
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "PartialClientFinishedWithClientHello",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				PartialClientFinishedWithClientHello: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":BUFFERED_MESSAGES_ON_CIPHER_CHANGE:",
+	})
+
+	// Test that early ChangeCipherSpecs are handled correctly.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "EarlyChangeCipherSpec-server-1",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				EarlyChangeCipherSpec: 1,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_RECORD:",
+	})
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "EarlyChangeCipherSpec-server-2",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				EarlyChangeCipherSpec: 2,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_RECORD:",
+	})
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		name:     "StrayChangeCipherSpec",
+		config: Config{
+			// TODO(davidben): Once DTLS 1.3 exists, test
+			// that stray ChangeCipherSpec messages are
+			// rejected.
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				StrayChangeCipherSpec: true,
+			},
+		},
+	})
+
+	// Test that the contents of ChangeCipherSpec are checked.
+	testCases = append(testCases, testCase{
+		name: "BadChangeCipherSpec-1",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				BadChangeCipherSpec: []byte{2},
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
+	})
+	testCases = append(testCases, testCase{
+		name: "BadChangeCipherSpec-2",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				BadChangeCipherSpec: []byte{1, 1},
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
+	})
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		name:     "BadChangeCipherSpec-DTLS-1",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				BadChangeCipherSpec: []byte{2},
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
+	})
+	testCases = append(testCases, testCase{
+		protocol: dtls,
+		name:     "BadChangeCipherSpec-DTLS-2",
+		config: Config{
+			MaxVersion: VersionTLS12,
+			Bugs: ProtocolBugs{
+				BadChangeCipherSpec: []byte{1, 1},
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":BAD_CHANGE_CIPHER_SPEC:",
+	})
+}
+
+type perMessageTest struct {
+	messageType uint8
+	test        testCase
+}
+
+// makePerMessageTests returns a series of test templates which cover each
+// message in the TLS handshake. These may be used with bugs like
+// WrongMessageType to fully test a per-message bug.
+func makePerMessageTests() []perMessageTest {
+	var ret []perMessageTest
+	for _, protocol := range []protocol{tls, dtls} {
+		var suffix string
+		if protocol == dtls {
+			suffix = "-DTLS"
+		}
+
+		ret = append(ret, perMessageTest{
+			messageType: typeClientHello,
+			test: testCase{
+				protocol: protocol,
+				testType: serverTest,
+				name:     "ClientHello" + suffix,
+				config: Config{
+					MaxVersion: VersionTLS12,
+				},
+			},
+		})
+
+		if protocol == dtls {
+			ret = append(ret, perMessageTest{
+				messageType: typeHelloVerifyRequest,
+				test: testCase{
+					protocol: protocol,
+					name:     "HelloVerifyRequest" + suffix,
+					config: Config{
+						MaxVersion: VersionTLS12,
+					},
+				},
+			})
+		}
+
+		ret = append(ret, perMessageTest{
+			messageType: typeServerHello,
+			test: testCase{
+				protocol: protocol,
+				name:     "ServerHello" + suffix,
+				config: Config{
+					MaxVersion: VersionTLS12,
+				},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeCertificate,
+			test: testCase{
+				protocol: protocol,
+				name:     "ServerCertificate" + suffix,
+				config: Config{
+					MaxVersion: VersionTLS12,
+				},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeCertificateStatus,
+			test: testCase{
+				protocol: protocol,
+				name:     "CertificateStatus" + suffix,
+				config: Config{
+					MaxVersion: VersionTLS12,
+				},
+				flags: []string{"-enable-ocsp-stapling"},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeServerKeyExchange,
+			test: testCase{
+				protocol: protocol,
+				name:     "ServerKeyExchange" + suffix,
+				config: Config{
+					MaxVersion:   VersionTLS12,
+					CipherSuites: []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
+				},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeCertificateRequest,
+			test: testCase{
+				protocol: protocol,
+				name:     "CertificateRequest" + suffix,
+				config: Config{
+					MaxVersion: VersionTLS12,
+					ClientAuth: RequireAnyClientCert,
+				},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeServerHelloDone,
+			test: testCase{
+				protocol: protocol,
+				name:     "ServerHelloDone" + suffix,
+				config: Config{
+					MaxVersion: VersionTLS12,
+				},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeCertificate,
+			test: testCase{
+				testType: serverTest,
+				protocol: protocol,
+				name:     "ClientCertificate" + suffix,
+				config: Config{
+					Certificates: []Certificate{rsaCertificate},
+					MaxVersion:   VersionTLS12,
+				},
+				flags: []string{"-require-any-client-certificate"},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeCertificateVerify,
+			test: testCase{
+				testType: serverTest,
+				protocol: protocol,
+				name:     "CertificateVerify" + suffix,
+				config: Config{
+					Certificates: []Certificate{rsaCertificate},
+					MaxVersion:   VersionTLS12,
+				},
+				flags: []string{"-require-any-client-certificate"},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeClientKeyExchange,
+			test: testCase{
+				testType: serverTest,
+				protocol: protocol,
+				name:     "ClientKeyExchange" + suffix,
+				config: Config{
+					MaxVersion: VersionTLS12,
+				},
+			},
+		})
+
+		if protocol != dtls {
+			ret = append(ret, perMessageTest{
+				messageType: typeNextProtocol,
+				test: testCase{
+					testType: serverTest,
+					protocol: protocol,
+					name:     "NextProtocol" + suffix,
+					config: Config{
+						MaxVersion: VersionTLS12,
+						NextProtos: []string{"bar"},
+					},
+					flags: []string{"-advertise-npn", "\x03foo\x03bar\x03baz"},
+				},
+			})
+
+			ret = append(ret, perMessageTest{
+				messageType: typeChannelID,
+				test: testCase{
+					testType: serverTest,
+					protocol: protocol,
+					name:     "ChannelID" + suffix,
+					config: Config{
+						MaxVersion: VersionTLS12,
+						ChannelID:  channelIDKey,
+					},
+					flags: []string{
+						"-expect-channel-id",
+						base64.StdEncoding.EncodeToString(channelIDBytes),
+					},
+				},
+			})
+		}
+
+		ret = append(ret, perMessageTest{
+			messageType: typeFinished,
+			test: testCase{
+				testType: serverTest,
+				protocol: protocol,
+				name:     "ClientFinished" + suffix,
+				config: Config{
+					MaxVersion: VersionTLS12,
+				},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeNewSessionTicket,
+			test: testCase{
+				protocol: protocol,
+				name:     "NewSessionTicket" + suffix,
+				config: Config{
+					MaxVersion: VersionTLS12,
+				},
+			},
+		})
+
+		ret = append(ret, perMessageTest{
+			messageType: typeFinished,
+			test: testCase{
+				protocol: protocol,
+				name:     "ServerFinished" + suffix,
+				config: Config{
+					MaxVersion: VersionTLS12,
+				},
+			},
+		})
+
+	}
+
+	ret = append(ret, perMessageTest{
+		messageType: typeClientHello,
+		test: testCase{
+			testType: serverTest,
+			name:     "TLS13-ClientHello",
+			config: Config{
+				MaxVersion: VersionTLS13,
+			},
+		},
+	})
+
+	ret = append(ret, perMessageTest{
+		messageType: typeServerHello,
+		test: testCase{
+			name: "TLS13-ServerHello",
+			config: Config{
+				MaxVersion: VersionTLS13,
+			},
+		},
+	})
+
+	ret = append(ret, perMessageTest{
+		messageType: typeEncryptedExtensions,
+		test: testCase{
+			name: "TLS13-EncryptedExtensions",
+			config: Config{
+				MaxVersion: VersionTLS13,
+			},
+		},
+	})
+
+	ret = append(ret, perMessageTest{
+		messageType: typeCertificateRequest,
+		test: testCase{
+			name: "TLS13-CertificateRequest",
+			config: Config{
+				MaxVersion: VersionTLS13,
+				ClientAuth: RequireAnyClientCert,
+			},
+		},
+	})
+
+	ret = append(ret, perMessageTest{
+		messageType: typeCertificate,
+		test: testCase{
+			name: "TLS13-ServerCertificate",
+			config: Config{
+				MaxVersion: VersionTLS13,
+			},
+		},
+	})
+
+	ret = append(ret, perMessageTest{
+		messageType: typeCertificateVerify,
+		test: testCase{
+			name: "TLS13-ServerCertificateVerify",
+			config: Config{
+				MaxVersion: VersionTLS13,
+			},
+		},
+	})
+
+	ret = append(ret, perMessageTest{
+		messageType: typeFinished,
+		test: testCase{
+			name: "TLS13-ServerFinished",
+			config: Config{
+				MaxVersion: VersionTLS13,
+			},
+		},
+	})
+
+	ret = append(ret, perMessageTest{
+		messageType: typeCertificate,
+		test: testCase{
+			testType: serverTest,
+			name:     "TLS13-ClientCertificate",
+			config: Config{
+				Certificates: []Certificate{rsaCertificate},
+				MaxVersion:   VersionTLS13,
+			},
+			flags: []string{"-require-any-client-certificate"},
+		},
+	})
+
+	ret = append(ret, perMessageTest{
+		messageType: typeCertificateVerify,
+		test: testCase{
+			testType: serverTest,
+			name:     "TLS13-ClientCertificateVerify",
+			config: Config{
+				Certificates: []Certificate{rsaCertificate},
+				MaxVersion:   VersionTLS13,
+			},
+			flags: []string{"-require-any-client-certificate"},
+		},
+	})
+
+	ret = append(ret, perMessageTest{
+		messageType: typeFinished,
+		test: testCase{
+			testType: serverTest,
+			name:     "TLS13-ClientFinished",
+			config: Config{
+				MaxVersion: VersionTLS13,
+			},
+		},
+	})
+
+	return ret
+}
+
+func addWrongMessageTypeTests() {
+	for _, t := range makePerMessageTests() {
+		t.test.name = "WrongMessageType-" + t.test.name
+		t.test.config.Bugs.SendWrongMessageType = t.messageType
+		t.test.shouldFail = true
+		t.test.expectedError = ":UNEXPECTED_MESSAGE:"
+		t.test.expectedLocalError = "remote error: unexpected message"
+
+		if t.test.config.MaxVersion >= VersionTLS13 && t.messageType == typeServerHello {
+			// In TLS 1.3, a bad ServerHello means the client sends
+			// an unencrypted alert while the server expects
+			// encryption, so the alert is not readable by runner.
+			t.test.expectedLocalError = "local error: bad record MAC"
+		}
+
+		testCases = append(testCases, t.test)
+	}
+}
+
+func addTrailingMessageDataTests() {
+	for _, t := range makePerMessageTests() {
+		t.test.name = "TrailingMessageData-" + t.test.name
+		t.test.config.Bugs.SendTrailingMessageData = t.messageType
+		t.test.shouldFail = true
+		t.test.expectedError = ":DECODE_ERROR:"
+		t.test.expectedLocalError = "remote error: error decoding message"
+
+		if t.test.config.MaxVersion >= VersionTLS13 && t.messageType == typeServerHello {
+			// In TLS 1.3, a bad ServerHello means the client sends
+			// an unencrypted alert while the server expects
+			// encryption, so the alert is not readable by runner.
+			t.test.expectedLocalError = "local error: bad record MAC"
+		}
+
+		if t.messageType == typeFinished {
+			// Bad Finished messages read as the verify data having
+			// the wrong length.
+			t.test.expectedError = ":DIGEST_CHECK_FAILED:"
+			t.test.expectedLocalError = "remote error: error decrypting message"
+		}
+
+		testCases = append(testCases, t.test)
+	}
+}
+
+func addTLS13HandshakeTests() {
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "NegotiatePSKResumption-TLS13",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				NegotiatePSKResumption: true,
+			},
+		},
+		resumeSession: true,
+		shouldFail:    true,
+		expectedError: ":MISSING_KEY_SHARE:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "MissingKeyShare-Client",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				MissingKeyShare: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":MISSING_KEY_SHARE:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "MissingKeyShare-Server",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				MissingKeyShare: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":MISSING_KEY_SHARE:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "DuplicateKeyShares",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				DuplicateKeyShares: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":DUPLICATE_KEY_SHARE:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SkipEarlyData",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendFakeEarlyDataLength: 4,
+			},
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SkipEarlyData-OmitEarlyDataExtension",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendFakeEarlyDataLength: 4,
+				OmitEarlyDataExtension:  true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SkipEarlyData-TooMuchData",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendFakeEarlyDataLength: 16384 + 1,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":TOO_MUCH_SKIPPED_EARLY_DATA:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SkipEarlyData-Interleaved",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendFakeEarlyDataLength: 4,
+				InterleaveEarlyData:     true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SkipEarlyData-EarlyDataInTLS12",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendFakeEarlyDataLength: 4,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_RECORD:",
+		flags:         []string{"-max-version", strconv.Itoa(VersionTLS12)},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SkipEarlyData-HRR",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendFakeEarlyDataLength: 4,
+			},
+			DefaultCurves: []CurveID{},
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SkipEarlyData-HRR-Interleaved",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendFakeEarlyDataLength: 4,
+				InterleaveEarlyData:     true,
+			},
+			DefaultCurves: []CurveID{},
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_RECORD:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SkipEarlyData-HRR-TooMuchData",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendFakeEarlyDataLength: 16384 + 1,
+			},
+			DefaultCurves: []CurveID{},
+		},
+		shouldFail:    true,
+		expectedError: ":TOO_MUCH_SKIPPED_EARLY_DATA:",
+	})
+
+	// Test that skipping early data looking for cleartext correctly
+	// processes an alert record.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SkipEarlyData-HRR-FatalAlert",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendEarlyAlert:          true,
+				SendFakeEarlyDataLength: 4,
+			},
+			DefaultCurves: []CurveID{},
+		},
+		shouldFail:    true,
+		expectedError: ":SSLV3_ALERT_HANDSHAKE_FAILURE:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SkipEarlyData-SecondClientHelloEarlyData",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendEarlyDataOnSecondClientHello: true,
+			},
+			DefaultCurves: []CurveID{},
+		},
+		shouldFail:         true,
+		expectedLocalError: "remote error: bad record MAC",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "EmptyEncryptedExtensions",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				EmptyEncryptedExtensions: true,
+			},
+		},
+		shouldFail:         true,
+		expectedLocalError: "remote error: error decoding message",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "EncryptedExtensionsWithKeyShare",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				EncryptedExtensionsWithKeyShare: true,
+			},
+		},
+		shouldFail:         true,
+		expectedLocalError: "remote error: unsupported extension",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SendHelloRetryRequest",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			// Require a HelloRetryRequest for every curve.
+			DefaultCurves: []CurveID{},
+		},
+		expectedCurveID: CurveX25519,
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SendHelloRetryRequest-2",
+		config: Config{
+			MaxVersion:    VersionTLS13,
+			DefaultCurves: []CurveID{CurveP384},
+		},
+		// Although the ClientHello did not predict our preferred curve,
+		// we always select it whether it is predicted or not.
+		expectedCurveID: CurveX25519,
+	})
+
+	testCases = append(testCases, testCase{
+		name: "UnknownCurve-HelloRetryRequest",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			// P-384 requires HelloRetryRequest in BoringSSL.
+			CurvePreferences: []CurveID{CurveP384},
+			Bugs: ProtocolBugs{
+				SendHelloRetryRequestCurve: bogusCurve,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_CURVE:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "DisabledCurve-HelloRetryRequest",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			CurvePreferences: []CurveID{CurveP256},
+			Bugs: ProtocolBugs{
+				IgnorePeerCurvePreferences: true,
+			},
+		},
+		flags:         []string{"-p384-only"},
+		shouldFail:    true,
+		expectedError: ":WRONG_CURVE:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "UnnecessaryHelloRetryRequest",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			CurvePreferences: []CurveID{CurveX25519},
+			Bugs: ProtocolBugs{
+				SendHelloRetryRequestCurve: CurveX25519,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_CURVE:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "SecondHelloRetryRequest",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			// P-384 requires HelloRetryRequest in BoringSSL.
+			CurvePreferences: []CurveID{CurveP384},
+			Bugs: ProtocolBugs{
+				SecondHelloRetryRequest: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_MESSAGE:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "HelloRetryRequest-Empty",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				AlwaysSendHelloRetryRequest: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":DECODE_ERROR:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "HelloRetryRequest-DuplicateCurve",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			// P-384 requires a HelloRetryRequest against BoringSSL's default
+			// configuration. Assert this ExpectMissingKeyShare.
+			CurvePreferences: []CurveID{CurveP384},
+			Bugs: ProtocolBugs{
+				ExpectMissingKeyShare:                true,
+				DuplicateHelloRetryRequestExtensions: true,
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":DUPLICATE_EXTENSION:",
+		expectedLocalError: "remote error: illegal parameter",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "HelloRetryRequest-Cookie",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendHelloRetryRequestCookie: []byte("cookie"),
+			},
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		name: "HelloRetryRequest-DuplicateCookie",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendHelloRetryRequestCookie:          []byte("cookie"),
+				DuplicateHelloRetryRequestExtensions: true,
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":DUPLICATE_EXTENSION:",
+		expectedLocalError: "remote error: illegal parameter",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "HelloRetryRequest-EmptyCookie",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendHelloRetryRequestCookie: []byte{},
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":DECODE_ERROR:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "HelloRetryRequest-Cookie-Curve",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			// P-384 requires HelloRetryRequest in BoringSSL.
+			CurvePreferences: []CurveID{CurveP384},
+			Bugs: ProtocolBugs{
+				SendHelloRetryRequestCookie: []byte("cookie"),
+				ExpectMissingKeyShare:       true,
+			},
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		name: "HelloRetryRequest-Unknown",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				CustomHelloRetryRequestExtension: "extension",
+			},
+		},
+		shouldFail:         true,
+		expectedError:      ":UNEXPECTED_EXTENSION:",
+		expectedLocalError: "remote error: unsupported extension",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SecondClientHelloMissingKeyShare",
+		config: Config{
+			MaxVersion:    VersionTLS13,
+			DefaultCurves: []CurveID{},
+			Bugs: ProtocolBugs{
+				SecondClientHelloMissingKeyShare: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":MISSING_KEY_SHARE:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "SecondClientHelloWrongCurve",
+		config: Config{
+			MaxVersion:    VersionTLS13,
+			DefaultCurves: []CurveID{},
+			Bugs: ProtocolBugs{
+				MisinterpretHelloRetryRequestCurve: CurveP521,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_CURVE:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "HelloRetryRequestVersionMismatch",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			// P-384 requires HelloRetryRequest in BoringSSL.
+			CurvePreferences: []CurveID{CurveP384},
+			Bugs: ProtocolBugs{
+				SendServerHelloVersion: 0x0305,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_VERSION_NUMBER:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "HelloRetryRequestCurveMismatch",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			// P-384 requires HelloRetryRequest in BoringSSL.
+			CurvePreferences: []CurveID{CurveP384},
+			Bugs: ProtocolBugs{
+				// Send P-384 (correct) in the HelloRetryRequest.
+				SendHelloRetryRequestCurve: CurveP384,
+				// But send P-256 in the ServerHello.
+				SendCurve: CurveP256,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_CURVE:",
+	})
+
+	// Test the server selecting a curve that requires a HelloRetryRequest
+	// without sending it.
+	testCases = append(testCases, testCase{
+		name: "SkipHelloRetryRequest",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			// P-384 requires HelloRetryRequest in BoringSSL.
+			CurvePreferences: []CurveID{CurveP384},
+			Bugs: ProtocolBugs{
+				SkipHelloRetryRequest: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_CURVE:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "TLS13-RequestContextInHandshake",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			MinVersion: VersionTLS13,
+			ClientAuth: RequireAnyClientCert,
+			Bugs: ProtocolBugs{
+				SendRequestContext: []byte("request context"),
+			},
+		},
+		flags: []string{
+			"-cert-file", path.Join(*resourceDir, rsaCertificateFile),
+			"-key-file", path.Join(*resourceDir, rsaKeyFile),
+		},
+		shouldFail:    true,
+		expectedError: ":DECODE_ERROR:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TLS13-TrailingKeyShareData",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				TrailingKeyShareData: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":DECODE_ERROR:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "TLS13-AlwaysSelectPSKIdentity",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				AlwaysSelectPSKIdentity: true,
+			},
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_EXTENSION:",
+	})
+
+	testCases = append(testCases, testCase{
+		name: "TLS13-InvalidPSKIdentity",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SelectPSKIdentityOnResume: 1,
+			},
+		},
+		resumeSession: true,
+		shouldFail:    true,
+		expectedError: ":PSK_IDENTITY_NOT_FOUND:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TLS13-ExtraPSKIdentity",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				ExtraPSKIdentity:   true,
+				SendExtraPSKBinder: true,
+			},
+		},
+		resumeSession: true,
+	})
+
+	// Test that unknown NewSessionTicket extensions are tolerated.
+	testCases = append(testCases, testCase{
+		name: "TLS13-CustomTicketExtension",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				CustomTicketExtension: "1234",
+			},
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "TLS13-DataLessEarlyData-Reject-Client",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			MaxEarlyDataSize: 16384,
+		},
+		resumeConfig: &Config{
+			MaxVersion:       VersionTLS13,
+			MaxEarlyDataSize: 16384,
+			Bugs: ProtocolBugs{
+				AlwaysRejectEarlyData: true,
+			},
+		},
+		resumeSession: true,
+		flags: []string{
+			"-enable-early-data",
+			"-expect-early-data-info",
+			"-expect-reject-early-data",
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "TLS13-DataLessEarlyData-HRR-Client",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			MaxEarlyDataSize: 16384,
+		},
+		resumeConfig: &Config{
+			MaxVersion:       VersionTLS13,
+			MaxEarlyDataSize: 16384,
+			Bugs: ProtocolBugs{
+				SendHelloRetryRequestCookie: []byte{1, 2, 3, 4},
+			},
+		},
+		resumeSession: true,
+		flags: []string{
+			"-enable-early-data",
+			"-expect-early-data-info",
+			"-expect-reject-early-data",
+		},
+	})
+
+	// The client must check the server does not send the early_data
+	// extension while rejecting the session.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "TLS13-EarlyDataWithoutResume-Client",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			MaxEarlyDataSize: 16384,
+		},
+		resumeConfig: &Config{
+			MaxVersion:             VersionTLS13,
+			SessionTicketsDisabled: true,
+			Bugs: ProtocolBugs{
+				SendEarlyDataExtension: true,
+			},
+		},
+		resumeSession: true,
+		flags: []string{
+			"-enable-early-data",
+			"-expect-early-data-info",
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_EXTENSION:",
+	})
+
+	// The client must fail with a dedicated error code if the server
+	// responds with TLS 1.2 when offering 0-RTT.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "TLS13-EarlyDataVersionDowngrade-Client",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			MaxEarlyDataSize: 16384,
+		},
+		resumeConfig: &Config{
+			MaxVersion: VersionTLS12,
+		},
+		resumeSession: true,
+		flags: []string{
+			"-enable-early-data",
+			"-expect-early-data-info",
+		},
+		shouldFail:    true,
+		expectedError: ":WRONG_VERSION_ON_EARLY_DATA:",
+	})
+
+	// Test that the client rejects an (unsolicited) early_data extension if
+	// the server sent an HRR.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "TLS13-ServerAcceptsEarlyDataOnHRR-Client",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			MaxEarlyDataSize: 16384,
+		},
+		resumeConfig: &Config{
+			MaxVersion:       VersionTLS13,
+			MaxEarlyDataSize: 16384,
+			Bugs: ProtocolBugs{
+				SendHelloRetryRequestCookie: []byte{1, 2, 3, 4},
+				SendEarlyDataExtension:      true,
+			},
+		},
+		resumeSession: true,
+		flags: []string{
+			"-enable-early-data",
+			"-expect-early-data-info",
+		},
+		shouldFail:    true,
+		expectedError: ":UNEXPECTED_EXTENSION:",
+	})
+
+	fooString := "foo"
+	barString := "bar"
+
+	// Test that the client reports the correct ALPN after a 0-RTT reject
+	// that changed it.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "TLS13-DataLessEarlyData-ALPNMismatch-Client",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			MaxEarlyDataSize: 16384,
+			Bugs: ProtocolBugs{
+				ALPNProtocol: &fooString,
+			},
+		},
+		resumeConfig: &Config{
+			MaxVersion:       VersionTLS13,
+			MaxEarlyDataSize: 16384,
+			Bugs: ProtocolBugs{
+				ALPNProtocol: &barString,
+			},
+		},
+		resumeSession: true,
+		flags: []string{
+			"-advertise-alpn", "\x03foo\x03bar",
+			"-enable-early-data",
+			"-expect-early-data-info",
+			"-expect-reject-early-data",
+			"-expect-alpn", "foo",
+			"-expect-resume-alpn", "bar",
+		},
+	})
+
+	// Test that the client reports the correct ALPN after a 0-RTT reject if
+	// ALPN was omitted from the first connection.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "TLS13-DataLessEarlyData-ALPNOmitted1-Client",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			MaxEarlyDataSize: 16384,
+		},
+		resumeConfig: &Config{
+			MaxVersion:       VersionTLS13,
+			MaxEarlyDataSize: 16384,
+			NextProtos:       []string{"foo"},
+		},
+		resumeSession: true,
+		flags: []string{
+			"-advertise-alpn", "\x03foo\x03bar",
+			"-enable-early-data",
+			"-expect-early-data-info",
+			"-expect-reject-early-data",
+			"-expect-no-alpn",
+			"-expect-resume-alpn", "foo",
+		},
+	})
+
+	// Test that the client reports the correct ALPN after a 0-RTT reject if
+	// ALPN was omitted from the second connection.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "TLS13-DataLessEarlyData-ALPNOmitted2-Client",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			MaxEarlyDataSize: 16384,
+			NextProtos:       []string{"foo"},
+		},
+		resumeConfig: &Config{
+			MaxVersion:       VersionTLS13,
+			MaxEarlyDataSize: 16384,
+		},
+		resumeSession: true,
+		flags: []string{
+			"-advertise-alpn", "\x03foo\x03bar",
+			"-enable-early-data",
+			"-expect-early-data-info",
+			"-expect-reject-early-data",
+			"-expect-alpn", "foo",
+			"-expect-no-resume-alpn",
+		},
+	})
+
+	// Test that the client enforces ALPN match on 0-RTT accept.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "TLS13-DataLessEarlyData-BadALPNMismatch-Client",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			MaxEarlyDataSize: 16384,
+			Bugs: ProtocolBugs{
+				ALPNProtocol: &fooString,
+			},
+		},
+		resumeConfig: &Config{
+			MaxVersion:       VersionTLS13,
+			MaxEarlyDataSize: 16384,
+			Bugs: ProtocolBugs{
+				AlwaysAcceptEarlyData: true,
+				ALPNProtocol:          &barString,
+			},
+		},
+		resumeSession: true,
+		flags: []string{
+			"-advertise-alpn", "\x03foo\x03bar",
+			"-enable-early-data",
+			"-expect-early-data-info",
+		},
+		shouldFail:    true,
+		expectedError: ":ALPN_MISMATCH_ON_EARLY_DATA:",
+	})
+
+	// Test that the server correctly rejects 0-RTT when the previous
+	// session did not allow early data on resumption.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TLS13-EarlyData-NonZeroRTTSession-Server",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		resumeConfig: &Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendEarlyData:           [][]byte{{1, 2, 3, 4}},
+				ExpectEarlyDataAccepted: false,
+			},
+		},
+		resumeSession: true,
+		flags: []string{
+			"-enable-resume-early-data",
+			"-expect-reject-early-data",
+		},
+	})
+
+	// Test that we reject early data where ALPN is omitted from the first
+	// connection.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TLS13-EarlyData-ALPNOmitted1-Server",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			NextProtos: []string{},
+		},
+		resumeConfig: &Config{
+			MaxVersion: VersionTLS13,
+			NextProtos: []string{"foo"},
+			Bugs: ProtocolBugs{
+				SendEarlyData:           [][]byte{{1, 2, 3, 4}},
+				ExpectEarlyDataAccepted: false,
+			},
+		},
+		resumeSession: true,
+		flags: []string{
+			"-enable-early-data",
+			"-select-alpn", "",
+			"-select-resume-alpn", "foo",
+		},
+	})
+
+	// Test that we reject early data where ALPN is omitted from the second
+	// connection.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TLS13-EarlyData-ALPNOmitted2-Server",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			NextProtos: []string{"foo"},
+		},
+		resumeConfig: &Config{
+			MaxVersion: VersionTLS13,
+			NextProtos: []string{},
+			Bugs: ProtocolBugs{
+				SendEarlyData:           [][]byte{{1, 2, 3, 4}},
+				ExpectEarlyDataAccepted: false,
+			},
+		},
+		resumeSession: true,
+		flags: []string{
+			"-enable-early-data",
+			"-select-alpn", "foo",
+			"-select-resume-alpn", "",
+		},
+	})
+
+	// Test that we reject early data with mismatched ALPN.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TLS13-EarlyData-ALPNMismatch-Server",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			NextProtos: []string{"foo"},
+		},
+		resumeConfig: &Config{
+			MaxVersion: VersionTLS13,
+			NextProtos: []string{"bar"},
+			Bugs: ProtocolBugs{
+				SendEarlyData:           [][]byte{{1, 2, 3, 4}},
+				ExpectEarlyDataAccepted: false,
+			},
+		},
+		resumeSession: true,
+		flags: []string{
+			"-enable-early-data",
+			"-select-alpn", "foo",
+			"-select-resume-alpn", "bar",
+		},
+	})
+
+	// Test that we fail on early data with Channel ID.
+	testCases = append(testCases, testCase{
+		testType: clientTest,
+		name:     "TLS13-EarlyData-ChannelID-Client",
+		config: Config{
+			MaxVersion:       VersionTLS13,
+			MaxEarlyDataSize: 16384,
+			RequestChannelID: true,
+		},
+		resumeSession:   true,
+		expectChannelID: true,
+		shouldFail:      true,
+		expectedError:   ":CHANNEL_ID_ON_EARLY_DATA:",
+		flags: []string{
+			"-enable-early-data",
+			"-expect-early-data-info",
+			"-send-channel-id", path.Join(*resourceDir, channelIDKeyFile),
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TLS13-EarlyData-ChannelID-Server",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			ChannelID:  channelIDKey,
+			Bugs: ProtocolBugs{
+				SendEarlyData:           [][]byte{{}},
+				ExpectEarlyDataAccepted: false,
+			},
+		},
+		resumeSession:   true,
+		expectChannelID: true,
+		flags: []string{
+			"-enable-early-data",
+			"-expect-reject-early-data",
+			"-expect-channel-id",
+			base64.StdEncoding.EncodeToString(channelIDBytes),
+		},
+	})
+
+	// Test that the server rejects 0-RTT streams without end_of_early_data.
+	// The subsequent records should fail to decrypt.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TLS13-EarlyData-SkipEndOfEarlyData",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendEarlyData:           [][]byte{{1, 2, 3, 4}},
+				ExpectEarlyDataAccepted: true,
+				SkipEndOfEarlyData:      true,
+			},
+		},
+		resumeSession:      true,
+		flags:              []string{"-enable-early-data"},
+		shouldFail:         true,
+		expectedLocalError: "remote error: bad record MAC",
+		expectedError:      ":BAD_DECRYPT:",
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TLS13-EarlyData-UnexpectedHandshake-Server",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		resumeConfig: &Config{
+			MaxVersion: VersionTLS13,
+			Bugs: ProtocolBugs{
+				SendEarlyData:           [][]byte{{1, 2, 3, 4}},
+				SendStrayEarlyHandshake: true,
+				ExpectEarlyDataAccepted: true},
+		},
+		resumeSession:      true,
+		shouldFail:         true,
+		expectedError:      ":UNEXPECTED_RECORD:",
+		expectedLocalError: "remote error: unexpected message",
+		flags: []string{
+			"-enable-early-data",
+		},
+	})
+}
+
+func addTLS13CipherPreferenceTests() {
+	// Test that client preference is honored if the shim has AES hardware
+	// and ChaCha20-Poly1305 is preferred otherwise.
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TLS13-CipherPreference-Server-ChaCha20-AES",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			CipherSuites: []uint16{
+				TLS_CHACHA20_POLY1305_SHA256,
+				TLS_AES_128_GCM_SHA256,
+			},
+		},
+		flags: []string{
+			"-expect-cipher-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
+			"-expect-cipher-no-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
+		},
+	})
+
+	testCases = append(testCases, testCase{
+		testType: serverTest,
+		name:     "TLS13-CipherPreference-Server-AES-ChaCha20",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			CipherSuites: []uint16{
+				TLS_AES_128_GCM_SHA256,
+				TLS_CHACHA20_POLY1305_SHA256,
+			},
+		},
+		flags: []string{
+			"-expect-cipher-aes", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
+			"-expect-cipher-no-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
+		},
+	})
+
+	// Test that the client orders ChaCha20-Poly1305 and AES-GCM based on
+	// whether it has AES hardware.
+	testCases = append(testCases, testCase{
+		name: "TLS13-CipherPreference-Client",
+		config: Config{
+			MaxVersion: VersionTLS13,
+			// Use the client cipher order. (This is the default but
+			// is listed to be explicit.)
+			PreferServerCipherSuites: false,
+		},
+		flags: []string{
+			"-expect-cipher-aes", strconv.Itoa(int(TLS_AES_128_GCM_SHA256)),
+			"-expect-cipher-no-aes", strconv.Itoa(int(TLS_CHACHA20_POLY1305_SHA256)),
+		},
+	})
+}
+
+func addPeekTests() {
+	// Test SSL_peek works, including on empty records.
+	testCases = append(testCases, testCase{
+		name:             "Peek-Basic",
+		sendEmptyRecords: 1,
+		flags:            []string{"-peek-then-read"},
+	})
+
+	// Test SSL_peek can drive the initial handshake.
+	testCases = append(testCases, testCase{
+		name: "Peek-ImplicitHandshake",
+		flags: []string{
+			"-peek-then-read",
+			"-implicit-handshake",
+		},
+	})
+
+	// Test SSL_peek can discover and drive a renegotiation.
+	testCases = append(testCases, testCase{
+		name: "Peek-Renegotiate",
+		config: Config{
+			MaxVersion: VersionTLS12,
+		},
+		renegotiate: 1,
+		flags: []string{
+			"-peek-then-read",
+			"-renegotiate-freely",
+			"-expect-total-renegotiations", "1",
+		},
+	})
+
+	// Test SSL_peek can discover a close_notify.
+	testCases = append(testCases, testCase{
+		name: "Peek-Shutdown",
+		config: Config{
+			Bugs: ProtocolBugs{
+				ExpectCloseNotify: true,
+			},
+		},
+		flags: []string{
+			"-peek-then-read",
+			"-check-close-notify",
+		},
+	})
+
+	// Test SSL_peek can discover an alert.
+	testCases = append(testCases, testCase{
+		name: "Peek-Alert",
+		config: Config{
+			Bugs: ProtocolBugs{
+				SendSpuriousAlert: alertRecordOverflow,
+			},
+		},
+		flags:         []string{"-peek-then-read"},
+		shouldFail:    true,
+		expectedError: ":TLSV1_ALERT_RECORD_OVERFLOW:",
+	})
+
+	// Test SSL_peek can handle KeyUpdate.
+	testCases = append(testCases, testCase{
+		name: "Peek-KeyUpdate",
+		config: Config{
+			MaxVersion: VersionTLS13,
+		},
+		sendKeyUpdates:   1,
+		keyUpdateRequest: keyUpdateNotRequested,
+		flags:            []string{"-peek-then-read"},
+	})
+}
+
+func addRecordVersionTests() {
+	for _, ver := range tlsVersions {
+		// Test that the record version is enforced.
+		testCases = append(testCases, testCase{
+			name: "CheckRecordVersion-" + ver.name,
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				Bugs: ProtocolBugs{
+					SendRecordVersion: 0x03ff,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":WRONG_VERSION_NUMBER:",
+		})
+
+		// Test that the ClientHello may use any record version, for
+		// compatibility reasons.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "LooseInitialRecordVersion-" + ver.name,
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				Bugs: ProtocolBugs{
+					SendInitialRecordVersion: 0x03ff,
+				},
+			},
+		})
+
+		// Test that garbage ClientHello record versions are rejected.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "GarbageInitialRecordVersion-" + ver.name,
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+				Bugs: ProtocolBugs{
+					SendInitialRecordVersion: 0xffff,
+				},
+			},
+			shouldFail:    true,
+			expectedError: ":WRONG_VERSION_NUMBER:",
 		})
 	}
 }
 
-func addKeyExchangeInfoTests() {
-	testCases = append(testCases, testCase{
-		name: "KeyExchangeInfo-RSA-Client",
-		config: Config{
-			CipherSuites: []uint16{TLS_RSA_WITH_AES_128_GCM_SHA256},
-		},
-		// key.pem is a 1024-bit RSA key.
-		flags: []string{"-expect-key-exchange-info", "1024"},
-	})
-	// TODO(davidben): key_exchange_info doesn't work for plain RSA on the
-	// server. Either fix this or change the API as it's not very useful in
-	// this case.
-
-	testCases = append(testCases, testCase{
-		name: "KeyExchangeInfo-DHE-Client",
-		config: Config{
-			CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
-			Bugs: ProtocolBugs{
-				// This is a 1234-bit prime number, generated
-				// with:
-				// openssl gendh 1234 | openssl asn1parse -i
-				DHGroupPrime: bigFromHex("0215C589A86BE450D1255A86D7A08877A70E124C11F0C75E476BA6A2186B1C830D4A132555973F2D5881D5F737BB800B7F417C01EC5960AEBF79478F8E0BBB6A021269BD10590C64C57F50AD8169D5488B56EE38DC5E02DA1A16ED3B5F41FEB2AD184B78A31F3A5B2BEC8441928343DA35DE3D4F89F0D4CEDE0034045084A0D1E6182E5EF7FCA325DD33CE81BE7FA87D43613E8FA7A1457099AB53"),
+func addCertificateTests() {
+	// Test that a certificate chain with intermediate may be sent and
+	// received as both client and server.
+	for _, ver := range tlsVersions {
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			name:     "SendReceiveIntermediate-Client-" + ver.name,
+			config: Config{
+				MinVersion:   ver.version,
+				MaxVersion:   ver.version,
+				Certificates: []Certificate{rsaChainCertificate},
+				ClientAuth:   RequireAnyClientCert,
 			},
-		},
-		flags: []string{"-expect-key-exchange-info", "1234"},
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "KeyExchangeInfo-DHE-Server",
-		config: Config{
-			CipherSuites: []uint16{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256},
-		},
-		// bssl_shim as a server configures a 2048-bit DHE group.
-		flags: []string{"-expect-key-exchange-info", "2048"},
-	})
+			expectPeerCertificate: &rsaChainCertificate,
+			flags: []string{
+				"-cert-file", path.Join(*resourceDir, rsaChainCertificateFile),
+				"-key-file", path.Join(*resourceDir, rsaChainKeyFile),
+				"-expect-peer-cert-file", path.Join(*resourceDir, rsaChainCertificateFile),
+			},
+		})
 
-	testCases = append(testCases, testCase{
-		name: "KeyExchangeInfo-ECDHE-Client",
-		config: Config{
-			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-			CurvePreferences: []CurveID{CurveX25519},
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "SendReceiveIntermediate-Server-" + ver.name,
+			config: Config{
+				MinVersion:   ver.version,
+				MaxVersion:   ver.version,
+				Certificates: []Certificate{rsaChainCertificate},
+			},
+			expectPeerCertificate: &rsaChainCertificate,
+			flags: []string{
+				"-cert-file", path.Join(*resourceDir, rsaChainCertificateFile),
+				"-key-file", path.Join(*resourceDir, rsaChainKeyFile),
+				"-require-any-client-certificate",
+				"-expect-peer-cert-file", path.Join(*resourceDir, rsaChainCertificateFile),
+			},
+		})
+	}
+}
+
+func addRetainOnlySHA256ClientCertTests() {
+	for _, ver := range tlsVersions {
+		// Test that enabling
+		// SSL_CTX_set_retain_only_sha256_of_client_certs without
+		// actually requesting a client certificate is a no-op.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "RetainOnlySHA256-NoCert-" + ver.name,
+			config: Config{
+				MinVersion: ver.version,
+				MaxVersion: ver.version,
+			},
+			flags: []string{
+				"-retain-only-sha256-client-cert-initial",
+				"-retain-only-sha256-client-cert-resume",
+			},
+			resumeSession: true,
+		})
+
+		// Test that when retaining only a SHA-256 certificate is
+		// enabled, the hash appears as expected.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "RetainOnlySHA256-Cert-" + ver.name,
+			config: Config{
+				MinVersion:   ver.version,
+				MaxVersion:   ver.version,
+				Certificates: []Certificate{rsaCertificate},
+			},
+			flags: []string{
+				"-verify-peer",
+				"-retain-only-sha256-client-cert-initial",
+				"-retain-only-sha256-client-cert-resume",
+				"-expect-sha256-client-cert-initial",
+				"-expect-sha256-client-cert-resume",
+			},
+			resumeSession: true,
+		})
+
+		// Test that when the config changes from on to off, a
+		// resumption is rejected because the server now wants the full
+		// certificate chain.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "RetainOnlySHA256-OnOff-" + ver.name,
+			config: Config{
+				MinVersion:   ver.version,
+				MaxVersion:   ver.version,
+				Certificates: []Certificate{rsaCertificate},
+			},
+			flags: []string{
+				"-verify-peer",
+				"-retain-only-sha256-client-cert-initial",
+				"-expect-sha256-client-cert-initial",
+			},
+			resumeSession:        true,
+			expectResumeRejected: true,
+		})
+
+		// Test that when the config changes from off to on, a
+		// resumption is rejected because the server now wants just the
+		// hash.
+		testCases = append(testCases, testCase{
+			testType: serverTest,
+			name:     "RetainOnlySHA256-OffOn-" + ver.name,
+			config: Config{
+				MinVersion:   ver.version,
+				MaxVersion:   ver.version,
+				Certificates: []Certificate{rsaCertificate},
+			},
+			flags: []string{
+				"-verify-peer",
+				"-retain-only-sha256-client-cert-resume",
+				"-expect-sha256-client-cert-resume",
+			},
+			resumeSession:        true,
+			expectResumeRejected: true,
+		})
+	}
+}
+
+func addECDSAKeyUsageTests() {
+	p256 := elliptic.P256()
+	priv, err := ecdsa.GenerateKey(p256, rand.Reader)
+	if err != nil {
+		panic(err)
+	}
+
+	serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
+	serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
+	if err != nil {
+		panic(err)
+	}
+
+	template := x509.Certificate{
+		SerialNumber: serialNumber,
+		Subject: pkix.Name{
+			Organization: []string{"Acme Co"},
 		},
-		flags: []string{"-expect-key-exchange-info", "29", "-enable-all-curves"},
-	})
-	testCases = append(testCases, testCase{
-		testType: serverTest,
-		name:     "KeyExchangeInfo-ECDHE-Server",
-		config: Config{
-			CipherSuites:     []uint16{TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256},
-			CurvePreferences: []CurveID{CurveX25519},
-		},
-		flags: []string{"-expect-key-exchange-info", "29", "-enable-all-curves"},
-	})
+		NotBefore: time.Now(),
+		NotAfter:  time.Now(),
+
+		// An ECC certificate with only the keyAgreement key usgae may
+		// be used with ECDH, but not ECDSA.
+		KeyUsage:              x509.KeyUsageKeyAgreement,
+		ExtKeyUsage:           []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
+		BasicConstraintsValid: true,
+	}
+
+	derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv)
+	if err != nil {
+		panic(err)
+	}
+
+	cert := Certificate{
+		Certificate: [][]byte{derBytes},
+		PrivateKey:  priv,
+	}
+
+	for _, ver := range tlsVersions {
+		if ver.version < VersionTLS12 {
+			continue
+		}
+
+		testCases = append(testCases, testCase{
+			testType: clientTest,
+			name:     "ECDSAKeyUsage-" + ver.name,
+			config: Config{
+				MinVersion:   ver.version,
+				MaxVersion:   ver.version,
+				Certificates: []Certificate{cert},
+			},
+			shouldFail:    true,
+			expectedError: ":ECC_CERT_NOT_FOR_SIGNING:",
+		})
+	}
 }
 
 func worker(statusChan chan statusMsg, c chan *testCase, shimPath string, wg *sync.WaitGroup) {
@@ -4731,10 +10746,7 @@
 	for test := range c {
 		var err error
 
-		if *mallocTest < 0 {
-			statusChan <- statusMsg{test: test, started: true}
-			err = runTest(test, shimPath, -1)
-		} else {
+		if *mallocTest >= 0 {
 			for mallocNumToFail := int64(*mallocTest); ; mallocNumToFail++ {
 				statusChan <- statusMsg{test: test, started: true}
 				if err = runTest(test, shimPath, mallocNumToFail); err != errMoreMallocs {
@@ -4744,6 +10756,14 @@
 					break
 				}
 			}
+		} else if *repeatUntilFailure {
+			for err == nil {
+				statusChan <- statusMsg{test: test, started: true}
+				err = runTest(test, shimPath, -1)
+			}
+		} else {
+			statusChan <- statusMsg{test: test, started: true}
+			err = runTest(test, shimPath, -1)
 		}
 		statusChan <- statusMsg{test: test, err: err}
 	}
@@ -4756,7 +10776,7 @@
 }
 
 func statusPrinter(doneChan chan *testOutput, statusChan chan statusMsg, total int) {
-	var started, done, failed, lineLen int
+	var started, done, failed, unimplemented, lineLen int
 
 	testOutput := newTestOutput()
 	for msg := range statusChan {
@@ -4775,9 +10795,18 @@
 			done++
 
 			if msg.err != nil {
-				fmt.Printf("FAILED (%s)\n%s\n", msg.test.name, msg.err)
-				failed++
-				testOutput.addResult(msg.test.name, "FAIL")
+				if msg.err == errUnimplemented {
+					if *pipe {
+						// Print each test instead of a status line.
+						fmt.Printf("UNIMPLEMENTED (%s)\n", msg.test.name)
+					}
+					unimplemented++
+					testOutput.addResult(msg.test.name, "UNIMPLEMENTED")
+				} else {
+					fmt.Printf("FAILED (%s)\n%s\n", msg.test.name, msg.err)
+					failed++
+					testOutput.addResult(msg.test.name, "FAIL")
+				}
 			} else {
 				if *pipe {
 					// Print each test instead of a status line.
@@ -4789,7 +10818,7 @@
 
 		if !*pipe {
 			// Print a new status line.
-			line := fmt.Sprintf("%d/%d/%d/%d", failed, done, started, total)
+			line := fmt.Sprintf("%d/%d/%d/%d/%d", failed, unimplemented, done, started, total)
 			lineLen = len(line)
 			os.Stdout.WriteString(line)
 		}
@@ -4801,6 +10830,7 @@
 func main() {
 	flag.Parse()
 	*resourceDir = path.Clean(*resourceDir)
+	initCertificates()
 
 	addBasicTests()
 	addCipherSuiteTests()
@@ -4816,21 +10846,26 @@
 	addExtendedMasterSecretTests()
 	addRenegotiationTests()
 	addDTLSReplayTests()
-	addSigningHashTests()
+	addSignatureAlgorithmTests()
 	addDTLSRetransmitTests()
 	addExportKeyingMaterialTests()
 	addTLSUniqueTests()
 	addCustomExtensionTests()
 	addRSAClientKeyExchangeTests()
 	addCurveTests()
-	addKeyExchangeInfoTests()
-	for _, async := range []bool{false, true} {
-		for _, splitHandshake := range []bool{false, true} {
-			for _, protocol := range []protocol{tls, dtls} {
-				addStateMachineCoverageTests(async, splitHandshake, protocol)
-			}
-		}
-	}
+	addSessionTicketTests()
+	addTLS13RecordTests()
+	addAllStateMachineCoverageTests()
+	addChangeCipherSpecTests()
+	addWrongMessageTypeTests()
+	addTrailingMessageDataTests()
+	addTLS13HandshakeTests()
+	addTLS13CipherPreferenceTests()
+	addPeekTests()
+	addRecordVersionTests()
+	addCertificateTests()
+	addRetainOnlySHA256ClientCertTests()
+	addECDSAKeyUsageTests()
 
 	var wg sync.WaitGroup
 
@@ -4838,6 +10873,19 @@
 	testChan := make(chan *testCase, *numWorkers)
 	doneChan := make(chan *testOutput)
 
+	if len(*shimConfigFile) != 0 {
+		encoded, err := ioutil.ReadFile(*shimConfigFile)
+		if err != nil {
+			fmt.Fprintf(os.Stderr, "Couldn't read config file %q: %s\n", *shimConfigFile, err)
+			os.Exit(1)
+		}
+
+		if err := json.Unmarshal(encoded, &shimConfig); err != nil {
+			fmt.Fprintf(os.Stderr, "Couldn't decode config file %q: %s\n", *shimConfigFile, err)
+			os.Exit(1)
+		}
+	}
+
 	go statusPrinter(doneChan, statusChan, len(testCases))
 
 	for i := 0; i < *numWorkers; i++ {
@@ -4845,10 +10893,47 @@
 		go worker(statusChan, testChan, *shimPath, &wg)
 	}
 
+	var foundTest bool
 	for i := range testCases {
-		if len(*testToRun) == 0 || *testToRun == testCases[i].name {
-			testChan <- &testCases[i]
+		matched := true
+		if len(*testToRun) != 0 {
+			var err error
+			matched, err = filepath.Match(*testToRun, testCases[i].name)
+			if err != nil {
+				fmt.Fprintf(os.Stderr, "Error matching pattern: %s\n", err)
+				os.Exit(1)
+			}
 		}
+
+		if !*includeDisabled {
+			for pattern := range shimConfig.DisabledTests {
+				isDisabled, err := filepath.Match(pattern, testCases[i].name)
+				if err != nil {
+					fmt.Fprintf(os.Stderr, "Error matching pattern %q from config file: %s\n", pattern, err)
+					os.Exit(1)
+				}
+
+				if isDisabled {
+					matched = false
+					break
+				}
+			}
+		}
+
+		if matched {
+			foundTest = true
+			testChan <- &testCases[i]
+
+			// Only run one test if repeating until failure.
+			if *repeatUntilFailure {
+				break
+			}
+		}
+	}
+
+	if !foundTest {
+		fmt.Fprintf(os.Stderr, "No tests run\n")
+		os.Exit(1)
 	}
 
 	close(testChan)
@@ -4864,7 +10949,11 @@
 		}
 	}
 
-	if !testOutput.allPassed {
+	if !*allowUnimplemented && testOutput.NumFailuresByType["UNIMPLEMENTED"] > 0 {
+		os.Exit(1)
+	}
+
+	if !testOutput.noneFailed {
 		os.Exit(1)
 	}
 }
diff --git a/src/ssl/test/runner/runner_test.go b/src/ssl/test/runner/runner_test.go
index 320ff52..6c7fcb0 100644
--- a/src/ssl/test/runner/runner_test.go
+++ b/src/ssl/test/runner/runner_test.go
@@ -1,3 +1,17 @@
+// Copyright (c) 2016, Google Inc.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
 package runner
 
 import "testing"
diff --git a/src/ssl/test/runner/shim_ticket.go b/src/ssl/test/runner/shim_ticket.go
new file mode 100644
index 0000000..9e57d48
--- /dev/null
+++ b/src/ssl/test/runner/shim_ticket.go
@@ -0,0 +1,249 @@
+// Copyright (c) 2016, Google Inc.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+package runner
+
+import (
+	"bytes"
+	"crypto/aes"
+	"crypto/cipher"
+	"crypto/hmac"
+	"crypto/sha256"
+	"encoding/asn1"
+	"errors"
+)
+
+// TestShimTicketKey is the testing key assumed for the shim.
+var TestShimTicketKey = make([]byte, 48)
+
+func DecryptShimTicket(in []byte) ([]byte, error) {
+	name := TestShimTicketKey[:16]
+	macKey := TestShimTicketKey[16:32]
+	encKey := TestShimTicketKey[32:48]
+
+	h := hmac.New(sha256.New, macKey)
+
+	block, err := aes.NewCipher(encKey)
+	if err != nil {
+		panic(err)
+	}
+
+	if len(in) < len(name)+block.BlockSize()+1+h.Size() {
+		return nil, errors.New("tls: shim ticket too short")
+	}
+
+	// Check the key name.
+	if !bytes.Equal(name, in[:len(name)]) {
+		return nil, errors.New("tls: shim ticket name mismatch")
+	}
+
+	// Check the MAC at the end of the ticket.
+	mac := in[len(in)-h.Size():]
+	in = in[:len(in)-h.Size()]
+	h.Write(in)
+	if !hmac.Equal(mac, h.Sum(nil)) {
+		return nil, errors.New("tls: shim ticket MAC mismatch")
+	}
+
+	// The MAC covers the key name, but the encryption does not.
+	in = in[len(name):]
+
+	// Decrypt in-place.
+	iv := in[:block.BlockSize()]
+	in = in[block.BlockSize():]
+	if l := len(in); l == 0 || l%block.BlockSize() != 0 {
+		return nil, errors.New("tls: ticket ciphertext not a multiple of the block size")
+	}
+	out := make([]byte, len(in))
+	cbc := cipher.NewCBCDecrypter(block, iv)
+	cbc.CryptBlocks(out, in)
+
+	// Remove the padding.
+	pad := int(out[len(out)-1])
+	if pad == 0 || pad > block.BlockSize() || pad > len(in) {
+		return nil, errors.New("tls: bad shim ticket CBC pad")
+	}
+
+	for i := 0; i < pad; i++ {
+		if out[len(out)-1-i] != byte(pad) {
+			return nil, errors.New("tls: bad shim ticket CBC pad")
+		}
+	}
+
+	return out[:len(out)-pad], nil
+}
+
+func EncryptShimTicket(in []byte) []byte {
+	name := TestShimTicketKey[:16]
+	macKey := TestShimTicketKey[16:32]
+	encKey := TestShimTicketKey[32:48]
+
+	h := hmac.New(sha256.New, macKey)
+
+	block, err := aes.NewCipher(encKey)
+	if err != nil {
+		panic(err)
+	}
+
+	// Use the zero IV for rewritten tickets.
+	iv := make([]byte, block.BlockSize())
+	cbc := cipher.NewCBCEncrypter(block, iv)
+	pad := block.BlockSize() - (len(in) % block.BlockSize())
+
+	out := make([]byte, 0, len(name)+len(iv)+len(in)+pad+h.Size())
+	out = append(out, name...)
+	out = append(out, iv...)
+	out = append(out, in...)
+	for i := 0; i < pad; i++ {
+		out = append(out, byte(pad))
+	}
+
+	ciphertext := out[len(name)+len(iv):]
+	cbc.CryptBlocks(ciphertext, ciphertext)
+
+	h.Write(out)
+	return h.Sum(out)
+}
+
+const asn1Constructed = 0x20
+
+func parseDERElement(in []byte) (tag byte, body, rest []byte, ok bool) {
+	rest = in
+	if len(rest) < 1 {
+		return
+	}
+
+	tag = rest[0]
+	rest = rest[1:]
+
+	if tag&0x1f == 0x1f {
+		// Long-form tags not supported.
+		return
+	}
+
+	if len(rest) < 1 {
+		return
+	}
+
+	length := int(rest[0])
+	rest = rest[1:]
+	if length > 0x7f {
+		lengthLength := length & 0x7f
+		length = 0
+		if lengthLength == 0 {
+			// No indefinite-length encoding.
+			return
+		}
+
+		// Decode long-form lengths.
+		for lengthLength > 0 {
+			if len(rest) < 1 || (length<<8)>>8 != length {
+				return
+			}
+			if length == 0 && rest[0] == 0 {
+				// Length not minimally-encoded.
+				return
+			}
+			length <<= 8
+			length |= int(rest[0])
+			rest = rest[1:]
+			lengthLength--
+		}
+
+		if length < 0x80 {
+			// Length not minimally-encoded.
+			return
+		}
+	}
+
+	if len(rest) < length {
+		return
+	}
+
+	body = rest[:length]
+	rest = rest[length:]
+	ok = true
+	return
+}
+
+func SetShimTicketVersion(in []byte, vers uint16) ([]byte, error) {
+	plaintext, err := DecryptShimTicket(in)
+	if err != nil {
+		return nil, err
+	}
+
+	tag, session, _, ok := parseDERElement(plaintext)
+	if !ok || tag != asn1.TagSequence|asn1Constructed {
+		return nil, errors.New("tls: could not decode shim session")
+	}
+
+	// Skip the session version.
+	tag, _, session, ok = parseDERElement(session)
+	if !ok || tag != asn1.TagInteger {
+		return nil, errors.New("tls: could not decode shim session")
+	}
+
+	// Next field is the protocol version.
+	tag, version, _, ok := parseDERElement(session)
+	if !ok || tag != asn1.TagInteger {
+		return nil, errors.New("tls: could not decode shim session")
+	}
+
+	// This code assumes both old and new versions are encoded in two
+	// bytes. This isn't quite right as INTEGERs are minimally-encoded, but
+	// we do not need to support other caess for now.
+	if len(version) != 2 || vers < 0x80 || vers >= 0x8000 {
+		return nil, errors.New("tls: unsupported version in shim session")
+	}
+
+	version[0] = byte(vers >> 8)
+	version[1] = byte(vers)
+
+	return EncryptShimTicket(plaintext), nil
+}
+
+func SetShimTicketCipherSuite(in []byte, id uint16) ([]byte, error) {
+	plaintext, err := DecryptShimTicket(in)
+	if err != nil {
+		return nil, err
+	}
+
+	tag, session, _, ok := parseDERElement(plaintext)
+	if !ok || tag != asn1.TagSequence|asn1Constructed {
+		return nil, errors.New("tls: could not decode shim session")
+	}
+
+	// Skip the session version.
+	tag, _, session, ok = parseDERElement(session)
+	if !ok || tag != asn1.TagInteger {
+		return nil, errors.New("tls: could not decode shim session")
+	}
+
+	// Skip the protocol version.
+	tag, _, session, ok = parseDERElement(session)
+	if !ok || tag != asn1.TagInteger {
+		return nil, errors.New("tls: could not decode shim session")
+	}
+
+	// Next field is the cipher suite.
+	tag, cipherSuite, _, ok := parseDERElement(session)
+	if !ok || tag != asn1.TagOctetString || len(cipherSuite) != 2 {
+		return nil, errors.New("tls: could not decode shim session")
+	}
+
+	cipherSuite[0] = byte(id >> 8)
+	cipherSuite[1] = byte(id)
+
+	return EncryptShimTicket(plaintext), nil
+}
diff --git a/src/ssl/test/runner/sign.go b/src/ssl/test/runner/sign.go
new file mode 100644
index 0000000..5f56ff9
--- /dev/null
+++ b/src/ssl/test/runner/sign.go
@@ -0,0 +1,297 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package runner
+
+import (
+	"crypto"
+	"crypto/ecdsa"
+	"crypto/elliptic"
+	"crypto/md5"
+	"crypto/rsa"
+	"crypto/sha1"
+	_ "crypto/sha256"
+	_ "crypto/sha512"
+	"encoding/asn1"
+	"errors"
+	"fmt"
+	"math/big"
+)
+
+type signer interface {
+	supportsKey(key crypto.PrivateKey) bool
+	signMessage(key crypto.PrivateKey, config *Config, msg []byte) ([]byte, error)
+	verifyMessage(key crypto.PublicKey, msg, sig []byte) error
+}
+
+func selectSignatureAlgorithm(version uint16, key crypto.PrivateKey, config *Config, peerSigAlgs []signatureAlgorithm) (signatureAlgorithm, error) {
+	// If the client didn't specify any signature_algorithms extension then
+	// we can assume that it supports SHA1. See
+	// http://tools.ietf.org/html/rfc5246#section-7.4.1.4.1
+	if len(peerSigAlgs) == 0 {
+		peerSigAlgs = []signatureAlgorithm{signatureRSAPKCS1WithSHA1, signatureECDSAWithSHA1}
+	}
+
+	for _, sigAlg := range config.signSignatureAlgorithms() {
+		if !isSupportedSignatureAlgorithm(sigAlg, peerSigAlgs) {
+			continue
+		}
+
+		signer, err := getSigner(version, key, config, sigAlg)
+		if err != nil {
+			continue
+		}
+
+		if signer.supportsKey(key) {
+			return sigAlg, nil
+		}
+	}
+	return 0, errors.New("tls: no common signature algorithms")
+}
+
+func signMessage(version uint16, key crypto.PrivateKey, config *Config, sigAlg signatureAlgorithm, msg []byte) ([]byte, error) {
+	if config.Bugs.InvalidSignature {
+		newMsg := make([]byte, len(msg))
+		copy(newMsg, msg)
+		newMsg[0] ^= 0x80
+		msg = newMsg
+	}
+
+	signer, err := getSigner(version, key, config, sigAlg)
+	if err != nil {
+		return nil, err
+	}
+
+	return signer.signMessage(key, config, msg)
+}
+
+func verifyMessage(version uint16, key crypto.PublicKey, config *Config, sigAlg signatureAlgorithm, msg, sig []byte) error {
+	if version >= VersionTLS12 && !isSupportedSignatureAlgorithm(sigAlg, config.verifySignatureAlgorithms()) {
+		return errors.New("tls: unsupported signature algorithm")
+	}
+
+	signer, err := getSigner(version, key, config, sigAlg)
+	if err != nil {
+		return err
+	}
+
+	return signer.verifyMessage(key, msg, sig)
+}
+
+type rsaPKCS1Signer struct {
+	hash crypto.Hash
+}
+
+func (r *rsaPKCS1Signer) computeHash(msg []byte) []byte {
+	if r.hash == crypto.MD5SHA1 {
+		// crypto.MD5SHA1 is not a real hash function.
+		hashMD5 := md5.New()
+		hashMD5.Write(msg)
+		hashSHA1 := sha1.New()
+		hashSHA1.Write(msg)
+		return hashSHA1.Sum(hashMD5.Sum(nil))
+	}
+
+	h := r.hash.New()
+	h.Write(msg)
+	return h.Sum(nil)
+}
+
+func (r *rsaPKCS1Signer) supportsKey(key crypto.PrivateKey) bool {
+	_, ok := key.(*rsa.PrivateKey)
+	return ok
+}
+
+func (r *rsaPKCS1Signer) signMessage(key crypto.PrivateKey, config *Config, msg []byte) ([]byte, error) {
+	rsaKey, ok := key.(*rsa.PrivateKey)
+	if !ok {
+		return nil, errors.New("invalid key type for RSA-PKCS1")
+	}
+
+	return rsa.SignPKCS1v15(config.rand(), rsaKey, r.hash, r.computeHash(msg))
+}
+
+func (r *rsaPKCS1Signer) verifyMessage(key crypto.PublicKey, msg, sig []byte) error {
+	rsaKey, ok := key.(*rsa.PublicKey)
+	if !ok {
+		return errors.New("invalid key type for RSA-PKCS1")
+	}
+
+	return rsa.VerifyPKCS1v15(rsaKey, r.hash, r.computeHash(msg), sig)
+}
+
+type ecdsaSigner struct {
+	version uint16
+	config  *Config
+	curve   elliptic.Curve
+	hash    crypto.Hash
+}
+
+func (e *ecdsaSigner) isCurveValid(curve elliptic.Curve) bool {
+	if e.config.Bugs.SkipECDSACurveCheck {
+		return true
+	}
+	if e.version <= VersionTLS12 {
+		return true
+	}
+	return e.curve != nil && curve == e.curve
+}
+
+func (e *ecdsaSigner) supportsKey(key crypto.PrivateKey) bool {
+	ecdsaKey, ok := key.(*ecdsa.PrivateKey)
+	return ok && e.isCurveValid(ecdsaKey.Curve)
+}
+
+func maybeCorruptECDSAValue(n *big.Int, typeOfCorruption BadValue, limit *big.Int) *big.Int {
+	switch typeOfCorruption {
+	case BadValueNone:
+		return n
+	case BadValueNegative:
+		return new(big.Int).Neg(n)
+	case BadValueZero:
+		return big.NewInt(0)
+	case BadValueLimit:
+		return limit
+	case BadValueLarge:
+		bad := new(big.Int).Set(limit)
+		return bad.Lsh(bad, 20)
+	default:
+		panic("unknown BadValue type")
+	}
+}
+
+func (e *ecdsaSigner) signMessage(key crypto.PrivateKey, config *Config, msg []byte) ([]byte, error) {
+	ecdsaKey, ok := key.(*ecdsa.PrivateKey)
+	if !ok {
+		return nil, errors.New("invalid key type for ECDSA")
+	}
+	if !e.isCurveValid(ecdsaKey.Curve) {
+		return nil, errors.New("invalid curve for ECDSA")
+	}
+
+	h := e.hash.New()
+	h.Write(msg)
+	digest := h.Sum(nil)
+
+	r, s, err := ecdsa.Sign(config.rand(), ecdsaKey, digest)
+	if err != nil {
+		return nil, errors.New("failed to sign ECDHE parameters: " + err.Error())
+	}
+	order := ecdsaKey.Curve.Params().N
+	r = maybeCorruptECDSAValue(r, config.Bugs.BadECDSAR, order)
+	s = maybeCorruptECDSAValue(s, config.Bugs.BadECDSAS, order)
+	return asn1.Marshal(ecdsaSignature{r, s})
+}
+
+func (e *ecdsaSigner) verifyMessage(key crypto.PublicKey, msg, sig []byte) error {
+	ecdsaKey, ok := key.(*ecdsa.PublicKey)
+	if !ok {
+		return errors.New("invalid key type for ECDSA")
+	}
+	if !e.isCurveValid(ecdsaKey.Curve) {
+		return errors.New("invalid curve for ECDSA")
+	}
+
+	ecdsaSig := new(ecdsaSignature)
+	if _, err := asn1.Unmarshal(sig, ecdsaSig); err != nil {
+		return err
+	}
+	if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
+		return errors.New("ECDSA signature contained zero or negative values")
+	}
+
+	h := e.hash.New()
+	h.Write(msg)
+	if !ecdsa.Verify(ecdsaKey, h.Sum(nil), ecdsaSig.R, ecdsaSig.S) {
+		return errors.New("ECDSA verification failure")
+	}
+	return nil
+}
+
+var pssOptions = rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash}
+
+type rsaPSSSigner struct {
+	hash crypto.Hash
+}
+
+func (r *rsaPSSSigner) supportsKey(key crypto.PrivateKey) bool {
+	_, ok := key.(*rsa.PrivateKey)
+	return ok
+}
+
+func (r *rsaPSSSigner) signMessage(key crypto.PrivateKey, config *Config, msg []byte) ([]byte, error) {
+	rsaKey, ok := key.(*rsa.PrivateKey)
+	if !ok {
+		return nil, errors.New("invalid key type for RSA-PSS")
+	}
+
+	h := r.hash.New()
+	h.Write(msg)
+	return rsa.SignPSS(config.rand(), rsaKey, r.hash, h.Sum(nil), &pssOptions)
+}
+
+func (r *rsaPSSSigner) verifyMessage(key crypto.PublicKey, msg, sig []byte) error {
+	rsaKey, ok := key.(*rsa.PublicKey)
+	if !ok {
+		return errors.New("invalid key type for RSA-PSS")
+	}
+
+	h := r.hash.New()
+	h.Write(msg)
+	return rsa.VerifyPSS(rsaKey, r.hash, h.Sum(nil), sig, &pssOptions)
+}
+
+func getSigner(version uint16, key interface{}, config *Config, sigAlg signatureAlgorithm) (signer, error) {
+	// TLS 1.1 and below use legacy signature algorithms.
+	if version < VersionTLS12 {
+		switch key.(type) {
+		case *rsa.PrivateKey, *rsa.PublicKey:
+			return &rsaPKCS1Signer{crypto.MD5SHA1}, nil
+		case *ecdsa.PrivateKey, *ecdsa.PublicKey:
+			return &ecdsaSigner{version, config, nil, crypto.SHA1}, nil
+		default:
+			return nil, errors.New("unknown key type")
+		}
+	}
+
+	// TODO(davidben): Forbid RSASSA-PKCS1-v1_5 in TLS 1.3.
+	switch sigAlg {
+	case signatureRSAPKCS1WithMD5:
+		if version < VersionTLS13 || config.Bugs.IgnoreSignatureVersionChecks {
+			return &rsaPKCS1Signer{crypto.MD5}, nil
+		}
+	case signatureRSAPKCS1WithSHA1:
+		if version < VersionTLS13 || config.Bugs.IgnoreSignatureVersionChecks {
+			return &rsaPKCS1Signer{crypto.SHA1}, nil
+		}
+	case signatureRSAPKCS1WithSHA256:
+		if version < VersionTLS13 || config.Bugs.IgnoreSignatureVersionChecks {
+			return &rsaPKCS1Signer{crypto.SHA256}, nil
+		}
+	case signatureRSAPKCS1WithSHA384:
+		if version < VersionTLS13 || config.Bugs.IgnoreSignatureVersionChecks {
+			return &rsaPKCS1Signer{crypto.SHA384}, nil
+		}
+	case signatureRSAPKCS1WithSHA512:
+		if version < VersionTLS13 || config.Bugs.IgnoreSignatureVersionChecks {
+			return &rsaPKCS1Signer{crypto.SHA512}, nil
+		}
+	case signatureECDSAWithSHA1:
+		return &ecdsaSigner{version, config, nil, crypto.SHA1}, nil
+	case signatureECDSAWithP256AndSHA256:
+		return &ecdsaSigner{version, config, elliptic.P256(), crypto.SHA256}, nil
+	case signatureECDSAWithP384AndSHA384:
+		return &ecdsaSigner{version, config, elliptic.P384(), crypto.SHA384}, nil
+	case signatureECDSAWithP521AndSHA512:
+		return &ecdsaSigner{version, config, elliptic.P521(), crypto.SHA512}, nil
+	case signatureRSAPSSWithSHA256:
+		return &rsaPSSSigner{crypto.SHA256}, nil
+	case signatureRSAPSSWithSHA384:
+		return &rsaPSSSigner{crypto.SHA384}, nil
+	case signatureRSAPSSWithSHA512:
+		return &rsaPSSSigner{crypto.SHA512}, nil
+	}
+
+	return nil, fmt.Errorf("unsupported signature algorithm %04x", sigAlg)
+}
diff --git a/src/ssl/test/runner/test_output.go b/src/ssl/test/runner/test_output.go
index 2112092..eb54638 100644
--- a/src/ssl/test/runner/test_output.go
+++ b/src/ssl/test/runner/test_output.go
@@ -29,7 +29,7 @@
 	SecondsSinceEpoch float64               `json:"seconds_since_epoch"`
 	NumFailuresByType map[string]int        `json:"num_failures_by_type"`
 	Tests             map[string]testResult `json:"tests"`
-	allPassed         bool
+	noneFailed        bool
 }
 
 type testResult struct {
@@ -45,7 +45,7 @@
 		SecondsSinceEpoch: float64(time.Now().UnixNano()) / float64(time.Second/time.Nanosecond),
 		NumFailuresByType: make(map[string]int),
 		Tests:             make(map[string]testResult),
-		allPassed:         true,
+		noneFailed:        true,
 	}
 }
 
@@ -59,8 +59,8 @@
 		IsUnexpected: result != "PASS",
 	}
 	t.NumFailuresByType[result]++
-	if result != "PASS" {
-		t.allPassed = false
+	if result != "PASS" && result != "UNIMPLEMENTED" {
+		t.noneFailed = false
 	}
 }
 
diff --git a/src/ssl/test/runner/ticket.go b/src/ssl/test/runner/ticket.go
index e121c05..10ac54f 100644
--- a/src/ssl/test/runner/ticket.go
+++ b/src/ssl/test/runner/ticket.go
@@ -5,14 +5,15 @@
 package runner
 
 import (
-	"bytes"
 	"crypto/aes"
 	"crypto/cipher"
 	"crypto/hmac"
 	"crypto/sha256"
 	"crypto/subtle"
+	"encoding/binary"
 	"errors"
 	"io"
+	"time"
 )
 
 // sessionState contains the information that is serialized into a session
@@ -24,79 +25,44 @@
 	handshakeHash        []byte
 	certificates         [][]byte
 	extendedMasterSecret bool
-}
-
-func (s *sessionState) equal(i interface{}) bool {
-	s1, ok := i.(*sessionState)
-	if !ok {
-		return false
-	}
-
-	if s.vers != s1.vers ||
-		s.cipherSuite != s1.cipherSuite ||
-		!bytes.Equal(s.masterSecret, s1.masterSecret) ||
-		!bytes.Equal(s.handshakeHash, s1.handshakeHash) ||
-		s.extendedMasterSecret != s1.extendedMasterSecret {
-		return false
-	}
-
-	if len(s.certificates) != len(s1.certificates) {
-		return false
-	}
-
-	for i := range s.certificates {
-		if !bytes.Equal(s.certificates[i], s1.certificates[i]) {
-			return false
-		}
-	}
-
-	return true
+	earlyALPN            []byte
+	ticketCreationTime   time.Time
+	ticketExpiration     time.Time
+	ticketFlags          uint32
+	ticketAgeAdd         uint32
 }
 
 func (s *sessionState) marshal() []byte {
-	length := 2 + 2 + 2 + len(s.masterSecret) + 2 + len(s.handshakeHash) + 2
+	msg := newByteBuilder()
+	msg.addU16(s.vers)
+	msg.addU16(s.cipherSuite)
+	masterSecret := msg.addU16LengthPrefixed()
+	masterSecret.addBytes(s.masterSecret)
+	handshakeHash := msg.addU16LengthPrefixed()
+	handshakeHash.addBytes(s.handshakeHash)
+	msg.addU16(uint16(len(s.certificates)))
 	for _, cert := range s.certificates {
-		length += 4 + len(cert)
-	}
-	length++
-
-	ret := make([]byte, length)
-	x := ret
-	x[0] = byte(s.vers >> 8)
-	x[1] = byte(s.vers)
-	x[2] = byte(s.cipherSuite >> 8)
-	x[3] = byte(s.cipherSuite)
-	x[4] = byte(len(s.masterSecret) >> 8)
-	x[5] = byte(len(s.masterSecret))
-	x = x[6:]
-	copy(x, s.masterSecret)
-	x = x[len(s.masterSecret):]
-
-	x[0] = byte(len(s.handshakeHash) >> 8)
-	x[1] = byte(len(s.handshakeHash))
-	x = x[2:]
-	copy(x, s.handshakeHash)
-	x = x[len(s.handshakeHash):]
-
-	x[0] = byte(len(s.certificates) >> 8)
-	x[1] = byte(len(s.certificates))
-	x = x[2:]
-
-	for _, cert := range s.certificates {
-		x[0] = byte(len(cert) >> 24)
-		x[1] = byte(len(cert) >> 16)
-		x[2] = byte(len(cert) >> 8)
-		x[3] = byte(len(cert))
-		copy(x[4:], cert)
-		x = x[4+len(cert):]
+		certMsg := msg.addU32LengthPrefixed()
+		certMsg.addBytes(cert)
 	}
 
 	if s.extendedMasterSecret {
-		x[0] = 1
+		msg.addU8(1)
+	} else {
+		msg.addU8(0)
 	}
-	x = x[1:]
 
-	return ret
+	if s.vers >= VersionTLS13 {
+		msg.addU64(uint64(s.ticketCreationTime.UnixNano()))
+		msg.addU64(uint64(s.ticketExpiration.UnixNano()))
+		msg.addU32(s.ticketFlags)
+		msg.addU32(s.ticketAgeAdd)
+	}
+
+	earlyALPN := msg.addU16LengthPrefixed()
+	earlyALPN.addBytes(s.earlyALPN)
+
+	return msg.finish()
 }
 
 func (s *sessionState) unmarshal(data []byte) bool {
@@ -162,6 +128,28 @@
 	}
 	data = data[1:]
 
+	if s.vers >= VersionTLS13 {
+		if len(data) < 24 {
+			return false
+		}
+		s.ticketCreationTime = time.Unix(0, int64(binary.BigEndian.Uint64(data)))
+		data = data[8:]
+		s.ticketExpiration = time.Unix(0, int64(binary.BigEndian.Uint64(data)))
+		data = data[8:]
+		s.ticketFlags = binary.BigEndian.Uint32(data)
+		data = data[4:]
+		s.ticketAgeAdd = binary.BigEndian.Uint32(data)
+		data = data[4:]
+	}
+
+	earlyALPNLen := int(data[0])<<8 | int(data[1])
+	data = data[2:]
+	if len(data) < earlyALPNLen {
+		return false
+	}
+	s.earlyALPN = data[:earlyALPNLen]
+	data = data[earlyALPNLen:]
+
 	if len(data) > 0 {
 		return false
 	}
diff --git a/src/ssl/test/test_config.cc b/src/ssl/test/test_config.cc
index 1cf316d..7e57543 100644
--- a/src/ssl/test/test_config.cc
+++ b/src/ssl/test/test_config.cc
@@ -46,7 +46,6 @@
 const Flag<bool> kBoolFlags[] = {
   { "-server", &TestConfig::is_server },
   { "-dtls", &TestConfig::is_dtls },
-  { "-resume", &TestConfig::resume },
   { "-fallback-scsv", &TestConfig::fallback_scsv },
   { "-require-any-client-certificate",
     &TestConfig::require_any_client_certificate },
@@ -56,12 +55,15 @@
     &TestConfig::write_different_record_sizes },
   { "-cbc-record-splitting", &TestConfig::cbc_record_splitting },
   { "-partial-write", &TestConfig::partial_write },
+  { "-no-tls13", &TestConfig::no_tls13 },
   { "-no-tls12", &TestConfig::no_tls12 },
   { "-no-tls11", &TestConfig::no_tls11 },
   { "-no-tls1", &TestConfig::no_tls1 },
   { "-no-ssl3", &TestConfig::no_ssl3 },
+  { "-enable-channel-id", &TestConfig::enable_channel_id },
   { "-shim-writes-first", &TestConfig::shim_writes_first },
   { "-expect-session-miss", &TestConfig::expect_session_miss },
+  { "-decline-alpn", &TestConfig::decline_alpn },
   { "-expect-extended-master-secret",
     &TestConfig::expect_extended_master_secret },
   { "-enable-ocsp-stapling", &TestConfig::enable_ocsp_stapling },
@@ -73,13 +75,17 @@
   { "-install-ddos-callback", &TestConfig::install_ddos_callback },
   { "-fail-ddos-callback", &TestConfig::fail_ddos_callback },
   { "-fail-second-ddos-callback", &TestConfig::fail_second_ddos_callback },
+  { "-fail-cert-callback", &TestConfig::fail_cert_callback },
   { "-handshake-never-done", &TestConfig::handshake_never_done },
   { "-use-export-context", &TestConfig::use_export_context },
   { "-tls-unique", &TestConfig::tls_unique },
   { "-expect-ticket-renewal", &TestConfig::expect_ticket_renewal },
   { "-expect-no-session", &TestConfig::expect_no_session },
+  { "-expect-early-data-info", &TestConfig::expect_early_data_info },
   { "-use-ticket-callback", &TestConfig::use_ticket_callback },
   { "-renew-ticket", &TestConfig::renew_ticket },
+  { "-enable-early-data", &TestConfig::enable_early_data },
+  { "-enable-resume-early-data", &TestConfig::enable_resume_early_data },
   { "-enable-client-custom-extension",
     &TestConfig::enable_client_custom_extension },
   { "-enable-server-custom-extension",
@@ -94,10 +100,34 @@
   { "-renegotiate-once", &TestConfig::renegotiate_once },
   { "-renegotiate-freely", &TestConfig::renegotiate_freely },
   { "-renegotiate-ignore", &TestConfig::renegotiate_ignore },
-  { "-disable-npn", &TestConfig::disable_npn },
   { "-p384-only", &TestConfig::p384_only },
   { "-enable-all-curves", &TestConfig::enable_all_curves },
   { "-use-sparse-dh-prime", &TestConfig::use_sparse_dh_prime },
+  { "-use-old-client-cert-callback",
+    &TestConfig::use_old_client_cert_callback },
+  { "-send-alert", &TestConfig::send_alert },
+  { "-peek-then-read", &TestConfig::peek_then_read },
+  { "-enable-grease", &TestConfig::enable_grease },
+  { "-use-exporter-between-reads", &TestConfig::use_exporter_between_reads },
+  { "-retain-only-sha256-client-cert-initial",
+    &TestConfig::retain_only_sha256_client_cert_initial },
+  { "-retain-only-sha256-client-cert-resume",
+    &TestConfig::retain_only_sha256_client_cert_resume },
+  { "-expect-sha256-client-cert-initial",
+    &TestConfig::expect_sha256_client_cert_initial },
+  { "-expect-sha256-client-cert-resume",
+    &TestConfig::expect_sha256_client_cert_resume },
+  { "-read-with-unfinished-write", &TestConfig::read_with_unfinished_write },
+  { "-expect-secure-renegotiation",
+    &TestConfig::expect_secure_renegotiation },
+  { "-expect-no-secure-renegotiation",
+    &TestConfig::expect_no_secure_renegotiation },
+  { "-expect-session-id", &TestConfig::expect_session_id },
+  { "-expect-no-session-id", &TestConfig::expect_no_session_id },
+  { "-expect-accept-early-data", &TestConfig::expect_accept_early_data },
+  { "-expect-reject-early-data", &TestConfig::expect_reject_early_data },
+  { "-expect-no-alpn", &TestConfig::expect_no_alpn },
+  { "-expect-no-resume-alpn", &TestConfig::expect_no_resume_alpn },
 };
 
 const Flag<std::string> kStringFlags[] = {
@@ -112,16 +142,19 @@
   { "-host-name", &TestConfig::host_name },
   { "-advertise-alpn", &TestConfig::advertise_alpn },
   { "-expect-alpn", &TestConfig::expected_alpn },
+  { "-expect-resume-alpn", &TestConfig::expected_resume_alpn },
   { "-expect-advertised-alpn", &TestConfig::expected_advertised_alpn },
   { "-select-alpn", &TestConfig::select_alpn },
+  { "-select-resume-alpn", &TestConfig::select_resume_alpn },
   { "-psk", &TestConfig::psk },
   { "-psk-identity", &TestConfig::psk_identity },
   { "-srtp-profiles", &TestConfig::srtp_profiles },
   { "-cipher", &TestConfig::cipher },
-  { "-cipher-tls10", &TestConfig::cipher_tls10 },
-  { "-cipher-tls11", &TestConfig::cipher_tls11 },
   { "-export-label", &TestConfig::export_label },
   { "-export-context", &TestConfig::export_context },
+  { "-expect-peer-cert-file", &TestConfig::expect_peer_cert_file },
+  { "-use-client-ca-list", &TestConfig::use_client_ca_list },
+  { "-expect-client-ca-list", &TestConfig::expected_client_ca_list },
 };
 
 const Flag<std::string> kBase64Flags[] = {
@@ -132,19 +165,33 @@
     &TestConfig::expected_signed_cert_timestamps },
   { "-ocsp-response", &TestConfig::ocsp_response },
   { "-signed-cert-timestamps", &TestConfig::signed_cert_timestamps },
+  { "-ticket-key", &TestConfig::ticket_key },
 };
 
 const Flag<int> kIntFlags[] = {
   { "-port", &TestConfig::port },
+  { "-resume-count", &TestConfig::resume_count },
   { "-min-version", &TestConfig::min_version },
   { "-max-version", &TestConfig::max_version },
   { "-mtu", &TestConfig::mtu },
   { "-export-keying-material", &TestConfig::export_keying_material },
   { "-expect-total-renegotiations", &TestConfig::expect_total_renegotiations },
-  { "-expect-server-key-exchange-hash",
-    &TestConfig::expect_server_key_exchange_hash },
-  { "-expect-key-exchange-info",
-    &TestConfig::expect_key_exchange_info },
+  { "-expect-peer-signature-algorithm",
+    &TestConfig::expect_peer_signature_algorithm },
+  { "-expect-curve-id", &TestConfig::expect_curve_id },
+  { "-expect-resume-curve-id", &TestConfig::expect_resume_curve_id },
+  { "-initial-timeout-duration-ms", &TestConfig::initial_timeout_duration_ms },
+  { "-max-cert-list", &TestConfig::max_cert_list },
+  { "-expect-cipher-aes", &TestConfig::expect_cipher_aes },
+  { "-expect-cipher-no-aes", &TestConfig::expect_cipher_no_aes },
+  { "-resumption-delay", &TestConfig::resumption_delay },
+  { "-max-send-fragment", &TestConfig::max_send_fragment },
+  { "-read-size", &TestConfig::read_size },
+  { "-expect-ticket-age-skew", &TestConfig::expect_ticket_age_skew },
+};
+
+const Flag<std::vector<int>> kIntVectorFlags[] = {
+  { "-signing-prefs", &TestConfig::signing_prefs },
 };
 
 }  // namespace
@@ -178,12 +225,14 @@
       size_t len;
       if (!EVP_DecodedLength(&len, strlen(argv[i]))) {
         fprintf(stderr, "Invalid base64: %s\n", argv[i]);
+        return false;
       }
       std::unique_ptr<uint8_t[]> decoded(new uint8_t[len]);
       if (!EVP_DecodeBase64(decoded.get(), &len, len,
                             reinterpret_cast<const uint8_t *>(argv[i]),
                             strlen(argv[i]))) {
         fprintf(stderr, "Invalid base64: %s\n", argv[i]);
+        return false;
       }
       base64_field->assign(reinterpret_cast<const char *>(decoded.get()), len);
       continue;
@@ -200,6 +249,20 @@
       continue;
     }
 
+    std::vector<int> *int_vector_field =
+        FindField(out_config, kIntVectorFlags, argv[i]);
+    if (int_vector_field) {
+      i++;
+      if (i >= argc) {
+        fprintf(stderr, "Missing parameter\n");
+        return false;
+      }
+
+      // Each instance of the flag adds to the list.
+      int_vector_field->push_back(atoi(argv[i]));
+      continue;
+    }
+
     fprintf(stderr, "Unknown argument: %s\n", argv[i]);
     return false;
   }
diff --git a/src/ssl/test/test_config.h b/src/ssl/test/test_config.h
index 4e0a46a..fadd05e 100644
--- a/src/ssl/test/test_config.h
+++ b/src/ssl/test/test_config.h
@@ -16,15 +16,17 @@
 #define HEADER_TEST_CONFIG
 
 #include <string>
+#include <vector>
 
 
 struct TestConfig {
   int port = 0;
   bool is_server = false;
   bool is_dtls = false;
-  bool resume = false;
+  int resume_count = 0;
   bool fallback_scsv = false;
   std::string digest_prefs;
+  std::vector<int> signing_prefs;
   std::string key_file;
   std::string cert_file;
   std::string expected_server_name;
@@ -38,18 +40,25 @@
   bool write_different_record_sizes = false;
   bool cbc_record_splitting = false;
   bool partial_write = false;
+  bool no_tls13 = false;
   bool no_tls12 = false;
   bool no_tls11 = false;
   bool no_tls1 = false;
   bool no_ssl3 = false;
   std::string expected_channel_id;
+  bool enable_channel_id = false;
   std::string send_channel_id;
   bool shim_writes_first = false;
   std::string host_name;
   std::string advertise_alpn;
   std::string expected_alpn;
+  std::string expected_resume_alpn;
+  bool expect_no_alpn = false;
+  bool expect_no_resume_alpn = false;
   std::string expected_advertised_alpn;
   std::string select_alpn;
+  std::string select_resume_alpn;
+  bool decline_alpn = false;
   bool expect_session_miss = false;
   bool expect_extended_master_secret = false;
   std::string psk;
@@ -68,9 +77,8 @@
   bool install_ddos_callback = false;
   bool fail_ddos_callback = false;
   bool fail_second_ddos_callback = false;
+  bool fail_cert_callback = false;
   std::string cipher;
-  std::string cipher_tls10;
-  std::string cipher_tls11;
   bool handshake_never_done = false;
   int export_keying_material = 0;
   std::string export_label;
@@ -79,8 +87,13 @@
   bool tls_unique = false;
   bool expect_ticket_renewal = false;
   bool expect_no_session = false;
+  bool expect_early_data_info = false;
+  bool expect_accept_early_data = false;
+  bool expect_reject_early_data = false;
   bool use_ticket_callback = false;
   bool renew_ticket = false;
+  bool enable_early_data = false;
+  bool enable_resume_early_data = false;
   bool enable_client_custom_extension = false;
   bool enable_server_custom_extension = false;
   bool custom_extension_skip = false;
@@ -96,12 +109,38 @@
   bool renegotiate_once = false;
   bool renegotiate_freely = false;
   bool renegotiate_ignore = false;
-  bool disable_npn = false;
-  int expect_server_key_exchange_hash = 0;
+  int expect_peer_signature_algorithm = 0;
   bool p384_only = false;
   bool enable_all_curves = false;
   bool use_sparse_dh_prime = false;
-  int expect_key_exchange_info = 0;
+  int expect_curve_id = 0;
+  int expect_resume_curve_id = 0;
+  bool use_old_client_cert_callback = false;
+  int initial_timeout_duration_ms = 0;
+  std::string use_client_ca_list;
+  std::string expected_client_ca_list;
+  bool send_alert = false;
+  bool peek_then_read = false;
+  bool enable_grease = false;
+  int max_cert_list = 0;
+  std::string ticket_key;
+  bool use_exporter_between_reads = false;
+  int expect_cipher_aes = 0;
+  int expect_cipher_no_aes = 0;
+  std::string expect_peer_cert_file;
+  int resumption_delay = 0;
+  bool retain_only_sha256_client_cert_initial = false;
+  bool retain_only_sha256_client_cert_resume = false;
+  bool expect_sha256_client_cert_initial = false;
+  bool expect_sha256_client_cert_resume = false;
+  bool read_with_unfinished_write = false;
+  bool expect_secure_renegotiation = false;
+  bool expect_no_secure_renegotiation = false;
+  int max_send_fragment = 0;
+  int read_size = 0;
+  bool expect_session_id = false;
+  bool expect_no_session_id = false;
+  int expect_ticket_age_skew = 0;
 };
 
 bool ParseConfig(int argc, char **argv, TestConfig *out_config);
diff --git a/src/ssl/tls13_both.c b/src/ssl/tls13_both.c
new file mode 100644
index 0000000..ec67cdc
--- /dev/null
+++ b/src/ssl/tls13_both.c
@@ -0,0 +1,657 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/ssl.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/bytestring.h>
+#include <openssl/err.h>
+#include <openssl/hkdf.h>
+#include <openssl/mem.h>
+#include <openssl/stack.h>
+#include <openssl/x509.h>
+
+#include "../crypto/internal.h"
+#include "internal.h"
+
+
+/* kMaxKeyUpdates is the number of consecutive KeyUpdates that will be
+ * processed. Without this limit an attacker could force unbounded processing
+ * without being able to return application data. */
+static const uint8_t kMaxKeyUpdates = 32;
+
+int tls13_handshake(SSL_HANDSHAKE *hs, int *out_early_return) {
+  SSL *const ssl = hs->ssl;
+  for (;;) {
+    /* Resolve the operation the handshake was waiting on. */
+    switch (hs->wait) {
+      case ssl_hs_error:
+        OPENSSL_PUT_ERROR(SSL, SSL_R_SSL_HANDSHAKE_FAILURE);
+        return -1;
+
+      case ssl_hs_flush:
+      case ssl_hs_flush_and_read_message: {
+        int ret = ssl->method->flush_flight(ssl);
+        if (ret <= 0) {
+          return ret;
+        }
+        if (hs->wait != ssl_hs_flush_and_read_message) {
+          break;
+        }
+        ssl->method->expect_flight(ssl);
+        hs->wait = ssl_hs_read_message;
+        /* Fall-through. */
+      }
+
+      case ssl_hs_read_message: {
+        int ret = ssl->method->ssl_get_message(ssl);
+        if (ret <= 0) {
+          return ret;
+        }
+        break;
+      }
+
+      case ssl_hs_read_end_of_early_data: {
+        if (ssl->s3->hs->can_early_read) {
+          /* While we are processing early data, the handshake returns early. */
+          *out_early_return = 1;
+          return 1;
+        }
+        hs->wait = ssl_hs_ok;
+        break;
+      }
+
+      case ssl_hs_x509_lookup:
+        ssl->rwstate = SSL_X509_LOOKUP;
+        hs->wait = ssl_hs_ok;
+        return -1;
+
+      case ssl_hs_channel_id_lookup:
+        ssl->rwstate = SSL_CHANNEL_ID_LOOKUP;
+        hs->wait = ssl_hs_ok;
+        return -1;
+
+      case ssl_hs_private_key_operation:
+        ssl->rwstate = SSL_PRIVATE_KEY_OPERATION;
+        hs->wait = ssl_hs_ok;
+        return -1;
+
+      case ssl_hs_pending_ticket:
+        ssl->rwstate = SSL_PENDING_TICKET;
+        hs->wait = ssl_hs_ok;
+        return -1;
+
+      case ssl_hs_ok:
+        break;
+    }
+
+    /* Run the state machine again. */
+    hs->wait = hs->do_tls13_handshake(hs);
+    if (hs->wait == ssl_hs_error) {
+      /* Don't loop around to avoid a stray |SSL_R_SSL_HANDSHAKE_FAILURE| the
+       * first time around. */
+      return -1;
+    }
+    if (hs->wait == ssl_hs_ok) {
+      /* The handshake has completed. */
+      return 1;
+    }
+
+    /* Otherwise, loop to the beginning and resolve what was blocking the
+     * handshake. */
+  }
+}
+
+int tls13_get_cert_verify_signature_input(
+    SSL_HANDSHAKE *hs, uint8_t **out, size_t *out_len,
+    enum ssl_cert_verify_context_t cert_verify_context) {
+  CBB cbb;
+  if (!CBB_init(&cbb, 64 + 33 + 1 + 2 * EVP_MAX_MD_SIZE)) {
+    goto err;
+  }
+
+  for (size_t i = 0; i < 64; i++) {
+    if (!CBB_add_u8(&cbb, 0x20)) {
+      goto err;
+    }
+  }
+
+  const uint8_t *context;
+  size_t context_len;
+  if (cert_verify_context == ssl_cert_verify_server) {
+    /* Include the NUL byte. */
+    static const char kContext[] = "TLS 1.3, server CertificateVerify";
+    context = (const uint8_t *)kContext;
+    context_len = sizeof(kContext);
+  } else if (cert_verify_context == ssl_cert_verify_client) {
+    static const char kContext[] = "TLS 1.3, client CertificateVerify";
+    context = (const uint8_t *)kContext;
+    context_len = sizeof(kContext);
+  } else if (cert_verify_context == ssl_cert_verify_channel_id) {
+    static const char kContext[] = "TLS 1.3, Channel ID";
+    context = (const uint8_t *)kContext;
+    context_len = sizeof(kContext);
+  } else {
+    goto err;
+  }
+
+  if (!CBB_add_bytes(&cbb, context, context_len)) {
+    goto err;
+  }
+
+  uint8_t context_hash[EVP_MAX_MD_SIZE];
+  size_t context_hash_len;
+  if (!SSL_TRANSCRIPT_get_hash(&hs->transcript, context_hash,
+                               &context_hash_len) ||
+      !CBB_add_bytes(&cbb, context_hash, context_hash_len) ||
+      !CBB_finish(&cbb, out, out_len)) {
+    goto err;
+  }
+
+  return 1;
+
+err:
+  OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+  CBB_cleanup(&cbb);
+  return 0;
+}
+
+int tls13_process_certificate(SSL_HANDSHAKE *hs, int allow_anonymous) {
+  SSL *const ssl = hs->ssl;
+  CBS cbs, context, certificate_list;
+  CBS_init(&cbs, ssl->init_msg, ssl->init_num);
+  if (!CBS_get_u8_length_prefixed(&cbs, &context) ||
+      CBS_len(&context) != 0) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    return 0;
+  }
+
+  const int retain_sha256 =
+      ssl->server && ssl->retain_only_sha256_of_client_certs;
+  int ret = 0;
+
+  EVP_PKEY *pkey = NULL;
+  STACK_OF(CRYPTO_BUFFER) *certs = sk_CRYPTO_BUFFER_new_null();
+  if (certs == NULL) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+    goto err;
+  }
+
+  if (!CBS_get_u24_length_prefixed(&cbs, &certificate_list)) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    goto err;
+  }
+
+  while (CBS_len(&certificate_list) > 0) {
+    CBS certificate, extensions;
+    if (!CBS_get_u24_length_prefixed(&certificate_list, &certificate) ||
+        !CBS_get_u16_length_prefixed(&certificate_list, &extensions) ||
+        CBS_len(&certificate) == 0) {
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+      OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_LENGTH_MISMATCH);
+      goto err;
+    }
+
+    if (sk_CRYPTO_BUFFER_num(certs) == 0) {
+      pkey = ssl_cert_parse_pubkey(&certificate);
+      if (pkey == NULL) {
+        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+        OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+        goto err;
+      }
+      /* TLS 1.3 always uses certificate keys for signing thus the correct
+       * keyUsage is enforced. */
+      if (!ssl_cert_check_digital_signature_key_usage(&certificate)) {
+        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+        goto err;
+      }
+
+      if (retain_sha256) {
+        /* Retain the hash of the leaf certificate if requested. */
+        SHA256(CBS_data(&certificate), CBS_len(&certificate),
+               hs->new_session->peer_sha256);
+      }
+    }
+
+    CRYPTO_BUFFER *buf =
+        CRYPTO_BUFFER_new_from_CBS(&certificate, ssl->ctx->pool);
+    if (buf == NULL ||
+        !sk_CRYPTO_BUFFER_push(certs, buf)) {
+      CRYPTO_BUFFER_free(buf);
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+      OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
+      goto err;
+    }
+
+    /* Parse out the extensions. */
+    int have_status_request = 0, have_sct = 0;
+    CBS status_request, sct;
+    const SSL_EXTENSION_TYPE ext_types[] = {
+        {TLSEXT_TYPE_status_request, &have_status_request, &status_request},
+        {TLSEXT_TYPE_certificate_timestamp, &have_sct, &sct},
+    };
+
+    uint8_t alert = SSL_AD_DECODE_ERROR;
+    if (!ssl_parse_extensions(&extensions, &alert, ext_types,
+                              OPENSSL_ARRAY_SIZE(ext_types),
+                              0 /* reject unknown */)) {
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
+      goto err;
+    }
+
+    /* All Certificate extensions are parsed, but only the leaf extensions are
+     * stored. */
+    if (have_status_request) {
+      if (ssl->server || !ssl->ocsp_stapling_enabled) {
+        OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
+        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION);
+        goto err;
+      }
+
+      uint8_t status_type;
+      CBS ocsp_response;
+      if (!CBS_get_u8(&status_request, &status_type) ||
+          status_type != TLSEXT_STATUSTYPE_ocsp ||
+          !CBS_get_u24_length_prefixed(&status_request, &ocsp_response) ||
+          CBS_len(&ocsp_response) == 0 ||
+          CBS_len(&status_request) != 0) {
+        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+        goto err;
+      }
+
+      if (sk_CRYPTO_BUFFER_num(certs) == 1 &&
+          !CBS_stow(&ocsp_response, &hs->new_session->ocsp_response,
+                    &hs->new_session->ocsp_response_length)) {
+        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+        goto err;
+      }
+    }
+
+    if (have_sct) {
+      if (ssl->server || !ssl->signed_cert_timestamps_enabled) {
+        OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
+        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION);
+        goto err;
+      }
+
+      if (!ssl_is_sct_list_valid(&sct)) {
+        OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION);
+        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+        goto err;
+      }
+
+      if (sk_CRYPTO_BUFFER_num(certs) == 1 &&
+          !CBS_stow(
+              &sct, &hs->new_session->tlsext_signed_cert_timestamp_list,
+              &hs->new_session->tlsext_signed_cert_timestamp_list_length)) {
+        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+        goto err;
+      }
+    }
+  }
+
+  if (CBS_len(&cbs) != 0) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+    goto err;
+  }
+
+  EVP_PKEY_free(hs->peer_pubkey);
+  hs->peer_pubkey = pkey;
+  pkey = NULL;
+
+  sk_CRYPTO_BUFFER_pop_free(hs->new_session->certs, CRYPTO_BUFFER_free);
+  hs->new_session->certs = certs;
+  certs = NULL;
+
+  if (!ssl->ctx->x509_method->session_cache_objects(hs->new_session)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+    goto err;
+  }
+
+  if (sk_CRYPTO_BUFFER_num(hs->new_session->certs) == 0) {
+    if (!allow_anonymous) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_CERTIFICATE_REQUIRED);
+      goto err;
+    }
+
+    /* OpenSSL returns X509_V_OK when no certificates are requested. This is
+     * classed by them as a bug, but it's assumed by at least NGINX. */
+    hs->new_session->verify_result = X509_V_OK;
+
+    /* No certificate, so nothing more to do. */
+    ret = 1;
+    goto err;
+  }
+
+  hs->new_session->peer_sha256_valid = retain_sha256;
+
+  if (!ssl->ctx->x509_method->session_verify_cert_chain(hs->new_session,
+                                                        ssl)) {
+    goto err;
+  }
+
+  ret = 1;
+
+err:
+  sk_CRYPTO_BUFFER_pop_free(certs, CRYPTO_BUFFER_free);
+  EVP_PKEY_free(pkey);
+  return ret;
+}
+
+int tls13_process_certificate_verify(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  int ret = 0;
+  uint8_t *msg = NULL;
+  size_t msg_len;
+
+  if (hs->peer_pubkey == NULL) {
+    goto err;
+  }
+
+  CBS cbs, signature;
+  uint16_t signature_algorithm;
+  CBS_init(&cbs, ssl->init_msg, ssl->init_num);
+  if (!CBS_get_u16(&cbs, &signature_algorithm) ||
+      !CBS_get_u16_length_prefixed(&cbs, &signature) ||
+      CBS_len(&cbs) != 0) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+    goto err;
+  }
+
+  int al;
+  if (!tls12_check_peer_sigalg(ssl, &al, signature_algorithm)) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, al);
+    goto err;
+  }
+  hs->new_session->peer_signature_algorithm = signature_algorithm;
+
+  if (!tls13_get_cert_verify_signature_input(
+          hs, &msg, &msg_len,
+          ssl->server ? ssl_cert_verify_client : ssl_cert_verify_server)) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+    goto err;
+  }
+
+  int sig_ok =
+      ssl_public_key_verify(ssl, CBS_data(&signature), CBS_len(&signature),
+                            signature_algorithm, hs->peer_pubkey, msg, msg_len);
+#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
+  sig_ok = 1;
+  ERR_clear_error();
+#endif
+  if (!sig_ok) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_SIGNATURE);
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR);
+    goto err;
+  }
+
+  ret = 1;
+
+err:
+  OPENSSL_free(msg);
+  return ret;
+}
+
+int tls13_process_finished(SSL_HANDSHAKE *hs, int use_saved_value) {
+  SSL *const ssl = hs->ssl;
+  uint8_t verify_data_buf[EVP_MAX_MD_SIZE];
+  const uint8_t *verify_data;
+  size_t verify_data_len;
+  if (use_saved_value) {
+    assert(ssl->server);
+    verify_data = hs->expected_client_finished;
+    verify_data_len = hs->hash_len;
+  } else {
+    if (!tls13_finished_mac(hs, verify_data_buf, &verify_data_len,
+                            !ssl->server)) {
+      return 0;
+    }
+    verify_data = verify_data_buf;
+  }
+
+  int finished_ok =
+      ssl->init_num == verify_data_len &&
+      CRYPTO_memcmp(verify_data, ssl->init_msg, verify_data_len) == 0;
+#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
+  finished_ok = 1;
+#endif
+  if (!finished_ok) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECRYPT_ERROR);
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DIGEST_CHECK_FAILED);
+    return 0;
+  }
+
+  return 1;
+}
+
+int tls13_add_certificate(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  CBB cbb, body, certificate_list;
+  if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_CERTIFICATE) ||
+      /* The request context is always empty in the handshake. */
+      !CBB_add_u8(&body, 0) ||
+      !CBB_add_u24_length_prefixed(&body, &certificate_list)) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    goto err;
+  }
+
+  if (!ssl_has_certificate(ssl)) {
+    if (!ssl_add_message_cbb(ssl, &cbb)) {
+      goto err;
+    }
+
+    return 1;
+  }
+
+  CERT *cert = ssl->cert;
+  CRYPTO_BUFFER *leaf_buf = sk_CRYPTO_BUFFER_value(cert->chain, 0);
+  CBB leaf, extensions;
+  if (!CBB_add_u24_length_prefixed(&certificate_list, &leaf) ||
+      !CBB_add_bytes(&leaf, CRYPTO_BUFFER_data(leaf_buf),
+                     CRYPTO_BUFFER_len(leaf_buf)) ||
+      !CBB_add_u16_length_prefixed(&certificate_list, &extensions)) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    goto err;
+  }
+
+  if (hs->scts_requested && ssl->cert->signed_cert_timestamp_list != NULL) {
+    CBB contents;
+    if (!CBB_add_u16(&extensions, TLSEXT_TYPE_certificate_timestamp) ||
+        !CBB_add_u16_length_prefixed(&extensions, &contents) ||
+        !CBB_add_bytes(
+            &contents,
+            CRYPTO_BUFFER_data(ssl->cert->signed_cert_timestamp_list),
+            CRYPTO_BUFFER_len(ssl->cert->signed_cert_timestamp_list)) ||
+        !CBB_flush(&extensions)) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+      goto err;
+    }
+  }
+
+  if (hs->ocsp_stapling_requested &&
+      ssl->cert->ocsp_response != NULL) {
+    CBB contents, ocsp_response;
+    if (!CBB_add_u16(&extensions, TLSEXT_TYPE_status_request) ||
+        !CBB_add_u16_length_prefixed(&extensions, &contents) ||
+        !CBB_add_u8(&contents, TLSEXT_STATUSTYPE_ocsp) ||
+        !CBB_add_u24_length_prefixed(&contents, &ocsp_response) ||
+        !CBB_add_bytes(&ocsp_response,
+                       CRYPTO_BUFFER_data(ssl->cert->ocsp_response),
+                       CRYPTO_BUFFER_len(ssl->cert->ocsp_response)) ||
+        !CBB_flush(&extensions)) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+      goto err;
+    }
+  }
+
+  for (size_t i = 1; i < sk_CRYPTO_BUFFER_num(cert->chain); i++) {
+    CRYPTO_BUFFER *cert_buf = sk_CRYPTO_BUFFER_value(cert->chain, i);
+    CBB child;
+    if (!CBB_add_u24_length_prefixed(&certificate_list, &child) ||
+        !CBB_add_bytes(&child, CRYPTO_BUFFER_data(cert_buf),
+                       CRYPTO_BUFFER_len(cert_buf)) ||
+        !CBB_add_u16(&certificate_list, 0 /* no extensions */)) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+      goto err;
+    }
+  }
+
+  if (!ssl_add_message_cbb(ssl, &cbb)) {
+    goto err;
+  }
+
+  return 1;
+
+err:
+  CBB_cleanup(&cbb);
+  return 0;
+}
+
+enum ssl_private_key_result_t tls13_add_certificate_verify(SSL_HANDSHAKE *hs,
+                                                           int is_first_run) {
+  SSL *const ssl = hs->ssl;
+  enum ssl_private_key_result_t ret = ssl_private_key_failure;
+  uint8_t *msg = NULL;
+  size_t msg_len;
+  CBB cbb, body;
+  CBB_zero(&cbb);
+
+  uint16_t signature_algorithm;
+  if (!tls1_choose_signature_algorithm(hs, &signature_algorithm)) {
+    goto err;
+  }
+  if (!ssl->method->init_message(ssl, &cbb, &body,
+                                 SSL3_MT_CERTIFICATE_VERIFY) ||
+      !CBB_add_u16(&body, signature_algorithm)) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    goto err;
+  }
+
+  /* Sign the digest. */
+  CBB child;
+  const size_t max_sig_len = ssl_private_key_max_signature_len(ssl);
+  uint8_t *sig;
+  size_t sig_len;
+  if (!CBB_add_u16_length_prefixed(&body, &child) ||
+      !CBB_reserve(&child, &sig, max_sig_len)) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+    goto err;
+  }
+
+  enum ssl_private_key_result_t sign_result;
+  if (is_first_run) {
+    if (!tls13_get_cert_verify_signature_input(
+            hs, &msg, &msg_len,
+            ssl->server ? ssl_cert_verify_server : ssl_cert_verify_client)) {
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+      goto err;
+    }
+    sign_result = ssl_private_key_sign(ssl, sig, &sig_len, max_sig_len,
+                                       signature_algorithm, msg, msg_len);
+  } else {
+    sign_result = ssl_private_key_complete(ssl, sig, &sig_len, max_sig_len);
+  }
+
+  if (sign_result != ssl_private_key_success) {
+    ret = sign_result;
+    goto err;
+  }
+
+  if (!CBB_did_write(&child, sig_len) ||
+      !ssl_add_message_cbb(ssl, &cbb)) {
+    goto err;
+  }
+
+  ret = ssl_private_key_success;
+
+err:
+  CBB_cleanup(&cbb);
+  OPENSSL_free(msg);
+  return ret;
+}
+
+int tls13_add_finished(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  size_t verify_data_len;
+  uint8_t verify_data[EVP_MAX_MD_SIZE];
+
+  if (!tls13_finished_mac(hs, verify_data, &verify_data_len, ssl->server)) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DIGEST_CHECK_FAILED);
+    return 0;
+  }
+
+  CBB cbb, body;
+  if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_FINISHED) ||
+      !CBB_add_bytes(&body, verify_data, verify_data_len) ||
+      !ssl_add_message_cbb(ssl, &cbb)) {
+    CBB_cleanup(&cbb);
+    return 0;
+  }
+
+  return 1;
+}
+
+static int tls13_receive_key_update(SSL *ssl) {
+  CBS cbs;
+  uint8_t key_update_request;
+  CBS_init(&cbs, ssl->init_msg, ssl->init_num);
+  if (!CBS_get_u8(&cbs, &key_update_request) ||
+      CBS_len(&cbs) != 0 ||
+      (key_update_request != SSL_KEY_UPDATE_NOT_REQUESTED &&
+       key_update_request != SSL_KEY_UPDATE_REQUESTED)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+    return 0;
+  }
+
+  /* TODO(svaldez): Send KeyUpdate if |key_update_request| is
+   * |SSL_KEY_UPDATE_REQUESTED|. */
+  return tls13_rotate_traffic_key(ssl, evp_aead_open);
+}
+
+int tls13_post_handshake(SSL *ssl) {
+  if (ssl->s3->tmp.message_type == SSL3_MT_KEY_UPDATE) {
+    ssl->s3->key_update_count++;
+    if (ssl->s3->key_update_count > kMaxKeyUpdates) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_TOO_MANY_KEY_UPDATES);
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+      return 0;
+    }
+
+    return tls13_receive_key_update(ssl);
+  }
+
+  ssl->s3->key_update_count = 0;
+
+  if (ssl->s3->tmp.message_type == SSL3_MT_NEW_SESSION_TICKET &&
+      !ssl->server) {
+    return tls13_process_new_session_ticket(ssl);
+  }
+
+  // TODO(svaldez): Handle post-handshake authentication.
+
+  ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+  OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE);
+  return 0;
+}
diff --git a/src/ssl/tls13_client.c b/src/ssl/tls13_client.c
new file mode 100644
index 0000000..0d60661
--- /dev/null
+++ b/src/ssl/tls13_client.c
@@ -0,0 +1,738 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/ssl.h>
+
+#include <assert.h>
+#include <limits.h>
+#include <string.h>
+
+#include <openssl/bytestring.h>
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/stack.h>
+
+#include "../crypto/internal.h"
+#include "internal.h"
+
+
+enum client_hs_state_t {
+  state_process_hello_retry_request = 0,
+  state_send_second_client_hello,
+  state_process_server_hello,
+  state_process_encrypted_extensions,
+  state_process_certificate_request,
+  state_process_server_certificate,
+  state_process_server_certificate_verify,
+  state_process_server_finished,
+  state_send_end_of_early_data,
+  state_send_client_certificate,
+  state_send_client_certificate_verify,
+  state_complete_client_certificate_verify,
+  state_complete_second_flight,
+  state_done,
+};
+
+static const uint8_t kZeroes[EVP_MAX_MD_SIZE] = {0};
+
+static enum ssl_hs_wait_t do_process_hello_retry_request(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  if (ssl->s3->tmp.message_type != SSL3_MT_HELLO_RETRY_REQUEST) {
+    hs->tls13_state = state_process_server_hello;
+    return ssl_hs_ok;
+  }
+
+  CBS cbs, extensions;
+  uint16_t server_wire_version;
+  CBS_init(&cbs, ssl->init_msg, ssl->init_num);
+  if (!CBS_get_u16(&cbs, &server_wire_version) ||
+      !CBS_get_u16_length_prefixed(&cbs, &extensions) ||
+      /* HelloRetryRequest may not be empty. */
+      CBS_len(&extensions) == 0 ||
+      CBS_len(&cbs) != 0) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+    return ssl_hs_error;
+  }
+
+  int have_cookie, have_key_share;
+  CBS cookie, key_share;
+  const SSL_EXTENSION_TYPE ext_types[] = {
+      {TLSEXT_TYPE_key_share, &have_key_share, &key_share},
+      {TLSEXT_TYPE_cookie, &have_cookie, &cookie},
+  };
+
+  uint8_t alert = SSL_AD_DECODE_ERROR;
+  if (!ssl_parse_extensions(&extensions, &alert, ext_types,
+                            OPENSSL_ARRAY_SIZE(ext_types),
+                            0 /* reject unknown */)) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
+    return ssl_hs_error;
+  }
+
+  if (have_cookie) {
+    CBS cookie_value;
+    if (!CBS_get_u16_length_prefixed(&cookie, &cookie_value) ||
+        CBS_len(&cookie_value) == 0 ||
+        CBS_len(&cookie) != 0) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+      return ssl_hs_error;
+    }
+
+    if (!CBS_stow(&cookie_value, &hs->cookie, &hs->cookie_len)) {
+      return ssl_hs_error;
+    }
+  }
+
+  if (have_key_share) {
+    uint16_t group_id;
+    if (!CBS_get_u16(&key_share, &group_id) || CBS_len(&key_share) != 0) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+      return ssl_hs_error;
+    }
+
+    /* The group must be supported. */
+    const uint16_t *groups;
+    size_t groups_len;
+    tls1_get_grouplist(ssl, &groups, &groups_len);
+    int found = 0;
+    for (size_t i = 0; i < groups_len; i++) {
+      if (groups[i] == group_id) {
+        found = 1;
+        break;
+      }
+    }
+
+    if (!found) {
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+      OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
+      return ssl_hs_error;
+    }
+
+    /* Check that the HelloRetryRequest does not request the key share that
+     * was provided in the initial ClientHello. */
+    if (SSL_ECDH_CTX_get_id(&hs->ecdh_ctx) == group_id) {
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+      OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
+      return ssl_hs_error;
+    }
+
+    SSL_ECDH_CTX_cleanup(&hs->ecdh_ctx);
+    hs->retry_group = group_id;
+  }
+
+  if (!ssl_hash_current_message(hs)) {
+    return ssl_hs_error;
+  }
+
+  hs->received_hello_retry_request = 1;
+  hs->tls13_state = state_send_second_client_hello;
+  return ssl_hs_ok;
+}
+
+static enum ssl_hs_wait_t do_send_second_client_hello(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  /* TODO(svaldez): Ensure that we set can_early_write to false since 0-RTT is
+   * rejected if we receive a HelloRetryRequest. */
+  if (!ssl->method->set_write_state(ssl, NULL) ||
+      !ssl_write_client_hello(hs)) {
+    return ssl_hs_error;
+  }
+
+  hs->tls13_state = state_process_server_hello;
+  return ssl_hs_flush_and_read_message;
+}
+
+static enum ssl_hs_wait_t do_process_server_hello(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  if (!ssl_check_message_type(ssl, SSL3_MT_SERVER_HELLO)) {
+    return ssl_hs_error;
+  }
+
+  CBS cbs, server_random, extensions;
+  uint16_t server_wire_version;
+  uint16_t cipher_suite;
+  CBS_init(&cbs, ssl->init_msg, ssl->init_num);
+  if (!CBS_get_u16(&cbs, &server_wire_version) ||
+      !CBS_get_bytes(&cbs, &server_random, SSL3_RANDOM_SIZE) ||
+      !CBS_get_u16(&cbs, &cipher_suite) ||
+      !CBS_get_u16_length_prefixed(&cbs, &extensions) ||
+      CBS_len(&cbs) != 0) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    return ssl_hs_error;
+  }
+
+  if (server_wire_version != ssl->version) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_VERSION_NUMBER);
+    return ssl_hs_error;
+  }
+
+  assert(ssl->s3->have_version);
+  OPENSSL_memcpy(ssl->s3->server_random, CBS_data(&server_random),
+                 SSL3_RANDOM_SIZE);
+
+  const SSL_CIPHER *cipher = SSL_get_cipher_by_value(cipher_suite);
+  if (cipher == NULL) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_CIPHER_RETURNED);
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+    return ssl_hs_error;
+  }
+
+  /* Check if the cipher is a TLS 1.3 cipher. */
+  if (SSL_CIPHER_get_min_version(cipher) > ssl3_protocol_version(ssl) ||
+      SSL_CIPHER_get_max_version(cipher) < ssl3_protocol_version(ssl)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CIPHER_RETURNED);
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+    return ssl_hs_error;
+  }
+
+  /* Parse out the extensions. */
+  int have_key_share = 0, have_pre_shared_key = 0;
+  CBS key_share, pre_shared_key;
+  const SSL_EXTENSION_TYPE ext_types[] = {
+      {TLSEXT_TYPE_key_share, &have_key_share, &key_share},
+      {TLSEXT_TYPE_pre_shared_key, &have_pre_shared_key, &pre_shared_key},
+  };
+
+  uint8_t alert = SSL_AD_DECODE_ERROR;
+  if (!ssl_parse_extensions(&extensions, &alert, ext_types,
+                            OPENSSL_ARRAY_SIZE(ext_types),
+                            0 /* reject unknown */)) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
+    return ssl_hs_error;
+  }
+
+  alert = SSL_AD_DECODE_ERROR;
+  if (have_pre_shared_key) {
+    if (ssl->session == NULL) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_EXTENSION);
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNSUPPORTED_EXTENSION);
+      return ssl_hs_error;
+    }
+
+    if (!ssl_ext_pre_shared_key_parse_serverhello(hs, &alert,
+                                                  &pre_shared_key)) {
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
+      return ssl_hs_error;
+    }
+
+    if (ssl->session->ssl_version != ssl->version) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_OLD_SESSION_VERSION_NOT_RETURNED);
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+      return ssl_hs_error;
+    }
+
+    if (ssl->session->cipher->algorithm_prf != cipher->algorithm_prf) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_OLD_SESSION_PRF_HASH_MISMATCH);
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+      return ssl_hs_error;
+    }
+
+    if (!ssl_session_is_context_valid(ssl, ssl->session)) {
+      /* This is actually a client application bug. */
+      OPENSSL_PUT_ERROR(SSL,
+                        SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+      return ssl_hs_error;
+    }
+
+    ssl->s3->session_reused = 1;
+    /* Only authentication information carries over in TLS 1.3. */
+    hs->new_session = SSL_SESSION_dup(ssl->session, SSL_SESSION_DUP_AUTH_ONLY);
+    if (hs->new_session == NULL) {
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+      return ssl_hs_error;
+    }
+
+    /* Resumption incorporates fresh key material, so refresh the timeout. */
+    ssl_session_renew_timeout(ssl, hs->new_session,
+                              ssl->session_ctx->session_psk_dhe_timeout);
+  } else if (!ssl_get_new_session(hs, 0)) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+    return ssl_hs_error;
+  }
+
+  hs->new_session->cipher = cipher;
+  hs->new_cipher = cipher;
+
+  /* The PRF hash is now known. Set up the key schedule. */
+  if (!tls13_init_key_schedule(hs)) {
+    return ssl_hs_error;
+  }
+
+  /* Incorporate the PSK into the running secret. */
+  if (ssl->s3->session_reused) {
+    if (!tls13_advance_key_schedule(hs, hs->new_session->master_key,
+                                    hs->new_session->master_key_length)) {
+      return ssl_hs_error;
+    }
+  } else if (!tls13_advance_key_schedule(hs, kZeroes, hs->hash_len)) {
+    return ssl_hs_error;
+  }
+
+  if (!have_key_share) {
+    /* We do not support psk_ke and thus always require a key share. */
+    OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_KEY_SHARE);
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_MISSING_EXTENSION);
+    return ssl_hs_error;
+  }
+
+  /* Resolve ECDHE and incorporate it into the secret. */
+  uint8_t *dhe_secret;
+  size_t dhe_secret_len;
+  alert = SSL_AD_DECODE_ERROR;
+  if (!ssl_ext_key_share_parse_serverhello(hs, &dhe_secret, &dhe_secret_len,
+                                           &alert, &key_share)) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
+    return ssl_hs_error;
+  }
+
+  if (!tls13_advance_key_schedule(hs, dhe_secret, dhe_secret_len)) {
+    OPENSSL_free(dhe_secret);
+    return ssl_hs_error;
+  }
+  OPENSSL_free(dhe_secret);
+
+  if (!ssl_hash_current_message(hs) ||
+      !tls13_derive_handshake_secrets(hs) ||
+      !tls13_set_traffic_key(ssl, evp_aead_open, hs->server_handshake_secret,
+                             hs->hash_len)) {
+    return ssl_hs_error;
+  }
+
+  /* If not sending early data, set client traffic keys now so that alerts are
+   * encrypted. */
+  if (!hs->early_data_offered &&
+      !tls13_set_traffic_key(ssl, evp_aead_seal, hs->client_handshake_secret,
+                             hs->hash_len)) {
+    return ssl_hs_error;
+  }
+
+  hs->tls13_state = state_process_encrypted_extensions;
+  return ssl_hs_read_message;
+}
+
+static enum ssl_hs_wait_t do_process_encrypted_extensions(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  if (!ssl_check_message_type(ssl, SSL3_MT_ENCRYPTED_EXTENSIONS)) {
+    return ssl_hs_error;
+  }
+
+  CBS cbs;
+  CBS_init(&cbs, ssl->init_msg, ssl->init_num);
+  if (!ssl_parse_serverhello_tlsext(hs, &cbs)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_PARSE_TLSEXT);
+    return ssl_hs_error;
+  }
+  if (CBS_len(&cbs) != 0) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+    return ssl_hs_error;
+  }
+
+  /* Store the negotiated ALPN in the session. */
+  if (ssl->s3->alpn_selected != NULL) {
+    hs->new_session->early_alpn =
+        BUF_memdup(ssl->s3->alpn_selected, ssl->s3->alpn_selected_len);
+    if (hs->new_session->early_alpn == NULL) {
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+      return ssl_hs_error;
+    }
+    hs->new_session->early_alpn_len = ssl->s3->alpn_selected_len;
+  }
+
+  if (ssl->early_data_accepted) {
+    if (ssl->session->cipher != hs->new_session->cipher ||
+        ssl->session->early_alpn_len != ssl->s3->alpn_selected_len ||
+        OPENSSL_memcmp(ssl->session->early_alpn, ssl->s3->alpn_selected,
+                       ssl->s3->alpn_selected_len) != 0) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_ALPN_MISMATCH_ON_EARLY_DATA);
+      return ssl_hs_error;
+    }
+    if (ssl->s3->tlsext_channel_id_valid) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_CHANNEL_ID_ON_EARLY_DATA);
+      return ssl_hs_error;
+    }
+  }
+
+  /* Release offered session now that it is no longer needed. */
+  if (ssl->s3->session_reused) {
+    ssl_set_session(ssl, NULL);
+  }
+
+  if (!ssl_hash_current_message(hs)) {
+    return ssl_hs_error;
+  }
+
+  hs->tls13_state = state_process_certificate_request;
+  return ssl_hs_read_message;
+}
+
+static enum ssl_hs_wait_t do_process_certificate_request(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  /* CertificateRequest may only be sent in non-resumption handshakes. */
+  if (ssl->s3->session_reused) {
+    hs->tls13_state = state_process_server_finished;
+    return ssl_hs_ok;
+  }
+
+  /* CertificateRequest is optional. */
+  if (ssl->s3->tmp.message_type != SSL3_MT_CERTIFICATE_REQUEST) {
+    hs->tls13_state = state_process_server_certificate;
+    return ssl_hs_ok;
+  }
+
+  CBS cbs, context, supported_signature_algorithms;
+  CBS_init(&cbs, ssl->init_msg, ssl->init_num);
+  if (!CBS_get_u8_length_prefixed(&cbs, &context) ||
+      /* The request context is always empty during the handshake. */
+      CBS_len(&context) != 0 ||
+      !CBS_get_u16_length_prefixed(&cbs, &supported_signature_algorithms) ||
+      CBS_len(&supported_signature_algorithms) == 0 ||
+      !tls1_parse_peer_sigalgs(hs, &supported_signature_algorithms)) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    return ssl_hs_error;
+  }
+
+  uint8_t alert = SSL_AD_DECODE_ERROR;
+  STACK_OF(CRYPTO_BUFFER) *ca_names =
+      ssl_parse_client_CA_list(ssl, &alert, &cbs);
+  if (ca_names == NULL) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
+    return ssl_hs_error;
+  }
+
+  /* Ignore extensions. */
+  CBS extensions;
+  if (!CBS_get_u16_length_prefixed(&cbs, &extensions) ||
+      CBS_len(&cbs) != 0) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+    sk_CRYPTO_BUFFER_pop_free(ca_names, CRYPTO_BUFFER_free);
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    return ssl_hs_error;
+  }
+
+  hs->cert_request = 1;
+  sk_CRYPTO_BUFFER_pop_free(hs->ca_names, CRYPTO_BUFFER_free);
+  hs->ca_names = ca_names;
+  ssl->ctx->x509_method->hs_flush_cached_ca_names(hs);
+
+  if (!ssl_hash_current_message(hs)) {
+    return ssl_hs_error;
+  }
+
+  hs->tls13_state = state_process_server_certificate;
+  return ssl_hs_read_message;
+}
+
+static enum ssl_hs_wait_t do_process_server_certificate(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  if (!ssl_check_message_type(ssl, SSL3_MT_CERTIFICATE) ||
+      !tls13_process_certificate(hs, 0 /* certificate required */) ||
+      !ssl_hash_current_message(hs)) {
+    return ssl_hs_error;
+  }
+
+  hs->tls13_state = state_process_server_certificate_verify;
+  return ssl_hs_read_message;
+}
+
+static enum ssl_hs_wait_t do_process_server_certificate_verify(
+    SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  if (!ssl_check_message_type(ssl, SSL3_MT_CERTIFICATE_VERIFY) ||
+      !tls13_process_certificate_verify(hs) ||
+      !ssl_hash_current_message(hs)) {
+    return ssl_hs_error;
+  }
+
+  hs->tls13_state = state_process_server_finished;
+  return ssl_hs_read_message;
+}
+
+static enum ssl_hs_wait_t do_process_server_finished(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  if (!ssl_check_message_type(ssl, SSL3_MT_FINISHED) ||
+      !tls13_process_finished(hs, 0 /* don't use saved value */) ||
+      !ssl_hash_current_message(hs) ||
+      /* Update the secret to the master secret and derive traffic keys. */
+      !tls13_advance_key_schedule(hs, kZeroes, hs->hash_len) ||
+      !tls13_derive_application_secrets(hs)) {
+    return ssl_hs_error;
+  }
+
+  ssl->method->received_flight(ssl);
+  hs->tls13_state = state_send_end_of_early_data;
+  return ssl_hs_ok;
+}
+
+static enum ssl_hs_wait_t do_send_end_of_early_data(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  /* TODO(svaldez): Stop sending early data. */
+  if (ssl->early_data_accepted &&
+      !ssl->method->add_alert(ssl, SSL3_AL_WARNING,
+                              TLS1_AD_END_OF_EARLY_DATA)) {
+    return ssl_hs_error;
+  }
+
+  if (hs->early_data_offered &&
+      !tls13_set_traffic_key(ssl, evp_aead_seal, hs->client_handshake_secret,
+                             hs->hash_len)) {
+    return ssl_hs_error;
+  }
+
+  hs->tls13_state = state_send_client_certificate;
+  return ssl_hs_ok;
+}
+
+static enum ssl_hs_wait_t do_send_client_certificate(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+
+  /* The peer didn't request a certificate. */
+  if (!hs->cert_request) {
+    hs->tls13_state = state_complete_second_flight;
+    return ssl_hs_ok;
+  }
+
+  /* Call cert_cb to update the certificate. */
+  if (ssl->cert->cert_cb != NULL) {
+    int rv = ssl->cert->cert_cb(ssl, ssl->cert->cert_cb_arg);
+    if (rv == 0) {
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+      OPENSSL_PUT_ERROR(SSL, SSL_R_CERT_CB_ERROR);
+      return ssl_hs_error;
+    }
+    if (rv < 0) {
+      hs->tls13_state = state_send_client_certificate;
+      return ssl_hs_x509_lookup;
+    }
+  }
+
+  if (!ssl->ctx->x509_method->ssl_auto_chain_if_needed(ssl) ||
+      !tls13_add_certificate(hs)) {
+    return ssl_hs_error;
+  }
+
+  hs->tls13_state = state_send_client_certificate_verify;
+  return ssl_hs_ok;
+}
+
+static enum ssl_hs_wait_t do_send_client_certificate_verify(SSL_HANDSHAKE *hs,
+                                                            int is_first_run) {
+  SSL *const ssl = hs->ssl;
+  /* Don't send CertificateVerify if there is no certificate. */
+  if (!ssl_has_certificate(ssl)) {
+    hs->tls13_state = state_complete_second_flight;
+    return ssl_hs_ok;
+  }
+
+  switch (tls13_add_certificate_verify(hs, is_first_run)) {
+    case ssl_private_key_success:
+      hs->tls13_state = state_complete_second_flight;
+      return ssl_hs_ok;
+
+    case ssl_private_key_retry:
+      hs->tls13_state = state_complete_client_certificate_verify;
+      return ssl_hs_private_key_operation;
+
+    case ssl_private_key_failure:
+      return ssl_hs_error;
+  }
+
+  assert(0);
+  return ssl_hs_error;
+}
+
+static enum ssl_hs_wait_t do_complete_second_flight(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+
+  /* Send a Channel ID assertion if necessary. */
+  if (ssl->s3->tlsext_channel_id_valid) {
+    if (!ssl_do_channel_id_callback(ssl)) {
+      hs->tls13_state = state_complete_second_flight;
+      return ssl_hs_error;
+    }
+
+    if (ssl->tlsext_channel_id_private == NULL) {
+      return ssl_hs_channel_id_lookup;
+    }
+
+    CBB cbb, body;
+    if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_CHANNEL_ID) ||
+        !tls1_write_channel_id(hs, &body) ||
+        !ssl_add_message_cbb(ssl, &cbb)) {
+      CBB_cleanup(&cbb);
+      return ssl_hs_error;
+    }
+  }
+
+  /* Send a Finished message. */
+  if (!tls13_add_finished(hs)) {
+    return ssl_hs_error;
+  }
+
+  /* Derive the final keys and enable them. */
+  if (!tls13_set_traffic_key(ssl, evp_aead_open, hs->server_traffic_secret_0,
+                             hs->hash_len) ||
+      !tls13_set_traffic_key(ssl, evp_aead_seal, hs->client_traffic_secret_0,
+                             hs->hash_len) ||
+      !tls13_derive_resumption_secret(hs)) {
+    return ssl_hs_error;
+  }
+
+  hs->tls13_state = state_done;
+  return ssl_hs_flush;
+}
+
+enum ssl_hs_wait_t tls13_client_handshake(SSL_HANDSHAKE *hs) {
+  while (hs->tls13_state != state_done) {
+    enum ssl_hs_wait_t ret = ssl_hs_error;
+    enum client_hs_state_t state = hs->tls13_state;
+    switch (state) {
+      case state_process_hello_retry_request:
+        ret = do_process_hello_retry_request(hs);
+        break;
+      case state_send_second_client_hello:
+        ret = do_send_second_client_hello(hs);
+        break;
+      case state_process_server_hello:
+        ret = do_process_server_hello(hs);
+        break;
+      case state_process_encrypted_extensions:
+        ret = do_process_encrypted_extensions(hs);
+        break;
+      case state_process_certificate_request:
+        ret = do_process_certificate_request(hs);
+        break;
+      case state_process_server_certificate:
+        ret = do_process_server_certificate(hs);
+        break;
+      case state_process_server_certificate_verify:
+        ret = do_process_server_certificate_verify(hs);
+        break;
+      case state_process_server_finished:
+        ret = do_process_server_finished(hs);
+        break;
+      case state_send_end_of_early_data:
+        ret = do_send_end_of_early_data(hs);
+        break;
+      case state_send_client_certificate:
+        ret = do_send_client_certificate(hs);
+        break;
+      case state_send_client_certificate_verify:
+        ret = do_send_client_certificate_verify(hs, 1 /* first run */);
+        break;
+      case state_complete_client_certificate_verify:
+        ret = do_send_client_certificate_verify(hs, 0 /* complete */);
+        break;
+      case state_complete_second_flight:
+        ret = do_complete_second_flight(hs);
+        break;
+      case state_done:
+        ret = ssl_hs_ok;
+        break;
+    }
+
+    if (ret != ssl_hs_ok) {
+      return ret;
+    }
+  }
+
+  return ssl_hs_ok;
+}
+
+int tls13_process_new_session_ticket(SSL *ssl) {
+  int ret = 0;
+  SSL_SESSION *session = SSL_SESSION_dup(ssl->s3->established_session,
+                                         SSL_SESSION_INCLUDE_NONAUTH);
+  if (session == NULL) {
+    return 0;
+  }
+
+  ssl_session_rebase_time(ssl, session);
+
+  uint32_t server_timeout;
+  CBS cbs, ticket, extensions;
+  CBS_init(&cbs, ssl->init_msg, ssl->init_num);
+  if (!CBS_get_u32(&cbs, &server_timeout) ||
+      !CBS_get_u32(&cbs, &session->ticket_age_add) ||
+      !CBS_get_u16_length_prefixed(&cbs, &ticket) ||
+      !CBS_stow(&ticket, &session->tlsext_tick, &session->tlsext_ticklen) ||
+      !CBS_get_u16_length_prefixed(&cbs, &extensions) ||
+      CBS_len(&cbs) != 0) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+    goto err;
+  }
+
+  /* Cap the renewable lifetime by the server advertised value. This avoids
+   * wasting bandwidth on 0-RTT when we know the server will reject it. */
+  if (session->timeout > server_timeout) {
+    session->timeout = server_timeout;
+  }
+
+  /* Parse out the extensions. */
+  int have_early_data_info = 0;
+  CBS early_data_info;
+  const SSL_EXTENSION_TYPE ext_types[] = {
+      {TLSEXT_TYPE_ticket_early_data_info, &have_early_data_info,
+       &early_data_info},
+  };
+
+  uint8_t alert = SSL_AD_DECODE_ERROR;
+  if (!ssl_parse_extensions(&extensions, &alert, ext_types,
+                            OPENSSL_ARRAY_SIZE(ext_types),
+                            1 /* ignore unknown */)) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
+    goto err;
+  }
+
+  if (have_early_data_info && ssl->ctx->enable_early_data) {
+    if (!CBS_get_u32(&early_data_info, &session->ticket_max_early_data) ||
+        CBS_len(&early_data_info) != 0) {
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+      OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
+      goto err;
+    }
+  }
+
+  session->ticket_age_add_valid = 1;
+  session->not_resumable = 0;
+
+  if (ssl->ctx->new_session_cb != NULL &&
+      ssl->ctx->new_session_cb(ssl, session)) {
+    /* |new_session_cb|'s return value signals that it took ownership. */
+    session = NULL;
+  }
+
+  ret = 1;
+
+err:
+  SSL_SESSION_free(session);
+  return ret;
+}
+
+void ssl_clear_tls13_state(SSL_HANDSHAKE *hs) {
+  SSL_ECDH_CTX_cleanup(&hs->ecdh_ctx);
+
+  OPENSSL_free(hs->key_share_bytes);
+  hs->key_share_bytes = NULL;
+  hs->key_share_bytes_len = 0;
+}
diff --git a/src/ssl/tls13_enc.c b/src/ssl/tls13_enc.c
new file mode 100644
index 0000000..3a7009c
--- /dev/null
+++ b/src/ssl/tls13_enc.c
@@ -0,0 +1,469 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/ssl.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/aead.h>
+#include <openssl/bytestring.h>
+#include <openssl/digest.h>
+#include <openssl/hkdf.h>
+#include <openssl/hmac.h>
+#include <openssl/mem.h>
+
+#include "../crypto/internal.h"
+#include "internal.h"
+
+
+static int init_key_schedule(SSL_HANDSHAKE *hs, uint16_t version,
+                              int algorithm_prf) {
+  if (!SSL_TRANSCRIPT_init_hash(&hs->transcript, version, algorithm_prf)) {
+    return 0;
+  }
+
+  hs->hash_len = SSL_TRANSCRIPT_digest_len(&hs->transcript);
+
+  /* Initialize the secret to the zero key. */
+  OPENSSL_memset(hs->secret, 0, hs->hash_len);
+
+  return 1;
+}
+
+int tls13_init_key_schedule(SSL_HANDSHAKE *hs) {
+  if (!init_key_schedule(hs, ssl3_protocol_version(hs->ssl),
+                         hs->new_cipher->algorithm_prf)) {
+    return 0;
+  }
+
+  SSL_TRANSCRIPT_free_buffer(&hs->transcript);
+  return 1;
+}
+
+int tls13_init_early_key_schedule(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  uint16_t session_version;
+  if (!ssl->method->version_from_wire(&session_version,
+                                      ssl->session->ssl_version) ||
+      !init_key_schedule(hs, session_version,
+                         ssl->session->cipher->algorithm_prf)) {
+    return 0;
+  }
+
+  return 1;
+}
+
+int tls13_advance_key_schedule(SSL_HANDSHAKE *hs, const uint8_t *in,
+                               size_t len) {
+  return HKDF_extract(hs->secret, &hs->hash_len,
+                      SSL_TRANSCRIPT_md(&hs->transcript), in, len, hs->secret,
+                      hs->hash_len);
+}
+
+static int hkdf_expand_label(uint8_t *out, const EVP_MD *digest,
+                             const uint8_t *secret, size_t secret_len,
+                             const uint8_t *label, size_t label_len,
+                             const uint8_t *hash, size_t hash_len, size_t len) {
+  static const char kTLS13LabelVersion[] = "TLS 1.3, ";
+
+  CBB cbb, child;
+  uint8_t *hkdf_label;
+  size_t hkdf_label_len;
+  if (!CBB_init(&cbb, 2 + 1 + strlen(kTLS13LabelVersion) + label_len + 1 +
+                          hash_len) ||
+      !CBB_add_u16(&cbb, len) ||
+      !CBB_add_u8_length_prefixed(&cbb, &child) ||
+      !CBB_add_bytes(&child, (const uint8_t *)kTLS13LabelVersion,
+                     strlen(kTLS13LabelVersion)) ||
+      !CBB_add_bytes(&child, label, label_len) ||
+      !CBB_add_u8_length_prefixed(&cbb, &child) ||
+      !CBB_add_bytes(&child, hash, hash_len) ||
+      !CBB_finish(&cbb, &hkdf_label, &hkdf_label_len)) {
+    CBB_cleanup(&cbb);
+    return 0;
+  }
+
+  int ret = HKDF_expand(out, len, digest, secret, secret_len, hkdf_label,
+                        hkdf_label_len);
+  OPENSSL_free(hkdf_label);
+  return ret;
+}
+
+/* derive_secret derives a secret of length |len| and writes the result in |out|
+ * with the given label and the current base secret and most recently-saved
+ * handshake context. It returns one on success and zero on error. */
+static int derive_secret(SSL_HANDSHAKE *hs, uint8_t *out, size_t len,
+                         const uint8_t *label, size_t label_len) {
+  uint8_t context_hash[EVP_MAX_MD_SIZE];
+  size_t context_hash_len;
+  if (!SSL_TRANSCRIPT_get_hash(&hs->transcript, context_hash,
+                               &context_hash_len)) {
+    return 0;
+  }
+
+  return hkdf_expand_label(out, SSL_TRANSCRIPT_md(&hs->transcript), hs->secret,
+                           hs->hash_len, label, label_len, context_hash,
+                           context_hash_len, len);
+}
+
+int tls13_set_traffic_key(SSL *ssl, enum evp_aead_direction_t direction,
+                          const uint8_t *traffic_secret,
+                          size_t traffic_secret_len) {
+  const SSL_SESSION *session = SSL_get_session(ssl);
+  uint16_t version;
+  if (!ssl->method->version_from_wire(&version, session->ssl_version)) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    return 0;
+  }
+
+  if (traffic_secret_len > 0xff) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
+    return 0;
+  }
+
+  /* Look up cipher suite properties. */
+  const EVP_AEAD *aead;
+  size_t discard;
+  if (!ssl_cipher_get_evp_aead(&aead, &discard, &discard, session->cipher,
+                               version)) {
+    return 0;
+  }
+
+  const EVP_MD *digest = ssl_get_handshake_digest(
+      session->cipher->algorithm_prf, version);
+
+  /* Derive the key. */
+  size_t key_len = EVP_AEAD_key_length(aead);
+  uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
+  if (!hkdf_expand_label(key, digest, traffic_secret, traffic_secret_len,
+                         (const uint8_t *)"key", 3, NULL, 0, key_len)) {
+    return 0;
+  }
+
+  /* Derive the IV. */
+  size_t iv_len = EVP_AEAD_nonce_length(aead);
+  uint8_t iv[EVP_AEAD_MAX_NONCE_LENGTH];
+  if (!hkdf_expand_label(iv, digest, traffic_secret, traffic_secret_len,
+                         (const uint8_t *)"iv", 2, NULL, 0, iv_len)) {
+    return 0;
+  }
+
+  SSL_AEAD_CTX *traffic_aead = SSL_AEAD_CTX_new(
+      direction, version, session->cipher, key, key_len, NULL, 0, iv, iv_len);
+  if (traffic_aead == NULL) {
+    return 0;
+  }
+
+  if (direction == evp_aead_open) {
+    if (!ssl->method->set_read_state(ssl, traffic_aead)) {
+      return 0;
+    }
+  } else {
+    if (!ssl->method->set_write_state(ssl, traffic_aead)) {
+      return 0;
+    }
+  }
+
+  /* Save the traffic secret. */
+  if (direction == evp_aead_open) {
+    OPENSSL_memmove(ssl->s3->read_traffic_secret, traffic_secret,
+                    traffic_secret_len);
+    ssl->s3->read_traffic_secret_len = traffic_secret_len;
+  } else {
+    OPENSSL_memmove(ssl->s3->write_traffic_secret, traffic_secret,
+                    traffic_secret_len);
+    ssl->s3->write_traffic_secret_len = traffic_secret_len;
+  }
+
+  return 1;
+}
+
+static const char kTLS13LabelExporter[] = "exporter master secret";
+static const char kTLS13LabelEarlyExporter[] = "early exporter master secret";
+
+static const char kTLS13LabelClientEarlyTraffic[] =
+    "client early traffic secret";
+static const char kTLS13LabelClientHandshakeTraffic[] =
+    "client handshake traffic secret";
+static const char kTLS13LabelServerHandshakeTraffic[] =
+    "server handshake traffic secret";
+static const char kTLS13LabelClientApplicationTraffic[] =
+    "client application traffic secret";
+static const char kTLS13LabelServerApplicationTraffic[] =
+    "server application traffic secret";
+
+int tls13_derive_early_secrets(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  return derive_secret(hs, hs->early_traffic_secret, hs->hash_len,
+                       (const uint8_t *)kTLS13LabelClientEarlyTraffic,
+                       strlen(kTLS13LabelClientEarlyTraffic)) &&
+         ssl_log_secret(ssl, "CLIENT_EARLY_TRAFFIC_SECRET",
+                        hs->early_traffic_secret, hs->hash_len) &&
+         derive_secret(hs, ssl->s3->early_exporter_secret, hs->hash_len,
+                       (const uint8_t *)kTLS13LabelEarlyExporter,
+                       strlen(kTLS13LabelEarlyExporter));
+}
+
+int tls13_derive_handshake_secrets(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  return derive_secret(hs, hs->client_handshake_secret, hs->hash_len,
+                       (const uint8_t *)kTLS13LabelClientHandshakeTraffic,
+                       strlen(kTLS13LabelClientHandshakeTraffic)) &&
+         ssl_log_secret(ssl, "CLIENT_HANDSHAKE_TRAFFIC_SECRET",
+                        hs->client_handshake_secret, hs->hash_len) &&
+         derive_secret(hs, hs->server_handshake_secret, hs->hash_len,
+                       (const uint8_t *)kTLS13LabelServerHandshakeTraffic,
+                       strlen(kTLS13LabelServerHandshakeTraffic)) &&
+         ssl_log_secret(ssl, "SERVER_HANDSHAKE_TRAFFIC_SECRET",
+                        hs->server_handshake_secret, hs->hash_len);
+}
+
+int tls13_derive_application_secrets(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  ssl->s3->exporter_secret_len = hs->hash_len;
+  return derive_secret(hs, hs->client_traffic_secret_0, hs->hash_len,
+                       (const uint8_t *)kTLS13LabelClientApplicationTraffic,
+                       strlen(kTLS13LabelClientApplicationTraffic)) &&
+         ssl_log_secret(ssl, "CLIENT_TRAFFIC_SECRET_0",
+                        hs->client_traffic_secret_0, hs->hash_len) &&
+         derive_secret(hs, hs->server_traffic_secret_0, hs->hash_len,
+                       (const uint8_t *)kTLS13LabelServerApplicationTraffic,
+                       strlen(kTLS13LabelServerApplicationTraffic)) &&
+         ssl_log_secret(ssl, "SERVER_TRAFFIC_SECRET_0",
+                        hs->server_traffic_secret_0, hs->hash_len) &&
+         derive_secret(hs, ssl->s3->exporter_secret, hs->hash_len,
+                       (const uint8_t *)kTLS13LabelExporter,
+                       strlen(kTLS13LabelExporter));
+}
+
+static const char kTLS13LabelApplicationTraffic[] =
+    "application traffic secret";
+
+int tls13_rotate_traffic_key(SSL *ssl, enum evp_aead_direction_t direction) {
+  const EVP_MD *digest = ssl_get_handshake_digest(
+      SSL_get_session(ssl)->cipher->algorithm_prf, ssl3_protocol_version(ssl));
+
+  uint8_t *secret;
+  size_t secret_len;
+  if (direction == evp_aead_open) {
+    secret = ssl->s3->read_traffic_secret;
+    secret_len = ssl->s3->read_traffic_secret_len;
+  } else {
+    secret = ssl->s3->write_traffic_secret;
+    secret_len = ssl->s3->write_traffic_secret_len;
+  }
+
+  if (!hkdf_expand_label(secret, digest, secret, secret_len,
+                         (const uint8_t *)kTLS13LabelApplicationTraffic,
+                         strlen(kTLS13LabelApplicationTraffic), NULL, 0,
+                         secret_len)) {
+    return 0;
+  }
+
+  return tls13_set_traffic_key(ssl, direction, secret, secret_len);
+}
+
+static const char kTLS13LabelResumption[] = "resumption master secret";
+
+int tls13_derive_resumption_secret(SSL_HANDSHAKE *hs) {
+  if (hs->hash_len > SSL_MAX_MASTER_KEY_LENGTH) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    return 0;
+  }
+
+  hs->new_session->master_key_length = hs->hash_len;
+  return derive_secret(
+      hs, hs->new_session->master_key, hs->new_session->master_key_length,
+      (const uint8_t *)kTLS13LabelResumption, strlen(kTLS13LabelResumption));
+}
+
+static const char kTLS13LabelFinished[] = "finished";
+
+/* tls13_verify_data sets |out| to be the HMAC of |context| using a derived
+ * Finished key for both Finished messages and the PSK binder. */
+static int tls13_verify_data(const EVP_MD *digest, uint8_t *out,
+                             size_t *out_len, const uint8_t *secret,
+                             size_t hash_len, uint8_t *context,
+                             size_t context_len) {
+  uint8_t key[EVP_MAX_MD_SIZE];
+  unsigned len;
+  if (!hkdf_expand_label(key, digest, secret, hash_len,
+                         (const uint8_t *)kTLS13LabelFinished,
+                         strlen(kTLS13LabelFinished), NULL, 0, hash_len) ||
+      HMAC(digest, key, hash_len, context, context_len, out, &len) == NULL) {
+    return 0;
+  }
+  *out_len = len;
+  return 1;
+}
+
+int tls13_finished_mac(SSL_HANDSHAKE *hs, uint8_t *out, size_t *out_len,
+                       int is_server) {
+  const uint8_t *traffic_secret;
+  if (is_server) {
+    traffic_secret = hs->server_handshake_secret;
+  } else {
+    traffic_secret = hs->client_handshake_secret;
+  }
+
+  uint8_t context_hash[EVP_MAX_MD_SIZE];
+  size_t context_hash_len;
+  if (!SSL_TRANSCRIPT_get_hash(&hs->transcript, context_hash,
+                               &context_hash_len) ||
+      !tls13_verify_data(SSL_TRANSCRIPT_md(&hs->transcript), out, out_len,
+                         traffic_secret, hs->hash_len, context_hash,
+                         context_hash_len)) {
+    return 0;
+  }
+  return 1;
+}
+
+int tls13_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len,
+                                 const char *label, size_t label_len,
+                                 const uint8_t *context, size_t context_len,
+                                 int use_context) {
+  const EVP_MD *digest = ssl_get_handshake_digest(
+      SSL_get_session(ssl)->cipher->algorithm_prf, ssl3_protocol_version(ssl));
+
+  const uint8_t *hash = NULL;
+  size_t hash_len = 0;
+  if (use_context) {
+    hash = context;
+    hash_len = context_len;
+  }
+  return hkdf_expand_label(out, digest, ssl->s3->exporter_secret,
+                           ssl->s3->exporter_secret_len, (const uint8_t *)label,
+                           label_len, hash, hash_len, out_len);
+}
+
+static const char kTLS13LabelPSKBinder[] = "resumption psk binder key";
+
+static int tls13_psk_binder(uint8_t *out, const EVP_MD *digest, uint8_t *psk,
+                            size_t psk_len, uint8_t *context,
+                            size_t context_len, size_t hash_len) {
+  uint8_t binder_context[EVP_MAX_MD_SIZE];
+  unsigned binder_context_len;
+  if (!EVP_Digest(NULL, 0, binder_context, &binder_context_len, digest, NULL)) {
+    return 0;
+  }
+
+  uint8_t early_secret[EVP_MAX_MD_SIZE] = {0};
+  size_t early_secret_len;
+  if (!HKDF_extract(early_secret, &early_secret_len, digest, psk, hash_len,
+                    NULL, 0)) {
+    return 0;
+  }
+
+  uint8_t binder_key[EVP_MAX_MD_SIZE] = {0};
+  size_t len;
+  if (!hkdf_expand_label(binder_key, digest, early_secret, hash_len,
+                         (const uint8_t *)kTLS13LabelPSKBinder,
+                         strlen(kTLS13LabelPSKBinder), binder_context,
+                         binder_context_len, hash_len) ||
+      !tls13_verify_data(digest, out, &len, binder_key, hash_len, context,
+                         context_len)) {
+    return 0;
+  }
+
+  return 1;
+}
+
+int tls13_write_psk_binder(SSL_HANDSHAKE *hs, uint8_t *msg, size_t len) {
+  SSL *const ssl = hs->ssl;
+  const EVP_MD *digest = SSL_SESSION_get_digest(ssl->session, ssl);
+  if (digest == NULL) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    return 0;
+  }
+  size_t hash_len = EVP_MD_size(digest);
+
+  if (len < hash_len + 3) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    return 0;
+  }
+
+  EVP_MD_CTX ctx;
+  EVP_MD_CTX_init(&ctx);
+  uint8_t context[EVP_MAX_MD_SIZE];
+  unsigned context_len;
+  if (!EVP_DigestInit_ex(&ctx, digest, NULL) ||
+      !EVP_DigestUpdate(&ctx, hs->transcript.buffer->data,
+                        hs->transcript.buffer->length) ||
+      !EVP_DigestUpdate(&ctx, msg, len - hash_len - 3) ||
+      !EVP_DigestFinal_ex(&ctx, context, &context_len)) {
+    EVP_MD_CTX_cleanup(&ctx);
+    return 0;
+  }
+
+  EVP_MD_CTX_cleanup(&ctx);
+
+  uint8_t verify_data[EVP_MAX_MD_SIZE] = {0};
+  if (!tls13_psk_binder(verify_data, digest, ssl->session->master_key,
+                        ssl->session->master_key_length, context, context_len,
+                        hash_len)) {
+    return 0;
+  }
+
+  OPENSSL_memcpy(msg + len - hash_len, verify_data, hash_len);
+  return 1;
+}
+
+int tls13_verify_psk_binder(SSL_HANDSHAKE *hs, SSL_SESSION *session,
+                            CBS *binders) {
+  size_t hash_len = SSL_TRANSCRIPT_digest_len(&hs->transcript);
+
+  /* Get the full ClientHello, including message header. It must be large enough
+   * to exclude the binders. */
+  CBS message;
+  hs->ssl->method->get_current_message(hs->ssl, &message);
+  if (CBS_len(&message) < CBS_len(binders) + 2) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    return 0;
+  }
+
+  /* Hash a ClientHello prefix up to the binders. For now, this assumes we only
+   * ever verify PSK binders on initial ClientHellos. */
+  uint8_t context[EVP_MAX_MD_SIZE];
+  unsigned context_len;
+  if (!EVP_Digest(CBS_data(&message), CBS_len(&message) - CBS_len(binders) - 2,
+                  context, &context_len, SSL_TRANSCRIPT_md(&hs->transcript),
+                  NULL)) {
+    return 0;
+  }
+
+  uint8_t verify_data[EVP_MAX_MD_SIZE] = {0};
+  CBS binder;
+  if (!tls13_psk_binder(verify_data, SSL_TRANSCRIPT_md(&hs->transcript),
+                        session->master_key, session->master_key_length,
+                        context, context_len, hash_len) ||
+      /* We only consider the first PSK, so compare against the first binder. */
+      !CBS_get_u8_length_prefixed(binders, &binder)) {
+    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+    return 0;
+  }
+
+  int binder_ok =
+      CBS_len(&binder) == hash_len &&
+      CRYPTO_memcmp(CBS_data(&binder), verify_data, hash_len) == 0;
+#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
+  binder_ok = 1;
+#endif
+  if (!binder_ok) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_DIGEST_CHECK_FAILED);
+    return 0;
+  }
+
+  return 1;
+}
diff --git a/src/ssl/tls13_server.c b/src/ssl/tls13_server.c
new file mode 100644
index 0000000..35ee4f7
--- /dev/null
+++ b/src/ssl/tls13_server.c
@@ -0,0 +1,862 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#include <openssl/ssl.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/aead.h>
+#include <openssl/bytestring.h>
+#include <openssl/digest.h>
+#include <openssl/err.h>
+#include <openssl/mem.h>
+#include <openssl/rand.h>
+#include <openssl/stack.h>
+
+#include "../crypto/internal.h"
+#include "internal.h"
+
+
+/* kMaxEarlyDataAccepted is the advertised number of plaintext bytes of early
+ * data that will be accepted. This value should be slightly below
+ * kMaxEarlyDataSkipped in tls_record.c, which is measured in ciphertext. */
+static const size_t kMaxEarlyDataAccepted = 14336;
+
+enum server_hs_state_t {
+  state_select_parameters = 0,
+  state_select_session,
+  state_send_hello_retry_request,
+  state_process_second_client_hello,
+  state_send_server_hello,
+  state_send_server_certificate_verify,
+  state_complete_server_certificate_verify,
+  state_send_server_finished,
+  state_read_second_client_flight,
+  state_process_end_of_early_data,
+  state_process_client_certificate,
+  state_process_client_certificate_verify,
+  state_process_channel_id,
+  state_process_client_finished,
+  state_send_new_session_ticket,
+  state_done,
+};
+
+static const uint8_t kZeroes[EVP_MAX_MD_SIZE] = {0};
+
+static int resolve_ecdhe_secret(SSL_HANDSHAKE *hs, int *out_need_retry,
+                                SSL_CLIENT_HELLO *client_hello) {
+  SSL *const ssl = hs->ssl;
+  *out_need_retry = 0;
+
+  /* We only support connections that include an ECDHE key exchange. */
+  CBS key_share;
+  if (!ssl_client_hello_get_extension(client_hello, &key_share,
+                                      TLSEXT_TYPE_key_share)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_MISSING_KEY_SHARE);
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_MISSING_EXTENSION);
+    return 0;
+  }
+
+  int found_key_share;
+  uint8_t *dhe_secret;
+  size_t dhe_secret_len;
+  uint8_t alert = SSL_AD_DECODE_ERROR;
+  if (!ssl_ext_key_share_parse_clienthello(hs, &found_key_share, &dhe_secret,
+                                           &dhe_secret_len, &alert,
+                                           &key_share)) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
+    return 0;
+  }
+
+  if (!found_key_share) {
+    *out_need_retry = 1;
+    return 0;
+  }
+
+  int ok = tls13_advance_key_schedule(hs, dhe_secret, dhe_secret_len);
+  OPENSSL_free(dhe_secret);
+  return ok;
+}
+
+static const SSL_CIPHER *choose_tls13_cipher(
+    const SSL *ssl, const SSL_CLIENT_HELLO *client_hello) {
+  if (client_hello->cipher_suites_len % 2 != 0) {
+    return NULL;
+  }
+
+  CBS cipher_suites;
+  CBS_init(&cipher_suites, client_hello->cipher_suites,
+           client_hello->cipher_suites_len);
+
+  const int aes_is_fine = EVP_has_aes_hardware();
+  const uint16_t version = ssl3_protocol_version(ssl);
+
+  const SSL_CIPHER *best = NULL;
+  while (CBS_len(&cipher_suites) > 0) {
+    uint16_t cipher_suite;
+    if (!CBS_get_u16(&cipher_suites, &cipher_suite)) {
+      return NULL;
+    }
+
+    /* Limit to TLS 1.3 ciphers we know about. */
+    const SSL_CIPHER *candidate = SSL_get_cipher_by_value(cipher_suite);
+    if (candidate == NULL ||
+        SSL_CIPHER_get_min_version(candidate) > version ||
+        SSL_CIPHER_get_max_version(candidate) < version) {
+      continue;
+    }
+
+    /* TLS 1.3 removes legacy ciphers, so honor the client order, but prefer
+     * ChaCha20 if we do not have AES hardware. */
+    if (aes_is_fine) {
+      return candidate;
+    }
+
+    if (candidate->algorithm_enc == SSL_CHACHA20POLY1305) {
+      return candidate;
+    }
+
+    if (best == NULL) {
+      best = candidate;
+    }
+  }
+
+  return best;
+}
+
+static int add_new_session_tickets(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  /* TLS 1.3 recommends single-use tickets, so issue multiple tickets in case
+   * the client makes several connections before getting a renewal. */
+  static const int kNumTickets = 2;
+
+  SSL_SESSION *session = hs->new_session;
+  CBB cbb;
+  CBB_zero(&cbb);
+
+  /* Rebase the session timestamp so that it is measured from ticket
+   * issuance. */
+  ssl_session_rebase_time(ssl, session);
+
+  for (int i = 0; i < kNumTickets; i++) {
+    if (!RAND_bytes((uint8_t *)&session->ticket_age_add, 4)) {
+      goto err;
+    }
+    session->ticket_age_add_valid = 1;
+
+    CBB body, ticket, extensions;
+    if (!ssl->method->init_message(ssl, &cbb, &body,
+                                   SSL3_MT_NEW_SESSION_TICKET) ||
+        !CBB_add_u32(&body, session->timeout) ||
+        !CBB_add_u32(&body, session->ticket_age_add) ||
+        !CBB_add_u16_length_prefixed(&body, &ticket) ||
+        !ssl_encrypt_ticket(ssl, &ticket, session) ||
+        !CBB_add_u16_length_prefixed(&body, &extensions)) {
+      goto err;
+    }
+
+    if (ssl->ctx->enable_early_data) {
+      session->ticket_max_early_data = kMaxEarlyDataAccepted;
+
+      CBB early_data_info;
+      if (!CBB_add_u16(&extensions, TLSEXT_TYPE_ticket_early_data_info) ||
+          !CBB_add_u16_length_prefixed(&extensions, &early_data_info) ||
+          !CBB_add_u32(&early_data_info, session->ticket_max_early_data) ||
+          !CBB_flush(&extensions)) {
+        goto err;
+      }
+    }
+
+    /* Add a fake extension. See draft-davidben-tls-grease-01. */
+    if (!CBB_add_u16(&extensions,
+                     ssl_get_grease_value(ssl, ssl_grease_ticket_extension)) ||
+        !CBB_add_u16(&extensions, 0 /* empty */)) {
+      goto err;
+    }
+
+    if (!ssl_add_message_cbb(ssl, &cbb)) {
+      goto err;
+    }
+  }
+
+  return 1;
+
+err:
+  CBB_cleanup(&cbb);
+  return 0;
+}
+
+static enum ssl_hs_wait_t do_select_parameters(SSL_HANDSHAKE *hs) {
+  /* At this point, most ClientHello extensions have already been processed by
+   * the common handshake logic. Resolve the remaining non-PSK parameters. */
+  SSL *const ssl = hs->ssl;
+
+  SSL_CLIENT_HELLO client_hello;
+  if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg,
+                             ssl->init_num)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED);
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+    return ssl_hs_error;
+  }
+
+  /* Negotiate the cipher suite. */
+  hs->new_cipher = choose_tls13_cipher(ssl, &client_hello);
+  if (hs->new_cipher == NULL) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_NO_SHARED_CIPHER);
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE);
+    return ssl_hs_error;
+  }
+
+  /* HTTP/2 negotiation depends on the cipher suite, so ALPN negotiation was
+   * deferred. Complete it now. */
+  uint8_t alert = SSL_AD_DECODE_ERROR;
+  if (!ssl_negotiate_alpn(hs, &alert, &client_hello)) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
+    return ssl_hs_error;
+  }
+
+  /* The PRF hash is now known. Set up the key schedule and hash the
+   * ClientHello. */
+  if (!tls13_init_key_schedule(hs) ||
+      !ssl_hash_current_message(hs)) {
+    return ssl_hs_error;
+  }
+
+  hs->tls13_state = state_select_session;
+  return ssl_hs_ok;
+}
+
+static enum ssl_ticket_aead_result_t select_session(
+    SSL_HANDSHAKE *hs, uint8_t *out_alert, SSL_SESSION **out_session,
+    int32_t *out_ticket_age_skew, const SSL_CLIENT_HELLO *client_hello) {
+  SSL *const ssl = hs->ssl;
+  *out_session = NULL;
+
+  /* Decode the ticket if we agreed on a PSK key exchange mode. */
+  CBS pre_shared_key;
+  if (!hs->accept_psk_mode ||
+      !ssl_client_hello_get_extension(client_hello, &pre_shared_key,
+                                      TLSEXT_TYPE_pre_shared_key)) {
+    return ssl_ticket_aead_ignore_ticket;
+  }
+
+  /* Verify that the pre_shared_key extension is the last extension in
+   * ClientHello. */
+  if (CBS_data(&pre_shared_key) + CBS_len(&pre_shared_key) !=
+      client_hello->extensions + client_hello->extensions_len) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_PRE_SHARED_KEY_MUST_BE_LAST);
+    *out_alert = SSL_AD_ILLEGAL_PARAMETER;
+    return ssl_ticket_aead_error;
+  }
+
+  CBS ticket, binders;
+  uint32_t client_ticket_age;
+  if (!ssl_ext_pre_shared_key_parse_clienthello(hs, &ticket, &binders,
+                                                &client_ticket_age, out_alert,
+                                                &pre_shared_key)) {
+    return ssl_ticket_aead_error;
+  }
+
+  /* TLS 1.3 session tickets are renewed separately as part of the
+   * NewSessionTicket. */
+  int unused_renew;
+  SSL_SESSION *session = NULL;
+  enum ssl_ticket_aead_result_t ret =
+      ssl_process_ticket(ssl, &session, &unused_renew, CBS_data(&ticket),
+                         CBS_len(&ticket), NULL, 0);
+  switch (ret) {
+    case ssl_ticket_aead_success:
+      break;
+    case ssl_ticket_aead_error:
+      *out_alert = SSL_AD_INTERNAL_ERROR;
+      return ret;
+    default:
+      return ret;
+  }
+
+  if (!ssl_session_is_resumable(hs, session) ||
+      /* Historically, some TLS 1.3 tickets were missing ticket_age_add. */
+      !session->ticket_age_add_valid) {
+    SSL_SESSION_free(session);
+    return ssl_ticket_aead_ignore_ticket;
+  }
+
+  /* Recover the client ticket age and convert to seconds. */
+  client_ticket_age -= session->ticket_age_add;
+  client_ticket_age /= 1000;
+
+  struct OPENSSL_timeval now;
+  ssl_get_current_time(ssl, &now);
+
+  /* Compute the server ticket age in seconds. */
+  assert(now.tv_sec >= session->time);
+  uint64_t server_ticket_age = now.tv_sec - session->time;
+
+  /* To avoid overflowing |hs->ticket_age_skew|, we will not resume
+   * 68-year-old sessions. */
+  if (server_ticket_age > INT32_MAX) {
+    SSL_SESSION_free(session);
+    return ssl_ticket_aead_ignore_ticket;
+  }
+
+  /* TODO(davidben,svaldez): Measure this value to decide on tolerance. For
+   * now, accept all values. https://crbug.com/boringssl/113. */
+  *out_ticket_age_skew =
+      (int32_t)client_ticket_age - (int32_t)server_ticket_age;
+
+  /* Check the PSK binder. */
+  if (!tls13_verify_psk_binder(hs, session, &binders)) {
+    SSL_SESSION_free(session);
+    *out_alert = SSL_AD_DECRYPT_ERROR;
+    return ssl_ticket_aead_error;
+  }
+
+  *out_session = session;
+  return ssl_ticket_aead_success;
+}
+
+static enum ssl_hs_wait_t do_select_session(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  SSL_CLIENT_HELLO client_hello;
+  if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg,
+                             ssl->init_num)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED);
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+    return ssl_hs_error;
+  }
+
+  uint8_t alert = SSL_AD_DECODE_ERROR;
+  SSL_SESSION *session = NULL;
+  switch (select_session(hs, &alert, &session, &ssl->s3->ticket_age_skew,
+                         &client_hello)) {
+    case ssl_ticket_aead_ignore_ticket:
+      assert(session == NULL);
+      if (!ssl_get_new_session(hs, 1 /* server */)) {
+        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+        return ssl_hs_error;
+      }
+      break;
+
+    case ssl_ticket_aead_success:
+      /* Carry over authentication information from the previous handshake into
+       * a fresh session. */
+      hs->new_session = SSL_SESSION_dup(session, SSL_SESSION_DUP_AUTH_ONLY);
+
+      if (/* Early data must be acceptable for this ticket. */
+          ssl->ctx->enable_early_data &&
+          session->ticket_max_early_data != 0 &&
+          /* The client must have offered early data. */
+          hs->early_data_offered &&
+          /* Channel ID is incompatible with 0-RTT. */
+          !ssl->s3->tlsext_channel_id_valid &&
+          /* The negotiated ALPN must match the one in the ticket. */
+          ssl->s3->alpn_selected_len == session->early_alpn_len &&
+          OPENSSL_memcmp(ssl->s3->alpn_selected, session->early_alpn,
+                         ssl->s3->alpn_selected_len) == 0) {
+        ssl->early_data_accepted = 1;
+      }
+
+      SSL_SESSION_free(session);
+      if (hs->new_session == NULL) {
+        ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+        return ssl_hs_error;
+      }
+
+      ssl->s3->session_reused = 1;
+
+      /* Resumption incorporates fresh key material, so refresh the timeout. */
+      ssl_session_renew_timeout(ssl, hs->new_session,
+                                ssl->session_ctx->session_psk_dhe_timeout);
+      break;
+
+    case ssl_ticket_aead_error:
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, alert);
+      return ssl_hs_error;
+
+    case ssl_ticket_aead_retry:
+      hs->tls13_state = state_select_session;
+      return ssl_hs_pending_ticket;
+  }
+
+  /* Record connection properties in the new session. */
+  hs->new_session->cipher = hs->new_cipher;
+
+  if (hs->hostname != NULL) {
+    OPENSSL_free(hs->new_session->tlsext_hostname);
+    hs->new_session->tlsext_hostname = BUF_strdup(hs->hostname);
+    if (hs->new_session->tlsext_hostname == NULL) {
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+      return ssl_hs_error;
+    }
+  }
+
+  /* Store the initial negotiated ALPN in the session. */
+  if (ssl->s3->alpn_selected != NULL) {
+    hs->new_session->early_alpn =
+        BUF_memdup(ssl->s3->alpn_selected, ssl->s3->alpn_selected_len);
+    if (hs->new_session->early_alpn == NULL) {
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+      return ssl_hs_error;
+    }
+    hs->new_session->early_alpn_len = ssl->s3->alpn_selected_len;
+  }
+
+  if (ssl->ctx->dos_protection_cb != NULL &&
+      ssl->ctx->dos_protection_cb(&client_hello) == 0) {
+    /* Connection rejected for DOS reasons. */
+    OPENSSL_PUT_ERROR(SSL, SSL_R_CONNECTION_REJECTED);
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_INTERNAL_ERROR);
+    return ssl_hs_error;
+  }
+
+  /* Incorporate the PSK into the running secret. */
+  if (ssl->s3->session_reused) {
+    if (!tls13_advance_key_schedule(hs, hs->new_session->master_key,
+                                    hs->new_session->master_key_length)) {
+      return ssl_hs_error;
+    }
+  } else if (!tls13_advance_key_schedule(hs, kZeroes, hs->hash_len)) {
+    return ssl_hs_error;
+  }
+
+  if (ssl->early_data_accepted) {
+    if (!tls13_derive_early_secrets(hs)) {
+      return ssl_hs_error;
+    }
+  } else if (hs->early_data_offered) {
+    ssl->s3->skip_early_data = 1;
+  }
+
+  ssl->method->received_flight(ssl);
+
+  /* Resolve ECDHE and incorporate it into the secret. */
+  int need_retry;
+  if (!resolve_ecdhe_secret(hs, &need_retry, &client_hello)) {
+    if (need_retry) {
+      ssl->early_data_accepted = 0;
+      ssl->s3->skip_early_data = 1;
+      hs->tls13_state = state_send_hello_retry_request;
+      return ssl_hs_ok;
+    }
+    return ssl_hs_error;
+  }
+
+  hs->tls13_state = state_send_server_hello;
+  return ssl_hs_ok;
+}
+
+static enum ssl_hs_wait_t do_send_hello_retry_request(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  CBB cbb, body, extensions;
+  uint16_t group_id;
+  if (!ssl->method->init_message(ssl, &cbb, &body,
+                                 SSL3_MT_HELLO_RETRY_REQUEST) ||
+      !CBB_add_u16(&body, ssl->version) ||
+      !tls1_get_shared_group(hs, &group_id) ||
+      !CBB_add_u16_length_prefixed(&body, &extensions) ||
+      !CBB_add_u16(&extensions, TLSEXT_TYPE_key_share) ||
+      !CBB_add_u16(&extensions, 2 /* length */) ||
+      !CBB_add_u16(&extensions, group_id) ||
+      !ssl_add_message_cbb(ssl, &cbb)) {
+    CBB_cleanup(&cbb);
+    return ssl_hs_error;
+  }
+
+  hs->tls13_state = state_process_second_client_hello;
+  return ssl_hs_flush_and_read_message;
+}
+
+static enum ssl_hs_wait_t do_process_second_client_hello(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  if (!ssl_check_message_type(ssl, SSL3_MT_CLIENT_HELLO)) {
+    return ssl_hs_error;
+  }
+
+  SSL_CLIENT_HELLO client_hello;
+  if (!ssl_client_hello_init(ssl, &client_hello, ssl->init_msg,
+                             ssl->init_num)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_CLIENTHELLO_PARSE_FAILED);
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR);
+    return ssl_hs_error;
+  }
+
+  int need_retry;
+  if (!resolve_ecdhe_secret(hs, &need_retry, &client_hello)) {
+    if (need_retry) {
+      /* Only send one HelloRetryRequest. */
+      ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_ILLEGAL_PARAMETER);
+      OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_CURVE);
+    }
+    return ssl_hs_error;
+  }
+
+  if (!ssl_hash_current_message(hs)) {
+    return ssl_hs_error;
+  }
+
+  ssl->method->received_flight(ssl);
+  hs->tls13_state = state_send_server_hello;
+  return ssl_hs_ok;
+}
+
+static enum ssl_hs_wait_t do_send_server_hello(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+
+  /* Send a ServerHello. */
+  CBB cbb, body, extensions;
+  if (!ssl->method->init_message(ssl, &cbb, &body, SSL3_MT_SERVER_HELLO) ||
+      !CBB_add_u16(&body, ssl->version) ||
+      !RAND_bytes(ssl->s3->server_random, sizeof(ssl->s3->server_random)) ||
+      !CBB_add_bytes(&body, ssl->s3->server_random, SSL3_RANDOM_SIZE) ||
+      !CBB_add_u16(&body, ssl_cipher_get_value(hs->new_cipher)) ||
+      !CBB_add_u16_length_prefixed(&body, &extensions) ||
+      !ssl_ext_pre_shared_key_add_serverhello(hs, &extensions) ||
+      !ssl_ext_key_share_add_serverhello(hs, &extensions) ||
+      !ssl_add_message_cbb(ssl, &cbb)) {
+    goto err;
+  }
+
+  /* Derive and enable the handshake traffic secrets. */
+  if (!tls13_derive_handshake_secrets(hs) ||
+      !tls13_set_traffic_key(ssl, evp_aead_seal, hs->server_handshake_secret,
+                             hs->hash_len)) {
+    goto err;
+  }
+
+  /* Send EncryptedExtensions. */
+  if (!ssl->method->init_message(ssl, &cbb, &body,
+                                 SSL3_MT_ENCRYPTED_EXTENSIONS) ||
+      !ssl_add_serverhello_tlsext(hs, &body) ||
+      !ssl_add_message_cbb(ssl, &cbb)) {
+    goto err;
+  }
+
+  /* Determine whether to request a client certificate. */
+  hs->cert_request = !!(ssl->verify_mode & SSL_VERIFY_PEER);
+  /* CertificateRequest may only be sent in non-resumption handshakes. */
+  if (ssl->s3->session_reused) {
+    hs->cert_request = 0;
+  }
+
+  /* Send a CertificateRequest, if necessary. */
+  if (hs->cert_request) {
+    CBB sigalgs_cbb;
+    if (!ssl->method->init_message(ssl, &cbb, &body,
+                                   SSL3_MT_CERTIFICATE_REQUEST) ||
+        !CBB_add_u8(&body, 0 /* no certificate_request_context. */)) {
+      goto err;
+    }
+
+    const uint16_t *sigalgs;
+    size_t num_sigalgs = tls12_get_verify_sigalgs(ssl, &sigalgs);
+    if (!CBB_add_u16_length_prefixed(&body, &sigalgs_cbb)) {
+      goto err;
+    }
+
+    for (size_t i = 0; i < num_sigalgs; i++) {
+      if (!CBB_add_u16(&sigalgs_cbb, sigalgs[i])) {
+        goto err;
+      }
+    }
+
+    if (!ssl_add_client_CA_list(ssl, &body) ||
+        !CBB_add_u16(&body, 0 /* empty certificate_extensions. */) ||
+        !ssl_add_message_cbb(ssl, &cbb)) {
+      goto err;
+    }
+  }
+
+  /* Send the server Certificate message, if necessary. */
+  if (!ssl->s3->session_reused) {
+    if (!ssl_has_certificate(ssl)) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATE_SET);
+      goto err;
+    }
+
+    if (!tls13_add_certificate(hs)) {
+      goto err;
+    }
+
+    hs->tls13_state = state_send_server_certificate_verify;
+    return ssl_hs_ok;
+  }
+
+  hs->tls13_state = state_send_server_finished;
+  return ssl_hs_ok;
+
+err:
+  CBB_cleanup(&cbb);
+  return ssl_hs_error;
+}
+
+static enum ssl_hs_wait_t do_send_server_certificate_verify(SSL_HANDSHAKE *hs,
+                                                            int is_first_run) {
+  switch (tls13_add_certificate_verify(hs, is_first_run)) {
+    case ssl_private_key_success:
+      hs->tls13_state = state_send_server_finished;
+      return ssl_hs_ok;
+
+    case ssl_private_key_retry:
+      hs->tls13_state = state_complete_server_certificate_verify;
+      return ssl_hs_private_key_operation;
+
+    case ssl_private_key_failure:
+      return ssl_hs_error;
+  }
+
+  assert(0);
+  return ssl_hs_error;
+}
+
+static enum ssl_hs_wait_t do_send_server_finished(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  if (!tls13_add_finished(hs) ||
+      /* Update the secret to the master secret and derive traffic keys. */
+      !tls13_advance_key_schedule(hs, kZeroes, hs->hash_len) ||
+      !tls13_derive_application_secrets(hs) ||
+      !tls13_set_traffic_key(ssl, evp_aead_seal, hs->server_traffic_secret_0,
+                             hs->hash_len)) {
+    return ssl_hs_error;
+  }
+
+  if (ssl->early_data_accepted) {
+    /* If accepting 0-RTT, we send tickets half-RTT. This gets the tickets on
+     * the wire sooner and also avoids triggering a write on |SSL_read| when
+     * processing the client Finished. This requires computing the client
+     * Finished early. See draft-ietf-tls-tls13-18, section 4.5.1. */
+    size_t finished_len;
+    if (!tls13_finished_mac(hs, hs->expected_client_finished, &finished_len,
+                            0 /* client */)) {
+      return ssl_hs_error;
+    }
+
+    if (finished_len != hs->hash_len) {
+      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
+      return ssl_hs_error;
+    }
+
+    /* Feed the predicted Finished into the transcript. This allows us to derive
+     * the resumption secret early and send half-RTT tickets.
+     *
+     * TODO(davidben): This will need to be updated for DTLS 1.3. */
+    assert(!SSL_is_dtls(hs->ssl));
+    uint8_t header[4] = {SSL3_MT_FINISHED, 0, 0, hs->hash_len};
+    if (!SSL_TRANSCRIPT_update(&hs->transcript, header, sizeof(header)) ||
+        !SSL_TRANSCRIPT_update(&hs->transcript, hs->expected_client_finished,
+                               hs->hash_len) ||
+        !tls13_derive_resumption_secret(hs) ||
+        !add_new_session_tickets(hs)) {
+      return ssl_hs_error;
+    }
+  }
+
+  hs->tls13_state = state_read_second_client_flight;
+  return ssl_hs_flush;
+}
+
+static enum ssl_hs_wait_t do_read_second_client_flight(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  if (ssl->early_data_accepted) {
+    if (!tls13_set_traffic_key(ssl, evp_aead_open, hs->early_traffic_secret,
+                               hs->hash_len)) {
+      return ssl_hs_error;
+    }
+    hs->can_early_write = 1;
+    hs->can_early_read = 1;
+    hs->tls13_state = state_process_end_of_early_data;
+    return ssl_hs_read_end_of_early_data;
+  }
+  hs->tls13_state = state_process_end_of_early_data;
+  return ssl_hs_ok;
+}
+
+static enum ssl_hs_wait_t do_process_end_of_early_data(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  if (!tls13_set_traffic_key(ssl, evp_aead_open, hs->client_handshake_secret,
+                             hs->hash_len)) {
+    return ssl_hs_error;
+  }
+  hs->tls13_state = ssl->early_data_accepted ? state_process_client_finished
+                                             : state_process_client_certificate;
+  return ssl_hs_read_message;
+}
+
+static enum ssl_hs_wait_t do_process_client_certificate(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  if (!hs->cert_request) {
+    /* OpenSSL returns X509_V_OK when no certificates are requested. This is
+     * classed by them as a bug, but it's assumed by at least NGINX. */
+    hs->new_session->verify_result = X509_V_OK;
+
+    /* Skip this state. */
+    hs->tls13_state = state_process_channel_id;
+    return ssl_hs_ok;
+  }
+
+  const int allow_anonymous =
+      (ssl->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) == 0;
+
+  if (!ssl_check_message_type(ssl, SSL3_MT_CERTIFICATE) ||
+      !tls13_process_certificate(hs, allow_anonymous) ||
+      !ssl_hash_current_message(hs)) {
+    return ssl_hs_error;
+  }
+
+  hs->tls13_state = state_process_client_certificate_verify;
+  return ssl_hs_read_message;
+}
+
+static enum ssl_hs_wait_t do_process_client_certificate_verify(
+    SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  if (sk_CRYPTO_BUFFER_num(hs->new_session->certs) == 0) {
+    /* Skip this state. */
+    hs->tls13_state = state_process_channel_id;
+    return ssl_hs_ok;
+  }
+
+  if (!ssl_check_message_type(ssl, SSL3_MT_CERTIFICATE_VERIFY) ||
+      !tls13_process_certificate_verify(hs) ||
+      !ssl_hash_current_message(hs)) {
+    return ssl_hs_error;
+  }
+
+  hs->tls13_state = state_process_channel_id;
+  return ssl_hs_read_message;
+}
+
+static enum ssl_hs_wait_t do_process_channel_id(SSL_HANDSHAKE *hs) {
+  if (!hs->ssl->s3->tlsext_channel_id_valid) {
+    hs->tls13_state = state_process_client_finished;
+    return ssl_hs_ok;
+  }
+
+  if (!ssl_check_message_type(hs->ssl, SSL3_MT_CHANNEL_ID) ||
+      !tls1_verify_channel_id(hs) ||
+      !ssl_hash_current_message(hs)) {
+    return ssl_hs_error;
+  }
+
+  hs->tls13_state = state_process_client_finished;
+  return ssl_hs_read_message;
+}
+
+static enum ssl_hs_wait_t do_process_client_finished(SSL_HANDSHAKE *hs) {
+  SSL *const ssl = hs->ssl;
+  if (!ssl_check_message_type(ssl, SSL3_MT_FINISHED) ||
+      /* If early data was accepted, we've already computed the client Finished
+       * and derived the resumption secret. */
+      !tls13_process_finished(hs, ssl->early_data_accepted) ||
+      /* evp_aead_seal keys have already been switched. */
+      !tls13_set_traffic_key(ssl, evp_aead_open, hs->client_traffic_secret_0,
+                             hs->hash_len)) {
+    return ssl_hs_error;
+  }
+
+  ssl->method->received_flight(ssl);
+
+  if (!ssl->early_data_accepted) {
+    if (!ssl_hash_current_message(hs) ||
+        !tls13_derive_resumption_secret(hs)) {
+      return ssl_hs_error;
+    }
+
+    /* We send post-handshake tickets as part of the handshake in 1-RTT. */
+    hs->tls13_state = state_send_new_session_ticket;
+    return ssl_hs_ok;
+  }
+
+  hs->tls13_state = state_done;
+  return ssl_hs_ok;
+}
+
+static enum ssl_hs_wait_t do_send_new_session_ticket(SSL_HANDSHAKE *hs) {
+  /* If the client doesn't accept resumption with PSK_DHE_KE, don't send a
+   * session ticket. */
+  if (!hs->accept_psk_mode) {
+    hs->tls13_state = state_done;
+    return ssl_hs_ok;
+  }
+
+  if (!add_new_session_tickets(hs)) {
+    return ssl_hs_error;
+  }
+
+  hs->tls13_state = state_done;
+  return ssl_hs_flush;
+}
+
+enum ssl_hs_wait_t tls13_server_handshake(SSL_HANDSHAKE *hs) {
+  while (hs->tls13_state != state_done) {
+    enum ssl_hs_wait_t ret = ssl_hs_error;
+    enum server_hs_state_t state = hs->tls13_state;
+    switch (state) {
+      case state_select_parameters:
+        ret = do_select_parameters(hs);
+        break;
+      case state_select_session:
+        ret = do_select_session(hs);
+        break;
+      case state_send_hello_retry_request:
+        ret = do_send_hello_retry_request(hs);
+        break;
+      case state_process_second_client_hello:
+        ret = do_process_second_client_hello(hs);
+        break;
+      case state_send_server_hello:
+        ret = do_send_server_hello(hs);
+        break;
+      case state_send_server_certificate_verify:
+        ret = do_send_server_certificate_verify(hs, 1 /* first run */);
+      break;
+      case state_complete_server_certificate_verify:
+        ret = do_send_server_certificate_verify(hs, 0 /* complete */);
+        break;
+      case state_send_server_finished:
+        ret = do_send_server_finished(hs);
+        break;
+      case state_read_second_client_flight:
+        ret = do_read_second_client_flight(hs);
+        break;
+      case state_process_end_of_early_data:
+        ret = do_process_end_of_early_data(hs);
+        break;
+      case state_process_client_certificate:
+        ret = do_process_client_certificate(hs);
+        break;
+      case state_process_client_certificate_verify:
+        ret = do_process_client_certificate_verify(hs);
+        break;
+      case state_process_channel_id:
+        ret = do_process_channel_id(hs);
+        break;
+      case state_process_client_finished:
+        ret = do_process_client_finished(hs);
+        break;
+      case state_send_new_session_ticket:
+        ret = do_send_new_session_ticket(hs);
+        break;
+      case state_done:
+        ret = ssl_hs_ok;
+        break;
+    }
+
+    if (ret != ssl_hs_ok) {
+      return ret;
+    }
+  }
+
+  return ssl_hs_ok;
+}
diff --git a/src/ssl/tls_method.c b/src/ssl/tls_method.c
new file mode 100644
index 0000000..6144f86
--- /dev/null
+++ b/src/ssl/tls_method.c
@@ -0,0 +1,328 @@
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to.  The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *    "This product includes cryptographic software written by
+ *     Eric Young (eay@cryptsoft.com)"
+ *    The word 'cryptographic' can be left out if the rouines from the library
+ *    being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ *    the apps directory (application code) you must include an acknowledgement:
+ *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed.  i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.] */
+
+#include <openssl/ssl.h>
+
+#include <assert.h>
+#include <string.h>
+
+#include <openssl/buf.h>
+
+#include "../crypto/internal.h"
+#include "internal.h"
+
+
+static int ssl3_version_from_wire(uint16_t *out_version,
+                                  uint16_t wire_version) {
+  switch (wire_version) {
+    case SSL3_VERSION:
+    case TLS1_VERSION:
+    case TLS1_1_VERSION:
+    case TLS1_2_VERSION:
+      *out_version = wire_version;
+      return 1;
+    case TLS1_3_DRAFT_VERSION:
+      *out_version = TLS1_3_VERSION;
+      return 1;
+  }
+
+  return 0;
+}
+
+static uint16_t ssl3_version_to_wire(uint16_t version) {
+  switch (version) {
+    case SSL3_VERSION:
+    case TLS1_VERSION:
+    case TLS1_1_VERSION:
+    case TLS1_2_VERSION:
+      return version;
+    case TLS1_3_VERSION:
+      return TLS1_3_DRAFT_VERSION;
+  }
+
+  /* It is an error to use this function with an invalid version. */
+  assert(0);
+  return 0;
+}
+
+static int ssl3_supports_cipher(const SSL_CIPHER *cipher) { return 1; }
+
+static void ssl3_expect_flight(SSL *ssl) {}
+
+static void ssl3_received_flight(SSL *ssl) {}
+
+static int ssl3_set_read_state(SSL *ssl, SSL_AEAD_CTX *aead_ctx) {
+  if (ssl->s3->rrec.length != 0) {
+    /* There may not be unprocessed record data at a cipher change. */
+    OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFERED_MESSAGES_ON_CIPHER_CHANGE);
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE);
+    SSL_AEAD_CTX_free(aead_ctx);
+    return 0;
+  }
+
+  OPENSSL_memset(ssl->s3->read_sequence, 0, sizeof(ssl->s3->read_sequence));
+
+  SSL_AEAD_CTX_free(ssl->s3->aead_read_ctx);
+  ssl->s3->aead_read_ctx = aead_ctx;
+  return 1;
+}
+
+static int ssl3_set_write_state(SSL *ssl, SSL_AEAD_CTX *aead_ctx) {
+  OPENSSL_memset(ssl->s3->write_sequence, 0, sizeof(ssl->s3->write_sequence));
+
+  SSL_AEAD_CTX_free(ssl->s3->aead_write_ctx);
+  ssl->s3->aead_write_ctx = aead_ctx;
+  return 1;
+}
+
+static const SSL_PROTOCOL_METHOD kTLSProtocolMethod = {
+    0 /* is_dtls */,
+    SSL3_VERSION,
+    TLS1_3_VERSION,
+    ssl3_version_from_wire,
+    ssl3_version_to_wire,
+    ssl3_new,
+    ssl3_free,
+    ssl3_get_message,
+    ssl3_get_current_message,
+    ssl3_release_current_message,
+    ssl3_read_app_data,
+    ssl3_read_change_cipher_spec,
+    ssl3_read_close_notify,
+    ssl3_write_app_data,
+    ssl3_dispatch_alert,
+    ssl3_supports_cipher,
+    ssl3_init_message,
+    ssl3_finish_message,
+    ssl3_add_message,
+    ssl3_add_change_cipher_spec,
+    ssl3_add_alert,
+    ssl3_flush_flight,
+    ssl3_expect_flight,
+    ssl3_received_flight,
+    ssl3_set_read_state,
+    ssl3_set_write_state,
+};
+
+const SSL_METHOD *TLS_method(void) {
+  static const SSL_METHOD kMethod = {
+      0,
+      &kTLSProtocolMethod,
+      &ssl_crypto_x509_method,
+  };
+  return &kMethod;
+}
+
+const SSL_METHOD *SSLv23_method(void) {
+  return TLS_method();
+}
+
+/* Legacy version-locked methods. */
+
+const SSL_METHOD *TLSv1_2_method(void) {
+  static const SSL_METHOD kMethod = {
+      TLS1_2_VERSION,
+      &kTLSProtocolMethod,
+      &ssl_crypto_x509_method,
+  };
+  return &kMethod;
+}
+
+const SSL_METHOD *TLSv1_1_method(void) {
+  static const SSL_METHOD kMethod = {
+      TLS1_1_VERSION,
+      &kTLSProtocolMethod,
+      &ssl_crypto_x509_method,
+  };
+  return &kMethod;
+}
+
+const SSL_METHOD *TLSv1_method(void) {
+  static const SSL_METHOD kMethod = {
+      TLS1_VERSION,
+      &kTLSProtocolMethod,
+      &ssl_crypto_x509_method,
+  };
+  return &kMethod;
+}
+
+const SSL_METHOD *SSLv3_method(void) {
+  static const SSL_METHOD kMethod = {
+      SSL3_VERSION,
+      &kTLSProtocolMethod,
+      &ssl_crypto_x509_method,
+  };
+  return &kMethod;
+}
+
+/* Legacy side-specific methods. */
+
+const SSL_METHOD *TLSv1_2_server_method(void) {
+  return TLSv1_2_method();
+}
+
+const SSL_METHOD *TLSv1_1_server_method(void) {
+  return TLSv1_1_method();
+}
+
+const SSL_METHOD *TLSv1_server_method(void) {
+  return TLSv1_method();
+}
+
+const SSL_METHOD *SSLv3_server_method(void) {
+  return SSLv3_method();
+}
+
+const SSL_METHOD *TLSv1_2_client_method(void) {
+  return TLSv1_2_method();
+}
+
+const SSL_METHOD *TLSv1_1_client_method(void) {
+  return TLSv1_1_method();
+}
+
+const SSL_METHOD *TLSv1_client_method(void) {
+  return TLSv1_method();
+}
+
+const SSL_METHOD *SSLv3_client_method(void) {
+  return SSLv3_method();
+}
+
+const SSL_METHOD *SSLv23_server_method(void) {
+  return SSLv23_method();
+}
+
+const SSL_METHOD *SSLv23_client_method(void) {
+  return SSLv23_method();
+}
+
+const SSL_METHOD *TLS_server_method(void) {
+  return TLS_method();
+}
+
+const SSL_METHOD *TLS_client_method(void) {
+  return TLS_method();
+}
+
+static int ssl_noop_x509_check_client_CA_names(
+    STACK_OF(CRYPTO_BUFFER) *names) {
+  return 1;
+}
+
+static void ssl_noop_x509_clear(CERT *cert) {}
+static void ssl_noop_x509_free(CERT *cert) {}
+static void ssl_noop_x509_dup(CERT *new_cert, const CERT *cert) {}
+static void ssl_noop_x509_flush_cached_leaf(CERT *cert) {}
+static void ssl_noop_x509_flush_cached_chain(CERT *cert) {}
+static int ssl_noop_x509_session_cache_objects(SSL_SESSION *sess) {
+  return 1;
+}
+static int ssl_noop_x509_session_dup(SSL_SESSION *new_session,
+                                       const SSL_SESSION *session) {
+  return 1;
+}
+static void ssl_noop_x509_session_clear(SSL_SESSION *session) {}
+static int ssl_noop_x509_session_verify_cert_chain(SSL_SESSION *session,
+                                                   SSL *ssl) {
+  if (!ssl->ctx->i_promise_to_verify_certs_after_the_handshake) {
+    ssl3_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNKNOWN_CA);
+    OPENSSL_PUT_ERROR(SSL, SSL_R_CERTIFICATE_VERIFY_FAILED);
+    return 0;
+  }
+
+  session->verify_result = X509_V_OK;
+  return 1;
+}
+
+static void ssl_noop_x509_hs_flush_cached_ca_names(SSL_HANDSHAKE *hs) {}
+static int ssl_noop_x509_ssl_new(SSL *ctx) { return 1; }
+static void ssl_noop_x509_ssl_free(SSL *ctx) { }
+static void ssl_noop_x509_ssl_flush_cached_client_CA(SSL *ssl) {}
+static int ssl_noop_x509_ssl_auto_chain_if_needed(SSL *ssl) { return 1; }
+static int ssl_noop_x509_ssl_ctx_new(SSL_CTX *ctx) { return 1; }
+static void ssl_noop_x509_ssl_ctx_free(SSL_CTX *ctx) { }
+static void ssl_noop_x509_ssl_ctx_flush_cached_client_CA(SSL_CTX *ctx) {}
+
+static const SSL_X509_METHOD ssl_noop_x509_method = {
+  ssl_noop_x509_check_client_CA_names,
+  ssl_noop_x509_clear,
+  ssl_noop_x509_free,
+  ssl_noop_x509_dup,
+  ssl_noop_x509_flush_cached_chain,
+  ssl_noop_x509_flush_cached_leaf,
+  ssl_noop_x509_session_cache_objects,
+  ssl_noop_x509_session_dup,
+  ssl_noop_x509_session_clear,
+  ssl_noop_x509_session_verify_cert_chain,
+  ssl_noop_x509_hs_flush_cached_ca_names,
+  ssl_noop_x509_ssl_new,
+  ssl_noop_x509_ssl_free,
+  ssl_noop_x509_ssl_flush_cached_client_CA,
+  ssl_noop_x509_ssl_auto_chain_if_needed,
+  ssl_noop_x509_ssl_ctx_new,
+  ssl_noop_x509_ssl_ctx_free,
+  ssl_noop_x509_ssl_ctx_flush_cached_client_CA,
+};
+
+const SSL_METHOD *TLS_with_buffers_method(void) {
+  static const SSL_METHOD kMethod = {
+      0,
+      &kTLSProtocolMethod,
+      &ssl_noop_x509_method,
+  };
+  return &kMethod;
+}
diff --git a/src/ssl/tls_record.c b/src/ssl/tls_record.c
index 3381eae..0f9720c 100644
--- a/src/ssl/tls_record.c
+++ b/src/ssl/tls_record.c
@@ -109,11 +109,14 @@
 #include <openssl/ssl.h>
 
 #include <assert.h>
+#include <string.h>
 
 #include <openssl/bytestring.h>
 #include <openssl/err.h>
+#include <openssl/mem.h>
 
 #include "internal.h"
+#include "../crypto/internal.h"
 
 
 /* kMaxEmptyRecords is the number of consecutive, empty records that will be
@@ -122,57 +125,86 @@
  * forever. */
 static const uint8_t kMaxEmptyRecords = 32;
 
+/* kMaxEarlyDataSkipped is the maximum number of rejected early data bytes that
+ * will be skipped. Without this limit an attacker could send records at a
+ * faster rate than we can process and cause trial decryption to loop forever.
+ * This value should be slightly above kMaxEarlyDataAccepted in tls13_server.c,
+ * which is measured in plaintext. */
+static const size_t kMaxEarlyDataSkipped = 16384;
+
+/* kMaxWarningAlerts is the number of consecutive warning alerts that will be
+ * processed. */
+static const uint8_t kMaxWarningAlerts = 4;
+
 /* ssl_needs_record_splitting returns one if |ssl|'s current outgoing cipher
  * state needs record-splitting and zero otherwise. */
 static int ssl_needs_record_splitting(const SSL *ssl) {
-  return !SSL_USE_EXPLICIT_IV(ssl) && ssl->aead_write_ctx != NULL &&
+  return ssl->s3->aead_write_ctx != NULL &&
+         ssl->s3->aead_write_ctx->version < TLS1_1_VERSION &&
          (ssl->mode & SSL_MODE_CBC_RECORD_SPLITTING) != 0 &&
-         SSL_CIPHER_is_block_cipher(ssl->aead_write_ctx->cipher);
+         SSL_CIPHER_is_block_cipher(ssl->s3->aead_write_ctx->cipher);
+}
+
+int ssl_record_sequence_update(uint8_t *seq, size_t seq_len) {
+  for (size_t i = seq_len - 1; i < seq_len; i--) {
+    ++seq[i];
+    if (seq[i] != 0) {
+      return 1;
+    }
+  }
+  OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
+  return 0;
 }
 
 size_t ssl_record_prefix_len(const SSL *ssl) {
-  if (SSL_IS_DTLS(ssl)) {
-    return DTLS1_RT_HEADER_LENGTH +
-           SSL_AEAD_CTX_explicit_nonce_len(ssl->aead_read_ctx);
+  size_t header_len;
+  if (SSL_is_dtls(ssl)) {
+    header_len = DTLS1_RT_HEADER_LENGTH;
   } else {
-    return SSL3_RT_HEADER_LENGTH +
-           SSL_AEAD_CTX_explicit_nonce_len(ssl->aead_read_ctx);
+    header_len = SSL3_RT_HEADER_LENGTH;
   }
+
+  return header_len + SSL_AEAD_CTX_explicit_nonce_len(ssl->s3->aead_read_ctx);
 }
 
-size_t ssl_seal_prefix_len(const SSL *ssl) {
-  if (SSL_IS_DTLS(ssl)) {
+size_t ssl_seal_align_prefix_len(const SSL *ssl) {
+  if (SSL_is_dtls(ssl)) {
     return DTLS1_RT_HEADER_LENGTH +
-           SSL_AEAD_CTX_explicit_nonce_len(ssl->aead_write_ctx);
-  } else {
-    size_t ret = SSL3_RT_HEADER_LENGTH +
-                 SSL_AEAD_CTX_explicit_nonce_len(ssl->aead_write_ctx);
-    if (ssl_needs_record_splitting(ssl)) {
-      ret += SSL3_RT_HEADER_LENGTH;
-      ret += ssl_cipher_get_record_split_len(ssl->aead_write_ctx->cipher);
-    }
-    return ret;
+           SSL_AEAD_CTX_explicit_nonce_len(ssl->s3->aead_write_ctx);
   }
+
+  size_t ret = SSL3_RT_HEADER_LENGTH +
+               SSL_AEAD_CTX_explicit_nonce_len(ssl->s3->aead_write_ctx);
+  if (ssl_needs_record_splitting(ssl)) {
+    ret += SSL3_RT_HEADER_LENGTH;
+    ret += ssl_cipher_get_record_split_len(ssl->s3->aead_write_ctx->cipher);
+  }
+  return ret;
 }
 
-size_t ssl_max_seal_overhead(const SSL *ssl) {
-  if (SSL_IS_DTLS(ssl)) {
-    return DTLS1_RT_HEADER_LENGTH +
-           SSL_AEAD_CTX_max_overhead(ssl->aead_write_ctx);
-  } else {
-    size_t ret = SSL3_RT_HEADER_LENGTH +
-                 SSL_AEAD_CTX_max_overhead(ssl->aead_write_ctx);
-    if (ssl_needs_record_splitting(ssl)) {
-      ret *= 2;
-    }
-    return ret;
+size_t SSL_max_seal_overhead(const SSL *ssl) {
+  if (SSL_is_dtls(ssl)) {
+    return dtls_max_seal_overhead(ssl, dtls1_use_current_epoch);
   }
+
+  size_t ret = SSL3_RT_HEADER_LENGTH;
+  ret += SSL_AEAD_CTX_max_overhead(ssl->s3->aead_write_ctx);
+  /* TLS 1.3 needs an extra byte for the encrypted record type. */
+  if (ssl->s3->aead_write_ctx != NULL &&
+      ssl->s3->aead_write_ctx->version >= TLS1_3_VERSION) {
+    ret += 1;
+  }
+  if (ssl_needs_record_splitting(ssl)) {
+    ret *= 2;
+  }
+  return ret;
 }
 
-enum ssl_open_record_t tls_open_record(
-    SSL *ssl, uint8_t *out_type, uint8_t *out, size_t *out_len,
-    size_t *out_consumed, uint8_t *out_alert, size_t max_out, const uint8_t *in,
-    size_t in_len) {
+enum ssl_open_record_t tls_open_record(SSL *ssl, uint8_t *out_type, CBS *out,
+                                       size_t *out_consumed, uint8_t *out_alert,
+                                       uint8_t *in, size_t in_len) {
+  *out_consumed = 0;
+
   CBS cbs;
   CBS_init(&cbs, in, in_len);
 
@@ -186,9 +218,20 @@
     return ssl_open_record_partial;
   }
 
-  /* Check the version. */
-  if ((ssl->s3->have_version && version != ssl->version) ||
-      (version >> 8) != SSL3_VERSION_MAJOR) {
+  int version_ok;
+  if (ssl->s3->aead_read_ctx == NULL) {
+    /* Only check the first byte. Enforcing beyond that can prevent decoding
+     * version negotiation failure alerts. */
+    version_ok = (version >> 8) == SSL3_VERSION_MAJOR;
+  } else if (ssl3_protocol_version(ssl) < TLS1_3_VERSION) {
+    /* Earlier versions of TLS switch the record version. */
+    version_ok = version == ssl->version;
+  } else {
+    /* Starting TLS 1.3, the version field is frozen at {3, 1}. */
+    version_ok = version == TLS1_VERSION;
+  }
+
+  if (!version_ok) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_WRONG_VERSION_NUMBER);
     *out_alert = SSL_AD_PROTOCOL_VERSION;
     return ssl_open_record_error;
@@ -208,34 +251,69 @@
     return ssl_open_record_partial;
   }
 
-  if (ssl->msg_callback != NULL) {
-    ssl->msg_callback(0 /* read */, 0, SSL3_RT_HEADER, in,
-                      SSL3_RT_HEADER_LENGTH, ssl, ssl->msg_callback_arg);
+  ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_HEADER, in,
+                      SSL3_RT_HEADER_LENGTH);
+
+  *out_consumed = in_len - CBS_len(&cbs);
+
+  /* Skip early data received when expecting a second ClientHello if we rejected
+   * 0RTT. */
+  if (ssl->s3->skip_early_data &&
+      ssl->s3->aead_read_ctx == NULL &&
+      type == SSL3_RT_APPLICATION_DATA) {
+    goto skipped_data;
   }
 
-  /* Decrypt the body. */
-  size_t plaintext_len;
-  if (!SSL_AEAD_CTX_open(ssl->aead_read_ctx, out, &plaintext_len, max_out,
-                         type, version, ssl->s3->read_sequence, CBS_data(&body),
+  /* Decrypt the body in-place. */
+  if (!SSL_AEAD_CTX_open(ssl->s3->aead_read_ctx, out, type, version,
+                         ssl->s3->read_sequence, (uint8_t *)CBS_data(&body),
                          CBS_len(&body))) {
+    if (ssl->s3->skip_early_data &&
+        ssl->s3->aead_read_ctx != NULL) {
+      ERR_clear_error();
+      goto skipped_data;
+    }
+
     OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
     *out_alert = SSL_AD_BAD_RECORD_MAC;
     return ssl_open_record_error;
   }
-  if (!ssl3_record_sequence_update(ssl->s3->read_sequence, 8)) {
+
+  ssl->s3->skip_early_data = 0;
+
+  if (!ssl_record_sequence_update(ssl->s3->read_sequence, 8)) {
     *out_alert = SSL_AD_INTERNAL_ERROR;
     return ssl_open_record_error;
   }
 
+  /* TLS 1.3 hides the record type inside the encrypted data. */
+  if (ssl->s3->aead_read_ctx != NULL &&
+      ssl->s3->aead_read_ctx->version >= TLS1_3_VERSION) {
+    /* The outer record type is always application_data. */
+    if (type != SSL3_RT_APPLICATION_DATA) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_INVALID_OUTER_RECORD_TYPE);
+      *out_alert = SSL_AD_DECODE_ERROR;
+      return ssl_open_record_error;
+    }
+
+    do {
+      if (!CBS_get_last_u8(out, &type)) {
+        OPENSSL_PUT_ERROR(SSL, SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC);
+        *out_alert = SSL_AD_DECRYPT_ERROR;
+        return ssl_open_record_error;
+      }
+    } while (type == 0);
+  }
+
   /* Check the plaintext length. */
-  if (plaintext_len > SSL3_RT_MAX_PLAIN_LENGTH) {
+  if (CBS_len(out) > SSL3_RT_MAX_PLAIN_LENGTH) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_DATA_LENGTH_TOO_LONG);
     *out_alert = SSL_AD_RECORD_OVERFLOW;
     return ssl_open_record_error;
   }
 
   /* Limit the number of consecutive empty records. */
-  if (plaintext_len == 0) {
+  if (CBS_len(out) == 0) {
     ssl->s3->empty_record_count++;
     if (ssl->s3->empty_record_count > kMaxEmptyRecords) {
       OPENSSL_PUT_ERROR(SSL, SSL_R_TOO_MANY_EMPTY_FRAGMENTS);
@@ -248,80 +326,116 @@
     ssl->s3->empty_record_count = 0;
   }
 
+  if (type == SSL3_RT_ALERT) {
+    /* Return end_of_early_data alerts as-is for the caller to process. */
+    if (CBS_len(out) == 2 &&
+        CBS_data(out)[0] == SSL3_AL_WARNING &&
+        CBS_data(out)[1] == TLS1_AD_END_OF_EARLY_DATA) {
+      *out_type = type;
+      return ssl_open_record_success;
+    }
+
+    return ssl_process_alert(ssl, out_alert, CBS_data(out), CBS_len(out));
+  }
+
+  ssl->s3->warning_alert_count = 0;
+
   *out_type = type;
-  *out_len = plaintext_len;
-  *out_consumed = in_len - CBS_len(&cbs);
   return ssl_open_record_success;
+
+skipped_data:
+  ssl->s3->early_data_skipped += *out_consumed;
+  if (ssl->s3->early_data_skipped < *out_consumed) {
+    ssl->s3->early_data_skipped = kMaxEarlyDataSkipped + 1;
+  }
+
+  if (ssl->s3->early_data_skipped > kMaxEarlyDataSkipped) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_TOO_MUCH_SKIPPED_EARLY_DATA);
+    *out_alert = SSL_AD_UNEXPECTED_MESSAGE;
+    return ssl_open_record_error;
+  }
+
+  return ssl_open_record_discard;
 }
 
 static int do_seal_record(SSL *ssl, uint8_t *out, size_t *out_len,
                           size_t max_out, uint8_t type, const uint8_t *in,
                           size_t in_len) {
+  assert(!buffers_alias(in, in_len, out, max_out));
+
+  /* TLS 1.3 hides the actual record type inside the encrypted data. */
+  if (ssl->s3->aead_write_ctx != NULL &&
+      ssl->s3->aead_write_ctx->version >= TLS1_3_VERSION) {
+    if (in_len > in_len + SSL3_RT_HEADER_LENGTH + 1 ||
+        max_out < in_len + SSL3_RT_HEADER_LENGTH + 1) {
+      OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL);
+      return 0;
+    }
+
+    OPENSSL_memcpy(out + SSL3_RT_HEADER_LENGTH, in, in_len);
+    out[SSL3_RT_HEADER_LENGTH + in_len] = type;
+    in = out + SSL3_RT_HEADER_LENGTH;
+    type = SSL3_RT_APPLICATION_DATA;
+    in_len++;
+  }
+
   if (max_out < SSL3_RT_HEADER_LENGTH) {
     OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL);
     return 0;
   }
-  /* Check the record header does not alias any part of the input.
-   * |SSL_AEAD_CTX_seal| will internally enforce other aliasing requirements. */
-  if (in < out + SSL3_RT_HEADER_LENGTH && out < in + in_len) {
-    OPENSSL_PUT_ERROR(SSL, SSL_R_OUTPUT_ALIASES_INPUT);
-    return 0;
+
+  /* The TLS record-layer version number is meaningless and, starting in
+   * TLS 1.3, is frozen at TLS 1.0. But for historical reasons, SSL 3.0
+   * ClientHellos should use SSL 3.0 and pre-TLS-1.3 expects the version
+   * to change after version negotiation. */
+  uint16_t wire_version = TLS1_VERSION;
+  if (ssl->version == SSL3_VERSION ||
+      (ssl->s3->have_version && ssl3_protocol_version(ssl) < TLS1_3_VERSION)) {
+    wire_version = ssl->version;
   }
 
+  /* Write the non-length portions of the header. */
   out[0] = type;
-
-  /* Some servers hang if initial ClientHello is larger than 256 bytes and
-   * record version number > TLS 1.0. */
-  uint16_t wire_version = ssl->version;
-  if (!ssl->s3->have_version && ssl->version > SSL3_VERSION) {
-    wire_version = TLS1_VERSION;
-  }
   out[1] = wire_version >> 8;
   out[2] = wire_version & 0xff;
+  out += 3;
+  max_out -= 3;
 
+  /* Write the ciphertext, leaving two bytes for the length. */
   size_t ciphertext_len;
-  if (!SSL_AEAD_CTX_seal(ssl->aead_write_ctx, out + SSL3_RT_HEADER_LENGTH,
-                         &ciphertext_len, max_out - SSL3_RT_HEADER_LENGTH,
-                         type, wire_version, ssl->s3->write_sequence, in,
-                         in_len) ||
-      !ssl3_record_sequence_update(ssl->s3->write_sequence, 8)) {
+  if (!SSL_AEAD_CTX_seal(ssl->s3->aead_write_ctx, out + 2, &ciphertext_len,
+                         max_out - 2, type, wire_version,
+                         ssl->s3->write_sequence, in, in_len) ||
+      !ssl_record_sequence_update(ssl->s3->write_sequence, 8)) {
     return 0;
   }
 
-  if (ciphertext_len >= 1 << 16) {
+  /* Fill in the length. */
+  if (ciphertext_len >= 1 << 15) {
     OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
     return 0;
   }
-  out[3] = ciphertext_len >> 8;
-  out[4] = ciphertext_len & 0xff;
+  out[0] = ciphertext_len >> 8;
+  out[1] = ciphertext_len & 0xff;
 
   *out_len = SSL3_RT_HEADER_LENGTH + ciphertext_len;
 
-  if (ssl->msg_callback) {
-    ssl->msg_callback(1 /* write */, 0, SSL3_RT_HEADER, out,
-                      SSL3_RT_HEADER_LENGTH, ssl, ssl->msg_callback_arg);
-  }
-
+  ssl_do_msg_callback(ssl, 1 /* write */, SSL3_RT_HEADER, out,
+                      SSL3_RT_HEADER_LENGTH);
   return 1;
 }
 
 int tls_seal_record(SSL *ssl, uint8_t *out, size_t *out_len, size_t max_out,
                     uint8_t type, const uint8_t *in, size_t in_len) {
+  if (buffers_alias(in, in_len, out, max_out)) {
+    OPENSSL_PUT_ERROR(SSL, SSL_R_OUTPUT_ALIASES_INPUT);
+    return 0;
+  }
+
   size_t frag_len = 0;
   if (type == SSL3_RT_APPLICATION_DATA && in_len > 1 &&
       ssl_needs_record_splitting(ssl)) {
-    /* |do_seal_record| will notice if it clobbers |in[0]|, but not if it
-     * aliases the rest of |in|. */
-    if (in + 1 <= out && out < in + in_len) {
-      OPENSSL_PUT_ERROR(SSL, SSL_R_OUTPUT_ALIASES_INPUT);
-      return 0;
-    }
-    /* Ensure |do_seal_record| does not write beyond |in[0]|. */
-    size_t frag_max_out = max_out;
-    if (out <= in + 1 && in + 1 < out + frag_max_out) {
-      frag_max_out = (size_t)(in + 1 - out);
-    }
-    if (!do_seal_record(ssl, out, &frag_len, frag_max_out, type, in, 1)) {
+    if (!do_seal_record(ssl, out, &frag_len, max_out, type, in, 1)) {
       return 0;
     }
     in++;
@@ -329,9 +443,11 @@
     out += frag_len;
     max_out -= frag_len;
 
-    assert(SSL3_RT_HEADER_LENGTH +
-               ssl_cipher_get_record_split_len(ssl->aead_write_ctx->cipher) ==
+#if !defined(BORINGSSL_UNSAFE_FUZZER_MODE)
+    assert(SSL3_RT_HEADER_LENGTH + ssl_cipher_get_record_split_len(
+                                       ssl->s3->aead_write_ctx->cipher) ==
            frag_len);
+#endif
   }
 
   if (!do_seal_record(ssl, out, out_len, max_out, type, in, in_len)) {
@@ -340,3 +456,58 @@
   *out_len += frag_len;
   return 1;
 }
+
+enum ssl_open_record_t ssl_process_alert(SSL *ssl, uint8_t *out_alert,
+                                         const uint8_t *in, size_t in_len) {
+  /* Alerts records may not contain fragmented or multiple alerts. */
+  if (in_len != 2) {
+    *out_alert = SSL_AD_DECODE_ERROR;
+    OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ALERT);
+    return ssl_open_record_error;
+  }
+
+  ssl_do_msg_callback(ssl, 0 /* read */, SSL3_RT_ALERT, in, in_len);
+
+  const uint8_t alert_level = in[0];
+  const uint8_t alert_descr = in[1];
+
+  uint16_t alert = (alert_level << 8) | alert_descr;
+  ssl_do_info_callback(ssl, SSL_CB_READ_ALERT, alert);
+
+  if (alert_level == SSL3_AL_WARNING) {
+    if (alert_descr == SSL_AD_CLOSE_NOTIFY) {
+      ssl->s3->recv_shutdown = ssl_shutdown_close_notify;
+      return ssl_open_record_close_notify;
+    }
+
+    /* Warning alerts do not exist in TLS 1.3. */
+    if (ssl->s3->have_version &&
+        ssl3_protocol_version(ssl) >= TLS1_3_VERSION) {
+      *out_alert = SSL_AD_DECODE_ERROR;
+      OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_ALERT);
+      return ssl_open_record_error;
+    }
+
+    ssl->s3->warning_alert_count++;
+    if (ssl->s3->warning_alert_count > kMaxWarningAlerts) {
+      *out_alert = SSL_AD_UNEXPECTED_MESSAGE;
+      OPENSSL_PUT_ERROR(SSL, SSL_R_TOO_MANY_WARNING_ALERTS);
+      return ssl_open_record_error;
+    }
+    return ssl_open_record_discard;
+  }
+
+  if (alert_level == SSL3_AL_FATAL) {
+    ssl->s3->recv_shutdown = ssl_shutdown_fatal_alert;
+
+    char tmp[16];
+    OPENSSL_PUT_ERROR(SSL, SSL_AD_REASON_OFFSET + alert_descr);
+    BIO_snprintf(tmp, sizeof(tmp), "%d", alert_descr);
+    ERR_add_error_data(2, "SSL alert number ", tmp);
+    return ssl_open_record_fatal_alert;
+  }
+
+  *out_alert = SSL_AD_ILLEGAL_PARAMETER;
+  OPENSSL_PUT_ERROR(SSL, SSL_R_UNKNOWN_ALERT_TYPE);
+  return ssl_open_record_error;
+}
diff --git a/src/third_party/android-cmake/AndroidNdkGdb.cmake b/src/third_party/android-cmake/AndroidNdkGdb.cmake
new file mode 100644
index 0000000..0677dcd
--- /dev/null
+++ b/src/third_party/android-cmake/AndroidNdkGdb.cmake
@@ -0,0 +1,96 @@
+# Copyright (c) 2014, Pavel Rojtberg
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the copyright holder nor the names of its
+# contributors may be used to endorse or promote products derived from this
+# software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+# ------------------------------------------------------------------------------
+# Usage:
+# 1. place AndroidNdkGdb.cmake somewhere inside ${CMAKE_MODULE_PATH}
+# 2. inside your project add
+#
+#    include(AndroidNdkGdb)
+#    android_ndk_gdb_enable()
+#    # for each target
+#    add_library(MyLibrary ...)
+#    android_ndk_gdb_debuggable(MyLibrary)    
+
+
+# add gdbserver and general gdb configuration to project
+# also create a mininal NDK skeleton so ndk-gdb finds the paths
+#
+# the optional parameter defines the path to the android project.
+# uses PROJECT_SOURCE_DIR by default.
+macro(android_ndk_gdb_enable)
+    if(ANDROID)
+        # create custom target that depends on the real target so it gets executed afterwards
+        add_custom_target(NDK_GDB ALL)
+        
+        if(${ARGC})
+            set(ANDROID_PROJECT_DIR ${ARGV0})
+        else()
+            set(ANDROID_PROJECT_DIR ${PROJECT_SOURCE_DIR})
+        endif()
+
+        set(NDK_GDB_SOLIB_PATH ${ANDROID_PROJECT_DIR}/obj/local/${ANDROID_NDK_ABI_NAME}/)
+        file(MAKE_DIRECTORY ${NDK_GDB_SOLIB_PATH})
+        
+        # 1. generate essential Android Makefiles
+        file(MAKE_DIRECTORY ${ANDROID_PROJECT_DIR}/jni)
+        if(NOT EXISTS ${ANDROID_PROJECT_DIR}/jni/Android.mk)
+            file(WRITE ${ANDROID_PROJECT_DIR}/jni/Android.mk "APP_ABI := ${ANDROID_NDK_ABI_NAME}\n")
+        endif()
+        if(NOT EXISTS ${ANDROID_PROJECT_DIR}/jni/Application.mk)
+            file(WRITE ${ANDROID_PROJECT_DIR}/jni/Application.mk "APP_ABI := ${ANDROID_NDK_ABI_NAME}\n")
+        endif()
+    
+        # 2. generate gdb.setup
+        get_directory_property(PROJECT_INCLUDES DIRECTORY ${PROJECT_SOURCE_DIR} INCLUDE_DIRECTORIES)
+        string(REGEX REPLACE ";" " " PROJECT_INCLUDES "${PROJECT_INCLUDES}")
+        file(WRITE ${LIBRARY_OUTPUT_PATH}/gdb.setup "set solib-search-path ${NDK_GDB_SOLIB_PATH}\n")
+        file(APPEND ${LIBRARY_OUTPUT_PATH}/gdb.setup "directory ${PROJECT_INCLUDES}\n")
+    
+        # 3. copy gdbserver executable
+        file(COPY ${ANDROID_NDK}/prebuilt/android-${ANDROID_ARCH_NAME}/gdbserver/gdbserver DESTINATION ${LIBRARY_OUTPUT_PATH})
+    endif()
+endmacro()
+
+# register a target for remote debugging
+# copies the debug version to NDK_GDB_SOLIB_PATH then strips symbols of original
+macro(android_ndk_gdb_debuggable TARGET_NAME)
+    if(ANDROID)
+        get_property(TARGET_LOCATION TARGET ${TARGET_NAME} PROPERTY LOCATION)
+        
+        # create custom target that depends on the real target so it gets executed afterwards
+        add_dependencies(NDK_GDB ${TARGET_NAME})
+    
+        # 4. copy lib to obj
+        add_custom_command(TARGET NDK_GDB POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${TARGET_LOCATION} ${NDK_GDB_SOLIB_PATH})
+    
+        # 5. strip symbols
+        add_custom_command(TARGET NDK_GDB POST_BUILD COMMAND ${CMAKE_STRIP} ${TARGET_LOCATION})
+    endif()
+endmacro()
diff --git a/src/third_party/android-cmake/AndroidNdkModules.cmake b/src/third_party/android-cmake/AndroidNdkModules.cmake
new file mode 100644
index 0000000..64f37fd
--- /dev/null
+++ b/src/third_party/android-cmake/AndroidNdkModules.cmake
@@ -0,0 +1,58 @@
+# Copyright (c) 2014, Pavel Rojtberg
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the copyright holder nor the names of its
+# contributors may be used to endorse or promote products derived from this
+# software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+macro(android_ndk_import_module_cpufeatures)
+    if(ANDROID)
+        include_directories(${ANDROID_NDK}/sources/android/cpufeatures)
+        add_library(cpufeatures ${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c)
+        target_link_libraries(cpufeatures dl)
+    endif()
+endmacro()
+
+macro(android_ndk_import_module_native_app_glue)
+    if(ANDROID)
+        include_directories(${ANDROID_NDK}/sources/android/native_app_glue)
+        add_library(native_app_glue ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c)
+        target_link_libraries(native_app_glue log)
+    endif()
+endmacro()
+
+macro(android_ndk_import_module_ndk_helper)
+    if(ANDROID)
+        android_ndk_import_module_cpufeatures()
+        android_ndk_import_module_native_app_glue()
+        
+        include_directories(${ANDROID_NDK}/sources/android/ndk_helper)
+        file(GLOB _NDK_HELPER_SRCS ${ANDROID_NDK}/sources/android/ndk_helper/*.cpp ${ANDROID_NDK}/sources/android/ndk_helper/gl3stub.c)
+        add_library(ndk_helper ${_NDK_HELPER_SRCS})
+        target_link_libraries(ndk_helper log android EGL GLESv2 cpufeatures native_app_glue)
+        
+        unset(_NDK_HELPER_SRCS)
+    endif()
+endmacro()
\ No newline at end of file
diff --git a/src/third_party/android-cmake/LICENSE b/src/third_party/android-cmake/LICENSE
new file mode 100644
index 0000000..a96a369
--- /dev/null
+++ b/src/third_party/android-cmake/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2010-2011, Ethan Rublee
+Copyright (c) 2011-2014, Andrey Kamaev
+Copyright (c) 2014, Pavel Rojtberg
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1.  Redistributions of source code must retain the above copyright notice,
+    this list of conditions and the following disclaimer.
+
+2.  Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+
+3.  Neither the name of the copyright holder nor the names of its
+    contributors may be used to endorse or promote products derived from this
+    software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/src/third_party/android-cmake/METADATA b/src/third_party/android-cmake/METADATA
new file mode 100644
index 0000000..0ba6817
--- /dev/null
+++ b/src/third_party/android-cmake/METADATA
@@ -0,0 +1,15 @@
+name: "android-cmake"
+description:
+    "android-cmake is a collection of CMake scripts for building against the "
+    "Android NDK."
+
+third_party {
+  url {
+    type: HOMEPAGE
+    value: "https://github.com/taka-no-me/android-cmake/"
+  }
+  version: "556cc14296c226f753a3778d99d8b60778b7df4f"
+  last_upgrade_date { year: 2016 month: 6 day: 2 }
+
+  local_modifications: "LICENSE file has been created for compliance purposes. Not included in original distribution."
+}
diff --git a/src/third_party/android-cmake/README.md b/src/third_party/android-cmake/README.md
new file mode 100644
index 0000000..ee63021
--- /dev/null
+++ b/src/third_party/android-cmake/README.md
@@ -0,0 +1,240 @@
+# android-cmake
+
+CMake is great, and so is Android. This is a collection of CMake scripts that may be useful to the Android NDK community. It is based on experience from porting OpenCV library to Android: http://opencv.org/platforms/android.html
+
+Main goal is to share these scripts so that devs that use CMake as their build system may easily compile native code for Android.
+
+## TL;DR
+
+    cmake -DCMAKE_TOOLCHAIN_FILE=android.toolchain.cmake \
+          -DANDROID_NDK=<ndk_path>                       \
+          -DCMAKE_BUILD_TYPE=Release                     \
+          -DANDROID_ABI="armeabi-v7a with NEON"          \
+          <source_path>
+    cmake --build .
+
+One-liner:
+
+    cmake -DCMAKE_TOOLCHAIN_FILE=android.toolchain.cmake -DANDROID_NDK=<ndk_path> -DCMAKE_BUILD_TYPE=Release -DANDROID_ABI="armeabi-v7a with NEON" <source_path> && cmake --build .
+
+_android-cmake_ will search for your NDK install in the following order:
+
+1. Value of `ANDROID_NDK` CMake variable;
+1. Value of `ANDROID_NDK` environment variable;
+1. Search under paths from `ANDROID_NDK_SEARCH_PATHS` CMake variable;
+1. Search platform specific locations (home folder, Windows "Program Files", etc).
+
+So if you have installed the NDK as `~/android-ndk-r10d` then _android-cmake_ will locate it automatically.
+
+## Getting started
+
+To build a cmake-based C/C++ project for Android you need:
+
+* Android NDK (>= r5) http://developer.android.com/tools/sdk/ndk/index.html
+* CMake (>= v2.6.3, >= v2.8.9 recommended) http://www.cmake.org/download
+
+The _android-cmake_ is also capable to build with NDK from AOSP or Linaro Android source tree, but you may be required to manually specify path to `libm` binary to link with.
+
+## Difference from traditional CMake
+
+Folowing the _ndk-build_ the _android-cmake_ supports **only two build targets**:
+
+* `-DCMAKE_BUILD_TYPE=Release`
+* `-DCMAKE_BUILD_TYPE=Debug`
+
+So don't even try other targets that can be found in CMake documentation and don't forget to explicitly specify `Release` or `Debug` because CMake builds without a build configuration by default.
+
+## Difference from _ndk-build_
+
+* Latest GCC available in NDK is used as the default compiler;
+* `Release` builds with `-O3` instead of `-Os`;
+* `Release` builds without debug info (without `-g`) (because _ndk-build_ always creates a stripped version but cmake delays this for `install/strip` target);
+* `-fsigned-char` is added to compiler flags to make `char` signed by default as it is on x86/x86_64;
+* GCC's stack protector is not used neither in `Debug` nor `Release` configurations;
+* No builds for multiple platforms (e.g. building for both arm and x86 require to run cmake twice with different parameters);
+* No file level Neon via `.neon` suffix;
+
+The following features of _ndk-build_ are not supported by the _android-cmake_ yet:
+
+* `armeabi-v7a-hard` ABI
+* `libc++_static`/`libc++_shared` STL runtime
+
+## Basic options
+
+Similarly to the NDK build system _android-cmake_ allows to select between several compiler toolchains and target platforms. Most of the options can be set either as cmake arguments: `-D<NAME>=<VALUE>` or as environment variables:
+
+* **ANDROID_NDK** - path to the Android NDK. If not set then _android-cmake_ will search for the most recent version of supported NDK in commonly used locations;
+* **ANDROID_ABI** - specifies the target Application Binary Interface (ABI). This option nearly matches to the APP_ABI variable used by ndk-build tool from Android NDK. If not specified then set to `armeabi-v7a`. Possible target names are:
+    * `armeabi` - ARMv5TE based CPU with software floating point operations;
+    * **`armeabi-v7a`** - ARMv7 based devices with hardware FPU instructions (VFPv3_D16);
+    * `armeabi-v7a with NEON` - same as armeabi-v7a, but sets NEON as floating-point unit;
+    * `armeabi-v7a with VFPV3` - same as armeabi-v7a, but sets VFPv3_D32 as floating-point unit;
+    * `armeabi-v6 with VFP` - tuned for ARMv6 processors having VFP;
+    * `x86` - IA-32 instruction set
+    * `mips` - MIPS32 instruction set
+    * `arm64-v8a` - ARMv8 AArch64 instruction set - only for NDK r10 and newer
+    * `x86_64` - Intel64 instruction set (r1) - only for NDK r10 and newer
+    * `mips64` - MIPS64 instruction set (r6) - only for NDK r10 and newer
+* **ANDROID_NATIVE_API_LEVEL** - level of android API to build for. Can be set either to full name (example: `android-8`) or a numeric value (example: `17`). The default API level depends on the target ABI:
+    * `android-8` for ARM;
+    * `android-9` for x86 and MIPS;
+    * `android-21` for 64-bit ABIs.
+
+    Building for `android-L` is possible only when it is explicitly selected.
+* **ANDROID_TOOLCHAIN_NAME** - the name of compiler toolchain to be used. This option allows to select between different GCC and Clang versions. The list of possible values depends on the NDK version and will be printed by toolchain file if an invalid value is set. By default _android-cmake_ selects the most recent version of GCC which can build for specified `ANDROID_ABI`.
+
+    Example values are:
+    * `aarch64-linux-android-4.9`
+    * `aarch64-linux-android-clang3.5`
+    * `arm-linux-androideabi-4.8`
+    * `arm-linux-androideabi-4.9`
+    * `arm-linux-androideabi-clang3.5`
+    * `mips64el-linux-android-4.9`
+    * `mipsel-linux-android-4.8`
+    * `x86-4.9`
+    * `x86_64-4.9`
+    * etc.
+* **ANDROID_STL** - the name of C++ runtime to use. The default is `gnustl_static`.
+    * `none` - do not configure the runtime.
+    * `system` - use the default minimal system C++ runtime library.
+        * Implies `-fno-rtti -fno-exceptions`.
+    * `system_re` - use the default minimal system C++ runtime library.
+        * Implies `-frtti -fexceptions`.
+    * `gabi++_static` - use the GAbi++ runtime as a static library.
+        * Implies `-frtti -fno-exceptions`.
+        * Available for NDK r7 and newer.
+    * `gabi++_shared` - use the GAbi++ runtime as a shared library.
+        * Implies `-frtti -fno-exceptions`.
+        * Available for NDK r7 and newer.
+    * `stlport_static` - use the STLport runtime as a static library.
+        * Implies `-fno-rtti -fno-exceptions` for NDK before r7.
+        * Implies `-frtti -fno-exceptions` for NDK r7 and newer.
+    * `stlport_shared` - use the STLport runtime as a shared library.
+        * Implies `-fno-rtti -fno-exceptions` for NDK before r7.
+        * Implies `-frtti -fno-exceptions` for NDK r7 and newer.
+    * **`gnustl_static`** - use the GNU STL as a static library.
+        * Implies `-frtti -fexceptions`.
+    * `gnustl_shared` - use the GNU STL as a shared library.
+        * Implies `-frtti -fno-exceptions`.
+        * Available for NDK r7b and newer.
+        * Silently degrades to `gnustl_static` if not available.
+* **NDK_CCACHE** - path to `ccache` executable. If not set then initialized from `NDK_CCACHE` environment variable.
+
+## Advanced _android-cmake_ options
+
+Normally _android-cmake_ users are not supposed to touch these variables but they might be useful to workaround some build issues:
+
+* **ANDROID_FORCE_ARM_BUILD** = `OFF` - generate 32-bit ARM instructions instead of Thumb. Applicable only for arm ABIs and is forced to be `ON` for `armeabi-v6 with VFP`;
+* **ANDROID_NO_UNDEFINED** = `ON` - show all undefined symbols as linker errors;
+* **ANDROID_SO_UNDEFINED** = `OFF` - allow undefined symbols in shared libraries;
+    * actually it is turned `ON` by default for NDK older than `r7`
+* **ANDROID_STL_FORCE_FEATURES** = `ON` - automatically configure rtti and exceptions support based on C++ runtime;
+* **ANDROID_NDK_LAYOUT** = `RELEASE` - inner layout of Android NDK, should be detected automatically. Possible values are:
+    * `RELEASE` - public releases from Google;
+    * `LINARO` - NDK from Linaro project;
+    * `ANDROID` - NDK from AOSP.
+* **ANDROID_FUNCTION_LEVEL_LINKING** = `ON` - enables saparate putting each function and data items into separate sections and enable garbage collection of unused input sections at link time (`-fdata-sections -ffunction-sections -Wl,--gc-sections`);
+* **ANDROID_GOLD_LINKER** = `ON` - use gold linker with GCC 4.6 for NDK r8b and newer (only for ARM and x86);
+* **ANDROID_NOEXECSTACK** = `ON` - enables or disables stack execution protection code (`-Wl,-z,noexecstack`);
+* **ANDROID_RELRO** = `ON` - Enables RELRO - a memory corruption mitigation technique (`-Wl,-z,relro -Wl,-z,now`);
+* **ANDROID_LIBM_PATH** - path to `libm.so` (set to something like `$(TOP)/out/target/product/<product_name>/obj/lib/libm.so`) to workaround unresolved `sincos`.
+
+## Fine-tuning `CMakeLists.txt` for _android-cmake_
+
+### Recognizing Android build
+
+_android-cmake_ defines `ANDROID` CMake variable which can be used to add Android-specific stuff:
+
+    if (ANDROID)
+        message(STATUS "Hello from Android build!")
+    endif()
+
+The recommended way to identify ARM/MIPS/x86 architecture is examining `CMAKE_SYSTEM_PROCESSOR` which is set to the appropriate value:
+
+* `armv5te` - for `armeabi` ABI
+* `armv6` - for `armeabi-v6 with VFP` ABI
+* `armv7-a` - for `armeabi-v7a`, `armeabi-v7a with VFPV3` and `armeabi-v7a with NEON` ABIs
+* `aarch64` - for `arm64-v8a` ABI
+* `i686` - for `x86` ABI
+* `x86_64` - for `x86_64` ABI
+* `mips` - for `mips` ABI
+* `mips64` - for `mips64` ABI
+
+Other variables that are set by _android-cmake_ and can be used for the fine-grained build configuration are:
+
+* `NEON` - set if target ABI supports Neon;
+* `ANDROID_NATIVE_API_LEVEL` - native Android API level we are building for (note: Java part of Andoid application can be built for another API level)
+* `ANDROID_NDK_RELEASE` - version of the Android NDK
+* `ANDROID_NDK_HOST_SYSTEM_NAME` - "windows", "linux-x86" or "darwin-x86" depending on the host platform
+* `ANDROID_RTTI` - set if rtti is enabled by the runtime
+* `ANDROID_EXCEPTIONS` - set if exceptions are enabled by the runtime
+
+### Finding packages
+
+When crosscompiling CMake `find_*` commands are normally expected to find libraries and packages belonging to the same build target. So _android-cmake_ configures CMake to search in Android-specific paths only and ignore your host system locations. So
+
+    find_package(ZLIB)
+
+will surely find libz.so within the Android NDK.
+
+However sometimes you need to locate a host package even when cross-compiling. For example you can be searching for your documentation generator. The _android-cmake_ recommends you to use `find_host_package` and `find_host_program` macro defined in the `android.toolchain.cmake`:
+
+    find_host_package(Doxygen)
+    find_host_program(PDFLATEX pdflatex)
+
+However this will break regular builds so instead of wrapping package search into platform-specific logic you can copy the following snippet into your project (put it after your top-level `project()` command):
+
+    # Search packages for host system instead of packages for target system
+    # in case of cross compilation these macro should be defined by toolchain file
+    if(NOT COMMAND find_host_package)
+      macro(find_host_package)
+        find_package(${ARGN})
+      endmacro()
+    endif()
+    if(NOT COMMAND find_host_program)
+      macro(find_host_program)
+        find_program(${ARGN})
+      endmacro()
+    endif()
+
+### Compiler flags recycling
+
+Make sure to do the following in your scripts:
+
+    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${my_cxx_flags}")
+    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${my_cxx_flags}")
+
+The flags will be prepopulated with critical flags, so don't loose them. Also be aware that _android-cmake_ also sets configuration-specific compiler and linker flags.
+
+## Troubleshooting
+
+### Building on Windows
+
+First of all `cygwin` builds are **NOT supported** and will not be supported by _android-cmake_. To build natively on Windows you need a port of make but I recommend http://martine.github.io/ninja/ instead.
+
+To build with Ninja you need:
+
+* Ensure you are using CMake newer than 2.8.9;
+* Download the latest Ninja from https://github.com/martine/ninja/releases;
+* Put the `ninja.exe` into your PATH (or add path to `ninja.exe` to your PATH environment variable);
+* Pass `-GNinja` to `cmake` alongside with other arguments (or choose Ninja generator in `cmake-gui`).
+* Enjoy the fast native multithreaded build :)
+
+But if you still want to stick to old make then:
+
+* Get a Windows port of GNU Make:
+    * Android NDK r7 (and newer) already has `make.exe` on board;
+    * `mingw-make` should work as fine;
+    * Download some other port. For example, this one: http://gnuwin32.sourceforge.net/packages/make.htm.
+* Add path to your `make.exe` to system PATH or always use full path;
+* Pass `-G"MinGW Makefiles"` and `-DCMAKE_MAKE_PROGRAM="<full/path/to/>make.exe"`
+    * It must be `MinGW Makefiles` and not `Unix Makefiles` even if your `make.exe` is not a MinGW's make.
+* Run `make.exe` or `cmake --build .` for single-threaded build.
+
+### Projects with assembler files
+
+The _android-cmake_ should correctly handle projects with assembler sources (`*.s` or `*.S`). But if you still facing problems with assembler then try to upgrade your CMake to version newer than 2.8.5
+
+## Copying
+
+_android-cmake_ is distributed under the terms of [BSD 3-Clause License](http://opensource.org/licenses/BSD-3-Clause)
\ No newline at end of file
diff --git a/src/third_party/android-cmake/android.toolchain.cmake b/src/third_party/android-cmake/android.toolchain.cmake
new file mode 100644
index 0000000..ffa2612
--- /dev/null
+++ b/src/third_party/android-cmake/android.toolchain.cmake
@@ -0,0 +1,1693 @@
+# Copyright (c) 2010-2011, Ethan Rublee
+# Copyright (c) 2011-2014, Andrey Kamaev
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1.  Redistributions of source code must retain the above copyright notice,
+#     this list of conditions and the following disclaimer.
+#
+# 2.  Redistributions in binary form must reproduce the above copyright notice,
+#     this list of conditions and the following disclaimer in the documentation
+#     and/or other materials provided with the distribution.
+#
+# 3.  Neither the name of the copyright holder nor the names of its
+#     contributors may be used to endorse or promote products derived from this
+#     software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+# ------------------------------------------------------------------------------
+#  Android CMake toolchain file, for use with the Android NDK r5-r10d
+#  Requires cmake 2.6.3 or newer (2.8.9 or newer is recommended).
+#  See home page: https://github.com/taka-no-me/android-cmake
+#
+#  Usage Linux:
+#   $ export ANDROID_NDK=/absolute/path/to/the/android-ndk
+#   $ mkdir build && cd build
+#   $ cmake -DCMAKE_TOOLCHAIN_FILE=path/to/the/android.toolchain.cmake ..
+#   $ make -j8
+#
+#  Usage Windows:
+#     You need native port of make to build your project.
+#     Android NDK r7 (and newer) already has make.exe on board.
+#     For older NDK you have to install it separately.
+#     For example, this one: http://gnuwin32.sourceforge.net/packages/make.htm
+#
+#   $ SET ANDROID_NDK=C:\absolute\path\to\the\android-ndk
+#   $ mkdir build && cd build
+#   $ cmake.exe -G"MinGW Makefiles"
+#       -DCMAKE_TOOLCHAIN_FILE=path\to\the\android.toolchain.cmake
+#       -DCMAKE_MAKE_PROGRAM="%ANDROID_NDK%\prebuilt\windows\bin\make.exe" ..
+#   $ cmake.exe --build .
+#
+#
+#  Options (can be set as cmake parameters: -D<option_name>=<value>):
+#    ANDROID_NDK=/opt/android-ndk - path to the NDK root.
+#      Can be set as environment variable. Can be set only at first cmake run.
+#
+#    ANDROID_ABI=armeabi-v7a - specifies the target Application Binary
+#      Interface (ABI). This option nearly matches to the APP_ABI variable
+#      used by ndk-build tool from Android NDK.
+#
+#      Possible targets are:
+#        "armeabi" - ARMv5TE based CPU with software floating point operations
+#        "armeabi-v7a" - ARMv7 based devices with hardware FPU instructions
+#            this ABI target is used by default
+#        "armeabi-v7a with NEON" - same as armeabi-v7a, but
+#            sets NEON as floating-point unit
+#        "armeabi-v7a with VFPV3" - same as armeabi-v7a, but
+#            sets VFPV3 as floating-point unit (has 32 registers instead of 16)
+#        "armeabi-v6 with VFP" - tuned for ARMv6 processors having VFP
+#        "x86" - IA-32 instruction set
+#        "mips" - MIPS32 instruction set
+#
+#      64-bit ABIs for NDK r10 and newer:
+#        "arm64-v8a" - ARMv8 AArch64 instruction set
+#        "x86_64" - Intel64 instruction set (r1)
+#        "mips64" - MIPS64 instruction set (r6)
+#
+#    ANDROID_NATIVE_API_LEVEL=android-8 - level of Android API compile for.
+#      Option is read-only when standalone toolchain is used.
+#      Note: building for "android-L" requires explicit configuration.
+#
+#    ANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-4.9 - the name of compiler
+#      toolchain to be used. The list of possible values depends on the NDK
+#      version. For NDK r10c the possible values are:
+#
+#        * aarch64-linux-android-4.9
+#        * aarch64-linux-android-clang3.4
+#        * aarch64-linux-android-clang3.5
+#        * arm-linux-androideabi-4.6
+#        * arm-linux-androideabi-4.8
+#        * arm-linux-androideabi-4.9 (default)
+#        * arm-linux-androideabi-clang3.4
+#        * arm-linux-androideabi-clang3.5
+#        * mips64el-linux-android-4.9
+#        * mips64el-linux-android-clang3.4
+#        * mips64el-linux-android-clang3.5
+#        * mipsel-linux-android-4.6
+#        * mipsel-linux-android-4.8
+#        * mipsel-linux-android-4.9
+#        * mipsel-linux-android-clang3.4
+#        * mipsel-linux-android-clang3.5
+#        * x86-4.6
+#        * x86-4.8
+#        * x86-4.9
+#        * x86-clang3.4
+#        * x86-clang3.5
+#        * x86_64-4.9
+#        * x86_64-clang3.4
+#        * x86_64-clang3.5
+#
+#    ANDROID_FORCE_ARM_BUILD=OFF - set ON to generate 32-bit ARM instructions
+#      instead of Thumb. Is not available for "armeabi-v6 with VFP"
+#      (is forced to be ON) ABI.
+#
+#    ANDROID_NO_UNDEFINED=ON - set ON to show all undefined symbols as linker
+#      errors even if they are not used.
+#
+#    ANDROID_SO_UNDEFINED=OFF - set ON to allow undefined symbols in shared
+#      libraries. Automatically turned for NDK r5x and r6x due to GLESv2
+#      problems.
+#
+#    ANDROID_STL=gnustl_static - specify the runtime to use.
+#
+#      Possible values are:
+#        none           -> Do not configure the runtime.
+#        system         -> Use the default minimal system C++ runtime library.
+#                          Implies -fno-rtti -fno-exceptions.
+#                          Is not available for standalone toolchain.
+#        system_re      -> Use the default minimal system C++ runtime library.
+#                          Implies -frtti -fexceptions.
+#                          Is not available for standalone toolchain.
+#        gabi++_static  -> Use the GAbi++ runtime as a static library.
+#                          Implies -frtti -fno-exceptions.
+#                          Available for NDK r7 and newer.
+#                          Is not available for standalone toolchain.
+#        gabi++_shared  -> Use the GAbi++ runtime as a shared library.
+#                          Implies -frtti -fno-exceptions.
+#                          Available for NDK r7 and newer.
+#                          Is not available for standalone toolchain.
+#        stlport_static -> Use the STLport runtime as a static library.
+#                          Implies -fno-rtti -fno-exceptions for NDK before r7.
+#                          Implies -frtti -fno-exceptions for NDK r7 and newer.
+#                          Is not available for standalone toolchain.
+#        stlport_shared -> Use the STLport runtime as a shared library.
+#                          Implies -fno-rtti -fno-exceptions for NDK before r7.
+#                          Implies -frtti -fno-exceptions for NDK r7 and newer.
+#                          Is not available for standalone toolchain.
+#        gnustl_static  -> Use the GNU STL as a static library.
+#                          Implies -frtti -fexceptions.
+#        gnustl_shared  -> Use the GNU STL as a shared library.
+#                          Implies -frtti -fno-exceptions.
+#                          Available for NDK r7b and newer.
+#                          Silently degrades to gnustl_static if not available.
+#
+#    ANDROID_STL_FORCE_FEATURES=ON - turn rtti and exceptions support based on
+#      chosen runtime. If disabled, then the user is responsible for settings
+#      these options.
+#
+#  What?:
+#    android-cmake toolchain searches for NDK/toolchain in the following order:
+#      ANDROID_NDK - cmake parameter
+#      ANDROID_NDK - environment variable
+#      ANDROID_STANDALONE_TOOLCHAIN - cmake parameter
+#      ANDROID_STANDALONE_TOOLCHAIN - environment variable
+#      ANDROID_NDK - default locations
+#      ANDROID_STANDALONE_TOOLCHAIN - default locations
+#
+#    Make sure to do the following in your scripts:
+#      SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${my_cxx_flags}" )
+#      SET( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${my_cxx_flags}" )
+#    The flags will be prepopulated with critical flags, so don't loose them.
+#    Also be aware that toolchain also sets configuration-specific compiler
+#    flags and linker flags.
+#
+#    ANDROID and BUILD_ANDROID will be set to true, you may test any of these
+#    variables to make necessary Android-specific configuration changes.
+#
+#    Also ARMEABI or ARMEABI_V7A or X86 or MIPS or ARM64_V8A or X86_64 or MIPS64
+#    will be set true, mutually exclusive. NEON option will be set true
+#    if VFP is set to NEON.
+#
+# ------------------------------------------------------------------------------
+
+cmake_minimum_required( VERSION 2.6.3 )
+
+if( DEFINED CMAKE_CROSSCOMPILING )
+ # subsequent toolchain loading is not really needed
+ return()
+endif()
+
+if( CMAKE_TOOLCHAIN_FILE )
+ # touch toolchain variable to suppress "unused variable" warning
+endif()
+
+# inherit settings in recursive loads
+get_property( _CMAKE_IN_TRY_COMPILE GLOBAL PROPERTY IN_TRY_COMPILE )
+if( _CMAKE_IN_TRY_COMPILE )
+ include( "${CMAKE_CURRENT_SOURCE_DIR}/../android.toolchain.config.cmake" OPTIONAL )
+endif()
+
+# this one is important
+if( CMAKE_VERSION VERSION_GREATER "3.0.99" )
+ set( CMAKE_SYSTEM_NAME Android )
+else()
+ set( CMAKE_SYSTEM_NAME Linux )
+endif()
+
+# this one not so much
+set( CMAKE_SYSTEM_VERSION 1 )
+
+# rpath makes low sense for Android
+set( CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG "" )
+set( CMAKE_SKIP_RPATH TRUE CACHE BOOL "If set, runtime paths are not added when using shared libraries." )
+
+# NDK search paths
+set( ANDROID_SUPPORTED_NDK_VERSIONS ${ANDROID_EXTRA_NDK_VERSIONS} -r10d -r10c -r10b -r10 -r9d -r9c -r9b -r9 -r8e -r8d -r8c -r8b -r8 -r7c -r7b -r7 -r6b -r6 -r5c -r5b -r5 "" )
+if( NOT DEFINED ANDROID_NDK_SEARCH_PATHS )
+ if( CMAKE_HOST_WIN32 )
+  file( TO_CMAKE_PATH "$ENV{PROGRAMFILES}" ANDROID_NDK_SEARCH_PATHS )
+  set( ANDROID_NDK_SEARCH_PATHS "${ANDROID_NDK_SEARCH_PATHS}" "$ENV{SystemDrive}/NVPACK" )
+ else()
+  file( TO_CMAKE_PATH "$ENV{HOME}" ANDROID_NDK_SEARCH_PATHS )
+  set( ANDROID_NDK_SEARCH_PATHS /opt "${ANDROID_NDK_SEARCH_PATHS}/NVPACK" )
+ endif()
+endif()
+if( NOT DEFINED ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH )
+ set( ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH /opt/android-toolchain )
+endif()
+
+# known ABIs
+set( ANDROID_SUPPORTED_ABIS_arm "armeabi-v7a;armeabi;armeabi-v7a with NEON;armeabi-v7a with VFPV3;armeabi-v6 with VFP" )
+set( ANDROID_SUPPORTED_ABIS_arm64 "arm64-v8a" )
+set( ANDROID_SUPPORTED_ABIS_x86 "x86" )
+set( ANDROID_SUPPORTED_ABIS_x86_64 "x86_64" )
+set( ANDROID_SUPPORTED_ABIS_mips "mips" )
+set( ANDROID_SUPPORTED_ABIS_mips64 "mips64" )
+
+# API level defaults
+set( ANDROID_DEFAULT_NDK_API_LEVEL 8 )
+set( ANDROID_DEFAULT_NDK_API_LEVEL_arm64 21 )
+set( ANDROID_DEFAULT_NDK_API_LEVEL_x86 9 )
+set( ANDROID_DEFAULT_NDK_API_LEVEL_x86_64 21 )
+set( ANDROID_DEFAULT_NDK_API_LEVEL_mips 9 )
+set( ANDROID_DEFAULT_NDK_API_LEVEL_mips64 21 )
+
+
+macro( __LIST_FILTER listvar regex )
+  if( ${listvar} )
+    foreach( __val ${${listvar}} )
+      if( __val MATCHES "${regex}" )
+        list( REMOVE_ITEM ${listvar} "${__val}" )
+      endif()
+    endforeach()
+  endif()
+endmacro()
+
+macro( __INIT_VARIABLE var_name )
+  set( __test_path 0 )
+  foreach( __var ${ARGN} )
+    if( __var STREQUAL "PATH" )
+      set( __test_path 1 )
+      break()
+    endif()
+  endforeach()
+
+  if( __test_path AND NOT EXISTS "${${var_name}}" )
+    unset( ${var_name} CACHE )
+  endif()
+
+  if( " ${${var_name}}" STREQUAL " " )
+    set( __values 0 )
+    foreach( __var ${ARGN} )
+      if( __var STREQUAL "VALUES" )
+        set( __values 1 )
+      elseif( NOT __var STREQUAL "PATH" )
+        if( __var MATCHES "^ENV_.*$" )
+          string( REPLACE "ENV_" "" __var "${__var}" )
+          set( __value "$ENV{${__var}}" )
+        elseif( DEFINED ${__var} )
+          set( __value "${${__var}}" )
+        elseif( __values )
+          set( __value "${__var}" )
+        else()
+          set( __value "" )
+        endif()
+
+        if( NOT " ${__value}" STREQUAL " " AND (NOT __test_path OR EXISTS "${__value}") )
+          set( ${var_name} "${__value}" )
+          break()
+        endif()
+      endif()
+    endforeach()
+    unset( __value )
+    unset( __values )
+  endif()
+
+  if( __test_path )
+    file( TO_CMAKE_PATH "${${var_name}}" ${var_name} )
+  endif()
+  unset( __test_path )
+endmacro()
+
+macro( __DETECT_NATIVE_API_LEVEL _var _path )
+  set( __ndkApiLevelRegex "^[\t ]*#define[\t ]+__ANDROID_API__[\t ]+([0-9]+)[\t ]*.*$" )
+  file( STRINGS ${_path} __apiFileContent REGEX "${__ndkApiLevelRegex}" )
+  if( NOT __apiFileContent )
+    message( SEND_ERROR "Could not get Android native API level. Probably you have specified invalid level value, or your copy of NDK/toolchain is broken." )
+  endif()
+  string( REGEX REPLACE "${__ndkApiLevelRegex}" "\\1" ${_var} "${__apiFileContent}" )
+  unset( __apiFileContent )
+  unset( __ndkApiLevelRegex )
+endmacro()
+
+macro( __DETECT_TOOLCHAIN_MACHINE_NAME _var _root )
+ if( EXISTS "${_root}" )
+    file( GLOB __gccExePath RELATIVE "${_root}/bin/" "${_root}/bin/*-gcc${TOOL_OS_SUFFIX}" )
+    __LIST_FILTER( __gccExePath "^[.].*" )
+    list( LENGTH __gccExePath __gccExePathsCount )
+    if( NOT __gccExePathsCount EQUAL 1  AND NOT _CMAKE_IN_TRY_COMPILE )
+      message( WARNING "Could not determine machine name for compiler from ${_root}" )
+      set( ${_var} "" )
+    else()
+      get_filename_component( __gccExeName "${__gccExePath}" NAME_WE )
+      string( REPLACE "-gcc" "" ${_var} "${__gccExeName}" )
+    endif()
+    unset( __gccExePath )
+    unset( __gccExePathsCount )
+    unset( __gccExeName )
+  else()
+    set( ${_var} "" )
+  endif()
+endmacro()
+
+
+# fight against cygwin
+set( ANDROID_FORBID_SYGWIN TRUE CACHE BOOL "Prevent cmake from working under cygwin and using cygwin tools")
+mark_as_advanced( ANDROID_FORBID_SYGWIN )
+if( ANDROID_FORBID_SYGWIN )
+ if( CYGWIN )
+  message( FATAL_ERROR "Android NDK and android-cmake toolchain are not welcome Cygwin. It is unlikely that this cmake toolchain will work under cygwin. But if you want to try then you can set cmake variable ANDROID_FORBID_SYGWIN to FALSE and rerun cmake." )
+ endif()
+
+ if( CMAKE_HOST_WIN32 )
+  # remove cygwin from PATH
+  set( __new_path "$ENV{PATH}")
+  __LIST_FILTER( __new_path "cygwin" )
+  set(ENV{PATH} "${__new_path}")
+  unset(__new_path)
+ endif()
+endif()
+
+
+# detect current host platform
+if( NOT DEFINED ANDROID_NDK_HOST_X64 AND (CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "amd64|x86_64|AMD64" OR CMAKE_HOST_APPLE) )
+ set( ANDROID_NDK_HOST_X64 1 CACHE BOOL "Try to use 64-bit compiler toolchain" )
+ mark_as_advanced( ANDROID_NDK_HOST_X64 )
+endif()
+
+set( TOOL_OS_SUFFIX "" )
+if( CMAKE_HOST_APPLE )
+ set( ANDROID_NDK_HOST_SYSTEM_NAME "darwin-x86_64" )
+ set( ANDROID_NDK_HOST_SYSTEM_NAME2 "darwin-x86" )
+elseif( CMAKE_HOST_WIN32 )
+ set( ANDROID_NDK_HOST_SYSTEM_NAME "windows-x86_64" )
+ set( ANDROID_NDK_HOST_SYSTEM_NAME2 "windows" )
+ set( TOOL_OS_SUFFIX ".exe" )
+elseif( CMAKE_HOST_UNIX )
+ set( ANDROID_NDK_HOST_SYSTEM_NAME "linux-x86_64" )
+ set( ANDROID_NDK_HOST_SYSTEM_NAME2 "linux-x86" )
+else()
+ message( FATAL_ERROR "Cross-compilation on your platform is not supported by this cmake toolchain" )
+endif()
+
+if( NOT ANDROID_NDK_HOST_X64 )
+ set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} )
+endif()
+
+# see if we have path to Android NDK
+if( NOT ANDROID_NDK AND NOT ANDROID_STANDALONE_TOOLCHAIN )
+  __INIT_VARIABLE( ANDROID_NDK PATH ENV_ANDROID_NDK )
+endif()
+if( NOT ANDROID_NDK )
+ # see if we have path to Android standalone toolchain
+ __INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ENV_ANDROID_STANDALONE_TOOLCHAIN )
+
+ if( NOT ANDROID_STANDALONE_TOOLCHAIN )
+  #try to find Android NDK in one of the the default locations
+  set( __ndkSearchPaths )
+  foreach( __ndkSearchPath ${ANDROID_NDK_SEARCH_PATHS} )
+   foreach( suffix ${ANDROID_SUPPORTED_NDK_VERSIONS} )
+    list( APPEND __ndkSearchPaths "${__ndkSearchPath}/android-ndk${suffix}" )
+   endforeach()
+  endforeach()
+  __INIT_VARIABLE( ANDROID_NDK PATH VALUES ${__ndkSearchPaths} )
+  unset( __ndkSearchPaths )
+
+  if( ANDROID_NDK )
+   message( STATUS "Using default path for Android NDK: ${ANDROID_NDK}" )
+   message( STATUS "  If you prefer to use a different location, please define a cmake or environment variable: ANDROID_NDK" )
+  else()
+   #try to find Android standalone toolchain in one of the the default locations
+   __INIT_VARIABLE( ANDROID_STANDALONE_TOOLCHAIN PATH ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH )
+
+   if( ANDROID_STANDALONE_TOOLCHAIN )
+    message( STATUS "Using default path for standalone toolchain ${ANDROID_STANDALONE_TOOLCHAIN}" )
+    message( STATUS "  If you prefer to use a different location, please define the variable: ANDROID_STANDALONE_TOOLCHAIN" )
+   endif( ANDROID_STANDALONE_TOOLCHAIN )
+  endif( ANDROID_NDK )
+ endif( NOT ANDROID_STANDALONE_TOOLCHAIN )
+endif( NOT ANDROID_NDK )
+
+# remember found paths
+if( ANDROID_NDK )
+ get_filename_component( ANDROID_NDK "${ANDROID_NDK}" ABSOLUTE )
+ set( ANDROID_NDK "${ANDROID_NDK}" CACHE INTERNAL "Path of the Android NDK" FORCE )
+ set( BUILD_WITH_ANDROID_NDK True )
+ if( EXISTS "${ANDROID_NDK}/RELEASE.TXT" )
+  file( STRINGS "${ANDROID_NDK}/RELEASE.TXT" ANDROID_NDK_RELEASE_FULL LIMIT_COUNT 1 REGEX "r[0-9]+[a-z]?" )
+  string( REGEX MATCH "r([0-9]+)([a-z]?)" ANDROID_NDK_RELEASE "${ANDROID_NDK_RELEASE_FULL}" )
+ else()
+  set( ANDROID_NDK_RELEASE "r1x" )
+  set( ANDROID_NDK_RELEASE_FULL "unreleased" )
+ endif()
+ string( REGEX REPLACE "r([0-9]+)([a-z]?)" "\\1*1000" ANDROID_NDK_RELEASE_NUM "${ANDROID_NDK_RELEASE}" )
+ string( FIND " abcdefghijklmnopqastuvwxyz" "${CMAKE_MATCH_2}" __ndkReleaseLetterNum )
+ math( EXPR ANDROID_NDK_RELEASE_NUM "${ANDROID_NDK_RELEASE_NUM}+${__ndkReleaseLetterNum}" )
+elseif( ANDROID_STANDALONE_TOOLCHAIN )
+ get_filename_component( ANDROID_STANDALONE_TOOLCHAIN "${ANDROID_STANDALONE_TOOLCHAIN}" ABSOLUTE )
+ # try to detect change
+ if( CMAKE_AR )
+  string( LENGTH "${ANDROID_STANDALONE_TOOLCHAIN}" __length )
+  string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidStandaloneToolchainPreviousPath )
+  if( NOT __androidStandaloneToolchainPreviousPath STREQUAL ANDROID_STANDALONE_TOOLCHAIN )
+   message( FATAL_ERROR "It is not possible to change path to the Android standalone toolchain on subsequent run." )
+  endif()
+  unset( __androidStandaloneToolchainPreviousPath )
+  unset( __length )
+ endif()
+ set( ANDROID_STANDALONE_TOOLCHAIN "${ANDROID_STANDALONE_TOOLCHAIN}" CACHE INTERNAL "Path of the Android standalone toolchain" FORCE )
+ set( BUILD_WITH_STANDALONE_TOOLCHAIN True )
+else()
+ list(GET ANDROID_NDK_SEARCH_PATHS 0 ANDROID_NDK_SEARCH_PATH)
+ message( FATAL_ERROR "Could not find neither Android NDK nor Android standalone toolchain.
+    You should either set an environment variable:
+      export ANDROID_NDK=~/my-android-ndk
+    or
+      export ANDROID_STANDALONE_TOOLCHAIN=~/my-android-toolchain
+    or put the toolchain or NDK in the default path:
+      sudo ln -s ~/my-android-ndk ${ANDROID_NDK_SEARCH_PATH}/android-ndk
+      sudo ln -s ~/my-android-toolchain ${ANDROID_STANDALONE_TOOLCHAIN_SEARCH_PATH}" )
+endif()
+
+# android NDK layout
+if( BUILD_WITH_ANDROID_NDK )
+ if( NOT DEFINED ANDROID_NDK_LAYOUT )
+  # try to automatically detect the layout
+  if( EXISTS "${ANDROID_NDK}/RELEASE.TXT")
+   set( ANDROID_NDK_LAYOUT "RELEASE" )
+  elseif( EXISTS "${ANDROID_NDK}/../../linux-x86/toolchain/" )
+   set( ANDROID_NDK_LAYOUT "LINARO" )
+  elseif( EXISTS "${ANDROID_NDK}/../../gcc/" )
+   set( ANDROID_NDK_LAYOUT "ANDROID" )
+  endif()
+ endif()
+ set( ANDROID_NDK_LAYOUT "${ANDROID_NDK_LAYOUT}" CACHE STRING "The inner layout of NDK" )
+ mark_as_advanced( ANDROID_NDK_LAYOUT )
+ if( ANDROID_NDK_LAYOUT STREQUAL "LINARO" )
+  set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) # only 32-bit at the moment
+  set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/../../${ANDROID_NDK_HOST_SYSTEM_NAME}/toolchain" )
+  set( ANDROID_NDK_TOOLCHAINS_SUBPATH  "" )
+  set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "" )
+ elseif( ANDROID_NDK_LAYOUT STREQUAL "ANDROID" )
+  set( ANDROID_NDK_HOST_SYSTEM_NAME ${ANDROID_NDK_HOST_SYSTEM_NAME2} ) # only 32-bit at the moment
+  set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/../../gcc/${ANDROID_NDK_HOST_SYSTEM_NAME}/arm" )
+  set( ANDROID_NDK_TOOLCHAINS_SUBPATH  "" )
+  set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "" )
+ else() # ANDROID_NDK_LAYOUT STREQUAL "RELEASE"
+  set( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK}/toolchains" )
+  set( ANDROID_NDK_TOOLCHAINS_SUBPATH  "/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME}" )
+  set( ANDROID_NDK_TOOLCHAINS_SUBPATH2 "/prebuilt/${ANDROID_NDK_HOST_SYSTEM_NAME2}" )
+ endif()
+ get_filename_component( ANDROID_NDK_TOOLCHAINS_PATH "${ANDROID_NDK_TOOLCHAINS_PATH}" ABSOLUTE )
+
+ # try to detect change of NDK
+ if( CMAKE_AR )
+  string( LENGTH "${ANDROID_NDK_TOOLCHAINS_PATH}" __length )
+  string( SUBSTRING "${CMAKE_AR}" 0 ${__length} __androidNdkPreviousPath )
+  if( NOT __androidNdkPreviousPath STREQUAL ANDROID_NDK_TOOLCHAINS_PATH )
+   message( FATAL_ERROR "It is not possible to change the path to the NDK on subsequent CMake run. You must remove all generated files from your build folder first.
+   " )
+  endif()
+  unset( __androidNdkPreviousPath )
+  unset( __length )
+ endif()
+endif()
+
+
+# get all the details about standalone toolchain
+if( BUILD_WITH_STANDALONE_TOOLCHAIN )
+ __DETECT_NATIVE_API_LEVEL( ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot/usr/include/android/api-level.h" )
+ set( ANDROID_STANDALONE_TOOLCHAIN_API_LEVEL ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} )
+ set( __availableToolchains "standalone" )
+ __DETECT_TOOLCHAIN_MACHINE_NAME( __availableToolchainMachines "${ANDROID_STANDALONE_TOOLCHAIN}" )
+ if( NOT __availableToolchainMachines )
+  message( FATAL_ERROR "Could not determine machine name of your toolchain. Probably your Android standalone toolchain is broken." )
+ endif()
+ if( __availableToolchainMachines MATCHES x86_64 )
+  set( __availableToolchainArchs "x86_64" )
+ elseif( __availableToolchainMachines MATCHES i686 )
+  set( __availableToolchainArchs "x86" )
+ elseif( __availableToolchainMachines MATCHES aarch64 )
+  set( __availableToolchainArchs "arm64" )
+ elseif( __availableToolchainMachines MATCHES arm )
+  set( __availableToolchainArchs "arm" )
+ elseif( __availableToolchainMachines MATCHES mips64el )
+  set( __availableToolchainArchs "mips64" )
+ elseif( __availableToolchainMachines MATCHES mipsel )
+  set( __availableToolchainArchs "mips" )
+ endif()
+ execute_process( COMMAND "${ANDROID_STANDALONE_TOOLCHAIN}/bin/${__availableToolchainMachines}-gcc${TOOL_OS_SUFFIX}" -dumpversion
+                  OUTPUT_VARIABLE __availableToolchainCompilerVersions OUTPUT_STRIP_TRAILING_WHITESPACE )
+ string( REGEX MATCH "[0-9]+[.][0-9]+([.][0-9]+)?" __availableToolchainCompilerVersions "${__availableToolchainCompilerVersions}" )
+ if( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/bin/clang${TOOL_OS_SUFFIX}" )
+  list( APPEND __availableToolchains "standalone-clang" )
+  list( APPEND __availableToolchainMachines ${__availableToolchainMachines} )
+  list( APPEND __availableToolchainArchs ${__availableToolchainArchs} )
+  list( APPEND __availableToolchainCompilerVersions ${__availableToolchainCompilerVersions} )
+ endif()
+endif()
+
+macro( __GLOB_NDK_TOOLCHAINS __availableToolchainsVar __availableToolchainsLst __toolchain_subpath )
+ foreach( __toolchain ${${__availableToolchainsLst}} )
+  if( "${__toolchain}" MATCHES "-clang3[.][0-9]$" AND NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${__toolchain}${__toolchain_subpath}" )
+   SET( __toolchainVersionRegex "^TOOLCHAIN_VERSION[\t ]+:=[\t ]+(.*)$" )
+   FILE( STRINGS "${ANDROID_NDK_TOOLCHAINS_PATH}/${__toolchain}/setup.mk" __toolchainVersionStr REGEX "${__toolchainVersionRegex}" )
+   if( __toolchainVersionStr )
+    string( REGEX REPLACE "${__toolchainVersionRegex}" "\\1" __toolchainVersionStr "${__toolchainVersionStr}" )
+    string( REGEX REPLACE "-clang3[.][0-9]$" "-${__toolchainVersionStr}" __gcc_toolchain "${__toolchain}" )
+   else()
+    string( REGEX REPLACE "-clang3[.][0-9]$" "-4.6" __gcc_toolchain "${__toolchain}" )
+   endif()
+   unset( __toolchainVersionStr )
+   unset( __toolchainVersionRegex )
+  else()
+   set( __gcc_toolchain "${__toolchain}" )
+  endif()
+  __DETECT_TOOLCHAIN_MACHINE_NAME( __machine "${ANDROID_NDK_TOOLCHAINS_PATH}/${__gcc_toolchain}${__toolchain_subpath}" )
+  if( __machine )
+   string( REGEX MATCH "[0-9]+[.][0-9]+([.][0-9x]+)?$" __version "${__gcc_toolchain}" )
+   if( __machine MATCHES x86_64 )
+    set( __arch "x86_64" )
+   elseif( __machine MATCHES i686 )
+    set( __arch "x86" )
+   elseif( __machine MATCHES aarch64 )
+    set( __arch "arm64" )
+   elseif( __machine MATCHES arm )
+    set( __arch "arm" )
+   elseif( __machine MATCHES mips64el )
+    set( __arch "mips64" )
+   elseif( __machine MATCHES mipsel )
+    set( __arch "mips" )
+   else()
+    set( __arch "" )
+   endif()
+   #message("machine: !${__machine}!\narch: !${__arch}!\nversion: !${__version}!\ntoolchain: !${__toolchain}!\n")
+   if (__arch)
+    list( APPEND __availableToolchainMachines "${__machine}" )
+    list( APPEND __availableToolchainArchs "${__arch}" )
+    list( APPEND __availableToolchainCompilerVersions "${__version}" )
+    list( APPEND ${__availableToolchainsVar} "${__toolchain}" )
+   endif()
+  endif()
+  unset( __gcc_toolchain )
+ endforeach()
+endmacro()
+
+# get all the details about NDK
+if( BUILD_WITH_ANDROID_NDK )
+ file( GLOB ANDROID_SUPPORTED_NATIVE_API_LEVELS RELATIVE "${ANDROID_NDK}/platforms" "${ANDROID_NDK}/platforms/android-*" )
+ string( REPLACE "android-" "" ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_SUPPORTED_NATIVE_API_LEVELS}" )
+ set( __availableToolchains "" )
+ set( __availableToolchainMachines "" )
+ set( __availableToolchainArchs "" )
+ set( __availableToolchainCompilerVersions "" )
+ if( ANDROID_TOOLCHAIN_NAME AND EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_TOOLCHAIN_NAME}/" )
+  # do not go through all toolchains if we know the name
+  set( __availableToolchainsLst "${ANDROID_TOOLCHAIN_NAME}" )
+  __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH}" )
+  if( NOT __availableToolchains AND NOT ANDROID_NDK_TOOLCHAINS_SUBPATH STREQUAL ANDROID_NDK_TOOLCHAINS_SUBPATH2 )
+   __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH2}" )
+   if( __availableToolchains )
+    set( ANDROID_NDK_TOOLCHAINS_SUBPATH ${ANDROID_NDK_TOOLCHAINS_SUBPATH2} )
+   endif()
+  endif()
+ endif()
+ if( NOT __availableToolchains )
+  file( GLOB __availableToolchainsLst RELATIVE "${ANDROID_NDK_TOOLCHAINS_PATH}" "${ANDROID_NDK_TOOLCHAINS_PATH}/*" )
+  if( __availableToolchainsLst )
+   list(SORT __availableToolchainsLst) # we need clang to go after gcc
+  endif()
+  __LIST_FILTER( __availableToolchainsLst "^[.]" )
+  __LIST_FILTER( __availableToolchainsLst "llvm" )
+  __LIST_FILTER( __availableToolchainsLst "renderscript" )
+  __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH}" )
+  if( NOT __availableToolchains AND NOT ANDROID_NDK_TOOLCHAINS_SUBPATH STREQUAL ANDROID_NDK_TOOLCHAINS_SUBPATH2 )
+   __GLOB_NDK_TOOLCHAINS( __availableToolchains __availableToolchainsLst "${ANDROID_NDK_TOOLCHAINS_SUBPATH2}" )
+   if( __availableToolchains )
+    set( ANDROID_NDK_TOOLCHAINS_SUBPATH ${ANDROID_NDK_TOOLCHAINS_SUBPATH2} )
+   endif()
+  endif()
+ endif()
+ if( NOT __availableToolchains )
+  message( FATAL_ERROR "Could not find any working toolchain in the NDK. Probably your Android NDK is broken." )
+ endif()
+endif()
+
+# build list of available ABIs
+set( ANDROID_SUPPORTED_ABIS "" )
+set( __uniqToolchainArchNames ${__availableToolchainArchs} )
+list( REMOVE_DUPLICATES __uniqToolchainArchNames )
+list( SORT __uniqToolchainArchNames )
+foreach( __arch ${__uniqToolchainArchNames} )
+ list( APPEND ANDROID_SUPPORTED_ABIS ${ANDROID_SUPPORTED_ABIS_${__arch}} )
+endforeach()
+unset( __uniqToolchainArchNames )
+if( NOT ANDROID_SUPPORTED_ABIS )
+ message( FATAL_ERROR "No one of known Android ABIs is supported by this cmake toolchain." )
+endif()
+
+# choose target ABI
+__INIT_VARIABLE( ANDROID_ABI VALUES ${ANDROID_SUPPORTED_ABIS} )
+# verify that target ABI is supported
+list( FIND ANDROID_SUPPORTED_ABIS "${ANDROID_ABI}" __androidAbiIdx )
+if( __androidAbiIdx EQUAL -1 )
+ string( REPLACE ";" "\", \"" PRINTABLE_ANDROID_SUPPORTED_ABIS  "${ANDROID_SUPPORTED_ABIS}" )
+ message( FATAL_ERROR "Specified ANDROID_ABI = \"${ANDROID_ABI}\" is not supported by this cmake toolchain or your NDK/toolchain.
+   Supported values are: \"${PRINTABLE_ANDROID_SUPPORTED_ABIS}\"
+   " )
+endif()
+unset( __androidAbiIdx )
+
+# set target ABI options
+if( ANDROID_ABI STREQUAL "x86" )
+ set( X86 true )
+ set( ANDROID_NDK_ABI_NAME "x86" )
+ set( ANDROID_ARCH_NAME "x86" )
+ set( ANDROID_LLVM_TRIPLE "i686-none-linux-android" )
+ set( CMAKE_SYSTEM_PROCESSOR "i686" )
+elseif( ANDROID_ABI STREQUAL "x86_64" )
+ set( X86 true )
+ set( X86_64 true )
+ set( ANDROID_NDK_ABI_NAME "x86_64" )
+ set( ANDROID_ARCH_NAME "x86_64" )
+ set( CMAKE_SYSTEM_PROCESSOR "x86_64" )
+ set( ANDROID_LLVM_TRIPLE "x86_64-none-linux-android" )
+elseif( ANDROID_ABI STREQUAL "mips64" )
+ set( MIPS64 true )
+ set( ANDROID_NDK_ABI_NAME "mips64" )
+ set( ANDROID_ARCH_NAME "mips64" )
+ set( ANDROID_LLVM_TRIPLE "mips64el-none-linux-android" )
+ set( CMAKE_SYSTEM_PROCESSOR "mips64" )
+elseif( ANDROID_ABI STREQUAL "mips" )
+ set( MIPS true )
+ set( ANDROID_NDK_ABI_NAME "mips" )
+ set( ANDROID_ARCH_NAME "mips" )
+ set( ANDROID_LLVM_TRIPLE "mipsel-none-linux-android" )
+ set( CMAKE_SYSTEM_PROCESSOR "mips" )
+elseif( ANDROID_ABI STREQUAL "arm64-v8a" )
+ set( ARM64_V8A true )
+ set( ANDROID_NDK_ABI_NAME "arm64-v8a" )
+ set( ANDROID_ARCH_NAME "arm64" )
+ set( ANDROID_LLVM_TRIPLE "aarch64-none-linux-android" )
+ set( CMAKE_SYSTEM_PROCESSOR "aarch64" )
+ set( VFPV3 true )
+ set( NEON true )
+elseif( ANDROID_ABI STREQUAL "armeabi" )
+ set( ARMEABI true )
+ set( ANDROID_NDK_ABI_NAME "armeabi" )
+ set( ANDROID_ARCH_NAME "arm" )
+ set( ANDROID_LLVM_TRIPLE "armv5te-none-linux-androideabi" )
+ set( CMAKE_SYSTEM_PROCESSOR "armv5te" )
+elseif( ANDROID_ABI STREQUAL "armeabi-v6 with VFP" )
+ set( ARMEABI_V6 true )
+ set( ANDROID_NDK_ABI_NAME "armeabi" )
+ set( ANDROID_ARCH_NAME "arm" )
+ set( ANDROID_LLVM_TRIPLE "armv5te-none-linux-androideabi" )
+ set( CMAKE_SYSTEM_PROCESSOR "armv6" )
+ # need always fallback to older platform
+ set( ARMEABI true )
+elseif( ANDROID_ABI STREQUAL "armeabi-v7a")
+ set( ARMEABI_V7A true )
+ set( ANDROID_NDK_ABI_NAME "armeabi-v7a" )
+ set( ANDROID_ARCH_NAME "arm" )
+ set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" )
+ set( CMAKE_SYSTEM_PROCESSOR "armv7-a" )
+elseif( ANDROID_ABI STREQUAL "armeabi-v7a with VFPV3" )
+ set( ARMEABI_V7A true )
+ set( ANDROID_NDK_ABI_NAME "armeabi-v7a" )
+ set( ANDROID_ARCH_NAME "arm" )
+ set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" )
+ set( CMAKE_SYSTEM_PROCESSOR "armv7-a" )
+ set( VFPV3 true )
+elseif( ANDROID_ABI STREQUAL "armeabi-v7a with NEON" )
+ set( ARMEABI_V7A true )
+ set( ANDROID_NDK_ABI_NAME "armeabi-v7a" )
+ set( ANDROID_ARCH_NAME "arm" )
+ set( ANDROID_LLVM_TRIPLE "armv7-none-linux-androideabi" )
+ set( CMAKE_SYSTEM_PROCESSOR "armv7-a" )
+ set( VFPV3 true )
+ set( NEON true )
+else()
+ message( SEND_ERROR "Unknown ANDROID_ABI=\"${ANDROID_ABI}\" is specified." )
+endif()
+
+if( CMAKE_BINARY_DIR AND EXISTS "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeSystem.cmake" )
+ # really dirty hack
+ # it is not possible to change CMAKE_SYSTEM_PROCESSOR after the first run...
+ file( APPEND "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeSystem.cmake" "SET(CMAKE_SYSTEM_PROCESSOR \"${CMAKE_SYSTEM_PROCESSOR}\")\n" )
+endif()
+
+if( ANDROID_ARCH_NAME STREQUAL "arm" AND NOT ARMEABI_V6 )
+ __INIT_VARIABLE( ANDROID_FORCE_ARM_BUILD VALUES OFF )
+ set( ANDROID_FORCE_ARM_BUILD ${ANDROID_FORCE_ARM_BUILD} CACHE BOOL "Use 32-bit ARM instructions instead of Thumb-1" FORCE )
+ mark_as_advanced( ANDROID_FORCE_ARM_BUILD )
+else()
+ unset( ANDROID_FORCE_ARM_BUILD CACHE )
+endif()
+
+# choose toolchain
+if( ANDROID_TOOLCHAIN_NAME )
+ list( FIND __availableToolchains "${ANDROID_TOOLCHAIN_NAME}" __toolchainIdx )
+ if( __toolchainIdx EQUAL -1 )
+  list( SORT __availableToolchains )
+  string( REPLACE ";" "\n  * " toolchains_list "${__availableToolchains}" )
+  set( toolchains_list "  * ${toolchains_list}")
+  message( FATAL_ERROR "Specified toolchain \"${ANDROID_TOOLCHAIN_NAME}\" is missing in your NDK or broken. Please verify that your NDK is working or select another compiler toolchain.
+To configure the toolchain set CMake variable ANDROID_TOOLCHAIN_NAME to one of the following values:\n${toolchains_list}\n" )
+ endif()
+ list( GET __availableToolchainArchs ${__toolchainIdx} __toolchainArch )
+ if( NOT __toolchainArch STREQUAL ANDROID_ARCH_NAME )
+  message( SEND_ERROR "Selected toolchain \"${ANDROID_TOOLCHAIN_NAME}\" is not able to compile binaries for the \"${ANDROID_ARCH_NAME}\" platform." )
+ endif()
+else()
+ set( __toolchainIdx -1 )
+ set( __applicableToolchains "" )
+ set( __toolchainMaxVersion "0.0.0" )
+ list( LENGTH __availableToolchains __availableToolchainsCount )
+ math( EXPR __availableToolchainsCount "${__availableToolchainsCount}-1" )
+ foreach( __idx RANGE ${__availableToolchainsCount} )
+  list( GET __availableToolchainArchs ${__idx} __toolchainArch )
+  if( __toolchainArch STREQUAL ANDROID_ARCH_NAME )
+   list( GET __availableToolchainCompilerVersions ${__idx} __toolchainVersion )
+   string( REPLACE "x" "99" __toolchainVersion "${__toolchainVersion}")
+   if( __toolchainVersion VERSION_GREATER __toolchainMaxVersion )
+    set( __toolchainMaxVersion "${__toolchainVersion}" )
+    set( __toolchainIdx ${__idx} )
+   endif()
+  endif()
+ endforeach()
+ unset( __availableToolchainsCount )
+ unset( __toolchainMaxVersion )
+ unset( __toolchainVersion )
+endif()
+unset( __toolchainArch )
+if( __toolchainIdx EQUAL -1 )
+ message( FATAL_ERROR "No one of available compiler toolchains is able to compile for ${ANDROID_ARCH_NAME} platform." )
+endif()
+list( GET __availableToolchains ${__toolchainIdx} ANDROID_TOOLCHAIN_NAME )
+list( GET __availableToolchainMachines ${__toolchainIdx} ANDROID_TOOLCHAIN_MACHINE_NAME )
+list( GET __availableToolchainCompilerVersions ${__toolchainIdx} ANDROID_COMPILER_VERSION )
+
+unset( __toolchainIdx )
+unset( __availableToolchains )
+unset( __availableToolchainMachines )
+unset( __availableToolchainArchs )
+unset( __availableToolchainCompilerVersions )
+
+# choose native API level
+__INIT_VARIABLE( ANDROID_NATIVE_API_LEVEL ENV_ANDROID_NATIVE_API_LEVEL ANDROID_API_LEVEL ENV_ANDROID_API_LEVEL ANDROID_STANDALONE_TOOLCHAIN_API_LEVEL ANDROID_DEFAULT_NDK_API_LEVEL_${ANDROID_ARCH_NAME} ANDROID_DEFAULT_NDK_API_LEVEL )
+string( REPLACE "android-" "" ANDROID_NATIVE_API_LEVEL "${ANDROID_NATIVE_API_LEVEL}" )
+string( STRIP "${ANDROID_NATIVE_API_LEVEL}" ANDROID_NATIVE_API_LEVEL )
+# adjust API level
+set( __real_api_level ${ANDROID_DEFAULT_NDK_API_LEVEL_${ANDROID_ARCH_NAME}} )
+foreach( __level ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} )
+ if( (__level LESS ANDROID_NATIVE_API_LEVEL OR __level STREQUAL ANDROID_NATIVE_API_LEVEL) AND NOT __level LESS __real_api_level )
+  set( __real_api_level ${__level} )
+ endif()
+endforeach()
+if( __real_api_level AND NOT ANDROID_NATIVE_API_LEVEL STREQUAL __real_api_level )
+ message( STATUS "Adjusting Android API level 'android-${ANDROID_NATIVE_API_LEVEL}' to 'android-${__real_api_level}'")
+ set( ANDROID_NATIVE_API_LEVEL ${__real_api_level} )
+endif()
+unset(__real_api_level)
+# validate
+list( FIND ANDROID_SUPPORTED_NATIVE_API_LEVELS "${ANDROID_NATIVE_API_LEVEL}" __levelIdx )
+if( __levelIdx EQUAL -1 )
+ message( SEND_ERROR "Specified Android native API level 'android-${ANDROID_NATIVE_API_LEVEL}' is not supported by your NDK/toolchain." )
+else()
+ if( BUILD_WITH_ANDROID_NDK )
+  __DETECT_NATIVE_API_LEVEL( __realApiLevel "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}/usr/include/android/api-level.h" )
+  if( NOT __realApiLevel EQUAL ANDROID_NATIVE_API_LEVEL AND NOT __realApiLevel GREATER 9000 )
+   message( SEND_ERROR "Specified Android API level (${ANDROID_NATIVE_API_LEVEL}) does not match to the level found (${__realApiLevel}). Probably your copy of NDK is broken." )
+  endif()
+  unset( __realApiLevel )
+ endif()
+ set( ANDROID_NATIVE_API_LEVEL "${ANDROID_NATIVE_API_LEVEL}" CACHE STRING "Android API level for native code" FORCE )
+ set( CMAKE_ANDROID_API ${ANDROID_NATIVE_API_LEVEL} )
+ if( CMAKE_VERSION VERSION_GREATER "2.8" )
+  list( SORT ANDROID_SUPPORTED_NATIVE_API_LEVELS )
+  set_property( CACHE ANDROID_NATIVE_API_LEVEL PROPERTY STRINGS ${ANDROID_SUPPORTED_NATIVE_API_LEVELS} )
+ endif()
+endif()
+unset( __levelIdx )
+
+
+# remember target ABI
+set( ANDROID_ABI "${ANDROID_ABI}" CACHE STRING "The target ABI for Android. If arm, then armeabi-v7a is recommended for hardware floating point." FORCE )
+if( CMAKE_VERSION VERSION_GREATER "2.8" )
+ list( SORT ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_NAME} )
+ set_property( CACHE ANDROID_ABI PROPERTY STRINGS ${ANDROID_SUPPORTED_ABIS_${ANDROID_ARCH_NAME}} )
+endif()
+
+
+# runtime choice (STL, rtti, exceptions)
+if( NOT ANDROID_STL )
+  set( ANDROID_STL gnustl_static )
+endif()
+set( ANDROID_STL "${ANDROID_STL}" CACHE STRING "C++ runtime" )
+set( ANDROID_STL_FORCE_FEATURES ON CACHE BOOL "automatically configure rtti and exceptions support based on C++ runtime" )
+mark_as_advanced( ANDROID_STL ANDROID_STL_FORCE_FEATURES )
+
+if( BUILD_WITH_ANDROID_NDK )
+ if( NOT "${ANDROID_STL}" MATCHES "^(none|system|system_re|gabi\\+\\+_static|gabi\\+\\+_shared|stlport_static|stlport_shared|gnustl_static|gnustl_shared)$")
+  message( FATAL_ERROR "ANDROID_STL is set to invalid value \"${ANDROID_STL}\".
+The possible values are:
+  none           -> Do not configure the runtime.
+  system         -> Use the default minimal system C++ runtime library.
+  system_re      -> Same as system but with rtti and exceptions.
+  gabi++_static  -> Use the GAbi++ runtime as a static library.
+  gabi++_shared  -> Use the GAbi++ runtime as a shared library.
+  stlport_static -> Use the STLport runtime as a static library.
+  stlport_shared -> Use the STLport runtime as a shared library.
+  gnustl_static  -> (default) Use the GNU STL as a static library.
+  gnustl_shared  -> Use the GNU STL as a shared library.
+" )
+ endif()
+elseif( BUILD_WITH_STANDALONE_TOOLCHAIN )
+ if( NOT "${ANDROID_STL}" MATCHES "^(none|gnustl_static|gnustl_shared)$")
+  message( FATAL_ERROR "ANDROID_STL is set to invalid value \"${ANDROID_STL}\".
+The possible values are:
+  none           -> Do not configure the runtime.
+  gnustl_static  -> (default) Use the GNU STL as a static library.
+  gnustl_shared  -> Use the GNU STL as a shared library.
+" )
+ endif()
+endif()
+
+unset( ANDROID_RTTI )
+unset( ANDROID_EXCEPTIONS )
+unset( ANDROID_STL_INCLUDE_DIRS )
+unset( __libstl )
+unset( __libsupcxx )
+
+if( NOT _CMAKE_IN_TRY_COMPILE AND ANDROID_NDK_RELEASE STREQUAL "r7b" AND ARMEABI_V7A AND NOT VFPV3 AND ANDROID_STL MATCHES "gnustl" )
+ message( WARNING  "The GNU STL armeabi-v7a binaries from NDK r7b can crash non-NEON devices. The files provided with NDK r7b were not configured properly, resulting in crashes on Tegra2-based devices and others when trying to use certain floating-point functions (e.g., cosf, sinf, expf).
+You are strongly recommended to switch to another NDK release.
+" )
+endif()
+
+if( NOT _CMAKE_IN_TRY_COMPILE AND X86 AND ANDROID_STL MATCHES "gnustl" AND ANDROID_NDK_RELEASE STREQUAL "r6" )
+  message( WARNING  "The x86 system header file from NDK r6 has incorrect definition for ptrdiff_t. You are recommended to upgrade to a newer NDK release or manually patch the header:
+See https://android.googlesource.com/platform/development.git f907f4f9d4e56ccc8093df6fee54454b8bcab6c2
+  diff --git a/ndk/platforms/android-9/arch-x86/include/machine/_types.h b/ndk/platforms/android-9/arch-x86/include/machine/_types.h
+  index 5e28c64..65892a1 100644
+  --- a/ndk/platforms/android-9/arch-x86/include/machine/_types.h
+  +++ b/ndk/platforms/android-9/arch-x86/include/machine/_types.h
+  @@ -51,7 +51,11 @@ typedef long int       ssize_t;
+   #endif
+   #ifndef _PTRDIFF_T
+   #define _PTRDIFF_T
+  -typedef long           ptrdiff_t;
+  +#  ifdef __ANDROID__
+  +     typedef int            ptrdiff_t;
+  +#  else
+  +     typedef long           ptrdiff_t;
+  +#  endif
+   #endif
+" )
+endif()
+
+
+# setup paths and STL for standalone toolchain
+if( BUILD_WITH_STANDALONE_TOOLCHAIN )
+ set( ANDROID_TOOLCHAIN_ROOT "${ANDROID_STANDALONE_TOOLCHAIN}" )
+ set( ANDROID_CLANG_TOOLCHAIN_ROOT "${ANDROID_STANDALONE_TOOLCHAIN}" )
+ set( ANDROID_SYSROOT "${ANDROID_STANDALONE_TOOLCHAIN}/sysroot" )
+
+ if( NOT ANDROID_STL STREQUAL "none" )
+  set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_STANDALONE_TOOLCHAIN}/include/c++/${ANDROID_COMPILER_VERSION}" )
+  if( NOT EXISTS "${ANDROID_STL_INCLUDE_DIRS}" )
+   # old location ( pre r8c )
+   set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/include/c++/${ANDROID_COMPILER_VERSION}" )
+  endif()
+  if( ARMEABI_V7A AND EXISTS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}/bits" )
+   list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/${CMAKE_SYSTEM_PROCESSOR}" )
+  elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/thumb/bits" )
+   list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/thumb" )
+  else()
+   list( APPEND ANDROID_STL_INCLUDE_DIRS "${ANDROID_STL_INCLUDE_DIRS}/${ANDROID_TOOLCHAIN_MACHINE_NAME}" )
+  endif()
+  # always search static GNU STL to get the location of libsupc++.a
+  if( ARMEABI_V7A AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb/libstdc++.a" )
+   set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb" )
+  elseif( ARMEABI_V7A AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libstdc++.a" )
+   set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}" )
+  elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libstdc++.a" )
+   set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb" )
+  elseif( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libstdc++.a" )
+   set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib" )
+  endif()
+  if( __libstl )
+   set( __libsupcxx "${__libstl}/libsupc++.a" )
+   set( __libstl    "${__libstl}/libstdc++.a" )
+  endif()
+  if( NOT EXISTS "${__libsupcxx}" )
+   message( FATAL_ERROR "The required libstdsupc++.a is missing in your standalone toolchain.
+ Usually it happens because of bug in make-standalone-toolchain.sh script from NDK r7, r7b and r7c.
+ You need to either upgrade to newer NDK or manually copy
+     $ANDROID_NDK/sources/cxx-stl/gnu-libstdc++/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a
+ to
+     ${__libsupcxx}
+   " )
+  endif()
+  if( ANDROID_STL STREQUAL "gnustl_shared" )
+   if( ARMEABI_V7A AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libgnustl_shared.so" )
+    set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libgnustl_shared.so" )
+   elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD AND EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libgnustl_shared.so" )
+    set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libgnustl_shared.so" )
+   elseif( EXISTS "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libgnustl_shared.so" )
+    set( __libstl "${ANDROID_STANDALONE_TOOLCHAIN}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libgnustl_shared.so" )
+   endif()
+  endif()
+ endif()
+endif()
+
+# clang
+if( "${ANDROID_TOOLCHAIN_NAME}" STREQUAL "standalone-clang" )
+ set( ANDROID_COMPILER_IS_CLANG 1 )
+ execute_process( COMMAND "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/clang${TOOL_OS_SUFFIX}" --version OUTPUT_VARIABLE ANDROID_CLANG_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE )
+ string( REGEX MATCH "[0-9]+[.][0-9]+" ANDROID_CLANG_VERSION "${ANDROID_CLANG_VERSION}")
+elseif( "${ANDROID_TOOLCHAIN_NAME}" MATCHES "-clang3[.][0-9]?$" )
+ string( REGEX MATCH "3[.][0-9]$" ANDROID_CLANG_VERSION "${ANDROID_TOOLCHAIN_NAME}")
+ string( REGEX REPLACE "-clang${ANDROID_CLANG_VERSION}$" "-${ANDROID_COMPILER_VERSION}" ANDROID_GCC_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" )
+ if( NOT EXISTS "${ANDROID_NDK_TOOLCHAINS_PATH}/llvm-${ANDROID_CLANG_VERSION}${ANDROID_NDK_TOOLCHAINS_SUBPATH}/bin/clang${TOOL_OS_SUFFIX}" )
+  message( FATAL_ERROR "Could not find the Clang compiler driver" )
+ endif()
+ set( ANDROID_COMPILER_IS_CLANG 1 )
+ set( ANDROID_CLANG_TOOLCHAIN_ROOT "${ANDROID_NDK_TOOLCHAINS_PATH}/llvm-${ANDROID_CLANG_VERSION}${ANDROID_NDK_TOOLCHAINS_SUBPATH}" )
+else()
+ set( ANDROID_GCC_TOOLCHAIN_NAME "${ANDROID_TOOLCHAIN_NAME}" )
+ unset( ANDROID_COMPILER_IS_CLANG CACHE )
+endif()
+
+string( REPLACE "." "" _clang_name "clang${ANDROID_CLANG_VERSION}" )
+if( NOT EXISTS "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}" )
+ set( _clang_name "clang" )
+endif()
+
+
+# setup paths and STL for NDK
+if( BUILD_WITH_ANDROID_NDK )
+ set( ANDROID_TOOLCHAIN_ROOT "${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}${ANDROID_NDK_TOOLCHAINS_SUBPATH}" )
+ set( ANDROID_SYSROOT "${ANDROID_NDK}/platforms/android-${ANDROID_NATIVE_API_LEVEL}/arch-${ANDROID_ARCH_NAME}" )
+
+ if( ANDROID_STL STREQUAL "none" )
+  # do nothing
+ elseif( ANDROID_STL STREQUAL "system" )
+  set( ANDROID_RTTI             OFF )
+  set( ANDROID_EXCEPTIONS       OFF )
+  set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/system/include" )
+ elseif( ANDROID_STL STREQUAL "system_re" )
+  set( ANDROID_RTTI             ON )
+  set( ANDROID_EXCEPTIONS       ON )
+  set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/system/include" )
+ elseif( ANDROID_STL MATCHES "gabi" )
+  if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7
+   message( FATAL_ERROR "gabi++ is not available in your NDK. You have to upgrade to NDK r7 or newer to use gabi++.")
+  endif()
+  set( ANDROID_RTTI             ON )
+  set( ANDROID_EXCEPTIONS       OFF )
+  set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/gabi++/include" )
+  set( __libstl                 "${ANDROID_NDK}/sources/cxx-stl/gabi++/libs/${ANDROID_NDK_ABI_NAME}/libgabi++_static.a" )
+ elseif( ANDROID_STL MATCHES "stlport" )
+  if( NOT ANDROID_NDK_RELEASE_NUM LESS 8004 ) # before r8d
+   set( ANDROID_EXCEPTIONS       ON )
+  else()
+   set( ANDROID_EXCEPTIONS       OFF )
+  endif()
+  if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7
+   set( ANDROID_RTTI            OFF )
+  else()
+   set( ANDROID_RTTI            ON )
+  endif()
+  set( ANDROID_STL_INCLUDE_DIRS "${ANDROID_NDK}/sources/cxx-stl/stlport/stlport" )
+  set( __libstl                 "${ANDROID_NDK}/sources/cxx-stl/stlport/libs/${ANDROID_NDK_ABI_NAME}/libstlport_static.a" )
+ elseif( ANDROID_STL MATCHES "gnustl" )
+  set( ANDROID_EXCEPTIONS       ON )
+  set( ANDROID_RTTI             ON )
+  if( EXISTS "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" )
+   if( ARMEABI_V7A AND ANDROID_COMPILER_VERSION VERSION_EQUAL "4.7" AND ANDROID_NDK_RELEASE STREQUAL "r8d" )
+    # gnustl binary for 4.7 compiler is buggy :(
+    # TODO: look for right fix
+    set( __libstl                "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/4.6" )
+   else()
+    set( __libstl                "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}" )
+   endif()
+  else()
+   set( __libstl                "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++" )
+  endif()
+  set( ANDROID_STL_INCLUDE_DIRS "${__libstl}/include" "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/include" "${__libstl}/include/backward" )
+  if( EXISTS "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libgnustl_static.a" )
+   set( __libstl                "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libgnustl_static.a" )
+  else()
+   set( __libstl                "${__libstl}/libs/${ANDROID_NDK_ABI_NAME}/libstdc++.a" )
+  endif()
+ else()
+  message( FATAL_ERROR "Unknown runtime: ${ANDROID_STL}" )
+ endif()
+ # find libsupc++.a - rtti & exceptions
+ if( ANDROID_STL STREQUAL "system_re" OR ANDROID_STL MATCHES "gnustl" )
+  set( __libsupcxx "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/${ANDROID_COMPILER_VERSION}/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" ) # r8b or newer
+  if( NOT EXISTS "${__libsupcxx}" )
+   set( __libsupcxx "${ANDROID_NDK}/sources/cxx-stl/gnu-libstdc++/libs/${ANDROID_NDK_ABI_NAME}/libsupc++.a" ) # r7-r8
+  endif()
+  if( NOT EXISTS "${__libsupcxx}" ) # before r7
+   if( ARMEABI_V7A )
+    if( ANDROID_FORCE_ARM_BUILD )
+     set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/libsupc++.a" )
+    else()
+     set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/${CMAKE_SYSTEM_PROCESSOR}/thumb/libsupc++.a" )
+    endif()
+   elseif( ARMEABI AND NOT ANDROID_FORCE_ARM_BUILD )
+    set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/thumb/libsupc++.a" )
+   else()
+    set( __libsupcxx "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}/lib/libsupc++.a" )
+   endif()
+  endif()
+  if( NOT EXISTS "${__libsupcxx}")
+   message( ERROR "Could not find libsupc++.a for a chosen platform. Either your NDK is not supported or is broken.")
+  endif()
+ endif()
+endif()
+
+
+# case of shared STL linkage
+if( ANDROID_STL MATCHES "shared" AND DEFINED __libstl )
+ string( REPLACE "_static.a" "_shared.so" __libstl "${__libstl}" )
+ # TODO: check if .so file exists before the renaming
+endif()
+
+
+# ccache support
+__INIT_VARIABLE( _ndk_ccache NDK_CCACHE ENV_NDK_CCACHE )
+if( _ndk_ccache )
+ if( DEFINED NDK_CCACHE AND NOT EXISTS NDK_CCACHE )
+  unset( NDK_CCACHE CACHE )
+ endif()
+ find_program( NDK_CCACHE "${_ndk_ccache}" DOC "The path to ccache binary")
+else()
+ unset( NDK_CCACHE CACHE )
+endif()
+unset( _ndk_ccache )
+
+
+# setup the cross-compiler
+if( NOT CMAKE_C_COMPILER )
+ if( NDK_CCACHE AND NOT ANDROID_SYSROOT MATCHES "[ ;\"]" )
+  set( CMAKE_C_COMPILER   "${NDK_CCACHE}" CACHE PATH "ccache as C compiler" )
+  set( CMAKE_CXX_COMPILER "${NDK_CCACHE}" CACHE PATH "ccache as C++ compiler" )
+  if( ANDROID_COMPILER_IS_CLANG )
+   set( CMAKE_C_COMPILER_ARG1   "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}"   CACHE PATH "C compiler")
+   set( CMAKE_CXX_COMPILER_ARG1 "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler")
+  else()
+   set( CMAKE_C_COMPILER_ARG1   "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}" CACHE PATH "C compiler")
+   set( CMAKE_CXX_COMPILER_ARG1 "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-g++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler")
+  endif()
+ else()
+  if( ANDROID_COMPILER_IS_CLANG )
+   set( CMAKE_C_COMPILER   "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}${TOOL_OS_SUFFIX}"   CACHE PATH "C compiler")
+   set( CMAKE_CXX_COMPILER "${ANDROID_CLANG_TOOLCHAIN_ROOT}/bin/${_clang_name}++${TOOL_OS_SUFFIX}" CACHE PATH "C++ compiler")
+  else()
+   set( CMAKE_C_COMPILER   "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}"    CACHE PATH "C compiler" )
+   set( CMAKE_CXX_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-g++${TOOL_OS_SUFFIX}"    CACHE PATH "C++ compiler" )
+  endif()
+ endif()
+ set( CMAKE_ASM_COMPILER "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc${TOOL_OS_SUFFIX}"     CACHE PATH "assembler" )
+ set( CMAKE_STRIP        "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-strip${TOOL_OS_SUFFIX}"   CACHE PATH "strip" )
+ if( EXISTS "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc-ar${TOOL_OS_SUFFIX}" )
+  # Use gcc-ar if we have it for better LTO support.
+  set( CMAKE_AR           "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-gcc-ar${TOOL_OS_SUFFIX}"      CACHE PATH "archive" )
+ else()
+  set( CMAKE_AR           "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ar${TOOL_OS_SUFFIX}"      CACHE PATH "archive" )
+ endif()
+ set( CMAKE_LINKER       "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ld${TOOL_OS_SUFFIX}"      CACHE PATH "linker" )
+ set( CMAKE_NM           "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-nm${TOOL_OS_SUFFIX}"      CACHE PATH "nm" )
+ set( CMAKE_OBJCOPY      "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objcopy${TOOL_OS_SUFFIX}" CACHE PATH "objcopy" )
+ set( CMAKE_OBJDUMP      "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-objdump${TOOL_OS_SUFFIX}" CACHE PATH "objdump" )
+ set( CMAKE_RANLIB       "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_MACHINE_NAME}-ranlib${TOOL_OS_SUFFIX}"  CACHE PATH "ranlib" )
+endif()
+
+set( _CMAKE_TOOLCHAIN_PREFIX "${ANDROID_TOOLCHAIN_MACHINE_NAME}-" )
+if( CMAKE_VERSION VERSION_LESS 2.8.5 )
+ set( CMAKE_ASM_COMPILER_ARG1 "-c" )
+endif()
+if( APPLE )
+ find_program( CMAKE_INSTALL_NAME_TOOL NAMES install_name_tool )
+ if( NOT CMAKE_INSTALL_NAME_TOOL )
+  message( FATAL_ERROR "Could not find install_name_tool, please check your installation." )
+ endif()
+ mark_as_advanced( CMAKE_INSTALL_NAME_TOOL )
+endif()
+
+# Force set compilers because standard identification works badly for us
+include( CMakeForceCompiler )
+CMAKE_FORCE_C_COMPILER( "${CMAKE_C_COMPILER}" GNU )
+if( ANDROID_COMPILER_IS_CLANG )
+ set( CMAKE_C_COMPILER_ID Clang )
+endif()
+set( CMAKE_C_PLATFORM_ID Linux )
+if( X86_64 OR MIPS64 OR ARM64_V8A )
+ set( CMAKE_C_SIZEOF_DATA_PTR 8 )
+else()
+ set( CMAKE_C_SIZEOF_DATA_PTR 4 )
+endif()
+set( CMAKE_C_HAS_ISYSROOT 1 )
+set( CMAKE_C_COMPILER_ABI ELF )
+CMAKE_FORCE_CXX_COMPILER( "${CMAKE_CXX_COMPILER}" GNU )
+if( ANDROID_COMPILER_IS_CLANG )
+ set( CMAKE_CXX_COMPILER_ID Clang)
+endif()
+set( CMAKE_CXX_PLATFORM_ID Linux )
+set( CMAKE_CXX_SIZEOF_DATA_PTR ${CMAKE_C_SIZEOF_DATA_PTR} )
+set( CMAKE_CXX_HAS_ISYSROOT 1 )
+set( CMAKE_CXX_COMPILER_ABI ELF )
+set( CMAKE_CXX_SOURCE_FILE_EXTENSIONS cc cp cxx cpp CPP c++ C )
+# force ASM compiler (required for CMake < 2.8.5)
+set( CMAKE_ASM_COMPILER_ID_RUN TRUE )
+set( CMAKE_ASM_COMPILER_ID GNU )
+set( CMAKE_ASM_COMPILER_WORKS TRUE )
+set( CMAKE_ASM_COMPILER_FORCED TRUE )
+set( CMAKE_COMPILER_IS_GNUASM 1)
+set( CMAKE_ASM_SOURCE_FILE_EXTENSIONS s S asm )
+
+foreach( lang C CXX ASM )
+ if( ANDROID_COMPILER_IS_CLANG )
+  set( CMAKE_${lang}_COMPILER_VERSION ${ANDROID_CLANG_VERSION} )
+ else()
+  set( CMAKE_${lang}_COMPILER_VERSION ${ANDROID_COMPILER_VERSION} )
+ endif()
+endforeach()
+
+# flags and definitions
+remove_definitions( -DANDROID )
+add_definitions( -DANDROID )
+
+if( ANDROID_SYSROOT MATCHES "[ ;\"]" )
+ if( CMAKE_HOST_WIN32 )
+  # try to convert path to 8.3 form
+  file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cvt83.cmd" "@echo %~s1" )
+  execute_process( COMMAND "$ENV{ComSpec}" /c "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/cvt83.cmd" "${ANDROID_SYSROOT}"
+                   OUTPUT_VARIABLE __path OUTPUT_STRIP_TRAILING_WHITESPACE
+                   RESULT_VARIABLE __result ERROR_QUIET )
+  if( __result EQUAL 0 )
+   file( TO_CMAKE_PATH "${__path}" ANDROID_SYSROOT )
+   set( ANDROID_CXX_FLAGS "--sysroot=${ANDROID_SYSROOT}" )
+  else()
+   set( ANDROID_CXX_FLAGS "--sysroot=\"${ANDROID_SYSROOT}\"" )
+  endif()
+ else()
+  set( ANDROID_CXX_FLAGS "'--sysroot=${ANDROID_SYSROOT}'" )
+ endif()
+ if( NOT _CMAKE_IN_TRY_COMPILE )
+  # quotes can break try_compile and compiler identification
+  message(WARNING "Path to your Android NDK (or toolchain) has non-alphanumeric symbols.\nThe build might be broken.\n")
+ endif()
+else()
+ set( ANDROID_CXX_FLAGS "--sysroot=${ANDROID_SYSROOT}" )
+endif()
+
+# NDK flags
+if (ARM64_V8A )
+ set( ANDROID_CXX_FLAGS         "${ANDROID_CXX_FLAGS} -funwind-tables" )
+ set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer -fstrict-aliasing" )
+ set( ANDROID_CXX_FLAGS_DEBUG   "-fno-omit-frame-pointer -fno-strict-aliasing" )
+ if( NOT ANDROID_COMPILER_IS_CLANG )
+  set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} -funswitch-loops -finline-limit=300" )
+ endif()
+elseif( ARMEABI OR ARMEABI_V7A)
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" )
+ if( NOT ANDROID_FORCE_ARM_BUILD AND NOT ARMEABI_V6 )
+  set( ANDROID_CXX_FLAGS_RELEASE "-mthumb -fomit-frame-pointer -fno-strict-aliasing" )
+  set( ANDROID_CXX_FLAGS_DEBUG   "-marm -fno-omit-frame-pointer -fno-strict-aliasing" )
+  if( NOT ANDROID_COMPILER_IS_CLANG )
+   set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -finline-limit=64" )
+  endif()
+ else()
+  # always compile ARMEABI_V6 in arm mode; otherwise there is no difference from ARMEABI
+  set( ANDROID_CXX_FLAGS_RELEASE "-marm -fomit-frame-pointer -fstrict-aliasing" )
+  set( ANDROID_CXX_FLAGS_DEBUG   "-marm -fno-omit-frame-pointer -fno-strict-aliasing" )
+  if( NOT ANDROID_COMPILER_IS_CLANG )
+   set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funswitch-loops -finline-limit=300" )
+  endif()
+ endif()
+elseif( X86 OR X86_64 )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funwind-tables" )
+ if( NOT ANDROID_COMPILER_IS_CLANG )
+  set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -funswitch-loops -finline-limit=300" )
+ endif()
+ set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer -fstrict-aliasing" )
+ set( ANDROID_CXX_FLAGS_DEBUG   "-fno-omit-frame-pointer -fno-strict-aliasing" )
+elseif( MIPS OR MIPS64 )
+ set( ANDROID_CXX_FLAGS         "${ANDROID_CXX_FLAGS} -fno-strict-aliasing -finline-functions -funwind-tables -fmessage-length=0" )
+ set( ANDROID_CXX_FLAGS_RELEASE "-fomit-frame-pointer" )
+ set( ANDROID_CXX_FLAGS_DEBUG   "-fno-omit-frame-pointer" )
+ if( NOT ANDROID_COMPILER_IS_CLANG )
+  set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fno-inline-functions-called-once -fgcse-after-reload -frerun-cse-after-loop -frename-registers" )
+  set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE} -funswitch-loops -finline-limit=300" )
+ endif()
+elseif()
+ set( ANDROID_CXX_FLAGS_RELEASE "" )
+ set( ANDROID_CXX_FLAGS_DEBUG   "" )
+endif()
+
+set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -fsigned-char" ) # good/necessary when porting desktop libraries
+
+if( NOT X86 AND NOT ANDROID_COMPILER_IS_CLANG )
+ set( ANDROID_CXX_FLAGS "-Wno-psabi ${ANDROID_CXX_FLAGS}" )
+endif()
+
+if( NOT ANDROID_COMPILER_VERSION VERSION_LESS "4.6" )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -no-canonical-prefixes" ) # see https://android-review.googlesource.com/#/c/47564/
+endif()
+
+# ABI-specific flags
+if( ARMEABI_V7A )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv7-a -mfloat-abi=softfp" )
+ if( NEON )
+  set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=neon" )
+ elseif( VFPV3 )
+  set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=vfpv3" )
+ else()
+  set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -mfpu=vfpv3-d16" )
+ endif()
+elseif( ARMEABI_V6 )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv6 -mfloat-abi=softfp -mfpu=vfp" ) # vfp == vfpv2
+elseif( ARMEABI )
+ set( ANDROID_CXX_FLAGS "${ANDROID_CXX_FLAGS} -march=armv5te -mtune=xscale -msoft-float" )
+endif()
+
+if( ANDROID_STL MATCHES "gnustl" AND (EXISTS "${__libstl}" OR EXISTS "${__libsupcxx}") )
+ set( CMAKE_CXX_CREATE_SHARED_LIBRARY "<CMAKE_C_COMPILER> <CMAKE_SHARED_LIBRARY_CXX_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" )
+ set( CMAKE_CXX_CREATE_SHARED_MODULE  "<CMAKE_C_COMPILER> <CMAKE_SHARED_LIBRARY_CXX_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" )
+ set( CMAKE_CXX_LINK_EXECUTABLE       "<CMAKE_C_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>" )
+else()
+ set( CMAKE_CXX_CREATE_SHARED_LIBRARY "<CMAKE_CXX_COMPILER> <CMAKE_SHARED_LIBRARY_CXX_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" )
+ set( CMAKE_CXX_CREATE_SHARED_MODULE  "<CMAKE_CXX_COMPILER> <CMAKE_SHARED_LIBRARY_CXX_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" )
+ set( CMAKE_CXX_LINK_EXECUTABLE       "<CMAKE_CXX_COMPILER> <FLAGS> <CMAKE_CXX_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>" )
+endif()
+
+# STL
+if( EXISTS "${__libstl}" OR EXISTS "${__libsupcxx}" )
+ if( EXISTS "${__libstl}" )
+  set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${__libstl}\"" )
+  set( CMAKE_CXX_CREATE_SHARED_MODULE  "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${__libstl}\"" )
+  set( CMAKE_CXX_LINK_EXECUTABLE       "${CMAKE_CXX_LINK_EXECUTABLE} \"${__libstl}\"" )
+ endif()
+ if( EXISTS "${__libsupcxx}" )
+  set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${__libsupcxx}\"" )
+  set( CMAKE_CXX_CREATE_SHARED_MODULE  "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${__libsupcxx}\"" )
+  set( CMAKE_CXX_LINK_EXECUTABLE       "${CMAKE_CXX_LINK_EXECUTABLE} \"${__libsupcxx}\"" )
+  # C objects:
+  set( CMAKE_C_CREATE_SHARED_LIBRARY "<CMAKE_C_COMPILER> <CMAKE_SHARED_LIBRARY_C_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_C_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" )
+  set( CMAKE_C_CREATE_SHARED_MODULE  "<CMAKE_C_COMPILER> <CMAKE_SHARED_LIBRARY_C_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS> <CMAKE_SHARED_LIBRARY_SONAME_C_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>" )
+  set( CMAKE_C_LINK_EXECUTABLE       "<CMAKE_C_COMPILER> <FLAGS> <CMAKE_C_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>" )
+  set( CMAKE_C_CREATE_SHARED_LIBRARY "${CMAKE_C_CREATE_SHARED_LIBRARY} \"${__libsupcxx}\"" )
+  set( CMAKE_C_CREATE_SHARED_MODULE  "${CMAKE_C_CREATE_SHARED_MODULE} \"${__libsupcxx}\"" )
+  set( CMAKE_C_LINK_EXECUTABLE       "${CMAKE_C_LINK_EXECUTABLE} \"${__libsupcxx}\"" )
+ endif()
+ if( ANDROID_STL MATCHES "gnustl" )
+  if( NOT EXISTS "${ANDROID_LIBM_PATH}" )
+   set( ANDROID_LIBM_PATH -lm )
+  endif()
+  set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} ${ANDROID_LIBM_PATH}" )
+  set( CMAKE_CXX_CREATE_SHARED_MODULE  "${CMAKE_CXX_CREATE_SHARED_MODULE} ${ANDROID_LIBM_PATH}" )
+  set( CMAKE_CXX_LINK_EXECUTABLE       "${CMAKE_CXX_LINK_EXECUTABLE} ${ANDROID_LIBM_PATH}" )
+ endif()
+endif()
+
+# variables controlling optional build flags
+if( ANDROID_NDK_RELEASE_NUM LESS 7000 ) # before r7
+ # libGLESv2.so in NDK's prior to r7 refers to missing external symbols.
+ # So this flag option is required for all projects using OpenGL from native.
+ __INIT_VARIABLE( ANDROID_SO_UNDEFINED                      VALUES ON )
+else()
+ __INIT_VARIABLE( ANDROID_SO_UNDEFINED                      VALUES OFF )
+endif()
+__INIT_VARIABLE( ANDROID_NO_UNDEFINED                       VALUES ON )
+__INIT_VARIABLE( ANDROID_FUNCTION_LEVEL_LINKING             VALUES ON )
+__INIT_VARIABLE( ANDROID_GOLD_LINKER                        VALUES ON )
+__INIT_VARIABLE( ANDROID_NOEXECSTACK                        VALUES ON )
+__INIT_VARIABLE( ANDROID_RELRO                              VALUES ON )
+
+set( ANDROID_NO_UNDEFINED           ${ANDROID_NO_UNDEFINED}           CACHE BOOL "Show all undefined symbols as linker errors" )
+set( ANDROID_SO_UNDEFINED           ${ANDROID_SO_UNDEFINED}           CACHE BOOL "Allows or disallows undefined symbols in shared libraries" )
+set( ANDROID_FUNCTION_LEVEL_LINKING ${ANDROID_FUNCTION_LEVEL_LINKING} CACHE BOOL "Put each function in separate section and enable garbage collection of unused input sections at link time" )
+set( ANDROID_GOLD_LINKER            ${ANDROID_GOLD_LINKER}            CACHE BOOL "Enables gold linker" )
+set( ANDROID_NOEXECSTACK            ${ANDROID_NOEXECSTACK}            CACHE BOOL "Allows or disallows undefined symbols in shared libraries" )
+set( ANDROID_RELRO                  ${ANDROID_RELRO}                  CACHE BOOL "Enables RELRO - a memory corruption mitigation technique" )
+mark_as_advanced( ANDROID_NO_UNDEFINED ANDROID_SO_UNDEFINED ANDROID_FUNCTION_LEVEL_LINKING ANDROID_GOLD_LINKER ANDROID_NOEXECSTACK ANDROID_RELRO )
+
+# linker flags
+set( ANDROID_LINKER_FLAGS "" )
+
+if( ARMEABI_V7A )
+ # this is *required* to use the following linker flags that routes around
+ # a CPU bug in some Cortex-A8 implementations:
+ set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--fix-cortex-a8" )
+endif()
+
+if( ANDROID_NO_UNDEFINED )
+ if( MIPS )
+  # there is some sysroot-related problem in mips linker...
+  if( NOT ANDROID_SYSROOT MATCHES "[ ;\"]" )
+   set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--no-undefined -Wl,-rpath-link,${ANDROID_SYSROOT}/usr/lib" )
+  endif()
+ else()
+  set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--no-undefined" )
+ endif()
+endif()
+
+if( ANDROID_SO_UNDEFINED )
+ set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-allow-shlib-undefined" )
+endif()
+
+if( ANDROID_FUNCTION_LEVEL_LINKING )
+ set( ANDROID_CXX_FLAGS    "${ANDROID_CXX_FLAGS} -fdata-sections -ffunction-sections" )
+ set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,--gc-sections" )
+endif()
+
+if( ANDROID_COMPILER_VERSION VERSION_EQUAL "4.6" )
+ if( ANDROID_GOLD_LINKER AND (CMAKE_HOST_UNIX OR ANDROID_NDK_RELEASE_NUM GREATER 8002) AND (ARMEABI OR ARMEABI_V7A OR X86) )
+  set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -fuse-ld=gold" )
+ elseif( ANDROID_NDK_RELEASE_NUM GREATER 8002 ) # after r8b
+  set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -fuse-ld=bfd" )
+ elseif( ANDROID_NDK_RELEASE STREQUAL "r8b" AND ARMEABI AND NOT _CMAKE_IN_TRY_COMPILE )
+  message( WARNING "The default bfd linker from arm GCC 4.6 toolchain can fail with 'unresolvable R_ARM_THM_CALL relocation' error message. See https://code.google.com/p/android/issues/detail?id=35342
+  On Linux and OS X host platform you can workaround this problem using gold linker (default).
+  Rerun cmake with -DANDROID_GOLD_LINKER=ON option in case of problems.
+" )
+ endif()
+endif() # version 4.6
+
+if( ANDROID_NOEXECSTACK )
+ if( ANDROID_COMPILER_IS_CLANG )
+  set( ANDROID_CXX_FLAGS    "${ANDROID_CXX_FLAGS} -Xclang -mnoexecstack" )
+ else()
+  set( ANDROID_CXX_FLAGS    "${ANDROID_CXX_FLAGS} -Wa,--noexecstack" )
+ endif()
+ set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-z,noexecstack" )
+endif()
+
+if( ANDROID_RELRO )
+ set( ANDROID_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} -Wl,-z,relro -Wl,-z,now" )
+endif()
+
+if( ANDROID_COMPILER_IS_CLANG )
+ set( ANDROID_CXX_FLAGS "-target ${ANDROID_LLVM_TRIPLE} -Qunused-arguments ${ANDROID_CXX_FLAGS}" )
+ if( BUILD_WITH_ANDROID_NDK )
+  set( ANDROID_CXX_FLAGS "-gcc-toolchain ${ANDROID_TOOLCHAIN_ROOT} ${ANDROID_CXX_FLAGS}" )
+ endif()
+endif()
+
+# cache flags
+set( CMAKE_CXX_FLAGS           ""                        CACHE STRING "c++ flags" )
+set( CMAKE_C_FLAGS             ""                        CACHE STRING "c flags" )
+set( CMAKE_CXX_FLAGS_RELEASE   "-O3 -DNDEBUG"            CACHE STRING "c++ Release flags" )
+set( CMAKE_C_FLAGS_RELEASE     "-O3 -DNDEBUG"            CACHE STRING "c Release flags" )
+set( CMAKE_CXX_FLAGS_DEBUG     "-O0 -g -DDEBUG -D_DEBUG" CACHE STRING "c++ Debug flags" )
+set( CMAKE_C_FLAGS_DEBUG       "-O0 -g -DDEBUG -D_DEBUG" CACHE STRING "c Debug flags" )
+set( CMAKE_SHARED_LINKER_FLAGS ""                        CACHE STRING "shared linker flags" )
+set( CMAKE_MODULE_LINKER_FLAGS ""                        CACHE STRING "module linker flags" )
+set( CMAKE_EXE_LINKER_FLAGS    "-Wl,-z,nocopyreloc"      CACHE STRING "executable linker flags" )
+
+# put flags to cache (for debug purpose only)
+set( ANDROID_CXX_FLAGS         "${ANDROID_CXX_FLAGS}"         CACHE INTERNAL "Android specific c/c++ flags" )
+set( ANDROID_CXX_FLAGS_RELEASE "${ANDROID_CXX_FLAGS_RELEASE}" CACHE INTERNAL "Android specific c/c++ Release flags" )
+set( ANDROID_CXX_FLAGS_DEBUG   "${ANDROID_CXX_FLAGS_DEBUG}"   CACHE INTERNAL "Android specific c/c++ Debug flags" )
+set( ANDROID_LINKER_FLAGS      "${ANDROID_LINKER_FLAGS}"      CACHE INTERNAL "Android specific c/c++ linker flags" )
+
+# finish flags
+set( CMAKE_CXX_FLAGS           "${ANDROID_CXX_FLAGS} ${CMAKE_CXX_FLAGS}" )
+set( CMAKE_C_FLAGS             "${ANDROID_CXX_FLAGS} ${CMAKE_C_FLAGS}" )
+set( CMAKE_CXX_FLAGS_RELEASE   "${ANDROID_CXX_FLAGS_RELEASE} ${CMAKE_CXX_FLAGS_RELEASE}" )
+set( CMAKE_C_FLAGS_RELEASE     "${ANDROID_CXX_FLAGS_RELEASE} ${CMAKE_C_FLAGS_RELEASE}" )
+set( CMAKE_CXX_FLAGS_DEBUG     "${ANDROID_CXX_FLAGS_DEBUG} ${CMAKE_CXX_FLAGS_DEBUG}" )
+set( CMAKE_C_FLAGS_DEBUG       "${ANDROID_CXX_FLAGS_DEBUG} ${CMAKE_C_FLAGS_DEBUG}" )
+set( CMAKE_SHARED_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_SHARED_LINKER_FLAGS}" )
+set( CMAKE_MODULE_LINKER_FLAGS "${ANDROID_LINKER_FLAGS} ${CMAKE_MODULE_LINKER_FLAGS}" )
+set( CMAKE_EXE_LINKER_FLAGS    "${ANDROID_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}" )
+
+if( MIPS AND BUILD_WITH_ANDROID_NDK AND ANDROID_NDK_RELEASE STREQUAL "r8" )
+ set( CMAKE_SHARED_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.xsc ${CMAKE_SHARED_LINKER_FLAGS}" )
+ set( CMAKE_MODULE_LINKER_FLAGS "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.xsc ${CMAKE_MODULE_LINKER_FLAGS}" )
+ set( CMAKE_EXE_LINKER_FLAGS    "-Wl,-T,${ANDROID_NDK_TOOLCHAINS_PATH}/${ANDROID_GCC_TOOLCHAIN_NAME}/mipself.x ${CMAKE_EXE_LINKER_FLAGS}" )
+endif()
+
+# pie/pic
+if( NOT (ANDROID_NATIVE_API_LEVEL LESS 16) AND (NOT DEFINED ANDROID_APP_PIE OR ANDROID_APP_PIE) AND (CMAKE_VERSION VERSION_GREATER 2.8.8) )
+ set( CMAKE_POSITION_INDEPENDENT_CODE TRUE )
+ set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fPIE -pie")
+else()
+ set( CMAKE_POSITION_INDEPENDENT_CODE FALSE )
+ set( CMAKE_CXX_FLAGS "-fpic ${CMAKE_CXX_FLAGS}" )
+ set( CMAKE_C_FLAGS   "-fpic ${CMAKE_C_FLAGS}" )
+endif()
+
+# configure rtti
+if( DEFINED ANDROID_RTTI AND ANDROID_STL_FORCE_FEATURES )
+ if( ANDROID_RTTI )
+  set( CMAKE_CXX_FLAGS "-frtti ${CMAKE_CXX_FLAGS}" )
+ else()
+  set( CMAKE_CXX_FLAGS "-fno-rtti ${CMAKE_CXX_FLAGS}" )
+ endif()
+endif()
+
+# configure exceptios
+if( DEFINED ANDROID_EXCEPTIONS AND ANDROID_STL_FORCE_FEATURES )
+ if( ANDROID_EXCEPTIONS )
+  set( CMAKE_CXX_FLAGS "-fexceptions ${CMAKE_CXX_FLAGS}" )
+  set( CMAKE_C_FLAGS "-fexceptions ${CMAKE_C_FLAGS}" )
+ else()
+  set( CMAKE_CXX_FLAGS "-fno-exceptions ${CMAKE_CXX_FLAGS}" )
+  set( CMAKE_C_FLAGS "-fno-exceptions ${CMAKE_C_FLAGS}" )
+ endif()
+endif()
+
+# global includes and link directories
+include_directories( SYSTEM "${ANDROID_SYSROOT}/usr/include" ${ANDROID_STL_INCLUDE_DIRS} )
+get_filename_component(__android_install_path "${CMAKE_INSTALL_PREFIX}/libs/${ANDROID_NDK_ABI_NAME}" ABSOLUTE) # avoid CMP0015 policy warning
+link_directories( "${__android_install_path}" )
+
+# detect if need link crtbegin_so.o explicitly
+if( NOT DEFINED ANDROID_EXPLICIT_CRT_LINK )
+ set( __cmd "${CMAKE_CXX_CREATE_SHARED_LIBRARY}" )
+ string( REPLACE "<CMAKE_CXX_COMPILER>" "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}" __cmd "${__cmd}" )
+ string( REPLACE "<CMAKE_C_COMPILER>"   "${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}"   __cmd "${__cmd}" )
+ string( REPLACE "<CMAKE_SHARED_LIBRARY_CXX_FLAGS>" "${CMAKE_CXX_FLAGS}" __cmd "${__cmd}" )
+ string( REPLACE "<LANGUAGE_COMPILE_FLAGS>" "" __cmd "${__cmd}" )
+ string( REPLACE "<LINK_FLAGS>" "${CMAKE_SHARED_LINKER_FLAGS}" __cmd "${__cmd}" )
+ string( REPLACE "<CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS>" "-shared" __cmd "${__cmd}" )
+ string( REPLACE "<CMAKE_SHARED_LIBRARY_SONAME_CXX_FLAG>" "" __cmd "${__cmd}" )
+ string( REPLACE "<TARGET_SONAME>" "" __cmd "${__cmd}" )
+ string( REPLACE "<TARGET>" "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/toolchain_crtlink_test.so" __cmd "${__cmd}" )
+ string( REPLACE "<OBJECTS>" "\"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" __cmd "${__cmd}" )
+ string( REPLACE "<LINK_LIBRARIES>" "" __cmd "${__cmd}" )
+ separate_arguments( __cmd )
+ foreach( __var ANDROID_NDK ANDROID_NDK_TOOLCHAINS_PATH ANDROID_STANDALONE_TOOLCHAIN )
+  if( ${__var} )
+   set( __tmp "${${__var}}" )
+   separate_arguments( __tmp )
+   string( REPLACE "${__tmp}" "${${__var}}" __cmd "${__cmd}")
+  endif()
+ endforeach()
+ string( REPLACE "'" "" __cmd "${__cmd}" )
+ string( REPLACE "\"" "" __cmd "${__cmd}" )
+ execute_process( COMMAND ${__cmd} RESULT_VARIABLE __cmd_result OUTPUT_QUIET ERROR_QUIET )
+ if( __cmd_result EQUAL 0 )
+  set( ANDROID_EXPLICIT_CRT_LINK ON )
+ else()
+  set( ANDROID_EXPLICIT_CRT_LINK OFF )
+ endif()
+endif()
+
+if( ANDROID_EXPLICIT_CRT_LINK )
+ set( CMAKE_CXX_CREATE_SHARED_LIBRARY "${CMAKE_CXX_CREATE_SHARED_LIBRARY} \"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" )
+ set( CMAKE_CXX_CREATE_SHARED_MODULE  "${CMAKE_CXX_CREATE_SHARED_MODULE} \"${ANDROID_SYSROOT}/usr/lib/crtbegin_so.o\"" )
+endif()
+
+# setup output directories
+set( CMAKE_INSTALL_PREFIX "${ANDROID_TOOLCHAIN_ROOT}/user" CACHE STRING "path for installing" )
+
+if( DEFINED LIBRARY_OUTPUT_PATH_ROOT
+      OR EXISTS "${CMAKE_SOURCE_DIR}/AndroidManifest.xml"
+      OR (EXISTS "${CMAKE_SOURCE_DIR}/../AndroidManifest.xml" AND EXISTS "${CMAKE_SOURCE_DIR}/../jni/") )
+  set( LIBRARY_OUTPUT_PATH_ROOT ${CMAKE_SOURCE_DIR} CACHE PATH "Root for binaries output, set this to change where Android libs are installed to" )
+  if( NOT _CMAKE_IN_TRY_COMPILE )
+    if( EXISTS "${CMAKE_SOURCE_DIR}/jni/CMakeLists.txt" )
+      set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin/${ANDROID_NDK_ABI_NAME}" CACHE PATH "Output directory for applications" )
+    else()
+      set( EXECUTABLE_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/bin" CACHE PATH "Output directory for applications" )
+    endif()
+    set( LIBRARY_OUTPUT_PATH "${LIBRARY_OUTPUT_PATH_ROOT}/libs/${ANDROID_NDK_ABI_NAME}" CACHE PATH "Output directory for Android libs" )
+  endif()
+endif()
+
+# copy shaed stl library to build directory
+if( NOT _CMAKE_IN_TRY_COMPILE AND __libstl MATCHES "[.]so$" AND DEFINED LIBRARY_OUTPUT_PATH )
+  get_filename_component( __libstlname "${__libstl}" NAME )
+  execute_process( COMMAND "${CMAKE_COMMAND}" -E copy_if_different "${__libstl}" "${LIBRARY_OUTPUT_PATH}/${__libstlname}" RESULT_VARIABLE __fileCopyProcess )
+  if( NOT __fileCopyProcess EQUAL 0 OR NOT EXISTS "${LIBRARY_OUTPUT_PATH}/${__libstlname}")
+    message( SEND_ERROR "Failed copying of ${__libstl} to the ${LIBRARY_OUTPUT_PATH}/${__libstlname}" )
+  endif()
+  unset( __fileCopyProcess )
+  unset( __libstlname )
+endif()
+
+
+# set these global flags for cmake client scripts to change behavior
+set( ANDROID True )
+set( BUILD_ANDROID True )
+
+# where is the target environment
+set( CMAKE_FIND_ROOT_PATH "${ANDROID_TOOLCHAIN_ROOT}/bin" "${ANDROID_TOOLCHAIN_ROOT}/${ANDROID_TOOLCHAIN_MACHINE_NAME}" "${ANDROID_SYSROOT}" "${CMAKE_INSTALL_PREFIX}" "${CMAKE_INSTALL_PREFIX}/share" )
+
+# only search for libraries and includes in the ndk toolchain
+set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY )
+set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY )
+set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY )
+
+
+# macro to find packages on the host OS
+macro( find_host_package )
+ set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER )
+ set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER )
+ set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER )
+ if( CMAKE_HOST_WIN32 )
+  SET( WIN32 1 )
+  SET( UNIX )
+ elseif( CMAKE_HOST_APPLE )
+  SET( APPLE 1 )
+  SET( UNIX )
+ endif()
+ find_package( ${ARGN} )
+ SET( WIN32 )
+ SET( APPLE )
+ SET( UNIX 1 )
+ set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY )
+ set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY )
+ set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY )
+endmacro()
+
+
+# macro to find programs on the host OS
+macro( find_host_program )
+ set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER )
+ set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER )
+ set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER )
+ if( CMAKE_HOST_WIN32 )
+  SET( WIN32 1 )
+  SET( UNIX )
+ elseif( CMAKE_HOST_APPLE )
+  SET( APPLE 1 )
+  SET( UNIX )
+ endif()
+ find_program( ${ARGN} )
+ SET( WIN32 )
+ SET( APPLE )
+ SET( UNIX 1 )
+ set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY )
+ set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY )
+ set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY )
+endmacro()
+
+
+# export toolchain settings for the try_compile() command
+if( NOT _CMAKE_IN_TRY_COMPILE )
+ set( __toolchain_config "")
+ foreach( __var NDK_CCACHE  LIBRARY_OUTPUT_PATH_ROOT  ANDROID_FORBID_SYGWIN
+                ANDROID_NDK_HOST_X64
+                ANDROID_NDK
+                ANDROID_NDK_LAYOUT
+                ANDROID_STANDALONE_TOOLCHAIN
+                ANDROID_TOOLCHAIN_NAME
+                ANDROID_ABI
+                ANDROID_NATIVE_API_LEVEL
+                ANDROID_STL
+                ANDROID_STL_FORCE_FEATURES
+                ANDROID_FORCE_ARM_BUILD
+                ANDROID_NO_UNDEFINED
+                ANDROID_SO_UNDEFINED
+                ANDROID_FUNCTION_LEVEL_LINKING
+                ANDROID_GOLD_LINKER
+                ANDROID_NOEXECSTACK
+                ANDROID_RELRO
+                ANDROID_LIBM_PATH
+                ANDROID_EXPLICIT_CRT_LINK
+                ANDROID_APP_PIE
+                )
+  if( DEFINED ${__var} )
+   if( ${__var} MATCHES " ")
+    set( __toolchain_config "${__toolchain_config}set( ${__var} \"${${__var}}\" CACHE INTERNAL \"\" )\n" )
+   else()
+    set( __toolchain_config "${__toolchain_config}set( ${__var} ${${__var}} CACHE INTERNAL \"\" )\n" )
+   endif()
+  endif()
+ endforeach()
+ file( WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/android.toolchain.config.cmake" "${__toolchain_config}" )
+ unset( __toolchain_config )
+endif()
+
+
+# force cmake to produce / instead of \ in build commands for Ninja generator
+if( CMAKE_GENERATOR MATCHES "Ninja" AND CMAKE_HOST_WIN32 )
+ # it is a bad hack after all
+ # CMake generates Ninja makefiles with UNIX paths only if it thinks that we are going to build with MinGW
+ set( CMAKE_COMPILER_IS_MINGW TRUE ) # tell CMake that we are MinGW
+ set( CMAKE_CROSSCOMPILING TRUE )    # stop recursion
+ enable_language( C )
+ enable_language( CXX )
+ # unset( CMAKE_COMPILER_IS_MINGW ) # can't unset because CMake does not convert back-slashes in response files without it
+ unset( MINGW )
+endif()
+
+
+# Variables controlling behavior or set by cmake toolchain:
+#   ANDROID_ABI : "armeabi-v7a" (default), "armeabi", "armeabi-v7a with NEON", "armeabi-v7a with VFPV3", "armeabi-v6 with VFP", "x86", "mips", "arm64-v8a", "x86_64", "mips64"
+#   ANDROID_NATIVE_API_LEVEL : 3,4,5,8,9,14,15,16,17,18,19,21 (depends on NDK version)
+#   ANDROID_STL : gnustl_static/gnustl_shared/stlport_static/stlport_shared/gabi++_static/gabi++_shared/system_re/system/none
+#   ANDROID_FORBID_SYGWIN : ON/OFF
+#   ANDROID_NO_UNDEFINED : ON/OFF
+#   ANDROID_SO_UNDEFINED : OFF/ON  (default depends on NDK version)
+#   ANDROID_FUNCTION_LEVEL_LINKING : ON/OFF
+#   ANDROID_GOLD_LINKER : ON/OFF
+#   ANDROID_NOEXECSTACK : ON/OFF
+#   ANDROID_RELRO : ON/OFF
+#   ANDROID_FORCE_ARM_BUILD : ON/OFF
+#   ANDROID_STL_FORCE_FEATURES : ON/OFF
+#   ANDROID_LIBM_PATH : path to libm.so (set to something like $(TOP)/out/target/product/<product_name>/obj/lib/libm.so) to workaround unresolved `sincos`
+# Can be set only at the first run:
+#   ANDROID_NDK : path to your NDK install
+#   NDK_CCACHE : path to your ccache executable
+#   ANDROID_TOOLCHAIN_NAME : the NDK name of compiler toolchain
+#   ANDROID_NDK_HOST_X64 : try to use x86_64 toolchain (default for x64 host systems)
+#   ANDROID_NDK_LAYOUT : the inner NDK structure (RELEASE, LINARO, ANDROID)
+#   LIBRARY_OUTPUT_PATH_ROOT : <any valid path>
+#   ANDROID_STANDALONE_TOOLCHAIN
+#
+# Primary read-only variables:
+#   ANDROID : always TRUE
+#   ARMEABI : TRUE for arm v6 and older devices
+#   ARMEABI_V6 : TRUE for arm v6
+#   ARMEABI_V7A : TRUE for arm v7a
+#   ARM64_V8A : TRUE for arm64-v8a
+#   NEON : TRUE if NEON unit is enabled
+#   VFPV3 : TRUE if VFP version 3 is enabled
+#   X86 : TRUE if configured for x86
+#   X86_64 : TRUE if configured for x86_64
+#   MIPS : TRUE if configured for mips
+#   MIPS64 : TRUE if configured for mips64
+#   BUILD_WITH_ANDROID_NDK : TRUE if NDK is used
+#   BUILD_WITH_STANDALONE_TOOLCHAIN : TRUE if standalone toolchain is used
+#   ANDROID_NDK_HOST_SYSTEM_NAME : "windows", "linux-x86" or "darwin-x86" depending on host platform
+#   ANDROID_NDK_ABI_NAME : "armeabi", "armeabi-v7a", "x86", "mips", "arm64-v8a", "x86_64", "mips64" depending on ANDROID_ABI
+#   ANDROID_NDK_RELEASE : from r5 to r10d; set only for NDK
+#   ANDROID_NDK_RELEASE_NUM : numeric ANDROID_NDK_RELEASE version (1000*major+minor)
+#   ANDROID_ARCH_NAME : "arm", "x86", "mips", "arm64", "x86_64", "mips64" depending on ANDROID_ABI
+#   ANDROID_SYSROOT : path to the compiler sysroot
+#   TOOL_OS_SUFFIX : "" or ".exe" depending on host platform
+#   ANDROID_COMPILER_IS_CLANG : TRUE if clang compiler is used
+#
+# Secondary (less stable) read-only variables:
+#   ANDROID_COMPILER_VERSION : GCC version used (not Clang version)
+#   ANDROID_CLANG_VERSION : version of clang compiler if clang is used
+#   ANDROID_CXX_FLAGS : C/C++ compiler flags required by Android platform
+#   ANDROID_SUPPORTED_ABIS : list of currently allowed values for ANDROID_ABI
+#   ANDROID_TOOLCHAIN_MACHINE_NAME : "arm-linux-androideabi", "arm-eabi" or "i686-android-linux"
+#   ANDROID_TOOLCHAIN_ROOT : path to the top level of toolchain (standalone or placed inside NDK)
+#   ANDROID_CLANG_TOOLCHAIN_ROOT : path to clang tools
+#   ANDROID_SUPPORTED_NATIVE_API_LEVELS : list of native API levels found inside NDK
+#   ANDROID_STL_INCLUDE_DIRS : stl include paths
+#   ANDROID_RTTI : if rtti is enabled by the runtime
+#   ANDROID_EXCEPTIONS : if exceptions are enabled by the runtime
+#   ANDROID_GCC_TOOLCHAIN_NAME : read-only, differs from ANDROID_TOOLCHAIN_NAME only if clang is used
+#
+# Defaults:
+#   ANDROID_DEFAULT_NDK_API_LEVEL
+#   ANDROID_DEFAULT_NDK_API_LEVEL_${ARCH}
+#   ANDROID_NDK_SEARCH_PATHS
+#   ANDROID_SUPPORTED_ABIS_${ARCH}
+#   ANDROID_SUPPORTED_NDK_VERSIONS
diff --git a/src/third_party/android-cmake/ndk_links.md b/src/third_party/android-cmake/ndk_links.md
new file mode 100644
index 0000000..6d93d61
--- /dev/null
+++ b/src/third_party/android-cmake/ndk_links.md
@@ -0,0 +1,211 @@
+
+============== r1 ============== (dead links)
+
+* http://dl.google.com/android/ndk/android-ndk-1.5_r1-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-1.5_r1-darwin-x86.zip
+* http://dl.google.com/android/ndk/android-ndk-1.5_r1-linux-x86.zip
+
+============== r2 ==============
+
+* http://dl.google.com/android/ndk/android-ndk-1.6_r1-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-1.6_r1-darwin-x86.zip
+* http://dl.google.com/android/ndk/android-ndk-1.6_r1-linux-x86.zip
+
+============== r3 ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r3-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-r3-darwin-x86.zip
+* http://dl.google.com/android/ndk/android-ndk-r3-linux-x86.zip
+
+============== r4 ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r4-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-r4-darwin-x86.zip
+* http://dl.google.com/android/ndk/android-ndk-r4-linux-x86.zip
+
+============== r4b ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r4b-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-r4b-darwin-x86.zip
+* http://dl.google.com/android/ndk/android-ndk-r4b-linux-x86.zip
+
+============== r5 ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r5-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-r5-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r5-linux-x86.tar.bz2
+
+============== r5b ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r5b-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-r5b-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r5b-linux-x86.tar.bz2
+
+============== r5c ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r5c-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-r5c-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r5c-linux-x86.tar.bz2
+
+============== r6 ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r6-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-r6-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r6-linux-x86.tar.bz2
+
+============== r6b ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r6b-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-r6b-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r6b-linux-x86.tar.bz2
+
+============== r7 ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r7-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-r7-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r7-linux-x86.tar.bz2
+
+============== r7b ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r7b-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-r7b-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r7b-linux-x86.tar.bz2
+
+============== r7c ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r7c-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-r7c-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r7c-linux-x86.tar.bz2
+
+============== r8 ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r8-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-r8-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r8-linux-x86.tar.bz2
+
+============== r8b ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r8b-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-r8b-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r8b-linux-x86.tar.bz2
+
+============== r8c ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r8c-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-r8c-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r8c-linux-x86.tar.bz2
+
+============== r8d ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r8d-windows.zip
+* http://dl.google.com/android/ndk/android-ndk-r8d-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r8d-linux-x86.tar.bz2
+
+============== r8e ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r8e-windows-x86.zip
+* http://dl.google.com/android/ndk/android-ndk-r8e-windows-x86_64.zip
+* http://dl.google.com/android/ndk/android-ndk-r8e-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r8e-darwin-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r8e-linux-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r8e-linux-x86_64.tar.bz2
+
+============== r9 ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86.zip
+* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86-legacy-toolchains.zip
+* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86_64.zip
+* http://dl.google.com/android/ndk/android-ndk-r9-windows-x86_64-legacy-toolchains.zip
+* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86-legacy-toolchains.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9-darwin-x86_64-legacy-toolchains.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86-legacy-toolchains.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9-linux-x86_64-legacy-toolchains.tar.bz2
+
+============== r9b ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86.zip
+* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86-legacy-toolchains.zip
+* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86_64.zip
+* http://dl.google.com/android/ndk/android-ndk-r9b-windows-x86_64-legacy-toolchains.zip
+* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86-legacy-toolchains.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9b-darwin-x86_64-legacy-toolchains.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86-legacy-toolchains.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9b-linux-x86_64-legacy-toolchains.tar.bz2
+
+============== r9c ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r9c-windows-x86.zip
+* http://dl.google.com/android/ndk/android-ndk-r9c-windows-x86_64.zip
+* http://dl.google.com/android/ndk/android-ndk-r9c-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9c-darwin-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9c-linux-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9c-linux-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9c-cxx-stl-libs-with-debugging-info.zip
+
+============== r9d ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r9d-windows-x86.zip
+* http://dl.google.com/android/ndk/android-ndk-r9d-windows-x86_64.zip
+* http://dl.google.com/android/ndk/android-ndk-r9d-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9d-darwin-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9d-linux-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9d-linux-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r9d-cxx-stl-libs-with-debug-info.zip
+
+============== r10 ==============
+
+* http://dl.google.com/android/ndk/android-ndk32-r10-windows-x86.zip
+* http://dl.google.com/android/ndk/android-ndk32-r10-windows-x86_64.zip
+* http://dl.google.com/android/ndk/android-ndk32-r10-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk32-r10-darwin-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk32-r10-linux-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk32-r10-linux-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk64-r10-windows-x86.zip
+* http://dl.google.com/android/ndk/android-ndk64-r10-windows-x86_64.zip
+* http://dl.google.com/android/ndk/android-ndk64-r10-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk64-r10-darwin-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk64-r10-linux-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk64-r10-linux-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r10-cxx-stl-libs-with-debug-info.zip
+
+============== r10b ==============
+
+* http://dl.google.com/android/ndk/android-ndk32-r10b-windows-x86.zip
+* http://dl.google.com/android/ndk/android-ndk32-r10b-windows-x86_64.zip
+* http://dl.google.com/android/ndk/android-ndk32-r10b-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk32-r10b-darwin-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk32-r10b-linux-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk32-r10b-linux-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk64-r10b-windows-x86.zip
+* http://dl.google.com/android/ndk/android-ndk64-r10b-windows-x86_64.zip
+* http://dl.google.com/android/ndk/android-ndk64-r10b-darwin-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk64-r10b-darwin-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk64-r10b-linux-x86.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk64-r10b-linux-x86_64.tar.bz2
+* http://dl.google.com/android/ndk/android-ndk-r10b-cxx-stl-libs-with-debug-info.zip
+
+============== r10c ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r10c-windows-x86.exe
+* http://dl.google.com/android/ndk/android-ndk-r10c-windows-x86_64.exe
+* http://dl.google.com/android/ndk/android-ndk-r10c-darwin-x86.bin
+* http://dl.google.com/android/ndk/android-ndk-r10c-darwin-x86_64.bin
+* http://dl.google.com/android/ndk/android-ndk-r10c-linux-x86.bin
+* http://dl.google.com/android/ndk/android-ndk-r10c-linux-x86_64.bin
+
+============== r10d ==============
+
+* http://dl.google.com/android/ndk/android-ndk-r10d-windows-x86.exe
+* http://dl.google.com/android/ndk/android-ndk-r10d-windows-x86_64.exe
+* http://dl.google.com/android/ndk/android-ndk-r10d-darwin-x86.bin
+* http://dl.google.com/android/ndk/android-ndk-r10d-darwin-x86_64.bin
+* http://dl.google.com/android/ndk/android-ndk-r10d-linux-x86.bin
+* http://dl.google.com/android/ndk/android-ndk-r10d-linux-x86_64.bin
diff --git a/src/tool/ciphers.cc b/src/tool/ciphers.cc
index d7cc36b..6370b78 100644
--- a/src/tool/ciphers.cc
+++ b/src/tool/ciphers.cc
@@ -20,8 +20,6 @@
 
 #include <openssl/ssl.h>
 
-#include "../crypto/test/scoped_types.h"
-#include "../ssl/test/scoped_types.h"
 #include "internal.h"
 
 
@@ -33,8 +31,8 @@
 
   const std::string &ciphers_string = args.back();
 
-  ScopedSSL_CTX ctx(SSL_CTX_new(SSLv23_client_method()));
-  if (!SSL_CTX_set_cipher_list(ctx.get(), ciphers_string.c_str())) {
+  bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(SSLv23_client_method()));
+  if (!SSL_CTX_set_strict_cipher_list(ctx.get(), ciphers_string.c_str())) {
     fprintf(stderr, "Failed to parse cipher suite config.\n");
     ERR_print_errors_fp(stderr);
     return false;
diff --git a/src/tool/client.cc b/src/tool/client.cc
index dbec184..bc17426 100644
--- a/src/tool/client.cc
+++ b/src/tool/client.cc
@@ -16,12 +16,19 @@
 
 #include <stdio.h>
 
+#if !defined(OPENSSL_WINDOWS)
+#include <sys/select.h>
+#else
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
+#include <winsock2.h>
+OPENSSL_MSVC_PRAGMA(warning(pop))
+#endif
+
 #include <openssl/err.h>
 #include <openssl/pem.h>
 #include <openssl/ssl.h>
 
-#include "../crypto/test/scoped_types.h"
-#include "../ssl/test/scoped_types.h"
+#include "../crypto/internal.h"
 #include "internal.h"
 #include "transport_common.h"
 
@@ -86,38 +93,41 @@
       "Private-key file to use (default is no client certificate)",
     },
     {
+      "-starttls", kOptionalArgument,
+      "A STARTTLS mini-protocol to run before the TLS handshake. Supported"
+      " values: 'smtp'",
+    },
+    {
+     "-grease", kBooleanArgument,
+     "Enable GREASE",
+    },
+    {
+      "-resume", kBooleanArgument,
+      "Establish a second connection resuming the original connection.",
+    },
+    {
+      "-root-certs", kOptionalArgument,
+      "A filename containing one of more PEM root certificates. Implies that "
+      "verification is required.",
+    },
+    {
+        "-early-data", kBooleanArgument, "Allow early data",
+    },
+    {
      "", kOptionalArgument, "",
     },
 };
 
-static ScopedEVP_PKEY LoadPrivateKey(const std::string &file) {
-  ScopedBIO bio(BIO_new(BIO_s_file()));
+static bssl::UniquePtr<EVP_PKEY> LoadPrivateKey(const std::string &file) {
+  bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_file()));
   if (!bio || !BIO_read_filename(bio.get(), file.c_str())) {
     return nullptr;
   }
-  ScopedEVP_PKEY pkey(PEM_read_bio_PrivateKey(bio.get(), nullptr, nullptr,
-                                              nullptr));
+  bssl::UniquePtr<EVP_PKEY> pkey(PEM_read_bio_PrivateKey(bio.get(), nullptr,
+                                 nullptr, nullptr));
   return pkey;
 }
 
-static bool VersionFromString(uint16_t *out_version,
-                              const std::string& version) {
-  if (version == "ssl3") {
-    *out_version = SSL3_VERSION;
-    return true;
-  } else if (version == "tls1" || version == "tls1.0") {
-    *out_version = TLS1_VERSION;
-    return true;
-  } else if (version == "tls1.1") {
-    *out_version = TLS1_1_VERSION;
-    return true;
-  } else if (version == "tls1.2") {
-    *out_version = TLS1_2_VERSION;
-    return true;
-  }
-  return false;
-}
-
 static int NextProtoSelectCallback(SSL* ssl, uint8_t** out, uint8_t* outlen,
                                    const uint8_t* in, unsigned inlen, void* arg) {
   *out = reinterpret_cast<uint8_t *>(arg);
@@ -132,6 +142,119 @@
   fflush(g_keylog_file);
 }
 
+static bssl::UniquePtr<BIO> session_out;
+static bssl::UniquePtr<SSL_SESSION> resume_session;
+
+static int NewSessionCallback(SSL *ssl, SSL_SESSION *session) {
+  if (session_out) {
+    if (!PEM_write_bio_SSL_SESSION(session_out.get(), session) ||
+        BIO_flush(session_out.get()) <= 0) {
+      fprintf(stderr, "Error while saving session:\n");
+      ERR_print_errors_cb(PrintErrorCallback, stderr);
+      return 0;
+    }
+  }
+  resume_session = bssl::UniquePtr<SSL_SESSION>(session);
+  return 1;
+}
+
+static bool WaitForSession(SSL *ssl, int sock) {
+  fd_set read_fds;
+  FD_ZERO(&read_fds);
+
+  if (!SocketSetNonBlocking(sock, true)) {
+    return false;
+  }
+
+  while (!resume_session) {
+    FD_SET(sock, &read_fds);
+    int ret = select(sock + 1, &read_fds, NULL, NULL, NULL);
+    if (ret <= 0) {
+      perror("select");
+      return false;
+    }
+
+    uint8_t buffer[512];
+    int ssl_ret = SSL_read(ssl, buffer, sizeof(buffer));
+
+    if (ssl_ret <= 0) {
+      int ssl_err = SSL_get_error(ssl, ssl_ret);
+      if (ssl_err == SSL_ERROR_WANT_READ) {
+        continue;
+      }
+      fprintf(stderr, "Error while reading: %d\n", ssl_err);
+      ERR_print_errors_cb(PrintErrorCallback, stderr);
+      return false;
+    }
+  }
+
+  return true;
+}
+
+static bool DoConnection(SSL_CTX *ctx,
+                         std::map<std::string, std::string> args_map,
+                         bool (*cb)(SSL *ssl, int sock)) {
+  int sock = -1;
+  if (!Connect(&sock, args_map["-connect"])) {
+    return false;
+  }
+
+  if (args_map.count("-starttls") != 0) {
+    const std::string& starttls = args_map["-starttls"];
+    if (starttls == "smtp") {
+      if (!DoSMTPStartTLS(sock)) {
+        return false;
+      }
+    } else {
+      fprintf(stderr, "Unknown value for -starttls: %s\n", starttls.c_str());
+      return false;
+    }
+  }
+
+  bssl::UniquePtr<BIO> bio(BIO_new_socket(sock, BIO_CLOSE));
+  bssl::UniquePtr<SSL> ssl(SSL_new(ctx));
+
+  if (args_map.count("-server-name") != 0) {
+    SSL_set_tlsext_host_name(ssl.get(), args_map["-server-name"].c_str());
+  }
+
+  if (args_map.count("-session-in") != 0) {
+    bssl::UniquePtr<BIO> in(BIO_new_file(args_map["-session-in"].c_str(),
+                                         "rb"));
+    if (!in) {
+      fprintf(stderr, "Error reading session\n");
+      ERR_print_errors_cb(PrintErrorCallback, stderr);
+      return false;
+    }
+    bssl::UniquePtr<SSL_SESSION> session(PEM_read_bio_SSL_SESSION(in.get(),
+                                         nullptr, nullptr, nullptr));
+    if (!session) {
+      fprintf(stderr, "Error reading session\n");
+      ERR_print_errors_cb(PrintErrorCallback, stderr);
+      return false;
+    }
+    SSL_set_session(ssl.get(), session.get());
+  } else if (resume_session) {
+    SSL_set_session(ssl.get(), resume_session.get());
+  }
+
+  SSL_set_bio(ssl.get(), bio.get(), bio.get());
+  bio.release();
+
+  int ret = SSL_connect(ssl.get());
+  if (ret != 1) {
+    int ssl_err = SSL_get_error(ssl.get(), ret);
+    fprintf(stderr, "Error while connecting: %d\n", ssl_err);
+    ERR_print_errors_cb(PrintErrorCallback, stderr);
+    return false;
+  }
+
+  fprintf(stderr, "Connected.\n");
+  PrintConnectionInfo(ssl.get());
+
+  return cb(ssl.get(), sock);
+}
+
 bool Client(const std::vector<std::string> &args) {
   if (!InitSocketLibrary()) {
     return false;
@@ -144,7 +267,7 @@
     return false;
   }
 
-  ScopedSSL_CTX ctx(SSL_CTX_new(SSLv23_client_method()));
+  bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(SSLv23_client_method()));
 
   const char *keylog_file = getenv("SSLKEYLOGFILE");
   if (keylog_file) {
@@ -157,19 +280,21 @@
   }
 
   if (args_map.count("-cipher") != 0 &&
-      !SSL_CTX_set_cipher_list(ctx.get(), args_map["-cipher"].c_str())) {
+      !SSL_CTX_set_strict_cipher_list(ctx.get(), args_map["-cipher"].c_str())) {
     fprintf(stderr, "Failed setting cipher list\n");
     return false;
   }
 
-  if (args_map.count("-max-version") != 0) {
-    uint16_t version;
-    if (!VersionFromString(&version, args_map["-max-version"])) {
-      fprintf(stderr, "Unknown protocol version: '%s'\n",
-              args_map["-max-version"].c_str());
-      return false;
-    }
-    SSL_CTX_set_max_version(ctx.get(), version);
+  uint16_t max_version = TLS1_3_VERSION;
+  if (args_map.count("-max-version") != 0 &&
+      !VersionFromString(&max_version, args_map["-max-version"])) {
+    fprintf(stderr, "Unknown protocol version: '%s'\n",
+            args_map["-max-version"].c_str());
+    return false;
+  }
+
+  if (!SSL_CTX_set_max_proto_version(ctx.get(), max_version)) {
+    return false;
   }
 
   if (args_map.count("-min-version") != 0) {
@@ -179,7 +304,9 @@
               args_map["-min-version"].c_str());
       return false;
     }
-    SSL_CTX_set_min_version(ctx.get(), version);
+    if (!SSL_CTX_set_min_proto_version(ctx.get(), version)) {
+      return false;
+    }
   }
 
   if (args_map.count("-select-next-proto") != 0) {
@@ -209,7 +336,8 @@
       }
       wire.push_back(static_cast<uint8_t>(len));
       wire.resize(wire.size() + len);
-      memcpy(wire.data() + wire.size() - len, alpn_protos.data() + i, len);
+      OPENSSL_memcpy(wire.data() + wire.size() - len, alpn_protos.data() + i,
+                     len);
       i = j + 1;
     }
     if (SSL_CTX_set_alpn_protos(ctx.get(), wire.data(), wire.size()) != 0) {
@@ -230,7 +358,8 @@
   }
 
   if (args_map.count("-channel-id-key") != 0) {
-    ScopedEVP_PKEY pkey = LoadPrivateKey(args_map["-channel-id-key"]);
+    bssl::UniquePtr<EVP_PKEY> pkey =
+        LoadPrivateKey(args_map["-channel-id-key"]);
     if (!pkey || !SSL_CTX_set1_tls_channel_id(ctx.get(), pkey.get())) {
       return false;
     }
@@ -252,60 +381,41 @@
     }
   }
 
-  int sock = -1;
-  if (!Connect(&sock, args_map["-connect"])) {
-    return false;
-  }
-
-  ScopedBIO bio(BIO_new_socket(sock, BIO_CLOSE));
-  ScopedSSL ssl(SSL_new(ctx.get()));
-
-  if (args_map.count("-server-name") != 0) {
-    SSL_set_tlsext_host_name(ssl.get(), args_map["-server-name"].c_str());
-  }
-
-  if (args_map.count("-session-in") != 0) {
-    ScopedBIO in(BIO_new_file(args_map["-session-in"].c_str(), "rb"));
-    if (!in) {
-      fprintf(stderr, "Error reading session\n");
-      ERR_print_errors_cb(PrintErrorCallback, stderr);
-      return false;
-    }
-    ScopedSSL_SESSION session(PEM_read_bio_SSL_SESSION(in.get(), nullptr,
-                                                       nullptr, nullptr));
-    if (!session) {
-      fprintf(stderr, "Error reading session\n");
-      ERR_print_errors_cb(PrintErrorCallback, stderr);
-      return false;
-    }
-    SSL_set_session(ssl.get(), session.get());
-  }
-
-  SSL_set_bio(ssl.get(), bio.get(), bio.get());
-  bio.release();
-
-  int ret = SSL_connect(ssl.get());
-  if (ret != 1) {
-    int ssl_err = SSL_get_error(ssl.get(), ret);
-    fprintf(stderr, "Error while connecting: %d\n", ssl_err);
-    ERR_print_errors_cb(PrintErrorCallback, stderr);
-    return false;
-  }
-
-  fprintf(stderr, "Connected.\n");
-  PrintConnectionInfo(ssl.get());
+  SSL_CTX_set_session_cache_mode(ctx.get(), SSL_SESS_CACHE_CLIENT);
+  SSL_CTX_sess_set_new_cb(ctx.get(), NewSessionCallback);
 
   if (args_map.count("-session-out") != 0) {
-    ScopedBIO out(BIO_new_file(args_map["-session-out"].c_str(), "wb"));
-    if (!out ||
-        !PEM_write_bio_SSL_SESSION(out.get(), SSL_get0_session(ssl.get()))) {
-      fprintf(stderr, "Error while saving session:\n");
+    session_out.reset(BIO_new_file(args_map["-session-out"].c_str(), "wb"));
+    if (!session_out) {
+      fprintf(stderr, "Error while opening %s:\n",
+              args_map["-session-out"].c_str());
       ERR_print_errors_cb(PrintErrorCallback, stderr);
       return false;
     }
   }
 
-  bool ok = TransferData(ssl.get(), sock);
+  if (args_map.count("-grease") != 0) {
+    SSL_CTX_set_grease_enabled(ctx.get(), 1);
+  }
 
-  return ok;
+  if (args_map.count("-root-certs") != 0) {
+    if (!SSL_CTX_load_verify_locations(
+            ctx.get(), args_map["-root-certs"].c_str(), nullptr)) {
+      fprintf(stderr, "Failed to load root certificates.\n");
+      ERR_print_errors_cb(PrintErrorCallback, stderr);
+      return false;
+    }
+    SSL_CTX_set_verify(ctx.get(), SSL_VERIFY_PEER, nullptr);
+  }
+
+  if (args_map.count("-early-data") != 0) {
+    SSL_CTX_set_early_data_enabled(ctx.get(), 1);
+  }
+
+  if (args_map.count("-resume") != 0 &&
+      !DoConnection(ctx.get(), args_map, &WaitForSession)) {
+    return false;
+  }
+
+  return DoConnection(ctx.get(), args_map, &TransferData);
 }
diff --git a/src/tool/digest.cc b/src/tool/digest.cc
index 7cd8827..7b6c88b 100644
--- a/src/tool/digest.cc
+++ b/src/tool/digest.cc
@@ -21,6 +21,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <limits.h>
+#include <stdio.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 
@@ -31,9 +32,9 @@
 #define O_BINARY 0
 #endif
 #else
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <windows.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
 #include <io.h>
 #define PATH_MAX MAX_PATH
 typedef int ssize_t;
@@ -41,10 +42,12 @@
 
 #include <openssl/digest.h>
 
+#include "internal.h"
+
 
 struct close_delete {
   void operator()(int *fd) {
-    close(*fd);
+    BORINGSSL_CLOSE(*fd);
   }
 };
 
@@ -62,8 +65,9 @@
   };
 
   Source() : is_stdin_(false) {}
-  Source(Type) : is_stdin_(true) {}
-  Source(const std::string &name) : is_stdin_(false), filename_(name) {}
+  explicit Source(Type) : is_stdin_(true) {}
+  explicit Source(const std::string &name)
+      : is_stdin_(false), filename_(name) {}
 
   bool is_stdin() const { return is_stdin_; }
   const std::string &filename() const { return filename_; }
@@ -81,7 +85,7 @@
 static bool OpenFile(int *out_fd, const std::string &filename) {
   *out_fd = -1;
 
-  int fd = open(filename.c_str(), O_RDONLY | O_BINARY);
+  int fd = BORINGSSL_OPEN(filename.c_str(), O_RDONLY | O_BINARY);
   if (fd < 0) {
     fprintf(stderr, "Failed to open input file '%s': %s\n", filename.c_str(),
             strerror(errno));
@@ -130,12 +134,8 @@
   static const size_t kBufSize = 8192;
   std::unique_ptr<uint8_t[]> buf(new uint8_t[kBufSize]);
 
-  EVP_MD_CTX ctx;
-  EVP_MD_CTX_init(&ctx);
-  std::unique_ptr<EVP_MD_CTX, func_delete<EVP_MD_CTX, int, EVP_MD_CTX_cleanup>>
-      scoped_ctx(&ctx);
-
-  if (!EVP_DigestInit_ex(&ctx, md, NULL)) {
+  bssl::ScopedEVP_MD_CTX ctx;
+  if (!EVP_DigestInit_ex(ctx.get(), md, NULL)) {
     fprintf(stderr, "Failed to initialize EVP_MD_CTX.\n");
     return false;
   }
@@ -144,7 +144,7 @@
     ssize_t n;
 
     do {
-      n = read(fd, buf.get(), kBufSize);
+      n = BORINGSSL_READ(fd, buf.get(), kBufSize);
     } while (n == -1 && errno == EINTR);
 
     if (n == 0) {
@@ -156,7 +156,7 @@
       return false;
     }
 
-    if (!EVP_DigestUpdate(&ctx, buf.get(), n)) {
+    if (!EVP_DigestUpdate(ctx.get(), buf.get(), n)) {
       fprintf(stderr, "Failed to update hash.\n");
       return false;
     }
@@ -164,7 +164,7 @@
 
   uint8_t digest[EVP_MAX_MD_SIZE];
   unsigned digest_len;
-  if (!EVP_DigestFinal_ex(&ctx, digest, &digest_len)) {
+  if (!EVP_DigestFinal_ex(ctx.get(), digest, &digest_len)) {
     fprintf(stderr, "Failed to finish hash.\n");
     return false;
   }
@@ -232,10 +232,10 @@
       return false;
     }
 
-    file = fdopen(fd, "rb");
+    file = BORINGSSL_FDOPEN(fd, "rb");
     if (!file) {
       perror("fdopen");
-      close(fd);
+      BORINGSSL_CLOSE(fd);
       return false;
     }
 
diff --git a/src/tool/generate_ed25519.cc b/src/tool/generate_ed25519.cc
index 15d3692..35b57b9 100644
--- a/src/tool/generate_ed25519.cc
+++ b/src/tool/generate_ed25519.cc
@@ -18,10 +18,17 @@
 #include <stdio.h>
 #include <string.h>
 
-#include "../crypto/test/scoped_types.h"
 #include "internal.h"
 
 
+struct FileCloser {
+  void operator()(FILE *file) {
+    fclose(file);
+  }
+};
+
+using ScopedFILE = std::unique_ptr<FILE, FileCloser>;
+
 static const struct argument kArguments[] = {
     {
         "-out-public", kRequiredArgument, "The file to write the public key to",
diff --git a/src/tool/genrsa.cc b/src/tool/genrsa.cc
index 4b39401..b49ebbc 100644
--- a/src/tool/genrsa.cc
+++ b/src/tool/genrsa.cc
@@ -18,7 +18,6 @@
 #include <openssl/pem.h>
 #include <openssl/rsa.h>
 
-#include "../crypto/test/scoped_types.h"
 #include "internal.h"
 
 
@@ -51,9 +50,9 @@
     return false;
   }
 
-  ScopedRSA rsa(RSA_new());
-  ScopedBIGNUM e(BN_new());
-  ScopedBIO bio(BIO_new_fp(stdout, BIO_NOCLOSE));
+  bssl::UniquePtr<RSA> rsa(RSA_new());
+  bssl::UniquePtr<BIGNUM> e(BN_new());
+  bssl::UniquePtr<BIO> bio(BIO_new_fp(stdout, BIO_NOCLOSE));
 
   if (!BN_set_word(e.get(), RSA_F4) ||
       !RSA_generate_multi_prime_key(rsa.get(), bits, nprimes, e.get(), NULL) ||
diff --git a/src/tool/internal.h b/src/tool/internal.h
index 84f8c4d..fd66e00 100644
--- a/src/tool/internal.h
+++ b/src/tool/internal.h
@@ -20,18 +20,28 @@
 #include <string>
 #include <vector>
 
-#if defined(_MSC_VER)
-#pragma warning(push)
+OPENSSL_MSVC_PRAGMA(warning(push))
 // MSVC issues warning C4702 for unreachable code in its xtree header when
 // compiling with -D_HAS_EXCEPTIONS=0. See
 // https://connect.microsoft.com/VisualStudio/feedback/details/809962
-#pragma warning(disable: 4702)
-#endif
+OPENSSL_MSVC_PRAGMA(warning(disable: 4702))
 
 #include <map>
 
-#if defined(_MSC_VER)
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
+
+#if defined(OPENSSL_WINDOWS)
+  #define BORINGSSL_OPEN _open
+  #define BORINGSSL_FDOPEN _fdopen
+  #define BORINGSSL_CLOSE _close
+  #define BORINGSSL_READ _read
+  #define BORINGSSL_WRITE _write
+#else
+  #define BORINGSSL_OPEN open
+  #define BORINGSSL_FDOPEN fdopen
+  #define BORINGSSL_CLOSE close
+  #define BORINGSSL_READ read
+  #define BORINGSSL_WRITE write
 #endif
 
 enum ArgumentType {
@@ -55,6 +65,21 @@
                  unsigned default_value,
                  const std::map<std::string, std::string> &args);
 
+bool Ciphers(const std::vector<std::string> &args);
+bool Client(const std::vector<std::string> &args);
+bool DoPKCS12(const std::vector<std::string> &args);
+bool GenerateEd25519Key(const std::vector<std::string> &args);
+bool GenerateRSAKey(const std::vector<std::string> &args);
+bool MD5Sum(const std::vector<std::string> &args);
+bool Rand(const std::vector<std::string> &args);
+bool SHA1Sum(const std::vector<std::string> &args);
+bool SHA224Sum(const std::vector<std::string> &args);
+bool SHA256Sum(const std::vector<std::string> &args);
+bool SHA384Sum(const std::vector<std::string> &args);
+bool SHA512Sum(const std::vector<std::string> &args);
+bool Server(const std::vector<std::string> &args);
+bool Speed(const std::vector<std::string> &args);
+
 // These values are DER encoded, RSA private keys.
 extern const uint8_t kDERRSAPrivate2048[];
 extern const size_t kDERRSAPrivate2048Len;
diff --git a/src/tool/pkcs12.cc b/src/tool/pkcs12.cc
index fe830d6..a8ddb0e 100644
--- a/src/tool/pkcs12.cc
+++ b/src/tool/pkcs12.cc
@@ -36,6 +36,7 @@
 #include <openssl/pkcs8.h>
 #include <openssl/stack.h>
 
+#include "../crypto/internal.h"
 #include "internal.h"
 
 
@@ -64,7 +65,7 @@
     return false;
   }
 
-  int fd = open(args_map["-dump"].c_str(), O_RDONLY);
+  int fd = BORINGSSL_OPEN(args_map["-dump"].c_str(), O_RDONLY);
   if (fd < 0) {
     perror("open");
     return false;
@@ -73,7 +74,7 @@
   struct stat st;
   if (fstat(fd, &st)) {
     perror("fstat");
-    close(fd);
+    BORINGSSL_CLOSE(fd);
     return false;
   }
   const size_t size = st.st_size;
@@ -82,7 +83,7 @@
   read_result_t n;
   size_t off = 0;
   do {
-    n = read(fd, &contents[off], size - off);
+    n = BORINGSSL_READ(fd, &contents[off], size - off);
     if (n >= 0) {
       off += static_cast<size_t>(n);
     }
@@ -90,11 +91,11 @@
 
   if (off != size) {
     perror("read");
-    close(fd);
+    BORINGSSL_CLOSE(fd);
     return false;
   }
 
-  close(fd);
+  BORINGSSL_CLOSE(fd);
 
   printf("Enter password: ");
   fflush(stdout);
@@ -102,15 +103,15 @@
   char password[256];
   off = 0;
   do {
-    n = read(0, &password[off], sizeof(password) - 1 - off);
+    n = BORINGSSL_READ(0, &password[off], sizeof(password) - 1 - off);
     if (n >= 0) {
       off += static_cast<size_t>(n);
     }
-  } while ((n > 0 && memchr(password, '\n', off) == NULL &&
+  } while ((n > 0 && OPENSSL_memchr(password, '\n', off) == NULL &&
             off < sizeof(password) - 1) ||
            (n == -1 && errno == EINTR));
 
-  char *newline = reinterpret_cast<char*>(memchr(password, '\n', off));
+  char *newline = reinterpret_cast<char *>(OPENSSL_memchr(password, '\n', off));
   if (newline == NULL) {
     return false;
   }
@@ -120,23 +121,22 @@
   CBS_init(&pkcs12, contents.get(), size);
 
   EVP_PKEY *key;
-  STACK_OF(X509) *certs = sk_X509_new_null();
+  bssl::UniquePtr<STACK_OF(X509)> certs(sk_X509_new_null());
 
-  if (!PKCS12_get_key_and_certs(&key, certs, &pkcs12, password)) {
+  if (!PKCS12_get_key_and_certs(&key, certs.get(), &pkcs12, password)) {
     fprintf(stderr, "Failed to parse PKCS#12 data:\n");
     ERR_print_errors_fp(stderr);
     return false;
   }
+  bssl::UniquePtr<EVP_PKEY> key_owned(key);
 
   if (key != NULL) {
     PEM_write_PrivateKey(stdout, key, NULL, NULL, 0, NULL, NULL);
-    EVP_PKEY_free(key);
   }
 
-  for (size_t i = 0; i < sk_X509_num(certs); i++) {
-    PEM_write_X509(stdout, sk_X509_value(certs, i));
+  for (size_t i = 0; i < sk_X509_num(certs.get()); i++) {
+    PEM_write_X509(stdout, sk_X509_value(certs.get(), i));
   }
-  sk_X509_pop_free(certs, X509_free);
 
   return true;
 }
diff --git a/src/tool/rand.cc b/src/tool/rand.cc
index 10078e2..b442e0d 100644
--- a/src/tool/rand.cc
+++ b/src/tool/rand.cc
@@ -16,6 +16,7 @@
 #include <vector>
 
 #include <stdint.h>
+#include <stdio.h>
 #include <stdlib.h>
 
 #include <openssl/rand.h>
@@ -71,7 +72,7 @@
     }
     RAND_bytes(buf, todo);
     if (hex) {
-      static const char hextable[] = "0123456789abdef";
+      static const char hextable[16 + 1] = "0123456789abcdef";
       for (unsigned i = 0; i < todo; i++) {
         hex_buf[i*2] = hextable[buf[i] >> 4];
         hex_buf[i*2 + 1] = hextable[buf[i] & 0xf];
diff --git a/src/tool/server.cc b/src/tool/server.cc
index 14f37a4..1a97dff 100644
--- a/src/tool/server.cc
+++ b/src/tool/server.cc
@@ -15,6 +15,7 @@
 #include <openssl/base.h>
 
 #include <openssl/err.h>
+#include <openssl/rand.h>
 #include <openssl/ssl.h>
 
 #include "internal.h"
@@ -23,23 +24,40 @@
 
 static const struct argument kArguments[] = {
     {
-     "-accept", kRequiredArgument,
-     "The port of the server to bind on; eg 45102",
+        "-accept", kRequiredArgument,
+        "The port of the server to bind on; eg 45102",
     },
     {
-     "-cipher", kOptionalArgument,
-     "An OpenSSL-style cipher suite string that configures the offered ciphers",
+        "-cipher", kOptionalArgument,
+        "An OpenSSL-style cipher suite string that configures the offered "
+        "ciphers",
     },
     {
-      "-key", kOptionalArgument,
-      "Private-key file to use (default is server.pem)",
+        "-max-version", kOptionalArgument,
+        "The maximum acceptable protocol version",
     },
     {
-      "-ocsp-response", kOptionalArgument,
-      "OCSP response file to send",
+        "-min-version", kOptionalArgument,
+        "The minimum acceptable protocol version",
     },
     {
-     "", kOptionalArgument, "",
+        "-key", kOptionalArgument,
+        "PEM-encoded file containing the private key, leaf certificate and "
+        "optional certificate chain. A self-signed certificate is generated "
+        "at runtime if this argument is not provided.",
+    },
+    {
+        "-ocsp-response", kOptionalArgument, "OCSP response file to send",
+    },
+    {
+        "-loop", kBooleanArgument,
+        "The server will continue accepting new sequential connections.",
+    },
+    {
+        "-early-data", kBooleanArgument, "Allow early data",
+    },
+    {
+        "", kOptionalArgument, "",
     },
 };
 
@@ -83,6 +101,49 @@
   return ret;
 }
 
+static bssl::UniquePtr<EVP_PKEY> MakeKeyPairForSelfSignedCert() {
+  bssl::UniquePtr<EC_KEY> ec_key(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
+  if (!ec_key || !EC_KEY_generate_key(ec_key.get())) {
+    fprintf(stderr, "Failed to generate key pair.\n");
+    return nullptr;
+  }
+  bssl::UniquePtr<EVP_PKEY> evp_pkey(EVP_PKEY_new());
+  if (!evp_pkey || !EVP_PKEY_assign_EC_KEY(evp_pkey.get(), ec_key.release())) {
+    fprintf(stderr, "Failed to assign key pair.\n");
+    return nullptr;
+  }
+  return evp_pkey;
+}
+
+static bssl::UniquePtr<X509> MakeSelfSignedCert(EVP_PKEY *evp_pkey,
+                                                const int valid_days) {
+  bssl::UniquePtr<X509> x509(X509_new());
+  uint32_t serial;
+  RAND_bytes(reinterpret_cast<uint8_t*>(&serial), sizeof(serial));
+  ASN1_INTEGER_set(X509_get_serialNumber(x509.get()), serial >> 1);
+  X509_gmtime_adj(X509_get_notBefore(x509.get()), 0);
+  X509_gmtime_adj(X509_get_notAfter(x509.get()), 60 * 60 * 24 * valid_days);
+
+  X509_NAME* subject = X509_get_subject_name(x509.get());
+  X509_NAME_add_entry_by_txt(subject, "C", MBSTRING_ASC,
+                             reinterpret_cast<const uint8_t *>("US"), -1, -1,
+                             0);
+  X509_NAME_add_entry_by_txt(subject, "O", MBSTRING_ASC,
+                             reinterpret_cast<const uint8_t *>("BoringSSL"), -1,
+                             -1, 0);
+  X509_set_issuer_name(x509.get(), subject);
+
+  if (!X509_set_pubkey(x509.get(), evp_pkey)) {
+    fprintf(stderr, "Failed to set public key.\n");
+    return nullptr;
+  }
+  if (!X509_sign(x509.get(), evp_pkey, EVP_sha256())) {
+    fprintf(stderr, "Failed to sign certificate.\n");
+    return nullptr;
+  }
+  return x509;
+}
+
 bool Server(const std::vector<std::string> &args) {
   if (!InitSocketLibrary()) {
     return false;
@@ -95,58 +156,104 @@
     return false;
   }
 
-  SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method());
-  SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3);
+  bssl::UniquePtr<SSL_CTX> ctx(SSL_CTX_new(TLS_method()));
+  SSL_CTX_set_options(ctx.get(), SSL_OP_NO_SSLv3);
 
   // Server authentication is required.
-  std::string key_file = "server.pem";
   if (args_map.count("-key") != 0) {
-    key_file = args_map["-key"];
-  }
-  if (!SSL_CTX_use_PrivateKey_file(ctx, key_file.c_str(), SSL_FILETYPE_PEM)) {
-    fprintf(stderr, "Failed to load private key: %s\n", key_file.c_str());
-    return false;
-  }
-  if (!SSL_CTX_use_certificate_chain_file(ctx, key_file.c_str())) {
-    fprintf(stderr, "Failed to load cert chain: %s\n", key_file.c_str());
-    return false;
+    std::string key_file = args_map["-key"];
+    if (!SSL_CTX_use_PrivateKey_file(ctx.get(), key_file.c_str(), SSL_FILETYPE_PEM)) {
+      fprintf(stderr, "Failed to load private key: %s\n", key_file.c_str());
+      return false;
+    }
+    if (!SSL_CTX_use_certificate_chain_file(ctx.get(), key_file.c_str())) {
+      fprintf(stderr, "Failed to load cert chain: %s\n", key_file.c_str());
+      return false;
+    }
+  } else {
+    bssl::UniquePtr<EVP_PKEY> evp_pkey = MakeKeyPairForSelfSignedCert();
+    if (!evp_pkey) {
+      return false;
+    }
+    bssl::UniquePtr<X509> cert =
+        MakeSelfSignedCert(evp_pkey.get(), 365 /* valid_days */);
+    if (!cert) {
+      return false;
+    }
+    if (!SSL_CTX_use_PrivateKey(ctx.get(), evp_pkey.get())) {
+      fprintf(stderr, "Failed to set private key.\n");
+      return false;
+    }
+    if (!SSL_CTX_use_certificate(ctx.get(), cert.get())) {
+      fprintf(stderr, "Failed to set certificate.\n");
+      return false;
+    }
   }
 
   if (args_map.count("-cipher") != 0 &&
-      !SSL_CTX_set_cipher_list(ctx, args_map["-cipher"].c_str())) {
+      !SSL_CTX_set_strict_cipher_list(ctx.get(), args_map["-cipher"].c_str())) {
     fprintf(stderr, "Failed setting cipher list\n");
     return false;
   }
 
+  uint16_t max_version = TLS1_3_VERSION;
+  if (args_map.count("-max-version") != 0 &&
+      !VersionFromString(&max_version, args_map["-max-version"])) {
+    fprintf(stderr, "Unknown protocol version: '%s'\n",
+            args_map["-max-version"].c_str());
+    return false;
+  }
+
+  if (!SSL_CTX_set_max_proto_version(ctx.get(), max_version)) {
+    return false;
+  }
+
+  if (args_map.count("-min-version") != 0) {
+    uint16_t version;
+    if (!VersionFromString(&version, args_map["-min-version"])) {
+      fprintf(stderr, "Unknown protocol version: '%s'\n",
+              args_map["-min-version"].c_str());
+      return false;
+    }
+    if (!SSL_CTX_set_min_proto_version(ctx.get(), version)) {
+      return false;
+    }
+  }
+
   if (args_map.count("-ocsp-response") != 0 &&
-      !LoadOCSPResponse(ctx, args_map["-ocsp-response"].c_str())) {
+      !LoadOCSPResponse(ctx.get(), args_map["-ocsp-response"].c_str())) {
     fprintf(stderr, "Failed to load OCSP response: %s\n", args_map["-ocsp-response"].c_str());
     return false;
   }
 
-  int sock = -1;
-  if (!Accept(&sock, args_map["-accept"])) {
-    return false;
+  if (args_map.count("-early-data") != 0) {
+    SSL_CTX_set_early_data_enabled(ctx.get(), 1);
   }
 
-  BIO *bio = BIO_new_socket(sock, BIO_CLOSE);
-  SSL *ssl = SSL_new(ctx);
-  SSL_set_bio(ssl, bio, bio);
+  bool result = true;
+  do {
+    int sock = -1;
+    if (!Accept(&sock, args_map["-accept"])) {
+      return false;
+    }
 
-  int ret = SSL_accept(ssl);
-  if (ret != 1) {
-    int ssl_err = SSL_get_error(ssl, ret);
-    fprintf(stderr, "Error while connecting: %d\n", ssl_err);
-    ERR_print_errors_cb(PrintErrorCallback, stderr);
-    return false;
-  }
+    BIO *bio = BIO_new_socket(sock, BIO_CLOSE);
+    bssl::UniquePtr<SSL> ssl(SSL_new(ctx.get()));
+    SSL_set_bio(ssl.get(), bio, bio);
 
-  fprintf(stderr, "Connected.\n");
-  PrintConnectionInfo(ssl);
+    int ret = SSL_accept(ssl.get());
+    if (ret != 1) {
+      int ssl_err = SSL_get_error(ssl.get(), ret);
+      fprintf(stderr, "Error while connecting: %d\n", ssl_err);
+      ERR_print_errors_cb(PrintErrorCallback, stderr);
+      return false;
+    }
 
-  bool ok = TransferData(ssl, sock);
+    fprintf(stderr, "Connected.\n");
+    PrintConnectionInfo(ssl.get());
 
-  SSL_free(ssl);
-  SSL_CTX_free(ctx);
-  return ok;
+    result = TransferData(ssl.get(), sock);
+  } while (result && args_map.count("-loop") != 0);
+
+  return result;
 }
diff --git a/src/tool/speed.cc b/src/tool/speed.cc
index db7c5fa..3e5952f 100644
--- a/src/tool/speed.cc
+++ b/src/tool/speed.cc
@@ -18,25 +18,32 @@
 #include <vector>
 
 #include <stdint.h>
+#include <stdlib.h>
 #include <string.h>
 
 #include <openssl/aead.h>
+#include <openssl/bn.h>
 #include <openssl/curve25519.h>
 #include <openssl/digest.h>
 #include <openssl/err.h>
-#include <openssl/obj.h>
+#include <openssl/ec.h>
+#include <openssl/ecdsa.h>
+#include <openssl/ec_key.h>
+#include <openssl/nid.h>
 #include <openssl/rand.h>
 #include <openssl/rsa.h>
 
 #if defined(OPENSSL_WINDOWS)
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <windows.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
 #elif defined(OPENSSL_APPLE)
 #include <sys/time.h>
+#else
+#include <time.h>
 #endif
 
-#include "../crypto/test/scoped_types.h"
+#include "../crypto/internal.h"
 #include "internal.h"
 
 
@@ -86,10 +93,12 @@
 }
 #endif
 
+static uint64_t g_timeout_seconds = 1;
+
 static bool TimeFunction(TimeResults *results, std::function<bool()> func) {
-  // kTotalMS is the total amount of time that we'll aim to measure a function
+  // total_us is the total amount of time that we'll aim to measure a function
   // for.
-  static const uint64_t kTotalUS = 1000000;
+  const uint64_t total_us = g_timeout_seconds * 1000000;
   uint64_t start = time_now(), now, delta;
   unsigned done = 0, iterations_between_time_checks;
 
@@ -120,7 +129,7 @@
     }
 
     now = time_now();
-    if (now - start > kTotalUS) {
+    if (now - start > total_us) {
       break;
     }
   }
@@ -143,6 +152,9 @@
   TimeResults results;
   if (!TimeFunction(&results,
                     [key, &sig, &fake_sha256_hash, &sig_len]() -> bool {
+        /* Usually during RSA signing we're using a long-lived |RSA| that has
+         * already had all of its |BN_MONT_CTX|s constructed, so it makes
+         * sense to use |key| directly here. */
         return RSA_sign(NID_sha256, fake_sha256_hash, sizeof(fake_sha256_hash),
                         sig.get(), &sig_len, key);
       })) {
@@ -154,6 +166,21 @@
 
   if (!TimeFunction(&results,
                     [key, &fake_sha256_hash, &sig, sig_len]() -> bool {
+        /* Usually during RSA verification we have to parse an RSA key from a
+         * certificate or similar, in which case we'd need to construct a new
+         * RSA key, with a new |BN_MONT_CTX| for the public modulus. If we were
+         * to use |key| directly instead, then these costs wouldn't be
+         * accounted for. */
+        bssl::UniquePtr<RSA> verify_key(RSA_new());
+        if (!verify_key) {
+          return false;
+        }
+        verify_key->n = BN_dup(key->n);
+        verify_key->e = BN_dup(key->e);
+        if (!verify_key->n ||
+            !verify_key->e) {
+          return false;
+        }
         return RSA_verify(NID_sha256, fake_sha256_hash,
                           sizeof(fake_sha256_hash), sig.get(), sig_len, key);
       })) {
@@ -173,29 +200,32 @@
 }
 
 static bool SpeedAEADChunk(const EVP_AEAD *aead, const std::string &name,
-                           size_t chunk_len, size_t ad_len) {
+                           size_t chunk_len, size_t ad_len,
+                           evp_aead_direction_t direction) {
   static const unsigned kAlignment = 16;
 
-  EVP_AEAD_CTX ctx;
+  bssl::ScopedEVP_AEAD_CTX ctx;
   const size_t key_len = EVP_AEAD_key_length(aead);
   const size_t nonce_len = EVP_AEAD_nonce_length(aead);
   const size_t overhead_len = EVP_AEAD_max_overhead(aead);
 
   std::unique_ptr<uint8_t[]> key(new uint8_t[key_len]);
-  memset(key.get(), 0, key_len);
+  OPENSSL_memset(key.get(), 0, key_len);
   std::unique_ptr<uint8_t[]> nonce(new uint8_t[nonce_len]);
-  memset(nonce.get(), 0, nonce_len);
+  OPENSSL_memset(nonce.get(), 0, nonce_len);
   std::unique_ptr<uint8_t[]> in_storage(new uint8_t[chunk_len + kAlignment]);
   std::unique_ptr<uint8_t[]> out_storage(new uint8_t[chunk_len + overhead_len + kAlignment]);
+  std::unique_ptr<uint8_t[]> in2_storage(new uint8_t[chunk_len + kAlignment]);
   std::unique_ptr<uint8_t[]> ad(new uint8_t[ad_len]);
-  memset(ad.get(), 0, ad_len);
+  OPENSSL_memset(ad.get(), 0, ad_len);
 
   uint8_t *const in = align(in_storage.get(), kAlignment);
-  memset(in, 0, chunk_len);
+  OPENSSL_memset(in, 0, chunk_len);
   uint8_t *const out = align(out_storage.get(), kAlignment);
-  memset(out, 0, chunk_len + overhead_len);
+  OPENSSL_memset(out, 0, chunk_len + overhead_len);
+  uint8_t *const in2 = align(in2_storage.get(), kAlignment);
 
-  if (!EVP_AEAD_CTX_init_with_direction(&ctx, aead, key.get(), key_len,
+  if (!EVP_AEAD_CTX_init_with_direction(ctx.get(), aead, key.get(), key_len,
                                         EVP_AEAD_DEFAULT_TAG_LENGTH,
                                         evp_aead_seal)) {
     fprintf(stderr, "Failed to create EVP_AEAD_CTX.\n");
@@ -204,23 +234,38 @@
   }
 
   TimeResults results;
-  if (!TimeFunction(&results, [chunk_len, overhead_len, nonce_len, ad_len, in,
-                               out, &ctx, &nonce, &ad]() -> bool {
-        size_t out_len;
+  if (direction == evp_aead_seal) {
+    if (!TimeFunction(&results, [chunk_len, overhead_len, nonce_len, ad_len, in,
+                                 out, &ctx, &nonce, &ad]() -> bool {
+          size_t out_len;
+          return EVP_AEAD_CTX_seal(ctx.get(), out, &out_len,
+                                   chunk_len + overhead_len, nonce.get(),
+                                   nonce_len, in, chunk_len, ad.get(), ad_len);
+        })) {
+      fprintf(stderr, "EVP_AEAD_CTX_seal failed.\n");
+      ERR_print_errors_fp(stderr);
+      return false;
+    }
+  } else {
+    size_t out_len;
+    EVP_AEAD_CTX_seal(ctx.get(), out, &out_len, chunk_len + overhead_len,
+                      nonce.get(), nonce_len, in, chunk_len, ad.get(), ad_len);
 
-        return EVP_AEAD_CTX_seal(
-            &ctx, out, &out_len, chunk_len + overhead_len, nonce.get(),
-            nonce_len, in, chunk_len, ad.get(), ad_len);
-      })) {
-    fprintf(stderr, "EVP_AEAD_CTX_seal failed.\n");
-    ERR_print_errors_fp(stderr);
-    return false;
+    if (!TimeFunction(&results, [chunk_len, nonce_len, ad_len, in2, out, &ctx,
+                                 &nonce, &ad, out_len]() -> bool {
+          size_t in2_len;
+          return EVP_AEAD_CTX_open(ctx.get(), in2, &in2_len, chunk_len,
+                                   nonce.get(), nonce_len, out, out_len,
+                                   ad.get(), ad_len);
+        })) {
+      fprintf(stderr, "EVP_AEAD_CTX_open failed.\n");
+      ERR_print_errors_fp(stderr);
+      return false;
+    }
   }
 
-  results.PrintWithBytes(name + " seal", chunk_len);
-
-  EVP_AEAD_CTX_cleanup(&ctx);
-
+  results.PrintWithBytes(
+      name + (direction == evp_aead_seal ? " seal" : " open"), chunk_len);
   return true;
 }
 
@@ -230,11 +275,30 @@
     return true;
   }
 
-  return SpeedAEADChunk(aead, name + " (16 bytes)", 16, ad_len) &&
-         SpeedAEADChunk(aead, name + " (1350 bytes)", 1350, ad_len) &&
-         SpeedAEADChunk(aead, name + " (8192 bytes)", 8192, ad_len);
+  return SpeedAEADChunk(aead, name + " (16 bytes)", 16, ad_len,
+                        evp_aead_seal) &&
+         SpeedAEADChunk(aead, name + " (1350 bytes)", 1350, ad_len,
+                        evp_aead_seal) &&
+         SpeedAEADChunk(aead, name + " (8192 bytes)", 8192, ad_len,
+                        evp_aead_seal);
 }
 
+#if !defined(OPENSSL_SMALL)
+static bool SpeedAEADOpen(const EVP_AEAD *aead, const std::string &name,
+                          size_t ad_len, const std::string &selected) {
+  if (!selected.empty() && name.find(selected) == std::string::npos) {
+    return true;
+  }
+
+  return SpeedAEADChunk(aead, name + " (16 bytes)", 16, ad_len,
+                        evp_aead_open) &&
+         SpeedAEADChunk(aead, name + " (1350 bytes)", 1350, ad_len,
+                        evp_aead_open) &&
+         SpeedAEADChunk(aead, name + " (8192 bytes)", 8192, ad_len,
+                        evp_aead_open);
+}
+#endif  /* !SMALL */
+
 static bool SpeedHashChunk(const EVP_MD *md, const std::string &name,
                            size_t chunk_len) {
   EVP_MD_CTX *ctx = EVP_MD_CTX_create();
@@ -275,7 +339,7 @@
          SpeedHashChunk(md, name + " (8192 bytes)", 8192);
 }
 
-static bool SpeedRandomChunk(const std::string name, size_t chunk_len) {
+static bool SpeedRandomChunk(const std::string &name, size_t chunk_len) {
   uint8_t scratch[8192];
 
   if (chunk_len > sizeof(scratch)) {
@@ -312,17 +376,17 @@
 
   TimeResults results;
   if (!TimeFunction(&results, [nid]() -> bool {
-        ScopedEC_KEY key(EC_KEY_new_by_curve_name(nid));
+        bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(nid));
         if (!key ||
             !EC_KEY_generate_key(key.get())) {
           return false;
         }
         const EC_GROUP *const group = EC_KEY_get0_group(key.get());
-        ScopedEC_POINT point(EC_POINT_new(group));
-        ScopedBN_CTX ctx(BN_CTX_new());
+        bssl::UniquePtr<EC_POINT> point(EC_POINT_new(group));
+        bssl::UniquePtr<BN_CTX> ctx(BN_CTX_new());
 
-        ScopedBIGNUM x(BN_new());
-        ScopedBIGNUM y(BN_new());
+        bssl::UniquePtr<BIGNUM> x(BN_new());
+        bssl::UniquePtr<BIGNUM> y(BN_new());
 
         if (!point || !ctx || !x || !y ||
             !EC_POINT_mul(group, point.get(), NULL,
@@ -348,7 +412,7 @@
     return true;
   }
 
-  ScopedEC_KEY key(EC_KEY_new_by_curve_name(nid));
+  bssl::UniquePtr<EC_KEY> key(EC_KEY_new_by_curve_name(nid));
   if (!key ||
       !EC_KEY_generate_key(key.get())) {
     return false;
@@ -359,7 +423,7 @@
     return false;
   }
   uint8_t digest[20];
-  memset(digest, 42, sizeof(digest));
+  OPENSSL_memset(digest, 42, sizeof(digest));
   unsigned sig_len;
 
   TimeResults results;
@@ -440,7 +504,7 @@
 
   if (!TimeFunction(&results, []() -> bool {
         uint8_t out[32], in[32];
-        memset(in, 0, sizeof(in));
+        OPENSSL_memset(in, 0, sizeof(in));
         X25519_public_from_private(out, in);
         return true;
       })) {
@@ -452,8 +516,8 @@
 
   if (!TimeFunction(&results, []() -> bool {
         uint8_t out[32], in1[32], in2[32];
-        memset(in1, 0, sizeof(in1));
-        memset(in2, 0, sizeof(in2));
+        OPENSSL_memset(in1, 0, sizeof(in1));
+        OPENSSL_memset(in2, 0, sizeof(in2));
         in1[0] = 1;
         in2[0] = 9;
         return X25519(out, in1, in2) == 1;
@@ -467,55 +531,120 @@
   return true;
 }
 
+static bool SpeedSPAKE2(const std::string &selected) {
+  if (!selected.empty() && selected.find("SPAKE2") == std::string::npos) {
+    return true;
+  }
+
+  TimeResults results;
+
+  static const uint8_t kAliceName[] = {'A'};
+  static const uint8_t kBobName[] = {'B'};
+  static const uint8_t kPassword[] = "password";
+  bssl::UniquePtr<SPAKE2_CTX> alice(SPAKE2_CTX_new(spake2_role_alice,
+                                    kAliceName, sizeof(kAliceName), kBobName,
+                                    sizeof(kBobName)));
+  uint8_t alice_msg[SPAKE2_MAX_MSG_SIZE];
+  size_t alice_msg_len;
+
+  if (!SPAKE2_generate_msg(alice.get(), alice_msg, &alice_msg_len,
+                           sizeof(alice_msg),
+                           kPassword, sizeof(kPassword))) {
+    fprintf(stderr, "SPAKE2_generate_msg failed.\n");
+    return false;
+  }
+
+  if (!TimeFunction(&results, [&alice_msg, alice_msg_len]() -> bool {
+        bssl::UniquePtr<SPAKE2_CTX> bob(SPAKE2_CTX_new(spake2_role_bob,
+                                        kBobName, sizeof(kBobName), kAliceName,
+                                        sizeof(kAliceName)));
+        uint8_t bob_msg[SPAKE2_MAX_MSG_SIZE], bob_key[64];
+        size_t bob_msg_len, bob_key_len;
+        if (!SPAKE2_generate_msg(bob.get(), bob_msg, &bob_msg_len,
+                                 sizeof(bob_msg), kPassword,
+                                 sizeof(kPassword)) ||
+            !SPAKE2_process_msg(bob.get(), bob_key, &bob_key_len,
+                                sizeof(bob_key), alice_msg, alice_msg_len)) {
+          return false;
+        }
+
+        return true;
+      })) {
+    fprintf(stderr, "SPAKE2 failed.\n");
+  }
+
+  results.Print("SPAKE2 over Ed25519");
+
+  return true;
+}
+
+static const struct argument kArguments[] = {
+    {
+     "-filter", kOptionalArgument,
+     "A filter on the speed tests to run",
+    },
+    {
+     "-timeout", kOptionalArgument,
+     "The number of seconds to run each test for (default is 1)",
+    },
+    {
+     "", kOptionalArgument, "",
+    },
+};
+
 bool Speed(const std::vector<std::string> &args) {
+  std::map<std::string, std::string> args_map;
+  if (!ParseKeyValueArguments(&args_map, args, kArguments)) {
+    PrintUsage(kArguments);
+    return false;
+  }
+
   std::string selected;
-  if (args.size() > 1) {
-    fprintf(stderr, "Usage: bssl speed [speed test selector, i.e. 'RNG']\n");
-    return false;
-  }
-  if (args.size() > 0) {
-    selected = args[0];
+  if (args_map.count("-filter") != 0) {
+    selected = args_map["-filter"];
   }
 
-  RSA *key = RSA_private_key_from_bytes(kDERRSAPrivate2048,
-                                        kDERRSAPrivate2048Len);
-  if (key == NULL) {
+  if (args_map.count("-timeout") != 0) {
+    g_timeout_seconds = atoi(args_map["-timeout"].c_str());
+  }
+
+  bssl::UniquePtr<RSA> key(
+      RSA_private_key_from_bytes(kDERRSAPrivate2048, kDERRSAPrivate2048Len));
+  if (key == nullptr) {
     fprintf(stderr, "Failed to parse RSA key.\n");
     ERR_print_errors_fp(stderr);
     return false;
   }
 
-  if (!SpeedRSA("RSA 2048", key, selected)) {
+  if (!SpeedRSA("RSA 2048", key.get(), selected)) {
     return false;
   }
 
-  RSA_free(key);
-  key = RSA_private_key_from_bytes(kDERRSAPrivate3Prime2048,
-                                   kDERRSAPrivate3Prime2048Len);
-  if (key == NULL) {
+  key.reset(RSA_private_key_from_bytes(kDERRSAPrivate3Prime2048,
+                                       kDERRSAPrivate3Prime2048Len));
+  if (key == nullptr) {
     fprintf(stderr, "Failed to parse RSA key.\n");
     ERR_print_errors_fp(stderr);
     return false;
   }
 
-  if (!SpeedRSA("RSA 2048 (3 prime, e=3)", key, selected)) {
+  if (!SpeedRSA("RSA 2048 (3 prime, e=3)", key.get(), selected)) {
     return false;
   }
 
-  RSA_free(key);
-  key = RSA_private_key_from_bytes(kDERRSAPrivate4096,
-                                   kDERRSAPrivate4096Len);
-  if (key == NULL) {
+  key.reset(
+      RSA_private_key_from_bytes(kDERRSAPrivate4096, kDERRSAPrivate4096Len));
+  if (key == nullptr) {
     fprintf(stderr, "Failed to parse 4096-bit RSA key.\n");
     ERR_print_errors_fp(stderr);
     return 1;
   }
 
-  if (!SpeedRSA("RSA 4096", key, selected)) {
+  if (!SpeedRSA("RSA 4096", key.get(), selected)) {
     return false;
   }
 
-  RSA_free(key);
+  key.reset();
 
   // kTLSADLen is the number of bytes of additional data that TLS passes to
   // AEADs.
@@ -530,23 +659,30 @@
       !SpeedAEAD(EVP_aead_aes_256_gcm(), "AES-256-GCM", kTLSADLen, selected) ||
       !SpeedAEAD(EVP_aead_chacha20_poly1305(), "ChaCha20-Poly1305", kTLSADLen,
                  selected) ||
-      !SpeedAEAD(EVP_aead_chacha20_poly1305_old(), "ChaCha20-Poly1305-Old",
-                 kTLSADLen, selected) ||
-      !SpeedAEAD(EVP_aead_rc4_md5_tls(), "RC4-MD5", kLegacyADLen, selected) ||
-      !SpeedAEAD(EVP_aead_rc4_sha1_tls(), "RC4-SHA1", kLegacyADLen, selected) ||
       !SpeedAEAD(EVP_aead_des_ede3_cbc_sha1_tls(), "DES-EDE3-CBC-SHA1",
                  kLegacyADLen, selected) ||
       !SpeedAEAD(EVP_aead_aes_128_cbc_sha1_tls(), "AES-128-CBC-SHA1",
                  kLegacyADLen, selected) ||
       !SpeedAEAD(EVP_aead_aes_256_cbc_sha1_tls(), "AES-256-CBC-SHA1",
                  kLegacyADLen, selected) ||
+#if !defined(OPENSSL_SMALL)
+      !SpeedAEAD(EVP_aead_aes_128_gcm_siv(), "AES-128-GCM-SIV", kTLSADLen,
+                 selected) ||
+      !SpeedAEAD(EVP_aead_aes_256_gcm_siv(), "AES-256-GCM-SIV", kTLSADLen,
+                 selected) ||
+      !SpeedAEADOpen(EVP_aead_aes_128_gcm_siv(), "AES-128-GCM-SIV", kTLSADLen,
+                     selected) ||
+      !SpeedAEADOpen(EVP_aead_aes_256_gcm_siv(), "AES-256-GCM-SIV", kTLSADLen,
+                     selected) ||
+#endif
       !SpeedHash(EVP_sha1(), "SHA-1", selected) ||
       !SpeedHash(EVP_sha256(), "SHA-256", selected) ||
       !SpeedHash(EVP_sha512(), "SHA-512", selected) ||
       !SpeedRandom(selected) ||
       !SpeedECDH(selected) ||
       !SpeedECDSA(selected) ||
-      !Speed25519(selected)) {
+      !Speed25519(selected) ||
+      !SpeedSPAKE2(selected)) {
     return false;
   }
 
diff --git a/src/tool/tool.cc b/src/tool/tool.cc
index b825008..34851b4 100644
--- a/src/tool/tool.cc
+++ b/src/tool/tool.cc
@@ -26,21 +26,8 @@
 #include <libgen.h>
 #endif
 
+#include "internal.h"
 
-bool Ciphers(const std::vector<std::string> &args);
-bool Client(const std::vector<std::string> &args);
-bool DoPKCS12(const std::vector<std::string> &args);
-bool GenerateEd25519Key(const std::vector<std::string> &args);
-bool GenerateRSAKey(const std::vector<std::string> &args);
-bool MD5Sum(const std::vector<std::string> &args);
-bool Rand(const std::vector<std::string> &args);
-bool SHA1Sum(const std::vector<std::string> &args);
-bool SHA224Sum(const std::vector<std::string> &args);
-bool SHA256Sum(const std::vector<std::string> &args);
-bool SHA384Sum(const std::vector<std::string> &args);
-bool SHA512Sum(const std::vector<std::string> &args);
-bool Server(const std::vector<std::string> &args);
-bool Speed(const std::vector<std::string> &args);
 
 typedef bool (*tool_func_t)(const std::vector<std::string> &args);
 
@@ -83,7 +70,7 @@
   }
 }
 
-tool_func_t FindTool(const std::string &name) {
+static tool_func_t FindTool(const std::string &name) {
   for (size_t i = 0;; i++) {
     const Tool &tool = kTools[i];
     if (tool.func == nullptr || name == tool.name) {
diff --git a/src/tool/transport_common.cc b/src/tool/transport_common.cc
index 2c15c00..56bde28 100644
--- a/src/tool/transport_common.cc
+++ b/src/tool/transport_common.cc
@@ -18,6 +18,7 @@
 #include <vector>
 
 #include <errno.h>
+#include <limits.h>
 #include <stddef.h>
 #include <stdlib.h>
 #include <string.h>
@@ -33,19 +34,22 @@
 #include <unistd.h>
 #else
 #include <io.h>
-#pragma warning(push, 3)
+OPENSSL_MSVC_PRAGMA(warning(push, 3))
 #include <winsock2.h>
 #include <ws2tcpip.h>
-#pragma warning(pop)
+OPENSSL_MSVC_PRAGMA(warning(pop))
 
 typedef int ssize_t;
-#pragma comment(lib, "Ws2_32.lib")
+OPENSSL_MSVC_PRAGMA(comment(lib, "Ws2_32.lib"))
 #endif
 
 #include <openssl/err.h>
 #include <openssl/ssl.h>
+#include <openssl/x509.h>
 
+#include "../crypto/internal.h"
 #include "internal.h"
+#include "transport_common.h"
 
 
 #if !defined(OPENSSL_WINDOWS)
@@ -70,9 +74,16 @@
 // in |hostname_and_port|, which should be of the form "www.example.com:123".
 // It returns true on success and false otherwise.
 bool Connect(int *out_sock, const std::string &hostname_and_port) {
-  const size_t colon_offset = hostname_and_port.find_last_of(':');
+  size_t colon_offset = hostname_and_port.find_last_of(':');
+  const size_t bracket_offset = hostname_and_port.find_last_of(']');
   std::string hostname, port;
 
+  // An IPv6 literal may have colons internally, guarded by square brackets.
+  if (bracket_offset != std::string::npos &&
+      colon_offset != std::string::npos && bracket_offset > colon_offset) {
+    colon_offset = std::string::npos;
+  }
+
   if (colon_offset == std::string::npos) {
     hostname = hostname_and_port;
     port = "443";
@@ -81,8 +92,14 @@
     port = hostname_and_port.substr(colon_offset + 1);
   }
 
+  // Handle IPv6 literals.
+  if (hostname.size() >= 2 && hostname[0] == '[' &&
+      hostname[hostname.size() - 1] == ']') {
+    hostname = hostname.substr(1, hostname.size() - 2);
+  }
+
   struct addrinfo hint, *result;
-  memset(&hint, 0, sizeof(hint));
+  OPENSSL_memset(&hint, 0, sizeof(hint));
   hint.ai_family = AF_UNSPEC;
   hint.ai_socktype = SOCK_STREAM;
 
@@ -135,13 +152,18 @@
 bool Accept(int *out_sock, const std::string &port) {
   struct sockaddr_in6 addr, cli_addr;
   socklen_t cli_addr_len = sizeof(cli_addr);
-  memset(&addr, 0, sizeof(addr));
+  OPENSSL_memset(&addr, 0, sizeof(addr));
 
   addr.sin6_family = AF_INET6;
-  addr.sin6_addr = in6addr_any;
+  addr.sin6_addr = IN6ADDR_ANY_INIT;
   addr.sin6_port = htons(atoi(port.c_str()));
 
   bool ok = false;
+#if defined(OPENSSL_WINDOWS)
+  const BOOL enable = TRUE;
+#else
+  const int enable = 1;
+#endif
   int server_sock = -1;
 
   server_sock =
@@ -151,6 +173,12 @@
     goto out;
   }
 
+  if (setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, (const char *)&enable,
+                 sizeof(enable)) < 0) {
+    perror("setsockopt");
+    goto out;
+  }
+
   if (bind(server_sock, (struct sockaddr*)&addr, sizeof(addr)) != 0) {
     perror("connect");
     goto out;
@@ -165,6 +193,56 @@
   return ok;
 }
 
+bool VersionFromString(uint16_t *out_version, const std::string &version) {
+  if (version == "ssl3") {
+    *out_version = SSL3_VERSION;
+    return true;
+  } else if (version == "tls1" || version == "tls1.0") {
+    *out_version = TLS1_VERSION;
+    return true;
+  } else if (version == "tls1.1") {
+    *out_version = TLS1_1_VERSION;
+    return true;
+  } else if (version == "tls1.2") {
+    *out_version = TLS1_2_VERSION;
+    return true;
+  } else if (version == "tls1.3") {
+    *out_version = TLS1_3_VERSION;
+    return true;
+  }
+  return false;
+}
+
+static const char *SignatureAlgorithmToString(uint16_t version, uint16_t sigalg) {
+  const bool is_tls12 = version == TLS1_2_VERSION || version == DTLS1_2_VERSION;
+  switch (sigalg) {
+    case SSL_SIGN_RSA_PKCS1_SHA1:
+      return "rsa_pkcs1_sha1";
+    case SSL_SIGN_RSA_PKCS1_SHA256:
+      return "rsa_pkcs1_sha256";
+    case SSL_SIGN_RSA_PKCS1_SHA384:
+      return "rsa_pkcs1_sha384";
+    case SSL_SIGN_RSA_PKCS1_SHA512:
+      return "rsa_pkcs1_sha512";
+    case SSL_SIGN_ECDSA_SHA1:
+      return "ecdsa_sha1";
+    case SSL_SIGN_ECDSA_SECP256R1_SHA256:
+      return is_tls12 ? "ecdsa_sha256" : "ecdsa_secp256r1_sha256";
+    case SSL_SIGN_ECDSA_SECP384R1_SHA384:
+      return is_tls12 ? "ecdsa_sha384" : "ecdsa_secp384r1_sha384";
+    case SSL_SIGN_ECDSA_SECP521R1_SHA512:
+      return is_tls12 ? "ecdsa_sha512" : "ecdsa_secp521r1_sha512";
+    case SSL_SIGN_RSA_PSS_SHA256:
+      return "rsa_pss_sha256";
+    case SSL_SIGN_RSA_PSS_SHA384:
+      return "rsa_pss_sha384";
+    case SSL_SIGN_RSA_PSS_SHA512:
+      return "rsa_pss_sha512";
+    default:
+      return "(unknown)";
+  }
+}
+
 void PrintConnectionInfo(const SSL *ssl) {
   const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl);
 
@@ -172,13 +250,19 @@
   fprintf(stderr, "  Resumed session: %s\n",
           SSL_session_reused(ssl) ? "yes" : "no");
   fprintf(stderr, "  Cipher: %s\n", SSL_CIPHER_get_name(cipher));
-  if (SSL_CIPHER_is_ECDHE(cipher)) {
-    fprintf(stderr, "  ECDHE curve: %s\n",
-            SSL_get_curve_name(
-                SSL_SESSION_get_key_exchange_info(SSL_get_session(ssl))));
+  uint16_t curve = SSL_get_curve_id(ssl);
+  if (curve != 0) {
+    fprintf(stderr, "  ECDHE curve: %s\n", SSL_get_curve_name(curve));
+  }
+  uint16_t sigalg = SSL_get_peer_signature_algorithm(ssl);
+  if (sigalg != 0) {
+    fprintf(stderr, "  Signature algorithm: %s\n",
+            SignatureAlgorithmToString(SSL_version(ssl), sigalg));
   }
   fprintf(stderr, "  Secure renegotiation: %s\n",
           SSL_get_secure_renegotiation_support(ssl) ? "yes" : "no");
+  fprintf(stderr, "  Extended master secret: %s\n",
+          SSL_get_extms_support(ssl) ? "yes" : "no");
 
   const uint8_t *next_proto;
   unsigned next_proto_len;
@@ -190,6 +274,38 @@
   unsigned alpn_len;
   SSL_get0_alpn_selected(ssl, &alpn, &alpn_len);
   fprintf(stderr, "  ALPN protocol: %.*s\n", alpn_len, alpn);
+
+  const char *host_name = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
+  if (host_name != nullptr && SSL_is_server(ssl)) {
+    fprintf(stderr, "  Client sent SNI: %s\n", host_name);
+  }
+
+  if (!SSL_is_server(ssl)) {
+    const uint8_t *ocsp_staple;
+    size_t ocsp_staple_len;
+    SSL_get0_ocsp_response(ssl, &ocsp_staple, &ocsp_staple_len);
+    fprintf(stderr, "  OCSP staple: %s\n", ocsp_staple_len > 0 ? "yes" : "no");
+
+    const uint8_t *sct_list;
+    size_t sct_list_len;
+    SSL_get0_signed_cert_timestamp_list(ssl, &sct_list, &sct_list_len);
+    fprintf(stderr, "  SCT list: %s\n", sct_list_len > 0 ? "yes" : "no");
+  }
+
+  fprintf(stderr, "  Early data: %s\n",
+          SSL_early_data_accepted(ssl) ? "yes" : "no");
+
+  // Print the server cert subject and issuer names.
+  bssl::UniquePtr<X509> peer(SSL_get_peer_certificate(ssl));
+  if (peer != nullptr) {
+    fprintf(stderr, "  Cert subject: ");
+    X509_NAME_print_ex_fp(stderr, X509_get_subject_name(peer.get()), 0,
+                          XN_FLAG_ONELINE);
+    fprintf(stderr, "\n  Cert issuer: ");
+    X509_NAME_print_ex_fp(stderr, X509_get_issuer_name(peer.get()), 0,
+                          XN_FLAG_ONELINE);
+    fprintf(stderr, "\n");
+  }
 }
 
 bool SocketSetNonBlocking(int sock, bool is_non_blocking) {
@@ -250,7 +366,7 @@
       ssize_t n;
 
       do {
-        n = read(0, buffer, sizeof(buffer));
+        n = BORINGSSL_READ(0, buffer, sizeof(buffer));
       } while (n == -1 && errno == EINTR);
 
       if (n == 0) {
@@ -304,7 +420,7 @@
 
       ssize_t n;
       do {
-        n = write(1, buffer, ssl_ret);
+        n = BORINGSSL_WRITE(1, buffer, ssl_ret);
       } while (n == -1 && errno == EINTR);
 
       if (n != ssl_ret) {
@@ -314,3 +430,194 @@
     }
   }
 }
+
+// SocketLineReader wraps a small buffer around a socket for line-orientated
+// protocols.
+class SocketLineReader {
+ public:
+  explicit SocketLineReader(int sock) : sock_(sock) {}
+
+  // Next reads a '\n'- or '\r\n'-terminated line from the socket and, on
+  // success, sets |*out_line| to it and returns true. Otherwise it returns
+  // false.
+  bool Next(std::string *out_line) {
+    for (;;) {
+      for (size_t i = 0; i < buf_len_; i++) {
+        if (buf_[i] != '\n') {
+          continue;
+        }
+
+        size_t length = i;
+        if (i > 0 && buf_[i - 1] == '\r') {
+          length--;
+        }
+
+        out_line->assign(buf_, length);
+        buf_len_ -= i + 1;
+        OPENSSL_memmove(buf_, &buf_[i + 1], buf_len_);
+
+        return true;
+      }
+
+      if (buf_len_ == sizeof(buf_)) {
+        fprintf(stderr, "Received line too long!\n");
+        return false;
+      }
+
+      ssize_t n;
+      do {
+        n = recv(sock_, &buf_[buf_len_], sizeof(buf_) - buf_len_, 0);
+      } while (n == -1 && errno == EINTR);
+
+      if (n < 0) {
+        fprintf(stderr, "Read error from socket\n");
+        return false;
+      }
+
+      buf_len_ += n;
+    }
+  }
+
+  // ReadSMTPReply reads one or more lines that make up an SMTP reply. On
+  // success, it sets |*out_code| to the reply's code (e.g. 250) and
+  // |*out_content| to the body of the reply (e.g. "OK") and returns true.
+  // Otherwise it returns false.
+  //
+  // See https://tools.ietf.org/html/rfc821#page-48
+  bool ReadSMTPReply(unsigned *out_code, std::string *out_content) {
+    out_content->clear();
+
+    // kMaxLines is the maximum number of lines that we'll accept in an SMTP
+    // reply.
+    static const unsigned kMaxLines = 512;
+    for (unsigned i = 0; i < kMaxLines; i++) {
+      std::string line;
+      if (!Next(&line)) {
+        return false;
+      }
+
+      if (line.size() < 4) {
+        fprintf(stderr, "Short line from SMTP server: %s\n", line.c_str());
+        return false;
+      }
+
+      const std::string code_str = line.substr(0, 3);
+      char *endptr;
+      const unsigned long code = strtoul(code_str.c_str(), &endptr, 10);
+      if (*endptr || code > UINT_MAX) {
+        fprintf(stderr, "Failed to parse code from line: %s\n", line.c_str());
+        return false;
+      }
+
+      if (i == 0) {
+        *out_code = code;
+      } else if (code != *out_code) {
+        fprintf(stderr,
+                "Reply code varied within a single reply: was %u, now %u\n",
+                *out_code, static_cast<unsigned>(code));
+        return false;
+      }
+
+      if (line[3] == ' ') {
+        // End of reply.
+        *out_content += line.substr(4, std::string::npos);
+        return true;
+      } else if (line[3] == '-') {
+        // Another line of reply will follow this one.
+        *out_content += line.substr(4, std::string::npos);
+        out_content->push_back('\n');
+      } else {
+        fprintf(stderr, "Bad character after code in SMTP reply: %s\n",
+                line.c_str());
+        return false;
+      }
+    }
+
+    fprintf(stderr, "Rejected SMTP reply of more then %u lines\n", kMaxLines);
+    return false;
+  }
+
+ private:
+  const int sock_;
+  char buf_[512];
+  size_t buf_len_ = 0;
+};
+
+// SendAll writes |data_len| bytes from |data| to |sock|. It returns true on
+// success and false otherwise.
+static bool SendAll(int sock, const char *data, size_t data_len) {
+  size_t done = 0;
+
+  while (done < data_len) {
+    ssize_t n;
+    do {
+      n = send(sock, &data[done], data_len - done, 0);
+    } while (n == -1 && errno == EINTR);
+
+    if (n < 0) {
+      fprintf(stderr, "Error while writing to socket\n");
+      return false;
+    }
+
+    done += n;
+  }
+
+  return true;
+}
+
+bool DoSMTPStartTLS(int sock) {
+  SocketLineReader line_reader(sock);
+
+  unsigned code_220 = 0;
+  std::string reply_220;
+  if (!line_reader.ReadSMTPReply(&code_220, &reply_220)) {
+    return false;
+  }
+
+  if (code_220 != 220) {
+    fprintf(stderr, "Expected 220 line from SMTP server but got code %u\n",
+            code_220);
+    return false;
+  }
+
+  static const char kHelloLine[] = "EHLO BoringSSL\r\n";
+  if (!SendAll(sock, kHelloLine, sizeof(kHelloLine) - 1)) {
+    return false;
+  }
+
+  unsigned code_250 = 0;
+  std::string reply_250;
+  if (!line_reader.ReadSMTPReply(&code_250, &reply_250)) {
+    return false;
+  }
+
+  if (code_250 != 250) {
+    fprintf(stderr, "Expected 250 line after EHLO but got code %u\n", code_250);
+    return false;
+  }
+
+  // https://tools.ietf.org/html/rfc1869#section-4.3
+  if (("\n" + reply_250 + "\n").find("\nSTARTTLS\n") == std::string::npos) {
+    fprintf(stderr, "Server does not support STARTTLS\n");
+    return false;
+  }
+
+  static const char kSTARTTLSLine[] = "STARTTLS\r\n";
+  if (!SendAll(sock, kSTARTTLSLine, sizeof(kSTARTTLSLine) - 1)) {
+    return false;
+  }
+
+  if (!line_reader.ReadSMTPReply(&code_220, &reply_220)) {
+    return false;
+  }
+
+  if (code_220 != 220) {
+    fprintf(
+        stderr,
+        "Expected 220 line from SMTP server after STARTTLS, but got code %u\n",
+        code_220);
+    return false;
+  }
+
+  return true;
+}
diff --git a/src/tool/transport_common.h b/src/tool/transport_common.h
index b701015..7595f45 100644
--- a/src/tool/transport_common.h
+++ b/src/tool/transport_common.h
@@ -31,6 +31,8 @@
 // It returns true on success and false otherwise.
 bool Accept(int *out_sock, const std::string &port);
 
+bool VersionFromString(uint16_t *out_version, const std::string &version);
+
 void PrintConnectionInfo(const SSL *ssl);
 
 bool SocketSetNonBlocking(int sock, bool is_non_blocking);
@@ -39,5 +41,8 @@
 
 bool TransferData(SSL *ssl, int sock);
 
+// DoSMTPStartTLS performs the SMTP STARTTLS mini-protocol over |sock|. It
+// returns true on success and false otherwise.
+bool DoSMTPStartTLS(int sock);
 
 #endif  /* !OPENSSL_HEADER_TOOL_TRANSPORT_COMMON_H */
diff --git a/src/util/BUILD.toplevel b/src/util/BUILD.toplevel
new file mode 100644
index 0000000..be3fd96
--- /dev/null
+++ b/src/util/BUILD.toplevel
@@ -0,0 +1,130 @@
+# Copyright (c) 2016, Google Inc.
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+licenses(["notice"])
+
+exports_files(["LICENSE"])
+
+load(
+    ":BUILD.generated.bzl",
+    "crypto_headers",
+    "crypto_internal_headers",
+    "crypto_sources",
+    "crypto_sources_linux_x86_64",
+    "crypto_sources_mac_x86_64",
+    "ssl_headers",
+    "ssl_internal_headers",
+    "ssl_c_sources",
+    "ssl_cc_sources",
+    "tool_sources",
+    "tool_headers",
+)
+
+config_setting(
+    name = "linux_x86_64",
+    values = {"cpu": "k8"},
+)
+
+config_setting(
+    name = "mac_x86_64",
+    values = {"cpu": "darwin"},
+)
+
+boringssl_copts = [
+    # Assembler option --noexecstack adds .note.GNU-stack to each object to
+    # ensure that binaries can be built with non-executable stack.
+    "-Wa,--noexecstack",
+
+    # This is needed on Linux systems (at least) to get rwlock in pthread.
+    "-D_XOPEN_SOURCE=700",
+
+    # This list of warnings should match those in the top-level CMakeLists.txt.
+    "-Wall",
+    "-Werror",
+    "-Wformat=2",
+    "-Wsign-compare",
+    "-Wmissing-field-initializers",
+    "-Wwrite-strings",
+    "-Wshadow",
+    "-fno-common",
+
+    # Modern build environments should be able to set this to use atomic
+    # operations for reference counting rather than locks. However, it's
+    # known not to work on some Android builds.
+    # "-DOPENSSL_C11_ATOMIC",
+] + select({
+    ":linux_x86_64": [],
+    ":mac_x86_64": [],
+    "//conditions:default": ["-DOPENSSL_NO_ASM"],
+})
+
+crypto_sources_asm = select({
+    ":linux_x86_64": crypto_sources_linux_x86_64,
+    ":mac_x86_64": crypto_sources_mac_x86_64,
+    "//conditions:default": [],
+})
+
+# For C targets only (not C++), compile with C11 support.
+boringssl_copts_c11 = boringssl_copts + [
+    "-std=c11",
+    "-Wmissing-prototypes",
+    "-Wold-style-definition",
+    "-Wstrict-prototypes",
+]
+
+# For C targets only (not C++), compile with C11 support.
+boringssl_copts_cxx = boringssl_copts + [
+    "-std=c++11",
+    "-Wmissing-declarations",
+]
+
+cc_library(
+    name = "crypto",
+    srcs = crypto_sources + crypto_internal_headers + crypto_sources_asm,
+    hdrs = crypto_headers,
+    copts = boringssl_copts_c11,
+    includes = ["src/include"],
+    linkopts = select({
+        ":mac_x86_64": [],
+        "//conditions:default": ["-lpthread"],
+    }),
+    visibility = ["//visibility:public"],
+)
+
+cc_library(
+    name = "ssl",
+    srcs = ssl_c_sources + ssl_internal_headers,
+    hdrs = ssl_headers,
+    copts = boringssl_copts_c11,
+    includes = ["src/include"],
+    visibility = ["//visibility:public"],
+    deps = [":crypto", ":ssl_cc"],
+)
+
+cc_library(
+    name = "ssl_cc",
+    srcs = ssl_cc_sources + ssl_internal_headers,
+    hdrs = ssl_headers,
+    copts = boringssl_copts,
+    includes = ["src/include"],
+    deps = [":crypto"],
+)
+
+cc_binary(
+    name = "bssl",
+    srcs = tool_sources + tool_headers,
+    copts = boringssl_copts_cxx,
+    visibility = ["//visibility:public"],
+    deps = [":ssl"],
+)
diff --git a/src/util/all_tests.go b/src/util/all_tests.go
index 566c3f7..3cf2320 100644
--- a/src/util/all_tests.go
+++ b/src/util/all_tests.go
@@ -24,6 +24,7 @@
 	"path"
 	"strconv"
 	"strings"
+	"sync"
 	"syscall"
 	"time"
 )
@@ -32,14 +33,28 @@
 
 var (
 	useValgrind     = flag.Bool("valgrind", false, "If true, run code under valgrind")
+	useCallgrind    = flag.Bool("callgrind", false, "If true, run code under valgrind to generate callgrind traces.")
 	useGDB          = flag.Bool("gdb", false, "If true, run BoringSSL code under gdb")
+	useSDE          = flag.Bool("sde", false, "If true, run BoringSSL code under Intel's SDE for each supported chip")
 	buildDir        = flag.String("build-dir", "build", "The build directory to run the tests from.")
+	numWorkers      = flag.Int("num-workers", 1, "Runs the given number of workers when testing.")
 	jsonOutput      = flag.String("json-output", "", "The file to output JSON results to.")
 	mallocTest      = flag.Int64("malloc-test", -1, "If non-negative, run each test with each malloc in turn failing from the given number onwards.")
 	mallocTestDebug = flag.Bool("malloc-test-debug", false, "If true, ask each test to abort rather than fail a malloc. This can be used with a specific value for --malloc-test to identity the malloc failing that is causing problems.")
 )
 
-type test []string
+type test struct {
+	args []string
+	// cpu, if not empty, contains an Intel CPU code to simulate. Run
+	// `sde64 -help` to get a list of these codes.
+	cpu string
+}
+
+type result struct {
+	Test   test
+	Passed bool
+	Error  error
+}
 
 // testOutput is a representation of Chromium's JSON test result format. See
 // https://www.chromium.org/developers/the-json-test-results-format
@@ -58,6 +73,27 @@
 	IsUnexpected bool   `json:"is_unexpected"`
 }
 
+// sdeCPUs contains a list of CPU code that we run all tests under when *useSDE
+// is true.
+var sdeCPUs = []string{
+	"p4p", // Pentium4 Prescott
+	"mrm", // Merom
+	"pnr", // Penryn
+	"nhm", // Nehalem
+	"wsm", // Westmere
+	"snb", // Sandy Bridge
+	"ivb", // Ivy Bridge
+	"hsw", // Haswell
+	"bdw", // Broadwell
+	"skx", // Skylake Server
+	"skl", // Skylake Client
+	"cnl", // Cannonlake
+	"knl", // Knights Landing
+	"slt", // Saltwell
+	"slm", // Silvermont
+	"glm", // Goldmont
+}
+
 func newTestOutput() *testOutput {
 	return &testOutput{
 		Version:           3,
@@ -95,7 +131,7 @@
 }
 
 func valgrindOf(dbAttach bool, path string, args ...string) *exec.Cmd {
-	valgrindArgs := []string{"--error-exitcode=99", "--track-origins=yes", "--leak-check=full"}
+	valgrindArgs := []string{"--error-exitcode=99", "--track-origins=yes", "--leak-check=full", "--quiet"}
 	if dbAttach {
 		valgrindArgs = append(valgrindArgs, "--db-attach=yes", "--db-command=xterm -e gdb -nw %f %p")
 	}
@@ -105,6 +141,14 @@
 	return exec.Command("valgrind", valgrindArgs...)
 }
 
+func callgrindOf(path string, args ...string) *exec.Cmd {
+	valgrindArgs := []string{"-q", "--tool=callgrind", "--dump-instr=yes", "--collect-jumps=yes", "--callgrind-out-file=" + *buildDir + "/callgrind/callgrind.out.%p"}
+	valgrindArgs = append(valgrindArgs, path)
+	valgrindArgs = append(valgrindArgs, args...)
+
+	return exec.Command("valgrind", valgrindArgs...)
+}
+
 func gdbOf(path string, args ...string) *exec.Cmd {
 	xtermArgs := []string{"-e", "gdb", "--args"}
 	xtermArgs = append(xtermArgs, path)
@@ -113,6 +157,12 @@
 	return exec.Command("xterm", xtermArgs...)
 }
 
+func sdeOf(cpu, path string, args ...string) *exec.Cmd {
+	sdeArgs := []string{"-" + cpu, "--", path}
+	sdeArgs = append(sdeArgs, args...)
+	return exec.Command("sde", sdeArgs...)
+}
+
 type moreMallocsError struct{}
 
 func (moreMallocsError) Error() string {
@@ -122,20 +172,23 @@
 var errMoreMallocs = moreMallocsError{}
 
 func runTestOnce(test test, mallocNumToFail int64) (passed bool, err error) {
-	prog := path.Join(*buildDir, test[0])
-	args := test[1:]
+	prog := path.Join(*buildDir, test.args[0])
+	args := test.args[1:]
 	var cmd *exec.Cmd
 	if *useValgrind {
 		cmd = valgrindOf(false, prog, args...)
+	} else if *useCallgrind {
+		cmd = callgrindOf(prog, args...)
 	} else if *useGDB {
 		cmd = gdbOf(prog, args...)
+	} else if *useSDE {
+		cmd = sdeOf(test.cpu, prog, args...)
 	} else {
 		cmd = exec.Command(prog, args...)
 	}
-	var stdoutBuf bytes.Buffer
-	var stderrBuf bytes.Buffer
-	cmd.Stdout = &stdoutBuf
-	cmd.Stderr = &stderrBuf
+	var outBuf bytes.Buffer
+	cmd.Stdout = &outBuf
+	cmd.Stderr = &outBuf
 	if mallocNumToFail >= 0 {
 		cmd.Env = os.Environ()
 		cmd.Env = append(cmd.Env, "MALLOC_NUMBER_TO_FAIL="+strconv.FormatInt(mallocNumToFail, 10))
@@ -154,18 +207,26 @@
 				return false, errMoreMallocs
 			}
 		}
-		fmt.Print(string(stderrBuf.Bytes()))
+		fmt.Print(string(outBuf.Bytes()))
 		return false, err
 	}
-	fmt.Print(string(stderrBuf.Bytes()))
 
 	// Account for Windows line-endings.
-	stdout := bytes.Replace(stdoutBuf.Bytes(), []byte("\r\n"), []byte("\n"), -1)
+	stdout := bytes.Replace(outBuf.Bytes(), []byte("\r\n"), []byte("\n"), -1)
 
 	if bytes.HasSuffix(stdout, []byte("PASS\n")) &&
 		(len(stdout) == 5 || stdout[len(stdout)-6] == '\n') {
 		return true, nil
 	}
+
+	// Also accept a googletest-style pass line. This is left here in
+	// transition until the tests are all converted and this script made
+	// unnecessary.
+	if bytes.Contains(stdout, []byte("\n[  PASSED  ]")) {
+		return true, nil
+	}
+
+	fmt.Print(string(outBuf.Bytes()))
 	return false, nil
 }
 
@@ -189,12 +250,12 @@
 // relevant to the test's uniqueness.
 func shortTestName(test test) string {
 	var args []string
-	for _, arg := range test {
-		if test[0] == "crypto/evp/evp_test" || !strings.HasSuffix(arg, ".txt") {
+	for _, arg := range test.args {
+		if test.args[0] == "crypto/evp/evp_test" || !strings.HasSuffix(arg, ".txt") {
 			args = append(args, arg)
 		}
 	}
-	return strings.Join(args, " ")
+	return strings.Join(args, " ") + test.cpuMsg()
 }
 
 // setWorkingDirectory walks up directories as needed until the current working
@@ -218,36 +279,85 @@
 	defer in.Close()
 
 	decoder := json.NewDecoder(in)
-	var result []test
-	if err := decoder.Decode(&result); err != nil {
+	var testArgs [][]string
+	if err := decoder.Decode(&testArgs); err != nil {
 		return nil, err
 	}
+
+	var result []test
+	for _, args := range testArgs {
+		result = append(result, test{args: args})
+	}
 	return result, nil
 }
 
+func worker(tests <-chan test, results chan<- result, done *sync.WaitGroup) {
+	defer done.Done()
+	for test := range tests {
+		passed, err := runTest(test)
+		results <- result{test, passed, err}
+	}
+}
+
+func (t test) cpuMsg() string {
+	if len(t.cpu) == 0 {
+		return ""
+	}
+
+	return fmt.Sprintf(" (for CPU %q)", t.cpu)
+}
+
 func main() {
 	flag.Parse()
 	setWorkingDirectory()
 
-	tests, err := parseTestConfig("util/all_tests.json")
+	testCases, err := parseTestConfig("util/all_tests.json")
 	if err != nil {
 		fmt.Printf("Failed to parse input: %s\n", err)
 		os.Exit(1)
 	}
 
+	var wg sync.WaitGroup
+	tests := make(chan test, *numWorkers)
+	results := make(chan result, *numWorkers)
+
+	for i := 0; i < *numWorkers; i++ {
+		wg.Add(1)
+		go worker(tests, results, &wg)
+	}
+
+	go func() {
+		for _, test := range testCases {
+			if *useSDE {
+				for _, cpu := range sdeCPUs {
+					testForCPU := test
+					testForCPU.cpu = cpu
+					tests <- testForCPU
+				}
+			} else {
+				tests <- test
+			}
+		}
+		close(tests)
+
+		wg.Wait()
+		close(results)
+	}()
+
 	testOutput := newTestOutput()
 	var failed []test
-	for _, test := range tests {
-		fmt.Printf("%s\n", strings.Join([]string(test), " "))
+	for testResult := range results {
+		test := testResult.Test
+		args := test.args
 
+		fmt.Printf("%s%s\n", strings.Join(args, " "), test.cpuMsg())
 		name := shortTestName(test)
-		passed, err := runTest(test)
-		if err != nil {
-			fmt.Printf("%s failed to complete: %s\n", test[0], err)
+		if testResult.Error != nil {
+			fmt.Printf("%s failed to complete: %s\n", args[0], testResult.Error)
 			failed = append(failed, test)
 			testOutput.addResult(name, "CRASHED")
-		} else if !passed {
-			fmt.Printf("%s failed to print PASS on the last line.\n", test[0])
+		} else if !testResult.Passed {
+			fmt.Printf("%s failed to print PASS on the last line.\n", args[0])
 			failed = append(failed, test)
 			testOutput.addResult(name, "FAIL")
 		} else {
@@ -262,9 +372,9 @@
 	}
 
 	if len(failed) > 0 {
-		fmt.Printf("\n%d of %d tests failed:\n", len(failed), len(tests))
+		fmt.Printf("\n%d of %d tests failed:\n", len(failed), len(testCases))
 		for _, test := range failed {
-			fmt.Printf("\t%s\n", strings.Join([]string(test), " "))
+			fmt.Printf("\t%s%s\n", strings.Join(test.args, ""), test.cpuMsg())
 		}
 		os.Exit(1)
 	}
diff --git a/src/util/all_tests.json b/src/util/all_tests.json
index c621799..a1ce5f2 100644
--- a/src/util/all_tests.json
+++ b/src/util/all_tests.json
@@ -1,17 +1,13 @@
 [
-	["crypto/aes/aes_test"],
+	["crypto/aes/aes_test", "crypto/aes/aes_tests.txt"],
 	["crypto/base64/base64_test"],
-	["crypto/bio/bio_test"],
-	["crypto/bn/bn_test"],
+	["crypto/bn/bn_test", "crypto/bn/bn_tests.txt"],
 	["crypto/bytestring/bytestring_test"],
 	["crypto/cipher/aead_test", "aes-128-gcm", "crypto/cipher/test/aes_128_gcm_tests.txt"],
-	["crypto/cipher/aead_test", "aes-128-key-wrap", "crypto/cipher/test/aes_128_key_wrap_tests.txt"],
 	["crypto/cipher/aead_test", "aes-256-gcm", "crypto/cipher/test/aes_256_gcm_tests.txt"],
-	["crypto/cipher/aead_test", "aes-256-key-wrap", "crypto/cipher/test/aes_256_key_wrap_tests.txt"],
+	["crypto/cipher/aead_test", "aes-128-gcm-siv", "crypto/cipher/test/aes_128_gcm_siv_tests.txt"],
+	["crypto/cipher/aead_test", "aes-256-gcm-siv", "crypto/cipher/test/aes_256_gcm_siv_tests.txt"],
 	["crypto/cipher/aead_test", "chacha20-poly1305", "crypto/cipher/test/chacha20_poly1305_tests.txt"],
-	["crypto/cipher/aead_test", "chacha20-poly1305-old", "crypto/cipher/test/chacha20_poly1305_old_tests.txt"],
-	["crypto/cipher/aead_test", "rc4-md5-tls", "crypto/cipher/test/rc4_md5_tls_tests.txt"],
-	["crypto/cipher/aead_test", "rc4-sha1-tls", "crypto/cipher/test/rc4_sha1_tls_tests.txt"],
 	["crypto/cipher/aead_test", "aes-128-cbc-sha1-tls", "crypto/cipher/test/aes_128_cbc_sha1_tls_tests.txt"],
 	["crypto/cipher/aead_test", "aes-128-cbc-sha1-tls-implicit-iv", "crypto/cipher/test/aes_128_cbc_sha1_tls_implicit_iv_tests.txt"],
 	["crypto/cipher/aead_test", "aes-128-cbc-sha256-tls", "crypto/cipher/test/aes_128_cbc_sha256_tls_tests.txt"],
@@ -21,41 +17,40 @@
 	["crypto/cipher/aead_test", "aes-256-cbc-sha384-tls", "crypto/cipher/test/aes_256_cbc_sha384_tls_tests.txt"],
 	["crypto/cipher/aead_test", "des-ede3-cbc-sha1-tls", "crypto/cipher/test/des_ede3_cbc_sha1_tls_tests.txt"],
 	["crypto/cipher/aead_test", "des-ede3-cbc-sha1-tls-implicit-iv", "crypto/cipher/test/des_ede3_cbc_sha1_tls_implicit_iv_tests.txt"],
-	["crypto/cipher/aead_test", "rc4-md5-ssl3", "crypto/cipher/test/rc4_md5_ssl3_tests.txt"],
-	["crypto/cipher/aead_test", "rc4-sha1-ssl3", "crypto/cipher/test/rc4_sha1_ssl3_tests.txt"],
 	["crypto/cipher/aead_test", "aes-128-cbc-sha1-ssl3", "crypto/cipher/test/aes_128_cbc_sha1_ssl3_tests.txt"],
 	["crypto/cipher/aead_test", "aes-256-cbc-sha1-ssl3", "crypto/cipher/test/aes_256_cbc_sha1_ssl3_tests.txt"],
 	["crypto/cipher/aead_test", "des-ede3-cbc-sha1-ssl3", "crypto/cipher/test/des_ede3_cbc_sha1_ssl3_tests.txt"],
 	["crypto/cipher/aead_test", "aes-128-ctr-hmac-sha256", "crypto/cipher/test/aes_128_ctr_hmac_sha256.txt"],
 	["crypto/cipher/aead_test", "aes-256-ctr-hmac-sha256", "crypto/cipher/test/aes_256_ctr_hmac_sha256.txt"],
-	["crypto/cipher/cipher_test", "crypto/cipher/test/cipher_test.txt"],
+	["crypto/cipher/cipher_test", "crypto/cipher/test/cipher_tests.txt"],
 	["crypto/cmac/cmac_test"],
-	["crypto/constant_time_test"],
+	["crypto/crypto_test"],
 	["crypto/curve25519/ed25519_test", "crypto/curve25519/ed25519_tests.txt"],
-	["crypto/curve25519/x25519_test"],
-	["crypto/dh/dh_test"],
+	["crypto/curve25519/spake25519_test"],
 	["crypto/digest/digest_test"],
-	["crypto/dsa/dsa_test"],
-	["crypto/ec/ec_test"],
 	["crypto/ec/example_mul"],
+	["crypto/ec/p256-x86_64_test", "crypto/ec/p256-x86_64_tests.txt"],
+	["crypto/ecdh/ecdh_test", "crypto/ecdh/ecdh_tests.txt"],
+	["crypto/ecdsa/ecdsa_sign_test", "crypto/ecdsa/ecdsa_sign_tests.txt"],
 	["crypto/ecdsa/ecdsa_test"],
-	["crypto/err/err_test"],
-	["crypto/evp/evp_extra_test"],
+	["crypto/ecdsa/ecdsa_verify_test", "crypto/ecdsa/ecdsa_verify_tests.txt"],
 	["crypto/evp/evp_test", "crypto/evp/evp_tests.txt"],
 	["crypto/evp/pbkdf_test"],
 	["crypto/hkdf/hkdf_test"],
 	["crypto/hmac/hmac_test", "crypto/hmac/hmac_tests.txt"],
 	["crypto/lhash/lhash_test"],
 	["crypto/modes/gcm_test"],
-	["crypto/pkcs8/pkcs8_test"],
+	["crypto/obj/obj_test"],
 	["crypto/pkcs8/pkcs12_test"],
-	["crypto/poly1305/poly1305_test", "crypto/poly1305/poly1305_test.txt"],
+	["crypto/pkcs8/pkcs8_test"],
+	["crypto/poly1305/poly1305_test", "crypto/poly1305/poly1305_tests.txt"],
+	["crypto/pool/pool_test"],
 	["crypto/refcount_test"],
-	["crypto/rsa/rsa_test"],
 	["crypto/thread_test"],
 	["crypto/x509/pkcs7_test"],
+	["crypto/x509/x509_test"],
 	["crypto/x509v3/tab_test"],
 	["crypto/x509v3/v3name_test"],
-	["ssl/pqueue/pqueue_test"],
+	["decrepit/decrepit_test"],
 	["ssl/ssl_test"]
 ]
diff --git a/src/util/bot/DEPS b/src/util/bot/DEPS
index 738fbd3..55eeb86 100644
--- a/src/util/bot/DEPS
+++ b/src/util/bot/DEPS
@@ -18,9 +18,21 @@
 
 deps = {
   'boringssl/util/bot/gyp':
-    Var('chromium_git') + '/external/gyp.git' + '@' + '4a9b712d5cb4a5ba7a9950128a7219569caf7263',
+    Var('chromium_git') + '/external/gyp.git' + '@' + 'e7079f0e0e14108ab0dba58728ff219637458563',
 }
 
+deps_os = {
+  'android': {
+    'boringssl/util/bot/android_tools':
+      Var('chromium_git') + '/android_tools.git' + '@' + 'b43a6a289a7588b1769814f04dd6c7d7176974cc',
+  },
+}
+
+recursedeps = [
+  # android_tools pulls in the NDK from a separate repository.
+  'boringssl/util/bot/android_tools',
+]
+
 hooks = [
   {
     'name': 'cmake_linux64',
@@ -92,8 +104,6 @@
                 'boringssl/util/bot/update_clang.py',
     ],
   },
-  # TODO(davidben): Only extract archives when they've changed. Extracting perl
-  # on Windows is a significant part of the cycle time.
   {
     'name': 'cmake_linux64_extract',
     'pattern': '.',
diff --git a/src/util/bot/UPDATING b/src/util/bot/UPDATING
new file mode 100644
index 0000000..2007d46
--- /dev/null
+++ b/src/util/bot/UPDATING
@@ -0,0 +1,47 @@
+This directory consumes tools from other repositories for use on the
+bots. To update to newer revisions, follow these instructions:
+
+DEPS: Set all revisions to those used in Chromium, found at
+   https://chromium.googlesource.com/chromium/src/+/master/DEPS (Search for the
+   corresponding repository name.)
+
+go/bootstrap.py: Set TOOLSET_VERSION to the latest release of Go, found at
+    https://golang.org/dl/.
+
+update_clang.py: Set CLANG_REVISION and CLANG_SUB_REVISION to the values used in
+    Chromium, found at
+    https://chromium.googlesource.com/chromium/src/+/master/tools/clang/scripts/update.py
+
+vs_toolchain.py: Set the hash in TOOLCHAIN_HASH to the toolchain
+    used in Chromium, found at _GetDesiredVsToolchainHashes
+    https://chromium.googlesource.com/chromium/src/+/master/build/vs_toolchain.py
+    This may require taking other updates to that file. If updating MSVS
+    version, also update TOOLCHAIN_VERSION accordingly.
+
+The .sha1 files correspond to files downloaded from Google Cloud Storage. To
+update, place the updated files in their intended location and run:
+
+    upload_to_google_storage.py -b chromium-tools FILE
+
+cmake-linux64.tar.gz: Download the latest CMake source tarball, found at
+    https://cmake.org/download/. Build it with:
+
+        ./bootstrap --prefix=$PWD/cmake-linux64 && make && make install
+        tar -czf cmake-linux64.tar.gz cmake-linux64/
+
+cmake-mac.tar.gz: Follow the same instructions as above on a Mac, but replace
+    cmake-linux64 with cmake-mac.
+
+cmake-win32.zip: Update to the latest prebuilt release of CMake, found at
+    https://cmake.org/download/. Use the file labeled "Windows ZIP". The
+    download will be named cmake-VERSION-win32-x86.zip.
+
+perl-win32.zip: Update to the latest 32-bit prebuilt "PortableZip" edition of
+    Strawberry Perl, found at http://strawberryperl.com/releases.html. The
+    download will be named strawberry-perl-VERSION-32bit-portable.zip.
+
+yasm-win32.exe: Update to the appropriate release of Yasm. Use the same version
+    as Chromium, found at
+    https://chromium.googlesource.com/chromium/src/+/master/third_party/yasm/README.chromium
+    Use the release at http://yasm.tortall.net/Download.html labeled
+    "Win32 .exe". The download will be named yasm-VERSION-win32.exe.
diff --git a/src/util/bot/cmake-linux64.tar.gz.sha1 b/src/util/bot/cmake-linux64.tar.gz.sha1
index 6a8aa1c..404570f 100644
--- a/src/util/bot/cmake-linux64.tar.gz.sha1
+++ b/src/util/bot/cmake-linux64.tar.gz.sha1
@@ -1 +1 @@
-32cd1d5fe84ae569dbb36f5767650d62efb8be38
\ No newline at end of file
+6ea4ad07a4bab113ea74c45fafb14b8d0b0feab5
\ No newline at end of file
diff --git a/src/util/bot/cmake-mac.tar.gz.sha1 b/src/util/bot/cmake-mac.tar.gz.sha1
index cb7251b..19c9b61 100644
--- a/src/util/bot/cmake-mac.tar.gz.sha1
+++ b/src/util/bot/cmake-mac.tar.gz.sha1
@@ -1 +1 @@
-310df6945ae7f8c9da559d22f5794ee8e578a663
\ No newline at end of file
+f3166dab96234c9516ece56dc2851bf4c8e70fe8
\ No newline at end of file
diff --git a/src/util/bot/cmake-win32.zip.sha1 b/src/util/bot/cmake-win32.zip.sha1
index 9196b58..6bb460e 100644
--- a/src/util/bot/cmake-win32.zip.sha1
+++ b/src/util/bot/cmake-win32.zip.sha1
@@ -1 +1 @@
-e9493171de0edd8879755aa7229a701010a19561
\ No newline at end of file
+ed4e1939d246374b0bae724a1a4200fd60e7efe8
\ No newline at end of file
diff --git a/src/util/bot/extract.py b/src/util/bot/extract.py
index 77603c0..e36ce99 100644
--- a/src/util/bot/extract.py
+++ b/src/util/bot/extract.py
@@ -15,6 +15,7 @@
 """Extracts archives."""
 
 
+import hashlib
 import optparse
 import os
 import os.path
@@ -78,6 +79,22 @@
     # Skip archives that weren't downloaded.
     return 0
 
+  with open(archive) as f:
+    sha256 = hashlib.sha256()
+    while True:
+      chunk = f.read(1024 * 1024)
+      if not chunk:
+        break
+      sha256.update(chunk)
+    digest = sha256.hexdigest()
+
+  stamp_path = os.path.join(output, ".boringssl_archive_digest")
+  if os.path.exists(stamp_path):
+    with open(stamp_path) as f:
+      if f.read().strip() == digest:
+        print "Already up-to-date."
+        return 0
+
   if archive.endswith('.zip'):
     entries = IterateZip(archive)
   elif archive.endswith('.tar.gz'):
@@ -129,9 +146,10 @@
   finally:
     entries.close()
 
-  if num_extracted % 100 == 0:
-    print "Done. Extracted %d files." % (num_extracted,)
+  with open(stamp_path, 'w') as f:
+    f.write(digest)
 
+  print "Done. Extracted %d files." % (num_extracted,)
   return 0
 
 
diff --git a/src/util/bot/go/bootstrap.py b/src/util/bot/go/bootstrap.py
index 4a52d9e..bb64e25 100755
--- a/src/util/bot/go/bootstrap.py
+++ b/src/util/bot/go/bootstrap.py
@@ -45,7 +45,7 @@
 EXE_SFX = '.exe' if sys.platform == 'win32' else ''
 
 # Pinned version of Go toolset to download.
-TOOLSET_VERSION = 'go1.5.1'
+TOOLSET_VERSION = 'go1.8'
 
 # Platform dependent portion of a download URL. See http://golang.org/dl/.
 TOOLSET_VARIANTS = {
diff --git a/src/util/bot/perl-win32.zip.sha1 b/src/util/bot/perl-win32.zip.sha1
index a5559d8..8874fbb 100644
--- a/src/util/bot/perl-win32.zip.sha1
+++ b/src/util/bot/perl-win32.zip.sha1
@@ -1 +1 @@
-ab6e7aee6a915c4d820b86f5227094763b649fce
\ No newline at end of file
+3db2b4964d56f6e23cc48ced40a6cee05419a0af
\ No newline at end of file
diff --git a/src/util/bot/update_clang.py b/src/util/bot/update_clang.py
index 1824393..7e91113 100644
--- a/src/util/bot/update_clang.py
+++ b/src/util/bot/update_clang.py
@@ -22,7 +22,7 @@
 # CLANG_REVISION and CLANG_SUB_REVISION determine the build of clang
 # to use. These should be synced with tools/clang/scripts/update.py in
 # Chromium.
-CLANG_REVISION = "233105"
+CLANG_REVISION = "296320"
 CLANG_SUB_REVISION = "1"
 
 PACKAGE_VERSION = "%s-%s" % (CLANG_REVISION, CLANG_SUB_REVISION)
diff --git a/src/util/bot/vs_toolchain.py b/src/util/bot/vs_toolchain.py
index 2a54b9e..2e87272 100644
--- a/src/util/bot/vs_toolchain.py
+++ b/src/util/bot/vs_toolchain.py
@@ -18,12 +18,16 @@
 import gyp
 
 
+TOOLCHAIN_VERSION = '2015'
+TOOLCHAIN_HASH = 'd3cb0e37bdd120ad0ac4650b674b09e81be45616'
+
+
 def SetEnvironmentAndGetRuntimeDllDirs():
   """Sets up os.environ to use the depot_tools VS toolchain with gyp, and
   returns the location of the VS runtime DLLs so they can be copied into
   the output directory after gyp generation.
   """
-  vs2013_runtime_dll_dirs = None
+  vs_runtime_dll_dirs = None
   depot_tools_win_toolchain = \
       bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1')))
   if sys.platform in ('win32', 'cygwin') and depot_tools_win_toolchain:
@@ -41,7 +45,7 @@
     # TODO(scottmg): The order unfortunately matters in these. They should be
     # split into separate keys for x86 and x64. (See CopyVsRuntimeDlls call
     # below). http://crbug.com/345992
-    vs2013_runtime_dll_dirs = toolchain_data['runtime_dirs']
+    vs_runtime_dll_dirs = toolchain_data['runtime_dirs']
 
     os.environ['GYP_MSVS_OVERRIDE_PATH'] = toolchain
     os.environ['GYP_MSVS_VERSION'] = version
@@ -56,16 +60,9 @@
     os.environ['WINDOWSSDKDIR'] = win_sdk
     os.environ['WDK_DIR'] = wdk
     # Include the VS runtime in the PATH in case it's not machine-installed.
-    runtime_path = ';'.join(vs2013_runtime_dll_dirs)
+    runtime_path = ';'.join(vs_runtime_dll_dirs)
     os.environ['PATH'] = runtime_path + ';' + os.environ['PATH']
-  return vs2013_runtime_dll_dirs
-
-
-def _GetDesiredVsToolchainHashes():
-  """Load a list of SHA1s corresponding to the toolchains that we want installed
-  to build with."""
-  # Use Chromium's VS2013.
-  return ['ee7d718ec60c2dc5d255bbe325909c2021a7efef']
+  return vs_runtime_dll_dirs
 
 
 def FindDepotTools():
@@ -85,13 +82,16 @@
       bool(int(os.environ.get('DEPOT_TOOLS_WIN_TOOLCHAIN', '1')))
   if sys.platform in ('win32', 'cygwin') and depot_tools_win_toolchain:
     depot_tools_path = FindDepotTools()
+    # Necessary so that get_toolchain_if_necessary.py will put the VS toolkit
+    # in the correct directory.
+    os.environ['GYP_MSVS_VERSION'] = TOOLCHAIN_VERSION
     get_toolchain_args = [
         sys.executable,
         os.path.join(depot_tools_path,
                     'win_toolchain',
                     'get_toolchain_if_necessary.py'),
-        '--output-json', json_data_file,
-      ] + _GetDesiredVsToolchainHashes()
+        '--output-json', json_data_file, TOOLCHAIN_HASH,
+      ]
     subprocess.check_call(get_toolchain_args)
 
   return 0
diff --git a/src/util/diff_asm.go b/src/util/diff_asm.go
new file mode 100644
index 0000000..0a0888b
--- /dev/null
+++ b/src/util/diff_asm.go
@@ -0,0 +1,112 @@
+/* Copyright (c) 2016, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+package main
+
+import (
+	"flag"
+	"fmt"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"strings"
+	"syscall"
+)
+
+var (
+	boringsslDir = flag.String("boringssl", ".", "The path to the BoringSSL checkout.")
+	opensslDir   = flag.String("openssl", filepath.Join("..", "openssl"), "The path to the OpenSSL checkout.")
+)
+
+func mapName(path string) string {
+	switch filepath.ToSlash(path) {
+	case "crypto/rand/asm/rdrand-x86_64.pl":
+		return ""
+	case "crypto/ec/asm/p256-x86_64-asm.pl":
+		return filepath.FromSlash("crypto/ec/asm/ecp_nistz256-x86_64.pl")
+	}
+	return path
+}
+
+func diff(from, to string) error {
+	cmd := exec.Command("diff", "-u", "--", from, to)
+	cmd.Stdout = os.Stdout
+	cmd.Stderr = os.Stderr
+	err := cmd.Run()
+	// diff returns exit code 1 if the files differ but it was otherwise
+	// successful.
+	if exitError, ok := err.(*exec.ExitError); ok && exitError.Sys().(syscall.WaitStatus).ExitStatus() == 1 {
+		return nil
+	}
+	return err
+}
+
+func main() {
+	flag.Usage = func() {
+		fmt.Fprintf(os.Stderr, "Usage: diff_asm [flag...] [filter...]\n")
+		fmt.Fprintf(os.Stderr, "Filter arguments limit to assembly files which match arguments.\n")
+		fmt.Fprintf(os.Stderr, "If not using a filter, piping to `diffstat` may be useful.\n\n")
+		flag.PrintDefaults()
+	}
+	flag.Parse()
+
+	// Find all the assembly files.
+	var files []string
+	err := filepath.Walk(*boringsslDir, func(path string, info os.FileInfo, err error) error {
+		if err != nil {
+			return nil
+		}
+
+		path, err = filepath.Rel(*boringsslDir, path)
+		if err != nil {
+			return err
+		}
+
+		dir := filepath.Base(filepath.Dir(path))
+		if !info.IsDir() && (dir == "asm" || dir == "perlasm") && strings.HasSuffix(filepath.Base(path), ".pl") {
+			files = append(files, path)
+		}
+
+		return nil
+	})
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "Error finding assembly: %s\n", err)
+		os.Exit(1)
+	}
+
+	for _, file := range files {
+		opensslFile := mapName(file)
+		if len(opensslFile) == 0 {
+			continue
+		}
+
+		if flag.NArg() > 0 {
+			var found bool
+			for _, arg := range flag.Args() {
+				if strings.Contains(file, arg) {
+					found = true
+					break
+				}
+			}
+			if !found {
+				continue
+			}
+		}
+
+		if err := diff(filepath.Join(*opensslDir, opensslFile), filepath.Join(*boringsslDir, file)); err != nil {
+			fmt.Fprintf(os.Stderr, "Error comparing %s: %s\n", file, err)
+			os.Exit(1)
+		}
+	}
+}
diff --git a/src/util/doc.config b/src/util/doc.config
index cbee543..f7e8baa 100644
--- a/src/util/doc.config
+++ b/src/util/doc.config
@@ -14,9 +14,9 @@
       "include/openssl/lhash.h",
       "include/openssl/mem.h",
       "include/openssl/obj.h",
+      "include/openssl/pool.h",
       "include/openssl/rand.h",
-      "include/openssl/stack.h",
-      "include/openssl/time_support.h"
+      "include/openssl/stack.h"
     ]
   },{
     "Name": "Low-level crypto primitives",
@@ -33,6 +33,7 @@
       "include/openssl/ecdh.h",
       "include/openssl/ecdsa.h",
       "include/openssl/engine.h",
+      "include/openssl/hkdf.h",
       "include/openssl/hmac.h",
       "include/openssl/md5.h",
       "include/openssl/rc4.h",
diff --git a/src/util/doc.css b/src/util/doc.css
index ab653e4..a868e44 100644
--- a/src/util/doc.css
+++ b/src/util/doc.css
@@ -7,12 +7,15 @@
 
 h2 {
   font-family: monospace;
-  margin-bottom: 2em;
   background-color: #b2c9db;
   padding: 7px;
   border-radius: 7px;
 }
 
+div.title {
+  margin-bottom: 2em;
+}
+
 ol {
   list-style: none;
   margin-bottom: 4em;
diff --git a/src/util/doc.go b/src/util/doc.go
index 7d15d9b..987794c 100644
--- a/src/util/doc.go
+++ b/src/util/doc.go
@@ -139,7 +139,7 @@
 }
 
 func extractDecl(lines []string, lineNo int) (decl string, rest []string, restLineNo int, err error) {
-	if len(lines) == 0 {
+	if len(lines) == 0 || len(lines[0]) == 0 {
 		return "", lines, lineNo, nil
 	}
 
@@ -203,15 +203,28 @@
 	for strings.HasPrefix(decl, "#if") || strings.HasPrefix(decl, "#elif") {
 		decl = skipLine(decl)
 	}
-	if strings.HasPrefix(decl, "struct ") {
+
+	if strings.HasPrefix(decl, "typedef ") {
 		return "", false
 	}
-	if strings.HasPrefix(decl, "#define ") {
-		// This is a preprocessor #define. The name is the next symbol.
-		decl = strings.TrimPrefix(decl, "#define ")
+
+	for _, prefix := range []string{"struct ", "enum ", "#define "} {
+		if !strings.HasPrefix(decl, prefix) {
+			continue
+		}
+
+		decl = strings.TrimPrefix(decl, prefix)
+
 		for len(decl) > 0 && decl[0] == ' ' {
 			decl = decl[1:]
 		}
+
+		// struct and enum types can be the return type of a
+		// function.
+		if prefix[0] != '#' && strings.Index(decl, "{") == -1 {
+			break
+		}
+
 		i := strings.IndexAny(decl, "( ")
 		if i < 0 {
 			return "", false
@@ -261,13 +274,12 @@
 		return nil, err
 	}
 
-	lineNo := 0
+	lineNo := 1
 	found := false
 	for i, line := range lines {
-		lineNo++
 		if line == cppGuard {
 			lines = lines[i+1:]
-			lineNo++
+			lineNo += i + 1
 			found = true
 			break
 		}
@@ -289,9 +301,9 @@
 	}
 
 	for i, line := range lines {
-		lineNo++
 		if len(line) > 0 {
 			lines = lines[i:]
+			lineNo += i
 			break
 		}
 	}
@@ -377,6 +389,7 @@
 			if len(lines) == 0 {
 				return nil, errors.New("expected decl at EOF")
 			}
+			declLineNo := lineNo
 			decl, lines, lineNo, err = extractDecl(lines, lineNo)
 			if err != nil {
 				return nil, err
@@ -396,10 +409,12 @@
 				// detected by starting with “The” or “These”.
 				if len(comment) > 0 &&
 					!strings.HasPrefix(comment[0], name) &&
+					!strings.HasPrefix(comment[0], "A "+name) &&
+					!strings.HasPrefix(comment[0], "An "+name) &&
 					!strings.HasPrefix(decl, "#define ") &&
 					!strings.HasPrefix(comment[0], "The ") &&
 					!strings.HasPrefix(comment[0], "These ") {
-					return nil, fmt.Errorf("Comment for %q doesn't seem to match just above %s:%d\n", name, path, lineNo)
+					return nil, fmt.Errorf("Comment for %q doesn't seem to match line %s:%d\n", name, path, declLineNo)
 				}
 				anchor := sanitizeAnchor(name)
 				// TODO(davidben): Enforce uniqueness. This is
@@ -529,7 +544,10 @@
 
   <body>
     <div id="main">
-    <h2>{{.Name}}</h2>
+    <div class="title">
+      <h2>{{.Name}}</h2>
+      <a href="headers.html">All headers</a>
+    </div>
 
     {{range .Preamble}}<p>{{. | html | markupPipeWords}}</p>{{end}}
 
@@ -622,6 +640,9 @@
 
   <body>
     <div id="main">
+      <div class="title">
+        <h2>BoringSSL Headers</h2>
+      </div>
       <table>
         {{range .Sections}}
 	  <tr class="header"><td colspan="2">{{.Name}}</td></tr>
diff --git a/src/util/generate-asm-lcov.py b/src/util/generate-asm-lcov.py
new file mode 100755
index 0000000..257ae84
--- /dev/null
+++ b/src/util/generate-asm-lcov.py
@@ -0,0 +1,152 @@
+#!/usr/bin/python
+# Copyright (c) 2016, Google Inc.
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+import os
+import os.path
+import subprocess
+import sys
+
+# The LCOV output format for each source file is:
+#
+# SF:<filename>
+# DA:<line>,<execution count>
+# ...
+# end_of_record
+#
+# The <execution count> can either be 0 for an unexecuted instruction or a
+# value representing the number of executions. The DA line should be omitted
+# for lines not representing an instruction.
+
+SECTION_SEPERATOR = '-' * 80
+
+def is_asm(l):
+  """Returns whether a line should be considered to be an instruction."""
+  l = l.strip()
+  # Empty lines
+  if l == '':
+    return False
+  # Comments
+  if l.startswith('#'):
+    return False
+  # Assembly Macros
+  if l.startswith('.'):
+    return False
+  # Label
+  if l.endswith(':'):
+    return False
+  return True
+
+def merge(callgrind_files, srcs):
+  """Calls callgrind_annotate over the set of callgrind output
+  |callgrind_files| using the sources |srcs| and merges the results
+  together."""
+  out = ''
+  for file in callgrind_files:
+    data = subprocess.check_output(['callgrind_annotate', file] + srcs)
+    out += '%s\n%s\n' % (data, SECTION_SEPERATOR)
+  return out
+
+def parse(filename, data, current):
+  """Parses an annotated execution flow |data| from callgrind_annotate for
+  source |filename| and updates the current execution counts from |current|."""
+  with open(filename) as f:
+    source = f.read().split('\n')
+
+  out = current
+  if out == None:
+    out = [0 if is_asm(l) else None for l in source]
+
+  # Lines are of the following formats:
+  #   -- line: Indicates that analysis continues from a different place.
+  #   Ir     : Indicates the start of a file.
+  #   =>     : Indicates a call/jump in the control flow.
+  #   <Count> <Code>: Indicates that the line has been executed that many times.
+  line = None
+  for l in data:
+    l = l.strip() + ' '
+    if l.startswith('-- line'):
+      line = int(l.split(' ')[2]) - 1
+    elif l.strip() == 'Ir':
+      line = 0
+    elif line != None and l.strip() and '=>' not in l and 'unidentified lines' not in l:
+      count = l.split(' ')[0].replace(',', '').replace('.', '0')
+      instruction = l.split(' ', 1)[1].strip()
+      if count != '0' or is_asm(instruction):
+        if out[line] == None:
+          out[line] = 0
+        out[line] += int(count)
+      line += 1
+
+  return out
+
+
+def generate(data):
+  """Parses the merged callgrind_annotate output |data| and generates execution
+  counts for all annotated files."""
+  out = {}
+  data = [p.strip() for p in data.split(SECTION_SEPERATOR)]
+
+
+  # Most sections are ignored, but a section with:
+  #  User-annotated source: <file>
+  # precedes a listing of execution count for that <file>.
+  for i in range(len(data)):
+    if 'User-annotated source' in data[i] and i < len(data) - 1:
+      filename = data[i].split(':', 1)[1].strip()
+      res = data[i + 1]
+      if filename not in out:
+        out[filename] = None
+      if 'No information' in res:
+        res = []
+      else:
+        res = res.split('\n')
+      out[filename] = parse(filename, res, out[filename])
+  return out
+
+def output(data):
+  """Takes a dictionary |data| of filenames and execution counts and generates
+  a LCOV coverage output."""
+  out = ''
+  for filename, counts in data.iteritems():
+    out += 'SF:%s\n' % (os.path.abspath(filename))
+    for line, count in enumerate(counts):
+      if count != None:
+        out += 'DA:%d,%s\n' % (line + 1, count)
+    out += 'end_of_record\n'
+  return out
+
+if __name__ == '__main__':
+  if len(sys.argv) != 3:
+    print '%s <Callgrind Folder> <Build Folder>' % (__file__)
+    sys.exit()
+
+  cg_folder = sys.argv[1]
+  build_folder = sys.argv[2]
+
+  cg_files = []
+  for (cwd, _, files) in os.walk(cg_folder):
+    for f in files:
+      if f.startswith('callgrind.out'):
+        cg_files.append(os.path.abspath(os.path.join(cwd, f)))
+
+  srcs = []
+  for (cwd, _, files) in os.walk(build_folder):
+    for f in files:
+      fn = os.path.join(cwd, f)
+      if fn.endswith('.S'):
+        srcs.append(fn)
+
+  annotated = merge(cg_files, srcs)
+  lcov = generate(annotated)
+  print output(lcov)
diff --git a/src/util/generate-coverage.sh b/src/util/generate-coverage.sh
new file mode 100755
index 0000000..3990c98
--- /dev/null
+++ b/src/util/generate-coverage.sh
@@ -0,0 +1,58 @@
+#!/bin/sh
+# Copyright (c) 2016, Google Inc.
+#
+# Permission to use, copy, modify, and/or distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+set -xe
+
+SRC=$PWD
+
+BUILD=$(mktemp -d '/tmp/boringssl.XXXXXX')
+BUILD_SRC=$(mktemp -d '/tmp/boringssl-src.XXXXXX')
+LCOV=$(mktemp -d '/tmp/boringssl-lcov.XXXXXX')
+
+if [ -n "$1" ]; then
+  LCOV=$(readlink -f "$1")
+  mkdir -p "$LCOV"
+fi
+
+cd "$BUILD"
+cmake "$SRC" -GNinja -DGCOV=1
+ninja
+
+cp -r "$SRC/crypto" "$SRC/decrepit" "$SRC/include" "$SRC/ssl" "$SRC/tool" \
+  "$BUILD_SRC"
+cp -r "$BUILD"/* "$BUILD_SRC"
+mkdir "$BUILD/callgrind/"
+
+cd "$SRC"
+go run "$SRC/util/all_tests.go" -build-dir "$BUILD" -callgrind -num-workers 16
+util/generate-asm-lcov.py "$BUILD/callgrind" "$BUILD" > "$BUILD/asm.info"
+
+go run "util/all_tests.go" -build-dir "$BUILD"
+
+cd "$SRC/ssl/test/runner"
+go test -shim-path "$BUILD/ssl/test/bssl_shim" -num-workers 1
+
+cd "$LCOV"
+lcov -c -d "$BUILD" -b "$BUILD" -o "$BUILD/lcov.info"
+lcov -r "$BUILD/lcov.info" -o "$BUILD/filtered.info" "*_test.c" "*_test.cc" "*/third_party/googletest/*"
+cat "$BUILD/filtered.info" "$BUILD/asm.info" > "$BUILD/final.info"
+sed -i "s;$BUILD;$BUILD_SRC;g" "$BUILD/final.info"
+sed -i "s;$SRC;$BUILD_SRC;g" "$BUILD/final.info"
+genhtml -p "$BUILD_SRC" "$BUILD/final.info"
+
+rm -rf "$BUILD"
+rm -rf "$BUILD_SRC"
+
+xdg-open index.html
diff --git a/src/util/generate_build_files.py b/src/util/generate_build_files.py
index 6321c5c..a3435f2 100644
--- a/src/util/generate_build_files.py
+++ b/src/util/generate_build_files.py
@@ -12,10 +12,9 @@
 # OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
 # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
-"""Enumerates the BoringSSL source in src/ and either generates two gypi files
-  (boringssl.gypi and boringssl_tests.gypi) for Chromium, or generates
-  source-list files for Android."""
+"""Enumerates source files for consumption by various build systems."""
 
+import optparse
 import os
 import subprocess
 import sys
@@ -27,6 +26,7 @@
 OS_ARCH_COMBOS = [
     ('linux', 'arm', 'linux32', [], 'S'),
     ('linux', 'aarch64', 'linux64', [], 'S'),
+    ('linux', 'ppc64le', 'ppc64le', [], 'S'),
     ('linux', 'x86', 'elf', ['-fPIC', '-DOPENSSL_IA32_SSE2'], 'S'),
     ('linux', 'x86_64', 'elf', [], 'S'),
     ('mac', 'x86', 'macosx', ['-fPIC', '-DOPENSSL_IA32_SSE2'], 'S'),
@@ -39,82 +39,22 @@
 # perlasm system.
 NON_PERL_FILES = {
     ('linux', 'arm'): [
-        'src/crypto/chacha/chacha_vec_arm.S',
-        'src/crypto/cpu-arm-asm.S',
         'src/crypto/curve25519/asm/x25519-asm-arm.S',
         'src/crypto/poly1305/poly1305_arm_asm.S',
     ],
+    ('linux', 'x86_64'): [
+        'src/crypto/curve25519/asm/x25519-asm-x86_64.S',
+    ],
+    ('mac', 'x86_64'): [
+        'src/crypto/curve25519/asm/x25519-asm-x86_64.S',
+    ],
 }
 
+PREFIX = None
 
-class Chromium(object):
 
-  def __init__(self):
-    self.header = \
-"""# Copyright (c) 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# This file is created by generate_build_files.py. Do not edit manually.
-
-"""
-
-  def PrintVariableSection(self, out, name, files):
-    out.write('    \'%s\': [\n' % name)
-    for f in sorted(files):
-      out.write('      \'%s\',\n' % f)
-    out.write('    ],\n')
-
-  def WriteFiles(self, files, asm_outputs):
-    with open('boringssl.gypi', 'w+') as gypi:
-      gypi.write(self.header + '{\n  \'variables\': {\n')
-
-      self.PrintVariableSection(
-          gypi, 'boringssl_ssl_sources', files['ssl'])
-      self.PrintVariableSection(
-          gypi, 'boringssl_crypto_sources', files['crypto'])
-
-      for ((osname, arch), asm_files) in asm_outputs:
-        self.PrintVariableSection(gypi, 'boringssl_%s_%s_sources' %
-                                  (osname, arch), asm_files)
-
-      gypi.write('  }\n}\n')
-
-    with open('boringssl_tests.gypi', 'w+') as test_gypi:
-      test_gypi.write(self.header + '{\n  \'targets\': [\n')
-
-      test_names = []
-      for test in sorted(files['test']):
-        test_name = 'boringssl_%s' % os.path.splitext(os.path.basename(test))[0]
-        test_gypi.write("""    {
-      'target_name': '%s',
-      'type': 'executable',
-      'dependencies': [
-        'boringssl.gyp:boringssl',
-      ],
-      'sources': [
-        '%s',
-        '<@(boringssl_test_support_sources)',
-      ],
-      # TODO(davidben): Fix size_t truncations in BoringSSL.
-      # https://crbug.com/429039
-      'msvs_disabled_warnings': [ 4267, ],
-    },\n""" % (test_name, test))
-        test_names.append(test_name)
-
-      test_names.sort()
-
-      test_gypi.write('  ],\n  \'variables\': {\n')
-
-      self.PrintVariableSection(
-          test_gypi, 'boringssl_test_support_sources', files['test_support'])
-
-      test_gypi.write('    \'boringssl_test_targets\': [\n')
-
-      for test in test_names:
-        test_gypi.write("""      '%s',\n""" % test)
-
-      test_gypi.write('    ],\n  }\n}\n')
+def PathOf(x):
+  return x if not PREFIX else os.path.join(PREFIX, x)
 
 
 class Android(object):
@@ -135,10 +75,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-"""
+# This file is created by generate_build_files.py. Do not edit manually.
 
-  def ExtraFiles(self):
-    return ['android_compat_hacks.c', 'android_compat_keywrap.c']
+"""
 
   def PrintVariableSection(self, out, name, files):
     out.write('%s := \\\n' % name)
@@ -147,29 +86,103 @@
     out.write('\n')
 
   def WriteFiles(self, files, asm_outputs):
+    # New Android.bp format
+    with open('sources.bp', 'w+') as blueprint:
+      blueprint.write(self.header.replace('#', '//'))
+
+      blueprint.write('cc_defaults {\n')
+      blueprint.write('    name: "libcrypto_sources",\n')
+      blueprint.write('    srcs: [\n')
+      for f in sorted(files['crypto']):
+        blueprint.write('        "%s",\n' % f)
+      blueprint.write('    ],\n')
+      blueprint.write('    target: {\n')
+
+      for ((osname, arch), asm_files) in asm_outputs:
+        if osname != 'linux' or arch == 'ppc64le':
+          continue
+        if arch == 'aarch64':
+          arch = 'arm64'
+
+        blueprint.write('        android_%s: {\n' % arch)
+        blueprint.write('            srcs: [\n')
+        for f in sorted(asm_files):
+          blueprint.write('                "%s",\n' % f)
+        blueprint.write('            ],\n')
+        blueprint.write('        },\n')
+
+        if arch == 'x86' or arch == 'x86_64':
+          blueprint.write('        linux_%s: {\n' % arch)
+          blueprint.write('            srcs: [\n')
+          for f in sorted(asm_files):
+            blueprint.write('                "%s",\n' % f)
+          blueprint.write('            ],\n')
+          blueprint.write('        },\n')
+
+      blueprint.write('    },\n')
+      blueprint.write('}\n\n')
+
+      blueprint.write('cc_defaults {\n')
+      blueprint.write('    name: "libssl_sources",\n')
+      blueprint.write('    srcs: [\n')
+      for f in sorted(files['ssl']):
+        blueprint.write('        "%s",\n' % f)
+      blueprint.write('    ],\n')
+      blueprint.write('}\n\n')
+
+      blueprint.write('cc_defaults {\n')
+      blueprint.write('    name: "bssl_sources",\n')
+      blueprint.write('    srcs: [\n')
+      for f in sorted(files['tool']):
+        blueprint.write('        "%s",\n' % f)
+      blueprint.write('    ],\n')
+      blueprint.write('}\n\n')
+
+      blueprint.write('cc_defaults {\n')
+      blueprint.write('    name: "boringssl_test_support_sources",\n')
+      blueprint.write('    srcs: [\n')
+      for f in sorted(files['test_support']):
+        blueprint.write('        "%s",\n' % f)
+      blueprint.write('    ],\n')
+      blueprint.write('}\n\n')
+
+      blueprint.write('cc_defaults {\n')
+      blueprint.write('    name: "boringssl_crypto_test_sources",\n')
+      blueprint.write('    srcs: [\n')
+      for f in sorted(files['crypto_test']):
+        blueprint.write('        "%s",\n' % f)
+      blueprint.write('    ],\n')
+      blueprint.write('}\n\n')
+
+      blueprint.write('cc_defaults {\n')
+      blueprint.write('    name: "boringssl_ssl_test_sources",\n')
+      blueprint.write('    srcs: [\n')
+      for f in sorted(files['ssl_test']):
+        blueprint.write('        "%s",\n' % f)
+      blueprint.write('    ],\n')
+      blueprint.write('}\n\n')
+
+      blueprint.write('cc_defaults {\n')
+      blueprint.write('    name: "boringssl_tests_sources",\n')
+      blueprint.write('    srcs: [\n')
+      for f in sorted(files['test']):
+        blueprint.write('        "%s",\n' % f)
+      blueprint.write('    ],\n')
+      blueprint.write('}\n')
+
+    # Legacy Android.mk format, only used by Trusty in new branches
     with open('sources.mk', 'w+') as makefile:
       makefile.write(self.header)
 
-      crypto_files = files['crypto'] + self.ExtraFiles()
-      self.PrintVariableSection(makefile, 'crypto_sources', crypto_files)
-      self.PrintVariableSection(makefile, 'ssl_sources', files['ssl'])
-      self.PrintVariableSection(makefile, 'tool_sources', files['tool'])
+      self.PrintVariableSection(makefile, 'crypto_sources', files['crypto'])
 
       for ((osname, arch), asm_files) in asm_outputs:
+        if osname != 'linux':
+          continue
         self.PrintVariableSection(
             makefile, '%s_%s_sources' % (osname, arch), asm_files)
 
 
-class AndroidStandalone(Android):
-  """AndroidStandalone is for Android builds outside of the Android-system, i.e.
-
-  for applications that wish wish to ship BoringSSL.
-  """
-
-  def ExtraFiles(self):
-    return []
-
-
 class Bazel(object):
   """Bazel outputs files suitable for including in Bazel files."""
 
@@ -187,7 +200,7 @@
 
     out.write('%s = [\n' % name)
     for f in sorted(files):
-      out.write('    "%s",\n' % f)
+      out.write('    "%s",\n' % PathOf(f))
     out.write(']\n')
 
   def WriteFiles(self, files, asm_outputs):
@@ -198,11 +211,14 @@
       self.PrintVariableSection(
           out, 'ssl_internal_headers', files['ssl_internal_headers'])
       self.PrintVariableSection(out, 'ssl_sources', files['ssl'])
+      self.PrintVariableSection(out, 'ssl_c_sources', files['ssl_c'])
+      self.PrintVariableSection(out, 'ssl_cc_sources', files['ssl_cc'])
       self.PrintVariableSection(out, 'crypto_headers', files['crypto_headers'])
       self.PrintVariableSection(
           out, 'crypto_internal_headers', files['crypto_internal_headers'])
       self.PrintVariableSection(out, 'crypto_sources', files['crypto'])
       self.PrintVariableSection(out, 'tool_sources', files['tool'])
+      self.PrintVariableSection(out, 'tool_headers', files['tool_headers'])
 
       for ((osname, arch), asm_files) in asm_outputs:
         self.PrintVariableSection(
@@ -212,16 +228,21 @@
       out.write(self.header)
 
       out.write('test_support_sources = [\n')
-      for filename in files['test_support']:
+      for filename in sorted(files['test_support'] +
+                             files['test_support_headers'] +
+                             files['crypto_internal_headers'] +
+                             files['ssl_internal_headers']):
         if os.path.basename(filename) == 'malloc.cc':
           continue
-        out.write('    "%s",\n' % filename)
+        out.write('    "%s",\n' % PathOf(filename))
 
       out.write(']\n\n')
 
-      out.write('def create_tests(copts):\n')
-      out.write('  test_support_sources_complete = test_support_sources + \\\n')
-      out.write('      native.glob(["src/crypto/test/*.h"])\n')
+      self.PrintVariableSection(out, 'crypto_test_sources',
+                                files['crypto_test'])
+      self.PrintVariableSection(out, 'ssl_test_sources', files['ssl_test'])
+
+      out.write('def create_tests(copts, crypto, ssl):\n')
       name_counts = {}
       for test in files['tests']:
         name = os.path.basename(test[0])
@@ -251,7 +272,8 @@
         out.write('  native.cc_test(\n')
         out.write('      name = "%s",\n' % name)
         out.write('      size = "small",\n')
-        out.write('      srcs = ["%s"] + test_support_sources_complete,\n' % src)
+        out.write('      srcs = ["%s"] + test_support_sources,\n' %
+            PathOf(src))
 
         data_files = []
         if len(test) > 1:
@@ -259,30 +281,150 @@
           out.write('      args = [\n')
           for arg in test[1:]:
             if '/' in arg:
-              out.write('          "$(location src/%s)",\n' % arg)
+              out.write('          "$(location %s)",\n' %
+                  PathOf(os.path.join('src', arg)))
               data_files.append('src/%s' % arg)
             else:
               out.write('          "%s",\n' % arg)
           out.write('      ],\n')
 
-        out.write('      copts = copts,\n')
+        out.write('      copts = copts + ["-DBORINGSSL_SHARED_LIBRARY"],\n')
 
         if len(data_files) > 0:
           out.write('      data = [\n')
           for filename in data_files:
-            out.write('          "%s",\n' % filename)
+            out.write('          "%s",\n' % PathOf(filename))
           out.write('      ],\n')
 
         if 'ssl/' in test[0]:
           out.write('      deps = [\n')
-          out.write('          ":crypto",\n')
-          out.write('          ":ssl",\n')
+          out.write('          crypto,\n')
+          out.write('          ssl,\n')
           out.write('      ],\n')
         else:
-          out.write('      deps = [":crypto"],\n')
+          out.write('      deps = [crypto],\n')
         out.write('  )\n')
 
 
+class GN(object):
+
+  def __init__(self):
+    self.firstSection = True
+    self.header = \
+"""# Copyright (c) 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This file is created by generate_build_files.py. Do not edit manually.
+
+"""
+
+  def PrintVariableSection(self, out, name, files):
+    if not self.firstSection:
+      out.write('\n')
+    self.firstSection = False
+
+    out.write('%s = [\n' % name)
+    for f in sorted(files):
+      out.write('  "%s",\n' % f)
+    out.write(']\n')
+
+  def WriteFiles(self, files, asm_outputs):
+    with open('BUILD.generated.gni', 'w+') as out:
+      out.write(self.header)
+
+      self.PrintVariableSection(out, 'crypto_sources',
+                                files['crypto'] + files['crypto_headers'] +
+                                files['crypto_internal_headers'])
+      self.PrintVariableSection(out, 'ssl_sources',
+                                files['ssl'] + files['ssl_headers'] +
+                                files['ssl_internal_headers'])
+
+      for ((osname, arch), asm_files) in asm_outputs:
+        self.PrintVariableSection(
+            out, 'crypto_sources_%s_%s' % (osname, arch), asm_files)
+
+      fuzzers = [os.path.splitext(os.path.basename(fuzzer))[0]
+                 for fuzzer in files['fuzz']]
+      self.PrintVariableSection(out, 'fuzzers', fuzzers)
+
+    with open('BUILD.generated_tests.gni', 'w+') as out:
+      self.firstSection = True
+      out.write(self.header)
+
+      self.PrintVariableSection(out, 'test_support_sources',
+                                files['test_support'] +
+                                files['test_support_headers'])
+      self.PrintVariableSection(out, 'crypto_test_sources',
+                                files['crypto_test'])
+      self.PrintVariableSection(out, 'ssl_test_sources', files['ssl_test'])
+      out.write('\n')
+
+      out.write('template("create_tests") {\n')
+
+      all_tests = []
+      for test in sorted(files['test']):
+        test_name = 'boringssl_%s' % os.path.splitext(os.path.basename(test))[0]
+        all_tests.append(test_name)
+
+        out.write('  executable("%s") {\n' % test_name)
+        out.write('    sources = [\n')
+        out.write('      "%s",\n' % test)
+        out.write('    ]\n')
+        out.write('    sources += test_support_sources\n')
+        out.write('    if (defined(invoker.configs_exclude)) {\n')
+        out.write('      configs -= invoker.configs_exclude\n')
+        out.write('    }\n')
+        out.write('    configs += invoker.configs\n')
+        out.write('    deps = invoker.deps\n')
+        out.write('  }\n')
+        out.write('\n')
+
+      out.write('  group(target_name) {\n')
+      out.write('    deps = [\n')
+      for test_name in sorted(all_tests):
+        out.write('      ":%s",\n' % test_name)
+      out.write('    ]\n')
+      out.write('  }\n')
+      out.write('}\n')
+
+
+class GYP(object):
+
+  def __init__(self):
+    self.header = \
+"""# Copyright (c) 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# This file is created by generate_build_files.py. Do not edit manually.
+
+"""
+
+  def PrintVariableSection(self, out, name, files):
+    out.write('    \'%s\': [\n' % name)
+    for f in sorted(files):
+      out.write('      \'%s\',\n' % f)
+    out.write('    ],\n')
+
+  def WriteFiles(self, files, asm_outputs):
+    with open('boringssl.gypi', 'w+') as gypi:
+      gypi.write(self.header + '{\n  \'variables\': {\n')
+
+      self.PrintVariableSection(gypi, 'boringssl_ssl_sources',
+                                files['ssl'] + files['ssl_headers'] +
+                                files['ssl_internal_headers'])
+      self.PrintVariableSection(gypi, 'boringssl_crypto_sources',
+                                files['crypto'] + files['crypto_headers'] +
+                                files['crypto_internal_headers'])
+
+      for ((osname, arch), asm_files) in asm_outputs:
+        self.PrintVariableSection(gypi, 'boringssl_%s_%s_sources' %
+                                  (osname, arch), asm_files)
+
+      gypi.write('  }\n}\n')
+
+
 def FindCMakeFiles(directory):
   """Returns list of all CMakeLists.txt files recursively in directory."""
   cmakefiles = []
@@ -317,6 +459,10 @@
   return True
 
 
+def NotGTestMain(dent, is_dir):
+  return dent != 'gtest_main.cc'
+
+
 def SSLHeaderFiles(dent, is_dir):
   return dent in ['ssl.h', 'tls1.h', 'ssl23.h', 'ssl3.h', 'dtls1.h']
 
@@ -353,6 +499,10 @@
         continue
       hfiles.append(os.path.join(path, filename))
 
+      for (i, dirname) in enumerate(dirnames):
+        if not filter_func(dirname, True):
+          del dirnames[i]
+
   return hfiles
 
 
@@ -397,10 +547,8 @@
   base_dir = os.path.dirname(output_filename)
   if not os.path.isdir(base_dir):
     os.makedirs(base_dir)
-  output = subprocess.check_output(
-      ['perl', input_filename, perlasm_style] + extra_args)
-  with open(output_filename, 'w+') as out_file:
-    out_file.write(output)
+  subprocess.check_call(
+      ['perl', input_filename, perlasm_style] + extra_args + [output_filename])
 
 
 def ArchForAsmFilename(filename):
@@ -417,6 +565,8 @@
     return ['aarch64']
   elif 'arm' in filename:
     return ['arm']
+  elif 'ppc' in filename:
+    return ['ppc64le']
   else:
     raise ValueError('Unknown arch for asm filename: ' + filename)
 
@@ -453,10 +603,16 @@
   return asmfiles
 
 
+def IsGTest(path):
+  with open(path) as f:
+    return "#include <gtest/gtest.h>" in f.read()
+
+
 def main(platforms):
   crypto_c_files = FindCFiles(os.path.join('src', 'crypto'), NoTests)
-  ssl_c_files = FindCFiles(os.path.join('src', 'ssl'), NoTests)
-  tool_cc_files = FindCFiles(os.path.join('src', 'tool'), NoTests)
+  ssl_source_files = FindCFiles(os.path.join('src', 'ssl'), NoTests)
+  tool_c_files = FindCFiles(os.path.join('src', 'tool'), NoTests)
+  tool_h_files = FindHeaderFiles(os.path.join('src', 'tool'), AllFiles)
 
   # Generate err_data.c
   with open('err_data.c', 'w+') as err_data:
@@ -465,11 +621,25 @@
                           stdout=err_data)
   crypto_c_files.append('err_data.c')
 
-  test_support_cc_files = FindCFiles(os.path.join('src', 'crypto', 'test'),
-                                     AllFiles)
+  test_support_c_files = FindCFiles(os.path.join('src', 'crypto', 'test'),
+                                    NotGTestMain)
+  test_support_h_files = (
+      FindHeaderFiles(os.path.join('src', 'crypto', 'test'), AllFiles) +
+      FindHeaderFiles(os.path.join('src', 'ssl', 'test'), AllFiles))
 
-  test_c_files = FindCFiles(os.path.join('src', 'crypto'), OnlyTests)
-  test_c_files += FindCFiles(os.path.join('src', 'ssl'), OnlyTests)
+  test_c_files = []
+  crypto_test_files = ['src/crypto/test/gtest_main.cc']
+  # TODO(davidben): Remove this loop once all tests are converted.
+  for path in FindCFiles(os.path.join('src', 'crypto'), OnlyTests):
+    if IsGTest(path):
+      crypto_test_files.append(path)
+    else:
+      test_c_files.append(path)
+
+  ssl_test_files = FindCFiles(os.path.join('src', 'ssl'), OnlyTests)
+  ssl_test_files.append('src/crypto/test/gtest_main.cc')
+
+  fuzz_c_files = FindCFiles(os.path.join('src', 'fuzz'), NoTests)
 
   ssl_h_files = (
       FindHeaderFiles(
@@ -489,6 +659,10 @@
 
   with open('src/util/all_tests.json', 'r') as f:
     tests = json.load(f)
+  # For now, GTest-based tests are specified manually.
+  tests = [test for test in tests if test[0] not in ['crypto/crypto_test',
+                                                     'decrepit/decrepit_test',
+                                                     'ssl/ssl_test']]
   test_binaries = set([test[0] for test in tests])
   test_sources = set([
       test.replace('.cc', '').replace('.c', '').replace(
@@ -508,12 +682,19 @@
       'crypto': crypto_c_files,
       'crypto_headers': crypto_h_files,
       'crypto_internal_headers': crypto_internal_h_files,
-      'ssl': ssl_c_files,
+      'crypto_test': sorted(crypto_test_files),
+      'fuzz': fuzz_c_files,
+      'ssl': ssl_source_files,
+      'ssl_c': [s for s in ssl_source_files if s.endswith('.c')],
+      'ssl_cc': [s for s in ssl_source_files if s.endswith('.cc')],
       'ssl_headers': ssl_h_files,
       'ssl_internal_headers': ssl_internal_h_files,
-      'tool': tool_cc_files,
+      'ssl_test': sorted(ssl_test_files),
+      'tool': tool_c_files,
+      'tool_headers': tool_h_files,
       'test': test_c_files,
-      'test_support': test_support_cc_files,
+      'test_support': test_support_c_files,
+      'test_support_headers': test_support_h_files,
       'tests': tests,
   }
 
@@ -525,26 +706,30 @@
   return 0
 
 
-def Usage():
-  print 'Usage: python %s [chromium|android|android-standalone|bazel]' % sys.argv[0]
-  sys.exit(1)
-
-
 if __name__ == '__main__':
-  if len(sys.argv) < 2:
-    Usage()
+  parser = optparse.OptionParser(usage='Usage: %prog [--prefix=<path>]'
+      ' [android|bazel|gn|gyp]')
+  parser.add_option('--prefix', dest='prefix',
+      help='For Bazel, prepend argument to all source files')
+  options, args = parser.parse_args(sys.argv[1:])
+  PREFIX = options.prefix
+
+  if not args:
+    parser.print_help()
+    sys.exit(1)
 
   platforms = []
-  for s in sys.argv[1:]:
-    if s == 'chromium' or s == 'gyp':
-      platforms.append(Chromium())
-    elif s == 'android':
+  for s in args:
+    if s == 'android':
       platforms.append(Android())
-    elif s == 'android-standalone':
-      platforms.append(AndroidStandalone())
     elif s == 'bazel':
       platforms.append(Bazel())
+    elif s == 'gn':
+      platforms.append(GN())
+    elif s == 'gyp':
+      platforms.append(GYP())
     else:
-      Usage()
+      parser.print_help()
+      sys.exit(1)
 
   sys.exit(main(platforms))
diff --git a/src/util/make_errors.go b/src/util/make_errors.go
index cc35409..c1aef82 100644
--- a/src/util/make_errors.go
+++ b/src/util/make_errors.go
@@ -10,7 +10,7 @@
 // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
-// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
 package main
 
diff --git a/src/util/run_android_tests.go b/src/util/run_android_tests.go
new file mode 100644
index 0000000..92deac0
--- /dev/null
+++ b/src/util/run_android_tests.go
@@ -0,0 +1,325 @@
+// Copyright (c) 2016, Google Inc.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+package main
+
+import (
+	"bytes"
+	"encoding/json"
+	"flag"
+	"fmt"
+	"io"
+	"io/ioutil"
+	"os"
+	"os/exec"
+	"path/filepath"
+	"strconv"
+	"strings"
+)
+
+var (
+	buildDir     = flag.String("build-dir", "build", "Specifies the build directory to push.")
+	adbPath      = flag.String("adb", "adb", "Specifies the adb binary to use. Defaults to looking in PATH.")
+	device       = flag.String("device", "", "Specifies the device or emulator. See adb's -s argument.")
+	aarch64      = flag.Bool("aarch64", false, "Build the test runners for aarch64 instead of arm.")
+	arm          = flag.Int("arm", 7, "Which arm revision to build for.")
+	suite        = flag.String("suite", "all", "Specifies the test suites to run (all, unit, or ssl).")
+	allTestsArgs = flag.String("all-tests-args", "", "Specifies space-separated arguments to pass to all_tests.go")
+	runnerArgs   = flag.String("runner-args", "", "Specifies space-separated arguments to pass to ssl/test/runner")
+	jsonOutput   = flag.String("json-output", "", "The file to output JSON results to.")
+)
+
+func enableUnitTests() bool {
+	return *suite == "all" || *suite == "unit"
+}
+
+func enableSSLTests() bool {
+	return *suite == "all" || *suite == "ssl"
+}
+
+func adb(args ...string) error {
+	if len(*device) > 0 {
+		args = append([]string{"-s", *device}, args...)
+	}
+	cmd := exec.Command(*adbPath, args...)
+	cmd.Stdout = os.Stdout
+	cmd.Stderr = os.Stderr
+	return cmd.Run()
+}
+
+func adbShell(shellCmd string) (int, error) {
+	var args []string
+	if len(*device) > 0 {
+		args = append([]string{"-s", *device}, args...)
+	}
+	args = append(args, "shell")
+
+	const delimiter = "___EXIT_CODE___"
+
+	// Older versions of adb and Android do not preserve the exit
+	// code, so work around this.
+	// https://code.google.com/p/android/issues/detail?id=3254
+	shellCmd += "; echo " + delimiter + " $?"
+	args = append(args, shellCmd)
+
+	cmd := exec.Command(*adbPath, args...)
+	stdout, err := cmd.StdoutPipe()
+	if err != nil {
+		return 0, err
+	}
+	cmd.Stderr = os.Stderr
+	if err := cmd.Start(); err != nil {
+		return 0, err
+	}
+
+	var stdoutBytes bytes.Buffer
+	for {
+		var buf [1024]byte
+		n, err := stdout.Read(buf[:])
+		stdoutBytes.Write(buf[:n])
+		os.Stdout.Write(buf[:n])
+		if err != nil {
+			break
+		}
+	}
+
+	if err := cmd.Wait(); err != nil {
+		return 0, err
+	}
+
+	stdoutStr := stdoutBytes.String()
+	idx := strings.LastIndex(stdoutStr, delimiter)
+	if idx < 0 {
+		return 0, fmt.Errorf("Could not find delimiter in output.")
+	}
+
+	return strconv.Atoi(strings.TrimSpace(stdoutStr[idx+len(delimiter):]))
+}
+
+func goTool(args ...string) error {
+	cmd := exec.Command("go", args...)
+	cmd.Stdout = os.Stdout
+	cmd.Stderr = os.Stderr
+
+	cmd.Env = os.Environ()
+	if *aarch64 {
+		cmd.Env = append(cmd.Env, "GOARCH=arm64")
+	} else {
+		cmd.Env = append(cmd.Env, "GOARCH=arm")
+		cmd.Env = append(cmd.Env, fmt.Sprintf("GOARM=%d", *arm))
+	}
+	return cmd.Run()
+}
+
+// setWorkingDirectory walks up directories as needed until the current working
+// directory is the top of a BoringSSL checkout.
+func setWorkingDirectory() {
+	for i := 0; i < 64; i++ {
+		if _, err := os.Stat("BUILDING.md"); err == nil {
+			return
+		}
+		os.Chdir("..")
+	}
+
+	panic("Couldn't find BUILDING.md in a parent directory!")
+}
+
+type test []string
+
+func parseTestConfig(filename string) ([]test, error) {
+	in, err := os.Open(filename)
+	if err != nil {
+		return nil, err
+	}
+	defer in.Close()
+
+	decoder := json.NewDecoder(in)
+	var result []test
+	if err := decoder.Decode(&result); err != nil {
+		return nil, err
+	}
+	return result, nil
+}
+
+func copyFile(dst, src string) error {
+	srcFile, err := os.Open(src)
+	if err != nil {
+		return err
+	}
+	defer srcFile.Close()
+
+	srcInfo, err := srcFile.Stat()
+	if err != nil {
+		return err
+	}
+
+	dir := filepath.Dir(dst)
+	if err := os.MkdirAll(dir, 0777); err != nil {
+		return err
+	}
+
+	dstFile, err := os.OpenFile(dst, os.O_CREATE|os.O_WRONLY, srcInfo.Mode())
+	if err != nil {
+		return err
+	}
+	defer dstFile.Close()
+
+	_, err = io.Copy(dstFile, srcFile)
+	return err
+}
+
+func main() {
+	flag.Parse()
+
+	if *suite == "all" && *jsonOutput != "" {
+		fmt.Printf("To use -json-output flag, select only one test suite with -suite.\n")
+		os.Exit(1)
+	}
+
+	setWorkingDirectory()
+
+	// Clear the target directory.
+	if err := adb("shell", "rm -Rf /data/local/tmp/boringssl-tmp"); err != nil {
+		fmt.Printf("Failed to clear target directory: %s\n", err)
+		os.Exit(1)
+	}
+
+	// Stage everything in a temporary directory.
+	tmpDir, err := ioutil.TempDir("", "boringssl-android")
+	if err != nil {
+		fmt.Printf("Error making temporary directory: %s\n", err)
+		os.Exit(1)
+	}
+	defer os.RemoveAll(tmpDir)
+
+	var binaries, files []string
+
+	if enableUnitTests() {
+		files = append(files,
+			"util/all_tests.json",
+			"BUILDING.md",
+		)
+
+		tests, err := parseTestConfig("util/all_tests.json")
+		if err != nil {
+			fmt.Printf("Failed to parse input: %s\n", err)
+			os.Exit(1)
+		}
+
+		seenBinary := make(map[string]struct{})
+		for _, test := range tests {
+			if _, ok := seenBinary[test[0]]; !ok {
+				binaries = append(binaries, test[0])
+				seenBinary[test[0]] = struct{}{}
+			}
+			for _, arg := range test[1:] {
+				if strings.Contains(arg, "/") {
+					files = append(files, arg)
+				}
+			}
+		}
+
+		fmt.Printf("Building all_tests...\n")
+		if err := goTool("build", "-o", filepath.Join(tmpDir, "util/all_tests"), "util/all_tests.go"); err != nil {
+			fmt.Printf("Error building all_tests.go: %s\n", err)
+			os.Exit(1)
+		}
+	}
+
+	if enableSSLTests() {
+		binaries = append(binaries, "ssl/test/bssl_shim")
+		files = append(files,
+			"BUILDING.md",
+			"ssl/test/runner/cert.pem",
+			"ssl/test/runner/channel_id_key.pem",
+			"ssl/test/runner/ecdsa_p224_cert.pem",
+			"ssl/test/runner/ecdsa_p224_key.pem",
+			"ssl/test/runner/ecdsa_p256_cert.pem",
+			"ssl/test/runner/ecdsa_p256_key.pem",
+			"ssl/test/runner/ecdsa_p384_cert.pem",
+			"ssl/test/runner/ecdsa_p384_key.pem",
+			"ssl/test/runner/ecdsa_p521_cert.pem",
+			"ssl/test/runner/ecdsa_p521_key.pem",
+			"ssl/test/runner/key.pem",
+			"ssl/test/runner/rsa_1024_cert.pem",
+			"ssl/test/runner/rsa_1024_key.pem",
+			"ssl/test/runner/rsa_chain_cert.pem",
+			"ssl/test/runner/rsa_chain_key.pem",
+			"util/all_tests.json",
+		)
+
+		fmt.Printf("Building runner...\n")
+		if err := goTool("test", "-c", "-o", filepath.Join(tmpDir, "ssl/test/runner/runner"), "./ssl/test/runner/"); err != nil {
+			fmt.Printf("Error building runner: %s\n", err)
+			os.Exit(1)
+		}
+	}
+
+	fmt.Printf("Copying test binaries...\n")
+	for _, binary := range binaries {
+		if err := copyFile(filepath.Join(tmpDir, "build", binary), filepath.Join(*buildDir, binary)); err != nil {
+			fmt.Printf("Failed to copy %s: %s\n", binary, err)
+			os.Exit(1)
+		}
+	}
+
+	fmt.Printf("Copying data files...\n")
+	for _, file := range files {
+		if err := copyFile(filepath.Join(tmpDir, file), file); err != nil {
+			fmt.Printf("Failed to copy %s: %s\n", file, err)
+			os.Exit(1)
+		}
+	}
+
+	fmt.Printf("Uploading files...\n")
+	if err := adb("push", "-p", tmpDir, "/data/local/tmp/boringssl-tmp"); err != nil {
+		fmt.Printf("Failed to push runner: %s\n", err)
+		os.Exit(1)
+	}
+
+	var unitTestExit int
+	if enableUnitTests() {
+		fmt.Printf("Running unit tests...\n")
+		unitTestExit, err = adbShell(fmt.Sprintf("cd /data/local/tmp/boringssl-tmp && ./util/all_tests -json-output results.json %s", *allTestsArgs))
+		if err != nil {
+			fmt.Printf("Failed to run unit tests: %s\n", err)
+			os.Exit(1)
+		}
+	}
+
+	var sslTestExit int
+	if enableSSLTests() {
+		fmt.Printf("Running SSL tests...\n")
+		sslTestExit, err = adbShell(fmt.Sprintf("cd /data/local/tmp/boringssl-tmp/ssl/test/runner && ./runner -json-output ../../../results.json %s", *runnerArgs))
+		if err != nil {
+			fmt.Printf("Failed to run SSL tests: %s\n", err)
+			os.Exit(1)
+		}
+	}
+
+	if *jsonOutput != "" {
+		if err := adb("pull", "-p", "/data/local/tmp/boringssl-tmp/results.json", *jsonOutput); err != nil {
+			fmt.Printf("Failed to extract results.json: %s\n", err)
+			os.Exit(1)
+		}
+	}
+
+	if unitTestExit != 0 {
+		os.Exit(unitTestExit)
+	}
+
+	if sslTestExit != 0 {
+		os.Exit(sslTestExit)
+	}
+}
diff --git a/ssl-sources.mk b/ssl-sources.mk
deleted file mode 100644
index a4c8470..0000000
--- a/ssl-sources.mk
+++ /dev/null
@@ -1,5 +0,0 @@
-LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/sources.mk
-include $(LOCAL_PATH)/sources.mk
-
-LOCAL_CFLAGS += -I$(LOCAL_PATH)/src/include -Wno-unused-parameter -DBORINGSSL_ANDROID_SYSTEM
-LOCAL_SRC_FILES += $(ssl_sources)
diff --git a/win-x86/crypto/bn/x86-mont.asm b/win-x86/crypto/bn/x86-mont.asm
index de7b949..b1a4d59 100644
--- a/win-x86/crypto/bn/x86-mont.asm
+++ b/win-x86/crypto/bn/x86-mont.asm
@@ -29,36 +29,51 @@
 	jl	NEAR L$000just_leave
 	lea	esi,[20+esp]
 	lea	edx,[24+esp]
-	mov	ebp,esp
 	add	edi,2
 	neg	edi
-	lea	esp,[edi*4+esp-32]
+	lea	ebp,[edi*4+esp-32]
 	neg	edi
-	mov	eax,esp
+	mov	eax,ebp
 	sub	eax,edx
 	and	eax,2047
-	sub	esp,eax
-	xor	edx,esp
+	sub	ebp,eax
+	xor	edx,ebp
 	and	edx,2048
 	xor	edx,2048
-	sub	esp,edx
-	and	esp,-64
+	sub	ebp,edx
+	and	ebp,-64
+	mov	eax,esp
+	sub	eax,ebp
+	and	eax,-4096
+	mov	edx,esp
+	lea	esp,[eax*1+ebp]
+	mov	eax,DWORD [esp]
+	cmp	esp,ebp
+	ja	NEAR L$001page_walk
+	jmp	NEAR L$002page_walk_done
+align	16
+L$001page_walk:
+	lea	esp,[esp-4096]
+	mov	eax,DWORD [esp]
+	cmp	esp,ebp
+	ja	NEAR L$001page_walk
+L$002page_walk_done:
 	mov	eax,DWORD [esi]
 	mov	ebx,DWORD [4+esi]
 	mov	ecx,DWORD [8+esi]
-	mov	edx,DWORD [12+esi]
+	mov	ebp,DWORD [12+esi]
 	mov	esi,DWORD [16+esi]
 	mov	esi,DWORD [esi]
 	mov	DWORD [4+esp],eax
 	mov	DWORD [8+esp],ebx
 	mov	DWORD [12+esp],ecx
-	mov	DWORD [16+esp],edx
+	mov	DWORD [16+esp],ebp
 	mov	DWORD [20+esp],esi
 	lea	ebx,[edi-3]
-	mov	DWORD [24+esp],ebp
+	mov	DWORD [24+esp],edx
 	lea	eax,[_OPENSSL_ia32cap_P]
 	bt	DWORD [eax],26
-	jnc	NEAR L$001non_sse2
+	jnc	NEAR L$003non_sse2
 	mov	eax,-1
 	movd	mm7,eax
 	mov	esi,DWORD [8+esp]
@@ -82,7 +97,7 @@
 	psrlq	mm3,32
 	inc	ecx
 align	16
-L$0021st:
+L$0041st:
 	pmuludq	mm0,mm4
 	pmuludq	mm1,mm5
 	paddq	mm2,mm0
@@ -97,7 +112,7 @@
 	psrlq	mm3,32
 	lea	ecx,[1+ecx]
 	cmp	ecx,ebx
-	jl	NEAR L$0021st
+	jl	NEAR L$0041st
 	pmuludq	mm0,mm4
 	pmuludq	mm1,mm5
 	paddq	mm2,mm0
@@ -111,7 +126,7 @@
 	paddq	mm3,mm2
 	movq	[32+ebx*4+esp],mm3
 	inc	edx
-L$003outer:
+L$005outer:
 	xor	ecx,ecx
 	movd	mm4,DWORD [edx*4+edi]
 	movd	mm5,DWORD [esi]
@@ -133,7 +148,7 @@
 	paddq	mm2,mm6
 	inc	ecx
 	dec	ebx
-L$004inner:
+L$006inner:
 	pmuludq	mm0,mm4
 	pmuludq	mm1,mm5
 	paddq	mm2,mm0
@@ -150,7 +165,7 @@
 	paddq	mm2,mm6
 	dec	ebx
 	lea	ecx,[1+ecx]
-	jnz	NEAR L$004inner
+	jnz	NEAR L$006inner
 	mov	ebx,ecx
 	pmuludq	mm0,mm4
 	pmuludq	mm1,mm5
@@ -168,11 +183,11 @@
 	movq	[32+ebx*4+esp],mm3
 	lea	edx,[1+edx]
 	cmp	edx,ebx
-	jle	NEAR L$003outer
+	jle	NEAR L$005outer
 	emms
-	jmp	NEAR L$005common_tail
+	jmp	NEAR L$007common_tail
 align	16
-L$001non_sse2:
+L$003non_sse2:
 	mov	esi,DWORD [8+esp]
 	lea	ebp,[1+ebx]
 	mov	edi,DWORD [12+esp]
@@ -183,12 +198,12 @@
 	lea	eax,[4+ebx*4+edi]
 	or	ebp,edx
 	mov	edi,DWORD [edi]
-	jz	NEAR L$006bn_sqr_mont
+	jz	NEAR L$008bn_sqr_mont
 	mov	DWORD [28+esp],eax
 	mov	eax,DWORD [esi]
 	xor	edx,edx
 align	16
-L$007mull:
+L$009mull:
 	mov	ebp,edx
 	mul	edi
 	add	ebp,eax
@@ -197,7 +212,7 @@
 	mov	eax,DWORD [ecx*4+esi]
 	cmp	ecx,ebx
 	mov	DWORD [28+ecx*4+esp],ebp
-	jl	NEAR L$007mull
+	jl	NEAR L$009mull
 	mov	ebp,edx
 	mul	edi
 	mov	edi,DWORD [20+esp]
@@ -215,9 +230,9 @@
 	mov	eax,DWORD [4+esi]
 	adc	edx,0
 	inc	ecx
-	jmp	NEAR L$0082ndmadd
+	jmp	NEAR L$0102ndmadd
 align	16
-L$0091stmadd:
+L$0111stmadd:
 	mov	ebp,edx
 	mul	edi
 	add	ebp,DWORD [32+ecx*4+esp]
@@ -228,7 +243,7 @@
 	adc	edx,0
 	cmp	ecx,ebx
 	mov	DWORD [28+ecx*4+esp],ebp
-	jl	NEAR L$0091stmadd
+	jl	NEAR L$0111stmadd
 	mov	ebp,edx
 	mul	edi
 	add	eax,DWORD [32+ebx*4+esp]
@@ -251,7 +266,7 @@
 	adc	edx,0
 	mov	ecx,1
 align	16
-L$0082ndmadd:
+L$0102ndmadd:
 	mov	ebp,edx
 	mul	edi
 	add	ebp,DWORD [32+ecx*4+esp]
@@ -262,7 +277,7 @@
 	adc	edx,0
 	cmp	ecx,ebx
 	mov	DWORD [24+ecx*4+esp],ebp
-	jl	NEAR L$0082ndmadd
+	jl	NEAR L$0102ndmadd
 	mov	ebp,edx
 	mul	edi
 	add	ebp,DWORD [32+ebx*4+esp]
@@ -278,16 +293,16 @@
 	mov	DWORD [32+ebx*4+esp],edx
 	cmp	ecx,DWORD [28+esp]
 	mov	DWORD [36+ebx*4+esp],eax
-	je	NEAR L$005common_tail
+	je	NEAR L$007common_tail
 	mov	edi,DWORD [ecx]
 	mov	esi,DWORD [8+esp]
 	mov	DWORD [12+esp],ecx
 	xor	ecx,ecx
 	xor	edx,edx
 	mov	eax,DWORD [esi]
-	jmp	NEAR L$0091stmadd
+	jmp	NEAR L$0111stmadd
 align	16
-L$006bn_sqr_mont:
+L$008bn_sqr_mont:
 	mov	DWORD [esp],ebx
 	mov	DWORD [12+esp],ecx
 	mov	eax,edi
@@ -298,7 +313,7 @@
 	and	ebx,1
 	inc	ecx
 align	16
-L$010sqr:
+L$012sqr:
 	mov	eax,DWORD [ecx*4+esi]
 	mov	ebp,edx
 	mul	edi
@@ -310,7 +325,7 @@
 	cmp	ecx,DWORD [esp]
 	mov	ebx,eax
 	mov	DWORD [28+ecx*4+esp],ebp
-	jl	NEAR L$010sqr
+	jl	NEAR L$012sqr
 	mov	eax,DWORD [ecx*4+esi]
 	mov	ebp,edx
 	mul	edi
@@ -334,7 +349,7 @@
 	mov	eax,DWORD [4+esi]
 	mov	ecx,1
 align	16
-L$0113rdmadd:
+L$0133rdmadd:
 	mov	ebp,edx
 	mul	edi
 	add	ebp,DWORD [32+ecx*4+esp]
@@ -353,7 +368,7 @@
 	adc	edx,0
 	cmp	ecx,ebx
 	mov	DWORD [24+ecx*4+esp],ebp
-	jl	NEAR L$0113rdmadd
+	jl	NEAR L$0133rdmadd
 	mov	ebp,edx
 	mul	edi
 	add	ebp,DWORD [32+ebx*4+esp]
@@ -369,7 +384,7 @@
 	mov	DWORD [32+ebx*4+esp],edx
 	cmp	ecx,ebx
 	mov	DWORD [36+ebx*4+esp],eax
-	je	NEAR L$005common_tail
+	je	NEAR L$007common_tail
 	mov	edi,DWORD [4+ecx*4+esi]
 	lea	ecx,[1+ecx]
 	mov	eax,edi
@@ -381,12 +396,12 @@
 	xor	ebp,ebp
 	cmp	ecx,ebx
 	lea	ecx,[1+ecx]
-	je	NEAR L$012sqrlast
+	je	NEAR L$014sqrlast
 	mov	ebx,edx
 	shr	edx,1
 	and	ebx,1
 align	16
-L$013sqradd:
+L$015sqradd:
 	mov	eax,DWORD [ecx*4+esi]
 	mov	ebp,edx
 	mul	edi
@@ -402,13 +417,13 @@
 	cmp	ecx,DWORD [esp]
 	mov	DWORD [28+ecx*4+esp],ebp
 	mov	ebx,eax
-	jle	NEAR L$013sqradd
+	jle	NEAR L$015sqradd
 	mov	ebp,edx
 	add	edx,edx
 	shr	ebp,31
 	add	edx,ebx
 	adc	ebp,0
-L$012sqrlast:
+L$014sqrlast:
 	mov	edi,DWORD [20+esp]
 	mov	esi,DWORD [16+esp]
 	imul	edi,DWORD [32+esp]
@@ -423,9 +438,9 @@
 	adc	edx,0
 	mov	ecx,1
 	mov	eax,DWORD [4+esi]
-	jmp	NEAR L$0113rdmadd
+	jmp	NEAR L$0133rdmadd
 align	16
-L$005common_tail:
+L$007common_tail:
 	mov	ebp,DWORD [16+esp]
 	mov	edi,DWORD [4+esp]
 	lea	esi,[32+esp]
@@ -433,25 +448,26 @@
 	mov	ecx,ebx
 	xor	edx,edx
 align	16
-L$014sub:
+L$016sub:
 	sbb	eax,DWORD [edx*4+ebp]
 	mov	DWORD [edx*4+edi],eax
 	dec	ecx
 	mov	eax,DWORD [4+edx*4+esi]
 	lea	edx,[1+edx]
-	jge	NEAR L$014sub
+	jge	NEAR L$016sub
 	sbb	eax,0
+	and	esi,eax
+	not	eax
+	mov	ebp,edi
+	and	ebp,eax
+	or	esi,ebp
 align	16
-L$015copy:
-	mov	edx,DWORD [ebx*4+esi]
-	mov	ebp,DWORD [ebx*4+edi]
-	xor	edx,ebp
-	and	edx,eax
-	xor	edx,ebp
-	mov	DWORD [ebx*4+esi],ecx
-	mov	DWORD [ebx*4+edi],edx
+L$017copy:
+	mov	eax,DWORD [ebx*4+esi]
+	mov	DWORD [ebx*4+edi],eax
+	mov	DWORD [32+ebx*4+esp],ecx
 	dec	ebx
-	jge	NEAR L$015copy
+	jge	NEAR L$017copy
 	mov	esp,DWORD [24+esp]
 	mov	eax,1
 L$000just_leave:
diff --git a/win-x86/crypto/chacha/chacha-x86.asm b/win-x86/crypto/chacha/chacha-x86.asm
new file mode 100644
index 0000000..3ba31a2
--- /dev/null
+++ b/win-x86/crypto/chacha/chacha-x86.asm
@@ -0,0 +1,977 @@
+%ifidn __OUTPUT_FORMAT__,obj
+section	code	use32 class=code align=64
+%elifidn __OUTPUT_FORMAT__,win32
+%ifdef __YASM_VERSION_ID__
+%if __YASM_VERSION_ID__ < 01010000h
+%error yasm version 1.1.0 or later needed.
+%endif
+; Yasm automatically includes .00 and complains about redefining it.
+; https://www.tortall.net/projects/yasm/manual/html/objfmt-win32-safeseh.html
+%else
+$@feat.00 equ 1
+%endif
+section	.text	code align=64
+%else
+section	.text	code
+%endif
+global	_ChaCha20_ctr32
+align	16
+_ChaCha20_ctr32:
+L$_ChaCha20_ctr32_begin:
+	push	ebp
+	push	ebx
+	push	esi
+	push	edi
+	xor	eax,eax
+	cmp	eax,DWORD [28+esp]
+	je	NEAR L$000no_data
+	call	L$pic_point
+L$pic_point:
+	pop	eax
+	lea	ebp,[_OPENSSL_ia32cap_P]
+	test	DWORD [ebp],16777216
+	jz	NEAR L$001x86
+	test	DWORD [4+ebp],512
+	jz	NEAR L$001x86
+	jmp	NEAR L$ssse3_shortcut
+L$001x86:
+	mov	esi,DWORD [32+esp]
+	mov	edi,DWORD [36+esp]
+	sub	esp,132
+	mov	eax,DWORD [esi]
+	mov	ebx,DWORD [4+esi]
+	mov	ecx,DWORD [8+esi]
+	mov	edx,DWORD [12+esi]
+	mov	DWORD [80+esp],eax
+	mov	DWORD [84+esp],ebx
+	mov	DWORD [88+esp],ecx
+	mov	DWORD [92+esp],edx
+	mov	eax,DWORD [16+esi]
+	mov	ebx,DWORD [20+esi]
+	mov	ecx,DWORD [24+esi]
+	mov	edx,DWORD [28+esi]
+	mov	DWORD [96+esp],eax
+	mov	DWORD [100+esp],ebx
+	mov	DWORD [104+esp],ecx
+	mov	DWORD [108+esp],edx
+	mov	eax,DWORD [edi]
+	mov	ebx,DWORD [4+edi]
+	mov	ecx,DWORD [8+edi]
+	mov	edx,DWORD [12+edi]
+	sub	eax,1
+	mov	DWORD [112+esp],eax
+	mov	DWORD [116+esp],ebx
+	mov	DWORD [120+esp],ecx
+	mov	DWORD [124+esp],edx
+	jmp	NEAR L$002entry
+align	16
+L$003outer_loop:
+	mov	DWORD [156+esp],ebx
+	mov	DWORD [152+esp],eax
+	mov	DWORD [160+esp],ecx
+L$002entry:
+	mov	eax,1634760805
+	mov	DWORD [4+esp],857760878
+	mov	DWORD [8+esp],2036477234
+	mov	DWORD [12+esp],1797285236
+	mov	ebx,DWORD [84+esp]
+	mov	ebp,DWORD [88+esp]
+	mov	ecx,DWORD [104+esp]
+	mov	esi,DWORD [108+esp]
+	mov	edx,DWORD [116+esp]
+	mov	edi,DWORD [120+esp]
+	mov	DWORD [20+esp],ebx
+	mov	DWORD [24+esp],ebp
+	mov	DWORD [40+esp],ecx
+	mov	DWORD [44+esp],esi
+	mov	DWORD [52+esp],edx
+	mov	DWORD [56+esp],edi
+	mov	ebx,DWORD [92+esp]
+	mov	edi,DWORD [124+esp]
+	mov	edx,DWORD [112+esp]
+	mov	ebp,DWORD [80+esp]
+	mov	ecx,DWORD [96+esp]
+	mov	esi,DWORD [100+esp]
+	add	edx,1
+	mov	DWORD [28+esp],ebx
+	mov	DWORD [60+esp],edi
+	mov	DWORD [112+esp],edx
+	mov	ebx,10
+	jmp	NEAR L$004loop
+align	16
+L$004loop:
+	add	eax,ebp
+	mov	DWORD [128+esp],ebx
+	mov	ebx,ebp
+	xor	edx,eax
+	rol	edx,16
+	add	ecx,edx
+	xor	ebx,ecx
+	mov	edi,DWORD [52+esp]
+	rol	ebx,12
+	mov	ebp,DWORD [20+esp]
+	add	eax,ebx
+	xor	edx,eax
+	mov	DWORD [esp],eax
+	rol	edx,8
+	mov	eax,DWORD [4+esp]
+	add	ecx,edx
+	mov	DWORD [48+esp],edx
+	xor	ebx,ecx
+	add	eax,ebp
+	rol	ebx,7
+	xor	edi,eax
+	mov	DWORD [32+esp],ecx
+	rol	edi,16
+	mov	DWORD [16+esp],ebx
+	add	esi,edi
+	mov	ecx,DWORD [40+esp]
+	xor	ebp,esi
+	mov	edx,DWORD [56+esp]
+	rol	ebp,12
+	mov	ebx,DWORD [24+esp]
+	add	eax,ebp
+	xor	edi,eax
+	mov	DWORD [4+esp],eax
+	rol	edi,8
+	mov	eax,DWORD [8+esp]
+	add	esi,edi
+	mov	DWORD [52+esp],edi
+	xor	ebp,esi
+	add	eax,ebx
+	rol	ebp,7
+	xor	edx,eax
+	mov	DWORD [36+esp],esi
+	rol	edx,16
+	mov	DWORD [20+esp],ebp
+	add	ecx,edx
+	mov	esi,DWORD [44+esp]
+	xor	ebx,ecx
+	mov	edi,DWORD [60+esp]
+	rol	ebx,12
+	mov	ebp,DWORD [28+esp]
+	add	eax,ebx
+	xor	edx,eax
+	mov	DWORD [8+esp],eax
+	rol	edx,8
+	mov	eax,DWORD [12+esp]
+	add	ecx,edx
+	mov	DWORD [56+esp],edx
+	xor	ebx,ecx
+	add	eax,ebp
+	rol	ebx,7
+	xor	edi,eax
+	rol	edi,16
+	mov	DWORD [24+esp],ebx
+	add	esi,edi
+	xor	ebp,esi
+	rol	ebp,12
+	mov	ebx,DWORD [20+esp]
+	add	eax,ebp
+	xor	edi,eax
+	mov	DWORD [12+esp],eax
+	rol	edi,8
+	mov	eax,DWORD [esp]
+	add	esi,edi
+	mov	edx,edi
+	xor	ebp,esi
+	add	eax,ebx
+	rol	ebp,7
+	xor	edx,eax
+	rol	edx,16
+	mov	DWORD [28+esp],ebp
+	add	ecx,edx
+	xor	ebx,ecx
+	mov	edi,DWORD [48+esp]
+	rol	ebx,12
+	mov	ebp,DWORD [24+esp]
+	add	eax,ebx
+	xor	edx,eax
+	mov	DWORD [esp],eax
+	rol	edx,8
+	mov	eax,DWORD [4+esp]
+	add	ecx,edx
+	mov	DWORD [60+esp],edx
+	xor	ebx,ecx
+	add	eax,ebp
+	rol	ebx,7
+	xor	edi,eax
+	mov	DWORD [40+esp],ecx
+	rol	edi,16
+	mov	DWORD [20+esp],ebx
+	add	esi,edi
+	mov	ecx,DWORD [32+esp]
+	xor	ebp,esi
+	mov	edx,DWORD [52+esp]
+	rol	ebp,12
+	mov	ebx,DWORD [28+esp]
+	add	eax,ebp
+	xor	edi,eax
+	mov	DWORD [4+esp],eax
+	rol	edi,8
+	mov	eax,DWORD [8+esp]
+	add	esi,edi
+	mov	DWORD [48+esp],edi
+	xor	ebp,esi
+	add	eax,ebx
+	rol	ebp,7
+	xor	edx,eax
+	mov	DWORD [44+esp],esi
+	rol	edx,16
+	mov	DWORD [24+esp],ebp
+	add	ecx,edx
+	mov	esi,DWORD [36+esp]
+	xor	ebx,ecx
+	mov	edi,DWORD [56+esp]
+	rol	ebx,12
+	mov	ebp,DWORD [16+esp]
+	add	eax,ebx
+	xor	edx,eax
+	mov	DWORD [8+esp],eax
+	rol	edx,8
+	mov	eax,DWORD [12+esp]
+	add	ecx,edx
+	mov	DWORD [52+esp],edx
+	xor	ebx,ecx
+	add	eax,ebp
+	rol	ebx,7
+	xor	edi,eax
+	rol	edi,16
+	mov	DWORD [28+esp],ebx
+	add	esi,edi
+	xor	ebp,esi
+	mov	edx,DWORD [48+esp]
+	rol	ebp,12
+	mov	ebx,DWORD [128+esp]
+	add	eax,ebp
+	xor	edi,eax
+	mov	DWORD [12+esp],eax
+	rol	edi,8
+	mov	eax,DWORD [esp]
+	add	esi,edi
+	mov	DWORD [56+esp],edi
+	xor	ebp,esi
+	rol	ebp,7
+	dec	ebx
+	jnz	NEAR L$004loop
+	mov	ebx,DWORD [160+esp]
+	add	eax,1634760805
+	add	ebp,DWORD [80+esp]
+	add	ecx,DWORD [96+esp]
+	add	esi,DWORD [100+esp]
+	cmp	ebx,64
+	jb	NEAR L$005tail
+	mov	ebx,DWORD [156+esp]
+	add	edx,DWORD [112+esp]
+	add	edi,DWORD [120+esp]
+	xor	eax,DWORD [ebx]
+	xor	ebp,DWORD [16+ebx]
+	mov	DWORD [esp],eax
+	mov	eax,DWORD [152+esp]
+	xor	ecx,DWORD [32+ebx]
+	xor	esi,DWORD [36+ebx]
+	xor	edx,DWORD [48+ebx]
+	xor	edi,DWORD [56+ebx]
+	mov	DWORD [16+eax],ebp
+	mov	DWORD [32+eax],ecx
+	mov	DWORD [36+eax],esi
+	mov	DWORD [48+eax],edx
+	mov	DWORD [56+eax],edi
+	mov	ebp,DWORD [4+esp]
+	mov	ecx,DWORD [8+esp]
+	mov	esi,DWORD [12+esp]
+	mov	edx,DWORD [20+esp]
+	mov	edi,DWORD [24+esp]
+	add	ebp,857760878
+	add	ecx,2036477234
+	add	esi,1797285236
+	add	edx,DWORD [84+esp]
+	add	edi,DWORD [88+esp]
+	xor	ebp,DWORD [4+ebx]
+	xor	ecx,DWORD [8+ebx]
+	xor	esi,DWORD [12+ebx]
+	xor	edx,DWORD [20+ebx]
+	xor	edi,DWORD [24+ebx]
+	mov	DWORD [4+eax],ebp
+	mov	DWORD [8+eax],ecx
+	mov	DWORD [12+eax],esi
+	mov	DWORD [20+eax],edx
+	mov	DWORD [24+eax],edi
+	mov	ebp,DWORD [28+esp]
+	mov	ecx,DWORD [40+esp]
+	mov	esi,DWORD [44+esp]
+	mov	edx,DWORD [52+esp]
+	mov	edi,DWORD [60+esp]
+	add	ebp,DWORD [92+esp]
+	add	ecx,DWORD [104+esp]
+	add	esi,DWORD [108+esp]
+	add	edx,DWORD [116+esp]
+	add	edi,DWORD [124+esp]
+	xor	ebp,DWORD [28+ebx]
+	xor	ecx,DWORD [40+ebx]
+	xor	esi,DWORD [44+ebx]
+	xor	edx,DWORD [52+ebx]
+	xor	edi,DWORD [60+ebx]
+	lea	ebx,[64+ebx]
+	mov	DWORD [28+eax],ebp
+	mov	ebp,DWORD [esp]
+	mov	DWORD [40+eax],ecx
+	mov	ecx,DWORD [160+esp]
+	mov	DWORD [44+eax],esi
+	mov	DWORD [52+eax],edx
+	mov	DWORD [60+eax],edi
+	mov	DWORD [eax],ebp
+	lea	eax,[64+eax]
+	sub	ecx,64
+	jnz	NEAR L$003outer_loop
+	jmp	NEAR L$006done
+L$005tail:
+	add	edx,DWORD [112+esp]
+	add	edi,DWORD [120+esp]
+	mov	DWORD [esp],eax
+	mov	DWORD [16+esp],ebp
+	mov	DWORD [32+esp],ecx
+	mov	DWORD [36+esp],esi
+	mov	DWORD [48+esp],edx
+	mov	DWORD [56+esp],edi
+	mov	ebp,DWORD [4+esp]
+	mov	ecx,DWORD [8+esp]
+	mov	esi,DWORD [12+esp]
+	mov	edx,DWORD [20+esp]
+	mov	edi,DWORD [24+esp]
+	add	ebp,857760878
+	add	ecx,2036477234
+	add	esi,1797285236
+	add	edx,DWORD [84+esp]
+	add	edi,DWORD [88+esp]
+	mov	DWORD [4+esp],ebp
+	mov	DWORD [8+esp],ecx
+	mov	DWORD [12+esp],esi
+	mov	DWORD [20+esp],edx
+	mov	DWORD [24+esp],edi
+	mov	ebp,DWORD [28+esp]
+	mov	ecx,DWORD [40+esp]
+	mov	esi,DWORD [44+esp]
+	mov	edx,DWORD [52+esp]
+	mov	edi,DWORD [60+esp]
+	add	ebp,DWORD [92+esp]
+	add	ecx,DWORD [104+esp]
+	add	esi,DWORD [108+esp]
+	add	edx,DWORD [116+esp]
+	add	edi,DWORD [124+esp]
+	mov	DWORD [28+esp],ebp
+	mov	ebp,DWORD [156+esp]
+	mov	DWORD [40+esp],ecx
+	mov	ecx,DWORD [152+esp]
+	mov	DWORD [44+esp],esi
+	xor	esi,esi
+	mov	DWORD [52+esp],edx
+	mov	DWORD [60+esp],edi
+	xor	eax,eax
+	xor	edx,edx
+L$007tail_loop:
+	mov	al,BYTE [ebp*1+esi]
+	mov	dl,BYTE [esi*1+esp]
+	lea	esi,[1+esi]
+	xor	al,dl
+	mov	BYTE [esi*1+ecx-1],al
+	dec	ebx
+	jnz	NEAR L$007tail_loop
+L$006done:
+	add	esp,132
+L$000no_data:
+	pop	edi
+	pop	esi
+	pop	ebx
+	pop	ebp
+	ret
+global	_ChaCha20_ssse3
+align	16
+_ChaCha20_ssse3:
+L$_ChaCha20_ssse3_begin:
+	push	ebp
+	push	ebx
+	push	esi
+	push	edi
+L$ssse3_shortcut:
+	mov	edi,DWORD [20+esp]
+	mov	esi,DWORD [24+esp]
+	mov	ecx,DWORD [28+esp]
+	mov	edx,DWORD [32+esp]
+	mov	ebx,DWORD [36+esp]
+	mov	ebp,esp
+	sub	esp,524
+	and	esp,-64
+	mov	DWORD [512+esp],ebp
+	lea	eax,[(L$ssse3_data-L$pic_point)+eax]
+	movdqu	xmm3,[ebx]
+	cmp	ecx,256
+	jb	NEAR L$0081x
+	mov	DWORD [516+esp],edx
+	mov	DWORD [520+esp],ebx
+	sub	ecx,256
+	lea	ebp,[384+esp]
+	movdqu	xmm7,[edx]
+	pshufd	xmm0,xmm3,0
+	pshufd	xmm1,xmm3,85
+	pshufd	xmm2,xmm3,170
+	pshufd	xmm3,xmm3,255
+	paddd	xmm0,[48+eax]
+	pshufd	xmm4,xmm7,0
+	pshufd	xmm5,xmm7,85
+	psubd	xmm0,[64+eax]
+	pshufd	xmm6,xmm7,170
+	pshufd	xmm7,xmm7,255
+	movdqa	[64+ebp],xmm0
+	movdqa	[80+ebp],xmm1
+	movdqa	[96+ebp],xmm2
+	movdqa	[112+ebp],xmm3
+	movdqu	xmm3,[16+edx]
+	movdqa	[ebp-64],xmm4
+	movdqa	[ebp-48],xmm5
+	movdqa	[ebp-32],xmm6
+	movdqa	[ebp-16],xmm7
+	movdqa	xmm7,[32+eax]
+	lea	ebx,[128+esp]
+	pshufd	xmm0,xmm3,0
+	pshufd	xmm1,xmm3,85
+	pshufd	xmm2,xmm3,170
+	pshufd	xmm3,xmm3,255
+	pshufd	xmm4,xmm7,0
+	pshufd	xmm5,xmm7,85
+	pshufd	xmm6,xmm7,170
+	pshufd	xmm7,xmm7,255
+	movdqa	[ebp],xmm0
+	movdqa	[16+ebp],xmm1
+	movdqa	[32+ebp],xmm2
+	movdqa	[48+ebp],xmm3
+	movdqa	[ebp-128],xmm4
+	movdqa	[ebp-112],xmm5
+	movdqa	[ebp-96],xmm6
+	movdqa	[ebp-80],xmm7
+	lea	esi,[128+esi]
+	lea	edi,[128+edi]
+	jmp	NEAR L$009outer_loop
+align	16
+L$009outer_loop:
+	movdqa	xmm1,[ebp-112]
+	movdqa	xmm2,[ebp-96]
+	movdqa	xmm3,[ebp-80]
+	movdqa	xmm5,[ebp-48]
+	movdqa	xmm6,[ebp-32]
+	movdqa	xmm7,[ebp-16]
+	movdqa	[ebx-112],xmm1
+	movdqa	[ebx-96],xmm2
+	movdqa	[ebx-80],xmm3
+	movdqa	[ebx-48],xmm5
+	movdqa	[ebx-32],xmm6
+	movdqa	[ebx-16],xmm7
+	movdqa	xmm2,[32+ebp]
+	movdqa	xmm3,[48+ebp]
+	movdqa	xmm4,[64+ebp]
+	movdqa	xmm5,[80+ebp]
+	movdqa	xmm6,[96+ebp]
+	movdqa	xmm7,[112+ebp]
+	paddd	xmm4,[64+eax]
+	movdqa	[32+ebx],xmm2
+	movdqa	[48+ebx],xmm3
+	movdqa	[64+ebx],xmm4
+	movdqa	[80+ebx],xmm5
+	movdqa	[96+ebx],xmm6
+	movdqa	[112+ebx],xmm7
+	movdqa	[64+ebp],xmm4
+	movdqa	xmm0,[ebp-128]
+	movdqa	xmm6,xmm4
+	movdqa	xmm3,[ebp-64]
+	movdqa	xmm4,[ebp]
+	movdqa	xmm5,[16+ebp]
+	mov	edx,10
+	nop
+align	16
+L$010loop:
+	paddd	xmm0,xmm3
+	movdqa	xmm2,xmm3
+	pxor	xmm6,xmm0
+	pshufb	xmm6,[eax]
+	paddd	xmm4,xmm6
+	pxor	xmm2,xmm4
+	movdqa	xmm3,[ebx-48]
+	movdqa	xmm1,xmm2
+	pslld	xmm2,12
+	psrld	xmm1,20
+	por	xmm2,xmm1
+	movdqa	xmm1,[ebx-112]
+	paddd	xmm0,xmm2
+	movdqa	xmm7,[80+ebx]
+	pxor	xmm6,xmm0
+	movdqa	[ebx-128],xmm0
+	pshufb	xmm6,[16+eax]
+	paddd	xmm4,xmm6
+	movdqa	[64+ebx],xmm6
+	pxor	xmm2,xmm4
+	paddd	xmm1,xmm3
+	movdqa	xmm0,xmm2
+	pslld	xmm2,7
+	psrld	xmm0,25
+	pxor	xmm7,xmm1
+	por	xmm2,xmm0
+	movdqa	[ebx],xmm4
+	pshufb	xmm7,[eax]
+	movdqa	[ebx-64],xmm2
+	paddd	xmm5,xmm7
+	movdqa	xmm4,[32+ebx]
+	pxor	xmm3,xmm5
+	movdqa	xmm2,[ebx-32]
+	movdqa	xmm0,xmm3
+	pslld	xmm3,12
+	psrld	xmm0,20
+	por	xmm3,xmm0
+	movdqa	xmm0,[ebx-96]
+	paddd	xmm1,xmm3
+	movdqa	xmm6,[96+ebx]
+	pxor	xmm7,xmm1
+	movdqa	[ebx-112],xmm1
+	pshufb	xmm7,[16+eax]
+	paddd	xmm5,xmm7
+	movdqa	[80+ebx],xmm7
+	pxor	xmm3,xmm5
+	paddd	xmm0,xmm2
+	movdqa	xmm1,xmm3
+	pslld	xmm3,7
+	psrld	xmm1,25
+	pxor	xmm6,xmm0
+	por	xmm3,xmm1
+	movdqa	[16+ebx],xmm5
+	pshufb	xmm6,[eax]
+	movdqa	[ebx-48],xmm3
+	paddd	xmm4,xmm6
+	movdqa	xmm5,[48+ebx]
+	pxor	xmm2,xmm4
+	movdqa	xmm3,[ebx-16]
+	movdqa	xmm1,xmm2
+	pslld	xmm2,12
+	psrld	xmm1,20
+	por	xmm2,xmm1
+	movdqa	xmm1,[ebx-80]
+	paddd	xmm0,xmm2
+	movdqa	xmm7,[112+ebx]
+	pxor	xmm6,xmm0
+	movdqa	[ebx-96],xmm0
+	pshufb	xmm6,[16+eax]
+	paddd	xmm4,xmm6
+	movdqa	[96+ebx],xmm6
+	pxor	xmm2,xmm4
+	paddd	xmm1,xmm3
+	movdqa	xmm0,xmm2
+	pslld	xmm2,7
+	psrld	xmm0,25
+	pxor	xmm7,xmm1
+	por	xmm2,xmm0
+	pshufb	xmm7,[eax]
+	movdqa	[ebx-32],xmm2
+	paddd	xmm5,xmm7
+	pxor	xmm3,xmm5
+	movdqa	xmm2,[ebx-48]
+	movdqa	xmm0,xmm3
+	pslld	xmm3,12
+	psrld	xmm0,20
+	por	xmm3,xmm0
+	movdqa	xmm0,[ebx-128]
+	paddd	xmm1,xmm3
+	pxor	xmm7,xmm1
+	movdqa	[ebx-80],xmm1
+	pshufb	xmm7,[16+eax]
+	paddd	xmm5,xmm7
+	movdqa	xmm6,xmm7
+	pxor	xmm3,xmm5
+	paddd	xmm0,xmm2
+	movdqa	xmm1,xmm3
+	pslld	xmm3,7
+	psrld	xmm1,25
+	pxor	xmm6,xmm0
+	por	xmm3,xmm1
+	pshufb	xmm6,[eax]
+	movdqa	[ebx-16],xmm3
+	paddd	xmm4,xmm6
+	pxor	xmm2,xmm4
+	movdqa	xmm3,[ebx-32]
+	movdqa	xmm1,xmm2
+	pslld	xmm2,12
+	psrld	xmm1,20
+	por	xmm2,xmm1
+	movdqa	xmm1,[ebx-112]
+	paddd	xmm0,xmm2
+	movdqa	xmm7,[64+ebx]
+	pxor	xmm6,xmm0
+	movdqa	[ebx-128],xmm0
+	pshufb	xmm6,[16+eax]
+	paddd	xmm4,xmm6
+	movdqa	[112+ebx],xmm6
+	pxor	xmm2,xmm4
+	paddd	xmm1,xmm3
+	movdqa	xmm0,xmm2
+	pslld	xmm2,7
+	psrld	xmm0,25
+	pxor	xmm7,xmm1
+	por	xmm2,xmm0
+	movdqa	[32+ebx],xmm4
+	pshufb	xmm7,[eax]
+	movdqa	[ebx-48],xmm2
+	paddd	xmm5,xmm7
+	movdqa	xmm4,[ebx]
+	pxor	xmm3,xmm5
+	movdqa	xmm2,[ebx-16]
+	movdqa	xmm0,xmm3
+	pslld	xmm3,12
+	psrld	xmm0,20
+	por	xmm3,xmm0
+	movdqa	xmm0,[ebx-96]
+	paddd	xmm1,xmm3
+	movdqa	xmm6,[80+ebx]
+	pxor	xmm7,xmm1
+	movdqa	[ebx-112],xmm1
+	pshufb	xmm7,[16+eax]
+	paddd	xmm5,xmm7
+	movdqa	[64+ebx],xmm7
+	pxor	xmm3,xmm5
+	paddd	xmm0,xmm2
+	movdqa	xmm1,xmm3
+	pslld	xmm3,7
+	psrld	xmm1,25
+	pxor	xmm6,xmm0
+	por	xmm3,xmm1
+	movdqa	[48+ebx],xmm5
+	pshufb	xmm6,[eax]
+	movdqa	[ebx-32],xmm3
+	paddd	xmm4,xmm6
+	movdqa	xmm5,[16+ebx]
+	pxor	xmm2,xmm4
+	movdqa	xmm3,[ebx-64]
+	movdqa	xmm1,xmm2
+	pslld	xmm2,12
+	psrld	xmm1,20
+	por	xmm2,xmm1
+	movdqa	xmm1,[ebx-80]
+	paddd	xmm0,xmm2
+	movdqa	xmm7,[96+ebx]
+	pxor	xmm6,xmm0
+	movdqa	[ebx-96],xmm0
+	pshufb	xmm6,[16+eax]
+	paddd	xmm4,xmm6
+	movdqa	[80+ebx],xmm6
+	pxor	xmm2,xmm4
+	paddd	xmm1,xmm3
+	movdqa	xmm0,xmm2
+	pslld	xmm2,7
+	psrld	xmm0,25
+	pxor	xmm7,xmm1
+	por	xmm2,xmm0
+	pshufb	xmm7,[eax]
+	movdqa	[ebx-16],xmm2
+	paddd	xmm5,xmm7
+	pxor	xmm3,xmm5
+	movdqa	xmm0,xmm3
+	pslld	xmm3,12
+	psrld	xmm0,20
+	por	xmm3,xmm0
+	movdqa	xmm0,[ebx-128]
+	paddd	xmm1,xmm3
+	movdqa	xmm6,[64+ebx]
+	pxor	xmm7,xmm1
+	movdqa	[ebx-80],xmm1
+	pshufb	xmm7,[16+eax]
+	paddd	xmm5,xmm7
+	movdqa	[96+ebx],xmm7
+	pxor	xmm3,xmm5
+	movdqa	xmm1,xmm3
+	pslld	xmm3,7
+	psrld	xmm1,25
+	por	xmm3,xmm1
+	dec	edx
+	jnz	NEAR L$010loop
+	movdqa	[ebx-64],xmm3
+	movdqa	[ebx],xmm4
+	movdqa	[16+ebx],xmm5
+	movdqa	[64+ebx],xmm6
+	movdqa	[96+ebx],xmm7
+	movdqa	xmm1,[ebx-112]
+	movdqa	xmm2,[ebx-96]
+	movdqa	xmm3,[ebx-80]
+	paddd	xmm0,[ebp-128]
+	paddd	xmm1,[ebp-112]
+	paddd	xmm2,[ebp-96]
+	paddd	xmm3,[ebp-80]
+	movdqa	xmm6,xmm0
+	punpckldq	xmm0,xmm1
+	movdqa	xmm7,xmm2
+	punpckldq	xmm2,xmm3
+	punpckhdq	xmm6,xmm1
+	punpckhdq	xmm7,xmm3
+	movdqa	xmm1,xmm0
+	punpcklqdq	xmm0,xmm2
+	movdqa	xmm3,xmm6
+	punpcklqdq	xmm6,xmm7
+	punpckhqdq	xmm1,xmm2
+	punpckhqdq	xmm3,xmm7
+	movdqu	xmm4,[esi-128]
+	movdqu	xmm5,[esi-64]
+	movdqu	xmm2,[esi]
+	movdqu	xmm7,[64+esi]
+	lea	esi,[16+esi]
+	pxor	xmm4,xmm0
+	movdqa	xmm0,[ebx-64]
+	pxor	xmm5,xmm1
+	movdqa	xmm1,[ebx-48]
+	pxor	xmm6,xmm2
+	movdqa	xmm2,[ebx-32]
+	pxor	xmm7,xmm3
+	movdqa	xmm3,[ebx-16]
+	movdqu	[edi-128],xmm4
+	movdqu	[edi-64],xmm5
+	movdqu	[edi],xmm6
+	movdqu	[64+edi],xmm7
+	lea	edi,[16+edi]
+	paddd	xmm0,[ebp-64]
+	paddd	xmm1,[ebp-48]
+	paddd	xmm2,[ebp-32]
+	paddd	xmm3,[ebp-16]
+	movdqa	xmm6,xmm0
+	punpckldq	xmm0,xmm1
+	movdqa	xmm7,xmm2
+	punpckldq	xmm2,xmm3
+	punpckhdq	xmm6,xmm1
+	punpckhdq	xmm7,xmm3
+	movdqa	xmm1,xmm0
+	punpcklqdq	xmm0,xmm2
+	movdqa	xmm3,xmm6
+	punpcklqdq	xmm6,xmm7
+	punpckhqdq	xmm1,xmm2
+	punpckhqdq	xmm3,xmm7
+	movdqu	xmm4,[esi-128]
+	movdqu	xmm5,[esi-64]
+	movdqu	xmm2,[esi]
+	movdqu	xmm7,[64+esi]
+	lea	esi,[16+esi]
+	pxor	xmm4,xmm0
+	movdqa	xmm0,[ebx]
+	pxor	xmm5,xmm1
+	movdqa	xmm1,[16+ebx]
+	pxor	xmm6,xmm2
+	movdqa	xmm2,[32+ebx]
+	pxor	xmm7,xmm3
+	movdqa	xmm3,[48+ebx]
+	movdqu	[edi-128],xmm4
+	movdqu	[edi-64],xmm5
+	movdqu	[edi],xmm6
+	movdqu	[64+edi],xmm7
+	lea	edi,[16+edi]
+	paddd	xmm0,[ebp]
+	paddd	xmm1,[16+ebp]
+	paddd	xmm2,[32+ebp]
+	paddd	xmm3,[48+ebp]
+	movdqa	xmm6,xmm0
+	punpckldq	xmm0,xmm1
+	movdqa	xmm7,xmm2
+	punpckldq	xmm2,xmm3
+	punpckhdq	xmm6,xmm1
+	punpckhdq	xmm7,xmm3
+	movdqa	xmm1,xmm0
+	punpcklqdq	xmm0,xmm2
+	movdqa	xmm3,xmm6
+	punpcklqdq	xmm6,xmm7
+	punpckhqdq	xmm1,xmm2
+	punpckhqdq	xmm3,xmm7
+	movdqu	xmm4,[esi-128]
+	movdqu	xmm5,[esi-64]
+	movdqu	xmm2,[esi]
+	movdqu	xmm7,[64+esi]
+	lea	esi,[16+esi]
+	pxor	xmm4,xmm0
+	movdqa	xmm0,[64+ebx]
+	pxor	xmm5,xmm1
+	movdqa	xmm1,[80+ebx]
+	pxor	xmm6,xmm2
+	movdqa	xmm2,[96+ebx]
+	pxor	xmm7,xmm3
+	movdqa	xmm3,[112+ebx]
+	movdqu	[edi-128],xmm4
+	movdqu	[edi-64],xmm5
+	movdqu	[edi],xmm6
+	movdqu	[64+edi],xmm7
+	lea	edi,[16+edi]
+	paddd	xmm0,[64+ebp]
+	paddd	xmm1,[80+ebp]
+	paddd	xmm2,[96+ebp]
+	paddd	xmm3,[112+ebp]
+	movdqa	xmm6,xmm0
+	punpckldq	xmm0,xmm1
+	movdqa	xmm7,xmm2
+	punpckldq	xmm2,xmm3
+	punpckhdq	xmm6,xmm1
+	punpckhdq	xmm7,xmm3
+	movdqa	xmm1,xmm0
+	punpcklqdq	xmm0,xmm2
+	movdqa	xmm3,xmm6
+	punpcklqdq	xmm6,xmm7
+	punpckhqdq	xmm1,xmm2
+	punpckhqdq	xmm3,xmm7
+	movdqu	xmm4,[esi-128]
+	movdqu	xmm5,[esi-64]
+	movdqu	xmm2,[esi]
+	movdqu	xmm7,[64+esi]
+	lea	esi,[208+esi]
+	pxor	xmm4,xmm0
+	pxor	xmm5,xmm1
+	pxor	xmm6,xmm2
+	pxor	xmm7,xmm3
+	movdqu	[edi-128],xmm4
+	movdqu	[edi-64],xmm5
+	movdqu	[edi],xmm6
+	movdqu	[64+edi],xmm7
+	lea	edi,[208+edi]
+	sub	ecx,256
+	jnc	NEAR L$009outer_loop
+	add	ecx,256
+	jz	NEAR L$011done
+	mov	ebx,DWORD [520+esp]
+	lea	esi,[esi-128]
+	mov	edx,DWORD [516+esp]
+	lea	edi,[edi-128]
+	movd	xmm2,DWORD [64+ebp]
+	movdqu	xmm3,[ebx]
+	paddd	xmm2,[96+eax]
+	pand	xmm3,[112+eax]
+	por	xmm3,xmm2
+L$0081x:
+	movdqa	xmm0,[32+eax]
+	movdqu	xmm1,[edx]
+	movdqu	xmm2,[16+edx]
+	movdqa	xmm6,[eax]
+	movdqa	xmm7,[16+eax]
+	mov	DWORD [48+esp],ebp
+	movdqa	[esp],xmm0
+	movdqa	[16+esp],xmm1
+	movdqa	[32+esp],xmm2
+	movdqa	[48+esp],xmm3
+	mov	edx,10
+	jmp	NEAR L$012loop1x
+align	16
+L$013outer1x:
+	movdqa	xmm3,[80+eax]
+	movdqa	xmm0,[esp]
+	movdqa	xmm1,[16+esp]
+	movdqa	xmm2,[32+esp]
+	paddd	xmm3,[48+esp]
+	mov	edx,10
+	movdqa	[48+esp],xmm3
+	jmp	NEAR L$012loop1x
+align	16
+L$012loop1x:
+	paddd	xmm0,xmm1
+	pxor	xmm3,xmm0
+db	102,15,56,0,222
+	paddd	xmm2,xmm3
+	pxor	xmm1,xmm2
+	movdqa	xmm4,xmm1
+	psrld	xmm1,20
+	pslld	xmm4,12
+	por	xmm1,xmm4
+	paddd	xmm0,xmm1
+	pxor	xmm3,xmm0
+db	102,15,56,0,223
+	paddd	xmm2,xmm3
+	pxor	xmm1,xmm2
+	movdqa	xmm4,xmm1
+	psrld	xmm1,25
+	pslld	xmm4,7
+	por	xmm1,xmm4
+	pshufd	xmm2,xmm2,78
+	pshufd	xmm1,xmm1,57
+	pshufd	xmm3,xmm3,147
+	nop
+	paddd	xmm0,xmm1
+	pxor	xmm3,xmm0
+db	102,15,56,0,222
+	paddd	xmm2,xmm3
+	pxor	xmm1,xmm2
+	movdqa	xmm4,xmm1
+	psrld	xmm1,20
+	pslld	xmm4,12
+	por	xmm1,xmm4
+	paddd	xmm0,xmm1
+	pxor	xmm3,xmm0
+db	102,15,56,0,223
+	paddd	xmm2,xmm3
+	pxor	xmm1,xmm2
+	movdqa	xmm4,xmm1
+	psrld	xmm1,25
+	pslld	xmm4,7
+	por	xmm1,xmm4
+	pshufd	xmm2,xmm2,78
+	pshufd	xmm1,xmm1,147
+	pshufd	xmm3,xmm3,57
+	dec	edx
+	jnz	NEAR L$012loop1x
+	paddd	xmm0,[esp]
+	paddd	xmm1,[16+esp]
+	paddd	xmm2,[32+esp]
+	paddd	xmm3,[48+esp]
+	cmp	ecx,64
+	jb	NEAR L$014tail
+	movdqu	xmm4,[esi]
+	movdqu	xmm5,[16+esi]
+	pxor	xmm0,xmm4
+	movdqu	xmm4,[32+esi]
+	pxor	xmm1,xmm5
+	movdqu	xmm5,[48+esi]
+	pxor	xmm2,xmm4
+	pxor	xmm3,xmm5
+	lea	esi,[64+esi]
+	movdqu	[edi],xmm0
+	movdqu	[16+edi],xmm1
+	movdqu	[32+edi],xmm2
+	movdqu	[48+edi],xmm3
+	lea	edi,[64+edi]
+	sub	ecx,64
+	jnz	NEAR L$013outer1x
+	jmp	NEAR L$011done
+L$014tail:
+	movdqa	[esp],xmm0
+	movdqa	[16+esp],xmm1
+	movdqa	[32+esp],xmm2
+	movdqa	[48+esp],xmm3
+	xor	eax,eax
+	xor	edx,edx
+	xor	ebp,ebp
+L$015tail_loop:
+	mov	al,BYTE [ebp*1+esp]
+	mov	dl,BYTE [ebp*1+esi]
+	lea	ebp,[1+ebp]
+	xor	al,dl
+	mov	BYTE [ebp*1+edi-1],al
+	dec	ecx
+	jnz	NEAR L$015tail_loop
+L$011done:
+	mov	esp,DWORD [512+esp]
+	pop	edi
+	pop	esi
+	pop	ebx
+	pop	ebp
+	ret
+align	64
+L$ssse3_data:
+db	2,3,0,1,6,7,4,5,10,11,8,9,14,15,12,13
+db	3,0,1,2,7,4,5,6,11,8,9,10,15,12,13,14
+dd	1634760805,857760878,2036477234,1797285236
+dd	0,1,2,3
+dd	4,4,4,4
+dd	1,0,0,0
+dd	4,0,0,0
+dd	0,-1,-1,-1
+align	64
+db	67,104,97,67,104,97,50,48,32,102,111,114,32,120,56,54
+db	44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32
+db	60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111
+db	114,103,62,0
+segment	.bss
+common	_OPENSSL_ia32cap_P 16
diff --git a/win-x86/crypto/modes/ghash-x86.asm b/win-x86/crypto/modes/ghash-x86.asm
index eb493ac..1d350d6 100644
--- a/win-x86/crypto/modes/ghash-x86.asm
+++ b/win-x86/crypto/modes/ghash-x86.asm
@@ -14,205 +14,6 @@
 %else
 section	.text	code
 %endif
-global	_gcm_gmult_4bit_x86
-align	16
-_gcm_gmult_4bit_x86:
-L$_gcm_gmult_4bit_x86_begin:
-	push	ebp
-	push	ebx
-	push	esi
-	push	edi
-	sub	esp,84
-	mov	edi,DWORD [104+esp]
-	mov	esi,DWORD [108+esp]
-	mov	ebp,DWORD [edi]
-	mov	edx,DWORD [4+edi]
-	mov	ecx,DWORD [8+edi]
-	mov	ebx,DWORD [12+edi]
-	mov	DWORD [16+esp],0
-	mov	DWORD [20+esp],471859200
-	mov	DWORD [24+esp],943718400
-	mov	DWORD [28+esp],610271232
-	mov	DWORD [32+esp],1887436800
-	mov	DWORD [36+esp],1822425088
-	mov	DWORD [40+esp],1220542464
-	mov	DWORD [44+esp],1423966208
-	mov	DWORD [48+esp],3774873600
-	mov	DWORD [52+esp],4246732800
-	mov	DWORD [56+esp],3644850176
-	mov	DWORD [60+esp],3311403008
-	mov	DWORD [64+esp],2441084928
-	mov	DWORD [68+esp],2376073216
-	mov	DWORD [72+esp],2847932416
-	mov	DWORD [76+esp],3051356160
-	mov	DWORD [esp],ebp
-	mov	DWORD [4+esp],edx
-	mov	DWORD [8+esp],ecx
-	mov	DWORD [12+esp],ebx
-	shr	ebx,20
-	and	ebx,240
-	mov	ebp,DWORD [4+ebx*1+esi]
-	mov	edx,DWORD [ebx*1+esi]
-	mov	ecx,DWORD [12+ebx*1+esi]
-	mov	ebx,DWORD [8+ebx*1+esi]
-	xor	eax,eax
-	mov	edi,15
-	jmp	NEAR L$000x86_loop
-align	16
-L$000x86_loop:
-	mov	al,bl
-	shrd	ebx,ecx,4
-	and	al,15
-	shrd	ecx,edx,4
-	shrd	edx,ebp,4
-	shr	ebp,4
-	xor	ebp,DWORD [16+eax*4+esp]
-	mov	al,BYTE [edi*1+esp]
-	and	al,240
-	xor	ebx,DWORD [8+eax*1+esi]
-	xor	ecx,DWORD [12+eax*1+esi]
-	xor	edx,DWORD [eax*1+esi]
-	xor	ebp,DWORD [4+eax*1+esi]
-	dec	edi
-	js	NEAR L$001x86_break
-	mov	al,bl
-	shrd	ebx,ecx,4
-	and	al,15
-	shrd	ecx,edx,4
-	shrd	edx,ebp,4
-	shr	ebp,4
-	xor	ebp,DWORD [16+eax*4+esp]
-	mov	al,BYTE [edi*1+esp]
-	shl	al,4
-	xor	ebx,DWORD [8+eax*1+esi]
-	xor	ecx,DWORD [12+eax*1+esi]
-	xor	edx,DWORD [eax*1+esi]
-	xor	ebp,DWORD [4+eax*1+esi]
-	jmp	NEAR L$000x86_loop
-align	16
-L$001x86_break:
-	bswap	ebx
-	bswap	ecx
-	bswap	edx
-	bswap	ebp
-	mov	edi,DWORD [104+esp]
-	mov	DWORD [12+edi],ebx
-	mov	DWORD [8+edi],ecx
-	mov	DWORD [4+edi],edx
-	mov	DWORD [edi],ebp
-	add	esp,84
-	pop	edi
-	pop	esi
-	pop	ebx
-	pop	ebp
-	ret
-global	_gcm_ghash_4bit_x86
-align	16
-_gcm_ghash_4bit_x86:
-L$_gcm_ghash_4bit_x86_begin:
-	push	ebp
-	push	ebx
-	push	esi
-	push	edi
-	sub	esp,84
-	mov	ebx,DWORD [104+esp]
-	mov	esi,DWORD [108+esp]
-	mov	edi,DWORD [112+esp]
-	mov	ecx,DWORD [116+esp]
-	add	ecx,edi
-	mov	DWORD [116+esp],ecx
-	mov	ebp,DWORD [ebx]
-	mov	edx,DWORD [4+ebx]
-	mov	ecx,DWORD [8+ebx]
-	mov	ebx,DWORD [12+ebx]
-	mov	DWORD [16+esp],0
-	mov	DWORD [20+esp],471859200
-	mov	DWORD [24+esp],943718400
-	mov	DWORD [28+esp],610271232
-	mov	DWORD [32+esp],1887436800
-	mov	DWORD [36+esp],1822425088
-	mov	DWORD [40+esp],1220542464
-	mov	DWORD [44+esp],1423966208
-	mov	DWORD [48+esp],3774873600
-	mov	DWORD [52+esp],4246732800
-	mov	DWORD [56+esp],3644850176
-	mov	DWORD [60+esp],3311403008
-	mov	DWORD [64+esp],2441084928
-	mov	DWORD [68+esp],2376073216
-	mov	DWORD [72+esp],2847932416
-	mov	DWORD [76+esp],3051356160
-align	16
-L$002x86_outer_loop:
-	xor	ebx,DWORD [12+edi]
-	xor	ecx,DWORD [8+edi]
-	xor	edx,DWORD [4+edi]
-	xor	ebp,DWORD [edi]
-	mov	DWORD [12+esp],ebx
-	mov	DWORD [8+esp],ecx
-	mov	DWORD [4+esp],edx
-	mov	DWORD [esp],ebp
-	shr	ebx,20
-	and	ebx,240
-	mov	ebp,DWORD [4+ebx*1+esi]
-	mov	edx,DWORD [ebx*1+esi]
-	mov	ecx,DWORD [12+ebx*1+esi]
-	mov	ebx,DWORD [8+ebx*1+esi]
-	xor	eax,eax
-	mov	edi,15
-	jmp	NEAR L$003x86_loop
-align	16
-L$003x86_loop:
-	mov	al,bl
-	shrd	ebx,ecx,4
-	and	al,15
-	shrd	ecx,edx,4
-	shrd	edx,ebp,4
-	shr	ebp,4
-	xor	ebp,DWORD [16+eax*4+esp]
-	mov	al,BYTE [edi*1+esp]
-	and	al,240
-	xor	ebx,DWORD [8+eax*1+esi]
-	xor	ecx,DWORD [12+eax*1+esi]
-	xor	edx,DWORD [eax*1+esi]
-	xor	ebp,DWORD [4+eax*1+esi]
-	dec	edi
-	js	NEAR L$004x86_break
-	mov	al,bl
-	shrd	ebx,ecx,4
-	and	al,15
-	shrd	ecx,edx,4
-	shrd	edx,ebp,4
-	shr	ebp,4
-	xor	ebp,DWORD [16+eax*4+esp]
-	mov	al,BYTE [edi*1+esp]
-	shl	al,4
-	xor	ebx,DWORD [8+eax*1+esi]
-	xor	ecx,DWORD [12+eax*1+esi]
-	xor	edx,DWORD [eax*1+esi]
-	xor	ebp,DWORD [4+eax*1+esi]
-	jmp	NEAR L$003x86_loop
-align	16
-L$004x86_break:
-	bswap	ebx
-	bswap	ecx
-	bswap	edx
-	bswap	ebp
-	mov	edi,DWORD [112+esp]
-	lea	edi,[16+edi]
-	cmp	edi,DWORD [116+esp]
-	mov	DWORD [112+esp],edi
-	jb	NEAR L$002x86_outer_loop
-	mov	edi,DWORD [104+esp]
-	mov	DWORD [12+edi],ebx
-	mov	DWORD [8+edi],ecx
-	mov	DWORD [4+edi],edx
-	mov	DWORD [edi],ebp
-	add	esp,84
-	pop	edi
-	pop	esi
-	pop	ebx
-	pop	ebp
-	ret
 global	_gcm_gmult_4bit_mmx
 align	16
 _gcm_gmult_4bit_mmx:
@@ -223,10 +24,10 @@
 	push	edi
 	mov	edi,DWORD [20+esp]
 	mov	esi,DWORD [24+esp]
-	call	L$005pic_point
-L$005pic_point:
+	call	L$000pic_point
+L$000pic_point:
 	pop	eax
-	lea	eax,[(L$rem_4bit-L$005pic_point)+eax]
+	lea	eax,[(L$rem_4bit-L$000pic_point)+eax]
 	movzx	ebx,BYTE [15+edi]
 	xor	ecx,ecx
 	mov	edx,ebx
@@ -237,9 +38,9 @@
 	movq	mm0,[8+ecx*1+esi]
 	movq	mm1,[ecx*1+esi]
 	movd	ebx,mm0
-	jmp	NEAR L$006mmx_loop
+	jmp	NEAR L$001mmx_loop
 align	16
-L$006mmx_loop:
+L$001mmx_loop:
 	psrlq	mm0,4
 	and	ebx,15
 	movq	mm2,mm1
@@ -253,7 +54,7 @@
 	pxor	mm1,[edx*1+esi]
 	mov	edx,ecx
 	pxor	mm0,mm2
-	js	NEAR L$007mmx_break
+	js	NEAR L$002mmx_break
 	shl	cl,4
 	and	ebx,15
 	psrlq	mm0,4
@@ -266,9 +67,9 @@
 	movd	ebx,mm0
 	pxor	mm1,[ecx*1+esi]
 	pxor	mm0,mm2
-	jmp	NEAR L$006mmx_loop
+	jmp	NEAR L$001mmx_loop
 align	16
-L$007mmx_break:
+L$002mmx_break:
 	shl	cl,4
 	and	ebx,15
 	psrlq	mm0,4
@@ -323,10 +124,10 @@
 	mov	ecx,DWORD [28+esp]
 	mov	edx,DWORD [32+esp]
 	mov	ebp,esp
-	call	L$008pic_point
-L$008pic_point:
+	call	L$003pic_point
+L$003pic_point:
 	pop	esi
-	lea	esi,[(L$rem_8bit-L$008pic_point)+esi]
+	lea	esi,[(L$rem_8bit-L$003pic_point)+esi]
 	sub	esp,544
 	and	esp,-64
 	sub	esp,16
@@ -565,7 +366,7 @@
 	mov	ebx,DWORD [8+eax]
 	mov	edx,DWORD [12+eax]
 align	16
-L$009outer:
+L$004outer:
 	xor	edx,DWORD [12+ecx]
 	xor	ebx,DWORD [8+ecx]
 	pxor	mm6,[ecx]
@@ -900,7 +701,7 @@
 	pshufw	mm6,mm6,27
 	bswap	ebx
 	cmp	ecx,DWORD [552+esp]
-	jne	NEAR L$009outer
+	jne	NEAR L$004outer
 	mov	eax,DWORD [544+esp]
 	mov	DWORD [12+eax],edx
 	mov	DWORD [8+eax],ebx
@@ -918,10 +719,10 @@
 L$_gcm_init_clmul_begin:
 	mov	edx,DWORD [4+esp]
 	mov	eax,DWORD [8+esp]
-	call	L$010pic
-L$010pic:
+	call	L$005pic
+L$005pic:
 	pop	ecx
-	lea	ecx,[(L$bswap-L$010pic)+ecx]
+	lea	ecx,[(L$bswap-L$005pic)+ecx]
 	movdqu	xmm2,[eax]
 	pshufd	xmm2,xmm2,78
 	pshufd	xmm4,xmm2,255
@@ -985,10 +786,10 @@
 L$_gcm_gmult_clmul_begin:
 	mov	eax,DWORD [4+esp]
 	mov	edx,DWORD [8+esp]
-	call	L$011pic
-L$011pic:
+	call	L$006pic
+L$006pic:
 	pop	ecx
-	lea	ecx,[(L$bswap-L$011pic)+ecx]
+	lea	ecx,[(L$bswap-L$006pic)+ecx]
 	movdqu	xmm0,[eax]
 	movdqa	xmm5,[ecx]
 	movups	xmm2,[edx]
@@ -1042,16 +843,16 @@
 	mov	edx,DWORD [24+esp]
 	mov	esi,DWORD [28+esp]
 	mov	ebx,DWORD [32+esp]
-	call	L$012pic
-L$012pic:
+	call	L$007pic
+L$007pic:
 	pop	ecx
-	lea	ecx,[(L$bswap-L$012pic)+ecx]
+	lea	ecx,[(L$bswap-L$007pic)+ecx]
 	movdqu	xmm0,[eax]
 	movdqa	xmm5,[ecx]
 	movdqu	xmm2,[edx]
 db	102,15,56,0,197
 	sub	ebx,16
-	jz	NEAR L$013odd_tail
+	jz	NEAR L$008odd_tail
 	movdqu	xmm3,[esi]
 	movdqu	xmm6,[16+esi]
 db	102,15,56,0,221
@@ -1068,10 +869,10 @@
 	movups	xmm2,[16+edx]
 	nop
 	sub	ebx,32
-	jbe	NEAR L$014even_tail
-	jmp	NEAR L$015mod_loop
+	jbe	NEAR L$009even_tail
+	jmp	NEAR L$010mod_loop
 align	32
-L$015mod_loop:
+L$010mod_loop:
 	pshufd	xmm4,xmm0,78
 	movdqa	xmm1,xmm0
 	pxor	xmm4,xmm0
@@ -1126,8 +927,8 @@
 db	102,15,58,68,221,0
 	lea	esi,[32+esi]
 	sub	ebx,32
-	ja	NEAR L$015mod_loop
-L$014even_tail:
+	ja	NEAR L$010mod_loop
+L$009even_tail:
 	pshufd	xmm4,xmm0,78
 	movdqa	xmm1,xmm0
 	pxor	xmm4,xmm0
@@ -1166,9 +967,9 @@
 	psrlq	xmm0,1
 	pxor	xmm0,xmm1
 	test	ebx,ebx
-	jnz	NEAR L$016done
+	jnz	NEAR L$011done
 	movups	xmm2,[edx]
-L$013odd_tail:
+L$008odd_tail:
 	movdqu	xmm3,[esi]
 db	102,15,56,0,221
 	pxor	xmm0,xmm3
@@ -1207,7 +1008,7 @@
 	pxor	xmm0,xmm4
 	psrlq	xmm0,1
 	pxor	xmm0,xmm1
-L$016done:
+L$011done:
 db	102,15,56,0,197
 	movdqu	[eax],xmm0
 	pop	edi
diff --git a/win-x86/crypto/rc4/rc4-586.asm b/win-x86/crypto/rc4/rc4-586.asm
deleted file mode 100644
index 08cd9f6..0000000
--- a/win-x86/crypto/rc4/rc4-586.asm
+++ /dev/null
@@ -1,382 +0,0 @@
-%ifidn __OUTPUT_FORMAT__,obj
-section	code	use32 class=code align=64
-%elifidn __OUTPUT_FORMAT__,win32
-%ifdef __YASM_VERSION_ID__
-%if __YASM_VERSION_ID__ < 01010000h
-%error yasm version 1.1.0 or later needed.
-%endif
-; Yasm automatically includes .00 and complains about redefining it.
-; https://www.tortall.net/projects/yasm/manual/html/objfmt-win32-safeseh.html
-%else
-$@feat.00 equ 1
-%endif
-section	.text	code align=64
-%else
-section	.text	code
-%endif
-;extern	_OPENSSL_ia32cap_P
-global	_asm_RC4
-align	16
-_asm_RC4:
-L$_asm_RC4_begin:
-	push	ebp
-	push	ebx
-	push	esi
-	push	edi
-	mov	edi,DWORD [20+esp]
-	mov	edx,DWORD [24+esp]
-	mov	esi,DWORD [28+esp]
-	mov	ebp,DWORD [32+esp]
-	xor	eax,eax
-	xor	ebx,ebx
-	cmp	edx,0
-	je	NEAR L$000abort
-	mov	al,BYTE [edi]
-	mov	bl,BYTE [4+edi]
-	add	edi,8
-	lea	ecx,[edx*1+esi]
-	sub	ebp,esi
-	mov	DWORD [24+esp],ecx
-	inc	al
-	cmp	DWORD [256+edi],-1
-	je	NEAR L$001RC4_CHAR
-	mov	ecx,DWORD [eax*4+edi]
-	and	edx,-4
-	jz	NEAR L$002loop1
-	mov	DWORD [32+esp],ebp
-	test	edx,-8
-	jz	NEAR L$003go4loop4
-	lea	ebp,[_OPENSSL_ia32cap_P]
-	bt	DWORD [ebp],26
-	jnc	NEAR L$003go4loop4
-	mov	ebp,DWORD [32+esp]
-	and	edx,-8
-	lea	edx,[edx*1+esi-8]
-	mov	DWORD [edi-4],edx
-	add	bl,cl
-	mov	edx,DWORD [ebx*4+edi]
-	mov	DWORD [ebx*4+edi],ecx
-	mov	DWORD [eax*4+edi],edx
-	inc	eax
-	add	edx,ecx
-	movzx	eax,al
-	movzx	edx,dl
-	movq	mm0,[esi]
-	mov	ecx,DWORD [eax*4+edi]
-	movd	mm2,DWORD [edx*4+edi]
-	jmp	NEAR L$004loop_mmx_enter
-align	16
-L$005loop_mmx:
-	add	bl,cl
-	psllq	mm1,56
-	mov	edx,DWORD [ebx*4+edi]
-	mov	DWORD [ebx*4+edi],ecx
-	mov	DWORD [eax*4+edi],edx
-	inc	eax
-	add	edx,ecx
-	movzx	eax,al
-	movzx	edx,dl
-	pxor	mm2,mm1
-	movq	mm0,[esi]
-	movq	[esi*1+ebp-8],mm2
-	mov	ecx,DWORD [eax*4+edi]
-	movd	mm2,DWORD [edx*4+edi]
-L$004loop_mmx_enter:
-	add	bl,cl
-	mov	edx,DWORD [ebx*4+edi]
-	mov	DWORD [ebx*4+edi],ecx
-	mov	DWORD [eax*4+edi],edx
-	inc	eax
-	add	edx,ecx
-	movzx	eax,al
-	movzx	edx,dl
-	pxor	mm2,mm0
-	mov	ecx,DWORD [eax*4+edi]
-	movd	mm1,DWORD [edx*4+edi]
-	add	bl,cl
-	psllq	mm1,8
-	mov	edx,DWORD [ebx*4+edi]
-	mov	DWORD [ebx*4+edi],ecx
-	mov	DWORD [eax*4+edi],edx
-	inc	eax
-	add	edx,ecx
-	movzx	eax,al
-	movzx	edx,dl
-	pxor	mm2,mm1
-	mov	ecx,DWORD [eax*4+edi]
-	movd	mm1,DWORD [edx*4+edi]
-	add	bl,cl
-	psllq	mm1,16
-	mov	edx,DWORD [ebx*4+edi]
-	mov	DWORD [ebx*4+edi],ecx
-	mov	DWORD [eax*4+edi],edx
-	inc	eax
-	add	edx,ecx
-	movzx	eax,al
-	movzx	edx,dl
-	pxor	mm2,mm1
-	mov	ecx,DWORD [eax*4+edi]
-	movd	mm1,DWORD [edx*4+edi]
-	add	bl,cl
-	psllq	mm1,24
-	mov	edx,DWORD [ebx*4+edi]
-	mov	DWORD [ebx*4+edi],ecx
-	mov	DWORD [eax*4+edi],edx
-	inc	eax
-	add	edx,ecx
-	movzx	eax,al
-	movzx	edx,dl
-	pxor	mm2,mm1
-	mov	ecx,DWORD [eax*4+edi]
-	movd	mm1,DWORD [edx*4+edi]
-	add	bl,cl
-	psllq	mm1,32
-	mov	edx,DWORD [ebx*4+edi]
-	mov	DWORD [ebx*4+edi],ecx
-	mov	DWORD [eax*4+edi],edx
-	inc	eax
-	add	edx,ecx
-	movzx	eax,al
-	movzx	edx,dl
-	pxor	mm2,mm1
-	mov	ecx,DWORD [eax*4+edi]
-	movd	mm1,DWORD [edx*4+edi]
-	add	bl,cl
-	psllq	mm1,40
-	mov	edx,DWORD [ebx*4+edi]
-	mov	DWORD [ebx*4+edi],ecx
-	mov	DWORD [eax*4+edi],edx
-	inc	eax
-	add	edx,ecx
-	movzx	eax,al
-	movzx	edx,dl
-	pxor	mm2,mm1
-	mov	ecx,DWORD [eax*4+edi]
-	movd	mm1,DWORD [edx*4+edi]
-	add	bl,cl
-	psllq	mm1,48
-	mov	edx,DWORD [ebx*4+edi]
-	mov	DWORD [ebx*4+edi],ecx
-	mov	DWORD [eax*4+edi],edx
-	inc	eax
-	add	edx,ecx
-	movzx	eax,al
-	movzx	edx,dl
-	pxor	mm2,mm1
-	mov	ecx,DWORD [eax*4+edi]
-	movd	mm1,DWORD [edx*4+edi]
-	mov	edx,ebx
-	xor	ebx,ebx
-	mov	bl,dl
-	cmp	esi,DWORD [edi-4]
-	lea	esi,[8+esi]
-	jb	NEAR L$005loop_mmx
-	psllq	mm1,56
-	pxor	mm2,mm1
-	movq	[esi*1+ebp-8],mm2
-	emms
-	cmp	esi,DWORD [24+esp]
-	je	NEAR L$006done
-	jmp	NEAR L$002loop1
-align	16
-L$003go4loop4:
-	lea	edx,[edx*1+esi-4]
-	mov	DWORD [28+esp],edx
-L$007loop4:
-	add	bl,cl
-	mov	edx,DWORD [ebx*4+edi]
-	mov	DWORD [ebx*4+edi],ecx
-	mov	DWORD [eax*4+edi],edx
-	add	edx,ecx
-	inc	al
-	and	edx,255
-	mov	ecx,DWORD [eax*4+edi]
-	mov	ebp,DWORD [edx*4+edi]
-	add	bl,cl
-	mov	edx,DWORD [ebx*4+edi]
-	mov	DWORD [ebx*4+edi],ecx
-	mov	DWORD [eax*4+edi],edx
-	add	edx,ecx
-	inc	al
-	and	edx,255
-	ror	ebp,8
-	mov	ecx,DWORD [eax*4+edi]
-	or	ebp,DWORD [edx*4+edi]
-	add	bl,cl
-	mov	edx,DWORD [ebx*4+edi]
-	mov	DWORD [ebx*4+edi],ecx
-	mov	DWORD [eax*4+edi],edx
-	add	edx,ecx
-	inc	al
-	and	edx,255
-	ror	ebp,8
-	mov	ecx,DWORD [eax*4+edi]
-	or	ebp,DWORD [edx*4+edi]
-	add	bl,cl
-	mov	edx,DWORD [ebx*4+edi]
-	mov	DWORD [ebx*4+edi],ecx
-	mov	DWORD [eax*4+edi],edx
-	add	edx,ecx
-	inc	al
-	and	edx,255
-	ror	ebp,8
-	mov	ecx,DWORD [32+esp]
-	or	ebp,DWORD [edx*4+edi]
-	ror	ebp,8
-	xor	ebp,DWORD [esi]
-	cmp	esi,DWORD [28+esp]
-	mov	DWORD [esi*1+ecx],ebp
-	lea	esi,[4+esi]
-	mov	ecx,DWORD [eax*4+edi]
-	jb	NEAR L$007loop4
-	cmp	esi,DWORD [24+esp]
-	je	NEAR L$006done
-	mov	ebp,DWORD [32+esp]
-align	16
-L$002loop1:
-	add	bl,cl
-	mov	edx,DWORD [ebx*4+edi]
-	mov	DWORD [ebx*4+edi],ecx
-	mov	DWORD [eax*4+edi],edx
-	add	edx,ecx
-	inc	al
-	and	edx,255
-	mov	edx,DWORD [edx*4+edi]
-	xor	dl,BYTE [esi]
-	lea	esi,[1+esi]
-	mov	ecx,DWORD [eax*4+edi]
-	cmp	esi,DWORD [24+esp]
-	mov	BYTE [esi*1+ebp-1],dl
-	jb	NEAR L$002loop1
-	jmp	NEAR L$006done
-align	16
-L$001RC4_CHAR:
-	movzx	ecx,BYTE [eax*1+edi]
-L$008cloop1:
-	add	bl,cl
-	movzx	edx,BYTE [ebx*1+edi]
-	mov	BYTE [ebx*1+edi],cl
-	mov	BYTE [eax*1+edi],dl
-	add	dl,cl
-	movzx	edx,BYTE [edx*1+edi]
-	add	al,1
-	xor	dl,BYTE [esi]
-	lea	esi,[1+esi]
-	movzx	ecx,BYTE [eax*1+edi]
-	cmp	esi,DWORD [24+esp]
-	mov	BYTE [esi*1+ebp-1],dl
-	jb	NEAR L$008cloop1
-L$006done:
-	dec	al
-	mov	DWORD [edi-4],ebx
-	mov	BYTE [edi-8],al
-L$000abort:
-	pop	edi
-	pop	esi
-	pop	ebx
-	pop	ebp
-	ret
-global	_asm_RC4_set_key
-align	16
-_asm_RC4_set_key:
-L$_asm_RC4_set_key_begin:
-	push	ebp
-	push	ebx
-	push	esi
-	push	edi
-	mov	edi,DWORD [20+esp]
-	mov	ebp,DWORD [24+esp]
-	mov	esi,DWORD [28+esp]
-	lea	edx,[_OPENSSL_ia32cap_P]
-	lea	edi,[8+edi]
-	lea	esi,[ebp*1+esi]
-	neg	ebp
-	xor	eax,eax
-	mov	DWORD [edi-4],ebp
-	bt	DWORD [edx],20
-	jc	NEAR L$009c1stloop
-align	16
-L$010w1stloop:
-	mov	DWORD [eax*4+edi],eax
-	add	al,1
-	jnc	NEAR L$010w1stloop
-	xor	ecx,ecx
-	xor	edx,edx
-align	16
-L$011w2ndloop:
-	mov	eax,DWORD [ecx*4+edi]
-	add	dl,BYTE [ebp*1+esi]
-	add	dl,al
-	add	ebp,1
-	mov	ebx,DWORD [edx*4+edi]
-	jnz	NEAR L$012wnowrap
-	mov	ebp,DWORD [edi-4]
-L$012wnowrap:
-	mov	DWORD [edx*4+edi],eax
-	mov	DWORD [ecx*4+edi],ebx
-	add	cl,1
-	jnc	NEAR L$011w2ndloop
-	jmp	NEAR L$013exit
-align	16
-L$009c1stloop:
-	mov	BYTE [eax*1+edi],al
-	add	al,1
-	jnc	NEAR L$009c1stloop
-	xor	ecx,ecx
-	xor	edx,edx
-	xor	ebx,ebx
-align	16
-L$014c2ndloop:
-	mov	al,BYTE [ecx*1+edi]
-	add	dl,BYTE [ebp*1+esi]
-	add	dl,al
-	add	ebp,1
-	mov	bl,BYTE [edx*1+edi]
-	jnz	NEAR L$015cnowrap
-	mov	ebp,DWORD [edi-4]
-L$015cnowrap:
-	mov	BYTE [edx*1+edi],al
-	mov	BYTE [ecx*1+edi],bl
-	add	cl,1
-	jnc	NEAR L$014c2ndloop
-	mov	DWORD [256+edi],-1
-L$013exit:
-	xor	eax,eax
-	mov	DWORD [edi-8],eax
-	mov	DWORD [edi-4],eax
-	pop	edi
-	pop	esi
-	pop	ebx
-	pop	ebp
-	ret
-global	_RC4_options
-align	16
-_RC4_options:
-L$_RC4_options_begin:
-	call	L$016pic_point
-L$016pic_point:
-	pop	eax
-	lea	eax,[(L$017opts-L$016pic_point)+eax]
-	lea	edx,[_OPENSSL_ia32cap_P]
-	mov	edx,DWORD [edx]
-	bt	edx,20
-	jc	NEAR L$0181xchar
-	bt	edx,26
-	jnc	NEAR L$019ret
-	add	eax,25
-	ret
-L$0181xchar:
-	add	eax,12
-L$019ret:
-	ret
-align	64
-L$017opts:
-db	114,99,52,40,52,120,44,105,110,116,41,0
-db	114,99,52,40,49,120,44,99,104,97,114,41,0
-db	114,99,52,40,56,120,44,109,109,120,41,0
-db	82,67,52,32,102,111,114,32,120,56,54,44,32,67,82,89
-db	80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114
-db	111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
-align	64
-segment	.bss
-common	_OPENSSL_ia32cap_P 16
diff --git a/win-x86_64/crypto/aes/aes-x86_64.asm b/win-x86_64/crypto/aes/aes-x86_64.asm
index 53394f0..3db1846 100644
--- a/win-x86_64/crypto/aes/aes-x86_64.asm
+++ b/win-x86_64/crypto/aes/aes-x86_64.asm
@@ -344,6 +344,7 @@
 	mov	rdx,r8
 
 
+	mov	rax,rsp
 	push	rbx
 	push	rbp
 	push	r12
@@ -352,7 +353,6 @@
 	push	r15
 
 
-	mov	r10,rsp
 	lea	rcx,[((-63))+rdx]
 	and	rsp,-64
 	sub	rcx,rsp
@@ -362,7 +362,7 @@
 	sub	rsp,32
 
 	mov	QWORD[16+rsp],rsi
-	mov	QWORD[24+rsp],r10
+	mov	QWORD[24+rsp],rax
 $L$enc_prologue:
 
 	mov	r15,rdx
@@ -394,13 +394,13 @@
 	mov	DWORD[8+r9],ecx
 	mov	DWORD[12+r9],edx
 
-	mov	r15,QWORD[rsi]
-	mov	r14,QWORD[8+rsi]
-	mov	r13,QWORD[16+rsi]
-	mov	r12,QWORD[24+rsi]
-	mov	rbp,QWORD[32+rsi]
-	mov	rbx,QWORD[40+rsi]
-	lea	rsp,[48+rsi]
+	mov	r15,QWORD[((-48))+rsi]
+	mov	r14,QWORD[((-40))+rsi]
+	mov	r13,QWORD[((-32))+rsi]
+	mov	r12,QWORD[((-24))+rsi]
+	mov	rbp,QWORD[((-16))+rsi]
+	mov	rbx,QWORD[((-8))+rsi]
+	lea	rsp,[rsi]
 $L$enc_epilogue:
 	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
 	mov	rsi,QWORD[16+rsp]
@@ -800,6 +800,7 @@
 	mov	rdx,r8
 
 
+	mov	rax,rsp
 	push	rbx
 	push	rbp
 	push	r12
@@ -808,7 +809,6 @@
 	push	r15
 
 
-	mov	r10,rsp
 	lea	rcx,[((-63))+rdx]
 	and	rsp,-64
 	sub	rcx,rsp
@@ -818,7 +818,7 @@
 	sub	rsp,32
 
 	mov	QWORD[16+rsp],rsi
-	mov	QWORD[24+rsp],r10
+	mov	QWORD[24+rsp],rax
 $L$dec_prologue:
 
 	mov	r15,rdx
@@ -852,13 +852,13 @@
 	mov	DWORD[8+r9],ecx
 	mov	DWORD[12+r9],edx
 
-	mov	r15,QWORD[rsi]
-	mov	r14,QWORD[8+rsi]
-	mov	r13,QWORD[16+rsi]
-	mov	r12,QWORD[24+rsi]
-	mov	rbp,QWORD[32+rsi]
-	mov	rbx,QWORD[40+rsi]
-	lea	rsp,[48+rsi]
+	mov	r15,QWORD[((-48))+rsi]
+	mov	r14,QWORD[((-40))+rsi]
+	mov	r13,QWORD[((-32))+rsi]
+	mov	r12,QWORD[((-24))+rsi]
+	mov	rbp,QWORD[((-16))+rsi]
+	mov	rbx,QWORD[((-8))+rsi]
+	lea	rsp,[rsi]
 $L$dec_epilogue:
 	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
 	mov	rsi,QWORD[16+rsp]
@@ -1367,10 +1367,9 @@
 	mov	r9d,r9d
 
 	lea	r14,[$L$AES_Te]
+	lea	r10,[$L$AES_Td]
 	cmp	r9,0
-	jne	NEAR $L$cbc_picked_te
-	lea	r14,[$L$AES_Td]
-$L$cbc_picked_te:
+	cmove	r14,r10
 
 	mov	r10d,DWORD[OPENSSL_ia32cap_P]
 	cmp	rdx,512
@@ -2626,7 +2625,6 @@
 	jae	NEAR $L$in_block_prologue
 
 	mov	rax,QWORD[24+rax]
-	lea	rax,[48+rax]
 
 	mov	rbx,QWORD[((-8))+rax]
 	mov	rbp,QWORD[((-16))+rax]
diff --git a/win-x86_64/crypto/aes/aesni-x86_64.asm b/win-x86_64/crypto/aes/aesni-x86_64.asm
index cf313d1..d5d454d 100644
--- a/win-x86_64/crypto/aes/aesni-x86_64.asm
+++ b/win-x86_64/crypto/aes/aesni-x86_64.asm
@@ -1129,22 +1129,21 @@
 
 ALIGN	16
 $L$ctr32_bulk:
-	lea	rax,[rsp]
+	lea	r11,[rsp]
 	push	rbp
 	sub	rsp,288
 	and	rsp,-16
-	movaps	XMMWORD[(-168)+rax],xmm6
-	movaps	XMMWORD[(-152)+rax],xmm7
-	movaps	XMMWORD[(-136)+rax],xmm8
-	movaps	XMMWORD[(-120)+rax],xmm9
-	movaps	XMMWORD[(-104)+rax],xmm10
-	movaps	XMMWORD[(-88)+rax],xmm11
-	movaps	XMMWORD[(-72)+rax],xmm12
-	movaps	XMMWORD[(-56)+rax],xmm13
-	movaps	XMMWORD[(-40)+rax],xmm14
-	movaps	XMMWORD[(-24)+rax],xmm15
+	movaps	XMMWORD[(-168)+r11],xmm6
+	movaps	XMMWORD[(-152)+r11],xmm7
+	movaps	XMMWORD[(-136)+r11],xmm8
+	movaps	XMMWORD[(-120)+r11],xmm9
+	movaps	XMMWORD[(-104)+r11],xmm10
+	movaps	XMMWORD[(-88)+r11],xmm11
+	movaps	XMMWORD[(-72)+r11],xmm12
+	movaps	XMMWORD[(-56)+r11],xmm13
+	movaps	XMMWORD[(-40)+r11],xmm14
+	movaps	XMMWORD[(-24)+r11],xmm15
 $L$ctr32_body:
-	lea	rbp,[((-8))+rax]
 
 
 
@@ -1153,7 +1152,7 @@
 	movdqu	xmm0,XMMWORD[rcx]
 	mov	r8d,DWORD[12+r8]
 	pxor	xmm2,xmm0
-	mov	r11d,DWORD[12+rcx]
+	mov	ebp,DWORD[12+rcx]
 	movdqa	XMMWORD[rsp],xmm2
 	bswap	r8d
 	movdqa	xmm3,xmm2
@@ -1169,8 +1168,8 @@
 	lea	rdx,[2+r8]
 	bswap	eax
 	bswap	edx
-	xor	eax,r11d
-	xor	edx,r11d
+	xor	eax,ebp
+	xor	edx,ebp
 DB	102,15,58,34,216,3
 	lea	rax,[3+r8]
 	movdqa	XMMWORD[16+rsp],xmm3
@@ -1179,25 +1178,25 @@
 	mov	rdx,r10
 	lea	r10,[4+r8]
 	movdqa	XMMWORD[32+rsp],xmm4
-	xor	eax,r11d
+	xor	eax,ebp
 	bswap	r10d
 DB	102,15,58,34,232,3
-	xor	r10d,r11d
+	xor	r10d,ebp
 	movdqa	XMMWORD[48+rsp],xmm5
 	lea	r9,[5+r8]
 	mov	DWORD[((64+12))+rsp],r10d
 	bswap	r9d
 	lea	r10,[6+r8]
 	mov	eax,DWORD[240+rcx]
-	xor	r9d,r11d
+	xor	r9d,ebp
 	bswap	r10d
 	mov	DWORD[((80+12))+rsp],r9d
-	xor	r10d,r11d
+	xor	r10d,ebp
 	lea	r9,[7+r8]
 	mov	DWORD[((96+12))+rsp],r10d
 	bswap	r9d
 	mov	r10d,DWORD[((OPENSSL_ia32cap_P+4))]
-	xor	r9d,r11d
+	xor	r9d,ebp
 	and	r10d,71303168
 	mov	DWORD[((112+12))+rsp],r9d
 
@@ -1221,7 +1220,7 @@
 $L$ctr32_6x:
 	shl	eax,4
 	mov	r10d,48
-	bswap	r11d
+	bswap	ebp
 	lea	rcx,[32+rax*1+rcx]
 	sub	r10,rax
 	jmp	NEAR $L$ctr32_loop6
@@ -1232,32 +1231,32 @@
 	movups	xmm0,XMMWORD[((-48))+r10*1+rcx]
 DB	102,15,56,220,209
 	mov	eax,r8d
-	xor	eax,r11d
+	xor	eax,ebp
 DB	102,15,56,220,217
 DB	0x0f,0x38,0xf1,0x44,0x24,12
 	lea	eax,[1+r8]
 DB	102,15,56,220,225
-	xor	eax,r11d
+	xor	eax,ebp
 DB	0x0f,0x38,0xf1,0x44,0x24,28
 DB	102,15,56,220,233
 	lea	eax,[2+r8]
-	xor	eax,r11d
+	xor	eax,ebp
 DB	102,15,56,220,241
 DB	0x0f,0x38,0xf1,0x44,0x24,44
 	lea	eax,[3+r8]
 DB	102,15,56,220,249
 	movups	xmm1,XMMWORD[((-32))+r10*1+rcx]
-	xor	eax,r11d
+	xor	eax,ebp
 
 DB	102,15,56,220,208
 DB	0x0f,0x38,0xf1,0x44,0x24,60
 	lea	eax,[4+r8]
 DB	102,15,56,220,216
-	xor	eax,r11d
+	xor	eax,ebp
 DB	0x0f,0x38,0xf1,0x44,0x24,76
 DB	102,15,56,220,224
 	lea	eax,[5+r8]
-	xor	eax,r11d
+	xor	eax,ebp
 DB	102,15,56,220,232
 DB	0x0f,0x38,0xf1,0x44,0x24,92
 	mov	rax,r10
@@ -1318,7 +1317,7 @@
 	bswap	r9d
 	movups	xmm0,XMMWORD[((32-128))+rcx]
 DB	102,15,56,220,225
-	xor	r9d,r11d
+	xor	r9d,ebp
 	nop
 DB	102,15,56,220,233
 	mov	DWORD[((0+12))+rsp],r9d
@@ -1331,7 +1330,7 @@
 	bswap	r9d
 DB	102,15,56,220,208
 DB	102,15,56,220,216
-	xor	r9d,r11d
+	xor	r9d,ebp
 DB	0x66,0x90
 DB	102,15,56,220,224
 DB	102,15,56,220,232
@@ -1345,7 +1344,7 @@
 	bswap	r9d
 DB	102,15,56,220,209
 DB	102,15,56,220,217
-	xor	r9d,r11d
+	xor	r9d,ebp
 DB	0x66,0x90
 DB	102,15,56,220,225
 DB	102,15,56,220,233
@@ -1359,7 +1358,7 @@
 	bswap	r9d
 DB	102,15,56,220,208
 DB	102,15,56,220,216
-	xor	r9d,r11d
+	xor	r9d,ebp
 DB	0x66,0x90
 DB	102,15,56,220,224
 DB	102,15,56,220,232
@@ -1373,7 +1372,7 @@
 	bswap	r9d
 DB	102,15,56,220,209
 DB	102,15,56,220,217
-	xor	r9d,r11d
+	xor	r9d,ebp
 DB	0x66,0x90
 DB	102,15,56,220,225
 DB	102,15,56,220,233
@@ -1387,7 +1386,7 @@
 	bswap	r9d
 DB	102,15,56,220,208
 DB	102,15,56,220,216
-	xor	r9d,r11d
+	xor	r9d,ebp
 DB	0x66,0x90
 DB	102,15,56,220,224
 DB	102,15,56,220,232
@@ -1401,7 +1400,7 @@
 	bswap	r9d
 DB	102,15,56,220,209
 DB	102,15,56,220,217
-	xor	r9d,r11d
+	xor	r9d,ebp
 DB	0x66,0x90
 DB	102,15,56,220,225
 DB	102,15,56,220,233
@@ -1416,7 +1415,7 @@
 DB	102,15,56,220,208
 DB	102,15,56,220,216
 DB	102,15,56,220,224
-	xor	r9d,r11d
+	xor	r9d,ebp
 	movdqu	xmm10,XMMWORD[rdi]
 DB	102,15,56,220,232
 	mov	DWORD[((112+12))+rsp],r9d
@@ -1651,32 +1650,32 @@
 
 $L$ctr32_done:
 	xorps	xmm0,xmm0
-	xor	r11d,r11d
+	xor	ebp,ebp
 	pxor	xmm1,xmm1
 	pxor	xmm2,xmm2
 	pxor	xmm3,xmm3
 	pxor	xmm4,xmm4
 	pxor	xmm5,xmm5
-	movaps	xmm6,XMMWORD[((-160))+rbp]
-	movaps	XMMWORD[(-160)+rbp],xmm0
-	movaps	xmm7,XMMWORD[((-144))+rbp]
-	movaps	XMMWORD[(-144)+rbp],xmm0
-	movaps	xmm8,XMMWORD[((-128))+rbp]
-	movaps	XMMWORD[(-128)+rbp],xmm0
-	movaps	xmm9,XMMWORD[((-112))+rbp]
-	movaps	XMMWORD[(-112)+rbp],xmm0
-	movaps	xmm10,XMMWORD[((-96))+rbp]
-	movaps	XMMWORD[(-96)+rbp],xmm0
-	movaps	xmm11,XMMWORD[((-80))+rbp]
-	movaps	XMMWORD[(-80)+rbp],xmm0
-	movaps	xmm12,XMMWORD[((-64))+rbp]
-	movaps	XMMWORD[(-64)+rbp],xmm0
-	movaps	xmm13,XMMWORD[((-48))+rbp]
-	movaps	XMMWORD[(-48)+rbp],xmm0
-	movaps	xmm14,XMMWORD[((-32))+rbp]
-	movaps	XMMWORD[(-32)+rbp],xmm0
-	movaps	xmm15,XMMWORD[((-16))+rbp]
-	movaps	XMMWORD[(-16)+rbp],xmm0
+	movaps	xmm6,XMMWORD[((-168))+r11]
+	movaps	XMMWORD[(-168)+r11],xmm0
+	movaps	xmm7,XMMWORD[((-152))+r11]
+	movaps	XMMWORD[(-152)+r11],xmm0
+	movaps	xmm8,XMMWORD[((-136))+r11]
+	movaps	XMMWORD[(-136)+r11],xmm0
+	movaps	xmm9,XMMWORD[((-120))+r11]
+	movaps	XMMWORD[(-120)+r11],xmm0
+	movaps	xmm10,XMMWORD[((-104))+r11]
+	movaps	XMMWORD[(-104)+r11],xmm0
+	movaps	xmm11,XMMWORD[((-88))+r11]
+	movaps	XMMWORD[(-88)+r11],xmm0
+	movaps	xmm12,XMMWORD[((-72))+r11]
+	movaps	XMMWORD[(-72)+r11],xmm0
+	movaps	xmm13,XMMWORD[((-56))+r11]
+	movaps	XMMWORD[(-56)+r11],xmm0
+	movaps	xmm14,XMMWORD[((-40))+r11]
+	movaps	XMMWORD[(-40)+r11],xmm0
+	movaps	xmm15,XMMWORD[((-24))+r11]
+	movaps	XMMWORD[(-24)+r11],xmm0
 	movaps	XMMWORD[rsp],xmm0
 	movaps	XMMWORD[16+rsp],xmm0
 	movaps	XMMWORD[32+rsp],xmm0
@@ -1685,8 +1684,8 @@
 	movaps	XMMWORD[80+rsp],xmm0
 	movaps	XMMWORD[96+rsp],xmm0
 	movaps	XMMWORD[112+rsp],xmm0
-	lea	rsp,[rbp]
-	pop	rbp
+	mov	rbp,QWORD[((-8))+r11]
+	lea	rsp,[r11]
 $L$ctr32_epilogue:
 	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
 	mov	rsi,QWORD[16+rsp]
@@ -1708,22 +1707,21 @@
 	mov	r9,QWORD[48+rsp]
 
 
-	lea	rax,[rsp]
+	lea	r11,[rsp]
 	push	rbp
 	sub	rsp,272
 	and	rsp,-16
-	movaps	XMMWORD[(-168)+rax],xmm6
-	movaps	XMMWORD[(-152)+rax],xmm7
-	movaps	XMMWORD[(-136)+rax],xmm8
-	movaps	XMMWORD[(-120)+rax],xmm9
-	movaps	XMMWORD[(-104)+rax],xmm10
-	movaps	XMMWORD[(-88)+rax],xmm11
-	movaps	XMMWORD[(-72)+rax],xmm12
-	movaps	XMMWORD[(-56)+rax],xmm13
-	movaps	XMMWORD[(-40)+rax],xmm14
-	movaps	XMMWORD[(-24)+rax],xmm15
+	movaps	XMMWORD[(-168)+r11],xmm6
+	movaps	XMMWORD[(-152)+r11],xmm7
+	movaps	XMMWORD[(-136)+r11],xmm8
+	movaps	XMMWORD[(-120)+r11],xmm9
+	movaps	XMMWORD[(-104)+r11],xmm10
+	movaps	XMMWORD[(-88)+r11],xmm11
+	movaps	XMMWORD[(-72)+r11],xmm12
+	movaps	XMMWORD[(-56)+r11],xmm13
+	movaps	XMMWORD[(-40)+r11],xmm14
+	movaps	XMMWORD[(-24)+r11],xmm15
 $L$xts_enc_body:
-	lea	rbp,[((-8))+rax]
 	movups	xmm2,XMMWORD[r9]
 	mov	eax,DWORD[240+r8]
 	mov	r10d,DWORD[240+rcx]
@@ -1739,7 +1737,7 @@
 	jnz	NEAR $L$oop_enc1_8
 DB	102,15,56,221,209
 	movups	xmm0,XMMWORD[rcx]
-	mov	r11,rcx
+	mov	rbp,rcx
 	mov	eax,r10d
 	shl	r10d,4
 	mov	r9,rdx
@@ -1795,9 +1793,9 @@
 	jc	NEAR $L$xts_enc_short
 
 	mov	eax,16+96
-	lea	rcx,[32+r10*1+r11]
+	lea	rcx,[32+r10*1+rbp]
 	sub	rax,r10
-	movups	xmm1,XMMWORD[16+r11]
+	movups	xmm1,XMMWORD[16+rbp]
 	mov	r10,rax
 	lea	r8,[$L$xts_magic]
 	jmp	NEAR $L$xts_enc_grandloop
@@ -1822,7 +1820,7 @@
 	movdqa	xmm9,XMMWORD[96+rsp]
 	pxor	xmm6,xmm14
 DB	102,15,56,220,233
-	movups	xmm0,XMMWORD[32+r11]
+	movups	xmm0,XMMWORD[32+rbp]
 	lea	rdi,[96+rdi]
 	pxor	xmm7,xmm8
 
@@ -1831,7 +1829,7 @@
 	pxor	xmm11,xmm9
 	movdqa	XMMWORD[rsp],xmm10
 DB	102,15,56,220,249
-	movups	xmm1,XMMWORD[48+r11]
+	movups	xmm1,XMMWORD[48+rbp]
 	pxor	xmm12,xmm9
 
 DB	102,15,56,220,208
@@ -1846,7 +1844,7 @@
 	movdqa	XMMWORD[64+rsp],xmm14
 DB	102,15,56,220,240
 DB	102,15,56,220,248
-	movups	xmm0,XMMWORD[64+r11]
+	movups	xmm0,XMMWORD[64+rbp]
 	movdqa	XMMWORD[80+rsp],xmm8
 	pshufd	xmm9,xmm15,0x5f
 	jmp	NEAR $L$xts_enc_loop6
@@ -1878,7 +1876,7 @@
 	psrad	xmm14,31
 DB	102,15,56,220,217
 	pand	xmm14,xmm8
-	movups	xmm10,XMMWORD[r11]
+	movups	xmm10,XMMWORD[rbp]
 DB	102,15,56,220,225
 DB	102,15,56,220,233
 DB	102,15,56,220,241
@@ -1946,10 +1944,10 @@
 DB	102,15,56,220,225
 DB	102,15,56,220,233
 	pxor	xmm15,xmm0
-	movups	xmm0,XMMWORD[r11]
+	movups	xmm0,XMMWORD[rbp]
 DB	102,15,56,220,241
 DB	102,15,56,220,249
-	movups	xmm1,XMMWORD[16+r11]
+	movups	xmm1,XMMWORD[16+rbp]
 
 	pxor	xmm14,xmm15
 DB	102,15,56,221,84,36,0
@@ -1976,7 +1974,7 @@
 
 	mov	eax,16+96
 	sub	eax,r10d
-	mov	rcx,r11
+	mov	rcx,rbp
 	shr	eax,4
 
 $L$xts_enc_short:
@@ -2132,7 +2130,7 @@
 	jnz	NEAR $L$xts_enc_steal
 
 	sub	rsi,r9
-	mov	rcx,r11
+	mov	rcx,rbp
 	mov	eax,r10d
 
 	movups	xmm2,XMMWORD[((-16))+rsi]
@@ -2158,26 +2156,26 @@
 	pxor	xmm3,xmm3
 	pxor	xmm4,xmm4
 	pxor	xmm5,xmm5
-	movaps	xmm6,XMMWORD[((-160))+rbp]
-	movaps	XMMWORD[(-160)+rbp],xmm0
-	movaps	xmm7,XMMWORD[((-144))+rbp]
-	movaps	XMMWORD[(-144)+rbp],xmm0
-	movaps	xmm8,XMMWORD[((-128))+rbp]
-	movaps	XMMWORD[(-128)+rbp],xmm0
-	movaps	xmm9,XMMWORD[((-112))+rbp]
-	movaps	XMMWORD[(-112)+rbp],xmm0
-	movaps	xmm10,XMMWORD[((-96))+rbp]
-	movaps	XMMWORD[(-96)+rbp],xmm0
-	movaps	xmm11,XMMWORD[((-80))+rbp]
-	movaps	XMMWORD[(-80)+rbp],xmm0
-	movaps	xmm12,XMMWORD[((-64))+rbp]
-	movaps	XMMWORD[(-64)+rbp],xmm0
-	movaps	xmm13,XMMWORD[((-48))+rbp]
-	movaps	XMMWORD[(-48)+rbp],xmm0
-	movaps	xmm14,XMMWORD[((-32))+rbp]
-	movaps	XMMWORD[(-32)+rbp],xmm0
-	movaps	xmm15,XMMWORD[((-16))+rbp]
-	movaps	XMMWORD[(-16)+rbp],xmm0
+	movaps	xmm6,XMMWORD[((-168))+r11]
+	movaps	XMMWORD[(-168)+r11],xmm0
+	movaps	xmm7,XMMWORD[((-152))+r11]
+	movaps	XMMWORD[(-152)+r11],xmm0
+	movaps	xmm8,XMMWORD[((-136))+r11]
+	movaps	XMMWORD[(-136)+r11],xmm0
+	movaps	xmm9,XMMWORD[((-120))+r11]
+	movaps	XMMWORD[(-120)+r11],xmm0
+	movaps	xmm10,XMMWORD[((-104))+r11]
+	movaps	XMMWORD[(-104)+r11],xmm0
+	movaps	xmm11,XMMWORD[((-88))+r11]
+	movaps	XMMWORD[(-88)+r11],xmm0
+	movaps	xmm12,XMMWORD[((-72))+r11]
+	movaps	XMMWORD[(-72)+r11],xmm0
+	movaps	xmm13,XMMWORD[((-56))+r11]
+	movaps	XMMWORD[(-56)+r11],xmm0
+	movaps	xmm14,XMMWORD[((-40))+r11]
+	movaps	XMMWORD[(-40)+r11],xmm0
+	movaps	xmm15,XMMWORD[((-24))+r11]
+	movaps	XMMWORD[(-24)+r11],xmm0
 	movaps	XMMWORD[rsp],xmm0
 	movaps	XMMWORD[16+rsp],xmm0
 	movaps	XMMWORD[32+rsp],xmm0
@@ -2185,8 +2183,8 @@
 	movaps	XMMWORD[64+rsp],xmm0
 	movaps	XMMWORD[80+rsp],xmm0
 	movaps	XMMWORD[96+rsp],xmm0
-	lea	rsp,[rbp]
-	pop	rbp
+	mov	rbp,QWORD[((-8))+r11]
+	lea	rsp,[r11]
 $L$xts_enc_epilogue:
 	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
 	mov	rsi,QWORD[16+rsp]
@@ -2208,22 +2206,21 @@
 	mov	r9,QWORD[48+rsp]
 
 
-	lea	rax,[rsp]
+	lea	r11,[rsp]
 	push	rbp
 	sub	rsp,272
 	and	rsp,-16
-	movaps	XMMWORD[(-168)+rax],xmm6
-	movaps	XMMWORD[(-152)+rax],xmm7
-	movaps	XMMWORD[(-136)+rax],xmm8
-	movaps	XMMWORD[(-120)+rax],xmm9
-	movaps	XMMWORD[(-104)+rax],xmm10
-	movaps	XMMWORD[(-88)+rax],xmm11
-	movaps	XMMWORD[(-72)+rax],xmm12
-	movaps	XMMWORD[(-56)+rax],xmm13
-	movaps	XMMWORD[(-40)+rax],xmm14
-	movaps	XMMWORD[(-24)+rax],xmm15
+	movaps	XMMWORD[(-168)+r11],xmm6
+	movaps	XMMWORD[(-152)+r11],xmm7
+	movaps	XMMWORD[(-136)+r11],xmm8
+	movaps	XMMWORD[(-120)+r11],xmm9
+	movaps	XMMWORD[(-104)+r11],xmm10
+	movaps	XMMWORD[(-88)+r11],xmm11
+	movaps	XMMWORD[(-72)+r11],xmm12
+	movaps	XMMWORD[(-56)+r11],xmm13
+	movaps	XMMWORD[(-40)+r11],xmm14
+	movaps	XMMWORD[(-24)+r11],xmm15
 $L$xts_dec_body:
-	lea	rbp,[((-8))+rax]
 	movups	xmm2,XMMWORD[r9]
 	mov	eax,DWORD[240+r8]
 	mov	r10d,DWORD[240+rcx]
@@ -2245,7 +2242,7 @@
 	sub	rdx,rax
 
 	movups	xmm0,XMMWORD[rcx]
-	mov	r11,rcx
+	mov	rbp,rcx
 	mov	eax,r10d
 	shl	r10d,4
 	mov	r9,rdx
@@ -2301,9 +2298,9 @@
 	jc	NEAR $L$xts_dec_short
 
 	mov	eax,16+96
-	lea	rcx,[32+r10*1+r11]
+	lea	rcx,[32+r10*1+rbp]
 	sub	rax,r10
-	movups	xmm1,XMMWORD[16+r11]
+	movups	xmm1,XMMWORD[16+rbp]
 	mov	r10,rax
 	lea	r8,[$L$xts_magic]
 	jmp	NEAR $L$xts_dec_grandloop
@@ -2328,7 +2325,7 @@
 	movdqa	xmm9,XMMWORD[96+rsp]
 	pxor	xmm6,xmm14
 DB	102,15,56,222,233
-	movups	xmm0,XMMWORD[32+r11]
+	movups	xmm0,XMMWORD[32+rbp]
 	lea	rdi,[96+rdi]
 	pxor	xmm7,xmm8
 
@@ -2337,7 +2334,7 @@
 	pxor	xmm11,xmm9
 	movdqa	XMMWORD[rsp],xmm10
 DB	102,15,56,222,249
-	movups	xmm1,XMMWORD[48+r11]
+	movups	xmm1,XMMWORD[48+rbp]
 	pxor	xmm12,xmm9
 
 DB	102,15,56,222,208
@@ -2352,7 +2349,7 @@
 	movdqa	XMMWORD[64+rsp],xmm14
 DB	102,15,56,222,240
 DB	102,15,56,222,248
-	movups	xmm0,XMMWORD[64+r11]
+	movups	xmm0,XMMWORD[64+rbp]
 	movdqa	XMMWORD[80+rsp],xmm8
 	pshufd	xmm9,xmm15,0x5f
 	jmp	NEAR $L$xts_dec_loop6
@@ -2384,7 +2381,7 @@
 	psrad	xmm14,31
 DB	102,15,56,222,217
 	pand	xmm14,xmm8
-	movups	xmm10,XMMWORD[r11]
+	movups	xmm10,XMMWORD[rbp]
 DB	102,15,56,222,225
 DB	102,15,56,222,233
 DB	102,15,56,222,241
@@ -2452,10 +2449,10 @@
 DB	102,15,56,222,225
 DB	102,15,56,222,233
 	pxor	xmm15,xmm0
-	movups	xmm0,XMMWORD[r11]
+	movups	xmm0,XMMWORD[rbp]
 DB	102,15,56,222,241
 DB	102,15,56,222,249
-	movups	xmm1,XMMWORD[16+r11]
+	movups	xmm1,XMMWORD[16+rbp]
 
 	pxor	xmm14,xmm15
 DB	102,15,56,223,84,36,0
@@ -2482,7 +2479,7 @@
 
 	mov	eax,16+96
 	sub	eax,r10d
-	mov	rcx,r11
+	mov	rcx,rbp
 	shr	eax,4
 
 $L$xts_dec_short:
@@ -2639,7 +2636,7 @@
 	jz	NEAR $L$xts_dec_ret
 $L$xts_dec_done2:
 	mov	rdx,r9
-	mov	rcx,r11
+	mov	rcx,rbp
 	mov	eax,r10d
 
 	movups	xmm2,XMMWORD[rdi]
@@ -2669,7 +2666,7 @@
 	jnz	NEAR $L$xts_dec_steal
 
 	sub	rsi,r9
-	mov	rcx,r11
+	mov	rcx,rbp
 	mov	eax,r10d
 
 	movups	xmm2,XMMWORD[rsi]
@@ -2695,26 +2692,26 @@
 	pxor	xmm3,xmm3
 	pxor	xmm4,xmm4
 	pxor	xmm5,xmm5
-	movaps	xmm6,XMMWORD[((-160))+rbp]
-	movaps	XMMWORD[(-160)+rbp],xmm0
-	movaps	xmm7,XMMWORD[((-144))+rbp]
-	movaps	XMMWORD[(-144)+rbp],xmm0
-	movaps	xmm8,XMMWORD[((-128))+rbp]
-	movaps	XMMWORD[(-128)+rbp],xmm0
-	movaps	xmm9,XMMWORD[((-112))+rbp]
-	movaps	XMMWORD[(-112)+rbp],xmm0
-	movaps	xmm10,XMMWORD[((-96))+rbp]
-	movaps	XMMWORD[(-96)+rbp],xmm0
-	movaps	xmm11,XMMWORD[((-80))+rbp]
-	movaps	XMMWORD[(-80)+rbp],xmm0
-	movaps	xmm12,XMMWORD[((-64))+rbp]
-	movaps	XMMWORD[(-64)+rbp],xmm0
-	movaps	xmm13,XMMWORD[((-48))+rbp]
-	movaps	XMMWORD[(-48)+rbp],xmm0
-	movaps	xmm14,XMMWORD[((-32))+rbp]
-	movaps	XMMWORD[(-32)+rbp],xmm0
-	movaps	xmm15,XMMWORD[((-16))+rbp]
-	movaps	XMMWORD[(-16)+rbp],xmm0
+	movaps	xmm6,XMMWORD[((-168))+r11]
+	movaps	XMMWORD[(-168)+r11],xmm0
+	movaps	xmm7,XMMWORD[((-152))+r11]
+	movaps	XMMWORD[(-152)+r11],xmm0
+	movaps	xmm8,XMMWORD[((-136))+r11]
+	movaps	XMMWORD[(-136)+r11],xmm0
+	movaps	xmm9,XMMWORD[((-120))+r11]
+	movaps	XMMWORD[(-120)+r11],xmm0
+	movaps	xmm10,XMMWORD[((-104))+r11]
+	movaps	XMMWORD[(-104)+r11],xmm0
+	movaps	xmm11,XMMWORD[((-88))+r11]
+	movaps	XMMWORD[(-88)+r11],xmm0
+	movaps	xmm12,XMMWORD[((-72))+r11]
+	movaps	XMMWORD[(-72)+r11],xmm0
+	movaps	xmm13,XMMWORD[((-56))+r11]
+	movaps	XMMWORD[(-56)+r11],xmm0
+	movaps	xmm14,XMMWORD[((-40))+r11]
+	movaps	XMMWORD[(-40)+r11],xmm0
+	movaps	xmm15,XMMWORD[((-24))+r11]
+	movaps	XMMWORD[(-24)+r11],xmm0
 	movaps	XMMWORD[rsp],xmm0
 	movaps	XMMWORD[16+rsp],xmm0
 	movaps	XMMWORD[32+rsp],xmm0
@@ -2722,13 +2719,901 @@
 	movaps	XMMWORD[64+rsp],xmm0
 	movaps	XMMWORD[80+rsp],xmm0
 	movaps	XMMWORD[96+rsp],xmm0
-	lea	rsp,[rbp]
-	pop	rbp
+	mov	rbp,QWORD[((-8))+r11]
+	lea	rsp,[r11]
 $L$xts_dec_epilogue:
 	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
 	mov	rsi,QWORD[16+rsp]
 	DB	0F3h,0C3h		;repret
 $L$SEH_end_aesni_xts_decrypt:
+global	aesni_ocb_encrypt
+
+ALIGN	32
+aesni_ocb_encrypt:
+	mov	QWORD[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_aesni_ocb_encrypt:
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+	mov	r8,QWORD[40+rsp]
+	mov	r9,QWORD[48+rsp]
+
+
+	lea	rax,[rsp]
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	lea	rsp,[((-160))+rsp]
+	movaps	XMMWORD[rsp],xmm6
+	movaps	XMMWORD[16+rsp],xmm7
+	movaps	XMMWORD[32+rsp],xmm8
+	movaps	XMMWORD[48+rsp],xmm9
+	movaps	XMMWORD[64+rsp],xmm10
+	movaps	XMMWORD[80+rsp],xmm11
+	movaps	XMMWORD[96+rsp],xmm12
+	movaps	XMMWORD[112+rsp],xmm13
+	movaps	XMMWORD[128+rsp],xmm14
+	movaps	XMMWORD[144+rsp],xmm15
+$L$ocb_enc_body:
+	mov	rbx,QWORD[56+rax]
+	mov	rbp,QWORD[((56+8))+rax]
+
+	mov	r10d,DWORD[240+rcx]
+	mov	r11,rcx
+	shl	r10d,4
+	movups	xmm9,XMMWORD[rcx]
+	movups	xmm1,XMMWORD[16+r10*1+rcx]
+
+	movdqu	xmm15,XMMWORD[r9]
+	pxor	xmm9,xmm1
+	pxor	xmm15,xmm1
+
+	mov	eax,16+32
+	lea	rcx,[32+r10*1+r11]
+	movups	xmm1,XMMWORD[16+r11]
+	sub	rax,r10
+	mov	r10,rax
+
+	movdqu	xmm10,XMMWORD[rbx]
+	movdqu	xmm8,XMMWORD[rbp]
+
+	test	r8,1
+	jnz	NEAR $L$ocb_enc_odd
+
+	bsf	r12,r8
+	add	r8,1
+	shl	r12,4
+	movdqu	xmm7,XMMWORD[r12*1+rbx]
+	movdqu	xmm2,XMMWORD[rdi]
+	lea	rdi,[16+rdi]
+
+	call	__ocb_encrypt1
+
+	movdqa	xmm15,xmm7
+	movups	XMMWORD[rsi],xmm2
+	lea	rsi,[16+rsi]
+	sub	rdx,1
+	jz	NEAR $L$ocb_enc_done
+
+$L$ocb_enc_odd:
+	lea	r12,[1+r8]
+	lea	r13,[3+r8]
+	lea	r14,[5+r8]
+	lea	r8,[6+r8]
+	bsf	r12,r12
+	bsf	r13,r13
+	bsf	r14,r14
+	shl	r12,4
+	shl	r13,4
+	shl	r14,4
+
+	sub	rdx,6
+	jc	NEAR $L$ocb_enc_short
+	jmp	NEAR $L$ocb_enc_grandloop
+
+ALIGN	32
+$L$ocb_enc_grandloop:
+	movdqu	xmm2,XMMWORD[rdi]
+	movdqu	xmm3,XMMWORD[16+rdi]
+	movdqu	xmm4,XMMWORD[32+rdi]
+	movdqu	xmm5,XMMWORD[48+rdi]
+	movdqu	xmm6,XMMWORD[64+rdi]
+	movdqu	xmm7,XMMWORD[80+rdi]
+	lea	rdi,[96+rdi]
+
+	call	__ocb_encrypt6
+
+	movups	XMMWORD[rsi],xmm2
+	movups	XMMWORD[16+rsi],xmm3
+	movups	XMMWORD[32+rsi],xmm4
+	movups	XMMWORD[48+rsi],xmm5
+	movups	XMMWORD[64+rsi],xmm6
+	movups	XMMWORD[80+rsi],xmm7
+	lea	rsi,[96+rsi]
+	sub	rdx,6
+	jnc	NEAR $L$ocb_enc_grandloop
+
+$L$ocb_enc_short:
+	add	rdx,6
+	jz	NEAR $L$ocb_enc_done
+
+	movdqu	xmm2,XMMWORD[rdi]
+	cmp	rdx,2
+	jb	NEAR $L$ocb_enc_one
+	movdqu	xmm3,XMMWORD[16+rdi]
+	je	NEAR $L$ocb_enc_two
+
+	movdqu	xmm4,XMMWORD[32+rdi]
+	cmp	rdx,4
+	jb	NEAR $L$ocb_enc_three
+	movdqu	xmm5,XMMWORD[48+rdi]
+	je	NEAR $L$ocb_enc_four
+
+	movdqu	xmm6,XMMWORD[64+rdi]
+	pxor	xmm7,xmm7
+
+	call	__ocb_encrypt6
+
+	movdqa	xmm15,xmm14
+	movups	XMMWORD[rsi],xmm2
+	movups	XMMWORD[16+rsi],xmm3
+	movups	XMMWORD[32+rsi],xmm4
+	movups	XMMWORD[48+rsi],xmm5
+	movups	XMMWORD[64+rsi],xmm6
+
+	jmp	NEAR $L$ocb_enc_done
+
+ALIGN	16
+$L$ocb_enc_one:
+	movdqa	xmm7,xmm10
+
+	call	__ocb_encrypt1
+
+	movdqa	xmm15,xmm7
+	movups	XMMWORD[rsi],xmm2
+	jmp	NEAR $L$ocb_enc_done
+
+ALIGN	16
+$L$ocb_enc_two:
+	pxor	xmm4,xmm4
+	pxor	xmm5,xmm5
+
+	call	__ocb_encrypt4
+
+	movdqa	xmm15,xmm11
+	movups	XMMWORD[rsi],xmm2
+	movups	XMMWORD[16+rsi],xmm3
+
+	jmp	NEAR $L$ocb_enc_done
+
+ALIGN	16
+$L$ocb_enc_three:
+	pxor	xmm5,xmm5
+
+	call	__ocb_encrypt4
+
+	movdqa	xmm15,xmm12
+	movups	XMMWORD[rsi],xmm2
+	movups	XMMWORD[16+rsi],xmm3
+	movups	XMMWORD[32+rsi],xmm4
+
+	jmp	NEAR $L$ocb_enc_done
+
+ALIGN	16
+$L$ocb_enc_four:
+	call	__ocb_encrypt4
+
+	movdqa	xmm15,xmm13
+	movups	XMMWORD[rsi],xmm2
+	movups	XMMWORD[16+rsi],xmm3
+	movups	XMMWORD[32+rsi],xmm4
+	movups	XMMWORD[48+rsi],xmm5
+
+$L$ocb_enc_done:
+	pxor	xmm15,xmm0
+	movdqu	XMMWORD[rbp],xmm8
+	movdqu	XMMWORD[r9],xmm15
+
+	xorps	xmm0,xmm0
+	pxor	xmm1,xmm1
+	pxor	xmm2,xmm2
+	pxor	xmm3,xmm3
+	pxor	xmm4,xmm4
+	pxor	xmm5,xmm5
+	movaps	xmm6,XMMWORD[rsp]
+	movaps	XMMWORD[rsp],xmm0
+	movaps	xmm7,XMMWORD[16+rsp]
+	movaps	XMMWORD[16+rsp],xmm0
+	movaps	xmm8,XMMWORD[32+rsp]
+	movaps	XMMWORD[32+rsp],xmm0
+	movaps	xmm9,XMMWORD[48+rsp]
+	movaps	XMMWORD[48+rsp],xmm0
+	movaps	xmm10,XMMWORD[64+rsp]
+	movaps	XMMWORD[64+rsp],xmm0
+	movaps	xmm11,XMMWORD[80+rsp]
+	movaps	XMMWORD[80+rsp],xmm0
+	movaps	xmm12,XMMWORD[96+rsp]
+	movaps	XMMWORD[96+rsp],xmm0
+	movaps	xmm13,XMMWORD[112+rsp]
+	movaps	XMMWORD[112+rsp],xmm0
+	movaps	xmm14,XMMWORD[128+rsp]
+	movaps	XMMWORD[128+rsp],xmm0
+	movaps	xmm15,XMMWORD[144+rsp]
+	movaps	XMMWORD[144+rsp],xmm0
+	lea	rax,[((160+40))+rsp]
+$L$ocb_enc_pop:
+	mov	r14,QWORD[((-40))+rax]
+	mov	r13,QWORD[((-32))+rax]
+	mov	r12,QWORD[((-24))+rax]
+	mov	rbp,QWORD[((-16))+rax]
+	mov	rbx,QWORD[((-8))+rax]
+	lea	rsp,[rax]
+$L$ocb_enc_epilogue:
+	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_aesni_ocb_encrypt:
+
+
+ALIGN	32
+__ocb_encrypt6:
+	pxor	xmm15,xmm9
+	movdqu	xmm11,XMMWORD[r12*1+rbx]
+	movdqa	xmm12,xmm10
+	movdqu	xmm13,XMMWORD[r13*1+rbx]
+	movdqa	xmm14,xmm10
+	pxor	xmm10,xmm15
+	movdqu	xmm15,XMMWORD[r14*1+rbx]
+	pxor	xmm11,xmm10
+	pxor	xmm8,xmm2
+	pxor	xmm2,xmm10
+	pxor	xmm12,xmm11
+	pxor	xmm8,xmm3
+	pxor	xmm3,xmm11
+	pxor	xmm13,xmm12
+	pxor	xmm8,xmm4
+	pxor	xmm4,xmm12
+	pxor	xmm14,xmm13
+	pxor	xmm8,xmm5
+	pxor	xmm5,xmm13
+	pxor	xmm15,xmm14
+	pxor	xmm8,xmm6
+	pxor	xmm6,xmm14
+	pxor	xmm8,xmm7
+	pxor	xmm7,xmm15
+	movups	xmm0,XMMWORD[32+r11]
+
+	lea	r12,[1+r8]
+	lea	r13,[3+r8]
+	lea	r14,[5+r8]
+	add	r8,6
+	pxor	xmm10,xmm9
+	bsf	r12,r12
+	bsf	r13,r13
+	bsf	r14,r14
+
+DB	102,15,56,220,209
+DB	102,15,56,220,217
+DB	102,15,56,220,225
+DB	102,15,56,220,233
+	pxor	xmm11,xmm9
+	pxor	xmm12,xmm9
+DB	102,15,56,220,241
+	pxor	xmm13,xmm9
+	pxor	xmm14,xmm9
+DB	102,15,56,220,249
+	movups	xmm1,XMMWORD[48+r11]
+	pxor	xmm15,xmm9
+
+DB	102,15,56,220,208
+DB	102,15,56,220,216
+DB	102,15,56,220,224
+DB	102,15,56,220,232
+DB	102,15,56,220,240
+DB	102,15,56,220,248
+	movups	xmm0,XMMWORD[64+r11]
+	shl	r12,4
+	shl	r13,4
+	jmp	NEAR $L$ocb_enc_loop6
+
+ALIGN	32
+$L$ocb_enc_loop6:
+DB	102,15,56,220,209
+DB	102,15,56,220,217
+DB	102,15,56,220,225
+DB	102,15,56,220,233
+DB	102,15,56,220,241
+DB	102,15,56,220,249
+	movups	xmm1,XMMWORD[rax*1+rcx]
+	add	rax,32
+
+DB	102,15,56,220,208
+DB	102,15,56,220,216
+DB	102,15,56,220,224
+DB	102,15,56,220,232
+DB	102,15,56,220,240
+DB	102,15,56,220,248
+	movups	xmm0,XMMWORD[((-16))+rax*1+rcx]
+	jnz	NEAR $L$ocb_enc_loop6
+
+DB	102,15,56,220,209
+DB	102,15,56,220,217
+DB	102,15,56,220,225
+DB	102,15,56,220,233
+DB	102,15,56,220,241
+DB	102,15,56,220,249
+	movups	xmm1,XMMWORD[16+r11]
+	shl	r14,4
+
+DB	102,65,15,56,221,210
+	movdqu	xmm10,XMMWORD[rbx]
+	mov	rax,r10
+DB	102,65,15,56,221,219
+DB	102,65,15,56,221,228
+DB	102,65,15,56,221,237
+DB	102,65,15,56,221,246
+DB	102,65,15,56,221,255
+	DB	0F3h,0C3h		;repret
+
+
+
+ALIGN	32
+__ocb_encrypt4:
+	pxor	xmm15,xmm9
+	movdqu	xmm11,XMMWORD[r12*1+rbx]
+	movdqa	xmm12,xmm10
+	movdqu	xmm13,XMMWORD[r13*1+rbx]
+	pxor	xmm10,xmm15
+	pxor	xmm11,xmm10
+	pxor	xmm8,xmm2
+	pxor	xmm2,xmm10
+	pxor	xmm12,xmm11
+	pxor	xmm8,xmm3
+	pxor	xmm3,xmm11
+	pxor	xmm13,xmm12
+	pxor	xmm8,xmm4
+	pxor	xmm4,xmm12
+	pxor	xmm8,xmm5
+	pxor	xmm5,xmm13
+	movups	xmm0,XMMWORD[32+r11]
+
+	pxor	xmm10,xmm9
+	pxor	xmm11,xmm9
+	pxor	xmm12,xmm9
+	pxor	xmm13,xmm9
+
+DB	102,15,56,220,209
+DB	102,15,56,220,217
+DB	102,15,56,220,225
+DB	102,15,56,220,233
+	movups	xmm1,XMMWORD[48+r11]
+
+DB	102,15,56,220,208
+DB	102,15,56,220,216
+DB	102,15,56,220,224
+DB	102,15,56,220,232
+	movups	xmm0,XMMWORD[64+r11]
+	jmp	NEAR $L$ocb_enc_loop4
+
+ALIGN	32
+$L$ocb_enc_loop4:
+DB	102,15,56,220,209
+DB	102,15,56,220,217
+DB	102,15,56,220,225
+DB	102,15,56,220,233
+	movups	xmm1,XMMWORD[rax*1+rcx]
+	add	rax,32
+
+DB	102,15,56,220,208
+DB	102,15,56,220,216
+DB	102,15,56,220,224
+DB	102,15,56,220,232
+	movups	xmm0,XMMWORD[((-16))+rax*1+rcx]
+	jnz	NEAR $L$ocb_enc_loop4
+
+DB	102,15,56,220,209
+DB	102,15,56,220,217
+DB	102,15,56,220,225
+DB	102,15,56,220,233
+	movups	xmm1,XMMWORD[16+r11]
+	mov	rax,r10
+
+DB	102,65,15,56,221,210
+DB	102,65,15,56,221,219
+DB	102,65,15,56,221,228
+DB	102,65,15,56,221,237
+	DB	0F3h,0C3h		;repret
+
+
+
+ALIGN	32
+__ocb_encrypt1:
+	pxor	xmm7,xmm15
+	pxor	xmm7,xmm9
+	pxor	xmm8,xmm2
+	pxor	xmm2,xmm7
+	movups	xmm0,XMMWORD[32+r11]
+
+DB	102,15,56,220,209
+	movups	xmm1,XMMWORD[48+r11]
+	pxor	xmm7,xmm9
+
+DB	102,15,56,220,208
+	movups	xmm0,XMMWORD[64+r11]
+	jmp	NEAR $L$ocb_enc_loop1
+
+ALIGN	32
+$L$ocb_enc_loop1:
+DB	102,15,56,220,209
+	movups	xmm1,XMMWORD[rax*1+rcx]
+	add	rax,32
+
+DB	102,15,56,220,208
+	movups	xmm0,XMMWORD[((-16))+rax*1+rcx]
+	jnz	NEAR $L$ocb_enc_loop1
+
+DB	102,15,56,220,209
+	movups	xmm1,XMMWORD[16+r11]
+	mov	rax,r10
+
+DB	102,15,56,221,215
+	DB	0F3h,0C3h		;repret
+
+
+global	aesni_ocb_decrypt
+
+ALIGN	32
+aesni_ocb_decrypt:
+	mov	QWORD[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_aesni_ocb_decrypt:
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+	mov	r8,QWORD[40+rsp]
+	mov	r9,QWORD[48+rsp]
+
+
+	lea	rax,[rsp]
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	lea	rsp,[((-160))+rsp]
+	movaps	XMMWORD[rsp],xmm6
+	movaps	XMMWORD[16+rsp],xmm7
+	movaps	XMMWORD[32+rsp],xmm8
+	movaps	XMMWORD[48+rsp],xmm9
+	movaps	XMMWORD[64+rsp],xmm10
+	movaps	XMMWORD[80+rsp],xmm11
+	movaps	XMMWORD[96+rsp],xmm12
+	movaps	XMMWORD[112+rsp],xmm13
+	movaps	XMMWORD[128+rsp],xmm14
+	movaps	XMMWORD[144+rsp],xmm15
+$L$ocb_dec_body:
+	mov	rbx,QWORD[56+rax]
+	mov	rbp,QWORD[((56+8))+rax]
+
+	mov	r10d,DWORD[240+rcx]
+	mov	r11,rcx
+	shl	r10d,4
+	movups	xmm9,XMMWORD[rcx]
+	movups	xmm1,XMMWORD[16+r10*1+rcx]
+
+	movdqu	xmm15,XMMWORD[r9]
+	pxor	xmm9,xmm1
+	pxor	xmm15,xmm1
+
+	mov	eax,16+32
+	lea	rcx,[32+r10*1+r11]
+	movups	xmm1,XMMWORD[16+r11]
+	sub	rax,r10
+	mov	r10,rax
+
+	movdqu	xmm10,XMMWORD[rbx]
+	movdqu	xmm8,XMMWORD[rbp]
+
+	test	r8,1
+	jnz	NEAR $L$ocb_dec_odd
+
+	bsf	r12,r8
+	add	r8,1
+	shl	r12,4
+	movdqu	xmm7,XMMWORD[r12*1+rbx]
+	movdqu	xmm2,XMMWORD[rdi]
+	lea	rdi,[16+rdi]
+
+	call	__ocb_decrypt1
+
+	movdqa	xmm15,xmm7
+	movups	XMMWORD[rsi],xmm2
+	xorps	xmm8,xmm2
+	lea	rsi,[16+rsi]
+	sub	rdx,1
+	jz	NEAR $L$ocb_dec_done
+
+$L$ocb_dec_odd:
+	lea	r12,[1+r8]
+	lea	r13,[3+r8]
+	lea	r14,[5+r8]
+	lea	r8,[6+r8]
+	bsf	r12,r12
+	bsf	r13,r13
+	bsf	r14,r14
+	shl	r12,4
+	shl	r13,4
+	shl	r14,4
+
+	sub	rdx,6
+	jc	NEAR $L$ocb_dec_short
+	jmp	NEAR $L$ocb_dec_grandloop
+
+ALIGN	32
+$L$ocb_dec_grandloop:
+	movdqu	xmm2,XMMWORD[rdi]
+	movdqu	xmm3,XMMWORD[16+rdi]
+	movdqu	xmm4,XMMWORD[32+rdi]
+	movdqu	xmm5,XMMWORD[48+rdi]
+	movdqu	xmm6,XMMWORD[64+rdi]
+	movdqu	xmm7,XMMWORD[80+rdi]
+	lea	rdi,[96+rdi]
+
+	call	__ocb_decrypt6
+
+	movups	XMMWORD[rsi],xmm2
+	pxor	xmm8,xmm2
+	movups	XMMWORD[16+rsi],xmm3
+	pxor	xmm8,xmm3
+	movups	XMMWORD[32+rsi],xmm4
+	pxor	xmm8,xmm4
+	movups	XMMWORD[48+rsi],xmm5
+	pxor	xmm8,xmm5
+	movups	XMMWORD[64+rsi],xmm6
+	pxor	xmm8,xmm6
+	movups	XMMWORD[80+rsi],xmm7
+	pxor	xmm8,xmm7
+	lea	rsi,[96+rsi]
+	sub	rdx,6
+	jnc	NEAR $L$ocb_dec_grandloop
+
+$L$ocb_dec_short:
+	add	rdx,6
+	jz	NEAR $L$ocb_dec_done
+
+	movdqu	xmm2,XMMWORD[rdi]
+	cmp	rdx,2
+	jb	NEAR $L$ocb_dec_one
+	movdqu	xmm3,XMMWORD[16+rdi]
+	je	NEAR $L$ocb_dec_two
+
+	movdqu	xmm4,XMMWORD[32+rdi]
+	cmp	rdx,4
+	jb	NEAR $L$ocb_dec_three
+	movdqu	xmm5,XMMWORD[48+rdi]
+	je	NEAR $L$ocb_dec_four
+
+	movdqu	xmm6,XMMWORD[64+rdi]
+	pxor	xmm7,xmm7
+
+	call	__ocb_decrypt6
+
+	movdqa	xmm15,xmm14
+	movups	XMMWORD[rsi],xmm2
+	pxor	xmm8,xmm2
+	movups	XMMWORD[16+rsi],xmm3
+	pxor	xmm8,xmm3
+	movups	XMMWORD[32+rsi],xmm4
+	pxor	xmm8,xmm4
+	movups	XMMWORD[48+rsi],xmm5
+	pxor	xmm8,xmm5
+	movups	XMMWORD[64+rsi],xmm6
+	pxor	xmm8,xmm6
+
+	jmp	NEAR $L$ocb_dec_done
+
+ALIGN	16
+$L$ocb_dec_one:
+	movdqa	xmm7,xmm10
+
+	call	__ocb_decrypt1
+
+	movdqa	xmm15,xmm7
+	movups	XMMWORD[rsi],xmm2
+	xorps	xmm8,xmm2
+	jmp	NEAR $L$ocb_dec_done
+
+ALIGN	16
+$L$ocb_dec_two:
+	pxor	xmm4,xmm4
+	pxor	xmm5,xmm5
+
+	call	__ocb_decrypt4
+
+	movdqa	xmm15,xmm11
+	movups	XMMWORD[rsi],xmm2
+	xorps	xmm8,xmm2
+	movups	XMMWORD[16+rsi],xmm3
+	xorps	xmm8,xmm3
+
+	jmp	NEAR $L$ocb_dec_done
+
+ALIGN	16
+$L$ocb_dec_three:
+	pxor	xmm5,xmm5
+
+	call	__ocb_decrypt4
+
+	movdqa	xmm15,xmm12
+	movups	XMMWORD[rsi],xmm2
+	xorps	xmm8,xmm2
+	movups	XMMWORD[16+rsi],xmm3
+	xorps	xmm8,xmm3
+	movups	XMMWORD[32+rsi],xmm4
+	xorps	xmm8,xmm4
+
+	jmp	NEAR $L$ocb_dec_done
+
+ALIGN	16
+$L$ocb_dec_four:
+	call	__ocb_decrypt4
+
+	movdqa	xmm15,xmm13
+	movups	XMMWORD[rsi],xmm2
+	pxor	xmm8,xmm2
+	movups	XMMWORD[16+rsi],xmm3
+	pxor	xmm8,xmm3
+	movups	XMMWORD[32+rsi],xmm4
+	pxor	xmm8,xmm4
+	movups	XMMWORD[48+rsi],xmm5
+	pxor	xmm8,xmm5
+
+$L$ocb_dec_done:
+	pxor	xmm15,xmm0
+	movdqu	XMMWORD[rbp],xmm8
+	movdqu	XMMWORD[r9],xmm15
+
+	xorps	xmm0,xmm0
+	pxor	xmm1,xmm1
+	pxor	xmm2,xmm2
+	pxor	xmm3,xmm3
+	pxor	xmm4,xmm4
+	pxor	xmm5,xmm5
+	movaps	xmm6,XMMWORD[rsp]
+	movaps	XMMWORD[rsp],xmm0
+	movaps	xmm7,XMMWORD[16+rsp]
+	movaps	XMMWORD[16+rsp],xmm0
+	movaps	xmm8,XMMWORD[32+rsp]
+	movaps	XMMWORD[32+rsp],xmm0
+	movaps	xmm9,XMMWORD[48+rsp]
+	movaps	XMMWORD[48+rsp],xmm0
+	movaps	xmm10,XMMWORD[64+rsp]
+	movaps	XMMWORD[64+rsp],xmm0
+	movaps	xmm11,XMMWORD[80+rsp]
+	movaps	XMMWORD[80+rsp],xmm0
+	movaps	xmm12,XMMWORD[96+rsp]
+	movaps	XMMWORD[96+rsp],xmm0
+	movaps	xmm13,XMMWORD[112+rsp]
+	movaps	XMMWORD[112+rsp],xmm0
+	movaps	xmm14,XMMWORD[128+rsp]
+	movaps	XMMWORD[128+rsp],xmm0
+	movaps	xmm15,XMMWORD[144+rsp]
+	movaps	XMMWORD[144+rsp],xmm0
+	lea	rax,[((160+40))+rsp]
+$L$ocb_dec_pop:
+	mov	r14,QWORD[((-40))+rax]
+	mov	r13,QWORD[((-32))+rax]
+	mov	r12,QWORD[((-24))+rax]
+	mov	rbp,QWORD[((-16))+rax]
+	mov	rbx,QWORD[((-8))+rax]
+	lea	rsp,[rax]
+$L$ocb_dec_epilogue:
+	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_aesni_ocb_decrypt:
+
+
+ALIGN	32
+__ocb_decrypt6:
+	pxor	xmm15,xmm9
+	movdqu	xmm11,XMMWORD[r12*1+rbx]
+	movdqa	xmm12,xmm10
+	movdqu	xmm13,XMMWORD[r13*1+rbx]
+	movdqa	xmm14,xmm10
+	pxor	xmm10,xmm15
+	movdqu	xmm15,XMMWORD[r14*1+rbx]
+	pxor	xmm11,xmm10
+	pxor	xmm2,xmm10
+	pxor	xmm12,xmm11
+	pxor	xmm3,xmm11
+	pxor	xmm13,xmm12
+	pxor	xmm4,xmm12
+	pxor	xmm14,xmm13
+	pxor	xmm5,xmm13
+	pxor	xmm15,xmm14
+	pxor	xmm6,xmm14
+	pxor	xmm7,xmm15
+	movups	xmm0,XMMWORD[32+r11]
+
+	lea	r12,[1+r8]
+	lea	r13,[3+r8]
+	lea	r14,[5+r8]
+	add	r8,6
+	pxor	xmm10,xmm9
+	bsf	r12,r12
+	bsf	r13,r13
+	bsf	r14,r14
+
+DB	102,15,56,222,209
+DB	102,15,56,222,217
+DB	102,15,56,222,225
+DB	102,15,56,222,233
+	pxor	xmm11,xmm9
+	pxor	xmm12,xmm9
+DB	102,15,56,222,241
+	pxor	xmm13,xmm9
+	pxor	xmm14,xmm9
+DB	102,15,56,222,249
+	movups	xmm1,XMMWORD[48+r11]
+	pxor	xmm15,xmm9
+
+DB	102,15,56,222,208
+DB	102,15,56,222,216
+DB	102,15,56,222,224
+DB	102,15,56,222,232
+DB	102,15,56,222,240
+DB	102,15,56,222,248
+	movups	xmm0,XMMWORD[64+r11]
+	shl	r12,4
+	shl	r13,4
+	jmp	NEAR $L$ocb_dec_loop6
+
+ALIGN	32
+$L$ocb_dec_loop6:
+DB	102,15,56,222,209
+DB	102,15,56,222,217
+DB	102,15,56,222,225
+DB	102,15,56,222,233
+DB	102,15,56,222,241
+DB	102,15,56,222,249
+	movups	xmm1,XMMWORD[rax*1+rcx]
+	add	rax,32
+
+DB	102,15,56,222,208
+DB	102,15,56,222,216
+DB	102,15,56,222,224
+DB	102,15,56,222,232
+DB	102,15,56,222,240
+DB	102,15,56,222,248
+	movups	xmm0,XMMWORD[((-16))+rax*1+rcx]
+	jnz	NEAR $L$ocb_dec_loop6
+
+DB	102,15,56,222,209
+DB	102,15,56,222,217
+DB	102,15,56,222,225
+DB	102,15,56,222,233
+DB	102,15,56,222,241
+DB	102,15,56,222,249
+	movups	xmm1,XMMWORD[16+r11]
+	shl	r14,4
+
+DB	102,65,15,56,223,210
+	movdqu	xmm10,XMMWORD[rbx]
+	mov	rax,r10
+DB	102,65,15,56,223,219
+DB	102,65,15,56,223,228
+DB	102,65,15,56,223,237
+DB	102,65,15,56,223,246
+DB	102,65,15,56,223,255
+	DB	0F3h,0C3h		;repret
+
+
+
+ALIGN	32
+__ocb_decrypt4:
+	pxor	xmm15,xmm9
+	movdqu	xmm11,XMMWORD[r12*1+rbx]
+	movdqa	xmm12,xmm10
+	movdqu	xmm13,XMMWORD[r13*1+rbx]
+	pxor	xmm10,xmm15
+	pxor	xmm11,xmm10
+	pxor	xmm2,xmm10
+	pxor	xmm12,xmm11
+	pxor	xmm3,xmm11
+	pxor	xmm13,xmm12
+	pxor	xmm4,xmm12
+	pxor	xmm5,xmm13
+	movups	xmm0,XMMWORD[32+r11]
+
+	pxor	xmm10,xmm9
+	pxor	xmm11,xmm9
+	pxor	xmm12,xmm9
+	pxor	xmm13,xmm9
+
+DB	102,15,56,222,209
+DB	102,15,56,222,217
+DB	102,15,56,222,225
+DB	102,15,56,222,233
+	movups	xmm1,XMMWORD[48+r11]
+
+DB	102,15,56,222,208
+DB	102,15,56,222,216
+DB	102,15,56,222,224
+DB	102,15,56,222,232
+	movups	xmm0,XMMWORD[64+r11]
+	jmp	NEAR $L$ocb_dec_loop4
+
+ALIGN	32
+$L$ocb_dec_loop4:
+DB	102,15,56,222,209
+DB	102,15,56,222,217
+DB	102,15,56,222,225
+DB	102,15,56,222,233
+	movups	xmm1,XMMWORD[rax*1+rcx]
+	add	rax,32
+
+DB	102,15,56,222,208
+DB	102,15,56,222,216
+DB	102,15,56,222,224
+DB	102,15,56,222,232
+	movups	xmm0,XMMWORD[((-16))+rax*1+rcx]
+	jnz	NEAR $L$ocb_dec_loop4
+
+DB	102,15,56,222,209
+DB	102,15,56,222,217
+DB	102,15,56,222,225
+DB	102,15,56,222,233
+	movups	xmm1,XMMWORD[16+r11]
+	mov	rax,r10
+
+DB	102,65,15,56,223,210
+DB	102,65,15,56,223,219
+DB	102,65,15,56,223,228
+DB	102,65,15,56,223,237
+	DB	0F3h,0C3h		;repret
+
+
+
+ALIGN	32
+__ocb_decrypt1:
+	pxor	xmm7,xmm15
+	pxor	xmm7,xmm9
+	pxor	xmm2,xmm7
+	movups	xmm0,XMMWORD[32+r11]
+
+DB	102,15,56,222,209
+	movups	xmm1,XMMWORD[48+r11]
+	pxor	xmm7,xmm9
+
+DB	102,15,56,222,208
+	movups	xmm0,XMMWORD[64+r11]
+	jmp	NEAR $L$ocb_dec_loop1
+
+ALIGN	32
+$L$ocb_dec_loop1:
+DB	102,15,56,222,209
+	movups	xmm1,XMMWORD[rax*1+rcx]
+	add	rax,32
+
+DB	102,15,56,222,208
+	movups	xmm0,XMMWORD[((-16))+rax*1+rcx]
+	jnz	NEAR $L$ocb_dec_loop1
+
+DB	102,15,56,222,209
+	movups	xmm1,XMMWORD[16+r11]
+	mov	rax,r10
+
+DB	102,15,56,223,215
+	DB	0F3h,0C3h		;repret
+
 global	aesni_cbc_encrypt
 
 ALIGN	16
@@ -2837,7 +3722,7 @@
 	jmp	NEAR $L$cbc_ret
 ALIGN	16
 $L$cbc_decrypt_bulk:
-	lea	rax,[rsp]
+	lea	r11,[rsp]
 	push	rbp
 	sub	rsp,176
 	and	rsp,-16
@@ -2852,7 +3737,7 @@
 	movaps	XMMWORD[144+rsp],xmm14
 	movaps	XMMWORD[160+rsp],xmm15
 $L$cbc_decrypt_body:
-	lea	rbp,[((-8))+rax]
+	mov	rbp,rcx
 	movups	xmm10,XMMWORD[r8]
 	mov	eax,r10d
 	cmp	rdx,0x50
@@ -2892,7 +3777,7 @@
 	pxor	xmm3,xmm0
 	movups	xmm1,XMMWORD[((16-112))+rcx]
 	pxor	xmm4,xmm0
-	xor	r11,r11
+	mov	rbp,-1
 	cmp	rdx,0x70
 	pxor	xmm5,xmm0
 	pxor	xmm6,xmm0
@@ -2908,10 +3793,10 @@
 DB	102,15,56,222,241
 DB	102,15,56,222,249
 DB	102,68,15,56,222,193
-	setnc	r11b
-	shl	r11,7
+	adc	rbp,0
+	and	rbp,128
 DB	102,68,15,56,222,201
-	add	r11,rdi
+	add	rbp,rdi
 	movups	xmm1,XMMWORD[((48-112))+rcx]
 DB	102,15,56,222,208
 DB	102,15,56,222,216
@@ -3049,18 +3934,18 @@
 	movdqu	xmm0,XMMWORD[112+rdi]
 DB	102,65,15,56,223,228
 	lea	rdi,[128+rdi]
-	movdqu	xmm11,XMMWORD[r11]
+	movdqu	xmm11,XMMWORD[rbp]
 DB	102,65,15,56,223,237
 DB	102,65,15,56,223,246
-	movdqu	xmm12,XMMWORD[16+r11]
-	movdqu	xmm13,XMMWORD[32+r11]
+	movdqu	xmm12,XMMWORD[16+rbp]
+	movdqu	xmm13,XMMWORD[32+rbp]
 DB	102,65,15,56,223,255
 DB	102,68,15,56,223,193
-	movdqu	xmm14,XMMWORD[48+r11]
-	movdqu	xmm15,XMMWORD[64+r11]
+	movdqu	xmm14,XMMWORD[48+rbp]
+	movdqu	xmm15,XMMWORD[64+rbp]
 DB	102,69,15,56,223,202
 	movdqa	xmm10,xmm0
-	movdqu	xmm1,XMMWORD[80+r11]
+	movdqu	xmm1,XMMWORD[80+rbp]
 	movups	xmm0,XMMWORD[((-112))+rcx]
 
 	movups	XMMWORD[rsi],xmm2
@@ -3179,7 +4064,7 @@
 	pxor	xmm5,xmm13
 	movdqu	XMMWORD[32+rsi],xmm4
 	pxor	xmm6,xmm14
-	mov	rcx,r11
+	mov	rcx,rbp
 	movdqu	XMMWORD[48+rsi],xmm5
 	pxor	xmm7,xmm15
 	mov	eax,r10d
@@ -3348,8 +4233,8 @@
 	movaps	XMMWORD[144+rsp],xmm0
 	movaps	xmm15,XMMWORD[160+rsp]
 	movaps	XMMWORD[160+rsp],xmm0
-	lea	rsp,[rbp]
-	pop	rbp
+	mov	rbp,QWORD[((-8))+r11]
+	lea	rsp,[r11]
 $L$cbc_ret:
 	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
 	mov	rsi,QWORD[16+rsp]
@@ -3865,13 +4750,75 @@
 	cmp	rbx,r10
 	jae	NEAR $L$common_seh_tail
 
-	mov	rax,QWORD[160+r8]
-	lea	rsi,[((-160))+rax]
+	mov	rax,QWORD[208+r8]
+
+	lea	rsi,[((-168))+rax]
 	lea	rdi,[512+r8]
 	mov	ecx,20
 	DD	0xa548f3fc
 
-	jmp	NEAR $L$common_rbp_tail
+	mov	rbp,QWORD[((-8))+rax]
+	mov	QWORD[160+r8],rbp
+	jmp	NEAR $L$common_seh_tail
+
+
+
+ALIGN	16
+ocb_se_handler:
+	push	rsi
+	push	rdi
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	pushfq
+	sub	rsp,64
+
+	mov	rax,QWORD[120+r8]
+	mov	rbx,QWORD[248+r8]
+
+	mov	rsi,QWORD[8+r9]
+	mov	r11,QWORD[56+r9]
+
+	mov	r10d,DWORD[r11]
+	lea	r10,[r10*1+rsi]
+	cmp	rbx,r10
+	jb	NEAR $L$common_seh_tail
+
+	mov	r10d,DWORD[4+r11]
+	lea	r10,[r10*1+rsi]
+	cmp	rbx,r10
+	jae	NEAR $L$common_seh_tail
+
+	mov	r10d,DWORD[8+r11]
+	lea	r10,[r10*1+rsi]
+	cmp	rbx,r10
+	jae	NEAR $L$ocb_no_xmm
+
+	mov	rax,QWORD[152+r8]
+
+	lea	rsi,[rax]
+	lea	rdi,[512+r8]
+	mov	ecx,20
+	DD	0xa548f3fc
+	lea	rax,[((160+40))+rax]
+
+$L$ocb_no_xmm:
+	mov	rbx,QWORD[((-8))+rax]
+	mov	rbp,QWORD[((-16))+rax]
+	mov	r12,QWORD[((-24))+rax]
+	mov	r13,QWORD[((-32))+rax]
+	mov	r14,QWORD[((-40))+rax]
+
+	mov	QWORD[144+r8],rbx
+	mov	QWORD[160+r8],rbp
+	mov	QWORD[216+r8],r12
+	mov	QWORD[224+r8],r13
+	mov	QWORD[232+r8],r14
+
+	jmp	NEAR $L$common_seh_tail
 
 
 ALIGN	16
@@ -3894,9 +4841,13 @@
 	cmp	rbx,r10
 	jb	NEAR $L$common_seh_tail
 
+	mov	rax,QWORD[120+r8]
+
 	lea	r10,[$L$cbc_decrypt_body]
 	cmp	rbx,r10
-	jb	NEAR $L$restore_cbc_rax
+	jb	NEAR $L$common_seh_tail
+
+	mov	rax,QWORD[152+r8]
 
 	lea	r10,[$L$cbc_ret]
 	cmp	rbx,r10
@@ -3907,15 +4858,10 @@
 	mov	ecx,20
 	DD	0xa548f3fc
 
-$L$common_rbp_tail:
-	mov	rax,QWORD[160+r8]
-	mov	rbp,QWORD[rax]
-	lea	rax,[8+rax]
-	mov	QWORD[160+r8],rbp
-	jmp	NEAR $L$common_seh_tail
+	mov	rax,QWORD[208+r8]
 
-$L$restore_cbc_rax:
-	mov	rax,QWORD[120+r8]
+	mov	rbp,QWORD[((-8))+rax]
+	mov	QWORD[160+r8],rbp
 
 $L$common_seh_tail:
 	mov	rdi,QWORD[8+rax]
@@ -3982,6 +4928,14 @@
 	DD	$L$SEH_begin_aesni_xts_decrypt wrt ..imagebase
 	DD	$L$SEH_end_aesni_xts_decrypt wrt ..imagebase
 	DD	$L$SEH_info_xts_dec wrt ..imagebase
+
+	DD	$L$SEH_begin_aesni_ocb_encrypt wrt ..imagebase
+	DD	$L$SEH_end_aesni_ocb_encrypt wrt ..imagebase
+	DD	$L$SEH_info_ocb_enc wrt ..imagebase
+
+	DD	$L$SEH_begin_aesni_ocb_decrypt wrt ..imagebase
+	DD	$L$SEH_end_aesni_ocb_decrypt wrt ..imagebase
+	DD	$L$SEH_info_ocb_dec wrt ..imagebase
 	DD	$L$SEH_begin_aesni_cbc_encrypt wrt ..imagebase
 	DD	$L$SEH_end_aesni_cbc_encrypt wrt ..imagebase
 	DD	$L$SEH_info_cbc wrt ..imagebase
@@ -4019,6 +4973,18 @@
 DB	9,0,0,0
 	DD	ctr_xts_se_handler wrt ..imagebase
 	DD	$L$xts_dec_body wrt ..imagebase,$L$xts_dec_epilogue wrt ..imagebase
+$L$SEH_info_ocb_enc:
+DB	9,0,0,0
+	DD	ocb_se_handler wrt ..imagebase
+	DD	$L$ocb_enc_body wrt ..imagebase,$L$ocb_enc_epilogue wrt ..imagebase
+	DD	$L$ocb_enc_pop wrt ..imagebase
+	DD	0
+$L$SEH_info_ocb_dec:
+DB	9,0,0,0
+	DD	ocb_se_handler wrt ..imagebase
+	DD	$L$ocb_dec_body wrt ..imagebase,$L$ocb_dec_epilogue wrt ..imagebase
+	DD	$L$ocb_dec_pop wrt ..imagebase
+	DD	0
 $L$SEH_info_cbc:
 DB	9,0,0,0
 	DD	cbc_se_handler wrt ..imagebase
diff --git a/win-x86_64/crypto/aes/bsaes-x86_64.asm b/win-x86_64/crypto/aes/bsaes-x86_64.asm
index 6d75248..9c6d129 100644
--- a/win-x86_64/crypto/aes/bsaes-x86_64.asm
+++ b/win-x86_64/crypto/aes/bsaes-x86_64.asm
@@ -1319,7 +1319,7 @@
 	cmp	rbp,rax
 	ja	NEAR $L$cbc_dec_bzero
 
-	lea	rsp,[rbp]
+	lea	rax,[120+rbp]
 	movaps	xmm6,XMMWORD[64+rbp]
 	movaps	xmm7,XMMWORD[80+rbp]
 	movaps	xmm8,XMMWORD[96+rbp]
@@ -1330,15 +1330,15 @@
 	movaps	xmm13,XMMWORD[176+rbp]
 	movaps	xmm14,XMMWORD[192+rbp]
 	movaps	xmm15,XMMWORD[208+rbp]
-	lea	rsp,[160+rbp]
-	mov	r15,QWORD[72+rsp]
-	mov	r14,QWORD[80+rsp]
-	mov	r13,QWORD[88+rsp]
-	mov	r12,QWORD[96+rsp]
-	mov	rbx,QWORD[104+rsp]
-	mov	rax,QWORD[112+rsp]
-	lea	rsp,[120+rsp]
-	mov	rbp,rax
+	lea	rax,[160+rax]
+$L$cbc_dec_tail:
+	mov	r15,QWORD[((-48))+rax]
+	mov	r14,QWORD[((-40))+rax]
+	mov	r13,QWORD[((-32))+rax]
+	mov	r12,QWORD[((-24))+rax]
+	mov	rbx,QWORD[((-16))+rax]
+	mov	rbp,QWORD[((-8))+rax]
+	lea	rsp,[rax]
 $L$cbc_dec_epilogue:
 	DB	0F3h,0C3h		;repret
 
@@ -1543,7 +1543,7 @@
 	cmp	rbp,rax
 	ja	NEAR $L$ctr_enc_bzero
 
-	lea	rsp,[rbp]
+	lea	rax,[120+rbp]
 	movaps	xmm6,XMMWORD[64+rbp]
 	movaps	xmm7,XMMWORD[80+rbp]
 	movaps	xmm8,XMMWORD[96+rbp]
@@ -1554,15 +1554,15 @@
 	movaps	xmm13,XMMWORD[176+rbp]
 	movaps	xmm14,XMMWORD[192+rbp]
 	movaps	xmm15,XMMWORD[208+rbp]
-	lea	rsp,[160+rbp]
-	mov	r15,QWORD[72+rsp]
-	mov	r14,QWORD[80+rsp]
-	mov	r13,QWORD[88+rsp]
-	mov	r12,QWORD[96+rsp]
-	mov	rbx,QWORD[104+rsp]
-	mov	rax,QWORD[112+rsp]
-	lea	rsp,[120+rsp]
-	mov	rbp,rax
+	lea	rax,[160+rax]
+$L$ctr_enc_tail:
+	mov	r15,QWORD[((-48))+rax]
+	mov	r14,QWORD[((-40))+rax]
+	mov	r13,QWORD[((-32))+rax]
+	mov	r12,QWORD[((-24))+rax]
+	mov	rbx,QWORD[((-16))+rax]
+	mov	rbp,QWORD[((-8))+rax]
+	lea	rsp,[rax]
 $L$ctr_enc_epilogue:
 	DB	0F3h,0C3h		;repret
 
@@ -2019,7 +2019,7 @@
 	cmp	rbp,rax
 	ja	NEAR $L$xts_enc_bzero
 
-	lea	rsp,[rbp]
+	lea	rax,[120+rbp]
 	movaps	xmm6,XMMWORD[64+rbp]
 	movaps	xmm7,XMMWORD[80+rbp]
 	movaps	xmm8,XMMWORD[96+rbp]
@@ -2030,15 +2030,15 @@
 	movaps	xmm13,XMMWORD[176+rbp]
 	movaps	xmm14,XMMWORD[192+rbp]
 	movaps	xmm15,XMMWORD[208+rbp]
-	lea	rsp,[160+rbp]
-	mov	r15,QWORD[72+rsp]
-	mov	r14,QWORD[80+rsp]
-	mov	r13,QWORD[88+rsp]
-	mov	r12,QWORD[96+rsp]
-	mov	rbx,QWORD[104+rsp]
-	mov	rax,QWORD[112+rsp]
-	lea	rsp,[120+rsp]
-	mov	rbp,rax
+	lea	rax,[160+rax]
+$L$xts_enc_tail:
+	mov	r15,QWORD[((-48))+rax]
+	mov	r14,QWORD[((-40))+rax]
+	mov	r13,QWORD[((-32))+rax]
+	mov	r12,QWORD[((-24))+rax]
+	mov	rbx,QWORD[((-16))+rax]
+	mov	rbp,QWORD[((-8))+rax]
+	lea	rsp,[rax]
 $L$xts_enc_epilogue:
 	DB	0F3h,0C3h		;repret
 
@@ -2522,7 +2522,7 @@
 	cmp	rbp,rax
 	ja	NEAR $L$xts_dec_bzero
 
-	lea	rsp,[rbp]
+	lea	rax,[120+rbp]
 	movaps	xmm6,XMMWORD[64+rbp]
 	movaps	xmm7,XMMWORD[80+rbp]
 	movaps	xmm8,XMMWORD[96+rbp]
@@ -2533,15 +2533,15 @@
 	movaps	xmm13,XMMWORD[176+rbp]
 	movaps	xmm14,XMMWORD[192+rbp]
 	movaps	xmm15,XMMWORD[208+rbp]
-	lea	rsp,[160+rbp]
-	mov	r15,QWORD[72+rsp]
-	mov	r14,QWORD[80+rsp]
-	mov	r13,QWORD[88+rsp]
-	mov	r12,QWORD[96+rsp]
-	mov	rbx,QWORD[104+rsp]
-	mov	rax,QWORD[112+rsp]
-	lea	rsp,[120+rsp]
-	mov	rbp,rax
+	lea	rax,[160+rax]
+$L$xts_dec_tail:
+	mov	r15,QWORD[((-48))+rax]
+	mov	r14,QWORD[((-40))+rax]
+	mov	r13,QWORD[((-32))+rax]
+	mov	r12,QWORD[((-24))+rax]
+	mov	rbx,QWORD[((-16))+rax]
+	mov	rbp,QWORD[((-8))+rax]
+	lea	rsp,[rax]
 $L$xts_dec_epilogue:
 	DB	0F3h,0C3h		;repret
 
@@ -2628,30 +2628,33 @@
 	mov	r10d,DWORD[r11]
 	lea	r10,[r10*1+rsi]
 	cmp	rbx,r10
-	jb	NEAR $L$in_prologue
-
-	mov	rax,QWORD[152+r8]
+	jbe	NEAR $L$in_prologue
 
 	mov	r10d,DWORD[4+r11]
 	lea	r10,[r10*1+rsi]
 	cmp	rbx,r10
 	jae	NEAR $L$in_prologue
 
+	mov	r10d,DWORD[8+r11]
+	lea	r10,[r10*1+rsi]
+	cmp	rbx,r10
+	jae	NEAR $L$in_tail
+
 	mov	rax,QWORD[160+r8]
 
 	lea	rsi,[64+rax]
 	lea	rdi,[512+r8]
 	mov	ecx,20
 	DD	0xa548f3fc
-	lea	rax,[160+rax]
+	lea	rax,[((160+120))+rax]
 
-	mov	rbp,QWORD[112+rax]
-	mov	rbx,QWORD[104+rax]
-	mov	r12,QWORD[96+rax]
-	mov	r13,QWORD[88+rax]
-	mov	r14,QWORD[80+rax]
-	mov	r15,QWORD[72+rax]
-	lea	rax,[120+rax]
+$L$in_tail:
+	mov	rbp,QWORD[((-48))+rax]
+	mov	rbx,QWORD[((-40))+rax]
+	mov	r12,QWORD[((-32))+rax]
+	mov	r13,QWORD[((-24))+rax]
+	mov	r14,QWORD[((-16))+rax]
+	mov	r15,QWORD[((-8))+rax]
 	mov	QWORD[144+r8],rbx
 	mov	QWORD[160+r8],rbp
 	mov	QWORD[216+r8],r12
@@ -2719,15 +2722,23 @@
 DB	9,0,0,0
 	DD	se_handler wrt ..imagebase
 	DD	$L$cbc_dec_body wrt ..imagebase,$L$cbc_dec_epilogue wrt ..imagebase
+	DD	$L$cbc_dec_tail wrt ..imagebase
+	DD	0
 $L$ctr_enc_info:
 DB	9,0,0,0
 	DD	se_handler wrt ..imagebase
 	DD	$L$ctr_enc_body wrt ..imagebase,$L$ctr_enc_epilogue wrt ..imagebase
+	DD	$L$ctr_enc_tail wrt ..imagebase
+	DD	0
 $L$xts_enc_info:
 DB	9,0,0,0
 	DD	se_handler wrt ..imagebase
 	DD	$L$xts_enc_body wrt ..imagebase,$L$xts_enc_epilogue wrt ..imagebase
+	DD	$L$xts_enc_tail wrt ..imagebase
+	DD	0
 $L$xts_dec_info:
 DB	9,0,0,0
 	DD	se_handler wrt ..imagebase
 	DD	$L$xts_dec_body wrt ..imagebase,$L$xts_dec_epilogue wrt ..imagebase
+	DD	$L$xts_dec_tail wrt ..imagebase
+	DD	0
diff --git a/win-x86_64/crypto/bn/rsaz-avx2.asm b/win-x86_64/crypto/bn/rsaz-avx2.asm
index 45d0fd4..a64bb56 100644
--- a/win-x86_64/crypto/bn/rsaz-avx2.asm
+++ b/win-x86_64/crypto/bn/rsaz-avx2.asm
@@ -5,26 +5,1970 @@
 section	.text code align=64
 
 
-global	rsaz_avx2_eligible
+global	rsaz_1024_sqr_avx2
 
-rsaz_avx2_eligible:
-	xor	eax,eax
+ALIGN	64
+rsaz_1024_sqr_avx2:
+	mov	QWORD[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_rsaz_1024_sqr_avx2:
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+	mov	r8,QWORD[40+rsp]
+
+
+
+	lea	rax,[rsp]
+
+	push	rbx
+
+	push	rbp
+
+	push	r12
+
+	push	r13
+
+	push	r14
+
+	push	r15
+
+	vzeroupper
+	lea	rsp,[((-168))+rsp]
+	vmovaps	XMMWORD[(-216)+rax],xmm6
+	vmovaps	XMMWORD[(-200)+rax],xmm7
+	vmovaps	XMMWORD[(-184)+rax],xmm8
+	vmovaps	XMMWORD[(-168)+rax],xmm9
+	vmovaps	XMMWORD[(-152)+rax],xmm10
+	vmovaps	XMMWORD[(-136)+rax],xmm11
+	vmovaps	XMMWORD[(-120)+rax],xmm12
+	vmovaps	XMMWORD[(-104)+rax],xmm13
+	vmovaps	XMMWORD[(-88)+rax],xmm14
+	vmovaps	XMMWORD[(-72)+rax],xmm15
+$L$sqr_1024_body:
+	mov	rbp,rax
+
+	mov	r13,rdx
+	sub	rsp,832
+	mov	r15,r13
+	sub	rdi,-128
+	sub	rsi,-128
+	sub	r13,-128
+
+	and	r15,4095
+	add	r15,32*10
+	shr	r15,12
+	vpxor	ymm9,ymm9,ymm9
+	jz	NEAR $L$sqr_1024_no_n_copy
+
+
+
+
+
+	sub	rsp,32*10
+	vmovdqu	ymm0,YMMWORD[((0-128))+r13]
+	and	rsp,-2048
+	vmovdqu	ymm1,YMMWORD[((32-128))+r13]
+	vmovdqu	ymm2,YMMWORD[((64-128))+r13]
+	vmovdqu	ymm3,YMMWORD[((96-128))+r13]
+	vmovdqu	ymm4,YMMWORD[((128-128))+r13]
+	vmovdqu	ymm5,YMMWORD[((160-128))+r13]
+	vmovdqu	ymm6,YMMWORD[((192-128))+r13]
+	vmovdqu	ymm7,YMMWORD[((224-128))+r13]
+	vmovdqu	ymm8,YMMWORD[((256-128))+r13]
+	lea	r13,[((832+128))+rsp]
+	vmovdqu	YMMWORD[(0-128)+r13],ymm0
+	vmovdqu	YMMWORD[(32-128)+r13],ymm1
+	vmovdqu	YMMWORD[(64-128)+r13],ymm2
+	vmovdqu	YMMWORD[(96-128)+r13],ymm3
+	vmovdqu	YMMWORD[(128-128)+r13],ymm4
+	vmovdqu	YMMWORD[(160-128)+r13],ymm5
+	vmovdqu	YMMWORD[(192-128)+r13],ymm6
+	vmovdqu	YMMWORD[(224-128)+r13],ymm7
+	vmovdqu	YMMWORD[(256-128)+r13],ymm8
+	vmovdqu	YMMWORD[(288-128)+r13],ymm9
+
+$L$sqr_1024_no_n_copy:
+	and	rsp,-1024
+
+	vmovdqu	ymm1,YMMWORD[((32-128))+rsi]
+	vmovdqu	ymm2,YMMWORD[((64-128))+rsi]
+	vmovdqu	ymm3,YMMWORD[((96-128))+rsi]
+	vmovdqu	ymm4,YMMWORD[((128-128))+rsi]
+	vmovdqu	ymm5,YMMWORD[((160-128))+rsi]
+	vmovdqu	ymm6,YMMWORD[((192-128))+rsi]
+	vmovdqu	ymm7,YMMWORD[((224-128))+rsi]
+	vmovdqu	ymm8,YMMWORD[((256-128))+rsi]
+
+	lea	rbx,[192+rsp]
+	vpbroadcastq	ymm15,QWORD[$L$and_mask]
+	jmp	NEAR $L$OOP_GRANDE_SQR_1024
+
+ALIGN	32
+$L$OOP_GRANDE_SQR_1024:
+	lea	r9,[((576+128))+rsp]
+	lea	r12,[448+rsp]
+
+
+
+
+	vpaddq	ymm1,ymm1,ymm1
+	vpbroadcastq	ymm10,QWORD[((0-128))+rsi]
+	vpaddq	ymm2,ymm2,ymm2
+	vmovdqa	YMMWORD[(0-128)+r9],ymm1
+	vpaddq	ymm3,ymm3,ymm3
+	vmovdqa	YMMWORD[(32-128)+r9],ymm2
+	vpaddq	ymm4,ymm4,ymm4
+	vmovdqa	YMMWORD[(64-128)+r9],ymm3
+	vpaddq	ymm5,ymm5,ymm5
+	vmovdqa	YMMWORD[(96-128)+r9],ymm4
+	vpaddq	ymm6,ymm6,ymm6
+	vmovdqa	YMMWORD[(128-128)+r9],ymm5
+	vpaddq	ymm7,ymm7,ymm7
+	vmovdqa	YMMWORD[(160-128)+r9],ymm6
+	vpaddq	ymm8,ymm8,ymm8
+	vmovdqa	YMMWORD[(192-128)+r9],ymm7
+	vpxor	ymm9,ymm9,ymm9
+	vmovdqa	YMMWORD[(224-128)+r9],ymm8
+
+	vpmuludq	ymm0,ymm10,YMMWORD[((0-128))+rsi]
+	vpbroadcastq	ymm11,QWORD[((32-128))+rsi]
+	vmovdqu	YMMWORD[(288-192)+rbx],ymm9
+	vpmuludq	ymm1,ymm1,ymm10
+	vmovdqu	YMMWORD[(320-448)+r12],ymm9
+	vpmuludq	ymm2,ymm2,ymm10
+	vmovdqu	YMMWORD[(352-448)+r12],ymm9
+	vpmuludq	ymm3,ymm3,ymm10
+	vmovdqu	YMMWORD[(384-448)+r12],ymm9
+	vpmuludq	ymm4,ymm4,ymm10
+	vmovdqu	YMMWORD[(416-448)+r12],ymm9
+	vpmuludq	ymm5,ymm5,ymm10
+	vmovdqu	YMMWORD[(448-448)+r12],ymm9
+	vpmuludq	ymm6,ymm6,ymm10
+	vmovdqu	YMMWORD[(480-448)+r12],ymm9
+	vpmuludq	ymm7,ymm7,ymm10
+	vmovdqu	YMMWORD[(512-448)+r12],ymm9
+	vpmuludq	ymm8,ymm8,ymm10
+	vpbroadcastq	ymm10,QWORD[((64-128))+rsi]
+	vmovdqu	YMMWORD[(544-448)+r12],ymm9
+
+	mov	r15,rsi
+	mov	r14d,4
+	jmp	NEAR $L$sqr_entry_1024
+ALIGN	32
+$L$OOP_SQR_1024:
+	vpbroadcastq	ymm11,QWORD[((32-128))+r15]
+	vpmuludq	ymm0,ymm10,YMMWORD[((0-128))+rsi]
+	vpaddq	ymm0,ymm0,YMMWORD[((0-192))+rbx]
+	vpmuludq	ymm1,ymm10,YMMWORD[((0-128))+r9]
+	vpaddq	ymm1,ymm1,YMMWORD[((32-192))+rbx]
+	vpmuludq	ymm2,ymm10,YMMWORD[((32-128))+r9]
+	vpaddq	ymm2,ymm2,YMMWORD[((64-192))+rbx]
+	vpmuludq	ymm3,ymm10,YMMWORD[((64-128))+r9]
+	vpaddq	ymm3,ymm3,YMMWORD[((96-192))+rbx]
+	vpmuludq	ymm4,ymm10,YMMWORD[((96-128))+r9]
+	vpaddq	ymm4,ymm4,YMMWORD[((128-192))+rbx]
+	vpmuludq	ymm5,ymm10,YMMWORD[((128-128))+r9]
+	vpaddq	ymm5,ymm5,YMMWORD[((160-192))+rbx]
+	vpmuludq	ymm6,ymm10,YMMWORD[((160-128))+r9]
+	vpaddq	ymm6,ymm6,YMMWORD[((192-192))+rbx]
+	vpmuludq	ymm7,ymm10,YMMWORD[((192-128))+r9]
+	vpaddq	ymm7,ymm7,YMMWORD[((224-192))+rbx]
+	vpmuludq	ymm8,ymm10,YMMWORD[((224-128))+r9]
+	vpbroadcastq	ymm10,QWORD[((64-128))+r15]
+	vpaddq	ymm8,ymm8,YMMWORD[((256-192))+rbx]
+$L$sqr_entry_1024:
+	vmovdqu	YMMWORD[(0-192)+rbx],ymm0
+	vmovdqu	YMMWORD[(32-192)+rbx],ymm1
+
+	vpmuludq	ymm12,ymm11,YMMWORD[((32-128))+rsi]
+	vpaddq	ymm2,ymm2,ymm12
+	vpmuludq	ymm14,ymm11,YMMWORD[((32-128))+r9]
+	vpaddq	ymm3,ymm3,ymm14
+	vpmuludq	ymm13,ymm11,YMMWORD[((64-128))+r9]
+	vpaddq	ymm4,ymm4,ymm13
+	vpmuludq	ymm12,ymm11,YMMWORD[((96-128))+r9]
+	vpaddq	ymm5,ymm5,ymm12
+	vpmuludq	ymm14,ymm11,YMMWORD[((128-128))+r9]
+	vpaddq	ymm6,ymm6,ymm14
+	vpmuludq	ymm13,ymm11,YMMWORD[((160-128))+r9]
+	vpaddq	ymm7,ymm7,ymm13
+	vpmuludq	ymm12,ymm11,YMMWORD[((192-128))+r9]
+	vpaddq	ymm8,ymm8,ymm12
+	vpmuludq	ymm0,ymm11,YMMWORD[((224-128))+r9]
+	vpbroadcastq	ymm11,QWORD[((96-128))+r15]
+	vpaddq	ymm0,ymm0,YMMWORD[((288-192))+rbx]
+
+	vmovdqu	YMMWORD[(64-192)+rbx],ymm2
+	vmovdqu	YMMWORD[(96-192)+rbx],ymm3
+
+	vpmuludq	ymm13,ymm10,YMMWORD[((64-128))+rsi]
+	vpaddq	ymm4,ymm4,ymm13
+	vpmuludq	ymm12,ymm10,YMMWORD[((64-128))+r9]
+	vpaddq	ymm5,ymm5,ymm12
+	vpmuludq	ymm14,ymm10,YMMWORD[((96-128))+r9]
+	vpaddq	ymm6,ymm6,ymm14
+	vpmuludq	ymm13,ymm10,YMMWORD[((128-128))+r9]
+	vpaddq	ymm7,ymm7,ymm13
+	vpmuludq	ymm12,ymm10,YMMWORD[((160-128))+r9]
+	vpaddq	ymm8,ymm8,ymm12
+	vpmuludq	ymm14,ymm10,YMMWORD[((192-128))+r9]
+	vpaddq	ymm0,ymm0,ymm14
+	vpmuludq	ymm1,ymm10,YMMWORD[((224-128))+r9]
+	vpbroadcastq	ymm10,QWORD[((128-128))+r15]
+	vpaddq	ymm1,ymm1,YMMWORD[((320-448))+r12]
+
+	vmovdqu	YMMWORD[(128-192)+rbx],ymm4
+	vmovdqu	YMMWORD[(160-192)+rbx],ymm5
+
+	vpmuludq	ymm12,ymm11,YMMWORD[((96-128))+rsi]
+	vpaddq	ymm6,ymm6,ymm12
+	vpmuludq	ymm14,ymm11,YMMWORD[((96-128))+r9]
+	vpaddq	ymm7,ymm7,ymm14
+	vpmuludq	ymm13,ymm11,YMMWORD[((128-128))+r9]
+	vpaddq	ymm8,ymm8,ymm13
+	vpmuludq	ymm12,ymm11,YMMWORD[((160-128))+r9]
+	vpaddq	ymm0,ymm0,ymm12
+	vpmuludq	ymm14,ymm11,YMMWORD[((192-128))+r9]
+	vpaddq	ymm1,ymm1,ymm14
+	vpmuludq	ymm2,ymm11,YMMWORD[((224-128))+r9]
+	vpbroadcastq	ymm11,QWORD[((160-128))+r15]
+	vpaddq	ymm2,ymm2,YMMWORD[((352-448))+r12]
+
+	vmovdqu	YMMWORD[(192-192)+rbx],ymm6
+	vmovdqu	YMMWORD[(224-192)+rbx],ymm7
+
+	vpmuludq	ymm12,ymm10,YMMWORD[((128-128))+rsi]
+	vpaddq	ymm8,ymm8,ymm12
+	vpmuludq	ymm14,ymm10,YMMWORD[((128-128))+r9]
+	vpaddq	ymm0,ymm0,ymm14
+	vpmuludq	ymm13,ymm10,YMMWORD[((160-128))+r9]
+	vpaddq	ymm1,ymm1,ymm13
+	vpmuludq	ymm12,ymm10,YMMWORD[((192-128))+r9]
+	vpaddq	ymm2,ymm2,ymm12
+	vpmuludq	ymm3,ymm10,YMMWORD[((224-128))+r9]
+	vpbroadcastq	ymm10,QWORD[((192-128))+r15]
+	vpaddq	ymm3,ymm3,YMMWORD[((384-448))+r12]
+
+	vmovdqu	YMMWORD[(256-192)+rbx],ymm8
+	vmovdqu	YMMWORD[(288-192)+rbx],ymm0
+	lea	rbx,[8+rbx]
+
+	vpmuludq	ymm13,ymm11,YMMWORD[((160-128))+rsi]
+	vpaddq	ymm1,ymm1,ymm13
+	vpmuludq	ymm12,ymm11,YMMWORD[((160-128))+r9]
+	vpaddq	ymm2,ymm2,ymm12
+	vpmuludq	ymm14,ymm11,YMMWORD[((192-128))+r9]
+	vpaddq	ymm3,ymm3,ymm14
+	vpmuludq	ymm4,ymm11,YMMWORD[((224-128))+r9]
+	vpbroadcastq	ymm11,QWORD[((224-128))+r15]
+	vpaddq	ymm4,ymm4,YMMWORD[((416-448))+r12]
+
+	vmovdqu	YMMWORD[(320-448)+r12],ymm1
+	vmovdqu	YMMWORD[(352-448)+r12],ymm2
+
+	vpmuludq	ymm12,ymm10,YMMWORD[((192-128))+rsi]
+	vpaddq	ymm3,ymm3,ymm12
+	vpmuludq	ymm14,ymm10,YMMWORD[((192-128))+r9]
+	vpbroadcastq	ymm0,QWORD[((256-128))+r15]
+	vpaddq	ymm4,ymm4,ymm14
+	vpmuludq	ymm5,ymm10,YMMWORD[((224-128))+r9]
+	vpbroadcastq	ymm10,QWORD[((0+8-128))+r15]
+	vpaddq	ymm5,ymm5,YMMWORD[((448-448))+r12]
+
+	vmovdqu	YMMWORD[(384-448)+r12],ymm3
+	vmovdqu	YMMWORD[(416-448)+r12],ymm4
+	lea	r15,[8+r15]
+
+	vpmuludq	ymm12,ymm11,YMMWORD[((224-128))+rsi]
+	vpaddq	ymm5,ymm5,ymm12
+	vpmuludq	ymm6,ymm11,YMMWORD[((224-128))+r9]
+	vpaddq	ymm6,ymm6,YMMWORD[((480-448))+r12]
+
+	vpmuludq	ymm7,ymm0,YMMWORD[((256-128))+rsi]
+	vmovdqu	YMMWORD[(448-448)+r12],ymm5
+	vpaddq	ymm7,ymm7,YMMWORD[((512-448))+r12]
+	vmovdqu	YMMWORD[(480-448)+r12],ymm6
+	vmovdqu	YMMWORD[(512-448)+r12],ymm7
+	lea	r12,[8+r12]
+
+	dec	r14d
+	jnz	NEAR $L$OOP_SQR_1024
+
+	vmovdqu	ymm8,YMMWORD[256+rsp]
+	vmovdqu	ymm1,YMMWORD[288+rsp]
+	vmovdqu	ymm2,YMMWORD[320+rsp]
+	lea	rbx,[192+rsp]
+
+	vpsrlq	ymm14,ymm8,29
+	vpand	ymm8,ymm8,ymm15
+	vpsrlq	ymm11,ymm1,29
+	vpand	ymm1,ymm1,ymm15
+
+	vpermq	ymm14,ymm14,0x93
+	vpxor	ymm9,ymm9,ymm9
+	vpermq	ymm11,ymm11,0x93
+
+	vpblendd	ymm10,ymm14,ymm9,3
+	vpblendd	ymm14,ymm11,ymm14,3
+	vpaddq	ymm8,ymm8,ymm10
+	vpblendd	ymm11,ymm9,ymm11,3
+	vpaddq	ymm1,ymm1,ymm14
+	vpaddq	ymm2,ymm2,ymm11
+	vmovdqu	YMMWORD[(288-192)+rbx],ymm1
+	vmovdqu	YMMWORD[(320-192)+rbx],ymm2
+
+	mov	rax,QWORD[rsp]
+	mov	r10,QWORD[8+rsp]
+	mov	r11,QWORD[16+rsp]
+	mov	r12,QWORD[24+rsp]
+	vmovdqu	ymm1,YMMWORD[32+rsp]
+	vmovdqu	ymm2,YMMWORD[((64-192))+rbx]
+	vmovdqu	ymm3,YMMWORD[((96-192))+rbx]
+	vmovdqu	ymm4,YMMWORD[((128-192))+rbx]
+	vmovdqu	ymm5,YMMWORD[((160-192))+rbx]
+	vmovdqu	ymm6,YMMWORD[((192-192))+rbx]
+	vmovdqu	ymm7,YMMWORD[((224-192))+rbx]
+
+	mov	r9,rax
+	imul	eax,ecx
+	and	eax,0x1fffffff
+	vmovd	xmm12,eax
+
+	mov	rdx,rax
+	imul	rax,QWORD[((-128))+r13]
+	vpbroadcastq	ymm12,xmm12
+	add	r9,rax
+	mov	rax,rdx
+	imul	rax,QWORD[((8-128))+r13]
+	shr	r9,29
+	add	r10,rax
+	mov	rax,rdx
+	imul	rax,QWORD[((16-128))+r13]
+	add	r10,r9
+	add	r11,rax
+	imul	rdx,QWORD[((24-128))+r13]
+	add	r12,rdx
+
+	mov	rax,r10
+	imul	eax,ecx
+	and	eax,0x1fffffff
+
+	mov	r14d,9
+	jmp	NEAR $L$OOP_REDUCE_1024
+
+ALIGN	32
+$L$OOP_REDUCE_1024:
+	vmovd	xmm13,eax
+	vpbroadcastq	ymm13,xmm13
+
+	vpmuludq	ymm10,ymm12,YMMWORD[((32-128))+r13]
+	mov	rdx,rax
+	imul	rax,QWORD[((-128))+r13]
+	vpaddq	ymm1,ymm1,ymm10
+	add	r10,rax
+	vpmuludq	ymm14,ymm12,YMMWORD[((64-128))+r13]
+	mov	rax,rdx
+	imul	rax,QWORD[((8-128))+r13]
+	vpaddq	ymm2,ymm2,ymm14
+	vpmuludq	ymm11,ymm12,YMMWORD[((96-128))+r13]
+DB	0x67
+	add	r11,rax
+DB	0x67
+	mov	rax,rdx
+	imul	rax,QWORD[((16-128))+r13]
+	shr	r10,29
+	vpaddq	ymm3,ymm3,ymm11
+	vpmuludq	ymm10,ymm12,YMMWORD[((128-128))+r13]
+	add	r12,rax
+	add	r11,r10
+	vpaddq	ymm4,ymm4,ymm10
+	vpmuludq	ymm14,ymm12,YMMWORD[((160-128))+r13]
+	mov	rax,r11
+	imul	eax,ecx
+	vpaddq	ymm5,ymm5,ymm14
+	vpmuludq	ymm11,ymm12,YMMWORD[((192-128))+r13]
+	and	eax,0x1fffffff
+	vpaddq	ymm6,ymm6,ymm11
+	vpmuludq	ymm10,ymm12,YMMWORD[((224-128))+r13]
+	vpaddq	ymm7,ymm7,ymm10
+	vpmuludq	ymm14,ymm12,YMMWORD[((256-128))+r13]
+	vmovd	xmm12,eax
+
+	vpaddq	ymm8,ymm8,ymm14
+
+	vpbroadcastq	ymm12,xmm12
+
+	vpmuludq	ymm11,ymm13,YMMWORD[((32-8-128))+r13]
+	vmovdqu	ymm14,YMMWORD[((96-8-128))+r13]
+	mov	rdx,rax
+	imul	rax,QWORD[((-128))+r13]
+	vpaddq	ymm1,ymm1,ymm11
+	vpmuludq	ymm10,ymm13,YMMWORD[((64-8-128))+r13]
+	vmovdqu	ymm11,YMMWORD[((128-8-128))+r13]
+	add	r11,rax
+	mov	rax,rdx
+	imul	rax,QWORD[((8-128))+r13]
+	vpaddq	ymm2,ymm2,ymm10
+	add	rax,r12
+	shr	r11,29
+	vpmuludq	ymm14,ymm14,ymm13
+	vmovdqu	ymm10,YMMWORD[((160-8-128))+r13]
+	add	rax,r11
+	vpaddq	ymm3,ymm3,ymm14
+	vpmuludq	ymm11,ymm11,ymm13
+	vmovdqu	ymm14,YMMWORD[((192-8-128))+r13]
+DB	0x67
+	mov	r12,rax
+	imul	eax,ecx
+	vpaddq	ymm4,ymm4,ymm11
+	vpmuludq	ymm10,ymm10,ymm13
+DB	0xc4,0x41,0x7e,0x6f,0x9d,0x58,0x00,0x00,0x00
+	and	eax,0x1fffffff
+	vpaddq	ymm5,ymm5,ymm10
+	vpmuludq	ymm14,ymm14,ymm13
+	vmovdqu	ymm10,YMMWORD[((256-8-128))+r13]
+	vpaddq	ymm6,ymm6,ymm14
+	vpmuludq	ymm11,ymm11,ymm13
+	vmovdqu	ymm9,YMMWORD[((288-8-128))+r13]
+	vmovd	xmm0,eax
+	imul	rax,QWORD[((-128))+r13]
+	vpaddq	ymm7,ymm7,ymm11
+	vpmuludq	ymm10,ymm10,ymm13
+	vmovdqu	ymm14,YMMWORD[((32-16-128))+r13]
+	vpbroadcastq	ymm0,xmm0
+	vpaddq	ymm8,ymm8,ymm10
+	vpmuludq	ymm9,ymm9,ymm13
+	vmovdqu	ymm11,YMMWORD[((64-16-128))+r13]
+	add	r12,rax
+
+	vmovdqu	ymm13,YMMWORD[((32-24-128))+r13]
+	vpmuludq	ymm14,ymm14,ymm12
+	vmovdqu	ymm10,YMMWORD[((96-16-128))+r13]
+	vpaddq	ymm1,ymm1,ymm14
+	vpmuludq	ymm13,ymm13,ymm0
+	vpmuludq	ymm11,ymm11,ymm12
+DB	0xc4,0x41,0x7e,0x6f,0xb5,0xf0,0xff,0xff,0xff
+	vpaddq	ymm13,ymm13,ymm1
+	vpaddq	ymm2,ymm2,ymm11
+	vpmuludq	ymm10,ymm10,ymm12
+	vmovdqu	ymm11,YMMWORD[((160-16-128))+r13]
+DB	0x67
+	vmovq	rax,xmm13
+	vmovdqu	YMMWORD[rsp],ymm13
+	vpaddq	ymm3,ymm3,ymm10
+	vpmuludq	ymm14,ymm14,ymm12
+	vmovdqu	ymm10,YMMWORD[((192-16-128))+r13]
+	vpaddq	ymm4,ymm4,ymm14
+	vpmuludq	ymm11,ymm11,ymm12
+	vmovdqu	ymm14,YMMWORD[((224-16-128))+r13]
+	vpaddq	ymm5,ymm5,ymm11
+	vpmuludq	ymm10,ymm10,ymm12
+	vmovdqu	ymm11,YMMWORD[((256-16-128))+r13]
+	vpaddq	ymm6,ymm6,ymm10
+	vpmuludq	ymm14,ymm14,ymm12
+	shr	r12,29
+	vmovdqu	ymm10,YMMWORD[((288-16-128))+r13]
+	add	rax,r12
+	vpaddq	ymm7,ymm7,ymm14
+	vpmuludq	ymm11,ymm11,ymm12
+
+	mov	r9,rax
+	imul	eax,ecx
+	vpaddq	ymm8,ymm8,ymm11
+	vpmuludq	ymm10,ymm10,ymm12
+	and	eax,0x1fffffff
+	vmovd	xmm12,eax
+	vmovdqu	ymm11,YMMWORD[((96-24-128))+r13]
+DB	0x67
+	vpaddq	ymm9,ymm9,ymm10
+	vpbroadcastq	ymm12,xmm12
+
+	vpmuludq	ymm14,ymm0,YMMWORD[((64-24-128))+r13]
+	vmovdqu	ymm10,YMMWORD[((128-24-128))+r13]
+	mov	rdx,rax
+	imul	rax,QWORD[((-128))+r13]
+	mov	r10,QWORD[8+rsp]
+	vpaddq	ymm1,ymm2,ymm14
+	vpmuludq	ymm11,ymm11,ymm0
+	vmovdqu	ymm14,YMMWORD[((160-24-128))+r13]
+	add	r9,rax
+	mov	rax,rdx
+	imul	rax,QWORD[((8-128))+r13]
+DB	0x67
+	shr	r9,29
+	mov	r11,QWORD[16+rsp]
+	vpaddq	ymm2,ymm3,ymm11
+	vpmuludq	ymm10,ymm10,ymm0
+	vmovdqu	ymm11,YMMWORD[((192-24-128))+r13]
+	add	r10,rax
+	mov	rax,rdx
+	imul	rax,QWORD[((16-128))+r13]
+	vpaddq	ymm3,ymm4,ymm10
+	vpmuludq	ymm14,ymm14,ymm0
+	vmovdqu	ymm10,YMMWORD[((224-24-128))+r13]
+	imul	rdx,QWORD[((24-128))+r13]
+	add	r11,rax
+	lea	rax,[r10*1+r9]
+	vpaddq	ymm4,ymm5,ymm14
+	vpmuludq	ymm11,ymm11,ymm0
+	vmovdqu	ymm14,YMMWORD[((256-24-128))+r13]
+	mov	r10,rax
+	imul	eax,ecx
+	vpmuludq	ymm10,ymm10,ymm0
+	vpaddq	ymm5,ymm6,ymm11
+	vmovdqu	ymm11,YMMWORD[((288-24-128))+r13]
+	and	eax,0x1fffffff
+	vpaddq	ymm6,ymm7,ymm10
+	vpmuludq	ymm14,ymm14,ymm0
+	add	rdx,QWORD[24+rsp]
+	vpaddq	ymm7,ymm8,ymm14
+	vpmuludq	ymm11,ymm11,ymm0
+	vpaddq	ymm8,ymm9,ymm11
+	vmovq	xmm9,r12
+	mov	r12,rdx
+
+	dec	r14d
+	jnz	NEAR $L$OOP_REDUCE_1024
+	lea	r12,[448+rsp]
+	vpaddq	ymm0,ymm13,ymm9
+	vpxor	ymm9,ymm9,ymm9
+
+	vpaddq	ymm0,ymm0,YMMWORD[((288-192))+rbx]
+	vpaddq	ymm1,ymm1,YMMWORD[((320-448))+r12]
+	vpaddq	ymm2,ymm2,YMMWORD[((352-448))+r12]
+	vpaddq	ymm3,ymm3,YMMWORD[((384-448))+r12]
+	vpaddq	ymm4,ymm4,YMMWORD[((416-448))+r12]
+	vpaddq	ymm5,ymm5,YMMWORD[((448-448))+r12]
+	vpaddq	ymm6,ymm6,YMMWORD[((480-448))+r12]
+	vpaddq	ymm7,ymm7,YMMWORD[((512-448))+r12]
+	vpaddq	ymm8,ymm8,YMMWORD[((544-448))+r12]
+
+	vpsrlq	ymm14,ymm0,29
+	vpand	ymm0,ymm0,ymm15
+	vpsrlq	ymm11,ymm1,29
+	vpand	ymm1,ymm1,ymm15
+	vpsrlq	ymm12,ymm2,29
+	vpermq	ymm14,ymm14,0x93
+	vpand	ymm2,ymm2,ymm15
+	vpsrlq	ymm13,ymm3,29
+	vpermq	ymm11,ymm11,0x93
+	vpand	ymm3,ymm3,ymm15
+	vpermq	ymm12,ymm12,0x93
+
+	vpblendd	ymm10,ymm14,ymm9,3
+	vpermq	ymm13,ymm13,0x93
+	vpblendd	ymm14,ymm11,ymm14,3
+	vpaddq	ymm0,ymm0,ymm10
+	vpblendd	ymm11,ymm12,ymm11,3
+	vpaddq	ymm1,ymm1,ymm14
+	vpblendd	ymm12,ymm13,ymm12,3
+	vpaddq	ymm2,ymm2,ymm11
+	vpblendd	ymm13,ymm9,ymm13,3
+	vpaddq	ymm3,ymm3,ymm12
+	vpaddq	ymm4,ymm4,ymm13
+
+	vpsrlq	ymm14,ymm0,29
+	vpand	ymm0,ymm0,ymm15
+	vpsrlq	ymm11,ymm1,29
+	vpand	ymm1,ymm1,ymm15
+	vpsrlq	ymm12,ymm2,29
+	vpermq	ymm14,ymm14,0x93
+	vpand	ymm2,ymm2,ymm15
+	vpsrlq	ymm13,ymm3,29
+	vpermq	ymm11,ymm11,0x93
+	vpand	ymm3,ymm3,ymm15
+	vpermq	ymm12,ymm12,0x93
+
+	vpblendd	ymm10,ymm14,ymm9,3
+	vpermq	ymm13,ymm13,0x93
+	vpblendd	ymm14,ymm11,ymm14,3
+	vpaddq	ymm0,ymm0,ymm10
+	vpblendd	ymm11,ymm12,ymm11,3
+	vpaddq	ymm1,ymm1,ymm14
+	vmovdqu	YMMWORD[(0-128)+rdi],ymm0
+	vpblendd	ymm12,ymm13,ymm12,3
+	vpaddq	ymm2,ymm2,ymm11
+	vmovdqu	YMMWORD[(32-128)+rdi],ymm1
+	vpblendd	ymm13,ymm9,ymm13,3
+	vpaddq	ymm3,ymm3,ymm12
+	vmovdqu	YMMWORD[(64-128)+rdi],ymm2
+	vpaddq	ymm4,ymm4,ymm13
+	vmovdqu	YMMWORD[(96-128)+rdi],ymm3
+	vpsrlq	ymm14,ymm4,29
+	vpand	ymm4,ymm4,ymm15
+	vpsrlq	ymm11,ymm5,29
+	vpand	ymm5,ymm5,ymm15
+	vpsrlq	ymm12,ymm6,29
+	vpermq	ymm14,ymm14,0x93
+	vpand	ymm6,ymm6,ymm15
+	vpsrlq	ymm13,ymm7,29
+	vpermq	ymm11,ymm11,0x93
+	vpand	ymm7,ymm7,ymm15
+	vpsrlq	ymm0,ymm8,29
+	vpermq	ymm12,ymm12,0x93
+	vpand	ymm8,ymm8,ymm15
+	vpermq	ymm13,ymm13,0x93
+
+	vpblendd	ymm10,ymm14,ymm9,3
+	vpermq	ymm0,ymm0,0x93
+	vpblendd	ymm14,ymm11,ymm14,3
+	vpaddq	ymm4,ymm4,ymm10
+	vpblendd	ymm11,ymm12,ymm11,3
+	vpaddq	ymm5,ymm5,ymm14
+	vpblendd	ymm12,ymm13,ymm12,3
+	vpaddq	ymm6,ymm6,ymm11
+	vpblendd	ymm13,ymm0,ymm13,3
+	vpaddq	ymm7,ymm7,ymm12
+	vpaddq	ymm8,ymm8,ymm13
+
+	vpsrlq	ymm14,ymm4,29
+	vpand	ymm4,ymm4,ymm15
+	vpsrlq	ymm11,ymm5,29
+	vpand	ymm5,ymm5,ymm15
+	vpsrlq	ymm12,ymm6,29
+	vpermq	ymm14,ymm14,0x93
+	vpand	ymm6,ymm6,ymm15
+	vpsrlq	ymm13,ymm7,29
+	vpermq	ymm11,ymm11,0x93
+	vpand	ymm7,ymm7,ymm15
+	vpsrlq	ymm0,ymm8,29
+	vpermq	ymm12,ymm12,0x93
+	vpand	ymm8,ymm8,ymm15
+	vpermq	ymm13,ymm13,0x93
+
+	vpblendd	ymm10,ymm14,ymm9,3
+	vpermq	ymm0,ymm0,0x93
+	vpblendd	ymm14,ymm11,ymm14,3
+	vpaddq	ymm4,ymm4,ymm10
+	vpblendd	ymm11,ymm12,ymm11,3
+	vpaddq	ymm5,ymm5,ymm14
+	vmovdqu	YMMWORD[(128-128)+rdi],ymm4
+	vpblendd	ymm12,ymm13,ymm12,3
+	vpaddq	ymm6,ymm6,ymm11
+	vmovdqu	YMMWORD[(160-128)+rdi],ymm5
+	vpblendd	ymm13,ymm0,ymm13,3
+	vpaddq	ymm7,ymm7,ymm12
+	vmovdqu	YMMWORD[(192-128)+rdi],ymm6
+	vpaddq	ymm8,ymm8,ymm13
+	vmovdqu	YMMWORD[(224-128)+rdi],ymm7
+	vmovdqu	YMMWORD[(256-128)+rdi],ymm8
+
+	mov	rsi,rdi
+	dec	r8d
+	jne	NEAR $L$OOP_GRANDE_SQR_1024
+
+	vzeroall
+	mov	rax,rbp
+
+$L$sqr_1024_in_tail:
+	movaps	xmm6,XMMWORD[((-216))+rax]
+	movaps	xmm7,XMMWORD[((-200))+rax]
+	movaps	xmm8,XMMWORD[((-184))+rax]
+	movaps	xmm9,XMMWORD[((-168))+rax]
+	movaps	xmm10,XMMWORD[((-152))+rax]
+	movaps	xmm11,XMMWORD[((-136))+rax]
+	movaps	xmm12,XMMWORD[((-120))+rax]
+	movaps	xmm13,XMMWORD[((-104))+rax]
+	movaps	xmm14,XMMWORD[((-88))+rax]
+	movaps	xmm15,XMMWORD[((-72))+rax]
+	mov	r15,QWORD[((-48))+rax]
+
+	mov	r14,QWORD[((-40))+rax]
+
+	mov	r13,QWORD[((-32))+rax]
+
+	mov	r12,QWORD[((-24))+rax]
+
+	mov	rbp,QWORD[((-16))+rax]
+
+	mov	rbx,QWORD[((-8))+rax]
+
+	lea	rsp,[rax]
+
+$L$sqr_1024_epilogue:
+	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD[16+rsp]
+	DB	0F3h,0C3h		;repret
+
+$L$SEH_end_rsaz_1024_sqr_avx2:
+global	rsaz_1024_mul_avx2
+
+ALIGN	64
+rsaz_1024_mul_avx2:
+	mov	QWORD[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_rsaz_1024_mul_avx2:
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+	mov	r8,QWORD[40+rsp]
+
+
+
+	lea	rax,[rsp]
+
+	push	rbx
+
+	push	rbp
+
+	push	r12
+
+	push	r13
+
+	push	r14
+
+	push	r15
+
+	vzeroupper
+	lea	rsp,[((-168))+rsp]
+	vmovaps	XMMWORD[(-216)+rax],xmm6
+	vmovaps	XMMWORD[(-200)+rax],xmm7
+	vmovaps	XMMWORD[(-184)+rax],xmm8
+	vmovaps	XMMWORD[(-168)+rax],xmm9
+	vmovaps	XMMWORD[(-152)+rax],xmm10
+	vmovaps	XMMWORD[(-136)+rax],xmm11
+	vmovaps	XMMWORD[(-120)+rax],xmm12
+	vmovaps	XMMWORD[(-104)+rax],xmm13
+	vmovaps	XMMWORD[(-88)+rax],xmm14
+	vmovaps	XMMWORD[(-72)+rax],xmm15
+$L$mul_1024_body:
+	mov	rbp,rax
+
+	vzeroall
+	mov	r13,rdx
+	sub	rsp,64
+
+
+
+
+
+
+DB	0x67,0x67
+	mov	r15,rsi
+	and	r15,4095
+	add	r15,32*10
+	shr	r15,12
+	mov	r15,rsi
+	cmovnz	rsi,r13
+	cmovnz	r13,r15
+
+	mov	r15,rcx
+	sub	rsi,-128
+	sub	rcx,-128
+	sub	rdi,-128
+
+	and	r15,4095
+	add	r15,32*10
+DB	0x67,0x67
+	shr	r15,12
+	jz	NEAR $L$mul_1024_no_n_copy
+
+
+
+
+
+	sub	rsp,32*10
+	vmovdqu	ymm0,YMMWORD[((0-128))+rcx]
+	and	rsp,-512
+	vmovdqu	ymm1,YMMWORD[((32-128))+rcx]
+	vmovdqu	ymm2,YMMWORD[((64-128))+rcx]
+	vmovdqu	ymm3,YMMWORD[((96-128))+rcx]
+	vmovdqu	ymm4,YMMWORD[((128-128))+rcx]
+	vmovdqu	ymm5,YMMWORD[((160-128))+rcx]
+	vmovdqu	ymm6,YMMWORD[((192-128))+rcx]
+	vmovdqu	ymm7,YMMWORD[((224-128))+rcx]
+	vmovdqu	ymm8,YMMWORD[((256-128))+rcx]
+	lea	rcx,[((64+128))+rsp]
+	vmovdqu	YMMWORD[(0-128)+rcx],ymm0
+	vpxor	ymm0,ymm0,ymm0
+	vmovdqu	YMMWORD[(32-128)+rcx],ymm1
+	vpxor	ymm1,ymm1,ymm1
+	vmovdqu	YMMWORD[(64-128)+rcx],ymm2
+	vpxor	ymm2,ymm2,ymm2
+	vmovdqu	YMMWORD[(96-128)+rcx],ymm3
+	vpxor	ymm3,ymm3,ymm3
+	vmovdqu	YMMWORD[(128-128)+rcx],ymm4
+	vpxor	ymm4,ymm4,ymm4
+	vmovdqu	YMMWORD[(160-128)+rcx],ymm5
+	vpxor	ymm5,ymm5,ymm5
+	vmovdqu	YMMWORD[(192-128)+rcx],ymm6
+	vpxor	ymm6,ymm6,ymm6
+	vmovdqu	YMMWORD[(224-128)+rcx],ymm7
+	vpxor	ymm7,ymm7,ymm7
+	vmovdqu	YMMWORD[(256-128)+rcx],ymm8
+	vmovdqa	ymm8,ymm0
+	vmovdqu	YMMWORD[(288-128)+rcx],ymm9
+$L$mul_1024_no_n_copy:
+	and	rsp,-64
+
+	mov	rbx,QWORD[r13]
+	vpbroadcastq	ymm10,QWORD[r13]
+	vmovdqu	YMMWORD[rsp],ymm0
+	xor	r9,r9
+DB	0x67
+	xor	r10,r10
+	xor	r11,r11
+	xor	r12,r12
+
+	vmovdqu	ymm15,YMMWORD[$L$and_mask]
+	mov	r14d,9
+	vmovdqu	YMMWORD[(288-128)+rdi],ymm9
+	jmp	NEAR $L$oop_mul_1024
+
+ALIGN	32
+$L$oop_mul_1024:
+	vpsrlq	ymm9,ymm3,29
+	mov	rax,rbx
+	imul	rax,QWORD[((-128))+rsi]
+	add	rax,r9
+	mov	r10,rbx
+	imul	r10,QWORD[((8-128))+rsi]
+	add	r10,QWORD[8+rsp]
+
+	mov	r9,rax
+	imul	eax,r8d
+	and	eax,0x1fffffff
+
+	mov	r11,rbx
+	imul	r11,QWORD[((16-128))+rsi]
+	add	r11,QWORD[16+rsp]
+
+	mov	r12,rbx
+	imul	r12,QWORD[((24-128))+rsi]
+	add	r12,QWORD[24+rsp]
+	vpmuludq	ymm0,ymm10,YMMWORD[((32-128))+rsi]
+	vmovd	xmm11,eax
+	vpaddq	ymm1,ymm1,ymm0
+	vpmuludq	ymm12,ymm10,YMMWORD[((64-128))+rsi]
+	vpbroadcastq	ymm11,xmm11
+	vpaddq	ymm2,ymm2,ymm12
+	vpmuludq	ymm13,ymm10,YMMWORD[((96-128))+rsi]
+	vpand	ymm3,ymm3,ymm15
+	vpaddq	ymm3,ymm3,ymm13
+	vpmuludq	ymm0,ymm10,YMMWORD[((128-128))+rsi]
+	vpaddq	ymm4,ymm4,ymm0
+	vpmuludq	ymm12,ymm10,YMMWORD[((160-128))+rsi]
+	vpaddq	ymm5,ymm5,ymm12
+	vpmuludq	ymm13,ymm10,YMMWORD[((192-128))+rsi]
+	vpaddq	ymm6,ymm6,ymm13
+	vpmuludq	ymm0,ymm10,YMMWORD[((224-128))+rsi]
+	vpermq	ymm9,ymm9,0x93
+	vpaddq	ymm7,ymm7,ymm0
+	vpmuludq	ymm12,ymm10,YMMWORD[((256-128))+rsi]
+	vpbroadcastq	ymm10,QWORD[8+r13]
+	vpaddq	ymm8,ymm8,ymm12
+
+	mov	rdx,rax
+	imul	rax,QWORD[((-128))+rcx]
+	add	r9,rax
+	mov	rax,rdx
+	imul	rax,QWORD[((8-128))+rcx]
+	add	r10,rax
+	mov	rax,rdx
+	imul	rax,QWORD[((16-128))+rcx]
+	add	r11,rax
+	shr	r9,29
+	imul	rdx,QWORD[((24-128))+rcx]
+	add	r12,rdx
+	add	r10,r9
+
+	vpmuludq	ymm13,ymm11,YMMWORD[((32-128))+rcx]
+	vmovq	rbx,xmm10
+	vpaddq	ymm1,ymm1,ymm13
+	vpmuludq	ymm0,ymm11,YMMWORD[((64-128))+rcx]
+	vpaddq	ymm2,ymm2,ymm0
+	vpmuludq	ymm12,ymm11,YMMWORD[((96-128))+rcx]
+	vpaddq	ymm3,ymm3,ymm12
+	vpmuludq	ymm13,ymm11,YMMWORD[((128-128))+rcx]
+	vpaddq	ymm4,ymm4,ymm13
+	vpmuludq	ymm0,ymm11,YMMWORD[((160-128))+rcx]
+	vpaddq	ymm5,ymm5,ymm0
+	vpmuludq	ymm12,ymm11,YMMWORD[((192-128))+rcx]
+	vpaddq	ymm6,ymm6,ymm12
+	vpmuludq	ymm13,ymm11,YMMWORD[((224-128))+rcx]
+	vpblendd	ymm9,ymm9,ymm14,3
+	vpaddq	ymm7,ymm7,ymm13
+	vpmuludq	ymm0,ymm11,YMMWORD[((256-128))+rcx]
+	vpaddq	ymm3,ymm3,ymm9
+	vpaddq	ymm8,ymm8,ymm0
+
+	mov	rax,rbx
+	imul	rax,QWORD[((-128))+rsi]
+	add	r10,rax
+	vmovdqu	ymm12,YMMWORD[((-8+32-128))+rsi]
+	mov	rax,rbx
+	imul	rax,QWORD[((8-128))+rsi]
+	add	r11,rax
+	vmovdqu	ymm13,YMMWORD[((-8+64-128))+rsi]
+
+	mov	rax,r10
+	imul	eax,r8d
+	and	eax,0x1fffffff
+
+	imul	rbx,QWORD[((16-128))+rsi]
+	add	r12,rbx
+	vpmuludq	ymm12,ymm12,ymm10
+	vmovd	xmm11,eax
+	vmovdqu	ymm0,YMMWORD[((-8+96-128))+rsi]
+	vpaddq	ymm1,ymm1,ymm12
+	vpmuludq	ymm13,ymm13,ymm10
+	vpbroadcastq	ymm11,xmm11
+	vmovdqu	ymm12,YMMWORD[((-8+128-128))+rsi]
+	vpaddq	ymm2,ymm2,ymm13
+	vpmuludq	ymm0,ymm0,ymm10
+	vmovdqu	ymm13,YMMWORD[((-8+160-128))+rsi]
+	vpaddq	ymm3,ymm3,ymm0
+	vpmuludq	ymm12,ymm12,ymm10
+	vmovdqu	ymm0,YMMWORD[((-8+192-128))+rsi]
+	vpaddq	ymm4,ymm4,ymm12
+	vpmuludq	ymm13,ymm13,ymm10
+	vmovdqu	ymm12,YMMWORD[((-8+224-128))+rsi]
+	vpaddq	ymm5,ymm5,ymm13
+	vpmuludq	ymm0,ymm0,ymm10
+	vmovdqu	ymm13,YMMWORD[((-8+256-128))+rsi]
+	vpaddq	ymm6,ymm6,ymm0
+	vpmuludq	ymm12,ymm12,ymm10
+	vmovdqu	ymm9,YMMWORD[((-8+288-128))+rsi]
+	vpaddq	ymm7,ymm7,ymm12
+	vpmuludq	ymm13,ymm13,ymm10
+	vpaddq	ymm8,ymm8,ymm13
+	vpmuludq	ymm9,ymm9,ymm10
+	vpbroadcastq	ymm10,QWORD[16+r13]
+
+	mov	rdx,rax
+	imul	rax,QWORD[((-128))+rcx]
+	add	r10,rax
+	vmovdqu	ymm0,YMMWORD[((-8+32-128))+rcx]
+	mov	rax,rdx
+	imul	rax,QWORD[((8-128))+rcx]
+	add	r11,rax
+	vmovdqu	ymm12,YMMWORD[((-8+64-128))+rcx]
+	shr	r10,29
+	imul	rdx,QWORD[((16-128))+rcx]
+	add	r12,rdx
+	add	r11,r10
+
+	vpmuludq	ymm0,ymm0,ymm11
+	vmovq	rbx,xmm10
+	vmovdqu	ymm13,YMMWORD[((-8+96-128))+rcx]
+	vpaddq	ymm1,ymm1,ymm0
+	vpmuludq	ymm12,ymm12,ymm11
+	vmovdqu	ymm0,YMMWORD[((-8+128-128))+rcx]
+	vpaddq	ymm2,ymm2,ymm12
+	vpmuludq	ymm13,ymm13,ymm11
+	vmovdqu	ymm12,YMMWORD[((-8+160-128))+rcx]
+	vpaddq	ymm3,ymm3,ymm13
+	vpmuludq	ymm0,ymm0,ymm11
+	vmovdqu	ymm13,YMMWORD[((-8+192-128))+rcx]
+	vpaddq	ymm4,ymm4,ymm0
+	vpmuludq	ymm12,ymm12,ymm11
+	vmovdqu	ymm0,YMMWORD[((-8+224-128))+rcx]
+	vpaddq	ymm5,ymm5,ymm12
+	vpmuludq	ymm13,ymm13,ymm11
+	vmovdqu	ymm12,YMMWORD[((-8+256-128))+rcx]
+	vpaddq	ymm6,ymm6,ymm13
+	vpmuludq	ymm0,ymm0,ymm11
+	vmovdqu	ymm13,YMMWORD[((-8+288-128))+rcx]
+	vpaddq	ymm7,ymm7,ymm0
+	vpmuludq	ymm12,ymm12,ymm11
+	vpaddq	ymm8,ymm8,ymm12
+	vpmuludq	ymm13,ymm13,ymm11
+	vpaddq	ymm9,ymm9,ymm13
+
+	vmovdqu	ymm0,YMMWORD[((-16+32-128))+rsi]
+	mov	rax,rbx
+	imul	rax,QWORD[((-128))+rsi]
+	add	rax,r11
+
+	vmovdqu	ymm12,YMMWORD[((-16+64-128))+rsi]
+	mov	r11,rax
+	imul	eax,r8d
+	and	eax,0x1fffffff
+
+	imul	rbx,QWORD[((8-128))+rsi]
+	add	r12,rbx
+	vpmuludq	ymm0,ymm0,ymm10
+	vmovd	xmm11,eax
+	vmovdqu	ymm13,YMMWORD[((-16+96-128))+rsi]
+	vpaddq	ymm1,ymm1,ymm0
+	vpmuludq	ymm12,ymm12,ymm10
+	vpbroadcastq	ymm11,xmm11
+	vmovdqu	ymm0,YMMWORD[((-16+128-128))+rsi]
+	vpaddq	ymm2,ymm2,ymm12
+	vpmuludq	ymm13,ymm13,ymm10
+	vmovdqu	ymm12,YMMWORD[((-16+160-128))+rsi]
+	vpaddq	ymm3,ymm3,ymm13
+	vpmuludq	ymm0,ymm0,ymm10
+	vmovdqu	ymm13,YMMWORD[((-16+192-128))+rsi]
+	vpaddq	ymm4,ymm4,ymm0
+	vpmuludq	ymm12,ymm12,ymm10
+	vmovdqu	ymm0,YMMWORD[((-16+224-128))+rsi]
+	vpaddq	ymm5,ymm5,ymm12
+	vpmuludq	ymm13,ymm13,ymm10
+	vmovdqu	ymm12,YMMWORD[((-16+256-128))+rsi]
+	vpaddq	ymm6,ymm6,ymm13
+	vpmuludq	ymm0,ymm0,ymm10
+	vmovdqu	ymm13,YMMWORD[((-16+288-128))+rsi]
+	vpaddq	ymm7,ymm7,ymm0
+	vpmuludq	ymm12,ymm12,ymm10
+	vpaddq	ymm8,ymm8,ymm12
+	vpmuludq	ymm13,ymm13,ymm10
+	vpbroadcastq	ymm10,QWORD[24+r13]
+	vpaddq	ymm9,ymm9,ymm13
+
+	vmovdqu	ymm0,YMMWORD[((-16+32-128))+rcx]
+	mov	rdx,rax
+	imul	rax,QWORD[((-128))+rcx]
+	add	r11,rax
+	vmovdqu	ymm12,YMMWORD[((-16+64-128))+rcx]
+	imul	rdx,QWORD[((8-128))+rcx]
+	add	r12,rdx
+	shr	r11,29
+
+	vpmuludq	ymm0,ymm0,ymm11
+	vmovq	rbx,xmm10
+	vmovdqu	ymm13,YMMWORD[((-16+96-128))+rcx]
+	vpaddq	ymm1,ymm1,ymm0
+	vpmuludq	ymm12,ymm12,ymm11
+	vmovdqu	ymm0,YMMWORD[((-16+128-128))+rcx]
+	vpaddq	ymm2,ymm2,ymm12
+	vpmuludq	ymm13,ymm13,ymm11
+	vmovdqu	ymm12,YMMWORD[((-16+160-128))+rcx]
+	vpaddq	ymm3,ymm3,ymm13
+	vpmuludq	ymm0,ymm0,ymm11
+	vmovdqu	ymm13,YMMWORD[((-16+192-128))+rcx]
+	vpaddq	ymm4,ymm4,ymm0
+	vpmuludq	ymm12,ymm12,ymm11
+	vmovdqu	ymm0,YMMWORD[((-16+224-128))+rcx]
+	vpaddq	ymm5,ymm5,ymm12
+	vpmuludq	ymm13,ymm13,ymm11
+	vmovdqu	ymm12,YMMWORD[((-16+256-128))+rcx]
+	vpaddq	ymm6,ymm6,ymm13
+	vpmuludq	ymm0,ymm0,ymm11
+	vmovdqu	ymm13,YMMWORD[((-16+288-128))+rcx]
+	vpaddq	ymm7,ymm7,ymm0
+	vpmuludq	ymm12,ymm12,ymm11
+	vmovdqu	ymm0,YMMWORD[((-24+32-128))+rsi]
+	vpaddq	ymm8,ymm8,ymm12
+	vpmuludq	ymm13,ymm13,ymm11
+	vmovdqu	ymm12,YMMWORD[((-24+64-128))+rsi]
+	vpaddq	ymm9,ymm9,ymm13
+
+	add	r12,r11
+	imul	rbx,QWORD[((-128))+rsi]
+	add	r12,rbx
+
+	mov	rax,r12
+	imul	eax,r8d
+	and	eax,0x1fffffff
+
+	vpmuludq	ymm0,ymm0,ymm10
+	vmovd	xmm11,eax
+	vmovdqu	ymm13,YMMWORD[((-24+96-128))+rsi]
+	vpaddq	ymm1,ymm1,ymm0
+	vpmuludq	ymm12,ymm12,ymm10
+	vpbroadcastq	ymm11,xmm11
+	vmovdqu	ymm0,YMMWORD[((-24+128-128))+rsi]
+	vpaddq	ymm2,ymm2,ymm12
+	vpmuludq	ymm13,ymm13,ymm10
+	vmovdqu	ymm12,YMMWORD[((-24+160-128))+rsi]
+	vpaddq	ymm3,ymm3,ymm13
+	vpmuludq	ymm0,ymm0,ymm10
+	vmovdqu	ymm13,YMMWORD[((-24+192-128))+rsi]
+	vpaddq	ymm4,ymm4,ymm0
+	vpmuludq	ymm12,ymm12,ymm10
+	vmovdqu	ymm0,YMMWORD[((-24+224-128))+rsi]
+	vpaddq	ymm5,ymm5,ymm12
+	vpmuludq	ymm13,ymm13,ymm10
+	vmovdqu	ymm12,YMMWORD[((-24+256-128))+rsi]
+	vpaddq	ymm6,ymm6,ymm13
+	vpmuludq	ymm0,ymm0,ymm10
+	vmovdqu	ymm13,YMMWORD[((-24+288-128))+rsi]
+	vpaddq	ymm7,ymm7,ymm0
+	vpmuludq	ymm12,ymm12,ymm10
+	vpaddq	ymm8,ymm8,ymm12
+	vpmuludq	ymm13,ymm13,ymm10
+	vpbroadcastq	ymm10,QWORD[32+r13]
+	vpaddq	ymm9,ymm9,ymm13
+	add	r13,32
+
+	vmovdqu	ymm0,YMMWORD[((-24+32-128))+rcx]
+	imul	rax,QWORD[((-128))+rcx]
+	add	r12,rax
+	shr	r12,29
+
+	vmovdqu	ymm12,YMMWORD[((-24+64-128))+rcx]
+	vpmuludq	ymm0,ymm0,ymm11
+	vmovq	rbx,xmm10
+	vmovdqu	ymm13,YMMWORD[((-24+96-128))+rcx]
+	vpaddq	ymm0,ymm1,ymm0
+	vpmuludq	ymm12,ymm12,ymm11
+	vmovdqu	YMMWORD[rsp],ymm0
+	vpaddq	ymm1,ymm2,ymm12
+	vmovdqu	ymm0,YMMWORD[((-24+128-128))+rcx]
+	vpmuludq	ymm13,ymm13,ymm11
+	vmovdqu	ymm12,YMMWORD[((-24+160-128))+rcx]
+	vpaddq	ymm2,ymm3,ymm13
+	vpmuludq	ymm0,ymm0,ymm11
+	vmovdqu	ymm13,YMMWORD[((-24+192-128))+rcx]
+	vpaddq	ymm3,ymm4,ymm0
+	vpmuludq	ymm12,ymm12,ymm11
+	vmovdqu	ymm0,YMMWORD[((-24+224-128))+rcx]
+	vpaddq	ymm4,ymm5,ymm12
+	vpmuludq	ymm13,ymm13,ymm11
+	vmovdqu	ymm12,YMMWORD[((-24+256-128))+rcx]
+	vpaddq	ymm5,ymm6,ymm13
+	vpmuludq	ymm0,ymm0,ymm11
+	vmovdqu	ymm13,YMMWORD[((-24+288-128))+rcx]
+	mov	r9,r12
+	vpaddq	ymm6,ymm7,ymm0
+	vpmuludq	ymm12,ymm12,ymm11
+	add	r9,QWORD[rsp]
+	vpaddq	ymm7,ymm8,ymm12
+	vpmuludq	ymm13,ymm13,ymm11
+	vmovq	xmm12,r12
+	vpaddq	ymm8,ymm9,ymm13
+
+	dec	r14d
+	jnz	NEAR $L$oop_mul_1024
+	vpermq	ymm15,ymm15,0
+	vpaddq	ymm0,ymm12,YMMWORD[rsp]
+
+	vpsrlq	ymm12,ymm0,29
+	vpand	ymm0,ymm0,ymm15
+	vpsrlq	ymm13,ymm1,29
+	vpand	ymm1,ymm1,ymm15
+	vpsrlq	ymm10,ymm2,29
+	vpermq	ymm12,ymm12,0x93
+	vpand	ymm2,ymm2,ymm15
+	vpsrlq	ymm11,ymm3,29
+	vpermq	ymm13,ymm13,0x93
+	vpand	ymm3,ymm3,ymm15
+
+	vpblendd	ymm9,ymm12,ymm14,3
+	vpermq	ymm10,ymm10,0x93
+	vpblendd	ymm12,ymm13,ymm12,3
+	vpermq	ymm11,ymm11,0x93
+	vpaddq	ymm0,ymm0,ymm9
+	vpblendd	ymm13,ymm10,ymm13,3
+	vpaddq	ymm1,ymm1,ymm12
+	vpblendd	ymm10,ymm11,ymm10,3
+	vpaddq	ymm2,ymm2,ymm13
+	vpblendd	ymm11,ymm14,ymm11,3
+	vpaddq	ymm3,ymm3,ymm10
+	vpaddq	ymm4,ymm4,ymm11
+
+	vpsrlq	ymm12,ymm0,29
+	vpand	ymm0,ymm0,ymm15
+	vpsrlq	ymm13,ymm1,29
+	vpand	ymm1,ymm1,ymm15
+	vpsrlq	ymm10,ymm2,29
+	vpermq	ymm12,ymm12,0x93
+	vpand	ymm2,ymm2,ymm15
+	vpsrlq	ymm11,ymm3,29
+	vpermq	ymm13,ymm13,0x93
+	vpand	ymm3,ymm3,ymm15
+	vpermq	ymm10,ymm10,0x93
+
+	vpblendd	ymm9,ymm12,ymm14,3
+	vpermq	ymm11,ymm11,0x93
+	vpblendd	ymm12,ymm13,ymm12,3
+	vpaddq	ymm0,ymm0,ymm9
+	vpblendd	ymm13,ymm10,ymm13,3
+	vpaddq	ymm1,ymm1,ymm12
+	vpblendd	ymm10,ymm11,ymm10,3
+	vpaddq	ymm2,ymm2,ymm13
+	vpblendd	ymm11,ymm14,ymm11,3
+	vpaddq	ymm3,ymm3,ymm10
+	vpaddq	ymm4,ymm4,ymm11
+
+	vmovdqu	YMMWORD[(0-128)+rdi],ymm0
+	vmovdqu	YMMWORD[(32-128)+rdi],ymm1
+	vmovdqu	YMMWORD[(64-128)+rdi],ymm2
+	vmovdqu	YMMWORD[(96-128)+rdi],ymm3
+	vpsrlq	ymm12,ymm4,29
+	vpand	ymm4,ymm4,ymm15
+	vpsrlq	ymm13,ymm5,29
+	vpand	ymm5,ymm5,ymm15
+	vpsrlq	ymm10,ymm6,29
+	vpermq	ymm12,ymm12,0x93
+	vpand	ymm6,ymm6,ymm15
+	vpsrlq	ymm11,ymm7,29
+	vpermq	ymm13,ymm13,0x93
+	vpand	ymm7,ymm7,ymm15
+	vpsrlq	ymm0,ymm8,29
+	vpermq	ymm10,ymm10,0x93
+	vpand	ymm8,ymm8,ymm15
+	vpermq	ymm11,ymm11,0x93
+
+	vpblendd	ymm9,ymm12,ymm14,3
+	vpermq	ymm0,ymm0,0x93
+	vpblendd	ymm12,ymm13,ymm12,3
+	vpaddq	ymm4,ymm4,ymm9
+	vpblendd	ymm13,ymm10,ymm13,3
+	vpaddq	ymm5,ymm5,ymm12
+	vpblendd	ymm10,ymm11,ymm10,3
+	vpaddq	ymm6,ymm6,ymm13
+	vpblendd	ymm11,ymm0,ymm11,3
+	vpaddq	ymm7,ymm7,ymm10
+	vpaddq	ymm8,ymm8,ymm11
+
+	vpsrlq	ymm12,ymm4,29
+	vpand	ymm4,ymm4,ymm15
+	vpsrlq	ymm13,ymm5,29
+	vpand	ymm5,ymm5,ymm15
+	vpsrlq	ymm10,ymm6,29
+	vpermq	ymm12,ymm12,0x93
+	vpand	ymm6,ymm6,ymm15
+	vpsrlq	ymm11,ymm7,29
+	vpermq	ymm13,ymm13,0x93
+	vpand	ymm7,ymm7,ymm15
+	vpsrlq	ymm0,ymm8,29
+	vpermq	ymm10,ymm10,0x93
+	vpand	ymm8,ymm8,ymm15
+	vpermq	ymm11,ymm11,0x93
+
+	vpblendd	ymm9,ymm12,ymm14,3
+	vpermq	ymm0,ymm0,0x93
+	vpblendd	ymm12,ymm13,ymm12,3
+	vpaddq	ymm4,ymm4,ymm9
+	vpblendd	ymm13,ymm10,ymm13,3
+	vpaddq	ymm5,ymm5,ymm12
+	vpblendd	ymm10,ymm11,ymm10,3
+	vpaddq	ymm6,ymm6,ymm13
+	vpblendd	ymm11,ymm0,ymm11,3
+	vpaddq	ymm7,ymm7,ymm10
+	vpaddq	ymm8,ymm8,ymm11
+
+	vmovdqu	YMMWORD[(128-128)+rdi],ymm4
+	vmovdqu	YMMWORD[(160-128)+rdi],ymm5
+	vmovdqu	YMMWORD[(192-128)+rdi],ymm6
+	vmovdqu	YMMWORD[(224-128)+rdi],ymm7
+	vmovdqu	YMMWORD[(256-128)+rdi],ymm8
+	vzeroupper
+
+	mov	rax,rbp
+
+$L$mul_1024_in_tail:
+	movaps	xmm6,XMMWORD[((-216))+rax]
+	movaps	xmm7,XMMWORD[((-200))+rax]
+	movaps	xmm8,XMMWORD[((-184))+rax]
+	movaps	xmm9,XMMWORD[((-168))+rax]
+	movaps	xmm10,XMMWORD[((-152))+rax]
+	movaps	xmm11,XMMWORD[((-136))+rax]
+	movaps	xmm12,XMMWORD[((-120))+rax]
+	movaps	xmm13,XMMWORD[((-104))+rax]
+	movaps	xmm14,XMMWORD[((-88))+rax]
+	movaps	xmm15,XMMWORD[((-72))+rax]
+	mov	r15,QWORD[((-48))+rax]
+
+	mov	r14,QWORD[((-40))+rax]
+
+	mov	r13,QWORD[((-32))+rax]
+
+	mov	r12,QWORD[((-24))+rax]
+
+	mov	rbp,QWORD[((-16))+rax]
+
+	mov	rbx,QWORD[((-8))+rax]
+
+	lea	rsp,[rax]
+
+$L$mul_1024_epilogue:
+	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD[16+rsp]
+	DB	0F3h,0C3h		;repret
+
+$L$SEH_end_rsaz_1024_mul_avx2:
+global	rsaz_1024_red2norm_avx2
+
+ALIGN	32
+rsaz_1024_red2norm_avx2:
+	sub	rdx,-128
+	xor	rax,rax
+	mov	r8,QWORD[((-128))+rdx]
+	mov	r9,QWORD[((-120))+rdx]
+	mov	r10,QWORD[((-112))+rdx]
+	shl	r8,0
+	shl	r9,29
+	mov	r11,r10
+	shl	r10,58
+	shr	r11,6
+	add	rax,r8
+	add	rax,r9
+	add	rax,r10
+	adc	r11,0
+	mov	QWORD[rcx],rax
+	mov	rax,r11
+	mov	r8,QWORD[((-104))+rdx]
+	mov	r9,QWORD[((-96))+rdx]
+	shl	r8,23
+	mov	r10,r9
+	shl	r9,52
+	shr	r10,12
+	add	rax,r8
+	add	rax,r9
+	adc	r10,0
+	mov	QWORD[8+rcx],rax
+	mov	rax,r10
+	mov	r11,QWORD[((-88))+rdx]
+	mov	r8,QWORD[((-80))+rdx]
+	shl	r11,17
+	mov	r9,r8
+	shl	r8,46
+	shr	r9,18
+	add	rax,r11
+	add	rax,r8
+	adc	r9,0
+	mov	QWORD[16+rcx],rax
+	mov	rax,r9
+	mov	r10,QWORD[((-72))+rdx]
+	mov	r11,QWORD[((-64))+rdx]
+	shl	r10,11
+	mov	r8,r11
+	shl	r11,40
+	shr	r8,24
+	add	rax,r10
+	add	rax,r11
+	adc	r8,0
+	mov	QWORD[24+rcx],rax
+	mov	rax,r8
+	mov	r9,QWORD[((-56))+rdx]
+	mov	r10,QWORD[((-48))+rdx]
+	mov	r11,QWORD[((-40))+rdx]
+	shl	r9,5
+	shl	r10,34
+	mov	r8,r11
+	shl	r11,63
+	shr	r8,1
+	add	rax,r9
+	add	rax,r10
+	add	rax,r11
+	adc	r8,0
+	mov	QWORD[32+rcx],rax
+	mov	rax,r8
+	mov	r9,QWORD[((-32))+rdx]
+	mov	r10,QWORD[((-24))+rdx]
+	shl	r9,28
+	mov	r11,r10
+	shl	r10,57
+	shr	r11,7
+	add	rax,r9
+	add	rax,r10
+	adc	r11,0
+	mov	QWORD[40+rcx],rax
+	mov	rax,r11
+	mov	r8,QWORD[((-16))+rdx]
+	mov	r9,QWORD[((-8))+rdx]
+	shl	r8,22
+	mov	r10,r9
+	shl	r9,51
+	shr	r10,13
+	add	rax,r8
+	add	rax,r9
+	adc	r10,0
+	mov	QWORD[48+rcx],rax
+	mov	rax,r10
+	mov	r11,QWORD[rdx]
+	mov	r8,QWORD[8+rdx]
+	shl	r11,16
+	mov	r9,r8
+	shl	r8,45
+	shr	r9,19
+	add	rax,r11
+	add	rax,r8
+	adc	r9,0
+	mov	QWORD[56+rcx],rax
+	mov	rax,r9
+	mov	r10,QWORD[16+rdx]
+	mov	r11,QWORD[24+rdx]
+	shl	r10,10
+	mov	r8,r11
+	shl	r11,39
+	shr	r8,25
+	add	rax,r10
+	add	rax,r11
+	adc	r8,0
+	mov	QWORD[64+rcx],rax
+	mov	rax,r8
+	mov	r9,QWORD[32+rdx]
+	mov	r10,QWORD[40+rdx]
+	mov	r11,QWORD[48+rdx]
+	shl	r9,4
+	shl	r10,33
+	mov	r8,r11
+	shl	r11,62
+	shr	r8,2
+	add	rax,r9
+	add	rax,r10
+	add	rax,r11
+	adc	r8,0
+	mov	QWORD[72+rcx],rax
+	mov	rax,r8
+	mov	r9,QWORD[56+rdx]
+	mov	r10,QWORD[64+rdx]
+	shl	r9,27
+	mov	r11,r10
+	shl	r10,56
+	shr	r11,8
+	add	rax,r9
+	add	rax,r10
+	adc	r11,0
+	mov	QWORD[80+rcx],rax
+	mov	rax,r11
+	mov	r8,QWORD[72+rdx]
+	mov	r9,QWORD[80+rdx]
+	shl	r8,21
+	mov	r10,r9
+	shl	r9,50
+	shr	r10,14
+	add	rax,r8
+	add	rax,r9
+	adc	r10,0
+	mov	QWORD[88+rcx],rax
+	mov	rax,r10
+	mov	r11,QWORD[88+rdx]
+	mov	r8,QWORD[96+rdx]
+	shl	r11,15
+	mov	r9,r8
+	shl	r8,44
+	shr	r9,20
+	add	rax,r11
+	add	rax,r8
+	adc	r9,0
+	mov	QWORD[96+rcx],rax
+	mov	rax,r9
+	mov	r10,QWORD[104+rdx]
+	mov	r11,QWORD[112+rdx]
+	shl	r10,9
+	mov	r8,r11
+	shl	r11,38
+	shr	r8,26
+	add	rax,r10
+	add	rax,r11
+	adc	r8,0
+	mov	QWORD[104+rcx],rax
+	mov	rax,r8
+	mov	r9,QWORD[120+rdx]
+	mov	r10,QWORD[128+rdx]
+	mov	r11,QWORD[136+rdx]
+	shl	r9,3
+	shl	r10,32
+	mov	r8,r11
+	shl	r11,61
+	shr	r8,3
+	add	rax,r9
+	add	rax,r10
+	add	rax,r11
+	adc	r8,0
+	mov	QWORD[112+rcx],rax
+	mov	rax,r8
+	mov	r9,QWORD[144+rdx]
+	mov	r10,QWORD[152+rdx]
+	shl	r9,26
+	mov	r11,r10
+	shl	r10,55
+	shr	r11,9
+	add	rax,r9
+	add	rax,r10
+	adc	r11,0
+	mov	QWORD[120+rcx],rax
+	mov	rax,r11
 	DB	0F3h,0C3h		;repret
 
 
-global	rsaz_1024_sqr_avx2
-global	rsaz_1024_mul_avx2
 global	rsaz_1024_norm2red_avx2
-global	rsaz_1024_red2norm_avx2
+
+ALIGN	32
+rsaz_1024_norm2red_avx2:
+	sub	rcx,-128
+	mov	r8,QWORD[rdx]
+	mov	eax,0x1fffffff
+	mov	r9,QWORD[8+rdx]
+	mov	r11,r8
+	shr	r11,0
+	and	r11,rax
+	mov	QWORD[((-128))+rcx],r11
+	mov	r10,r8
+	shr	r10,29
+	and	r10,rax
+	mov	QWORD[((-120))+rcx],r10
+	shrd	r8,r9,58
+	and	r8,rax
+	mov	QWORD[((-112))+rcx],r8
+	mov	r10,QWORD[16+rdx]
+	mov	r8,r9
+	shr	r8,23
+	and	r8,rax
+	mov	QWORD[((-104))+rcx],r8
+	shrd	r9,r10,52
+	and	r9,rax
+	mov	QWORD[((-96))+rcx],r9
+	mov	r11,QWORD[24+rdx]
+	mov	r9,r10
+	shr	r9,17
+	and	r9,rax
+	mov	QWORD[((-88))+rcx],r9
+	shrd	r10,r11,46
+	and	r10,rax
+	mov	QWORD[((-80))+rcx],r10
+	mov	r8,QWORD[32+rdx]
+	mov	r10,r11
+	shr	r10,11
+	and	r10,rax
+	mov	QWORD[((-72))+rcx],r10
+	shrd	r11,r8,40
+	and	r11,rax
+	mov	QWORD[((-64))+rcx],r11
+	mov	r9,QWORD[40+rdx]
+	mov	r11,r8
+	shr	r11,5
+	and	r11,rax
+	mov	QWORD[((-56))+rcx],r11
+	mov	r10,r8
+	shr	r10,34
+	and	r10,rax
+	mov	QWORD[((-48))+rcx],r10
+	shrd	r8,r9,63
+	and	r8,rax
+	mov	QWORD[((-40))+rcx],r8
+	mov	r10,QWORD[48+rdx]
+	mov	r8,r9
+	shr	r8,28
+	and	r8,rax
+	mov	QWORD[((-32))+rcx],r8
+	shrd	r9,r10,57
+	and	r9,rax
+	mov	QWORD[((-24))+rcx],r9
+	mov	r11,QWORD[56+rdx]
+	mov	r9,r10
+	shr	r9,22
+	and	r9,rax
+	mov	QWORD[((-16))+rcx],r9
+	shrd	r10,r11,51
+	and	r10,rax
+	mov	QWORD[((-8))+rcx],r10
+	mov	r8,QWORD[64+rdx]
+	mov	r10,r11
+	shr	r10,16
+	and	r10,rax
+	mov	QWORD[rcx],r10
+	shrd	r11,r8,45
+	and	r11,rax
+	mov	QWORD[8+rcx],r11
+	mov	r9,QWORD[72+rdx]
+	mov	r11,r8
+	shr	r11,10
+	and	r11,rax
+	mov	QWORD[16+rcx],r11
+	shrd	r8,r9,39
+	and	r8,rax
+	mov	QWORD[24+rcx],r8
+	mov	r10,QWORD[80+rdx]
+	mov	r8,r9
+	shr	r8,4
+	and	r8,rax
+	mov	QWORD[32+rcx],r8
+	mov	r11,r9
+	shr	r11,33
+	and	r11,rax
+	mov	QWORD[40+rcx],r11
+	shrd	r9,r10,62
+	and	r9,rax
+	mov	QWORD[48+rcx],r9
+	mov	r11,QWORD[88+rdx]
+	mov	r9,r10
+	shr	r9,27
+	and	r9,rax
+	mov	QWORD[56+rcx],r9
+	shrd	r10,r11,56
+	and	r10,rax
+	mov	QWORD[64+rcx],r10
+	mov	r8,QWORD[96+rdx]
+	mov	r10,r11
+	shr	r10,21
+	and	r10,rax
+	mov	QWORD[72+rcx],r10
+	shrd	r11,r8,50
+	and	r11,rax
+	mov	QWORD[80+rcx],r11
+	mov	r9,QWORD[104+rdx]
+	mov	r11,r8
+	shr	r11,15
+	and	r11,rax
+	mov	QWORD[88+rcx],r11
+	shrd	r8,r9,44
+	and	r8,rax
+	mov	QWORD[96+rcx],r8
+	mov	r10,QWORD[112+rdx]
+	mov	r8,r9
+	shr	r8,9
+	and	r8,rax
+	mov	QWORD[104+rcx],r8
+	shrd	r9,r10,38
+	and	r9,rax
+	mov	QWORD[112+rcx],r9
+	mov	r11,QWORD[120+rdx]
+	mov	r9,r10
+	shr	r9,3
+	and	r9,rax
+	mov	QWORD[120+rcx],r9
+	mov	r8,r10
+	shr	r8,32
+	and	r8,rax
+	mov	QWORD[128+rcx],r8
+	shrd	r10,r11,61
+	and	r10,rax
+	mov	QWORD[136+rcx],r10
+	xor	r8,r8
+	mov	r10,r11
+	shr	r10,26
+	and	r10,rax
+	mov	QWORD[144+rcx],r10
+	shrd	r11,r8,55
+	and	r11,rax
+	mov	QWORD[152+rcx],r11
+	mov	QWORD[160+rcx],r8
+	mov	QWORD[168+rcx],r8
+	mov	QWORD[176+rcx],r8
+	mov	QWORD[184+rcx],r8
+	DB	0F3h,0C3h		;repret
+
 global	rsaz_1024_scatter5_avx2
+
+ALIGN	32
+rsaz_1024_scatter5_avx2:
+	vzeroupper
+	vmovdqu	ymm5,YMMWORD[$L$scatter_permd]
+	shl	r8d,4
+	lea	rcx,[r8*1+rcx]
+	mov	eax,9
+	jmp	NEAR $L$oop_scatter_1024
+
+ALIGN	32
+$L$oop_scatter_1024:
+	vmovdqu	ymm0,YMMWORD[rdx]
+	lea	rdx,[32+rdx]
+	vpermd	ymm0,ymm5,ymm0
+	vmovdqu	XMMWORD[rcx],xmm0
+	lea	rcx,[512+rcx]
+	dec	eax
+	jnz	NEAR $L$oop_scatter_1024
+
+	vzeroupper
+	DB	0F3h,0C3h		;repret
+
+
 global	rsaz_1024_gather5_avx2
 
-rsaz_1024_sqr_avx2:
-rsaz_1024_mul_avx2:
-rsaz_1024_norm2red_avx2:
-rsaz_1024_red2norm_avx2:
-rsaz_1024_scatter5_avx2:
+ALIGN	32
 rsaz_1024_gather5_avx2:
-DB	0x0f,0x0b
+
+	vzeroupper
+	mov	r11,rsp
+
+	lea	rax,[((-136))+rsp]
+$L$SEH_begin_rsaz_1024_gather5:
+
+DB	0x48,0x8d,0x60,0xe0
+DB	0xc5,0xf8,0x29,0x70,0xe0
+DB	0xc5,0xf8,0x29,0x78,0xf0
+DB	0xc5,0x78,0x29,0x40,0x00
+DB	0xc5,0x78,0x29,0x48,0x10
+DB	0xc5,0x78,0x29,0x50,0x20
+DB	0xc5,0x78,0x29,0x58,0x30
+DB	0xc5,0x78,0x29,0x60,0x40
+DB	0xc5,0x78,0x29,0x68,0x50
+DB	0xc5,0x78,0x29,0x70,0x60
+DB	0xc5,0x78,0x29,0x78,0x70
+	lea	rsp,[((-256))+rsp]
+	and	rsp,-32
+	lea	r10,[$L$inc]
+	lea	rax,[((-128))+rsp]
+
+	vmovd	xmm4,r8d
+	vmovdqa	ymm0,YMMWORD[r10]
+	vmovdqa	ymm1,YMMWORD[32+r10]
+	vmovdqa	ymm5,YMMWORD[64+r10]
+	vpbroadcastd	ymm4,xmm4
+
+	vpaddd	ymm2,ymm0,ymm5
+	vpcmpeqd	ymm0,ymm0,ymm4
+	vpaddd	ymm3,ymm1,ymm5
+	vpcmpeqd	ymm1,ymm1,ymm4
+	vmovdqa	YMMWORD[(0+128)+rax],ymm0
+	vpaddd	ymm0,ymm2,ymm5
+	vpcmpeqd	ymm2,ymm2,ymm4
+	vmovdqa	YMMWORD[(32+128)+rax],ymm1
+	vpaddd	ymm1,ymm3,ymm5
+	vpcmpeqd	ymm3,ymm3,ymm4
+	vmovdqa	YMMWORD[(64+128)+rax],ymm2
+	vpaddd	ymm2,ymm0,ymm5
+	vpcmpeqd	ymm0,ymm0,ymm4
+	vmovdqa	YMMWORD[(96+128)+rax],ymm3
+	vpaddd	ymm3,ymm1,ymm5
+	vpcmpeqd	ymm1,ymm1,ymm4
+	vmovdqa	YMMWORD[(128+128)+rax],ymm0
+	vpaddd	ymm8,ymm2,ymm5
+	vpcmpeqd	ymm2,ymm2,ymm4
+	vmovdqa	YMMWORD[(160+128)+rax],ymm1
+	vpaddd	ymm9,ymm3,ymm5
+	vpcmpeqd	ymm3,ymm3,ymm4
+	vmovdqa	YMMWORD[(192+128)+rax],ymm2
+	vpaddd	ymm10,ymm8,ymm5
+	vpcmpeqd	ymm8,ymm8,ymm4
+	vmovdqa	YMMWORD[(224+128)+rax],ymm3
+	vpaddd	ymm11,ymm9,ymm5
+	vpcmpeqd	ymm9,ymm9,ymm4
+	vpaddd	ymm12,ymm10,ymm5
+	vpcmpeqd	ymm10,ymm10,ymm4
+	vpaddd	ymm13,ymm11,ymm5
+	vpcmpeqd	ymm11,ymm11,ymm4
+	vpaddd	ymm14,ymm12,ymm5
+	vpcmpeqd	ymm12,ymm12,ymm4
+	vpaddd	ymm15,ymm13,ymm5
+	vpcmpeqd	ymm13,ymm13,ymm4
+	vpcmpeqd	ymm14,ymm14,ymm4
+	vpcmpeqd	ymm15,ymm15,ymm4
+
+	vmovdqa	ymm7,YMMWORD[((-32))+r10]
+	lea	rdx,[128+rdx]
+	mov	r8d,9
+
+$L$oop_gather_1024:
+	vmovdqa	ymm0,YMMWORD[((0-128))+rdx]
+	vmovdqa	ymm1,YMMWORD[((32-128))+rdx]
+	vmovdqa	ymm2,YMMWORD[((64-128))+rdx]
+	vmovdqa	ymm3,YMMWORD[((96-128))+rdx]
+	vpand	ymm0,ymm0,YMMWORD[((0+128))+rax]
+	vpand	ymm1,ymm1,YMMWORD[((32+128))+rax]
+	vpand	ymm2,ymm2,YMMWORD[((64+128))+rax]
+	vpor	ymm4,ymm1,ymm0
+	vpand	ymm3,ymm3,YMMWORD[((96+128))+rax]
+	vmovdqa	ymm0,YMMWORD[((128-128))+rdx]
+	vmovdqa	ymm1,YMMWORD[((160-128))+rdx]
+	vpor	ymm5,ymm3,ymm2
+	vmovdqa	ymm2,YMMWORD[((192-128))+rdx]
+	vmovdqa	ymm3,YMMWORD[((224-128))+rdx]
+	vpand	ymm0,ymm0,YMMWORD[((128+128))+rax]
+	vpand	ymm1,ymm1,YMMWORD[((160+128))+rax]
+	vpand	ymm2,ymm2,YMMWORD[((192+128))+rax]
+	vpor	ymm4,ymm4,ymm0
+	vpand	ymm3,ymm3,YMMWORD[((224+128))+rax]
+	vpand	ymm0,ymm8,YMMWORD[((256-128))+rdx]
+	vpor	ymm5,ymm5,ymm1
+	vpand	ymm1,ymm9,YMMWORD[((288-128))+rdx]
+	vpor	ymm4,ymm4,ymm2
+	vpand	ymm2,ymm10,YMMWORD[((320-128))+rdx]
+	vpor	ymm5,ymm5,ymm3
+	vpand	ymm3,ymm11,YMMWORD[((352-128))+rdx]
+	vpor	ymm4,ymm4,ymm0
+	vpand	ymm0,ymm12,YMMWORD[((384-128))+rdx]
+	vpor	ymm5,ymm5,ymm1
+	vpand	ymm1,ymm13,YMMWORD[((416-128))+rdx]
+	vpor	ymm4,ymm4,ymm2
+	vpand	ymm2,ymm14,YMMWORD[((448-128))+rdx]
+	vpor	ymm5,ymm5,ymm3
+	vpand	ymm3,ymm15,YMMWORD[((480-128))+rdx]
+	lea	rdx,[512+rdx]
+	vpor	ymm4,ymm4,ymm0
+	vpor	ymm5,ymm5,ymm1
+	vpor	ymm4,ymm4,ymm2
+	vpor	ymm5,ymm5,ymm3
+
+	vpor	ymm4,ymm4,ymm5
+	vextracti128	xmm5,ymm4,1
+	vpor	xmm5,xmm5,xmm4
+	vpermd	ymm5,ymm7,ymm5
+	vmovdqu	YMMWORD[rcx],ymm5
+	lea	rcx,[32+rcx]
+	dec	r8d
+	jnz	NEAR $L$oop_gather_1024
+
+	vpxor	ymm0,ymm0,ymm0
+	vmovdqu	YMMWORD[rcx],ymm0
+	vzeroupper
+	movaps	xmm6,XMMWORD[((-168))+r11]
+	movaps	xmm7,XMMWORD[((-152))+r11]
+	movaps	xmm8,XMMWORD[((-136))+r11]
+	movaps	xmm9,XMMWORD[((-120))+r11]
+	movaps	xmm10,XMMWORD[((-104))+r11]
+	movaps	xmm11,XMMWORD[((-88))+r11]
+	movaps	xmm12,XMMWORD[((-72))+r11]
+	movaps	xmm13,XMMWORD[((-56))+r11]
+	movaps	xmm14,XMMWORD[((-40))+r11]
+	movaps	xmm15,XMMWORD[((-24))+r11]
+	lea	rsp,[r11]
+
 	DB	0F3h,0C3h		;repret
 
+$L$SEH_end_rsaz_1024_gather5:
+
+EXTERN	OPENSSL_ia32cap_P
+global	rsaz_avx2_eligible
+
+ALIGN	32
+rsaz_avx2_eligible:
+	mov	eax,DWORD[((OPENSSL_ia32cap_P+8))]
+	mov	ecx,524544
+	mov	edx,0
+	and	ecx,eax
+	cmp	ecx,524544
+	cmove	eax,edx
+	and	eax,32
+	shr	eax,5
+	DB	0F3h,0C3h		;repret
+
+
+ALIGN	64
+$L$and_mask:
+	DQ	0x1fffffff,0x1fffffff,0x1fffffff,-1
+$L$scatter_permd:
+	DD	0,2,4,6,7,7,7,7
+$L$gather_permd:
+	DD	0,7,1,7,2,7,3,7
+$L$inc:
+	DD	0,0,0,0,1,1,1,1
+	DD	2,2,2,2,3,3,3,3
+	DD	4,4,4,4,4,4,4,4
+ALIGN	64
+EXTERN	__imp_RtlVirtualUnwind
+
+ALIGN	16
+rsaz_se_handler:
+	push	rsi
+	push	rdi
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	pushfq
+	sub	rsp,64
+
+	mov	rax,QWORD[120+r8]
+	mov	rbx,QWORD[248+r8]
+
+	mov	rsi,QWORD[8+r9]
+	mov	r11,QWORD[56+r9]
+
+	mov	r10d,DWORD[r11]
+	lea	r10,[r10*1+rsi]
+	cmp	rbx,r10
+	jb	NEAR $L$common_seh_tail
+
+	mov	r10d,DWORD[4+r11]
+	lea	r10,[r10*1+rsi]
+	cmp	rbx,r10
+	jae	NEAR $L$common_seh_tail
+
+	mov	rbp,QWORD[160+r8]
+
+	mov	r10d,DWORD[8+r11]
+	lea	r10,[r10*1+rsi]
+	cmp	rbx,r10
+	cmovc	rax,rbp
+
+	mov	r15,QWORD[((-48))+rax]
+	mov	r14,QWORD[((-40))+rax]
+	mov	r13,QWORD[((-32))+rax]
+	mov	r12,QWORD[((-24))+rax]
+	mov	rbp,QWORD[((-16))+rax]
+	mov	rbx,QWORD[((-8))+rax]
+	mov	QWORD[240+r8],r15
+	mov	QWORD[232+r8],r14
+	mov	QWORD[224+r8],r13
+	mov	QWORD[216+r8],r12
+	mov	QWORD[160+r8],rbp
+	mov	QWORD[144+r8],rbx
+
+	lea	rsi,[((-216))+rax]
+	lea	rdi,[512+r8]
+	mov	ecx,20
+	DD	0xa548f3fc
+
+$L$common_seh_tail:
+	mov	rdi,QWORD[8+rax]
+	mov	rsi,QWORD[16+rax]
+	mov	QWORD[152+r8],rax
+	mov	QWORD[168+r8],rsi
+	mov	QWORD[176+r8],rdi
+
+	mov	rdi,QWORD[40+r9]
+	mov	rsi,r8
+	mov	ecx,154
+	DD	0xa548f3fc
+
+	mov	rsi,r9
+	xor	rcx,rcx
+	mov	rdx,QWORD[8+rsi]
+	mov	r8,QWORD[rsi]
+	mov	r9,QWORD[16+rsi]
+	mov	r10,QWORD[40+rsi]
+	lea	r11,[56+rsi]
+	lea	r12,[24+rsi]
+	mov	QWORD[32+rsp],r10
+	mov	QWORD[40+rsp],r11
+	mov	QWORD[48+rsp],r12
+	mov	QWORD[56+rsp],rcx
+	call	QWORD[__imp_RtlVirtualUnwind]
+
+	mov	eax,1
+	add	rsp,64
+	popfq
+	pop	r15
+	pop	r14
+	pop	r13
+	pop	r12
+	pop	rbp
+	pop	rbx
+	pop	rdi
+	pop	rsi
+	DB	0F3h,0C3h		;repret
+
+
+section	.pdata rdata align=4
+ALIGN	4
+	DD	$L$SEH_begin_rsaz_1024_sqr_avx2 wrt ..imagebase
+	DD	$L$SEH_end_rsaz_1024_sqr_avx2 wrt ..imagebase
+	DD	$L$SEH_info_rsaz_1024_sqr_avx2 wrt ..imagebase
+
+	DD	$L$SEH_begin_rsaz_1024_mul_avx2 wrt ..imagebase
+	DD	$L$SEH_end_rsaz_1024_mul_avx2 wrt ..imagebase
+	DD	$L$SEH_info_rsaz_1024_mul_avx2 wrt ..imagebase
+
+	DD	$L$SEH_begin_rsaz_1024_gather5 wrt ..imagebase
+	DD	$L$SEH_end_rsaz_1024_gather5 wrt ..imagebase
+	DD	$L$SEH_info_rsaz_1024_gather5 wrt ..imagebase
+section	.xdata rdata align=8
+ALIGN	8
+$L$SEH_info_rsaz_1024_sqr_avx2:
+DB	9,0,0,0
+	DD	rsaz_se_handler wrt ..imagebase
+	DD	$L$sqr_1024_body wrt ..imagebase,$L$sqr_1024_epilogue wrt ..imagebase,$L$sqr_1024_in_tail wrt ..imagebase
+	DD	0
+$L$SEH_info_rsaz_1024_mul_avx2:
+DB	9,0,0,0
+	DD	rsaz_se_handler wrt ..imagebase
+	DD	$L$mul_1024_body wrt ..imagebase,$L$mul_1024_epilogue wrt ..imagebase,$L$mul_1024_in_tail wrt ..imagebase
+	DD	0
+$L$SEH_info_rsaz_1024_gather5:
+DB	0x01,0x36,0x17,0x0b
+DB	0x36,0xf8,0x09,0x00
+DB	0x31,0xe8,0x08,0x00
+DB	0x2c,0xd8,0x07,0x00
+DB	0x27,0xc8,0x06,0x00
+DB	0x22,0xb8,0x05,0x00
+DB	0x1d,0xa8,0x04,0x00
+DB	0x18,0x98,0x03,0x00
+DB	0x13,0x88,0x02,0x00
+DB	0x0e,0x78,0x01,0x00
+DB	0x09,0x68,0x00,0x00
+DB	0x04,0x01,0x15,0x00
+DB	0x00,0xb3,0x00,0x00
diff --git a/win-x86_64/crypto/bn/rsaz-x86_64.asm b/win-x86_64/crypto/bn/rsaz-x86_64.asm
deleted file mode 100644
index 04d5e39..0000000
--- a/win-x86_64/crypto/bn/rsaz-x86_64.asm
+++ /dev/null
@@ -1,1320 +0,0 @@
-default	rel
-%define XMMWORD
-%define YMMWORD
-%define ZMMWORD
-section	.text code align=64
-
-
-EXTERN	OPENSSL_ia32cap_P
-
-global	rsaz_512_sqr
-
-ALIGN	32
-rsaz_512_sqr:
-	mov	QWORD[8+rsp],rdi	;WIN64 prologue
-	mov	QWORD[16+rsp],rsi
-	mov	rax,rsp
-$L$SEH_begin_rsaz_512_sqr:
-	mov	rdi,rcx
-	mov	rsi,rdx
-	mov	rdx,r8
-	mov	rcx,r9
-	mov	r8,QWORD[40+rsp]
-
-
-	push	rbx
-	push	rbp
-	push	r12
-	push	r13
-	push	r14
-	push	r15
-
-	sub	rsp,128+24
-$L$sqr_body:
-	mov	rbp,rdx
-	mov	rdx,QWORD[rsi]
-	mov	rax,QWORD[8+rsi]
-	mov	QWORD[128+rsp],rcx
-	jmp	NEAR $L$oop_sqr
-
-ALIGN	32
-$L$oop_sqr:
-	mov	DWORD[((128+8))+rsp],r8d
-
-	mov	rbx,rdx
-	mul	rdx
-	mov	r8,rax
-	mov	rax,QWORD[16+rsi]
-	mov	r9,rdx
-
-	mul	rbx
-	add	r9,rax
-	mov	rax,QWORD[24+rsi]
-	mov	r10,rdx
-	adc	r10,0
-
-	mul	rbx
-	add	r10,rax
-	mov	rax,QWORD[32+rsi]
-	mov	r11,rdx
-	adc	r11,0
-
-	mul	rbx
-	add	r11,rax
-	mov	rax,QWORD[40+rsi]
-	mov	r12,rdx
-	adc	r12,0
-
-	mul	rbx
-	add	r12,rax
-	mov	rax,QWORD[48+rsi]
-	mov	r13,rdx
-	adc	r13,0
-
-	mul	rbx
-	add	r13,rax
-	mov	rax,QWORD[56+rsi]
-	mov	r14,rdx
-	adc	r14,0
-
-	mul	rbx
-	add	r14,rax
-	mov	rax,rbx
-	mov	r15,rdx
-	adc	r15,0
-
-	add	r8,r8
-	mov	rcx,r9
-	adc	r9,r9
-
-	mul	rax
-	mov	QWORD[rsp],rax
-	add	r8,rdx
-	adc	r9,0
-
-	mov	QWORD[8+rsp],r8
-	shr	rcx,63
-
-
-	mov	r8,QWORD[8+rsi]
-	mov	rax,QWORD[16+rsi]
-	mul	r8
-	add	r10,rax
-	mov	rax,QWORD[24+rsi]
-	mov	rbx,rdx
-	adc	rbx,0
-
-	mul	r8
-	add	r11,rax
-	mov	rax,QWORD[32+rsi]
-	adc	rdx,0
-	add	r11,rbx
-	mov	rbx,rdx
-	adc	rbx,0
-
-	mul	r8
-	add	r12,rax
-	mov	rax,QWORD[40+rsi]
-	adc	rdx,0
-	add	r12,rbx
-	mov	rbx,rdx
-	adc	rbx,0
-
-	mul	r8
-	add	r13,rax
-	mov	rax,QWORD[48+rsi]
-	adc	rdx,0
-	add	r13,rbx
-	mov	rbx,rdx
-	adc	rbx,0
-
-	mul	r8
-	add	r14,rax
-	mov	rax,QWORD[56+rsi]
-	adc	rdx,0
-	add	r14,rbx
-	mov	rbx,rdx
-	adc	rbx,0
-
-	mul	r8
-	add	r15,rax
-	mov	rax,r8
-	adc	rdx,0
-	add	r15,rbx
-	mov	r8,rdx
-	mov	rdx,r10
-	adc	r8,0
-
-	add	rdx,rdx
-	lea	r10,[r10*2+rcx]
-	mov	rbx,r11
-	adc	r11,r11
-
-	mul	rax
-	add	r9,rax
-	adc	r10,rdx
-	adc	r11,0
-
-	mov	QWORD[16+rsp],r9
-	mov	QWORD[24+rsp],r10
-	shr	rbx,63
-
-
-	mov	r9,QWORD[16+rsi]
-	mov	rax,QWORD[24+rsi]
-	mul	r9
-	add	r12,rax
-	mov	rax,QWORD[32+rsi]
-	mov	rcx,rdx
-	adc	rcx,0
-
-	mul	r9
-	add	r13,rax
-	mov	rax,QWORD[40+rsi]
-	adc	rdx,0
-	add	r13,rcx
-	mov	rcx,rdx
-	adc	rcx,0
-
-	mul	r9
-	add	r14,rax
-	mov	rax,QWORD[48+rsi]
-	adc	rdx,0
-	add	r14,rcx
-	mov	rcx,rdx
-	adc	rcx,0
-
-	mul	r9
-	mov	r10,r12
-	lea	r12,[r12*2+rbx]
-	add	r15,rax
-	mov	rax,QWORD[56+rsi]
-	adc	rdx,0
-	add	r15,rcx
-	mov	rcx,rdx
-	adc	rcx,0
-
-	mul	r9
-	shr	r10,63
-	add	r8,rax
-	mov	rax,r9
-	adc	rdx,0
-	add	r8,rcx
-	mov	r9,rdx
-	adc	r9,0
-
-	mov	rcx,r13
-	lea	r13,[r13*2+r10]
-
-	mul	rax
-	add	r11,rax
-	adc	r12,rdx
-	adc	r13,0
-
-	mov	QWORD[32+rsp],r11
-	mov	QWORD[40+rsp],r12
-	shr	rcx,63
-
-
-	mov	r10,QWORD[24+rsi]
-	mov	rax,QWORD[32+rsi]
-	mul	r10
-	add	r14,rax
-	mov	rax,QWORD[40+rsi]
-	mov	rbx,rdx
-	adc	rbx,0
-
-	mul	r10
-	add	r15,rax
-	mov	rax,QWORD[48+rsi]
-	adc	rdx,0
-	add	r15,rbx
-	mov	rbx,rdx
-	adc	rbx,0
-
-	mul	r10
-	mov	r12,r14
-	lea	r14,[r14*2+rcx]
-	add	r8,rax
-	mov	rax,QWORD[56+rsi]
-	adc	rdx,0
-	add	r8,rbx
-	mov	rbx,rdx
-	adc	rbx,0
-
-	mul	r10
-	shr	r12,63
-	add	r9,rax
-	mov	rax,r10
-	adc	rdx,0
-	add	r9,rbx
-	mov	r10,rdx
-	adc	r10,0
-
-	mov	rbx,r15
-	lea	r15,[r15*2+r12]
-
-	mul	rax
-	add	r13,rax
-	adc	r14,rdx
-	adc	r15,0
-
-	mov	QWORD[48+rsp],r13
-	mov	QWORD[56+rsp],r14
-	shr	rbx,63
-
-
-	mov	r11,QWORD[32+rsi]
-	mov	rax,QWORD[40+rsi]
-	mul	r11
-	add	r8,rax
-	mov	rax,QWORD[48+rsi]
-	mov	rcx,rdx
-	adc	rcx,0
-
-	mul	r11
-	add	r9,rax
-	mov	rax,QWORD[56+rsi]
-	adc	rdx,0
-	mov	r12,r8
-	lea	r8,[r8*2+rbx]
-	add	r9,rcx
-	mov	rcx,rdx
-	adc	rcx,0
-
-	mul	r11
-	shr	r12,63
-	add	r10,rax
-	mov	rax,r11
-	adc	rdx,0
-	add	r10,rcx
-	mov	r11,rdx
-	adc	r11,0
-
-	mov	rcx,r9
-	lea	r9,[r9*2+r12]
-
-	mul	rax
-	add	r15,rax
-	adc	r8,rdx
-	adc	r9,0
-
-	mov	QWORD[64+rsp],r15
-	mov	QWORD[72+rsp],r8
-	shr	rcx,63
-
-
-	mov	r12,QWORD[40+rsi]
-	mov	rax,QWORD[48+rsi]
-	mul	r12
-	add	r10,rax
-	mov	rax,QWORD[56+rsi]
-	mov	rbx,rdx
-	adc	rbx,0
-
-	mul	r12
-	add	r11,rax
-	mov	rax,r12
-	mov	r15,r10
-	lea	r10,[r10*2+rcx]
-	adc	rdx,0
-	shr	r15,63
-	add	r11,rbx
-	mov	r12,rdx
-	adc	r12,0
-
-	mov	rbx,r11
-	lea	r11,[r11*2+r15]
-
-	mul	rax
-	add	r9,rax
-	adc	r10,rdx
-	adc	r11,0
-
-	mov	QWORD[80+rsp],r9
-	mov	QWORD[88+rsp],r10
-
-
-	mov	r13,QWORD[48+rsi]
-	mov	rax,QWORD[56+rsi]
-	mul	r13
-	add	r12,rax
-	mov	rax,r13
-	mov	r13,rdx
-	adc	r13,0
-
-	xor	r14,r14
-	shl	rbx,1
-	adc	r12,r12
-	adc	r13,r13
-	adc	r14,r14
-
-	mul	rax
-	add	r11,rax
-	adc	r12,rdx
-	adc	r13,0
-
-	mov	QWORD[96+rsp],r11
-	mov	QWORD[104+rsp],r12
-
-
-	mov	rax,QWORD[56+rsi]
-	mul	rax
-	add	r13,rax
-	adc	rdx,0
-
-	add	r14,rdx
-
-	mov	QWORD[112+rsp],r13
-	mov	QWORD[120+rsp],r14
-
-	mov	r8,QWORD[rsp]
-	mov	r9,QWORD[8+rsp]
-	mov	r10,QWORD[16+rsp]
-	mov	r11,QWORD[24+rsp]
-	mov	r12,QWORD[32+rsp]
-	mov	r13,QWORD[40+rsp]
-	mov	r14,QWORD[48+rsp]
-	mov	r15,QWORD[56+rsp]
-
-	call	__rsaz_512_reduce
-
-	add	r8,QWORD[64+rsp]
-	adc	r9,QWORD[72+rsp]
-	adc	r10,QWORD[80+rsp]
-	adc	r11,QWORD[88+rsp]
-	adc	r12,QWORD[96+rsp]
-	adc	r13,QWORD[104+rsp]
-	adc	r14,QWORD[112+rsp]
-	adc	r15,QWORD[120+rsp]
-	sbb	rcx,rcx
-
-	call	__rsaz_512_subtract
-
-	mov	rdx,r8
-	mov	rax,r9
-	mov	r8d,DWORD[((128+8))+rsp]
-	mov	rsi,rdi
-
-	dec	r8d
-	jnz	NEAR $L$oop_sqr
-
-	lea	rax,[((128+24+48))+rsp]
-	mov	r15,QWORD[((-48))+rax]
-	mov	r14,QWORD[((-40))+rax]
-	mov	r13,QWORD[((-32))+rax]
-	mov	r12,QWORD[((-24))+rax]
-	mov	rbp,QWORD[((-16))+rax]
-	mov	rbx,QWORD[((-8))+rax]
-	lea	rsp,[rax]
-$L$sqr_epilogue:
-	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
-	mov	rsi,QWORD[16+rsp]
-	DB	0F3h,0C3h		;repret
-$L$SEH_end_rsaz_512_sqr:
-global	rsaz_512_mul
-
-ALIGN	32
-rsaz_512_mul:
-	mov	QWORD[8+rsp],rdi	;WIN64 prologue
-	mov	QWORD[16+rsp],rsi
-	mov	rax,rsp
-$L$SEH_begin_rsaz_512_mul:
-	mov	rdi,rcx
-	mov	rsi,rdx
-	mov	rdx,r8
-	mov	rcx,r9
-	mov	r8,QWORD[40+rsp]
-
-
-	push	rbx
-	push	rbp
-	push	r12
-	push	r13
-	push	r14
-	push	r15
-
-	sub	rsp,128+24
-$L$mul_body:
-DB	102,72,15,110,199
-DB	102,72,15,110,201
-	mov	QWORD[128+rsp],r8
-	mov	rbx,QWORD[rdx]
-	mov	rbp,rdx
-	call	__rsaz_512_mul
-
-DB	102,72,15,126,199
-DB	102,72,15,126,205
-
-	mov	r8,QWORD[rsp]
-	mov	r9,QWORD[8+rsp]
-	mov	r10,QWORD[16+rsp]
-	mov	r11,QWORD[24+rsp]
-	mov	r12,QWORD[32+rsp]
-	mov	r13,QWORD[40+rsp]
-	mov	r14,QWORD[48+rsp]
-	mov	r15,QWORD[56+rsp]
-
-	call	__rsaz_512_reduce
-	add	r8,QWORD[64+rsp]
-	adc	r9,QWORD[72+rsp]
-	adc	r10,QWORD[80+rsp]
-	adc	r11,QWORD[88+rsp]
-	adc	r12,QWORD[96+rsp]
-	adc	r13,QWORD[104+rsp]
-	adc	r14,QWORD[112+rsp]
-	adc	r15,QWORD[120+rsp]
-	sbb	rcx,rcx
-
-	call	__rsaz_512_subtract
-
-	lea	rax,[((128+24+48))+rsp]
-	mov	r15,QWORD[((-48))+rax]
-	mov	r14,QWORD[((-40))+rax]
-	mov	r13,QWORD[((-32))+rax]
-	mov	r12,QWORD[((-24))+rax]
-	mov	rbp,QWORD[((-16))+rax]
-	mov	rbx,QWORD[((-8))+rax]
-	lea	rsp,[rax]
-$L$mul_epilogue:
-	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
-	mov	rsi,QWORD[16+rsp]
-	DB	0F3h,0C3h		;repret
-$L$SEH_end_rsaz_512_mul:
-global	rsaz_512_mul_gather4
-
-ALIGN	32
-rsaz_512_mul_gather4:
-	mov	QWORD[8+rsp],rdi	;WIN64 prologue
-	mov	QWORD[16+rsp],rsi
-	mov	rax,rsp
-$L$SEH_begin_rsaz_512_mul_gather4:
-	mov	rdi,rcx
-	mov	rsi,rdx
-	mov	rdx,r8
-	mov	rcx,r9
-	mov	r8,QWORD[40+rsp]
-	mov	r9,QWORD[48+rsp]
-
-
-	push	rbx
-	push	rbp
-	push	r12
-	push	r13
-	push	r14
-	push	r15
-
-	mov	r9d,r9d
-	sub	rsp,128+24
-$L$mul_gather4_body:
-	mov	eax,DWORD[64+r9*4+rdx]
-DB	102,72,15,110,199
-	mov	ebx,DWORD[r9*4+rdx]
-DB	102,72,15,110,201
-	mov	QWORD[128+rsp],r8
-
-	shl	rax,32
-	or	rbx,rax
-	mov	rax,QWORD[rsi]
-	mov	rcx,QWORD[8+rsi]
-	lea	rbp,[128+r9*4+rdx]
-	mul	rbx
-	mov	QWORD[rsp],rax
-	mov	rax,rcx
-	mov	r8,rdx
-
-	mul	rbx
-	movd	xmm4,DWORD[rbp]
-	add	r8,rax
-	mov	rax,QWORD[16+rsi]
-	mov	r9,rdx
-	adc	r9,0
-
-	mul	rbx
-	movd	xmm5,DWORD[64+rbp]
-	add	r9,rax
-	mov	rax,QWORD[24+rsi]
-	mov	r10,rdx
-	adc	r10,0
-
-	mul	rbx
-	pslldq	xmm5,4
-	add	r10,rax
-	mov	rax,QWORD[32+rsi]
-	mov	r11,rdx
-	adc	r11,0
-
-	mul	rbx
-	por	xmm4,xmm5
-	add	r11,rax
-	mov	rax,QWORD[40+rsi]
-	mov	r12,rdx
-	adc	r12,0
-
-	mul	rbx
-	add	r12,rax
-	mov	rax,QWORD[48+rsi]
-	mov	r13,rdx
-	adc	r13,0
-
-	mul	rbx
-	lea	rbp,[128+rbp]
-	add	r13,rax
-	mov	rax,QWORD[56+rsi]
-	mov	r14,rdx
-	adc	r14,0
-
-	mul	rbx
-DB	102,72,15,126,227
-	add	r14,rax
-	mov	rax,QWORD[rsi]
-	mov	r15,rdx
-	adc	r15,0
-
-	lea	rdi,[8+rsp]
-	mov	ecx,7
-	jmp	NEAR $L$oop_mul_gather
-
-ALIGN	32
-$L$oop_mul_gather:
-	mul	rbx
-	add	r8,rax
-	mov	rax,QWORD[8+rsi]
-	mov	QWORD[rdi],r8
-	mov	r8,rdx
-	adc	r8,0
-
-	mul	rbx
-	movd	xmm4,DWORD[rbp]
-	add	r9,rax
-	mov	rax,QWORD[16+rsi]
-	adc	rdx,0
-	add	r8,r9
-	mov	r9,rdx
-	adc	r9,0
-
-	mul	rbx
-	movd	xmm5,DWORD[64+rbp]
-	add	r10,rax
-	mov	rax,QWORD[24+rsi]
-	adc	rdx,0
-	add	r9,r10
-	mov	r10,rdx
-	adc	r10,0
-
-	mul	rbx
-	pslldq	xmm5,4
-	add	r11,rax
-	mov	rax,QWORD[32+rsi]
-	adc	rdx,0
-	add	r10,r11
-	mov	r11,rdx
-	adc	r11,0
-
-	mul	rbx
-	por	xmm4,xmm5
-	add	r12,rax
-	mov	rax,QWORD[40+rsi]
-	adc	rdx,0
-	add	r11,r12
-	mov	r12,rdx
-	adc	r12,0
-
-	mul	rbx
-	add	r13,rax
-	mov	rax,QWORD[48+rsi]
-	adc	rdx,0
-	add	r12,r13
-	mov	r13,rdx
-	adc	r13,0
-
-	mul	rbx
-	add	r14,rax
-	mov	rax,QWORD[56+rsi]
-	adc	rdx,0
-	add	r13,r14
-	mov	r14,rdx
-	adc	r14,0
-
-	mul	rbx
-DB	102,72,15,126,227
-	add	r15,rax
-	mov	rax,QWORD[rsi]
-	adc	rdx,0
-	add	r14,r15
-	mov	r15,rdx
-	adc	r15,0
-
-	lea	rbp,[128+rbp]
-	lea	rdi,[8+rdi]
-
-	dec	ecx
-	jnz	NEAR $L$oop_mul_gather
-
-	mov	QWORD[rdi],r8
-	mov	QWORD[8+rdi],r9
-	mov	QWORD[16+rdi],r10
-	mov	QWORD[24+rdi],r11
-	mov	QWORD[32+rdi],r12
-	mov	QWORD[40+rdi],r13
-	mov	QWORD[48+rdi],r14
-	mov	QWORD[56+rdi],r15
-
-DB	102,72,15,126,199
-DB	102,72,15,126,205
-
-	mov	r8,QWORD[rsp]
-	mov	r9,QWORD[8+rsp]
-	mov	r10,QWORD[16+rsp]
-	mov	r11,QWORD[24+rsp]
-	mov	r12,QWORD[32+rsp]
-	mov	r13,QWORD[40+rsp]
-	mov	r14,QWORD[48+rsp]
-	mov	r15,QWORD[56+rsp]
-
-	call	__rsaz_512_reduce
-	add	r8,QWORD[64+rsp]
-	adc	r9,QWORD[72+rsp]
-	adc	r10,QWORD[80+rsp]
-	adc	r11,QWORD[88+rsp]
-	adc	r12,QWORD[96+rsp]
-	adc	r13,QWORD[104+rsp]
-	adc	r14,QWORD[112+rsp]
-	adc	r15,QWORD[120+rsp]
-	sbb	rcx,rcx
-
-	call	__rsaz_512_subtract
-
-	lea	rax,[((128+24+48))+rsp]
-	mov	r15,QWORD[((-48))+rax]
-	mov	r14,QWORD[((-40))+rax]
-	mov	r13,QWORD[((-32))+rax]
-	mov	r12,QWORD[((-24))+rax]
-	mov	rbp,QWORD[((-16))+rax]
-	mov	rbx,QWORD[((-8))+rax]
-	lea	rsp,[rax]
-$L$mul_gather4_epilogue:
-	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
-	mov	rsi,QWORD[16+rsp]
-	DB	0F3h,0C3h		;repret
-$L$SEH_end_rsaz_512_mul_gather4:
-global	rsaz_512_mul_scatter4
-
-ALIGN	32
-rsaz_512_mul_scatter4:
-	mov	QWORD[8+rsp],rdi	;WIN64 prologue
-	mov	QWORD[16+rsp],rsi
-	mov	rax,rsp
-$L$SEH_begin_rsaz_512_mul_scatter4:
-	mov	rdi,rcx
-	mov	rsi,rdx
-	mov	rdx,r8
-	mov	rcx,r9
-	mov	r8,QWORD[40+rsp]
-	mov	r9,QWORD[48+rsp]
-
-
-	push	rbx
-	push	rbp
-	push	r12
-	push	r13
-	push	r14
-	push	r15
-
-	mov	r9d,r9d
-	sub	rsp,128+24
-$L$mul_scatter4_body:
-	lea	r8,[r9*4+r8]
-DB	102,72,15,110,199
-DB	102,72,15,110,202
-DB	102,73,15,110,208
-	mov	QWORD[128+rsp],rcx
-
-	mov	rbp,rdi
-	mov	rbx,QWORD[rdi]
-	call	__rsaz_512_mul
-
-DB	102,72,15,126,199
-DB	102,72,15,126,205
-
-	mov	r8,QWORD[rsp]
-	mov	r9,QWORD[8+rsp]
-	mov	r10,QWORD[16+rsp]
-	mov	r11,QWORD[24+rsp]
-	mov	r12,QWORD[32+rsp]
-	mov	r13,QWORD[40+rsp]
-	mov	r14,QWORD[48+rsp]
-	mov	r15,QWORD[56+rsp]
-
-	call	__rsaz_512_reduce
-	add	r8,QWORD[64+rsp]
-	adc	r9,QWORD[72+rsp]
-	adc	r10,QWORD[80+rsp]
-	adc	r11,QWORD[88+rsp]
-	adc	r12,QWORD[96+rsp]
-	adc	r13,QWORD[104+rsp]
-	adc	r14,QWORD[112+rsp]
-	adc	r15,QWORD[120+rsp]
-DB	102,72,15,126,214
-	sbb	rcx,rcx
-
-	call	__rsaz_512_subtract
-
-	mov	DWORD[rsi],r8d
-	shr	r8,32
-	mov	DWORD[128+rsi],r9d
-	shr	r9,32
-	mov	DWORD[256+rsi],r10d
-	shr	r10,32
-	mov	DWORD[384+rsi],r11d
-	shr	r11,32
-	mov	DWORD[512+rsi],r12d
-	shr	r12,32
-	mov	DWORD[640+rsi],r13d
-	shr	r13,32
-	mov	DWORD[768+rsi],r14d
-	shr	r14,32
-	mov	DWORD[896+rsi],r15d
-	shr	r15,32
-	mov	DWORD[64+rsi],r8d
-	mov	DWORD[192+rsi],r9d
-	mov	DWORD[320+rsi],r10d
-	mov	DWORD[448+rsi],r11d
-	mov	DWORD[576+rsi],r12d
-	mov	DWORD[704+rsi],r13d
-	mov	DWORD[832+rsi],r14d
-	mov	DWORD[960+rsi],r15d
-
-	lea	rax,[((128+24+48))+rsp]
-	mov	r15,QWORD[((-48))+rax]
-	mov	r14,QWORD[((-40))+rax]
-	mov	r13,QWORD[((-32))+rax]
-	mov	r12,QWORD[((-24))+rax]
-	mov	rbp,QWORD[((-16))+rax]
-	mov	rbx,QWORD[((-8))+rax]
-	lea	rsp,[rax]
-$L$mul_scatter4_epilogue:
-	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
-	mov	rsi,QWORD[16+rsp]
-	DB	0F3h,0C3h		;repret
-$L$SEH_end_rsaz_512_mul_scatter4:
-global	rsaz_512_mul_by_one
-
-ALIGN	32
-rsaz_512_mul_by_one:
-	mov	QWORD[8+rsp],rdi	;WIN64 prologue
-	mov	QWORD[16+rsp],rsi
-	mov	rax,rsp
-$L$SEH_begin_rsaz_512_mul_by_one:
-	mov	rdi,rcx
-	mov	rsi,rdx
-	mov	rdx,r8
-	mov	rcx,r9
-
-
-	push	rbx
-	push	rbp
-	push	r12
-	push	r13
-	push	r14
-	push	r15
-
-	sub	rsp,128+24
-$L$mul_by_one_body:
-	mov	rbp,rdx
-	mov	QWORD[128+rsp],rcx
-
-	mov	r8,QWORD[rsi]
-	pxor	xmm0,xmm0
-	mov	r9,QWORD[8+rsi]
-	mov	r10,QWORD[16+rsi]
-	mov	r11,QWORD[24+rsi]
-	mov	r12,QWORD[32+rsi]
-	mov	r13,QWORD[40+rsi]
-	mov	r14,QWORD[48+rsi]
-	mov	r15,QWORD[56+rsi]
-
-	movdqa	XMMWORD[rsp],xmm0
-	movdqa	XMMWORD[16+rsp],xmm0
-	movdqa	XMMWORD[32+rsp],xmm0
-	movdqa	XMMWORD[48+rsp],xmm0
-	movdqa	XMMWORD[64+rsp],xmm0
-	movdqa	XMMWORD[80+rsp],xmm0
-	movdqa	XMMWORD[96+rsp],xmm0
-	call	__rsaz_512_reduce
-	mov	QWORD[rdi],r8
-	mov	QWORD[8+rdi],r9
-	mov	QWORD[16+rdi],r10
-	mov	QWORD[24+rdi],r11
-	mov	QWORD[32+rdi],r12
-	mov	QWORD[40+rdi],r13
-	mov	QWORD[48+rdi],r14
-	mov	QWORD[56+rdi],r15
-
-	lea	rax,[((128+24+48))+rsp]
-	mov	r15,QWORD[((-48))+rax]
-	mov	r14,QWORD[((-40))+rax]
-	mov	r13,QWORD[((-32))+rax]
-	mov	r12,QWORD[((-24))+rax]
-	mov	rbp,QWORD[((-16))+rax]
-	mov	rbx,QWORD[((-8))+rax]
-	lea	rsp,[rax]
-$L$mul_by_one_epilogue:
-	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
-	mov	rsi,QWORD[16+rsp]
-	DB	0F3h,0C3h		;repret
-$L$SEH_end_rsaz_512_mul_by_one:
-
-ALIGN	32
-__rsaz_512_reduce:
-	mov	rbx,r8
-	imul	rbx,QWORD[((128+8))+rsp]
-	mov	rax,QWORD[rbp]
-	mov	ecx,8
-	jmp	NEAR $L$reduction_loop
-
-ALIGN	32
-$L$reduction_loop:
-	mul	rbx
-	mov	rax,QWORD[8+rbp]
-	neg	r8
-	mov	r8,rdx
-	adc	r8,0
-
-	mul	rbx
-	add	r9,rax
-	mov	rax,QWORD[16+rbp]
-	adc	rdx,0
-	add	r8,r9
-	mov	r9,rdx
-	adc	r9,0
-
-	mul	rbx
-	add	r10,rax
-	mov	rax,QWORD[24+rbp]
-	adc	rdx,0
-	add	r9,r10
-	mov	r10,rdx
-	adc	r10,0
-
-	mul	rbx
-	add	r11,rax
-	mov	rax,QWORD[32+rbp]
-	adc	rdx,0
-	add	r10,r11
-	mov	rsi,QWORD[((128+8))+rsp]
-
-
-	adc	rdx,0
-	mov	r11,rdx
-
-	mul	rbx
-	add	r12,rax
-	mov	rax,QWORD[40+rbp]
-	adc	rdx,0
-	imul	rsi,r8
-	add	r11,r12
-	mov	r12,rdx
-	adc	r12,0
-
-	mul	rbx
-	add	r13,rax
-	mov	rax,QWORD[48+rbp]
-	adc	rdx,0
-	add	r12,r13
-	mov	r13,rdx
-	adc	r13,0
-
-	mul	rbx
-	add	r14,rax
-	mov	rax,QWORD[56+rbp]
-	adc	rdx,0
-	add	r13,r14
-	mov	r14,rdx
-	adc	r14,0
-
-	mul	rbx
-	mov	rbx,rsi
-	add	r15,rax
-	mov	rax,QWORD[rbp]
-	adc	rdx,0
-	add	r14,r15
-	mov	r15,rdx
-	adc	r15,0
-
-	dec	ecx
-	jne	NEAR $L$reduction_loop
-
-	DB	0F3h,0C3h		;repret
-
-
-ALIGN	32
-__rsaz_512_subtract:
-	mov	QWORD[rdi],r8
-	mov	QWORD[8+rdi],r9
-	mov	QWORD[16+rdi],r10
-	mov	QWORD[24+rdi],r11
-	mov	QWORD[32+rdi],r12
-	mov	QWORD[40+rdi],r13
-	mov	QWORD[48+rdi],r14
-	mov	QWORD[56+rdi],r15
-
-	mov	r8,QWORD[rbp]
-	mov	r9,QWORD[8+rbp]
-	neg	r8
-	not	r9
-	and	r8,rcx
-	mov	r10,QWORD[16+rbp]
-	and	r9,rcx
-	not	r10
-	mov	r11,QWORD[24+rbp]
-	and	r10,rcx
-	not	r11
-	mov	r12,QWORD[32+rbp]
-	and	r11,rcx
-	not	r12
-	mov	r13,QWORD[40+rbp]
-	and	r12,rcx
-	not	r13
-	mov	r14,QWORD[48+rbp]
-	and	r13,rcx
-	not	r14
-	mov	r15,QWORD[56+rbp]
-	and	r14,rcx
-	not	r15
-	and	r15,rcx
-
-	add	r8,QWORD[rdi]
-	adc	r9,QWORD[8+rdi]
-	adc	r10,QWORD[16+rdi]
-	adc	r11,QWORD[24+rdi]
-	adc	r12,QWORD[32+rdi]
-	adc	r13,QWORD[40+rdi]
-	adc	r14,QWORD[48+rdi]
-	adc	r15,QWORD[56+rdi]
-
-	mov	QWORD[rdi],r8
-	mov	QWORD[8+rdi],r9
-	mov	QWORD[16+rdi],r10
-	mov	QWORD[24+rdi],r11
-	mov	QWORD[32+rdi],r12
-	mov	QWORD[40+rdi],r13
-	mov	QWORD[48+rdi],r14
-	mov	QWORD[56+rdi],r15
-
-	DB	0F3h,0C3h		;repret
-
-
-ALIGN	32
-__rsaz_512_mul:
-	lea	rdi,[8+rsp]
-
-	mov	rax,QWORD[rsi]
-	mul	rbx
-	mov	QWORD[rdi],rax
-	mov	rax,QWORD[8+rsi]
-	mov	r8,rdx
-
-	mul	rbx
-	add	r8,rax
-	mov	rax,QWORD[16+rsi]
-	mov	r9,rdx
-	adc	r9,0
-
-	mul	rbx
-	add	r9,rax
-	mov	rax,QWORD[24+rsi]
-	mov	r10,rdx
-	adc	r10,0
-
-	mul	rbx
-	add	r10,rax
-	mov	rax,QWORD[32+rsi]
-	mov	r11,rdx
-	adc	r11,0
-
-	mul	rbx
-	add	r11,rax
-	mov	rax,QWORD[40+rsi]
-	mov	r12,rdx
-	adc	r12,0
-
-	mul	rbx
-	add	r12,rax
-	mov	rax,QWORD[48+rsi]
-	mov	r13,rdx
-	adc	r13,0
-
-	mul	rbx
-	add	r13,rax
-	mov	rax,QWORD[56+rsi]
-	mov	r14,rdx
-	adc	r14,0
-
-	mul	rbx
-	add	r14,rax
-	mov	rax,QWORD[rsi]
-	mov	r15,rdx
-	adc	r15,0
-
-	lea	rbp,[8+rbp]
-	lea	rdi,[8+rdi]
-
-	mov	ecx,7
-	jmp	NEAR $L$oop_mul
-
-ALIGN	32
-$L$oop_mul:
-	mov	rbx,QWORD[rbp]
-	mul	rbx
-	add	r8,rax
-	mov	rax,QWORD[8+rsi]
-	mov	QWORD[rdi],r8
-	mov	r8,rdx
-	adc	r8,0
-
-	mul	rbx
-	add	r9,rax
-	mov	rax,QWORD[16+rsi]
-	adc	rdx,0
-	add	r8,r9
-	mov	r9,rdx
-	adc	r9,0
-
-	mul	rbx
-	add	r10,rax
-	mov	rax,QWORD[24+rsi]
-	adc	rdx,0
-	add	r9,r10
-	mov	r10,rdx
-	adc	r10,0
-
-	mul	rbx
-	add	r11,rax
-	mov	rax,QWORD[32+rsi]
-	adc	rdx,0
-	add	r10,r11
-	mov	r11,rdx
-	adc	r11,0
-
-	mul	rbx
-	add	r12,rax
-	mov	rax,QWORD[40+rsi]
-	adc	rdx,0
-	add	r11,r12
-	mov	r12,rdx
-	adc	r12,0
-
-	mul	rbx
-	add	r13,rax
-	mov	rax,QWORD[48+rsi]
-	adc	rdx,0
-	add	r12,r13
-	mov	r13,rdx
-	adc	r13,0
-
-	mul	rbx
-	add	r14,rax
-	mov	rax,QWORD[56+rsi]
-	adc	rdx,0
-	add	r13,r14
-	mov	r14,rdx
-	lea	rbp,[8+rbp]
-	adc	r14,0
-
-	mul	rbx
-	add	r15,rax
-	mov	rax,QWORD[rsi]
-	adc	rdx,0
-	add	r14,r15
-	mov	r15,rdx
-	adc	r15,0
-
-	lea	rdi,[8+rdi]
-
-	dec	ecx
-	jnz	NEAR $L$oop_mul
-
-	mov	QWORD[rdi],r8
-	mov	QWORD[8+rdi],r9
-	mov	QWORD[16+rdi],r10
-	mov	QWORD[24+rdi],r11
-	mov	QWORD[32+rdi],r12
-	mov	QWORD[40+rdi],r13
-	mov	QWORD[48+rdi],r14
-	mov	QWORD[56+rdi],r15
-
-	DB	0F3h,0C3h		;repret
-
-global	rsaz_512_scatter4
-
-ALIGN	16
-rsaz_512_scatter4:
-	lea	rcx,[r8*4+rcx]
-	mov	r9d,8
-	jmp	NEAR $L$oop_scatter
-ALIGN	16
-$L$oop_scatter:
-	mov	rax,QWORD[rdx]
-	lea	rdx,[8+rdx]
-	mov	DWORD[rcx],eax
-	shr	rax,32
-	mov	DWORD[64+rcx],eax
-	lea	rcx,[128+rcx]
-	dec	r9d
-	jnz	NEAR $L$oop_scatter
-	DB	0F3h,0C3h		;repret
-
-
-global	rsaz_512_gather4
-
-ALIGN	16
-rsaz_512_gather4:
-	lea	rdx,[r8*4+rdx]
-	mov	r9d,8
-	jmp	NEAR $L$oop_gather
-ALIGN	16
-$L$oop_gather:
-	mov	eax,DWORD[rdx]
-	mov	r8d,DWORD[64+rdx]
-	lea	rdx,[128+rdx]
-	shl	r8,32
-	or	rax,r8
-	mov	QWORD[rcx],rax
-	lea	rcx,[8+rcx]
-	dec	r9d
-	jnz	NEAR $L$oop_gather
-	DB	0F3h,0C3h		;repret
-
-EXTERN	__imp_RtlVirtualUnwind
-
-ALIGN	16
-se_handler:
-	push	rsi
-	push	rdi
-	push	rbx
-	push	rbp
-	push	r12
-	push	r13
-	push	r14
-	push	r15
-	pushfq
-	sub	rsp,64
-
-	mov	rax,QWORD[120+r8]
-	mov	rbx,QWORD[248+r8]
-
-	mov	rsi,QWORD[8+r9]
-	mov	r11,QWORD[56+r9]
-
-	mov	r10d,DWORD[r11]
-	lea	r10,[r10*1+rsi]
-	cmp	rbx,r10
-	jb	NEAR $L$common_seh_tail
-
-	mov	rax,QWORD[152+r8]
-
-	mov	r10d,DWORD[4+r11]
-	lea	r10,[r10*1+rsi]
-	cmp	rbx,r10
-	jae	NEAR $L$common_seh_tail
-
-	lea	rax,[((128+24+48))+rax]
-
-	mov	rbx,QWORD[((-8))+rax]
-	mov	rbp,QWORD[((-16))+rax]
-	mov	r12,QWORD[((-24))+rax]
-	mov	r13,QWORD[((-32))+rax]
-	mov	r14,QWORD[((-40))+rax]
-	mov	r15,QWORD[((-48))+rax]
-	mov	QWORD[144+r8],rbx
-	mov	QWORD[160+r8],rbp
-	mov	QWORD[216+r8],r12
-	mov	QWORD[224+r8],r13
-	mov	QWORD[232+r8],r14
-	mov	QWORD[240+r8],r15
-
-$L$common_seh_tail:
-	mov	rdi,QWORD[8+rax]
-	mov	rsi,QWORD[16+rax]
-	mov	QWORD[152+r8],rax
-	mov	QWORD[168+r8],rsi
-	mov	QWORD[176+r8],rdi
-
-	mov	rdi,QWORD[40+r9]
-	mov	rsi,r8
-	mov	ecx,154
-	DD	0xa548f3fc
-
-	mov	rsi,r9
-	xor	rcx,rcx
-	mov	rdx,QWORD[8+rsi]
-	mov	r8,QWORD[rsi]
-	mov	r9,QWORD[16+rsi]
-	mov	r10,QWORD[40+rsi]
-	lea	r11,[56+rsi]
-	lea	r12,[24+rsi]
-	mov	QWORD[32+rsp],r10
-	mov	QWORD[40+rsp],r11
-	mov	QWORD[48+rsp],r12
-	mov	QWORD[56+rsp],rcx
-	call	QWORD[__imp_RtlVirtualUnwind]
-
-	mov	eax,1
-	add	rsp,64
-	popfq
-	pop	r15
-	pop	r14
-	pop	r13
-	pop	r12
-	pop	rbp
-	pop	rbx
-	pop	rdi
-	pop	rsi
-	DB	0F3h,0C3h		;repret
-
-
-section	.pdata rdata align=4
-ALIGN	4
-	DD	$L$SEH_begin_rsaz_512_sqr wrt ..imagebase
-	DD	$L$SEH_end_rsaz_512_sqr wrt ..imagebase
-	DD	$L$SEH_info_rsaz_512_sqr wrt ..imagebase
-
-	DD	$L$SEH_begin_rsaz_512_mul wrt ..imagebase
-	DD	$L$SEH_end_rsaz_512_mul wrt ..imagebase
-	DD	$L$SEH_info_rsaz_512_mul wrt ..imagebase
-
-	DD	$L$SEH_begin_rsaz_512_mul_gather4 wrt ..imagebase
-	DD	$L$SEH_end_rsaz_512_mul_gather4 wrt ..imagebase
-	DD	$L$SEH_info_rsaz_512_mul_gather4 wrt ..imagebase
-
-	DD	$L$SEH_begin_rsaz_512_mul_scatter4 wrt ..imagebase
-	DD	$L$SEH_end_rsaz_512_mul_scatter4 wrt ..imagebase
-	DD	$L$SEH_info_rsaz_512_mul_scatter4 wrt ..imagebase
-
-	DD	$L$SEH_begin_rsaz_512_mul_by_one wrt ..imagebase
-	DD	$L$SEH_end_rsaz_512_mul_by_one wrt ..imagebase
-	DD	$L$SEH_info_rsaz_512_mul_by_one wrt ..imagebase
-
-section	.xdata rdata align=8
-ALIGN	8
-$L$SEH_info_rsaz_512_sqr:
-DB	9,0,0,0
-	DD	se_handler wrt ..imagebase
-	DD	$L$sqr_body wrt ..imagebase,$L$sqr_epilogue wrt ..imagebase
-$L$SEH_info_rsaz_512_mul:
-DB	9,0,0,0
-	DD	se_handler wrt ..imagebase
-	DD	$L$mul_body wrt ..imagebase,$L$mul_epilogue wrt ..imagebase
-$L$SEH_info_rsaz_512_mul_gather4:
-DB	9,0,0,0
-	DD	se_handler wrt ..imagebase
-	DD	$L$mul_gather4_body wrt ..imagebase,$L$mul_gather4_epilogue wrt ..imagebase
-$L$SEH_info_rsaz_512_mul_scatter4:
-DB	9,0,0,0
-	DD	se_handler wrt ..imagebase
-	DD	$L$mul_scatter4_body wrt ..imagebase,$L$mul_scatter4_epilogue wrt ..imagebase
-$L$SEH_info_rsaz_512_mul_by_one:
-DB	9,0,0,0
-	DD	se_handler wrt ..imagebase
-	DD	$L$mul_by_one_body wrt ..imagebase,$L$mul_by_one_epilogue wrt ..imagebase
diff --git a/win-x86_64/crypto/bn/x86_64-mont.asm b/win-x86_64/crypto/bn/x86_64-mont.asm
index db0d1b9..1a9da51 100644
--- a/win-x86_64/crypto/bn/x86_64-mont.asm
+++ b/win-x86_64/crypto/bn/x86_64-mont.asm
@@ -23,6 +23,10 @@
 	mov	r9,QWORD[48+rsp]
 
 
+
+	mov	r9d,r9d
+	mov	rax,rsp
+
 	test	r9d,3
 	jnz	NEAR $L$mul_enter
 	cmp	r9d,8
@@ -36,20 +40,50 @@
 ALIGN	16
 $L$mul_enter:
 	push	rbx
+
 	push	rbp
+
 	push	r12
+
 	push	r13
+
 	push	r14
+
 	push	r15
 
-	mov	r9d,r9d
-	lea	r10,[2+r9]
-	mov	r11,rsp
-	neg	r10
-	lea	rsp,[r10*8+rsp]
-	and	rsp,-1024
 
-	mov	QWORD[8+r9*8+rsp],r11
+	neg	r9
+	mov	r11,rsp
+	lea	r10,[((-16))+r9*8+rsp]
+	neg	r9
+	and	r10,-1024
+
+
+
+
+
+
+
+
+
+	sub	r11,r10
+	and	r11,-4096
+	lea	rsp,[r11*1+r10]
+	mov	r11,QWORD[rsp]
+	cmp	rsp,r10
+	ja	NEAR $L$mul_page_walk
+	jmp	NEAR $L$mul_page_walk_done
+
+ALIGN	16
+$L$mul_page_walk:
+	lea	rsp,[((-4096))+rsp]
+	mov	r11,QWORD[rsp]
+	cmp	rsp,r10
+	ja	NEAR $L$mul_page_walk
+$L$mul_page_walk_done:
+
+	mov	QWORD[8+r9*8+rsp],rax
+
 $L$mul_body:
 	mov	r12,rdx
 	mov	r8,QWORD[r8]
@@ -201,33 +235,43 @@
 
 	sbb	rax,0
 	xor	r14,r14
+	and	rsi,rax
+	not	rax
+	mov	rcx,rdi
+	and	rcx,rax
 	mov	r15,r9
+	or	rsi,rcx
 ALIGN	16
 $L$copy:
-	mov	rsi,QWORD[r14*8+rsp]
-	mov	rcx,QWORD[r14*8+rdi]
-	xor	rsi,rcx
-	and	rsi,rax
-	xor	rsi,rcx
+	mov	rax,QWORD[r14*8+rsi]
 	mov	QWORD[r14*8+rsp],r14
-	mov	QWORD[r14*8+rdi],rsi
+	mov	QWORD[r14*8+rdi],rax
 	lea	r14,[1+r14]
 	sub	r15,1
 	jnz	NEAR $L$copy
 
 	mov	rsi,QWORD[8+r9*8+rsp]
+
 	mov	rax,1
-	mov	r15,QWORD[rsi]
-	mov	r14,QWORD[8+rsi]
-	mov	r13,QWORD[16+rsi]
-	mov	r12,QWORD[24+rsi]
-	mov	rbp,QWORD[32+rsi]
-	mov	rbx,QWORD[40+rsi]
-	lea	rsp,[48+rsi]
+	mov	r15,QWORD[((-48))+rsi]
+
+	mov	r14,QWORD[((-40))+rsi]
+
+	mov	r13,QWORD[((-32))+rsi]
+
+	mov	r12,QWORD[((-24))+rsi]
+
+	mov	rbp,QWORD[((-16))+rsi]
+
+	mov	rbx,QWORD[((-8))+rsi]
+
+	lea	rsp,[rsi]
+
 $L$mul_epilogue:
 	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
 	mov	rsi,QWORD[16+rsp]
 	DB	0F3h,0C3h		;repret
+
 $L$SEH_end_bn_mul_mont:
 
 ALIGN	16
@@ -244,22 +288,47 @@
 	mov	r9,QWORD[48+rsp]
 
 
-$L$mul4x_enter:
-	push	rbx
-	push	rbp
-	push	r12
-	push	r13
-	push	r14
-	push	r15
 
 	mov	r9d,r9d
-	lea	r10,[4+r9]
-	mov	r11,rsp
-	neg	r10
-	lea	rsp,[r10*8+rsp]
-	and	rsp,-1024
+	mov	rax,rsp
 
-	mov	QWORD[8+r9*8+rsp],r11
+$L$mul4x_enter:
+	push	rbx
+
+	push	rbp
+
+	push	r12
+
+	push	r13
+
+	push	r14
+
+	push	r15
+
+
+	neg	r9
+	mov	r11,rsp
+	lea	r10,[((-32))+r9*8+rsp]
+	neg	r9
+	and	r10,-1024
+
+	sub	r11,r10
+	and	r11,-4096
+	lea	rsp,[r11*1+r10]
+	mov	r11,QWORD[rsp]
+	cmp	rsp,r10
+	ja	NEAR $L$mul4x_page_walk
+	jmp	NEAR $L$mul4x_page_walk_done
+
+$L$mul4x_page_walk:
+	lea	rsp,[((-4096))+rsp]
+	mov	r11,QWORD[rsp]
+	cmp	rsp,r10
+	ja	NEAR $L$mul4x_page_walk
+$L$mul4x_page_walk_done:
+
+	mov	QWORD[8+r9*8+rsp],rax
+
 $L$mul4x_body:
 	mov	QWORD[16+r9*8+rsp],rdi
 	mov	r12,rdx
@@ -559,9 +628,11 @@
 	cmp	r14,r9
 	jb	NEAR $L$outer4x
 	mov	rdi,QWORD[16+r9*8+rsp]
+	lea	r15,[((-4))+r9]
 	mov	rax,QWORD[rsp]
+	pxor	xmm0,xmm0
 	mov	rdx,QWORD[8+rsp]
-	shr	r9,2
+	shr	r15,2
 	lea	rsi,[rsp]
 	xor	r14,r14
 
@@ -569,7 +640,6 @@
 	mov	rbx,QWORD[16+rsi]
 	mov	rbp,QWORD[24+rsi]
 	sbb	rdx,QWORD[8+rcx]
-	lea	r15,[((-1))+r9]
 	jmp	NEAR $L$sub4x
 ALIGN	16
 $L$sub4x:
@@ -597,49 +667,57 @@
 	mov	QWORD[16+r14*8+rdi],rbx
 
 	sbb	rax,0
-DB 66h, 48h, 0fh, 6eh, 0c0h
-	punpcklqdq	xmm0,xmm0
 	mov	QWORD[24+r14*8+rdi],rbp
 	xor	r14,r14
+	and	rsi,rax
+	not	rax
+	mov	rcx,rdi
+	and	rcx,rax
+	lea	r15,[((-4))+r9]
+	or	rsi,rcx
+	shr	r15,2
 
-	mov	r15,r9
-	pxor	xmm5,xmm5
+	movdqu	xmm1,XMMWORD[rsi]
+	movdqa	XMMWORD[rsp],xmm0
+	movdqu	XMMWORD[rdi],xmm1
 	jmp	NEAR $L$copy4x
 ALIGN	16
 $L$copy4x:
-	movdqu	xmm2,XMMWORD[r14*1+rsp]
-	movdqu	xmm4,XMMWORD[16+r14*1+rsp]
-	movdqu	xmm1,XMMWORD[r14*1+rdi]
-	movdqu	xmm3,XMMWORD[16+r14*1+rdi]
-	pxor	xmm2,xmm1
-	pxor	xmm4,xmm3
-	pand	xmm2,xmm0
-	pand	xmm4,xmm0
-	pxor	xmm2,xmm1
-	pxor	xmm4,xmm3
-	movdqu	XMMWORD[r14*1+rdi],xmm2
-	movdqu	XMMWORD[16+r14*1+rdi],xmm4
-	movdqa	XMMWORD[r14*1+rsp],xmm5
-	movdqa	XMMWORD[16+r14*1+rsp],xmm5
-
+	movdqu	xmm2,XMMWORD[16+r14*1+rsi]
+	movdqu	xmm1,XMMWORD[32+r14*1+rsi]
+	movdqa	XMMWORD[16+r14*1+rsp],xmm0
+	movdqu	XMMWORD[16+r14*1+rdi],xmm2
+	movdqa	XMMWORD[32+r14*1+rsp],xmm0
+	movdqu	XMMWORD[32+r14*1+rdi],xmm1
 	lea	r14,[32+r14]
 	dec	r15
 	jnz	NEAR $L$copy4x
 
-	shl	r9,2
+	movdqu	xmm2,XMMWORD[16+r14*1+rsi]
+	movdqa	XMMWORD[16+r14*1+rsp],xmm0
+	movdqu	XMMWORD[16+r14*1+rdi],xmm2
 	mov	rsi,QWORD[8+r9*8+rsp]
+
 	mov	rax,1
-	mov	r15,QWORD[rsi]
-	mov	r14,QWORD[8+rsi]
-	mov	r13,QWORD[16+rsi]
-	mov	r12,QWORD[24+rsi]
-	mov	rbp,QWORD[32+rsi]
-	mov	rbx,QWORD[40+rsi]
-	lea	rsp,[48+rsi]
+	mov	r15,QWORD[((-48))+rsi]
+
+	mov	r14,QWORD[((-40))+rsi]
+
+	mov	r13,QWORD[((-32))+rsi]
+
+	mov	r12,QWORD[((-24))+rsi]
+
+	mov	rbp,QWORD[((-16))+rsi]
+
+	mov	rbx,QWORD[((-8))+rsi]
+
+	lea	rsp,[rsi]
+
 $L$mul4x_epilogue:
 	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
 	mov	rsi,QWORD[16+rsp]
 	DB	0F3h,0C3h		;repret
+
 $L$SEH_end_bn_mul4x_mont:
 EXTERN	bn_sqr8x_internal
 
@@ -658,15 +736,24 @@
 	mov	r9,QWORD[48+rsp]
 
 
-$L$sqr8x_enter:
+
 	mov	rax,rsp
+
+$L$sqr8x_enter:
 	push	rbx
+
 	push	rbp
+
 	push	r12
+
 	push	r13
+
 	push	r14
+
 	push	r15
 
+$L$sqr8x_prologue:
+
 	mov	r10d,r9d
 	shl	r9d,3
 	shl	r10,3+2
@@ -677,94 +764,144 @@
 
 
 
-	lea	r11,[((-64))+r9*4+rsp]
+	lea	r11,[((-64))+r9*2+rsp]
+	mov	rbp,rsp
 	mov	r8,QWORD[r8]
 	sub	r11,rsi
 	and	r11,4095
 	cmp	r10,r11
 	jb	NEAR $L$sqr8x_sp_alt
-	sub	rsp,r11
-	lea	rsp,[((-64))+r9*4+rsp]
+	sub	rbp,r11
+	lea	rbp,[((-64))+r9*2+rbp]
 	jmp	NEAR $L$sqr8x_sp_done
 
 ALIGN	32
 $L$sqr8x_sp_alt:
-	lea	r10,[((4096-64))+r9*4]
-	lea	rsp,[((-64))+r9*4+rsp]
+	lea	r10,[((4096-64))+r9*2]
+	lea	rbp,[((-64))+r9*2+rbp]
 	sub	r11,r10
 	mov	r10,0
 	cmovc	r11,r10
-	sub	rsp,r11
+	sub	rbp,r11
 $L$sqr8x_sp_done:
-	and	rsp,-64
+	and	rbp,-64
+	mov	r11,rsp
+	sub	r11,rbp
+	and	r11,-4096
+	lea	rsp,[rbp*1+r11]
+	mov	r10,QWORD[rsp]
+	cmp	rsp,rbp
+	ja	NEAR $L$sqr8x_page_walk
+	jmp	NEAR $L$sqr8x_page_walk_done
+
+ALIGN	16
+$L$sqr8x_page_walk:
+	lea	rsp,[((-4096))+rsp]
+	mov	r10,QWORD[rsp]
+	cmp	rsp,rbp
+	ja	NEAR $L$sqr8x_page_walk
+$L$sqr8x_page_walk_done:
+
 	mov	r10,r9
 	neg	r9
 
-	lea	r11,[64+r9*2+rsp]
 	mov	QWORD[32+rsp],r8
 	mov	QWORD[40+rsp],rax
+
 $L$sqr8x_body:
 
-	mov	rbp,r9
-DB	102,73,15,110,211
-	shr	rbp,3+2
-	mov	eax,DWORD[((OPENSSL_ia32cap_P+8))]
-	jmp	NEAR $L$sqr8x_copy_n
-
-ALIGN	32
-$L$sqr8x_copy_n:
-	movq	xmm0,QWORD[rcx]
-	movq	xmm1,QWORD[8+rcx]
-	movq	xmm3,QWORD[16+rcx]
-	movq	xmm4,QWORD[24+rcx]
-	lea	rcx,[32+rcx]
-	movdqa	XMMWORD[r11],xmm0
-	movdqa	XMMWORD[16+r11],xmm1
-	movdqa	XMMWORD[32+r11],xmm3
-	movdqa	XMMWORD[48+r11],xmm4
-	lea	r11,[64+r11]
-	dec	rbp
-	jnz	NEAR $L$sqr8x_copy_n
-
+DB	102,72,15,110,209
 	pxor	xmm0,xmm0
 DB	102,72,15,110,207
 DB	102,73,15,110,218
 	call	bn_sqr8x_internal
 
-	pxor	xmm0,xmm0
-	lea	rax,[48+rsp]
-	lea	rdx,[64+r9*2+rsp]
-	shr	r9,3+2
-	mov	rsi,QWORD[40+rsp]
-	jmp	NEAR $L$sqr8x_zero
+
+
+
+	lea	rbx,[r9*1+rdi]
+	mov	rcx,r9
+	mov	rdx,r9
+DB	102,72,15,126,207
+	sar	rcx,3+2
+	jmp	NEAR $L$sqr8x_sub
 
 ALIGN	32
-$L$sqr8x_zero:
-	movdqa	XMMWORD[rax],xmm0
-	movdqa	XMMWORD[16+rax],xmm0
-	movdqa	XMMWORD[32+rax],xmm0
-	movdqa	XMMWORD[48+rax],xmm0
-	lea	rax,[64+rax]
-	movdqa	XMMWORD[rdx],xmm0
-	movdqa	XMMWORD[16+rdx],xmm0
-	movdqa	XMMWORD[32+rdx],xmm0
-	movdqa	XMMWORD[48+rdx],xmm0
-	lea	rdx,[64+rdx]
-	dec	r9
-	jnz	NEAR $L$sqr8x_zero
+$L$sqr8x_sub:
+	mov	r12,QWORD[rbx]
+	mov	r13,QWORD[8+rbx]
+	mov	r14,QWORD[16+rbx]
+	mov	r15,QWORD[24+rbx]
+	lea	rbx,[32+rbx]
+	sbb	r12,QWORD[rbp]
+	sbb	r13,QWORD[8+rbp]
+	sbb	r14,QWORD[16+rbp]
+	sbb	r15,QWORD[24+rbp]
+	lea	rbp,[32+rbp]
+	mov	QWORD[rdi],r12
+	mov	QWORD[8+rdi],r13
+	mov	QWORD[16+rdi],r14
+	mov	QWORD[24+rdi],r15
+	lea	rdi,[32+rdi]
+	inc	rcx
+	jnz	NEAR $L$sqr8x_sub
+
+	sbb	rax,0
+	lea	rbx,[r9*1+rbx]
+	lea	rdi,[r9*1+rdi]
+
+DB	102,72,15,110,200
+	pxor	xmm0,xmm0
+	pshufd	xmm1,xmm1,0
+	mov	rsi,QWORD[40+rsp]
+
+	jmp	NEAR $L$sqr8x_cond_copy
+
+ALIGN	32
+$L$sqr8x_cond_copy:
+	movdqa	xmm2,XMMWORD[rbx]
+	movdqa	xmm3,XMMWORD[16+rbx]
+	lea	rbx,[32+rbx]
+	movdqu	xmm4,XMMWORD[rdi]
+	movdqu	xmm5,XMMWORD[16+rdi]
+	lea	rdi,[32+rdi]
+	movdqa	XMMWORD[(-32)+rbx],xmm0
+	movdqa	XMMWORD[(-16)+rbx],xmm0
+	movdqa	XMMWORD[(-32)+rdx*1+rbx],xmm0
+	movdqa	XMMWORD[(-16)+rdx*1+rbx],xmm0
+	pcmpeqd	xmm0,xmm1
+	pand	xmm2,xmm1
+	pand	xmm3,xmm1
+	pand	xmm4,xmm0
+	pand	xmm5,xmm0
+	pxor	xmm0,xmm0
+	por	xmm4,xmm2
+	por	xmm5,xmm3
+	movdqu	XMMWORD[(-32)+rdi],xmm4
+	movdqu	XMMWORD[(-16)+rdi],xmm5
+	add	r9,32
+	jnz	NEAR $L$sqr8x_cond_copy
 
 	mov	rax,1
 	mov	r15,QWORD[((-48))+rsi]
+
 	mov	r14,QWORD[((-40))+rsi]
+
 	mov	r13,QWORD[((-32))+rsi]
+
 	mov	r12,QWORD[((-24))+rsi]
+
 	mov	rbp,QWORD[((-16))+rsi]
+
 	mov	rbx,QWORD[((-8))+rsi]
+
 	lea	rsp,[rsi]
+
 $L$sqr8x_epilogue:
 	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
 	mov	rsi,QWORD[16+rsp]
 	DB	0F3h,0C3h		;repret
+
 $L$SEH_end_bn_sqr8x_mont:
 DB	77,111,110,116,103,111,109,101,114,121,32,77,117,108,116,105
 DB	112,108,105,99,97,116,105,111,110,32,102,111,114,32,120,56
@@ -807,22 +944,8 @@
 
 	mov	r10,QWORD[192+r8]
 	mov	rax,QWORD[8+r10*8+rax]
-	lea	rax,[48+rax]
 
-	mov	rbx,QWORD[((-8))+rax]
-	mov	rbp,QWORD[((-16))+rax]
-	mov	r12,QWORD[((-24))+rax]
-	mov	r13,QWORD[((-32))+rax]
-	mov	r14,QWORD[((-40))+rax]
-	mov	r15,QWORD[((-48))+rax]
-	mov	QWORD[144+r8],rbx
-	mov	QWORD[160+r8],rbp
-	mov	QWORD[216+r8],r12
-	mov	QWORD[224+r8],r13
-	mov	QWORD[232+r8],r14
-	mov	QWORD[240+r8],r15
-
-	jmp	NEAR $L$common_seh_tail
+	jmp	NEAR $L$common_pop_regs
 
 
 
@@ -850,15 +973,21 @@
 	cmp	rbx,r10
 	jb	NEAR $L$common_seh_tail
 
+	mov	r10d,DWORD[4+r11]
+	lea	r10,[r10*1+rsi]
+	cmp	rbx,r10
+	jb	NEAR $L$common_pop_regs
+
 	mov	rax,QWORD[152+r8]
 
-	mov	r10d,DWORD[4+r11]
+	mov	r10d,DWORD[8+r11]
 	lea	r10,[r10*1+rsi]
 	cmp	rbx,r10
 	jae	NEAR $L$common_seh_tail
 
 	mov	rax,QWORD[40+rax]
 
+$L$common_pop_regs:
 	mov	rbx,QWORD[((-8))+rax]
 	mov	rbp,QWORD[((-16))+rax]
 	mov	r12,QWORD[((-24))+rax]
@@ -938,4 +1067,5 @@
 $L$SEH_info_bn_sqr8x_mont:
 DB	9,0,0,0
 	DD	sqr_handler wrt ..imagebase
-	DD	$L$sqr8x_body wrt ..imagebase,$L$sqr8x_epilogue wrt ..imagebase
+	DD	$L$sqr8x_prologue wrt ..imagebase,$L$sqr8x_body wrt ..imagebase,$L$sqr8x_epilogue wrt ..imagebase
+ALIGN	8
diff --git a/win-x86_64/crypto/bn/x86_64-mont5.asm b/win-x86_64/crypto/bn/x86_64-mont5.asm
index 560b384..b330641 100644
--- a/win-x86_64/crypto/bn/x86_64-mont5.asm
+++ b/win-x86_64/crypto/bn/x86_64-mont5.asm
@@ -23,57 +23,193 @@
 	mov	r9,QWORD[48+rsp]
 
 
+
+	mov	r9d,r9d
+	mov	rax,rsp
+
 	test	r9d,7
 	jnz	NEAR $L$mul_enter
 	jmp	NEAR $L$mul4x_enter
 
 ALIGN	16
 $L$mul_enter:
-	mov	r9d,r9d
-	mov	rax,rsp
-	mov	r10d,DWORD[56+rsp]
+	movd	xmm5,DWORD[56+rsp]
 	push	rbx
+
 	push	rbp
+
 	push	r12
+
 	push	r13
+
 	push	r14
+
 	push	r15
-	lea	rsp,[((-40))+rsp]
-	movaps	XMMWORD[rsp],xmm6
-	movaps	XMMWORD[16+rsp],xmm7
-	lea	r11,[2+r9]
-	neg	r11
-	lea	rsp,[r11*8+rsp]
-	and	rsp,-1024
 
+
+	neg	r9
+	mov	r11,rsp
+	lea	r10,[((-280))+r9*8+rsp]
+	neg	r9
+	and	r10,-1024
+
+
+
+
+
+
+
+
+
+	sub	r11,r10
+	and	r11,-4096
+	lea	rsp,[r11*1+r10]
+	mov	r11,QWORD[rsp]
+	cmp	rsp,r10
+	ja	NEAR $L$mul_page_walk
+	jmp	NEAR $L$mul_page_walk_done
+
+$L$mul_page_walk:
+	lea	rsp,[((-4096))+rsp]
+	mov	r11,QWORD[rsp]
+	cmp	rsp,r10
+	ja	NEAR $L$mul_page_walk
+$L$mul_page_walk_done:
+
+	lea	r10,[$L$inc]
 	mov	QWORD[8+r9*8+rsp],rax
+
 $L$mul_body:
-	mov	r12,rdx
-	mov	r11,r10
-	shr	r10,3
-	and	r11,7
-	not	r10
-	lea	rax,[$L$magic_masks]
-	and	r10,3
-	lea	r12,[96+r11*8+r12]
-	movq	xmm4,QWORD[r10*8+rax]
-	movq	xmm5,QWORD[8+r10*8+rax]
-	movq	xmm6,QWORD[16+r10*8+rax]
-	movq	xmm7,QWORD[24+r10*8+rax]
 
-	movq	xmm0,QWORD[(((-96)))+r12]
-	movq	xmm1,QWORD[((-32))+r12]
-	pand	xmm0,xmm4
-	movq	xmm2,QWORD[32+r12]
-	pand	xmm1,xmm5
-	movq	xmm3,QWORD[96+r12]
-	pand	xmm2,xmm6
-	por	xmm0,xmm1
-	pand	xmm3,xmm7
+	lea	r12,[128+rdx]
+	movdqa	xmm0,XMMWORD[r10]
+	movdqa	xmm1,XMMWORD[16+r10]
+	lea	r10,[((24-112))+r9*8+rsp]
+	and	r10,-16
+
+	pshufd	xmm5,xmm5,0
+	movdqa	xmm4,xmm1
+	movdqa	xmm2,xmm1
+	paddd	xmm1,xmm0
+	pcmpeqd	xmm0,xmm5
+DB	0x67
+	movdqa	xmm3,xmm4
+	paddd	xmm2,xmm1
+	pcmpeqd	xmm1,xmm5
+	movdqa	XMMWORD[112+r10],xmm0
+	movdqa	xmm0,xmm4
+
+	paddd	xmm3,xmm2
+	pcmpeqd	xmm2,xmm5
+	movdqa	XMMWORD[128+r10],xmm1
+	movdqa	xmm1,xmm4
+
+	paddd	xmm0,xmm3
+	pcmpeqd	xmm3,xmm5
+	movdqa	XMMWORD[144+r10],xmm2
+	movdqa	xmm2,xmm4
+
+	paddd	xmm1,xmm0
+	pcmpeqd	xmm0,xmm5
+	movdqa	XMMWORD[160+r10],xmm3
+	movdqa	xmm3,xmm4
+	paddd	xmm2,xmm1
+	pcmpeqd	xmm1,xmm5
+	movdqa	XMMWORD[176+r10],xmm0
+	movdqa	xmm0,xmm4
+
+	paddd	xmm3,xmm2
+	pcmpeqd	xmm2,xmm5
+	movdqa	XMMWORD[192+r10],xmm1
+	movdqa	xmm1,xmm4
+
+	paddd	xmm0,xmm3
+	pcmpeqd	xmm3,xmm5
+	movdqa	XMMWORD[208+r10],xmm2
+	movdqa	xmm2,xmm4
+
+	paddd	xmm1,xmm0
+	pcmpeqd	xmm0,xmm5
+	movdqa	XMMWORD[224+r10],xmm3
+	movdqa	xmm3,xmm4
+	paddd	xmm2,xmm1
+	pcmpeqd	xmm1,xmm5
+	movdqa	XMMWORD[240+r10],xmm0
+	movdqa	xmm0,xmm4
+
+	paddd	xmm3,xmm2
+	pcmpeqd	xmm2,xmm5
+	movdqa	XMMWORD[256+r10],xmm1
+	movdqa	xmm1,xmm4
+
+	paddd	xmm0,xmm3
+	pcmpeqd	xmm3,xmm5
+	movdqa	XMMWORD[272+r10],xmm2
+	movdqa	xmm2,xmm4
+
+	paddd	xmm1,xmm0
+	pcmpeqd	xmm0,xmm5
+	movdqa	XMMWORD[288+r10],xmm3
+	movdqa	xmm3,xmm4
+	paddd	xmm2,xmm1
+	pcmpeqd	xmm1,xmm5
+	movdqa	XMMWORD[304+r10],xmm0
+
+	paddd	xmm3,xmm2
+DB	0x67
+	pcmpeqd	xmm2,xmm5
+	movdqa	XMMWORD[320+r10],xmm1
+
+	pcmpeqd	xmm3,xmm5
+	movdqa	XMMWORD[336+r10],xmm2
+	pand	xmm0,XMMWORD[64+r12]
+
+	pand	xmm1,XMMWORD[80+r12]
+	pand	xmm2,XMMWORD[96+r12]
+	movdqa	XMMWORD[352+r10],xmm3
+	pand	xmm3,XMMWORD[112+r12]
 	por	xmm0,xmm2
+	por	xmm1,xmm3
+	movdqa	xmm4,XMMWORD[((-128))+r12]
+	movdqa	xmm5,XMMWORD[((-112))+r12]
+	movdqa	xmm2,XMMWORD[((-96))+r12]
+	pand	xmm4,XMMWORD[112+r10]
+	movdqa	xmm3,XMMWORD[((-80))+r12]
+	pand	xmm5,XMMWORD[128+r10]
+	por	xmm0,xmm4
+	pand	xmm2,XMMWORD[144+r10]
+	por	xmm1,xmm5
+	pand	xmm3,XMMWORD[160+r10]
+	por	xmm0,xmm2
+	por	xmm1,xmm3
+	movdqa	xmm4,XMMWORD[((-64))+r12]
+	movdqa	xmm5,XMMWORD[((-48))+r12]
+	movdqa	xmm2,XMMWORD[((-32))+r12]
+	pand	xmm4,XMMWORD[176+r10]
+	movdqa	xmm3,XMMWORD[((-16))+r12]
+	pand	xmm5,XMMWORD[192+r10]
+	por	xmm0,xmm4
+	pand	xmm2,XMMWORD[208+r10]
+	por	xmm1,xmm5
+	pand	xmm3,XMMWORD[224+r10]
+	por	xmm0,xmm2
+	por	xmm1,xmm3
+	movdqa	xmm4,XMMWORD[r12]
+	movdqa	xmm5,XMMWORD[16+r12]
+	movdqa	xmm2,XMMWORD[32+r12]
+	pand	xmm4,XMMWORD[240+r10]
+	movdqa	xmm3,XMMWORD[48+r12]
+	pand	xmm5,XMMWORD[256+r10]
+	por	xmm0,xmm4
+	pand	xmm2,XMMWORD[272+r10]
+	por	xmm1,xmm5
+	pand	xmm3,XMMWORD[288+r10]
+	por	xmm0,xmm2
+	por	xmm1,xmm3
+	por	xmm0,xmm1
+	pshufd	xmm1,xmm0,0x4e
+	por	xmm0,xmm1
 	lea	r12,[256+r12]
-	por	xmm0,xmm3
-
 DB	102,72,15,126,195
 
 	mov	r8,QWORD[r8]
@@ -82,29 +218,14 @@
 	xor	r14,r14
 	xor	r15,r15
 
-	movq	xmm0,QWORD[(((-96)))+r12]
-	movq	xmm1,QWORD[((-32))+r12]
-	pand	xmm0,xmm4
-	movq	xmm2,QWORD[32+r12]
-	pand	xmm1,xmm5
-
 	mov	rbp,r8
 	mul	rbx
 	mov	r10,rax
 	mov	rax,QWORD[rcx]
 
-	movq	xmm3,QWORD[96+r12]
-	pand	xmm2,xmm6
-	por	xmm0,xmm1
-	pand	xmm3,xmm7
-
 	imul	rbp,r10
 	mov	r11,rdx
 
-	por	xmm0,xmm2
-	lea	r12,[256+r12]
-	por	xmm0,xmm3
-
 	mul	rbp
 	add	r10,rax
 	mov	rax,QWORD[8+rsi]
@@ -137,14 +258,12 @@
 	cmp	r15,r9
 	jne	NEAR $L$1st
 
-DB	102,72,15,126,195
 
 	add	r13,rax
-	mov	rax,QWORD[rsi]
 	adc	rdx,0
 	add	r13,r11
 	adc	rdx,0
-	mov	QWORD[((-16))+r15*8+rsp],r13
+	mov	QWORD[((-16))+r9*8+rsp],r13
 	mov	r13,rdx
 	mov	r11,r10
 
@@ -158,33 +277,78 @@
 	jmp	NEAR $L$outer
 ALIGN	16
 $L$outer:
+	lea	rdx,[((24+128))+r9*8+rsp]
+	and	rdx,-16
+	pxor	xmm4,xmm4
+	pxor	xmm5,xmm5
+	movdqa	xmm0,XMMWORD[((-128))+r12]
+	movdqa	xmm1,XMMWORD[((-112))+r12]
+	movdqa	xmm2,XMMWORD[((-96))+r12]
+	movdqa	xmm3,XMMWORD[((-80))+r12]
+	pand	xmm0,XMMWORD[((-128))+rdx]
+	pand	xmm1,XMMWORD[((-112))+rdx]
+	por	xmm4,xmm0
+	pand	xmm2,XMMWORD[((-96))+rdx]
+	por	xmm5,xmm1
+	pand	xmm3,XMMWORD[((-80))+rdx]
+	por	xmm4,xmm2
+	por	xmm5,xmm3
+	movdqa	xmm0,XMMWORD[((-64))+r12]
+	movdqa	xmm1,XMMWORD[((-48))+r12]
+	movdqa	xmm2,XMMWORD[((-32))+r12]
+	movdqa	xmm3,XMMWORD[((-16))+r12]
+	pand	xmm0,XMMWORD[((-64))+rdx]
+	pand	xmm1,XMMWORD[((-48))+rdx]
+	por	xmm4,xmm0
+	pand	xmm2,XMMWORD[((-32))+rdx]
+	por	xmm5,xmm1
+	pand	xmm3,XMMWORD[((-16))+rdx]
+	por	xmm4,xmm2
+	por	xmm5,xmm3
+	movdqa	xmm0,XMMWORD[r12]
+	movdqa	xmm1,XMMWORD[16+r12]
+	movdqa	xmm2,XMMWORD[32+r12]
+	movdqa	xmm3,XMMWORD[48+r12]
+	pand	xmm0,XMMWORD[rdx]
+	pand	xmm1,XMMWORD[16+rdx]
+	por	xmm4,xmm0
+	pand	xmm2,XMMWORD[32+rdx]
+	por	xmm5,xmm1
+	pand	xmm3,XMMWORD[48+rdx]
+	por	xmm4,xmm2
+	por	xmm5,xmm3
+	movdqa	xmm0,XMMWORD[64+r12]
+	movdqa	xmm1,XMMWORD[80+r12]
+	movdqa	xmm2,XMMWORD[96+r12]
+	movdqa	xmm3,XMMWORD[112+r12]
+	pand	xmm0,XMMWORD[64+rdx]
+	pand	xmm1,XMMWORD[80+rdx]
+	por	xmm4,xmm0
+	pand	xmm2,XMMWORD[96+rdx]
+	por	xmm5,xmm1
+	pand	xmm3,XMMWORD[112+rdx]
+	por	xmm4,xmm2
+	por	xmm5,xmm3
+	por	xmm4,xmm5
+	pshufd	xmm0,xmm4,0x4e
+	por	xmm0,xmm4
+	lea	r12,[256+r12]
+
+	mov	rax,QWORD[rsi]
+DB	102,72,15,126,195
+
 	xor	r15,r15
 	mov	rbp,r8
 	mov	r10,QWORD[rsp]
 
-	movq	xmm0,QWORD[(((-96)))+r12]
-	movq	xmm1,QWORD[((-32))+r12]
-	pand	xmm0,xmm4
-	movq	xmm2,QWORD[32+r12]
-	pand	xmm1,xmm5
-
 	mul	rbx
 	add	r10,rax
 	mov	rax,QWORD[rcx]
 	adc	rdx,0
 
-	movq	xmm3,QWORD[96+r12]
-	pand	xmm2,xmm6
-	por	xmm0,xmm1
-	pand	xmm3,xmm7
-
 	imul	rbp,r10
 	mov	r11,rdx
 
-	por	xmm0,xmm2
-	lea	r12,[256+r12]
-	por	xmm0,xmm3
-
 	mul	rbp
 	add	r10,rax
 	mov	rax,QWORD[8+rsi]
@@ -220,15 +384,12 @@
 	cmp	r15,r9
 	jne	NEAR $L$inner
 
-DB	102,72,15,126,195
-
 	add	r13,rax
-	mov	rax,QWORD[rsi]
 	adc	rdx,0
 	add	r13,r10
-	mov	r10,QWORD[r15*8+rsp]
+	mov	r10,QWORD[r9*8+rsp]
 	adc	rdx,0
-	mov	QWORD[((-16))+r15*8+rsp],r13
+	mov	QWORD[((-16))+r9*8+rsp],r13
 	mov	r13,rdx
 
 	xor	rdx,rdx
@@ -258,35 +419,44 @@
 
 	sbb	rax,0
 	xor	r14,r14
+	and	rsi,rax
+	not	rax
+	mov	rcx,rdi
+	and	rcx,rax
 	mov	r15,r9
+	or	rsi,rcx
 ALIGN	16
 $L$copy:
-	mov	rsi,QWORD[r14*8+rsp]
-	mov	rcx,QWORD[r14*8+rdi]
-	xor	rsi,rcx
-	and	rsi,rax
-	xor	rsi,rcx
+	mov	rax,QWORD[r14*8+rsi]
 	mov	QWORD[r14*8+rsp],r14
-	mov	QWORD[r14*8+rdi],rsi
+	mov	QWORD[r14*8+rdi],rax
 	lea	r14,[1+r14]
 	sub	r15,1
 	jnz	NEAR $L$copy
 
 	mov	rsi,QWORD[8+r9*8+rsp]
+
 	mov	rax,1
-	movaps	xmm6,XMMWORD[((-88))+rsi]
-	movaps	xmm7,XMMWORD[((-72))+rsi]
+
 	mov	r15,QWORD[((-48))+rsi]
+
 	mov	r14,QWORD[((-40))+rsi]
+
 	mov	r13,QWORD[((-32))+rsi]
+
 	mov	r12,QWORD[((-24))+rsi]
+
 	mov	rbp,QWORD[((-16))+rsi]
+
 	mov	rbx,QWORD[((-8))+rsi]
+
 	lea	rsp,[rsi]
+
 $L$mul_epilogue:
 	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
 	mov	rsi,QWORD[16+rsp]
 	DB	0F3h,0C3h		;repret
+
 $L$SEH_end_bn_mul_mont_gather5:
 
 ALIGN	32
@@ -303,22 +473,28 @@
 	mov	r9,QWORD[48+rsp]
 
 
-$L$mul4x_enter:
+
 DB	0x67
 	mov	rax,rsp
+
+$L$mul4x_enter:
 	push	rbx
+
 	push	rbp
+
 	push	r12
+
 	push	r13
+
 	push	r14
+
 	push	r15
-	lea	rsp,[((-40))+rsp]
-	movaps	XMMWORD[rsp],xmm6
-	movaps	XMMWORD[16+rsp],xmm7
+
+$L$mul4x_prologue:
+
 DB	0x67
-	mov	r10d,r9d
 	shl	r9d,3
-	shl	r10d,3+2
+	lea	r10,[r9*2+r9]
 	neg	r9
 
 
@@ -328,94 +504,216 @@
 
 
 
-	lea	r11,[((-64))+r9*2+rsp]
-	sub	r11,rsi
+
+
+	lea	r11,[((-320))+r9*2+rsp]
+	mov	rbp,rsp
+	sub	r11,rdi
 	and	r11,4095
 	cmp	r10,r11
 	jb	NEAR $L$mul4xsp_alt
-	sub	rsp,r11
-	lea	rsp,[((-64))+r9*2+rsp]
+	sub	rbp,r11
+	lea	rbp,[((-320))+r9*2+rbp]
 	jmp	NEAR $L$mul4xsp_done
 
 ALIGN	32
 $L$mul4xsp_alt:
-	lea	r10,[((4096-64))+r9*2]
-	lea	rsp,[((-64))+r9*2+rsp]
+	lea	r10,[((4096-320))+r9*2]
+	lea	rbp,[((-320))+r9*2+rbp]
 	sub	r11,r10
 	mov	r10,0
 	cmovc	r11,r10
-	sub	rsp,r11
+	sub	rbp,r11
 $L$mul4xsp_done:
-	and	rsp,-64
+	and	rbp,-64
+	mov	r11,rsp
+	sub	r11,rbp
+	and	r11,-4096
+	lea	rsp,[rbp*1+r11]
+	mov	r10,QWORD[rsp]
+	cmp	rsp,rbp
+	ja	NEAR $L$mul4x_page_walk
+	jmp	NEAR $L$mul4x_page_walk_done
+
+$L$mul4x_page_walk:
+	lea	rsp,[((-4096))+rsp]
+	mov	r10,QWORD[rsp]
+	cmp	rsp,rbp
+	ja	NEAR $L$mul4x_page_walk
+$L$mul4x_page_walk_done:
+
 	neg	r9
 
 	mov	QWORD[40+rsp],rax
+
 $L$mul4x_body:
 
 	call	mul4x_internal
 
 	mov	rsi,QWORD[40+rsp]
+
 	mov	rax,1
-	movaps	xmm6,XMMWORD[((-88))+rsi]
-	movaps	xmm7,XMMWORD[((-72))+rsi]
+
 	mov	r15,QWORD[((-48))+rsi]
+
 	mov	r14,QWORD[((-40))+rsi]
+
 	mov	r13,QWORD[((-32))+rsi]
+
 	mov	r12,QWORD[((-24))+rsi]
+
 	mov	rbp,QWORD[((-16))+rsi]
+
 	mov	rbx,QWORD[((-8))+rsi]
+
 	lea	rsp,[rsi]
+
 $L$mul4x_epilogue:
 	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
 	mov	rsi,QWORD[16+rsp]
 	DB	0F3h,0C3h		;repret
+
 $L$SEH_end_bn_mul4x_mont_gather5:
 
 
 ALIGN	32
 mul4x_internal:
 	shl	r9,5
-	mov	r10d,DWORD[56+rax]
-	lea	r13,[256+r9*1+rdx]
+	movd	xmm5,DWORD[56+rax]
+	lea	rax,[$L$inc]
+	lea	r13,[128+r9*1+rdx]
 	shr	r9,5
-	mov	r11,r10
-	shr	r10,3
-	and	r11,7
-	not	r10
-	lea	rax,[$L$magic_masks]
-	and	r10,3
-	lea	r12,[96+r11*8+rdx]
-	movq	xmm4,QWORD[r10*8+rax]
-	movq	xmm5,QWORD[8+r10*8+rax]
-	add	r11,7
-	movq	xmm6,QWORD[16+r10*8+rax]
-	movq	xmm7,QWORD[24+r10*8+rax]
-	and	r11,7
+	movdqa	xmm0,XMMWORD[rax]
+	movdqa	xmm1,XMMWORD[16+rax]
+	lea	r10,[((88-112))+r9*1+rsp]
+	lea	r12,[128+rdx]
 
-	movq	xmm0,QWORD[(((-96)))+r12]
-	lea	r14,[256+r12]
-	movq	xmm1,QWORD[((-32))+r12]
-	pand	xmm0,xmm4
-	movq	xmm2,QWORD[32+r12]
-	pand	xmm1,xmm5
-	movq	xmm3,QWORD[96+r12]
-	pand	xmm2,xmm6
+	pshufd	xmm5,xmm5,0
+	movdqa	xmm4,xmm1
+DB	0x67,0x67
+	movdqa	xmm2,xmm1
+	paddd	xmm1,xmm0
+	pcmpeqd	xmm0,xmm5
 DB	0x67
-	por	xmm0,xmm1
-	movq	xmm1,QWORD[((-96))+r14]
+	movdqa	xmm3,xmm4
+	paddd	xmm2,xmm1
+	pcmpeqd	xmm1,xmm5
+	movdqa	XMMWORD[112+r10],xmm0
+	movdqa	xmm0,xmm4
+
+	paddd	xmm3,xmm2
+	pcmpeqd	xmm2,xmm5
+	movdqa	XMMWORD[128+r10],xmm1
+	movdqa	xmm1,xmm4
+
+	paddd	xmm0,xmm3
+	pcmpeqd	xmm3,xmm5
+	movdqa	XMMWORD[144+r10],xmm2
+	movdqa	xmm2,xmm4
+
+	paddd	xmm1,xmm0
+	pcmpeqd	xmm0,xmm5
+	movdqa	XMMWORD[160+r10],xmm3
+	movdqa	xmm3,xmm4
+	paddd	xmm2,xmm1
+	pcmpeqd	xmm1,xmm5
+	movdqa	XMMWORD[176+r10],xmm0
+	movdqa	xmm0,xmm4
+
+	paddd	xmm3,xmm2
+	pcmpeqd	xmm2,xmm5
+	movdqa	XMMWORD[192+r10],xmm1
+	movdqa	xmm1,xmm4
+
+	paddd	xmm0,xmm3
+	pcmpeqd	xmm3,xmm5
+	movdqa	XMMWORD[208+r10],xmm2
+	movdqa	xmm2,xmm4
+
+	paddd	xmm1,xmm0
+	pcmpeqd	xmm0,xmm5
+	movdqa	XMMWORD[224+r10],xmm3
+	movdqa	xmm3,xmm4
+	paddd	xmm2,xmm1
+	pcmpeqd	xmm1,xmm5
+	movdqa	XMMWORD[240+r10],xmm0
+	movdqa	xmm0,xmm4
+
+	paddd	xmm3,xmm2
+	pcmpeqd	xmm2,xmm5
+	movdqa	XMMWORD[256+r10],xmm1
+	movdqa	xmm1,xmm4
+
+	paddd	xmm0,xmm3
+	pcmpeqd	xmm3,xmm5
+	movdqa	XMMWORD[272+r10],xmm2
+	movdqa	xmm2,xmm4
+
+	paddd	xmm1,xmm0
+	pcmpeqd	xmm0,xmm5
+	movdqa	XMMWORD[288+r10],xmm3
+	movdqa	xmm3,xmm4
+	paddd	xmm2,xmm1
+	pcmpeqd	xmm1,xmm5
+	movdqa	XMMWORD[304+r10],xmm0
+
+	paddd	xmm3,xmm2
 DB	0x67
-	pand	xmm3,xmm7
-DB	0x67
+	pcmpeqd	xmm2,xmm5
+	movdqa	XMMWORD[320+r10],xmm1
+
+	pcmpeqd	xmm3,xmm5
+	movdqa	XMMWORD[336+r10],xmm2
+	pand	xmm0,XMMWORD[64+r12]
+
+	pand	xmm1,XMMWORD[80+r12]
+	pand	xmm2,XMMWORD[96+r12]
+	movdqa	XMMWORD[352+r10],xmm3
+	pand	xmm3,XMMWORD[112+r12]
 	por	xmm0,xmm2
-	movq	xmm2,QWORD[((-32))+r14]
-DB	0x67
-	pand	xmm1,xmm4
-DB	0x67
-	por	xmm0,xmm3
-	movq	xmm3,QWORD[32+r14]
-
+	por	xmm1,xmm3
+	movdqa	xmm4,XMMWORD[((-128))+r12]
+	movdqa	xmm5,XMMWORD[((-112))+r12]
+	movdqa	xmm2,XMMWORD[((-96))+r12]
+	pand	xmm4,XMMWORD[112+r10]
+	movdqa	xmm3,XMMWORD[((-80))+r12]
+	pand	xmm5,XMMWORD[128+r10]
+	por	xmm0,xmm4
+	pand	xmm2,XMMWORD[144+r10]
+	por	xmm1,xmm5
+	pand	xmm3,XMMWORD[160+r10]
+	por	xmm0,xmm2
+	por	xmm1,xmm3
+	movdqa	xmm4,XMMWORD[((-64))+r12]
+	movdqa	xmm5,XMMWORD[((-48))+r12]
+	movdqa	xmm2,XMMWORD[((-32))+r12]
+	pand	xmm4,XMMWORD[176+r10]
+	movdqa	xmm3,XMMWORD[((-16))+r12]
+	pand	xmm5,XMMWORD[192+r10]
+	por	xmm0,xmm4
+	pand	xmm2,XMMWORD[208+r10]
+	por	xmm1,xmm5
+	pand	xmm3,XMMWORD[224+r10]
+	por	xmm0,xmm2
+	por	xmm1,xmm3
+	movdqa	xmm4,XMMWORD[r12]
+	movdqa	xmm5,XMMWORD[16+r12]
+	movdqa	xmm2,XMMWORD[32+r12]
+	pand	xmm4,XMMWORD[240+r10]
+	movdqa	xmm3,XMMWORD[48+r12]
+	pand	xmm5,XMMWORD[256+r10]
+	por	xmm0,xmm4
+	pand	xmm2,XMMWORD[272+r10]
+	por	xmm1,xmm5
+	pand	xmm3,XMMWORD[288+r10]
+	por	xmm0,xmm2
+	por	xmm1,xmm3
+	por	xmm0,xmm1
+	pshufd	xmm1,xmm0,0x4e
+	por	xmm0,xmm1
+	lea	r12,[256+r12]
 DB	102,72,15,126,195
-	movq	xmm0,QWORD[96+r14]
+
 	mov	QWORD[((16+8))+rsp],r13
 	mov	QWORD[((56+8))+rsp],rdi
 
@@ -429,26 +727,10 @@
 	mov	r10,rax
 	mov	rax,QWORD[rcx]
 
-	pand	xmm2,xmm5
-	pand	xmm3,xmm6
-	por	xmm1,xmm2
-
 	imul	rbp,r10
-
-
-
-
-
-
-
-	lea	r14,[((64+8))+r11*8+rsp]
+	lea	r14,[((64+8))+rsp]
 	mov	r11,rdx
 
-	pand	xmm0,xmm7
-	por	xmm1,xmm3
-	lea	r12,[512+r12]
-	por	xmm0,xmm1
-
 	mul	rbp
 	add	r10,rax
 	mov	rax,QWORD[8+r9*1+rsi]
@@ -457,7 +739,7 @@
 
 	mul	rbx
 	add	r11,rax
-	mov	rax,QWORD[16+rcx]
+	mov	rax,QWORD[8+rcx]
 	adc	rdx,0
 	mov	r10,rdx
 
@@ -467,7 +749,7 @@
 	adc	rdx,0
 	add	rdi,r11
 	lea	r15,[32+r9]
-	lea	rcx,[64+rcx]
+	lea	rcx,[32+rcx]
 	adc	rdx,0
 	mov	QWORD[r14],rdi
 	mov	r13,rdx
@@ -477,7 +759,7 @@
 $L$1st4x:
 	mul	rbx
 	add	r10,rax
-	mov	rax,QWORD[((-32))+rcx]
+	mov	rax,QWORD[((-16))+rcx]
 	lea	r14,[32+r14]
 	adc	rdx,0
 	mov	r11,rdx
@@ -493,7 +775,7 @@
 
 	mul	rbx
 	add	r11,rax
-	mov	rax,QWORD[((-16))+rcx]
+	mov	rax,QWORD[((-8))+rcx]
 	adc	rdx,0
 	mov	r10,rdx
 
@@ -523,7 +805,7 @@
 
 	mul	rbx
 	add	r11,rax
-	mov	rax,QWORD[16+rcx]
+	mov	rax,QWORD[8+rcx]
 	adc	rdx,0
 	mov	r10,rdx
 
@@ -532,7 +814,7 @@
 	mov	rax,QWORD[16+r15*1+rsi]
 	adc	rdx,0
 	add	rdi,r11
-	lea	rcx,[64+rcx]
+	lea	rcx,[32+rcx]
 	adc	rdx,0
 	mov	QWORD[r14],rdi
 	mov	r13,rdx
@@ -542,7 +824,7 @@
 
 	mul	rbx
 	add	r10,rax
-	mov	rax,QWORD[((-32))+rcx]
+	mov	rax,QWORD[((-16))+rcx]
 	lea	r14,[32+r14]
 	adc	rdx,0
 	mov	r11,rdx
@@ -558,7 +840,7 @@
 
 	mul	rbx
 	add	r11,rax
-	mov	rax,QWORD[((-16))+rcx]
+	mov	rax,QWORD[((-8))+rcx]
 	adc	rdx,0
 	mov	r10,rdx
 
@@ -571,8 +853,7 @@
 	mov	QWORD[((-16))+r14],rdi
 	mov	r13,rdx
 
-DB	102,72,15,126,195
-	lea	rcx,[r9*2+rcx]
+	lea	rcx,[r9*1+rcx]
 
 	xor	rdi,rdi
 	add	r13,r10
@@ -583,6 +864,63 @@
 
 ALIGN	32
 $L$outer4x:
+	lea	rdx,[((16+128))+r14]
+	pxor	xmm4,xmm4
+	pxor	xmm5,xmm5
+	movdqa	xmm0,XMMWORD[((-128))+r12]
+	movdqa	xmm1,XMMWORD[((-112))+r12]
+	movdqa	xmm2,XMMWORD[((-96))+r12]
+	movdqa	xmm3,XMMWORD[((-80))+r12]
+	pand	xmm0,XMMWORD[((-128))+rdx]
+	pand	xmm1,XMMWORD[((-112))+rdx]
+	por	xmm4,xmm0
+	pand	xmm2,XMMWORD[((-96))+rdx]
+	por	xmm5,xmm1
+	pand	xmm3,XMMWORD[((-80))+rdx]
+	por	xmm4,xmm2
+	por	xmm5,xmm3
+	movdqa	xmm0,XMMWORD[((-64))+r12]
+	movdqa	xmm1,XMMWORD[((-48))+r12]
+	movdqa	xmm2,XMMWORD[((-32))+r12]
+	movdqa	xmm3,XMMWORD[((-16))+r12]
+	pand	xmm0,XMMWORD[((-64))+rdx]
+	pand	xmm1,XMMWORD[((-48))+rdx]
+	por	xmm4,xmm0
+	pand	xmm2,XMMWORD[((-32))+rdx]
+	por	xmm5,xmm1
+	pand	xmm3,XMMWORD[((-16))+rdx]
+	por	xmm4,xmm2
+	por	xmm5,xmm3
+	movdqa	xmm0,XMMWORD[r12]
+	movdqa	xmm1,XMMWORD[16+r12]
+	movdqa	xmm2,XMMWORD[32+r12]
+	movdqa	xmm3,XMMWORD[48+r12]
+	pand	xmm0,XMMWORD[rdx]
+	pand	xmm1,XMMWORD[16+rdx]
+	por	xmm4,xmm0
+	pand	xmm2,XMMWORD[32+rdx]
+	por	xmm5,xmm1
+	pand	xmm3,XMMWORD[48+rdx]
+	por	xmm4,xmm2
+	por	xmm5,xmm3
+	movdqa	xmm0,XMMWORD[64+r12]
+	movdqa	xmm1,XMMWORD[80+r12]
+	movdqa	xmm2,XMMWORD[96+r12]
+	movdqa	xmm3,XMMWORD[112+r12]
+	pand	xmm0,XMMWORD[64+rdx]
+	pand	xmm1,XMMWORD[80+rdx]
+	por	xmm4,xmm0
+	pand	xmm2,XMMWORD[96+rdx]
+	por	xmm5,xmm1
+	pand	xmm3,XMMWORD[112+rdx]
+	por	xmm4,xmm2
+	por	xmm5,xmm3
+	por	xmm4,xmm5
+	pshufd	xmm0,xmm4,0x4e
+	por	xmm0,xmm4
+	lea	r12,[256+r12]
+DB	102,72,15,126,195
+
 	mov	r10,QWORD[r9*1+r14]
 	mov	rbp,r8
 	mul	rbx
@@ -590,25 +928,11 @@
 	mov	rax,QWORD[rcx]
 	adc	rdx,0
 
-	movq	xmm0,QWORD[(((-96)))+r12]
-	movq	xmm1,QWORD[((-32))+r12]
-	pand	xmm0,xmm4
-	movq	xmm2,QWORD[32+r12]
-	pand	xmm1,xmm5
-	movq	xmm3,QWORD[96+r12]
-
 	imul	rbp,r10
-DB	0x67
 	mov	r11,rdx
 	mov	QWORD[r14],rdi
 
-	pand	xmm2,xmm6
-	por	xmm0,xmm1
-	pand	xmm3,xmm7
-	por	xmm0,xmm2
 	lea	r14,[r9*1+r14]
-	lea	r12,[256+r12]
-	por	xmm0,xmm3
 
 	mul	rbp
 	add	r10,rax
@@ -618,7 +942,7 @@
 
 	mul	rbx
 	add	r11,rax
-	mov	rax,QWORD[16+rcx]
+	mov	rax,QWORD[8+rcx]
 	adc	rdx,0
 	add	r11,QWORD[8+r14]
 	adc	rdx,0
@@ -630,7 +954,7 @@
 	adc	rdx,0
 	add	rdi,r11
 	lea	r15,[32+r9]
-	lea	rcx,[64+rcx]
+	lea	rcx,[32+rcx]
 	adc	rdx,0
 	mov	r13,rdx
 	jmp	NEAR $L$inner4x
@@ -639,7 +963,7 @@
 $L$inner4x:
 	mul	rbx
 	add	r10,rax
-	mov	rax,QWORD[((-32))+rcx]
+	mov	rax,QWORD[((-16))+rcx]
 	adc	rdx,0
 	add	r10,QWORD[16+r14]
 	lea	r14,[32+r14]
@@ -657,7 +981,7 @@
 
 	mul	rbx
 	add	r11,rax
-	mov	rax,QWORD[((-16))+rcx]
+	mov	rax,QWORD[((-8))+rcx]
 	adc	rdx,0
 	add	r11,QWORD[((-8))+r14]
 	adc	rdx,0
@@ -691,7 +1015,7 @@
 
 	mul	rbx
 	add	r11,rax
-	mov	rax,QWORD[16+rcx]
+	mov	rax,QWORD[8+rcx]
 	adc	rdx,0
 	add	r11,QWORD[8+r14]
 	adc	rdx,0
@@ -702,7 +1026,7 @@
 	mov	rax,QWORD[16+r15*1+rsi]
 	adc	rdx,0
 	add	rdi,r11
-	lea	rcx,[64+rcx]
+	lea	rcx,[32+rcx]
 	adc	rdx,0
 	mov	QWORD[((-8))+r14],r13
 	mov	r13,rdx
@@ -712,7 +1036,7 @@
 
 	mul	rbx
 	add	r10,rax
-	mov	rax,QWORD[((-32))+rcx]
+	mov	rax,QWORD[((-16))+rcx]
 	adc	rdx,0
 	add	r10,QWORD[16+r14]
 	lea	r14,[32+r14]
@@ -731,7 +1055,7 @@
 	mul	rbx
 	add	r11,rax
 	mov	rax,rbp
-	mov	rbp,QWORD[((-16))+rcx]
+	mov	rbp,QWORD[((-8))+rcx]
 	adc	rdx,0
 	add	r11,QWORD[((-8))+r14]
 	adc	rdx,0
@@ -746,9 +1070,8 @@
 	mov	QWORD[((-24))+r14],r13
 	mov	r13,rdx
 
-DB	102,72,15,126,195
 	mov	QWORD[((-16))+r14],rdi
-	lea	rcx,[r9*2+rcx]
+	lea	rcx,[r9*1+rcx]
 
 	xor	rdi,rdi
 	add	r13,r10
@@ -759,16 +1082,23 @@
 
 	cmp	r12,QWORD[((16+8))+rsp]
 	jb	NEAR $L$outer4x
+	xor	rax,rax
 	sub	rbp,r13
 	adc	r15,r15
 	or	rdi,r15
-	xor	rdi,1
+	sub	rax,rdi
 	lea	rbx,[r9*1+r14]
-	lea	rbp,[rdi*8+rcx]
+	mov	r12,QWORD[rcx]
+	lea	rbp,[rcx]
 	mov	rcx,r9
 	sar	rcx,3+2
 	mov	rdi,QWORD[((56+8))+rsp]
-	jmp	NEAR $L$sqr4x_sub
+	dec	r12
+	xor	r10,r10
+	mov	r13,QWORD[8+rbp]
+	mov	r14,QWORD[16+rbp]
+	mov	r15,QWORD[24+rbp]
+	jmp	NEAR $L$sqr4x_sub_entry
 
 global	bn_power5
 
@@ -786,19 +1116,25 @@
 	mov	r9,QWORD[48+rsp]
 
 
+
 	mov	rax,rsp
+
 	push	rbx
+
 	push	rbp
+
 	push	r12
+
 	push	r13
+
 	push	r14
+
 	push	r15
-	lea	rsp,[((-40))+rsp]
-	movaps	XMMWORD[rsp],xmm6
-	movaps	XMMWORD[16+rsp],xmm7
-	mov	r10d,r9d
+
+$L$power5_prologue:
+
 	shl	r9d,3
-	shl	r10d,3+2
+	lea	r10d,[r9*2+r9]
 	neg	r9
 	mov	r8,QWORD[r8]
 
@@ -808,25 +1144,43 @@
 
 
 
-	lea	r11,[((-64))+r9*2+rsp]
-	sub	r11,rsi
+
+	lea	r11,[((-320))+r9*2+rsp]
+	mov	rbp,rsp
+	sub	r11,rdi
 	and	r11,4095
 	cmp	r10,r11
 	jb	NEAR $L$pwr_sp_alt
-	sub	rsp,r11
-	lea	rsp,[((-64))+r9*2+rsp]
+	sub	rbp,r11
+	lea	rbp,[((-320))+r9*2+rbp]
 	jmp	NEAR $L$pwr_sp_done
 
 ALIGN	32
 $L$pwr_sp_alt:
-	lea	r10,[((4096-64))+r9*2]
-	lea	rsp,[((-64))+r9*2+rsp]
+	lea	r10,[((4096-320))+r9*2]
+	lea	rbp,[((-320))+r9*2+rbp]
 	sub	r11,r10
 	mov	r10,0
 	cmovc	r11,r10
-	sub	rsp,r11
+	sub	rbp,r11
 $L$pwr_sp_done:
-	and	rsp,-64
+	and	rbp,-64
+	mov	r11,rsp
+	sub	r11,rbp
+	and	r11,-4096
+	lea	rsp,[rbp*1+r11]
+	mov	r10,QWORD[rsp]
+	cmp	rsp,rbp
+	ja	NEAR $L$pwr_page_walk
+	jmp	NEAR $L$pwr_page_walk_done
+
+$L$pwr_page_walk:
+	lea	rsp,[((-4096))+rsp]
+	mov	r10,QWORD[rsp]
+	cmp	rsp,rbp
+	ja	NEAR $L$pwr_page_walk
+$L$pwr_page_walk_done:
+
 	mov	r10,r9
 	neg	r9
 
@@ -841,6 +1195,7 @@
 
 	mov	QWORD[32+rsp],r8
 	mov	QWORD[40+rsp],rax
+
 $L$power5_body:
 DB	102,72,15,110,207
 DB	102,72,15,110,209
@@ -848,10 +1203,15 @@
 DB	102,72,15,110,226
 
 	call	__bn_sqr8x_internal
+	call	__bn_post4x_internal
 	call	__bn_sqr8x_internal
+	call	__bn_post4x_internal
 	call	__bn_sqr8x_internal
+	call	__bn_post4x_internal
 	call	__bn_sqr8x_internal
+	call	__bn_post4x_internal
 	call	__bn_sqr8x_internal
+	call	__bn_post4x_internal
 
 DB	102,72,15,126,209
 DB	102,72,15,126,226
@@ -862,18 +1222,27 @@
 	call	mul4x_internal
 
 	mov	rsi,QWORD[40+rsp]
+
 	mov	rax,1
 	mov	r15,QWORD[((-48))+rsi]
+
 	mov	r14,QWORD[((-40))+rsi]
+
 	mov	r13,QWORD[((-32))+rsi]
+
 	mov	r12,QWORD[((-24))+rsi]
+
 	mov	rbp,QWORD[((-16))+rsi]
+
 	mov	rbx,QWORD[((-8))+rsi]
+
 	lea	rsp,[rsi]
+
 $L$power5_epilogue:
 	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
 	mov	rsi,QWORD[16+rsp]
 	DB	0F3h,0C3h		;repret
+
 $L$SEH_end_bn_power5:
 
 global	bn_sqr8x_internal
@@ -1397,9 +1766,9 @@
 	mov	QWORD[((-16))+rdi],rbx
 	mov	QWORD[((-8))+rdi],r8
 DB	102,72,15,126,213
-sqr8x_reduction:
+__bn_sqr8x_reduction:
 	xor	rax,rax
-	lea	rcx,[r9*2+rbp]
+	lea	rcx,[rbp*1+r9]
 	lea	rdx,[((48+8))+r9*2+rsp]
 	mov	QWORD[((0+8))+rsp],rcx
 	lea	rdi,[((48+8))+r9*1+rsp]
@@ -1432,14 +1801,14 @@
 ALIGN	32
 $L$8x_reduce:
 	mul	rbx
-	mov	rax,QWORD[16+rbp]
+	mov	rax,QWORD[8+rbp]
 	neg	r8
 	mov	r8,rdx
 	adc	r8,0
 
 	mul	rbx
 	add	r9,rax
-	mov	rax,QWORD[32+rbp]
+	mov	rax,QWORD[16+rbp]
 	adc	rdx,0
 	add	r8,r9
 	mov	QWORD[((48-8+8))+rcx*8+rsp],rbx
@@ -1448,7 +1817,7 @@
 
 	mul	rbx
 	add	r10,rax
-	mov	rax,QWORD[48+rbp]
+	mov	rax,QWORD[24+rbp]
 	adc	rdx,0
 	add	r9,r10
 	mov	rsi,QWORD[((32+8))+rsp]
@@ -1457,7 +1826,7 @@
 
 	mul	rbx
 	add	r11,rax
-	mov	rax,QWORD[64+rbp]
+	mov	rax,QWORD[32+rbp]
 	adc	rdx,0
 	imul	rsi,r8
 	add	r10,r11
@@ -1466,7 +1835,7 @@
 
 	mul	rbx
 	add	r12,rax
-	mov	rax,QWORD[80+rbp]
+	mov	rax,QWORD[40+rbp]
 	adc	rdx,0
 	add	r11,r12
 	mov	r12,rdx
@@ -1474,7 +1843,7 @@
 
 	mul	rbx
 	add	r13,rax
-	mov	rax,QWORD[96+rbp]
+	mov	rax,QWORD[48+rbp]
 	adc	rdx,0
 	add	r12,r13
 	mov	r13,rdx
@@ -1482,7 +1851,7 @@
 
 	mul	rbx
 	add	r14,rax
-	mov	rax,QWORD[112+rbp]
+	mov	rax,QWORD[56+rbp]
 	adc	rdx,0
 	add	r13,r14
 	mov	r14,rdx
@@ -1500,7 +1869,7 @@
 	dec	ecx
 	jnz	NEAR $L$8x_reduce
 
-	lea	rbp,[128+rbp]
+	lea	rbp,[64+rbp]
 	xor	rax,rax
 	mov	rdx,QWORD[((8+8))+rsp]
 	cmp	rbp,QWORD[((0+8))+rsp]
@@ -1526,14 +1895,14 @@
 $L$8x_tail:
 	mul	rbx
 	add	r8,rax
-	mov	rax,QWORD[16+rbp]
+	mov	rax,QWORD[8+rbp]
 	mov	QWORD[rdi],r8
 	mov	r8,rdx
 	adc	r8,0
 
 	mul	rbx
 	add	r9,rax
-	mov	rax,QWORD[32+rbp]
+	mov	rax,QWORD[16+rbp]
 	adc	rdx,0
 	add	r8,r9
 	lea	rdi,[8+rdi]
@@ -1542,7 +1911,7 @@
 
 	mul	rbx
 	add	r10,rax
-	mov	rax,QWORD[48+rbp]
+	mov	rax,QWORD[24+rbp]
 	adc	rdx,0
 	add	r9,r10
 	mov	r10,rdx
@@ -1550,7 +1919,7 @@
 
 	mul	rbx
 	add	r11,rax
-	mov	rax,QWORD[64+rbp]
+	mov	rax,QWORD[32+rbp]
 	adc	rdx,0
 	add	r10,r11
 	mov	r11,rdx
@@ -1558,7 +1927,7 @@
 
 	mul	rbx
 	add	r12,rax
-	mov	rax,QWORD[80+rbp]
+	mov	rax,QWORD[40+rbp]
 	adc	rdx,0
 	add	r11,r12
 	mov	r12,rdx
@@ -1566,7 +1935,7 @@
 
 	mul	rbx
 	add	r13,rax
-	mov	rax,QWORD[96+rbp]
+	mov	rax,QWORD[48+rbp]
 	adc	rdx,0
 	add	r12,r13
 	mov	r13,rdx
@@ -1574,7 +1943,7 @@
 
 	mul	rbx
 	add	r14,rax
-	mov	rax,QWORD[112+rbp]
+	mov	rax,QWORD[56+rbp]
 	adc	rdx,0
 	add	r13,r14
 	mov	r14,rdx
@@ -1592,7 +1961,7 @@
 	dec	ecx
 	jnz	NEAR $L$8x_tail
 
-	lea	rbp,[128+rbp]
+	lea	rbp,[64+rbp]
 	mov	rdx,QWORD[((8+8))+rsp]
 	cmp	rbp,QWORD[((0+8))+rsp]
 	jae	NEAR $L$8x_tail_done
@@ -1615,6 +1984,7 @@
 
 ALIGN	32
 $L$8x_tail_done:
+	xor	rax,rax
 	add	r8,QWORD[rdx]
 	adc	r9,0
 	adc	r10,0
@@ -1623,9 +1993,7 @@
 	adc	r13,0
 	adc	r14,0
 	adc	r15,0
-
-
-	xor	rax,rax
+	adc	rax,0
 
 	neg	rsi
 $L$8x_no_tail:
@@ -1638,7 +2006,7 @@
 	adc	r14,QWORD[48+rdi]
 	adc	r15,QWORD[56+rdi]
 	adc	rax,0
-	mov	rcx,QWORD[((-16))+rbp]
+	mov	rcx,QWORD[((-8))+rbp]
 	xor	rsi,rsi
 
 DB	102,72,15,126,213
@@ -1656,40 +2024,58 @@
 
 	cmp	rdi,rdx
 	jb	NEAR $L$8x_reduction_loop
+	DB	0F3h,0C3h		;repret
 
-	sub	rcx,r15
-	lea	rbx,[r9*1+rdi]
-	adc	rsi,rsi
-	mov	rcx,r9
-	or	rax,rsi
-DB	102,72,15,126,207
-	xor	rax,1
-DB	102,72,15,126,206
-	lea	rbp,[rax*8+rbp]
-	sar	rcx,3+2
-	jmp	NEAR $L$sqr4x_sub
 
 ALIGN	32
+__bn_post4x_internal:
+	mov	r12,QWORD[rbp]
+	lea	rbx,[r9*1+rdi]
+	mov	rcx,r9
+DB	102,72,15,126,207
+	neg	rax
+DB	102,72,15,126,206
+	sar	rcx,3+2
+	dec	r12
+	xor	r10,r10
+	mov	r13,QWORD[8+rbp]
+	mov	r14,QWORD[16+rbp]
+	mov	r15,QWORD[24+rbp]
+	jmp	NEAR $L$sqr4x_sub_entry
+
+ALIGN	16
 $L$sqr4x_sub:
-DB	0x66
-	mov	r12,QWORD[rbx]
-	mov	r13,QWORD[8+rbx]
-	sbb	r12,QWORD[rbp]
-	mov	r14,QWORD[16+rbx]
-	sbb	r13,QWORD[16+rbp]
-	mov	r15,QWORD[24+rbx]
-	lea	rbx,[32+rbx]
-	sbb	r14,QWORD[32+rbp]
+	mov	r12,QWORD[rbp]
+	mov	r13,QWORD[8+rbp]
+	mov	r14,QWORD[16+rbp]
+	mov	r15,QWORD[24+rbp]
+$L$sqr4x_sub_entry:
+	lea	rbp,[32+rbp]
+	not	r12
+	not	r13
+	not	r14
+	not	r15
+	and	r12,rax
+	and	r13,rax
+	and	r14,rax
+	and	r15,rax
+
+	neg	r10
+	adc	r12,QWORD[rbx]
+	adc	r13,QWORD[8+rbx]
+	adc	r14,QWORD[16+rbx]
+	adc	r15,QWORD[24+rbx]
 	mov	QWORD[rdi],r12
-	sbb	r15,QWORD[48+rbp]
-	lea	rbp,[64+rbp]
+	lea	rbx,[32+rbx]
 	mov	QWORD[8+rdi],r13
+	sbb	r10,r10
 	mov	QWORD[16+rdi],r14
 	mov	QWORD[24+rdi],r15
 	lea	rdi,[32+rdi]
 
 	inc	rcx
 	jnz	NEAR $L$sqr4x_sub
+
 	mov	r10,r9
 	neg	r9
 	DB	0F3h,0C3h		;repret
@@ -1719,21 +2105,26 @@
 	mov	r9,QWORD[48+rsp]
 
 
+
 DB	0x67
 	mov	rax,rsp
+
 	push	rbx
+
 	push	rbp
+
 	push	r12
+
 	push	r13
+
 	push	r14
+
 	push	r15
-	lea	rsp,[((-40))+rsp]
-	movaps	XMMWORD[rsp],xmm6
-	movaps	XMMWORD[16+rsp],xmm7
-DB	0x67
-	mov	r10d,r9d
+
+$L$from_prologue:
+
 	shl	r9d,3
-	shl	r10d,3+2
+	lea	r10,[r9*2+r9]
 	neg	r9
 	mov	r8,QWORD[r8]
 
@@ -1743,25 +2134,43 @@
 
 
 
-	lea	r11,[((-64))+r9*2+rsp]
-	sub	r11,rsi
+
+	lea	r11,[((-320))+r9*2+rsp]
+	mov	rbp,rsp
+	sub	r11,rdi
 	and	r11,4095
 	cmp	r10,r11
 	jb	NEAR $L$from_sp_alt
-	sub	rsp,r11
-	lea	rsp,[((-64))+r9*2+rsp]
+	sub	rbp,r11
+	lea	rbp,[((-320))+r9*2+rbp]
 	jmp	NEAR $L$from_sp_done
 
 ALIGN	32
 $L$from_sp_alt:
-	lea	r10,[((4096-64))+r9*2]
-	lea	rsp,[((-64))+r9*2+rsp]
+	lea	r10,[((4096-320))+r9*2]
+	lea	rbp,[((-320))+r9*2+rbp]
 	sub	r11,r10
 	mov	r10,0
 	cmovc	r11,r10
-	sub	rsp,r11
+	sub	rbp,r11
 $L$from_sp_done:
-	and	rsp,-64
+	and	rbp,-64
+	mov	r11,rsp
+	sub	r11,rbp
+	and	r11,-4096
+	lea	rsp,[rbp*1+r11]
+	mov	r10,QWORD[rsp]
+	cmp	rsp,rbp
+	ja	NEAR $L$from_page_walk
+	jmp	NEAR $L$from_page_walk_done
+
+$L$from_page_walk:
+	lea	rsp,[((-4096))+rsp]
+	mov	r10,QWORD[rsp]
+	cmp	rsp,rbp
+	ja	NEAR $L$from_page_walk
+$L$from_page_walk_done:
+
 	mov	r10,r9
 	neg	r9
 
@@ -1776,6 +2185,7 @@
 
 	mov	QWORD[32+rsp],r8
 	mov	QWORD[40+rsp],rax
+
 $L$from_body:
 	mov	r11,r9
 	lea	rax,[48+rsp]
@@ -1806,15 +2216,17 @@
 DB	0x67
 	mov	rbp,rcx
 DB	102,73,15,110,218
-	call	sqr8x_reduction
+	call	__bn_sqr8x_reduction
+	call	__bn_post4x_internal
 
 	pxor	xmm0,xmm0
 	lea	rax,[48+rsp]
-	mov	rsi,QWORD[40+rsp]
 	jmp	NEAR $L$from_mont_zero
 
 ALIGN	32
 $L$from_mont_zero:
+	mov	rsi,QWORD[40+rsp]
+
 	movdqa	XMMWORD[rax],xmm0
 	movdqa	XMMWORD[16+rax],xmm0
 	movdqa	XMMWORD[32+rax],xmm0
@@ -1825,16 +2237,24 @@
 
 	mov	rax,1
 	mov	r15,QWORD[((-48))+rsi]
+
 	mov	r14,QWORD[((-40))+rsi]
+
 	mov	r13,QWORD[((-32))+rsi]
+
 	mov	r12,QWORD[((-24))+rsi]
+
 	mov	rbp,QWORD[((-16))+rsi]
+
 	mov	rbx,QWORD[((-8))+rsi]
+
 	lea	rsp,[rsi]
+
 $L$from_epilogue:
 	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
 	mov	rsi,QWORD[16+rsp]
 	DB	0F3h,0C3h		;repret
+
 $L$SEH_end_bn_from_mont8x:
 global	bn_scatter5
 
@@ -1856,55 +2276,171 @@
 
 global	bn_gather5
 
-ALIGN	16
+ALIGN	32
 bn_gather5:
 $L$SEH_begin_bn_gather5:
 
-DB	0x48,0x83,0xec,0x28
-DB	0x0f,0x29,0x34,0x24
-DB	0x0f,0x29,0x7c,0x24,0x10
-	mov	r11d,r9d
-	shr	r9d,3
-	and	r11,7
-	not	r9d
-	lea	rax,[$L$magic_masks]
-	and	r9d,3
-	lea	r8,[128+r11*8+r8]
-	movq	xmm4,QWORD[r9*8+rax]
-	movq	xmm5,QWORD[8+r9*8+rax]
-	movq	xmm6,QWORD[16+r9*8+rax]
-	movq	xmm7,QWORD[24+r9*8+rax]
-	jmp	NEAR $L$gather
-ALIGN	16
-$L$gather:
-	movq	xmm0,QWORD[(((-128)))+r8]
-	movq	xmm1,QWORD[((-64))+r8]
-	pand	xmm0,xmm4
-	movq	xmm2,QWORD[r8]
-	pand	xmm1,xmm5
-	movq	xmm3,QWORD[64+r8]
-	pand	xmm2,xmm6
-	por	xmm0,xmm1
-	pand	xmm3,xmm7
-DB	0x67,0x67
-	por	xmm0,xmm2
-	lea	r8,[256+r8]
-	por	xmm0,xmm3
+DB	0x4c,0x8d,0x14,0x24
+DB	0x48,0x81,0xec,0x08,0x01,0x00,0x00
+	lea	rax,[$L$inc]
+	and	rsp,-16
 
+	movd	xmm5,r9d
+	movdqa	xmm0,XMMWORD[rax]
+	movdqa	xmm1,XMMWORD[16+rax]
+	lea	r11,[128+r8]
+	lea	rax,[128+rsp]
+
+	pshufd	xmm5,xmm5,0
+	movdqa	xmm4,xmm1
+	movdqa	xmm2,xmm1
+	paddd	xmm1,xmm0
+	pcmpeqd	xmm0,xmm5
+	movdqa	xmm3,xmm4
+
+	paddd	xmm2,xmm1
+	pcmpeqd	xmm1,xmm5
+	movdqa	XMMWORD[(-128)+rax],xmm0
+	movdqa	xmm0,xmm4
+
+	paddd	xmm3,xmm2
+	pcmpeqd	xmm2,xmm5
+	movdqa	XMMWORD[(-112)+rax],xmm1
+	movdqa	xmm1,xmm4
+
+	paddd	xmm0,xmm3
+	pcmpeqd	xmm3,xmm5
+	movdqa	XMMWORD[(-96)+rax],xmm2
+	movdqa	xmm2,xmm4
+	paddd	xmm1,xmm0
+	pcmpeqd	xmm0,xmm5
+	movdqa	XMMWORD[(-80)+rax],xmm3
+	movdqa	xmm3,xmm4
+
+	paddd	xmm2,xmm1
+	pcmpeqd	xmm1,xmm5
+	movdqa	XMMWORD[(-64)+rax],xmm0
+	movdqa	xmm0,xmm4
+
+	paddd	xmm3,xmm2
+	pcmpeqd	xmm2,xmm5
+	movdqa	XMMWORD[(-48)+rax],xmm1
+	movdqa	xmm1,xmm4
+
+	paddd	xmm0,xmm3
+	pcmpeqd	xmm3,xmm5
+	movdqa	XMMWORD[(-32)+rax],xmm2
+	movdqa	xmm2,xmm4
+	paddd	xmm1,xmm0
+	pcmpeqd	xmm0,xmm5
+	movdqa	XMMWORD[(-16)+rax],xmm3
+	movdqa	xmm3,xmm4
+
+	paddd	xmm2,xmm1
+	pcmpeqd	xmm1,xmm5
+	movdqa	XMMWORD[rax],xmm0
+	movdqa	xmm0,xmm4
+
+	paddd	xmm3,xmm2
+	pcmpeqd	xmm2,xmm5
+	movdqa	XMMWORD[16+rax],xmm1
+	movdqa	xmm1,xmm4
+
+	paddd	xmm0,xmm3
+	pcmpeqd	xmm3,xmm5
+	movdqa	XMMWORD[32+rax],xmm2
+	movdqa	xmm2,xmm4
+	paddd	xmm1,xmm0
+	pcmpeqd	xmm0,xmm5
+	movdqa	XMMWORD[48+rax],xmm3
+	movdqa	xmm3,xmm4
+
+	paddd	xmm2,xmm1
+	pcmpeqd	xmm1,xmm5
+	movdqa	XMMWORD[64+rax],xmm0
+	movdqa	xmm0,xmm4
+
+	paddd	xmm3,xmm2
+	pcmpeqd	xmm2,xmm5
+	movdqa	XMMWORD[80+rax],xmm1
+	movdqa	xmm1,xmm4
+
+	paddd	xmm0,xmm3
+	pcmpeqd	xmm3,xmm5
+	movdqa	XMMWORD[96+rax],xmm2
+	movdqa	xmm2,xmm4
+	movdqa	XMMWORD[112+rax],xmm3
+	jmp	NEAR $L$gather
+
+ALIGN	32
+$L$gather:
+	pxor	xmm4,xmm4
+	pxor	xmm5,xmm5
+	movdqa	xmm0,XMMWORD[((-128))+r11]
+	movdqa	xmm1,XMMWORD[((-112))+r11]
+	movdqa	xmm2,XMMWORD[((-96))+r11]
+	pand	xmm0,XMMWORD[((-128))+rax]
+	movdqa	xmm3,XMMWORD[((-80))+r11]
+	pand	xmm1,XMMWORD[((-112))+rax]
+	por	xmm4,xmm0
+	pand	xmm2,XMMWORD[((-96))+rax]
+	por	xmm5,xmm1
+	pand	xmm3,XMMWORD[((-80))+rax]
+	por	xmm4,xmm2
+	por	xmm5,xmm3
+	movdqa	xmm0,XMMWORD[((-64))+r11]
+	movdqa	xmm1,XMMWORD[((-48))+r11]
+	movdqa	xmm2,XMMWORD[((-32))+r11]
+	pand	xmm0,XMMWORD[((-64))+rax]
+	movdqa	xmm3,XMMWORD[((-16))+r11]
+	pand	xmm1,XMMWORD[((-48))+rax]
+	por	xmm4,xmm0
+	pand	xmm2,XMMWORD[((-32))+rax]
+	por	xmm5,xmm1
+	pand	xmm3,XMMWORD[((-16))+rax]
+	por	xmm4,xmm2
+	por	xmm5,xmm3
+	movdqa	xmm0,XMMWORD[r11]
+	movdqa	xmm1,XMMWORD[16+r11]
+	movdqa	xmm2,XMMWORD[32+r11]
+	pand	xmm0,XMMWORD[rax]
+	movdqa	xmm3,XMMWORD[48+r11]
+	pand	xmm1,XMMWORD[16+rax]
+	por	xmm4,xmm0
+	pand	xmm2,XMMWORD[32+rax]
+	por	xmm5,xmm1
+	pand	xmm3,XMMWORD[48+rax]
+	por	xmm4,xmm2
+	por	xmm5,xmm3
+	movdqa	xmm0,XMMWORD[64+r11]
+	movdqa	xmm1,XMMWORD[80+r11]
+	movdqa	xmm2,XMMWORD[96+r11]
+	pand	xmm0,XMMWORD[64+rax]
+	movdqa	xmm3,XMMWORD[112+r11]
+	pand	xmm1,XMMWORD[80+rax]
+	por	xmm4,xmm0
+	pand	xmm2,XMMWORD[96+rax]
+	por	xmm5,xmm1
+	pand	xmm3,XMMWORD[112+rax]
+	por	xmm4,xmm2
+	por	xmm5,xmm3
+	por	xmm4,xmm5
+	lea	r11,[256+r11]
+	pshufd	xmm0,xmm4,0x4e
+	por	xmm0,xmm4
 	movq	QWORD[rcx],xmm0
 	lea	rcx,[8+rcx]
 	sub	edx,1
 	jnz	NEAR $L$gather
-	movaps	xmm6,XMMWORD[rsp]
-	movaps	xmm7,XMMWORD[16+rsp]
-	lea	rsp,[40+rsp]
+
+	lea	rsp,[r10]
 	DB	0F3h,0C3h		;repret
 $L$SEH_end_bn_gather5:
 
 ALIGN	64
-$L$magic_masks:
-	DD	0,0,0,0,0,0,-1,-1
-	DD	0,0,0,0,0,0,0,0
+$L$inc:
+	DD	0,0,1,1
+	DD	2,2,2,2
 DB	77,111,110,116,103,111,109,101,114,121,32,77,117,108,116,105
 DB	112,108,105,99,97,116,105,111,110,32,119,105,116,104,32,115
 DB	99,97,116,116,101,114,47,103,97,116,104,101,114,32,102,111
@@ -1937,28 +2473,30 @@
 	cmp	rbx,r10
 	jb	NEAR $L$common_seh_tail
 
+	mov	r10d,DWORD[4+r11]
+	lea	r10,[r10*1+rsi]
+	cmp	rbx,r10
+	jb	NEAR $L$common_pop_regs
+
 	mov	rax,QWORD[152+r8]
 
-	mov	r10d,DWORD[4+r11]
+	mov	r10d,DWORD[8+r11]
 	lea	r10,[r10*1+rsi]
 	cmp	rbx,r10
 	jae	NEAR $L$common_seh_tail
 
 	lea	r10,[$L$mul_epilogue]
 	cmp	rbx,r10
-	jb	NEAR $L$body_40
+	ja	NEAR $L$body_40
 
 	mov	r10,QWORD[192+r8]
 	mov	rax,QWORD[8+r10*8+rax]
-	jmp	NEAR $L$body_proceed
+
+	jmp	NEAR $L$common_pop_regs
 
 $L$body_40:
 	mov	rax,QWORD[40+rax]
-$L$body_proceed:
-
-	movaps	xmm0,XMMWORD[((-88))+rax]
-	movaps	xmm1,XMMWORD[((-72))+rax]
-
+$L$common_pop_regs:
 	mov	rbx,QWORD[((-8))+rax]
 	mov	rbp,QWORD[((-16))+rax]
 	mov	r12,QWORD[((-24))+rax]
@@ -1971,8 +2509,6 @@
 	mov	QWORD[224+r8],r13
 	mov	QWORD[232+r8],r14
 	mov	QWORD[240+r8],r15
-	movups	XMMWORD[512+r8],xmm0
-	movups	XMMWORD[528+r8],xmm1
 
 $L$common_seh_tail:
 	mov	rdi,QWORD[8+rax]
@@ -2040,26 +2576,25 @@
 $L$SEH_info_bn_mul_mont_gather5:
 DB	9,0,0,0
 	DD	mul_handler wrt ..imagebase
-	DD	$L$mul_body wrt ..imagebase,$L$mul_epilogue wrt ..imagebase
+	DD	$L$mul_body wrt ..imagebase,$L$mul_body wrt ..imagebase,$L$mul_epilogue wrt ..imagebase
 ALIGN	8
 $L$SEH_info_bn_mul4x_mont_gather5:
 DB	9,0,0,0
 	DD	mul_handler wrt ..imagebase
-	DD	$L$mul4x_body wrt ..imagebase,$L$mul4x_epilogue wrt ..imagebase
+	DD	$L$mul4x_prologue wrt ..imagebase,$L$mul4x_body wrt ..imagebase,$L$mul4x_epilogue wrt ..imagebase
 ALIGN	8
 $L$SEH_info_bn_power5:
 DB	9,0,0,0
 	DD	mul_handler wrt ..imagebase
-	DD	$L$power5_body wrt ..imagebase,$L$power5_epilogue wrt ..imagebase
+	DD	$L$power5_prologue wrt ..imagebase,$L$power5_body wrt ..imagebase,$L$power5_epilogue wrt ..imagebase
 ALIGN	8
 $L$SEH_info_bn_from_mont8x:
 DB	9,0,0,0
 	DD	mul_handler wrt ..imagebase
-	DD	$L$from_body wrt ..imagebase,$L$from_epilogue wrt ..imagebase
+	DD	$L$from_prologue wrt ..imagebase,$L$from_body wrt ..imagebase,$L$from_epilogue wrt ..imagebase
 ALIGN	8
 $L$SEH_info_bn_gather5:
-DB	0x01,0x0d,0x05,0x00
-DB	0x0d,0x78,0x01,0x00
-DB	0x08,0x68,0x00,0x00
-DB	0x04,0x42,0x00,0x00
+DB	0x01,0x0b,0x03,0x0a
+DB	0x0b,0x01,0x21,0x00
+DB	0x04,0xa3,0x00,0x00
 ALIGN	8
diff --git a/win-x86_64/crypto/chacha/chacha-x86_64.asm b/win-x86_64/crypto/chacha/chacha-x86_64.asm
new file mode 100644
index 0000000..cb36246
--- /dev/null
+++ b/win-x86_64/crypto/chacha/chacha-x86_64.asm
@@ -0,0 +1,1891 @@
+default	rel
+%define XMMWORD
+%define YMMWORD
+%define ZMMWORD
+section	.text code align=64
+
+
+EXTERN	OPENSSL_ia32cap_P
+
+ALIGN	64
+$L$zero:
+	DD	0,0,0,0
+$L$one:
+	DD	1,0,0,0
+$L$inc:
+	DD	0,1,2,3
+$L$four:
+	DD	4,4,4,4
+$L$incy:
+	DD	0,2,4,6,1,3,5,7
+$L$eight:
+	DD	8,8,8,8,8,8,8,8
+$L$rot16:
+DB	0x2,0x3,0x0,0x1,0x6,0x7,0x4,0x5,0xa,0xb,0x8,0x9,0xe,0xf,0xc,0xd
+$L$rot24:
+DB	0x3,0x0,0x1,0x2,0x7,0x4,0x5,0x6,0xb,0x8,0x9,0xa,0xf,0xc,0xd,0xe
+$L$sigma:
+DB	101,120,112,97,110,100,32,51,50,45,98,121,116,101,32,107
+DB	0
+ALIGN	64
+$L$zeroz:
+	DD	0,0,0,0,1,0,0,0,2,0,0,0,3,0,0,0
+$L$fourz:
+	DD	4,0,0,0,4,0,0,0,4,0,0,0,4,0,0,0
+$L$incz:
+	DD	0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
+$L$sixteen:
+	DD	16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16
+DB	67,104,97,67,104,97,50,48,32,102,111,114,32,120,56,54
+DB	95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32
+DB	98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115
+DB	108,46,111,114,103,62,0
+global	ChaCha20_ctr32
+
+ALIGN	64
+ChaCha20_ctr32:
+	mov	QWORD[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_ChaCha20_ctr32:
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+	mov	r8,QWORD[40+rsp]
+
+
+	cmp	rdx,0
+	je	NEAR $L$no_data
+	mov	r10,QWORD[((OPENSSL_ia32cap_P+4))]
+	test	r10d,512
+	jnz	NEAR $L$ChaCha20_ssse3
+
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	sub	rsp,64+24
+$L$ctr32_body:
+
+
+	movdqu	xmm1,XMMWORD[rcx]
+	movdqu	xmm2,XMMWORD[16+rcx]
+	movdqu	xmm3,XMMWORD[r8]
+	movdqa	xmm4,XMMWORD[$L$one]
+
+
+	movdqa	XMMWORD[16+rsp],xmm1
+	movdqa	XMMWORD[32+rsp],xmm2
+	movdqa	XMMWORD[48+rsp],xmm3
+	mov	rbp,rdx
+	jmp	NEAR $L$oop_outer
+
+ALIGN	32
+$L$oop_outer:
+	mov	eax,0x61707865
+	mov	ebx,0x3320646e
+	mov	ecx,0x79622d32
+	mov	edx,0x6b206574
+	mov	r8d,DWORD[16+rsp]
+	mov	r9d,DWORD[20+rsp]
+	mov	r10d,DWORD[24+rsp]
+	mov	r11d,DWORD[28+rsp]
+	movd	r12d,xmm3
+	mov	r13d,DWORD[52+rsp]
+	mov	r14d,DWORD[56+rsp]
+	mov	r15d,DWORD[60+rsp]
+
+	mov	QWORD[((64+0))+rsp],rbp
+	mov	ebp,10
+	mov	QWORD[((64+8))+rsp],rsi
+DB	102,72,15,126,214
+	mov	QWORD[((64+16))+rsp],rdi
+	mov	rdi,rsi
+	shr	rdi,32
+	jmp	NEAR $L$oop
+
+ALIGN	32
+$L$oop:
+	add	eax,r8d
+	xor	r12d,eax
+	rol	r12d,16
+	add	ebx,r9d
+	xor	r13d,ebx
+	rol	r13d,16
+	add	esi,r12d
+	xor	r8d,esi
+	rol	r8d,12
+	add	edi,r13d
+	xor	r9d,edi
+	rol	r9d,12
+	add	eax,r8d
+	xor	r12d,eax
+	rol	r12d,8
+	add	ebx,r9d
+	xor	r13d,ebx
+	rol	r13d,8
+	add	esi,r12d
+	xor	r8d,esi
+	rol	r8d,7
+	add	edi,r13d
+	xor	r9d,edi
+	rol	r9d,7
+	mov	DWORD[32+rsp],esi
+	mov	DWORD[36+rsp],edi
+	mov	esi,DWORD[40+rsp]
+	mov	edi,DWORD[44+rsp]
+	add	ecx,r10d
+	xor	r14d,ecx
+	rol	r14d,16
+	add	edx,r11d
+	xor	r15d,edx
+	rol	r15d,16
+	add	esi,r14d
+	xor	r10d,esi
+	rol	r10d,12
+	add	edi,r15d
+	xor	r11d,edi
+	rol	r11d,12
+	add	ecx,r10d
+	xor	r14d,ecx
+	rol	r14d,8
+	add	edx,r11d
+	xor	r15d,edx
+	rol	r15d,8
+	add	esi,r14d
+	xor	r10d,esi
+	rol	r10d,7
+	add	edi,r15d
+	xor	r11d,edi
+	rol	r11d,7
+	add	eax,r9d
+	xor	r15d,eax
+	rol	r15d,16
+	add	ebx,r10d
+	xor	r12d,ebx
+	rol	r12d,16
+	add	esi,r15d
+	xor	r9d,esi
+	rol	r9d,12
+	add	edi,r12d
+	xor	r10d,edi
+	rol	r10d,12
+	add	eax,r9d
+	xor	r15d,eax
+	rol	r15d,8
+	add	ebx,r10d
+	xor	r12d,ebx
+	rol	r12d,8
+	add	esi,r15d
+	xor	r9d,esi
+	rol	r9d,7
+	add	edi,r12d
+	xor	r10d,edi
+	rol	r10d,7
+	mov	DWORD[40+rsp],esi
+	mov	DWORD[44+rsp],edi
+	mov	esi,DWORD[32+rsp]
+	mov	edi,DWORD[36+rsp]
+	add	ecx,r11d
+	xor	r13d,ecx
+	rol	r13d,16
+	add	edx,r8d
+	xor	r14d,edx
+	rol	r14d,16
+	add	esi,r13d
+	xor	r11d,esi
+	rol	r11d,12
+	add	edi,r14d
+	xor	r8d,edi
+	rol	r8d,12
+	add	ecx,r11d
+	xor	r13d,ecx
+	rol	r13d,8
+	add	edx,r8d
+	xor	r14d,edx
+	rol	r14d,8
+	add	esi,r13d
+	xor	r11d,esi
+	rol	r11d,7
+	add	edi,r14d
+	xor	r8d,edi
+	rol	r8d,7
+	dec	ebp
+	jnz	NEAR $L$oop
+	mov	DWORD[36+rsp],edi
+	mov	DWORD[32+rsp],esi
+	mov	rbp,QWORD[64+rsp]
+	movdqa	xmm1,xmm2
+	mov	rsi,QWORD[((64+8))+rsp]
+	paddd	xmm3,xmm4
+	mov	rdi,QWORD[((64+16))+rsp]
+
+	add	eax,0x61707865
+	add	ebx,0x3320646e
+	add	ecx,0x79622d32
+	add	edx,0x6b206574
+	add	r8d,DWORD[16+rsp]
+	add	r9d,DWORD[20+rsp]
+	add	r10d,DWORD[24+rsp]
+	add	r11d,DWORD[28+rsp]
+	add	r12d,DWORD[48+rsp]
+	add	r13d,DWORD[52+rsp]
+	add	r14d,DWORD[56+rsp]
+	add	r15d,DWORD[60+rsp]
+	paddd	xmm1,XMMWORD[32+rsp]
+
+	cmp	rbp,64
+	jb	NEAR $L$tail
+
+	xor	eax,DWORD[rsi]
+	xor	ebx,DWORD[4+rsi]
+	xor	ecx,DWORD[8+rsi]
+	xor	edx,DWORD[12+rsi]
+	xor	r8d,DWORD[16+rsi]
+	xor	r9d,DWORD[20+rsi]
+	xor	r10d,DWORD[24+rsi]
+	xor	r11d,DWORD[28+rsi]
+	movdqu	xmm0,XMMWORD[32+rsi]
+	xor	r12d,DWORD[48+rsi]
+	xor	r13d,DWORD[52+rsi]
+	xor	r14d,DWORD[56+rsi]
+	xor	r15d,DWORD[60+rsi]
+	lea	rsi,[64+rsi]
+	pxor	xmm0,xmm1
+
+	movdqa	XMMWORD[32+rsp],xmm2
+	movd	DWORD[48+rsp],xmm3
+
+	mov	DWORD[rdi],eax
+	mov	DWORD[4+rdi],ebx
+	mov	DWORD[8+rdi],ecx
+	mov	DWORD[12+rdi],edx
+	mov	DWORD[16+rdi],r8d
+	mov	DWORD[20+rdi],r9d
+	mov	DWORD[24+rdi],r10d
+	mov	DWORD[28+rdi],r11d
+	movdqu	XMMWORD[32+rdi],xmm0
+	mov	DWORD[48+rdi],r12d
+	mov	DWORD[52+rdi],r13d
+	mov	DWORD[56+rdi],r14d
+	mov	DWORD[60+rdi],r15d
+	lea	rdi,[64+rdi]
+
+	sub	rbp,64
+	jnz	NEAR $L$oop_outer
+
+	jmp	NEAR $L$done
+
+ALIGN	16
+$L$tail:
+	mov	DWORD[rsp],eax
+	mov	DWORD[4+rsp],ebx
+	xor	rbx,rbx
+	mov	DWORD[8+rsp],ecx
+	mov	DWORD[12+rsp],edx
+	mov	DWORD[16+rsp],r8d
+	mov	DWORD[20+rsp],r9d
+	mov	DWORD[24+rsp],r10d
+	mov	DWORD[28+rsp],r11d
+	movdqa	XMMWORD[32+rsp],xmm1
+	mov	DWORD[48+rsp],r12d
+	mov	DWORD[52+rsp],r13d
+	mov	DWORD[56+rsp],r14d
+	mov	DWORD[60+rsp],r15d
+
+$L$oop_tail:
+	movzx	eax,BYTE[rbx*1+rsi]
+	movzx	edx,BYTE[rbx*1+rsp]
+	lea	rbx,[1+rbx]
+	xor	eax,edx
+	mov	BYTE[((-1))+rbx*1+rdi],al
+	dec	rbp
+	jnz	NEAR $L$oop_tail
+
+$L$done:
+	lea	rsi,[((64+24+48))+rsp]
+	mov	r15,QWORD[((-48))+rsi]
+	mov	r14,QWORD[((-40))+rsi]
+	mov	r13,QWORD[((-32))+rsi]
+	mov	r12,QWORD[((-24))+rsi]
+	mov	rbp,QWORD[((-16))+rsi]
+	mov	rbx,QWORD[((-8))+rsi]
+	lea	rsp,[rsi]
+$L$no_data:
+	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_ChaCha20_ctr32:
+
+ALIGN	32
+ChaCha20_ssse3:
+	mov	QWORD[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_ChaCha20_ssse3:
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+	mov	r8,QWORD[40+rsp]
+
+
+$L$ChaCha20_ssse3:
+	mov	r9,rsp
+	cmp	rdx,128
+	ja	NEAR $L$ChaCha20_4x
+
+$L$do_sse3_after_all:
+	sub	rsp,64+40
+	movaps	XMMWORD[(-40)+r9],xmm6
+	movaps	XMMWORD[(-24)+r9],xmm7
+$L$ssse3_body:
+	movdqa	xmm0,XMMWORD[$L$sigma]
+	movdqu	xmm1,XMMWORD[rcx]
+	movdqu	xmm2,XMMWORD[16+rcx]
+	movdqu	xmm3,XMMWORD[r8]
+	movdqa	xmm6,XMMWORD[$L$rot16]
+	movdqa	xmm7,XMMWORD[$L$rot24]
+
+	movdqa	XMMWORD[rsp],xmm0
+	movdqa	XMMWORD[16+rsp],xmm1
+	movdqa	XMMWORD[32+rsp],xmm2
+	movdqa	XMMWORD[48+rsp],xmm3
+	mov	r8,10
+	jmp	NEAR $L$oop_ssse3
+
+ALIGN	32
+$L$oop_outer_ssse3:
+	movdqa	xmm3,XMMWORD[$L$one]
+	movdqa	xmm0,XMMWORD[rsp]
+	movdqa	xmm1,XMMWORD[16+rsp]
+	movdqa	xmm2,XMMWORD[32+rsp]
+	paddd	xmm3,XMMWORD[48+rsp]
+	mov	r8,10
+	movdqa	XMMWORD[48+rsp],xmm3
+	jmp	NEAR $L$oop_ssse3
+
+ALIGN	32
+$L$oop_ssse3:
+	paddd	xmm0,xmm1
+	pxor	xmm3,xmm0
+DB	102,15,56,0,222
+	paddd	xmm2,xmm3
+	pxor	xmm1,xmm2
+	movdqa	xmm4,xmm1
+	psrld	xmm1,20
+	pslld	xmm4,12
+	por	xmm1,xmm4
+	paddd	xmm0,xmm1
+	pxor	xmm3,xmm0
+DB	102,15,56,0,223
+	paddd	xmm2,xmm3
+	pxor	xmm1,xmm2
+	movdqa	xmm4,xmm1
+	psrld	xmm1,25
+	pslld	xmm4,7
+	por	xmm1,xmm4
+	pshufd	xmm2,xmm2,78
+	pshufd	xmm1,xmm1,57
+	pshufd	xmm3,xmm3,147
+	nop
+	paddd	xmm0,xmm1
+	pxor	xmm3,xmm0
+DB	102,15,56,0,222
+	paddd	xmm2,xmm3
+	pxor	xmm1,xmm2
+	movdqa	xmm4,xmm1
+	psrld	xmm1,20
+	pslld	xmm4,12
+	por	xmm1,xmm4
+	paddd	xmm0,xmm1
+	pxor	xmm3,xmm0
+DB	102,15,56,0,223
+	paddd	xmm2,xmm3
+	pxor	xmm1,xmm2
+	movdqa	xmm4,xmm1
+	psrld	xmm1,25
+	pslld	xmm4,7
+	por	xmm1,xmm4
+	pshufd	xmm2,xmm2,78
+	pshufd	xmm1,xmm1,147
+	pshufd	xmm3,xmm3,57
+	dec	r8
+	jnz	NEAR $L$oop_ssse3
+	paddd	xmm0,XMMWORD[rsp]
+	paddd	xmm1,XMMWORD[16+rsp]
+	paddd	xmm2,XMMWORD[32+rsp]
+	paddd	xmm3,XMMWORD[48+rsp]
+
+	cmp	rdx,64
+	jb	NEAR $L$tail_ssse3
+
+	movdqu	xmm4,XMMWORD[rsi]
+	movdqu	xmm5,XMMWORD[16+rsi]
+	pxor	xmm0,xmm4
+	movdqu	xmm4,XMMWORD[32+rsi]
+	pxor	xmm1,xmm5
+	movdqu	xmm5,XMMWORD[48+rsi]
+	lea	rsi,[64+rsi]
+	pxor	xmm2,xmm4
+	pxor	xmm3,xmm5
+
+	movdqu	XMMWORD[rdi],xmm0
+	movdqu	XMMWORD[16+rdi],xmm1
+	movdqu	XMMWORD[32+rdi],xmm2
+	movdqu	XMMWORD[48+rdi],xmm3
+	lea	rdi,[64+rdi]
+
+	sub	rdx,64
+	jnz	NEAR $L$oop_outer_ssse3
+
+	jmp	NEAR $L$done_ssse3
+
+ALIGN	16
+$L$tail_ssse3:
+	movdqa	XMMWORD[rsp],xmm0
+	movdqa	XMMWORD[16+rsp],xmm1
+	movdqa	XMMWORD[32+rsp],xmm2
+	movdqa	XMMWORD[48+rsp],xmm3
+	xor	r8,r8
+
+$L$oop_tail_ssse3:
+	movzx	eax,BYTE[r8*1+rsi]
+	movzx	ecx,BYTE[r8*1+rsp]
+	lea	r8,[1+r8]
+	xor	eax,ecx
+	mov	BYTE[((-1))+r8*1+rdi],al
+	dec	rdx
+	jnz	NEAR $L$oop_tail_ssse3
+
+$L$done_ssse3:
+	movaps	xmm6,XMMWORD[((-40))+r9]
+	movaps	xmm7,XMMWORD[((-24))+r9]
+	lea	rsp,[r9]
+$L$ssse3_epilogue:
+	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_ChaCha20_ssse3:
+
+ALIGN	32
+ChaCha20_4x:
+	mov	QWORD[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_ChaCha20_4x:
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+	mov	r8,QWORD[40+rsp]
+
+
+$L$ChaCha20_4x:
+	mov	r9,rsp
+	mov	r11,r10
+	shr	r10,32
+	test	r10,32
+	jnz	NEAR $L$ChaCha20_8x
+	cmp	rdx,192
+	ja	NEAR $L$proceed4x
+
+	and	r11,71303168
+	cmp	r11,4194304
+	je	NEAR $L$do_sse3_after_all
+
+$L$proceed4x:
+	sub	rsp,0x140+168
+	movaps	XMMWORD[(-168)+r9],xmm6
+	movaps	XMMWORD[(-152)+r9],xmm7
+	movaps	XMMWORD[(-136)+r9],xmm8
+	movaps	XMMWORD[(-120)+r9],xmm9
+	movaps	XMMWORD[(-104)+r9],xmm10
+	movaps	XMMWORD[(-88)+r9],xmm11
+	movaps	XMMWORD[(-72)+r9],xmm12
+	movaps	XMMWORD[(-56)+r9],xmm13
+	movaps	XMMWORD[(-40)+r9],xmm14
+	movaps	XMMWORD[(-24)+r9],xmm15
+$L$4x_body:
+	movdqa	xmm11,XMMWORD[$L$sigma]
+	movdqu	xmm15,XMMWORD[rcx]
+	movdqu	xmm7,XMMWORD[16+rcx]
+	movdqu	xmm3,XMMWORD[r8]
+	lea	rcx,[256+rsp]
+	lea	r10,[$L$rot16]
+	lea	r11,[$L$rot24]
+
+	pshufd	xmm8,xmm11,0x00
+	pshufd	xmm9,xmm11,0x55
+	movdqa	XMMWORD[64+rsp],xmm8
+	pshufd	xmm10,xmm11,0xaa
+	movdqa	XMMWORD[80+rsp],xmm9
+	pshufd	xmm11,xmm11,0xff
+	movdqa	XMMWORD[96+rsp],xmm10
+	movdqa	XMMWORD[112+rsp],xmm11
+
+	pshufd	xmm12,xmm15,0x00
+	pshufd	xmm13,xmm15,0x55
+	movdqa	XMMWORD[(128-256)+rcx],xmm12
+	pshufd	xmm14,xmm15,0xaa
+	movdqa	XMMWORD[(144-256)+rcx],xmm13
+	pshufd	xmm15,xmm15,0xff
+	movdqa	XMMWORD[(160-256)+rcx],xmm14
+	movdqa	XMMWORD[(176-256)+rcx],xmm15
+
+	pshufd	xmm4,xmm7,0x00
+	pshufd	xmm5,xmm7,0x55
+	movdqa	XMMWORD[(192-256)+rcx],xmm4
+	pshufd	xmm6,xmm7,0xaa
+	movdqa	XMMWORD[(208-256)+rcx],xmm5
+	pshufd	xmm7,xmm7,0xff
+	movdqa	XMMWORD[(224-256)+rcx],xmm6
+	movdqa	XMMWORD[(240-256)+rcx],xmm7
+
+	pshufd	xmm0,xmm3,0x00
+	pshufd	xmm1,xmm3,0x55
+	paddd	xmm0,XMMWORD[$L$inc]
+	pshufd	xmm2,xmm3,0xaa
+	movdqa	XMMWORD[(272-256)+rcx],xmm1
+	pshufd	xmm3,xmm3,0xff
+	movdqa	XMMWORD[(288-256)+rcx],xmm2
+	movdqa	XMMWORD[(304-256)+rcx],xmm3
+
+	jmp	NEAR $L$oop_enter4x
+
+ALIGN	32
+$L$oop_outer4x:
+	movdqa	xmm8,XMMWORD[64+rsp]
+	movdqa	xmm9,XMMWORD[80+rsp]
+	movdqa	xmm10,XMMWORD[96+rsp]
+	movdqa	xmm11,XMMWORD[112+rsp]
+	movdqa	xmm12,XMMWORD[((128-256))+rcx]
+	movdqa	xmm13,XMMWORD[((144-256))+rcx]
+	movdqa	xmm14,XMMWORD[((160-256))+rcx]
+	movdqa	xmm15,XMMWORD[((176-256))+rcx]
+	movdqa	xmm4,XMMWORD[((192-256))+rcx]
+	movdqa	xmm5,XMMWORD[((208-256))+rcx]
+	movdqa	xmm6,XMMWORD[((224-256))+rcx]
+	movdqa	xmm7,XMMWORD[((240-256))+rcx]
+	movdqa	xmm0,XMMWORD[((256-256))+rcx]
+	movdqa	xmm1,XMMWORD[((272-256))+rcx]
+	movdqa	xmm2,XMMWORD[((288-256))+rcx]
+	movdqa	xmm3,XMMWORD[((304-256))+rcx]
+	paddd	xmm0,XMMWORD[$L$four]
+
+$L$oop_enter4x:
+	movdqa	XMMWORD[32+rsp],xmm6
+	movdqa	XMMWORD[48+rsp],xmm7
+	movdqa	xmm7,XMMWORD[r10]
+	mov	eax,10
+	movdqa	XMMWORD[(256-256)+rcx],xmm0
+	jmp	NEAR $L$oop4x
+
+ALIGN	32
+$L$oop4x:
+	paddd	xmm8,xmm12
+	paddd	xmm9,xmm13
+	pxor	xmm0,xmm8
+	pxor	xmm1,xmm9
+DB	102,15,56,0,199
+DB	102,15,56,0,207
+	paddd	xmm4,xmm0
+	paddd	xmm5,xmm1
+	pxor	xmm12,xmm4
+	pxor	xmm13,xmm5
+	movdqa	xmm6,xmm12
+	pslld	xmm12,12
+	psrld	xmm6,20
+	movdqa	xmm7,xmm13
+	pslld	xmm13,12
+	por	xmm12,xmm6
+	psrld	xmm7,20
+	movdqa	xmm6,XMMWORD[r11]
+	por	xmm13,xmm7
+	paddd	xmm8,xmm12
+	paddd	xmm9,xmm13
+	pxor	xmm0,xmm8
+	pxor	xmm1,xmm9
+DB	102,15,56,0,198
+DB	102,15,56,0,206
+	paddd	xmm4,xmm0
+	paddd	xmm5,xmm1
+	pxor	xmm12,xmm4
+	pxor	xmm13,xmm5
+	movdqa	xmm7,xmm12
+	pslld	xmm12,7
+	psrld	xmm7,25
+	movdqa	xmm6,xmm13
+	pslld	xmm13,7
+	por	xmm12,xmm7
+	psrld	xmm6,25
+	movdqa	xmm7,XMMWORD[r10]
+	por	xmm13,xmm6
+	movdqa	XMMWORD[rsp],xmm4
+	movdqa	XMMWORD[16+rsp],xmm5
+	movdqa	xmm4,XMMWORD[32+rsp]
+	movdqa	xmm5,XMMWORD[48+rsp]
+	paddd	xmm10,xmm14
+	paddd	xmm11,xmm15
+	pxor	xmm2,xmm10
+	pxor	xmm3,xmm11
+DB	102,15,56,0,215
+DB	102,15,56,0,223
+	paddd	xmm4,xmm2
+	paddd	xmm5,xmm3
+	pxor	xmm14,xmm4
+	pxor	xmm15,xmm5
+	movdqa	xmm6,xmm14
+	pslld	xmm14,12
+	psrld	xmm6,20
+	movdqa	xmm7,xmm15
+	pslld	xmm15,12
+	por	xmm14,xmm6
+	psrld	xmm7,20
+	movdqa	xmm6,XMMWORD[r11]
+	por	xmm15,xmm7
+	paddd	xmm10,xmm14
+	paddd	xmm11,xmm15
+	pxor	xmm2,xmm10
+	pxor	xmm3,xmm11
+DB	102,15,56,0,214
+DB	102,15,56,0,222
+	paddd	xmm4,xmm2
+	paddd	xmm5,xmm3
+	pxor	xmm14,xmm4
+	pxor	xmm15,xmm5
+	movdqa	xmm7,xmm14
+	pslld	xmm14,7
+	psrld	xmm7,25
+	movdqa	xmm6,xmm15
+	pslld	xmm15,7
+	por	xmm14,xmm7
+	psrld	xmm6,25
+	movdqa	xmm7,XMMWORD[r10]
+	por	xmm15,xmm6
+	paddd	xmm8,xmm13
+	paddd	xmm9,xmm14
+	pxor	xmm3,xmm8
+	pxor	xmm0,xmm9
+DB	102,15,56,0,223
+DB	102,15,56,0,199
+	paddd	xmm4,xmm3
+	paddd	xmm5,xmm0
+	pxor	xmm13,xmm4
+	pxor	xmm14,xmm5
+	movdqa	xmm6,xmm13
+	pslld	xmm13,12
+	psrld	xmm6,20
+	movdqa	xmm7,xmm14
+	pslld	xmm14,12
+	por	xmm13,xmm6
+	psrld	xmm7,20
+	movdqa	xmm6,XMMWORD[r11]
+	por	xmm14,xmm7
+	paddd	xmm8,xmm13
+	paddd	xmm9,xmm14
+	pxor	xmm3,xmm8
+	pxor	xmm0,xmm9
+DB	102,15,56,0,222
+DB	102,15,56,0,198
+	paddd	xmm4,xmm3
+	paddd	xmm5,xmm0
+	pxor	xmm13,xmm4
+	pxor	xmm14,xmm5
+	movdqa	xmm7,xmm13
+	pslld	xmm13,7
+	psrld	xmm7,25
+	movdqa	xmm6,xmm14
+	pslld	xmm14,7
+	por	xmm13,xmm7
+	psrld	xmm6,25
+	movdqa	xmm7,XMMWORD[r10]
+	por	xmm14,xmm6
+	movdqa	XMMWORD[32+rsp],xmm4
+	movdqa	XMMWORD[48+rsp],xmm5
+	movdqa	xmm4,XMMWORD[rsp]
+	movdqa	xmm5,XMMWORD[16+rsp]
+	paddd	xmm10,xmm15
+	paddd	xmm11,xmm12
+	pxor	xmm1,xmm10
+	pxor	xmm2,xmm11
+DB	102,15,56,0,207
+DB	102,15,56,0,215
+	paddd	xmm4,xmm1
+	paddd	xmm5,xmm2
+	pxor	xmm15,xmm4
+	pxor	xmm12,xmm5
+	movdqa	xmm6,xmm15
+	pslld	xmm15,12
+	psrld	xmm6,20
+	movdqa	xmm7,xmm12
+	pslld	xmm12,12
+	por	xmm15,xmm6
+	psrld	xmm7,20
+	movdqa	xmm6,XMMWORD[r11]
+	por	xmm12,xmm7
+	paddd	xmm10,xmm15
+	paddd	xmm11,xmm12
+	pxor	xmm1,xmm10
+	pxor	xmm2,xmm11
+DB	102,15,56,0,206
+DB	102,15,56,0,214
+	paddd	xmm4,xmm1
+	paddd	xmm5,xmm2
+	pxor	xmm15,xmm4
+	pxor	xmm12,xmm5
+	movdqa	xmm7,xmm15
+	pslld	xmm15,7
+	psrld	xmm7,25
+	movdqa	xmm6,xmm12
+	pslld	xmm12,7
+	por	xmm15,xmm7
+	psrld	xmm6,25
+	movdqa	xmm7,XMMWORD[r10]
+	por	xmm12,xmm6
+	dec	eax
+	jnz	NEAR $L$oop4x
+
+	paddd	xmm8,XMMWORD[64+rsp]
+	paddd	xmm9,XMMWORD[80+rsp]
+	paddd	xmm10,XMMWORD[96+rsp]
+	paddd	xmm11,XMMWORD[112+rsp]
+
+	movdqa	xmm6,xmm8
+	punpckldq	xmm8,xmm9
+	movdqa	xmm7,xmm10
+	punpckldq	xmm10,xmm11
+	punpckhdq	xmm6,xmm9
+	punpckhdq	xmm7,xmm11
+	movdqa	xmm9,xmm8
+	punpcklqdq	xmm8,xmm10
+	movdqa	xmm11,xmm6
+	punpcklqdq	xmm6,xmm7
+	punpckhqdq	xmm9,xmm10
+	punpckhqdq	xmm11,xmm7
+	paddd	xmm12,XMMWORD[((128-256))+rcx]
+	paddd	xmm13,XMMWORD[((144-256))+rcx]
+	paddd	xmm14,XMMWORD[((160-256))+rcx]
+	paddd	xmm15,XMMWORD[((176-256))+rcx]
+
+	movdqa	XMMWORD[rsp],xmm8
+	movdqa	XMMWORD[16+rsp],xmm9
+	movdqa	xmm8,XMMWORD[32+rsp]
+	movdqa	xmm9,XMMWORD[48+rsp]
+
+	movdqa	xmm10,xmm12
+	punpckldq	xmm12,xmm13
+	movdqa	xmm7,xmm14
+	punpckldq	xmm14,xmm15
+	punpckhdq	xmm10,xmm13
+	punpckhdq	xmm7,xmm15
+	movdqa	xmm13,xmm12
+	punpcklqdq	xmm12,xmm14
+	movdqa	xmm15,xmm10
+	punpcklqdq	xmm10,xmm7
+	punpckhqdq	xmm13,xmm14
+	punpckhqdq	xmm15,xmm7
+	paddd	xmm4,XMMWORD[((192-256))+rcx]
+	paddd	xmm5,XMMWORD[((208-256))+rcx]
+	paddd	xmm8,XMMWORD[((224-256))+rcx]
+	paddd	xmm9,XMMWORD[((240-256))+rcx]
+
+	movdqa	XMMWORD[32+rsp],xmm6
+	movdqa	XMMWORD[48+rsp],xmm11
+
+	movdqa	xmm14,xmm4
+	punpckldq	xmm4,xmm5
+	movdqa	xmm7,xmm8
+	punpckldq	xmm8,xmm9
+	punpckhdq	xmm14,xmm5
+	punpckhdq	xmm7,xmm9
+	movdqa	xmm5,xmm4
+	punpcklqdq	xmm4,xmm8
+	movdqa	xmm9,xmm14
+	punpcklqdq	xmm14,xmm7
+	punpckhqdq	xmm5,xmm8
+	punpckhqdq	xmm9,xmm7
+	paddd	xmm0,XMMWORD[((256-256))+rcx]
+	paddd	xmm1,XMMWORD[((272-256))+rcx]
+	paddd	xmm2,XMMWORD[((288-256))+rcx]
+	paddd	xmm3,XMMWORD[((304-256))+rcx]
+
+	movdqa	xmm8,xmm0
+	punpckldq	xmm0,xmm1
+	movdqa	xmm7,xmm2
+	punpckldq	xmm2,xmm3
+	punpckhdq	xmm8,xmm1
+	punpckhdq	xmm7,xmm3
+	movdqa	xmm1,xmm0
+	punpcklqdq	xmm0,xmm2
+	movdqa	xmm3,xmm8
+	punpcklqdq	xmm8,xmm7
+	punpckhqdq	xmm1,xmm2
+	punpckhqdq	xmm3,xmm7
+	cmp	rdx,64*4
+	jb	NEAR $L$tail4x
+
+	movdqu	xmm6,XMMWORD[rsi]
+	movdqu	xmm11,XMMWORD[16+rsi]
+	movdqu	xmm2,XMMWORD[32+rsi]
+	movdqu	xmm7,XMMWORD[48+rsi]
+	pxor	xmm6,XMMWORD[rsp]
+	pxor	xmm11,xmm12
+	pxor	xmm2,xmm4
+	pxor	xmm7,xmm0
+
+	movdqu	XMMWORD[rdi],xmm6
+	movdqu	xmm6,XMMWORD[64+rsi]
+	movdqu	XMMWORD[16+rdi],xmm11
+	movdqu	xmm11,XMMWORD[80+rsi]
+	movdqu	XMMWORD[32+rdi],xmm2
+	movdqu	xmm2,XMMWORD[96+rsi]
+	movdqu	XMMWORD[48+rdi],xmm7
+	movdqu	xmm7,XMMWORD[112+rsi]
+	lea	rsi,[128+rsi]
+	pxor	xmm6,XMMWORD[16+rsp]
+	pxor	xmm11,xmm13
+	pxor	xmm2,xmm5
+	pxor	xmm7,xmm1
+
+	movdqu	XMMWORD[64+rdi],xmm6
+	movdqu	xmm6,XMMWORD[rsi]
+	movdqu	XMMWORD[80+rdi],xmm11
+	movdqu	xmm11,XMMWORD[16+rsi]
+	movdqu	XMMWORD[96+rdi],xmm2
+	movdqu	xmm2,XMMWORD[32+rsi]
+	movdqu	XMMWORD[112+rdi],xmm7
+	lea	rdi,[128+rdi]
+	movdqu	xmm7,XMMWORD[48+rsi]
+	pxor	xmm6,XMMWORD[32+rsp]
+	pxor	xmm11,xmm10
+	pxor	xmm2,xmm14
+	pxor	xmm7,xmm8
+
+	movdqu	XMMWORD[rdi],xmm6
+	movdqu	xmm6,XMMWORD[64+rsi]
+	movdqu	XMMWORD[16+rdi],xmm11
+	movdqu	xmm11,XMMWORD[80+rsi]
+	movdqu	XMMWORD[32+rdi],xmm2
+	movdqu	xmm2,XMMWORD[96+rsi]
+	movdqu	XMMWORD[48+rdi],xmm7
+	movdqu	xmm7,XMMWORD[112+rsi]
+	lea	rsi,[128+rsi]
+	pxor	xmm6,XMMWORD[48+rsp]
+	pxor	xmm11,xmm15
+	pxor	xmm2,xmm9
+	pxor	xmm7,xmm3
+	movdqu	XMMWORD[64+rdi],xmm6
+	movdqu	XMMWORD[80+rdi],xmm11
+	movdqu	XMMWORD[96+rdi],xmm2
+	movdqu	XMMWORD[112+rdi],xmm7
+	lea	rdi,[128+rdi]
+
+	sub	rdx,64*4
+	jnz	NEAR $L$oop_outer4x
+
+	jmp	NEAR $L$done4x
+
+$L$tail4x:
+	cmp	rdx,192
+	jae	NEAR $L$192_or_more4x
+	cmp	rdx,128
+	jae	NEAR $L$128_or_more4x
+	cmp	rdx,64
+	jae	NEAR $L$64_or_more4x
+
+
+	xor	r10,r10
+
+	movdqa	XMMWORD[16+rsp],xmm12
+	movdqa	XMMWORD[32+rsp],xmm4
+	movdqa	XMMWORD[48+rsp],xmm0
+	jmp	NEAR $L$oop_tail4x
+
+ALIGN	32
+$L$64_or_more4x:
+	movdqu	xmm6,XMMWORD[rsi]
+	movdqu	xmm11,XMMWORD[16+rsi]
+	movdqu	xmm2,XMMWORD[32+rsi]
+	movdqu	xmm7,XMMWORD[48+rsi]
+	pxor	xmm6,XMMWORD[rsp]
+	pxor	xmm11,xmm12
+	pxor	xmm2,xmm4
+	pxor	xmm7,xmm0
+	movdqu	XMMWORD[rdi],xmm6
+	movdqu	XMMWORD[16+rdi],xmm11
+	movdqu	XMMWORD[32+rdi],xmm2
+	movdqu	XMMWORD[48+rdi],xmm7
+	je	NEAR $L$done4x
+
+	movdqa	xmm6,XMMWORD[16+rsp]
+	lea	rsi,[64+rsi]
+	xor	r10,r10
+	movdqa	XMMWORD[rsp],xmm6
+	movdqa	XMMWORD[16+rsp],xmm13
+	lea	rdi,[64+rdi]
+	movdqa	XMMWORD[32+rsp],xmm5
+	sub	rdx,64
+	movdqa	XMMWORD[48+rsp],xmm1
+	jmp	NEAR $L$oop_tail4x
+
+ALIGN	32
+$L$128_or_more4x:
+	movdqu	xmm6,XMMWORD[rsi]
+	movdqu	xmm11,XMMWORD[16+rsi]
+	movdqu	xmm2,XMMWORD[32+rsi]
+	movdqu	xmm7,XMMWORD[48+rsi]
+	pxor	xmm6,XMMWORD[rsp]
+	pxor	xmm11,xmm12
+	pxor	xmm2,xmm4
+	pxor	xmm7,xmm0
+
+	movdqu	XMMWORD[rdi],xmm6
+	movdqu	xmm6,XMMWORD[64+rsi]
+	movdqu	XMMWORD[16+rdi],xmm11
+	movdqu	xmm11,XMMWORD[80+rsi]
+	movdqu	XMMWORD[32+rdi],xmm2
+	movdqu	xmm2,XMMWORD[96+rsi]
+	movdqu	XMMWORD[48+rdi],xmm7
+	movdqu	xmm7,XMMWORD[112+rsi]
+	pxor	xmm6,XMMWORD[16+rsp]
+	pxor	xmm11,xmm13
+	pxor	xmm2,xmm5
+	pxor	xmm7,xmm1
+	movdqu	XMMWORD[64+rdi],xmm6
+	movdqu	XMMWORD[80+rdi],xmm11
+	movdqu	XMMWORD[96+rdi],xmm2
+	movdqu	XMMWORD[112+rdi],xmm7
+	je	NEAR $L$done4x
+
+	movdqa	xmm6,XMMWORD[32+rsp]
+	lea	rsi,[128+rsi]
+	xor	r10,r10
+	movdqa	XMMWORD[rsp],xmm6
+	movdqa	XMMWORD[16+rsp],xmm10
+	lea	rdi,[128+rdi]
+	movdqa	XMMWORD[32+rsp],xmm14
+	sub	rdx,128
+	movdqa	XMMWORD[48+rsp],xmm8
+	jmp	NEAR $L$oop_tail4x
+
+ALIGN	32
+$L$192_or_more4x:
+	movdqu	xmm6,XMMWORD[rsi]
+	movdqu	xmm11,XMMWORD[16+rsi]
+	movdqu	xmm2,XMMWORD[32+rsi]
+	movdqu	xmm7,XMMWORD[48+rsi]
+	pxor	xmm6,XMMWORD[rsp]
+	pxor	xmm11,xmm12
+	pxor	xmm2,xmm4
+	pxor	xmm7,xmm0
+
+	movdqu	XMMWORD[rdi],xmm6
+	movdqu	xmm6,XMMWORD[64+rsi]
+	movdqu	XMMWORD[16+rdi],xmm11
+	movdqu	xmm11,XMMWORD[80+rsi]
+	movdqu	XMMWORD[32+rdi],xmm2
+	movdqu	xmm2,XMMWORD[96+rsi]
+	movdqu	XMMWORD[48+rdi],xmm7
+	movdqu	xmm7,XMMWORD[112+rsi]
+	lea	rsi,[128+rsi]
+	pxor	xmm6,XMMWORD[16+rsp]
+	pxor	xmm11,xmm13
+	pxor	xmm2,xmm5
+	pxor	xmm7,xmm1
+
+	movdqu	XMMWORD[64+rdi],xmm6
+	movdqu	xmm6,XMMWORD[rsi]
+	movdqu	XMMWORD[80+rdi],xmm11
+	movdqu	xmm11,XMMWORD[16+rsi]
+	movdqu	XMMWORD[96+rdi],xmm2
+	movdqu	xmm2,XMMWORD[32+rsi]
+	movdqu	XMMWORD[112+rdi],xmm7
+	lea	rdi,[128+rdi]
+	movdqu	xmm7,XMMWORD[48+rsi]
+	pxor	xmm6,XMMWORD[32+rsp]
+	pxor	xmm11,xmm10
+	pxor	xmm2,xmm14
+	pxor	xmm7,xmm8
+	movdqu	XMMWORD[rdi],xmm6
+	movdqu	XMMWORD[16+rdi],xmm11
+	movdqu	XMMWORD[32+rdi],xmm2
+	movdqu	XMMWORD[48+rdi],xmm7
+	je	NEAR $L$done4x
+
+	movdqa	xmm6,XMMWORD[48+rsp]
+	lea	rsi,[64+rsi]
+	xor	r10,r10
+	movdqa	XMMWORD[rsp],xmm6
+	movdqa	XMMWORD[16+rsp],xmm15
+	lea	rdi,[64+rdi]
+	movdqa	XMMWORD[32+rsp],xmm9
+	sub	rdx,192
+	movdqa	XMMWORD[48+rsp],xmm3
+
+$L$oop_tail4x:
+	movzx	eax,BYTE[r10*1+rsi]
+	movzx	ecx,BYTE[r10*1+rsp]
+	lea	r10,[1+r10]
+	xor	eax,ecx
+	mov	BYTE[((-1))+r10*1+rdi],al
+	dec	rdx
+	jnz	NEAR $L$oop_tail4x
+
+$L$done4x:
+	movaps	xmm6,XMMWORD[((-168))+r9]
+	movaps	xmm7,XMMWORD[((-152))+r9]
+	movaps	xmm8,XMMWORD[((-136))+r9]
+	movaps	xmm9,XMMWORD[((-120))+r9]
+	movaps	xmm10,XMMWORD[((-104))+r9]
+	movaps	xmm11,XMMWORD[((-88))+r9]
+	movaps	xmm12,XMMWORD[((-72))+r9]
+	movaps	xmm13,XMMWORD[((-56))+r9]
+	movaps	xmm14,XMMWORD[((-40))+r9]
+	movaps	xmm15,XMMWORD[((-24))+r9]
+	lea	rsp,[r9]
+$L$4x_epilogue:
+	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_ChaCha20_4x:
+
+ALIGN	32
+ChaCha20_8x:
+	mov	QWORD[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_ChaCha20_8x:
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+	mov	r8,QWORD[40+rsp]
+
+
+$L$ChaCha20_8x:
+	mov	r9,rsp
+	sub	rsp,0x280+168
+	and	rsp,-32
+	movaps	XMMWORD[(-168)+r9],xmm6
+	movaps	XMMWORD[(-152)+r9],xmm7
+	movaps	XMMWORD[(-136)+r9],xmm8
+	movaps	XMMWORD[(-120)+r9],xmm9
+	movaps	XMMWORD[(-104)+r9],xmm10
+	movaps	XMMWORD[(-88)+r9],xmm11
+	movaps	XMMWORD[(-72)+r9],xmm12
+	movaps	XMMWORD[(-56)+r9],xmm13
+	movaps	XMMWORD[(-40)+r9],xmm14
+	movaps	XMMWORD[(-24)+r9],xmm15
+$L$8x_body:
+	vzeroupper
+
+
+
+
+
+
+
+
+
+
+	vbroadcasti128	ymm11,XMMWORD[$L$sigma]
+	vbroadcasti128	ymm3,XMMWORD[rcx]
+	vbroadcasti128	ymm15,XMMWORD[16+rcx]
+	vbroadcasti128	ymm7,XMMWORD[r8]
+	lea	rcx,[256+rsp]
+	lea	rax,[512+rsp]
+	lea	r10,[$L$rot16]
+	lea	r11,[$L$rot24]
+
+	vpshufd	ymm8,ymm11,0x00
+	vpshufd	ymm9,ymm11,0x55
+	vmovdqa	YMMWORD[(128-256)+rcx],ymm8
+	vpshufd	ymm10,ymm11,0xaa
+	vmovdqa	YMMWORD[(160-256)+rcx],ymm9
+	vpshufd	ymm11,ymm11,0xff
+	vmovdqa	YMMWORD[(192-256)+rcx],ymm10
+	vmovdqa	YMMWORD[(224-256)+rcx],ymm11
+
+	vpshufd	ymm0,ymm3,0x00
+	vpshufd	ymm1,ymm3,0x55
+	vmovdqa	YMMWORD[(256-256)+rcx],ymm0
+	vpshufd	ymm2,ymm3,0xaa
+	vmovdqa	YMMWORD[(288-256)+rcx],ymm1
+	vpshufd	ymm3,ymm3,0xff
+	vmovdqa	YMMWORD[(320-256)+rcx],ymm2
+	vmovdqa	YMMWORD[(352-256)+rcx],ymm3
+
+	vpshufd	ymm12,ymm15,0x00
+	vpshufd	ymm13,ymm15,0x55
+	vmovdqa	YMMWORD[(384-512)+rax],ymm12
+	vpshufd	ymm14,ymm15,0xaa
+	vmovdqa	YMMWORD[(416-512)+rax],ymm13
+	vpshufd	ymm15,ymm15,0xff
+	vmovdqa	YMMWORD[(448-512)+rax],ymm14
+	vmovdqa	YMMWORD[(480-512)+rax],ymm15
+
+	vpshufd	ymm4,ymm7,0x00
+	vpshufd	ymm5,ymm7,0x55
+	vpaddd	ymm4,ymm4,YMMWORD[$L$incy]
+	vpshufd	ymm6,ymm7,0xaa
+	vmovdqa	YMMWORD[(544-512)+rax],ymm5
+	vpshufd	ymm7,ymm7,0xff
+	vmovdqa	YMMWORD[(576-512)+rax],ymm6
+	vmovdqa	YMMWORD[(608-512)+rax],ymm7
+
+	jmp	NEAR $L$oop_enter8x
+
+ALIGN	32
+$L$oop_outer8x:
+	vmovdqa	ymm8,YMMWORD[((128-256))+rcx]
+	vmovdqa	ymm9,YMMWORD[((160-256))+rcx]
+	vmovdqa	ymm10,YMMWORD[((192-256))+rcx]
+	vmovdqa	ymm11,YMMWORD[((224-256))+rcx]
+	vmovdqa	ymm0,YMMWORD[((256-256))+rcx]
+	vmovdqa	ymm1,YMMWORD[((288-256))+rcx]
+	vmovdqa	ymm2,YMMWORD[((320-256))+rcx]
+	vmovdqa	ymm3,YMMWORD[((352-256))+rcx]
+	vmovdqa	ymm12,YMMWORD[((384-512))+rax]
+	vmovdqa	ymm13,YMMWORD[((416-512))+rax]
+	vmovdqa	ymm14,YMMWORD[((448-512))+rax]
+	vmovdqa	ymm15,YMMWORD[((480-512))+rax]
+	vmovdqa	ymm4,YMMWORD[((512-512))+rax]
+	vmovdqa	ymm5,YMMWORD[((544-512))+rax]
+	vmovdqa	ymm6,YMMWORD[((576-512))+rax]
+	vmovdqa	ymm7,YMMWORD[((608-512))+rax]
+	vpaddd	ymm4,ymm4,YMMWORD[$L$eight]
+
+$L$oop_enter8x:
+	vmovdqa	YMMWORD[64+rsp],ymm14
+	vmovdqa	YMMWORD[96+rsp],ymm15
+	vbroadcasti128	ymm15,XMMWORD[r10]
+	vmovdqa	YMMWORD[(512-512)+rax],ymm4
+	mov	eax,10
+	jmp	NEAR $L$oop8x
+
+ALIGN	32
+$L$oop8x:
+	vpaddd	ymm8,ymm8,ymm0
+	vpxor	ymm4,ymm8,ymm4
+	vpshufb	ymm4,ymm4,ymm15
+	vpaddd	ymm9,ymm9,ymm1
+	vpxor	ymm5,ymm9,ymm5
+	vpshufb	ymm5,ymm5,ymm15
+	vpaddd	ymm12,ymm12,ymm4
+	vpxor	ymm0,ymm12,ymm0
+	vpslld	ymm14,ymm0,12
+	vpsrld	ymm0,ymm0,20
+	vpor	ymm0,ymm14,ymm0
+	vbroadcasti128	ymm14,XMMWORD[r11]
+	vpaddd	ymm13,ymm13,ymm5
+	vpxor	ymm1,ymm13,ymm1
+	vpslld	ymm15,ymm1,12
+	vpsrld	ymm1,ymm1,20
+	vpor	ymm1,ymm15,ymm1
+	vpaddd	ymm8,ymm8,ymm0
+	vpxor	ymm4,ymm8,ymm4
+	vpshufb	ymm4,ymm4,ymm14
+	vpaddd	ymm9,ymm9,ymm1
+	vpxor	ymm5,ymm9,ymm5
+	vpshufb	ymm5,ymm5,ymm14
+	vpaddd	ymm12,ymm12,ymm4
+	vpxor	ymm0,ymm12,ymm0
+	vpslld	ymm15,ymm0,7
+	vpsrld	ymm0,ymm0,25
+	vpor	ymm0,ymm15,ymm0
+	vbroadcasti128	ymm15,XMMWORD[r10]
+	vpaddd	ymm13,ymm13,ymm5
+	vpxor	ymm1,ymm13,ymm1
+	vpslld	ymm14,ymm1,7
+	vpsrld	ymm1,ymm1,25
+	vpor	ymm1,ymm14,ymm1
+	vmovdqa	YMMWORD[rsp],ymm12
+	vmovdqa	YMMWORD[32+rsp],ymm13
+	vmovdqa	ymm12,YMMWORD[64+rsp]
+	vmovdqa	ymm13,YMMWORD[96+rsp]
+	vpaddd	ymm10,ymm10,ymm2
+	vpxor	ymm6,ymm10,ymm6
+	vpshufb	ymm6,ymm6,ymm15
+	vpaddd	ymm11,ymm11,ymm3
+	vpxor	ymm7,ymm11,ymm7
+	vpshufb	ymm7,ymm7,ymm15
+	vpaddd	ymm12,ymm12,ymm6
+	vpxor	ymm2,ymm12,ymm2
+	vpslld	ymm14,ymm2,12
+	vpsrld	ymm2,ymm2,20
+	vpor	ymm2,ymm14,ymm2
+	vbroadcasti128	ymm14,XMMWORD[r11]
+	vpaddd	ymm13,ymm13,ymm7
+	vpxor	ymm3,ymm13,ymm3
+	vpslld	ymm15,ymm3,12
+	vpsrld	ymm3,ymm3,20
+	vpor	ymm3,ymm15,ymm3
+	vpaddd	ymm10,ymm10,ymm2
+	vpxor	ymm6,ymm10,ymm6
+	vpshufb	ymm6,ymm6,ymm14
+	vpaddd	ymm11,ymm11,ymm3
+	vpxor	ymm7,ymm11,ymm7
+	vpshufb	ymm7,ymm7,ymm14
+	vpaddd	ymm12,ymm12,ymm6
+	vpxor	ymm2,ymm12,ymm2
+	vpslld	ymm15,ymm2,7
+	vpsrld	ymm2,ymm2,25
+	vpor	ymm2,ymm15,ymm2
+	vbroadcasti128	ymm15,XMMWORD[r10]
+	vpaddd	ymm13,ymm13,ymm7
+	vpxor	ymm3,ymm13,ymm3
+	vpslld	ymm14,ymm3,7
+	vpsrld	ymm3,ymm3,25
+	vpor	ymm3,ymm14,ymm3
+	vpaddd	ymm8,ymm8,ymm1
+	vpxor	ymm7,ymm8,ymm7
+	vpshufb	ymm7,ymm7,ymm15
+	vpaddd	ymm9,ymm9,ymm2
+	vpxor	ymm4,ymm9,ymm4
+	vpshufb	ymm4,ymm4,ymm15
+	vpaddd	ymm12,ymm12,ymm7
+	vpxor	ymm1,ymm12,ymm1
+	vpslld	ymm14,ymm1,12
+	vpsrld	ymm1,ymm1,20
+	vpor	ymm1,ymm14,ymm1
+	vbroadcasti128	ymm14,XMMWORD[r11]
+	vpaddd	ymm13,ymm13,ymm4
+	vpxor	ymm2,ymm13,ymm2
+	vpslld	ymm15,ymm2,12
+	vpsrld	ymm2,ymm2,20
+	vpor	ymm2,ymm15,ymm2
+	vpaddd	ymm8,ymm8,ymm1
+	vpxor	ymm7,ymm8,ymm7
+	vpshufb	ymm7,ymm7,ymm14
+	vpaddd	ymm9,ymm9,ymm2
+	vpxor	ymm4,ymm9,ymm4
+	vpshufb	ymm4,ymm4,ymm14
+	vpaddd	ymm12,ymm12,ymm7
+	vpxor	ymm1,ymm12,ymm1
+	vpslld	ymm15,ymm1,7
+	vpsrld	ymm1,ymm1,25
+	vpor	ymm1,ymm15,ymm1
+	vbroadcasti128	ymm15,XMMWORD[r10]
+	vpaddd	ymm13,ymm13,ymm4
+	vpxor	ymm2,ymm13,ymm2
+	vpslld	ymm14,ymm2,7
+	vpsrld	ymm2,ymm2,25
+	vpor	ymm2,ymm14,ymm2
+	vmovdqa	YMMWORD[64+rsp],ymm12
+	vmovdqa	YMMWORD[96+rsp],ymm13
+	vmovdqa	ymm12,YMMWORD[rsp]
+	vmovdqa	ymm13,YMMWORD[32+rsp]
+	vpaddd	ymm10,ymm10,ymm3
+	vpxor	ymm5,ymm10,ymm5
+	vpshufb	ymm5,ymm5,ymm15
+	vpaddd	ymm11,ymm11,ymm0
+	vpxor	ymm6,ymm11,ymm6
+	vpshufb	ymm6,ymm6,ymm15
+	vpaddd	ymm12,ymm12,ymm5
+	vpxor	ymm3,ymm12,ymm3
+	vpslld	ymm14,ymm3,12
+	vpsrld	ymm3,ymm3,20
+	vpor	ymm3,ymm14,ymm3
+	vbroadcasti128	ymm14,XMMWORD[r11]
+	vpaddd	ymm13,ymm13,ymm6
+	vpxor	ymm0,ymm13,ymm0
+	vpslld	ymm15,ymm0,12
+	vpsrld	ymm0,ymm0,20
+	vpor	ymm0,ymm15,ymm0
+	vpaddd	ymm10,ymm10,ymm3
+	vpxor	ymm5,ymm10,ymm5
+	vpshufb	ymm5,ymm5,ymm14
+	vpaddd	ymm11,ymm11,ymm0
+	vpxor	ymm6,ymm11,ymm6
+	vpshufb	ymm6,ymm6,ymm14
+	vpaddd	ymm12,ymm12,ymm5
+	vpxor	ymm3,ymm12,ymm3
+	vpslld	ymm15,ymm3,7
+	vpsrld	ymm3,ymm3,25
+	vpor	ymm3,ymm15,ymm3
+	vbroadcasti128	ymm15,XMMWORD[r10]
+	vpaddd	ymm13,ymm13,ymm6
+	vpxor	ymm0,ymm13,ymm0
+	vpslld	ymm14,ymm0,7
+	vpsrld	ymm0,ymm0,25
+	vpor	ymm0,ymm14,ymm0
+	dec	eax
+	jnz	NEAR $L$oop8x
+
+	lea	rax,[512+rsp]
+	vpaddd	ymm8,ymm8,YMMWORD[((128-256))+rcx]
+	vpaddd	ymm9,ymm9,YMMWORD[((160-256))+rcx]
+	vpaddd	ymm10,ymm10,YMMWORD[((192-256))+rcx]
+	vpaddd	ymm11,ymm11,YMMWORD[((224-256))+rcx]
+
+	vpunpckldq	ymm14,ymm8,ymm9
+	vpunpckldq	ymm15,ymm10,ymm11
+	vpunpckhdq	ymm8,ymm8,ymm9
+	vpunpckhdq	ymm10,ymm10,ymm11
+	vpunpcklqdq	ymm9,ymm14,ymm15
+	vpunpckhqdq	ymm14,ymm14,ymm15
+	vpunpcklqdq	ymm11,ymm8,ymm10
+	vpunpckhqdq	ymm8,ymm8,ymm10
+	vpaddd	ymm0,ymm0,YMMWORD[((256-256))+rcx]
+	vpaddd	ymm1,ymm1,YMMWORD[((288-256))+rcx]
+	vpaddd	ymm2,ymm2,YMMWORD[((320-256))+rcx]
+	vpaddd	ymm3,ymm3,YMMWORD[((352-256))+rcx]
+
+	vpunpckldq	ymm10,ymm0,ymm1
+	vpunpckldq	ymm15,ymm2,ymm3
+	vpunpckhdq	ymm0,ymm0,ymm1
+	vpunpckhdq	ymm2,ymm2,ymm3
+	vpunpcklqdq	ymm1,ymm10,ymm15
+	vpunpckhqdq	ymm10,ymm10,ymm15
+	vpunpcklqdq	ymm3,ymm0,ymm2
+	vpunpckhqdq	ymm0,ymm0,ymm2
+	vperm2i128	ymm15,ymm9,ymm1,0x20
+	vperm2i128	ymm1,ymm9,ymm1,0x31
+	vperm2i128	ymm9,ymm14,ymm10,0x20
+	vperm2i128	ymm10,ymm14,ymm10,0x31
+	vperm2i128	ymm14,ymm11,ymm3,0x20
+	vperm2i128	ymm3,ymm11,ymm3,0x31
+	vperm2i128	ymm11,ymm8,ymm0,0x20
+	vperm2i128	ymm0,ymm8,ymm0,0x31
+	vmovdqa	YMMWORD[rsp],ymm15
+	vmovdqa	YMMWORD[32+rsp],ymm9
+	vmovdqa	ymm15,YMMWORD[64+rsp]
+	vmovdqa	ymm9,YMMWORD[96+rsp]
+
+	vpaddd	ymm12,ymm12,YMMWORD[((384-512))+rax]
+	vpaddd	ymm13,ymm13,YMMWORD[((416-512))+rax]
+	vpaddd	ymm15,ymm15,YMMWORD[((448-512))+rax]
+	vpaddd	ymm9,ymm9,YMMWORD[((480-512))+rax]
+
+	vpunpckldq	ymm2,ymm12,ymm13
+	vpunpckldq	ymm8,ymm15,ymm9
+	vpunpckhdq	ymm12,ymm12,ymm13
+	vpunpckhdq	ymm15,ymm15,ymm9
+	vpunpcklqdq	ymm13,ymm2,ymm8
+	vpunpckhqdq	ymm2,ymm2,ymm8
+	vpunpcklqdq	ymm9,ymm12,ymm15
+	vpunpckhqdq	ymm12,ymm12,ymm15
+	vpaddd	ymm4,ymm4,YMMWORD[((512-512))+rax]
+	vpaddd	ymm5,ymm5,YMMWORD[((544-512))+rax]
+	vpaddd	ymm6,ymm6,YMMWORD[((576-512))+rax]
+	vpaddd	ymm7,ymm7,YMMWORD[((608-512))+rax]
+
+	vpunpckldq	ymm15,ymm4,ymm5
+	vpunpckldq	ymm8,ymm6,ymm7
+	vpunpckhdq	ymm4,ymm4,ymm5
+	vpunpckhdq	ymm6,ymm6,ymm7
+	vpunpcklqdq	ymm5,ymm15,ymm8
+	vpunpckhqdq	ymm15,ymm15,ymm8
+	vpunpcklqdq	ymm7,ymm4,ymm6
+	vpunpckhqdq	ymm4,ymm4,ymm6
+	vperm2i128	ymm8,ymm13,ymm5,0x20
+	vperm2i128	ymm5,ymm13,ymm5,0x31
+	vperm2i128	ymm13,ymm2,ymm15,0x20
+	vperm2i128	ymm15,ymm2,ymm15,0x31
+	vperm2i128	ymm2,ymm9,ymm7,0x20
+	vperm2i128	ymm7,ymm9,ymm7,0x31
+	vperm2i128	ymm9,ymm12,ymm4,0x20
+	vperm2i128	ymm4,ymm12,ymm4,0x31
+	vmovdqa	ymm6,YMMWORD[rsp]
+	vmovdqa	ymm12,YMMWORD[32+rsp]
+
+	cmp	rdx,64*8
+	jb	NEAR $L$tail8x
+
+	vpxor	ymm6,ymm6,YMMWORD[rsi]
+	vpxor	ymm8,ymm8,YMMWORD[32+rsi]
+	vpxor	ymm1,ymm1,YMMWORD[64+rsi]
+	vpxor	ymm5,ymm5,YMMWORD[96+rsi]
+	lea	rsi,[128+rsi]
+	vmovdqu	YMMWORD[rdi],ymm6
+	vmovdqu	YMMWORD[32+rdi],ymm8
+	vmovdqu	YMMWORD[64+rdi],ymm1
+	vmovdqu	YMMWORD[96+rdi],ymm5
+	lea	rdi,[128+rdi]
+
+	vpxor	ymm12,ymm12,YMMWORD[rsi]
+	vpxor	ymm13,ymm13,YMMWORD[32+rsi]
+	vpxor	ymm10,ymm10,YMMWORD[64+rsi]
+	vpxor	ymm15,ymm15,YMMWORD[96+rsi]
+	lea	rsi,[128+rsi]
+	vmovdqu	YMMWORD[rdi],ymm12
+	vmovdqu	YMMWORD[32+rdi],ymm13
+	vmovdqu	YMMWORD[64+rdi],ymm10
+	vmovdqu	YMMWORD[96+rdi],ymm15
+	lea	rdi,[128+rdi]
+
+	vpxor	ymm14,ymm14,YMMWORD[rsi]
+	vpxor	ymm2,ymm2,YMMWORD[32+rsi]
+	vpxor	ymm3,ymm3,YMMWORD[64+rsi]
+	vpxor	ymm7,ymm7,YMMWORD[96+rsi]
+	lea	rsi,[128+rsi]
+	vmovdqu	YMMWORD[rdi],ymm14
+	vmovdqu	YMMWORD[32+rdi],ymm2
+	vmovdqu	YMMWORD[64+rdi],ymm3
+	vmovdqu	YMMWORD[96+rdi],ymm7
+	lea	rdi,[128+rdi]
+
+	vpxor	ymm11,ymm11,YMMWORD[rsi]
+	vpxor	ymm9,ymm9,YMMWORD[32+rsi]
+	vpxor	ymm0,ymm0,YMMWORD[64+rsi]
+	vpxor	ymm4,ymm4,YMMWORD[96+rsi]
+	lea	rsi,[128+rsi]
+	vmovdqu	YMMWORD[rdi],ymm11
+	vmovdqu	YMMWORD[32+rdi],ymm9
+	vmovdqu	YMMWORD[64+rdi],ymm0
+	vmovdqu	YMMWORD[96+rdi],ymm4
+	lea	rdi,[128+rdi]
+
+	sub	rdx,64*8
+	jnz	NEAR $L$oop_outer8x
+
+	jmp	NEAR $L$done8x
+
+$L$tail8x:
+	cmp	rdx,448
+	jae	NEAR $L$448_or_more8x
+	cmp	rdx,384
+	jae	NEAR $L$384_or_more8x
+	cmp	rdx,320
+	jae	NEAR $L$320_or_more8x
+	cmp	rdx,256
+	jae	NEAR $L$256_or_more8x
+	cmp	rdx,192
+	jae	NEAR $L$192_or_more8x
+	cmp	rdx,128
+	jae	NEAR $L$128_or_more8x
+	cmp	rdx,64
+	jae	NEAR $L$64_or_more8x
+
+	xor	r10,r10
+	vmovdqa	YMMWORD[rsp],ymm6
+	vmovdqa	YMMWORD[32+rsp],ymm8
+	jmp	NEAR $L$oop_tail8x
+
+ALIGN	32
+$L$64_or_more8x:
+	vpxor	ymm6,ymm6,YMMWORD[rsi]
+	vpxor	ymm8,ymm8,YMMWORD[32+rsi]
+	vmovdqu	YMMWORD[rdi],ymm6
+	vmovdqu	YMMWORD[32+rdi],ymm8
+	je	NEAR $L$done8x
+
+	lea	rsi,[64+rsi]
+	xor	r10,r10
+	vmovdqa	YMMWORD[rsp],ymm1
+	lea	rdi,[64+rdi]
+	sub	rdx,64
+	vmovdqa	YMMWORD[32+rsp],ymm5
+	jmp	NEAR $L$oop_tail8x
+
+ALIGN	32
+$L$128_or_more8x:
+	vpxor	ymm6,ymm6,YMMWORD[rsi]
+	vpxor	ymm8,ymm8,YMMWORD[32+rsi]
+	vpxor	ymm1,ymm1,YMMWORD[64+rsi]
+	vpxor	ymm5,ymm5,YMMWORD[96+rsi]
+	vmovdqu	YMMWORD[rdi],ymm6
+	vmovdqu	YMMWORD[32+rdi],ymm8
+	vmovdqu	YMMWORD[64+rdi],ymm1
+	vmovdqu	YMMWORD[96+rdi],ymm5
+	je	NEAR $L$done8x
+
+	lea	rsi,[128+rsi]
+	xor	r10,r10
+	vmovdqa	YMMWORD[rsp],ymm12
+	lea	rdi,[128+rdi]
+	sub	rdx,128
+	vmovdqa	YMMWORD[32+rsp],ymm13
+	jmp	NEAR $L$oop_tail8x
+
+ALIGN	32
+$L$192_or_more8x:
+	vpxor	ymm6,ymm6,YMMWORD[rsi]
+	vpxor	ymm8,ymm8,YMMWORD[32+rsi]
+	vpxor	ymm1,ymm1,YMMWORD[64+rsi]
+	vpxor	ymm5,ymm5,YMMWORD[96+rsi]
+	vpxor	ymm12,ymm12,YMMWORD[128+rsi]
+	vpxor	ymm13,ymm13,YMMWORD[160+rsi]
+	vmovdqu	YMMWORD[rdi],ymm6
+	vmovdqu	YMMWORD[32+rdi],ymm8
+	vmovdqu	YMMWORD[64+rdi],ymm1
+	vmovdqu	YMMWORD[96+rdi],ymm5
+	vmovdqu	YMMWORD[128+rdi],ymm12
+	vmovdqu	YMMWORD[160+rdi],ymm13
+	je	NEAR $L$done8x
+
+	lea	rsi,[192+rsi]
+	xor	r10,r10
+	vmovdqa	YMMWORD[rsp],ymm10
+	lea	rdi,[192+rdi]
+	sub	rdx,192
+	vmovdqa	YMMWORD[32+rsp],ymm15
+	jmp	NEAR $L$oop_tail8x
+
+ALIGN	32
+$L$256_or_more8x:
+	vpxor	ymm6,ymm6,YMMWORD[rsi]
+	vpxor	ymm8,ymm8,YMMWORD[32+rsi]
+	vpxor	ymm1,ymm1,YMMWORD[64+rsi]
+	vpxor	ymm5,ymm5,YMMWORD[96+rsi]
+	vpxor	ymm12,ymm12,YMMWORD[128+rsi]
+	vpxor	ymm13,ymm13,YMMWORD[160+rsi]
+	vpxor	ymm10,ymm10,YMMWORD[192+rsi]
+	vpxor	ymm15,ymm15,YMMWORD[224+rsi]
+	vmovdqu	YMMWORD[rdi],ymm6
+	vmovdqu	YMMWORD[32+rdi],ymm8
+	vmovdqu	YMMWORD[64+rdi],ymm1
+	vmovdqu	YMMWORD[96+rdi],ymm5
+	vmovdqu	YMMWORD[128+rdi],ymm12
+	vmovdqu	YMMWORD[160+rdi],ymm13
+	vmovdqu	YMMWORD[192+rdi],ymm10
+	vmovdqu	YMMWORD[224+rdi],ymm15
+	je	NEAR $L$done8x
+
+	lea	rsi,[256+rsi]
+	xor	r10,r10
+	vmovdqa	YMMWORD[rsp],ymm14
+	lea	rdi,[256+rdi]
+	sub	rdx,256
+	vmovdqa	YMMWORD[32+rsp],ymm2
+	jmp	NEAR $L$oop_tail8x
+
+ALIGN	32
+$L$320_or_more8x:
+	vpxor	ymm6,ymm6,YMMWORD[rsi]
+	vpxor	ymm8,ymm8,YMMWORD[32+rsi]
+	vpxor	ymm1,ymm1,YMMWORD[64+rsi]
+	vpxor	ymm5,ymm5,YMMWORD[96+rsi]
+	vpxor	ymm12,ymm12,YMMWORD[128+rsi]
+	vpxor	ymm13,ymm13,YMMWORD[160+rsi]
+	vpxor	ymm10,ymm10,YMMWORD[192+rsi]
+	vpxor	ymm15,ymm15,YMMWORD[224+rsi]
+	vpxor	ymm14,ymm14,YMMWORD[256+rsi]
+	vpxor	ymm2,ymm2,YMMWORD[288+rsi]
+	vmovdqu	YMMWORD[rdi],ymm6
+	vmovdqu	YMMWORD[32+rdi],ymm8
+	vmovdqu	YMMWORD[64+rdi],ymm1
+	vmovdqu	YMMWORD[96+rdi],ymm5
+	vmovdqu	YMMWORD[128+rdi],ymm12
+	vmovdqu	YMMWORD[160+rdi],ymm13
+	vmovdqu	YMMWORD[192+rdi],ymm10
+	vmovdqu	YMMWORD[224+rdi],ymm15
+	vmovdqu	YMMWORD[256+rdi],ymm14
+	vmovdqu	YMMWORD[288+rdi],ymm2
+	je	NEAR $L$done8x
+
+	lea	rsi,[320+rsi]
+	xor	r10,r10
+	vmovdqa	YMMWORD[rsp],ymm3
+	lea	rdi,[320+rdi]
+	sub	rdx,320
+	vmovdqa	YMMWORD[32+rsp],ymm7
+	jmp	NEAR $L$oop_tail8x
+
+ALIGN	32
+$L$384_or_more8x:
+	vpxor	ymm6,ymm6,YMMWORD[rsi]
+	vpxor	ymm8,ymm8,YMMWORD[32+rsi]
+	vpxor	ymm1,ymm1,YMMWORD[64+rsi]
+	vpxor	ymm5,ymm5,YMMWORD[96+rsi]
+	vpxor	ymm12,ymm12,YMMWORD[128+rsi]
+	vpxor	ymm13,ymm13,YMMWORD[160+rsi]
+	vpxor	ymm10,ymm10,YMMWORD[192+rsi]
+	vpxor	ymm15,ymm15,YMMWORD[224+rsi]
+	vpxor	ymm14,ymm14,YMMWORD[256+rsi]
+	vpxor	ymm2,ymm2,YMMWORD[288+rsi]
+	vpxor	ymm3,ymm3,YMMWORD[320+rsi]
+	vpxor	ymm7,ymm7,YMMWORD[352+rsi]
+	vmovdqu	YMMWORD[rdi],ymm6
+	vmovdqu	YMMWORD[32+rdi],ymm8
+	vmovdqu	YMMWORD[64+rdi],ymm1
+	vmovdqu	YMMWORD[96+rdi],ymm5
+	vmovdqu	YMMWORD[128+rdi],ymm12
+	vmovdqu	YMMWORD[160+rdi],ymm13
+	vmovdqu	YMMWORD[192+rdi],ymm10
+	vmovdqu	YMMWORD[224+rdi],ymm15
+	vmovdqu	YMMWORD[256+rdi],ymm14
+	vmovdqu	YMMWORD[288+rdi],ymm2
+	vmovdqu	YMMWORD[320+rdi],ymm3
+	vmovdqu	YMMWORD[352+rdi],ymm7
+	je	NEAR $L$done8x
+
+	lea	rsi,[384+rsi]
+	xor	r10,r10
+	vmovdqa	YMMWORD[rsp],ymm11
+	lea	rdi,[384+rdi]
+	sub	rdx,384
+	vmovdqa	YMMWORD[32+rsp],ymm9
+	jmp	NEAR $L$oop_tail8x
+
+ALIGN	32
+$L$448_or_more8x:
+	vpxor	ymm6,ymm6,YMMWORD[rsi]
+	vpxor	ymm8,ymm8,YMMWORD[32+rsi]
+	vpxor	ymm1,ymm1,YMMWORD[64+rsi]
+	vpxor	ymm5,ymm5,YMMWORD[96+rsi]
+	vpxor	ymm12,ymm12,YMMWORD[128+rsi]
+	vpxor	ymm13,ymm13,YMMWORD[160+rsi]
+	vpxor	ymm10,ymm10,YMMWORD[192+rsi]
+	vpxor	ymm15,ymm15,YMMWORD[224+rsi]
+	vpxor	ymm14,ymm14,YMMWORD[256+rsi]
+	vpxor	ymm2,ymm2,YMMWORD[288+rsi]
+	vpxor	ymm3,ymm3,YMMWORD[320+rsi]
+	vpxor	ymm7,ymm7,YMMWORD[352+rsi]
+	vpxor	ymm11,ymm11,YMMWORD[384+rsi]
+	vpxor	ymm9,ymm9,YMMWORD[416+rsi]
+	vmovdqu	YMMWORD[rdi],ymm6
+	vmovdqu	YMMWORD[32+rdi],ymm8
+	vmovdqu	YMMWORD[64+rdi],ymm1
+	vmovdqu	YMMWORD[96+rdi],ymm5
+	vmovdqu	YMMWORD[128+rdi],ymm12
+	vmovdqu	YMMWORD[160+rdi],ymm13
+	vmovdqu	YMMWORD[192+rdi],ymm10
+	vmovdqu	YMMWORD[224+rdi],ymm15
+	vmovdqu	YMMWORD[256+rdi],ymm14
+	vmovdqu	YMMWORD[288+rdi],ymm2
+	vmovdqu	YMMWORD[320+rdi],ymm3
+	vmovdqu	YMMWORD[352+rdi],ymm7
+	vmovdqu	YMMWORD[384+rdi],ymm11
+	vmovdqu	YMMWORD[416+rdi],ymm9
+	je	NEAR $L$done8x
+
+	lea	rsi,[448+rsi]
+	xor	r10,r10
+	vmovdqa	YMMWORD[rsp],ymm0
+	lea	rdi,[448+rdi]
+	sub	rdx,448
+	vmovdqa	YMMWORD[32+rsp],ymm4
+
+$L$oop_tail8x:
+	movzx	eax,BYTE[r10*1+rsi]
+	movzx	ecx,BYTE[r10*1+rsp]
+	lea	r10,[1+r10]
+	xor	eax,ecx
+	mov	BYTE[((-1))+r10*1+rdi],al
+	dec	rdx
+	jnz	NEAR $L$oop_tail8x
+
+$L$done8x:
+	vzeroall
+	movaps	xmm6,XMMWORD[((-168))+r9]
+	movaps	xmm7,XMMWORD[((-152))+r9]
+	movaps	xmm8,XMMWORD[((-136))+r9]
+	movaps	xmm9,XMMWORD[((-120))+r9]
+	movaps	xmm10,XMMWORD[((-104))+r9]
+	movaps	xmm11,XMMWORD[((-88))+r9]
+	movaps	xmm12,XMMWORD[((-72))+r9]
+	movaps	xmm13,XMMWORD[((-56))+r9]
+	movaps	xmm14,XMMWORD[((-40))+r9]
+	movaps	xmm15,XMMWORD[((-24))+r9]
+	lea	rsp,[r9]
+$L$8x_epilogue:
+	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_ChaCha20_8x:
+EXTERN	__imp_RtlVirtualUnwind
+
+ALIGN	16
+se_handler:
+	push	rsi
+	push	rdi
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	pushfq
+	sub	rsp,64
+
+	mov	rax,QWORD[120+r8]
+	mov	rbx,QWORD[248+r8]
+
+	mov	rsi,QWORD[8+r9]
+	mov	r11,QWORD[56+r9]
+
+	lea	r10,[$L$ctr32_body]
+	cmp	rbx,r10
+	jb	NEAR $L$common_seh_tail
+
+	mov	rax,QWORD[152+r8]
+
+	lea	r10,[$L$no_data]
+	cmp	rbx,r10
+	jae	NEAR $L$common_seh_tail
+
+	lea	rax,[((64+24+48))+rax]
+
+	mov	rbx,QWORD[((-8))+rax]
+	mov	rbp,QWORD[((-16))+rax]
+	mov	r12,QWORD[((-24))+rax]
+	mov	r13,QWORD[((-32))+rax]
+	mov	r14,QWORD[((-40))+rax]
+	mov	r15,QWORD[((-48))+rax]
+	mov	QWORD[144+r8],rbx
+	mov	QWORD[160+r8],rbp
+	mov	QWORD[216+r8],r12
+	mov	QWORD[224+r8],r13
+	mov	QWORD[232+r8],r14
+	mov	QWORD[240+r8],r15
+
+$L$common_seh_tail:
+	mov	rdi,QWORD[8+rax]
+	mov	rsi,QWORD[16+rax]
+	mov	QWORD[152+r8],rax
+	mov	QWORD[168+r8],rsi
+	mov	QWORD[176+r8],rdi
+
+	mov	rdi,QWORD[40+r9]
+	mov	rsi,r8
+	mov	ecx,154
+	DD	0xa548f3fc
+
+	mov	rsi,r9
+	xor	rcx,rcx
+	mov	rdx,QWORD[8+rsi]
+	mov	r8,QWORD[rsi]
+	mov	r9,QWORD[16+rsi]
+	mov	r10,QWORD[40+rsi]
+	lea	r11,[56+rsi]
+	lea	r12,[24+rsi]
+	mov	QWORD[32+rsp],r10
+	mov	QWORD[40+rsp],r11
+	mov	QWORD[48+rsp],r12
+	mov	QWORD[56+rsp],rcx
+	call	QWORD[__imp_RtlVirtualUnwind]
+
+	mov	eax,1
+	add	rsp,64
+	popfq
+	pop	r15
+	pop	r14
+	pop	r13
+	pop	r12
+	pop	rbp
+	pop	rbx
+	pop	rdi
+	pop	rsi
+	DB	0F3h,0C3h		;repret
+
+
+
+ALIGN	16
+ssse3_handler:
+	push	rsi
+	push	rdi
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	pushfq
+	sub	rsp,64
+
+	mov	rax,QWORD[120+r8]
+	mov	rbx,QWORD[248+r8]
+
+	mov	rsi,QWORD[8+r9]
+	mov	r11,QWORD[56+r9]
+
+	mov	r10d,DWORD[r11]
+	lea	r10,[r10*1+rsi]
+	cmp	rbx,r10
+	jb	NEAR $L$common_seh_tail
+
+	mov	rax,QWORD[192+r8]
+
+	mov	r10d,DWORD[4+r11]
+	lea	r10,[r10*1+rsi]
+	cmp	rbx,r10
+	jae	NEAR $L$common_seh_tail
+
+	lea	rsi,[((-40))+rax]
+	lea	rdi,[512+r8]
+	mov	ecx,4
+	DD	0xa548f3fc
+
+	jmp	NEAR $L$common_seh_tail
+
+
+
+ALIGN	16
+full_handler:
+	push	rsi
+	push	rdi
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	pushfq
+	sub	rsp,64
+
+	mov	rax,QWORD[120+r8]
+	mov	rbx,QWORD[248+r8]
+
+	mov	rsi,QWORD[8+r9]
+	mov	r11,QWORD[56+r9]
+
+	mov	r10d,DWORD[r11]
+	lea	r10,[r10*1+rsi]
+	cmp	rbx,r10
+	jb	NEAR $L$common_seh_tail
+
+	mov	rax,QWORD[192+r8]
+
+	mov	r10d,DWORD[4+r11]
+	lea	r10,[r10*1+rsi]
+	cmp	rbx,r10
+	jae	NEAR $L$common_seh_tail
+
+	lea	rsi,[((-168))+rax]
+	lea	rdi,[512+r8]
+	mov	ecx,20
+	DD	0xa548f3fc
+
+	jmp	NEAR $L$common_seh_tail
+
+
+section	.pdata rdata align=4
+ALIGN	4
+	DD	$L$SEH_begin_ChaCha20_ctr32 wrt ..imagebase
+	DD	$L$SEH_end_ChaCha20_ctr32 wrt ..imagebase
+	DD	$L$SEH_info_ChaCha20_ctr32 wrt ..imagebase
+
+	DD	$L$SEH_begin_ChaCha20_ssse3 wrt ..imagebase
+	DD	$L$SEH_end_ChaCha20_ssse3 wrt ..imagebase
+	DD	$L$SEH_info_ChaCha20_ssse3 wrt ..imagebase
+
+	DD	$L$SEH_begin_ChaCha20_4x wrt ..imagebase
+	DD	$L$SEH_end_ChaCha20_4x wrt ..imagebase
+	DD	$L$SEH_info_ChaCha20_4x wrt ..imagebase
+	DD	$L$SEH_begin_ChaCha20_8x wrt ..imagebase
+	DD	$L$SEH_end_ChaCha20_8x wrt ..imagebase
+	DD	$L$SEH_info_ChaCha20_8x wrt ..imagebase
+section	.xdata rdata align=8
+ALIGN	8
+$L$SEH_info_ChaCha20_ctr32:
+DB	9,0,0,0
+	DD	se_handler wrt ..imagebase
+
+$L$SEH_info_ChaCha20_ssse3:
+DB	9,0,0,0
+	DD	ssse3_handler wrt ..imagebase
+	DD	$L$ssse3_body wrt ..imagebase,$L$ssse3_epilogue wrt ..imagebase
+
+$L$SEH_info_ChaCha20_4x:
+DB	9,0,0,0
+	DD	full_handler wrt ..imagebase
+	DD	$L$4x_body wrt ..imagebase,$L$4x_epilogue wrt ..imagebase
+$L$SEH_info_ChaCha20_8x:
+DB	9,0,0,0
+	DD	full_handler wrt ..imagebase
+	DD	$L$8x_body wrt ..imagebase,$L$8x_epilogue wrt ..imagebase
diff --git a/win-x86_64/crypto/cipher/chacha20_poly1305_x86_64.asm b/win-x86_64/crypto/cipher/chacha20_poly1305_x86_64.asm
new file mode 100644
index 0000000..ab8cf92
--- /dev/null
+++ b/win-x86_64/crypto/cipher/chacha20_poly1305_x86_64.asm
@@ -0,0 +1,8 @@
+default	rel
+%define XMMWORD
+%define YMMWORD
+%define ZMMWORD
+global	dummy_chacha20_poly1305_asm
+
+dummy_chacha20_poly1305_asm:
+	DB	0F3h,0C3h		;repret
diff --git a/win-x86_64/crypto/ec/p256-x86_64-asm.asm b/win-x86_64/crypto/ec/p256-x86_64-asm.asm
index 45ba686..55db00e 100644
--- a/win-x86_64/crypto/ec/p256-x86_64-asm.asm
+++ b/win-x86_64/crypto/ec/p256-x86_64-asm.asm
@@ -21,57 +21,6 @@
 	DQ	0x0000000000000001,0xffffffff00000000,0xffffffffffffffff,0x00000000fffffffe
 
 
-ALIGN	64
-ecp_nistz256_mul_by_2:
-	mov	QWORD[8+rsp],rdi	;WIN64 prologue
-	mov	QWORD[16+rsp],rsi
-	mov	rax,rsp
-$L$SEH_begin_ecp_nistz256_mul_by_2:
-	mov	rdi,rcx
-	mov	rsi,rdx
-
-
-	push	r12
-	push	r13
-
-	mov	r8,QWORD[rsi]
-	mov	r9,QWORD[8+rsi]
-	add	r8,r8
-	mov	r10,QWORD[16+rsi]
-	adc	r9,r9
-	mov	r11,QWORD[24+rsi]
-	lea	rsi,[$L$poly]
-	mov	rax,r8
-	adc	r10,r10
-	adc	r11,r11
-	mov	rdx,r9
-	sbb	r13,r13
-
-	sub	r8,QWORD[rsi]
-	mov	rcx,r10
-	sbb	r9,QWORD[8+rsi]
-	sbb	r10,QWORD[16+rsi]
-	mov	r12,r11
-	sbb	r11,QWORD[24+rsi]
-	test	r13,r13
-
-	cmovz	r8,rax
-	cmovz	r9,rdx
-	mov	QWORD[rdi],r8
-	cmovz	r10,rcx
-	mov	QWORD[8+rdi],r9
-	cmovz	r11,r12
-	mov	QWORD[16+rdi],r10
-	mov	QWORD[24+rdi],r11
-
-	pop	r13
-	pop	r12
-	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
-	mov	rsi,QWORD[16+rsp]
-	DB	0F3h,0C3h		;repret
-$L$SEH_end_ecp_nistz256_mul_by_2:
-
-
 
 global	ecp_nistz256_neg
 
@@ -594,110 +543,6 @@
 
 
 
-
-
-
-
-global	ecp_nistz256_from_mont
-
-ALIGN	32
-ecp_nistz256_from_mont:
-	mov	QWORD[8+rsp],rdi	;WIN64 prologue
-	mov	QWORD[16+rsp],rsi
-	mov	rax,rsp
-$L$SEH_begin_ecp_nistz256_from_mont:
-	mov	rdi,rcx
-	mov	rsi,rdx
-
-
-	push	r12
-	push	r13
-
-	mov	rax,QWORD[rsi]
-	mov	r13,QWORD[(($L$poly+24))]
-	mov	r9,QWORD[8+rsi]
-	mov	r10,QWORD[16+rsi]
-	mov	r11,QWORD[24+rsi]
-	mov	r8,rax
-	mov	r12,QWORD[(($L$poly+8))]
-
-
-
-	mov	rcx,rax
-	shl	r8,32
-	mul	r13
-	shr	rcx,32
-	add	r9,r8
-	adc	r10,rcx
-	adc	r11,rax
-	mov	rax,r9
-	adc	rdx,0
-
-
-
-	mov	rcx,r9
-	shl	r9,32
-	mov	r8,rdx
-	mul	r13
-	shr	rcx,32
-	add	r10,r9
-	adc	r11,rcx
-	adc	r8,rax
-	mov	rax,r10
-	adc	rdx,0
-
-
-
-	mov	rcx,r10
-	shl	r10,32
-	mov	r9,rdx
-	mul	r13
-	shr	rcx,32
-	add	r11,r10
-	adc	r8,rcx
-	adc	r9,rax
-	mov	rax,r11
-	adc	rdx,0
-
-
-
-	mov	rcx,r11
-	shl	r11,32
-	mov	r10,rdx
-	mul	r13
-	shr	rcx,32
-	add	r8,r11
-	adc	r9,rcx
-	mov	rcx,r8
-	adc	r10,rax
-	mov	rsi,r9
-	adc	rdx,0
-
-	sub	r8,-1
-	mov	rax,r10
-	sbb	r9,r12
-	sbb	r10,0
-	mov	r11,rdx
-	sbb	rdx,r13
-	sbb	r13,r13
-
-	cmovnz	r8,rcx
-	cmovnz	r9,rsi
-	mov	QWORD[rdi],r8
-	cmovnz	r10,rax
-	mov	QWORD[8+rdi],r9
-	cmovz	r11,rdx
-	mov	QWORD[16+rdi],r10
-	mov	QWORD[24+rdi],r11
-
-	pop	r13
-	pop	r12
-	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
-	mov	rsi,QWORD[16+rsp]
-	DB	0F3h,0C3h		;repret
-$L$SEH_end_ecp_nistz256_from_mont:
-
-
 global	ecp_nistz256_select_w5
 
 ALIGN	32
@@ -873,13 +718,14 @@
 
 ALIGN	32
 __ecp_nistz256_add_toq:
+	xor	r11,r11
 	add	r12,QWORD[rbx]
 	adc	r13,QWORD[8+rbx]
 	mov	rax,r12
 	adc	r8,QWORD[16+rbx]
 	adc	r9,QWORD[24+rbx]
 	mov	rbp,r13
-	sbb	r11,r11
+	adc	r11,0
 
 	sub	r12,-1
 	mov	rcx,r8
@@ -887,14 +733,14 @@
 	sbb	r8,0
 	mov	r10,r9
 	sbb	r9,r15
-	test	r11,r11
+	sbb	r11,0
 
-	cmovz	r12,rax
-	cmovz	r13,rbp
+	cmovc	r12,rax
+	cmovc	r13,rbp
 	mov	QWORD[rdi],r12
-	cmovz	r8,rcx
+	cmovc	r8,rcx
 	mov	QWORD[8+rdi],r13
-	cmovz	r9,r10
+	cmovc	r9,r10
 	mov	QWORD[16+rdi],r8
 	mov	QWORD[24+rdi],r9
 
@@ -962,13 +808,14 @@
 
 ALIGN	32
 __ecp_nistz256_mul_by_2q:
+	xor	r11,r11
 	add	r12,r12
 	adc	r13,r13
 	mov	rax,r12
 	adc	r8,r8
 	adc	r9,r9
 	mov	rbp,r13
-	sbb	r11,r11
+	adc	r11,0
 
 	sub	r12,-1
 	mov	rcx,r8
@@ -976,14 +823,14 @@
 	sbb	r8,0
 	mov	r10,r9
 	sbb	r9,r15
-	test	r11,r11
+	sbb	r11,0
 
-	cmovz	r12,rax
-	cmovz	r13,rbp
+	cmovc	r12,rax
+	cmovc	r13,rbp
 	mov	QWORD[rdi],r12
-	cmovz	r8,rcx
+	cmovc	r8,rcx
 	mov	QWORD[8+rdi],r13
-	cmovz	r9,r10
+	cmovc	r9,r10
 	mov	QWORD[16+rdi],r8
 	mov	QWORD[24+rdi],r9
 
@@ -1009,6 +856,7 @@
 	push	r15
 	sub	rsp,32*5+8
 
+$L$point_double_shortcutq:
 	movdqu	xmm0,XMMWORD[rsi]
 	mov	rbx,rsi
 	movdqu	xmm1,XMMWORD[16+rsi]
@@ -1231,16 +1079,14 @@
 	mov	rsi,rdx
 	movdqa	XMMWORD[384+rsp],xmm0
 	movdqa	XMMWORD[(384+16)+rsp],xmm1
-	por	xmm1,xmm0
 	movdqa	XMMWORD[416+rsp],xmm2
 	movdqa	XMMWORD[(416+16)+rsp],xmm3
-	por	xmm3,xmm2
 	movdqa	XMMWORD[448+rsp],xmm4
 	movdqa	XMMWORD[(448+16)+rsp],xmm5
-	por	xmm3,xmm1
+	por	xmm5,xmm4
 
 	movdqu	xmm0,XMMWORD[rsi]
-	pshufd	xmm5,xmm3,0xb1
+	pshufd	xmm3,xmm5,0xb1
 	movdqu	xmm1,XMMWORD[16+rsi]
 	movdqu	xmm2,XMMWORD[32+rsi]
 	por	xmm5,xmm3
@@ -1252,14 +1098,14 @@
 	movdqa	XMMWORD[480+rsp],xmm0
 	pshufd	xmm4,xmm5,0x1e
 	movdqa	XMMWORD[(480+16)+rsp],xmm1
-	por	xmm1,xmm0
-DB	102,72,15,110,199
+	movdqu	xmm0,XMMWORD[64+rsi]
+	movdqu	xmm1,XMMWORD[80+rsi]
 	movdqa	XMMWORD[512+rsp],xmm2
 	movdqa	XMMWORD[(512+16)+rsp],xmm3
-	por	xmm3,xmm2
 	por	xmm5,xmm4
 	pxor	xmm4,xmm4
-	por	xmm3,xmm1
+	por	xmm1,xmm0
+DB	102,72,15,110,199
 
 	lea	rsi,[((64-0))+rsi]
 	mov	QWORD[((544+0))+rsp],rax
@@ -1270,8 +1116,8 @@
 	call	__ecp_nistz256_sqr_montq
 
 	pcmpeqd	xmm5,xmm4
-	pshufd	xmm4,xmm3,0xb1
-	por	xmm4,xmm3
+	pshufd	xmm4,xmm1,0xb1
+	por	xmm4,xmm1
 	pshufd	xmm5,xmm5,0
 	pshufd	xmm3,xmm4,0x1e
 	por	xmm4,xmm3
@@ -1282,6 +1128,7 @@
 	mov	r14,QWORD[((64+8))+rbx]
 	mov	r15,QWORD[((64+16))+rbx]
 	mov	r8,QWORD[((64+24))+rbx]
+DB	102,72,15,110,203
 
 	lea	rsi,[((64-0))+rbx]
 	lea	rdi,[32+rsp]
@@ -1373,7 +1220,7 @@
 	test	r8,r8
 	jnz	NEAR $L$add_proceedq
 	test	r9,r9
-	jz	NEAR $L$add_proceedq
+	jz	NEAR $L$add_doubleq
 
 DB	102,72,15,126,199
 	pxor	xmm0,xmm0
@@ -1386,6 +1233,13 @@
 	jmp	NEAR $L$add_doneq
 
 ALIGN	32
+$L$add_doubleq:
+DB	102,72,15,126,206
+DB	102,72,15,126,199
+	add	rsp,416
+	jmp	NEAR $L$point_double_shortcutq
+
+ALIGN	32
 $L$add_proceedq:
 	mov	rax,QWORD[((0+64))+rsp]
 	mov	r14,QWORD[((8+64))+rsp]
@@ -1446,6 +1300,7 @@
 
 
 
+	xor	r11,r11
 	add	r12,r12
 	lea	rsi,[96+rsp]
 	adc	r13,r13
@@ -1453,7 +1308,7 @@
 	adc	r8,r8
 	adc	r9,r9
 	mov	rbp,r13
-	sbb	r11,r11
+	adc	r11,0
 
 	sub	r12,-1
 	mov	rcx,r8
@@ -1461,15 +1316,15 @@
 	sbb	r8,0
 	mov	r10,r9
 	sbb	r9,r15
-	test	r11,r11
+	sbb	r11,0
 
-	cmovz	r12,rax
+	cmovc	r12,rax
 	mov	rax,QWORD[rsi]
-	cmovz	r13,rbp
+	cmovc	r13,rbp
 	mov	rbp,QWORD[8+rsi]
-	cmovz	r8,rcx
+	cmovc	r8,rcx
 	mov	rcx,QWORD[16+rsi]
-	cmovz	r9,r10
+	cmovc	r9,r10
 	mov	r10,QWORD[24+rsi]
 
 	call	__ecp_nistz256_subq
@@ -1634,16 +1489,14 @@
 	mov	r8,QWORD[((64+24))+rsi]
 	movdqa	XMMWORD[320+rsp],xmm0
 	movdqa	XMMWORD[(320+16)+rsp],xmm1
-	por	xmm1,xmm0
 	movdqa	XMMWORD[352+rsp],xmm2
 	movdqa	XMMWORD[(352+16)+rsp],xmm3
-	por	xmm3,xmm2
 	movdqa	XMMWORD[384+rsp],xmm4
 	movdqa	XMMWORD[(384+16)+rsp],xmm5
-	por	xmm3,xmm1
+	por	xmm5,xmm4
 
 	movdqu	xmm0,XMMWORD[rbx]
-	pshufd	xmm5,xmm3,0xb1
+	pshufd	xmm3,xmm5,0xb1
 	movdqu	xmm1,XMMWORD[16+rbx]
 	movdqu	xmm2,XMMWORD[32+rbx]
 	por	xmm5,xmm3
@@ -1761,6 +1614,7 @@
 
 
 
+	xor	r11,r11
 	add	r12,r12
 	lea	rsi,[192+rsp]
 	adc	r13,r13
@@ -1768,7 +1622,7 @@
 	adc	r8,r8
 	adc	r9,r9
 	mov	rbp,r13
-	sbb	r11,r11
+	adc	r11,0
 
 	sub	r12,-1
 	mov	rcx,r8
@@ -1776,15 +1630,15 @@
 	sbb	r8,0
 	mov	r10,r9
 	sbb	r9,r15
-	test	r11,r11
+	sbb	r11,0
 
-	cmovz	r12,rax
+	cmovc	r12,rax
 	mov	rax,QWORD[rsi]
-	cmovz	r13,rbp
+	cmovc	r13,rbp
 	mov	rbp,QWORD[8+rsi]
-	cmovz	r8,rcx
+	cmovc	r8,rcx
 	mov	rcx,QWORD[16+rsi]
-	cmovz	r9,r10
+	cmovc	r9,r10
 	mov	r10,QWORD[24+rsi]
 
 	call	__ecp_nistz256_subq
diff --git a/win-x86_64/crypto/modes/aesni-gcm-x86_64.asm b/win-x86_64/crypto/modes/aesni-gcm-x86_64.asm
index d7fff6a..741a9e4 100644
--- a/win-x86_64/crypto/modes/aesni-gcm-x86_64.asm
+++ b/win-x86_64/crypto/modes/aesni-gcm-x86_64.asm
@@ -5,16 +5,982 @@
 section	.text code align=64
 
 
-global	aesni_gcm_encrypt
 
-aesni_gcm_encrypt:
-	xor	eax,eax
+ALIGN	32
+_aesni_ctr32_ghash_6x:
+	vmovdqu	xmm2,XMMWORD[32+r11]
+	sub	rdx,6
+	vpxor	xmm4,xmm4,xmm4
+	vmovdqu	xmm15,XMMWORD[((0-128))+rcx]
+	vpaddb	xmm10,xmm1,xmm2
+	vpaddb	xmm11,xmm10,xmm2
+	vpaddb	xmm12,xmm11,xmm2
+	vpaddb	xmm13,xmm12,xmm2
+	vpaddb	xmm14,xmm13,xmm2
+	vpxor	xmm9,xmm1,xmm15
+	vmovdqu	XMMWORD[(16+8)+rsp],xmm4
+	jmp	NEAR $L$oop6x
+
+ALIGN	32
+$L$oop6x:
+	add	ebx,100663296
+	jc	NEAR $L$handle_ctr32
+	vmovdqu	xmm3,XMMWORD[((0-32))+r9]
+	vpaddb	xmm1,xmm14,xmm2
+	vpxor	xmm10,xmm10,xmm15
+	vpxor	xmm11,xmm11,xmm15
+
+$L$resume_ctr32:
+	vmovdqu	XMMWORD[r8],xmm1
+	vpclmulqdq	xmm5,xmm7,xmm3,0x10
+	vpxor	xmm12,xmm12,xmm15
+	vmovups	xmm2,XMMWORD[((16-128))+rcx]
+	vpclmulqdq	xmm6,xmm7,xmm3,0x01
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+	xor	r12,r12
+	cmp	r15,r14
+
+	vaesenc	xmm9,xmm9,xmm2
+	vmovdqu	xmm0,XMMWORD[((48+8))+rsp]
+	vpxor	xmm13,xmm13,xmm15
+	vpclmulqdq	xmm1,xmm7,xmm3,0x00
+	vaesenc	xmm10,xmm10,xmm2
+	vpxor	xmm14,xmm14,xmm15
+	setnc	r12b
+	vpclmulqdq	xmm7,xmm7,xmm3,0x11
+	vaesenc	xmm11,xmm11,xmm2
+	vmovdqu	xmm3,XMMWORD[((16-32))+r9]
+	neg	r12
+	vaesenc	xmm12,xmm12,xmm2
+	vpxor	xmm6,xmm6,xmm5
+	vpclmulqdq	xmm5,xmm0,xmm3,0x00
+	vpxor	xmm8,xmm8,xmm4
+	vaesenc	xmm13,xmm13,xmm2
+	vpxor	xmm4,xmm1,xmm5
+	and	r12,0x60
+	vmovups	xmm15,XMMWORD[((32-128))+rcx]
+	vpclmulqdq	xmm1,xmm0,xmm3,0x10
+	vaesenc	xmm14,xmm14,xmm2
+
+	vpclmulqdq	xmm2,xmm0,xmm3,0x01
+	lea	r14,[r12*1+r14]
+	vaesenc	xmm9,xmm9,xmm15
+	vpxor	xmm8,xmm8,XMMWORD[((16+8))+rsp]
+	vpclmulqdq	xmm3,xmm0,xmm3,0x11
+	vmovdqu	xmm0,XMMWORD[((64+8))+rsp]
+	vaesenc	xmm10,xmm10,xmm15
+	movbe	r13,QWORD[88+r14]
+	vaesenc	xmm11,xmm11,xmm15
+	movbe	r12,QWORD[80+r14]
+	vaesenc	xmm12,xmm12,xmm15
+	mov	QWORD[((32+8))+rsp],r13
+	vaesenc	xmm13,xmm13,xmm15
+	mov	QWORD[((40+8))+rsp],r12
+	vmovdqu	xmm5,XMMWORD[((48-32))+r9]
+	vaesenc	xmm14,xmm14,xmm15
+
+	vmovups	xmm15,XMMWORD[((48-128))+rcx]
+	vpxor	xmm6,xmm6,xmm1
+	vpclmulqdq	xmm1,xmm0,xmm5,0x00
+	vaesenc	xmm9,xmm9,xmm15
+	vpxor	xmm6,xmm6,xmm2
+	vpclmulqdq	xmm2,xmm0,xmm5,0x10
+	vaesenc	xmm10,xmm10,xmm15
+	vpxor	xmm7,xmm7,xmm3
+	vpclmulqdq	xmm3,xmm0,xmm5,0x01
+	vaesenc	xmm11,xmm11,xmm15
+	vpclmulqdq	xmm5,xmm0,xmm5,0x11
+	vmovdqu	xmm0,XMMWORD[((80+8))+rsp]
+	vaesenc	xmm12,xmm12,xmm15
+	vaesenc	xmm13,xmm13,xmm15
+	vpxor	xmm4,xmm4,xmm1
+	vmovdqu	xmm1,XMMWORD[((64-32))+r9]
+	vaesenc	xmm14,xmm14,xmm15
+
+	vmovups	xmm15,XMMWORD[((64-128))+rcx]
+	vpxor	xmm6,xmm6,xmm2
+	vpclmulqdq	xmm2,xmm0,xmm1,0x00
+	vaesenc	xmm9,xmm9,xmm15
+	vpxor	xmm6,xmm6,xmm3
+	vpclmulqdq	xmm3,xmm0,xmm1,0x10
+	vaesenc	xmm10,xmm10,xmm15
+	movbe	r13,QWORD[72+r14]
+	vpxor	xmm7,xmm7,xmm5
+	vpclmulqdq	xmm5,xmm0,xmm1,0x01
+	vaesenc	xmm11,xmm11,xmm15
+	movbe	r12,QWORD[64+r14]
+	vpclmulqdq	xmm1,xmm0,xmm1,0x11
+	vmovdqu	xmm0,XMMWORD[((96+8))+rsp]
+	vaesenc	xmm12,xmm12,xmm15
+	mov	QWORD[((48+8))+rsp],r13
+	vaesenc	xmm13,xmm13,xmm15
+	mov	QWORD[((56+8))+rsp],r12
+	vpxor	xmm4,xmm4,xmm2
+	vmovdqu	xmm2,XMMWORD[((96-32))+r9]
+	vaesenc	xmm14,xmm14,xmm15
+
+	vmovups	xmm15,XMMWORD[((80-128))+rcx]
+	vpxor	xmm6,xmm6,xmm3
+	vpclmulqdq	xmm3,xmm0,xmm2,0x00
+	vaesenc	xmm9,xmm9,xmm15
+	vpxor	xmm6,xmm6,xmm5
+	vpclmulqdq	xmm5,xmm0,xmm2,0x10
+	vaesenc	xmm10,xmm10,xmm15
+	movbe	r13,QWORD[56+r14]
+	vpxor	xmm7,xmm7,xmm1
+	vpclmulqdq	xmm1,xmm0,xmm2,0x01
+	vpxor	xmm8,xmm8,XMMWORD[((112+8))+rsp]
+	vaesenc	xmm11,xmm11,xmm15
+	movbe	r12,QWORD[48+r14]
+	vpclmulqdq	xmm2,xmm0,xmm2,0x11
+	vaesenc	xmm12,xmm12,xmm15
+	mov	QWORD[((64+8))+rsp],r13
+	vaesenc	xmm13,xmm13,xmm15
+	mov	QWORD[((72+8))+rsp],r12
+	vpxor	xmm4,xmm4,xmm3
+	vmovdqu	xmm3,XMMWORD[((112-32))+r9]
+	vaesenc	xmm14,xmm14,xmm15
+
+	vmovups	xmm15,XMMWORD[((96-128))+rcx]
+	vpxor	xmm6,xmm6,xmm5
+	vpclmulqdq	xmm5,xmm8,xmm3,0x10
+	vaesenc	xmm9,xmm9,xmm15
+	vpxor	xmm6,xmm6,xmm1
+	vpclmulqdq	xmm1,xmm8,xmm3,0x01
+	vaesenc	xmm10,xmm10,xmm15
+	movbe	r13,QWORD[40+r14]
+	vpxor	xmm7,xmm7,xmm2
+	vpclmulqdq	xmm2,xmm8,xmm3,0x00
+	vaesenc	xmm11,xmm11,xmm15
+	movbe	r12,QWORD[32+r14]
+	vpclmulqdq	xmm8,xmm8,xmm3,0x11
+	vaesenc	xmm12,xmm12,xmm15
+	mov	QWORD[((80+8))+rsp],r13
+	vaesenc	xmm13,xmm13,xmm15
+	mov	QWORD[((88+8))+rsp],r12
+	vpxor	xmm6,xmm6,xmm5
+	vaesenc	xmm14,xmm14,xmm15
+	vpxor	xmm6,xmm6,xmm1
+
+	vmovups	xmm15,XMMWORD[((112-128))+rcx]
+	vpslldq	xmm5,xmm6,8
+	vpxor	xmm4,xmm4,xmm2
+	vmovdqu	xmm3,XMMWORD[16+r11]
+
+	vaesenc	xmm9,xmm9,xmm15
+	vpxor	xmm7,xmm7,xmm8
+	vaesenc	xmm10,xmm10,xmm15
+	vpxor	xmm4,xmm4,xmm5
+	movbe	r13,QWORD[24+r14]
+	vaesenc	xmm11,xmm11,xmm15
+	movbe	r12,QWORD[16+r14]
+	vpalignr	xmm0,xmm4,xmm4,8
+	vpclmulqdq	xmm4,xmm4,xmm3,0x10
+	mov	QWORD[((96+8))+rsp],r13
+	vaesenc	xmm12,xmm12,xmm15
+	mov	QWORD[((104+8))+rsp],r12
+	vaesenc	xmm13,xmm13,xmm15
+	vmovups	xmm1,XMMWORD[((128-128))+rcx]
+	vaesenc	xmm14,xmm14,xmm15
+
+	vaesenc	xmm9,xmm9,xmm1
+	vmovups	xmm15,XMMWORD[((144-128))+rcx]
+	vaesenc	xmm10,xmm10,xmm1
+	vpsrldq	xmm6,xmm6,8
+	vaesenc	xmm11,xmm11,xmm1
+	vpxor	xmm7,xmm7,xmm6
+	vaesenc	xmm12,xmm12,xmm1
+	vpxor	xmm4,xmm4,xmm0
+	movbe	r13,QWORD[8+r14]
+	vaesenc	xmm13,xmm13,xmm1
+	movbe	r12,QWORD[r14]
+	vaesenc	xmm14,xmm14,xmm1
+	vmovups	xmm1,XMMWORD[((160-128))+rcx]
+	cmp	ebp,11
+	jb	NEAR $L$enc_tail
+
+	vaesenc	xmm9,xmm9,xmm15
+	vaesenc	xmm10,xmm10,xmm15
+	vaesenc	xmm11,xmm11,xmm15
+	vaesenc	xmm12,xmm12,xmm15
+	vaesenc	xmm13,xmm13,xmm15
+	vaesenc	xmm14,xmm14,xmm15
+
+	vaesenc	xmm9,xmm9,xmm1
+	vaesenc	xmm10,xmm10,xmm1
+	vaesenc	xmm11,xmm11,xmm1
+	vaesenc	xmm12,xmm12,xmm1
+	vaesenc	xmm13,xmm13,xmm1
+	vmovups	xmm15,XMMWORD[((176-128))+rcx]
+	vaesenc	xmm14,xmm14,xmm1
+	vmovups	xmm1,XMMWORD[((192-128))+rcx]
+	je	NEAR $L$enc_tail
+
+	vaesenc	xmm9,xmm9,xmm15
+	vaesenc	xmm10,xmm10,xmm15
+	vaesenc	xmm11,xmm11,xmm15
+	vaesenc	xmm12,xmm12,xmm15
+	vaesenc	xmm13,xmm13,xmm15
+	vaesenc	xmm14,xmm14,xmm15
+
+	vaesenc	xmm9,xmm9,xmm1
+	vaesenc	xmm10,xmm10,xmm1
+	vaesenc	xmm11,xmm11,xmm1
+	vaesenc	xmm12,xmm12,xmm1
+	vaesenc	xmm13,xmm13,xmm1
+	vmovups	xmm15,XMMWORD[((208-128))+rcx]
+	vaesenc	xmm14,xmm14,xmm1
+	vmovups	xmm1,XMMWORD[((224-128))+rcx]
+	jmp	NEAR $L$enc_tail
+
+ALIGN	32
+$L$handle_ctr32:
+	vmovdqu	xmm0,XMMWORD[r11]
+	vpshufb	xmm6,xmm1,xmm0
+	vmovdqu	xmm5,XMMWORD[48+r11]
+	vpaddd	xmm10,xmm6,XMMWORD[64+r11]
+	vpaddd	xmm11,xmm6,xmm5
+	vmovdqu	xmm3,XMMWORD[((0-32))+r9]
+	vpaddd	xmm12,xmm10,xmm5
+	vpshufb	xmm10,xmm10,xmm0
+	vpaddd	xmm13,xmm11,xmm5
+	vpshufb	xmm11,xmm11,xmm0
+	vpxor	xmm10,xmm10,xmm15
+	vpaddd	xmm14,xmm12,xmm5
+	vpshufb	xmm12,xmm12,xmm0
+	vpxor	xmm11,xmm11,xmm15
+	vpaddd	xmm1,xmm13,xmm5
+	vpshufb	xmm13,xmm13,xmm0
+	vpshufb	xmm14,xmm14,xmm0
+	vpshufb	xmm1,xmm1,xmm0
+	jmp	NEAR $L$resume_ctr32
+
+ALIGN	32
+$L$enc_tail:
+	vaesenc	xmm9,xmm9,xmm15
+	vmovdqu	XMMWORD[(16+8)+rsp],xmm7
+	vpalignr	xmm8,xmm4,xmm4,8
+	vaesenc	xmm10,xmm10,xmm15
+	vpclmulqdq	xmm4,xmm4,xmm3,0x10
+	vpxor	xmm2,xmm1,XMMWORD[rdi]
+	vaesenc	xmm11,xmm11,xmm15
+	vpxor	xmm0,xmm1,XMMWORD[16+rdi]
+	vaesenc	xmm12,xmm12,xmm15
+	vpxor	xmm5,xmm1,XMMWORD[32+rdi]
+	vaesenc	xmm13,xmm13,xmm15
+	vpxor	xmm6,xmm1,XMMWORD[48+rdi]
+	vaesenc	xmm14,xmm14,xmm15
+	vpxor	xmm7,xmm1,XMMWORD[64+rdi]
+	vpxor	xmm3,xmm1,XMMWORD[80+rdi]
+	vmovdqu	xmm1,XMMWORD[r8]
+
+	vaesenclast	xmm9,xmm9,xmm2
+	vmovdqu	xmm2,XMMWORD[32+r11]
+	vaesenclast	xmm10,xmm10,xmm0
+	vpaddb	xmm0,xmm1,xmm2
+	mov	QWORD[((112+8))+rsp],r13
+	lea	rdi,[96+rdi]
+	vaesenclast	xmm11,xmm11,xmm5
+	vpaddb	xmm5,xmm0,xmm2
+	mov	QWORD[((120+8))+rsp],r12
+	lea	rsi,[96+rsi]
+	vmovdqu	xmm15,XMMWORD[((0-128))+rcx]
+	vaesenclast	xmm12,xmm12,xmm6
+	vpaddb	xmm6,xmm5,xmm2
+	vaesenclast	xmm13,xmm13,xmm7
+	vpaddb	xmm7,xmm6,xmm2
+	vaesenclast	xmm14,xmm14,xmm3
+	vpaddb	xmm3,xmm7,xmm2
+
+	add	r10,0x60
+	sub	rdx,0x6
+	jc	NEAR $L$6x_done
+
+	vmovups	XMMWORD[(-96)+rsi],xmm9
+	vpxor	xmm9,xmm1,xmm15
+	vmovups	XMMWORD[(-80)+rsi],xmm10
+	vmovdqa	xmm10,xmm0
+	vmovups	XMMWORD[(-64)+rsi],xmm11
+	vmovdqa	xmm11,xmm5
+	vmovups	XMMWORD[(-48)+rsi],xmm12
+	vmovdqa	xmm12,xmm6
+	vmovups	XMMWORD[(-32)+rsi],xmm13
+	vmovdqa	xmm13,xmm7
+	vmovups	XMMWORD[(-16)+rsi],xmm14
+	vmovdqa	xmm14,xmm3
+	vmovdqu	xmm7,XMMWORD[((32+8))+rsp]
+	jmp	NEAR $L$oop6x
+
+$L$6x_done:
+	vpxor	xmm8,xmm8,XMMWORD[((16+8))+rsp]
+	vpxor	xmm8,xmm8,xmm4
+
 	DB	0F3h,0C3h		;repret
 
-
 global	aesni_gcm_decrypt
 
+ALIGN	32
 aesni_gcm_decrypt:
-	xor	eax,eax
+	mov	QWORD[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_aesni_gcm_decrypt:
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+	mov	r8,QWORD[40+rsp]
+	mov	r9,QWORD[48+rsp]
+
+
+	xor	r10,r10
+
+
+
+	cmp	rdx,0x60
+	jb	NEAR $L$gcm_dec_abort
+
+	lea	rax,[rsp]
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	lea	rsp,[((-168))+rsp]
+	movaps	XMMWORD[(-216)+rax],xmm6
+	movaps	XMMWORD[(-200)+rax],xmm7
+	movaps	XMMWORD[(-184)+rax],xmm8
+	movaps	XMMWORD[(-168)+rax],xmm9
+	movaps	XMMWORD[(-152)+rax],xmm10
+	movaps	XMMWORD[(-136)+rax],xmm11
+	movaps	XMMWORD[(-120)+rax],xmm12
+	movaps	XMMWORD[(-104)+rax],xmm13
+	movaps	XMMWORD[(-88)+rax],xmm14
+	movaps	XMMWORD[(-72)+rax],xmm15
+$L$gcm_dec_body:
+	vzeroupper
+
+	vmovdqu	xmm1,XMMWORD[r8]
+	add	rsp,-128
+	mov	ebx,DWORD[12+r8]
+	lea	r11,[$L$bswap_mask]
+	lea	r14,[((-128))+rcx]
+	mov	r15,0xf80
+	vmovdqu	xmm8,XMMWORD[r9]
+	and	rsp,-128
+	vmovdqu	xmm0,XMMWORD[r11]
+	lea	rcx,[128+rcx]
+	lea	r9,[((32+32))+r9]
+	mov	ebp,DWORD[((240-128))+rcx]
+	vpshufb	xmm8,xmm8,xmm0
+
+	and	r14,r15
+	and	r15,rsp
+	sub	r15,r14
+	jc	NEAR $L$dec_no_key_aliasing
+	cmp	r15,768
+	jnc	NEAR $L$dec_no_key_aliasing
+	sub	rsp,r15
+$L$dec_no_key_aliasing:
+
+	vmovdqu	xmm7,XMMWORD[80+rdi]
+	lea	r14,[rdi]
+	vmovdqu	xmm4,XMMWORD[64+rdi]
+
+
+
+
+
+
+
+	lea	r15,[((-192))+rdx*1+rdi]
+
+	vmovdqu	xmm5,XMMWORD[48+rdi]
+	shr	rdx,4
+	xor	r10,r10
+	vmovdqu	xmm6,XMMWORD[32+rdi]
+	vpshufb	xmm7,xmm7,xmm0
+	vmovdqu	xmm2,XMMWORD[16+rdi]
+	vpshufb	xmm4,xmm4,xmm0
+	vmovdqu	xmm3,XMMWORD[rdi]
+	vpshufb	xmm5,xmm5,xmm0
+	vmovdqu	XMMWORD[48+rsp],xmm4
+	vpshufb	xmm6,xmm6,xmm0
+	vmovdqu	XMMWORD[64+rsp],xmm5
+	vpshufb	xmm2,xmm2,xmm0
+	vmovdqu	XMMWORD[80+rsp],xmm6
+	vpshufb	xmm3,xmm3,xmm0
+	vmovdqu	XMMWORD[96+rsp],xmm2
+	vmovdqu	XMMWORD[112+rsp],xmm3
+
+	call	_aesni_ctr32_ghash_6x
+
+	vmovups	XMMWORD[(-96)+rsi],xmm9
+	vmovups	XMMWORD[(-80)+rsi],xmm10
+	vmovups	XMMWORD[(-64)+rsi],xmm11
+	vmovups	XMMWORD[(-48)+rsi],xmm12
+	vmovups	XMMWORD[(-32)+rsi],xmm13
+	vmovups	XMMWORD[(-16)+rsi],xmm14
+
+	vpshufb	xmm8,xmm8,XMMWORD[r11]
+	vmovdqu	XMMWORD[(-64)+r9],xmm8
+
+	vzeroupper
+	movaps	xmm6,XMMWORD[((-216))+rax]
+	movaps	xmm7,XMMWORD[((-200))+rax]
+	movaps	xmm8,XMMWORD[((-184))+rax]
+	movaps	xmm9,XMMWORD[((-168))+rax]
+	movaps	xmm10,XMMWORD[((-152))+rax]
+	movaps	xmm11,XMMWORD[((-136))+rax]
+	movaps	xmm12,XMMWORD[((-120))+rax]
+	movaps	xmm13,XMMWORD[((-104))+rax]
+	movaps	xmm14,XMMWORD[((-88))+rax]
+	movaps	xmm15,XMMWORD[((-72))+rax]
+	mov	r15,QWORD[((-48))+rax]
+	mov	r14,QWORD[((-40))+rax]
+	mov	r13,QWORD[((-32))+rax]
+	mov	r12,QWORD[((-24))+rax]
+	mov	rbp,QWORD[((-16))+rax]
+	mov	rbx,QWORD[((-8))+rax]
+	lea	rsp,[rax]
+$L$gcm_dec_abort:
+	mov	rax,r10
+	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_aesni_gcm_decrypt:
+
+ALIGN	32
+_aesni_ctr32_6x:
+	vmovdqu	xmm4,XMMWORD[((0-128))+rcx]
+	vmovdqu	xmm2,XMMWORD[32+r11]
+	lea	r13,[((-1))+rbp]
+	vmovups	xmm15,XMMWORD[((16-128))+rcx]
+	lea	r12,[((32-128))+rcx]
+	vpxor	xmm9,xmm1,xmm4
+	add	ebx,100663296
+	jc	NEAR $L$handle_ctr32_2
+	vpaddb	xmm10,xmm1,xmm2
+	vpaddb	xmm11,xmm10,xmm2
+	vpxor	xmm10,xmm10,xmm4
+	vpaddb	xmm12,xmm11,xmm2
+	vpxor	xmm11,xmm11,xmm4
+	vpaddb	xmm13,xmm12,xmm2
+	vpxor	xmm12,xmm12,xmm4
+	vpaddb	xmm14,xmm13,xmm2
+	vpxor	xmm13,xmm13,xmm4
+	vpaddb	xmm1,xmm14,xmm2
+	vpxor	xmm14,xmm14,xmm4
+	jmp	NEAR $L$oop_ctr32
+
+ALIGN	16
+$L$oop_ctr32:
+	vaesenc	xmm9,xmm9,xmm15
+	vaesenc	xmm10,xmm10,xmm15
+	vaesenc	xmm11,xmm11,xmm15
+	vaesenc	xmm12,xmm12,xmm15
+	vaesenc	xmm13,xmm13,xmm15
+	vaesenc	xmm14,xmm14,xmm15
+	vmovups	xmm15,XMMWORD[r12]
+	lea	r12,[16+r12]
+	dec	r13d
+	jnz	NEAR $L$oop_ctr32
+
+	vmovdqu	xmm3,XMMWORD[r12]
+	vaesenc	xmm9,xmm9,xmm15
+	vpxor	xmm4,xmm3,XMMWORD[rdi]
+	vaesenc	xmm10,xmm10,xmm15
+	vpxor	xmm5,xmm3,XMMWORD[16+rdi]
+	vaesenc	xmm11,xmm11,xmm15
+	vpxor	xmm6,xmm3,XMMWORD[32+rdi]
+	vaesenc	xmm12,xmm12,xmm15
+	vpxor	xmm8,xmm3,XMMWORD[48+rdi]
+	vaesenc	xmm13,xmm13,xmm15
+	vpxor	xmm2,xmm3,XMMWORD[64+rdi]
+	vaesenc	xmm14,xmm14,xmm15
+	vpxor	xmm3,xmm3,XMMWORD[80+rdi]
+	lea	rdi,[96+rdi]
+
+	vaesenclast	xmm9,xmm9,xmm4
+	vaesenclast	xmm10,xmm10,xmm5
+	vaesenclast	xmm11,xmm11,xmm6
+	vaesenclast	xmm12,xmm12,xmm8
+	vaesenclast	xmm13,xmm13,xmm2
+	vaesenclast	xmm14,xmm14,xmm3
+	vmovups	XMMWORD[rsi],xmm9
+	vmovups	XMMWORD[16+rsi],xmm10
+	vmovups	XMMWORD[32+rsi],xmm11
+	vmovups	XMMWORD[48+rsi],xmm12
+	vmovups	XMMWORD[64+rsi],xmm13
+	vmovups	XMMWORD[80+rsi],xmm14
+	lea	rsi,[96+rsi]
+
+	DB	0F3h,0C3h		;repret
+ALIGN	32
+$L$handle_ctr32_2:
+	vpshufb	xmm6,xmm1,xmm0
+	vmovdqu	xmm5,XMMWORD[48+r11]
+	vpaddd	xmm10,xmm6,XMMWORD[64+r11]
+	vpaddd	xmm11,xmm6,xmm5
+	vpaddd	xmm12,xmm10,xmm5
+	vpshufb	xmm10,xmm10,xmm0
+	vpaddd	xmm13,xmm11,xmm5
+	vpshufb	xmm11,xmm11,xmm0
+	vpxor	xmm10,xmm10,xmm4
+	vpaddd	xmm14,xmm12,xmm5
+	vpshufb	xmm12,xmm12,xmm0
+	vpxor	xmm11,xmm11,xmm4
+	vpaddd	xmm1,xmm13,xmm5
+	vpshufb	xmm13,xmm13,xmm0
+	vpxor	xmm12,xmm12,xmm4
+	vpshufb	xmm14,xmm14,xmm0
+	vpxor	xmm13,xmm13,xmm4
+	vpshufb	xmm1,xmm1,xmm0
+	vpxor	xmm14,xmm14,xmm4
+	jmp	NEAR $L$oop_ctr32
+
+
+global	aesni_gcm_encrypt
+
+ALIGN	32
+aesni_gcm_encrypt:
+	mov	QWORD[8+rsp],rdi	;WIN64 prologue
+	mov	QWORD[16+rsp],rsi
+	mov	rax,rsp
+$L$SEH_begin_aesni_gcm_encrypt:
+	mov	rdi,rcx
+	mov	rsi,rdx
+	mov	rdx,r8
+	mov	rcx,r9
+	mov	r8,QWORD[40+rsp]
+	mov	r9,QWORD[48+rsp]
+
+
+	xor	r10,r10
+
+
+
+
+	cmp	rdx,0x60*3
+	jb	NEAR $L$gcm_enc_abort
+
+	lea	rax,[rsp]
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	lea	rsp,[((-168))+rsp]
+	movaps	XMMWORD[(-216)+rax],xmm6
+	movaps	XMMWORD[(-200)+rax],xmm7
+	movaps	XMMWORD[(-184)+rax],xmm8
+	movaps	XMMWORD[(-168)+rax],xmm9
+	movaps	XMMWORD[(-152)+rax],xmm10
+	movaps	XMMWORD[(-136)+rax],xmm11
+	movaps	XMMWORD[(-120)+rax],xmm12
+	movaps	XMMWORD[(-104)+rax],xmm13
+	movaps	XMMWORD[(-88)+rax],xmm14
+	movaps	XMMWORD[(-72)+rax],xmm15
+$L$gcm_enc_body:
+	vzeroupper
+
+	vmovdqu	xmm1,XMMWORD[r8]
+	add	rsp,-128
+	mov	ebx,DWORD[12+r8]
+	lea	r11,[$L$bswap_mask]
+	lea	r14,[((-128))+rcx]
+	mov	r15,0xf80
+	lea	rcx,[128+rcx]
+	vmovdqu	xmm0,XMMWORD[r11]
+	and	rsp,-128
+	mov	ebp,DWORD[((240-128))+rcx]
+
+	and	r14,r15
+	and	r15,rsp
+	sub	r15,r14
+	jc	NEAR $L$enc_no_key_aliasing
+	cmp	r15,768
+	jnc	NEAR $L$enc_no_key_aliasing
+	sub	rsp,r15
+$L$enc_no_key_aliasing:
+
+	lea	r14,[rsi]
+
+
+
+
+
+
+
+
+	lea	r15,[((-192))+rdx*1+rsi]
+
+	shr	rdx,4
+
+	call	_aesni_ctr32_6x
+	vpshufb	xmm8,xmm9,xmm0
+	vpshufb	xmm2,xmm10,xmm0
+	vmovdqu	XMMWORD[112+rsp],xmm8
+	vpshufb	xmm4,xmm11,xmm0
+	vmovdqu	XMMWORD[96+rsp],xmm2
+	vpshufb	xmm5,xmm12,xmm0
+	vmovdqu	XMMWORD[80+rsp],xmm4
+	vpshufb	xmm6,xmm13,xmm0
+	vmovdqu	XMMWORD[64+rsp],xmm5
+	vpshufb	xmm7,xmm14,xmm0
+	vmovdqu	XMMWORD[48+rsp],xmm6
+
+	call	_aesni_ctr32_6x
+
+	vmovdqu	xmm8,XMMWORD[r9]
+	lea	r9,[((32+32))+r9]
+	sub	rdx,12
+	mov	r10,0x60*2
+	vpshufb	xmm8,xmm8,xmm0
+
+	call	_aesni_ctr32_ghash_6x
+	vmovdqu	xmm7,XMMWORD[32+rsp]
+	vmovdqu	xmm0,XMMWORD[r11]
+	vmovdqu	xmm3,XMMWORD[((0-32))+r9]
+	vpunpckhqdq	xmm1,xmm7,xmm7
+	vmovdqu	xmm15,XMMWORD[((32-32))+r9]
+	vmovups	XMMWORD[(-96)+rsi],xmm9
+	vpshufb	xmm9,xmm9,xmm0
+	vpxor	xmm1,xmm1,xmm7
+	vmovups	XMMWORD[(-80)+rsi],xmm10
+	vpshufb	xmm10,xmm10,xmm0
+	vmovups	XMMWORD[(-64)+rsi],xmm11
+	vpshufb	xmm11,xmm11,xmm0
+	vmovups	XMMWORD[(-48)+rsi],xmm12
+	vpshufb	xmm12,xmm12,xmm0
+	vmovups	XMMWORD[(-32)+rsi],xmm13
+	vpshufb	xmm13,xmm13,xmm0
+	vmovups	XMMWORD[(-16)+rsi],xmm14
+	vpshufb	xmm14,xmm14,xmm0
+	vmovdqu	XMMWORD[16+rsp],xmm9
+	vmovdqu	xmm6,XMMWORD[48+rsp]
+	vmovdqu	xmm0,XMMWORD[((16-32))+r9]
+	vpunpckhqdq	xmm2,xmm6,xmm6
+	vpclmulqdq	xmm5,xmm7,xmm3,0x00
+	vpxor	xmm2,xmm2,xmm6
+	vpclmulqdq	xmm7,xmm7,xmm3,0x11
+	vpclmulqdq	xmm1,xmm1,xmm15,0x00
+
+	vmovdqu	xmm9,XMMWORD[64+rsp]
+	vpclmulqdq	xmm4,xmm6,xmm0,0x00
+	vmovdqu	xmm3,XMMWORD[((48-32))+r9]
+	vpxor	xmm4,xmm4,xmm5
+	vpunpckhqdq	xmm5,xmm9,xmm9
+	vpclmulqdq	xmm6,xmm6,xmm0,0x11
+	vpxor	xmm5,xmm5,xmm9
+	vpxor	xmm6,xmm6,xmm7
+	vpclmulqdq	xmm2,xmm2,xmm15,0x10
+	vmovdqu	xmm15,XMMWORD[((80-32))+r9]
+	vpxor	xmm2,xmm2,xmm1
+
+	vmovdqu	xmm1,XMMWORD[80+rsp]
+	vpclmulqdq	xmm7,xmm9,xmm3,0x00
+	vmovdqu	xmm0,XMMWORD[((64-32))+r9]
+	vpxor	xmm7,xmm7,xmm4
+	vpunpckhqdq	xmm4,xmm1,xmm1
+	vpclmulqdq	xmm9,xmm9,xmm3,0x11
+	vpxor	xmm4,xmm4,xmm1
+	vpxor	xmm9,xmm9,xmm6
+	vpclmulqdq	xmm5,xmm5,xmm15,0x00
+	vpxor	xmm5,xmm5,xmm2
+
+	vmovdqu	xmm2,XMMWORD[96+rsp]
+	vpclmulqdq	xmm6,xmm1,xmm0,0x00
+	vmovdqu	xmm3,XMMWORD[((96-32))+r9]
+	vpxor	xmm6,xmm6,xmm7
+	vpunpckhqdq	xmm7,xmm2,xmm2
+	vpclmulqdq	xmm1,xmm1,xmm0,0x11
+	vpxor	xmm7,xmm7,xmm2
+	vpxor	xmm1,xmm1,xmm9
+	vpclmulqdq	xmm4,xmm4,xmm15,0x10
+	vmovdqu	xmm15,XMMWORD[((128-32))+r9]
+	vpxor	xmm4,xmm4,xmm5
+
+	vpxor	xmm8,xmm8,XMMWORD[112+rsp]
+	vpclmulqdq	xmm5,xmm2,xmm3,0x00
+	vmovdqu	xmm0,XMMWORD[((112-32))+r9]
+	vpunpckhqdq	xmm9,xmm8,xmm8
+	vpxor	xmm5,xmm5,xmm6
+	vpclmulqdq	xmm2,xmm2,xmm3,0x11
+	vpxor	xmm9,xmm9,xmm8
+	vpxor	xmm2,xmm2,xmm1
+	vpclmulqdq	xmm7,xmm7,xmm15,0x00
+	vpxor	xmm4,xmm7,xmm4
+
+	vpclmulqdq	xmm6,xmm8,xmm0,0x00
+	vmovdqu	xmm3,XMMWORD[((0-32))+r9]
+	vpunpckhqdq	xmm1,xmm14,xmm14
+	vpclmulqdq	xmm8,xmm8,xmm0,0x11
+	vpxor	xmm1,xmm1,xmm14
+	vpxor	xmm5,xmm6,xmm5
+	vpclmulqdq	xmm9,xmm9,xmm15,0x10
+	vmovdqu	xmm15,XMMWORD[((32-32))+r9]
+	vpxor	xmm7,xmm8,xmm2
+	vpxor	xmm6,xmm9,xmm4
+
+	vmovdqu	xmm0,XMMWORD[((16-32))+r9]
+	vpxor	xmm9,xmm7,xmm5
+	vpclmulqdq	xmm4,xmm14,xmm3,0x00
+	vpxor	xmm6,xmm6,xmm9
+	vpunpckhqdq	xmm2,xmm13,xmm13
+	vpclmulqdq	xmm14,xmm14,xmm3,0x11
+	vpxor	xmm2,xmm2,xmm13
+	vpslldq	xmm9,xmm6,8
+	vpclmulqdq	xmm1,xmm1,xmm15,0x00
+	vpxor	xmm8,xmm5,xmm9
+	vpsrldq	xmm6,xmm6,8
+	vpxor	xmm7,xmm7,xmm6
+
+	vpclmulqdq	xmm5,xmm13,xmm0,0x00
+	vmovdqu	xmm3,XMMWORD[((48-32))+r9]
+	vpxor	xmm5,xmm5,xmm4
+	vpunpckhqdq	xmm9,xmm12,xmm12
+	vpclmulqdq	xmm13,xmm13,xmm0,0x11
+	vpxor	xmm9,xmm9,xmm12
+	vpxor	xmm13,xmm13,xmm14
+	vpalignr	xmm14,xmm8,xmm8,8
+	vpclmulqdq	xmm2,xmm2,xmm15,0x10
+	vmovdqu	xmm15,XMMWORD[((80-32))+r9]
+	vpxor	xmm2,xmm2,xmm1
+
+	vpclmulqdq	xmm4,xmm12,xmm3,0x00
+	vmovdqu	xmm0,XMMWORD[((64-32))+r9]
+	vpxor	xmm4,xmm4,xmm5
+	vpunpckhqdq	xmm1,xmm11,xmm11
+	vpclmulqdq	xmm12,xmm12,xmm3,0x11
+	vpxor	xmm1,xmm1,xmm11
+	vpxor	xmm12,xmm12,xmm13
+	vxorps	xmm7,xmm7,XMMWORD[16+rsp]
+	vpclmulqdq	xmm9,xmm9,xmm15,0x00
+	vpxor	xmm9,xmm9,xmm2
+
+	vpclmulqdq	xmm8,xmm8,XMMWORD[16+r11],0x10
+	vxorps	xmm8,xmm8,xmm14
+
+	vpclmulqdq	xmm5,xmm11,xmm0,0x00
+	vmovdqu	xmm3,XMMWORD[((96-32))+r9]
+	vpxor	xmm5,xmm5,xmm4
+	vpunpckhqdq	xmm2,xmm10,xmm10
+	vpclmulqdq	xmm11,xmm11,xmm0,0x11
+	vpxor	xmm2,xmm2,xmm10
+	vpalignr	xmm14,xmm8,xmm8,8
+	vpxor	xmm11,xmm11,xmm12
+	vpclmulqdq	xmm1,xmm1,xmm15,0x10
+	vmovdqu	xmm15,XMMWORD[((128-32))+r9]
+	vpxor	xmm1,xmm1,xmm9
+
+	vxorps	xmm14,xmm14,xmm7
+	vpclmulqdq	xmm8,xmm8,XMMWORD[16+r11],0x10
+	vxorps	xmm8,xmm8,xmm14
+
+	vpclmulqdq	xmm4,xmm10,xmm3,0x00
+	vmovdqu	xmm0,XMMWORD[((112-32))+r9]
+	vpxor	xmm4,xmm4,xmm5
+	vpunpckhqdq	xmm9,xmm8,xmm8
+	vpclmulqdq	xmm10,xmm10,xmm3,0x11
+	vpxor	xmm9,xmm9,xmm8
+	vpxor	xmm10,xmm10,xmm11
+	vpclmulqdq	xmm2,xmm2,xmm15,0x00
+	vpxor	xmm2,xmm2,xmm1
+
+	vpclmulqdq	xmm5,xmm8,xmm0,0x00
+	vpclmulqdq	xmm7,xmm8,xmm0,0x11
+	vpxor	xmm5,xmm5,xmm4
+	vpclmulqdq	xmm6,xmm9,xmm15,0x10
+	vpxor	xmm7,xmm7,xmm10
+	vpxor	xmm6,xmm6,xmm2
+
+	vpxor	xmm4,xmm7,xmm5
+	vpxor	xmm6,xmm6,xmm4
+	vpslldq	xmm1,xmm6,8
+	vmovdqu	xmm3,XMMWORD[16+r11]
+	vpsrldq	xmm6,xmm6,8
+	vpxor	xmm8,xmm5,xmm1
+	vpxor	xmm7,xmm7,xmm6
+
+	vpalignr	xmm2,xmm8,xmm8,8
+	vpclmulqdq	xmm8,xmm8,xmm3,0x10
+	vpxor	xmm8,xmm8,xmm2
+
+	vpalignr	xmm2,xmm8,xmm8,8
+	vpclmulqdq	xmm8,xmm8,xmm3,0x10
+	vpxor	xmm2,xmm2,xmm7
+	vpxor	xmm8,xmm8,xmm2
+	vpshufb	xmm8,xmm8,XMMWORD[r11]
+	vmovdqu	XMMWORD[(-64)+r9],xmm8
+
+	vzeroupper
+	movaps	xmm6,XMMWORD[((-216))+rax]
+	movaps	xmm7,XMMWORD[((-200))+rax]
+	movaps	xmm8,XMMWORD[((-184))+rax]
+	movaps	xmm9,XMMWORD[((-168))+rax]
+	movaps	xmm10,XMMWORD[((-152))+rax]
+	movaps	xmm11,XMMWORD[((-136))+rax]
+	movaps	xmm12,XMMWORD[((-120))+rax]
+	movaps	xmm13,XMMWORD[((-104))+rax]
+	movaps	xmm14,XMMWORD[((-88))+rax]
+	movaps	xmm15,XMMWORD[((-72))+rax]
+	mov	r15,QWORD[((-48))+rax]
+	mov	r14,QWORD[((-40))+rax]
+	mov	r13,QWORD[((-32))+rax]
+	mov	r12,QWORD[((-24))+rax]
+	mov	rbp,QWORD[((-16))+rax]
+	mov	rbx,QWORD[((-8))+rax]
+	lea	rsp,[rax]
+$L$gcm_enc_abort:
+	mov	rax,r10
+	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
+	mov	rsi,QWORD[16+rsp]
+	DB	0F3h,0C3h		;repret
+$L$SEH_end_aesni_gcm_encrypt:
+ALIGN	64
+$L$bswap_mask:
+DB	15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
+$L$poly:
+DB	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xc2
+$L$one_msb:
+DB	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1
+$L$two_lsb:
+DB	2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+$L$one_lsb:
+DB	1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+DB	65,69,83,45,78,73,32,71,67,77,32,109,111,100,117,108
+DB	101,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82
+DB	89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112
+DB	114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
+ALIGN	64
+EXTERN	__imp_RtlVirtualUnwind
+
+ALIGN	16
+gcm_se_handler:
+	push	rsi
+	push	rdi
+	push	rbx
+	push	rbp
+	push	r12
+	push	r13
+	push	r14
+	push	r15
+	pushfq
+	sub	rsp,64
+
+	mov	rax,QWORD[120+r8]
+	mov	rbx,QWORD[248+r8]
+
+	mov	rsi,QWORD[8+r9]
+	mov	r11,QWORD[56+r9]
+
+	mov	r10d,DWORD[r11]
+	lea	r10,[r10*1+rsi]
+	cmp	rbx,r10
+	jb	NEAR $L$common_seh_tail
+
+	mov	rax,QWORD[152+r8]
+
+	mov	r10d,DWORD[4+r11]
+	lea	r10,[r10*1+rsi]
+	cmp	rbx,r10
+	jae	NEAR $L$common_seh_tail
+
+	mov	rax,QWORD[120+r8]
+
+	mov	r15,QWORD[((-48))+rax]
+	mov	r14,QWORD[((-40))+rax]
+	mov	r13,QWORD[((-32))+rax]
+	mov	r12,QWORD[((-24))+rax]
+	mov	rbp,QWORD[((-16))+rax]
+	mov	rbx,QWORD[((-8))+rax]
+	mov	QWORD[240+r8],r15
+	mov	QWORD[232+r8],r14
+	mov	QWORD[224+r8],r13
+	mov	QWORD[216+r8],r12
+	mov	QWORD[160+r8],rbp
+	mov	QWORD[144+r8],rbx
+
+	lea	rsi,[((-216))+rax]
+	lea	rdi,[512+r8]
+	mov	ecx,20
+	DD	0xa548f3fc
+
+$L$common_seh_tail:
+	mov	rdi,QWORD[8+rax]
+	mov	rsi,QWORD[16+rax]
+	mov	QWORD[152+r8],rax
+	mov	QWORD[168+r8],rsi
+	mov	QWORD[176+r8],rdi
+
+	mov	rdi,QWORD[40+r9]
+	mov	rsi,r8
+	mov	ecx,154
+	DD	0xa548f3fc
+
+	mov	rsi,r9
+	xor	rcx,rcx
+	mov	rdx,QWORD[8+rsi]
+	mov	r8,QWORD[rsi]
+	mov	r9,QWORD[16+rsi]
+	mov	r10,QWORD[40+rsi]
+	lea	r11,[56+rsi]
+	lea	r12,[24+rsi]
+	mov	QWORD[32+rsp],r10
+	mov	QWORD[40+rsp],r11
+	mov	QWORD[48+rsp],r12
+	mov	QWORD[56+rsp],rcx
+	call	QWORD[__imp_RtlVirtualUnwind]
+
+	mov	eax,1
+	add	rsp,64
+	popfq
+	pop	r15
+	pop	r14
+	pop	r13
+	pop	r12
+	pop	rbp
+	pop	rbx
+	pop	rdi
+	pop	rsi
 	DB	0F3h,0C3h		;repret
 
+
+section	.pdata rdata align=4
+ALIGN	4
+	DD	$L$SEH_begin_aesni_gcm_decrypt wrt ..imagebase
+	DD	$L$SEH_end_aesni_gcm_decrypt wrt ..imagebase
+	DD	$L$SEH_gcm_dec_info wrt ..imagebase
+
+	DD	$L$SEH_begin_aesni_gcm_encrypt wrt ..imagebase
+	DD	$L$SEH_end_aesni_gcm_encrypt wrt ..imagebase
+	DD	$L$SEH_gcm_enc_info wrt ..imagebase
+section	.xdata rdata align=8
+ALIGN	8
+$L$SEH_gcm_dec_info:
+DB	9,0,0,0
+	DD	gcm_se_handler wrt ..imagebase
+	DD	$L$gcm_dec_body wrt ..imagebase,$L$gcm_dec_abort wrt ..imagebase
+$L$SEH_gcm_enc_info:
+DB	9,0,0,0
+	DD	gcm_se_handler wrt ..imagebase
+	DD	$L$gcm_enc_body wrt ..imagebase,$L$gcm_enc_abort wrt ..imagebase
diff --git a/win-x86_64/crypto/modes/ghash-x86_64.asm b/win-x86_64/crypto/modes/ghash-x86_64.asm
index 5d8fadc..b01f98c 100644
--- a/win-x86_64/crypto/modes/ghash-x86_64.asm
+++ b/win-x86_64/crypto/modes/ghash-x86_64.asm
@@ -21,6 +21,10 @@
 	push	rbx
 	push	rbp
 	push	r12
+	push	r13
+	push	r14
+	push	r15
+	sub	rsp,280
 $L$gmult_prologue:
 
 	movzx	r8,BYTE[15+rdi]
@@ -97,8 +101,9 @@
 	mov	QWORD[8+rdi],r8
 	mov	QWORD[rdi],r9
 
-	mov	rbx,QWORD[16+rsp]
-	lea	rsp,[24+rsp]
+	lea	rsi,[((280+48))+rsp]
+	mov	rbx,QWORD[((-8))+rsi]
+	lea	rsp,[rsi]
 $L$gmult_epilogue:
 	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
 	mov	rsi,QWORD[16+rsp]
@@ -669,14 +674,14 @@
 	mov	QWORD[8+rdi],r8
 	mov	QWORD[rdi],r9
 
-	lea	rsi,[280+rsp]
-	mov	r15,QWORD[rsi]
-	mov	r14,QWORD[8+rsi]
-	mov	r13,QWORD[16+rsi]
-	mov	r12,QWORD[24+rsi]
-	mov	rbp,QWORD[32+rsi]
-	mov	rbx,QWORD[40+rsi]
-	lea	rsp,[48+rsi]
+	lea	rsi,[((280+48))+rsp]
+	mov	r15,QWORD[((-48))+rsi]
+	mov	r14,QWORD[((-40))+rsi]
+	mov	r13,QWORD[((-32))+rsi]
+	mov	r12,QWORD[((-24))+rsi]
+	mov	rbp,QWORD[((-16))+rsi]
+	mov	rbx,QWORD[((-8))+rsi]
+	lea	rsp,[rsi]
 $L$ghash_epilogue:
 	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
 	mov	rsi,QWORD[16+rsp]
@@ -1309,7 +1314,115 @@
 
 ALIGN	32
 gcm_init_avx:
-	jmp	NEAR $L$_init_clmul
+$L$SEH_begin_gcm_init_avx:
+
+DB	0x48,0x83,0xec,0x18
+DB	0x0f,0x29,0x34,0x24
+	vzeroupper
+
+	vmovdqu	xmm2,XMMWORD[rdx]
+	vpshufd	xmm2,xmm2,78
+
+
+	vpshufd	xmm4,xmm2,255
+	vpsrlq	xmm3,xmm2,63
+	vpsllq	xmm2,xmm2,1
+	vpxor	xmm5,xmm5,xmm5
+	vpcmpgtd	xmm5,xmm5,xmm4
+	vpslldq	xmm3,xmm3,8
+	vpor	xmm2,xmm2,xmm3
+
+
+	vpand	xmm5,xmm5,XMMWORD[$L$0x1c2_polynomial]
+	vpxor	xmm2,xmm2,xmm5
+
+	vpunpckhqdq	xmm6,xmm2,xmm2
+	vmovdqa	xmm0,xmm2
+	vpxor	xmm6,xmm6,xmm2
+	mov	r10,4
+	jmp	NEAR $L$init_start_avx
+ALIGN	32
+$L$init_loop_avx:
+	vpalignr	xmm5,xmm4,xmm3,8
+	vmovdqu	XMMWORD[(-16)+rcx],xmm5
+	vpunpckhqdq	xmm3,xmm0,xmm0
+	vpxor	xmm3,xmm3,xmm0
+	vpclmulqdq	xmm1,xmm0,xmm2,0x11
+	vpclmulqdq	xmm0,xmm0,xmm2,0x00
+	vpclmulqdq	xmm3,xmm3,xmm6,0x00
+	vpxor	xmm4,xmm1,xmm0
+	vpxor	xmm3,xmm3,xmm4
+
+	vpslldq	xmm4,xmm3,8
+	vpsrldq	xmm3,xmm3,8
+	vpxor	xmm0,xmm0,xmm4
+	vpxor	xmm1,xmm1,xmm3
+	vpsllq	xmm3,xmm0,57
+	vpsllq	xmm4,xmm0,62
+	vpxor	xmm4,xmm4,xmm3
+	vpsllq	xmm3,xmm0,63
+	vpxor	xmm4,xmm4,xmm3
+	vpslldq	xmm3,xmm4,8
+	vpsrldq	xmm4,xmm4,8
+	vpxor	xmm0,xmm0,xmm3
+	vpxor	xmm1,xmm1,xmm4
+
+	vpsrlq	xmm4,xmm0,1
+	vpxor	xmm1,xmm1,xmm0
+	vpxor	xmm0,xmm0,xmm4
+	vpsrlq	xmm4,xmm4,5
+	vpxor	xmm0,xmm0,xmm4
+	vpsrlq	xmm0,xmm0,1
+	vpxor	xmm0,xmm0,xmm1
+$L$init_start_avx:
+	vmovdqa	xmm5,xmm0
+	vpunpckhqdq	xmm3,xmm0,xmm0
+	vpxor	xmm3,xmm3,xmm0
+	vpclmulqdq	xmm1,xmm0,xmm2,0x11
+	vpclmulqdq	xmm0,xmm0,xmm2,0x00
+	vpclmulqdq	xmm3,xmm3,xmm6,0x00
+	vpxor	xmm4,xmm1,xmm0
+	vpxor	xmm3,xmm3,xmm4
+
+	vpslldq	xmm4,xmm3,8
+	vpsrldq	xmm3,xmm3,8
+	vpxor	xmm0,xmm0,xmm4
+	vpxor	xmm1,xmm1,xmm3
+	vpsllq	xmm3,xmm0,57
+	vpsllq	xmm4,xmm0,62
+	vpxor	xmm4,xmm4,xmm3
+	vpsllq	xmm3,xmm0,63
+	vpxor	xmm4,xmm4,xmm3
+	vpslldq	xmm3,xmm4,8
+	vpsrldq	xmm4,xmm4,8
+	vpxor	xmm0,xmm0,xmm3
+	vpxor	xmm1,xmm1,xmm4
+
+	vpsrlq	xmm4,xmm0,1
+	vpxor	xmm1,xmm1,xmm0
+	vpxor	xmm0,xmm0,xmm4
+	vpsrlq	xmm4,xmm4,5
+	vpxor	xmm0,xmm0,xmm4
+	vpsrlq	xmm0,xmm0,1
+	vpxor	xmm0,xmm0,xmm1
+	vpshufd	xmm3,xmm5,78
+	vpshufd	xmm4,xmm0,78
+	vpxor	xmm3,xmm3,xmm5
+	vmovdqu	XMMWORD[rcx],xmm5
+	vpxor	xmm4,xmm4,xmm0
+	vmovdqu	XMMWORD[16+rcx],xmm0
+	lea	rcx,[48+rcx]
+	sub	r10,1
+	jnz	NEAR $L$init_loop_avx
+
+	vpalignr	xmm5,xmm3,xmm4,8
+	vmovdqu	XMMWORD[(-16)+rcx],xmm5
+
+	vzeroupper
+	movaps	xmm6,XMMWORD[rsp]
+	lea	rsp,[24+rsp]
+$L$SEH_end_gcm_init_avx:
+	DB	0F3h,0C3h		;repret
 
 global	gcm_gmult_avx
 
@@ -1321,7 +1434,403 @@
 
 ALIGN	32
 gcm_ghash_avx:
-	jmp	NEAR $L$_ghash_clmul
+	lea	rax,[((-136))+rsp]
+$L$SEH_begin_gcm_ghash_avx:
+
+DB	0x48,0x8d,0x60,0xe0
+DB	0x0f,0x29,0x70,0xe0
+DB	0x0f,0x29,0x78,0xf0
+DB	0x44,0x0f,0x29,0x00
+DB	0x44,0x0f,0x29,0x48,0x10
+DB	0x44,0x0f,0x29,0x50,0x20
+DB	0x44,0x0f,0x29,0x58,0x30
+DB	0x44,0x0f,0x29,0x60,0x40
+DB	0x44,0x0f,0x29,0x68,0x50
+DB	0x44,0x0f,0x29,0x70,0x60
+DB	0x44,0x0f,0x29,0x78,0x70
+	vzeroupper
+
+	vmovdqu	xmm10,XMMWORD[rcx]
+	lea	r10,[$L$0x1c2_polynomial]
+	lea	rdx,[64+rdx]
+	vmovdqu	xmm13,XMMWORD[$L$bswap_mask]
+	vpshufb	xmm10,xmm10,xmm13
+	cmp	r9,0x80
+	jb	NEAR $L$short_avx
+	sub	r9,0x80
+
+	vmovdqu	xmm14,XMMWORD[112+r8]
+	vmovdqu	xmm6,XMMWORD[((0-64))+rdx]
+	vpshufb	xmm14,xmm14,xmm13
+	vmovdqu	xmm7,XMMWORD[((32-64))+rdx]
+
+	vpunpckhqdq	xmm9,xmm14,xmm14
+	vmovdqu	xmm15,XMMWORD[96+r8]
+	vpclmulqdq	xmm0,xmm14,xmm6,0x00
+	vpxor	xmm9,xmm9,xmm14
+	vpshufb	xmm15,xmm15,xmm13
+	vpclmulqdq	xmm1,xmm14,xmm6,0x11
+	vmovdqu	xmm6,XMMWORD[((16-64))+rdx]
+	vpunpckhqdq	xmm8,xmm15,xmm15
+	vmovdqu	xmm14,XMMWORD[80+r8]
+	vpclmulqdq	xmm2,xmm9,xmm7,0x00
+	vpxor	xmm8,xmm8,xmm15
+
+	vpshufb	xmm14,xmm14,xmm13
+	vpclmulqdq	xmm3,xmm15,xmm6,0x00
+	vpunpckhqdq	xmm9,xmm14,xmm14
+	vpclmulqdq	xmm4,xmm15,xmm6,0x11
+	vmovdqu	xmm6,XMMWORD[((48-64))+rdx]
+	vpxor	xmm9,xmm9,xmm14
+	vmovdqu	xmm15,XMMWORD[64+r8]
+	vpclmulqdq	xmm5,xmm8,xmm7,0x10
+	vmovdqu	xmm7,XMMWORD[((80-64))+rdx]
+
+	vpshufb	xmm15,xmm15,xmm13
+	vpxor	xmm3,xmm3,xmm0
+	vpclmulqdq	xmm0,xmm14,xmm6,0x00
+	vpxor	xmm4,xmm4,xmm1
+	vpunpckhqdq	xmm8,xmm15,xmm15
+	vpclmulqdq	xmm1,xmm14,xmm6,0x11
+	vmovdqu	xmm6,XMMWORD[((64-64))+rdx]
+	vpxor	xmm5,xmm5,xmm2
+	vpclmulqdq	xmm2,xmm9,xmm7,0x00
+	vpxor	xmm8,xmm8,xmm15
+
+	vmovdqu	xmm14,XMMWORD[48+r8]
+	vpxor	xmm0,xmm0,xmm3
+	vpclmulqdq	xmm3,xmm15,xmm6,0x00
+	vpxor	xmm1,xmm1,xmm4
+	vpshufb	xmm14,xmm14,xmm13
+	vpclmulqdq	xmm4,xmm15,xmm6,0x11
+	vmovdqu	xmm6,XMMWORD[((96-64))+rdx]
+	vpxor	xmm2,xmm2,xmm5
+	vpunpckhqdq	xmm9,xmm14,xmm14
+	vpclmulqdq	xmm5,xmm8,xmm7,0x10
+	vmovdqu	xmm7,XMMWORD[((128-64))+rdx]
+	vpxor	xmm9,xmm9,xmm14
+
+	vmovdqu	xmm15,XMMWORD[32+r8]
+	vpxor	xmm3,xmm3,xmm0
+	vpclmulqdq	xmm0,xmm14,xmm6,0x00
+	vpxor	xmm4,xmm4,xmm1
+	vpshufb	xmm15,xmm15,xmm13
+	vpclmulqdq	xmm1,xmm14,xmm6,0x11
+	vmovdqu	xmm6,XMMWORD[((112-64))+rdx]
+	vpxor	xmm5,xmm5,xmm2
+	vpunpckhqdq	xmm8,xmm15,xmm15
+	vpclmulqdq	xmm2,xmm9,xmm7,0x00
+	vpxor	xmm8,xmm8,xmm15
+
+	vmovdqu	xmm14,XMMWORD[16+r8]
+	vpxor	xmm0,xmm0,xmm3
+	vpclmulqdq	xmm3,xmm15,xmm6,0x00
+	vpxor	xmm1,xmm1,xmm4
+	vpshufb	xmm14,xmm14,xmm13
+	vpclmulqdq	xmm4,xmm15,xmm6,0x11
+	vmovdqu	xmm6,XMMWORD[((144-64))+rdx]
+	vpxor	xmm2,xmm2,xmm5
+	vpunpckhqdq	xmm9,xmm14,xmm14
+	vpclmulqdq	xmm5,xmm8,xmm7,0x10
+	vmovdqu	xmm7,XMMWORD[((176-64))+rdx]
+	vpxor	xmm9,xmm9,xmm14
+
+	vmovdqu	xmm15,XMMWORD[r8]
+	vpxor	xmm3,xmm3,xmm0
+	vpclmulqdq	xmm0,xmm14,xmm6,0x00
+	vpxor	xmm4,xmm4,xmm1
+	vpshufb	xmm15,xmm15,xmm13
+	vpclmulqdq	xmm1,xmm14,xmm6,0x11
+	vmovdqu	xmm6,XMMWORD[((160-64))+rdx]
+	vpxor	xmm5,xmm5,xmm2
+	vpclmulqdq	xmm2,xmm9,xmm7,0x10
+
+	lea	r8,[128+r8]
+	cmp	r9,0x80
+	jb	NEAR $L$tail_avx
+
+	vpxor	xmm15,xmm15,xmm10
+	sub	r9,0x80
+	jmp	NEAR $L$oop8x_avx
+
+ALIGN	32
+$L$oop8x_avx:
+	vpunpckhqdq	xmm8,xmm15,xmm15
+	vmovdqu	xmm14,XMMWORD[112+r8]
+	vpxor	xmm3,xmm3,xmm0
+	vpxor	xmm8,xmm8,xmm15
+	vpclmulqdq	xmm10,xmm15,xmm6,0x00
+	vpshufb	xmm14,xmm14,xmm13
+	vpxor	xmm4,xmm4,xmm1
+	vpclmulqdq	xmm11,xmm15,xmm6,0x11
+	vmovdqu	xmm6,XMMWORD[((0-64))+rdx]
+	vpunpckhqdq	xmm9,xmm14,xmm14
+	vpxor	xmm5,xmm5,xmm2
+	vpclmulqdq	xmm12,xmm8,xmm7,0x00
+	vmovdqu	xmm7,XMMWORD[((32-64))+rdx]
+	vpxor	xmm9,xmm9,xmm14
+
+	vmovdqu	xmm15,XMMWORD[96+r8]
+	vpclmulqdq	xmm0,xmm14,xmm6,0x00
+	vpxor	xmm10,xmm10,xmm3
+	vpshufb	xmm15,xmm15,xmm13
+	vpclmulqdq	xmm1,xmm14,xmm6,0x11
+	vxorps	xmm11,xmm11,xmm4
+	vmovdqu	xmm6,XMMWORD[((16-64))+rdx]
+	vpunpckhqdq	xmm8,xmm15,xmm15
+	vpclmulqdq	xmm2,xmm9,xmm7,0x00
+	vpxor	xmm12,xmm12,xmm5
+	vxorps	xmm8,xmm8,xmm15
+
+	vmovdqu	xmm14,XMMWORD[80+r8]
+	vpxor	xmm12,xmm12,xmm10
+	vpclmulqdq	xmm3,xmm15,xmm6,0x00
+	vpxor	xmm12,xmm12,xmm11
+	vpslldq	xmm9,xmm12,8
+	vpxor	xmm3,xmm3,xmm0
+	vpclmulqdq	xmm4,xmm15,xmm6,0x11
+	vpsrldq	xmm12,xmm12,8
+	vpxor	xmm10,xmm10,xmm9
+	vmovdqu	xmm6,XMMWORD[((48-64))+rdx]
+	vpshufb	xmm14,xmm14,xmm13
+	vxorps	xmm11,xmm11,xmm12
+	vpxor	xmm4,xmm4,xmm1
+	vpunpckhqdq	xmm9,xmm14,xmm14
+	vpclmulqdq	xmm5,xmm8,xmm7,0x10
+	vmovdqu	xmm7,XMMWORD[((80-64))+rdx]
+	vpxor	xmm9,xmm9,xmm14
+	vpxor	xmm5,xmm5,xmm2
+
+	vmovdqu	xmm15,XMMWORD[64+r8]
+	vpalignr	xmm12,xmm10,xmm10,8
+	vpclmulqdq	xmm0,xmm14,xmm6,0x00
+	vpshufb	xmm15,xmm15,xmm13
+	vpxor	xmm0,xmm0,xmm3
+	vpclmulqdq	xmm1,xmm14,xmm6,0x11
+	vmovdqu	xmm6,XMMWORD[((64-64))+rdx]
+	vpunpckhqdq	xmm8,xmm15,xmm15
+	vpxor	xmm1,xmm1,xmm4
+	vpclmulqdq	xmm2,xmm9,xmm7,0x00
+	vxorps	xmm8,xmm8,xmm15
+	vpxor	xmm2,xmm2,xmm5
+
+	vmovdqu	xmm14,XMMWORD[48+r8]
+	vpclmulqdq	xmm10,xmm10,XMMWORD[r10],0x10
+	vpclmulqdq	xmm3,xmm15,xmm6,0x00
+	vpshufb	xmm14,xmm14,xmm13
+	vpxor	xmm3,xmm3,xmm0
+	vpclmulqdq	xmm4,xmm15,xmm6,0x11
+	vmovdqu	xmm6,XMMWORD[((96-64))+rdx]
+	vpunpckhqdq	xmm9,xmm14,xmm14
+	vpxor	xmm4,xmm4,xmm1
+	vpclmulqdq	xmm5,xmm8,xmm7,0x10
+	vmovdqu	xmm7,XMMWORD[((128-64))+rdx]
+	vpxor	xmm9,xmm9,xmm14
+	vpxor	xmm5,xmm5,xmm2
+
+	vmovdqu	xmm15,XMMWORD[32+r8]
+	vpclmulqdq	xmm0,xmm14,xmm6,0x00
+	vpshufb	xmm15,xmm15,xmm13
+	vpxor	xmm0,xmm0,xmm3
+	vpclmulqdq	xmm1,xmm14,xmm6,0x11
+	vmovdqu	xmm6,XMMWORD[((112-64))+rdx]
+	vpunpckhqdq	xmm8,xmm15,xmm15
+	vpxor	xmm1,xmm1,xmm4
+	vpclmulqdq	xmm2,xmm9,xmm7,0x00
+	vpxor	xmm8,xmm8,xmm15
+	vpxor	xmm2,xmm2,xmm5
+	vxorps	xmm10,xmm10,xmm12
+
+	vmovdqu	xmm14,XMMWORD[16+r8]
+	vpalignr	xmm12,xmm10,xmm10,8
+	vpclmulqdq	xmm3,xmm15,xmm6,0x00
+	vpshufb	xmm14,xmm14,xmm13
+	vpxor	xmm3,xmm3,xmm0
+	vpclmulqdq	xmm4,xmm15,xmm6,0x11
+	vmovdqu	xmm6,XMMWORD[((144-64))+rdx]
+	vpclmulqdq	xmm10,xmm10,XMMWORD[r10],0x10
+	vxorps	xmm12,xmm12,xmm11
+	vpunpckhqdq	xmm9,xmm14,xmm14
+	vpxor	xmm4,xmm4,xmm1
+	vpclmulqdq	xmm5,xmm8,xmm7,0x10
+	vmovdqu	xmm7,XMMWORD[((176-64))+rdx]
+	vpxor	xmm9,xmm9,xmm14
+	vpxor	xmm5,xmm5,xmm2
+
+	vmovdqu	xmm15,XMMWORD[r8]
+	vpclmulqdq	xmm0,xmm14,xmm6,0x00
+	vpshufb	xmm15,xmm15,xmm13
+	vpclmulqdq	xmm1,xmm14,xmm6,0x11
+	vmovdqu	xmm6,XMMWORD[((160-64))+rdx]
+	vpxor	xmm15,xmm15,xmm12
+	vpclmulqdq	xmm2,xmm9,xmm7,0x10
+	vpxor	xmm15,xmm15,xmm10
+
+	lea	r8,[128+r8]
+	sub	r9,0x80
+	jnc	NEAR $L$oop8x_avx
+
+	add	r9,0x80
+	jmp	NEAR $L$tail_no_xor_avx
+
+ALIGN	32
+$L$short_avx:
+	vmovdqu	xmm14,XMMWORD[((-16))+r9*1+r8]
+	lea	r8,[r9*1+r8]
+	vmovdqu	xmm6,XMMWORD[((0-64))+rdx]
+	vmovdqu	xmm7,XMMWORD[((32-64))+rdx]
+	vpshufb	xmm15,xmm14,xmm13
+
+	vmovdqa	xmm3,xmm0
+	vmovdqa	xmm4,xmm1
+	vmovdqa	xmm5,xmm2
+	sub	r9,0x10
+	jz	NEAR $L$tail_avx
+
+	vpunpckhqdq	xmm8,xmm15,xmm15
+	vpxor	xmm3,xmm3,xmm0
+	vpclmulqdq	xmm0,xmm15,xmm6,0x00
+	vpxor	xmm8,xmm8,xmm15
+	vmovdqu	xmm14,XMMWORD[((-32))+r8]
+	vpxor	xmm4,xmm4,xmm1
+	vpclmulqdq	xmm1,xmm15,xmm6,0x11
+	vmovdqu	xmm6,XMMWORD[((16-64))+rdx]
+	vpshufb	xmm15,xmm14,xmm13
+	vpxor	xmm5,xmm5,xmm2
+	vpclmulqdq	xmm2,xmm8,xmm7,0x00
+	vpsrldq	xmm7,xmm7,8
+	sub	r9,0x10
+	jz	NEAR $L$tail_avx
+
+	vpunpckhqdq	xmm8,xmm15,xmm15
+	vpxor	xmm3,xmm3,xmm0
+	vpclmulqdq	xmm0,xmm15,xmm6,0x00
+	vpxor	xmm8,xmm8,xmm15
+	vmovdqu	xmm14,XMMWORD[((-48))+r8]
+	vpxor	xmm4,xmm4,xmm1
+	vpclmulqdq	xmm1,xmm15,xmm6,0x11
+	vmovdqu	xmm6,XMMWORD[((48-64))+rdx]
+	vpshufb	xmm15,xmm14,xmm13
+	vpxor	xmm5,xmm5,xmm2
+	vpclmulqdq	xmm2,xmm8,xmm7,0x00
+	vmovdqu	xmm7,XMMWORD[((80-64))+rdx]
+	sub	r9,0x10
+	jz	NEAR $L$tail_avx
+
+	vpunpckhqdq	xmm8,xmm15,xmm15
+	vpxor	xmm3,xmm3,xmm0
+	vpclmulqdq	xmm0,xmm15,xmm6,0x00
+	vpxor	xmm8,xmm8,xmm15
+	vmovdqu	xmm14,XMMWORD[((-64))+r8]
+	vpxor	xmm4,xmm4,xmm1
+	vpclmulqdq	xmm1,xmm15,xmm6,0x11
+	vmovdqu	xmm6,XMMWORD[((64-64))+rdx]
+	vpshufb	xmm15,xmm14,xmm13
+	vpxor	xmm5,xmm5,xmm2
+	vpclmulqdq	xmm2,xmm8,xmm7,0x00
+	vpsrldq	xmm7,xmm7,8
+	sub	r9,0x10
+	jz	NEAR $L$tail_avx
+
+	vpunpckhqdq	xmm8,xmm15,xmm15
+	vpxor	xmm3,xmm3,xmm0
+	vpclmulqdq	xmm0,xmm15,xmm6,0x00
+	vpxor	xmm8,xmm8,xmm15
+	vmovdqu	xmm14,XMMWORD[((-80))+r8]
+	vpxor	xmm4,xmm4,xmm1
+	vpclmulqdq	xmm1,xmm15,xmm6,0x11
+	vmovdqu	xmm6,XMMWORD[((96-64))+rdx]
+	vpshufb	xmm15,xmm14,xmm13
+	vpxor	xmm5,xmm5,xmm2
+	vpclmulqdq	xmm2,xmm8,xmm7,0x00
+	vmovdqu	xmm7,XMMWORD[((128-64))+rdx]
+	sub	r9,0x10
+	jz	NEAR $L$tail_avx
+
+	vpunpckhqdq	xmm8,xmm15,xmm15
+	vpxor	xmm3,xmm3,xmm0
+	vpclmulqdq	xmm0,xmm15,xmm6,0x00
+	vpxor	xmm8,xmm8,xmm15
+	vmovdqu	xmm14,XMMWORD[((-96))+r8]
+	vpxor	xmm4,xmm4,xmm1
+	vpclmulqdq	xmm1,xmm15,xmm6,0x11
+	vmovdqu	xmm6,XMMWORD[((112-64))+rdx]
+	vpshufb	xmm15,xmm14,xmm13
+	vpxor	xmm5,xmm5,xmm2
+	vpclmulqdq	xmm2,xmm8,xmm7,0x00
+	vpsrldq	xmm7,xmm7,8
+	sub	r9,0x10
+	jz	NEAR $L$tail_avx
+
+	vpunpckhqdq	xmm8,xmm15,xmm15
+	vpxor	xmm3,xmm3,xmm0
+	vpclmulqdq	xmm0,xmm15,xmm6,0x00
+	vpxor	xmm8,xmm8,xmm15
+	vmovdqu	xmm14,XMMWORD[((-112))+r8]
+	vpxor	xmm4,xmm4,xmm1
+	vpclmulqdq	xmm1,xmm15,xmm6,0x11
+	vmovdqu	xmm6,XMMWORD[((144-64))+rdx]
+	vpshufb	xmm15,xmm14,xmm13
+	vpxor	xmm5,xmm5,xmm2
+	vpclmulqdq	xmm2,xmm8,xmm7,0x00
+	vmovq	xmm7,QWORD[((184-64))+rdx]
+	sub	r9,0x10
+	jmp	NEAR $L$tail_avx
+
+ALIGN	32
+$L$tail_avx:
+	vpxor	xmm15,xmm15,xmm10
+$L$tail_no_xor_avx:
+	vpunpckhqdq	xmm8,xmm15,xmm15
+	vpxor	xmm3,xmm3,xmm0
+	vpclmulqdq	xmm0,xmm15,xmm6,0x00
+	vpxor	xmm8,xmm8,xmm15
+	vpxor	xmm4,xmm4,xmm1
+	vpclmulqdq	xmm1,xmm15,xmm6,0x11
+	vpxor	xmm5,xmm5,xmm2
+	vpclmulqdq	xmm2,xmm8,xmm7,0x00
+
+	vmovdqu	xmm12,XMMWORD[r10]
+
+	vpxor	xmm10,xmm3,xmm0
+	vpxor	xmm11,xmm4,xmm1
+	vpxor	xmm5,xmm5,xmm2
+
+	vpxor	xmm5,xmm5,xmm10
+	vpxor	xmm5,xmm5,xmm11
+	vpslldq	xmm9,xmm5,8
+	vpsrldq	xmm5,xmm5,8
+	vpxor	xmm10,xmm10,xmm9
+	vpxor	xmm11,xmm11,xmm5
+
+	vpclmulqdq	xmm9,xmm10,xmm12,0x10
+	vpalignr	xmm10,xmm10,xmm10,8
+	vpxor	xmm10,xmm10,xmm9
+
+	vpclmulqdq	xmm9,xmm10,xmm12,0x10
+	vpalignr	xmm10,xmm10,xmm10,8
+	vpxor	xmm10,xmm10,xmm11
+	vpxor	xmm10,xmm10,xmm9
+
+	cmp	r9,0
+	jne	NEAR $L$short_avx
+
+	vpshufb	xmm10,xmm10,xmm13
+	vmovdqu	XMMWORD[rcx],xmm10
+	vzeroupper
+	movaps	xmm6,XMMWORD[rsp]
+	movaps	xmm7,XMMWORD[16+rsp]
+	movaps	xmm8,XMMWORD[32+rsp]
+	movaps	xmm9,XMMWORD[48+rsp]
+	movaps	xmm10,XMMWORD[64+rsp]
+	movaps	xmm11,XMMWORD[80+rsp]
+	movaps	xmm12,XMMWORD[96+rsp]
+	movaps	xmm13,XMMWORD[112+rsp]
+	movaps	xmm14,XMMWORD[128+rsp]
+	movaps	xmm15,XMMWORD[144+rsp]
+	lea	rsp,[168+rsp]
+$L$SEH_end_gcm_ghash_avx:
+	DB	0F3h,0C3h		;repret
 
 ALIGN	64
 $L$bswap_mask:
@@ -1412,14 +1921,20 @@
 	cmp	rbx,r10
 	jae	NEAR $L$in_prologue
 
-	lea	rax,[24+rax]
+	lea	rax,[((48+280))+rax]
 
 	mov	rbx,QWORD[((-8))+rax]
 	mov	rbp,QWORD[((-16))+rax]
 	mov	r12,QWORD[((-24))+rax]
+	mov	r13,QWORD[((-32))+rax]
+	mov	r14,QWORD[((-40))+rax]
+	mov	r15,QWORD[((-48))+rax]
 	mov	QWORD[144+r8],rbx
 	mov	QWORD[160+r8],rbp
 	mov	QWORD[216+r8],r12
+	mov	QWORD[224+r8],r13
+	mov	QWORD[232+r8],r14
+	mov	QWORD[240+r8],r15
 
 $L$in_prologue:
 	mov	rdi,QWORD[8+rax]
@@ -1478,6 +1993,13 @@
 	DD	$L$SEH_begin_gcm_ghash_clmul wrt ..imagebase
 	DD	$L$SEH_end_gcm_ghash_clmul wrt ..imagebase
 	DD	$L$SEH_info_gcm_ghash_clmul wrt ..imagebase
+	DD	$L$SEH_begin_gcm_init_avx wrt ..imagebase
+	DD	$L$SEH_end_gcm_init_avx wrt ..imagebase
+	DD	$L$SEH_info_gcm_init_clmul wrt ..imagebase
+
+	DD	$L$SEH_begin_gcm_ghash_avx wrt ..imagebase
+	DD	$L$SEH_end_gcm_ghash_avx wrt ..imagebase
+	DD	$L$SEH_info_gcm_ghash_clmul wrt ..imagebase
 section	.xdata rdata align=8
 ALIGN	8
 $L$SEH_info_gcm_gmult_4bit:
diff --git a/win-x86_64/crypto/rc4/rc4-x86_64.asm b/win-x86_64/crypto/rc4/rc4-x86_64.asm
deleted file mode 100644
index c7c3b7b..0000000
--- a/win-x86_64/crypto/rc4/rc4-x86_64.asm
+++ /dev/null
@@ -1,741 +0,0 @@
-default	rel
-%define XMMWORD
-%define YMMWORD
-%define ZMMWORD
-section	.text code align=64
-
-EXTERN	OPENSSL_ia32cap_P
-
-global	asm_RC4
-
-ALIGN	16
-asm_RC4:
-	mov	QWORD[8+rsp],rdi	;WIN64 prologue
-	mov	QWORD[16+rsp],rsi
-	mov	rax,rsp
-$L$SEH_begin_asm_RC4:
-	mov	rdi,rcx
-	mov	rsi,rdx
-	mov	rdx,r8
-	mov	rcx,r9
-
-
-	or	rsi,rsi
-	jne	NEAR $L$entry
-	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
-	mov	rsi,QWORD[16+rsp]
-	DB	0F3h,0C3h		;repret
-$L$entry:
-	push	rbx
-	push	r12
-	push	r13
-$L$prologue:
-	mov	r11,rsi
-	mov	r12,rdx
-	mov	r13,rcx
-	xor	r10,r10
-	xor	rcx,rcx
-
-	lea	rdi,[8+rdi]
-	mov	r10b,BYTE[((-8))+rdi]
-	mov	cl,BYTE[((-4))+rdi]
-	cmp	DWORD[256+rdi],-1
-	je	NEAR $L$RC4_CHAR
-	mov	r8d,DWORD[OPENSSL_ia32cap_P]
-	xor	rbx,rbx
-	inc	r10b
-	sub	rbx,r10
-	sub	r13,r12
-	mov	eax,DWORD[r10*4+rdi]
-	test	r11,-16
-	jz	NEAR $L$loop1
-	bt	r8d,30
-	jc	NEAR $L$intel
-	and	rbx,7
-	lea	rsi,[1+r10]
-	jz	NEAR $L$oop8
-	sub	r11,rbx
-$L$oop8_warmup:
-	add	cl,al
-	mov	edx,DWORD[rcx*4+rdi]
-	mov	DWORD[rcx*4+rdi],eax
-	mov	DWORD[r10*4+rdi],edx
-	add	al,dl
-	inc	r10b
-	mov	edx,DWORD[rax*4+rdi]
-	mov	eax,DWORD[r10*4+rdi]
-	xor	dl,BYTE[r12]
-	mov	BYTE[r13*1+r12],dl
-	lea	r12,[1+r12]
-	dec	rbx
-	jnz	NEAR $L$oop8_warmup
-
-	lea	rsi,[1+r10]
-	jmp	NEAR $L$oop8
-ALIGN	16
-$L$oop8:
-	add	cl,al
-	mov	edx,DWORD[rcx*4+rdi]
-	mov	DWORD[rcx*4+rdi],eax
-	mov	ebx,DWORD[rsi*4+rdi]
-	ror	r8,8
-	mov	DWORD[r10*4+rdi],edx
-	add	dl,al
-	mov	r8b,BYTE[rdx*4+rdi]
-	add	cl,bl
-	mov	edx,DWORD[rcx*4+rdi]
-	mov	DWORD[rcx*4+rdi],ebx
-	mov	eax,DWORD[4+rsi*4+rdi]
-	ror	r8,8
-	mov	DWORD[4+r10*4+rdi],edx
-	add	dl,bl
-	mov	r8b,BYTE[rdx*4+rdi]
-	add	cl,al
-	mov	edx,DWORD[rcx*4+rdi]
-	mov	DWORD[rcx*4+rdi],eax
-	mov	ebx,DWORD[8+rsi*4+rdi]
-	ror	r8,8
-	mov	DWORD[8+r10*4+rdi],edx
-	add	dl,al
-	mov	r8b,BYTE[rdx*4+rdi]
-	add	cl,bl
-	mov	edx,DWORD[rcx*4+rdi]
-	mov	DWORD[rcx*4+rdi],ebx
-	mov	eax,DWORD[12+rsi*4+rdi]
-	ror	r8,8
-	mov	DWORD[12+r10*4+rdi],edx
-	add	dl,bl
-	mov	r8b,BYTE[rdx*4+rdi]
-	add	cl,al
-	mov	edx,DWORD[rcx*4+rdi]
-	mov	DWORD[rcx*4+rdi],eax
-	mov	ebx,DWORD[16+rsi*4+rdi]
-	ror	r8,8
-	mov	DWORD[16+r10*4+rdi],edx
-	add	dl,al
-	mov	r8b,BYTE[rdx*4+rdi]
-	add	cl,bl
-	mov	edx,DWORD[rcx*4+rdi]
-	mov	DWORD[rcx*4+rdi],ebx
-	mov	eax,DWORD[20+rsi*4+rdi]
-	ror	r8,8
-	mov	DWORD[20+r10*4+rdi],edx
-	add	dl,bl
-	mov	r8b,BYTE[rdx*4+rdi]
-	add	cl,al
-	mov	edx,DWORD[rcx*4+rdi]
-	mov	DWORD[rcx*4+rdi],eax
-	mov	ebx,DWORD[24+rsi*4+rdi]
-	ror	r8,8
-	mov	DWORD[24+r10*4+rdi],edx
-	add	dl,al
-	mov	r8b,BYTE[rdx*4+rdi]
-	add	sil,8
-	add	cl,bl
-	mov	edx,DWORD[rcx*4+rdi]
-	mov	DWORD[rcx*4+rdi],ebx
-	mov	eax,DWORD[((-4))+rsi*4+rdi]
-	ror	r8,8
-	mov	DWORD[28+r10*4+rdi],edx
-	add	dl,bl
-	mov	r8b,BYTE[rdx*4+rdi]
-	add	r10b,8
-	ror	r8,8
-	sub	r11,8
-
-	xor	r8,QWORD[r12]
-	mov	QWORD[r13*1+r12],r8
-	lea	r12,[8+r12]
-
-	test	r11,-8
-	jnz	NEAR $L$oop8
-	cmp	r11,0
-	jne	NEAR $L$loop1
-	jmp	NEAR $L$exit
-
-ALIGN	16
-$L$intel:
-	test	r11,-32
-	jz	NEAR $L$loop1
-	and	rbx,15
-	jz	NEAR $L$oop16_is_hot
-	sub	r11,rbx
-$L$oop16_warmup:
-	add	cl,al
-	mov	edx,DWORD[rcx*4+rdi]
-	mov	DWORD[rcx*4+rdi],eax
-	mov	DWORD[r10*4+rdi],edx
-	add	al,dl
-	inc	r10b
-	mov	edx,DWORD[rax*4+rdi]
-	mov	eax,DWORD[r10*4+rdi]
-	xor	dl,BYTE[r12]
-	mov	BYTE[r13*1+r12],dl
-	lea	r12,[1+r12]
-	dec	rbx
-	jnz	NEAR $L$oop16_warmup
-
-	mov	rbx,rcx
-	xor	rcx,rcx
-	mov	cl,bl
-
-$L$oop16_is_hot:
-	lea	rsi,[r10*4+rdi]
-	add	cl,al
-	mov	edx,DWORD[rcx*4+rdi]
-	pxor	xmm0,xmm0
-	mov	DWORD[rcx*4+rdi],eax
-	add	al,dl
-	mov	ebx,DWORD[4+rsi]
-	movzx	eax,al
-	mov	DWORD[rsi],edx
-	add	cl,bl
-	pinsrw	xmm0,WORD[rax*4+rdi],0
-	jmp	NEAR $L$oop16_enter
-ALIGN	16
-$L$oop16:
-	add	cl,al
-	mov	edx,DWORD[rcx*4+rdi]
-	pxor	xmm2,xmm0
-	psllq	xmm1,8
-	pxor	xmm0,xmm0
-	mov	DWORD[rcx*4+rdi],eax
-	add	al,dl
-	mov	ebx,DWORD[4+rsi]
-	movzx	eax,al
-	mov	DWORD[rsi],edx
-	pxor	xmm2,xmm1
-	add	cl,bl
-	pinsrw	xmm0,WORD[rax*4+rdi],0
-	movdqu	XMMWORD[r13*1+r12],xmm2
-	lea	r12,[16+r12]
-$L$oop16_enter:
-	mov	edx,DWORD[rcx*4+rdi]
-	pxor	xmm1,xmm1
-	mov	DWORD[rcx*4+rdi],ebx
-	add	bl,dl
-	mov	eax,DWORD[8+rsi]
-	movzx	ebx,bl
-	mov	DWORD[4+rsi],edx
-	add	cl,al
-	pinsrw	xmm1,WORD[rbx*4+rdi],0
-	mov	edx,DWORD[rcx*4+rdi]
-	mov	DWORD[rcx*4+rdi],eax
-	add	al,dl
-	mov	ebx,DWORD[12+rsi]
-	movzx	eax,al
-	mov	DWORD[8+rsi],edx
-	add	cl,bl
-	pinsrw	xmm0,WORD[rax*4+rdi],1
-	mov	edx,DWORD[rcx*4+rdi]
-	mov	DWORD[rcx*4+rdi],ebx
-	add	bl,dl
-	mov	eax,DWORD[16+rsi]
-	movzx	ebx,bl
-	mov	DWORD[12+rsi],edx
-	add	cl,al
-	pinsrw	xmm1,WORD[rbx*4+rdi],1
-	mov	edx,DWORD[rcx*4+rdi]
-	mov	DWORD[rcx*4+rdi],eax
-	add	al,dl
-	mov	ebx,DWORD[20+rsi]
-	movzx	eax,al
-	mov	DWORD[16+rsi],edx
-	add	cl,bl
-	pinsrw	xmm0,WORD[rax*4+rdi],2
-	mov	edx,DWORD[rcx*4+rdi]
-	mov	DWORD[rcx*4+rdi],ebx
-	add	bl,dl
-	mov	eax,DWORD[24+rsi]
-	movzx	ebx,bl
-	mov	DWORD[20+rsi],edx
-	add	cl,al
-	pinsrw	xmm1,WORD[rbx*4+rdi],2
-	mov	edx,DWORD[rcx*4+rdi]
-	mov	DWORD[rcx*4+rdi],eax
-	add	al,dl
-	mov	ebx,DWORD[28+rsi]
-	movzx	eax,al
-	mov	DWORD[24+rsi],edx
-	add	cl,bl
-	pinsrw	xmm0,WORD[rax*4+rdi],3
-	mov	edx,DWORD[rcx*4+rdi]
-	mov	DWORD[rcx*4+rdi],ebx
-	add	bl,dl
-	mov	eax,DWORD[32+rsi]
-	movzx	ebx,bl
-	mov	DWORD[28+rsi],edx
-	add	cl,al
-	pinsrw	xmm1,WORD[rbx*4+rdi],3
-	mov	edx,DWORD[rcx*4+rdi]
-	mov	DWORD[rcx*4+rdi],eax
-	add	al,dl
-	mov	ebx,DWORD[36+rsi]
-	movzx	eax,al
-	mov	DWORD[32+rsi],edx
-	add	cl,bl
-	pinsrw	xmm0,WORD[rax*4+rdi],4
-	mov	edx,DWORD[rcx*4+rdi]
-	mov	DWORD[rcx*4+rdi],ebx
-	add	bl,dl
-	mov	eax,DWORD[40+rsi]
-	movzx	ebx,bl
-	mov	DWORD[36+rsi],edx
-	add	cl,al
-	pinsrw	xmm1,WORD[rbx*4+rdi],4
-	mov	edx,DWORD[rcx*4+rdi]
-	mov	DWORD[rcx*4+rdi],eax
-	add	al,dl
-	mov	ebx,DWORD[44+rsi]
-	movzx	eax,al
-	mov	DWORD[40+rsi],edx
-	add	cl,bl
-	pinsrw	xmm0,WORD[rax*4+rdi],5
-	mov	edx,DWORD[rcx*4+rdi]
-	mov	DWORD[rcx*4+rdi],ebx
-	add	bl,dl
-	mov	eax,DWORD[48+rsi]
-	movzx	ebx,bl
-	mov	DWORD[44+rsi],edx
-	add	cl,al
-	pinsrw	xmm1,WORD[rbx*4+rdi],5
-	mov	edx,DWORD[rcx*4+rdi]
-	mov	DWORD[rcx*4+rdi],eax
-	add	al,dl
-	mov	ebx,DWORD[52+rsi]
-	movzx	eax,al
-	mov	DWORD[48+rsi],edx
-	add	cl,bl
-	pinsrw	xmm0,WORD[rax*4+rdi],6
-	mov	edx,DWORD[rcx*4+rdi]
-	mov	DWORD[rcx*4+rdi],ebx
-	add	bl,dl
-	mov	eax,DWORD[56+rsi]
-	movzx	ebx,bl
-	mov	DWORD[52+rsi],edx
-	add	cl,al
-	pinsrw	xmm1,WORD[rbx*4+rdi],6
-	mov	edx,DWORD[rcx*4+rdi]
-	mov	DWORD[rcx*4+rdi],eax
-	add	al,dl
-	mov	ebx,DWORD[60+rsi]
-	movzx	eax,al
-	mov	DWORD[56+rsi],edx
-	add	cl,bl
-	pinsrw	xmm0,WORD[rax*4+rdi],7
-	add	r10b,16
-	movdqu	xmm2,XMMWORD[r12]
-	mov	edx,DWORD[rcx*4+rdi]
-	mov	DWORD[rcx*4+rdi],ebx
-	add	bl,dl
-	movzx	ebx,bl
-	mov	DWORD[60+rsi],edx
-	lea	rsi,[r10*4+rdi]
-	pinsrw	xmm1,WORD[rbx*4+rdi],7
-	mov	eax,DWORD[rsi]
-	mov	rbx,rcx
-	xor	rcx,rcx
-	sub	r11,16
-	mov	cl,bl
-	test	r11,-16
-	jnz	NEAR $L$oop16
-
-	psllq	xmm1,8
-	pxor	xmm2,xmm0
-	pxor	xmm2,xmm1
-	movdqu	XMMWORD[r13*1+r12],xmm2
-	lea	r12,[16+r12]
-
-	cmp	r11,0
-	jne	NEAR $L$loop1
-	jmp	NEAR $L$exit
-
-ALIGN	16
-$L$loop1:
-	add	cl,al
-	mov	edx,DWORD[rcx*4+rdi]
-	mov	DWORD[rcx*4+rdi],eax
-	mov	DWORD[r10*4+rdi],edx
-	add	al,dl
-	inc	r10b
-	mov	edx,DWORD[rax*4+rdi]
-	mov	eax,DWORD[r10*4+rdi]
-	xor	dl,BYTE[r12]
-	mov	BYTE[r13*1+r12],dl
-	lea	r12,[1+r12]
-	dec	r11
-	jnz	NEAR $L$loop1
-	jmp	NEAR $L$exit
-
-ALIGN	16
-$L$RC4_CHAR:
-	add	r10b,1
-	movzx	eax,BYTE[r10*1+rdi]
-	test	r11,-8
-	jz	NEAR $L$cloop1
-	jmp	NEAR $L$cloop8
-ALIGN	16
-$L$cloop8:
-	mov	r8d,DWORD[r12]
-	mov	r9d,DWORD[4+r12]
-	add	cl,al
-	lea	rsi,[1+r10]
-	movzx	edx,BYTE[rcx*1+rdi]
-	movzx	esi,sil
-	movzx	ebx,BYTE[rsi*1+rdi]
-	mov	BYTE[rcx*1+rdi],al
-	cmp	rcx,rsi
-	mov	BYTE[r10*1+rdi],dl
-	jne	NEAR $L$cmov0
-	mov	rbx,rax
-$L$cmov0:
-	add	dl,al
-	xor	r8b,BYTE[rdx*1+rdi]
-	ror	r8d,8
-	add	cl,bl
-	lea	r10,[1+rsi]
-	movzx	edx,BYTE[rcx*1+rdi]
-	movzx	r10d,r10b
-	movzx	eax,BYTE[r10*1+rdi]
-	mov	BYTE[rcx*1+rdi],bl
-	cmp	rcx,r10
-	mov	BYTE[rsi*1+rdi],dl
-	jne	NEAR $L$cmov1
-	mov	rax,rbx
-$L$cmov1:
-	add	dl,bl
-	xor	r8b,BYTE[rdx*1+rdi]
-	ror	r8d,8
-	add	cl,al
-	lea	rsi,[1+r10]
-	movzx	edx,BYTE[rcx*1+rdi]
-	movzx	esi,sil
-	movzx	ebx,BYTE[rsi*1+rdi]
-	mov	BYTE[rcx*1+rdi],al
-	cmp	rcx,rsi
-	mov	BYTE[r10*1+rdi],dl
-	jne	NEAR $L$cmov2
-	mov	rbx,rax
-$L$cmov2:
-	add	dl,al
-	xor	r8b,BYTE[rdx*1+rdi]
-	ror	r8d,8
-	add	cl,bl
-	lea	r10,[1+rsi]
-	movzx	edx,BYTE[rcx*1+rdi]
-	movzx	r10d,r10b
-	movzx	eax,BYTE[r10*1+rdi]
-	mov	BYTE[rcx*1+rdi],bl
-	cmp	rcx,r10
-	mov	BYTE[rsi*1+rdi],dl
-	jne	NEAR $L$cmov3
-	mov	rax,rbx
-$L$cmov3:
-	add	dl,bl
-	xor	r8b,BYTE[rdx*1+rdi]
-	ror	r8d,8
-	add	cl,al
-	lea	rsi,[1+r10]
-	movzx	edx,BYTE[rcx*1+rdi]
-	movzx	esi,sil
-	movzx	ebx,BYTE[rsi*1+rdi]
-	mov	BYTE[rcx*1+rdi],al
-	cmp	rcx,rsi
-	mov	BYTE[r10*1+rdi],dl
-	jne	NEAR $L$cmov4
-	mov	rbx,rax
-$L$cmov4:
-	add	dl,al
-	xor	r9b,BYTE[rdx*1+rdi]
-	ror	r9d,8
-	add	cl,bl
-	lea	r10,[1+rsi]
-	movzx	edx,BYTE[rcx*1+rdi]
-	movzx	r10d,r10b
-	movzx	eax,BYTE[r10*1+rdi]
-	mov	BYTE[rcx*1+rdi],bl
-	cmp	rcx,r10
-	mov	BYTE[rsi*1+rdi],dl
-	jne	NEAR $L$cmov5
-	mov	rax,rbx
-$L$cmov5:
-	add	dl,bl
-	xor	r9b,BYTE[rdx*1+rdi]
-	ror	r9d,8
-	add	cl,al
-	lea	rsi,[1+r10]
-	movzx	edx,BYTE[rcx*1+rdi]
-	movzx	esi,sil
-	movzx	ebx,BYTE[rsi*1+rdi]
-	mov	BYTE[rcx*1+rdi],al
-	cmp	rcx,rsi
-	mov	BYTE[r10*1+rdi],dl
-	jne	NEAR $L$cmov6
-	mov	rbx,rax
-$L$cmov6:
-	add	dl,al
-	xor	r9b,BYTE[rdx*1+rdi]
-	ror	r9d,8
-	add	cl,bl
-	lea	r10,[1+rsi]
-	movzx	edx,BYTE[rcx*1+rdi]
-	movzx	r10d,r10b
-	movzx	eax,BYTE[r10*1+rdi]
-	mov	BYTE[rcx*1+rdi],bl
-	cmp	rcx,r10
-	mov	BYTE[rsi*1+rdi],dl
-	jne	NEAR $L$cmov7
-	mov	rax,rbx
-$L$cmov7:
-	add	dl,bl
-	xor	r9b,BYTE[rdx*1+rdi]
-	ror	r9d,8
-	lea	r11,[((-8))+r11]
-	mov	DWORD[r13],r8d
-	lea	r12,[8+r12]
-	mov	DWORD[4+r13],r9d
-	lea	r13,[8+r13]
-
-	test	r11,-8
-	jnz	NEAR $L$cloop8
-	cmp	r11,0
-	jne	NEAR $L$cloop1
-	jmp	NEAR $L$exit
-ALIGN	16
-$L$cloop1:
-	add	cl,al
-	movzx	ecx,cl
-	movzx	edx,BYTE[rcx*1+rdi]
-	mov	BYTE[rcx*1+rdi],al
-	mov	BYTE[r10*1+rdi],dl
-	add	dl,al
-	add	r10b,1
-	movzx	edx,dl
-	movzx	r10d,r10b
-	movzx	edx,BYTE[rdx*1+rdi]
-	movzx	eax,BYTE[r10*1+rdi]
-	xor	dl,BYTE[r12]
-	lea	r12,[1+r12]
-	mov	BYTE[r13],dl
-	lea	r13,[1+r13]
-	sub	r11,1
-	jnz	NEAR $L$cloop1
-	jmp	NEAR $L$exit
-
-ALIGN	16
-$L$exit:
-	sub	r10b,1
-	mov	DWORD[((-8))+rdi],r10d
-	mov	DWORD[((-4))+rdi],ecx
-
-	mov	r13,QWORD[rsp]
-	mov	r12,QWORD[8+rsp]
-	mov	rbx,QWORD[16+rsp]
-	add	rsp,24
-$L$epilogue:
-	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
-	mov	rsi,QWORD[16+rsp]
-	DB	0F3h,0C3h		;repret
-$L$SEH_end_asm_RC4:
-global	asm_RC4_set_key
-
-ALIGN	16
-asm_RC4_set_key:
-	mov	QWORD[8+rsp],rdi	;WIN64 prologue
-	mov	QWORD[16+rsp],rsi
-	mov	rax,rsp
-$L$SEH_begin_asm_RC4_set_key:
-	mov	rdi,rcx
-	mov	rsi,rdx
-	mov	rdx,r8
-
-
-	lea	rdi,[8+rdi]
-	lea	rdx,[rsi*1+rdx]
-	neg	rsi
-	mov	rcx,rsi
-	xor	eax,eax
-	xor	r9,r9
-	xor	r10,r10
-	xor	r11,r11
-
-	mov	r8d,DWORD[OPENSSL_ia32cap_P]
-	bt	r8d,20
-	jc	NEAR $L$c1stloop
-	jmp	NEAR $L$w1stloop
-
-ALIGN	16
-$L$w1stloop:
-	mov	DWORD[rax*4+rdi],eax
-	add	al,1
-	jnc	NEAR $L$w1stloop
-
-	xor	r9,r9
-	xor	r8,r8
-ALIGN	16
-$L$w2ndloop:
-	mov	r10d,DWORD[r9*4+rdi]
-	add	r8b,BYTE[rsi*1+rdx]
-	add	r8b,r10b
-	add	rsi,1
-	mov	r11d,DWORD[r8*4+rdi]
-	cmovz	rsi,rcx
-	mov	DWORD[r8*4+rdi],r10d
-	mov	DWORD[r9*4+rdi],r11d
-	add	r9b,1
-	jnc	NEAR $L$w2ndloop
-	jmp	NEAR $L$exit_key
-
-ALIGN	16
-$L$c1stloop:
-	mov	BYTE[rax*1+rdi],al
-	add	al,1
-	jnc	NEAR $L$c1stloop
-
-	xor	r9,r9
-	xor	r8,r8
-ALIGN	16
-$L$c2ndloop:
-	mov	r10b,BYTE[r9*1+rdi]
-	add	r8b,BYTE[rsi*1+rdx]
-	add	r8b,r10b
-	add	rsi,1
-	mov	r11b,BYTE[r8*1+rdi]
-	jnz	NEAR $L$cnowrap
-	mov	rsi,rcx
-$L$cnowrap:
-	mov	BYTE[r8*1+rdi],r10b
-	mov	BYTE[r9*1+rdi],r11b
-	add	r9b,1
-	jnc	NEAR $L$c2ndloop
-	mov	DWORD[256+rdi],-1
-
-ALIGN	16
-$L$exit_key:
-	xor	eax,eax
-	mov	DWORD[((-8))+rdi],eax
-	mov	DWORD[((-4))+rdi],eax
-	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
-	mov	rsi,QWORD[16+rsp]
-	DB	0F3h,0C3h		;repret
-$L$SEH_end_asm_RC4_set_key:
-EXTERN	__imp_RtlVirtualUnwind
-
-ALIGN	16
-stream_se_handler:
-	push	rsi
-	push	rdi
-	push	rbx
-	push	rbp
-	push	r12
-	push	r13
-	push	r14
-	push	r15
-	pushfq
-	sub	rsp,64
-
-	mov	rax,QWORD[120+r8]
-	mov	rbx,QWORD[248+r8]
-
-	lea	r10,[$L$prologue]
-	cmp	rbx,r10
-	jb	NEAR $L$in_prologue
-
-	mov	rax,QWORD[152+r8]
-
-	lea	r10,[$L$epilogue]
-	cmp	rbx,r10
-	jae	NEAR $L$in_prologue
-
-	lea	rax,[24+rax]
-
-	mov	rbx,QWORD[((-8))+rax]
-	mov	r12,QWORD[((-16))+rax]
-	mov	r13,QWORD[((-24))+rax]
-	mov	QWORD[144+r8],rbx
-	mov	QWORD[216+r8],r12
-	mov	QWORD[224+r8],r13
-
-$L$in_prologue:
-	mov	rdi,QWORD[8+rax]
-	mov	rsi,QWORD[16+rax]
-	mov	QWORD[152+r8],rax
-	mov	QWORD[168+r8],rsi
-	mov	QWORD[176+r8],rdi
-
-	jmp	NEAR $L$common_seh_exit
-
-
-
-ALIGN	16
-key_se_handler:
-	push	rsi
-	push	rdi
-	push	rbx
-	push	rbp
-	push	r12
-	push	r13
-	push	r14
-	push	r15
-	pushfq
-	sub	rsp,64
-
-	mov	rax,QWORD[152+r8]
-	mov	rdi,QWORD[8+rax]
-	mov	rsi,QWORD[16+rax]
-	mov	QWORD[168+r8],rsi
-	mov	QWORD[176+r8],rdi
-
-$L$common_seh_exit:
-
-	mov	rdi,QWORD[40+r9]
-	mov	rsi,r8
-	mov	ecx,154
-	DD	0xa548f3fc
-
-	mov	rsi,r9
-	xor	rcx,rcx
-	mov	rdx,QWORD[8+rsi]
-	mov	r8,QWORD[rsi]
-	mov	r9,QWORD[16+rsi]
-	mov	r10,QWORD[40+rsi]
-	lea	r11,[56+rsi]
-	lea	r12,[24+rsi]
-	mov	QWORD[32+rsp],r10
-	mov	QWORD[40+rsp],r11
-	mov	QWORD[48+rsp],r12
-	mov	QWORD[56+rsp],rcx
-	call	QWORD[__imp_RtlVirtualUnwind]
-
-	mov	eax,1
-	add	rsp,64
-	popfq
-	pop	r15
-	pop	r14
-	pop	r13
-	pop	r12
-	pop	rbp
-	pop	rbx
-	pop	rdi
-	pop	rsi
-	DB	0F3h,0C3h		;repret
-
-
-section	.pdata rdata align=4
-ALIGN	4
-	DD	$L$SEH_begin_asm_RC4 wrt ..imagebase
-	DD	$L$SEH_end_asm_RC4 wrt ..imagebase
-	DD	$L$SEH_info_asm_RC4 wrt ..imagebase
-
-	DD	$L$SEH_begin_asm_RC4_set_key wrt ..imagebase
-	DD	$L$SEH_end_asm_RC4_set_key wrt ..imagebase
-	DD	$L$SEH_info_asm_RC4_set_key wrt ..imagebase
-
-section	.xdata rdata align=8
-ALIGN	8
-$L$SEH_info_asm_RC4:
-DB	9,0,0,0
-	DD	stream_se_handler wrt ..imagebase
-$L$SEH_info_asm_RC4_set_key:
-DB	9,0,0,0
-	DD	key_se_handler wrt ..imagebase
diff --git a/win-x86_64/crypto/sha/sha1-x86_64.asm b/win-x86_64/crypto/sha/sha1-x86_64.asm
index 168f78d..5484574 100644
--- a/win-x86_64/crypto/sha/sha1-x86_64.asm
+++ b/win-x86_64/crypto/sha/sha1-x86_64.asm
@@ -1263,21 +1263,20 @@
 
 
 _ssse3_shortcut:
-	mov	rax,rsp
+	mov	r11,rsp
 	push	rbx
 	push	rbp
 	push	r12
 	push	r13
 	push	r14
 	lea	rsp,[((-160))+rsp]
-	movaps	XMMWORD[(-40-96)+rax],xmm6
-	movaps	XMMWORD[(-40-80)+rax],xmm7
-	movaps	XMMWORD[(-40-64)+rax],xmm8
-	movaps	XMMWORD[(-40-48)+rax],xmm9
-	movaps	XMMWORD[(-40-32)+rax],xmm10
-	movaps	XMMWORD[(-40-16)+rax],xmm11
+	movaps	XMMWORD[(-40-96)+r11],xmm6
+	movaps	XMMWORD[(-40-80)+r11],xmm7
+	movaps	XMMWORD[(-40-64)+r11],xmm8
+	movaps	XMMWORD[(-40-48)+r11],xmm9
+	movaps	XMMWORD[(-40-32)+r11],xmm10
+	movaps	XMMWORD[(-40-16)+r11],xmm11
 $L$prologue_ssse3:
-	mov	r14,rax
 	and	rsp,-64
 	mov	r8,rdi
 	mov	r9,rsi
@@ -1285,7 +1284,7 @@
 
 	shl	r10,6
 	add	r10,r9
-	lea	r11,[((K_XX_XX+64))]
+	lea	r14,[((K_XX_XX+64))]
 
 	mov	eax,DWORD[r8]
 	mov	ebx,DWORD[4+r8]
@@ -1297,8 +1296,8 @@
 	xor	edi,edx
 	and	esi,edi
 
-	movdqa	xmm6,XMMWORD[64+r11]
-	movdqa	xmm9,XMMWORD[((-64))+r11]
+	movdqa	xmm6,XMMWORD[64+r14]
+	movdqa	xmm9,XMMWORD[((-64))+r14]
 	movdqu	xmm0,XMMWORD[r9]
 	movdqu	xmm1,XMMWORD[16+r9]
 	movdqu	xmm2,XMMWORD[32+r9]
@@ -1374,7 +1373,7 @@
 	pslld	xmm9,2
 	pxor	xmm4,xmm10
 	xor	edx,ebp
-	movdqa	xmm10,XMMWORD[((-64))+r11]
+	movdqa	xmm10,XMMWORD[((-64))+r14]
 	rol	ecx,5
 	add	ebx,edi
 	and	esi,edx
@@ -1435,7 +1434,7 @@
 	pslld	xmm10,2
 	pxor	xmm5,xmm8
 	xor	ebp,eax
-	movdqa	xmm8,XMMWORD[((-32))+r11]
+	movdqa	xmm8,XMMWORD[((-32))+r14]
 	rol	edx,5
 	add	ecx,edi
 	and	esi,ebp
@@ -1496,7 +1495,7 @@
 	pslld	xmm8,2
 	pxor	xmm6,xmm9
 	xor	eax,ebx
-	movdqa	xmm9,XMMWORD[((-32))+r11]
+	movdqa	xmm9,XMMWORD[((-32))+r14]
 	rol	ebp,5
 	add	edx,edi
 	and	esi,eax
@@ -1557,7 +1556,7 @@
 	pslld	xmm9,2
 	pxor	xmm7,xmm10
 	xor	ebx,ecx
-	movdqa	xmm10,XMMWORD[((-32))+r11]
+	movdqa	xmm10,XMMWORD[((-32))+r14]
 	rol	eax,5
 	add	ebp,edi
 	and	esi,ebx
@@ -1668,7 +1667,7 @@
 	pxor	xmm2,xmm3
 	add	eax,esi
 	xor	edi,edx
-	movdqa	xmm10,XMMWORD[r11]
+	movdqa	xmm10,XMMWORD[r14]
 	ror	ecx,7
 	paddd	xmm9,xmm1
 	add	eax,ebx
@@ -1903,7 +1902,7 @@
 	pxor	xmm7,xmm0
 	rol	ebx,5
 	add	eax,esi
-	movdqa	xmm9,XMMWORD[32+r11]
+	movdqa	xmm9,XMMWORD[32+r14]
 	xor	edi,ecx
 	paddd	xmm8,xmm6
 	xor	ecx,edx
@@ -2194,8 +2193,8 @@
 	add	ecx,edx
 	cmp	r9,r10
 	je	NEAR $L$done_ssse3
-	movdqa	xmm6,XMMWORD[64+r11]
-	movdqa	xmm9,XMMWORD[((-64))+r11]
+	movdqa	xmm6,XMMWORD[64+r14]
+	movdqa	xmm9,XMMWORD[((-64))+r14]
 	movdqu	xmm0,XMMWORD[r9]
 	movdqu	xmm1,XMMWORD[16+r9]
 	movdqu	xmm2,XMMWORD[32+r9]
@@ -2432,19 +2431,18 @@
 	mov	DWORD[8+r8],ecx
 	mov	DWORD[12+r8],edx
 	mov	DWORD[16+r8],ebp
-	movaps	xmm6,XMMWORD[((-40-96))+r14]
-	movaps	xmm7,XMMWORD[((-40-80))+r14]
-	movaps	xmm8,XMMWORD[((-40-64))+r14]
-	movaps	xmm9,XMMWORD[((-40-48))+r14]
-	movaps	xmm10,XMMWORD[((-40-32))+r14]
-	movaps	xmm11,XMMWORD[((-40-16))+r14]
-	lea	rsi,[r14]
-	mov	r14,QWORD[((-40))+rsi]
-	mov	r13,QWORD[((-32))+rsi]
-	mov	r12,QWORD[((-24))+rsi]
-	mov	rbp,QWORD[((-16))+rsi]
-	mov	rbx,QWORD[((-8))+rsi]
-	lea	rsp,[rsi]
+	movaps	xmm6,XMMWORD[((-40-96))+r11]
+	movaps	xmm7,XMMWORD[((-40-80))+r11]
+	movaps	xmm8,XMMWORD[((-40-64))+r11]
+	movaps	xmm9,XMMWORD[((-40-48))+r11]
+	movaps	xmm10,XMMWORD[((-40-32))+r11]
+	movaps	xmm11,XMMWORD[((-40-16))+r11]
+	mov	r14,QWORD[((-40))+r11]
+	mov	r13,QWORD[((-32))+r11]
+	mov	r12,QWORD[((-24))+r11]
+	mov	rbp,QWORD[((-16))+r11]
+	mov	rbx,QWORD[((-8))+r11]
+	lea	rsp,[r11]
 $L$epilogue_ssse3:
 	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
 	mov	rsi,QWORD[16+rsp]
@@ -2463,7 +2461,7 @@
 
 
 _avx_shortcut:
-	mov	rax,rsp
+	mov	r11,rsp
 	push	rbx
 	push	rbp
 	push	r12
@@ -2471,14 +2469,13 @@
 	push	r14
 	lea	rsp,[((-160))+rsp]
 	vzeroupper
-	vmovaps	XMMWORD[(-40-96)+rax],xmm6
-	vmovaps	XMMWORD[(-40-80)+rax],xmm7
-	vmovaps	XMMWORD[(-40-64)+rax],xmm8
-	vmovaps	XMMWORD[(-40-48)+rax],xmm9
-	vmovaps	XMMWORD[(-40-32)+rax],xmm10
-	vmovaps	XMMWORD[(-40-16)+rax],xmm11
+	vmovaps	XMMWORD[(-40-96)+r11],xmm6
+	vmovaps	XMMWORD[(-40-80)+r11],xmm7
+	vmovaps	XMMWORD[(-40-64)+r11],xmm8
+	vmovaps	XMMWORD[(-40-48)+r11],xmm9
+	vmovaps	XMMWORD[(-40-32)+r11],xmm10
+	vmovaps	XMMWORD[(-40-16)+r11],xmm11
 $L$prologue_avx:
-	mov	r14,rax
 	and	rsp,-64
 	mov	r8,rdi
 	mov	r9,rsi
@@ -2486,7 +2483,7 @@
 
 	shl	r10,6
 	add	r10,r9
-	lea	r11,[((K_XX_XX+64))]
+	lea	r14,[((K_XX_XX+64))]
 
 	mov	eax,DWORD[r8]
 	mov	ebx,DWORD[4+r8]
@@ -2498,8 +2495,8 @@
 	xor	edi,edx
 	and	esi,edi
 
-	vmovdqa	xmm6,XMMWORD[64+r11]
-	vmovdqa	xmm11,XMMWORD[((-64))+r11]
+	vmovdqa	xmm6,XMMWORD[64+r14]
+	vmovdqa	xmm11,XMMWORD[((-64))+r14]
 	vmovdqu	xmm0,XMMWORD[r9]
 	vmovdqu	xmm1,XMMWORD[16+r9]
 	vmovdqu	xmm2,XMMWORD[32+r9]
@@ -2624,7 +2621,7 @@
 	vpxor	xmm5,xmm5,xmm10
 	xor	ebp,eax
 	shld	edx,edx,5
-	vmovdqa	xmm11,XMMWORD[((-32))+r11]
+	vmovdqa	xmm11,XMMWORD[((-32))+r14]
 	add	ecx,edi
 	and	esi,ebp
 	xor	ebp,eax
@@ -2837,7 +2834,7 @@
 	add	eax,esi
 	xor	edi,edx
 	vpaddd	xmm9,xmm11,xmm1
-	vmovdqa	xmm11,XMMWORD[r11]
+	vmovdqa	xmm11,XMMWORD[r14]
 	shrd	ecx,ecx,7
 	add	eax,ebx
 	vpxor	xmm2,xmm2,xmm8
@@ -3056,7 +3053,7 @@
 	mov	edi,ebx
 	xor	esi,edx
 	vpaddd	xmm9,xmm11,xmm6
-	vmovdqa	xmm11,XMMWORD[32+r11]
+	vmovdqa	xmm11,XMMWORD[32+r14]
 	shld	ebx,ebx,5
 	add	eax,esi
 	vpxor	xmm7,xmm7,xmm8
@@ -3335,8 +3332,8 @@
 	add	ecx,edx
 	cmp	r9,r10
 	je	NEAR $L$done_avx
-	vmovdqa	xmm6,XMMWORD[64+r11]
-	vmovdqa	xmm11,XMMWORD[((-64))+r11]
+	vmovdqa	xmm6,XMMWORD[64+r14]
+	vmovdqa	xmm11,XMMWORD[((-64))+r14]
 	vmovdqu	xmm0,XMMWORD[r9]
 	vmovdqu	xmm1,XMMWORD[16+r9]
 	vmovdqu	xmm2,XMMWORD[32+r9]
@@ -3572,19 +3569,18 @@
 	mov	DWORD[8+r8],ecx
 	mov	DWORD[12+r8],edx
 	mov	DWORD[16+r8],ebp
-	movaps	xmm6,XMMWORD[((-40-96))+r14]
-	movaps	xmm7,XMMWORD[((-40-80))+r14]
-	movaps	xmm8,XMMWORD[((-40-64))+r14]
-	movaps	xmm9,XMMWORD[((-40-48))+r14]
-	movaps	xmm10,XMMWORD[((-40-32))+r14]
-	movaps	xmm11,XMMWORD[((-40-16))+r14]
-	lea	rsi,[r14]
-	mov	r14,QWORD[((-40))+rsi]
-	mov	r13,QWORD[((-32))+rsi]
-	mov	r12,QWORD[((-24))+rsi]
-	mov	rbp,QWORD[((-16))+rsi]
-	mov	rbx,QWORD[((-8))+rsi]
-	lea	rsp,[rsi]
+	movaps	xmm6,XMMWORD[((-40-96))+r11]
+	movaps	xmm7,XMMWORD[((-40-80))+r11]
+	movaps	xmm8,XMMWORD[((-40-64))+r11]
+	movaps	xmm9,XMMWORD[((-40-48))+r11]
+	movaps	xmm10,XMMWORD[((-40-32))+r11]
+	movaps	xmm11,XMMWORD[((-40-16))+r11]
+	mov	r14,QWORD[((-40))+r11]
+	mov	r13,QWORD[((-32))+r11]
+	mov	r12,QWORD[((-24))+r11]
+	mov	rbp,QWORD[((-16))+r11]
+	mov	rbx,QWORD[((-8))+r11]
+	lea	rsp,[r11]
 $L$epilogue_avx:
 	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
 	mov	rsi,QWORD[16+rsp]
@@ -3677,15 +3673,13 @@
 	cmp	rbx,r10
 	jb	NEAR $L$common_seh_tail
 
-	mov	rax,QWORD[152+r8]
+	mov	rax,QWORD[208+r8]
 
 	mov	r10d,DWORD[4+r11]
 	lea	r10,[r10*1+rsi]
 	cmp	rbx,r10
 	jae	NEAR $L$common_seh_tail
 
-	mov	rax,QWORD[232+r8]
-
 	lea	rsi,[((-40-96))+rax]
 	lea	rdi,[512+r8]
 	mov	ecx,12
diff --git a/win-x86_64/crypto/sha/sha256-x86_64.asm b/win-x86_64/crypto/sha/sha256-x86_64.asm
index efaf9b5..6e3d154 100644
--- a/win-x86_64/crypto/sha/sha256-x86_64.asm
+++ b/win-x86_64/crypto/sha/sha256-x86_64.asm
@@ -30,13 +30,13 @@
 	je	NEAR $L$avx_shortcut
 	test	r10d,512
 	jnz	NEAR $L$ssse3_shortcut
+	mov	rax,rsp
 	push	rbx
 	push	rbp
 	push	r12
 	push	r13
 	push	r14
 	push	r15
-	mov	r11,rsp
 	shl	rdx,4
 	sub	rsp,16*4+4*8
 	lea	rdx,[rdx*4+rsi]
@@ -44,7 +44,7 @@
 	mov	QWORD[((64+0))+rsp],rdi
 	mov	QWORD[((64+8))+rsp],rsi
 	mov	QWORD[((64+16))+rsp],rdx
-	mov	QWORD[((64+24))+rsp],r11
+	mov	QWORD[((64+24))+rsp],rax
 $L$prologue:
 
 	mov	eax,DWORD[rdi]
@@ -1709,13 +1709,13 @@
 	jb	NEAR $L$loop
 
 	mov	rsi,QWORD[((64+24))+rsp]
-	mov	r15,QWORD[rsi]
-	mov	r14,QWORD[8+rsi]
-	mov	r13,QWORD[16+rsi]
-	mov	r12,QWORD[24+rsi]
-	mov	rbp,QWORD[32+rsi]
-	mov	rbx,QWORD[40+rsi]
-	lea	rsp,[48+rsi]
+	mov	r15,QWORD[((-48))+rsi]
+	mov	r14,QWORD[((-40))+rsi]
+	mov	r13,QWORD[((-32))+rsi]
+	mov	r12,QWORD[((-24))+rsi]
+	mov	rbp,QWORD[((-16))+rsi]
+	mov	rbx,QWORD[((-8))+rsi]
+	lea	rsp,[rsi]
 $L$epilogue:
 	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
 	mov	rsi,QWORD[16+rsp]
@@ -1781,13 +1781,13 @@
 
 
 $L$ssse3_shortcut:
+	mov	rax,rsp
 	push	rbx
 	push	rbp
 	push	r12
 	push	r13
 	push	r14
 	push	r15
-	mov	r11,rsp
 	shl	rdx,4
 	sub	rsp,160
 	lea	rdx,[rdx*4+rsi]
@@ -1795,7 +1795,7 @@
 	mov	QWORD[((64+0))+rsp],rdi
 	mov	QWORD[((64+8))+rsp],rsi
 	mov	QWORD[((64+16))+rsp],rdx
-	mov	QWORD[((64+24))+rsp],r11
+	mov	QWORD[((64+24))+rsp],rax
 	movaps	XMMWORD[(64+32)+rsp],xmm6
 	movaps	XMMWORD[(64+48)+rsp],xmm7
 	movaps	XMMWORD[(64+64)+rsp],xmm8
@@ -2870,13 +2870,13 @@
 	movaps	xmm7,XMMWORD[((64+48))+rsp]
 	movaps	xmm8,XMMWORD[((64+64))+rsp]
 	movaps	xmm9,XMMWORD[((64+80))+rsp]
-	mov	r15,QWORD[rsi]
-	mov	r14,QWORD[8+rsi]
-	mov	r13,QWORD[16+rsi]
-	mov	r12,QWORD[24+rsi]
-	mov	rbp,QWORD[32+rsi]
-	mov	rbx,QWORD[40+rsi]
-	lea	rsp,[48+rsi]
+	mov	r15,QWORD[((-48))+rsi]
+	mov	r14,QWORD[((-40))+rsi]
+	mov	r13,QWORD[((-32))+rsi]
+	mov	r12,QWORD[((-24))+rsi]
+	mov	rbp,QWORD[((-16))+rsi]
+	mov	rbx,QWORD[((-8))+rsi]
+	lea	rsp,[rsi]
 $L$epilogue_ssse3:
 	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
 	mov	rsi,QWORD[16+rsp]
@@ -2895,13 +2895,13 @@
 
 
 $L$avx_shortcut:
+	mov	rax,rsp
 	push	rbx
 	push	rbp
 	push	r12
 	push	r13
 	push	r14
 	push	r15
-	mov	r11,rsp
 	shl	rdx,4
 	sub	rsp,160
 	lea	rdx,[rdx*4+rsi]
@@ -2909,7 +2909,7 @@
 	mov	QWORD[((64+0))+rsp],rdi
 	mov	QWORD[((64+8))+rsp],rsi
 	mov	QWORD[((64+16))+rsp],rdx
-	mov	QWORD[((64+24))+rsp],r11
+	mov	QWORD[((64+24))+rsp],rax
 	movaps	XMMWORD[(64+32)+rsp],xmm6
 	movaps	XMMWORD[(64+48)+rsp],xmm7
 	movaps	XMMWORD[(64+64)+rsp],xmm8
@@ -3946,13 +3946,13 @@
 	movaps	xmm7,XMMWORD[((64+48))+rsp]
 	movaps	xmm8,XMMWORD[((64+64))+rsp]
 	movaps	xmm9,XMMWORD[((64+80))+rsp]
-	mov	r15,QWORD[rsi]
-	mov	r14,QWORD[8+rsi]
-	mov	r13,QWORD[16+rsi]
-	mov	r12,QWORD[24+rsi]
-	mov	rbp,QWORD[32+rsi]
-	mov	rbx,QWORD[40+rsi]
-	lea	rsp,[48+rsi]
+	mov	r15,QWORD[((-48))+rsi]
+	mov	r14,QWORD[((-40))+rsi]
+	mov	r13,QWORD[((-32))+rsi]
+	mov	r12,QWORD[((-24))+rsi]
+	mov	rbp,QWORD[((-16))+rsi]
+	mov	rbx,QWORD[((-8))+rsi]
+	lea	rsp,[rsi]
 $L$epilogue_avx:
 	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
 	mov	rsi,QWORD[16+rsp]
@@ -3992,7 +3992,6 @@
 	jae	NEAR $L$in_prologue
 	mov	rsi,rax
 	mov	rax,QWORD[((64+24))+rax]
-	lea	rax,[48+rax]
 
 	mov	rbx,QWORD[((-8))+rax]
 	mov	rbp,QWORD[((-16))+rax]
diff --git a/win-x86_64/crypto/sha/sha512-x86_64.asm b/win-x86_64/crypto/sha/sha512-x86_64.asm
index 71449cd..d0d7a43 100644
--- a/win-x86_64/crypto/sha/sha512-x86_64.asm
+++ b/win-x86_64/crypto/sha/sha512-x86_64.asm
@@ -30,13 +30,13 @@
 	or	r10d,r9d
 	cmp	r10d,1342177792
 	je	NEAR $L$avx_shortcut
+	mov	rax,rsp
 	push	rbx
 	push	rbp
 	push	r12
 	push	r13
 	push	r14
 	push	r15
-	mov	r11,rsp
 	shl	rdx,4
 	sub	rsp,16*8+4*8
 	lea	rdx,[rdx*8+rsi]
@@ -44,7 +44,7 @@
 	mov	QWORD[((128+0))+rsp],rdi
 	mov	QWORD[((128+8))+rsp],rsi
 	mov	QWORD[((128+16))+rsp],rdx
-	mov	QWORD[((128+24))+rsp],r11
+	mov	QWORD[((128+24))+rsp],rax
 $L$prologue:
 
 	mov	rax,QWORD[rdi]
@@ -1709,13 +1709,13 @@
 	jb	NEAR $L$loop
 
 	mov	rsi,QWORD[((128+24))+rsp]
-	mov	r15,QWORD[rsi]
-	mov	r14,QWORD[8+rsi]
-	mov	r13,QWORD[16+rsi]
-	mov	r12,QWORD[24+rsi]
-	mov	rbp,QWORD[32+rsi]
-	mov	rbx,QWORD[40+rsi]
-	lea	rsp,[48+rsi]
+	mov	r15,QWORD[((-48))+rsi]
+	mov	r14,QWORD[((-40))+rsi]
+	mov	r13,QWORD[((-32))+rsi]
+	mov	r12,QWORD[((-24))+rsi]
+	mov	rbp,QWORD[((-16))+rsi]
+	mov	rbx,QWORD[((-8))+rsi]
+	lea	rsp,[rsi]
 $L$epilogue:
 	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
 	mov	rsi,QWORD[16+rsp]
@@ -1825,13 +1825,13 @@
 
 
 $L$xop_shortcut:
+	mov	rax,rsp
 	push	rbx
 	push	rbp
 	push	r12
 	push	r13
 	push	r14
 	push	r15
-	mov	r11,rsp
 	shl	rdx,4
 	sub	rsp,256
 	lea	rdx,[rdx*8+rsi]
@@ -1839,7 +1839,7 @@
 	mov	QWORD[((128+0))+rsp],rdi
 	mov	QWORD[((128+8))+rsp],rsi
 	mov	QWORD[((128+16))+rsp],rdx
-	mov	QWORD[((128+24))+rsp],r11
+	mov	QWORD[((128+24))+rsp],rax
 	movaps	XMMWORD[(128+32)+rsp],xmm6
 	movaps	XMMWORD[(128+48)+rsp],xmm7
 	movaps	XMMWORD[(128+64)+rsp],xmm8
@@ -2906,13 +2906,13 @@
 	movaps	xmm9,XMMWORD[((128+80))+rsp]
 	movaps	xmm10,XMMWORD[((128+96))+rsp]
 	movaps	xmm11,XMMWORD[((128+112))+rsp]
-	mov	r15,QWORD[rsi]
-	mov	r14,QWORD[8+rsi]
-	mov	r13,QWORD[16+rsi]
-	mov	r12,QWORD[24+rsi]
-	mov	rbp,QWORD[32+rsi]
-	mov	rbx,QWORD[40+rsi]
-	lea	rsp,[48+rsi]
+	mov	r15,QWORD[((-48))+rsi]
+	mov	r14,QWORD[((-40))+rsi]
+	mov	r13,QWORD[((-32))+rsi]
+	mov	r12,QWORD[((-24))+rsi]
+	mov	rbp,QWORD[((-16))+rsi]
+	mov	rbx,QWORD[((-8))+rsi]
+	lea	rsp,[rsi]
 $L$epilogue_xop:
 	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
 	mov	rsi,QWORD[16+rsp]
@@ -2931,13 +2931,13 @@
 
 
 $L$avx_shortcut:
+	mov	rax,rsp
 	push	rbx
 	push	rbp
 	push	r12
 	push	r13
 	push	r14
 	push	r15
-	mov	r11,rsp
 	shl	rdx,4
 	sub	rsp,256
 	lea	rdx,[rdx*8+rsi]
@@ -2945,7 +2945,7 @@
 	mov	QWORD[((128+0))+rsp],rdi
 	mov	QWORD[((128+8))+rsp],rsi
 	mov	QWORD[((128+16))+rsp],rdx
-	mov	QWORD[((128+24))+rsp],r11
+	mov	QWORD[((128+24))+rsp],rax
 	movaps	XMMWORD[(128+32)+rsp],xmm6
 	movaps	XMMWORD[(128+48)+rsp],xmm7
 	movaps	XMMWORD[(128+64)+rsp],xmm8
@@ -4076,13 +4076,13 @@
 	movaps	xmm9,XMMWORD[((128+80))+rsp]
 	movaps	xmm10,XMMWORD[((128+96))+rsp]
 	movaps	xmm11,XMMWORD[((128+112))+rsp]
-	mov	r15,QWORD[rsi]
-	mov	r14,QWORD[8+rsi]
-	mov	r13,QWORD[16+rsi]
-	mov	r12,QWORD[24+rsi]
-	mov	rbp,QWORD[32+rsi]
-	mov	rbx,QWORD[40+rsi]
-	lea	rsp,[48+rsi]
+	mov	r15,QWORD[((-48))+rsi]
+	mov	r14,QWORD[((-40))+rsi]
+	mov	r13,QWORD[((-32))+rsi]
+	mov	r12,QWORD[((-24))+rsi]
+	mov	rbp,QWORD[((-16))+rsi]
+	mov	rbx,QWORD[((-8))+rsi]
+	lea	rsp,[rsi]
 $L$epilogue_avx:
 	mov	rdi,QWORD[8+rsp]	;WIN64 epilogue
 	mov	rsi,QWORD[16+rsp]
@@ -4122,7 +4122,6 @@
 	jae	NEAR $L$in_prologue
 	mov	rsi,rax
 	mov	rax,QWORD[((128+24))+rax]
-	lea	rax,[48+rax]
 
 	mov	rbx,QWORD[((-8))+rax]
 	mov	rbp,QWORD[((-16))+rax]